summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChia-I Wu <olvaffe@gmail.com>2009-09-15 14:16:22 +0800
committerChia-I Wu <olvaffe@gmail.com>2009-09-15 14:16:22 +0800
commite2ba90a9cc762cf00a168f0a59d31e7dc52fc42e (patch)
treefe3206d7602ad935296884742980f3c4d30bd867 /src
parent11a4292d4eb515813b82b8d688a318adef66b3e6 (diff)
parentb4b8800315637d9218a81c76f09df7d601710d29 (diff)
Merge commit 'eee/mesa-es' into android
Diffstat (limited to 'src')
-rw-r--r--src/SConscript11
-rw-r--r--src/descrip.mms43
-rw-r--r--src/driclient/include/driclient.h97
-rw-r--r--src/driclient/include/xf86dri.h119
-rw-r--r--src/driclient/src/Makefile19
-rw-r--r--src/driclient/src/XF86dri.c619
-rw-r--r--src/driclient/src/driclient.c310
-rw-r--r--src/driclient/src/xf86dristr.h342
-rw-r--r--src/egl/Makefile9
-rw-r--r--src/egl/drivers/Makefile31
-rw-r--r--src/egl/drivers/demo/Makefile4
-rw-r--r--src/egl/drivers/demo/demo.c147
-rw-r--r--src/egl/drivers/dri/Makefile13
-rw-r--r--src/egl/drivers/dri/egldri.c143
-rw-r--r--src/egl/drivers/dri/egldri.h9
-rw-r--r--src/egl/drivers/glx/Makefile77
-rw-r--r--src/egl/drivers/glx/egl_glx.c882
-rw-r--r--src/egl/drivers/xdri/Makefile78
-rw-r--r--src/egl/drivers/xdri/driinit.c67
-rw-r--r--src/egl/drivers/xdri/driinit.h9
-rw-r--r--src/egl/drivers/xdri/egl_xdri.c784
-rw-r--r--src/egl/drivers/xdri/glxinit.c626
-rw-r--r--src/egl/drivers/xdri/glxinit.h14
-rw-r--r--src/egl/main/Makefile37
-rw-r--r--src/egl/main/README.txt71
-rw-r--r--src/egl/main/eglapi.c867
-rw-r--r--src/egl/main/eglapi.h98
-rw-r--r--src/egl/main/eglclient.c21
-rw-r--r--src/egl/main/eglclient.h12
-rw-r--r--src/egl/main/eglcompiler.h64
-rw-r--r--src/egl/main/eglconfig.c329
-rw-r--r--src/egl/main/eglconfig.h35
-rw-r--r--src/egl/main/eglconfigutil.c260
-rw-r--r--src/egl/main/eglconfigutil.h26
-rw-r--r--src/egl/main/eglcontext.c265
-rw-r--r--src/egl/main/eglcontext.h58
-rw-r--r--src/egl/main/eglcurrent.c342
-rw-r--r--src/egl/main/eglcurrent.h84
-rw-r--r--src/egl/main/egldefines.h45
-rw-r--r--src/egl/main/egldisplay.c366
-rw-r--r--src/egl/main/egldisplay.h251
-rw-r--r--src/egl/main/egldriver.c456
-rw-r--r--src/egl/main/egldriver.h62
-rw-r--r--src/egl/main/eglglobals.c166
-rw-r--r--src/egl/main/eglglobals.h56
-rw-r--r--src/egl/main/eglhash.c347
-rw-r--r--src/egl/main/eglhash.h39
-rw-r--r--src/egl/main/eglimage.c104
-rw-r--r--src/egl/main/eglimage.h93
-rw-r--r--src/egl/main/egllog.c34
-rw-r--r--src/egl/main/eglmisc.c141
-rw-r--r--src/egl/main/eglmisc.h47
-rw-r--r--src/egl/main/eglmode.c37
-rw-r--r--src/egl/main/eglmode.h13
-rw-r--r--src/egl/main/eglmutex.h52
-rw-r--r--src/egl/main/eglscreen.c108
-rw-r--r--src/egl/main/eglscreen.h24
-rw-r--r--src/egl/main/eglstring.c24
-rw-r--r--src/egl/main/eglstring.h9
-rw-r--r--src/egl/main/eglsurface.c250
-rw-r--r--src/egl/main/eglsurface.h79
-rw-r--r--src/egl/main/egltypedefs.h9
-rw-r--r--src/gallium/Makefile12
-rw-r--r--src/gallium/Makefile.template66
-rw-r--r--src/gallium/README.portability109
-rw-r--r--src/gallium/SConscript37
-rw-r--r--src/gallium/auxiliary/Makefile12
-rw-r--r--src/gallium/auxiliary/cso_cache/Makefile11
-rw-r--r--src/gallium/auxiliary/cso_cache/SConscript11
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_cache.c410
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_cache.h176
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.c865
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.h145
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_hash.c439
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_hash.h129
-rw-r--r--src/gallium/auxiliary/draw/Makefile46
-rw-r--r--src/gallium/auxiliary/draw/SConscript46
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c430
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h182
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe.c319
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe.h126
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_aaline.c921
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_aapoint.c884
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_clip.c516
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_cull.c148
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_flatshade.c282
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_offset.c185
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_pstipple.c777
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_stipple.c251
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_twoside.c200
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_unfilled.c204
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_util.c137
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_validate.c339
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_vbuf.c492
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_wide_line.c181
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_wide_point.c333
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h319
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c324
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h233
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_decompose.h182
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_elts.c89
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_emit.c313
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch.c234
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c437
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c429
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c395
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_post_vs.c233
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_util.c77
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray.c193
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray_tmp.h238
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h91
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c516
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h214
-rw-r--r--src/gallium/auxiliary/draw/draw_vbuf.h129
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex.c129
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex.h162
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.c254
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.h224
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_aos.c2274
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_aos.h253
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_aos_io.c462
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_aos_machine.c324
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_exec.c208
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_llvm.c161
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_ppc.c245
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_sse.c217
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_varient.c322
-rw-r--r--src/gallium/auxiliary/gallivm/Makefile92
-rw-r--r--src/gallium/auxiliary/gallivm/SConscript16
-rw-r--r--src/gallium/auxiliary/gallivm/gallivm.cpp332
-rw-r--r--src/gallium/auxiliary/gallivm/gallivm.h118
-rw-r--r--src/gallium/auxiliary/gallivm/gallivm_builtins.cpp140
-rw-r--r--src/gallium/auxiliary/gallivm/gallivm_cpu.cpp243
-rw-r--r--src/gallium/auxiliary/gallivm/gallivm_p.h110
-rw-r--r--src/gallium/auxiliary/gallivm/instructions.cpp1193
-rw-r--r--src/gallium/auxiliary/gallivm/instructions.h175
-rw-r--r--src/gallium/auxiliary/gallivm/instructionssoa.cpp525
-rw-r--r--src/gallium/auxiliary/gallivm/instructionssoa.h116
-rw-r--r--src/gallium/auxiliary/gallivm/llvm_builtins.c114
-rw-r--r--src/gallium/auxiliary/gallivm/loweringpass.cpp17
-rw-r--r--src/gallium/auxiliary/gallivm/loweringpass.h15
-rw-r--r--src/gallium/auxiliary/gallivm/soabuiltins.c210
-rw-r--r--src/gallium/auxiliary/gallivm/storage.cpp364
-rw-r--r--src/gallium/auxiliary/gallivm/storage.h133
-rw-r--r--src/gallium/auxiliary/gallivm/storagesoa.cpp438
-rw-r--r--src/gallium/auxiliary/gallivm/storagesoa.h107
-rw-r--r--src/gallium/auxiliary/gallivm/tgsitollvm.cpp1136
-rw-r--r--src/gallium/auxiliary/gallivm/tgsitollvm.h20
-rw-r--r--src/gallium/auxiliary/indices/Makefile16
-rw-r--r--src/gallium/auxiliary/indices/SConscript28
-rw-r--r--src/gallium/auxiliary/indices/u_indices.c253
-rw-r--r--src/gallium/auxiliary/indices/u_indices.h106
-rw-r--r--src/gallium/auxiliary/indices/u_indices_gen.c5129
-rw-r--r--src/gallium/auxiliary/indices/u_indices_gen.py319
-rw-r--r--src/gallium/auxiliary/indices/u_indices_priv.h43
-rw-r--r--src/gallium/auxiliary/indices/u_unfilled_gen.c992
-rw-r--r--src/gallium/auxiliary/indices/u_unfilled_gen.py246
-rw-r--r--src/gallium/auxiliary/indices/u_unfilled_indices.c186
-rw-r--r--src/gallium/auxiliary/pipebuffer/Makefile19
-rw-r--r--src/gallium/auxiliary/pipebuffer/SConscript19
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_buffer.h286
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c597
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h142
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c188
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr.h214
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c120
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c385
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c494
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c152
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c318
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_ondemand.c305
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c321
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c584
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_validate.c193
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_validate.h97
-rw-r--r--src/gallium/auxiliary/rbug/Makefile14
-rw-r--r--src/gallium/auxiliary/rbug/README21
-rw-r--r--src/gallium/auxiliary/rbug/SConscript14
-rw-r--r--src/gallium/auxiliary/rbug/rbug.h33
-rw-r--r--src/gallium/auxiliary/rbug/rbug_connection.c167
-rw-r--r--src/gallium/auxiliary/rbug/rbug_connection.h45
-rw-r--r--src/gallium/auxiliary/rbug/rbug_context.c759
-rw-r--r--src/gallium/auxiliary/rbug/rbug_context.h212
-rw-r--r--src/gallium/auxiliary/rbug/rbug_core.c359
-rw-r--r--src/gallium/auxiliary/rbug/rbug_core.h105
-rw-r--r--src/gallium/auxiliary/rbug/rbug_demarshal.c93
-rw-r--r--src/gallium/auxiliary/rbug/rbug_internal.h100
-rw-r--r--src/gallium/auxiliary/rbug/rbug_proto.h94
-rw-r--r--src/gallium/auxiliary/rbug/rbug_shader.c468
-rw-r--r--src/gallium/auxiliary/rbug/rbug_shader.h142
-rw-r--r--src/gallium/auxiliary/rbug/rbug_texture.c631
-rw-r--r--src/gallium/auxiliary/rbug/rbug_texture.h206
-rw-r--r--src/gallium/auxiliary/rtasm/Makefile13
-rw-r--r--src/gallium/auxiliary/rtasm/SConscript13
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_cpu.c67
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_cpu.h42
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_execmem.c141
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_execmem.h (renamed from src/mesa/shader/prog_debug.h)35
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_ppc.c1077
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_ppc.h342
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c1067
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h433
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_x86sse.c1757
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_x86sse.h320
-rw-r--r--src/gallium/auxiliary/sct/Makefile9
-rw-r--r--src/gallium/auxiliary/sct/SConscript9
-rw-r--r--src/gallium/auxiliary/sct/sct.c453
-rw-r--r--src/gallium/auxiliary/sct/sct.h123
-rw-r--r--src/gallium/auxiliary/sct/usage.c61
-rw-r--r--src/gallium/auxiliary/tgsi/Makefile22
-rw-r--r--src/gallium/auxiliary/tgsi/SConscript23
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt1131
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_build.c1368
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_build.h339
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump.c617
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump.h70
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump_c.c720
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump_c.h49
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c3311
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.h327
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_info.c181
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_info.h60
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_iterate.c85
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_iterate.h76
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h172
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_parse.c352
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_parse.h149
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ppc.c1375
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ppc.h51
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sanity.c385
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sanity.h49
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_scan.c256
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_scan.h75
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sse2.c2985
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sse2.h77
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_text.c1157
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_text.h47
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_transform.c227
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_transform.h92
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.c938
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.h590
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_util.c299
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_util.h100
-rw-r--r--src/gallium/auxiliary/translate/Makefile12
-rw-r--r--src/gallium/auxiliary/translate/SConscript12
-rw-r--r--src/gallium/auxiliary/translate/translate.c50
-rw-r--r--src/gallium/auxiliary/translate/translate.h127
-rw-r--r--src/gallium/auxiliary/translate/translate_cache.c102
-rw-r--r--src/gallium/auxiliary/translate/translate_cache.h54
-rw-r--r--src/gallium/auxiliary/translate/translate_generic.c700
-rw-r--r--src/gallium/auxiliary/translate/translate_sse.c706
-rw-r--r--src/gallium/auxiliary/util/.gitignore2
-rw-r--r--src/gallium/auxiliary/util/Makefile44
-rw-r--r--src/gallium/auxiliary/util/SConscript58
-rw-r--r--src/gallium/auxiliary/util/u_bitmask.c320
-rw-r--r--src/gallium/auxiliary/util/u_bitmask.h114
-rw-r--r--src/gallium/auxiliary/util/u_blit.c600
-rw-r--r--src/gallium/auxiliary/util/u_blit.h93
-rw-r--r--src/gallium/auxiliary/util/u_cache.c217
-rw-r--r--src/gallium/auxiliary/util/u_cache.h87
-rw-r--r--src/gallium/auxiliary/util/u_clear.h60
-rw-r--r--src/gallium/auxiliary/util/u_cpu_detect.c506
-rw-r--r--src/gallium/auxiliary/util/u_cpu_detect.h78
-rw-r--r--src/gallium/auxiliary/util/u_debug.c823
-rw-r--r--src/gallium/auxiliary/util/u_debug.h384
-rw-r--r--src/gallium/auxiliary/util/u_debug_dump.c189
-rw-r--r--src/gallium/auxiliary/util/u_debug_dump.h65
-rw-r--r--src/gallium/auxiliary/util/u_debug_memory.c324
-rw-r--r--src/gallium/auxiliary/util/u_debug_profile.c320
-rw-r--r--src/gallium/auxiliary/util/u_debug_stack.c107
-rw-r--r--src/gallium/auxiliary/util/u_debug_stack.h65
-rw-r--r--src/gallium/auxiliary/util/u_debug_symbol.c250
-rw-r--r--src/gallium/auxiliary/util/u_debug_symbol.h53
-rw-r--r--src/gallium/auxiliary/util/u_double_list.h102
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.c134
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.h54
-rw-r--r--src/gallium/auxiliary/util/u_fifo.h94
-rw-r--r--src/gallium/auxiliary/util/u_format.c46
-rw-r--r--src/gallium/auxiliary/util/u_format.csv99
-rw-r--r--src/gallium/auxiliary/util/u_format.h138
-rw-r--r--src/gallium/auxiliary/util/u_format_access.py498
-rwxr-xr-xsrc/gallium/auxiliary/util/u_format_parse.py141
-rwxr-xr-xsrc/gallium/auxiliary/util/u_format_table.py144
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c1613
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.h70
-rw-r--r--src/gallium/auxiliary/util/u_handle_table.c298
-rw-r--r--src/gallium/auxiliary/util/u_handle_table.h116
-rw-r--r--src/gallium/auxiliary/util/u_hash.c121
-rw-r--r--src/gallium/auxiliary/util/u_hash.h55
-rw-r--r--src/gallium/auxiliary/util/u_hash_table.c292
-rw-r--r--src/gallium/auxiliary/util/u_hash_table.h95
-rw-r--r--src/gallium/auxiliary/util/u_keymap.c319
-rw-r--r--src/gallium/auxiliary/util/u_keymap.h68
-rw-r--r--src/gallium/auxiliary/util/u_linear.c101
-rw-r--r--src/gallium/auxiliary/util/u_linear.h92
-rw-r--r--src/gallium/auxiliary/util/u_math.c73
-rw-r--r--src/gallium/auxiliary/util/u_math.h516
-rw-r--r--src/gallium/auxiliary/util/u_memory.h242
-rw-r--r--src/gallium/auxiliary/util/u_mm.c289
-rw-r--r--src/gallium/auxiliary/util/u_mm.h91
-rw-r--r--src/gallium/auxiliary/util/u_network.c188
-rw-r--r--src/gallium/auxiliary/util/u_network.h24
-rw-r--r--src/gallium/auxiliary/util/u_pack_color.h502
-rw-r--r--src/gallium/auxiliary/util/u_pointer.h107
-rw-r--r--src/gallium/auxiliary/util/u_prim.h138
-rw-r--r--src/gallium/auxiliary/util/u_rect.c301
-rw-r--r--src/gallium/auxiliary/util/u_rect.h72
-rw-r--r--src/gallium/auxiliary/util/u_simple_list.h197
-rw-r--r--src/gallium/auxiliary/util/u_simple_screen.c153
-rw-r--r--src/gallium/auxiliary/util/u_simple_screen.h47
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.c153
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.h69
-rw-r--r--src/gallium/auxiliary/util/u_snprintf.c1497
-rw-r--r--src/gallium/auxiliary/util/u_sse.h77
-rw-r--r--src/gallium/auxiliary/util/u_stream.h61
-rw-r--r--src/gallium/auxiliary/util/u_stream_stdc.c106
-rw-r--r--src/gallium/auxiliary/util/u_stream_wd.c224
-rw-r--r--src/gallium/auxiliary/util/u_string.h220
-rw-r--r--src/gallium/auxiliary/util/u_surface.c113
-rw-r--r--src/gallium/auxiliary/util/u_surface.h69
-rw-r--r--src/gallium/auxiliary/util/u_tile.c1526
-rw-r--r--src/gallium/auxiliary/util/u_tile.h101
-rw-r--r--src/gallium/auxiliary/util/u_time.c225
-rw-r--r--src/gallium/auxiliary/util/u_time.h109
-rw-r--r--src/gallium/auxiliary/util/u_timed_winsys.c318
-rw-r--r--src/gallium/auxiliary/util/u_timed_winsys.h41
-rw-r--r--src/gallium/auxiliary/util/u_upload_mgr.c230
-rw-r--r--src/gallium/auxiliary/util/u_upload_mgr.h75
-rw-r--r--src/gallium/drivers/Makefile12
-rw-r--r--src/gallium/drivers/cell/Makefile12
-rw-r--r--src/gallium/drivers/cell/common.h376
-rw-r--r--src/gallium/drivers/cell/ppu/Makefile86
-rw-r--r--src/gallium/drivers/cell/ppu/cell_batch.c260
-rw-r--r--src/gallium/drivers/cell/ppu/cell_batch.h54
-rw-r--r--src/gallium/drivers/cell/ppu/cell_clear.c92
-rw-r--r--src/gallium/drivers/cell/ppu/cell_clear.h41
-rw-r--r--src/gallium/drivers/cell/ppu/cell_context.c208
-rw-r--r--src/gallium/drivers/cell/ppu/cell_context.h202
-rw-r--r--src/gallium/drivers/cell/ppu/cell_draw_arrays.c191
-rw-r--r--src/gallium/drivers/cell/ppu/cell_draw_arrays.h36
-rw-r--r--src/gallium/drivers/cell/ppu/cell_fence.c164
-rw-r--r--src/gallium/drivers/cell/ppu/cell_fence.h57
-rw-r--r--src/gallium/drivers/cell/ppu/cell_flush.c112
-rw-r--r--src/gallium/drivers/cell/ppu/cell_flush.h45
-rw-r--r--src/gallium/drivers/cell/ppu/cell_gen_fp.c2046
-rw-r--r--src/gallium/drivers/cell/ppu/cell_gen_fp.h42
-rw-r--r--src/gallium/drivers/cell/ppu/cell_gen_fragment.c2181
-rw-r--r--src/gallium/drivers/cell/ppu/cell_gen_fragment.h38
-rw-r--r--src/gallium/drivers/cell/ppu/cell_pipe_state.c407
-rw-r--r--src/gallium/drivers/cell/ppu/cell_pipe_state.h39
-rw-r--r--src/gallium/drivers/cell/ppu/cell_render.c211
-rw-r--r--src/gallium/drivers/cell/ppu/cell_render.h39
-rw-r--r--src/gallium/drivers/cell/ppu/cell_screen.c178
-rw-r--r--src/gallium/drivers/cell/ppu/cell_screen.h41
-rw-r--r--src/gallium/drivers/cell/ppu/cell_spu.c219
-rw-r--r--src/gallium/drivers/cell/ppu/cell_spu.h79
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state.h65
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_derived.c170
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_emit.c344
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_emit.h36
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_per_fragment.c1430
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_per_fragment.h39
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_shader.c217
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_vertex.c79
-rw-r--r--src/gallium/drivers/cell/ppu/cell_surface.c50
-rw-r--r--src/gallium/drivers/cell/ppu/cell_surface.h42
-rw-r--r--src/gallium/drivers/cell/ppu/cell_texture.c497
-rw-r--r--src/gallium/drivers/cell/ppu/cell_texture.h86
-rw-r--r--src/gallium/drivers/cell/ppu/cell_vbuf.c332
-rw-r--r--src/gallium/drivers/cell/ppu/cell_vbuf.h38
-rw-r--r--src/gallium/drivers/cell/ppu/cell_vertex_fetch.c346
-rw-r--r--src/gallium/drivers/cell/ppu/cell_vertex_shader.c146
-rw-r--r--src/gallium/drivers/cell/ppu/cell_winsys.h50
-rw-r--r--src/gallium/drivers/cell/spu/.gitignore1
-rw-r--r--src/gallium/drivers/cell/spu/Makefile83
-rw-r--r--src/gallium/drivers/cell/spu/spu_colorpack.h145
-rw-r--r--src/gallium/drivers/cell/spu/spu_command.c815
-rw-r--r--src/gallium/drivers/cell/spu/spu_command.h35
-rw-r--r--src/gallium/drivers/cell/spu/spu_dcache.c145
-rw-r--r--src/gallium/drivers/cell/spu/spu_dcache.h37
-rw-r--r--src/gallium/drivers/cell/spu/spu_exec.c1907
-rw-r--r--src/gallium/drivers/cell/spu/spu_exec.h172
-rw-r--r--src/gallium/drivers/cell/spu/spu_funcs.c173
-rw-r--r--src/gallium/drivers/cell/spu/spu_funcs.h35
-rw-r--r--src/gallium/drivers/cell/spu/spu_main.c117
-rw-r--r--src/gallium/drivers/cell/spu/spu_main.h254
-rw-r--r--src/gallium/drivers/cell/spu/spu_per_fragment_op.c631
-rw-r--r--src/gallium/drivers/cell/spu/spu_per_fragment_op.h44
-rw-r--r--src/gallium/drivers/cell/spu/spu_render.c356
-rw-r--r--src/gallium/drivers/cell/spu/spu_render.h38
-rw-r--r--src/gallium/drivers/cell/spu/spu_shuffle.h186
-rw-r--r--src/gallium/drivers/cell/spu/spu_texture.c641
-rw-r--r--src/gallium/drivers/cell/spu/spu_texture.h67
-rw-r--r--src/gallium/drivers/cell/spu/spu_tile.c126
-rw-r--r--src/gallium/drivers/cell/spu/spu_tile.h75
-rw-r--r--src/gallium/drivers/cell/spu/spu_tri.c843
-rw-r--r--src/gallium/drivers/cell/spu/spu_tri.h37
-rw-r--r--src/gallium/drivers/cell/spu/spu_util.c167
-rw-r--r--src/gallium/drivers/cell/spu/spu_vertex_fetch.c145
-rw-r--r--src/gallium/drivers/cell/spu/spu_vertex_shader.c244
-rw-r--r--src/gallium/drivers/cell/spu/spu_vertex_shader.h66
-rw-r--r--src/gallium/drivers/failover/Makefile11
-rw-r--r--src/gallium/drivers/failover/SConscript13
-rw-r--r--src/gallium/drivers/failover/fo_context.c182
-rw-r--r--src/gallium/drivers/failover/fo_context.h125
-rw-r--r--src/gallium/drivers/failover/fo_state.c481
-rw-r--r--src/gallium/drivers/failover/fo_state_emit.c117
-rw-r--r--src/gallium/drivers/failover/fo_winsys.h45
-rw-r--r--src/gallium/drivers/i915simple/Makefile28
-rw-r--r--src/gallium/drivers/i915simple/SConscript30
-rw-r--r--src/gallium/drivers/i915simple/i915_batch.h47
-rw-r--r--src/gallium/drivers/i915simple/i915_blit.c151
-rw-r--r--src/gallium/drivers/i915simple/i915_blit.h55
-rw-r--r--src/gallium/drivers/i915simple/i915_buffer.c136
-rw-r--r--src/gallium/drivers/i915simple/i915_buffer.h31
-rw-r--r--src/gallium/drivers/i915simple/i915_clear.c48
-rw-r--r--src/gallium/drivers/i915simple/i915_context.c237
-rw-r--r--src/gallium/drivers/i915simple/i915_context.h350
-rw-r--r--src/gallium/drivers/i915simple/i915_debug.c898
-rw-r--r--src/gallium/drivers/i915simple/i915_debug.h114
-rw-r--r--src/gallium/drivers/i915simple/i915_debug_fp.c363
-rw-r--r--src/gallium/drivers/i915simple/i915_flush.c86
-rw-r--r--src/gallium/drivers/i915simple/i915_fpc.h207
-rw-r--r--src/gallium/drivers/i915simple/i915_fpc_emit.c375
-rw-r--r--src/gallium/drivers/i915simple/i915_fpc_translate.c1202
-rw-r--r--src/gallium/drivers/i915simple/i915_prim_emit.c219
-rw-r--r--src/gallium/drivers/i915simple/i915_prim_vbuf.c616
-rw-r--r--src/gallium/drivers/i915simple/i915_reg.h978
-rw-r--r--src/gallium/drivers/i915simple/i915_screen.c300
-rw-r--r--src/gallium/drivers/i915simple/i915_screen.h80
-rw-r--r--src/gallium/drivers/i915simple/i915_state.c788
-rw-r--r--src/gallium/drivers/i915simple/i915_state.h50
-rw-r--r--src/gallium/drivers/i915simple/i915_state_derived.c183
-rw-r--r--src/gallium/drivers/i915simple/i915_state_dynamic.c310
-rw-r--r--src/gallium/drivers/i915simple/i915_state_emit.c402
-rw-r--r--src/gallium/drivers/i915simple/i915_state_immediate.c225
-rw-r--r--src/gallium/drivers/i915simple/i915_state_inlines.h230
-rw-r--r--src/gallium/drivers/i915simple/i915_state_sampler.c299
-rw-r--r--src/gallium/drivers/i915simple/i915_surface.c94
-rw-r--r--src/gallium/drivers/i915simple/i915_texture.c911
-rw-r--r--src/gallium/drivers/i915simple/i915_texture.h36
-rw-r--r--src/gallium/drivers/i915simple/intel_batchbuffer.h87
-rw-r--r--src/gallium/drivers/i915simple/intel_winsys.h230
-rw-r--r--src/gallium/drivers/i965simple/Makefile52
-rw-r--r--src/gallium/drivers/i965simple/SConscript54
-rw-r--r--src/gallium/drivers/i965simple/brw_batch.h59
-rw-r--r--src/gallium/drivers/i965simple/brw_blit.c218
-rw-r--r--src/gallium/drivers/i965simple/brw_blit.h33
-rw-r--r--src/gallium/drivers/i965simple/brw_cc.c269
-rw-r--r--src/gallium/drivers/i965simple/brw_clip.c206
-rw-r--r--src/gallium/drivers/i965simple/brw_clip.h170
-rw-r--r--src/gallium/drivers/i965simple/brw_clip_line.c245
-rw-r--r--src/gallium/drivers/i965simple/brw_clip_point.c47
-rw-r--r--src/gallium/drivers/i965simple/brw_clip_state.c93
-rw-r--r--src/gallium/drivers/i965simple/brw_clip_tri.c566
-rw-r--r--src/gallium/drivers/i965simple/brw_clip_unfilled.c477
-rw-r--r--src/gallium/drivers/i965simple/brw_clip_util.c351
-rw-r--r--src/gallium/drivers/i965simple/brw_context.c139
-rw-r--r--src/gallium/drivers/i965simple/brw_context.h684
-rw-r--r--src/gallium/drivers/i965simple/brw_curbe.c369
-rw-r--r--src/gallium/drivers/i965simple/brw_defines.h870
-rw-r--r--src/gallium/drivers/i965simple/brw_draw.c226
-rw-r--r--src/gallium/drivers/i965simple/brw_draw.h55
-rw-r--r--src/gallium/drivers/i965simple/brw_draw_upload.c300
-rw-r--r--src/gallium/drivers/i965simple/brw_eu.c130
-rw-r--r--src/gallium/drivers/i965simple/brw_eu.h888
-rw-r--r--src/gallium/drivers/i965simple/brw_eu_debug.c90
-rw-r--r--src/gallium/drivers/i965simple/brw_eu_emit.c1080
-rw-r--r--src/gallium/drivers/i965simple/brw_eu_util.c126
-rw-r--r--src/gallium/drivers/i965simple/brw_flush.c73
-rw-r--r--src/gallium/drivers/i965simple/brw_gs.c196
-rw-r--r--src/gallium/drivers/i965simple/brw_gs.h75
-rw-r--r--src/gallium/drivers/i965simple/brw_gs_emit.c148
-rw-r--r--src/gallium/drivers/i965simple/brw_gs_state.c90
-rw-r--r--src/gallium/drivers/i965simple/brw_misc_state.c488
-rw-r--r--src/gallium/drivers/i965simple/brw_reg.h76
-rw-r--r--src/gallium/drivers/i965simple/brw_screen.c246
-rw-r--r--src/gallium/drivers/i965simple/brw_screen.h68
-rw-r--r--src/gallium/drivers/i965simple/brw_sf.c351
-rw-r--r--src/gallium/drivers/i965simple/brw_sf.h122
-rw-r--r--src/gallium/drivers/i965simple/brw_sf_emit.c382
-rw-r--r--src/gallium/drivers/i965simple/brw_sf_state.c181
-rw-r--r--src/gallium/drivers/i965simple/brw_shader_info.c48
-rw-r--r--src/gallium/drivers/i965simple/brw_state.c469
-rw-r--r--src/gallium/drivers/i965simple/brw_state.h151
-rw-r--r--src/gallium/drivers/i965simple/brw_state_batch.c113
-rw-r--r--src/gallium/drivers/i965simple/brw_state_cache.c443
-rw-r--r--src/gallium/drivers/i965simple/brw_state_pool.c138
-rw-r--r--src/gallium/drivers/i965simple/brw_state_upload.c202
-rw-r--r--src/gallium/drivers/i965simple/brw_structs.h1348
-rw-r--r--src/gallium/drivers/i965simple/brw_surface.c126
-rw-r--r--src/gallium/drivers/i965simple/brw_tex_layout.c380
-rw-r--r--src/gallium/drivers/i965simple/brw_tex_layout.h44
-rw-r--r--src/gallium/drivers/i965simple/brw_urb.c186
-rw-r--r--src/gallium/drivers/i965simple/brw_util.c104
-rw-r--r--src/gallium/drivers/i965simple/brw_util.h43
-rw-r--r--src/gallium/drivers/i965simple/brw_vs.c120
-rw-r--r--src/gallium/drivers/i965simple/brw_vs.h82
-rw-r--r--src/gallium/drivers/i965simple/brw_vs_emit.c1330
-rw-r--r--src/gallium/drivers/i965simple/brw_vs_state.c103
-rw-r--r--src/gallium/drivers/i965simple/brw_winsys.h209
-rw-r--r--src/gallium/drivers/i965simple/brw_wm.c209
-rw-r--r--src/gallium/drivers/i965simple/brw_wm.h142
-rw-r--r--src/gallium/drivers/i965simple/brw_wm_decl.c392
-rw-r--r--src/gallium/drivers/i965simple/brw_wm_glsl.c1076
-rw-r--r--src/gallium/drivers/i965simple/brw_wm_iz.c214
-rw-r--r--src/gallium/drivers/i965simple/brw_wm_sampler_state.c275
-rw-r--r--src/gallium/drivers/i965simple/brw_wm_state.c195
-rw-r--r--src/gallium/drivers/i965simple/brw_wm_surface_state.c305
-rw-r--r--src/gallium/drivers/identity/Makefile12
-rw-r--r--src/gallium/drivers/identity/SConscript13
-rw-r--r--src/gallium/drivers/identity/id_context.c719
-rw-r--r--src/gallium/drivers/identity/id_context.h48
-rw-r--r--src/gallium/drivers/identity/id_drm.c173
-rw-r--r--src/gallium/drivers/identity/id_drm.h35
-rw-r--r--src/gallium/drivers/identity/id_objects.c182
-rw-r--r--src/gallium/drivers/identity/id_objects.h169
-rw-r--r--src/gallium/drivers/identity/id_public.h40
-rw-r--r--src/gallium/drivers/identity/id_screen.c483
-rw-r--r--src/gallium/drivers/identity/id_screen.h48
-rw-r--r--src/gallium/drivers/llvmpipe/Makefile55
-rw-r--r--src/gallium/drivers/llvmpipe/README149
-rw-r--r--src/gallium/drivers/llvmpipe/SConscript84
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_alpha.c64
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_alpha.h54
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_arit.c1082
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_arit.h175
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_blend.h107
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c356
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_blend_logicop.c108
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c298
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_const.c369
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_const.h108
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_conv.c702
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_conv.h73
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_debug.c125
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_debug.h64
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_depth.c216
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_depth.h63
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_flow.c493
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_flow.h129
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_format.h119
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_format_aos.c303
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_format_soa.c208
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_interp.c377
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_interp.h99
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_intr.c192
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_intr.h102
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_logic.c394
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_logic.h72
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_sample.h135
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_sample_soa.c411
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_struct.c72
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_struct.h75
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_swizzle.c238
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_swizzle.h91
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_tgsi.h84
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c1339
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_type.c181
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_type.h178
-rw-r--r--src/gallium/drivers/llvmpipe/lp_buffer.c150
-rw-r--r--src/gallium/drivers/llvmpipe/lp_buffer.h55
-rw-r--r--src/gallium/drivers/llvmpipe/lp_clear.c81
-rw-r--r--src/gallium/drivers/llvmpipe/lp_clear.h43
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.c295
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h155
-rw-r--r--src/gallium/drivers/llvmpipe/lp_draw_arrays.c192
-rw-r--r--src/gallium/drivers/llvmpipe/lp_flush.c98
-rw-r--r--src/gallium/drivers/llvmpipe/lp_flush.h37
-rw-r--r--src/gallium/drivers/llvmpipe/lp_jit.c173
-rw-r--r--src/gallium/drivers/llvmpipe/lp_jit.h135
-rw-r--r--src/gallium/drivers/llvmpipe/lp_prim_setup.c190
-rw-r--r--src/gallium/drivers/llvmpipe/lp_prim_setup.h85
-rw-r--r--src/gallium/drivers/llvmpipe/lp_prim_vbuf.c607
-rw-r--r--src/gallium/drivers/llvmpipe/lp_prim_vbuf.h38
-rw-r--r--src/gallium/drivers/llvmpipe/lp_quad.h114
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.c111
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.h39
-rw-r--r--src/gallium/drivers/llvmpipe/lp_screen.c243
-rw-r--r--src/gallium/drivers/llvmpipe/lp_screen.h79
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c1483
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.h53
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state.h230
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_blend.c114
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_clip.c79
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c260
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c762
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_rasterizer.c62
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_sampler.c127
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_surface.c106
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_vertex.c73
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_vs.c96
-rw-r--r--src/gallium/drivers/llvmpipe/lp_surface.c50
-rw-r--r--src/gallium/drivers/llvmpipe/lp_surface.h42
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test.h128
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_blend.c881
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_conv.c427
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_format.c272
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_main.c384
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tex_cache.c304
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tex_cache.h151
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tex_sample.h101
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tex_sample_c.c1713
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c196
-rw-r--r--src/gallium/drivers/llvmpipe/lp_texture.c429
-rw-r--r--src/gallium/drivers/llvmpipe/lp_texture.h90
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tile_cache.c299
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tile_cache.h106
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tile_soa.c931
-rw-r--r--src/gallium/drivers/llvmpipe/lp_tile_soa.h81
-rw-r--r--src/gallium/drivers/llvmpipe/lp_winsys.h128
-rwxr-xr-xsrc/gallium/drivers/llvmpipe/sp2lp.sh34
-rw-r--r--src/gallium/drivers/nouveau/Makefile8
-rw-r--r--src/gallium/drivers/nouveau/nouveau_gldefs.h196
-rw-r--r--src/gallium/drivers/nouveau/nouveau_push.h93
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.c243
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.h36
-rw-r--r--src/gallium/drivers/nouveau/nouveau_stateobj.h159
-rw-r--r--src/gallium/drivers/nouveau/nouveau_util.h91
-rw-r--r--src/gallium/drivers/nouveau/nouveau_winsys.h62
-rw-r--r--src/gallium/drivers/nv04/Makefile21
-rw-r--r--src/gallium/drivers/nv04/nv04_clear.c12
-rw-r--r--src/gallium/drivers/nv04/nv04_context.c134
-rw-r--r--src/gallium/drivers/nv04/nv04_context.h151
-rw-r--r--src/gallium/drivers/nv04/nv04_fragprog.c21
-rw-r--r--src/gallium/drivers/nv04/nv04_fragtex.c73
-rw-r--r--src/gallium/drivers/nv04/nv04_miptree.c153
-rw-r--r--src/gallium/drivers/nv04/nv04_prim_vbuf.c321
-rw-r--r--src/gallium/drivers/nv04/nv04_screen.c212
-rw-r--r--src/gallium/drivers/nv04/nv04_screen.h30
-rw-r--r--src/gallium/drivers/nv04/nv04_state.c459
-rw-r--r--src/gallium/drivers/nv04/nv04_state.h71
-rw-r--r--src/gallium/drivers/nv04/nv04_state_emit.c226
-rw-r--r--src/gallium/drivers/nv04/nv04_surface.c63
-rw-r--r--src/gallium/drivers/nv04/nv04_surface_2d.c558
-rw-r--r--src/gallium/drivers/nv04/nv04_surface_2d.h33
-rw-r--r--src/gallium/drivers/nv04/nv04_transfer.c195
-rw-r--r--src/gallium/drivers/nv04/nv04_vbo.c80
-rw-r--r--src/gallium/drivers/nv10/Makefile20
-rw-r--r--src/gallium/drivers/nv10/nv10_clear.c14
-rw-r--r--src/gallium/drivers/nv10/nv10_context.c322
-rw-r--r--src/gallium/drivers/nv10/nv10_context.h154
-rw-r--r--src/gallium/drivers/nv10/nv10_fragprog.c21
-rw-r--r--src/gallium/drivers/nv10/nv10_fragtex.c124
-rw-r--r--src/gallium/drivers/nv10/nv10_miptree.c167
-rw-r--r--src/gallium/drivers/nv10/nv10_prim_vbuf.c261
-rw-r--r--src/gallium/drivers/nv10/nv10_screen.c198
-rw-r--r--src/gallium/drivers/nv10/nv10_screen.h28
-rw-r--r--src/gallium/drivers/nv10/nv10_state.c590
-rw-r--r--src/gallium/drivers/nv10/nv10_state.h139
-rw-r--r--src/gallium/drivers/nv10/nv10_state_emit.c306
-rw-r--r--src/gallium/drivers/nv10/nv10_surface.c63
-rw-r--r--src/gallium/drivers/nv10/nv10_transfer.c195
-rw-r--r--src/gallium/drivers/nv10/nv10_vbo.c78
-rw-r--r--src/gallium/drivers/nv20/Makefile21
-rw-r--r--src/gallium/drivers/nv20/nv20_clear.c14
-rw-r--r--src/gallium/drivers/nv20/nv20_context.c446
-rw-r--r--src/gallium/drivers/nv20/nv20_context.h153
-rw-r--r--src/gallium/drivers/nv20/nv20_fragprog.c21
-rw-r--r--src/gallium/drivers/nv20/nv20_fragtex.c124
-rw-r--r--src/gallium/drivers/nv20/nv20_miptree.c206
-rw-r--r--src/gallium/drivers/nv20/nv20_prim_vbuf.c428
-rw-r--r--src/gallium/drivers/nv20/nv20_screen.c194
-rw-r--r--src/gallium/drivers/nv20/nv20_screen.h28
-rw-r--r--src/gallium/drivers/nv20/nv20_state.c583
-rw-r--r--src/gallium/drivers/nv20/nv20_state.h139
-rw-r--r--src/gallium/drivers/nv20/nv20_state_emit.c396
-rw-r--r--src/gallium/drivers/nv20/nv20_surface.c63
-rw-r--r--src/gallium/drivers/nv20/nv20_transfer.c195
-rw-r--r--src/gallium/drivers/nv20/nv20_vbo.c80
-rw-r--r--src/gallium/drivers/nv20/nv20_vertprog.c838
-rw-r--r--src/gallium/drivers/nv30/Makefile29
-rw-r--r--src/gallium/drivers/nv30/nv30_clear.c14
-rw-r--r--src/gallium/drivers/nv30/nv30_context.c98
-rw-r--r--src/gallium/drivers/nv30/nv30_context.h212
-rw-r--r--src/gallium/drivers/nv30/nv30_draw.c61
-rw-r--r--src/gallium/drivers/nv30/nv30_fragprog.c915
-rw-r--r--src/gallium/drivers/nv30/nv30_fragtex.c166
-rw-r--r--src/gallium/drivers/nv30/nv30_miptree.c213
-rw-r--r--src/gallium/drivers/nv30/nv30_query.c121
-rw-r--r--src/gallium/drivers/nv30/nv30_screen.c324
-rw-r--r--src/gallium/drivers/nv30/nv30_screen.h41
-rw-r--r--src/gallium/drivers/nv30/nv30_shader.h490
-rw-r--r--src/gallium/drivers/nv30/nv30_state.c728
-rw-r--r--src/gallium/drivers/nv30/nv30_state.h85
-rw-r--r--src/gallium/drivers/nv30/nv30_state_blend.c41
-rw-r--r--src/gallium/drivers/nv30/nv30_state_emit.c111
-rw-r--r--src/gallium/drivers/nv30/nv30_state_fb.c145
-rw-r--r--src/gallium/drivers/nv30/nv30_state_rasterizer.c17
-rw-r--r--src/gallium/drivers/nv30/nv30_state_scissor.c36
-rw-r--r--src/gallium/drivers/nv30/nv30_state_stipple.c40
-rw-r--r--src/gallium/drivers/nv30/nv30_state_viewport.c72
-rw-r--r--src/gallium/drivers/nv30/nv30_state_zsa.c17
-rw-r--r--src/gallium/drivers/nv30/nv30_surface.c63
-rw-r--r--src/gallium/drivers/nv30/nv30_transfer.c195
-rw-r--r--src/gallium/drivers/nv30/nv30_vbo.c561
-rw-r--r--src/gallium/drivers/nv30/nv30_vertprog.c837
-rw-r--r--src/gallium/drivers/nv40/Makefile29
-rw-r--r--src/gallium/drivers/nv40/nv40_clear.c14
-rw-r--r--src/gallium/drivers/nv40/nv40_context.c98
-rw-r--r--src/gallium/drivers/nv40/nv40_context.h233
-rw-r--r--src/gallium/drivers/nv40/nv40_draw.c352
-rw-r--r--src/gallium/drivers/nv40/nv40_fragprog.c995
-rw-r--r--src/gallium/drivers/nv40/nv40_fragtex.c170
-rw-r--r--src/gallium/drivers/nv40/nv40_miptree.c213
-rw-r--r--src/gallium/drivers/nv40/nv40_query.c121
-rw-r--r--src/gallium/drivers/nv40/nv40_screen.c303
-rw-r--r--src/gallium/drivers/nv40/nv40_screen.h40
-rw-r--r--src/gallium/drivers/nv40/nv40_shader.h556
-rw-r--r--src/gallium/drivers/nv40/nv40_state.c743
-rw-r--r--src/gallium/drivers/nv40/nv40_state.h88
-rw-r--r--src/gallium/drivers/nv40/nv40_state_blend.c41
-rw-r--r--src/gallium/drivers/nv40/nv40_state_emit.c177
-rw-r--r--src/gallium/drivers/nv40/nv40_state_fb.c172
-rw-r--r--src/gallium/drivers/nv40/nv40_state_rasterizer.c17
-rw-r--r--src/gallium/drivers/nv40/nv40_state_scissor.c36
-rw-r--r--src/gallium/drivers/nv40/nv40_state_stipple.c39
-rw-r--r--src/gallium/drivers/nv40/nv40_state_viewport.c69
-rw-r--r--src/gallium/drivers/nv40/nv40_state_zsa.c17
-rw-r--r--src/gallium/drivers/nv40/nv40_surface.c (renamed from src/mesa/drivers/dri/i915/i915_tex.c)62
-rw-r--r--src/gallium/drivers/nv40/nv40_transfer.c195
-rw-r--r--src/gallium/drivers/nv40/nv40_vbo.c562
-rw-r--r--src/gallium/drivers/nv40/nv40_vertprog.c1069
-rw-r--r--src/gallium/drivers/nv50/Makefile21
-rw-r--r--src/gallium/drivers/nv50/nv50_clear.c68
-rw-r--r--src/gallium/drivers/nv50/nv50_context.c122
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h201
-rw-r--r--src/gallium/drivers/nv50/nv50_draw.c89
-rw-r--r--src/gallium/drivers/nv50/nv50_miptree.c219
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c2482
-rw-r--r--src/gallium/drivers/nv50/nv50_program.h50
-rw-r--r--src/gallium/drivers/nv50/nv50_query.c134
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.c436
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.h38
-rw-r--r--src/gallium/drivers/nv50/nv50_state.c683
-rw-r--r--src/gallium/drivers/nv50/nv50_state_validate.c359
-rw-r--r--src/gallium/drivers/nv50/nv50_surface.c195
-rw-r--r--src/gallium/drivers/nv50/nv50_tex.c176
-rw-r--r--src/gallium/drivers/nv50/nv50_texture.h150
-rw-r--r--src/gallium/drivers/nv50/nv50_transfer.c239
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c400
-rw-r--r--src/gallium/drivers/r300/Makefile42
-rw-r--r--src/gallium/drivers/r300/SConscript29
-rw-r--r--src/gallium/drivers/r300/r300_chipset.c361
-rw-r--r--src/gallium/drivers/r300/r300_chipset.h82
-rw-r--r--src/gallium/drivers/r300/r300_clear.c35
-rw-r--r--src/gallium/drivers/r300/r300_clear.h36
-rw-r--r--src/gallium/drivers/r300/r300_context.c197
-rw-r--r--src/gallium/drivers/r300/r300_context.h327
-rw-r--r--src/gallium/drivers/r300/r300_cs.h154
-rw-r--r--src/gallium/drivers/r300/r300_debug.c88
-rw-r--r--src/gallium/drivers/r300/r300_emit.c813
-rw-r--r--src/gallium/drivers/r300/r300_emit.h96
-rw-r--r--src/gallium/drivers/r300/r300_flush.c49
-rw-r--r--src/gallium/drivers/r300/r300_flush.h35
-rw-r--r--src/gallium/drivers/r300/r300_fs.c137
-rw-r--r--src/gallium/drivers/r300/r300_fs.h51
-rw-r--r--src/gallium/drivers/r300/r300_query.c145
-rw-r--r--src/gallium/drivers/r300/r300_query.h39
-rw-r--r--src/gallium/drivers/r300/r300_reg.h3323
-rw-r--r--src/gallium/drivers/r300/r300_render.c298
-rw-r--r--src/gallium/drivers/r300/r300_screen.c416
-rw-r--r--src/gallium/drivers/r300/r300_screen.h66
-rw-r--r--src/gallium/drivers/r300/r300_shader_inlines.h47
-rw-r--r--src/gallium/drivers/r300/r300_state.c734
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c465
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.h30
-rw-r--r--src/gallium/drivers/r300/r300_state_inlines.h403
-rw-r--r--src/gallium/drivers/r300/r300_state_invariant.c145
-rw-r--r--src/gallium/drivers/r300/r300_state_invariant.h34
-rw-r--r--src/gallium/drivers/r300/r300_surface.c372
-rw-r--r--src/gallium/drivers/r300/r300_surface.h124
-rw-r--r--src/gallium/drivers/r300/r300_texture.c228
-rw-r--r--src/gallium/drivers/r300/r300_texture.h89
-rw-r--r--src/gallium/drivers/r300/r300_tgsi_to_rc.c336
-rw-r--r--src/gallium/drivers/r300/r300_tgsi_to_rc.h41
-rw-r--r--src/gallium/drivers/r300/r300_vs.c234
-rw-r--r--src/gallium/drivers/r300/r300_vs.h54
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h108
-rw-r--r--src/gallium/drivers/r300/r3xx_fs.c74
-rw-r--r--src/gallium/drivers/r300/r3xx_fs.h32
-rw-r--r--src/gallium/drivers/r300/r5xx_fs.c125
-rw-r--r--src/gallium/drivers/r300/r5xx_fs.h32
-rw-r--r--src/gallium/drivers/softpipe/Makefile44
-rw-r--r--src/gallium/drivers/softpipe/SConscript46
-rw-r--r--src/gallium/drivers/softpipe/sp_clear.c89
-rw-r--r--src/gallium/drivers/softpipe/sp_clear.h42
-rw-r--r--src/gallium/drivers/softpipe/sp_context.c330
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h168
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c194
-rw-r--r--src/gallium/drivers/softpipe/sp_flush.c94
-rw-r--r--src/gallium/drivers/softpipe/sp_flush.h37
-rw-r--r--src/gallium/drivers/softpipe/sp_fs.h54
-rw-r--r--src/gallium/drivers/softpipe/sp_fs_exec.c162
-rw-r--r--src/gallium/drivers/softpipe/sp_fs_llvm.c205
-rw-r--r--src/gallium/drivers/softpipe/sp_fs_sse.c169
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_setup.c190
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_setup.h85
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_vbuf.c585
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_vbuf.h38
-rw-r--r--src/gallium/drivers/softpipe/sp_quad.h106
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_alpha_test.c108
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_blend.c777
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_bufloop.c74
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_colormask.c116
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_coverage.c94
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_depth_test.c290
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_earlyz.c88
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_fs.c192
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_occlusion.c85
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_output.c103
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_pipe.c118
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_pipe.h74
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_stencil.c352
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_stipple.c77
-rw-r--r--src/gallium/drivers/softpipe/sp_query.c111
-rw-r--r--src/gallium/drivers/softpipe/sp_query.h39
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c190
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.h58
-rw-r--r--src/gallium/drivers/softpipe/sp_setup.c1550
-rw-r--r--src/gallium/drivers/softpipe/sp_setup.h53
-rw-r--r--src/gallium/drivers/softpipe/sp_state.h206
-rw-r--r--src/gallium/drivers/softpipe/sp_state_blend.c98
-rw-r--r--src/gallium/drivers/softpipe/sp_state_clip.c79
-rw-r--r--src/gallium/drivers/softpipe/sp_state_derived.c211
-rw-r--r--src/gallium/drivers/softpipe/sp_state_fs.c169
-rw-r--r--src/gallium/drivers/softpipe/sp_state_rasterizer.c62
-rw-r--r--src/gallium/drivers/softpipe/sp_state_sampler.c117
-rw-r--r--src/gallium/drivers/softpipe/sp_state_surface.c129
-rw-r--r--src/gallium/drivers/softpipe/sp_state_vertex.c73
-rw-r--r--src/gallium/drivers/softpipe/sp_surface.c50
-rw-r--r--src/gallium/drivers/softpipe/sp_surface.h42
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_sample.c1295
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_sample.h73
-rw-r--r--src/gallium/drivers/softpipe/sp_texture.c407
-rw-r--r--src/gallium/drivers/softpipe/sp_texture.h80
-rw-r--r--src/gallium/drivers/softpipe/sp_tile_cache.c626
-rw-r--r--src/gallium/drivers/softpipe/sp_tile_cache.h106
-rw-r--r--src/gallium/drivers/softpipe/sp_winsys.h65
-rw-r--r--src/gallium/drivers/trace/Makefile17
-rw-r--r--src/gallium/drivers/trace/README78
-rw-r--r--src/gallium/drivers/trace/SConscript19
-rw-r--r--src/gallium/drivers/trace/tr_buffer.c75
-rw-r--r--src/gallium/drivers/trace/tr_buffer.h70
-rw-r--r--src/gallium/drivers/trace/tr_context.c1302
-rw-r--r--src/gallium/drivers/trace/tr_context.h108
-rw-r--r--src/gallium/drivers/trace/tr_drm.c186
-rw-r--r--src/gallium/drivers/trace/tr_drm.h35
-rw-r--r--src/gallium/drivers/trace/tr_dump.c627
-rw-r--r--src/gallium/drivers/trace/tr_dump.h177
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.c549
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.h78
-rw-r--r--src/gallium/drivers/trace/tr_rbug.c864
-rw-r--r--src/gallium/drivers/trace/tr_screen.c958
-rw-r--r--src/gallium/drivers/trace/tr_screen.h130
-rw-r--r--src/gallium/drivers/trace/tr_state.c66
-rw-r--r--src/gallium/drivers/trace/tr_state.h68
-rw-r--r--src/gallium/drivers/trace/tr_texture.c170
-rw-r--r--src/gallium/drivers/trace/tr_texture.h122
-rw-r--r--src/gallium/drivers/trace/trace.xsl188
-rw-r--r--src/gallium/include/pipe/internal/p_winsys_screen.h190
-rw-r--r--src/gallium/include/pipe/p_atomic.h353
-rw-r--r--src/gallium/include/pipe/p_compiler.h179
-rw-r--r--src/gallium/include/pipe/p_config.h176
-rw-r--r--src/gallium/include/pipe/p_context.h271
-rw-r--r--src/gallium/include/pipe/p_defines.h322
-rw-r--r--src/gallium/include/pipe/p_error.h65
-rw-r--r--src/gallium/include/pipe/p_format.h620
-rw-r--r--src/gallium/include/pipe/p_inlines.h163
-rw-r--r--src/gallium/include/pipe/p_refcnt.h96
-rw-r--r--src/gallium/include/pipe/p_screen.h296
-rw-r--r--src/gallium/include/pipe/p_shader_tokens.h671
-rw-r--r--src/gallium/include/pipe/p_state.h412
-rw-r--r--src/gallium/include/pipe/p_thread.h279
-rw-r--r--src/gallium/include/state_tracker/dri1_api.h82
-rw-r--r--src/gallium/include/state_tracker/drm_api.h69
-rw-r--r--src/gallium/state_trackers/Makefile25
-rw-r--r--src/gallium/state_trackers/README2
-rw-r--r--src/gallium/state_trackers/dri/Makefile28
-rw-r--r--src/gallium/state_trackers/dri/SConscript23
-rw-r--r--src/gallium/state_trackers/dri/dri_context.c215
-rw-r--r--src/gallium/state_trackers/dri/dri_context.h123
-rw-r--r--src/gallium/state_trackers/dri/dri_drawable.c687
-rw-r--r--src/gallium/state_trackers/dri/dri_drawable.h111
-rw-r--r--src/gallium/state_trackers/dri/dri_extensions.c128
-rw-r--r--src/gallium/state_trackers/dri/dri_screen.c354
-rw-r--r--src/gallium/state_trackers/dri/dri_screen.h79
-rw-r--r--src/gallium/state_trackers/egl/Makefile19
-rw-r--r--src/gallium/state_trackers/egl/egl_context.c179
-rw-r--r--src/gallium/state_trackers/egl/egl_surface.c387
-rw-r--r--src/gallium/state_trackers/egl/egl_tracker.c271
-rw-r--r--src/gallium/state_trackers/egl/egl_tracker.h197
-rw-r--r--src/gallium/state_trackers/egl/egl_visual.c85
-rw-r--r--src/gallium/state_trackers/es/Makefile100
-rw-r--r--src/gallium/state_trackers/es/st_es1.c1
-rw-r--r--src/gallium/state_trackers/es/st_es2.c1
-rw-r--r--src/gallium/state_trackers/g3dvl/Makefile21
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_basic_csc.c714
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_basic_csc.h13
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_context.c205
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_context.h73
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_csc.h53
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_defs.h11
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_display.c48
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_display.h29
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c1155
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h18
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc1185
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_render.h38
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_screen.c115
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_screen.h63
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_shader_build.c215
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_shader_build.h61
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_surface.c242
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_surface.h86
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_types.h115
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_util.c16
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_util.h6
-rw-r--r--src/gallium/state_trackers/glx/Makefile25
-rw-r--r--src/gallium/state_trackers/glx/xlib/Makefile16
-rw-r--r--src/gallium/state_trackers/glx/xlib/SConscript27
-rw-r--r--src/gallium/state_trackers/glx/xlib/glx_api.c2629
-rw-r--r--src/gallium/state_trackers/glx/xlib/glx_getproc.c214
-rw-r--r--src/gallium/state_trackers/glx/xlib/glx_usefont.c375
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_api.c1220
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_api.h394
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_winsys.h59
-rw-r--r--src/gallium/state_trackers/python/README43
-rw-r--r--src/gallium/state_trackers/python/SConscript47
-rw-r--r--src/gallium/state_trackers/python/gallium.i103
-rw-r--r--src/gallium/state_trackers/python/p_compiler.i29
-rw-r--r--src/gallium/state_trackers/python/p_context.i319
-rw-r--r--src/gallium/state_trackers/python/p_device.i130
-rw-r--r--src/gallium/state_trackers/python/p_format.i162
-rw-r--r--src/gallium/state_trackers/python/p_state.i137
-rw-r--r--src/gallium/state_trackers/python/p_texture.i450
-rw-r--r--src/gallium/state_trackers/python/retrace/README17
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/format.py173
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/interpreter.py748
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/model.py213
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/parse.py392
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/parser.py34
-rw-r--r--src/gallium/state_trackers/python/samples/tri.py232
-rw-r--r--src/gallium/state_trackers/python/st_device.c305
-rw-r--r--src/gallium/state_trackers/python/st_device.h106
-rw-r--r--src/gallium/state_trackers/python/st_hardpipe_winsys.c237
-rw-r--r--src/gallium/state_trackers/python/st_sample.c570
-rw-r--r--src/gallium/state_trackers/python/st_sample.h47
-rw-r--r--src/gallium/state_trackers/python/st_softpipe_winsys.c270
-rw-r--r--src/gallium/state_trackers/python/st_winsys.h52
-rw-r--r--src/gallium/state_trackers/python/tests/.gitignore3
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/base.py344
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-add.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp3.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp4.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dst.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-ex2.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-flr.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-frc.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lg2.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lit.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lrp.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mad.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-max.sh10
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-min.sh10
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mov.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mul.sh10
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rcp.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rsq.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sge.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-abs.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-neg.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-swz.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sub.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-xpd.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py218
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-abs.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-add.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arl.sh23
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arr.sh23
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp3.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp4.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dst.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-ex2.sh18
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-flr.sh23
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-frc.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lg2.sh18
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lit.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lrp.sh14
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mad.sh14
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-max.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-min.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mov.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mul.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rcp.sh18
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rsq.sh18
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sge.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-slt.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-abs.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-neg.sh12
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-swz.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sub.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-xpd.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py247
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/surface_copy.py199
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/texture_render.py320
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/texture_sample.py591
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/texture_transfer.py179
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/tree.py23
-rw-r--r--src/gallium/state_trackers/vega/Makefile128
-rw-r--r--src/gallium/state_trackers/vega/api_consts.h56
-rw-r--r--src/gallium/state_trackers/vega/api_context.c75
-rw-r--r--src/gallium/state_trackers/vega/api_filters.c805
-rw-r--r--src/gallium/state_trackers/vega/api_images.c489
-rw-r--r--src/gallium/state_trackers/vega/api_masks.c373
-rw-r--r--src/gallium/state_trackers/vega/api_misc.c83
-rw-r--r--src/gallium/state_trackers/vega/api_paint.c166
-rw-r--r--src/gallium/state_trackers/vega/api_params.c1673
-rw-r--r--src/gallium/state_trackers/vega/api_path.c488
-rw-r--r--src/gallium/state_trackers/vega/api_text.c258
-rw-r--r--src/gallium/state_trackers/vega/api_transform.c128
-rw-r--r--src/gallium/state_trackers/vega/arc.c708
-rw-r--r--src/gallium/state_trackers/vega/arc.h80
-rw-r--r--src/gallium/state_trackers/vega/asm_fill.h246
-rw-r--r--src/gallium/state_trackers/vega/asm_filters.h117
-rw-r--r--src/gallium/state_trackers/vega/asm_util.h136
-rw-r--r--src/gallium/state_trackers/vega/bezier.c704
-rw-r--r--src/gallium/state_trackers/vega/bezier.h81
-rw-r--r--src/gallium/state_trackers/vega/image.c654
-rw-r--r--src/gallium/state_trackers/vega/image.h104
-rw-r--r--src/gallium/state_trackers/vega/mask.c690
-rw-r--r--src/gallium/state_trackers/vega/mask.h68
-rw-r--r--src/gallium/state_trackers/vega/matrix.h462
-rw-r--r--src/gallium/state_trackers/vega/paint.c699
-rw-r--r--src/gallium/state_trackers/vega/paint.h118
-rw-r--r--src/gallium/state_trackers/vega/path.c2034
-rw-r--r--src/gallium/state_trackers/vega/path.h126
-rw-r--r--src/gallium/state_trackers/vega/path_utils.h109
-rw-r--r--src/gallium/state_trackers/vega/polygon.c550
-rw-r--r--src/gallium/state_trackers/vega/polygon.h75
-rw-r--r--src/gallium/state_trackers/vega/renderer.c592
-rw-r--r--src/gallium/state_trackers/vega/renderer.h76
-rw-r--r--src/gallium/state_trackers/vega/shader.c310
-rw-r--r--src/gallium/state_trackers/vega/shader.h56
-rw-r--r--src/gallium/state_trackers/vega/shaders_cache.c439
-rw-r--r--src/gallium/state_trackers/vega/shaders_cache.h77
-rw-r--r--src/gallium/state_trackers/vega/st_inlines.h159
-rw-r--r--src/gallium/state_trackers/vega/stroker.c1349
-rw-r--r--src/gallium/state_trackers/vega/stroker.h89
-rw-r--r--src/gallium/state_trackers/vega/util_array.h122
-rw-r--r--src/gallium/state_trackers/vega/vg_context.c543
-rw-r--r--src/gallium/state_trackers/vega/vg_context.h292
-rw-r--r--src/gallium/state_trackers/vega/vg_state.c124
-rw-r--r--src/gallium/state_trackers/vega/vg_state.h109
-rw-r--r--src/gallium/state_trackers/vega/vg_tracker.c416
-rw-r--r--src/gallium/state_trackers/vega/vg_tracker.h107
-rw-r--r--src/gallium/state_trackers/vega/vg_translate.c1030
-rw-r--r--src/gallium/state_trackers/vega/vg_translate.h49
-rw-r--r--src/gallium/state_trackers/vega/vgu.c450
-rw-r--r--src/gallium/state_trackers/wgl/SConscript42
-rw-r--r--src/gallium/state_trackers/wgl/icd/stw_icd.c617
-rw-r--r--src/gallium/state_trackers/wgl/icd/stw_icd.h489
-rw-r--r--src/gallium/state_trackers/wgl/opengl32.def388
-rw-r--r--src/gallium/state_trackers/wgl/opengl32.mingw.def387
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c483
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_context.c382
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_context.h43
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_device.c225
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_device.h77
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_extensionsstring.c59
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_extgallium.c79
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_extgallium.h47
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_extswapinterval.c57
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_framebuffer.c493
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_framebuffer.h148
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c86
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_pixelformat.c370
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_pixelformat.h65
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_public.h73
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_tls.c139
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_tls.h59
-rw-r--r--src/gallium/state_trackers/wgl/shared/stw_winsys.h65
-rw-r--r--src/gallium/state_trackers/wgl/wgl/stw_wgl.c329
-rw-r--r--src/gallium/state_trackers/wgl/wgl/stw_wgl.h63
-rw-r--r--src/gallium/state_trackers/xorg/Makefile18
-rw-r--r--src/gallium/state_trackers/xorg/SConscript27
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.c1019
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.h37
-rw-r--r--src/gallium/state_trackers/xorg/xorg_crtc.c331
-rw-r--r--src/gallium/state_trackers/xorg/xorg_dri2.c380
-rw-r--r--src/gallium/state_trackers/xorg/xorg_driver.c744
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c771
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.h57
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.c489
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.h43
-rw-r--r--src/gallium/state_trackers/xorg/xorg_output.c296
-rw-r--r--src/gallium/state_trackers/xorg/xorg_tracker.h155
-rw-r--r--src/gallium/state_trackers/xorg/xorg_winsys.h49
-rw-r--r--src/gallium/winsys/Makefile12
-rw-r--r--src/gallium/winsys/SConscript16
-rw-r--r--src/gallium/winsys/drm/Makefile12
-rw-r--r--src/gallium/winsys/drm/Makefile.template126
-rw-r--r--src/gallium/winsys/drm/SConscript59
-rw-r--r--src/gallium/winsys/drm/intel/Makefile12
-rw-r--r--src/gallium/winsys/drm/intel/SConscript7
-rw-r--r--src/gallium/winsys/drm/intel/dri/Makefile27
-rw-r--r--src/gallium/winsys/drm/intel/dri/SConscript20
-rw-r--r--src/gallium/winsys/drm/intel/egl/Makefile29
-rw-r--r--src/gallium/winsys/drm/intel/gem/Makefile16
-rw-r--r--src/gallium/winsys/drm/intel/gem/SConscript17
-rw-r--r--src/gallium/winsys/drm/intel/gem/intel_drm_api.c202
-rw-r--r--src/gallium/winsys/drm/intel/gem/intel_drm_batchbuffer.c229
-rw-r--r--src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c148
-rw-r--r--src/gallium/winsys/drm/intel/gem/intel_drm_fence.c81
-rw-r--r--src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h78
-rw-r--r--src/gallium/winsys/drm/intel/xorg/Makefile57
-rw-r--r--src/gallium/winsys/drm/intel/xorg/intel_xorg.c147
-rw-r--r--src/gallium/winsys/drm/nouveau/Makefile12
-rw-r--r--src/gallium/winsys/drm/nouveau/dri/Makefile27
-rw-r--r--src/gallium/winsys/drm/nouveau/drm/Makefile11
-rw-r--r--src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h28
-rw-r--r--src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c263
-rw-r--r--src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h34
-rw-r--r--src/gallium/winsys/drm/radeon/Makefile12
-rw-r--r--src/gallium/winsys/drm/radeon/SConscript7
-rw-r--r--src/gallium/winsys/drm/radeon/core/Makefile18
-rw-r--r--src/gallium/winsys/drm/radeon/core/SConscript19
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_buffer.c285
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_buffer.h86
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_drm.c188
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_drm.h79
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_r300.c210
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_r300.h42
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.c41
-rw-r--r--src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.h44
-rw-r--r--src/gallium/winsys/drm/radeon/dri/Makefile26
-rw-r--r--src/gallium/winsys/drm/radeon/dri/SConscript17
-rw-r--r--src/gallium/winsys/drm/radeon/egl/Makefile26
-rw-r--r--src/gallium/winsys/drm/radeon/python/README15
-rw-r--r--src/gallium/winsys/drm/radeon/python/SConscript33
-rw-r--r--src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c140
-rw-r--r--src/gallium/winsys/drm/radeon/python/xf86dri.c605
-rw-r--r--src/gallium/winsys/drm/radeon/python/xf86dri.h123
-rw-r--r--src/gallium/winsys/drm/radeon/python/xf86dristr.h389
-rw-r--r--src/gallium/winsys/drm/radeon/xorg/Makefile42
-rw-r--r--src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c148
-rw-r--r--src/gallium/winsys/egl_xlib/Makefile89
-rw-r--r--src/gallium/winsys/egl_xlib/egl_xlib.c869
-rw-r--r--src/gallium/winsys/egl_xlib/sw_winsys.c243
-rw-r--r--src/gallium/winsys/egl_xlib/sw_winsys.h40
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/Makefile50
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_context_vl.c172
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_context_vl.h39
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_screen_vl.c88
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_screen_vl.h20
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c94
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h10
-rw-r--r--src/gallium/winsys/g3dvl/vl_winsys.h14
-rw-r--r--src/gallium/winsys/g3dvl/xsp_winsys.c290
-rw-r--r--src/gallium/winsys/gdi/SConscript39
-rw-r--r--src/gallium/winsys/gdi/gdi_softpipe_winsys.c334
-rw-r--r--src/gallium/winsys/xlib/Makefile105
-rw-r--r--src/gallium/winsys/xlib/SConscript66
-rw-r--r--src/gallium/winsys/xlib/xlib.c123
-rw-r--r--src/gallium/winsys/xlib/xlib.h15
-rw-r--r--src/gallium/winsys/xlib/xlib_brw.h30
-rw-r--r--src/gallium/winsys/xlib/xlib_brw_aub.c399
-rw-r--r--src/gallium/winsys/xlib/xlib_brw_aub.h114
-rw-r--r--src/gallium/winsys/xlib/xlib_brw_context.c209
-rw-r--r--src/gallium/winsys/xlib/xlib_brw_screen.c469
-rw-r--r--src/gallium/winsys/xlib/xlib_cell.c437
-rw-r--r--src/gallium/winsys/xlib/xlib_llvmpipe.c461
-rw-r--r--src/gallium/winsys/xlib/xlib_softpipe.c507
-rw-r--r--src/gallium/winsys/xlib/xlib_trace.c113
-rw-r--r--src/gallium/winsys/xlib/xmesa.h424
-rw-r--r--src/gallium/winsys/xlib/xmesa_x.h86
-rw-r--r--src/glew/LICENSE.txt73
-rw-r--r--src/glew/Makefile54
-rw-r--r--src/glew/SConscript50
-rw-r--r--src/glew/glew.c12180
-rw-r--r--src/glew/glewinfo.c7180
-rw-r--r--src/glew/visualinfo.c1173
-rw-r--r--src/glu/.gitignore1
-rw-r--r--src/glu/Makefile5
-rw-r--r--src/glu/descrip.mms9
-rw-r--r--src/glu/glu.pc.in2
-rw-r--r--src/glu/mesa/Makefile.DJ100
-rw-r--r--src/glu/mesa/descrip.mms61
-rw-r--r--src/glu/mesa/mms_depend15
-rw-r--r--src/glu/sgi/.gitignore1
-rw-r--r--src/glu/sgi/Makefile.DJ188
-rw-r--r--src/glu/sgi/descrip.mms451
-rw-r--r--src/glu/sgi/glu.exports.darwin118
-rw-r--r--src/glut/beos/Makefile1
-rw-r--r--src/glut/directfb/Makefile1
-rw-r--r--src/glut/dos/Makefile.DJ126
-rw-r--r--src/glut/fbdev/Makefile3
-rw-r--r--src/glut/ggi/Makefile1
-rw-r--r--src/glut/glx/Makefile6
-rw-r--r--src/glut/glx/SConscript87
-rw-r--r--src/glut/glx/descrip.mms208
-rw-r--r--src/glut/glx/glut.def6
-rw-r--r--src/glut/glx/glut.pc.in2
-rw-r--r--src/glut/glx/glut_event.c9
-rw-r--r--src/glut/glx/glut_input.c2
-rw-r--r--src/glut/glx/glutint.h38
-rw-r--r--src/glut/glx/glutstroke.h2
-rw-r--r--src/glut/glx/glutwin32.h1
-rw-r--r--src/glut/glx/mms_depend72
-rw-r--r--src/glut/glx/win32_glx.c2
-rw-r--r--src/glut/glx/win32_winproc.c9
-rw-r--r--src/glut/glx/win32_x11.h2
-rw-r--r--src/glut/mini/Makefile6
-rw-r--r--src/glut/mini/glut.pc.in2
-rw-r--r--src/glw/Makefile6
-rw-r--r--src/glw/glw.pc.in2
-rw-r--r--src/glx/mini/Makefile1
-rw-r--r--src/glx/x11/Makefile9
-rw-r--r--src/glx/x11/dri2.c510
-rw-r--r--src/glx/x11/dri2.h58
-rw-r--r--src/glx/x11/dri2_glx.c685
-rw-r--r--src/glx/x11/dri_common.c440
-rw-r--r--src/glx/x11/dri_glx.c1010
-rw-r--r--src/glx/x11/drisw_glx.c6
-rw-r--r--src/glx/x11/glx_pbuffer.c25
-rw-r--r--src/glx/x11/glx_query.c46
-rw-r--r--src/glx/x11/glxclient.h428
-rw-r--r--src/glx/x11/glxcmds.c3633
-rw-r--r--src/glx/x11/glxcurrent.c101
-rw-r--r--src/glx/x11/glxext.c160
-rw-r--r--src/glx/x11/glxextensions.c26
-rw-r--r--src/glx/x11/indirect.c75
-rw-r--r--src/glx/x11/indirect_size.c5
-rw-r--r--src/glx/x11/indirect_vertex_array.c78
-rw-r--r--src/glx/x11/indirect_vertex_program.c4
-rw-r--r--src/glx/x11/pixelstore.c4
-rw-r--r--src/glx/x11/single2.c156
-rw-r--r--src/mesa/Makefile27
-rw-r--r--src/mesa/Makefile.DJ166
-rw-r--r--src/mesa/Makefile.mgw2
-rw-r--r--src/mesa/SConscript356
-rw-r--r--src/mesa/drivers/allegro/amesa.c2
-rw-r--r--src/mesa/drivers/common/driverfuncs.c58
-rw-r--r--src/mesa/drivers/common/meta.c2039
-rw-r--r--src/mesa/drivers/common/meta.h91
-rw-r--r--src/mesa/drivers/dri/Makefile2
-rw-r--r--src/mesa/drivers/dri/Makefile.es104
-rw-r--r--src/mesa/drivers/dri/Makefile.template26
-rw-r--r--src/mesa/drivers/dri/common/.gitignore1
-rw-r--r--src/mesa/drivers/dri/common/dri_metaops.c298
-rw-r--r--src/mesa/drivers/dri/common/dri_metaops.h81
-rw-r--r--src/mesa/drivers/dri/common/dri_util.c80
-rw-r--r--src/mesa/drivers/dri/common/dri_util.h42
-rw-r--r--src/mesa/drivers/dri/common/drirenderbuffer.c2
-rw-r--r--src/mesa/drivers/dri/common/extension_helper.h2228
-rw-r--r--src/mesa/drivers/dri/common/spantmp2.h65
-rw-r--r--src/mesa/drivers/dri/common/texmem.c10
-rw-r--r--src/mesa/drivers/dri/common/utils.c229
-rw-r--r--src/mesa/drivers/dri/common/utils.h6
-rw-r--r--src/mesa/drivers/dri/common/xmlpool.h4
-rw-r--r--src/mesa/drivers/dri/common/xmlpool/options.h20
-rw-r--r--src/mesa/drivers/dri/common/xmlpool/t_options.h10
-rw-r--r--src/mesa/drivers/dri/fb/fb_dri.c2
-rw-r--r--src/mesa/drivers/dri/fb/fb_egl.c22
-rw-r--r--src/mesa/drivers/dri/ffb/ffb_state.c4
-rw-r--r--src/mesa/drivers/dri/ffb/ffb_xmesa.c12
-rw-r--r--src/mesa/drivers/dri/gamma/gamma_context.c2
-rw-r--r--src/mesa/drivers/dri/gamma/gamma_tex.c21
-rw-r--r--src/mesa/drivers/dri/gamma/gamma_xmesa.c2
-rw-r--r--src/mesa/drivers/dri/glcore/Makefile84
-rw-r--r--src/mesa/drivers/dri/i810/i810context.c8
-rw-r--r--src/mesa/drivers/dri/i810/i810screen.c8
-rw-r--r--src/mesa/drivers/dri/i810/i810tex.c6
-rw-r--r--src/mesa/drivers/dri/i915/Makefile18
-rw-r--r--src/mesa/drivers/dri/i915/i830_context.c7
-rw-r--r--src/mesa/drivers/dri/i915/i830_context.h8
-rw-r--r--src/mesa/drivers/dri/i915/i830_reg.h16
-rw-r--r--src/mesa/drivers/dri/i915/i830_state.c53
-rw-r--r--src/mesa/drivers/dri/i915/i830_tex.c100
-rw-r--r--src/mesa/drivers/dri/i915/i830_texstate.c34
-rw-r--r--src/mesa/drivers/dri/i915/i830_vtbl.c100
-rw-r--r--src/mesa/drivers/dri/i915/i915_context.c28
-rw-r--r--src/mesa/drivers/dri/i915/i915_context.h12
-rw-r--r--src/mesa/drivers/dri/i915/i915_fragprog.c20
-rw-r--r--src/mesa/drivers/dri/i915/i915_reg.h19
-rw-r--r--src/mesa/drivers/dri/i915/i915_state.c248
-rw-r--r--src/mesa/drivers/dri/i915/i915_tex_layout.c64
-rw-r--r--src/mesa/drivers/dri/i915/i915_texstate.c51
-rw-r--r--src/mesa/drivers/dri/i915/i915_vtbl.c104
l---------src/mesa/drivers/dri/i915/intel_clear.c1
l---------src/mesa/drivers/dri/i915/intel_depthstencil.c1
l---------src/mesa/drivers/dri/i915/intel_eglimage.c1
l---------src/mesa/drivers/dri/i915/intel_eglimage.h1
l---------src/mesa/drivers/dri/i915/intel_extensions.c1
l---------src/mesa/drivers/dri/i915/intel_generatemipmap.c1
l---------[-rw-r--r--]src/mesa/drivers/dri/i915/intel_pixel_read.c307
l---------[-rw-r--r--]src/mesa/drivers/dri/i915/intel_state.c298
l---------src/mesa/drivers/dri/i915/intel_swapbuffers.c1
l---------src/mesa/drivers/dri/i915/intel_syncobj.c1
-rw-r--r--src/mesa/drivers/dri/i915/intel_tris.c15
-rw-r--r--src/mesa/drivers/dri/i965/Makefile10
-rw-r--r--src/mesa/drivers/dri/i965/brw_cc.c75
-rw-r--r--src/mesa/drivers/dri/i965/brw_clip.c63
-rw-r--r--src/mesa/drivers/dri/i965/brw_clip.h6
-rw-r--r--src/mesa/drivers/dri/i965/brw_clip_line.c75
-rw-r--r--src/mesa/drivers/dri/i965/brw_clip_point.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_clip_state.c20
-rw-r--r--src/mesa/drivers/dri/i965/brw_clip_tri.c93
-rw-r--r--src/mesa/drivers/dri/i965/brw_clip_unfilled.c1
-rw-r--r--src/mesa/drivers/dri/i965/brw_clip_util.c51
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.c65
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.h191
-rw-r--r--src/mesa/drivers/dri/i965/brw_curbe.c99
-rw-r--r--src/mesa/drivers/dri/i965/brw_defines.h61
-rw-r--r--src/mesa/drivers/dri/i965/brw_disasm.c903
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw.c182
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw.h1
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw_upload.c276
-rw-r--r--src/mesa/drivers/dri/i965/brw_eu.c125
-rw-r--r--src/mesa/drivers/dri/i965/brw_eu.h68
-rw-r--r--src/mesa/drivers/dri/i965/brw_eu_debug.c5
-rw-r--r--src/mesa/drivers/dri/i965/brw_eu_emit.c546
-rw-r--r--src/mesa/drivers/dri/i965/brw_fallback.c47
-rw-r--r--src/mesa/drivers/dri/i965/brw_gs.c9
-rw-r--r--src/mesa/drivers/dri/i965/brw_gs.h1
-rw-r--r--src/mesa/drivers/dri/i965/brw_gs_emit.c30
-rw-r--r--src/mesa/drivers/dri/i965/brw_gs_state.c8
-rw-r--r--src/mesa/drivers/dri/i965/brw_metaops.c583
-rw-r--r--src/mesa/drivers/dri/i965/brw_misc_state.c111
-rw-r--r--src/mesa/drivers/dri/i965/brw_program.c38
-rw-r--r--src/mesa/drivers/dri/i965/brw_queryobj.c7
-rw-r--r--src/mesa/drivers/dri/i965/brw_sf.c27
-rw-r--r--src/mesa/drivers/dri/i965/brw_sf.h3
-rw-r--r--src/mesa/drivers/dri/i965/brw_sf_emit.c73
-rw-r--r--src/mesa/drivers/dri/i965/brw_sf_state.c167
-rw-r--r--src/mesa/drivers/dri/i965/brw_state.h27
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_batch.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_cache.c159
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_dump.c30
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_upload.c76
-rw-r--r--src/mesa/drivers/dri/i965/brw_structs.h149
-rw-r--r--src/mesa/drivers/dri/i965/brw_tex.c12
-rw-r--r--src/mesa/drivers/dri/i965/brw_tex_layout.c159
-rw-r--r--src/mesa/drivers/dri/i965/brw_urb.c27
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs.c14
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs.h7
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_constval.c53
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_emit.c666
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_state.c28
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_surface_state.c226
-rw-r--r--src/mesa/drivers/dri/i965/brw_vtbl.c112
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm.c197
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm.h50
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_debug.c3
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_emit.c286
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_fp.c469
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_glsl.c1467
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_iz.c7
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_pass0.c98
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_pass1.c37
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_pass2.c49
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_sampler_state.c49
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_state.c78
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c428
l---------src/mesa/drivers/dri/i965/intel_clear.c1
l---------src/mesa/drivers/dri/i965/intel_depthstencil.c1
l---------src/mesa/drivers/dri/i965/intel_extensions.c1
l---------src/mesa/drivers/dri/i965/intel_generatemipmap.c1
l---------src/mesa/drivers/dri/i965/intel_pixel_read.c1
l---------[-rw-r--r--]src/mesa/drivers/dri/i965/intel_state.c226
l---------src/mesa/drivers/dri/i965/intel_swapbuffers.c1
l---------src/mesa/drivers/dri/i965/intel_syncobj.c1
-rw-r--r--src/mesa/drivers/dri/intel/intel_batchbuffer.c21
-rw-r--r--src/mesa/drivers/dri/intel/intel_blit.c225
-rw-r--r--src/mesa/drivers/dri/intel/intel_blit.h20
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffer_objects.c357
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffer_objects.h16
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffers.c519
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffers.h7
-rw-r--r--src/mesa/drivers/dri/intel/intel_chipset.h27
-rw-r--r--src/mesa/drivers/dri/intel/intel_clear.c194
-rw-r--r--src/mesa/drivers/dri/intel/intel_clear.h38
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.c536
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.h86
-rw-r--r--src/mesa/drivers/dri/intel/intel_decode.c81
-rw-r--r--src/mesa/drivers/dri/intel/intel_depthstencil.c261
-rw-r--r--src/mesa/drivers/dri/intel/intel_depthstencil.h15
-rw-r--r--src/mesa/drivers/dri/intel/intel_depthtmp.h54
-rw-r--r--src/mesa/drivers/dri/intel/intel_eglimage.c139
-rw-r--r--src/mesa/drivers/dri/intel/intel_eglimage.h61
-rw-r--r--src/mesa/drivers/dri/intel/intel_extensions.c213
-rw-r--r--src/mesa/drivers/dri/intel/intel_extensions.h36
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.c205
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.h86
-rw-r--r--src/mesa/drivers/dri/intel/intel_generatemipmap.c286
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.c104
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.h19
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel.c181
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel.h10
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_bitmap.c120
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_copy.c199
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_draw.c222
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_read.c315
-rw-r--r--src/mesa/drivers/dri/intel/intel_reg.h13
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.c249
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.h30
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.c211
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.h10
-rw-r--r--src/mesa/drivers/dri/intel/intel_span.c468
-rw-r--r--src/mesa/drivers/dri/intel/intel_spantmp.h61
-rw-r--r--src/mesa/drivers/dri/intel/intel_state.c233
-rw-r--r--src/mesa/drivers/dri/intel/intel_swapbuffers.c248
-rw-r--r--src/mesa/drivers/dri/intel/intel_swapbuffers.h52
-rw-r--r--src/mesa/drivers/dri/intel/intel_syncobj.c142
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.c74
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.h113
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_copy.c97
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_format.c44
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_image.c193
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_layout.c33
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_layout.h6
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_subimage.c101
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_validate.c8
-rw-r--r--src/mesa/drivers/dri/mach64/mach64_context.c7
-rw-r--r--src/mesa/drivers/dri/mach64/mach64_screen.c8
-rw-r--r--src/mesa/drivers/dri/mach64/mach64_tex.c12
-rw-r--r--src/mesa/drivers/dri/mga/mga_texstate.c8
-rw-r--r--src/mesa/drivers/dri/mga/mga_xmesa.c18
-rw-r--r--src/mesa/drivers/dri/mga/mgapixel.c2
-rw-r--r--src/mesa/drivers/dri/mga/mgatex.c14
-rw-r--r--src/mesa/drivers/dri/r128/r128_context.c8
-rw-r--r--src/mesa/drivers/dri/r128/r128_screen.c43
-rw-r--r--src/mesa/drivers/dri/r128/r128_state.c5
-rw-r--r--src/mesa/drivers/dri/r128/r128_tex.c11
-rw-r--r--src/mesa/drivers/dri/r128/r128_tris.c2
-rw-r--r--src/mesa/drivers/dri/r128/r128_tris.h2
-rw-r--r--src/mesa/drivers/dri/r200/.gitignore3
-rw-r--r--src/mesa/drivers/dri/r200/Makefile57
-rw-r--r--src/mesa/drivers/dri/r200/r200_cmdbuf.c547
-rw-r--r--src/mesa/drivers/dri/r200/r200_context.c459
-rw-r--r--src/mesa/drivers/dri/r200/r200_context.h470
-rw-r--r--src/mesa/drivers/dri/r200/r200_fragshader.c2
-rw-r--r--src/mesa/drivers/dri/r200/r200_ioctl.c849
-rw-r--r--src/mesa/drivers/dri/r200/r200_ioctl.h145
-rw-r--r--src/mesa/drivers/dri/r200/r200_lock.c116
-rw-r--r--src/mesa/drivers/dri/r200/r200_lock.h106
-rw-r--r--src/mesa/drivers/dri/r200/r200_maos.h1
-rw-r--r--src/mesa/drivers/dri/r200/r200_maos_arrays.c381
-rw-r--r--src/mesa/drivers/dri/r200/r200_pixel.c130
-rw-r--r--src/mesa/drivers/dri/r200/r200_reg.h6
-rw-r--r--src/mesa/drivers/dri/r200/r200_sanity.c4
-rw-r--r--src/mesa/drivers/dri/r200/r200_span.c307
-rw-r--r--src/mesa/drivers/dri/r200/r200_state.c638
-rw-r--r--src/mesa/drivers/dri/r200/r200_state.h12
-rw-r--r--src/mesa/drivers/dri/r200/r200_state_init.c1289
-rw-r--r--src/mesa/drivers/dri/r200/r200_swtcl.c269
-rw-r--r--src/mesa/drivers/dri/r200/r200_swtcl.h11
-rw-r--r--src/mesa/drivers/dri/r200/r200_tcl.c143
-rw-r--r--src/mesa/drivers/dri/r200/r200_tex.c865
-rw-r--r--src/mesa/drivers/dri/r200/r200_tex.h7
-rw-r--r--src/mesa/drivers/dri/r200/r200_texmem.c530
-rw-r--r--src/mesa/drivers/dri/r200/r200_texstate.c859
-rw-r--r--src/mesa/drivers/dri/r200/r200_vertprog.c54
l---------src/mesa/drivers/dri/r200/radeon_bo_legacy.c1
l---------src/mesa/drivers/dri/r200/radeon_bo_legacy.h1
l---------src/mesa/drivers/dri/r200/radeon_bocs_wrapper.h1
l---------src/mesa/drivers/dri/r200/radeon_chipset.h1
l---------src/mesa/drivers/dri/r200/radeon_cmdbuf.h1
l---------src/mesa/drivers/dri/r200/radeon_common.c1
l---------src/mesa/drivers/dri/r200/radeon_common.h1
l---------src/mesa/drivers/dri/r200/radeon_common_context.c1
l---------src/mesa/drivers/dri/r200/radeon_common_context.h1
l---------src/mesa/drivers/dri/r200/radeon_cs_legacy.c1
l---------src/mesa/drivers/dri/r200/radeon_cs_legacy.h1
l---------src/mesa/drivers/dri/r200/radeon_cs_space_drm.c1
l---------src/mesa/drivers/dri/r200/radeon_debug.c1
l---------src/mesa/drivers/dri/r200/radeon_debug.h1
l---------src/mesa/drivers/dri/r200/radeon_dma.c1
l---------src/mesa/drivers/dri/r200/radeon_dma.h1
l---------src/mesa/drivers/dri/r200/radeon_fbo.c1
l---------src/mesa/drivers/dri/r200/radeon_lock.c1
l---------src/mesa/drivers/dri/r200/radeon_lock.h1
l---------src/mesa/drivers/dri/r200/radeon_mipmap_tree.c1
l---------src/mesa/drivers/dri/r200/radeon_mipmap_tree.h1
l---------src/mesa/drivers/dri/r200/radeon_queryobj.c1
l---------src/mesa/drivers/dri/r200/radeon_queryobj.h1
l---------src/mesa/drivers/dri/r200/radeon_screen.c1
l---------src/mesa/drivers/dri/r200/radeon_screen.h1
l---------src/mesa/drivers/dri/r200/radeon_span.c1
l---------src/mesa/drivers/dri/r200/radeon_span.h1
l---------src/mesa/drivers/dri/r200/radeon_texture.c1
l---------src/mesa/drivers/dri/r200/radeon_texture.h1
l---------src/mesa/drivers/dri/r200/server/radeon.h1
l---------src/mesa/drivers/dri/r200/server/radeon_dri.c1
l---------src/mesa/drivers/dri/r200/server/radeon_dri.h1
l---------src/mesa/drivers/dri/r200/server/radeon_egl.c1
l---------src/mesa/drivers/dri/r200/server/radeon_macros.h1
l---------src/mesa/drivers/dri/r200/server/radeon_reg.h1
-rw-r--r--src/mesa/drivers/dri/r300/.gitignore4
-rw-r--r--src/mesa/drivers/dri/r300/Makefile78
-rw-r--r--src/mesa/drivers/dri/r300/compiler/Makefile75
-rw-r--r--src/mesa/drivers/dri/r300/compiler/memory_pool.c95
-rw-r--r--src/mesa/drivers/dri/r300/compiler/memory_pool.h49
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog.c416
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog.h49
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c (renamed from src/mesa/drivers/dri/r300/r300_fragprog_emit.c)216
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c (renamed from src/mesa/drivers/dri/r300/r300_fragprog_swizzle.c)40
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.h (renamed from src/mesa/drivers/dri/r300/r300_fragprog_swizzle.h)0
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c149
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c655
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r3xx_vertprog_dump.c177
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r500_fragprog.c449
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r500_fragprog.h (renamed from src/mesa/drivers/dri/r300/r500_fragprog.h)29
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c (renamed from src/mesa/drivers/dri/r300/r500_fragprog_emit.c)84
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_code.c170
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_code.h207
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler.c262
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler.h108
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_nqssadce.c (renamed from src/mesa/drivers/dri/r300/radeon_nqssadce.c)184
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_nqssadce.h (renamed from src/mesa/drivers/dri/r300/radeon_nqssadce.h)19
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program.c187
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program.h (renamed from src/mesa/drivers/dri/r300/radeon_program.h)76
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c695
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_alu.h (renamed from src/mesa/drivers/dri/r300/radeon_program_alu.h)21
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c (renamed from src/mesa/drivers/dri/r300/radeon_program_pair.c)324
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h (renamed from src/mesa/drivers/dri/r300/radeon_program_pair.h)37
-rw-r--r--src/mesa/drivers/dri/r300/r300_cmdbuf.c953
-rw-r--r--src/mesa/drivers/dri/r300/r300_cmdbuf.h81
-rw-r--r--src/mesa/drivers/dri/r300/r300_context.c659
-rw-r--r--src/mesa/drivers/dri/r300/r300_context.h784
-rw-r--r--src/mesa/drivers/dri/r300/r300_draw.c718
-rw-r--r--src/mesa/drivers/dri/r300/r300_emit.c483
-rw-r--r--src/mesa/drivers/dri/r300/r300_emit.h225
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog.c686
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog.h132
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog_common.c263
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog_common.h37
-rw-r--r--src/mesa/drivers/dri/r300/r300_ioctl.c1118
-rw-r--r--src/mesa/drivers/dri/r300/r300_ioctl.h16
-rw-r--r--src/mesa/drivers/dri/r300/r300_mem.c385
-rw-r--r--src/mesa/drivers/dri/r300/r300_mem.h37
-rw-r--r--src/mesa/drivers/dri/r300/r300_reg.h146
-rw-r--r--src/mesa/drivers/dri/r300/r300_render.c499
-rw-r--r--src/mesa/drivers/dri/r300/r300_render.h69
-rw-r--r--src/mesa/drivers/dri/r300/r300_shader.c119
-rw-r--r--src/mesa/drivers/dri/r300/r300_state.c1616
-rw-r--r--src/mesa/drivers/dri/r300/r300_state.h28
-rw-r--r--src/mesa/drivers/dri/r300/r300_swtcl.c689
-rw-r--r--src/mesa/drivers/dri/r300/r300_swtcl.h20
-rw-r--r--src/mesa/drivers/dri/r300/r300_tex.c881
-rw-r--r--src/mesa/drivers/dri/r300/r300_tex.h13
-rw-r--r--src/mesa/drivers/dri/r300/r300_texmem.c567
-rw-r--r--src/mesa/drivers/dri/r300/r300_texstate.c615
-rw-r--r--src/mesa/drivers/dri/r300/r300_vertprog.c1563
-rw-r--r--src/mesa/drivers/dri/r300/r300_vertprog.h28
-rw-r--r--src/mesa/drivers/dri/r300/r500_fragprog.c700
l---------src/mesa/drivers/dri/r300/radeon_bo_legacy.c1
l---------src/mesa/drivers/dri/r300/radeon_bo_legacy.h1
l---------src/mesa/drivers/dri/r300/radeon_bocs_wrapper.h1
l---------src/mesa/drivers/dri/r300/radeon_buffer_objects.c1
l---------src/mesa/drivers/dri/r300/radeon_buffer_objects.h1
l---------src/mesa/drivers/dri/r300/radeon_chipset.h1
l---------src/mesa/drivers/dri/r300/radeon_cmdbuf.h1
l---------src/mesa/drivers/dri/r300/radeon_common.c1
l---------src/mesa/drivers/dri/r300/radeon_common.h1
l---------src/mesa/drivers/dri/r300/radeon_common_context.c1
l---------src/mesa/drivers/dri/r300/radeon_common_context.h1
-rw-r--r--src/mesa/drivers/dri/r300/radeon_context.c330
-rw-r--r--src/mesa/drivers/dri/r300/radeon_context.h159
l---------src/mesa/drivers/dri/r300/radeon_cs_legacy.c1
l---------src/mesa/drivers/dri/r300/radeon_cs_legacy.h1
l---------src/mesa/drivers/dri/r300/radeon_cs_space_drm.c1
l---------src/mesa/drivers/dri/r300/radeon_debug.c1
l---------src/mesa/drivers/dri/r300/radeon_debug.h1
l---------src/mesa/drivers/dri/r300/radeon_dma.c1
l---------src/mesa/drivers/dri/r300/radeon_dma.h1
l---------src/mesa/drivers/dri/r300/radeon_fbo.c1
-rw-r--r--src/mesa/drivers/dri/r300/radeon_ioctl.c396
-rw-r--r--src/mesa/drivers/dri/r300/radeon_ioctl.h57
l---------[-rw-r--r--]src/mesa/drivers/dri/r300/radeon_lock.c138
l---------[-rw-r--r--]src/mesa/drivers/dri/r300/radeon_lock.h116
l---------src/mesa/drivers/dri/r300/radeon_mipmap_tree.c1
l---------src/mesa/drivers/dri/r300/radeon_mipmap_tree.h1
-rw-r--r--src/mesa/drivers/dri/r300/radeon_program.c128
-rw-r--r--src/mesa/drivers/dri/r300/radeon_program_alu.c658
l---------src/mesa/drivers/dri/r300/radeon_queryobj.c1
l---------src/mesa/drivers/dri/r300/radeon_queryobj.h1
l---------src/mesa/drivers/dri/r300/radeon_screen.c1
l---------src/mesa/drivers/dri/r300/radeon_screen.h1
l---------[-rw-r--r--]src/mesa/drivers/dri/r300/radeon_span.c350
l---------src/mesa/drivers/dri/r300/radeon_span.h1
-rw-r--r--src/mesa/drivers/dri/r300/radeon_state.c244
l---------src/mesa/drivers/dri/r300/radeon_texture.c1
l---------src/mesa/drivers/dri/r300/radeon_texture.h1
l---------src/mesa/drivers/dri/r300/server/radeon.h1
l---------src/mesa/drivers/dri/r300/server/radeon_dri.c1
l---------src/mesa/drivers/dri/r300/server/radeon_dri.h1
l---------src/mesa/drivers/dri/r300/server/radeon_egl.c1
l---------src/mesa/drivers/dri/r300/server/radeon_macros.h1
l---------src/mesa/drivers/dri/r300/server/radeon_reg.h1
-rwxr-xr-xsrc/mesa/drivers/dri/r600/Lindent2
-rw-r--r--src/mesa/drivers/dri/r600/Makefile79
-rw-r--r--src/mesa/drivers/dri/r600/defaultendian.h38
-rw-r--r--src/mesa/drivers/dri/r600/r600_cmdbuf.c514
-rw-r--r--src/mesa/drivers/dri/r600/r600_cmdbuf.h212
-rw-r--r--src/mesa/drivers/dri/r600/r600_context.c396
-rw-r--r--src/mesa/drivers/dri/r600/r600_context.h208
-rw-r--r--src/mesa/drivers/dri/r600/r600_emit.c117
-rw-r--r--src/mesa/drivers/dri/r600/r600_emit.h (renamed from src/mesa/drivers/dri/r300/radeon_state.h)34
-rw-r--r--src/mesa/drivers/dri/r600/r600_reg.h121
-rw-r--r--src/mesa/drivers/dri/r600/r600_reg_auto_r6xx.h3087
-rw-r--r--src/mesa/drivers/dri/r600/r600_reg_r6xx.h492
-rw-r--r--src/mesa/drivers/dri/r600/r600_reg_r7xx.h149
-rw-r--r--src/mesa/drivers/dri/r600/r600_tex.c440
-rw-r--r--src/mesa/drivers/dri/r600/r600_tex.h (renamed from src/mesa/drivers/dri/r200/r200_span.h)32
-rw-r--r--src/mesa/drivers/dri/r600/r600_texstate.c1003
-rw-r--r--src/mesa/drivers/dri/r600/r700_assembler.c4118
-rw-r--r--src/mesa/drivers/dri/r600/r700_assembler.h512
-rw-r--r--src/mesa/drivers/dri/r600/r700_chip.c1274
-rw-r--r--src/mesa/drivers/dri/r600/r700_chip.h503
-rw-r--r--src/mesa/drivers/dri/r600/r700_chipoffset.h693
-rw-r--r--src/mesa/drivers/dri/r600/r700_clear.c118
-rw-r--r--src/mesa/drivers/dri/r600/r700_clear.h33
-rw-r--r--src/mesa/drivers/dri/r600/r700_debug.c60
-rw-r--r--src/mesa/drivers/dri/r600/r700_debug.h39
-rw-r--r--src/mesa/drivers/dri/r600/r700_driconf.h33
-rw-r--r--src/mesa/drivers/dri/r600/r700_fragprog.c476
-rw-r--r--src/mesa/drivers/dri/r600/r700_fragprog.h66
-rw-r--r--src/mesa/drivers/dri/r600/r700_ioctl.c50
-rw-r--r--src/mesa/drivers/dri/r600/r700_ioctl.h35
-rw-r--r--src/mesa/drivers/dri/r600/r700_oglprog.c149
-rw-r--r--src/mesa/drivers/dri/r600/r700_oglprog.h34
-rw-r--r--src/mesa/drivers/dri/r600/r700_render.c480
-rw-r--r--src/mesa/drivers/dri/r600/r700_shader.c527
-rw-r--r--src/mesa/drivers/dri/r600/r700_shader.h150
-rw-r--r--src/mesa/drivers/dri/r600/r700_shaderinst.c224
-rw-r--r--src/mesa/drivers/dri/r600/r700_shaderinst.h321
-rw-r--r--src/mesa/drivers/dri/r600/r700_state.c1810
-rw-r--r--src/mesa/drivers/dri/r600/r700_state.h46
-rw-r--r--src/mesa/drivers/dri/r600/r700_vertprog.c474
-rw-r--r--src/mesa/drivers/dri/r600/r700_vertprog.h94
l---------src/mesa/drivers/dri/r600/radeon_bo_legacy.c1
l---------src/mesa/drivers/dri/r600/radeon_bo_legacy.h1
l---------src/mesa/drivers/dri/r600/radeon_bocs_wrapper.h1
l---------src/mesa/drivers/dri/r600/radeon_chipset.h1
l---------src/mesa/drivers/dri/r600/radeon_cmdbuf.h1
l---------src/mesa/drivers/dri/r600/radeon_common.c1
l---------src/mesa/drivers/dri/r600/radeon_common.h1
l---------src/mesa/drivers/dri/r600/radeon_common_context.c1
l---------src/mesa/drivers/dri/r600/radeon_common_context.h1
l---------src/mesa/drivers/dri/r600/radeon_cs_legacy.c1
l---------src/mesa/drivers/dri/r600/radeon_cs_legacy.h1
l---------src/mesa/drivers/dri/r600/radeon_cs_space_drm.c1
l---------src/mesa/drivers/dri/r600/radeon_debug.c1
l---------src/mesa/drivers/dri/r600/radeon_debug.h1
l---------src/mesa/drivers/dri/r600/radeon_dma.c1
l---------src/mesa/drivers/dri/r600/radeon_dma.h1
l---------src/mesa/drivers/dri/r600/radeon_fbo.c1
l---------src/mesa/drivers/dri/r600/radeon_lock.c1
l---------src/mesa/drivers/dri/r600/radeon_lock.h1
l---------src/mesa/drivers/dri/r600/radeon_mipmap_tree.c1
l---------src/mesa/drivers/dri/r600/radeon_mipmap_tree.h1
l---------src/mesa/drivers/dri/r600/radeon_queryobj.c1
l---------src/mesa/drivers/dri/r600/radeon_queryobj.h1
l---------src/mesa/drivers/dri/r600/radeon_screen.c1
l---------src/mesa/drivers/dri/r600/radeon_screen.h1
l---------src/mesa/drivers/dri/r600/radeon_span.c1
l---------src/mesa/drivers/dri/r600/radeon_span.h1
l---------src/mesa/drivers/dri/r600/radeon_texture.c1
l---------src/mesa/drivers/dri/r600/radeon_texture.h1
l---------src/mesa/drivers/dri/r600/server/radeon.h1
l---------src/mesa/drivers/dri/r600/server/radeon_dri.c1
l---------src/mesa/drivers/dri/r600/server/radeon_dri.h1
l---------src/mesa/drivers/dri/r600/server/radeon_egl.c1
l---------src/mesa/drivers/dri/r600/server/radeon_macros.h1
l---------src/mesa/drivers/dri/r600/server/radeon_reg.h1
-rw-r--r--src/mesa/drivers/dri/r600/sq_micro_reg.h2008
-rw-r--r--src/mesa/drivers/dri/radeon/Makefile34
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_bo_drm.h219
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_bo_legacy.c926
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_bo_legacy.h50
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_bocs_wrapper.h99
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_buffer_objects.c222
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_buffer_objects.h52
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_chipset.h156
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_cmdbuf.h121
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common.c1349
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common.h87
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.c805
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.h594
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_compat.c301
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_context.c469
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_context.h386
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_cs_drm.h246
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_cs_legacy.c409
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_cs_legacy.h40
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_cs_space_drm.c234
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_debug.c107
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_debug.h169
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_dma.c476
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_dma.h58
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_fbo.c599
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_ioctl.c1359
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_ioctl.h137
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_lighting.c14
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_lock.c128
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_lock.h83
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_maos.h1
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_maos_arrays.c464
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h3
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_maos_verts.c36
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c421
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h101
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_queryobj.c235
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_queryobj.h55
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_sanity.c6
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_sanity.h2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.c1268
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.h13
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_span.c589
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_span.h3
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_state.c654
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_state.h15
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_state_init.c989
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_swtcl.c280
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_swtcl.h3
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tcl.c148
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tex.c544
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_tex.h8
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texmem.c404
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texstate.c829
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texture.c1052
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texture.h122
-rw-r--r--src/mesa/drivers/dri/radeon/server/radeon_reg.h10
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_context.c2
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_state.c5
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_tex.c21
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_xmesa.c5
-rw-r--r--src/mesa/drivers/dri/savage/savage_xmesa.c32
-rw-r--r--src/mesa/drivers/dri/savage/savagecontext.h1
-rw-r--r--src/mesa/drivers/dri/savage/savagestate.c4
-rw-r--r--src/mesa/drivers/dri/savage/savagetex.c6
-rw-r--r--src/mesa/drivers/dri/sis/sis_alloc.c8
-rw-r--r--src/mesa/drivers/dri/sis/sis_context.c8
-rw-r--r--src/mesa/drivers/dri/sis/sis_screen.c8
-rw-r--r--src/mesa/drivers/dri/sis/sis_texstate.c15
-rw-r--r--src/mesa/drivers/dri/sis/sis_tris.c2
-rw-r--r--src/mesa/drivers/dri/swrast/swrast.c94
-rw-r--r--src/mesa/drivers/dri/swrast/swrast_priv.h10
-rw-r--r--src/mesa/drivers/dri/swrast/swrast_span.c72
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_context.c16
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_dd.c8
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_pixels.c2
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_render.c2
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_screen.c21
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_state.c2
-rw-r--r--src/mesa/drivers/dri/trident/trident_context.c5
-rw-r--r--src/mesa/drivers/dri/trident/trident_vb.c2
-rw-r--r--src/mesa/drivers/dri/unichrome/via_context.c6
-rw-r--r--src/mesa/drivers/dri/unichrome/via_screen.c6
-rw-r--r--src/mesa/drivers/dri/unichrome/via_state.c2
-rw-r--r--src/mesa/drivers/fbdev/glfbdev.c2
-rw-r--r--src/mesa/drivers/ggi/default/stubs.c2
-rw-r--r--src/mesa/drivers/glide/fxapi.c4
-rw-r--r--src/mesa/drivers/glide/fxdd.c10
-rw-r--r--src/mesa/drivers/glslcompiler/glslcompiler.c53
-rw-r--r--src/mesa/drivers/osmesa/Makefile36
-rw-r--r--src/mesa/drivers/osmesa/osmesa.c2
-rw-r--r--src/mesa/drivers/windows/gdi/mesa.def3
-rw-r--r--src/mesa/drivers/windows/gdi/wmesa.c79
-rw-r--r--src/mesa/drivers/windows/gldirect/dglcontext.c1
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c2
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c1
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c1
-rw-r--r--src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c1
-rw-r--r--src/mesa/drivers/x11/Makefile3
-rw-r--r--src/mesa/drivers/x11/fakeglx.c47
-rw-r--r--src/mesa/drivers/x11/glxapi.c6
-rw-r--r--src/mesa/drivers/x11/xm_api.c34
-rw-r--r--src/mesa/drivers/x11/xm_buffer.c1
-rw-r--r--src/mesa/drivers/x11/xm_dd.c33
-rw-r--r--src/mesa/drivers/x11/xm_span.c18
-rw-r--r--src/mesa/drivers/x11/xmesaP.h4
-rw-r--r--src/mesa/es/Makefile115
-rw-r--r--src/mesa/es/glapi/Makefile65
-rw-r--r--src/mesa/es/glapi/base1_API.xml760
-rw-r--r--src/mesa/es/glapi/base2_API.xml533
-rw-r--r--src/mesa/es/glapi/es1_API.xml1100
-rw-r--r--src/mesa/es/glapi/es1_COMPAT.xml130
-rw-r--r--src/mesa/es/glapi/es1_EXT.xml693
-rw-r--r--src/mesa/es/glapi/es2_API.xml294
-rw-r--r--src/mesa/es/glapi/es2_COMPAT.xml363
-rw-r--r--src/mesa/es/glapi/es2_EXT.xml122
-rw-r--r--src/mesa/es/glapi/es_COMPAT.xml2650
-rw-r--r--src/mesa/es/glapi/es_EXT.xml97
-rw-r--r--src/mesa/es/glapi/gl_compare.py354
-rw-r--r--src/mesa/es/glapi/gl_parse_header.py450
-rw-r--r--src/mesa/es/main/APIspec.txt2974
-rw-r--r--src/mesa/es/main/apiutil.py1117
-rw-r--r--src/mesa/es/main/drawtex.c149
-rw-r--r--src/mesa/es/main/drawtex.h79
-rw-r--r--src/mesa/es/main/eglimage.c115
-rw-r--r--src/mesa/es/main/eglimage.h61
-rw-r--r--src/mesa/es/main/es1_special8
-rw-r--r--src/mesa/es/main/es2_special5
-rw-r--r--src/mesa/es/main/es_cpaltex.c240
-rw-r--r--src/mesa/es/main/es_fbo.c37
-rw-r--r--src/mesa/es/main/es_generator.py782
-rw-r--r--src/mesa/es/main/es_query_matrix.c199
-rw-r--r--src/mesa/es/main/get_gen.py785
-rw-r--r--src/mesa/es/main/mfeatures.h113
-rw-r--r--src/mesa/es/main/specials_es1.c186
-rw-r--r--src/mesa/es/main/specials_es2.c173
-rw-r--r--src/mesa/es/main/stubs.c138
-rw-r--r--src/mesa/es/sources.mak159
-rw-r--r--src/mesa/gl.pc.in2
-rw-r--r--src/mesa/glapi/ARB_copy_buffer.xml24
-rw-r--r--src/mesa/glapi/ARB_depth_clamp.xml12
-rw-r--r--src/mesa/glapi/ARB_draw_elements_base_vertex.xml40
-rw-r--r--src/mesa/glapi/ARB_framebuffer_object.xml269
-rw-r--r--src/mesa/glapi/ARB_map_buffer_range.xml34
-rw-r--r--src/mesa/glapi/ARB_seamless_cube_map.xml12
-rw-r--r--src/mesa/glapi/ARB_sync.xml82
-rw-r--r--src/mesa/glapi/ARB_vertex_array_object.xml34
-rw-r--r--src/mesa/glapi/EXT_framebuffer_object.xml38
-rw-r--r--src/mesa/glapi/EXT_provoking_vertex.xml22
-rw-r--r--src/mesa/glapi/EXT_texture_array.xml41
-rw-r--r--src/mesa/glapi/Makefile10
-rw-r--r--src/mesa/glapi/descrip.mms39
-rw-r--r--src/mesa/glapi/dispatch.h595
-rw-r--r--src/mesa/glapi/extension_helper.py13
-rw-r--r--src/mesa/glapi/glX_proto_recv.py2
-rw-r--r--src/mesa/glapi/glX_proto_send.py6
-rw-r--r--src/mesa/glapi/gl_API.xml182
-rw-r--r--src/mesa/glapi/gl_SPARC_asm.py228
-rw-r--r--src/mesa/glapi/gl_enums.py26
-rw-r--r--src/mesa/glapi/gl_offsets.py25
-rw-r--r--src/mesa/glapi/gl_procs.py30
-rw-r--r--src/mesa/glapi/gl_table.py67
-rw-r--r--src/mesa/glapi/gl_x86-64_asm.py2
-rw-r--r--src/mesa/glapi/gl_x86_asm.py2
-rw-r--r--src/mesa/glapi/glapi.c187
-rw-r--r--src/mesa/glapi/glapi.h4
-rw-r--r--src/mesa/glapi/glapi_getproc.c97
-rw-r--r--src/mesa/glapi/glapioffsets.h470
-rw-r--r--src/mesa/glapi/glapitable.h443
-rw-r--r--src/mesa/glapi/glapitemp.h494
-rw-r--r--src/mesa/glapi/glprocs.h1229
-rw-r--r--src/mesa/glapi/glthread.c59
-rw-r--r--src/mesa/glapi/glthread.h104
-rw-r--r--src/mesa/main/accum.c14
-rw-r--r--src/mesa/main/accum.h36
-rw-r--r--src/mesa/main/api_arrayelt.c60
-rw-r--r--src/mesa/main/api_arrayelt.h47
-rw-r--r--src/mesa/main/api_exec.c271
-rw-r--r--src/mesa/main/api_loopback.c7
-rw-r--r--src/mesa/main/api_loopback.h14
-rw-r--r--src/mesa/main/api_noop.c145
-rw-r--r--src/mesa/main/api_noop.h20
-rw-r--r--src/mesa/main/api_validate.c187
-rw-r--r--src/mesa/main/api_validate.h4
-rw-r--r--src/mesa/main/arrayobj.c442
-rw-r--r--src/mesa/main/arrayobj.h29
-rw-r--r--src/mesa/main/attrib.c506
-rw-r--r--src/mesa/main/attrib.h36
-rw-r--r--src/mesa/main/bufferobj.c839
-rw-r--r--src/mesa/main/bufferobj.h106
-rw-r--r--src/mesa/main/buffers.c33
-rw-r--r--src/mesa/main/clip.c1
-rw-r--r--src/mesa/main/colormac.h9
-rw-r--r--src/mesa/main/colortab.c85
-rw-r--r--src/mesa/main/colortab.h41
-rw-r--r--src/mesa/main/compiler.h484
-rw-r--r--src/mesa/main/config.h90
-rw-r--r--src/mesa/main/context.c830
-rw-r--r--src/mesa/main/context.h17
-rw-r--r--src/mesa/main/convolve.c213
-rw-r--r--src/mesa/main/convolve.h67
-rw-r--r--src/mesa/main/cpuinfo.c109
-rw-r--r--src/mesa/main/cpuinfo.h (renamed from src/mesa/math/mathmod.h)34
-rw-r--r--src/mesa/main/dd.h115
-rw-r--r--src/mesa/main/debug.c223
-rw-r--r--src/mesa/main/debug.h12
-rw-r--r--src/mesa/main/depthstencil.c8
-rw-r--r--src/mesa/main/dispatch.c1
-rw-r--r--src/mesa/main/dlist.c714
-rw-r--r--src/mesa/main/dlist.h71
-rw-r--r--src/mesa/main/dlopen.c8
-rw-r--r--src/mesa/main/drawpix.c250
-rw-r--r--src/mesa/main/drawpix.h30
-rw-r--r--src/mesa/main/enable.c72
-rw-r--r--src/mesa/main/enums.c6257
-rw-r--r--src/mesa/main/enums.h6
-rw-r--r--src/mesa/main/eval.c39
-rw-r--r--src/mesa/main/eval.h49
-rw-r--r--src/mesa/main/execmem.c4
-rw-r--r--src/mesa/main/extensions.c212
-rw-r--r--src/mesa/main/fbobject.c615
-rw-r--r--src/mesa/main/fbobject.h5
-rw-r--r--src/mesa/main/feedback.c124
-rw-r--r--src/mesa/main/feedback.h91
-rw-r--r--src/mesa/main/ffvertex_prog.c536
-rw-r--r--src/mesa/main/fog.c2
-rw-r--r--src/mesa/main/framebuffer.c115
-rw-r--r--src/mesa/main/framebuffer.h3
-rw-r--r--src/mesa/main/get.c2098
-rw-r--r--src/mesa/main/get.h3
-rw-r--r--src/mesa/main/get_gen.py133
-rw-r--r--src/mesa/main/getstring.c45
-rw-r--r--src/mesa/main/glheader.h253
-rw-r--r--src/mesa/main/hash.c18
-rw-r--r--src/mesa/main/hint.c4
-rw-r--r--src/mesa/main/histogram.c91
-rw-r--r--src/mesa/main/histogram.h22
-rw-r--r--src/mesa/main/image.c894
-rw-r--r--src/mesa/main/image.h41
-rw-r--r--src/mesa/main/imports.c250
-rw-r--r--src/mesa/main/imports.h199
-rw-r--r--src/mesa/main/light.c77
-rw-r--r--src/mesa/main/light.h14
-rw-r--r--src/mesa/main/macros.h40
-rw-r--r--src/mesa/main/matrix.c170
-rw-r--r--src/mesa/main/matrix.h25
-rw-r--r--src/mesa/main/mfeatures.h49
-rw-r--r--src/mesa/main/mipmap.c118
-rw-r--r--src/mesa/main/mtypes.h979
-rw-r--r--src/mesa/main/multisample.c5
-rw-r--r--src/mesa/main/pixel.c265
-rw-r--r--src/mesa/main/pixel.h25
-rw-r--r--src/mesa/main/pixelstore.c9
-rw-r--r--src/mesa/main/polygon.c75
-rw-r--r--src/mesa/main/queryobj.c78
-rw-r--r--src/mesa/main/queryobj.h63
-rw-r--r--src/mesa/main/rastpos.c66
-rw-r--r--src/mesa/main/rastpos.h27
-rw-r--r--src/mesa/main/readpix.c58
-rw-r--r--src/mesa/main/renderbuffer.c10
-rw-r--r--src/mesa/main/shaders.c78
-rw-r--r--src/mesa/main/shared.c370
-rw-r--r--src/mesa/main/shared.h (renamed from src/mesa/x86/x86.h)20
-rw-r--r--src/mesa/main/simple_list.h5
-rw-r--r--src/mesa/main/sources2
-rw-r--r--src/mesa/main/state.c337
-rw-r--r--src/mesa/main/state.h14
-rw-r--r--src/mesa/main/stencil.c106
-rw-r--r--src/mesa/main/syncobj.c409
-rw-r--r--src/mesa/main/syncobj.h70
-rw-r--r--src/mesa/main/texcompress.c150
-rw-r--r--src/mesa/main/texcompress_fxt1.c49
-rw-r--r--src/mesa/main/texcompress_s3tc.c238
-rw-r--r--src/mesa/main/texenv.c1339
-rw-r--r--src/mesa/main/texenv.h11
-rw-r--r--src/mesa/main/texenvprogram.c700
-rw-r--r--src/mesa/main/texenvprogram.h2
-rw-r--r--src/mesa/main/texformat.c597
-rw-r--r--src/mesa/main/texformat.h52
-rw-r--r--src/mesa/main/texformat_tmp.h555
-rw-r--r--src/mesa/main/texgen.c610
-rw-r--r--src/mesa/main/texgen.h22
-rw-r--r--src/mesa/main/texgetimage.c581
-rw-r--r--src/mesa/main/texgetimage.h55
-rw-r--r--src/mesa/main/teximage.c942
-rw-r--r--src/mesa/main/teximage.h16
-rw-r--r--src/mesa/main/texobj.c282
-rw-r--r--src/mesa/main/texobj.h11
-rw-r--r--src/mesa/main/texparam.c1206
-rw-r--r--src/mesa/main/texrender.c55
-rw-r--r--src/mesa/main/texstate.c543
-rw-r--r--src/mesa/main/texstate.h18
-rw-r--r--src/mesa/main/texstore.c598
-rw-r--r--src/mesa/main/texstore.h19
-rw-r--r--src/mesa/main/varray.c333
-rw-r--r--src/mesa/main/varray.h56
-rw-r--r--src/mesa/main/version.h7
-rw-r--r--src/mesa/main/viewport.c180
-rw-r--r--src/mesa/main/viewport.h52
-rw-r--r--src/mesa/main/vtxfmt.c45
-rw-r--r--src/mesa/main/vtxfmt.h29
-rw-r--r--src/mesa/main/vtxfmt_tmp.h53
-rw-r--r--src/mesa/math/m_clip_tmp.h44
-rw-r--r--src/mesa/math/m_debug_clip.c31
-rw-r--r--src/mesa/math/m_debug_util.h4
-rw-r--r--src/mesa/math/m_debug_xform.c3
-rw-r--r--src/mesa/math/m_matrix.c26
-rw-r--r--src/mesa/math/m_matrix.h3
-rw-r--r--src/mesa/math/m_vector.c85
-rw-r--r--src/mesa/math/m_vector.h30
-rw-r--r--src/mesa/math/m_xform.c102
-rw-r--r--src/mesa/math/m_xform.h25
-rw-r--r--src/mesa/ppc/common_ppc.c2
-rw-r--r--src/mesa/shader/.gitignore1
-rw-r--r--src/mesa/shader/Makefile7
-rw-r--r--src/mesa/shader/arbprogparse.c3947
-rw-r--r--src/mesa/shader/arbprogram.c60
-rw-r--r--src/mesa/shader/arbprogram.syn2824
-rw-r--r--src/mesa/shader/arbprogram_syn.h1350
-rw-r--r--src/mesa/shader/atifragshader.h2
-rw-r--r--src/mesa/shader/grammar/descrip.mms42
-rw-r--r--src/mesa/shader/hash_table.c163
-rw-r--r--src/mesa/shader/hash_table.h117
-rw-r--r--src/mesa/shader/lex.yy.c3578
-rw-r--r--src/mesa/shader/nvfragparse.c317
-rw-r--r--src/mesa/shader/nvfragparse.h9
-rw-r--r--src/mesa/shader/nvprogram.c44
-rw-r--r--src/mesa/shader/nvvertparse.c175
-rw-r--r--src/mesa/shader/nvvertparse.h5
-rw-r--r--src/mesa/shader/prog_cache.c29
-rw-r--r--src/mesa/shader/prog_cache.h2
-rw-r--r--src/mesa/shader/prog_debug.c259
-rw-r--r--src/mesa/shader/prog_execute.c116
-rw-r--r--src/mesa/shader/prog_execute.h2
-rw-r--r--src/mesa/shader/prog_instruction.c61
-rw-r--r--src/mesa/shader/prog_instruction.h110
-rw-r--r--src/mesa/shader/prog_optimize.c832
-rw-r--r--src/mesa/shader/prog_optimize.h45
-rw-r--r--src/mesa/shader/prog_parameter.c66
-rw-r--r--src/mesa/shader/prog_parameter.h11
-rw-r--r--src/mesa/shader/prog_parameter_layout.c217
-rw-r--r--src/mesa/shader/prog_parameter_layout.h42
-rw-r--r--src/mesa/shader/prog_print.c595
-rw-r--r--src/mesa/shader/prog_print.h23
-rw-r--r--src/mesa/shader/prog_statevars.c223
-rw-r--r--src/mesa/shader/prog_statevars.h6
-rw-r--r--src/mesa/shader/prog_uniform.c4
-rw-r--r--src/mesa/shader/program.c124
-rw-r--r--src/mesa/shader/program.h2
-rw-r--r--src/mesa/shader/program_lexer.l493
-rw-r--r--src/mesa/shader/program_parse.tab.c5249
-rw-r--r--src/mesa/shader/program_parse.tab.h207
-rw-r--r--src/mesa/shader/program_parse.y2379
-rw-r--r--src/mesa/shader/program_parse_extra.c117
-rw-r--r--src/mesa/shader/program_parser.h266
-rw-r--r--src/mesa/shader/programopt.c129
-rw-r--r--src/mesa/shader/programopt.h2
-rw-r--r--src/mesa/shader/shader_api.c560
-rw-r--r--src/mesa/shader/shader_api.h8
-rw-r--r--src/mesa/shader/slang/library/slang_common_builtin.gc34
-rw-r--r--src/mesa/shader/slang/library/slang_common_builtin_gc.h234
-rw-r--r--src/mesa/shader/slang/library/slang_fragment_builtin.gc30
-rw-r--r--src/mesa/shader/slang/library/slang_fragment_builtin_gc.h177
-rw-r--r--src/mesa/shader/slang/library/slang_version_syn.h64
-rw-r--r--src/mesa/shader/slang/library/slang_vertex_builtin.gc28
-rw-r--r--src/mesa/shader/slang/library/slang_vertex_builtin_gc.h131
-rw-r--r--src/mesa/shader/slang/slang_builtin.c224
-rw-r--r--src/mesa/shader/slang/slang_builtin.h14
-rw-r--r--src/mesa/shader/slang/slang_codegen.c1474
-rw-r--r--src/mesa/shader/slang/slang_codegen.h17
-rw-r--r--src/mesa/shader/slang/slang_compile.c32
-rw-r--r--src/mesa/shader/slang/slang_compile_operation.c68
-rw-r--r--src/mesa/shader/slang/slang_compile_operation.h62
-rw-r--r--src/mesa/shader/slang/slang_compile_variable.h1
-rw-r--r--src/mesa/shader/slang/slang_emit.c114
-rw-r--r--src/mesa/shader/slang/slang_emit.h4
-rw-r--r--src/mesa/shader/slang/slang_ir.c13
-rw-r--r--src/mesa/shader/slang/slang_ir.h19
-rw-r--r--src/mesa/shader/slang/slang_link.c271
-rw-r--r--src/mesa/shader/slang/slang_log.c4
-rw-r--r--src/mesa/shader/slang/slang_preprocess.c120
-rw-r--r--src/mesa/shader/slang/slang_print.c10
-rw-r--r--src/mesa/shader/slang/slang_typeinfo.c1
-rw-r--r--src/mesa/shader/slang/slang_vartable.c59
-rw-r--r--src/mesa/shader/symbol_table.c350
-rw-r--r--src/mesa/shader/symbol_table.h55
-rw-r--r--src/mesa/sources.mak (renamed from src/mesa/sources)108
-rw-r--r--src/mesa/sparc/clip.S32
-rw-r--r--src/mesa/sparc/glapi_sparc.S1654
-rw-r--r--src/mesa/sparc/norm.S25
-rw-r--r--src/mesa/sparc/sparc.c43
-rw-r--r--src/mesa/sparc/sparc.h1
-rw-r--r--src/mesa/state_tracker/Makefile2
-rw-r--r--src/mesa/state_tracker/st_api.c33
-rw-r--r--src/mesa/state_tracker/st_atom.c192
-rw-r--r--src/mesa/state_tracker/st_atom.h66
-rw-r--r--src/mesa/state_tracker/st_atom_blend.c232
-rw-r--r--src/mesa/state_tracker/st_atom_clip.c71
-rw-r--r--src/mesa/state_tracker/st_atom_constbuf.c142
-rw-r--r--src/mesa/state_tracker/st_atom_constbuf.h38
-rw-r--r--src/mesa/state_tracker/st_atom_depth.c155
-rw-r--r--src/mesa/state_tracker/st_atom_framebuffer.c184
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c473
-rw-r--r--src/mesa/state_tracker/st_atom_rasterizer.c276
-rw-r--r--src/mesa/state_tracker/st_atom_sampler.c250
-rw-r--r--src/mesa/state_tracker/st_atom_scissor.c92
-rw-r--r--src/mesa/state_tracker/st_atom_shader.c377
-rw-r--r--src/mesa/state_tracker/st_atom_shader.h38
-rw-r--r--src/mesa/state_tracker/st_atom_stipple.c91
-rw-r--r--src/mesa/state_tracker/st_atom_texture.c161
-rw-r--r--src/mesa/state_tracker/st_atom_viewport.c91
-rw-r--r--src/mesa/state_tracker/st_cache.h68
-rw-r--r--src/mesa/state_tracker/st_cb_accum.c333
-rw-r--r--src/mesa/state_tracker/st_cb_accum.h39
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.c819
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.h52
-rw-r--r--src/mesa/state_tracker/st_cb_blit.c184
-rw-r--r--src/mesa/state_tracker/st_cb_blit.h46
-rw-r--r--src/mesa/state_tracker/st_cb_bufferobjects.c354
-rw-r--r--src/mesa/state_tracker/st_cb_bufferobjects.h58
-rw-r--r--src/mesa/state_tracker/st_cb_clear.c495
-rw-r--r--src/mesa/state_tracker/st_cb_clear.h49
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c1146
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.h39
-rw-r--r--src/mesa/state_tracker/st_cb_drawtex.c297
-rw-r--r--src/mesa/state_tracker/st_cb_drawtex.h18
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.c664
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.h75
-rw-r--r--src/mesa/state_tracker/st_cb_feedback.c309
-rw-r--r--src/mesa/state_tracker/st_cb_feedback.h37
-rw-r--r--src/mesa/state_tracker/st_cb_flush.c176
-rw-r--r--src/mesa/state_tracker/st_cb_flush.h38
-rw-r--r--src/mesa/state_tracker/st_cb_get.c97
-rw-r--r--src/mesa/state_tracker/st_cb_get.h37
-rw-r--r--src/mesa/state_tracker/st_cb_program.c266
-rw-r--r--src/mesa/state_tracker/st_cb_program.h39
-rw-r--r--src/mesa/state_tracker/st_cb_queryobj.c171
-rw-r--r--src/mesa/state_tracker/st_cb_queryobj.h36
-rw-r--r--src/mesa/state_tracker/st_cb_rasterpos.c262
-rw-r--r--src/mesa/state_tracker/st_cb_rasterpos.h33
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.c544
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.h46
-rw-r--r--src/mesa/state_tracker/st_cb_strings.c73
-rw-r--r--src/mesa/state_tracker/st_cb_strings.h38
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c1993
-rw-r--r--src/mesa/state_tracker/st_cb_texture.h48
-rw-r--r--src/mesa/state_tracker/st_cb_viewport.c53
-rw-r--r--src/mesa/state_tracker/st_cb_viewport.h29
-rw-r--r--src/mesa/state_tracker/st_context.c350
-rw-r--r--src/mesa/state_tracker/st_context.h245
-rw-r--r--src/mesa/state_tracker/st_debug.c70
-rw-r--r--src/mesa/state_tracker/st_debug.h36
-rw-r--r--src/mesa/state_tracker/st_draw.c719
-rw-r--r--src/mesa/state_tracker/st_draw.h85
-rw-r--r--src/mesa/state_tracker/st_draw_feedback.c274
-rw-r--r--src/mesa/state_tracker/st_extensions.c308
-rw-r--r--src/mesa/state_tracker/st_extensions.h38
-rw-r--r--src/mesa/state_tracker/st_format.c742
-rw-r--r--src/mesa/state_tracker/st_format.h83
-rw-r--r--src/mesa/state_tracker/st_framebuffer.c409
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c214
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.h46
-rw-r--r--src/mesa/state_tracker/st_inlines.h154
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c1202
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.h67
-rw-r--r--src/mesa/state_tracker/st_program.c597
-rw-r--r--src/mesa/state_tracker/st_program.h158
-rw-r--r--src/mesa/state_tracker/st_public.h129
-rw-r--r--src/mesa/state_tracker/st_texture.c583
-rw-r--r--src/mesa/state_tracker/st_texture.h184
-rw-r--r--src/mesa/swrast/s_accum.c14
-rw-r--r--src/mesa/swrast/s_accum.h11
-rw-r--r--src/mesa/swrast/s_atifragshader.c11
-rw-r--r--src/mesa/swrast/s_bitmap.c18
-rw-r--r--src/mesa/swrast/s_blit.c194
-rw-r--r--src/mesa/swrast/s_clear.c (renamed from src/mesa/swrast/s_buffers.c)13
-rw-r--r--src/mesa/swrast/s_context.c100
-rw-r--r--src/mesa/swrast/s_context.h83
-rw-r--r--src/mesa/swrast/s_copypix.c9
-rw-r--r--src/mesa/swrast/s_depth.c27
-rw-r--r--src/mesa/swrast/s_depth.h2
-rw-r--r--src/mesa/swrast/s_drawpix.c77
-rw-r--r--src/mesa/swrast/s_feedback.c17
-rw-r--r--src/mesa/swrast/s_feedback.h45
-rw-r--r--src/mesa/swrast/s_fog.c4
-rw-r--r--src/mesa/swrast/s_fragprog.c91
-rw-r--r--src/mesa/swrast/s_imaging.c42
-rw-r--r--src/mesa/swrast/s_points.c33
-rw-r--r--src/mesa/swrast/s_readpix.c16
-rw-r--r--src/mesa/swrast/s_span.c145
-rw-r--r--src/mesa/swrast/s_span.h9
-rw-r--r--src/mesa/swrast/s_stencil.c15
-rw-r--r--src/mesa/swrast/s_texcombine.c1278
-rw-r--r--src/mesa/swrast/s_texfilter.c1109
-rw-r--r--src/mesa/swrast/s_texstore.c15
-rw-r--r--src/mesa/swrast/s_triangle.c50
-rw-r--r--src/mesa/swrast/swrast.h65
-rw-r--r--src/mesa/swrast/swrast_features.h142
-rw-r--r--src/mesa/swrast_setup/ss_triangle.c119
-rw-r--r--src/mesa/swrast_setup/ss_tritmp.h4
-rw-r--r--src/mesa/tnl/t_context.c33
-rw-r--r--src/mesa/tnl/t_context.h5
-rw-r--r--src/mesa/tnl/t_draw.c107
-rw-r--r--src/mesa/tnl/t_rasterpos.c64
-rw-r--r--src/mesa/tnl/t_vb_cliptmp.h35
-rw-r--r--src/mesa/tnl/t_vb_lighttmp.h6
-rw-r--r--src/mesa/tnl/t_vb_points.c2
-rw-r--r--src/mesa/tnl/t_vb_program.c47
-rw-r--r--src/mesa/tnl/t_vb_rendertmp.h101
-rw-r--r--src/mesa/tnl/t_vb_texgen.c24
-rw-r--r--src/mesa/tnl/t_vb_vertex.c24
-rw-r--r--src/mesa/tnl/t_vertex.c45
-rw-r--r--src/mesa/tnl/t_vp_build.c1
-rw-r--r--src/mesa/tnl/t_vp_build.h7
-rw-r--r--src/mesa/tnl/tnl.h13
-rw-r--r--src/mesa/tnl/tnl_features.h13
-rw-r--r--src/mesa/tnl_dd/t_dd_vb.c3
-rw-r--r--src/mesa/vbo/vbo.h25
-rw-r--r--src/mesa/vbo/vbo_attrib_tmp.h16
-rw-r--r--src/mesa/vbo/vbo_context.c40
-rw-r--r--src/mesa/vbo/vbo_context.h18
-rw-r--r--src/mesa/vbo/vbo_exec.c1
-rw-r--r--src/mesa/vbo/vbo_exec.h43
-rw-r--r--src/mesa/vbo/vbo_exec_api.c354
-rw-r--r--src/mesa/vbo/vbo_exec_array.c779
-rw-r--r--src/mesa/vbo/vbo_exec_draw.c224
-rw-r--r--src/mesa/vbo/vbo_rebase.c18
-rw-r--r--src/mesa/vbo/vbo_save.h11
-rw-r--r--src/mesa/vbo/vbo_save_api.c162
-rw-r--r--src/mesa/vbo/vbo_save_draw.c90
-rw-r--r--src/mesa/vbo/vbo_save_loopback.c2
-rw-r--r--src/mesa/vbo/vbo_split.c8
-rw-r--r--src/mesa/vbo/vbo_split_copy.c242
-rw-r--r--src/mesa/vbo/vbo_split_inplace.c39
-rw-r--r--src/mesa/vf/vf.c372
-rw-r--r--src/mesa/vf/vf.h234
-rw-r--r--src/mesa/vf/vf_generic.c981
-rw-r--r--src/mesa/vf/vf_sse.c662
-rw-r--r--src/mesa/x86-64/glapi_x86-64.S2996
-rw-r--r--src/mesa/x86-64/x86-64.c2
-rw-r--r--src/mesa/x86/3dnow.c2
-rw-r--r--src/mesa/x86/Makefile2
-rw-r--r--src/mesa/x86/common_x86.c83
-rw-r--r--src/mesa/x86/common_x86_asm.h14
-rw-r--r--src/mesa/x86/gen_matypes.c8
-rw-r--r--src/mesa/x86/glapi_x86.S181
-rw-r--r--src/mesa/x86/rtasm/x86sse.c9
-rw-r--r--src/mesa/x86/sse.c2
-rw-r--r--src/mesa/x86/sse_xform2.S1
-rw-r--r--src/mesa/x86/sse_xform3.S1
-rw-r--r--src/mesa/x86/x86_xform.c (renamed from src/mesa/x86/x86.c)77
-rw-r--r--src/mesa/x86/x86_xform.h (renamed from src/mesa/x86/common_x86_macros.h)4
-rw-r--r--src/xvmc/Makefile73
-rw-r--r--src/xvmc/attributes.c20
-rw-r--r--src/xvmc/block.c79
-rw-r--r--src/xvmc/context.c207
-rw-r--r--src/xvmc/subpicture.c215
-rw-r--r--src/xvmc/surface.c355
-rw-r--r--src/xvmc/tests/.gitignore5
-rw-r--r--src/xvmc/tests/Makefile27
-rw-r--r--src/xvmc/tests/test_blocks.c84
-rw-r--r--src/xvmc/tests/test_context.c92
-rw-r--r--src/xvmc/tests/test_rendering.c287
-rw-r--r--src/xvmc/tests/test_surface.c72
-rw-r--r--src/xvmc/tests/testlib.c119
-rw-r--r--src/xvmc/tests/testlib.h42
-rw-r--r--src/xvmc/tests/xvmc_bench.c271
2248 files changed, 456861 insertions, 67363 deletions
diff --git a/src/SConscript b/src/SConscript
new file mode 100644
index 0000000000..5440acd135
--- /dev/null
+++ b/src/SConscript
@@ -0,0 +1,11 @@
+Import('*')
+
+SConscript('gallium/SConscript')
+
+if 'mesa' in env['statetrackers']:
+ SConscript('mesa/SConscript')
+
+SConscript('gallium/winsys/SConscript')
+
+SConscript('glut/glx/SConscript')
+SConscript('glew/SConscript')
diff --git a/src/descrip.mms b/src/descrip.mms
deleted file mode 100644
index 71b8ea16ac..0000000000
--- a/src/descrip.mms
+++ /dev/null
@@ -1,43 +0,0 @@
-# Makefile for Mesa for VMS
-# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl
-
-.include [-]mms-config.
-
-all :
- set default [.mesa]
- $(MMS)$(MMSQUALIFIERS)
- set default [-]
-.ifdef SHARE
- $(MMS)$(MMSQUALIFIERS) [-.lib]$(GL_SHAR)
-.endif
- set default [.glu]
- $(MMS)$(MMSQUALIFIERS)
- set default [-.glut.glx]
- $(MMS)$(MMSQUALIFIERS)
- set default [--]
-
-[-.lib]$(GL_SHAR) : [-.lib]$(GL_LIB)
- @ WRITE_ SYS$OUTPUT " generating libmesa.opt"
- @ library/extract=* [-.lib]$(GL_LIB)
- @ OPEN_/WRITE FILE libmesa.opt
- @ WRITE_ FILE "!"
- @ WRITE_ FILE "! libmesa.opt generated by DESCRIP.$(MMS_EXT)"
- @ WRITE_ FILE "!"
- @ WRITE_ FILE "IDENTIFICATION=""mesa5.1"""
- @ WRITE_ FILE "GSMATCH=LEQUAL,5,1
- @ WRITE_ FILE "libmesagl.obj"
- @ write_ file "sys$share:decw$xextlibshr/share"
- @ write_ file "sys$share:decw$xlibshr/share"
- @ write_ file "sys$share:pthread$rtl/share"
- @ CLOSE_ FILE
- @ $(MMS)$(MMSQUALIFIERS)/ignore=warning mesa_vms
- @ WRITE_ SYS$OUTPUT " linking ..."
- @ LINK_/NODEB/SHARE=[-.lib]$(GL_SHAR)/MAP=libmesa.map/FULL libmesa.opt/opt,\
- mesa_vms.opt/opt
- @ delete libmesagl.obj;*
-
-mesa_vms :
- @ WRITE_ SYS$OUTPUT " generating libmesa.map ..."
- @ LINK_/NODEB/NOSHARE/NOEXE/MAP=libmesa.map/FULL libmesa.opt/OPT
- @ WRITE_ SYS$OUTPUT " analyzing libmesa.map ..."
- @ @[-.vms]analyze_map.com libmesa.map mesa_vms.opt
diff --git a/src/driclient/include/driclient.h b/src/driclient/include/driclient.h
new file mode 100644
index 0000000000..d391525039
--- /dev/null
+++ b/src/driclient/include/driclient.h
@@ -0,0 +1,97 @@
+#ifndef driclient_h
+#define driclient_h
+
+#include <stdint.h>
+#include <X11/Xlib.h>
+#include <drm_sarea.h>
+#include "xf86dri.h"
+
+/* TODO: Bring in DRI XML options */
+
+typedef struct dri_version
+{
+ int major;
+ int minor;
+ int patch;
+} dri_version_t;
+
+typedef struct dri_screen
+{
+ Display *display;
+ unsigned int num;
+ dri_version_t ddx, dri, drm;
+ int draw_lock_id;
+ int fd;
+ drm_sarea_t *sarea;
+ void *drawable_hash;
+ void *private;
+} dri_screen_t;
+
+struct dri_context;
+
+typedef struct dri_drawable
+{
+ drm_drawable_t drm_drawable;
+ Drawable x_drawable;
+ unsigned int sarea_index;
+ unsigned int *sarea_stamp;
+ unsigned int last_sarea_stamp;
+ int x, y, w, h;
+ int back_x, back_y;
+ int num_cliprects, num_back_cliprects;
+ drm_clip_rect_t *cliprects, *back_cliprects;
+ dri_screen_t *dri_screen;
+ unsigned int refcount;
+ void *private;
+} dri_drawable_t;
+
+typedef struct dri_context
+{
+ XID id;
+ drm_context_t drm_context;
+ dri_screen_t *dri_screen;
+ void *private;
+} dri_context_t;
+
+typedef struct dri_framebuffer
+{
+ drm_handle_t drm_handle;
+ int base, size, stride;
+ int private_size;
+ void *private;
+} dri_framebuffer_t;
+
+int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf);
+int driDestroyScreen(dri_screen_t *dri_screen);
+int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable);
+int driUpdateDrawableInfo(dri_drawable_t *dri_drawable);
+int driDestroyDrawable(dri_drawable_t *dri_drawable);
+int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context);
+int driDestroyContext(dri_context_t *dri_context);
+
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable) \
+do \
+{ \
+ if (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp) \
+ driUpdateDrawableInfo(dri_drawable); \
+} while (0)
+
+#define DRI_VALIDATE_DRAWABLE_INFO(dri_screen, dri_drawable) \
+do \
+{ \
+ while (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp) \
+ { \
+ register unsigned int hwContext = dri_screen->sarea->lock.lock & \
+ ~(DRM_LOCK_HELD | DRM_LOCK_CONT); \
+ DRM_UNLOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext); \
+ \
+ DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable); \
+ DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id); \
+ \
+ DRM_LIGHT_LOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext); \
+ } \
+} while (0)
+
+#endif
+
diff --git a/src/driclient/include/xf86dri.h b/src/driclient/include/xf86dri.h
new file mode 100644
index 0000000000..baf80a7a9d
--- /dev/null
+++ b/src/driclient/include/xf86dri.h
@@ -0,0 +1,119 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, 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 PRECISION INSIGHT 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.
+
+**************************************************************************/
+
+/**
+ * \file xf86dri.h
+ * Protocol numbers and function prototypes for DRI X protocol.
+ *
+ * \author Kevin E. Martin <martin@valinux.com>
+ * \author Jens Owen <jens@tungstengraphics.com>
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+#ifndef _XF86DRI_H_
+#define _XF86DRI_H_
+
+#include <X11/Xfuncproto.h>
+#include <xf86drm.h>
+
+#define X_XF86DRIQueryVersion 0
+#define X_XF86DRIQueryDirectRenderingCapable 1
+#define X_XF86DRIOpenConnection 2
+#define X_XF86DRICloseConnection 3
+#define X_XF86DRIGetClientDriverName 4
+#define X_XF86DRICreateContext 5
+#define X_XF86DRIDestroyContext 6
+#define X_XF86DRICreateDrawable 7
+#define X_XF86DRIDestroyDrawable 8
+#define X_XF86DRIGetDrawableInfo 9
+#define X_XF86DRIGetDeviceInfo 10
+#define X_XF86DRIAuthConnection 11
+#define X_XF86DRIOpenFullScreen 12 /* Deprecated */
+#define X_XF86DRICloseFullScreen 13 /* Deprecated */
+
+#define XF86DRINumberEvents 0
+
+#define XF86DRIClientNotLocal 0
+#define XF86DRIOperationNotSupported 1
+#define XF86DRINumberErrors (XF86DRIOperationNotSupported + 1)
+
+#ifndef _XF86DRI_SERVER_
+
+_XFUNCPROTOBEGIN
+
+Bool XF86DRIQueryExtension( Display *dpy, int *event_base, int *error_base );
+
+Bool XF86DRIQueryVersion( Display *dpy, int *majorVersion, int *minorVersion,
+ int *patchVersion );
+
+Bool XF86DRIQueryDirectRenderingCapable( Display *dpy, int screen,
+ Bool *isCapable );
+
+Bool XF86DRIOpenConnection( Display *dpy, int screen, drm_handle_t *hSAREA,
+ char **busIDString );
+
+Bool XF86DRIAuthConnection( Display *dpy, int screen, drm_magic_t magic );
+
+Bool XF86DRICloseConnection( Display *dpy, int screen );
+
+Bool XF86DRIGetClientDriverName( Display *dpy, int screen,
+ int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
+ int *ddxDriverPatchVersion, char **clientDriverName );
+
+Bool XF86DRICreateContext( Display *dpy, int screen, Visual *visual,
+ XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
+
+Bool XF86DRICreateContextWithConfig( Display *dpy, int screen, int configID,
+ XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
+
+Bool XF86DRIDestroyContext( Display *dpy, int screen,
+ XID context_id );
+
+Bool XF86DRICreateDrawable( Display *dpy, int screen,
+ Drawable drawable, drm_drawable_t *hHWDrawable );
+
+Bool XF86DRIDestroyDrawable( Display *dpy, int screen,
+ Drawable drawable);
+
+Bool XF86DRIGetDrawableInfo( Display *dpy, int screen, Drawable drawable,
+ unsigned int *index, unsigned int *stamp,
+ int *X, int *Y, int *W, int *H,
+ int *numClipRects, drm_clip_rect_t ** pClipRects,
+ int *backX, int *backY,
+ int *numBackClipRects, drm_clip_rect_t **pBackClipRects );
+
+Bool XF86DRIGetDeviceInfo( Display *dpy, int screen,
+ drm_handle_t *hFrameBuffer, int *fbOrigin, int *fbSize,
+ int *fbStride, int *devPrivateSize, void **pDevPrivate );
+
+_XFUNCPROTOEND
+
+#endif /* _XF86DRI_SERVER_ */
+
+#endif /* _XF86DRI_H_ */
+
diff --git a/src/driclient/src/Makefile b/src/driclient/src/Makefile
new file mode 100644
index 0000000000..34435a2086
--- /dev/null
+++ b/src/driclient/src/Makefile
@@ -0,0 +1,19 @@
+TARGET = libdriclient.a
+OBJECTS = driclient.o XF86dri.o
+DRMDIR ?= /usr
+
+CFLAGS += -g -Wall -fPIC -I../include -I${DRMDIR}/include -I${DRMDIR}/include/drm
+
+#############################################
+
+.PHONY = all clean
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS}
+ ar rcs $@ $^
+ if ! test -d ../lib; then mkdir ../lib; fi
+ cp ${TARGET} ../lib
+
+clean:
+ rm -rf ${OBJECTS} ${TARGET} ../lib/${TARGET}
diff --git a/src/driclient/src/XF86dri.c b/src/driclient/src/XF86dri.c
new file mode 100644
index 0000000000..9e359a9238
--- /dev/null
+++ b/src/driclient/src/XF86dri.c
@@ -0,0 +1,619 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, 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 PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include "xf86dristr.h"
+
+static XExtensionInfo _xf86dri_info_data;
+static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
+static char xf86dri_extension_name[] = XF86DRINAME;
+
+#define XF86DRICheckExtension(dpy,i,val) \
+ XextCheckExtension (dpy, i, xf86dri_extension_name, val)
+
+/*****************************************************************************
+ * *
+ * private utility routines *
+ * *
+ *****************************************************************************/
+
+static int close_display(Display *dpy, XExtCodes *extCodes);
+static /* const */ XExtensionHooks xf86dri_extension_hooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ close_display, /* close_display */
+ NULL, /* wire_to_event */
+ NULL, /* event_to_wire */
+ NULL, /* error */
+ NULL, /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info,
+ xf86dri_extension_name,
+ &xf86dri_extension_hooks,
+ 0, NULL)
+
+static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info)
+
+
+/*****************************************************************************
+ * *
+ * public XFree86-DRI Extension routines *
+ * *
+ *****************************************************************************/
+
+#if 0
+#include <stdio.h>
+#define TRACE(msg) fprintf(stderr,"XF86DRI%s\n", msg);
+#else
+#define TRACE(msg)
+#endif
+
+#define PUBLIC
+
+PUBLIC Bool XF86DRIQueryExtension (dpy, event_basep, error_basep)
+ Display *dpy;
+ int *event_basep, *error_basep;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+
+ TRACE("QueryExtension...");
+ if (XextHasExtension(info)) {
+ *event_basep = info->codes->first_event;
+ *error_basep = info->codes->first_error;
+ TRACE("QueryExtension... return True");
+ return True;
+ } else {
+ TRACE("QueryExtension... return False");
+ return False;
+ }
+}
+
+PUBLIC Bool XF86DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
+ Display* dpy;
+ int* majorVersion;
+ int* minorVersion;
+ int* patchVersion;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIQueryVersionReply rep;
+ xXF86DRIQueryVersionReq *req;
+
+ TRACE("QueryVersion...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryVersion, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryVersion;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return False");
+ return False;
+ }
+ *majorVersion = rep.majorVersion;
+ *minorVersion = rep.minorVersion;
+ *patchVersion = rep.patchVersion;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable)
+ Display* dpy;
+ int screen;
+ Bool* isCapable;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIQueryDirectRenderingCapableReply rep;
+ xXF86DRIQueryDirectRenderingCapableReq *req;
+
+ TRACE("QueryDirectRenderingCapable...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryDirectRenderingCapable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return False");
+ return False;
+ }
+ *isCapable = rep.isCapable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString)
+ Display* dpy;
+ int screen;
+ drm_handle_t * hSAREA;
+ char **busIdString;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIOpenConnectionReply rep;
+ xXF86DRIOpenConnectionReq *req;
+
+ TRACE("OpenConnection...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIOpenConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIOpenConnection;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+
+ *hSAREA = rep.hSAREALow;
+ if (sizeof(drm_handle_t) == 8) {
+ int shift = 32; /* var to prevent warning on next line */
+ *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift;
+ }
+
+ if (rep.length) {
+ if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
+ _XEatData(dpy, ((rep.busIdStringLength+3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+ _XReadPad(dpy, *busIdString, rep.busIdStringLength);
+ } else {
+ *busIdString = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIAuthConnection(dpy, screen, magic)
+ Display* dpy;
+ int screen;
+ drm_magic_t magic;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIAuthConnectionReq *req;
+ xXF86DRIAuthConnectionReply rep;
+
+ TRACE("AuthConnection...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIAuthConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIAuthConnection;
+ req->screen = screen;
+ req->magic = magic;
+ rep.authenticated = 0;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return False");
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRICloseConnection(dpy, screen)
+ Display* dpy;
+ int screen;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRICloseConnectionReq *req;
+
+ TRACE("CloseConnection...");
+
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICloseConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICloseConnection;
+ req->screen = screen;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CloseConnection... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion,
+ ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
+ Display* dpy;
+ int screen;
+ int* ddxDriverMajorVersion;
+ int* ddxDriverMinorVersion;
+ int* ddxDriverPatchVersion;
+ char** clientDriverName;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIGetClientDriverNameReply rep;
+ xXF86DRIGetClientDriverNameReq *req;
+
+ TRACE("GetClientDriverName...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetClientDriverName, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetClientDriverName;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+
+ *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
+ *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
+ *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
+
+ if (rep.length) {
+ if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
+ _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+ _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
+ } else {
+ *clientDriverName = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRICreateContextWithConfig(dpy, screen, configID, context,
+ hHWContext)
+ Display* dpy;
+ int screen;
+ int configID;
+ XID* context;
+ drm_context_t * hHWContext;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRICreateContextReply rep;
+ xXF86DRICreateContextReq *req;
+
+ TRACE("CreateContext...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateContext;
+ req->visual = configID;
+ req->screen = screen;
+ *context = XAllocID(dpy);
+ req->context = *context;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return False");
+ return False;
+ }
+ *hHWContext = rep.hHWContext;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRICreateContext(dpy, screen, visual, context, hHWContext)
+ Display* dpy;
+ int screen;
+ Visual* visual;
+ XID* context;
+ drm_context_t * hHWContext;
+{
+ return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid,
+ context, hHWContext );
+}
+
+PUBLIC Bool XF86DRIDestroyContext( Display * ndpy, int screen,
+ XID context )
+{
+ Display * const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIDestroyContextReq *req;
+
+ TRACE("DestroyContext...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyContext;
+ req->screen = screen;
+ req->context = context;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyContext... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRICreateDrawable( Display * ndpy, int screen,
+ Drawable drawable, drm_drawable_t * hHWDrawable )
+{
+ Display * const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRICreateDrawableReply rep;
+ xXF86DRICreateDrawableReq *req;
+
+ TRACE("CreateDrawable...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return False");
+ return False;
+ }
+ *hHWDrawable = rep.hHWDrawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIDestroyDrawable( Display * ndpy, int screen,
+ Drawable drawable )
+{
+ Display * const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIDestroyDrawableReq *req;
+
+ TRACE("DestroyDrawable...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyDrawable... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
+ unsigned int* index, unsigned int* stamp,
+ int* X, int* Y, int* W, int* H,
+ int* numClipRects, drm_clip_rect_t ** pClipRects,
+ int* backX, int* backY,
+ int* numBackClipRects, drm_clip_rect_t ** pBackClipRects )
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIGetDrawableInfoReply rep;
+ xXF86DRIGetDrawableInfoReq *req;
+ int total_rects;
+
+ TRACE("GetDrawableInfo...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDrawableInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDrawableInfo;
+ req->screen = screen;
+ req->drawable = drawable;
+
+ if (!_XReply(dpy, (xReply *)&rep, 1, xFalse))
+ {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+ *index = rep.drawableTableIndex;
+ *stamp = rep.drawableTableStamp;
+ *X = (int)rep.drawableX;
+ *Y = (int)rep.drawableY;
+ *W = (int)rep.drawableWidth;
+ *H = (int)rep.drawableHeight;
+ *numClipRects = rep.numClipRects;
+ total_rects = *numClipRects;
+
+ *backX = rep.backX;
+ *backY = rep.backY;
+ *numBackClipRects = rep.numBackClipRects;
+ total_rects += *numBackClipRects;
+
+#if 0
+ /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
+ * backwards compatibility (Because of the >> 2 shift) but the fix
+ * enables multi-threaded apps to work.
+ */
+ if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
+ SIZEOF(xGenericReply) +
+ total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) {
+ _XEatData(dpy, rep.length);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+#endif
+
+ if (*numClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numClipRects);
+
+ *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
+ if (*pClipRects)
+ _XRead(dpy, (char*)*pClipRects, len);
+ } else {
+ *pClipRects = NULL;
+ }
+
+ if (*numBackClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
+
+ *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
+ if (*pBackClipRects)
+ _XRead(dpy, (char*)*pBackClipRects, len);
+ } else {
+ *pBackClipRects = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer,
+ fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
+ Display* dpy;
+ int screen;
+ drm_handle_t * hFrameBuffer;
+ int* fbOrigin;
+ int* fbSize;
+ int* fbStride;
+ int* devPrivateSize;
+ void** pDevPrivate;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIGetDeviceInfoReply rep;
+ xXF86DRIGetDeviceInfoReq *req;
+
+ TRACE("GetDeviceInfo...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDeviceInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDeviceInfo;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+
+ *hFrameBuffer = rep.hFrameBufferLow;
+ if (sizeof(drm_handle_t) == 8) {
+ int shift = 32; /* var to prevent warning on next line */
+ *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift;
+ }
+
+ *fbOrigin = rep.framebufferOrigin;
+ *fbSize = rep.framebufferSize;
+ *fbStride = rep.framebufferStride;
+ *devPrivateSize = rep.devPrivateSize;
+
+ if (rep.length) {
+ if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
+ _XEatData(dpy, ((rep.devPrivateSize+3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+ _XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize);
+ } else {
+ *pDevPrivate = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIOpenFullScreen(dpy, screen, drawable)
+ Display* dpy;
+ int screen;
+ Drawable drawable;
+{
+ /* This function and the underlying X protocol are deprecated.
+ */
+ (void) dpy;
+ (void) screen;
+ (void) drawable;
+ return False;
+}
+
+PUBLIC Bool XF86DRICloseFullScreen(dpy, screen, drawable)
+ Display* dpy;
+ int screen;
+ Drawable drawable;
+{
+ /* This function and the underlying X protocol are deprecated.
+ */
+ (void) dpy;
+ (void) screen;
+ (void) drawable;
+ return True;
+}
+
diff --git a/src/driclient/src/driclient.c b/src/driclient/src/driclient.c
new file mode 100644
index 0000000000..dc2189afec
--- /dev/null
+++ b/src/driclient/src/driclient.c
@@ -0,0 +1,310 @@
+#include "driclient.h"
+#include <assert.h>
+#include <stdlib.h>
+
+int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf)
+{
+ int evbase, errbase;
+ char *driver_name;
+ int newly_opened;
+ drm_magic_t magic;
+ drmVersionPtr drm_version;
+ drm_handle_t sarea_handle;
+ char *bus_id;
+ dri_screen_t *dri_scrn;
+
+ assert(display);
+ assert(dri_screen);
+
+ if (!XF86DRIQueryExtension(display, &evbase, &errbase))
+ return 1;
+
+ dri_scrn = calloc(1, sizeof(dri_screen_t));
+
+ if (!dri_scrn)
+ return 1;
+
+ if (!XF86DRIQueryVersion(display, &dri_scrn->dri.major, &dri_scrn->dri.minor, &dri_scrn->dri.patch))
+ goto free_screen;
+
+ dri_scrn->display = display;
+ dri_scrn->num = screen;
+ dri_scrn->draw_lock_id = 1;
+
+ if (!XF86DRIOpenConnection(display, screen, &sarea_handle, &bus_id))
+ goto free_screen;
+
+ dri_scrn->fd = -1;
+ dri_scrn->fd = drmOpenOnce(NULL, bus_id, &newly_opened);
+ XFree(bus_id);
+
+ if (dri_scrn->fd < 0)
+ goto close_connection;
+
+ if (drmGetMagic(dri_scrn->fd, &magic))
+ goto close_drm;
+
+ drm_version = drmGetVersion(dri_scrn->fd);
+
+ if (!drm_version)
+ goto close_drm;
+
+ dri_scrn->drm.major = drm_version->version_major;
+ dri_scrn->drm.minor = drm_version->version_minor;
+ dri_scrn->drm.patch = drm_version->version_patchlevel;
+ drmFreeVersion(drm_version);
+
+ if (!XF86DRIAuthConnection(display, screen, magic))
+ goto close_drm;
+
+ if (!XF86DRIGetClientDriverName
+ (
+ display,
+ screen,
+ &dri_scrn->ddx.major,
+ &dri_scrn->ddx.minor,
+ &dri_scrn->ddx.patch,
+ &driver_name
+ ))
+ goto close_drm;
+
+ if (drmMap(dri_scrn->fd, sarea_handle, SAREA_MAX, (drmAddress)&dri_scrn->sarea))
+ goto close_drm;
+
+ dri_scrn->drawable_hash = drmHashCreate();
+
+ if (!dri_scrn->drawable_hash)
+ goto unmap_sarea;
+
+ if (dri_framebuf)
+ {
+ if (!XF86DRIGetDeviceInfo
+ (
+ display,
+ screen, &dri_framebuf->drm_handle,
+ &dri_framebuf->base,
+ &dri_framebuf->size,
+ &dri_framebuf->stride,
+ &dri_framebuf->private_size,
+ &dri_framebuf->private
+ ))
+ goto destroy_hash;
+ }
+
+ *dri_screen = dri_scrn;
+
+ return 0;
+
+destroy_hash:
+ drmHashDestroy(dri_scrn->drawable_hash);
+unmap_sarea:
+ drmUnmap(dri_scrn->sarea, SAREA_MAX);
+close_drm:
+ drmCloseOnce(dri_scrn->fd);
+close_connection:
+ XF86DRICloseConnection(display, screen);
+free_screen:
+ free(dri_scrn);
+
+ return 1;
+}
+
+int driDestroyScreen(dri_screen_t *dri_screen)
+{
+ Drawable draw;
+ dri_drawable_t *dri_draw;
+
+ assert(dri_screen);
+
+ if (drmHashFirst(dri_screen->drawable_hash, &draw, (void**)&dri_draw))
+ {
+ dri_draw->refcount = 1;
+ driDestroyDrawable(dri_draw);
+
+ while (drmHashNext(dri_screen->drawable_hash, &draw, (void**)&dri_draw))
+ {
+ dri_draw->refcount = 1;
+ driDestroyDrawable(dri_draw);
+ }
+ }
+
+ drmHashDestroy(dri_screen->drawable_hash);
+ drmUnmap(dri_screen->sarea, SAREA_MAX);
+ drmCloseOnce(dri_screen->fd);
+ XF86DRICloseConnection(dri_screen->display, dri_screen->num);
+ free(dri_screen);
+
+ return 0;
+}
+
+int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable)
+{
+ int evbase, errbase;
+ dri_drawable_t *dri_draw;
+
+ assert(dri_screen);
+ assert(dri_drawable);
+
+ if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
+ return 1;
+
+ if (!drmHashLookup(dri_screen->drawable_hash, drawable, (void**)dri_drawable))
+ {
+ /* Found */
+ (*dri_drawable)->refcount++;
+ return 0;
+ }
+
+ dri_draw = calloc(1, sizeof(dri_drawable_t));
+
+ if (!dri_draw)
+ return 1;
+
+ if (!XF86DRICreateDrawable(dri_screen->display, 0, drawable, &dri_draw->drm_drawable))
+ {
+ free(dri_draw);
+ return 1;
+ }
+
+ dri_draw->x_drawable = drawable;
+ dri_draw->sarea_index = 0;
+ dri_draw->sarea_stamp = NULL;
+ dri_draw->last_sarea_stamp = 0;
+ dri_draw->dri_screen = dri_screen;
+ dri_draw->refcount = 1;
+
+ if (drmHashInsert(dri_screen->drawable_hash, drawable, dri_draw))
+ {
+ XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
+ free(dri_draw);
+ return 1;
+ }
+
+ if (!dri_draw->sarea_stamp || *dri_draw->sarea_stamp != dri_draw->last_sarea_stamp)
+ {
+ DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
+
+ if (driUpdateDrawableInfo(dri_draw))
+ {
+ XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
+ free(dri_draw);
+ DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
+ return 1;
+ }
+
+ DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
+ }
+
+ *dri_drawable = dri_draw;
+
+ return 0;
+}
+
+int driUpdateDrawableInfo(dri_drawable_t *dri_drawable)
+{
+ assert(dri_drawable);
+
+ if (dri_drawable->cliprects)
+ {
+ XFree(dri_drawable->cliprects);
+ dri_drawable->cliprects = NULL;
+ }
+ if (dri_drawable->back_cliprects)
+ {
+ XFree(dri_drawable->back_cliprects);
+ dri_drawable->back_cliprects = NULL;
+ }
+
+ DRM_SPINUNLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
+
+ if (!XF86DRIGetDrawableInfo
+ (
+ dri_drawable->dri_screen->display,
+ dri_drawable->dri_screen->num,
+ dri_drawable->x_drawable,
+ &dri_drawable->sarea_index,
+ &dri_drawable->last_sarea_stamp,
+ &dri_drawable->x,
+ &dri_drawable->y,
+ &dri_drawable->w,
+ &dri_drawable->h,
+ &dri_drawable->num_cliprects,
+ &dri_drawable->cliprects,
+ &dri_drawable->back_x,
+ &dri_drawable->back_y,
+ &dri_drawable->num_back_cliprects,
+ &dri_drawable->back_cliprects
+ ))
+ {
+ dri_drawable->sarea_stamp = &dri_drawable->last_sarea_stamp;
+ dri_drawable->num_cliprects = 0;
+ dri_drawable->cliprects = NULL;
+ dri_drawable->num_back_cliprects = 0;
+ dri_drawable->back_cliprects = 0;
+
+ return 1;
+ }
+ else
+ dri_drawable->sarea_stamp = &dri_drawable->dri_screen->sarea->drawableTable[dri_drawable->sarea_index].stamp;
+
+ DRM_SPINLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
+
+ return 0;
+}
+
+int driDestroyDrawable(dri_drawable_t *dri_drawable)
+{
+ assert(dri_drawable);
+
+ if (--dri_drawable->refcount == 0)
+ {
+ if (dri_drawable->cliprects)
+ XFree(dri_drawable->cliprects);
+ if (dri_drawable->back_cliprects)
+ XFree(dri_drawable->back_cliprects);
+ drmHashDelete(dri_drawable->dri_screen->drawable_hash, dri_drawable->x_drawable);
+ XF86DRIDestroyDrawable(dri_drawable->dri_screen->display, dri_drawable->dri_screen->num, dri_drawable->x_drawable);
+ free(dri_drawable);
+ }
+
+ return 0;
+}
+
+int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context)
+{
+ int evbase, errbase;
+ dri_context_t *dri_ctx;
+
+ assert(dri_screen);
+ assert(visual);
+ assert(dri_context);
+
+ if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
+ return 1;
+
+ dri_ctx = calloc(1, sizeof(dri_context_t));
+
+ if (!dri_ctx)
+ return 1;
+
+ if (!XF86DRICreateContext(dri_screen->display, dri_screen->num, visual, &dri_ctx->id, &dri_ctx->drm_context))
+ {
+ free(dri_ctx);
+ return 1;
+ }
+
+ dri_ctx->dri_screen = dri_screen;
+ *dri_context = dri_ctx;
+
+ return 0;
+}
+
+int driDestroyContext(dri_context_t *dri_context)
+{
+ assert(dri_context);
+
+ XF86DRIDestroyContext(dri_context->dri_screen->display, dri_context->dri_screen->num, dri_context->id);
+ free(dri_context);
+
+ return 0;
+}
diff --git a/src/driclient/src/xf86dristr.h b/src/driclient/src/xf86dristr.h
new file mode 100644
index 0000000000..b834bd1a1a
--- /dev/null
+++ b/src/driclient/src/xf86dristr.h
@@ -0,0 +1,342 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, 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 PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Fiath <faith@valinux.com>
+ *
+ */
+
+#ifndef _XF86DRISTR_H_
+#define _XF86DRISTR_H_
+
+#include "xf86dri.h"
+
+#define XF86DRINAME "XFree86-DRI"
+
+/* The DRI version number. This was originally set to be the same of the
+ * XFree86 version number. However, this version is really indepedent of
+ * the XFree86 version.
+ *
+ * Version History:
+ * 4.0.0: Original
+ * 4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02
+ * 4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02
+ */
+#define XF86DRI_MAJOR_VERSION 4
+#define XF86DRI_MINOR_VERSION 1
+#define XF86DRI_PATCH_VERSION 0
+
+typedef struct _XF86DRIQueryVersion {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIQueryVersion */
+ CARD16 length B16;
+} xXF86DRIQueryVersionReq;
+#define sz_xXF86DRIQueryVersionReq 4
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 majorVersion B16; /* major version of DRI protocol */
+ CARD16 minorVersion B16; /* minor version of DRI protocol */
+ CARD32 patchVersion B32; /* patch version of DRI protocol */
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIQueryVersionReply;
+#define sz_xXF86DRIQueryVersionReply 32
+
+typedef struct _XF86DRIQueryDirectRenderingCapable {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIQueryDirectRenderingCapableReq;
+#define sz_xXF86DRIQueryDirectRenderingCapableReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ BOOL isCapable;
+ BOOL pad2;
+ BOOL pad3;
+ BOOL pad4;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+ CARD32 pad9 B32;
+} xXF86DRIQueryDirectRenderingCapableReply;
+#define sz_xXF86DRIQueryDirectRenderingCapableReply 32
+
+typedef struct _XF86DRIOpenConnection {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIOpenConnectionReq;
+#define sz_xXF86DRIOpenConnectionReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hSAREALow B32;
+ CARD32 hSAREAHigh B32;
+ CARD32 busIdStringLength B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+} xXF86DRIOpenConnectionReply;
+#define sz_xXF86DRIOpenConnectionReply 32
+
+typedef struct _XF86DRIAuthConnection {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 magic B32;
+} xXF86DRIAuthConnectionReq;
+#define sz_xXF86DRIAuthConnectionReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 authenticated B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIAuthConnectionReply;
+#define zx_xXF86DRIAuthConnectionReply 32
+
+typedef struct _XF86DRICloseConnection {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRICloseConnectionReq;
+#define sz_xXF86DRICloseConnectionReq 8
+
+typedef struct _XF86DRIGetClientDriverName {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetClientDriverName */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetClientDriverNameReq;
+#define sz_xXF86DRIGetClientDriverNameReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 ddxDriverMajorVersion B32;
+ CARD32 ddxDriverMinorVersion B32;
+ CARD32 ddxDriverPatchVersion B32;
+ CARD32 clientDriverNameLength B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIGetClientDriverNameReply;
+#define sz_xXF86DRIGetClientDriverNameReply 32
+
+typedef struct _XF86DRICreateContext {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 visual B32;
+ CARD32 context B32;
+} xXF86DRICreateContextReq;
+#define sz_xXF86DRICreateContextReq 16
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWContext B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateContextReply;
+#define sz_xXF86DRICreateContextReply 32
+
+typedef struct _XF86DRIDestroyContext {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 context B32;
+} xXF86DRIDestroyContextReq;
+#define sz_xXF86DRIDestroyContextReq 12
+
+typedef struct _XF86DRICreateDrawable {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICreateDrawableReq;
+#define sz_xXF86DRICreateDrawableReq 12
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWDrawable B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateDrawableReply;
+#define sz_xXF86DRICreateDrawableReply 32
+
+typedef struct _XF86DRIDestroyDrawable {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIDestroyDrawableReq;
+#define sz_xXF86DRIDestroyDrawableReq 12
+
+typedef struct _XF86DRIGetDrawableInfo {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDrawableInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIGetDrawableInfoReq;
+#define sz_xXF86DRIGetDrawableInfoReq 12
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 drawableTableIndex B32;
+ CARD32 drawableTableStamp B32;
+ INT16 drawableX B16;
+ INT16 drawableY B16;
+ INT16 drawableWidth B16;
+ INT16 drawableHeight B16;
+ CARD32 numClipRects B32;
+ INT16 backX B16;
+ INT16 backY B16;
+ CARD32 numBackClipRects B32;
+} xXF86DRIGetDrawableInfoReply;
+
+#define sz_xXF86DRIGetDrawableInfoReply 36
+
+
+typedef struct _XF86DRIGetDeviceInfo {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDeviceInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetDeviceInfoReq;
+#define sz_xXF86DRIGetDeviceInfoReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hFrameBufferLow B32;
+ CARD32 hFrameBufferHigh B32;
+ CARD32 framebufferOrigin B32;
+ CARD32 framebufferSize B32;
+ CARD32 framebufferStride B32;
+ CARD32 devPrivateSize B32;
+} xXF86DRIGetDeviceInfoReply;
+#define sz_xXF86DRIGetDeviceInfoReply 32
+
+typedef struct _XF86DRIOpenFullScreen {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIOpenFullScreenReq;
+#define sz_xXF86DRIOpenFullScreenReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 isFullScreen B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIOpenFullScreenReply;
+#define sz_xXF86DRIOpenFullScreenReply 32
+
+typedef struct _XF86DRICloseFullScreen {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICloseFullScreenReq;
+#define sz_xXF86DRICloseFullScreenReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xXF86DRICloseFullScreenReply;
+#define sz_xXF86DRICloseFullScreenReply 32
+
+
+#endif /* _XF86DRISTR_H_ */
diff --git a/src/egl/Makefile b/src/egl/Makefile
index fb4db8f9b9..5b09e178c6 100644
--- a/src/egl/Makefile
+++ b/src/egl/Makefile
@@ -1,8 +1,9 @@
# src/egl/Makefile
TOP = ../..
+include $(TOP)/configs/current
-SUBDIRS = main drivers/demo drivers/dri
+SUBDIRS = main drivers
default: subdirs
@@ -15,6 +16,12 @@ subdirs:
fi \
done
+install:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) install) || exit 1 ; \
+ fi \
+ done
clean:
-@for dir in $(SUBDIRS) ; do \
diff --git a/src/egl/drivers/Makefile b/src/egl/drivers/Makefile
new file mode 100644
index 0000000000..dde4ee2255
--- /dev/null
+++ b/src/egl/drivers/Makefile
@@ -0,0 +1,31 @@
+# src/egl/drivers/Makefile
+
+TOP = ../../..
+include $(TOP)/configs/current
+
+SUBDIRS = $(EGL_DRIVERS_DIRS)
+
+
+default: subdirs
+
+
+subdirs:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir ; $(MAKE)) || exit 1 ; \
+ fi \
+ done
+
+install:
+ @ for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir ; $(MAKE) install) || exit 1 ; \
+ fi \
+ done
+
+clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir ; $(MAKE) clean) ; \
+ fi \
+ done
diff --git a/src/egl/drivers/demo/Makefile b/src/egl/drivers/demo/Makefile
index 6ca25aa5d6..444dfb35bd 100644
--- a/src/egl/drivers/demo/Makefile
+++ b/src/egl/drivers/demo/Makefile
@@ -4,7 +4,7 @@ TOP = ../../../..
include $(TOP)/configs/current
-INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/egl/main
+INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/egl/main $(X11_INCLUDES)
SOURCES = demo.c
@@ -25,7 +25,7 @@ $(TOP)/$(LIB_DIR)/demodriver.so: $(OBJECTS)
-ldflags '$(LDFLAGS)' -install $(TOP)/$(LIB_DIR) \
$(OBJECTS)
-
+install:
clean:
-rm -f *.o
diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c
index 45545755c0..aea4894448 100644
--- a/src/egl/drivers/demo/demo.c
+++ b/src/egl/drivers/demo/demo.c
@@ -21,7 +21,7 @@
typedef struct demo_driver
{
_EGLDriver Base; /* base class/object */
- GLuint DemoStuff;
+ unsigned DemoStuff;
} DemoDriver;
#define DEMO_DRIVER(D) ((DemoDriver *) (D))
@@ -33,7 +33,7 @@ typedef struct demo_driver
typedef struct demo_surface
{
_EGLSurface Base; /* base class/object */
- GLuint DemoStuff;
+ unsigned DemoStuff;
} DemoSurface;
@@ -43,15 +43,14 @@ typedef struct demo_surface
typedef struct demo_context
{
_EGLContext Base; /* base class/object */
- GLuint DemoStuff;
+ unsigned DemoStuff;
} DemoContext;
static EGLBoolean
-demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
+demoInitialize(_EGLDriver *drv, _EGLDisplay *disp, EGLint *major, EGLint *minor)
{
- _EGLDisplay *disp = _eglLookupDisplay(dpy);
_EGLScreen *scrn;
EGLint i;
@@ -67,25 +66,27 @@ demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
/* Create the display's visual configs - silly example */
for (i = 0; i < 4; i++) {
- _EGLConfig config;
- _eglInitConfig(&config, i + 1);
- _eglSetConfigAttrib(&config, EGL_RED_SIZE, 8);
- _eglSetConfigAttrib(&config, EGL_GREEN_SIZE, 8);
- _eglSetConfigAttrib(&config, EGL_BLUE_SIZE, 8);
- _eglSetConfigAttrib(&config, EGL_ALPHA_SIZE, 8);
- _eglSetConfigAttrib(&config, EGL_BUFFER_SIZE, 32);
+ _EGLConfig *config = calloc(1, sizeof(_EGLConfig));
+ _eglInitConfig(config, i + 1);
+ _eglSetConfigAttrib(config, EGL_RED_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32);
if (i & 1) {
- _eglSetConfigAttrib(&config, EGL_DEPTH_SIZE, 32);
+ _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 32);
}
if (i & 2) {
- _eglSetConfigAttrib(&config, EGL_STENCIL_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8);
}
- _eglSetConfigAttrib(&config, EGL_SURFACE_TYPE,
+ _eglSetConfigAttrib(config, EGL_SURFACE_TYPE,
(EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT));
- _eglAddConfig(disp, &config);
+ _eglAddConfig(disp, config);
}
- drv->Initialized = EGL_TRUE;
+ /* enable supported extensions */
+ disp->Extensions.MESA_screen_surface = EGL_TRUE;
+ disp->Extensions.MESA_copy_context = EGL_TRUE;
*major = 1;
*minor = 0;
@@ -95,71 +96,56 @@ demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
static EGLBoolean
-demoTerminate(_EGLDriver *drv, EGLDisplay dpy)
+demoTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
{
/*DemoDriver *demo = DEMO_DRIVER(dpy);*/
- free(drv);
return EGL_TRUE;
}
static DemoContext *
-LookupDemoContext(EGLContext ctx)
+LookupDemoContext(_EGLContext *c)
{
- _EGLContext *c = _eglLookupContext(ctx);
return (DemoContext *) c;
}
static DemoSurface *
-LookupDemoSurface(EGLSurface surf)
+LookupDemoSurface(_EGLSurface *s)
{
- _EGLSurface *s = _eglLookupSurface(surf);
return (DemoSurface *) s;
}
-
-static EGLContext
-demoCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
+static _EGLContext *
+demoCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list)
{
- _EGLConfig *conf;
DemoContext *c;
int i;
- conf = _eglLookupConfig(drv, dpy, config);
- if (!conf) {
- _eglError(EGL_BAD_CONFIG, "eglCreateContext");
- return EGL_NO_CONTEXT;
- }
-
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
switch (attrib_list[i]) {
/* no attribs defined for now */
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
- return EGL_NO_CONTEXT;
+ return NULL;
}
}
c = (DemoContext *) calloc(1, sizeof(DemoContext));
if (!c)
- return EGL_NO_CONTEXT;
+ return NULL;
- _eglInitContext(drv, dpy, &c->Base, config, attrib_list);
+ _eglInitContext(drv, &c->Base, conf, attrib_list);
c->DemoStuff = 1;
printf("demoCreateContext\n");
- /* generate handle and insert into hash table */
- _eglSaveContext(&c->Base);
- assert(c->Base.Handle);
-
- return c->Base.Handle;
+ return &c->Base;
}
-static EGLSurface
-demoCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
+static _EGLSurface *
+demoCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list)
{
int i;
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
@@ -167,107 +153,88 @@ demoCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, Nativ
/* no attribs at this time */
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglCreateWindowSurface");
- return EGL_NO_SURFACE;
+ return NULL;
}
}
printf("eglCreateWindowSurface()\n");
/* XXX unfinished */
- return EGL_NO_SURFACE;
+ return NULL;
}
-static EGLSurface
-demoCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
+static _EGLSurface *
+demoCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list)
{
- _EGLConfig *conf;
EGLint i;
- conf = _eglLookupConfig(drv, dpy, config);
- if (!conf) {
- _eglError(EGL_BAD_CONFIG, "eglCreatePixmapSurface");
- return EGL_NO_SURFACE;
- }
-
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
switch (attrib_list[i]) {
/* no attribs at this time */
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface");
- return EGL_NO_SURFACE;
+ return NULL;
}
}
if (conf->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] == 0) {
_eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface");
- return EGL_NO_SURFACE;
+ return NULL;
}
printf("eglCreatePixmapSurface()\n");
- return EGL_NO_SURFACE;
+ return NULL;
}
-static EGLSurface
-demoCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+static _EGLSurface *
+demoCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
const EGLint *attrib_list)
{
DemoSurface *surf = (DemoSurface *) calloc(1, sizeof(DemoSurface));
+
if (!surf)
- return EGL_NO_SURFACE;
+ return NULL;
- if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT,
- config, attrib_list)) {
+ if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT,
+ conf, attrib_list)) {
free(surf);
- return EGL_NO_SURFACE;
+ return NULL;
}
/* a real driver would allocate the pbuffer memory here */
- return surf->Base.Handle;
+ return &surf->Base;
}
static EGLBoolean
-demoDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
+demoDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
{
DemoSurface *fs = LookupDemoSurface(surface);
- _eglRemoveSurface(&fs->Base);
- if (fs->Base.IsBound) {
- fs->Base.DeletePending = EGL_TRUE;
- }
- else {
+ if (!_eglIsSurfaceBound(&fs->Base))
free(fs);
- }
return EGL_TRUE;
}
static EGLBoolean
-demoDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
+demoDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *context)
{
DemoContext *fc = LookupDemoContext(context);
- _eglRemoveContext(&fc->Base);
- if (fc->Base.IsBound) {
- fc->Base.DeletePending = EGL_TRUE;
- }
- else {
+ if (!_eglIsContextBound(&fc->Base))
free(fc);
- }
return EGL_TRUE;
}
static EGLBoolean
-demoMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context)
+demoMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *drawSurf, _EGLSurface *readSurf, _EGLContext *ctx)
{
/*DemoDriver *demo = DEMO_DRIVER(dpy);*/
- DemoSurface *readSurf = LookupDemoSurface(read);
- DemoSurface *drawSurf = LookupDemoSurface(draw);
- DemoContext *ctx = LookupDemoContext(context);
EGLBoolean b;
- b = _eglMakeCurrent(drv, dpy, draw, read, context);
+ b = _eglMakeCurrent(drv, dpy, drawSurf, readSurf, ctx);
if (!b)
return EGL_FALSE;
@@ -281,12 +248,19 @@ demoMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface rea
}
+static void
+demoUnload(_EGLDriver *drv)
+{
+ free(drv);
+}
+
+
/**
* The bootstrap function. Return a new DemoDriver object and
* plug in API functions.
*/
_EGLDriver *
-_eglMain(_EGLDisplay *dpy)
+_eglMain(const char *args)
{
DemoDriver *demo;
@@ -308,9 +282,8 @@ _eglMain(_EGLDisplay *dpy)
demo->Base.API.DestroySurface = demoDestroySurface;
demo->Base.API.DestroyContext = demoDestroyContext;
- /* enable supported extensions */
- demo->Base.Extensions.MESA_screen_surface = EGL_TRUE;
- demo->Base.Extensions.MESA_copy_context = EGL_TRUE;
+ demo->Base.Name = "egl/demo";
+ demo->Base.Unload = demoUnload;
return &demo->Base;
}
diff --git a/src/egl/drivers/dri/Makefile b/src/egl/drivers/dri/Makefile
index af0c40fe2b..7339c97c77 100644
--- a/src/egl/drivers/dri/Makefile
+++ b/src/egl/drivers/dri/Makefile
@@ -8,7 +8,7 @@ include $(TOP)/configs/current
INCLUDE_DIRS = \
-I. \
-I/usr/include \
- -I/usr/include/drm \
+ $(shell pkg-config --cflags-only-I libdrm) \
-I$(TOP)/include \
-I$(TOP)/include/GL/internal \
-I$(TOP)/src/mesa \
@@ -29,6 +29,8 @@ SOURCES = egldri.c
OBJECTS = $(SOURCES:.c=.o)
+DRM_LIB = `pkg-config --libs libdrm`
+
.c.o:
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
@@ -44,18 +46,23 @@ library: $(TOP)/$(LIB_DIR)/libEGLdri.so
$(TOP)/$(LIB_DIR)/libEGLdri.so: $(OBJECTS)
$(MKLIB) -o EGLdri -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-major 1 -minor 0 \
- -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS)
+ -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS) $(LIBS)
+install:
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/libEGLdri.so $(DESTDIR)$(INSTALL_LIB_DIR)
clean:
-rm -f *.o
-rm -f *.so
+ -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
+ $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null
include depend
# DO NOT DELETE
diff --git a/src/egl/drivers/dri/egldri.c b/src/egl/drivers/dri/egldri.c
index cab0be2bd1..9e400be624 100644
--- a/src/egl/drivers/dri/egldri.c
+++ b/src/egl/drivers/dri/egldri.c
@@ -1,5 +1,6 @@
/**
- * Generic EGL driver for DRI.
+ * Generic EGL driver for DRI. This is basically an "adaptor" driver
+ * that allows libEGL to load/use regular DRI drivers.
*
* This file contains all the code needed to interface DRI-based drivers
* with libEGL.
@@ -23,6 +24,7 @@
#include "egldisplay.h"
#include "eglcontext.h"
#include "eglconfig.h"
+#include "eglconfigutil.h"
#include "eglsurface.h"
#include "eglscreen.h"
#include "eglglobals.h"
@@ -32,18 +34,72 @@
#include "egldri.h"
const char *sysfs = "/sys/class";
-#define None 0
+
static const int empty_attribute_list[1] = { None };
+
+/**
+ * Given a card number, return the name of the DRI driver to use.
+ * This generally means reading the contents of
+ * /sys/class/drm/cardX/dri_library_name, where X is the card number
+ */
+static EGLBoolean
+driver_name_from_card_number(int card, char *driverName, int maxDriverName)
+{
+ char path[2000];
+ FILE *f;
+ int length;
+
+ snprintf(path, sizeof(path), "%s/drm/card%d/dri_library_name", sysfs, card);
+
+ f = fopen(path, "r");
+ if (!f)
+ return EGL_FALSE;
+
+ fgets(driverName, maxDriverName, f);
+ fclose(f);
+
+ if ((length = strlen(driverName)) > 1) {
+ /* remove the trailing newline from sysfs */
+ driverName[length - 1] = '\0';
+ strncat(driverName, "_dri", maxDriverName);
+ return EGL_TRUE;
+ }
+ else {
+ return EGL_FALSE;
+ }
+}
+
+
+
/**
* The bootstrap function.
* Return a new driDriver object and plug in API functions.
* This function, in turn, loads a specific DRI driver (ex: r200_dri.so).
*/
_EGLDriver *
-_eglMain(_EGLDisplay *dpy)
+_eglMain(_EGLDisplay *dpy, const char *args)
{
+#if 1
+ const int card = args ? atoi(args) : 0;
+ _EGLDriver *driver = NULL;
+ char driverName[1000];
+
+ if (!driver_name_from_card_number(card, driverName, sizeof(driverName))) {
+ _eglLog(_EGL_WARNING,
+ "Unable to determine driver name for card %d\n", card);
+ return NULL;
+ }
+
+ _eglLog(_EGL_DEBUG, "Driver name: %s\n", driverName);
+
+ driver = _eglOpenDriver(dpy, driverName, args);
+
+ return driver;
+
+#else
+
int length;
char path[NAME_MAX];
struct dirent *dirent;
@@ -58,14 +114,19 @@ _eglMain(_EGLDisplay *dpy)
_eglLog(_EGL_WARNING, "%s DRM devices not found.", path);
return EGL_FALSE;
}
+
+ /* loop over dir entries looking for cardX where "X" is in the
+ * dpy->DriverName ":X" string.
+ */
while ((dirent = readdir(dir))) {
if (strncmp(&dirent->d_name[0], "card", 4) != 0)
continue;
- if (strcmp(&dirent->d_name[4], &dpy->Name[1]) != 0)
+ if (strcmp(&dirent->d_name[4], &driverName[1]) != 0)
continue;
- snprintf(path, sizeof(path), "%s/drm/card%s/dri_library_name", sysfs, &dpy->Name[1]);
+ snprintf(path, sizeof(path), "%s/drm/card%s/dri_library_name",
+ sysfs, &driverName[1]);
_eglLog(_EGL_INFO, "Opening %s", path);
#if 1
file = fopen(path, "r");
@@ -89,6 +150,7 @@ _eglMain(_EGLDisplay *dpy)
closedir(dir);
return driver;
+#endif
}
@@ -109,7 +171,10 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
if (!c)
return EGL_NO_CONTEXT;
- if (!_eglInitContext(drv, dpy, &c->Base, config, attrib_list)) {
+ conf = _eglLookupConfig(drv, dpy, config);
+ assert(conf);
+
+ if (!_eglInitContext(drv, &c->Base, conf, attrib_list)) {
free(c);
return EGL_NO_CONTEXT;
}
@@ -127,8 +192,6 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
else
sharePriv = NULL;
- conf = _eglLookupConfig(drv, dpy, config);
- assert(conf);
_eglConfigToContextModesRec(conf, &visMode);
c->driContext.private = disp->driScreen.createNewContext(disp, &visMode,
@@ -138,10 +201,10 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
return EGL_FALSE;
}
- /* generate handle and insert into hash table */
- _eglSaveContext(&c->Base);
+ /* link to display */
+ _eglLinkContext(&c->Base, &disp->Base);
- return c->Base.Handle;
+ return _eglGetContextHandle(&c->Base);
}
@@ -152,13 +215,15 @@ _eglDRIMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw,
driDisplay *disp = Lookup_driDisplay(dpy);
driContext *ctx = Lookup_driContext(context);
EGLBoolean b;
+ __DRIid drawBuf = (__DRIid) draw;
+ __DRIid readBuf = (__DRIid) read;
b = _eglMakeCurrent(drv, dpy, draw, read, context);
if (!b)
return EGL_FALSE;
if (ctx) {
- ctx->driContext.bindContext(disp, 0, read, draw, &ctx->driContext);
+ ctx->driContext.bindContext(disp, 0, drawBuf, readBuf, &ctx->driContext);
}
else {
/* what's this??? */
@@ -173,14 +238,18 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
const EGLint *attrib_list)
{
driSurface *surf;
+ _EGLConfig *conf;
+
+ conf = _eglLookupConfig(drv, dpy, config);
+ assert(conf);
surf = (driSurface *) calloc(1, sizeof(*surf));
if (!surf) {
return EGL_NO_SURFACE;
}
- if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT,
- config, attrib_list)) {
+ if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT,
+ conf, attrib_list)) {
free(surf);
return EGL_NO_SURFACE;
}
@@ -190,7 +259,7 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
#if 0
GLcontext *ctx = NULL; /* this _should_ be OK */
#endif
- GLvisual visMode;
+ __GLcontextModes visMode;
_EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
assert(conf); /* bad config should be caught earlier */
_eglConfigToContextModesRec(conf, &visMode);
@@ -211,7 +280,7 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
#endif
}
- _eglSaveSurface(&surf->Base);
+ _eglLinkSurface(&surf->Base, _eglLookupDisplay(dpy));
return surf->Base.Handle;
}
@@ -223,16 +292,12 @@ _eglDRIDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
driDisplay *disp = Lookup_driDisplay(dpy);
driSurface *fs = Lookup_driSurface(surface);
- _eglRemoveSurface(&fs->Base);
+ _eglUnlinkSurface(&fs->Base);
fs->drawable.destroyDrawable(disp, fs->drawable.private);
- if (fs->Base.IsBound) {
- fs->Base.DeletePending = EGL_TRUE;
- }
- else {
+ if (!_eglIsSurfaceBound(&fs->Base))
free(fs);
- }
return EGL_TRUE;
}
@@ -243,16 +308,12 @@ _eglDRIDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
driDisplay *disp = Lookup_driDisplay(dpy);
driContext *fc = Lookup_driContext(context);
- _eglRemoveContext(&fc->Base);
+ _eglUnlinkContext(&fc->Base);
fc->driContext.destroyContext(disp, 0, fc->driContext.private);
- if (fc->Base.IsBound) {
- fc->Base.DeletePending = EGL_TRUE;
- }
- else {
+ if (!_eglIsContextBound(&fc->Base))
free(fc);
- }
return EGL_TRUE;
}
@@ -267,7 +328,8 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
_EGLConfig *config = _eglLookupConfig(drv, dpy, cfg);
driDisplay *disp = Lookup_driDisplay(dpy);
driSurface *surface;
- GLvisual visMode;
+ __GLcontextModes visMode;
+ __DRIid drawBuf;
surface = (driSurface *) calloc(1, sizeof(*surface));
if (!surface) {
@@ -275,13 +337,13 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
}
/* init base class, do error checking, etc. */
- if (!_eglInitSurface(drv, dpy, &surface->Base, EGL_SCREEN_BIT_MESA,
- cfg, attrib_list)) {
+ if (!_eglInitSurface(drv, &surface->Base, EGL_SCREEN_BIT_MESA,
+ config, attrib_list)) {
free(surface);
return EGL_NO_SURFACE;
}
- _eglSaveSurface(&surface->Base);
+ _eglLinkSurface(&surface->Base &disp->Base);
/*
@@ -292,11 +354,13 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
/* convert EGLConfig to GLvisual */
_eglConfigToContextModesRec(config, &visMode);
+ drawBuf = (__DRIid) _eglGetSurfaceHandle(&surface->Base);
+
/* Create a new DRI drawable */
- if (!disp->driScreen.createNewDrawable(disp, &visMode, surface->Base.Handle,
+ if (!disp->driScreen.createNewDrawable(disp, &visMode, drawBuf,
&surface->drawable, GLX_WINDOW_BIT,
empty_attribute_list)) {
- _eglRemoveSurface(&surface->Base);
+ _eglUnlinkSurface(&surface->Base);
free(surface);
return EGL_NO_SURFACE;
}
@@ -715,7 +779,7 @@ __eglGetDrawableInfo(__DRInativeDisplay * ndpy, int screen, __DRIid drawable,
{
__DRIscreen *pDRIScreen;
__DRIscreenPrivate *psp;
- driSurface *surf = Lookup_driSurface(drawable);
+ driSurface *surf = Lookup_driSurface((EGLSurface) drawable);
pDRIScreen = __eglFindDRIScreen(ndpy, screen);
@@ -1019,8 +1083,10 @@ _eglDRICreateDisplay(driDisplay *dpy, __DRIframebuffer *framebuffer)
api_ver,
& interface_methods,
NULL);
- if (!dpy->driScreen.private)
+ if (!dpy->driScreen.private) {
+ _eglLog(_EGL_WARNING, "egldri.c: DRI create new screen failed");
return EGL_FALSE;
+ }
DRM_UNLOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext );
@@ -1080,6 +1146,7 @@ _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy,
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
driDisplay *display;
+ const char *driverName = (const char *) disp->NativeDisplay;
assert(disp);
@@ -1088,13 +1155,13 @@ _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy,
*/
display = calloc(1, sizeof(*display));
display->Base = *disp;
- _eglHashInsert(_eglGlobal.Displays, disp->Handle, display);
+ _eglSaveDisplay(&display->Base);
free(disp);
*major = 1;
*minor = 0;
- sscanf(&disp->Name[1], "%d", &display->minor);
+ sscanf(driverName + 1, "%d", &display->minor);
drv->Initialized = EGL_TRUE;
return EGL_TRUE;
diff --git a/src/egl/drivers/dri/egldri.h b/src/egl/drivers/dri/egldri.h
index 34b12d64fc..54a9a4ea26 100644
--- a/src/egl/drivers/dri/egldri.h
+++ b/src/egl/drivers/dri/egldri.h
@@ -1,11 +1,14 @@
#ifndef EGLDRI_INCLUDED
#define EGLDRI_INCLUDED
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
#include "egldisplay.h"
#include "eglscreen.h"
#include "eglsurface.h"
#include "eglcontext.h"
-#include "mtypes.h"
+
#include "dri_util.h"
#include "drm_sarea.h"
@@ -14,7 +17,7 @@
*/
typedef struct dri_display
{
- _EGLDisplay Base; /* base class/object */
+ _EGLDisplay Base; /**< base class */
void *pFB;
int drmFD; /**< \brief DRM device file descriptor */
int minor;
@@ -32,7 +35,7 @@ typedef struct dri_display
unsigned long FBStart; /**< \brief physical address of the framebuffer */
void *driverClientMsg;
int driverClientMsgSize;
- int chipset;
+ unsigned chipset;
void *driverPrivate;
drm_magic_t magic;
diff --git a/src/egl/drivers/glx/Makefile b/src/egl/drivers/glx/Makefile
new file mode 100644
index 0000000000..20ef0352ad
--- /dev/null
+++ b/src/egl/drivers/glx/Makefile
@@ -0,0 +1,77 @@
+# src/egl/drivers/glx/Makefile
+
+# Build XEGL DRI driver loader library: egl_glx.so
+
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+EXTRA_DEFINES = -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\"
+
+DRIVER_NAME = egl_glx.so
+
+
+INCLUDE_DIRS = \
+ -I. \
+ -I/usr/include \
+ $(shell pkg-config --cflags-only-I libdrm) \
+ -I$(TOP)/include \
+ -I$(TOP)/include/GL/internal \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/src/glx/x11
+
+SOURCES = egl_glx.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+DRM_LIB = `pkg-config --libs libdrm`
+
+MISC_LIBS = -ldl -lXext -lGL
+
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@
+
+
+.PHONY: library
+
+
+default: depend library Makefile
+
+
+library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME)
+
+
+# Make the egl_glx.so library
+$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS)
+ $(TOP)/bin/mklib -o $(DRIVER_NAME) \
+ -noprefix \
+ -major 1 -minor 0 \
+ -L$(TOP)/$(LIB_DIR) \
+ -install $(TOP)/$(LIB_DIR) \
+ $(OBJECTS) $(DRM_LIB) $(MISC_LIBS)
+
+install:
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(DESTDIR)$(INSTALL_LIB_DIR)
+
+clean:
+ rm -f *.o
+ rm -f *.so
+ 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/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c
new file mode 100644
index 0000000000..4685f600e2
--- /dev/null
+++ b/src/egl/drivers/glx/egl_glx.c
@@ -0,0 +1,882 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * This is an EGL driver that wraps GLX. This gives the benefit of being
+ * completely agnostic of the direct rendering implementation.
+ *
+ * Authors: Alan Hourihane <alanh@tungstengraphics.com>
+ */
+
+/*
+ * TODO:
+ *
+ * test eglBind/ReleaseTexImage
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "dlfcn.h"
+#include <X11/Xlib.h>
+#include <GL/gl.h>
+#include "glxclient.h"
+
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "egllog.h"
+#include "eglsurface.h"
+
+#include <GL/gl.h>
+
+#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
+
+static const EGLint all_apis = (EGL_OPENGL_ES_BIT
+ | EGL_OPENGL_ES2_BIT
+ | EGL_OPENVG_BIT
+ /* | EGL_OPENGL_BIT */); /* can't do */
+
+struct visual_attribs
+{
+ /* X visual attribs */
+ int id;
+ int klass;
+ int depth;
+ int redMask, greenMask, blueMask;
+ int colormapSize;
+ int bitsPerRGB;
+
+ /* GL visual attribs */
+ int supportsGL;
+ int transparentType;
+ int transparentRedValue;
+ int transparentGreenValue;
+ int transparentBlueValue;
+ int transparentAlphaValue;
+ int transparentIndexValue;
+ int bufferSize;
+ int level;
+ int render_type;
+ int doubleBuffer;
+ int stereo;
+ int auxBuffers;
+ int redSize, greenSize, blueSize, alphaSize;
+ int depthSize;
+ int stencilSize;
+ int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
+ int numSamples, numMultisample;
+ int visualCaveat;
+};
+
+/** subclass of _EGLDriver */
+struct GLX_egl_driver
+{
+ _EGLDriver Base; /**< base class */
+};
+
+
+/** driver data of _EGLDisplay */
+struct GLX_egl_display
+{
+ Display *dpy;
+ XVisualInfo *visuals;
+ GLXFBConfig *fbconfigs;
+
+ int glx_maj, glx_min;
+};
+
+
+/** subclass of _EGLContext */
+struct GLX_egl_context
+{
+ _EGLContext Base; /**< base class */
+
+ GLXContext context;
+};
+
+
+/** subclass of _EGLSurface */
+struct GLX_egl_surface
+{
+ _EGLSurface Base; /**< base class */
+
+ GLXDrawable drawable;
+};
+
+
+/** subclass of _EGLConfig */
+struct GLX_egl_config
+{
+ _EGLConfig Base; /**< base class */
+ int index;
+};
+
+/** cast wrapper */
+static struct GLX_egl_driver *
+GLX_egl_driver(_EGLDriver *drv)
+{
+ return (struct GLX_egl_driver *) drv;
+}
+
+static struct GLX_egl_display *
+GLX_egl_display(_EGLDisplay *dpy)
+{
+ return (struct GLX_egl_display *) dpy->DriverData;
+}
+
+static struct GLX_egl_context *
+GLX_egl_context(_EGLContext *ctx)
+{
+ return (struct GLX_egl_context *) ctx;
+}
+
+static struct GLX_egl_surface *
+GLX_egl_surface(_EGLSurface *surf)
+{
+ return (struct GLX_egl_surface *) surf;
+}
+
+static int
+GLX_egl_config_index(_EGLConfig *conf)
+{
+ return ((struct GLX_egl_config *) conf)->index;
+}
+
+static GLboolean
+get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
+ struct visual_attribs *attribs)
+{
+ const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
+ int rgba;
+
+ memset(attribs, 0, sizeof(struct visual_attribs));
+
+ attribs->id = vInfo->visualid;
+#if defined(__cplusplus) || defined(c_plusplus)
+ attribs->klass = vInfo->c_class;
+#else
+ attribs->klass = vInfo->class;
+#endif
+ attribs->depth = vInfo->depth;
+ attribs->redMask = vInfo->red_mask;
+ attribs->greenMask = vInfo->green_mask;
+ attribs->blueMask = vInfo->blue_mask;
+ attribs->colormapSize = vInfo->colormap_size;
+ attribs->bitsPerRGB = vInfo->bits_per_rgb;
+
+ if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 ||
+ !attribs->supportsGL)
+ return GL_FALSE;
+ glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
+ glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
+ glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba);
+ if (!rgba)
+ return GL_FALSE;
+ attribs->render_type = GLX_RGBA_BIT;
+
+ glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
+ if (!attribs->doubleBuffer)
+ return GL_FALSE;
+
+ glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
+ glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
+ glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
+ glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
+ glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
+ glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
+ glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
+ glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
+ glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
+ glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
+ glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
+ glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
+
+ /* get transparent pixel stuff */
+ glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
+ if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
+ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
+ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
+ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
+ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
+ }
+ else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
+ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
+ }
+
+ /* multisample attribs */
+#ifdef GLX_ARB_multisample
+ if (ext && strstr(ext, "GLX_ARB_multisample")) {
+ glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
+ glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
+ }
+#endif
+ else {
+ attribs->numSamples = 0;
+ attribs->numMultisample = 0;
+ }
+
+#if defined(GLX_EXT_visual_rating)
+ if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
+ glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
+ }
+ else {
+ attribs->visualCaveat = GLX_NONE_EXT;
+ }
+#else
+ attribs->visualCaveat = 0;
+#endif
+
+ return GL_TRUE;
+}
+
+#ifdef GLX_VERSION_1_3
+
+static int
+glx_token_to_visual_class(int visual_type)
+{
+ switch (visual_type) {
+ case GLX_TRUE_COLOR:
+ return TrueColor;
+ case GLX_DIRECT_COLOR:
+ return DirectColor;
+ case GLX_PSEUDO_COLOR:
+ return PseudoColor;
+ case GLX_STATIC_COLOR:
+ return StaticColor;
+ case GLX_GRAY_SCALE:
+ return GrayScale;
+ case GLX_STATIC_GRAY:
+ return StaticGray;
+ case GLX_NONE:
+ default:
+ return None;
+ }
+}
+
+static int
+get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
+ struct visual_attribs *attribs)
+{
+ int visual_type;
+ int fbconfig_id;
+
+ memset(attribs, 0, sizeof(struct visual_attribs));
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &fbconfig_id);
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_VISUAL_ID, &attribs->id);
+
+#if 0
+ attribs->depth = vInfo->depth;
+ attribs->redMask = vInfo->red_mask;
+ attribs->greenMask = vInfo->green_mask;
+ attribs->blueMask = vInfo->blue_mask;
+ attribs->colormapSize = vInfo->colormap_size;
+ attribs->bitsPerRGB = vInfo->bits_per_rgb;
+#endif
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
+ attribs->klass = glx_token_to_visual_class(visual_type);
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type);
+ if (!(attribs->render_type & GLX_RGBA_BIT))
+ return 0;
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
+ if (!attribs->doubleBuffer)
+ return 0;
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize);
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
+
+ /* get transparent pixel stuff */
+ glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
+ if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
+ }
+ else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
+ }
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
+
+ if (attribs->id == 0) {
+ attribs->id = fbconfig_id;
+ return EGL_PBUFFER_BIT | EGL_PIXMAP_BIT;
+ }
+
+ return EGL_WINDOW_BIT;
+}
+
+#endif
+
+static EGLBoolean
+create_configs(_EGLDisplay *disp, struct GLX_egl_display *GLX_dpy)
+{
+ XVisualInfo theTemplate;
+ int numVisuals;
+ long mask;
+ int i;
+ struct visual_attribs attribs;
+
+ GLX_dpy->fbconfigs = NULL;
+
+#ifdef GLX_VERSION_1_3
+ /* get list of all fbconfigs on this screen */
+ GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, DefaultScreen(GLX_dpy->dpy), &numVisuals);
+
+ if (numVisuals == 0) {
+ GLX_dpy->fbconfigs = NULL;
+ goto xvisual;
+ }
+
+ for (i = 0; i < numVisuals; i++) {
+ struct GLX_egl_config *config;
+ int bit;
+
+ bit = get_fbconfig_attribs(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &attribs);
+ if (!bit)
+ continue;
+
+ config = CALLOC_STRUCT(GLX_egl_config);
+
+ config->index = i;
+ _eglInitConfig(&config->Base, (i+1));
+ SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, bit);
+
+ /* XXX possibly other things to init... */
+
+ _eglAddConfig(disp, &config->Base);
+ }
+
+ goto end;
+#endif
+
+xvisual:
+ /* get list of all visuals on this screen */
+ theTemplate.screen = DefaultScreen(GLX_dpy->dpy);
+ mask = VisualScreenMask;
+ GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &theTemplate, &numVisuals);
+
+ for (i = 0; i < numVisuals; i++) {
+ struct GLX_egl_config *config;
+
+ if (!get_visual_attribs(GLX_dpy->dpy, &GLX_dpy->visuals[i], &attribs))
+ continue;
+
+ config = CALLOC_STRUCT(GLX_egl_config);
+
+ config->index = i;
+ _eglInitConfig(&config->Base, (i+1));
+ SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE,
+ (EGL_WINDOW_BIT /*| EGL_PBUFFER_BIT | EGL_PIXMAP_BIT*/));
+
+ /* XXX possibly other things to init... */
+
+ _eglAddConfig(disp, &config->Base);
+ }
+
+end:
+ return EGL_TRUE;
+}
+
+/**
+ * Called via eglInitialize(), GLX_drv->API.Initialize().
+ */
+static EGLBoolean
+GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
+ EGLint *major, EGLint *minor)
+{
+ struct GLX_egl_display *GLX_dpy;
+
+ GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
+ if (!GLX_dpy)
+ return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+ GLX_dpy->dpy = (Display *) disp->NativeDisplay;
+ if (!GLX_dpy->dpy) {
+ GLX_dpy->dpy = XOpenDisplay(NULL);
+ if (!GLX_dpy->dpy) {
+ _eglLog(_EGL_WARNING, "GLX: XOpenDisplay failed");
+ free(GLX_dpy);
+ return EGL_FALSE;
+ }
+ }
+
+ disp->DriverData = (void *) GLX_dpy;
+ disp->ClientAPIsMask = all_apis;
+
+ glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min);
+
+ /* we're supporting EGL 1.4 */
+ *major = 1;
+ *minor = 4;
+
+ create_configs(disp, GLX_dpy);
+
+ return EGL_TRUE;
+}
+
+/**
+ * Called via eglTerminate(), drv->API.Terminate().
+ */
+static EGLBoolean
+GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
+{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+
+ _eglReleaseDisplayResources(drv, disp);
+ _eglCleanupDisplay(disp);
+
+ if (GLX_dpy->visuals)
+ XFree(GLX_dpy->visuals);
+ if (GLX_dpy->fbconfigs)
+ XFree(GLX_dpy->fbconfigs);
+
+ if (!disp->NativeDisplay)
+ XCloseDisplay(GLX_dpy->dpy);
+ free(GLX_dpy);
+
+ disp->DriverData = NULL;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglCreateContext(), drv->API.CreateContext().
+ */
+static _EGLContext *
+GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
+ _EGLContext *share_list, const EGLint *attrib_list)
+{
+ struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+ struct GLX_egl_context *GLX_ctx_shared = GLX_egl_context(share_list);
+
+ if (!GLX_ctx) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateContext");
+ return NULL;
+ }
+
+ if (!_eglInitContext(drv, &GLX_ctx->Base, conf, attrib_list)) {
+ free(GLX_ctx);
+ return NULL;
+ }
+
+#ifdef GLX_VERSION_1_3
+ if (GLX_dpy->fbconfigs)
+ GLX_ctx->context =
+ glXCreateNewContext(GLX_dpy->dpy,
+ GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+ GLX_RGBA_TYPE,
+ GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
+ GL_TRUE);
+ else
+#endif
+ GLX_ctx->context =
+ glXCreateContext(GLX_dpy->dpy,
+ &GLX_dpy->visuals[GLX_egl_config_index(conf)],
+ GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
+ GL_TRUE);
+ if (!GLX_ctx->context) {
+ free(GLX_ctx);
+ return NULL;
+ }
+
+#if 1
+ /* (maybe?) need to have a direct rendering context */
+ if (!glXIsDirect(GLX_dpy->dpy, GLX_ctx->context)) {
+ glXDestroyContext(GLX_dpy->dpy, GLX_ctx->context);
+ free(GLX_ctx);
+ return NULL;
+ }
+#endif
+
+ return &GLX_ctx->Base;
+}
+
+
+/**
+ * Called via eglMakeCurrent(), drv->API.MakeCurrent().
+ */
+static EGLBoolean
+GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
+ _EGLSurface *rsurf, _EGLContext *ctx)
+{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+ struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
+ struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
+ struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
+ GLXDrawable ddraw, rdraw;
+ GLXContext cctx;
+
+ if (!_eglMakeCurrent(drv, disp, dsurf, rsurf, ctx))
+ return EGL_FALSE;
+
+ ddraw = (GLX_dsurf) ? GLX_dsurf->drawable : None;
+ rdraw = (GLX_rsurf) ? GLX_rsurf->drawable : None;
+ cctx = (GLX_ctx) ? GLX_ctx->context : NULL;
+
+#ifdef GLX_VERSION_1_3
+ if (glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx))
+ return EGL_TRUE;
+#endif
+
+ if (ddraw == rdraw && glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx))
+ return EGL_TRUE;
+
+ return EGL_FALSE;
+}
+
+/** Get size of given window */
+static Status
+get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
+{
+ Window root;
+ Status stat;
+ int xpos, ypos;
+ unsigned int w, h, bw, depth;
+ stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+ *width = w;
+ *height = h;
+ return stat;
+}
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static _EGLSurface *
+GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
+ NativeWindowType window, const EGLint *attrib_list)
+{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+ struct GLX_egl_surface *GLX_surf;
+ uint width, height;
+
+ GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
+ if (!GLX_surf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_WINDOW_BIT,
+ conf, attrib_list)) {
+ free(GLX_surf);
+ return NULL;
+ }
+
+ GLX_surf->drawable = window;
+ get_drawable_size(GLX_dpy->dpy, window, &width, &height);
+ GLX_surf->Base.Width = width;
+ GLX_surf->Base.Height = height;
+
+ return &GLX_surf->Base;
+}
+
+#ifdef GLX_VERSION_1_3
+static _EGLSurface *
+GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
+ NativePixmapType pixmap, const EGLint *attrib_list)
+{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+ struct GLX_egl_surface *GLX_surf;
+ int i;
+
+ /* GLX must >= 1.3 */
+ if (!(GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3))
+ return NULL;
+
+ GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
+ if (!GLX_surf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PIXMAP_BIT,
+ conf, attrib_list)) {
+ free(GLX_surf);
+ return NULL;
+ }
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ /* no attribs at this time */
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface");
+ free(GLX_surf);
+ return NULL;
+ }
+ }
+
+ GLX_surf->drawable =
+ glXCreatePixmap(GLX_dpy->dpy,
+ GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+ pixmap, NULL);
+ if (!GLX_surf->drawable) {
+ free(GLX_surf);
+ return NULL;
+ }
+
+ return &GLX_surf->Base;
+}
+
+static _EGLSurface *
+GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
+ _EGLConfig *conf, const EGLint *attrib_list)
+{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+ struct GLX_egl_surface *GLX_surf;
+ int attribs[5];
+ int i = 0, j = 0;
+
+ /* GLX must >= 1.3 */
+ if (!(GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3))
+ return NULL;
+
+ GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
+ if (!GLX_surf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PBUFFER_BIT,
+ conf, attrib_list)) {
+ free(GLX_surf);
+ return NULL;
+ }
+
+ while(attrib_list[i] != EGL_NONE) {
+ switch (attrib_list[i]) {
+ case EGL_WIDTH:
+ attribs[j++] = GLX_PBUFFER_WIDTH;
+ attribs[j++] = attrib_list[i+1];
+ break;
+ case EGL_HEIGHT:
+ attribs[j++] = GLX_PBUFFER_HEIGHT;
+ attribs[j++] = attrib_list[i+1];
+ break;
+ }
+ i++;
+ }
+ attribs[j++] = 0;
+
+ GLX_surf->drawable =
+ glXCreatePbuffer(GLX_dpy->dpy,
+ GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+ attribs);
+ if (!GLX_surf->drawable) {
+ free(GLX_surf);
+ return NULL;
+ }
+
+ return &GLX_surf->Base;
+}
+#endif
+
+static EGLBoolean
+GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
+{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+ if (!_eglIsSurfaceBound(surf)) {
+ struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+ switch (surf->Type) {
+ case EGL_PBUFFER_BIT:
+ glXDestroyPbuffer(GLX_dpy->dpy, GLX_surf->drawable);
+ break;
+ case EGL_PIXMAP_BIT:
+ glXDestroyPixmap(GLX_dpy->dpy, GLX_surf->drawable);
+ break;
+ default:
+ break;
+ }
+ free(surf);
+ }
+
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+GLX_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
+ EGLint buffer)
+{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+ struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+
+ /* buffer ?? */
+ glXBindTexImageEXT(GLX_dpy->dpy, GLX_surf->drawable,
+ GLX_FRONT_LEFT_EXT, NULL);
+
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+GLX_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
+ EGLint buffer)
+{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+ struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+
+ /* buffer ?? */
+ glXReleaseTexImageEXT(GLX_dpy->dpy, GLX_surf->drawable,
+ GLX_FRONT_LEFT_EXT);
+
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
+{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+ struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw);
+
+ _eglLog(_EGL_DEBUG, "GLX: EGL SwapBuffers 0x%x",draw);
+
+ glXSwapBuffers(GLX_dpy->dpy, GLX_surf->drawable);
+
+ return EGL_TRUE;
+}
+
+/*
+ * Called from eglGetProcAddress() via drv->API.GetProcAddress().
+ */
+static _EGLProc
+GLX_eglGetProcAddress(const char *procname)
+{
+ /* This is a bit of a hack to get at the gallium/Mesa state tracker
+ * function st_get_proc_address(). This will probably change at
+ * some point.
+ */
+ _EGLProc (*get_proc_addr)(const char *procname);
+ _EGLProc proc_addr;
+ get_proc_addr = dlsym(NULL, "st_get_proc_address");
+ if (get_proc_addr)
+ return get_proc_addr(procname);
+
+ proc_addr = glXGetProcAddress((const GLubyte *)procname);
+ if (proc_addr)
+ return proc_addr;
+
+ return (_EGLProc)dlsym(NULL, procname);
+}
+
+
+static void
+GLX_Unload(_EGLDriver *drv)
+{
+ struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+ free(GLX_drv);
+}
+
+
+/**
+ * This is the main entrypoint into the driver, called by libEGL.
+ * Create a new _EGLDriver object and init its dispatch table.
+ */
+_EGLDriver *
+_eglMain(const char *args)
+{
+ struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
+
+ if (!GLX_drv)
+ return NULL;
+
+ _eglInitDriverFallbacks(&GLX_drv->Base);
+ GLX_drv->Base.API.Initialize = GLX_eglInitialize;
+ GLX_drv->Base.API.Terminate = GLX_eglTerminate;
+ GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
+ GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
+ GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
+#ifdef GLX_VERSION_1_3
+ GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
+ GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
+#endif
+ GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
+ GLX_drv->Base.API.BindTexImage = GLX_eglBindTexImage;
+ GLX_drv->Base.API.ReleaseTexImage = GLX_eglReleaseTexImage;
+ GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
+ GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
+
+ GLX_drv->Base.Name = "GLX";
+ GLX_drv->Base.Unload = GLX_Unload;
+
+ return &GLX_drv->Base;
+}
diff --git a/src/egl/drivers/xdri/Makefile b/src/egl/drivers/xdri/Makefile
new file mode 100644
index 0000000000..4c1fc9071c
--- /dev/null
+++ b/src/egl/drivers/xdri/Makefile
@@ -0,0 +1,78 @@
+# src/egl/drivers/xdri/Makefile
+
+# Build XEGL DRI driver loader library: egl_xdri.so
+
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+DRIVER_NAME = egl_xdri.so
+
+
+INCLUDE_DIRS = \
+ -I. \
+ -I/usr/include \
+ $(shell pkg-config --cflags-only-I libdrm) \
+ -I$(TOP)/include \
+ -I$(TOP)/include/GL/internal \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/src/glx/x11
+
+HEADERS = glxinit.h driinit.h
+SOURCES = egl_xdri.c glxinit.c driinit.c
+
+DRI_SOURCES = dri_common.c XF86dri.c dri2.c dri2_glx.c dri_glx.c
+DRI_SOURCES := $(addprefix ../../../glx/x11/,$(DRI_SOURCES))
+
+SOURCES += $(DRI_SOURCES)
+
+OBJECTS = $(SOURCES:.c=.o)
+
+DRM_LIB = `pkg-config --libs libdrm`
+
+CFLAGS += -DGLX_DIRECT_RENDERING
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+.PHONY: library
+
+
+default: depend library Makefile
+
+
+library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME)
+
+
+# Make the egl_xdri.so library
+$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS)
+ $(TOP)/bin/mklib -o $(DRIVER_NAME) \
+ -noprefix \
+ -major 1 -minor 0 \
+ -L$(TOP)/$(LIB_DIR) \
+ -install $(TOP)/$(LIB_DIR) \
+ $(OBJECTS) $(DRM_LIB) $(GL_LIB_DEPS)
+
+install:
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(DESTDIR)$(INSTALL_LIB_DIR)
+
+clean:
+ rm -f *.o
+ rm -f *.so
+ 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/drivers/xdri/driinit.c b/src/egl/drivers/xdri/driinit.c
new file mode 100644
index 0000000000..12da1bcd24
--- /dev/null
+++ b/src/egl/drivers/xdri/driinit.c
@@ -0,0 +1,67 @@
+/**
+ * DRI initialization. The DRI loaders are defined in src/glx/x11/.
+ */
+
+#include <sys/time.h>
+
+#include "glxclient.h"
+#include "driinit.h"
+
+/* for __DRI_SYSTEM_TIME extension */
+_X_HIDDEN int
+__glXGetUST(int64_t * ust)
+{
+ struct timeval tv;
+
+ if (ust == NULL) {
+ return -EFAULT;
+ }
+
+ if (gettimeofday(&tv, NULL) == 0) {
+ ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
+ return 0;
+ }
+ else {
+ return -errno;
+ }
+}
+
+_X_HIDDEN GLboolean
+__driGetMscRateOML(__DRIdrawable * draw,
+ int32_t * numerator, int32_t * denominator, void *private)
+{
+ return GL_FALSE;
+}
+
+/* ignore glx extensions */
+_X_HIDDEN void
+__glXEnableDirectExtension(__GLXscreenConfigs * psc, const char *name)
+{
+}
+
+_X_HIDDEN __GLXDRIdisplay *
+__driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version)
+{
+ __GLXDRIdisplay *driDisplay;
+ int ver = 0;
+
+ /* try DRI2 first */
+ driDisplay = dri2CreateDisplay(dpyPriv->dpy);
+ if (driDisplay) {
+ /* fill in the required field */
+ dpyPriv->dri2Display = driDisplay;
+ ver = 2;
+ }
+ else {
+ /* try DRI */
+ driDisplay = driCreateDisplay(dpyPriv->dpy);
+ if (driDisplay) {
+ dpyPriv->driDisplay = driDisplay;
+ ver = 1;
+ }
+ }
+
+ if (version)
+ *version = ver;
+ return driDisplay;
+}
diff --git a/src/egl/drivers/xdri/driinit.h b/src/egl/drivers/xdri/driinit.h
new file mode 100644
index 0000000000..6ea05cebef
--- /dev/null
+++ b/src/egl/drivers/xdri/driinit.h
@@ -0,0 +1,9 @@
+#ifndef DRIINIT_INCLUDED
+#define DRIINIT_INCLUDED
+
+#include "glxclient.h"
+
+extern __GLXDRIdisplay *
+__driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version);
+
+#endif /* DRIINIT_INCLUDED */
diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c
new file mode 100644
index 0000000000..9793e4f8b4
--- /dev/null
+++ b/src/egl/drivers/xdri/egl_xdri.c
@@ -0,0 +1,784 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Code to interface a DRI driver to libEGL.
+ * Note that unlike previous DRI/EGL interfaces, this one is meant to
+ * be used _with_ X. Applications will use eglCreateWindowSurface()
+ * to render into X-created windows.
+ *
+ * This is an EGL driver that, in turn, loads a regular DRI driver.
+ * There are some dependencies on code in libGL, but those could be
+ * removed with some effort.
+ *
+ * Authors: Brian Paul
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+
+#include "glxinit.h"
+#include "driinit.h"
+#include "glapi/glapi.h" /* for glapi functions */
+
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "egllog.h"
+#include "eglsurface.h"
+#include "eglimage.h"
+
+#include "EGL/internal/eglimage_dri.h"
+
+#define MAX_DEPTH 32
+#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
+
+/** subclass of _EGLDriver */
+struct xdri_egl_driver
+{
+ _EGLDriver Base; /**< base class */
+ void (*FlushCurrentContext)(void);
+};
+
+
+/** driver data of _EGLDisplay */
+struct xdri_egl_display
+{
+ Display *dpy;
+ __GLXdisplayPrivate *dpyPriv;
+ __GLXDRIdisplay *driDisplay;
+
+ __GLXscreenConfigs *psc;
+ EGLint scr;
+
+ const __GLcontextModes *imageConfigs[MAX_DEPTH + 1];
+};
+
+
+/** subclass of _EGLContext */
+struct xdri_egl_context
+{
+ _EGLContext Base; /**< base class */
+
+ /* just enough info to create dri contexts */
+ GLXContext dummy_gc;
+
+ __GLXDRIcontext *driContext;
+};
+
+
+/** subclass of _EGLSurface */
+struct xdri_egl_surface
+{
+ _EGLSurface Base; /**< base class */
+
+ Drawable drawable;
+ __GLXDRIdrawable *driDrawable;
+};
+
+
+/** subclass of _EGLImage */
+struct xdri_egl_image
+{
+ _EGLImage Base; /**< base class */
+
+ Drawable pixmap;
+ __GLXDRIdrawable *driDrawable;
+};
+
+
+/** subclass of _EGLConfig */
+struct xdri_egl_config
+{
+ _EGLConfig Base; /**< base class */
+
+ const __GLcontextModes *mode; /**< corresponding GLX mode */
+};
+
+
+
+/** cast wrapper */
+static INLINE struct xdri_egl_driver *
+xdri_egl_driver(_EGLDriver *drv)
+{
+ return (struct xdri_egl_driver *) drv;
+}
+
+
+static INLINE struct xdri_egl_display *
+lookup_display(_EGLDisplay *dpy)
+{
+ return (struct xdri_egl_display *) dpy->DriverData;
+}
+
+
+/** Map EGLSurface handle to xdri_egl_surface object */
+static INLINE struct xdri_egl_surface *
+lookup_surface(_EGLSurface *surface)
+{
+ return (struct xdri_egl_surface *) surface;
+}
+
+
+/** Map EGLContext handle to xdri_egl_context object */
+static INLINE struct xdri_egl_context *
+lookup_context(_EGLContext *context)
+{
+ return (struct xdri_egl_context *) context;
+}
+
+
+/** Map EGLConfig handle to xdri_egl_config object */
+static INLINE struct xdri_egl_config *
+lookup_config(_EGLConfig *conf)
+{
+ return (struct xdri_egl_config *) conf;
+}
+
+
+/** Map EGLImage handle to xdri_egl_image object */
+static INLINE struct xdri_egl_image *
+lookup_image(_EGLImage *img)
+{
+ return (struct xdri_egl_image *) img;
+}
+
+
+/** Get size of given window */
+static Status
+get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
+{
+ Window root;
+ Status stat;
+ int xpos, ypos;
+ unsigned int w, h, bw, depth;
+ stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+ *width = w;
+ *height = h;
+ return stat;
+}
+
+
+#if EGL_KHR_image_base
+/** Get depth of given window */
+static Status
+get_drawable_depth(Display *dpy, Drawable d, uint *depth_ret)
+{
+ Window root;
+ Status stat;
+ int xpos, ypos;
+ unsigned int w, h, bw, depth;
+ stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+ *depth_ret = depth;
+ return stat;
+}
+
+
+/**
+ * The config of a pixmap must be guessed from its depth. Do the guess once
+ * for all depths.
+ */
+static void
+find_image_configs(_EGLDisplay *dpy, const __GLcontextModes *modes)
+{
+ struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
+ EGLint depth;
+
+ for (depth = 0; depth < MAX_DEPTH + 1; depth++) {
+ const __GLcontextModes *m;
+
+ for (m = modes; m; m = m->next) {
+ /* the depth of a pixmap might not include alpha */
+ if (m->rgbBits != depth && (m->rgbBits - m->alphaBits) != depth)
+ continue;
+ if (!m->visualID)
+ continue;
+
+ if (depth == 32) {
+ if (m->bindToTextureRgba) {
+ xdri_dpy->imageConfigs[depth] = m;
+ break;
+ }
+ }
+
+ if (m->bindToTextureRgb) {
+ xdri_dpy->imageConfigs[depth] = m;
+ break;
+ }
+ }
+
+ if (m)
+ _eglLog(_EGL_DEBUG, "Use mode 0x%02x for depth %d",
+ m->visualID, depth);
+ }
+}
+#endif /* EGL_KHR_image_base */
+
+
+/**
+ * Produce a set of EGL configs.
+ */
+static EGLint
+create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id)
+{
+ static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
+ EGL_OPENGL_ES2_BIT |
+ EGL_OPENVG_BIT |
+ EGL_OPENGL_BIT);
+ int id = first_id;
+
+ for (; m; m = m->next) {
+ /* add double buffered visual */
+ if (m->doubleBufferMode) {
+ struct xdri_egl_config *config = CALLOC_STRUCT(xdri_egl_config);
+
+ _eglInitConfig(&config->Base, id++);
+
+ SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, m->rgbBits);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, m->redBits);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, m->greenBits);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, m->blueBits);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, m->alphaBits);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, m->depthBits);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, m->stencilBits);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, m->samples);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, m->sampleBuffers);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, m->visualID);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+
+ /* XXX possibly other things to init... */
+
+ /* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */
+ config->mode = m;
+
+ _eglAddConfig(disp, &config->Base);
+ }
+ }
+
+ return id;
+}
+
+
+/**
+ * Called via eglInitialize(), xdri_dpy->API.Initialize().
+ */
+static EGLBoolean
+xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
+ EGLint *minor, EGLint *major)
+{
+ struct xdri_egl_display *xdri_dpy;
+ __GLXdisplayPrivate *dpyPriv;
+ __GLXDRIdisplay *driDisplay;
+ __GLXscreenConfigs *psc;
+ EGLint first_id = 1;
+ int scr;
+
+ xdri_dpy = CALLOC_STRUCT(xdri_egl_display);
+ if (!xdri_dpy)
+ return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+ xdri_dpy->dpy = (Display *) dpy->NativeDisplay;
+ if (!xdri_dpy->dpy) {
+ xdri_dpy->dpy = XOpenDisplay(NULL);
+ if (!xdri_dpy->dpy) {
+ free(xdri_dpy);
+ return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
+ }
+ }
+
+ dpyPriv = __glXInitialize(xdri_dpy->dpy);
+ if (!dpyPriv) {
+ _eglLog(_EGL_WARNING, "failed to create GLX display");
+ free(xdri_dpy);
+ return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
+ }
+
+ driDisplay = __driCreateDisplay(dpyPriv, NULL);
+ if (!driDisplay) {
+ _eglLog(_EGL_WARNING, "failed to create DRI display");
+ free(xdri_dpy);
+ return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
+ }
+
+ scr = DefaultScreen(xdri_dpy->dpy);
+ psc = &dpyPriv->screenConfigs[scr];
+
+ xdri_dpy->dpyPriv = dpyPriv;
+ xdri_dpy->driDisplay = driDisplay;
+ xdri_dpy->psc = psc;
+ xdri_dpy->scr = scr;
+
+ psc->driScreen = driDisplay->createScreen(psc, scr, dpyPriv);
+ if (!psc->driScreen) {
+ _eglLog(_EGL_WARNING, "failed to create DRI screen #%d", scr);
+ free(xdri_dpy);
+ return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
+ }
+
+ /* add visuals and fbconfigs */
+ first_id = create_configs(dpy, psc->visuals, first_id);
+ create_configs(dpy, psc->configs, first_id);
+
+ dpy->DriverData = xdri_dpy;
+ dpy->ClientAPIsMask = (EGL_OPENGL_BIT |
+ EGL_OPENGL_ES_BIT |
+ EGL_OPENGL_ES2_BIT |
+ EGL_OPENVG_BIT);
+
+#if EGL_KHR_image_base
+ /* must be called after DriverData is set */
+ find_image_configs(dpy, psc->configs);
+
+ dpy->Extensions.KHR_image = EGL_TRUE;
+ dpy->Extensions.KHR_image_base = EGL_TRUE;
+ dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
+#endif
+
+ /* we're supporting EGL 1.4 */
+ *minor = 1;
+ *major = 4;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglTerminate(), drv->API.Terminate().
+ */
+static EGLBoolean
+xdri_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
+ __GLXscreenConfigs *psc;
+
+ _eglReleaseDisplayResources(drv, dpy);
+ _eglCleanupDisplay(dpy);
+
+ psc = xdri_dpy->psc;
+ if (psc->driver_configs) {
+ unsigned int i;
+ for (i = 0; psc->driver_configs[i]; i++)
+ free((__DRIconfig *) psc->driver_configs[i]);
+ free(psc->driver_configs);
+ psc->driver_configs = NULL;
+ }
+ if (psc->driScreen) {
+ psc->driScreen->destroyScreen(psc);
+ free(psc->driScreen);
+ psc->driScreen = NULL;
+ }
+
+ xdri_dpy->driDisplay->destroyDisplay(xdri_dpy->driDisplay);
+ __glXRelease(xdri_dpy->dpyPriv);
+
+ free(xdri_dpy);
+ dpy->DriverData = NULL;
+
+ return EGL_TRUE;
+}
+
+
+/*
+ * Called from eglGetProcAddress() via drv->API.GetProcAddress().
+ */
+static _EGLProc
+xdri_eglGetProcAddress(const char *procname)
+{
+ /* the symbol is defined in libGL.so */
+ return (_EGLProc) _glapi_get_proc_address(procname);
+}
+
+
+/**
+ * Called via eglCreateContext(), drv->API.CreateContext().
+ */
+static _EGLContext *
+xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+ _EGLContext *share_list, const EGLint *attrib_list)
+{
+ struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
+ struct xdri_egl_config *xdri_config = lookup_config(conf);
+ struct xdri_egl_context *shared = lookup_context(share_list);
+ __GLXscreenConfigs *psc = xdri_dpy->psc;
+ int renderType = GLX_RGBA_BIT;
+ struct xdri_egl_context *xdri_ctx;
+
+ xdri_ctx = CALLOC_STRUCT(xdri_egl_context);
+ if (!xdri_ctx) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateContext");
+ return NULL;
+ }
+
+ xdri_ctx->dummy_gc = CALLOC_STRUCT(__GLXcontextRec);
+ if (!xdri_ctx->dummy_gc) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateContext");
+ free(xdri_ctx);
+ return NULL;
+ }
+
+ if (!_eglInitContext(drv, &xdri_ctx->Base, &xdri_config->Base, attrib_list)) {
+ free(xdri_ctx->dummy_gc);
+ free(xdri_ctx);
+ return NULL;
+ }
+
+ xdri_ctx->driContext =
+ psc->driScreen->createContext(psc,
+ xdri_config->mode,
+ xdri_ctx->dummy_gc,
+ (shared) ? shared->dummy_gc : NULL,
+ renderType);
+ if (!xdri_ctx->driContext) {
+ free(xdri_ctx->dummy_gc);
+ free(xdri_ctx);
+ return NULL;
+ }
+
+ /* fill in the required field */
+ xdri_ctx->dummy_gc->driContext = xdri_ctx->driContext;
+
+ return &xdri_ctx->Base;
+}
+
+
+static EGLBoolean
+xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
+ struct xdri_egl_context *xdri_ctx = lookup_context(ctx);
+
+ if (!_eglIsContextBound(ctx)) {
+ xdri_ctx->driContext->destroyContext(xdri_ctx->driContext,
+ xdri_dpy->psc, xdri_dpy->dpy);
+ free(xdri_ctx->dummy_gc);
+ free(xdri_ctx);
+ }
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglMakeCurrent(), drv->API.MakeCurrent().
+ */
+static EGLBoolean
+xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d,
+ _EGLSurface *r, _EGLContext *context)
+{
+ struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv);
+ struct xdri_egl_context *xdri_ctx = lookup_context(context);
+ struct xdri_egl_surface *draw = lookup_surface(d);
+ struct xdri_egl_surface *read = lookup_surface(r);
+ _EGLContext *old = _eglGetCurrentContext();
+
+ /* an unlinked context will be invalid after context switch */
+ if (!_eglIsContextLinked(old))
+ old = NULL;
+
+ if (!_eglMakeCurrent(drv, dpy, d, r, context))
+ return EGL_FALSE;
+
+ /* flush before context switch */
+ if (old && old != context && xdri_driver->FlushCurrentContext)
+ xdri_driver->FlushCurrentContext();
+
+ /* the symbol is defined in libGL.so */
+ _glapi_check_multithread();
+
+ if (xdri_ctx) {
+ if (!xdri_ctx->driContext->bindContext(xdri_ctx->driContext,
+ draw->driDrawable,
+ read->driDrawable)) {
+ return EGL_FALSE;
+ }
+ }
+ else if (old) {
+ xdri_ctx = lookup_context(old);
+ xdri_ctx->driContext->unbindContext(xdri_ctx->driContext);
+ }
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static _EGLSurface *
+xdri_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+ NativeWindowType window, const EGLint *attrib_list)
+{
+ struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
+ struct xdri_egl_config *xdri_config = lookup_config(conf);
+ struct xdri_egl_surface *xdri_surf;
+ uint width, height;
+
+ xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
+ if (!xdri_surf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_WINDOW_BIT,
+ &xdri_config->Base, attrib_list)) {
+ free(xdri_surf);
+ return NULL;
+ }
+
+ xdri_surf->driDrawable =
+ xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc,
+ (XID) window,
+ (GLXDrawable) window,
+ xdri_config->mode);
+ if (!xdri_surf->driDrawable) {
+ free(xdri_surf);
+ return NULL;
+ }
+
+ xdri_surf->drawable = (Drawable) window;
+
+ get_drawable_size(xdri_dpy->dpy, window, &width, &height);
+ xdri_surf->Base.Width = width;
+ xdri_surf->Base.Height = height;
+
+ return &xdri_surf->Base;
+}
+
+
+/**
+ * Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface().
+ */
+static _EGLSurface *
+xdri_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+ const EGLint *attrib_list)
+{
+ return NULL;
+}
+
+
+
+static EGLBoolean
+xdri_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
+{
+ struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
+
+ if (!_eglIsSurfaceBound(&xdri_surf->Base)) {
+ xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable);
+ free(xdri_surf);
+ }
+
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+xdri_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
+ EGLint buffer)
+{
+ return EGL_FALSE;
+}
+
+
+static EGLBoolean
+xdri_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
+ EGLint buffer)
+{
+ return EGL_FALSE;
+}
+
+
+static EGLBoolean
+xdri_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
+{
+ struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv);
+ struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
+ struct xdri_egl_surface *xdri_surf = lookup_surface(draw);
+
+ /* swapBuffers does not flush commands */
+ if (draw == _eglGetCurrentSurface(EGL_DRAW) &&
+ xdri_driver->FlushCurrentContext)
+ xdri_driver->FlushCurrentContext();
+
+ xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable);
+
+ return EGL_TRUE;
+}
+
+
+#if EGL_KHR_image_base
+
+
+static _EGLImage *
+xdri_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
+ EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
+{
+ struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
+ struct xdri_egl_image *xdri_img;
+ __DRIEGLImage *driImage;
+ EGLint err = EGL_SUCCESS;
+ const __GLcontextModes *mode;
+ uint depth;
+
+ xdri_img = CALLOC_STRUCT(xdri_egl_image);
+ if (!xdri_img) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
+ return NULL;
+ }
+
+ switch (target) {
+ case EGL_NATIVE_PIXMAP_KHR:
+ if (ctx) {
+ err = EGL_BAD_PARAMETER;
+ break;
+ }
+ xdri_img->pixmap = (Pixmap) buffer;
+ break;
+ default:
+ err = EGL_BAD_PARAMETER;
+ break;
+ }
+
+ if (err != EGL_SUCCESS) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateImageKHR");
+ free(xdri_img);
+ return NULL;
+ }
+
+ if (!_eglInitImage(drv, &xdri_img->Base, attr_list)) {
+ free(xdri_img);
+ return NULL;
+ }
+ if (!get_drawable_depth(xdri_dpy->dpy, xdri_img->pixmap, &depth) ||
+ depth > MAX_DEPTH) {
+ free(xdri_img);
+ return NULL;
+ }
+ mode = xdri_dpy->imageConfigs[depth];
+ if (!mode) {
+ free(xdri_img);
+ return NULL;
+ }
+
+ driImage = CALLOC_STRUCT(__DRIEGLImageRec);
+ if (!driImage) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
+ free(xdri_img);
+ return NULL;
+ }
+
+ xdri_img->driDrawable =
+ xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc,
+ (XID) xdri_img->pixmap,
+ (GLXDrawable) xdri_img->pixmap,
+ mode);
+ if (!xdri_img->driDrawable) {
+ free(driImage);
+ free(xdri_img);
+ return NULL;
+ }
+
+ driImage->magic = __DRI_EGL_IMAGE_MAGIC;
+ driImage->drawable = xdri_img->driDrawable->driDrawable;
+ driImage->texture_format_rgba = (depth == 32 && mode->bindToTextureRgba);
+ driImage->level = 0;
+
+ xdri_img->Base.ClientData = (void *) driImage;
+
+ return &xdri_img->Base;
+}
+
+
+static EGLBoolean
+xdri_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
+{
+ struct xdri_egl_image *xdri_img = lookup_image(img);
+
+ free(xdri_img->Base.ClientData);
+ xdri_img->driDrawable->destroyDrawable(xdri_img->driDrawable);
+ free(xdri_img);
+ return EGL_TRUE;
+}
+
+
+#endif /* EGL_KHR_image_base */
+
+
+static void
+xdri_Unload(_EGLDriver *drv)
+{
+ struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
+ free(xdri_drv);
+}
+
+
+/**
+ * This is the main entrypoint into the driver, called by libEGL.
+ * Create a new _EGLDriver object and init its dispatch table.
+ */
+_EGLDriver *
+_eglMain(const char *args)
+{
+ struct xdri_egl_driver *xdri_drv = CALLOC_STRUCT(xdri_egl_driver);
+ if (!xdri_drv)
+ return NULL;
+
+ _eglInitDriverFallbacks(&xdri_drv->Base);
+ xdri_drv->Base.API.Initialize = xdri_eglInitialize;
+ xdri_drv->Base.API.Terminate = xdri_eglTerminate;
+
+ xdri_drv->Base.API.GetProcAddress = xdri_eglGetProcAddress;
+
+ xdri_drv->Base.API.CreateContext = xdri_eglCreateContext;
+ xdri_drv->Base.API.DestroyContext = xdri_eglDestroyContext;
+ xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent;
+ xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface;
+ xdri_drv->Base.API.CreatePbufferSurface = xdri_eglCreatePbufferSurface;
+ xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface;
+ xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage;
+ xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage;
+ xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers;
+#if EGL_KHR_image_base
+ xdri_drv->Base.API.CreateImageKHR = xdri_eglCreateImageKHR;
+ xdri_drv->Base.API.DestroyImageKHR = xdri_eglDestroyImageKHR;
+#endif /* EGL_KHR_image_base */
+
+ xdri_drv->Base.Name = "X/DRI";
+ xdri_drv->Base.Unload = xdri_Unload;
+
+ /* we need a way to flush commands */
+ xdri_drv->FlushCurrentContext =
+ (void (*)(void)) xdri_eglGetProcAddress("glFlush");
+
+ return &xdri_drv->Base;
+}
diff --git a/src/egl/drivers/xdri/glxinit.c b/src/egl/drivers/xdri/glxinit.c
new file mode 100644
index 0000000000..7775009394
--- /dev/null
+++ b/src/egl/drivers/xdri/glxinit.c
@@ -0,0 +1,626 @@
+/**
+ * GLX initialization. Code based on glxext.c, glx_query.c, and
+ * glcontextmodes.c under src/glx/x11/. The major difference is that no DRI
+ * related code here.
+ *
+ */
+
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include <sys/time.h>
+
+#include "glxinit.h"
+
+typedef struct GLXGenericGetString
+{
+ CARD8 reqType;
+ CARD8 glxCode;
+ CARD16 length B16;
+ CARD32 for_whom B32;
+ CARD32 name B32;
+} xGLXGenericGetStringReq;
+
+#define sz_xGLXGenericGetStringReq 12
+#define X_GLXGenericGetString 0
+
+/* Extension required boiler plate */
+
+static char *__glXExtensionName = GLX_EXTENSION_NAME;
+static XExtensionInfo *__glXExtensionInfo = NULL;
+
+static /* const */ XExtensionHooks __glXExtensionHooks = { NULL };
+static
+XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
+ __glXExtensionName, &__glXExtensionHooks,
+ __GLX_NUMBER_EVENTS, NULL)
+
+static GLint
+_gl_convert_from_x_visual_type(int visualType)
+{
+#define NUM_VISUAL_TYPES 6
+ static const int glx_visual_types[NUM_VISUAL_TYPES] = {
+ GLX_STATIC_GRAY, GLX_GRAY_SCALE,
+ GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
+ GLX_TRUE_COLOR, GLX_DIRECT_COLOR
+ };
+
+ return ((unsigned) visualType < NUM_VISUAL_TYPES)
+ ? glx_visual_types[visualType] : GLX_NONE;
+}
+
+static __GLcontextModes *
+_gl_context_modes_create(unsigned count, size_t minimum_size)
+{
+ const size_t size = (minimum_size > sizeof(__GLcontextModes))
+ ? minimum_size : sizeof(__GLcontextModes);
+ __GLcontextModes *base = NULL;
+ __GLcontextModes **next;
+ unsigned i;
+
+ next = &base;
+ for (i = 0; i < count; i++) {
+ *next = (__GLcontextModes *) Xmalloc(size);
+ if (*next == NULL) {
+ _gl_context_modes_destroy(base);
+ base = NULL;
+ break;
+ }
+
+ memset(*next, 0, size);
+ (*next)->visualID = GLX_DONT_CARE;
+ (*next)->visualType = GLX_DONT_CARE;
+ (*next)->visualRating = GLX_NONE;
+ (*next)->transparentPixel = GLX_NONE;
+ (*next)->transparentRed = GLX_DONT_CARE;
+ (*next)->transparentGreen = GLX_DONT_CARE;
+ (*next)->transparentBlue = GLX_DONT_CARE;
+ (*next)->transparentAlpha = GLX_DONT_CARE;
+ (*next)->transparentIndex = GLX_DONT_CARE;
+ (*next)->xRenderable = GLX_DONT_CARE;
+ (*next)->fbconfigID = GLX_DONT_CARE;
+ (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
+ (*next)->bindToTextureRgb = GLX_DONT_CARE;
+ (*next)->bindToTextureRgba = GLX_DONT_CARE;
+ (*next)->bindToMipmapTexture = GLX_DONT_CARE;
+ (*next)->bindToTextureTargets = GLX_DONT_CARE;
+ (*next)->yInverted = GLX_DONT_CARE;
+
+ next = &((*next)->next);
+ }
+
+ return base;
+}
+
+_X_HIDDEN void
+_gl_context_modes_destroy(__GLcontextModes * modes)
+{
+ while (modes != NULL) {
+ __GLcontextModes *const next = modes->next;
+
+ Xfree(modes);
+ modes = next;
+ }
+}
+
+_X_HIDDEN char *
+__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
+{
+ xGLXGenericGetStringReq *req;
+ xGLXSingleReply reply;
+ int length;
+ int numbytes;
+ char *buf;
+ CARD32 for_whom = screen;
+ CARD32 glxCode = X_GLXQueryServerString;
+
+
+ LockDisplay(dpy);
+
+
+ /* All of the GLX protocol requests for getting a string from the server
+ * look the same. The exact meaning of the for_whom field is usually
+ * either the screen number (for glXQueryServerString) or the context tag
+ * (for GLXSingle).
+ */
+
+ GetReq(GLXGenericGetString, req);
+ req->reqType = opcode;
+ req->glxCode = glxCode;
+ req->for_whom = for_whom;
+ req->name = name;
+
+ _XReply(dpy, (xReply *) & reply, 0, False);
+
+ length = reply.length * 4;
+ numbytes = reply.size;
+
+ buf = (char *) Xmalloc(numbytes);
+ if (buf != NULL) {
+ _XRead(dpy, buf, numbytes);
+ length -= numbytes;
+ }
+
+ _XEatData(dpy, length);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return buf;
+}
+
+/************************************************************************/
+/*
+** Free the per screen configs data as well as the array of
+** __glXScreenConfigs.
+*/
+static void
+FreeScreenConfigs(__GLXdisplayPrivate * priv)
+{
+ __GLXscreenConfigs *psc;
+ GLint i, screens;
+
+ /* Free screen configuration information */
+ psc = priv->screenConfigs;
+ screens = ScreenCount(priv->dpy);
+ for (i = 0; i < screens; i++, psc++) {
+ if (psc->configs) {
+ _gl_context_modes_destroy(psc->configs);
+ psc->configs = NULL; /* NOTE: just for paranoia */
+ }
+ if (psc->visuals) {
+ _gl_context_modes_destroy(psc->visuals);
+ psc->visuals = NULL; /* NOTE: just for paranoia */
+ }
+ Xfree((char *) psc->serverGLXexts);
+ }
+ XFree((char *) priv->screenConfigs);
+ priv->screenConfigs = NULL;
+}
+
+/************************************************************************/
+
+/*
+** Query the version of the GLX extension. This procedure works even if
+** the client extension is not completely set up.
+*/
+static Bool
+QueryVersion(Display * dpy, int opcode, int *major, int *minor)
+{
+ xGLXQueryVersionReq *req;
+ xGLXQueryVersionReply reply;
+
+ /* Send the glXQueryVersion request */
+ LockDisplay(dpy);
+ GetReq(GLXQueryVersion, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXQueryVersion;
+ req->majorVersion = GLX_MAJOR_VERSION;
+ req->minorVersion = GLX_MINOR_VERSION;
+ _XReply(dpy, (xReply *) & reply, 0, False);
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ if (reply.majorVersion != GLX_MAJOR_VERSION) {
+ /*
+ ** The server does not support the same major release as this
+ ** client.
+ */
+ return GL_FALSE;
+ }
+ *major = reply.majorVersion;
+ *minor = min(reply.minorVersion, GLX_MINOR_VERSION);
+ return GL_TRUE;
+}
+
+_X_HIDDEN void
+__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
+ const INT32 * bp, Bool tagged_only,
+ Bool fbconfig_style_tags)
+{
+ int i;
+
+ if (!tagged_only) {
+ /* Copy in the first set of properties */
+ config->visualID = *bp++;
+
+ config->visualType = _gl_convert_from_x_visual_type(*bp++);
+
+ config->rgbMode = *bp++;
+
+ config->redBits = *bp++;
+ config->greenBits = *bp++;
+ config->blueBits = *bp++;
+ config->alphaBits = *bp++;
+ config->accumRedBits = *bp++;
+ config->accumGreenBits = *bp++;
+ config->accumBlueBits = *bp++;
+ config->accumAlphaBits = *bp++;
+
+ config->doubleBufferMode = *bp++;
+ config->stereoMode = *bp++;
+
+ config->rgbBits = *bp++;
+ config->depthBits = *bp++;
+ config->stencilBits = *bp++;
+ config->numAuxBuffers = *bp++;
+ config->level = *bp++;
+
+ count -= __GLX_MIN_CONFIG_PROPS;
+ }
+
+ /*
+ ** Additional properties may be in a list at the end
+ ** of the reply. They are in pairs of property type
+ ** and property value.
+ */
+
+#define FETCH_OR_SET(tag) \
+ config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
+
+ for (i = 0; i < count; i += 2) {
+ switch (*bp++) {
+ case GLX_RGBA:
+ FETCH_OR_SET(rgbMode);
+ break;
+ case GLX_BUFFER_SIZE:
+ config->rgbBits = *bp++;
+ break;
+ case GLX_LEVEL:
+ config->level = *bp++;
+ break;
+ case GLX_DOUBLEBUFFER:
+ FETCH_OR_SET(doubleBufferMode);
+ break;
+ case GLX_STEREO:
+ FETCH_OR_SET(stereoMode);
+ break;
+ case GLX_AUX_BUFFERS:
+ config->numAuxBuffers = *bp++;
+ break;
+ case GLX_RED_SIZE:
+ config->redBits = *bp++;
+ break;
+ case GLX_GREEN_SIZE:
+ config->greenBits = *bp++;
+ break;
+ case GLX_BLUE_SIZE:
+ config->blueBits = *bp++;
+ break;
+ case GLX_ALPHA_SIZE:
+ config->alphaBits = *bp++;
+ break;
+ case GLX_DEPTH_SIZE:
+ config->depthBits = *bp++;
+ break;
+ case GLX_STENCIL_SIZE:
+ config->stencilBits = *bp++;
+ break;
+ case GLX_ACCUM_RED_SIZE:
+ config->accumRedBits = *bp++;
+ break;
+ case GLX_ACCUM_GREEN_SIZE:
+ config->accumGreenBits = *bp++;
+ break;
+ case GLX_ACCUM_BLUE_SIZE:
+ config->accumBlueBits = *bp++;
+ break;
+ case GLX_ACCUM_ALPHA_SIZE:
+ config->accumAlphaBits = *bp++;
+ break;
+ case GLX_VISUAL_CAVEAT_EXT:
+ config->visualRating = *bp++;
+ break;
+ case GLX_X_VISUAL_TYPE:
+ config->visualType = *bp++;
+ break;
+ case GLX_TRANSPARENT_TYPE:
+ config->transparentPixel = *bp++;
+ break;
+ case GLX_TRANSPARENT_INDEX_VALUE:
+ config->transparentIndex = *bp++;
+ break;
+ case GLX_TRANSPARENT_RED_VALUE:
+ config->transparentRed = *bp++;
+ break;
+ case GLX_TRANSPARENT_GREEN_VALUE:
+ config->transparentGreen = *bp++;
+ break;
+ case GLX_TRANSPARENT_BLUE_VALUE:
+ config->transparentBlue = *bp++;
+ break;
+ case GLX_TRANSPARENT_ALPHA_VALUE:
+ config->transparentAlpha = *bp++;
+ break;
+ case GLX_VISUAL_ID:
+ config->visualID = *bp++;
+ break;
+ case GLX_DRAWABLE_TYPE:
+ config->drawableType = *bp++;
+ break;
+ case GLX_RENDER_TYPE:
+ config->renderType = *bp++;
+ break;
+ case GLX_X_RENDERABLE:
+ config->xRenderable = *bp++;
+ break;
+ case GLX_FBCONFIG_ID:
+ config->fbconfigID = *bp++;
+ break;
+ case GLX_MAX_PBUFFER_WIDTH:
+ config->maxPbufferWidth = *bp++;
+ break;
+ case GLX_MAX_PBUFFER_HEIGHT:
+ config->maxPbufferHeight = *bp++;
+ break;
+ case GLX_MAX_PBUFFER_PIXELS:
+ config->maxPbufferPixels = *bp++;
+ break;
+ case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
+ config->optimalPbufferWidth = *bp++;
+ break;
+ case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
+ config->optimalPbufferHeight = *bp++;
+ break;
+ case GLX_VISUAL_SELECT_GROUP_SGIX:
+ config->visualSelectGroup = *bp++;
+ break;
+ case GLX_SWAP_METHOD_OML:
+ config->swapMethod = *bp++;
+ break;
+ case GLX_SAMPLE_BUFFERS_SGIS:
+ config->sampleBuffers = *bp++;
+ break;
+ case GLX_SAMPLES_SGIS:
+ config->samples = *bp++;
+ break;
+ case GLX_BIND_TO_TEXTURE_RGB_EXT:
+ config->bindToTextureRgb = *bp++;
+ break;
+ case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+ config->bindToTextureRgba = *bp++;
+ break;
+ case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+ config->bindToMipmapTexture = *bp++;
+ break;
+ case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+ config->bindToTextureTargets = *bp++;
+ break;
+ case GLX_Y_INVERTED_EXT:
+ config->yInverted = *bp++;
+ break;
+ case None:
+ i = count;
+ break;
+ default:
+ break;
+ }
+ }
+
+ config->renderType =
+ (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
+
+ config->haveAccumBuffer = ((config->accumRedBits +
+ config->accumGreenBits +
+ config->accumBlueBits +
+ config->accumAlphaBits) > 0);
+ config->haveDepthBuffer = (config->depthBits > 0);
+ config->haveStencilBuffer = (config->stencilBits > 0);
+}
+
+static __GLcontextModes *
+createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
+ int screen, GLboolean tagged_only)
+{
+ INT32 buf[__GLX_TOTAL_CONFIG], *props;
+ unsigned prop_size;
+ __GLcontextModes *modes, *m;
+ int i;
+
+ if (nprops == 0)
+ return NULL;
+
+ /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
+
+ /* Check number of properties */
+ if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
+ return NULL;
+
+ /* Allocate memory for our config structure */
+ modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes));
+ if (!modes)
+ return NULL;
+
+ prop_size = nprops * __GLX_SIZE_INT32;
+ if (prop_size <= sizeof(buf))
+ props = buf;
+ else
+ props = Xmalloc(prop_size);
+
+ /* Read each config structure and convert it into our format */
+ m = modes;
+ for (i = 0; i < nvisuals; i++) {
+ _XRead(dpy, (char *) props, prop_size);
+ /* Older X servers don't send this so we default it here. */
+ m->drawableType = GLX_WINDOW_BIT;
+ __glXInitializeVisualConfigFromTags(m, nprops, props,
+ tagged_only, GL_TRUE);
+ m->screen = screen;
+ m = m->next;
+ }
+
+ if (props != buf)
+ Xfree(props);
+
+ return modes;
+}
+
+static GLboolean
+getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
+{
+ xGLXGetVisualConfigsReq *req;
+ __GLXscreenConfigs *psc;
+ xGLXGetVisualConfigsReply reply;
+
+ LockDisplay(dpy);
+
+ psc = priv->screenConfigs + screen;
+ psc->visuals = NULL;
+ GetReq(GLXGetVisualConfigs, req);
+ req->reqType = priv->majorOpcode;
+ req->glxCode = X_GLXGetVisualConfigs;
+ req->screen = screen;
+
+ if (!_XReply(dpy, (xReply *) & reply, 0, False))
+ goto out;
+
+ psc->visuals = createConfigsFromProperties(dpy,
+ reply.numVisuals,
+ reply.numProps,
+ screen, GL_FALSE);
+
+ out:
+ UnlockDisplay(dpy);
+ return psc->visuals != NULL;
+}
+
+static GLboolean
+getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
+{
+ xGLXGetFBConfigsReq *fb_req;
+ xGLXGetFBConfigsSGIXReq *sgi_req;
+ xGLXVendorPrivateWithReplyReq *vpreq;
+ xGLXGetFBConfigsReply reply;
+ __GLXscreenConfigs *psc;
+
+ psc = priv->screenConfigs + screen;
+ psc->serverGLXexts =
+ __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
+
+ LockDisplay(dpy);
+
+ psc->configs = NULL;
+ if (atof(priv->serverGLXversion) >= 1.3) {
+ GetReq(GLXGetFBConfigs, fb_req);
+ fb_req->reqType = priv->majorOpcode;
+ fb_req->glxCode = X_GLXGetFBConfigs;
+ fb_req->screen = screen;
+ }
+ else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
+ GetReqExtra(GLXVendorPrivateWithReply,
+ sz_xGLXGetFBConfigsSGIXReq +
+ sz_xGLXVendorPrivateWithReplyReq, vpreq);
+ sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
+ sgi_req->reqType = priv->majorOpcode;
+ sgi_req->glxCode = X_GLXVendorPrivateWithReply;
+ sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
+ sgi_req->screen = screen;
+ }
+ else
+ goto out;
+
+ if (!_XReply(dpy, (xReply *) & reply, 0, False))
+ goto out;
+
+ psc->configs = createConfigsFromProperties(dpy,
+ reply.numFBConfigs,
+ reply.numAttribs * 2,
+ screen, GL_TRUE);
+
+ out:
+ UnlockDisplay(dpy);
+ return psc->configs != NULL;
+}
+
+static GLboolean
+AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
+{
+ __GLXscreenConfigs *psc;
+ GLint i, screens;
+
+ /*
+ ** First allocate memory for the array of per screen configs.
+ */
+ screens = ScreenCount(dpy);
+ psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
+ if (!psc) {
+ return GL_FALSE;
+ }
+ memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
+ priv->screenConfigs = psc;
+
+ priv->serverGLXversion =
+ __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
+ if (priv->serverGLXversion == NULL) {
+ FreeScreenConfigs(priv);
+ return GL_FALSE;
+ }
+
+ for (i = 0; i < screens; i++, psc++) {
+ getFBConfigs(dpy, priv, i);
+ getVisualConfigs(dpy, priv, i);
+ psc->scr = i;
+ psc->dpy = dpy;
+ }
+
+ SyncHandle();
+
+ return GL_TRUE;
+}
+
+_X_HIDDEN void
+__glXRelease(__GLXdisplayPrivate *dpyPriv)
+{
+ FreeScreenConfigs(dpyPriv);
+
+ if (dpyPriv->serverGLXvendor) {
+ Xfree((char *) dpyPriv->serverGLXvendor);
+ dpyPriv->serverGLXvendor = NULL;
+ }
+ if (dpyPriv->serverGLXversion) {
+ Xfree((char *) dpyPriv->serverGLXversion);
+ dpyPriv->serverGLXversion = NULL;
+ }
+
+ Xfree(dpyPriv);
+}
+
+_X_HIDDEN __GLXdisplayPrivate *
+__glXInitialize(Display * dpy)
+{
+ XExtDisplayInfo *info = __glXFindDisplay(dpy);
+ __GLXdisplayPrivate *dpyPriv;
+ int major, minor;
+
+ if (!XextHasExtension(info))
+ return NULL;
+
+ /* See if the versions are compatible */
+ if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor))
+ return NULL;
+
+ dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate));
+ if (!dpyPriv)
+ return NULL;
+
+ /*
+ ** Init the display private and then read in the screen config
+ ** structures from the server.
+ */
+ dpyPriv->majorOpcode = info->codes->major_opcode;
+ dpyPriv->majorVersion = major;
+ dpyPriv->minorVersion = minor;
+ dpyPriv->dpy = dpy;
+
+ dpyPriv->serverGLXvendor = NULL;
+ dpyPriv->serverGLXversion = NULL;
+
+ if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
+ Xfree(dpyPriv);
+ return NULL;
+ }
+
+ return dpyPriv;
+}
diff --git a/src/egl/drivers/xdri/glxinit.h b/src/egl/drivers/xdri/glxinit.h
new file mode 100644
index 0000000000..57206e627b
--- /dev/null
+++ b/src/egl/drivers/xdri/glxinit.h
@@ -0,0 +1,14 @@
+#ifndef GLXINIT_INCLUDED
+#define GLXINIT_INCLUDED
+
+#include <X11/Xlib.h>
+#include "glxclient.h"
+
+/* this is used by DRI loaders */
+extern void
+_gl_context_modes_destroy(__GLcontextModes * modes);
+
+extern void
+__glXRelease(__GLXdisplayPrivate *dpyPriv);
+
+#endif /* GLXINIT_INCLUDED */
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
index 7ab78197c7..1fc51e930e 100644
--- a/src/egl/main/Makefile
+++ b/src/egl/main/Makefile
@@ -4,38 +4,55 @@ TOP = ../../..
include $(TOP)/configs/current
-INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi
+INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi $(X11_INCLUDES)
HEADERS = \
+ eglclient.h \
+ eglcompiler.h \
eglconfig.h \
+ eglconfigutil.h \
eglcontext.h \
+ eglcurrent.h \
+ egldefines.h \
egldisplay.h \
egldriver.h \
eglglobals.h \
+ eglimage.h \
egllog.h \
- eglhash.h \
+ eglmisc.h \
eglmode.h \
+ eglmutex.h \
eglscreen.h \
+ eglstring.h \
eglsurface.h
SOURCES = \
eglapi.c \
+ eglclient.c \
eglconfig.c \
+ eglconfigutil.c \
eglcontext.c \
+ eglcurrent.c \
egldisplay.c \
egldriver.c \
eglglobals.c \
+ eglimage.c \
egllog.c \
- eglhash.c \
+ eglmisc.c \
eglmode.c \
eglscreen.c \
+ eglstring.c \
eglsurface.c
OBJECTS = $(SOURCES:.c=.o)
+# Undefined for now
+LOCAL_CFLAGS = -D_EGL_PLATFORM_X=1
+
+
.c.o:
- $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@
@@ -48,20 +65,26 @@ library: $(TOP)/$(LIB_DIR)/libEGL.so
$(TOP)/$(LIB_DIR)/libEGL.so: $(OBJECTS)
$(MKLIB) -o EGL -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-major 1 -minor 0 \
- -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS)
-
+ -install $(TOP)/$(LIB_DIR) \
+ $(EGL_LIB_DEPS) $(OBJECTS)
+install: default
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/libEGL.so* $(DESTDIR)$(INSTALL_LIB_DIR)
clean:
-rm -f *.o *.so*
-rm -f core.*
+ -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
+ $(SOURCES) $(HEADERS) > /dev/null 2>/dev/null
+
include depend
# DO NOT DELETE
diff --git a/src/egl/main/README.txt b/src/egl/main/README.txt
new file mode 100644
index 0000000000..b3d253dd13
--- /dev/null
+++ b/src/egl/main/README.txt
@@ -0,0 +1,71 @@
+
+
+Notes about the EGL library:
+
+
+The EGL code here basically consists of two things:
+
+1. An EGL API dispatcher. This directly routes all the eglFooBar() API
+ calls into driver-specific functions.
+
+2. Fallbacks for EGL API functions. A driver _could_ implement all the
+ EGL API calls from scratch. But in many cases, the fallbacks provided
+ in libEGL (such as eglChooseConfig()) will do the job.
+
+
+
+Bootstrapping:
+
+When the apps calls eglOpenDisplay() a device driver is selected and loaded
+(look for dlsym() or LoadLibrary() in egldriver.c).
+
+The driver's _eglMain() function is then called. This driver function
+allocates, initializes and returns a new _EGLDriver object (usually a
+subclass of that type).
+
+As part of initialization, the dispatch table in _EGLDriver->API must be
+populated with all the EGL entrypoints. Typically, _eglInitDriverFallbacks()
+can be used to plug in default/fallback functions. Some functions like
+driver->API.Initialize and driver->API.Terminate _must_ be implemented
+with driver-specific code (no default/fallback function is possible).
+
+
+A bit later, the app will call eglInitialize(). This will get routed
+to the driver->API.Initialize() function. Any additional driver
+initialization that wasn't done in _eglMain() should be done at this
+point. Typically, this will involve setting up visual configs, etc.
+
+
+
+Special Functions:
+
+Certain EGL functions _must_ be implemented by the driver. This includes:
+
+eglCreateContext
+eglCreateWindowSurface
+eglCreatePixmapSurface
+eglCreatePBufferSurface
+eglMakeCurrent
+eglSwapBuffers
+
+Most of the EGLConfig-related functions can be implemented with the
+defaults/fallbacks. Same thing for the eglGet/Query functions.
+
+
+
+
+Teardown:
+
+When eglTerminate() is called, the driver->API.Terminate() function is
+called. The driver should clean up after itself. eglTerminate() will
+then close/unload the driver (shared library).
+
+
+
+
+Subclassing:
+
+The internal libEGL data structures such as _EGLDisplay, _EGLContext,
+_EGLSurface, etc should be considered base classes from which drivers
+will derive subclasses.
+
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index bfa580e6c3..d39266fda3 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -29,7 +29,6 @@
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -39,276 +38,554 @@
#include "eglglobals.h"
#include "egldriver.h"
#include "eglsurface.h"
-
+#include "eglconfig.h"
+#include "eglscreen.h"
+#include "eglmode.h"
+#include "eglimage.h"
/**
- * NOTE: displayName is treated as a string in _eglChooseDriver()!!!
- * This will probably change!
- * See _eglChooseDriver() for details!
+ * This is typically the first EGL function that an application calls.
+ * We initialize our global vars and create a private _EGLDisplay object.
*/
-EGLDisplay APIENTRY
-eglGetDisplay(NativeDisplayType displayName)
+EGLDisplay EGLAPIENTRY
+eglGetDisplay(NativeDisplayType nativeDisplay)
{
_EGLDisplay *dpy;
- _eglInitGlobals();
- dpy = _eglNewDisplay(displayName);
- if (dpy)
- return dpy->Handle;
- else
- return EGL_NO_DISPLAY;
+ dpy = _eglFindDisplay(nativeDisplay);
+ if (!dpy) {
+ dpy = _eglNewDisplay(nativeDisplay);
+ if (dpy)
+ _eglLinkDisplay(dpy);
+ }
+ return _eglGetDisplayHandle(dpy);
}
-EGLBoolean APIENTRY
+/**
+ * This is typically the second EGL function that an application calls.
+ * Here we load/initialize the actual hardware driver.
+ */
+EGLBoolean EGLAPIENTRY
eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
- if (dpy) {
- _EGLDriver *drv = _eglChooseDriver(dpy);
- if (drv)
- return drv->API.Initialize(drv, dpy, major, minor);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLDriver *drv;
+ EGLint major_int, minor_int;
+
+ if (!disp)
+ return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
+
+ drv = disp->Driver;
+ if (!drv) {
+ drv = _eglOpenDriver(disp);
+ if (!drv)
+ return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
+
+ /* Initialize the particular display now */
+ if (!drv->API.Initialize(drv, disp, &major_int, &minor_int)) {
+ _eglCloseDriver(drv, disp);
+ return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
+ }
+
+ disp->APImajor = major_int;
+ disp->APIminor = minor_int;
+ snprintf(disp->Version, sizeof(disp->Version),
+ "%d.%d (%s)", major_int, minor_int, drv->Name);
+
+ /* update the global notion of supported APIs */
+ _eglGlobal.ClientAPIsMask |= disp->ClientAPIsMask;
+
+ disp->Driver = drv;
+ } else {
+ major_int = disp->APImajor;
+ minor_int = disp->APIminor;
}
- return EGL_FALSE;
+
+ /* Update applications version of major and minor if not NULL */
+ if ((major != NULL) && (minor != NULL)) {
+ *major = major_int;
+ *minor = minor_int;
+ }
+
+ return EGL_TRUE;
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglTerminate(EGLDisplay dpy)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- if (drv)
- return _eglCloseDriver(drv, dpy);
- else
- return EGL_FALSE;
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLDriver *drv;
+
+ if (!disp)
+ return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
+
+ drv = disp->Driver;
+ if (drv) {
+ drv->API.Terminate(drv, disp);
+ _eglCloseDriver(drv, disp);
+ disp->Driver = NULL;
+ }
+
+ return EGL_TRUE;
}
-const char * APIENTRY
-eglQueryString(EGLDisplay dpy, EGLint name)
+/**
+ * A bunch of check functions and declare macros to simply error checking.
+ */
+static INLINE _EGLDriver *
+_eglCheckDisplay(_EGLDisplay *disp, const char *msg)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- if (drv)
- return drv->API.QueryString(drv, dpy, name);
- else
+ if (!disp) {
+ _eglError(EGL_BAD_DISPLAY, msg);
+ return NULL;
+ }
+ if (!disp->Driver) {
+ _eglError(EGL_NOT_INITIALIZED, msg);
return NULL;
+ }
+ return disp->Driver;
}
-EGLBoolean APIENTRY
-eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+static INLINE _EGLDriver *
+_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- /* XXX check drv for null in remaining functions */
- return drv->API.GetConfigs(drv, dpy, configs, config_size, num_config);
+ _EGLDriver *drv = _eglCheckDisplay(disp, msg);
+ if (!drv)
+ return NULL;
+ if (!surf) {
+ _eglError(EGL_BAD_SURFACE, msg);
+ return NULL;
+ }
+ return drv;
}
-EGLBoolean APIENTRY
-eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+static INLINE _EGLDriver *
+_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.ChooseConfig(drv, dpy, attrib_list, configs, config_size, num_config);
+ _EGLDriver *drv = _eglCheckDisplay(disp, msg);
+ if (!drv)
+ return NULL;
+ if (!context) {
+ _eglError(EGL_BAD_CONTEXT, msg);
+ return NULL;
+ }
+ return drv;
}
-EGLBoolean APIENTRY
-eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+static INLINE _EGLDriver *
+_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.GetConfigAttrib(drv, dpy, config, attribute, value);
+ _EGLDriver *drv = _eglCheckDisplay(disp, msg);
+ if (!drv)
+ return NULL;
+ if (!conf) {
+ _eglError(EGL_BAD_CONFIG, msg);
+ return NULL;
+ }
+ return drv;
}
-EGLContext APIENTRY
-eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
+#define _EGL_DECLARE_DD(dpy) \
+ _EGLDisplay *disp = _eglLookupDisplay(dpy); \
+ _EGLDriver *drv; \
+ do { \
+ drv = _eglCheckDisplay(disp, __FUNCTION__); \
+ if (!drv) \
+ return EGL_FALSE; \
+ } while (0)
+
+
+#define _EGL_DECLARE_DD_AND_SURFACE(dpy, surface) \
+ _EGLDisplay *disp = _eglLookupDisplay(dpy); \
+ _EGLSurface *surf = _eglLookupSurface((surface), disp); \
+ _EGLDriver *drv; \
+ do { \
+ drv = _eglCheckSurface(disp, surf, __FUNCTION__); \
+ if (!drv) \
+ return EGL_FALSE; \
+ } while (0)
+
+
+#define _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx) \
+ _EGLDisplay *disp = _eglLookupDisplay(dpy); \
+ _EGLContext *context = _eglLookupContext((ctx), disp); \
+ _EGLDriver *drv; \
+ do { \
+ drv = _eglCheckContext(disp, context, __FUNCTION__); \
+ if (!drv) \
+ return EGL_FALSE; \
+ } while (0)
+
+
+#ifdef EGL_MESA_screen_surface
+
+
+static INLINE _EGLDriver *
+_eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.CreateContext(drv, dpy, config, share_list, attrib_list);
+ _EGLDriver *drv = _eglCheckDisplay(disp, msg);
+ if (!drv)
+ return NULL;
+ if (!scrn) {
+ _eglError(EGL_BAD_SCREEN_MESA, msg);
+ return NULL;
+ }
+ return drv;
}
-EGLBoolean APIENTRY
-eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+static INLINE _EGLDriver *
+_eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg)
+{
+ _EGLDriver *drv = _eglCheckDisplay(disp, msg);
+ if (!drv)
+ return NULL;
+ if (!m) {
+ _eglError(EGL_BAD_MODE_MESA, msg);
+ return NULL;
+ }
+ return drv;
+}
+
+
+#define _EGL_DECLARE_DD_AND_SCREEN(dpy, screen) \
+ _EGLDisplay *disp = _eglLookupDisplay(dpy); \
+ _EGLScreen *scrn = _eglLookupScreen((screen), disp); \
+ _EGLDriver *drv; \
+ do { \
+ drv = _eglCheckScreen(disp, scrn, __FUNCTION__); \
+ if (!drv) \
+ return EGL_FALSE; \
+ } while (0)
+
+
+#define _EGL_DECLARE_DD_AND_MODE(dpy, mode) \
+ _EGLDisplay *disp = _eglLookupDisplay(dpy); \
+ _EGLMode *m = _eglLookupMode((mode), disp); \
+ _EGLDriver *drv; \
+ do { \
+ drv = _eglCheckMode(disp, m, __FUNCTION__); \
+ if (!drv) \
+ return EGL_FALSE; \
+ } while (0)
+
+
+#endif /* EGL_MESA_screen_surface */
+
+
+const char * EGLAPIENTRY
+eglQueryString(EGLDisplay dpy, EGLint name)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.DestroyContext(drv, dpy, ctx);
+ _EGL_DECLARE_DD(dpy);
+ return drv->API.QueryString(drv, disp, name);
}
-EGLBoolean APIENTRY
-eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+EGLBoolean EGLAPIENTRY
+eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
+ EGLint config_size, EGLint *num_config)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.MakeCurrent(drv, dpy, draw, read, ctx);
+ _EGL_DECLARE_DD(dpy);
+ return drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
}
-EGLBoolean APIENTRY
-eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+EGLBoolean EGLAPIENTRY
+eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
+ EGLint config_size, EGLint *num_config)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.QueryContext(drv, dpy, ctx, attribute, value);
+ _EGL_DECLARE_DD(dpy);
+ return drv->API.ChooseConfig(drv, disp, attrib_list, configs,
+ config_size, num_config);
}
-EGLSurface APIENTRY
-eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY
+eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+ EGLint attribute, EGLint *value)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.CreateWindowSurface(drv, dpy, config, window, attrib_list);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLConfig *conf = _eglLookupConfig(config, disp);
+ _EGLDriver *drv;
+
+ drv = _eglCheckConfig(disp, conf, __FUNCTION__);
+ if (!drv)
+ return EGL_FALSE;
+
+ return drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
}
-EGLSurface APIENTRY
-eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
+EGLContext EGLAPIENTRY
+eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
+ const EGLint *attrib_list)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.CreatePixmapSurface(drv, dpy, config, pixmap, attrib_list);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLConfig *conf = _eglLookupConfig(config, disp);
+ _EGLContext *share = _eglLookupContext(share_list, disp);
+ _EGLDriver *drv;
+ _EGLContext *context;
+
+ drv = _eglCheckConfig(disp, conf, __FUNCTION__);
+ if (!drv)
+ return EGL_NO_CONTEXT;
+ if (!share && share_list != EGL_NO_CONTEXT) {
+ _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+ return EGL_NO_CONTEXT;
+ }
+
+ context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
+ if (context)
+ return _eglLinkContext(context, disp);
+ else
+ return EGL_NO_CONTEXT;
}
-EGLSurface APIENTRY
-eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY
+eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.CreatePbufferSurface(drv, dpy, config, attrib_list);
+ _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx);
+ _eglUnlinkContext(context);
+ return drv->API.DestroyContext(drv, disp, context);
}
-EGLBoolean APIENTRY
-eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+EGLBoolean EGLAPIENTRY
+eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
+ EGLContext ctx)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.DestroySurface(drv, dpy, surface);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLContext *context = _eglLookupContext(ctx, disp);
+ _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
+ _EGLSurface *read_surf = _eglLookupSurface(read, disp);
+ _EGLDriver *drv;
+
+ drv = _eglCheckDisplay(disp, __FUNCTION__);
+ if (!drv)
+ return EGL_FALSE;
+ if (!context && ctx != EGL_NO_CONTEXT)
+ return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+ if ((!draw_surf && draw != EGL_NO_SURFACE) ||
+ (!read_surf && read != EGL_NO_SURFACE))
+ return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+
+ return drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
}
-EGLBoolean APIENTRY
-eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+EGLBoolean EGLAPIENTRY
+eglQueryContext(EGLDisplay dpy, EGLContext ctx,
+ EGLint attribute, EGLint *value)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.QuerySurface(drv, dpy, surface, attribute, value);
+ _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx);
+ return drv->API.QueryContext(drv, disp, context, attribute, value);
}
-EGLBoolean APIENTRY
-eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+EGLSurface EGLAPIENTRY
+eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
+ NativeWindowType window, const EGLint *attrib_list)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.SurfaceAttrib(drv, dpy, surface, attribute, value);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLConfig *conf = _eglLookupConfig(config, disp);
+ _EGLDriver *drv;
+ _EGLSurface *surf;
+
+ drv = _eglCheckConfig(disp, conf, __FUNCTION__);
+ if (!drv)
+ return EGL_NO_SURFACE;
+
+ surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
+ if (surf)
+ return _eglLinkSurface(surf, disp);
+ else
+ return EGL_NO_SURFACE;
}
-EGLBoolean APIENTRY
+EGLSurface EGLAPIENTRY
+eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
+ NativePixmapType pixmap, const EGLint *attrib_list)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLConfig *conf = _eglLookupConfig(config, disp);
+ _EGLDriver *drv;
+ _EGLSurface *surf;
+
+ drv = _eglCheckConfig(disp, conf, __FUNCTION__);
+ if (!drv)
+ return EGL_NO_SURFACE;
+
+ surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
+ if (surf)
+ return _eglLinkSurface(surf, disp);
+ else
+ return EGL_NO_SURFACE;
+}
+
+
+EGLSurface EGLAPIENTRY
+eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLConfig *conf = _eglLookupConfig(config, disp);
+ _EGLDriver *drv;
+ _EGLSurface *surf;
+
+ drv = _eglCheckConfig(disp, conf, __FUNCTION__);
+ if (!drv)
+ return EGL_NO_SURFACE;
+
+ surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
+ if (surf)
+ return _eglLinkSurface(surf, disp);
+ else
+ return EGL_NO_SURFACE;
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+ _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+ _eglUnlinkSurface(surf);
+ return drv->API.DestroySurface(drv, disp, surf);
+}
+
+EGLBoolean EGLAPIENTRY
+eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
+ EGLint attribute, EGLint *value)
+{
+ _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+ return drv->API.QuerySurface(drv, disp, surf, attribute, value);
+}
+
+EGLBoolean EGLAPIENTRY
+eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
+ EGLint attribute, EGLint value)
+{
+ _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+ return drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
+}
+
+
+EGLBoolean EGLAPIENTRY
eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.BindTexImage(drv, dpy, surface, buffer);
+ _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+ return drv->API.BindTexImage(drv, disp, surf, buffer);
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.ReleaseTexImage(drv, dpy, surface, buffer);
+ _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+ return drv->API.ReleaseTexImage(drv, disp, surf, buffer);
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.SwapInterval(drv, dpy, interval);
+ _EGL_DECLARE_DD(dpy);
+ return drv->API.SwapInterval(drv, disp, interval);
}
-EGLBoolean APIENTRY
-eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
+EGLBoolean EGLAPIENTRY
+eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.SwapBuffers(drv, dpy, draw);
+ _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+ return drv->API.SwapBuffers(drv, disp, surf);
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.CopyBuffers(drv, dpy, surface, target);
+ _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+ return drv->API.CopyBuffers(drv, disp, surf, target);
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglWaitGL(void)
{
- EGLDisplay dpy = eglGetCurrentDisplay();
- if (dpy != EGL_NO_DISPLAY) {
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.WaitGL(drv, dpy);
- }
- else
- return EGL_FALSE;
+ _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLDriver *drv;
+
+ if (!disp)
+ return EGL_TRUE;
+
+ /* a current display is always initialized */
+ drv = disp->Driver;
+
+ return drv->API.WaitGL(drv, disp);
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglWaitNative(EGLint engine)
{
- EGLDisplay dpy = eglGetCurrentDisplay();
- if (dpy != EGL_NO_DISPLAY) {
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.WaitNative(drv, dpy, engine);
- }
- else
- return EGL_FALSE;
+ _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLDriver *drv;
+
+ if (!disp)
+ return EGL_TRUE;
+
+ /* a current display is always initialized */
+ drv = disp->Driver;
+
+ return drv->API.WaitNative(drv, disp, engine);
}
-EGLDisplay APIENTRY
+EGLDisplay EGLAPIENTRY
eglGetCurrentDisplay(void)
{
_EGLDisplay *dpy = _eglGetCurrentDisplay();
- if (dpy)
- return dpy->Handle;
- else
- return EGL_NO_DISPLAY;
+ return _eglGetDisplayHandle(dpy);
}
-EGLContext APIENTRY
+EGLContext EGLAPIENTRY
eglGetCurrentContext(void)
{
_EGLContext *ctx = _eglGetCurrentContext();
- if (ctx)
- return ctx->Handle;
- else
- return EGL_NO_CONTEXT;
+ return _eglGetContextHandle(ctx);
}
-EGLSurface APIENTRY
+EGLSurface EGLAPIENTRY
eglGetCurrentSurface(EGLint readdraw)
{
_EGLSurface *s = _eglGetCurrentSurface(readdraw);
- if (s)
- return s->Handle;
- else
- return EGL_NO_SURFACE;
+ return _eglGetSurfaceHandle(s);
}
-EGLint APIENTRY
+EGLint EGLAPIENTRY
eglGetError(void)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
EGLint e = t->LastError;
- t->LastError = EGL_SUCCESS;
+ if (!_eglIsCurrentThreadDummy())
+ t->LastError = EGL_SUCCESS;
return e;
}
-void (* APIENTRY eglGetProcAddress(const char *procname))()
+void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
{
typedef void (*genericFunc)();
struct name_function {
@@ -368,6 +645,10 @@ void (* APIENTRY eglGetProcAddress(const char *procname))()
{ "eglReleaseThread", (_EGLProc) eglReleaseThread },
{ "eglWaitClient", (_EGLProc) eglWaitClient },
#endif /* EGL_VERSION_1_2 */
+#ifdef EGL_KHR_image_base
+ { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
+ { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
+#endif /* EGL_KHR_image_base */
{ NULL, NULL }
};
EGLint i;
@@ -376,12 +657,15 @@ void (* APIENTRY eglGetProcAddress(const char *procname))()
return (genericFunc) egl_functions[i].function;
}
}
-#if 0
- /* XXX enable this code someday */
- return (genericFunc) _glapi_get_proc_address(procname);
-#else
+
+ /* now loop over drivers to query their procs */
+ for (i = 0; i < _eglGlobal.NumDrivers; i++) {
+ _EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname);
+ if (p)
+ return p;
+ }
+
return NULL;
-#endif
}
@@ -389,116 +673,173 @@ void (* APIENTRY eglGetProcAddress(const char *procname))()
* EGL_MESA_screen extension
*/
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
const EGLint *attrib_list, EGLModeMESA *modes,
EGLint modes_size, EGLint *num_modes)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- if (drv)
- return drv->API.ChooseModeMESA(drv, dpy, screen, attrib_list, modes, modes_size, num_modes);
- else
- return EGL_FALSE;
+ _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
+ return drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list,
+ modes, modes_size, num_modes);
}
-EGLBoolean APIENTRY
-eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode)
+EGLBoolean EGLAPIENTRY
+eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes,
+ EGLint mode_size, EGLint *num_mode)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- if (drv)
- return drv->API.GetModesMESA(drv, dpy, screen, modes, mode_size, num_mode);
- else
- return EGL_FALSE;
+ _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
+ return drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode);
}
-EGLBoolean APIENTRY
-eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value)
+EGLBoolean EGLAPIENTRY
+eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
+ EGLint attribute, EGLint *value)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- if (drv)
- return drv->API.GetModeAttribMESA(drv, dpy, mode, attribute, value);
- else
- return EGL_FALSE;
+ _EGL_DECLARE_DD_AND_MODE(dpy, mode);
+ return drv->API.GetModeAttribMESA(drv, disp, m, attribute, value);
}
-EGLBoolean APIENTRY
-eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask)
+EGLBoolean EGLAPIENTRY
+eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
+ EGLint mask)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- if (drv)
- return drv->API.CopyContextMESA(drv, dpy, source, dest, mask);
- else
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLContext *source_context = _eglLookupContext(source, disp);
+ _EGLContext *dest_context = _eglLookupContext(dest, disp);
+ _EGLDriver *drv;
+
+ drv = _eglCheckContext(disp, source_context, __FUNCTION__);
+ if (!drv || !dest_context) {
+ if (drv)
+ _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
return EGL_FALSE;
+ }
+
+ return drv->API.CopyContextMESA(drv, disp, source_context, dest_context,
+ mask);
}
EGLBoolean
-eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens)
+eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
+ EGLint max_screens, EGLint *num_screens)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- if (drv)
- return drv->API.GetScreensMESA(drv, dpy, screens, max_screens, num_screens);
- else
- return EGL_FALSE;
+ _EGL_DECLARE_DD(dpy);
+ return drv->API.GetScreensMESA(drv, disp, screens,
+ max_screens, num_screens);
}
EGLSurface
-eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.CreateScreenSurfaceMESA(drv, dpy, config, attrib_list);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLConfig *conf = _eglLookupConfig(config, disp);
+ _EGLDriver *drv;
+ _EGLSurface *surf;
+
+ drv = _eglCheckConfig(disp, conf, __FUNCTION__);
+ if (!drv)
+ return EGL_NO_SURFACE;
+
+ surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list);
+ if (surf)
+ return _eglLinkSurface(surf, disp);
+ else
+ return EGL_NO_SURFACE;
}
EGLBoolean
-eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode)
+eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
+ EGLSurface surface, EGLModeMESA mode)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.ShowScreenSurfaceMESA(drv, dpy, screen, surface, mode);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
+ _EGLSurface *surf = _eglLookupSurface(surface, disp);
+ _EGLMode *m = _eglLookupMode(mode, disp);
+ _EGLDriver *drv;
+
+ drv = _eglCheckScreen(disp, scrn, __FUNCTION__);
+ if (!drv)
+ return EGL_FALSE;
+ if (!surf && surface != EGL_NO_SURFACE)
+ return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+ if (!m && mode != EGL_NO_MODE_MESA)
+ return _eglError(EGL_BAD_MODE_MESA, __FUNCTION__);
+
+ return drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m);
}
EGLBoolean
eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.ScreenPositionMESA(drv, dpy, screen, x, y);
+ _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
+ return drv->API.ScreenPositionMESA(drv, disp, scrn, x, y);
}
EGLBoolean
-eglQueryScreenMESA( EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value)
+eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLint attribute, EGLint *value)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.QueryScreenMESA(drv, dpy, screen, attribute, value);
+ _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
+ return drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value);
}
EGLBoolean
-eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface)
+eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLSurface *surface)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.QueryScreenSurfaceMESA(drv, dpy, screen, surface);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
+ _EGLDriver *drv;
+ _EGLSurface *surf;
+
+ drv = _eglCheckScreen(disp, scrn, __FUNCTION__);
+ if (!drv)
+ return EGL_FALSE;
+
+ if (drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf) != EGL_TRUE)
+ surf = NULL;
+ if (surface)
+ *surface = _eglGetSurfaceHandle(surf);
+ return (surf != NULL);
}
EGLBoolean
eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.QueryScreenModeMESA(drv, dpy, screen, mode);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
+ _EGLDriver *drv;
+ _EGLMode *m;
+
+ drv = _eglCheckScreen(disp, scrn, __FUNCTION__);
+ if (!drv)
+ return EGL_FALSE;
+
+ if (drv->API.QueryScreenModeMESA(drv, disp, scrn, &m) != EGL_TRUE)
+ m = NULL;
+ if (mode)
+ *mode = m->Handle;
+
+ return (m != NULL);
}
const char *
eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.QueryModeStringMESA(drv, dpy, mode);
+ _EGL_DECLARE_DD_AND_MODE(dpy, mode);
+ return drv->API.QueryModeStringMESA(drv, disp, m);
}
@@ -508,22 +849,49 @@ eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
#ifdef EGL_VERSION_1_2
+
+/**
+ * Specify the client API to use for subsequent calls including:
+ * eglCreateContext()
+ * eglGetCurrentContext()
+ * eglGetCurrentDisplay()
+ * eglGetCurrentSurface()
+ * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
+ * eglWaitClient()
+ * eglWaitNative()
+ * See section 3.7 "Rendering Context" in the EGL specification for details.
+ */
EGLBoolean
eglBindAPI(EGLenum api)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
+ if (_eglIsCurrentThreadDummy())
+ return _eglError(EGL_BAD_ALLOC, "eglBindAPI");
+
+ if (!_eglIsApiValid(api))
+ return _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
+
switch (api) {
+#ifdef EGL_VERSION_1_4
+ case EGL_OPENGL_API:
+ if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) {
+ t->CurrentAPIIndex = _eglConvertApiToIndex(api);
+ return EGL_TRUE;
+ }
+ _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
+ return EGL_FALSE;
+#endif
case EGL_OPENGL_ES_API:
- if (_eglGlobal.OpenGLESAPISupported) {
- t->CurrentAPI = api;
+ if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) {
+ t->CurrentAPIIndex = _eglConvertApiToIndex(api);
return EGL_TRUE;
}
_eglError(EGL_BAD_PARAMETER, "eglBindAPI");
return EGL_FALSE;
case EGL_OPENVG_API:
- if (_eglGlobal.OpenVGAPISupported) {
- t->CurrentAPI = api;
+ if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) {
+ t->CurrentAPIIndex = _eglConvertApiToIndex(api);
return EGL_TRUE;
}
_eglError(EGL_BAD_PARAMETER, "eglBindAPI");
@@ -535,38 +903,55 @@ eglBindAPI(EGLenum api)
}
+/**
+ * Return the last value set with eglBindAPI().
+ */
+EGLenum
+eglQueryAPI(void)
+{
+ /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ return _eglConvertApiFromIndex(t->CurrentAPIIndex);
+}
+
+
EGLSurface
eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
EGLClientBuffer buffer, EGLConfig config,
const EGLint *attrib_list)
{
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.CreatePbufferFromClientBuffer(drv, dpy, buftype, buffer,
- config, attrib_list);
-}
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLConfig *conf = _eglLookupConfig(config, disp);
+ _EGLDriver *drv;
+ _EGLSurface *surf;
+ drv = _eglCheckConfig(disp, conf, __FUNCTION__);
+ if (!drv)
+ return EGL_NO_SURFACE;
-EGLenum
-eglQueryAPI(void)
-{
- /* returns one of EGL_OPENGL_ES_API or EGL_OPENVG_API */
- _EGLThreadInfo *t = _eglGetCurrentThread();
- return t->CurrentAPI;
+ surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
+ conf, attrib_list);
+ if (surf)
+ return _eglLinkSurface(surf, disp);
+ else
+ return EGL_NO_SURFACE;
}
EGLBoolean
eglReleaseThread(void)
{
- _EGLThreadInfo *t = _eglGetCurrentThread();
- EGLDisplay dpy = eglGetCurrentDisplay();
- if (dpy) {
- _EGLDriver *drv = _eglLookupDriver(dpy);
- /* unbind context */
- (void) drv->API.MakeCurrent(drv, dpy, EGL_NO_SURFACE,
- EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ /* unbind current context */
+ if (!_eglIsCurrentThreadDummy()) {
+ _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLDriver *drv;
+ if (disp) {
+ drv = disp->Driver;
+ (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
+ }
}
- _eglDeleteThreadData(t);
+
+ _eglDestroyCurrentThread();
return EGL_TRUE;
}
@@ -574,13 +959,63 @@ eglReleaseThread(void)
EGLBoolean
eglWaitClient(void)
{
- EGLDisplay dpy = eglGetCurrentDisplay();
- if (dpy != EGL_NO_DISPLAY) {
- _EGLDriver *drv = _eglLookupDriver(dpy);
- return drv->API.WaitClient(drv, dpy);
+ _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLDriver *drv;
+
+ if (!disp)
+ return EGL_TRUE;
+
+ /* a current display is always initialized */
+ drv = disp->Driver;
+
+ return drv->API.WaitClient(drv, disp);
+}
+
+
+#endif /* EGL_VERSION_1_2 */
+
+
+#ifdef EGL_KHR_image_base
+
+
+EGLImageKHR
+eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLContext *context = _eglLookupContext(ctx, disp);
+ _EGLDriver *drv;
+ _EGLImage *img;
+
+ drv = _eglCheckDisplay(disp, __FUNCTION__);
+ if (!drv)
+ return EGL_NO_IMAGE_KHR;
+ if (!context && ctx != EGL_NO_CONTEXT) {
+ _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+ return EGL_NO_IMAGE_KHR;
}
+
+ img = drv->API.CreateImageKHR(drv, disp, context, target, buffer, attr_list);
+ if (img)
+ return _eglLinkImage(img, disp);
else
+ return EGL_NO_IMAGE_KHR;
+}
+
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLImage *img = _eglLookupImage(image, disp);
+ _EGLDriver *drv;
+
+ drv = _eglCheckDisplay(disp, __FUNCTION__);
+ if (!drv)
return EGL_FALSE;
+ if (!img)
+ return _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
+
+ return drv->API.DestroyImageKHR(drv, disp, img);
}
-#endif /* EGL_VERSION_1_2 */
+
+#endif /* EGL_KHR_image_base */
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index 555aa5dd9e..c2c4339294 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -2,66 +2,79 @@
#define EGLAPI_INCLUDED
/**
- * Typedefs for all EGL API entrypoint functions.
+ * A generic function ptr type
*/
+typedef void (*_EGLProc)();
+
+/**
+ * Typedefs for all EGL API entrypoint functions.
+ */
/* driver funcs */
-typedef EGLBoolean (*Initialize_t)(_EGLDriver *, EGLDisplay dpy, EGLint *major, EGLint *minor);
-typedef EGLBoolean (*Terminate_t)(_EGLDriver *, EGLDisplay dpy);
+typedef EGLBoolean (*Initialize_t)(_EGLDriver *, _EGLDisplay *dpy, EGLint *major, EGLint *minor);
+typedef EGLBoolean (*Terminate_t)(_EGLDriver *, _EGLDisplay *dpy);
/* config funcs */
-typedef EGLBoolean (*GetConfigs_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
-typedef EGLBoolean (*ChooseConfig_t)(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
-typedef EGLBoolean (*GetConfigAttrib_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+typedef EGLBoolean (*GetConfigs_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+typedef EGLBoolean (*ChooseConfig_t)(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+typedef EGLBoolean (*GetConfigAttrib_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, EGLint attribute, EGLint *value);
/* context funcs */
-typedef EGLContext (*CreateContext_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
-typedef EGLBoolean (*DestroyContext_t)(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx);
-typedef EGLBoolean (*MakeCurrent_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
-typedef EGLBoolean (*QueryContext_t)(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+typedef _EGLContext *(*CreateContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, _EGLContext *share_list, const EGLint *attrib_list);
+typedef EGLBoolean (*DestroyContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx);
+typedef EGLBoolean (*MakeCurrent_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx);
+typedef EGLBoolean (*QueryContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLint attribute, EGLint *value);
/* surface funcs */
-typedef EGLSurface (*CreateWindowSurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list);
-typedef EGLSurface (*CreatePixmapSurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list);
-typedef EGLSurface (*CreatePbufferSurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
-typedef EGLBoolean (*DestroySurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface);
-typedef EGLBoolean (*QuerySurface_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
-typedef EGLBoolean (*SurfaceAttrib_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
-typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint interval);
-typedef EGLBoolean (*SwapBuffers_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw);
-typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, NativePixmapType target);
+typedef _EGLSurface *(*CreateWindowSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, NativeWindowType window, const EGLint *attrib_list);
+typedef _EGLSurface *(*CreatePixmapSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, NativePixmapType pixmap, const EGLint *attrib_list);
+typedef _EGLSurface *(*CreatePbufferSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, const EGLint *attrib_list);
+typedef EGLBoolean (*DestroySurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface);
+typedef EGLBoolean (*QuerySurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint *value);
+typedef EGLBoolean (*SurfaceAttrib_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint value);
+typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer);
+typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer);
+typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval);
+typedef EGLBoolean (*SwapBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw);
+typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, NativePixmapType target);
/* misc funcs */
-typedef const char *(*QueryString_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint name);
-typedef EGLBoolean (*WaitGL_t)(_EGLDriver *drv, EGLDisplay dpy);
-typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint engine);
+typedef const char *(*QueryString_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name);
+typedef EGLBoolean (*WaitGL_t)(_EGLDriver *drv, _EGLDisplay *dpy);
+typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine);
+
+typedef _EGLProc (*GetProcAddress_t)(const char *procname);
+
#ifdef EGL_MESA_screen_surface
-typedef EGLBoolean (*ChooseModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
-typedef EGLBoolean (*GetModesMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode);
-typedef EGLBoolean (*GetModeAttribMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value);
-typedef EGLBoolean (*CopyContextMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
-typedef EGLBoolean (*GetScreensMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
-typedef EGLSurface (*CreateScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
-typedef EGLBoolean (*ShowScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode);
-typedef EGLBoolean (*ScreenPositionMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
-typedef EGLBoolean (*QueryScreenMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
-typedef EGLBoolean (*QueryScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface);
-typedef EGLBoolean (*QueryScreenModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
-typedef const char * (*QueryModeStringMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode);
+typedef EGLBoolean (*ChooseModeMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
+typedef EGLBoolean (*GetModesMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode);
+typedef EGLBoolean (*GetModeAttribMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *mode, EGLint attribute, EGLint *value);
+typedef EGLBoolean (*CopyContextMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *source, _EGLContext *dest, EGLint mask);
+typedef EGLBoolean (*GetScreensMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
+typedef _EGLSurface *(*CreateScreenSurfaceMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, const EGLint *attrib_list);
+typedef EGLBoolean (*ShowScreenSurfaceMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, _EGLSurface *surface, _EGLMode *mode);
+typedef EGLBoolean (*ScreenPositionMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, EGLint x, EGLint y);
+typedef EGLBoolean (*QueryScreenMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, EGLint attribute, EGLint *value);
+typedef EGLBoolean (*QueryScreenSurfaceMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, _EGLSurface **surface);
+typedef EGLBoolean (*QueryScreenModeMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, _EGLMode **mode);
+typedef const char * (*QueryModeStringMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *mode);
#endif /* EGL_MESA_screen_surface */
#ifdef EGL_VERSION_1_2
-typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, EGLDisplay dpy);
-typedef EGLSurface (*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, _EGLDisplay *dpy);
+typedef _EGLSurface *(*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum buftype, EGLClientBuffer buffer, _EGLConfig *config, const EGLint *attrib_list);
#endif /* EGL_VERSION_1_2 */
+#ifdef EGL_KHR_image_base
+typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list);
+typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
+#endif /* EGL_KHR_image_base */
+
/**
* The API dispatcher jumps through these functions
@@ -95,8 +108,9 @@ struct _egl_api
QueryString_t QueryString;
WaitGL_t WaitGL;
WaitNative_t WaitNative;
+ GetProcAddress_t GetProcAddress;
- /* EGL_MESA_screen extension */
+#ifdef EGL_MESA_screen_surface
ChooseModeMESA_t ChooseModeMESA;
GetModesMESA_t GetModesMESA;
GetModeAttribMESA_t GetModeAttribMESA;
@@ -109,11 +123,17 @@ struct _egl_api
QueryScreenSurfaceMESA_t QueryScreenSurfaceMESA;
QueryScreenModeMESA_t QueryScreenModeMESA;
QueryModeStringMESA_t QueryModeStringMESA;
+#endif /* EGL_MESA_screen_surface */
#ifdef EGL_VERSION_1_2
WaitClient_t WaitClient;
CreatePbufferFromClientBuffer_t CreatePbufferFromClientBuffer;
#endif
+
+#ifdef EGL_KHR_image_base
+ CreateImageKHR_t CreateImageKHR;
+ DestroyImageKHR_t DestroyImageKHR;
+#endif /* EGL_KHR_image_base */
};
#endif /* EGLAPI_INCLUDED */
diff --git a/src/egl/main/eglclient.c b/src/egl/main/eglclient.c
new file mode 100644
index 0000000000..8426301948
--- /dev/null
+++ b/src/egl/main/eglclient.c
@@ -0,0 +1,21 @@
+/**
+ * Functions that client APIs can call.
+ */
+
+
+#include "eglcurrent.h"
+#include "egldisplay.h"
+#include "eglimage.h"
+#include "eglclient.h"
+
+
+/**
+ * Return the opaque client data of an image.
+ */
+void *
+_eglClientGetImageData(EGLImageKHR image)
+{
+ _EGLDisplay *dpy = _eglGetCurrentDisplay();
+ _EGLImage *img = _eglLookupImage(image, dpy);
+ return (img) ? img->ClientData : NULL;
+}
diff --git a/src/egl/main/eglclient.h b/src/egl/main/eglclient.h
new file mode 100644
index 0000000000..0158664936
--- /dev/null
+++ b/src/egl/main/eglclient.h
@@ -0,0 +1,12 @@
+#ifndef EGLCLIENT_INCLUDED
+#define EGLCLIENT_INCLUDED
+
+
+#include "egltypedefs.h"
+
+
+extern void *
+_eglClientGetImageData(EGLImageKHR image);
+
+
+#endif /* EGLCLIENT_INCLUDED */
diff --git a/src/egl/main/eglcompiler.h b/src/egl/main/eglcompiler.h
new file mode 100644
index 0000000000..6b639b75c6
--- /dev/null
+++ b/src/egl/main/eglcompiler.h
@@ -0,0 +1,64 @@
+#ifndef EGLCOMPILER_INCLUDED
+#define EGLCOMPILER_INCLUDED
+
+
+/**
+ * Get standard integer types
+ */
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
+# include <stdint.h>
+#elif defined(_MSC_VER)
+ typedef __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+ typedef __int16 int16_t;
+ typedef unsigned __int16 uint16_t;
+# ifndef __eglplatform_h_
+ typedef __int32 int32_t;
+# endif
+ typedef unsigned __int32 uint32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+
+# if defined(_WIN64)
+ typedef __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+# else
+ typedef __int32 intptr_t;
+ typedef unsigned __int32 uintptr_t;
+# endif
+
+# define INT64_C(__val) __val##i64
+# define UINT64_C(__val) __val##ui64
+#else
+/* hope the best instead of adding a bunch of ifdef's */
+# include <stdint.h>
+#endif
+
+
+/**
+ * Function inlining
+ */
+#if defined(__GNUC__)
+# define INLINE __inline__
+#elif defined(__MSC__)
+# define INLINE __inline
+#elif defined(_MSC_VER)
+# define INLINE __inline
+#elif defined(__ICL)
+# define INLINE __inline
+#elif defined(__INTEL_COMPILER)
+# define INLINE inline
+#elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100)
+# define INLINE __inline
+#elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
+# define INLINE inline
+# define __inline inline
+# define __inline__ inline
+#elif (__STDC_VERSION__ >= 199901L) /* C99 */
+# define INLINE inline
+#else
+# define INLINE
+#endif
+
+
+#endif /* EGLCOMPILER_INCLUDED */
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index 2a62f95b54..d47b99eed4 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -17,48 +17,6 @@
#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
-/**
- * Convert an _EGLConfig to a __GLcontextModes object.
- * NOTE: This routine may be incomplete - we're only making sure that
- * the fields needed by Mesa (for _mesa_create_context/framebuffer) are
- * set correctly.
- */
-void
-_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
-{
- memset(mode, 0, sizeof(*mode));
-
- mode->rgbMode = GL_TRUE; /* no color index */
- mode->colorIndexMode = GL_FALSE;
- mode->doubleBufferMode = GL_TRUE; /* always DB for now */
- mode->stereoMode = GL_FALSE;
-
- mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE);
- mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE);
- mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE);
- mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE);
- mode->rgbBits = GET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE);
-
- /* no rgba masks - fix? */
-
- mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE);
- mode->haveDepthBuffer = mode->depthBits > 0;
-
- mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE);
- mode->haveStencilBuffer = mode->stencilBits > 0;
-
- /* no accum */
-
- mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL);
- mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES);
- mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS);
-
- /* surface type - not really needed */
- mode->visualType = GLX_TRUE_COLOR;
- mode->renderType = GLX_RGBA_BIT;
-}
-
-
void
_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val)
{
@@ -76,7 +34,7 @@ void
_eglInitConfig(_EGLConfig *config, EGLint id)
{
memset(config, 0, sizeof(*config));
- config->Handle = id;
+ config->Handle = (EGLConfig) _eglUIntToPointer((unsigned int) id);
_eglSetConfigAttrib(config, EGL_CONFIG_ID, id);
_eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE);
_eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE);
@@ -85,9 +43,7 @@ _eglInitConfig(_EGLConfig *config, EGLint id)
_eglSetConfigAttrib(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE);
_eglSetConfigAttrib(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE);
_eglSetConfigAttrib(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_SURFACE_TYPE,
- EGL_SCREEN_BIT_MESA | EGL_PBUFFER_BIT |
- EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
+ _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
_eglSetConfigAttrib(config, EGL_TRANSPARENT_TYPE, EGL_NONE);
_eglSetConfigAttrib(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE);
_eglSetConfigAttrib(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE);
@@ -100,16 +56,27 @@ _eglInitConfig(_EGLConfig *config, EGLint id)
/**
+ * Return the public handle for an internal _EGLConfig.
+ * This is the inverse of _eglLookupConfig().
+ */
+EGLConfig
+_eglGetConfigHandle(_EGLConfig *config)
+{
+ return config ? config->Handle : 0;
+}
+
+
+/**
* Given an EGLConfig handle, return the corresponding _EGLConfig object.
+ * This is the inverse of _eglGetConfigHandle().
*/
_EGLConfig *
-_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
+_eglLookupConfig(EGLConfig config, _EGLDisplay *disp)
{
EGLint i;
- _EGLDisplay *disp = _eglLookupDisplay(dpy);
for (i = 0; i < disp->NumConfigs; i++) {
- if (disp->Configs[i].Handle == config) {
- return disp->Configs + i;
+ if (disp->Configs[i]->Handle == config) {
+ return disp->Configs[i];
}
}
return NULL;
@@ -118,23 +85,32 @@ _eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
/**
* Add the given _EGLConfig to the given display.
+ * Note that we just save the ptr to the config (we don't copy the config).
*/
_EGLConfig *
-_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config)
+_eglAddConfig(_EGLDisplay *display, _EGLConfig *config)
{
- _EGLConfig *newConfigs;
+ _EGLConfig **newConfigs;
EGLint n;
+ /* do some sanity checks on the config's attribs */
+ assert(GET_CONFIG_ATTRIB(config, EGL_CONFIG_ID) > 0);
+ assert(GET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE) != 0x0);
+ assert(GET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE) != 0x0);
+ assert(GET_CONFIG_ATTRIB(config, EGL_RED_SIZE) > 0);
+ assert(GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE) > 0);
+ assert(GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE) > 0);
+
n = display->NumConfigs;
- newConfigs = (_EGLConfig *) realloc(display->Configs,
- (n + 1) * sizeof(_EGLConfig));
+ /* realloc array of ptrs */
+ newConfigs = (_EGLConfig **) realloc(display->Configs,
+ (n + 1) * sizeof(_EGLConfig *));
if (newConfigs) {
display->Configs = newConfigs;
- display->Configs[n] = *config; /* copy struct */
- display->Configs[n].Handle = n;
+ display->Configs[n] = config;
display->NumConfigs++;
- return display->Configs + n;
+ return config;
}
else {
return NULL;
@@ -156,6 +132,9 @@ _eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list)
config->Attrib[i] = EGL_DONT_CARE;
}
+ /* by default choose windows unless otherwise specified */
+ config->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] = EGL_WINDOW_BIT;
+
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
const EGLint attr = attrib_list[i];
if (attr >= EGL_BUFFER_SIZE &&
@@ -176,7 +155,7 @@ _eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list)
}
else if (attr == EGL_RENDERABLE_TYPE) {
EGLint renType = attrib_list[++i];
- if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT)) {
+ if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT)) {
_eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
return EGL_FALSE;
}
@@ -339,10 +318,9 @@ _eglCompareConfigs(const void *a, const void *b)
* Typical fallback routine for eglChooseConfig
*/
EGLBoolean
-_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list,
+_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
EGLConfig *configs, EGLint config_size, EGLint *num_configs)
{
- _EGLDisplay *disp = _eglLookupDisplay(dpy);
_EGLConfig **configList, criteria;
EGLint i, count;
@@ -360,8 +338,8 @@ _eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list,
/* make array of pointers to qualifying configs */
for (i = count = 0; i < disp->NumConfigs && count < config_size; i++) {
- if (_eglConfigQualifies(disp->Configs + i, &criteria)) {
- configList[count++] = disp->Configs + i;
+ if (_eglConfigQualifies(disp->Configs[i], &criteria)) {
+ configList[count++] = disp->Configs[i];
}
}
@@ -369,8 +347,10 @@ _eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list,
qsort(configList, count, sizeof(_EGLConfig *), _eglCompareConfigs);
/* copy config handles to output array */
- for (i = 0; i < count; i++) {
- configs[i] = configList[i]->Handle;
+ if (configs) {
+ for (i = 0; i < count; i++) {
+ configs[i] = configList[i]->Handle;
+ }
}
free(configList);
@@ -385,10 +365,9 @@ _eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list,
* Fallback for eglGetConfigAttrib.
*/
EGLBoolean
-_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
EGLint attribute, EGLint *value)
{
- const _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
const EGLint k = attribute - FIRST_ATTRIB;
if (k >= 0 && k < MAX_ATTRIBS) {
*value = conf->Attrib[k];
@@ -405,21 +384,14 @@ _eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
* Fallback for eglGetConfigs.
*/
EGLBoolean
-_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs,
+_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
EGLint config_size, EGLint *num_config)
{
- _EGLDisplay *disp = _eglLookupDisplay(dpy);
-
- if (!drv->Initialized) {
- _eglError(EGL_NOT_INITIALIZED, "eglGetConfigs");
- return EGL_FALSE;
- }
-
if (configs) {
EGLint i;
*num_config = MIN2(disp->NumConfigs, config_size);
for (i = 0; i < *num_config; i++) {
- configs[i] = disp->Configs[i].Handle;
+ configs[i] = disp->Configs[i]->Handle;
}
}
else {
@@ -429,210 +401,3 @@ _eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs,
return EGL_TRUE;
}
-
-
-/**
- * Creates a set of \c __GLcontextModes that a driver will expose.
- *
- * A set of \c __GLcontextModes will be created based on the supplied
- * parameters. The number of modes processed will be 2 *
- * \c num_depth_stencil_bits * \c num_db_modes.
- *
- * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
- * \c db_modes, and \c visType into each \c __GLcontextModes element.
- * However, the meanings of \c fb_format and \c fb_type require further
- * explanation. The \c fb_format specifies which color components are in
- * each pixel and what the default order is. For example, \c GL_RGB specifies
- * that red, green, blue are available and red is in the "most significant"
- * position and blue is in the "least significant". The \c fb_type specifies
- * the bit sizes of each component and the actual ordering. For example, if
- * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
- * are the blue value, bits [10:5] are the green value, and bits [4:0] are
- * the red value.
- *
- * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
- * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
- * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
- * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
- * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
- * still uses 32-bits.
- *
- * If in doubt, look at the tables used in the function.
- *
- * \param ptr_to_modes Pointer to a pointer to a linked list of
- * \c __GLcontextModes. Upon completion, a pointer to
- * the next element to be process will be stored here.
- * If the function fails and returns \c GL_FALSE, this
- * value will be unmodified, but some elements in the
- * linked list may be modified.
- * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
- * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
- * \param fb_type Type of the pixels in the framebuffer. Currently only
- * \c GL_UNSIGNED_SHORT_5_6_5,
- * \c GL_UNSIGNED_SHORT_5_6_5_REV,
- * \c GL_UNSIGNED_INT_8_8_8_8, and
- * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
- * \param depth_bits Array of depth buffer sizes to be exposed.
- * \param stencil_bits Array of stencil buffer sizes to be exposed.
- * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
- * \c stencil_bits.
- * \param db_modes Array of buffer swap modes. If an element has a
- * value of \c GLX_NONE, then it represents a
- * single-buffered mode. Other valid values are
- * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
- * \c GLX_SWAP_UNDEFINED_OML. See the
- * GLX_OML_swap_method extension spec for more details.
- * \param num_db_modes Number of entries in \c db_modes.
- * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
- * \c GLX_DIRECT_COLOR.
- *
- * \returns
- * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
- * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
- * \c fb_type).
- *
- * \todo
- * There is currently no way to support packed RGB modes (i.e., modes with
- * exactly 3 bytes per pixel) or floating-point modes. This could probably
- * be done by creating some new, private enums with clever names likes
- * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
- * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
- */
-GLboolean
-_eglFillInConfigs(_EGLConfig * configs,
- GLenum fb_format, GLenum fb_type,
- const uint8_t * depth_bits, const uint8_t * stencil_bits,
- unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes,
- int visType)
-{
- static const uint8_t bits_table[3][4] = {
- /* R G B A */
- { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
- { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
- { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
- };
-
- /* The following arrays are all indexed by the fb_type masked with 0x07.
- * Given the four supported fb_type values, this results in valid array
- * indices of 3, 4, 5, and 7.
- */
- static const uint32_t masks_table_rgb[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
- {0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000} /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_rgba[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
- {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_bgr[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
- {0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000}, /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_bgra[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
- {0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, /* 8_8_8_8_REV */
- };
-
- static const uint8_t bytes_per_pixel[8] = {
- 0, 0, 0, 2, 2, 4, 0, 4
- };
-
- const uint8_t * bits;
- const uint32_t * masks;
- const int index = fb_type & 0x07;
- _EGLConfig *config;
- unsigned i;
- unsigned j;
- unsigned k;
-
- if ( bytes_per_pixel[index] == 0 ) {
- _eglLog(_EGL_INFO,
- "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.",
- __FUNCTION__, __LINE__, fb_type);
- return GL_FALSE;
- }
-
- /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
- * the _REV versions.
- *
- * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
- */
- switch ( fb_format ) {
- case GL_RGB:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
- masks = masks_table_rgb[index];
- break;
-
- case GL_RGBA:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
- masks = masks_table_rgba[index];
- break;
-
- case GL_BGR:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
- masks = masks_table_bgr[index];
- break;
-
- case GL_BGRA:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
- masks = masks_table_bgra[index];
- break;
-
- default:
- _eglLog(_EGL_WARNING,
- "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.",
- __FUNCTION__, __LINE__, fb_format);
- return GL_FALSE;
- }
-
- config = configs;
- for (k = 0; k < num_depth_stencil_bits; k++) {
- for (i = 0; i < num_db_modes; i++) {
- for (j = 0; j < 2; j++) {
- _eglSetConfigAttrib(config, EGL_RED_SIZE, bits[0]);
- _eglSetConfigAttrib(config, EGL_GREEN_SIZE, bits[1]);
- _eglSetConfigAttrib(config, EGL_BLUE_SIZE, bits[2]);
- _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, bits[3]);
- _eglSetConfigAttrib(config, EGL_BUFFER_SIZE,
- bits[0] + bits[1] + bits[2] + bits[3]);
-
- _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, stencil_bits[k]);
- _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, depth_bits[i]);
-
- _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_SCREEN_BIT_MESA |
- EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
-
- config++;
- }
- }
- }
- return GL_TRUE;
-}
diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h
index 441b3f4d20..36ed96ae95 100644
--- a/src/egl/main/eglconfig.h
+++ b/src/egl/main/eglconfig.h
@@ -3,10 +3,10 @@
#include "egltypedefs.h"
-#include "GL/internal/glcore.h"
+#include <GLES/gl.h>
-#define MAX_ATTRIBS 100
+#define MAX_ATTRIBS 128
#define FIRST_ATTRIB EGL_BUFFER_SIZE
@@ -17,7 +17,11 @@ struct _egl_config
};
-#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL)
+#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) \
+ assert((ATTR) - FIRST_ATTRIB < MAX_ATTRIBS); \
+ ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL)
+
+
#define GET_CONFIG_ATTRIB(CONF, ATTR) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB])
@@ -25,12 +29,16 @@ extern void
_eglInitConfig(_EGLConfig *config, EGLint id);
+extern EGLConfig
+_eglGetConfigHandle(_EGLConfig *config);
+
+
extern _EGLConfig *
-_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config);
+_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy);
extern _EGLConfig *
-_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config);
+_eglAddConfig(_EGLDisplay *display, _EGLConfig *config);
extern EGLBoolean
@@ -38,30 +46,19 @@ _eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list);
extern EGLBoolean
-_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
extern EGLBoolean
-_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, EGLint attribute, EGLint *value);
extern EGLBoolean
-_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
extern void
_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val);
-extern GLboolean
-_eglFillInConfigs( _EGLConfig *configs,
- GLenum fb_format, GLenum fb_type,
- const uint8_t * depth_bits, const uint8_t * stencil_bits,
- unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes,
- int visType );
-
-extern void
-_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode);
-
#endif /* EGLCONFIG_INCLUDED */
diff --git a/src/egl/main/eglconfigutil.c b/src/egl/main/eglconfigutil.c
new file mode 100644
index 0000000000..c9d00e7982
--- /dev/null
+++ b/src/egl/main/eglconfigutil.c
@@ -0,0 +1,260 @@
+/**
+ * Extra utility functions related to EGL configs.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "eglconfigutil.h"
+#include "egllog.h"
+
+
+/**
+ * Convert an _EGLConfig to a __GLcontextModes object.
+ * NOTE: This routine may be incomplete - we're only making sure that
+ * the fields needed by Mesa (for _mesa_create_context/framebuffer) are
+ * set correctly.
+ */
+void
+_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
+{
+ memset(mode, 0, sizeof(*mode));
+
+ mode->rgbMode = GL_TRUE; /* no color index */
+ mode->colorIndexMode = GL_FALSE;
+ mode->doubleBufferMode = GL_TRUE; /* always DB for now */
+ mode->stereoMode = GL_FALSE;
+
+ mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE);
+ mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE);
+ mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE);
+ mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE);
+ mode->rgbBits = GET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE);
+
+ /* no rgba masks - fix? */
+
+ mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE);
+ mode->haveDepthBuffer = mode->depthBits > 0;
+
+ mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE);
+ mode->haveStencilBuffer = mode->stencilBits > 0;
+
+ /* no accum */
+
+ mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL);
+ mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES);
+ mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS);
+
+ /* surface type - not really needed */
+ mode->visualType = GLX_TRUE_COLOR;
+ mode->renderType = GLX_RGBA_BIT;
+}
+
+
+
+/**
+ * Creates a set of \c _EGLConfigs that a driver will expose.
+ *
+ * A set of \c __GLcontextModes will be created based on the supplied
+ * parameters. The number of modes processed will be 2 *
+ * \c num_depth_stencil_bits * \c num_db_modes.
+ *
+ * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
+ * \c db_modes, and \c visType into each \c __GLcontextModes element.
+ * However, the meanings of \c fb_format and \c fb_type require further
+ * explanation. The \c fb_format specifies which color components are in
+ * each pixel and what the default order is. For example, \c GL_RGB specifies
+ * that red, green, blue are available and red is in the "most significant"
+ * position and blue is in the "least significant". The \c fb_type specifies
+ * the bit sizes of each component and the actual ordering. For example, if
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
+ * are the blue value, bits [10:5] are the green value, and bits [4:0] are
+ * the red value.
+ *
+ * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
+ * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
+ * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
+ * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
+ * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
+ * still uses 32-bits.
+ *
+ * If in doubt, look at the tables used in the function.
+ *
+ * \param configs the array of configs generated
+ * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
+ * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
+ * \param fb_type Type of the pixels in the framebuffer. Currently only
+ * \c GL_UNSIGNED_SHORT_5_6_5,
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV,
+ * \c GL_UNSIGNED_INT_8_8_8_8, and
+ * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
+ * \param depth_bits Array of depth buffer sizes to be exposed.
+ * \param stencil_bits Array of stencil buffer sizes to be exposed.
+ * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
+ * \c stencil_bits.
+ * \param db_modes Array of buffer swap modes. If an element has a
+ * value of \c GLX_NONE, then it represents a
+ * single-buffered mode. Other valid values are
+ * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
+ * \c GLX_SWAP_UNDEFINED_OML. See the
+ * GLX_OML_swap_method extension spec for more details.
+ * \param num_db_modes Number of entries in \c db_modes.
+ * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
+ * \c GLX_DIRECT_COLOR.
+ *
+ * \returns
+ * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
+ * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
+ * \c fb_type).
+ *
+ * \todo
+ * There is currently no way to support packed RGB modes (i.e., modes with
+ * exactly 3 bytes per pixel) or floating-point modes. This could probably
+ * be done by creating some new, private enums with clever names likes
+ * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
+ * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
+ */
+EGLBoolean
+_eglFillInConfigs(_EGLConfig * configs,
+ GLenum fb_format, GLenum fb_type,
+ const uint8_t * depth_bits, const uint8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes,
+ int visType)
+{
+ static const uint8_t bits_table[3][4] = {
+ /* R G B A */
+ { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
+ { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
+ { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
+ };
+
+ /* The following arrays are all indexed by the fb_type masked with 0x07.
+ * Given the four supported fb_type values, this results in valid array
+ * indices of 3, 4, 5, and 7.
+ */
+ static const uint32_t masks_table_rgb[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
+ {0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000} /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_rgba[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
+ {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, /* 8_8_8_8_REV */
+ };
+
+#if 0
+ static const uint32_t masks_table_bgr[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
+ {0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000}, /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_bgra[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
+ {0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, /* 8_8_8_8_REV */
+ };
+#endif
+
+ static const uint8_t bytes_per_pixel[8] = {
+ 0, 0, 0, 2, 2, 4, 0, 4
+ };
+
+ const uint8_t * bits;
+ const uint32_t * masks;
+ const int index = fb_type & 0x07;
+ _EGLConfig *config;
+ unsigned i;
+ unsigned j;
+ unsigned k;
+
+ if ( bytes_per_pixel[index] == 0 ) {
+ _eglLog(_EGL_INFO,
+ "[_eglFillInConfigs:%u] Framebuffer type 0x%04x has 0 bytes per pixel.",
+ __LINE__, fb_type);
+ return GL_FALSE;
+ }
+
+ /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
+ * the _REV versions.
+ *
+ * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
+ */
+ switch ( fb_format ) {
+ case GL_RGB:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
+ masks = masks_table_rgb[index];
+ break;
+
+ case GL_RGBA:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
+ masks = masks_table_rgba[index];
+ break;
+
+#if 0
+ case GL_BGR:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
+ masks = masks_table_bgr[index];
+ break;
+
+ case GL_BGRA:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
+ masks = masks_table_bgra[index];
+ break;
+#endif
+
+ default:
+ _eglLog(_EGL_WARNING,
+ "[_eglFillInConfigs:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.",
+ __LINE__, fb_format);
+ return GL_FALSE;
+ }
+
+ config = configs;
+ for (k = 0; k < num_depth_stencil_bits; k++) {
+ for (i = 0; i < num_db_modes; i++) {
+ for (j = 0; j < 2; j++) {
+ _eglSetConfigAttrib(config, EGL_RED_SIZE, bits[0]);
+ _eglSetConfigAttrib(config, EGL_GREEN_SIZE, bits[1]);
+ _eglSetConfigAttrib(config, EGL_BLUE_SIZE, bits[2]);
+ _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, bits[3]);
+ _eglSetConfigAttrib(config, EGL_BUFFER_SIZE,
+ bits[0] + bits[1] + bits[2] + bits[3]);
+
+ _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, stencil_bits[k]);
+ _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, depth_bits[i]);
+
+ _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_SCREEN_BIT_MESA |
+ EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
+
+ config++;
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
diff --git a/src/egl/main/eglconfigutil.h b/src/egl/main/eglconfigutil.h
new file mode 100644
index 0000000000..c477b94737
--- /dev/null
+++ b/src/egl/main/eglconfigutil.h
@@ -0,0 +1,26 @@
+
+#ifndef EGLCONFIGUTIL_INCLUDED
+#define EGLCONFIGUTIL_INCLUDED
+
+#include "eglconfig.h"
+#include "GL/internal/glcore.h"
+#if (!defined(WIN32) && !defined(_WIN32_WCE))
+#include "stdint.h"
+#endif
+
+
+extern void
+_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode);
+
+
+extern EGLBoolean
+_eglFillInConfigs( _EGLConfig *configs,
+ EGLenum fb_format, EGLenum fb_type,
+ const uint8_t * depth_bits, const uint8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const EGLenum * db_modes, unsigned num_db_modes,
+ int visType );
+
+
+
+#endif /* EGLCONFIGUTIL_INCLUDED */
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index 374c006dae..b094f49bfc 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -6,115 +6,72 @@
#include "egldisplay.h"
#include "egldriver.h"
#include "eglglobals.h"
-#include "eglhash.h"
#include "eglsurface.h"
/**
- * Initialize the given _EGLContext object to defaults.
+ * Initialize the given _EGLContext object to defaults and/or the values
+ * in the attrib_list.
*/
EGLBoolean
-_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
- EGLConfig config, const EGLint *attrib_list)
+_eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
+ _EGLConfig *conf, const EGLint *attrib_list)
{
- _EGLConfig *conf;
- _EGLDisplay *display = _eglLookupDisplay(dpy);
EGLint i;
+ const EGLenum api = eglQueryAPI();
- conf = _eglLookupConfig(drv, dpy, config);
- if (!conf) {
- _eglError(EGL_BAD_CONFIG, "eglCreateContext");
+ if (api == EGL_NONE) {
+ _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
return EGL_FALSE;
}
+ memset(ctx, 0, sizeof(_EGLContext));
+
+ ctx->ClientVersion = 1; /* the default, per EGL spec */
+
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
switch (attrib_list[i]) {
- /* no attribs defined for now */
+ case EGL_CONTEXT_CLIENT_VERSION:
+ i++;
+ ctx->ClientVersion = attrib_list[i];
+ break;
default:
- _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
- return EGL_NO_CONTEXT;
+ _eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext");
+ return EGL_FALSE;
}
}
- memset(ctx, 0, sizeof(_EGLContext));
- ctx->Display = display;
ctx->Config = conf;
ctx->DrawSurface = EGL_NO_SURFACE;
ctx->ReadSurface = EGL_NO_SURFACE;
+ ctx->ClientAPI = api;
return EGL_TRUE;
}
-/*
- * Assign an EGLContext handle to the _EGLContext object then put it into
- * the hash table.
- */
-void
-_eglSaveContext(_EGLContext *ctx)
-{
- assert(ctx);
- ctx->Handle = _eglHashGenKey(_eglGlobal.Contexts);
- _eglHashInsert(_eglGlobal.Contexts, ctx->Handle, ctx);
-}
-
-
-/**
- * Remove the given _EGLContext object from the hash table.
- */
-void
-_eglRemoveContext(_EGLContext *ctx)
-{
- _eglHashRemove(_eglGlobal.Contexts, ctx->Handle);
-}
-
-
-/**
- * Return the _EGLContext object that corresponds to the given
- * EGLContext handle.
- */
-_EGLContext *
-_eglLookupContext(EGLContext ctx)
-{
- _EGLContext *c = (_EGLContext *) _eglHashLookup(_eglGlobal.Contexts, ctx);
- return c;
-}
-
-
-/**
- * Return the currently bound _EGLContext object, or NULL.
- */
-_EGLContext *
-_eglGetCurrentContext(void)
-{
- _EGLThreadInfo *t = _eglGetCurrentThread();
- return t->CurrentContext;
-}
-
-
/**
* Just a placeholder/demo function. Real driver will never use this!
*/
-EGLContext
-_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
- EGLContext share_list, const EGLint *attrib_list)
+_EGLContext *
+_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+ _EGLContext *share_list, const EGLint *attrib_list)
{
#if 0 /* example code */
_EGLContext *context;
context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
if (!context)
- return EGL_NO_CONTEXT;
+ return NULL;
- if (!_eglInitContext(drv, dpy, context, config, attrib_list)) {
+ if (!_eglInitContext(drv, context, conf, attrib_list)) {
free(context);
- return EGL_NO_CONTEXT;
+ return NULL;
}
- _eglSaveContext(context);
- return context->Handle;
+ return context;
#endif
- return EGL_NO_CONTEXT;
+ return NULL;
}
@@ -122,40 +79,21 @@ _eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
* Default fallback routine - drivers should usually override this.
*/
EGLBoolean
-_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
+_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
{
- _EGLContext *context = _eglLookupContext(ctx);
- if (context) {
- _eglHashRemove(_eglGlobal.Contexts, ctx);
- if (context->IsBound) {
- context->DeletePending = EGL_TRUE;
- }
- else {
- free(context);
- }
- return EGL_TRUE;
- }
- else {
- _eglError(EGL_BAD_CONTEXT, "eglDestroyContext");
- return EGL_TRUE;
- }
+ if (!_eglIsContextBound(ctx))
+ free(ctx);
+ return EGL_TRUE;
}
EGLBoolean
-_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
+_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
EGLint attribute, EGLint *value)
{
- _EGLContext *c = _eglLookupContext(ctx);
-
(void) drv;
(void) dpy;
- if (!c) {
- _eglError(EGL_BAD_CONTEXT, "eglQueryContext");
- return EGL_FALSE;
- }
-
switch (attribute) {
case EGL_CONFIG_ID:
*value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
@@ -163,8 +101,11 @@ _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
#ifdef EGL_VERSION_1_2
case EGL_CONTEXT_CLIENT_TYPE:
*value = c->ClientAPI;
- return EGL_FALSE;
+ return EGL_TRUE;
#endif /* EGL_VERSION_1_2 */
+ case EGL_CONTEXT_CLIENT_VERSION:
+ *value = c->ClientVersion;
+ return EGL_TRUE;
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
return EGL_FALSE;
@@ -174,90 +115,100 @@ _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
/**
* Drivers will typically call this to do the error checking and
- * update the various IsBound and DeletePending flags.
+ * update the various flags.
* Then, the driver will do its device-dependent Make-Current stuff.
*/
EGLBoolean
-_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
- EGLSurface r, EGLContext context)
+_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw,
+ _EGLSurface *read, _EGLContext *ctx)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
- _EGLContext *ctx = _eglLookupContext(context);
- _EGLSurface *draw = _eglLookupSurface(d);
- _EGLSurface *read = _eglLookupSurface(r);
+ _EGLContext *oldContext = NULL;
+ _EGLSurface *oldDrawSurface = NULL;
+ _EGLSurface *oldReadSurface = NULL;
+ EGLint apiIndex;
- _EGLContext *oldContext = _eglGetCurrentContext();
- _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW);
- _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ);
+ if (_eglIsCurrentThreadDummy())
+ return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
- /* error checking */
if (ctx) {
- if (draw == NULL || read == NULL) {
- _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
- return EGL_FALSE;
- }
- if (draw->Config != ctx->Config) {
- _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
- return EGL_FALSE;
- }
- if (read->Config != ctx->Config) {
- _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
- return EGL_FALSE;
+ /* error checking */
+ if (ctx->Binding && ctx->Binding != t)
+ return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+ if (draw == NULL || read == NULL)
+ return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+ if (draw->Config != ctx->Config || read->Config != ctx->Config)
+ return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+ if ((draw->Binding && draw->Binding->Binding != t) ||
+ (read->Binding && read->Binding->Binding != t))
+ return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+
+#ifdef EGL_VERSION_1_4
+ /* OpenGL and OpenGL ES are conflicting */
+ switch (ctx->ClientAPI) {
+ case EGL_OPENGL_ES_API:
+ if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)])
+ return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+ break;
+ case EGL_OPENGL_API:
+ if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)])
+ return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+ break;
+ default:
+ break;
}
+#endif
+ apiIndex = _eglConvertApiToIndex(ctx->ClientAPI);
+ }
+ else {
+ if (draw != NULL || read != NULL)
+ return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+ apiIndex = t->CurrentAPIIndex;
}
- /*
- * check if the old context or surfaces need to be deleted
- */
- if (oldDrawSurface != NULL) {
- oldDrawSurface->IsBound = EGL_FALSE;
- if (oldDrawSurface->DeletePending) {
- /* make sure we don't try to rebind a deleted surface */
- if (draw == oldDrawSurface || draw == oldReadSurface) {
- draw = NULL;
- }
- /* really delete surface now */
- drv->API.DestroySurface(drv, dpy, oldDrawSurface->Handle);
+ oldContext = t->CurrentContexts[apiIndex];
+ if (oldContext) {
+ oldDrawSurface = oldContext->DrawSurface;
+ oldReadSurface = oldContext->ReadSurface;
+ assert(oldDrawSurface);
+ assert(oldReadSurface);
+
+ /* break old bindings */
+ t->CurrentContexts[apiIndex] = NULL;
+ oldContext->Binding = NULL;
+ oldContext->DrawSurface = NULL;
+ oldContext->ReadSurface = NULL;
+ oldDrawSurface->Binding = NULL;
+ oldReadSurface->Binding = NULL;
+
+ /*
+ * check if the old context or surfaces need to be deleted
+ */
+ if (!_eglIsSurfaceLinked(oldDrawSurface)) {
+ assert(draw != oldDrawSurface && read != oldDrawSurface);
+ drv->API.DestroySurface(drv, dpy, oldDrawSurface);
}
- }
- if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) {
- oldReadSurface->IsBound = EGL_FALSE;
- if (oldReadSurface->DeletePending) {
- /* make sure we don't try to rebind a deleted surface */
- if (read == oldDrawSurface || read == oldReadSurface) {
- read = NULL;
- }
- /* really delete surface now */
- drv->API.DestroySurface(drv, dpy, oldReadSurface->Handle);
+ if (oldReadSurface != oldDrawSurface &&
+ !_eglIsSurfaceLinked(oldReadSurface)) {
+ assert(draw != oldReadSurface && read != oldReadSurface);
+ drv->API.DestroySurface(drv, dpy, oldReadSurface);
}
- }
- if (oldContext != NULL) {
- oldContext->IsBound = EGL_FALSE;
- if (oldContext->DeletePending) {
- /* make sure we don't try to rebind a deleted context */
- if (ctx == oldContext) {
- ctx = NULL;
- }
- /* really delete context now */
- drv->API.DestroyContext(drv, dpy, oldContext->Handle);
+ if (!_eglIsContextLinked(oldContext)) {
+ assert(ctx != oldContext);
+ drv->API.DestroyContext(drv, dpy, oldContext);
}
}
+ /* build new bindings */
if (ctx) {
- /* check read/draw again, in case we deleted them above */
- if (draw == NULL || read == NULL) {
- _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
- return EGL_FALSE;
- }
+ t->CurrentContexts[apiIndex] = ctx;
+ ctx->Binding = t;
ctx->DrawSurface = draw;
ctx->ReadSurface = read;
- ctx->IsBound = EGL_TRUE;
- draw->IsBound = EGL_TRUE;
- read->IsBound = EGL_TRUE;
+ draw->Binding = ctx;
+ read->Binding = ctx;
}
- t->CurrentContext = ctx;
-
return EGL_TRUE;
}
diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h
index 82bfde151f..647f24488f 100644
--- a/src/egl/main/eglcontext.h
+++ b/src/egl/main/eglcontext.h
@@ -11,61 +11,55 @@
*/
struct _egl_context
{
- EGLContext Handle; /* The public/opaque handle which names this object */
-
- _EGLDisplay *Display; /* who do I belong to? */
-
- _EGLConfig *Config;
+ /* Managed by EGLDisplay for linking */
+ _EGLDisplay *Display;
+ _EGLContext *Next;
+ /* The bound status of the context */
+ _EGLThreadInfo *Binding;
_EGLSurface *DrawSurface;
_EGLSurface *ReadSurface;
- EGLBoolean IsBound;
- EGLBoolean DeletePending;
-#ifdef EGL_VERSION_1_2
- EGLint ClientAPI; /* Either EGL_OPENGL_ES_API or EGL_OPENVG_API */
-#endif /* EGL_VERSION_1_2 */
+ _EGLConfig *Config;
+
+ EGLint ClientAPI; /**< EGL_OPENGL_ES_API, EGL_OPENGL_API, EGL_OPENVG_API */
+ EGLint ClientVersion; /**< 1 = OpenGLES 1.x, 2 = OpenGLES 2.x */
};
extern EGLBoolean
-_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
- EGLConfig config, const EGLint *attrib_list);
-
-
-extern void
-_eglSaveContext(_EGLContext *ctx);
-
-
-extern void
-_eglRemoveContext(_EGLContext *ctx);
+_eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
+ _EGLConfig *config, const EGLint *attrib_list);
extern _EGLContext *
-_eglLookupContext(EGLContext ctx);
-
-
-extern _EGLContext *
-_eglGetCurrentContext(void);
-
-
-extern EGLContext
-_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
+_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list);
extern EGLBoolean
-_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx);
+_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx);
extern EGLBoolean
-_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLint attribute, EGLint *value);
extern EGLBoolean
-_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx);
extern EGLBoolean
_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
+
+/**
+ * Return true if the context is bound to a thread.
+ */
+static INLINE EGLBoolean
+_eglIsContextBound(_EGLContext *ctx)
+{
+ return (ctx->Binding != NULL);
+}
+
+
#endif /* EGLCONTEXT_INCLUDED */
diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c
new file mode 100644
index 0000000000..4431f964f6
--- /dev/null
+++ b/src/egl/main/eglcurrent.c
@@ -0,0 +1,342 @@
+#include <stdlib.h>
+#include <string.h>
+#include "eglcurrent.h"
+#include "eglcontext.h"
+#include "egllog.h"
+#include "eglmutex.h"
+#include "eglglobals.h"
+
+
+/* This should be kept in sync with _eglInitThreadInfo() */
+#define _EGL_THREAD_INFO_INITIALIZER \
+ { EGL_SUCCESS, { NULL }, 1 }
+
+/* a fallback thread info to guarantee that every thread always has one */
+static _EGLThreadInfo dummy_thread = _EGL_THREAD_INFO_INITIALIZER;
+
+
+#ifdef GLX_USE_TLS
+static __thread const _EGLThreadInfo *_egl_TSD;
+ __attribute__ ((tls_model("initial-exec")));
+
+static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
+{
+ _egl_TSD = t;
+}
+
+static INLINE _EGLThreadInfo *_eglGetTSD(void)
+{
+ return (_EGLThreadInfo *) _egl_TSD;
+}
+
+static INLINE void _eglFiniTSD(void)
+{
+}
+
+static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *))
+{
+ /* TODO destroy TSD */
+ (void) dtor;
+ (void) _eglFiniTSD;
+ return EGL_TRUE;
+}
+
+#elif PTHREADS
+#include <pthread.h>
+
+static _EGL_DECLARE_MUTEX(_egl_TSDMutex);
+static EGLBoolean _egl_TSDInitialized;
+static pthread_key_t _egl_TSD;
+static void (*_egl_FreeTSD)(_EGLThreadInfo *);
+
+static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
+{
+ pthread_setspecific(_egl_TSD, (const void *) t);
+}
+
+static INLINE _EGLThreadInfo *_eglGetTSD(void)
+{
+ return (_EGLThreadInfo *) pthread_getspecific(_egl_TSD);
+}
+
+static INLINE void _eglFiniTSD(void)
+{
+ _eglLockMutex(&_egl_TSDMutex);
+ if (_egl_TSDInitialized) {
+ _EGLThreadInfo *t = _eglGetTSD();
+
+ _egl_TSDInitialized = EGL_FALSE;
+ if (t && _egl_FreeTSD)
+ _egl_FreeTSD((void *) t);
+ pthread_key_delete(_egl_TSD);
+ }
+ _eglUnlockMutex(&_egl_TSDMutex);
+}
+
+static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *))
+{
+ if (!_egl_TSDInitialized) {
+ _eglLockMutex(&_egl_TSDMutex);
+
+ /* check again after acquiring lock */
+ if (!_egl_TSDInitialized) {
+ if (pthread_key_create(&_egl_TSD, (void (*)(void *)) dtor) != 0) {
+ _eglUnlockMutex(&_egl_TSDMutex);
+ return EGL_FALSE;
+ }
+ _egl_FreeTSD = dtor;
+ _eglAddAtExitCall(_eglFiniTSD);
+ _egl_TSDInitialized = EGL_TRUE;
+ }
+
+ _eglUnlockMutex(&_egl_TSDMutex);
+ }
+
+ return EGL_TRUE;
+}
+
+#else /* PTHREADS */
+static const _EGLThreadInfo *_egl_TSD;
+static void (*_egl_FreeTSD)(_EGLThreadInfo *);
+
+static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
+{
+ _egl_TSD = t;
+}
+
+static INLINE _EGLThreadInfo *_eglGetTSD(void)
+{
+ return (_EGLThreadInfo *) _egl_TSD;
+}
+
+static INLINE void _eglFiniTSD(void)
+{
+ if (_egl_FreeTSD && _egl_TSD)
+ _egl_FreeTSD((_EGLThreadInfo *) _egl_TSD);
+}
+
+static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *))
+{
+ if (!_egl_FreeTSD && dtor) {
+ _egl_FreeTSD = dtor;
+ _eglAddAtExitCall(_eglFiniTSD);
+ }
+ return EGL_TRUE;
+}
+
+#endif /* !PTHREADS */
+
+
+static void
+_eglInitThreadInfo(_EGLThreadInfo *t)
+{
+ memset(t, 0, sizeof(*t));
+ t->LastError = EGL_SUCCESS;
+ /* default, per EGL spec */
+ t->CurrentAPIIndex = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
+}
+
+
+/**
+ * Allocate and init a new _EGLThreadInfo object.
+ */
+static _EGLThreadInfo *
+_eglCreateThreadInfo(void)
+{
+ _EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo));
+ if (t)
+ _eglInitThreadInfo(t);
+ else
+ t = &dummy_thread;
+ return t;
+}
+
+
+/**
+ * Delete/free a _EGLThreadInfo object.
+ */
+static void
+_eglDestroyThreadInfo(_EGLThreadInfo *t)
+{
+ if (t != &dummy_thread)
+ free(t);
+}
+
+
+/**
+ * Make sure TSD is initialized and return current value.
+ */
+static INLINE _EGLThreadInfo *
+_eglCheckedGetTSD(void)
+{
+ if (_eglInitTSD(&_eglDestroyThreadInfo) != EGL_TRUE) {
+ _eglLog(_EGL_FATAL, "failed to initialize \"current\" system");
+ return NULL;
+ }
+
+ return _eglGetTSD();
+}
+
+
+/**
+ * Return the calling thread's thread info.
+ * If the calling thread nevers calls this function before, or if its thread
+ * info was destroyed, a new one is created. This function never returns NULL.
+ * In the case allocation fails, a dummy one is returned. See also
+ * _eglIsCurrentThreadDummy.
+ */
+_EGLThreadInfo *
+_eglGetCurrentThread(void)
+{
+ _EGLThreadInfo *t = _eglCheckedGetTSD();
+ if (!t) {
+ t = _eglCreateThreadInfo();
+ _eglSetTSD(t);
+ }
+
+ return t;
+}
+
+
+/**
+ * Destroy the calling thread's thread info.
+ */
+void
+_eglDestroyCurrentThread(void)
+{
+ _EGLThreadInfo *t = _eglCheckedGetTSD();
+ if (t) {
+ _eglDestroyThreadInfo(t);
+ _eglSetTSD(NULL);
+ }
+}
+
+
+/**
+ * Return true if the calling thread's thread info is dummy.
+ * A dummy thread info is shared by all threads and should not be modified.
+ * Functions like eglBindAPI or eglMakeCurrent should check for dummy-ness
+ * before updating the thread info.
+ */
+EGLBoolean
+_eglIsCurrentThreadDummy(void)
+{
+ _EGLThreadInfo *t = _eglCheckedGetTSD();
+ return (!t || t == &dummy_thread);
+}
+
+
+/**
+ * Return the currently bound context, or NULL.
+ */
+_EGLContext *
+_eglGetCurrentContext(void)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ return t->CurrentContexts[t->CurrentAPIIndex];
+}
+
+
+/**
+ * Return the display of the currently bound context, or NULL.
+ */
+_EGLDisplay *
+_eglGetCurrentDisplay(void)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex];
+ if (ctx)
+ return ctx->Display;
+ else
+ return NULL;
+}
+
+
+/**
+ * Return the read or write surface of the currently bound context, or NULL.
+ */
+_EGLSurface *
+_eglGetCurrentSurface(EGLint readdraw)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex];
+ if (ctx) {
+ switch (readdraw) {
+ case EGL_DRAW:
+ return ctx->DrawSurface;
+ case EGL_READ:
+ return ctx->ReadSurface;
+ default:
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * Record EGL error code.
+ */
+EGLBoolean
+_eglError(EGLint errCode, const char *msg)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ const char *s;
+
+ if (t == &dummy_thread)
+ return EGL_FALSE;
+
+ if (t->LastError == EGL_SUCCESS) {
+ t->LastError = errCode;
+
+ switch (errCode) {
+ case EGL_BAD_ACCESS:
+ s = "EGL_BAD_ACCESS";
+ break;
+ case EGL_BAD_ALLOC:
+ s = "EGL_BAD_ALLOC";
+ break;
+ case EGL_BAD_ATTRIBUTE:
+ s = "EGL_BAD_ATTRIBUTE";
+ break;
+ case EGL_BAD_CONFIG:
+ s = "EGL_BAD_CONFIG";
+ break;
+ case EGL_BAD_CONTEXT:
+ s = "EGL_BAD_CONTEXT";
+ break;
+ case EGL_BAD_CURRENT_SURFACE:
+ s = "EGL_BAD_CURRENT_SURFACE";
+ break;
+ case EGL_BAD_DISPLAY:
+ s = "EGL_BAD_DISPLAY";
+ break;
+ case EGL_BAD_MATCH:
+ s = "EGL_BAD_MATCH";
+ break;
+ case EGL_BAD_NATIVE_PIXMAP:
+ s = "EGL_BAD_NATIVE_PIXMAP";
+ break;
+ case EGL_BAD_NATIVE_WINDOW:
+ s = "EGL_BAD_NATIVE_WINDOW";
+ break;
+ case EGL_BAD_PARAMETER:
+ s = "EGL_BAD_PARAMETER";
+ break;
+ case EGL_BAD_SURFACE:
+ s = "EGL_BAD_SURFACE";
+ break;
+ case EGL_BAD_SCREEN_MESA:
+ s = "EGL_BAD_SCREEN_MESA";
+ break;
+ case EGL_BAD_MODE_MESA:
+ s = "EGL_BAD_MODE_MESA";
+ break;
+ default:
+ s = "other";
+ }
+ _eglLog(_EGL_DEBUG, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg);
+ }
+
+ return EGL_FALSE;
+}
diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h
new file mode 100644
index 0000000000..8eb241029e
--- /dev/null
+++ b/src/egl/main/eglcurrent.h
@@ -0,0 +1,84 @@
+#ifndef EGLCURRENT_INCLUDED
+#define EGLCURRENT_INCLUDED
+
+#include "egltypedefs.h"
+
+
+#define _EGL_API_NUM_INDICES \
+ (EGL_OPENGL_API - EGL_OPENGL_ES_API + 2) /* idx 0 is for EGL_NONE */
+
+
+/**
+ * Per-thread info
+ */
+struct _egl_thread_info
+{
+ EGLint LastError;
+ _EGLContext *CurrentContexts[_EGL_API_NUM_INDICES];
+ /* use index for fast access to current context */
+ EGLint CurrentAPIIndex;
+};
+
+
+/**
+ * Return true if a client API enum can be converted to an index.
+ */
+static INLINE EGLBoolean
+_eglIsApiValid(EGLenum api)
+{
+ return ((api >= EGL_OPENGL_ES_API && api <= EGL_OPENGL_API) ||
+ api == EGL_NONE);
+}
+
+
+/**
+ * Convert a client API enum to an index, for use by thread info.
+ * The client API enum is assumed to be valid.
+ */
+static INLINE EGLint
+_eglConvertApiToIndex(EGLenum api)
+{
+ return (api != EGL_NONE) ? api - EGL_OPENGL_ES_API + 1 : 0;
+}
+
+
+/**
+ * Convert an index, used by thread info, to a client API enum.
+ * The index is assumed to be valid.
+ */
+static INLINE EGLenum
+_eglConvertApiFromIndex(EGLint idx)
+{
+ return (idx) ? EGL_OPENGL_ES_API + idx - 1 : EGL_NONE;
+}
+
+
+extern _EGLThreadInfo *
+_eglGetCurrentThread(void);
+
+
+extern void
+_eglDestroyCurrentThread(void);
+
+
+extern EGLBoolean
+_eglIsCurrentThreadDummy(void);
+
+
+extern _EGLContext *
+_eglGetCurrentContext(void);
+
+
+extern _EGLDisplay *
+_eglGetCurrentDisplay(void);
+
+
+extern _EGLSurface *
+_eglGetCurrentSurface(EGLint readdraw);
+
+
+extern EGLBoolean
+_eglError(EGLint errCode, const char *msg);
+
+
+#endif /* EGLCURRENT_INCLUDED */
diff --git a/src/egl/main/egldefines.h b/src/egl/main/egldefines.h
new file mode 100644
index 0000000000..8fc2301b79
--- /dev/null
+++ b/src/egl/main/egldefines.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+
+/**
+ * Internal EGL defines
+ */
+
+
+#ifndef EGLDEFINES_INCLUDED
+#define EGLDEFINES_INCLUDED
+
+
+#define _EGL_MAX_EXTENSIONS_LEN 1000
+
+#define _EGL_VENDOR_STRING "Mesa Project"
+
+
+
+#endif /* EGLDEFINES_INCLUDED */
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
index 074a85bf26..896d60dbe1 100644
--- a/src/egl/main/egldisplay.c
+++ b/src/egl/main/egldisplay.c
@@ -1,71 +1,371 @@
+/**
+ * Functions related to EGLDisplay.
+ */
+
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "eglcontext.h"
+#include "eglsurface.h"
#include "egldisplay.h"
+#include "egldriver.h"
#include "eglglobals.h"
-#include "eglhash.h"
+#include "eglstring.h"
+#include "eglmutex.h"
+#include "egllog.h"
+
+
+/**
+ * Finish display management.
+ */
+void
+_eglFiniDisplay(void)
+{
+ _EGLDisplay *dpyList, *dpy;
+
+ /* atexit function is called with global mutex locked */
+ dpyList = _eglGlobal.DisplayList;
+ while (dpyList) {
+ /* pop list head */
+ dpy = dpyList;
+ dpyList = dpyList->Next;
+
+ if (dpy->ContextList || dpy->SurfaceList)
+ _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
+
+ free(dpy);
+ }
+ _eglGlobal.DisplayList = NULL;
+}
-static char *
-my_strdup(const char *s)
+/**
+ * If the first character is '!' we interpret it as specific driver name
+ * (i.e. "!r200" or "!i830"). Whatever follows ':' is interpreted as
+ * arguments.
+ *
+ * The caller may free() the returned driver name.
+ */
+char *
+_eglSplitDisplayString(const char *dpyString, const char **args)
{
- int l = strlen(s);
- char *s2 = malloc(l + 1);
- strcpy(s2, s);
- return s2;
+ char *drv, *p;
+
+ if (!dpyString || dpyString[0] != '!')
+ return NULL;
+ drv = _eglstrdup(dpyString + 1);
+ if (!drv)
+ return NULL;
+
+ p = strchr(dpyString, ':');
+ if (p) {
+ drv[p - dpyString] = '\0';
+ p++;
+ }
+ if (args)
+ *args = p;
+
+ return drv;
}
/**
- * We're assuming that the NativeDisplayType parameter is actually
- * a string.
- * Return a new _EGLDisplay object for the given displayName
+ * Allocate a new _EGLDisplay object for the given nativeDisplay handle.
+ * We'll also try to determine the device driver name at this time.
+ *
+ * Note that nativeDisplay may be an X Display ptr, or a string.
*/
_EGLDisplay *
-_eglNewDisplay(NativeDisplayType displayName)
+_eglNewDisplay(NativeDisplayType nativeDisplay)
{
_EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
if (dpy) {
- dpy->Handle = _eglHashGenKey(_eglGlobal.Displays);
- _eglHashInsert(_eglGlobal.Displays, dpy->Handle, dpy);
- if (displayName)
- dpy->Name = my_strdup(displayName);
- else
- dpy->Name = NULL;
- dpy->Driver = NULL; /* this gets set later */
+ dpy->NativeDisplay = nativeDisplay;
+
+ dpy->DriverName = _eglPreloadDriver(dpy);
+ if (!dpy->DriverName) {
+ free(dpy);
+ return NULL;
+ }
}
return dpy;
}
/**
- * Return the _EGLDisplay object that corresponds to the given public/
- * opaque display handle.
+ * Link a display to itself and return the handle of the link.
+ * The handle can be passed to client directly.
*/
-_EGLDisplay *
-_eglLookupDisplay(EGLDisplay dpy)
+EGLDisplay
+_eglLinkDisplay(_EGLDisplay *dpy)
+{
+ _eglLockMutex(_eglGlobal.Mutex);
+
+ dpy->Next = _eglGlobal.DisplayList;
+ _eglGlobal.DisplayList = dpy;
+
+ _eglUnlockMutex(_eglGlobal.Mutex);
+
+ return (EGLDisplay) dpy;
+}
+
+
+/**
+ * Unlink a linked display from itself.
+ * Accessing an unlinked display should generate EGL_BAD_DISPLAY error.
+ */
+void
+_eglUnlinkDisplay(_EGLDisplay *dpy)
{
- _EGLDisplay *d = (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, dpy);
- return d;
+ _EGLDisplay *prev;
+
+ _eglLockMutex(_eglGlobal.Mutex);
+
+ prev = _eglGlobal.DisplayList;
+ if (prev != dpy) {
+ while (prev) {
+ if (prev->Next == dpy)
+ break;
+ prev = prev->Next;
+ }
+ assert(prev);
+ prev->Next = dpy->Next;
+ }
+ else {
+ _eglGlobal.DisplayList = dpy->Next;
+ }
+
+ _eglUnlockMutex(_eglGlobal.Mutex);
}
+/**
+ * Find the display corresponding to the specified native display id in all
+ * linked displays.
+ */
_EGLDisplay *
-_eglGetCurrentDisplay(void)
+_eglFindDisplay(NativeDisplayType nativeDisplay)
{
- _EGLContext *ctx = _eglGetCurrentContext();
- if (ctx)
- return ctx->Display;
- else
- return NULL;
+ _EGLDisplay *dpy;
+
+ _eglLockMutex(_eglGlobal.Mutex);
+
+ dpy = _eglGlobal.DisplayList;
+ while (dpy) {
+ if (dpy->NativeDisplay == nativeDisplay) {
+ _eglUnlockMutex(_eglGlobal.Mutex);
+ return dpy;
+ }
+ dpy = dpy->Next;
+ }
+
+ _eglUnlockMutex(_eglGlobal.Mutex);
+
+ return NULL;
+}
+
+
+/**
+ * Destroy the contexts and surfaces that are linked to the display.
+ */
+void
+_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
+{
+ _EGLContext *contexts;
+ _EGLSurface *surfaces;
+
+ contexts = display->ContextList;
+ surfaces = display->SurfaceList;
+
+ while (contexts) {
+ _EGLContext *ctx = contexts;
+ contexts = contexts->Next;
+
+ _eglUnlinkContext(ctx);
+ drv->API.DestroyContext(drv, display, ctx);
+ }
+ assert(!display->ContextList);
+
+ while (surfaces) {
+ _EGLSurface *surf = surfaces;
+ surfaces = surfaces->Next;
+
+ _eglUnlinkSurface(surf);
+ drv->API.DestroySurface(drv, display, surf);
+ }
+ assert(!display->SurfaceList);
}
+/**
+ * Free all the data hanging of an _EGLDisplay object, but not
+ * the object itself.
+ */
void
_eglCleanupDisplay(_EGLDisplay *disp)
{
+ EGLint i;
+
+ if (disp->Configs) {
+ for (i = 0; i < disp->NumConfigs; i++)
+ free(disp->Configs[i]);
+ free(disp->Configs);
+ disp->Configs = NULL;
+ disp->NumConfigs = 0;
+ }
+
/* XXX incomplete */
- free(disp->Configs);
- free(disp->Name);
- /* driver deletes _EGLDisplay */
}
+
+
+/**
+ * Link a context to a display and return the handle of the link.
+ * The handle can be passed to client directly.
+ */
+EGLContext
+_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy)
+{
+ ctx->Display = dpy;
+ ctx->Next = dpy->ContextList;
+ dpy->ContextList = ctx;
+ return (EGLContext) ctx;
+}
+
+
+/**
+ * Unlink a linked context from its display.
+ * Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
+ */
+void
+_eglUnlinkContext(_EGLContext *ctx)
+{
+ _EGLContext *prev;
+
+ prev = ctx->Display->ContextList;
+ if (prev != ctx) {
+ while (prev) {
+ if (prev->Next == ctx)
+ break;
+ prev = prev->Next;
+ }
+ assert(prev);
+ prev->Next = ctx->Next;
+ }
+ else {
+ ctx->Display->ContextList = ctx->Next;
+ }
+
+ ctx->Next = NULL;
+ ctx->Display = NULL;
+}
+
+
+/**
+ * Link a surface to a display and return the handle of the link.
+ * The handle can be passed to client directly.
+ */
+EGLSurface
+_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy)
+{
+ surf->Display = dpy;
+ surf->Next = dpy->SurfaceList;
+ dpy->SurfaceList = surf;
+ return (EGLSurface) surf;
+}
+
+
+/**
+ * Unlink a linked surface from its display.
+ * Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
+ */
+void
+_eglUnlinkSurface(_EGLSurface *surf)
+{
+ _EGLSurface *prev;
+
+ prev = surf->Display->SurfaceList;
+ if (prev != surf) {
+ while (prev) {
+ if (prev->Next == surf)
+ break;
+ prev = prev->Next;
+ }
+ assert(prev);
+ prev->Next = surf->Next;
+ }
+ else {
+ prev = NULL;
+ surf->Display->SurfaceList = surf->Next;
+ }
+
+ surf->Next = NULL;
+ surf->Display = NULL;
+}
+
+
+#ifndef _EGL_SKIP_HANDLE_CHECK
+
+
+/**
+ * Return EGL_TRUE if the given handle is a valid handle to a display.
+ */
+EGLBoolean
+_eglCheckDisplayHandle(EGLDisplay dpy)
+{
+ _EGLDisplay *cur;
+
+ _eglLockMutex(_eglGlobal.Mutex);
+ cur = _eglGlobal.DisplayList;
+ while (cur) {
+ if (cur == (_EGLDisplay *) dpy)
+ break;
+ cur = cur->Next;
+ }
+ _eglUnlockMutex(_eglGlobal.Mutex);
+ return (cur != NULL);
+}
+
+
+/**
+ * Return EGL_TRUE if the given handle is a valid handle to a context.
+ */
+EGLBoolean
+_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy)
+{
+ _EGLContext *cur = NULL;
+
+ if (dpy)
+ cur = dpy->ContextList;
+ while (cur) {
+ if (cur == (_EGLContext *) ctx) {
+ assert(cur->Display == dpy);
+ break;
+ }
+ cur = cur->Next;
+ }
+ return (cur != NULL);
+}
+
+
+/**
+ * Return EGL_TRUE if the given handle is a valid handle to a surface.
+ */
+EGLBoolean
+_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy)
+{
+ _EGLSurface *cur = NULL;
+
+ if (dpy)
+ cur = dpy->SurfaceList;
+ while (cur) {
+ if (cur == (_EGLSurface *) surf) {
+ assert(cur->Display == dpy);
+ break;
+ }
+ cur = cur->Next;
+ }
+ return (cur != NULL);
+}
+
+
+#endif /* !_EGL_SKIP_HANDLE_CHECK */
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 1a03fdd4ad..cf103b35c6 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -1,44 +1,277 @@
#ifndef EGLDISPLAY_INCLUDED
#define EGLDISPLAY_INCLUDED
-
#include "egltypedefs.h"
+#include "egldefines.h"
+#include "eglcontext.h"
+#include "eglsurface.h"
+
+
+/**
+ * Optional EGL extensions info.
+ */
+struct _egl_extensions
+{
+ EGLBoolean MESA_screen_surface;
+ EGLBoolean MESA_copy_context;
+ EGLBoolean KHR_image;
+ EGLBoolean KHR_image_base;
+ EGLBoolean KHR_image_pixmap;
+
+ char String[_EGL_MAX_EXTENSIONS_LEN];
+};
struct _egl_display
{
- EGLDisplay Handle;
+ /* used to link displays */
+ _EGLDisplay *Next;
- char *Name;
+ EGLNativeDisplayType NativeDisplay;
+
+ const char *DriverName;
_EGLDriver *Driver;
+ void *DriverData; /* private to driver */
+
+ int APImajor, APIminor; /**< as returned by eglInitialize() */
+ char Version[1000]; /**< initialized from APImajor/minor, DriverName */
+
+ /** Bitmask of supported APIs (EGL_xx_BIT) set by the driver during init */
+ EGLint ClientAPIsMask;
+ char ClientAPIs[1000]; /**< updated by eglQueryString */
+
+ _EGLExtensions Extensions;
+
+ int LargestPbuffer;
EGLint NumScreens;
_EGLScreen **Screens; /* array [NumScreens] */
EGLint NumConfigs;
- _EGLConfig *Configs; /* array [NumConfigs] */
+ _EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */
+
+ /* lists of linked contexts and surface */
+ _EGLContext *ContextList;
+ _EGLSurface *SurfaceList;
+
+ _EGLImage *ImageList;
};
+extern void
+_eglFiniDisplay(void);
+
+
+extern char *
+_eglSplitDisplayString(const char *dpyString, const char **args);
+
+
extern _EGLDisplay *
_eglNewDisplay(NativeDisplayType displayName);
-extern _EGLDisplay *
-_eglLookupDisplay(EGLDisplay dpy);
+extern EGLDisplay
+_eglLinkDisplay(_EGLDisplay *dpy);
+
+
+extern void
+_eglUnlinkDisplay(_EGLDisplay *dpy);
extern _EGLDisplay *
-_eglGetCurrentDisplay(void);
+_eglFindDisplay(NativeDisplayType nativeDisplay);
+
+
+extern void
+_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *dpy);
extern void
_eglCleanupDisplay(_EGLDisplay *disp);
-extern EGLBoolean
-_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attrib, EGLint *value);
+extern EGLContext
+_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy);
+
+
+extern void
+_eglUnlinkContext(_EGLContext *ctx);
+
+
+extern EGLSurface
+_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy);
+
+
+extern void
+_eglUnlinkSurface(_EGLSurface *surf);
+
+
+#ifndef _EGL_SKIP_HANDLE_CHECK
+
+
+extern EGLBoolean
+_eglCheckDisplayHandle(EGLDisplay dpy);
+
+
+extern EGLBoolean
+_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy);
+
+
+extern EGLBoolean
+_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy);
+
+
+#else /* !_EGL_SKIP_HANDLE_CHECK */
+/* Only do a quick check. This is NOT standard compliant. */
+
+static INLINE EGLBoolean
+_eglCheckDisplayHandle(EGLDisplay dpy)
+{
+ return ((_EGLDisplay *) dpy != NULL);
+}
+
+
+static INLINE EGLBoolean
+_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy)
+{
+ _EGLContext *c = (_EGLContext *) ctx;
+ return (dpy && c && c->Display == dpy);
+}
+
+
+static INLINE EGLBoolean
+_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy)
+{
+ _EGLSurface *s = (_EGLSurface *) surf;
+ return (dpy && s && s->Display == dpy);
+}
+
+
+#endif /* _EGL_SKIP_HANDLE_CHECK */
+
+
+/**
+ * Lookup a handle to find the linked display.
+ * Return NULL if the handle has no corresponding linked display.
+ */
+static INLINE _EGLDisplay *
+_eglLookupDisplay(EGLDisplay display)
+{
+ _EGLDisplay *dpy = (_EGLDisplay *) display;
+ if (!_eglCheckDisplayHandle(display))
+ dpy = NULL;
+ return dpy;
+}
+
+
+/**
+ * Return the handle of a linked display, or EGL_NO_DISPLAY.
+ */
+static INLINE EGLDisplay
+_eglGetDisplayHandle(_EGLDisplay *dpy)
+{
+ return (EGLDisplay) ((dpy) ? dpy : EGL_NO_DISPLAY);
+}
+
+
+/**
+ * Return true if the display is linked.
+ */
+static INLINE EGLBoolean
+_eglIsDisplayLinked(_EGLDisplay *dpy)
+{
+ return (EGLBoolean) (_eglGetDisplayHandle(dpy) != EGL_NO_DISPLAY);
+}
+
+
+/**
+ * Lookup a handle to find the linked context.
+ * Return NULL if the handle has no corresponding linked context.
+ */
+static INLINE _EGLContext *
+_eglLookupContext(EGLContext context, _EGLDisplay *dpy)
+{
+ _EGLContext *ctx = (_EGLContext *) context;
+ if (!_eglCheckContextHandle(context, dpy))
+ ctx = NULL;
+ return ctx;
+}
+
+
+/**
+ * Return the handle of a linked context, or EGL_NO_CONTEXT.
+ */
+static INLINE EGLContext
+_eglGetContextHandle(_EGLContext *ctx)
+{
+ return (EGLContext) ((ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT);
+}
+
+
+/**
+ * Return true if the context is linked to a display.
+ */
+static INLINE EGLBoolean
+_eglIsContextLinked(_EGLContext *ctx)
+{
+ return (EGLBoolean) (_eglGetContextHandle(ctx) != EGL_NO_CONTEXT);
+}
+
+
+/**
+ * Lookup a handle to find the linked surface.
+ * Return NULL if the handle has no corresponding linked surface.
+ */
+static INLINE _EGLSurface *
+_eglLookupSurface(EGLSurface surface, _EGLDisplay *dpy)
+{
+ _EGLSurface *surf = (_EGLSurface *) surface;
+ if (!_eglCheckSurfaceHandle(surf, dpy))
+ surf = NULL;
+ return surf;
+}
+
+
+/**
+ * Return the handle of a linked surface, or EGL_NO_SURFACE.
+ */
+static INLINE EGLSurface
+_eglGetSurfaceHandle(_EGLSurface *surf)
+{
+ return (EGLSurface) ((surf && surf->Display) ? surf : EGL_NO_SURFACE);
+}
+
+
+/**
+ * Return true if the surface is linked to a display.
+ */
+static INLINE EGLBoolean
+_eglIsSurfaceLinked(_EGLSurface *surf)
+{
+ return (EGLBoolean) (_eglGetSurfaceHandle(surf) != EGL_NO_SURFACE);
+}
+
+
+/**
+ * Cast an unsigned int to a pointer.
+ */
+static INLINE void *
+_eglUIntToPointer(unsigned int v)
+{
+ return (void *) ((uintptr_t) v);
+}
+
+
+/**
+ * Cast a pointer to an unsigned int. The pointer must be one that is
+ * returned by _eglUIntToPointer.
+ */
+static INLINE unsigned int
+_eglPointerToUInt(const void *p)
+{
+ return (unsigned int) ((uintptr_t) p);
+}
#endif /* EGLDISPLAY_INCLUDED */
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index bda06dd827..89e04a7130 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -1,131 +1,338 @@
+/**
+ * Functions for choosing and opening/loading device drivers.
+ */
+
+
#include <assert.h>
-#include <dlfcn.h>
-#include <stdio.h>
#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "eglconfig.h"
#include "eglcontext.h"
+#include "egldefines.h"
#include "egldisplay.h"
#include "egldriver.h"
#include "eglglobals.h"
#include "egllog.h"
+#include "eglmisc.h"
#include "eglmode.h"
#include "eglscreen.h"
+#include "eglstring.h"
#include "eglsurface.h"
+#include "eglimage.h"
-
-const char *DefaultDriverName = "demodriver";
-
+#if defined(_EGL_PLATFORM_X)
+#include <dlfcn.h>
+#elif defined(_EGL_PLATFORM_WINDOWS)
+/* Use static linking on Windows for now */
+#define WINDOWS_STATIC_LINK
+#endif
/**
- * Choose and open/init the hardware driver for the given EGLDisplay.
- * Previously, the EGLDisplay was created with _eglNewDisplay() where
- * we recorded the user's NativeDisplayType parameter.
- *
- * Now we'll use the NativeDisplayType value.
- *
- * Currently, the native display value is treated as a string.
- * If the first character is ':' we interpret it as a screen or card index
- * number (i.e. ":0" or ":1", etc)
- * Else if the first character is '!' we interpret it as specific driver name
- * (i.e. "!r200" or "!i830".
+ * Wrappers for dlopen/dlclose()
*/
-_EGLDriver *
-_eglChooseDriver(EGLDisplay display)
-{
- _EGLDisplay *dpy = _eglLookupDisplay(display);
- _EGLDriver *drv;
- const char *driverName = DefaultDriverName;
- const char *name;
+#if defined(_EGL_PLATFORM_WINDOWS)
+#ifdef WINDOWS_STATIC_LINK
+ static const char *DefaultDriverName = "Windows EGL Static Library";
+#else
+ /* XXX Need to decide how to do dynamic name lookup on Windows */
+ static const char *DefaultDriverName = "TBD";
+#endif
+ typedef HMODULE lib_handle;
+
+ static HMODULE
+ open_library(const char *filename)
+ {
+#ifdef WINDOWS_STATIC_LINK
+ return 0;
+#else
+ return LoadLibrary(filename);
+#endif
+ }
+
+ static void
+ close_library(HMODULE lib)
+ {
+#ifdef WINDOWS_STATIC_LINK
+#else
+ FreeLibrary(lib);
+#endif
+ }
- assert(dpy);
+#elif defined(_EGL_PLATFORM_X)
+ static const char *DefaultDriverName = "egl_softpipe";
- name = dpy->Name;
- if (!name) {
- /* use default */
+ typedef void * lib_handle;
+
+ static void *
+ open_library(const char *filename)
+ {
+ return dlopen(filename, RTLD_LAZY);
}
- else if (name[0] == ':' && (name[1] >= '0' && name[1] <= '9') && !name[2]) {
- /* XXX probe hardware here to determine which driver to open */
- driverName = "libEGLdri";
+
+ static void
+ close_library(void *lib)
+ {
+ dlclose(lib);
}
- else if (name[0] == '!') {
- /* use specified driver name */
- driverName = name + 1;
+
+#endif
+
+
+/**
+ * Choose a driver for a given display.
+ * The caller may free() the returned strings.
+ */
+static char *
+_eglChooseDriver(_EGLDisplay *dpy, char **argsRet)
+{
+ char *path = NULL;
+ const char *args = NULL;
+ const char *suffix = NULL;
+ const char *p;
+
+ path = getenv("EGL_DRIVER");
+ if (path)
+ path = _eglstrdup(path);
+
+#if defined(_EGL_PLATFORM_X)
+ if (!path && dpy->NativeDisplay) {
+ /* assume (wrongly!) that the native display is a display string */
+ path = _eglSplitDisplayString((const char *) dpy->NativeDisplay, &args);
}
- else {
- /* Maybe display was returned by XOpenDisplay? */
- _eglLog(_EGL_FATAL, "eglChooseDriver() bad name");
+ suffix = "so";
+#elif defined(_EGL_PLATFORM_WINDOWS)
+ suffix = "dll";
+#endif /* _EGL_PLATFORM_X */
+
+ if (!path)
+ path = _eglstrdup(DefaultDriverName);
+
+ /* append suffix if there isn't */
+ p = strrchr(path, '.');
+ if (!p && suffix) {
+ size_t len = strlen(path);
+ char *tmp = malloc(len + strlen(suffix) + 2);
+ if (tmp) {
+ memcpy(tmp, path, len);
+ tmp[len++] = '.';
+ tmp[len] = '\0';
+ strcat(tmp + len, suffix);
+
+ free(path);
+ path = tmp;
+ }
}
- _eglLog(_EGL_INFO, "eglChooseDriver() choosing %s", driverName);
-
- drv = _eglOpenDriver(dpy, driverName);
- dpy->Driver = drv;
+ if (argsRet)
+ *argsRet = (args) ? _eglstrdup(args) : NULL;
- return drv;
+ return path;
}
/**
- * Open/load the named driver and call its bootstrap function: _eglMain().
- * \return new _EGLDriver object.
+ * Open the named driver and find its bootstrap function: _eglMain().
*/
-_EGLDriver *
-_eglOpenDriver(_EGLDisplay *dpy, const char *driverName)
+static _EGLMain_t
+_eglOpenLibrary(const char *driverPath, lib_handle *handle)
{
- _EGLDriver *drv;
_EGLMain_t mainFunc;
- void *lib;
- char driverFilename[1000];
-
- /* XXX also prepend a directory path??? */
- sprintf(driverFilename, "%s.so", driverName);
-
- _eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
- lib = dlopen(driverFilename, RTLD_NOW);
+ lib_handle lib;
+
+ assert(driverPath);
+
+#if defined(_EGL_PLATFORM_WINDOWS)
+/* Use static linking on Windows for now */
+#ifdef WINDOWS_STATIC_LINK
+ lib = 0;
+ mainFunc = (_EGLMain_t)_eglMain;
+#else
+ /* XXX untested */
+ _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath);
+ lib = open_library(driverPath);
+ if (!lib) {
+ _eglLog(_EGL_WARNING, "Could not open %s",
+ driverPath);
+ return NULL;
+ }
+ mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
+#endif
+#elif defined(_EGL_PLATFORM_X)
+ _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath);
+ lib = open_library(driverPath);
if (!lib) {
_eglLog(_EGL_WARNING, "Could not open %s (%s)",
- driverFilename, dlerror());
+ driverPath, dlerror());
+ if (!getenv("EGL_DRIVER"))
+ _eglLog(_EGL_WARNING,
+ "The driver can be overridden by setting EGL_DRIVER");
return NULL;
}
-
mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
+#endif
+
if (!mainFunc) {
- _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
- dlclose(lib);
+ _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverPath);
+ if (lib)
+ close_library(lib);
return NULL;
}
- drv = mainFunc(dpy);
+ *handle = lib;
+ return mainFunc;
+}
+
+
+/**
+ * Load the named driver. The path and args passed will be
+ * owned by the driver and freed.
+ */
+static _EGLDriver *
+_eglLoadDriver(char *path, char *args)
+{
+ _EGLMain_t mainFunc;
+ lib_handle lib;
+ _EGLDriver *drv = NULL;
+
+ mainFunc = _eglOpenLibrary(path, &lib);
+ if (!mainFunc)
+ return NULL;
+
+ drv = mainFunc(args);
if (!drv) {
- dlclose(lib);
+ if (lib)
+ close_library(lib);
return NULL;
}
- /* with a recurvise open you want the inner most handle */
- if (!drv->LibHandle)
- drv->LibHandle = lib;
- else
- dlclose(lib);
- drv->Display = dpy;
+ if (!drv->Name) {
+ _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", path);
+ drv->Name = "UNNAMED";
+ }
+
+ drv->Path = path;
+ drv->Args = args;
+ drv->LibHandle = lib;
+
+ return drv;
+}
+
+
+/**
+ * Match a display to a preloaded driver.
+ */
+static _EGLDriver *
+_eglMatchDriver(_EGLDisplay *dpy)
+{
+ _EGLDriver *defaultDriver = NULL;
+ EGLint i;
+
+ for (i = 0; i < _eglGlobal.NumDrivers; i++) {
+ _EGLDriver *drv = _eglGlobal.Drivers[i];
+
+ /* display specifies a driver */
+ if (dpy->DriverName) {
+ if (strcmp(dpy->DriverName, drv->Name) == 0)
+ return drv;
+ }
+ else if (drv->Probe) {
+ if (drv->Probe(drv, dpy))
+ return drv;
+ }
+ else {
+ if (!defaultDriver)
+ defaultDriver = drv;
+ }
+ }
+
+ return defaultDriver;
+}
+
+
+/**
+ * Load a driver and save it.
+ */
+const char *
+_eglPreloadDriver(_EGLDisplay *dpy)
+{
+ char *path, *args;
+ _EGLDriver *drv;
+ EGLint i;
+
+ path = _eglChooseDriver(dpy, &args);
+ if (!path)
+ return NULL;
+
+ for (i = 0; i < _eglGlobal.NumDrivers; i++) {
+ drv = _eglGlobal.Drivers[i];
+ if (strcmp(drv->Path, path) == 0) {
+ _eglLog(_EGL_DEBUG, "Driver %s is already preloaded",
+ drv->Name);
+ free(path);
+ if (args)
+ free(args);
+ return drv->Name;
+ }
+ }
+
+ drv = _eglLoadDriver(path, args);
+ if (!drv)
+ return NULL;
+
+ _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+
+ return drv->Name;
+}
+
+
+/**
+ * Open a preloaded driver.
+ */
+_EGLDriver *
+_eglOpenDriver(_EGLDisplay *dpy)
+{
+ _EGLDriver *drv = _eglMatchDriver(dpy);
return drv;
}
+/**
+ * Close a preloaded driver.
+ */
EGLBoolean
-_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy)
+_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy)
{
- void *handle = drv->LibHandle;
- EGLBoolean b;
+ return EGL_TRUE;
+}
- _eglLog(_EGL_INFO, "Closing driver");
- /*
- * XXX check for currently bound context/surfaces and delete them?
- */
+/**
+ * Unload preloaded drivers.
+ */
+void
+_eglUnloadDrivers(void)
+{
+ EGLint i;
+ for (i = 0; i < _eglGlobal.NumDrivers; i++) {
+ _EGLDriver *drv = _eglGlobal.Drivers[i];
+ lib_handle handle = drv->LibHandle;
+
+ if (drv->Path)
+ free((char *) drv->Path);
+ if (drv->Args)
+ free((char *) drv->Args);
+
+ /* destroy driver */
+ if (drv->Unload)
+ drv->Unload(drv);
+
+ if (handle)
+ close_library(handle);
+ _eglGlobal.Drivers[i] = NULL;
+ }
- b = drv->API.Terminate(drv, dpy);
- dlclose(handle);
- return b;
+ _eglGlobal.NumDrivers = 0;
}
@@ -198,75 +405,56 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
#ifdef EGL_VERSION_1_2
drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
#endif /* EGL_VERSION_1_2 */
-}
-
-
-/**
- * Examine the individual extension enable/disable flags and recompute
- * the driver's Extensions string.
- */
-static void
-_eglUpdateExtensionsString(_EGLDriver *drv)
-{
- drv->Extensions.String[0] = 0;
- if (drv->Extensions.MESA_screen_surface)
- strcat(drv->Extensions.String, "EGL_MESA_screen_surface ");
- if (drv->Extensions.MESA_copy_context)
- strcat(drv->Extensions.String, "EGL_MESA_copy_context ");
- assert(strlen(drv->Extensions.String) < MAX_EXTENSIONS_LEN);
+#ifdef EGL_KHR_image_base
+ drv->API.CreateImageKHR = _eglCreateImageKHR;
+ drv->API.DestroyImageKHR = _eglDestroyImageKHR;
+#endif /* EGL_KHR_image_base */
}
-const char *
-_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name)
+/**
+ * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
+ * are supported on the system by looking for standard library names.
+ */
+EGLint
+_eglFindAPIs(void)
{
- (void) drv;
- (void) dpy;
- switch (name) {
- case EGL_VENDOR:
- return "Mesa Project";
- case EGL_VERSION:
- return "1.0";
- case EGL_EXTENSIONS:
- _eglUpdateExtensionsString(drv);
- return drv->Extensions.String;
-#ifdef EGL_VERSION_1_2
- case EGL_CLIENT_APIS:
- /* XXX need to initialize somewhere */
- return drv->ClientAPIs;
+ EGLint mask = 0x0;
+ lib_handle lib;
+#if defined(_EGL_PLATFORM_WINDOWS)
+ /* XXX not sure about these names */
+ const char *es1_libname = "libGLESv1_CM.dll";
+ const char *es2_libname = "libGLESv2.dll";
+ const char *gl_libname = "OpenGL32.dll";
+ const char *vg_libname = "libOpenVG.dll";
+#elif defined(_EGL_PLATFORM_X)
+ const char *es1_libname = "libGLESv1_CM.so";
+ const char *es2_libname = "libGLESv2.so";
+ const char *gl_libname = "libGL.so";
+ const char *vg_libname = "libOpenVG.so";
#endif
- default:
- _eglError(EGL_BAD_PARAMETER, "eglQueryString");
- return NULL;
- }
-}
+ if ((lib = open_library(es1_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENGL_ES_BIT;
+ }
-EGLBoolean
-_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy)
-{
- /* just a placeholder */
- (void) drv;
- (void) dpy;
- return EGL_TRUE;
-}
+ if ((lib = open_library(es2_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENGL_ES2_BIT;
+ }
+ if ((lib = open_library(gl_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENGL_BIT;
+ }
-EGLBoolean
-_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine)
-{
- /* just a placeholder */
- (void) drv;
- (void) dpy;
- switch (engine) {
- case EGL_CORE_NATIVE_ENGINE:
- break;
- default:
- _eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)");
- return EGL_FALSE;
+ if ((lib = open_library(vg_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENVG_BIT;
}
- return EGL_TRUE;
+ return mask;
}
diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h
index 88526e973d..6c848eb35e 100644
--- a/src/egl/main/egldriver.h
+++ b/src/egl/main/egldriver.h
@@ -5,56 +5,43 @@
#include "egltypedefs.h"
#include "eglapi.h"
-/* should probably use a dynamic-length string, but this will do */
-#define MAX_EXTENSIONS_LEN 1000
-
-
-/**
- * Optional EGL extensions info.
- */
-struct _egl_extensions
-{
- EGLBoolean MESA_screen_surface;
- EGLBoolean MESA_copy_context;
-
- char String[MAX_EXTENSIONS_LEN];
-};
-
/**
* Base class for device drivers.
*/
struct _egl_driver
{
- EGLBoolean Initialized; /* set by driver after initialized */
-
- void *LibHandle; /* dlopen handle */
+ void *LibHandle; /**< dlopen handle */
+ const char *Path; /**< path to this driver */
+ const char *Args; /**< args to load this driver */
- _EGLDisplay *Display;
+ const char *Name; /**< name of this driver */
+ /**< probe a display to see if it is supported */
+ EGLBoolean (*Probe)(_EGLDriver *drv, _EGLDisplay *dpy);
+ /**< called before dlclose to release this driver */
+ void (*Unload)(_EGLDriver *drv);
- int ABIversion;
- int APImajor, APIminor; /* returned through eglInitialize */
- const char *ClientAPIs;
-
- _EGLAPI API;
-
- _EGLExtensions Extensions;
+ _EGLAPI API; /**< EGL API dispatch table */
};
-extern _EGLDriver *_eglMain(_EGLDisplay *dpy);
+extern _EGLDriver *_eglMain(const char *args);
-extern _EGLDriver *
-_eglChooseDriver(EGLDisplay dpy);
+extern const char *
+_eglPreloadDriver(_EGLDisplay *dpy);
extern _EGLDriver *
-_eglOpenDriver(_EGLDisplay *dpy, const char *driverName);
+_eglOpenDriver(_EGLDisplay *dpy);
extern EGLBoolean
-_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy);
+_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy);
+
+
+void
+_eglUnloadDrivers(void);
extern _EGLDriver *
@@ -65,17 +52,8 @@ extern void
_eglInitDriverFallbacks(_EGLDriver *drv);
-extern const char *
-_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name);
-
-
-extern EGLBoolean
-_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy);
-
-
-extern EGLBoolean
-_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine);
-
+extern EGLint
+_eglFindAPIs(void);
#endif /* EGLDRIVER_INCLUDED */
diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c
index 608311d749..3ae4c1ad3a 100644
--- a/src/egl/main/eglglobals.c
+++ b/src/egl/main/eglglobals.c
@@ -1,148 +1,56 @@
-#include <stdio.h>
#include <stdlib.h>
+#include <assert.h>
#include "eglglobals.h"
+#include "egldriver.h"
+#include "egllog.h"
+#include "eglmutex.h"
-struct _egl_global _eglGlobal = { .Initialized = EGL_FALSE };
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-/**
- * Init the fields in the _eglGlobal struct
- * May be safely called more than once.
- */
-void
-_eglInitGlobals(void)
-{
- if (!_eglGlobal.Initialized) {
- _eglGlobal.Displays = _eglNewHashTable();
- _eglGlobal.Contexts = _eglNewHashTable();
- _eglGlobal.Surfaces = _eglNewHashTable();
- _eglGlobal.FreeScreenHandle = 1;
- _eglGlobal.Initialized = EGL_TRUE;
-
- _eglGlobal.OpenGLESAPISupported = EGL_TRUE;
- _eglGlobal.OpenVGAPISupported = EGL_FALSE;
-
- /* XXX temporary */
- _eglGlobal.ThreadInfo = _eglNewThreadInfo();
- }
-}
-
-
-/**
- * Should call this via an atexit handler.
- */
-void
-_eglDestroyGlobals(void)
+static _EGL_DECLARE_MUTEX(_eglGlobalMutex);
+struct _egl_global _eglGlobal =
{
- /* XXX TODO walk over table entries, deleting each */
- _eglDeleteHashTable(_eglGlobal.Displays);
- _eglDeleteHashTable(_eglGlobal.Contexts);
- _eglDeleteHashTable(_eglGlobal.Surfaces);
-}
-
-
-/**
- * Allocate and init a new _EGLThreadInfo object.
- */
-_EGLThreadInfo *
-_eglNewThreadInfo(void)
+ &_eglGlobalMutex, /* Mutex */
+ NULL, /* DisplayList */
+ 1, /* FreeScreenHandle */
+ 0x0, /* ClientAPIsMask */
+ 0, /* NumDrivers */
+ { NULL }, /* Drivers */
+ 2, /* NumAtExitCalls */
+ { /* AtExitCalls */
+ _eglFiniDisplay,
+ _eglUnloadDrivers
+ },
+};
+
+
+static void
+_eglAtExit(void)
{
- _EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo));
- if (t) {
- t->CurrentContext = EGL_NO_CONTEXT;
- t->LastError = EGL_SUCCESS;
- t->CurrentAPI = EGL_NONE;
- }
- return t;
+ EGLint i;
+ for (i = _eglGlobal.NumAtExitCalls - 1; i >= 0; i--)
+ _eglGlobal.AtExitCalls[i]();
}
-/**
- * Delete/free a _EGLThreadInfo object.
- */
void
-_eglDeleteThreadData(_EGLThreadInfo *t)
-{
- free(t);
-}
-
-
-
-/**
- * Return pointer to calling thread's _EGLThreadInfo object.
- * Create a new one if needed.
- * Should never return NULL.
- */
-_EGLThreadInfo *
-_eglGetCurrentThread(void)
+_eglAddAtExitCall(void (*func)(void))
{
- _eglInitGlobals();
-
- /* XXX temporary */
- return _eglGlobal.ThreadInfo;
-}
+ if (func) {
+ static EGLBoolean registered = EGL_FALSE;
+ _eglLockMutex(_eglGlobal.Mutex);
-/**
- * Record EGL error code.
- */
-void
-_eglError(EGLint errCode, const char *msg)
-{
- _EGLThreadInfo *t = _eglGetCurrentThread();
- const char *s;
+ if (!registered) {
+ atexit(_eglAtExit);
+ registered = EGL_TRUE;
+ }
- if (t->LastError == EGL_SUCCESS) {
- t->LastError = errCode;
+ assert(_eglGlobal.NumAtExitCalls < ARRAY_SIZE(_eglGlobal.AtExitCalls));
+ _eglGlobal.AtExitCalls[_eglGlobal.NumAtExitCalls++] = func;
- switch (errCode) {
- case EGL_BAD_ACCESS:
- s = "EGL_BAD_ACCESS";
- break;
- case EGL_BAD_ALLOC:
- s = "EGL_BAD_ALLOC";
- break;
- case EGL_BAD_ATTRIBUTE:
- s = "EGL_BAD_ATTRIBUTE";
- break;
- case EGL_BAD_CONFIG:
- s = "EGL_BAD_CONFIG";
- break;
- case EGL_BAD_CONTEXT:
- s = "EGL_BAD_CONTEXT";
- break;
- case EGL_BAD_CURRENT_SURFACE:
- s = "EGL_BAD_CURRENT_SURFACE";
- break;
- case EGL_BAD_DISPLAY:
- s = "EGL_BAD_DISPLAY";
- break;
- case EGL_BAD_MATCH:
- s = "EGL_BAD_MATCH";
- break;
- case EGL_BAD_NATIVE_PIXMAP:
- s = "EGL_BAD_NATIVE_PIXMAP";
- break;
- case EGL_BAD_NATIVE_WINDOW:
- s = "EGL_BAD_NATIVE_WINDOW";
- break;
- case EGL_BAD_PARAMETER:
- s = "EGL_BAD_PARAMETER";
- break;
- case EGL_BAD_SURFACE:
- s = "EGL_BAD_SURFACE";
- break;
- case EGL_BAD_SCREEN_MESA:
- s = "EGL_BAD_SCREEN_MESA";
- break;
- case EGL_BAD_MODE_MESA:
- s = "EGL_BAD_MODE_MESA";
- break;
- default:
- s = "other";
- }
- /* XXX temporary */
- fprintf(stderr, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg);
+ _eglUnlockMutex(_eglGlobal.Mutex);
}
}
diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h
index c16baa2d6b..58511076d4 100644
--- a/src/egl/main/eglglobals.h
+++ b/src/egl/main/eglglobals.h
@@ -2,18 +2,9 @@
#define EGLGLOBALS_INCLUDED
#include "egltypedefs.h"
-#include "eglhash.h"
-
-
-/**
- * Per-thread info
- */
-struct _egl_thread_info
-{
- EGLint LastError;
- _EGLContext *CurrentContext;
- EGLenum CurrentAPI;
-};
+#include "egldisplay.h"
+#include "eglcurrent.h"
+#include "eglmutex.h"
/**
@@ -21,20 +12,21 @@ struct _egl_thread_info
*/
struct _egl_global
{
- EGLBoolean Initialized;
+ _EGLMutex *Mutex;
- _EGLHashtable *Displays;
- _EGLHashtable *Contexts;
- _EGLHashtable *Surfaces;
+ /* the list of all displays */
+ _EGLDisplay *DisplayList;
EGLScreenMESA FreeScreenHandle;
- /* XXX these may be temporary */
- EGLBoolean OpenGLESAPISupported;
- EGLBoolean OpenVGAPISupported;
+ /* bitmaks of supported APIs (supported by _some_ driver) */
+ EGLint ClientAPIsMask;
+
+ EGLint NumDrivers;
+ _EGLDriver *Drivers[10];
- /* XXX temporary - should be thread-specific data (TSD) */
- _EGLThreadInfo *ThreadInfo;
+ EGLint NumAtExitCalls;
+ void (*AtExitCalls[10])(void);
};
@@ -42,27 +34,7 @@ extern struct _egl_global _eglGlobal;
extern void
-_eglInitGlobals(void);
-
-
-extern void
-_eglDestroyGlobals(void);
-
-
-extern _EGLThreadInfo *
-_eglNewThreadInfo(void);
-
-
-extern void
-_eglDeleteThreadData(_EGLThreadInfo *t);
-
-
-extern _EGLThreadInfo *
-_eglGetCurrentThread(void);
-
-
-extern void
-_eglError(EGLint errCode, const char *msg);
+_eglAddAtExitCall(void (*func)(void));
#endif /* EGLGLOBALS_INCLUDED */
diff --git a/src/egl/main/eglhash.c b/src/egl/main/eglhash.c
deleted file mode 100644
index 8e3da2e906..0000000000
--- a/src/egl/main/eglhash.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/**
- * \file hash.c
- * Generic hash table.
- *
- * This code taken from Mesa and adapted.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "eglhash.h"
-
-
-#define TABLE_SIZE 1023 /**< Size of lookup table/array */
-
-#define HASH_FUNC(K) ((K) % TABLE_SIZE)
-
-
-/*
- * Unfinished mutex stuff
- */
-
-typedef int _EGLMutex;
-
-static void
-_eglInitMutex(_EGLMutex m)
-{
-}
-
-static void
-_eglDestroyMutex(_EGLMutex m)
-{
-}
-
-static void
-_eglLockMutex(_EGLMutex m)
-{
-}
-
-static void
-_eglUnlockMutex(_EGLMutex m)
-{
-}
-
-
-
-typedef struct _egl_hashentry _EGLHashentry;
-
-struct _egl_hashentry
-{
- EGLuint Key; /**< the entry's key */
- void *Data; /**< the entry's data */
- _EGLHashentry *Next; /**< pointer to next entry */
-};
-
-
-struct _egl_hashtable
-{
- _EGLHashentry *Table[TABLE_SIZE]; /**< the lookup table */
- EGLuint MaxKey; /**< highest key inserted so far */
- _EGLMutex Mutex; /**< mutual exclusion lock */
-};
-
-
-/**
- * Create a new hash table.
- *
- * \return pointer to a new, empty hash table.
- */
-_EGLHashtable *
-_eglNewHashTable(void)
-{
- _EGLHashtable *table = (_EGLHashtable *) calloc(1, sizeof(_EGLHashtable));
- if (table) {
- _eglInitMutex(table->Mutex);
- table->MaxKey = 1;
- }
- return table;
-}
-
-
-
-/**
- * Delete a hash table.
- * Frees each entry on the hash table and then the hash table structure itself.
- * Note that the caller should have already traversed the table and deleted
- * the objects in the table (i.e. We don't free the entries' data pointer).
- *
- * \param table the hash table to delete.
- */
-void
-_eglDeleteHashTable(_EGLHashtable *table)
-{
- EGLuint i;
- assert(table);
- for (i = 0; i < TABLE_SIZE; i++) {
- _EGLHashentry *entry = table->Table[i];
- while (entry) {
- _EGLHashentry *next = entry->Next;
- free(entry);
- entry = next;
- }
- }
- _eglDestroyMutex(table->Mutex);
- free(table);
-}
-
-
-
-/**
- * Lookup an entry in the hash table.
- *
- * \param table the hash table.
- * \param key the key.
- *
- * \return pointer to user's data or NULL if key not in table
- */
-void *
-_eglHashLookup(const _EGLHashtable *table, EGLuint key)
-{
- EGLuint pos;
- const _EGLHashentry *entry;
-
- assert(table);
-
- if (!key)
- return NULL;
-
- pos = HASH_FUNC(key);
- entry = table->Table[pos];
- while (entry) {
- if (entry->Key == key) {
- return entry->Data;
- }
- entry = entry->Next;
- }
- return NULL;
-}
-
-
-
-/**
- * Insert a key/pointer pair into the hash table.
- * If an entry with this key already exists we'll replace the existing entry.
- *
- * \param table the hash table.
- * \param key the key (not zero).
- * \param data pointer to user data.
- */
-void
-_eglHashInsert(_EGLHashtable *table, EGLuint key, void *data)
-{
- /* search for existing entry with this key */
- EGLuint pos;
- _EGLHashentry *entry;
-
- assert(table);
- assert(key);
-
- _eglLockMutex(table->Mutex);
-
- if (key > table->MaxKey)
- table->MaxKey = key;
-
- pos = HASH_FUNC(key);
- entry = table->Table[pos];
- while (entry) {
- if (entry->Key == key) {
- /* replace entry's data */
- entry->Data = data;
- _eglUnlockMutex(table->Mutex);
- return;
- }
- entry = entry->Next;
- }
-
- /* alloc and insert new table entry */
- entry = (_EGLHashentry *) malloc(sizeof(_EGLHashentry));
- entry->Key = key;
- entry->Data = data;
- entry->Next = table->Table[pos];
- table->Table[pos] = entry;
-
- _eglUnlockMutex(table->Mutex);
-}
-
-
-
-/**
- * Remove an entry from the hash table.
- *
- * \param table the hash table.
- * \param key key of entry to remove.
- *
- * While holding the hash table's lock, searches the entry with the matching
- * key and unlinks it.
- */
-void
-_eglHashRemove(_EGLHashtable *table, EGLuint key)
-{
- EGLuint pos;
- _EGLHashentry *entry, *prev;
-
- assert(table);
- assert(key);
-
- _eglLockMutex(table->Mutex);
-
- pos = HASH_FUNC(key);
- prev = NULL;
- entry = table->Table[pos];
- while (entry) {
- if (entry->Key == key) {
- /* found it! */
- if (prev) {
- prev->Next = entry->Next;
- }
- else {
- table->Table[pos] = entry->Next;
- }
- free(entry);
- _eglUnlockMutex(table->Mutex);
- return;
- }
- prev = entry;
- entry = entry->Next;
- }
-
- _eglUnlockMutex(table->Mutex);
-}
-
-
-
-/**
- * Get the key of the "first" entry in the hash table.
- *
- * This is used in the course of deleting all display lists when
- * a context is destroyed.
- *
- * \param table the hash table
- *
- * \return key for the "first" entry in the hash table.
- *
- * While holding the lock, walks through all table positions until finding
- * the first entry of the first non-empty one.
- */
-EGLuint
-_eglHashFirstEntry(_EGLHashtable *table)
-{
- EGLuint pos;
- assert(table);
- _eglLockMutex(table->Mutex);
- for (pos = 0; pos < TABLE_SIZE; pos++) {
- if (table->Table[pos]) {
- _eglUnlockMutex(table->Mutex);
- return table->Table[pos]->Key;
- }
- }
- _eglUnlockMutex(table->Mutex);
- return 0;
-}
-
-
-/**
- * Given a hash table key, return the next key. This is used to walk
- * over all entries in the table. Note that the keys returned during
- * walking won't be in any particular order.
- * \return next hash key or 0 if end of table.
- */
-EGLuint
-_eglHashNextEntry(const _EGLHashtable *table, EGLuint key)
-{
- const _EGLHashentry *entry;
- EGLuint pos;
-
- assert(table);
- assert(key);
-
- /* Find the entry with given key */
- pos = HASH_FUNC(key);
- entry = table->Table[pos];
- while (entry) {
- if (entry->Key == key) {
- break;
- }
- entry = entry->Next;
- }
-
- if (!entry) {
- /* the key was not found, we can't find next entry */
- return 0;
- }
-
- if (entry->Next) {
- /* return next in linked list */
- return entry->Next->Key;
- }
- else {
- /* look for next non-empty table slot */
- pos++;
- while (pos < TABLE_SIZE) {
- if (table->Table[pos]) {
- return table->Table[pos]->Key;
- }
- pos++;
- }
- return 0;
- }
-}
-
-
-/**
- * Dump contents of hash table for debugging.
- *
- * \param table the hash table.
- */
-void
-_eglHashPrint(const _EGLHashtable *table)
-{
- EGLuint i;
- assert(table);
- for (i = 0; i < TABLE_SIZE; i++) {
- const _EGLHashentry *entry = table->Table[i];
- while (entry) {
- printf("%u %p\n", entry->Key, entry->Data);
- entry = entry->Next;
- }
- }
-}
-
-
-
-/**
- * Return a new, unused hash key.
- */
-EGLuint
-_eglHashGenKey(_EGLHashtable *table)
-{
- EGLuint k;
-
- _eglLockMutex(table->Mutex);
- k = table->MaxKey;
- table->MaxKey++;
- _eglUnlockMutex(table->Mutex);
- return k;
-}
-
diff --git a/src/egl/main/eglhash.h b/src/egl/main/eglhash.h
deleted file mode 100644
index 1d6db9598c..0000000000
--- a/src/egl/main/eglhash.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * \file eglhash.h
- * Generic hash table.
- */
-
-
-#ifndef EGLHASH_INCLUDED
-#define EGLHASH_INCLUDED
-
-
-/* XXX move this? */
-typedef unsigned int EGLuint;
-
-
-typedef struct _egl_hashtable _EGLHashtable;
-
-
-extern _EGLHashtable *_eglNewHashTable(void);
-
-extern void _eglDeleteHashTable(_EGLHashtable *table);
-
-extern void *_eglHashLookup(const _EGLHashtable *table, EGLuint key);
-
-extern void _eglHashInsert(_EGLHashtable *table, EGLuint key, void *data);
-
-extern void _eglHashRemove(_EGLHashtable *table, EGLuint key);
-
-extern EGLuint _eglHashFirstEntry(_EGLHashtable *table);
-
-extern EGLuint _eglHashNextEntry(const _EGLHashtable *table, EGLuint key);
-
-extern void _eglHashPrint(const _EGLHashtable *table);
-
-extern EGLuint _eglHashGenKey(_EGLHashtable *table);
-
-extern void _egltest_hash_functions(void);
-
-
-#endif /* EGLHASH_INCLUDED */
diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c
new file mode 100644
index 0000000000..dc1c728320
--- /dev/null
+++ b/src/egl/main/eglimage.c
@@ -0,0 +1,104 @@
+#include <assert.h>
+
+#include "eglimage.h"
+#include "egldisplay.h"
+
+EGLBoolean
+_eglInitImage(_EGLDriver *drv, _EGLImage *img, const EGLint *attrib_list)
+{
+ EGLint i;
+
+ img->Preserved = EGL_FALSE;
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ case EGL_IMAGE_PRESERVED_KHR:
+ i++;
+ img->Preserved = attrib_list[i];
+ break;
+ default:
+ /* not an error */
+ break;
+ }
+ }
+
+ return EGL_TRUE;
+}
+
+
+_EGLImage *
+_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
+ EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
+{
+ /* driver should override this function */
+ return NULL;
+}
+
+
+EGLBoolean
+_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image)
+{
+ /* driver should override this function */
+ return EGL_FALSE;
+}
+
+
+EGLImageKHR
+_eglLinkImage(_EGLImage *img, _EGLDisplay *dpy)
+{
+ img->Display = dpy;
+ img->Next = dpy->ImageList;
+ dpy->ImageList = img;
+ return (EGLImageKHR) img;
+}
+
+
+void
+_eglUnlinkImage(_EGLImage *img)
+{
+ _EGLImage *prev;
+
+ prev = img->Display->ImageList;
+ if (prev != img) {
+ while (prev) {
+ if (prev->Next == img)
+ break;
+ prev = prev->Next;
+ }
+ assert(prev);
+ prev->Next = img->Next;
+ }
+ else {
+ img->Display->ImageList = img->Next;
+ }
+
+ img->Next = NULL;
+ img->Display = NULL;
+}
+
+
+#ifndef _EGL_SKIP_HANDLE_CHECK
+
+
+/**
+ * Return EGL_TRUE if the given handle is a valid handle to an image.
+ */
+EGLBoolean
+_eglCheckImageHandle(EGLImageKHR img, _EGLDisplay *dpy)
+{
+ _EGLImage *cur = NULL;
+
+ if (dpy)
+ cur = dpy->ImageList;
+ while (cur) {
+ if (cur == (_EGLImage *) img) {
+ assert(cur->Display == dpy);
+ break;
+ }
+ cur = cur->Next;
+ }
+ return (cur != NULL);
+}
+
+
+#endif /* _EGL_SKIP_HANDLE_CHECK */
diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h
new file mode 100644
index 0000000000..3a96028e3d
--- /dev/null
+++ b/src/egl/main/eglimage.h
@@ -0,0 +1,93 @@
+#ifndef EGLIMAGE_INCLUDED
+#define EGLIMAGE_INCLUDED
+
+
+#include "egltypedefs.h"
+
+
+/**
+ * "Base" class for device driver images.
+ */
+struct _egl_image
+{
+ /* Client data that client APIs and the driver agree on */
+ void *ClientData;
+
+ /* Managed by EGLDisplay for linking */
+ _EGLDisplay *Display;
+ _EGLImage *Next;
+
+ EGLBoolean Preserved;
+};
+
+
+extern EGLBoolean
+_eglInitImage(_EGLDriver *drv, _EGLImage *img, const EGLint *attrib_list);
+
+
+extern _EGLImage *
+_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
+ EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list);
+
+
+extern EGLBoolean
+_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
+
+
+extern EGLImageKHR
+_eglLinkImage(_EGLImage *img, _EGLDisplay *dpy);
+
+
+extern void
+_eglUnlinkImage(_EGLImage *img);
+
+
+#ifndef _EGL_SKIP_HANDLE_CHECK
+
+
+extern EGLBoolean
+_eglCheckImageHandle(EGLImageKHR img, _EGLDisplay *dpy);
+
+
+#else
+
+
+/**
+ * Perform a quick check on the handle.
+ */
+static INLINE EGLBoolean
+_eglCheckImageHandle(EGLImageKHR img, _EGLDisplay *dpy)
+{
+ _EGLImage *i = (_EGLImage *) img;
+ return (dpy && i && i->Display == dpy);
+}
+
+
+#endif
+
+
+/**
+ * Lookup a handle to find the linked image.
+ * Return NULL if the handle has no corresponding linked image.
+ */
+static INLINE _EGLImage *
+_eglLookupImage(EGLImageKHR image, _EGLDisplay *dpy)
+{
+ _EGLImage *img = (_EGLImage *) image;
+ if (!_eglCheckImageHandle(img, dpy))
+ img = NULL;
+ return img;
+}
+
+
+/**
+ * Return the handle of a linked image.
+ */
+static INLINE EGLImageKHR
+_eglGetImageHandle(_EGLImage *img)
+{
+ return (EGLImageKHR) ((img && img->Display) ? img : EGL_NO_IMAGE_KHR);
+}
+
+
+#endif /* EGLIMAGE_INCLUDED */
diff --git a/src/egl/main/egllog.c b/src/egl/main/egllog.c
index dc1daaa996..1d7a0a388c 100644
--- a/src/egl/main/egllog.c
+++ b/src/egl/main/egllog.c
@@ -1,5 +1,7 @@
/**
* Logging facility for debug/info messages.
+ * _EGL_FATAL messages are printed to stderr
+ * The EGL_LOG_LEVEL var controls the output of other warning/info/debug msgs.
*/
@@ -10,37 +12,41 @@
#include "egllog.h"
#define MAXSTRING 1000
-#define FALLBACK_LOG_LEVEL _EGL_DEBUG
-#define FALLBACK_LOG_LEVEL_STR "debug"
+#define FALLBACK_LOG_LEVEL _EGL_WARNING
+#define FALLBACK_LOG_LEVEL_STR "warning"
static EGLint ReportingLevel = -1;
static void
-log_level_initialize (void)
+log_level_initialize(void)
{
- char *log_env = getenv ("EGL_LOG_LEVEL");
+#if defined(_EGL_PLATFORM_X)
+ char *log_env = getenv("EGL_LOG_LEVEL");
+#else
+ char *log_env = NULL;
+#endif
if (log_env == NULL) {
ReportingLevel = FALLBACK_LOG_LEVEL;
}
- else if (strcasecmp (log_env, "fatal") == 0) {
+ else if (strcasecmp(log_env, "fatal") == 0) {
ReportingLevel = _EGL_FATAL;
}
- else if (strcasecmp (log_env, "warning") == 0) {
+ else if (strcasecmp(log_env, "warning") == 0) {
ReportingLevel = _EGL_WARNING;
}
- else if (strcasecmp (log_env, "info") == 0) {
+ else if (strcasecmp(log_env, "info") == 0) {
ReportingLevel = _EGL_INFO;
}
- else if (strcasecmp (log_env, "debug") == 0) {
+ else if (strcasecmp(log_env, "debug") == 0) {
ReportingLevel = _EGL_DEBUG;
}
else {
- fprintf (stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. "
- "Expected one of \"fatal\", \"warning\", \"info\", \"debug\". "
- "Got \"%s\". Falling back to \"%s\".\n",
- log_env, FALLBACK_LOG_LEVEL_STR);
+ fprintf(stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. "
+ "Expected one of \"fatal\", \"warning\", \"info\", \"debug\". "
+ "Got \"%s\". Falling back to \"%s\".\n",
+ log_env, FALLBACK_LOG_LEVEL_STR);
ReportingLevel = FALLBACK_LOG_LEVEL;
}
}
@@ -59,7 +65,7 @@ _eglLog(EGLint level, const char *fmtStr, ...)
static int log_level_initialized = 0;
if (!log_level_initialized) {
- log_level_initialize ();
+ log_level_initialize();
log_level_initialized = 1;
}
@@ -85,7 +91,7 @@ _eglLog(EGLint level, const char *fmtStr, ...)
vsnprintf(msg, MAXSTRING, fmtStr, args);
va_end(args);
- fprintf(stderr, "EGL %s: %s\n", levelStr, msg);
+ fprintf(stderr, "libEGL %s: %s\n", levelStr, msg);
if (level == _EGL_FATAL) {
exit(1); /* or abort()? */
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
new file mode 100644
index 0000000000..f40321b1df
--- /dev/null
+++ b/src/egl/main/eglmisc.c
@@ -0,0 +1,141 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Small/misc EGL functions
+ */
+
+
+#include <assert.h>
+#include <string.h>
+#include "eglglobals.h"
+#include "eglmisc.h"
+#include "egldisplay.h"
+
+
+/**
+ * Examine the individual extension enable/disable flags and recompute
+ * the driver's Extensions string.
+ */
+static void
+_eglUpdateExtensionsString(_EGLDisplay *dpy)
+{
+ char *exts = dpy->Extensions.String;
+
+ if (exts[0])
+ return;
+
+ if (dpy->Extensions.MESA_screen_surface)
+ strcat(exts, "EGL_MESA_screen_surface ");
+ if (dpy->Extensions.MESA_copy_context)
+ strcat(exts, "EGL_MESA_copy_context ");
+ if (dpy->Extensions.KHR_image)
+ strcat(exts, "EGL_KHR_image ");
+ if (dpy->Extensions.KHR_image_base)
+ strcat(exts, "EGL_KHR_image_base ");
+ if (dpy->Extensions.KHR_image_pixmap)
+ strcat(exts, "EGL_KHR_image_pixmap ");
+ assert(strlen(exts) < _EGL_MAX_EXTENSIONS_LEN);
+}
+
+
+static void
+_eglUpdateAPIsString(_EGLDisplay *dpy)
+{
+ char *apis = dpy->ClientAPIs;
+
+ if (apis[0] || !dpy->ClientAPIsMask)
+ return;
+
+ if (dpy->ClientAPIsMask & EGL_OPENGL_BIT)
+ strcat(apis, "OpenGL ");
+
+ if (dpy->ClientAPIsMask & EGL_OPENGL_ES_BIT)
+ strcat(apis, "OpenGL_ES ");
+
+ if (dpy->ClientAPIsMask & EGL_OPENGL_ES2_BIT)
+ strcat(apis, "OpenGL_ES2 ");
+
+ if (dpy->ClientAPIsMask & EGL_OPENVG_BIT)
+ strcat(apis, "OpenVG ");
+
+ assert(strlen(apis) < sizeof(dpy->ClientAPIs));
+}
+
+
+const char *
+_eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name)
+{
+ (void) drv;
+ (void) dpy;
+ switch (name) {
+ case EGL_VENDOR:
+ return _EGL_VENDOR_STRING;
+ case EGL_VERSION:
+ return dpy->Version;
+ case EGL_EXTENSIONS:
+ _eglUpdateExtensionsString(dpy);
+ return dpy->Extensions.String;
+#ifdef EGL_VERSION_1_2
+ case EGL_CLIENT_APIS:
+ _eglUpdateAPIsString(dpy);
+ return dpy->ClientAPIs;
+#endif
+ default:
+ _eglError(EGL_BAD_PARAMETER, "eglQueryString");
+ return NULL;
+ }
+}
+
+
+EGLBoolean
+_eglWaitGL(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ /* just a placeholder */
+ (void) drv;
+ (void) dpy;
+ return EGL_TRUE;
+}
+
+
+EGLBoolean
+_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
+{
+ /* just a placeholder */
+ (void) drv;
+ (void) dpy;
+ switch (engine) {
+ case EGL_CORE_NATIVE_ENGINE:
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)");
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
diff --git a/src/egl/main/eglmisc.h b/src/egl/main/eglmisc.h
new file mode 100644
index 0000000000..a15c839be2
--- /dev/null
+++ b/src/egl/main/eglmisc.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef EGLMISC_INCLUDED
+#define EGLMISC_INCLUDED
+
+#include "egldriver.h"
+
+
+extern const char *
+_eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name);
+
+
+extern EGLBoolean
+_eglWaitGL(_EGLDriver *drv, _EGLDisplay *dpy);
+
+
+extern EGLBoolean
+_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine);
+
+
+#endif /* EGLMISC_INCLUDED */
diff --git a/src/egl/main/eglmode.c b/src/egl/main/eglmode.c
index 786432234b..0f3ba6e5c0 100644
--- a/src/egl/main/eglmode.c
+++ b/src/egl/main/eglmode.c
@@ -34,9 +34,8 @@ my_strdup(const char *s)
* or null if non-existant.
*/
_EGLMode *
-_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode)
+_eglLookupMode(EGLModeMESA mode, _EGLDisplay *disp)
{
- const _EGLDisplay *disp = _eglLookupDisplay(dpy);
EGLint scrnum;
/* loop over all screens on the display */
@@ -272,19 +271,13 @@ _eglCompareModes(const void *a, const void *b)
* Called via eglChooseModeMESA API function.
*/
EGLBoolean
-_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+_eglChooseModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
const EGLint *attrib_list, EGLModeMESA *modes,
EGLint modes_size, EGLint *num_modes)
{
- const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
_EGLMode **modeList, min;
EGLint i, count;
- if (!scrn) {
- _eglError(EGL_BAD_SCREEN_MESA, "eglChooseModeMESA");
- return EGL_FALSE;
- }
-
if (!_eglParseModeAttribs(&min, attrib_list)) {
/* error code will have been recorded */
return EGL_FALSE;
@@ -326,16 +319,9 @@ _eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
* Called via eglGetModesMESA() API function.
*/
EGLBoolean
-_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+_eglGetModesMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes)
{
- _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
-
- if (!scrn) {
- _eglError(EGL_BAD_SCREEN_MESA, "eglGetModesMESA");
- return EGL_FALSE;
- }
-
if (modes) {
EGLint i;
*num_modes = MIN2(scrn->NumModes, modes_size);
@@ -356,17 +342,11 @@ _eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
* Query an attribute of a mode.
*/
EGLBoolean
-_eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy,
- EGLModeMESA mode, EGLint attribute, EGLint *value)
+_eglGetModeAttribMESA(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLMode *m, EGLint attribute, EGLint *value)
{
- _EGLMode *m = _eglLookupMode(dpy, mode);
EGLint v;
- if (!m) {
- _eglError(EGL_BAD_MODE_MESA, "eglGetModeAttribMESA");
- return EGL_FALSE;
- }
-
v = getModeAttrib(m, attribute);
if (v < 0) {
_eglError(EGL_BAD_ATTRIBUTE, "eglGetModeAttribMESA");
@@ -382,13 +362,8 @@ _eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy,
* This is the default function called by eglQueryModeStringMESA().
*/
const char *
-_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode)
+_eglQueryModeStringMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *m)
{
- _EGLMode *m = _eglLookupMode(dpy, mode);
- if (!m) {
- _eglError(EGL_BAD_MODE_MESA, "eglQueryModeStringMESA");
- return NULL;
- }
return m->Name;
}
diff --git a/src/egl/main/eglmode.h b/src/egl/main/eglmode.h
index e70da85759..af7c2c56d3 100644
--- a/src/egl/main/eglmode.h
+++ b/src/egl/main/eglmode.h
@@ -4,6 +4,9 @@
#include "egltypedefs.h"
+#define EGL_NO_MODE_MESA 0
+
+
/**
* Data structure which corresponds to an EGLModeMESA.
*/
@@ -23,7 +26,7 @@ struct _egl_mode
extern _EGLMode *
-_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode);
+_eglLookupMode(EGLModeMESA mode, _EGLDisplay *dpy);
extern _EGLMode *
@@ -32,23 +35,23 @@ _eglAddNewMode(_EGLScreen *screen, EGLint width, EGLint height,
extern EGLBoolean
-_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+_eglChooseModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
const EGLint *attrib_list, EGLModeMESA *modes,
EGLint modes_size, EGLint *num_modes);
extern EGLBoolean
-_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+_eglGetModesMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
extern EGLBoolean
-_eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode,
+_eglGetModeAttribMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *m,
EGLint attribute, EGLint *value);
extern const char *
-_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode);
+_eglQueryModeStringMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *m);
#endif /* EGLMODE_INCLUDED */
diff --git a/src/egl/main/eglmutex.h b/src/egl/main/eglmutex.h
new file mode 100644
index 0000000000..29faba0f24
--- /dev/null
+++ b/src/egl/main/eglmutex.h
@@ -0,0 +1,52 @@
+#ifndef EGLMUTEX_INCLUDED
+#define EGLMUTEX_INCLUDED
+
+#include "eglcompiler.h"
+
+#ifdef PTHREADS
+#include <pthread.h>
+
+typedef pthread_mutex_t _EGLMutex;
+
+static INLINE void _eglInitMutex(_EGLMutex *m)
+{
+ pthread_mutex_init(m, NULL);
+}
+
+static INLINE void
+_eglDestroyMutex(_EGLMutex *m)
+{
+ pthread_mutex_destroy(m);
+}
+
+static INLINE void
+_eglLockMutex(_EGLMutex *m)
+{
+ pthread_mutex_lock(m);
+}
+
+static INLINE void
+_eglUnlockMutex(_EGLMutex *m)
+{
+ pthread_mutex_unlock(m);
+}
+
+#define _EGL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define _EGL_DECLARE_MUTEX(m) \
+ _EGLMutex m = _EGL_MUTEX_INITIALIZER
+
+#else
+
+typedef int _EGLMutex;
+static INLINE void _eglInitMutex(_EGLMutex *m) { (void) m; }
+static INLINE void _eglDestroyMutex(_EGLMutex *m) { (void) m; }
+static INLINE void _eglLockMutex(_EGLMutex *m) { (void) m; }
+static INLINE void _eglUnlockMutex(_EGLMutex *m) { (void) m; }
+
+#define _EGL_MUTEX_INITIALIZER 0
+#define _EGL_DECLARE_MUTEX(m) \
+ _EGLMutex m = _EGL_MUTEX_INITIALIZER
+
+#endif
+
+#endif /* EGLMUTEX_INCLUDED */
diff --git a/src/egl/main/eglscreen.c b/src/egl/main/eglscreen.c
index 9c9a8377bf..14a1e9f8fe 100644
--- a/src/egl/main/eglscreen.c
+++ b/src/egl/main/eglscreen.c
@@ -52,13 +52,9 @@ _eglInitScreen(_EGLScreen *screen)
* Given a public screen handle, return the internal _EGLScreen object.
*/
_EGLScreen *
-_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen)
+_eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display)
{
EGLint i;
- _EGLDisplay *display = _eglLookupDisplay(dpy);
-
- if (!display)
- return NULL;
for (i = 0; i < display->NumScreens; i++) {
if (display->Screens[i]->Handle == screen)
@@ -89,17 +85,11 @@ _eglAddScreen(_EGLDisplay *display, _EGLScreen *screen)
EGLBoolean
-_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens,
+_eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens,
EGLint max_screens, EGLint *num_screens)
{
- _EGLDisplay *display = _eglLookupDisplay(dpy);
EGLint n;
- if (!display) {
- _eglError(EGL_BAD_DISPLAY, "eglGetScreensMESA");
- return EGL_FALSE;
- }
-
if (display->NumScreens > max_screens) {
n = max_screens;
}
@@ -122,8 +112,8 @@ _eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens,
/**
* Example function - drivers should do a proper implementation.
*/
-EGLSurface
-_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+_EGLSurface *
+_eglCreateScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
const EGLint *attrib_list)
{
#if 0 /* THIS IS JUST EXAMPLE CODE */
@@ -131,19 +121,17 @@ _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
if (!surf)
- return EGL_NO_SURFACE;
+ return NULL;
- if (!_eglInitSurface(drv, dpy, surf, EGL_SCREEN_BIT_MESA,
- config, attrib_list)) {
+ if (!_eglInitSurface(drv, surf, EGL_SCREEN_BIT_MESA,
+ conf, attrib_list)) {
free(surf);
- return EGL_NO_SURFACE;
+ return NULL;
}
- _eglSaveSurface(surf);
-
- return surf->Handle;
+ return surf;
#endif
- return EGL_NO_SURFACE;
+ return NULL;
}
@@ -155,28 +143,15 @@ _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
* this with code that _really_ shows the surface.
*/
EGLBoolean
-_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
- EGLScreenMESA screen, EGLSurface surface,
- EGLModeMESA m)
+_eglShowScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLScreen *scrn, _EGLSurface *surf,
+ _EGLMode *mode)
{
- _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
- _EGLMode *mode = _eglLookupMode(dpy, m);
-
- if (!scrn) {
- _eglError(EGL_BAD_SCREEN_MESA, "eglShowSurfaceMESA");
- return EGL_FALSE;
- }
- if (!mode && (m != EGL_NO_MODE_MESA )) {
- _eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA");
- return EGL_FALSE;
- }
-
- if (surface == EGL_NO_SURFACE) {
+ if (!surf) {
scrn->CurrentSurface = NULL;
}
else {
- _EGLSurface *surf = _eglLookupSurface(surface);
- if (!surf || surf->Type != EGL_SCREEN_BIT_MESA) {
+ if (surf->Type != EGL_SCREEN_BIT_MESA) {
_eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA");
return EGL_FALSE;
}
@@ -201,18 +176,10 @@ _eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
* this with code that _really_ sets the mode.
*/
EGLBoolean
-_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
- EGLModeMESA mode)
+_eglScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
+ _EGLMode *m)
{
- _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
-
- if (!scrn) {
- _eglError(EGL_BAD_SCREEN_MESA, "eglScreenModeMESA");
- return EGL_FALSE;
- }
-
- scrn->CurrentMode = _eglLookupMode(dpy, mode);
-
+ scrn->CurrentMode = m;
return EGL_TRUE;
}
@@ -221,15 +188,9 @@ _eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
* Set a screen's surface origin.
*/
EGLBoolean
-_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy,
- EGLScreenMESA screen, EGLint x, EGLint y)
+_eglScreenPositionMESA(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLScreen *scrn, EGLint x, EGLint y)
{
- _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
- if (!scrn) {
- _eglError(EGL_BAD_SCREEN_MESA, "eglScreenPositionMESA");
- return EGL_FALSE;
- }
-
scrn->OriginX = x;
scrn->OriginY = y;
@@ -241,14 +202,10 @@ _eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy,
* Query a screen's current surface.
*/
EGLBoolean
-_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
- EGLScreenMESA screen, EGLSurface *surface)
+_eglQueryScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLScreen *scrn, _EGLSurface **surf)
{
- const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
- if (scrn->CurrentSurface)
- *surface = scrn->CurrentSurface->Handle;
- else
- *surface = EGL_NO_SURFACE;
+ *surf = scrn->CurrentSurface;
return EGL_TRUE;
}
@@ -257,29 +214,18 @@ _eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
* Query a screen's current mode.
*/
EGLBoolean
-_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
- EGLModeMESA *mode)
+_eglQueryScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
+ _EGLMode **m)
{
- const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
- if (scrn->CurrentMode)
- *mode = scrn->CurrentMode->Handle;
- else
- *mode = EGL_NO_MODE_MESA;
+ *m = scrn->CurrentMode;
return EGL_TRUE;
}
EGLBoolean
-_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+_eglQueryScreenMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn,
EGLint attribute, EGLint *value)
{
- const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
-
- if (!scrn) {
- _eglError(EGL_BAD_SCREEN_MESA, "eglQueryScreenMESA");
- return EGL_FALSE;
- }
-
switch (attribute) {
case EGL_SCREEN_POSITION_MESA:
value[0] = scrn->OriginX;
diff --git a/src/egl/main/eglscreen.h b/src/egl/main/eglscreen.h
index 833439b410..8860a2aa7f 100644
--- a/src/egl/main/eglscreen.h
+++ b/src/egl/main/eglscreen.h
@@ -35,7 +35,7 @@ _eglInitScreen(_EGLScreen *screen);
extern _EGLScreen *
-_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen);
+_eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *dpy);
extern void
@@ -43,40 +43,40 @@ _eglAddScreen(_EGLDisplay *display, _EGLScreen *screen);
extern EGLBoolean
-_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
+_eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
-extern EGLSurface
-_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+extern _EGLSurface *
+_eglCreateScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list);
extern EGLBoolean
-_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode);
+_eglShowScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, _EGLSurface *surf, _EGLMode *m);
extern EGLBoolean
-_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA mode);
+_eglScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, _EGLMode *m);
extern EGLBoolean
-_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
+_eglScreenPositionMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, EGLint x, EGLint y);
extern EGLBoolean
-_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attribute, EGLint *value);
+_eglQueryDisplayMESA(_EGLDriver *drv, _EGLDisplay *dpy, EGLint attribute, EGLint *value);
extern EGLBoolean
-_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
- EGLScreenMESA screen, EGLSurface *surface);
+_eglQueryScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLScreen *scrn, _EGLSurface **surface);
extern EGLBoolean
-_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
+_eglQueryScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, _EGLMode **m);
extern EGLBoolean
-_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
+_eglQueryScreenMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, EGLint attribute, EGLint *value);
extern void
diff --git a/src/egl/main/eglstring.c b/src/egl/main/eglstring.c
new file mode 100644
index 0000000000..ba7406158c
--- /dev/null
+++ b/src/egl/main/eglstring.c
@@ -0,0 +1,24 @@
+/**
+ * String utils.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "eglstring.h"
+
+
+char *
+_eglstrdup(const char *s)
+{
+ if (s) {
+ int l = strlen(s);
+ char *s2 = malloc(l + 1);
+ if (s2)
+ strcpy(s2, s);
+ return s2;
+ }
+ return NULL;
+}
+
+
+
diff --git a/src/egl/main/eglstring.h b/src/egl/main/eglstring.h
new file mode 100644
index 0000000000..10468636e8
--- /dev/null
+++ b/src/egl/main/eglstring.h
@@ -0,0 +1,9 @@
+#ifndef EGLSTRING_INCLUDED
+#define EGLSTRING_INCLUDED
+
+
+extern char *
+_eglstrdup(const char *s);
+
+
+#endif /* EGLSTRING_INCLUDED */
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index 874f318e96..e7a1a8329e 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -6,10 +6,11 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include "egldisplay.h"
#include "eglcontext.h"
#include "eglconfig.h"
+#include "egldriver.h"
#include "eglglobals.h"
-#include "eglhash.h"
#include "egllog.h"
#include "eglsurface.h"
@@ -19,14 +20,13 @@
* \return EGL_TRUE if no errors, EGL_FALSE otherwise.
*/
EGLBoolean
-_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
- _EGLSurface *surf, EGLint type, EGLConfig config,
- const EGLint *attrib_list)
+_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type,
+ _EGLConfig *conf, const EGLint *attrib_list)
{
const char *func;
- _EGLConfig *conf;
EGLint width = 0, height = 0, largest = 0;
- EGLint texFormat = 0, texTarget = 0, mipmapTex = 0;
+ EGLint texFormat = EGL_NO_TEXTURE, texTarget = EGL_NO_TEXTURE;
+ EGLint mipmapTex = EGL_FALSE;
EGLint renderBuffer = EGL_BACK_BUFFER;
#ifdef EGL_VERSION_1_2
EGLint colorspace = EGL_COLORSPACE_sRGB;
@@ -54,12 +54,17 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
return EGL_FALSE;
}
- conf = _eglLookupConfig(drv, dpy, config);
if (!conf) {
_eglError(EGL_BAD_CONFIG, func);
return EGL_FALSE;
}
+ if ((GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) & type) == 0) {
+ /* The config can't be used to create a surface of this type */
+ _eglError(EGL_BAD_CONFIG, func);
+ return EGL_FALSE;
+ }
+
/*
* Parse attribute list. Different kinds of surfaces support different
* attributes.
@@ -175,7 +180,7 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
}
}
- if (width <= 0 || height <= 0) {
+ if (width < 0 || height < 0) {
_eglError(EGL_BAD_ATTRIBUTE, func);
return EGL_FALSE;
}
@@ -204,72 +209,16 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
}
-void
-_eglSaveSurface(_EGLSurface *surf)
-{
- assert(surf);
- assert(!surf->Handle);
- surf->Handle = _eglHashGenKey(_eglGlobal.Contexts);
- assert(surf->Handle);
- _eglHashInsert(_eglGlobal.Surfaces, surf->Handle, surf);
-}
-
-
-void
-_eglRemoveSurface(_EGLSurface *surf)
-{
- _eglHashRemove(_eglGlobal.Surfaces, surf->Handle);
-}
-
-
-_EGLSurface *
-_eglLookupSurface(EGLSurface surf)
-{
- _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, surf);
- return c;
-}
-
-
-_EGLSurface *
-_eglGetCurrentSurface(EGLint readdraw)
-{
- _EGLContext *ctx = _eglGetCurrentContext();
- if (ctx) {
- switch (readdraw) {
- case EGL_DRAW:
- return ctx->DrawSurface;
- case EGL_READ:
- return ctx->ReadSurface;
- default:
- return NULL;
- }
- }
- return NULL;
-}
-
-
EGLBoolean
-_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
+_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
{
- /* Basically just do error checking here. Drivers have to do the
- * actual buffer swap.
- */
- _EGLContext *context = _eglGetCurrentContext();
- _EGLSurface *surface = _eglLookupSurface(draw);
- if (context && context->DrawSurface != surface) {
- _eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
- return EGL_FALSE;
- }
- if (surface == NULL) {
- _eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
- return EGL_FALSE;
- }
+ /* Drivers have to do the actual buffer swap. */
return EGL_TRUE;
}
EGLBoolean
-_eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
+_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
NativePixmapType target)
{
/* copy surface to native pixmap */
@@ -279,14 +228,9 @@ _eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
EGLBoolean
-_eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
+_eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
EGLint attribute, EGLint *value)
{
- _EGLSurface *surface = _eglLookupSurface(surf);
- if (surface == NULL) {
- _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
- return EGL_FALSE;
- }
switch (attribute) {
case EGL_WIDTH:
*value = surface->Width;
@@ -297,7 +241,9 @@ _eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
case EGL_CONFIG_ID:
*value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID);
return EGL_TRUE;
- /*XXX case EGL_LARGEST_PBUFFER:*/
+ case EGL_LARGEST_PBUFFER:
+ *value = dpy->LargestPbuffer;
+ return EGL_TRUE;
case EGL_SURFACE_TYPE:
*value = surface->Type;
return EGL_TRUE;
@@ -353,8 +299,8 @@ _eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
/**
* Example function - drivers should do a proper implementation.
*/
-EGLSurface
-_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+_EGLSurface *
+_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
NativeWindowType window, const EGLint *attrib_list)
{
#if 0 /* THIS IS JUST EXAMPLE CODE */
@@ -362,26 +308,24 @@ _eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
if (!surf)
- return EGL_NO_SURFACE;
+ return NULL;
- if (!_eglInitSurface(drv, dpy, surf, EGL_WINDOW_BIT, config, attrib_list)) {
+ if (!_eglInitSurface(drv, surf, EGL_WINDOW_BIT, conf, attrib_list)) {
free(surf);
- return EGL_NO_SURFACE;
+ return NULL;
}
- _eglSaveSurface(surf);
-
- return surf->Handle;
+ return surf;
#endif
- return EGL_NO_SURFACE;
+ return NULL;
}
/**
* Example function - drivers should do a proper implementation.
*/
-EGLSurface
-_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+_EGLSurface *
+_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
NativePixmapType pixmap, const EGLint *attrib_list)
{
#if 0 /* THIS IS JUST EXAMPLE CODE */
@@ -389,26 +333,24 @@ _eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
if (!surf)
- return EGL_NO_SURFACE;
+ return NULL;
- if (!_eglInitSurface(drv, dpy, surf, EGL_PIXMAP_BIT, config, attrib_list)) {
+ if (!_eglInitSurface(drv, surf, EGL_PIXMAP_BIT, conf, attrib_list)) {
free(surf);
- return EGL_NO_SURFACE;
+ return NULL;
}
- _eglSaveSurface(surf);
-
- return surf->Handle;
+ return surf;
#endif
- return EGL_NO_SURFACE;
+ return NULL;
}
/**
* Example function - drivers should do a proper implementation.
*/
-EGLSurface
-_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+_EGLSurface *
+_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
const EGLint *attrib_list)
{
#if 0 /* THIS IS JUST EXAMPLE CODE */
@@ -416,18 +358,16 @@ _eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
if (!surf)
- return EGL_NO_SURFACE;
+ return NULL;
- if (!_eglInitSurface(drv, dpy, surf, EGL_PBUFFER_BIT, config, attrib_list)) {
+ if (!_eglInitSurface(drv, surf, EGL_PBUFFER_BIT, conf, attrib_list)) {
free(surf);
- return EGL_NO_SURFACE;
+ return NULL;
}
- _eglSaveSurface(surf);
-
- return surf->Handle;
+ return NULL;
#endif
- return EGL_NO_SURFACE;
+ return NULL;
}
@@ -435,23 +375,11 @@ _eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
* Default fallback routine - drivers should usually override this.
*/
EGLBoolean
-_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
+_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
{
- _EGLSurface *surf = _eglLookupSurface(surface);
- if (surf) {
- _eglHashRemove(_eglGlobal.Surfaces, surface);
- if (surf->IsBound) {
- surf->DeletePending = EGL_TRUE;
- }
- else {
- free(surf);
- }
- return EGL_TRUE;
- }
- else {
- _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
- return EGL_FALSE;
- }
+ if (!_eglIsSurfaceBound(surf))
+ free(surf);
+ return EGL_TRUE;
}
@@ -459,15 +387,9 @@ _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
* Default fallback routine - drivers might override this.
*/
EGLBoolean
-_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attribute, EGLint value)
+_eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
+ EGLint attribute, EGLint value)
{
- _EGLSurface *surface = _eglLookupSurface(surf);
-
- if (surface == NULL) {
- _eglError(EGL_BAD_SURFACE, "eglSurfaceAttrib");
- return EGL_FALSE;
- }
-
switch (attribute) {
case EGL_MIPMAP_LEVEL:
surface->MipmapLevel = value;
@@ -481,30 +403,74 @@ _eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attri
EGLBoolean
-_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
+ EGLint buffer)
{
- /* XXX unfinished */
- return EGL_FALSE;
+ /* Just do basic error checking and return success/fail.
+ * Drivers must implement the real stuff.
+ */
+
+ if (surface->Type != EGL_PBUFFER_BIT) {
+ _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ if (surface->TextureFormat == EGL_NO_TEXTURE) {
+ _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ if (buffer != EGL_BACK_BUFFER) {
+ _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ surface->BoundToTexture = EGL_TRUE;
+
+ return EGL_TRUE;
}
EGLBoolean
-_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
+ EGLint buffer)
{
- /* XXX unfinished */
- return EGL_FALSE;
+ /* Just do basic error checking and return success/fail.
+ * Drivers must implement the real stuff.
+ */
+
+ if (surface->Type != EGL_PBUFFER_BIT) {
+ _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ if (surface->TextureFormat == EGL_NO_TEXTURE) {
+ _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ if (buffer != EGL_BACK_BUFFER) {
+ _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
+ return EGL_FALSE;
+ }
+
+ if (!surface->BoundToTexture) {
+ _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
+ return EGL_FALSE;
+ }
+
+ surface->BoundToTexture = EGL_FALSE;
+
+ return EGL_TRUE;
}
EGLBoolean
-_eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval)
+_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval)
{
_EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
- if (surf == NULL) {
- _eglError(EGL_BAD_SURFACE, "eglSwapInterval");
- return EGL_FALSE;
- }
- surf->SwapInterval = interval;
+ if (surf)
+ surf->SwapInterval = interval;
return EGL_TRUE;
}
@@ -514,17 +480,17 @@ _eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval)
/**
* Example function - drivers should do a proper implementation.
*/
-EGLSurface
-_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy,
+_EGLSurface *
+_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, _EGLDisplay *dpy,
EGLenum buftype, EGLClientBuffer buffer,
- EGLConfig config, const EGLint *attrib_list)
+ _EGLConfig *conf, const EGLint *attrib_list)
{
if (buftype != EGL_OPENVG_IMAGE) {
_eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer");
- return EGL_NO_SURFACE;
+ return NULL;
}
- return EGL_NO_SURFACE;
+ return NULL;
}
#endif /* EGL_VERSION_1_2 */
diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
index 79abeca0b2..f6d44b5922 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -10,12 +10,15 @@
*/
struct _egl_surface
{
- EGLSurface Handle; /* The public/opaque handle which names this object */
- _EGLConfig *Config;
+ /* Managed by EGLDisplay for linking */
+ _EGLDisplay *Display;
+ _EGLSurface *Next;
+
+ /* The bound status of the surface */
+ _EGLContext *Binding;
+ EGLBoolean BoundToTexture;
- /* May need reference counting here */
- EGLBoolean IsBound;
- EGLBoolean DeletePending;
+ _EGLConfig *Config;
EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */
EGLint Width, Height;
@@ -38,80 +41,74 @@ struct _egl_surface
extern EGLBoolean
-_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
- _EGLSurface *surf, EGLint type, EGLConfig config,
- const EGLint *attrib_list);
-
-
-extern void
-_eglSaveSurface(_EGLSurface *surf);
-
-
-extern void
-_eglRemoveSurface(_EGLSurface *surf);
-
-
-extern _EGLSurface *
-_eglLookupSurface(EGLSurface surf);
-
-
-extern _EGLSurface *
-_eglGetCurrentSurface(EGLint readdraw);
+_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type,
+ _EGLConfig *config, const EGLint *attrib_list);
extern EGLBoolean
-_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw);
+_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf);
extern EGLBoolean
-_eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, NativePixmapType target);
+_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, NativePixmapType target);
extern EGLBoolean
-_eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+_eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint attribute, EGLint *value);
-extern EGLSurface
-_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list);
+extern _EGLSurface *
+_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list);
-extern EGLSurface
-_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list);
+extern _EGLSurface *
+_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list);
-extern EGLSurface
-_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+extern _EGLSurface *
+_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list);
extern EGLBoolean
-_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface);
+_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf);
extern EGLBoolean
-_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+_eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint attribute, EGLint value);
extern EGLBoolean
-_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer);
extern EGLBoolean
-_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer);
extern EGLBoolean
-_eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval);
+_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval);
#ifdef EGL_VERSION_1_2
-extern EGLSurface
-_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy,
+extern _EGLSurface *
+_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, _EGLDisplay *dpy,
EGLenum buftype, EGLClientBuffer buffer,
- EGLConfig config, const EGLint *attrib_list);
+ _EGLConfig *conf, const EGLint *attrib_list);
#endif /* EGL_VERSION_1_2 */
+/**
+ * Return true if the surface is bound to a thread.
+ * A surface bound to a texutre is not considered bound by
+ * this function.
+ */
+static INLINE EGLBoolean
+_eglIsSurfaceBound(_EGLSurface *surf)
+{
+ return (surf->Binding != NULL);
+}
+
#endif /* EGLSURFACE_INCLUDED */
diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h
index fa8cb496f8..b6321716d3 100644
--- a/src/egl/main/egltypedefs.h
+++ b/src/egl/main/egltypedefs.h
@@ -1,9 +1,12 @@
#ifndef EGLTYPEDEFS_INCLUDED
#define EGLTYPEDEFS_INCLUDED
+#define EGL_EGLEXT_PROTOTYPES
-#include <GLES/egl.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include "eglcompiler.h"
typedef struct _egl_api _EGLAPI;
@@ -25,10 +28,10 @@ typedef struct _egl_surface _EGLSurface;
typedef struct _egl_thread_info _EGLThreadInfo;
+typedef struct _egl_image _EGLImage;
-typedef void (*_EGLProc)();
-typedef _EGLDriver *(*_EGLMain_t)(_EGLDisplay *dpy);
+typedef _EGLDriver *(*_EGLMain_t)(const char *args);
#endif /* EGLTYPEDEFS_INCLUDED */
diff --git a/src/gallium/Makefile b/src/gallium/Makefile
new file mode 100644
index 0000000000..79ca767f7e
--- /dev/null
+++ b/src/gallium/Makefile
@@ -0,0 +1,12 @@
+# src/gallium/Makefile
+TOP = ../..
+include $(TOP)/configs/current
+
+SUBDIRS = $(GALLIUM_DIRS)
+
+default install clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) $@) || exit 1; \
+ fi \
+ done
diff --git a/src/gallium/Makefile.template b/src/gallium/Makefile.template
new file mode 100644
index 0000000000..63983c5220
--- /dev/null
+++ b/src/gallium/Makefile.template
@@ -0,0 +1,66 @@
+# src/gallium/Makefile.template
+
+# Template makefile for gallium libraries.
+#
+# Usage:
+# The minimum that the including makefile needs to define
+# is TOP, LIBNAME and one of of the *_SOURCES.
+#
+# Optional defines:
+# LIBRARY_INCLUDES are appended to the list of includes directories.
+# LIBRARY_DEFINES is not used for makedepend, but for compilation.
+
+### Basic defines ###
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(CPP_SOURCES:.cpp=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+INCLUDES = \
+ -I. \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/src/gallium/drivers \
+ -I$(GALLIUM)/src/gallium/include \
+ -I$(GALLIUM)/src/gallium/auxiliary \
+ -I$(GALLIUM)/src/gallium/drivers \
+ $(LIBRARY_INCLUDES)
+
+
+##### TARGETS #####
+
+default: depend lib$(LIBNAME).a
+
+lib$(LIBNAME).a: $(OBJECTS) $(EXTRA_OBJECTS) Makefile $(TOP)/src/gallium/Makefile.template
+ $(MKLIB) -o $(LIBNAME) -static $(OBJECTS) $(EXTRA_OBJECTS)
+
+depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) 2> /dev/null
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find $(TOP)/src/gallium/include -name \*.h`
+
+# Remove .o and backup files
+clean:
+ rm -f $(OBJECTS) lib$(LIBNAME).a depend depend.bak
+
+# Dummy target
+install:
+ @echo -n ""
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(LIBRARY_DEFINES) $< -o $@
+
+.cpp.o:
+ $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(LIBRARY_DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(LIBRARY_DEFINES) $< -o $@
+
+
+sinclude depend
diff --git a/src/gallium/README.portability b/src/gallium/README.portability
new file mode 100644
index 0000000000..adecf4bb79
--- /dev/null
+++ b/src/gallium/README.portability
@@ -0,0 +1,109 @@
+ CROSS-PLATFORM PORTABILITY GUIDELINES FOR GALLIUM3D
+
+
+= General Considerations =
+
+The state tracker and winsys driver support a rather limited number of
+platforms. However, the pipe drivers are meant to run in a wide number of
+platforms. Hence the pipe drivers, the auxiliary modules, and all public
+headers in general, should strictly follow these guidelines to ensure
+
+
+= Compiler Support =
+
+* Include the p_compiler.h.
+
+* Don't use the 'inline' keyword, use the INLINE macro in p_compiler.h instead.
+
+* Cast explicitly when converting to integer types of smaller sizes.
+
+* Cast explicitly when converting between float, double and integral types.
+
+* Don't use named struct initializers.
+
+* Don't use variable number of macro arguments. Use static inline functions
+instead.
+
+* Don't use C99 features.
+
+= Standard Library =
+
+* Avoid including standard library headers. Most standard library functions are
+not available in Windows Kernel Mode. Use the appropriate p_*.h include.
+
+== Memory Allocation ==
+
+* Use MALLOC, CALLOC, FREE instead of the malloc, calloc, free functions.
+
+* Use align_pointer() function defined in u_memory.h for aligning pointers
+ in a portable way.
+
+== Debugging ==
+
+* Use the functions/macros in p_debug.h.
+
+* Don't include assert.h, call abort, printf, etc.
+
+
+= Code Style =
+
+== Inherantice in C ==
+
+The main thing we do is mimic inheritance by structure containment.
+
+Here's a silly made-up example:
+
+/* base class */
+struct buffer
+{
+ int size;
+ void (*validate)(struct buffer *buf);
+};
+
+/* sub-class of bufffer */
+struct texture_buffer
+{
+ struct buffer base; /* the base class, MUST COME FIRST! */
+ int format;
+ int width, height;
+};
+
+
+Then, we'll typically have cast-wrapper functions to convert base-class
+pointers to sub-class pointers where needed:
+
+static inline struct vertex_buffer *vertex_buffer(struct buffer *buf)
+{
+ return (struct vertex_buffer *) buf;
+}
+
+
+To create/init a sub-classed object:
+
+struct buffer *create_texture_buffer(int w, int h, int format)
+{
+ struct texture_buffer *t = malloc(sizeof(*t));
+ t->format = format;
+ t->width = w;
+ t->height = h;
+ t->base.size = w * h;
+ t->base.validate = tex_validate;
+ return &t->base;
+}
+
+Example sub-class method:
+
+void tex_validate(struct buffer *buf)
+{
+ struct texture_buffer *tb = texture_buffer(buf);
+ assert(tb->format);
+ assert(tb->width);
+ assert(tb->height);
+}
+
+
+Note that we typically do not use typedefs to make "class names"; we use
+'struct whatever' everywhere.
+
+Gallium's pipe_context and the subclassed psb_context, etc are prime examples
+of this. There's also many examples in Mesa and the Mesa state tracker.
diff --git a/src/gallium/SConscript b/src/gallium/SConscript
new file mode 100644
index 0000000000..89c69d7205
--- /dev/null
+++ b/src/gallium/SConscript
@@ -0,0 +1,37 @@
+import os
+
+Import('*')
+
+env = env.Clone()
+
+auxiliaries = []
+
+Export('auxiliaries')
+
+
+if llvm:
+ SConscript(['auxiliary/gallivm/SConscript'])
+
+SConscript([
+ # NOTE: order matters!
+ 'auxiliary/util/SConscript',
+ 'auxiliary/rtasm/SConscript',
+ 'auxiliary/tgsi/SConscript',
+ 'auxiliary/cso_cache/SConscript',
+ 'auxiliary/translate/SConscript',
+ 'auxiliary/draw/SConscript',
+ 'auxiliary/pipebuffer/SConscript',
+ 'auxiliary/indices/SConscript',
+ 'auxiliary/rbug/SConscript',
+])
+
+for driver in env['drivers']:
+ SConscript(os.path.join('drivers', driver, 'SConscript'))
+
+SConscript('state_trackers/python/SConscript')
+SConscript('state_trackers/glx/xlib/SConscript')
+SConscript('state_trackers/dri/SConscript')
+SConscript('state_trackers/xorg/SConscript')
+
+if platform == 'windows':
+ SConscript('state_trackers/wgl/SConscript')
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
new file mode 100644
index 0000000000..5446eb68a9
--- /dev/null
+++ b/src/gallium/auxiliary/Makefile
@@ -0,0 +1,12 @@
+# src/gallium/auxiliary/Makefile
+TOP = ../../..
+include $(TOP)/configs/current
+
+SUBDIRS = $(GALLIUM_AUXILIARY_DIRS)
+
+default install clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) $@) || exit 1; \
+ fi \
+ done
diff --git a/src/gallium/auxiliary/cso_cache/Makefile b/src/gallium/auxiliary/cso_cache/Makefile
new file mode 100644
index 0000000000..8726afcd94
--- /dev/null
+++ b/src/gallium/auxiliary/cso_cache/Makefile
@@ -0,0 +1,11 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = cso_cache
+
+C_SOURCES = \
+ cso_context.c \
+ cso_cache.c \
+ cso_hash.c
+
+include ../../Makefile.template
diff --git a/src/gallium/auxiliary/cso_cache/SConscript b/src/gallium/auxiliary/cso_cache/SConscript
new file mode 100644
index 0000000000..651e68a191
--- /dev/null
+++ b/src/gallium/auxiliary/cso_cache/SConscript
@@ -0,0 +1,11 @@
+Import('*')
+
+cso_cache = env.ConvenienceLibrary(
+ target = 'cso_cache',
+ source = [
+ 'cso_context.c',
+ 'cso_cache.c',
+ 'cso_hash.c',
+ ])
+
+auxiliaries.insert(0, cso_cache)
diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.c b/src/gallium/auxiliary/cso_cache/cso_cache.c
new file mode 100644
index 0000000000..e6dce3f0e5
--- /dev/null
+++ b/src/gallium/auxiliary/cso_cache/cso_cache.c
@@ -0,0 +1,410 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Zack Rusin <zack@tungstengraphics.com>
+ */
+
+#include "util/u_debug.h"
+
+#include "util/u_memory.h"
+
+#include "cso_cache.h"
+#include "cso_hash.h"
+
+
+struct cso_cache {
+ struct cso_hash *blend_hash;
+ struct cso_hash *depth_stencil_hash;
+ struct cso_hash *fs_hash;
+ struct cso_hash *vs_hash;
+ struct cso_hash *rasterizer_hash;
+ struct cso_hash *sampler_hash;
+ int max_size;
+
+ cso_sanitize_callback sanitize_cb;
+ void *sanitize_data;
+};
+
+#if 1
+static unsigned hash_key(const void *key, unsigned key_size)
+{
+ unsigned *ikey = (unsigned *)key;
+ unsigned hash = 0, i;
+
+ assert(key_size % 4 == 0);
+
+ /* I'm sure this can be improved on:
+ */
+ for (i = 0; i < key_size/4; i++)
+ hash ^= ikey[i];
+
+ return hash;
+}
+#else
+static unsigned hash_key(const unsigned char *p, int n)
+{
+ unsigned h = 0;
+ unsigned g;
+
+ while (n--) {
+ h = (h << 4) + *p++;
+ if ((g = (h & 0xf0000000)) != 0)
+ h ^= g >> 23;
+ h &= ~g;
+ }
+ return h;
+}
+#endif
+
+unsigned cso_construct_key(void *item, int item_size)
+{
+ return hash_key((item), item_size);
+}
+
+static struct cso_hash *_cso_hash_for_type(struct cso_cache *sc, enum cso_cache_type type)
+{
+ struct cso_hash *hash = 0;
+
+ switch(type) {
+ case CSO_BLEND:
+ hash = sc->blend_hash;
+ break;
+ case CSO_SAMPLER:
+ hash = sc->sampler_hash;
+ break;
+ case CSO_DEPTH_STENCIL_ALPHA:
+ hash = sc->depth_stencil_hash;
+ break;
+ case CSO_RASTERIZER:
+ hash = sc->rasterizer_hash;
+ break;
+ case CSO_FRAGMENT_SHADER:
+ hash = sc->fs_hash;
+ break;
+ case CSO_VERTEX_SHADER:
+ hash = sc->vs_hash;
+ break;
+ }
+
+ return hash;
+}
+
+static int _cso_size_for_type(enum cso_cache_type type)
+{
+ switch(type) {
+ case CSO_BLEND:
+ return sizeof(struct pipe_blend_state);
+ case CSO_SAMPLER:
+ return sizeof(struct pipe_sampler_state);
+ case CSO_DEPTH_STENCIL_ALPHA:
+ return sizeof(struct pipe_depth_stencil_alpha_state);
+ case CSO_RASTERIZER:
+ return sizeof(struct pipe_rasterizer_state);
+ case CSO_FRAGMENT_SHADER:
+ return sizeof(struct pipe_shader_state);
+ case CSO_VERTEX_SHADER:
+ return sizeof(struct pipe_shader_state);
+ }
+ return 0;
+}
+
+
+static void delete_blend_state(void *state, void *data)
+{
+ struct cso_blend *cso = (struct cso_blend *)state;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+}
+
+static void delete_depth_stencil_state(void *state, void *data)
+{
+ struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+}
+
+static void delete_sampler_state(void *state, void *data)
+{
+ struct cso_sampler *cso = (struct cso_sampler *)state;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+}
+
+static void delete_rasterizer_state(void *state, void *data)
+{
+ struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+}
+
+static void delete_fs_state(void *state, void *data)
+{
+ struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+}
+
+static void delete_vs_state(void *state, void *data)
+{
+ struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+}
+
+
+static INLINE void delete_cso(void *state, enum cso_cache_type type)
+{
+ switch (type) {
+ case CSO_BLEND:
+ delete_blend_state(state, 0);
+ break;
+ case CSO_SAMPLER:
+ delete_sampler_state(state, 0);
+ break;
+ case CSO_DEPTH_STENCIL_ALPHA:
+ delete_depth_stencil_state(state, 0);
+ break;
+ case CSO_RASTERIZER:
+ delete_rasterizer_state(state, 0);
+ break;
+ case CSO_FRAGMENT_SHADER:
+ delete_fs_state(state, 0);
+ break;
+ case CSO_VERTEX_SHADER:
+ delete_vs_state(state, 0);
+ break;
+ default:
+ assert(0);
+ FREE(state);
+ }
+}
+
+
+static INLINE void sanitize_hash(struct cso_cache *sc,
+ struct cso_hash *hash,
+ enum cso_cache_type type,
+ int max_size)
+{
+ if (sc->sanitize_cb)
+ sc->sanitize_cb(hash, type, max_size, sc->sanitize_data);
+}
+
+
+static INLINE void sanitize_cb(struct cso_hash *hash, enum cso_cache_type type,
+ int max_size, void *user_data)
+{
+ /* if we're approach the maximum size, remove fourth of the entries
+ * otherwise every subsequent call will go through the same */
+ int hash_size = cso_hash_size(hash);
+ int max_entries = (max_size > hash_size) ? max_size : hash_size;
+ int to_remove = (max_size < max_entries) * max_entries/4;
+ if (hash_size > max_size)
+ to_remove += hash_size - max_size;
+ while (to_remove) {
+ /*remove elements until we're good */
+ /*fixme: currently we pick the nodes to remove at random*/
+ struct cso_hash_iter iter = cso_hash_first_node(hash);
+ void *cso = cso_hash_take(hash, cso_hash_iter_key(iter));
+ delete_cso(cso, type);
+ --to_remove;
+ }
+}
+
+struct cso_hash_iter
+cso_insert_state(struct cso_cache *sc,
+ unsigned hash_key, enum cso_cache_type type,
+ void *state)
+{
+ struct cso_hash *hash = _cso_hash_for_type(sc, type);
+ sanitize_hash(sc, hash, type, sc->max_size);
+
+ return cso_hash_insert(hash, hash_key, state);
+}
+
+struct cso_hash_iter
+cso_find_state(struct cso_cache *sc,
+ unsigned hash_key, enum cso_cache_type type)
+{
+ struct cso_hash *hash = _cso_hash_for_type(sc, type);
+
+ return cso_hash_find(hash, hash_key);
+}
+
+
+void *cso_hash_find_data_from_template( struct cso_hash *hash,
+ unsigned hash_key,
+ void *templ,
+ int size )
+{
+ struct cso_hash_iter iter = cso_hash_find(hash, hash_key);
+ while (!cso_hash_iter_is_null(iter)) {
+ void *iter_data = cso_hash_iter_data(iter);
+ if (!memcmp(iter_data, templ, size)) {
+ /* We found a match
+ */
+ return iter_data;
+ }
+ iter = cso_hash_iter_next(iter);
+ }
+ return NULL;
+}
+
+
+struct cso_hash_iter cso_find_state_template(struct cso_cache *sc,
+ unsigned hash_key, enum cso_cache_type type,
+ void *templ)
+{
+ struct cso_hash_iter iter = cso_find_state(sc, hash_key, type);
+ int size = _cso_size_for_type(type);
+ while (!cso_hash_iter_is_null(iter)) {
+ void *iter_data = cso_hash_iter_data(iter);
+ if (!memcmp(iter_data, templ, size))
+ return iter;
+ iter = cso_hash_iter_next(iter);
+ }
+ return iter;
+}
+
+void * cso_take_state(struct cso_cache *sc,
+ unsigned hash_key, enum cso_cache_type type)
+{
+ struct cso_hash *hash = _cso_hash_for_type(sc, type);
+ return cso_hash_take(hash, hash_key);
+}
+
+struct cso_cache *cso_cache_create(void)
+{
+ struct cso_cache *sc = MALLOC_STRUCT(cso_cache);
+ if (sc == NULL)
+ return NULL;
+
+ sc->max_size = 4096;
+ sc->blend_hash = cso_hash_create();
+ sc->sampler_hash = cso_hash_create();
+ sc->depth_stencil_hash = cso_hash_create();
+ sc->rasterizer_hash = cso_hash_create();
+ sc->fs_hash = cso_hash_create();
+ sc->vs_hash = cso_hash_create();
+ sc->sanitize_cb = sanitize_cb;
+ sc->sanitize_data = 0;
+
+ return sc;
+}
+
+void cso_for_each_state(struct cso_cache *sc, enum cso_cache_type type,
+ cso_state_callback func, void *user_data)
+{
+ struct cso_hash *hash = 0;
+ struct cso_hash_iter iter;
+
+ switch (type) {
+ case CSO_BLEND:
+ hash = sc->blend_hash;
+ break;
+ case CSO_SAMPLER:
+ hash = sc->sampler_hash;
+ break;
+ case CSO_DEPTH_STENCIL_ALPHA:
+ hash = sc->depth_stencil_hash;
+ break;
+ case CSO_RASTERIZER:
+ hash = sc->rasterizer_hash;
+ break;
+ case CSO_FRAGMENT_SHADER:
+ hash = sc->fs_hash;
+ break;
+ case CSO_VERTEX_SHADER:
+ hash = sc->vs_hash;
+ break;
+ }
+
+ iter = cso_hash_first_node(hash);
+ while (!cso_hash_iter_is_null(iter)) {
+ void *state = cso_hash_iter_data(iter);
+ iter = cso_hash_iter_next(iter);
+ if (state) {
+ func(state, user_data);
+ }
+ }
+}
+
+void cso_cache_delete(struct cso_cache *sc)
+{
+ assert(sc);
+
+ if (!sc)
+ return;
+
+ /* delete driver data */
+ cso_for_each_state(sc, CSO_BLEND, delete_blend_state, 0);
+ cso_for_each_state(sc, CSO_DEPTH_STENCIL_ALPHA, delete_depth_stencil_state, 0);
+ cso_for_each_state(sc, CSO_FRAGMENT_SHADER, delete_fs_state, 0);
+ cso_for_each_state(sc, CSO_VERTEX_SHADER, delete_vs_state, 0);
+ cso_for_each_state(sc, CSO_RASTERIZER, delete_rasterizer_state, 0);
+ cso_for_each_state(sc, CSO_SAMPLER, delete_sampler_state, 0);
+
+ cso_hash_delete(sc->blend_hash);
+ cso_hash_delete(sc->sampler_hash);
+ cso_hash_delete(sc->depth_stencil_hash);
+ cso_hash_delete(sc->rasterizer_hash);
+ cso_hash_delete(sc->fs_hash);
+ cso_hash_delete(sc->vs_hash);
+ FREE(sc);
+}
+
+void cso_set_maximum_cache_size(struct cso_cache *sc, int number)
+{
+ sc->max_size = number;
+
+ sanitize_hash(sc, sc->blend_hash, CSO_BLEND, sc->max_size);
+ sanitize_hash(sc, sc->depth_stencil_hash, CSO_DEPTH_STENCIL_ALPHA,
+ sc->max_size);
+ sanitize_hash(sc, sc->fs_hash, CSO_FRAGMENT_SHADER, sc->max_size);
+ sanitize_hash(sc, sc->vs_hash, CSO_VERTEX_SHADER, sc->max_size);
+ sanitize_hash(sc, sc->rasterizer_hash, CSO_RASTERIZER, sc->max_size);
+ sanitize_hash(sc, sc->sampler_hash, CSO_SAMPLER, sc->max_size);
+}
+
+int cso_maximum_cache_size(const struct cso_cache *sc)
+{
+ return sc->max_size;
+}
+
+void cso_cache_set_sanitize_callback(struct cso_cache *sc,
+ cso_sanitize_callback cb,
+ void *user_data)
+{
+ sc->sanitize_cb = cb;
+ sc->sanitize_data = user_data;
+}
+
diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.h b/src/gallium/auxiliary/cso_cache/cso_cache.h
new file mode 100644
index 0000000000..6b5c230e8f
--- /dev/null
+++ b/src/gallium/auxiliary/cso_cache/cso_cache.h
@@ -0,0 +1,176 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /**
+ * @file
+ * Constant State Object (CSO) cache.
+ *
+ * The basic idea is that the states are created via the
+ * create_state/bind_state/delete_state semantics. The driver is expected to
+ * perform as much of the Gallium state translation to whatever its internal
+ * representation is during the create call. Gallium then has a caching
+ * mechanism where it stores the created states. When the pipeline needs an
+ * actual state change, a bind call is issued. In the bind call the driver
+ * gets its already translated representation.
+ *
+ * Those semantics mean that the driver doesn't do the repeated translations
+ * of states on every frame, but only once, when a new state is actually
+ * created.
+ *
+ * Even on hardware that doesn't do any kind of state cache, it makes the
+ * driver look a lot neater, plus it avoids all the redundant state
+ * translations on every frame.
+ *
+ * Currently our constant state objects are:
+ * - alpha test
+ * - blend
+ * - depth stencil
+ * - fragment shader
+ * - rasterizer (old setup)
+ * - sampler
+ * - vertex shader
+ *
+ * Things that are not constant state objects include:
+ * - blend_color
+ * - clip_state
+ * - clear_color_state
+ * - constant_buffer
+ * - feedback_state
+ * - framebuffer_state
+ * - polygon_stipple
+ * - scissor_state
+ * - texture_state
+ * - viewport_state
+ *
+ * @author Zack Rusin <zack@tungstengraphics.com>
+ */
+
+#ifndef CSO_CACHE_H
+#define CSO_CACHE_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+/* cso_hash.h is necessary for cso_hash_iter, as MSVC requires structures
+ * returned by value to be fully defined */
+#include "cso_hash.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum cso_cache_type {
+ CSO_BLEND,
+ CSO_SAMPLER,
+ CSO_DEPTH_STENCIL_ALPHA,
+ CSO_RASTERIZER,
+ CSO_FRAGMENT_SHADER,
+ CSO_VERTEX_SHADER
+};
+
+typedef void (*cso_state_callback)(void *ctx, void *obj);
+
+typedef void (*cso_sanitize_callback)(struct cso_hash *hash,
+ enum cso_cache_type type,
+ int max_size,
+ void *user_data);
+
+struct cso_cache;
+
+struct cso_blend {
+ struct pipe_blend_state state;
+ void *data;
+ cso_state_callback delete_state;
+ struct pipe_context *context;
+};
+
+struct cso_depth_stencil_alpha {
+ struct pipe_depth_stencil_alpha_state state;
+ void *data;
+ cso_state_callback delete_state;
+ struct pipe_context *context;
+};
+
+struct cso_rasterizer {
+ struct pipe_rasterizer_state state;
+ void *data;
+ cso_state_callback delete_state;
+ struct pipe_context *context;
+};
+
+struct cso_fragment_shader {
+ struct pipe_shader_state state;
+ void *data;
+ cso_state_callback delete_state;
+ struct pipe_context *context;
+};
+
+struct cso_vertex_shader {
+ struct pipe_shader_state state;
+ void *data;
+ cso_state_callback delete_state;
+ struct pipe_context *context;
+};
+
+struct cso_sampler {
+ struct pipe_sampler_state state;
+ void *data;
+ cso_state_callback delete_state;
+ struct pipe_context *context;
+};
+
+unsigned cso_construct_key(void *item, int item_size);
+
+struct cso_cache *cso_cache_create(void);
+void cso_cache_delete(struct cso_cache *sc);
+
+void cso_cache_set_sanitize_callback(struct cso_cache *sc,
+ cso_sanitize_callback cb,
+ void *user_data);
+
+struct cso_hash_iter cso_insert_state(struct cso_cache *sc,
+ unsigned hash_key, enum cso_cache_type type,
+ void *state);
+struct cso_hash_iter cso_find_state(struct cso_cache *sc,
+ unsigned hash_key, enum cso_cache_type type);
+struct cso_hash_iter cso_find_state_template(struct cso_cache *sc,
+ unsigned hash_key, enum cso_cache_type type,
+ void *templ);
+void cso_for_each_state(struct cso_cache *sc, enum cso_cache_type type,
+ cso_state_callback func, void *user_data);
+void * cso_take_state(struct cso_cache *sc, unsigned hash_key,
+ enum cso_cache_type type);
+
+void cso_set_maximum_cache_size(struct cso_cache *sc, int number);
+int cso_maximum_cache_size(const struct cso_cache *sc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
new file mode 100644
index 0000000000..36c882acb7
--- /dev/null
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -0,0 +1,865 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /**
+ * @file
+ *
+ * Wrap the cso cache & hash mechanisms in a simplified
+ * pipe-driver-specific interface.
+ *
+ * @author Zack Rusin <zack@tungstengraphics.com>
+ * @author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "pipe/p_state.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_parse.h"
+
+#include "cso_cache/cso_context.h"
+#include "cso_cache/cso_cache.h"
+#include "cso_cache/cso_hash.h"
+
+struct cso_context {
+ struct pipe_context *pipe;
+ struct cso_cache *cache;
+
+ struct {
+ void *samplers[PIPE_MAX_SAMPLERS];
+ unsigned nr_samplers;
+ } hw;
+
+ void *samplers[PIPE_MAX_SAMPLERS];
+ unsigned nr_samplers;
+
+ unsigned nr_samplers_saved;
+ void *samplers_saved[PIPE_MAX_SAMPLERS];
+
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ uint nr_textures;
+
+ uint nr_textures_saved;
+ struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS];
+
+ /** Current and saved state.
+ * The saved state is used as a 1-deep stack.
+ */
+ void *blend, *blend_saved;
+ void *depth_stencil, *depth_stencil_saved;
+ void *rasterizer, *rasterizer_saved;
+ void *fragment_shader, *fragment_shader_saved;
+ void *vertex_shader, *vertex_shader_saved;
+
+ struct pipe_framebuffer_state fb, fb_saved;
+ struct pipe_viewport_state vp, vp_saved;
+ struct pipe_blend_color blend_color;
+};
+
+
+static void
+free_framebuffer_state(struct pipe_framebuffer_state *fb);
+
+
+static boolean delete_blend_state(struct cso_context *ctx, void *state)
+{
+ struct cso_blend *cso = (struct cso_blend *)state;
+
+ if (ctx->blend == cso->data)
+ return FALSE;
+
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+ return TRUE;
+}
+
+static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state)
+{
+ struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
+
+ if (ctx->depth_stencil == cso->data)
+ return FALSE;
+
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+
+ return TRUE;
+}
+
+static boolean delete_sampler_state(struct cso_context *ctx, void *state)
+{
+ struct cso_sampler *cso = (struct cso_sampler *)state;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+ return TRUE;
+}
+
+static boolean delete_rasterizer_state(struct cso_context *ctx, void *state)
+{
+ struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
+
+ if (ctx->rasterizer == cso->data)
+ return FALSE;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+ return TRUE;
+}
+
+static boolean delete_fs_state(struct cso_context *ctx, void *state)
+{
+ struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
+ if (ctx->fragment_shader == cso->data)
+ return FALSE;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+ return TRUE;
+}
+
+static boolean delete_vs_state(struct cso_context *ctx, void *state)
+{
+ struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
+ if (ctx->vertex_shader == cso->data)
+ return TRUE;
+ if (cso->delete_state)
+ cso->delete_state(cso->context, cso->data);
+ FREE(state);
+ return FALSE;
+}
+
+
+static INLINE boolean delete_cso(struct cso_context *ctx,
+ void *state, enum cso_cache_type type)
+{
+ switch (type) {
+ case CSO_BLEND:
+ return delete_blend_state(ctx, state);
+ break;
+ case CSO_SAMPLER:
+ return delete_sampler_state(ctx, state);
+ break;
+ case CSO_DEPTH_STENCIL_ALPHA:
+ return delete_depth_stencil_state(ctx, state);
+ break;
+ case CSO_RASTERIZER:
+ return delete_rasterizer_state(ctx, state);
+ break;
+ case CSO_FRAGMENT_SHADER:
+ return delete_fs_state(ctx, state);
+ break;
+ case CSO_VERTEX_SHADER:
+ return delete_vs_state(ctx, state);
+ break;
+ default:
+ assert(0);
+ FREE(state);
+ }
+ return FALSE;
+}
+
+static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
+ int max_size, void *user_data)
+{
+ struct cso_context *ctx = (struct cso_context *)user_data;
+ /* if we're approach the maximum size, remove fourth of the entries
+ * otherwise every subsequent call will go through the same */
+ int hash_size = cso_hash_size(hash);
+ int max_entries = (max_size > hash_size) ? max_size : hash_size;
+ int to_remove = (max_size < max_entries) * max_entries/4;
+ struct cso_hash_iter iter = cso_hash_first_node(hash);
+ if (hash_size > max_size)
+ to_remove += hash_size - max_size;
+ while (to_remove) {
+ /*remove elements until we're good */
+ /*fixme: currently we pick the nodes to remove at random*/
+ void *cso = cso_hash_iter_data(iter);
+ if (delete_cso(ctx, cso, type)) {
+ iter = cso_hash_erase(hash, iter);
+ --to_remove;
+ } else
+ iter = cso_hash_iter_next(iter);
+ }
+}
+
+
+struct cso_context *cso_create_context( struct pipe_context *pipe )
+{
+ struct cso_context *ctx = CALLOC_STRUCT(cso_context);
+ if (ctx == NULL)
+ goto out;
+
+ ctx->cache = cso_cache_create();
+ if (ctx->cache == NULL)
+ goto out;
+ cso_cache_set_sanitize_callback(ctx->cache,
+ sanitize_hash,
+ ctx);
+
+ ctx->pipe = pipe;
+
+ /* Enable for testing: */
+ if (0) cso_set_maximum_cache_size( ctx->cache, 4 );
+
+ return ctx;
+
+out:
+ cso_destroy_context( ctx );
+ return NULL;
+}
+
+
+/**
+ * Prior to context destruction, this function unbinds all state objects.
+ */
+void cso_release_all( struct cso_context *ctx )
+{
+ unsigned i;
+
+ if (ctx->pipe) {
+ ctx->pipe->bind_blend_state( ctx->pipe, NULL );
+ ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
+ ctx->pipe->bind_sampler_states( ctx->pipe, 0, NULL );
+ ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
+ ctx->pipe->bind_fs_state( ctx->pipe, NULL );
+ ctx->pipe->bind_vs_state( ctx->pipe, NULL );
+ }
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ pipe_texture_reference(&ctx->textures[i], NULL);
+ pipe_texture_reference(&ctx->textures_saved[i], NULL);
+ }
+
+ free_framebuffer_state(&ctx->fb);
+ free_framebuffer_state(&ctx->fb_saved);
+
+ if (ctx->cache) {
+ cso_cache_delete( ctx->cache );
+ ctx->cache = NULL;
+ }
+}
+
+
+void cso_destroy_context( struct cso_context *ctx )
+{
+ if (ctx) {
+ //cso_release_all( ctx );
+ FREE( ctx );
+ }
+}
+
+
+/* Those function will either find the state of the given template
+ * in the cache or they will create a new state from the given
+ * template, insert it in the cache and return it.
+ */
+
+/*
+ * If the driver returns 0 from the create method then they will assign
+ * the data member of the cso to be the template itself.
+ */
+
+enum pipe_error cso_set_blend(struct cso_context *ctx,
+ const struct pipe_blend_state *templ)
+{
+ unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_blend_state));
+ struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
+ hash_key, CSO_BLEND,
+ (void*)templ);
+ void *handle;
+
+ if (cso_hash_iter_is_null(iter)) {
+ struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
+ if (!cso)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ memcpy(&cso->state, templ, sizeof(*templ));
+ cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
+ cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
+ cso->context = ctx->pipe;
+
+ iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso);
+ if (cso_hash_iter_is_null(iter)) {
+ FREE(cso);
+ return PIPE_ERROR_OUT_OF_MEMORY;
+ }
+
+ handle = cso->data;
+ }
+ else {
+ handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
+ }
+
+ if (ctx->blend != handle) {
+ ctx->blend = handle;
+ ctx->pipe->bind_blend_state(ctx->pipe, handle);
+ }
+ return PIPE_OK;
+}
+
+void cso_save_blend(struct cso_context *ctx)
+{
+ assert(!ctx->blend_saved);
+ ctx->blend_saved = ctx->blend;
+}
+
+void cso_restore_blend(struct cso_context *ctx)
+{
+ if (ctx->blend != ctx->blend_saved) {
+ ctx->blend = ctx->blend_saved;
+ ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
+ }
+ ctx->blend_saved = NULL;
+}
+
+
+
+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 hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_sampler_state));
+ struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
+ hash_key, CSO_SAMPLER,
+ (void*)templ);
+
+ 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;
+}
+
+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_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->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 );
+}
+
+
+enum pipe_error cso_set_sampler_textures( struct cso_context *ctx,
+ uint count,
+ struct pipe_texture **textures )
+{
+ uint i;
+
+ ctx->nr_textures = count;
+
+ for (i = 0; i < count; i++)
+ pipe_texture_reference(&ctx->textures[i], textures[i]);
+ for ( ; i < PIPE_MAX_SAMPLERS; i++)
+ pipe_texture_reference(&ctx->textures[i], NULL);
+
+ ctx->pipe->set_sampler_textures(ctx->pipe, count, textures);
+
+ return PIPE_OK;
+}
+
+void cso_save_sampler_textures( struct cso_context *ctx )
+{
+ uint i;
+
+ ctx->nr_textures_saved = ctx->nr_textures;
+ for (i = 0; i < ctx->nr_textures; i++) {
+ assert(!ctx->textures_saved[i]);
+ pipe_texture_reference(&ctx->textures_saved[i], ctx->textures[i]);
+ }
+}
+
+void cso_restore_sampler_textures( struct cso_context *ctx )
+{
+ uint i;
+
+ ctx->nr_textures = ctx->nr_textures_saved;
+
+ for (i = 0; i < ctx->nr_textures; i++) {
+ pipe_texture_reference(&ctx->textures[i], NULL);
+ ctx->textures[i] = ctx->textures_saved[i];
+ ctx->textures_saved[i] = NULL;
+ }
+ for ( ; i < PIPE_MAX_SAMPLERS; i++)
+ pipe_texture_reference(&ctx->textures[i], NULL);
+
+ ctx->pipe->set_sampler_textures(ctx->pipe, ctx->nr_textures, ctx->textures);
+
+ ctx->nr_textures_saved = 0;
+}
+
+
+
+enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx,
+ const struct pipe_depth_stencil_alpha_state *templ)
+{
+ unsigned hash_key = cso_construct_key((void*)templ,
+ sizeof(struct pipe_depth_stencil_alpha_state));
+ struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
+ hash_key,
+ CSO_DEPTH_STENCIL_ALPHA,
+ (void*)templ);
+ void *handle;
+
+ if (cso_hash_iter_is_null(iter)) {
+ struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha));
+ if (!cso)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ memcpy(&cso->state, templ, sizeof(*templ));
+ cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state);
+ cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state;
+ cso->context = ctx->pipe;
+
+ iter = cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso);
+ if (cso_hash_iter_is_null(iter)) {
+ FREE(cso);
+ return PIPE_ERROR_OUT_OF_MEMORY;
+ }
+
+ handle = cso->data;
+ }
+ else {
+ handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data;
+ }
+
+ if (ctx->depth_stencil != handle) {
+ ctx->depth_stencil = handle;
+ ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
+ }
+ return PIPE_OK;
+}
+
+void cso_save_depth_stencil_alpha(struct cso_context *ctx)
+{
+ assert(!ctx->depth_stencil_saved);
+ ctx->depth_stencil_saved = ctx->depth_stencil;
+}
+
+void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
+{
+ if (ctx->depth_stencil != ctx->depth_stencil_saved) {
+ ctx->depth_stencil = ctx->depth_stencil_saved;
+ ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved);
+ }
+ ctx->depth_stencil_saved = NULL;
+}
+
+
+
+enum pipe_error cso_set_rasterizer(struct cso_context *ctx,
+ const struct pipe_rasterizer_state *templ)
+{
+ unsigned hash_key = cso_construct_key((void*)templ,
+ sizeof(struct pipe_rasterizer_state));
+ struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
+ hash_key, CSO_RASTERIZER,
+ (void*)templ);
+ void *handle = NULL;
+
+ if (cso_hash_iter_is_null(iter)) {
+ struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));
+ if (!cso)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ memcpy(&cso->state, templ, sizeof(*templ));
+ cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);
+ cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state;
+ cso->context = ctx->pipe;
+
+ iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso);
+ if (cso_hash_iter_is_null(iter)) {
+ FREE(cso);
+ return PIPE_ERROR_OUT_OF_MEMORY;
+ }
+
+ handle = cso->data;
+ }
+ else {
+ handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
+ }
+
+ if (ctx->rasterizer != handle) {
+ ctx->rasterizer = handle;
+ ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
+ }
+ return PIPE_OK;
+}
+
+void cso_save_rasterizer(struct cso_context *ctx)
+{
+ assert(!ctx->rasterizer_saved);
+ ctx->rasterizer_saved = ctx->rasterizer;
+}
+
+void cso_restore_rasterizer(struct cso_context *ctx)
+{
+ if (ctx->rasterizer != ctx->rasterizer_saved) {
+ ctx->rasterizer = ctx->rasterizer_saved;
+ ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
+ }
+ ctx->rasterizer_saved = NULL;
+}
+
+
+
+enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx,
+ void *handle )
+{
+ if (ctx->fragment_shader != handle) {
+ ctx->fragment_shader = handle;
+ ctx->pipe->bind_fs_state(ctx->pipe, handle);
+ }
+ return PIPE_OK;
+}
+
+void cso_delete_fragment_shader(struct cso_context *ctx, void *handle )
+{
+ if (handle == ctx->fragment_shader) {
+ /* unbind before deleting */
+ ctx->pipe->bind_fs_state(ctx->pipe, NULL);
+ ctx->fragment_shader = NULL;
+ }
+ ctx->pipe->delete_fs_state(ctx->pipe, handle);
+}
+
+/* Not really working:
+ */
+#if 0
+enum pipe_error cso_set_fragment_shader(struct cso_context *ctx,
+ const struct pipe_shader_state *templ)
+{
+ const struct tgsi_token *tokens = templ->tokens;
+ unsigned num_tokens = tgsi_num_tokens(tokens);
+ size_t tokens_size = num_tokens*sizeof(struct tgsi_token);
+ unsigned hash_key = cso_construct_key((void*)tokens, tokens_size);
+ struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
+ hash_key,
+ CSO_FRAGMENT_SHADER,
+ (void*)tokens);
+ void *handle = NULL;
+
+ if (cso_hash_iter_is_null(iter)) {
+ struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader) + tokens_size);
+ struct tgsi_token *cso_tokens = (struct tgsi_token *)((char *)cso + sizeof(*cso));
+
+ if (!cso)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ memcpy(cso_tokens, tokens, tokens_size);
+ cso->state.tokens = cso_tokens;
+ cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state);
+ cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state;
+ cso->context = ctx->pipe;
+
+ iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso);
+ if (cso_hash_iter_is_null(iter)) {
+ FREE(cso);
+ return PIPE_ERROR_OUT_OF_MEMORY;
+ }
+
+ handle = cso->data;
+ }
+ else {
+ handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data;
+ }
+
+ return cso_set_fragment_shader_handle( ctx, handle );
+}
+#endif
+
+void cso_save_fragment_shader(struct cso_context *ctx)
+{
+ assert(!ctx->fragment_shader_saved);
+ ctx->fragment_shader_saved = ctx->fragment_shader;
+}
+
+void cso_restore_fragment_shader(struct cso_context *ctx)
+{
+ if (ctx->fragment_shader_saved != ctx->fragment_shader) {
+ ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
+ ctx->fragment_shader = ctx->fragment_shader_saved;
+ }
+ ctx->fragment_shader_saved = NULL;
+}
+
+
+enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx,
+ void *handle )
+{
+ if (ctx->vertex_shader != handle) {
+ ctx->vertex_shader = handle;
+ ctx->pipe->bind_vs_state(ctx->pipe, handle);
+ }
+ return PIPE_OK;
+}
+
+void cso_delete_vertex_shader(struct cso_context *ctx, void *handle )
+{
+ if (handle == ctx->vertex_shader) {
+ /* unbind before deleting */
+ ctx->pipe->bind_vs_state(ctx->pipe, NULL);
+ ctx->vertex_shader = NULL;
+ }
+ ctx->pipe->delete_vs_state(ctx->pipe, handle);
+}
+
+
+/* Not really working:
+ */
+#if 0
+enum pipe_error cso_set_vertex_shader(struct cso_context *ctx,
+ const struct pipe_shader_state *templ)
+{
+ unsigned hash_key = cso_construct_key((void*)templ,
+ sizeof(struct pipe_shader_state));
+ struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
+ hash_key, CSO_VERTEX_SHADER,
+ (void*)templ);
+ void *handle = NULL;
+
+ if (cso_hash_iter_is_null(iter)) {
+ struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader));
+
+ if (!cso)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ memcpy(cso->state, templ, sizeof(*templ));
+ cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state);
+ cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state;
+ cso->context = ctx->pipe;
+
+ iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso);
+ if (cso_hash_iter_is_null(iter)) {
+ FREE(cso);
+ return PIPE_ERROR_OUT_OF_MEMORY;
+ }
+
+ handle = cso->data;
+ }
+ else {
+ handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data;
+ }
+
+ return cso_set_vertex_shader_handle( ctx, handle );
+}
+#endif
+
+
+
+void cso_save_vertex_shader(struct cso_context *ctx)
+{
+ assert(!ctx->vertex_shader_saved);
+ ctx->vertex_shader_saved = ctx->vertex_shader;
+}
+
+void cso_restore_vertex_shader(struct cso_context *ctx)
+{
+ if (ctx->vertex_shader_saved != ctx->vertex_shader) {
+ ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved);
+ ctx->vertex_shader = ctx->vertex_shader_saved;
+ }
+ ctx->vertex_shader_saved = NULL;
+}
+
+
+/**
+ * Copy framebuffer state from src to dst with refcounting of surfaces.
+ */
+static void
+copy_framebuffer_state(struct pipe_framebuffer_state *dst,
+ const struct pipe_framebuffer_state *src)
+{
+ uint i;
+
+ dst->width = src->width;
+ dst->height = src->height;
+ dst->nr_cbufs = src->nr_cbufs;
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
+ }
+ pipe_surface_reference(&dst->zsbuf, src->zsbuf);
+}
+
+
+static void
+free_framebuffer_state(struct pipe_framebuffer_state *fb)
+{
+ uint i;
+
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&fb->cbufs[i], NULL);
+ }
+ pipe_surface_reference(&fb->zsbuf, NULL);
+}
+
+
+enum pipe_error cso_set_framebuffer(struct cso_context *ctx,
+ const struct pipe_framebuffer_state *fb)
+{
+ if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {
+ copy_framebuffer_state(&ctx->fb, fb);
+ ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
+ }
+ return PIPE_OK;
+}
+
+void cso_save_framebuffer(struct cso_context *ctx)
+{
+ copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
+}
+
+void cso_restore_framebuffer(struct cso_context *ctx)
+{
+ if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
+ copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);
+ ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
+ free_framebuffer_state(&ctx->fb_saved);
+ }
+}
+
+
+enum pipe_error cso_set_viewport(struct cso_context *ctx,
+ const struct pipe_viewport_state *vp)
+{
+ if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
+ ctx->vp = *vp;
+ ctx->pipe->set_viewport_state(ctx->pipe, vp);
+ }
+ return PIPE_OK;
+}
+
+void cso_save_viewport(struct cso_context *ctx)
+{
+ ctx->vp_saved = ctx->vp;
+}
+
+
+void cso_restore_viewport(struct cso_context *ctx)
+{
+ if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
+ ctx->vp = ctx->vp_saved;
+ ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp);
+ }
+}
+
+
+
+
+enum pipe_error cso_set_blend_color(struct cso_context *ctx,
+ const struct pipe_blend_color *bc)
+{
+ if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) {
+ ctx->blend_color = *bc;
+ ctx->pipe->set_blend_color(ctx->pipe, bc);
+ }
+ return PIPE_OK;
+}
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h
new file mode 100644
index 0000000000..b04e98bfa1
--- /dev/null
+++ b/src/gallium/auxiliary/cso_cache/cso_context.h
@@ -0,0 +1,145 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CSO_CONTEXT_H
+#define CSO_CONTEXT_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_error.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct cso_context;
+
+struct cso_context *cso_create_context( struct pipe_context *pipe );
+
+void cso_release_all( struct cso_context *ctx );
+
+void cso_destroy_context( struct cso_context *cso );
+
+
+
+enum pipe_error cso_set_blend( struct cso_context *cso,
+ const struct pipe_blend_state *blend );
+void cso_save_blend(struct cso_context *cso);
+void cso_restore_blend(struct cso_context *cso);
+
+
+
+enum pipe_error cso_set_depth_stencil_alpha( struct cso_context *cso,
+ const struct pipe_depth_stencil_alpha_state *dsa );
+void cso_save_depth_stencil_alpha(struct cso_context *cso);
+void cso_restore_depth_stencil_alpha(struct cso_context *cso);
+
+
+
+enum pipe_error cso_set_rasterizer( struct cso_context *cso,
+ const struct pipe_rasterizer_state *rasterizer );
+void cso_save_rasterizer(struct cso_context *cso);
+void cso_restore_rasterizer(struct cso_context *cso);
+
+
+
+enum pipe_error cso_set_samplers( struct cso_context *cso,
+ unsigned count,
+ const struct pipe_sampler_state **states );
+void cso_save_samplers(struct cso_context *cso);
+void cso_restore_samplers(struct cso_context *cso);
+
+/* Alternate interface to support state trackers that like to modify
+ * samplers one at a time:
+ */
+enum pipe_error cso_single_sampler( struct cso_context *cso,
+ unsigned nr,
+ const struct pipe_sampler_state *states );
+
+void cso_single_sampler_done( struct cso_context *cso );
+
+
+
+enum pipe_error cso_set_sampler_textures( struct cso_context *cso,
+ uint count,
+ struct pipe_texture **textures );
+void cso_save_sampler_textures( struct cso_context *cso );
+void cso_restore_sampler_textures( struct cso_context *cso );
+
+
+
+/* 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
+ * the state tracker to implement their own specialized caching.
+ */
+enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx,
+ void *handle );
+void cso_delete_fragment_shader(struct cso_context *ctx, void *handle );
+/*
+enum pipe_error cso_set_fragment_shader( struct cso_context *cso,
+ const struct pipe_shader_state *shader );
+*/
+void cso_save_fragment_shader(struct cso_context *cso);
+void cso_restore_fragment_shader(struct cso_context *cso);
+
+
+enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx,
+ void *handle );
+void cso_delete_vertex_shader(struct cso_context *ctx, void *handle );
+/*
+enum pipe_error cso_set_vertex_shader( struct cso_context *cso,
+ const struct pipe_shader_state *shader );
+*/
+void cso_save_vertex_shader(struct cso_context *cso);
+void cso_restore_vertex_shader(struct cso_context *cso);
+
+
+
+enum pipe_error cso_set_framebuffer(struct cso_context *cso,
+ const struct pipe_framebuffer_state *fb);
+void cso_save_framebuffer(struct cso_context *cso);
+void cso_restore_framebuffer(struct cso_context *cso);
+
+
+enum pipe_error cso_set_viewport(struct cso_context *cso,
+ const struct pipe_viewport_state *vp);
+void cso_save_viewport(struct cso_context *cso);
+void cso_restore_viewport(struct cso_context *cso);
+
+
+enum pipe_error cso_set_blend_color(struct cso_context *cso,
+ const struct pipe_blend_color *bc);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/auxiliary/cso_cache/cso_hash.c b/src/gallium/auxiliary/cso_cache/cso_hash.c
new file mode 100644
index 0000000000..288cef7b6f
--- /dev/null
+++ b/src/gallium/auxiliary/cso_cache/cso_hash.c
@@ -0,0 +1,439 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin <zack@tungstengraphics.com>
+ */
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+
+#include "cso_hash.h"
+
+#define MAX(a, b) ((a > b) ? (a) : (b))
+
+static const int MinNumBits = 4;
+
+static const unsigned char prime_deltas[] = {
+ 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
+ 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
+};
+
+static int primeForNumBits(int numBits)
+{
+ return (1 << numBits) + prime_deltas[numBits];
+}
+
+/*
+ Returns the smallest integer n such that
+ primeForNumBits(n) >= hint.
+*/
+static int countBits(int hint)
+{
+ int numBits = 0;
+ int bits = hint;
+
+ while (bits > 1) {
+ bits >>= 1;
+ numBits++;
+ }
+
+ if (numBits >= (int)sizeof(prime_deltas)) {
+ numBits = sizeof(prime_deltas) - 1;
+ } else if (primeForNumBits(numBits) < hint) {
+ ++numBits;
+ }
+ return numBits;
+}
+
+struct cso_node {
+ struct cso_node *next;
+ unsigned key;
+ void *value;
+};
+
+struct cso_hash_data {
+ struct cso_node *fakeNext;
+ struct cso_node **buckets;
+ int size;
+ int nodeSize;
+ short userNumBits;
+ short numBits;
+ int numBuckets;
+};
+
+struct cso_hash {
+ union {
+ struct cso_hash_data *d;
+ struct cso_node *e;
+ } data;
+};
+
+static void *cso_data_allocate_node(struct cso_hash_data *hash)
+{
+ return MALLOC(hash->nodeSize);
+}
+
+static void cso_free_node(struct cso_node *node)
+{
+ FREE(node);
+}
+
+static struct cso_node *
+cso_hash_create_node(struct cso_hash *hash,
+ unsigned akey, void *avalue,
+ struct cso_node **anextNode)
+{
+ struct cso_node *node = cso_data_allocate_node(hash->data.d);
+
+ if (!node)
+ return NULL;
+
+ node->key = akey;
+ node->value = avalue;
+
+ node->next = (struct cso_node*)(*anextNode);
+ *anextNode = node;
+ ++hash->data.d->size;
+ return node;
+}
+
+static void cso_data_rehash(struct cso_hash_data *hash, int hint)
+{
+ if (hint < 0) {
+ hint = countBits(-hint);
+ if (hint < MinNumBits)
+ hint = MinNumBits;
+ hash->userNumBits = (short)hint;
+ while (primeForNumBits(hint) < (hash->size >> 1))
+ ++hint;
+ } else if (hint < MinNumBits) {
+ hint = MinNumBits;
+ }
+
+ if (hash->numBits != hint) {
+ struct cso_node *e = (struct cso_node *)(hash);
+ struct cso_node **oldBuckets = hash->buckets;
+ int oldNumBuckets = hash->numBuckets;
+ int i = 0;
+
+ hash->numBits = (short)hint;
+ hash->numBuckets = primeForNumBits(hint);
+ hash->buckets = MALLOC(sizeof(struct cso_node*) * hash->numBuckets);
+ for (i = 0; i < hash->numBuckets; ++i)
+ hash->buckets[i] = e;
+
+ for (i = 0; i < oldNumBuckets; ++i) {
+ struct cso_node *firstNode = oldBuckets[i];
+ while (firstNode != e) {
+ unsigned h = firstNode->key;
+ struct cso_node *lastNode = firstNode;
+ struct cso_node *afterLastNode;
+ struct cso_node **beforeFirstNode;
+
+ while (lastNode->next != e && lastNode->next->key == h)
+ lastNode = lastNode->next;
+
+ afterLastNode = lastNode->next;
+ beforeFirstNode = &hash->buckets[h % hash->numBuckets];
+ while (*beforeFirstNode != e)
+ beforeFirstNode = &(*beforeFirstNode)->next;
+ lastNode->next = *beforeFirstNode;
+ *beforeFirstNode = firstNode;
+ firstNode = afterLastNode;
+ }
+ }
+ FREE(oldBuckets);
+ }
+}
+
+static void cso_data_might_grow(struct cso_hash_data *hash)
+{
+ if (hash->size >= hash->numBuckets)
+ cso_data_rehash(hash, hash->numBits + 1);
+}
+
+static void cso_data_has_shrunk(struct cso_hash_data *hash)
+{
+ if (hash->size <= (hash->numBuckets >> 3) &&
+ hash->numBits > hash->userNumBits) {
+ int max = MAX(hash->numBits-2, hash->userNumBits);
+ cso_data_rehash(hash, max);
+ }
+}
+
+static struct cso_node *cso_data_first_node(struct cso_hash_data *hash)
+{
+ struct cso_node *e = (struct cso_node *)(hash);
+ struct cso_node **bucket = hash->buckets;
+ int n = hash->numBuckets;
+ while (n--) {
+ if (*bucket != e)
+ return *bucket;
+ ++bucket;
+ }
+ return e;
+}
+
+static struct cso_node **cso_hash_find_node(struct cso_hash *hash, unsigned akey)
+{
+ struct cso_node **node;
+
+ if (hash->data.d->numBuckets) {
+ node = (struct cso_node **)(&hash->data.d->buckets[akey % hash->data.d->numBuckets]);
+ assert(*node == hash->data.e || (*node)->next);
+ while (*node != hash->data.e && (*node)->key != akey)
+ node = &(*node)->next;
+ } else {
+ node = (struct cso_node **)((const struct cso_node * const *)(&hash->data.e));
+ }
+ return node;
+}
+
+struct cso_hash_iter cso_hash_insert(struct cso_hash *hash,
+ unsigned key, void *data)
+{
+ cso_data_might_grow(hash->data.d);
+
+ {
+ struct cso_node **nextNode = cso_hash_find_node(hash, key);
+ struct cso_node *node = cso_hash_create_node(hash, key, data, nextNode);
+ if (!node) {
+ struct cso_hash_iter null_iter = {hash, 0};
+ return null_iter;
+ }
+
+ {
+ struct cso_hash_iter iter = {hash, node};
+ return iter;
+ }
+ }
+}
+
+struct cso_hash * cso_hash_create(void)
+{
+ struct cso_hash *hash = MALLOC_STRUCT(cso_hash);
+ if (!hash)
+ return NULL;
+
+ hash->data.d = MALLOC_STRUCT(cso_hash_data);
+ if (!hash->data.d) {
+ FREE(hash);
+ return NULL;
+ }
+
+ hash->data.d->fakeNext = 0;
+ hash->data.d->buckets = 0;
+ hash->data.d->size = 0;
+ hash->data.d->nodeSize = sizeof(struct cso_node);
+ hash->data.d->userNumBits = (short)MinNumBits;
+ hash->data.d->numBits = 0;
+ hash->data.d->numBuckets = 0;
+
+ return hash;
+}
+
+void cso_hash_delete(struct cso_hash *hash)
+{
+ struct cso_node *e_for_x = (struct cso_node *)(hash->data.d);
+ struct cso_node **bucket = (struct cso_node **)(hash->data.d->buckets);
+ int n = hash->data.d->numBuckets;
+ while (n--) {
+ struct cso_node *cur = *bucket++;
+ while (cur != e_for_x) {
+ struct cso_node *next = cur->next;
+ cso_free_node(cur);
+ cur = next;
+ }
+ }
+ FREE(hash->data.d->buckets);
+ FREE(hash->data.d);
+ FREE(hash);
+}
+
+struct cso_hash_iter cso_hash_find(struct cso_hash *hash,
+ unsigned key)
+{
+ struct cso_node **nextNode = cso_hash_find_node(hash, key);
+ struct cso_hash_iter iter = {hash, *nextNode};
+ return iter;
+}
+
+unsigned cso_hash_iter_key(struct cso_hash_iter iter)
+{
+ if (!iter.node || iter.hash->data.e == iter.node)
+ return 0;
+ return iter.node->key;
+}
+
+void * cso_hash_iter_data(struct cso_hash_iter iter)
+{
+ if (!iter.node || iter.hash->data.e == iter.node)
+ return 0;
+ return iter.node->value;
+}
+
+static struct cso_node *cso_hash_data_next(struct cso_node *node)
+{
+ union {
+ struct cso_node *next;
+ struct cso_node *e;
+ struct cso_hash_data *d;
+ } a;
+ int start;
+ struct cso_node **bucket;
+ int n;
+
+ a.next = node->next;
+ if (!a.next) {
+ debug_printf("iterating beyond the last element\n");
+ return 0;
+ }
+ if (a.next->next)
+ return a.next;
+
+ start = (node->key % a.d->numBuckets) + 1;
+ bucket = a.d->buckets + start;
+ n = a.d->numBuckets - start;
+ while (n--) {
+ if (*bucket != a.e)
+ return *bucket;
+ ++bucket;
+ }
+ return a.e;
+}
+
+
+static struct cso_node *cso_hash_data_prev(struct cso_node *node)
+{
+ union {
+ struct cso_node *e;
+ struct cso_hash_data *d;
+ } a;
+ int start;
+ struct cso_node *sentinel;
+ struct cso_node **bucket;
+
+ a.e = node;
+ while (a.e->next)
+ a.e = a.e->next;
+
+ if (node == a.e)
+ start = a.d->numBuckets - 1;
+ else
+ start = node->key % a.d->numBuckets;
+
+ sentinel = node;
+ bucket = a.d->buckets + start;
+ while (start >= 0) {
+ if (*bucket != sentinel) {
+ struct cso_node *prev = *bucket;
+ while (prev->next != sentinel)
+ prev = prev->next;
+ return prev;
+ }
+
+ sentinel = a.e;
+ --bucket;
+ --start;
+ }
+ debug_printf("iterating backward beyond first element\n");
+ return a.e;
+}
+
+struct cso_hash_iter cso_hash_iter_next(struct cso_hash_iter iter)
+{
+ struct cso_hash_iter next = {iter.hash, cso_hash_data_next(iter.node)};
+ return next;
+}
+
+int cso_hash_iter_is_null(struct cso_hash_iter iter)
+{
+ if (!iter.node || iter.node == iter.hash->data.e)
+ return 1;
+ return 0;
+}
+
+void * cso_hash_take(struct cso_hash *hash,
+ unsigned akey)
+{
+ struct cso_node **node = cso_hash_find_node(hash, akey);
+ if (*node != hash->data.e) {
+ void *t = (*node)->value;
+ struct cso_node *next = (*node)->next;
+ cso_free_node(*node);
+ *node = next;
+ --hash->data.d->size;
+ cso_data_has_shrunk(hash->data.d);
+ return t;
+ }
+ return 0;
+}
+
+struct cso_hash_iter cso_hash_iter_prev(struct cso_hash_iter iter)
+{
+ struct cso_hash_iter prev = {iter.hash,
+ cso_hash_data_prev(iter.node)};
+ return prev;
+}
+
+struct cso_hash_iter cso_hash_first_node(struct cso_hash *hash)
+{
+ struct cso_hash_iter iter = {hash, cso_data_first_node(hash->data.d)};
+ return iter;
+}
+
+int cso_hash_size(struct cso_hash *hash)
+{
+ return hash->data.d->size;
+}
+
+struct cso_hash_iter cso_hash_erase(struct cso_hash *hash, struct cso_hash_iter iter)
+{
+ struct cso_hash_iter ret = iter;
+ struct cso_node *node = iter.node;
+ struct cso_node **node_ptr;
+
+ if (node == hash->data.e)
+ return iter;
+
+ ret = cso_hash_iter_next(ret);
+ node_ptr = (struct cso_node**)(&hash->data.d->buckets[node->key % hash->data.d->numBuckets]);
+ while (*node_ptr != node)
+ node_ptr = &(*node_ptr)->next;
+ *node_ptr = node->next;
+ cso_free_node(node);
+ --hash->data.d->size;
+ return ret;
+}
+
+boolean cso_hash_contains(struct cso_hash *hash, unsigned key)
+{
+ struct cso_node **node = cso_hash_find_node(hash, key);
+ return (*node != hash->data.e);
+}
diff --git a/src/gallium/auxiliary/cso_cache/cso_hash.h b/src/gallium/auxiliary/cso_cache/cso_hash.h
new file mode 100644
index 0000000000..5891c325fa
--- /dev/null
+++ b/src/gallium/auxiliary/cso_cache/cso_hash.h
@@ -0,0 +1,129 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Hash table implementation.
+ *
+ * This file provides a hash implementation that is capable of dealing
+ * with collisions. It stores colliding entries in linked list. All
+ * functions operating on the hash return an iterator. The iterator
+ * itself points to the collision list. If there wasn't any collision
+ * the list will have just one entry, otherwise client code should
+ * iterate over the entries to find the exact entry among ones that
+ * had the same key (e.g. memcmp could be used on the data to check
+ * that)
+ *
+ * @author Zack Rusin <zack@tungstengraphics.com>
+ */
+
+#ifndef CSO_HASH_H
+#define CSO_HASH_H
+
+#include "pipe/p_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct cso_hash;
+struct cso_node;
+
+
+struct cso_hash_iter {
+ struct cso_hash *hash;
+ struct cso_node *node;
+};
+
+
+struct cso_hash *cso_hash_create(void);
+void cso_hash_delete(struct cso_hash *hash);
+
+
+int cso_hash_size(struct cso_hash *hash);
+
+
+/**
+ * Adds a data with the given key to the hash. If entry with the given
+ * key is already in the hash, this current entry is instered before it
+ * in the collision list.
+ * Function returns iterator pointing to the inserted item in the hash.
+ */
+struct cso_hash_iter cso_hash_insert(struct cso_hash *hash, unsigned key,
+ void *data);
+/**
+ * Removes the item pointed to by the current iterator from the hash.
+ * Note that the data itself is not erased and if it was a malloc'ed pointer
+ * it will have to be freed after calling this function by the callee.
+ * Function returns iterator pointing to the item after the removed one in
+ * the hash.
+ */
+struct cso_hash_iter cso_hash_erase(struct cso_hash *hash, struct cso_hash_iter iter);
+
+void *cso_hash_take(struct cso_hash *hash, unsigned key);
+
+
+
+struct cso_hash_iter cso_hash_first_node(struct cso_hash *hash);
+
+/**
+ * Return an iterator pointing to the first entry in the collision list.
+ */
+struct cso_hash_iter cso_hash_find(struct cso_hash *hash, unsigned key);
+
+/**
+ * Returns true if a value with the given key exists in the hash
+ */
+boolean cso_hash_contains(struct cso_hash *hash, unsigned key);
+
+
+int cso_hash_iter_is_null(struct cso_hash_iter iter);
+unsigned cso_hash_iter_key(struct cso_hash_iter iter);
+void *cso_hash_iter_data(struct cso_hash_iter iter);
+
+
+struct cso_hash_iter cso_hash_iter_next(struct cso_hash_iter iter);
+struct cso_hash_iter cso_hash_iter_prev(struct cso_hash_iter iter);
+
+
+/**
+ * Convenience routine to iterate over the collision list while doing a memory
+ * comparison to see which entry in the list is a direct copy of our template
+ * and returns that entry.
+ */
+void *cso_hash_find_data_from_template( struct cso_hash *hash,
+ unsigned hash_key,
+ void *templ,
+ int size );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile
new file mode 100644
index 0000000000..5041dcc072
--- /dev/null
+++ b/src/gallium/auxiliary/draw/Makefile
@@ -0,0 +1,46 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = draw
+
+C_SOURCES = \
+ draw_context.c \
+ draw_pipe.c \
+ draw_pipe_aaline.c \
+ draw_pipe_aapoint.c \
+ draw_pipe_clip.c \
+ draw_pipe_cull.c \
+ draw_pipe_flatshade.c \
+ draw_pipe_offset.c \
+ draw_pipe_pstipple.c \
+ draw_pipe_stipple.c \
+ draw_pipe_twoside.c \
+ draw_pipe_unfilled.c \
+ draw_pipe_util.c \
+ draw_pipe_validate.c \
+ draw_pipe_vbuf.c \
+ draw_pipe_wide_line.c \
+ draw_pipe_wide_point.c \
+ draw_pt.c \
+ draw_pt_elts.c \
+ draw_pt_emit.c \
+ draw_pt_fetch.c \
+ draw_pt_fetch_emit.c \
+ draw_pt_fetch_shade_emit.c \
+ draw_pt_fetch_shade_pipeline.c \
+ draw_pt_post_vs.c \
+ draw_pt_util.c \
+ draw_pt_varray.c \
+ draw_pt_vcache.c \
+ draw_vertex.c \
+ draw_vs.c \
+ draw_vs_varient.c \
+ draw_vs_aos.c \
+ draw_vs_aos_io.c \
+ draw_vs_aos_machine.c \
+ draw_vs_exec.c \
+ draw_vs_llvm.c \
+ draw_vs_ppc.c \
+ draw_vs_sse.c
+
+include ../../Makefile.template
diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript
new file mode 100644
index 0000000000..5f05aa324a
--- /dev/null
+++ b/src/gallium/auxiliary/draw/SConscript
@@ -0,0 +1,46 @@
+Import('*')
+
+draw = env.ConvenienceLibrary(
+ target = 'draw',
+ source = [
+ 'draw_context.c',
+ 'draw_pipe.c',
+ 'draw_pipe_aaline.c',
+ 'draw_pipe_aapoint.c',
+ 'draw_pipe_clip.c',
+ 'draw_pipe_cull.c',
+ 'draw_pipe_flatshade.c',
+ 'draw_pipe_offset.c',
+ 'draw_pipe_pstipple.c',
+ 'draw_pipe_stipple.c',
+ 'draw_pipe_twoside.c',
+ 'draw_pipe_unfilled.c',
+ 'draw_pipe_util.c',
+ 'draw_pipe_validate.c',
+ 'draw_pipe_vbuf.c',
+ 'draw_pipe_wide_line.c',
+ 'draw_pipe_wide_point.c',
+ 'draw_pt.c',
+ 'draw_pt_elts.c',
+ 'draw_pt_emit.c',
+ 'draw_pt_fetch.c',
+ 'draw_pt_fetch_emit.c',
+ 'draw_pt_fetch_shade_emit.c',
+ 'draw_pt_fetch_shade_pipeline.c',
+ 'draw_pt_post_vs.c',
+ 'draw_pt_util.c',
+ 'draw_pt_varray.c',
+ 'draw_pt_vcache.c',
+ 'draw_vertex.c',
+ 'draw_vs.c',
+ 'draw_vs_aos.c',
+ 'draw_vs_aos_io.c',
+ 'draw_vs_aos_machine.c',
+ 'draw_vs_exec.c',
+ 'draw_vs_llvm.c',
+ 'draw_vs_ppc.c',
+ 'draw_vs_sse.c',
+ 'draw_vs_varient.c'
+ ])
+
+auxiliaries.insert(0, draw)
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
new file mode 100644
index 0000000000..a4f1fcddc1
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -0,0 +1,430 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "draw_context.h"
+#include "draw_vbuf.h"
+#include "draw_vs.h"
+#include "draw_pt.h"
+#include "draw_pipe.h"
+
+
+struct draw_context *draw_create( void )
+{
+ struct draw_context *draw = CALLOC_STRUCT( draw_context );
+ if (draw == NULL)
+ goto fail;
+
+ ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 );
+ ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 );
+ ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 );
+ ASSIGN_4V( draw->plane[3], 0, 1, 0, 1 );
+ ASSIGN_4V( draw->plane[4], 0, 0, 1, 1 ); /* yes these are correct */
+ ASSIGN_4V( draw->plane[5], 0, 0, -1, 1 ); /* mesa's a bit wonky */
+ draw->nr_planes = 6;
+
+
+ draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */
+
+
+ if (!draw_pipeline_init( draw ))
+ goto fail;
+
+ if (!draw_pt_init( draw ))
+ goto fail;
+
+ if (!draw_vs_init( draw ))
+ goto fail;
+
+ return draw;
+
+fail:
+ draw_destroy( draw );
+ return NULL;
+}
+
+
+void draw_destroy( struct draw_context *draw )
+{
+ if (!draw)
+ return;
+
+
+
+ /* Not so fast -- we're just borrowing this at the moment.
+ *
+ if (draw->render)
+ draw->render->destroy( draw->render );
+ */
+
+ draw_pipeline_destroy( draw );
+ draw_pt_destroy( draw );
+ draw_vs_destroy( draw );
+
+ FREE( draw );
+}
+
+
+
+void draw_flush( struct draw_context *draw )
+{
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+}
+
+
+/**
+ * Specify the Minimum Resolvable Depth factor for polygon offset.
+ * This factor potentially depends on the number of Z buffer bits,
+ * the rasterization algorithm and the arithmetic performed on Z
+ * values between vertex shading and rasterization. It will vary
+ * from one driver to another.
+ */
+void draw_set_mrd(struct draw_context *draw, double mrd)
+{
+ draw->mrd = mrd;
+}
+
+
+/**
+ * Register new primitive rasterization/rendering state.
+ * This causes the drawing pipeline to be rebuilt.
+ */
+void draw_set_rasterizer_state( struct draw_context *draw,
+ const struct pipe_rasterizer_state *raster )
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
+ draw->rasterizer = raster;
+ draw->bypass_clipping =
+ ((draw->rasterizer && draw->rasterizer->bypass_vs_clip_and_viewport) ||
+ draw->driver.bypass_clipping);
+}
+
+
+void draw_set_driver_clipping( struct draw_context *draw,
+ boolean bypass_clipping )
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
+ draw->driver.bypass_clipping = bypass_clipping;
+ draw->bypass_clipping =
+ ((draw->rasterizer && draw->rasterizer->bypass_vs_clip_and_viewport) ||
+ draw->driver.bypass_clipping);
+}
+
+
+/**
+ * Plug in the primitive rendering/rasterization stage (which is the last
+ * stage in the drawing pipeline).
+ * This is provided by the device driver.
+ */
+void draw_set_rasterize_stage( struct draw_context *draw,
+ struct draw_stage *stage )
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
+ draw->pipeline.rasterize = stage;
+}
+
+
+/**
+ * Set the draw module's clipping state.
+ */
+void draw_set_clip_state( struct draw_context *draw,
+ const struct pipe_clip_state *clip )
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
+ assert(clip->nr <= PIPE_MAX_CLIP_PLANES);
+ memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0]));
+ draw->nr_planes = 6 + clip->nr;
+}
+
+
+/**
+ * Set the draw module's viewport state.
+ */
+void draw_set_viewport_state( struct draw_context *draw,
+ const struct pipe_viewport_state *viewport )
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw->viewport = *viewport; /* struct copy */
+ draw->identity_viewport = (viewport->scale[0] == 1.0f &&
+ viewport->scale[1] == 1.0f &&
+ viewport->scale[2] == 1.0f &&
+ viewport->scale[3] == 1.0f &&
+ viewport->translate[0] == 0.0f &&
+ viewport->translate[1] == 0.0f &&
+ viewport->translate[2] == 0.0f &&
+ viewport->translate[3] == 0.0f);
+
+ draw_vs_set_viewport( draw, viewport );
+}
+
+
+
+void
+draw_set_vertex_buffers(struct draw_context *draw,
+ unsigned count,
+ const struct pipe_vertex_buffer *buffers)
+{
+ assert(count <= PIPE_MAX_ATTRIBS);
+
+ memcpy(draw->pt.vertex_buffer, buffers, count * sizeof(buffers[0]));
+ draw->pt.nr_vertex_buffers = count;
+}
+
+
+void
+draw_set_vertex_elements(struct draw_context *draw,
+ unsigned count,
+ const struct pipe_vertex_element *elements)
+{
+ assert(count <= PIPE_MAX_ATTRIBS);
+
+ memcpy(draw->pt.vertex_element, elements, count * sizeof(elements[0]));
+ draw->pt.nr_vertex_elements = count;
+}
+
+
+/**
+ * Tell drawing context where to find mapped vertex buffers.
+ */
+void
+draw_set_mapped_vertex_buffer(struct draw_context *draw,
+ unsigned attr, const void *buffer)
+{
+ draw->pt.user.vbuffer[attr] = buffer;
+}
+
+
+void
+draw_set_mapped_constant_buffer(struct draw_context *draw,
+ const void *buffer,
+ unsigned size )
+{
+ draw->pt.user.constants = buffer;
+ draw_vs_set_constants( draw, (const float (*)[4])buffer, size );
+}
+
+
+/**
+ * Tells the draw module to draw points with triangles if their size
+ * is greater than this threshold.
+ */
+void
+draw_wide_point_threshold(struct draw_context *draw, float threshold)
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw->pipeline.wide_point_threshold = threshold;
+}
+
+
+/**
+ * Tells the draw module to draw lines with triangles if their width
+ * is greater than this threshold.
+ */
+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;
+}
+
+
+/**
+ * Tells the draw module whether or not to implement line stipple.
+ */
+void
+draw_enable_line_stipple(struct draw_context *draw, boolean enable)
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw->pipeline.line_stipple = enable;
+}
+
+
+/**
+ * Tells draw module whether to convert points to quads for sprite mode.
+ */
+void
+draw_enable_point_sprites(struct draw_context *draw, boolean enable)
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw->pipeline.point_sprite = enable;
+}
+
+
+void
+draw_set_force_passthrough( struct draw_context *draw, boolean enable )
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw->force_passthrough = enable;
+}
+
+
+/**
+ * Ask the draw module for the location/slot of the given vertex attribute in
+ * a post-transformed vertex.
+ *
+ * With this function, drivers that use the draw module should have no reason
+ * to track the current vertex shader.
+ *
+ * Note that the draw module may sometimes generate vertices with extra
+ * attributes (such as texcoords for AA lines). The driver can call this
+ * function to find those attributes.
+ *
+ * Zero is returned if the attribute is not found since this is
+ * a don't care / undefined situtation. Returning -1 would be a bit more
+ * work for the drivers.
+ */
+int
+draw_find_vs_output(const struct draw_context *draw,
+ uint semantic_name, uint semantic_index)
+{
+ const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+ uint i;
+ for (i = 0; i < vs->info.num_outputs; i++) {
+ if (vs->info.output_semantic_name[i] == semantic_name &&
+ vs->info.output_semantic_index[i] == semantic_index)
+ return i;
+ }
+
+ /* XXX there may be more than one extra vertex attrib.
+ * For example, simulated gl_FragCoord and gl_PointCoord.
+ */
+ if (draw->extra_vp_outputs.semantic_name == semantic_name &&
+ draw->extra_vp_outputs.semantic_index == semantic_index) {
+ return draw->extra_vp_outputs.slot;
+ }
+ return 0;
+}
+
+
+/**
+ * Return number of vertex shader outputs.
+ */
+uint
+draw_num_vs_outputs(const struct draw_context *draw)
+{
+ uint count = draw->vs.vertex_shader->info.num_outputs;
+ if (draw->extra_vp_outputs.slot > 0)
+ count++;
+ return count;
+}
+
+
+/**
+ * Provide TGSI sampler objects for vertex shaders that use texture fetches.
+ * This might only be used by software drivers for the time being.
+ */
+void
+draw_texture_samplers(struct draw_context *draw,
+ uint num_samplers,
+ struct tgsi_sampler **samplers)
+{
+ draw->vs.num_samplers = num_samplers;
+ draw->vs.samplers = samplers;
+}
+
+
+
+
+void draw_set_render( struct draw_context *draw,
+ struct vbuf_render *render )
+{
+ draw->render = render;
+}
+
+void draw_set_edgeflags( struct draw_context *draw,
+ const unsigned *edgeflag )
+{
+ draw->pt.user.edgeflag = edgeflag;
+}
+
+
+
+
+/**
+ * Tell the drawing context about the index/element buffer to use
+ * (ala glDrawElements)
+ * If no element buffer is to be used (i.e. glDrawArrays) then this
+ * should be called with eltSize=0 and elements=NULL.
+ *
+ * \param draw the drawing context
+ * \param eltSize size of each element (1, 2 or 4 bytes)
+ * \param elements the element buffer ptr
+ */
+void
+draw_set_mapped_element_buffer_range( struct draw_context *draw,
+ unsigned eltSize,
+ unsigned min_index,
+ unsigned max_index,
+ const void *elements )
+{
+ draw->pt.user.elts = elements;
+ draw->pt.user.eltSize = eltSize;
+ draw->pt.user.min_index = min_index;
+ draw->pt.user.max_index = max_index;
+}
+
+
+void
+draw_set_mapped_element_buffer( struct draw_context *draw,
+ unsigned eltSize,
+ const void *elements )
+{
+ draw->pt.user.elts = elements;
+ draw->pt.user.eltSize = eltSize;
+ draw->pt.user.min_index = 0;
+ draw->pt.user.max_index = 0xffffffff;
+}
+
+
+/* Revamp me please:
+ */
+void draw_do_flush( struct draw_context *draw, unsigned flags )
+{
+ if (!draw->suspend_flushing)
+ {
+ assert(!draw->flushing); /* catch inadvertant recursion */
+
+ draw->flushing = TRUE;
+
+ draw_pipeline_flush( draw, flags );
+
+ draw->reduced_prim = ~0; /* is reduced_prim needed any more? */
+
+ draw->flushing = FALSE;
+ }
+}
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
new file mode 100644
index 0000000000..d529e4e9a2
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -0,0 +1,182 @@
+
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Public interface into the drawing module.
+ */
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef DRAW_CONTEXT_H
+#define DRAW_CONTEXT_H
+
+
+#include "pipe/p_state.h"
+
+
+struct pipe_context;
+struct draw_context;
+struct draw_stage;
+struct draw_vertex_shader;
+struct tgsi_sampler;
+
+
+struct draw_context *draw_create( void );
+
+void draw_destroy( struct draw_context *draw );
+
+void draw_set_viewport_state( struct draw_context *draw,
+ const struct pipe_viewport_state *viewport );
+
+void draw_set_clip_state( struct draw_context *pipe,
+ const struct pipe_clip_state *clip );
+
+void draw_set_rasterizer_state( struct draw_context *draw,
+ const struct pipe_rasterizer_state *raster );
+
+void draw_set_rasterize_stage( struct draw_context *draw,
+ struct draw_stage *stage );
+
+void draw_wide_point_threshold(struct draw_context *draw, float threshold);
+
+void draw_wide_line_threshold(struct draw_context *draw, float threshold);
+
+void draw_enable_line_stipple(struct draw_context *draw, boolean enable);
+
+void draw_enable_point_sprites(struct draw_context *draw, boolean enable);
+
+void draw_set_mrd(struct draw_context *draw, double mrd);
+
+boolean
+draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe);
+
+boolean
+draw_install_aapoint_stage(struct draw_context *draw, struct pipe_context *pipe);
+
+boolean
+draw_install_pstipple_stage(struct draw_context *draw, struct pipe_context *pipe);
+
+
+int
+draw_find_vs_output(const struct draw_context *draw,
+ uint semantic_name, uint semantic_index);
+
+uint
+draw_num_vs_outputs(const struct draw_context *draw);
+
+
+void
+draw_texture_samplers(struct draw_context *draw,
+ uint num_samplers,
+ struct tgsi_sampler **samplers);
+
+
+
+/*
+ * Vertex shader functions
+ */
+
+struct draw_vertex_shader *
+draw_create_vertex_shader(struct draw_context *draw,
+ const struct pipe_shader_state *shader);
+void draw_bind_vertex_shader(struct draw_context *draw,
+ struct draw_vertex_shader *dvs);
+void draw_delete_vertex_shader(struct draw_context *draw,
+ struct draw_vertex_shader *dvs);
+
+
+
+/*
+ * Vertex data functions
+ */
+
+void draw_set_vertex_buffers(struct draw_context *draw,
+ unsigned count,
+ const struct pipe_vertex_buffer *buffers);
+
+void draw_set_vertex_elements(struct draw_context *draw,
+ unsigned count,
+ const struct pipe_vertex_element *elements);
+
+void
+draw_set_mapped_element_buffer_range( struct draw_context *draw,
+ unsigned eltSize,
+ unsigned min_index,
+ unsigned max_index,
+ const void *elements );
+
+void draw_set_mapped_element_buffer( struct draw_context *draw,
+ unsigned eltSize,
+ const void *elements );
+
+void draw_set_mapped_vertex_buffer(struct draw_context *draw,
+ unsigned attr, const void *buffer);
+
+void draw_set_mapped_constant_buffer(struct draw_context *draw,
+ const void *buffer,
+ unsigned size );
+
+void draw_set_edgeflags( struct draw_context *draw,
+ const unsigned *edgeflag );
+
+
+/***********************************************************************
+ * draw_prim.c
+ */
+
+void draw_arrays(struct draw_context *draw, unsigned prim,
+ unsigned start, unsigned count);
+
+void draw_flush(struct draw_context *draw);
+
+
+/*******************************************************************************
+ * Driver backend interface
+ */
+struct vbuf_render;
+void draw_set_render( struct draw_context *draw,
+ struct vbuf_render *render );
+
+void draw_set_driver_clipping( struct draw_context *draw,
+ boolean bypass_clipping );
+
+void draw_set_force_passthrough( struct draw_context *draw,
+ boolean enable );
+
+/*******************************************************************************
+ * Draw pipeline
+ */
+boolean draw_need_pipeline(const struct draw_context *draw,
+ const struct pipe_rasterizer_state *rasterizer,
+ unsigned prim );
+
+
+
+#endif /* DRAW_CONTEXT_H */
diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
new file mode 100644
index 0000000000..1c6d657297
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe.c
@@ -0,0 +1,319 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "draw/draw_private.h"
+#include "draw/draw_pipe.h"
+
+
+
+boolean draw_pipeline_init( struct draw_context *draw )
+{
+ /* create pipeline stages */
+ draw->pipeline.wide_line = draw_wide_line_stage( draw );
+ draw->pipeline.wide_point = draw_wide_point_stage( draw );
+ draw->pipeline.stipple = draw_stipple_stage( draw );
+ draw->pipeline.unfilled = draw_unfilled_stage( draw );
+ draw->pipeline.twoside = draw_twoside_stage( draw );
+ draw->pipeline.offset = draw_offset_stage( draw );
+ draw->pipeline.clip = draw_clip_stage( draw );
+ draw->pipeline.flatshade = draw_flatshade_stage( draw );
+ draw->pipeline.cull = draw_cull_stage( draw );
+ draw->pipeline.validate = draw_validate_stage( draw );
+ draw->pipeline.first = draw->pipeline.validate;
+
+ if (!draw->pipeline.wide_line ||
+ !draw->pipeline.wide_point ||
+ !draw->pipeline.stipple ||
+ !draw->pipeline.unfilled ||
+ !draw->pipeline.twoside ||
+ !draw->pipeline.offset ||
+ !draw->pipeline.clip ||
+ !draw->pipeline.flatshade ||
+ !draw->pipeline.cull ||
+ !draw->pipeline.validate)
+ 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.line_stipple = TRUE;
+ draw->pipeline.point_sprite = TRUE;
+
+ return TRUE;
+}
+
+
+void draw_pipeline_destroy( struct draw_context *draw )
+{
+ if (draw->pipeline.wide_line)
+ draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
+ if (draw->pipeline.wide_point)
+ draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
+ if (draw->pipeline.stipple)
+ draw->pipeline.stipple->destroy( draw->pipeline.stipple );
+ if (draw->pipeline.unfilled)
+ draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
+ if (draw->pipeline.twoside)
+ draw->pipeline.twoside->destroy( draw->pipeline.twoside );
+ if (draw->pipeline.offset)
+ draw->pipeline.offset->destroy( draw->pipeline.offset );
+ if (draw->pipeline.clip)
+ draw->pipeline.clip->destroy( draw->pipeline.clip );
+ if (draw->pipeline.flatshade)
+ draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
+ if (draw->pipeline.cull)
+ draw->pipeline.cull->destroy( draw->pipeline.cull );
+ if (draw->pipeline.validate)
+ draw->pipeline.validate->destroy( draw->pipeline.validate );
+ if (draw->pipeline.aaline)
+ draw->pipeline.aaline->destroy( draw->pipeline.aaline );
+ if (draw->pipeline.aapoint)
+ draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );
+ if (draw->pipeline.pstipple)
+ draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );
+ if (draw->pipeline.rasterize)
+ draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
+}
+
+
+
+
+
+
+
+static void do_point( struct draw_context *draw,
+ const char *v0 )
+{
+ struct prim_header prim;
+
+ prim.flags = 0;
+ prim.pad = 0;
+ prim.v[0] = (struct vertex_header *)v0;
+
+ draw->pipeline.first->point( draw->pipeline.first, &prim );
+}
+
+
+static void do_line( struct draw_context *draw,
+ ushort flags,
+ const char *v0,
+ const char *v1 )
+{
+ struct prim_header prim;
+
+ prim.flags = flags;
+ prim.pad = 0;
+ prim.v[0] = (struct vertex_header *)v0;
+ prim.v[1] = (struct vertex_header *)v1;
+
+ draw->pipeline.first->line( draw->pipeline.first, &prim );
+}
+
+
+static void do_triangle( struct draw_context *draw,
+ ushort flags,
+ char *v0,
+ char *v1,
+ char *v2 )
+{
+ struct prim_header prim;
+
+ prim.v[0] = (struct vertex_header *)v0;
+ prim.v[1] = (struct vertex_header *)v1;
+ prim.v[2] = (struct vertex_header *)v2;
+ prim.flags = flags;
+ prim.pad = 0;
+
+ draw->pipeline.first->tri( draw->pipeline.first, &prim );
+}
+
+
+
+#define QUAD(i0,i1,i2,i3) \
+ do_triangle( draw, \
+ ( DRAW_PIPE_RESET_STIPPLE | \
+ DRAW_PIPE_EDGE_FLAG_0 | \
+ DRAW_PIPE_EDGE_FLAG_2 ), \
+ verts + stride * elts[i0], \
+ verts + stride * elts[i1], \
+ verts + stride * elts[i3]); \
+ do_triangle( draw, \
+ ( DRAW_PIPE_EDGE_FLAG_0 | \
+ DRAW_PIPE_EDGE_FLAG_1 ), \
+ verts + stride * elts[i1], \
+ verts + stride * elts[i2], \
+ verts + stride * elts[i3])
+
+#define TRIANGLE(flags,i0,i1,i2) \
+ do_triangle( draw, \
+ elts[i0], /* flags */ \
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * elts[i1], \
+ verts + stride * elts[i2])
+
+#define LINE(flags,i0,i1) \
+ do_line( draw, \
+ elts[i0], \
+ verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * elts[i1])
+
+#define POINT(i0) \
+ do_point( draw, \
+ verts + stride * elts[i0] )
+
+#define FUNC pipe_run
+#define ARGS \
+ struct draw_context *draw, \
+ unsigned prim, \
+ struct vertex_header *vertices, \
+ unsigned stride, \
+ const ushort *elts
+
+#define LOCAL_VARS \
+ char *verts = (char *)vertices; \
+ boolean flatfirst = (draw->rasterizer->flatshade && \
+ draw->rasterizer->flatshade_first); \
+ unsigned i; \
+ ushort flags
+
+#define FLUSH
+
+#include "draw_pt_decompose.h"
+#undef ARGS
+#undef LOCAL_VARS
+
+
+
+/* Code to run the pipeline on a fairly arbitary collection of vertices.
+ *
+ * Vertex headers must be pre-initialized with the
+ * UNDEFINED_VERTEX_ID, this code will cause that id to become
+ * overwritten, so it may have to be reset if there is the intention
+ * to reuse the vertices.
+ *
+ * This code provides a callback to reset the vertex id's which the
+ * draw_vbuf.c code uses when it has to perform a flush.
+ */
+void draw_pipeline_run( struct draw_context *draw,
+ unsigned prim,
+ struct vertex_header *vertices,
+ unsigned vertex_count,
+ unsigned stride,
+ const ushort *elts,
+ unsigned count )
+{
+ char *verts = (char *)vertices;
+
+ draw->pipeline.verts = verts;
+ draw->pipeline.vertex_stride = stride;
+ draw->pipeline.vertex_count = vertex_count;
+
+ pipe_run(draw, prim, vertices, stride, elts, count);
+
+ draw->pipeline.verts = NULL;
+ draw->pipeline.vertex_count = 0;
+}
+
+#define QUAD(i0,i1,i2,i3) \
+ do_triangle( draw, \
+ ( DRAW_PIPE_RESET_STIPPLE | \
+ DRAW_PIPE_EDGE_FLAG_0 | \
+ DRAW_PIPE_EDGE_FLAG_2 ), \
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i1), \
+ verts + stride * (i3)); \
+ do_triangle( draw, \
+ ( DRAW_PIPE_EDGE_FLAG_0 | \
+ DRAW_PIPE_EDGE_FLAG_1 ), \
+ verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i2), \
+ verts + stride * (i3))
+
+#define TRIANGLE(flags,i0,i1,i2) \
+ do_triangle( draw, \
+ flags, /* flags */ \
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i1), \
+ verts + stride * (i2))
+
+#define LINE(flags,i0,i1) \
+ do_line( draw, \
+ flags, \
+ verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
+ verts + stride * (i1))
+
+#define POINT(i0) \
+ do_point( draw, \
+ verts + stride * i0 )
+
+#define FUNC pipe_run_linear
+#define ARGS \
+ struct draw_context *draw, \
+ unsigned prim, \
+ struct vertex_header *vertices, \
+ unsigned stride
+
+#define LOCAL_VARS \
+ char *verts = (char *)vertices; \
+ boolean flatfirst = (draw->rasterizer->flatshade && \
+ draw->rasterizer->flatshade_first); \
+ unsigned i; \
+ ushort flags
+
+#define FLUSH
+
+#include "draw_pt_decompose.h"
+
+void draw_pipeline_run_linear( struct draw_context *draw,
+ unsigned prim,
+ struct vertex_header *vertices,
+ unsigned count,
+ unsigned stride )
+{
+ char *verts = (char *)vertices;
+ draw->pipeline.verts = verts;
+ draw->pipeline.vertex_stride = stride;
+ draw->pipeline.vertex_count = count;
+
+ pipe_run_linear(draw, prim, vertices, stride, count);
+
+ draw->pipeline.verts = NULL;
+ draw->pipeline.vertex_count = 0;
+}
+
+
+void draw_pipeline_flush( struct draw_context *draw,
+ unsigned flags )
+{
+ draw->pipeline.first->flush( draw->pipeline.first, flags );
+ draw->pipeline.first = draw->pipeline.validate;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe.h b/src/gallium/auxiliary/draw/draw_pipe.h
new file mode 100644
index 0000000000..479250729f
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe.h
@@ -0,0 +1,126 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef DRAW_PIPE_H
+#define DRAW_PIPE_H
+
+#include "pipe/p_compiler.h"
+#include "draw_private.h" /* for sizeof(vertex_header) */
+
+
+/**
+ * Basic info for a point/line/triangle primitive.
+ */
+struct prim_header {
+ float det; /**< front/back face determinant */
+ ushort flags;
+ ushort pad;
+ struct vertex_header *v[3]; /**< 1 to 3 vertex pointers */
+};
+
+
+
+/**
+ * Base class for all primitive drawing stages.
+ */
+struct draw_stage
+{
+ struct draw_context *draw; /**< parent context */
+
+ struct draw_stage *next; /**< next stage in pipeline */
+ const char *name; /**< for debugging */
+
+ struct vertex_header **tmp; /**< temp vert storage, such as for clipping */
+ unsigned nr_tmps;
+
+ void (*point)( struct draw_stage *,
+ struct prim_header * );
+
+ void (*line)( struct draw_stage *,
+ struct prim_header * );
+
+ void (*tri)( struct draw_stage *,
+ struct prim_header * );
+
+ void (*flush)( struct draw_stage *,
+ unsigned flags );
+
+ void (*reset_stipple_counter)( struct draw_stage * );
+
+ void (*destroy)( struct draw_stage * );
+};
+
+
+extern struct draw_stage *draw_unfilled_stage( struct draw_context *context );
+extern struct draw_stage *draw_twoside_stage( struct draw_context *context );
+extern struct draw_stage *draw_offset_stage( struct draw_context *context );
+extern struct draw_stage *draw_clip_stage( struct draw_context *context );
+extern struct draw_stage *draw_flatshade_stage( struct draw_context *context );
+extern struct draw_stage *draw_cull_stage( struct draw_context *context );
+extern struct draw_stage *draw_stipple_stage( struct draw_context *context );
+extern struct draw_stage *draw_wide_line_stage( struct draw_context *context );
+extern struct draw_stage *draw_wide_point_stage( struct draw_context *context );
+extern struct draw_stage *draw_validate_stage( struct draw_context *context );
+
+
+extern void draw_free_temp_verts( struct draw_stage *stage );
+extern boolean draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr );
+
+extern void draw_reset_vertex_ids( struct draw_context *draw );
+
+void draw_pipe_passthrough_tri(struct draw_stage *stage, struct prim_header *header);
+void draw_pipe_passthrough_line(struct draw_stage *stage, struct prim_header *header);
+void draw_pipe_passthrough_point(struct draw_stage *stage, struct prim_header *header);
+
+
+
+/**
+ * Get a writeable copy of a vertex.
+ * \param stage drawing stage info
+ * \param vert the vertex to copy (source)
+ * \param idx index into stage's tmp[] array to put the copy (dest)
+ * \return pointer to the copied vertex
+ */
+static INLINE struct vertex_header *
+dup_vert( struct draw_stage *stage,
+ const struct vertex_header *vert,
+ unsigned idx )
+{
+ struct vertex_header *tmp = stage->tmp[idx];
+ const uint vsize = sizeof(struct vertex_header)
+ + stage->draw->vs.num_vs_outputs * 4 * sizeof(float);
+ memcpy(tmp, vert, vsize);
+ tmp->vertex_id = UNDEFINED_VERTEX_ID;
+ return tmp;
+}
+
+#endif
diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
new file mode 100644
index 0000000000..9f956715a2
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
@@ -0,0 +1,921 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * AA line stage: AA lines are converted to texture mapped triangles.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "tgsi/tgsi_transform.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "draw_context.h"
+#include "draw_private.h"
+#include "draw_pipe.h"
+
+
+/**
+ * Max texture level for the alpha texture used for antialiasing
+ */
+#define MAX_TEXTURE_LEVEL 5 /* 32 x 32 */
+
+
+/**
+ * Subclass of pipe_shader_state to carry extra fragment shader info.
+ */
+struct aaline_fragment_shader
+{
+ struct pipe_shader_state state;
+ void *driver_fs;
+ void *aaline_fs;
+ uint sampler_unit;
+ int generic_attrib; /**< texcoord/generic used for texture */
+};
+
+
+/**
+ * Subclass of draw_stage
+ */
+struct aaline_stage
+{
+ struct draw_stage stage;
+
+ float half_line_width;
+
+ /** For AA lines, this is the vertex attrib slot for the new texcoords */
+ uint tex_slot;
+ /** position, not necessarily output zero */
+ uint pos_slot;
+
+ void *sampler_cso;
+ struct pipe_texture *texture;
+ uint num_samplers;
+ uint num_textures;
+
+
+ /*
+ * Currently bound state
+ */
+ struct aaline_fragment_shader *fs;
+ struct {
+ void *sampler[PIPE_MAX_SAMPLERS];
+ struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
+ } state;
+
+ /*
+ * Driver interface/override functions
+ */
+ void * (*driver_create_fs_state)(struct pipe_context *,
+ const struct pipe_shader_state *);
+ void (*driver_bind_fs_state)(struct pipe_context *, void *);
+ void (*driver_delete_fs_state)(struct pipe_context *, void *);
+
+ void (*driver_bind_sampler_states)(struct pipe_context *, unsigned,
+ void **);
+ void (*driver_set_sampler_textures)(struct pipe_context *, unsigned,
+ struct pipe_texture **);
+
+ struct pipe_context *pipe;
+};
+
+
+
+/**
+ * Subclass of tgsi_transform_context, used for transforming the
+ * user's fragment shader to add the special AA instructions.
+ */
+struct aa_transform_context {
+ struct tgsi_transform_context base;
+ uint tempsUsed; /**< bitmask */
+ int colorOutput; /**< which output is the primary color */
+ uint samplersUsed; /**< bitfield of samplers used */
+ int freeSampler; /** an available sampler for the pstipple */
+ int maxInput, maxGeneric; /**< max input index found */
+ int colorTemp, texTemp; /**< temp registers */
+ boolean firstInstruction;
+};
+
+
+/**
+ * TGSI declaration transform callback.
+ * Look for a free sampler, a free input attrib, and two free temp regs.
+ */
+static void
+aa_transform_decl(struct tgsi_transform_context *ctx,
+ struct tgsi_full_declaration *decl)
+{
+ struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
+
+ if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
+ decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR &&
+ decl->Semantic.SemanticIndex == 0) {
+ aactx->colorOutput = decl->DeclarationRange.First;
+ }
+ else if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
+ uint i;
+ for (i = decl->DeclarationRange.First;
+ i <= decl->DeclarationRange.Last; i++) {
+ aactx->samplersUsed |= 1 << i;
+ }
+ }
+ else if (decl->Declaration.File == TGSI_FILE_INPUT) {
+ if ((int) decl->DeclarationRange.Last > aactx->maxInput)
+ aactx->maxInput = decl->DeclarationRange.Last;
+ if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC &&
+ (int) decl->Semantic.SemanticIndex > aactx->maxGeneric) {
+ aactx->maxGeneric = decl->Semantic.SemanticIndex;
+ }
+ }
+ else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
+ uint i;
+ for (i = decl->DeclarationRange.First;
+ i <= decl->DeclarationRange.Last; i++) {
+ aactx->tempsUsed |= (1 << i);
+ }
+ }
+
+ ctx->emit_declaration(ctx, decl);
+}
+
+
+/**
+ * Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
+ */
+static int
+free_bit(uint bitfield)
+{
+ int i;
+ for (i = 0; i < 32; i++) {
+ if ((bitfield & (1 << i)) == 0)
+ return i;
+ }
+ return -1;
+}
+
+
+/**
+ * TGSI instruction transform callback.
+ * Replace writes to result.color w/ a temp reg.
+ * Upon END instruction, insert texture sampling code for antialiasing.
+ */
+static void
+aa_transform_inst(struct tgsi_transform_context *ctx,
+ struct tgsi_full_instruction *inst)
+{
+ struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
+
+ if (aactx->firstInstruction) {
+ /* emit our new declarations before the first instruction */
+
+ struct tgsi_full_declaration decl;
+ uint i;
+
+ /* find free sampler */
+ aactx->freeSampler = free_bit(aactx->samplersUsed);
+ if (aactx->freeSampler >= PIPE_MAX_SAMPLERS)
+ aactx->freeSampler = PIPE_MAX_SAMPLERS - 1;
+
+ /* find two free temp regs */
+ for (i = 0; i < 32; i++) {
+ if ((aactx->tempsUsed & (1 << i)) == 0) {
+ /* found a free temp */
+ if (aactx->colorTemp < 0)
+ aactx->colorTemp = i;
+ else if (aactx->texTemp < 0)
+ aactx->texTemp = i;
+ else
+ break;
+ }
+ }
+ assert(aactx->colorTemp >= 0);
+ assert(aactx->texTemp >= 0);
+
+ /* declare new generic input/texcoord */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ /* XXX this could be linear... */
+ decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+ decl.Semantic.SemanticIndex = aactx->maxGeneric + 1;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = aactx->maxInput + 1;
+ ctx->emit_declaration(ctx, &decl);
+
+ /* declare new sampler */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = aactx->freeSampler;
+ ctx->emit_declaration(ctx, &decl);
+
+ /* declare new temp regs */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = aactx->texTemp;
+ ctx->emit_declaration(ctx, &decl);
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = aactx->colorTemp;
+ ctx->emit_declaration(ctx, &decl);
+
+ aactx->firstInstruction = FALSE;
+ }
+
+ if (inst->Instruction.Opcode == TGSI_OPCODE_END &&
+ aactx->colorOutput != -1) {
+ struct tgsi_full_instruction newInst;
+
+ /* TEX */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = aactx->texTemp;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->maxInput + 1;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->freeSampler;
+
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* MOV rgb */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_MOV;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+ newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XYZ;
+ newInst.Instruction.NumSrcRegs = 1;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* MUL alpha */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+ newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->texTemp;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* END */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_END;
+ newInst.Instruction.NumDstRegs = 0;
+ newInst.Instruction.NumSrcRegs = 0;
+ ctx->emit_instruction(ctx, &newInst);
+ }
+ else {
+ /* Not an END instruction.
+ * Look for writes to result.color and replace with colorTemp reg.
+ */
+ uint i;
+
+ for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
+ struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
+ if (dst->DstRegister.File == TGSI_FILE_OUTPUT &&
+ dst->DstRegister.Index == aactx->colorOutput) {
+ dst->DstRegister.File = TGSI_FILE_TEMPORARY;
+ dst->DstRegister.Index = aactx->colorTemp;
+ }
+ }
+
+ ctx->emit_instruction(ctx, inst);
+ }
+}
+
+
+/**
+ * Generate the frag shader we'll use for drawing AA lines.
+ * This will be the user's shader plus some texture/modulate instructions.
+ */
+static boolean
+generate_aaline_fs(struct aaline_stage *aaline)
+{
+ const struct pipe_shader_state *orig_fs = &aaline->fs->state;
+ struct pipe_shader_state aaline_fs;
+ struct aa_transform_context transform;
+
+#define MAX 1000
+
+ aaline_fs = *orig_fs; /* copy to init */
+ aaline_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
+ if (aaline_fs.tokens == NULL)
+ return FALSE;
+
+ memset(&transform, 0, sizeof(transform));
+ transform.colorOutput = -1;
+ transform.maxInput = -1;
+ transform.maxGeneric = -1;
+ transform.colorTemp = -1;
+ transform.texTemp = -1;
+ transform.firstInstruction = TRUE;
+ transform.base.transform_instruction = aa_transform_inst;
+ transform.base.transform_declaration = aa_transform_decl;
+
+ tgsi_transform_shader(orig_fs->tokens,
+ (struct tgsi_token *) aaline_fs.tokens,
+ MAX, &transform.base);
+
+#if 0 /* DEBUG */
+ tgsi_dump(orig_fs->tokens, 0);
+ tgsi_dump(aaline_fs.tokens, 0);
+#endif
+
+ aaline->fs->sampler_unit = transform.freeSampler;
+
+ aaline->fs->aaline_fs
+ = aaline->driver_create_fs_state(aaline->pipe, &aaline_fs);
+ if (aaline->fs->aaline_fs == NULL)
+ goto fail;
+
+ aaline->fs->generic_attrib = transform.maxGeneric + 1;
+ FREE((void *)aaline_fs.tokens);
+ return TRUE;
+
+fail:
+ FREE((void *)aaline_fs.tokens);
+ return FALSE;
+}
+
+
+/**
+ * Create the texture map we'll use for antialiasing the lines.
+ */
+static boolean
+aaline_create_texture(struct aaline_stage *aaline)
+{
+ struct pipe_context *pipe = aaline->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture texTemp;
+ uint level;
+
+ memset(&texTemp, 0, sizeof(texTemp));
+ texTemp.target = PIPE_TEXTURE_2D;
+ texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
+ texTemp.last_level = MAX_TEXTURE_LEVEL;
+ texTemp.width[0] = 1 << MAX_TEXTURE_LEVEL;
+ texTemp.height[0] = 1 << MAX_TEXTURE_LEVEL;
+ texTemp.depth[0] = 1;
+ pf_get_block(texTemp.format, &texTemp.block);
+
+ aaline->texture = screen->texture_create(screen, &texTemp);
+ if (!aaline->texture)
+ return FALSE;
+
+ /* Fill in mipmap images.
+ * Basically each level is solid opaque, except for the outermost
+ * texels which are zero. Special case the 1x1 and 2x2 levels.
+ */
+ for (level = 0; level <= MAX_TEXTURE_LEVEL; level++) {
+ struct pipe_transfer *transfer;
+ const uint size = aaline->texture->width[level];
+ ubyte *data;
+ uint i, j;
+
+ assert(aaline->texture->width[level] == aaline->texture->height[level]);
+
+ /* This texture is new, no need to flush.
+ */
+ transfer = screen->get_tex_transfer(screen, aaline->texture, 0, level, 0,
+ PIPE_TRANSFER_WRITE, 0, 0, size, size);
+ data = screen->transfer_map(screen, transfer);
+ if (data == NULL)
+ return FALSE;
+
+ for (i = 0; i < size; i++) {
+ for (j = 0; j < size; j++) {
+ ubyte d;
+ if (size == 1) {
+ d = 255;
+ }
+ else if (size == 2) {
+ d = 200; /* tuneable */
+ }
+ else if (i == 0 || j == 0 || i == size - 1 || j == size - 1) {
+ d = 0;
+ }
+ else {
+ d = 255;
+ }
+ data[i * transfer->stride + j] = d;
+ }
+ }
+
+ /* unmap */
+ screen->transfer_unmap(screen, transfer);
+ screen->tex_transfer_destroy(transfer);
+ }
+ return TRUE;
+}
+
+
+/**
+ * Create the sampler CSO that'll be used for antialiasing.
+ * By using a mipmapped texture, we don't have to generate a different
+ * texture image for each line size.
+ */
+static boolean
+aaline_create_sampler(struct aaline_stage *aaline)
+{
+ struct pipe_sampler_state sampler;
+ struct pipe_context *pipe = aaline->pipe;
+
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR;
+ sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.normalized_coords = 1;
+ sampler.min_lod = 0.0f;
+ sampler.max_lod = MAX_TEXTURE_LEVEL;
+
+ aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
+ if (aaline->sampler_cso == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * When we're about to draw our first AA line in a batch, this function is
+ * called to tell the driver to bind our modified fragment shader.
+ */
+static boolean
+bind_aaline_fragment_shader(struct aaline_stage *aaline)
+{
+ struct draw_context *draw = aaline->stage.draw;
+
+ if (!aaline->fs->aaline_fs &&
+ !generate_aaline_fs(aaline))
+ return FALSE;
+
+ draw->suspend_flushing = TRUE;
+ aaline->driver_bind_fs_state(aaline->pipe, aaline->fs->aaline_fs);
+ draw->suspend_flushing = FALSE;
+
+ return TRUE;
+}
+
+
+
+static INLINE struct aaline_stage *
+aaline_stage( struct draw_stage *stage )
+{
+ return (struct aaline_stage *) stage;
+}
+
+
+/**
+ * Draw a wide line by drawing a quad, using geometry which will
+ * fullfill GL's antialiased line requirements.
+ */
+static void
+aaline_line(struct draw_stage *stage, struct prim_header *header)
+{
+ const struct aaline_stage *aaline = aaline_stage(stage);
+ const float half_width = aaline->half_line_width;
+ struct prim_header tri;
+ struct vertex_header *v[8];
+ uint texPos = aaline->tex_slot;
+ uint posPos = aaline->pos_slot;
+ float *pos, *tex;
+ float dx = header->v[1]->data[posPos][0] - header->v[0]->data[posPos][0];
+ float dy = header->v[1]->data[posPos][1] - header->v[0]->data[posPos][1];
+ double a = atan2(dy, dx);
+ float c_a = (float) cos(a), s_a = (float) sin(a);
+ uint i;
+
+ /* XXX the ends of lines aren't quite perfect yet, but probably passable */
+ dx = 0.5F * half_width;
+ dy = half_width;
+
+ /* allocate/dup new verts */
+ for (i = 0; i < 8; i++) {
+ v[i] = dup_vert(stage, header->v[i/4], i);
+ }
+
+ /*
+ * Quad strip for line from v0 to v1 (*=endpoints):
+ *
+ * 1 3 5 7
+ * +---+---------------------+---+
+ * | |
+ * | *v0 v1* |
+ * | |
+ * +---+---------------------+---+
+ * 0 2 4 6
+ */
+
+ /* new verts */
+ pos = v[0]->data[posPos];
+ pos[0] += (-dx * c_a - dy * s_a);
+ pos[1] += (-dx * s_a + dy * c_a);
+
+ pos = v[1]->data[posPos];
+ pos[0] += (-dx * c_a - -dy * s_a);
+ pos[1] += (-dx * s_a + -dy * c_a);
+
+ pos = v[2]->data[posPos];
+ pos[0] += ( dx * c_a - dy * s_a);
+ pos[1] += ( dx * s_a + dy * c_a);
+
+ pos = v[3]->data[posPos];
+ pos[0] += ( dx * c_a - -dy * s_a);
+ pos[1] += ( dx * s_a + -dy * c_a);
+
+ pos = v[4]->data[posPos];
+ pos[0] += (-dx * c_a - dy * s_a);
+ pos[1] += (-dx * s_a + dy * c_a);
+
+ pos = v[5]->data[posPos];
+ pos[0] += (-dx * c_a - -dy * s_a);
+ pos[1] += (-dx * s_a + -dy * c_a);
+
+ pos = v[6]->data[posPos];
+ pos[0] += ( dx * c_a - dy * s_a);
+ pos[1] += ( dx * s_a + dy * c_a);
+
+ pos = v[7]->data[posPos];
+ pos[0] += ( dx * c_a - -dy * s_a);
+ pos[1] += ( dx * s_a + -dy * c_a);
+
+ /* new texcoords */
+ tex = v[0]->data[texPos];
+ ASSIGN_4V(tex, 0, 0, 0, 1);
+
+ tex = v[1]->data[texPos];
+ ASSIGN_4V(tex, 0, 1, 0, 1);
+
+ tex = v[2]->data[texPos];
+ ASSIGN_4V(tex, .5, 0, 0, 1);
+
+ tex = v[3]->data[texPos];
+ ASSIGN_4V(tex, .5, 1, 0, 1);
+
+ tex = v[4]->data[texPos];
+ ASSIGN_4V(tex, .5, 0, 0, 1);
+
+ tex = v[5]->data[texPos];
+ ASSIGN_4V(tex, .5, 1, 0, 1);
+
+ tex = v[6]->data[texPos];
+ ASSIGN_4V(tex, 1, 0, 0, 1);
+
+ tex = v[7]->data[texPos];
+ ASSIGN_4V(tex, 1, 1, 0, 1);
+
+ /* emit 6 tris for the quad strip */
+ tri.v[0] = v[2]; tri.v[1] = v[1]; tri.v[2] = v[0];
+ stage->next->tri( stage->next, &tri );
+
+ tri.v[0] = v[3]; tri.v[1] = v[1]; tri.v[2] = v[2];
+ stage->next->tri( stage->next, &tri );
+
+ tri.v[0] = v[4]; tri.v[1] = v[3]; tri.v[2] = v[2];
+ stage->next->tri( stage->next, &tri );
+
+ tri.v[0] = v[5]; tri.v[1] = v[3]; tri.v[2] = v[4];
+ stage->next->tri( stage->next, &tri );
+
+ tri.v[0] = v[6]; tri.v[1] = v[5]; tri.v[2] = v[4];
+ stage->next->tri( stage->next, &tri );
+
+ tri.v[0] = v[7]; tri.v[1] = v[5]; tri.v[2] = v[6];
+ stage->next->tri( stage->next, &tri );
+}
+
+
+static void
+aaline_first_line(struct draw_stage *stage, struct prim_header *header)
+{
+ auto struct aaline_stage *aaline = aaline_stage(stage);
+ struct draw_context *draw = stage->draw;
+ struct pipe_context *pipe = aaline->pipe;
+ uint num_samplers;
+
+ assert(draw->rasterizer->line_smooth);
+
+ if (draw->rasterizer->line_width <= 3.0)
+ aaline->half_line_width = 1.5f;
+ else
+ aaline->half_line_width = 0.5f * draw->rasterizer->line_width;
+
+ /*
+ * Bind (generate) our fragprog, sampler and texture
+ */
+ if (!bind_aaline_fragment_shader(aaline)) {
+ stage->line = draw_pipe_passthrough_line;
+ stage->line(stage, header);
+ return;
+ }
+
+ /* update vertex attrib info */
+ aaline->tex_slot = draw->vs.num_vs_outputs;
+ aaline->pos_slot = draw->vs.position_output;
+
+ /* advertise the extra post-transformed vertex attribute */
+ draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
+ draw->extra_vp_outputs.semantic_index = aaline->fs->generic_attrib;
+ draw->extra_vp_outputs.slot = aaline->tex_slot;
+
+ /* how many samplers? */
+ /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
+ num_samplers = MAX2(aaline->num_textures, aaline->num_samplers);
+ num_samplers = MAX2(num_samplers, aaline->fs->sampler_unit + 1);
+
+ aaline->state.sampler[aaline->fs->sampler_unit] = aaline->sampler_cso;
+ pipe_texture_reference(&aaline->state.texture[aaline->fs->sampler_unit],
+ aaline->texture);
+
+ draw->suspend_flushing = TRUE;
+ aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler);
+ aaline->driver_set_sampler_textures(pipe, num_samplers, aaline->state.texture);
+ draw->suspend_flushing = FALSE;
+
+ /* now really draw first line */
+ stage->line = aaline_line;
+ stage->line(stage, header);
+}
+
+
+static void
+aaline_flush(struct draw_stage *stage, unsigned flags)
+{
+ struct draw_context *draw = stage->draw;
+ struct aaline_stage *aaline = aaline_stage(stage);
+ struct pipe_context *pipe = aaline->pipe;
+
+ stage->line = aaline_first_line;
+ stage->next->flush( stage->next, flags );
+
+ /* restore original frag shader, texture, sampler state */
+ draw->suspend_flushing = TRUE;
+ aaline->driver_bind_fs_state(pipe, aaline->fs->driver_fs);
+ aaline->driver_bind_sampler_states(pipe, aaline->num_samplers,
+ aaline->state.sampler);
+ aaline->driver_set_sampler_textures(pipe, aaline->num_textures,
+ aaline->state.texture);
+ draw->suspend_flushing = FALSE;
+
+ draw->extra_vp_outputs.slot = 0;
+}
+
+
+static void
+aaline_reset_stipple_counter(struct draw_stage *stage)
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void
+aaline_destroy(struct draw_stage *stage)
+{
+ struct aaline_stage *aaline = aaline_stage(stage);
+ uint i;
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ pipe_texture_reference(&aaline->state.texture[i], NULL);
+ }
+
+ if (aaline->sampler_cso)
+ aaline->pipe->delete_sampler_state(aaline->pipe, aaline->sampler_cso);
+
+ if (aaline->texture)
+ pipe_texture_reference(&aaline->texture, NULL);
+
+ draw_free_temp_verts( stage );
+
+ FREE( stage );
+}
+
+
+static struct aaline_stage *
+draw_aaline_stage(struct draw_context *draw)
+{
+ struct aaline_stage *aaline = CALLOC_STRUCT(aaline_stage);
+ if (aaline == NULL)
+ return NULL;
+
+ if (!draw_alloc_temp_verts( &aaline->stage, 8 ))
+ goto fail;
+
+ aaline->stage.draw = draw;
+ aaline->stage.name = "aaline";
+ aaline->stage.next = NULL;
+ aaline->stage.point = draw_pipe_passthrough_point;
+ aaline->stage.line = aaline_first_line;
+ aaline->stage.tri = draw_pipe_passthrough_tri;
+ aaline->stage.flush = aaline_flush;
+ aaline->stage.reset_stipple_counter = aaline_reset_stipple_counter;
+ aaline->stage.destroy = aaline_destroy;
+
+ return aaline;
+
+ fail:
+ if (aaline)
+ aaline_destroy(&aaline->stage);
+
+ return NULL;
+}
+
+
+static struct aaline_stage *
+aaline_stage_from_pipe(struct pipe_context *pipe)
+{
+ struct draw_context *draw = (struct draw_context *) pipe->draw;
+ return aaline_stage(draw->pipeline.aaline);
+}
+
+
+/**
+ * This function overrides the driver's create_fs_state() function and
+ * will typically be called by the state tracker.
+ */
+static void *
+aaline_create_fs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *fs)
+{
+ struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
+ struct aaline_fragment_shader *aafs = CALLOC_STRUCT(aaline_fragment_shader);
+ if (aafs == NULL)
+ return NULL;
+
+ aafs->state = *fs;
+
+ /* pass-through */
+ aafs->driver_fs = aaline->driver_create_fs_state(aaline->pipe, fs);
+
+ return aafs;
+}
+
+
+static void
+aaline_bind_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
+ struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
+
+ /* save current */
+ aaline->fs = aafs;
+ /* pass-through */
+ aaline->driver_bind_fs_state(aaline->pipe,
+ (aafs ? aafs->driver_fs : NULL));
+}
+
+
+static void
+aaline_delete_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
+ struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
+ /* pass-through */
+ aaline->driver_delete_fs_state(aaline->pipe, aafs->driver_fs);
+
+ if (aafs->aaline_fs)
+ aaline->driver_delete_fs_state(aaline->pipe, aafs->aaline_fs);
+
+ FREE(aafs);
+}
+
+
+static void
+aaline_bind_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **sampler)
+{
+ struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
+
+ /* save current */
+ memcpy(aaline->state.sampler, sampler, num * sizeof(void *));
+ aaline->num_samplers = num;
+
+ /* pass-through */
+ aaline->driver_bind_sampler_states(aaline->pipe, num, sampler);
+}
+
+
+static void
+aaline_set_sampler_textures(struct pipe_context *pipe,
+ unsigned num, struct pipe_texture **texture)
+{
+ struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
+ uint i;
+
+ /* save current */
+ for (i = 0; i < num; i++) {
+ pipe_texture_reference(&aaline->state.texture[i], texture[i]);
+ }
+ for ( ; i < PIPE_MAX_SAMPLERS; i++) {
+ pipe_texture_reference(&aaline->state.texture[i], NULL);
+ }
+ aaline->num_textures = num;
+
+ /* pass-through */
+ aaline->driver_set_sampler_textures(aaline->pipe, num, texture);
+}
+
+
+/**
+ * Called by drivers that want to install this AA line prim stage
+ * into the draw module's pipeline. This will not be used if the
+ * hardware has native support for AA lines.
+ */
+boolean
+draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe)
+{
+ struct aaline_stage *aaline;
+
+ pipe->draw = (void *) draw;
+
+ /*
+ * Create / install AA line drawing / prim stage
+ */
+ aaline = draw_aaline_stage( draw );
+ if (!aaline)
+ goto fail;
+
+ aaline->pipe = pipe;
+
+ /* create special texture, sampler state */
+ if (!aaline_create_texture(aaline))
+ goto fail;
+
+ if (!aaline_create_sampler(aaline))
+ goto fail;
+
+ /* save original driver functions */
+ aaline->driver_create_fs_state = pipe->create_fs_state;
+ aaline->driver_bind_fs_state = pipe->bind_fs_state;
+ aaline->driver_delete_fs_state = pipe->delete_fs_state;
+
+ aaline->driver_bind_sampler_states = pipe->bind_sampler_states;
+ aaline->driver_set_sampler_textures = pipe->set_sampler_textures;
+
+ /* override the driver's functions */
+ pipe->create_fs_state = aaline_create_fs_state;
+ pipe->bind_fs_state = aaline_bind_fs_state;
+ pipe->delete_fs_state = aaline_delete_fs_state;
+
+ pipe->bind_sampler_states = aaline_bind_sampler_states;
+ pipe->set_sampler_textures = aaline_set_sampler_textures;
+
+ /* Install once everything is known to be OK:
+ */
+ draw->pipeline.aaline = &aaline->stage;
+
+ return TRUE;
+
+ fail:
+ if (aaline)
+ aaline->stage.destroy( &aaline->stage );
+
+ return FALSE;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_aapoint.c b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c
new file mode 100644
index 0000000000..ae1712fe12
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c
@@ -0,0 +1,884 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * AA point stage: AA points are converted to quads and rendered with a
+ * special fragment shader. Another approach would be to use a texture
+ * map image of a point, but experiments indicate the quality isn't nearly
+ * as good as this approach.
+ *
+ * Note: this looks a lot like draw_aaline.c but there's actually little
+ * if any code that can be shared.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "tgsi/tgsi_transform.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "draw_context.h"
+#include "draw_vs.h"
+#include "draw_pipe.h"
+
+
+/*
+ * Enabling NORMALIZE might give _slightly_ better results.
+ * Basically, it controls whether we compute distance as d=sqrt(x*x+y*y) or
+ * d=x*x+y*y. Since we're working with a unit circle, the later seems
+ * close enough and saves some costly instructions.
+ */
+#define NORMALIZE 0
+
+
+/**
+ * Subclass of pipe_shader_state to carry extra fragment shader info.
+ */
+struct aapoint_fragment_shader
+{
+ struct pipe_shader_state state;
+ void *driver_fs; /**< the regular shader */
+ void *aapoint_fs; /**< the aa point-augmented shader */
+ int generic_attrib; /**< The generic input attrib/texcoord we'll use */
+};
+
+
+/**
+ * Subclass of draw_stage
+ */
+struct aapoint_stage
+{
+ struct draw_stage stage;
+
+ int psize_slot;
+ float radius;
+
+ /** this is the vertex attrib slot for the new texcoords */
+ uint tex_slot;
+ uint pos_slot;
+
+ /*
+ * Currently bound state
+ */
+ struct aapoint_fragment_shader *fs;
+
+ /*
+ * Driver interface/override functions
+ */
+ void * (*driver_create_fs_state)(struct pipe_context *,
+ const struct pipe_shader_state *);
+ void (*driver_bind_fs_state)(struct pipe_context *, void *);
+ void (*driver_delete_fs_state)(struct pipe_context *, void *);
+
+ struct pipe_context *pipe;
+};
+
+
+
+/**
+ * Subclass of tgsi_transform_context, used for transforming the
+ * user's fragment shader to add the special AA instructions.
+ */
+struct aa_transform_context {
+ struct tgsi_transform_context base;
+ uint tempsUsed; /**< bitmask */
+ int colorOutput; /**< which output is the primary color */
+ int maxInput, maxGeneric; /**< max input index found */
+ int tmp0, colorTemp; /**< temp registers */
+ boolean firstInstruction;
+};
+
+
+/**
+ * TGSI declaration transform callback.
+ * Look for two free temp regs and available input reg for new texcoords.
+ */
+static void
+aa_transform_decl(struct tgsi_transform_context *ctx,
+ struct tgsi_full_declaration *decl)
+{
+ struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
+
+ if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
+ decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR &&
+ decl->Semantic.SemanticIndex == 0) {
+ aactx->colorOutput = decl->DeclarationRange.First;
+ }
+ else if (decl->Declaration.File == TGSI_FILE_INPUT) {
+ if ((int) decl->DeclarationRange.Last > aactx->maxInput)
+ aactx->maxInput = decl->DeclarationRange.Last;
+ if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC &&
+ (int) decl->Semantic.SemanticIndex > aactx->maxGeneric) {
+ aactx->maxGeneric = decl->Semantic.SemanticIndex;
+ }
+ }
+ else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
+ uint i;
+ for (i = decl->DeclarationRange.First;
+ i <= decl->DeclarationRange.Last; i++) {
+ aactx->tempsUsed |= (1 << i);
+ }
+ }
+
+ ctx->emit_declaration(ctx, decl);
+}
+
+
+/**
+ * TGSI instruction transform callback.
+ * Replace writes to result.color w/ a temp reg.
+ * Upon END instruction, insert texture sampling code for antialiasing.
+ */
+static void
+aa_transform_inst(struct tgsi_transform_context *ctx,
+ struct tgsi_full_instruction *inst)
+{
+ struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
+ struct tgsi_full_instruction newInst;
+
+ if (aactx->firstInstruction) {
+ /* emit our new declarations before the first instruction */
+
+ struct tgsi_full_declaration decl;
+ const int texInput = aactx->maxInput + 1;
+ int tmp0;
+ uint i;
+
+ /* find two free temp regs */
+ for (i = 0; i < 32; i++) {
+ if ((aactx->tempsUsed & (1 << i)) == 0) {
+ /* found a free temp */
+ if (aactx->tmp0 < 0)
+ aactx->tmp0 = i;
+ else if (aactx->colorTemp < 0)
+ aactx->colorTemp = i;
+ else
+ break;
+ }
+ }
+
+ assert(aactx->colorTemp != aactx->tmp0);
+
+ tmp0 = aactx->tmp0;
+
+ /* declare new generic input/texcoord */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ /* XXX this could be linear... */
+ decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+ decl.Semantic.SemanticIndex = aactx->maxGeneric + 1;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = texInput;
+ ctx->emit_declaration(ctx, &decl);
+
+ /* declare new temp regs */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = tmp0;
+ ctx->emit_declaration(ctx, &decl);
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = aactx->colorTemp;
+ ctx->emit_declaration(ctx, &decl);
+
+ aactx->firstInstruction = FALSE;
+
+
+ /*
+ * Emit code to compute fragment coverage, kill if outside point radius
+ *
+ * Temp reg0 usage:
+ * t0.x = distance of fragment from center point
+ * t0.y = boolean, is t0.x > 1.0, also misc temp usage
+ * t0.z = temporary for computing 1/(1-k) value
+ * t0.w = final coverage value
+ */
+
+ /* MUL t0.xy, tex, tex; # compute x^2, y^2 */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XY;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = texInput;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = texInput;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* ADD t0.x, t0.x, t0.y; # x^2 + y^2 */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_ADD;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+ ctx->emit_instruction(ctx, &newInst);
+
+#if NORMALIZE /* OPTIONAL normalization of length */
+ /* RSQ t0.x, t0.x; */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_RSQ;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X;
+ newInst.Instruction.NumSrcRegs = 1;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* RCP t0.x, t0.x; */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_RCP;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X;
+ newInst.Instruction.NumSrcRegs = 1;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
+ ctx->emit_instruction(ctx, &newInst);
+#endif
+
+ /* SGT t0.y, t0.xxxx, tex.wwww; # bool b = d > 1 (NOTE tex.w == 1) */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_SGT;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = texInput;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* KIL -tmp0.yyyy; # if -tmp0.y < 0, KILL */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
+ newInst.Instruction.NumDstRegs = 0;
+ newInst.Instruction.NumSrcRegs = 1;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+ newInst.FullSrcRegisters[0].SrcRegister.Negate = 1;
+ ctx->emit_instruction(ctx, &newInst);
+
+
+ /* compute coverage factor = (1-d)/(1-k) */
+
+ /* SUB t0.z, tex.w, tex.z; # m = 1 - k */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_SUB;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Z;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = texInput;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = texInput;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* RCP t0.z, t0.z; # t0.z = 1 / m */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_RCP;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Z;
+ newInst.Instruction.NumSrcRegs = 1;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Z;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* SUB t0.y, 1, t0.x; # d = 1 - d */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_SUB;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = texInput;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* MUL t0.w, t0.y, t0.z; # coverage = d * m */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Z;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* SLE t0.y, t0.x, tex.z; # bool b = distance <= k */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_SLE;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = texInput;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Z;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* CMP t0.w, -t0.y, tex.w, t0.w;
+ * # if -t0.y < 0 then
+ * t0.w = 1
+ * else
+ * t0.w = t0.w
+ */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_CMP;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
+ newInst.Instruction.NumSrcRegs = 3;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+ newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+ newInst.FullSrcRegisters[0].SrcRegister.Negate = 1;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = texInput;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_W;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
+ newInst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+ newInst.FullSrcRegisters[2].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[2].SrcRegister.Index = tmp0;
+ newInst.FullSrcRegisters[2].SrcRegister.SwizzleX = TGSI_SWIZZLE_W;
+ newInst.FullSrcRegisters[2].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+ newInst.FullSrcRegisters[2].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
+ newInst.FullSrcRegisters[2].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+ ctx->emit_instruction(ctx, &newInst);
+
+ }
+
+ if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
+ /* add alpha modulation code at tail of program */
+
+ /* MOV result.color.xyz, colorTemp; */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_MOV;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+ newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XYZ;
+ newInst.Instruction.NumSrcRegs = 1;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* MUL result.color.w, colorTemp, tmp0.w; */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+ newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
+ newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->tmp0;
+ ctx->emit_instruction(ctx, &newInst);
+ }
+ else {
+ /* Not an END instruction.
+ * Look for writes to result.color and replace with colorTemp reg.
+ */
+ uint i;
+
+ for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
+ struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
+ if (dst->DstRegister.File == TGSI_FILE_OUTPUT &&
+ dst->DstRegister.Index == aactx->colorOutput) {
+ dst->DstRegister.File = TGSI_FILE_TEMPORARY;
+ dst->DstRegister.Index = aactx->colorTemp;
+ }
+ }
+ }
+
+ ctx->emit_instruction(ctx, inst);
+}
+
+
+/**
+ * Generate the frag shader we'll use for drawing AA points.
+ * This will be the user's shader plus some texture/modulate instructions.
+ */
+static boolean
+generate_aapoint_fs(struct aapoint_stage *aapoint)
+{
+ const struct pipe_shader_state *orig_fs = &aapoint->fs->state;
+ struct pipe_shader_state aapoint_fs;
+ struct aa_transform_context transform;
+
+#define MAX 1000
+
+ aapoint_fs = *orig_fs; /* copy to init */
+ aapoint_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
+ if (aapoint_fs.tokens == NULL)
+ return FALSE;
+
+ memset(&transform, 0, sizeof(transform));
+ transform.colorOutput = -1;
+ transform.maxInput = -1;
+ transform.maxGeneric = -1;
+ transform.colorTemp = -1;
+ transform.tmp0 = -1;
+ transform.firstInstruction = TRUE;
+ transform.base.transform_instruction = aa_transform_inst;
+ transform.base.transform_declaration = aa_transform_decl;
+
+ tgsi_transform_shader(orig_fs->tokens,
+ (struct tgsi_token *) aapoint_fs.tokens,
+ MAX, &transform.base);
+
+#if 0 /* DEBUG */
+ printf("draw_aapoint, orig shader:\n");
+ tgsi_dump(orig_fs->tokens, 0);
+ printf("draw_aapoint, new shader:\n");
+ tgsi_dump(aapoint_fs.tokens, 0);
+#endif
+
+ aapoint->fs->aapoint_fs
+ = aapoint->driver_create_fs_state(aapoint->pipe, &aapoint_fs);
+ if (aapoint->fs->aapoint_fs == NULL)
+ goto fail;
+
+ aapoint->fs->generic_attrib = transform.maxGeneric + 1;
+ FREE((void *)aapoint_fs.tokens);
+ return TRUE;
+
+fail:
+ FREE((void *)aapoint_fs.tokens);
+ return FALSE;
+}
+
+
+/**
+ * When we're about to draw our first AA point in a batch, this function is
+ * called to tell the driver to bind our modified fragment shader.
+ */
+static boolean
+bind_aapoint_fragment_shader(struct aapoint_stage *aapoint)
+{
+ struct draw_context *draw = aapoint->stage.draw;
+
+ if (!aapoint->fs->aapoint_fs &&
+ !generate_aapoint_fs(aapoint))
+ return FALSE;
+
+ draw->suspend_flushing = TRUE;
+ aapoint->driver_bind_fs_state(aapoint->pipe, aapoint->fs->aapoint_fs);
+ draw->suspend_flushing = FALSE;
+
+ return TRUE;
+}
+
+
+
+static INLINE struct aapoint_stage *
+aapoint_stage( struct draw_stage *stage )
+{
+ return (struct aapoint_stage *) stage;
+}
+
+
+
+
+/**
+ * Draw an AA point by drawing a quad.
+ */
+static void
+aapoint_point(struct draw_stage *stage, struct prim_header *header)
+{
+ const struct aapoint_stage *aapoint = aapoint_stage(stage);
+ struct prim_header tri;
+ struct vertex_header *v[4];
+ uint texPos = aapoint->tex_slot;
+ uint pos_slot = aapoint->pos_slot;
+ float radius, *pos, *tex;
+ uint i;
+ float k;
+
+ if (aapoint->psize_slot >= 0) {
+ radius = 0.5f * header->v[0]->data[aapoint->psize_slot][0];
+ }
+ else {
+ radius = aapoint->radius;
+ }
+
+ /*
+ * Note: the texcoords (generic attrib, really) we use are special:
+ * The S and T components simply vary from -1 to +1.
+ * The R component is k, below.
+ * The Q component is 1.0 and will used as a handy constant in the
+ * fragment shader.
+ */
+
+ /*
+ * k is the threshold distance from the point's center at which
+ * we begin alpha attenuation (the coverage value).
+ * Operating within a unit circle, we'll compute the fragment's
+ * distance 'd' from the center point using the texcoords.
+ * IF d > 1.0 THEN
+ * KILL fragment
+ * ELSE IF d > k THEN
+ * compute coverage in [0,1] proportional to d in [k, 1].
+ * ELSE
+ * coverage = 1.0; // full coverage
+ * ENDIF
+ *
+ * Note: the ELSEIF and ELSE clauses are actually implemented with CMP to
+ * avoid using IF/ELSE/ENDIF TGSI opcodes.
+ */
+
+#if !NORMALIZE
+ k = 1.0f / radius;
+ k = 1.0f - 2.0f * k + k * k;
+#else
+ k = 1.0f - 1.0f / radius;
+#endif
+
+ /* allocate/dup new verts */
+ for (i = 0; i < 4; i++) {
+ v[i] = dup_vert(stage, header->v[0], i);
+ }
+
+ /* new verts */
+ pos = v[0]->data[pos_slot];
+ pos[0] -= radius;
+ pos[1] -= radius;
+
+ pos = v[1]->data[pos_slot];
+ pos[0] += radius;
+ pos[1] -= radius;
+
+ pos = v[2]->data[pos_slot];
+ pos[0] += radius;
+ pos[1] += radius;
+
+ pos = v[3]->data[pos_slot];
+ pos[0] -= radius;
+ pos[1] += radius;
+
+ /* new texcoords */
+ tex = v[0]->data[texPos];
+ ASSIGN_4V(tex, -1, -1, k, 1);
+
+ tex = v[1]->data[texPos];
+ ASSIGN_4V(tex, 1, -1, k, 1);
+
+ tex = v[2]->data[texPos];
+ ASSIGN_4V(tex, 1, 1, k, 1);
+
+ tex = v[3]->data[texPos];
+ ASSIGN_4V(tex, -1, 1, k, 1);
+
+ /* emit 2 tris for the quad strip */
+ tri.v[0] = v[0];
+ tri.v[1] = v[1];
+ tri.v[2] = v[2];
+ stage->next->tri( stage->next, &tri );
+
+ tri.v[0] = v[0];
+ tri.v[1] = v[2];
+ tri.v[2] = v[3];
+ stage->next->tri( stage->next, &tri );
+}
+
+
+static void
+aapoint_first_point(struct draw_stage *stage, struct prim_header *header)
+{
+ auto struct aapoint_stage *aapoint = aapoint_stage(stage);
+ struct draw_context *draw = stage->draw;
+
+ assert(draw->rasterizer->point_smooth);
+
+ if (draw->rasterizer->point_size <= 2.0)
+ aapoint->radius = 1.0;
+ else
+ aapoint->radius = 0.5f * draw->rasterizer->point_size;
+
+ /*
+ * Bind (generate) our fragprog.
+ */
+ bind_aapoint_fragment_shader(aapoint);
+
+ /* update vertex attrib info */
+ aapoint->tex_slot = draw->vs.num_vs_outputs;
+ assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */
+
+ aapoint->pos_slot = draw->vs.position_output;
+
+ draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
+ draw->extra_vp_outputs.semantic_index = aapoint->fs->generic_attrib;
+ draw->extra_vp_outputs.slot = aapoint->tex_slot;
+
+ /* find psize slot in post-transform vertex */
+ aapoint->psize_slot = -1;
+ if (draw->rasterizer->point_size_per_vertex) {
+ /* find PSIZ vertex output */
+ const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+ uint i;
+ for (i = 0; i < vs->info.num_outputs; i++) {
+ if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) {
+ aapoint->psize_slot = i;
+ break;
+ }
+ }
+ }
+
+ /* now really draw first point */
+ stage->point = aapoint_point;
+ stage->point(stage, header);
+}
+
+
+static void
+aapoint_flush(struct draw_stage *stage, unsigned flags)
+{
+ struct draw_context *draw = stage->draw;
+ struct aapoint_stage *aapoint = aapoint_stage(stage);
+ struct pipe_context *pipe = aapoint->pipe;
+
+ stage->point = aapoint_first_point;
+ stage->next->flush( stage->next, flags );
+
+ /* restore original frag shader */
+ draw->suspend_flushing = TRUE;
+ aapoint->driver_bind_fs_state(pipe, aapoint->fs->driver_fs);
+ draw->suspend_flushing = FALSE;
+
+ draw->extra_vp_outputs.slot = 0;
+}
+
+
+static void
+aapoint_reset_stipple_counter(struct draw_stage *stage)
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void
+aapoint_destroy(struct draw_stage *stage)
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+static struct aapoint_stage *
+draw_aapoint_stage(struct draw_context *draw)
+{
+ struct aapoint_stage *aapoint = CALLOC_STRUCT(aapoint_stage);
+ if (aapoint == NULL)
+ goto fail;
+
+ if (!draw_alloc_temp_verts( &aapoint->stage, 4 ))
+ goto fail;
+
+ aapoint->stage.draw = draw;
+ aapoint->stage.name = "aapoint";
+ aapoint->stage.next = NULL;
+ aapoint->stage.point = aapoint_first_point;
+ aapoint->stage.line = draw_pipe_passthrough_line;
+ aapoint->stage.tri = draw_pipe_passthrough_tri;
+ aapoint->stage.flush = aapoint_flush;
+ aapoint->stage.reset_stipple_counter = aapoint_reset_stipple_counter;
+ aapoint->stage.destroy = aapoint_destroy;
+
+ return aapoint;
+
+ fail:
+ if (aapoint)
+ aapoint_destroy(&aapoint->stage);
+
+ return NULL;
+
+}
+
+
+static struct aapoint_stage *
+aapoint_stage_from_pipe(struct pipe_context *pipe)
+{
+ struct draw_context *draw = (struct draw_context *) pipe->draw;
+ return aapoint_stage(draw->pipeline.aapoint);
+}
+
+
+/**
+ * This function overrides the driver's create_fs_state() function and
+ * will typically be called by the state tracker.
+ */
+static void *
+aapoint_create_fs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *fs)
+{
+ struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
+ struct aapoint_fragment_shader *aafs = CALLOC_STRUCT(aapoint_fragment_shader);
+ if (aafs == NULL)
+ return NULL;
+
+ aafs->state = *fs;
+
+ /* pass-through */
+ aafs->driver_fs = aapoint->driver_create_fs_state(aapoint->pipe, fs);
+
+ return aafs;
+}
+
+
+static void
+aapoint_bind_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
+ struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs;
+ /* save current */
+ aapoint->fs = aafs;
+ /* pass-through */
+ aapoint->driver_bind_fs_state(aapoint->pipe,
+ (aafs ? aafs->driver_fs : NULL));
+}
+
+
+static void
+aapoint_delete_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
+ struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs;
+
+ /* pass-through */
+ aapoint->driver_delete_fs_state(aapoint->pipe, aafs->driver_fs);
+
+ if (aafs->aapoint_fs)
+ aapoint->driver_delete_fs_state(aapoint->pipe, aafs->aapoint_fs);
+
+ FREE(aafs);
+}
+
+
+/**
+ * Called by drivers that want to install this AA point prim stage
+ * into the draw module's pipeline. This will not be used if the
+ * hardware has native support for AA points.
+ */
+boolean
+draw_install_aapoint_stage(struct draw_context *draw,
+ struct pipe_context *pipe)
+{
+ struct aapoint_stage *aapoint;
+
+ pipe->draw = (void *) draw;
+
+ /*
+ * Create / install AA point drawing / prim stage
+ */
+ aapoint = draw_aapoint_stage( draw );
+ if (aapoint == NULL)
+ goto fail;
+
+ aapoint->pipe = pipe;
+
+ /* save original driver functions */
+ aapoint->driver_create_fs_state = pipe->create_fs_state;
+ aapoint->driver_bind_fs_state = pipe->bind_fs_state;
+ aapoint->driver_delete_fs_state = pipe->delete_fs_state;
+
+ /* override the driver's functions */
+ pipe->create_fs_state = aapoint_create_fs_state;
+ pipe->bind_fs_state = aapoint_bind_fs_state;
+ pipe->delete_fs_state = aapoint_delete_fs_state;
+
+ draw->pipeline.aapoint = &aapoint->stage;
+
+ return TRUE;
+
+ fail:
+ if (aapoint)
+ aapoint->stage.destroy( &aapoint->stage );
+
+ return FALSE;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
new file mode 100644
index 0000000000..0670268a19
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
@@ -0,0 +1,516 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Clipping stage
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "pipe/p_shader_tokens.h"
+
+#include "draw_vs.h"
+#include "draw_pipe.h"
+
+
+#ifndef IS_NEGATIVE
+#define IS_NEGATIVE(X) ((X) < 0.0)
+#endif
+
+#ifndef DIFFERENT_SIGNS
+#define DIFFERENT_SIGNS(x, y) ((x) * (y) <= 0.0F && (x) - (y) != 0.0F)
+#endif
+
+#ifndef MAX_CLIPPED_VERTICES
+#define MAX_CLIPPED_VERTICES ((2 * (6 + PIPE_MAX_CLIP_PLANES))+1)
+#endif
+
+
+
+struct clipper {
+ struct draw_stage stage; /**< base class */
+
+ /* Basically duplicate some of the flatshading logic here:
+ */
+ boolean flat;
+ uint num_color_attribs;
+ uint color_attribs[4]; /* front/back primary/secondary colors */
+
+ float (*plane)[4];
+};
+
+
+/* This is a bit confusing:
+ */
+static INLINE struct clipper *clipper_stage( struct draw_stage *stage )
+{
+ return (struct clipper *)stage;
+}
+
+
+#define LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT)))
+
+
+/* All attributes are float[4], so this is easy:
+ */
+static void interp_attr( float *fdst,
+ float t,
+ const float *fin,
+ const float *fout )
+{
+ fdst[0] = LINTERP( t, fout[0], fin[0] );
+ fdst[1] = LINTERP( t, fout[1], fin[1] );
+ fdst[2] = LINTERP( t, fout[2], fin[2] );
+ fdst[3] = LINTERP( t, fout[3], fin[3] );
+}
+
+static void copy_colors( struct draw_stage *stage,
+ struct vertex_header *dst,
+ const struct vertex_header *src )
+{
+ const struct clipper *clipper = clipper_stage(stage);
+ uint i;
+ for (i = 0; i < clipper->num_color_attribs; i++) {
+ const uint attr = clipper->color_attribs[i];
+ COPY_4FV(dst->data[attr], src->data[attr]);
+ }
+}
+
+
+
+/* Interpolate between two vertices to produce a third.
+ */
+static void interp( const struct clipper *clip,
+ struct vertex_header *dst,
+ float t,
+ const struct vertex_header *out,
+ const struct vertex_header *in )
+{
+ const unsigned nr_attrs = clip->stage.draw->vs.num_vs_outputs;
+ const unsigned pos_attr = clip->stage.draw->vs.position_output;
+ unsigned j;
+
+ /* Vertex header.
+ */
+ {
+ dst->clipmask = 0;
+ dst->edgeflag = 0; /* will get overwritten later */
+ dst->pad = 0;
+ dst->vertex_id = UNDEFINED_VERTEX_ID;
+ }
+
+ /* Clip coordinates: interpolate normally
+ */
+ {
+ interp_attr(dst->clip, t, in->clip, out->clip);
+ }
+
+ /* Do the projective divide and insert window coordinates:
+ */
+ {
+ const float *pos = dst->clip;
+ const float *scale = clip->stage.draw->viewport.scale;
+ const float *trans = clip->stage.draw->viewport.translate;
+ const float oow = 1.0f / pos[3];
+
+ dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0];
+ dst->data[pos_attr][1] = pos[1] * oow * scale[1] + trans[1];
+ dst->data[pos_attr][2] = pos[2] * oow * scale[2] + trans[2];
+ dst->data[pos_attr][3] = oow;
+ }
+
+ /* Other attributes
+ */
+ for (j = 0; j < nr_attrs; j++) {
+ if (j != pos_attr)
+ interp_attr(dst->data[j], t, in->data[j], out->data[j]);
+ }
+}
+
+
+static void emit_poly( struct draw_stage *stage,
+ struct vertex_header **inlist,
+ unsigned n,
+ const struct prim_header *origPrim)
+{
+ struct prim_header header;
+ unsigned i;
+
+ const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2;
+ const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0;
+ const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1;
+
+ /* later stages may need the determinant, but only the sign matters */
+ header.det = origPrim->det;
+ header.flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
+ header.pad = 0;
+
+ for (i = 2; i < n; i++, header.flags = edge_middle) {
+ header.v[0] = inlist[i-1];
+ header.v[1] = inlist[i];
+ header.v[2] = inlist[0]; /* keep in v[2] for flatshading */
+
+ if (i == n-1)
+ header.flags |= edge_last;
+
+ if (0) {
+ const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
+ uint j, k;
+ debug_printf("Clipped tri:\n");
+ for (j = 0; j < 3; j++) {
+ for (k = 0; k < vs->info.num_outputs; k++) {
+ debug_printf(" Vert %d: Attr %d: %f %f %f %f\n", j, k,
+ header.v[j]->data[k][0],
+ header.v[j]->data[k][1],
+ header.v[j]->data[k][2],
+ header.v[j]->data[k][3]);
+ }
+ }
+ }
+
+ stage->next->tri( stage->next, &header );
+ }
+}
+
+static INLINE float
+dot4(const float *a, const float *b)
+{
+ return (a[0]*b[0] +
+ a[1]*b[1] +
+ a[2]*b[2] +
+ a[3]*b[3]);
+}
+
+
+/* Clip a triangle against the viewport and user clip planes.
+ */
+static void
+do_clip_tri( struct draw_stage *stage,
+ struct prim_header *header,
+ unsigned clipmask )
+{
+ struct clipper *clipper = clipper_stage( stage );
+ struct vertex_header *a[MAX_CLIPPED_VERTICES];
+ struct vertex_header *b[MAX_CLIPPED_VERTICES];
+ struct vertex_header **inlist = a;
+ struct vertex_header **outlist = b;
+ unsigned tmpnr = 0;
+ unsigned n = 3;
+ unsigned i;
+
+ inlist[0] = header->v[0];
+ inlist[1] = header->v[1];
+ inlist[2] = header->v[2];
+
+ while (clipmask && n >= 3) {
+ const unsigned plane_idx = ffs(clipmask)-1;
+ const float *plane = clipper->plane[plane_idx];
+ struct vertex_header *vert_prev = inlist[0];
+ float dp_prev = dot4( vert_prev->clip, plane );
+ unsigned outcount = 0;
+
+ clipmask &= ~(1<<plane_idx);
+
+ inlist[n] = inlist[0]; /* prevent rotation of vertices */
+
+ for (i = 1; i <= n; i++) {
+ struct vertex_header *vert = inlist[i];
+
+ float dp = dot4( vert->clip, plane );
+
+ if (!IS_NEGATIVE(dp_prev)) {
+ outlist[outcount++] = vert_prev;
+ }
+
+ if (DIFFERENT_SIGNS(dp, dp_prev)) {
+ struct vertex_header *new_vert = clipper->stage.tmp[tmpnr++];
+ outlist[outcount++] = new_vert;
+
+ if (IS_NEGATIVE(dp)) {
+ /* Going out of bounds. Avoid division by zero as we
+ * know dp != dp_prev from DIFFERENT_SIGNS, above.
+ */
+ float t = dp / (dp - dp_prev);
+ interp( clipper, new_vert, t, vert, vert_prev );
+
+ /* Force edgeflag true in this case:
+ */
+ new_vert->edgeflag = 1;
+ } else {
+ /* Coming back in.
+ */
+ float t = dp_prev / (dp_prev - dp);
+ interp( clipper, new_vert, t, vert_prev, vert );
+
+ /* Copy starting vert's edgeflag:
+ */
+ new_vert->edgeflag = vert_prev->edgeflag;
+ }
+ }
+
+ vert_prev = vert;
+ dp_prev = dp;
+ }
+
+ {
+ struct vertex_header **tmp = inlist;
+ inlist = outlist;
+ outlist = tmp;
+ n = outcount;
+ }
+ }
+
+ /* If flat-shading, copy color to new provoking vertex.
+ */
+ if (clipper->flat && inlist[0] != header->v[2]) {
+ if (1) {
+ inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
+ }
+
+ copy_colors(stage, inlist[0], header->v[2]);
+ }
+
+
+
+ /* Emit the polygon as triangles to the setup stage:
+ */
+ if (n >= 3)
+ emit_poly( stage, inlist, n, header );
+}
+
+
+/* Clip a line against the viewport and user clip planes.
+ */
+static void
+do_clip_line( struct draw_stage *stage,
+ struct prim_header *header,
+ unsigned clipmask )
+{
+ const struct clipper *clipper = clipper_stage( stage );
+ struct vertex_header *v0 = header->v[0];
+ struct vertex_header *v1 = header->v[1];
+ const float *pos0 = v0->clip;
+ const float *pos1 = v1->clip;
+ float t0 = 0.0F;
+ float t1 = 0.0F;
+ struct prim_header newprim;
+
+ while (clipmask) {
+ const unsigned plane_idx = ffs(clipmask)-1;
+ const float *plane = clipper->plane[plane_idx];
+ const float dp0 = dot4( pos0, plane );
+ const float dp1 = dot4( pos1, plane );
+
+ if (dp1 < 0.0F) {
+ float t = dp1 / (dp1 - dp0);
+ t1 = MAX2(t1, t);
+ }
+
+ if (dp0 < 0.0F) {
+ float t = dp0 / (dp0 - dp1);
+ t0 = MAX2(t0, t);
+ }
+
+ if (t0 + t1 >= 1.0F)
+ return; /* discard */
+
+ clipmask &= ~(1 << plane_idx); /* turn off this plane's bit */
+ }
+
+ if (v0->clipmask) {
+ interp( clipper, stage->tmp[0], t0, v0, v1 );
+
+ if (clipper->flat)
+ copy_colors(stage, stage->tmp[0], v0);
+
+ newprim.v[0] = stage->tmp[0];
+ }
+ else {
+ newprim.v[0] = v0;
+ }
+
+ if (v1->clipmask) {
+ interp( clipper, stage->tmp[1], t1, v1, v0 );
+ newprim.v[1] = stage->tmp[1];
+ }
+ else {
+ newprim.v[1] = v1;
+ }
+
+ stage->next->line( stage->next, &newprim );
+}
+
+
+static void
+clip_point( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ if (header->v[0]->clipmask == 0)
+ stage->next->point( stage->next, header );
+}
+
+
+static void
+clip_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ unsigned clipmask = (header->v[0]->clipmask |
+ header->v[1]->clipmask);
+
+ if (clipmask == 0) {
+ /* no clipping needed */
+ stage->next->line( stage->next, header );
+ }
+ else if ((header->v[0]->clipmask &
+ header->v[1]->clipmask) == 0) {
+ do_clip_line(stage, header, clipmask);
+ }
+ /* else, totally clipped */
+}
+
+
+static void
+clip_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ unsigned clipmask = (header->v[0]->clipmask |
+ header->v[1]->clipmask |
+ header->v[2]->clipmask);
+
+ if (clipmask == 0) {
+ /* no clipping needed */
+ stage->next->tri( stage->next, header );
+ }
+ else if ((header->v[0]->clipmask &
+ header->v[1]->clipmask &
+ header->v[2]->clipmask) == 0) {
+ do_clip_tri(stage, header, clipmask);
+ }
+}
+
+/* Update state. Could further delay this until we hit the first
+ * primitive that really requires clipping.
+ */
+static void
+clip_init_state( struct draw_stage *stage )
+{
+ struct clipper *clipper = clipper_stage( stage );
+
+ clipper->flat = stage->draw->rasterizer->flatshade ? TRUE : FALSE;
+
+ if (clipper->flat) {
+ const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
+ uint i;
+
+ clipper->num_color_attribs = 0;
+ for (i = 0; i < vs->info.num_outputs; i++) {
+ if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR ||
+ vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
+ clipper->color_attribs[clipper->num_color_attribs++] = i;
+ }
+ }
+ }
+
+ stage->tri = clip_tri;
+ stage->line = clip_line;
+}
+
+
+
+static void clip_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ clip_init_state( stage );
+ stage->tri( stage, header );
+}
+
+static void clip_first_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ clip_init_state( stage );
+ stage->line( stage, header );
+}
+
+
+static void clip_flush( struct draw_stage *stage,
+ unsigned flags )
+{
+ stage->tri = clip_first_tri;
+ stage->line = clip_first_line;
+ stage->next->flush( stage->next, flags );
+}
+
+
+static void clip_reset_stipple_counter( struct draw_stage *stage )
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void clip_destroy( struct draw_stage *stage )
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+/**
+ * Allocate a new clipper stage.
+ * \return pointer to new stage object
+ */
+struct draw_stage *draw_clip_stage( struct draw_context *draw )
+{
+ struct clipper *clipper = CALLOC_STRUCT(clipper);
+ if (clipper == NULL)
+ goto fail;
+
+ if (!draw_alloc_temp_verts( &clipper->stage, MAX_CLIPPED_VERTICES+1 ))
+ goto fail;
+
+ clipper->stage.draw = draw;
+ clipper->stage.name = "clipper";
+ clipper->stage.point = clip_point;
+ clipper->stage.line = clip_first_line;
+ clipper->stage.tri = clip_first_tri;
+ clipper->stage.flush = clip_flush;
+ clipper->stage.reset_stipple_counter = clip_reset_stipple_counter;
+ clipper->stage.destroy = clip_destroy;
+
+ clipper->plane = draw->plane;
+
+ return &clipper->stage;
+
+ fail:
+ if (clipper)
+ clipper->stage.destroy( &clipper->stage );
+
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_cull.c b/src/gallium/auxiliary/draw/draw_pipe_cull.c
new file mode 100644
index 0000000000..0a70483858
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_cull.c
@@ -0,0 +1,148 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Drawing stage for polygon culling
+ */
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "util/u_memory.h"
+#include "pipe/p_defines.h"
+#include "draw_pipe.h"
+
+
+struct cull_stage {
+ struct draw_stage stage;
+ unsigned winding; /**< which winding(s) to cull (one of PIPE_WINDING_x) */
+};
+
+
+static INLINE struct cull_stage *cull_stage( struct draw_stage *stage )
+{
+ return (struct cull_stage *)stage;
+}
+
+
+
+
+static void cull_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ const unsigned pos = stage->draw->vs.position_output;
+
+ /* Window coords: */
+ const float *v0 = header->v[0]->data[pos];
+ const float *v1 = header->v[1]->data[pos];
+ const float *v2 = header->v[2]->data[pos];
+
+ /* edge vectors e = v0 - v2, f = v1 - v2 */
+ const float ex = v0[0] - v2[0];
+ const float ey = v0[1] - v2[1];
+ const float fx = v1[0] - v2[0];
+ const float fy = v1[1] - v2[1];
+
+ /* det = cross(e,f).z */
+ header->det = ex * fy - ey * fx;
+
+ if (header->det != 0) {
+ /* if (det < 0 then Z points toward camera and triangle is
+ * counter-clockwise winding.
+ */
+ unsigned winding = (header->det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW;
+
+ if ((winding & cull_stage(stage)->winding) == 0) {
+ /* triangle is not culled, pass to next stage */
+ stage->next->tri( stage->next, header );
+ }
+ }
+}
+
+static void cull_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct cull_stage *cull = cull_stage(stage);
+
+ cull->winding = stage->draw->rasterizer->cull_mode;
+
+ stage->tri = cull_tri;
+ stage->tri( stage, header );
+}
+
+
+
+static void cull_flush( struct draw_stage *stage, unsigned flags )
+{
+ stage->tri = cull_first_tri;
+ stage->next->flush( stage->next, flags );
+}
+
+static void cull_reset_stipple_counter( struct draw_stage *stage )
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void cull_destroy( struct draw_stage *stage )
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+/**
+ * Create a new polygon culling stage.
+ */
+struct draw_stage *draw_cull_stage( struct draw_context *draw )
+{
+ struct cull_stage *cull = CALLOC_STRUCT(cull_stage);
+ if (cull == NULL)
+ goto fail;
+
+ if (!draw_alloc_temp_verts( &cull->stage, 0 ))
+ goto fail;
+
+ cull->stage.draw = draw;
+ cull->stage.name = "cull";
+ cull->stage.next = NULL;
+ cull->stage.point = draw_pipe_passthrough_point;
+ cull->stage.line = draw_pipe_passthrough_line;
+ cull->stage.tri = cull_first_tri;
+ cull->stage.flush = cull_flush;
+ cull->stage.reset_stipple_counter = cull_reset_stipple_counter;
+ cull->stage.destroy = cull_destroy;
+
+ return &cull->stage;
+
+ fail:
+ if (cull)
+ cull->stage.destroy( &cull->stage );
+
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_flatshade.c b/src/gallium/auxiliary/draw/draw_pipe_flatshade.c
new file mode 100644
index 0000000000..34afb1a0b6
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_flatshade.c
@@ -0,0 +1,282 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "draw_vs.h"
+#include "draw_pipe.h"
+
+
+/** subclass of draw_stage */
+struct flat_stage
+{
+ struct draw_stage stage;
+
+ uint num_color_attribs;
+ uint color_attribs[2]; /* front/back primary colors */
+
+ uint num_spec_attribs;
+ uint spec_attribs[2]; /* front/back secondary colors */
+};
+
+#define COPY_3FV( DST, SRC ) \
+do { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+ (DST)[2] = (SRC)[2]; \
+} while (0)
+
+
+static INLINE struct flat_stage *
+flat_stage(struct draw_stage *stage)
+{
+ return (struct flat_stage *) stage;
+}
+
+
+/** Copy all the color attributes from 'src' vertex to 'dst' vertex */
+static INLINE void copy_colors( struct draw_stage *stage,
+ struct vertex_header *dst,
+ const struct vertex_header *src )
+{
+ const struct flat_stage *flat = flat_stage(stage);
+ uint i;
+
+ for (i = 0; i < flat->num_color_attribs; i++) {
+ const uint attr = flat->color_attribs[i];
+ COPY_4FV(dst->data[attr], src->data[attr]);
+ }
+
+ for (i = 0; i < flat->num_spec_attribs; i++) {
+ const uint attr = flat->spec_attribs[i];
+ COPY_3FV(dst->data[attr], src->data[attr]);
+ }
+}
+
+
+/** Copy all the color attributes from src vertex to dst0 & dst1 vertices */
+static INLINE void copy_colors2( struct draw_stage *stage,
+ struct vertex_header *dst0,
+ struct vertex_header *dst1,
+ const struct vertex_header *src )
+{
+ const struct flat_stage *flat = flat_stage(stage);
+ uint i;
+ for (i = 0; i < flat->num_color_attribs; i++) {
+ const uint attr = flat->color_attribs[i];
+ COPY_4FV(dst0->data[attr], src->data[attr]);
+ COPY_4FV(dst1->data[attr], src->data[attr]);
+ }
+
+ for (i = 0; i < flat->num_spec_attribs; i++) {
+ const uint attr = flat->spec_attribs[i];
+ COPY_3FV(dst0->data[attr], src->data[attr]);
+ COPY_3FV(dst1->data[attr], src->data[attr]);
+ }
+}
+
+
+/**
+ * Flatshade tri. Required for clipping and when unfilled tris are
+ * active, otherwise handled by hardware.
+ */
+static void flatshade_tri_0( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct prim_header tmp;
+
+ tmp.det = header->det;
+ tmp.flags = header->flags;
+ tmp.pad = header->pad;
+ tmp.v[0] = header->v[0];
+ tmp.v[1] = dup_vert(stage, header->v[1], 0);
+ tmp.v[2] = dup_vert(stage, header->v[2], 1);
+
+ copy_colors2(stage, tmp.v[1], tmp.v[2], tmp.v[0]);
+
+ stage->next->tri( stage->next, &tmp );
+}
+
+
+static void flatshade_tri_2( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct prim_header tmp;
+
+ tmp.det = header->det;
+ tmp.flags = header->flags;
+ tmp.pad = header->pad;
+ tmp.v[0] = dup_vert(stage, header->v[0], 0);
+ tmp.v[1] = dup_vert(stage, header->v[1], 1);
+ tmp.v[2] = header->v[2];
+
+ copy_colors2(stage, tmp.v[0], tmp.v[1], tmp.v[2]);
+
+ stage->next->tri( stage->next, &tmp );
+}
+
+
+
+
+
+/**
+ * Flatshade line. Required for clipping.
+ */
+static void flatshade_line_0( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct prim_header tmp;
+
+ tmp.v[0] = header->v[0];
+ tmp.v[1] = dup_vert(stage, header->v[1], 0);
+
+ copy_colors(stage, tmp.v[1], tmp.v[0]);
+
+ stage->next->line( stage->next, &tmp );
+}
+
+static void flatshade_line_1( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct prim_header tmp;
+
+ tmp.v[0] = dup_vert(stage, header->v[0], 0);
+ tmp.v[1] = header->v[1];
+
+ copy_colors(stage, tmp.v[0], tmp.v[1]);
+
+ stage->next->line( stage->next, &tmp );
+}
+
+
+
+
+static void flatshade_init_state( struct draw_stage *stage )
+{
+ struct flat_stage *flat = flat_stage(stage);
+ const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
+ uint i;
+
+ /* Find which vertex shader outputs are colors, make a list */
+ flat->num_color_attribs = 0;
+ flat->num_spec_attribs = 0;
+ for (i = 0; i < vs->info.num_outputs; i++) {
+ if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR ||
+ vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
+ if (vs->info.output_semantic_index[i] == 0)
+ flat->color_attribs[flat->num_color_attribs++] = i;
+ else
+ flat->spec_attribs[flat->num_spec_attribs++] = i;
+ }
+ }
+
+ /* Choose flatshade routine according to provoking vertex:
+ */
+ if (stage->draw->rasterizer->flatshade_first) {
+ stage->line = flatshade_line_0;
+ stage->tri = flatshade_tri_0;
+ }
+ else {
+ stage->line = flatshade_line_1;
+ stage->tri = flatshade_tri_2;
+ }
+}
+
+static void flatshade_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ flatshade_init_state( stage );
+ stage->tri( stage, header );
+}
+
+static void flatshade_first_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ flatshade_init_state( stage );
+ stage->line( stage, header );
+}
+
+
+static void flatshade_flush( struct draw_stage *stage,
+ unsigned flags )
+{
+ stage->tri = flatshade_first_tri;
+ stage->line = flatshade_first_line;
+ stage->next->flush( stage->next, flags );
+}
+
+
+static void flatshade_reset_stipple_counter( struct draw_stage *stage )
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void flatshade_destroy( struct draw_stage *stage )
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+/**
+ * Create flatshading drawing stage.
+ */
+struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
+{
+ struct flat_stage *flatshade = CALLOC_STRUCT(flat_stage);
+ if (flatshade == NULL)
+ goto fail;
+
+ if (!draw_alloc_temp_verts( &flatshade->stage, 2 ))
+ goto fail;
+
+ flatshade->stage.draw = draw;
+ flatshade->stage.name = "flatshade";
+ flatshade->stage.next = NULL;
+ flatshade->stage.point = draw_pipe_passthrough_point;
+ flatshade->stage.line = flatshade_first_line;
+ flatshade->stage.tri = flatshade_first_tri;
+ flatshade->stage.flush = flatshade_flush;
+ flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter;
+ flatshade->stage.destroy = flatshade_destroy;
+
+ return &flatshade->stage;
+
+ fail:
+ if (flatshade)
+ flatshade->stage.destroy( &flatshade->stage );
+
+ return NULL;
+}
+
+
diff --git a/src/gallium/auxiliary/draw/draw_pipe_offset.c b/src/gallium/auxiliary/draw/draw_pipe_offset.c
new file mode 100644
index 0000000000..40798a5d6e
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_offset.c
@@ -0,0 +1,185 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief polygon offset state
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Brian Paul
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "draw_pipe.h"
+
+
+
+struct offset_stage {
+ struct draw_stage stage;
+
+ float scale;
+ float units;
+};
+
+
+
+static INLINE struct offset_stage *offset_stage( struct draw_stage *stage )
+{
+ return (struct offset_stage *) stage;
+}
+
+
+
+
+
+/**
+ * Offset tri Z. Some hardware can handle this, but not usually when
+ * doing unfilled rendering.
+ */
+static void do_offset_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ const unsigned pos = stage->draw->vs.position_output;
+ struct offset_stage *offset = offset_stage(stage);
+ float inv_det = 1.0f / header->det;
+
+ /* Window coords:
+ */
+ float *v0 = header->v[0]->data[pos];
+ float *v1 = header->v[1]->data[pos];
+ float *v2 = header->v[2]->data[pos];
+
+ /* edge vectors e = v0 - v2, f = v1 - v2 */
+ float ex = v0[0] - v2[0];
+ float ey = v0[1] - v2[1];
+ float ez = v0[2] - v2[2];
+ float fx = v1[0] - v2[0];
+ float fy = v1[1] - v2[1];
+ float fz = v1[2] - v2[2];
+
+ /* (a,b) = cross(e,f).xy */
+ float a = ey*fz - ez*fy;
+ float b = ez*fx - ex*fz;
+
+ float dzdx = fabsf(a * inv_det);
+ float dzdy = fabsf(b * inv_det);
+
+ float zoffset = offset->units + MAX2(dzdx, dzdy) * offset->scale;
+
+ /*
+ * Note: we're applying the offset and clamping per-vertex.
+ * Ideally, the offset is applied per-fragment prior to fragment shading.
+ */
+ v0[2] = CLAMP(v0[2] + zoffset, 0.0f, 1.0f);
+ v1[2] = CLAMP(v1[2] + zoffset, 0.0f, 1.0f);
+ v2[2] = CLAMP(v2[2] + zoffset, 0.0f, 1.0f);
+
+ stage->next->tri( stage->next, header );
+}
+
+
+static void offset_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct prim_header tmp;
+
+ tmp.det = header->det;
+ tmp.flags = header->flags;
+ tmp.pad = header->pad;
+ tmp.v[0] = dup_vert(stage, header->v[0], 0);
+ tmp.v[1] = dup_vert(stage, header->v[1], 1);
+ tmp.v[2] = dup_vert(stage, header->v[2], 2);
+
+ do_offset_tri( stage, &tmp );
+}
+
+
+static void offset_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct offset_stage *offset = offset_stage(stage);
+
+ offset->units = (float) (stage->draw->rasterizer->offset_units * stage->draw->mrd);
+ offset->scale = stage->draw->rasterizer->offset_scale;
+
+ stage->tri = offset_tri;
+ stage->tri( stage, header );
+}
+
+
+
+
+static void offset_flush( struct draw_stage *stage,
+ unsigned flags )
+{
+ stage->tri = offset_first_tri;
+ stage->next->flush( stage->next, flags );
+}
+
+
+static void offset_reset_stipple_counter( struct draw_stage *stage )
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void offset_destroy( struct draw_stage *stage )
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+/**
+ * Create polygon offset drawing stage.
+ */
+struct draw_stage *draw_offset_stage( struct draw_context *draw )
+{
+ struct offset_stage *offset = CALLOC_STRUCT(offset_stage);
+ if (offset == NULL)
+ goto fail;
+
+ draw_alloc_temp_verts( &offset->stage, 3 );
+
+ offset->stage.draw = draw;
+ offset->stage.name = "offset";
+ offset->stage.next = NULL;
+ offset->stage.point = draw_pipe_passthrough_point;
+ offset->stage.line = draw_pipe_passthrough_line;
+ offset->stage.tri = offset_first_tri;
+ offset->stage.flush = offset_flush;
+ offset->stage.reset_stipple_counter = offset_reset_stipple_counter;
+ offset->stage.destroy = offset_destroy;
+
+ return &offset->stage;
+
+ fail:
+ if (offset)
+ offset->stage.destroy( &offset->stage );
+
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
new file mode 100644
index 0000000000..283502cdf3
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
@@ -0,0 +1,777 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * 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.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "tgsi/tgsi_transform.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "draw_context.h"
+#include "draw_pipe.h"
+
+
+
+/**
+ * Subclass of pipe_shader_state to carry extra fragment shader info.
+ */
+struct pstip_fragment_shader
+{
+ struct pipe_shader_state state;
+ void *driver_fs;
+ void *pstip_fs;
+ uint sampler_unit;
+};
+
+
+/**
+ * Subclass of draw_stage
+ */
+struct pstip_stage
+{
+ struct draw_stage stage;
+
+ void *sampler_cso;
+ struct pipe_texture *texture;
+ uint num_samplers;
+ uint num_textures;
+
+ /*
+ * Currently bound state
+ */
+ struct pstip_fragment_shader *fs;
+ struct {
+ void *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ const struct pipe_poly_stipple *stipple;
+ } state;
+
+ /*
+ * Driver interface/override functions
+ */
+ void * (*driver_create_fs_state)(struct pipe_context *,
+ const struct pipe_shader_state *);
+ void (*driver_bind_fs_state)(struct pipe_context *, void *);
+ void (*driver_delete_fs_state)(struct pipe_context *, void *);
+
+ void (*driver_bind_sampler_states)(struct pipe_context *, unsigned, void **);
+
+ void (*driver_set_sampler_textures)(struct pipe_context *, unsigned,
+ struct pipe_texture **);
+
+ void (*driver_set_polygon_stipple)(struct pipe_context *,
+ const struct pipe_poly_stipple *);
+
+ struct pipe_context *pipe;
+};
+
+
+
+/**
+ * Subclass of tgsi_transform_context, used for transforming the
+ * user's fragment shader to add the special AA instructions.
+ */
+struct pstip_transform_context {
+ struct tgsi_transform_context base;
+ uint tempsUsed; /**< bitmask */
+ int wincoordInput;
+ int maxInput;
+ uint samplersUsed; /**< bitfield of samplers used */
+ int freeSampler; /** an available sampler for the pstipple */
+ int texTemp; /**< temp registers */
+ int numImmed;
+ boolean firstInstruction;
+};
+
+
+/**
+ * TGSI declaration transform callback.
+ * Look for a free sampler, a free input attrib, and two free temp regs.
+ */
+static void
+pstip_transform_decl(struct tgsi_transform_context *ctx,
+ struct tgsi_full_declaration *decl)
+{
+ struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
+
+ if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
+ uint i;
+ for (i = decl->DeclarationRange.First;
+ i <= decl->DeclarationRange.Last; i++) {
+ pctx->samplersUsed |= 1 << i;
+ }
+ }
+ else if (decl->Declaration.File == TGSI_FILE_INPUT) {
+ pctx->maxInput = MAX2(pctx->maxInput, (int) decl->DeclarationRange.Last);
+ if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION)
+ pctx->wincoordInput = (int) decl->DeclarationRange.First;
+ }
+ else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
+ uint i;
+ for (i = decl->DeclarationRange.First;
+ i <= decl->DeclarationRange.Last; i++) {
+ pctx->tempsUsed |= (1 << i);
+ }
+ }
+
+ ctx->emit_declaration(ctx, decl);
+}
+
+
+static void
+pstip_transform_immed(struct tgsi_transform_context *ctx,
+ struct tgsi_full_immediate *immed)
+{
+ struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
+ pctx->numImmed++;
+}
+
+
+/**
+ * Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
+ */
+static int
+free_bit(uint bitfield)
+{
+ int i;
+ for (i = 0; i < 32; i++) {
+ if ((bitfield & (1 << i)) == 0)
+ return i;
+ }
+ return -1;
+}
+
+
+/**
+ * TGSI instruction transform callback.
+ * Replace writes to result.color w/ a temp reg.
+ * Upon END instruction, insert texture sampling code for antialiasing.
+ */
+static void
+pstip_transform_inst(struct tgsi_transform_context *ctx,
+ struct tgsi_full_instruction *inst)
+{
+ struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
+
+ if (pctx->firstInstruction) {
+ /* emit our new declarations before the first instruction */
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction newInst;
+ uint i;
+ int wincoordInput;
+
+ /* find free sampler */
+ pctx->freeSampler = free_bit(pctx->samplersUsed);
+ if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
+ pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
+
+ if (pctx->wincoordInput < 0)
+ wincoordInput = pctx->maxInput + 1;
+ else
+ wincoordInput = pctx->wincoordInput;
+
+ /* find one free temp reg */
+ for (i = 0; i < 32; i++) {
+ if ((pctx->tempsUsed & (1 << i)) == 0) {
+ /* found a free temp */
+ if (pctx->texTemp < 0)
+ pctx->texTemp = i;
+ else
+ break;
+ }
+ }
+ assert(pctx->texTemp >= 0);
+
+ if (pctx->wincoordInput < 0) {
+ /* declare new position input reg */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ decl.Declaration.Interpolate = TGSI_INTERPOLATE_LINEAR; /* XXX? */
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = TGSI_SEMANTIC_POSITION;
+ decl.Semantic.SemanticIndex = 0;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = wincoordInput;
+ ctx->emit_declaration(ctx, &decl);
+ }
+
+ /* declare new sampler */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = pctx->freeSampler;
+ ctx->emit_declaration(ctx, &decl);
+
+ /* declare new temp regs */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ decl.DeclarationRange.First =
+ decl.DeclarationRange.Last = pctx->texTemp;
+ ctx->emit_declaration(ctx, &decl);
+
+ /* emit immediate = {1/32, 1/32, 1, 1}
+ * The index/position of this immediate will be pctx->numImmed
+ */
+ {
+ static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 };
+ struct tgsi_full_immediate immed;
+ uint size = 4;
+ immed = tgsi_default_full_immediate();
+ immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
+ immed.u[0].Float = value[0];
+ immed.u[1].Float = value[1];
+ immed.u[2].Float = value[2];
+ immed.u[3].Float = value[3];
+ ctx->emit_immediate(ctx, &immed);
+ }
+
+ pctx->firstInstruction = FALSE;
+
+
+ /*
+ * Insert new MUL/TEX/KILP instructions at start of program
+ * Take gl_FragCoord, divide by 32 (stipple size), sample the
+ * texture and kill fragment if needed.
+ *
+ * We'd like to use non-normalized texcoords to index into a RECT
+ * texture, but we can only use GL_REPEAT wrap mode with normalized
+ * texcoords. Darn.
+ */
+
+ /* MUL texTemp, INPUT[wincoord], 1/32; */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = pctx->texTemp;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = wincoordInput;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_IMMEDIATE;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = pctx->numImmed;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* TEX texTemp, texTemp, sampler; */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
+ newInst.Instruction.NumDstRegs = 1;
+ newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullDstRegisters[0].DstRegister.Index = pctx->texTemp;
+ newInst.Instruction.NumSrcRegs = 2;
+ newInst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = pctx->texTemp;
+ newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ newInst.FullSrcRegisters[1].SrcRegister.Index = pctx->freeSampler;
+ ctx->emit_instruction(ctx, &newInst);
+
+ /* KIL -texTemp; # if -texTemp < 0, KILL fragment */
+ newInst = tgsi_default_full_instruction();
+ newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
+ newInst.Instruction.NumDstRegs = 0;
+ newInst.Instruction.NumSrcRegs = 1;
+ newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+ newInst.FullSrcRegisters[0].SrcRegister.Index = pctx->texTemp;
+ newInst.FullSrcRegisters[0].SrcRegister.Negate = 1;
+ ctx->emit_instruction(ctx, &newInst);
+ }
+
+ /* emit this instruction */
+ ctx->emit_instruction(ctx, inst);
+}
+
+
+/**
+ * Generate the frag shader we'll use for doing polygon stipple.
+ * This will be the user's shader prefixed with a TEX and KIL instruction.
+ */
+static boolean
+generate_pstip_fs(struct pstip_stage *pstip)
+{
+ const struct pipe_shader_state *orig_fs = &pstip->fs->state;
+ /*struct draw_context *draw = pstip->stage.draw;*/
+ struct pipe_shader_state pstip_fs;
+ struct pstip_transform_context transform;
+
+#define MAX 1000
+
+ pstip_fs = *orig_fs; /* copy to init */
+ pstip_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
+ if (pstip_fs.tokens == NULL)
+ return FALSE;
+
+ memset(&transform, 0, sizeof(transform));
+ transform.wincoordInput = -1;
+ transform.maxInput = -1;
+ transform.texTemp = -1;
+ transform.firstInstruction = TRUE;
+ transform.base.transform_instruction = pstip_transform_inst;
+ transform.base.transform_declaration = pstip_transform_decl;
+ transform.base.transform_immediate = pstip_transform_immed;
+
+ tgsi_transform_shader(orig_fs->tokens,
+ (struct tgsi_token *) pstip_fs.tokens,
+ MAX, &transform.base);
+
+#if 0 /* DEBUG */
+ tgsi_dump(orig_fs->tokens, 0);
+ tgsi_dump(pstip_fs.tokens, 0);
+#endif
+
+ pstip->fs->sampler_unit = transform.freeSampler;
+ assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
+
+ pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
+
+ FREE((void *)pstip_fs.tokens);
+ return TRUE;
+}
+
+
+/**
+ * Load texture image with current stipple pattern.
+ */
+static void
+pstip_update_texture(struct pstip_stage *pstip)
+{
+ static const uint bit31 = 1 << 31;
+ struct pipe_context *pipe = pstip->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_transfer *transfer;
+ const uint *stipple = pstip->state.stipple->stipple;
+ uint i, j;
+ ubyte *data;
+
+ /* XXX: want to avoid flushing just because we use stipple:
+ */
+ pipe->flush( pipe, PIPE_FLUSH_TEXTURE_CACHE, NULL );
+
+ transfer = screen->get_tex_transfer(screen, pstip->texture, 0, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0, 32, 32);
+ data = screen->transfer_map(screen, transfer);
+
+ /*
+ * Load alpha texture.
+ * Note: 0 means keep the fragment, 255 means kill it.
+ * We'll negate the texel value and use KILP which kills if value
+ * is negative.
+ */
+ for (i = 0; i < 32; i++) {
+ for (j = 0; j < 32; j++) {
+ if (stipple[i] & (bit31 >> j)) {
+ /* fragment "on" */
+ data[i * transfer->stride + j] = 0;
+ }
+ else {
+ /* fragment "off" */
+ data[i * transfer->stride + j] = 255;
+ }
+ }
+ }
+
+ /* unmap */
+ screen->transfer_unmap(screen, transfer);
+ screen->tex_transfer_destroy(transfer);
+}
+
+
+/**
+ * Create the texture map we'll use for stippling.
+ */
+static boolean
+pstip_create_texture(struct pstip_stage *pstip)
+{
+ struct pipe_context *pipe = pstip->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture texTemp;
+
+ memset(&texTemp, 0, sizeof(texTemp));
+ texTemp.target = PIPE_TEXTURE_2D;
+ texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
+ texTemp.last_level = 0;
+ texTemp.width[0] = 32;
+ texTemp.height[0] = 32;
+ texTemp.depth[0] = 1;
+ pf_get_block(texTemp.format, &texTemp.block);
+
+ pstip->texture = screen->texture_create(screen, &texTemp);
+ if (pstip->texture == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * Create the sampler CSO that'll be used for stippling.
+ */
+static boolean
+pstip_create_sampler(struct pstip_stage *pstip)
+{
+ struct pipe_sampler_state sampler;
+ struct pipe_context *pipe = pstip->pipe;
+
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
+ sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
+ sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.normalized_coords = 1;
+ sampler.min_lod = 0.0f;
+ sampler.max_lod = 0.0f;
+
+ pstip->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
+ if (pstip->sampler_cso == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * When we're about to draw our first stipple polygon in a batch, this function
+ * is called to tell the driver to bind our modified fragment shader.
+ */
+static boolean
+bind_pstip_fragment_shader(struct pstip_stage *pstip)
+{
+ struct draw_context *draw = pstip->stage.draw;
+ if (!pstip->fs->pstip_fs &&
+ !generate_pstip_fs(pstip))
+ return FALSE;
+
+ draw->suspend_flushing = TRUE;
+ pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
+ draw->suspend_flushing = FALSE;
+ return TRUE;
+}
+
+
+static INLINE struct pstip_stage *
+pstip_stage( struct draw_stage *stage )
+{
+ return (struct pstip_stage *) stage;
+}
+
+
+static void
+pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
+{
+ struct pstip_stage *pstip = pstip_stage(stage);
+ struct pipe_context *pipe = pstip->pipe;
+ struct draw_context *draw = stage->draw;
+ uint num_samplers;
+
+ assert(stage->draw->rasterizer->poly_stipple_enable);
+
+ /* bind our fragprog */
+ if (!bind_pstip_fragment_shader(pstip)) {
+ stage->tri = draw_pipe_passthrough_tri;
+ stage->tri(stage, header);
+ return;
+ }
+
+
+ /* how many samplers? */
+ /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
+ num_samplers = MAX2(pstip->num_textures, pstip->num_samplers);
+ num_samplers = MAX2(num_samplers, pstip->fs->sampler_unit + 1);
+
+ /* plug in our sampler, texture */
+ pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso;
+ pipe_texture_reference(&pstip->state.textures[pstip->fs->sampler_unit],
+ pstip->texture);
+
+ assert(num_samplers <= PIPE_MAX_SAMPLERS);
+
+ draw->suspend_flushing = TRUE;
+ pstip->driver_bind_sampler_states(pipe, num_samplers, pstip->state.samplers);
+ pstip->driver_set_sampler_textures(pipe, num_samplers, pstip->state.textures);
+ draw->suspend_flushing = FALSE;
+
+ /* now really draw first triangle */
+ stage->tri = draw_pipe_passthrough_tri;
+ stage->tri(stage, header);
+}
+
+
+static void
+pstip_flush(struct draw_stage *stage, unsigned flags)
+{
+ struct draw_context *draw = stage->draw;
+ struct pstip_stage *pstip = pstip_stage(stage);
+ struct pipe_context *pipe = pstip->pipe;
+
+ stage->tri = pstip_first_tri;
+ stage->next->flush( stage->next, flags );
+
+ /* restore original frag shader, texture, sampler state */
+ draw->suspend_flushing = TRUE;
+ pstip->driver_bind_fs_state(pipe, pstip->fs->driver_fs);
+ pstip->driver_bind_sampler_states(pipe, pstip->num_samplers,
+ pstip->state.samplers);
+ pstip->driver_set_sampler_textures(pipe, pstip->num_textures,
+ pstip->state.textures);
+ draw->suspend_flushing = FALSE;
+}
+
+
+static void
+pstip_reset_stipple_counter(struct draw_stage *stage)
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void
+pstip_destroy(struct draw_stage *stage)
+{
+ struct pstip_stage *pstip = pstip_stage(stage);
+ uint i;
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ pipe_texture_reference(&pstip->state.textures[i], NULL);
+ }
+
+ pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso);
+
+ pipe_texture_reference(&pstip->texture, NULL);
+
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+static struct pstip_stage *
+draw_pstip_stage(struct draw_context *draw)
+{
+ struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
+
+ draw_alloc_temp_verts( &pstip->stage, 8 );
+
+ pstip->stage.draw = draw;
+ pstip->stage.name = "pstip";
+ pstip->stage.next = NULL;
+ pstip->stage.point = draw_pipe_passthrough_point;
+ pstip->stage.line = draw_pipe_passthrough_line;
+ pstip->stage.tri = pstip_first_tri;
+ pstip->stage.flush = pstip_flush;
+ pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter;
+ pstip->stage.destroy = pstip_destroy;
+
+ return pstip;
+}
+
+
+static struct pstip_stage *
+pstip_stage_from_pipe(struct pipe_context *pipe)
+{
+ struct draw_context *draw = (struct draw_context *) pipe->draw;
+ return pstip_stage(draw->pipeline.pstipple);
+}
+
+
+/**
+ * This function overrides the driver's create_fs_state() function and
+ * will typically be called by the state tracker.
+ */
+static void *
+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);
+
+ if (aafs) {
+ aafs->state = *fs;
+
+ /* pass-through */
+ aafs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
+ }
+
+ return aafs;
+}
+
+
+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;
+ /* save current */
+ pstip->fs = aafs;
+ /* pass-through */
+ pstip->driver_bind_fs_state(pstip->pipe,
+ (aafs ? aafs->driver_fs : NULL));
+}
+
+
+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;
+ /* pass-through */
+ pstip->driver_delete_fs_state(pstip->pipe, aafs->driver_fs);
+
+ if (aafs->pstip_fs)
+ pstip->driver_delete_fs_state(pstip->pipe, aafs->pstip_fs);
+
+ FREE(aafs);
+}
+
+
+static void
+pstip_bind_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **sampler)
+{
+ struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
+ uint i;
+
+ /* save current */
+ memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
+ for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
+ pstip->state.samplers[i] = NULL;
+ }
+
+ pstip->num_samplers = num;
+ /* pass-through */
+ pstip->driver_bind_sampler_states(pstip->pipe, num, sampler);
+}
+
+
+static void
+pstip_set_sampler_textures(struct pipe_context *pipe,
+ unsigned num, struct pipe_texture **texture)
+{
+ struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
+ uint i;
+
+ /* save current */
+ for (i = 0; i < num; i++) {
+ pipe_texture_reference(&pstip->state.textures[i], texture[i]);
+ }
+ for (; i < PIPE_MAX_SAMPLERS; i++) {
+ pipe_texture_reference(&pstip->state.textures[i], NULL);
+ }
+
+ pstip->num_textures = num;
+
+ /* pass-through */
+ pstip->driver_set_sampler_textures(pstip->pipe, num, texture);
+}
+
+
+static void
+pstip_set_polygon_stipple(struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple)
+{
+ struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
+
+ /* save current */
+ pstip->state.stipple = stipple;
+
+ /* pass-through */
+ pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
+
+ pstip_update_texture(pstip);
+}
+
+
+/**
+ * Called by drivers that want to install this polygon stipple stage
+ * into the draw module's pipeline. This will not be used if the
+ * hardware has native support for polygon stipple.
+ */
+boolean
+draw_install_pstipple_stage(struct draw_context *draw,
+ struct pipe_context *pipe)
+{
+ struct pstip_stage *pstip;
+
+ pipe->draw = (void *) draw;
+
+ /*
+ * Create / install pgon stipple drawing / prim stage
+ */
+ pstip = draw_pstip_stage( draw );
+ if (pstip == NULL)
+ goto fail;
+
+ draw->pipeline.pstipple = &pstip->stage;
+
+ pstip->pipe = pipe;
+
+ /* create special texture, sampler state */
+ if (!pstip_create_texture(pstip))
+ goto fail;
+
+ if (!pstip_create_sampler(pstip))
+ goto fail;
+
+ /* save original driver functions */
+ pstip->driver_create_fs_state = pipe->create_fs_state;
+ pstip->driver_bind_fs_state = pipe->bind_fs_state;
+ pstip->driver_delete_fs_state = pipe->delete_fs_state;
+
+ pstip->driver_bind_sampler_states = pipe->bind_sampler_states;
+ pstip->driver_set_sampler_textures = pipe->set_sampler_textures;
+ pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple;
+
+ /* override the driver's functions */
+ pipe->create_fs_state = pstip_create_fs_state;
+ pipe->bind_fs_state = pstip_bind_fs_state;
+ pipe->delete_fs_state = pstip_delete_fs_state;
+
+ pipe->bind_sampler_states = pstip_bind_sampler_states;
+ pipe->set_sampler_textures = pstip_set_sampler_textures;
+ pipe->set_polygon_stipple = pstip_set_polygon_stipple;
+
+ return TRUE;
+
+ fail:
+ if (pstip)
+ pstip->stage.destroy( &pstip->stage );
+
+ return FALSE;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_stipple.c b/src/gallium/auxiliary/draw/draw_pipe_stipple.c
new file mode 100644
index 0000000000..6e921bac27
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_stipple.c
@@ -0,0 +1,251 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/* Implement line stipple by cutting lines up into smaller lines.
+ * There are hundreds of ways to implement line stipple, this is one
+ * choice that should work in all situations, requires no state
+ * manipulations, but with a penalty in terms of large amounts of
+ * generated geometry.
+ */
+
+
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "draw/draw_pipe.h"
+
+
+/** Subclass of draw_stage */
+struct stipple_stage {
+ struct draw_stage stage;
+ float counter;
+ uint pattern;
+ uint factor;
+};
+
+
+static INLINE struct stipple_stage *
+stipple_stage(struct draw_stage *stage)
+{
+ return (struct stipple_stage *) stage;
+}
+
+
+/**
+ * Compute interpolated vertex attributes for 'dst' at position 't'
+ * between 'v0' and 'v1'.
+ * XXX using linear interpolation for all attribs at this time.
+ */
+static void
+screen_interp( struct draw_context *draw,
+ struct vertex_header *dst,
+ float t,
+ const struct vertex_header *v0,
+ const struct vertex_header *v1 )
+{
+ uint attr;
+ for (attr = 0; attr < draw->vs.num_vs_outputs; attr++) {
+ const float *val0 = v0->data[attr];
+ const float *val1 = v1->data[attr];
+ float *newv = dst->data[attr];
+ uint i;
+ for (i = 0; i < 4; i++) {
+ newv[i] = val0[i] + t * (val1[i] - val0[i]);
+ }
+ }
+}
+
+
+static void
+emit_segment(struct draw_stage *stage, struct prim_header *header,
+ float t0, float t1)
+{
+ struct vertex_header *v0new = dup_vert(stage, header->v[0], 0);
+ struct vertex_header *v1new = dup_vert(stage, header->v[1], 1);
+ struct prim_header newprim = *header;
+
+ if (t0 > 0.0) {
+ screen_interp( stage->draw, v0new, t0, header->v[0], header->v[1] );
+ newprim.v[0] = v0new;
+ }
+
+ if (t1 < 1.0) {
+ screen_interp( stage->draw, v1new, t1, header->v[0], header->v[1] );
+ newprim.v[1] = v1new;
+ }
+
+ stage->next->line( stage->next, &newprim );
+}
+
+
+static INLINE unsigned
+stipple_test(int counter, ushort pattern, int factor)
+{
+ int b = (counter / factor) & 0xf;
+ return (1 << b) & pattern;
+}
+
+
+static void
+stipple_line(struct draw_stage *stage, struct prim_header *header)
+{
+ struct stipple_stage *stipple = stipple_stage(stage);
+ struct vertex_header *v0 = header->v[0];
+ struct vertex_header *v1 = header->v[1];
+ const unsigned pos = stage->draw->vs.position_output;
+ const float *pos0 = v0->data[pos];
+ const float *pos1 = v1->data[pos];
+ float start = 0;
+ int state = 0;
+
+ float x0 = pos0[0];
+ float x1 = pos1[0];
+ float y0 = pos0[1];
+ float y1 = pos1[1];
+
+ float dx = x0 > x1 ? x0 - x1 : x1 - x0;
+ float dy = y0 > y1 ? y0 - y1 : y1 - y0;
+
+ float length = MAX2(dx, dy);
+ int i;
+
+ if (header->flags & DRAW_PIPE_RESET_STIPPLE)
+ stipple->counter = 0;
+
+
+ /* XXX ToDo: intead of iterating pixel-by-pixel, use a look-up table.
+ */
+ for (i = 0; i < length; i++) {
+ int result = stipple_test( (int) stipple->counter+i,
+ (ushort) stipple->pattern, stipple->factor );
+ if (result != state) {
+ /* changing from "off" to "on" or vice versa */
+ if (state) {
+ if (start != i) {
+ /* finishing an "on" segment */
+ emit_segment( stage, header, start / length, i / length );
+ }
+ }
+ else {
+ /* starting an "on" segment */
+ start = (float) i;
+ }
+ state = result;
+ }
+ }
+
+ if (state && start < length)
+ emit_segment( stage, header, start / length, 1.0 );
+
+ stipple->counter += length;
+}
+
+
+static void
+reset_stipple_counter(struct draw_stage *stage)
+{
+ struct stipple_stage *stipple = stipple_stage(stage);
+ stipple->counter = 0;
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+static void
+stipple_reset_point(struct draw_stage *stage, struct prim_header *header)
+{
+ struct stipple_stage *stipple = stipple_stage(stage);
+ stipple->counter = 0;
+ stage->next->point(stage->next, header);
+}
+
+static void
+stipple_reset_tri(struct draw_stage *stage, struct prim_header *header)
+{
+ struct stipple_stage *stipple = stipple_stage(stage);
+ stipple->counter = 0;
+ stage->next->tri(stage->next, header);
+}
+
+
+static void
+stipple_first_line(struct draw_stage *stage,
+ struct prim_header *header)
+{
+ struct stipple_stage *stipple = stipple_stage(stage);
+ struct draw_context *draw = stage->draw;
+
+ stipple->pattern = draw->rasterizer->line_stipple_pattern;
+ stipple->factor = draw->rasterizer->line_stipple_factor + 1;
+
+ stage->line = stipple_line;
+ stage->line( stage, header );
+}
+
+
+static void
+stipple_flush(struct draw_stage *stage, unsigned flags)
+{
+ stage->line = stipple_first_line;
+ stage->next->flush( stage->next, flags );
+}
+
+
+
+
+static void
+stipple_destroy( struct draw_stage *stage )
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+/**
+ * Create line stippler stage
+ */
+struct draw_stage *draw_stipple_stage( struct draw_context *draw )
+{
+ struct stipple_stage *stipple = CALLOC_STRUCT(stipple_stage);
+
+ draw_alloc_temp_verts( &stipple->stage, 2 );
+
+ stipple->stage.draw = draw;
+ stipple->stage.name = "stipple";
+ stipple->stage.next = NULL;
+ stipple->stage.point = stipple_reset_point;
+ stipple->stage.line = stipple_first_line;
+ stipple->stage.tri = stipple_reset_tri;
+ stipple->stage.reset_stipple_counter = reset_stipple_counter;
+ stipple->stage.flush = stipple_flush;
+ stipple->stage.destroy = stipple_destroy;
+
+ return &stipple->stage;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_twoside.c b/src/gallium/auxiliary/draw/draw_pipe_twoside.c
new file mode 100644
index 0000000000..eef0238b15
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_twoside.c
@@ -0,0 +1,200 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw_vs.h"
+#include "draw_pipe.h"
+
+struct twoside_stage {
+ struct draw_stage stage;
+ float sign; /**< +1 or -1 */
+ uint attrib_front0, attrib_back0;
+ uint attrib_front1, attrib_back1;
+};
+
+
+static INLINE struct twoside_stage *twoside_stage( struct draw_stage *stage )
+{
+ return (struct twoside_stage *)stage;
+}
+
+
+
+
+/**
+ * Copy back color(s) to front color(s).
+ */
+static INLINE struct vertex_header *
+copy_bfc( struct twoside_stage *twoside,
+ const struct vertex_header *v,
+ unsigned idx )
+{
+ struct vertex_header *tmp = dup_vert( &twoside->stage, v, idx );
+
+ if (twoside->attrib_back0) {
+ COPY_4FV(tmp->data[twoside->attrib_front0],
+ tmp->data[twoside->attrib_back0]);
+ }
+ if (twoside->attrib_back1) {
+ COPY_4FV(tmp->data[twoside->attrib_front1],
+ tmp->data[twoside->attrib_back1]);
+ }
+
+ return tmp;
+}
+
+
+/* Twoside tri:
+ */
+static void twoside_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct twoside_stage *twoside = twoside_stage(stage);
+
+ if (header->det * twoside->sign < 0.0) {
+ /* this is a back-facing triangle */
+ struct prim_header tmp;
+
+ tmp.det = header->det;
+ tmp.flags = header->flags;
+ tmp.pad = header->pad;
+ /* copy back attribs to front attribs */
+ tmp.v[0] = copy_bfc(twoside, header->v[0], 0);
+ tmp.v[1] = copy_bfc(twoside, header->v[1], 1);
+ tmp.v[2] = copy_bfc(twoside, header->v[2], 2);
+
+ stage->next->tri( stage->next, &tmp );
+ }
+ else {
+ stage->next->tri( stage->next, header );
+ }
+}
+
+
+
+static void twoside_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct twoside_stage *twoside = twoside_stage(stage);
+ const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
+ uint i;
+
+ twoside->attrib_front0 = 0;
+ twoside->attrib_front1 = 0;
+ twoside->attrib_back0 = 0;
+ twoside->attrib_back1 = 0;
+
+ /* Find which vertex shader outputs are front/back colors */
+ for (i = 0; i < vs->info.num_outputs; i++) {
+ if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR) {
+ if (vs->info.output_semantic_index[i] == 0)
+ twoside->attrib_front0 = i;
+ else
+ twoside->attrib_front1 = i;
+ }
+ if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
+ if (vs->info.output_semantic_index[i] == 0)
+ twoside->attrib_back0 = i;
+ else
+ twoside->attrib_back1 = i;
+ }
+ }
+
+ if (!twoside->attrib_back0)
+ twoside->attrib_front0 = 0;
+
+ if (!twoside->attrib_back1)
+ twoside->attrib_front1 = 0;
+
+ /*
+ * We'll multiply the primitive's determinant by this sign to determine
+ * if the triangle is back-facing (negative).
+ * sign = -1 for CCW, +1 for CW
+ */
+ twoside->sign = (stage->draw->rasterizer->front_winding == PIPE_WINDING_CCW) ? -1.0f : 1.0f;
+
+ stage->tri = twoside_tri;
+ stage->tri( stage, header );
+}
+
+
+static void twoside_flush( struct draw_stage *stage, unsigned flags )
+{
+ stage->tri = twoside_first_tri;
+ stage->next->flush( stage->next, flags );
+}
+
+
+static void twoside_reset_stipple_counter( struct draw_stage *stage )
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void twoside_destroy( struct draw_stage *stage )
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+/**
+ * Create twoside pipeline stage.
+ */
+struct draw_stage *draw_twoside_stage( struct draw_context *draw )
+{
+ struct twoside_stage *twoside = CALLOC_STRUCT(twoside_stage);
+ if (twoside == NULL)
+ goto fail;
+
+ if (!draw_alloc_temp_verts( &twoside->stage, 3 ))
+ goto fail;
+
+ twoside->stage.draw = draw;
+ twoside->stage.name = "twoside";
+ twoside->stage.next = NULL;
+ twoside->stage.point = draw_pipe_passthrough_point;
+ twoside->stage.line = draw_pipe_passthrough_line;
+ twoside->stage.tri = twoside_first_tri;
+ twoside->stage.flush = twoside_flush;
+ twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter;
+ twoside->stage.destroy = twoside_destroy;
+
+ return &twoside->stage;
+
+ fail:
+ if (twoside)
+ twoside->stage.destroy( &twoside->stage );
+
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_unfilled.c b/src/gallium/auxiliary/draw/draw_pipe_unfilled.c
new file mode 100644
index 0000000000..03bb842e20
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_unfilled.c
@@ -0,0 +1,204 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Drawing stage for handling glPolygonMode(line/point).
+ * Convert triangles to points or lines as needed.
+ */
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_memory.h"
+#include "pipe/p_defines.h"
+#include "draw_private.h"
+#include "draw_pipe.h"
+
+
+struct unfilled_stage {
+ struct draw_stage stage;
+
+ /** [0] = front face, [1] = back face.
+ * legal values: PIPE_POLYGON_MODE_FILL, PIPE_POLYGON_MODE_LINE,
+ * and PIPE_POLYGON_MODE_POINT,
+ */
+ unsigned mode[2];
+};
+
+
+static INLINE struct unfilled_stage *unfilled_stage( struct draw_stage *stage )
+{
+ return (struct unfilled_stage *)stage;
+}
+
+
+
+static void point( struct draw_stage *stage,
+ struct vertex_header *v0 )
+{
+ struct prim_header tmp;
+ tmp.v[0] = v0;
+ stage->next->point( stage->next, &tmp );
+}
+
+static void line( struct draw_stage *stage,
+ struct vertex_header *v0,
+ struct vertex_header *v1 )
+{
+ struct prim_header tmp;
+ tmp.v[0] = v0;
+ tmp.v[1] = v1;
+ stage->next->line( stage->next, &tmp );
+}
+
+
+static void points( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct vertex_header *v0 = header->v[0];
+ struct vertex_header *v1 = header->v[1];
+ struct vertex_header *v2 = header->v[2];
+
+ if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) point( stage, v0 );
+ if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) point( stage, v1 );
+ if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) point( stage, v2 );
+}
+
+
+static void lines( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct vertex_header *v0 = header->v[0];
+ struct vertex_header *v1 = header->v[1];
+ struct vertex_header *v2 = header->v[2];
+
+ if (header->flags & DRAW_PIPE_RESET_STIPPLE)
+ stage->next->reset_stipple_counter( stage->next );
+
+ if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) line( stage, v2, v0 );
+ if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) line( stage, v0, v1 );
+ if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) line( stage, v1, v2 );
+}
+
+
+/* Unfilled tri:
+ *
+ * Note edgeflags in the vertex struct is not sufficient as we will
+ * need to manipulate them when decomposing primitives.
+ *
+ * We currently keep the vertex edgeflag and primitive edgeflag mask
+ * separate until the last possible moment.
+ */
+static void unfilled_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct unfilled_stage *unfilled = unfilled_stage(stage);
+ unsigned mode = unfilled->mode[header->det >= 0.0];
+
+ switch (mode) {
+ case PIPE_POLYGON_MODE_FILL:
+ stage->next->tri( stage->next, header );
+ break;
+ case PIPE_POLYGON_MODE_LINE:
+ lines( stage, header );
+ break;
+ case PIPE_POLYGON_MODE_POINT:
+ points( stage, header );
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+static void unfilled_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct unfilled_stage *unfilled = unfilled_stage(stage);
+
+ unfilled->mode[0] = stage->draw->rasterizer->fill_ccw; /* front */
+ unfilled->mode[1] = stage->draw->rasterizer->fill_cw; /* back */
+
+ stage->tri = unfilled_tri;
+ stage->tri( stage, header );
+}
+
+
+
+static void unfilled_flush( struct draw_stage *stage,
+ unsigned flags )
+{
+ stage->next->flush( stage->next, flags );
+
+ stage->tri = unfilled_first_tri;
+}
+
+
+static void unfilled_reset_stipple_counter( struct draw_stage *stage )
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void unfilled_destroy( struct draw_stage *stage )
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+/**
+ * Create unfilled triangle stage.
+ */
+struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
+{
+ struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage);
+ if (unfilled == NULL)
+ goto fail;
+
+ if (!draw_alloc_temp_verts( &unfilled->stage, 0 ))
+ goto fail;
+
+ unfilled->stage.draw = draw;
+ unfilled->stage.name = "unfilled";
+ unfilled->stage.next = NULL;
+ unfilled->stage.tmp = NULL;
+ unfilled->stage.point = draw_pipe_passthrough_point;
+ unfilled->stage.line = draw_pipe_passthrough_line;
+ unfilled->stage.tri = unfilled_first_tri;
+ unfilled->stage.flush = unfilled_flush;
+ unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter;
+ unfilled->stage.destroy = unfilled_destroy;
+
+ return &unfilled->stage;
+
+ fail:
+ if (unfilled)
+ unfilled->stage.destroy( &unfilled->stage );
+
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_util.c b/src/gallium/auxiliary/draw/draw_pipe_util.c
new file mode 100644
index 0000000000..e22e5fed0c
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_util.c
@@ -0,0 +1,137 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_memory.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pipe.h"
+
+
+
+void
+draw_pipe_passthrough_point(struct draw_stage *stage, struct prim_header *header)
+{
+ stage->next->point(stage->next, header);
+}
+
+void
+draw_pipe_passthrough_line(struct draw_stage *stage, struct prim_header *header)
+{
+ stage->next->line(stage->next, header);
+}
+
+void
+draw_pipe_passthrough_tri(struct draw_stage *stage, struct prim_header *header)
+{
+ stage->next->tri(stage->next, header);
+}
+
+
+
+
+
+/* This is only used for temporary verts.
+ */
+#define MAX_VERTEX_SIZE ((2 + PIPE_MAX_SHADER_OUTPUTS) * 4 * sizeof(float))
+
+
+/**
+ * Allocate space for temporary post-transform vertices, such as for clipping.
+ */
+boolean draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr )
+{
+ assert(!stage->tmp);
+
+ stage->tmp = NULL;
+ stage->nr_tmps = nr;
+
+ if (nr != 0)
+ {
+ unsigned i;
+ ubyte *store = (ubyte *) MALLOC( MAX_VERTEX_SIZE * nr );
+
+ if (store == NULL)
+ return FALSE;
+
+ stage->tmp = (struct vertex_header **) MALLOC( sizeof(struct vertex_header *) * nr );
+ if (stage->tmp == NULL) {
+ FREE(store);
+ return FALSE;
+ }
+
+ for (i = 0; i < nr; i++)
+ stage->tmp[i] = (struct vertex_header *)(store + i * MAX_VERTEX_SIZE);
+ }
+
+ return TRUE;
+}
+
+
+void draw_free_temp_verts( struct draw_stage *stage )
+{
+ if (stage->tmp) {
+ FREE( stage->tmp[0] );
+ FREE( stage->tmp );
+ stage->tmp = NULL;
+ }
+}
+
+
+/* Reset vertex ids. This is basically a type of flush.
+ *
+ * Called only from draw_pipe_vbuf.c
+ */
+void draw_reset_vertex_ids(struct draw_context *draw)
+{
+ struct draw_stage *stage = draw->pipeline.first;
+
+ while (stage) {
+ unsigned i;
+
+ for (i = 0; i < stage->nr_tmps; i++)
+ stage->tmp[i]->vertex_id = UNDEFINED_VERTEX_ID;
+
+ stage = stage->next;
+ }
+
+ if (draw->pipeline.verts)
+ {
+ unsigned i;
+ char *verts = draw->pipeline.verts;
+ unsigned stride = draw->pipeline.vertex_stride;
+
+ for (i = 0; i < draw->pipeline.vertex_count; i++) {
+ ((struct vertex_header *)verts)->vertex_id = UNDEFINED_VERTEX_ID;
+ verts += stride;
+ }
+ }
+}
+
diff --git a/src/gallium/auxiliary/draw/draw_pipe_validate.c b/src/gallium/auxiliary/draw/draw_pipe_validate.c
new file mode 100644
index 0000000000..bea90e50d3
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_validate.c
@@ -0,0 +1,339 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_memory.h"
+#include "pipe/p_defines.h"
+#include "draw_private.h"
+#include "draw_pipe.h"
+#include "draw_context.h"
+#include "draw_vbuf.h"
+
+static boolean points( unsigned prim )
+{
+ return (prim == PIPE_PRIM_POINTS);
+}
+
+static boolean lines( unsigned prim )
+{
+ return (prim == PIPE_PRIM_LINES ||
+ prim == PIPE_PRIM_LINE_STRIP ||
+ prim == PIPE_PRIM_LINE_LOOP);
+}
+
+static boolean triangles( unsigned prim )
+{
+ return prim >= PIPE_PRIM_TRIANGLES;
+}
+
+/**
+ * Default version of a function to check if we need any special
+ * pipeline stages, or whether prims/verts can go through untouched.
+ * Don't test for bypass clipping or vs modes, this function is just
+ * about the primitive pipeline stages.
+ *
+ * This can be overridden by the driver.
+ */
+boolean
+draw_need_pipeline(const struct draw_context *draw,
+ const struct pipe_rasterizer_state *rasterizer,
+ unsigned int prim )
+{
+ /* If the driver has overridden this, use that version:
+ */
+ if (draw->render &&
+ draw->render->need_pipeline)
+ {
+ return draw->render->need_pipeline( draw->render,
+ rasterizer,
+ prim );
+ }
+
+ /* Don't have to worry about triangles turning into lines/points
+ * and triggering the pipeline, because we have to trigger the
+ * pipeline *anyway* if unfilled mode is active.
+ */
+ if (lines(prim))
+ {
+ /* line stipple */
+ if (rasterizer->line_stipple_enable && draw->pipeline.line_stipple)
+ return TRUE;
+
+ /* wide lines */
+ if (rasterizer->line_width > draw->pipeline.wide_line_threshold)
+ return TRUE;
+
+ /* AA lines */
+ if (rasterizer->line_smooth && draw->pipeline.aaline)
+ return TRUE;
+ }
+
+ if (points(prim))
+ {
+ /* large points */
+ if (rasterizer->point_size > draw->pipeline.wide_point_threshold)
+ return TRUE;
+
+ /* AA points */
+ if (rasterizer->point_smooth && draw->pipeline.aapoint)
+ return TRUE;
+
+ /* point sprites */
+ if (rasterizer->point_sprite && draw->pipeline.point_sprite)
+ return TRUE;
+ }
+
+
+ if (triangles(prim))
+ {
+ /* polygon stipple */
+ if (rasterizer->poly_stipple_enable && draw->pipeline.pstipple)
+ return TRUE;
+
+ /* unfilled polygons */
+ if (rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
+ rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL)
+ return TRUE;
+
+ /* polygon offset */
+ if (rasterizer->offset_cw || rasterizer->offset_ccw)
+ return TRUE;
+
+ /* two-side lighting */
+ if (rasterizer->light_twoside)
+ return TRUE;
+ }
+
+ /* polygon cull - this is difficult - hardware can cull just fine
+ * most of the time (though sometimes CULL_NEITHER is unsupported.
+ *
+ * Generally this isn't a reason to require the pipeline, though.
+ *
+ if (rasterizer->cull_mode)
+ return TRUE;
+ */
+
+ return FALSE;
+}
+
+
+
+/**
+ * Rebuild the rendering pipeline.
+ */
+static struct draw_stage *validate_pipeline( struct draw_stage *stage )
+{
+ struct draw_context *draw = stage->draw;
+ struct draw_stage *next = draw->pipeline.rasterize;
+ int need_det = 0;
+ int precalc_flat = 0;
+ boolean wide_lines, wide_points;
+
+ /* Set the validate's next stage to the rasterize stage, so that it
+ * can be found later if needed for flushing.
+ */
+ stage->next = next;
+
+ /* drawing wide lines? */
+ wide_lines = (draw->rasterizer->line_width > draw->pipeline.wide_line_threshold
+ && !draw->rasterizer->line_smooth);
+
+ /* drawing large points? */
+ if (draw->rasterizer->point_sprite && draw->pipeline.point_sprite)
+ wide_points = TRUE;
+ else if (draw->rasterizer->point_smooth && draw->pipeline.aapoint)
+ wide_points = FALSE;
+ else if (draw->rasterizer->point_size > draw->pipeline.wide_point_threshold)
+ wide_points = TRUE;
+ else
+ wide_points = FALSE;
+
+ /*
+ * NOTE: we build up the pipeline in end-to-start order.
+ *
+ * TODO: make the current primitive part of the state and build
+ * shorter pipelines for lines & points.
+ */
+
+ if (draw->rasterizer->line_smooth && draw->pipeline.aaline) {
+ draw->pipeline.aaline->next = next;
+ next = draw->pipeline.aaline;
+ }
+
+ if (draw->rasterizer->point_smooth && draw->pipeline.aapoint) {
+ draw->pipeline.aapoint->next = next;
+ next = draw->pipeline.aapoint;
+ }
+
+ if (wide_lines) {
+ draw->pipeline.wide_line->next = next;
+ next = draw->pipeline.wide_line;
+ precalc_flat = 1;
+ }
+
+ if (wide_points || draw->rasterizer->point_sprite) {
+ draw->pipeline.wide_point->next = next;
+ next = draw->pipeline.wide_point;
+ }
+
+ if (draw->rasterizer->line_stipple_enable && draw->pipeline.line_stipple) {
+ draw->pipeline.stipple->next = next;
+ next = draw->pipeline.stipple;
+ precalc_flat = 1; /* only needed for lines really */
+ }
+
+ if (draw->rasterizer->poly_stipple_enable
+ && draw->pipeline.pstipple) {
+ draw->pipeline.pstipple->next = next;
+ next = draw->pipeline.pstipple;
+ }
+
+ if (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
+ draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) {
+ draw->pipeline.unfilled->next = next;
+ next = draw->pipeline.unfilled;
+ precalc_flat = 1; /* only needed for triangles really */
+ need_det = 1;
+ }
+
+ if (draw->rasterizer->flatshade && precalc_flat) {
+ draw->pipeline.flatshade->next = next;
+ next = draw->pipeline.flatshade;
+ }
+
+ if (draw->rasterizer->offset_cw ||
+ draw->rasterizer->offset_ccw) {
+ draw->pipeline.offset->next = next;
+ next = draw->pipeline.offset;
+ need_det = 1;
+ }
+
+ if (draw->rasterizer->light_twoside) {
+ draw->pipeline.twoside->next = next;
+ next = draw->pipeline.twoside;
+ need_det = 1;
+ }
+
+ /* Always run the cull stage as we calculate determinant there
+ * also.
+ *
+ * This can actually be a win as culling out the triangles can lead
+ * to less work emitting vertices, smaller vertex buffers, etc.
+ * It's difficult to say whether this will be true in general.
+ */
+ if (need_det || draw->rasterizer->cull_mode) {
+ draw->pipeline.cull->next = next;
+ next = draw->pipeline.cull;
+ }
+
+ /* Clip stage
+ */
+ if (!draw->bypass_clipping)
+ {
+ draw->pipeline.clip->next = next;
+ next = draw->pipeline.clip;
+ }
+
+
+ draw->pipeline.first = next;
+
+ if (0) {
+ debug_printf("draw pipeline:\n");
+ for (next = draw->pipeline.first; next ; next = next->next )
+ debug_printf(" %s\n", next->name);
+ debug_printf("\n");
+ }
+
+ return draw->pipeline.first;
+}
+
+static void validate_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct draw_stage *pipeline = validate_pipeline( stage );
+ pipeline->tri( pipeline, header );
+}
+
+static void validate_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct draw_stage *pipeline = validate_pipeline( stage );
+ pipeline->line( pipeline, header );
+}
+
+static void validate_point( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct draw_stage *pipeline = validate_pipeline( stage );
+ pipeline->point( pipeline, header );
+}
+
+static void validate_reset_stipple_counter( struct draw_stage *stage )
+{
+ struct draw_stage *pipeline = validate_pipeline( stage );
+ pipeline->reset_stipple_counter( pipeline );
+}
+
+static void validate_flush( struct draw_stage *stage,
+ unsigned flags )
+{
+ /* May need to pass a backend flush on to the rasterize stage.
+ */
+ if (stage->next)
+ stage->next->flush( stage->next, flags );
+}
+
+
+static void validate_destroy( struct draw_stage *stage )
+{
+ FREE( stage );
+}
+
+
+/**
+ * Create validate pipeline stage.
+ */
+struct draw_stage *draw_validate_stage( struct draw_context *draw )
+{
+ struct draw_stage *stage = CALLOC_STRUCT(draw_stage);
+ if (stage == NULL)
+ return NULL;
+
+ stage->draw = draw;
+ stage->name = "validate";
+ stage->next = NULL;
+ stage->point = validate_point;
+ stage->line = validate_line;
+ stage->tri = validate_tri;
+ stage->flush = validate_flush;
+ stage->reset_stipple_counter = validate_reset_stipple_counter;
+ stage->destroy = validate_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
new file mode 100644
index 0000000000..1a5269c0de
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
@@ -0,0 +1,492 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Vertex buffer drawing stage.
+ *
+ * \author Jose Fonseca <jrfonsec@tungstengraphics.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "util/u_debug.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "draw_vbuf.h"
+#include "draw_private.h"
+#include "draw_vertex.h"
+#include "draw_pipe.h"
+#include "translate/translate.h"
+#include "translate/translate_cache.h"
+
+
+/**
+ * Vertex buffer emit stage.
+ */
+struct vbuf_stage {
+ struct draw_stage stage; /**< This must be first (base class) */
+
+ struct vbuf_render *render;
+
+ const struct vertex_info *vinfo;
+
+ /** Vertex size in bytes */
+ unsigned vertex_size;
+
+ struct translate *translate;
+
+ /* FIXME: we have no guarantee that 'unsigned' is 32bit */
+
+ /** Vertices in hardware format */
+ unsigned *vertices;
+ unsigned *vertex_ptr;
+ unsigned max_vertices;
+ unsigned nr_vertices;
+
+ /** Indices */
+ ushort *indices;
+ unsigned max_indices;
+ unsigned nr_indices;
+
+ /* Cache point size somewhere it's address won't change:
+ */
+ float point_size;
+
+ struct translate_cache *cache;
+};
+
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct vbuf_stage *
+vbuf_stage( struct draw_stage *stage )
+{
+ assert(stage);
+ return (struct vbuf_stage *)stage;
+}
+
+
+static void vbuf_flush_vertices( struct vbuf_stage *vbuf );
+static void vbuf_alloc_vertices( struct vbuf_stage *vbuf );
+
+
+static INLINE boolean
+overflow( void *map, void *ptr, unsigned bytes, unsigned bufsz )
+{
+ unsigned long used = (unsigned long) ((char *)ptr - (char *)map);
+ return (used + bytes) > bufsz;
+}
+
+
+static INLINE void
+check_space( struct vbuf_stage *vbuf, unsigned nr )
+{
+ if (vbuf->nr_vertices + nr > vbuf->max_vertices ||
+ vbuf->nr_indices + nr > vbuf->max_indices)
+ {
+ vbuf_flush_vertices( vbuf );
+ vbuf_alloc_vertices( vbuf );
+ }
+}
+
+
+
+
+/**
+ * Extract the needed fields from post-transformed vertex and emit
+ * a hardware(driver) vertex.
+ * Recall that the vertices are constructed by the 'draw' module and
+ * have a couple of slots at the beginning (1-dword header, 4-dword
+ * clip pos) that we ignore here. We only use the vertex->data[] fields.
+ */
+static INLINE ushort
+emit_vertex( struct vbuf_stage *vbuf,
+ struct vertex_header *vertex )
+{
+ if(vertex->vertex_id == UNDEFINED_VERTEX_ID) {
+ /* Hmm - vertices are emitted one at a time - better make sure
+ * set_buffer is efficient. Consider a special one-shot mode for
+ * translate.
+ */
+ /* Note: we really do want data[0] here, not data[pos]:
+ */
+ vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0);
+ vbuf->translate->run(vbuf->translate, 0, 1, vbuf->vertex_ptr);
+
+ if (0) draw_dump_emitted_vertex(vbuf->vinfo, (uint8_t *)vbuf->vertex_ptr);
+
+ vbuf->vertex_ptr += vbuf->vertex_size/4;
+ vertex->vertex_id = vbuf->nr_vertices++;
+ }
+
+ return (ushort)vertex->vertex_id;
+}
+
+
+static void
+vbuf_tri( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+ unsigned i;
+
+ check_space( vbuf, 3 );
+
+ if (vbuf->stage.draw->rasterizer->flatshade_first) {
+ /* Put provoking vertex in position expected by the driver.
+ * Emit last provoking vertex in first pos.
+ * Swap verts 0 & 1 to preserve polygon winding.
+ */
+ vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[2] );
+ vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[0] );
+ vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[1] );
+ }
+ else {
+ for (i = 0; i < 3; i++) {
+ vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
+ }
+ }
+}
+
+
+static void
+vbuf_line( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+ unsigned i;
+
+ check_space( vbuf, 2 );
+
+ for (i = 0; i < 2; i++) {
+ vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
+ }
+}
+
+
+static void
+vbuf_point( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ check_space( vbuf, 1 );
+
+ vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[0] );
+}
+
+
+
+
+/**
+ * Set the prim type for subsequent vertices.
+ * This may result in a new vertex size. The existing vbuffer (if any)
+ * will be flushed if needed and a new one allocated.
+ */
+static void
+vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
+{
+ struct translate_key hw_key;
+ unsigned dst_offset;
+ unsigned i;
+
+ vbuf->render->set_primitive(vbuf->render, prim);
+
+ /* Must do this after set_primitive() above:
+ *
+ * XXX: need some state managment to track when this needs to be
+ * recalculated. The driver should tell us whether there was a
+ * state change.
+ */
+ vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
+ vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);
+
+ /* Translate from pipeline vertices to hw vertices.
+ */
+ dst_offset = 0;
+
+ for (i = 0; i < vbuf->vinfo->num_attribs; i++) {
+ unsigned emit_sz = 0;
+ unsigned src_buffer = 0;
+ unsigned output_format;
+ unsigned src_offset = (vbuf->vinfo->attrib[i].src_index * 4 * sizeof(float) );
+
+ switch (vbuf->vinfo->attrib[i].emit) {
+ case EMIT_4F:
+ output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ emit_sz = 4 * sizeof(float);
+ break;
+ case EMIT_3F:
+ output_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ emit_sz = 3 * sizeof(float);
+ break;
+ case EMIT_2F:
+ output_format = PIPE_FORMAT_R32G32_FLOAT;
+ emit_sz = 2 * sizeof(float);
+ break;
+ case EMIT_1F:
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ break;
+ case EMIT_1F_PSIZE:
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ src_buffer = 1;
+ src_offset = 0;
+ break;
+ case EMIT_4UB:
+ output_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ emit_sz = 4 * sizeof(ubyte);
+ break;
+ default:
+ assert(0);
+ output_format = PIPE_FORMAT_NONE;
+ emit_sz = 0;
+ break;
+ }
+
+ hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ hw_key.element[i].input_buffer = src_buffer;
+ hw_key.element[i].input_offset = src_offset;
+ hw_key.element[i].output_format = output_format;
+ hw_key.element[i].output_offset = dst_offset;
+
+ dst_offset += emit_sz;
+ }
+
+ hw_key.nr_elements = vbuf->vinfo->num_attribs;
+ hw_key.output_stride = vbuf->vinfo->size * 4;
+
+ /* Don't bother with caching at this stage:
+ */
+ if (!vbuf->translate ||
+ translate_key_compare(&vbuf->translate->key, &hw_key) != 0)
+ {
+ translate_key_sanitize(&hw_key);
+ vbuf->translate = translate_cache_find(vbuf->cache, &hw_key);
+
+ vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0);
+ }
+
+ vbuf->point_size = vbuf->stage.draw->rasterizer->point_size;
+
+ /* Allocate new buffer?
+ */
+ assert(vbuf->vertices == NULL);
+ vbuf_alloc_vertices(vbuf);
+}
+
+
+static void
+vbuf_first_tri( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ vbuf_flush_vertices( vbuf );
+ vbuf_start_prim(vbuf, PIPE_PRIM_TRIANGLES);
+ stage->tri = vbuf_tri;
+ stage->tri( stage, prim );
+}
+
+
+static void
+vbuf_first_line( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ vbuf_flush_vertices( vbuf );
+ vbuf_start_prim(vbuf, PIPE_PRIM_LINES);
+ stage->line = vbuf_line;
+ stage->line( stage, prim );
+}
+
+
+static void
+vbuf_first_point( struct draw_stage *stage,
+ struct prim_header *prim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ vbuf_flush_vertices(vbuf);
+ vbuf_start_prim(vbuf, PIPE_PRIM_POINTS);
+ stage->point = vbuf_point;
+ stage->point( stage, prim );
+}
+
+
+
+/**
+ * Flush existing vertex buffer and allocate a new one.
+ */
+static void
+vbuf_flush_vertices( struct vbuf_stage *vbuf )
+{
+ if(vbuf->vertices) {
+
+ vbuf->render->unmap_vertices( vbuf->render, 0, vbuf->nr_vertices - 1 );
+
+ if (vbuf->nr_indices)
+ {
+ vbuf->render->draw(vbuf->render,
+ vbuf->indices,
+ vbuf->nr_indices );
+
+ vbuf->nr_indices = 0;
+ }
+
+ /* Reset temporary vertices ids */
+ if(vbuf->nr_vertices)
+ draw_reset_vertex_ids( vbuf->stage.draw );
+
+ /* Free the vertex buffer */
+ vbuf->render->release_vertices( vbuf->render );
+
+ vbuf->max_vertices = vbuf->nr_vertices = 0;
+ vbuf->vertex_ptr = vbuf->vertices = NULL;
+ }
+}
+
+
+static void
+vbuf_alloc_vertices( struct vbuf_stage *vbuf )
+{
+ assert(!vbuf->nr_indices);
+ assert(!vbuf->vertices);
+
+ /* Allocate a new vertex buffer */
+ vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size;
+
+ /* even number */
+ vbuf->max_vertices = vbuf->max_vertices & ~1;
+
+ if(vbuf->max_vertices >= UNDEFINED_VERTEX_ID)
+ vbuf->max_vertices = UNDEFINED_VERTEX_ID - 1;
+
+ /* Must always succeed -- driver gives us a
+ * 'max_vertex_buffer_bytes' which it guarantees it can allocate,
+ * and it will flush itself if necessary to do so. If this does
+ * fail, we are basically without usable hardware.
+ */
+ vbuf->render->allocate_vertices(vbuf->render,
+ (ushort) vbuf->vertex_size,
+ (ushort) vbuf->max_vertices);
+
+ vbuf->vertices = (uint *) vbuf->render->map_vertices( vbuf->render );
+
+ vbuf->vertex_ptr = vbuf->vertices;
+}
+
+
+
+static void
+vbuf_flush( struct draw_stage *stage, unsigned flags )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ vbuf_flush_vertices( vbuf );
+
+ stage->point = vbuf_first_point;
+ stage->line = vbuf_first_line;
+ stage->tri = vbuf_first_tri;
+}
+
+
+static void
+vbuf_reset_stipple_counter( struct draw_stage *stage )
+{
+ /* XXX: Need to do something here for hardware with linestipple.
+ */
+ (void) stage;
+}
+
+
+static void vbuf_destroy( struct draw_stage *stage )
+{
+ struct vbuf_stage *vbuf = vbuf_stage( stage );
+
+ if(vbuf->indices)
+ align_free( vbuf->indices );
+
+ if (vbuf->render)
+ vbuf->render->destroy( vbuf->render );
+
+ if (vbuf->cache)
+ translate_cache_destroy(vbuf->cache);
+
+ FREE( stage );
+}
+
+
+/**
+ * Create a new primitive vbuf/render stage.
+ */
+struct draw_stage *draw_vbuf_stage( struct draw_context *draw,
+ struct vbuf_render *render )
+{
+ struct vbuf_stage *vbuf = CALLOC_STRUCT(vbuf_stage);
+ if (vbuf == NULL)
+ goto fail;
+
+ vbuf->stage.draw = draw;
+ vbuf->stage.name = "vbuf";
+ vbuf->stage.point = vbuf_first_point;
+ vbuf->stage.line = vbuf_first_line;
+ vbuf->stage.tri = vbuf_first_tri;
+ vbuf->stage.flush = vbuf_flush;
+ vbuf->stage.reset_stipple_counter = vbuf_reset_stipple_counter;
+ vbuf->stage.destroy = vbuf_destroy;
+
+ vbuf->render = render;
+ vbuf->max_indices = MAX2(render->max_indices, UNDEFINED_VERTEX_ID-1);
+
+ vbuf->indices = (ushort *) align_malloc( vbuf->max_indices *
+ sizeof(vbuf->indices[0]),
+ 16 );
+ if (!vbuf->indices)
+ goto fail;
+
+ vbuf->cache = translate_cache_create();
+ if (!vbuf->cache)
+ goto fail;
+
+
+ vbuf->vertices = NULL;
+ vbuf->vertex_ptr = vbuf->vertices;
+
+ return &vbuf->stage;
+
+ fail:
+ if (vbuf)
+ vbuf_destroy(&vbuf->stage);
+
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_line.c b/src/gallium/auxiliary/draw/draw_pipe_wide_line.c
new file mode 100644
index 0000000000..f32cbef983
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_wide_line.c
@@ -0,0 +1,181 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "draw_private.h"
+#include "draw_pipe.h"
+
+
+struct wideline_stage {
+ struct draw_stage stage;
+
+ float half_line_width;
+};
+
+
+
+static INLINE struct wideline_stage *wideline_stage( struct draw_stage *stage )
+{
+ return (struct wideline_stage *)stage;
+}
+
+
+
+/**
+ * Draw a wide line by drawing a quad (two triangles).
+ * XXX need to disable polygon stipple.
+ */
+static void wideline_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ /*const struct wideline_stage *wide = wideline_stage(stage);*/
+ const unsigned pos = stage->draw->vs.position_output;
+ const float half_width = 0.5f * stage->draw->rasterizer->line_width;
+
+ struct prim_header tri;
+
+ struct vertex_header *v0 = dup_vert(stage, header->v[0], 0);
+ struct vertex_header *v1 = dup_vert(stage, header->v[0], 1);
+ struct vertex_header *v2 = dup_vert(stage, header->v[1], 2);
+ struct vertex_header *v3 = dup_vert(stage, header->v[1], 3);
+
+ float *pos0 = v0->data[pos];
+ float *pos1 = v1->data[pos];
+ float *pos2 = v2->data[pos];
+ float *pos3 = v3->data[pos];
+
+ const float dx = fabsf(pos0[0] - pos2[0]);
+ const float dy = fabsf(pos0[1] - pos2[1]);
+
+ /* small tweak to meet GL specification */
+ const float bias = 0.125f;
+
+ /*
+ * Draw wide line as a quad (two tris) by "stretching" the line along
+ * X or Y.
+ * We need to tweak coords in several ways to be conformant here.
+ */
+
+ if (dx > dy) {
+ /* x-major line */
+ pos0[1] = pos0[1] - half_width - bias;
+ pos1[1] = pos1[1] + half_width - bias;
+ pos2[1] = pos2[1] - half_width - bias;
+ pos3[1] = pos3[1] + half_width - bias;
+ if (pos0[0] < pos2[0]) {
+ /* left to right line */
+ pos0[0] -= 0.5f;
+ pos1[0] -= 0.5f;
+ pos2[0] -= 0.5f;
+ pos3[0] -= 0.5f;
+ }
+ else {
+ /* right to left line */
+ pos0[0] += 0.5f;
+ pos1[0] += 0.5f;
+ pos2[0] += 0.5f;
+ pos3[0] += 0.5f;
+ }
+ }
+ else {
+ /* y-major line */
+ pos0[0] = pos0[0] - half_width + bias;
+ pos1[0] = pos1[0] + half_width + bias;
+ pos2[0] = pos2[0] - half_width + bias;
+ pos3[0] = pos3[0] + half_width + bias;
+ if (pos0[1] < pos2[1]) {
+ /* top to bottom line */
+ pos0[1] -= 0.5f;
+ pos1[1] -= 0.5f;
+ pos2[1] -= 0.5f;
+ pos3[1] -= 0.5f;
+ }
+ else {
+ /* bottom to top line */
+ pos0[1] += 0.5f;
+ pos1[1] += 0.5f;
+ pos2[1] += 0.5f;
+ pos3[1] += 0.5f;
+ }
+ }
+
+ tri.det = header->det; /* only the sign matters */
+ tri.v[0] = v0;
+ tri.v[1] = v2;
+ tri.v[2] = v3;
+ stage->next->tri( stage->next, &tri );
+
+ tri.v[0] = v0;
+ tri.v[1] = v3;
+ tri.v[2] = v1;
+ stage->next->tri( stage->next, &tri );
+}
+
+
+static void wideline_flush( struct draw_stage *stage, unsigned flags )
+{
+ stage->next->flush( stage->next, flags );
+}
+
+
+static void wideline_reset_stipple_counter( struct draw_stage *stage )
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void wideline_destroy( struct draw_stage *stage )
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+struct draw_stage *draw_wide_line_stage( struct draw_context *draw )
+{
+ struct wideline_stage *wide = CALLOC_STRUCT(wideline_stage);
+
+ draw_alloc_temp_verts( &wide->stage, 4 );
+
+ wide->stage.draw = draw;
+ wide->stage.name = "wide-line";
+ wide->stage.next = NULL;
+ wide->stage.point = draw_pipe_passthrough_point;
+ wide->stage.line = wideline_line;
+ wide->stage.tri = draw_pipe_passthrough_tri;
+ wide->stage.flush = wideline_flush;
+ wide->stage.reset_stipple_counter = wideline_reset_stipple_counter;
+ wide->stage.destroy = wideline_destroy;
+
+ return &wide->stage;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
new file mode 100644
index 0000000000..7d76a7dbf3
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c
@@ -0,0 +1,333 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/**
+ * Notes on wide points and sprite mode:
+ *
+ * In wide point/sprite mode we effectively need to convert each incoming
+ * vertex into four outgoing vertices specifying the corners of a quad.
+ * Since we don't (yet) have geometry shaders, we have to handle this here
+ * in the draw module.
+ *
+ * For sprites, it also means that this is where we have to handle texcoords
+ * for the vertices of the quad. OpenGL's GL_COORD_REPLACE state specifies
+ * if/how enabled texcoords are automatically generated for sprites. We pass
+ * that info through gallium in the pipe_rasterizer_state::sprite_coord_mode
+ * array.
+ *
+ * Additionally, GLSL's gl_PointCoord fragment attribute has to be handled
+ * here as well. This is basically an additional texture/generic attribute
+ * that varies .x from 0 to 1 horizontally across the point and varies .y
+ * vertically from 0 to 1 down the sprite.
+ *
+ * With geometry shaders, the state tracker could create a GS to do
+ * most/all of this.
+ */
+
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw_vs.h"
+#include "draw_pipe.h"
+
+
+struct widepoint_stage {
+ struct draw_stage stage;
+
+ float half_point_size;
+ float point_size_min;
+ float point_size_max;
+
+ float xbias;
+ float ybias;
+
+ uint texcoord_slot[PIPE_MAX_SHADER_OUTPUTS];
+ uint texcoord_mode[PIPE_MAX_SHADER_OUTPUTS];
+ uint num_texcoords;
+
+ int psize_slot;
+
+ int point_coord_fs_input; /**< input for pointcoord */
+};
+
+
+
+static INLINE struct widepoint_stage *
+widepoint_stage( struct draw_stage *stage )
+{
+ return (struct widepoint_stage *)stage;
+}
+
+
+/**
+ * Set the vertex texcoords for sprite mode.
+ * Coords may be left untouched or set to a right-side-up or upside-down
+ * orientation.
+ */
+static void set_texcoords(const struct widepoint_stage *wide,
+ struct vertex_header *v, const float tc[4])
+{
+ uint i;
+ for (i = 0; i < wide->num_texcoords; i++) {
+ if (wide->texcoord_mode[i] != PIPE_SPRITE_COORD_NONE) {
+ uint j = wide->texcoord_slot[i];
+ v->data[j][0] = tc[0];
+ if (wide->texcoord_mode[i] == PIPE_SPRITE_COORD_LOWER_LEFT)
+ v->data[j][1] = 1.0f - tc[1];
+ else
+ v->data[j][1] = tc[1];
+ v->data[j][2] = tc[2];
+ v->data[j][3] = tc[3];
+ }
+ }
+
+ if (wide->point_coord_fs_input >= 0) {
+ /* put gl_PointCoord into the extra vertex slot */
+ uint slot = wide->stage.draw->extra_vp_outputs.slot;
+ v->data[slot][0] = tc[0];
+ v->data[slot][1] = tc[1];
+ v->data[slot][2] = 0.0F;
+ v->data[slot][3] = 1.0F;
+ }
+}
+
+
+/* If there are lots of sprite points (and why wouldn't there be?) it
+ * would probably be more sensible to change hardware setup to
+ * optimize this rather than doing the whole thing in software like
+ * this.
+ */
+static void widepoint_point( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ const struct widepoint_stage *wide = widepoint_stage(stage);
+ const unsigned pos = stage->draw->vs.position_output;
+ const boolean sprite = (boolean) stage->draw->rasterizer->point_sprite;
+ float half_size;
+ float left_adj, right_adj, bot_adj, top_adj;
+
+ struct prim_header tri;
+
+ /* four dups of original vertex */
+ struct vertex_header *v0 = dup_vert(stage, header->v[0], 0);
+ struct vertex_header *v1 = dup_vert(stage, header->v[0], 1);
+ struct vertex_header *v2 = dup_vert(stage, header->v[0], 2);
+ struct vertex_header *v3 = dup_vert(stage, header->v[0], 3);
+
+ float *pos0 = v0->data[pos];
+ float *pos1 = v1->data[pos];
+ float *pos2 = v2->data[pos];
+ float *pos3 = v3->data[pos];
+
+ /* point size is either per-vertex or fixed size */
+ if (wide->psize_slot >= 0) {
+ half_size = header->v[0]->data[wide->psize_slot][0];
+
+ /* XXX: temporary -- do this in the vertex shader??
+ */
+ half_size = CLAMP(half_size,
+ wide->point_size_min,
+ wide->point_size_max);
+
+ half_size *= 0.5f;
+ }
+ else {
+ half_size = wide->half_point_size;
+ }
+
+ left_adj = -half_size + wide->xbias;
+ right_adj = half_size + wide->xbias;
+ bot_adj = half_size + wide->ybias;
+ top_adj = -half_size + wide->ybias;
+
+ pos0[0] += left_adj;
+ pos0[1] += top_adj;
+
+ pos1[0] += left_adj;
+ pos1[1] += bot_adj;
+
+ pos2[0] += right_adj;
+ pos2[1] += top_adj;
+
+ pos3[0] += right_adj;
+ pos3[1] += bot_adj;
+
+ if (sprite) {
+ static const float tex00[4] = { 0, 0, 0, 1 };
+ static const float tex01[4] = { 0, 1, 0, 1 };
+ static const float tex11[4] = { 1, 1, 0, 1 };
+ static const float tex10[4] = { 1, 0, 0, 1 };
+ set_texcoords( wide, v0, tex00 );
+ set_texcoords( wide, v1, tex01 );
+ set_texcoords( wide, v2, tex10 );
+ set_texcoords( wide, v3, tex11 );
+ }
+
+ tri.det = header->det; /* only the sign matters */
+ tri.v[0] = v0;
+ tri.v[1] = v2;
+ tri.v[2] = v3;
+ stage->next->tri( stage->next, &tri );
+
+ tri.v[0] = v0;
+ tri.v[1] = v3;
+ tri.v[2] = v1;
+ stage->next->tri( stage->next, &tri );
+}
+
+
+static int
+find_pntc_input_attrib(struct draw_context *draw)
+{
+ /* Scan the fragment program's input decls to find the pointcoord
+ * attribute. The xy components will store the point coord.
+ */
+ return 0; /* XXX fix this */
+}
+
+
+static void widepoint_first_point( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct widepoint_stage *wide = widepoint_stage(stage);
+ struct draw_context *draw = stage->draw;
+
+ wide->half_point_size = 0.5f * draw->rasterizer->point_size;
+ wide->point_size_min = draw->rasterizer->point_size_min;
+ wide->point_size_max = draw->rasterizer->point_size_max;
+ wide->xbias = 0.0;
+ wide->ybias = 0.0;
+
+ if (draw->rasterizer->gl_rasterization_rules) {
+ wide->xbias = 0.125;
+ }
+
+ /* XXX we won't know the real size if it's computed by the vertex shader! */
+ if ((draw->rasterizer->point_size > draw->pipeline.wide_point_threshold) ||
+ (draw->rasterizer->point_sprite && draw->pipeline.point_sprite)) {
+ stage->point = widepoint_point;
+ }
+ else {
+ stage->point = draw_pipe_passthrough_point;
+ }
+
+ if (draw->rasterizer->point_sprite) {
+ /* find vertex shader texcoord outputs */
+ const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+ uint i, j = 0;
+ for (i = 0; i < vs->info.num_outputs; i++) {
+ if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_GENERIC) {
+ wide->texcoord_slot[j] = i;
+ wide->texcoord_mode[j] = draw->rasterizer->sprite_coord_mode[j];
+ j++;
+ }
+ }
+ wide->num_texcoords = j;
+
+ /* find fragment shader PointCoord input */
+ wide->point_coord_fs_input = find_pntc_input_attrib(draw);
+
+ /* setup extra vp output (point coord implemented as a texcoord) */
+ draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
+ draw->extra_vp_outputs.semantic_index = 0;
+ draw->extra_vp_outputs.slot = draw->vs.num_vs_outputs;
+ }
+ else {
+ wide->point_coord_fs_input = -1;
+ draw->extra_vp_outputs.slot = 0;
+ }
+
+ wide->psize_slot = -1;
+ if (draw->rasterizer->point_size_per_vertex) {
+ /* find PSIZ vertex output */
+ const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+ uint i;
+ for (i = 0; i < vs->info.num_outputs; i++) {
+ if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) {
+ wide->psize_slot = i;
+ break;
+ }
+ }
+ }
+
+ stage->point( stage, header );
+}
+
+
+static void widepoint_flush( struct draw_stage *stage, unsigned flags )
+{
+ stage->point = widepoint_first_point;
+ stage->next->flush( stage->next, flags );
+ stage->draw->extra_vp_outputs.slot = 0;
+}
+
+
+static void widepoint_reset_stipple_counter( struct draw_stage *stage )
+{
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void widepoint_destroy( struct draw_stage *stage )
+{
+ draw_free_temp_verts( stage );
+ FREE( stage );
+}
+
+
+struct draw_stage *draw_wide_point_stage( struct draw_context *draw )
+{
+ struct widepoint_stage *wide = CALLOC_STRUCT(widepoint_stage);
+ if (wide == NULL)
+ goto fail;
+
+ if (!draw_alloc_temp_verts( &wide->stage, 4 ))
+ goto fail;
+
+ wide->stage.draw = draw;
+ wide->stage.name = "wide-point";
+ wide->stage.next = NULL;
+ wide->stage.point = widepoint_first_point;
+ wide->stage.line = draw_pipe_passthrough_line;
+ wide->stage.tri = draw_pipe_passthrough_tri;
+ wide->stage.flush = widepoint_flush;
+ wide->stage.reset_stipple_counter = widepoint_reset_stipple_counter;
+ wide->stage.destroy = widepoint_destroy;
+
+ return &wide->stage;
+
+ fail:
+ if (wide)
+ wide->stage.destroy( &wide->stage );
+
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
new file mode 100644
index 0000000000..41fcb16a0a
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -0,0 +1,319 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Private data structures, etc for the draw module.
+ */
+
+
+/**
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+
+#ifndef DRAW_PRIVATE_H
+#define DRAW_PRIVATE_H
+
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+
+#include "tgsi/tgsi_scan.h"
+
+
+struct pipe_context;
+struct gallivm_prog;
+struct gallivm_cpu_engine;
+struct draw_vertex_shader;
+struct draw_context;
+struct draw_stage;
+struct vbuf_render;
+struct tgsi_exec_machine;
+struct tgsi_sampler;
+
+
+/**
+ * Basic vertex info.
+ * Carry some useful information around with the vertices in the prim pipe.
+ */
+struct vertex_header {
+ unsigned clipmask:12;
+ unsigned edgeflag:1;
+ unsigned pad:3;
+ unsigned vertex_id:16;
+
+ float clip[4];
+
+ /* This will probably become float (*data)[4] soon:
+ */
+ float data[][4];
+};
+
+/* NOTE: It should match vertex_id size above */
+#define UNDEFINED_VERTEX_ID 0xffff
+
+
+/**
+ * Private context for the drawing module.
+ */
+struct draw_context
+{
+ /** Drawing/primitive pipeline stages */
+ struct {
+ struct draw_stage *first; /**< one of the following */
+
+ struct draw_stage *validate;
+
+ /* stages (in logical order) */
+ struct draw_stage *flatshade;
+ struct draw_stage *clip;
+ struct draw_stage *cull;
+ struct draw_stage *twoside;
+ struct draw_stage *offset;
+ struct draw_stage *unfilled;
+ struct draw_stage *stipple;
+ struct draw_stage *aapoint;
+ struct draw_stage *aaline;
+ struct draw_stage *pstipple;
+ struct draw_stage *wide_line;
+ struct draw_stage *wide_point;
+ struct draw_stage *rasterize;
+
+ float wide_point_threshold; /**< convert pnts to tris if larger than this */
+ float wide_line_threshold; /**< convert lines to tris if wider than this */
+ boolean line_stipple; /**< do line stipple? */
+ boolean point_sprite; /**< convert points to quads for sprites? */
+
+ /* Temporary storage while the pipeline is being run:
+ */
+ char *verts;
+ unsigned vertex_stride;
+ unsigned vertex_count;
+ } pipeline;
+
+
+ struct vbuf_render *render;
+
+ /* Support prototype passthrough path:
+ */
+ struct {
+ struct {
+ struct draw_pt_middle_end *fetch_emit;
+ struct draw_pt_middle_end *fetch_shade_emit;
+ struct draw_pt_middle_end *general;
+ } middle;
+
+ struct {
+ struct draw_pt_front_end *vcache;
+ struct draw_pt_front_end *varray;
+ } front;
+
+ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ unsigned nr_vertex_buffers;
+
+ struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
+ unsigned nr_vertex_elements;
+
+ /* user-space vertex data, buffers */
+ struct {
+ const unsigned *edgeflag;
+
+ /** vertex element/index buffer (ex: glDrawElements) */
+ const void *elts;
+ /** bytes per index (0, 1, 2 or 4) */
+ unsigned eltSize;
+ unsigned min_index;
+ unsigned max_index;
+
+ /** vertex arrays */
+ const void *vbuffer[PIPE_MAX_ATTRIBS];
+
+ /** constant buffer (for vertex shader) */
+ const void *constants;
+ } user;
+
+ boolean test_fse; /* enable FSE even though its not correct (eg for softpipe) */
+ boolean no_fse; /* disable FSE even when it is correct */
+ } pt;
+
+ struct {
+ boolean bypass_clipping;
+ boolean bypass_vs;
+ } driver;
+
+ boolean flushing; /**< debugging/sanity */
+ boolean suspend_flushing; /**< internally set */
+ boolean bypass_clipping; /**< set if either api or driver bypass_clipping true */
+
+ boolean force_passthrough; /**< never clip or shade */
+
+ double mrd; /**< minimum resolvable depth value, for polygon offset */
+
+ /* pipe state that we need: */
+ const struct pipe_rasterizer_state *rasterizer;
+ struct pipe_viewport_state viewport;
+ boolean identity_viewport;
+
+ struct {
+ struct draw_vertex_shader *vertex_shader;
+ uint num_vs_outputs; /**< convenience, from vertex_shader */
+ uint position_output;
+
+ /** TGSI program interpreter runtime state */
+ struct tgsi_exec_machine *machine;
+
+ uint num_samplers;
+ struct tgsi_sampler **samplers;
+
+ /* This (and the tgsi_exec_machine struct) probably need to be moved somewhere private.
+ */
+ struct gallivm_cpu_engine *engine;
+
+ /* Here's another one:
+ */
+ struct aos_machine *aos_machine;
+
+
+ const float (*aligned_constants)[4];
+
+ const float (*aligned_constant_storage)[4];
+ unsigned const_storage_size;
+
+
+ struct translate *fetch;
+ struct translate_cache *fetch_cache;
+ struct translate *emit;
+ struct translate_cache *emit_cache;
+ } vs;
+
+ /* Clip derived state:
+ */
+ float plane[12][4];
+ unsigned nr_planes;
+
+ /* If a prim stage introduces new vertex attributes, they'll be stored here
+ */
+ struct {
+ uint semantic_name;
+ uint semantic_index;
+ int slot;
+ } extra_vp_outputs;
+
+ unsigned reduced_prim;
+
+ void *driver_private;
+};
+
+
+/*******************************************************************************
+ * Vertex shader code:
+ */
+boolean draw_vs_init( struct draw_context *draw );
+void draw_vs_destroy( struct draw_context *draw );
+
+void draw_vs_set_viewport( struct draw_context *,
+ const struct pipe_viewport_state * );
+
+void draw_vs_set_constants( struct draw_context *,
+ const float (*constants)[4],
+ unsigned size );
+
+
+
+
+/*******************************************************************************
+ * Vertex processing (was passthrough) code:
+ */
+boolean draw_pt_init( struct draw_context *draw );
+void draw_pt_destroy( struct draw_context *draw );
+void draw_pt_reset_vertex_ids( struct draw_context *draw );
+
+
+/*******************************************************************************
+ * Primitive processing (pipeline) code:
+ */
+
+boolean draw_pipeline_init( struct draw_context *draw );
+void draw_pipeline_destroy( struct draw_context *draw );
+
+
+
+
+
+/* We use the top few bits in the elts[] parameter to convey a little
+ * API information. This limits the number of vertices we can address
+ * to only 4096 -- if that becomes a problem, we can switch to 32-bit
+ * draw indices.
+ *
+ * These flags expected at first vertex of lines & triangles when
+ * unfilled and/or line stipple modes are operational.
+ */
+#define DRAW_PIPE_MAX_VERTICES (0x1<<12)
+#define DRAW_PIPE_EDGE_FLAG_0 (0x1<<12)
+#define DRAW_PIPE_EDGE_FLAG_1 (0x2<<12)
+#define DRAW_PIPE_EDGE_FLAG_2 (0x4<<12)
+#define DRAW_PIPE_EDGE_FLAG_ALL (0x7<<12)
+#define DRAW_PIPE_RESET_STIPPLE (0x8<<12)
+#define DRAW_PIPE_FLAG_MASK (0xf<<12)
+
+void draw_pipeline_run( struct draw_context *draw,
+ unsigned prim,
+ struct vertex_header *vertices,
+ unsigned vertex_count,
+ unsigned stride,
+ const ushort *elts,
+ unsigned count );
+
+void draw_pipeline_run_linear( struct draw_context *draw,
+ unsigned prim,
+ struct vertex_header *vertices,
+ unsigned count,
+ unsigned stride );
+
+
+
+void draw_pipeline_flush( struct draw_context *draw,
+ unsigned flags );
+
+
+
+/*******************************************************************************
+ * Flushing
+ */
+
+#define DRAW_FLUSH_STATE_CHANGE 0x8
+#define DRAW_FLUSH_BACKEND 0x10
+
+
+void draw_do_flush( struct draw_context *draw, unsigned flags );
+
+
+
+
+#endif /* DRAW_PRIVATE_H */
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
new file mode 100644
index 0000000000..dbb5ac7182
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -0,0 +1,324 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pt.h"
+#include "draw/draw_vs.h"
+#include "tgsi/tgsi_dump.h"
+#include "util/u_math.h"
+#include "util/u_prim.h"
+
+static unsigned trim( unsigned count, unsigned first, unsigned incr )
+{
+ if (count < first)
+ return 0;
+ return count - (count - first) % incr;
+}
+
+
+
+/* Overall we split things into:
+ * - frontend -- prepare fetch_elts, draw_elts - eg vcache
+ * - middle -- fetch, shade, cliptest, viewport
+ * - pipeline -- the prim pipeline: clipping, wide lines, etc
+ * - backend -- the vbuf_render provided by the driver.
+ */
+static boolean
+draw_pt_arrays(struct draw_context *draw,
+ unsigned prim,
+ unsigned start,
+ unsigned count)
+{
+ struct draw_pt_front_end *frontend = NULL;
+ struct draw_pt_middle_end *middle = NULL;
+ unsigned opt = 0;
+
+ /* Sanitize primitive length:
+ */
+ {
+ unsigned first, incr;
+ draw_pt_split_prim(prim, &first, &incr);
+ count = trim(count, first, incr);
+ if (count < first)
+ return TRUE;
+ }
+
+ if (!draw->force_passthrough) {
+ if (!draw->render) {
+ opt |= PT_PIPELINE;
+ }
+
+ if (draw_need_pipeline(draw,
+ draw->rasterizer,
+ prim)) {
+ opt |= PT_PIPELINE;
+ }
+
+ if (!draw->bypass_clipping && !draw->pt.test_fse) {
+ opt |= PT_CLIPTEST;
+ }
+
+ if (!draw->rasterizer->bypass_vs_clip_and_viewport) {
+ opt |= PT_SHADE;
+ }
+ }
+
+ if (opt == 0)
+ middle = draw->pt.middle.fetch_emit;
+ else if (opt == PT_SHADE && !draw->pt.no_fse)
+ middle = draw->pt.middle.fetch_shade_emit;
+ else
+ middle = draw->pt.middle.general;
+
+
+ /* Pick the right frontend
+ */
+ if (draw->pt.user.elts || (opt & PT_PIPELINE)) {
+ frontend = draw->pt.front.vcache;
+ } else {
+ frontend = draw->pt.front.varray;
+ }
+
+ frontend->prepare( frontend, prim, middle, opt );
+
+ frontend->run(frontend,
+ draw_pt_elt_func(draw),
+ draw_pt_elt_ptr(draw, start),
+ count);
+
+ frontend->finish( frontend );
+
+ return TRUE;
+}
+
+
+boolean draw_pt_init( struct draw_context *draw )
+{
+ draw->pt.test_fse = debug_get_bool_option("DRAW_FSE", FALSE);
+ draw->pt.no_fse = debug_get_bool_option("DRAW_NO_FSE", FALSE);
+
+ draw->pt.front.vcache = draw_pt_vcache( draw );
+ if (!draw->pt.front.vcache)
+ return FALSE;
+
+ draw->pt.front.varray = draw_pt_varray(draw);
+ if (!draw->pt.front.varray)
+ return FALSE;
+
+ draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
+ if (!draw->pt.middle.fetch_emit)
+ return FALSE;
+
+ draw->pt.middle.fetch_shade_emit = draw_pt_middle_fse( draw );
+ if (!draw->pt.middle.fetch_shade_emit)
+ return FALSE;
+
+ draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit( draw );
+ if (!draw->pt.middle.general)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+void draw_pt_destroy( struct draw_context *draw )
+{
+ if (draw->pt.middle.general) {
+ draw->pt.middle.general->destroy( draw->pt.middle.general );
+ draw->pt.middle.general = NULL;
+ }
+
+ if (draw->pt.middle.fetch_emit) {
+ draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit );
+ draw->pt.middle.fetch_emit = NULL;
+ }
+
+ if (draw->pt.middle.fetch_shade_emit) {
+ draw->pt.middle.fetch_shade_emit->destroy( draw->pt.middle.fetch_shade_emit );
+ draw->pt.middle.fetch_shade_emit = NULL;
+ }
+
+ if (draw->pt.front.vcache) {
+ draw->pt.front.vcache->destroy( draw->pt.front.vcache );
+ draw->pt.front.vcache = NULL;
+ }
+
+ if (draw->pt.front.varray) {
+ draw->pt.front.varray->destroy( draw->pt.front.varray );
+ draw->pt.front.varray = NULL;
+ }
+}
+
+
+/**
+ * Debug- print the first 'count' vertices.
+ */
+static void
+draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
+{
+ uint i;
+
+ debug_printf("Draw arrays(prim = %u, start = %u, count = %u)\n",
+ prim, start, count);
+
+ for (i = 0; i < count; i++) {
+ uint ii, j;
+
+ if (draw->pt.user.elts) {
+ /* indexed arrays */
+ switch (draw->pt.user.eltSize) {
+ case 1:
+ {
+ const ubyte *elem = (const ubyte *) draw->pt.user.elts;
+ ii = elem[start + i];
+ }
+ break;
+ case 2:
+ {
+ const ushort *elem = (const ushort *) draw->pt.user.elts;
+ ii = elem[start + i];
+ }
+ break;
+ case 4:
+ {
+ const uint *elem = (const uint *) draw->pt.user.elts;
+ ii = elem[start + i];
+ }
+ break;
+ default:
+ assert(0);
+ }
+ debug_printf("Element[%u + %u] -> Vertex %u:\n", start, i, ii);
+ }
+ else {
+ /* non-indexed arrays */
+ ii = start + i;
+ debug_printf("Vertex %u:\n", ii);
+ }
+
+ for (j = 0; j < draw->pt.nr_vertex_elements; j++) {
+ uint buf = draw->pt.vertex_element[j].vertex_buffer_index;
+ ubyte *ptr = (ubyte *) draw->pt.user.vbuffer[buf];
+ ptr += draw->pt.vertex_buffer[buf].stride * ii;
+ ptr += draw->pt.vertex_element[j].src_offset;
+
+ debug_printf(" Attr %u: ", j);
+ switch (draw->pt.vertex_element[j].src_format) {
+ case PIPE_FORMAT_R32_FLOAT:
+ {
+ float *v = (float *) ptr;
+ debug_printf("%f @ %p\n", v[0], (void *) v);
+ }
+ break;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ {
+ float *v = (float *) ptr;
+ debug_printf("%f %f @ %p\n", v[0], v[1], (void *) v);
+ }
+ break;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ {
+ float *v = (float *) ptr;
+ debug_printf("%f %f %f @ %p\n", v[0], v[1], v[2], (void *) v);
+ }
+ break;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ {
+ float *v = (float *) ptr;
+ debug_printf("%f %f %f %f @ %p\n", v[0], v[1], v[2], v[3],
+ (void *) v);
+ }
+ break;
+ default:
+ debug_printf("other format (fix me)\n");
+ ;
+ }
+ }
+ }
+}
+
+
+/**
+ * Draw vertex arrays
+ * This is the main entrypoint into the drawing module.
+ * \param prim one of PIPE_PRIM_x
+ * \param start index of first vertex to draw
+ * \param count number of vertices to draw
+ */
+void
+draw_arrays(struct draw_context *draw, unsigned prim,
+ unsigned start, unsigned count)
+{
+ unsigned reduced_prim = u_reduced_prim(prim);
+ if (reduced_prim != draw->reduced_prim) {
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw->reduced_prim = reduced_prim;
+ }
+
+ if (0)
+ draw_print_arrays(draw, prim, start, MIN2(count, 20));
+
+#if 0
+ {
+ int i;
+ debug_printf("draw_arrays(prim=%u start=%u count=%u):\n",
+ prim, start, count);
+ tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
+ debug_printf("Elements:\n");
+ for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
+ debug_printf(" format=%s comps=%u\n",
+ pf_name(draw->pt.vertex_element[i].src_format),
+ draw->pt.vertex_element[i].nr_components);
+ }
+ debug_printf("Buffers:\n");
+ for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
+ debug_printf(" stride=%u offset=%u ptr=%p\n",
+ draw->pt.vertex_buffer[i].stride,
+ draw->pt.vertex_buffer[i].buffer_offset,
+ draw->pt.user.vbuffer[i]);
+ }
+ }
+#endif
+
+ /* drawing done here: */
+ draw_pt_arrays(draw, prim, start, count);
+}
+
+boolean draw_pt_get_edgeflag( struct draw_context *draw,
+ unsigned idx )
+{
+ if (draw->pt.user.edgeflag)
+ return (draw->pt.user.edgeflag[idx/32] & (1 << (idx%32))) != 0;
+ else
+ return 1;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
new file mode 100644
index 0000000000..7a17a9fb6b
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -0,0 +1,233 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef DRAW_PT_H
+#define DRAW_PT_H
+
+#include "pipe/p_compiler.h"
+
+typedef unsigned (*pt_elt_func)( const void *elts, unsigned idx );
+
+struct draw_pt_middle_end;
+struct draw_context;
+
+
+#define PT_SHADE 0x1
+#define PT_CLIPTEST 0x2
+#define PT_PIPELINE 0x4
+#define PT_MAX_MIDDLE 0x8
+
+
+/* The "front end" - prepare sets of fetch, draw elements for the
+ * middle end.
+ *
+ * Currenly one version of this:
+ * - vcache - catchall implementation, decomposes to TRI/LINE/POINT prims
+ * Later:
+ * - varray, varray_split
+ * - velement, velement_split
+ *
+ * Currenly only using the vcache version.
+ */
+struct draw_pt_front_end {
+ void (*prepare)( struct draw_pt_front_end *,
+ unsigned prim,
+ struct draw_pt_middle_end *,
+ unsigned opt );
+
+ void (*run)( struct draw_pt_front_end *,
+ pt_elt_func elt_func,
+ const void *elt_ptr,
+ unsigned count );
+
+ void (*finish)( struct draw_pt_front_end * );
+ void (*destroy)( struct draw_pt_front_end * );
+};
+
+
+/* The "middle end" - prepares actual hardware vertices for the
+ * hardware backend.
+ *
+ * Currently two versions of this:
+ * - fetch, vertex shade, cliptest, prim-pipeline
+ * - fetch, emit (ie passthrough)
+ */
+struct draw_pt_middle_end {
+ void (*prepare)( struct draw_pt_middle_end *,
+ unsigned prim,
+ unsigned opt,
+ unsigned *max_vertices );
+
+ void (*run)( struct draw_pt_middle_end *,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count );
+
+ void (*run_linear)(struct draw_pt_middle_end *,
+ unsigned start,
+ unsigned count);
+
+ /* Transform all vertices in a linear range and then draw them with
+ * the supplied element list. May fail and return FALSE.
+ */
+ boolean (*run_linear_elts)( struct draw_pt_middle_end *,
+ unsigned fetch_start,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count );
+
+ int (*get_max_vertex_count)( struct draw_pt_middle_end * );
+
+ void (*finish)( struct draw_pt_middle_end * );
+ void (*destroy)( struct draw_pt_middle_end * );
+};
+
+
+/* The "back end" - supplied by the driver, defined in draw_vbuf.h.
+ */
+struct vbuf_render;
+struct vertex_header;
+
+
+/* Helper functions.
+ */
+pt_elt_func draw_pt_elt_func( struct draw_context *draw );
+const void *draw_pt_elt_ptr( struct draw_context *draw,
+ unsigned start );
+
+/* Frontends:
+ *
+ * Currently only the general-purpose vcache implementation, could add
+ * a special case for tiny vertex buffers.
+ */
+struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw );
+struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw);
+
+
+/* Middle-ends:
+ *
+ * Currently one general-purpose case which can do all possibilities,
+ * at the slight expense of creating a vertex_header in some cases
+ * unecessarily.
+ *
+ * The special case fetch_emit code avoids pipeline vertices
+ * altogether and builds hardware vertices directly from API
+ * vertex_elements.
+ */
+struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw );
+struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw );
+struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw);
+
+
+/* More helpers:
+ */
+boolean draw_pt_get_edgeflag( struct draw_context *draw,
+ unsigned idx );
+
+
+/*******************************************************************************
+ * HW vertex emit:
+ */
+struct pt_emit;
+
+void draw_pt_emit_prepare( struct pt_emit *emit,
+ unsigned prim,
+ unsigned *max_vertices );
+
+void draw_pt_emit( struct pt_emit *emit,
+ const float (*vertex_data)[4],
+ unsigned vertex_count,
+ unsigned stride,
+ const ushort *elts,
+ unsigned count );
+
+void draw_pt_emit_linear( struct pt_emit *emit,
+ const float (*vertex_data)[4],
+ unsigned stride,
+ unsigned count );
+
+void draw_pt_emit_destroy( struct pt_emit *emit );
+
+struct pt_emit *draw_pt_emit_create( struct draw_context *draw );
+
+
+/*******************************************************************************
+ * API vertex fetch:
+ */
+
+struct pt_fetch;
+void draw_pt_fetch_prepare( struct pt_fetch *fetch,
+ unsigned vertex_input_count,
+ unsigned vertex_size );
+
+void draw_pt_fetch_run( struct pt_fetch *fetch,
+ const unsigned *elts,
+ unsigned count,
+ char *verts );
+
+void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
+ unsigned start,
+ unsigned count,
+ char *verts );
+
+void draw_pt_fetch_destroy( struct pt_fetch *fetch );
+
+struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw );
+
+/*******************************************************************************
+ * Post-VS: cliptest, rhw, viewport
+ */
+struct pt_post_vs;
+
+boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
+ struct vertex_header *pipeline_verts,
+ unsigned stride,
+ unsigned count );
+
+void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
+ boolean bypass_clipping,
+ boolean bypass_viewport,
+ boolean opengl );
+
+struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw );
+
+void draw_pt_post_vs_destroy( struct pt_post_vs *pvs );
+
+
+/*******************************************************************************
+ * Utils:
+ */
+void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr);
+
+
+#endif
diff --git a/src/gallium/auxiliary/draw/draw_pt_decompose.h b/src/gallium/auxiliary/draw/draw_pt_decompose.h
new file mode 100644
index 0000000000..4ca5b52020
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_decompose.h
@@ -0,0 +1,182 @@
+
+
+static void FUNC( ARGS,
+ unsigned count )
+{
+ LOCAL_VARS;
+
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < count; i ++) {
+ POINT( (i + 0) );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 0; i+1 < count; i += 2) {
+ LINE( DRAW_PIPE_RESET_STIPPLE,
+ (i + 0),
+ (i + 1));
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ if (count >= 2) {
+ flags = DRAW_PIPE_RESET_STIPPLE;
+
+ for (i = 1; i < count; i++, flags = 0) {
+ LINE( flags,
+ (i - 1),
+ (i ));
+ }
+
+ LINE( flags,
+ (i - 1),
+ (0 ));
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ flags = DRAW_PIPE_RESET_STIPPLE;
+ for (i = 1; i < count; i++, flags = 0) {
+ LINE( flags,
+ (i - 1),
+ (i ));
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i+2 < count; i += 3) {
+ if (flatfirst) {
+ /* put provoking vertex in last pos for clipper */
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (i + 1),
+ (i + 2),
+ (i + 0 ));
+ }
+ else {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (i + 0),
+ (i + 1),
+ (i + 2 ));
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (i + 1 + (i&1)),
+ (i + 2 - (i&1)),
+ (i + 0) );
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (i + 0 + (i&1)),
+ (i + 1 - (i&1)),
+ (i + 2 ));
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (count >= 3) {
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (i + 2),
+ 0,
+ (i + 1) );
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ (0),
+ (i + 1),
+ (i + 2 ));
+ }
+ }
+ }
+ break;
+
+
+ case PIPE_PRIM_QUADS:
+ if (flatfirst) {
+ for (i = 0; i+3 < count; i += 4) {
+ QUAD( (i + 1),
+ (i + 2),
+ (i + 3),
+ (i + 0) );
+ }
+ }
+ else {
+ for (i = 0; i+3 < count; i += 4) {
+ QUAD( (i + 0),
+ (i + 1),
+ (i + 2),
+ (i + 3));
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ if (flatfirst) {
+ for (i = 0; i+3 < count; i += 2) {
+ QUAD( (i + 1),
+ (i + 3),
+ (i + 2),
+ (i + 0) );
+ }
+ }
+ else {
+ for (i = 0; i+3 < count; i += 2) {
+ QUAD( (i + 2),
+ (i + 0),
+ (i + 1),
+ (i + 3));
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ {
+ /* These bitflags look a little odd because we submit the
+ * vertices as (1,2,0) to satisfy flatshade requirements.
+ */
+ const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2;
+ const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0;
+ const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1;
+
+ flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
+
+ for (i = 0; i+2 < count; i++, flags = edge_middle) {
+
+ if (i + 3 == count)
+ flags |= edge_last;
+
+ TRIANGLE( flags,
+ (i + 1),
+ (i + 2),
+ (0));
+ }
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ FLUSH;
+}
+
+
+#undef TRIANGLE
+#undef QUAD
+#undef POINT
+#undef LINE
+#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_pt_elts.c b/src/gallium/auxiliary/draw/draw_pt_elts.c
new file mode 100644
index 0000000000..88f4d9f495
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_elts.c
@@ -0,0 +1,89 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "draw/draw_pt.h"
+#include "draw/draw_private.h"
+
+/* Neat get_elt func that also works for varrays drawing by encoding
+ * the start value into a pointer.
+ */
+
+static unsigned elt_uint( const void *elts, unsigned idx )
+{
+ return *(((const uint *)elts) + idx);
+}
+
+static unsigned elt_ushort( const void *elts, unsigned idx )
+{
+ return *(((const ushort *)elts) + idx);
+}
+
+static unsigned elt_ubyte( const void *elts, unsigned idx )
+{
+ return *(((const ubyte *)elts) + idx);
+}
+
+static unsigned elt_vert( const void *elts, unsigned idx )
+{
+ /* unsigned index is packed in the pointer */
+ return (unsigned)(uintptr_t)elts + idx;
+}
+
+pt_elt_func draw_pt_elt_func( struct draw_context *draw )
+{
+ switch (draw->pt.user.eltSize) {
+ case 0: return &elt_vert;
+ case 1: return &elt_ubyte;
+ case 2: return &elt_ushort;
+ case 4: return &elt_uint;
+ default: return NULL;
+ }
+}
+
+const void *draw_pt_elt_ptr( struct draw_context *draw,
+ unsigned start )
+{
+ const char *elts = draw->pt.user.elts;
+
+ switch (draw->pt.user.eltSize) {
+ case 0:
+ return (const void *)(((const ubyte *)NULL) + start);
+ case 1:
+ return (const void *)(((const ubyte *)elts) + start);
+ case 2:
+ return (const void *)(((const ushort *)elts) + start);
+ case 4:
+ return (const void *)(((const uint *)elts) + start);
+ default:
+ return NULL;
+ }
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
new file mode 100644
index 0000000000..064e16c295
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -0,0 +1,313 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+#include "translate/translate.h"
+#include "translate/translate_cache.h"
+
+struct pt_emit {
+ struct draw_context *draw;
+
+ struct translate *translate;
+
+ struct translate_cache *cache;
+ unsigned prim;
+
+ const struct vertex_info *vinfo;
+};
+
+void draw_pt_emit_prepare( struct pt_emit *emit,
+ unsigned prim,
+ unsigned *max_vertices )
+{
+ struct draw_context *draw = emit->draw;
+ const struct vertex_info *vinfo;
+ unsigned dst_offset;
+ struct translate_key hw_key;
+ unsigned i;
+ boolean ok;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+
+ /* XXX: may need to defensively reset this later on as clipping can
+ * clobber this state in the render backend.
+ */
+ emit->prim = prim;
+
+ ok = draw->render->set_primitive(draw->render, emit->prim);
+ if (!ok) {
+ assert(0);
+ return;
+ }
+
+ /* Must do this after set_primitive() above:
+ */
+ emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render);
+
+
+ /* Translate from pipeline vertices to hw vertices.
+ */
+ dst_offset = 0;
+ for (i = 0; i < vinfo->num_attribs; i++) {
+ unsigned emit_sz = 0;
+ unsigned src_buffer = 0;
+ unsigned output_format;
+ unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );
+
+
+
+ switch (vinfo->attrib[i].emit) {
+ case EMIT_4F:
+ output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ emit_sz = 4 * sizeof(float);
+ break;
+ case EMIT_3F:
+ output_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ emit_sz = 3 * sizeof(float);
+ break;
+ case EMIT_2F:
+ output_format = PIPE_FORMAT_R32G32_FLOAT;
+ emit_sz = 2 * sizeof(float);
+ break;
+ case EMIT_1F:
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ break;
+ case EMIT_1F_PSIZE:
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ src_buffer = 1;
+ src_offset = 0;
+ break;
+ case EMIT_4UB:
+ output_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ emit_sz = 4 * sizeof(ubyte);
+ break;
+ default:
+ assert(0);
+ output_format = PIPE_FORMAT_NONE;
+ emit_sz = 0;
+ break;
+ }
+
+ hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ hw_key.element[i].input_buffer = src_buffer;
+ hw_key.element[i].input_offset = src_offset;
+ hw_key.element[i].output_format = output_format;
+ hw_key.element[i].output_offset = dst_offset;
+
+ dst_offset += emit_sz;
+ }
+
+ hw_key.nr_elements = vinfo->num_attribs;
+ hw_key.output_stride = vinfo->size * 4;
+
+ if (!emit->translate ||
+ translate_key_compare(&emit->translate->key, &hw_key) != 0)
+ {
+ translate_key_sanitize(&hw_key);
+ emit->translate = translate_cache_find(emit->cache, &hw_key);
+ }
+
+ *max_vertices = (draw->render->max_vertex_buffer_bytes /
+ (vinfo->size * 4));
+
+ /* even number */
+ *max_vertices = *max_vertices & ~1;
+}
+
+
+void draw_pt_emit( struct pt_emit *emit,
+ const float (*vertex_data)[4],
+ unsigned vertex_count,
+ unsigned stride,
+ const ushort *elts,
+ unsigned count )
+{
+ struct draw_context *draw = emit->draw;
+ struct translate *translate = emit->translate;
+ struct vbuf_render *render = draw->render;
+ void *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ if (vertex_count == 0)
+ return;
+
+ if (vertex_count >= UNDEFINED_VERTEX_ID) {
+ assert(0);
+ return;
+ }
+
+ /* XXX: and work out some way to coordinate the render primitive
+ * between vbuf.c and here...
+ */
+ if (!draw->render->set_primitive(draw->render, emit->prim)) {
+ assert(0);
+ return;
+ }
+
+ render->allocate_vertices(render,
+ (ushort)translate->key.output_stride,
+ (ushort)vertex_count);
+
+ hw_verts = render->map_vertices( render );
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+ translate->set_buffer(translate,
+ 0,
+ vertex_data,
+ stride );
+
+ translate->set_buffer(translate,
+ 1,
+ &draw->rasterizer->point_size,
+ 0);
+
+ translate->run( translate,
+ 0,
+ vertex_count,
+ hw_verts );
+
+ render->unmap_vertices( render,
+ 0,
+ vertex_count - 1 );
+
+ render->draw(render,
+ elts,
+ count);
+
+ render->release_vertices(render);
+}
+
+
+void draw_pt_emit_linear(struct pt_emit *emit,
+ const float (*vertex_data)[4],
+ unsigned stride,
+ unsigned count)
+{
+ struct draw_context *draw = emit->draw;
+ struct translate *translate = emit->translate;
+ struct vbuf_render *render = draw->render;
+ void *hw_verts;
+
+#if 0
+ debug_printf("Linear emit\n");
+#endif
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ if (count >= UNDEFINED_VERTEX_ID)
+ goto fail;
+
+ /* XXX: and work out some way to coordinate the render primitive
+ * between vbuf.c and here...
+ */
+ if (!draw->render->set_primitive(draw->render, emit->prim))
+ goto fail;
+
+ if (!render->allocate_vertices(render,
+ (ushort)translate->key.output_stride,
+ (ushort)count))
+ goto fail;
+
+ hw_verts = render->map_vertices( render );
+ if (!hw_verts)
+ goto fail;
+
+ translate->set_buffer(translate, 0,
+ vertex_data, stride);
+
+ translate->set_buffer(translate, 1,
+ &draw->rasterizer->point_size,
+ 0);
+
+ translate->run(translate,
+ 0,
+ count,
+ hw_verts);
+
+ if (0) {
+ unsigned i;
+ for (i = 0; i < count; i++) {
+ debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i);
+ draw_dump_emitted_vertex( emit->vinfo,
+ (const uint8_t *)hw_verts +
+ translate->key.output_stride * i );
+ }
+ }
+
+ render->unmap_vertices( render, 0, count - 1 );
+
+ render->draw_arrays(render, 0, count);
+
+ render->release_vertices(render);
+
+ return;
+
+fail:
+ assert(0);
+ return;
+}
+
+struct pt_emit *draw_pt_emit_create( struct draw_context *draw )
+{
+ struct pt_emit *emit = CALLOC_STRUCT(pt_emit);
+ if (!emit)
+ return NULL;
+
+ emit->draw = draw;
+ emit->cache = translate_cache_create();
+ if (!emit->cache) {
+ FREE(emit);
+ return NULL;
+ }
+
+ return emit;
+}
+
+void draw_pt_emit_destroy( struct pt_emit *emit )
+{
+ if (emit->cache)
+ translate_cache_destroy(emit->cache);
+
+ FREE(emit);
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
new file mode 100644
index 0000000000..65c3a34c34
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -0,0 +1,234 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+#include "translate/translate.h"
+#include "translate/translate_cache.h"
+
+
+struct pt_fetch {
+ struct draw_context *draw;
+
+ struct translate *translate;
+
+ unsigned vertex_size;
+ boolean need_edgeflags;
+
+ struct translate_cache *cache;
+};
+
+/* Perform the fetch from API vertex elements & vertex buffers, to a
+ * contiguous set of float[4] attributes as required for the
+ * vertex_shader->run_linear() method.
+ *
+ * This is used in all cases except pure passthrough
+ * (draw_pt_fetch_emit.c) which has its own version to translate
+ * directly to hw vertices.
+ *
+ */
+void draw_pt_fetch_prepare( struct pt_fetch *fetch,
+ unsigned vs_input_count,
+ unsigned vertex_size )
+{
+ struct draw_context *draw = fetch->draw;
+ unsigned nr_inputs;
+ unsigned i, nr = 0;
+ unsigned dst_offset = 0;
+ struct translate_key key;
+
+ fetch->vertex_size = vertex_size;
+
+ /* Always emit/leave space for a vertex header.
+ *
+ * It's worth considering whether the vertex headers should contain
+ * a pointer to the 'data', rather than having it inline.
+ * Something to look at after we've fully switched over to the pt
+ * paths.
+ */
+ {
+ /* Need to set header->vertex_id = 0xffff somehow.
+ */
+ key.element[nr].input_format = PIPE_FORMAT_R32_FLOAT;
+ key.element[nr].input_buffer = draw->pt.nr_vertex_buffers;
+ key.element[nr].input_offset = 0;
+ key.element[nr].output_format = PIPE_FORMAT_R32_FLOAT;
+ key.element[nr].output_offset = dst_offset;
+ dst_offset += 1 * sizeof(float);
+ nr++;
+
+
+ /* Just leave the clip[] array untouched.
+ */
+ dst_offset += 4 * sizeof(float);
+ }
+
+ assert( draw->pt.nr_vertex_elements >= vs_input_count );
+
+ nr_inputs = MIN2( vs_input_count, draw->pt.nr_vertex_elements );
+
+ for (i = 0; i < nr_inputs; i++) {
+ key.element[nr].input_format = draw->pt.vertex_element[i].src_format;
+ key.element[nr].input_buffer = draw->pt.vertex_element[i].vertex_buffer_index;
+ key.element[nr].input_offset = draw->pt.vertex_element[i].src_offset;
+ key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ key.element[nr].output_offset = dst_offset;
+
+ dst_offset += 4 * sizeof(float);
+ nr++;
+ }
+
+ assert(dst_offset <= vertex_size);
+
+ key.nr_elements = nr;
+ key.output_stride = vertex_size;
+
+
+ if (!fetch->translate ||
+ translate_key_compare(&fetch->translate->key, &key) != 0)
+ {
+ translate_key_sanitize(&key);
+ fetch->translate = translate_cache_find(fetch->cache, &key);
+
+ {
+ static struct vertex_header vh = { 0, 1, 0, UNDEFINED_VERTEX_ID, { .0f, .0f, .0f, .0f } };
+ fetch->translate->set_buffer(fetch->translate,
+ draw->pt.nr_vertex_buffers,
+ &vh,
+ 0);
+ }
+ }
+
+ fetch->need_edgeflags = ((draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
+ draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) &&
+ draw->pt.user.edgeflag);
+}
+
+
+
+
+void draw_pt_fetch_run( struct pt_fetch *fetch,
+ const unsigned *elts,
+ unsigned count,
+ char *verts )
+{
+ struct draw_context *draw = fetch->draw;
+ struct translate *translate = fetch->translate;
+ unsigned i;
+
+ for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
+ translate->set_buffer(translate,
+ i,
+ ((char *)draw->pt.user.vbuffer[i] +
+ draw->pt.vertex_buffer[i].buffer_offset),
+ draw->pt.vertex_buffer[i].stride );
+ }
+
+ translate->run_elts( translate,
+ elts,
+ count,
+ verts );
+
+ /* Edgeflags are hard to fit into a translate program, populate
+ * them separately if required. In the setup above they are
+ * defaulted to one, so only need this if there is reason to change
+ * that default:
+ */
+ if (fetch->need_edgeflags) {
+ for (i = 0; i < count; i++) {
+ struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
+ vh->edgeflag = draw_pt_get_edgeflag( draw, elts[i] );
+ }
+ }
+}
+
+
+void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
+ unsigned start,
+ unsigned count,
+ char *verts )
+{
+ struct draw_context *draw = fetch->draw;
+ struct translate *translate = fetch->translate;
+ unsigned i;
+
+ for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
+ translate->set_buffer(translate,
+ i,
+ ((char *)draw->pt.user.vbuffer[i] +
+ draw->pt.vertex_buffer[i].buffer_offset),
+ draw->pt.vertex_buffer[i].stride );
+ }
+
+ translate->run( translate,
+ start,
+ count,
+ verts );
+
+ /* Edgeflags are hard to fit into a translate program, populate
+ * them separately if required. In the setup above they are
+ * defaulted to one, so only need this if there is reason to change
+ * that default:
+ */
+ if (fetch->need_edgeflags) {
+ for (i = 0; i < count; i++) {
+ struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
+ vh->edgeflag = draw_pt_get_edgeflag( draw, start + i );
+ }
+ }
+}
+
+
+struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw )
+{
+ struct pt_fetch *fetch = CALLOC_STRUCT(pt_fetch);
+ if (!fetch)
+ return NULL;
+
+ fetch->draw = draw;
+ fetch->cache = translate_cache_create();
+ if (!fetch->cache) {
+ FREE(fetch);
+ return NULL;
+ }
+
+ return fetch;
+}
+
+void draw_pt_fetch_destroy( struct pt_fetch *fetch )
+{
+ if (fetch->cache)
+ translate_cache_destroy(fetch->cache);
+
+ FREE(fetch);
+}
+
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
new file mode 100644
index 0000000000..e7fe6b3b76
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -0,0 +1,437 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_memory.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+#include "translate/translate.h"
+#include "translate/translate_cache.h"
+
+/* The simplest 'middle end' in the new vertex code.
+ *
+ * The responsibilities of a middle end are to:
+ * - perform vertex fetch using
+ * - draw vertex element/buffer state
+ * - a list of fetch indices we received as an input
+ * - run the vertex shader
+ * - cliptest,
+ * - clip coord calculation
+ * - viewport transformation
+ * - if necessary, run the primitive pipeline, passing it:
+ * - a linear array of vertex_header vertices constructed here
+ * - a set of draw indices we received as an input
+ * - otherwise, drive the hw backend,
+ * - allocate space for hardware format vertices
+ * - translate the vertex-shader output vertices to hw format
+ * - calling the backend draw functions.
+ *
+ * For convenience, we provide a helper function to drive the hardware
+ * backend given similar inputs to those required to run the pipeline.
+ *
+ * In the case of passthrough mode, many of these actions are disabled
+ * or noops, so we end up doing:
+ *
+ * - perform vertex fetch
+ * - drive the hw backend
+ *
+ * IE, basically just vertex fetch to post-vs-format vertices,
+ * followed by a call to the backend helper function.
+ */
+
+
+struct fetch_emit_middle_end {
+ struct draw_pt_middle_end base;
+ struct draw_context *draw;
+
+ struct translate *translate;
+ const struct vertex_info *vinfo;
+
+ /* Cache point size somewhere it's address won't change:
+ */
+ float point_size;
+
+ struct translate_cache *cache;
+};
+
+
+
+
+static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
+ unsigned prim,
+ unsigned opt,
+ unsigned *max_vertices )
+{
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+ struct draw_context *draw = feme->draw;
+ const struct vertex_info *vinfo;
+ unsigned i, dst_offset;
+ boolean ok;
+ struct translate_key key;
+
+
+ ok = draw->render->set_primitive( draw->render,
+ prim );
+ if (!ok) {
+ assert(0);
+ return;
+ }
+
+ /* Must do this after set_primitive() above:
+ */
+ vinfo = feme->vinfo = draw->render->get_vertex_info(draw->render);
+
+
+
+ /* Transform from API vertices to HW vertices, skipping the
+ * pipeline_vertex intermediate step.
+ */
+ dst_offset = 0;
+ memset(&key, 0, sizeof(key));
+
+ for (i = 0; i < vinfo->num_attribs; i++) {
+ const struct pipe_vertex_element *src = &draw->pt.vertex_element[vinfo->attrib[i].src_index];
+
+ unsigned emit_sz = 0;
+ unsigned input_format = src->src_format;
+ unsigned input_buffer = src->vertex_buffer_index;
+ unsigned input_offset = src->src_offset;
+ unsigned output_format;
+
+ switch (vinfo->attrib[i].emit) {
+ case EMIT_4UB:
+ output_format = PIPE_FORMAT_R8G8B8A8_UNORM;
+ emit_sz = 4 * sizeof(unsigned char);
+ break;
+ case EMIT_4F:
+ output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ emit_sz = 4 * sizeof(float);
+ break;
+ case EMIT_3F:
+ output_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ emit_sz = 3 * sizeof(float);
+ break;
+ case EMIT_2F:
+ output_format = PIPE_FORMAT_R32G32_FLOAT;
+ emit_sz = 2 * sizeof(float);
+ break;
+ case EMIT_1F:
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ break;
+ case EMIT_1F_PSIZE:
+ input_format = PIPE_FORMAT_R32_FLOAT;
+ input_buffer = draw->pt.nr_vertex_buffers;
+ input_offset = 0;
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ emit_sz = 1 * sizeof(float);
+ break;
+ case EMIT_OMIT:
+ continue;
+ default:
+ assert(0);
+ output_format = PIPE_FORMAT_NONE;
+ emit_sz = 0;
+ continue;
+ }
+
+ key.element[i].input_format = input_format;
+ key.element[i].input_buffer = input_buffer;
+ key.element[i].input_offset = input_offset;
+ key.element[i].output_format = output_format;
+ key.element[i].output_offset = dst_offset;
+
+ dst_offset += emit_sz;
+ }
+
+ key.nr_elements = vinfo->num_attribs;
+ key.output_stride = vinfo->size * 4;
+
+ /* Don't bother with caching at this stage:
+ */
+ if (!feme->translate ||
+ translate_key_compare(&feme->translate->key, &key) != 0)
+ {
+ translate_key_sanitize(&key);
+ feme->translate = translate_cache_find(feme->cache,
+ &key);
+
+
+ feme->translate->set_buffer(feme->translate,
+ draw->pt.nr_vertex_buffers,
+ &feme->point_size,
+ 0);
+ }
+
+ feme->point_size = draw->rasterizer->point_size;
+
+ for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
+ feme->translate->set_buffer(feme->translate,
+ i,
+ ((char *)draw->pt.user.vbuffer[i] +
+ draw->pt.vertex_buffer[i].buffer_offset),
+ draw->pt.vertex_buffer[i].stride );
+ }
+
+ *max_vertices = (draw->render->max_vertex_buffer_bytes /
+ (vinfo->size * 4));
+
+ /* Return an even number of verts.
+ * This prevents "parity" errors when splitting long triangle strips which
+ * can lead to front/back culling mix-ups.
+ * Every other triangle in a strip has an alternate front/back orientation
+ * so splitting at an odd position can cause the orientation of subsequent
+ * triangles to get reversed.
+ */
+ *max_vertices = *max_vertices & ~1;
+}
+
+
+
+
+
+static void fetch_emit_run( struct draw_pt_middle_end *middle,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+ struct draw_context *draw = feme->draw;
+ void *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ if (fetch_count >= UNDEFINED_VERTEX_ID) {
+ assert(0);
+ return;
+ }
+
+ draw->render->allocate_vertices( draw->render,
+ (ushort)feme->translate->key.output_stride,
+ (ushort)fetch_count );
+
+ hw_verts = draw->render->map_vertices( draw->render );
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+
+ /* Single routine to fetch vertices and emit HW verts.
+ */
+ feme->translate->run_elts( feme->translate,
+ fetch_elts,
+ fetch_count,
+ hw_verts );
+
+ if (0) {
+ unsigned i;
+ for (i = 0; i < fetch_count; i++) {
+ debug_printf("\n\nvertex %d:\n", i);
+ draw_dump_emitted_vertex( feme->vinfo,
+ (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i );
+ }
+ }
+
+ draw->render->unmap_vertices( draw->render,
+ 0,
+ (ushort)(fetch_count - 1) );
+
+ /* XXX: Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw( draw->render,
+ draw_elts,
+ draw_count );
+
+ /* Done -- that was easy, wasn't it:
+ */
+ draw->render->release_vertices( draw->render );
+
+}
+
+
+static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count )
+{
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+ struct draw_context *draw = feme->draw;
+ void *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ if (count >= UNDEFINED_VERTEX_ID)
+ goto fail;
+
+ if (!draw->render->allocate_vertices( draw->render,
+ (ushort)feme->translate->key.output_stride,
+ (ushort)count ))
+ goto fail;
+
+ hw_verts = draw->render->map_vertices( draw->render );
+ if (!hw_verts)
+ goto fail;
+
+ /* Single routine to fetch vertices and emit HW verts.
+ */
+ feme->translate->run( feme->translate,
+ start,
+ count,
+ hw_verts );
+
+ if (0) {
+ unsigned i;
+ for (i = 0; i < count; i++) {
+ debug_printf("\n\nvertex %d:\n", i);
+ draw_dump_emitted_vertex( feme->vinfo,
+ (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i );
+ }
+ }
+
+ draw->render->unmap_vertices( draw->render, 0, count - 1 );
+
+ /* XXX: Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw_arrays( draw->render, 0, count );
+
+ /* Done -- that was easy, wasn't it:
+ */
+ draw->render->release_vertices( draw->render );
+ return;
+
+fail:
+ assert(0);
+ return;
+}
+
+
+static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+ struct draw_context *draw = feme->draw;
+ void *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ if (count >= UNDEFINED_VERTEX_ID)
+ return FALSE;
+
+ if (!draw->render->allocate_vertices( draw->render,
+ (ushort)feme->translate->key.output_stride,
+ (ushort)count ))
+ return FALSE;
+
+ hw_verts = draw->render->map_vertices( draw->render );
+ if (!hw_verts)
+ return FALSE;
+
+ /* Single routine to fetch vertices and emit HW verts.
+ */
+ feme->translate->run( feme->translate,
+ start,
+ count,
+ hw_verts );
+
+ draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) );
+
+ /* XXX: Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw( draw->render,
+ draw_elts,
+ draw_count );
+
+ /* Done -- that was easy, wasn't it:
+ */
+ draw->render->release_vertices( draw->render );
+
+ return TRUE;
+}
+
+
+
+
+static void fetch_emit_finish( struct draw_pt_middle_end *middle )
+{
+ /* nothing to do */
+}
+
+static void fetch_emit_destroy( struct draw_pt_middle_end *middle )
+{
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+
+ if (feme->cache)
+ translate_cache_destroy(feme->cache);
+
+ FREE(middle);
+}
+
+
+struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw )
+{
+ struct fetch_emit_middle_end *fetch_emit = CALLOC_STRUCT( fetch_emit_middle_end );
+ if (fetch_emit == NULL)
+ return NULL;
+
+ fetch_emit->cache = translate_cache_create();
+ if (!fetch_emit->cache) {
+ FREE(fetch_emit);
+ return NULL;
+ }
+
+ fetch_emit->base.prepare = fetch_emit_prepare;
+ fetch_emit->base.run = fetch_emit_run;
+ fetch_emit->base.run_linear = fetch_emit_run_linear;
+ fetch_emit->base.run_linear_elts = fetch_emit_run_linear_elts;
+ fetch_emit->base.finish = fetch_emit_finish;
+ fetch_emit->base.destroy = fetch_emit_destroy;
+
+ fetch_emit->draw = draw;
+
+ return &fetch_emit->base;
+}
+
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
new file mode 100644
index 0000000000..44147aed9b
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
@@ -0,0 +1,429 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+#include "draw/draw_vs.h"
+
+#include "translate/translate.h"
+
+struct fetch_shade_emit;
+
+
+/* Prototype fetch, shade, emit-hw-verts all in one go.
+ */
+struct fetch_shade_emit {
+ struct draw_pt_middle_end base;
+ struct draw_context *draw;
+
+
+ /* Temporaries:
+ */
+ const float *constants;
+ unsigned pitch[PIPE_MAX_ATTRIBS];
+ const ubyte *src[PIPE_MAX_ATTRIBS];
+ unsigned prim;
+
+ struct draw_vs_varient_key key;
+ struct draw_vs_varient *active;
+
+
+ const struct vertex_info *vinfo;
+};
+
+
+
+
+static void fse_prepare( struct draw_pt_middle_end *middle,
+ unsigned prim,
+ unsigned opt,
+ unsigned *max_vertices )
+{
+ struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+ struct draw_context *draw = fse->draw;
+ unsigned num_vs_inputs = draw->vs.vertex_shader->info.num_inputs;
+ const struct vertex_info *vinfo;
+ unsigned i;
+ unsigned nr_vbs = 0;
+
+
+ if (!draw->render->set_primitive( draw->render,
+ prim )) {
+ assert(0);
+ return;
+ }
+
+ /* Must do this after set_primitive() above:
+ */
+ fse->vinfo = vinfo = draw->render->get_vertex_info(draw->render);
+
+
+
+ fse->key.output_stride = vinfo->size * 4;
+ fse->key.nr_outputs = vinfo->num_attribs;
+ fse->key.nr_inputs = num_vs_inputs;
+
+ fse->key.nr_elements = MAX2(fse->key.nr_outputs, /* outputs - translate to hw format */
+ fse->key.nr_inputs); /* inputs - fetch from api format */
+
+ fse->key.viewport = (!draw->rasterizer->bypass_vs_clip_and_viewport &&
+ !draw->identity_viewport);
+ fse->key.clip = !draw->bypass_clipping;
+ fse->key.const_vbuffers = 0;
+
+ memset(fse->key.element, 0,
+ fse->key.nr_elements * sizeof(fse->key.element[0]));
+
+ for (i = 0; i < num_vs_inputs; i++) {
+ const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];
+ fse->key.element[i].in.format = src->src_format;
+
+ /* Consider ignoring these, ie make generated programs
+ * independent of this state:
+ */
+ fse->key.element[i].in.buffer = src->vertex_buffer_index;
+ fse->key.element[i].in.offset = src->src_offset;
+ nr_vbs = MAX2(nr_vbs, src->vertex_buffer_index + 1);
+ }
+
+ for (i = 0; i < 5 && i < nr_vbs; i++) {
+ if (draw->pt.vertex_buffer[i].stride == 0)
+ fse->key.const_vbuffers |= (1<<i);
+ }
+
+ if (0) debug_printf("%s: lookup const_vbuffers: %x\n", __FUNCTION__, fse->key.const_vbuffers);
+
+ {
+ unsigned dst_offset = 0;
+
+ for (i = 0; i < vinfo->num_attribs; i++) {
+ unsigned emit_sz = 0;
+
+ switch (vinfo->attrib[i].emit) {
+ case EMIT_4F:
+ emit_sz = 4 * sizeof(float);
+ break;
+ case EMIT_3F:
+ emit_sz = 3 * sizeof(float);
+ break;
+ case EMIT_2F:
+ emit_sz = 2 * sizeof(float);
+ break;
+ case EMIT_1F:
+ emit_sz = 1 * sizeof(float);
+ break;
+ case EMIT_1F_PSIZE:
+ emit_sz = 1 * sizeof(float);
+ break;
+ case EMIT_4UB:
+ emit_sz = 4 * sizeof(ubyte);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* The elements in the key correspond to vertex shader output
+ * numbers, not to positions in the hw vertex description --
+ * that's handled by the output_offset field.
+ */
+ fse->key.element[i].out.format = vinfo->attrib[i].emit;
+ fse->key.element[i].out.vs_output = vinfo->attrib[i].src_index;
+ fse->key.element[i].out.offset = dst_offset;
+
+ dst_offset += emit_sz;
+ assert(fse->key.output_stride >= dst_offset);
+ }
+ }
+
+
+ fse->active = draw_vs_lookup_varient( draw->vs.vertex_shader,
+ &fse->key );
+
+ if (!fse->active) {
+ assert(0);
+ return ;
+ }
+
+ if (0) debug_printf("%s: found const_vbuffers: %x\n", __FUNCTION__,
+ fse->active->key.const_vbuffers);
+
+ /* Now set buffer pointers:
+ */
+ for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
+ fse->active->set_buffer( fse->active,
+ i,
+ ((const ubyte *) draw->pt.user.vbuffer[i] +
+ draw->pt.vertex_buffer[i].buffer_offset),
+ draw->pt.vertex_buffer[i].stride );
+ }
+
+ *max_vertices = (draw->render->max_vertex_buffer_bytes /
+ (vinfo->size * 4));
+
+ /* Return an even number of verts.
+ * This prevents "parity" errors when splitting long triangle strips which
+ * can lead to front/back culling mix-ups.
+ * Every other triangle in a strip has an alternate front/back orientation
+ * so splitting at an odd position can cause the orientation of subsequent
+ * triangles to get reversed.
+ */
+ *max_vertices = *max_vertices & ~1;
+
+ /* Probably need to do this somewhere (or fix exec shader not to
+ * need it):
+ */
+ if (1) {
+ struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+ vs->prepare(vs, draw);
+ }
+
+
+ //return TRUE;
+}
+
+
+
+
+
+
+
+static void fse_run_linear( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count )
+{
+ struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+ struct draw_context *draw = fse->draw;
+ char *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ if (count >= UNDEFINED_VERTEX_ID)
+ goto fail;
+
+ if (!draw->render->allocate_vertices( draw->render,
+ (ushort)fse->key.output_stride,
+ (ushort)count ))
+ goto fail;
+
+ hw_verts = draw->render->map_vertices( draw->render );
+ if (!hw_verts)
+ goto fail;
+
+ /* Single routine to fetch vertices, run shader and emit HW verts.
+ * Clipping is done elsewhere -- either by the API or on hardware,
+ * or for some other reason not required...
+ */
+ fse->active->run_linear( fse->active,
+ start, count,
+ hw_verts );
+
+
+ if (0) {
+ unsigned i;
+ for (i = 0; i < count; i++) {
+ debug_printf("\n\n%s vertex %d: (stride %d, offset %d)\n", __FUNCTION__, i,
+ fse->key.output_stride,
+ fse->key.output_stride * i);
+
+ draw_dump_emitted_vertex( fse->vinfo,
+ (const uint8_t *)hw_verts + fse->key.output_stride * i );
+ }
+ }
+
+ draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) );
+
+ /* Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw_arrays( draw->render,
+ 0,
+ count );
+
+
+ draw->render->release_vertices( draw->render );
+
+ return;
+
+fail:
+ assert(0);
+ return;
+}
+
+
+static void
+fse_run(struct draw_pt_middle_end *middle,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+ struct draw_context *draw = fse->draw;
+ void *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ if (fetch_count >= UNDEFINED_VERTEX_ID)
+ goto fail;
+
+ if (!draw->render->allocate_vertices( draw->render,
+ (ushort)fse->key.output_stride,
+ (ushort)fetch_count ))
+ goto fail;
+
+ hw_verts = draw->render->map_vertices( draw->render );
+ if (!hw_verts)
+ goto fail;
+
+
+ /* Single routine to fetch vertices, run shader and emit HW verts.
+ */
+ fse->active->run_elts( fse->active,
+ fetch_elts,
+ fetch_count,
+ hw_verts );
+
+
+ if (0) {
+ unsigned i;
+ for (i = 0; i < fetch_count; i++) {
+ debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i);
+ draw_dump_emitted_vertex( fse->vinfo,
+ (const uint8_t *)hw_verts +
+ fse->key.output_stride * i );
+ }
+ }
+
+ draw->render->unmap_vertices( draw->render, 0, (ushort)(fetch_count - 1) );
+
+ draw->render->draw( draw->render,
+ draw_elts,
+ draw_count );
+
+
+ draw->render->release_vertices( draw->render );
+ return;
+
+fail:
+ assert(0);
+ return;
+}
+
+
+
+static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
+ struct draw_context *draw = fse->draw;
+ char *hw_verts;
+
+ /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+ */
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+
+ if (count >= UNDEFINED_VERTEX_ID)
+ return FALSE;
+
+ if (!draw->render->allocate_vertices( draw->render,
+ (ushort)fse->key.output_stride,
+ (ushort)count ))
+ return FALSE;
+
+ hw_verts = draw->render->map_vertices( draw->render );
+ if (!hw_verts)
+ return FALSE;
+
+ /* Single routine to fetch vertices, run shader and emit HW verts.
+ * Clipping is done elsewhere -- either by the API or on hardware,
+ * or for some other reason not required...
+ */
+ fse->active->run_linear( fse->active,
+ start, count,
+ hw_verts );
+
+
+ draw->render->draw( draw->render,
+ draw_elts,
+ draw_count );
+
+
+ draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) );
+
+ draw->render->release_vertices( draw->render );
+
+ return TRUE;
+}
+
+
+
+static void fse_finish( struct draw_pt_middle_end *middle )
+{
+}
+
+
+static void
+fse_destroy( struct draw_pt_middle_end *middle )
+{
+ FREE(middle);
+}
+
+struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw )
+{
+ struct fetch_shade_emit *fse = CALLOC_STRUCT(fetch_shade_emit);
+ if (!fse)
+ return NULL;
+
+ fse->base.prepare = fse_prepare;
+ fse->base.run = fse_run;
+ fse->base.run_linear = fse_run_linear;
+ fse->base.run_linear_elts = fse_run_linear_elts;
+ fse->base.finish = fse_finish;
+ fse->base.destroy = fse_destroy;
+ fse->draw = draw;
+
+ return &fse->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
new file mode 100644
index 0000000000..df6c265b7e
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -0,0 +1,395 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "draw/draw_context.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+#include "draw/draw_vs.h"
+#include "translate/translate.h"
+
+
+struct fetch_pipeline_middle_end {
+ struct draw_pt_middle_end base;
+ struct draw_context *draw;
+
+ struct pt_emit *emit;
+ struct pt_fetch *fetch;
+ struct pt_post_vs *post_vs;
+
+ unsigned vertex_data_offset;
+ unsigned vertex_size;
+ unsigned prim;
+ unsigned opt;
+};
+
+
+static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
+ unsigned prim,
+ unsigned opt,
+ unsigned *max_vertices )
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+
+ /* Add one to num_outputs because the pipeline occasionally tags on
+ * an additional texcoord, eg for AA lines.
+ */
+ unsigned nr = MAX2( vs->info.num_inputs,
+ vs->info.num_outputs + 1 );
+
+ fpme->prim = prim;
+ fpme->opt = opt;
+
+ /* Always leave room for the vertex header whether we need it or
+ * not. It's hard to get rid of it in particular because of the
+ * viewport code in draw_pt_post_vs.c.
+ */
+ fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
+
+
+
+ draw_pt_fetch_prepare( fpme->fetch,
+ vs->info.num_inputs,
+ fpme->vertex_size );
+ /* XXX: it's not really gl rasterization rules we care about here,
+ * but gl vs dx9 clip spaces.
+ */
+ draw_pt_post_vs_prepare( fpme->post_vs,
+ (boolean)draw->bypass_clipping,
+ (boolean)(draw->identity_viewport ||
+ draw->rasterizer->bypass_vs_clip_and_viewport),
+ (boolean)draw->rasterizer->gl_rasterization_rules );
+
+
+ if (!(opt & PT_PIPELINE)) {
+ draw_pt_emit_prepare( fpme->emit,
+ prim,
+ max_vertices );
+
+ *max_vertices = MAX2( *max_vertices,
+ DRAW_PIPE_MAX_VERTICES );
+ }
+ else {
+ *max_vertices = DRAW_PIPE_MAX_VERTICES;
+ }
+
+ /* return even number */
+ *max_vertices = *max_vertices & ~1;
+
+ /* No need to prepare the shader.
+ */
+ vs->prepare(vs, draw);
+}
+
+
+
+static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ struct draw_vertex_shader *shader = draw->vs.vertex_shader;
+ unsigned opt = fpme->opt;
+ unsigned alloc_count = align( fetch_count, 4 );
+
+ struct vertex_header *pipeline_verts =
+ (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
+
+ if (!pipeline_verts) {
+ /* Not much we can do here - just skip the rendering.
+ */
+ assert(0);
+ return;
+ }
+
+ /* Fetch into our vertex buffer
+ */
+ draw_pt_fetch_run( fpme->fetch,
+ fetch_elts,
+ fetch_count,
+ (char *)pipeline_verts );
+
+ /* Run the shader, note that this overwrites the data[] parts of
+ * the pipeline verts. If there is no shader, eg if
+ * bypass_vs_clip_and_viewport, then the inputs == outputs, and are
+ * already in the correct place.
+ */
+ if (opt & PT_SHADE)
+ {
+ shader->run_linear(shader,
+ (const float (*)[4])pipeline_verts->data,
+ ( float (*)[4])pipeline_verts->data,
+ (const float (*)[4])draw->pt.user.constants,
+ fetch_count,
+ fpme->vertex_size,
+ fpme->vertex_size);
+ }
+
+ if (draw_pt_post_vs_run( fpme->post_vs,
+ pipeline_verts,
+ fetch_count,
+ fpme->vertex_size ))
+ {
+ opt |= PT_PIPELINE;
+ }
+
+ /* Do we need to run the pipeline?
+ */
+ if (opt & PT_PIPELINE) {
+ draw_pipeline_run( fpme->draw,
+ fpme->prim,
+ pipeline_verts,
+ fetch_count,
+ fpme->vertex_size,
+ draw_elts,
+ draw_count );
+ }
+ else {
+ draw_pt_emit( fpme->emit,
+ (const float (*)[4])pipeline_verts->data,
+ fetch_count,
+ fpme->vertex_size,
+ draw_elts,
+ draw_count );
+ }
+
+
+ FREE(pipeline_verts);
+}
+
+
+static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count)
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ struct draw_vertex_shader *shader = draw->vs.vertex_shader;
+ unsigned opt = fpme->opt;
+ unsigned alloc_count = align( count, 4 );
+
+ struct vertex_header *pipeline_verts =
+ (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
+
+ if (!pipeline_verts) {
+ /* Not much we can do here - just skip the rendering.
+ */
+ assert(0);
+ return;
+ }
+
+ /* Fetch into our vertex buffer
+ */
+ draw_pt_fetch_run_linear( fpme->fetch,
+ start,
+ count,
+ (char *)pipeline_verts );
+
+ /* Run the shader, note that this overwrites the data[] parts of
+ * the pipeline verts. If there is no shader, ie if
+ * bypass_vs_clip_and_viewport, then the inputs == outputs, and are
+ * already in the correct place.
+ */
+ if (opt & PT_SHADE)
+ {
+ shader->run_linear(shader,
+ (const float (*)[4])pipeline_verts->data,
+ ( float (*)[4])pipeline_verts->data,
+ (const float (*)[4])draw->pt.user.constants,
+ count,
+ fpme->vertex_size,
+ fpme->vertex_size);
+ }
+
+ if (draw_pt_post_vs_run( fpme->post_vs,
+ pipeline_verts,
+ count,
+ fpme->vertex_size ))
+ {
+ opt |= PT_PIPELINE;
+ }
+
+ /* Do we need to run the pipeline?
+ */
+ if (opt & PT_PIPELINE) {
+ draw_pipeline_run_linear( fpme->draw,
+ fpme->prim,
+ pipeline_verts,
+ count,
+ fpme->vertex_size);
+ }
+ else {
+ draw_pt_emit_linear( fpme->emit,
+ (const float (*)[4])pipeline_verts->data,
+ fpme->vertex_size,
+ count );
+ }
+
+ FREE(pipeline_verts);
+}
+
+
+
+static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
+ unsigned start,
+ unsigned count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ struct draw_vertex_shader *shader = draw->vs.vertex_shader;
+ unsigned opt = fpme->opt;
+ unsigned alloc_count = align( count, 4 );
+
+ struct vertex_header *pipeline_verts =
+ (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
+
+ if (!pipeline_verts)
+ return FALSE;
+
+ /* Fetch into our vertex buffer
+ */
+ draw_pt_fetch_run_linear( fpme->fetch,
+ start,
+ count,
+ (char *)pipeline_verts );
+
+ /* Run the shader, note that this overwrites the data[] parts of
+ * the pipeline verts. If there is no shader, ie if
+ * bypass_vs_clip_and_viewport, then the inputs == outputs, and are
+ * already in the correct place.
+ */
+ if (opt & PT_SHADE)
+ {
+ shader->run_linear(shader,
+ (const float (*)[4])pipeline_verts->data,
+ ( float (*)[4])pipeline_verts->data,
+ (const float (*)[4])draw->pt.user.constants,
+ count,
+ fpme->vertex_size,
+ fpme->vertex_size);
+ }
+
+ if (draw_pt_post_vs_run( fpme->post_vs,
+ pipeline_verts,
+ count,
+ fpme->vertex_size ))
+ {
+ opt |= PT_PIPELINE;
+ }
+
+ /* Do we need to run the pipeline?
+ */
+ if (opt & PT_PIPELINE) {
+ draw_pipeline_run( fpme->draw,
+ fpme->prim,
+ pipeline_verts,
+ count,
+ fpme->vertex_size,
+ draw_elts,
+ draw_count );
+ }
+ else {
+ draw_pt_emit( fpme->emit,
+ (const float (*)[4])pipeline_verts->data,
+ count,
+ fpme->vertex_size,
+ draw_elts,
+ draw_count );
+ }
+
+ FREE(pipeline_verts);
+ return TRUE;
+}
+
+
+
+static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
+{
+ /* nothing to do */
+}
+
+static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+
+ if (fpme->fetch)
+ draw_pt_fetch_destroy( fpme->fetch );
+
+ if (fpme->emit)
+ draw_pt_emit_destroy( fpme->emit );
+
+ if (fpme->post_vs)
+ draw_pt_post_vs_destroy( fpme->post_vs );
+
+ FREE(middle);
+}
+
+
+struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw )
+{
+ struct fetch_pipeline_middle_end *fpme = CALLOC_STRUCT( fetch_pipeline_middle_end );
+ if (!fpme)
+ goto fail;
+
+ fpme->base.prepare = fetch_pipeline_prepare;
+ fpme->base.run = fetch_pipeline_run;
+ fpme->base.run_linear = fetch_pipeline_linear_run;
+ fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
+ fpme->base.finish = fetch_pipeline_finish;
+ fpme->base.destroy = fetch_pipeline_destroy;
+
+ fpme->draw = draw;
+
+ fpme->fetch = draw_pt_fetch_create( draw );
+ if (!fpme->fetch)
+ goto fail;
+
+ fpme->post_vs = draw_pt_post_vs_create( draw );
+ if (!fpme->post_vs)
+ goto fail;
+
+ fpme->emit = draw_pt_emit_create( draw );
+ if (!fpme->emit)
+ goto fail;
+
+ return &fpme->base;
+
+ fail:
+ if (fpme)
+ fetch_pipeline_destroy( &fpme->base );
+
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
new file mode 100644
index 0000000000..00d7197b13
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
@@ -0,0 +1,233 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "pipe/p_context.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+
+struct pt_post_vs {
+ struct draw_context *draw;
+
+ boolean (*run)( struct pt_post_vs *pvs,
+ struct vertex_header *vertices,
+ unsigned count,
+ unsigned stride );
+};
+
+
+
+static INLINE float
+dot4(const float *a, const float *b)
+{
+ return (a[0]*b[0] +
+ a[1]*b[1] +
+ a[2]*b[2] +
+ a[3]*b[3]);
+}
+
+
+
+static INLINE unsigned
+compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr)
+{
+ unsigned mask = 0x0;
+ unsigned i;
+
+#if 0
+ debug_printf("compute clipmask %f %f %f %f\n",
+ clip[0], clip[1], clip[2], clip[3]);
+ assert(clip[3] != 0.0);
+#endif
+
+ /* Do the hardwired planes first:
+ */
+ if (-clip[0] + clip[3] < 0) mask |= (1<<0);
+ if ( clip[0] + clip[3] < 0) mask |= (1<<1);
+ if (-clip[1] + clip[3] < 0) mask |= (1<<2);
+ if ( clip[1] + clip[3] < 0) mask |= (1<<3);
+ if ( clip[2] + clip[3] < 0) mask |= (1<<4); /* match mesa clipplane numbering - for now */
+ if (-clip[2] + clip[3] < 0) mask |= (1<<5); /* match mesa clipplane numbering - for now */
+
+ /* Followed by any remaining ones:
+ */
+ for (i = 6; i < nr; i++) {
+ if (dot4(clip, plane[i]) < 0)
+ mask |= (1<<i);
+ }
+
+ return mask;
+}
+
+
+/* The normal case - cliptest, rhw divide, viewport transform.
+ *
+ * Also handle identity viewport here at the expense of a few wasted
+ * instructions
+ */
+static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
+ struct vertex_header *vertices,
+ unsigned count,
+ unsigned stride )
+{
+ struct vertex_header *out = vertices;
+ const float *scale = pvs->draw->viewport.scale;
+ const float *trans = pvs->draw->viewport.translate;
+ const unsigned pos = pvs->draw->vs.position_output;
+ unsigned clipped = 0;
+ unsigned j;
+
+ if (0) debug_printf("%s\n");
+
+ for (j = 0; j < count; j++) {
+ float *position = out->data[pos];
+
+ out->clip[0] = position[0];
+ out->clip[1] = position[1];
+ out->clip[2] = position[2];
+ out->clip[3] = position[3];
+
+ out->vertex_id = 0xffff;
+ out->clipmask = compute_clipmask_gl(out->clip,
+ pvs->draw->plane,
+ pvs->draw->nr_planes);
+ clipped += out->clipmask;
+
+ if (out->clipmask == 0)
+ {
+ /* divide by w */
+ float w = 1.0f / position[3];
+
+ /* Viewport mapping */
+ position[0] = position[0] * w * scale[0] + trans[0];
+ position[1] = position[1] * w * scale[1] + trans[1];
+ position[2] = position[2] * w * scale[2] + trans[2];
+ position[3] = w;
+#if 0
+ debug_printf("post viewport: %f %f %f %f\n",
+ position[0],
+ position[1],
+ position[2],
+ position[3]);
+#endif
+ }
+
+ out = (struct vertex_header *)( (char *)out + stride );
+ }
+
+ return clipped != 0;
+}
+
+
+
+/* If bypass_clipping is set, skip cliptest and rhw divide.
+ */
+static boolean post_vs_viewport( struct pt_post_vs *pvs,
+ struct vertex_header *vertices,
+ unsigned count,
+ unsigned stride )
+{
+ struct vertex_header *out = vertices;
+ const float *scale = pvs->draw->viewport.scale;
+ const float *trans = pvs->draw->viewport.translate;
+ const unsigned pos = pvs->draw->vs.position_output;
+ unsigned j;
+
+ if (0) debug_printf("%s\n", __FUNCTION__);
+ for (j = 0; j < count; j++) {
+ float *position = out->data[pos];
+
+ /* Viewport mapping only, no cliptest/rhw divide
+ */
+ position[0] = position[0] * scale[0] + trans[0];
+ position[1] = position[1] * scale[1] + trans[1];
+ position[2] = position[2] * scale[2] + trans[2];
+
+ out = (struct vertex_header *)((char *)out + stride);
+ }
+
+ return FALSE;
+}
+
+
+/* If bypass_clipping is set and we have an identity viewport, nothing
+ * to do.
+ */
+static boolean post_vs_none( struct pt_post_vs *pvs,
+ struct vertex_header *vertices,
+ unsigned count,
+ unsigned stride )
+{
+ if (0) debug_printf("%s\n", __FUNCTION__);
+ return FALSE;
+}
+
+boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
+ struct vertex_header *pipeline_verts,
+ unsigned count,
+ unsigned stride )
+{
+ return pvs->run( pvs, pipeline_verts, count, stride );
+}
+
+
+void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
+ boolean bypass_clipping,
+ boolean bypass_viewport,
+ boolean opengl )
+{
+ if (bypass_clipping) {
+ if (bypass_viewport)
+ pvs->run = post_vs_none;
+ else
+ pvs->run = post_vs_viewport;
+ }
+ else {
+ //if (opengl)
+ pvs->run = post_vs_cliptest_viewport_gl;
+ }
+}
+
+
+struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw )
+{
+ struct pt_post_vs *pvs = CALLOC_STRUCT( pt_post_vs );
+ if (!pvs)
+ return NULL;
+
+ pvs->draw = draw;
+
+ return pvs;
+}
+
+void draw_pt_post_vs_destroy( struct pt_post_vs *pvs )
+{
+ FREE(pvs);
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_util.c b/src/gallium/auxiliary/draw/draw_pt_util.c
new file mode 100644
index 0000000000..b61fa29143
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_util.c
@@ -0,0 +1,77 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pt.h"
+
+void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr)
+{
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ *first = 1;
+ *incr = 1;
+ break;
+ case PIPE_PRIM_LINES:
+ *first = 2;
+ *incr = 2;
+ break;
+ case PIPE_PRIM_LINE_STRIP:
+ case PIPE_PRIM_LINE_LOOP:
+ *first = 2;
+ *incr = 1;
+ break;
+ case PIPE_PRIM_TRIANGLES:
+ *first = 3;
+ *incr = 3;
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ case PIPE_PRIM_TRIANGLE_FAN:
+ case PIPE_PRIM_POLYGON:
+ *first = 3;
+ *incr = 1;
+ break;
+ case PIPE_PRIM_QUADS:
+ *first = 4;
+ *incr = 4;
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ *first = 4;
+ *incr = 2;
+ break;
+ default:
+ assert(0);
+ *first = 0;
+ *incr = 1; /* set to one so that count % incr works */
+ break;
+ }
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c
new file mode 100644
index 0000000000..d0e16c9bc3
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_varray.c
@@ -0,0 +1,193 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pt.h"
+
+#define FETCH_MAX 256
+#define DRAW_MAX (FETCH_MAX+8)
+
+struct varray_frontend {
+ struct draw_pt_front_end base;
+ struct draw_context *draw;
+
+ ushort draw_elts[DRAW_MAX];
+ unsigned fetch_elts[FETCH_MAX];
+
+ unsigned driver_fetch_max;
+ unsigned fetch_max;
+
+ struct draw_pt_middle_end *middle;
+
+ unsigned input_prim;
+ unsigned output_prim;
+};
+
+
+static void varray_flush_linear(struct varray_frontend *varray,
+ unsigned start, unsigned count)
+{
+ if (count) {
+ assert(varray->middle->run_linear);
+ varray->middle->run_linear(varray->middle, start, count);
+ }
+}
+
+static void varray_line_loop_segment(struct varray_frontend *varray,
+ unsigned start,
+ unsigned segment_start,
+ unsigned segment_count,
+ boolean end )
+{
+ assert(segment_count < varray->fetch_max);
+ if (segment_count >= 1) {
+ unsigned nr = 0, i;
+
+ for (i = 0; i < segment_count; i++)
+ varray->fetch_elts[nr++] = start + segment_start + i;
+
+ if (end)
+ varray->fetch_elts[nr++] = start;
+
+ assert(nr <= FETCH_MAX);
+
+ varray->middle->run(varray->middle,
+ varray->fetch_elts,
+ nr,
+ varray->draw_elts, /* ie. linear */
+ nr);
+ }
+}
+
+
+
+static void varray_fan_segment(struct varray_frontend *varray,
+ unsigned start,
+ unsigned segment_start,
+ unsigned segment_count )
+{
+ assert(segment_count < varray->fetch_max);
+ if (segment_count >= 2) {
+ unsigned nr = 0, i;
+
+ if (segment_start != 0)
+ varray->fetch_elts[nr++] = start;
+
+ for (i = 0 ; i < segment_count; i++)
+ varray->fetch_elts[nr++] = start + segment_start + i;
+
+ assert(nr <= FETCH_MAX);
+
+ varray->middle->run(varray->middle,
+ varray->fetch_elts,
+ nr,
+ varray->draw_elts, /* ie. linear */
+ nr);
+ }
+}
+
+
+
+
+#define FUNC varray_run
+#include "draw_pt_varray_tmp_linear.h"
+
+static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = {
+ PIPE_PRIM_POINTS,
+ PIPE_PRIM_LINES,
+ PIPE_PRIM_LINE_STRIP, /* decomposed LINELOOP */
+ PIPE_PRIM_LINE_STRIP,
+ PIPE_PRIM_TRIANGLES,
+ PIPE_PRIM_TRIANGLE_STRIP,
+ PIPE_PRIM_TRIANGLE_FAN,
+ PIPE_PRIM_QUADS,
+ PIPE_PRIM_QUAD_STRIP,
+ PIPE_PRIM_POLYGON
+};
+
+
+
+static void varray_prepare(struct draw_pt_front_end *frontend,
+ unsigned prim,
+ struct draw_pt_middle_end *middle,
+ unsigned opt)
+{
+ struct varray_frontend *varray = (struct varray_frontend *)frontend;
+
+ varray->base.run = varray_run;
+
+ varray->input_prim = prim;
+ varray->output_prim = decompose_prim[prim];
+
+ varray->middle = middle;
+ middle->prepare(middle, varray->output_prim, opt, &varray->driver_fetch_max );
+
+ /* check that the max is even */
+ assert((varray->driver_fetch_max & 1) == 0);
+
+ varray->fetch_max = MIN2(FETCH_MAX, varray->driver_fetch_max);
+}
+
+
+
+
+static void varray_finish(struct draw_pt_front_end *frontend)
+{
+ struct varray_frontend *varray = (struct varray_frontend *)frontend;
+ varray->middle->finish(varray->middle);
+ varray->middle = NULL;
+}
+
+static void varray_destroy(struct draw_pt_front_end *frontend)
+{
+ FREE(frontend);
+}
+
+
+struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw)
+{
+ ushort i;
+ struct varray_frontend *varray = CALLOC_STRUCT(varray_frontend);
+ if (varray == NULL)
+ return NULL;
+
+ varray->base.prepare = varray_prepare;
+ varray->base.run = NULL;
+ varray->base.finish = varray_finish;
+ varray->base.destroy = varray_destroy;
+ varray->draw = draw;
+
+ for (i = 0; i < DRAW_MAX; i++) {
+ varray->draw_elts[i] = i;
+ }
+
+ return &varray->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h
new file mode 100644
index 0000000000..7c722457c3
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h
@@ -0,0 +1,238 @@
+
+static void FUNC(struct draw_pt_front_end *frontend,
+ pt_elt_func get_elt,
+ const void *elts,
+ unsigned count)
+{
+ struct varray_frontend *varray = (struct varray_frontend *)frontend;
+ struct draw_context *draw = varray->draw;
+ unsigned start = (unsigned)elts;
+
+ boolean flatfirst = (draw->rasterizer->flatshade &&
+ draw->rasterizer->flatshade_first);
+ unsigned i, j;
+ ushort flags;
+ unsigned first, incr;
+
+ varray->fetch_start = start;
+
+ draw_pt_split_prim(varray->input_prim, &first, &incr);
+
+#if 0
+ debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
+ varray->input_prim,
+ start, count);
+#endif
+
+ switch (varray->input_prim) {
+ case PIPE_PRIM_POINTS:
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i < end; i++) {
+ POINT(varray, i + 0);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+1 < end; i += 2) {
+ LINE(varray, DRAW_PIPE_RESET_STIPPLE,
+ i + 0, i + 1);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ if (count >= 2) {
+ flags = DRAW_PIPE_RESET_STIPPLE;
+
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 1; i < end; i++, flags = 0) {
+ LINE(varray, flags, i - 1, i);
+ }
+ LINE(varray, flags, i - 1, 0);
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ flags = DRAW_PIPE_RESET_STIPPLE;
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 1; i < end; i++, flags = 0) {
+ LINE(varray, flags, i - 1, i);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i += 3) {
+ TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ i + 0, i + 1, i + 2);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ if (flatfirst) {
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i++) {
+ TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ i + 0, i + 1 + (i&1), i + 2 - (i&1));
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ if (j + first + i <= count) {
+ varray->fetch_start -= 2;
+ i -= 2;
+ }
+ }
+ }
+ else {
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i + 2 < end; i++) {
+ TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ i + 0 + (i&1), i + 1 - (i&1), i + 2);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ if (j + first + i <= count) {
+ varray->fetch_start -= 2;
+ i -= 2;
+ }
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (count >= 3) {
+ if (flatfirst) {
+ flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i++) {
+ TRIANGLE(varray, flags, i + 1, i + 2, 0);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ }
+ else {
+ flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i++) {
+ TRIANGLE(varray, flags, 0, i + 1, i + 2);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUADS:
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+3 < end; i += 4) {
+ QUAD(varray, i + 0, i + 1, i + 2, i + 3);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+3 < end; i += 2) {
+ QUAD(varray, i + 2, i + 0, i + 1, i + 3);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ if (j + first + i <= count) {
+ varray->fetch_start -= 2;
+ i -= 2;
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ {
+ /* These bitflags look a little odd because we submit the
+ * vertices as (1,2,0) to satisfy flatshade requirements.
+ */
+ const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2;
+ const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0;
+ const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1;
+
+ flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
+ for (j = 0; j + first <= count; j += i) {
+ unsigned end = MIN2(FETCH_MAX, count - j);
+ end -= (end % incr);
+ for (i = 0; i+2 < end; i++, flags = edge_middle) {
+
+ if (i + 3 == count)
+ flags |= edge_last;
+
+ TRIANGLE(varray, flags, i + 1, i + 2, 0);
+ }
+ i = end;
+ fetch_init(varray, end);
+ varray_flush(varray);
+ }
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ varray_flush(varray);
+}
+
+#undef TRIANGLE
+#undef QUAD
+#undef POINT
+#undef LINE
+#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
new file mode 100644
index 0000000000..010c7a18a7
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
@@ -0,0 +1,91 @@
+static unsigned trim( unsigned count, unsigned first, unsigned incr )
+{
+ return count - (count - first) % incr;
+}
+
+static void FUNC(struct draw_pt_front_end *frontend,
+ pt_elt_func get_elt,
+ const void *elts,
+ unsigned count)
+{
+ struct varray_frontend *varray = (struct varray_frontend *)frontend;
+ unsigned start = (unsigned) ((char *) elts - (char *) NULL);
+
+ unsigned j;
+ unsigned first, incr;
+
+ draw_pt_split_prim(varray->input_prim, &first, &incr);
+
+ /* Sanitize primitive length:
+ */
+ count = trim(count, first, incr);
+ if (count < first)
+ return;
+
+#if 0
+ debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
+ varray->input_prim,
+ start, count);
+#endif
+
+ switch (varray->input_prim) {
+ case PIPE_PRIM_POINTS:
+ case PIPE_PRIM_LINES:
+ case PIPE_PRIM_TRIANGLES:
+ case PIPE_PRIM_LINE_STRIP:
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ case PIPE_PRIM_QUADS:
+ case PIPE_PRIM_QUAD_STRIP:
+ for (j = 0; j < count;) {
+ unsigned remaining = count - j;
+ unsigned nr = trim( MIN2(varray->driver_fetch_max, remaining), first, incr );
+ varray_flush_linear(varray, start + j, nr);
+ j += nr;
+ if (nr != remaining)
+ j -= (first - incr);
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ /* Always have to decompose as we've stated that this will be
+ * emitted as a line-strip.
+ */
+ for (j = 0; j < count;) {
+ unsigned remaining = count - j;
+ unsigned nr = trim( MIN2(varray->fetch_max-1, remaining), first, incr );
+ varray_line_loop_segment(varray, start, j, nr, nr == remaining);
+ j += nr;
+ if (nr != remaining)
+ j -= (first - incr);
+ }
+ break;
+
+
+ case PIPE_PRIM_POLYGON:
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (count < varray->driver_fetch_max) {
+ varray_flush_linear(varray, start, count);
+ }
+ else {
+ for ( j = 0; j < count;) {
+ unsigned remaining = count - j;
+ unsigned nr = trim( MIN2(varray->fetch_max-1, remaining), first, incr );
+ varray_fan_segment(varray, start, j, nr);
+ j += nr;
+ if (nr != remaining)
+ j -= (first - incr);
+ }
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+}
+
+#undef TRIANGLE
+#undef QUAD
+#undef POINT
+#undef LINE
+#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
new file mode 100644
index 0000000000..1a0527be63
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c
@@ -0,0 +1,516 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_memory.h"
+#include "util/u_prim.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pt.h"
+
+
+#define CACHE_MAX 256
+#define FETCH_MAX 256
+#define DRAW_MAX (16*1024)
+
+struct vcache_frontend {
+ struct draw_pt_front_end base;
+ struct draw_context *draw;
+
+ unsigned in[CACHE_MAX];
+ ushort out[CACHE_MAX];
+
+ ushort draw_elts[DRAW_MAX];
+ unsigned fetch_elts[FETCH_MAX];
+
+ unsigned draw_count;
+ unsigned fetch_count;
+ unsigned fetch_max;
+
+ struct draw_pt_middle_end *middle;
+
+ unsigned input_prim;
+ unsigned output_prim;
+
+ unsigned middle_prim;
+ unsigned opt;
+};
+
+static INLINE void
+vcache_flush( struct vcache_frontend *vcache )
+{
+ if (vcache->middle_prim != vcache->output_prim) {
+ vcache->middle_prim = vcache->output_prim;
+ vcache->middle->prepare( vcache->middle,
+ vcache->middle_prim,
+ vcache->opt,
+ &vcache->fetch_max );
+ }
+
+ if (vcache->draw_count) {
+ vcache->middle->run( vcache->middle,
+ vcache->fetch_elts,
+ vcache->fetch_count,
+ vcache->draw_elts,
+ vcache->draw_count );
+ }
+
+ memset(vcache->in, ~0, sizeof(vcache->in));
+ vcache->fetch_count = 0;
+ vcache->draw_count = 0;
+}
+
+static INLINE void
+vcache_check_flush( struct vcache_frontend *vcache )
+{
+ if ( vcache->draw_count + 6 >= DRAW_MAX ||
+ vcache->fetch_count + 4 >= FETCH_MAX )
+ {
+ vcache_flush( vcache );
+ }
+}
+
+
+static INLINE void
+vcache_elt( struct vcache_frontend *vcache,
+ unsigned felt,
+ ushort flags )
+{
+ unsigned idx = felt % CACHE_MAX;
+
+ if (vcache->in[idx] != felt) {
+ assert(vcache->fetch_count < FETCH_MAX);
+
+ vcache->in[idx] = felt;
+ vcache->out[idx] = (ushort)vcache->fetch_count;
+ vcache->fetch_elts[vcache->fetch_count++] = felt;
+ }
+
+ vcache->draw_elts[vcache->draw_count++] = vcache->out[idx] | flags;
+}
+
+
+
+static INLINE void
+vcache_triangle( struct vcache_frontend *vcache,
+ unsigned i0,
+ unsigned i1,
+ unsigned i2 )
+{
+ vcache_elt(vcache, i0, 0);
+ vcache_elt(vcache, i1, 0);
+ vcache_elt(vcache, i2, 0);
+ vcache_check_flush(vcache);
+}
+
+
+static INLINE void
+vcache_triangle_flags( struct vcache_frontend *vcache,
+ ushort flags,
+ unsigned i0,
+ unsigned i1,
+ unsigned i2 )
+{
+ vcache_elt(vcache, i0, flags);
+ vcache_elt(vcache, i1, 0);
+ vcache_elt(vcache, i2, 0);
+ vcache_check_flush(vcache);
+}
+
+static INLINE void
+vcache_line( struct vcache_frontend *vcache,
+ unsigned i0,
+ unsigned i1 )
+{
+ vcache_elt(vcache, i0, 0);
+ vcache_elt(vcache, i1, 0);
+ vcache_check_flush(vcache);
+}
+
+
+static INLINE void
+vcache_line_flags( struct vcache_frontend *vcache,
+ ushort flags,
+ unsigned i0,
+ unsigned i1 )
+{
+ vcache_elt(vcache, i0, flags);
+ vcache_elt(vcache, i1, 0);
+ vcache_check_flush(vcache);
+}
+
+
+static INLINE void
+vcache_point( struct vcache_frontend *vcache,
+ unsigned i0 )
+{
+ vcache_elt(vcache, i0, 0);
+ vcache_check_flush(vcache);
+}
+
+static INLINE void
+vcache_quad( struct vcache_frontend *vcache,
+ unsigned i0,
+ unsigned i1,
+ unsigned i2,
+ unsigned i3 )
+{
+ vcache_triangle( vcache, i0, i1, i3 );
+ vcache_triangle( vcache, i1, i2, i3 );
+}
+
+static INLINE void
+vcache_ef_quad( struct vcache_frontend *vcache,
+ unsigned i0,
+ unsigned i1,
+ unsigned i2,
+ unsigned i3 )
+{
+ if (vcache->draw->rasterizer->flatshade_first) {
+ vcache_triangle_flags( vcache,
+ ( DRAW_PIPE_RESET_STIPPLE |
+ DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_1 ),
+ i0, i1, i2 );
+
+ vcache_triangle_flags( vcache,
+ ( DRAW_PIPE_EDGE_FLAG_2 |
+ DRAW_PIPE_EDGE_FLAG_1 ),
+ i0, i2, i3 );
+ }
+ else {
+ vcache_triangle_flags( vcache,
+ ( DRAW_PIPE_RESET_STIPPLE |
+ DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_2 ),
+ i0, i1, i3 );
+
+ vcache_triangle_flags( vcache,
+ ( DRAW_PIPE_EDGE_FLAG_0 |
+ DRAW_PIPE_EDGE_FLAG_1 ),
+ i1, i2, i3 );
+ }
+}
+
+/* At least for now, we're back to using a template include file for
+ * this. The two paths aren't too different though - it may be
+ * possible to reunify them.
+ */
+#define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
+#define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
+#define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
+#define POINT(vc,i0) vcache_point(vc,i0)
+#define FUNC vcache_run_extras
+#include "draw_pt_vcache_tmp.h"
+
+#define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
+#define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
+#define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
+#define POINT(vc,i0) vcache_point(vc,i0)
+#define FUNC vcache_run
+#include "draw_pt_vcache_tmp.h"
+
+static INLINE void
+rebase_uint_elts( const unsigned *src,
+ unsigned count,
+ int delta,
+ ushort *dest )
+{
+ unsigned i;
+
+ for (i = 0; i < count; i++)
+ dest[i] = (ushort)(src[i] + delta);
+}
+
+static INLINE void
+rebase_ushort_elts( const ushort *src,
+ unsigned count,
+ int delta,
+ ushort *dest )
+{
+ unsigned i;
+
+ for (i = 0; i < count; i++)
+ dest[i] = (ushort)(src[i] + delta);
+}
+
+static INLINE void
+rebase_ubyte_elts( const ubyte *src,
+ unsigned count,
+ int delta,
+ ushort *dest )
+{
+ unsigned i;
+
+ for (i = 0; i < count; i++)
+ dest[i] = (ushort)(src[i] + delta);
+}
+
+
+
+static INLINE void
+translate_uint_elts( const unsigned *src,
+ unsigned count,
+ ushort *dest )
+{
+ unsigned i;
+
+ for (i = 0; i < count; i++)
+ dest[i] = (ushort)(src[i]);
+}
+
+static INLINE void
+translate_ushort_elts( const ushort *src,
+ unsigned count,
+ ushort *dest )
+{
+ unsigned i;
+
+ for (i = 0; i < count; i++)
+ dest[i] = (ushort)(src[i]);
+}
+
+static INLINE void
+translate_ubyte_elts( const ubyte *src,
+ unsigned count,
+ ushort *dest )
+{
+ unsigned i;
+
+ for (i = 0; i < count; i++)
+ dest[i] = (ushort)(src[i]);
+}
+
+
+
+
+#if 0
+static INLINE enum pipe_format
+format_from_get_elt( pt_elt_func get_elt )
+{
+ switch (draw->pt.user.eltSize) {
+ case 1: return PIPE_FORMAT_R8_UNORM;
+ case 2: return PIPE_FORMAT_R16_UNORM;
+ case 4: return PIPE_FORMAT_R32_UNORM;
+ default: return PIPE_FORMAT_NONE;
+ }
+}
+#endif
+
+static INLINE void
+vcache_check_run( struct draw_pt_front_end *frontend,
+ pt_elt_func get_elt,
+ const void *elts,
+ unsigned draw_count )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+ struct draw_context *draw = vcache->draw;
+ unsigned min_index = draw->pt.user.min_index;
+ unsigned max_index = draw->pt.user.max_index;
+ unsigned index_size = draw->pt.user.eltSize;
+ unsigned fetch_count = max_index + 1 - min_index;
+ const ushort *transformed_elts;
+ ushort *storage = NULL;
+ boolean ok = FALSE;
+
+
+ if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count,
+ vcache->fetch_max,
+ draw_count);
+
+ if (max_index == 0xffffffff ||
+ fetch_count > draw_count) {
+ if (0) debug_printf("fail\n");
+ goto fail;
+ }
+
+ if (vcache->middle_prim != vcache->input_prim) {
+ vcache->middle_prim = vcache->input_prim;
+ vcache->middle->prepare( vcache->middle,
+ vcache->middle_prim,
+ vcache->opt,
+ &vcache->fetch_max );
+ }
+
+
+ if (min_index == 0 &&
+ index_size == 2)
+ {
+ transformed_elts = (const ushort *)elts;
+ }
+ else
+ {
+ storage = MALLOC( draw_count * sizeof(ushort) );
+ if (!storage)
+ goto fail;
+
+ if (min_index == 0) {
+ switch(index_size) {
+ case 1:
+ translate_ubyte_elts( (const ubyte *)elts,
+ draw_count,
+ storage );
+ break;
+
+ case 2:
+ translate_ushort_elts( (const ushort *)elts,
+ draw_count,
+ storage );
+ break;
+
+ case 4:
+ translate_uint_elts( (const uint *)elts,
+ draw_count,
+ storage );
+ break;
+
+ default:
+ assert(0);
+ return;
+ }
+ }
+ else {
+ switch(index_size) {
+ case 1:
+ rebase_ubyte_elts( (const ubyte *)elts,
+ draw_count,
+ 0 - (int)min_index,
+ storage );
+ break;
+
+ case 2:
+ rebase_ushort_elts( (const ushort *)elts,
+ draw_count,
+ 0 - (int)min_index,
+ storage );
+ break;
+
+ case 4:
+ rebase_uint_elts( (const uint *)elts,
+ draw_count,
+ 0 - (int)min_index,
+ storage );
+ break;
+
+ default:
+ assert(0);
+ return;
+ }
+ }
+ transformed_elts = storage;
+ }
+
+ if (fetch_count < UNDEFINED_VERTEX_ID)
+ ok = vcache->middle->run_linear_elts( vcache->middle,
+ min_index, /* start */
+ fetch_count,
+ transformed_elts,
+ draw_count );
+
+ FREE(storage);
+
+ if (ok)
+ return;
+
+ debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
+ fetch_count, draw_count);
+
+ fail:
+ vcache_run( frontend, get_elt, elts, draw_count );
+}
+
+
+
+
+static void
+vcache_prepare( struct draw_pt_front_end *frontend,
+ unsigned prim,
+ struct draw_pt_middle_end *middle,
+ unsigned opt )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+
+ if (opt & PT_PIPELINE)
+ {
+ vcache->base.run = vcache_run_extras;
+ }
+ else
+ {
+ vcache->base.run = vcache_check_run;
+ }
+
+ vcache->input_prim = prim;
+ vcache->output_prim = u_reduced_prim(prim);
+
+ vcache->middle = middle;
+ vcache->opt = opt;
+
+ /* Have to run prepare here, but try and guess a good prim for
+ * doing so:
+ */
+ vcache->middle_prim = (opt & PT_PIPELINE) ? vcache->output_prim : vcache->input_prim;
+ middle->prepare( middle, vcache->middle_prim, opt, &vcache->fetch_max );
+}
+
+
+
+
+static void
+vcache_finish( struct draw_pt_front_end *frontend )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+ vcache->middle->finish( vcache->middle );
+ vcache->middle = NULL;
+}
+
+static void
+vcache_destroy( struct draw_pt_front_end *frontend )
+{
+ FREE(frontend);
+}
+
+
+struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw )
+{
+ struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
+ if (vcache == NULL)
+ return NULL;
+
+ vcache->base.prepare = vcache_prepare;
+ vcache->base.run = NULL;
+ vcache->base.finish = vcache_finish;
+ vcache->base.destroy = vcache_destroy;
+ vcache->draw = draw;
+
+ memset(vcache->in, ~0, sizeof(vcache->in));
+
+ return &vcache->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h
new file mode 100644
index 0000000000..62822a3d56
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h
@@ -0,0 +1,214 @@
+
+
+static void FUNC( struct draw_pt_front_end *frontend,
+ pt_elt_func get_elt,
+ const void *elts,
+ unsigned count )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+ struct draw_context *draw = vcache->draw;
+
+ boolean flatfirst = (draw->rasterizer->flatshade &&
+ draw->rasterizer->flatshade_first);
+ unsigned i;
+ ushort flags;
+
+ if (0) debug_printf("%s %d\n", __FUNCTION__, count);
+
+
+ switch (vcache->input_prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < count; i ++) {
+ POINT( vcache,
+ get_elt(elts, i + 0) );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 0; i+1 < count; i += 2) {
+ LINE( vcache,
+ DRAW_PIPE_RESET_STIPPLE,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1));
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ if (count >= 2) {
+ flags = DRAW_PIPE_RESET_STIPPLE;
+
+ for (i = 1; i < count; i++, flags = 0) {
+ LINE( vcache,
+ flags,
+ get_elt(elts, i - 1),
+ get_elt(elts, i ));
+ }
+
+ LINE( vcache,
+ flags,
+ get_elt(elts, i - 1),
+ get_elt(elts, 0 ));
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ flags = DRAW_PIPE_RESET_STIPPLE;
+ for (i = 1; i < count; i++, flags = 0) {
+ LINE( vcache,
+ flags,
+ get_elt(elts, i - 1),
+ get_elt(elts, i ));
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i+2 < count; i += 3) {
+ TRIANGLE( vcache,
+ DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2 ));
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( vcache,
+ DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1 + (i&1)),
+ get_elt(elts, i + 2 - (i&1)));
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( vcache,
+ DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ get_elt(elts, i + 0 + (i&1)),
+ get_elt(elts, i + 1 - (i&1)),
+ get_elt(elts, i + 2 ));
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (count >= 3) {
+ if (flatfirst) {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( vcache,
+ DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2),
+ get_elt(elts, 0 ));
+ }
+ }
+ else {
+ for (i = 0; i+2 < count; i++) {
+ TRIANGLE( vcache,
+ DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
+ get_elt(elts, 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2 ));
+ }
+ }
+ }
+ break;
+
+
+ case PIPE_PRIM_QUADS:
+ for (i = 0; i+3 < count; i += 4) {
+ if (flatfirst) {
+ QUAD( vcache,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2),
+ get_elt(elts, i + 3) );
+ }
+ else {
+ QUAD( vcache,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2),
+ get_elt(elts, i + 3) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = 0; i+3 < count; i += 2) {
+ if (flatfirst) {
+ QUAD( vcache,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 3),
+ get_elt(elts, i + 2) );
+ }
+ else {
+ QUAD( vcache,
+ get_elt(elts, i + 2),
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 3) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ {
+ /* These bitflags look a little odd because we submit the
+ * vertices as (1,2,0) to satisfy flatshade requirements.
+ */
+ const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2;
+ const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0;
+ const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1;
+ ushort edge_next, edge_finish;
+
+ if (flatfirst) {
+ flags = DRAW_PIPE_RESET_STIPPLE | edge_middle | edge_last;
+ edge_next = edge_last;
+ edge_finish = edge_first;
+ }
+ else {
+ flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
+ edge_next = edge_middle;
+ edge_finish = edge_last;
+ }
+
+ for (i = 0; i+2 < count; i++, flags = edge_next) {
+
+ if (i + 3 == count)
+ flags |= edge_finish;
+
+ if (flatfirst) {
+ TRIANGLE( vcache,
+ flags,
+ get_elt(elts, 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2) );
+ }
+ else {
+ TRIANGLE( vcache,
+ flags,
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2),
+ get_elt(elts, 0));
+ }
+ }
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ vcache_flush( vcache );
+}
+
+
+#undef TRIANGLE
+#undef QUAD
+#undef POINT
+#undef LINE
+#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_vbuf.h b/src/gallium/auxiliary/draw/draw_vbuf.h
new file mode 100644
index 0000000000..cccd3bf435
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vbuf.h
@@ -0,0 +1,129 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Vertex buffer drawing stage.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Jose Fonseca <jrfonsec@tungstengraphics.com>
+ */
+
+#ifndef DRAW_VBUF_H_
+#define DRAW_VBUF_H_
+
+
+#include "pipe/p_compiler.h"
+
+
+struct pipe_rasterizer_state;
+struct draw_context;
+struct vertex_info;
+
+
+/**
+ * Interface for hardware vertex buffer rendering.
+ */
+struct vbuf_render {
+
+ /**
+ * Driver limits. May be tuned lower to improve cache hits on
+ * index list.
+ */
+ unsigned max_indices;
+ unsigned max_vertex_buffer_bytes;
+
+ /**
+ * Query if the hardware driver needs assistance for a particular
+ * combination of rasterizer state and primitive.
+ *
+ * Currently optional.
+ */
+ boolean (*need_pipeline)(const struct vbuf_render *render,
+ const struct pipe_rasterizer_state *rasterizer,
+ unsigned int prim );
+
+
+ /**
+ * Get the hardware vertex format.
+ *
+ * XXX: have this in draw_context instead?
+ */
+ const struct vertex_info *(*get_vertex_info)( struct vbuf_render * );
+
+ /**
+ * Request a destination for vertices.
+ * Hardware renderers will use ttm memory, others will just malloc
+ * something.
+ */
+ boolean (*allocate_vertices)( struct vbuf_render *,
+ ushort vertex_size,
+ ushort nr_vertices );
+
+ void *(*map_vertices)( struct vbuf_render * );
+ void (*unmap_vertices)( struct vbuf_render *,
+ ushort min_index,
+ ushort max_index );
+
+ /**
+ * Notify the renderer of the current primitive when it changes.
+ * Must succeed for TRIANGLES, LINES and POINTS. Other prims at
+ * the discretion of the driver, for the benefit of the passthrough
+ * path.
+ */
+ boolean (*set_primitive)( struct vbuf_render *, unsigned prim );
+
+ /**
+ * DrawElements, note indices are ushort. The driver must complete
+ * this call, if necessary splitting the index list itself.
+ */
+ void (*draw)( struct vbuf_render *,
+ const ushort *indices,
+ uint nr_indices );
+
+ /* Draw Arrays path too.
+ */
+ void (*draw_arrays)( struct vbuf_render *,
+ unsigned start,
+ uint nr );
+
+ /**
+ * Called when vbuf is done with this set of vertices:
+ */
+ void (*release_vertices)( struct vbuf_render * );
+
+ void (*destroy)( struct vbuf_render * );
+};
+
+
+
+struct draw_stage *
+draw_vbuf_stage( struct draw_context *draw,
+ struct vbuf_render *render );
+
+
+#endif /*DRAW_VBUF_H_*/
diff --git a/src/gallium/auxiliary/draw/draw_vertex.c b/src/gallium/auxiliary/draw/draw_vertex.c
new file mode 100644
index 0000000000..3214213e44
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vertex.c
@@ -0,0 +1,129 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Functions for specifying the post-transformation vertex layout.
+ *
+ * Author:
+ * Brian Paul
+ * Keith Whitwell
+ */
+
+
+#include "draw/draw_private.h"
+#include "draw/draw_vertex.h"
+
+
+/**
+ * Compute the size of a vertex, in dwords/floats, to update the
+ * vinfo->size field.
+ */
+void
+draw_compute_vertex_size(struct vertex_info *vinfo)
+{
+ uint i;
+
+ vinfo->size = 0;
+ for (i = 0; i < vinfo->num_attribs; i++) {
+ switch (vinfo->attrib[i].emit) {
+ case EMIT_OMIT:
+ break;
+ case EMIT_4UB:
+ /* fall-through */
+ case EMIT_1F_PSIZE:
+ /* fall-through */
+ case EMIT_1F:
+ vinfo->size += 1;
+ break;
+ case EMIT_2F:
+ vinfo->size += 2;
+ break;
+ case EMIT_3F:
+ vinfo->size += 3;
+ break;
+ case EMIT_4F:
+ vinfo->size += 4;
+ break;
+ default:
+ assert(0);
+ }
+ }
+}
+
+
+void
+draw_dump_emitted_vertex(const struct vertex_info *vinfo, const uint8_t *data)
+{
+ unsigned i, j;
+
+ for (i = 0; i < vinfo->num_attribs; i++) {
+ j = vinfo->attrib[i].src_index;
+ switch (vinfo->attrib[i].emit) {
+ case EMIT_OMIT:
+ debug_printf("EMIT_OMIT:");
+ break;
+ case EMIT_1F:
+ debug_printf("EMIT_1F:\t");
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ break;
+ case EMIT_1F_PSIZE:
+ debug_printf("EMIT_1F_PSIZE:\t");
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ break;
+ case EMIT_2F:
+ debug_printf("EMIT_2F:\t");
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ break;
+ case EMIT_3F:
+ debug_printf("EMIT_3F:\t");
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ data += sizeof(float);
+ break;
+ case EMIT_4F:
+ debug_printf("EMIT_4F:\t");
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ debug_printf("%f ", *(float *)data); data += sizeof(float);
+ break;
+ case EMIT_4UB:
+ debug_printf("EMIT_4UB:\t");
+ debug_printf("%u ", *data++);
+ debug_printf("%u ", *data++);
+ debug_printf("%u ", *data++);
+ debug_printf("%u ", *data++);
+ break;
+ default:
+ assert(0);
+ }
+ debug_printf("\n");
+ }
+ debug_printf("\n");
+}
diff --git a/src/gallium/auxiliary/draw/draw_vertex.h b/src/gallium/auxiliary/draw/draw_vertex.h
new file mode 100644
index 0000000000..554f4ac3c1
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vertex.h
@@ -0,0 +1,162 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Post-transform vertex format info. The vertex_info struct is used by
+ * the draw_vbuf code to emit hardware-specific vertex layouts into hw
+ * vertex buffers.
+ *
+ * Author:
+ * Brian Paul
+ */
+
+
+#ifndef DRAW_VERTEX_H
+#define DRAW_VERTEX_H
+
+
+#include "pipe/p_state.h"
+
+
+/**
+ * Vertex attribute emit modes
+ */
+enum attrib_emit {
+ EMIT_OMIT, /**< don't emit the attribute */
+ EMIT_1F,
+ EMIT_1F_PSIZE, /**< insert constant point size */
+ EMIT_2F,
+ EMIT_3F,
+ EMIT_4F,
+ EMIT_4UB /**< XXX may need variations for RGBA vs BGRA, etc */
+};
+
+
+/**
+ * Attribute interpolation mode
+ */
+enum interp_mode {
+ INTERP_NONE, /**< never interpolate vertex header info */
+ INTERP_POS, /**< special case for frag position */
+ INTERP_CONSTANT,
+ INTERP_LINEAR,
+ INTERP_PERSPECTIVE
+};
+
+
+/**
+ * Information about hardware/rasterization vertex layout.
+ */
+struct vertex_info
+{
+ uint num_attribs;
+ uint hwfmt[4]; /**< hardware format info for this format */
+ uint size; /**< total vertex size in dwords */
+
+ /* Keep this small and at the end of the struct to allow quick
+ * memcmp() comparisons.
+ */
+ struct {
+ unsigned interp_mode:4; /**< INTERP_x */
+ unsigned emit:4; /**< EMIT_x */
+ unsigned src_index:8; /**< map to post-xform attribs */
+ } attrib[PIPE_MAX_SHADER_INPUTS];
+};
+
+static INLINE size_t
+draw_vinfo_size( const struct vertex_info *a )
+{
+ return offsetof(const struct vertex_info, attrib[a->num_attribs]);
+}
+
+static INLINE int
+draw_vinfo_compare( const struct vertex_info *a,
+ const struct vertex_info *b )
+{
+ size_t sizea = draw_vinfo_size( a );
+ return memcmp( a, b, sizea );
+}
+
+static INLINE void
+draw_vinfo_copy( struct vertex_info *dst,
+ const struct vertex_info *src )
+{
+ size_t size = draw_vinfo_size( src );
+ memcpy( dst, src, size );
+}
+
+
+
+/**
+ * Add another attribute to the given vertex_info object.
+ * \param src_index indicates which post-transformed vertex attrib slot
+ * corresponds to this attribute.
+ * \return slot in which the attribute was added
+ */
+static INLINE uint
+draw_emit_vertex_attr(struct vertex_info *vinfo,
+ enum attrib_emit emit,
+ enum interp_mode interp, /* only used by softpipe??? */
+ uint src_index)
+{
+ const uint n = vinfo->num_attribs;
+ assert(n < PIPE_MAX_SHADER_INPUTS);
+ vinfo->attrib[n].emit = emit;
+ vinfo->attrib[n].interp_mode = interp;
+ vinfo->attrib[n].src_index = src_index;
+ vinfo->num_attribs++;
+ return n;
+}
+
+
+extern void draw_compute_vertex_size(struct vertex_info *vinfo);
+
+void draw_dump_emitted_vertex(const struct vertex_info *vinfo,
+ const uint8_t *data);
+
+
+static INLINE unsigned draw_translate_vinfo_format(unsigned format )
+{
+ switch (format) {
+ case EMIT_1F:
+ case EMIT_1F_PSIZE:
+ return PIPE_FORMAT_R32_FLOAT;
+ case EMIT_2F:
+ return PIPE_FORMAT_R32G32_FLOAT;
+ case EMIT_3F:
+ return PIPE_FORMAT_R32G32B32_FLOAT;
+ case EMIT_4F:
+ return PIPE_FORMAT_R32G32B32A32_FLOAT;
+ case EMIT_4UB:
+ return PIPE_FORMAT_R8G8B8A8_UNORM;
+ default:
+ return PIPE_FORMAT_NONE;
+ }
+}
+
+
+#endif /* DRAW_VERTEX_H */
diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c
new file mode 100644
index 0000000000..790e89ed82
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs.c
@@ -0,0 +1,254 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "pipe/p_shader_tokens.h"
+
+#include "draw_private.h"
+#include "draw_context.h"
+#include "draw_vs.h"
+
+#include "translate/translate.h"
+#include "translate/translate_cache.h"
+
+#include "tgsi/tgsi_exec.h"
+
+
+
+
+void draw_vs_set_constants( struct draw_context *draw,
+ const float (*constants)[4],
+ unsigned size )
+{
+ if (((uintptr_t)constants) & 0xf) {
+ if (size > draw->vs.const_storage_size) {
+ if (draw->vs.aligned_constant_storage)
+ align_free((void *)draw->vs.aligned_constant_storage);
+ draw->vs.aligned_constant_storage = align_malloc( size, 16 );
+ }
+ memcpy( (void*)draw->vs.aligned_constant_storage,
+ constants,
+ size );
+ constants = draw->vs.aligned_constant_storage;
+ }
+
+ draw->vs.aligned_constants = constants;
+ draw_vs_aos_machine_constants( draw->vs.aos_machine, constants );
+}
+
+
+void draw_vs_set_viewport( struct draw_context *draw,
+ const struct pipe_viewport_state *viewport )
+{
+ draw_vs_aos_machine_viewport( draw->vs.aos_machine, viewport );
+}
+
+
+
+struct draw_vertex_shader *
+draw_create_vertex_shader(struct draw_context *draw,
+ const struct pipe_shader_state *shader)
+{
+ struct draw_vertex_shader *vs;
+
+ vs = draw_create_vs_llvm( draw, shader );
+ if (!vs) {
+ vs = draw_create_vs_sse( draw, shader );
+ if (!vs) {
+ vs = draw_create_vs_ppc( draw, shader );
+ if (!vs) {
+ vs = draw_create_vs_exec( draw, shader );
+ }
+ }
+ }
+
+ if (vs)
+ {
+ uint i;
+ for (i = 0; i < vs->info.num_outputs; i++) {
+ if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
+ vs->info.output_semantic_index[i] == 0)
+ vs->position_output = i;
+ }
+ }
+
+ assert(vs);
+ return vs;
+}
+
+
+void
+draw_bind_vertex_shader(struct draw_context *draw,
+ struct draw_vertex_shader *dvs)
+{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
+ if (dvs)
+ {
+ draw->vs.vertex_shader = dvs;
+ draw->vs.num_vs_outputs = dvs->info.num_outputs;
+ draw->vs.position_output = dvs->position_output;
+ dvs->prepare( dvs, draw );
+ }
+ else {
+ draw->vs.vertex_shader = NULL;
+ draw->vs.num_vs_outputs = 0;
+ }
+}
+
+
+void
+draw_delete_vertex_shader(struct draw_context *draw,
+ struct draw_vertex_shader *dvs)
+{
+ unsigned i;
+
+ for (i = 0; i < dvs->nr_varients; i++)
+ dvs->varient[i]->destroy( dvs->varient[i] );
+
+ dvs->nr_varients = 0;
+
+ dvs->delete( dvs );
+}
+
+
+
+boolean
+draw_vs_init( struct draw_context *draw )
+{
+ draw->vs.machine = tgsi_exec_machine_create();
+ if (!draw->vs.machine)
+ return FALSE;
+
+ draw->vs.emit_cache = translate_cache_create();
+ if (!draw->vs.emit_cache)
+ return FALSE;
+
+ draw->vs.fetch_cache = translate_cache_create();
+ if (!draw->vs.fetch_cache)
+ return FALSE;
+
+ draw->vs.aos_machine = draw_vs_aos_machine();
+#ifdef PIPE_ARCH_X86
+ if (!draw->vs.aos_machine)
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+void
+draw_vs_destroy( struct draw_context *draw )
+{
+ if (draw->vs.fetch_cache)
+ translate_cache_destroy(draw->vs.fetch_cache);
+
+ if (draw->vs.emit_cache)
+ translate_cache_destroy(draw->vs.emit_cache);
+
+ if (draw->vs.aos_machine)
+ draw_vs_aos_machine_destroy(draw->vs.aos_machine);
+
+ if (draw->vs.aligned_constant_storage)
+ align_free((void*)draw->vs.aligned_constant_storage);
+
+ tgsi_exec_machine_destroy(draw->vs.machine);
+}
+
+
+struct draw_vs_varient *
+draw_vs_lookup_varient( struct draw_vertex_shader *vs,
+ const struct draw_vs_varient_key *key )
+{
+ struct draw_vs_varient *varient;
+ unsigned i;
+
+ /* Lookup existing varient:
+ */
+ for (i = 0; i < vs->nr_varients; i++)
+ if (draw_vs_varient_key_compare(key, &vs->varient[i]->key) == 0)
+ return vs->varient[i];
+
+ /* Else have to create a new one:
+ */
+ varient = vs->create_varient( vs, key );
+ if (varient == NULL)
+ return NULL;
+
+ /* Add it to our list, could be smarter:
+ */
+ if (vs->nr_varients < Elements(vs->varient)) {
+ vs->varient[vs->nr_varients++] = varient;
+ }
+ else {
+ vs->last_varient++;
+ vs->last_varient %= Elements(vs->varient);
+ vs->varient[vs->last_varient]->destroy(vs->varient[vs->last_varient]);
+ vs->varient[vs->last_varient] = varient;
+ }
+
+ /* Done
+ */
+ return varient;
+}
+
+
+struct translate *
+draw_vs_get_fetch( struct draw_context *draw,
+ struct translate_key *key )
+{
+ if (!draw->vs.fetch ||
+ translate_key_compare(&draw->vs.fetch->key, key) != 0)
+ {
+ translate_key_sanitize(key);
+ draw->vs.fetch = translate_cache_find(draw->vs.fetch_cache, key);
+ }
+
+ return draw->vs.fetch;
+}
+
+struct translate *
+draw_vs_get_emit( struct draw_context *draw,
+ struct translate_key *key )
+{
+ if (!draw->vs.emit ||
+ translate_key_compare(&draw->vs.emit->key, key) != 0)
+ {
+ translate_key_sanitize(key);
+ draw->vs.emit = translate_cache_find(draw->vs.emit_cache, key);
+ }
+
+ return draw->vs.emit;
+}
diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
new file mode 100644
index 0000000000..89ae158751
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs.h
@@ -0,0 +1,224 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef DRAW_VS_H
+#define DRAW_VS_H
+
+#include "draw_context.h"
+#include "draw_private.h"
+
+
+struct draw_context;
+struct pipe_shader_state;
+
+struct draw_varient_input
+{
+ enum pipe_format format;
+ unsigned buffer;
+ unsigned offset;
+};
+
+struct draw_varient_output
+{
+ enum pipe_format format; /* output format */
+ unsigned vs_output:8; /* which vertex shader output is this? */
+ unsigned offset:24; /* offset into output vertex */
+};
+
+struct draw_varient_element {
+ struct draw_varient_input in;
+ struct draw_varient_output out;
+};
+
+struct draw_vs_varient_key {
+ unsigned output_stride;
+ unsigned nr_elements:8; /* max2(nr_inputs, nr_outputs) */
+ unsigned nr_inputs:8;
+ unsigned nr_outputs:8;
+ unsigned viewport:1;
+ unsigned clip:1;
+ unsigned const_vbuffers:5;
+ struct draw_varient_element element[PIPE_MAX_ATTRIBS];
+};
+
+struct draw_vs_varient;
+
+
+struct draw_vs_varient {
+ struct draw_vs_varient_key key;
+
+ struct draw_vertex_shader *vs;
+
+ void (*set_buffer)( struct draw_vs_varient *,
+ unsigned i,
+ const void *ptr,
+ unsigned stride );
+
+ void (PIPE_CDECL *run_linear)( struct draw_vs_varient *shader,
+ unsigned start,
+ unsigned count,
+ void *output_buffer );
+
+ void (PIPE_CDECL *run_elts)( struct draw_vs_varient *shader,
+ const unsigned *elts,
+ unsigned count,
+ void *output_buffer );
+
+ void (*destroy)( struct draw_vs_varient * );
+};
+
+
+/**
+ * Private version of the compiled vertex_shader
+ */
+struct draw_vertex_shader {
+ struct draw_context *draw;
+
+ /* This member will disappear shortly:
+ */
+ struct pipe_shader_state state;
+
+ struct tgsi_shader_info info;
+ unsigned position_output;
+
+ /* Extracted from shader:
+ */
+ const float (*immediates)[4];
+
+ /*
+ */
+ struct draw_vs_varient *varient[16];
+ unsigned nr_varients;
+ unsigned last_varient;
+ struct draw_vs_varient *(*create_varient)( struct draw_vertex_shader *shader,
+ const struct draw_vs_varient_key *key );
+
+
+ void (*prepare)( struct draw_vertex_shader *shader,
+ struct draw_context *draw );
+
+ /* Run the shader - this interface will get cleaned up in the
+ * future:
+ */
+ void (*run_linear)( struct draw_vertex_shader *shader,
+ const float (*input)[4],
+ float (*output)[4],
+ const float (*constants)[4],
+ unsigned count,
+ unsigned input_stride,
+ unsigned output_stride );
+
+
+ void (*delete)( struct draw_vertex_shader * );
+};
+
+
+struct draw_vs_varient *
+draw_vs_lookup_varient( struct draw_vertex_shader *base,
+ const struct draw_vs_varient_key *key );
+
+
+/********************************************************************************
+ * Internal functions:
+ */
+
+struct draw_vertex_shader *
+draw_create_vs_exec(struct draw_context *draw,
+ const struct pipe_shader_state *templ);
+
+struct draw_vertex_shader *
+draw_create_vs_sse(struct draw_context *draw,
+ const struct pipe_shader_state *templ);
+
+struct draw_vertex_shader *
+draw_create_vs_ppc(struct draw_context *draw,
+ const struct pipe_shader_state *templ);
+
+struct draw_vertex_shader *
+draw_create_vs_llvm(struct draw_context *draw,
+ const struct pipe_shader_state *templ);
+
+
+
+struct draw_vs_varient_key;
+struct draw_vertex_shader;
+
+struct draw_vs_varient *draw_vs_varient_aos_sse( struct draw_vertex_shader *vs,
+ const struct draw_vs_varient_key *key );
+
+
+
+/********************************************************************************
+ * Helpers for vs implementations that don't do their own fetch/emit varients.
+ * Means these can be shared between shaders.
+ */
+struct translate;
+struct translate_key;
+
+struct translate *draw_vs_get_fetch( struct draw_context *draw,
+ struct translate_key *key );
+
+
+struct translate *draw_vs_get_emit( struct draw_context *draw,
+ struct translate_key *key );
+
+struct draw_vs_varient *draw_vs_varient_generic( struct draw_vertex_shader *vs,
+ const struct draw_vs_varient_key *key );
+
+
+
+static INLINE int draw_vs_varient_keysize( const struct draw_vs_varient_key *key )
+{
+ return 2 * sizeof(int) + key->nr_elements * sizeof(struct draw_varient_element);
+}
+
+static INLINE int draw_vs_varient_key_compare( const struct draw_vs_varient_key *a,
+ const struct draw_vs_varient_key *b )
+{
+ int keysize = draw_vs_varient_keysize(a);
+ return memcmp(a, b, keysize);
+}
+
+
+struct aos_machine *draw_vs_aos_machine( void );
+void draw_vs_aos_machine_destroy( struct aos_machine *machine );
+
+void draw_vs_aos_machine_constants( struct aos_machine *machine,
+ const float (*constants)[4] );
+
+void draw_vs_aos_machine_viewport( struct aos_machine *machine,
+ const struct pipe_viewport_state *viewport );
+
+
+#define MAX_TGSI_VERTICES 4
+
+
+
+#endif
diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.c b/src/gallium/auxiliary/draw/draw_vs_aos.c
new file mode 100644
index 0000000000..62e04a65f3
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_aos.c
@@ -0,0 +1,2274 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/**
+ * Translate tgsi vertex programs to x86/x87/SSE/SSE2 machine code
+ * using the rtasm runtime assembler. Based on the old
+ * t_vb_arb_program_sse.c
+ */
+
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_debug.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_exec.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "draw_vs.h"
+#include "draw_vs_aos.h"
+
+#include "rtasm/rtasm_x86sse.h"
+
+#ifdef PIPE_ARCH_X86
+#define DISASSEM 0
+#define FAST_MATH 1
+
+static const char *files[] =
+{
+ "NULL",
+ "CONST",
+ "IN",
+ "OUT",
+ "TEMP",
+ "SAMP",
+ "ADDR",
+ "IMM",
+ "INTERNAL",
+};
+
+static INLINE boolean eq( struct x86_reg a,
+ struct x86_reg b )
+{
+ return (a.file == b.file &&
+ a.idx == b.idx &&
+ a.mod == b.mod &&
+ a.disp == b.disp);
+}
+
+struct x86_reg aos_get_x86( struct aos_compilation *cp,
+ unsigned which_reg, /* quick hack */
+ unsigned value )
+{
+ struct x86_reg reg;
+
+ if (which_reg == 0)
+ reg = cp->temp_EBP;
+ else
+ reg = cp->tmp_EAX;
+
+ if (cp->x86_reg[which_reg] != value) {
+ unsigned offset;
+
+ switch (value) {
+ case X86_IMMEDIATES:
+ assert(which_reg == 0);
+ offset = Offset(struct aos_machine, immediates);
+ break;
+ case X86_CONSTANTS:
+ assert(which_reg == 1);
+ offset = Offset(struct aos_machine, constants);
+ break;
+ case X86_BUFFERS:
+ assert(which_reg == 0);
+ offset = Offset(struct aos_machine, buffer);
+ break;
+ default:
+ assert(0);
+ offset = 0;
+ }
+
+
+ x86_mov(cp->func, reg,
+ x86_make_disp(cp->machine_EDX, offset));
+
+ cp->x86_reg[which_reg] = value;
+ }
+
+ return reg;
+}
+
+
+static struct x86_reg get_reg_ptr(struct aos_compilation *cp,
+ unsigned file,
+ unsigned idx )
+{
+ struct x86_reg ptr = cp->machine_EDX;
+
+ switch (file) {
+ case TGSI_FILE_INPUT:
+ assert(idx < MAX_INPUTS);
+ return x86_make_disp(ptr, Offset(struct aos_machine, input[idx]));
+
+ case TGSI_FILE_OUTPUT:
+ return x86_make_disp(ptr, Offset(struct aos_machine, output[idx]));
+
+ case TGSI_FILE_TEMPORARY:
+ assert(idx < MAX_TEMPS);
+ return x86_make_disp(ptr, Offset(struct aos_machine, temp[idx]));
+
+ case AOS_FILE_INTERNAL:
+ assert(idx < MAX_INTERNALS);
+ return x86_make_disp(ptr, Offset(struct aos_machine, internal[idx]));
+
+ case TGSI_FILE_IMMEDIATE:
+ assert(idx < MAX_IMMEDIATES); /* just a sanity check */
+ return x86_make_disp(aos_get_x86(cp, 0, X86_IMMEDIATES), idx * 4 * sizeof(float));
+
+ case TGSI_FILE_CONSTANT:
+ assert(idx < MAX_CONSTANTS); /* just a sanity check */
+ return x86_make_disp(aos_get_x86(cp, 1, X86_CONSTANTS), idx * 4 * sizeof(float));
+
+ default:
+ AOS_ERROR(cp, "unknown reg file");
+ return x86_make_reg(0,0);
+ }
+}
+
+
+
+#define X87_CW_EXCEPTION_INV_OP (1<<0)
+#define X87_CW_EXCEPTION_DENORM_OP (1<<1)
+#define X87_CW_EXCEPTION_ZERO_DIVIDE (1<<2)
+#define X87_CW_EXCEPTION_OVERFLOW (1<<3)
+#define X87_CW_EXCEPTION_UNDERFLOW (1<<4)
+#define X87_CW_EXCEPTION_PRECISION (1<<5)
+#define X87_CW_PRECISION_SINGLE (0<<8)
+#define X87_CW_PRECISION_RESERVED (1<<8)
+#define X87_CW_PRECISION_DOUBLE (2<<8)
+#define X87_CW_PRECISION_DOUBLE_EXT (3<<8)
+#define X87_CW_PRECISION_MASK (3<<8)
+#define X87_CW_ROUND_NEAREST (0<<10)
+#define X87_CW_ROUND_DOWN (1<<10)
+#define X87_CW_ROUND_UP (2<<10)
+#define X87_CW_ROUND_ZERO (3<<10)
+#define X87_CW_ROUND_MASK (3<<10)
+#define X87_CW_INFINITY (1<<12)
+
+
+
+
+static void spill( struct aos_compilation *cp, unsigned idx )
+{
+ if (!cp->xmm[idx].dirty ||
+ (cp->xmm[idx].file != TGSI_FILE_INPUT && /* inputs are fetched into xmm & set dirty */
+ cp->xmm[idx].file != TGSI_FILE_OUTPUT &&
+ cp->xmm[idx].file != TGSI_FILE_TEMPORARY)) {
+ AOS_ERROR(cp, "invalid spill");
+ return;
+ }
+ else {
+ struct x86_reg oldval = get_reg_ptr(cp,
+ cp->xmm[idx].file,
+ cp->xmm[idx].idx);
+
+ if (0) debug_printf("\nspill %s[%d]",
+ files[cp->xmm[idx].file],
+ cp->xmm[idx].idx);
+
+ assert(cp->xmm[idx].dirty);
+ sse_movaps(cp->func, oldval, x86_make_reg(file_XMM, idx));
+ cp->xmm[idx].dirty = 0;
+ }
+}
+
+
+void aos_spill_all( struct aos_compilation *cp )
+{
+ unsigned i;
+
+ for (i = 0; i < 8; i++) {
+ if (cp->xmm[i].dirty)
+ spill(cp, i);
+ aos_release_xmm_reg(cp, i);
+ }
+}
+
+
+static struct x86_reg get_xmm_writable( struct aos_compilation *cp,
+ struct x86_reg reg )
+{
+ if (reg.file != file_XMM ||
+ cp->xmm[reg.idx].file != TGSI_FILE_NULL)
+ {
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+ sse_movaps(cp->func, tmp, reg);
+ reg = tmp;
+ }
+
+ cp->xmm[reg.idx].last_used = cp->insn_counter;
+ return reg;
+}
+
+static struct x86_reg get_xmm( struct aos_compilation *cp,
+ struct x86_reg reg )
+{
+ if (reg.file != file_XMM)
+ {
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+ sse_movaps(cp->func, tmp, reg);
+ reg = tmp;
+ }
+
+ cp->xmm[reg.idx].last_used = cp->insn_counter;
+ return reg;
+}
+
+
+/* Allocate an empty xmm register, either as a temporary or later to
+ * "adopt" as a shader reg.
+ */
+struct x86_reg aos_get_xmm_reg( struct aos_compilation *cp )
+{
+ unsigned i;
+ unsigned oldest = 0;
+ boolean found = FALSE;
+
+ for (i = 0; i < 8; i++)
+ if (cp->xmm[i].last_used != cp->insn_counter &&
+ cp->xmm[i].file == TGSI_FILE_NULL) {
+ oldest = i;
+ found = TRUE;
+ }
+
+ if (!found) {
+ for (i = 0; i < 8; i++)
+ if (cp->xmm[i].last_used < cp->xmm[oldest].last_used)
+ oldest = i;
+ }
+
+ /* Need to write out the old value?
+ */
+ if (cp->xmm[oldest].dirty)
+ spill(cp, oldest);
+
+ assert(cp->xmm[oldest].last_used != cp->insn_counter);
+
+ cp->xmm[oldest].file = TGSI_FILE_NULL;
+ cp->xmm[oldest].idx = 0;
+ cp->xmm[oldest].dirty = 0;
+ cp->xmm[oldest].last_used = cp->insn_counter;
+ return x86_make_reg(file_XMM, oldest);
+}
+
+void aos_release_xmm_reg( struct aos_compilation *cp,
+ unsigned idx )
+{
+ cp->xmm[idx].file = TGSI_FILE_NULL;
+ cp->xmm[idx].idx = 0;
+ cp->xmm[idx].dirty = 0;
+ cp->xmm[idx].last_used = 0;
+}
+
+
+static void aos_soft_release_xmm( struct aos_compilation *cp,
+ struct x86_reg reg )
+{
+ if (reg.file == file_XMM) {
+ assert(cp->xmm[reg.idx].last_used == cp->insn_counter);
+ cp->xmm[reg.idx].last_used = cp->insn_counter - 1;
+ }
+}
+
+
+
+/* Mark an xmm reg as holding the current copy of a shader reg.
+ */
+void aos_adopt_xmm_reg( struct aos_compilation *cp,
+ struct x86_reg reg,
+ unsigned file,
+ unsigned idx,
+ unsigned dirty )
+{
+ unsigned i;
+
+ if (reg.file != file_XMM) {
+ assert(0);
+ return;
+ }
+
+
+ /* If any xmm reg thinks it holds this shader reg, break the
+ * illusion.
+ */
+ for (i = 0; i < 8; i++) {
+ if (cp->xmm[i].file == file &&
+ cp->xmm[i].idx == idx)
+ {
+ /* If an xmm reg is already holding this shader reg, take into account its
+ * dirty flag...
+ */
+ dirty |= cp->xmm[i].dirty;
+ aos_release_xmm_reg(cp, i);
+ }
+ }
+
+ cp->xmm[reg.idx].file = file;
+ cp->xmm[reg.idx].idx = idx;
+ cp->xmm[reg.idx].dirty = dirty;
+ cp->xmm[reg.idx].last_used = cp->insn_counter;
+}
+
+
+/* Return a pointer to the in-memory copy of the reg, making sure it is uptodate.
+ */
+static struct x86_reg aos_get_shader_reg_ptr( struct aos_compilation *cp,
+ unsigned file,
+ unsigned idx )
+{
+ unsigned i;
+
+ /* Ensure the in-memory copy of this reg is up-to-date
+ */
+ for (i = 0; i < 8; i++) {
+ if (cp->xmm[i].file == file &&
+ cp->xmm[i].idx == idx &&
+ cp->xmm[i].dirty) {
+ spill(cp, i);
+ }
+ }
+
+ return get_reg_ptr( cp, file, idx );
+}
+
+
+/* As above, but return a pointer. Note - this pointer may alias
+ * those returned by get_arg_ptr().
+ */
+static struct x86_reg get_dst_ptr( struct aos_compilation *cp,
+ const struct tgsi_full_dst_register *dst )
+{
+ unsigned file = dst->DstRegister.File;
+ unsigned idx = dst->DstRegister.Index;
+ unsigned i;
+
+
+ /* Ensure in-memory copy of this reg is up-to-date and invalidate
+ * any xmm copies.
+ */
+ for (i = 0; i < 8; i++) {
+ if (cp->xmm[i].file == file &&
+ cp->xmm[i].idx == idx)
+ {
+ if (cp->xmm[i].dirty)
+ spill(cp, i);
+
+ aos_release_xmm_reg(cp, i);
+ }
+ }
+
+ return get_reg_ptr( cp, file, idx );
+}
+
+
+
+
+
+/* Return an XMM reg if the argument is resident, otherwise return a
+ * base+offset pointer to the saved value.
+ */
+struct x86_reg aos_get_shader_reg( struct aos_compilation *cp,
+ unsigned file,
+ unsigned idx )
+{
+ unsigned i;
+
+ for (i = 0; i < 8; i++) {
+ if (cp->xmm[i].file == file &&
+ cp->xmm[i].idx == idx)
+ {
+ cp->xmm[i].last_used = cp->insn_counter;
+ return x86_make_reg(file_XMM, i);
+ }
+ }
+
+ /* If not found in the XMM register file, return an indirect
+ * reference to the in-memory copy:
+ */
+ return get_reg_ptr( cp, file, idx );
+}
+
+
+
+static struct x86_reg aos_get_shader_reg_xmm( struct aos_compilation *cp,
+ unsigned file,
+ unsigned idx )
+{
+ struct x86_reg reg = get_xmm( cp,
+ aos_get_shader_reg( cp, file, idx ) );
+
+ aos_adopt_xmm_reg( cp,
+ reg,
+ file,
+ idx,
+ FALSE );
+
+ return reg;
+}
+
+
+
+struct x86_reg aos_get_internal_xmm( struct aos_compilation *cp,
+ unsigned imm )
+{
+ return aos_get_shader_reg_xmm( cp, AOS_FILE_INTERNAL, imm );
+}
+
+
+struct x86_reg aos_get_internal( struct aos_compilation *cp,
+ unsigned imm )
+{
+ return aos_get_shader_reg( cp, AOS_FILE_INTERNAL, imm );
+}
+
+
+
+
+
+/* Emulate pshufd insn in regular SSE, if necessary:
+ */
+static void emit_pshufd( struct aos_compilation *cp,
+ struct x86_reg dst,
+ struct x86_reg arg0,
+ ubyte shuf )
+{
+ if (cp->have_sse2) {
+ sse2_pshufd(cp->func, dst, arg0, shuf);
+ }
+ else {
+ if (!eq(dst, arg0))
+ sse_movaps(cp->func, dst, arg0);
+
+ sse_shufps(cp->func, dst, dst, shuf);
+ }
+}
+
+/* load masks (pack into negs??)
+ * pshufd - shuffle according to writemask
+ * and - result, mask
+ * nand - dest, mask
+ * or - dest, result
+ */
+static boolean mask_write( struct aos_compilation *cp,
+ struct x86_reg dst,
+ struct x86_reg result,
+ unsigned mask )
+{
+ struct x86_reg imm_swz = aos_get_internal_xmm(cp, IMM_SWZ);
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+
+ emit_pshufd(cp, tmp, imm_swz,
+ SHUF((mask & 1) ? 2 : 3,
+ (mask & 2) ? 2 : 3,
+ (mask & 4) ? 2 : 3,
+ (mask & 8) ? 2 : 3));
+
+ sse_andps(cp->func, dst, tmp);
+ sse_andnps(cp->func, tmp, result);
+ sse_orps(cp->func, dst, tmp);
+
+ aos_release_xmm_reg(cp, tmp.idx);
+ return TRUE;
+}
+
+
+
+
+/* Helper for writemask:
+ */
+static boolean emit_shuf_copy2( struct aos_compilation *cp,
+ struct x86_reg dst,
+ struct x86_reg arg0,
+ struct x86_reg arg1,
+ ubyte shuf )
+{
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+
+ emit_pshufd(cp, dst, arg1, shuf);
+ emit_pshufd(cp, tmp, arg0, shuf);
+ sse_shufps(cp->func, dst, tmp, SHUF(X, Y, Z, W));
+ emit_pshufd(cp, dst, dst, shuf);
+
+ aos_release_xmm_reg(cp, tmp.idx);
+ return TRUE;
+}
+
+
+
+#define SSE_SWIZZLE_NOOP ((0<<0) | (1<<2) | (2<<4) | (3<<6))
+
+
+/* Locate a source register and perform any required (simple) swizzle.
+ *
+ * Just fail on complex swizzles at this point.
+ */
+static struct x86_reg fetch_src( struct aos_compilation *cp,
+ const struct tgsi_full_src_register *src )
+{
+ struct x86_reg arg0 = aos_get_shader_reg(cp,
+ src->SrcRegister.File,
+ src->SrcRegister.Index);
+ unsigned i;
+ ubyte swz = 0;
+ unsigned negs = 0;
+ unsigned abs = 0;
+
+ for (i = 0; i < 4; i++) {
+ unsigned swizzle = tgsi_util_get_full_src_register_extswizzle( src, i );
+ unsigned neg = tgsi_util_get_full_src_register_sign_mode( src, i );
+
+ switch (swizzle) {
+ case TGSI_EXTSWIZZLE_ZERO:
+ case TGSI_EXTSWIZZLE_ONE:
+ AOS_ERROR(cp, "not supporting full swizzles yet in tgsi_aos_sse2");
+ break;
+
+ default:
+ swz |= (swizzle & 0x3) << (i * 2);
+ break;
+ }
+
+ switch (neg) {
+ case TGSI_UTIL_SIGN_TOGGLE:
+ negs |= (1<<i);
+ break;
+
+ case TGSI_UTIL_SIGN_KEEP:
+ break;
+
+ case TGSI_UTIL_SIGN_CLEAR:
+ abs |= (1<<i);
+ break;
+
+ default:
+ AOS_ERROR(cp, "unsupported sign-mode");
+ break;
+ }
+ }
+
+ if (swz != SSE_SWIZZLE_NOOP || negs != 0 || abs != 0) {
+ struct x86_reg dst = aos_get_xmm_reg(cp);
+
+ if (swz != SSE_SWIZZLE_NOOP)
+ emit_pshufd(cp, dst, arg0, swz);
+ else
+ sse_movaps(cp->func, dst, arg0);
+
+ if (negs && negs != 0xf) {
+ struct x86_reg imm_swz = aos_get_internal_xmm(cp, IMM_SWZ);
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+
+ /* Load 1,-1,0,0
+ * Use neg as arg to pshufd
+ * Multiply
+ */
+ emit_pshufd(cp, tmp, imm_swz,
+ SHUF((negs & 1) ? 1 : 0,
+ (negs & 2) ? 1 : 0,
+ (negs & 4) ? 1 : 0,
+ (negs & 8) ? 1 : 0));
+ sse_mulps(cp->func, dst, tmp);
+
+ aos_release_xmm_reg(cp, tmp.idx);
+ aos_soft_release_xmm(cp, imm_swz);
+ }
+ else if (negs) {
+ struct x86_reg imm_negs = aos_get_internal_xmm(cp, IMM_NEGS);
+ sse_mulps(cp->func, dst, imm_negs);
+ aos_soft_release_xmm(cp, imm_negs);
+ }
+
+
+ if (abs && abs != 0xf) {
+ AOS_ERROR(cp, "unsupported partial abs");
+ }
+ else if (abs) {
+ struct x86_reg neg = aos_get_internal(cp, IMM_NEGS);
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+
+ sse_movaps(cp->func, tmp, dst);
+ sse_mulps(cp->func, tmp, neg);
+ sse_maxps(cp->func, dst, tmp);
+
+ aos_release_xmm_reg(cp, tmp.idx);
+ aos_soft_release_xmm(cp, neg);
+ }
+
+ aos_soft_release_xmm(cp, arg0);
+ return dst;
+ }
+
+ return arg0;
+}
+
+static void x87_fld_src( struct aos_compilation *cp,
+ const struct tgsi_full_src_register *src,
+ unsigned channel )
+{
+ struct x86_reg arg0 = aos_get_shader_reg_ptr(cp,
+ src->SrcRegister.File,
+ src->SrcRegister.Index);
+
+ unsigned swizzle = tgsi_util_get_full_src_register_extswizzle( src, channel );
+ unsigned neg = tgsi_util_get_full_src_register_sign_mode( src, channel );
+
+ switch (swizzle) {
+ case TGSI_EXTSWIZZLE_ZERO:
+ x87_fldz( cp->func );
+ break;
+
+ case TGSI_EXTSWIZZLE_ONE:
+ x87_fld1( cp->func );
+ break;
+
+ default:
+ x87_fld( cp->func, x86_make_disp(arg0, (swizzle & 3) * sizeof(float)) );
+ break;
+ }
+
+
+ switch (neg) {
+ case TGSI_UTIL_SIGN_TOGGLE:
+ /* Flip the sign:
+ */
+ x87_fchs( cp->func );
+ break;
+
+ case TGSI_UTIL_SIGN_KEEP:
+ break;
+
+ case TGSI_UTIL_SIGN_CLEAR:
+ x87_fabs( cp->func );
+ break;
+
+ case TGSI_UTIL_SIGN_SET:
+ x87_fabs( cp->func );
+ x87_fchs( cp->func );
+ break;
+
+ default:
+ AOS_ERROR(cp, "unsupported sign-mode");
+ break;
+ }
+}
+
+
+
+
+
+
+/* Used to implement write masking. This and most of the other instructions
+ * here would be easier to implement if there had been a translation
+ * to a 2 argument format (dst/arg0, arg1) at the shader level before
+ * attempting to translate to x86/sse code.
+ */
+static void store_dest( struct aos_compilation *cp,
+ const struct tgsi_full_dst_register *reg,
+ struct x86_reg result )
+{
+ struct x86_reg dst;
+
+ switch (reg->DstRegister.WriteMask) {
+ case 0:
+ return;
+
+ case TGSI_WRITEMASK_XYZW:
+ aos_adopt_xmm_reg(cp,
+ get_xmm_writable(cp, result),
+ reg->DstRegister.File,
+ reg->DstRegister.Index,
+ TRUE);
+ return;
+ default:
+ break;
+ }
+
+ dst = aos_get_shader_reg_xmm(cp,
+ reg->DstRegister.File,
+ reg->DstRegister.Index);
+
+ switch (reg->DstRegister.WriteMask) {
+ case TGSI_WRITEMASK_X:
+ sse_movss(cp->func, dst, get_xmm(cp, result));
+ break;
+
+ case TGSI_WRITEMASK_ZW:
+ sse_shufps(cp->func, dst, get_xmm(cp, result), SHUF(X, Y, Z, W));
+ break;
+
+ case TGSI_WRITEMASK_XY:
+ result = get_xmm_writable(cp, result);
+ sse_shufps(cp->func, result, dst, SHUF(X, Y, Z, W));
+ dst = result;
+ break;
+
+ case TGSI_WRITEMASK_YZW:
+ result = get_xmm_writable(cp, result);
+ sse_movss(cp->func, result, dst);
+ dst = result;
+ break;
+
+ default:
+ mask_write(cp, dst, result, reg->DstRegister.WriteMask);
+ break;
+ }
+
+ aos_adopt_xmm_reg(cp,
+ dst,
+ reg->DstRegister.File,
+ reg->DstRegister.Index,
+ TRUE);
+
+}
+
+static void inject_scalar( struct aos_compilation *cp,
+ struct x86_reg dst,
+ struct x86_reg result,
+ ubyte swizzle )
+{
+ sse_shufps(cp->func, dst, dst, swizzle);
+ sse_movss(cp->func, dst, result);
+ sse_shufps(cp->func, dst, dst, swizzle);
+}
+
+
+static void store_scalar_dest( struct aos_compilation *cp,
+ const struct tgsi_full_dst_register *reg,
+ struct x86_reg result )
+{
+ unsigned writemask = reg->DstRegister.WriteMask;
+ struct x86_reg dst;
+
+ if (writemask != TGSI_WRITEMASK_X &&
+ writemask != TGSI_WRITEMASK_Y &&
+ writemask != TGSI_WRITEMASK_Z &&
+ writemask != TGSI_WRITEMASK_W &&
+ writemask != 0)
+ {
+ result = get_xmm_writable(cp, result); /* already true, right? */
+ sse_shufps(cp->func, result, result, SHUF(X,X,X,X));
+ store_dest(cp, reg, result);
+ return;
+ }
+
+ result = get_xmm(cp, result);
+ dst = aos_get_shader_reg_xmm(cp,
+ reg->DstRegister.File,
+ reg->DstRegister.Index);
+
+
+
+ switch (reg->DstRegister.WriteMask) {
+ case TGSI_WRITEMASK_X:
+ sse_movss(cp->func, dst, result);
+ break;
+
+ case TGSI_WRITEMASK_Y:
+ inject_scalar(cp, dst, result, SHUF(Y, X, Z, W));
+ break;
+
+ case TGSI_WRITEMASK_Z:
+ inject_scalar(cp, dst, result, SHUF(Z, Y, X, W));
+ break;
+
+ case TGSI_WRITEMASK_W:
+ inject_scalar(cp, dst, result, SHUF(W, Y, Z, X));
+ break;
+
+ default:
+ break;
+ }
+
+ aos_adopt_xmm_reg(cp,
+ dst,
+ reg->DstRegister.File,
+ reg->DstRegister.Index,
+ TRUE);
+}
+
+
+
+static void x87_fst_or_nop( struct x86_function *func,
+ unsigned writemask,
+ unsigned channel,
+ struct x86_reg ptr )
+{
+ assert(ptr.file == file_REG32);
+ if (writemask & (1<<channel))
+ x87_fst( func, x86_make_disp(ptr, channel * sizeof(float)) );
+}
+
+static void x87_fstp_or_pop( struct x86_function *func,
+ unsigned writemask,
+ unsigned channel,
+ struct x86_reg ptr )
+{
+ assert(ptr.file == file_REG32);
+ if (writemask & (1<<channel))
+ x87_fstp( func, x86_make_disp(ptr, channel * sizeof(float)) );
+ else
+ x87_fstp( func, x86_make_reg( file_x87, 0 ));
+}
+
+
+
+/*
+ */
+static void x87_fstp_dest4( struct aos_compilation *cp,
+ const struct tgsi_full_dst_register *dst )
+{
+ struct x86_reg ptr = get_dst_ptr(cp, dst);
+ unsigned writemask = dst->DstRegister.WriteMask;
+
+ x87_fst_or_nop(cp->func, writemask, 0, ptr);
+ x87_fst_or_nop(cp->func, writemask, 1, ptr);
+ x87_fst_or_nop(cp->func, writemask, 2, ptr);
+ x87_fstp_or_pop(cp->func, writemask, 3, ptr);
+}
+
+/* Save current x87 state and put it into single precision mode.
+ */
+static void save_fpu_state( struct aos_compilation *cp )
+{
+ x87_fnstcw( cp->func, x86_make_disp(cp->machine_EDX,
+ Offset(struct aos_machine, fpu_restore)));
+}
+
+static void restore_fpu_state( struct aos_compilation *cp )
+{
+ x87_fnclex(cp->func);
+ x87_fldcw( cp->func, x86_make_disp(cp->machine_EDX,
+ Offset(struct aos_machine, fpu_restore)));
+}
+
+static void set_fpu_round_neg_inf( struct aos_compilation *cp )
+{
+ if (cp->fpucntl != FPU_RND_NEG) {
+ cp->fpucntl = FPU_RND_NEG;
+ x87_fnclex(cp->func);
+ x87_fldcw( cp->func, x86_make_disp(cp->machine_EDX,
+ Offset(struct aos_machine, fpu_rnd_neg_inf)));
+ }
+}
+
+static void set_fpu_round_nearest( struct aos_compilation *cp )
+{
+ if (cp->fpucntl != FPU_RND_NEAREST) {
+ cp->fpucntl = FPU_RND_NEAREST;
+ x87_fnclex(cp->func);
+ x87_fldcw( cp->func, x86_make_disp(cp->machine_EDX,
+ Offset(struct aos_machine, fpu_rnd_nearest)));
+ }
+}
+
+#if 0
+static void x87_emit_ex2( struct aos_compilation *cp )
+{
+ struct x86_reg st0 = x86_make_reg(file_x87, 0);
+ struct x86_reg st1 = x86_make_reg(file_x87, 1);
+ int stack = cp->func->x87_stack;
+
+// set_fpu_round_neg_inf( cp );
+
+ x87_fld(cp->func, st0); /* a a */
+ x87_fprndint( cp->func ); /* int(a) a*/
+ x87_fsubr(cp->func, st1, st0); /* int(a) frc(a) */
+ x87_fxch(cp->func, st1); /* frc(a) int(a) */
+ x87_f2xm1(cp->func); /* (2^frc(a))-1 int(a) */
+ x87_fld1(cp->func); /* 1 (2^frc(a))-1 int(a) */
+ x87_faddp(cp->func, st1); /* 2^frac(a) int(a) */
+ x87_fscale(cp->func); /* (2^frac(a)*2^int(int(a))) int(a) */
+ /* 2^a int(a) */
+ x87_fstp(cp->func, st1); /* 2^a */
+
+ assert( stack == cp->func->x87_stack);
+
+}
+#endif
+
+#if 0
+static void PIPE_CDECL print_reg( const char *msg,
+ const float *reg )
+{
+ debug_printf("%s: %f %f %f %f\n", msg, reg[0], reg[1], reg[2], reg[3]);
+}
+#endif
+
+#if 0
+static void emit_print( struct aos_compilation *cp,
+ const char *message, /* must point to a static string! */
+ unsigned file,
+ unsigned idx )
+{
+ struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX );
+ struct x86_reg arg = aos_get_shader_reg_ptr( cp, file, idx );
+ unsigned i;
+
+ /* There shouldn't be anything on the x87 stack. Can add this
+ * capacity later if need be.
+ */
+ assert(cp->func->x87_stack == 0);
+
+ /* For absolute correctness, need to spill/invalidate all XMM regs
+ * too. We're obviously not concerned about performance on this
+ * debug path, so here goes:
+ */
+ for (i = 0; i < 8; i++) {
+ if (cp->xmm[i].dirty)
+ spill(cp, i);
+
+ aos_release_xmm_reg(cp, i);
+ }
+
+ /* Push caller-save (ie scratch) regs.
+ */
+ x86_cdecl_caller_push_regs( cp->func );
+
+
+ /* Push the arguments:
+ */
+ x86_lea( cp->func, ecx, arg );
+ x86_push( cp->func, ecx );
+ x86_push_imm32( cp->func, (int)message );
+
+ /* Call the helper. Could call debug_printf directly, but
+ * print_reg is a nice place to put a breakpoint if need be.
+ */
+ x86_mov_reg_imm( cp->func, ecx, (int)print_reg );
+ x86_call( cp->func, ecx );
+ x86_pop( cp->func, ecx );
+ x86_pop( cp->func, ecx );
+
+ /* Pop caller-save regs
+ */
+ x86_cdecl_caller_pop_regs( cp->func );
+
+ /* Done...
+ */
+}
+#endif
+
+/**
+ * The traditional instructions. All operate on internal registers
+ * and ignore write masks and swizzling issues.
+ */
+
+static boolean emit_ABS( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg neg = aos_get_internal(cp, IMM_NEGS);
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+
+ sse_movaps(cp->func, tmp, arg0);
+ sse_mulps(cp->func, tmp, neg);
+ sse_maxps(cp->func, tmp, arg0);
+
+ store_dest(cp, &op->FullDstRegisters[0], tmp);
+ return TRUE;
+}
+
+static boolean emit_ADD( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_addps(cp->func, dst, arg1);
+
+ store_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_COS( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ x87_fld_src(cp, &op->FullSrcRegisters[0], 0);
+ x87_fcos(cp->func);
+ x87_fstp_dest4(cp, &op->FullDstRegisters[0]);
+ return TRUE;
+}
+
+/* The dotproduct instructions don't really do that well in sse:
+ * XXX: produces wrong results -- disabled.
+ */
+static boolean emit_DP3( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_mulps(cp->func, dst, arg1);
+ /* Now the hard bit: sum the first 3 values:
+ */
+ sse_movhlps(cp->func, tmp, dst);
+ sse_addss(cp->func, dst, tmp); /* a*x+c*z, b*y, ?, ? */
+ emit_pshufd(cp, tmp, dst, SHUF(Y,X,W,Z));
+ sse_addss(cp->func, dst, tmp);
+
+ aos_release_xmm_reg(cp, tmp.idx);
+ store_scalar_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_DP4( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_mulps(cp->func, dst, arg1);
+
+ /* Now the hard bit: sum the values:
+ */
+ sse_movhlps(cp->func, tmp, dst);
+ sse_addps(cp->func, dst, tmp); /* a*x+c*z, b*y+d*w, a*x+c*z, b*y+d*w */
+ emit_pshufd(cp, tmp, dst, SHUF(Y,X,W,Z));
+ sse_addss(cp->func, dst, tmp);
+
+ aos_release_xmm_reg(cp, tmp.idx);
+ store_scalar_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_DPH( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_mulps(cp->func, dst, arg1);
+
+ /* Now the hard bit: sum the values (from DP3):
+ */
+ sse_movhlps(cp->func, tmp, dst);
+ sse_addss(cp->func, dst, tmp); /* a*x+c*z, b*y, ?, ? */
+ emit_pshufd(cp, tmp, dst, SHUF(Y,X,W,Z));
+ sse_addss(cp->func, dst, tmp);
+ emit_pshufd(cp, tmp, arg1, SHUF(W,W,W,W));
+ sse_addss(cp->func, dst, tmp);
+
+ aos_release_xmm_reg(cp, tmp.idx);
+ store_scalar_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_DST( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg dst = aos_get_xmm_reg(cp);
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+ struct x86_reg ones = aos_get_internal(cp, IMM_ONES);
+
+/* dst[0] = 1.0 * 1.0F; */
+/* dst[1] = arg0[1] * arg1[1]; */
+/* dst[2] = arg0[2] * 1.0; */
+/* dst[3] = 1.0 * arg1[3]; */
+
+ emit_shuf_copy2(cp, dst, arg0, ones, SHUF(X,W,Z,Y));
+ emit_shuf_copy2(cp, tmp, arg1, ones, SHUF(X,Z,Y,W));
+ sse_mulps(cp->func, dst, tmp);
+
+ aos_release_xmm_reg(cp, tmp.idx);
+ store_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_LG2( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ x87_fld1(cp->func); /* 1 */
+ x87_fld_src(cp, &op->FullSrcRegisters[0], 0); /* a0 1 */
+ x87_fyl2x(cp->func); /* log2(a0) */
+ x87_fstp_dest4(cp, &op->FullDstRegisters[0]);
+ return TRUE;
+}
+
+#if 0
+static boolean emit_EX2( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ x87_fld_src(cp, &op->FullSrcRegisters[0], 0);
+ x87_emit_ex2(cp);
+ x87_fstp_dest4(cp, &op->FullDstRegisters[0]);
+ return TRUE;
+}
+#endif
+
+
+static boolean emit_FLR( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg dst = get_dst_ptr(cp, &op->FullDstRegisters[0]);
+ unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask;
+ int i;
+
+ set_fpu_round_neg_inf( cp );
+
+ /* Load all sources first to avoid aliasing
+ */
+ for (i = 3; i >= 0; i--) {
+ if (writemask & (1<<i)) {
+ x87_fld_src(cp, &op->FullSrcRegisters[0], i);
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (writemask & (1<<i)) {
+ x87_fprndint( cp->func );
+ x87_fstp(cp->func, x86_make_disp(dst, i*4));
+ }
+ }
+
+ return TRUE;
+}
+
+
+static boolean emit_RND( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg dst = get_dst_ptr(cp, &op->FullDstRegisters[0]);
+ unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask;
+ int i;
+
+ set_fpu_round_nearest( cp );
+
+ /* Load all sources first to avoid aliasing
+ */
+ for (i = 3; i >= 0; i--) {
+ if (writemask & (1<<i)) {
+ x87_fld_src(cp, &op->FullSrcRegisters[0], i);
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (writemask & (1<<i)) {
+ x87_fprndint( cp->func );
+ x87_fstp(cp->func, x86_make_disp(dst, i*4));
+ }
+ }
+
+ return TRUE;
+}
+
+
+static boolean emit_FRC( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg dst = get_dst_ptr(cp, &op->FullDstRegisters[0]);
+ struct x86_reg st0 = x86_make_reg(file_x87, 0);
+ struct x86_reg st1 = x86_make_reg(file_x87, 1);
+ unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask;
+ int i;
+
+ set_fpu_round_neg_inf( cp );
+
+ /* suck all the source values onto the stack before writing out any
+ * dst, which may alias...
+ */
+ for (i = 3; i >= 0; i--) {
+ if (writemask & (1<<i)) {
+ x87_fld_src(cp, &op->FullSrcRegisters[0], i);
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (writemask & (1<<i)) {
+ x87_fld(cp->func, st0); /* a a */
+ x87_fprndint( cp->func ); /* flr(a) a */
+ x87_fsubp(cp->func, st1); /* frc(a) */
+ x87_fstp(cp->func, x86_make_disp(dst, i*4));
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+
+static boolean emit_LIT( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX );
+ unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask;
+ unsigned lit_count = cp->lit_count++;
+ struct x86_reg result, arg0;
+ unsigned i;
+
+#if 1
+ /* For absolute correctness, need to spill/invalidate all XMM regs
+ * too.
+ */
+ for (i = 0; i < 8; i++) {
+ if (cp->xmm[i].dirty)
+ spill(cp, i);
+ aos_release_xmm_reg(cp, i);
+ }
+#endif
+
+ if (writemask != TGSI_WRITEMASK_XYZW)
+ result = x86_make_disp(cp->machine_EDX, Offset(struct aos_machine, tmp[0]));
+ else
+ result = get_dst_ptr(cp, &op->FullDstRegisters[0]);
+
+
+ arg0 = fetch_src( cp, &op->FullSrcRegisters[0] );
+ if (arg0.file == file_XMM) {
+ struct x86_reg tmp = x86_make_disp(cp->machine_EDX,
+ Offset(struct aos_machine, tmp[1]));
+ sse_movaps( cp->func, tmp, arg0 );
+ arg0 = tmp;
+ }
+
+
+
+ /* Push caller-save (ie scratch) regs.
+ */
+ x86_cdecl_caller_push_regs( cp->func );
+
+ /* Push the arguments:
+ */
+ x86_push_imm32( cp->func, lit_count );
+
+ x86_lea( cp->func, ecx, arg0 );
+ x86_push( cp->func, ecx );
+
+ x86_lea( cp->func, ecx, result );
+ x86_push( cp->func, ecx );
+
+ x86_push( cp->func, cp->machine_EDX );
+
+ if (lit_count < MAX_LIT_INFO) {
+ x86_mov( cp->func, ecx, x86_make_disp( cp->machine_EDX,
+ Offset(struct aos_machine, lit_info) +
+ lit_count * sizeof(struct lit_info) +
+ Offset(struct lit_info, func)));
+ }
+ else {
+ x86_mov_reg_imm( cp->func, ecx, (int)aos_do_lit );
+ }
+
+ x86_call( cp->func, ecx );
+
+ x86_pop( cp->func, ecx ); /* fixme... */
+ x86_pop( cp->func, ecx );
+ x86_pop( cp->func, ecx );
+ x86_pop( cp->func, ecx );
+
+ x86_cdecl_caller_pop_regs( cp->func );
+
+ if (writemask != TGSI_WRITEMASK_XYZW) {
+ store_dest( cp,
+ &op->FullDstRegisters[0],
+ get_xmm_writable( cp, result ) );
+ }
+
+ return TRUE;
+}
+
+#if 0
+static boolean emit_inline_LIT( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg dst = get_dst_ptr(cp, &op->FullDstRegisters[0]);
+ unsigned writemask = op->FullDstRegisters[0].DstRegister.WriteMask;
+
+ if (writemask & TGSI_WRITEMASK_YZ) {
+ struct x86_reg st1 = x86_make_reg(file_x87, 1);
+ struct x86_reg st2 = x86_make_reg(file_x87, 2);
+
+ /* a1' = a1 <= 0 ? 1 : a1;
+ */
+ x87_fldz(cp->func); /* 1 0 */
+#if 1
+ x87_fld1(cp->func); /* 1 0 */
+#else
+ /* Correct but slow due to fp exceptions generated in fyl2x - fix me.
+ */
+ x87_fldz(cp->func); /* 1 0 */
+#endif
+ x87_fld_src(cp, &op->FullSrcRegisters[0], 1); /* a1 1 0 */
+ x87_fcomi(cp->func, st2); /* a1 1 0 */
+ x87_fcmovb(cp->func, st1); /* a1' 1 0 */
+ x87_fstp(cp->func, st1); /* a1' 0 */
+ x87_fstp(cp->func, st1); /* a1' */
+
+ x87_fld_src(cp, &op->FullSrcRegisters[0], 3); /* a3 a1' */
+ x87_fxch(cp->func, st1); /* a1' a3 */
+
+
+ /* Compute pow(a1, a3)
+ */
+ x87_fyl2x(cp->func); /* a3*log2(a1) */
+ x87_emit_ex2( cp ); /* 2^(a3*log2(a1)) */
+
+
+ /* a0' = max2(a0, 0):
+ */
+ x87_fldz(cp->func); /* 0 r2 */
+ x87_fld_src(cp, &op->FullSrcRegisters[0], 0); /* a0 0 r2 */
+ x87_fcomi(cp->func, st1);
+ x87_fcmovb(cp->func, st1); /* a0' 0 r2 */
+
+ x87_fst_or_nop(cp->func, writemask, 1, dst); /* result[1] = a0' */
+
+ x87_fcomi(cp->func, st1); /* a0' 0 r2 */
+ x87_fcmovnbe(cp->func, st2); /* r2' 0' r2 */
+
+ x87_fstp_or_pop(cp->func, writemask, 2, dst); /* 0 r2 */
+ x87_fpop(cp->func); /* r2 */
+ x87_fpop(cp->func);
+ }
+
+ if (writemask & TGSI_WRITEMASK_XW) {
+ x87_fld1(cp->func);
+ x87_fst_or_nop(cp->func, writemask, 0, dst);
+ x87_fstp_or_pop(cp->func, writemask, 3, dst);
+ }
+
+ return TRUE;
+}
+#endif
+
+
+
+static boolean emit_MAX( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_maxps(cp->func, dst, arg1);
+
+ store_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+
+static boolean emit_MIN( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_minps(cp->func, dst, arg1);
+
+ store_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_MOV( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ /* potentially nothing to do */
+
+ store_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_MUL( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_mulps(cp->func, dst, arg1);
+
+ store_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+
+static boolean emit_MAD( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg arg2 = fetch_src(cp, &op->FullSrcRegisters[2]);
+
+ /* If we can't clobber old contents of arg0, get a temporary & copy
+ * it there, then clobber it...
+ */
+ arg0 = get_xmm_writable(cp, arg0);
+
+ sse_mulps(cp->func, arg0, arg1);
+ sse_addps(cp->func, arg0, arg2);
+ store_dest(cp, &op->FullDstRegisters[0], arg0);
+ return TRUE;
+}
+
+
+
+/* A wrapper for powf().
+ * Makes sure it is cdecl and operates on floats.
+ */
+static float PIPE_CDECL _powerf( float x, float y )
+{
+#if FAST_MATH
+ return util_fast_pow(x, y);
+#else
+ return powf( x, y );
+#endif
+}
+
+#if FAST_MATH
+static float PIPE_CDECL _exp2(float x)
+{
+ return util_fast_exp2(x);
+}
+#endif
+
+
+/* Really not sufficient -- need to check for conditions that could
+ * generate inf/nan values, which will slow things down hugely.
+ */
+static boolean emit_POW( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+#if 0
+ x87_fld_src(cp, &op->FullSrcRegisters[1], 0); /* a1.x */
+ x87_fld_src(cp, &op->FullSrcRegisters[0], 0); /* a0.x a1.x */
+ x87_fyl2x(cp->func); /* a1*log2(a0) */
+
+ x87_emit_ex2( cp ); /* 2^(a1*log2(a0)) */
+
+ x87_fstp_dest4(cp, &op->FullDstRegisters[0]);
+#else
+ uint i;
+
+ /* For absolute correctness, need to spill/invalidate all XMM regs
+ * too.
+ */
+ for (i = 0; i < 8; i++) {
+ if (cp->xmm[i].dirty)
+ spill(cp, i);
+ aos_release_xmm_reg(cp, i);
+ }
+
+ /* Push caller-save (ie scratch) regs.
+ */
+ x86_cdecl_caller_push_regs( cp->func );
+
+ x86_lea( cp->func, cp->stack_ESP, x86_make_disp(cp->stack_ESP, -8) );
+
+ x87_fld_src( cp, &op->FullSrcRegisters[1], 0 );
+ x87_fstp( cp->func, x86_make_disp( cp->stack_ESP, 4 ) );
+ x87_fld_src( cp, &op->FullSrcRegisters[0], 0 );
+ x87_fstp( cp->func, x86_make_disp( cp->stack_ESP, 0 ) );
+
+ /* tmp_EAX has been pushed & will be restored below */
+ x86_mov_reg_imm( cp->func, cp->tmp_EAX, (unsigned long) _powerf );
+ x86_call( cp->func, cp->tmp_EAX );
+
+ x86_lea( cp->func, cp->stack_ESP, x86_make_disp(cp->stack_ESP, 8) );
+
+ x86_cdecl_caller_pop_regs( cp->func );
+
+ /* Note retval on x87 stack:
+ */
+ cp->func->x87_stack++;
+
+ x87_fstp_dest4( cp, &op->FullDstRegisters[0] );
+#endif
+ return TRUE;
+}
+
+
+#if FAST_MATH
+static boolean emit_EXPBASE2( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ uint i;
+
+ /* For absolute correctness, need to spill/invalidate all XMM regs
+ * too.
+ */
+ for (i = 0; i < 8; i++) {
+ if (cp->xmm[i].dirty)
+ spill(cp, i);
+ aos_release_xmm_reg(cp, i);
+ }
+
+ /* Push caller-save (ie scratch) regs.
+ */
+ x86_cdecl_caller_push_regs( cp->func );
+
+ x86_lea( cp->func, cp->stack_ESP, x86_make_disp(cp->stack_ESP, -4) );
+
+ x87_fld_src( cp, &op->FullSrcRegisters[0], 0 );
+ x87_fstp( cp->func, x86_make_disp( cp->stack_ESP, 0 ) );
+
+ /* tmp_EAX has been pushed & will be restored below */
+ x86_mov_reg_imm( cp->func, cp->tmp_EAX, (unsigned long) _exp2 );
+ x86_call( cp->func, cp->tmp_EAX );
+
+ x86_lea( cp->func, cp->stack_ESP, x86_make_disp(cp->stack_ESP, 4) );
+
+ x86_cdecl_caller_pop_regs( cp->func );
+
+ /* Note retval on x87 stack:
+ */
+ cp->func->x87_stack++;
+
+ x87_fstp_dest4( cp, &op->FullDstRegisters[0] );
+
+ return TRUE;
+}
+#endif
+
+
+static boolean emit_RCP( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg dst = aos_get_xmm_reg(cp);
+
+ if (cp->have_sse2) {
+ sse2_rcpss(cp->func, dst, arg0);
+ /* extend precision here...
+ */
+ }
+ else {
+ struct x86_reg ones = aos_get_internal(cp, IMM_ONES);
+ sse_movss(cp->func, dst, ones);
+ sse_divss(cp->func, dst, arg0);
+ }
+
+ store_scalar_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+
+/* Although rsqrtps() and rcpps() are low precision on some/all SSE
+ * implementations, it is possible to improve its precision at
+ * fairly low cost, using a newton/raphson step, as below:
+ *
+ * x1 = 2 * rcpps(a) - a * rcpps(a) * rcpps(a)
+ * x1 = 0.5 * rsqrtps(a) * [3.0 - (a * rsqrtps(a))* rsqrtps(a)]
+ * or:
+ * x1 = rsqrtps(a) * [1.5 - .5 * a * rsqrtps(a) * rsqrtps(a)]
+ *
+ *
+ * See: http://softwarecommunity.intel.com/articles/eng/1818.htm
+ */
+static boolean emit_RSQ( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ if (0) {
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg r = aos_get_xmm_reg(cp);
+ sse_rsqrtss(cp->func, r, arg0);
+ store_scalar_dest(cp, &op->FullDstRegisters[0], r);
+ return TRUE;
+ }
+ else {
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg r = aos_get_xmm_reg(cp);
+
+ struct x86_reg neg_half = get_reg_ptr( cp, AOS_FILE_INTERNAL, IMM_RSQ );
+ struct x86_reg one_point_five = x86_make_disp( neg_half, 4 );
+ struct x86_reg src = get_xmm_writable( cp, arg0 );
+ struct x86_reg neg = aos_get_internal(cp, IMM_NEGS);
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+
+ sse_movaps(cp->func, tmp, src);
+ sse_mulps(cp->func, tmp, neg);
+ sse_maxps(cp->func, tmp, src);
+
+ sse_rsqrtss( cp->func, r, tmp ); /* rsqrtss(a) */
+ sse_mulss( cp->func, tmp, neg_half ); /* -.5 * a */
+ sse_mulss( cp->func, tmp, r ); /* -.5 * a * r */
+ sse_mulss( cp->func, tmp, r ); /* -.5 * a * r * r */
+ sse_addss( cp->func, tmp, one_point_five ); /* 1.5 - .5 * a * r * r */
+ sse_mulss( cp->func, r, tmp ); /* r * (1.5 - .5 * a * r * r) */
+
+ store_scalar_dest(cp, &op->FullDstRegisters[0], r);
+
+ aos_release_xmm_reg(cp, tmp.idx);
+
+ return TRUE;
+ }
+}
+
+
+static boolean emit_SGE( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg ones = aos_get_internal(cp, IMM_ONES);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_cmpps(cp->func, dst, arg1, cc_NotLessThan);
+ sse_andps(cp->func, dst, ones);
+
+ store_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_SIN( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ x87_fld_src(cp, &op->FullSrcRegisters[0], 0);
+ x87_fsin(cp->func);
+ x87_fstp_dest4(cp, &op->FullDstRegisters[0]);
+ return TRUE;
+}
+
+
+
+static boolean emit_SLT( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg ones = aos_get_internal(cp, IMM_ONES);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_cmpps(cp->func, dst, arg1, cc_LessThan);
+ sse_andps(cp->func, dst, ones);
+
+ store_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_SUB( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg dst = get_xmm_writable(cp, arg0);
+
+ sse_subps(cp->func, dst, arg1);
+
+ store_dest(cp, &op->FullDstRegisters[0], dst);
+ return TRUE;
+}
+
+static boolean emit_TRUNC( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg tmp0 = aos_get_xmm_reg(cp);
+
+ sse2_cvttps2dq(cp->func, tmp0, arg0);
+ sse2_cvtdq2ps(cp->func, tmp0, tmp0);
+
+ store_dest(cp, &op->FullDstRegisters[0], tmp0);
+ return TRUE;
+}
+
+static boolean emit_XPD( struct aos_compilation *cp, const struct tgsi_full_instruction *op )
+{
+ struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]);
+ struct x86_reg arg1 = fetch_src(cp, &op->FullSrcRegisters[1]);
+ struct x86_reg tmp0 = aos_get_xmm_reg(cp);
+ struct x86_reg tmp1 = aos_get_xmm_reg(cp);
+
+ emit_pshufd(cp, tmp1, arg1, SHUF(Y, Z, X, W));
+ sse_mulps(cp->func, tmp1, arg0);
+ emit_pshufd(cp, tmp0, arg0, SHUF(Y, Z, X, W));
+ sse_mulps(cp->func, tmp0, arg1);
+ sse_subps(cp->func, tmp1, tmp0);
+ sse_shufps(cp->func, tmp1, tmp1, SHUF(Y, Z, X, W));
+
+/* dst[2] = arg0[0] * arg1[1] - arg0[1] * arg1[0]; */
+/* dst[0] = arg0[1] * arg1[2] - arg0[2] * arg1[1]; */
+/* dst[1] = arg0[2] * arg1[0] - arg0[0] * arg1[2]; */
+/* dst[3] is undef */
+
+
+ aos_release_xmm_reg(cp, tmp0.idx);
+ store_dest(cp, &op->FullDstRegisters[0], tmp1);
+ return TRUE;
+}
+
+
+
+static boolean
+emit_instruction( struct aos_compilation *cp,
+ struct tgsi_full_instruction *inst )
+{
+ x87_assert_stack_empty(cp->func);
+
+ switch( inst->Instruction.Opcode ) {
+ case TGSI_OPCODE_MOV:
+ return emit_MOV( cp, inst );
+
+ case TGSI_OPCODE_LIT:
+ return emit_LIT(cp, inst);
+
+ case TGSI_OPCODE_RCP:
+ return emit_RCP(cp, inst);
+
+ case TGSI_OPCODE_RSQ:
+ return emit_RSQ(cp, inst);
+
+ case TGSI_OPCODE_EXP:
+ /*return emit_EXP(cp, inst);*/
+ return FALSE;
+
+ case TGSI_OPCODE_LOG:
+ /*return emit_LOG(cp, inst);*/
+ return FALSE;
+
+ case TGSI_OPCODE_MUL:
+ return emit_MUL(cp, inst);
+
+ case TGSI_OPCODE_ADD:
+ return emit_ADD(cp, inst);
+
+ case TGSI_OPCODE_DP3:
+ return emit_DP3(cp, inst);
+
+ case TGSI_OPCODE_DP4:
+ return emit_DP4(cp, inst);
+
+ case TGSI_OPCODE_DST:
+ return emit_DST(cp, inst);
+
+ case TGSI_OPCODE_MIN:
+ return emit_MIN(cp, inst);
+
+ case TGSI_OPCODE_MAX:
+ return emit_MAX(cp, inst);
+
+ case TGSI_OPCODE_SLT:
+ return emit_SLT(cp, inst);
+
+ case TGSI_OPCODE_SGE:
+ return emit_SGE(cp, inst);
+
+ case TGSI_OPCODE_MAD:
+ return emit_MAD(cp, inst);
+
+ case TGSI_OPCODE_SUB:
+ return emit_SUB(cp, inst);
+
+ case TGSI_OPCODE_LRP:
+// return emit_LERP(cp, inst);
+ return FALSE;
+
+ case TGSI_OPCODE_FRC:
+ return emit_FRC(cp, inst);
+
+ case TGSI_OPCODE_CLAMP:
+// return emit_CLAMP(cp, inst);
+ return FALSE;
+
+ case TGSI_OPCODE_FLR:
+ return emit_FLR(cp, inst);
+
+ case TGSI_OPCODE_ROUND:
+ return emit_RND(cp, inst);
+
+ case TGSI_OPCODE_EX2:
+#if FAST_MATH
+ return emit_EXPBASE2(cp, inst);
+#elif 0
+ /* this seems to fail for "larger" exponents.
+ * See glean tvertProg1's EX2 test.
+ */
+ return emit_EX2(cp, inst);
+#else
+ return FALSE;
+#endif
+
+ case TGSI_OPCODE_LG2:
+ return emit_LG2(cp, inst);
+
+ case TGSI_OPCODE_POW:
+ return emit_POW(cp, inst);
+
+ case TGSI_OPCODE_XPD:
+ return emit_XPD(cp, inst);
+
+ case TGSI_OPCODE_ABS:
+ return emit_ABS(cp, inst);
+
+ case TGSI_OPCODE_DPH:
+ return emit_DPH(cp, inst);
+
+ case TGSI_OPCODE_COS:
+ return emit_COS(cp, inst);
+
+ case TGSI_OPCODE_SIN:
+ return emit_SIN(cp, inst);
+
+ case TGSI_OPCODE_TRUNC:
+ return emit_TRUNC(cp, inst);
+
+ case TGSI_OPCODE_END:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+
+static boolean emit_viewport( struct aos_compilation *cp )
+{
+ struct x86_reg pos = aos_get_shader_reg_xmm(cp,
+ TGSI_FILE_OUTPUT,
+ cp->vaos->draw->vs.position_output );
+
+ struct x86_reg scale = x86_make_disp(cp->machine_EDX,
+ Offset(struct aos_machine, scale));
+
+ struct x86_reg translate = x86_make_disp(cp->machine_EDX,
+ Offset(struct aos_machine, translate));
+
+ sse_mulps(cp->func, pos, scale);
+ sse_addps(cp->func, pos, translate);
+
+ aos_adopt_xmm_reg( cp,
+ pos,
+ TGSI_FILE_OUTPUT,
+ cp->vaos->draw->vs.position_output,
+ TRUE );
+ return TRUE;
+}
+
+
+/* This is useful to be able to see the results on softpipe. Doesn't
+ * do proper clipping, just assumes the backend can do it during
+ * rasterization -- for debug only...
+ */
+static boolean emit_rhw_viewport( struct aos_compilation *cp )
+{
+ struct x86_reg tmp = aos_get_xmm_reg(cp);
+ struct x86_reg pos = aos_get_shader_reg_xmm(cp,
+ TGSI_FILE_OUTPUT,
+ cp->vaos->draw->vs.position_output);
+
+ struct x86_reg scale = x86_make_disp(cp->machine_EDX,
+ Offset(struct aos_machine, scale));
+
+ struct x86_reg translate = x86_make_disp(cp->machine_EDX,
+ Offset(struct aos_machine, translate));
+
+
+
+ emit_pshufd(cp, tmp, pos, SHUF(W, W, W, W));
+ sse2_rcpss(cp->func, tmp, tmp);
+ sse_shufps(cp->func, tmp, tmp, SHUF(X, X, X, X));
+
+ sse_mulps(cp->func, pos, scale);
+ sse_mulps(cp->func, pos, tmp);
+ sse_addps(cp->func, pos, translate);
+
+ /* Set pos[3] = w
+ */
+ mask_write(cp, pos, tmp, TGSI_WRITEMASK_W);
+
+ aos_adopt_xmm_reg( cp,
+ pos,
+ TGSI_FILE_OUTPUT,
+ cp->vaos->draw->vs.position_output,
+ TRUE );
+ return TRUE;
+}
+
+
+#if 0
+static boolean note_immediate( struct aos_compilation *cp,
+ struct tgsi_full_immediate *imm )
+{
+ unsigned pos = cp->num_immediates++;
+ unsigned j;
+
+ assert( imm->Immediate.NrTokens <= 4 + 1 );
+ for (j = 0; j < imm->Immediate.NrTokens - 1; j++) {
+ cp->vaos->machine->immediate[pos][j] = imm->u[j].Float;
+ }
+
+ return TRUE;
+}
+#endif
+
+
+
+
+static void find_last_write_outputs( struct aos_compilation *cp )
+{
+ struct tgsi_parse_context parse;
+ unsigned this_instruction = 0;
+ unsigned i;
+
+ tgsi_parse_init( &parse, cp->vaos->base.vs->state.tokens );
+
+ while (!tgsi_parse_end_of_tokens( &parse )) {
+
+ tgsi_parse_token( &parse );
+
+ if (parse.FullToken.Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION)
+ continue;
+
+ for (i = 0; i < TGSI_FULL_MAX_DST_REGISTERS; i++) {
+ if (parse.FullToken.FullInstruction.FullDstRegisters[i].DstRegister.File ==
+ TGSI_FILE_OUTPUT)
+ {
+ unsigned idx = parse.FullToken.FullInstruction.FullDstRegisters[i].DstRegister.Index;
+ cp->output_last_write[idx] = this_instruction;
+ }
+ }
+
+ this_instruction++;
+ }
+
+ tgsi_parse_free( &parse );
+}
+
+
+#define ARG_MACHINE 1
+#define ARG_START_ELTS 2
+#define ARG_COUNT 3
+#define ARG_OUTBUF 4
+
+
+static boolean build_vertex_program( struct draw_vs_varient_aos_sse *varient,
+ boolean linear )
+{
+ struct tgsi_parse_context parse;
+ struct aos_compilation cp;
+ unsigned fixup, label;
+
+ util_init_math();
+
+ tgsi_parse_init( &parse, varient->base.vs->state.tokens );
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.insn_counter = 1;
+ cp.vaos = varient;
+ cp.have_sse2 = 1;
+ cp.func = &varient->func[ linear ? 0 : 1 ];
+
+ cp.tmp_EAX = x86_make_reg(file_REG32, reg_AX);
+ cp.idx_EBX = x86_make_reg(file_REG32, reg_BX);
+ cp.outbuf_ECX = x86_make_reg(file_REG32, reg_CX);
+ cp.machine_EDX = x86_make_reg(file_REG32, reg_DX);
+ cp.count_ESI = x86_make_reg(file_REG32, reg_SI);
+ cp.temp_EBP = x86_make_reg(file_REG32, reg_BP);
+ cp.stack_ESP = x86_make_reg( file_REG32, reg_SP );
+
+ x86_init_func(cp.func);
+
+ find_last_write_outputs(&cp);
+
+ x86_push(cp.func, cp.idx_EBX);
+ x86_push(cp.func, cp.count_ESI);
+ x86_push(cp.func, cp.temp_EBP);
+
+
+ /* Load arguments into regs:
+ */
+ x86_mov(cp.func, cp.machine_EDX, x86_fn_arg(cp.func, ARG_MACHINE));
+ x86_mov(cp.func, cp.idx_EBX, x86_fn_arg(cp.func, ARG_START_ELTS));
+ x86_mov(cp.func, cp.count_ESI, x86_fn_arg(cp.func, ARG_COUNT));
+ x86_mov(cp.func, cp.outbuf_ECX, x86_fn_arg(cp.func, ARG_OUTBUF));
+
+
+ /* Compare count to zero and possibly bail.
+ */
+ x86_xor(cp.func, cp.tmp_EAX, cp.tmp_EAX);
+ x86_cmp(cp.func, cp.count_ESI, cp.tmp_EAX);
+ fixup = x86_jcc_forward(cp.func, cc_E);
+
+
+ save_fpu_state( &cp );
+ set_fpu_round_nearest( &cp );
+
+ aos_init_inputs( &cp, linear );
+
+ cp.x86_reg[0] = 0;
+ cp.x86_reg[1] = 0;
+
+ /* Note address for loop jump
+ */
+ label = x86_get_label(cp.func);
+ {
+ /* Fetch inputs... TODO: fetch lazily...
+ */
+ if (!aos_fetch_inputs( &cp, linear ))
+ goto fail;
+
+ /* Emit the shader:
+ */
+ while( !tgsi_parse_end_of_tokens( &parse ) && !cp.error )
+ {
+ tgsi_parse_token( &parse );
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+#if 0
+ if (!note_immediate( &cp, &parse.FullToken.FullImmediate ))
+ goto fail;
+#endif
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (DISASSEM)
+ tgsi_dump_instruction( &parse.FullToken.FullInstruction, cp.insn_counter );
+
+ if (!emit_instruction( &cp, &parse.FullToken.FullInstruction ))
+ goto fail;
+ break;
+ }
+
+ x87_assert_stack_empty(cp.func);
+ cp.insn_counter++;
+
+ if (DISASSEM)
+ debug_printf("\n");
+ }
+
+
+ {
+ unsigned i;
+ for (i = 0; i < 8; i++) {
+ if (cp.xmm[i].file != TGSI_FILE_OUTPUT) {
+ cp.xmm[i].file = TGSI_FILE_NULL;
+ cp.xmm[i].dirty = 0;
+ }
+ }
+ }
+
+ if (cp.error)
+ goto fail;
+
+ if (cp.vaos->base.key.clip) {
+ /* not really handling clipping, just do the rhw so we can
+ * see the results...
+ */
+ emit_rhw_viewport(&cp);
+ }
+ else if (cp.vaos->base.key.viewport) {
+ emit_viewport(&cp);
+ }
+
+ /* Emit output... TODO: do this eagerly after the last write to a
+ * given output.
+ */
+ if (!aos_emit_outputs( &cp ))
+ goto fail;
+
+
+ /* Next vertex:
+ */
+ x86_lea(cp.func,
+ cp.outbuf_ECX,
+ x86_make_disp(cp.outbuf_ECX,
+ cp.vaos->base.key.output_stride));
+
+ /* Incr index
+ */
+ aos_incr_inputs( &cp, linear );
+ }
+ /* decr count, loop if not zero
+ */
+ x86_dec(cp.func, cp.count_ESI);
+ x86_jcc(cp.func, cc_NZ, label);
+
+ restore_fpu_state(&cp);
+
+ /* Land forward jump here:
+ */
+ x86_fixup_fwd_jump(cp.func, fixup);
+
+ /* Exit mmx state?
+ */
+ if (cp.func->need_emms)
+ mmx_emms(cp.func);
+
+ x86_pop(cp.func, cp.temp_EBP);
+ x86_pop(cp.func, cp.count_ESI);
+ x86_pop(cp.func, cp.idx_EBX);
+
+ x87_assert_stack_empty(cp.func);
+ x86_ret(cp.func);
+
+ tgsi_parse_free( &parse );
+ return !cp.error;
+
+ fail:
+ tgsi_parse_free( &parse );
+ return FALSE;
+}
+
+
+
+static void vaos_set_buffer( struct draw_vs_varient *varient,
+ unsigned buf,
+ const void *ptr,
+ unsigned stride )
+{
+ struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient;
+
+ if (buf < vaos->nr_vb) {
+ vaos->buffer[buf].base_ptr = (char *)ptr;
+ vaos->buffer[buf].stride = stride;
+ }
+
+ if (0) debug_printf("%s %d/%d: %p %d\n", __FUNCTION__, buf, vaos->nr_vb, ptr, stride);
+}
+
+
+
+static void PIPE_CDECL vaos_run_elts( struct draw_vs_varient *varient,
+ const unsigned *elts,
+ unsigned count,
+ void *output_buffer )
+{
+ struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient;
+ struct aos_machine *machine = vaos->draw->vs.aos_machine;
+
+ if (0) debug_printf("%s %d\n", __FUNCTION__, count);
+
+ machine->internal[IMM_PSIZE][0] = vaos->draw->rasterizer->point_size;
+ machine->constants = vaos->draw->vs.aligned_constants;
+ machine->immediates = vaos->base.vs->immediates;
+ machine->buffer = vaos->buffer;
+
+ vaos->gen_run_elts( machine,
+ elts,
+ count,
+ output_buffer );
+}
+
+static void PIPE_CDECL vaos_run_linear( struct draw_vs_varient *varient,
+ unsigned start,
+ unsigned count,
+ void *output_buffer )
+{
+ struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient;
+ struct aos_machine *machine = vaos->draw->vs.aos_machine;
+
+ if (0) debug_printf("%s %d %d const: %x\n", __FUNCTION__, start, count,
+ vaos->base.key.const_vbuffers);
+
+ machine->internal[IMM_PSIZE][0] = vaos->draw->rasterizer->point_size;
+ machine->constants = vaos->draw->vs.aligned_constants;
+ machine->immediates = vaos->base.vs->immediates;
+ machine->buffer = vaos->buffer;
+
+ vaos->gen_run_linear( machine,
+ start,
+ count,
+ output_buffer );
+
+ /* Sanity spot checks to make sure we didn't trash our constants */
+ assert(machine->internal[IMM_ONES][0] == 1.0f);
+ assert(machine->internal[IMM_IDENTITY][0] == 0.0f);
+ assert(machine->internal[IMM_NEGS][0] == -1.0f);
+}
+
+
+
+static void vaos_destroy( struct draw_vs_varient *varient )
+{
+ struct draw_vs_varient_aos_sse *vaos = (struct draw_vs_varient_aos_sse *)varient;
+
+ FREE( vaos->buffer );
+
+ x86_release_func( &vaos->func[0] );
+ x86_release_func( &vaos->func[1] );
+
+ FREE(vaos);
+}
+
+
+
+static struct draw_vs_varient *varient_aos_sse( struct draw_vertex_shader *vs,
+ const struct draw_vs_varient_key *key )
+{
+ unsigned i;
+ struct draw_vs_varient_aos_sse *vaos = CALLOC_STRUCT(draw_vs_varient_aos_sse);
+
+ if (!vaos)
+ goto fail;
+
+ vaos->base.key = *key;
+ vaos->base.vs = vs;
+ vaos->base.set_buffer = vaos_set_buffer;
+ vaos->base.destroy = vaos_destroy;
+ vaos->base.run_linear = vaos_run_linear;
+ vaos->base.run_elts = vaos_run_elts;
+
+ vaos->draw = vs->draw;
+
+ for (i = 0; i < key->nr_inputs; i++)
+ vaos->nr_vb = MAX2( vaos->nr_vb, key->element[i].in.buffer + 1 );
+
+ vaos->buffer = MALLOC( vaos->nr_vb * sizeof(vaos->buffer[0]) );
+ if (!vaos->buffer)
+ goto fail;
+
+ if (0)
+ debug_printf("nr_vb: %d const: %x\n", vaos->nr_vb, vaos->base.key.const_vbuffers);
+
+#if 0
+ tgsi_dump(vs->state.tokens, 0);
+#endif
+
+ if (!build_vertex_program( vaos, TRUE ))
+ goto fail;
+
+ if (!build_vertex_program( vaos, FALSE ))
+ goto fail;
+
+ vaos->gen_run_linear = (vaos_run_linear_func)x86_get_func(&vaos->func[0]);
+ if (!vaos->gen_run_linear)
+ goto fail;
+
+ vaos->gen_run_elts = (vaos_run_elts_func)x86_get_func(&vaos->func[1]);
+ if (!vaos->gen_run_elts)
+ goto fail;
+
+ return &vaos->base;
+
+ fail:
+ if (vaos && vaos->buffer)
+ FREE(vaos->buffer);
+
+ if (vaos)
+ x86_release_func( &vaos->func[0] );
+
+ if (vaos)
+ x86_release_func( &vaos->func[1] );
+
+ FREE(vaos);
+
+ return NULL;
+}
+
+
+struct draw_vs_varient *draw_vs_varient_aos_sse( struct draw_vertex_shader *vs,
+ const struct draw_vs_varient_key *key )
+{
+ struct draw_vs_varient *varient = varient_aos_sse( vs, key );
+
+ if (varient == NULL) {
+ varient = draw_vs_varient_generic( vs, key );
+ }
+
+ return varient;
+}
+
+
+
+#endif /* PIPE_ARCH_X86 */
diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.h b/src/gallium/auxiliary/draw/draw_vs_aos.h
new file mode 100644
index 0000000000..2cf72ddf7b
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_aos.h
@@ -0,0 +1,253 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef DRAW_VS_AOS_H
+#define DRAW_VS_AOS_H
+
+#include "pipe/p_config.h"
+
+#ifdef PIPE_ARCH_X86
+
+struct tgsi_token;
+struct x86_function;
+
+#include "pipe/p_state.h"
+#include "rtasm/rtasm_x86sse.h"
+
+
+
+
+
+#define X 0
+#define Y 1
+#define Z 2
+#define W 3
+
+#define MAX_INPUTS PIPE_MAX_ATTRIBS
+#define MAX_OUTPUTS PIPE_MAX_SHADER_OUTPUTS
+#define MAX_TEMPS TGSI_EXEC_NUM_TEMPS
+#define MAX_CONSTANTS 1024 /** only used for sanity checking */
+#define MAX_IMMEDIATES 1024 /** only used for sanity checking */
+#define MAX_INTERNALS 8 /** see IMM_x values below */
+
+#define AOS_FILE_INTERNAL TGSI_FILE_COUNT
+
+#define FPU_RND_NEG 1
+#define FPU_RND_NEAREST 2
+
+struct aos_machine;
+typedef void (PIPE_CDECL *lit_func)( struct aos_machine *,
+ float *result,
+ const float *in,
+ unsigned count );
+
+void PIPE_CDECL aos_do_lit( struct aos_machine *machine,
+ float *result,
+ const float *in,
+ unsigned count );
+
+struct shine_tab {
+ float exponent;
+ float values[258];
+ unsigned last_used;
+};
+
+struct lit_info {
+ lit_func func;
+ struct shine_tab *shine_tab;
+};
+
+#define MAX_SHINE_TAB 4
+#define MAX_LIT_INFO 16
+
+struct aos_buffer {
+ const void *base_ptr;
+ unsigned stride;
+ void *ptr; /* updated per vertex */
+};
+
+
+
+
+/* This is the temporary storage used by all the aos_sse vs varients.
+ * Create one per context and reuse by passing a pointer in at
+ * vs_varient creation??
+ */
+struct aos_machine {
+ float input [MAX_INPUTS ][4];
+ float output [MAX_OUTPUTS ][4];
+ float temp [MAX_TEMPS ][4];
+ float internal [MAX_INTERNALS ][4];
+
+ float scale[4]; /* viewport */
+ float translate[4]; /* viewport */
+
+ float tmp[2][4]; /* scratch space for LIT */
+
+ struct shine_tab shine_tab[MAX_SHINE_TAB];
+ struct lit_info lit_info[MAX_LIT_INFO];
+ unsigned now;
+
+
+ ushort fpu_rnd_nearest;
+ ushort fpu_rnd_neg_inf;
+ ushort fpu_restore;
+ ushort fpucntl; /* one of FPU_* above */
+
+ const float (*immediates)[4]; /* points to shader data */
+ const float (*constants)[4]; /* points to draw data */
+
+ const struct aos_buffer *buffer; /* points to ? */
+};
+
+
+
+
+struct aos_compilation {
+ struct x86_function *func;
+ struct draw_vs_varient_aos_sse *vaos;
+
+ unsigned insn_counter;
+ unsigned num_immediates;
+ unsigned count;
+ unsigned lit_count;
+
+ struct {
+ unsigned idx:16;
+ unsigned file:8;
+ unsigned dirty:8;
+ unsigned last_used;
+ } xmm[8];
+
+ unsigned x86_reg[2]; /* one of X86_* */
+
+ boolean input_fetched[PIPE_MAX_ATTRIBS];
+ unsigned output_last_write[PIPE_MAX_ATTRIBS];
+
+ boolean have_sse2;
+ boolean error;
+ short fpucntl;
+
+ /* these are actually known values, but putting them in a struct
+ * like this is helpful to keep them in sync across the file.
+ */
+ struct x86_reg tmp_EAX;
+ struct x86_reg idx_EBX; /* either start+i or &elt[i] */
+ struct x86_reg outbuf_ECX;
+ struct x86_reg machine_EDX;
+ struct x86_reg count_ESI; /* decrements to zero */
+ struct x86_reg temp_EBP;
+ struct x86_reg stack_ESP;
+};
+
+struct x86_reg aos_get_xmm_reg( struct aos_compilation *cp );
+void aos_release_xmm_reg( struct aos_compilation *cp, unsigned idx );
+
+void aos_adopt_xmm_reg( struct aos_compilation *cp,
+ struct x86_reg reg,
+ unsigned file,
+ unsigned idx,
+ unsigned dirty );
+
+void aos_spill_all( struct aos_compilation *cp );
+
+struct x86_reg aos_get_shader_reg( struct aos_compilation *cp,
+ unsigned file,
+ unsigned idx );
+
+boolean aos_init_inputs( struct aos_compilation *cp, boolean linear );
+boolean aos_fetch_inputs( struct aos_compilation *cp, boolean linear );
+boolean aos_incr_inputs( struct aos_compilation *cp, boolean linear );
+
+boolean aos_emit_outputs( struct aos_compilation *cp );
+
+
+#define IMM_ONES 0 /* 1, 1,1,1 */
+#define IMM_SWZ 1 /* 1,-1,0, 0xffffffff */
+#define IMM_IDENTITY 2 /* 0, 0,0,1 */
+#define IMM_INV_255 3 /* 1/255, 1/255, 1/255, 1/255 */
+#define IMM_255 4 /* 255, 255, 255, 255 */
+#define IMM_NEGS 5 /* -1,-1,-1,-1 */
+#define IMM_RSQ 6 /* -.5,1.5,_,_ */
+#define IMM_PSIZE 7 /* not really an immediate - updated each run */
+
+struct x86_reg aos_get_internal( struct aos_compilation *cp,
+ unsigned imm );
+struct x86_reg aos_get_internal_xmm( struct aos_compilation *cp,
+ unsigned imm );
+
+
+#define AOS_ERROR(cp, msg) \
+do { \
+ if (0) debug_printf("%s: x86 translation failed: %s\n", __FUNCTION__, msg); \
+ cp->error = 1; \
+} while (0)
+
+
+#define X86_NULL 0
+#define X86_IMMEDIATES 1
+#define X86_CONSTANTS 2
+#define X86_BUFFERS 3
+
+struct x86_reg aos_get_x86( struct aos_compilation *cp,
+ unsigned which_reg,
+ unsigned value );
+
+
+typedef void (PIPE_CDECL *vaos_run_elts_func)( struct aos_machine *,
+ const unsigned *elts,
+ unsigned count,
+ void *output_buffer);
+
+typedef void (PIPE_CDECL *vaos_run_linear_func)( struct aos_machine *,
+ unsigned start,
+ unsigned count,
+ void *output_buffer);
+
+
+struct draw_vs_varient_aos_sse {
+ struct draw_vs_varient base;
+ struct draw_context *draw;
+
+ struct aos_buffer *buffer;
+ unsigned nr_vb;
+
+ vaos_run_linear_func gen_run_linear;
+ vaos_run_elts_func gen_run_elts;
+
+
+ struct x86_function func[2];
+};
+
+
+#endif
+
+#endif
+
diff --git a/src/gallium/auxiliary/draw/draw_vs_aos_io.c b/src/gallium/auxiliary/draw/draw_vs_aos_io.c
new file mode 100644
index 0000000000..a6eb37d128
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_aos_io.c
@@ -0,0 +1,462 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_exec.h"
+#include "draw_vs.h"
+#include "draw_vs_aos.h"
+#include "draw_vertex.h"
+
+#include "rtasm/rtasm_x86sse.h"
+
+#ifdef PIPE_ARCH_X86
+
+/* Note - don't yet have to worry about interacting with the code in
+ * draw_vs_aos.c as there is no intermingling of generated code...
+ * That may have to change, we'll see.
+ */
+static void emit_load_R32G32B32A32( struct aos_compilation *cp,
+ struct x86_reg data,
+ struct x86_reg src_ptr )
+{
+ sse_movups(cp->func, data, src_ptr);
+}
+
+static void emit_load_R32G32B32( struct aos_compilation *cp,
+ struct x86_reg data,
+ struct x86_reg src_ptr )
+{
+#if 1
+ sse_movss(cp->func, data, x86_make_disp(src_ptr, 8));
+ /* data = z ? ? ? */
+ sse_shufps(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ), SHUF(X,Y,Z,W) );
+ /* data = z ? 0 1 */
+ sse_shufps(cp->func, data, data, SHUF(Y,Z,X,W) );
+ /* data = ? 0 z 1 */
+ sse_movlps(cp->func, data, src_ptr);
+ /* data = x y z 1 */
+#else
+ sse_movups(cp->func, data, src_ptr);
+ /* data = x y z ? */
+ sse2_pshufd(cp->func, data, data, SHUF(W,X,Y,Z) );
+ /* data = ? x y z */
+ sse_movss(cp->func, data, aos_get_internal_xmm( cp, IMM_ONES ) );
+ /* data = 1 x y z */
+ sse2_pshufd(cp->func, data, data, SHUF(Y,Z,W,X) );
+ /* data = x y z 1 */
+#endif
+}
+
+static void emit_load_R32G32( struct aos_compilation *cp,
+ struct x86_reg data,
+ struct x86_reg src_ptr )
+{
+ sse_movups(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ) );
+ sse_movlps(cp->func, data, src_ptr);
+}
+
+
+static void emit_load_R32( struct aos_compilation *cp,
+ struct x86_reg data,
+ struct x86_reg src_ptr )
+{
+ sse_movss(cp->func, data, src_ptr);
+ sse_orps(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ) );
+}
+
+
+static void emit_load_R8G8B8A8_UNORM( struct aos_compilation *cp,
+ struct x86_reg data,
+ struct x86_reg src_ptr )
+{
+ sse_movss(cp->func, data, src_ptr);
+ sse2_punpcklbw(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ));
+ sse2_punpcklbw(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ));
+ sse2_cvtdq2ps(cp->func, data, data);
+ sse_mulps(cp->func, data, aos_get_internal(cp, IMM_INV_255));
+}
+
+
+
+/* Extended swizzles? Maybe later.
+ */
+static void emit_swizzle( struct aos_compilation *cp,
+ struct x86_reg dest,
+ struct x86_reg src,
+ ubyte shuffle )
+{
+ sse_shufps(cp->func, dest, src, shuffle);
+}
+
+
+
+static boolean get_buffer_ptr( struct aos_compilation *cp,
+ boolean linear,
+ unsigned buf_idx,
+ struct x86_reg elt,
+ struct x86_reg ptr)
+{
+ struct x86_reg buf = x86_make_disp(aos_get_x86( cp, 0, X86_BUFFERS ),
+ buf_idx * sizeof(struct aos_buffer));
+
+ struct x86_reg buf_stride = x86_make_disp(buf,
+ Offset(struct aos_buffer, stride));
+ if (linear) {
+ struct x86_reg buf_ptr = x86_make_disp(buf,
+ Offset(struct aos_buffer, ptr));
+
+
+ /* Calculate pointer to current attrib:
+ */
+ x86_mov(cp->func, ptr, buf_ptr);
+ x86_mov(cp->func, elt, buf_stride);
+ x86_add(cp->func, elt, ptr);
+ if (buf_idx == 0) sse_prefetchnta(cp->func, x86_make_disp(elt, 192));
+ x86_mov(cp->func, buf_ptr, elt);
+ }
+ else {
+ struct x86_reg buf_base_ptr = x86_make_disp(buf,
+ Offset(struct aos_buffer, base_ptr));
+
+
+ /* Calculate pointer to current attrib:
+ */
+ x86_mov(cp->func, ptr, buf_stride);
+ x86_imul(cp->func, ptr, elt);
+ x86_add(cp->func, ptr, buf_base_ptr);
+ }
+
+ cp->insn_counter++;
+
+ return TRUE;
+}
+
+
+static boolean load_input( struct aos_compilation *cp,
+ unsigned idx,
+ struct x86_reg bufptr )
+{
+ unsigned format = cp->vaos->base.key.element[idx].in.format;
+ unsigned offset = cp->vaos->base.key.element[idx].in.offset;
+ struct x86_reg dataXMM = aos_get_xmm_reg(cp);
+
+ /* Figure out source pointer address:
+ */
+ struct x86_reg src = x86_make_disp(bufptr, offset);
+
+ aos_adopt_xmm_reg( cp,
+ dataXMM,
+ TGSI_FILE_INPUT,
+ idx,
+ TRUE );
+
+ switch (format) {
+ case PIPE_FORMAT_R32_FLOAT:
+ emit_load_R32(cp, dataXMM, src);
+ break;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ emit_load_R32G32(cp, dataXMM, src);
+ break;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ emit_load_R32G32B32(cp, dataXMM, src);
+ break;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ emit_load_R32G32B32A32(cp, dataXMM, src);
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ emit_load_R8G8B8A8_UNORM(cp, dataXMM, src);
+ emit_swizzle(cp, dataXMM, dataXMM, SHUF(Z,Y,X,W));
+ break;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ emit_load_R8G8B8A8_UNORM(cp, dataXMM, src);
+ break;
+ default:
+ AOS_ERROR(cp, "unhandled input format");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static boolean load_inputs( struct aos_compilation *cp,
+ unsigned buffer,
+ struct x86_reg ptr )
+{
+ unsigned i;
+
+ for (i = 0; i < cp->vaos->base.key.nr_inputs; i++) {
+ if (cp->vaos->base.key.element[i].in.buffer == buffer) {
+
+ if (!load_input( cp, i, ptr ))
+ return FALSE;
+
+ cp->insn_counter++;
+ }
+ }
+
+ return TRUE;
+}
+
+boolean aos_init_inputs( struct aos_compilation *cp, boolean linear )
+{
+ unsigned i;
+ for (i = 0; i < cp->vaos->nr_vb; i++) {
+ struct x86_reg buf = x86_make_disp(aos_get_x86( cp, 0, X86_BUFFERS ),
+ i * sizeof(struct aos_buffer));
+
+ struct x86_reg buf_base_ptr = x86_make_disp(buf,
+ Offset(struct aos_buffer, base_ptr));
+
+ if (cp->vaos->base.key.const_vbuffers & (1<<i)) {
+ struct x86_reg ptr = cp->tmp_EAX;
+
+ x86_mov(cp->func, ptr, buf_base_ptr);
+
+ /* Load all inputs for this constant vertex buffer
+ */
+ load_inputs( cp, i, x86_deref(ptr) );
+
+ /* Then just force them out to aos_machine.input[]
+ */
+ aos_spill_all( cp );
+
+ }
+ else if (linear) {
+
+ struct x86_reg elt = cp->idx_EBX;
+ struct x86_reg ptr = cp->tmp_EAX;
+
+ struct x86_reg buf_stride = x86_make_disp(buf,
+ Offset(struct aos_buffer, stride));
+
+ struct x86_reg buf_ptr = x86_make_disp(buf,
+ Offset(struct aos_buffer, ptr));
+
+
+ /* Calculate pointer to current attrib:
+ */
+ x86_mov(cp->func, ptr, buf_stride);
+ x86_imul(cp->func, ptr, elt);
+ x86_add(cp->func, ptr, buf_base_ptr);
+
+
+ /* In the linear case, keep the buffer pointer instead of the
+ * index number.
+ */
+ if (cp->vaos->nr_vb == 1)
+ x86_mov( cp->func, elt, ptr );
+ else
+ x86_mov( cp->func, buf_ptr, ptr );
+
+ cp->insn_counter++;
+ }
+ }
+
+ return TRUE;
+}
+
+boolean aos_fetch_inputs( struct aos_compilation *cp, boolean linear )
+{
+ unsigned j;
+
+ for (j = 0; j < cp->vaos->nr_vb; j++) {
+ if (cp->vaos->base.key.const_vbuffers & (1<<j)) {
+ /* just retreive pre-transformed input */
+ }
+ else if (linear && cp->vaos->nr_vb == 1) {
+ load_inputs( cp, 0, cp->idx_EBX );
+ }
+ else {
+ struct x86_reg elt = linear ? cp->idx_EBX : x86_deref(cp->idx_EBX);
+ struct x86_reg ptr = cp->tmp_EAX;
+
+ if (!get_buffer_ptr( cp, linear, j, elt, ptr ))
+ return FALSE;
+
+ if (!load_inputs( cp, j, ptr ))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+boolean aos_incr_inputs( struct aos_compilation *cp, boolean linear )
+{
+ if (linear && cp->vaos->nr_vb == 1) {
+ struct x86_reg stride = x86_make_disp(aos_get_x86( cp, 0, X86_BUFFERS ),
+ (0 * sizeof(struct aos_buffer) +
+ Offset(struct aos_buffer, stride)));
+
+ x86_add(cp->func, cp->idx_EBX, stride);
+ sse_prefetchnta(cp->func, x86_make_disp(cp->idx_EBX, 192));
+ }
+ else if (linear) {
+ /* Nothing to do */
+ }
+ else {
+ x86_lea(cp->func, cp->idx_EBX, x86_make_disp(cp->idx_EBX, 4));
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+
+static void emit_store_R32G32B32A32( struct aos_compilation *cp,
+ struct x86_reg dst_ptr,
+ struct x86_reg dataXMM )
+{
+ sse_movups(cp->func, dst_ptr, dataXMM);
+}
+
+static void emit_store_R32G32B32( struct aos_compilation *cp,
+ struct x86_reg dst_ptr,
+ struct x86_reg dataXMM )
+{
+ sse_movlps(cp->func, dst_ptr, dataXMM);
+ sse_shufps(cp->func, dataXMM, dataXMM, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
+ sse_movss(cp->func, x86_make_disp(dst_ptr,8), dataXMM);
+}
+
+static void emit_store_R32G32( struct aos_compilation *cp,
+ struct x86_reg dst_ptr,
+ struct x86_reg dataXMM )
+{
+ sse_movlps(cp->func, dst_ptr, dataXMM);
+}
+
+static void emit_store_R32( struct aos_compilation *cp,
+ struct x86_reg dst_ptr,
+ struct x86_reg dataXMM )
+{
+ sse_movss(cp->func, dst_ptr, dataXMM);
+}
+
+
+
+static void emit_store_R8G8B8A8_UNORM( struct aos_compilation *cp,
+ struct x86_reg dst_ptr,
+ struct x86_reg dataXMM )
+{
+ sse_mulps(cp->func, dataXMM, aos_get_internal(cp, IMM_255));
+ sse2_cvtps2dq(cp->func, dataXMM, dataXMM);
+ sse2_packssdw(cp->func, dataXMM, dataXMM);
+ sse2_packuswb(cp->func, dataXMM, dataXMM);
+ sse_movss(cp->func, dst_ptr, dataXMM);
+}
+
+
+
+
+
+static boolean emit_output( struct aos_compilation *cp,
+ struct x86_reg ptr,
+ struct x86_reg dataXMM,
+ unsigned format )
+{
+ switch (format) {
+ case EMIT_1F:
+ case EMIT_1F_PSIZE:
+ emit_store_R32(cp, ptr, dataXMM);
+ break;
+ case EMIT_2F:
+ emit_store_R32G32(cp, ptr, dataXMM);
+ break;
+ case EMIT_3F:
+ emit_store_R32G32B32(cp, ptr, dataXMM);
+ break;
+ case EMIT_4F:
+ emit_store_R32G32B32A32(cp, ptr, dataXMM);
+ break;
+ case EMIT_4UB:
+ if (1) {
+ emit_swizzle(cp, dataXMM, dataXMM, SHUF(Z,Y,X,W));
+ emit_store_R8G8B8A8_UNORM(cp, ptr, dataXMM);
+ }
+ else {
+ emit_store_R8G8B8A8_UNORM(cp, ptr, dataXMM);
+ }
+ break;
+ default:
+ AOS_ERROR(cp, "unhandled output format");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+boolean aos_emit_outputs( struct aos_compilation *cp )
+{
+ unsigned i;
+
+ for (i = 0; i < cp->vaos->base.key.nr_outputs; i++) {
+ unsigned format = cp->vaos->base.key.element[i].out.format;
+ unsigned offset = cp->vaos->base.key.element[i].out.offset;
+ unsigned vs_output = cp->vaos->base.key.element[i].out.vs_output;
+
+ struct x86_reg data;
+
+ if (format == EMIT_1F_PSIZE) {
+ data = aos_get_internal_xmm( cp, IMM_PSIZE );
+ }
+ else {
+ data = aos_get_shader_reg( cp,
+ TGSI_FILE_OUTPUT,
+ vs_output );
+ }
+
+ if (data.file != file_XMM) {
+ struct x86_reg tmp = aos_get_xmm_reg( cp );
+ sse_movaps(cp->func, tmp, data);
+ data = tmp;
+ }
+
+ if (!emit_output( cp,
+ x86_make_disp( cp->outbuf_ECX, offset ),
+ data,
+ format ))
+ return FALSE;
+
+ aos_release_xmm_reg( cp, data.idx );
+
+ cp->insn_counter++;
+ }
+
+ return TRUE;
+}
+
+#endif
diff --git a/src/gallium/auxiliary/draw/draw_vs_aos_machine.c b/src/gallium/auxiliary/draw/draw_vs_aos_machine.c
new file mode 100644
index 0000000000..3240e3745d
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_aos_machine.c
@@ -0,0 +1,324 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_config.h"
+
+
+#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_exec.h"
+#include "draw_vs.h"
+#include "draw_vs_aos.h"
+#include "draw_vertex.h"
+
+#ifdef PIPE_ARCH_X86
+
+#include "rtasm/rtasm_x86sse.h"
+
+
+#define X87_CW_EXCEPTION_INV_OP (1<<0)
+#define X87_CW_EXCEPTION_DENORM_OP (1<<1)
+#define X87_CW_EXCEPTION_ZERO_DIVIDE (1<<2)
+#define X87_CW_EXCEPTION_OVERFLOW (1<<3)
+#define X87_CW_EXCEPTION_UNDERFLOW (1<<4)
+#define X87_CW_EXCEPTION_PRECISION (1<<5)
+#define X87_CW_PRECISION_SINGLE (0<<8)
+#define X87_CW_PRECISION_RESERVED (1<<8)
+#define X87_CW_PRECISION_DOUBLE (2<<8)
+#define X87_CW_PRECISION_DOUBLE_EXT (3<<8)
+#define X87_CW_PRECISION_MASK (3<<8)
+#define X87_CW_ROUND_NEAREST (0<<10)
+#define X87_CW_ROUND_DOWN (1<<10)
+#define X87_CW_ROUND_UP (2<<10)
+#define X87_CW_ROUND_ZERO (3<<10)
+#define X87_CW_ROUND_MASK (3<<10)
+#define X87_CW_INFINITY (1<<12)
+
+
+void PIPE_CDECL aos_do_lit( struct aos_machine *machine,
+ float *result,
+ const float *in,
+ unsigned count )
+{
+ if (in[0] > 0)
+ {
+ if (in[1] <= 0.0)
+ {
+ result[0] = 1.0F;
+ result[1] = in[0];
+ result[2] = 0.0F;
+ result[3] = 1.0F;
+ }
+ else
+ {
+ const float epsilon = 1.0F / 256.0F;
+ float exponent = CLAMP(in[3], -(128.0F - epsilon), (128.0F - epsilon));
+ result[0] = 1.0F;
+ result[1] = in[0];
+ result[2] = powf(in[1], exponent);
+ result[3] = 1.0;
+ }
+ }
+ else
+ {
+ result[0] = 1.0F;
+ result[1] = 0.0;
+ result[2] = 0.0;
+ result[3] = 1.0F;
+ }
+}
+
+
+static void PIPE_CDECL do_lit_lut( struct aos_machine *machine,
+ float *result,
+ const float *in,
+ unsigned count )
+{
+ if (in[0] > 0)
+ {
+ if (in[1] <= 0.0)
+ {
+ result[0] = 1.0F;
+ result[1] = in[0];
+ result[2] = 0.0F;
+ result[3] = 1.0F;
+ return;
+ }
+
+ if (machine->lit_info[count].shine_tab->exponent != in[3]) {
+ machine->lit_info[count].func = aos_do_lit;
+ goto no_luck;
+ }
+
+ if (in[1] <= 1.0)
+ {
+ const float *tab = machine->lit_info[count].shine_tab->values;
+ float f = in[1] * 256;
+ int k = (int)f;
+ float frac = f - (float)k;
+
+ result[0] = 1.0F;
+ result[1] = in[0];
+ result[2] = tab[k] + frac*(tab[k+1]-tab[k]);
+ result[3] = 1.0;
+ return;
+ }
+
+ no_luck:
+ {
+ const float epsilon = 1.0F / 256.0F;
+ float exponent = CLAMP(in[3], -(128.0F - epsilon), (128.0F - epsilon));
+ result[0] = 1.0F;
+ result[1] = in[0];
+ result[2] = powf(in[1], exponent);
+ result[3] = 1.0;
+ }
+ }
+ else
+ {
+ result[0] = 1.0F;
+ result[1] = 0.0;
+ result[2] = 0.0;
+ result[3] = 1.0F;
+ }
+}
+
+
+static void do_populate_lut( struct shine_tab *tab,
+ float unclamped_exponent )
+{
+ const float epsilon = 1.0F / 256.0F;
+ float exponent = CLAMP(unclamped_exponent, -(128.0F - epsilon), (128.0F - epsilon));
+ unsigned i;
+
+ tab->exponent = unclamped_exponent; /* for later comparison */
+
+ tab->values[0] = 0;
+ if (exponent == 0) {
+ for (i = 1; i < 258; i++) {
+ tab->values[i] = 1.0;
+ }
+ }
+ else {
+ for (i = 1; i < 258; i++) {
+ tab->values[i] = powf((float)i * epsilon, exponent);
+ }
+ }
+}
+
+
+
+
+static void PIPE_CDECL populate_lut( struct aos_machine *machine,
+ float *result,
+ const float *in,
+ unsigned count )
+{
+ unsigned i, tab;
+
+ /* Search for an existing table for this value. Note that without
+ * static analysis we don't really know if in[3] will be constant,
+ * but it usually is...
+ */
+ for (tab = 0; tab < 4; tab++) {
+ if (machine->shine_tab[tab].exponent == in[3]) {
+ goto found;
+ }
+ }
+
+ for (tab = 0, i = 1; i < 4; i++) {
+ if (machine->shine_tab[i].last_used < machine->shine_tab[tab].last_used)
+ tab = i;
+ }
+
+ if (machine->shine_tab[tab].last_used == machine->now) {
+ /* No unused tables (this is not a ffvertex program...). Just
+ * call pow each time:
+ */
+ machine->lit_info[count].func = aos_do_lit;
+ machine->lit_info[count].func( machine, result, in, count );
+ return;
+ }
+ else {
+ do_populate_lut( &machine->shine_tab[tab], in[3] );
+ }
+
+ found:
+ machine->shine_tab[tab].last_used = machine->now;
+ machine->lit_info[count].shine_tab = &machine->shine_tab[tab];
+ machine->lit_info[count].func = do_lit_lut;
+ machine->lit_info[count].func( machine, result, in, count );
+}
+
+
+void draw_vs_aos_machine_constants( struct aos_machine *machine,
+ const float (*constants)[4] )
+{
+ machine->constants = constants;
+
+ {
+ unsigned i;
+ for (i = 0; i < MAX_LIT_INFO; i++) {
+ machine->lit_info[i].func = populate_lut;
+ machine->now++;
+ }
+ }
+}
+
+
+void draw_vs_aos_machine_viewport( struct aos_machine *machine,
+ const struct pipe_viewport_state *viewport )
+{
+ memcpy(machine->scale, viewport->scale, 4 * sizeof(float));
+ memcpy(machine->translate, viewport->translate, 4 * sizeof(float));
+}
+
+
+
+void draw_vs_aos_machine_destroy( struct aos_machine *machine )
+{
+ align_free(machine);
+}
+
+struct aos_machine *draw_vs_aos_machine( void )
+{
+ struct aos_machine *machine;
+ unsigned i;
+ float inv = 1.0f/255.0f;
+ float f255 = 255.0f;
+
+ machine = align_malloc(sizeof(struct aos_machine), 16);
+ if (!machine)
+ return NULL;
+
+ memset(machine, 0, sizeof(*machine));
+
+ ASSIGN_4V(machine->internal[IMM_SWZ], 1.0f, -1.0f, 0.0f, 1.0f);
+ *(unsigned *)&machine->internal[IMM_SWZ][3] = 0xffffffff;
+
+ ASSIGN_4V(machine->internal[IMM_ONES], 1.0f, 1.0f, 1.0f, 1.0f);
+ ASSIGN_4V(machine->internal[IMM_NEGS], -1.0f, -1.0f, -1.0f, -1.0f);
+ ASSIGN_4V(machine->internal[IMM_IDENTITY], 0.0f, 0.0f, 0.0f, 1.0f);
+ ASSIGN_4V(machine->internal[IMM_INV_255], inv, inv, inv, inv);
+ ASSIGN_4V(machine->internal[IMM_255], f255, f255, f255, f255);
+ ASSIGN_4V(machine->internal[IMM_RSQ], -.5f, 1.5f, 0.0f, 0.0f);
+
+
+ machine->fpu_rnd_nearest = (X87_CW_EXCEPTION_INV_OP |
+ X87_CW_EXCEPTION_DENORM_OP |
+ X87_CW_EXCEPTION_ZERO_DIVIDE |
+ X87_CW_EXCEPTION_OVERFLOW |
+ X87_CW_EXCEPTION_UNDERFLOW |
+ X87_CW_EXCEPTION_PRECISION |
+ (1<<6) |
+ X87_CW_ROUND_NEAREST |
+ X87_CW_PRECISION_DOUBLE_EXT);
+
+ assert(machine->fpu_rnd_nearest == 0x37f);
+
+ machine->fpu_rnd_neg_inf = (X87_CW_EXCEPTION_INV_OP |
+ X87_CW_EXCEPTION_DENORM_OP |
+ X87_CW_EXCEPTION_ZERO_DIVIDE |
+ X87_CW_EXCEPTION_OVERFLOW |
+ X87_CW_EXCEPTION_UNDERFLOW |
+ X87_CW_EXCEPTION_PRECISION |
+ (1<<6) |
+ X87_CW_ROUND_DOWN |
+ X87_CW_PRECISION_DOUBLE_EXT);
+
+ for (i = 0; i < MAX_SHINE_TAB; i++)
+ do_populate_lut( &machine->shine_tab[i], 1.0f );
+
+ return machine;
+}
+
+#else
+
+void draw_vs_aos_machine_viewport( struct aos_machine *machine,
+ const struct pipe_viewport_state *viewport )
+{
+}
+
+void draw_vs_aos_machine_constants( struct aos_machine *machine,
+ const float (*constants)[4] )
+{
+}
+
+void draw_vs_aos_machine_destroy( struct aos_machine *machine )
+{
+}
+
+struct aos_machine *draw_vs_aos_machine( void )
+{
+ return NULL;
+}
+#endif
+
diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c
new file mode 100644
index 0000000000..41cc802613
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_exec.c
@@ -0,0 +1,208 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "draw_private.h"
+#include "draw_context.h"
+#include "draw_vs.h"
+
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
+#include "tgsi/tgsi_exec.h"
+
+
+struct exec_vertex_shader {
+ struct draw_vertex_shader base;
+ struct tgsi_exec_machine *machine;
+};
+
+static struct exec_vertex_shader *exec_vertex_shader( struct draw_vertex_shader *vs )
+{
+ return (struct exec_vertex_shader *)vs;
+}
+
+
+/* Not required for run_linear.
+ */
+static void
+vs_exec_prepare( struct draw_vertex_shader *shader,
+ struct draw_context *draw )
+{
+ struct exec_vertex_shader *evs = exec_vertex_shader(shader);
+
+ /* Specify the vertex program to interpret/execute.
+ * Avoid rebinding when possible.
+ */
+ if (evs->machine->Tokens != shader->state.tokens) {
+ tgsi_exec_machine_bind_shader(evs->machine,
+ shader->state.tokens,
+ draw->vs.num_samplers,
+ draw->vs.samplers);
+ }
+}
+
+
+
+
+/* Simplified vertex shader interface for the pt paths. Given the
+ * complexity of code-generating all the above operations together,
+ * it's time to try doing all the other stuff separately.
+ */
+static void
+vs_exec_run_linear( struct draw_vertex_shader *shader,
+ const float (*input)[4],
+ float (*output)[4],
+ const float (*constants)[4],
+ unsigned count,
+ unsigned input_stride,
+ unsigned output_stride )
+{
+ struct exec_vertex_shader *evs = exec_vertex_shader(shader);
+ struct tgsi_exec_machine *machine = evs->machine;
+ unsigned int i, j;
+ unsigned slot;
+
+ machine->Consts = constants;
+
+ for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
+ unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
+
+ /* Swizzle inputs.
+ */
+ for (j = 0; j < max_vertices; j++) {
+#if 0
+ debug_printf("%d) Input vert:\n", i + j);
+ for (slot = 0; slot < shader->info.num_inputs; slot++) {
+ debug_printf("\t%d: %f %f %f %f\n", slot,
+ input[slot][0],
+ input[slot][1],
+ input[slot][2],
+ input[slot][3]);
+ }
+#endif
+
+ for (slot = 0; slot < shader->info.num_inputs; slot++) {
+#if 0
+ assert(!util_is_inf_or_nan(input[slot][0]));
+ assert(!util_is_inf_or_nan(input[slot][1]));
+ assert(!util_is_inf_or_nan(input[slot][2]));
+ assert(!util_is_inf_or_nan(input[slot][3]));
+#endif
+ machine->Inputs[slot].xyzw[0].f[j] = input[slot][0];
+ machine->Inputs[slot].xyzw[1].f[j] = input[slot][1];
+ machine->Inputs[slot].xyzw[2].f[j] = input[slot][2];
+ machine->Inputs[slot].xyzw[3].f[j] = input[slot][3];
+ }
+
+ input = (const float (*)[4])((const char *)input + input_stride);
+ }
+
+ tgsi_set_exec_mask(machine,
+ 1,
+ max_vertices > 1,
+ max_vertices > 2,
+ max_vertices > 3);
+
+ /* run interpreter */
+ tgsi_exec_machine_run( machine );
+
+ /* Unswizzle all output results.
+ */
+ for (j = 0; j < max_vertices; j++) {
+ for (slot = 0; slot < shader->info.num_outputs; slot++) {
+ output[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
+ output[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
+ output[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
+ output[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
+
+ }
+
+#if 0
+ debug_printf("%d) Post xform vert:\n", i + j);
+ for (slot = 0; slot < shader->info.num_outputs; slot++) {
+ debug_printf("\t%d: %f %f %f %f\n", slot,
+ output[slot][0],
+ output[slot][1],
+ output[slot][2],
+ output[slot][3]);
+ assert(!util_is_inf_or_nan(output[slot][0]));
+ }
+#endif
+
+ output = (float (*)[4])((char *)output + output_stride);
+ }
+
+ }
+}
+
+
+
+
+static void
+vs_exec_delete( struct draw_vertex_shader *dvs )
+{
+ FREE((void*) dvs->state.tokens);
+ FREE( dvs );
+}
+
+
+struct draw_vertex_shader *
+draw_create_vs_exec(struct draw_context *draw,
+ const struct pipe_shader_state *state)
+{
+ struct exec_vertex_shader *vs = CALLOC_STRUCT( exec_vertex_shader );
+
+ if (vs == NULL)
+ return NULL;
+
+ /* we make a private copy of the tokens */
+ vs->base.state.tokens = tgsi_dup_tokens(state->tokens);
+ if (!vs->base.state.tokens) {
+ FREE(vs);
+ return NULL;
+ }
+
+ tgsi_scan_shader(state->tokens, &vs->base.info);
+
+ vs->base.draw = draw;
+ vs->base.prepare = vs_exec_prepare;
+ vs->base.run_linear = vs_exec_run_linear;
+ vs->base.delete = vs_exec_delete;
+ vs->base.create_varient = draw_vs_varient_generic;
+ vs->machine = draw->vs.machine;
+
+ return &vs->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c
new file mode 100644
index 0000000000..b3535c0e48
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
@@ -0,0 +1,161 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw_private.h"
+#include "draw_context.h"
+#include "draw_vs.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#ifdef MESA_LLVM
+
+#include "gallivm/gallivm.h"
+
+struct draw_llvm_vertex_shader {
+ struct draw_vertex_shader base;
+ struct gallivm_prog *llvm_prog;
+ struct tgsi_exec_machine *machine;
+};
+
+
+static void
+vs_llvm_prepare( struct draw_vertex_shader *base,
+ struct draw_context *draw )
+{
+}
+
+
+
+
+static void
+vs_llvm_run_linear( struct draw_vertex_shader *base,
+ const float (*input)[4],
+ float (*output)[4],
+ const float (*constants)[4],
+ unsigned count,
+ unsigned input_stride,
+ unsigned output_stride )
+{
+ struct draw_llvm_vertex_shader *shader =
+ (struct draw_llvm_vertex_shader *)base;
+
+ gallivm_cpu_vs_exec(shader->llvm_prog, shader->machine,
+ input, base->info.num_inputs, output, base->info.num_outputs,
+ constants, count, input_stride, output_stride);
+}
+
+
+
+static void
+vs_llvm_delete( struct draw_vertex_shader *base )
+{
+ struct draw_llvm_vertex_shader *shader =
+ (struct draw_llvm_vertex_shader *)base;
+
+ /* Do something to free compiled shader:
+ */
+
+ FREE( (void*) shader->base.state.tokens );
+ FREE( shader );
+}
+
+
+
+
+struct draw_vertex_shader *
+draw_create_vs_llvm(struct draw_context *draw,
+ const struct pipe_shader_state *templ)
+{
+ struct draw_llvm_vertex_shader *vs;
+
+ vs = CALLOC_STRUCT( draw_llvm_vertex_shader );
+ if (vs == NULL)
+ return NULL;
+
+ /* we make a private copy of the tokens */
+ vs->base.state.tokens = tgsi_dup_tokens(templ->tokens);
+ if (!vs->base.state.tokens) {
+ FREE(vs);
+ return NULL;
+ }
+
+ tgsi_scan_shader(vs->base.state.tokens, &vs->base.info);
+
+ vs->base.draw = draw;
+ vs->base.prepare = vs_llvm_prepare;
+ vs->base.create_varient = draw_vs_varient_generic;
+ vs->base.run_linear = vs_llvm_run_linear;
+ vs->base.delete = vs_llvm_delete;
+ vs->machine = draw->vs.machine;
+
+ {
+ struct gallivm_ir *ir = gallivm_ir_new(GALLIVM_VS);
+ gallivm_ir_set_layout(ir, GALLIVM_SOA);
+ gallivm_ir_set_components(ir, 4);
+ gallivm_ir_fill_from_tgsi(ir, vs->base.state.tokens);
+ vs->llvm_prog = gallivm_ir_compile(ir);
+ gallivm_ir_delete(ir);
+ }
+
+ draw->vs.engine = gallivm_global_cpu_engine();
+
+ /* XXX: Why are there two versions of this? Shouldn't creating the
+ * engine be a separate operation to compiling a shader?
+ */
+ if (!draw->vs.engine) {
+ draw->vs.engine = gallivm_cpu_engine_create(vs->llvm_prog);
+ }
+ else {
+ gallivm_cpu_jit_compile(draw->vs.engine, vs->llvm_prog);
+ }
+
+ return &vs->base;
+}
+
+
+
+
+
+#else
+
+struct draw_vertex_shader *
+draw_create_vs_llvm(struct draw_context *draw,
+ const struct pipe_shader_state *shader)
+{
+ return NULL;
+}
+
+#endif
diff --git a/src/gallium/auxiliary/draw/draw_vs_ppc.c b/src/gallium/auxiliary/draw/draw_vs_ppc.c
new file mode 100644
index 0000000000..ad184bd696
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_ppc.c
@@ -0,0 +1,245 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_config.h"
+
+#include "draw_vs.h"
+
+#if defined(PIPE_ARCH_PPC)
+
+#include "pipe/p_shader_tokens.h"
+
+#include "draw_private.h"
+#include "draw_context.h"
+
+#include "rtasm/rtasm_cpu.h"
+#include "rtasm/rtasm_ppc.h"
+#include "tgsi/tgsi_ppc.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_exec.h"
+
+
+
+typedef void (PIPE_CDECL *codegen_function) (float (*inputs)[4][4],
+ float (*outputs)[4][4],
+ float (*temps)[4][4],
+ float (*immeds)[4],
+ float (*consts)[4],
+ const float *builtins);
+
+
+struct draw_ppc_vertex_shader {
+ struct draw_vertex_shader base;
+ struct ppc_function ppc_program;
+
+ codegen_function func;
+};
+
+
+static void
+vs_ppc_prepare( struct draw_vertex_shader *base,
+ struct draw_context *draw )
+{
+ /* nothing */
+}
+
+
+/**
+ * Simplified vertex shader interface for the pt paths. Given the
+ * complexity of code-generating all the above operations together,
+ * it's time to try doing all the other stuff separately.
+ */
+static void
+vs_ppc_run_linear( struct draw_vertex_shader *base,
+ const float (*input)[4],
+ float (*output)[4],
+ const float (*constants)[4],
+ unsigned count,
+ unsigned input_stride,
+ unsigned output_stride )
+{
+ struct draw_ppc_vertex_shader *shader = (struct draw_ppc_vertex_shader *)base;
+ unsigned int i;
+
+#define MAX_VERTICES 4
+
+ /* loop over verts */
+ for (i = 0; i < count; i += MAX_VERTICES) {
+ const uint max_vertices = MIN2(MAX_VERTICES, count - i);
+ float inputs_soa[PIPE_MAX_SHADER_INPUTS][4][4] ALIGN16_ATTRIB;
+ float outputs_soa[PIPE_MAX_SHADER_OUTPUTS][4][4] ALIGN16_ATTRIB;
+ float temps_soa[TGSI_EXEC_NUM_TEMPS][4][4] ALIGN16_ATTRIB;
+ uint attr;
+
+ /* convert (up to) four input verts to SoA format */
+ for (attr = 0; attr < base->info.num_inputs; attr++) {
+ const float *vIn = (const float *) input;
+ uint vert;
+ for (vert = 0; vert < max_vertices; vert++) {
+#if 0
+ if (attr==0)
+ printf("Input v%d a%d: %f %f %f %f\n",
+ vert, attr, vIn[0], vIn[1], vIn[2], vIn[3]);
+#endif
+ inputs_soa[attr][0][vert] = vIn[attr * 4 + 0];
+ inputs_soa[attr][1][vert] = vIn[attr * 4 + 1];
+ inputs_soa[attr][2][vert] = vIn[attr * 4 + 2];
+ inputs_soa[attr][3][vert] = vIn[attr * 4 + 3];
+ vIn += input_stride / 4;
+ }
+ }
+
+ /* run compiled shader
+ */
+ shader->func(inputs_soa, outputs_soa, temps_soa,
+ (float (*)[4]) shader->base.immediates,
+ (float (*)[4]) constants,
+ ppc_builtin_constants);
+
+ /* convert (up to) four output verts from SoA back to AoS format */
+ for (attr = 0; attr < base->info.num_outputs; attr++) {
+ float *vOut = (float *) output;
+ uint vert;
+ for (vert = 0; vert < max_vertices; vert++) {
+ vOut[attr * 4 + 0] = outputs_soa[attr][0][vert];
+ vOut[attr * 4 + 1] = outputs_soa[attr][1][vert];
+ vOut[attr * 4 + 2] = outputs_soa[attr][2][vert];
+ vOut[attr * 4 + 3] = outputs_soa[attr][3][vert];
+#if 0
+ if (attr==0)
+ printf("Output v%d a%d: %f %f %f %f\n",
+ vert, attr, vOut[0], vOut[1], vOut[2], vOut[3]);
+#endif
+ vOut += output_stride / 4;
+ }
+ }
+
+ /* advance to next group of four input/output verts */
+ input = (const float (*)[4])((const char *)input + input_stride * max_vertices);
+ output = (float (*)[4])((char *)output + output_stride * max_vertices);
+ }
+}
+
+
+static void
+vs_ppc_delete( struct draw_vertex_shader *base )
+{
+ struct draw_ppc_vertex_shader *shader = (struct draw_ppc_vertex_shader *)base;
+
+ ppc_release_func( &shader->ppc_program );
+
+ align_free( (void *) shader->base.immediates );
+
+ FREE( (void*) shader->base.state.tokens );
+ FREE( shader );
+}
+
+
+struct draw_vertex_shader *
+draw_create_vs_ppc(struct draw_context *draw,
+ const struct pipe_shader_state *templ)
+{
+ struct draw_ppc_vertex_shader *vs;
+
+ vs = CALLOC_STRUCT( draw_ppc_vertex_shader );
+ if (vs == NULL)
+ return NULL;
+
+ /* we make a private copy of the tokens */
+ vs->base.state.tokens = tgsi_dup_tokens(templ->tokens);
+ if (!vs->base.state.tokens)
+ goto fail;
+
+ tgsi_scan_shader(templ->tokens, &vs->base.info);
+
+ vs->base.draw = draw;
+#if 0
+ if (1)
+ vs->base.create_varient = draw_vs_varient_aos_ppc;
+ else
+#endif
+ vs->base.create_varient = draw_vs_varient_generic;
+ vs->base.prepare = vs_ppc_prepare;
+ vs->base.run_linear = vs_ppc_run_linear;
+ vs->base.delete = vs_ppc_delete;
+
+ vs->base.immediates = align_malloc(TGSI_EXEC_NUM_IMMEDIATES * 4 *
+ sizeof(float), 16);
+
+ ppc_init_func( &vs->ppc_program );
+
+#if 0
+ ppc_print_code(&vs->ppc_program, TRUE);
+ ppc_indent(&vs->ppc_program, 8);
+#endif
+
+ if (!tgsi_emit_ppc( (struct tgsi_token *) vs->base.state.tokens,
+ &vs->ppc_program,
+ (float (*)[4]) vs->base.immediates,
+ TRUE ))
+ goto fail;
+
+ vs->func = (codegen_function) ppc_get_func( &vs->ppc_program );
+ if (!vs->func) {
+ goto fail;
+ }
+
+ return &vs->base;
+
+fail:
+ /*
+ debug_error("tgsi_emit_ppc() failed, falling back to interpreter\n");
+ */
+
+ ppc_release_func( &vs->ppc_program );
+
+ FREE(vs);
+ return NULL;
+}
+
+
+
+#else /* PIPE_ARCH_PPC */
+
+
+struct draw_vertex_shader *
+draw_create_vs_ppc( struct draw_context *draw,
+ const struct pipe_shader_state *templ )
+{
+ return (void *) 0;
+}
+
+
+#endif /* PIPE_ARCH_PPC */
diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c
new file mode 100644
index 0000000000..702051387a
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_sse.c
@@ -0,0 +1,217 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_config.h"
+
+#include "draw_vs.h"
+
+#if defined(PIPE_ARCH_X86)
+
+#include "pipe/p_shader_tokens.h"
+
+#include "draw_private.h"
+#include "draw_context.h"
+
+#include "rtasm/rtasm_cpu.h"
+#include "rtasm/rtasm_x86sse.h"
+#include "tgsi/tgsi_sse2.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_exec.h"
+
+#define SSE_MAX_VERTICES 4
+
+
+struct draw_sse_vertex_shader {
+ struct draw_vertex_shader base;
+ struct x86_function sse2_program;
+
+ tgsi_sse2_vs_func func;
+
+ struct tgsi_exec_machine *machine;
+};
+
+
+static void
+vs_sse_prepare( struct draw_vertex_shader *base,
+ struct draw_context *draw )
+{
+ struct draw_sse_vertex_shader *shader = (struct draw_sse_vertex_shader *)base;
+ struct tgsi_exec_machine *machine = shader->machine;
+
+ machine->Samplers = draw->vs.samplers;
+}
+
+
+
+/* Simplified vertex shader interface for the pt paths. Given the
+ * complexity of code-generating all the above operations together,
+ * it's time to try doing all the other stuff separately.
+ */
+static void
+vs_sse_run_linear( struct draw_vertex_shader *base,
+ const float (*input)[4],
+ float (*output)[4],
+ const float (*constants)[4],
+ unsigned count,
+ unsigned input_stride,
+ unsigned output_stride )
+{
+ struct draw_sse_vertex_shader *shader = (struct draw_sse_vertex_shader *)base;
+ struct tgsi_exec_machine *machine = shader->machine;
+ unsigned int i;
+
+ /* By default, execute all channels. XXX move this inside the loop
+ * below when we support shader conditionals/loops.
+ */
+ tgsi_set_exec_mask(machine, 1, 1, 1, 1);
+
+ for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
+ unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
+
+ if (max_vertices < 4) {
+ /* disable the unused execution channels */
+ tgsi_set_exec_mask(machine,
+ 1,
+ max_vertices > 1,
+ max_vertices > 2,
+ 0);
+ }
+
+ /* run compiled shader
+ */
+ shader->func(machine,
+ constants,
+ shader->base.immediates,
+ input,
+ base->info.num_inputs,
+ input_stride,
+ output,
+ base->info.num_outputs,
+ output_stride );
+
+ input = (const float (*)[4])((const char *)input + input_stride * max_vertices);
+ output = (float (*)[4])((char *)output + output_stride * max_vertices);
+ }
+}
+
+
+
+
+static void
+vs_sse_delete( struct draw_vertex_shader *base )
+{
+ struct draw_sse_vertex_shader *shader = (struct draw_sse_vertex_shader *)base;
+
+ x86_release_func( &shader->sse2_program );
+
+ align_free( (void *) shader->base.immediates );
+
+ FREE( (void*) shader->base.state.tokens );
+ FREE( shader );
+}
+
+
+struct draw_vertex_shader *
+draw_create_vs_sse(struct draw_context *draw,
+ const struct pipe_shader_state *templ)
+{
+ struct draw_sse_vertex_shader *vs;
+
+ if (!rtasm_cpu_has_sse2())
+ return NULL;
+
+ vs = CALLOC_STRUCT( draw_sse_vertex_shader );
+ if (vs == NULL)
+ return NULL;
+
+ /* we make a private copy of the tokens */
+ vs->base.state.tokens = tgsi_dup_tokens(templ->tokens);
+ if (!vs->base.state.tokens)
+ goto fail;
+
+ tgsi_scan_shader(templ->tokens, &vs->base.info);
+
+ vs->base.draw = draw;
+ if (1)
+ vs->base.create_varient = draw_vs_varient_aos_sse;
+ else
+ vs->base.create_varient = draw_vs_varient_generic;
+ vs->base.prepare = vs_sse_prepare;
+ vs->base.run_linear = vs_sse_run_linear;
+ vs->base.delete = vs_sse_delete;
+
+ vs->base.immediates = align_malloc(TGSI_EXEC_NUM_IMMEDIATES * 4 *
+ sizeof(float), 16);
+
+ vs->machine = draw->vs.machine;
+
+ x86_init_func( &vs->sse2_program );
+
+ if (!tgsi_emit_sse2( (struct tgsi_token *) vs->base.state.tokens,
+ &vs->sse2_program,
+ (float (*)[4])vs->base.immediates,
+ TRUE ))
+ goto fail;
+
+ vs->func = (tgsi_sse2_vs_func) x86_get_func( &vs->sse2_program );
+ if (!vs->func) {
+ goto fail;
+ }
+
+ return &vs->base;
+
+fail:
+ debug_error("tgsi_emit_sse2() failed, falling back to interpreter\n");
+
+ x86_release_func( &vs->sse2_program );
+
+ FREE(vs);
+ return NULL;
+}
+
+
+
+#else
+
+struct draw_vertex_shader *
+draw_create_vs_sse( struct draw_context *draw,
+ const struct pipe_shader_state *templ )
+{
+ return (void *) 0;
+}
+
+
+#endif
+
diff --git a/src/gallium/auxiliary/draw/draw_vs_varient.c b/src/gallium/auxiliary/draw/draw_vs_varient.c
new file mode 100644
index 0000000000..7ee567d478
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_vs_varient.c
@@ -0,0 +1,322 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_vs.h"
+#include "translate/translate.h"
+#include "translate/translate_cache.h"
+
+/* A first pass at incorporating vertex fetch/emit functionality into
+ */
+struct draw_vs_varient_generic {
+ struct draw_vs_varient base;
+
+ struct draw_vertex_shader *shader;
+ struct draw_context *draw;
+
+ /* Basic plan is to run these two translate functions before/after
+ * the vertex shader's existing run_linear() routine to simulate
+ * the inclusion of this functionality into the shader...
+ *
+ * Next will look at actually including it.
+ */
+ struct translate *fetch;
+ struct translate *emit;
+
+ unsigned temp_vertex_stride;
+};
+
+
+
+
+
+static void vsvg_set_buffer( struct draw_vs_varient *varient,
+ unsigned buffer,
+ const void *ptr,
+ unsigned stride )
+{
+ struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient;
+
+ vsvg->fetch->set_buffer(vsvg->fetch,
+ buffer,
+ ptr,
+ stride);
+}
+
+
+/* Mainly for debug at this stage:
+ */
+static void do_rhw_viewport( struct draw_vs_varient_generic *vsvg,
+ unsigned count,
+ void *output_buffer )
+{
+ char *ptr = (char *)output_buffer;
+ const float *scale = vsvg->base.vs->draw->viewport.scale;
+ const float *trans = vsvg->base.vs->draw->viewport.translate;
+ unsigned stride = vsvg->temp_vertex_stride;
+ unsigned j;
+
+ ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
+
+ for (j = 0; j < count; j++, ptr += stride) {
+ float *data = (float *)ptr;
+ float w = 1.0f / data[3];
+
+ data[0] = data[0] * w * scale[0] + trans[0];
+ data[1] = data[1] * w * scale[1] + trans[1];
+ data[2] = data[2] * w * scale[2] + trans[2];
+ data[3] = w;
+ }
+}
+
+static void do_viewport( struct draw_vs_varient_generic *vsvg,
+ unsigned count,
+ void *output_buffer )
+{
+ char *ptr = (char *)output_buffer;
+ const float *scale = vsvg->base.vs->draw->viewport.scale;
+ const float *trans = vsvg->base.vs->draw->viewport.translate;
+ unsigned stride = vsvg->temp_vertex_stride;
+ unsigned j;
+
+ ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
+
+ for (j = 0; j < count; j++, ptr += stride) {
+ float *data = (float *)ptr;
+
+ data[0] = data[0] * scale[0] + trans[0];
+ data[1] = data[1] * scale[1] + trans[1];
+ data[2] = data[2] * scale[2] + trans[2];
+ }
+}
+
+
+static void PIPE_CDECL vsvg_run_elts( struct draw_vs_varient *varient,
+ const unsigned *elts,
+ unsigned count,
+ void *output_buffer)
+{
+ struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient;
+ unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
+ void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
+
+ if (0) debug_printf("%s %d \n", __FUNCTION__, count);
+
+ /* Want to do this in small batches for cache locality?
+ */
+
+ vsvg->fetch->run_elts( vsvg->fetch,
+ elts,
+ count,
+ temp_buffer );
+
+ vsvg->base.vs->run_linear( vsvg->base.vs,
+ temp_buffer,
+ temp_buffer,
+ (const float (*)[4])vsvg->base.vs->draw->pt.user.constants,
+ count,
+ temp_vertex_stride,
+ temp_vertex_stride);
+
+
+ if (vsvg->base.key.clip) {
+ /* not really handling clipping, just do the rhw so we can
+ * see the results...
+ */
+ do_rhw_viewport( vsvg,
+ count,
+ temp_buffer );
+ }
+ else if (vsvg->base.key.viewport) {
+ do_viewport( vsvg,
+ count,
+ temp_buffer );
+ }
+
+
+ vsvg->emit->set_buffer( vsvg->emit,
+ 0,
+ temp_buffer,
+ temp_vertex_stride );
+
+ vsvg->emit->set_buffer( vsvg->emit,
+ 1,
+ &vsvg->draw->rasterizer->point_size,
+ 0);
+
+ vsvg->emit->run( vsvg->emit,
+ 0, count,
+ output_buffer );
+
+ FREE(temp_buffer);
+}
+
+
+static void PIPE_CDECL vsvg_run_linear( struct draw_vs_varient *varient,
+ unsigned start,
+ unsigned count,
+ void *output_buffer )
+{
+ struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient;
+ unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
+ void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
+
+ if (0) debug_printf("%s %d %d (sz %d, %d)\n", __FUNCTION__, start, count,
+ vsvg->base.key.output_stride,
+ temp_vertex_stride);
+
+ vsvg->fetch->run( vsvg->fetch,
+ start,
+ count,
+ temp_buffer );
+
+ vsvg->base.vs->run_linear( vsvg->base.vs,
+ temp_buffer,
+ temp_buffer,
+ (const float (*)[4])vsvg->base.vs->draw->pt.user.constants,
+ count,
+ temp_vertex_stride,
+ temp_vertex_stride);
+
+ if (vsvg->base.key.clip) {
+ /* not really handling clipping, just do the rhw so we can
+ * see the results...
+ */
+ do_rhw_viewport( vsvg,
+ count,
+ temp_buffer );
+ }
+ else if (vsvg->base.key.viewport) {
+ do_viewport( vsvg,
+ count,
+ temp_buffer );
+ }
+
+ vsvg->emit->set_buffer( vsvg->emit,
+ 0,
+ temp_buffer,
+ temp_vertex_stride );
+
+ vsvg->emit->set_buffer( vsvg->emit,
+ 1,
+ &vsvg->draw->rasterizer->point_size,
+ 0);
+
+ vsvg->emit->run( vsvg->emit,
+ 0, count,
+ output_buffer );
+
+ FREE(temp_buffer);
+}
+
+
+
+
+
+static void vsvg_destroy( struct draw_vs_varient *varient )
+{
+ FREE(varient);
+}
+
+
+struct draw_vs_varient *draw_vs_varient_generic( struct draw_vertex_shader *vs,
+ const struct draw_vs_varient_key *key )
+{
+ unsigned i;
+ struct translate_key fetch, emit;
+
+ struct draw_vs_varient_generic *vsvg = CALLOC_STRUCT( draw_vs_varient_generic );
+ if (vsvg == NULL)
+ return NULL;
+
+ vsvg->base.key = *key;
+ vsvg->base.vs = vs;
+ vsvg->base.set_buffer = vsvg_set_buffer;
+ vsvg->base.run_elts = vsvg_run_elts;
+ vsvg->base.run_linear = vsvg_run_linear;
+ vsvg->base.destroy = vsvg_destroy;
+
+ vsvg->draw = vs->draw;
+
+ vsvg->temp_vertex_stride = MAX2(key->nr_inputs,
+ vsvg->base.vs->info.num_outputs) * 4 * sizeof(float);
+
+ /* Build free-standing fetch and emit functions:
+ */
+ fetch.nr_elements = key->nr_inputs;
+ fetch.output_stride = vsvg->temp_vertex_stride;
+ for (i = 0; i < key->nr_inputs; i++) {
+ fetch.element[i].input_format = key->element[i].in.format;
+ fetch.element[i].input_buffer = key->element[i].in.buffer;
+ fetch.element[i].input_offset = key->element[i].in.offset;
+ fetch.element[i].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ fetch.element[i].output_offset = i * 4 * sizeof(float);
+ assert(fetch.element[i].output_offset < fetch.output_stride);
+ }
+
+
+ emit.nr_elements = key->nr_outputs;
+ emit.output_stride = key->output_stride;
+ for (i = 0; i < key->nr_outputs; i++) {
+ if (key->element[i].out.format != EMIT_1F_PSIZE)
+ {
+ emit.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ emit.element[i].input_buffer = 0;
+ emit.element[i].input_offset = key->element[i].out.vs_output * 4 * sizeof(float);
+ emit.element[i].output_format = draw_translate_vinfo_format(key->element[i].out.format);
+ emit.element[i].output_offset = key->element[i].out.offset;
+ assert(emit.element[i].input_offset <= fetch.output_stride);
+ }
+ else {
+ emit.element[i].input_format = PIPE_FORMAT_R32_FLOAT;
+ emit.element[i].input_buffer = 1;
+ emit.element[i].input_offset = 0;
+ emit.element[i].output_format = PIPE_FORMAT_R32_FLOAT;
+ emit.element[i].output_offset = key->element[i].out.offset;
+ }
+ }
+
+ vsvg->fetch = draw_vs_get_fetch( vs->draw, &fetch );
+ vsvg->emit = draw_vs_get_emit( vs->draw, &emit );
+
+ return &vsvg->base;
+}
+
+
+
+
+
diff --git a/src/gallium/auxiliary/gallivm/Makefile b/src/gallium/auxiliary/gallivm/Makefile
new file mode 100644
index 0000000000..5a96d94ec3
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/Makefile
@@ -0,0 +1,92 @@
+# -*-makefile-*-
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = gallivm
+
+
+GALLIVM_SOURCES = \
+ gallivm.cpp \
+ gallivm_cpu.cpp \
+ instructions.cpp \
+ loweringpass.cpp \
+ tgsitollvm.cpp \
+ storage.cpp \
+ storagesoa.cpp \
+ instructionssoa.cpp
+
+INC_SOURCES = gallivm_builtins.cpp gallivmsoabuiltins.cpp
+
+CPP_SOURCES = \
+ $(GALLIVM_SOURCES)
+
+C_SOURCES =
+ASM_SOURCES =
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(CPP_SOURCES:.cpp=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+### Include directories
+INCLUDES = \
+ -I. \
+ -I$(TOP)/src/gallium/drivers \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/include
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(LLVM_CFLAGS) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+.cpp.o:
+ $(CXX) -c $(INCLUDES) $(LLVM_CXXFLAGS) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+##### TARGETS #####
+
+default:: depend symlinks $(LIBNAME)
+
+
+$(LIBNAME): $(OBJECTS) Makefile
+ $(TOP)/bin/mklib -o $@ -static $(OBJECTS)
+
+
+depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(INC_SOURCES)
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) $(CPP_SOURCES) \
+ $(ASM_SOURCES) $(INC_SOURCES) 2> /dev/null
+
+
+gallivm_builtins.cpp: llvm_builtins.c
+ clang --emit-llvm < $< |llvm-as|opt -std-compile-opts > temp1.bin
+ (echo "static const unsigned char llvm_builtins_data[] = {"; od -txC temp1.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/,0x00};/") >$@
+ rm temp1.bin
+
+gallivmsoabuiltins.cpp: soabuiltins.c
+ clang --emit-llvm < $< |llvm-as|opt -std-compile-opts > temp2.bin
+ (echo "static const unsigned char soabuiltins_data[] = {"; od -txC temp2.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/,0x00};/") >$@
+ rm temp2.bin
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+ -rm -f *.o */*.o *~ *.so *~ server/*.o
+ -rm -f depend depend.bak
+ -rm -f gallivm_builtins.cpp
+ -rm -f gallivmsoabuiltins.cpp
+
+symlinks:
+
+
+include depend
diff --git a/src/gallium/auxiliary/gallivm/SConscript b/src/gallium/auxiliary/gallivm/SConscript
new file mode 100644
index 0000000000..c0aa51b90a
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/SConscript
@@ -0,0 +1,16 @@
+Import('*')
+
+gallivm = env.ConvenienceLibrary(
+ target = 'gallivm',
+ source = [
+ 'gallivm.cpp',
+ 'gallivm_cpu.cpp',
+ 'instructions.cpp',
+ 'loweringpass.cpp',
+ 'tgsitollvm.cpp',
+ 'storage.cpp',
+ 'storagesoa.cpp',
+ 'instructionssoa.cpp',
+ ])
+
+auxiliaries.insert(0, gallivm)
diff --git a/src/gallium/auxiliary/gallivm/gallivm.cpp b/src/gallium/auxiliary/gallivm/gallivm.cpp
new file mode 100644
index 0000000000..f4af5cc8ad
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/gallivm.cpp
@@ -0,0 +1,332 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+#ifdef MESA_LLVM
+
+#include "gallivm.h"
+#include "gallivm_p.h"
+
+#include "instructions.h"
+#include "loweringpass.h"
+#include "storage.h"
+#include "tgsitollvm.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "tgsi/tgsi_exec.h"
+#include "tgsi/tgsi_dump.h"
+
+#include <llvm/Module.h>
+#include <llvm/CallingConv.h>
+#include <llvm/Constants.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Instructions.h>
+#include <llvm/ModuleProvider.h>
+#include <llvm/Pass.h>
+#include <llvm/PassManager.h>
+#include <llvm/Attributes.h>
+#include <llvm/Support/PatternMatch.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/ExecutionEngine/Interpreter.h>
+#include <llvm/ExecutionEngine/GenericValue.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/LinkAllPasses.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Analysis/LoopPass.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/Transforms/Utils/Cloning.h>
+
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+static int GLOBAL_ID = 0;
+
+using namespace llvm;
+
+static inline
+void AddStandardCompilePasses(PassManager &PM)
+{
+ PM.add(new LoweringPass());
+ PM.add(createVerifierPass()); // Verify that input is correct
+
+ PM.add(createLowerSetJmpPass()); // Lower llvm.setjmp/.longjmp
+
+ //PM.add(createStripSymbolsPass(true));
+
+ PM.add(createRaiseAllocationsPass()); // call %malloc -> malloc inst
+ PM.add(createCFGSimplificationPass()); // Clean up disgusting code
+ PM.add(createPromoteMemoryToRegisterPass());// Kill useless allocas
+ PM.add(createGlobalOptimizerPass()); // Optimize out global vars
+ PM.add(createGlobalDCEPass()); // Remove unused fns and globs
+ PM.add(createIPConstantPropagationPass());// IP Constant Propagation
+ PM.add(createDeadArgEliminationPass()); // Dead argument elimination
+ PM.add(createInstructionCombiningPass()); // Clean up after IPCP & DAE
+ PM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE
+
+ PM.add(createPruneEHPass()); // Remove dead EH info
+
+ PM.add(createFunctionInliningPass()); // Inline small functions
+ PM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args
+
+ PM.add(createTailDuplicationPass()); // Simplify cfg by copying code
+ PM.add(createInstructionCombiningPass()); // Cleanup for scalarrepl.
+ PM.add(createCFGSimplificationPass()); // Merge & remove BBs
+ PM.add(createScalarReplAggregatesPass()); // Break up aggregate allocas
+ PM.add(createInstructionCombiningPass()); // Combine silly seq's
+ PM.add(createCondPropagationPass()); // Propagate conditionals
+
+ PM.add(createTailCallEliminationPass()); // Eliminate tail calls
+ PM.add(createCFGSimplificationPass()); // Merge & remove BBs
+ PM.add(createReassociatePass()); // Reassociate expressions
+ PM.add(createLoopRotatePass());
+ PM.add(createLICMPass()); // Hoist loop invariants
+ PM.add(createLoopUnswitchPass()); // Unswitch loops.
+ PM.add(createLoopIndexSplitPass()); // Index split loops.
+ PM.add(createInstructionCombiningPass()); // Clean up after LICM/reassoc
+ PM.add(createIndVarSimplifyPass()); // Canonicalize indvars
+ PM.add(createLoopUnrollPass()); // Unroll small loops
+ PM.add(createInstructionCombiningPass()); // Clean up after the unroller
+ PM.add(createGVNPass()); // Remove redundancies
+ PM.add(createSCCPPass()); // Constant prop with SCCP
+
+ // Run instcombine after redundancy elimination to exploit opportunities
+ // opened up by them.
+ PM.add(createInstructionCombiningPass());
+ PM.add(createCondPropagationPass()); // Propagate conditionals
+
+ PM.add(createDeadStoreEliminationPass()); // Delete dead stores
+ PM.add(createAggressiveDCEPass()); // SSA based 'Aggressive DCE'
+ PM.add(createCFGSimplificationPass()); // Merge & remove BBs
+ PM.add(createSimplifyLibCallsPass()); // Library Call Optimizations
+ PM.add(createDeadTypeEliminationPass()); // Eliminate dead types
+ PM.add(createConstantMergePass()); // Merge dup global constants
+}
+
+void gallivm_prog_delete(struct gallivm_prog *prog)
+{
+ delete prog->module;
+ prog->module = 0;
+ prog->function = 0;
+ free(prog);
+}
+
+static inline void
+constant_interpolation(float (*inputs)[16][4],
+ const struct tgsi_interp_coef *coefs,
+ unsigned attrib,
+ unsigned chan)
+{
+ unsigned i;
+
+ for (i = 0; i < QUAD_SIZE; ++i) {
+ inputs[i][attrib][chan] = coefs[attrib].a0[chan];
+ }
+}
+
+static inline void
+linear_interpolation(float (*inputs)[16][4],
+ const struct tgsi_interp_coef *coefs,
+ unsigned attrib,
+ unsigned chan)
+{
+ unsigned i;
+
+ for( i = 0; i < QUAD_SIZE; i++ ) {
+ const float x = inputs[i][0][0];
+ const float y = inputs[i][0][1];
+
+ inputs[i][attrib][chan] =
+ coefs[attrib].a0[chan] +
+ coefs[attrib].dadx[chan] * x +
+ coefs[attrib].dady[chan] * y;
+ }
+}
+
+static inline void
+perspective_interpolation(float (*inputs)[16][4],
+ const struct tgsi_interp_coef *coefs,
+ unsigned attrib,
+ unsigned chan )
+{
+ unsigned i;
+
+ for( i = 0; i < QUAD_SIZE; i++ ) {
+ const float x = inputs[i][0][0];
+ const float y = inputs[i][0][1];
+ /* WPOS.w here is really 1/w */
+ const float w = 1.0f / inputs[i][0][3];
+ assert(inputs[i][0][3] != 0.0);
+
+ inputs[i][attrib][chan] =
+ (coefs[attrib].a0[chan] +
+ coefs[attrib].dadx[chan] * x +
+ coefs[attrib].dady[chan] * y) * w;
+ }
+}
+
+void gallivm_ir_dump(struct gallivm_ir *ir, const char *file_prefix)
+{
+ if (!ir || !ir->module)
+ return;
+
+ if (file_prefix) {
+ std::ostringstream stream;
+ stream << file_prefix;
+ stream << ir->id;
+ stream << ".ll";
+ std::string name = stream.str();
+ std::ofstream out(name.c_str());
+ if (!out) {
+ std::cerr<<"Can't open file : "<<stream.str()<<std::endl;;
+ return;
+ }
+ out << (*ir->module);
+ out.close();
+ } else {
+ const llvm::Module::FunctionListType &funcs = ir->module->getFunctionList();
+ llvm::Module::FunctionListType::const_iterator itr;
+ std::cout<<"; ---------- Start shader "<<ir->id<<std::endl;
+ for (itr = funcs.begin(); itr != funcs.end(); ++itr) {
+ const llvm::Function &func = (*itr);
+ std::string name = func.getName();
+ const llvm::Function *found = 0;
+ if (name.find("vs_shader") != std::string::npos ||
+ name.find("fs_shader") != std::string::npos ||
+ name.find("function") != std::string::npos)
+ found = &func;
+ if (found) {
+ std::cout<<*found<<std::endl;
+ }
+ }
+ std::cout<<"; ---------- End shader "<<ir->id<<std::endl;
+ }
+}
+
+
+void gallivm_prog_inputs_interpolate(struct gallivm_prog *prog,
+ float (*inputs)[16][4],
+ const struct tgsi_interp_coef *coef)
+{
+ for (int i = 0; i < prog->num_interp; ++i) {
+ const gallivm_interpolate &interp = prog->interpolators[i];
+ switch (interp.type) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ constant_interpolation(inputs, coef, interp.attrib, interp.chan);
+ break;
+
+ case TGSI_INTERPOLATE_LINEAR:
+ linear_interpolation(inputs, coef, interp.attrib, interp.chan);
+ break;
+
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ perspective_interpolation(inputs, coef, interp.attrib, interp.chan);
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+}
+
+
+struct gallivm_ir * gallivm_ir_new(enum gallivm_shader_type type)
+{
+ struct gallivm_ir *ir =
+ (struct gallivm_ir *)calloc(1, sizeof(struct gallivm_ir));
+ ++GLOBAL_ID;
+ ir->id = GLOBAL_ID;
+ ir->type = type;
+
+ return ir;
+}
+
+void gallivm_ir_set_layout(struct gallivm_ir *ir,
+ enum gallivm_vector_layout layout)
+{
+ ir->layout = layout;
+}
+
+void gallivm_ir_set_components(struct gallivm_ir *ir, int num)
+{
+ ir->num_components = num;
+}
+
+void gallivm_ir_fill_from_tgsi(struct gallivm_ir *ir,
+ const struct tgsi_token *tokens)
+{
+ std::cout << "Creating llvm from: " <<std::endl;
+ tgsi_dump(tokens, 0);
+
+ llvm::Module *mod = tgsi_to_llvmir(ir, tokens);
+ ir->module = mod;
+ gallivm_ir_dump(ir, 0);
+}
+
+void gallivm_ir_delete(struct gallivm_ir *ir)
+{
+ delete ir->module;
+ free(ir);
+}
+
+struct gallivm_prog * gallivm_ir_compile(struct gallivm_ir *ir)
+{
+ struct gallivm_prog *prog =
+ (struct gallivm_prog *)calloc(1, sizeof(struct gallivm_prog));
+
+ std::cout << "Before optimizations:"<<std::endl;
+ ir->module->dump();
+ std::cout<<"-------------------------------"<<std::endl;
+
+ PassManager veri;
+ veri.add(createVerifierPass());
+ veri.run(*ir->module);
+ llvm::Module *mod = llvm::CloneModule(ir->module);
+ prog->num_consts = ir->num_consts;
+ memcpy(prog->interpolators, ir->interpolators, sizeof(prog->interpolators));
+ prog->num_interp = ir->num_interp;
+
+ /* Run optimization passes over it */
+ PassManager passes;
+ passes.add(new TargetData(mod));
+ AddStandardCompilePasses(passes);
+ passes.run(*mod);
+ prog->module = mod;
+
+ std::cout << "After optimizations:"<<std::endl;
+ mod->dump();
+
+ return prog;
+}
+
+#endif /* MESA_LLVM */
diff --git a/src/gallium/auxiliary/gallivm/gallivm.h b/src/gallium/auxiliary/gallivm/gallivm.h
new file mode 100644
index 0000000000..36a64a7747
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/gallivm.h
@@ -0,0 +1,118 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+
+#ifndef GALLIVM_H
+#define GALLIVM_H
+
+/*
+ LLVM representation consists of two stages - layout independent
+ intermediate representation gallivm_ir and driver specific
+ gallivm_prog. TGSI is first being translated into gallivm_ir
+ after that driver can set number of options on gallivm_ir and
+ have it compiled into gallivm_prog. gallivm_prog can be either
+ executed (assuming there's LLVM JIT backend for the current
+ target) or machine code generation can be done (assuming there's
+ a LLVM code generator for thecurrent target)
+ */
+#if defined __cplusplus
+extern "C" {
+#endif
+
+#include "pipe/p_state.h"
+
+#ifdef MESA_LLVM
+
+struct tgsi_token;
+
+struct gallivm_ir;
+struct gallivm_prog;
+struct gallivm_cpu_engine;
+struct tgsi_interp_coef;
+struct tgsi_sampler;
+struct tgsi_exec_vector;
+
+enum gallivm_shader_type {
+ GALLIVM_VS,
+ GALLIVM_FS
+};
+
+enum gallivm_vector_layout {
+ GALLIVM_AOS,
+ GALLIVM_SOA
+};
+
+struct gallivm_ir *gallivm_ir_new(enum gallivm_shader_type type);
+void gallivm_ir_set_layout(struct gallivm_ir *ir,
+ enum gallivm_vector_layout layout);
+void gallivm_ir_set_components(struct gallivm_ir *ir, int num);
+void gallivm_ir_fill_from_tgsi(struct gallivm_ir *ir,
+ const struct tgsi_token *tokens);
+void gallivm_ir_delete(struct gallivm_ir *ir);
+
+
+struct gallivm_prog *gallivm_ir_compile(struct gallivm_ir *ir);
+
+void gallivm_prog_inputs_interpolate(struct gallivm_prog *prog,
+ float (*inputs)[PIPE_MAX_SHADER_INPUTS][4],
+ const struct tgsi_interp_coef *coefs);
+void gallivm_prog_dump(struct gallivm_prog *prog, const char *file_prefix);
+
+
+struct gallivm_cpu_engine *gallivm_cpu_engine_create(struct gallivm_prog *prog);
+struct gallivm_cpu_engine *gallivm_global_cpu_engine();
+int gallivm_cpu_vs_exec(struct gallivm_prog *prog,
+ struct tgsi_exec_machine *machine,
+ const float (*input)[4],
+ unsigned num_inputs,
+ float (*output)[4],
+ unsigned num_outputs,
+ const float (*constants)[4],
+ unsigned count,
+ unsigned input_stride,
+ unsigned output_stride);
+int gallivm_cpu_fs_exec(struct gallivm_prog *prog,
+ float x, float y,
+ float (*dests)[PIPE_MAX_SHADER_INPUTS][4],
+ float (*inputs)[PIPE_MAX_SHADER_INPUTS][4],
+ float (*consts)[4],
+ struct tgsi_sampler *samplers);
+void gallivm_cpu_jit_compile(struct gallivm_cpu_engine *ee, struct gallivm_prog *prog);
+void gallivm_cpu_engine_delete(struct gallivm_cpu_engine *ee);
+
+
+#endif /* MESA_LLVM */
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/auxiliary/gallivm/gallivm_builtins.cpp b/src/gallium/auxiliary/gallivm/gallivm_builtins.cpp
new file mode 100644
index 0000000000..634bac0150
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/gallivm_builtins.cpp
@@ -0,0 +1,140 @@
+static const unsigned char llvm_builtins_data[] = {
+0x42,0x43,0xc0,0xde,0x21,0x0c,0x00,0x00,0x27,0x02,0x00,0x00,0x01,0x10,0x00,0x00,
+0x10,0x00,0x00,0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,0x39,
+0x92,0x01,0x84,0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,0x02,
+0x42,0x92,0x0b,0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,0x24,
+0x48,0x0a,0x90,0x21,0x23,0x44,0x72,0x80,0x8c,0x14,0x21,0x86,0x0a,0x8a,0x0a,0x64,
+0x0c,0x1f,0x00,0x00,0x49,0x18,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x84,0xff,0xff,
+0xff,0xff,0x1f,0xc0,0x00,0x00,0x00,0x00,0x51,0x20,0x00,0x00,0x12,0x00,0x00,0x00,
+0x32,0x22,0x48,0x09,0x20,0x65,0x82,0x84,0x00,0x26,0x45,0x48,0x05,0x09,0x26,0x45,
+0xc6,0x05,0x42,0x52,0x26,0x08,0xae,0x19,0x80,0x61,0x04,0x02,0x98,0x23,0x00,0x83,
+0x29,0x80,0x21,0x00,0xb2,0x73,0x04,0x01,0x51,0x8a,0xf4,0x08,0x92,0xa4,0x39,0x47,
+0x80,0x50,0x2b,0x03,0x00,0xa0,0x08,0x21,0x5c,0x46,0x2b,0x44,0x08,0x21,0xd4,0x40,
+0x14,0x01,0x80,0x11,0x80,0x22,0x88,0x00,0x13,0x30,0x7c,0xc0,0x03,0x3b,0xf8,0x05,
+0x3b,0xa0,0x83,0x36,0xa8,0x07,0x77,0x58,0x07,0x77,0x78,0x87,0x7b,0x70,0x87,0x36,
+0x60,0x87,0x74,0x70,0x87,0x7a,0xc0,0x87,0x36,0x38,0x07,0x77,0xa8,0x87,0x0d,0xf7,
+0x50,0x0e,0x6d,0x00,0x0f,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,
+0x07,0x74,0xd0,0x06,0xe9,0x10,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,
+0x78,0xa0,0x07,0x78,0xa0,0x07,0x78,0xd0,0x06,0xe9,0x10,0x07,0x76,0xa0,0x07,0x71,
+0x60,0x07,0x7a,0x10,0x07,0x76,0xd0,0x06,0xe9,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,
+0x07,0x7a,0x30,0x07,0x72,0xd0,0x06,0xe9,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,
+0x7a,0x60,0x07,0x74,0xd0,0x06,0xe6,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,
+0x30,0x07,0x72,0xd0,0x06,0xe6,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,
+0x07,0x74,0xd0,0x06,0xf6,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,
+0x74,0xd0,0x06,0xf6,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x7a,
+0x10,0x07,0x72,0x80,0x07,0x6d,0x10,0x0e,0x70,0xa0,0x07,0x70,0xa0,0x07,0x76,0x40,
+0x07,0x6d,0x60,0x0e,0x78,0x00,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,
+0x72,0x80,0x07,0x3a,0x0f,0x84,0x48,0x20,0x23,0x24,0x40,0x00,0x62,0x67,0x88,0x9f,
+0x19,0x92,0x24,0x00,0x10,0x04,0x00,0x00,0x00,0x43,0x92,0x04,0x08,0x00,0x00,0x00,
+0x00,0x60,0x48,0xa2,0x00,0x40,0x10,0x00,0x00,0x00,0x0c,0x49,0x16,0x00,0x08,0x02,
+0x00,0x00,0x80,0x21,0x89,0x02,0x00,0x41,0x00,0x00,0x00,0x30,0x24,0x61,0x80,0x00,
+0x00,0x00,0x00,0x00,0x86,0x24,0x07,0x10,0x00,0x00,0x00,0x00,0xc0,0x90,0x44,0x01,
+0x80,0x20,0x00,0x00,0x00,0x18,0x92,0x1c,0x40,0x00,0x00,0x00,0x00,0x00,0x43,0x12,
+0x05,0x00,0x82,0x00,0x00,0x00,0x60,0x48,0x52,0x00,0x40,0x10,0x00,0x00,0x00,0x64,
+0x81,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x32,0x1e,0x98,0x10,0x19,0x11,0x4c,0x90,
+0x8c,0x09,0x26,0x47,0xc6,0x04,0x43,0x8a,0x8a,0x59,0x8b,0x43,0x50,0xd2,0x09,0x02,
+0x81,0xd2,0x73,0x50,0xc9,0x0c,0x2a,0x99,0x41,0x25,0x33,0xa8,0x64,0x56,0x28,0x66,
+0x2d,0x0e,0x41,0xcf,0x2a,0x15,0x04,0x4a,0xcf,0x41,0x25,0x33,0xa8,0x64,0x06,0x95,
+0xcc,0xa0,0x92,0x59,0x01,0x00,0x00,0x00,0x53,0x82,0x26,0x0c,0x04,0x00,0x00,0x00,
+0x22,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x05,0x00,0x00,0x00,
+0x04,0xc6,0x08,0x40,0x10,0x04,0xe1,0x70,0x18,0x23,0x00,0x41,0x10,0x84,0xc3,0x60,
+0x04,0x00,0x00,0x00,0xc3,0x0d,0xce,0x43,0x4c,0x37,0x3c,0x8e,0x34,0xdc,0x30,0x41,
+0xc2,0x74,0x03,0x34,0x51,0xc3,0x0d,0x4d,0x44,0x4c,0x37,0x44,0x8d,0x35,0x56,0x01,
+0x04,0xc3,0x55,0x21,0x16,0x0e,0x04,0x00,0x0f,0x00,0x00,0x00,0xd6,0x10,0x00,0xe6,
+0x10,0x04,0x76,0x81,0x00,0x3e,0x30,0x0c,0x91,0x4f,0x1b,0x05,0x21,0x30,0x8f,0x6d,
+0x13,0x48,0xe0,0x03,0xc3,0x10,0xf9,0xb4,0x55,0x20,0x81,0x0f,0x0c,0x43,0xe4,0xd7,
+0x66,0x41,0x08,0xcc,0xa3,0x1f,0x40,0x41,0x34,0x53,0x84,0x99,0xc4,0x20,0x30,0x8f,
+0x61,0x10,0x02,0xb0,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,
+0x27,0x00,0x00,0x00,0x13,0x04,0x43,0x2c,0x10,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
+0x24,0x8a,0xa0,0x0c,0x46,0x00,0x4a,0x80,0xc2,0x1c,0x84,0x55,0x55,0xd6,0x1c,0x84,
+0x45,0x51,0x16,0x81,0x19,0x80,0x11,0x80,0x31,0x02,0x10,0x04,0x41,0xfc,0x03,0x00,
+0x63,0x08,0x0d,0x34,0xdc,0x70,0x55,0xc2,0x2c,0x43,0x20,0x60,0x73,0x0c,0xd3,0x15,
+0x8d,0x21,0x34,0xd1,0x18,0x42,0xf3,0x8c,0x55,0x00,0x81,0xa0,0x6d,0x73,0x0c,0x19,
+0xe7,0x60,0x87,0x52,0x38,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x27,0x50,0x20,0x05,
+0xd1,0x0c,0x17,0x60,0x20,0xc5,0x74,0x10,0x8d,0x65,0x14,0x13,0xf3,0xd4,0xb4,0x6d,
+0x14,0x13,0xf3,0xd4,0xb8,0x69,0x14,0x13,0xf3,0xd4,0xb6,0x75,0x14,0x13,0xf3,0xd4,
+0xba,0x35,0x0c,0x13,0xf3,0xd8,0x05,0x31,0x31,0x8f,0x6e,0x1c,0x84,0x00,0x2c,0xcb,
+0x01,0x14,0x44,0x33,0x45,0x98,0x61,0x0c,0x02,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,
+0x61,0x20,0x00,0x00,0x81,0x00,0x00,0x00,0x13,0x04,0x4d,0x2c,0x10,0x00,0x00,0x00,
+0x04,0x00,0x00,0x00,0x24,0xca,0x60,0x04,0xa0,0x04,0x8a,0x80,0xc2,0x0c,0x00,0x91,
+0x11,0x00,0x00,0x00,0x63,0x08,0x4d,0x64,0x16,0xc1,0xe1,0x86,0xab,0x22,0x66,0x19,
+0x02,0x01,0x1b,0x43,0x70,0xa2,0x59,0x82,0x61,0x0c,0xe1,0x89,0x66,0x09,0x86,0x81,
+0x0a,0x20,0x0b,0x34,0x61,0x8e,0x81,0xda,0xa2,0x31,0x84,0x46,0xb2,0x8e,0xe0,0x70,
+0x83,0x57,0x11,0xb3,0x0c,0x44,0xf1,0x8d,0x21,0x38,0xd2,0x2c,0x81,0x31,0x86,0xf0,
+0x48,0xb3,0x04,0xc6,0x40,0x05,0x00,0x06,0x44,0x18,0x14,0x73,0x0c,0x9c,0x18,0x48,
+0x63,0x08,0xcd,0x64,0x64,0x40,0x70,0xb8,0xa1,0x0c,0x2a,0x62,0x96,0xe1,0x40,0xcc,
+0x60,0x0c,0xc1,0x99,0x66,0x09,0x92,0x31,0x84,0x67,0x9a,0x25,0x48,0x06,0x2a,0x80,
+0x33,0x38,0xd0,0x00,0x99,0x63,0x18,0x83,0x34,0x98,0xc6,0x10,0x1a,0xc8,0xd6,0x80,
+0xe0,0x70,0x03,0x1b,0x54,0xc4,0x2c,0x83,0xb2,0xb4,0xc1,0x18,0x82,0x03,0xcd,0x12,
+0x30,0x63,0x08,0x0f,0x34,0x4b,0xc0,0x0c,0x54,0x00,0x6e,0xa0,0xbc,0xc1,0x32,0xc7,
+0xa0,0x06,0x70,0x00,0x61,0x1c,0x84,0x03,0x01,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,
+0x76,0x52,0x4c,0xcc,0x73,0xd3,0x24,0x05,0x64,0xec,0xcd,0x8d,0xcc,0xe5,0x87,0x46,
+0xc6,0x50,0x8a,0x89,0x79,0xee,0xdb,0x54,0x8a,0x89,0x79,0xee,0xdd,0x1a,0x88,0x89,
+0x79,0x68,0x73,0x20,0x26,0xe6,0xa9,0xed,0x81,0x98,0x98,0xc7,0x36,0x0b,0x62,0x62,
+0x9e,0xdb,0x32,0x88,0x89,0x79,0x72,0xd3,0x20,0x26,0xe6,0xd9,0x8d,0x83,0x98,0x98,
+0xa7,0xb7,0x95,0x62,0x62,0x9e,0xbb,0x27,0x2d,0x20,0x63,0x6f,0x6e,0x64,0x2e,0x3a,
+0x34,0x35,0x56,0x62,0x08,0x4e,0x53,0xd9,0xba,0xb5,0x14,0x02,0xf3,0xe0,0xf5,0x25,
+0x2c,0x82,0xd3,0x0c,0xbe,0xe0,0x34,0xd3,0x8d,0x9b,0x88,0x21,0x38,0xcd,0x60,0xd7,
+0x24,0x01,0x63,0xec,0xcd,0x8d,0xcc,0x45,0x87,0x44,0x80,0x8c,0xbd,0xb9,0x91,0xb9,
+0xfc,0xc4,0xd0,0x90,0x02,0x8c,0xb1,0x37,0x37,0x32,0x97,0x1f,0x73,0x29,0x26,0xe6,
+0xc1,0x71,0x7b,0x29,0x26,0xe6,0xc1,0x77,0xfb,0x28,0x04,0xe6,0xa9,0x6f,0x52,0x01,
+0x32,0xf6,0xe6,0x46,0xe6,0xa2,0x13,0x73,0x63,0x18,0x83,0xc0,0x3c,0xb6,0x41,0x08,
+0x4e,0x33,0x58,0x47,0x31,0x31,0x4f,0x5d,0x1f,0xc3,0x22,0x38,0xcd,0xe0,0x0b,0x4e,
+0x33,0xe1,0xbc,0xa5,0x18,0x82,0xd3,0x0c,0x77,0x6e,0x20,0xc5,0xc4,0x3c,0xb5,0x4e,
+0x3a,0x40,0xc6,0xde,0xdc,0xc8,0x5c,0x7e,0x64,0x70,0x2c,0xa4,0x98,0x98,0xa7,0xee,
+0x6f,0x20,0x11,0x9c,0x66,0xf0,0x05,0xa7,0x99,0xec,0x82,0x10,0x9c,0xa6,0x32,0x93,
+0x42,0x60,0x1e,0x7b,0xb7,0x98,0x62,0x62,0x9e,0xbc,0x36,0x16,0x43,0x70,0x9a,0x0a,
+0xa7,0x6d,0xa4,0x98,0x98,0xc7,0xbe,0x8d,0xa4,0x98,0x98,0xc7,0xce,0x0d,0xc6,0x10,
+0x9c,0x66,0xc0,0x7b,0x12,0x02,0x32,0xf6,0xe6,0x46,0xe6,0xa2,0x33,0x13,0x73,0x06,
+0x8b,0xe0,0x34,0x83,0x2f,0x38,0xcd,0x64,0xd3,0x07,0x50,0x10,0xcd,0x14,0x61,0xe6,
+0x61,0x08,0x4e,0x53,0xd5,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,
+0x4a,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x07,0x00,0x00,0x00,
+0x24,0xca,0x60,0x04,0xa0,0x04,0x8a,0x80,0xc2,0x0c,0x00,0xb9,0x61,0x0c,0x04,0x10,
+0x1e,0xe1,0x19,0xc6,0x40,0x02,0xe1,0x11,0x1e,0x00,0x00,0x00,0x63,0x08,0xcd,0x63,
+0x15,0xc1,0x31,0x84,0x06,0xb2,0x8b,0xe0,0x18,0x42,0x13,0x59,0x46,0x70,0x0c,0xa1,
+0x71,0x6c,0x23,0x38,0x16,0x02,0x04,0xc7,0x64,0x61,0x1a,0x37,0x16,0x01,0x04,0x48,
+0x35,0xc7,0x20,0x79,0xcf,0x58,0x04,0x10,0x20,0xd5,0x1c,0xc3,0x07,0x06,0xd0,0x58,
+0x04,0x10,0x20,0xd5,0x1c,0x43,0x18,0x88,0x41,0x34,0x16,0x01,0x04,0x48,0x35,0xc7,
+0x30,0x06,0x64,0xe0,0x98,0x47,0xd0,0xc0,0x80,0xa0,0x89,0x01,0x41,0x23,0x03,0x82,
+0x63,0x21,0x40,0x70,0x50,0x66,0x70,0x06,0x68,0x90,0x06,0x58,0x06,0xe1,0x40,0x00,
+0x25,0x00,0x00,0x00,0x56,0x52,0x4c,0xcc,0x73,0xd3,0x56,0x41,0x4c,0xcc,0x53,0xdb,
+0x05,0x31,0x31,0xcf,0x6d,0x19,0xc4,0xc4,0x3c,0xba,0x6d,0x10,0x13,0xf3,0xf4,0xd6,
+0x41,0x08,0xc0,0xb2,0x18,0x46,0x21,0x38,0x4d,0x85,0x9b,0x46,0x21,0x38,0x4d,0xb5,
+0x9b,0x8a,0x21,0x00,0xcb,0x82,0xdf,0x66,0x62,0x08,0x4e,0x53,0xdd,0xb7,0x9d,0x18,
+0x82,0xd3,0x54,0xb7,0x6e,0x28,0x86,0xe0,0x34,0xd5,0xdd,0xdb,0x47,0x31,0x31,0x4f,
+0x9d,0x9b,0x87,0x21,0x00,0xcb,0x52,0xdf,0x06,0x62,0x08,0xc0,0xb2,0xd4,0xbc,0x59,
+0x10,0x82,0xd3,0x54,0x96,0x62,0x08,0x4e,0x53,0xe1,0xb6,0x85,0x14,0x13,0xf3,0xd8,
+0xb4,0x8d,0x14,0x13,0xf3,0xd8,0xb9,0x89,0x18,0x02,0xb0,0x2c,0xf6,0x6d,0x24,0x86,
+0x00,0x2c,0x8b,0xcd,0x1b,0x87,0x21,0x38,0x4d,0x55,0xd3,0xd6,0x30,0x54,0xc0,0x72,
+0x00,0x05,0xd1,0x4c,0x11,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,
+0x19,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+0x24,0x4a,0x60,0x04,0x80,0xc2,0x0c,0x00,0x00,0x00,0x00,0x00,0x63,0x08,0xcd,0x33,
+0x16,0x01,0x04,0x48,0x34,0xc7,0x00,0x49,0xcf,0x58,0x04,0x10,0x28,0xd1,0x1c,0xc3,
+0x44,0x39,0x58,0x85,0x03,0x01,0x00,0x00,0x0a,0x00,0x00,0x00,0x26,0x41,0x08,0xc0,
+0xb2,0x18,0x45,0x21,0x00,0xcb,0xb2,0x5b,0x04,0x31,0x31,0x8f,0x6d,0x13,0xc4,0xc4,
+0x3c,0xb9,0x35,0x0c,0x15,0xb0,0x58,0x05,0x31,0x31,0x4f,0x7f,0x00,0x05,0xd1,0x4c,
+0x11,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,0x1b,0x00,0x00,0x00,
+0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x24,0xca,0x60,0x04,
+0xa0,0x04,0x8a,0x80,0xc2,0x0c,0x00,0x00,0x63,0x08,0xcd,0x33,0x16,0x01,0x04,0xca,
+0x34,0xc7,0x20,0x51,0xcf,0x1c,0x43,0x45,0x41,0x73,0x0c,0x16,0x15,0xcd,0x31,0x5c,
+0x94,0x83,0x58,0x38,0x10,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x76,0x51,0x4c,0xcc,
+0x53,0xdb,0x86,0x51,0x4c,0xcc,0x53,0xe7,0x36,0x41,0x4c,0xcc,0x63,0x5b,0x05,0x31,
+0x31,0x8f,0x6e,0x16,0xc4,0xc4,0x3c,0xbd,0x51,0x10,0x02,0xb0,0x2c,0xd6,0x30,0x54,
+0xc0,0x72,0x00,0x05,0xd1,0x4c,0x11,0x06,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,
+0x2c,0x00,0x00,0x00,0x13,0x04,0x45,0x2c,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+0x24,0xca,0xa0,0x04,0x46,0x00,0x8a,0x80,0xc0,0x08,0x00,0x00,0x63,0x08,0x0d,0x34,
+0xdc,0x30,0x49,0xc4,0x2c,0x03,0x11,0x50,0x63,0x08,0xcd,0x33,0xdc,0x50,0x49,0xc4,
+0x2c,0x03,0x21,0x58,0x63,0x08,0x4d,0x34,0xdc,0x70,0x49,0xc4,0x2c,0x03,0x31,0x60,
+0x63,0x08,0x8d,0x33,0xdc,0x90,0x49,0x84,0x69,0x22,0x70,0xc3,0x27,0x1c,0x08,0x00,
+0x17,0x00,0x00,0x00,0x96,0x51,0x4c,0xcc,0x53,0xdf,0x66,0x41,0x08,0xcc,0x83,0xdb,
+0x04,0x31,0x31,0x4f,0x6d,0x15,0xc4,0xc4,0x3c,0xb7,0x61,0x10,0x02,0xf3,0xf0,0x76,
+0x41,0x4c,0xcc,0xb3,0x1f,0x81,0x11,0x11,0x13,0x15,0x35,0x37,0x90,0x2c,0x4e,0xf4,
+0x47,0x87,0x54,0xd7,0x17,0x70,0x2c,0x4e,0xf4,0x47,0x87,0x74,0x02,0xc8,0xe2,0x44,
+0x7f,0x74,0x48,0xb9,0x69,0x14,0x02,0xf3,0xd4,0xb8,0x6d,0x18,0x11,0x31,0x55,0xc0,
+0x62,0x0d,0x43,0x05,0x2c,0x07,0x50,0x10,0xcd,0x14,0x61,0x46,0x31,0x08,0xcc,0x03,
+0x00,0x00,0x00,0x00,0x71,0x20,0x00,0x00,0x12,0x00,0x00,0x00,0x66,0x40,0x54,0x82,
+0x23,0x19,0xc3,0xa0,0x20,0x8b,0x1d,0x18,0x4f,0x84,0x34,0x53,0x61,0x03,0xc4,0xe3,
+0x58,0x85,0x05,0x14,0xbe,0x34,0x45,0xb5,0x21,0x10,0x82,0x23,0x15,0x46,0x30,0x2c,
+0xc8,0x64,0x02,0x06,0xf0,0x3c,0x91,0x73,0x19,0x00,0xe1,0x4b,0x53,0x64,0x0a,0x84,
+0x84,0x34,0x85,0x25,0x0c,0x92,0x20,0x59,0xc1,0x20,0x30,0x8f,0x2d,0x10,0x95,0x84,
+0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
diff --git a/src/gallium/auxiliary/gallivm/gallivm_cpu.cpp b/src/gallium/auxiliary/gallivm/gallivm_cpu.cpp
new file mode 100644
index 0000000000..1bd00a0c2a
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/gallivm_cpu.cpp
@@ -0,0 +1,243 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+#ifdef MESA_LLVM
+
+#include "gallivm.h"
+#include "gallivm_p.h"
+
+#include "instructions.h"
+#include "loweringpass.h"
+#include "storage.h"
+#include "tgsitollvm.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "tgsi/tgsi_exec.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include <llvm/Module.h>
+#include <llvm/CallingConv.h>
+#include <llvm/Constants.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Instructions.h>
+#include <llvm/ModuleProvider.h>
+#include <llvm/Pass.h>
+#include <llvm/PassManager.h>
+#include <llvm/Attributes.h>
+#include <llvm/Support/PatternMatch.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/ExecutionEngine/Interpreter.h>
+#include <llvm/ExecutionEngine/GenericValue.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/LinkAllPasses.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Analysis/LoopPass.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/Transforms/Utils/Cloning.h>
+
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+struct gallivm_cpu_engine {
+ llvm::ExecutionEngine *engine;
+};
+
+static struct gallivm_cpu_engine *CPU = 0;
+
+typedef int (*fragment_shader_runner)(float x, float y,
+ float (*dests)[16][4],
+ float (*inputs)[16][4],
+ int num_attribs,
+ float (*consts)[4], int num_consts,
+ struct tgsi_sampler *samplers);
+
+int gallivm_cpu_fs_exec(struct gallivm_prog *prog,
+ float fx, float fy,
+ float (*dests)[16][4],
+ float (*inputs)[16][4],
+ float (*consts)[4],
+ struct tgsi_sampler *samplers)
+{
+ fragment_shader_runner runner = reinterpret_cast<fragment_shader_runner>(prog->function);
+ assert(runner);
+
+ return runner(fx, fy, dests, inputs, prog->num_interp,
+ consts, prog->num_consts,
+ samplers);
+}
+
+static inline llvm::Function *func_for_shader(struct gallivm_prog *prog)
+{
+ llvm::Module *mod = prog->module;
+ llvm::Function *func = 0;
+
+ switch (prog->type) {
+ case GALLIVM_VS:
+ func = mod->getFunction("vs_shader");
+ break;
+ case GALLIVM_FS:
+ func = mod->getFunction("fs_shader");
+ break;
+ default:
+ assert(!"Unknown shader type!");
+ break;
+ }
+ return func;
+}
+
+/*!
+ This function creates a CPU based execution engine for the given gallivm_prog.
+ gallivm_cpu_engine should be used as a singleton throughout the library. Before
+ executing gallivm_prog_exec one needs to call gallivm_cpu_jit_compile.
+ The gallivm_prog instance which is being passed to the constructor is being
+ automatically JIT compiled so one shouldn't call gallivm_cpu_jit_compile
+ with it again.
+ */
+struct gallivm_cpu_engine * gallivm_cpu_engine_create(struct gallivm_prog *prog)
+{
+ struct gallivm_cpu_engine *cpu = (struct gallivm_cpu_engine *)
+ calloc(1, sizeof(struct gallivm_cpu_engine));
+ llvm::Module *mod = static_cast<llvm::Module*>(prog->module);
+ llvm::ExistingModuleProvider *mp = new llvm::ExistingModuleProvider(mod);
+ llvm::ExecutionEngine *ee = llvm::ExecutionEngine::create(mp, false);
+ ee->DisableLazyCompilation();
+ cpu->engine = ee;
+
+ llvm::Function *func = func_for_shader(prog);
+
+ prog->function = ee->getPointerToFunction(func);
+ CPU = cpu;
+ return cpu;
+}
+
+
+/*!
+ This function JIT compiles the given gallivm_prog with the given cpu based execution engine.
+ The reference to the generated machine code entry point will be stored
+ in the gallivm_prog program. After executing this function one can call gallivm_prog_exec
+ in order to execute the gallivm_prog on the CPU.
+ */
+void gallivm_cpu_jit_compile(struct gallivm_cpu_engine *cpu, struct gallivm_prog *prog)
+{
+ llvm::Module *mod = static_cast<llvm::Module*>(prog->module);
+ llvm::ExistingModuleProvider *mp = new llvm::ExistingModuleProvider(mod);
+ llvm::ExecutionEngine *ee = cpu->engine;
+ assert(ee);
+ /*FIXME : why was this disabled ? we need it for pow/sqrt/... */
+ ee->DisableLazyCompilation(false);
+ ee->addModuleProvider(mp);
+
+ llvm::Function *func = func_for_shader(prog);
+ prog->function = ee->getPointerToFunction(func);
+}
+
+void gallivm_cpu_engine_delete(struct gallivm_cpu_engine *cpu)
+{
+ free(cpu);
+}
+
+struct gallivm_cpu_engine * gallivm_global_cpu_engine()
+{
+ return CPU;
+}
+
+
+typedef void (*vertex_shader_runner)(void *ainputs,
+ void *dests,
+ float (*aconsts)[4]);
+
+#define MAX_TGSI_VERTICES 4
+/*!
+ This function is used to execute the gallivm_prog in software. Before calling
+ this function the gallivm_prog has to be JIT compiled with the gallivm_cpu_jit_compile
+ function.
+ */
+int gallivm_cpu_vs_exec(struct gallivm_prog *prog,
+ struct tgsi_exec_machine *machine,
+ const float (*input)[4],
+ unsigned num_inputs,
+ float (*output)[4],
+ unsigned num_outputs,
+ const float (*constants)[4],
+ unsigned count,
+ unsigned input_stride,
+ unsigned output_stride )
+{
+ unsigned int i, j;
+ unsigned slot;
+ vertex_shader_runner runner = reinterpret_cast<vertex_shader_runner>(prog->function);
+ assert(runner);
+
+ for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
+ unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
+
+ /* Swizzle inputs.
+ */
+ for (j = 0; j < max_vertices; j++) {
+ for (slot = 0; slot < num_inputs; slot++) {
+ machine->Inputs[slot].xyzw[0].f[j] = input[slot][0];
+ machine->Inputs[slot].xyzw[1].f[j] = input[slot][1];
+ machine->Inputs[slot].xyzw[2].f[j] = input[slot][2];
+ machine->Inputs[slot].xyzw[3].f[j] = input[slot][3];
+ }
+
+ input = (const float (*)[4])((const char *)input + input_stride);
+ }
+
+ /* run shader */
+ runner(machine->Inputs,
+ machine->Outputs,
+ (float (*)[4]) constants);
+
+ /* Unswizzle all output results
+ */
+ for (j = 0; j < max_vertices; j++) {
+ for (slot = 0; slot < num_outputs; slot++) {
+ output[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
+ output[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
+ output[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
+ output[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
+ }
+ output = (float (*)[4])((char *)output + output_stride);
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/src/gallium/auxiliary/gallivm/gallivm_p.h b/src/gallium/auxiliary/gallivm/gallivm_p.h
new file mode 100644
index 0000000000..d2c5852bdf
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/gallivm_p.h
@@ -0,0 +1,110 @@
+#ifndef GALLIVM_P_H
+#define GALLIVM_P_H
+
+#ifdef MESA_LLVM
+
+#include "gallivm.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_compiler.h"
+
+namespace llvm {
+ class Module;
+}
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+enum gallivm_shader_type;
+enum gallivm_vector_layout;
+
+struct gallivm_interpolate {
+ int attrib;
+ int chan;
+ int type;
+};
+
+struct gallivm_ir {
+ llvm::Module *module;
+ int id;
+ enum gallivm_shader_type type;
+ enum gallivm_vector_layout layout;
+ int num_components;
+ int num_consts;
+
+ /* FIXME: this might not be enough for some shaders */
+ struct gallivm_interpolate interpolators[32*4];
+ int num_interp;
+};
+
+struct gallivm_prog {
+ llvm::Module *module;
+ void *function;
+
+ int id;
+ enum gallivm_shader_type type;
+
+ int num_consts;
+
+ /* FIXME: this might not be enough for some shaders */
+ struct gallivm_interpolate interpolators[32*4];
+ int num_interp;
+};
+
+static INLINE void gallivm_swizzle_components(int swizzle,
+ int *xc, int *yc,
+ int *zc, int *wc)
+{
+ int x = swizzle / 1000; swizzle -= x * 1000;
+ int y = swizzle / 100; swizzle -= y * 100;
+ int z = swizzle / 10; swizzle -= z * 10;
+ int w = swizzle;
+
+ if (xc) *xc = x;
+ if (yc) *yc = y;
+ if (zc) *zc = z;
+ if (wc) *wc = w;
+}
+
+static INLINE boolean gallivm_is_swizzle(int swizzle)
+{
+ const int NO_SWIZZLE = TGSI_SWIZZLE_X * 1000 + TGSI_SWIZZLE_Y * 100 +
+ TGSI_SWIZZLE_Z * 10 + TGSI_SWIZZLE_W;
+ return swizzle != NO_SWIZZLE;
+}
+
+static INLINE int gallivm_x_swizzle(int swizzle)
+{
+ int x;
+ gallivm_swizzle_components(swizzle, &x, 0, 0, 0);
+ return x;
+}
+
+static INLINE int gallivm_y_swizzle(int swizzle)
+{
+ int y;
+ gallivm_swizzle_components(swizzle, 0, &y, 0, 0);
+ return y;
+}
+
+static INLINE int gallivm_z_swizzle(int swizzle)
+{
+ int z;
+ gallivm_swizzle_components(swizzle, 0, 0, &z, 0);
+ return z;
+}
+
+static INLINE int gallivm_w_swizzle(int swizzle)
+{
+ int w;
+ gallivm_swizzle_components(swizzle, 0, 0, 0, &w);
+ return w;
+}
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* MESA_LLVM */
+
+#endif
diff --git a/src/gallium/auxiliary/gallivm/instructions.cpp b/src/gallium/auxiliary/gallivm/instructions.cpp
new file mode 100644
index 0000000000..ee8162efce
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/instructions.cpp
@@ -0,0 +1,1193 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+#ifdef MESA_LLVM
+
+#include "instructions.h"
+
+#include "storage.h"
+
+#include "util/u_memory.h"
+
+#include <llvm/CallingConv.h>
+#include <llvm/Constants.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Function.h>
+#include <llvm/InstrTypes.h>
+#include <llvm/Instructions.h>
+#include <llvm/Attributes.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+using namespace llvm;
+
+#include "gallivm_builtins.cpp"
+
+#if 0
+llvm::Value *arrayFromChannels(std::vector<llvm::Value*> &vals)
+{
+ VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
+ ArrayType *vectorArray = ArrayType::get(vectorType, 4);
+}
+#endif
+
+static inline std::string createFuncName(int label)
+{
+ std::ostringstream stream;
+ stream << "function";
+ stream << label;
+ return stream.str();
+}
+
+Instructions::Instructions(llvm::Module *mod, llvm::Function *func, llvm::BasicBlock *block,
+ Storage *storage)
+ : m_mod(mod), m_func(func), m_builder(block), m_idx(0),
+ m_storage(storage)
+{
+ m_floatVecType = VectorType::get(Type::FloatTy, 4);
+
+ m_llvmFSqrt = 0;
+ m_llvmFAbs = 0;
+ m_llvmPow = 0;
+ m_llvmFloor = 0;
+ m_llvmFlog = 0;
+ m_llvmFexp = 0;
+ m_llvmLit = 0;
+ m_fmtPtr = 0;
+
+ MemoryBuffer *buffer = MemoryBuffer::getMemBuffer(
+ (const char*)&llvm_builtins_data[0],
+ (const char*)&llvm_builtins_data[Elements(llvm_builtins_data)-1]);
+ m_mod = ParseBitcodeFile(buffer);
+}
+
+llvm::BasicBlock * Instructions::currentBlock() const
+{
+ return m_builder.GetInsertBlock();
+}
+
+llvm::Value * Instructions::abs(llvm::Value *in)
+{
+ std::vector<llvm::Value*> vec = extractVector(in);
+ Value *xabs = callFAbs(vec[0]);
+ Value *yabs = callFAbs(vec[1]);
+ Value *zabs = callFAbs(vec[2]);
+ Value *wabs = callFAbs(vec[3]);
+ return vectorFromVals(xabs, yabs, zabs, wabs);
+}
+
+llvm::Value * Instructions::add(llvm::Value *in1, llvm::Value *in2)
+{
+ return m_builder.CreateAdd(in1, in2, name("add"));
+}
+
+llvm::Value * Instructions::arl(llvm::Value *in)
+{
+ return floor(in);
+}
+
+void Instructions::beginLoop()
+{
+ BasicBlock *begin = BasicBlock::Create(name("loop"), m_func,0);
+ BasicBlock *end = BasicBlock::Create(name("endloop"), m_func,0);
+
+ m_builder.CreateBr(begin);
+ Loop loop;
+ loop.begin = begin;
+ loop.end = end;
+ m_builder.SetInsertPoint(begin);
+ m_loopStack.push(loop);
+}
+
+void Instructions::bgnSub(unsigned label)
+{
+ llvm::Function *func = findFunction(label);
+
+ Function::arg_iterator args = func->arg_begin();
+ Value *ptr_INPUT = args++;
+ ptr_INPUT->setName("INPUT");
+ m_storage->pushArguments(ptr_INPUT);
+
+ llvm::BasicBlock *entry = BasicBlock::Create("entry", func, 0);
+
+ m_func = func;
+ m_builder.SetInsertPoint(entry);
+}
+
+void Instructions::brk()
+{
+ assert(!m_loopStack.empty());
+ BasicBlock *unr = BasicBlock::Create(name("unreachable"), m_func,0);
+ m_builder.CreateBr(m_loopStack.top().end);
+ m_builder.SetInsertPoint(unr);
+}
+
+void Instructions::cal(int label, llvm::Value *input)
+{
+ std::vector<Value*> params;
+ params.push_back(input);
+ llvm::Function *func = findFunction(label);
+
+ m_builder.CreateCall(func, params.begin(), params.end());
+}
+
+llvm::Value * Instructions::ceil(llvm::Value *in)
+{
+ std::vector<llvm::Value*> vec = extractVector(in);
+ return vectorFromVals(callCeil(vec[0]), callCeil(vec[1]),
+ callCeil(vec[2]), callCeil(vec[3]));
+}
+
+llvm::Value * Instructions::clamp(llvm::Value *in1)
+{
+ llvm::Value *zero = constVector(0.0f, 0.0f, 0.0f, 0.0f);
+ llvm::Value *one = constVector(1.0f, 1.0f, 1.0f, 1.0f);
+ return min( max(zero, in1), one);
+}
+
+llvm::Value * Instructions::cmp(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
+{
+ llvm::Function *func = m_mod->getFunction("cmp");
+ assert(func);
+
+ std::vector<Value*> params;
+ params.push_back(in1);
+ params.push_back(in2);
+ params.push_back(in3);
+ CallInst *call = m_builder.CreateCall(func, params.begin(), params.end(), name("cmpres"));
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::cnd(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
+{
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+ std::vector<llvm::Value*> vec3 = extractVector(in3);
+ Constant *half = ConstantFP::get(APFloat(0.5f));
+
+ Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], half, name("xcmp"));
+ Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0],
+ name("selx"));
+
+ Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], half, name("ycmp"));
+ Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1],
+ name("sely"));
+
+ Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], half, name("zcmp"));
+ Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2],
+ name("selz"));
+
+ Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], half, name("wcmp"));
+ Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3],
+ name("selw"));
+
+ return vectorFromVals(selx, sely, selz, selw);
+}
+
+llvm::Value * Instructions::cnd0(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
+{
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+ std::vector<llvm::Value*> vec3 = extractVector(in3);
+ Constant *zero = Constant::getNullValue(Type::FloatTy);
+
+ Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], zero, name("xcmp"));
+ Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0],
+ name("selx"));
+
+ Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], zero, name("ycmp"));
+ Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1],
+ name("sely"));
+
+ Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], zero, name("zcmp"));
+ Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2],
+ name("selz"));
+
+ Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], zero, name("wcmp"));
+ Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3],
+ name("selw"));
+
+ return vectorFromVals(selx, sely, selz, selw);
+}
+
+llvm::Value * Instructions::cos(llvm::Value *in)
+{
+#if 0
+ llvm::Function *func = m_mod->getFunction("vcos");
+ assert(func);
+
+ CallInst *call = m_builder.CreateCall(func, in, name("cosres"));
+ call->setTailCall(false);
+ return call;
+#else
+ std::vector<llvm::Value*> elems = extractVector(in);
+ Function *func = m_mod->getFunction("cosf");
+ assert(func);
+ CallInst *cos = m_builder.CreateCall(func, elems[0], name("cosres"));
+ cos->setCallingConv(CallingConv::C);
+ cos->setTailCall(true);
+ return vectorFromVals(cos, cos, cos, cos);
+#endif
+}
+
+llvm::Value * Instructions::cross(llvm::Value *in1, llvm::Value *in2)
+{
+ Value *x1 = m_builder.CreateExtractElement(in1,
+ m_storage->constantInt(0),
+ name("x1"));
+ Value *y1 = m_builder.CreateExtractElement(in1,
+ m_storage->constantInt(1),
+ name("y1"));
+ Value *z1 = m_builder.CreateExtractElement(in1,
+ m_storage->constantInt(2),
+ name("z1"));
+
+ Value *x2 = m_builder.CreateExtractElement(in2,
+ m_storage->constantInt(0),
+ name("x2"));
+ Value *y2 = m_builder.CreateExtractElement(in2,
+ m_storage->constantInt(1),
+ name("y2"));
+ Value *z2 = m_builder.CreateExtractElement(in2,
+ m_storage->constantInt(2),
+ name("z2"));
+ Value *y1z2 = mul(y1, z2);
+ Value *z1y2 = mul(z1, y2);
+
+ Value *z1x2 = mul(z1, x2);
+ Value *x1z2 = mul(x1, z2);
+
+ Value *x1y2 = mul(x1, y2);
+ Value *y1x2 = mul(y1, x2);
+
+ return vectorFromVals(sub(y1z2, z1y2), sub(z1x2, x1z2), sub(x1y2, y1x2));
+}
+
+llvm::Value * Instructions::ddx(llvm::Value *in)
+{
+ // FIXME
+ assert(0);
+}
+
+llvm::Value * Instructions::ddy(llvm::Value *in)
+{
+ // FIXME
+ assert(0);
+}
+
+llvm::Value * Instructions::div(llvm::Value *in1, llvm::Value *in2)
+{
+ return m_builder.CreateFDiv(in1, in2, name("div"));
+}
+
+llvm::Value * Instructions::dot2add(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
+{
+ Value *mulRes = mul(in1, in2);
+ Value *x = m_builder.CreateExtractElement(mulRes,
+ m_storage->constantInt(0),
+ name("extractx"));
+ Value *y = m_builder.CreateExtractElement(mulRes,
+ m_storage->constantInt(1),
+ name("extracty"));
+ Value *z = m_builder.CreateExtractElement(in3,
+ m_storage->constantInt(2),
+ name("extractz"));
+ Value *xy = m_builder.CreateAdd(x, y,name("xy"));
+ Value *dot2add = m_builder.CreateAdd(xy, z, name("dot2add"));
+ return vectorFromVals(dot2add, dot2add, dot2add, dot2add);
+}
+
+llvm::Value * Instructions::dp2(llvm::Value *in1, llvm::Value *in2)
+{
+ Value *mulRes = mul(in1, in2);
+ Value *x = m_builder.CreateExtractElement(mulRes,
+ m_storage->constantInt(0),
+ name("extractx"));
+ Value *y = m_builder.CreateExtractElement(mulRes,
+ m_storage->constantInt(1),
+ name("extracty"));
+ Value *xy = m_builder.CreateAdd(x, y,name("xy"));
+ return vectorFromVals(xy, xy, xy, xy);
+}
+
+llvm::Value * Instructions::dp3(llvm::Value *in1, llvm::Value *in2)
+{
+ Value *mulRes = mul(in1, in2);
+ Value *x = m_builder.CreateExtractElement(mulRes,
+ m_storage->constantInt(0),
+ name("extractx"));
+ Value *y = m_builder.CreateExtractElement(mulRes,
+ m_storage->constantInt(1),
+ name("extracty"));
+ Value *z = m_builder.CreateExtractElement(mulRes,
+ m_storage->constantInt(2),
+ name("extractz"));
+ Value *xy = m_builder.CreateAdd(x, y,name("xy"));
+ Value *dot3 = m_builder.CreateAdd(xy, z, name("dot3"));
+ return vectorFromVals(dot3, dot3, dot3, dot3);
+}
+
+llvm::Value * Instructions::dp4(llvm::Value *in1, llvm::Value *in2)
+{
+ Value *mulRes = mul(in1, in2);
+ std::vector<llvm::Value*> vec = extractVector(mulRes);
+ Value *xy = m_builder.CreateAdd(vec[0], vec[1], name("xy"));
+ Value *xyz = m_builder.CreateAdd(xy, vec[2], name("xyz"));
+ Value *dot4 = m_builder.CreateAdd(xyz, vec[3], name("dot4"));
+ return vectorFromVals(dot4, dot4, dot4, dot4);
+}
+
+llvm::Value * Instructions::dph(llvm::Value *in1, llvm::Value *in2)
+{
+ Value *mulRes = mul(in1, in2);
+ std::vector<llvm::Value*> vec1 = extractVector(mulRes);
+ Value *xy = m_builder.CreateAdd(vec1[0], vec1[1], name("xy"));
+ Value *xyz = m_builder.CreateAdd(xy, vec1[2], name("xyz"));
+ Value *dph = m_builder.CreateAdd(xyz, vec1[3], name("dph"));
+ return vectorFromVals(dph, dph, dph, dph);
+}
+
+llvm::Value * Instructions::dst(llvm::Value *in1, llvm::Value *in2)
+{
+ Value *y1 = m_builder.CreateExtractElement(in1,
+ m_storage->constantInt(1),
+ name("y1"));
+ Value *z = m_builder.CreateExtractElement(in1,
+ m_storage->constantInt(2),
+ name("z"));
+ Value *y2 = m_builder.CreateExtractElement(in2,
+ m_storage->constantInt(1),
+ name("y2"));
+ Value *w = m_builder.CreateExtractElement(in2,
+ m_storage->constantInt(3),
+ name("w"));
+ Value *ry = m_builder.CreateMul(y1, y2, name("tyuy"));
+ return vectorFromVals(ConstantFP::get(APFloat(1.f)),
+ ry, z, w);
+}
+
+void Instructions::elseop()
+{
+ assert(!m_ifStack.empty());
+ BasicBlock *ifend = BasicBlock::Create(name("ifend"), m_func,0);
+ m_builder.CreateBr(ifend);
+ m_builder.SetInsertPoint(m_ifStack.top());
+ currentBlock()->setName(name("ifelse"));
+ m_ifStack.pop();
+ m_ifStack.push(ifend);
+}
+
+void Instructions::endif()
+{
+ assert(!m_ifStack.empty());
+ m_builder.CreateBr(m_ifStack.top());
+ m_builder.SetInsertPoint(m_ifStack.top());
+ m_ifStack.pop();
+}
+
+void Instructions::endLoop()
+{
+ assert(!m_loopStack.empty());
+ Loop loop = m_loopStack.top();
+ m_builder.CreateBr(loop.begin);
+ loop.end->moveAfter(currentBlock());
+ m_builder.SetInsertPoint(loop.end);
+ m_loopStack.pop();
+}
+
+void Instructions::end()
+{
+ m_builder.CreateRetVoid();
+}
+
+void Instructions::endSub()
+{
+ m_func = 0;
+ m_builder.SetInsertPoint(0);
+}
+
+llvm::Value * Instructions::exp(llvm::Value *in)
+{
+ std::vector<llvm::Value*> vec = extractVector(in);
+ return vectorFromVals(callFExp(vec[0]), callFExp(vec[1]),
+ callFExp(vec[2]), callFExp(vec[3]));
+}
+
+llvm::Value * Instructions::ex2(llvm::Value *in)
+{
+ llvm::Value *val = callPow(ConstantFP::get(APFloat(2.f)),
+ m_builder.CreateExtractElement(
+ in, m_storage->constantInt(0),
+ name("x1")));
+ return vectorFromVals(val, val, val, val);
+}
+
+llvm::Value * Instructions::floor(llvm::Value *in)
+{
+ std::vector<llvm::Value*> vec = extractVector(in);
+ return vectorFromVals(callFloor(vec[0]), callFloor(vec[1]),
+ callFloor(vec[2]), callFloor(vec[3]));
+}
+
+llvm::Value * Instructions::frc(llvm::Value *in)
+{
+ llvm::Value *flr = floor(in);
+ return sub(in, flr);
+}
+
+void Instructions::ifop(llvm::Value *in)
+{
+ BasicBlock *ifthen = BasicBlock::Create(name("ifthen"), m_func,0);
+ BasicBlock *ifend = BasicBlock::Create(name("ifthenend"), m_func,0);
+
+ //BasicBlock *yblock = new BasicBlock(name("yblock"), m_func,0);
+ //BasicBlock *zblock = new BasicBlock(name("zblock"), m_func,0);
+ //BasicBlock *wblock = new BasicBlock(name("wblock"), m_func,0);
+
+ Constant *float0 = Constant::getNullValue(Type::FloatTy);
+
+ Value *x = m_builder.CreateExtractElement(in, m_storage->constantInt(0),
+ name("extractx"));
+ Value *xcmp = m_builder.CreateFCmpUNE(x, float0, name("xcmp"));
+ m_builder.CreateCondBr(xcmp, ifthen, ifend);
+ //m_builder.SetInsertPoint(yblock);
+
+ m_builder.SetInsertPoint(ifthen);
+ m_ifStack.push(ifend);
+}
+
+llvm::Value * Instructions::kil(llvm::Value *in)
+{
+ llvm::Function *func = m_mod->getFunction("kil");
+ assert(func);
+
+ CallInst *call = m_builder.CreateCall(func, in, name("kilpres"));
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::lerp(llvm::Value *in1, llvm::Value *in2,
+ llvm::Value *in3)
+{
+ llvm::Value *m = mul(in1, in2);
+ llvm::Value *vec1 = constVector(1.f, 1.f, 1.f, 1.f);
+ llvm::Value *s = sub(vec1, in1);
+ return add(m, mul(s, in3));
+}
+
+llvm::Value * Instructions::lg2(llvm::Value *in)
+{
+ std::vector<llvm::Value*> vec = extractVector(in);
+ llvm::Value *const_vec = constVector(1.442695f, 1.442695f,
+ 1.442695f, 1.442695f);
+ return mul(vectorFromVals(callFLog(vec[0]), callFLog(vec[1]),
+ callFLog(vec[2]), callFLog(vec[3])), const_vec);
+}
+
+llvm::Value * Instructions::lit(llvm::Value *in)
+{
+ if (!m_llvmLit) {
+ m_llvmLit = m_mod->getFunction("lit");
+ }
+ CallInst *call = m_builder.CreateCall(m_llvmLit, in, name("litres"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::log(llvm::Value *in)
+{
+ std::vector<llvm::Value*> vec = extractVector(in);
+ return vectorFromVals(callFLog(vec[0]), callFLog(vec[1]),
+ callFLog(vec[2]), callFLog(vec[3]));
+}
+
+llvm::Value * Instructions::madd(llvm::Value *in1, llvm::Value *in2,
+ llvm::Value *in3)
+{
+ Value *mulRes = mul(in1, in2);
+ return add(mulRes, in3);
+}
+
+llvm::Value * Instructions::max(llvm::Value *in1, llvm::Value *in2)
+{
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+
+ Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0],
+ name("xcmp"));
+ Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
+ name("selx"));
+
+ Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1],
+ name("ycmp"));
+ Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
+ name("sely"));
+
+ Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2],
+ name("zcmp"));
+ Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
+ name("selz"));
+
+ Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3],
+ name("wcmp"));
+ Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
+ name("selw"));
+
+ return vectorFromVals(selx, sely, selz, selw);
+}
+
+llvm::Value * Instructions::min(llvm::Value *in1, llvm::Value *in2)
+{
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+
+ Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
+ Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
+ name("selx"));
+
+ Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
+ Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
+ name("sely"));
+
+ Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
+ Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
+ name("selz"));
+
+ Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
+ Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
+ name("selw"));
+
+ return vectorFromVals(selx, sely, selz, selw);
+}
+
+llvm::Value * Instructions::mul(llvm::Value *in1, llvm::Value *in2)
+{
+ return m_builder.CreateMul(in1, in2, name("mul"));
+}
+
+llvm::Value * Instructions::neg(llvm::Value *in)
+{
+ Value *neg = m_builder.CreateNeg(in, name("neg"));
+ return neg;
+}
+
+llvm::Value * Instructions::nrm(llvm::Value *in)
+{
+ llvm::Value *v = rsq(in);
+ return mul(v, in);
+}
+
+llvm::Value * Instructions::pow(llvm::Value *in1, llvm::Value *in2)
+{
+ Value *x1 = m_builder.CreateExtractElement(in1,
+ m_storage->constantInt(0),
+ name("x1"));
+ Value *x2 = m_builder.CreateExtractElement(in2,
+ m_storage->constantInt(0),
+ name("x2"));
+ llvm::Value *val = callPow(x1, x2);
+ return vectorFromVals(val, val, val, val);
+}
+
+llvm::Value * Instructions::rcp(llvm::Value *in1)
+{
+ Value *x1 = m_builder.CreateExtractElement(in1,
+ m_storage->constantInt(0),
+ name("x1"));
+ Value *res = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)),
+ x1, name("rcp"));
+ return vectorFromVals(res, res, res, res);
+}
+
+llvm::Value * Instructions::rsq(llvm::Value *in1)
+{
+ Value *x = m_builder.CreateExtractElement(in1,
+ m_storage->constantInt(0),
+ name("extractx"));
+ Value *abs = callFAbs(x);
+ Value *sqrt = callFSqrt(abs);
+
+ Value *rsqrt = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)),
+ sqrt,
+ name("rsqrt"));
+ return vectorFromVals(rsqrt, rsqrt, rsqrt, rsqrt);
+}
+
+llvm::Value * Instructions::scs(llvm::Value *in)
+{
+ llvm::Function *func = m_mod->getFunction("scs");
+ assert(func);
+
+ CallInst *call = m_builder.CreateCall(func, in, name("scsres"));
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::seq(llvm::Value *in1, llvm::Value *in2)
+{
+ Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
+ Constant *const0f = Constant::getNullValue(Type::FloatTy);
+
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+
+ Value *xcmp = m_builder.CreateFCmpOEQ(vec1[0], vec2[0], name("xcmp"));
+ Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
+
+ Value *ycmp = m_builder.CreateFCmpOEQ(vec1[1], vec2[1], name("ycmp"));
+ Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
+
+ Value *zcmp = m_builder.CreateFCmpOEQ(vec1[2], vec2[2], name("zcmp"));
+ Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
+
+ Value *wcmp = m_builder.CreateFCmpOEQ(vec1[3], vec2[3], name("wcmp"));
+ Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
+
+ return vectorFromVals(x, y, z, w);
+}
+
+llvm::Value * Instructions::sfl(llvm::Value *in1, llvm::Value *in2)
+{
+ Constant *const0f = Constant::getNullValue(Type::FloatTy);
+
+ return vectorFromVals(const0f, const0f, const0f, const0f);
+}
+
+llvm::Value * Instructions::sge(llvm::Value *in1, llvm::Value *in2)
+{
+ Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
+ Constant *const0f = Constant::getNullValue(Type::FloatTy);
+
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+
+ Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], vec2[0], name("xcmp"));
+ Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
+
+ Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], vec2[1], name("ycmp"));
+ Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
+
+ Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], vec2[2], name("zcmp"));
+ Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
+
+ Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], vec2[3], name("wcmp"));
+ Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
+
+ return vectorFromVals(x, y, z, w);
+}
+
+llvm::Value * Instructions::sgt(llvm::Value *in1, llvm::Value *in2)
+{
+ Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
+ Constant *const0f = Constant::getNullValue(Type::FloatTy);
+
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+ Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0], name("xcmp"));
+ Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
+
+ Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1], name("ycmp"));
+ Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
+
+ Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2], name("zcmp"));
+ Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
+
+ Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3], name("wcmp"));
+ Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
+
+ return vectorFromVals(x, y, z, w);
+}
+
+llvm::Value * Instructions::sin(llvm::Value *in)
+{
+ llvm::Function *func = m_mod->getFunction("vsin");
+ assert(func);
+
+ CallInst *call = m_builder.CreateCall(func, in, name("sinres"));
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::sle(llvm::Value *in1, llvm::Value *in2)
+{
+ Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
+ Constant *const0f = Constant::getNullValue(Type::FloatTy);
+
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+
+ Value *xcmp = m_builder.CreateFCmpOLE(vec1[0], vec2[0], name("xcmp"));
+ Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
+
+ Value *ycmp = m_builder.CreateFCmpOLE(vec1[1], vec2[1], name("ycmp"));
+ Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
+
+ Value *zcmp = m_builder.CreateFCmpOLE(vec1[2], vec2[2], name("zcmp"));
+ Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
+
+ Value *wcmp = m_builder.CreateFCmpOLE(vec1[3], vec2[3], name("wcmp"));
+ Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
+
+ return vectorFromVals(x, y, z, w);
+}
+
+llvm::Value * Instructions::slt(llvm::Value *in1, llvm::Value *in2)
+{
+ Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
+ Constant *const0f = Constant::getNullValue(Type::FloatTy);
+
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+
+ Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
+ Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
+
+ Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
+ Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
+
+ Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
+ Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
+
+ Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
+ Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
+
+ return vectorFromVals(x, y, z, w);
+}
+
+llvm::Value * Instructions::sne(llvm::Value *in1, llvm::Value *in2)
+{
+ Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
+ Constant *const0f = Constant::getNullValue(Type::FloatTy);
+
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+
+ Value *xcmp = m_builder.CreateFCmpONE(vec1[0], vec2[0], name("xcmp"));
+ Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
+
+ Value *ycmp = m_builder.CreateFCmpONE(vec1[1], vec2[1], name("ycmp"));
+ Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
+
+ Value *zcmp = m_builder.CreateFCmpONE(vec1[2], vec2[2], name("zcmp"));
+ Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
+
+ Value *wcmp = m_builder.CreateFCmpONE(vec1[3], vec2[3], name("wcmp"));
+ Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
+
+ return vectorFromVals(x, y, z, w);
+}
+
+llvm::Value * Instructions::str(llvm::Value *in1, llvm::Value *in2)
+{
+ Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
+
+ return vectorFromVals(const1f, const1f, const1f, const1f);
+}
+
+llvm::Value * Instructions::sub(llvm::Value *in1, llvm::Value *in2)
+{
+ Value *res = m_builder.CreateSub(in1, in2, name("sub"));
+ return res;
+}
+
+llvm::Value * Instructions::trunc(llvm::Value *in)
+{
+ std::vector<llvm::Value*> vec = extractVector(in);
+ Value *icastx = m_builder.CreateFPToSI(vec[0], IntegerType::get(32),
+ name("ftoix"));
+ Value *icasty = m_builder.CreateFPToSI(vec[1], IntegerType::get(32),
+ name("ftoiy"));
+ Value *icastz = m_builder.CreateFPToSI(vec[2], IntegerType::get(32),
+ name("ftoiz"));
+ Value *icastw = m_builder.CreateFPToSI(vec[3], IntegerType::get(32),
+ name("ftoiw"));
+ Value *fx = m_builder.CreateSIToFP(icastx, Type::FloatTy,
+ name("fx"));
+ Value *fy = m_builder.CreateSIToFP(icasty, Type::FloatTy,
+ name("fy"));
+ Value *fz = m_builder.CreateSIToFP(icastz, Type::FloatTy,
+ name("fz"));
+ Value *fw = m_builder.CreateSIToFP(icastw, Type::FloatTy,
+ name("fw"));
+ return vectorFromVals(fx, fy, fz, fw);
+}
+
+llvm::Value * Instructions::x2d(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
+{
+ std::vector<llvm::Value*> vec1 = extractVector(in1);
+ std::vector<llvm::Value*> vec2 = extractVector(in2);
+ std::vector<llvm::Value*> vec3 = extractVector(in3);
+
+ Value *x2x3 = m_builder.CreateMul( vec2[0], vec3[0], name("x2x3"));
+ Value *y2y3 = m_builder.CreateMul( vec2[1], vec3[1], name("y2y3"));
+ Value *x1px2x3 = m_builder.CreateAdd (vec1[0], x2x3, name("x1 + x2x3"));
+ Value *x1px2x3py2y3 = m_builder.CreateAdd (x1px2x3, y2y3, name("x1 + x2x3 + y2y3"));
+
+ Value *x2z3 = m_builder.CreateMul( vec2[0], vec3[2], name("x2z3"));
+ Value *y2w3 = m_builder.CreateMul( vec2[1], vec3[3], name("y2w3"));
+ Value *y1px2z3 = m_builder.CreateAdd (vec1[1], x2z3, name("y1 + x2z3"));
+ Value *y1px2z3py2w3 = m_builder.CreateAdd (y1px2z3, y2w3, name("y1 + x2z3 + y2w3"));
+
+ return vectorFromVals(x1px2x3py2y3, y1px2z3py2w3, x1px2x3py2y3, y1px2z3py2w3);
+}
+
+void Instructions::printVector(llvm::Value *val)
+{
+ static const char *frmt = "Vector is [%f, %f, %f, %f]\x0A";
+
+ if (!m_fmtPtr) {
+ Constant *format = ConstantArray::get(frmt, true);
+ ArrayType *arrayTy = ArrayType::get(IntegerType::get(8), strlen(frmt) + 1);
+ GlobalVariable* globalFormat = new GlobalVariable(
+ /*Type=*/arrayTy,
+ /*isConstant=*/true,
+ /*Linkage=*/GlobalValue::InternalLinkage,
+ /*Initializer=*/0, // has initializer, specified below
+ /*Name=*/name(".str"),
+ m_mod);
+ globalFormat->setInitializer(format);
+
+ Constant* const_int0 = Constant::getNullValue(IntegerType::get(32));
+ std::vector<Constant*> const_ptr_21_indices;
+ const_ptr_21_indices.push_back(const_int0);
+ const_ptr_21_indices.push_back(const_int0);
+ m_fmtPtr = ConstantExpr::getGetElementPtr(globalFormat,
+ &const_ptr_21_indices[0], const_ptr_21_indices.size());
+ }
+
+ Function *func_printf = m_mod->getFunction("printf");
+ if (!func_printf)
+ func_printf = declarePrintf();
+ assert(func_printf);
+ std::vector<llvm::Value*> vec = extractVector(val);
+ Value *dx = m_builder.CreateFPExt(vec[0], Type::DoubleTy, name("dx"));
+ Value *dy = m_builder.CreateFPExt(vec[1], Type::DoubleTy, name("dy"));
+ Value *dz = m_builder.CreateFPExt(vec[2], Type::DoubleTy, name("dz"));
+ Value *dw = m_builder.CreateFPExt(vec[3], Type::DoubleTy, name("dw"));
+ std::vector<Value*> params;
+ params.push_back(m_fmtPtr);
+ params.push_back(dx);
+ params.push_back(dy);
+ params.push_back(dz);
+ params.push_back(dw);
+ CallInst *call = m_builder.CreateCall(func_printf, params.begin(), params.end(),
+ name("printf"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(true);
+}
+
+const char * Instructions::name(const char *prefix)
+{
+ ++m_idx;
+ snprintf(m_name, 32, "%s%d", prefix, m_idx);
+ return m_name;
+}
+
+llvm::Value * Instructions::callCeil(llvm::Value *val)
+{
+ if (!m_llvmCeil) {
+ // predeclare the intrinsic
+ std::vector<const Type*> ceilArgs;
+ ceilArgs.push_back(Type::FloatTy);
+ AttrListPtr ceilPal;
+ FunctionType* ceilType = FunctionType::get(
+ /*Result=*/Type::FloatTy,
+ /*Params=*/ceilArgs,
+ /*isVarArg=*/false);
+ m_llvmCeil = Function::Create(
+ /*Type=*/ceilType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"ceilf", m_mod);
+ m_llvmCeil->setCallingConv(CallingConv::C);
+ m_llvmCeil->setAttributes(ceilPal);
+ }
+ CallInst *call = m_builder.CreateCall(m_llvmCeil, val,
+ name("ceilf"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value *Instructions::callFAbs(llvm::Value *val)
+{
+ if (!m_llvmFAbs) {
+ // predeclare the intrinsic
+ std::vector<const Type*> fabsArgs;
+ fabsArgs.push_back(Type::FloatTy);
+ AttrListPtr fabsPal;
+ FunctionType* fabsType = FunctionType::get(
+ /*Result=*/Type::FloatTy,
+ /*Params=*/fabsArgs,
+ /*isVarArg=*/false);
+ m_llvmFAbs = Function::Create(
+ /*Type=*/fabsType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"fabs", m_mod);
+ m_llvmFAbs->setCallingConv(CallingConv::C);
+ m_llvmFAbs->setAttributes(fabsPal);
+ }
+ CallInst *call = m_builder.CreateCall(m_llvmFAbs, val,
+ name("fabs"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::callFExp(llvm::Value *val)
+{
+ if (!m_llvmFexp) {
+ // predeclare the intrinsic
+ std::vector<const Type*> fexpArgs;
+ fexpArgs.push_back(Type::FloatTy);
+ AttrListPtr fexpPal;
+ FunctionType* fexpType = FunctionType::get(
+ /*Result=*/Type::FloatTy,
+ /*Params=*/fexpArgs,
+ /*isVarArg=*/false);
+ m_llvmFexp = Function::Create(
+ /*Type=*/fexpType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"expf", m_mod);
+ m_llvmFexp->setCallingConv(CallingConv::C);
+ m_llvmFexp->setAttributes(fexpPal);
+ }
+ CallInst *call = m_builder.CreateCall(m_llvmFexp, val,
+ name("expf"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::callFLog(llvm::Value *val)
+{
+ if (!m_llvmFlog) {
+ // predeclare the intrinsic
+ std::vector<const Type*> flogArgs;
+ flogArgs.push_back(Type::FloatTy);
+ AttrListPtr flogPal;
+ FunctionType* flogType = FunctionType::get(
+ /*Result=*/Type::FloatTy,
+ /*Params=*/flogArgs,
+ /*isVarArg=*/false);
+ m_llvmFlog = Function::Create(
+ /*Type=*/flogType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"logf", m_mod);
+ m_llvmFlog->setCallingConv(CallingConv::C);
+ m_llvmFlog->setAttributes(flogPal);
+ }
+ CallInst *call = m_builder.CreateCall(m_llvmFlog, val,
+ name("logf"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::callFloor(llvm::Value *val)
+{
+ if (!m_llvmFloor) {
+ // predeclare the intrinsic
+ std::vector<const Type*> floorArgs;
+ floorArgs.push_back(Type::FloatTy);
+ AttrListPtr floorPal;
+ FunctionType* floorType = FunctionType::get(
+ /*Result=*/Type::FloatTy,
+ /*Params=*/floorArgs,
+ /*isVarArg=*/false);
+ m_llvmFloor = Function::Create(
+ /*Type=*/floorType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"floorf", m_mod);
+ m_llvmFloor->setCallingConv(CallingConv::C);
+ m_llvmFloor->setAttributes(floorPal);
+ }
+ CallInst *call = m_builder.CreateCall(m_llvmFloor, val,
+ name("floorf"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value *Instructions::callFSqrt(llvm::Value *val)
+{
+ if (!m_llvmFSqrt) {
+ // predeclare the intrinsic
+ std::vector<const Type*> fsqrtArgs;
+ fsqrtArgs.push_back(Type::FloatTy);
+ AttrListPtr fsqrtPal;
+ FunctionType* fsqrtType = FunctionType::get(
+ /*Result=*/Type::FloatTy,
+ /*Params=*/fsqrtArgs,
+ /*isVarArg=*/false);
+ m_llvmFSqrt = Function::Create(
+ /*Type=*/fsqrtType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"llvm.sqrt.f32", m_mod);
+ m_llvmFSqrt->setCallingConv(CallingConv::C);
+ m_llvmFSqrt->setAttributes(fsqrtPal);
+ }
+ CallInst *call = m_builder.CreateCall(m_llvmFSqrt, val,
+ name("sqrt"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::callPow(llvm::Value *val1, llvm::Value *val2)
+{
+ if (!m_llvmPow) {
+ // predeclare the intrinsic
+ std::vector<const Type*> powArgs;
+ powArgs.push_back(Type::FloatTy);
+ powArgs.push_back(Type::FloatTy);
+ AttrListPtr powPal;
+ FunctionType* powType = FunctionType::get(
+ /*Result=*/Type::FloatTy,
+ /*Params=*/powArgs,
+ /*isVarArg=*/false);
+ m_llvmPow = Function::Create(
+ /*Type=*/powType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"llvm.pow.f32", m_mod);
+ m_llvmPow->setCallingConv(CallingConv::C);
+ m_llvmPow->setAttributes(powPal);
+ }
+ std::vector<Value*> params;
+ params.push_back(val1);
+ params.push_back(val2);
+ CallInst *call = m_builder.CreateCall(m_llvmPow, params.begin(), params.end(),
+ name("pow"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::vectorFromVals(llvm::Value *x, llvm::Value *y,
+ llvm::Value *z, llvm::Value *w)
+{
+ Constant *const_vec = Constant::getNullValue(m_floatVecType);
+ Value *res = m_builder.CreateInsertElement(const_vec, x,
+ m_storage->constantInt(0),
+ name("vecx"));
+ res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1),
+ name("vecxy"));
+ res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2),
+ name("vecxyz"));
+ if (w)
+ res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3),
+ name("vecxyzw"));
+ return res;
+}
+
+llvm::Value * Instructions::constVector(float x, float y, float z, float w)
+{
+ std::vector<Constant*> vec(4);
+ vec[0] = ConstantFP::get(APFloat(x));
+ vec[1] = ConstantFP::get(APFloat(y));
+ vec[2] = ConstantFP::get(APFloat(z));
+ vec[3] = ConstantFP::get(APFloat(w));
+ return ConstantVector::get(m_floatVecType, vec);
+}
+
+llvm::Function * Instructions::declarePrintf()
+{
+ std::vector<const Type*> args;
+ AttrListPtr params;
+ FunctionType* funcTy = FunctionType::get(
+ /*Result=*/IntegerType::get(32),
+ /*Params=*/args,
+ /*isVarArg=*/true);
+ Function* func_printf = Function::Create(
+ /*Type=*/funcTy,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"printf", m_mod);
+ func_printf->setCallingConv(CallingConv::C);
+ func_printf->setAttributes(params);
+ return func_printf;
+}
+
+llvm::Function * Instructions::declareFunc(int label)
+{
+ PointerType *vecPtr = PointerType::getUnqual(m_floatVecType);
+ std::vector<const Type*> args;
+ args.push_back(vecPtr);
+ args.push_back(vecPtr);
+ args.push_back(vecPtr);
+ args.push_back(vecPtr);
+ AttrListPtr params;
+ FunctionType *funcType = FunctionType::get(
+ /*Result=*/Type::VoidTy,
+ /*Params=*/args,
+ /*isVarArg=*/false);
+ std::string name = createFuncName(label);
+ Function *func = Function::Create(
+ /*Type=*/funcType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/name.c_str(), m_mod);
+ func->setCallingConv(CallingConv::C);
+ func->setAttributes(params);
+ return func;
+}
+
+llvm::Function * Instructions::findFunction(int label)
+{
+ llvm::Function *func = m_functions[label];
+ if (!func) {
+ func = declareFunc(label);
+ m_functions[label] = func;
+ }
+ return func;
+}
+
+std::vector<llvm::Value*> Instructions::extractVector(llvm::Value *vec)
+{
+ std::vector<llvm::Value*> elems(4);
+ elems[0] = m_builder.CreateExtractElement(vec, m_storage->constantInt(0),
+ name("x"));
+ elems[1] = m_builder.CreateExtractElement(vec, m_storage->constantInt(1),
+ name("y"));
+ elems[2] = m_builder.CreateExtractElement(vec, m_storage->constantInt(2),
+ name("z"));
+ elems[3] = m_builder.CreateExtractElement(vec, m_storage->constantInt(3),
+ name("w"));
+ return elems;
+}
+
+
+#endif //MESA_LLVM
+
+
diff --git a/src/gallium/auxiliary/gallivm/instructions.h b/src/gallium/auxiliary/gallivm/instructions.h
new file mode 100644
index 0000000000..e18571251e
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/instructions.h
@@ -0,0 +1,175 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+
+#ifndef INSTRUCTIONS_H
+#define INSTRUCTIONS_H
+
+#include <llvm/BasicBlock.h>
+#include <llvm/Module.h>
+#include <llvm/Value.h>
+#include <llvm/Support/IRBuilder.h>
+
+#include <map>
+#include <stack>
+
+namespace llvm {
+ class VectorType;
+ class Function;
+}
+
+class Storage;
+
+class Instructions
+{
+public:
+ Instructions(llvm::Module *mod, llvm::Function *func, llvm::BasicBlock *block,
+ Storage *storage);
+
+ llvm::BasicBlock *currentBlock() const;
+
+ llvm::Value *abs(llvm::Value *in1);
+ llvm::Value *add(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *arl(llvm::Value *in1);
+ void beginLoop();
+ void bgnSub(unsigned);
+ void brk();
+ void cal(int label, llvm::Value *input);
+ llvm::Value *ceil(llvm::Value *in);
+ llvm::Value *clamp(llvm::Value *in);
+ llvm::Value *cmp(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3);
+ llvm::Value *cnd(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3);
+ llvm::Value *cnd0(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3);
+ llvm::Value *cos(llvm::Value *in);
+ llvm::Value *cross(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *ddx(llvm::Value *in);
+ llvm::Value *ddy(llvm::Value *in);
+ llvm::Value *div(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *dot2add(llvm::Value *in, llvm::Value *in2, llvm::Value *in3);
+ llvm::Value *dp2(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *dp3(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *dp4(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *dph(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *dst(llvm::Value *in1, llvm::Value *in2);
+ void elseop();
+ void endif();
+ void endLoop();
+ void end();
+ void endSub();
+ llvm::Value *exp(llvm::Value *in);
+ llvm::Value *ex2(llvm::Value *in);
+ llvm::Value *floor(llvm::Value *in);
+ llvm::Value *frc(llvm::Value *in);
+ void ifop(llvm::Value *in);
+ llvm::Value *kil(llvm::Value *in);
+ llvm::Value *lerp(llvm::Value *in1, llvm::Value *in2,
+ llvm::Value *in3);
+ llvm::Value *lg2(llvm::Value *in);
+ llvm::Value *lit(llvm::Value *in);
+ llvm::Value *log(llvm::Value *in);
+ llvm::Value *madd(llvm::Value *in1, llvm::Value *in2,
+ llvm::Value *in3);
+ llvm::Value *max(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *min(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *mul(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *neg(llvm::Value *in);
+ llvm::Value *nrm(llvm::Value *in);
+ llvm::Value *pow(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *rcp(llvm::Value *in);
+ llvm::Value *rsq(llvm::Value *in);
+ llvm::Value *scs(llvm::Value *in);
+ llvm::Value *seq(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *sfl(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *sge(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *sgt(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *sin(llvm::Value *in);
+ llvm::Value *sle(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *slt(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *sne(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *str(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *sub(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *trunc(llvm::Value *in);
+ llvm::Value *x2d(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3);
+
+ void printVector(llvm::Value *val);
+private:
+ const char *name(const char *prefix);
+
+ llvm::Value *callCeil(llvm::Value *val);
+ llvm::Value *callFAbs(llvm::Value *val);
+ llvm::Value *callFExp(llvm::Value *val);
+ llvm::Value *callFLog(llvm::Value *val);
+ llvm::Value *callFloor(llvm::Value *val);
+ llvm::Value *callFSqrt(llvm::Value *val);
+ llvm::Value *callPow(llvm::Value *val1, llvm::Value *val2);
+
+ llvm::Value *vectorFromVals(llvm::Value *x, llvm::Value *y,
+ llvm::Value *z, llvm::Value *w=0);
+
+ llvm::Value *constVector(float x, float y, float z, float w);
+
+ llvm::Function *declarePrintf();
+ llvm::Function *declareFunc(int label);
+
+ llvm::Function *findFunction(int label);
+
+ std::vector<llvm::Value*> extractVector(llvm::Value *vec);
+private:
+ llvm::Module *m_mod;
+ llvm::Function *m_func;
+ char m_name[32];
+ llvm::IRBuilder<> m_builder;
+ int m_idx;
+
+ llvm::VectorType *m_floatVecType;
+
+ llvm::Function *m_llvmCeil;
+ llvm::Function *m_llvmFSqrt;
+ llvm::Function *m_llvmFAbs;
+ llvm::Function *m_llvmPow;
+ llvm::Function *m_llvmFloor;
+ llvm::Function *m_llvmFlog;
+ llvm::Function *m_llvmFexp;
+ llvm::Function *m_llvmLit;
+
+ llvm::Constant *m_fmtPtr;
+
+ std::stack<llvm::BasicBlock*> m_ifStack;
+ struct Loop {
+ llvm::BasicBlock *begin;
+ llvm::BasicBlock *end;
+ };
+ std::stack<Loop> m_loopStack;
+ std::map<int, llvm::Function*> m_functions;
+ Storage *m_storage;
+};
+
+#endif
diff --git a/src/gallium/auxiliary/gallivm/instructionssoa.cpp b/src/gallium/auxiliary/gallivm/instructionssoa.cpp
new file mode 100644
index 0000000000..721b7d2d83
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/instructionssoa.cpp
@@ -0,0 +1,525 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <cstdio>
+#include "instructionssoa.h"
+
+#include "storagesoa.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "util/u_memory.h"
+
+#include <llvm/CallingConv.h>
+#include <llvm/Constants.h>
+#include <llvm/Module.h>
+#include <llvm/Function.h>
+#include <llvm/Instructions.h>
+#include <llvm/Transforms/Utils/Cloning.h>
+#include <llvm/Attributes.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+
+
+#include <iostream>
+
+
+/* disable some warnings. this file is autogenerated */
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#endif
+using namespace llvm;
+#include "gallivmsoabuiltins.cpp"
+#if defined(__GNUC__)
+#pragma GCC diagnostic warning "-Wunused-variable"
+#endif
+
+InstructionsSoa::InstructionsSoa(llvm::Module *mod, llvm::Function *func,
+ llvm::BasicBlock *block, StorageSoa *storage)
+ : m_builder(block),
+ m_storage(storage),
+ m_idx(0)
+{
+ createFunctionMap();
+ createBuiltins();
+}
+
+const char * InstructionsSoa::name(const char *prefix) const
+{
+ ++m_idx;
+ snprintf(m_name, 32, "%s%d", prefix, m_idx);
+ return m_name;
+}
+
+llvm::Value * InstructionsSoa::vectorFromVals(llvm::Value *x, llvm::Value *y,
+ llvm::Value *z, llvm::Value *w)
+{
+ VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
+ Constant *constVector = Constant::getNullValue(vectorType);
+ Value *res = m_builder.CreateInsertElement(constVector, x,
+ m_storage->constantInt(0),
+ name("vecx"));
+ res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1),
+ name("vecxy"));
+ res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2),
+ name("vecxyz"));
+ if (w)
+ res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3),
+ name("vecxyzw"));
+ return res;
+}
+
+void InstructionsSoa::end()
+{
+ m_builder.CreateRetVoid();
+}
+
+std::vector<llvm::Value*> InstructionsSoa::extractVector(llvm::Value *vector)
+{
+ std::vector<llvm::Value*> res(4);
+ res[0] = m_builder.CreateExtractElement(vector,
+ m_storage->constantInt(0),
+ name("extract1X"));
+ res[1] = m_builder.CreateExtractElement(vector,
+ m_storage->constantInt(1),
+ name("extract2X"));
+ res[2] = m_builder.CreateExtractElement(vector,
+ m_storage->constantInt(2),
+ name("extract3X"));
+ res[3] = m_builder.CreateExtractElement(vector,
+ m_storage->constantInt(3),
+ name("extract4X"));
+
+ return res;
+}
+
+llvm::IRBuilder<>* InstructionsSoa::getIRBuilder()
+{
+ return &m_builder;
+}
+
+void InstructionsSoa::createFunctionMap()
+{
+ m_functionsMap[TGSI_OPCODE_ABS] = "abs";
+ m_functionsMap[TGSI_OPCODE_DP3] = "dp3";
+ m_functionsMap[TGSI_OPCODE_DP4] = "dp4";
+ m_functionsMap[TGSI_OPCODE_MIN] = "min";
+ m_functionsMap[TGSI_OPCODE_MAX] = "max";
+ m_functionsMap[TGSI_OPCODE_POW] = "pow";
+ m_functionsMap[TGSI_OPCODE_LIT] = "lit";
+ m_functionsMap[TGSI_OPCODE_RSQ] = "rsq";
+ m_functionsMap[TGSI_OPCODE_SLT] = "slt";
+}
+
+void InstructionsSoa::createDependencies()
+{
+ {
+ std::vector<std::string> powDeps(2);
+ powDeps[0] = "powf";
+ powDeps[1] = "powvec";
+ m_builtinDependencies["pow"] = powDeps;
+ }
+ {
+ std::vector<std::string> absDeps(2);
+ absDeps[0] = "fabsf";
+ absDeps[1] = "absvec";
+ m_builtinDependencies["abs"] = absDeps;
+ }
+ {
+ std::vector<std::string> maxDeps(1);
+ maxDeps[0] = "maxvec";
+ m_builtinDependencies["max"] = maxDeps;
+ }
+ {
+ std::vector<std::string> minDeps(1);
+ minDeps[0] = "minvec";
+ m_builtinDependencies["min"] = minDeps;
+ }
+ {
+ std::vector<std::string> litDeps(4);
+ litDeps[0] = "minvec";
+ litDeps[1] = "maxvec";
+ litDeps[2] = "powf";
+ litDeps[3] = "powvec";
+ m_builtinDependencies["lit"] = litDeps;
+ }
+ {
+ std::vector<std::string> rsqDeps(4);
+ rsqDeps[0] = "sqrtf";
+ rsqDeps[1] = "sqrtvec";
+ rsqDeps[2] = "fabsf";
+ rsqDeps[3] = "absvec";
+ m_builtinDependencies["rsq"] = rsqDeps;
+ }
+}
+
+llvm::Function * InstructionsSoa::function(int op)
+{
+ if (m_functions.find(op) != m_functions.end())
+ return m_functions[op];
+
+ std::string name = m_functionsMap[op];
+
+ std::cout <<"For op = "<<op<<", func is '"<<name<<"'"<<std::endl;
+
+ std::vector<std::string> deps = m_builtinDependencies[name];
+ for (unsigned int i = 0; i < deps.size(); ++i) {
+ llvm::Function *func = m_builtins->getFunction(deps[i]);
+ std::cout <<"\tinjecting dep = '"<<func->getName()<<"'"<<std::endl;
+ injectFunction(func);
+ }
+
+ llvm::Function *originalFunc = m_builtins->getFunction(name);
+ injectFunction(originalFunc, op);
+ return m_functions[op];
+}
+
+llvm::Module * InstructionsSoa::currentModule() const
+{
+ BasicBlock *block = m_builder.GetInsertBlock();
+ if (!block || !block->getParent())
+ return 0;
+
+ return block->getParent()->getParent();
+}
+
+void InstructionsSoa::createBuiltins()
+{
+ std::string ErrMsg;
+ MemoryBuffer *buffer = MemoryBuffer::getMemBuffer(
+ (const char*)&soabuiltins_data[0],
+ (const char*)&soabuiltins_data[Elements(soabuiltins_data) - 1]);
+ m_builtins = ParseBitcodeFile(buffer, &ErrMsg);
+ std::cout<<"Builtins created at "<<m_builtins<<" ("<<ErrMsg<<")"<<std::endl;
+ assert(m_builtins);
+ createDependencies();
+}
+
+
+std::vector<llvm::Value*> InstructionsSoa::abs(const std::vector<llvm::Value*> in1)
+{
+ llvm::Function *func = function(TGSI_OPCODE_ABS);
+ return callBuiltin(func, in1);
+}
+
+std::vector<llvm::Value*> InstructionsSoa::add(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ std::vector<llvm::Value*> res(4);
+
+ res[0] = m_builder.CreateAdd(in1[0], in2[0], name("addx"));
+ res[1] = m_builder.CreateAdd(in1[1], in2[1], name("addy"));
+ res[2] = m_builder.CreateAdd(in1[2], in2[2], name("addz"));
+ res[3] = m_builder.CreateAdd(in1[3], in2[3], name("addw"));
+
+ return res;
+}
+
+std::vector<llvm::Value*> InstructionsSoa::arl(const std::vector<llvm::Value*> in)
+{
+ std::vector<llvm::Value*> res(4);
+
+ //Extract x's
+ llvm::Value *x1 = m_builder.CreateExtractElement(in[0],
+ m_storage->constantInt(0),
+ name("extractX"));
+ //cast it to an unsigned int
+ x1 = m_builder.CreateFPToUI(x1, IntegerType::get(32), name("x1IntCast"));
+
+ res[0] = x1;//vectorFromVals(x1, x2, x3, x4);
+ //only x is valid. the others shouldn't be necessary
+ /*
+ res[1] = Constant::getNullValue(m_floatVecType);
+ res[2] = Constant::getNullValue(m_floatVecType);
+ res[3] = Constant::getNullValue(m_floatVecType);
+ */
+
+ return res;
+}
+
+std::vector<llvm::Value*> InstructionsSoa::dp3(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ llvm::Function *func = function(TGSI_OPCODE_DP3);
+ return callBuiltin(func, in1, in2);
+}
+
+std::vector<llvm::Value*> InstructionsSoa::lit(const std::vector<llvm::Value*> in)
+{
+ llvm::Function *func = function(TGSI_OPCODE_LIT);
+ return callBuiltin(func, in);
+}
+
+std::vector<llvm::Value*> InstructionsSoa::madd(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2,
+ const std::vector<llvm::Value*> in3)
+{
+ std::vector<llvm::Value*> res = mul(in1, in2);
+ return add(res, in3);
+}
+
+std::vector<llvm::Value*> InstructionsSoa::max(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ llvm::Function *func = function(TGSI_OPCODE_MAX);
+ return callBuiltin(func, in1, in2);
+}
+
+std::vector<llvm::Value*> InstructionsSoa::min(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ llvm::Function *func = function(TGSI_OPCODE_MIN);
+ return callBuiltin(func, in1, in2);
+}
+
+std::vector<llvm::Value*> InstructionsSoa::mul(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ std::vector<llvm::Value*> res(4);
+
+ res[0] = m_builder.CreateMul(in1[0], in2[0], name("mulx"));
+ res[1] = m_builder.CreateMul(in1[1], in2[1], name("muly"));
+ res[2] = m_builder.CreateMul(in1[2], in2[2], name("mulz"));
+ res[3] = m_builder.CreateMul(in1[3], in2[3], name("mulw"));
+
+ return res;
+}
+
+std::vector<llvm::Value*> InstructionsSoa::pow(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ llvm::Function *func = function(TGSI_OPCODE_POW);
+ return callBuiltin(func, in1, in2);
+}
+
+std::vector<llvm::Value*> InstructionsSoa::rsq(const std::vector<llvm::Value*> in)
+{
+ llvm::Function *func = function(TGSI_OPCODE_RSQ);
+ return callBuiltin(func, in);
+}
+
+std::vector<llvm::Value*> InstructionsSoa::slt(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ llvm::Function *func = function(TGSI_OPCODE_SLT);
+ return callBuiltin(func, in1, in2);
+}
+
+std::vector<llvm::Value*> InstructionsSoa::sub(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ std::vector<llvm::Value*> res(4);
+
+ res[0] = m_builder.CreateSub(in1[0], in2[0], name("subx"));
+ res[1] = m_builder.CreateSub(in1[1], in2[1], name("suby"));
+ res[2] = m_builder.CreateSub(in1[2], in2[2], name("subz"));
+ res[3] = m_builder.CreateSub(in1[3], in2[3], name("subw"));
+
+ return res;
+}
+
+void checkFunction(Function *func)
+{
+ for (Function::const_iterator BI = func->begin(), BE = func->end();
+ BI != BE; ++BI) {
+ const BasicBlock &BB = *BI;
+ for (BasicBlock::const_iterator II = BB.begin(), IE = BB.end();
+ II != IE; ++II) {
+ const Instruction &I = *II;
+ std::cout<< "Instr = "<<I;
+ for (unsigned op = 0, E = I.getNumOperands(); op != E; ++op) {
+ const Value *Op = I.getOperand(op);
+ std::cout<< "\top = "<<Op<<"("<<op<<")"<<std::endl;
+ //I->setOperand(op, V);
+ }
+ }
+ }
+}
+
+llvm::Value * InstructionsSoa::allocaTemp()
+{
+ VectorType *vector = VectorType::get(Type::FloatTy, 4);
+ ArrayType *vecArray = ArrayType::get(vector, 4);
+ AllocaInst *alloca = new AllocaInst(vecArray, name("tmpRes"),
+ m_builder.GetInsertBlock());
+
+ std::vector<Value*> indices;
+ indices.push_back(m_storage->constantInt(0));
+ indices.push_back(m_storage->constantInt(0));
+ GetElementPtrInst *getElem = GetElementPtrInst::Create(alloca,
+ indices.begin(),
+ indices.end(),
+ name("allocaPtr"),
+ m_builder.GetInsertBlock());
+ return getElem;
+}
+
+std::vector<llvm::Value*> InstructionsSoa::allocaToResult(llvm::Value *allocaPtr)
+{
+ GetElementPtrInst *xElemPtr = GetElementPtrInst::Create(allocaPtr,
+ m_storage->constantInt(0),
+ name("xPtr"),
+ m_builder.GetInsertBlock());
+ GetElementPtrInst *yElemPtr = GetElementPtrInst::Create(allocaPtr,
+ m_storage->constantInt(1),
+ name("yPtr"),
+ m_builder.GetInsertBlock());
+ GetElementPtrInst *zElemPtr = GetElementPtrInst::Create(allocaPtr,
+ m_storage->constantInt(2),
+ name("zPtr"),
+ m_builder.GetInsertBlock());
+ GetElementPtrInst *wElemPtr = GetElementPtrInst::Create(allocaPtr,
+ m_storage->constantInt(3),
+ name("wPtr"),
+ m_builder.GetInsertBlock());
+
+ std::vector<llvm::Value*> res(4);
+ res[0] = new LoadInst(xElemPtr, name("xRes"), false, m_builder.GetInsertBlock());
+ res[1] = new LoadInst(yElemPtr, name("yRes"), false, m_builder.GetInsertBlock());
+ res[2] = new LoadInst(zElemPtr, name("zRes"), false, m_builder.GetInsertBlock());
+ res[3] = new LoadInst(wElemPtr, name("wRes"), false, m_builder.GetInsertBlock());
+
+ return res;
+}
+
+std::vector<llvm::Value*> InstructionsSoa::dp4(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ llvm::Function *func = function(TGSI_OPCODE_DP4);
+ return callBuiltin(func, in1, in2);
+}
+
+std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1)
+{
+ std::vector<Value*> params;
+
+ llvm::Value *allocaPtr = allocaTemp();
+ params.push_back(allocaPtr);
+ params.push_back(in1[0]);
+ params.push_back(in1[1]);
+ params.push_back(in1[2]);
+ params.push_back(in1[3]);
+ CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+
+ return allocaToResult(allocaPtr);
+}
+
+std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ std::vector<Value*> params;
+
+ llvm::Value *allocaPtr = allocaTemp();
+ params.push_back(allocaPtr);
+ params.push_back(in1[0]);
+ params.push_back(in1[1]);
+ params.push_back(in1[2]);
+ params.push_back(in1[3]);
+ params.push_back(in2[0]);
+ params.push_back(in2[1]);
+ params.push_back(in2[2]);
+ params.push_back(in2[3]);
+ CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+
+ return allocaToResult(allocaPtr);
+}
+
+std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2,
+ const std::vector<llvm::Value*> in3)
+{
+ std::vector<Value*> params;
+
+ llvm::Value *allocaPtr = allocaTemp();
+ params.push_back(allocaPtr);
+ params.push_back(in1[0]);
+ params.push_back(in1[1]);
+ params.push_back(in1[2]);
+ params.push_back(in1[3]);
+ params.push_back(in2[0]);
+ params.push_back(in2[1]);
+ params.push_back(in2[2]);
+ params.push_back(in2[3]);
+ params.push_back(in3[0]);
+ params.push_back(in3[1]);
+ params.push_back(in3[2]);
+ params.push_back(in3[3]);
+ CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+
+ return allocaToResult(allocaPtr);
+}
+
+void InstructionsSoa::injectFunction(llvm::Function *originalFunc, int op)
+{
+ assert(originalFunc);
+ std::cout << "injecting function originalFunc " <<originalFunc->getName() <<std::endl;
+ if (op != TGSI_OPCODE_LAST) {
+ /* in this case it's possible the function has been already
+ * injected as part of the dependency chain, which gets
+ * injected below */
+ llvm::Function *func = currentModule()->getFunction(originalFunc->getName());
+ if (func) {
+ m_functions[op] = func;
+ return;
+ }
+ }
+ llvm::Function *func = 0;
+ if (originalFunc->isDeclaration()) {
+ func = Function::Create(originalFunc->getFunctionType(), GlobalValue::ExternalLinkage,
+ originalFunc->getName(), currentModule());
+ func->setCallingConv(CallingConv::C);
+ const AttrListPtr pal;
+ func->setAttributes(pal);
+ currentModule()->dump();
+ } else {
+ DenseMap<const Value*, Value *> val;
+ val[m_builtins->getFunction("fabsf")] = currentModule()->getFunction("fabsf");
+ val[m_builtins->getFunction("powf")] = currentModule()->getFunction("powf");
+ val[m_builtins->getFunction("sqrtf")] = currentModule()->getFunction("sqrtf");
+ func = CloneFunction(originalFunc, val);
+#if 0
+ std::cout <<" replacing "<<m_builtins->getFunction("powf")
+ <<", with " <<currentModule()->getFunction("powf")<<std::endl;
+ std::cout<<"1111-------------------------------"<<std::endl;
+ checkFunction(originalFunc);
+ std::cout<<"2222-------------------------------"<<std::endl;
+ checkFunction(func);
+ std::cout <<"XXXX = " <<val[m_builtins->getFunction("powf")]<<std::endl;
+#endif
+ currentModule()->getFunctionList().push_back(func);
+ }
+ if (op != TGSI_OPCODE_LAST) {
+ m_functions[op] = func;
+ }
+}
+
+
diff --git a/src/gallium/auxiliary/gallivm/instructionssoa.h b/src/gallium/auxiliary/gallivm/instructionssoa.h
new file mode 100644
index 0000000000..d6831e0a6b
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/instructionssoa.h
@@ -0,0 +1,116 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef INSTRUCTIONSSOA_H
+#define INSTRUCTIONSSOA_H
+
+#include <pipe/p_shader_tokens.h>
+#include <llvm/Support/IRBuilder.h>
+
+#include <map>
+#include <vector>
+
+namespace llvm {
+ class Module;
+ class Function;
+ class BasicBlock;
+ class Value;
+}
+class StorageSoa;
+
+class InstructionsSoa
+{
+public:
+ InstructionsSoa(llvm::Module *mod, llvm::Function *func,
+ llvm::BasicBlock *block, StorageSoa *storage);
+
+ std::vector<llvm::Value*> abs(const std::vector<llvm::Value*> in1);
+ std::vector<llvm::Value*> arl(const std::vector<llvm::Value*> in);
+ std::vector<llvm::Value*> add(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> dp3(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> dp4(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> lit(const std::vector<llvm::Value*> in);
+ std::vector<llvm::Value*> madd(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2,
+ const std::vector<llvm::Value*> in3);
+ std::vector<llvm::Value*> max(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> min(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> mul(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> pow(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> rsq(const std::vector<llvm::Value*> in1);
+ std::vector<llvm::Value*> slt(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> sub(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ void end();
+
+ std::vector<llvm::Value*> extractVector(llvm::Value *vector);
+ llvm::IRBuilder<>* getIRBuilder();
+private:
+ const char * name(const char *prefix) const;
+ llvm::Value *vectorFromVals(llvm::Value *x, llvm::Value *y,
+ llvm::Value *z, llvm::Value *w);
+ void createFunctionMap();
+ void createBuiltins();
+ void createDependencies();
+ llvm::Function *function(int);
+ llvm::Module *currentModule() const;
+ llvm::Value *allocaTemp();
+ std::vector<llvm::Value*> allocaToResult(llvm::Value *allocaPtr);
+ std::vector<llvm::Value*> callBuiltin(llvm::Function *func,
+ const std::vector<llvm::Value*> in1);
+ std::vector<llvm::Value*> callBuiltin(llvm::Function *func,
+ const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> callBuiltin(llvm::Function *func,
+ const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2,
+ const std::vector<llvm::Value*> in3);
+ void injectFunction(llvm::Function *originalFunc, int op = TGSI_OPCODE_LAST);
+private:
+ llvm::IRBuilder<> m_builder;
+ StorageSoa *m_storage;
+
+ std::map<int, std::string> m_functionsMap;
+ std::map<int, llvm::Function*> m_functions;
+ llvm::Module *m_builtins;
+ std::map<std::string, std::vector<std::string> > m_builtinDependencies;
+
+private:
+ mutable int m_idx;
+ mutable char m_name[32];
+};
+
+
+#endif
diff --git a/src/gallium/auxiliary/gallivm/llvm_builtins.c b/src/gallium/auxiliary/gallivm/llvm_builtins.c
new file mode 100644
index 0000000000..d5a003a48b
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/llvm_builtins.c
@@ -0,0 +1,114 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+typedef __attribute__(( ext_vector_type(4) )) float float4;
+
+extern float powf(float a, float b);
+
+inline float approx(float a, float b)
+{
+ if (b < -128.0f) b = -128.0f;
+ if (b > 128.0f) b = 128.0f;
+ if (a < 0) a = 0;
+ return powf(a, b);
+}
+
+inline float4 lit(float4 tmp)
+{
+ float4 result;
+ result.x = 1.0;
+ result.w = 1.0;
+ if (tmp.x > 0) {
+ result.y = tmp.x;
+ result.z = approx(tmp.y, tmp.w);
+ } else {
+ result.y = 0;
+ result.z = 0;
+ }
+ return result;
+}
+
+inline float4 cmp(float4 tmp0, float4 tmp1, float4 tmp2)
+{
+ float4 result;
+
+ result.x = (tmp0.x < 0.0) ? tmp1.x : tmp2.x;
+ result.y = (tmp0.y < 0.0) ? tmp1.y : tmp2.y;
+ result.z = (tmp0.z < 0.0) ? tmp1.z : tmp2.z;
+ result.w = (tmp0.w < 0.0) ? tmp1.w : tmp2.w;
+
+ return result;
+}
+
+extern float cosf(float val);
+extern float sinf(float val);
+
+inline float4 vcos(float4 val)
+{
+ float4 result;
+ printf("VEC IN is %f %f %f %f\n", val.x, val.y, val.z, val.w);
+ result.x = cosf(val.x);
+ result.y = cosf(val.x);
+ result.z = cosf(val.x);
+ result.w = cosf(val.x);
+ printf("VEC OUT is %f %f %f %f\n", result.x, result.y, result.z, result.w);
+ return result;
+}
+
+inline float4 scs(float4 val)
+{
+ float4 result;
+ float tmp = val.x;
+ result.x = cosf(tmp);
+ result.y = sinf(tmp);
+ return result;
+}
+
+
+inline float4 vsin(float4 val)
+{
+ float4 result;
+ float tmp = val.x;
+ float res = sinf(tmp);
+ result.x = res;
+ result.y = res;
+ result.z = res;
+ result.w = res;
+ return result;
+}
+
+inline int kil(float4 val)
+{
+ if (val.x < 0 || val.y < 0 || val.z < 0 || val.w < 0)
+ return 1;
+ else
+ return 0;
+}
diff --git a/src/gallium/auxiliary/gallivm/loweringpass.cpp b/src/gallium/auxiliary/gallivm/loweringpass.cpp
new file mode 100644
index 0000000000..556dbec366
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/loweringpass.cpp
@@ -0,0 +1,17 @@
+#include "loweringpass.h"
+
+using namespace llvm;
+
+char LoweringPass::ID = 0;
+RegisterPass<LoweringPass> X("lowering", "Lowering Pass");
+
+LoweringPass::LoweringPass()
+ : ModulePass((intptr_t)&ID)
+{
+}
+
+bool LoweringPass::runOnModule(Module &m)
+{
+ llvm::cerr << "Hello: " << m.getModuleIdentifier() << "\n";
+ return false;
+}
diff --git a/src/gallium/auxiliary/gallivm/loweringpass.h b/src/gallium/auxiliary/gallivm/loweringpass.h
new file mode 100644
index 0000000000..f62dcf6ba7
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/loweringpass.h
@@ -0,0 +1,15 @@
+#ifndef LOWERINGPASS_H
+#define LOWERINGPASS_H
+
+#include "llvm/Pass.h"
+#include "llvm/Module.h"
+
+struct LoweringPass : public llvm::ModulePass
+{
+ static char ID;
+ LoweringPass();
+
+ virtual bool runOnModule(llvm::Module &m);
+};
+
+#endif
diff --git a/src/gallium/auxiliary/gallivm/soabuiltins.c b/src/gallium/auxiliary/gallivm/soabuiltins.c
new file mode 100644
index 0000000000..cb85e1734e
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/soabuiltins.c
@@ -0,0 +1,210 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * This file is compiled with clang into the LLVM bitcode
+ *
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+typedef __attribute__(( ext_vector_type(4) )) float float4;
+
+
+extern float fabsf(float val);
+
+/* helpers */
+
+float4 absvec(float4 vec)
+{
+ float4 res;
+ res.x = fabsf(vec.x);
+ res.y = fabsf(vec.y);
+ res.z = fabsf(vec.z);
+ res.w = fabsf(vec.w);
+
+ return res;
+}
+
+float4 maxvec(float4 a, float4 b)
+{
+ return (float4){(a.x > b.x) ? a.x : b.x,
+ (a.y > b.y) ? a.y : b.y,
+ (a.z > b.z) ? a.z : b.z,
+ (a.w > b.w) ? a.w : b.w};
+}
+
+float4 minvec(float4 a, float4 b)
+{
+ return (float4){(a.x < b.x) ? a.x : b.x,
+ (a.y < b.y) ? a.y : b.y,
+ (a.z < b.z) ? a.z : b.z,
+ (a.w < b.w) ? a.w : b.w};
+}
+
+extern float powf(float num, float p);
+extern float sqrtf(float x);
+
+float4 powvec(float4 vec, float4 q)
+{
+ float4 p;
+ p.x = powf(vec.x, q.x);
+ p.y = powf(vec.y, q.y);
+ p.z = powf(vec.z, q.z);
+ p.w = powf(vec.w, q.w);
+ return p;
+}
+
+float4 sqrtvec(float4 vec)
+{
+ float4 p;
+ p.x = sqrtf(vec.x);
+ p.y = sqrtf(vec.y);
+ p.z = sqrtf(vec.z);
+ p.w = sqrtf(vec.w);
+ return p;
+}
+
+float4 sltvec(float4 v1, float4 v2)
+{
+ float4 p;
+ p.x = (v1.x < v2.x) ? 1.0 : 0.0;
+ p.y = (v1.y < v2.y) ? 1.0 : 0.0;
+ p.z = (v1.z < v2.z) ? 1.0 : 0.0;
+ p.w = (v1.w < v2.w) ? 1.0 : 0.0;
+ return p;
+}
+
+
+/* instructions */
+
+void abs(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w)
+{
+ res[0] = absvec(tmp0x);
+ res[1] = absvec(tmp0y);
+ res[2] = absvec(tmp0z);
+ res[3] = absvec(tmp0w);
+}
+
+void dp3(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
+ float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
+{
+ float4 dot = (tmp0x * tmp1x) + (tmp0y * tmp1y) +
+ (tmp0z * tmp1z);
+
+ res[0] = dot;
+ res[1] = dot;
+ res[2] = dot;
+ res[3] = dot;
+}
+
+void dp4(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
+ float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
+{
+ float4 dot = (tmp0x * tmp1x) + (tmp0y * tmp1y) +
+ (tmp0z * tmp1z) + (tmp0w * tmp1w);
+
+ res[0] = dot;
+ res[1] = dot;
+ res[2] = dot;
+ res[3] = dot;
+}
+
+void lit(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w)
+{
+ const float4 zerovec = (float4) {0.0, 0.0, 0.0, 0.0};
+ const float4 min128 = (float4) {-128.f, -128.f, -128.f, -128.f};
+ const float4 plus128 = (float4) {128.f, 128.f, 128.f, 128.f};
+
+ res[0] = (float4){1.0, 1.0, 1.0, 1.0};
+ if (tmp0x.x > 0) {
+ float4 tmpy = maxvec(tmp0y, zerovec);
+ float4 tmpw = minvec(tmp0w, plus128);
+ tmpw = maxvec(tmpw, min128);
+ res[1] = tmp0x;
+ res[2] = powvec(tmpy, tmpw);
+ } else {
+ res[1] = zerovec;
+ res[2] = zerovec;
+ }
+ res[3] = (float4){1.0, 1.0, 1.0, 1.0};
+}
+
+void min(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
+ float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
+{
+ res[0] = minvec(tmp0x, tmp1x);
+ res[1] = minvec(tmp0y, tmp1y);
+ res[2] = minvec(tmp0z, tmp1z);
+ res[3] = minvec(tmp0w, tmp1w);
+}
+
+
+void max(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
+ float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
+{
+ res[0] = maxvec(tmp0x, tmp1x);
+ res[1] = maxvec(tmp0y, tmp1y);
+ res[2] = maxvec(tmp0z, tmp1z);
+ res[3] = maxvec(tmp0w, tmp1w);
+}
+
+void pow(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
+ float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
+{
+ res[0] = powvec(tmp0x, tmp1x);
+ res[1] = res[0];
+ res[2] = res[0];
+ res[3] = res[0];
+}
+
+void rsq(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w)
+{
+ const float4 onevec = (float4) {1., 1., 1., 1.};
+ res[0] = onevec/sqrtvec(absvec(tmp0x));
+ res[1] = onevec/sqrtvec(absvec(tmp0y));
+ res[2] = onevec/sqrtvec(absvec(tmp0z));
+ res[3] = onevec/sqrtvec(absvec(tmp0w));
+}
+
+void slt(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
+ float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
+{
+ res[0] = sltvec(tmp0x, tmp1x);
+ res[1] = sltvec(tmp0y, tmp1y);
+ res[2] = sltvec(tmp0z, tmp1z);
+ res[3] = sltvec(tmp0w, tmp1w);
+}
+
diff --git a/src/gallium/auxiliary/gallivm/storage.cpp b/src/gallium/auxiliary/gallivm/storage.cpp
new file mode 100644
index 0000000000..73df24c976
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/storage.cpp
@@ -0,0 +1,364 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+#ifdef MESA_LLVM
+
+#include "storage.h"
+
+#include "gallivm_p.h"
+
+#include "pipe/p_shader_tokens.h"
+#include <llvm/BasicBlock.h>
+#include <llvm/Module.h>
+#include <llvm/Value.h>
+
+#include <llvm/CallingConv.h>
+#include <llvm/Constants.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/InstrTypes.h>
+#include <llvm/Instructions.h>
+
+using namespace llvm;
+
+Storage::Storage(llvm::BasicBlock *block, llvm::Value *input)
+ : m_block(block),
+ m_INPUT(input),
+ m_addrs(32),
+ m_idx(0)
+{
+ m_floatVecType = VectorType::get(Type::FloatTy, 4);
+ m_intVecType = VectorType::get(IntegerType::get(32), 4);
+
+ m_undefFloatVec = UndefValue::get(m_floatVecType);
+ m_undefIntVec = UndefValue::get(m_intVecType);
+ m_extSwizzleVec = 0;
+
+ m_numConsts = 0;
+}
+
+//can only build vectors with all members in the [0, 9] range
+llvm::Constant *Storage::shuffleMask(int vec)
+{
+ if (!m_extSwizzleVec) {
+ std::vector<Constant*> elems;
+ elems.push_back(ConstantFP::get(APFloat(0.f)));
+ elems.push_back(ConstantFP::get(APFloat(1.f)));
+ elems.push_back(ConstantFP::get(APFloat(0.f)));
+ elems.push_back(ConstantFP::get(APFloat(1.f)));
+ m_extSwizzleVec = ConstantVector::get(m_floatVecType, elems);
+ }
+
+ if (m_intVecs.find(vec) != m_intVecs.end()) {
+ return m_intVecs[vec];
+ }
+ int origVec = vec;
+ Constant* const_vec = 0;
+ if (origVec == 0) {
+ const_vec = Constant::getNullValue(m_intVecType);
+ } else {
+ int x = gallivm_x_swizzle(vec);
+ int y = gallivm_y_swizzle(vec);
+ int z = gallivm_z_swizzle(vec);
+ int w = gallivm_w_swizzle(vec);
+ std::vector<Constant*> elems;
+ elems.push_back(constantInt(x));
+ elems.push_back(constantInt(y));
+ elems.push_back(constantInt(z));
+ elems.push_back(constantInt(w));
+ const_vec = ConstantVector::get(m_intVecType, elems);
+ }
+
+ m_intVecs[origVec] = const_vec;
+ return const_vec;
+}
+
+llvm::ConstantInt *Storage::constantInt(int idx)
+{
+ if (m_constInts.find(idx) != m_constInts.end()) {
+ return m_constInts[idx];
+ }
+ ConstantInt *const_int = ConstantInt::get(APInt(32, idx));
+ m_constInts[idx] = const_int;
+ return const_int;
+}
+
+llvm::Value *Storage::inputElement(int idx, llvm::Value *indIdx)
+{
+ Value *val = element(InputsArg, idx, indIdx);
+ LoadInst *load = new LoadInst(val, name("input"), false, m_block);
+ load->setAlignment(8);
+
+ return load;
+}
+
+llvm::Value *Storage::constElement(int idx, llvm::Value *indIdx)
+{
+ m_numConsts = ((idx + 1) > m_numConsts) ? (idx + 1) : m_numConsts;
+
+ Value *elem = element(ConstsArg, idx, indIdx);
+ LoadInst *load = new LoadInst(elem, name("const"), false, m_block);
+ load->setAlignment(8);
+ return load;
+}
+
+llvm::Value *Storage::shuffleVector(llvm::Value *vec, int shuffle)
+{
+ Constant *mask = shuffleMask(shuffle);
+ ShuffleVectorInst *res =
+ new ShuffleVectorInst(vec, m_extSwizzleVec, mask,
+ name("shuffle"), m_block);
+ return res;
+}
+
+
+llvm::Value *Storage::tempElement(int idx, llvm::Value *indIdx)
+{
+ Value *elem = element(TempsArg, idx, indIdx);
+
+ LoadInst *load = new LoadInst(elem, name("temp"), false, m_block);
+ load->setAlignment(8);
+
+ return load;
+}
+
+void Storage::setTempElement(int idx, llvm::Value *val, int mask)
+{
+ if (mask != TGSI_WRITEMASK_XYZW) {
+ llvm::Value *templ = 0;
+ if (m_tempWriteMap[idx])
+ templ = tempElement(idx);
+ val = maskWrite(val, mask, templ);
+ }
+ Value *elem = element(TempsArg, idx);
+ StoreInst *st = new StoreInst(val, elem, false, m_block);
+ st->setAlignment(8);
+ m_tempWriteMap[idx] = true;
+}
+
+void Storage::setOutputElement(int dstIdx, llvm::Value *val, int mask)
+{
+ if (mask != TGSI_WRITEMASK_XYZW) {
+ llvm::Value *templ = 0;
+ if (m_destWriteMap[dstIdx])
+ templ = outputElement(dstIdx);
+ val = maskWrite(val, mask, templ);
+ }
+
+ Value *elem = element(DestsArg, dstIdx);
+ StoreInst *st = new StoreInst(val, elem, false, m_block);
+ st->setAlignment(8);
+ m_destWriteMap[dstIdx] = true;
+}
+
+llvm::Value *Storage::maskWrite(llvm::Value *src, int mask, llvm::Value *templ)
+{
+ llvm::Value *dst = templ;
+ if (!dst)
+ dst = Constant::getNullValue(m_floatVecType);
+ if ((mask & TGSI_WRITEMASK_X)) {
+ llvm::Value *x = new ExtractElementInst(src, unsigned(0),
+ name("x"), m_block);
+ dst = InsertElementInst::Create(dst, x, unsigned(0),
+ name("dstx"), m_block);
+ }
+ if ((mask & TGSI_WRITEMASK_Y)) {
+ llvm::Value *y = new ExtractElementInst(src, unsigned(1),
+ name("y"), m_block);
+ dst = InsertElementInst::Create(dst, y, unsigned(1),
+ name("dsty"), m_block);
+ }
+ if ((mask & TGSI_WRITEMASK_Z)) {
+ llvm::Value *z = new ExtractElementInst(src, unsigned(2),
+ name("z"), m_block);
+ dst = InsertElementInst::Create(dst, z, unsigned(2),
+ name("dstz"), m_block);
+ }
+ if ((mask & TGSI_WRITEMASK_W)) {
+ llvm::Value *w = new ExtractElementInst(src, unsigned(3),
+ name("w"), m_block);
+ dst = InsertElementInst::Create(dst, w, unsigned(3),
+ name("dstw"), m_block);
+ }
+ return dst;
+}
+
+const char * Storage::name(const char *prefix)
+{
+ ++m_idx;
+ snprintf(m_name, 32, "%s%d", prefix, m_idx);
+ return m_name;
+}
+
+int Storage::numConsts() const
+{
+ return m_numConsts;
+}
+
+llvm::Value * Storage::addrElement(int idx) const
+{
+ Value *ret = m_addrs[idx];
+ if (!ret)
+ return m_undefFloatVec;
+ return ret;
+}
+
+void Storage::setAddrElement(int idx, llvm::Value *val, int mask)
+{
+ if (mask != TGSI_WRITEMASK_XYZW) {
+ llvm::Value *templ = m_addrs[idx];
+ val = maskWrite(val, mask, templ);
+ }
+ m_addrs[idx] = val;
+}
+
+llvm::Value * Storage::extractIndex(llvm::Value *vec)
+{
+ llvm::Value *x = new ExtractElementInst(vec, unsigned(0),
+ name("x"), m_block);
+ return new FPToSIInst(x, IntegerType::get(32), name("intidx"), m_block);
+}
+
+void Storage::setCurrentBlock(llvm::BasicBlock *block)
+{
+ m_block = block;
+}
+
+llvm::Value * Storage::outputElement(int idx, llvm::Value *indIdx)
+{
+ Value *elem = element(DestsArg, idx, indIdx);
+ LoadInst *load = new LoadInst(elem, name("output"), false, m_block);
+ load->setAlignment(8);
+
+ return load;
+}
+
+llvm::Value * Storage::inputPtr() const
+{
+ return m_INPUT;
+}
+
+void Storage::pushArguments(llvm::Value *input)
+{
+ m_argStack.push(m_INPUT);
+
+ m_INPUT = input;
+}
+
+void Storage::popArguments()
+{
+ m_INPUT = m_argStack.top();
+ m_argStack.pop();
+}
+
+void Storage::pushTemps()
+{
+ m_extSwizzleVec = 0;
+}
+
+void Storage::popTemps()
+{
+}
+
+llvm::Value * Storage::immediateElement(int idx)
+{
+ return m_immediates[idx];
+}
+
+void Storage::addImmediate(float *val)
+{
+ std::vector<Constant*> vec(4);
+ vec[0] = ConstantFP::get(APFloat(val[0]));
+ vec[1] = ConstantFP::get(APFloat(val[1]));
+ vec[2] = ConstantFP::get(APFloat(val[2]));
+ vec[3] = ConstantFP::get(APFloat(val[3]));
+ m_immediates.push_back(ConstantVector::get(m_floatVecType, vec));
+}
+
+
+llvm::Value * Storage::elemPtr(Args arg)
+{
+ std::vector<Value*> indices;
+ indices.push_back(constantInt(0));
+ indices.push_back(constantInt(static_cast<int>(arg)));
+ GetElementPtrInst *getElem = GetElementPtrInst::Create(m_INPUT,
+ indices.begin(),
+ indices.end(),
+ name("input_ptr"),
+ m_block);
+ return new LoadInst(getElem, name("input_field"), false, m_block);
+}
+
+llvm::Value * Storage::elemIdx(llvm::Value *ptr, int idx,
+ llvm::Value *indIdx )
+{
+ GetElementPtrInst *getElem = 0;
+
+ if (indIdx) {
+ getElem = GetElementPtrInst::Create(ptr,
+ BinaryOperator::Create(Instruction::Add,
+ indIdx,
+ constantInt(idx),
+ name("add"),
+ m_block),
+ name("field"),
+ m_block);
+ } else {
+ getElem = GetElementPtrInst::Create(ptr,
+ constantInt(idx),
+ name("field"),
+ m_block);
+ }
+ return getElem;
+}
+
+llvm::Value * Storage::element(Args arg, int idx, llvm::Value *indIdx )
+{
+ Value *val = elemPtr(arg);
+ return elemIdx(val, idx, indIdx);
+}
+
+void Storage::setKilElement(llvm::Value *val)
+{
+ std::vector<Value*> indices;
+ indices.push_back(constantInt(0));
+ indices.push_back(constantInt(static_cast<int>(KilArg)));
+ GetElementPtrInst *elem = GetElementPtrInst::Create(m_INPUT,
+ indices.begin(),
+ indices.end(),
+ name("kil_ptr"),
+ m_block);
+ StoreInst *st = new StoreInst(val, elem, false, m_block);
+ st->setAlignment(8);
+}
+
+#endif //MESA_LLVM
+
+
diff --git a/src/gallium/auxiliary/gallivm/storage.h b/src/gallium/auxiliary/gallivm/storage.h
new file mode 100644
index 0000000000..8574f7554e
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/storage.h
@@ -0,0 +1,133 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+
+#ifndef STORAGE_H
+#define STORAGE_H
+
+#include <map>
+#include <set>
+#include <stack>
+#include <vector>
+
+namespace llvm {
+ class BasicBlock;
+ class Constant;
+ class ConstantInt;
+ class LoadInst;
+ class Value;
+ class VectorType;
+}
+
+class Storage
+{
+public:
+ Storage(llvm::BasicBlock *block,
+ llvm::Value *input);
+
+ llvm::Value *inputPtr() const;
+
+ void setCurrentBlock(llvm::BasicBlock *block);
+
+ llvm::ConstantInt *constantInt(int);
+ llvm::Constant *shuffleMask(int vec);
+ llvm::Value *inputElement(int idx, llvm::Value *indIdx =0);
+ llvm::Value *constElement(int idx, llvm::Value *indIdx =0);
+ llvm::Value *outputElement(int idx, llvm::Value *indIdx =0);
+ llvm::Value *tempElement(int idx, llvm::Value *indIdx =0);
+ llvm::Value *immediateElement(int idx);
+
+ void setOutputElement(int dstIdx, llvm::Value *val, int mask);
+ void setTempElement(int idx, llvm::Value *val, int mask);
+
+ llvm::Value *addrElement(int idx) const;
+ void setAddrElement(int idx, llvm::Value *val, int mask);
+
+ void setKilElement(llvm::Value *val);
+
+ llvm::Value *shuffleVector(llvm::Value *vec, int shuffle);
+
+ llvm::Value *extractIndex(llvm::Value *vec);
+
+ int numConsts() const;
+
+ void pushArguments(llvm::Value *input);
+ void popArguments();
+ void pushTemps();
+ void popTemps();
+
+ void addImmediate(float *val);
+
+private:
+ llvm::Value *maskWrite(llvm::Value *src, int mask, llvm::Value *templ);
+ const char *name(const char *prefix);
+
+ enum Args {
+ DestsArg = 0,
+ InputsArg = 1,
+ TempsArg = 2,
+ ConstsArg = 3,
+ KilArg = 4
+ };
+ llvm::Value *elemPtr(Args arg);
+ llvm::Value *elemIdx(llvm::Value *ptr, int idx,
+ llvm::Value *indIdx = 0);
+ llvm::Value *element(Args arg, int idx, llvm::Value *indIdx = 0);
+
+private:
+ llvm::BasicBlock *m_block;
+ llvm::Value *m_INPUT;
+
+ std::map<int, llvm::ConstantInt*> m_constInts;
+ std::map<int, llvm::Constant*> m_intVecs;
+ std::vector<llvm::Value*> m_addrs;
+ std::vector<llvm::Constant*> m_immediates;
+
+ llvm::VectorType *m_floatVecType;
+ llvm::VectorType *m_intVecType;
+
+ char m_name[32];
+ int m_idx;
+
+ int m_numConsts;
+
+ std::map<int, bool > m_destWriteMap;
+ std::map<int, bool > m_tempWriteMap;
+
+ llvm::Value *m_undefFloatVec;
+ llvm::Value *m_undefIntVec;
+ llvm::Value *m_extSwizzleVec;
+
+ std::stack<llvm::Value*> m_argStack;
+ std::stack<std::vector<llvm::Value*> > m_tempStack;
+};
+
+#endif
diff --git a/src/gallium/auxiliary/gallivm/storagesoa.cpp b/src/gallium/auxiliary/gallivm/storagesoa.cpp
new file mode 100644
index 0000000000..4984ce985c
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/storagesoa.cpp
@@ -0,0 +1,438 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "storagesoa.h"
+
+#include "gallivm_p.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "util/u_debug.h"
+
+#include <llvm/BasicBlock.h>
+#include <llvm/Module.h>
+#include <llvm/Value.h>
+
+#include <llvm/CallingConv.h>
+#include <llvm/Constants.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/InstrTypes.h>
+#include <llvm/Instructions.h>
+
+using namespace llvm;
+
+
+StorageSoa::StorageSoa(llvm::BasicBlock *block,
+ llvm::Value *input,
+ llvm::Value *output,
+ llvm::Value *consts)
+ : m_block(block),
+ m_input(input),
+ m_output(output),
+ m_consts(consts),
+ m_immediates(0),
+ m_idx(0)
+{
+}
+
+void StorageSoa::addImmediate(float *vec)
+{
+ std::vector<float> vals(4);
+ vals[0] = vec[0];
+ vals[1] = vec[1];
+ vals[2] = vec[2];
+ vals[3] = vec[3];
+ m_immediatesToFlush.push_back(vals);
+}
+
+void StorageSoa::declareImmediates()
+{
+ if (m_immediatesToFlush.empty())
+ return;
+
+ VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
+ ArrayType *vectorChannels = ArrayType::get(vectorType, 4);
+ ArrayType *arrayType = ArrayType::get(vectorChannels, m_immediatesToFlush.size());
+
+ m_immediates = new GlobalVariable(
+ /*Type=*/arrayType,
+ /*isConstant=*/false,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Initializer=*/0, // has initializer, specified below
+ /*Name=*/name("immediates"),
+ currentModule());
+
+ std::vector<Constant*> arrayVals;
+ for (unsigned int i = 0; i < m_immediatesToFlush.size(); ++i) {
+ std::vector<float> vec = m_immediatesToFlush[i];
+ std::vector<float> vals(4);
+ std::vector<Constant*> channelArray;
+
+ vals[0] = vec[0]; vals[1] = vec[1]; vals[2] = vec[2]; vals[3] = vec[3];
+ llvm::Constant *xChannel = createConstGlobalVector(vals);
+
+ vals[0] = vec[1]; vals[1] = vec[1]; vals[2] = vec[1]; vals[3] = vec[1];
+ llvm::Constant *yChannel = createConstGlobalVector(vals);
+
+ vals[0] = vec[2]; vals[1] = vec[2]; vals[2] = vec[2]; vals[3] = vec[2];
+ llvm::Constant *zChannel = createConstGlobalVector(vals);
+
+ vals[0] = vec[3]; vals[1] = vec[3]; vals[2] = vec[3]; vals[3] = vec[3];
+ llvm::Constant *wChannel = createConstGlobalVector(vals);
+ channelArray.push_back(xChannel);
+ channelArray.push_back(yChannel);
+ channelArray.push_back(zChannel);
+ channelArray.push_back(wChannel);
+ Constant *constChannels = ConstantArray::get(vectorChannels,
+ channelArray);
+ arrayVals.push_back(constChannels);
+ }
+ Constant *constArray = ConstantArray::get(arrayType, arrayVals);
+ m_immediates->setInitializer(constArray);
+
+ m_immediatesToFlush.clear();
+}
+
+llvm::Value *StorageSoa::addrElement(int idx) const
+{
+ std::map<int, llvm::Value*>::const_iterator itr = m_addresses.find(idx);
+ if (itr == m_addresses.end()) {
+ debug_printf("Trying to access invalid shader 'address'\n");
+ return 0;
+ }
+ llvm::Value * res = (*itr).second;
+
+ res = new LoadInst(res, name("addr"), false, m_block);
+
+ return res;
+}
+
+std::vector<llvm::Value*> StorageSoa::inputElement(llvm::Value *idx)
+{
+ std::vector<llvm::Value*> res(4);
+
+ res[0] = element(m_input, idx, 0);
+ res[1] = element(m_input, idx, 1);
+ res[2] = element(m_input, idx, 2);
+ res[3] = element(m_input, idx, 3);
+
+ return res;
+}
+
+llvm::Value* StorageSoa::unpackConstElement(llvm::IRBuilder<>* m_builder, llvm::Value* vector, int cc)
+{
+ std::vector<llvm::Value*> x(4);
+ x[0] = m_builder->CreateExtractElement(vector,
+ constantInt(cc),
+ name("x"));
+
+ VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
+ Constant *constVector = Constant::getNullValue(vectorType);
+ Value *res = m_builder->CreateInsertElement(constVector, x[0],
+ constantInt(0),
+ name("vecx"));
+ res = m_builder->CreateInsertElement(res, x[0], constantInt(1),
+ name("vecxx"));
+ res = m_builder->CreateInsertElement(res, x[0], constantInt(2),
+ name("vecxxx"));
+ res = m_builder->CreateInsertElement(res, x[0], constantInt(3),
+ name("vecxxxx"));
+ return res;
+}
+
+std::vector<llvm::Value*> StorageSoa::constElement(llvm::IRBuilder<>* m_builder, llvm::Value *idx)
+{
+ llvm::Value* res;
+ std::vector<llvm::Value*> res2(4);
+ llvm::Value *xChannel;
+
+ xChannel = elementPointer(m_consts, idx, 0);
+
+ res = alignedArrayLoad(xChannel);
+
+ res2[0]=unpackConstElement(m_builder, res,0);
+ res2[1]=unpackConstElement(m_builder, res,1);
+ res2[2]=unpackConstElement(m_builder, res,2);
+ res2[3]=unpackConstElement(m_builder, res,3);
+
+ return res2;
+}
+
+std::vector<llvm::Value*> StorageSoa::outputElement(llvm::Value *idx)
+{
+ std::vector<llvm::Value*> res(4);
+
+ res[0] = element(m_output, idx, 0);
+ res[1] = element(m_output, idx, 1);
+ res[2] = element(m_output, idx, 2);
+ res[3] = element(m_output, idx, 3);
+
+ return res;
+}
+
+std::vector<llvm::Value*> StorageSoa::tempElement(llvm::IRBuilder<>* m_builder, int idx)
+{
+ std::vector<llvm::Value*> res(4);
+ llvm::Value *temp = m_temps[idx];
+
+ res[0] = element(temp, constantInt(0), 0);
+ res[1] = element(temp, constantInt(0), 1);
+ res[2] = element(temp, constantInt(0), 2);
+ res[3] = element(temp, constantInt(0), 3);
+
+ return res;
+}
+
+std::vector<llvm::Value*> StorageSoa::immediateElement(llvm::Value *idx)
+{
+ std::vector<llvm::Value*> res(4);
+
+ res[0] = element(m_immediates, idx, 0);
+ res[1] = element(m_immediates, idx, 1);
+ res[2] = element(m_immediates, idx, 2);
+ res[3] = element(m_immediates, idx, 3);
+
+ return res;
+}
+
+llvm::Value * StorageSoa::elementPointer(llvm::Value *ptr, llvm::Value *index,
+ int channel) const
+{
+ std::vector<Value*> indices;
+ if (m_immediates == ptr)
+ indices.push_back(constantInt(0));
+ indices.push_back(index);
+ indices.push_back(constantInt(channel));
+
+ GetElementPtrInst *getElem = GetElementPtrInst::Create(ptr,
+ indices.begin(),
+ indices.end(),
+ name("ptr"),
+ m_block);
+ return getElem;
+}
+
+llvm::Value * StorageSoa::element(llvm::Value *ptr, llvm::Value *index,
+ int channel) const
+{
+ llvm::Value *res = elementPointer(ptr, index, channel);
+ LoadInst *load = new LoadInst(res, name("element"), false, m_block);
+ //load->setAlignment(8);
+ return load;
+}
+
+const char * StorageSoa::name(const char *prefix) const
+{
+ ++m_idx;
+ snprintf(m_name, 32, "%s%d", prefix, m_idx);
+ return m_name;
+}
+
+llvm::ConstantInt * StorageSoa::constantInt(int idx) const
+{
+ if (m_constInts.find(idx) != m_constInts.end()) {
+ return m_constInts[idx];
+ }
+ ConstantInt *constInt = ConstantInt::get(APInt(32, idx));
+ m_constInts[idx] = constInt;
+ return constInt;
+}
+
+llvm::Value *StorageSoa::alignedArrayLoad(llvm::Value *val)
+{
+ VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
+ PointerType *vectorPtr = PointerType::get(vectorType, 0);
+
+ CastInst *cast = new BitCastInst(val, vectorPtr, name("toVector"), m_block);
+ LoadInst *load = new LoadInst(cast, name("alignLoad"), false, m_block);
+ load->setAlignment(8);
+ return load;
+}
+
+llvm::Module * StorageSoa::currentModule() const
+{
+ if (!m_block || !m_block->getParent())
+ return 0;
+
+ return m_block->getParent()->getParent();
+}
+
+llvm::Constant * StorageSoa::createConstGlobalFloat(const float val)
+{
+ Constant*c = ConstantFP::get(APFloat(val));
+ return c;
+}
+
+llvm::Constant * StorageSoa::createConstGlobalVector(const std::vector<float> &vec)
+{
+ VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
+ std::vector<Constant*> immValues;
+ ConstantFP *constx = ConstantFP::get(APFloat(vec[0]));
+ ConstantFP *consty = ConstantFP::get(APFloat(vec[1]));
+ ConstantFP *constz = ConstantFP::get(APFloat(vec[2]));
+ ConstantFP *constw = ConstantFP::get(APFloat(vec[3]));
+ immValues.push_back(constx);
+ immValues.push_back(consty);
+ immValues.push_back(constz);
+ immValues.push_back(constw);
+ Constant *constVector = ConstantVector::get(vectorType, immValues);
+
+ return constVector;
+}
+
+std::vector<llvm::Value*> StorageSoa::load(enum tgsi_file_type type, int idx, int swizzle,
+ llvm::IRBuilder<>* m_builder,llvm::Value *indIdx)
+{
+ std::vector<llvm::Value*> val(4);
+
+ //if we have an indirect index, always use that
+ // if not use the integer offset to create one
+ llvm::Value *realIndex = 0;
+ if (indIdx)
+ realIndex = indIdx;
+ else
+ realIndex = constantInt(idx);
+ debug_printf("XXXXXXXXX realIdx = %p, indIdx = %p\n", realIndex, indIdx);
+
+ switch(type) {
+ case TGSI_FILE_INPUT:
+ val = inputElement(realIndex);
+ break;
+ case TGSI_FILE_OUTPUT:
+ val = outputElement(realIndex);
+ break;
+ case TGSI_FILE_TEMPORARY:
+ val = tempElement(m_builder, idx);
+ break;
+ case TGSI_FILE_CONSTANT:
+ val = constElement(m_builder, realIndex);
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ val = immediateElement(realIndex);
+ break;
+ case TGSI_FILE_ADDRESS:
+ debug_printf("Address not handled in the load phase!\n");
+ assert(0);
+ break;
+ default:
+ debug_printf("Unknown load!\n");
+ assert(0);
+ break;
+ }
+ if (!gallivm_is_swizzle(swizzle))
+ return val;
+
+ std::vector<llvm::Value*> res(4);
+
+ res[0] = val[gallivm_x_swizzle(swizzle)];
+ res[1] = val[gallivm_y_swizzle(swizzle)];
+ res[2] = val[gallivm_z_swizzle(swizzle)];
+ res[3] = val[gallivm_w_swizzle(swizzle)];
+ return res;
+}
+
+llvm::Value * StorageSoa::allocaTemp(llvm::IRBuilder<>* m_builder)
+{
+ VectorType *vector = VectorType::get(Type::FloatTy, 4);
+ ArrayType *vecArray = ArrayType::get(vector, 4);
+ AllocaInst *alloca = new AllocaInst(vecArray, "temp",
+ m_builder->GetInsertBlock());
+
+ return alloca;
+}
+
+
+void StorageSoa::store(enum tgsi_file_type type, int idx, const std::vector<llvm::Value*> &val,
+ int mask, llvm::IRBuilder<>* m_builder)
+{
+ llvm::Value *out = 0;
+ llvm::Value *realIndex = 0;
+ switch(type) {
+ case TGSI_FILE_OUTPUT:
+ out = m_output;
+ realIndex = constantInt(idx);
+ break;
+ case TGSI_FILE_TEMPORARY:
+ // if that temp doesn't already exist, alloca it
+ if (m_temps.find(idx) == m_temps.end())
+ m_temps[idx] = allocaTemp(m_builder);
+
+ out = m_temps[idx];
+
+ realIndex = constantInt(0);
+ break;
+ case TGSI_FILE_INPUT:
+ out = m_input;
+ realIndex = constantInt(idx);
+ break;
+ case TGSI_FILE_ADDRESS: {
+ llvm::Value *addr = m_addresses[idx];
+ if (!addr) {
+ addAddress(idx);
+ addr = m_addresses[idx];
+ assert(addr);
+ }
+ new StoreInst(val[0], addr, false, m_block);
+ return;
+ break;
+ }
+ default:
+ debug_printf("Can't save output of this type: %d !\n", type);
+ assert(0);
+ break;
+ }
+ if ((mask & TGSI_WRITEMASK_X)) {
+ llvm::Value *xChannel = elementPointer(out, realIndex, 0);
+ new StoreInst(val[0], xChannel, false, m_block);
+ }
+ if ((mask & TGSI_WRITEMASK_Y)) {
+ llvm::Value *yChannel = elementPointer(out, realIndex, 1);
+ new StoreInst(val[1], yChannel, false, m_block);
+ }
+ if ((mask & TGSI_WRITEMASK_Z)) {
+ llvm::Value *zChannel = elementPointer(out, realIndex, 2);
+ new StoreInst(val[2], zChannel, false, m_block);
+ }
+ if ((mask & TGSI_WRITEMASK_W)) {
+ llvm::Value *wChannel = elementPointer(out, realIndex, 3);
+ new StoreInst(val[3], wChannel, false, m_block);
+ }
+}
+
+void StorageSoa::addAddress(int idx)
+{
+ GlobalVariable *val = new GlobalVariable(
+ /*Type=*/IntegerType::get(32),
+ /*isConstant=*/false,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Initializer=*/0, // has initializer, specified below
+ /*Name=*/name("address"),
+ currentModule());
+ val->setInitializer(Constant::getNullValue(IntegerType::get(32)));
+
+ debug_printf("adding to %d\n", idx);
+ m_addresses[idx] = val;
+}
diff --git a/src/gallium/auxiliary/gallivm/storagesoa.h b/src/gallium/auxiliary/gallivm/storagesoa.h
new file mode 100644
index 0000000000..56886f85e7
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/storagesoa.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STORAGESOA_H
+#define STORAGESOA_H
+
+#include <pipe/p_shader_tokens.h>
+#include <llvm/Support/IRBuilder.h>
+
+#include <vector>
+#include <list>
+#include <map>
+
+namespace llvm {
+ class BasicBlock;
+ class Constant;
+ class ConstantInt;
+ class GlobalVariable;
+ class LoadInst;
+ class Value;
+ class VectorType;
+ class Module;
+}
+
+class StorageSoa
+{
+public:
+ StorageSoa(llvm::BasicBlock *block,
+ llvm::Value *input,
+ llvm::Value *output,
+ llvm::Value *consts);
+
+
+ std::vector<llvm::Value*> load(enum tgsi_file_type type, int idx, int swizzle,
+ llvm::IRBuilder<>* m_builder, llvm::Value *indIdx =0);
+ void store(enum tgsi_file_type type, int idx, const std::vector<llvm::Value*> &val,
+ int mask, llvm::IRBuilder<>* m_builder);
+
+ void addImmediate(float *vec);
+ void declareImmediates();
+
+ void addAddress(int idx);
+
+ llvm::Value * addrElement(int idx) const;
+
+ llvm::ConstantInt *constantInt(int) const;
+private:
+ llvm::Value *elementPointer(llvm::Value *ptr, llvm::Value *indIdx,
+ int channel) const;
+ llvm::Value *element(llvm::Value *ptr, llvm::Value *idx,
+ int channel) const;
+ const char *name(const char *prefix) const;
+ llvm::Value *alignedArrayLoad(llvm::Value *val);
+ llvm::Module *currentModule() const;
+ llvm::Constant *createConstGlobalFloat(const float val);
+ llvm::Constant *createConstGlobalVector(const std::vector<float> &vec);
+
+ std::vector<llvm::Value*> inputElement(llvm::Value *indIdx);
+ llvm::Value* unpackConstElement(llvm::IRBuilder<>* m_builder, llvm::Value *indIdx, int cc);
+ std::vector<llvm::Value*> constElement(llvm::IRBuilder<>* m_builder, llvm::Value *indIdx);
+ std::vector<llvm::Value*> outputElement(llvm::Value *indIdx);
+ std::vector<llvm::Value*> tempElement(llvm::IRBuilder<>* m_builder, int idx);
+ std::vector<llvm::Value*> immediateElement(llvm::Value *indIdx);
+private:
+ llvm::BasicBlock *m_block;
+
+ llvm::Value *m_input;
+ llvm::Value *m_output;
+ llvm::Value *m_consts;
+ std::map<int, llvm::Value*> m_temps;
+ llvm::GlobalVariable *m_immediates;
+
+ std::map<int, llvm::Value*> m_addresses;
+
+ std::vector<std::vector<float> > m_immediatesToFlush;
+ llvm::Value * allocaTemp(llvm::IRBuilder<>* m_builder);
+
+ mutable std::map<int, llvm::ConstantInt*> m_constInts;
+ mutable char m_name[32];
+ mutable int m_idx;
+};
+
+#endif
diff --git a/src/gallium/auxiliary/gallivm/tgsitollvm.cpp b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp
new file mode 100644
index 0000000000..bf84401e11
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp
@@ -0,0 +1,1136 @@
+#include "tgsitollvm.h"
+
+#include "gallivm.h"
+#include "gallivm_p.h"
+
+#include "storage.h"
+#include "instructions.h"
+#include "storagesoa.h"
+#include "instructionssoa.h"
+
+#include "pipe/p_shader_tokens.h"
+
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_exec.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_build.h"
+#include "tgsi/tgsi_dump.h"
+
+
+#include <llvm/Module.h>
+#include <llvm/CallingConv.h>
+#include <llvm/Constants.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Instructions.h>
+#include <llvm/ModuleProvider.h>
+#include <llvm/Pass.h>
+#include <llvm/PassManager.h>
+#include <llvm/Attributes.h>
+#include <llvm/Support/PatternMatch.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/ExecutionEngine/Interpreter.h>
+#include <llvm/ExecutionEngine/GenericValue.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/LinkAllPasses.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Analysis/LoopPass.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/Transforms/Utils/Cloning.h>
+
+
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+using namespace llvm;
+
+static inline FunctionType *vertexShaderFunctionType()
+{
+ //Function takes three arguments,
+ // the calling code has to make sure the types it will
+ // pass are castable to the following:
+ // [4 x <4 x float>] inputs,
+ // [4 x <4 x float>] output,
+ // [4 x [1 x float]] consts,
+
+ std::vector<const Type*> funcArgs;
+ VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
+ ArrayType *vectorArray = ArrayType::get(vectorType, 4);
+ PointerType *vectorArrayPtr = PointerType::get(vectorArray, 0);
+
+ ArrayType *floatArray = ArrayType::get(Type::FloatTy, 4);
+ ArrayType *constsArray = ArrayType::get(floatArray, 1);
+ PointerType *constsArrayPtr = PointerType::get(constsArray, 0);
+
+ funcArgs.push_back(vectorArrayPtr);//inputs
+ funcArgs.push_back(vectorArrayPtr);//output
+ funcArgs.push_back(constsArrayPtr);//consts
+
+ FunctionType *functionType = FunctionType::get(
+ /*Result=*/Type::VoidTy,
+ /*Params=*/funcArgs,
+ /*isVarArg=*/false);
+
+ return functionType;
+}
+
+static inline void
+add_interpolator(struct gallivm_ir *ir,
+ struct gallivm_interpolate *interp)
+{
+ ir->interpolators[ir->num_interp] = *interp;
+ ++ir->num_interp;
+}
+
+static void
+translate_declaration(struct gallivm_ir *prog,
+ llvm::Module *module,
+ Storage *storage,
+ struct tgsi_full_declaration *decl,
+ struct tgsi_full_declaration *fd)
+{
+ if (decl->Declaration.File == TGSI_FILE_INPUT) {
+ unsigned first, last, mask;
+ uint interp_method;
+
+ first = decl->DeclarationRange.First;
+ last = decl->DeclarationRange.Last;
+ mask = decl->Declaration.UsageMask;
+
+ /* Do not touch WPOS.xy */
+ if (first == 0) {
+ mask &= ~TGSI_WRITEMASK_XY;
+ if (mask == TGSI_WRITEMASK_NONE) {
+ first++;
+ if (first > last) {
+ return;
+ }
+ }
+ }
+
+ interp_method = decl->Declaration.Interpolate;
+
+ if (mask == TGSI_WRITEMASK_XYZW) {
+ unsigned i, j;
+
+ for (i = first; i <= last; i++) {
+ for (j = 0; j < NUM_CHANNELS; j++) {
+ //interp( mach, i, j );
+ struct gallivm_interpolate interp;
+ interp.type = interp_method;
+ interp.attrib = i;
+ interp.chan = j;
+ add_interpolator(prog, &interp);
+ }
+ }
+ } else {
+ unsigned i, j;
+ for( j = 0; j < NUM_CHANNELS; j++ ) {
+ if( mask & (1 << j) ) {
+ for( i = first; i <= last; i++ ) {
+ struct gallivm_interpolate interp;
+ interp.type = interp_method;
+ interp.attrib = i;
+ interp.chan = j;
+ add_interpolator(prog, &interp);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void
+translate_declarationir(struct gallivm_ir *,
+ llvm::Module *,
+ StorageSoa *storage,
+ struct tgsi_full_declaration *decl,
+ struct tgsi_full_declaration *)
+{
+ if (decl->Declaration.File == TGSI_FILE_ADDRESS) {
+ int idx = decl->DeclarationRange.First;
+ storage->addAddress(idx);
+ }
+}
+
+static void
+translate_immediate(Storage *storage,
+ struct tgsi_full_immediate *imm)
+{
+ float vec[4];
+ int i;
+ assert( imm->Immediate.NrTokens <= 4 + 1 );
+ for (i = 0; i < imm->Immediate.NrTokens - 1; ++i) {
+ switch (imm->Immediate.DataType) {
+ case TGSI_IMM_FLOAT32:
+ vec[i] = imm->u[i].Float;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ storage->addImmediate(vec);
+}
+
+
+static void
+translate_immediateir(StorageSoa *storage,
+ struct tgsi_full_immediate *imm)
+{
+ float vec[4];
+ int i;
+ assert( imm->Immediate.NrTokens <= 4 + 1 );
+ for (i = 0; i < imm->Immediate.NrTokens - 1; ++i) {
+ switch (imm->Immediate.DataType) {
+ case TGSI_IMM_FLOAT32:
+ vec[i] = imm->u[i].Float;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ storage->addImmediate(vec);
+}
+
+static inline int
+swizzleInt(struct tgsi_full_src_register *src)
+{
+ int swizzle = 0;
+ int start = 1000;
+
+ for (int k = 0; k < 4; ++k) {
+ swizzle += tgsi_util_get_full_src_register_extswizzle(src, k) * start;
+ start /= 10;
+ }
+ return swizzle;
+}
+
+static inline llvm::Value *
+swizzleVector(llvm::Value *val, struct tgsi_full_src_register *src,
+ Storage *storage)
+{
+ int swizzle = swizzleInt(src);
+
+ if (gallivm_is_swizzle(swizzle)) {
+ /*fprintf(stderr, "XXXXXXXX swizzle = %d\n", swizzle);*/
+ val = storage->shuffleVector(val, swizzle);
+ }
+ return val;
+}
+
+static void
+translate_instruction(llvm::Module *module,
+ Storage *storage,
+ Instructions *instr,
+ struct tgsi_full_instruction *inst,
+ struct tgsi_full_instruction *fi,
+ unsigned instno)
+{
+ llvm::Value *inputs[4];
+ inputs[0] = 0;
+ inputs[1] = 0;
+ inputs[2] = 0;
+ inputs[3] = 0;
+
+ for (int i = 0; i < inst->Instruction.NumSrcRegs; ++i) {
+ struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
+ llvm::Value *val = 0;
+ llvm::Value *indIdx = 0;
+
+ if (src->SrcRegister.Indirect) {
+ indIdx = storage->addrElement(src->SrcRegisterInd.Index);
+ indIdx = storage->extractIndex(indIdx);
+ }
+ if (src->SrcRegister.File == TGSI_FILE_CONSTANT) {
+ val = storage->constElement(src->SrcRegister.Index, indIdx);
+ } else if (src->SrcRegister.File == TGSI_FILE_INPUT) {
+ val = storage->inputElement(src->SrcRegister.Index, indIdx);
+ } else if (src->SrcRegister.File == TGSI_FILE_TEMPORARY) {
+ val = storage->tempElement(src->SrcRegister.Index);
+ } else if (src->SrcRegister.File == TGSI_FILE_OUTPUT) {
+ val = storage->outputElement(src->SrcRegister.Index, indIdx);
+ } else if (src->SrcRegister.File == TGSI_FILE_IMMEDIATE) {
+ val = storage->immediateElement(src->SrcRegister.Index);
+ } else {
+ fprintf(stderr, "ERROR: not supported llvm source %d\n", src->SrcRegister.File);
+ return;
+ }
+
+ inputs[i] = swizzleVector(val, src, storage);
+ }
+
+ /*if (inputs[0])
+ instr->printVector(inputs[0]);
+ if (inputs[1])
+ instr->printVector(inputs[1]);*/
+ llvm::Value *out = 0;
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ARL: {
+ out = instr->arl(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_MOV: {
+ out = inputs[0];
+ }
+ break;
+ case TGSI_OPCODE_LIT: {
+ out = instr->lit(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_RCP: {
+ out = instr->rcp(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_RSQ: {
+ out = instr->rsq(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_EXP: {
+ out = instr->exp(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_LOG: {
+ out = instr->log(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_MUL: {
+ out = instr->mul(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_ADD: {
+ out = instr->add(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_DP3: {
+ out = instr->dp3(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_DP4: {
+ out = instr->dp4(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_DST: {
+ out = instr->dst(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_MIN: {
+ out = instr->min(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_MAX: {
+ out = instr->max(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_SLT: {
+ out = instr->slt(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_SGE: {
+ out = instr->sge(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_MAD: {
+ out = instr->madd(inputs[0], inputs[1], inputs[2]);
+ }
+ break;
+ case TGSI_OPCODE_SUB: {
+ out = instr->sub(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_LRP: {
+ out = instr->lerp(inputs[0], inputs[1], inputs[2]);
+ }
+ break;
+ case TGSI_OPCODE_CND: {
+ out = instr->cnd(inputs[0], inputs[1], inputs[2]);
+ }
+ break;
+ case TGSI_OPCODE_CND0: {
+ out = instr->cnd0(inputs[0], inputs[1], inputs[2]);
+ }
+ break;
+ case TGSI_OPCODE_DP2A: {
+ out = instr->dot2add(inputs[0], inputs[1], inputs[2]);
+ }
+ break;
+ case TGSI_OPCODE_FRC: {
+ out = instr->frc(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_CLAMP: {
+ out = instr->clamp(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_FLR: {
+ out = instr->floor(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_ROUND:
+ break;
+ case TGSI_OPCODE_EX2: {
+ out = instr->ex2(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_LG2: {
+ out = instr->lg2(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_POW: {
+ out = instr->pow(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_XPD: {
+ out = instr->cross(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_ABS: {
+ out = instr->abs(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_RCC:
+ break;
+ case TGSI_OPCODE_DPH: {
+ out = instr->dph(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_COS: {
+ out = instr->cos(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_DDX: {
+ out = instr->ddx(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_DDY: {
+ out = instr->ddy(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_KILP:
+ break;
+ case TGSI_OPCODE_PK2H:
+ break;
+ case TGSI_OPCODE_PK2US:
+ break;
+ case TGSI_OPCODE_PK4B:
+ break;
+ case TGSI_OPCODE_PK4UB:
+ break;
+ case TGSI_OPCODE_RFL:
+ break;
+ case TGSI_OPCODE_SEQ: {
+ out = instr->seq(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_SFL: {
+ out = instr->sfl(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_SGT: {
+ out = instr->sgt(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_SIN: {
+ out = instr->sin(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_SLE: {
+ out = instr->sle(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_SNE: {
+ out = instr->sne(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_STR: {
+ out = instr->str(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_TEX:
+ break;
+ case TGSI_OPCODE_TXD:
+ break;
+ case TGSI_OPCODE_UP2H:
+ break;
+ case TGSI_OPCODE_UP2US:
+ break;
+ case TGSI_OPCODE_UP4B:
+ break;
+ case TGSI_OPCODE_UP4UB:
+ break;
+ case TGSI_OPCODE_X2D: {
+ out = instr->x2d(inputs[0], inputs[1], inputs[2]);
+ }
+ break;
+ case TGSI_OPCODE_ARA:
+ break;
+ case TGSI_OPCODE_ARR:
+ break;
+ case TGSI_OPCODE_BRA:
+ break;
+ case TGSI_OPCODE_CAL: {
+ instr->cal(inst->InstructionExtLabel.Label, storage->inputPtr());
+ return;
+ }
+ break;
+ case TGSI_OPCODE_RET: {
+ instr->end();
+ return;
+ }
+ break;
+ case TGSI_OPCODE_SSG:
+ break;
+ case TGSI_OPCODE_CMP: {
+ out = instr->cmp(inputs[0], inputs[1], inputs[2]);
+ }
+ break;
+ case TGSI_OPCODE_SCS: {
+ out = instr->scs(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_TXB:
+ break;
+ case TGSI_OPCODE_NRM4:
+ case TGSI_OPCODE_NRM: {
+ out = instr->nrm(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_DIV: {
+ out = instr->div(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_DP2: {
+ out = instr->dp2(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_TXL:
+ break;
+ case TGSI_OPCODE_BRK: {
+ instr->brk();
+ return;
+ }
+ break;
+ case TGSI_OPCODE_IF: {
+ instr->ifop(inputs[0]);
+ storage->setCurrentBlock(instr->currentBlock());
+ return; //just update the state
+ }
+ break;
+ case TGSI_OPCODE_BGNFOR:
+ break;
+ case TGSI_OPCODE_REP:
+ break;
+ case TGSI_OPCODE_ELSE: {
+ instr->elseop();
+ storage->setCurrentBlock(instr->currentBlock());
+ return; //only state update
+ }
+ break;
+ case TGSI_OPCODE_ENDIF: {
+ instr->endif();
+ storage->setCurrentBlock(instr->currentBlock());
+ return; //just update the state
+ }
+ break;
+ case TGSI_OPCODE_ENDFOR:
+ break;
+ case TGSI_OPCODE_ENDREP:
+ break;
+ case TGSI_OPCODE_PUSHA:
+ break;
+ case TGSI_OPCODE_POPA:
+ break;
+ case TGSI_OPCODE_CEIL:
+ break;
+ case TGSI_OPCODE_I2F:
+ break;
+ case TGSI_OPCODE_NOT:
+ break;
+ case TGSI_OPCODE_TRUNC: {
+ out = instr->trunc(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_SHL:
+ break;
+ case TGSI_OPCODE_SHR:
+ break;
+ case TGSI_OPCODE_AND:
+ break;
+ case TGSI_OPCODE_OR:
+ break;
+ case TGSI_OPCODE_MOD:
+ break;
+ case TGSI_OPCODE_XOR:
+ break;
+ case TGSI_OPCODE_SAD:
+ break;
+ case TGSI_OPCODE_TXF:
+ break;
+ case TGSI_OPCODE_TXQ:
+ break;
+ case TGSI_OPCODE_CONT:
+ break;
+ case TGSI_OPCODE_EMIT:
+ break;
+ case TGSI_OPCODE_ENDPRIM:
+ break;
+ case TGSI_OPCODE_BGNLOOP: {
+ instr->beginLoop();
+ storage->setCurrentBlock(instr->currentBlock());
+ return;
+ }
+ break;
+ case TGSI_OPCODE_BGNSUB: {
+ instr->bgnSub(instno);
+ storage->setCurrentBlock(instr->currentBlock());
+ storage->pushTemps();
+ return;
+ }
+ break;
+ case TGSI_OPCODE_ENDLOOP: {
+ instr->endLoop();
+ storage->setCurrentBlock(instr->currentBlock());
+ return;
+ }
+ break;
+ case TGSI_OPCODE_ENDSUB: {
+ instr->endSub();
+ storage->setCurrentBlock(instr->currentBlock());
+ storage->popArguments();
+ storage->popTemps();
+ return;
+ }
+ break;
+ case TGSI_OPCODE_NOISE1:
+ break;
+ case TGSI_OPCODE_NOISE2:
+ break;
+ case TGSI_OPCODE_NOISE3:
+ break;
+ case TGSI_OPCODE_NOISE4:
+ break;
+ case TGSI_OPCODE_NOP:
+ break;
+ case TGSI_OPCODE_CALLNZ:
+ break;
+ case TGSI_OPCODE_IFC:
+ break;
+ case TGSI_OPCODE_BREAKC:
+ break;
+ case TGSI_OPCODE_KIL: {
+ out = instr->kil(inputs[0]);
+ storage->setKilElement(out);
+ return;
+ }
+ break;
+ case TGSI_OPCODE_END:
+ instr->end();
+ return;
+ break;
+ default:
+ fprintf(stderr, "ERROR: Unknown opcode %d\n",
+ inst->Instruction.Opcode);
+ assert(0);
+ break;
+ }
+
+ if (!out) {
+ fprintf(stderr, "ERROR: unsupported opcode %d\n",
+ inst->Instruction.Opcode);
+ assert(!"Unsupported opcode");
+ }
+
+ /* # not sure if we need this */
+ switch( inst->Instruction.Saturate ) {
+ case TGSI_SAT_NONE:
+ break;
+ case TGSI_SAT_ZERO_ONE:
+ /*TXT( "_SAT" );*/
+ break;
+ case TGSI_SAT_MINUS_PLUS_ONE:
+ /*TXT( "_SAT[-1,1]" );*/
+ break;
+ default:
+ assert( 0 );
+ }
+
+ /* store results */
+ for (int i = 0; i < inst->Instruction.NumDstRegs; ++i) {
+ struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
+
+ if (dst->DstRegister.File == TGSI_FILE_OUTPUT) {
+ storage->setOutputElement(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
+ } else if (dst->DstRegister.File == TGSI_FILE_TEMPORARY) {
+ storage->setTempElement(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
+ } else if (dst->DstRegister.File == TGSI_FILE_ADDRESS) {
+ storage->setAddrElement(dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
+ } else {
+ fprintf(stderr, "ERROR: unsupported LLVM destination!");
+ assert(!"wrong destination");
+ }
+ }
+}
+
+
+static void
+translate_instructionir(llvm::Module *module,
+ StorageSoa *storage,
+ InstructionsSoa *instr,
+ struct tgsi_full_instruction *inst,
+ struct tgsi_full_instruction *fi,
+ unsigned instno)
+{
+ std::vector< std::vector<llvm::Value*> > inputs(inst->Instruction.NumSrcRegs);
+
+ for (int i = 0; i < inst->Instruction.NumSrcRegs; ++i) {
+ struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
+ std::vector<llvm::Value*> val;
+ llvm::Value *indIdx = 0;
+ int swizzle = swizzleInt(src);
+
+ if (src->SrcRegister.Indirect) {
+ indIdx = storage->addrElement(src->SrcRegisterInd.Index);
+ }
+ val = storage->load((enum tgsi_file_type)src->SrcRegister.File,
+ src->SrcRegister.Index, swizzle, instr->getIRBuilder(), indIdx);
+
+ inputs[i] = val;
+ }
+
+ std::vector<llvm::Value*> out(4);
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ARL: {
+ out = instr->arl(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_MOV: {
+ out = inputs[0];
+ }
+ break;
+ case TGSI_OPCODE_LIT: {
+ out = instr->lit(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_RCP: {
+ }
+ break;
+ case TGSI_OPCODE_RSQ: {
+ out = instr->rsq(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_EXP:
+ break;
+ case TGSI_OPCODE_LOG:
+ break;
+ case TGSI_OPCODE_MUL: {
+ out = instr->mul(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_ADD: {
+ out = instr->add(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_DP3: {
+ out = instr->dp3(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_DP4: {
+ out = instr->dp4(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_DST: {
+ }
+ break;
+ case TGSI_OPCODE_MIN: {
+ out = instr->min(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_MAX: {
+ out = instr->max(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_SLT: {
+ out = instr->slt(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_SGE: {
+ }
+ break;
+ case TGSI_OPCODE_MAD: {
+ out = instr->madd(inputs[0], inputs[1], inputs[2]);
+ }
+ break;
+ case TGSI_OPCODE_SUB: {
+ out = instr->sub(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_LRP: {
+ }
+ break;
+ case TGSI_OPCODE_CND:
+ break;
+ case TGSI_OPCODE_CND0:
+ break;
+ case TGSI_OPCODE_DP2A:
+ break;
+ case TGSI_OPCODE_FRC: {
+ }
+ break;
+ case TGSI_OPCODE_CLAMP:
+ break;
+ case TGSI_OPCODE_FLR: {
+ }
+ break;
+ case TGSI_OPCODE_ROUND:
+ break;
+ case TGSI_OPCODE_EX2: {
+ }
+ break;
+ case TGSI_OPCODE_LG2: {
+ }
+ break;
+ case TGSI_OPCODE_POW: {
+ out = instr->pow(inputs[0], inputs[1]);
+ }
+ break;
+ case TGSI_OPCODE_XPD: {
+ }
+ break;
+ case TGSI_OPCODE_ABS: {
+ out = instr->abs(inputs[0]);
+ }
+ break;
+ case TGSI_OPCODE_RCC:
+ break;
+ case TGSI_OPCODE_DPH: {
+ }
+ break;
+ case TGSI_OPCODE_COS: {
+ }
+ break;
+ case TGSI_OPCODE_DDX:
+ break;
+ case TGSI_OPCODE_DDY:
+ break;
+ case TGSI_OPCODE_KILP:
+ break;
+ case TGSI_OPCODE_PK2H:
+ break;
+ case TGSI_OPCODE_PK2US:
+ break;
+ case TGSI_OPCODE_PK4B:
+ break;
+ case TGSI_OPCODE_PK4UB:
+ break;
+ case TGSI_OPCODE_RFL:
+ break;
+ case TGSI_OPCODE_SEQ:
+ break;
+ case TGSI_OPCODE_SFL:
+ break;
+ case TGSI_OPCODE_SGT: {
+ }
+ break;
+ case TGSI_OPCODE_SIN: {
+ }
+ break;
+ case TGSI_OPCODE_SLE:
+ break;
+ case TGSI_OPCODE_SNE:
+ break;
+ case TGSI_OPCODE_STR:
+ break;
+ case TGSI_OPCODE_TEX:
+ break;
+ case TGSI_OPCODE_TXD:
+ break;
+ case TGSI_OPCODE_UP2H:
+ break;
+ case TGSI_OPCODE_UP2US:
+ break;
+ case TGSI_OPCODE_UP4B:
+ break;
+ case TGSI_OPCODE_UP4UB:
+ break;
+ case TGSI_OPCODE_X2D:
+ break;
+ case TGSI_OPCODE_ARA:
+ break;
+ case TGSI_OPCODE_ARR:
+ break;
+ case TGSI_OPCODE_BRA:
+ break;
+ case TGSI_OPCODE_CAL: {
+ }
+ break;
+ case TGSI_OPCODE_RET: {
+ }
+ break;
+ case TGSI_OPCODE_SSG:
+ break;
+ case TGSI_OPCODE_CMP: {
+ }
+ break;
+ case TGSI_OPCODE_SCS: {
+ }
+ break;
+ case TGSI_OPCODE_TXB:
+ break;
+ case TGSI_OPCODE_NRM:
+ break;
+ case TGSI_OPCODE_DIV:
+ break;
+ case TGSI_OPCODE_DP2:
+ break;
+ case TGSI_OPCODE_TXL:
+ break;
+ case TGSI_OPCODE_BRK: {
+ }
+ break;
+ case TGSI_OPCODE_IF: {
+ }
+ break;
+ case TGSI_OPCODE_BGNFOR:
+ break;
+ case TGSI_OPCODE_REP:
+ break;
+ case TGSI_OPCODE_ELSE: {
+ }
+ break;
+ case TGSI_OPCODE_ENDIF: {
+ }
+ break;
+ case TGSI_OPCODE_ENDFOR:
+ break;
+ case TGSI_OPCODE_ENDREP:
+ break;
+ case TGSI_OPCODE_PUSHA:
+ break;
+ case TGSI_OPCODE_POPA:
+ break;
+ case TGSI_OPCODE_CEIL:
+ break;
+ case TGSI_OPCODE_I2F:
+ break;
+ case TGSI_OPCODE_NOT:
+ break;
+ case TGSI_OPCODE_TRUNC: {
+ }
+ break;
+ case TGSI_OPCODE_SHL:
+ break;
+ case TGSI_OPCODE_SHR:
+ break;
+ case TGSI_OPCODE_AND:
+ break;
+ case TGSI_OPCODE_OR:
+ break;
+ case TGSI_OPCODE_MOD:
+ break;
+ case TGSI_OPCODE_XOR:
+ break;
+ case TGSI_OPCODE_SAD:
+ break;
+ case TGSI_OPCODE_TXF:
+ break;
+ case TGSI_OPCODE_TXQ:
+ break;
+ case TGSI_OPCODE_CONT:
+ break;
+ case TGSI_OPCODE_EMIT:
+ break;
+ case TGSI_OPCODE_ENDPRIM:
+ break;
+ case TGSI_OPCODE_BGNLOOP: {
+ }
+ break;
+ case TGSI_OPCODE_BGNSUB: {
+ }
+ break;
+ case TGSI_OPCODE_ENDLOOP: {
+ }
+ break;
+ case TGSI_OPCODE_ENDSUB: {
+ }
+ break;
+ case TGSI_OPCODE_NOISE1:
+ break;
+ case TGSI_OPCODE_NOISE2:
+ break;
+ case TGSI_OPCODE_NOISE3:
+ break;
+ case TGSI_OPCODE_NOISE4:
+ break;
+ case TGSI_OPCODE_NOP:
+ break;
+ case TGSI_OPCODE_NRM4:
+ break;
+ case TGSI_OPCODE_CALLNZ:
+ break;
+ case TGSI_OPCODE_IFC:
+ break;
+ case TGSI_OPCODE_BREAKC:
+ break;
+ case TGSI_OPCODE_KIL: {
+ }
+ break;
+ case TGSI_OPCODE_END:
+ instr->end();
+ return;
+ break;
+ default:
+ fprintf(stderr, "ERROR: Unknown opcode %d\n",
+ inst->Instruction.Opcode);
+ assert(0);
+ break;
+ }
+
+ if (!out[0]) {
+ fprintf(stderr, "ERROR: unsupported opcode %d\n",
+ inst->Instruction.Opcode);
+ assert(!"Unsupported opcode");
+ }
+
+ /* store results */
+ for (int i = 0; i < inst->Instruction.NumDstRegs; ++i) {
+ struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
+ storage->store((enum tgsi_file_type)dst->DstRegister.File,
+ dst->DstRegister.Index, out, dst->DstRegister.WriteMask,
+ instr->getIRBuilder() );
+ }
+}
+
+llvm::Module *
+tgsi_to_llvm(struct gallivm_ir *ir, const struct tgsi_token *tokens)
+{
+ llvm::Module *mod = new Module("shader");
+ struct tgsi_parse_context parse;
+ struct tgsi_full_instruction fi;
+ struct tgsi_full_declaration fd;
+ unsigned instno = 0;
+ Function* shader = mod->getFunction("execute_shader");
+ std::ostringstream stream;
+ if (ir->type == GALLIVM_VS) {
+ stream << "vs_shader";
+ } else {
+ stream << "fs_shader";
+ }
+ stream << ir->id;
+ std::string func_name = stream.str();
+ shader->setName(func_name.c_str());
+
+ Function::arg_iterator args = shader->arg_begin();
+ Value *ptr_INPUT = args++;
+ ptr_INPUT->setName("input");
+
+ BasicBlock *label_entry = BasicBlock::Create("entry", shader, 0);
+
+ tgsi_parse_init(&parse, tokens);
+
+ fi = tgsi_default_full_instruction();
+ fd = tgsi_default_full_declaration();
+ Storage storage(label_entry, ptr_INPUT);
+ Instructions instr(mod, shader, label_entry, &storage);
+ while(!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ translate_declaration(ir, mod, &storage,
+ &parse.FullToken.FullDeclaration,
+ &fd);
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ translate_immediate(&storage,
+ &parse.FullToken.FullImmediate);
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ translate_instruction(mod, &storage, &instr,
+ &parse.FullToken.FullInstruction,
+ &fi, instno);
+ ++instno;
+ break;
+
+ default:
+ assert(0);
+ }
+ }
+
+ tgsi_parse_free(&parse);
+
+ ir->num_consts = storage.numConsts();
+ return mod;
+}
+
+llvm::Module * tgsi_to_llvmir(struct gallivm_ir *ir,
+ const struct tgsi_token *tokens)
+{
+ llvm::Module *mod = new Module("shader");
+ struct tgsi_parse_context parse;
+ struct tgsi_full_instruction fi;
+ struct tgsi_full_declaration fd;
+ unsigned instno = 0;
+ std::ostringstream stream;
+ if (ir->type == GALLIVM_VS) {
+ stream << "vs_shader";
+ } else {
+ stream << "fs_shader";
+ }
+ //stream << ir->id;
+ std::string func_name = stream.str();
+ Function *shader = llvm::cast<Function>(mod->getOrInsertFunction(
+ func_name.c_str(),
+ vertexShaderFunctionType()));
+
+ Function::arg_iterator args = shader->arg_begin();
+ Value *input = args++;
+ input->setName("inputs");
+ Value *output = args++;
+ output->setName("outputs");
+ Value *consts = args++;
+ consts->setName("consts");
+
+ BasicBlock *label_entry = BasicBlock::Create("entry", shader, 0);
+
+ tgsi_parse_init(&parse, tokens);
+
+ fi = tgsi_default_full_instruction();
+ fd = tgsi_default_full_declaration();
+
+ StorageSoa storage(label_entry, input, output, consts);
+ InstructionsSoa instr(mod, shader, label_entry, &storage);
+
+ while(!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ translate_declarationir(ir, mod, &storage,
+ &parse.FullToken.FullDeclaration,
+ &fd);
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ translate_immediateir(&storage,
+ &parse.FullToken.FullImmediate);
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ storage.declareImmediates();
+ translate_instructionir(mod, &storage, &instr,
+ &parse.FullToken.FullInstruction,
+ &fi, instno);
+ ++instno;
+ break;
+
+ default:
+ assert(0);
+ }
+ }
+
+ tgsi_parse_free(&parse);
+
+ return mod;
+}
diff --git a/src/gallium/auxiliary/gallivm/tgsitollvm.h b/src/gallium/auxiliary/gallivm/tgsitollvm.h
new file mode 100644
index 0000000000..7ada04d629
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/tgsitollvm.h
@@ -0,0 +1,20 @@
+#ifndef TGSITOLLVM_H
+#define TGSITOLLVM_H
+
+
+namespace llvm {
+ class Module;
+}
+
+struct gallivm_ir;
+struct tgsi_token;
+
+
+llvm::Module * tgsi_to_llvm(struct gallivm_ir *ir,
+ const struct tgsi_token *tokens);
+
+
+llvm::Module * tgsi_to_llvmir(struct gallivm_ir *ir,
+ const struct tgsi_token *tokens);
+
+#endif
diff --git a/src/gallium/auxiliary/indices/Makefile b/src/gallium/auxiliary/indices/Makefile
new file mode 100644
index 0000000000..f2ebc3f410
--- /dev/null
+++ b/src/gallium/auxiliary/indices/Makefile
@@ -0,0 +1,16 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = indices
+
+C_SOURCES = \
+ u_indices_gen.c \
+ u_unfilled_gen.c
+
+include ../../Makefile.template
+
+u_indices_gen.c: u_indices_gen.py
+ python $< > $@
+
+u_unfilled_gen.c: u_unfilled_gen.py
+ python $< > $@
diff --git a/src/gallium/auxiliary/indices/SConscript b/src/gallium/auxiliary/indices/SConscript
new file mode 100644
index 0000000000..712e215534
--- /dev/null
+++ b/src/gallium/auxiliary/indices/SConscript
@@ -0,0 +1,28 @@
+Import('*')
+
+from sys import executable as python_cmd
+
+env.CodeGenerate(
+ target = 'u_indices_gen.c',
+ script = 'u_indices_gen.py',
+ source = [],
+ command = python_cmd + ' $SCRIPT > $TARGET'
+)
+
+env.CodeGenerate(
+ target = 'u_unfilled_gen.c',
+ script = 'u_unfilled_gen.py',
+ source = [],
+ command = python_cmd + ' $SCRIPT > $TARGET'
+)
+
+indices = env.ConvenienceLibrary(
+ target = 'indices',
+ source = [
+# 'u_indices.c',
+# 'u_unfilled_indices.c',
+ 'u_indices_gen.c',
+ 'u_unfilled_gen.c',
+ ])
+
+auxiliaries.insert(0, indices)
diff --git a/src/gallium/auxiliary/indices/u_indices.c b/src/gallium/auxiliary/indices/u_indices.c
new file mode 100644
index 0000000000..03d7453f30
--- /dev/null
+++ b/src/gallium/auxiliary/indices/u_indices.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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 "u_indices.h"
+#include "u_indices_priv.h"
+
+static void translate_memcpy_ushort( const void *in,
+ unsigned nr,
+ void *out )
+{
+ memcpy(out, in, nr*sizeof(short));
+}
+
+static void translate_memcpy_uint( const void *in,
+ unsigned nr,
+ void *out )
+{
+ memcpy(out, in, nr*sizeof(int));
+}
+
+
+int u_index_translator( unsigned hw_mask,
+ unsigned prim,
+ unsigned in_index_size,
+ unsigned nr,
+ unsigned in_pv,
+ unsigned out_pv,
+ unsigned *out_prim,
+ unsigned *out_index_size,
+ unsigned *out_nr,
+ u_translate_func *out_translate )
+{
+ unsigned in_idx;
+ unsigned out_idx;
+ int ret = U_TRANSLATE_NORMAL;
+
+ u_index_init();
+
+ in_idx = in_size_idx(in_index_size);
+ *out_index_size = (in_index_size == 4) ? 4 : 2;
+ out_idx = out_size_idx(*out_index_size);
+
+ if ((hw_mask & (1<<prim)) &&
+ in_index_size == *out_index_size &&
+ in_pv == out_pv)
+ {
+ if (in_index_size == 4)
+ *out_translate = translate_memcpy_uint;
+ else
+ *out_translate = translate_memcpy_ushort;
+
+ *out_prim = prim;
+ *out_nr = nr;
+
+ return U_TRANSLATE_MEMCPY;
+ }
+ else {
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_POINTS;
+ *out_nr = nr;
+ break;
+
+ case PIPE_PRIM_LINES:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_LINES;
+ *out_nr = nr;
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_LINES;
+ *out_nr = (nr - 1) * 2;
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_LINES;
+ *out_nr = nr * 2;
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = nr;
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr - 2) * 3;
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr - 2) * 3;
+ break;
+
+ case PIPE_PRIM_QUADS:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr / 4) * 6;
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr - 2) * 3;
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr - 2) * 3;
+ break;
+
+ default:
+ assert(0);
+ *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_POINTS;
+ *out_nr = nr;
+ return U_TRANSLATE_ERROR;
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+
+int u_index_generator( unsigned hw_mask,
+ unsigned prim,
+ unsigned start,
+ unsigned nr,
+ unsigned in_pv,
+ unsigned out_pv,
+ unsigned *out_prim,
+ unsigned *out_index_size,
+ unsigned *out_nr,
+ u_generate_func *out_generate )
+
+{
+ unsigned out_idx;
+
+ u_index_init();
+
+ *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;
+ out_idx = out_size_idx(*out_index_size);
+
+ if ((hw_mask & (1<<prim)) &&
+ (in_pv == out_pv)) {
+
+ *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
+ *out_prim = prim;
+ *out_nr = nr;
+ return U_GENERATE_LINEAR;
+ }
+ else {
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_POINTS;
+ *out_nr = nr;
+ return U_GENERATE_REUSABLE;
+
+ case PIPE_PRIM_LINES:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_LINES;
+ *out_nr = nr;
+ return U_GENERATE_REUSABLE;
+
+ case PIPE_PRIM_LINE_STRIP:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_LINES;
+ *out_nr = (nr - 1) * 2;
+ return U_GENERATE_REUSABLE;
+
+ case PIPE_PRIM_LINE_LOOP:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_LINES;
+ *out_nr = nr * 2;
+ return U_GENERATE_ONE_OFF;
+
+ case PIPE_PRIM_TRIANGLES:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = nr;
+ return U_GENERATE_REUSABLE;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr - 2) * 3;
+ return U_GENERATE_REUSABLE;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr - 2) * 3;
+ return U_GENERATE_REUSABLE;
+
+ case PIPE_PRIM_QUADS:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr / 4) * 6;
+ return U_GENERATE_REUSABLE;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr - 2) * 3;
+ return U_GENERATE_REUSABLE;
+
+ case PIPE_PRIM_POLYGON:
+ *out_generate = generate[out_idx][in_pv][out_pv][prim];
+ *out_prim = PIPE_PRIM_TRIANGLES;
+ *out_nr = (nr - 2) * 3;
+ return U_GENERATE_REUSABLE;
+
+ default:
+ assert(0);
+ *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
+ *out_prim = PIPE_PRIM_POINTS;
+ *out_nr = nr;
+ return U_TRANSLATE_ERROR;
+ }
+ }
+}
diff --git a/src/gallium/auxiliary/indices/u_indices.h b/src/gallium/auxiliary/indices/u_indices.h
new file mode 100644
index 0000000000..be522c6725
--- /dev/null
+++ b/src/gallium/auxiliary/indices/u_indices.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef U_INDICES_H
+#define U_INDICES_H
+
+#include "pipe/p_compiler.h"
+
+#define PV_FIRST 0
+#define PV_LAST 1
+#define PV_COUNT 2
+
+typedef void (*u_translate_func)( const void *in,
+ unsigned nr,
+ void *out );
+
+typedef void (*u_generate_func)( unsigned nr,
+ void *out );
+
+
+/* Return codes describe the translate/generate operation. Caller may
+ * be able to reuse translated indices under some circumstances.
+ */
+#define U_TRANSLATE_ERROR -1
+#define U_TRANSLATE_NORMAL 1
+#define U_TRANSLATE_MEMCPY 2
+#define U_GENERATE_LINEAR 3
+#define U_GENERATE_REUSABLE 4
+#define U_GENERATE_ONE_OFF 5
+
+
+void u_index_init( void );
+
+int u_index_translator( unsigned hw_mask,
+ unsigned prim,
+ unsigned in_index_size,
+ unsigned nr,
+ unsigned in_pv, /* API */
+ unsigned out_pv, /* hardware */
+ unsigned *out_prim,
+ unsigned *out_index_size,
+ unsigned *out_nr,
+ u_translate_func *out_translate );
+
+/* Note that even when generating it is necessary to know what the
+ * API's PV is, as the indices generated will depend on whether it is
+ * the same as hardware or not, and in the case of triangle strips,
+ * whether it is first or last.
+ */
+int u_index_generator( unsigned hw_mask,
+ unsigned prim,
+ unsigned start,
+ unsigned nr,
+ unsigned in_pv, /* API */
+ unsigned out_pv, /* hardware */
+ unsigned *out_prim,
+ unsigned *out_index_size,
+ unsigned *out_nr,
+ u_generate_func *out_generate );
+
+
+void u_unfilled_init( void );
+
+int u_unfilled_translator( unsigned prim,
+ unsigned in_index_size,
+ unsigned nr,
+ unsigned unfilled_mode,
+ unsigned *out_prim,
+ unsigned *out_index_size,
+ unsigned *out_nr,
+ u_translate_func *out_translate );
+
+int u_unfilled_generator( unsigned prim,
+ unsigned start,
+ unsigned nr,
+ unsigned unfilled_mode,
+ unsigned *out_prim,
+ unsigned *out_index_size,
+ unsigned *out_nr,
+ u_generate_func *out_generate );
+
+
+
+
+#endif
diff --git a/src/gallium/auxiliary/indices/u_indices_gen.c b/src/gallium/auxiliary/indices/u_indices_gen.c
new file mode 100644
index 0000000000..3c981e5d7f
--- /dev/null
+++ b/src/gallium/auxiliary/indices/u_indices_gen.c
@@ -0,0 +1,5129 @@
+/* File automatically generated by indices.py */
+
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+
+
+/**
+ * @file
+ * Functions to translate and generate index lists
+ */
+
+#include "indices/u_indices.h"
+#include "indices/u_indices_priv.h"
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+
+
+static unsigned out_size_idx( unsigned index_size )
+{
+ switch (index_size) {
+ case 4: return OUT_UINT;
+ case 2: return OUT_USHORT;
+ default: assert(0); return OUT_USHORT;
+ }
+}
+
+static unsigned in_size_idx( unsigned index_size )
+{
+ switch (index_size) {
+ case 4: return IN_UINT;
+ case 2: return IN_USHORT;
+ case 1: return IN_UBYTE;
+ default: assert(0); return IN_UBYTE;
+ }
+}
+
+
+static u_translate_func translate[IN_COUNT][OUT_COUNT][PV_COUNT][PV_COUNT][PRIM_COUNT];
+static u_generate_func generate[OUT_COUNT][PV_COUNT][PV_COUNT][PRIM_COUNT];
+
+
+
+static void generate_points_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)(i);
+ }
+}
+static void generate_lines_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)(i);
+ (out+i)[1] = (ushort)(i+1);
+ }
+}
+static void generate_linestrip_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)(i);
+ (out+j)[1] = (ushort)(i+1);
+ }
+}
+static void generate_lineloop_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)(i);
+ (out+j)[1] = (ushort)(i+1);
+ }
+ (out+j)[0] = (ushort)(i);
+ (out+j)[1] = (ushort)(0);
+}
+static void generate_tris_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)(i);
+ (out+i)[1] = (ushort)(i+1);
+ (out+i)[2] = (ushort)(i+2);
+ }
+}
+static void generate_tristrip_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(i);
+ (out+j)[1] = (ushort)(i+1+(i&1));
+ (out+j)[2] = (ushort)(i+2-(i&1));
+ }
+}
+static void generate_trifan_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(0);
+ (out+j)[1] = (ushort)(i+1);
+ (out+j)[2] = (ushort)(i+2);
+ }
+}
+static void generate_quads_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)(i+0);
+ (out+j+0)[1] = (ushort)(i+1);
+ (out+j+0)[2] = (ushort)(i+3);
+ (out+j+3)[0] = (ushort)(i+1);
+ (out+j+3)[1] = (ushort)(i+2);
+ (out+j+3)[2] = (ushort)(i+3);
+ }
+}
+static void generate_quadstrip_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)(i+2);
+ (out+j+0)[1] = (ushort)(i+0);
+ (out+j+0)[2] = (ushort)(i+3);
+ (out+j+3)[0] = (ushort)(i+0);
+ (out+j+3)[1] = (ushort)(i+1);
+ (out+j+3)[2] = (ushort)(i+3);
+ }
+}
+static void generate_polygon_ushort_first2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(0);
+ (out+j)[1] = (ushort)(i+1);
+ (out+j)[2] = (ushort)(i+2);
+ }
+}
+static void generate_points_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)(i);
+ }
+}
+static void generate_lines_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)(i+1);
+ (out+i)[1] = (ushort)(i);
+ }
+}
+static void generate_linestrip_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)(i+1);
+ (out+j)[1] = (ushort)(i);
+ }
+}
+static void generate_lineloop_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)(i+1);
+ (out+j)[1] = (ushort)(i);
+ }
+ (out+j)[0] = (ushort)(0);
+ (out+j)[1] = (ushort)(i);
+}
+static void generate_tris_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)(i+1);
+ (out+i)[1] = (ushort)(i+2);
+ (out+i)[2] = (ushort)(i);
+ }
+}
+static void generate_tristrip_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(i+1+(i&1));
+ (out+j)[1] = (ushort)(i+2-(i&1));
+ (out+j)[2] = (ushort)(i);
+ }
+}
+static void generate_trifan_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(i+1);
+ (out+j)[1] = (ushort)(i+2);
+ (out+j)[2] = (ushort)(0);
+ }
+}
+static void generate_quads_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)(i+1);
+ (out+j+0)[1] = (ushort)(i+3);
+ (out+j+0)[2] = (ushort)(i+0);
+ (out+j+3)[0] = (ushort)(i+2);
+ (out+j+3)[1] = (ushort)(i+3);
+ (out+j+3)[2] = (ushort)(i+1);
+ }
+}
+static void generate_quadstrip_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)(i+0);
+ (out+j+0)[1] = (ushort)(i+3);
+ (out+j+0)[2] = (ushort)(i+2);
+ (out+j+3)[0] = (ushort)(i+1);
+ (out+j+3)[1] = (ushort)(i+3);
+ (out+j+3)[2] = (ushort)(i+0);
+ }
+}
+static void generate_polygon_ushort_first2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(i+1);
+ (out+j)[1] = (ushort)(i+2);
+ (out+j)[2] = (ushort)(0);
+ }
+}
+static void generate_points_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)(i);
+ }
+}
+static void generate_lines_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)(i+1);
+ (out+i)[1] = (ushort)(i);
+ }
+}
+static void generate_linestrip_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)(i+1);
+ (out+j)[1] = (ushort)(i);
+ }
+}
+static void generate_lineloop_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)(i+1);
+ (out+j)[1] = (ushort)(i);
+ }
+ (out+j)[0] = (ushort)(0);
+ (out+j)[1] = (ushort)(i);
+}
+static void generate_tris_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)(i+2);
+ (out+i)[1] = (ushort)(i);
+ (out+i)[2] = (ushort)(i+1);
+ }
+}
+static void generate_tristrip_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(i+2);
+ (out+j)[1] = (ushort)(i+(i&1));
+ (out+j)[2] = (ushort)(i+1-(i&1));
+ }
+}
+static void generate_trifan_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(i+2);
+ (out+j)[1] = (ushort)(0);
+ (out+j)[2] = (ushort)(i+1);
+ }
+}
+static void generate_quads_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)(i+3);
+ (out+j+0)[1] = (ushort)(i+0);
+ (out+j+0)[2] = (ushort)(i+1);
+ (out+j+3)[0] = (ushort)(i+3);
+ (out+j+3)[1] = (ushort)(i+1);
+ (out+j+3)[2] = (ushort)(i+2);
+ }
+}
+static void generate_quadstrip_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)(i+3);
+ (out+j+0)[1] = (ushort)(i+2);
+ (out+j+0)[2] = (ushort)(i+0);
+ (out+j+3)[0] = (ushort)(i+3);
+ (out+j+3)[1] = (ushort)(i+0);
+ (out+j+3)[2] = (ushort)(i+1);
+ }
+}
+static void generate_polygon_ushort_last2first(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(0);
+ (out+j)[1] = (ushort)(i+1);
+ (out+j)[2] = (ushort)(i+2);
+ }
+}
+static void generate_points_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)(i);
+ }
+}
+static void generate_lines_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)(i);
+ (out+i)[1] = (ushort)(i+1);
+ }
+}
+static void generate_linestrip_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)(i);
+ (out+j)[1] = (ushort)(i+1);
+ }
+}
+static void generate_lineloop_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)(i);
+ (out+j)[1] = (ushort)(i+1);
+ }
+ (out+j)[0] = (ushort)(i);
+ (out+j)[1] = (ushort)(0);
+}
+static void generate_tris_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)(i);
+ (out+i)[1] = (ushort)(i+1);
+ (out+i)[2] = (ushort)(i+2);
+ }
+}
+static void generate_tristrip_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(i+(i&1));
+ (out+j)[1] = (ushort)(i+1-(i&1));
+ (out+j)[2] = (ushort)(i+2);
+ }
+}
+static void generate_trifan_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(0);
+ (out+j)[1] = (ushort)(i+1);
+ (out+j)[2] = (ushort)(i+2);
+ }
+}
+static void generate_quads_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)(i+0);
+ (out+j+0)[1] = (ushort)(i+1);
+ (out+j+0)[2] = (ushort)(i+3);
+ (out+j+3)[0] = (ushort)(i+1);
+ (out+j+3)[1] = (ushort)(i+2);
+ (out+j+3)[2] = (ushort)(i+3);
+ }
+}
+static void generate_quadstrip_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)(i+2);
+ (out+j+0)[1] = (ushort)(i+0);
+ (out+j+0)[2] = (ushort)(i+3);
+ (out+j+3)[0] = (ushort)(i+0);
+ (out+j+3)[1] = (ushort)(i+1);
+ (out+j+3)[2] = (ushort)(i+3);
+ }
+}
+static void generate_polygon_ushort_last2last(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)(i+1);
+ (out+j)[1] = (ushort)(i+2);
+ (out+j)[2] = (ushort)(0);
+ }
+}
+static void generate_points_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)(i);
+ }
+}
+static void generate_lines_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)(i);
+ (out+i)[1] = (uint)(i+1);
+ }
+}
+static void generate_linestrip_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)(i);
+ (out+j)[1] = (uint)(i+1);
+ }
+}
+static void generate_lineloop_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)(i);
+ (out+j)[1] = (uint)(i+1);
+ }
+ (out+j)[0] = (uint)(i);
+ (out+j)[1] = (uint)(0);
+}
+static void generate_tris_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)(i);
+ (out+i)[1] = (uint)(i+1);
+ (out+i)[2] = (uint)(i+2);
+ }
+}
+static void generate_tristrip_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(i);
+ (out+j)[1] = (uint)(i+1+(i&1));
+ (out+j)[2] = (uint)(i+2-(i&1));
+ }
+}
+static void generate_trifan_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(0);
+ (out+j)[1] = (uint)(i+1);
+ (out+j)[2] = (uint)(i+2);
+ }
+}
+static void generate_quads_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)(i+0);
+ (out+j+0)[1] = (uint)(i+1);
+ (out+j+0)[2] = (uint)(i+3);
+ (out+j+3)[0] = (uint)(i+1);
+ (out+j+3)[1] = (uint)(i+2);
+ (out+j+3)[2] = (uint)(i+3);
+ }
+}
+static void generate_quadstrip_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)(i+2);
+ (out+j+0)[1] = (uint)(i+0);
+ (out+j+0)[2] = (uint)(i+3);
+ (out+j+3)[0] = (uint)(i+0);
+ (out+j+3)[1] = (uint)(i+1);
+ (out+j+3)[2] = (uint)(i+3);
+ }
+}
+static void generate_polygon_uint_first2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(0);
+ (out+j)[1] = (uint)(i+1);
+ (out+j)[2] = (uint)(i+2);
+ }
+}
+static void generate_points_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)(i);
+ }
+}
+static void generate_lines_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)(i+1);
+ (out+i)[1] = (uint)(i);
+ }
+}
+static void generate_linestrip_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)(i+1);
+ (out+j)[1] = (uint)(i);
+ }
+}
+static void generate_lineloop_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)(i+1);
+ (out+j)[1] = (uint)(i);
+ }
+ (out+j)[0] = (uint)(0);
+ (out+j)[1] = (uint)(i);
+}
+static void generate_tris_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)(i+1);
+ (out+i)[1] = (uint)(i+2);
+ (out+i)[2] = (uint)(i);
+ }
+}
+static void generate_tristrip_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(i+1+(i&1));
+ (out+j)[1] = (uint)(i+2-(i&1));
+ (out+j)[2] = (uint)(i);
+ }
+}
+static void generate_trifan_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(i+1);
+ (out+j)[1] = (uint)(i+2);
+ (out+j)[2] = (uint)(0);
+ }
+}
+static void generate_quads_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)(i+1);
+ (out+j+0)[1] = (uint)(i+3);
+ (out+j+0)[2] = (uint)(i+0);
+ (out+j+3)[0] = (uint)(i+2);
+ (out+j+3)[1] = (uint)(i+3);
+ (out+j+3)[2] = (uint)(i+1);
+ }
+}
+static void generate_quadstrip_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)(i+0);
+ (out+j+0)[1] = (uint)(i+3);
+ (out+j+0)[2] = (uint)(i+2);
+ (out+j+3)[0] = (uint)(i+1);
+ (out+j+3)[1] = (uint)(i+3);
+ (out+j+3)[2] = (uint)(i+0);
+ }
+}
+static void generate_polygon_uint_first2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(i+1);
+ (out+j)[1] = (uint)(i+2);
+ (out+j)[2] = (uint)(0);
+ }
+}
+static void generate_points_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)(i);
+ }
+}
+static void generate_lines_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)(i+1);
+ (out+i)[1] = (uint)(i);
+ }
+}
+static void generate_linestrip_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)(i+1);
+ (out+j)[1] = (uint)(i);
+ }
+}
+static void generate_lineloop_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)(i+1);
+ (out+j)[1] = (uint)(i);
+ }
+ (out+j)[0] = (uint)(0);
+ (out+j)[1] = (uint)(i);
+}
+static void generate_tris_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)(i+2);
+ (out+i)[1] = (uint)(i);
+ (out+i)[2] = (uint)(i+1);
+ }
+}
+static void generate_tristrip_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(i+2);
+ (out+j)[1] = (uint)(i+(i&1));
+ (out+j)[2] = (uint)(i+1-(i&1));
+ }
+}
+static void generate_trifan_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(i+2);
+ (out+j)[1] = (uint)(0);
+ (out+j)[2] = (uint)(i+1);
+ }
+}
+static void generate_quads_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)(i+3);
+ (out+j+0)[1] = (uint)(i+0);
+ (out+j+0)[2] = (uint)(i+1);
+ (out+j+3)[0] = (uint)(i+3);
+ (out+j+3)[1] = (uint)(i+1);
+ (out+j+3)[2] = (uint)(i+2);
+ }
+}
+static void generate_quadstrip_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)(i+3);
+ (out+j+0)[1] = (uint)(i+2);
+ (out+j+0)[2] = (uint)(i+0);
+ (out+j+3)[0] = (uint)(i+3);
+ (out+j+3)[1] = (uint)(i+0);
+ (out+j+3)[2] = (uint)(i+1);
+ }
+}
+static void generate_polygon_uint_last2first(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(0);
+ (out+j)[1] = (uint)(i+1);
+ (out+j)[2] = (uint)(i+2);
+ }
+}
+static void generate_points_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)(i);
+ }
+}
+static void generate_lines_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)(i);
+ (out+i)[1] = (uint)(i+1);
+ }
+}
+static void generate_linestrip_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)(i);
+ (out+j)[1] = (uint)(i+1);
+ }
+}
+static void generate_lineloop_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)(i);
+ (out+j)[1] = (uint)(i+1);
+ }
+ (out+j)[0] = (uint)(i);
+ (out+j)[1] = (uint)(0);
+}
+static void generate_tris_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)(i);
+ (out+i)[1] = (uint)(i+1);
+ (out+i)[2] = (uint)(i+2);
+ }
+}
+static void generate_tristrip_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(i+(i&1));
+ (out+j)[1] = (uint)(i+1-(i&1));
+ (out+j)[2] = (uint)(i+2);
+ }
+}
+static void generate_trifan_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(0);
+ (out+j)[1] = (uint)(i+1);
+ (out+j)[2] = (uint)(i+2);
+ }
+}
+static void generate_quads_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)(i+0);
+ (out+j+0)[1] = (uint)(i+1);
+ (out+j+0)[2] = (uint)(i+3);
+ (out+j+3)[0] = (uint)(i+1);
+ (out+j+3)[1] = (uint)(i+2);
+ (out+j+3)[2] = (uint)(i+3);
+ }
+}
+static void generate_quadstrip_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)(i+2);
+ (out+j+0)[1] = (uint)(i+0);
+ (out+j+0)[2] = (uint)(i+3);
+ (out+j+3)[0] = (uint)(i+0);
+ (out+j+3)[1] = (uint)(i+1);
+ (out+j+3)[2] = (uint)(i+3);
+ }
+}
+static void generate_polygon_uint_last2last(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)(i+1);
+ (out+j)[1] = (uint)(i+2);
+ (out+j)[2] = (uint)(0);
+ }
+}
+static void translate_points_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_linestrip_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_lineloop_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[0];
+}
+static void translate_tris_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ (out+i)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_tristrip_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1+(i&1)];
+ (out+j)[2] = (ushort)in[i+2-(i&1)];
+ }
+}
+static void translate_trifan_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_quads_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+0];
+ (out+j+0)[1] = (ushort)in[i+1];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+1];
+ (out+j+3)[1] = (ushort)in[i+2];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_quadstrip_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+2];
+ (out+j+0)[1] = (ushort)in[i+0];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+0];
+ (out+j+3)[1] = (ushort)in[i+1];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_polygon_ubyte2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_points_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i+1];
+ (out+i)[1] = (ushort)in[i];
+ }
+}
+static void translate_linestrip_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+}
+static void translate_lineloop_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i];
+}
+static void translate_tris_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i+1];
+ (out+i)[1] = (ushort)in[i+2];
+ (out+i)[2] = (ushort)in[i];
+ }
+}
+static void translate_tristrip_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1+(i&1)];
+ (out+j)[1] = (ushort)in[i+2-(i&1)];
+ (out+j)[2] = (ushort)in[i];
+ }
+}
+static void translate_trifan_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i+2];
+ (out+j)[2] = (ushort)in[0];
+ }
+}
+static void translate_quads_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+1];
+ (out+j+0)[1] = (ushort)in[i+3];
+ (out+j+0)[2] = (ushort)in[i+0];
+ (out+j+3)[0] = (ushort)in[i+2];
+ (out+j+3)[1] = (ushort)in[i+3];
+ (out+j+3)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_quadstrip_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+0];
+ (out+j+0)[1] = (ushort)in[i+3];
+ (out+j+0)[2] = (ushort)in[i+2];
+ (out+j+3)[0] = (ushort)in[i+1];
+ (out+j+3)[1] = (ushort)in[i+3];
+ (out+j+3)[2] = (ushort)in[i+0];
+ }
+}
+static void translate_polygon_ubyte2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i+2];
+ (out+j)[2] = (ushort)in[0];
+ }
+}
+static void translate_points_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i+1];
+ (out+i)[1] = (ushort)in[i];
+ }
+}
+static void translate_linestrip_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+}
+static void translate_lineloop_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i];
+}
+static void translate_tris_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i+2];
+ (out+i)[1] = (ushort)in[i];
+ (out+i)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_tristrip_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+2];
+ (out+j)[1] = (ushort)in[i+(i&1)];
+ (out+j)[2] = (ushort)in[i+1-(i&1)];
+ }
+}
+static void translate_trifan_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+2];
+ (out+j)[1] = (ushort)in[0];
+ (out+j)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_quads_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+3];
+ (out+j+0)[1] = (ushort)in[i+0];
+ (out+j+0)[2] = (ushort)in[i+1];
+ (out+j+3)[0] = (ushort)in[i+3];
+ (out+j+3)[1] = (ushort)in[i+1];
+ (out+j+3)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_quadstrip_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+3];
+ (out+j+0)[1] = (ushort)in[i+2];
+ (out+j+0)[2] = (ushort)in[i+0];
+ (out+j+3)[0] = (ushort)in[i+3];
+ (out+j+3)[1] = (ushort)in[i+0];
+ (out+j+3)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_polygon_ubyte2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_points_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_linestrip_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_lineloop_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[0];
+}
+static void translate_tris_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ (out+i)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_tristrip_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+(i&1)];
+ (out+j)[1] = (ushort)in[i+1-(i&1)];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_trifan_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_quads_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+0];
+ (out+j+0)[1] = (ushort)in[i+1];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+1];
+ (out+j+3)[1] = (ushort)in[i+2];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_quadstrip_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+2];
+ (out+j+0)[1] = (ushort)in[i+0];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+0];
+ (out+j+3)[1] = (ushort)in[i+1];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_polygon_ubyte2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i+2];
+ (out+j)[2] = (ushort)in[0];
+ }
+}
+static void translate_points_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ }
+}
+static void translate_linestrip_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+}
+static void translate_lineloop_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[0];
+}
+static void translate_tris_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ (out+i)[2] = (uint)in[i+2];
+ }
+}
+static void translate_tristrip_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1+(i&1)];
+ (out+j)[2] = (uint)in[i+2-(i&1)];
+ }
+}
+static void translate_trifan_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_quads_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+0];
+ (out+j+0)[1] = (uint)in[i+1];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+1];
+ (out+j+3)[1] = (uint)in[i+2];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_quadstrip_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+2];
+ (out+j+0)[1] = (uint)in[i+0];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+0];
+ (out+j+3)[1] = (uint)in[i+1];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_polygon_ubyte2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_points_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i+1];
+ (out+i)[1] = (uint)in[i];
+ }
+}
+static void translate_linestrip_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+}
+static void translate_lineloop_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i];
+}
+static void translate_tris_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i+1];
+ (out+i)[1] = (uint)in[i+2];
+ (out+i)[2] = (uint)in[i];
+ }
+}
+static void translate_tristrip_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1+(i&1)];
+ (out+j)[1] = (uint)in[i+2-(i&1)];
+ (out+j)[2] = (uint)in[i];
+ }
+}
+static void translate_trifan_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i+2];
+ (out+j)[2] = (uint)in[0];
+ }
+}
+static void translate_quads_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+1];
+ (out+j+0)[1] = (uint)in[i+3];
+ (out+j+0)[2] = (uint)in[i+0];
+ (out+j+3)[0] = (uint)in[i+2];
+ (out+j+3)[1] = (uint)in[i+3];
+ (out+j+3)[2] = (uint)in[i+1];
+ }
+}
+static void translate_quadstrip_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+0];
+ (out+j+0)[1] = (uint)in[i+3];
+ (out+j+0)[2] = (uint)in[i+2];
+ (out+j+3)[0] = (uint)in[i+1];
+ (out+j+3)[1] = (uint)in[i+3];
+ (out+j+3)[2] = (uint)in[i+0];
+ }
+}
+static void translate_polygon_ubyte2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i+2];
+ (out+j)[2] = (uint)in[0];
+ }
+}
+static void translate_points_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i+1];
+ (out+i)[1] = (uint)in[i];
+ }
+}
+static void translate_linestrip_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+}
+static void translate_lineloop_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i];
+}
+static void translate_tris_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i+2];
+ (out+i)[1] = (uint)in[i];
+ (out+i)[2] = (uint)in[i+1];
+ }
+}
+static void translate_tristrip_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+2];
+ (out+j)[1] = (uint)in[i+(i&1)];
+ (out+j)[2] = (uint)in[i+1-(i&1)];
+ }
+}
+static void translate_trifan_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+2];
+ (out+j)[1] = (uint)in[0];
+ (out+j)[2] = (uint)in[i+1];
+ }
+}
+static void translate_quads_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+3];
+ (out+j+0)[1] = (uint)in[i+0];
+ (out+j+0)[2] = (uint)in[i+1];
+ (out+j+3)[0] = (uint)in[i+3];
+ (out+j+3)[1] = (uint)in[i+1];
+ (out+j+3)[2] = (uint)in[i+2];
+ }
+}
+static void translate_quadstrip_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+3];
+ (out+j+0)[1] = (uint)in[i+2];
+ (out+j+0)[2] = (uint)in[i+0];
+ (out+j+3)[0] = (uint)in[i+3];
+ (out+j+3)[1] = (uint)in[i+0];
+ (out+j+3)[2] = (uint)in[i+1];
+ }
+}
+static void translate_polygon_ubyte2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_points_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ }
+}
+static void translate_linestrip_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+}
+static void translate_lineloop_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[0];
+}
+static void translate_tris_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ (out+i)[2] = (uint)in[i+2];
+ }
+}
+static void translate_tristrip_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+(i&1)];
+ (out+j)[1] = (uint)in[i+1-(i&1)];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_trifan_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_quads_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+0];
+ (out+j+0)[1] = (uint)in[i+1];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+1];
+ (out+j+3)[1] = (uint)in[i+2];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_quadstrip_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+2];
+ (out+j+0)[1] = (uint)in[i+0];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+0];
+ (out+j+3)[1] = (uint)in[i+1];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_polygon_ubyte2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i+2];
+ (out+j)[2] = (uint)in[0];
+ }
+}
+static void translate_points_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_linestrip_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_lineloop_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[0];
+}
+static void translate_tris_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ (out+i)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_tristrip_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1+(i&1)];
+ (out+j)[2] = (ushort)in[i+2-(i&1)];
+ }
+}
+static void translate_trifan_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_quads_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+0];
+ (out+j+0)[1] = (ushort)in[i+1];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+1];
+ (out+j+3)[1] = (ushort)in[i+2];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_quadstrip_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+2];
+ (out+j+0)[1] = (ushort)in[i+0];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+0];
+ (out+j+3)[1] = (ushort)in[i+1];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_polygon_ushort2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_points_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i+1];
+ (out+i)[1] = (ushort)in[i];
+ }
+}
+static void translate_linestrip_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+}
+static void translate_lineloop_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i];
+}
+static void translate_tris_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i+1];
+ (out+i)[1] = (ushort)in[i+2];
+ (out+i)[2] = (ushort)in[i];
+ }
+}
+static void translate_tristrip_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1+(i&1)];
+ (out+j)[1] = (ushort)in[i+2-(i&1)];
+ (out+j)[2] = (ushort)in[i];
+ }
+}
+static void translate_trifan_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i+2];
+ (out+j)[2] = (ushort)in[0];
+ }
+}
+static void translate_quads_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+1];
+ (out+j+0)[1] = (ushort)in[i+3];
+ (out+j+0)[2] = (ushort)in[i+0];
+ (out+j+3)[0] = (ushort)in[i+2];
+ (out+j+3)[1] = (ushort)in[i+3];
+ (out+j+3)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_quadstrip_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+0];
+ (out+j+0)[1] = (ushort)in[i+3];
+ (out+j+0)[2] = (ushort)in[i+2];
+ (out+j+3)[0] = (ushort)in[i+1];
+ (out+j+3)[1] = (ushort)in[i+3];
+ (out+j+3)[2] = (ushort)in[i+0];
+ }
+}
+static void translate_polygon_ushort2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i+2];
+ (out+j)[2] = (ushort)in[0];
+ }
+}
+static void translate_points_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i+1];
+ (out+i)[1] = (ushort)in[i];
+ }
+}
+static void translate_linestrip_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+}
+static void translate_lineloop_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i];
+}
+static void translate_tris_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i+2];
+ (out+i)[1] = (ushort)in[i];
+ (out+i)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_tristrip_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+2];
+ (out+j)[1] = (ushort)in[i+(i&1)];
+ (out+j)[2] = (ushort)in[i+1-(i&1)];
+ }
+}
+static void translate_trifan_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+2];
+ (out+j)[1] = (ushort)in[0];
+ (out+j)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_quads_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+3];
+ (out+j+0)[1] = (ushort)in[i+0];
+ (out+j+0)[2] = (ushort)in[i+1];
+ (out+j+3)[0] = (ushort)in[i+3];
+ (out+j+3)[1] = (ushort)in[i+1];
+ (out+j+3)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_quadstrip_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+3];
+ (out+j+0)[1] = (ushort)in[i+2];
+ (out+j+0)[2] = (ushort)in[i+0];
+ (out+j+3)[0] = (ushort)in[i+3];
+ (out+j+3)[1] = (ushort)in[i+0];
+ (out+j+3)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_polygon_ushort2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_points_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_linestrip_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_lineloop_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[0];
+}
+static void translate_tris_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ (out+i)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_tristrip_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+(i&1)];
+ (out+j)[1] = (ushort)in[i+1-(i&1)];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_trifan_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_quads_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+0];
+ (out+j+0)[1] = (ushort)in[i+1];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+1];
+ (out+j+3)[1] = (ushort)in[i+2];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_quadstrip_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+2];
+ (out+j+0)[1] = (ushort)in[i+0];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+0];
+ (out+j+3)[1] = (ushort)in[i+1];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_polygon_ushort2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i+2];
+ (out+j)[2] = (ushort)in[0];
+ }
+}
+static void translate_points_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ }
+}
+static void translate_linestrip_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+}
+static void translate_lineloop_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[0];
+}
+static void translate_tris_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ (out+i)[2] = (uint)in[i+2];
+ }
+}
+static void translate_tristrip_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1+(i&1)];
+ (out+j)[2] = (uint)in[i+2-(i&1)];
+ }
+}
+static void translate_trifan_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_quads_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+0];
+ (out+j+0)[1] = (uint)in[i+1];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+1];
+ (out+j+3)[1] = (uint)in[i+2];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_quadstrip_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+2];
+ (out+j+0)[1] = (uint)in[i+0];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+0];
+ (out+j+3)[1] = (uint)in[i+1];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_polygon_ushort2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_points_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i+1];
+ (out+i)[1] = (uint)in[i];
+ }
+}
+static void translate_linestrip_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+}
+static void translate_lineloop_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i];
+}
+static void translate_tris_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i+1];
+ (out+i)[1] = (uint)in[i+2];
+ (out+i)[2] = (uint)in[i];
+ }
+}
+static void translate_tristrip_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1+(i&1)];
+ (out+j)[1] = (uint)in[i+2-(i&1)];
+ (out+j)[2] = (uint)in[i];
+ }
+}
+static void translate_trifan_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i+2];
+ (out+j)[2] = (uint)in[0];
+ }
+}
+static void translate_quads_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+1];
+ (out+j+0)[1] = (uint)in[i+3];
+ (out+j+0)[2] = (uint)in[i+0];
+ (out+j+3)[0] = (uint)in[i+2];
+ (out+j+3)[1] = (uint)in[i+3];
+ (out+j+3)[2] = (uint)in[i+1];
+ }
+}
+static void translate_quadstrip_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+0];
+ (out+j+0)[1] = (uint)in[i+3];
+ (out+j+0)[2] = (uint)in[i+2];
+ (out+j+3)[0] = (uint)in[i+1];
+ (out+j+3)[1] = (uint)in[i+3];
+ (out+j+3)[2] = (uint)in[i+0];
+ }
+}
+static void translate_polygon_ushort2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i+2];
+ (out+j)[2] = (uint)in[0];
+ }
+}
+static void translate_points_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i+1];
+ (out+i)[1] = (uint)in[i];
+ }
+}
+static void translate_linestrip_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+}
+static void translate_lineloop_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i];
+}
+static void translate_tris_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i+2];
+ (out+i)[1] = (uint)in[i];
+ (out+i)[2] = (uint)in[i+1];
+ }
+}
+static void translate_tristrip_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+2];
+ (out+j)[1] = (uint)in[i+(i&1)];
+ (out+j)[2] = (uint)in[i+1-(i&1)];
+ }
+}
+static void translate_trifan_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+2];
+ (out+j)[1] = (uint)in[0];
+ (out+j)[2] = (uint)in[i+1];
+ }
+}
+static void translate_quads_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+3];
+ (out+j+0)[1] = (uint)in[i+0];
+ (out+j+0)[2] = (uint)in[i+1];
+ (out+j+3)[0] = (uint)in[i+3];
+ (out+j+3)[1] = (uint)in[i+1];
+ (out+j+3)[2] = (uint)in[i+2];
+ }
+}
+static void translate_quadstrip_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+3];
+ (out+j+0)[1] = (uint)in[i+2];
+ (out+j+0)[2] = (uint)in[i+0];
+ (out+j+3)[0] = (uint)in[i+3];
+ (out+j+3)[1] = (uint)in[i+0];
+ (out+j+3)[2] = (uint)in[i+1];
+ }
+}
+static void translate_polygon_ushort2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_points_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ }
+}
+static void translate_linestrip_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+}
+static void translate_lineloop_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[0];
+}
+static void translate_tris_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ (out+i)[2] = (uint)in[i+2];
+ }
+}
+static void translate_tristrip_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+(i&1)];
+ (out+j)[1] = (uint)in[i+1-(i&1)];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_trifan_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_quads_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+0];
+ (out+j+0)[1] = (uint)in[i+1];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+1];
+ (out+j+3)[1] = (uint)in[i+2];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_quadstrip_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+2];
+ (out+j+0)[1] = (uint)in[i+0];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+0];
+ (out+j+3)[1] = (uint)in[i+1];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_polygon_ushort2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i+2];
+ (out+j)[2] = (uint)in[0];
+ }
+}
+static void translate_points_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_linestrip_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_lineloop_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[0];
+}
+static void translate_tris_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ (out+i)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_tristrip_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1+(i&1)];
+ (out+j)[2] = (ushort)in[i+2-(i&1)];
+ }
+}
+static void translate_trifan_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_quads_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+0];
+ (out+j+0)[1] = (ushort)in[i+1];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+1];
+ (out+j+3)[1] = (ushort)in[i+2];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_quadstrip_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+2];
+ (out+j+0)[1] = (ushort)in[i+0];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+0];
+ (out+j+3)[1] = (ushort)in[i+1];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_polygon_uint2ushort_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_points_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i+1];
+ (out+i)[1] = (ushort)in[i];
+ }
+}
+static void translate_linestrip_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+}
+static void translate_lineloop_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i];
+}
+static void translate_tris_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i+1];
+ (out+i)[1] = (ushort)in[i+2];
+ (out+i)[2] = (ushort)in[i];
+ }
+}
+static void translate_tristrip_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1+(i&1)];
+ (out+j)[1] = (ushort)in[i+2-(i&1)];
+ (out+j)[2] = (ushort)in[i];
+ }
+}
+static void translate_trifan_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i+2];
+ (out+j)[2] = (ushort)in[0];
+ }
+}
+static void translate_quads_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+1];
+ (out+j+0)[1] = (ushort)in[i+3];
+ (out+j+0)[2] = (ushort)in[i+0];
+ (out+j+3)[0] = (ushort)in[i+2];
+ (out+j+3)[1] = (ushort)in[i+3];
+ (out+j+3)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_quadstrip_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+0];
+ (out+j+0)[1] = (ushort)in[i+3];
+ (out+j+0)[2] = (ushort)in[i+2];
+ (out+j+3)[0] = (ushort)in[i+1];
+ (out+j+3)[1] = (ushort)in[i+3];
+ (out+j+3)[2] = (ushort)in[i+0];
+ }
+}
+static void translate_polygon_uint2ushort_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i+2];
+ (out+j)[2] = (ushort)in[0];
+ }
+}
+static void translate_points_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i+1];
+ (out+i)[1] = (ushort)in[i];
+ }
+}
+static void translate_linestrip_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+}
+static void translate_lineloop_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i];
+ }
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i];
+}
+static void translate_tris_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i+2];
+ (out+i)[1] = (ushort)in[i];
+ (out+i)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_tristrip_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+2];
+ (out+j)[1] = (ushort)in[i+(i&1)];
+ (out+j)[2] = (ushort)in[i+1-(i&1)];
+ }
+}
+static void translate_trifan_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+2];
+ (out+j)[1] = (ushort)in[0];
+ (out+j)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_quads_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+3];
+ (out+j+0)[1] = (ushort)in[i+0];
+ (out+j+0)[2] = (ushort)in[i+1];
+ (out+j+3)[0] = (ushort)in[i+3];
+ (out+j+3)[1] = (ushort)in[i+1];
+ (out+j+3)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_quadstrip_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+3];
+ (out+j+0)[1] = (ushort)in[i+2];
+ (out+j+0)[2] = (ushort)in[i+0];
+ (out+j+3)[0] = (ushort)in[i+3];
+ (out+j+3)[1] = (ushort)in[i+0];
+ (out+j+3)[2] = (ushort)in[i+1];
+ }
+}
+static void translate_polygon_uint2ushort_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_points_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (ushort)in[i];
+ }
+}
+static void translate_lines_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_linestrip_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+}
+static void translate_lineloop_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ }
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[0];
+}
+static void translate_tris_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (ushort)in[i];
+ (out+i)[1] = (ushort)in[i+1];
+ (out+i)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_tristrip_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+(i&1)];
+ (out+j)[1] = (ushort)in[i+1-(i&1)];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_trifan_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j)[2] = (ushort)in[i+2];
+ }
+}
+static void translate_quads_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (ushort)in[i+0];
+ (out+j+0)[1] = (ushort)in[i+1];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+1];
+ (out+j+3)[1] = (ushort)in[i+2];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_quadstrip_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (ushort)in[i+2];
+ (out+j+0)[1] = (ushort)in[i+0];
+ (out+j+0)[2] = (ushort)in[i+3];
+ (out+j+3)[0] = (ushort)in[i+0];
+ (out+j+3)[1] = (ushort)in[i+1];
+ (out+j+3)[2] = (ushort)in[i+3];
+ }
+}
+static void translate_polygon_uint2ushort_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (ushort)in[i+1];
+ (out+j)[1] = (ushort)in[i+2];
+ (out+j)[2] = (ushort)in[0];
+ }
+}
+static void translate_points_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ }
+}
+static void translate_linestrip_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+}
+static void translate_lineloop_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[0];
+}
+static void translate_tris_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ (out+i)[2] = (uint)in[i+2];
+ }
+}
+static void translate_tristrip_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1+(i&1)];
+ (out+j)[2] = (uint)in[i+2-(i&1)];
+ }
+}
+static void translate_trifan_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_quads_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+0];
+ (out+j+0)[1] = (uint)in[i+1];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+1];
+ (out+j+3)[1] = (uint)in[i+2];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_quadstrip_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+2];
+ (out+j+0)[1] = (uint)in[i+0];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+0];
+ (out+j+3)[1] = (uint)in[i+1];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_polygon_uint2uint_first2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_points_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i+1];
+ (out+i)[1] = (uint)in[i];
+ }
+}
+static void translate_linestrip_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+}
+static void translate_lineloop_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i];
+}
+static void translate_tris_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i+1];
+ (out+i)[1] = (uint)in[i+2];
+ (out+i)[2] = (uint)in[i];
+ }
+}
+static void translate_tristrip_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1+(i&1)];
+ (out+j)[1] = (uint)in[i+2-(i&1)];
+ (out+j)[2] = (uint)in[i];
+ }
+}
+static void translate_trifan_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i+2];
+ (out+j)[2] = (uint)in[0];
+ }
+}
+static void translate_quads_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+1];
+ (out+j+0)[1] = (uint)in[i+3];
+ (out+j+0)[2] = (uint)in[i+0];
+ (out+j+3)[0] = (uint)in[i+2];
+ (out+j+3)[1] = (uint)in[i+3];
+ (out+j+3)[2] = (uint)in[i+1];
+ }
+}
+static void translate_quadstrip_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+0];
+ (out+j+0)[1] = (uint)in[i+3];
+ (out+j+0)[2] = (uint)in[i+2];
+ (out+j+3)[0] = (uint)in[i+1];
+ (out+j+3)[1] = (uint)in[i+3];
+ (out+j+3)[2] = (uint)in[i+0];
+ }
+}
+static void translate_polygon_uint2uint_first2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i+2];
+ (out+j)[2] = (uint)in[0];
+ }
+}
+static void translate_points_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i+1];
+ (out+i)[1] = (uint)in[i];
+ }
+}
+static void translate_linestrip_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+}
+static void translate_lineloop_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i];
+ }
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i];
+}
+static void translate_tris_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i+2];
+ (out+i)[1] = (uint)in[i];
+ (out+i)[2] = (uint)in[i+1];
+ }
+}
+static void translate_tristrip_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+2];
+ (out+j)[1] = (uint)in[i+(i&1)];
+ (out+j)[2] = (uint)in[i+1-(i&1)];
+ }
+}
+static void translate_trifan_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+2];
+ (out+j)[1] = (uint)in[0];
+ (out+j)[2] = (uint)in[i+1];
+ }
+}
+static void translate_quads_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+3];
+ (out+j+0)[1] = (uint)in[i+0];
+ (out+j+0)[2] = (uint)in[i+1];
+ (out+j+3)[0] = (uint)in[i+3];
+ (out+j+3)[1] = (uint)in[i+1];
+ (out+j+3)[2] = (uint)in[i+2];
+ }
+}
+static void translate_quadstrip_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+3];
+ (out+j+0)[1] = (uint)in[i+2];
+ (out+j+0)[2] = (uint)in[i+0];
+ (out+j+3)[0] = (uint)in[i+3];
+ (out+j+3)[1] = (uint)in[i+0];
+ (out+j+3)[2] = (uint)in[i+1];
+ }
+}
+static void translate_polygon_uint2uint_last2first(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_points_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i++) {
+ (out+i)[0] = (uint)in[i];
+ }
+}
+static void translate_lines_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=2) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ }
+}
+static void translate_linestrip_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+}
+static void translate_lineloop_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr - 2; j+=2, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ }
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[0];
+}
+static void translate_tris_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (i = 0; i < nr; i+=3) {
+ (out+i)[0] = (uint)in[i];
+ (out+i)[1] = (uint)in[i+1];
+ (out+i)[2] = (uint)in[i+2];
+ }
+}
+static void translate_tristrip_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+(i&1)];
+ (out+j)[1] = (uint)in[i+1-(i&1)];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_trifan_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j)[2] = (uint)in[i+2];
+ }
+}
+static void translate_quads_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=4) {
+ (out+j+0)[0] = (uint)in[i+0];
+ (out+j+0)[1] = (uint)in[i+1];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+1];
+ (out+j+3)[1] = (uint)in[i+2];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_quadstrip_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=2) {
+ (out+j+0)[0] = (uint)in[i+2];
+ (out+j+0)[1] = (uint)in[i+0];
+ (out+j+0)[2] = (uint)in[i+3];
+ (out+j+3)[0] = (uint)in[i+0];
+ (out+j+3)[1] = (uint)in[i+1];
+ (out+j+3)[2] = (uint)in[i+3];
+ }
+}
+static void translate_polygon_uint2uint_last2last(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=3, i++) {
+ (out+j)[0] = (uint)in[i+1];
+ (out+j)[1] = (uint)in[i+2];
+ (out+j)[2] = (uint)in[0];
+ }
+}
+void u_index_init( void )
+{
+ static int firsttime = 1;
+ if (!firsttime) return;
+ firsttime = 0;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_POINTS] = generate_points_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINES] = generate_lines_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = generate_linestrip_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = generate_lineloop_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLES] = generate_tris_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUADS] = generate_quads_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_POLYGON] = generate_polygon_ushort_first2first;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_POINTS] = generate_points_ushort_first2last;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINES] = generate_lines_ushort_first2last;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_STRIP] = generate_linestrip_ushort_first2last;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_LOOP] = generate_lineloop_ushort_first2last;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLES] = generate_tris_ushort_first2last;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_ushort_first2last;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_ushort_first2last;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_QUADS] = generate_quads_ushort_first2last;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_ushort_first2last;
+generate[OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_POLYGON] = generate_polygon_ushort_first2last;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_POINTS] = generate_points_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINES] = generate_lines_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = generate_linestrip_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = generate_lineloop_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLES] = generate_tris_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_QUADS] = generate_quads_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_POLYGON] = generate_polygon_ushort_last2first;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_POINTS] = generate_points_ushort_last2last;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINES] = generate_lines_ushort_last2last;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_STRIP] = generate_linestrip_ushort_last2last;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_LOOP] = generate_lineloop_ushort_last2last;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLES] = generate_tris_ushort_last2last;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_ushort_last2last;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_ushort_last2last;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_QUADS] = generate_quads_ushort_last2last;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_ushort_last2last;
+generate[OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_POLYGON] = generate_polygon_ushort_last2last;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_POINTS] = generate_points_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINES] = generate_lines_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = generate_linestrip_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = generate_lineloop_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLES] = generate_tris_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUADS] = generate_quads_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_POLYGON] = generate_polygon_uint_first2first;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_POINTS] = generate_points_uint_first2last;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINES] = generate_lines_uint_first2last;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_STRIP] = generate_linestrip_uint_first2last;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_LOOP] = generate_lineloop_uint_first2last;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLES] = generate_tris_uint_first2last;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_uint_first2last;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_uint_first2last;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_QUADS] = generate_quads_uint_first2last;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_uint_first2last;
+generate[OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_POLYGON] = generate_polygon_uint_first2last;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_POINTS] = generate_points_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINES] = generate_lines_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = generate_linestrip_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = generate_lineloop_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLES] = generate_tris_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_QUADS] = generate_quads_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_POLYGON] = generate_polygon_uint_last2first;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_POINTS] = generate_points_uint_last2last;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINES] = generate_lines_uint_last2last;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_STRIP] = generate_linestrip_uint_last2last;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_LOOP] = generate_lineloop_uint_last2last;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLES] = generate_tris_uint_last2last;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_uint_last2last;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_uint_last2last;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_QUADS] = generate_quads_uint_last2last;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_uint_last2last;
+generate[OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_POLYGON] = generate_polygon_uint_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2ushort_first2first;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2ushort_first2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2ushort_last2first;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2ushort_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2uint_first2first;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2uint_first2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2uint_last2first;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_ubyte2uint_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_ubyte2uint_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ubyte2uint_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ubyte2uint_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2uint_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2uint_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2uint_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_ubyte2uint_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2uint_last2last;
+translate[IN_UBYTE][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2uint_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_ushort2ushort_first2first;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_ushort2ushort_first2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_ushort2ushort_last2first;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_ushort2ushort_last2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_ushort2uint_first2first;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_ushort2uint_first2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_ushort2uint_last2first;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_ushort2uint_last2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_ushort2uint_last2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_ushort2uint_last2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_ushort2uint_last2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2uint_last2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2uint_last2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2uint_last2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_ushort2uint_last2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2uint_last2last;
+translate[IN_USHORT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_ushort2uint_last2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_uint2ushort_first2first;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_FIRST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_uint2ushort_first2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_uint2ushort_last2first;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_uint2ushort_last2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_uint2ushort_last2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_uint2ushort_last2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_uint2ushort_last2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_uint2ushort_last2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2ushort_last2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2ushort_last2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_uint2ushort_last2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2ushort_last2last;
+translate[IN_UINT][OUT_USHORT][PV_LAST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_uint2ushort_last2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_uint2uint_first2first;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_FIRST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_uint2uint_first2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_POINTS] = translate_points_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINES] = translate_lines_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLES] = translate_tris_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_QUADS] = translate_quads_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_FIRST][PIPE_PRIM_POLYGON] = translate_polygon_uint2uint_last2first;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_POINTS] = translate_points_uint2uint_last2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINES] = translate_lines_uint2uint_last2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_STRIP] = translate_linestrip_uint2uint_last2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_LINE_LOOP] = translate_lineloop_uint2uint_last2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLES] = translate_tris_uint2uint_last2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2uint_last2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2uint_last2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_QUADS] = translate_quads_uint2uint_last2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2uint_last2last;
+translate[IN_UINT][OUT_UINT][PV_LAST][PV_LAST][PIPE_PRIM_POLYGON] = translate_polygon_uint2uint_last2last;
+}
+#include "indices/u_indices.c"
diff --git a/src/gallium/auxiliary/indices/u_indices_gen.py b/src/gallium/auxiliary/indices/u_indices_gen.py
new file mode 100644
index 0000000000..af63d09930
--- /dev/null
+++ b/src/gallium/auxiliary/indices/u_indices_gen.py
@@ -0,0 +1,319 @@
+#!/usr/bin/env python
+copyright = '''
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+'''
+
+GENERATE, UBYTE, USHORT, UINT = 'generate', 'ubyte', 'ushort', 'uint'
+FIRST, LAST = 'first', 'last'
+
+INTYPES = (GENERATE, UBYTE, USHORT, UINT)
+OUTTYPES = (USHORT, UINT)
+PVS=(FIRST, LAST)
+PRIMS=('points',
+ 'lines',
+ 'linestrip',
+ 'lineloop',
+ 'tris',
+ 'trifan',
+ 'tristrip',
+ 'quads',
+ 'quadstrip',
+ 'polygon')
+
+LONGPRIMS=('PIPE_PRIM_POINTS',
+ 'PIPE_PRIM_LINES',
+ 'PIPE_PRIM_LINE_STRIP',
+ 'PIPE_PRIM_LINE_LOOP',
+ 'PIPE_PRIM_TRIANGLES',
+ 'PIPE_PRIM_TRIANGLE_FAN',
+ 'PIPE_PRIM_TRIANGLE_STRIP',
+ 'PIPE_PRIM_QUADS',
+ 'PIPE_PRIM_QUAD_STRIP',
+ 'PIPE_PRIM_POLYGON')
+
+longprim = dict(zip(PRIMS, LONGPRIMS))
+intype_idx = dict(ubyte='IN_UBYTE', ushort='IN_USHORT', uint='IN_UINT')
+outtype_idx = dict(ushort='OUT_USHORT', uint='OUT_UINT')
+pv_idx = dict(first='PV_FIRST', last='PV_LAST')
+
+
+def prolog():
+ print '''/* File automatically generated by indices.py */'''
+ print copyright
+ print r'''
+
+/**
+ * @file
+ * Functions to translate and generate index lists
+ */
+
+#include "indices/u_indices.h"
+#include "indices/u_indices_priv.h"
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+
+
+static unsigned out_size_idx( unsigned index_size )
+{
+ switch (index_size) {
+ case 4: return OUT_UINT;
+ case 2: return OUT_USHORT;
+ default: assert(0); return OUT_USHORT;
+ }
+}
+
+static unsigned in_size_idx( unsigned index_size )
+{
+ switch (index_size) {
+ case 4: return IN_UINT;
+ case 2: return IN_USHORT;
+ case 1: return IN_UBYTE;
+ default: assert(0); return IN_UBYTE;
+ }
+}
+
+
+static u_translate_func translate[IN_COUNT][OUT_COUNT][PV_COUNT][PV_COUNT][PRIM_COUNT];
+static u_generate_func generate[OUT_COUNT][PV_COUNT][PV_COUNT][PRIM_COUNT];
+
+
+'''
+
+def vert( intype, outtype, v0 ):
+ if intype == GENERATE:
+ return '(' + outtype + ')(' + v0 + ')'
+ else:
+ return '(' + outtype + ')in[' + v0 + ']'
+
+def point( intype, outtype, ptr, v0 ):
+ print ' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';'
+
+def line( intype, outtype, ptr, v0, v1 ):
+ print ' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';'
+ print ' (' + ptr + ')[1] = ' + vert( intype, outtype, v1 ) + ';'
+
+def tri( intype, outtype, ptr, v0, v1, v2 ):
+ print ' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';'
+ print ' (' + ptr + ')[1] = ' + vert( intype, outtype, v1 ) + ';'
+ print ' (' + ptr + ')[2] = ' + vert( intype, outtype, v2 ) + ';'
+
+def do_point( intype, outtype, ptr, v0 ):
+ point( intype, outtype, ptr, v0 )
+
+def do_line( intype, outtype, ptr, v0, v1, inpv, outpv ):
+ if inpv == outpv:
+ line( intype, outtype, ptr, v0, v1 )
+ else:
+ line( intype, outtype, ptr, v1, v0 )
+
+def do_tri( intype, outtype, ptr, v0, v1, v2, inpv, outpv ):
+ if inpv == outpv:
+ tri( intype, outtype, ptr, v0, v1, v2 )
+ else:
+ if inpv == FIRST:
+ tri( intype, outtype, ptr, v1, v2, v0 )
+ else:
+ tri( intype, outtype, ptr, v2, v0, v1 )
+
+def do_quad( intype, outtype, ptr, v0, v1, v2, v3, inpv, outpv ):
+ do_tri( intype, outtype, ptr+'+0', v0, v1, v3, inpv, outpv );
+ do_tri( intype, outtype, ptr+'+3', v1, v2, v3, inpv, outpv );
+
+def name(intype, outtype, inpv, outpv, prim):
+ if intype == GENERATE:
+ return 'generate_' + prim + '_' + outtype + '_' + inpv + '2' + outpv
+ else:
+ return 'translate_' + prim + '_' + intype + '2' + outtype + '_' + inpv + '2' + outpv
+
+def preamble(intype, outtype, inpv, outpv, prim):
+ print 'static void ' + name( intype, outtype, inpv, outpv, prim ) + '('
+ if intype != GENERATE:
+ print ' const void * _in,'
+ print ' unsigned nr,'
+ print ' void *_out )'
+ print '{'
+ if intype != GENERATE:
+ print ' const ' + intype + '*in = (const ' + intype + '*)_in;'
+ print ' ' + outtype + ' *out = (' + outtype + '*)_out;'
+ print ' unsigned i, j;'
+ print ' (void)j;'
+
+def postamble():
+ print '}'
+
+
+def points(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='points')
+ print ' for (i = 0; i < nr; i++) { '
+ do_point( intype, outtype, 'out+i', 'i' );
+ print ' }'
+ postamble()
+
+def lines(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='lines')
+ print ' for (i = 0; i < nr; i+=2) { '
+ do_line( intype, outtype, 'out+i', 'i', 'i+1', inpv, outpv );
+ print ' }'
+ postamble()
+
+def linestrip(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='linestrip')
+ print ' for (j = i = 0; j < nr; j+=2, i++) { '
+ do_line( intype, outtype, 'out+j', 'i', 'i+1', inpv, outpv );
+ print ' }'
+ postamble()
+
+def lineloop(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='lineloop')
+ print ' for (j = i = 0; j < nr - 2; j+=2, i++) { '
+ do_line( intype, outtype, 'out+j', 'i', 'i+1', inpv, outpv );
+ print ' }'
+ do_line( intype, outtype, 'out+j', 'i', '0', inpv, outpv );
+ postamble()
+
+def tris(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='tris')
+ print ' for (i = 0; i < nr; i+=3) { '
+ do_tri( intype, outtype, 'out+i', 'i', 'i+1', 'i+2', inpv, outpv );
+ print ' }'
+ postamble()
+
+
+def tristrip(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='tristrip')
+ print ' for (j = i = 0; j < nr; j+=3, i++) { '
+ if inpv == FIRST:
+ do_tri( intype, outtype, 'out+j', 'i', 'i+1+(i&1)', 'i+2-(i&1)', inpv, outpv );
+ else:
+ do_tri( intype, outtype, 'out+j', 'i+(i&1)', 'i+1-(i&1)', 'i+2', inpv, outpv );
+ print ' }'
+ postamble()
+
+
+def trifan(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='trifan')
+ print ' for (j = i = 0; j < nr; j+=3, i++) { '
+ do_tri( intype, outtype, 'out+j', '0', 'i+1', 'i+2', inpv, outpv );
+ print ' }'
+ postamble()
+
+
+
+def polygon(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='polygon')
+ print ' for (j = i = 0; j < nr; j+=3, i++) { '
+ if inpv == FIRST:
+ do_tri( intype, outtype, 'out+j', '0', 'i+1', 'i+2', inpv, outpv );
+ else:
+ do_tri( intype, outtype, 'out+j', 'i+1', 'i+2', '0', inpv, outpv );
+ print ' }'
+ postamble()
+
+
+def quads(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='quads')
+ print ' for (j = i = 0; j < nr; j+=6, i+=4) { '
+ do_quad( intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv );
+ print ' }'
+ postamble()
+
+
+def quadstrip(intype, outtype, inpv, outpv):
+ preamble(intype, outtype, inpv, outpv, prim='quadstrip')
+ print ' for (j = i = 0; j < nr; j+=6, i+=2) { '
+ do_quad( intype, outtype, 'out+j', 'i+2', 'i+0', 'i+1', 'i+3', inpv, outpv );
+ print ' }'
+ postamble()
+
+
+def emit_funcs():
+ for intype in INTYPES:
+ for outtype in OUTTYPES:
+ for inpv in (FIRST, LAST):
+ for outpv in (FIRST, LAST):
+ points(intype, outtype, inpv, outpv)
+ lines(intype, outtype, inpv, outpv)
+ linestrip(intype, outtype, inpv, outpv)
+ lineloop(intype, outtype, inpv, outpv)
+ tris(intype, outtype, inpv, outpv)
+ tristrip(intype, outtype, inpv, outpv)
+ trifan(intype, outtype, inpv, outpv)
+ quads(intype, outtype, inpv, outpv)
+ quadstrip(intype, outtype, inpv, outpv)
+ polygon(intype, outtype, inpv, outpv)
+
+def init(intype, outtype, inpv, outpv, prim):
+ if intype == GENERATE:
+ print ('generate[' +
+ outtype_idx[outtype] +
+ '][' + pv_idx[inpv] +
+ '][' + pv_idx[outpv] +
+ '][' + longprim[prim] +
+ '] = ' + name( intype, outtype, inpv, outpv, prim ) + ';')
+ else:
+ print ('translate[' +
+ intype_idx[intype] +
+ '][' + outtype_idx[outtype] +
+ '][' + pv_idx[inpv] +
+ '][' + pv_idx[outpv] +
+ '][' + longprim[prim] +
+ '] = ' + name( intype, outtype, inpv, outpv, prim ) + ';')
+
+
+def emit_all_inits():
+ for intype in INTYPES:
+ for outtype in OUTTYPES:
+ for inpv in PVS:
+ for outpv in PVS:
+ for prim in PRIMS:
+ init(intype, outtype, inpv, outpv, prim)
+
+def emit_init():
+ print 'void u_index_init( void )'
+ print '{'
+ print ' static int firsttime = 1;'
+ print ' if (!firsttime) return;'
+ print ' firsttime = 0;'
+ emit_all_inits()
+ print '}'
+
+
+
+
+def epilog():
+ print '#include "indices/u_indices.c"'
+
+
+def main():
+ prolog()
+ emit_funcs()
+ emit_init()
+ epilog()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/auxiliary/indices/u_indices_priv.h b/src/gallium/auxiliary/indices/u_indices_priv.h
new file mode 100644
index 0000000000..9c3298c24d
--- /dev/null
+++ b/src/gallium/auxiliary/indices/u_indices_priv.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef U_INDICES_PRIV_H
+#define U_INDICES_PRIV_H
+
+#include "pipe/p_compiler.h"
+#include "u_indices.h"
+
+#define IN_UBYTE 0
+#define IN_USHORT 1
+#define IN_UINT 2
+#define IN_COUNT 3
+
+#define OUT_USHORT 0
+#define OUT_UINT 1
+#define OUT_COUNT 2
+
+
+#define PRIM_COUNT (PIPE_PRIM_POLYGON + 1)
+
+#endif
diff --git a/src/gallium/auxiliary/indices/u_unfilled_gen.c b/src/gallium/auxiliary/indices/u_unfilled_gen.c
new file mode 100644
index 0000000000..93897c98de
--- /dev/null
+++ b/src/gallium/auxiliary/indices/u_unfilled_gen.c
@@ -0,0 +1,992 @@
+/* File automatically generated by u_unfilled_gen.py */
+
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+
+
+/**
+ * @file
+ * Functions to translate and generate index lists
+ */
+
+#include "indices/u_indices.h"
+#include "indices/u_indices_priv.h"
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+
+
+static unsigned out_size_idx( unsigned index_size )
+{
+ switch (index_size) {
+ case 4: return OUT_UINT;
+ case 2: return OUT_USHORT;
+ default: assert(0); return OUT_USHORT;
+ }
+}
+
+static unsigned in_size_idx( unsigned index_size )
+{
+ switch (index_size) {
+ case 4: return IN_UINT;
+ case 2: return IN_USHORT;
+ case 1: return IN_UBYTE;
+ default: assert(0); return IN_UBYTE;
+ }
+}
+
+
+static u_generate_func generate_line[OUT_COUNT][PRIM_COUNT];
+static u_translate_func translate_line[IN_COUNT][OUT_COUNT][PRIM_COUNT];
+
+
+static void generate_tris_ushort(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=3) {
+ (out+j)[0] = (ushort)(i);
+ (out+j)[1] = (ushort)(i+1);
+ (out+j+2)[0] = (ushort)(i+1);
+ (out+j+2)[1] = (ushort)(i+2);
+ (out+j+4)[0] = (ushort)(i+2);
+ (out+j+4)[1] = (ushort)(i);
+ }
+}
+static void generate_tristrip_ushort(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)(i);
+ (out+j)[1] = (ushort)(i+1/*+(i&1)*/);
+ (out+j+2)[0] = (ushort)(i+1/*+(i&1)*/);
+ (out+j+2)[1] = (ushort)(i+2/*-(i&1)*/);
+ (out+j+4)[0] = (ushort)(i+2/*-(i&1)*/);
+ (out+j+4)[1] = (ushort)(i);
+ }
+}
+static void generate_trifan_ushort(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)(0);
+ (out+j)[1] = (ushort)(i+1);
+ (out+j+2)[0] = (ushort)(i+1);
+ (out+j+2)[1] = (ushort)(i+2);
+ (out+j+4)[0] = (ushort)(i+2);
+ (out+j+4)[1] = (ushort)(0);
+ }
+}
+static void generate_quads_ushort(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=4) {
+ (out+j)[0] = (ushort)(i+0);
+ (out+j)[1] = (ushort)(i+1);
+ (out+j+2)[0] = (ushort)(i+1);
+ (out+j+2)[1] = (ushort)(i+2);
+ (out+j+4)[0] = (ushort)(i+2);
+ (out+j+4)[1] = (ushort)(i+3);
+ (out+j+6)[0] = (ushort)(i+3);
+ (out+j+6)[1] = (ushort)(i+0);
+ }
+}
+static void generate_quadstrip_ushort(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=2) {
+ (out+j)[0] = (ushort)(i+2);
+ (out+j)[1] = (ushort)(i+0);
+ (out+j+2)[0] = (ushort)(i+0);
+ (out+j+2)[1] = (ushort)(i+1);
+ (out+j+4)[0] = (ushort)(i+1);
+ (out+j+4)[1] = (ushort)(i+3);
+ (out+j+6)[0] = (ushort)(i+3);
+ (out+j+6)[1] = (ushort)(i+2);
+ }
+}
+static void generate_polygon_ushort(
+ unsigned nr,
+ void *_out )
+{
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)(0);
+ (out+j)[1] = (ushort)(i+1);
+ (out+j+2)[0] = (ushort)(i+1);
+ (out+j+2)[1] = (ushort)(i+2);
+ (out+j+4)[0] = (ushort)(i+2);
+ (out+j+4)[1] = (ushort)(0);
+ }
+}
+static void generate_tris_uint(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=3) {
+ (out+j)[0] = (uint)(i);
+ (out+j)[1] = (uint)(i+1);
+ (out+j+2)[0] = (uint)(i+1);
+ (out+j+2)[1] = (uint)(i+2);
+ (out+j+4)[0] = (uint)(i+2);
+ (out+j+4)[1] = (uint)(i);
+ }
+}
+static void generate_tristrip_uint(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)(i);
+ (out+j)[1] = (uint)(i+1/*+(i&1)*/);
+ (out+j+2)[0] = (uint)(i+1/*+(i&1)*/);
+ (out+j+2)[1] = (uint)(i+2/*-(i&1)*/);
+ (out+j+4)[0] = (uint)(i+2/*-(i&1)*/);
+ (out+j+4)[1] = (uint)(i);
+ }
+}
+static void generate_trifan_uint(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)(0);
+ (out+j)[1] = (uint)(i+1);
+ (out+j+2)[0] = (uint)(i+1);
+ (out+j+2)[1] = (uint)(i+2);
+ (out+j+4)[0] = (uint)(i+2);
+ (out+j+4)[1] = (uint)(0);
+ }
+}
+static void generate_quads_uint(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=4) {
+ (out+j)[0] = (uint)(i+0);
+ (out+j)[1] = (uint)(i+1);
+ (out+j+2)[0] = (uint)(i+1);
+ (out+j+2)[1] = (uint)(i+2);
+ (out+j+4)[0] = (uint)(i+2);
+ (out+j+4)[1] = (uint)(i+3);
+ (out+j+6)[0] = (uint)(i+3);
+ (out+j+6)[1] = (uint)(i+0);
+ }
+}
+static void generate_quadstrip_uint(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=2) {
+ (out+j)[0] = (uint)(i+2);
+ (out+j)[1] = (uint)(i+0);
+ (out+j+2)[0] = (uint)(i+0);
+ (out+j+2)[1] = (uint)(i+1);
+ (out+j+4)[0] = (uint)(i+1);
+ (out+j+4)[1] = (uint)(i+3);
+ (out+j+6)[0] = (uint)(i+3);
+ (out+j+6)[1] = (uint)(i+2);
+ }
+}
+static void generate_polygon_uint(
+ unsigned nr,
+ void *_out )
+{
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)(0);
+ (out+j)[1] = (uint)(i+1);
+ (out+j+2)[0] = (uint)(i+1);
+ (out+j+2)[1] = (uint)(i+2);
+ (out+j+4)[0] = (uint)(i+2);
+ (out+j+4)[1] = (uint)(0);
+ }
+}
+static void translate_tris_ubyte2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=3) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[i];
+ }
+}
+static void translate_tristrip_ubyte2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1/*+(i&1)*/];
+ (out+j+2)[0] = (ushort)in[i+1/*+(i&1)*/];
+ (out+j+2)[1] = (ushort)in[i+2/*-(i&1)*/];
+ (out+j+4)[0] = (ushort)in[i+2/*-(i&1)*/];
+ (out+j+4)[1] = (ushort)in[i];
+ }
+}
+static void translate_trifan_ubyte2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[0];
+ }
+}
+static void translate_quads_ubyte2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=4) {
+ (out+j)[0] = (ushort)in[i+0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[i+3];
+ (out+j+6)[0] = (ushort)in[i+3];
+ (out+j+6)[1] = (ushort)in[i+0];
+ }
+}
+static void translate_quadstrip_ubyte2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=2) {
+ (out+j)[0] = (ushort)in[i+2];
+ (out+j)[1] = (ushort)in[i+0];
+ (out+j+2)[0] = (ushort)in[i+0];
+ (out+j+2)[1] = (ushort)in[i+1];
+ (out+j+4)[0] = (ushort)in[i+1];
+ (out+j+4)[1] = (ushort)in[i+3];
+ (out+j+6)[0] = (ushort)in[i+3];
+ (out+j+6)[1] = (ushort)in[i+2];
+ }
+}
+static void translate_polygon_ubyte2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[0];
+ }
+}
+static void translate_tris_ubyte2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=3) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[i];
+ }
+}
+static void translate_tristrip_ubyte2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1/*+(i&1)*/];
+ (out+j+2)[0] = (uint)in[i+1/*+(i&1)*/];
+ (out+j+2)[1] = (uint)in[i+2/*-(i&1)*/];
+ (out+j+4)[0] = (uint)in[i+2/*-(i&1)*/];
+ (out+j+4)[1] = (uint)in[i];
+ }
+}
+static void translate_trifan_ubyte2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[0];
+ }
+}
+static void translate_quads_ubyte2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=4) {
+ (out+j)[0] = (uint)in[i+0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[i+3];
+ (out+j+6)[0] = (uint)in[i+3];
+ (out+j+6)[1] = (uint)in[i+0];
+ }
+}
+static void translate_quadstrip_ubyte2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=2) {
+ (out+j)[0] = (uint)in[i+2];
+ (out+j)[1] = (uint)in[i+0];
+ (out+j+2)[0] = (uint)in[i+0];
+ (out+j+2)[1] = (uint)in[i+1];
+ (out+j+4)[0] = (uint)in[i+1];
+ (out+j+4)[1] = (uint)in[i+3];
+ (out+j+6)[0] = (uint)in[i+3];
+ (out+j+6)[1] = (uint)in[i+2];
+ }
+}
+static void translate_polygon_ubyte2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ubyte*in = (const ubyte*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[0];
+ }
+}
+static void translate_tris_ushort2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=3) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[i];
+ }
+}
+static void translate_tristrip_ushort2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1/*+(i&1)*/];
+ (out+j+2)[0] = (ushort)in[i+1/*+(i&1)*/];
+ (out+j+2)[1] = (ushort)in[i+2/*-(i&1)*/];
+ (out+j+4)[0] = (ushort)in[i+2/*-(i&1)*/];
+ (out+j+4)[1] = (ushort)in[i];
+ }
+}
+static void translate_trifan_ushort2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[0];
+ }
+}
+static void translate_quads_ushort2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=4) {
+ (out+j)[0] = (ushort)in[i+0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[i+3];
+ (out+j+6)[0] = (ushort)in[i+3];
+ (out+j+6)[1] = (ushort)in[i+0];
+ }
+}
+static void translate_quadstrip_ushort2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=2) {
+ (out+j)[0] = (ushort)in[i+2];
+ (out+j)[1] = (ushort)in[i+0];
+ (out+j+2)[0] = (ushort)in[i+0];
+ (out+j+2)[1] = (ushort)in[i+1];
+ (out+j+4)[0] = (ushort)in[i+1];
+ (out+j+4)[1] = (ushort)in[i+3];
+ (out+j+6)[0] = (ushort)in[i+3];
+ (out+j+6)[1] = (ushort)in[i+2];
+ }
+}
+static void translate_polygon_ushort2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[0];
+ }
+}
+static void translate_tris_ushort2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=3) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[i];
+ }
+}
+static void translate_tristrip_ushort2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1/*+(i&1)*/];
+ (out+j+2)[0] = (uint)in[i+1/*+(i&1)*/];
+ (out+j+2)[1] = (uint)in[i+2/*-(i&1)*/];
+ (out+j+4)[0] = (uint)in[i+2/*-(i&1)*/];
+ (out+j+4)[1] = (uint)in[i];
+ }
+}
+static void translate_trifan_ushort2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[0];
+ }
+}
+static void translate_quads_ushort2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=4) {
+ (out+j)[0] = (uint)in[i+0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[i+3];
+ (out+j+6)[0] = (uint)in[i+3];
+ (out+j+6)[1] = (uint)in[i+0];
+ }
+}
+static void translate_quadstrip_ushort2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=2) {
+ (out+j)[0] = (uint)in[i+2];
+ (out+j)[1] = (uint)in[i+0];
+ (out+j+2)[0] = (uint)in[i+0];
+ (out+j+2)[1] = (uint)in[i+1];
+ (out+j+4)[0] = (uint)in[i+1];
+ (out+j+4)[1] = (uint)in[i+3];
+ (out+j+6)[0] = (uint)in[i+3];
+ (out+j+6)[1] = (uint)in[i+2];
+ }
+}
+static void translate_polygon_ushort2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const ushort*in = (const ushort*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[0];
+ }
+}
+static void translate_tris_uint2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=3) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[i];
+ }
+}
+static void translate_tristrip_uint2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)in[i];
+ (out+j)[1] = (ushort)in[i+1/*+(i&1)*/];
+ (out+j+2)[0] = (ushort)in[i+1/*+(i&1)*/];
+ (out+j+2)[1] = (ushort)in[i+2/*-(i&1)*/];
+ (out+j+4)[0] = (ushort)in[i+2/*-(i&1)*/];
+ (out+j+4)[1] = (ushort)in[i];
+ }
+}
+static void translate_trifan_uint2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[0];
+ }
+}
+static void translate_quads_uint2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=4) {
+ (out+j)[0] = (ushort)in[i+0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[i+3];
+ (out+j+6)[0] = (ushort)in[i+3];
+ (out+j+6)[1] = (ushort)in[i+0];
+ }
+}
+static void translate_quadstrip_uint2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=2) {
+ (out+j)[0] = (ushort)in[i+2];
+ (out+j)[1] = (ushort)in[i+0];
+ (out+j+2)[0] = (ushort)in[i+0];
+ (out+j+2)[1] = (ushort)in[i+1];
+ (out+j+4)[0] = (ushort)in[i+1];
+ (out+j+4)[1] = (ushort)in[i+3];
+ (out+j+6)[0] = (ushort)in[i+3];
+ (out+j+6)[1] = (ushort)in[i+2];
+ }
+}
+static void translate_polygon_uint2ushort(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ ushort *out = (ushort*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (ushort)in[0];
+ (out+j)[1] = (ushort)in[i+1];
+ (out+j+2)[0] = (ushort)in[i+1];
+ (out+j+2)[1] = (ushort)in[i+2];
+ (out+j+4)[0] = (ushort)in[i+2];
+ (out+j+4)[1] = (ushort)in[0];
+ }
+}
+static void translate_tris_uint2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i+=3) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[i];
+ }
+}
+static void translate_tristrip_uint2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)in[i];
+ (out+j)[1] = (uint)in[i+1/*+(i&1)*/];
+ (out+j+2)[0] = (uint)in[i+1/*+(i&1)*/];
+ (out+j+2)[1] = (uint)in[i+2/*-(i&1)*/];
+ (out+j+4)[0] = (uint)in[i+2/*-(i&1)*/];
+ (out+j+4)[1] = (uint)in[i];
+ }
+}
+static void translate_trifan_uint2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[0];
+ }
+}
+static void translate_quads_uint2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=4) {
+ (out+j)[0] = (uint)in[i+0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[i+3];
+ (out+j+6)[0] = (uint)in[i+3];
+ (out+j+6)[1] = (uint)in[i+0];
+ }
+}
+static void translate_quadstrip_uint2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=8, i+=2) {
+ (out+j)[0] = (uint)in[i+2];
+ (out+j)[1] = (uint)in[i+0];
+ (out+j+2)[0] = (uint)in[i+0];
+ (out+j+2)[1] = (uint)in[i+1];
+ (out+j+4)[0] = (uint)in[i+1];
+ (out+j+4)[1] = (uint)in[i+3];
+ (out+j+6)[0] = (uint)in[i+3];
+ (out+j+6)[1] = (uint)in[i+2];
+ }
+}
+static void translate_polygon_uint2uint(
+ const void * _in,
+ unsigned nr,
+ void *_out )
+{
+ const uint*in = (const uint*)_in;
+ uint *out = (uint*)_out;
+ unsigned i, j;
+ (void)j;
+ for (j = i = 0; j < nr; j+=6, i++) {
+ (out+j)[0] = (uint)in[0];
+ (out+j)[1] = (uint)in[i+1];
+ (out+j+2)[0] = (uint)in[i+1];
+ (out+j+2)[1] = (uint)in[i+2];
+ (out+j+4)[0] = (uint)in[i+2];
+ (out+j+4)[1] = (uint)in[0];
+ }
+}
+void u_unfilled_init( void )
+{
+ static int firsttime = 1;
+ if (!firsttime) return;
+ firsttime = 0;
+generate_line[OUT_USHORT][PIPE_PRIM_TRIANGLES] = generate_tris_ushort;
+generate_line[OUT_USHORT][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_ushort;
+generate_line[OUT_USHORT][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_ushort;
+generate_line[OUT_USHORT][PIPE_PRIM_QUADS] = generate_quads_ushort;
+generate_line[OUT_USHORT][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_ushort;
+generate_line[OUT_USHORT][PIPE_PRIM_POLYGON] = generate_polygon_ushort;
+generate_line[OUT_UINT][PIPE_PRIM_TRIANGLES] = generate_tris_uint;
+generate_line[OUT_UINT][PIPE_PRIM_TRIANGLE_FAN] = generate_trifan_uint;
+generate_line[OUT_UINT][PIPE_PRIM_TRIANGLE_STRIP] = generate_tristrip_uint;
+generate_line[OUT_UINT][PIPE_PRIM_QUADS] = generate_quads_uint;
+generate_line[OUT_UINT][PIPE_PRIM_QUAD_STRIP] = generate_quadstrip_uint;
+generate_line[OUT_UINT][PIPE_PRIM_POLYGON] = generate_polygon_uint;
+translate_line[IN_UBYTE][OUT_USHORT][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2ushort;
+translate_line[IN_UBYTE][OUT_USHORT][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2ushort;
+translate_line[IN_UBYTE][OUT_USHORT][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2ushort;
+translate_line[IN_UBYTE][OUT_USHORT][PIPE_PRIM_QUADS] = translate_quads_ubyte2ushort;
+translate_line[IN_UBYTE][OUT_USHORT][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2ushort;
+translate_line[IN_UBYTE][OUT_USHORT][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2ushort;
+translate_line[IN_UBYTE][OUT_UINT][PIPE_PRIM_TRIANGLES] = translate_tris_ubyte2uint;
+translate_line[IN_UBYTE][OUT_UINT][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ubyte2uint;
+translate_line[IN_UBYTE][OUT_UINT][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ubyte2uint;
+translate_line[IN_UBYTE][OUT_UINT][PIPE_PRIM_QUADS] = translate_quads_ubyte2uint;
+translate_line[IN_UBYTE][OUT_UINT][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ubyte2uint;
+translate_line[IN_UBYTE][OUT_UINT][PIPE_PRIM_POLYGON] = translate_polygon_ubyte2uint;
+translate_line[IN_USHORT][OUT_USHORT][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2ushort;
+translate_line[IN_USHORT][OUT_USHORT][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2ushort;
+translate_line[IN_USHORT][OUT_USHORT][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2ushort;
+translate_line[IN_USHORT][OUT_USHORT][PIPE_PRIM_QUADS] = translate_quads_ushort2ushort;
+translate_line[IN_USHORT][OUT_USHORT][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2ushort;
+translate_line[IN_USHORT][OUT_USHORT][PIPE_PRIM_POLYGON] = translate_polygon_ushort2ushort;
+translate_line[IN_USHORT][OUT_UINT][PIPE_PRIM_TRIANGLES] = translate_tris_ushort2uint;
+translate_line[IN_USHORT][OUT_UINT][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_ushort2uint;
+translate_line[IN_USHORT][OUT_UINT][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_ushort2uint;
+translate_line[IN_USHORT][OUT_UINT][PIPE_PRIM_QUADS] = translate_quads_ushort2uint;
+translate_line[IN_USHORT][OUT_UINT][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_ushort2uint;
+translate_line[IN_USHORT][OUT_UINT][PIPE_PRIM_POLYGON] = translate_polygon_ushort2uint;
+translate_line[IN_UINT][OUT_USHORT][PIPE_PRIM_TRIANGLES] = translate_tris_uint2ushort;
+translate_line[IN_UINT][OUT_USHORT][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2ushort;
+translate_line[IN_UINT][OUT_USHORT][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2ushort;
+translate_line[IN_UINT][OUT_USHORT][PIPE_PRIM_QUADS] = translate_quads_uint2ushort;
+translate_line[IN_UINT][OUT_USHORT][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2ushort;
+translate_line[IN_UINT][OUT_USHORT][PIPE_PRIM_POLYGON] = translate_polygon_uint2ushort;
+translate_line[IN_UINT][OUT_UINT][PIPE_PRIM_TRIANGLES] = translate_tris_uint2uint;
+translate_line[IN_UINT][OUT_UINT][PIPE_PRIM_TRIANGLE_FAN] = translate_trifan_uint2uint;
+translate_line[IN_UINT][OUT_UINT][PIPE_PRIM_TRIANGLE_STRIP] = translate_tristrip_uint2uint;
+translate_line[IN_UINT][OUT_UINT][PIPE_PRIM_QUADS] = translate_quads_uint2uint;
+translate_line[IN_UINT][OUT_UINT][PIPE_PRIM_QUAD_STRIP] = translate_quadstrip_uint2uint;
+translate_line[IN_UINT][OUT_UINT][PIPE_PRIM_POLYGON] = translate_polygon_uint2uint;
+}
+#include "indices/u_unfilled_indices.c"
diff --git a/src/gallium/auxiliary/indices/u_unfilled_gen.py b/src/gallium/auxiliary/indices/u_unfilled_gen.py
new file mode 100644
index 0000000000..36896ce605
--- /dev/null
+++ b/src/gallium/auxiliary/indices/u_unfilled_gen.py
@@ -0,0 +1,246 @@
+#!/usr/bin/env python
+copyright = '''
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+'''
+
+GENERATE, UBYTE, USHORT, UINT = 'generate', 'ubyte', 'ushort', 'uint'
+FIRST, LAST = 'first', 'last'
+
+INTYPES = (GENERATE, UBYTE, USHORT, UINT)
+OUTTYPES = (USHORT, UINT)
+PRIMS=('tris',
+ 'trifan',
+ 'tristrip',
+ 'quads',
+ 'quadstrip',
+ 'polygon')
+
+LONGPRIMS=('PIPE_PRIM_TRIANGLES',
+ 'PIPE_PRIM_TRIANGLE_FAN',
+ 'PIPE_PRIM_TRIANGLE_STRIP',
+ 'PIPE_PRIM_QUADS',
+ 'PIPE_PRIM_QUAD_STRIP',
+ 'PIPE_PRIM_POLYGON')
+
+longprim = dict(zip(PRIMS, LONGPRIMS))
+intype_idx = dict(ubyte='IN_UBYTE', ushort='IN_USHORT', uint='IN_UINT')
+outtype_idx = dict(ushort='OUT_USHORT', uint='OUT_UINT')
+
+
+def prolog():
+ print '''/* File automatically generated by u_unfilled_gen.py */'''
+ print copyright
+ print r'''
+
+/**
+ * @file
+ * Functions to translate and generate index lists
+ */
+
+#include "indices/u_indices.h"
+#include "indices/u_indices_priv.h"
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+
+
+static unsigned out_size_idx( unsigned index_size )
+{
+ switch (index_size) {
+ case 4: return OUT_UINT;
+ case 2: return OUT_USHORT;
+ default: assert(0); return OUT_USHORT;
+ }
+}
+
+static unsigned in_size_idx( unsigned index_size )
+{
+ switch (index_size) {
+ case 4: return IN_UINT;
+ case 2: return IN_USHORT;
+ case 1: return IN_UBYTE;
+ default: assert(0); return IN_UBYTE;
+ }
+}
+
+
+static u_generate_func generate_line[OUT_COUNT][PRIM_COUNT];
+static u_translate_func translate_line[IN_COUNT][OUT_COUNT][PRIM_COUNT];
+
+'''
+
+def vert( intype, outtype, v0 ):
+ if intype == GENERATE:
+ return '(' + outtype + ')(' + v0 + ')'
+ else:
+ return '(' + outtype + ')in[' + v0 + ']'
+
+def line( intype, outtype, ptr, v0, v1 ):
+ print ' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';'
+ print ' (' + ptr + ')[1] = ' + vert( intype, outtype, v1 ) + ';'
+
+# XXX: have the opportunity here to avoid over-drawing shared lines in
+# tristrips, fans, etc, by integrating this into the calling functions
+# and only emitting each line at most once.
+#
+def do_tri( intype, outtype, ptr, v0, v1, v2 ):
+ line( intype, outtype, ptr, v0, v1 )
+ line( intype, outtype, ptr + '+2', v1, v2 )
+ line( intype, outtype, ptr + '+4', v2, v0 )
+
+def do_quad( intype, outtype, ptr, v0, v1, v2, v3 ):
+ line( intype, outtype, ptr, v0, v1 )
+ line( intype, outtype, ptr + '+2', v1, v2 )
+ line( intype, outtype, ptr + '+4', v2, v3 )
+ line( intype, outtype, ptr + '+6', v3, v0 )
+
+def name(intype, outtype, prim):
+ if intype == GENERATE:
+ return 'generate_' + prim + '_' + outtype
+ else:
+ return 'translate_' + prim + '_' + intype + '2' + outtype
+
+def preamble(intype, outtype, prim):
+ print 'static void ' + name( intype, outtype, prim ) + '('
+ if intype != GENERATE:
+ print ' const void * _in,'
+ print ' unsigned nr,'
+ print ' void *_out )'
+ print '{'
+ if intype != GENERATE:
+ print ' const ' + intype + '*in = (const ' + intype + '*)_in;'
+ print ' ' + outtype + ' *out = (' + outtype + '*)_out;'
+ print ' unsigned i, j;'
+ print ' (void)j;'
+
+def postamble():
+ print '}'
+
+
+def tris(intype, outtype):
+ preamble(intype, outtype, prim='tris')
+ print ' for (j = i = 0; j < nr; j+=6, i+=3) { '
+ do_tri( intype, outtype, 'out+j', 'i', 'i+1', 'i+2' );
+ print ' }'
+ postamble()
+
+
+def tristrip(intype, outtype):
+ preamble(intype, outtype, prim='tristrip')
+ print ' for (j = i = 0; j < nr; j+=6, i++) { '
+ do_tri( intype, outtype, 'out+j', 'i', 'i+1/*+(i&1)*/', 'i+2/*-(i&1)*/' );
+ print ' }'
+ postamble()
+
+
+def trifan(intype, outtype):
+ preamble(intype, outtype, prim='trifan')
+ print ' for (j = i = 0; j < nr; j+=6, i++) { '
+ do_tri( intype, outtype, 'out+j', '0', 'i+1', 'i+2' );
+ print ' }'
+ postamble()
+
+
+
+def polygon(intype, outtype):
+ preamble(intype, outtype, prim='polygon')
+ print ' for (j = i = 0; j < nr; j+=6, i++) { '
+ do_tri( intype, outtype, 'out+j', '0', 'i+1', 'i+2' );
+ print ' }'
+ postamble()
+
+
+def quads(intype, outtype):
+ preamble(intype, outtype, prim='quads')
+ print ' for (j = i = 0; j < nr; j+=8, i+=4) { '
+ do_quad( intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3' );
+ print ' }'
+ postamble()
+
+
+def quadstrip(intype, outtype):
+ preamble(intype, outtype, prim='quadstrip')
+ print ' for (j = i = 0; j < nr; j+=8, i+=2) { '
+ do_quad( intype, outtype, 'out+j', 'i+2', 'i+0', 'i+1', 'i+3' );
+ print ' }'
+ postamble()
+
+
+def emit_funcs():
+ for intype in INTYPES:
+ for outtype in OUTTYPES:
+ tris(intype, outtype)
+ tristrip(intype, outtype)
+ trifan(intype, outtype)
+ quads(intype, outtype)
+ quadstrip(intype, outtype)
+ polygon(intype, outtype)
+
+def init(intype, outtype, prim):
+ if intype == GENERATE:
+ print ('generate_line[' +
+ outtype_idx[outtype] +
+ '][' + longprim[prim] +
+ '] = ' + name( intype, outtype, prim ) + ';')
+ else:
+ print ('translate_line[' +
+ intype_idx[intype] +
+ '][' + outtype_idx[outtype] +
+ '][' + longprim[prim] +
+ '] = ' + name( intype, outtype, prim ) + ';')
+
+
+def emit_all_inits():
+ for intype in INTYPES:
+ for outtype in OUTTYPES:
+ for prim in PRIMS:
+ init(intype, outtype, prim)
+
+def emit_init():
+ print 'void u_unfilled_init( void )'
+ print '{'
+ print ' static int firsttime = 1;'
+ print ' if (!firsttime) return;'
+ print ' firsttime = 0;'
+ emit_all_inits()
+ print '}'
+
+
+
+
+def epilog():
+ print '#include "indices/u_unfilled_indices.c"'
+
+
+def main():
+ prolog()
+ emit_funcs()
+ emit_init()
+ epilog()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/auxiliary/indices/u_unfilled_indices.c b/src/gallium/auxiliary/indices/u_unfilled_indices.c
new file mode 100644
index 0000000000..26c5d4d4c7
--- /dev/null
+++ b/src/gallium/auxiliary/indices/u_unfilled_indices.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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 "u_indices.h"
+#include "u_indices_priv.h"
+
+
+static void translate_ubyte_ushort( const void *in,
+ unsigned nr,
+ void *out )
+{
+ const ubyte *in_ub = (const ubyte *)in;
+ ushort *out_us = (ushort *)out;
+ unsigned i;
+ for (i = 0; i < nr; i++)
+ out_us[i] = (ushort) in_ub[i];
+}
+
+static void translate_memcpy_ushort( const void *in,
+ unsigned nr,
+ void *out )
+{
+ memcpy(out, in, nr*sizeof(short));
+}
+
+static void translate_memcpy_uint( const void *in,
+ unsigned nr,
+ void *out )
+{
+ memcpy(out, in, nr*sizeof(int));
+}
+
+
+static void generate_linear_ushort( unsigned nr,
+ void *out )
+{
+ ushort *out_us = (ushort *)out;
+ unsigned i;
+ for (i = 0; i < nr; i++)
+ out_us[i] = (ushort) i;
+}
+
+static void generate_linear_uint( unsigned nr,
+ void *out )
+{
+ unsigned *out_ui = (unsigned *)out;
+ unsigned i;
+ for (i = 0; i < nr; i++)
+ out_ui[i] = i;
+}
+
+
+static unsigned nr_lines( unsigned prim,
+ unsigned nr )
+{
+ switch (prim) {
+ case PIPE_PRIM_TRIANGLES:
+ return (nr / 3) * 6;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ return (nr - 2) * 6;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ return (nr - 2) * 6;
+ case PIPE_PRIM_QUADS:
+ return (nr / 4) * 8;
+ case PIPE_PRIM_QUAD_STRIP:
+ return (nr - 2) / 2 * 8;
+ case PIPE_PRIM_POLYGON:
+ return (nr - 2) * 6;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+
+int u_unfilled_translator( unsigned prim,
+ unsigned in_index_size,
+ unsigned nr,
+ unsigned unfilled_mode,
+ unsigned *out_prim,
+ unsigned *out_index_size,
+ unsigned *out_nr,
+ u_translate_func *out_translate )
+{
+ unsigned in_idx;
+ unsigned out_idx;
+
+ u_unfilled_init();
+
+ in_idx = in_size_idx(in_index_size);
+ *out_index_size = (in_index_size == 4) ? 4 : 2;
+ out_idx = out_size_idx(*out_index_size);
+
+ if (unfilled_mode == PIPE_POLYGON_MODE_POINT)
+ {
+ *out_prim = PIPE_PRIM_POINTS;
+ *out_nr = nr;
+
+ switch (in_index_size)
+ {
+ case 1:
+ *out_translate = translate_ubyte_ushort;
+ return U_TRANSLATE_NORMAL;
+ case 2:
+ *out_translate = translate_memcpy_uint;
+ return U_TRANSLATE_MEMCPY;
+ case 4:
+ *out_translate = translate_memcpy_ushort;
+ return U_TRANSLATE_MEMCPY;
+ default:
+ *out_translate = translate_memcpy_uint;
+ *out_nr = 0;
+ assert(0);
+ return U_TRANSLATE_ERROR;
+ }
+ }
+ else {
+ assert(unfilled_mode == PIPE_POLYGON_MODE_LINE);
+ *out_prim = PIPE_PRIM_LINES;
+ *out_translate = translate_line[in_idx][out_idx][prim];
+ *out_nr = nr_lines( prim, nr );
+ return U_TRANSLATE_NORMAL;
+ }
+}
+
+
+
+int u_unfilled_generator( unsigned prim,
+ unsigned start,
+ unsigned nr,
+ unsigned unfilled_mode,
+ unsigned *out_prim,
+ unsigned *out_index_size,
+ unsigned *out_nr,
+ u_generate_func *out_generate )
+{
+ unsigned out_idx;
+
+ u_unfilled_init();
+
+ *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;
+ out_idx = out_size_idx(*out_index_size);
+
+ if (unfilled_mode == PIPE_POLYGON_MODE_POINT) {
+
+ if (*out_index_size == 4)
+ *out_generate = generate_linear_uint;
+ else
+ *out_generate = generate_linear_ushort;
+
+ *out_prim = PIPE_PRIM_POINTS;
+ *out_nr = nr;
+ return U_GENERATE_LINEAR;
+ }
+ else {
+ assert(unfilled_mode == PIPE_POLYGON_MODE_LINE);
+ *out_prim = PIPE_PRIM_LINES;
+ *out_generate = generate_line[out_idx][prim];
+ *out_nr = nr_lines( prim, nr );
+
+ return U_GENERATE_REUSABLE;
+ }
+}
+
diff --git a/src/gallium/auxiliary/pipebuffer/Makefile b/src/gallium/auxiliary/pipebuffer/Makefile
new file mode 100644
index 0000000000..1c00ba8d98
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/Makefile
@@ -0,0 +1,19 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = pipebuffer
+
+C_SOURCES = \
+ pb_buffer_fenced.c \
+ pb_buffer_malloc.c \
+ pb_bufmgr_alt.c \
+ pb_bufmgr_cache.c \
+ pb_bufmgr_debug.c \
+ pb_bufmgr_fenced.c \
+ pb_bufmgr_mm.c \
+ pb_bufmgr_ondemand.c \
+ pb_bufmgr_pool.c \
+ pb_bufmgr_slab.c \
+ pb_validate.c
+
+include ../../Makefile.template
diff --git a/src/gallium/auxiliary/pipebuffer/SConscript b/src/gallium/auxiliary/pipebuffer/SConscript
new file mode 100644
index 0000000000..8e9f06abe4
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/SConscript
@@ -0,0 +1,19 @@
+Import('*')
+
+pipebuffer = env.ConvenienceLibrary(
+ target = 'pipebuffer',
+ source = [
+ 'pb_buffer_fenced.c',
+ 'pb_buffer_malloc.c',
+ 'pb_bufmgr_alt.c',
+ 'pb_bufmgr_cache.c',
+ 'pb_bufmgr_debug.c',
+ 'pb_bufmgr_fenced.c',
+ 'pb_bufmgr_mm.c',
+ 'pb_bufmgr_ondemand.c',
+ 'pb_bufmgr_pool.c',
+ 'pb_bufmgr_slab.c',
+ 'pb_validate.c',
+ ])
+
+auxiliaries.insert(0, pipebuffer)
diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer.h b/src/gallium/auxiliary/pipebuffer/pb_buffer.h
new file mode 100644
index 0000000000..2590546cb4
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_buffer.h
@@ -0,0 +1,286 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Generic code for buffers.
+ *
+ * Behind a pipe buffle handle there can be DMA buffers, client (or user)
+ * buffers, regular malloced buffers, etc. This file provides an abstract base
+ * buffer handle that allows the driver to cope with all those kinds of buffers
+ * in a more flexible way.
+ *
+ * There is no obligation of a winsys driver to use this library. And a pipe
+ * driver should be completly agnostic about it.
+ *
+ * \author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef PB_BUFFER_H_
+#define PB_BUFFER_H_
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_error.h"
+#include "pipe/p_state.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pb_vtbl;
+struct pb_validate;
+
+
+/**
+ * Buffer description.
+ *
+ * Used when allocating the buffer.
+ */
+struct pb_desc
+{
+ unsigned alignment;
+ unsigned usage;
+};
+
+
+/**
+ * Size. Regular (32bit) unsigned for now.
+ */
+typedef unsigned pb_size;
+
+
+/**
+ * Base class for all pb_* buffers.
+ */
+struct pb_buffer
+{
+ struct pipe_buffer base;
+
+ /**
+ * Pointer to the virtual function table.
+ *
+ * Avoid accessing this table directly. Use the inline functions below
+ * instead to avoid mistakes.
+ */
+ const struct pb_vtbl *vtbl;
+};
+
+
+/**
+ * Virtual function table for the buffer storage operations.
+ *
+ * Note that creation is not done through this table.
+ */
+struct pb_vtbl
+{
+ void (*destroy)( struct pb_buffer *buf );
+
+ /**
+ * Map the entire data store of a buffer object into the client's address.
+ * flags is bitmask of PIPE_BUFFER_FLAG_READ/WRITE.
+ */
+ void *(*map)( struct pb_buffer *buf,
+ unsigned flags );
+
+ void (*unmap)( struct pb_buffer *buf );
+
+ enum pipe_error (*validate)( struct pb_buffer *buf,
+ struct pb_validate *vl,
+ unsigned flags );
+
+ void (*fence)( struct pb_buffer *buf,
+ struct pipe_fence_handle *fence );
+
+ /**
+ * Get the base buffer and the offset.
+ *
+ * A buffer can be subdivided in smaller buffers. This method should return
+ * the underlaying buffer, and the relative offset.
+ *
+ * Buffers without an underlaying base buffer should return themselves, with
+ * a zero offset.
+ *
+ * Note that this will increase the reference count of the base buffer.
+ */
+ void (*get_base_buffer)( struct pb_buffer *buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset );
+
+};
+
+
+static INLINE struct pipe_buffer *
+pb_pipe_buffer( struct pb_buffer *pbuf )
+{
+ assert(pbuf);
+ return &pbuf->base;
+}
+
+
+static INLINE struct pb_buffer *
+pb_buffer( struct pipe_buffer *buf )
+{
+ assert(buf);
+ /* Could add a magic cookie check on debug builds.
+ */
+ return (struct pb_buffer *)buf;
+}
+
+
+/* Accessor functions for pb->vtbl:
+ */
+static INLINE void *
+pb_map(struct pb_buffer *buf,
+ unsigned flags)
+{
+ assert(buf);
+ if(!buf)
+ return NULL;
+ assert(pipe_is_referenced(&buf->base.reference));
+ return buf->vtbl->map(buf, flags);
+}
+
+
+static INLINE void
+pb_unmap(struct pb_buffer *buf)
+{
+ assert(buf);
+ if(!buf)
+ return;
+ assert(pipe_is_referenced(&buf->base.reference));
+ buf->vtbl->unmap(buf);
+}
+
+
+static INLINE void
+pb_get_base_buffer( struct pb_buffer *buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset )
+{
+ assert(buf);
+ if(!buf) {
+ base_buf = NULL;
+ offset = 0;
+ return;
+ }
+ assert(pipe_is_referenced(&buf->base.reference));
+ assert(buf->vtbl->get_base_buffer);
+ buf->vtbl->get_base_buffer(buf, base_buf, offset);
+ assert(*base_buf);
+ assert(*offset < (*base_buf)->base.size);
+}
+
+
+static INLINE enum pipe_error
+pb_validate(struct pb_buffer *buf, struct pb_validate *vl, unsigned flags)
+{
+ assert(buf);
+ if(!buf)
+ return PIPE_ERROR;
+ assert(buf->vtbl->validate);
+ return buf->vtbl->validate(buf, vl, flags);
+}
+
+
+static INLINE void
+pb_fence(struct pb_buffer *buf, struct pipe_fence_handle *fence)
+{
+ assert(buf);
+ if(!buf)
+ return;
+ assert(buf->vtbl->fence);
+ buf->vtbl->fence(buf, fence);
+}
+
+
+static INLINE void
+pb_destroy(struct pb_buffer *buf)
+{
+ assert(buf);
+ if(!buf)
+ return;
+ assert(!pipe_is_referenced(&buf->base.reference));
+ buf->vtbl->destroy(buf);
+}
+
+static INLINE void
+pb_reference(struct pb_buffer **dst,
+ struct pb_buffer *src)
+{
+ struct pb_buffer *old = *dst;
+
+ if (pipe_reference((struct pipe_reference**)dst, &src->base.reference))
+ pb_destroy( old );
+}
+
+
+/**
+ * Utility function to check whether the provided alignment is consistent with
+ * the requested or not.
+ */
+static INLINE boolean
+pb_check_alignment(pb_size requested, pb_size provided)
+{
+ if(!requested)
+ return TRUE;
+ if(requested > provided)
+ return FALSE;
+ if(provided % requested != 0)
+ return FALSE;
+ return TRUE;
+}
+
+
+/**
+ * Utility function to check whether the provided alignment is consistent with
+ * the requested or not.
+ */
+static INLINE boolean
+pb_check_usage(unsigned requested, unsigned provided)
+{
+ return (requested & provided) == requested ? TRUE : FALSE;
+}
+
+
+/**
+ * Malloc-based buffer to store data that can't be used by the graphics
+ * hardware.
+ */
+struct pb_buffer *
+pb_malloc_buffer_create(pb_size size,
+ const struct pb_desc *desc);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*PB_BUFFER_H_*/
diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c
new file mode 100644
index 0000000000..109ac7c9d6
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c
@@ -0,0 +1,597 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Implementation of fenced buffers.
+ *
+ * \author Jose Fonseca <jrfonseca-at-tungstengraphics-dot-com>
+ * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)
+#include <unistd.h>
+#include <sched.h>
+#endif
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_error.h"
+#include "util/u_debug.h"
+#include "pipe/p_thread.h"
+#include "util/u_memory.h"
+#include "util/u_double_list.h"
+
+#include "pb_buffer.h"
+#include "pb_buffer_fenced.h"
+
+
+
+/**
+ * Convenience macro (type safe).
+ */
+#define SUPER(__derived) (&(__derived)->base)
+
+
+struct fenced_buffer_list
+{
+ pipe_mutex mutex;
+
+ struct pb_fence_ops *ops;
+
+ pb_size numDelayed;
+ struct list_head delayed;
+
+#ifdef DEBUG
+ pb_size numUnfenced;
+ struct list_head unfenced;
+#endif
+};
+
+
+/**
+ * Wrapper around a pipe buffer which adds fencing and reference counting.
+ */
+struct fenced_buffer
+{
+ struct pb_buffer base;
+
+ struct pb_buffer *buffer;
+
+ /* FIXME: protect access with mutex */
+
+ /**
+ * A bitmask of PIPE_BUFFER_USAGE_CPU/GPU_READ/WRITE describing the current
+ * buffer usage.
+ */
+ unsigned flags;
+
+ unsigned mapcount;
+ struct pb_validate *vl;
+ unsigned validation_flags;
+ struct pipe_fence_handle *fence;
+
+ struct list_head head;
+ struct fenced_buffer_list *list;
+};
+
+
+static INLINE struct fenced_buffer *
+fenced_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ return (struct fenced_buffer *)buf;
+}
+
+
+static INLINE void
+_fenced_buffer_add(struct fenced_buffer *fenced_buf)
+{
+ struct fenced_buffer_list *fenced_list = fenced_buf->list;
+
+ assert(pipe_is_referenced(&fenced_buf->base.base.reference));
+ assert(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE);
+ assert(fenced_buf->fence);
+
+#ifdef DEBUG
+ LIST_DEL(&fenced_buf->head);
+ assert(fenced_list->numUnfenced);
+ --fenced_list->numUnfenced;
+#endif
+ LIST_ADDTAIL(&fenced_buf->head, &fenced_list->delayed);
+ ++fenced_list->numDelayed;
+}
+
+
+/**
+ * Actually destroy the buffer.
+ */
+static INLINE void
+_fenced_buffer_destroy(struct fenced_buffer *fenced_buf)
+{
+ struct fenced_buffer_list *fenced_list = fenced_buf->list;
+
+ assert(!pipe_is_referenced(&fenced_buf->base.base.reference));
+ assert(!fenced_buf->fence);
+#ifdef DEBUG
+ assert(fenced_buf->head.prev);
+ assert(fenced_buf->head.next);
+ LIST_DEL(&fenced_buf->head);
+ assert(fenced_list->numUnfenced);
+ --fenced_list->numUnfenced;
+#else
+ (void)fenced_list;
+#endif
+ pb_reference(&fenced_buf->buffer, NULL);
+ FREE(fenced_buf);
+}
+
+
+static INLINE void
+_fenced_buffer_remove(struct fenced_buffer_list *fenced_list,
+ struct fenced_buffer *fenced_buf)
+{
+ struct pb_fence_ops *ops = fenced_list->ops;
+
+ assert(fenced_buf->fence);
+ assert(fenced_buf->list == fenced_list);
+
+ ops->fence_reference(ops, &fenced_buf->fence, NULL);
+ fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE;
+
+ assert(fenced_buf->head.prev);
+ assert(fenced_buf->head.next);
+
+ LIST_DEL(&fenced_buf->head);
+ assert(fenced_list->numDelayed);
+ --fenced_list->numDelayed;
+
+#ifdef DEBUG
+ LIST_ADDTAIL(&fenced_buf->head, &fenced_list->unfenced);
+ ++fenced_list->numUnfenced;
+#endif
+
+ /**
+ * FIXME!!!
+ */
+
+ if(!pipe_is_referenced(&fenced_buf->base.base.reference))
+ _fenced_buffer_destroy(fenced_buf);
+}
+
+
+static INLINE enum pipe_error
+_fenced_buffer_finish(struct fenced_buffer *fenced_buf)
+{
+ struct fenced_buffer_list *fenced_list = fenced_buf->list;
+ struct pb_fence_ops *ops = fenced_list->ops;
+
+#if 0
+ debug_warning("waiting for GPU");
+#endif
+
+ assert(fenced_buf->fence);
+ if(fenced_buf->fence) {
+ if(ops->fence_finish(ops, fenced_buf->fence, 0) != 0) {
+ return PIPE_ERROR;
+ }
+ /* Remove from the fenced list */
+ /* TODO: remove consequents */
+ _fenced_buffer_remove(fenced_list, fenced_buf);
+ }
+
+ fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE;
+ return PIPE_OK;
+}
+
+
+/**
+ * Free as many fenced buffers from the list head as possible.
+ */
+static void
+_fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
+ int wait)
+{
+ struct pb_fence_ops *ops = fenced_list->ops;
+ struct list_head *curr, *next;
+ struct fenced_buffer *fenced_buf;
+ struct pipe_fence_handle *prev_fence = NULL;
+
+ curr = fenced_list->delayed.next;
+ next = curr->next;
+ while(curr != &fenced_list->delayed) {
+ fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
+
+ if(fenced_buf->fence != prev_fence) {
+ int signaled;
+ if (wait)
+ signaled = ops->fence_finish(ops, fenced_buf->fence, 0);
+ else
+ signaled = ops->fence_signalled(ops, fenced_buf->fence, 0);
+ if (signaled != 0)
+ break;
+ prev_fence = fenced_buf->fence;
+ }
+ else {
+ assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0);
+ }
+
+ _fenced_buffer_remove(fenced_list, fenced_buf);
+
+ curr = next;
+ next = curr->next;
+ }
+}
+
+
+static void
+fenced_buffer_destroy(struct pb_buffer *buf)
+{
+ struct fenced_buffer *fenced_buf = fenced_buffer(buf);
+ struct fenced_buffer_list *fenced_list = fenced_buf->list;
+
+ pipe_mutex_lock(fenced_list->mutex);
+ assert(!pipe_is_referenced(&fenced_buf->base.base.reference));
+ if (fenced_buf->fence) {
+ struct pb_fence_ops *ops = fenced_list->ops;
+ if(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0) {
+ struct list_head *curr, *prev;
+ curr = &fenced_buf->head;
+ prev = curr->prev;
+ do {
+ fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
+ assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0);
+ _fenced_buffer_remove(fenced_list, fenced_buf);
+ curr = prev;
+ prev = curr->prev;
+ } while (curr != &fenced_list->delayed);
+ }
+ else {
+ /* delay destruction */
+ }
+ }
+ else {
+ _fenced_buffer_destroy(fenced_buf);
+ }
+ pipe_mutex_unlock(fenced_list->mutex);
+}
+
+
+static void *
+fenced_buffer_map(struct pb_buffer *buf,
+ unsigned flags)
+{
+ struct fenced_buffer *fenced_buf = fenced_buffer(buf);
+ struct fenced_buffer_list *fenced_list = fenced_buf->list;
+ struct pb_fence_ops *ops = fenced_list->ops;
+ void *map;
+
+ assert(!(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE));
+
+ /* Serialize writes */
+ if((fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_WRITE) ||
+ ((fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ) && (flags & PIPE_BUFFER_USAGE_CPU_WRITE))) {
+ if(flags & PIPE_BUFFER_USAGE_DONTBLOCK) {
+ /* Don't wait for the GPU to finish writing */
+ if(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0)
+ _fenced_buffer_remove(fenced_list, fenced_buf);
+ else
+ return NULL;
+ }
+ else {
+ /* Wait for the GPU to finish writing */
+ _fenced_buffer_finish(fenced_buf);
+ }
+ }
+
+#if 0
+ /* Check for CPU write access (read is OK) */
+ if(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) {
+ /* this is legal -- just for debugging */
+ debug_warning("concurrent CPU writes");
+ }
+#endif
+
+ map = pb_map(fenced_buf->buffer, flags);
+ if(map) {
+ ++fenced_buf->mapcount;
+ fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ }
+
+ return map;
+}
+
+
+static void
+fenced_buffer_unmap(struct pb_buffer *buf)
+{
+ struct fenced_buffer *fenced_buf = fenced_buffer(buf);
+ assert(fenced_buf->mapcount);
+ if(fenced_buf->mapcount) {
+ pb_unmap(fenced_buf->buffer);
+ --fenced_buf->mapcount;
+ if(!fenced_buf->mapcount)
+ fenced_buf->flags &= ~PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ }
+}
+
+
+static enum pipe_error
+fenced_buffer_validate(struct pb_buffer *buf,
+ struct pb_validate *vl,
+ unsigned flags)
+{
+ struct fenced_buffer *fenced_buf = fenced_buffer(buf);
+ enum pipe_error ret;
+
+ if(!vl) {
+ /* invalidate */
+ fenced_buf->vl = NULL;
+ fenced_buf->validation_flags = 0;
+ return PIPE_OK;
+ }
+
+ assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE);
+ assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE));
+ flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE;
+
+ /* Buffer cannot be validated in two different lists */
+ if(fenced_buf->vl && fenced_buf->vl != vl)
+ return PIPE_ERROR_RETRY;
+
+#if 0
+ /* Do not validate if buffer is still mapped */
+ if(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE) {
+ /* TODO: wait for the thread that mapped the buffer to unmap it */
+ return PIPE_ERROR_RETRY;
+ }
+ /* Final sanity checking */
+ assert(!(fenced_buf->flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE));
+ assert(!fenced_buf->mapcount);
+#endif
+
+ if(fenced_buf->vl == vl &&
+ (fenced_buf->validation_flags & flags) == flags) {
+ /* Nothing to do -- buffer already validated */
+ return PIPE_OK;
+ }
+
+ ret = pb_validate(fenced_buf->buffer, vl, flags);
+ if (ret != PIPE_OK)
+ return ret;
+
+ fenced_buf->vl = vl;
+ fenced_buf->validation_flags |= flags;
+
+ return PIPE_OK;
+}
+
+
+static void
+fenced_buffer_fence(struct pb_buffer *buf,
+ struct pipe_fence_handle *fence)
+{
+ struct fenced_buffer *fenced_buf;
+ struct fenced_buffer_list *fenced_list;
+ struct pb_fence_ops *ops;
+
+ fenced_buf = fenced_buffer(buf);
+ fenced_list = fenced_buf->list;
+ ops = fenced_list->ops;
+
+ if(fence == fenced_buf->fence) {
+ /* Nothing to do */
+ return;
+ }
+
+ assert(fenced_buf->vl);
+ assert(fenced_buf->validation_flags);
+
+ pipe_mutex_lock(fenced_list->mutex);
+ if (fenced_buf->fence)
+ _fenced_buffer_remove(fenced_list, fenced_buf);
+ if (fence) {
+ ops->fence_reference(ops, &fenced_buf->fence, fence);
+ fenced_buf->flags |= fenced_buf->validation_flags;
+ _fenced_buffer_add(fenced_buf);
+ }
+ pipe_mutex_unlock(fenced_list->mutex);
+
+ pb_fence(fenced_buf->buffer, fence);
+
+ fenced_buf->vl = NULL;
+ fenced_buf->validation_flags = 0;
+}
+
+
+static void
+fenced_buffer_get_base_buffer(struct pb_buffer *buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset)
+{
+ struct fenced_buffer *fenced_buf = fenced_buffer(buf);
+ pb_get_base_buffer(fenced_buf->buffer, base_buf, offset);
+}
+
+
+static const struct pb_vtbl
+fenced_buffer_vtbl = {
+ fenced_buffer_destroy,
+ fenced_buffer_map,
+ fenced_buffer_unmap,
+ fenced_buffer_validate,
+ fenced_buffer_fence,
+ fenced_buffer_get_base_buffer
+};
+
+
+struct pb_buffer *
+fenced_buffer_create(struct fenced_buffer_list *fenced_list,
+ struct pb_buffer *buffer)
+{
+ struct fenced_buffer *buf;
+
+ if(!buffer)
+ return NULL;
+
+ buf = CALLOC_STRUCT(fenced_buffer);
+ if(!buf) {
+ pb_reference(&buffer, NULL);
+ return NULL;
+ }
+
+ pipe_reference_init(&buf->base.base.reference, 1);
+ buf->base.base.alignment = buffer->base.alignment;
+ buf->base.base.usage = buffer->base.usage;
+ buf->base.base.size = buffer->base.size;
+
+ buf->base.vtbl = &fenced_buffer_vtbl;
+ buf->buffer = buffer;
+ buf->list = fenced_list;
+
+#ifdef DEBUG
+ pipe_mutex_lock(fenced_list->mutex);
+ LIST_ADDTAIL(&buf->head, &fenced_list->unfenced);
+ ++fenced_list->numUnfenced;
+ pipe_mutex_unlock(fenced_list->mutex);
+#endif
+
+ return &buf->base;
+}
+
+
+struct fenced_buffer_list *
+fenced_buffer_list_create(struct pb_fence_ops *ops)
+{
+ struct fenced_buffer_list *fenced_list;
+
+ fenced_list = CALLOC_STRUCT(fenced_buffer_list);
+ if (!fenced_list)
+ return NULL;
+
+ fenced_list->ops = ops;
+
+ LIST_INITHEAD(&fenced_list->delayed);
+ fenced_list->numDelayed = 0;
+
+#ifdef DEBUG
+ LIST_INITHEAD(&fenced_list->unfenced);
+ fenced_list->numUnfenced = 0;
+#endif
+
+ pipe_mutex_init(fenced_list->mutex);
+
+ return fenced_list;
+}
+
+
+void
+fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
+ int wait)
+{
+ pipe_mutex_lock(fenced_list->mutex);
+ _fenced_buffer_list_check_free(fenced_list, wait);
+ pipe_mutex_unlock(fenced_list->mutex);
+}
+
+
+#ifdef DEBUG
+void
+fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list)
+{
+ struct pb_fence_ops *ops = fenced_list->ops;
+ struct list_head *curr, *next;
+ struct fenced_buffer *fenced_buf;
+
+ pipe_mutex_lock(fenced_list->mutex);
+
+ debug_printf("%10s %7s %7s %10s %s\n",
+ "buffer", "size", "refcount", "fence", "signalled");
+
+ curr = fenced_list->unfenced.next;
+ next = curr->next;
+ while(curr != &fenced_list->unfenced) {
+ fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
+ assert(!fenced_buf->fence);
+ debug_printf("%10p %7u %7u\n",
+ fenced_buf,
+ fenced_buf->base.base.size,
+ fenced_buf->base.base.reference.count);
+ curr = next;
+ next = curr->next;
+ }
+
+ curr = fenced_list->delayed.next;
+ next = curr->next;
+ while(curr != &fenced_list->delayed) {
+ int signaled;
+ fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
+ signaled = ops->fence_signalled(ops, fenced_buf->fence, 0);
+ debug_printf("%10p %7u %7u %10p %s\n",
+ fenced_buf,
+ fenced_buf->base.base.size,
+ fenced_buf->base.base.reference.count,
+ fenced_buf->fence,
+ signaled == 0 ? "y" : "n");
+ curr = next;
+ next = curr->next;
+ }
+
+ pipe_mutex_unlock(fenced_list->mutex);
+}
+#endif
+
+
+void
+fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list)
+{
+ pipe_mutex_lock(fenced_list->mutex);
+
+ /* Wait on outstanding fences */
+ while (fenced_list->numDelayed) {
+ pipe_mutex_unlock(fenced_list->mutex);
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)
+ sched_yield();
+#endif
+ _fenced_buffer_list_check_free(fenced_list, 1);
+ pipe_mutex_lock(fenced_list->mutex);
+ }
+
+#ifdef DEBUG
+ //assert(!fenced_list->numUnfenced);
+#endif
+
+ pipe_mutex_unlock(fenced_list->mutex);
+
+ fenced_list->ops->destroy(fenced_list->ops);
+
+ FREE(fenced_list);
+}
+
+
diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h
new file mode 100644
index 0000000000..034ca1e024
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.h
@@ -0,0 +1,142 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Buffer fencing.
+ *
+ * "Fenced buffers" is actually a misnomer. They should be referred as
+ * "fenceable buffers", i.e, buffers that can be fenced, but I couldn't find
+ * the word "fenceable" in the dictionary.
+ *
+ * A "fenced buffer" is a decorator around a normal buffer, which adds two
+ * special properties:
+ * - the ability for the destruction to be delayed by a fence;
+ * - reference counting.
+ *
+ * Usually DMA buffers have a life-time that will extend the life-time of its
+ * handle. The end-of-life is dictated by the fence signalling.
+ *
+ * Between the handle's destruction, and the fence signalling, the buffer is
+ * stored in a fenced buffer list.
+ *
+ * \author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef PB_BUFFER_FENCED_H_
+#define PB_BUFFER_FENCED_H_
+
+
+#include "util/u_debug.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_buffer;
+struct pipe_fence_handle;
+
+
+/**
+ * List of buffers which are awaiting fence signalling.
+ */
+struct fenced_buffer_list;
+
+
+struct pb_fence_ops
+{
+ void (*destroy)( struct pb_fence_ops *ops );
+
+ /** Set ptr = fence, with reference counting */
+ void (*fence_reference)( struct pb_fence_ops *ops,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence );
+
+ /**
+ * Checks whether the fence has been signalled.
+ * \param flags driver-specific meaning
+ * \return zero on success.
+ */
+ int (*fence_signalled)( struct pb_fence_ops *ops,
+ struct pipe_fence_handle *fence,
+ unsigned flag );
+
+ /**
+ * Wait for the fence to finish.
+ * \param flags driver-specific meaning
+ * \return zero on success.
+ */
+ int (*fence_finish)( struct pb_fence_ops *ops,
+ struct pipe_fence_handle *fence,
+ unsigned flag );
+};
+
+
+/**
+ * Create a fenced buffer list.
+ *
+ * See also fenced_bufmgr_create for a more convenient way to use this.
+ */
+struct fenced_buffer_list *
+fenced_buffer_list_create(struct pb_fence_ops *ops);
+
+
+/**
+ * Walk the fenced buffer list to check and free signalled buffers.
+ */
+void
+fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
+ int wait);
+
+
+#ifdef DEBUG
+void
+fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list);
+#endif
+
+
+void
+fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list);
+
+
+/**
+ * Wrap a buffer in a fenced buffer.
+ *
+ * NOTE: this will not increase the buffer reference count.
+ */
+struct pb_buffer *
+fenced_buffer_create(struct fenced_buffer_list *fenced,
+ struct pb_buffer *buffer);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*PB_BUFFER_FENCED_H_*/
diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c
new file mode 100644
index 0000000000..6bdce5fcb0
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c
@@ -0,0 +1,188 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Implementation of malloc-based buffers to store data that can't be processed
+ * by the hardware.
+ *
+ * \author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+struct malloc_buffer
+{
+ struct pb_buffer base;
+ void *data;
+};
+
+
+extern const struct pb_vtbl malloc_buffer_vtbl;
+
+static INLINE struct malloc_buffer *
+malloc_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ if (!buf)
+ return NULL;
+ assert(buf->vtbl == &malloc_buffer_vtbl);
+ return (struct malloc_buffer *)buf;
+}
+
+
+static void
+malloc_buffer_destroy(struct pb_buffer *buf)
+{
+ align_free(malloc_buffer(buf)->data);
+ FREE(buf);
+}
+
+
+static void *
+malloc_buffer_map(struct pb_buffer *buf,
+ unsigned flags)
+{
+ return malloc_buffer(buf)->data;
+}
+
+
+static void
+malloc_buffer_unmap(struct pb_buffer *buf)
+{
+ /* No-op */
+}
+
+
+static enum pipe_error
+malloc_buffer_validate(struct pb_buffer *buf,
+ struct pb_validate *vl,
+ unsigned flags)
+{
+ assert(0);
+ return PIPE_ERROR;
+}
+
+
+static void
+malloc_buffer_fence(struct pb_buffer *buf,
+ struct pipe_fence_handle *fence)
+{
+ assert(0);
+}
+
+
+static void
+malloc_buffer_get_base_buffer(struct pb_buffer *buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset)
+{
+ *base_buf = buf;
+ *offset = 0;
+}
+
+
+const struct pb_vtbl
+malloc_buffer_vtbl = {
+ malloc_buffer_destroy,
+ malloc_buffer_map,
+ malloc_buffer_unmap,
+ malloc_buffer_validate,
+ malloc_buffer_fence,
+ malloc_buffer_get_base_buffer
+};
+
+
+struct pb_buffer *
+pb_malloc_buffer_create(pb_size size,
+ const struct pb_desc *desc)
+{
+ struct malloc_buffer *buf;
+
+ /* TODO: do a single allocation */
+
+ buf = CALLOC_STRUCT(malloc_buffer);
+ if(!buf)
+ return NULL;
+
+ 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 = &malloc_buffer_vtbl;
+
+ buf->data = align_malloc(size, desc->alignment < sizeof(void*) ? sizeof(void*) : desc->alignment);
+ if(!buf->data) {
+ FREE(buf);
+ return NULL;
+ }
+
+ return &buf->base;
+}
+
+
+static struct pb_buffer *
+pb_malloc_bufmgr_create_buffer(struct pb_manager *mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ return pb_malloc_buffer_create(size, desc);
+}
+
+
+static void
+pb_malloc_bufmgr_flush(struct pb_manager *mgr)
+{
+ /* No-op */
+}
+
+
+static void
+pb_malloc_bufmgr_destroy(struct pb_manager *mgr)
+{
+ /* No-op */
+}
+
+
+static struct pb_manager
+pb_malloc_bufmgr = {
+ pb_malloc_bufmgr_destroy,
+ pb_malloc_bufmgr_create_buffer,
+ pb_malloc_bufmgr_flush
+};
+
+
+struct pb_manager *
+pb_malloc_bufmgr_create(void)
+{
+ return &pb_malloc_bufmgr;
+}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
new file mode 100644
index 0000000000..39ab8e722c
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
@@ -0,0 +1,214 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Buffer management.
+ *
+ * A buffer manager does only one basic thing: it creates buffers. Actually,
+ * "buffer factory" would probably a more accurate description.
+ *
+ * You can chain buffer managers so that you can have a finer grained memory
+ * management and pooling.
+ *
+ * For example, for a simple batch buffer manager you would chain:
+ * - the native buffer manager, which provides DMA memory from the graphics
+ * memory space;
+ * - the pool buffer manager, which keep around a pool of equally sized buffers
+ * to avoid latency associated with the native buffer manager;
+ * - the fenced buffer manager, which will delay buffer destruction until the
+ * the moment the card finishing processing it.
+ *
+ * \author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef PB_BUFMGR_H_
+#define PB_BUFMGR_H_
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_error.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pb_desc;
+struct pipe_buffer;
+
+
+/**
+ * Abstract base class for all buffer managers.
+ */
+struct pb_manager
+{
+ void
+ (*destroy)( struct pb_manager *mgr );
+
+ struct pb_buffer *
+ (*create_buffer)( struct pb_manager *mgr,
+ pb_size size,
+ const struct pb_desc *desc);
+
+ /**
+ * Flush all temporary-held buffers.
+ *
+ * Used mostly to aid debugging memory issues or to clean up resources when
+ * the drivers are long lived.
+ */
+ void
+ (*flush)( struct pb_manager *mgr );
+};
+
+
+/**
+ * Malloc buffer provider.
+ *
+ * Simple wrapper around pb_malloc_buffer_create for convenience.
+ */
+struct pb_manager *
+pb_malloc_bufmgr_create(void);
+
+
+/**
+ * Static buffer pool sub-allocator.
+ *
+ * Manages the allocation of equally sized buffers. It does so by allocating
+ * a single big buffer and divide it equally sized buffers.
+ *
+ * It is meant to manage the allocation of batch buffer pools.
+ */
+struct pb_manager *
+pool_bufmgr_create(struct pb_manager *provider,
+ pb_size n, pb_size size,
+ const struct pb_desc *desc);
+
+
+/**
+ * Static sub-allocator based the old memory manager.
+ *
+ * It managers buffers of different sizes. It does so by allocating a buffer
+ * with the size of the heap, and then using the old mm memory manager to manage
+ * that heap.
+ */
+struct pb_manager *
+mm_bufmgr_create(struct pb_manager *provider,
+ pb_size size, pb_size align2);
+
+/**
+ * Same as mm_bufmgr_create.
+ *
+ * Buffer will be release when the manager is destroyed.
+ */
+struct pb_manager *
+mm_bufmgr_create_from_buffer(struct pb_buffer *buffer,
+ pb_size size, pb_size align2);
+
+
+/**
+ * Slab sub-allocator.
+ */
+struct pb_manager *
+pb_slab_manager_create(struct pb_manager *provider,
+ pb_size bufSize,
+ pb_size slabSize,
+ const struct pb_desc *desc);
+
+/**
+ * Allow a range of buffer size, by aggregating multiple slabs sub-allocators
+ * with different bucket sizes.
+ */
+struct pb_manager *
+pb_slab_range_manager_create(struct pb_manager *provider,
+ pb_size minBufSize,
+ pb_size maxBufSize,
+ pb_size slabSize,
+ const struct pb_desc *desc);
+
+
+/**
+ * Time-based buffer cache.
+ *
+ * This manager keeps a cache of destroyed buffers during a time interval.
+ */
+struct pb_manager *
+pb_cache_manager_create(struct pb_manager *provider,
+ unsigned usecs);
+
+
+struct pb_fence_ops;
+
+/**
+ * Fenced buffer manager.
+ *
+ * This manager is just meant for convenience. It wraps the buffers returned
+ * by another manager in fenced buffers, so that
+ *
+ * NOTE: the buffer manager that provides the buffers will be destroyed
+ * at the same time.
+ */
+struct pb_manager *
+fenced_bufmgr_create(struct pb_manager *provider,
+ struct pb_fence_ops *ops);
+
+
+struct pb_manager *
+pb_alt_manager_create(struct pb_manager *provider1,
+ struct pb_manager *provider2);
+
+
+/**
+ * Ondemand buffer manager.
+ *
+ * Buffers are created in malloc'ed memory (fast and cached), and the constents
+ * is transfered to a buffer from the provider (typically in slow uncached
+ * memory) when there is an attempt to validate the buffer.
+ *
+ * Ideal for situations where one does not know before hand whether a given
+ * buffer will effectively be used by the hardware or not.
+ */
+struct pb_manager *
+pb_ondemand_manager_create(struct pb_manager *provider);
+
+
+/**
+ * Debug buffer manager to detect buffer under- and overflows.
+ *
+ * Under/overflow sizes should be a multiple of the largest alignment
+ */
+struct pb_manager *
+pb_debug_manager_create(struct pb_manager *provider,
+ pb_size underflow_size, pb_size overflow_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*PB_BUFMGR_H_*/
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c
new file mode 100644
index 0000000000..f60c836f18
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c
@@ -0,0 +1,120 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Allocate buffers from two alternative buffer providers.
+ *
+ * \author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+struct pb_alt_manager
+{
+ struct pb_manager base;
+
+ struct pb_manager *provider1;
+ struct pb_manager *provider2;
+};
+
+
+static INLINE struct pb_alt_manager *
+pb_alt_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct pb_alt_manager *)mgr;
+}
+
+
+static struct pb_buffer *
+pb_alt_manager_create_buffer(struct pb_manager *_mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct pb_alt_manager *mgr = pb_alt_manager(_mgr);
+ struct pb_buffer *buf;
+
+ buf = mgr->provider1->create_buffer(mgr->provider1, size, desc);
+ if(buf)
+ return buf;
+
+ buf = mgr->provider2->create_buffer(mgr->provider2, size, desc);
+ return buf;
+}
+
+
+static void
+pb_alt_manager_flush(struct pb_manager *_mgr)
+{
+ struct pb_alt_manager *mgr = pb_alt_manager(_mgr);
+
+ assert(mgr->provider1->flush);
+ if(mgr->provider1->flush)
+ mgr->provider1->flush(mgr->provider1);
+
+ assert(mgr->provider2->flush);
+ if(mgr->provider2->flush)
+ mgr->provider2->flush(mgr->provider2);
+}
+
+
+static void
+pb_alt_manager_destroy(struct pb_manager *mgr)
+{
+ FREE(mgr);
+}
+
+
+struct pb_manager *
+pb_alt_manager_create(struct pb_manager *provider1,
+ struct pb_manager *provider2)
+{
+ struct pb_alt_manager *mgr;
+
+ if(!provider1 || !provider2)
+ return NULL;
+
+ mgr = CALLOC_STRUCT(pb_alt_manager);
+ if (!mgr)
+ return NULL;
+
+ mgr->base.destroy = pb_alt_manager_destroy;
+ mgr->base.create_buffer = pb_alt_manager_create_buffer;
+ mgr->base.flush = pb_alt_manager_flush;
+ mgr->provider1 = provider1;
+ mgr->provider2 = provider2;
+
+ return &mgr->base;
+}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
new file mode 100644
index 0000000000..57d1ede45a
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
@@ -0,0 +1,385 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Buffer cache.
+ *
+ * \author Jose Fonseca <jrfonseca-at-tungstengraphics-dot-com>
+ * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_thread.h"
+#include "util/u_memory.h"
+#include "util/u_double_list.h"
+#include "util/u_time.h"
+
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+/**
+ * Convenience macro (type safe).
+ */
+#define SUPER(__derived) (&(__derived)->base)
+
+
+struct pb_cache_manager;
+
+
+/**
+ * Wrapper around a pipe buffer which adds delayed destruction.
+ */
+struct pb_cache_buffer
+{
+ struct pb_buffer base;
+
+ struct pb_buffer *buffer;
+ struct pb_cache_manager *mgr;
+
+ /** Caching time interval */
+ struct util_time start, end;
+
+ struct list_head head;
+};
+
+
+struct pb_cache_manager
+{
+ struct pb_manager base;
+
+ struct pb_manager *provider;
+ unsigned usecs;
+
+ pipe_mutex mutex;
+
+ struct list_head delayed;
+ pb_size numDelayed;
+};
+
+
+static INLINE struct pb_cache_buffer *
+pb_cache_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ return (struct pb_cache_buffer *)buf;
+}
+
+
+static INLINE struct pb_cache_manager *
+pb_cache_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct pb_cache_manager *)mgr;
+}
+
+
+/**
+ * Actually destroy the buffer.
+ */
+static INLINE void
+_pb_cache_buffer_destroy(struct pb_cache_buffer *buf)
+{
+ struct pb_cache_manager *mgr = buf->mgr;
+
+ LIST_DEL(&buf->head);
+ assert(mgr->numDelayed);
+ --mgr->numDelayed;
+ assert(!pipe_is_referenced(&buf->base.base.reference));
+ pb_reference(&buf->buffer, NULL);
+ FREE(buf);
+}
+
+
+/**
+ * Free as many cache buffers from the list head as possible.
+ */
+static void
+_pb_cache_buffer_list_check_free(struct pb_cache_manager *mgr)
+{
+ struct list_head *curr, *next;
+ struct pb_cache_buffer *buf;
+ struct util_time now;
+
+ util_time_get(&now);
+
+ curr = mgr->delayed.next;
+ next = curr->next;
+ while(curr != &mgr->delayed) {
+ buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
+
+ if(!util_time_timeout(&buf->start, &buf->end, &now))
+ break;
+
+ _pb_cache_buffer_destroy(buf);
+
+ curr = next;
+ next = curr->next;
+ }
+}
+
+
+static void
+pb_cache_buffer_destroy(struct pb_buffer *_buf)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ struct pb_cache_manager *mgr = buf->mgr;
+
+ pipe_mutex_lock(mgr->mutex);
+ assert(!pipe_is_referenced(&buf->base.base.reference));
+
+ _pb_cache_buffer_list_check_free(mgr);
+
+ util_time_get(&buf->start);
+ util_time_add(&buf->start, mgr->usecs, &buf->end);
+ LIST_ADDTAIL(&buf->head, &mgr->delayed);
+ ++mgr->numDelayed;
+ pipe_mutex_unlock(mgr->mutex);
+}
+
+
+static void *
+pb_cache_buffer_map(struct pb_buffer *_buf,
+ unsigned flags)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ return pb_map(buf->buffer, flags);
+}
+
+
+static void
+pb_cache_buffer_unmap(struct pb_buffer *_buf)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ pb_unmap(buf->buffer);
+}
+
+
+static enum pipe_error
+pb_cache_buffer_validate(struct pb_buffer *_buf,
+ struct pb_validate *vl,
+ unsigned flags)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ return pb_validate(buf->buffer, vl, flags);
+}
+
+
+static void
+pb_cache_buffer_fence(struct pb_buffer *_buf,
+ struct pipe_fence_handle *fence)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ pb_fence(buf->buffer, fence);
+}
+
+
+static void
+pb_cache_buffer_get_base_buffer(struct pb_buffer *_buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ pb_get_base_buffer(buf->buffer, base_buf, offset);
+}
+
+
+const struct pb_vtbl
+pb_cache_buffer_vtbl = {
+ pb_cache_buffer_destroy,
+ pb_cache_buffer_map,
+ pb_cache_buffer_unmap,
+ pb_cache_buffer_validate,
+ pb_cache_buffer_fence,
+ pb_cache_buffer_get_base_buffer
+};
+
+
+static INLINE boolean
+pb_cache_is_buffer_compat(struct pb_cache_buffer *buf,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ if(buf->base.base.size < size)
+ return FALSE;
+
+ /* be lenient with size */
+ if(buf->base.base.size >= 2*size)
+ return FALSE;
+
+ if(!pb_check_alignment(desc->alignment, buf->base.base.alignment))
+ return FALSE;
+
+ if(!pb_check_usage(desc->usage, buf->base.base.usage))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static struct pb_buffer *
+pb_cache_manager_create_buffer(struct pb_manager *_mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
+ struct pb_cache_buffer *buf;
+ struct pb_cache_buffer *curr_buf;
+ struct list_head *curr, *next;
+ struct util_time now;
+
+ pipe_mutex_lock(mgr->mutex);
+
+ buf = NULL;
+ curr = mgr->delayed.next;
+ next = curr->next;
+
+ /* search in the expired buffers, freeing them in the process */
+ util_time_get(&now);
+ while(curr != &mgr->delayed) {
+ curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
+ if(!buf && pb_cache_is_buffer_compat(curr_buf, size, desc))
+ buf = curr_buf;
+ else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now))
+ _pb_cache_buffer_destroy(curr_buf);
+ else
+ /* This buffer (and all hereafter) are still hot in cache */
+ break;
+ curr = next;
+ next = curr->next;
+ }
+
+ /* keep searching in the hot buffers */
+ if(!buf) {
+ while(curr != &mgr->delayed) {
+ curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
+ if(pb_cache_is_buffer_compat(curr_buf, size, desc)) {
+ buf = curr_buf;
+ break;
+ }
+ /* no need to check the timeout here */
+ curr = next;
+ next = curr->next;
+ }
+ }
+
+ if(buf) {
+ LIST_DEL(&buf->head);
+ pipe_mutex_unlock(mgr->mutex);
+ /* Increase refcount */
+ pb_reference((struct pb_buffer**)&buf, &buf->base);
+ return &buf->base;
+ }
+
+ pipe_mutex_unlock(mgr->mutex);
+
+ buf = CALLOC_STRUCT(pb_cache_buffer);
+ if(!buf)
+ return NULL;
+
+ buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
+ if(!buf->buffer) {
+ FREE(buf);
+ return NULL;
+ }
+
+ assert(pipe_is_referenced(&buf->buffer->base.reference));
+ assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment));
+ assert(pb_check_usage(desc->usage, buf->buffer->base.usage));
+ assert(buf->buffer->base.size >= size);
+
+ pipe_reference_init(&buf->base.base.reference, 1);
+ buf->base.base.alignment = buf->buffer->base.alignment;
+ buf->base.base.usage = buf->buffer->base.usage;
+ buf->base.base.size = buf->buffer->base.size;
+
+ buf->base.vtbl = &pb_cache_buffer_vtbl;
+ buf->mgr = mgr;
+
+ return &buf->base;
+}
+
+
+static void
+pb_cache_manager_flush(struct pb_manager *_mgr)
+{
+ struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
+ struct list_head *curr, *next;
+ struct pb_cache_buffer *buf;
+
+ pipe_mutex_lock(mgr->mutex);
+ curr = mgr->delayed.next;
+ next = curr->next;
+ while(curr != &mgr->delayed) {
+ buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
+ _pb_cache_buffer_destroy(buf);
+ curr = next;
+ next = curr->next;
+ }
+ pipe_mutex_unlock(mgr->mutex);
+
+ assert(mgr->provider->flush);
+ if(mgr->provider->flush)
+ mgr->provider->flush(mgr->provider);
+}
+
+
+static void
+pb_cache_manager_destroy(struct pb_manager *mgr)
+{
+ pb_cache_manager_flush(mgr);
+ FREE(mgr);
+}
+
+
+struct pb_manager *
+pb_cache_manager_create(struct pb_manager *provider,
+ unsigned usecs)
+{
+ struct pb_cache_manager *mgr;
+
+ if(!provider)
+ return NULL;
+
+ mgr = CALLOC_STRUCT(pb_cache_manager);
+ if (!mgr)
+ return NULL;
+
+ mgr->base.destroy = pb_cache_manager_destroy;
+ mgr->base.create_buffer = pb_cache_manager_create_buffer;
+ mgr->base.flush = pb_cache_manager_flush;
+ mgr->provider = provider;
+ mgr->usecs = usecs;
+ LIST_INITHEAD(&mgr->delayed);
+ mgr->numDelayed = 0;
+ pipe_mutex_init(mgr->mutex);
+
+ return &mgr->base;
+}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c
new file mode 100644
index 0000000000..1b4df28c70
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c
@@ -0,0 +1,494 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Debug buffer manager to detect buffer under- and overflows.
+ *
+ * \author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_thread.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_double_list.h"
+#include "util/u_time.h"
+#include "util/u_debug_stack.h"
+
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+#ifdef DEBUG
+
+
+#define PB_DEBUG_CREATE_BACKTRACE 8
+#define PB_DEBUG_MAP_BACKTRACE 8
+
+
+/**
+ * Convenience macro (type safe).
+ */
+#define SUPER(__derived) (&(__derived)->base)
+
+
+struct pb_debug_manager;
+
+
+/**
+ * Wrapper around a pipe buffer which adds delayed destruction.
+ */
+struct pb_debug_buffer
+{
+ struct pb_buffer base;
+
+ struct pb_buffer *buffer;
+ struct pb_debug_manager *mgr;
+
+ pb_size underflow_size;
+ pb_size overflow_size;
+
+ struct debug_stack_frame create_backtrace[PB_DEBUG_CREATE_BACKTRACE];
+
+ pipe_mutex mutex;
+ unsigned map_count;
+ struct debug_stack_frame map_backtrace[PB_DEBUG_MAP_BACKTRACE];
+
+ struct list_head head;
+};
+
+
+struct pb_debug_manager
+{
+ struct pb_manager base;
+
+ struct pb_manager *provider;
+
+ pb_size underflow_size;
+ pb_size overflow_size;
+
+ pipe_mutex mutex;
+ struct list_head list;
+};
+
+
+static INLINE struct pb_debug_buffer *
+pb_debug_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ return (struct pb_debug_buffer *)buf;
+}
+
+
+static INLINE struct pb_debug_manager *
+pb_debug_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct pb_debug_manager *)mgr;
+}
+
+
+static const uint8_t random_pattern[32] = {
+ 0xaf, 0xcf, 0xa5, 0xa2, 0xc2, 0x63, 0x15, 0x1a,
+ 0x7e, 0xe2, 0x7e, 0x84, 0x15, 0x49, 0xa2, 0x1e,
+ 0x49, 0x63, 0xf5, 0x52, 0x74, 0x66, 0x9e, 0xc4,
+ 0x6d, 0xcf, 0x2c, 0x4a, 0x74, 0xe6, 0xfd, 0x94
+};
+
+
+static INLINE void
+fill_random_pattern(uint8_t *dst, pb_size size)
+{
+ pb_size i = 0;
+ while(size--) {
+ *dst++ = random_pattern[i++];
+ i &= sizeof(random_pattern) - 1;
+ }
+}
+
+
+static INLINE boolean
+check_random_pattern(const uint8_t *dst, pb_size size,
+ pb_size *min_ofs, pb_size *max_ofs)
+{
+ boolean result = TRUE;
+ pb_size i;
+ *min_ofs = size;
+ *max_ofs = 0;
+ for(i = 0; i < size; ++i) {
+ if(*dst++ != random_pattern[i % sizeof(random_pattern)]) {
+ *min_ofs = MIN2(*min_ofs, i);
+ *max_ofs = MAX2(*max_ofs, i);
+ result = FALSE;
+ }
+ }
+ return result;
+}
+
+
+static void
+pb_debug_buffer_fill(struct pb_debug_buffer *buf)
+{
+ uint8_t *map;
+
+ map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
+ assert(map);
+ if(map) {
+ fill_random_pattern(map, buf->underflow_size);
+ fill_random_pattern(map + buf->underflow_size + buf->base.base.size,
+ buf->overflow_size);
+ pb_unmap(buf->buffer);
+ }
+}
+
+
+/**
+ * Check for under/over flows.
+ *
+ * Should be called with the buffer unmaped.
+ */
+static void
+pb_debug_buffer_check(struct pb_debug_buffer *buf)
+{
+ uint8_t *map;
+
+ map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+ assert(map);
+ if(map) {
+ boolean underflow, overflow;
+ pb_size min_ofs, max_ofs;
+
+ underflow = !check_random_pattern(map, buf->underflow_size,
+ &min_ofs, &max_ofs);
+ if(underflow) {
+ debug_printf("buffer underflow (offset -%u%s to -%u bytes) detected\n",
+ buf->underflow_size - min_ofs,
+ min_ofs == 0 ? "+" : "",
+ buf->underflow_size - max_ofs);
+ }
+
+ overflow = !check_random_pattern(map + buf->underflow_size + buf->base.base.size,
+ buf->overflow_size,
+ &min_ofs, &max_ofs);
+ if(overflow) {
+ debug_printf("buffer overflow (size %u plus offset %u to %u%s bytes) detected\n",
+ buf->base.base.size,
+ min_ofs,
+ max_ofs,
+ max_ofs == buf->overflow_size - 1 ? "+" : "");
+ }
+
+ if(underflow || overflow)
+ debug_backtrace_dump(buf->create_backtrace, PB_DEBUG_CREATE_BACKTRACE);
+
+ debug_assert(!underflow && !overflow);
+
+ /* re-fill if not aborted */
+ if(underflow)
+ fill_random_pattern(map, buf->underflow_size);
+ if(overflow)
+ fill_random_pattern(map + buf->underflow_size + buf->base.base.size,
+ buf->overflow_size);
+
+ pb_unmap(buf->buffer);
+ }
+}
+
+
+static void
+pb_debug_buffer_destroy(struct pb_buffer *_buf)
+{
+ struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
+ struct pb_debug_manager *mgr = buf->mgr;
+
+ assert(!pipe_is_referenced(&buf->base.base.reference));
+
+ pb_debug_buffer_check(buf);
+
+ pipe_mutex_lock(mgr->mutex);
+ LIST_DEL(&buf->head);
+ pipe_mutex_unlock(mgr->mutex);
+
+ pipe_mutex_destroy(buf->mutex);
+
+ pb_reference(&buf->buffer, NULL);
+ FREE(buf);
+}
+
+
+static void *
+pb_debug_buffer_map(struct pb_buffer *_buf,
+ unsigned flags)
+{
+ struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
+ void *map;
+
+ pb_debug_buffer_check(buf);
+
+ map = pb_map(buf->buffer, flags);
+ if(!map)
+ return NULL;
+
+ if(map) {
+ pipe_mutex_lock(buf->mutex);
+ ++buf->map_count;
+ debug_backtrace_capture(buf->map_backtrace, 1, PB_DEBUG_MAP_BACKTRACE);
+ pipe_mutex_unlock(buf->mutex);
+ }
+
+ return (uint8_t *)map + buf->underflow_size;
+}
+
+
+static void
+pb_debug_buffer_unmap(struct pb_buffer *_buf)
+{
+ struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
+
+ pipe_mutex_lock(buf->mutex);
+ assert(buf->map_count);
+ if(buf->map_count)
+ --buf->map_count;
+ pipe_mutex_unlock(buf->mutex);
+
+ pb_unmap(buf->buffer);
+
+ pb_debug_buffer_check(buf);
+}
+
+
+static void
+pb_debug_buffer_get_base_buffer(struct pb_buffer *_buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset)
+{
+ struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
+ pb_get_base_buffer(buf->buffer, base_buf, offset);
+ *offset += buf->underflow_size;
+}
+
+
+static enum pipe_error
+pb_debug_buffer_validate(struct pb_buffer *_buf,
+ struct pb_validate *vl,
+ unsigned flags)
+{
+ struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
+
+ pipe_mutex_lock(buf->mutex);
+ if(buf->map_count) {
+ debug_printf("%s: attempting to validate a mapped buffer\n", __FUNCTION__);
+ debug_printf("last map backtrace is\n");
+ debug_backtrace_dump(buf->map_backtrace, PB_DEBUG_MAP_BACKTRACE);
+ }
+ pipe_mutex_unlock(buf->mutex);
+
+ pb_debug_buffer_check(buf);
+
+ return pb_validate(buf->buffer, vl, flags);
+}
+
+
+static void
+pb_debug_buffer_fence(struct pb_buffer *_buf,
+ struct pipe_fence_handle *fence)
+{
+ struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
+ pb_fence(buf->buffer, fence);
+}
+
+
+const struct pb_vtbl
+pb_debug_buffer_vtbl = {
+ pb_debug_buffer_destroy,
+ pb_debug_buffer_map,
+ pb_debug_buffer_unmap,
+ pb_debug_buffer_validate,
+ pb_debug_buffer_fence,
+ pb_debug_buffer_get_base_buffer
+};
+
+
+static void
+pb_debug_manager_dump(struct pb_debug_manager *mgr)
+{
+ struct list_head *curr, *next;
+ struct pb_debug_buffer *buf;
+
+ pipe_mutex_lock(mgr->mutex);
+
+ curr = mgr->list.next;
+ next = curr->next;
+ while(curr != &mgr->list) {
+ buf = LIST_ENTRY(struct pb_debug_buffer, curr, head);
+
+ debug_printf("buffer = %p\n", buf);
+ debug_printf(" .size = %p\n", buf->base.base.size);
+ debug_backtrace_dump(buf->create_backtrace, PB_DEBUG_CREATE_BACKTRACE);
+
+ curr = next;
+ next = curr->next;
+ }
+
+ pipe_mutex_unlock(mgr->mutex);
+}
+
+
+static struct pb_buffer *
+pb_debug_manager_create_buffer(struct pb_manager *_mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct pb_debug_manager *mgr = pb_debug_manager(_mgr);
+ struct pb_debug_buffer *buf;
+ struct pb_desc real_desc;
+ pb_size real_size;
+
+ buf = CALLOC_STRUCT(pb_debug_buffer);
+ if(!buf)
+ return NULL;
+
+ real_size = mgr->underflow_size + size + mgr->overflow_size;
+ real_desc = *desc;
+ real_desc.usage |= PIPE_BUFFER_USAGE_CPU_WRITE;
+ real_desc.usage |= PIPE_BUFFER_USAGE_CPU_READ;
+
+ buf->buffer = mgr->provider->create_buffer(mgr->provider,
+ real_size,
+ &real_desc);
+ if(!buf->buffer) {
+ FREE(buf);
+#if 0
+ pipe_mutex_lock(mgr->mutex);
+ debug_printf("%s: failed to create buffer\n", __FUNCTION__);
+ if(!LIST_IS_EMPTY(&mgr->list))
+ pb_debug_manager_dump(mgr);
+ pipe_mutex_unlock(mgr->mutex);
+#endif
+ return NULL;
+ }
+
+ assert(pipe_is_referenced(&buf->buffer->base.reference));
+ assert(pb_check_alignment(real_desc.alignment, buf->buffer->base.alignment));
+ assert(pb_check_usage(real_desc.usage, buf->buffer->base.usage));
+ assert(buf->buffer->base.size >= real_size);
+
+ 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 = &pb_debug_buffer_vtbl;
+ buf->mgr = mgr;
+
+ buf->underflow_size = mgr->underflow_size;
+ buf->overflow_size = buf->buffer->base.size - buf->underflow_size - size;
+
+ debug_backtrace_capture(buf->create_backtrace, 1, PB_DEBUG_CREATE_BACKTRACE);
+
+ pb_debug_buffer_fill(buf);
+
+ pipe_mutex_init(buf->mutex);
+
+ pipe_mutex_lock(mgr->mutex);
+ LIST_ADDTAIL(&buf->head, &mgr->list);
+ pipe_mutex_unlock(mgr->mutex);
+
+ return &buf->base;
+}
+
+
+static void
+pb_debug_manager_flush(struct pb_manager *_mgr)
+{
+ struct pb_debug_manager *mgr = pb_debug_manager(_mgr);
+ assert(mgr->provider->flush);
+ if(mgr->provider->flush)
+ mgr->provider->flush(mgr->provider);
+}
+
+
+static void
+pb_debug_manager_destroy(struct pb_manager *_mgr)
+{
+ struct pb_debug_manager *mgr = pb_debug_manager(_mgr);
+
+ pipe_mutex_lock(mgr->mutex);
+ if(!LIST_IS_EMPTY(&mgr->list)) {
+ debug_printf("%s: unfreed buffers\n", __FUNCTION__);
+ pb_debug_manager_dump(mgr);
+ }
+ pipe_mutex_unlock(mgr->mutex);
+
+ pipe_mutex_destroy(mgr->mutex);
+ mgr->provider->destroy(mgr->provider);
+ FREE(mgr);
+}
+
+
+struct pb_manager *
+pb_debug_manager_create(struct pb_manager *provider,
+ pb_size underflow_size, pb_size overflow_size)
+{
+ struct pb_debug_manager *mgr;
+
+ if(!provider)
+ return NULL;
+
+ mgr = CALLOC_STRUCT(pb_debug_manager);
+ if (!mgr)
+ return NULL;
+
+ mgr->base.destroy = pb_debug_manager_destroy;
+ mgr->base.create_buffer = pb_debug_manager_create_buffer;
+ mgr->base.flush = pb_debug_manager_flush;
+ mgr->provider = provider;
+ mgr->underflow_size = underflow_size;
+ mgr->overflow_size = overflow_size;
+
+ pipe_mutex_init(mgr->mutex);
+ LIST_INITHEAD(&mgr->list);
+
+ return &mgr->base;
+}
+
+
+#else /* !DEBUG */
+
+
+struct pb_manager *
+pb_debug_manager_create(struct pb_manager *provider,
+ pb_size underflow_size, pb_size overflow_size)
+{
+ return provider;
+}
+
+
+#endif /* !DEBUG */
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c
new file mode 100644
index 0000000000..97dd1427fd
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c
@@ -0,0 +1,152 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * 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.
+ *
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * A buffer manager that wraps buffers in fenced buffers.
+ *
+ * \author Jose Fonseca <jrfonseca@tungstengraphics.dot.com>
+ */
+
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+
+#include "pb_buffer.h"
+#include "pb_buffer_fenced.h"
+#include "pb_bufmgr.h"
+
+
+struct fenced_pb_manager
+{
+ struct pb_manager base;
+
+ struct pb_manager *provider;
+
+ struct fenced_buffer_list *fenced_list;
+};
+
+
+static INLINE struct fenced_pb_manager *
+fenced_pb_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct fenced_pb_manager *)mgr;
+}
+
+
+static struct pb_buffer *
+fenced_bufmgr_create_buffer(struct pb_manager *mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct fenced_pb_manager *fenced_mgr = fenced_pb_manager(mgr);
+ struct pb_buffer *buf;
+ struct pb_buffer *fenced_buf;
+
+ /* check for free buffers before allocating new ones */
+ fenced_buffer_list_check_free(fenced_mgr->fenced_list, 0);
+
+ buf = fenced_mgr->provider->create_buffer(fenced_mgr->provider, size, desc);
+ if(!buf) {
+ /* try harder to get a buffer */
+ fenced_buffer_list_check_free(fenced_mgr->fenced_list, 1);
+
+ buf = fenced_mgr->provider->create_buffer(fenced_mgr->provider, size, desc);
+ if(!buf) {
+#if 0
+ fenced_buffer_list_dump(fenced_mgr->fenced_list);
+#endif
+
+ /* give up */
+ return NULL;
+ }
+ }
+
+ fenced_buf = fenced_buffer_create(fenced_mgr->fenced_list, buf);
+ if(!fenced_buf) {
+ pb_reference(&buf, NULL);
+ }
+
+ return fenced_buf;
+}
+
+
+static void
+fenced_bufmgr_flush(struct pb_manager *mgr)
+{
+ struct fenced_pb_manager *fenced_mgr = fenced_pb_manager(mgr);
+
+ fenced_buffer_list_check_free(fenced_mgr->fenced_list, TRUE);
+
+ assert(fenced_mgr->provider->flush);
+ if(fenced_mgr->provider->flush)
+ fenced_mgr->provider->flush(fenced_mgr->provider);
+}
+
+
+static void
+fenced_bufmgr_destroy(struct pb_manager *mgr)
+{
+ struct fenced_pb_manager *fenced_mgr = fenced_pb_manager(mgr);
+
+ fenced_buffer_list_destroy(fenced_mgr->fenced_list);
+
+ if(fenced_mgr->provider)
+ fenced_mgr->provider->destroy(fenced_mgr->provider);
+
+ FREE(fenced_mgr);
+}
+
+
+struct pb_manager *
+fenced_bufmgr_create(struct pb_manager *provider,
+ struct pb_fence_ops *ops)
+{
+ struct fenced_pb_manager *fenced_mgr;
+
+ if(!provider)
+ return NULL;
+
+ fenced_mgr = CALLOC_STRUCT(fenced_pb_manager);
+ if (!fenced_mgr)
+ return NULL;
+
+ fenced_mgr->base.destroy = fenced_bufmgr_destroy;
+ fenced_mgr->base.create_buffer = fenced_bufmgr_create_buffer;
+ fenced_mgr->base.flush = fenced_bufmgr_flush;
+
+ fenced_mgr->provider = provider;
+ fenced_mgr->fenced_list = fenced_buffer_list_create(ops);
+ if(!fenced_mgr->fenced_list) {
+ FREE(fenced_mgr);
+ return NULL;
+ }
+
+ return &fenced_mgr->base;
+}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c
new file mode 100644
index 0000000000..6400fc5b0a
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c
@@ -0,0 +1,318 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Buffer manager using the old texture memory manager.
+ *
+ * \author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_defines.h"
+#include "util/u_debug.h"
+#include "pipe/p_thread.h"
+#include "util/u_memory.h"
+#include "util/u_double_list.h"
+#include "util/u_mm.h"
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+/**
+ * Convenience macro (type safe).
+ */
+#define SUPER(__derived) (&(__derived)->base)
+
+
+struct mm_pb_manager
+{
+ struct pb_manager base;
+
+ pipe_mutex mutex;
+
+ pb_size size;
+ struct mem_block *heap;
+
+ pb_size align2;
+
+ struct pb_buffer *buffer;
+ void *map;
+};
+
+
+static INLINE struct mm_pb_manager *
+mm_pb_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct mm_pb_manager *)mgr;
+}
+
+
+struct mm_buffer
+{
+ struct pb_buffer base;
+
+ struct mm_pb_manager *mgr;
+
+ struct mem_block *block;
+};
+
+
+static INLINE struct mm_buffer *
+mm_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ return (struct mm_buffer *)buf;
+}
+
+
+static void
+mm_buffer_destroy(struct pb_buffer *buf)
+{
+ struct mm_buffer *mm_buf = mm_buffer(buf);
+ struct mm_pb_manager *mm = mm_buf->mgr;
+
+ assert(!pipe_is_referenced(&mm_buf->base.base.reference));
+
+ pipe_mutex_lock(mm->mutex);
+ u_mmFreeMem(mm_buf->block);
+ FREE(mm_buf);
+ pipe_mutex_unlock(mm->mutex);
+}
+
+
+static void *
+mm_buffer_map(struct pb_buffer *buf,
+ unsigned flags)
+{
+ struct mm_buffer *mm_buf = mm_buffer(buf);
+ struct mm_pb_manager *mm = mm_buf->mgr;
+
+ return (unsigned char *) mm->map + mm_buf->block->ofs;
+}
+
+
+static void
+mm_buffer_unmap(struct pb_buffer *buf)
+{
+ /* No-op */
+}
+
+
+static enum pipe_error
+mm_buffer_validate(struct pb_buffer *buf,
+ struct pb_validate *vl,
+ unsigned flags)
+{
+ struct mm_buffer *mm_buf = mm_buffer(buf);
+ struct mm_pb_manager *mm = mm_buf->mgr;
+ return pb_validate(mm->buffer, vl, flags);
+}
+
+
+static void
+mm_buffer_fence(struct pb_buffer *buf,
+ struct pipe_fence_handle *fence)
+{
+ struct mm_buffer *mm_buf = mm_buffer(buf);
+ struct mm_pb_manager *mm = mm_buf->mgr;
+ pb_fence(mm->buffer, fence);
+}
+
+
+static void
+mm_buffer_get_base_buffer(struct pb_buffer *buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset)
+{
+ struct mm_buffer *mm_buf = mm_buffer(buf);
+ struct mm_pb_manager *mm = mm_buf->mgr;
+ pb_get_base_buffer(mm->buffer, base_buf, offset);
+ *offset += mm_buf->block->ofs;
+}
+
+
+static const struct pb_vtbl
+mm_buffer_vtbl = {
+ mm_buffer_destroy,
+ mm_buffer_map,
+ mm_buffer_unmap,
+ mm_buffer_validate,
+ mm_buffer_fence,
+ mm_buffer_get_base_buffer
+};
+
+
+static struct pb_buffer *
+mm_bufmgr_create_buffer(struct pb_manager *mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct mm_pb_manager *mm = mm_pb_manager(mgr);
+ struct mm_buffer *mm_buf;
+
+ /* We don't handle alignments larger then the one initially setup */
+ assert(pb_check_alignment(desc->alignment, (pb_size)1 << mm->align2));
+ if(!pb_check_alignment(desc->alignment, (pb_size)1 << mm->align2))
+ return NULL;
+
+ pipe_mutex_lock(mm->mutex);
+
+ mm_buf = CALLOC_STRUCT(mm_buffer);
+ if (!mm_buf) {
+ pipe_mutex_unlock(mm->mutex);
+ return NULL;
+ }
+
+ pipe_reference_init(&mm_buf->base.base.reference, 1);
+ mm_buf->base.base.alignment = desc->alignment;
+ mm_buf->base.base.usage = desc->usage;
+ mm_buf->base.base.size = size;
+
+ mm_buf->base.vtbl = &mm_buffer_vtbl;
+
+ mm_buf->mgr = mm;
+
+ mm_buf->block = u_mmAllocMem(mm->heap, (int)size, (int)mm->align2, 0);
+ if(!mm_buf->block) {
+#if 0
+ debug_printf("warning: heap full\n");
+ mmDumpMemInfo(mm->heap);
+#endif
+ FREE(mm_buf);
+ pipe_mutex_unlock(mm->mutex);
+ return NULL;
+ }
+
+ /* Some sanity checks */
+ assert(0 <= (pb_size)mm_buf->block->ofs && (pb_size)mm_buf->block->ofs < mm->size);
+ assert(size <= (pb_size)mm_buf->block->size && (pb_size)mm_buf->block->ofs + (pb_size)mm_buf->block->size <= mm->size);
+
+ pipe_mutex_unlock(mm->mutex);
+ return SUPER(mm_buf);
+}
+
+
+static void
+mm_bufmgr_flush(struct pb_manager *mgr)
+{
+ /* No-op */
+}
+
+
+static void
+mm_bufmgr_destroy(struct pb_manager *mgr)
+{
+ struct mm_pb_manager *mm = mm_pb_manager(mgr);
+
+ pipe_mutex_lock(mm->mutex);
+
+ u_mmDestroy(mm->heap);
+
+ pb_unmap(mm->buffer);
+ pb_reference(&mm->buffer, NULL);
+
+ pipe_mutex_unlock(mm->mutex);
+
+ FREE(mgr);
+}
+
+
+struct pb_manager *
+mm_bufmgr_create_from_buffer(struct pb_buffer *buffer,
+ pb_size size, pb_size align2)
+{
+ struct mm_pb_manager *mm;
+
+ if(!buffer)
+ return NULL;
+
+ mm = CALLOC_STRUCT(mm_pb_manager);
+ if (!mm)
+ return NULL;
+
+ mm->base.destroy = mm_bufmgr_destroy;
+ mm->base.create_buffer = mm_bufmgr_create_buffer;
+ mm->base.flush = mm_bufmgr_flush;
+
+ mm->size = size;
+ mm->align2 = align2; /* 64-byte alignment */
+
+ pipe_mutex_init(mm->mutex);
+
+ mm->buffer = buffer;
+
+ mm->map = pb_map(mm->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ |
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ if(!mm->map)
+ goto failure;
+
+ mm->heap = u_mmInit(0, (int)size);
+ if (!mm->heap)
+ goto failure;
+
+ return SUPER(mm);
+
+failure:
+if(mm->heap)
+ u_mmDestroy(mm->heap);
+ if(mm->map)
+ pb_unmap(mm->buffer);
+ if(mm)
+ FREE(mm);
+ return NULL;
+}
+
+
+struct pb_manager *
+mm_bufmgr_create(struct pb_manager *provider,
+ pb_size size, pb_size align2)
+{
+ struct pb_buffer *buffer;
+ struct pb_manager *mgr;
+ struct pb_desc desc;
+
+ if(!provider)
+ return NULL;
+
+ memset(&desc, 0, sizeof(desc));
+ desc.alignment = 1 << align2;
+
+ buffer = provider->create_buffer(provider, size, &desc);
+ if (!buffer)
+ return NULL;
+
+ mgr = mm_bufmgr_create_from_buffer(buffer, size, align2);
+ if (!mgr) {
+ pb_reference(&buffer, NULL);
+ return NULL;
+ }
+
+ return mgr;
+}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_ondemand.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_ondemand.c
new file mode 100644
index 0000000000..cb32d25136
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_ondemand.c
@@ -0,0 +1,305 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * A variation of malloc buffers which get transferred to real graphics memory
+ * when there is an attempt to validate them.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+struct pb_ondemand_manager;
+
+
+struct pb_ondemand_buffer
+{
+ struct pb_buffer base;
+
+ struct pb_ondemand_manager *mgr;
+
+ /** Regular malloc'ed memory */
+ void *data;
+ unsigned mapcount;
+
+ /** Real buffer */
+ struct pb_buffer *buffer;
+ pb_size size;
+ struct pb_desc desc;
+};
+
+
+struct pb_ondemand_manager
+{
+ struct pb_manager base;
+
+ struct pb_manager *provider;
+};
+
+
+extern const struct pb_vtbl pb_ondemand_buffer_vtbl;
+
+static INLINE struct pb_ondemand_buffer *
+pb_ondemand_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ if (!buf)
+ return NULL;
+ assert(buf->vtbl == &pb_ondemand_buffer_vtbl);
+ return (struct pb_ondemand_buffer *)buf;
+}
+
+static INLINE struct pb_ondemand_manager *
+pb_ondemand_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct pb_ondemand_manager *)mgr;
+}
+
+
+static void
+pb_ondemand_buffer_destroy(struct pb_buffer *_buf)
+{
+ struct pb_ondemand_buffer *buf = pb_ondemand_buffer(_buf);
+
+ pb_reference(&buf->buffer, NULL);
+
+ align_free(buf->data);
+
+ FREE(buf);
+}
+
+
+static void *
+pb_ondemand_buffer_map(struct pb_buffer *_buf,
+ unsigned flags)
+{
+ struct pb_ondemand_buffer *buf = pb_ondemand_buffer(_buf);
+
+ if(buf->buffer) {
+ assert(!buf->data);
+ return pb_map(buf->buffer, flags);
+ }
+ else {
+ assert(buf->data);
+ ++buf->mapcount;
+ return buf->data;
+ }
+}
+
+
+static void
+pb_ondemand_buffer_unmap(struct pb_buffer *_buf)
+{
+ struct pb_ondemand_buffer *buf = pb_ondemand_buffer(_buf);
+
+ if(buf->buffer) {
+ assert(!buf->data);
+ pb_unmap(buf->buffer);
+ }
+ else {
+ assert(buf->data);
+ assert(buf->mapcount);
+ if(buf->mapcount)
+ --buf->mapcount;
+ }
+}
+
+
+static enum pipe_error
+pb_ondemand_buffer_instantiate(struct pb_ondemand_buffer *buf)
+{
+ if(!buf->buffer) {
+ struct pb_manager *provider = buf->mgr->provider;
+ uint8_t *map;
+
+ assert(!buf->mapcount);
+
+ buf->buffer = provider->create_buffer(provider, buf->size, &buf->desc);
+ if(!buf->buffer)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+ if(!map) {
+ pb_reference(&buf->buffer, NULL);
+ return PIPE_ERROR;
+ }
+
+ memcpy(map, buf->data, buf->size);
+
+ pb_unmap(buf->buffer);
+
+ if(!buf->mapcount) {
+ FREE(buf->data);
+ buf->data = NULL;
+ }
+ }
+
+ return PIPE_OK;
+}
+
+static enum pipe_error
+pb_ondemand_buffer_validate(struct pb_buffer *_buf,
+ struct pb_validate *vl,
+ unsigned flags)
+{
+ struct pb_ondemand_buffer *buf = pb_ondemand_buffer(_buf);
+ enum pipe_error ret;
+
+ assert(!buf->mapcount);
+ if(buf->mapcount)
+ return PIPE_ERROR;
+
+ ret = pb_ondemand_buffer_instantiate(buf);
+ if(ret != PIPE_OK)
+ return ret;
+
+ return pb_validate(buf->buffer, vl, flags);
+}
+
+
+static void
+pb_ondemand_buffer_fence(struct pb_buffer *_buf,
+ struct pipe_fence_handle *fence)
+{
+ struct pb_ondemand_buffer *buf = pb_ondemand_buffer(_buf);
+
+ assert(buf->buffer);
+ if(!buf->buffer)
+ return;
+
+ pb_fence(buf->buffer, fence);
+}
+
+
+static void
+pb_ondemand_buffer_get_base_buffer(struct pb_buffer *_buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset)
+{
+ struct pb_ondemand_buffer *buf = pb_ondemand_buffer(_buf);
+
+ if(pb_ondemand_buffer_instantiate(buf) != PIPE_OK) {
+ assert(0);
+ *base_buf = &buf->base;
+ *offset = 0;
+ return;
+ }
+
+ pb_get_base_buffer(buf->buffer, base_buf, offset);
+}
+
+
+const struct pb_vtbl
+pb_ondemand_buffer_vtbl = {
+ pb_ondemand_buffer_destroy,
+ pb_ondemand_buffer_map,
+ pb_ondemand_buffer_unmap,
+ pb_ondemand_buffer_validate,
+ pb_ondemand_buffer_fence,
+ pb_ondemand_buffer_get_base_buffer
+};
+
+
+static struct pb_buffer *
+pb_ondemand_manager_create_buffer(struct pb_manager *_mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct pb_ondemand_manager *mgr = pb_ondemand_manager(_mgr);
+ struct pb_ondemand_buffer *buf;
+
+ buf = CALLOC_STRUCT(pb_ondemand_buffer);
+ if(!buf)
+ return NULL;
+
+ 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 = &pb_ondemand_buffer_vtbl;
+
+ buf->mgr = mgr;
+
+ buf->data = align_malloc(size, desc->alignment < sizeof(void*) ? sizeof(void*) : desc->alignment);
+ if(!buf->data) {
+ FREE(buf);
+ return NULL;
+ }
+
+ buf->size = size;
+ buf->desc = *desc;
+
+ return &buf->base;
+}
+
+
+static void
+pb_ondemand_manager_flush(struct pb_manager *_mgr)
+{
+ struct pb_ondemand_manager *mgr = pb_ondemand_manager(_mgr);
+
+ mgr->provider->flush(mgr->provider);
+}
+
+
+static void
+pb_ondemand_manager_destroy(struct pb_manager *_mgr)
+{
+ struct pb_ondemand_manager *mgr = pb_ondemand_manager(_mgr);
+
+ FREE(mgr);
+}
+
+
+struct pb_manager *
+pb_ondemand_manager_create(struct pb_manager *provider)
+{
+ struct pb_ondemand_manager *mgr;
+
+ if(!provider)
+ return NULL;
+
+ mgr = CALLOC_STRUCT(pb_ondemand_manager);
+ if(!mgr)
+ return NULL;
+
+ mgr->base.destroy = pb_ondemand_manager_destroy;
+ mgr->base.create_buffer = pb_ondemand_manager_create_buffer;
+ mgr->base.flush = pb_ondemand_manager_flush;
+
+ mgr->provider = provider;
+
+ return &mgr->base;
+}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c
new file mode 100644
index 0000000000..7fd65ed226
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c
@@ -0,0 +1,321 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * 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.
+ *
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Batch buffer pool management.
+ *
+ * \author Jose Fonseca <jrfonseca-at-tungstengraphics-dot-com>
+ * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_thread.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "util/u_double_list.h"
+
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+/**
+ * Convenience macro (type safe).
+ */
+#define SUPER(__derived) (&(__derived)->base)
+
+
+struct pool_pb_manager
+{
+ struct pb_manager base;
+
+ pipe_mutex mutex;
+
+ pb_size bufSize;
+ pb_size bufAlign;
+
+ pb_size numFree;
+ pb_size numTot;
+
+ struct list_head free;
+
+ struct pb_buffer *buffer;
+ void *map;
+
+ struct pool_buffer *bufs;
+};
+
+
+static INLINE struct pool_pb_manager *
+pool_pb_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct pool_pb_manager *)mgr;
+}
+
+
+struct pool_buffer
+{
+ struct pb_buffer base;
+
+ struct pool_pb_manager *mgr;
+
+ struct list_head head;
+
+ pb_size start;
+};
+
+
+static INLINE struct pool_buffer *
+pool_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ return (struct pool_buffer *)buf;
+}
+
+
+
+static void
+pool_buffer_destroy(struct pb_buffer *buf)
+{
+ struct pool_buffer *pool_buf = pool_buffer(buf);
+ struct pool_pb_manager *pool = pool_buf->mgr;
+
+ assert(!pipe_is_referenced(&pool_buf->base.base.reference));
+
+ pipe_mutex_lock(pool->mutex);
+ LIST_ADD(&pool_buf->head, &pool->free);
+ pool->numFree++;
+ pipe_mutex_unlock(pool->mutex);
+}
+
+
+static void *
+pool_buffer_map(struct pb_buffer *buf, unsigned flags)
+{
+ struct pool_buffer *pool_buf = pool_buffer(buf);
+ struct pool_pb_manager *pool = pool_buf->mgr;
+ void *map;
+
+ pipe_mutex_lock(pool->mutex);
+ map = (unsigned char *) pool->map + pool_buf->start;
+ pipe_mutex_unlock(pool->mutex);
+ return map;
+}
+
+
+static void
+pool_buffer_unmap(struct pb_buffer *buf)
+{
+ /* No-op */
+}
+
+
+static enum pipe_error
+pool_buffer_validate(struct pb_buffer *buf,
+ struct pb_validate *vl,
+ unsigned flags)
+{
+ struct pool_buffer *pool_buf = pool_buffer(buf);
+ struct pool_pb_manager *pool = pool_buf->mgr;
+ return pb_validate(pool->buffer, vl, flags);
+}
+
+
+static void
+pool_buffer_fence(struct pb_buffer *buf,
+ struct pipe_fence_handle *fence)
+{
+ struct pool_buffer *pool_buf = pool_buffer(buf);
+ struct pool_pb_manager *pool = pool_buf->mgr;
+ pb_fence(pool->buffer, fence);
+}
+
+
+static void
+pool_buffer_get_base_buffer(struct pb_buffer *buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset)
+{
+ struct pool_buffer *pool_buf = pool_buffer(buf);
+ struct pool_pb_manager *pool = pool_buf->mgr;
+ pb_get_base_buffer(pool->buffer, base_buf, offset);
+ *offset += pool_buf->start;
+}
+
+
+static const struct pb_vtbl
+pool_buffer_vtbl = {
+ pool_buffer_destroy,
+ pool_buffer_map,
+ pool_buffer_unmap,
+ pool_buffer_validate,
+ pool_buffer_fence,
+ pool_buffer_get_base_buffer
+};
+
+
+static struct pb_buffer *
+pool_bufmgr_create_buffer(struct pb_manager *mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct pool_pb_manager *pool = pool_pb_manager(mgr);
+ struct pool_buffer *pool_buf;
+ struct list_head *item;
+
+ assert(size == pool->bufSize);
+ assert(pool->bufAlign % desc->alignment == 0);
+
+ pipe_mutex_lock(pool->mutex);
+
+ if (pool->numFree == 0) {
+ pipe_mutex_unlock(pool->mutex);
+ debug_printf("warning: out of fixed size buffer objects\n");
+ return NULL;
+ }
+
+ item = pool->free.next;
+
+ if (item == &pool->free) {
+ pipe_mutex_unlock(pool->mutex);
+ debug_printf("error: fixed size buffer pool corruption\n");
+ return NULL;
+ }
+
+ LIST_DEL(item);
+ --pool->numFree;
+
+ pipe_mutex_unlock(pool->mutex);
+
+ pool_buf = LIST_ENTRY(struct pool_buffer, item, head);
+ assert(!pipe_is_referenced(&pool_buf->base.base.reference));
+ pipe_reference_init(&pool_buf->base.base.reference, 1);
+ pool_buf->base.base.alignment = desc->alignment;
+ pool_buf->base.base.usage = desc->usage;
+
+ return SUPER(pool_buf);
+}
+
+
+static void
+pool_bufmgr_flush(struct pb_manager *mgr)
+{
+ /* No-op */
+}
+
+
+static void
+pool_bufmgr_destroy(struct pb_manager *mgr)
+{
+ struct pool_pb_manager *pool = pool_pb_manager(mgr);
+ pipe_mutex_lock(pool->mutex);
+
+ FREE(pool->bufs);
+
+ pb_unmap(pool->buffer);
+ pb_reference(&pool->buffer, NULL);
+
+ pipe_mutex_unlock(pool->mutex);
+
+ FREE(mgr);
+}
+
+
+struct pb_manager *
+pool_bufmgr_create(struct pb_manager *provider,
+ pb_size numBufs,
+ pb_size bufSize,
+ const struct pb_desc *desc)
+{
+ struct pool_pb_manager *pool;
+ struct pool_buffer *pool_buf;
+ pb_size i;
+
+ if(!provider)
+ return NULL;
+
+ pool = CALLOC_STRUCT(pool_pb_manager);
+ if (!pool)
+ return NULL;
+
+ pool->base.destroy = pool_bufmgr_destroy;
+ pool->base.create_buffer = pool_bufmgr_create_buffer;
+ pool->base.flush = pool_bufmgr_flush;
+
+ LIST_INITHEAD(&pool->free);
+
+ pool->numTot = numBufs;
+ pool->numFree = numBufs;
+ pool->bufSize = bufSize;
+ pool->bufAlign = desc->alignment;
+
+ pipe_mutex_init(pool->mutex);
+
+ pool->buffer = provider->create_buffer(provider, numBufs*bufSize, desc);
+ if (!pool->buffer)
+ goto failure;
+
+ pool->map = pb_map(pool->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ |
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ if(!pool->map)
+ goto failure;
+
+ pool->bufs = (struct pool_buffer *)CALLOC(numBufs, sizeof(*pool->bufs));
+ if (!pool->bufs)
+ goto failure;
+
+ pool_buf = pool->bufs;
+ for (i = 0; i < numBufs; ++i) {
+ pipe_reference_init(&pool_buf->base.base.reference, 0);
+ pool_buf->base.base.alignment = 0;
+ pool_buf->base.base.usage = 0;
+ pool_buf->base.base.size = bufSize;
+ pool_buf->base.vtbl = &pool_buffer_vtbl;
+ pool_buf->mgr = pool;
+ pool_buf->start = i * bufSize;
+ LIST_ADDTAIL(&pool_buf->head, &pool->free);
+ pool_buf++;
+ }
+
+ return SUPER(pool);
+
+failure:
+ if(pool->bufs)
+ FREE(pool->bufs);
+ if(pool->map)
+ pb_unmap(pool->buffer);
+ if(pool->buffer)
+ pb_reference(&pool->buffer, NULL);
+ if(pool)
+ FREE(pool);
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c
new file mode 100644
index 0000000000..e7352e90db
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c
@@ -0,0 +1,584 @@
+/**************************************************************************
+ *
+ * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * 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.
+ *
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * S-lab pool implementation.
+ *
+ * @sa http://en.wikipedia.org/wiki/Slab_allocation
+ *
+ * @author Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_error.h"
+#include "util/u_debug.h"
+#include "pipe/p_thread.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "util/u_double_list.h"
+#include "util/u_time.h"
+
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+struct pb_slab;
+
+
+/**
+ * Buffer in a slab.
+ *
+ * Sub-allocation of a contiguous buffer.
+ */
+struct pb_slab_buffer
+{
+ struct pb_buffer base;
+
+ struct pb_slab *slab;
+
+ struct list_head head;
+
+ unsigned mapCount;
+
+ /** Offset relative to the start of the slab buffer. */
+ pb_size start;
+
+ /** Use when validating, to signal that all mappings are finished */
+ /* TODO: Actually validation does not reach this stage yet */
+ pipe_condvar event;
+};
+
+
+/**
+ * Slab -- a contiguous piece of memory.
+ */
+struct pb_slab
+{
+ struct list_head head;
+ struct list_head freeBuffers;
+ pb_size numBuffers;
+ pb_size numFree;
+
+ struct pb_slab_buffer *buffers;
+ struct pb_slab_manager *mgr;
+
+ /** Buffer from the provider */
+ struct pb_buffer *bo;
+
+ void *virtual;
+};
+
+
+/**
+ * It adds/removes slabs as needed in order to meet the allocation/destruction
+ * of individual buffers.
+ */
+struct pb_slab_manager
+{
+ struct pb_manager base;
+
+ /** From where we get our buffers */
+ struct pb_manager *provider;
+
+ /** Size of the buffers we hand on downstream */
+ pb_size bufSize;
+
+ /** Size of the buffers we request upstream */
+ pb_size slabSize;
+
+ /**
+ * Alignment, usage to be used to allocate the slab buffers.
+ *
+ * We can only provide buffers which are consistent (in alignment, usage)
+ * with this description.
+ */
+ struct pb_desc desc;
+
+ /**
+ * Partial slabs
+ *
+ * Full slabs are not stored in any list. Empty slabs are destroyed
+ * immediatly.
+ */
+ struct list_head slabs;
+
+ pipe_mutex mutex;
+};
+
+
+/**
+ * Wrapper around several slabs, therefore capable of handling buffers of
+ * multiple sizes.
+ *
+ * This buffer manager just dispatches buffer allocations to the appropriate slab
+ * manager, according to the requested buffer size, or by passes the slab
+ * managers altogether for even greater sizes.
+ *
+ * The data of this structure remains constant after
+ * initialization and thus needs no mutex protection.
+ */
+struct pb_slab_range_manager
+{
+ struct pb_manager base;
+
+ struct pb_manager *provider;
+
+ pb_size minBufSize;
+ pb_size maxBufSize;
+
+ /** @sa pb_slab_manager::desc */
+ struct pb_desc desc;
+
+ unsigned numBuckets;
+ pb_size *bucketSizes;
+
+ /** Array of pb_slab_manager, one for each bucket size */
+ struct pb_manager **buckets;
+};
+
+
+static INLINE struct pb_slab_buffer *
+pb_slab_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ return (struct pb_slab_buffer *)buf;
+}
+
+
+static INLINE struct pb_slab_manager *
+pb_slab_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct pb_slab_manager *)mgr;
+}
+
+
+static INLINE struct pb_slab_range_manager *
+pb_slab_range_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct pb_slab_range_manager *)mgr;
+}
+
+
+/**
+ * Delete a buffer from the slab delayed list and put
+ * it on the slab FREE list.
+ */
+static void
+pb_slab_buffer_destroy(struct pb_buffer *_buf)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+ struct pb_slab *slab = buf->slab;
+ struct pb_slab_manager *mgr = slab->mgr;
+ struct list_head *list = &buf->head;
+
+ pipe_mutex_lock(mgr->mutex);
+
+ assert(!pipe_is_referenced(&buf->base.base.reference));
+
+ buf->mapCount = 0;
+
+ LIST_DEL(list);
+ LIST_ADDTAIL(list, &slab->freeBuffers);
+ slab->numFree++;
+
+ if (slab->head.next == &slab->head)
+ LIST_ADDTAIL(&slab->head, &mgr->slabs);
+
+ /* If the slab becomes totally empty, free it */
+ if (slab->numFree == slab->numBuffers) {
+ list = &slab->head;
+ LIST_DELINIT(list);
+ pb_reference(&slab->bo, NULL);
+ FREE(slab->buffers);
+ FREE(slab);
+ }
+
+ pipe_mutex_unlock(mgr->mutex);
+}
+
+
+static void *
+pb_slab_buffer_map(struct pb_buffer *_buf,
+ unsigned flags)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+
+ ++buf->mapCount;
+ return (void *) ((uint8_t *) buf->slab->virtual + buf->start);
+}
+
+
+static void
+pb_slab_buffer_unmap(struct pb_buffer *_buf)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+
+ --buf->mapCount;
+ if (buf->mapCount == 0)
+ pipe_condvar_broadcast(buf->event);
+}
+
+
+static enum pipe_error
+pb_slab_buffer_validate(struct pb_buffer *_buf,
+ struct pb_validate *vl,
+ unsigned flags)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+ return pb_validate(buf->slab->bo, vl, flags);
+}
+
+
+static void
+pb_slab_buffer_fence(struct pb_buffer *_buf,
+ struct pipe_fence_handle *fence)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+ pb_fence(buf->slab->bo, fence);
+}
+
+
+static void
+pb_slab_buffer_get_base_buffer(struct pb_buffer *_buf,
+ struct pb_buffer **base_buf,
+ pb_size *offset)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+ pb_get_base_buffer(buf->slab->bo, base_buf, offset);
+ *offset += buf->start;
+}
+
+
+static const struct pb_vtbl
+pb_slab_buffer_vtbl = {
+ pb_slab_buffer_destroy,
+ pb_slab_buffer_map,
+ pb_slab_buffer_unmap,
+ pb_slab_buffer_validate,
+ pb_slab_buffer_fence,
+ pb_slab_buffer_get_base_buffer
+};
+
+
+/**
+ * Create a new slab.
+ *
+ * Called when we ran out of free slabs.
+ */
+static enum pipe_error
+pb_slab_create(struct pb_slab_manager *mgr)
+{
+ struct pb_slab *slab;
+ struct pb_slab_buffer *buf;
+ unsigned numBuffers;
+ unsigned i;
+ enum pipe_error ret;
+
+ slab = CALLOC_STRUCT(pb_slab);
+ if (!slab)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ slab->bo = mgr->provider->create_buffer(mgr->provider, mgr->slabSize, &mgr->desc);
+ if(!slab->bo) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
+ goto out_err0;
+ }
+
+ /* Note down the slab virtual address. All mappings are accessed directly
+ * through this address so it is required that the buffer is pinned. */
+ slab->virtual = pb_map(slab->bo,
+ PIPE_BUFFER_USAGE_CPU_READ |
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ if(!slab->virtual) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
+ goto out_err1;
+ }
+ pb_unmap(slab->bo);
+
+ numBuffers = slab->bo->base.size / mgr->bufSize;
+
+ slab->buffers = CALLOC(numBuffers, sizeof(*slab->buffers));
+ if (!slab->buffers) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
+ goto out_err1;
+ }
+
+ LIST_INITHEAD(&slab->head);
+ LIST_INITHEAD(&slab->freeBuffers);
+ slab->numBuffers = numBuffers;
+ slab->numFree = 0;
+ slab->mgr = mgr;
+
+ buf = slab->buffers;
+ for (i=0; i < numBuffers; ++i) {
+ pipe_reference_init(&buf->base.base.reference, 0);
+ buf->base.base.size = mgr->bufSize;
+ buf->base.base.alignment = 0;
+ buf->base.base.usage = 0;
+ buf->base.vtbl = &pb_slab_buffer_vtbl;
+ buf->slab = slab;
+ buf->start = i* mgr->bufSize;
+ buf->mapCount = 0;
+ pipe_condvar_init(buf->event);
+ LIST_ADDTAIL(&buf->head, &slab->freeBuffers);
+ slab->numFree++;
+ buf++;
+ }
+
+ /* Add this slab to the list of partial slabs */
+ LIST_ADDTAIL(&slab->head, &mgr->slabs);
+
+ return PIPE_OK;
+
+out_err1:
+ pb_reference(&slab->bo, NULL);
+out_err0:
+ FREE(slab);
+ return ret;
+}
+
+
+static struct pb_buffer *
+pb_slab_manager_create_buffer(struct pb_manager *_mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct pb_slab_manager *mgr = pb_slab_manager(_mgr);
+ static struct pb_slab_buffer *buf;
+ struct pb_slab *slab;
+ struct list_head *list;
+
+ /* check size */
+ assert(size <= mgr->bufSize);
+ if(size > mgr->bufSize)
+ return NULL;
+
+ /* check if we can provide the requested alignment */
+ assert(pb_check_alignment(desc->alignment, mgr->desc.alignment));
+ if(!pb_check_alignment(desc->alignment, mgr->desc.alignment))
+ return NULL;
+ assert(pb_check_alignment(desc->alignment, mgr->bufSize));
+ if(!pb_check_alignment(desc->alignment, mgr->bufSize))
+ return NULL;
+
+ assert(pb_check_usage(desc->usage, mgr->desc.usage));
+ if(!pb_check_usage(desc->usage, mgr->desc.usage))
+ return NULL;
+
+ pipe_mutex_lock(mgr->mutex);
+
+ /* Create a new slab, if we run out of partial slabs */
+ if (mgr->slabs.next == &mgr->slabs) {
+ (void) pb_slab_create(mgr);
+ if (mgr->slabs.next == &mgr->slabs) {
+ pipe_mutex_unlock(mgr->mutex);
+ return NULL;
+ }
+ }
+
+ /* Allocate the buffer from a partial (or just created) slab */
+ list = mgr->slabs.next;
+ slab = LIST_ENTRY(struct pb_slab, list, head);
+
+ /* If totally full remove from the partial slab list */
+ if (--slab->numFree == 0)
+ LIST_DELINIT(list);
+
+ list = slab->freeBuffers.next;
+ LIST_DELINIT(list);
+
+ pipe_mutex_unlock(mgr->mutex);
+ buf = LIST_ENTRY(struct pb_slab_buffer, list, head);
+
+ pipe_reference_init(&buf->base.base.reference, 1);
+ buf->base.base.alignment = desc->alignment;
+ buf->base.base.usage = desc->usage;
+
+ return &buf->base;
+}
+
+
+static void
+pb_slab_manager_flush(struct pb_manager *_mgr)
+{
+ struct pb_slab_manager *mgr = pb_slab_manager(_mgr);
+
+ assert(mgr->provider->flush);
+ if(mgr->provider->flush)
+ mgr->provider->flush(mgr->provider);
+}
+
+
+static void
+pb_slab_manager_destroy(struct pb_manager *_mgr)
+{
+ struct pb_slab_manager *mgr = pb_slab_manager(_mgr);
+
+ /* TODO: cleanup all allocated buffers */
+ FREE(mgr);
+}
+
+
+struct pb_manager *
+pb_slab_manager_create(struct pb_manager *provider,
+ pb_size bufSize,
+ pb_size slabSize,
+ const struct pb_desc *desc)
+{
+ struct pb_slab_manager *mgr;
+
+ mgr = CALLOC_STRUCT(pb_slab_manager);
+ if (!mgr)
+ return NULL;
+
+ mgr->base.destroy = pb_slab_manager_destroy;
+ mgr->base.create_buffer = pb_slab_manager_create_buffer;
+ mgr->base.flush = pb_slab_manager_flush;
+
+ mgr->provider = provider;
+ mgr->bufSize = bufSize;
+ mgr->slabSize = slabSize;
+ mgr->desc = *desc;
+
+ LIST_INITHEAD(&mgr->slabs);
+
+ pipe_mutex_init(mgr->mutex);
+
+ return &mgr->base;
+}
+
+
+static struct pb_buffer *
+pb_slab_range_manager_create_buffer(struct pb_manager *_mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct pb_slab_range_manager *mgr = pb_slab_range_manager(_mgr);
+ pb_size bufSize;
+ unsigned i;
+
+ bufSize = mgr->minBufSize;
+ for (i = 0; i < mgr->numBuckets; ++i) {
+ if(bufSize >= size)
+ return mgr->buckets[i]->create_buffer(mgr->buckets[i], size, desc);
+ bufSize *= 2;
+ }
+
+ /* Fall back to allocate a buffer object directly from the provider. */
+ return mgr->provider->create_buffer(mgr->provider, size, desc);
+}
+
+
+static void
+pb_slab_range_manager_flush(struct pb_manager *_mgr)
+{
+ struct pb_slab_range_manager *mgr = pb_slab_range_manager(_mgr);
+
+ /* Individual slabs don't hold any temporary buffers so no need to call them */
+
+ assert(mgr->provider->flush);
+ if(mgr->provider->flush)
+ mgr->provider->flush(mgr->provider);
+}
+
+
+static void
+pb_slab_range_manager_destroy(struct pb_manager *_mgr)
+{
+ struct pb_slab_range_manager *mgr = pb_slab_range_manager(_mgr);
+ unsigned i;
+
+ for (i = 0; i < mgr->numBuckets; ++i)
+ mgr->buckets[i]->destroy(mgr->buckets[i]);
+ FREE(mgr->buckets);
+ FREE(mgr->bucketSizes);
+ FREE(mgr);
+}
+
+
+struct pb_manager *
+pb_slab_range_manager_create(struct pb_manager *provider,
+ pb_size minBufSize,
+ pb_size maxBufSize,
+ pb_size slabSize,
+ const struct pb_desc *desc)
+{
+ struct pb_slab_range_manager *mgr;
+ pb_size bufSize;
+ unsigned i;
+
+ if(!provider)
+ return NULL;
+
+ mgr = CALLOC_STRUCT(pb_slab_range_manager);
+ if (!mgr)
+ goto out_err0;
+
+ mgr->base.destroy = pb_slab_range_manager_destroy;
+ mgr->base.create_buffer = pb_slab_range_manager_create_buffer;
+ mgr->base.flush = pb_slab_range_manager_flush;
+
+ mgr->provider = provider;
+ mgr->minBufSize = minBufSize;
+ mgr->maxBufSize = maxBufSize;
+
+ mgr->numBuckets = 1;
+ bufSize = minBufSize;
+ while(bufSize < maxBufSize) {
+ bufSize *= 2;
+ ++mgr->numBuckets;
+ }
+
+ mgr->buckets = CALLOC(mgr->numBuckets, sizeof(*mgr->buckets));
+ if (!mgr->buckets)
+ goto out_err1;
+
+ bufSize = minBufSize;
+ for (i = 0; i < mgr->numBuckets; ++i) {
+ mgr->buckets[i] = pb_slab_manager_create(provider, bufSize, slabSize, desc);
+ if(!mgr->buckets[i])
+ goto out_err2;
+ bufSize *= 2;
+ }
+
+ return &mgr->base;
+
+out_err2:
+ for (i = 0; i < mgr->numBuckets; ++i)
+ if(mgr->buckets[i])
+ mgr->buckets[i]->destroy(mgr->buckets[i]);
+ FREE(mgr->buckets);
+out_err1:
+ FREE(mgr);
+out_err0:
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.c b/src/gallium/auxiliary/pipebuffer/pb_validate.c
new file mode 100644
index 0000000000..150fd50618
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_validate.c
@@ -0,0 +1,193 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Buffer validation.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_error.h"
+#include "util/u_memory.h"
+#include "util/u_debug.h"
+
+#include "pb_buffer.h"
+#include "pb_buffer_fenced.h"
+#include "pb_validate.h"
+
+
+#define PB_VALIDATE_INITIAL_SIZE 1 /* 512 */
+
+
+struct pb_validate_entry
+{
+ struct pb_buffer *buf;
+ unsigned flags;
+};
+
+
+struct pb_validate
+{
+ struct pb_validate_entry *entries;
+ unsigned used;
+ unsigned size;
+};
+
+
+enum pipe_error
+pb_validate_add_buffer(struct pb_validate *vl,
+ struct pb_buffer *buf,
+ unsigned flags)
+{
+ assert(buf);
+ if(!buf)
+ return PIPE_ERROR;
+
+ assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE);
+ assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE));
+ flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE;
+
+ /* We only need to store one reference for each buffer, so avoid storing
+ * consecutive references for the same buffer. It might not be the most
+ * common pattern, but it is easy to implement.
+ */
+ if(vl->used && vl->entries[vl->used - 1].buf == buf) {
+ vl->entries[vl->used - 1].flags |= flags;
+ return PIPE_OK;
+ }
+
+ /* Grow the table */
+ if(vl->used == vl->size) {
+ unsigned new_size;
+ struct pb_validate_entry *new_entries;
+
+ new_size = vl->size * 2;
+ if(!new_size)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ new_entries = (struct pb_validate_entry *)REALLOC(vl->entries,
+ vl->size*sizeof(struct pb_validate_entry),
+ new_size*sizeof(struct pb_validate_entry));
+ if(!new_entries)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ memset(new_entries + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_validate_entry));
+
+ vl->size = new_size;
+ vl->entries = new_entries;
+ }
+
+ assert(!vl->entries[vl->used].buf);
+ pb_reference(&vl->entries[vl->used].buf, buf);
+ vl->entries[vl->used].flags = flags;
+ ++vl->used;
+
+ return PIPE_OK;
+}
+
+
+enum pipe_error
+pb_validate_foreach(struct pb_validate *vl,
+ enum pipe_error (*callback)(struct pb_buffer *buf, void *data),
+ void *data)
+{
+ unsigned i;
+ for(i = 0; i < vl->used; ++i) {
+ enum pipe_error ret;
+ ret = callback(vl->entries[i].buf, data);
+ if(ret != PIPE_OK)
+ return ret;
+ }
+ return PIPE_OK;
+}
+
+
+enum pipe_error
+pb_validate_validate(struct pb_validate *vl)
+{
+ unsigned i;
+
+ for(i = 0; i < vl->used; ++i) {
+ enum pipe_error ret;
+ ret = pb_validate(vl->entries[i].buf, vl, vl->entries[i].flags);
+ if(ret != PIPE_OK) {
+ while(i--)
+ pb_validate(vl->entries[i].buf, NULL, 0);
+ return ret;
+ }
+ }
+
+ return PIPE_OK;
+}
+
+
+void
+pb_validate_fence(struct pb_validate *vl,
+ struct pipe_fence_handle *fence)
+{
+ unsigned i;
+ for(i = 0; i < vl->used; ++i) {
+ pb_fence(vl->entries[i].buf, fence);
+ pb_reference(&vl->entries[i].buf, NULL);
+ }
+ vl->used = 0;
+}
+
+
+void
+pb_validate_destroy(struct pb_validate *vl)
+{
+ unsigned i;
+ for(i = 0; i < vl->used; ++i)
+ pb_reference(&vl->entries[i].buf, NULL);
+ FREE(vl->entries);
+ FREE(vl);
+}
+
+
+struct pb_validate *
+pb_validate_create()
+{
+ struct pb_validate *vl;
+
+ vl = CALLOC_STRUCT(pb_validate);
+ if(!vl)
+ return NULL;
+
+ vl->size = PB_VALIDATE_INITIAL_SIZE;
+ vl->entries = (struct pb_validate_entry *)CALLOC(vl->size, sizeof(struct pb_validate_entry));
+ if(!vl->entries) {
+ FREE(vl);
+ return NULL;
+ }
+
+ return vl;
+}
+
diff --git a/src/gallium/auxiliary/pipebuffer/pb_validate.h b/src/gallium/auxiliary/pipebuffer/pb_validate.h
new file mode 100644
index 0000000000..dfb84df1ce
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_validate.h
@@ -0,0 +1,97 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Buffer validation.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef PB_VALIDATE_H_
+#define PB_VALIDATE_H_
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_error.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pb_buffer;
+struct pipe_fence_handle;
+
+
+/**
+ * Buffer validation list.
+ *
+ * It holds a list of buffers to be validated and fenced when flushing.
+ */
+struct pb_validate;
+
+
+enum pipe_error
+pb_validate_add_buffer(struct pb_validate *vl,
+ struct pb_buffer *buf,
+ unsigned flags);
+
+enum pipe_error
+pb_validate_foreach(struct pb_validate *vl,
+ enum pipe_error (*callback)(struct pb_buffer *buf, void *data),
+ void *data);
+
+/**
+ * Validate all buffers for hardware access.
+ *
+ * Should be called right before issuing commands to the hardware.
+ */
+enum pipe_error
+pb_validate_validate(struct pb_validate *vl);
+
+/**
+ * Fence all buffers and clear the list.
+ *
+ * Should be called right after issuing commands to the hardware.
+ */
+void
+pb_validate_fence(struct pb_validate *vl,
+ struct pipe_fence_handle *fence);
+
+struct pb_validate *
+pb_validate_create(void);
+
+void
+pb_validate_destroy(struct pb_validate *vl);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*PB_VALIDATE_H_*/
diff --git a/src/gallium/auxiliary/rbug/Makefile b/src/gallium/auxiliary/rbug/Makefile
new file mode 100644
index 0000000000..cd12e8468f
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/Makefile
@@ -0,0 +1,14 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = rbug
+
+C_SOURCES = \
+ rbug_connection.c \
+ rbug_core.c \
+ rbug_texture.c \
+ rbug_context.c \
+ rbug_shader.c \
+ rbug_demarshal.c
+
+include ../../Makefile.template
diff --git a/src/gallium/auxiliary/rbug/README b/src/gallium/auxiliary/rbug/README
new file mode 100644
index 0000000000..33d76371de
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/README
@@ -0,0 +1,21 @@
+ GALLIUM REMOTE DEBUGGING COMMON CODE
+
+= About =
+
+This directory contains the common code for the Gallium 3D remote debugging
+driver and clients. The code is two parts the connection managment code and
+the (de)marsheller.
+
+The code currently uses tcp and ip4v for connections.
+
+Information about driver integration can be found in:
+
+src/gallium/drivers/trace/README
+
+for information about applications look in:
+
+progs/rbug/README
+
+
+--
+Jakob Bornecrantz <jakob@vmware.com>
diff --git a/src/gallium/auxiliary/rbug/SConscript b/src/gallium/auxiliary/rbug/SConscript
new file mode 100644
index 0000000000..4a9afb45d3
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/SConscript
@@ -0,0 +1,14 @@
+Import('*')
+
+rbug = env.ConvenienceLibrary(
+ target = 'rbug',
+ source = [
+ 'rbug_core.c',
+ 'rbug_shader.c',
+ 'rbug_context.c',
+ 'rbug_texture.c',
+ 'rbug_demarshal.c',
+ 'rbug_connection.c',
+ ])
+
+auxiliaries.insert(0, rbug)
diff --git a/src/gallium/auxiliary/rbug/rbug.h b/src/gallium/auxiliary/rbug/rbug.h
new file mode 100644
index 0000000000..259bfc6c79
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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 all for users the remote debugger protocol code.
+ */
+
+#include "rbug/rbug_core.h"
+#include "rbug/rbug_shader.h"
+#include "rbug/rbug_context.h"
+#include "rbug/rbug_texture.h"
+#include "rbug/rbug_connection.h"
diff --git a/src/gallium/auxiliary/rbug/rbug_connection.c b/src/gallium/auxiliary/rbug/rbug_connection.c
new file mode 100644
index 0000000000..52acb700af
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_connection.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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 "rbug/rbug.h"
+#include "rbug/rbug_internal.h"
+
+#include "util/u_network.h"
+
+struct rbug_connection
+{
+ int socket;
+ uint32_t send_serial;
+ uint32_t recv_serial;
+ enum rbug_opcode opcode;
+};
+
+/**
+ * Create a rbug connection from a socket created with u_socket.
+ *
+ * Result:
+ * A new allocated connection using socket as communication path
+ */
+struct rbug_connection *
+rbug_from_socket(int socket)
+{
+ struct rbug_connection *c = CALLOC_STRUCT(rbug_connection);
+ c->socket = socket;
+ return c;
+}
+
+/**
+ * Free a connection, also closes socket.
+ */
+void
+rbug_disconnect(struct rbug_connection *c)
+{
+ u_socket_close(c->socket);
+ FREE(c);
+}
+
+/**
+ * Waits for a message to be fully received.
+ * Also returns the serial for the message, serial is not touched for replys.
+ *
+ * Result:
+ * demarshaled message on success, NULL on connection error
+ */
+struct rbug_header *
+rbug_get_message(struct rbug_connection *c, uint32_t *serial)
+{
+ struct rbug_proto_header header;
+ struct rbug_header *out;
+ struct rbug_proto_header *data;
+ size_t length = 0;
+ size_t read = 0;
+ int ret;
+
+
+ ret = u_socket_peek(c->socket, &header, sizeof(header));
+ if (ret <= 0) {
+ return NULL;
+ }
+
+ length = (size_t)header.length * 4;
+ data = MALLOC(length);
+ if (!data) {
+ return NULL;
+ }
+
+ do {
+ uint8_t *ptr = ((uint8_t*)data) + read;
+ ret = u_socket_recv(c->socket, ptr, length - read);
+
+ if (ret <= 0) {
+ FREE(data);
+ return NULL;
+ }
+
+ read += ret;
+ } while(read < length);
+
+ out = rbug_demarshal(data);
+ if (!out)
+ FREE(data);
+ else if (serial)
+ *serial = c->recv_serial++;
+ else
+ c->recv_serial++;
+
+ return out;
+}
+
+/**
+ * Frees a message and associated data.
+ */
+void
+rbug_free_header(struct rbug_header *header)
+{
+ if (!header)
+ return;
+
+ FREE(header->__message);
+ FREE(header);
+}
+
+/**
+ * Internal function used by rbug_send_* functions.
+ *
+ * Start sending a message.
+ */
+int
+rbug_connection_send_start(struct rbug_connection *c, enum rbug_opcode opcode, uint32_t length)
+{
+ c->opcode = opcode;
+ return 0;
+}
+
+/**
+ * Internal function used by rbug_send_* functions.
+ *
+ * Write data to the socket.
+ */
+int
+rbug_connection_write(struct rbug_connection *c, void *to, uint32_t size)
+{
+ int ret = u_socket_send(c->socket, to, size);
+ return ret;
+}
+
+/**
+ * Internal function used by rbug_send_* functions.
+ *
+ * Finish writeing data to the socket.
+ * Ups the send_serial and sets the serial argument if supplied.
+ */
+int rbug_connection_send_finish(struct rbug_connection *c, uint32_t *serial)
+{
+ if (c->opcode < 0)
+ return 0;
+ else if (serial)
+ *serial = c->send_serial++;
+ else
+ c->send_serial++;
+
+ return 0;
+}
diff --git a/src/gallium/auxiliary/rbug/rbug_connection.h b/src/gallium/auxiliary/rbug/rbug_connection.h
new file mode 100644
index 0000000000..1f2c9ff347
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_connection.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file contains the function defentions for connection see c file for
+ * more comments covering function use.
+ */
+
+#ifndef _RBUG_CONNECTION_H_
+#define _RBUG_CONNECTION_H_
+
+#include "rbug/rbug_proto.h"
+
+struct rbug_connection * rbug_from_socket(int socket);
+
+void rbug_disconnect(struct rbug_connection *c);
+
+struct rbug_header * rbug_get_message(struct rbug_connection *c, uint32_t *serial);
+
+void rbug_free_header(struct rbug_header *header);
+
+struct rbug_header * rbug_demarshal(struct rbug_proto_header *header);
+
+#endif
diff --git a/src/gallium/auxiliary/rbug/rbug_context.c b/src/gallium/auxiliary/rbug/rbug_context.c
new file mode 100644
index 0000000000..1832425658
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_context.c
@@ -0,0 +1,759 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file holds the function implementation for one of the rbug extensions.
+ * Prototypes and declerations of functions and structs is in the same folder
+ * in the header file matching this file's name.
+ *
+ * The functions starting rbug_send_* encodes a call to the write format and
+ * sends that to the supplied connection, while functions starting with
+ * rbug_demarshal_* demarshal data in the wire protocol.
+ *
+ * Functions ending with _reply are replies to requests.
+ */
+
+#include "rbug_internal.h"
+#include "rbug/rbug_context.h"
+
+int rbug_send_context_list(struct rbug_connection *__con,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_LIST));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_LIST, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_context_info(struct rbug_connection *__con,
+ rbug_context_t context,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_INFO));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_INFO, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_context_draw_block(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_block_t block,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+ LEN(4); /* block */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_BLOCK));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+ WRITE(4, rbug_block_t, block); /* block */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_BLOCK, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_context_draw_step(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_block_t step,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+ LEN(4); /* step */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_STEP));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+ WRITE(4, rbug_block_t, step); /* step */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_STEP, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_context_draw_unblock(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_block_t unblock,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+ LEN(4); /* unblock */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_UNBLOCK));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+ WRITE(4, rbug_block_t, unblock); /* unblock */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_UNBLOCK, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_context_draw_rule(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_shader_t vertex,
+ rbug_shader_t fragment,
+ rbug_texture_t texture,
+ rbug_texture_t surface,
+ rbug_block_t block,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+ LEN(8); /* vertex */
+ LEN(8); /* fragment */
+ LEN(8); /* texture */
+ LEN(8); /* surface */
+ LEN(4); /* block */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_RULE));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+ WRITE(8, rbug_shader_t, vertex); /* vertex */
+ WRITE(8, rbug_shader_t, fragment); /* fragment */
+ WRITE(8, rbug_texture_t, texture); /* texture */
+ WRITE(8, rbug_texture_t, surface); /* surface */
+ WRITE(4, rbug_block_t, block); /* block */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_RULE, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_context_flush(struct rbug_connection *__con,
+ rbug_context_t context,
+ int32_t flags,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+ LEN(4); /* flags */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_FLUSH));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+ WRITE(4, int32_t, flags); /* flags */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_FLUSH, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_context_list_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ rbug_context_t *contexts,
+ uint32_t contexts_len,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* serial */
+ LEN_ARRAY(8, contexts); /* contexts */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_LIST_REPLY));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, serial); /* serial */
+ WRITE_ARRAY(8, rbug_context_t, contexts); /* contexts */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_LIST_REPLY, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_context_info_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ rbug_shader_t vertex,
+ rbug_shader_t fragment,
+ rbug_texture_t *texs,
+ uint32_t texs_len,
+ rbug_texture_t *cbufs,
+ uint32_t cbufs_len,
+ rbug_texture_t zsbuf,
+ rbug_block_t blocker,
+ rbug_block_t blocked,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* serial */
+ LEN(8); /* vertex */
+ LEN(8); /* fragment */
+ LEN_ARRAY(8, texs); /* texs */
+ LEN_ARRAY(8, cbufs); /* cbufs */
+ LEN(8); /* zsbuf */
+ LEN(4); /* blocker */
+ LEN(4); /* blocked */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_INFO_REPLY));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, serial); /* serial */
+ WRITE(8, rbug_shader_t, vertex); /* vertex */
+ WRITE(8, rbug_shader_t, fragment); /* fragment */
+ WRITE_ARRAY(8, rbug_texture_t, texs); /* texs */
+ WRITE_ARRAY(8, rbug_texture_t, cbufs); /* cbufs */
+ WRITE(8, rbug_texture_t, zsbuf); /* zsbuf */
+ WRITE(4, rbug_block_t, blocker); /* blocker */
+ WRITE(4, rbug_block_t, blocked); /* blocked */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_INFO_REPLY, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_context_draw_blocked(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_block_t block,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+ LEN(4); /* block */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_BLOCKED));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+ WRITE(4, rbug_block_t, block); /* block */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_BLOCKED, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+struct rbug_proto_context_list * rbug_demarshal_context_list(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_list *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_LIST)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+
+ return ret;
+}
+
+struct rbug_proto_context_info * rbug_demarshal_context_info(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_info *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_INFO)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+
+ return ret;
+}
+
+struct rbug_proto_context_draw_block * rbug_demarshal_context_draw_block(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_draw_block *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_BLOCK)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+ READ(4, rbug_block_t, block); /* block */
+
+ return ret;
+}
+
+struct rbug_proto_context_draw_step * rbug_demarshal_context_draw_step(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_draw_step *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_STEP)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+ READ(4, rbug_block_t, step); /* step */
+
+ return ret;
+}
+
+struct rbug_proto_context_draw_unblock * rbug_demarshal_context_draw_unblock(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_draw_unblock *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_UNBLOCK)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+ READ(4, rbug_block_t, unblock); /* unblock */
+
+ return ret;
+}
+
+struct rbug_proto_context_draw_rule * rbug_demarshal_context_draw_rule(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_draw_rule *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_RULE)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+ READ(8, rbug_shader_t, vertex); /* vertex */
+ READ(8, rbug_shader_t, fragment); /* fragment */
+ READ(8, rbug_texture_t, texture); /* texture */
+ READ(8, rbug_texture_t, surface); /* surface */
+ READ(4, rbug_block_t, block); /* block */
+
+ return ret;
+}
+
+struct rbug_proto_context_flush * rbug_demarshal_context_flush(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_flush *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_FLUSH)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+ READ(4, int32_t, flags); /* flags */
+
+ return ret;
+}
+
+struct rbug_proto_context_list_reply * rbug_demarshal_context_list_reply(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_list_reply *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_LIST_REPLY)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, serial); /* serial */
+ READ_ARRAY(8, rbug_context_t, contexts); /* contexts */
+
+ return ret;
+}
+
+struct rbug_proto_context_info_reply * rbug_demarshal_context_info_reply(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_info_reply *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_INFO_REPLY)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, serial); /* serial */
+ READ(8, rbug_shader_t, vertex); /* vertex */
+ READ(8, rbug_shader_t, fragment); /* fragment */
+ READ_ARRAY(8, rbug_texture_t, texs); /* texs */
+ READ_ARRAY(8, rbug_texture_t, cbufs); /* cbufs */
+ READ(8, rbug_texture_t, zsbuf); /* zsbuf */
+ READ(4, rbug_block_t, blocker); /* blocker */
+ READ(4, rbug_block_t, blocked); /* blocked */
+
+ return ret;
+}
+
+struct rbug_proto_context_draw_blocked * rbug_demarshal_context_draw_blocked(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_context_draw_blocked *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_BLOCKED)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+ READ(4, rbug_block_t, block); /* block */
+
+ return ret;
+}
diff --git a/src/gallium/auxiliary/rbug/rbug_context.h b/src/gallium/auxiliary/rbug/rbug_context.h
new file mode 100644
index 0000000000..da61c2365b
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_context.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file holds structs decelerations and function prototypes for one of
+ * the rbug extensions. Implementation of the functions is in the same folder
+ * in the c file matching this file's name.
+ *
+ * The structs what is returned from the demarshal functions. The functions
+ * starting rbug_send_* encodes a call to the write format and sends that to
+ * the supplied connection, while functions starting with rbug_demarshal_*
+ * demarshal data from the wire protocol.
+ *
+ * Structs and functions ending with _reply are replies to requests.
+ */
+
+#ifndef _RBUG_PROTO_CONTEXT_H_
+#define _RBUG_PROTO_CONTEXT_H_
+
+#include "rbug/rbug_proto.h"
+#include "rbug/rbug_core.h"
+
+typedef enum
+{
+ RBUG_BLOCK_BEFORE = 1,
+ RBUG_BLOCK_AFTER = 2,
+ RBUG_BLOCK_RULE = 4,
+ RBUG_BLOCK_MASK = 7,
+} rbug_block_t;
+
+struct rbug_proto_context_list
+{
+ struct rbug_header header;
+};
+
+struct rbug_proto_context_info
+{
+ struct rbug_header header;
+ rbug_context_t context;
+};
+
+struct rbug_proto_context_draw_block
+{
+ struct rbug_header header;
+ rbug_context_t context;
+ rbug_block_t block;
+};
+
+struct rbug_proto_context_draw_step
+{
+ struct rbug_header header;
+ rbug_context_t context;
+ rbug_block_t step;
+};
+
+struct rbug_proto_context_draw_unblock
+{
+ struct rbug_header header;
+ rbug_context_t context;
+ rbug_block_t unblock;
+};
+
+struct rbug_proto_context_draw_rule
+{
+ struct rbug_header header;
+ rbug_context_t context;
+ rbug_shader_t vertex;
+ rbug_shader_t fragment;
+ rbug_texture_t texture;
+ rbug_texture_t surface;
+ rbug_block_t block;
+};
+
+struct rbug_proto_context_flush
+{
+ struct rbug_header header;
+ rbug_context_t context;
+ int32_t flags;
+};
+
+struct rbug_proto_context_list_reply
+{
+ struct rbug_header header;
+ uint32_t serial;
+ rbug_context_t *contexts;
+ uint32_t contexts_len;
+};
+
+struct rbug_proto_context_info_reply
+{
+ struct rbug_header header;
+ uint32_t serial;
+ rbug_shader_t vertex;
+ rbug_shader_t fragment;
+ rbug_texture_t *texs;
+ uint32_t texs_len;
+ rbug_texture_t *cbufs;
+ uint32_t cbufs_len;
+ rbug_texture_t zsbuf;
+ rbug_block_t blocker;
+ rbug_block_t blocked;
+};
+
+struct rbug_proto_context_draw_blocked
+{
+ struct rbug_header header;
+ rbug_context_t context;
+ rbug_block_t block;
+};
+
+int rbug_send_context_list(struct rbug_connection *__con,
+ uint32_t *__serial);
+
+int rbug_send_context_info(struct rbug_connection *__con,
+ rbug_context_t context,
+ uint32_t *__serial);
+
+int rbug_send_context_draw_block(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_block_t block,
+ uint32_t *__serial);
+
+int rbug_send_context_draw_step(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_block_t step,
+ uint32_t *__serial);
+
+int rbug_send_context_draw_unblock(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_block_t unblock,
+ uint32_t *__serial);
+
+int rbug_send_context_draw_rule(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_shader_t vertex,
+ rbug_shader_t fragment,
+ rbug_texture_t texture,
+ rbug_texture_t surface,
+ rbug_block_t block,
+ uint32_t *__serial);
+
+int rbug_send_context_flush(struct rbug_connection *__con,
+ rbug_context_t context,
+ int32_t flags,
+ uint32_t *__serial);
+
+int rbug_send_context_list_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ rbug_context_t *contexts,
+ uint32_t contexts_len,
+ uint32_t *__serial);
+
+int rbug_send_context_info_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ rbug_shader_t vertex,
+ rbug_shader_t fragment,
+ rbug_texture_t *texs,
+ uint32_t texs_len,
+ rbug_texture_t *cbufs,
+ uint32_t cbufs_len,
+ rbug_texture_t zsbuf,
+ rbug_block_t blocker,
+ rbug_block_t blocked,
+ uint32_t *__serial);
+
+int rbug_send_context_draw_blocked(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_block_t block,
+ uint32_t *__serial);
+
+struct rbug_proto_context_list * rbug_demarshal_context_list(struct rbug_proto_header *header);
+
+struct rbug_proto_context_info * rbug_demarshal_context_info(struct rbug_proto_header *header);
+
+struct rbug_proto_context_draw_block * rbug_demarshal_context_draw_block(struct rbug_proto_header *header);
+
+struct rbug_proto_context_draw_step * rbug_demarshal_context_draw_step(struct rbug_proto_header *header);
+
+struct rbug_proto_context_draw_unblock * rbug_demarshal_context_draw_unblock(struct rbug_proto_header *header);
+
+struct rbug_proto_context_draw_rule * rbug_demarshal_context_draw_rule(struct rbug_proto_header *header);
+
+struct rbug_proto_context_flush * rbug_demarshal_context_flush(struct rbug_proto_header *header);
+
+struct rbug_proto_context_list_reply * rbug_demarshal_context_list_reply(struct rbug_proto_header *header);
+
+struct rbug_proto_context_info_reply * rbug_demarshal_context_info_reply(struct rbug_proto_header *header);
+
+struct rbug_proto_context_draw_blocked * rbug_demarshal_context_draw_blocked(struct rbug_proto_header *header);
+
+#endif
diff --git a/src/gallium/auxiliary/rbug/rbug_core.c b/src/gallium/auxiliary/rbug/rbug_core.c
new file mode 100644
index 0000000000..876ae5a0ce
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_core.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file holds the function implementation for one of the rbug extensions.
+ * Prototypes and declerations of functions and structs is in the same folder
+ * in the header file matching this file's name.
+ *
+ * The functions starting rbug_send_* encodes a call to the write format and
+ * sends that to the supplied connection, while functions starting with
+ * rbug_demarshal_* demarshal data in the wire protocol.
+ *
+ * Functions ending with _reply are replies to requests.
+ */
+
+#include "rbug_internal.h"
+#include "rbug/rbug_core.h"
+
+int rbug_send_noop(struct rbug_connection *__con,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_NOOP));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_NOOP, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_ping(struct rbug_connection *__con,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_PING));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_PING, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_error(struct rbug_connection *__con,
+ uint32_t error,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* error */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_ERROR));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, error); /* error */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_ERROR, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_ping_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* serial */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_PING_REPLY));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, serial); /* serial */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_PING_REPLY, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_error_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t error,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* serial */
+ LEN(4); /* error */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_ERROR_REPLY));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, serial); /* serial */
+ WRITE(4, uint32_t, error); /* error */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_ERROR_REPLY, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+struct rbug_proto_noop * rbug_demarshal_noop(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_noop *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_NOOP)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+
+ return ret;
+}
+
+struct rbug_proto_ping * rbug_demarshal_ping(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_ping *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_PING)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+
+ return ret;
+}
+
+struct rbug_proto_error * rbug_demarshal_error(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_error *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_ERROR)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, error); /* error */
+
+ return ret;
+}
+
+struct rbug_proto_ping_reply * rbug_demarshal_ping_reply(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_ping_reply *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_PING_REPLY)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, serial); /* serial */
+
+ return ret;
+}
+
+struct rbug_proto_error_reply * rbug_demarshal_error_reply(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_error_reply *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_ERROR_REPLY)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, serial); /* serial */
+ READ(4, uint32_t, error); /* error */
+
+ return ret;
+}
diff --git a/src/gallium/auxiliary/rbug/rbug_core.h b/src/gallium/auxiliary/rbug/rbug_core.h
new file mode 100644
index 0000000000..99a36a0163
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_core.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file holds structs decelerations and function prototypes for one of
+ * the rbug extensions. Implementation of the functions is in the same folder
+ * in the c file matching this file's name.
+ *
+ * The structs what is returned from the demarshal functions. The functions
+ * starting rbug_send_* encodes a call to the write format and sends that to
+ * the supplied connection, while functions starting with rbug_demarshal_*
+ * demarshal data from the wire protocol.
+ *
+ * Structs and functions ending with _reply are replies to requests.
+ */
+
+#ifndef _RBUG_PROTO_CORE_H_
+#define _RBUG_PROTO_CORE_H_
+
+#include "rbug/rbug_proto.h"
+
+typedef uint64_t rbug_shader_t;
+typedef uint64_t rbug_context_t;
+typedef uint64_t rbug_texture_t;
+
+struct rbug_proto_noop
+{
+ struct rbug_header header;
+};
+
+struct rbug_proto_ping
+{
+ struct rbug_header header;
+};
+
+struct rbug_proto_error
+{
+ struct rbug_header header;
+ uint32_t error;
+};
+
+struct rbug_proto_ping_reply
+{
+ struct rbug_header header;
+ uint32_t serial;
+};
+
+struct rbug_proto_error_reply
+{
+ struct rbug_header header;
+ uint32_t serial;
+ uint32_t error;
+};
+
+int rbug_send_noop(struct rbug_connection *__con,
+ uint32_t *__serial);
+
+int rbug_send_ping(struct rbug_connection *__con,
+ uint32_t *__serial);
+
+int rbug_send_error(struct rbug_connection *__con,
+ uint32_t error,
+ uint32_t *__serial);
+
+int rbug_send_ping_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t *__serial);
+
+int rbug_send_error_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t error,
+ uint32_t *__serial);
+
+struct rbug_proto_noop * rbug_demarshal_noop(struct rbug_proto_header *header);
+
+struct rbug_proto_ping * rbug_demarshal_ping(struct rbug_proto_header *header);
+
+struct rbug_proto_error * rbug_demarshal_error(struct rbug_proto_header *header);
+
+struct rbug_proto_ping_reply * rbug_demarshal_ping_reply(struct rbug_proto_header *header);
+
+struct rbug_proto_error_reply * rbug_demarshal_error_reply(struct rbug_proto_header *header);
+
+#endif
diff --git a/src/gallium/auxiliary/rbug/rbug_demarshal.c b/src/gallium/auxiliary/rbug/rbug_demarshal.c
new file mode 100644
index 0000000000..47390fbcee
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_demarshal.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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 "rbug.h"
+
+/**
+ * Small function that looks at the proto_header and selects the correct
+ * demarshal functions and return the result.
+ */
+struct rbug_header * rbug_demarshal(struct rbug_proto_header *header)
+{
+ switch(header->opcode) {
+ case RBUG_OP_NOOP:
+ return (struct rbug_header *)rbug_demarshal_noop(header);
+ case RBUG_OP_PING:
+ return (struct rbug_header *)rbug_demarshal_ping(header);
+ case RBUG_OP_ERROR:
+ return (struct rbug_header *)rbug_demarshal_error(header);
+ case RBUG_OP_PING_REPLY:
+ return (struct rbug_header *)rbug_demarshal_ping_reply(header);
+ case RBUG_OP_ERROR_REPLY:
+ return (struct rbug_header *)rbug_demarshal_error_reply(header);
+ case RBUG_OP_TEXTURE_LIST:
+ return (struct rbug_header *)rbug_demarshal_texture_list(header);
+ case RBUG_OP_TEXTURE_INFO:
+ return (struct rbug_header *)rbug_demarshal_texture_info(header);
+ case RBUG_OP_TEXTURE_WRITE:
+ return (struct rbug_header *)rbug_demarshal_texture_write(header);
+ case RBUG_OP_TEXTURE_READ:
+ return (struct rbug_header *)rbug_demarshal_texture_read(header);
+ case RBUG_OP_TEXTURE_LIST_REPLY:
+ return (struct rbug_header *)rbug_demarshal_texture_list_reply(header);
+ case RBUG_OP_TEXTURE_INFO_REPLY:
+ return (struct rbug_header *)rbug_demarshal_texture_info_reply(header);
+ case RBUG_OP_TEXTURE_READ_REPLY:
+ return (struct rbug_header *)rbug_demarshal_texture_read_reply(header);
+ case RBUG_OP_CONTEXT_LIST:
+ return (struct rbug_header *)rbug_demarshal_context_list(header);
+ case RBUG_OP_CONTEXT_INFO:
+ return (struct rbug_header *)rbug_demarshal_context_info(header);
+ case RBUG_OP_CONTEXT_DRAW_BLOCK:
+ return (struct rbug_header *)rbug_demarshal_context_draw_block(header);
+ case RBUG_OP_CONTEXT_DRAW_STEP:
+ return (struct rbug_header *)rbug_demarshal_context_draw_step(header);
+ case RBUG_OP_CONTEXT_DRAW_UNBLOCK:
+ return (struct rbug_header *)rbug_demarshal_context_draw_unblock(header);
+ case RBUG_OP_CONTEXT_DRAW_RULE:
+ return (struct rbug_header *)rbug_demarshal_context_draw_rule(header);
+ case RBUG_OP_CONTEXT_FLUSH:
+ return (struct rbug_header *)rbug_demarshal_context_flush(header);
+ case RBUG_OP_CONTEXT_LIST_REPLY:
+ return (struct rbug_header *)rbug_demarshal_context_list_reply(header);
+ case RBUG_OP_CONTEXT_INFO_REPLY:
+ return (struct rbug_header *)rbug_demarshal_context_info_reply(header);
+ case RBUG_OP_CONTEXT_DRAW_BLOCKED:
+ return (struct rbug_header *)rbug_demarshal_context_draw_blocked(header);
+ case RBUG_OP_SHADER_LIST:
+ return (struct rbug_header *)rbug_demarshal_shader_list(header);
+ case RBUG_OP_SHADER_INFO:
+ return (struct rbug_header *)rbug_demarshal_shader_info(header);
+ case RBUG_OP_SHADER_DISABLE:
+ return (struct rbug_header *)rbug_demarshal_shader_disable(header);
+ case RBUG_OP_SHADER_REPLACE:
+ return (struct rbug_header *)rbug_demarshal_shader_replace(header);
+ case RBUG_OP_SHADER_LIST_REPLY:
+ return (struct rbug_header *)rbug_demarshal_shader_list_reply(header);
+ case RBUG_OP_SHADER_INFO_REPLY:
+ return (struct rbug_header *)rbug_demarshal_shader_info_reply(header);
+ default:
+ return NULL;
+ }
+}
diff --git a/src/gallium/auxiliary/rbug/rbug_internal.h b/src/gallium/auxiliary/rbug/rbug_internal.h
new file mode 100644
index 0000000000..4aba1a810f
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_internal.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file is internal to the rbug protocol code, and contains asorted
+ * features needed by the code.
+ */
+
+#ifndef _RBUG_INTERNAL_H_
+#define _RBUG_INTERNAL_H_
+
+#include "rbug/rbug_proto.h"
+
+#include "util/u_memory.h"
+#include "util/u_debug.h"
+#include <errno.h>
+
+int rbug_connection_send_start(struct rbug_connection *con, enum rbug_opcode opcode, uint32_t length);
+int rbug_connection_write(struct rbug_connection *con, void *data, uint32_t size);
+int rbug_connection_send_finish(struct rbug_connection *con, uint32_t *c);
+
+/**
+ * Only works with multiples of 2
+ */
+#define PAD(from, to) \
+do { \
+ from = (from + to - 1) & ~(to - 1); \
+} while(0)
+
+#define LEN(size) \
+do { \
+ PAD(__len, size); \
+ __len += size; \
+} while(0)
+
+#define LEN_ARRAY(size, name) \
+do { \
+ LEN(4); \
+ PAD(__len, size); \
+ __len += size * name##_len; \
+} while(0)
+
+#define WRITE(size, type, name) \
+do { \
+ PAD(__pos, size); \
+ *((type *)(&__data[__pos])) = name; \
+ __pos += size; \
+} while(0)
+
+#define WRITE_ARRAY(size, type, name) \
+do { \
+ WRITE(4, uint32_t, name##_len); \
+ PAD(__pos, size); \
+ memcpy(&__data[__pos], name, size * name##_len); \
+ __pos += size * name##_len; \
+} while(0)
+
+#define READ(size, type, name) \
+do { \
+ PAD(pos, size); \
+ pos += size; \
+ if (pos > len) \
+ break; \
+ ret->name = *((type *)(&data[pos - size])); \
+} while(0)
+
+#define READ_ARRAY(size, type, name) \
+do { \
+ READ(4, uint32_t, name##_len); \
+ if (pos > len) \
+ break; \
+ PAD(pos, size); \
+ pos += size * ret->name##_len; \
+ if (pos > len) \
+ break; \
+ ret->name = (type *)&data[pos - size * ret->name##_len]; \
+} while(0)
+
+#endif
diff --git a/src/gallium/auxiliary/rbug/rbug_proto.h b/src/gallium/auxiliary/rbug/rbug_proto.h
new file mode 100644
index 0000000000..d273be0166
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_proto.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file holds common definitions of the gallium remote debugging protocol.
+ */
+
+#ifndef _RBUG_PROTO_H_
+#define _RBUG_PROTO_H_
+
+#include "pipe/p_compiler.h"
+
+/**
+ * Uniqe indentifier for each command.
+ *
+ * Replys are designated by negative.
+ */
+enum rbug_opcode
+{
+ RBUG_OP_NOOP = 0,
+ RBUG_OP_PING = 1,
+ RBUG_OP_ERROR = 2,
+ RBUG_OP_PING_REPLY = -1,
+ RBUG_OP_ERROR_REPLY = -2,
+ RBUG_OP_TEXTURE_LIST = 256,
+ RBUG_OP_TEXTURE_INFO = 257,
+ RBUG_OP_TEXTURE_WRITE = 258,
+ RBUG_OP_TEXTURE_READ = 259,
+ RBUG_OP_TEXTURE_LIST_REPLY = -256,
+ RBUG_OP_TEXTURE_INFO_REPLY = -257,
+ RBUG_OP_TEXTURE_READ_REPLY = -259,
+ RBUG_OP_CONTEXT_LIST = 512,
+ RBUG_OP_CONTEXT_INFO = 513,
+ RBUG_OP_CONTEXT_DRAW_BLOCK = 514,
+ RBUG_OP_CONTEXT_DRAW_STEP = 515,
+ RBUG_OP_CONTEXT_DRAW_UNBLOCK = 516,
+ RBUG_OP_CONTEXT_DRAW_RULE = 518,
+ RBUG_OP_CONTEXT_FLUSH = 519,
+ RBUG_OP_CONTEXT_LIST_REPLY = -512,
+ RBUG_OP_CONTEXT_INFO_REPLY = -513,
+ RBUG_OP_CONTEXT_DRAW_BLOCKED = 517,
+ RBUG_OP_SHADER_LIST = 768,
+ RBUG_OP_SHADER_INFO = 769,
+ RBUG_OP_SHADER_DISABLE = 770,
+ RBUG_OP_SHADER_REPLACE = 771,
+ RBUG_OP_SHADER_LIST_REPLY = -768,
+ RBUG_OP_SHADER_INFO_REPLY = -769,
+};
+
+/**
+ * Header for demarshaled message.
+ */
+struct rbug_header
+{
+ enum rbug_opcode opcode;
+ void *__message;
+};
+
+/**
+ * Header for a message in wire format.
+ */
+struct rbug_proto_header
+{
+ int32_t opcode;
+ uint32_t length;
+};
+
+/**
+ * Forward declare connection here, as this file is included by all users.
+ */
+struct rbug_connection;
+
+#endif
diff --git a/src/gallium/auxiliary/rbug/rbug_shader.c b/src/gallium/auxiliary/rbug/rbug_shader.c
new file mode 100644
index 0000000000..fccd2f55ef
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_shader.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file holds the function implementation for one of the rbug extensions.
+ * Prototypes and declerations of functions and structs is in the same folder
+ * in the header file matching this file's name.
+ *
+ * The functions starting rbug_send_* encodes a call to the write format and
+ * sends that to the supplied connection, while functions starting with
+ * rbug_demarshal_* demarshal data in the wire protocol.
+ *
+ * Functions ending with _reply are replies to requests.
+ */
+
+#include "rbug_internal.h"
+#include "rbug/rbug_shader.h"
+
+int rbug_send_shader_list(struct rbug_connection *__con,
+ rbug_context_t context,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_LIST));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_SHADER_LIST, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_shader_info(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_shader_t shader,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+ LEN(8); /* shader */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_INFO));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+ WRITE(8, rbug_shader_t, shader); /* shader */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_SHADER_INFO, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_shader_disable(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_shader_t shader,
+ uint8_t disable,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+ LEN(8); /* shader */
+ LEN(1); /* disable */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_DISABLE));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+ WRITE(8, rbug_shader_t, shader); /* shader */
+ WRITE(1, uint8_t, disable); /* disable */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_SHADER_DISABLE, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_shader_replace(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_shader_t shader,
+ uint32_t *tokens,
+ uint32_t tokens_len,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* context */
+ LEN(8); /* shader */
+ LEN_ARRAY(4, tokens); /* tokens */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_REPLACE));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_context_t, context); /* context */
+ WRITE(8, rbug_shader_t, shader); /* shader */
+ WRITE_ARRAY(4, uint32_t, tokens); /* tokens */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_SHADER_REPLACE, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_shader_list_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ rbug_shader_t *shaders,
+ uint32_t shaders_len,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* serial */
+ LEN_ARRAY(8, shaders); /* shaders */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_LIST_REPLY));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, serial); /* serial */
+ WRITE_ARRAY(8, rbug_shader_t, shaders); /* shaders */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_SHADER_LIST_REPLY, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_shader_info_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t *original,
+ uint32_t original_len,
+ uint32_t *replaced,
+ uint32_t replaced_len,
+ uint8_t disabled,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* serial */
+ LEN_ARRAY(4, original); /* original */
+ LEN_ARRAY(4, replaced); /* replaced */
+ LEN(1); /* disabled */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_INFO_REPLY));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, serial); /* serial */
+ WRITE_ARRAY(4, uint32_t, original); /* original */
+ WRITE_ARRAY(4, uint32_t, replaced); /* replaced */
+ WRITE(1, uint8_t, disabled); /* disabled */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_SHADER_INFO_REPLY, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+struct rbug_proto_shader_list * rbug_demarshal_shader_list(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_shader_list *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_SHADER_LIST)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+
+ return ret;
+}
+
+struct rbug_proto_shader_info * rbug_demarshal_shader_info(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_shader_info *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_SHADER_INFO)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+ READ(8, rbug_shader_t, shader); /* shader */
+
+ return ret;
+}
+
+struct rbug_proto_shader_disable * rbug_demarshal_shader_disable(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_shader_disable *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_SHADER_DISABLE)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+ READ(8, rbug_shader_t, shader); /* shader */
+ READ(1, uint8_t, disable); /* disable */
+
+ return ret;
+}
+
+struct rbug_proto_shader_replace * rbug_demarshal_shader_replace(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_shader_replace *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_SHADER_REPLACE)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_context_t, context); /* context */
+ READ(8, rbug_shader_t, shader); /* shader */
+ READ_ARRAY(4, uint32_t, tokens); /* tokens */
+
+ return ret;
+}
+
+struct rbug_proto_shader_list_reply * rbug_demarshal_shader_list_reply(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_shader_list_reply *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_SHADER_LIST_REPLY)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, serial); /* serial */
+ READ_ARRAY(8, rbug_shader_t, shaders); /* shaders */
+
+ return ret;
+}
+
+struct rbug_proto_shader_info_reply * rbug_demarshal_shader_info_reply(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_shader_info_reply *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_SHADER_INFO_REPLY)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, serial); /* serial */
+ READ_ARRAY(4, uint32_t, original); /* original */
+ READ_ARRAY(4, uint32_t, replaced); /* replaced */
+ READ(1, uint8_t, disabled); /* disabled */
+
+ return ret;
+}
diff --git a/src/gallium/auxiliary/rbug/rbug_shader.h b/src/gallium/auxiliary/rbug/rbug_shader.h
new file mode 100644
index 0000000000..b5d886781d
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_shader.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file holds structs decelerations and function prototypes for one of
+ * the rbug extensions. Implementation of the functions is in the same folder
+ * in the c file matching this file's name.
+ *
+ * The structs what is returned from the demarshal functions. The functions
+ * starting rbug_send_* encodes a call to the write format and sends that to
+ * the supplied connection, while functions starting with rbug_demarshal_*
+ * demarshal data from the wire protocol.
+ *
+ * Structs and functions ending with _reply are replies to requests.
+ */
+
+#ifndef _RBUG_PROTO_SHADER_H_
+#define _RBUG_PROTO_SHADER_H_
+
+#include "rbug/rbug_proto.h"
+#include "rbug/rbug_core.h"
+
+struct rbug_proto_shader_list
+{
+ struct rbug_header header;
+ rbug_context_t context;
+};
+
+struct rbug_proto_shader_info
+{
+ struct rbug_header header;
+ rbug_context_t context;
+ rbug_shader_t shader;
+};
+
+struct rbug_proto_shader_disable
+{
+ struct rbug_header header;
+ rbug_context_t context;
+ rbug_shader_t shader;
+ uint8_t disable;
+};
+
+struct rbug_proto_shader_replace
+{
+ struct rbug_header header;
+ rbug_context_t context;
+ rbug_shader_t shader;
+ uint32_t *tokens;
+ uint32_t tokens_len;
+};
+
+struct rbug_proto_shader_list_reply
+{
+ struct rbug_header header;
+ uint32_t serial;
+ rbug_shader_t *shaders;
+ uint32_t shaders_len;
+};
+
+struct rbug_proto_shader_info_reply
+{
+ struct rbug_header header;
+ uint32_t serial;
+ uint32_t *original;
+ uint32_t original_len;
+ uint32_t *replaced;
+ uint32_t replaced_len;
+ uint8_t disabled;
+};
+
+int rbug_send_shader_list(struct rbug_connection *__con,
+ rbug_context_t context,
+ uint32_t *__serial);
+
+int rbug_send_shader_info(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_shader_t shader,
+ uint32_t *__serial);
+
+int rbug_send_shader_disable(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_shader_t shader,
+ uint8_t disable,
+ uint32_t *__serial);
+
+int rbug_send_shader_replace(struct rbug_connection *__con,
+ rbug_context_t context,
+ rbug_shader_t shader,
+ uint32_t *tokens,
+ uint32_t tokens_len,
+ uint32_t *__serial);
+
+int rbug_send_shader_list_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ rbug_shader_t *shaders,
+ uint32_t shaders_len,
+ uint32_t *__serial);
+
+int rbug_send_shader_info_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t *original,
+ uint32_t original_len,
+ uint32_t *replaced,
+ uint32_t replaced_len,
+ uint8_t disabled,
+ uint32_t *__serial);
+
+struct rbug_proto_shader_list * rbug_demarshal_shader_list(struct rbug_proto_header *header);
+
+struct rbug_proto_shader_info * rbug_demarshal_shader_info(struct rbug_proto_header *header);
+
+struct rbug_proto_shader_disable * rbug_demarshal_shader_disable(struct rbug_proto_header *header);
+
+struct rbug_proto_shader_replace * rbug_demarshal_shader_replace(struct rbug_proto_header *header);
+
+struct rbug_proto_shader_list_reply * rbug_demarshal_shader_list_reply(struct rbug_proto_header *header);
+
+struct rbug_proto_shader_info_reply * rbug_demarshal_shader_info_reply(struct rbug_proto_header *header);
+
+#endif
diff --git a/src/gallium/auxiliary/rbug/rbug_texture.c b/src/gallium/auxiliary/rbug/rbug_texture.c
new file mode 100644
index 0000000000..5a918fe6bc
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_texture.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file holds the function implementation for one of the rbug extensions.
+ * Prototypes and declerations of functions and structs is in the same folder
+ * in the header file matching this file's name.
+ *
+ * The functions starting rbug_send_* encodes a call to the write format and
+ * sends that to the supplied connection, while functions starting with
+ * rbug_demarshal_* demarshal data in the wire protocol.
+ *
+ * Functions ending with _reply are replies to requests.
+ */
+
+#include "rbug_internal.h"
+#include "rbug/rbug_texture.h"
+
+int rbug_send_texture_list(struct rbug_connection *__con,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_LIST));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_TEXTURE_LIST, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_texture_info(struct rbug_connection *__con,
+ rbug_texture_t texture,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* texture */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_INFO));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_texture_t, texture); /* texture */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_TEXTURE_INFO, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_texture_write(struct rbug_connection *__con,
+ rbug_texture_t texture,
+ uint32_t face,
+ uint32_t level,
+ uint32_t zslice,
+ uint32_t x,
+ uint32_t y,
+ uint32_t w,
+ uint32_t h,
+ uint8_t *data,
+ uint32_t data_len,
+ uint32_t stride,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* texture */
+ LEN(4); /* face */
+ LEN(4); /* level */
+ LEN(4); /* zslice */
+ LEN(4); /* x */
+ LEN(4); /* y */
+ LEN(4); /* w */
+ LEN(4); /* h */
+ LEN_ARRAY(1, data); /* data */
+ LEN(4); /* stride */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_WRITE));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_texture_t, texture); /* texture */
+ WRITE(4, uint32_t, face); /* face */
+ WRITE(4, uint32_t, level); /* level */
+ WRITE(4, uint32_t, zslice); /* zslice */
+ WRITE(4, uint32_t, x); /* x */
+ WRITE(4, uint32_t, y); /* y */
+ WRITE(4, uint32_t, w); /* w */
+ WRITE(4, uint32_t, h); /* h */
+ WRITE_ARRAY(1, uint8_t, data); /* data */
+ WRITE(4, uint32_t, stride); /* stride */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_TEXTURE_WRITE, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_texture_read(struct rbug_connection *__con,
+ rbug_texture_t texture,
+ uint32_t face,
+ uint32_t level,
+ uint32_t zslice,
+ uint32_t x,
+ uint32_t y,
+ uint32_t w,
+ uint32_t h,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(8); /* texture */
+ LEN(4); /* face */
+ LEN(4); /* level */
+ LEN(4); /* zslice */
+ LEN(4); /* x */
+ LEN(4); /* y */
+ LEN(4); /* w */
+ LEN(4); /* h */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_READ));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(8, rbug_texture_t, texture); /* texture */
+ WRITE(4, uint32_t, face); /* face */
+ WRITE(4, uint32_t, level); /* level */
+ WRITE(4, uint32_t, zslice); /* zslice */
+ WRITE(4, uint32_t, x); /* x */
+ WRITE(4, uint32_t, y); /* y */
+ WRITE(4, uint32_t, w); /* w */
+ WRITE(4, uint32_t, h); /* h */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_TEXTURE_READ, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_texture_list_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ rbug_texture_t *textures,
+ uint32_t textures_len,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* serial */
+ LEN_ARRAY(8, textures); /* textures */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_LIST_REPLY));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, serial); /* serial */
+ WRITE_ARRAY(8, rbug_texture_t, textures); /* textures */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_TEXTURE_LIST_REPLY, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_texture_info_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t target,
+ uint32_t format,
+ uint32_t *width,
+ uint32_t width_len,
+ uint32_t *height,
+ uint32_t height_len,
+ uint32_t *depth,
+ uint32_t depth_len,
+ uint32_t blockw,
+ uint32_t blockh,
+ uint32_t blocksize,
+ uint32_t last_level,
+ uint32_t nr_samples,
+ uint32_t tex_usage,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* serial */
+ LEN(4); /* target */
+ LEN(4); /* format */
+ LEN_ARRAY(4, width); /* width */
+ LEN_ARRAY(4, height); /* height */
+ LEN_ARRAY(4, depth); /* depth */
+ LEN(4); /* blockw */
+ LEN(4); /* blockh */
+ LEN(4); /* blocksize */
+ LEN(4); /* last_level */
+ LEN(4); /* nr_samples */
+ LEN(4); /* tex_usage */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_INFO_REPLY));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, serial); /* serial */
+ WRITE(4, uint32_t, target); /* target */
+ WRITE(4, uint32_t, format); /* format */
+ WRITE_ARRAY(4, uint32_t, width); /* width */
+ WRITE_ARRAY(4, uint32_t, height); /* height */
+ WRITE_ARRAY(4, uint32_t, depth); /* depth */
+ WRITE(4, uint32_t, blockw); /* blockw */
+ WRITE(4, uint32_t, blockh); /* blockh */
+ WRITE(4, uint32_t, blocksize); /* blocksize */
+ WRITE(4, uint32_t, last_level); /* last_level */
+ WRITE(4, uint32_t, nr_samples); /* nr_samples */
+ WRITE(4, uint32_t, tex_usage); /* tex_usage */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_TEXTURE_INFO_REPLY, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+int rbug_send_texture_read_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t format,
+ uint32_t blockw,
+ uint32_t blockh,
+ uint32_t blocksize,
+ uint8_t *data,
+ uint32_t data_len,
+ uint32_t stride,
+ uint32_t *__serial)
+{
+ uint32_t __len = 0;
+ uint32_t __pos = 0;
+ uint8_t *__data = NULL;
+ int __ret = 0;
+
+ LEN(8); /* header */
+ LEN(4); /* serial */
+ LEN(4); /* format */
+ LEN(4); /* blockw */
+ LEN(4); /* blockh */
+ LEN(4); /* blocksize */
+ LEN_ARRAY(1, data); /* data */
+ LEN(4); /* stride */
+
+ /* align */
+ PAD(__len, 8);
+
+ __data = (uint8_t*)MALLOC(__len);
+ if (!__data)
+ return -ENOMEM;
+
+ WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_READ_REPLY));
+ WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
+ WRITE(4, uint32_t, serial); /* serial */
+ WRITE(4, uint32_t, format); /* format */
+ WRITE(4, uint32_t, blockw); /* blockw */
+ WRITE(4, uint32_t, blockh); /* blockh */
+ WRITE(4, uint32_t, blocksize); /* blocksize */
+ WRITE_ARRAY(1, uint8_t, data); /* data */
+ WRITE(4, uint32_t, stride); /* stride */
+
+ /* final pad */
+ PAD(__pos, 8);
+
+ if (__pos != __len) {
+ __ret = -EINVAL;
+ } else {
+ rbug_connection_send_start(__con, RBUG_OP_TEXTURE_READ_REPLY, __len);
+ rbug_connection_write(__con, __data, __len);
+ __ret = rbug_connection_send_finish(__con, __serial);
+ }
+
+ FREE(__data);
+ return __ret;
+}
+
+struct rbug_proto_texture_list * rbug_demarshal_texture_list(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_texture_list *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_TEXTURE_LIST)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+
+ return ret;
+}
+
+struct rbug_proto_texture_info * rbug_demarshal_texture_info(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_texture_info *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_TEXTURE_INFO)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_texture_t, texture); /* texture */
+
+ return ret;
+}
+
+struct rbug_proto_texture_write * rbug_demarshal_texture_write(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_texture_write *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_TEXTURE_WRITE)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_texture_t, texture); /* texture */
+ READ(4, uint32_t, face); /* face */
+ READ(4, uint32_t, level); /* level */
+ READ(4, uint32_t, zslice); /* zslice */
+ READ(4, uint32_t, x); /* x */
+ READ(4, uint32_t, y); /* y */
+ READ(4, uint32_t, w); /* w */
+ READ(4, uint32_t, h); /* h */
+ READ_ARRAY(1, uint8_t, data); /* data */
+ READ(4, uint32_t, stride); /* stride */
+
+ return ret;
+}
+
+struct rbug_proto_texture_read * rbug_demarshal_texture_read(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_texture_read *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_TEXTURE_READ)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(8, rbug_texture_t, texture); /* texture */
+ READ(4, uint32_t, face); /* face */
+ READ(4, uint32_t, level); /* level */
+ READ(4, uint32_t, zslice); /* zslice */
+ READ(4, uint32_t, x); /* x */
+ READ(4, uint32_t, y); /* y */
+ READ(4, uint32_t, w); /* w */
+ READ(4, uint32_t, h); /* h */
+
+ return ret;
+}
+
+struct rbug_proto_texture_list_reply * rbug_demarshal_texture_list_reply(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_texture_list_reply *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_TEXTURE_LIST_REPLY)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, serial); /* serial */
+ READ_ARRAY(8, rbug_texture_t, textures); /* textures */
+
+ return ret;
+}
+
+struct rbug_proto_texture_info_reply * rbug_demarshal_texture_info_reply(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_texture_info_reply *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_TEXTURE_INFO_REPLY)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, serial); /* serial */
+ READ(4, uint32_t, target); /* target */
+ READ(4, uint32_t, format); /* format */
+ READ_ARRAY(4, uint32_t, width); /* width */
+ READ_ARRAY(4, uint32_t, height); /* height */
+ READ_ARRAY(4, uint32_t, depth); /* depth */
+ READ(4, uint32_t, blockw); /* blockw */
+ READ(4, uint32_t, blockh); /* blockh */
+ READ(4, uint32_t, blocksize); /* blocksize */
+ READ(4, uint32_t, last_level); /* last_level */
+ READ(4, uint32_t, nr_samples); /* nr_samples */
+ READ(4, uint32_t, tex_usage); /* tex_usage */
+
+ return ret;
+}
+
+struct rbug_proto_texture_read_reply * rbug_demarshal_texture_read_reply(struct rbug_proto_header *header)
+{
+ uint32_t len = 0;
+ uint32_t pos = 0;
+ uint8_t *data = NULL;
+ struct rbug_proto_texture_read_reply *ret;
+
+ if (!header)
+ return NULL;
+ if (header->opcode != (int16_t)RBUG_OP_TEXTURE_READ_REPLY)
+ return NULL;
+
+ pos = 0;
+ len = header->length * 4;
+ data = (uint8_t*)&header[1];
+ ret = MALLOC(sizeof(*ret));
+ if (!ret)
+ return NULL;
+
+ ret->header.__message = header;
+ ret->header.opcode = header->opcode;
+
+ READ(4, uint32_t, serial); /* serial */
+ READ(4, uint32_t, format); /* format */
+ READ(4, uint32_t, blockw); /* blockw */
+ READ(4, uint32_t, blockh); /* blockh */
+ READ(4, uint32_t, blocksize); /* blocksize */
+ READ_ARRAY(1, uint8_t, data); /* data */
+ READ(4, uint32_t, stride); /* stride */
+
+ return ret;
+}
diff --git a/src/gallium/auxiliary/rbug/rbug_texture.h b/src/gallium/auxiliary/rbug/rbug_texture.h
new file mode 100644
index 0000000000..fbb247e1d4
--- /dev/null
+++ b/src/gallium/auxiliary/rbug/rbug_texture.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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.
+ */
+
+/*
+ * This file holds structs decelerations and function prototypes for one of
+ * the rbug extensions. Implementation of the functions is in the same folder
+ * in the c file matching this file's name.
+ *
+ * The structs what is returned from the demarshal functions. The functions
+ * starting rbug_send_* encodes a call to the write format and sends that to
+ * the supplied connection, while functions starting with rbug_demarshal_*
+ * demarshal data from the wire protocol.
+ *
+ * Structs and functions ending with _reply are replies to requests.
+ */
+
+#ifndef _RBUG_PROTO_TEXTURE_H_
+#define _RBUG_PROTO_TEXTURE_H_
+
+#include "rbug/rbug_proto.h"
+#include "rbug/rbug_core.h"
+
+struct rbug_proto_texture_list
+{
+ struct rbug_header header;
+};
+
+struct rbug_proto_texture_info
+{
+ struct rbug_header header;
+ rbug_texture_t texture;
+};
+
+struct rbug_proto_texture_write
+{
+ struct rbug_header header;
+ rbug_texture_t texture;
+ uint32_t face;
+ uint32_t level;
+ uint32_t zslice;
+ uint32_t x;
+ uint32_t y;
+ uint32_t w;
+ uint32_t h;
+ uint8_t *data;
+ uint32_t data_len;
+ uint32_t stride;
+};
+
+struct rbug_proto_texture_read
+{
+ struct rbug_header header;
+ rbug_texture_t texture;
+ uint32_t face;
+ uint32_t level;
+ uint32_t zslice;
+ uint32_t x;
+ uint32_t y;
+ uint32_t w;
+ uint32_t h;
+};
+
+struct rbug_proto_texture_list_reply
+{
+ struct rbug_header header;
+ uint32_t serial;
+ rbug_texture_t *textures;
+ uint32_t textures_len;
+};
+
+struct rbug_proto_texture_info_reply
+{
+ struct rbug_header header;
+ uint32_t serial;
+ uint32_t target;
+ uint32_t format;
+ uint32_t *width;
+ uint32_t width_len;
+ uint32_t *height;
+ uint32_t height_len;
+ uint32_t *depth;
+ uint32_t depth_len;
+ uint32_t blockw;
+ uint32_t blockh;
+ uint32_t blocksize;
+ uint32_t last_level;
+ uint32_t nr_samples;
+ uint32_t tex_usage;
+};
+
+struct rbug_proto_texture_read_reply
+{
+ struct rbug_header header;
+ uint32_t serial;
+ uint32_t format;
+ uint32_t blockw;
+ uint32_t blockh;
+ uint32_t blocksize;
+ uint8_t *data;
+ uint32_t data_len;
+ uint32_t stride;
+};
+
+int rbug_send_texture_list(struct rbug_connection *__con,
+ uint32_t *__serial);
+
+int rbug_send_texture_info(struct rbug_connection *__con,
+ rbug_texture_t texture,
+ uint32_t *__serial);
+
+int rbug_send_texture_write(struct rbug_connection *__con,
+ rbug_texture_t texture,
+ uint32_t face,
+ uint32_t level,
+ uint32_t zslice,
+ uint32_t x,
+ uint32_t y,
+ uint32_t w,
+ uint32_t h,
+ uint8_t *data,
+ uint32_t data_len,
+ uint32_t stride,
+ uint32_t *__serial);
+
+int rbug_send_texture_read(struct rbug_connection *__con,
+ rbug_texture_t texture,
+ uint32_t face,
+ uint32_t level,
+ uint32_t zslice,
+ uint32_t x,
+ uint32_t y,
+ uint32_t w,
+ uint32_t h,
+ uint32_t *__serial);
+
+int rbug_send_texture_list_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ rbug_texture_t *textures,
+ uint32_t textures_len,
+ uint32_t *__serial);
+
+int rbug_send_texture_info_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t target,
+ uint32_t format,
+ uint32_t *width,
+ uint32_t width_len,
+ uint32_t *height,
+ uint32_t height_len,
+ uint32_t *depth,
+ uint32_t depth_len,
+ uint32_t blockw,
+ uint32_t blockh,
+ uint32_t blocksize,
+ uint32_t last_level,
+ uint32_t nr_samples,
+ uint32_t tex_usage,
+ uint32_t *__serial);
+
+int rbug_send_texture_read_reply(struct rbug_connection *__con,
+ uint32_t serial,
+ uint32_t format,
+ uint32_t blockw,
+ uint32_t blockh,
+ uint32_t blocksize,
+ uint8_t *data,
+ uint32_t data_len,
+ uint32_t stride,
+ uint32_t *__serial);
+
+struct rbug_proto_texture_list * rbug_demarshal_texture_list(struct rbug_proto_header *header);
+
+struct rbug_proto_texture_info * rbug_demarshal_texture_info(struct rbug_proto_header *header);
+
+struct rbug_proto_texture_write * rbug_demarshal_texture_write(struct rbug_proto_header *header);
+
+struct rbug_proto_texture_read * rbug_demarshal_texture_read(struct rbug_proto_header *header);
+
+struct rbug_proto_texture_list_reply * rbug_demarshal_texture_list_reply(struct rbug_proto_header *header);
+
+struct rbug_proto_texture_info_reply * rbug_demarshal_texture_info_reply(struct rbug_proto_header *header);
+
+struct rbug_proto_texture_read_reply * rbug_demarshal_texture_read_reply(struct rbug_proto_header *header);
+
+#endif
diff --git a/src/gallium/auxiliary/rtasm/Makefile b/src/gallium/auxiliary/rtasm/Makefile
new file mode 100644
index 0000000000..ab8ea464c6
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/Makefile
@@ -0,0 +1,13 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = rtasm
+
+C_SOURCES = \
+ rtasm_cpu.c \
+ rtasm_execmem.c \
+ rtasm_x86sse.c \
+ rtasm_ppc.c \
+ rtasm_ppc_spe.c
+
+include ../../Makefile.template
diff --git a/src/gallium/auxiliary/rtasm/SConscript b/src/gallium/auxiliary/rtasm/SConscript
new file mode 100644
index 0000000000..eb48368acc
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/SConscript
@@ -0,0 +1,13 @@
+Import('*')
+
+rtasm = env.ConvenienceLibrary(
+ target = 'rtasm',
+ source = [
+ 'rtasm_cpu.c',
+ 'rtasm_execmem.c',
+ 'rtasm_x86sse.c',
+ 'rtasm_ppc.c',
+ 'rtasm_ppc_spe.c',
+ ])
+
+auxiliaries.insert(0, rtasm)
diff --git a/src/gallium/auxiliary/rtasm/rtasm_cpu.c b/src/gallium/auxiliary/rtasm/rtasm_cpu.c
new file mode 100644
index 0000000000..2e15751e50
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/rtasm_cpu.c
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_debug.h"
+#include "rtasm_cpu.h"
+
+
+#if defined(PIPE_ARCH_X86)
+static boolean rtasm_sse_enabled(void)
+{
+ static boolean firsttime = 1;
+ static boolean enabled;
+
+ /* This gets called quite often at the moment:
+ */
+ if (firsttime) {
+ enabled = !debug_get_bool_option("GALLIUM_NOSSE", FALSE);
+ firsttime = FALSE;
+ }
+ return enabled;
+}
+#endif
+
+int rtasm_cpu_has_sse(void)
+{
+ /* FIXME: actually detect this at run-time */
+#if defined(PIPE_ARCH_X86)
+ return rtasm_sse_enabled();
+#else
+ return 0;
+#endif
+}
+
+int rtasm_cpu_has_sse2(void)
+{
+ /* FIXME: actually detect this at run-time */
+#if defined(PIPE_ARCH_X86)
+ return rtasm_sse_enabled();
+#else
+ return 0;
+#endif
+}
diff --git a/src/gallium/auxiliary/rtasm/rtasm_cpu.h b/src/gallium/auxiliary/rtasm/rtasm_cpu.h
new file mode 100644
index 0000000000..ebc71634fd
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/rtasm_cpu.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Runtime detection of CPU capabilities.
+ */
+
+#ifndef _RTASM_CPU_H_
+#define _RTASM_CPU_H_
+
+
+int rtasm_cpu_has_sse(void);
+
+int rtasm_cpu_has_sse2(void);
+
+
+#endif /* _RTASM_CPU_H_ */
diff --git a/src/gallium/auxiliary/rtasm/rtasm_execmem.c b/src/gallium/auxiliary/rtasm/rtasm_execmem.c
new file mode 100644
index 0000000000..01811d5011
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/rtasm_execmem.c
@@ -0,0 +1,141 @@
+/**************************************************************************
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * \file exemem.c
+ * Functions for allocating executable memory.
+ *
+ * \author Keith Whitwell
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_thread.h"
+#include "util/u_memory.h"
+
+#include "rtasm_execmem.h"
+
+#if defined(PIPE_OS_BSD)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)
+
+
+/*
+ * Allocate a large block of memory which can hold code then dole it out
+ * in pieces by means of the generic memory manager code.
+ */
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include "pipe/p_thread.h"
+#include "util/u_mm.h"
+
+#define EXEC_HEAP_SIZE (10*1024*1024)
+
+pipe_static_mutex(exec_mutex);
+
+static struct mem_block *exec_heap = NULL;
+static unsigned char *exec_mem = NULL;
+
+
+static void
+init_heap(void)
+{
+ if (!exec_heap)
+ exec_heap = u_mmInit( 0, EXEC_HEAP_SIZE );
+
+ if (!exec_mem)
+ exec_mem = (unsigned char *) mmap(0, EXEC_HEAP_SIZE,
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+
+void *
+rtasm_exec_malloc(size_t size)
+{
+ struct mem_block *block = NULL;
+ void *addr = NULL;
+
+ pipe_mutex_lock(exec_mutex);
+
+ init_heap();
+
+ if (exec_heap) {
+ size = (size + 31) & ~31; /* next multiple of 32 bytes */
+ block = u_mmAllocMem( exec_heap, size, 5, 0 ); /* 5 -> 32-byte alignment */
+ }
+
+ if (block)
+ addr = exec_mem + block->ofs;
+ else
+ debug_printf("rtasm_exec_malloc failed\n");
+
+ pipe_mutex_unlock(exec_mutex);
+
+ return addr;
+}
+
+
+void
+rtasm_exec_free(void *addr)
+{
+ pipe_mutex_lock(exec_mutex);
+
+ if (exec_heap) {
+ struct mem_block *block = u_mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem);
+
+ if (block)
+ u_mmFreeMem(block);
+ }
+
+ pipe_mutex_unlock(exec_mutex);
+}
+
+
+#else /* PIPE_OS_LINUX || PIPE_OS_BSD || PIPE_OS_SOLARIS */
+
+/*
+ * Just use regular memory.
+ */
+
+void *
+rtasm_exec_malloc(size_t size)
+{
+ return MALLOC( size );
+}
+
+
+void
+rtasm_exec_free(void *addr)
+{
+ FREE(addr);
+}
+
+
+#endif /* PIPE_OS_LINUX || PIPE_OS_BSD || PIPE_OS_SOLARIS */
diff --git a/src/mesa/shader/prog_debug.h b/src/gallium/auxiliary/rtasm/rtasm_execmem.h
index fc400e19de..155c6d34e0 100644
--- a/src/mesa/shader/prog_debug.h
+++ b/src/gallium/auxiliary/rtasm/rtasm_execmem.h
@@ -1,8 +1,6 @@
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
+/**************************************************************************
*
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2005 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"),
@@ -20,25 +18,28 @@
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
+ *
+ **************************************************************************/
+/**
+ * \file exemem.c
+ * Functions for allocating executable memory.
+ *
+ * \author Keith Whitwell
+ */
-#ifndef PROG_DEBUG_H
-#define PROG_DEBUG_H 1
+#ifndef _RTASM_EXECMEM_H_
+#define _RTASM_EXECMEM_H_
+#include "pipe/p_compiler.h"
-/*
- * GL_MESA_program_debug
- */
-extern void
-_mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
- GLvoid *data);
+extern void *
+rtasm_exec_malloc( size_t size );
-extern void
-_mesa_GetProgramRegisterfvMESA(GLenum target, GLsizei len,
- const GLubyte *registerName, GLfloat *v);
+extern void
+rtasm_exec_free( void *addr );
-#endif /* PROG_DEBUG_H */
+#endif
diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc.c b/src/gallium/auxiliary/rtasm/rtasm_ppc.c
new file mode 100644
index 0000000000..ef4b306cb6
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/rtasm_ppc.c
@@ -0,0 +1,1077 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2008 Tungsten Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * PPC code generation.
+ * For reference, see http://www.power.org/resources/reading/PowerISA_V2.05.pdf
+ * ABI info: http://www.cs.utsa.edu/~whaley/teach/cs6463FHPO/LEC/lec12_ho.pdf
+ *
+ * Other PPC refs:
+ * http://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
+ * http://www.ibm.com/developerworks/eserver/library/es-archguide-v2.html
+ * http://www.freescale.com/files/product/doc/MPCFPE32B.pdf
+ *
+ * \author Brian Paul
+ */
+
+
+#include <stdio.h>
+#include "util/u_memory.h"
+#include "util/u_debug.h"
+#include "rtasm_execmem.h"
+#include "rtasm_ppc.h"
+
+
+void
+ppc_init_func(struct ppc_function *p)
+{
+ uint i;
+
+ memset(p, 0, sizeof(*p));
+
+ p->num_inst = 0;
+ p->max_inst = 100; /* first guess at buffer size */
+ p->store = rtasm_exec_malloc(p->max_inst * PPC_INST_SIZE);
+ p->reg_used = 0x0;
+ p->fp_used = 0x0;
+ p->vec_used = 0x0;
+
+ p->print = FALSE;
+ p->indent = 0;
+
+ /* only allow using gp registers 3..12 for now */
+ for (i = 0; i < 3; i++)
+ ppc_reserve_register(p, i);
+ for (i = 12; i < PPC_NUM_REGS; i++)
+ ppc_reserve_register(p, i);
+}
+
+
+void
+ppc_release_func(struct ppc_function *p)
+{
+ assert(p->num_inst <= p->max_inst);
+ if (p->store != NULL) {
+ rtasm_exec_free(p->store);
+ }
+ p->store = NULL;
+}
+
+
+uint
+ppc_num_instructions(const struct ppc_function *p)
+{
+ return p->num_inst;
+}
+
+
+void (*ppc_get_func(struct ppc_function *p))(void)
+{
+#if 0
+ DUMP_END();
+ if (DISASSEM && p->store)
+ debug_printf("disassemble %p %p\n", p->store, p->csr);
+
+ if (p->store == p->error_overflow)
+ return (void (*)(void)) NULL;
+ else
+#endif
+ return (void (*)(void)) p->store;
+}
+
+
+void
+ppc_dump_func(const struct ppc_function *p)
+{
+ uint i;
+ for (i = 0; i < p->num_inst; i++) {
+ debug_printf("%3u: 0x%08x\n", i, p->store[i]);
+ }
+}
+
+
+void
+ppc_print_code(struct ppc_function *p, boolean enable)
+{
+ p->print = enable;
+}
+
+
+void
+ppc_indent(struct ppc_function *p, int spaces)
+{
+ p->indent += spaces;
+}
+
+
+static void
+indent(const struct ppc_function *p)
+{
+ int i;
+ for (i = 0; i < p->indent; i++) {
+ putchar(' ');
+ }
+}
+
+
+void
+ppc_comment(struct ppc_function *p, int rel_indent, const char *s)
+{
+ if (p->print) {
+ p->indent += rel_indent;
+ indent(p);
+ p->indent -= rel_indent;
+ printf("# %s\n", s);
+ }
+}
+
+
+/**
+ * Mark a register as being unavailable.
+ */
+int
+ppc_reserve_register(struct ppc_function *p, int reg)
+{
+ assert(reg < PPC_NUM_REGS);
+ p->reg_used |= (1 << reg);
+ return reg;
+}
+
+
+/**
+ * Allocate a general purpose register.
+ * \return register index or -1 if none left.
+ */
+int
+ppc_allocate_register(struct ppc_function *p)
+{
+ unsigned i;
+ for (i = 0; i < PPC_NUM_REGS; i++) {
+ const uint32_t mask = 1 << i;
+ if ((p->reg_used & mask) == 0) {
+ p->reg_used |= mask;
+ return i;
+ }
+ }
+ printf("OUT OF PPC registers!\n");
+ return -1;
+}
+
+
+/**
+ * Mark the given general purpose register as "unallocated".
+ */
+void
+ppc_release_register(struct ppc_function *p, int reg)
+{
+ assert(reg < PPC_NUM_REGS);
+ assert(p->reg_used & (1 << reg));
+ p->reg_used &= ~(1 << reg);
+}
+
+
+/**
+ * Allocate a floating point register.
+ * \return register index or -1 if none left.
+ */
+int
+ppc_allocate_fp_register(struct ppc_function *p)
+{
+ unsigned i;
+ for (i = 0; i < PPC_NUM_FP_REGS; i++) {
+ const uint32_t mask = 1 << i;
+ if ((p->fp_used & mask) == 0) {
+ p->fp_used |= mask;
+ return i;
+ }
+ }
+ printf("OUT OF PPC FP registers!\n");
+ return -1;
+}
+
+
+/**
+ * Mark the given floating point register as "unallocated".
+ */
+void
+ppc_release_fp_register(struct ppc_function *p, int reg)
+{
+ assert(reg < PPC_NUM_FP_REGS);
+ assert(p->fp_used & (1 << reg));
+ p->fp_used &= ~(1 << reg);
+}
+
+
+/**
+ * Allocate a vector register.
+ * \return register index or -1 if none left.
+ */
+int
+ppc_allocate_vec_register(struct ppc_function *p)
+{
+ unsigned i;
+ for (i = 0; i < PPC_NUM_VEC_REGS; i++) {
+ const uint32_t mask = 1 << i;
+ if ((p->vec_used & mask) == 0) {
+ p->vec_used |= mask;
+ return i;
+ }
+ }
+ printf("OUT OF PPC VEC registers!\n");
+ return -1;
+}
+
+
+/**
+ * Mark the given vector register as "unallocated".
+ */
+void
+ppc_release_vec_register(struct ppc_function *p, int reg)
+{
+ assert(reg < PPC_NUM_VEC_REGS);
+ assert(p->vec_used & (1 << reg));
+ p->vec_used &= ~(1 << reg);
+}
+
+
+/**
+ * Append instruction to instruction buffer. Grow buffer if out of room.
+ */
+static void
+emit_instruction(struct ppc_function *p, uint32_t inst_bits)
+{
+ if (!p->store)
+ return; /* out of memory, drop the instruction */
+
+ if (p->num_inst == p->max_inst) {
+ /* allocate larger buffer */
+ uint32_t *newbuf;
+ p->max_inst *= 2; /* 2x larger */
+ newbuf = rtasm_exec_malloc(p->max_inst * PPC_INST_SIZE);
+ if (newbuf) {
+ memcpy(newbuf, p->store, p->num_inst * PPC_INST_SIZE);
+ }
+ rtasm_exec_free(p->store);
+ p->store = newbuf;
+ if (!p->store) {
+ /* out of memory */
+ p->num_inst = 0;
+ return;
+ }
+ }
+
+ p->store[p->num_inst++] = inst_bits;
+}
+
+
+union vx_inst {
+ uint32_t bits;
+ struct {
+ unsigned op:6;
+ unsigned vD:5;
+ unsigned vA:5;
+ unsigned vB:5;
+ unsigned op2:11;
+ } inst;
+};
+
+static INLINE void
+emit_vx(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB,
+ const char *format, boolean transpose)
+{
+ union vx_inst inst;
+ inst.inst.op = 4;
+ inst.inst.vD = vD;
+ inst.inst.vA = vA;
+ inst.inst.vB = vB;
+ inst.inst.op2 = op2;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ if (transpose)
+ printf(format, vD, vB, vA);
+ else
+ printf(format, vD, vA, vB);
+ }
+}
+
+
+union vxr_inst {
+ uint32_t bits;
+ struct {
+ unsigned op:6;
+ unsigned vD:5;
+ unsigned vA:5;
+ unsigned vB:5;
+ unsigned rC:1;
+ unsigned op2:10;
+ } inst;
+};
+
+static INLINE void
+emit_vxr(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB,
+ const char *format)
+{
+ union vxr_inst inst;
+ inst.inst.op = 4;
+ inst.inst.vD = vD;
+ inst.inst.vA = vA;
+ inst.inst.vB = vB;
+ inst.inst.rC = 0;
+ inst.inst.op2 = op2;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf(format, vD, vA, vB);
+ }
+}
+
+
+union va_inst {
+ uint32_t bits;
+ struct {
+ unsigned op:6;
+ unsigned vD:5;
+ unsigned vA:5;
+ unsigned vB:5;
+ unsigned vC:5;
+ unsigned op2:6;
+ } inst;
+};
+
+static INLINE void
+emit_va(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB, uint vC,
+ const char *format)
+{
+ union va_inst inst;
+ inst.inst.op = 4;
+ inst.inst.vD = vD;
+ inst.inst.vA = vA;
+ inst.inst.vB = vB;
+ inst.inst.vC = vC;
+ inst.inst.op2 = op2;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf(format, vD, vA, vB, vC);
+ }
+}
+
+
+union i_inst {
+ uint32_t bits;
+ struct {
+ unsigned op:6;
+ unsigned li:24;
+ unsigned aa:1;
+ unsigned lk:1;
+ } inst;
+};
+
+static INLINE void
+emit_i(struct ppc_function *p, uint op, uint li, uint aa, uint lk)
+{
+ union i_inst inst;
+ inst.inst.op = op;
+ inst.inst.li = li;
+ inst.inst.aa = aa;
+ inst.inst.lk = lk;
+ emit_instruction(p, inst.bits);
+}
+
+
+union xl_inst {
+ uint32_t bits;
+ struct {
+ unsigned op:6;
+ unsigned bo:5;
+ unsigned bi:5;
+ unsigned unused:3;
+ unsigned bh:2;
+ unsigned op2:10;
+ unsigned lk:1;
+ } inst;
+};
+
+static INLINE void
+emit_xl(struct ppc_function *p, uint op, uint bo, uint bi, uint bh,
+ uint op2, uint lk)
+{
+ union xl_inst inst;
+ inst.inst.op = op;
+ inst.inst.bo = bo;
+ inst.inst.bi = bi;
+ inst.inst.unused = 0x0;
+ inst.inst.bh = bh;
+ inst.inst.op2 = op2;
+ inst.inst.lk = lk;
+ emit_instruction(p, inst.bits);
+}
+
+static INLINE void
+dump_xl(const char *name, uint inst)
+{
+ union xl_inst i;
+
+ i.bits = inst;
+ debug_printf("%s = 0x%08x\n", name, inst);
+ debug_printf(" op: %d 0x%x\n", i.inst.op, i.inst.op);
+ debug_printf(" bo: %d 0x%x\n", i.inst.bo, i.inst.bo);
+ debug_printf(" bi: %d 0x%x\n", i.inst.bi, i.inst.bi);
+ debug_printf(" unused: %d 0x%x\n", i.inst.unused, i.inst.unused);
+ debug_printf(" bh: %d 0x%x\n", i.inst.bh, i.inst.bh);
+ debug_printf(" op2: %d 0x%x\n", i.inst.op2, i.inst.op2);
+ debug_printf(" lk: %d 0x%x\n", i.inst.lk, i.inst.lk);
+}
+
+
+union x_inst {
+ uint32_t bits;
+ struct {
+ unsigned op:6;
+ unsigned vrs:5;
+ unsigned ra:5;
+ unsigned rb:5;
+ unsigned op2:10;
+ unsigned unused:1;
+ } inst;
+};
+
+static INLINE void
+emit_x(struct ppc_function *p, uint op, uint vrs, uint ra, uint rb, uint op2,
+ const char *format)
+{
+ union x_inst inst;
+ inst.inst.op = op;
+ inst.inst.vrs = vrs;
+ inst.inst.ra = ra;
+ inst.inst.rb = rb;
+ inst.inst.op2 = op2;
+ inst.inst.unused = 0x0;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf(format, vrs, ra, rb);
+ }
+}
+
+
+union d_inst {
+ uint32_t bits;
+ struct {
+ unsigned op:6;
+ unsigned rt:5;
+ unsigned ra:5;
+ unsigned si:16;
+ } inst;
+};
+
+static INLINE void
+emit_d(struct ppc_function *p, uint op, uint rt, uint ra, int si,
+ const char *format, boolean transpose)
+{
+ union d_inst inst;
+ assert(si >= -32768);
+ assert(si <= 32767);
+ inst.inst.op = op;
+ inst.inst.rt = rt;
+ inst.inst.ra = ra;
+ inst.inst.si = (unsigned) (si & 0xffff);
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ if (transpose)
+ printf(format, rt, si, ra);
+ else
+ printf(format, rt, ra, si);
+ }
+}
+
+
+union a_inst {
+ uint32_t bits;
+ struct {
+ unsigned op:6;
+ unsigned frt:5;
+ unsigned fra:5;
+ unsigned frb:5;
+ unsigned unused:5;
+ unsigned op2:5;
+ unsigned rc:1;
+ } inst;
+};
+
+static INLINE void
+emit_a(struct ppc_function *p, uint op, uint frt, uint fra, uint frb, uint op2,
+ uint rc, const char *format)
+{
+ union a_inst inst;
+ inst.inst.op = op;
+ inst.inst.frt = frt;
+ inst.inst.fra = fra;
+ inst.inst.frb = frb;
+ inst.inst.unused = 0x0;
+ inst.inst.op2 = op2;
+ inst.inst.rc = rc;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf(format, frt, fra, frb);
+ }
+}
+
+
+union xo_inst {
+ uint32_t bits;
+ struct {
+ unsigned op:6;
+ unsigned rt:5;
+ unsigned ra:5;
+ unsigned rb:5;
+ unsigned oe:1;
+ unsigned op2:9;
+ unsigned rc:1;
+ } inst;
+};
+
+static INLINE void
+emit_xo(struct ppc_function *p, uint op, uint rt, uint ra, uint rb, uint oe,
+ uint op2, uint rc, const char *format)
+{
+ union xo_inst inst;
+ inst.inst.op = op;
+ inst.inst.rt = rt;
+ inst.inst.ra = ra;
+ inst.inst.rb = rb;
+ inst.inst.oe = oe;
+ inst.inst.op2 = op2;
+ inst.inst.rc = rc;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf(format, rt, ra, rb);
+ }
+}
+
+
+
+
+
+/**
+ ** float vector arithmetic
+ **/
+
+/** vector float add */
+void
+ppc_vaddfp(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 10, vD, vA, vB, "vaddfp\t%u, v%u, v%u\n", FALSE);
+}
+
+/** vector float substract */
+void
+ppc_vsubfp(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 74, vD, vA, vB, "vsubfp\tv%u, v%u, v%u\n", FALSE);
+}
+
+/** vector float min */
+void
+ppc_vminfp(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 1098, vD, vA, vB, "vminfp\tv%u, v%u, v%u\n", FALSE);
+}
+
+/** vector float max */
+void
+ppc_vmaxfp(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 1034, vD, vA, vB, "vmaxfp\tv%u, v%u, v%u\n", FALSE);
+}
+
+/** vector float mult add: vD = vA * vB + vC */
+void
+ppc_vmaddfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
+{
+ /* note arg order */
+ emit_va(p, 46, vD, vA, vC, vB, "vmaddfp\tv%u, v%u, v%u, v%u\n");
+}
+
+/** vector float negative mult subtract: vD = vA - vB * vC */
+void
+ppc_vnmsubfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
+{
+ /* note arg order */
+ emit_va(p, 47, vD, vB, vA, vC, "vnmsubfp\tv%u, v%u, v%u, v%u\n");
+}
+
+/** vector float compare greater than */
+void
+ppc_vcmpgtfpx(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vxr(p, 710, vD, vA, vB, "vcmpgtfpx\tv%u, v%u, v%u");
+}
+
+/** vector float compare greater than or equal to */
+void
+ppc_vcmpgefpx(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vxr(p, 454, vD, vA, vB, "vcmpgefpx\tv%u, v%u, v%u");
+}
+
+/** vector float compare equal */
+void
+ppc_vcmpeqfpx(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vxr(p, 198, vD, vA, vB, "vcmpeqfpx\tv%u, v%u, v%u");
+}
+
+/** vector float 2^x */
+void
+ppc_vexptefp(struct ppc_function *p, uint vD, uint vB)
+{
+ emit_vx(p, 394, vD, 0, vB, "vexptefp\tv%u, 0%u, v%u\n", FALSE);
+}
+
+/** vector float log2(x) */
+void
+ppc_vlogefp(struct ppc_function *p, uint vD, uint vB)
+{
+ emit_vx(p, 458, vD, 0, vB, "vlogefp\tv%u, 0%u, v%u\n", FALSE);
+}
+
+/** vector float reciprocol */
+void
+ppc_vrefp(struct ppc_function *p, uint vD, uint vB)
+{
+ emit_vx(p, 266, vD, 0, vB, "vrefp\tv%u, 0%u, v%u\n", FALSE);
+}
+
+/** vector float reciprocol sqrt estimate */
+void
+ppc_vrsqrtefp(struct ppc_function *p, uint vD, uint vB)
+{
+ emit_vx(p, 330, vD, 0, vB, "vrsqrtefp\tv%u, 0%u, v%u\n", FALSE);
+}
+
+/** vector float round to negative infinity */
+void
+ppc_vrfim(struct ppc_function *p, uint vD, uint vB)
+{
+ emit_vx(p, 714, vD, 0, vB, "vrfim\tv%u, 0%u, v%u\n", FALSE);
+}
+
+/** vector float round to positive infinity */
+void
+ppc_vrfip(struct ppc_function *p, uint vD, uint vB)
+{
+ emit_vx(p, 650, vD, 0, vB, "vrfip\tv%u, 0%u, v%u\n", FALSE);
+}
+
+/** vector float round to nearest int */
+void
+ppc_vrfin(struct ppc_function *p, uint vD, uint vB)
+{
+ emit_vx(p, 522, vD, 0, vB, "vrfin\tv%u, 0%u, v%u\n", FALSE);
+}
+
+/** vector float round to int toward zero */
+void
+ppc_vrfiz(struct ppc_function *p, uint vD, uint vB)
+{
+ emit_vx(p, 586, vD, 0, vB, "vrfiz\tv%u, 0%u, v%u\n", FALSE);
+}
+
+/** vector store: store vR at mem[rA+rB] */
+void
+ppc_stvx(struct ppc_function *p, uint vR, uint rA, uint rB)
+{
+ emit_x(p, 31, vR, rA, rB, 231, "stvx\tv%u, r%u, r%u\n");
+}
+
+/** vector load: vR = mem[rA+rB] */
+void
+ppc_lvx(struct ppc_function *p, uint vR, uint rA, uint rB)
+{
+ emit_x(p, 31, vR, rA, rB, 103, "lvx\tv%u, r%u, r%u\n");
+}
+
+/** load vector element word: vR = mem_word[ra+rb] */
+void
+ppc_lvewx(struct ppc_function *p, uint vR, uint rA, uint rB)
+{
+ emit_x(p, 31, vR, rA, rB, 71, "lvewx\tv%u, r%u, r%u\n");
+}
+
+
+
+
+/**
+ ** vector bitwise operations
+ **/
+
+/** vector and */
+void
+ppc_vand(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 1028, vD, vA, vB, "vand\tv%u, v%u, v%u\n", FALSE);
+}
+
+/** vector and complement */
+void
+ppc_vandc(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 1092, vD, vA, vB, "vandc\tv%u, v%u, v%u\n", FALSE);
+}
+
+/** vector or */
+void
+ppc_vor(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 1156, vD, vA, vB, "vor\tv%u, v%u, v%u\n", FALSE);
+}
+
+/** vector nor */
+void
+ppc_vnor(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 1284, vD, vA, vB, "vnor\tv%u, v%u, v%u\n", FALSE);
+}
+
+/** vector xor */
+void
+ppc_vxor(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 1220, vD, vA, vB, "vxor\tv%u, v%u, v%u\n", FALSE);
+}
+
+/** Pseudo-instruction: vector move */
+void
+ppc_vmove(struct ppc_function *p, uint vD, uint vA)
+{
+ boolean print = p->print;
+ p->print = FALSE;
+ ppc_vor(p, vD, vA, vA);
+ if (print) {
+ indent(p);
+ printf("vor\tv%u, v%u, v%u \t# v%u = v%u\n", vD, vA, vA, vD, vA);
+ }
+ p->print = print;
+}
+
+/** Set vector register to {0,0,0,0} */
+void
+ppc_vzero(struct ppc_function *p, uint vr)
+{
+ boolean print = p->print;
+ p->print = FALSE;
+ ppc_vxor(p, vr, vr, vr);
+ if (print) {
+ indent(p);
+ printf("vxor\tv%u, v%u, v%u \t# v%u = {0,0,0,0}\n", vr, vr, vr, vr);
+ }
+ p->print = print;
+}
+
+
+
+
+/**
+ ** Vector shuffle / select / splat / etc
+ **/
+
+/** vector permute */
+void
+ppc_vperm(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
+{
+ emit_va(p, 43, vD, vA, vB, vC, "vperm\tr%u, r%u, r%u, r%u");
+}
+
+/** vector select */
+void
+ppc_vsel(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
+{
+ emit_va(p, 42, vD, vA, vB, vC, "vsel\tr%u, r%u, r%u, r%u");
+}
+
+/** vector splat byte */
+void
+ppc_vspltb(struct ppc_function *p, uint vD, uint vB, uint imm)
+{
+ emit_vx(p, 42, vD, imm, vB, "vspltb\tv%u, v%u, %u\n", TRUE);
+}
+
+/** vector splat half word */
+void
+ppc_vsplthw(struct ppc_function *p, uint vD, uint vB, uint imm)
+{
+ emit_vx(p, 588, vD, imm, vB, "vsplthw\tv%u, v%u, %u\n", TRUE);
+}
+
+/** vector splat word */
+void
+ppc_vspltw(struct ppc_function *p, uint vD, uint vB, uint imm)
+{
+ emit_vx(p, 652, vD, imm, vB, "vspltw\tv%u, v%u, %u\n", TRUE);
+}
+
+/** vector splat signed immediate word */
+void
+ppc_vspltisw(struct ppc_function *p, uint vD, int imm)
+{
+ assert(imm >= -16);
+ assert(imm < 15);
+ emit_vx(p, 908, vD, imm, 0, "vspltisw\tv%u, %d, %u\n", FALSE);
+}
+
+/** vector shift left word: vD[word] = vA[word] << (vB[word] & 0x1f) */
+void
+ppc_vslw(struct ppc_function *p, uint vD, uint vA, uint vB)
+{
+ emit_vx(p, 388, vD, vA, vB, "vslw\tv%u, v%u, v%u\n", FALSE);
+}
+
+
+
+
+/**
+ ** integer arithmetic
+ **/
+
+/** rt = ra + imm */
+void
+ppc_addi(struct ppc_function *p, uint rt, uint ra, int imm)
+{
+ emit_d(p, 14, rt, ra, imm, "addi\tr%u, r%u, %d\n", FALSE);
+}
+
+/** rt = ra + (imm << 16) */
+void
+ppc_addis(struct ppc_function *p, uint rt, uint ra, int imm)
+{
+ emit_d(p, 15, rt, ra, imm, "addis\tr%u, r%u, %d\n", FALSE);
+}
+
+/** rt = ra + rb */
+void
+ppc_add(struct ppc_function *p, uint rt, uint ra, uint rb)
+{
+ emit_xo(p, 31, rt, ra, rb, 0, 266, 0, "add\tr%u, r%u, r%u\n");
+}
+
+/** rt = ra AND ra */
+void
+ppc_and(struct ppc_function *p, uint rt, uint ra, uint rb)
+{
+ emit_x(p, 31, ra, rt, rb, 28, "and\tr%u, r%u, r%u\n"); /* note argument order */
+}
+
+/** rt = ra AND imm */
+void
+ppc_andi(struct ppc_function *p, uint rt, uint ra, int imm)
+{
+ /* note argument order */
+ emit_d(p, 28, ra, rt, imm, "andi\tr%u, r%u, %d\n", FALSE);
+}
+
+/** rt = ra OR ra */
+void
+ppc_or(struct ppc_function *p, uint rt, uint ra, uint rb)
+{
+ emit_x(p, 31, ra, rt, rb, 444, "or\tr%u, r%u, r%u\n"); /* note argument order */
+}
+
+/** rt = ra OR imm */
+void
+ppc_ori(struct ppc_function *p, uint rt, uint ra, int imm)
+{
+ /* note argument order */
+ emit_d(p, 24, ra, rt, imm, "ori\tr%u, r%u, %d\n", FALSE);
+}
+
+/** rt = ra XOR ra */
+void
+ppc_xor(struct ppc_function *p, uint rt, uint ra, uint rb)
+{
+ emit_x(p, 31, ra, rt, rb, 316, "xor\tr%u, r%u, r%u\n"); /* note argument order */
+}
+
+/** rt = ra XOR imm */
+void
+ppc_xori(struct ppc_function *p, uint rt, uint ra, int imm)
+{
+ /* note argument order */
+ emit_d(p, 26, ra, rt, imm, "xori\tr%u, r%u, %d\n", FALSE);
+}
+
+/** pseudo instruction: move: rt = ra */
+void
+ppc_mr(struct ppc_function *p, uint rt, uint ra)
+{
+ ppc_or(p, rt, ra, ra);
+}
+
+/** pseudo instruction: load immediate: rt = imm */
+void
+ppc_li(struct ppc_function *p, uint rt, int imm)
+{
+ boolean print = p->print;
+ p->print = FALSE;
+ ppc_addi(p, rt, 0, imm);
+ if (print) {
+ indent(p);
+ printf("addi\tr%u, r0, %d \t# r%u = %d\n", rt, imm, rt, imm);
+ }
+ p->print = print;
+}
+
+/** rt = imm << 16 */
+void
+ppc_lis(struct ppc_function *p, uint rt, int imm)
+{
+ ppc_addis(p, rt, 0, imm);
+}
+
+/** rt = imm */
+void
+ppc_load_int(struct ppc_function *p, uint rt, int imm)
+{
+ ppc_lis(p, rt, (imm >> 16)); /* rt = imm >> 16 */
+ ppc_ori(p, rt, rt, (imm & 0xffff)); /* rt = rt | (imm & 0xffff) */
+}
+
+
+
+
+/**
+ ** integer load/store
+ **/
+
+/** store rs at memory[(ra)+d],
+ * then update ra = (ra)+d
+ */
+void
+ppc_stwu(struct ppc_function *p, uint rs, uint ra, int d)
+{
+ emit_d(p, 37, rs, ra, d, "stwu\tr%u, %d(r%u)\n", TRUE);
+}
+
+/** store rs at memory[(ra)+d] */
+void
+ppc_stw(struct ppc_function *p, uint rs, uint ra, int d)
+{
+ emit_d(p, 36, rs, ra, d, "stw\tr%u, %d(r%u)\n", TRUE);
+}
+
+/** Load rt = mem[(ra)+d]; then zero set high 32 bits to zero. */
+void
+ppc_lwz(struct ppc_function *p, uint rt, uint ra, int d)
+{
+ emit_d(p, 32, rt, ra, d, "lwz\tr%u, %d(r%u)\n", TRUE);
+}
+
+
+
+/**
+ ** Float (non-vector) arithmetic
+ **/
+
+/** add: frt = fra + frb */
+void
+ppc_fadd(struct ppc_function *p, uint frt, uint fra, uint frb)
+{
+ emit_a(p, 63, frt, fra, frb, 21, 0, "fadd\tf%u, f%u, f%u\n");
+}
+
+/** sub: frt = fra - frb */
+void
+ppc_fsub(struct ppc_function *p, uint frt, uint fra, uint frb)
+{
+ emit_a(p, 63, frt, fra, frb, 20, 0, "fsub\tf%u, f%u, f%u\n");
+}
+
+/** convert to int: rt = (int) ra */
+void
+ppc_fctiwz(struct ppc_function *p, uint rt, uint fra)
+{
+ emit_x(p, 63, rt, 0, fra, 15, "fctiwz\tr%u, r%u, r%u\n");
+}
+
+/** store frs at mem[(ra)+offset] */
+void
+ppc_stfs(struct ppc_function *p, uint frs, uint ra, int offset)
+{
+ emit_d(p, 52, frs, ra, offset, "stfs\tr%u, %d(r%u)\n", TRUE);
+}
+
+/** store frs at mem[(ra)+(rb)] */
+void
+ppc_stfiwx(struct ppc_function *p, uint frs, uint ra, uint rb)
+{
+ emit_x(p, 31, frs, ra, rb, 983, "stfiwx\tr%u, r%u, r%u\n");
+}
+
+/** load frt = mem[(ra)+offset] */
+void
+ppc_lfs(struct ppc_function *p, uint frt, uint ra, int offset)
+{
+ emit_d(p, 48, frt, ra, offset, "stfs\tr%u, %d(r%u)\n", TRUE);
+}
+
+
+
+
+
+/**
+ ** branch instructions
+ **/
+
+/** BLR: Branch to link register (p. 35) */
+void
+ppc_blr(struct ppc_function *p)
+{
+ emit_i(p, 18, 0, 0, 1);
+ if (p->print) {
+ indent(p);
+ printf("blr\n");
+ }
+}
+
+/** Branch Conditional to Link Register (p. 36) */
+void
+ppc_bclr(struct ppc_function *p, uint condOp, uint branchHint, uint condReg)
+{
+ emit_xl(p, 19, condOp, condReg, branchHint, 16, 0);
+ if (p->print) {
+ indent(p);
+ printf("bclr\t%u %u %u\n", condOp, branchHint, condReg);
+ }
+}
+
+/** Pseudo instruction: return from subroutine */
+void
+ppc_return(struct ppc_function *p)
+{
+ ppc_bclr(p, BRANCH_COND_ALWAYS, BRANCH_HINT_SUB_RETURN, 0);
+}
diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc.h b/src/gallium/auxiliary/rtasm/rtasm_ppc.h
new file mode 100644
index 0000000000..93e5f5187d
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/rtasm_ppc.h
@@ -0,0 +1,342 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2008 Tungsten Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * PPC code generation.
+ * \author Brian Paul
+ */
+
+
+#ifndef RTASM_PPC_H
+#define RTASM_PPC_H
+
+
+#include "pipe/p_compiler.h"
+
+
+#define PPC_INST_SIZE 4 /**< 4 bytes / instruction */
+
+#define PPC_NUM_REGS 32
+#define PPC_NUM_FP_REGS 32
+#define PPC_NUM_VEC_REGS 32
+
+/** Stack pointer register */
+#define PPC_REG_SP 1
+
+/** Branch conditions */
+#define BRANCH_COND_ALWAYS 0x14 /* binary 1z1zz (z=ignored) */
+
+/** Branch hints */
+#define BRANCH_HINT_SUB_RETURN 0x0 /* binary 00 */
+
+
+struct ppc_function
+{
+ uint32_t *store; /**< instruction buffer */
+ uint num_inst;
+ uint max_inst;
+ uint32_t reg_used; /** used/free general-purpose registers bitmask */
+ uint32_t fp_used; /** used/free floating point registers bitmask */
+ uint32_t vec_used; /** used/free vector registers bitmask */
+ int indent;
+ boolean print;
+};
+
+
+
+extern void ppc_init_func(struct ppc_function *p);
+extern void ppc_release_func(struct ppc_function *p);
+extern uint ppc_num_instructions(const struct ppc_function *p);
+extern void (*ppc_get_func( struct ppc_function *p ))( void );
+extern void ppc_dump_func(const struct ppc_function *p);
+
+extern void ppc_print_code(struct ppc_function *p, boolean enable);
+extern void ppc_indent(struct ppc_function *p, int spaces);
+extern void ppc_comment(struct ppc_function *p, int rel_indent, const char *s);
+
+extern int ppc_reserve_register(struct ppc_function *p, int reg);
+extern int ppc_allocate_register(struct ppc_function *p);
+extern void ppc_release_register(struct ppc_function *p, int reg);
+extern int ppc_allocate_fp_register(struct ppc_function *p);
+extern void ppc_release_fp_register(struct ppc_function *p, int reg);
+extern int ppc_allocate_vec_register(struct ppc_function *p);
+extern void ppc_release_vec_register(struct ppc_function *p, int reg);
+
+
+
+/**
+ ** float vector arithmetic
+ **/
+
+/** vector float add */
+extern void
+ppc_vaddfp(struct ppc_function *p,uint vD, uint vA, uint vB);
+
+/** vector float substract */
+extern void
+ppc_vsubfp(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector float min */
+extern void
+ppc_vminfp(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector float max */
+extern void
+ppc_vmaxfp(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector float mult add: vD = vA * vB + vC */
+extern void
+ppc_vmaddfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC);
+
+/** vector float negative mult subtract: vD = vA - vB * vC */
+extern void
+ppc_vnmsubfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC);
+
+/** vector float compare greater than */
+extern void
+ppc_vcmpgtfpx(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector float compare greater than or equal to */
+extern void
+ppc_vcmpgefpx(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector float compare equal */
+extern void
+ppc_vcmpeqfpx(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector float 2^x */
+extern void
+ppc_vexptefp(struct ppc_function *p, uint vD, uint vB);
+
+/** vector float log2(x) */
+extern void
+ppc_vlogefp(struct ppc_function *p, uint vD, uint vB);
+
+/** vector float reciprocol */
+extern void
+ppc_vrefp(struct ppc_function *p, uint vD, uint vB);
+
+/** vector float reciprocol sqrt estimate */
+extern void
+ppc_vrsqrtefp(struct ppc_function *p, uint vD, uint vB);
+
+/** vector float round to negative infinity */
+extern void
+ppc_vrfim(struct ppc_function *p, uint vD, uint vB);
+
+/** vector float round to positive infinity */
+extern void
+ppc_vrfip(struct ppc_function *p, uint vD, uint vB);
+
+/** vector float round to nearest int */
+extern void
+ppc_vrfin(struct ppc_function *p, uint vD, uint vB);
+
+/** vector float round to int toward zero */
+extern void
+ppc_vrfiz(struct ppc_function *p, uint vD, uint vB);
+
+
+/** vector store: store vR at mem[vA+vB] */
+extern void
+ppc_stvx(struct ppc_function *p, uint vR, uint vA, uint vB);
+
+/** vector load: vR = mem[vA+vB] */
+extern void
+ppc_lvx(struct ppc_function *p, uint vR, uint vA, uint vB);
+
+/** load vector element word: vR = mem_word[vA+vB] */
+extern void
+ppc_lvewx(struct ppc_function *p, uint vR, uint vA, uint vB);
+
+
+
+/**
+ ** vector bitwise operations
+ **/
+
+
+/** vector and */
+extern void
+ppc_vand(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector and complement */
+extern void
+ppc_vandc(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector or */
+extern void
+ppc_vor(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector nor */
+extern void
+ppc_vnor(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** vector xor */
+extern void
+ppc_vxor(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+/** Pseudo-instruction: vector move */
+extern void
+ppc_vmove(struct ppc_function *p, uint vD, uint vA);
+
+/** Set vector register to {0,0,0,0} */
+extern void
+ppc_vzero(struct ppc_function *p, uint vr);
+
+
+
+/**
+ ** Vector shuffle / select / splat / etc
+ **/
+
+/** vector permute */
+extern void
+ppc_vperm(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC);
+
+/** vector select */
+extern void
+ppc_vsel(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC);
+
+/** vector splat byte */
+extern void
+ppc_vspltb(struct ppc_function *p, uint vD, uint vB, uint imm);
+
+/** vector splat half word */
+extern void
+ppc_vsplthw(struct ppc_function *p, uint vD, uint vB, uint imm);
+
+/** vector splat word */
+extern void
+ppc_vspltw(struct ppc_function *p, uint vD, uint vB, uint imm);
+
+/** vector splat signed immediate word */
+extern void
+ppc_vspltisw(struct ppc_function *p, uint vD, int imm);
+
+/** vector shift left word: vD[word] = vA[word] << (vB[word] & 0x1f) */
+extern void
+ppc_vslw(struct ppc_function *p, uint vD, uint vA, uint vB);
+
+
+
+/**
+ ** scalar arithmetic
+ **/
+
+extern void
+ppc_add(struct ppc_function *p, uint rt, uint ra, uint rb);
+
+extern void
+ppc_addi(struct ppc_function *p, uint rt, uint ra, int imm);
+
+extern void
+ppc_addis(struct ppc_function *p, uint rt, uint ra, int imm);
+
+extern void
+ppc_and(struct ppc_function *p, uint rt, uint ra, uint rb);
+
+extern void
+ppc_andi(struct ppc_function *p, uint rt, uint ra, int imm);
+
+extern void
+ppc_or(struct ppc_function *p, uint rt, uint ra, uint rb);
+
+extern void
+ppc_ori(struct ppc_function *p, uint rt, uint ra, int imm);
+
+extern void
+ppc_xor(struct ppc_function *p, uint rt, uint ra, uint rb);
+
+extern void
+ppc_xori(struct ppc_function *p, uint rt, uint ra, int imm);
+
+extern void
+ppc_mr(struct ppc_function *p, uint rt, uint ra);
+
+extern void
+ppc_li(struct ppc_function *p, uint rt, int imm);
+
+extern void
+ppc_lis(struct ppc_function *p, uint rt, int imm);
+
+extern void
+ppc_load_int(struct ppc_function *p, uint rt, int imm);
+
+
+
+/**
+ ** scalar load/store
+ **/
+
+extern void
+ppc_stwu(struct ppc_function *p, uint rs, uint ra, int d);
+
+extern void
+ppc_stw(struct ppc_function *p, uint rs, uint ra, int d);
+
+extern void
+ppc_lwz(struct ppc_function *p, uint rs, uint ra, int d);
+
+
+
+/**
+ ** Float (non-vector) arithmetic
+ **/
+
+extern void
+ppc_fadd(struct ppc_function *p, uint frt, uint fra, uint frb);
+
+extern void
+ppc_fsub(struct ppc_function *p, uint frt, uint fra, uint frb);
+
+extern void
+ppc_fctiwz(struct ppc_function *p, uint rt, uint ra);
+
+extern void
+ppc_stfs(struct ppc_function *p, uint frs, uint ra, int offset);
+
+extern void
+ppc_stfiwx(struct ppc_function *p, uint frs, uint ra, uint rb);
+
+extern void
+ppc_lfs(struct ppc_function *p, uint frt, uint ra, int offset);
+
+
+
+/**
+ ** branch instructions
+ **/
+
+extern void
+ppc_blr(struct ppc_function *p);
+
+void
+ppc_bclr(struct ppc_function *p, uint condOp, uint branchHint, uint condReg);
+
+extern void
+ppc_return(struct ppc_function *p);
+
+
+#endif /* RTASM_PPC_H */
diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
new file mode 100644
index 0000000000..53a0e722cf
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c
@@ -0,0 +1,1067 @@
+/*
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file
+ * Real-time assembly generation interface for Cell B.E. SPEs.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ * \author Brian Paul
+ */
+
+
+#include <stdio.h>
+#include "pipe/p_compiler.h"
+#include "util/u_memory.h"
+#include "rtasm_ppc_spe.h"
+
+
+#ifdef GALLIUM_CELL
+/**
+ * SPE instruction types
+ *
+ * There are 6 primary instruction encodings used on the Cell's SPEs. Each of
+ * the following unions encodes one type.
+ *
+ * \bug
+ * If, at some point, we start generating SPE code from a little-endian host
+ * these unions will not work.
+ */
+/*@{*/
+/**
+ * Encode one output register with two input registers
+ */
+union spe_inst_RR {
+ uint32_t bits;
+ struct {
+ unsigned op:11;
+ unsigned rB:7;
+ unsigned rA:7;
+ unsigned rT:7;
+ } inst;
+};
+
+
+/**
+ * Encode one output register with three input registers
+ */
+union spe_inst_RRR {
+ uint32_t bits;
+ struct {
+ unsigned op:4;
+ unsigned rT:7;
+ unsigned rB:7;
+ unsigned rA:7;
+ unsigned rC:7;
+ } inst;
+};
+
+
+/**
+ * Encode one output register with one input reg. and a 7-bit signed immed
+ */
+union spe_inst_RI7 {
+ uint32_t bits;
+ struct {
+ unsigned op:11;
+ unsigned i7:7;
+ unsigned rA:7;
+ unsigned rT:7;
+ } inst;
+};
+
+
+/**
+ * Encode one output register with one input reg. and an 8-bit signed immed
+ */
+union spe_inst_RI8 {
+ uint32_t bits;
+ struct {
+ unsigned op:10;
+ unsigned i8:8;
+ unsigned rA:7;
+ unsigned rT:7;
+ } inst;
+};
+
+
+/**
+ * Encode one output register with one input reg. and a 10-bit signed immed
+ */
+union spe_inst_RI10 {
+ uint32_t bits;
+ struct {
+ unsigned op:8;
+ unsigned i10:10;
+ unsigned rA:7;
+ unsigned rT:7;
+ } inst;
+};
+
+
+/**
+ * Encode one output register with a 16-bit signed immediate
+ */
+union spe_inst_RI16 {
+ uint32_t bits;
+ struct {
+ unsigned op:9;
+ unsigned i16:16;
+ unsigned rT:7;
+ } inst;
+};
+
+
+/**
+ * Encode one output register with a 18-bit signed immediate
+ */
+union spe_inst_RI18 {
+ uint32_t bits;
+ struct {
+ unsigned op:7;
+ unsigned i18:18;
+ unsigned rT:7;
+ } inst;
+};
+/*@}*/
+
+
+static void
+indent(const struct spe_function *p)
+{
+ int i;
+ for (i = 0; i < p->indent; i++) {
+ putchar(' ');
+ }
+}
+
+
+static const char *
+rem_prefix(const char *longname)
+{
+ return longname + 4;
+}
+
+
+static const char *
+reg_name(int reg)
+{
+ switch (reg) {
+ case SPE_REG_SP:
+ return "$sp";
+ case SPE_REG_RA:
+ return "$lr";
+ default:
+ {
+ /* cycle through four buffers to handle multiple calls per printf */
+ static char buf[4][10];
+ static int b = 0;
+ b = (b + 1) % 4;
+ sprintf(buf[b], "$%d", reg);
+ return buf[b];
+ }
+ }
+}
+
+
+static void
+emit_instruction(struct spe_function *p, uint32_t inst_bits)
+{
+ if (!p->store)
+ return; /* out of memory, drop the instruction */
+
+ if (p->num_inst == p->max_inst) {
+ /* allocate larger buffer */
+ uint32_t *newbuf;
+ p->max_inst *= 2; /* 2x larger */
+ newbuf = align_malloc(p->max_inst * SPE_INST_SIZE, 16);
+ if (newbuf) {
+ memcpy(newbuf, p->store, p->num_inst * SPE_INST_SIZE);
+ }
+ align_free(p->store);
+ p->store = newbuf;
+ if (!p->store) {
+ /* out of memory */
+ p->num_inst = 0;
+ return;
+ }
+ }
+
+ p->store[p->num_inst++] = inst_bits;
+}
+
+
+
+static void emit_RR(struct spe_function *p, unsigned op, int rT,
+ int rA, int rB, const char *name)
+{
+ union spe_inst_RR inst;
+ inst.inst.op = op;
+ inst.inst.rB = rB;
+ inst.inst.rA = rA;
+ inst.inst.rT = rT;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf("%s\t%s, %s, %s\n",
+ rem_prefix(name), reg_name(rT), reg_name(rA), reg_name(rB));
+ }
+}
+
+
+static void emit_RRR(struct spe_function *p, unsigned op, int rT,
+ int rA, int rB, int rC, const char *name)
+{
+ union spe_inst_RRR inst;
+ inst.inst.op = op;
+ inst.inst.rT = rT;
+ inst.inst.rB = rB;
+ inst.inst.rA = rA;
+ inst.inst.rC = rC;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf("%s\t%s, %s, %s, %s\n", rem_prefix(name), reg_name(rT),
+ reg_name(rA), reg_name(rB), reg_name(rC));
+ }
+}
+
+
+static void emit_RI7(struct spe_function *p, unsigned op, int rT,
+ int rA, int imm, const char *name)
+{
+ union spe_inst_RI7 inst;
+ inst.inst.op = op;
+ inst.inst.i7 = imm;
+ inst.inst.rA = rA;
+ inst.inst.rT = rT;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf("%s\t%s, %s, 0x%x\n",
+ rem_prefix(name), reg_name(rT), reg_name(rA), imm);
+ }
+}
+
+
+
+static void emit_RI8(struct spe_function *p, unsigned op, int rT,
+ int rA, int imm, const char *name)
+{
+ union spe_inst_RI8 inst;
+ inst.inst.op = op;
+ inst.inst.i8 = imm;
+ inst.inst.rA = rA;
+ inst.inst.rT = rT;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf("%s\t%s, %s, 0x%x\n",
+ rem_prefix(name), reg_name(rT), reg_name(rA), imm);
+ }
+}
+
+
+
+static void emit_RI10(struct spe_function *p, unsigned op, int rT,
+ int rA, int imm, const char *name)
+{
+ union spe_inst_RI10 inst;
+ inst.inst.op = op;
+ inst.inst.i10 = imm;
+ inst.inst.rA = rA;
+ inst.inst.rT = rT;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf("%s\t%s, %s, 0x%x\n",
+ rem_prefix(name), reg_name(rT), reg_name(rA), imm);
+ }
+}
+
+
+/** As above, but do range checking on signed immediate value */
+static void emit_RI10s(struct spe_function *p, unsigned op, int rT,
+ int rA, int imm, const char *name)
+{
+ assert(imm <= 511);
+ assert(imm >= -512);
+ emit_RI10(p, op, rT, rA, imm, name);
+}
+
+
+static void emit_RI16(struct spe_function *p, unsigned op, int rT,
+ int imm, const char *name)
+{
+ union spe_inst_RI16 inst;
+ inst.inst.op = op;
+ inst.inst.i16 = imm;
+ inst.inst.rT = rT;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf("%s\t%s, 0x%x\n", rem_prefix(name), reg_name(rT), imm);
+ }
+}
+
+
+static void emit_RI18(struct spe_function *p, unsigned op, int rT,
+ int imm, const char *name)
+{
+ union spe_inst_RI18 inst;
+ inst.inst.op = op;
+ inst.inst.i18 = imm;
+ inst.inst.rT = rT;
+ emit_instruction(p, inst.bits);
+ if (p->print) {
+ indent(p);
+ printf("%s\t%s, 0x%x\n", rem_prefix(name), reg_name(rT), imm);
+ }
+}
+
+
+#define EMIT(_name, _op) \
+void _name (struct spe_function *p) \
+{ \
+ emit_RR(p, _op, 0, 0, 0, __FUNCTION__); \
+}
+
+#define EMIT_(_name, _op) \
+void _name (struct spe_function *p, int rT) \
+{ \
+ emit_RR(p, _op, rT, 0, 0, __FUNCTION__); \
+}
+
+#define EMIT_R(_name, _op) \
+void _name (struct spe_function *p, int rT, int rA) \
+{ \
+ emit_RR(p, _op, rT, rA, 0, __FUNCTION__); \
+}
+
+#define EMIT_RR(_name, _op) \
+void _name (struct spe_function *p, int rT, int rA, int rB) \
+{ \
+ emit_RR(p, _op, rT, rA, rB, __FUNCTION__); \
+}
+
+#define EMIT_RRR(_name, _op) \
+void _name (struct spe_function *p, int rT, int rA, int rB, int rC) \
+{ \
+ emit_RRR(p, _op, rT, rA, rB, rC, __FUNCTION__); \
+}
+
+#define EMIT_RI7(_name, _op) \
+void _name (struct spe_function *p, int rT, int rA, int imm) \
+{ \
+ emit_RI7(p, _op, rT, rA, imm, __FUNCTION__); \
+}
+
+#define EMIT_RI8(_name, _op, bias) \
+void _name (struct spe_function *p, int rT, int rA, int imm) \
+{ \
+ emit_RI8(p, _op, rT, rA, bias - imm, __FUNCTION__); \
+}
+
+#define EMIT_RI10(_name, _op) \
+void _name (struct spe_function *p, int rT, int rA, int imm) \
+{ \
+ emit_RI10(p, _op, rT, rA, imm, __FUNCTION__); \
+}
+
+#define EMIT_RI10s(_name, _op) \
+void _name (struct spe_function *p, int rT, int rA, int imm) \
+{ \
+ emit_RI10s(p, _op, rT, rA, imm, __FUNCTION__); \
+}
+
+#define EMIT_RI16(_name, _op) \
+void _name (struct spe_function *p, int rT, int imm) \
+{ \
+ emit_RI16(p, _op, rT, imm, __FUNCTION__); \
+}
+
+#define EMIT_RI18(_name, _op) \
+void _name (struct spe_function *p, int rT, int imm) \
+{ \
+ emit_RI18(p, _op, rT, imm, __FUNCTION__); \
+}
+
+#define EMIT_I16(_name, _op) \
+void _name (struct spe_function *p, int imm) \
+{ \
+ emit_RI16(p, _op, 0, imm, __FUNCTION__); \
+}
+
+#include "rtasm_ppc_spe.h"
+
+
+
+/**
+ * Initialize an spe_function.
+ * \param code_size initial size of instruction buffer to allocate, in bytes.
+ * If zero, use a default.
+ */
+void spe_init_func(struct spe_function *p, unsigned code_size)
+{
+ uint i;
+
+ if (!code_size)
+ code_size = 64;
+
+ p->num_inst = 0;
+ p->max_inst = code_size / SPE_INST_SIZE;
+ p->store = align_malloc(code_size, 16);
+
+ p->set_count = 0;
+ memset(p->regs, 0, SPE_NUM_REGS * sizeof(p->regs[0]));
+
+ /* Conservatively treat R0 - R2 and R80 - R127 as non-volatile.
+ */
+ p->regs[0] = p->regs[1] = p->regs[2] = 1;
+ for (i = 80; i <= 127; i++) {
+ p->regs[i] = 1;
+ }
+
+ p->print = FALSE;
+ p->indent = 0;
+}
+
+
+void spe_release_func(struct spe_function *p)
+{
+ assert(p->num_inst <= p->max_inst);
+ if (p->store != NULL) {
+ align_free(p->store);
+ }
+ p->store = NULL;
+}
+
+
+/** Return current code size in bytes. */
+unsigned spe_code_size(const struct spe_function *p)
+{
+ return p->num_inst * SPE_INST_SIZE;
+}
+
+
+/**
+ * Allocate a SPE register.
+ * \return register index or -1 if none left.
+ */
+int spe_allocate_available_register(struct spe_function *p)
+{
+ unsigned i;
+ for (i = 0; i < SPE_NUM_REGS; i++) {
+ if (p->regs[i] == 0) {
+ p->regs[i] = 1;
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/**
+ * Mark the given SPE register as "allocated".
+ */
+int spe_allocate_register(struct spe_function *p, int reg)
+{
+ assert(reg < SPE_NUM_REGS);
+ assert(p->regs[reg] == 0);
+ p->regs[reg] = 1;
+ return reg;
+}
+
+
+/**
+ * Mark the given SPE register as "unallocated". Note that this should
+ * only be used on registers allocated in the current register set; an
+ * assertion will fail if an attempt is made to deallocate a register
+ * allocated in an earlier register set.
+ */
+void spe_release_register(struct spe_function *p, int reg)
+{
+ assert(reg >= 0);
+ assert(reg < SPE_NUM_REGS);
+ assert(p->regs[reg] == 1);
+
+ p->regs[reg] = 0;
+}
+
+/**
+ * Start a new set of registers. This can be called if
+ * it will be difficult later to determine exactly what
+ * registers were actually allocated during a code generation
+ * sequence, and you really just want to deallocate all of them.
+ */
+void spe_allocate_register_set(struct spe_function *p)
+{
+ uint i;
+
+ /* Keep track of the set count. If it ever wraps around to 0,
+ * we're in trouble.
+ */
+ p->set_count++;
+ assert(p->set_count > 0);
+
+ /* Increment the allocation count of all registers currently
+ * allocated. Then any registers that are allocated in this set
+ * will be the only ones with a count of 1; they'll all be released
+ * when the register set is released.
+ */
+ for (i = 0; i < SPE_NUM_REGS; i++) {
+ if (p->regs[i] > 0)
+ p->regs[i]++;
+ }
+}
+
+void spe_release_register_set(struct spe_function *p)
+{
+ uint i;
+
+ /* If the set count drops below zero, we're in trouble. */
+ assert(p->set_count > 0);
+ p->set_count--;
+
+ /* Drop the allocation level of all registers. Any allocated
+ * during this register set will drop to 0 and then become
+ * available.
+ */
+ for (i = 0; i < SPE_NUM_REGS; i++) {
+ if (p->regs[i] > 0)
+ p->regs[i]--;
+ }
+}
+
+
+unsigned
+spe_get_registers_used(const struct spe_function *p, ubyte used[])
+{
+ unsigned i, num = 0;
+ /* only count registers in the range available to callers */
+ for (i = 2; i < 80; i++) {
+ if (p->regs[i]) {
+ used[num++] = i;
+ }
+ }
+ return num;
+}
+
+
+void
+spe_print_code(struct spe_function *p, boolean enable)
+{
+ p->print = enable;
+}
+
+
+void
+spe_indent(struct spe_function *p, int spaces)
+{
+ p->indent += spaces;
+}
+
+
+void
+spe_comment(struct spe_function *p, int rel_indent, const char *s)
+{
+ if (p->print) {
+ p->indent += rel_indent;
+ indent(p);
+ p->indent -= rel_indent;
+ printf("# %s\n", s);
+ }
+}
+
+
+/**
+ * Load quad word.
+ * NOTE: offset is in bytes and the least significant 4 bits must be zero!
+ */
+void spe_lqd(struct spe_function *p, int rT, int rA, int offset)
+{
+ const boolean pSave = p->print;
+
+ /* offset must be a multiple of 16 */
+ assert(offset % 16 == 0);
+ /* offset must fit in 10-bit signed int field, after shifting */
+ assert((offset >> 4) <= 511);
+ assert((offset >> 4) >= -512);
+
+ p->print = FALSE;
+ emit_RI10(p, 0x034, rT, rA, offset >> 4, "spe_lqd");
+ p->print = pSave;
+
+ if (p->print) {
+ indent(p);
+ printf("lqd\t%s, %d(%s)\n", reg_name(rT), offset, reg_name(rA));
+ }
+}
+
+
+/**
+ * Store quad word.
+ * NOTE: offset is in bytes and the least significant 4 bits must be zero!
+ */
+void spe_stqd(struct spe_function *p, int rT, int rA, int offset)
+{
+ const boolean pSave = p->print;
+
+ /* offset must be a multiple of 16 */
+ assert(offset % 16 == 0);
+ /* offset must fit in 10-bit signed int field, after shifting */
+ assert((offset >> 4) <= 511);
+ assert((offset >> 4) >= -512);
+
+ p->print = FALSE;
+ emit_RI10(p, 0x024, rT, rA, offset >> 4, "spe_stqd");
+ p->print = pSave;
+
+ if (p->print) {
+ indent(p);
+ printf("stqd\t%s, %d(%s)\n", reg_name(rT), offset, reg_name(rA));
+ }
+}
+
+
+/**
+ * For branch instructions:
+ * \param d if 1, disable interupts if branch is taken
+ * \param e if 1, enable interupts if branch is taken
+ * If d and e are both zero, don't change interupt status (right?)
+ */
+
+/** Branch Indirect to address in rA */
+void spe_bi(struct spe_function *p, int rA, int d, int e)
+{
+ emit_RI7(p, 0x1a8, 0, rA, (d << 5) | (e << 4), __FUNCTION__);
+}
+
+/** Interupt Return */
+void spe_iret(struct spe_function *p, int rA, int d, int e)
+{
+ emit_RI7(p, 0x1aa, 0, rA, (d << 5) | (e << 4), __FUNCTION__);
+}
+
+/** Branch indirect and set link on external data */
+void spe_bisled(struct spe_function *p, int rT, int rA, int d,
+ int e)
+{
+ emit_RI7(p, 0x1ab, rT, rA, (d << 5) | (e << 4), __FUNCTION__);
+}
+
+/** Branch indirect and set link. Save PC in rT, jump to rA. */
+void spe_bisl(struct spe_function *p, int rT, int rA, int d,
+ int e)
+{
+ emit_RI7(p, 0x1a9, rT, rA, (d << 5) | (e << 4), __FUNCTION__);
+}
+
+/** Branch indirect if zero word. If rT.word[0]==0, jump to rA. */
+void spe_biz(struct spe_function *p, int rT, int rA, int d, int e)
+{
+ emit_RI7(p, 0x128, rT, rA, (d << 5) | (e << 4), __FUNCTION__);
+}
+
+/** Branch indirect if non-zero word. If rT.word[0]!=0, jump to rA. */
+void spe_binz(struct spe_function *p, int rT, int rA, int d, int e)
+{
+ emit_RI7(p, 0x129, rT, rA, (d << 5) | (e << 4), __FUNCTION__);
+}
+
+/** Branch indirect if zero halfword. If rT.halfword[1]==0, jump to rA. */
+void spe_bihz(struct spe_function *p, int rT, int rA, int d, int e)
+{
+ emit_RI7(p, 0x12a, rT, rA, (d << 5) | (e << 4), __FUNCTION__);
+}
+
+/** Branch indirect if non-zero halfword. If rT.halfword[1]!=0, jump to rA. */
+void spe_bihnz(struct spe_function *p, int rT, int rA, int d, int e)
+{
+ emit_RI7(p, 0x12b, rT, rA, (d << 5) | (e << 4), __FUNCTION__);
+}
+
+
+/* Hint-for-branch instructions
+ */
+#if 0
+hbr;
+hbra;
+hbrr;
+#endif
+
+
+/* Control instructions
+ */
+#if 0
+stop;
+EMIT_RR (spe_stopd, 0x140);
+EMIT_ (spe_nop, 0x201);
+sync;
+EMIT_ (spe_dsync, 0x003);
+EMIT_R (spe_mfspr, 0x00c);
+EMIT_R (spe_mtspr, 0x10c);
+#endif
+
+
+/**
+ ** Helper / "macro" instructions.
+ ** Use somewhat verbose names as a reminder that these aren't native
+ ** SPE instructions.
+ **/
+
+
+void
+spe_load_float(struct spe_function *p, int rT, float x)
+{
+ if (x == 0.0f) {
+ spe_il(p, rT, 0x0);
+ }
+ else if (x == 0.5f) {
+ spe_ilhu(p, rT, 0x3f00);
+ }
+ else if (x == 1.0f) {
+ spe_ilhu(p, rT, 0x3f80);
+ }
+ else if (x == -1.0f) {
+ spe_ilhu(p, rT, 0xbf80);
+ }
+ else {
+ union {
+ float f;
+ unsigned u;
+ } bits;
+ bits.f = x;
+ spe_ilhu(p, rT, bits.u >> 16);
+ spe_iohl(p, rT, bits.u & 0xffff);
+ }
+}
+
+
+void
+spe_load_int(struct spe_function *p, int rT, int i)
+{
+ if (-32768 <= i && i <= 32767) {
+ spe_il(p, rT, i);
+ }
+ else {
+ spe_ilhu(p, rT, i >> 16);
+ if (i & 0xffff)
+ spe_iohl(p, rT, i & 0xffff);
+ }
+}
+
+void spe_load_uint(struct spe_function *p, int rT, uint ui)
+{
+ /* If the whole value is in the lower 18 bits, use ila, which
+ * doesn't sign-extend. Otherwise, if the two halfwords of
+ * the constant are identical, use ilh. Otherwise, if every byte of
+ * the desired value is 0x00 or 0xff, we can use Form Select Mask for
+ * Bytes Immediate (fsmbi) to load the value in a single instruction.
+ * Otherwise, in the general case, we have to use ilhu followed by iohl.
+ */
+ if ((ui & 0x0003ffff) == ui) {
+ spe_ila(p, rT, ui);
+ }
+ else if ((ui >> 16) == (ui & 0xffff)) {
+ spe_ilh(p, rT, ui & 0xffff);
+ }
+ else if (
+ ((ui & 0x000000ff) == 0 || (ui & 0x000000ff) == 0x000000ff) &&
+ ((ui & 0x0000ff00) == 0 || (ui & 0x0000ff00) == 0x0000ff00) &&
+ ((ui & 0x00ff0000) == 0 || (ui & 0x00ff0000) == 0x00ff0000) &&
+ ((ui & 0xff000000) == 0 || (ui & 0xff000000) == 0xff000000)
+ ) {
+ uint mask = 0;
+ /* fsmbi duplicates each bit in the given mask eight times,
+ * using a 16-bit value to initialize a 16-byte quadword.
+ * Each 4-bit nybble of the mask corresponds to a full word
+ * of the result; look at the value and figure out the mask
+ * (replicated for each word in the quadword), and then
+ * form the "select mask" to get the value.
+ */
+ if ((ui & 0x000000ff) == 0x000000ff) mask |= 0x1111;
+ if ((ui & 0x0000ff00) == 0x0000ff00) mask |= 0x2222;
+ if ((ui & 0x00ff0000) == 0x00ff0000) mask |= 0x4444;
+ if ((ui & 0xff000000) == 0xff000000) mask |= 0x8888;
+ spe_fsmbi(p, rT, mask);
+ }
+ else {
+ /* The general case: this usually uses two instructions, but
+ * may use only one if the low-order 16 bits of each word are 0.
+ */
+ spe_ilhu(p, rT, ui >> 16);
+ if (ui & 0xffff)
+ spe_iohl(p, rT, ui & 0xffff);
+ }
+}
+
+/**
+ * This function is constructed identically to spe_xor_uint() below.
+ * Changes to one should be made in the other.
+ */
+void
+spe_and_uint(struct spe_function *p, int rT, int rA, uint ui)
+{
+ /* If we can, emit a single instruction, either And Byte Immediate
+ * (which uses the same constant across each byte), And Halfword Immediate
+ * (which sign-extends a 10-bit immediate to 16 bits and uses that
+ * across each halfword), or And Word Immediate (which sign-extends
+ * a 10-bit immediate to 32 bits).
+ *
+ * Otherwise, we'll need to use a temporary register.
+ */
+ uint tmp;
+
+ /* If the upper 23 bits are all 0s or all 1s, sign extension
+ * will work and we can use And Word Immediate
+ */
+ tmp = ui & 0xfffffe00;
+ if (tmp == 0xfffffe00 || tmp == 0) {
+ spe_andi(p, rT, rA, ui & 0x000003ff);
+ return;
+ }
+
+ /* If the ui field is symmetric along halfword boundaries and
+ * the upper 7 bits of each halfword are all 0s or 1s, we
+ * can use And Halfword Immediate
+ */
+ tmp = ui & 0xfe00fe00;
+ if ((tmp == 0xfe00fe00 || tmp == 0) && ((ui >> 16) == (ui & 0x0000ffff))) {
+ spe_andhi(p, rT, rA, ui & 0x000003ff);
+ return;
+ }
+
+ /* If the ui field is symmetric in each byte, then we can use
+ * the And Byte Immediate instruction.
+ */
+ tmp = ui & 0x000000ff;
+ if ((ui >> 24) == tmp && ((ui >> 16) & 0xff) == tmp && ((ui >> 8) & 0xff) == tmp) {
+ spe_andbi(p, rT, rA, tmp);
+ return;
+ }
+
+ /* Otherwise, we'll have to use a temporary register. */
+ int tmp_reg = spe_allocate_available_register(p);
+ spe_load_uint(p, tmp_reg, ui);
+ spe_and(p, rT, rA, tmp_reg);
+ spe_release_register(p, tmp_reg);
+}
+
+
+/**
+ * This function is constructed identically to spe_and_uint() above.
+ * Changes to one should be made in the other.
+ */
+void
+spe_xor_uint(struct spe_function *p, int rT, int rA, uint ui)
+{
+ /* If we can, emit a single instruction, either Exclusive Or Byte
+ * Immediate (which uses the same constant across each byte), Exclusive
+ * Or Halfword Immediate (which sign-extends a 10-bit immediate to
+ * 16 bits and uses that across each halfword), or Exclusive Or Word
+ * Immediate (which sign-extends a 10-bit immediate to 32 bits).
+ *
+ * Otherwise, we'll need to use a temporary register.
+ */
+ uint tmp;
+
+ /* If the upper 23 bits are all 0s or all 1s, sign extension
+ * will work and we can use Exclusive Or Word Immediate
+ */
+ tmp = ui & 0xfffffe00;
+ if (tmp == 0xfffffe00 || tmp == 0) {
+ spe_xori(p, rT, rA, ui & 0x000003ff);
+ return;
+ }
+
+ /* If the ui field is symmetric along halfword boundaries and
+ * the upper 7 bits of each halfword are all 0s or 1s, we
+ * can use Exclusive Or Halfword Immediate
+ */
+ tmp = ui & 0xfe00fe00;
+ if ((tmp == 0xfe00fe00 || tmp == 0) && ((ui >> 16) == (ui & 0x0000ffff))) {
+ spe_xorhi(p, rT, rA, ui & 0x000003ff);
+ return;
+ }
+
+ /* If the ui field is symmetric in each byte, then we can use
+ * the Exclusive Or Byte Immediate instruction.
+ */
+ tmp = ui & 0x000000ff;
+ if ((ui >> 24) == tmp && ((ui >> 16) & 0xff) == tmp && ((ui >> 8) & 0xff) == tmp) {
+ spe_xorbi(p, rT, rA, tmp);
+ return;
+ }
+
+ /* Otherwise, we'll have to use a temporary register. */
+ int tmp_reg = spe_allocate_available_register(p);
+ spe_load_uint(p, tmp_reg, ui);
+ spe_xor(p, rT, rA, tmp_reg);
+ spe_release_register(p, tmp_reg);
+}
+
+void
+spe_compare_equal_uint(struct spe_function *p, int rT, int rA, uint ui)
+{
+ /* If the comparison value is 9 bits or less, it fits inside a
+ * Compare Equal Word Immediate instruction.
+ */
+ if ((ui & 0x000001ff) == ui) {
+ spe_ceqi(p, rT, rA, ui);
+ }
+ /* Otherwise, we're going to have to load a word first. */
+ else {
+ int tmp_reg = spe_allocate_available_register(p);
+ spe_load_uint(p, tmp_reg, ui);
+ spe_ceq(p, rT, rA, tmp_reg);
+ spe_release_register(p, tmp_reg);
+ }
+}
+
+void
+spe_compare_greater_uint(struct spe_function *p, int rT, int rA, uint ui)
+{
+ /* If the comparison value is 10 bits or less, it fits inside a
+ * Compare Logical Greater Than Word Immediate instruction.
+ */
+ if ((ui & 0x000003ff) == ui) {
+ spe_clgti(p, rT, rA, ui);
+ }
+ /* Otherwise, we're going to have to load a word first. */
+ else {
+ int tmp_reg = spe_allocate_available_register(p);
+ spe_load_uint(p, tmp_reg, ui);
+ spe_clgt(p, rT, rA, tmp_reg);
+ spe_release_register(p, tmp_reg);
+ }
+}
+
+void
+spe_splat(struct spe_function *p, int rT, int rA)
+{
+ /* Use a temporary, just in case rT == rA */
+ int tmp_reg = spe_allocate_available_register(p);
+ /* Duplicate bytes 0, 1, 2, and 3 across the whole register */
+ spe_ila(p, tmp_reg, 0x00010203);
+ spe_shufb(p, rT, rA, rA, tmp_reg);
+ spe_release_register(p, tmp_reg);
+}
+
+
+void
+spe_complement(struct spe_function *p, int rT, int rA)
+{
+ spe_nor(p, rT, rA, rA);
+}
+
+
+void
+spe_move(struct spe_function *p, int rT, int rA)
+{
+ /* Use different instructions depending on the instruction address
+ * to take advantage of the dual pipelines.
+ */
+ if (p->num_inst & 1)
+ spe_shlqbyi(p, rT, rA, 0); /* odd pipe */
+ else
+ spe_ori(p, rT, rA, 0); /* even pipe */
+}
+
+
+void
+spe_zero(struct spe_function *p, int rT)
+{
+ spe_xor(p, rT, rT, rT);
+}
+
+
+void
+spe_splat_word(struct spe_function *p, int rT, int rA, int word)
+{
+ assert(word >= 0);
+ assert(word <= 3);
+
+ if (word == 0) {
+ int tmp1 = rT;
+ spe_ila(p, tmp1, 66051);
+ spe_shufb(p, rT, rA, rA, tmp1);
+ }
+ else {
+ /* XXX review this, we may not need the rotqbyi instruction */
+ int tmp1 = rT;
+ int tmp2 = spe_allocate_available_register(p);
+
+ spe_ila(p, tmp1, 66051);
+ spe_rotqbyi(p, tmp2, rA, 4 * word);
+ spe_shufb(p, rT, tmp2, tmp2, tmp1);
+
+ spe_release_register(p, tmp2);
+ }
+}
+
+/**
+ * For each 32-bit float element of rA and rB, choose the smaller of the
+ * two, compositing them into the rT register.
+ *
+ * The Float Compare Greater Than (fcgt) instruction will put 1s into
+ * compare_reg where rA > rB, and 0s where rA <= rB.
+ *
+ * Then the Select Bits (selb) instruction will take bits from rA where
+ * compare_reg is 0, and from rB where compare_reg is 1; i.e., from rA
+ * where rA <= rB and from rB where rB > rA, which is exactly the
+ * "min" operation.
+ *
+ * The compare_reg could in many cases be the same as rT, unless
+ * rT == rA || rt == rB. But since this is common in constructions
+ * like "x = min(x, a)", we always allocate a new register to be safe.
+ */
+void
+spe_float_min(struct spe_function *p, int rT, int rA, int rB)
+{
+ int compare_reg = spe_allocate_available_register(p);
+ spe_fcgt(p, compare_reg, rA, rB);
+ spe_selb(p, rT, rA, rB, compare_reg);
+ spe_release_register(p, compare_reg);
+}
+
+/**
+ * For each 32-bit float element of rA and rB, choose the greater of the
+ * two, compositing them into the rT register.
+ *
+ * The logic is similar to that of spe_float_min() above; the only
+ * difference is that the registers on spe_selb() have been reversed,
+ * so that the larger of the two is selected instead of the smaller.
+ */
+void
+spe_float_max(struct spe_function *p, int rT, int rA, int rB)
+{
+ int compare_reg = spe_allocate_available_register(p);
+ spe_fcgt(p, compare_reg, rA, rB);
+ spe_selb(p, rT, rB, rA, compare_reg);
+ spe_release_register(p, compare_reg);
+}
+
+#endif /* GALLIUM_CELL */
diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h
new file mode 100644
index 0000000000..65d9c77415
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h
@@ -0,0 +1,433 @@
+/*
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file
+ * Real-time assembly generation interface for Cell B.E. SPEs.
+ * For details, see /opt/cell/sdk/docs/arch/SPU_ISA_v1.2_27Jan2007_pub.pdf
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ * \author Brian Paul
+ */
+
+#ifndef RTASM_PPC_SPE_H
+#define RTASM_PPC_SPE_H
+
+/** 4 bytes per instruction */
+#define SPE_INST_SIZE 4
+
+/** number of general-purpose SIMD registers */
+#define SPE_NUM_REGS 128
+
+/** Return Address register (aka $lr / Link Register) */
+#define SPE_REG_RA 0
+
+/** Stack Pointer register (aka $sp) */
+#define SPE_REG_SP 1
+
+
+struct spe_function
+{
+ uint32_t *store; /**< instruction buffer */
+ uint num_inst;
+ uint max_inst;
+
+ /**
+ * The "set count" reflects the number of nested register sets
+ * are allowed. In the unlikely case that we exceed the set count,
+ * register allocation will start to be confused, which is critical
+ * enough that we check for it.
+ */
+ unsigned char set_count;
+
+ /**
+ * Flags for used and unused registers. Each byte corresponds to a
+ * register; a 0 in that byte means that the register is available.
+ * A value of 1 means that the register was allocated in the current
+ * register set. Any other value N means that the register was allocated
+ * N register sets ago.
+ *
+ * \sa
+ * spe_allocate_register, spe_allocate_available_register,
+ * spe_allocate_register_set, spe_release_register_set, spe_release_register,
+ */
+ unsigned char regs[SPE_NUM_REGS];
+
+ boolean print; /**< print/dump instructions as they're emitted? */
+ int indent; /**< number of spaces to indent */
+};
+
+
+extern void spe_init_func(struct spe_function *p, uint code_size);
+extern void spe_release_func(struct spe_function *p);
+extern uint spe_code_size(const struct spe_function *p);
+
+extern int spe_allocate_available_register(struct spe_function *p);
+extern int spe_allocate_register(struct spe_function *p, int reg);
+extern void spe_release_register(struct spe_function *p, int reg);
+extern void spe_allocate_register_set(struct spe_function *p);
+extern void spe_release_register_set(struct spe_function *p);
+
+extern uint spe_get_registers_used(const struct spe_function *p, ubyte used[]);
+
+extern void spe_print_code(struct spe_function *p, boolean enable);
+extern void spe_indent(struct spe_function *p, int spaces);
+extern void spe_comment(struct spe_function *p, int rel_indent, const char *s);
+
+
+#endif /* RTASM_PPC_SPE_H */
+
+#ifndef EMIT
+#define EMIT(_name, _op) \
+ extern void _name (struct spe_function *p);
+#define EMIT_(_name, _op) \
+ extern void _name (struct spe_function *p, int rT);
+#define EMIT_R(_name, _op) \
+ extern void _name (struct spe_function *p, int rT, int rA);
+#define EMIT_RR(_name, _op) \
+ extern void _name (struct spe_function *p, int rT, int rA, int rB);
+#define EMIT_RRR(_name, _op) \
+ extern void _name (struct spe_function *p, int rT, int rA, int rB, int rC);
+#define EMIT_RI7(_name, _op) \
+ extern void _name (struct spe_function *p, int rT, int rA, int imm);
+#define EMIT_RI8(_name, _op, bias) \
+ extern void _name (struct spe_function *p, int rT, int rA, int imm);
+#define EMIT_RI10(_name, _op) \
+ extern void _name (struct spe_function *p, int rT, int rA, int imm);
+#define EMIT_RI10s(_name, _op) \
+ extern void _name (struct spe_function *p, int rT, int rA, int imm);
+#define EMIT_RI16(_name, _op) \
+ extern void _name (struct spe_function *p, int rT, int imm);
+#define EMIT_RI18(_name, _op) \
+ extern void _name (struct spe_function *p, int rT, int imm);
+#define EMIT_I16(_name, _op) \
+ extern void _name (struct spe_function *p, int imm);
+#define UNDEF_EMIT_MACROS
+#endif /* EMIT */
+
+
+/* Memory load / store instructions
+ */
+EMIT_RR (spe_lqx, 0x1c4)
+EMIT_RI16(spe_lqa, 0x061)
+EMIT_RI16(spe_lqr, 0x067)
+EMIT_RR (spe_stqx, 0x144)
+EMIT_RI16(spe_stqa, 0x041)
+EMIT_RI16(spe_stqr, 0x047)
+EMIT_RI7 (spe_cbd, 0x1f4)
+EMIT_RR (spe_cbx, 0x1d4)
+EMIT_RI7 (spe_chd, 0x1f5)
+EMIT_RI7 (spe_chx, 0x1d5)
+EMIT_RI7 (spe_cwd, 0x1f6)
+EMIT_RI7 (spe_cwx, 0x1d6)
+EMIT_RI7 (spe_cdd, 0x1f7)
+EMIT_RI7 (spe_cdx, 0x1d7)
+
+
+/* Constant formation instructions
+ */
+EMIT_RI16(spe_ilh, 0x083)
+EMIT_RI16(spe_ilhu, 0x082)
+EMIT_RI16(spe_il, 0x081)
+EMIT_RI18(spe_ila, 0x021)
+EMIT_RI16(spe_iohl, 0x0c1)
+EMIT_RI16(spe_fsmbi, 0x065)
+
+
+
+/* Integer and logical instructions
+ */
+EMIT_RR (spe_ah, 0x0c8)
+EMIT_RI10(spe_ahi, 0x01d)
+EMIT_RR (spe_a, 0x0c0)
+EMIT_RI10s(spe_ai, 0x01c)
+EMIT_RR (spe_sfh, 0x048)
+EMIT_RI10(spe_sfhi, 0x00d)
+EMIT_RR (spe_sf, 0x040)
+EMIT_RI10(spe_sfi, 0x00c)
+EMIT_RR (spe_addx, 0x340)
+EMIT_RR (spe_cg, 0x0c2)
+EMIT_RR (spe_cgx, 0x342)
+EMIT_RR (spe_sfx, 0x341)
+EMIT_RR (spe_bg, 0x042)
+EMIT_RR (spe_bgx, 0x343)
+EMIT_RR (spe_mpy, 0x3c4)
+EMIT_RR (spe_mpyu, 0x3cc)
+EMIT_RI10(spe_mpyi, 0x074)
+EMIT_RI10(spe_mpyui, 0x075)
+EMIT_RRR (spe_mpya, 0x00c)
+EMIT_RR (spe_mpyh, 0x3c5)
+EMIT_RR (spe_mpys, 0x3c7)
+EMIT_RR (spe_mpyhh, 0x3c6)
+EMIT_RR (spe_mpyhha, 0x346)
+EMIT_RR (spe_mpyhhu, 0x3ce)
+EMIT_RR (spe_mpyhhau, 0x34e)
+EMIT_R (spe_clz, 0x2a5)
+EMIT_R (spe_cntb, 0x2b4)
+EMIT_R (spe_fsmb, 0x1b6)
+EMIT_R (spe_fsmh, 0x1b5)
+EMIT_R (spe_fsm, 0x1b4)
+EMIT_R (spe_gbb, 0x1b2)
+EMIT_R (spe_gbh, 0x1b1)
+EMIT_R (spe_gb, 0x1b0)
+EMIT_RR (spe_avgb, 0x0d3)
+EMIT_RR (spe_absdb, 0x053)
+EMIT_RR (spe_sumb, 0x253)
+EMIT_R (spe_xsbh, 0x2b6)
+EMIT_R (spe_xshw, 0x2ae)
+EMIT_R (spe_xswd, 0x2a6)
+EMIT_RR (spe_and, 0x0c1)
+EMIT_RR (spe_andc, 0x2c1)
+EMIT_RI10s(spe_andbi, 0x016)
+EMIT_RI10s(spe_andhi, 0x015)
+EMIT_RI10s(spe_andi, 0x014)
+EMIT_RR (spe_or, 0x041)
+EMIT_RR (spe_orc, 0x2c9)
+EMIT_RI10s(spe_orbi, 0x006)
+EMIT_RI10s(spe_orhi, 0x005)
+EMIT_RI10s(spe_ori, 0x004)
+EMIT_R (spe_orx, 0x1f0)
+EMIT_RR (spe_xor, 0x241)
+EMIT_RI10s(spe_xorbi, 0x046)
+EMIT_RI10s(spe_xorhi, 0x045)
+EMIT_RI10s(spe_xori, 0x044)
+EMIT_RR (spe_nand, 0x0c9)
+EMIT_RR (spe_nor, 0x049)
+EMIT_RR (spe_eqv, 0x249)
+EMIT_RRR (spe_selb, 0x008)
+EMIT_RRR (spe_shufb, 0x00b)
+
+
+/* Shift and rotate instructions
+ */
+EMIT_RR (spe_shlh, 0x05f)
+EMIT_RI7 (spe_shlhi, 0x07f)
+EMIT_RR (spe_shl, 0x05b)
+EMIT_RI7 (spe_shli, 0x07b)
+EMIT_RR (spe_shlqbi, 0x1db)
+EMIT_RI7 (spe_shlqbii, 0x1fb)
+EMIT_RR (spe_shlqby, 0x1df)
+EMIT_RI7 (spe_shlqbyi, 0x1ff)
+EMIT_RR (spe_shlqbybi, 0x1cf)
+EMIT_RR (spe_roth, 0x05c)
+EMIT_RI7 (spe_rothi, 0x07c)
+EMIT_RR (spe_rot, 0x058)
+EMIT_RI7 (spe_roti, 0x078)
+EMIT_RR (spe_rotqby, 0x1dc)
+EMIT_RI7 (spe_rotqbyi, 0x1fc)
+EMIT_RR (spe_rotqbybi, 0x1cc)
+EMIT_RR (spe_rotqbi, 0x1d8)
+EMIT_RI7 (spe_rotqbii, 0x1f8)
+EMIT_RR (spe_rothm, 0x05d)
+EMIT_RI7 (spe_rothmi, 0x07d)
+EMIT_RR (spe_rotm, 0x059)
+EMIT_RI7 (spe_rotmi, 0x079)
+EMIT_RR (spe_rotqmby, 0x1dd)
+EMIT_RI7 (spe_rotqmbyi, 0x1fd)
+EMIT_RR (spe_rotqmbybi, 0x1cd)
+EMIT_RR (spe_rotqmbi, 0x1c9)
+EMIT_RI7 (spe_rotqmbii, 0x1f9)
+EMIT_RR (spe_rotmah, 0x05e)
+EMIT_RI7 (spe_rotmahi, 0x07e)
+EMIT_RR (spe_rotma, 0x05a)
+EMIT_RI7 (spe_rotmai, 0x07a)
+
+
+/* Compare, branch, and halt instructions
+ */
+EMIT_RR (spe_heq, 0x3d8)
+EMIT_RI10(spe_heqi, 0x07f)
+EMIT_RR (spe_hgt, 0x258)
+EMIT_RI10(spe_hgti, 0x04f)
+EMIT_RR (spe_hlgt, 0x2d8)
+EMIT_RI10(spe_hlgti, 0x05f)
+EMIT_RR (spe_ceqb, 0x3d0)
+EMIT_RI10(spe_ceqbi, 0x07e)
+EMIT_RR (spe_ceqh, 0x3c8)
+EMIT_RI10(spe_ceqhi, 0x07d)
+EMIT_RR (spe_ceq, 0x3c0)
+EMIT_RI10(spe_ceqi, 0x07c)
+EMIT_RR (spe_cgtb, 0x250)
+EMIT_RI10(spe_cgtbi, 0x04e)
+EMIT_RR (spe_cgth, 0x248)
+EMIT_RI10(spe_cgthi, 0x04d)
+EMIT_RR (spe_cgt, 0x240)
+EMIT_RI10(spe_cgti, 0x04c)
+EMIT_RR (spe_clgtb, 0x2d0)
+EMIT_RI10(spe_clgtbi, 0x05e)
+EMIT_RR (spe_clgth, 0x2c8)
+EMIT_RI10(spe_clgthi, 0x05d)
+EMIT_RR (spe_clgt, 0x2c0)
+EMIT_RI10(spe_clgti, 0x05c)
+EMIT_I16 (spe_br, 0x064)
+EMIT_I16 (spe_bra, 0x060)
+EMIT_RI16(spe_brsl, 0x066)
+EMIT_RI16(spe_brasl, 0x062)
+EMIT_RI16(spe_brnz, 0x042)
+EMIT_RI16(spe_brz, 0x040)
+EMIT_RI16(spe_brhnz, 0x046)
+EMIT_RI16(spe_brhz, 0x044)
+
+/* Control instructions
+ */
+EMIT (spe_lnop, 0x001)
+
+extern void
+spe_lqd(struct spe_function *p, int rT, int rA, int offset);
+
+extern void
+spe_stqd(struct spe_function *p, int rT, int rA, int offset);
+
+extern void spe_bi(struct spe_function *p, int rA, int d, int e);
+extern void spe_iret(struct spe_function *p, int rA, int d, int e);
+extern void spe_bisled(struct spe_function *p, int rT, int rA,
+ int d, int e);
+extern void spe_bisl(struct spe_function *p, int rT, int rA,
+ int d, int e);
+extern void spe_biz(struct spe_function *p, int rT, int rA,
+ int d, int e);
+extern void spe_binz(struct spe_function *p, int rT, int rA,
+ int d, int e);
+extern void spe_bihz(struct spe_function *p, int rT, int rA,
+ int d, int e);
+extern void spe_bihnz(struct spe_function *p, int rT, int rA,
+ int d, int e);
+
+
+/** Load/splat immediate float into rT. */
+extern void
+spe_load_float(struct spe_function *p, int rT, float x);
+
+/** Load/splat immediate int into rT. */
+extern void
+spe_load_int(struct spe_function *p, int rT, int i);
+
+/** Load/splat immediate unsigned int into rT. */
+extern void
+spe_load_uint(struct spe_function *p, int rT, uint ui);
+
+/** And immediate value into rT. */
+extern void
+spe_and_uint(struct spe_function *p, int rT, int rA, uint ui);
+
+/** Xor immediate value into rT. */
+extern void
+spe_xor_uint(struct spe_function *p, int rT, int rA, uint ui);
+
+/** Compare equal with immediate value. */
+extern void
+spe_compare_equal_uint(struct spe_function *p, int rT, int rA, uint ui);
+
+/** Compare greater with immediate value. */
+extern void
+spe_compare_greater_uint(struct spe_function *p, int rT, int rA, uint ui);
+
+/** Replicate word 0 of rA across rT. */
+extern void
+spe_splat(struct spe_function *p, int rT, int rA);
+
+/** rT = complement_all_bits(rA). */
+extern void
+spe_complement(struct spe_function *p, int rT, int rA);
+
+/** rT = rA. */
+extern void
+spe_move(struct spe_function *p, int rT, int rA);
+
+/** rT = {0,0,0,0}. */
+extern void
+spe_zero(struct spe_function *p, int rT);
+
+/** rT = splat(rA, word) */
+extern void
+spe_splat_word(struct spe_function *p, int rT, int rA, int word);
+
+/** rT = float min(rA, rB) */
+extern void
+spe_float_min(struct spe_function *p, int rT, int rA, int rB);
+
+/** rT = float max(rA, rB) */
+extern void
+spe_float_max(struct spe_function *p, int rT, int rA, int rB);
+
+
+/* Floating-point instructions
+ */
+EMIT_RR (spe_fa, 0x2c4)
+EMIT_RR (spe_dfa, 0x2cc)
+EMIT_RR (spe_fs, 0x2c5)
+EMIT_RR (spe_dfs, 0x2cd)
+EMIT_RR (spe_fm, 0x2c6)
+EMIT_RR (spe_dfm, 0x2ce)
+EMIT_RRR (spe_fma, 0x00e)
+EMIT_RR (spe_dfma, 0x35c)
+EMIT_RRR (spe_fnms, 0x00d)
+EMIT_RR (spe_dfnms, 0x35e)
+EMIT_RRR (spe_fms, 0x00f)
+EMIT_RR (spe_dfms, 0x35d)
+EMIT_RR (spe_dfnma, 0x35f)
+EMIT_R (spe_frest, 0x1b8)
+EMIT_R (spe_frsqest, 0x1b9)
+EMIT_RR (spe_fi, 0x3d4)
+EMIT_RI8 (spe_csflt, 0x1da, 155)
+EMIT_RI8 (spe_cflts, 0x1d8, 173)
+EMIT_RI8 (spe_cuflt, 0x1db, 155)
+EMIT_RI8 (spe_cfltu, 0x1d9, 173)
+EMIT_R (spe_frds, 0x3b9)
+EMIT_R (spe_fesd, 0x3b8)
+EMIT_RR (spe_dfceq, 0x3c3)
+EMIT_RR (spe_dfcmeq, 0x3cb)
+EMIT_RR (spe_dfcgt, 0x2c3)
+EMIT_RR (spe_dfcmgt, 0x2cb)
+EMIT_RI7 (spe_dftsv, 0x3bf)
+EMIT_RR (spe_fceq, 0x3c2)
+EMIT_RR (spe_fcmeq, 0x3ca)
+EMIT_RR (spe_fcgt, 0x2c2)
+EMIT_RR (spe_fcmgt, 0x2ca)
+EMIT_R (spe_fscrwr, 0x3ba)
+EMIT_ (spe_fscrrd, 0x398)
+
+
+/* Channel instructions
+ */
+EMIT_R (spe_rdch, 0x00d)
+EMIT_R (spe_rdchcnt, 0x00f)
+EMIT_R (spe_wrch, 0x10d)
+
+
+#ifdef UNDEF_EMIT_MACROS
+#undef EMIT
+#undef EMIT_
+#undef EMIT_R
+#undef EMIT_RR
+#undef EMIT_RRR
+#undef EMIT_RI7
+#undef EMIT_RI8
+#undef EMIT_RI10
+#undef EMIT_RI10s
+#undef EMIT_RI16
+#undef EMIT_RI18
+#undef EMIT_I16
+#undef UNDEF_EMIT_MACROS
+#endif /* EMIT_ */
diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
new file mode 100644
index 0000000000..1acf3c373e
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
@@ -0,0 +1,1757 @@
+/**************************************************************************
+ *
+ * Copyright (C) 1999-2005 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.
+ *
+ **************************************************************************/
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_ARCH_X86)
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "util/u_pointer.h"
+
+#include "rtasm_execmem.h"
+#include "rtasm_x86sse.h"
+
+#define DISASSEM 0
+#define X86_TWOB 0x0f
+
+
+#define DUMP_SSE 0
+
+
+void x86_print_reg( struct x86_reg reg )
+{
+ if (reg.mod != mod_REG)
+ debug_printf( "[" );
+
+ switch( reg.file ) {
+ case file_REG32:
+ switch( reg.idx ) {
+ case reg_AX: debug_printf( "EAX" ); break;
+ case reg_CX: debug_printf( "ECX" ); break;
+ case reg_DX: debug_printf( "EDX" ); break;
+ case reg_BX: debug_printf( "EBX" ); break;
+ case reg_SP: debug_printf( "ESP" ); break;
+ case reg_BP: debug_printf( "EBP" ); break;
+ case reg_SI: debug_printf( "ESI" ); break;
+ case reg_DI: debug_printf( "EDI" ); break;
+ }
+ break;
+ case file_MMX:
+ debug_printf( "MMX%u", reg.idx );
+ break;
+ case file_XMM:
+ debug_printf( "XMM%u", reg.idx );
+ break;
+ case file_x87:
+ debug_printf( "fp%u", reg.idx );
+ break;
+ }
+
+ if (reg.mod == mod_DISP8 ||
+ reg.mod == mod_DISP32)
+ debug_printf("+%d", reg.disp);
+
+ if (reg.mod != mod_REG)
+ debug_printf( "]" );
+}
+
+#if DUMP_SSE
+
+#define DUMP_START() debug_printf( "\n" )
+#define DUMP_END() debug_printf( "\n" )
+
+#define DUMP() do { \
+ const char *foo = __FUNCTION__; \
+ while (*foo && *foo != '_') \
+ foo++; \
+ if (*foo) \
+ foo++; \
+ debug_printf( "\n% 4x% 15s ", p->csr - p->store, foo ); \
+} while (0)
+
+#define DUMP_I( I ) do { \
+ DUMP(); \
+ debug_printf( "%u", I ); \
+} while( 0 )
+
+#define DUMP_R( R0 ) do { \
+ DUMP(); \
+ x86_print_reg( R0 ); \
+} while( 0 )
+
+#define DUMP_RR( R0, R1 ) do { \
+ DUMP(); \
+ x86_print_reg( R0 ); \
+ debug_printf( ", " ); \
+ x86_print_reg( R1 ); \
+} while( 0 )
+
+#define DUMP_RI( R0, I ) do { \
+ DUMP(); \
+ x86_print_reg( R0 ); \
+ debug_printf( ", %u", I ); \
+} while( 0 )
+
+#define DUMP_RRI( R0, R1, I ) do { \
+ DUMP(); \
+ x86_print_reg( R0 ); \
+ debug_printf( ", " ); \
+ x86_print_reg( R1 ); \
+ debug_printf( ", %u", I ); \
+} while( 0 )
+
+#else
+
+#define DUMP_START()
+#define DUMP_END()
+#define DUMP( )
+#define DUMP_I( I )
+#define DUMP_R( R0 )
+#define DUMP_RR( R0, R1 )
+#define DUMP_RI( R0, I )
+#define DUMP_RRI( R0, R1, I )
+
+#endif
+
+
+static void do_realloc( struct x86_function *p )
+{
+ if (p->store == p->error_overflow) {
+ p->csr = p->store;
+ }
+ else if (p->size == 0) {
+ p->size = 1024;
+ p->store = rtasm_exec_malloc(p->size);
+ p->csr = p->store;
+ }
+ else {
+ uintptr_t used = pointer_to_uintptr( p->csr ) - pointer_to_uintptr( p->store );
+ unsigned char *tmp = p->store;
+ p->size *= 2;
+ p->store = rtasm_exec_malloc(p->size);
+
+ if (p->store) {
+ memcpy(p->store, tmp, used);
+ p->csr = p->store + used;
+ }
+ else {
+ p->csr = p->store;
+ }
+
+ rtasm_exec_free(tmp);
+ }
+
+ if (p->store == NULL) {
+ p->store = p->csr = p->error_overflow;
+ p->size = sizeof(p->error_overflow);
+ }
+}
+
+/* Emit bytes to the instruction stream:
+ */
+static unsigned char *reserve( struct x86_function *p, int bytes )
+{
+ if (p->csr + bytes - p->store > (int) p->size)
+ do_realloc(p);
+
+ {
+ unsigned char *csr = p->csr;
+ p->csr += bytes;
+ return csr;
+ }
+}
+
+
+
+static void emit_1b( struct x86_function *p, char b0 )
+{
+ char *csr = (char *)reserve(p, 1);
+ *csr = b0;
+}
+
+static void emit_1i( struct x86_function *p, int i0 )
+{
+ int *icsr = (int *)reserve(p, sizeof(i0));
+ *icsr = i0;
+}
+
+static void emit_1ub( struct x86_function *p, unsigned char b0 )
+{
+ unsigned char *csr = reserve(p, 1);
+ *csr++ = b0;
+}
+
+static void emit_2ub( struct x86_function *p, unsigned char b0, unsigned char b1 )
+{
+ unsigned char *csr = reserve(p, 2);
+ *csr++ = b0;
+ *csr++ = b1;
+}
+
+static void emit_3ub( struct x86_function *p, unsigned char b0, unsigned char b1, unsigned char b2 )
+{
+ unsigned char *csr = reserve(p, 3);
+ *csr++ = b0;
+ *csr++ = b1;
+ *csr++ = b2;
+}
+
+
+/* Build a modRM byte + possible displacement. No treatment of SIB
+ * indexing. BZZT - no way to encode an absolute address.
+ *
+ * This is the "/r" field in the x86 manuals...
+ */
+static void emit_modrm( struct x86_function *p,
+ struct x86_reg reg,
+ struct x86_reg regmem )
+{
+ unsigned char val = 0;
+
+ assert(reg.mod == mod_REG);
+
+ val |= regmem.mod << 6; /* mod field */
+ val |= reg.idx << 3; /* reg field */
+ val |= regmem.idx; /* r/m field */
+
+ emit_1ub(p, val);
+
+ /* Oh-oh we've stumbled into the SIB thing.
+ */
+ if (regmem.file == file_REG32 &&
+ regmem.idx == reg_SP &&
+ regmem.mod != mod_REG) {
+ emit_1ub(p, 0x24); /* simplistic! */
+ }
+
+ switch (regmem.mod) {
+ case mod_REG:
+ case mod_INDIRECT:
+ break;
+ case mod_DISP8:
+ emit_1b(p, (char) regmem.disp);
+ break;
+ case mod_DISP32:
+ emit_1i(p, regmem.disp);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+/* Emits the "/0".."/7" specialized versions of the modrm ("/r") bytes.
+ */
+static void emit_modrm_noreg( struct x86_function *p,
+ unsigned op,
+ struct x86_reg regmem )
+{
+ struct x86_reg dummy = x86_make_reg(file_REG32, op);
+ emit_modrm(p, dummy, regmem);
+}
+
+/* Many x86 instructions have two opcodes to cope with the situations
+ * where the destination is a register or memory reference
+ * respectively. This function selects the correct opcode based on
+ * the arguments presented.
+ */
+static void emit_op_modrm( struct x86_function *p,
+ unsigned char op_dst_is_reg,
+ unsigned char op_dst_is_mem,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ switch (dst.mod) {
+ case mod_REG:
+ emit_1ub(p, op_dst_is_reg);
+ emit_modrm(p, dst, src);
+ break;
+ case mod_INDIRECT:
+ case mod_DISP32:
+ case mod_DISP8:
+ assert(src.mod == mod_REG);
+ emit_1ub(p, op_dst_is_mem);
+ emit_modrm(p, src, dst);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+
+
+
+
+
+
+/* Create and manipulate registers and regmem values:
+ */
+struct x86_reg x86_make_reg( enum x86_reg_file file,
+ enum x86_reg_name idx )
+{
+ struct x86_reg reg;
+
+ reg.file = file;
+ reg.idx = idx;
+ reg.mod = mod_REG;
+ reg.disp = 0;
+
+ return reg;
+}
+
+struct x86_reg x86_make_disp( struct x86_reg reg,
+ int disp )
+{
+ assert(reg.file == file_REG32);
+
+ if (reg.mod == mod_REG)
+ reg.disp = disp;
+ else
+ reg.disp += disp;
+
+ if (reg.disp == 0 && reg.idx != reg_BP)
+ reg.mod = mod_INDIRECT;
+ else if (reg.disp <= 127 && reg.disp >= -128)
+ reg.mod = mod_DISP8;
+ else
+ reg.mod = mod_DISP32;
+
+ return reg;
+}
+
+struct x86_reg x86_deref( struct x86_reg reg )
+{
+ return x86_make_disp(reg, 0);
+}
+
+struct x86_reg x86_get_base_reg( struct x86_reg reg )
+{
+ return x86_make_reg( reg.file, reg.idx );
+}
+
+int x86_get_label( struct x86_function *p )
+{
+ return p->csr - p->store;
+}
+
+
+
+/***********************************************************************
+ * x86 instructions
+ */
+
+
+void x86_jcc( struct x86_function *p,
+ enum x86_cc cc,
+ int label )
+{
+ int offset = label - (x86_get_label(p) + 2);
+ DUMP_I(cc);
+
+ if (offset < 0) {
+ /*assert(p->csr - p->store > -offset);*/
+ if (p->csr - p->store <= -offset) {
+ /* probably out of memory (using the error_overflow buffer) */
+ return;
+ }
+ }
+
+ if (offset <= 127 && offset >= -128) {
+ emit_1ub(p, 0x70 + cc);
+ emit_1b(p, (char) offset);
+ }
+ else {
+ offset = label - (x86_get_label(p) + 6);
+ emit_2ub(p, 0x0f, 0x80 + cc);
+ emit_1i(p, offset);
+ }
+}
+
+/* Always use a 32bit offset for forward jumps:
+ */
+int x86_jcc_forward( struct x86_function *p,
+ enum x86_cc cc )
+{
+ DUMP_I(cc);
+ emit_2ub(p, 0x0f, 0x80 + cc);
+ emit_1i(p, 0);
+ return x86_get_label(p);
+}
+
+int x86_jmp_forward( struct x86_function *p)
+{
+ DUMP();
+ emit_1ub(p, 0xe9);
+ emit_1i(p, 0);
+ return x86_get_label(p);
+}
+
+int x86_call_forward( struct x86_function *p)
+{
+ DUMP();
+
+ emit_1ub(p, 0xe8);
+ emit_1i(p, 0);
+ return x86_get_label(p);
+}
+
+/* Fixup offset from forward jump:
+ */
+void x86_fixup_fwd_jump( struct x86_function *p,
+ int fixup )
+{
+ *(int *)(p->store + fixup - 4) = x86_get_label(p) - fixup;
+}
+
+void x86_jmp( struct x86_function *p, int label)
+{
+ DUMP_I( label );
+ emit_1ub(p, 0xe9);
+ emit_1i(p, label - x86_get_label(p) - 4);
+}
+
+void x86_call( struct x86_function *p, struct x86_reg reg)
+{
+ DUMP_R( reg );
+ emit_1ub(p, 0xff);
+ emit_modrm_noreg(p, 2, reg);
+}
+
+
+void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm )
+{
+ DUMP_RI( dst, imm );
+ assert(dst.file == file_REG32);
+ assert(dst.mod == mod_REG);
+ emit_1ub(p, 0xb8 + dst.idx);
+ emit_1i(p, imm);
+}
+
+/**
+ * Immediate group 1 instructions.
+ */
+static INLINE void
+x86_group1_imm( struct x86_function *p,
+ unsigned op, struct x86_reg dst, int imm )
+{
+ assert(dst.file == file_REG32);
+ assert(dst.mod == mod_REG);
+ if(-0x80 <= imm && imm < 0x80) {
+ emit_1ub(p, 0x83);
+ emit_modrm_noreg(p, op, dst);
+ emit_1b(p, (char)imm);
+ }
+ else {
+ emit_1ub(p, 0x81);
+ emit_modrm_noreg(p, op, dst);
+ emit_1i(p, imm);
+ }
+}
+
+void x86_add_imm( struct x86_function *p, struct x86_reg dst, int imm )
+{
+ DUMP_RI( dst, imm );
+ x86_group1_imm(p, 0, dst, imm);
+}
+
+void x86_or_imm( struct x86_function *p, struct x86_reg dst, int imm )
+{
+ DUMP_RI( dst, imm );
+ x86_group1_imm(p, 1, dst, imm);
+}
+
+void x86_and_imm( struct x86_function *p, struct x86_reg dst, int imm )
+{
+ DUMP_RI( dst, imm );
+ x86_group1_imm(p, 4, dst, imm);
+}
+
+void x86_sub_imm( struct x86_function *p, struct x86_reg dst, int imm )
+{
+ DUMP_RI( dst, imm );
+ x86_group1_imm(p, 5, dst, imm);
+}
+
+void x86_xor_imm( struct x86_function *p, struct x86_reg dst, int imm )
+{
+ DUMP_RI( dst, imm );
+ x86_group1_imm(p, 6, dst, imm);
+}
+
+void x86_cmp_imm( struct x86_function *p, struct x86_reg dst, int imm )
+{
+ DUMP_RI( dst, imm );
+ x86_group1_imm(p, 7, dst, imm);
+}
+
+
+void x86_push( struct x86_function *p,
+ struct x86_reg reg )
+{
+ DUMP_R( reg );
+ if (reg.mod == mod_REG)
+ emit_1ub(p, 0x50 + reg.idx);
+ else
+ {
+ emit_1ub(p, 0xff);
+ emit_modrm_noreg(p, 6, reg);
+ }
+
+
+ p->stack_offset += 4;
+}
+
+void x86_push_imm32( struct x86_function *p,
+ int imm32 )
+{
+ DUMP_I( imm32 );
+ emit_1ub(p, 0x68);
+ emit_1i(p, imm32);
+
+ p->stack_offset += 4;
+}
+
+
+void x86_pop( struct x86_function *p,
+ struct x86_reg reg )
+{
+ DUMP_R( reg );
+ assert(reg.mod == mod_REG);
+ emit_1ub(p, 0x58 + reg.idx);
+ p->stack_offset -= 4;
+}
+
+void x86_inc( struct x86_function *p,
+ struct x86_reg reg )
+{
+ DUMP_R( reg );
+ assert(reg.mod == mod_REG);
+ emit_1ub(p, 0x40 + reg.idx);
+}
+
+void x86_dec( struct x86_function *p,
+ struct x86_reg reg )
+{
+ DUMP_R( reg );
+ assert(reg.mod == mod_REG);
+ emit_1ub(p, 0x48 + reg.idx);
+}
+
+void x86_ret( struct x86_function *p )
+{
+ DUMP();
+ assert(p->stack_offset == 0);
+ emit_1ub(p, 0xc3);
+}
+
+void x86_retw( struct x86_function *p, unsigned short imm )
+{
+ DUMP();
+ emit_3ub(p, 0xc2, imm & 0xff, (imm >> 8) & 0xff);
+}
+
+void x86_sahf( struct x86_function *p )
+{
+ DUMP();
+ emit_1ub(p, 0x9e);
+}
+
+void x86_mov( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_op_modrm( p, 0x8b, 0x89, dst, src );
+}
+
+void x86_xor( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_op_modrm( p, 0x33, 0x31, dst, src );
+}
+
+void x86_cmp( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_op_modrm( p, 0x3b, 0x39, dst, src );
+}
+
+void x86_lea( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_1ub(p, 0x8d);
+ emit_modrm( p, dst, src );
+}
+
+void x86_test( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_1ub(p, 0x85);
+ emit_modrm( p, dst, src );
+}
+
+void x86_add( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_op_modrm(p, 0x03, 0x01, dst, src );
+}
+
+/* Calculate EAX * src, results in EDX:EAX.
+ */
+void x86_mul( struct x86_function *p,
+ struct x86_reg src )
+{
+ DUMP_R( src );
+ emit_1ub(p, 0xf7);
+ emit_modrm_noreg(p, 4, src );
+}
+
+
+void x86_imul( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0xAF);
+ emit_modrm(p, dst, src);
+}
+
+
+void x86_sub( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_op_modrm(p, 0x2b, 0x29, dst, src );
+}
+
+void x86_or( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_op_modrm( p, 0x0b, 0x09, dst, src );
+}
+
+void x86_and( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_op_modrm( p, 0x23, 0x21, dst, src );
+}
+
+
+
+/***********************************************************************
+ * SSE instructions
+ */
+
+void sse_prefetchnta( struct x86_function *p, struct x86_reg ptr)
+{
+ DUMP_R( ptr );
+ assert(ptr.mod != mod_REG);
+ emit_2ub(p, 0x0f, 0x18);
+ emit_modrm_noreg(p, 0, ptr);
+}
+
+void sse_prefetch0( struct x86_function *p, struct x86_reg ptr)
+{
+ DUMP_R( ptr );
+ assert(ptr.mod != mod_REG);
+ emit_2ub(p, 0x0f, 0x18);
+ emit_modrm_noreg(p, 1, ptr);
+}
+
+void sse_prefetch1( struct x86_function *p, struct x86_reg ptr)
+{
+ DUMP_R( ptr );
+ assert(ptr.mod != mod_REG);
+ emit_2ub(p, 0x0f, 0x18);
+ emit_modrm_noreg(p, 2, ptr);
+}
+
+void sse_movntps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src)
+{
+ DUMP_RR( dst, src );
+
+ assert(dst.mod != mod_REG);
+ assert(src.mod == mod_REG);
+ emit_2ub(p, 0x0f, 0x2b);
+ emit_modrm(p, src, dst);
+}
+
+
+
+
+void sse_movss( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, 0xF3, X86_TWOB);
+ emit_op_modrm( p, 0x10, 0x11, dst, src );
+}
+
+void sse_movaps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_1ub(p, X86_TWOB);
+ emit_op_modrm( p, 0x28, 0x29, dst, src );
+}
+
+void sse_movups( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_1ub(p, X86_TWOB);
+ emit_op_modrm( p, 0x10, 0x11, dst, src );
+}
+
+void sse_movhps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ assert(dst.mod != mod_REG || src.mod != mod_REG);
+ emit_1ub(p, X86_TWOB);
+ emit_op_modrm( p, 0x16, 0x17, dst, src ); /* cf movlhps */
+}
+
+void sse_movlps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ assert(dst.mod != mod_REG || src.mod != mod_REG);
+ emit_1ub(p, X86_TWOB);
+ emit_op_modrm( p, 0x12, 0x13, dst, src ); /* cf movhlps */
+}
+
+void sse_maxps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x5F);
+ emit_modrm( p, dst, src );
+}
+
+void sse_maxss( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0xF3, X86_TWOB, 0x5F);
+ emit_modrm( p, dst, src );
+}
+
+void sse_divss( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0xF3, X86_TWOB, 0x5E);
+ emit_modrm( p, dst, src );
+}
+
+void sse_minps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x5D);
+ emit_modrm( p, dst, src );
+}
+
+void sse_subps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x5C);
+ emit_modrm( p, dst, src );
+}
+
+void sse_mulps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x59);
+ emit_modrm( p, dst, src );
+}
+
+void sse_mulss( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0xF3, X86_TWOB, 0x59);
+ emit_modrm( p, dst, src );
+}
+
+void sse_addps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x58);
+ emit_modrm( p, dst, src );
+}
+
+void sse_addss( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0xF3, X86_TWOB, 0x58);
+ emit_modrm( p, dst, src );
+}
+
+void sse_andnps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x55);
+ emit_modrm( p, dst, src );
+}
+
+void sse_andps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x54);
+ emit_modrm( p, dst, src );
+}
+
+void sse_rsqrtps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x52);
+ emit_modrm( p, dst, src );
+}
+
+void sse_rsqrtss( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0xF3, X86_TWOB, 0x52);
+ emit_modrm( p, dst, src );
+
+}
+
+void sse_movhlps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ assert(dst.mod == mod_REG && src.mod == mod_REG);
+ emit_2ub(p, X86_TWOB, 0x12);
+ emit_modrm( p, dst, src );
+}
+
+void sse_movlhps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ assert(dst.mod == mod_REG && src.mod == mod_REG);
+ emit_2ub(p, X86_TWOB, 0x16);
+ emit_modrm( p, dst, src );
+}
+
+void sse_orps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x56);
+ emit_modrm( p, dst, src );
+}
+
+void sse_xorps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x57);
+ emit_modrm( p, dst, src );
+}
+
+void sse_cvtps2pi( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ assert(dst.file == file_MMX &&
+ (src.file == file_XMM || src.mod != mod_REG));
+
+ p->need_emms = 1;
+
+ emit_2ub(p, X86_TWOB, 0x2d);
+ emit_modrm( p, dst, src );
+}
+
+void sse2_cvtdq2ps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x5b);
+ emit_modrm( p, dst, src );
+}
+
+
+/* Shufps can also be used to implement a reduced swizzle when dest ==
+ * arg0.
+ */
+void sse_shufps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src,
+ unsigned char shuf)
+{
+ DUMP_RRI( dst, src, shuf );
+ emit_2ub(p, X86_TWOB, 0xC6);
+ emit_modrm(p, dst, src);
+ emit_1ub(p, shuf);
+}
+
+void sse_unpckhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub( p, X86_TWOB, 0x15 );
+ emit_modrm( p, dst, src );
+}
+
+void sse_unpcklps( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub( p, X86_TWOB, 0x14 );
+ emit_modrm( p, dst, src );
+}
+
+void sse_cmpps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src,
+ enum sse_cc cc)
+{
+ DUMP_RRI( dst, src, cc );
+ emit_2ub(p, X86_TWOB, 0xC2);
+ emit_modrm(p, dst, src);
+ emit_1ub(p, cc);
+}
+
+void sse_pmovmskb( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src)
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0x66, X86_TWOB, 0xD7);
+ emit_modrm(p, dst, src);
+}
+
+void sse_movmskps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src)
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x50);
+ emit_modrm(p, dst, src);
+}
+
+/***********************************************************************
+ * SSE2 instructions
+ */
+
+/**
+ * Perform a reduced swizzle:
+ */
+void sse2_pshufd( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src,
+ unsigned char shuf)
+{
+ DUMP_RRI( dst, src, shuf );
+ emit_3ub(p, 0x66, X86_TWOB, 0x70);
+ emit_modrm(p, dst, src);
+ emit_1ub(p, shuf);
+}
+
+void sse2_cvttps2dq( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub( p, 0xF3, X86_TWOB, 0x5B );
+ emit_modrm( p, dst, src );
+}
+
+void sse2_cvtps2dq( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0x66, X86_TWOB, 0x5B);
+ emit_modrm( p, dst, src );
+}
+
+void sse2_packssdw( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0x66, X86_TWOB, 0x6B);
+ emit_modrm( p, dst, src );
+}
+
+void sse2_packsswb( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0x66, X86_TWOB, 0x63);
+ emit_modrm( p, dst, src );
+}
+
+void sse2_packuswb( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0x66, X86_TWOB, 0x67);
+ emit_modrm( p, dst, src );
+}
+
+void sse2_punpcklbw( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0x66, X86_TWOB, 0x60);
+ emit_modrm( p, dst, src );
+}
+
+
+void sse2_rcpps( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, X86_TWOB, 0x53);
+ emit_modrm( p, dst, src );
+}
+
+void sse2_rcpss( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_3ub(p, 0xF3, X86_TWOB, 0x53);
+ emit_modrm( p, dst, src );
+}
+
+void sse2_movd( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ emit_2ub(p, 0x66, X86_TWOB);
+ emit_op_modrm( p, 0x6e, 0x7e, dst, src );
+}
+
+
+
+
+/***********************************************************************
+ * x87 instructions
+ */
+static void note_x87_pop( struct x86_function *p )
+{
+ p->x87_stack--;
+ assert(p->x87_stack >= 0);
+}
+
+static void note_x87_push( struct x86_function *p )
+{
+ p->x87_stack++;
+ assert(p->x87_stack <= 7);
+}
+
+void x87_assert_stack_empty( struct x86_function *p )
+{
+ assert (p->x87_stack == 0);
+}
+
+
+void x87_fist( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ emit_1ub(p, 0xdb);
+ emit_modrm_noreg(p, 2, dst);
+}
+
+void x87_fistp( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ emit_1ub(p, 0xdb);
+ emit_modrm_noreg(p, 3, dst);
+ note_x87_pop(p);
+}
+
+void x87_fild( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ emit_1ub(p, 0xdf);
+ emit_modrm_noreg(p, 0, arg);
+ note_x87_push(p);
+}
+
+void x87_fldz( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xee);
+ note_x87_push(p);
+}
+
+
+void x87_fldcw( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_REG32);
+ assert(arg.mod != mod_REG);
+ emit_1ub(p, 0xd9);
+ emit_modrm_noreg(p, 5, arg);
+}
+
+void x87_fld1( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xe8);
+ note_x87_push(p);
+}
+
+void x87_fldl2e( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xea);
+ note_x87_push(p);
+}
+
+void x87_fldln2( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xed);
+ note_x87_push(p);
+}
+
+void x87_fwait( struct x86_function *p )
+{
+ DUMP();
+ emit_1ub(p, 0x9b);
+}
+
+void x87_fnclex( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xdb, 0xe2);
+}
+
+void x87_fclex( struct x86_function *p )
+{
+ x87_fwait(p);
+ x87_fnclex(p);
+}
+
+void x87_fcmovb( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_x87);
+ emit_2ub(p, 0xda, 0xc0+arg.idx);
+}
+
+void x87_fcmove( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_x87);
+ emit_2ub(p, 0xda, 0xc8+arg.idx);
+}
+
+void x87_fcmovbe( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_x87);
+ emit_2ub(p, 0xda, 0xd0+arg.idx);
+}
+
+void x87_fcmovnb( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_x87);
+ emit_2ub(p, 0xdb, 0xc0+arg.idx);
+}
+
+void x87_fcmovne( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_x87);
+ emit_2ub(p, 0xdb, 0xc8+arg.idx);
+}
+
+void x87_fcmovnbe( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_x87);
+ emit_2ub(p, 0xdb, 0xd0+arg.idx);
+}
+
+
+
+static void x87_arith_op( struct x86_function *p, struct x86_reg dst, struct x86_reg arg,
+ unsigned char dst0ub0,
+ unsigned char dst0ub1,
+ unsigned char arg0ub0,
+ unsigned char arg0ub1,
+ unsigned char argmem_noreg)
+{
+ assert(dst.file == file_x87);
+
+ if (arg.file == file_x87) {
+ if (dst.idx == 0)
+ emit_2ub(p, dst0ub0, dst0ub1+arg.idx);
+ else if (arg.idx == 0)
+ emit_2ub(p, arg0ub0, arg0ub1+arg.idx);
+ else
+ assert(0);
+ }
+ else if (dst.idx == 0) {
+ assert(arg.file == file_REG32);
+ emit_1ub(p, 0xd8);
+ emit_modrm_noreg(p, argmem_noreg, arg);
+ }
+ else
+ assert(0);
+}
+
+void x87_fmul( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ x87_arith_op(p, dst, src,
+ 0xd8, 0xc8,
+ 0xdc, 0xc8,
+ 4);
+}
+
+void x87_fsub( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ x87_arith_op(p, dst, src,
+ 0xd8, 0xe0,
+ 0xdc, 0xe8,
+ 4);
+}
+
+void x87_fsubr( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ x87_arith_op(p, dst, src,
+ 0xd8, 0xe8,
+ 0xdc, 0xe0,
+ 5);
+}
+
+void x87_fadd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ x87_arith_op(p, dst, src,
+ 0xd8, 0xc0,
+ 0xdc, 0xc0,
+ 0);
+}
+
+void x87_fdiv( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ x87_arith_op(p, dst, src,
+ 0xd8, 0xf0,
+ 0xdc, 0xf8,
+ 6);
+}
+
+void x87_fdivr( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ x87_arith_op(p, dst, src,
+ 0xd8, 0xf8,
+ 0xdc, 0xf0,
+ 7);
+}
+
+void x87_fmulp( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ assert(dst.file == file_x87);
+ assert(dst.idx >= 1);
+ emit_2ub(p, 0xde, 0xc8+dst.idx);
+ note_x87_pop(p);
+}
+
+void x87_fsubp( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ assert(dst.file == file_x87);
+ assert(dst.idx >= 1);
+ emit_2ub(p, 0xde, 0xe8+dst.idx);
+ note_x87_pop(p);
+}
+
+void x87_fsubrp( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ assert(dst.file == file_x87);
+ assert(dst.idx >= 1);
+ emit_2ub(p, 0xde, 0xe0+dst.idx);
+ note_x87_pop(p);
+}
+
+void x87_faddp( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ assert(dst.file == file_x87);
+ assert(dst.idx >= 1);
+ emit_2ub(p, 0xde, 0xc0+dst.idx);
+ note_x87_pop(p);
+}
+
+void x87_fdivp( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ assert(dst.file == file_x87);
+ assert(dst.idx >= 1);
+ emit_2ub(p, 0xde, 0xf8+dst.idx);
+ note_x87_pop(p);
+}
+
+void x87_fdivrp( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ assert(dst.file == file_x87);
+ assert(dst.idx >= 1);
+ emit_2ub(p, 0xde, 0xf0+dst.idx);
+ note_x87_pop(p);
+}
+
+void x87_ftst( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xe4);
+}
+
+void x87_fucom( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_x87);
+ emit_2ub(p, 0xdd, 0xe0+arg.idx);
+}
+
+void x87_fucomp( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_x87);
+ emit_2ub(p, 0xdd, 0xe8+arg.idx);
+ note_x87_pop(p);
+}
+
+void x87_fucompp( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xda, 0xe9);
+ note_x87_pop(p); /* pop twice */
+ note_x87_pop(p); /* pop twice */
+}
+
+void x87_fxch( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ assert(arg.file == file_x87);
+ emit_2ub(p, 0xd9, 0xc8+arg.idx);
+}
+
+void x87_fabs( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xe1);
+}
+
+void x87_fchs( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xe0);
+}
+
+void x87_fcos( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xff);
+}
+
+
+void x87_fprndint( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xfc);
+}
+
+void x87_fscale( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xfd);
+}
+
+void x87_fsin( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xfe);
+}
+
+void x87_fsincos( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xfb);
+}
+
+void x87_fsqrt( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xfa);
+}
+
+void x87_fxtract( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xf4);
+}
+
+/* st0 = (2^st0)-1
+ *
+ * Restrictions: -1.0 <= st0 <= 1.0
+ */
+void x87_f2xm1( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xf0);
+}
+
+/* st1 = st1 * log2(st0);
+ * pop_stack;
+ */
+void x87_fyl2x( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xf1);
+ note_x87_pop(p);
+}
+
+/* st1 = st1 * log2(st0 + 1.0);
+ * pop_stack;
+ *
+ * A fast operation, with restrictions: -.29 < st0 < .29
+ */
+void x87_fyl2xp1( struct x86_function *p )
+{
+ DUMP();
+ emit_2ub(p, 0xd9, 0xf9);
+ note_x87_pop(p);
+}
+
+
+void x87_fld( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ if (arg.file == file_x87)
+ emit_2ub(p, 0xd9, 0xc0 + arg.idx);
+ else {
+ emit_1ub(p, 0xd9);
+ emit_modrm_noreg(p, 0, arg);
+ }
+ note_x87_push(p);
+}
+
+void x87_fst( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ if (dst.file == file_x87)
+ emit_2ub(p, 0xdd, 0xd0 + dst.idx);
+ else {
+ emit_1ub(p, 0xd9);
+ emit_modrm_noreg(p, 2, dst);
+ }
+}
+
+void x87_fstp( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ if (dst.file == file_x87)
+ emit_2ub(p, 0xdd, 0xd8 + dst.idx);
+ else {
+ emit_1ub(p, 0xd9);
+ emit_modrm_noreg(p, 3, dst);
+ }
+ note_x87_pop(p);
+}
+
+void x87_fpop( struct x86_function *p )
+{
+ x87_fstp( p, x86_make_reg( file_x87, 0 ));
+}
+
+
+void x87_fcom( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ if (dst.file == file_x87)
+ emit_2ub(p, 0xd8, 0xd0 + dst.idx);
+ else {
+ emit_1ub(p, 0xd8);
+ emit_modrm_noreg(p, 2, dst);
+ }
+}
+
+
+void x87_fcomp( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ if (dst.file == file_x87)
+ emit_2ub(p, 0xd8, 0xd8 + dst.idx);
+ else {
+ emit_1ub(p, 0xd8);
+ emit_modrm_noreg(p, 3, dst);
+ }
+ note_x87_pop(p);
+}
+
+void x87_fcomi( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ emit_2ub(p, 0xdb, 0xf0+arg.idx);
+}
+
+void x87_fcomip( struct x86_function *p, struct x86_reg arg )
+{
+ DUMP_R( arg );
+ emit_2ub(p, 0xdb, 0xf0+arg.idx);
+ note_x87_pop(p);
+}
+
+
+void x87_fnstsw( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ assert(dst.file == file_REG32);
+
+ if (dst.idx == reg_AX &&
+ dst.mod == mod_REG)
+ emit_2ub(p, 0xdf, 0xe0);
+ else {
+ emit_1ub(p, 0xdd);
+ emit_modrm_noreg(p, 7, dst);
+ }
+}
+
+
+void x87_fnstcw( struct x86_function *p, struct x86_reg dst )
+{
+ DUMP_R( dst );
+ assert(dst.file == file_REG32);
+
+ emit_1ub(p, 0x9b); /* WAIT -- needed? */
+ emit_1ub(p, 0xd9);
+ emit_modrm_noreg(p, 7, dst);
+}
+
+
+
+
+/***********************************************************************
+ * MMX instructions
+ */
+
+void mmx_emms( struct x86_function *p )
+{
+ DUMP();
+ assert(p->need_emms);
+ emit_2ub(p, 0x0f, 0x77);
+ p->need_emms = 0;
+}
+
+void mmx_packssdw( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ assert(dst.file == file_MMX &&
+ (src.file == file_MMX || src.mod != mod_REG));
+
+ p->need_emms = 1;
+
+ emit_2ub(p, X86_TWOB, 0x6b);
+ emit_modrm( p, dst, src );
+}
+
+void mmx_packuswb( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ assert(dst.file == file_MMX &&
+ (src.file == file_MMX || src.mod != mod_REG));
+
+ p->need_emms = 1;
+
+ emit_2ub(p, X86_TWOB, 0x67);
+ emit_modrm( p, dst, src );
+}
+
+void mmx_movd( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ p->need_emms = 1;
+ emit_1ub(p, X86_TWOB);
+ emit_op_modrm( p, 0x6e, 0x7e, dst, src );
+}
+
+void mmx_movq( struct x86_function *p,
+ struct x86_reg dst,
+ struct x86_reg src )
+{
+ DUMP_RR( dst, src );
+ p->need_emms = 1;
+ emit_1ub(p, X86_TWOB);
+ emit_op_modrm( p, 0x6f, 0x7f, dst, src );
+}
+
+
+/***********************************************************************
+ * Helper functions
+ */
+
+
+void x86_cdecl_caller_push_regs( struct x86_function *p )
+{
+ x86_push(p, x86_make_reg(file_REG32, reg_AX));
+ x86_push(p, x86_make_reg(file_REG32, reg_CX));
+ x86_push(p, x86_make_reg(file_REG32, reg_DX));
+}
+
+void x86_cdecl_caller_pop_regs( struct x86_function *p )
+{
+ x86_pop(p, x86_make_reg(file_REG32, reg_DX));
+ x86_pop(p, x86_make_reg(file_REG32, reg_CX));
+ x86_pop(p, x86_make_reg(file_REG32, reg_AX));
+}
+
+
+/* Retreive a reference to one of the function arguments, taking into
+ * account any push/pop activity:
+ */
+struct x86_reg x86_fn_arg( struct x86_function *p,
+ unsigned arg )
+{
+ return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
+ p->stack_offset + arg * 4); /* ??? */
+}
+
+
+void x86_init_func( struct x86_function *p )
+{
+ p->size = 0;
+ p->store = NULL;
+ p->csr = p->store;
+ DUMP_START();
+}
+
+void x86_init_func_size( struct x86_function *p, unsigned code_size )
+{
+ p->size = code_size;
+ p->store = rtasm_exec_malloc(code_size);
+ if (p->store == NULL) {
+ p->store = p->error_overflow;
+ }
+ p->csr = p->store;
+ DUMP_START();
+}
+
+void x86_release_func( struct x86_function *p )
+{
+ if (p->store && p->store != p->error_overflow)
+ rtasm_exec_free(p->store);
+
+ p->store = NULL;
+ p->csr = NULL;
+ p->size = 0;
+}
+
+
+void (*x86_get_func( struct x86_function *p ))(void)
+{
+ DUMP_END();
+ if (DISASSEM && p->store)
+ debug_printf("disassemble %p %p\n", p->store, p->csr);
+
+ if (p->store == p->error_overflow)
+ return (void (*)(void)) NULL;
+ else
+ return (void (*)(void)) p->store;
+}
+
+#else
+
+void x86sse_dummy( void )
+{
+}
+
+#endif
diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h
new file mode 100644
index 0000000000..731a651796
--- /dev/null
+++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h
@@ -0,0 +1,320 @@
+/**************************************************************************
+ *
+ * Copyright (C) 1999-2005 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 _RTASM_X86SSE_H_
+#define _RTASM_X86SSE_H_
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_ARCH_X86)
+
+/* It is up to the caller to ensure that instructions issued are
+ * suitable for the host cpu. There are no checks made in this module
+ * for mmx/sse/sse2 support on the cpu.
+ */
+struct x86_reg {
+ unsigned file:3;
+ unsigned idx:3;
+ unsigned mod:2; /* mod_REG if this is just a register */
+ int disp:24; /* only +/- 23bits of offset - should be enough... */
+};
+
+struct x86_function {
+ unsigned size;
+ unsigned char *store;
+ unsigned char *csr;
+
+ unsigned stack_offset:16;
+ unsigned need_emms:8;
+ int x87_stack:8;
+
+ unsigned char error_overflow[4];
+};
+
+enum x86_reg_file {
+ file_REG32,
+ file_MMX,
+ file_XMM,
+ file_x87
+};
+
+/* Values for mod field of modr/m byte
+ */
+enum x86_reg_mod {
+ mod_INDIRECT,
+ mod_DISP8,
+ mod_DISP32,
+ mod_REG
+};
+
+enum x86_reg_name {
+ reg_AX,
+ reg_CX,
+ reg_DX,
+ reg_BX,
+ reg_SP,
+ reg_BP,
+ reg_SI,
+ reg_DI
+};
+
+
+enum x86_cc {
+ cc_O, /* overflow */
+ cc_NO, /* not overflow */
+ cc_NAE, /* not above or equal / carry */
+ cc_AE, /* above or equal / not carry */
+ cc_E, /* equal / zero */
+ cc_NE /* not equal / not zero */
+};
+
+enum sse_cc {
+ cc_Equal,
+ cc_LessThan,
+ cc_LessThanEqual,
+ cc_Unordered,
+ cc_NotEqual,
+ cc_NotLessThan,
+ cc_NotLessThanEqual,
+ cc_Ordered
+};
+
+#define cc_Z cc_E
+#define cc_NZ cc_NE
+
+/* Begin/end/retreive function creation:
+ */
+
+
+void x86_init_func( struct x86_function *p );
+void x86_init_func_size( struct x86_function *p, unsigned code_size );
+void x86_release_func( struct x86_function *p );
+void (*x86_get_func( struct x86_function *p ))( void );
+
+/* Debugging:
+ */
+void x86_print_reg( struct x86_reg reg );
+
+
+/* Create and manipulate registers and regmem values:
+ */
+struct x86_reg x86_make_reg( enum x86_reg_file file,
+ enum x86_reg_name idx );
+
+struct x86_reg x86_make_disp( struct x86_reg reg,
+ int disp );
+
+struct x86_reg x86_deref( struct x86_reg reg );
+
+struct x86_reg x86_get_base_reg( struct x86_reg reg );
+
+
+/* Labels, jumps and fixup:
+ */
+int x86_get_label( struct x86_function *p );
+
+void x86_jcc( struct x86_function *p,
+ enum x86_cc cc,
+ int label );
+
+int x86_jcc_forward( struct x86_function *p,
+ enum x86_cc cc );
+
+int x86_jmp_forward( struct x86_function *p);
+
+int x86_call_forward( struct x86_function *p);
+
+void x86_fixup_fwd_jump( struct x86_function *p,
+ int fixup );
+
+void x86_jmp( struct x86_function *p, int label );
+
+/* void x86_call( struct x86_function *p, void (*label)() ); */
+void x86_call( struct x86_function *p, struct x86_reg reg);
+
+void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm );
+void x86_add_imm( struct x86_function *p, struct x86_reg dst, int imm );
+void x86_or_imm( struct x86_function *p, struct x86_reg dst, int imm );
+void x86_and_imm( struct x86_function *p, struct x86_reg dst, int imm );
+void x86_sub_imm( struct x86_function *p, struct x86_reg dst, int imm );
+void x86_xor_imm( struct x86_function *p, struct x86_reg dst, int imm );
+void x86_cmp_imm( struct x86_function *p, struct x86_reg dst, int imm );
+
+
+/* Macro for sse_shufps() and sse2_pshufd():
+ */
+#define SHUF(_x,_y,_z,_w) (((_x)<<0) | ((_y)<<2) | ((_z)<<4) | ((_w)<<6))
+#define SHUF_NOOP RSW(0,1,2,3)
+#define GET_SHUF(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
+
+void mmx_emms( struct x86_function *p );
+void mmx_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void mmx_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void mmx_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void mmx_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+
+void sse2_cvtps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_cvttps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_cvtdq2ps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_packsswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_pshufd( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
+ unsigned char shuf );
+void sse2_rcpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_rcpss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+
+
+void sse_prefetchnta( struct x86_function *p, struct x86_reg ptr);
+void sse_prefetch0( struct x86_function *p, struct x86_reg ptr);
+void sse_prefetch1( struct x86_function *p, struct x86_reg ptr);
+
+void sse_movntps( struct x86_function *p, struct x86_reg dst, struct x86_reg src);
+
+void sse_addps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_addss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_cvtps2pi( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_divss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_andnps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_andps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_cmpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src,
+ enum sse_cc cc );
+void sse_maxps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_maxss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_minps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_movaps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_movhlps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_movhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_movlhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_movlps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_movss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_movups( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_mulps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_mulss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_orps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_xorps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_subps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_rsqrtps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_rsqrtss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_shufps( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
+ unsigned char shuf );
+void sse_unpckhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_unpcklps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_pmovmskb( struct x86_function *p, struct x86_reg dest, struct x86_reg src );
+void sse2_punpcklbw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse_movmskps( struct x86_function *p, struct x86_reg dst, struct x86_reg src);
+
+void x86_add( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_and( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_cmp( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_dec( struct x86_function *p, struct x86_reg reg );
+void x86_inc( struct x86_function *p, struct x86_reg reg );
+void x86_lea( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_mov( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_mul( struct x86_function *p, struct x86_reg src );
+void x86_imul( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_or( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_pop( struct x86_function *p, struct x86_reg reg );
+void x86_push( struct x86_function *p, struct x86_reg reg );
+void x86_push_imm32( struct x86_function *p, int imm );
+void x86_ret( struct x86_function *p );
+void x86_retw( struct x86_function *p, unsigned short imm );
+void x86_sub( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_test( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_xor( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_sahf( struct x86_function *p );
+
+
+void x86_cdecl_caller_push_regs( struct x86_function *p );
+void x86_cdecl_caller_pop_regs( struct x86_function *p );
+
+void x87_assert_stack_empty( struct x86_function *p );
+
+void x87_f2xm1( struct x86_function *p );
+void x87_fabs( struct x86_function *p );
+void x87_fadd( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
+void x87_faddp( struct x86_function *p, struct x86_reg dst );
+void x87_fchs( struct x86_function *p );
+void x87_fclex( struct x86_function *p );
+void x87_fcmovb( struct x86_function *p, struct x86_reg src );
+void x87_fcmovbe( struct x86_function *p, struct x86_reg src );
+void x87_fcmove( struct x86_function *p, struct x86_reg src );
+void x87_fcmovnb( struct x86_function *p, struct x86_reg src );
+void x87_fcmovnbe( struct x86_function *p, struct x86_reg src );
+void x87_fcmovne( struct x86_function *p, struct x86_reg src );
+void x87_fcom( struct x86_function *p, struct x86_reg dst );
+void x87_fcomi( struct x86_function *p, struct x86_reg dst );
+void x87_fcomip( struct x86_function *p, struct x86_reg dst );
+void x87_fcomp( struct x86_function *p, struct x86_reg dst );
+void x87_fcos( struct x86_function *p );
+void x87_fdiv( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
+void x87_fdivp( struct x86_function *p, struct x86_reg dst );
+void x87_fdivr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
+void x87_fdivrp( struct x86_function *p, struct x86_reg dst );
+void x87_fild( struct x86_function *p, struct x86_reg arg );
+void x87_fist( struct x86_function *p, struct x86_reg dst );
+void x87_fistp( struct x86_function *p, struct x86_reg dst );
+void x87_fld( struct x86_function *p, struct x86_reg arg );
+void x87_fld1( struct x86_function *p );
+void x87_fldcw( struct x86_function *p, struct x86_reg arg );
+void x87_fldl2e( struct x86_function *p );
+void x87_fldln2( struct x86_function *p );
+void x87_fldz( struct x86_function *p );
+void x87_fmul( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
+void x87_fmulp( struct x86_function *p, struct x86_reg dst );
+void x87_fnclex( struct x86_function *p );
+void x87_fprndint( struct x86_function *p );
+void x87_fpop( struct x86_function *p );
+void x87_fscale( struct x86_function *p );
+void x87_fsin( struct x86_function *p );
+void x87_fsincos( struct x86_function *p );
+void x87_fsqrt( struct x86_function *p );
+void x87_fst( struct x86_function *p, struct x86_reg dst );
+void x87_fstp( struct x86_function *p, struct x86_reg dst );
+void x87_fsub( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
+void x87_fsubp( struct x86_function *p, struct x86_reg dst );
+void x87_fsubr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
+void x87_fsubrp( struct x86_function *p, struct x86_reg dst );
+void x87_ftst( struct x86_function *p );
+void x87_fxch( struct x86_function *p, struct x86_reg dst );
+void x87_fxtract( struct x86_function *p );
+void x87_fyl2x( struct x86_function *p );
+void x87_fyl2xp1( struct x86_function *p );
+void x87_fwait( struct x86_function *p );
+void x87_fnstcw( struct x86_function *p, struct x86_reg dst );
+void x87_fnstsw( struct x86_function *p, struct x86_reg dst );
+void x87_fucompp( struct x86_function *p );
+void x87_fucomp( struct x86_function *p, struct x86_reg arg );
+void x87_fucom( struct x86_function *p, struct x86_reg arg );
+
+
+
+/* Retreive a reference to one of the function arguments, taking into
+ * account any push/pop activity. Note - doesn't track explict
+ * manipulation of ESP by other instructions.
+ */
+struct x86_reg x86_fn_arg( struct x86_function *p, unsigned arg );
+
+#endif
+#endif
diff --git a/src/gallium/auxiliary/sct/Makefile b/src/gallium/auxiliary/sct/Makefile
new file mode 100644
index 0000000000..a7d111b689
--- /dev/null
+++ b/src/gallium/auxiliary/sct/Makefile
@@ -0,0 +1,9 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = sct
+
+C_SOURCES = \
+ sct.c
+
+include ../../Makefile.template
diff --git a/src/gallium/auxiliary/sct/SConscript b/src/gallium/auxiliary/sct/SConscript
new file mode 100644
index 0000000000..76927d973f
--- /dev/null
+++ b/src/gallium/auxiliary/sct/SConscript
@@ -0,0 +1,9 @@
+Import('*')
+
+sct = env.ConvenienceLibrary(
+ target = 'sct',
+ source = [
+ 'sct.c'
+ ])
+
+auxiliaries.insert(0, sct)
diff --git a/src/gallium/auxiliary/sct/sct.c b/src/gallium/auxiliary/sct/sct.c
new file mode 100644
index 0000000000..722d2b7e66
--- /dev/null
+++ b/src/gallium/auxiliary/sct/sct.c
@@ -0,0 +1,453 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "pipe/p_state.h"
+#include "sct.h"
+
+
+struct texture_list
+{
+ struct pipe_texture *texture;
+ struct texture_list *next;
+};
+
+
+
+#define MAX_SURFACES ((PIPE_MAX_COLOR_BUFS) + 1)
+
+struct sct_context
+{
+ const struct pipe_context *context;
+
+ /** surfaces the context is drawing into */
+ struct pipe_surface *surfaces[MAX_SURFACES];
+
+ /** currently bound textures */
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+
+ /** previously bound textures, used but not flushed */
+ struct texture_list *textures_used;
+
+ boolean needs_flush;
+
+ struct sct_context *next;
+};
+
+
+
+struct sct_surface
+{
+ const struct pipe_surface *surface;
+
+ /** list of contexts drawing to this surface */
+ struct sct_context_list *contexts;
+
+ struct sct_surface *next;
+};
+
+
+
+/**
+ * Find the surface_info for the given pipe_surface
+ */
+static struct sct_surface *
+find_surface_info(struct surface_context_tracker *sct,
+ const struct pipe_surface *surface)
+{
+ struct sct_surface *si;
+ for (si = sct->surfaces; si; si = si->next)
+ if (si->surface == surface)
+ return si;
+ return NULL;
+}
+
+
+/**
+ * As above, but create new surface_info if surface is new.
+ */
+static struct sct_surface *
+find_create_surface_info(struct surface_context_tracker *sct,
+ const struct pipe_surface *surface)
+{
+ struct sct_surface *si = find_surface_info(sct, surface);
+ if (si)
+ return si;
+
+ /* alloc new */
+ si = CALLOC_STRUCT(sct_surface);
+ if (si) {
+ si->surface = surface;
+
+ /* insert at head */
+ si->next = sct->surfaces;
+ sct->surfaces = si;
+ }
+
+ return si;
+}
+
+
+/**
+ * Find a context_info for the given context.
+ */
+static struct sct_context *
+find_context_info(struct surface_context_tracker *sct,
+ const struct pipe_context *context)
+{
+ struct sct_context *ci;
+ for (ci = sct->contexts; ci; ci = ci->next)
+ if (ci->context == context)
+ return ci;
+ return NULL;
+}
+
+
+/**
+ * As above, but create new context_info if context is new.
+ */
+static struct sct_context *
+find_create_context_info(struct surface_context_tracker *sct,
+ const struct pipe_context *context)
+{
+ struct sct_context *ci = find_context_info(sct, context);
+ if (ci)
+ return ci;
+
+ /* alloc new */
+ ci = CALLOC_STRUCT(sct_context);
+ if (ci) {
+ ci->context = context;
+
+ /* insert at head */
+ ci->next = sct->contexts;
+ sct->contexts = ci;
+ }
+
+ return ci;
+}
+
+
+/**
+ * Is the context already bound to the surface?
+ */
+static boolean
+find_surface_context(const struct sct_surface *si,
+ const struct pipe_context *context)
+{
+ const struct sct_context_list *cl;
+ for (cl = si->contexts; cl; cl = cl->next) {
+ if (cl->context == context) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/**
+ * Add a context to the list of contexts associated with a surface.
+ */
+static void
+add_context_to_surface(struct sct_surface *si,
+ const struct pipe_context *context)
+{
+ struct sct_context_list *cl = CALLOC_STRUCT(sct_context_list);
+ if (cl) {
+ cl->context = context;
+ /* insert at head of list of contexts */
+ cl->next = si->contexts;
+ si->contexts = cl;
+ }
+}
+
+
+/**
+ * Remove a context from the list of contexts associated with a surface.
+ */
+static void
+remove_context_from_surface(struct sct_surface *si,
+ const struct pipe_context *context)
+{
+ struct sct_context_list *prev = NULL, *curr, *next;
+
+ for (curr = si->contexts; curr; curr = next) {
+ if (curr->context == context) {
+ /* remove */
+ if (prev)
+ prev->next = curr->next;
+ else
+ si->contexts = curr->next;
+ next = curr->next;
+ FREE(curr);
+ }
+ else {
+ prev = curr;
+ next = curr->next;
+ }
+ }
+}
+
+
+/**
+ * Unbind context from surface.
+ */
+static void
+unbind_context_surface(struct surface_context_tracker *sct,
+ struct pipe_context *context,
+ struct pipe_surface *surface)
+{
+ struct sct_surface *si = find_surface_info(sct, surface);
+ if (si) {
+ remove_context_from_surface(si, context);
+ }
+}
+
+
+/**
+ * Bind context to a set of surfaces (color + Z).
+ * Like MakeCurrent().
+ */
+void
+sct_bind_surfaces(struct surface_context_tracker *sct,
+ struct pipe_context *context,
+ uint num_surf,
+ struct pipe_surface **surfaces)
+{
+ struct sct_context *ci = find_create_context_info(sct, context);
+ uint i;
+
+ if (!ci) {
+ return; /* out of memory */
+ }
+
+ /* unbind currently bound surfaces */
+ for (i = 0; i < MAX_SURFACES; i++) {
+ if (ci->surfaces[i]) {
+ unbind_context_surface(sct, context, ci->surfaces[i]);
+ }
+ }
+
+ /* bind new surfaces */
+ for (i = 0; i < num_surf; i++) {
+ struct sct_surface *si = find_create_surface_info(sct, surfaces[i]);
+ if (!find_surface_context(si, context)) {
+ add_context_to_surface(si, context);
+ }
+ }
+}
+
+
+/**
+ * Return list of contexts bound to a surface.
+ */
+const struct sct_context_list *
+sct_get_surface_contexts(struct surface_context_tracker *sct,
+ const struct pipe_surface *surface)
+{
+ const struct sct_surface *si = find_surface_info(sct, surface);
+ return si->contexts;
+}
+
+
+
+static boolean
+find_texture(const struct sct_context *ci,
+ const struct pipe_texture *texture)
+{
+ const struct texture_list *tl;
+
+ for (tl = ci->textures_used; tl; tl = tl->next) {
+ if (tl->texture == texture) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/**
+ * Add the given texture to the context's list of used textures.
+ */
+static void
+add_texture_used(struct sct_context *ci,
+ struct pipe_texture *texture)
+{
+ if (!find_texture(ci, texture)) {
+ /* add to list */
+ struct texture_list *tl = CALLOC_STRUCT(texture_list);
+ if (tl) {
+ pipe_texture_reference(&tl->texture, texture);
+ /* insert at head */
+ tl->next = ci->textures_used;
+ ci->textures_used = tl;
+ }
+ }
+}
+
+
+/**
+ * Bind a texture to a rendering context.
+ */
+void
+sct_bind_texture(struct surface_context_tracker *sct,
+ struct pipe_context *context,
+ uint unit,
+ struct pipe_texture *tex)
+{
+ struct sct_context *ci = find_context_info(sct, context);
+
+ if (ci->textures[unit] != tex) {
+ /* put texture on the 'used' list */
+ add_texture_used(ci, tex);
+ /* bind new */
+ pipe_texture_reference(&ci->textures[unit], tex);
+ }
+}
+
+
+/**
+ * Check if the given texture has been used by the rendering context
+ * since the last call to sct_flush_textures().
+ */
+boolean
+sct_is_texture_used(struct surface_context_tracker *sct,
+ const struct pipe_context *context,
+ const struct pipe_texture *texture)
+{
+ const struct sct_context *ci = find_context_info(sct, context);
+ return find_texture(ci, texture);
+}
+
+
+/**
+ * To be called when the image contents of a texture are changed, such
+ * as for gl[Copy]TexSubImage().
+ * XXX this may not be needed
+ */
+void
+sct_update_texture(struct pipe_texture *tex)
+{
+
+}
+
+
+/**
+ * When a scene is flushed/rendered we can release the list of
+ * used textures.
+ */
+void
+sct_flush_textures(struct surface_context_tracker *sct,
+ struct pipe_context *context)
+{
+ struct sct_context *ci = find_context_info(sct, context);
+ struct texture_list *tl, *next;
+ uint i;
+
+ for (tl = ci->textures_used; tl; tl = next) {
+ next = tl->next;
+ pipe_texture_reference(&tl->texture, NULL);
+ FREE(tl);
+ }
+ ci->textures_used = NULL;
+
+ /* put the currently bound textures on the 'used' list */
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ add_texture_used(ci, ci->textures[i]);
+ }
+}
+
+
+
+void
+sct_destroy_context(struct surface_context_tracker *sct,
+ struct pipe_context *context)
+{
+ /* XXX should we require an unbinding first? */
+ {
+ struct sct_surface *si;
+ for (si = sct->surfaces; si; si = si->next) {
+ remove_context_from_surface(si, context);
+ }
+ }
+
+ /* remove context from context_info list */
+ {
+ struct sct_context *ci, *next, *prev = NULL;
+ for (ci = sct->contexts; ci; ci = next) {
+ next = ci->next;
+ if (ci->context == context) {
+ if (prev)
+ prev->next = ci->next;
+ else
+ sct->contexts = ci->next;
+ FREE(ci);
+ }
+ else {
+ prev = ci;
+ }
+ }
+ }
+
+}
+
+
+void
+sct_destroy_surface(struct surface_context_tracker *sct,
+ struct pipe_surface *surface)
+{
+ if (1) {
+ /* debug/sanity: no context should be bound to surface */
+ struct sct_context *ci;
+ uint i;
+ for (ci = sct->contexts; ci; ci = ci->next) {
+ for (i = 0; i < MAX_SURFACES; i++) {
+ assert(ci->surfaces[i] != surface);
+ }
+ }
+ }
+
+ /* remove surface from sct_surface list */
+ {
+ struct sct_surface *si, *next, *prev = NULL;
+ for (si = sct->surfaces; si; si = next) {
+ next = si->next;
+ if (si->surface == surface) {
+ /* unlink */
+ if (prev)
+ prev->next = si->next;
+ else
+ sct->surfaces = si->next;
+ FREE(si);
+ }
+ else {
+ prev = si;
+ }
+ }
+ }
+}
diff --git a/src/gallium/auxiliary/sct/sct.h b/src/gallium/auxiliary/sct/sct.h
new file mode 100644
index 0000000000..cf7c4d3bdf
--- /dev/null
+++ b/src/gallium/auxiliary/sct/sct.h
@@ -0,0 +1,123 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Surface/Context Tracking
+ *
+ * For some drivers, we need to monitor the binding between contexts and
+ * surfaces/textures.
+ * This code may evolve quite a bit...
+ */
+
+
+#ifndef SCT_H
+#define SCT_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_context;
+struct pipe_surface;
+
+struct sct_context;
+struct sct_surface;
+
+
+/**
+ * Per-device info, basically
+ */
+struct surface_context_tracker
+{
+ struct sct_context *contexts;
+ struct sct_surface *surfaces;
+};
+
+
+
+/**
+ * Simple linked list of contexts
+ */
+struct sct_context_list
+{
+ const struct pipe_context *context;
+ struct sct_context_list *next;
+};
+
+
+
+extern void
+sct_bind_surfaces(struct surface_context_tracker *sct,
+ struct pipe_context *context,
+ uint num_surf,
+ struct pipe_surface **surfaces);
+
+
+extern void
+sct_bind_texture(struct surface_context_tracker *sct,
+ struct pipe_context *context,
+ uint unit,
+ struct pipe_texture *texture);
+
+
+extern void
+sct_update_texture(struct pipe_texture *tex);
+
+
+extern boolean
+sct_is_texture_used(struct surface_context_tracker *sct,
+ const struct pipe_context *context,
+ const struct pipe_texture *texture);
+
+extern void
+sct_flush_textures(struct surface_context_tracker *sct,
+ struct pipe_context *context);
+
+
+extern const struct sct_context_list *
+sct_get_surface_contexts(struct surface_context_tracker *sct,
+ const struct pipe_surface *surf);
+
+
+extern void
+sct_destroy_context(struct surface_context_tracker *sct,
+ struct pipe_context *context);
+
+
+extern void
+sct_destroy_surface(struct surface_context_tracker *sct,
+ struct pipe_surface *surface);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SCT_H */
diff --git a/src/gallium/auxiliary/sct/usage.c b/src/gallium/auxiliary/sct/usage.c
new file mode 100644
index 0000000000..6227f19962
--- /dev/null
+++ b/src/gallium/auxiliary/sct/usage.c
@@ -0,0 +1,61 @@
+/* surface / context tracking */
+
+
+/*
+
+context A:
+ render to texture T
+
+context B:
+ texture from T
+
+-----------------------
+
+flush surface:
+ which contexts are bound to the surface?
+
+-----------------------
+
+glTexSubImage():
+ which contexts need to be flushed?
+
+ */
+
+
+/*
+
+in MakeCurrent():
+
+ call sct_bind_surfaces(context, list of surfaces) to update the
+ dependencies between context and surfaces
+
+
+in SurfaceFlush(), or whatever it is in D3D:
+
+ call sct_get_surface_contexts(surface) to get a list of contexts
+ which are currently bound to the surface.
+
+
+
+in BindTexture():
+
+ call sct_bind_texture(context, texture) to indicate that the texture
+ is used in the scene.
+
+
+in glTexSubImage() or RenderToTexture():
+
+ call sct_is_texture_used(context, texture) to determine if the texture
+ has been used in the scene, but the scene's not flushed. If TRUE is
+ returned it means the scene has to be rendered/flushed before the contents
+ of the texture can be changed.
+
+
+in psb_scene_flush/terminate():
+
+ call sct_flush_textures(context) to tell the SCT that the textures which
+ were used in the scene can be released.
+
+
+
+*/
diff --git a/src/gallium/auxiliary/tgsi/Makefile b/src/gallium/auxiliary/tgsi/Makefile
new file mode 100644
index 0000000000..5f0a580b09
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/Makefile
@@ -0,0 +1,22 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = tgsi
+
+C_SOURCES = \
+ tgsi_sanity.c \
+ tgsi_build.c \
+ tgsi_dump.c \
+ tgsi_exec.c \
+ tgsi_info.c \
+ tgsi_iterate.c \
+ tgsi_parse.c \
+ tgsi_ppc.c \
+ tgsi_scan.c \
+ tgsi_sse2.c \
+ tgsi_text.c \
+ tgsi_transform.c \
+ tgsi_ureg.c \
+ tgsi_util.c
+
+include ../../Makefile.template
diff --git a/src/gallium/auxiliary/tgsi/SConscript b/src/gallium/auxiliary/tgsi/SConscript
new file mode 100644
index 0000000000..b6bc2924f0
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/SConscript
@@ -0,0 +1,23 @@
+Import('*')
+
+tgsi = env.ConvenienceLibrary(
+ target = 'tgsi',
+ source = [
+ 'tgsi_build.c',
+ 'tgsi_dump.c',
+ 'tgsi_dump_c.c',
+ 'tgsi_exec.c',
+ 'tgsi_info.c',
+ 'tgsi_iterate.c',
+ 'tgsi_parse.c',
+ 'tgsi_sanity.c',
+ 'tgsi_scan.c',
+ 'tgsi_ppc.c',
+ 'tgsi_sse2.c',
+ 'tgsi_text.c',
+ 'tgsi_transform.c',
+ 'tgsi_ureg.c',
+ 'tgsi_util.c',
+ ])
+
+auxiliaries.insert(0, tgsi)
diff --git a/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt
new file mode 100644
index 0000000000..eb492076b7
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt
@@ -0,0 +1,1131 @@
+TGSI Instruction Specification
+==============================
+==============================
+
+
+1 Instruction Set Operations
+=============================
+
+
+1.1 GL_NV_vertex_program
+-------------------------
+
+
+1.1.1 ARL - Address Register Load
+
+ dst.x = floor(src.x)
+ dst.y = floor(src.y)
+ dst.z = floor(src.z)
+ dst.w = floor(src.w)
+
+
+1.1.2 MOV - Move
+
+ dst.x = src.x
+ dst.y = src.y
+ dst.z = src.z
+ dst.w = src.w
+
+
+1.1.3 LIT - Light Coefficients
+
+ dst.x = 1.0
+ dst.y = max(src.x, 0.0)
+ dst.z = (src.x > 0.0) ? pow(max(src.y, 0.0), clamp(src.w, -128.0, 128.0)) : 0.0
+ dst.w = 1.0
+
+
+1.1.4 RCP - Reciprocal
+
+ dst.x = 1.0 / src.x
+ dst.y = 1.0 / src.x
+ dst.z = 1.0 / src.x
+ dst.w = 1.0 / src.x
+
+
+1.1.5 RSQ - Reciprocal Square Root
+
+ dst.x = 1.0 / sqrt(abs(src.x))
+ dst.y = 1.0 / sqrt(abs(src.x))
+ dst.z = 1.0 / sqrt(abs(src.x))
+ dst.w = 1.0 / sqrt(abs(src.x))
+
+
+1.1.6 EXP - Approximate Exponential Base 2
+
+ dst.x = pow(2.0, floor(src.x))
+ dst.y = src.x - floor(src.x)
+ dst.z = pow(2.0, src.x)
+ dst.w = 1.0
+
+
+1.1.7 LOG - Approximate Logarithm Base 2
+
+ dst.x = floor(lg2(abs(src.x)))
+ dst.y = abs(src.x) / pow(2.0, floor(lg2(abs(src.x))))
+ dst.z = lg2(abs(src.x))
+ dst.w = 1.0
+
+
+1.1.8 MUL - Multiply
+
+ dst.x = src0.x * src1.x
+ dst.y = src0.y * src1.y
+ dst.z = src0.z * src1.z
+ dst.w = src0.w * src1.w
+
+
+1.1.9 ADD - Add
+
+ dst.x = src0.x + src1.x
+ dst.y = src0.y + src1.y
+ dst.z = src0.z + src1.z
+ dst.w = src0.w + src1.w
+
+
+1.1.10 DP3 - 3-component Dot Product
+
+ dst.x = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z
+ dst.y = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z
+ dst.z = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z
+ dst.w = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z
+
+
+1.1.11 DP4 - 4-component Dot Product
+
+ dst.x = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src0.w * src1.w
+ dst.y = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src0.w * src1.w
+ dst.z = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src0.w * src1.w
+ dst.w = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src0.w * src1.w
+
+
+1.1.12 DST - Distance Vector
+
+ dst.x = 1.0
+ dst.y = src0.y * src1.y
+ dst.z = src0.z
+ dst.w = src1.w
+
+
+1.1.13 MIN - Minimum
+
+ dst.x = min(src0.x, src1.x)
+ dst.y = min(src0.y, src1.y)
+ dst.z = min(src0.z, src1.z)
+ dst.w = min(src0.w, src1.w)
+
+
+1.1.14 MAX - Maximum
+
+ dst.x = max(src0.x, src1.x)
+ dst.y = max(src0.y, src1.y)
+ dst.z = max(src0.z, src1.z)
+ dst.w = max(src0.w, src1.w)
+
+
+1.1.15 SLT - Set On Less Than
+
+ dst.x = (src0.x < src1.x) ? 1.0 : 0.0
+ dst.y = (src0.y < src1.y) ? 1.0 : 0.0
+ dst.z = (src0.z < src1.z) ? 1.0 : 0.0
+ dst.w = (src0.w < src1.w) ? 1.0 : 0.0
+
+
+1.1.16 SGE - Set On Greater Equal Than
+
+ dst.x = (src0.x >= src1.x) ? 1.0 : 0.0
+ dst.y = (src0.y >= src1.y) ? 1.0 : 0.0
+ dst.z = (src0.z >= src1.z) ? 1.0 : 0.0
+ dst.w = (src0.w >= src1.w) ? 1.0 : 0.0
+
+
+1.1.17 MAD - Multiply And Add
+
+ dst.x = src0.x * src1.x + src2.x
+ dst.y = src0.y * src1.y + src2.y
+ dst.z = src0.z * src1.z + src2.z
+ dst.w = src0.w * src1.w + src2.w
+
+
+1.2 GL_ATI_fragment_shader
+---------------------------
+
+
+1.2.1 SUB - Subtract
+
+ dst.x = src0.x - src1.x
+ dst.y = src0.y - src1.y
+ dst.z = src0.z - src1.z
+ dst.w = src0.w - src1.w
+
+
+1.2.2 DOT3 - 3-component Dot Product
+
+ Alias for DP3.
+
+
+1.2.3 DOT4 - 4-component Dot Product
+
+ Alias for DP4.
+
+
+1.2.4 LERP - Linear Interpolate
+
+ dst.x = src0.x * (src1.x - src2.x) + src2.x
+ dst.y = src0.y * (src1.y - src2.y) + src2.y
+ dst.z = src0.z * (src1.z - src2.z) + src2.z
+ dst.w = src0.w * (src1.w - src2.w) + src2.w
+
+
+1.2.5 CND - Condition
+
+ dst.x = (src2.x > 0.5) ? src0.x : src1.x
+ dst.y = (src2.y > 0.5) ? src0.y : src1.y
+ dst.z = (src2.z > 0.5) ? src0.z : src1.z
+ dst.w = (src2.w > 0.5) ? src0.w : src1.w
+
+
+1.2.6 CND0 - Condition Zero
+
+ Removed. Use (CMP src2, src1, src0) instead.
+
+1.2.7 DOT2ADD - 2-component Dot Product And Add
+
+ dst.x = src0.x * src1.x + src0.y * src1.y + src2.x
+ dst.y = src0.x * src1.x + src0.y * src1.y + src2.x
+ dst.z = src0.x * src1.x + src0.y * src1.y + src2.x
+ dst.w = src0.x * src1.x + src0.y * src1.y + src2.x
+
+
+1.3 GL_EXT_vertex_shader
+-------------------------
+
+
+1.3.1 INDEX - Array Lookup
+
+ Considered for removal from language.
+
+
+1.3.2 NEGATE - Negate
+
+ Considered for removal from language.
+
+
+1.3.3 MADD - Multiply And Add
+
+ Alias for MAD.
+
+
+1.3.4 FRAC - Fraction
+
+ dst.x = src.x - floor(src.x)
+ dst.y = src.y - floor(src.y)
+ dst.z = src.z - floor(src.z)
+ dst.w = src.w - floor(src.w)
+
+
+1.3.5 SETGE - Set On Greater Equal
+
+ Alias for SGE.
+
+
+1.3.6 SETLT - Set On Less Than
+
+ Alias for SLT.
+
+
+1.3.7 CLAMP - Clamp
+
+ dst.x = clamp(src0.x, src1.x, src2.x)
+ dst.y = clamp(src0.y, src1.y, src2.y)
+ dst.z = clamp(src0.z, src1.z, src2.z)
+ dst.w = clamp(src0.w, src1.w, src2.w)
+
+
+1.3.8 FLOOR - Floor
+
+ dst.x = floor(src.x)
+ dst.y = floor(src.y)
+ dst.z = floor(src.z)
+ dst.w = floor(src.w)
+
+
+1.3.9 ROUND - Round
+
+ dst.x = round(src.x)
+ dst.y = round(src.y)
+ dst.z = round(src.z)
+ dst.w = round(src.w)
+
+
+1.3.10 EXPBASE2 - Exponential Base 2
+
+ dst.x = pow(2.0, src.x)
+ dst.y = pow(2.0, src.x)
+ dst.z = pow(2.0, src.x)
+ dst.w = pow(2.0, src.x)
+
+
+1.3.11 LOGBASE2 - Logarithm Base 2
+
+ dst.x = lg2(src.x)
+ dst.y = lg2(src.x)
+ dst.z = lg2(src.x)
+ dst.w = lg2(src.x)
+
+
+1.3.12 POWER - Power
+
+ dst.x = pow(src0.x, src1.x)
+ dst.y = pow(src0.x, src1.x)
+ dst.z = pow(src0.x, src1.x)
+ dst.w = pow(src0.x, src1.x)
+
+
+1.3.13 RECIP - Reciprocal
+
+ Alias for RCP.
+
+
+1.3.14 RECIPSQRT - Reciprocal Square Root
+
+ Alias for RSQ.
+
+
+1.3.15 CROSSPRODUCT - Cross Product
+
+ dst.x = src0.y * src1.z - src1.y * src0.z
+ dst.y = src0.z * src1.x - src1.z * src0.x
+ dst.z = src0.x * src1.y - src1.x * src0.y
+ dst.w = 1.0
+
+
+1.3.16 MULTIPLYMATRIX - Multiply Matrix
+
+ Considered for removal from language.
+
+
+1.4 GL_NV_vertex_program1_1
+----------------------------
+
+
+1.4.1 ABS - Absolute
+
+ dst.x = abs(src.x)
+ dst.y = abs(src.y)
+ dst.z = abs(src.z)
+ dst.w = abs(src.w)
+
+
+1.4.2 RCC - Reciprocal Clamped
+
+ dst.x = (1.0 / src.x) > 0.0 ? clamp(1.0 / src.x, 5.42101e-020, 1.884467e+019) : clamp(1.0 / src.x, -1.884467e+019, -5.42101e-020)
+ dst.y = (1.0 / src.x) > 0.0 ? clamp(1.0 / src.x, 5.42101e-020, 1.884467e+019) : clamp(1.0 / src.x, -1.884467e+019, -5.42101e-020)
+ dst.z = (1.0 / src.x) > 0.0 ? clamp(1.0 / src.x, 5.42101e-020, 1.884467e+019) : clamp(1.0 / src.x, -1.884467e+019, -5.42101e-020)
+ dst.w = (1.0 / src.x) > 0.0 ? clamp(1.0 / src.x, 5.42101e-020, 1.884467e+019) : clamp(1.0 / src.x, -1.884467e+019, -5.42101e-020)
+
+
+1.4.3 DPH - Homogeneous Dot Product
+
+ dst.x = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w
+ dst.y = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w
+ dst.z = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w
+ dst.w = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w
+
+
+1.5 GL_NV_fragment_program
+---------------------------
+
+
+1.5.1 COS - Cosine
+
+ dst.x = cos(src.x)
+ dst.y = cos(src.x)
+ dst.z = cos(src.x)
+ dst.w = cos(src.w)
+
+
+1.5.2 DDX - Derivative Relative To X
+
+ dst.x = partialx(src.x)
+ dst.y = partialx(src.y)
+ dst.z = partialx(src.z)
+ dst.w = partialx(src.w)
+
+
+1.5.3 DDY - Derivative Relative To Y
+
+ dst.x = partialy(src.x)
+ dst.y = partialy(src.y)
+ dst.z = partialy(src.z)
+ dst.w = partialy(src.w)
+
+
+1.5.4 EX2 - Exponential Base 2
+
+ Alias for EXPBASE2.
+
+
+1.5.5 FLR - Floor
+
+ Alias for FLOOR.
+
+
+1.5.6 FRC - Fraction
+
+ Alias for FRAC.
+
+
+1.5.7 KILP - Predicated Discard
+
+ discard
+
+
+1.5.8 LG2 - Logarithm Base 2
+
+ Alias for LOGBASE2.
+
+
+1.5.9 LRP - Linear Interpolate
+
+ Alias for LERP.
+
+
+1.5.10 PK2H - Pack Two 16-bit Floats
+
+ TBD
+
+
+1.5.11 PK2US - Pack Two Unsigned 16-bit Scalars
+
+ TBD
+
+
+1.5.12 PK4B - Pack Four Signed 8-bit Scalars
+
+ TBD
+
+
+1.5.13 PK4UB - Pack Four Unsigned 8-bit Scalars
+
+ TBD
+
+
+1.5.14 POW - Power
+
+ Alias for POWER.
+
+
+1.5.15 RFL - Reflection Vector
+
+ dst.x = 2.0 * (src0.x * src1.x + src0.y * src1.y + src0.z * src1.z) / (src0.x * src0.x + src0.y * src0.y + src0.z * src0.z) * src0.x - src1.x
+ dst.y = 2.0 * (src0.x * src1.x + src0.y * src1.y + src0.z * src1.z) / (src0.x * src0.x + src0.y * src0.y + src0.z * src0.z) * src0.y - src1.y
+ dst.z = 2.0 * (src0.x * src1.x + src0.y * src1.y + src0.z * src1.z) / (src0.x * src0.x + src0.y * src0.y + src0.z * src0.z) * src0.z - src1.z
+ dst.w = 1.0
+
+
+1.5.16 SEQ - Set On Equal
+
+ dst.x = (src0.x == src1.x) ? 1.0 : 0.0
+ dst.y = (src0.y == src1.y) ? 1.0 : 0.0
+ dst.z = (src0.z == src1.z) ? 1.0 : 0.0
+ dst.w = (src0.w == src1.w) ? 1.0 : 0.0
+
+
+1.5.17 SFL - Set On False
+
+ dst.x = 0.0
+ dst.y = 0.0
+ dst.z = 0.0
+ dst.w = 0.0
+
+
+1.5.18 SGT - Set On Greater Than
+
+ dst.x = (src0.x > src1.x) ? 1.0 : 0.0
+ dst.y = (src0.y > src1.y) ? 1.0 : 0.0
+ dst.z = (src0.z > src1.z) ? 1.0 : 0.0
+ dst.w = (src0.w > src1.w) ? 1.0 : 0.0
+
+
+1.5.19 SIN - Sine
+
+ dst.x = sin(src.x)
+ dst.y = sin(src.x)
+ dst.z = sin(src.x)
+ dst.w = sin(src.w)
+
+
+1.5.20 SLE - Set On Less Equal Than
+
+ dst.x = (src0.x <= src1.x) ? 1.0 : 0.0
+ dst.y = (src0.y <= src1.y) ? 1.0 : 0.0
+ dst.z = (src0.z <= src1.z) ? 1.0 : 0.0
+ dst.w = (src0.w <= src1.w) ? 1.0 : 0.0
+
+
+1.5.21 SNE - Set On Not Equal
+
+ dst.x = (src0.x != src1.x) ? 1.0 : 0.0
+ dst.y = (src0.y != src1.y) ? 1.0 : 0.0
+ dst.z = (src0.z != src1.z) ? 1.0 : 0.0
+ dst.w = (src0.w != src1.w) ? 1.0 : 0.0
+
+
+1.5.22 STR - Set On True
+
+ dst.x = 1.0
+ dst.y = 1.0
+ dst.z = 1.0
+ dst.w = 1.0
+
+
+1.5.23 TEX - Texture Lookup
+
+ TBD
+
+
+1.5.24 TXD - Texture Lookup with Derivatives
+
+ TBD
+
+
+1.5.25 TXP - Projective Texture Lookup
+
+ TBD
+
+
+1.5.26 UP2H - Unpack Two 16-Bit Floats
+
+ TBD
+
+
+1.5.27 UP2US - Unpack Two Unsigned 16-Bit Scalars
+
+ TBD
+
+
+1.5.28 UP4B - Unpack Four Signed 8-Bit Values
+
+ TBD
+
+
+1.5.29 UP4UB - Unpack Four Unsigned 8-Bit Scalars
+
+ TBD
+
+
+1.5.30 X2D - 2D Coordinate Transformation
+
+ dst.x = src0.x + src1.x * src2.x + src1.y * src2.y
+ dst.y = src0.y + src1.x * src2.z + src1.y * src2.w
+ dst.z = src0.x + src1.x * src2.x + src1.y * src2.y
+ dst.w = src0.y + src1.x * src2.z + src1.y * src2.w
+
+
+1.6 GL_NV_vertex_program2
+--------------------------
+
+
+1.6.1 ARA - Address Register Add
+
+ TBD
+
+
+1.6.2 ARR - Address Register Load With Round
+
+ dst.x = round(src.x)
+ dst.y = round(src.y)
+ dst.z = round(src.z)
+ dst.w = round(src.w)
+
+
+1.6.3 BRA - Branch
+
+ pc = target
+
+
+1.6.4 CAL - Subroutine Call
+
+ push(pc)
+ pc = target
+
+
+1.6.5 RET - Subroutine Call Return
+
+ pc = pop()
+
+
+1.6.6 SSG - Set Sign
+
+ dst.x = (src.x > 0.0) ? 1.0 : (src.x < 0.0) ? -1.0 : 0.0
+ dst.y = (src.y > 0.0) ? 1.0 : (src.y < 0.0) ? -1.0 : 0.0
+ dst.z = (src.z > 0.0) ? 1.0 : (src.z < 0.0) ? -1.0 : 0.0
+ dst.w = (src.w > 0.0) ? 1.0 : (src.w < 0.0) ? -1.0 : 0.0
+
+
+1.7 GL_ARB_vertex_program
+--------------------------
+
+
+1.7.1 SWZ - Extended Swizzle
+
+ dst.x = src.x
+ dst.y = src.y
+ dst.z = src.z
+ dst.w = src.w
+
+
+1.7.2 XPD - Cross Product
+
+ Alias for CROSSPRODUCT.
+
+
+1.8 GL_ARB_fragment_program
+----------------------------
+
+
+1.8.1 CMP - Compare
+
+ dst.x = (src0.x < 0.0) ? src1.x : src2.x
+ dst.y = (src0.y < 0.0) ? src1.y : src2.y
+ dst.z = (src0.z < 0.0) ? src1.z : src2.z
+ dst.w = (src0.w < 0.0) ? src1.w : src2.w
+
+
+1.8.2 KIL - Conditional Discard
+
+ if (src.x < 0.0 || src.y < 0.0 || src.z < 0.0 || src.w < 0.0)
+ discard
+ endif
+
+
+1.8.3 SCS - Sine Cosine
+
+ dst.x = cos(src.x)
+ dst.y = sin(src.x)
+ dst.z = 0.0
+ dst.y = 1.0
+
+
+1.8.4 TXB - Texture Lookup With Bias
+
+ TBD
+
+
+1.9 GL_NV_fragment_program2
+----------------------------
+
+
+1.9.1 NRM - 3-component Vector Normalise
+
+ dst.x = src.x / (src.x * src.x + src.y * src.y + src.z * src.z)
+ dst.y = src.y / (src.x * src.x + src.y * src.y + src.z * src.z)
+ dst.z = src.z / (src.x * src.x + src.y * src.y + src.z * src.z)
+ dst.w = 1.0
+
+
+1.9.2 DIV - Divide
+
+ dst.x = src0.x / src1.x
+ dst.y = src0.y / src1.y
+ dst.z = src0.z / src1.z
+ dst.w = src0.w / src1.w
+
+
+1.9.3 DP2 - 2-component Dot Product
+
+ dst.x = src0.x * src1.x + src0.y * src1.y
+ dst.y = src0.x * src1.x + src0.y * src1.y
+ dst.z = src0.x * src1.x + src0.y * src1.y
+ dst.w = src0.x * src1.x + src0.y * src1.y
+
+
+1.9.4 DP2A - 2-component Dot Product And Add
+
+ Alias for DOT2ADD.
+
+
+1.9.5 TXL - Texture Lookup With LOD
+
+ TBD
+
+
+1.9.6 BRK - Break
+
+ TBD
+
+
+1.9.7 IF - If
+
+ TBD
+
+
+1.9.8 BGNFOR - Begin a For-Loop
+
+ dst.x = floor(src.x)
+ dst.y = floor(src.y)
+ dst.z = floor(src.z)
+
+ if (dst.y <= 0)
+ pc = [matching ENDFOR] + 1
+ endif
+
+ Note: The destination must be a loop register.
+ The source must be a constant register.
+
+
+1.9.9 REP - Repeat
+
+ TBD
+
+
+1.9.10 ELSE - Else
+
+ TBD
+
+
+1.9.11 ENDIF - End If
+
+ TBD
+
+
+1.9.12 ENDFOR - End a For-Loop
+
+ dst.x = dst.x + dst.z
+ dst.y = dst.y - 1.0
+
+ if (dst.y > 0)
+ pc = [matching BGNFOR instruction] + 1
+ endif
+
+ Note: The destination must be a loop register.
+
+
+1.9.13 ENDREP - End Repeat
+
+ TBD
+
+
+1.10 GL_NV_vertex_program3
+---------------------------
+
+
+1.10.1 PUSHA - Push Address Register On Stack
+
+ push(src.x)
+ push(src.y)
+ push(src.z)
+ push(src.w)
+
+
+1.10.2 POPA - Pop Address Register From Stack
+
+ dst.w = pop()
+ dst.z = pop()
+ dst.y = pop()
+ dst.x = pop()
+
+
+1.11 GL_NV_gpu_program4
+------------------------
+
+
+1.11.1 CEIL - Ceiling
+
+ dst.x = ceil(src.x)
+ dst.y = ceil(src.y)
+ dst.z = ceil(src.z)
+ dst.w = ceil(src.w)
+
+
+1.11.2 I2F - Integer To Float
+
+ dst.x = (float) src.x
+ dst.y = (float) src.y
+ dst.z = (float) src.z
+ dst.w = (float) src.w
+
+
+1.11.3 NOT - Bitwise Not
+
+ dst.x = ~src.x
+ dst.y = ~src.y
+ dst.z = ~src.z
+ dst.w = ~src.w
+
+
+1.11.4 TRUNC - Truncate
+
+ dst.x = trunc(src.x)
+ dst.y = trunc(src.y)
+ dst.z = trunc(src.z)
+ dst.w = trunc(src.w)
+
+
+1.11.5 SHL - Shift Left
+
+ dst.x = src0.x << src1.x
+ dst.y = src0.y << src1.x
+ dst.z = src0.z << src1.x
+ dst.w = src0.w << src1.x
+
+
+1.11.6 SHR - Shift Right
+
+ dst.x = src0.x >> src1.x
+ dst.y = src0.y >> src1.x
+ dst.z = src0.z >> src1.x
+ dst.w = src0.w >> src1.x
+
+
+1.11.7 AND - Bitwise And
+
+ dst.x = src0.x & src1.x
+ dst.y = src0.y & src1.y
+ dst.z = src0.z & src1.z
+ dst.w = src0.w & src1.w
+
+
+1.11.8 OR - Bitwise Or
+
+ dst.x = src0.x | src1.x
+ dst.y = src0.y | src1.y
+ dst.z = src0.z | src1.z
+ dst.w = src0.w | src1.w
+
+
+1.11.9 MOD - Modulus
+
+ dst.x = src0.x % src1.x
+ dst.y = src0.y % src1.y
+ dst.z = src0.z % src1.z
+ dst.w = src0.w % src1.w
+
+
+1.11.10 XOR - Bitwise Xor
+
+ dst.x = src0.x ^ src1.x
+ dst.y = src0.y ^ src1.y
+ dst.z = src0.z ^ src1.z
+ dst.w = src0.w ^ src1.w
+
+
+1.11.11 SAD - Sum Of Absolute Differences
+
+ dst.x = abs(src0.x - src1.x) + src2.x
+ dst.y = abs(src0.y - src1.y) + src2.y
+ dst.z = abs(src0.z - src1.z) + src2.z
+ dst.w = abs(src0.w - src1.w) + src2.w
+
+
+1.11.12 TXF - Texel Fetch
+
+ TBD
+
+
+1.11.13 TXQ - Texture Size Query
+
+ TBD
+
+
+1.11.14 CONT - Continue
+
+ TBD
+
+
+1.12 GL_NV_geometry_program4
+-----------------------------
+
+
+1.12.1 EMIT - Emit
+
+ TBD
+
+
+1.12.2 ENDPRIM - End Primitive
+
+ TBD
+
+
+1.13 GLSL
+----------
+
+
+1.13.1 BGNLOOP - Begin a Loop
+
+ TBD
+
+
+1.13.2 BGNSUB - Begin Subroutine
+
+ TBD
+
+
+1.13.3 ENDLOOP - End a Loop
+
+ TBD
+
+
+1.13.4 ENDSUB - End Subroutine
+
+ TBD
+
+
+1.13.5 INT - Truncate
+
+ Alias for TRUNC.
+
+
+1.13.6 NOISE1 - 1D Noise
+
+ TBD
+
+
+1.13.7 NOISE2 - 2D Noise
+
+ TBD
+
+
+1.13.8 NOISE3 - 3D Noise
+
+ TBD
+
+
+1.13.9 NOISE4 - 4D Noise
+
+ TBD
+
+
+1.13.10 NOP - No Operation
+
+ Do nothing.
+
+
+1.14 ps_1_1
+------------
+
+
+1.14.1 TEXKILL - Conditional Discard
+
+ Alias for KIL.
+
+
+1.15 ps_1_4
+------------
+
+
+1.15.1 TEXLD - Texture Lookup
+
+ Alias for TEX.
+
+
+1.16 ps_2_0
+------------
+
+
+1.16.1 M4X4 - Multiply Matrix
+
+ Alias for MULTIPLYMATRIX.
+
+
+1.16.2 M4X3 - Multiply Matrix
+
+ Considered for removal from language.
+
+
+1.16.3 M3X4 - Multiply Matrix
+
+ Considered for removal from language.
+
+
+1.16.4 M3X3 - Multiply Matrix
+
+ Considered for removal from language.
+
+
+1.16.5 M3X2 - Multiply Matrix
+
+ Considered for removal from language.
+
+
+1.16.6 CRS - Cross Product
+
+ Alias for XPD.
+
+
+1.16.7 NRM4 - 4-component Vector Normalise
+
+ dst.x = src.x / (src.x * src.x + src.y * src.y + src.z * src.z + src.w * src.w)
+ dst.y = src.y / (src.x * src.x + src.y * src.y + src.z * src.z + src.w * src.w)
+ dst.z = src.z / (src.x * src.x + src.y * src.y + src.z * src.z + src.w * src.w)
+ dst.w = src.w / (src.x * src.x + src.y * src.y + src.z * src.z + src.w * src.w)
+
+
+1.16.8 SINCOS - Sine Cosine
+
+ Alias for SCS.
+
+
+1.16.9 TEXLDB - Texture Lookup With Bias
+
+ Alias for TXB.
+
+
+1.16.10 DP2ADD - 2-component Dot Product And Add
+
+ Alias for DP2A.
+
+
+1.17 ps_2_x
+------------
+
+
+1.17.1 CALL - Subroutine Call
+
+ Alias for CAL.
+
+
+1.17.2 CALLNZ - Subroutine Call If Not Zero
+
+ TBD
+
+
+1.17.3 IFC - If
+
+ TBD
+
+
+1.17.4 BREAK - Break
+
+ Alias for BRK.
+
+
+1.17.5 BREAKC - Break Conditional
+
+ TBD
+
+
+1.17.6 DSX - Derivative Relative To X
+
+ Alias for DDX.
+
+
+1.17.7 DSY - Derivative Relative To Y
+
+ Alias for DDY.
+
+
+1.17.8 TEXLDD - Texture Lookup with Derivatives
+
+ Alias for TXD.
+
+
+1.18 vs_1_1
+------------
+
+
+1.18.1 EXPP - Approximate Exponential Base 2
+
+ Use EXP. See also 1.19.3.
+
+
+1.18.2 LOGP - Logarithm Base 2
+
+ Use LOG. See also 1.19.4.
+
+
+1.19 vs_2_0
+------------
+
+
+1.19.1 SGN - Set Sign
+
+ Alias for SSG.
+
+
+1.19.2 MOVA - Move Address Register
+
+ Alias for ARR.
+
+
+1.19.3 EXPP - Approximate Exponential Base 2
+
+ Use EX2.
+
+
+1.19.4 LOGP - Logarithm Base 2
+
+ Use LG2.
+
+
+2 Explanation of symbols used
+==============================
+
+
+2.1 Functions
+--------------
+
+
+ abs(x) Absolute value of x.
+ |x|
+ (x < 0.0) ? -x : x
+
+ ceil(x) Ceiling of x.
+
+ clamp(x,y,z) Clamp x between y and z.
+ (x < y) ? y : (x > z) ? z : x
+
+ cos(x) Cosine of x.
+
+ floor(x) Floor of x.
+
+ lg2(x) Logarithm base 2 of x.
+
+ max(x,y) Maximum of x and y.
+ (x > y) ? x : y
+
+ min(x,y) Minimum of x and y.
+ (x < y) ? x : y
+
+ partialx(x) Derivative of x relative to fragment's X.
+
+ partialy(x) Derivative of x relative to fragment's Y.
+
+ pop() Pop from stack.
+
+ pow(x,y) Raise x to power of y.
+
+ push(x) Push x on stack.
+
+ round(x) Round x.
+
+ sin(x) Sine of x.
+
+ sqrt(x) Square root of x.
+
+ trunc(x) Truncate x.
+
+
+2.2 Keywords
+-------------
+
+
+ discard Discard fragment.
+
+ dst First destination register.
+
+ dst0 First destination register.
+
+ pc Program counter.
+
+ src First source register.
+
+ src0 First source register.
+
+ src1 Second source register.
+
+ src2 Third source register.
+
+ target Label of target instruction.
+
diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c
new file mode 100644
index 0000000000..e0cfc54420
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_build.c
@@ -0,0 +1,1368 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi_build.h"
+#include "tgsi_parse.h"
+
+/*
+ * version
+ */
+
+struct tgsi_version
+tgsi_build_version( void )
+{
+ struct tgsi_version version;
+
+ version.MajorVersion = 1;
+ version.MinorVersion = 1;
+ version.Padding = 0;
+
+ return version;
+}
+
+/*
+ * header
+ */
+
+struct tgsi_header
+tgsi_build_header( void )
+{
+ struct tgsi_header header;
+
+ header.HeaderSize = 1;
+ header.BodySize = 0;
+
+ return header;
+}
+
+static void
+header_headersize_grow( struct tgsi_header *header )
+{
+ assert( header->HeaderSize < 0xFF );
+ assert( header->BodySize == 0 );
+
+ header->HeaderSize++;
+}
+
+static void
+header_bodysize_grow( struct tgsi_header *header )
+{
+ assert( header->BodySize < 0xFFFFFF );
+
+ header->BodySize++;
+}
+
+struct tgsi_processor
+tgsi_default_processor( void )
+{
+ struct tgsi_processor processor;
+
+ processor.Processor = TGSI_PROCESSOR_FRAGMENT;
+ processor.Padding = 0;
+
+ return processor;
+}
+
+struct tgsi_processor
+tgsi_build_processor(
+ unsigned type,
+ struct tgsi_header *header )
+{
+ struct tgsi_processor processor;
+
+ processor = tgsi_default_processor();
+ processor.Processor = type;
+
+ header_headersize_grow( header );
+
+ return processor;
+}
+
+/*
+ * declaration
+ */
+
+struct tgsi_declaration
+tgsi_default_declaration( void )
+{
+ struct tgsi_declaration declaration;
+
+ declaration.Type = TGSI_TOKEN_TYPE_DECLARATION;
+ declaration.NrTokens = 1;
+ declaration.File = TGSI_FILE_NULL;
+ declaration.UsageMask = TGSI_WRITEMASK_XYZW;
+ declaration.Interpolate = TGSI_INTERPOLATE_CONSTANT;
+ declaration.Semantic = 0;
+ declaration.Centroid = 0;
+ declaration.Invariant = 0;
+ declaration.Padding = 0;
+ declaration.Extended = 0;
+
+ return declaration;
+}
+
+struct tgsi_declaration
+tgsi_build_declaration(
+ unsigned file,
+ unsigned usage_mask,
+ unsigned interpolate,
+ unsigned semantic,
+ unsigned centroid,
+ unsigned invariant,
+ struct tgsi_header *header )
+{
+ struct tgsi_declaration declaration;
+
+ assert( file < TGSI_FILE_COUNT );
+ assert( interpolate < TGSI_INTERPOLATE_COUNT );
+
+ declaration = tgsi_default_declaration();
+ declaration.File = file;
+ declaration.UsageMask = usage_mask;
+ declaration.Interpolate = interpolate;
+ declaration.Semantic = semantic;
+ declaration.Centroid = centroid;
+ declaration.Invariant = invariant;
+
+ header_bodysize_grow( header );
+
+ return declaration;
+}
+
+static void
+declaration_grow(
+ struct tgsi_declaration *declaration,
+ struct tgsi_header *header )
+{
+ assert( declaration->NrTokens < 0xFF );
+
+ declaration->NrTokens++;
+
+ header_bodysize_grow( header );
+}
+
+struct tgsi_full_declaration
+tgsi_default_full_declaration( void )
+{
+ struct tgsi_full_declaration full_declaration;
+
+ full_declaration.Declaration = tgsi_default_declaration();
+ full_declaration.DeclarationRange = tgsi_default_declaration_range();
+ full_declaration.Semantic = tgsi_default_declaration_semantic();
+
+ return full_declaration;
+}
+
+unsigned
+tgsi_build_full_declaration(
+ const struct tgsi_full_declaration *full_decl,
+ struct tgsi_token *tokens,
+ struct tgsi_header *header,
+ unsigned maxsize )
+{
+ unsigned size = 0;
+ struct tgsi_declaration *declaration;
+ struct tgsi_declaration_range *dr;
+
+ if( maxsize <= size )
+ return 0;
+ declaration = (struct tgsi_declaration *) &tokens[size];
+ size++;
+
+ *declaration = tgsi_build_declaration(
+ full_decl->Declaration.File,
+ full_decl->Declaration.UsageMask,
+ full_decl->Declaration.Interpolate,
+ full_decl->Declaration.Semantic,
+ full_decl->Declaration.Centroid,
+ full_decl->Declaration.Invariant,
+ header );
+
+ if (maxsize <= size)
+ return 0;
+ dr = (struct tgsi_declaration_range *) &tokens[size];
+ size++;
+
+ *dr = tgsi_build_declaration_range(
+ full_decl->DeclarationRange.First,
+ full_decl->DeclarationRange.Last,
+ declaration,
+ header );
+
+ if( full_decl->Declaration.Semantic ) {
+ struct tgsi_declaration_semantic *ds;
+
+ if( maxsize <= size )
+ return 0;
+ ds = (struct tgsi_declaration_semantic *) &tokens[size];
+ size++;
+
+ *ds = tgsi_build_declaration_semantic(
+ full_decl->Semantic.SemanticName,
+ full_decl->Semantic.SemanticIndex,
+ declaration,
+ header );
+ }
+
+ return size;
+}
+
+struct tgsi_declaration_range
+tgsi_default_declaration_range( void )
+{
+ struct tgsi_declaration_range dr;
+
+ dr.First = 0;
+ dr.Last = 0;
+
+ return dr;
+}
+
+struct tgsi_declaration_range
+tgsi_build_declaration_range(
+ unsigned first,
+ unsigned last,
+ struct tgsi_declaration *declaration,
+ struct tgsi_header *header )
+{
+ struct tgsi_declaration_range declaration_range;
+
+ assert( last >= first );
+ assert( last <= 0xFFFF );
+
+ declaration_range = tgsi_default_declaration_range();
+ declaration_range.First = first;
+ declaration_range.Last = last;
+
+ declaration_grow( declaration, header );
+
+ return declaration_range;
+}
+
+struct tgsi_declaration_semantic
+tgsi_default_declaration_semantic( void )
+{
+ struct tgsi_declaration_semantic ds;
+
+ ds.SemanticName = TGSI_SEMANTIC_POSITION;
+ ds.SemanticIndex = 0;
+ ds.Padding = 0;
+
+ return ds;
+}
+
+struct tgsi_declaration_semantic
+tgsi_build_declaration_semantic(
+ unsigned semantic_name,
+ unsigned semantic_index,
+ struct tgsi_declaration *declaration,
+ struct tgsi_header *header )
+{
+ struct tgsi_declaration_semantic ds;
+
+ assert( semantic_name <= TGSI_SEMANTIC_COUNT );
+ assert( semantic_index <= 0xFFFF );
+
+ ds = tgsi_default_declaration_semantic();
+ ds.SemanticName = semantic_name;
+ ds.SemanticIndex = semantic_index;
+
+ declaration_grow( declaration, header );
+
+ return ds;
+}
+
+/*
+ * immediate
+ */
+
+struct tgsi_immediate
+tgsi_default_immediate( void )
+{
+ struct tgsi_immediate immediate;
+
+ immediate.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
+ immediate.NrTokens = 1;
+ immediate.DataType = TGSI_IMM_FLOAT32;
+ immediate.Padding = 0;
+ immediate.Extended = 0;
+
+ return immediate;
+}
+
+struct tgsi_immediate
+tgsi_build_immediate(
+ struct tgsi_header *header )
+{
+ struct tgsi_immediate immediate;
+
+ immediate = tgsi_default_immediate();
+
+ header_bodysize_grow( header );
+
+ return immediate;
+}
+
+struct tgsi_full_immediate
+tgsi_default_full_immediate( void )
+{
+ struct tgsi_full_immediate fullimm;
+
+ fullimm.Immediate = tgsi_default_immediate();
+ fullimm.u[0].Float = 0.0f;
+ fullimm.u[1].Float = 0.0f;
+ fullimm.u[2].Float = 0.0f;
+ fullimm.u[3].Float = 0.0f;
+
+ return fullimm;
+}
+
+static void
+immediate_grow(
+ struct tgsi_immediate *immediate,
+ struct tgsi_header *header )
+{
+ assert( immediate->NrTokens < 0xFF );
+
+ immediate->NrTokens++;
+
+ header_bodysize_grow( header );
+}
+
+union tgsi_immediate_data
+tgsi_build_immediate_float32(
+ float value,
+ struct tgsi_immediate *immediate,
+ struct tgsi_header *header )
+{
+ union tgsi_immediate_data immediate_data;
+
+ immediate_data.Float = value;
+
+ immediate_grow( immediate, header );
+
+ return immediate_data;
+}
+
+unsigned
+tgsi_build_full_immediate(
+ const struct tgsi_full_immediate *full_imm,
+ struct tgsi_token *tokens,
+ struct tgsi_header *header,
+ unsigned maxsize )
+{
+ unsigned size = 0, i;
+ struct tgsi_immediate *immediate;
+
+ if( maxsize <= size )
+ return 0;
+ immediate = (struct tgsi_immediate *) &tokens[size];
+ size++;
+
+ *immediate = tgsi_build_immediate( header );
+
+ assert( full_imm->Immediate.NrTokens <= 4 + 1 );
+
+ for( i = 0; i < full_imm->Immediate.NrTokens - 1; i++ ) {
+ union tgsi_immediate_data *data;
+
+ if( maxsize <= size )
+ return 0;
+ data = (union tgsi_immediate_data *) &tokens[size];
+ size++;
+
+ *data = tgsi_build_immediate_float32(
+ full_imm->u[i].Float,
+ immediate,
+ header );
+ }
+
+ return size;
+}
+
+/*
+ * instruction
+ */
+
+struct tgsi_instruction
+tgsi_default_instruction( void )
+{
+ struct tgsi_instruction instruction;
+
+ instruction.Type = TGSI_TOKEN_TYPE_INSTRUCTION;
+ instruction.NrTokens = 1;
+ instruction.Opcode = TGSI_OPCODE_MOV;
+ instruction.Saturate = TGSI_SAT_NONE;
+ instruction.NumDstRegs = 1;
+ instruction.NumSrcRegs = 1;
+ instruction.Padding = 0;
+ instruction.Extended = 0;
+
+ return instruction;
+}
+
+struct tgsi_instruction
+tgsi_build_instruction(
+ unsigned opcode,
+ unsigned saturate,
+ unsigned num_dst_regs,
+ unsigned num_src_regs,
+ struct tgsi_header *header )
+{
+ struct tgsi_instruction instruction;
+
+ assert (opcode <= TGSI_OPCODE_LAST);
+ assert (saturate <= TGSI_SAT_MINUS_PLUS_ONE);
+ assert (num_dst_regs <= 3);
+ assert (num_src_regs <= 15);
+
+ instruction = tgsi_default_instruction();
+ instruction.Opcode = opcode;
+ instruction.Saturate = saturate;
+ instruction.NumDstRegs = num_dst_regs;
+ instruction.NumSrcRegs = num_src_regs;
+
+ header_bodysize_grow( header );
+
+ return instruction;
+}
+
+static void
+instruction_grow(
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ assert (instruction->NrTokens < 0xFF);
+
+ instruction->NrTokens++;
+
+ header_bodysize_grow( header );
+}
+
+struct tgsi_full_instruction
+tgsi_default_full_instruction( void )
+{
+ struct tgsi_full_instruction full_instruction;
+ unsigned i;
+
+ full_instruction.Instruction = tgsi_default_instruction();
+ full_instruction.InstructionExtNv = tgsi_default_instruction_ext_nv();
+ full_instruction.InstructionExtLabel = tgsi_default_instruction_ext_label();
+ full_instruction.InstructionExtTexture = tgsi_default_instruction_ext_texture();
+ for( i = 0; i < TGSI_FULL_MAX_DST_REGISTERS; i++ ) {
+ full_instruction.FullDstRegisters[i] = tgsi_default_full_dst_register();
+ }
+ for( i = 0; i < TGSI_FULL_MAX_SRC_REGISTERS; i++ ) {
+ full_instruction.FullSrcRegisters[i] = tgsi_default_full_src_register();
+ }
+
+ full_instruction.Flags = 0x0;
+
+ return full_instruction;
+}
+
+unsigned
+tgsi_build_full_instruction(
+ const struct tgsi_full_instruction *full_inst,
+ struct tgsi_token *tokens,
+ struct tgsi_header *header,
+ unsigned maxsize )
+{
+ unsigned size = 0;
+ unsigned i;
+ struct tgsi_instruction *instruction;
+ struct tgsi_token *prev_token;
+
+ if( maxsize <= size )
+ return 0;
+ instruction = (struct tgsi_instruction *) &tokens[size];
+ size++;
+
+ *instruction = tgsi_build_instruction(
+ full_inst->Instruction.Opcode,
+ full_inst->Instruction.Saturate,
+ full_inst->Instruction.NumDstRegs,
+ full_inst->Instruction.NumSrcRegs,
+ header );
+ prev_token = (struct tgsi_token *) instruction;
+
+ if( tgsi_compare_instruction_ext_nv(
+ full_inst->InstructionExtNv,
+ tgsi_default_instruction_ext_nv() ) ) {
+ struct tgsi_instruction_ext_nv *instruction_ext_nv;
+
+ if( maxsize <= size )
+ return 0;
+ instruction_ext_nv =
+ (struct tgsi_instruction_ext_nv *) &tokens[size];
+ size++;
+
+ *instruction_ext_nv = tgsi_build_instruction_ext_nv(
+ full_inst->InstructionExtNv.Precision,
+ full_inst->InstructionExtNv.CondDstIndex,
+ full_inst->InstructionExtNv.CondFlowIndex,
+ full_inst->InstructionExtNv.CondMask,
+ full_inst->InstructionExtNv.CondSwizzleX,
+ full_inst->InstructionExtNv.CondSwizzleY,
+ full_inst->InstructionExtNv.CondSwizzleZ,
+ full_inst->InstructionExtNv.CondSwizzleW,
+ full_inst->InstructionExtNv.CondDstUpdate,
+ full_inst->InstructionExtNv.CondFlowEnable,
+ prev_token,
+ instruction,
+ header );
+ prev_token = (struct tgsi_token *) instruction_ext_nv;
+ }
+
+ if( tgsi_compare_instruction_ext_label(
+ full_inst->InstructionExtLabel,
+ tgsi_default_instruction_ext_label() ) ) {
+ struct tgsi_instruction_ext_label *instruction_ext_label;
+
+ if( maxsize <= size )
+ return 0;
+ instruction_ext_label =
+ (struct tgsi_instruction_ext_label *) &tokens[size];
+ size++;
+
+ *instruction_ext_label = tgsi_build_instruction_ext_label(
+ full_inst->InstructionExtLabel.Label,
+ prev_token,
+ instruction,
+ header );
+ prev_token = (struct tgsi_token *) instruction_ext_label;
+ }
+
+ if( tgsi_compare_instruction_ext_texture(
+ full_inst->InstructionExtTexture,
+ tgsi_default_instruction_ext_texture() ) ) {
+ struct tgsi_instruction_ext_texture *instruction_ext_texture;
+
+ if( maxsize <= size )
+ return 0;
+ instruction_ext_texture =
+ (struct tgsi_instruction_ext_texture *) &tokens[size];
+ size++;
+
+ *instruction_ext_texture = tgsi_build_instruction_ext_texture(
+ full_inst->InstructionExtTexture.Texture,
+ prev_token,
+ instruction,
+ header );
+ prev_token = (struct tgsi_token *) instruction_ext_texture;
+ }
+
+ for( i = 0; i < full_inst->Instruction.NumDstRegs; i++ ) {
+ const struct tgsi_full_dst_register *reg = &full_inst->FullDstRegisters[i];
+ struct tgsi_dst_register *dst_register;
+ struct tgsi_token *prev_token;
+
+ if( maxsize <= size )
+ return 0;
+ dst_register = (struct tgsi_dst_register *) &tokens[size];
+ size++;
+
+ *dst_register = tgsi_build_dst_register(
+ reg->DstRegister.File,
+ reg->DstRegister.WriteMask,
+ reg->DstRegister.Indirect,
+ reg->DstRegister.Index,
+ instruction,
+ header );
+ prev_token = (struct tgsi_token *) dst_register;
+
+ if( tgsi_compare_dst_register_ext_concode(
+ reg->DstRegisterExtConcode,
+ tgsi_default_dst_register_ext_concode() ) ) {
+ struct tgsi_dst_register_ext_concode *dst_register_ext_concode;
+
+ if( maxsize <= size )
+ return 0;
+ dst_register_ext_concode =
+ (struct tgsi_dst_register_ext_concode *) &tokens[size];
+ size++;
+
+ *dst_register_ext_concode = tgsi_build_dst_register_ext_concode(
+ reg->DstRegisterExtConcode.CondMask,
+ reg->DstRegisterExtConcode.CondSwizzleX,
+ reg->DstRegisterExtConcode.CondSwizzleY,
+ reg->DstRegisterExtConcode.CondSwizzleZ,
+ reg->DstRegisterExtConcode.CondSwizzleW,
+ reg->DstRegisterExtConcode.CondSrcIndex,
+ prev_token,
+ instruction,
+ header );
+ prev_token = (struct tgsi_token *) dst_register_ext_concode;
+ }
+
+ if( tgsi_compare_dst_register_ext_modulate(
+ reg->DstRegisterExtModulate,
+ tgsi_default_dst_register_ext_modulate() ) ) {
+ struct tgsi_dst_register_ext_modulate *dst_register_ext_modulate;
+
+ if( maxsize <= size )
+ return 0;
+ dst_register_ext_modulate =
+ (struct tgsi_dst_register_ext_modulate *) &tokens[size];
+ size++;
+
+ *dst_register_ext_modulate = tgsi_build_dst_register_ext_modulate(
+ reg->DstRegisterExtModulate.Modulate,
+ prev_token,
+ instruction,
+ header );
+ prev_token = (struct tgsi_token *) dst_register_ext_modulate;
+ }
+
+ if( reg->DstRegister.Indirect ) {
+ struct tgsi_src_register *ind;
+
+ if( maxsize <= size )
+ return 0;
+ ind = (struct tgsi_src_register *) &tokens[size];
+ size++;
+
+ *ind = tgsi_build_src_register(
+ reg->DstRegisterInd.File,
+ reg->DstRegisterInd.SwizzleX,
+ reg->DstRegisterInd.SwizzleY,
+ reg->DstRegisterInd.SwizzleZ,
+ reg->DstRegisterInd.SwizzleW,
+ reg->DstRegisterInd.Negate,
+ reg->DstRegisterInd.Indirect,
+ reg->DstRegisterInd.Dimension,
+ reg->DstRegisterInd.Index,
+ instruction,
+ header );
+ }
+ }
+
+ for( i = 0; i < full_inst->Instruction.NumSrcRegs; i++ ) {
+ const struct tgsi_full_src_register *reg = &full_inst->FullSrcRegisters[i];
+ struct tgsi_src_register *src_register;
+ struct tgsi_token *prev_token;
+
+ if( maxsize <= size )
+ return 0;
+ src_register = (struct tgsi_src_register *) &tokens[size];
+ size++;
+
+ *src_register = tgsi_build_src_register(
+ reg->SrcRegister.File,
+ reg->SrcRegister.SwizzleX,
+ reg->SrcRegister.SwizzleY,
+ reg->SrcRegister.SwizzleZ,
+ reg->SrcRegister.SwizzleW,
+ reg->SrcRegister.Negate,
+ reg->SrcRegister.Indirect,
+ reg->SrcRegister.Dimension,
+ reg->SrcRegister.Index,
+ instruction,
+ header );
+ prev_token = (struct tgsi_token *) src_register;
+
+ if( tgsi_compare_src_register_ext_swz(
+ reg->SrcRegisterExtSwz,
+ tgsi_default_src_register_ext_swz() ) ) {
+ struct tgsi_src_register_ext_swz *src_register_ext_swz;
+
+ /* Use of the extended swizzle requires the simple swizzle to be identity.
+ */
+ assert( reg->SrcRegister.SwizzleX == TGSI_SWIZZLE_X );
+ assert( reg->SrcRegister.SwizzleY == TGSI_SWIZZLE_Y );
+ assert( reg->SrcRegister.SwizzleZ == TGSI_SWIZZLE_Z );
+ assert( reg->SrcRegister.SwizzleW == TGSI_SWIZZLE_W );
+ assert( reg->SrcRegister.Negate == FALSE );
+
+ if( maxsize <= size )
+ return 0;
+ src_register_ext_swz =
+ (struct tgsi_src_register_ext_swz *) &tokens[size];
+ size++;
+
+ *src_register_ext_swz = tgsi_build_src_register_ext_swz(
+ reg->SrcRegisterExtSwz.ExtSwizzleX,
+ reg->SrcRegisterExtSwz.ExtSwizzleY,
+ reg->SrcRegisterExtSwz.ExtSwizzleZ,
+ reg->SrcRegisterExtSwz.ExtSwizzleW,
+ reg->SrcRegisterExtSwz.NegateX,
+ reg->SrcRegisterExtSwz.NegateY,
+ reg->SrcRegisterExtSwz.NegateZ,
+ reg->SrcRegisterExtSwz.NegateW,
+ prev_token,
+ instruction,
+ header );
+ prev_token = (struct tgsi_token *) src_register_ext_swz;
+ }
+
+ if( tgsi_compare_src_register_ext_mod(
+ reg->SrcRegisterExtMod,
+ tgsi_default_src_register_ext_mod() ) ) {
+ struct tgsi_src_register_ext_mod *src_register_ext_mod;
+
+ if( maxsize <= size )
+ return 0;
+ src_register_ext_mod =
+ (struct tgsi_src_register_ext_mod *) &tokens[size];
+ size++;
+
+ *src_register_ext_mod = tgsi_build_src_register_ext_mod(
+ reg->SrcRegisterExtMod.Complement,
+ reg->SrcRegisterExtMod.Bias,
+ reg->SrcRegisterExtMod.Scale2X,
+ reg->SrcRegisterExtMod.Absolute,
+ reg->SrcRegisterExtMod.Negate,
+ prev_token,
+ instruction,
+ header );
+ prev_token = (struct tgsi_token *) src_register_ext_mod;
+ }
+
+ if( reg->SrcRegister.Indirect ) {
+ struct tgsi_src_register *ind;
+
+ if( maxsize <= size )
+ return 0;
+ ind = (struct tgsi_src_register *) &tokens[size];
+ size++;
+
+ *ind = tgsi_build_src_register(
+ reg->SrcRegisterInd.File,
+ reg->SrcRegisterInd.SwizzleX,
+ reg->SrcRegisterInd.SwizzleY,
+ reg->SrcRegisterInd.SwizzleZ,
+ reg->SrcRegisterInd.SwizzleW,
+ reg->SrcRegisterInd.Negate,
+ reg->SrcRegisterInd.Indirect,
+ reg->SrcRegisterInd.Dimension,
+ reg->SrcRegisterInd.Index,
+ instruction,
+ header );
+ }
+
+ if( reg->SrcRegister.Dimension ) {
+ struct tgsi_dimension *dim;
+
+ assert( !reg->SrcRegisterDim.Dimension );
+
+ if( maxsize <= size )
+ return 0;
+ dim = (struct tgsi_dimension *) &tokens[size];
+ size++;
+
+ *dim = tgsi_build_dimension(
+ reg->SrcRegisterDim.Indirect,
+ reg->SrcRegisterDim.Index,
+ instruction,
+ header );
+
+ if( reg->SrcRegisterDim.Indirect ) {
+ struct tgsi_src_register *ind;
+
+ if( maxsize <= size )
+ return 0;
+ ind = (struct tgsi_src_register *) &tokens[size];
+ size++;
+
+ *ind = tgsi_build_src_register(
+ reg->SrcRegisterDimInd.File,
+ reg->SrcRegisterDimInd.SwizzleX,
+ reg->SrcRegisterDimInd.SwizzleY,
+ reg->SrcRegisterDimInd.SwizzleZ,
+ reg->SrcRegisterDimInd.SwizzleW,
+ reg->SrcRegisterDimInd.Negate,
+ reg->SrcRegisterDimInd.Indirect,
+ reg->SrcRegisterDimInd.Dimension,
+ reg->SrcRegisterDimInd.Index,
+ instruction,
+ header );
+ }
+ }
+ }
+
+ return size;
+}
+
+struct tgsi_instruction_ext_nv
+tgsi_default_instruction_ext_nv( void )
+{
+ struct tgsi_instruction_ext_nv instruction_ext_nv;
+
+ instruction_ext_nv.Type = TGSI_INSTRUCTION_EXT_TYPE_NV;
+ instruction_ext_nv.Precision = TGSI_PRECISION_DEFAULT;
+ instruction_ext_nv.CondDstIndex = 0;
+ instruction_ext_nv.CondFlowIndex = 0;
+ instruction_ext_nv.CondMask = TGSI_CC_TR;
+ instruction_ext_nv.CondSwizzleX = TGSI_SWIZZLE_X;
+ instruction_ext_nv.CondSwizzleY = TGSI_SWIZZLE_Y;
+ instruction_ext_nv.CondSwizzleZ = TGSI_SWIZZLE_Z;
+ instruction_ext_nv.CondSwizzleW = TGSI_SWIZZLE_W;
+ instruction_ext_nv.CondDstUpdate = 0;
+ instruction_ext_nv.CondFlowEnable = 0;
+ instruction_ext_nv.Padding = 0;
+ instruction_ext_nv.Extended = 0;
+
+ return instruction_ext_nv;
+}
+
+
+/** test for inequality of 32-bit values pointed to by a and b */
+static INLINE boolean
+compare32(const void *a, const void *b)
+{
+ return *((uint32_t *) a) != *((uint32_t *) b);
+}
+
+
+unsigned
+tgsi_compare_instruction_ext_nv(
+ struct tgsi_instruction_ext_nv a,
+ struct tgsi_instruction_ext_nv b )
+{
+ a.Padding = b.Padding = 0;
+ a.Extended = b.Extended = 0;
+ return compare32(&a, &b);
+}
+
+struct tgsi_instruction_ext_nv
+tgsi_build_instruction_ext_nv(
+ unsigned precision,
+ unsigned cond_dst_index,
+ unsigned cond_flow_index,
+ unsigned cond_mask,
+ unsigned cond_swizzle_x,
+ unsigned cond_swizzle_y,
+ unsigned cond_swizzle_z,
+ unsigned cond_swizzle_w,
+ unsigned cond_dst_update,
+ unsigned cond_flow_enable,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_instruction_ext_nv instruction_ext_nv;
+
+ instruction_ext_nv = tgsi_default_instruction_ext_nv();
+ instruction_ext_nv.Precision = precision;
+ instruction_ext_nv.CondDstIndex = cond_dst_index;
+ instruction_ext_nv.CondFlowIndex = cond_flow_index;
+ instruction_ext_nv.CondMask = cond_mask;
+ instruction_ext_nv.CondSwizzleX = cond_swizzle_x;
+ instruction_ext_nv.CondSwizzleY = cond_swizzle_y;
+ instruction_ext_nv.CondSwizzleZ = cond_swizzle_z;
+ instruction_ext_nv.CondSwizzleW = cond_swizzle_w;
+ instruction_ext_nv.CondDstUpdate = cond_dst_update;
+ instruction_ext_nv.CondFlowEnable = cond_flow_enable;
+
+ prev_token->Extended = 1;
+ instruction_grow( instruction, header );
+
+ return instruction_ext_nv;
+}
+
+struct tgsi_instruction_ext_label
+tgsi_default_instruction_ext_label( void )
+{
+ struct tgsi_instruction_ext_label instruction_ext_label;
+
+ instruction_ext_label.Type = TGSI_INSTRUCTION_EXT_TYPE_LABEL;
+ instruction_ext_label.Label = 0;
+ instruction_ext_label.Padding = 0;
+ instruction_ext_label.Extended = 0;
+
+ return instruction_ext_label;
+}
+
+unsigned
+tgsi_compare_instruction_ext_label(
+ struct tgsi_instruction_ext_label a,
+ struct tgsi_instruction_ext_label b )
+{
+ a.Padding = b.Padding = 0;
+ a.Extended = b.Extended = 0;
+ return compare32(&a, &b);
+}
+
+struct tgsi_instruction_ext_label
+tgsi_build_instruction_ext_label(
+ unsigned label,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_instruction_ext_label instruction_ext_label;
+
+ instruction_ext_label = tgsi_default_instruction_ext_label();
+ instruction_ext_label.Label = label;
+
+ prev_token->Extended = 1;
+ instruction_grow( instruction, header );
+
+ return instruction_ext_label;
+}
+
+struct tgsi_instruction_ext_texture
+tgsi_default_instruction_ext_texture( void )
+{
+ struct tgsi_instruction_ext_texture instruction_ext_texture;
+
+ instruction_ext_texture.Type = TGSI_INSTRUCTION_EXT_TYPE_TEXTURE;
+ instruction_ext_texture.Texture = TGSI_TEXTURE_UNKNOWN;
+ instruction_ext_texture.Padding = 0;
+ instruction_ext_texture.Extended = 0;
+
+ return instruction_ext_texture;
+}
+
+unsigned
+tgsi_compare_instruction_ext_texture(
+ struct tgsi_instruction_ext_texture a,
+ struct tgsi_instruction_ext_texture b )
+{
+ a.Padding = b.Padding = 0;
+ a.Extended = b.Extended = 0;
+ return compare32(&a, &b);
+}
+
+struct tgsi_instruction_ext_texture
+tgsi_build_instruction_ext_texture(
+ unsigned texture,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_instruction_ext_texture instruction_ext_texture;
+
+ instruction_ext_texture = tgsi_default_instruction_ext_texture();
+ instruction_ext_texture.Texture = texture;
+
+ prev_token->Extended = 1;
+ instruction_grow( instruction, header );
+
+ return instruction_ext_texture;
+}
+
+struct tgsi_src_register
+tgsi_default_src_register( void )
+{
+ struct tgsi_src_register src_register;
+
+ src_register.File = TGSI_FILE_NULL;
+ src_register.SwizzleX = TGSI_SWIZZLE_X;
+ src_register.SwizzleY = TGSI_SWIZZLE_Y;
+ src_register.SwizzleZ = TGSI_SWIZZLE_Z;
+ src_register.SwizzleW = TGSI_SWIZZLE_W;
+ src_register.Negate = 0;
+ src_register.Indirect = 0;
+ src_register.Dimension = 0;
+ src_register.Index = 0;
+ src_register.Extended = 0;
+
+ return src_register;
+}
+
+struct tgsi_src_register
+tgsi_build_src_register(
+ unsigned file,
+ unsigned swizzle_x,
+ unsigned swizzle_y,
+ unsigned swizzle_z,
+ unsigned swizzle_w,
+ unsigned negate,
+ unsigned indirect,
+ unsigned dimension,
+ int index,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_src_register src_register;
+
+ assert( file < TGSI_FILE_COUNT );
+ assert( swizzle_x <= TGSI_SWIZZLE_W );
+ assert( swizzle_y <= TGSI_SWIZZLE_W );
+ assert( swizzle_z <= TGSI_SWIZZLE_W );
+ assert( swizzle_w <= TGSI_SWIZZLE_W );
+ assert( negate <= 1 );
+ assert( index >= -0x8000 && index <= 0x7FFF );
+
+ src_register = tgsi_default_src_register();
+ src_register.File = file;
+ src_register.SwizzleX = swizzle_x;
+ src_register.SwizzleY = swizzle_y;
+ src_register.SwizzleZ = swizzle_z;
+ src_register.SwizzleW = swizzle_w;
+ src_register.Negate = negate;
+ src_register.Indirect = indirect;
+ src_register.Dimension = dimension;
+ src_register.Index = index;
+
+ instruction_grow( instruction, header );
+
+ return src_register;
+}
+
+struct tgsi_full_src_register
+tgsi_default_full_src_register( void )
+{
+ struct tgsi_full_src_register full_src_register;
+
+ full_src_register.SrcRegister = tgsi_default_src_register();
+ full_src_register.SrcRegisterExtSwz = tgsi_default_src_register_ext_swz();
+ full_src_register.SrcRegisterExtMod = tgsi_default_src_register_ext_mod();
+ full_src_register.SrcRegisterInd = tgsi_default_src_register();
+ full_src_register.SrcRegisterDim = tgsi_default_dimension();
+ full_src_register.SrcRegisterDimInd = tgsi_default_src_register();
+
+ return full_src_register;
+}
+
+struct tgsi_src_register_ext_swz
+tgsi_default_src_register_ext_swz( void )
+{
+ struct tgsi_src_register_ext_swz src_register_ext_swz;
+
+ src_register_ext_swz.Type = TGSI_SRC_REGISTER_EXT_TYPE_SWZ;
+ src_register_ext_swz.ExtSwizzleX = TGSI_EXTSWIZZLE_X;
+ src_register_ext_swz.ExtSwizzleY = TGSI_EXTSWIZZLE_Y;
+ src_register_ext_swz.ExtSwizzleZ = TGSI_EXTSWIZZLE_Z;
+ src_register_ext_swz.ExtSwizzleW = TGSI_EXTSWIZZLE_W;
+ src_register_ext_swz.NegateX = 0;
+ src_register_ext_swz.NegateY = 0;
+ src_register_ext_swz.NegateZ = 0;
+ src_register_ext_swz.NegateW = 0;
+ src_register_ext_swz.Padding = 0;
+ src_register_ext_swz.Extended = 0;
+
+ return src_register_ext_swz;
+}
+
+unsigned
+tgsi_compare_src_register_ext_swz(
+ struct tgsi_src_register_ext_swz a,
+ struct tgsi_src_register_ext_swz b )
+{
+ a.Padding = b.Padding = 0;
+ a.Extended = b.Extended = 0;
+ return compare32(&a, &b);
+}
+
+struct tgsi_src_register_ext_swz
+tgsi_build_src_register_ext_swz(
+ unsigned ext_swizzle_x,
+ unsigned ext_swizzle_y,
+ unsigned ext_swizzle_z,
+ unsigned ext_swizzle_w,
+ unsigned negate_x,
+ unsigned negate_y,
+ unsigned negate_z,
+ unsigned negate_w,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_src_register_ext_swz src_register_ext_swz;
+
+ assert( ext_swizzle_x <= TGSI_EXTSWIZZLE_ONE );
+ assert( ext_swizzle_y <= TGSI_EXTSWIZZLE_ONE );
+ assert( ext_swizzle_z <= TGSI_EXTSWIZZLE_ONE );
+ assert( ext_swizzle_w <= TGSI_EXTSWIZZLE_ONE );
+ assert( negate_x <= 1 );
+ assert( negate_y <= 1 );
+ assert( negate_z <= 1 );
+ assert( negate_w <= 1 );
+
+ src_register_ext_swz = tgsi_default_src_register_ext_swz();
+ src_register_ext_swz.ExtSwizzleX = ext_swizzle_x;
+ src_register_ext_swz.ExtSwizzleY = ext_swizzle_y;
+ src_register_ext_swz.ExtSwizzleZ = ext_swizzle_z;
+ src_register_ext_swz.ExtSwizzleW = ext_swizzle_w;
+ src_register_ext_swz.NegateX = negate_x;
+ src_register_ext_swz.NegateY = negate_y;
+ src_register_ext_swz.NegateZ = negate_z;
+ src_register_ext_swz.NegateW = negate_w;
+
+ prev_token->Extended = 1;
+ instruction_grow( instruction, header );
+
+ return src_register_ext_swz;
+}
+
+struct tgsi_src_register_ext_mod
+tgsi_default_src_register_ext_mod( void )
+{
+ struct tgsi_src_register_ext_mod src_register_ext_mod;
+
+ src_register_ext_mod.Type = TGSI_SRC_REGISTER_EXT_TYPE_MOD;
+ src_register_ext_mod.Complement = 0;
+ src_register_ext_mod.Bias = 0;
+ src_register_ext_mod.Scale2X = 0;
+ src_register_ext_mod.Absolute = 0;
+ src_register_ext_mod.Negate = 0;
+ src_register_ext_mod.Padding = 0;
+ src_register_ext_mod.Extended = 0;
+
+ return src_register_ext_mod;
+}
+
+unsigned
+tgsi_compare_src_register_ext_mod(
+ struct tgsi_src_register_ext_mod a,
+ struct tgsi_src_register_ext_mod b )
+{
+ a.Padding = b.Padding = 0;
+ a.Extended = b.Extended = 0;
+ return compare32(&a, &b);
+}
+
+struct tgsi_src_register_ext_mod
+tgsi_build_src_register_ext_mod(
+ unsigned complement,
+ unsigned bias,
+ unsigned scale_2x,
+ unsigned absolute,
+ unsigned negate,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_src_register_ext_mod src_register_ext_mod;
+
+ assert( complement <= 1 );
+ assert( bias <= 1 );
+ assert( scale_2x <= 1 );
+ assert( absolute <= 1 );
+ assert( negate <= 1 );
+
+ src_register_ext_mod = tgsi_default_src_register_ext_mod();
+ src_register_ext_mod.Complement = complement;
+ src_register_ext_mod.Bias = bias;
+ src_register_ext_mod.Scale2X = scale_2x;
+ src_register_ext_mod.Absolute = absolute;
+ src_register_ext_mod.Negate = negate;
+
+ prev_token->Extended = 1;
+ instruction_grow( instruction, header );
+
+ return src_register_ext_mod;
+}
+
+struct tgsi_dimension
+tgsi_default_dimension( void )
+{
+ struct tgsi_dimension dimension;
+
+ dimension.Indirect = 0;
+ dimension.Dimension = 0;
+ dimension.Padding = 0;
+ dimension.Index = 0;
+ dimension.Extended = 0;
+
+ return dimension;
+}
+
+struct tgsi_dimension
+tgsi_build_dimension(
+ unsigned indirect,
+ unsigned index,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_dimension dimension;
+
+ dimension = tgsi_default_dimension();
+ dimension.Indirect = indirect;
+ dimension.Index = index;
+
+ instruction_grow( instruction, header );
+
+ return dimension;
+}
+
+struct tgsi_dst_register
+tgsi_default_dst_register( void )
+{
+ struct tgsi_dst_register dst_register;
+
+ dst_register.File = TGSI_FILE_NULL;
+ dst_register.WriteMask = TGSI_WRITEMASK_XYZW;
+ dst_register.Indirect = 0;
+ dst_register.Dimension = 0;
+ dst_register.Index = 0;
+ dst_register.Padding = 0;
+ dst_register.Extended = 0;
+
+ return dst_register;
+}
+
+struct tgsi_dst_register
+tgsi_build_dst_register(
+ unsigned file,
+ unsigned mask,
+ unsigned indirect,
+ int index,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_dst_register dst_register;
+
+ assert( file < TGSI_FILE_COUNT );
+ assert( mask <= TGSI_WRITEMASK_XYZW );
+ assert( index >= -32768 && index <= 32767 );
+
+ dst_register = tgsi_default_dst_register();
+ dst_register.File = file;
+ dst_register.WriteMask = mask;
+ dst_register.Index = index;
+ dst_register.Indirect = indirect;
+
+ instruction_grow( instruction, header );
+
+ return dst_register;
+}
+
+struct tgsi_full_dst_register
+tgsi_default_full_dst_register( void )
+{
+ struct tgsi_full_dst_register full_dst_register;
+
+ full_dst_register.DstRegister = tgsi_default_dst_register();
+ full_dst_register.DstRegisterInd = tgsi_default_src_register();
+ full_dst_register.DstRegisterExtConcode =
+ tgsi_default_dst_register_ext_concode();
+ full_dst_register.DstRegisterExtModulate =
+ tgsi_default_dst_register_ext_modulate();
+
+ return full_dst_register;
+}
+
+struct tgsi_dst_register_ext_concode
+tgsi_default_dst_register_ext_concode( void )
+{
+ struct tgsi_dst_register_ext_concode dst_register_ext_concode;
+
+ dst_register_ext_concode.Type = TGSI_DST_REGISTER_EXT_TYPE_CONDCODE;
+ dst_register_ext_concode.CondMask = TGSI_CC_TR;
+ dst_register_ext_concode.CondSwizzleX = TGSI_SWIZZLE_X;
+ dst_register_ext_concode.CondSwizzleY = TGSI_SWIZZLE_Y;
+ dst_register_ext_concode.CondSwizzleZ = TGSI_SWIZZLE_Z;
+ dst_register_ext_concode.CondSwizzleW = TGSI_SWIZZLE_W;
+ dst_register_ext_concode.CondSrcIndex = 0;
+ dst_register_ext_concode.Padding = 0;
+ dst_register_ext_concode.Extended = 0;
+
+ return dst_register_ext_concode;
+}
+
+unsigned
+tgsi_compare_dst_register_ext_concode(
+ struct tgsi_dst_register_ext_concode a,
+ struct tgsi_dst_register_ext_concode b )
+{
+ a.Padding = b.Padding = 0;
+ a.Extended = b.Extended = 0;
+ return compare32(&a, &b);
+}
+
+struct tgsi_dst_register_ext_concode
+tgsi_build_dst_register_ext_concode(
+ unsigned cc,
+ unsigned swizzle_x,
+ unsigned swizzle_y,
+ unsigned swizzle_z,
+ unsigned swizzle_w,
+ int index,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_dst_register_ext_concode dst_register_ext_concode;
+
+ assert( cc <= TGSI_CC_FL );
+ assert( swizzle_x <= TGSI_SWIZZLE_W );
+ assert( swizzle_y <= TGSI_SWIZZLE_W );
+ assert( swizzle_z <= TGSI_SWIZZLE_W );
+ assert( swizzle_w <= TGSI_SWIZZLE_W );
+ assert( index >= -32768 && index <= 32767 );
+
+ dst_register_ext_concode = tgsi_default_dst_register_ext_concode();
+ dst_register_ext_concode.CondMask = cc;
+ dst_register_ext_concode.CondSwizzleX = swizzle_x;
+ dst_register_ext_concode.CondSwizzleY = swizzle_y;
+ dst_register_ext_concode.CondSwizzleZ = swizzle_z;
+ dst_register_ext_concode.CondSwizzleW = swizzle_w;
+ dst_register_ext_concode.CondSrcIndex = index;
+
+ prev_token->Extended = 1;
+ instruction_grow( instruction, header );
+
+ return dst_register_ext_concode;
+}
+
+struct tgsi_dst_register_ext_modulate
+tgsi_default_dst_register_ext_modulate( void )
+{
+ struct tgsi_dst_register_ext_modulate dst_register_ext_modulate;
+
+ dst_register_ext_modulate.Type = TGSI_DST_REGISTER_EXT_TYPE_MODULATE;
+ dst_register_ext_modulate.Modulate = TGSI_MODULATE_1X;
+ dst_register_ext_modulate.Padding = 0;
+ dst_register_ext_modulate.Extended = 0;
+
+ return dst_register_ext_modulate;
+}
+
+unsigned
+tgsi_compare_dst_register_ext_modulate(
+ struct tgsi_dst_register_ext_modulate a,
+ struct tgsi_dst_register_ext_modulate b )
+{
+ a.Padding = b.Padding = 0;
+ a.Extended = b.Extended = 0;
+ return compare32(&a, &b);
+}
+
+struct tgsi_dst_register_ext_modulate
+tgsi_build_dst_register_ext_modulate(
+ unsigned modulate,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header )
+{
+ struct tgsi_dst_register_ext_modulate dst_register_ext_modulate;
+
+ assert( modulate <= TGSI_MODULATE_EIGHTH );
+
+ dst_register_ext_modulate = tgsi_default_dst_register_ext_modulate();
+ dst_register_ext_modulate.Modulate = modulate;
+
+ prev_token->Extended = 1;
+ instruction_grow( instruction, header );
+
+ return dst_register_ext_modulate;
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.h b/src/gallium/auxiliary/tgsi/tgsi_build.h
new file mode 100644
index 0000000000..17d977b059
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_build.h
@@ -0,0 +1,339 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_BUILD_H
+#define TGSI_BUILD_H
+
+
+struct tgsi_token;
+
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+/*
+ * version
+ */
+
+struct tgsi_version
+tgsi_build_version( void );
+
+/*
+ * header
+ */
+
+struct tgsi_header
+tgsi_build_header( void );
+
+struct tgsi_processor
+tgsi_default_processor( void );
+
+struct tgsi_processor
+tgsi_build_processor(
+ unsigned processor,
+ struct tgsi_header *header );
+
+/*
+ * declaration
+ */
+
+struct tgsi_declaration
+tgsi_default_declaration( void );
+
+struct tgsi_declaration
+tgsi_build_declaration(
+ unsigned file,
+ unsigned usage_mask,
+ unsigned interpolate,
+ unsigned semantic,
+ unsigned centroid,
+ unsigned invariant,
+ struct tgsi_header *header );
+
+struct tgsi_full_declaration
+tgsi_default_full_declaration( void );
+
+unsigned
+tgsi_build_full_declaration(
+ const struct tgsi_full_declaration *full_decl,
+ struct tgsi_token *tokens,
+ struct tgsi_header *header,
+ unsigned maxsize );
+
+struct tgsi_declaration_range
+tgsi_default_declaration_range( void );
+
+struct tgsi_declaration_range
+tgsi_build_declaration_range(
+ unsigned first,
+ unsigned last,
+ struct tgsi_declaration *declaration,
+ struct tgsi_header *header );
+
+struct tgsi_declaration_semantic
+tgsi_default_declaration_semantic( void );
+
+struct tgsi_declaration_semantic
+tgsi_build_declaration_semantic(
+ unsigned semantic_name,
+ unsigned semantic_index,
+ struct tgsi_declaration *declaration,
+ struct tgsi_header *header );
+
+/*
+ * immediate
+ */
+
+struct tgsi_immediate
+tgsi_default_immediate( void );
+
+struct tgsi_immediate
+tgsi_build_immediate(
+ struct tgsi_header *header );
+
+struct tgsi_full_immediate
+tgsi_default_full_immediate( void );
+
+union tgsi_immediate_data
+tgsi_build_immediate_float32(
+ float value,
+ struct tgsi_immediate *immediate,
+ struct tgsi_header *header );
+
+unsigned
+tgsi_build_full_immediate(
+ const struct tgsi_full_immediate *full_imm,
+ struct tgsi_token *tokens,
+ struct tgsi_header *header,
+ unsigned maxsize );
+
+/*
+ * instruction
+ */
+
+struct tgsi_instruction
+tgsi_default_instruction( void );
+
+struct tgsi_instruction
+tgsi_build_instruction(
+ unsigned opcode,
+ unsigned saturate,
+ unsigned num_dst_regs,
+ unsigned num_src_regs,
+ struct tgsi_header *header );
+
+struct tgsi_full_instruction
+tgsi_default_full_instruction( void );
+
+unsigned
+tgsi_build_full_instruction(
+ const struct tgsi_full_instruction *full_inst,
+ struct tgsi_token *tokens,
+ struct tgsi_header *header,
+ unsigned maxsize );
+
+struct tgsi_instruction_ext_nv
+tgsi_default_instruction_ext_nv( void );
+
+unsigned
+tgsi_compare_instruction_ext_nv(
+ struct tgsi_instruction_ext_nv a,
+ struct tgsi_instruction_ext_nv b );
+
+struct tgsi_instruction_ext_nv
+tgsi_build_instruction_ext_nv(
+ unsigned precision,
+ unsigned cond_dst_index,
+ unsigned cond_flow_index,
+ unsigned cond_mask,
+ unsigned cond_swizzle_x,
+ unsigned cond_swizzle_y,
+ unsigned cond_swizzle_z,
+ unsigned cond_swizzle_w,
+ unsigned cond_dst_update,
+ unsigned cond_flow_enable,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+struct tgsi_instruction_ext_label
+tgsi_default_instruction_ext_label( void );
+
+unsigned
+tgsi_compare_instruction_ext_label(
+ struct tgsi_instruction_ext_label a,
+ struct tgsi_instruction_ext_label b );
+
+struct tgsi_instruction_ext_label
+tgsi_build_instruction_ext_label(
+ unsigned label,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+struct tgsi_instruction_ext_texture
+tgsi_default_instruction_ext_texture( void );
+
+unsigned
+tgsi_compare_instruction_ext_texture(
+ struct tgsi_instruction_ext_texture a,
+ struct tgsi_instruction_ext_texture b );
+
+struct tgsi_instruction_ext_texture
+tgsi_build_instruction_ext_texture(
+ unsigned texture,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+struct tgsi_src_register
+tgsi_default_src_register( void );
+
+struct tgsi_src_register
+tgsi_build_src_register(
+ unsigned file,
+ unsigned swizzle_x,
+ unsigned swizzle_y,
+ unsigned swizzle_z,
+ unsigned swizzle_w,
+ unsigned negate,
+ unsigned indirect,
+ unsigned dimension,
+ int index,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+struct tgsi_full_src_register
+tgsi_default_full_src_register( void );
+
+struct tgsi_src_register_ext_swz
+tgsi_default_src_register_ext_swz( void );
+
+unsigned
+tgsi_compare_src_register_ext_swz(
+ struct tgsi_src_register_ext_swz a,
+ struct tgsi_src_register_ext_swz b );
+
+struct tgsi_src_register_ext_swz
+tgsi_build_src_register_ext_swz(
+ unsigned ext_swizzle_x,
+ unsigned ext_swizzle_y,
+ unsigned ext_swizzle_z,
+ unsigned ext_swizzle_w,
+ unsigned negate_x,
+ unsigned negate_y,
+ unsigned negate_z,
+ unsigned negate_w,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+struct tgsi_src_register_ext_mod
+tgsi_default_src_register_ext_mod( void );
+
+unsigned
+tgsi_compare_src_register_ext_mod(
+ struct tgsi_src_register_ext_mod a,
+ struct tgsi_src_register_ext_mod b );
+
+struct tgsi_src_register_ext_mod
+tgsi_build_src_register_ext_mod(
+ unsigned complement,
+ unsigned bias,
+ unsigned scale_2x,
+ unsigned absolute,
+ unsigned negate,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+struct tgsi_dimension
+tgsi_default_dimension( void );
+
+struct tgsi_dimension
+tgsi_build_dimension(
+ unsigned indirect,
+ unsigned index,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+struct tgsi_dst_register
+tgsi_default_dst_register( void );
+
+struct tgsi_dst_register
+tgsi_build_dst_register(
+ unsigned file,
+ unsigned mask,
+ unsigned indirect,
+ int index,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+struct tgsi_full_dst_register
+tgsi_default_full_dst_register( void );
+
+struct tgsi_dst_register_ext_concode
+tgsi_default_dst_register_ext_concode( void );
+
+unsigned
+tgsi_compare_dst_register_ext_concode(
+ struct tgsi_dst_register_ext_concode a,
+ struct tgsi_dst_register_ext_concode b );
+
+struct tgsi_dst_register_ext_concode
+tgsi_build_dst_register_ext_concode(
+ unsigned cc,
+ unsigned swizzle_x,
+ unsigned swizzle_y,
+ unsigned swizzle_z,
+ unsigned swizzle_w,
+ int index,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+struct tgsi_dst_register_ext_modulate
+tgsi_default_dst_register_ext_modulate( void );
+
+unsigned
+tgsi_compare_dst_register_ext_modulate(
+ struct tgsi_dst_register_ext_modulate a,
+ struct tgsi_dst_register_ext_modulate b );
+
+struct tgsi_dst_register_ext_modulate
+tgsi_build_dst_register_ext_modulate(
+ unsigned modulate,
+ struct tgsi_token *prev_token,
+ struct tgsi_instruction *instruction,
+ struct tgsi_header *header );
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_BUILD_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c
new file mode 100644
index 0000000000..111d95b666
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c
@@ -0,0 +1,617 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "util/u_string.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "tgsi_dump.h"
+#include "tgsi_info.h"
+#include "tgsi_iterate.h"
+
+
+/** Number of spaces to indent for IF/LOOP/etc */
+static const int indent_spaces = 3;
+
+
+struct dump_ctx
+{
+ struct tgsi_iterate_context iter;
+
+ uint instno;
+ int indent;
+
+ uint indentation;
+
+ void (*printf)(struct dump_ctx *ctx, const char *format, ...);
+};
+
+static void
+dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
+{
+ va_list ap;
+ (void)ctx;
+ va_start(ap, format);
+ debug_vprintf(format, ap);
+ va_end(ap);
+}
+
+static void
+dump_enum(
+ struct dump_ctx *ctx,
+ uint e,
+ const char **enums,
+ uint enum_count )
+{
+ if (e >= enum_count)
+ ctx->printf( ctx, "%u", e );
+ else
+ ctx->printf( ctx, "%s", enums[e] );
+}
+
+#define EOL() ctx->printf( ctx, "\n" )
+#define TXT(S) ctx->printf( ctx, "%s", S )
+#define CHR(C) ctx->printf( ctx, "%c", C )
+#define UIX(I) ctx->printf( ctx, "0x%x", I )
+#define UID(I) ctx->printf( ctx, "%u", I )
+#define INSTID(I) ctx->printf( ctx, "% 3u", I )
+#define SID(I) ctx->printf( ctx, "%d", I )
+#define FLT(F) ctx->printf( ctx, "%10.4f", F )
+#define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
+
+static const char *processor_type_names[] =
+{
+ "FRAG",
+ "VERT",
+ "GEOM"
+};
+
+static const char *file_names[TGSI_FILE_COUNT] =
+{
+ "NULL",
+ "CONST",
+ "IN",
+ "OUT",
+ "TEMP",
+ "SAMP",
+ "ADDR",
+ "IMM",
+ "LOOP"
+};
+
+static const char *interpolate_names[] =
+{
+ "CONSTANT",
+ "LINEAR",
+ "PERSPECTIVE"
+};
+
+static const char *semantic_names[] =
+{
+ "POSITION",
+ "COLOR",
+ "BCOLOR",
+ "FOG",
+ "PSIZE",
+ "GENERIC",
+ "NORMAL",
+ "FACE"
+};
+
+static const char *immediate_type_names[] =
+{
+ "FLT32"
+};
+
+static const char *swizzle_names[] =
+{
+ "x",
+ "y",
+ "z",
+ "w"
+};
+
+static const char *texture_names[] =
+{
+ "UNKNOWN",
+ "1D",
+ "2D",
+ "3D",
+ "CUBE",
+ "RECT",
+ "SHADOW1D",
+ "SHADOW2D",
+ "SHADOWRECT"
+};
+
+static const char *extswizzle_names[] =
+{
+ "x",
+ "y",
+ "z",
+ "w",
+ "0",
+ "1"
+};
+
+static const char *modulate_names[TGSI_MODULATE_COUNT] =
+{
+ "",
+ "_2X",
+ "_4X",
+ "_8X",
+ "_D2",
+ "_D4",
+ "_D8"
+};
+
+static void
+_dump_register(
+ struct dump_ctx *ctx,
+ uint file,
+ int first,
+ int last )
+{
+ ENM( file, file_names );
+ CHR( '[' );
+ SID( first );
+ if (first != last) {
+ TXT( ".." );
+ SID( last );
+ }
+ CHR( ']' );
+}
+
+static void
+_dump_register_ind(
+ struct dump_ctx *ctx,
+ uint file,
+ int index,
+ uint ind_file,
+ int ind_index,
+ uint ind_swizzle )
+{
+ ENM( file, file_names );
+ CHR( '[' );
+ ENM( ind_file, file_names );
+ CHR( '[' );
+ SID( ind_index );
+ TXT( "]." );
+ ENM( ind_swizzle, swizzle_names );
+ if (index != 0) {
+ if (index > 0)
+ CHR( '+' );
+ SID( index );
+ }
+ CHR( ']' );
+}
+
+static void
+_dump_writemask(
+ struct dump_ctx *ctx,
+ uint writemask )
+{
+ if (writemask != TGSI_WRITEMASK_XYZW) {
+ CHR( '.' );
+ if (writemask & TGSI_WRITEMASK_X)
+ CHR( 'x' );
+ if (writemask & TGSI_WRITEMASK_Y)
+ CHR( 'y' );
+ if (writemask & TGSI_WRITEMASK_Z)
+ CHR( 'z' );
+ if (writemask & TGSI_WRITEMASK_W)
+ CHR( 'w' );
+ }
+}
+
+static boolean
+iter_declaration(
+ struct tgsi_iterate_context *iter,
+ struct tgsi_full_declaration *decl )
+{
+ struct dump_ctx *ctx = (struct dump_ctx *)iter;
+
+ assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT);
+ assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT);
+
+ TXT( "DCL " );
+
+ _dump_register(
+ ctx,
+ decl->Declaration.File,
+ decl->DeclarationRange.First,
+ decl->DeclarationRange.Last );
+ _dump_writemask(
+ ctx,
+ decl->Declaration.UsageMask );
+
+ if (decl->Declaration.Semantic) {
+ TXT( ", " );
+ ENM( decl->Semantic.SemanticName, semantic_names );
+ if (decl->Semantic.SemanticIndex != 0 ||
+ decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC) {
+ CHR( '[' );
+ UID( decl->Semantic.SemanticIndex );
+ CHR( ']' );
+ }
+ }
+
+ if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
+ decl->Declaration.File == TGSI_FILE_INPUT)
+ {
+ TXT( ", " );
+ ENM( decl->Declaration.Interpolate, interpolate_names );
+ }
+
+ if (decl->Declaration.Centroid) {
+ TXT( ", CENTROID" );
+ }
+
+ if (decl->Declaration.Invariant) {
+ TXT( ", INVARIANT" );
+ }
+
+ EOL();
+
+ return TRUE;
+}
+
+void
+tgsi_dump_declaration(
+ const struct tgsi_full_declaration *decl )
+{
+ struct dump_ctx ctx;
+
+ ctx.printf = dump_ctx_printf;
+
+ iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
+}
+
+static boolean
+iter_immediate(
+ struct tgsi_iterate_context *iter,
+ struct tgsi_full_immediate *imm )
+{
+ struct dump_ctx *ctx = (struct dump_ctx *) iter;
+
+ uint i;
+
+ TXT( "IMM " );
+ ENM( imm->Immediate.DataType, immediate_type_names );
+
+ TXT( " { " );
+
+ assert( imm->Immediate.NrTokens <= 4 + 1 );
+ for (i = 0; i < imm->Immediate.NrTokens - 1; i++) {
+ switch (imm->Immediate.DataType) {
+ case TGSI_IMM_FLOAT32:
+ FLT( imm->u[i].Float );
+ break;
+ default:
+ assert( 0 );
+ }
+
+ if (i < imm->Immediate.NrTokens - 2)
+ TXT( ", " );
+ }
+ TXT( " }" );
+
+ EOL();
+
+ return TRUE;
+}
+
+void
+tgsi_dump_immediate(
+ const struct tgsi_full_immediate *imm )
+{
+ struct dump_ctx ctx;
+
+ ctx.printf = dump_ctx_printf;
+
+ iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
+}
+
+static boolean
+iter_instruction(
+ struct tgsi_iterate_context *iter,
+ struct tgsi_full_instruction *inst )
+{
+ struct dump_ctx *ctx = (struct dump_ctx *) iter;
+ uint instno = ctx->instno++;
+ const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
+ uint i;
+ boolean first_reg = TRUE;
+
+ INSTID( instno );
+ TXT( ": " );
+
+ ctx->indent -= info->pre_dedent;
+ for(i = 0; (int)i < ctx->indent; ++i)
+ TXT( " " );
+ ctx->indent += info->post_indent;
+
+ TXT( info->mnemonic );
+
+ switch (inst->Instruction.Saturate) {
+ case TGSI_SAT_NONE:
+ break;
+ case TGSI_SAT_ZERO_ONE:
+ TXT( "_SAT" );
+ break;
+ case TGSI_SAT_MINUS_PLUS_ONE:
+ TXT( "_SATNV" );
+ break;
+ default:
+ assert( 0 );
+ }
+
+ for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
+ const struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
+
+ if (!first_reg)
+ CHR( ',' );
+ CHR( ' ' );
+
+ if (dst->DstRegister.Indirect) {
+ _dump_register_ind(
+ ctx,
+ dst->DstRegister.File,
+ dst->DstRegister.Index,
+ dst->DstRegisterInd.File,
+ dst->DstRegisterInd.Index,
+ dst->DstRegisterInd.SwizzleX );
+ }
+ else {
+ _dump_register(
+ ctx,
+ dst->DstRegister.File,
+ dst->DstRegister.Index,
+ dst->DstRegister.Index );
+ }
+ ENM( dst->DstRegisterExtModulate.Modulate, modulate_names );
+ _dump_writemask( ctx, dst->DstRegister.WriteMask );
+
+ first_reg = FALSE;
+ }
+
+ for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
+
+ if (!first_reg)
+ CHR( ',' );
+ CHR( ' ' );
+
+ if (src->SrcRegisterExtMod.Negate)
+ TXT( "-(" );
+ if (src->SrcRegisterExtMod.Absolute)
+ CHR( '|' );
+ if (src->SrcRegisterExtMod.Scale2X)
+ TXT( "2*(" );
+ if (src->SrcRegisterExtMod.Bias)
+ CHR( '(' );
+ if (src->SrcRegisterExtMod.Complement)
+ TXT( "1-(" );
+ if (src->SrcRegister.Negate)
+ CHR( '-' );
+
+ if (src->SrcRegister.Indirect) {
+ _dump_register_ind(
+ ctx,
+ src->SrcRegister.File,
+ src->SrcRegister.Index,
+ src->SrcRegisterInd.File,
+ src->SrcRegisterInd.Index,
+ src->SrcRegisterInd.SwizzleX );
+ }
+ else {
+ _dump_register(
+ ctx,
+ src->SrcRegister.File,
+ src->SrcRegister.Index,
+ src->SrcRegister.Index );
+ }
+
+ if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
+ src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
+ src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
+ src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) {
+ CHR( '.' );
+ ENM( src->SrcRegister.SwizzleX, swizzle_names );
+ ENM( src->SrcRegister.SwizzleY, swizzle_names );
+ ENM( src->SrcRegister.SwizzleZ, swizzle_names );
+ ENM( src->SrcRegister.SwizzleW, swizzle_names );
+ }
+ if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
+ src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
+ src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
+ src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
+ CHR( '.' );
+ if (src->SrcRegisterExtSwz.NegateX)
+ TXT("-");
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleX, extswizzle_names );
+ if (src->SrcRegisterExtSwz.NegateY)
+ TXT("-");
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleY, extswizzle_names );
+ if (src->SrcRegisterExtSwz.NegateZ)
+ TXT("-");
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, extswizzle_names );
+ if (src->SrcRegisterExtSwz.NegateW)
+ TXT("-");
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleW, extswizzle_names );
+ }
+
+ if (src->SrcRegisterExtMod.Complement)
+ CHR( ')' );
+ if (src->SrcRegisterExtMod.Bias)
+ TXT( ")-.5" );
+ if (src->SrcRegisterExtMod.Scale2X)
+ CHR( ')' );
+ if (src->SrcRegisterExtMod.Absolute)
+ CHR( '|' );
+ if (src->SrcRegisterExtMod.Negate)
+ CHR( ')' );
+
+ first_reg = FALSE;
+ }
+
+ if (inst->InstructionExtTexture.Texture != TGSI_TEXTURE_UNKNOWN) {
+ TXT( ", " );
+ ENM( inst->InstructionExtTexture.Texture, texture_names );
+ }
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_IF:
+ case TGSI_OPCODE_ELSE:
+ case TGSI_OPCODE_BGNLOOP:
+ case TGSI_OPCODE_ENDLOOP:
+ case TGSI_OPCODE_CAL:
+ TXT( " :" );
+ UID( inst->InstructionExtLabel.Label );
+ break;
+ }
+
+ /* update indentation */
+ if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
+ inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
+ inst->Instruction.Opcode == TGSI_OPCODE_BGNFOR ||
+ inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
+ ctx->indentation += indent_spaces;
+ }
+
+ EOL();
+
+ return TRUE;
+}
+
+void
+tgsi_dump_instruction(
+ const struct tgsi_full_instruction *inst,
+ uint instno )
+{
+ struct dump_ctx ctx;
+
+ ctx.instno = instno;
+ ctx.indent = 0;
+ ctx.printf = dump_ctx_printf;
+ ctx.indentation = 0;
+
+ iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
+}
+
+static boolean
+prolog(
+ struct tgsi_iterate_context *iter )
+{
+ struct dump_ctx *ctx = (struct dump_ctx *) iter;
+ ENM( iter->processor.Processor, processor_type_names );
+ UID( iter->version.MajorVersion );
+ CHR( '.' );
+ UID( iter->version.MinorVersion );
+ EOL();
+ return TRUE;
+}
+
+void
+tgsi_dump(
+ const struct tgsi_token *tokens,
+ uint flags )
+{
+ struct dump_ctx ctx;
+
+ ctx.iter.prolog = prolog;
+ ctx.iter.iterate_instruction = iter_instruction;
+ ctx.iter.iterate_declaration = iter_declaration;
+ ctx.iter.iterate_immediate = iter_immediate;
+ ctx.iter.epilog = NULL;
+
+ ctx.instno = 0;
+ ctx.indent = 0;
+ ctx.printf = dump_ctx_printf;
+ ctx.indentation = 0;
+
+ tgsi_iterate_shader( tokens, &ctx.iter );
+}
+
+struct str_dump_ctx
+{
+ struct dump_ctx base;
+ char *str;
+ char *ptr;
+ int left;
+};
+
+static void
+str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
+{
+ struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
+
+ if(sctx->left > 1) {
+ int written;
+ va_list ap;
+ va_start(ap, format);
+ written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
+ va_end(ap);
+
+ /* Some complicated logic needed to handle the return value of
+ * vsnprintf:
+ */
+ if (written > 0) {
+ written = MIN2(sctx->left, written);
+ sctx->ptr += written;
+ sctx->left -= written;
+ }
+ }
+}
+
+void
+tgsi_dump_str(
+ const struct tgsi_token *tokens,
+ uint flags,
+ char *str,
+ size_t size)
+{
+ struct str_dump_ctx ctx;
+
+ ctx.base.iter.prolog = prolog;
+ ctx.base.iter.iterate_instruction = iter_instruction;
+ ctx.base.iter.iterate_declaration = iter_declaration;
+ ctx.base.iter.iterate_immediate = iter_immediate;
+ ctx.base.iter.epilog = NULL;
+
+ ctx.base.instno = 0;
+ ctx.base.indent = 0;
+ ctx.base.printf = &str_dump_ctx_printf;
+ ctx.base.indentation = 0;
+
+ ctx.str = str;
+ ctx.str[0] = 0;
+ ctx.ptr = str;
+ ctx.left = (int)size;
+
+ tgsi_iterate_shader( tokens, &ctx.base.iter );
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.h b/src/gallium/auxiliary/tgsi/tgsi_dump.h
new file mode 100644
index 0000000000..ad1e647ec9
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_DUMP_H
+#define TGSI_DUMP_H
+
+#include "pipe/p_shader_tokens.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+void
+tgsi_dump_str(
+ const struct tgsi_token *tokens,
+ uint flags,
+ char *str,
+ size_t size);
+
+void
+tgsi_dump(
+ const struct tgsi_token *tokens,
+ uint flags );
+
+struct tgsi_full_immediate;
+struct tgsi_full_instruction;
+struct tgsi_full_declaration;
+
+void
+tgsi_dump_immediate(
+ const struct tgsi_full_immediate *imm );
+
+void
+tgsi_dump_instruction(
+ const struct tgsi_full_instruction *inst,
+ uint instno );
+
+void
+tgsi_dump_declaration(
+ const struct tgsi_full_declaration *decl );
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_DUMP_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump_c.c b/src/gallium/auxiliary/tgsi/tgsi_dump_c.c
new file mode 100644
index 0000000000..4a9c02b141
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump_c.c
@@ -0,0 +1,720 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "util/u_string.h"
+#include "tgsi_dump_c.h"
+#include "tgsi_build.h"
+#include "tgsi_info.h"
+#include "tgsi_parse.h"
+
+static void
+dump_enum(
+ const unsigned e,
+ const char **enums,
+ const unsigned enums_count )
+{
+ if (e >= enums_count) {
+ debug_printf( "%u", e );
+ }
+ else {
+ debug_printf( "%s", enums[e] );
+ }
+}
+
+#define EOL() debug_printf( "\n" )
+#define TXT(S) debug_printf( "%s", S )
+#define CHR(C) debug_printf( "%c", C )
+#define UIX(I) debug_printf( "0x%x", I )
+#define UID(I) debug_printf( "%u", I )
+#define SID(I) debug_printf( "%d", I )
+#define FLT(F) debug_printf( "%10.4f", F )
+#define ENM(E,ENUMS) dump_enum( E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
+
+static const char *TGSI_PROCESSOR_TYPES[] =
+{
+ "PROCESSOR_FRAGMENT",
+ "PROCESSOR_VERTEX",
+ "PROCESSOR_GEOMETRY"
+};
+
+static const char *TGSI_TOKEN_TYPES[] =
+{
+ "TOKEN_TYPE_DECLARATION",
+ "TOKEN_TYPE_IMMEDIATE",
+ "TOKEN_TYPE_INSTRUCTION"
+};
+
+static const char *TGSI_FILES[TGSI_FILE_COUNT] =
+{
+ "FILE_NULL",
+ "FILE_CONSTANT",
+ "FILE_INPUT",
+ "FILE_OUTPUT",
+ "FILE_TEMPORARY",
+ "FILE_SAMPLER",
+ "FILE_ADDRESS",
+ "FILE_IMMEDIATE",
+ "FILE_LOOP"
+};
+
+static const char *TGSI_INTERPOLATES[] =
+{
+ "INTERPOLATE_CONSTANT",
+ "INTERPOLATE_LINEAR",
+ "INTERPOLATE_PERSPECTIVE"
+};
+
+static const char *TGSI_SEMANTICS[] =
+{
+ "SEMANTIC_POSITION",
+ "SEMANTIC_COLOR",
+ "SEMANTIC_BCOLOR",
+ "SEMANTIC_FOG",
+ "SEMANTIC_PSIZE",
+ "SEMANTIC_GENERIC",
+ "SEMANTIC_NORMAL"
+};
+
+static const char *TGSI_IMMS[] =
+{
+ "IMM_FLOAT32"
+};
+
+static const char *TGSI_SATS[] =
+{
+ "SAT_NONE",
+ "SAT_ZERO_ONE",
+ "SAT_MINUS_PLUS_ONE"
+};
+
+static const char *TGSI_INSTRUCTION_EXTS[] =
+{
+ "INSTRUCTION_EXT_TYPE_NV",
+ "INSTRUCTION_EXT_TYPE_LABEL",
+ "INSTRUCTION_EXT_TYPE_TEXTURE"
+};
+
+static const char *TGSI_PRECISIONS[] =
+{
+ "PRECISION_DEFAULT",
+ "PRECISION_FLOAT32",
+ "PRECISION_FLOAT16",
+ "PRECISION_FIXED12"
+};
+
+static const char *TGSI_CCS[] =
+{
+ "CC_GT",
+ "CC_EQ",
+ "CC_LT",
+ "CC_UN",
+ "CC_GE",
+ "CC_LE",
+ "CC_NE",
+ "CC_TR",
+ "CC_FL"
+};
+
+static const char *TGSI_SWIZZLES[] =
+{
+ "SWIZZLE_X",
+ "SWIZZLE_Y",
+ "SWIZZLE_Z",
+ "SWIZZLE_W"
+};
+
+static const char *TGSI_TEXTURES[] =
+{
+ "TEXTURE_UNKNOWN",
+ "TEXTURE_1D",
+ "TEXTURE_2D",
+ "TEXTURE_3D",
+ "TEXTURE_CUBE",
+ "TEXTURE_RECT",
+ "TEXTURE_SHADOW1D",
+ "TEXTURE_SHADOW2D",
+ "TEXTURE_SHADOWRECT"
+};
+
+static const char *TGSI_SRC_REGISTER_EXTS[] =
+{
+ "SRC_REGISTER_EXT_TYPE_SWZ",
+ "SRC_REGISTER_EXT_TYPE_MOD"
+};
+
+static const char *TGSI_EXTSWIZZLES[] =
+{
+ "EXTSWIZZLE_X",
+ "EXTSWIZZLE_Y",
+ "EXTSWIZZLE_Z",
+ "EXTSWIZZLE_W",
+ "EXTSWIZZLE_ZERO",
+ "EXTSWIZZLE_ONE"
+};
+
+static const char *TGSI_WRITEMASKS[] =
+{
+ "0",
+ "WRITEMASK_X",
+ "WRITEMASK_Y",
+ "WRITEMASK_XY",
+ "WRITEMASK_Z",
+ "WRITEMASK_XZ",
+ "WRITEMASK_YZ",
+ "WRITEMASK_XYZ",
+ "WRITEMASK_W",
+ "WRITEMASK_XW",
+ "WRITEMASK_YW",
+ "WRITEMASK_XYW",
+ "WRITEMASK_ZW",
+ "WRITEMASK_XZW",
+ "WRITEMASK_YZW",
+ "WRITEMASK_XYZW"
+};
+
+static const char *TGSI_DST_REGISTER_EXTS[] =
+{
+ "DST_REGISTER_EXT_TYPE_CONDCODE",
+ "DST_REGISTER_EXT_TYPE_MODULATE"
+};
+
+static const char *TGSI_MODULATES[] =
+{
+ "MODULATE_1X",
+ "MODULATE_2X",
+ "MODULATE_4X",
+ "MODULATE_8X",
+ "MODULATE_HALF",
+ "MODULATE_QUARTER",
+ "MODULATE_EIGHTH"
+};
+
+static void
+dump_declaration_verbose(
+ struct tgsi_full_declaration *decl,
+ unsigned ignored,
+ unsigned deflt,
+ struct tgsi_full_declaration *fd )
+{
+ TXT( "\nFile : " );
+ ENM( decl->Declaration.File, TGSI_FILES );
+ if( deflt || fd->Declaration.UsageMask != decl->Declaration.UsageMask ) {
+ TXT( "\nUsageMask : " );
+ if( decl->Declaration.UsageMask & TGSI_WRITEMASK_X ) {
+ CHR( 'X' );
+ }
+ if( decl->Declaration.UsageMask & TGSI_WRITEMASK_Y ) {
+ CHR( 'Y' );
+ }
+ if( decl->Declaration.UsageMask & TGSI_WRITEMASK_Z ) {
+ CHR( 'Z' );
+ }
+ if( decl->Declaration.UsageMask & TGSI_WRITEMASK_W ) {
+ CHR( 'W' );
+ }
+ }
+ if( deflt || fd->Declaration.Interpolate != decl->Declaration.Interpolate ) {
+ TXT( "\nInterpolate: " );
+ ENM( decl->Declaration.Interpolate, TGSI_INTERPOLATES );
+ }
+ if( deflt || fd->Declaration.Semantic != decl->Declaration.Semantic ) {
+ TXT( "\nSemantic : " );
+ UID( decl->Declaration.Semantic );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( decl->Declaration.Padding );
+ }
+
+ EOL();
+ TXT( "\nFirst: " );
+ UID( decl->DeclarationRange.First );
+ TXT( "\nLast : " );
+ UID( decl->DeclarationRange.Last );
+
+ if( decl->Declaration.Semantic ) {
+ EOL();
+ TXT( "\nSemanticName : " );
+ ENM( decl->Semantic.SemanticName, TGSI_SEMANTICS );
+ TXT( "\nSemanticIndex: " );
+ UID( decl->Semantic.SemanticIndex );
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( decl->Semantic.Padding );
+ }
+ }
+}
+
+static void
+dump_immediate_verbose(
+ struct tgsi_full_immediate *imm,
+ unsigned ignored )
+{
+ unsigned i;
+
+ TXT( "\nDataType : " );
+ ENM( imm->Immediate.DataType, TGSI_IMMS );
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( imm->Immediate.Padding );
+ }
+
+ assert( imm->Immediate.NrTokens <= 4 + 1 );
+ for( i = 0; i < imm->Immediate.NrTokens - 1; i++ ) {
+ EOL();
+ switch( imm->Immediate.DataType ) {
+ case TGSI_IMM_FLOAT32:
+ TXT( "\nFloat: " );
+ FLT( imm->u[i].Float );
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+}
+
+static void
+dump_instruction_verbose(
+ struct tgsi_full_instruction *inst,
+ unsigned ignored,
+ unsigned deflt,
+ struct tgsi_full_instruction *fi )
+{
+ unsigned i;
+
+ TXT( "\nOpcode : OPCODE_" );
+ TXT( tgsi_get_opcode_info( inst->Instruction.Opcode )->mnemonic );
+ if( deflt || fi->Instruction.Saturate != inst->Instruction.Saturate ) {
+ TXT( "\nSaturate : " );
+ ENM( inst->Instruction.Saturate, TGSI_SATS );
+ }
+ if( deflt || fi->Instruction.NumDstRegs != inst->Instruction.NumDstRegs ) {
+ TXT( "\nNumDstRegs : " );
+ UID( inst->Instruction.NumDstRegs );
+ }
+ if( deflt || fi->Instruction.NumSrcRegs != inst->Instruction.NumSrcRegs ) {
+ TXT( "\nNumSrcRegs : " );
+ UID( inst->Instruction.NumSrcRegs );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( inst->Instruction.Padding );
+ }
+
+ if( deflt || tgsi_compare_instruction_ext_nv( inst->InstructionExtNv, fi->InstructionExtNv ) ) {
+ EOL();
+ TXT( "\nType : " );
+ ENM( inst->InstructionExtNv.Type, TGSI_INSTRUCTION_EXTS );
+ if( deflt || fi->InstructionExtNv.Precision != inst->InstructionExtNv.Precision ) {
+ TXT( "\nPrecision : " );
+ ENM( inst->InstructionExtNv.Precision, TGSI_PRECISIONS );
+ }
+ if( deflt || fi->InstructionExtNv.CondDstIndex != inst->InstructionExtNv.CondDstIndex ) {
+ TXT( "\nCondDstIndex : " );
+ UID( inst->InstructionExtNv.CondDstIndex );
+ }
+ if( deflt || fi->InstructionExtNv.CondFlowIndex != inst->InstructionExtNv.CondFlowIndex ) {
+ TXT( "\nCondFlowIndex : " );
+ UID( inst->InstructionExtNv.CondFlowIndex );
+ }
+ if( deflt || fi->InstructionExtNv.CondMask != inst->InstructionExtNv.CondMask ) {
+ TXT( "\nCondMask : " );
+ ENM( inst->InstructionExtNv.CondMask, TGSI_CCS );
+ }
+ if( deflt || fi->InstructionExtNv.CondSwizzleX != inst->InstructionExtNv.CondSwizzleX ) {
+ TXT( "\nCondSwizzleX : " );
+ ENM( inst->InstructionExtNv.CondSwizzleX, TGSI_SWIZZLES );
+ }
+ if( deflt || fi->InstructionExtNv.CondSwizzleY != inst->InstructionExtNv.CondSwizzleY ) {
+ TXT( "\nCondSwizzleY : " );
+ ENM( inst->InstructionExtNv.CondSwizzleY, TGSI_SWIZZLES );
+ }
+ if( deflt || fi->InstructionExtNv.CondSwizzleZ != inst->InstructionExtNv.CondSwizzleZ ) {
+ TXT( "\nCondSwizzleZ : " );
+ ENM( inst->InstructionExtNv.CondSwizzleZ, TGSI_SWIZZLES );
+ }
+ if( deflt || fi->InstructionExtNv.CondSwizzleW != inst->InstructionExtNv.CondSwizzleW ) {
+ TXT( "\nCondSwizzleW : " );
+ ENM( inst->InstructionExtNv.CondSwizzleW, TGSI_SWIZZLES );
+ }
+ if( deflt || fi->InstructionExtNv.CondDstUpdate != inst->InstructionExtNv.CondDstUpdate ) {
+ TXT( "\nCondDstUpdate : " );
+ UID( inst->InstructionExtNv.CondDstUpdate );
+ }
+ if( deflt || fi->InstructionExtNv.CondFlowEnable != inst->InstructionExtNv.CondFlowEnable ) {
+ TXT( "\nCondFlowEnable: " );
+ UID( inst->InstructionExtNv.CondFlowEnable );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( inst->InstructionExtNv.Padding );
+ if( deflt || fi->InstructionExtNv.Extended != inst->InstructionExtNv.Extended ) {
+ TXT( "\nExtended : " );
+ UID( inst->InstructionExtNv.Extended );
+ }
+ }
+ }
+
+ if( deflt || tgsi_compare_instruction_ext_label( inst->InstructionExtLabel, fi->InstructionExtLabel ) ) {
+ EOL();
+ TXT( "\nType : " );
+ ENM( inst->InstructionExtLabel.Type, TGSI_INSTRUCTION_EXTS );
+ if( deflt || fi->InstructionExtLabel.Label != inst->InstructionExtLabel.Label ) {
+ TXT( "\nLabel : " );
+ UID( inst->InstructionExtLabel.Label );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( inst->InstructionExtLabel.Padding );
+ if( deflt || fi->InstructionExtLabel.Extended != inst->InstructionExtLabel.Extended ) {
+ TXT( "\nExtended: " );
+ UID( inst->InstructionExtLabel.Extended );
+ }
+ }
+ }
+
+ if( deflt || tgsi_compare_instruction_ext_texture( inst->InstructionExtTexture, fi->InstructionExtTexture ) ) {
+ EOL();
+ TXT( "\nType : " );
+ ENM( inst->InstructionExtTexture.Type, TGSI_INSTRUCTION_EXTS );
+ if( deflt || fi->InstructionExtTexture.Texture != inst->InstructionExtTexture.Texture ) {
+ TXT( "\nTexture : " );
+ ENM( inst->InstructionExtTexture.Texture, TGSI_TEXTURES );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( inst->InstructionExtTexture.Padding );
+ if( deflt || fi->InstructionExtTexture.Extended != inst->InstructionExtTexture.Extended ) {
+ TXT( "\nExtended: " );
+ UID( inst->InstructionExtTexture.Extended );
+ }
+ }
+ }
+
+ for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
+ struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
+ struct tgsi_full_dst_register *fd = &fi->FullDstRegisters[i];
+
+ EOL();
+ TXT( "\nFile : " );
+ ENM( dst->DstRegister.File, TGSI_FILES );
+ if( deflt || fd->DstRegister.WriteMask != dst->DstRegister.WriteMask ) {
+ TXT( "\nWriteMask: " );
+ ENM( dst->DstRegister.WriteMask, TGSI_WRITEMASKS );
+ }
+ if( ignored ) {
+ if( deflt || fd->DstRegister.Indirect != dst->DstRegister.Indirect ) {
+ TXT( "\nIndirect : " );
+ UID( dst->DstRegister.Indirect );
+ }
+ if( deflt || fd->DstRegister.Dimension != dst->DstRegister.Dimension ) {
+ TXT( "\nDimension: " );
+ UID( dst->DstRegister.Dimension );
+ }
+ }
+ if( deflt || fd->DstRegister.Index != dst->DstRegister.Index ) {
+ TXT( "\nIndex : " );
+ SID( dst->DstRegister.Index );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( dst->DstRegister.Padding );
+ if( deflt || fd->DstRegister.Extended != dst->DstRegister.Extended ) {
+ TXT( "\nExtended : " );
+ UID( dst->DstRegister.Extended );
+ }
+ }
+
+ if( deflt || tgsi_compare_dst_register_ext_concode( dst->DstRegisterExtConcode, fd->DstRegisterExtConcode ) ) {
+ EOL();
+ TXT( "\nType : " );
+ ENM( dst->DstRegisterExtConcode.Type, TGSI_DST_REGISTER_EXTS );
+ if( deflt || fd->DstRegisterExtConcode.CondMask != dst->DstRegisterExtConcode.CondMask ) {
+ TXT( "\nCondMask : " );
+ ENM( dst->DstRegisterExtConcode.CondMask, TGSI_CCS );
+ }
+ if( deflt || fd->DstRegisterExtConcode.CondSwizzleX != dst->DstRegisterExtConcode.CondSwizzleX ) {
+ TXT( "\nCondSwizzleX: " );
+ ENM( dst->DstRegisterExtConcode.CondSwizzleX, TGSI_SWIZZLES );
+ }
+ if( deflt || fd->DstRegisterExtConcode.CondSwizzleY != dst->DstRegisterExtConcode.CondSwizzleY ) {
+ TXT( "\nCondSwizzleY: " );
+ ENM( dst->DstRegisterExtConcode.CondSwizzleY, TGSI_SWIZZLES );
+ }
+ if( deflt || fd->DstRegisterExtConcode.CondSwizzleZ != dst->DstRegisterExtConcode.CondSwizzleZ ) {
+ TXT( "\nCondSwizzleZ: " );
+ ENM( dst->DstRegisterExtConcode.CondSwizzleZ, TGSI_SWIZZLES );
+ }
+ if( deflt || fd->DstRegisterExtConcode.CondSwizzleW != dst->DstRegisterExtConcode.CondSwizzleW ) {
+ TXT( "\nCondSwizzleW: " );
+ ENM( dst->DstRegisterExtConcode.CondSwizzleW, TGSI_SWIZZLES );
+ }
+ if( deflt || fd->DstRegisterExtConcode.CondSrcIndex != dst->DstRegisterExtConcode.CondSrcIndex ) {
+ TXT( "\nCondSrcIndex: " );
+ UID( dst->DstRegisterExtConcode.CondSrcIndex );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( dst->DstRegisterExtConcode.Padding );
+ if( deflt || fd->DstRegisterExtConcode.Extended != dst->DstRegisterExtConcode.Extended ) {
+ TXT( "\nExtended : " );
+ UID( dst->DstRegisterExtConcode.Extended );
+ }
+ }
+ }
+
+ if( deflt || tgsi_compare_dst_register_ext_modulate( dst->DstRegisterExtModulate, fd->DstRegisterExtModulate ) ) {
+ EOL();
+ TXT( "\nType : " );
+ ENM( dst->DstRegisterExtModulate.Type, TGSI_DST_REGISTER_EXTS );
+ if( deflt || fd->DstRegisterExtModulate.Modulate != dst->DstRegisterExtModulate.Modulate ) {
+ TXT( "\nModulate: " );
+ ENM( dst->DstRegisterExtModulate.Modulate, TGSI_MODULATES );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( dst->DstRegisterExtModulate.Padding );
+ if( deflt || fd->DstRegisterExtModulate.Extended != dst->DstRegisterExtModulate.Extended ) {
+ TXT( "\nExtended: " );
+ UID( dst->DstRegisterExtModulate.Extended );
+ }
+ }
+ }
+ }
+
+ for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
+ struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
+ struct tgsi_full_src_register *fs = &fi->FullSrcRegisters[i];
+
+ EOL();
+ TXT( "\nFile : ");
+ ENM( src->SrcRegister.File, TGSI_FILES );
+ if( deflt || fs->SrcRegister.SwizzleX != src->SrcRegister.SwizzleX ) {
+ TXT( "\nSwizzleX : " );
+ ENM( src->SrcRegister.SwizzleX, TGSI_SWIZZLES );
+ }
+ if( deflt || fs->SrcRegister.SwizzleY != src->SrcRegister.SwizzleY ) {
+ TXT( "\nSwizzleY : " );
+ ENM( src->SrcRegister.SwizzleY, TGSI_SWIZZLES );
+ }
+ if( deflt || fs->SrcRegister.SwizzleZ != src->SrcRegister.SwizzleZ ) {
+ TXT( "\nSwizzleZ : " );
+ ENM( src->SrcRegister.SwizzleZ, TGSI_SWIZZLES );
+ }
+ if( deflt || fs->SrcRegister.SwizzleW != src->SrcRegister.SwizzleW ) {
+ TXT( "\nSwizzleW : " );
+ ENM( src->SrcRegister.SwizzleW, TGSI_SWIZZLES );
+ }
+ if( deflt || fs->SrcRegister.Negate != src->SrcRegister.Negate ) {
+ TXT( "\nNegate : " );
+ UID( src->SrcRegister.Negate );
+ }
+ if( ignored ) {
+ if( deflt || fs->SrcRegister.Indirect != src->SrcRegister.Indirect ) {
+ TXT( "\nIndirect : " );
+ UID( src->SrcRegister.Indirect );
+ }
+ if( deflt || fs->SrcRegister.Dimension != src->SrcRegister.Dimension ) {
+ TXT( "\nDimension: " );
+ UID( src->SrcRegister.Dimension );
+ }
+ }
+ if( deflt || fs->SrcRegister.Index != src->SrcRegister.Index ) {
+ TXT( "\nIndex : " );
+ SID( src->SrcRegister.Index );
+ }
+ if( ignored ) {
+ if( deflt || fs->SrcRegister.Extended != src->SrcRegister.Extended ) {
+ TXT( "\nExtended : " );
+ UID( src->SrcRegister.Extended );
+ }
+ }
+
+ if( deflt || tgsi_compare_src_register_ext_swz( src->SrcRegisterExtSwz, fs->SrcRegisterExtSwz ) ) {
+ EOL();
+ TXT( "\nType : " );
+ ENM( src->SrcRegisterExtSwz.Type, TGSI_SRC_REGISTER_EXTS );
+ if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleX != src->SrcRegisterExtSwz.ExtSwizzleX ) {
+ TXT( "\nExtSwizzleX: " );
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleX, TGSI_EXTSWIZZLES );
+ }
+ if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleY != src->SrcRegisterExtSwz.ExtSwizzleY ) {
+ TXT( "\nExtSwizzleY: " );
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleY, TGSI_EXTSWIZZLES );
+ }
+ if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleZ != src->SrcRegisterExtSwz.ExtSwizzleZ ) {
+ TXT( "\nExtSwizzleZ: " );
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, TGSI_EXTSWIZZLES );
+ }
+ if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleW != src->SrcRegisterExtSwz.ExtSwizzleW ) {
+ TXT( "\nExtSwizzleW: " );
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleW, TGSI_EXTSWIZZLES );
+ }
+ if( deflt || fs->SrcRegisterExtSwz.NegateX != src->SrcRegisterExtSwz.NegateX ) {
+ TXT( "\nNegateX : " );
+ UID( src->SrcRegisterExtSwz.NegateX );
+ }
+ if( deflt || fs->SrcRegisterExtSwz.NegateY != src->SrcRegisterExtSwz.NegateY ) {
+ TXT( "\nNegateY : " );
+ UID( src->SrcRegisterExtSwz.NegateY );
+ }
+ if( deflt || fs->SrcRegisterExtSwz.NegateZ != src->SrcRegisterExtSwz.NegateZ ) {
+ TXT( "\nNegateZ : " );
+ UID( src->SrcRegisterExtSwz.NegateZ );
+ }
+ if( deflt || fs->SrcRegisterExtSwz.NegateW != src->SrcRegisterExtSwz.NegateW ) {
+ TXT( "\nNegateW : " );
+ UID( src->SrcRegisterExtSwz.NegateW );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( src->SrcRegisterExtSwz.Padding );
+ if( deflt || fs->SrcRegisterExtSwz.Extended != src->SrcRegisterExtSwz.Extended ) {
+ TXT( "\nExtended : " );
+ UID( src->SrcRegisterExtSwz.Extended );
+ }
+ }
+ }
+
+ if( deflt || tgsi_compare_src_register_ext_mod( src->SrcRegisterExtMod, fs->SrcRegisterExtMod ) ) {
+ EOL();
+ TXT( "\nType : " );
+ ENM( src->SrcRegisterExtMod.Type, TGSI_SRC_REGISTER_EXTS );
+ if( deflt || fs->SrcRegisterExtMod.Complement != src->SrcRegisterExtMod.Complement ) {
+ TXT( "\nComplement: " );
+ UID( src->SrcRegisterExtMod.Complement );
+ }
+ if( deflt || fs->SrcRegisterExtMod.Bias != src->SrcRegisterExtMod.Bias ) {
+ TXT( "\nBias : " );
+ UID( src->SrcRegisterExtMod.Bias );
+ }
+ if( deflt || fs->SrcRegisterExtMod.Scale2X != src->SrcRegisterExtMod.Scale2X ) {
+ TXT( "\nScale2X : " );
+ UID( src->SrcRegisterExtMod.Scale2X );
+ }
+ if( deflt || fs->SrcRegisterExtMod.Absolute != src->SrcRegisterExtMod.Absolute ) {
+ TXT( "\nAbsolute : " );
+ UID( src->SrcRegisterExtMod.Absolute );
+ }
+ if( deflt || fs->SrcRegisterExtMod.Negate != src->SrcRegisterExtMod.Negate ) {
+ TXT( "\nNegate : " );
+ UID( src->SrcRegisterExtMod.Negate );
+ }
+ if( ignored ) {
+ TXT( "\nPadding : " );
+ UIX( src->SrcRegisterExtMod.Padding );
+ if( deflt || fs->SrcRegisterExtMod.Extended != src->SrcRegisterExtMod.Extended ) {
+ TXT( "\nExtended : " );
+ UID( src->SrcRegisterExtMod.Extended );
+ }
+ }
+ }
+ }
+}
+
+void
+tgsi_dump_c(
+ const struct tgsi_token *tokens,
+ uint flags )
+{
+ struct tgsi_parse_context parse;
+ struct tgsi_full_instruction fi;
+ struct tgsi_full_declaration fd;
+ uint ignored = flags & TGSI_DUMP_C_IGNORED;
+ uint deflt = flags & TGSI_DUMP_C_DEFAULT;
+
+ tgsi_parse_init( &parse, tokens );
+
+ TXT( "tgsi-dump begin -----------------" );
+
+ TXT( "\nMajorVersion: " );
+ UID( parse.FullVersion.Version.MajorVersion );
+ TXT( "\nMinorVersion: " );
+ UID( parse.FullVersion.Version.MinorVersion );
+ EOL();
+
+ TXT( "\nHeaderSize: " );
+ UID( parse.FullHeader.Header.HeaderSize );
+ TXT( "\nBodySize : " );
+ UID( parse.FullHeader.Header.BodySize );
+ TXT( "\nProcessor : " );
+ ENM( parse.FullHeader.Processor.Processor, TGSI_PROCESSOR_TYPES );
+ EOL();
+
+ fi = tgsi_default_full_instruction();
+ fd = tgsi_default_full_declaration();
+
+ while( !tgsi_parse_end_of_tokens( &parse ) ) {
+ tgsi_parse_token( &parse );
+
+ TXT( "\nType : " );
+ ENM( parse.FullToken.Token.Type, TGSI_TOKEN_TYPES );
+ if( ignored ) {
+ TXT( "\nSize : " );
+ UID( parse.FullToken.Token.NrTokens );
+ if( deflt || parse.FullToken.Token.Extended ) {
+ TXT( "\nExtended : " );
+ UID( parse.FullToken.Token.Extended );
+ }
+ }
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ dump_declaration_verbose(
+ &parse.FullToken.FullDeclaration,
+ ignored,
+ deflt,
+ &fd );
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ dump_immediate_verbose(
+ &parse.FullToken.FullImmediate,
+ ignored );
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ dump_instruction_verbose(
+ &parse.FullToken.FullInstruction,
+ ignored,
+ deflt,
+ &fi );
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ EOL();
+ }
+
+ TXT( "\ntgsi-dump end -------------------\n" );
+
+ tgsi_parse_free( &parse );
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump_c.h b/src/gallium/auxiliary/tgsi/tgsi_dump_c.h
new file mode 100644
index 0000000000..d91cd35b3b
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump_c.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_DUMP_C_H
+#define TGSI_DUMP_C_H
+
+#include "pipe/p_shader_tokens.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+#define TGSI_DUMP_C_IGNORED 1
+#define TGSI_DUMP_C_DEFAULT 2
+
+void
+tgsi_dump_c(
+ const struct tgsi_token *tokens,
+ uint flags );
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_DUMP_C_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
new file mode 100644
index 0000000000..c79c56debd
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -0,0 +1,3311 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * TGSI interpreter/executor.
+ *
+ * Flow control information:
+ *
+ * Since we operate on 'quads' (4 pixels or 4 vertices in parallel)
+ * flow control statements (IF/ELSE/ENDIF, LOOP/ENDLOOP) require special
+ * care since a condition may be true for some quad components but false
+ * for other components.
+ *
+ * We basically execute all statements (even if they're in the part of
+ * an IF/ELSE clause that's "not taken") and use a special mask to
+ * control writing to destination registers. This is the ExecMask.
+ * See store_dest().
+ *
+ * The ExecMask is computed from three other masks (CondMask, LoopMask and
+ * ContMask) which are controlled by the flow control instructions (namely:
+ * (IF/ELSE/ENDIF, LOOP/ENDLOOP and CONT).
+ *
+ *
+ * Authors:
+ * Michal Krol
+ * Brian Paul
+ */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi_exec.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#define FAST_MATH 1
+
+/** for tgsi_full_instruction::Flags */
+#define SOA_DEPENDENCY_FLAG 0x1
+
+#define TILE_TOP_LEFT 0
+#define TILE_TOP_RIGHT 1
+#define TILE_BOTTOM_LEFT 2
+#define TILE_BOTTOM_RIGHT 3
+
+#define CHAN_X 0
+#define CHAN_Y 1
+#define CHAN_Z 2
+#define CHAN_W 3
+
+/*
+ * Shorthand locations of various utility registers (_I = Index, _C = Channel)
+ */
+#define TEMP_0_I TGSI_EXEC_TEMP_00000000_I
+#define TEMP_0_C TGSI_EXEC_TEMP_00000000_C
+#define TEMP_7F_I TGSI_EXEC_TEMP_7FFFFFFF_I
+#define TEMP_7F_C TGSI_EXEC_TEMP_7FFFFFFF_C
+#define TEMP_80_I TGSI_EXEC_TEMP_80000000_I
+#define TEMP_80_C TGSI_EXEC_TEMP_80000000_C
+#define TEMP_FF_I TGSI_EXEC_TEMP_FFFFFFFF_I
+#define TEMP_FF_C TGSI_EXEC_TEMP_FFFFFFFF_C
+#define TEMP_1_I TGSI_EXEC_TEMP_ONE_I
+#define TEMP_1_C TGSI_EXEC_TEMP_ONE_C
+#define TEMP_2_I TGSI_EXEC_TEMP_TWO_I
+#define TEMP_2_C TGSI_EXEC_TEMP_TWO_C
+#define TEMP_128_I TGSI_EXEC_TEMP_128_I
+#define TEMP_128_C TGSI_EXEC_TEMP_128_C
+#define TEMP_M128_I TGSI_EXEC_TEMP_MINUS_128_I
+#define TEMP_M128_C TGSI_EXEC_TEMP_MINUS_128_C
+#define TEMP_KILMASK_I TGSI_EXEC_TEMP_KILMASK_I
+#define TEMP_KILMASK_C TGSI_EXEC_TEMP_KILMASK_C
+#define TEMP_OUTPUT_I TGSI_EXEC_TEMP_OUTPUT_I
+#define TEMP_OUTPUT_C TGSI_EXEC_TEMP_OUTPUT_C
+#define TEMP_PRIMITIVE_I TGSI_EXEC_TEMP_PRIMITIVE_I
+#define TEMP_PRIMITIVE_C TGSI_EXEC_TEMP_PRIMITIVE_C
+#define TEMP_CC_I TGSI_EXEC_TEMP_CC_I
+#define TEMP_CC_C TGSI_EXEC_TEMP_CC_C
+#define TEMP_3_I TGSI_EXEC_TEMP_THREE_I
+#define TEMP_3_C TGSI_EXEC_TEMP_THREE_C
+#define TEMP_HALF_I TGSI_EXEC_TEMP_HALF_I
+#define TEMP_HALF_C TGSI_EXEC_TEMP_HALF_C
+#define TEMP_R0 TGSI_EXEC_TEMP_R0
+
+#define IS_CHANNEL_ENABLED(INST, CHAN)\
+ ((INST).FullDstRegisters[0].DstRegister.WriteMask & (1 << (CHAN)))
+
+#define IS_CHANNEL_ENABLED2(INST, CHAN)\
+ ((INST).FullDstRegisters[1].DstRegister.WriteMask & (1 << (CHAN)))
+
+#define FOR_EACH_ENABLED_CHANNEL(INST, CHAN)\
+ for (CHAN = 0; CHAN < NUM_CHANNELS; CHAN++)\
+ if (IS_CHANNEL_ENABLED( INST, CHAN ))
+
+#define FOR_EACH_ENABLED_CHANNEL2(INST, CHAN)\
+ for (CHAN = 0; CHAN < NUM_CHANNELS; CHAN++)\
+ if (IS_CHANNEL_ENABLED2( INST, CHAN ))
+
+
+/** The execution mask depends on the conditional mask and the loop mask */
+#define UPDATE_EXEC_MASK(MACH) \
+ MACH->ExecMask = MACH->CondMask & MACH->LoopMask & MACH->ContMask & MACH->FuncMask
+
+
+static const union tgsi_exec_channel ZeroVec =
+ { { 0.0, 0.0, 0.0, 0.0 } };
+
+
+#ifdef DEBUG
+static void
+check_inf_or_nan(const union tgsi_exec_channel *chan)
+{
+ assert(!util_is_inf_or_nan(chan->f[0]));
+ assert(!util_is_inf_or_nan(chan->f[1]));
+ assert(!util_is_inf_or_nan(chan->f[2]));
+ assert(!util_is_inf_or_nan(chan->f[3]));
+}
+#endif
+
+
+#ifdef DEBUG
+static void
+print_chan(const char *msg, const union tgsi_exec_channel *chan)
+{
+ debug_printf("%s = {%f, %f, %f, %f}\n",
+ msg, chan->f[0], chan->f[1], chan->f[2], chan->f[3]);
+}
+#endif
+
+
+#ifdef DEBUG
+static void
+print_temp(const struct tgsi_exec_machine *mach, uint index)
+{
+ const struct tgsi_exec_vector *tmp = &mach->Temps[index];
+ int i;
+ debug_printf("Temp[%u] =\n", index);
+ for (i = 0; i < 4; i++) {
+ debug_printf(" %c: { %f, %f, %f, %f }\n",
+ "XYZW"[i],
+ tmp->xyzw[i].f[0],
+ tmp->xyzw[i].f[1],
+ tmp->xyzw[i].f[2],
+ tmp->xyzw[i].f[3]);
+ }
+}
+#endif
+
+
+/**
+ * Check if there's a potential src/dst register data dependency when
+ * using SOA execution.
+ * Example:
+ * MOV T, T.yxwz;
+ * This would expand into:
+ * MOV t0, t1;
+ * MOV t1, t0;
+ * MOV t2, t3;
+ * MOV t3, t2;
+ * The second instruction will have the wrong value for t0 if executed as-is.
+ */
+boolean
+tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst)
+{
+ uint i, chan;
+
+ uint writemask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ if (writemask == TGSI_WRITEMASK_X ||
+ writemask == TGSI_WRITEMASK_Y ||
+ writemask == TGSI_WRITEMASK_Z ||
+ writemask == TGSI_WRITEMASK_W ||
+ writemask == TGSI_WRITEMASK_NONE) {
+ /* no chance of data dependency */
+ return FALSE;
+ }
+
+ /* loop over src regs */
+ for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+ if ((inst->FullSrcRegisters[i].SrcRegister.File ==
+ inst->FullDstRegisters[0].DstRegister.File) &&
+ (inst->FullSrcRegisters[i].SrcRegister.Index ==
+ inst->FullDstRegisters[0].DstRegister.Index)) {
+ /* loop over dest channels */
+ uint channelsWritten = 0x0;
+ FOR_EACH_ENABLED_CHANNEL(*inst, chan) {
+ /* check if we're reading a channel that's been written */
+ uint swizzle = tgsi_util_get_full_src_register_extswizzle(&inst->FullSrcRegisters[i], chan);
+ if (swizzle <= TGSI_SWIZZLE_W &&
+ (channelsWritten & (1 << swizzle))) {
+ return TRUE;
+ }
+
+ channelsWritten |= (1 << chan);
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/**
+ * Initialize machine state by expanding tokens to full instructions,
+ * allocating temporary storage, setting up constants, etc.
+ * After this, we can call tgsi_exec_machine_run() many times.
+ */
+void
+tgsi_exec_machine_bind_shader(
+ struct tgsi_exec_machine *mach,
+ const struct tgsi_token *tokens,
+ uint numSamplers,
+ struct tgsi_sampler **samplers)
+{
+ uint k;
+ struct tgsi_parse_context parse;
+ struct tgsi_exec_labels *labels = &mach->Labels;
+ struct tgsi_full_instruction *instructions;
+ struct tgsi_full_declaration *declarations;
+ uint maxInstructions = 10, numInstructions = 0;
+ uint maxDeclarations = 10, numDeclarations = 0;
+ uint instno = 0;
+
+#if 0
+ tgsi_dump(tokens, 0);
+#endif
+
+ util_init_math();
+
+ mach->Tokens = tokens;
+ mach->Samplers = samplers;
+
+ k = tgsi_parse_init (&parse, mach->Tokens);
+ if (k != TGSI_PARSE_OK) {
+ debug_printf( "Problem parsing!\n" );
+ return;
+ }
+
+ mach->Processor = parse.FullHeader.Processor.Processor;
+ mach->ImmLimit = 0;
+ labels->count = 0;
+
+ declarations = (struct tgsi_full_declaration *)
+ MALLOC( maxDeclarations * sizeof(struct tgsi_full_declaration) );
+
+ if (!declarations) {
+ return;
+ }
+
+ instructions = (struct tgsi_full_instruction *)
+ MALLOC( maxInstructions * sizeof(struct tgsi_full_instruction) );
+
+ if (!instructions) {
+ FREE( declarations );
+ return;
+ }
+
+ while( !tgsi_parse_end_of_tokens( &parse ) ) {
+ uint pointer = parse.Position;
+ uint i;
+
+ tgsi_parse_token( &parse );
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ /* save expanded declaration */
+ if (numDeclarations == maxDeclarations) {
+ declarations = REALLOC(declarations,
+ maxDeclarations
+ * sizeof(struct tgsi_full_declaration),
+ (maxDeclarations + 10)
+ * sizeof(struct tgsi_full_declaration));
+ maxDeclarations += 10;
+ }
+ memcpy(declarations + numDeclarations,
+ &parse.FullToken.FullDeclaration,
+ sizeof(declarations[0]));
+ numDeclarations++;
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
+ assert( size <= 4 );
+ assert( mach->ImmLimit + 1 <= TGSI_EXEC_NUM_IMMEDIATES );
+
+ for( i = 0; i < size; i++ ) {
+ mach->Imms[mach->ImmLimit][i] =
+ parse.FullToken.FullImmediate.u[i].Float;
+ }
+ mach->ImmLimit += 1;
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ assert( labels->count < MAX_LABELS );
+
+ labels->labels[labels->count][0] = instno;
+ labels->labels[labels->count][1] = pointer;
+ labels->count++;
+
+ /* save expanded instruction */
+ if (numInstructions == maxInstructions) {
+ instructions = REALLOC(instructions,
+ maxInstructions
+ * sizeof(struct tgsi_full_instruction),
+ (maxInstructions + 10)
+ * sizeof(struct tgsi_full_instruction));
+ maxInstructions += 10;
+ }
+
+ if (tgsi_check_soa_dependencies(&parse.FullToken.FullInstruction)) {
+ uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode;
+ parse.FullToken.FullInstruction.Flags = SOA_DEPENDENCY_FLAG;
+ /* XXX we only handle SOA dependencies properly for MOV/SWZ
+ * at this time!
+ */
+ if (opcode != TGSI_OPCODE_MOV && opcode != TGSI_OPCODE_SWZ) {
+ debug_printf("Warning: SOA dependency in instruction"
+ " is not handled:\n");
+ tgsi_dump_instruction(&parse.FullToken.FullInstruction,
+ numInstructions);
+ }
+ }
+
+ memcpy(instructions + numInstructions,
+ &parse.FullToken.FullInstruction,
+ sizeof(instructions[0]));
+
+ numInstructions++;
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+ tgsi_parse_free (&parse);
+
+ if (mach->Declarations) {
+ FREE( mach->Declarations );
+ }
+ mach->Declarations = declarations;
+ mach->NumDeclarations = numDeclarations;
+
+ if (mach->Instructions) {
+ FREE( mach->Instructions );
+ }
+ mach->Instructions = instructions;
+ mach->NumInstructions = numInstructions;
+}
+
+
+struct tgsi_exec_machine *
+tgsi_exec_machine_create( void )
+{
+ struct tgsi_exec_machine *mach;
+ uint i;
+
+ mach = align_malloc( sizeof *mach, 16 );
+ if (!mach)
+ goto fail;
+
+ memset(mach, 0, sizeof(*mach));
+
+ mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR];
+
+ /* Setup constants. */
+ for( i = 0; i < 4; i++ ) {
+ mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].u[i] = 0x00000000;
+ mach->Temps[TEMP_7F_I].xyzw[TEMP_7F_C].u[i] = 0x7FFFFFFF;
+ mach->Temps[TEMP_80_I].xyzw[TEMP_80_C].u[i] = 0x80000000;
+ mach->Temps[TEMP_FF_I].xyzw[TEMP_FF_C].u[i] = 0xFFFFFFFF;
+ mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].f[i] = 1.0f;
+ mach->Temps[TEMP_2_I].xyzw[TEMP_2_C].f[i] = 2.0f;
+ mach->Temps[TEMP_128_I].xyzw[TEMP_128_C].f[i] = 128.0f;
+ mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C].f[i] = -128.0f;
+ mach->Temps[TEMP_3_I].xyzw[TEMP_3_C].f[i] = 3.0f;
+ mach->Temps[TEMP_HALF_I].xyzw[TEMP_HALF_C].f[i] = 0.5f;
+ }
+
+#ifdef DEBUG
+ /* silence warnings */
+ (void) print_chan;
+ (void) print_temp;
+#endif
+
+ return mach;
+
+fail:
+ align_free(mach);
+ return NULL;
+}
+
+
+void
+tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach)
+{
+ if (mach) {
+ FREE(mach->Instructions);
+ FREE(mach->Declarations);
+ }
+
+ align_free(mach);
+}
+
+
+static void
+micro_abs(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = fabsf( src->f[0] );
+ dst->f[1] = fabsf( src->f[1] );
+ dst->f[2] = fabsf( src->f[2] );
+ dst->f[3] = fabsf( src->f[3] );
+}
+
+static void
+micro_add(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->f[0] = src0->f[0] + src1->f[0];
+ dst->f[1] = src0->f[1] + src1->f[1];
+ dst->f[2] = src0->f[2] + src1->f[2];
+ dst->f[3] = src0->f[3] + src1->f[3];
+}
+
+#if 0
+static void
+micro_iadd(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->i[0] = src0->i[0] + src1->i[0];
+ dst->i[1] = src0->i[1] + src1->i[1];
+ dst->i[2] = src0->i[2] + src1->i[2];
+ dst->i[3] = src0->i[3] + src1->i[3];
+}
+#endif
+
+static void
+micro_and(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->u[0] = src0->u[0] & src1->u[0];
+ dst->u[1] = src0->u[1] & src1->u[1];
+ dst->u[2] = src0->u[2] & src1->u[2];
+ dst->u[3] = src0->u[3] & src1->u[3];
+}
+
+static void
+micro_ceil(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = ceilf( src->f[0] );
+ dst->f[1] = ceilf( src->f[1] );
+ dst->f[2] = ceilf( src->f[2] );
+ dst->f[3] = ceilf( src->f[3] );
+}
+
+static void
+micro_cos(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = cosf( src->f[0] );
+ dst->f[1] = cosf( src->f[1] );
+ dst->f[2] = cosf( src->f[2] );
+ dst->f[3] = cosf( src->f[3] );
+}
+
+static void
+micro_ddx(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] =
+ dst->f[1] =
+ dst->f[2] =
+ dst->f[3] = src->f[TILE_BOTTOM_RIGHT] - src->f[TILE_BOTTOM_LEFT];
+}
+
+static void
+micro_ddy(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] =
+ dst->f[1] =
+ dst->f[2] =
+ dst->f[3] = src->f[TILE_TOP_LEFT] - src->f[TILE_BOTTOM_LEFT];
+}
+
+static void
+micro_div(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ if (src1->f[0] != 0) {
+ dst->f[0] = src0->f[0] / src1->f[0];
+ }
+ if (src1->f[1] != 0) {
+ dst->f[1] = src0->f[1] / src1->f[1];
+ }
+ if (src1->f[2] != 0) {
+ dst->f[2] = src0->f[2] / src1->f[2];
+ }
+ if (src1->f[3] != 0) {
+ dst->f[3] = src0->f[3] / src1->f[3];
+ }
+}
+
+#if 0
+static void
+micro_udiv(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->u[0] = src0->u[0] / src1->u[0];
+ dst->u[1] = src0->u[1] / src1->u[1];
+ dst->u[2] = src0->u[2] / src1->u[2];
+ dst->u[3] = src0->u[3] / src1->u[3];
+}
+#endif
+
+static void
+micro_eq(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1,
+ const union tgsi_exec_channel *src2,
+ const union tgsi_exec_channel *src3 )
+{
+ dst->f[0] = src0->f[0] == src1->f[0] ? src2->f[0] : src3->f[0];
+ dst->f[1] = src0->f[1] == src1->f[1] ? src2->f[1] : src3->f[1];
+ dst->f[2] = src0->f[2] == src1->f[2] ? src2->f[2] : src3->f[2];
+ dst->f[3] = src0->f[3] == src1->f[3] ? src2->f[3] : src3->f[3];
+}
+
+#if 0
+static void
+micro_ieq(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1,
+ const union tgsi_exec_channel *src2,
+ const union tgsi_exec_channel *src3 )
+{
+ dst->i[0] = src0->i[0] == src1->i[0] ? src2->i[0] : src3->i[0];
+ dst->i[1] = src0->i[1] == src1->i[1] ? src2->i[1] : src3->i[1];
+ dst->i[2] = src0->i[2] == src1->i[2] ? src2->i[2] : src3->i[2];
+ dst->i[3] = src0->i[3] == src1->i[3] ? src2->i[3] : src3->i[3];
+}
+#endif
+
+static void
+micro_exp2(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src)
+{
+#if FAST_MATH
+ dst->f[0] = util_fast_exp2( src->f[0] );
+ dst->f[1] = util_fast_exp2( src->f[1] );
+ dst->f[2] = util_fast_exp2( src->f[2] );
+ dst->f[3] = util_fast_exp2( src->f[3] );
+#else
+ dst->f[0] = powf( 2.0f, src->f[0] );
+ dst->f[1] = powf( 2.0f, src->f[1] );
+ dst->f[2] = powf( 2.0f, src->f[2] );
+ dst->f[3] = powf( 2.0f, src->f[3] );
+#endif
+}
+
+#if 0
+static void
+micro_f2ut(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->u[0] = (uint) src->f[0];
+ dst->u[1] = (uint) src->f[1];
+ dst->u[2] = (uint) src->f[2];
+ dst->u[3] = (uint) src->f[3];
+}
+#endif
+
+static void
+micro_float_clamp(union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src)
+{
+ uint i;
+
+ for (i = 0; i < 4; i++) {
+ if (src->f[i] > 0.0f) {
+ if (src->f[i] > 1.884467e+019f)
+ dst->f[i] = 1.884467e+019f;
+ else if (src->f[i] < 5.42101e-020f)
+ dst->f[i] = 5.42101e-020f;
+ else
+ dst->f[i] = src->f[i];
+ }
+ else {
+ if (src->f[i] < -1.884467e+019f)
+ dst->f[i] = -1.884467e+019f;
+ else if (src->f[i] > -5.42101e-020f)
+ dst->f[i] = -5.42101e-020f;
+ else
+ dst->f[i] = src->f[i];
+ }
+ }
+}
+
+static void
+micro_flr(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = floorf( src->f[0] );
+ dst->f[1] = floorf( src->f[1] );
+ dst->f[2] = floorf( src->f[2] );
+ dst->f[3] = floorf( src->f[3] );
+}
+
+static void
+micro_frc(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = src->f[0] - floorf( src->f[0] );
+ dst->f[1] = src->f[1] - floorf( src->f[1] );
+ dst->f[2] = src->f[2] - floorf( src->f[2] );
+ dst->f[3] = src->f[3] - floorf( src->f[3] );
+}
+
+static void
+micro_i2f(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = (float) src->i[0];
+ dst->f[1] = (float) src->i[1];
+ dst->f[2] = (float) src->i[2];
+ dst->f[3] = (float) src->i[3];
+}
+
+static void
+micro_lg2(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+#if FAST_MATH
+ dst->f[0] = util_fast_log2( src->f[0] );
+ dst->f[1] = util_fast_log2( src->f[1] );
+ dst->f[2] = util_fast_log2( src->f[2] );
+ dst->f[3] = util_fast_log2( src->f[3] );
+#else
+ dst->f[0] = logf( src->f[0] ) * 1.442695f;
+ dst->f[1] = logf( src->f[1] ) * 1.442695f;
+ dst->f[2] = logf( src->f[2] ) * 1.442695f;
+ dst->f[3] = logf( src->f[3] ) * 1.442695f;
+#endif
+}
+
+static void
+micro_le(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1,
+ const union tgsi_exec_channel *src2,
+ const union tgsi_exec_channel *src3 )
+{
+ dst->f[0] = src0->f[0] <= src1->f[0] ? src2->f[0] : src3->f[0];
+ dst->f[1] = src0->f[1] <= src1->f[1] ? src2->f[1] : src3->f[1];
+ dst->f[2] = src0->f[2] <= src1->f[2] ? src2->f[2] : src3->f[2];
+ dst->f[3] = src0->f[3] <= src1->f[3] ? src2->f[3] : src3->f[3];
+}
+
+static void
+micro_lt(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1,
+ const union tgsi_exec_channel *src2,
+ const union tgsi_exec_channel *src3 )
+{
+ dst->f[0] = src0->f[0] < src1->f[0] ? src2->f[0] : src3->f[0];
+ dst->f[1] = src0->f[1] < src1->f[1] ? src2->f[1] : src3->f[1];
+ dst->f[2] = src0->f[2] < src1->f[2] ? src2->f[2] : src3->f[2];
+ dst->f[3] = src0->f[3] < src1->f[3] ? src2->f[3] : src3->f[3];
+}
+
+#if 0
+static void
+micro_ilt(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1,
+ const union tgsi_exec_channel *src2,
+ const union tgsi_exec_channel *src3 )
+{
+ dst->i[0] = src0->i[0] < src1->i[0] ? src2->i[0] : src3->i[0];
+ dst->i[1] = src0->i[1] < src1->i[1] ? src2->i[1] : src3->i[1];
+ dst->i[2] = src0->i[2] < src1->i[2] ? src2->i[2] : src3->i[2];
+ dst->i[3] = src0->i[3] < src1->i[3] ? src2->i[3] : src3->i[3];
+}
+#endif
+
+#if 0
+static void
+micro_ult(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1,
+ const union tgsi_exec_channel *src2,
+ const union tgsi_exec_channel *src3 )
+{
+ dst->u[0] = src0->u[0] < src1->u[0] ? src2->u[0] : src3->u[0];
+ dst->u[1] = src0->u[1] < src1->u[1] ? src2->u[1] : src3->u[1];
+ dst->u[2] = src0->u[2] < src1->u[2] ? src2->u[2] : src3->u[2];
+ dst->u[3] = src0->u[3] < src1->u[3] ? src2->u[3] : src3->u[3];
+}
+#endif
+
+static void
+micro_max(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->f[0] = src0->f[0] > src1->f[0] ? src0->f[0] : src1->f[0];
+ dst->f[1] = src0->f[1] > src1->f[1] ? src0->f[1] : src1->f[1];
+ dst->f[2] = src0->f[2] > src1->f[2] ? src0->f[2] : src1->f[2];
+ dst->f[3] = src0->f[3] > src1->f[3] ? src0->f[3] : src1->f[3];
+}
+
+#if 0
+static void
+micro_imax(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->i[0] = src0->i[0] > src1->i[0] ? src0->i[0] : src1->i[0];
+ dst->i[1] = src0->i[1] > src1->i[1] ? src0->i[1] : src1->i[1];
+ dst->i[2] = src0->i[2] > src1->i[2] ? src0->i[2] : src1->i[2];
+ dst->i[3] = src0->i[3] > src1->i[3] ? src0->i[3] : src1->i[3];
+}
+#endif
+
+#if 0
+static void
+micro_umax(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->u[0] = src0->u[0] > src1->u[0] ? src0->u[0] : src1->u[0];
+ dst->u[1] = src0->u[1] > src1->u[1] ? src0->u[1] : src1->u[1];
+ dst->u[2] = src0->u[2] > src1->u[2] ? src0->u[2] : src1->u[2];
+ dst->u[3] = src0->u[3] > src1->u[3] ? src0->u[3] : src1->u[3];
+}
+#endif
+
+static void
+micro_min(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->f[0] = src0->f[0] < src1->f[0] ? src0->f[0] : src1->f[0];
+ dst->f[1] = src0->f[1] < src1->f[1] ? src0->f[1] : src1->f[1];
+ dst->f[2] = src0->f[2] < src1->f[2] ? src0->f[2] : src1->f[2];
+ dst->f[3] = src0->f[3] < src1->f[3] ? src0->f[3] : src1->f[3];
+}
+
+#if 0
+static void
+micro_imin(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->i[0] = src0->i[0] < src1->i[0] ? src0->i[0] : src1->i[0];
+ dst->i[1] = src0->i[1] < src1->i[1] ? src0->i[1] : src1->i[1];
+ dst->i[2] = src0->i[2] < src1->i[2] ? src0->i[2] : src1->i[2];
+ dst->i[3] = src0->i[3] < src1->i[3] ? src0->i[3] : src1->i[3];
+}
+#endif
+
+#if 0
+static void
+micro_umin(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->u[0] = src0->u[0] < src1->u[0] ? src0->u[0] : src1->u[0];
+ dst->u[1] = src0->u[1] < src1->u[1] ? src0->u[1] : src1->u[1];
+ dst->u[2] = src0->u[2] < src1->u[2] ? src0->u[2] : src1->u[2];
+ dst->u[3] = src0->u[3] < src1->u[3] ? src0->u[3] : src1->u[3];
+}
+#endif
+
+#if 0
+static void
+micro_umod(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->u[0] = src0->u[0] % src1->u[0];
+ dst->u[1] = src0->u[1] % src1->u[1];
+ dst->u[2] = src0->u[2] % src1->u[2];
+ dst->u[3] = src0->u[3] % src1->u[3];
+}
+#endif
+
+static void
+micro_mul(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->f[0] = src0->f[0] * src1->f[0];
+ dst->f[1] = src0->f[1] * src1->f[1];
+ dst->f[2] = src0->f[2] * src1->f[2];
+ dst->f[3] = src0->f[3] * src1->f[3];
+}
+
+#if 0
+static void
+micro_imul(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->i[0] = src0->i[0] * src1->i[0];
+ dst->i[1] = src0->i[1] * src1->i[1];
+ dst->i[2] = src0->i[2] * src1->i[2];
+ dst->i[3] = src0->i[3] * src1->i[3];
+}
+#endif
+
+#if 0
+static void
+micro_imul64(
+ union tgsi_exec_channel *dst0,
+ union tgsi_exec_channel *dst1,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst1->i[0] = src0->i[0] * src1->i[0];
+ dst1->i[1] = src0->i[1] * src1->i[1];
+ dst1->i[2] = src0->i[2] * src1->i[2];
+ dst1->i[3] = src0->i[3] * src1->i[3];
+ dst0->i[0] = 0;
+ dst0->i[1] = 0;
+ dst0->i[2] = 0;
+ dst0->i[3] = 0;
+}
+#endif
+
+#if 0
+static void
+micro_umul64(
+ union tgsi_exec_channel *dst0,
+ union tgsi_exec_channel *dst1,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst1->u[0] = src0->u[0] * src1->u[0];
+ dst1->u[1] = src0->u[1] * src1->u[1];
+ dst1->u[2] = src0->u[2] * src1->u[2];
+ dst1->u[3] = src0->u[3] * src1->u[3];
+ dst0->u[0] = 0;
+ dst0->u[1] = 0;
+ dst0->u[2] = 0;
+ dst0->u[3] = 0;
+}
+#endif
+
+
+#if 0
+static void
+micro_movc(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1,
+ const union tgsi_exec_channel *src2 )
+{
+ dst->u[0] = src0->u[0] ? src1->u[0] : src2->u[0];
+ dst->u[1] = src0->u[1] ? src1->u[1] : src2->u[1];
+ dst->u[2] = src0->u[2] ? src1->u[2] : src2->u[2];
+ dst->u[3] = src0->u[3] ? src1->u[3] : src2->u[3];
+}
+#endif
+
+static void
+micro_neg(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = -src->f[0];
+ dst->f[1] = -src->f[1];
+ dst->f[2] = -src->f[2];
+ dst->f[3] = -src->f[3];
+}
+
+#if 0
+static void
+micro_ineg(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->i[0] = -src->i[0];
+ dst->i[1] = -src->i[1];
+ dst->i[2] = -src->i[2];
+ dst->i[3] = -src->i[3];
+}
+#endif
+
+static void
+micro_not(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->u[0] = ~src->u[0];
+ dst->u[1] = ~src->u[1];
+ dst->u[2] = ~src->u[2];
+ dst->u[3] = ~src->u[3];
+}
+
+static void
+micro_or(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->u[0] = src0->u[0] | src1->u[0];
+ dst->u[1] = src0->u[1] | src1->u[1];
+ dst->u[2] = src0->u[2] | src1->u[2];
+ dst->u[3] = src0->u[3] | src1->u[3];
+}
+
+static void
+micro_pow(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+#if FAST_MATH
+ dst->f[0] = util_fast_pow( src0->f[0], src1->f[0] );
+ dst->f[1] = util_fast_pow( src0->f[1], src1->f[1] );
+ dst->f[2] = util_fast_pow( src0->f[2], src1->f[2] );
+ dst->f[3] = util_fast_pow( src0->f[3], src1->f[3] );
+#else
+ dst->f[0] = powf( src0->f[0], src1->f[0] );
+ dst->f[1] = powf( src0->f[1], src1->f[1] );
+ dst->f[2] = powf( src0->f[2], src1->f[2] );
+ dst->f[3] = powf( src0->f[3], src1->f[3] );
+#endif
+}
+
+static void
+micro_rnd(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = floorf( src->f[0] + 0.5f );
+ dst->f[1] = floorf( src->f[1] + 0.5f );
+ dst->f[2] = floorf( src->f[2] + 0.5f );
+ dst->f[3] = floorf( src->f[3] + 0.5f );
+}
+
+static void
+micro_sgn(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = src->f[0] < 0.0f ? -1.0f : src->f[0] > 0.0f ? 1.0f : 0.0f;
+ dst->f[1] = src->f[1] < 0.0f ? -1.0f : src->f[1] > 0.0f ? 1.0f : 0.0f;
+ dst->f[2] = src->f[2] < 0.0f ? -1.0f : src->f[2] > 0.0f ? 1.0f : 0.0f;
+ dst->f[3] = src->f[3] < 0.0f ? -1.0f : src->f[3] > 0.0f ? 1.0f : 0.0f;
+}
+
+static void
+micro_shl(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->i[0] = src0->i[0] << src1->i[0];
+ dst->i[1] = src0->i[1] << src1->i[1];
+ dst->i[2] = src0->i[2] << src1->i[2];
+ dst->i[3] = src0->i[3] << src1->i[3];
+}
+
+static void
+micro_ishr(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->i[0] = src0->i[0] >> src1->i[0];
+ dst->i[1] = src0->i[1] >> src1->i[1];
+ dst->i[2] = src0->i[2] >> src1->i[2];
+ dst->i[3] = src0->i[3] >> src1->i[3];
+}
+
+static void
+micro_trunc(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0 )
+{
+ dst->f[0] = (float) (int) src0->f[0];
+ dst->f[1] = (float) (int) src0->f[1];
+ dst->f[2] = (float) (int) src0->f[2];
+ dst->f[3] = (float) (int) src0->f[3];
+}
+
+#if 0
+static void
+micro_ushr(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->u[0] = src0->u[0] >> src1->u[0];
+ dst->u[1] = src0->u[1] >> src1->u[1];
+ dst->u[2] = src0->u[2] >> src1->u[2];
+ dst->u[3] = src0->u[3] >> src1->u[3];
+}
+#endif
+
+static void
+micro_sin(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = sinf( src->f[0] );
+ dst->f[1] = sinf( src->f[1] );
+ dst->f[2] = sinf( src->f[2] );
+ dst->f[3] = sinf( src->f[3] );
+}
+
+static void
+micro_sqrt( union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = sqrtf( src->f[0] );
+ dst->f[1] = sqrtf( src->f[1] );
+ dst->f[2] = sqrtf( src->f[2] );
+ dst->f[3] = sqrtf( src->f[3] );
+}
+
+static void
+micro_sub(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->f[0] = src0->f[0] - src1->f[0];
+ dst->f[1] = src0->f[1] - src1->f[1];
+ dst->f[2] = src0->f[2] - src1->f[2];
+ dst->f[3] = src0->f[3] - src1->f[3];
+}
+
+#if 0
+static void
+micro_u2f(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src )
+{
+ dst->f[0] = (float) src->u[0];
+ dst->f[1] = (float) src->u[1];
+ dst->f[2] = (float) src->u[2];
+ dst->f[3] = (float) src->u[3];
+}
+#endif
+
+static void
+micro_xor(
+ union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1 )
+{
+ dst->u[0] = src0->u[0] ^ src1->u[0];
+ dst->u[1] = src0->u[1] ^ src1->u[1];
+ dst->u[2] = src0->u[2] ^ src1->u[2];
+ dst->u[3] = src0->u[3] ^ src1->u[3];
+}
+
+static void
+fetch_src_file_channel(
+ const struct tgsi_exec_machine *mach,
+ const uint file,
+ const uint swizzle,
+ const union tgsi_exec_channel *index,
+ union tgsi_exec_channel *chan )
+{
+ switch( swizzle ) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ switch( file ) {
+ case TGSI_FILE_CONSTANT:
+ assert(mach->Consts);
+ if (index->i[0] < 0)
+ chan->f[0] = 0.0f;
+ else
+ chan->f[0] = mach->Consts[index->i[0]][swizzle];
+ if (index->i[1] < 0)
+ chan->f[1] = 0.0f;
+ else
+ chan->f[1] = mach->Consts[index->i[1]][swizzle];
+ if (index->i[2] < 0)
+ chan->f[2] = 0.0f;
+ else
+ chan->f[2] = mach->Consts[index->i[2]][swizzle];
+ if (index->i[3] < 0)
+ chan->f[3] = 0.0f;
+ else
+ chan->f[3] = mach->Consts[index->i[3]][swizzle];
+ break;
+
+ case TGSI_FILE_INPUT:
+ chan->u[0] = mach->Inputs[index->i[0]].xyzw[swizzle].u[0];
+ chan->u[1] = mach->Inputs[index->i[1]].xyzw[swizzle].u[1];
+ chan->u[2] = mach->Inputs[index->i[2]].xyzw[swizzle].u[2];
+ chan->u[3] = mach->Inputs[index->i[3]].xyzw[swizzle].u[3];
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ assert(index->i[0] < TGSI_EXEC_NUM_TEMPS);
+ chan->u[0] = mach->Temps[index->i[0]].xyzw[swizzle].u[0];
+ chan->u[1] = mach->Temps[index->i[1]].xyzw[swizzle].u[1];
+ chan->u[2] = mach->Temps[index->i[2]].xyzw[swizzle].u[2];
+ chan->u[3] = mach->Temps[index->i[3]].xyzw[swizzle].u[3];
+ break;
+
+ case TGSI_FILE_IMMEDIATE:
+ assert( index->i[0] < (int) mach->ImmLimit );
+ chan->f[0] = mach->Imms[index->i[0]][swizzle];
+ assert( index->i[1] < (int) mach->ImmLimit );
+ chan->f[1] = mach->Imms[index->i[1]][swizzle];
+ assert( index->i[2] < (int) mach->ImmLimit );
+ chan->f[2] = mach->Imms[index->i[2]][swizzle];
+ assert( index->i[3] < (int) mach->ImmLimit );
+ chan->f[3] = mach->Imms[index->i[3]][swizzle];
+ break;
+
+ case TGSI_FILE_ADDRESS:
+ chan->u[0] = mach->Addrs[index->i[0]].xyzw[swizzle].u[0];
+ chan->u[1] = mach->Addrs[index->i[1]].xyzw[swizzle].u[1];
+ chan->u[2] = mach->Addrs[index->i[2]].xyzw[swizzle].u[2];
+ chan->u[3] = mach->Addrs[index->i[3]].xyzw[swizzle].u[3];
+ break;
+
+ case TGSI_FILE_OUTPUT:
+ /* vertex/fragment output vars can be read too */
+ chan->u[0] = mach->Outputs[index->i[0]].xyzw[swizzle].u[0];
+ chan->u[1] = mach->Outputs[index->i[1]].xyzw[swizzle].u[1];
+ chan->u[2] = mach->Outputs[index->i[2]].xyzw[swizzle].u[2];
+ chan->u[3] = mach->Outputs[index->i[3]].xyzw[swizzle].u[3];
+ break;
+
+ default:
+ assert( 0 );
+ }
+ break;
+
+ case TGSI_EXTSWIZZLE_ZERO:
+ *chan = mach->Temps[TEMP_0_I].xyzw[TEMP_0_C];
+ break;
+
+ case TGSI_EXTSWIZZLE_ONE:
+ *chan = mach->Temps[TEMP_1_I].xyzw[TEMP_1_C];
+ break;
+
+ default:
+ assert( 0 );
+ }
+}
+
+static void
+fetch_source(
+ const struct tgsi_exec_machine *mach,
+ union tgsi_exec_channel *chan,
+ const struct tgsi_full_src_register *reg,
+ const uint chan_index )
+{
+ union tgsi_exec_channel index;
+ uint swizzle;
+
+ /* We start with a direct index into a register file.
+ *
+ * file[1],
+ * where:
+ * file = SrcRegister.File
+ * [1] = SrcRegister.Index
+ */
+ index.i[0] =
+ index.i[1] =
+ index.i[2] =
+ index.i[3] = reg->SrcRegister.Index;
+
+ /* There is an extra source register that indirectly subscripts
+ * a register file. The direct index now becomes an offset
+ * that is being added to the indirect register.
+ *
+ * file[ind[2].x+1],
+ * where:
+ * ind = SrcRegisterInd.File
+ * [2] = SrcRegisterInd.Index
+ * .x = SrcRegisterInd.SwizzleX
+ */
+ if (reg->SrcRegister.Indirect) {
+ union tgsi_exec_channel index2;
+ union tgsi_exec_channel indir_index;
+ const uint execmask = mach->ExecMask;
+ uint i;
+
+ /* which address register (always zero now) */
+ index2.i[0] =
+ index2.i[1] =
+ index2.i[2] =
+ index2.i[3] = reg->SrcRegisterInd.Index;
+
+ /* get current value of address register[swizzle] */
+ swizzle = tgsi_util_get_src_register_swizzle( &reg->SrcRegisterInd, CHAN_X );
+ fetch_src_file_channel(
+ mach,
+ reg->SrcRegisterInd.File,
+ swizzle,
+ &index2,
+ &indir_index );
+
+ /* add value of address register to the offset */
+ index.i[0] += (int) indir_index.f[0];
+ index.i[1] += (int) indir_index.f[1];
+ index.i[2] += (int) indir_index.f[2];
+ index.i[3] += (int) indir_index.f[3];
+
+ /* for disabled execution channels, zero-out the index to
+ * avoid using a potential garbage value.
+ */
+ for (i = 0; i < QUAD_SIZE; i++) {
+ if ((execmask & (1 << i)) == 0)
+ index.i[i] = 0;
+ }
+ }
+
+ /* There is an extra source register that is a second
+ * subscript to a register file. Effectively it means that
+ * the register file is actually a 2D array of registers.
+ *
+ * file[1][3] == file[1*sizeof(file[1])+3],
+ * where:
+ * [3] = SrcRegisterDim.Index
+ */
+ if (reg->SrcRegister.Dimension) {
+ /* The size of the first-order array depends on the register file type.
+ * We need to multiply the index to the first array to get an effective,
+ * "flat" index that points to the beginning of the second-order array.
+ */
+ switch (reg->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ index.i[0] *= TGSI_EXEC_MAX_INPUT_ATTRIBS;
+ index.i[1] *= TGSI_EXEC_MAX_INPUT_ATTRIBS;
+ index.i[2] *= TGSI_EXEC_MAX_INPUT_ATTRIBS;
+ index.i[3] *= TGSI_EXEC_MAX_INPUT_ATTRIBS;
+ break;
+ case TGSI_FILE_CONSTANT:
+ index.i[0] *= TGSI_EXEC_MAX_CONST_BUFFER;
+ index.i[1] *= TGSI_EXEC_MAX_CONST_BUFFER;
+ index.i[2] *= TGSI_EXEC_MAX_CONST_BUFFER;
+ index.i[3] *= TGSI_EXEC_MAX_CONST_BUFFER;
+ break;
+ default:
+ assert( 0 );
+ }
+
+ index.i[0] += reg->SrcRegisterDim.Index;
+ index.i[1] += reg->SrcRegisterDim.Index;
+ index.i[2] += reg->SrcRegisterDim.Index;
+ index.i[3] += reg->SrcRegisterDim.Index;
+
+ /* Again, the second subscript index can be addressed indirectly
+ * identically to the first one.
+ * Nothing stops us from indirectly addressing the indirect register,
+ * but there is no need for that, so we won't exercise it.
+ *
+ * file[1][ind[4].y+3],
+ * where:
+ * ind = SrcRegisterDimInd.File
+ * [4] = SrcRegisterDimInd.Index
+ * .y = SrcRegisterDimInd.SwizzleX
+ */
+ if (reg->SrcRegisterDim.Indirect) {
+ union tgsi_exec_channel index2;
+ union tgsi_exec_channel indir_index;
+ const uint execmask = mach->ExecMask;
+ uint i;
+
+ index2.i[0] =
+ index2.i[1] =
+ index2.i[2] =
+ index2.i[3] = reg->SrcRegisterDimInd.Index;
+
+ swizzle = tgsi_util_get_src_register_swizzle( &reg->SrcRegisterDimInd, CHAN_X );
+ fetch_src_file_channel(
+ mach,
+ reg->SrcRegisterDimInd.File,
+ swizzle,
+ &index2,
+ &indir_index );
+
+ index.i[0] += (int) indir_index.f[0];
+ index.i[1] += (int) indir_index.f[1];
+ index.i[2] += (int) indir_index.f[2];
+ index.i[3] += (int) indir_index.f[3];
+
+ /* for disabled execution channels, zero-out the index to
+ * avoid using a potential garbage value.
+ */
+ for (i = 0; i < QUAD_SIZE; i++) {
+ if ((execmask & (1 << i)) == 0)
+ index.i[i] = 0;
+ }
+ }
+
+ /* If by any chance there was a need for a 3D array of register
+ * files, we would have to check whether SrcRegisterDim is followed
+ * by a dimension register and continue the saga.
+ */
+ }
+
+ swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index );
+ fetch_src_file_channel(
+ mach,
+ reg->SrcRegister.File,
+ swizzle,
+ &index,
+ chan );
+
+ switch (tgsi_util_get_full_src_register_sign_mode( reg, chan_index )) {
+ case TGSI_UTIL_SIGN_CLEAR:
+ micro_abs( chan, chan );
+ break;
+
+ case TGSI_UTIL_SIGN_SET:
+ micro_abs( chan, chan );
+ micro_neg( chan, chan );
+ break;
+
+ case TGSI_UTIL_SIGN_TOGGLE:
+ micro_neg( chan, chan );
+ break;
+
+ case TGSI_UTIL_SIGN_KEEP:
+ break;
+ }
+
+ if (reg->SrcRegisterExtMod.Complement) {
+ micro_sub( chan, &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], chan );
+ }
+}
+
+static void
+store_dest(
+ struct tgsi_exec_machine *mach,
+ const union tgsi_exec_channel *chan,
+ const struct tgsi_full_dst_register *reg,
+ const struct tgsi_full_instruction *inst,
+ uint chan_index )
+{
+ uint i;
+ union tgsi_exec_channel null;
+ union tgsi_exec_channel *dst;
+ uint execmask = mach->ExecMask;
+ int offset = 0; /* indirection offset */
+ int index;
+
+#ifdef DEBUG
+ check_inf_or_nan(chan);
+#endif
+
+ /* There is an extra source register that indirectly subscripts
+ * a register file. The direct index now becomes an offset
+ * that is being added to the indirect register.
+ *
+ * file[ind[2].x+1],
+ * where:
+ * ind = DstRegisterInd.File
+ * [2] = DstRegisterInd.Index
+ * .x = DstRegisterInd.SwizzleX
+ */
+ if (reg->DstRegister.Indirect) {
+ union tgsi_exec_channel index;
+ union tgsi_exec_channel indir_index;
+ uint swizzle;
+
+ /* which address register (always zero for now) */
+ index.i[0] =
+ index.i[1] =
+ index.i[2] =
+ index.i[3] = reg->DstRegisterInd.Index;
+
+ /* get current value of address register[swizzle] */
+ swizzle = tgsi_util_get_src_register_swizzle( &reg->DstRegisterInd, CHAN_X );
+
+ /* fetch values from the address/indirection register */
+ fetch_src_file_channel(
+ mach,
+ reg->DstRegisterInd.File,
+ swizzle,
+ &index,
+ &indir_index );
+
+ /* save indirection offset */
+ offset = (int) indir_index.f[0];
+ }
+
+ switch (reg->DstRegister.File) {
+ case TGSI_FILE_NULL:
+ dst = &null;
+ break;
+
+ case TGSI_FILE_OUTPUT:
+ index = mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0]
+ + reg->DstRegister.Index;
+ dst = &mach->Outputs[offset + index].xyzw[chan_index];
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ index = reg->DstRegister.Index;
+ assert( index < TGSI_EXEC_NUM_TEMPS );
+ dst = &mach->Temps[offset + index].xyzw[chan_index];
+ break;
+
+ case TGSI_FILE_ADDRESS:
+ index = reg->DstRegister.Index;
+ dst = &mach->Addrs[index].xyzw[chan_index];
+ break;
+
+ default:
+ assert( 0 );
+ return;
+ }
+
+ if (inst->InstructionExtNv.CondFlowEnable) {
+ union tgsi_exec_channel *cc = &mach->Temps[TEMP_CC_I].xyzw[TEMP_CC_C];
+ uint swizzle;
+ uint shift;
+ uint mask;
+ uint test;
+
+ /* Only CC0 supported.
+ */
+ assert( inst->InstructionExtNv.CondFlowIndex < 1 );
+
+ switch (chan_index) {
+ case CHAN_X:
+ swizzle = inst->InstructionExtNv.CondSwizzleX;
+ break;
+ case CHAN_Y:
+ swizzle = inst->InstructionExtNv.CondSwizzleY;
+ break;
+ case CHAN_Z:
+ swizzle = inst->InstructionExtNv.CondSwizzleZ;
+ break;
+ case CHAN_W:
+ swizzle = inst->InstructionExtNv.CondSwizzleW;
+ break;
+ default:
+ assert( 0 );
+ return;
+ }
+
+ switch (swizzle) {
+ case TGSI_SWIZZLE_X:
+ shift = TGSI_EXEC_CC_X_SHIFT;
+ mask = TGSI_EXEC_CC_X_MASK;
+ break;
+ case TGSI_SWIZZLE_Y:
+ shift = TGSI_EXEC_CC_Y_SHIFT;
+ mask = TGSI_EXEC_CC_Y_MASK;
+ break;
+ case TGSI_SWIZZLE_Z:
+ shift = TGSI_EXEC_CC_Z_SHIFT;
+ mask = TGSI_EXEC_CC_Z_MASK;
+ break;
+ case TGSI_SWIZZLE_W:
+ shift = TGSI_EXEC_CC_W_SHIFT;
+ mask = TGSI_EXEC_CC_W_MASK;
+ break;
+ default:
+ assert( 0 );
+ return;
+ }
+
+ switch (inst->InstructionExtNv.CondMask) {
+ case TGSI_CC_GT:
+ test = ~(TGSI_EXEC_CC_GT << shift) & mask;
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (cc->u[i] & test)
+ execmask &= ~(1 << i);
+ break;
+
+ case TGSI_CC_EQ:
+ test = ~(TGSI_EXEC_CC_EQ << shift) & mask;
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (cc->u[i] & test)
+ execmask &= ~(1 << i);
+ break;
+
+ case TGSI_CC_LT:
+ test = ~(TGSI_EXEC_CC_LT << shift) & mask;
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (cc->u[i] & test)
+ execmask &= ~(1 << i);
+ break;
+
+ case TGSI_CC_GE:
+ test = ~((TGSI_EXEC_CC_GT | TGSI_EXEC_CC_EQ) << shift) & mask;
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (cc->u[i] & test)
+ execmask &= ~(1 << i);
+ break;
+
+ case TGSI_CC_LE:
+ test = ~((TGSI_EXEC_CC_LT | TGSI_EXEC_CC_EQ) << shift) & mask;
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (cc->u[i] & test)
+ execmask &= ~(1 << i);
+ break;
+
+ case TGSI_CC_NE:
+ test = ~((TGSI_EXEC_CC_GT | TGSI_EXEC_CC_LT | TGSI_EXEC_CC_UN) << shift) & mask;
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (cc->u[i] & test)
+ execmask &= ~(1 << i);
+ break;
+
+ case TGSI_CC_TR:
+ break;
+
+ case TGSI_CC_FL:
+ for (i = 0; i < QUAD_SIZE; i++)
+ execmask &= ~(1 << i);
+ break;
+
+ default:
+ assert( 0 );
+ return;
+ }
+ }
+
+ switch (inst->Instruction.Saturate) {
+ case TGSI_SAT_NONE:
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (execmask & (1 << i))
+ dst->i[i] = chan->i[i];
+ break;
+
+ case TGSI_SAT_ZERO_ONE:
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (execmask & (1 << i)) {
+ if (chan->f[i] < 0.0f)
+ dst->f[i] = 0.0f;
+ else if (chan->f[i] > 1.0f)
+ dst->f[i] = 1.0f;
+ else
+ dst->i[i] = chan->i[i];
+ }
+ break;
+
+ case TGSI_SAT_MINUS_PLUS_ONE:
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (execmask & (1 << i)) {
+ if (chan->f[i] < -1.0f)
+ dst->f[i] = -1.0f;
+ else if (chan->f[i] > 1.0f)
+ dst->f[i] = 1.0f;
+ else
+ dst->i[i] = chan->i[i];
+ }
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ if (inst->InstructionExtNv.CondDstUpdate) {
+ union tgsi_exec_channel *cc = &mach->Temps[TEMP_CC_I].xyzw[TEMP_CC_C];
+ uint shift;
+ uint mask;
+
+ /* Only CC0 supported.
+ */
+ assert( inst->InstructionExtNv.CondDstIndex < 1 );
+
+ switch (chan_index) {
+ case CHAN_X:
+ shift = TGSI_EXEC_CC_X_SHIFT;
+ mask = ~TGSI_EXEC_CC_X_MASK;
+ break;
+ case CHAN_Y:
+ shift = TGSI_EXEC_CC_Y_SHIFT;
+ mask = ~TGSI_EXEC_CC_Y_MASK;
+ break;
+ case CHAN_Z:
+ shift = TGSI_EXEC_CC_Z_SHIFT;
+ mask = ~TGSI_EXEC_CC_Z_MASK;
+ break;
+ case CHAN_W:
+ shift = TGSI_EXEC_CC_W_SHIFT;
+ mask = ~TGSI_EXEC_CC_W_MASK;
+ break;
+ default:
+ assert( 0 );
+ return;
+ }
+
+ for (i = 0; i < QUAD_SIZE; i++)
+ if (execmask & (1 << i)) {
+ cc->u[i] &= mask;
+ if (dst->f[i] < 0.0f)
+ cc->u[i] |= TGSI_EXEC_CC_LT << shift;
+ else if (dst->f[i] > 0.0f)
+ cc->u[i] |= TGSI_EXEC_CC_GT << shift;
+ else if (dst->f[i] == 0.0f)
+ cc->u[i] |= TGSI_EXEC_CC_EQ << shift;
+ else
+ cc->u[i] |= TGSI_EXEC_CC_UN << shift;
+ }
+ }
+}
+
+#define FETCH(VAL,INDEX,CHAN)\
+ fetch_source (mach, VAL, &inst->FullSrcRegisters[INDEX], CHAN)
+
+#define STORE(VAL,INDEX,CHAN)\
+ store_dest (mach, VAL, &inst->FullDstRegisters[INDEX], inst, CHAN )
+
+
+/**
+ * Execute ARB-style KIL which is predicated by a src register.
+ * Kill fragment if any of the four values is less than zero.
+ */
+static void
+exec_kil(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst)
+{
+ uint uniquemask;
+ uint chan_index;
+ uint kilmask = 0; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */
+ union tgsi_exec_channel r[1];
+
+ /* This mask stores component bits that were already tested. Note that
+ * we test if the value is less than zero, so 1.0 and 0.0 need not to be
+ * tested. */
+ uniquemask = (1 << TGSI_EXTSWIZZLE_ZERO) | (1 << TGSI_EXTSWIZZLE_ONE);
+
+ for (chan_index = 0; chan_index < 4; chan_index++)
+ {
+ uint swizzle;
+ uint i;
+
+ /* unswizzle channel */
+ swizzle = tgsi_util_get_full_src_register_extswizzle (
+ &inst->FullSrcRegisters[0],
+ chan_index);
+
+ /* check if the component has not been already tested */
+ if (uniquemask & (1 << swizzle))
+ continue;
+ uniquemask |= 1 << swizzle;
+
+ FETCH(&r[0], 0, chan_index);
+ for (i = 0; i < 4; i++)
+ if (r[0].f[i] < 0.0f)
+ kilmask |= 1 << i;
+ }
+
+ mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask;
+}
+
+/**
+ * Execute NVIDIA-style KIL which is predicated by a condition code.
+ * Kill fragment if the condition code is TRUE.
+ */
+static void
+exec_kilp(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst)
+{
+ uint kilmask; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */
+
+ if (inst->InstructionExtNv.CondFlowEnable) {
+ uint swizzle[4];
+ uint chan_index;
+
+ kilmask = 0x0;
+
+ swizzle[0] = inst->InstructionExtNv.CondSwizzleX;
+ swizzle[1] = inst->InstructionExtNv.CondSwizzleY;
+ swizzle[2] = inst->InstructionExtNv.CondSwizzleZ;
+ swizzle[3] = inst->InstructionExtNv.CondSwizzleW;
+
+ for (chan_index = 0; chan_index < 4; chan_index++)
+ {
+ uint i;
+
+ for (i = 0; i < 4; i++) {
+ /* TODO: evaluate the condition code */
+ if (0)
+ kilmask |= 1 << i;
+ }
+ }
+ }
+ else {
+ /* "unconditional" kil */
+ kilmask = mach->ExecMask;
+ }
+ mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask;
+}
+
+
+/*
+ * Fetch a four texture samples using STR texture coordinates.
+ */
+static void
+fetch_texel( struct tgsi_sampler *sampler,
+ const union tgsi_exec_channel *s,
+ const union tgsi_exec_channel *t,
+ const union tgsi_exec_channel *p,
+ float lodbias, /* XXX should be float[4] */
+ union tgsi_exec_channel *r,
+ union tgsi_exec_channel *g,
+ union tgsi_exec_channel *b,
+ union tgsi_exec_channel *a )
+{
+ uint j;
+ float rgba[NUM_CHANNELS][QUAD_SIZE];
+
+ sampler->get_samples(sampler, s->f, t->f, p->f, lodbias, rgba);
+
+ for (j = 0; j < 4; j++) {
+ r->f[j] = rgba[0][j];
+ g->f[j] = rgba[1][j];
+ b->f[j] = rgba[2][j];
+ a->f[j] = rgba[3][j];
+ }
+}
+
+
+static void
+exec_tex(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst,
+ boolean biasLod,
+ boolean projected)
+{
+ const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
+ union tgsi_exec_channel r[4];
+ uint chan_index;
+ float lodBias;
+
+ /* debug_printf("Sampler %u unit %u\n", sampler, unit); */
+
+ switch (inst->InstructionExtTexture.Texture) {
+ case TGSI_TEXTURE_1D:
+ case TGSI_TEXTURE_SHADOW1D:
+
+ FETCH(&r[0], 0, CHAN_X);
+
+ if (projected) {
+ FETCH(&r[1], 0, CHAN_W);
+ micro_div( &r[0], &r[0], &r[1] );
+ }
+
+ if (biasLod) {
+ FETCH(&r[1], 0, CHAN_W);
+ lodBias = r[2].f[0];
+ }
+ else
+ lodBias = 0.0;
+
+ fetch_texel(mach->Samplers[unit],
+ &r[0], &ZeroVec, &ZeroVec, lodBias, /* S, T, P, 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);
+
+ if (projected) {
+ FETCH(&r[3], 0, CHAN_W);
+ micro_div( &r[0], &r[0], &r[3] );
+ micro_div( &r[1], &r[1], &r[3] );
+ micro_div( &r[2], &r[2], &r[3] );
+ }
+
+ if (biasLod) {
+ FETCH(&r[3], 0, CHAN_W);
+ lodBias = r[3].f[0];
+ }
+ else
+ lodBias = 0.0;
+
+ fetch_texel(mach->Samplers[unit],
+ &r[0], &r[1], &r[2], lodBias, /* inputs */
+ &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 (projected) {
+ FETCH(&r[3], 0, CHAN_W);
+ micro_div( &r[0], &r[0], &r[3] );
+ micro_div( &r[1], &r[1], &r[3] );
+ micro_div( &r[2], &r[2], &r[3] );
+ }
+
+ if (biasLod) {
+ FETCH(&r[3], 0, CHAN_W);
+ lodBias = r[3].f[0];
+ }
+ else
+ lodBias = 0.0;
+
+ fetch_texel(mach->Samplers[unit],
+ &r[0], &r[1], &r[2], lodBias,
+ &r[0], &r[1], &r[2], &r[3]);
+ break;
+
+ default:
+ assert (0);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[chan_index], 0, chan_index );
+ }
+}
+
+
+/**
+ * Evaluate a constant-valued coefficient at the position of the
+ * current quad.
+ */
+static void
+eval_constant_coef(
+ struct tgsi_exec_machine *mach,
+ unsigned attrib,
+ unsigned chan )
+{
+ unsigned i;
+
+ for( i = 0; i < QUAD_SIZE; i++ ) {
+ mach->Inputs[attrib].xyzw[chan].f[i] = mach->InterpCoefs[attrib].a0[chan];
+ }
+}
+
+/**
+ * Evaluate a linear-valued coefficient at the position of the
+ * current quad.
+ */
+static void
+eval_linear_coef(
+ struct tgsi_exec_machine *mach,
+ unsigned attrib,
+ unsigned chan )
+{
+ const float x = mach->QuadPos.xyzw[0].f[0];
+ const float y = mach->QuadPos.xyzw[1].f[0];
+ const float dadx = mach->InterpCoefs[attrib].dadx[chan];
+ const float dady = mach->InterpCoefs[attrib].dady[chan];
+ const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y;
+ mach->Inputs[attrib].xyzw[chan].f[0] = a0;
+ mach->Inputs[attrib].xyzw[chan].f[1] = a0 + dadx;
+ mach->Inputs[attrib].xyzw[chan].f[2] = a0 + dady;
+ mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady;
+}
+
+/**
+ * Evaluate a perspective-valued coefficient at the position of the
+ * current quad.
+ */
+static void
+eval_perspective_coef(
+ struct tgsi_exec_machine *mach,
+ unsigned attrib,
+ unsigned chan )
+{
+ const float x = mach->QuadPos.xyzw[0].f[0];
+ const float y = mach->QuadPos.xyzw[1].f[0];
+ const float dadx = mach->InterpCoefs[attrib].dadx[chan];
+ const float dady = mach->InterpCoefs[attrib].dady[chan];
+ const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y;
+ const float *w = mach->QuadPos.xyzw[3].f;
+ /* divide by W here */
+ mach->Inputs[attrib].xyzw[chan].f[0] = a0 / w[0];
+ mach->Inputs[attrib].xyzw[chan].f[1] = (a0 + dadx) / w[1];
+ mach->Inputs[attrib].xyzw[chan].f[2] = (a0 + dady) / w[2];
+ mach->Inputs[attrib].xyzw[chan].f[3] = (a0 + dadx + dady) / w[3];
+}
+
+
+typedef void (* eval_coef_func)(
+ struct tgsi_exec_machine *mach,
+ unsigned attrib,
+ unsigned chan );
+
+static void
+exec_declaration(
+ struct tgsi_exec_machine *mach,
+ const struct tgsi_full_declaration *decl )
+{
+ if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) {
+ if( decl->Declaration.File == TGSI_FILE_INPUT ) {
+ unsigned first, last, mask;
+ eval_coef_func eval;
+
+ first = decl->DeclarationRange.First;
+ last = decl->DeclarationRange.Last;
+ mask = decl->Declaration.UsageMask;
+
+ switch( decl->Declaration.Interpolate ) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ eval = eval_constant_coef;
+ break;
+
+ case TGSI_INTERPOLATE_LINEAR:
+ eval = eval_linear_coef;
+ break;
+
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ eval = eval_perspective_coef;
+ break;
+
+ default:
+ eval = NULL;
+ assert( 0 );
+ }
+
+ if( mask == TGSI_WRITEMASK_XYZW ) {
+ unsigned i, j;
+
+ for( i = first; i <= last; i++ ) {
+ for( j = 0; j < NUM_CHANNELS; j++ ) {
+ eval( mach, i, j );
+ }
+ }
+ }
+ else {
+ unsigned i, j;
+
+ for( j = 0; j < NUM_CHANNELS; j++ ) {
+ if( mask & (1 << j) ) {
+ for( i = first; i <= last; i++ ) {
+ eval( mach, i, j );
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void
+exec_instruction(
+ struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst,
+ int *pc )
+{
+ uint chan_index;
+ union tgsi_exec_channel r[10];
+
+ (*pc)++;
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ARL:
+ case TGSI_OPCODE_FLR:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_flr( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ if (inst->Flags & SOA_DEPENDENCY_FLAG) {
+ /* Do all fetches into temp regs, then do all stores to avoid
+ * intermediate/accidental clobbering. This could be done all the
+ * time for MOV but for other instructions we'll need more temps...
+ */
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[chan_index], 0, chan_index );
+ }
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[chan_index], 0, chan_index );
+ }
+ }
+ else {
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ STORE( &r[0], 0, chan_index );
+ }
+ }
+ break;
+
+ case TGSI_OPCODE_LIT:
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_X );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y ) || IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ FETCH( &r[0], 0, CHAN_X );
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ micro_max( &r[0], &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+ STORE( &r[0], 0, CHAN_Y );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ FETCH( &r[1], 0, CHAN_Y );
+ micro_max( &r[1], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+
+ FETCH( &r[2], 0, CHAN_W );
+ micro_min( &r[2], &r[2], &mach->Temps[TEMP_128_I].xyzw[TEMP_128_C] );
+ micro_max( &r[2], &r[2], &mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C] );
+ micro_pow( &r[1], &r[1], &r[2] );
+ micro_lt( &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[0], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+ STORE( &r[0], 0, CHAN_Z );
+ }
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_RCP:
+ /* TGSI_OPCODE_RECIP */
+ FETCH( &r[0], 0, CHAN_X );
+ micro_div( &r[0], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &r[0] );
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_RSQ:
+ /* TGSI_OPCODE_RECIPSQRT */
+ FETCH( &r[0], 0, CHAN_X );
+ micro_abs( &r[0], &r[0] );
+ micro_sqrt( &r[0], &r[0] );
+ micro_div( &r[0], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &r[0] );
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_EXP:
+ FETCH( &r[0], 0, CHAN_X );
+ micro_flr( &r[1], &r[0] ); /* r1 = floor(r0) */
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ micro_exp2( &r[2], &r[1] ); /* r2 = 2 ^ r1 */
+ STORE( &r[2], 0, CHAN_X ); /* store r2 */
+ }
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ micro_sub( &r[2], &r[0], &r[1] ); /* r2 = r0 - r1 */
+ STORE( &r[2], 0, CHAN_Y ); /* store r2 */
+ }
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ micro_exp2( &r[2], &r[0] ); /* r2 = 2 ^ r0 */
+ STORE( &r[2], 0, CHAN_Z ); /* store r2 */
+ }
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_LOG:
+ FETCH( &r[0], 0, CHAN_X );
+ micro_abs( &r[2], &r[0] ); /* r2 = abs(r0) */
+ micro_lg2( &r[1], &r[2] ); /* r1 = lg2(r2) */
+ micro_flr( &r[0], &r[1] ); /* r0 = floor(r1) */
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ STORE( &r[0], 0, CHAN_X );
+ }
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ micro_exp2( &r[0], &r[0] ); /* r0 = 2 ^ r0 */
+ micro_div( &r[0], &r[2], &r[0] ); /* r0 = r2 / r0 */
+ STORE( &r[0], 0, CHAN_Y );
+ }
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ STORE( &r[1], 0, CHAN_Z );
+ }
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_MUL:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index )
+ {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+
+ micro_mul( &r[0], &r[0], &r[1] );
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_ADD:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_add( &r[0], &r[0], &r[1] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DP3:
+ /* TGSI_OPCODE_DOT3 */
+ FETCH( &r[0], 0, CHAN_X );
+ FETCH( &r[1], 1, CHAN_X );
+ micro_mul( &r[0], &r[0], &r[1] );
+
+ FETCH( &r[1], 0, CHAN_Y );
+ FETCH( &r[2], 1, CHAN_Y );
+ micro_mul( &r[1], &r[1], &r[2] );
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FETCH( &r[1], 0, CHAN_Z );
+ FETCH( &r[2], 1, CHAN_Z );
+ micro_mul( &r[1], &r[1], &r[2] );
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DP4:
+ /* TGSI_OPCODE_DOT4 */
+ FETCH(&r[0], 0, CHAN_X);
+ FETCH(&r[1], 1, CHAN_X);
+
+ micro_mul( &r[0], &r[0], &r[1] );
+
+ FETCH(&r[1], 0, CHAN_Y);
+ FETCH(&r[2], 1, CHAN_Y);
+
+ micro_mul( &r[1], &r[1], &r[2] );
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FETCH(&r[1], 0, CHAN_Z);
+ FETCH(&r[2], 1, CHAN_Z);
+
+ micro_mul( &r[1], &r[1], &r[2] );
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FETCH(&r[1], 0, CHAN_W);
+ FETCH(&r[2], 1, CHAN_W);
+
+ micro_mul( &r[1], &r[1], &r[2] );
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DST:
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_X );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ FETCH( &r[0], 0, CHAN_Y );
+ FETCH( &r[1], 1, CHAN_Y);
+ micro_mul( &r[0], &r[0], &r[1] );
+ STORE( &r[0], 0, CHAN_Y );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ FETCH( &r[0], 0, CHAN_Z );
+ STORE( &r[0], 0, CHAN_Z );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ FETCH( &r[0], 1, CHAN_W );
+ STORE( &r[0], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_MIN:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+
+ /* XXX use micro_min()?? */
+ micro_lt( &r[0], &r[0], &r[1], &r[0], &r[1] );
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_MAX:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+
+ /* XXX use micro_max()?? */
+ micro_lt( &r[0], &r[0], &r[1], &r[1], &r[0] );
+
+ STORE(&r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SLT:
+ /* TGSI_OPCODE_SETLT */
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_lt( &r[0], &r[0], &r[1], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SGE:
+ /* TGSI_OPCODE_SETGE */
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_le( &r[0], &r[1], &r[0], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_MAD:
+ /* TGSI_OPCODE_MADD */
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_mul( &r[0], &r[0], &r[1] );
+ FETCH( &r[1], 2, chan_index );
+ micro_add( &r[0], &r[0], &r[1] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SUB:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+
+ micro_sub( &r[0], &r[0], &r[1] );
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_LRP:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+ FETCH(&r[2], 2, chan_index);
+
+ micro_sub( &r[1], &r[1], &r[2] );
+ micro_mul( &r[0], &r[0], &r[1] );
+ micro_add( &r[0], &r[0], &r[2] );
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_CND:
+ FOR_EACH_ENABLED_CHANNEL(*inst, chan_index) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+ FETCH(&r[2], 2, chan_index);
+ micro_lt(&r[0], &mach->Temps[TEMP_HALF_I].xyzw[TEMP_HALF_C], &r[2], &r[0], &r[1]);
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_DP2A:
+ FETCH( &r[0], 0, CHAN_X );
+ FETCH( &r[1], 1, CHAN_X );
+ micro_mul( &r[0], &r[0], &r[1] );
+
+ FETCH( &r[1], 0, CHAN_Y );
+ FETCH( &r[2], 1, CHAN_Y );
+ micro_mul( &r[1], &r[1], &r[2] );
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FETCH( &r[2], 2, CHAN_X );
+ micro_add( &r[0], &r[0], &r[2] );
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_FRC:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_frc( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_CLAMP:
+ FOR_EACH_ENABLED_CHANNEL(*inst, chan_index) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+ micro_max(&r[0], &r[0], &r[1]);
+ FETCH(&r[1], 2, chan_index);
+ micro_min(&r[0], &r[0], &r[1]);
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_ROUND:
+ case TGSI_OPCODE_ARR:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_rnd( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_EX2:
+ FETCH(&r[0], 0, CHAN_X);
+
+#if FAST_MATH
+ micro_exp2( &r[0], &r[0] );
+#else
+ micro_pow( &r[0], &mach->Temps[TEMP_2_I].xyzw[TEMP_2_C], &r[0] );
+#endif
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_LG2:
+ FETCH( &r[0], 0, CHAN_X );
+ micro_lg2( &r[0], &r[0] );
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_POW:
+ FETCH(&r[0], 0, CHAN_X);
+ FETCH(&r[1], 1, CHAN_X);
+
+ micro_pow( &r[0], &r[0], &r[1] );
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_XPD:
+ FETCH(&r[0], 0, CHAN_Y);
+ FETCH(&r[1], 1, CHAN_Z);
+
+ micro_mul( &r[2], &r[0], &r[1] );
+
+ FETCH(&r[3], 0, CHAN_Z);
+ FETCH(&r[4], 1, CHAN_Y);
+
+ micro_mul( &r[5], &r[3], &r[4] );
+ micro_sub( &r[2], &r[2], &r[5] );
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ STORE( &r[2], 0, CHAN_X );
+ }
+
+ FETCH(&r[2], 1, CHAN_X);
+
+ micro_mul( &r[3], &r[3], &r[2] );
+
+ FETCH(&r[5], 0, CHAN_X);
+
+ micro_mul( &r[1], &r[1], &r[5] );
+ micro_sub( &r[3], &r[3], &r[1] );
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ STORE( &r[3], 0, CHAN_Y );
+ }
+
+ micro_mul( &r[5], &r[5], &r[4] );
+ micro_mul( &r[0], &r[0], &r[2] );
+ micro_sub( &r[5], &r[5], &r[0] );
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ STORE( &r[5], 0, CHAN_Z );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_ABS:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+
+ micro_abs( &r[0], &r[0] );
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_RCC:
+ FETCH(&r[0], 0, CHAN_X);
+ micro_div(&r[0], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &r[0]);
+ micro_float_clamp(&r[0], &r[0]);
+ FOR_EACH_ENABLED_CHANNEL(*inst, chan_index) {
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_DPH:
+ FETCH(&r[0], 0, CHAN_X);
+ FETCH(&r[1], 1, CHAN_X);
+
+ micro_mul( &r[0], &r[0], &r[1] );
+
+ FETCH(&r[1], 0, CHAN_Y);
+ FETCH(&r[2], 1, CHAN_Y);
+
+ micro_mul( &r[1], &r[1], &r[2] );
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FETCH(&r[1], 0, CHAN_Z);
+ FETCH(&r[2], 1, CHAN_Z);
+
+ micro_mul( &r[1], &r[1], &r[2] );
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FETCH(&r[1], 1, CHAN_W);
+
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_COS:
+ FETCH(&r[0], 0, CHAN_X);
+
+ micro_cos( &r[0], &r[0] );
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DDX:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_ddx( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DDY:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_ddy( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_KILP:
+ exec_kilp (mach, inst);
+ break;
+
+ case TGSI_OPCODE_KIL:
+ exec_kil (mach, inst);
+ break;
+
+ case TGSI_OPCODE_PK2H:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_PK2US:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_PK4B:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_PK4UB:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_RFL:
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_X) ||
+ IS_CHANNEL_ENABLED(*inst, CHAN_Y) ||
+ IS_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ /* r0 = dp3(src0, src0) */
+ FETCH(&r[2], 0, CHAN_X);
+ micro_mul(&r[0], &r[2], &r[2]);
+ FETCH(&r[4], 0, CHAN_Y);
+ micro_mul(&r[8], &r[4], &r[4]);
+ micro_add(&r[0], &r[0], &r[8]);
+ FETCH(&r[6], 0, CHAN_Z);
+ micro_mul(&r[8], &r[6], &r[6]);
+ micro_add(&r[0], &r[0], &r[8]);
+
+ /* r1 = dp3(src0, src1) */
+ FETCH(&r[3], 1, CHAN_X);
+ micro_mul(&r[1], &r[2], &r[3]);
+ FETCH(&r[5], 1, CHAN_Y);
+ micro_mul(&r[8], &r[4], &r[5]);
+ micro_add(&r[1], &r[1], &r[8]);
+ FETCH(&r[7], 1, CHAN_Z);
+ micro_mul(&r[8], &r[6], &r[7]);
+ micro_add(&r[1], &r[1], &r[8]);
+
+ /* r1 = 2 * r1 / r0 */
+ micro_add(&r[1], &r[1], &r[1]);
+ micro_div(&r[1], &r[1], &r[0]);
+
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_X)) {
+ micro_mul(&r[2], &r[2], &r[1]);
+ micro_sub(&r[2], &r[2], &r[3]);
+ STORE(&r[2], 0, CHAN_X);
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ micro_mul(&r[4], &r[4], &r[1]);
+ micro_sub(&r[4], &r[4], &r[5]);
+ STORE(&r[4], 0, CHAN_Y);
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ micro_mul(&r[6], &r[6], &r[1]);
+ micro_sub(&r[6], &r[6], &r[7]);
+ STORE(&r[6], 0, CHAN_Z);
+ }
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_W)) {
+ STORE(&mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W);
+ }
+ break;
+
+ case TGSI_OPCODE_SEQ:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_eq( &r[0], &r[0], &r[1],
+ &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C],
+ &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SFL:
+ FOR_EACH_ENABLED_CHANNEL(*inst, chan_index) {
+ STORE(&mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_SGT:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_le( &r[0], &r[0], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SIN:
+ FETCH( &r[0], 0, CHAN_X );
+ micro_sin( &r[0], &r[0] );
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SLE:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_le( &r[0], &r[0], &r[1], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SNE:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_eq( &r[0], &r[0], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_STR:
+ FOR_EACH_ENABLED_CHANNEL(*inst, chan_index) {
+ STORE(&mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_TEX:
+ /* simple texture lookup */
+ /* src[0] = texcoord */
+ /* src[1] = sampler unit */
+ exec_tex(mach, inst, FALSE, FALSE);
+ break;
+
+ case TGSI_OPCODE_TXB:
+ /* Texture lookup with lod bias */
+ /* src[0] = texcoord (src[0].w = LOD bias) */
+ /* src[1] = sampler unit */
+ exec_tex(mach, inst, TRUE, FALSE);
+ break;
+
+ case TGSI_OPCODE_TXD:
+ /* Texture lookup with explict partial derivatives */
+ /* src[0] = texcoord */
+ /* src[1] = d[strq]/dx */
+ /* src[2] = d[strq]/dy */
+ /* src[3] = sampler unit */
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_TXL:
+ /* Texture lookup with explit LOD */
+ /* src[0] = texcoord (src[0].w = LOD) */
+ /* src[1] = sampler unit */
+ exec_tex(mach, inst, TRUE, FALSE);
+ break;
+
+ case TGSI_OPCODE_TXP:
+ /* Texture lookup with projection */
+ /* src[0] = texcoord (src[0].w = projection) */
+ /* src[1] = sampler unit */
+ exec_tex(mach, inst, FALSE, TRUE);
+ break;
+
+ case TGSI_OPCODE_UP2H:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_UP2US:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_UP4B:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_UP4UB:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_X2D:
+ FETCH(&r[0], 1, CHAN_X);
+ FETCH(&r[1], 1, CHAN_Y);
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_X) ||
+ IS_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ FETCH(&r[2], 2, CHAN_X);
+ micro_mul(&r[2], &r[2], &r[0]);
+ FETCH(&r[3], 2, CHAN_Y);
+ micro_mul(&r[3], &r[3], &r[1]);
+ micro_add(&r[2], &r[2], &r[3]);
+ FETCH(&r[3], 0, CHAN_X);
+ micro_add(&r[2], &r[2], &r[3]);
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_X)) {
+ STORE(&r[2], 0, CHAN_X);
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ STORE(&r[2], 0, CHAN_Z);
+ }
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_Y) ||
+ IS_CHANNEL_ENABLED(*inst, CHAN_W)) {
+ FETCH(&r[2], 2, CHAN_Z);
+ micro_mul(&r[2], &r[2], &r[0]);
+ FETCH(&r[3], 2, CHAN_W);
+ micro_mul(&r[3], &r[3], &r[1]);
+ micro_add(&r[2], &r[2], &r[3]);
+ FETCH(&r[3], 0, CHAN_Y);
+ micro_add(&r[2], &r[2], &r[3]);
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ STORE(&r[2], 0, CHAN_Y);
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_W)) {
+ STORE(&r[2], 0, CHAN_W);
+ }
+ }
+ break;
+
+ case TGSI_OPCODE_ARA:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_BRA:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_CAL:
+ /* skip the call if no execution channels are enabled */
+ if (mach->ExecMask) {
+ /* do the call */
+
+ /* First, record the depths of the execution stacks.
+ * This is important for deeply nested/looped return statements.
+ * We have to unwind the stacks by the correct amount. For a
+ * real code generator, we could determine the number of entries
+ * to pop off each stack with simple static analysis and avoid
+ * implementing this data structure at run time.
+ */
+ mach->CallStack[mach->CallStackTop].CondStackTop = mach->CondStackTop;
+ mach->CallStack[mach->CallStackTop].LoopStackTop = mach->LoopStackTop;
+ mach->CallStack[mach->CallStackTop].ContStackTop = mach->ContStackTop;
+ /* note that PC was already incremented above */
+ mach->CallStack[mach->CallStackTop].ReturnAddr = *pc;
+
+ mach->CallStackTop++;
+
+ /* Second, push the Cond, Loop, Cont, Func stacks */
+ assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
+ mach->CondStack[mach->CondStackTop++] = mach->CondMask;
+ assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
+ assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->ContStack[mach->ContStackTop++] = mach->ContMask;
+ assert(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING);
+ mach->FuncStack[mach->FuncStackTop++] = mach->FuncMask;
+
+ /* Finally, jump to the subroutine */
+ *pc = inst->InstructionExtLabel.Label;
+ }
+ break;
+
+ case TGSI_OPCODE_RET:
+ mach->FuncMask &= ~mach->ExecMask;
+ UPDATE_EXEC_MASK(mach);
+
+ if (mach->FuncMask == 0x0) {
+ /* really return now (otherwise, keep executing */
+
+ if (mach->CallStackTop == 0) {
+ /* returning from main() */
+ *pc = -1;
+ return;
+ }
+
+ assert(mach->CallStackTop > 0);
+ mach->CallStackTop--;
+
+ mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop;
+ mach->CondMask = mach->CondStack[mach->CondStackTop];
+
+ mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop;
+ mach->LoopMask = mach->LoopStack[mach->LoopStackTop];
+
+ mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop;
+ mach->ContMask = mach->ContStack[mach->ContStackTop];
+
+ assert(mach->FuncStackTop > 0);
+ mach->FuncMask = mach->FuncStack[--mach->FuncStackTop];
+
+ *pc = mach->CallStack[mach->CallStackTop].ReturnAddr;
+
+ UPDATE_EXEC_MASK(mach);
+ }
+ break;
+
+ case TGSI_OPCODE_SSG:
+ /* TGSI_OPCODE_SGN */
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_sgn( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_CMP:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+ FETCH(&r[2], 2, chan_index);
+
+ micro_lt( &r[0], &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[1], &r[2] );
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_SCS:
+ if( IS_CHANNEL_ENABLED( *inst, CHAN_X ) || IS_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
+ FETCH( &r[0], 0, CHAN_X );
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_X)) {
+ micro_cos(&r[1], &r[0]);
+ STORE(&r[1], 0, CHAN_X);
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ micro_sin(&r[1], &r[0]);
+ STORE(&r[1], 0, CHAN_Y);
+ }
+ }
+ if( IS_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
+ STORE( &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], 0, CHAN_Z );
+ }
+ if( IS_CHANNEL_ENABLED( *inst, CHAN_W ) ) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_NRM:
+ /* 3-component vector normalize */
+ if(IS_CHANNEL_ENABLED(*inst, CHAN_X) ||
+ IS_CHANNEL_ENABLED(*inst, CHAN_Y) ||
+ IS_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ /* r3 = sqrt(dp3(src0, src0)) */
+ FETCH(&r[0], 0, CHAN_X);
+ micro_mul(&r[3], &r[0], &r[0]);
+ FETCH(&r[1], 0, CHAN_Y);
+ micro_mul(&r[4], &r[1], &r[1]);
+ micro_add(&r[3], &r[3], &r[4]);
+ FETCH(&r[2], 0, CHAN_Z);
+ micro_mul(&r[4], &r[2], &r[2]);
+ micro_add(&r[3], &r[3], &r[4]);
+ micro_sqrt(&r[3], &r[3]);
+
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_X)) {
+ micro_div(&r[0], &r[0], &r[3]);
+ STORE(&r[0], 0, CHAN_X);
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ micro_div(&r[1], &r[1], &r[3]);
+ STORE(&r[1], 0, CHAN_Y);
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ micro_div(&r[2], &r[2], &r[3]);
+ STORE(&r[2], 0, CHAN_Z);
+ }
+ }
+ if (IS_CHANNEL_ENABLED(*inst, CHAN_W)) {
+ STORE(&mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W);
+ }
+ break;
+
+ case TGSI_OPCODE_NRM4:
+ /* 4-component vector normalize */
+ {
+ union tgsi_exec_channel tmp, dot;
+
+ /* tmp = dp4(src0, src0): */
+ FETCH( &r[0], 0, CHAN_X );
+ micro_mul( &tmp, &r[0], &r[0] );
+
+ FETCH( &r[1], 0, CHAN_Y );
+ micro_mul( &dot, &r[1], &r[1] );
+ micro_add( &tmp, &tmp, &dot );
+
+ FETCH( &r[2], 0, CHAN_Z );
+ micro_mul( &dot, &r[2], &r[2] );
+ micro_add( &tmp, &tmp, &dot );
+
+ FETCH( &r[3], 0, CHAN_W );
+ micro_mul( &dot, &r[3], &r[3] );
+ micro_add( &tmp, &tmp, &dot );
+
+ /* tmp = 1 / sqrt(tmp) */
+ micro_sqrt( &tmp, &tmp );
+ micro_div( &tmp, &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &tmp );
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ /* chan = chan * tmp */
+ micro_mul( &r[chan_index], &tmp, &r[chan_index] );
+ STORE( &r[chan_index], 0, chan_index );
+ }
+ }
+ break;
+
+ case TGSI_OPCODE_DIV:
+ assert( 0 );
+ break;
+
+ case TGSI_OPCODE_DP2:
+ FETCH( &r[0], 0, CHAN_X );
+ FETCH( &r[1], 1, CHAN_X );
+ micro_mul( &r[0], &r[0], &r[1] );
+
+ FETCH( &r[1], 0, CHAN_Y );
+ FETCH( &r[2], 1, CHAN_Y );
+ micro_mul( &r[1], &r[1], &r[2] );
+ micro_add( &r[0], &r[0], &r[1] );
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_IF:
+ /* push CondMask */
+ assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
+ mach->CondStack[mach->CondStackTop++] = mach->CondMask;
+ FETCH( &r[0], 0, CHAN_X );
+ /* update CondMask */
+ if( ! r[0].u[0] ) {
+ mach->CondMask &= ~0x1;
+ }
+ if( ! r[0].u[1] ) {
+ mach->CondMask &= ~0x2;
+ }
+ if( ! r[0].u[2] ) {
+ mach->CondMask &= ~0x4;
+ }
+ if( ! r[0].u[3] ) {
+ mach->CondMask &= ~0x8;
+ }
+ UPDATE_EXEC_MASK(mach);
+ /* Todo: If CondMask==0, jump to ELSE */
+ break;
+
+ case TGSI_OPCODE_ELSE:
+ /* invert CondMask wrt previous mask */
+ {
+ uint prevMask;
+ assert(mach->CondStackTop > 0);
+ prevMask = mach->CondStack[mach->CondStackTop - 1];
+ mach->CondMask = ~mach->CondMask & prevMask;
+ UPDATE_EXEC_MASK(mach);
+ /* Todo: If CondMask==0, jump to ENDIF */
+ }
+ break;
+
+ case TGSI_OPCODE_ENDIF:
+ /* pop CondMask */
+ assert(mach->CondStackTop > 0);
+ mach->CondMask = mach->CondStack[--mach->CondStackTop];
+ UPDATE_EXEC_MASK(mach);
+ break;
+
+ case TGSI_OPCODE_END:
+ /* halt execution */
+ *pc = -1;
+ break;
+
+ case TGSI_OPCODE_REP:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_ENDREP:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_PUSHA:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_POPA:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_CEIL:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_ceil( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_I2F:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_i2f( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_NOT:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_not( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_TRUNC:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ micro_trunc( &r[0], &r[0] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SHL:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_shl( &r[0], &r[0], &r[1] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SHR:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_ishr( &r[0], &r[0], &r[1] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_AND:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_and( &r[0], &r[0], &r[1] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_OR:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_or( &r[0], &r[0], &r[1] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_MOD:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_XOR:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ micro_xor( &r[0], &r[0], &r[1] );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SAD:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_TXF:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_TXQ:
+ assert (0);
+ break;
+
+ case TGSI_OPCODE_EMIT:
+ mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] += 16;
+ mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]]++;
+ break;
+
+ case TGSI_OPCODE_ENDPRIM:
+ mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]++;
+ mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]] = 0;
+ break;
+
+ case TGSI_OPCODE_BGNFOR:
+ assert(mach->LoopCounterStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ for (chan_index = 0; chan_index < 3; chan_index++) {
+ FETCH( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[chan_index], 0, chan_index );
+ }
+ STORE( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[CHAN_Y], 0, CHAN_X );
+ ++mach->LoopCounterStackTop;
+ /* fall-through (for now) */
+ case TGSI_OPCODE_BGNLOOP:
+ /* push LoopMask and ContMasks */
+ assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
+ assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->ContStack[mach->ContStackTop++] = mach->ContMask;
+ assert(mach->LoopLabelStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->LoopLabelStack[mach->LoopLabelStackTop++] = *pc - 1;
+ break;
+
+ case TGSI_OPCODE_ENDFOR:
+ assert(mach->LoopCounterStackTop > 0);
+ micro_sub( &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X],
+ &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X],
+ &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] );
+ /* update LoopMask */
+ if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[0] <= 0) {
+ mach->LoopMask &= ~0x1;
+ }
+ if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[1] <= 0 ) {
+ mach->LoopMask &= ~0x2;
+ }
+ if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[2] <= 0 ) {
+ mach->LoopMask &= ~0x4;
+ }
+ if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[3] <= 0 ) {
+ mach->LoopMask &= ~0x8;
+ }
+ micro_add( &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Y],
+ &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Y],
+ &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Z]);
+ assert(mach->LoopLabelStackTop > 0);
+ inst = mach->Instructions + mach->LoopLabelStack[mach->LoopLabelStackTop - 1];
+ STORE( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[CHAN_Y], 0, CHAN_X );
+ /* Restore ContMask, but don't pop */
+ assert(mach->ContStackTop > 0);
+ mach->ContMask = mach->ContStack[mach->ContStackTop - 1];
+ UPDATE_EXEC_MASK(mach);
+ if (mach->ExecMask) {
+ /* repeat loop: jump to instruction just past BGNLOOP */
+ assert(mach->LoopLabelStackTop > 0);
+ *pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1;
+ }
+ else {
+ /* exit loop: pop LoopMask */
+ assert(mach->LoopStackTop > 0);
+ mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
+ /* pop ContMask */
+ assert(mach->ContStackTop > 0);
+ mach->ContMask = mach->ContStack[--mach->ContStackTop];
+ assert(mach->LoopLabelStackTop > 0);
+ --mach->LoopLabelStackTop;
+ assert(mach->LoopCounterStackTop > 0);
+ --mach->LoopCounterStackTop;
+ }
+ UPDATE_EXEC_MASK(mach);
+ break;
+
+ case TGSI_OPCODE_ENDLOOP:
+ /* Restore ContMask, but don't pop */
+ assert(mach->ContStackTop > 0);
+ mach->ContMask = mach->ContStack[mach->ContStackTop - 1];
+ UPDATE_EXEC_MASK(mach);
+ if (mach->ExecMask) {
+ /* repeat loop: jump to instruction just past BGNLOOP */
+ assert(mach->LoopLabelStackTop > 0);
+ *pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1;
+ }
+ else {
+ /* exit loop: pop LoopMask */
+ assert(mach->LoopStackTop > 0);
+ mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
+ /* pop ContMask */
+ assert(mach->ContStackTop > 0);
+ mach->ContMask = mach->ContStack[--mach->ContStackTop];
+ assert(mach->LoopLabelStackTop > 0);
+ --mach->LoopLabelStackTop;
+ }
+ UPDATE_EXEC_MASK(mach);
+ break;
+
+ case TGSI_OPCODE_BRK:
+ /* turn off loop channels for each enabled exec channel */
+ mach->LoopMask &= ~mach->ExecMask;
+ /* Todo: if mach->LoopMask == 0, jump to end of loop */
+ UPDATE_EXEC_MASK(mach);
+ break;
+
+ case TGSI_OPCODE_CONT:
+ /* turn off cont channels for each enabled exec channel */
+ mach->ContMask &= ~mach->ExecMask;
+ /* Todo: if mach->LoopMask == 0, jump to end of loop */
+ UPDATE_EXEC_MASK(mach);
+ break;
+
+ case TGSI_OPCODE_BGNSUB:
+ /* no-op */
+ break;
+
+ case TGSI_OPCODE_ENDSUB:
+ /* no-op */
+ break;
+
+ case TGSI_OPCODE_NOISE1:
+ assert( 0 );
+ break;
+
+ case TGSI_OPCODE_NOISE2:
+ assert( 0 );
+ break;
+
+ case TGSI_OPCODE_NOISE3:
+ assert( 0 );
+ break;
+
+ case TGSI_OPCODE_NOISE4:
+ assert( 0 );
+ break;
+
+ case TGSI_OPCODE_NOP:
+ break;
+
+ default:
+ assert( 0 );
+ }
+}
+
+
+/**
+ * Run TGSI interpreter.
+ * \return bitmask of "alive" quad components
+ */
+uint
+tgsi_exec_machine_run( struct tgsi_exec_machine *mach )
+{
+ uint i;
+ int pc = 0;
+
+ mach->CondMask = 0xf;
+ mach->LoopMask = 0xf;
+ mach->ContMask = 0xf;
+ mach->FuncMask = 0xf;
+ mach->ExecMask = 0xf;
+
+ assert(mach->CondStackTop == 0);
+ assert(mach->LoopStackTop == 0);
+ assert(mach->ContStackTop == 0);
+ assert(mach->CallStackTop == 0);
+
+ mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0;
+ mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] = 0;
+
+ if( mach->Processor == TGSI_PROCESSOR_GEOMETRY ) {
+ mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0] = 0;
+ mach->Primitives[0] = 0;
+ }
+
+ for (i = 0; i < QUAD_SIZE; i++) {
+ mach->Temps[TEMP_CC_I].xyzw[TEMP_CC_C].u[i] =
+ (TGSI_EXEC_CC_EQ << TGSI_EXEC_CC_X_SHIFT) |
+ (TGSI_EXEC_CC_EQ << TGSI_EXEC_CC_Y_SHIFT) |
+ (TGSI_EXEC_CC_EQ << TGSI_EXEC_CC_Z_SHIFT) |
+ (TGSI_EXEC_CC_EQ << TGSI_EXEC_CC_W_SHIFT);
+ }
+
+ /* execute declarations (interpolants) */
+ for (i = 0; i < mach->NumDeclarations; i++) {
+ exec_declaration( mach, mach->Declarations+i );
+ }
+
+ /* execute instructions, until pc is set to -1 */
+ while (pc != -1) {
+ assert(pc < (int) mach->NumInstructions);
+ exec_instruction( mach, mach->Instructions + pc, &pc );
+ }
+
+#if 0
+ /* we scale from floats in [0,1] to Zbuffer ints in sp_quad_depth_test.c */
+ if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
+ /*
+ * Scale back depth component.
+ */
+ for (i = 0; i < 4; i++)
+ mach->Outputs[0].xyzw[2].f[i] *= ctx->DrawBuffer->_DepthMaxF;
+ }
+#endif
+
+ return ~mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
new file mode 100644
index 0000000000..c72f76809d
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -0,0 +1,327 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_EXEC_H
+#define TGSI_EXEC_H
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+#define MAX_LABELS (4 * 1024) /**< basically, max instructions */
+
+#define NUM_CHANNELS 4 /* R,G,B,A */
+#define QUAD_SIZE 4 /* 4 pixel/quad */
+
+/**
+ * Registers may be treated as float, signed int or unsigned int.
+ */
+union tgsi_exec_channel
+{
+ float f[QUAD_SIZE];
+ int i[QUAD_SIZE];
+ unsigned u[QUAD_SIZE];
+};
+
+/**
+ * A vector[RGBA] of channels[4 pixels]
+ */
+struct tgsi_exec_vector
+{
+ union tgsi_exec_channel xyzw[NUM_CHANNELS];
+};
+
+/**
+ * For fragment programs, information for computing fragment input
+ * values from plane equation of the triangle/line.
+ */
+struct tgsi_interp_coef
+{
+ float a0[NUM_CHANNELS]; /* in an xyzw layout */
+ float dadx[NUM_CHANNELS];
+ float dady[NUM_CHANNELS];
+};
+
+/**
+ * Information for sampling textures, which must be implemented
+ * by code outside the TGSI executor.
+ */
+struct tgsi_sampler
+{
+ /** Get samples for four fragments in a quad */
+ void (*get_samples)(struct tgsi_sampler *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE]);
+};
+
+/**
+ * For branching/calling subroutines.
+ */
+struct tgsi_exec_labels
+{
+ unsigned labels[MAX_LABELS][2];
+ unsigned count;
+};
+
+
+#define TGSI_EXEC_NUM_TEMPS 128
+#define TGSI_EXEC_NUM_IMMEDIATES 256
+
+/*
+ * Locations of various utility registers (_I = Index, _C = Channel)
+ */
+#define TGSI_EXEC_TEMP_00000000_I (TGSI_EXEC_NUM_TEMPS + 0)
+#define TGSI_EXEC_TEMP_00000000_C 0
+
+#define TGSI_EXEC_TEMP_7FFFFFFF_I (TGSI_EXEC_NUM_TEMPS + 0)
+#define TGSI_EXEC_TEMP_7FFFFFFF_C 1
+
+#define TGSI_EXEC_TEMP_80000000_I (TGSI_EXEC_NUM_TEMPS + 0)
+#define TGSI_EXEC_TEMP_80000000_C 2
+
+#define TGSI_EXEC_TEMP_FFFFFFFF_I (TGSI_EXEC_NUM_TEMPS + 0)
+#define TGSI_EXEC_TEMP_FFFFFFFF_C 3
+
+#define TGSI_EXEC_TEMP_ONE_I (TGSI_EXEC_NUM_TEMPS + 1)
+#define TGSI_EXEC_TEMP_ONE_C 0
+
+#define TGSI_EXEC_TEMP_TWO_I (TGSI_EXEC_NUM_TEMPS + 1)
+#define TGSI_EXEC_TEMP_TWO_C 1
+
+#define TGSI_EXEC_TEMP_128_I (TGSI_EXEC_NUM_TEMPS + 1)
+#define TGSI_EXEC_TEMP_128_C 2
+
+#define TGSI_EXEC_TEMP_MINUS_128_I (TGSI_EXEC_NUM_TEMPS + 1)
+#define TGSI_EXEC_TEMP_MINUS_128_C 3
+
+#define TGSI_EXEC_TEMP_KILMASK_I (TGSI_EXEC_NUM_TEMPS + 2)
+#define TGSI_EXEC_TEMP_KILMASK_C 0
+
+#define TGSI_EXEC_TEMP_OUTPUT_I (TGSI_EXEC_NUM_TEMPS + 2)
+#define TGSI_EXEC_TEMP_OUTPUT_C 1
+
+#define TGSI_EXEC_TEMP_PRIMITIVE_I (TGSI_EXEC_NUM_TEMPS + 2)
+#define TGSI_EXEC_TEMP_PRIMITIVE_C 2
+
+/* NVIDIA condition code (CC) vector
+ */
+#define TGSI_EXEC_CC_GT 0x01
+#define TGSI_EXEC_CC_EQ 0x02
+#define TGSI_EXEC_CC_LT 0x04
+#define TGSI_EXEC_CC_UN 0x08
+
+#define TGSI_EXEC_CC_X_MASK 0x000000ff
+#define TGSI_EXEC_CC_X_SHIFT 0
+#define TGSI_EXEC_CC_Y_MASK 0x0000ff00
+#define TGSI_EXEC_CC_Y_SHIFT 8
+#define TGSI_EXEC_CC_Z_MASK 0x00ff0000
+#define TGSI_EXEC_CC_Z_SHIFT 16
+#define TGSI_EXEC_CC_W_MASK 0xff000000
+#define TGSI_EXEC_CC_W_SHIFT 24
+
+#define TGSI_EXEC_TEMP_CC_I (TGSI_EXEC_NUM_TEMPS + 2)
+#define TGSI_EXEC_TEMP_CC_C 3
+
+#define TGSI_EXEC_TEMP_THREE_I (TGSI_EXEC_NUM_TEMPS + 3)
+#define TGSI_EXEC_TEMP_THREE_C 0
+
+#define TGSI_EXEC_TEMP_HALF_I (TGSI_EXEC_NUM_TEMPS + 3)
+#define TGSI_EXEC_TEMP_HALF_C 1
+
+/* execution mask, each value is either 0 or ~0 */
+#define TGSI_EXEC_MASK_I (TGSI_EXEC_NUM_TEMPS + 3)
+#define TGSI_EXEC_MASK_C 2
+
+/* 4 register buffer for various purposes */
+#define TGSI_EXEC_TEMP_R0 (TGSI_EXEC_NUM_TEMPS + 4)
+#define TGSI_EXEC_NUM_TEMP_R 4
+
+#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 8)
+#define TGSI_EXEC_NUM_ADDRS 1
+#define TGSI_EXEC_NUM_TEMP_EXTRAS 9
+
+
+
+#define TGSI_EXEC_MAX_COND_NESTING 20
+#define TGSI_EXEC_MAX_LOOP_NESTING 20
+#define TGSI_EXEC_MAX_CALL_NESTING 20
+
+/* The maximum number of input attributes per vertex. For 2D
+ * input register files, this is the stride between two 1D
+ * arrays.
+ */
+#define TGSI_EXEC_MAX_INPUT_ATTRIBS 17
+
+/* The maximum number of constant vectors per constant buffer.
+ */
+#define TGSI_EXEC_MAX_CONST_BUFFER 4096
+
+
+/** function call/activation record */
+struct tgsi_call_record
+{
+ uint CondStackTop;
+ uint LoopStackTop;
+ uint ContStackTop;
+ uint ReturnAddr;
+};
+
+
+/**
+ * Run-time virtual machine state for executing TGSI shader.
+ */
+struct tgsi_exec_machine
+{
+ /* Total = program temporaries + internal temporaries
+ */
+ struct tgsi_exec_vector Temps[TGSI_EXEC_NUM_TEMPS +
+ TGSI_EXEC_NUM_TEMP_EXTRAS];
+
+ float Imms[TGSI_EXEC_NUM_IMMEDIATES][4];
+
+ struct tgsi_exec_vector Inputs[PIPE_MAX_ATTRIBS];
+ struct tgsi_exec_vector Outputs[PIPE_MAX_ATTRIBS];
+
+ struct tgsi_exec_vector *Addrs;
+
+ struct tgsi_sampler **Samplers;
+
+ unsigned ImmLimit;
+ const float (*Consts)[4];
+ const struct tgsi_token *Tokens; /**< Declarations, instructions */
+ unsigned Processor; /**< TGSI_PROCESSOR_x */
+
+ /* GEOMETRY processor only. */
+ unsigned *Primitives;
+
+ /* FRAGMENT processor only. */
+ const struct tgsi_interp_coef *InterpCoefs;
+ struct tgsi_exec_vector QuadPos;
+
+ /* Conditional execution masks */
+ uint CondMask; /**< For IF/ELSE/ENDIF */
+ uint LoopMask; /**< For BGNLOOP/ENDLOOP */
+ uint ContMask; /**< For loop CONT statements */
+ uint FuncMask; /**< For function calls */
+ uint ExecMask; /**< = CondMask & LoopMask */
+
+ /** Condition mask stack (for nested conditionals) */
+ uint CondStack[TGSI_EXEC_MAX_COND_NESTING];
+ int CondStackTop;
+
+ /** Loop mask stack (for nested loops) */
+ uint LoopStack[TGSI_EXEC_MAX_LOOP_NESTING];
+ int LoopStackTop;
+
+ /** Loop label stack */
+ uint LoopLabelStack[TGSI_EXEC_MAX_LOOP_NESTING];
+ int LoopLabelStackTop;
+
+ /** Loop counter stack (x = count, y = current, z = step) */
+ struct tgsi_exec_vector LoopCounterStack[TGSI_EXEC_MAX_LOOP_NESTING];
+ int LoopCounterStackTop;
+
+ /** Loop continue mask stack (see comments in tgsi_exec.c) */
+ uint ContStack[TGSI_EXEC_MAX_LOOP_NESTING];
+ int ContStackTop;
+
+ /** Function execution mask stack (for executing subroutine code) */
+ uint FuncStack[TGSI_EXEC_MAX_CALL_NESTING];
+ int FuncStackTop;
+
+ /** Function call stack for saving/restoring the program counter */
+ struct tgsi_call_record CallStack[TGSI_EXEC_MAX_CALL_NESTING];
+ int CallStackTop;
+
+ struct tgsi_full_instruction *Instructions;
+ uint NumInstructions;
+
+ struct tgsi_full_declaration *Declarations;
+ uint NumDeclarations;
+
+ struct tgsi_exec_labels Labels;
+};
+
+struct tgsi_exec_machine *
+tgsi_exec_machine_create( void );
+
+void
+tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach);
+
+
+void
+tgsi_exec_machine_bind_shader(
+ struct tgsi_exec_machine *mach,
+ const struct tgsi_token *tokens,
+ uint numSamplers,
+ struct tgsi_sampler **samplers);
+
+uint
+tgsi_exec_machine_run(
+ struct tgsi_exec_machine *mach );
+
+
+void
+tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach);
+
+
+boolean
+tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst);
+
+
+static INLINE void
+tgsi_set_kill_mask(struct tgsi_exec_machine *mach, unsigned mask)
+{
+ mach->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0] =
+ mask;
+}
+
+
+/** Set execution mask values prior to executing the shader */
+static INLINE void
+tgsi_set_exec_mask(struct tgsi_exec_machine *mach,
+ boolean ch0, boolean ch1, boolean ch2, boolean ch3)
+{
+ int *mask = mach->Temps[TGSI_EXEC_MASK_I].xyzw[TGSI_EXEC_MASK_C].i;
+ mask[0] = ch0 ? ~0 : 0;
+ mask[1] = ch1 ? ~0 : 0;
+ mask[2] = ch2 ? ~0 : 0;
+ mask[3] = ch3 ? ~0 : 0;
+}
+
+
+#if defined __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* TGSI_EXEC_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c
new file mode 100644
index 0000000000..17af4cb7ad
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.c
@@ -0,0 +1,181 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "tgsi_info.h"
+
+static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
+{
+ { 1, 1, 0, 0, 0, 0, "ARL", TGSI_OPCODE_ARL },
+ { 1, 1, 0, 0, 0, 0, "MOV", TGSI_OPCODE_MOV },
+ { 1, 1, 0, 0, 0, 0, "LIT", TGSI_OPCODE_LIT },
+ { 1, 1, 0, 0, 0, 0, "RCP", TGSI_OPCODE_RCP },
+ { 1, 1, 0, 0, 0, 0, "RSQ", TGSI_OPCODE_RSQ },
+ { 1, 1, 0, 0, 0, 0, "EXP", TGSI_OPCODE_EXP },
+ { 1, 1, 0, 0, 0, 0, "LOG", TGSI_OPCODE_LOG },
+ { 1, 2, 0, 0, 0, 0, "MUL", TGSI_OPCODE_MUL },
+ { 1, 2, 0, 0, 0, 0, "ADD", TGSI_OPCODE_ADD },
+ { 1, 2, 0, 0, 0, 0, "DP3", TGSI_OPCODE_DP3 },
+ { 1, 2, 0, 0, 0, 0, "DP4", TGSI_OPCODE_DP4 },
+ { 1, 2, 0, 0, 0, 0, "DST", TGSI_OPCODE_DST },
+ { 1, 2, 0, 0, 0, 0, "MIN", TGSI_OPCODE_MIN },
+ { 1, 2, 0, 0, 0, 0, "MAX", TGSI_OPCODE_MAX },
+ { 1, 2, 0, 0, 0, 0, "SLT", TGSI_OPCODE_SLT },
+ { 1, 2, 0, 0, 0, 0, "SGE", TGSI_OPCODE_SGE },
+ { 1, 3, 0, 0, 0, 0, "MAD", TGSI_OPCODE_MAD },
+ { 1, 2, 0, 0, 0, 0, "SUB", TGSI_OPCODE_SUB },
+ { 1, 3, 0, 0, 0, 0, "LRP", TGSI_OPCODE_LRP },
+ { 1, 3, 0, 0, 0, 0, "CND", TGSI_OPCODE_CND },
+ { 0, 0, 0, 0, 0, 0, "", 20 }, /* removed */
+ { 1, 3, 0, 0, 0, 0, "DP2A", TGSI_OPCODE_DP2A },
+ { 0, 0, 0, 0, 0, 0, "", 22 }, /* removed */
+ { 0, 0, 0, 0, 0, 0, "", 23 }, /* removed */
+ { 1, 1, 0, 0, 0, 0, "FRC", TGSI_OPCODE_FRC },
+ { 1, 3, 0, 0, 0, 0, "CLAMP", TGSI_OPCODE_CLAMP },
+ { 1, 1, 0, 0, 0, 0, "FLR", TGSI_OPCODE_FLR },
+ { 1, 1, 0, 0, 0, 0, "ROUND", TGSI_OPCODE_ROUND },
+ { 1, 1, 0, 0, 0, 0, "EX2", TGSI_OPCODE_EX2 },
+ { 1, 1, 0, 0, 0, 0, "LG2", TGSI_OPCODE_LG2 },
+ { 1, 2, 0, 0, 0, 0, "POW", TGSI_OPCODE_POW },
+ { 1, 2, 0, 0, 0, 0, "XPD", TGSI_OPCODE_XPD },
+ { 0, 0, 0, 0, 0, 0, "", 32 }, /* removed */
+ { 1, 1, 0, 0, 0, 0, "ABS", TGSI_OPCODE_ABS },
+ { 1, 1, 0, 0, 0, 0, "RCC", TGSI_OPCODE_RCC },
+ { 1, 2, 0, 0, 0, 0, "DPH", TGSI_OPCODE_DPH },
+ { 1, 1, 0, 0, 0, 0, "COS", TGSI_OPCODE_COS },
+ { 1, 1, 0, 0, 0, 0, "DDX", TGSI_OPCODE_DDX },
+ { 1, 1, 0, 0, 0, 0, "DDY", TGSI_OPCODE_DDY },
+ { 0, 0, 0, 0, 0, 0, "KILP", TGSI_OPCODE_KILP },
+ { 1, 1, 0, 0, 0, 0, "PK2H", TGSI_OPCODE_PK2H },
+ { 1, 1, 0, 0, 0, 0, "PK2US", TGSI_OPCODE_PK2US },
+ { 1, 1, 0, 0, 0, 0, "PK4B", TGSI_OPCODE_PK4B },
+ { 1, 1, 0, 0, 0, 0, "PK4UB", TGSI_OPCODE_PK4UB },
+ { 1, 2, 0, 0, 0, 0, "RFL", TGSI_OPCODE_RFL },
+ { 1, 2, 0, 0, 0, 0, "SEQ", TGSI_OPCODE_SEQ },
+ { 1, 2, 0, 0, 0, 0, "SFL", TGSI_OPCODE_SFL },
+ { 1, 2, 0, 0, 0, 0, "SGT", TGSI_OPCODE_SGT },
+ { 1, 1, 0, 0, 0, 0, "SIN", TGSI_OPCODE_SIN },
+ { 1, 2, 0, 0, 0, 0, "SLE", TGSI_OPCODE_SLE },
+ { 1, 2, 0, 0, 0, 0, "SNE", TGSI_OPCODE_SNE },
+ { 1, 2, 0, 0, 0, 0, "STR", TGSI_OPCODE_STR },
+ { 1, 2, 1, 0, 0, 0, "TEX", TGSI_OPCODE_TEX },
+ { 1, 4, 1, 0, 0, 0, "TXD", TGSI_OPCODE_TXD },
+ { 1, 2, 1, 0, 0, 0, "TXP", TGSI_OPCODE_TXP },
+ { 1, 1, 0, 0, 0, 0, "UP2H", TGSI_OPCODE_UP2H },
+ { 1, 1, 0, 0, 0, 0, "UP2US", TGSI_OPCODE_UP2US },
+ { 1, 1, 0, 0, 0, 0, "UP4B", TGSI_OPCODE_UP4B },
+ { 1, 1, 0, 0, 0, 0, "UP4UB", TGSI_OPCODE_UP4UB },
+ { 1, 3, 0, 0, 0, 0, "X2D", TGSI_OPCODE_X2D },
+ { 1, 1, 0, 0, 0, 0, "ARA", TGSI_OPCODE_ARA },
+ { 1, 1, 0, 0, 0, 0, "ARR", TGSI_OPCODE_ARR },
+ { 0, 1, 0, 0, 0, 0, "BRA", TGSI_OPCODE_BRA },
+ { 0, 0, 0, 1, 0, 0, "CAL", TGSI_OPCODE_CAL },
+ { 0, 0, 0, 0, 0, 0, "RET", TGSI_OPCODE_RET },
+ { 1, 1, 0, 0, 0, 0, "SSG", TGSI_OPCODE_SSG },
+ { 1, 3, 0, 0, 0, 0, "CMP", TGSI_OPCODE_CMP },
+ { 1, 1, 0, 0, 0, 0, "SCS", TGSI_OPCODE_SCS },
+ { 1, 2, 1, 0, 0, 0, "TXB", TGSI_OPCODE_TXB },
+ { 1, 1, 0, 0, 0, 0, "NRM", TGSI_OPCODE_NRM },
+ { 1, 2, 0, 0, 0, 0, "DIV", TGSI_OPCODE_DIV },
+ { 1, 2, 0, 0, 0, 0, "DP2", TGSI_OPCODE_DP2 },
+ { 1, 2, 1, 0, 0, 0, "TXL", TGSI_OPCODE_TXL },
+ { 0, 0, 0, 0, 0, 0, "BRK", TGSI_OPCODE_BRK },
+ { 0, 1, 0, 1, 0, 1, "IF", TGSI_OPCODE_IF },
+ { 1, 1, 0, 0, 0, 1, "BGNFOR", TGSI_OPCODE_BGNFOR },
+ { 0, 1, 0, 0, 0, 1, "REP", TGSI_OPCODE_REP },
+ { 0, 0, 0, 1, 1, 1, "ELSE", TGSI_OPCODE_ELSE },
+ { 0, 0, 0, 0, 1, 0, "ENDIF", TGSI_OPCODE_ENDIF },
+ { 1, 0, 0, 0, 1, 0, "ENDFOR", TGSI_OPCODE_ENDFOR },
+ { 0, 0, 0, 0, 1, 0, "ENDREP", TGSI_OPCODE_ENDREP },
+ { 0, 1, 0, 0, 0, 0, "PUSHA", TGSI_OPCODE_PUSHA },
+ { 1, 0, 0, 0, 0, 0, "POPA", TGSI_OPCODE_POPA },
+ { 1, 1, 0, 0, 0, 0, "CEIL", TGSI_OPCODE_CEIL },
+ { 1, 1, 0, 0, 0, 0, "I2F", TGSI_OPCODE_I2F },
+ { 1, 1, 0, 0, 0, 0, "NOT", TGSI_OPCODE_NOT },
+ { 1, 1, 0, 0, 0, 0, "TRUNC", TGSI_OPCODE_TRUNC },
+ { 1, 2, 0, 0, 0, 0, "SHL", TGSI_OPCODE_SHL },
+ { 1, 2, 0, 0, 0, 0, "SHR", TGSI_OPCODE_SHR },
+ { 1, 2, 0, 0, 0, 0, "AND", TGSI_OPCODE_AND },
+ { 1, 2, 0, 0, 0, 0, "OR", TGSI_OPCODE_OR },
+ { 1, 2, 0, 0, 0, 0, "MOD", TGSI_OPCODE_MOD },
+ { 1, 2, 0, 0, 0, 0, "XOR", TGSI_OPCODE_XOR },
+ { 1, 3, 0, 0, 0, 0, "SAD", TGSI_OPCODE_SAD },
+ { 1, 2, 1, 0, 0, 0, "TXF", TGSI_OPCODE_TXF },
+ { 1, 2, 1, 0, 0, 0, "TXQ", TGSI_OPCODE_TXQ },
+ { 0, 0, 0, 0, 0, 0, "CONT", TGSI_OPCODE_CONT },
+ { 0, 0, 0, 0, 0, 0, "EMIT", TGSI_OPCODE_EMIT },
+ { 0, 0, 0, 0, 0, 0, "ENDPRIM", TGSI_OPCODE_ENDPRIM },
+ { 0, 0, 0, 1, 0, 1, "BGNLOOP", TGSI_OPCODE_BGNLOOP },
+ { 0, 0, 0, 0, 0, 1, "BGNSUB", TGSI_OPCODE_BGNSUB },
+ { 0, 0, 0, 1, 1, 0, "ENDLOOP", TGSI_OPCODE_ENDLOOP },
+ { 0, 0, 0, 0, 1, 0, "ENDSUB", TGSI_OPCODE_ENDSUB },
+ { 1, 1, 0, 0, 0, 0, "NOISE1", TGSI_OPCODE_NOISE1 },
+ { 1, 1, 0, 0, 0, 0, "NOISE2", TGSI_OPCODE_NOISE2 },
+ { 1, 1, 0, 0, 0, 0, "NOISE3", TGSI_OPCODE_NOISE3 },
+ { 1, 1, 0, 0, 0, 0, "NOISE4", TGSI_OPCODE_NOISE4 },
+ { 0, 0, 0, 0, 0, 0, "NOP", TGSI_OPCODE_NOP },
+ { 0, 0, 0, 0, 0, 0, "", 108 }, /* removed */
+ { 0, 0, 0, 0, 0, 0, "", 109 }, /* removed */
+ { 0, 0, 0, 0, 0, 0, "", 110 }, /* removed */
+ { 0, 0, 0, 0, 0, 0, "", 111 }, /* removed */
+ { 1, 1, 0, 0, 0, 0, "NRM4", TGSI_OPCODE_NRM4 },
+ { 0, 1, 0, 0, 0, 0, "CALLNZ", TGSI_OPCODE_CALLNZ },
+ { 0, 1, 0, 0, 0, 0, "IFC", TGSI_OPCODE_IFC },
+ { 0, 1, 0, 0, 0, 0, "BREAKC", TGSI_OPCODE_BREAKC },
+ { 0, 1, 0, 0, 0, 0, "KIL", TGSI_OPCODE_KIL },
+ { 0, 0, 0, 0, 0, 0, "END", TGSI_OPCODE_END },
+ { 1, 1, 0, 0, 0, 0, "SWZ", TGSI_OPCODE_SWZ }
+};
+
+const struct tgsi_opcode_info *
+tgsi_get_opcode_info( uint opcode )
+{
+ static boolean firsttime = 1;
+
+ if (firsttime) {
+ unsigned i;
+ firsttime = 0;
+ for (i = 0; i < Elements(opcode_info); i++)
+ assert(opcode_info[i].opcode == i);
+ }
+
+ if (opcode < TGSI_OPCODE_LAST)
+ return &opcode_info[opcode];
+
+ assert( 0 );
+ return NULL;
+}
+
+
+const char *
+tgsi_get_opcode_name( uint opcode )
+{
+ const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode);
+ return info->mnemonic;
+}
+
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.h b/src/gallium/auxiliary/tgsi/tgsi_info.h
new file mode 100644
index 0000000000..74713c3b98
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_INFO_H
+#define TGSI_INFO_H
+
+#include "pipe/p_shader_tokens.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct tgsi_opcode_info
+{
+ unsigned num_dst:3;
+ unsigned num_src:3;
+ unsigned is_tex:1;
+ unsigned is_branch:1;
+ int pre_dedent:2;
+ int post_indent:2;
+ const char *mnemonic;
+ uint opcode;
+};
+
+const struct tgsi_opcode_info *
+tgsi_get_opcode_info( uint opcode );
+
+const char *
+tgsi_get_opcode_name( uint opcode );
+
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_INFO_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_iterate.c b/src/gallium/auxiliary/tgsi/tgsi_iterate.c
new file mode 100644
index 0000000000..d88c2558d8
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_iterate.c
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "tgsi_iterate.h"
+
+boolean
+tgsi_iterate_shader(
+ const struct tgsi_token *tokens,
+ struct tgsi_iterate_context *ctx )
+{
+ struct tgsi_parse_context parse;
+
+ if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK)
+ return FALSE;
+
+ ctx->processor = parse.FullHeader.Processor;
+ ctx->version = parse.FullVersion.Version;
+
+ if (ctx->prolog)
+ if (!ctx->prolog( ctx ))
+ goto fail;
+
+ while (!tgsi_parse_end_of_tokens( &parse )) {
+ tgsi_parse_token( &parse );
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (ctx->iterate_instruction)
+ if (!ctx->iterate_instruction( ctx, &parse.FullToken.FullInstruction ))
+ goto fail;
+ break;
+
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ if (ctx->iterate_declaration)
+ if (!ctx->iterate_declaration( ctx, &parse.FullToken.FullDeclaration ))
+ goto fail;
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ if (ctx->iterate_immediate)
+ if (!ctx->iterate_immediate( ctx, &parse.FullToken.FullImmediate ))
+ goto fail;
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+
+ if (ctx->epilog)
+ if (!ctx->epilog( ctx ))
+ goto fail;
+
+ tgsi_parse_free( &parse );
+ return TRUE;
+
+fail:
+ tgsi_parse_free( &parse );
+ return FALSE;
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_iterate.h b/src/gallium/auxiliary/tgsi/tgsi_iterate.h
new file mode 100644
index 0000000000..ec7b85bf63
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_iterate.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_ITERATE_H
+#define TGSI_ITERATE_H
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct tgsi_iterate_context
+{
+ boolean
+ (* prolog)(
+ struct tgsi_iterate_context *ctx );
+
+ boolean
+ (* iterate_instruction)(
+ struct tgsi_iterate_context *ctx,
+ struct tgsi_full_instruction *inst );
+
+ boolean
+ (* iterate_declaration)(
+ struct tgsi_iterate_context *ctx,
+ struct tgsi_full_declaration *decl );
+
+ boolean
+ (* iterate_immediate)(
+ struct tgsi_iterate_context *ctx,
+ struct tgsi_full_immediate *imm );
+
+ boolean
+ (* epilog)(
+ struct tgsi_iterate_context *ctx );
+
+ struct tgsi_processor processor;
+ struct tgsi_version version;
+};
+
+boolean
+tgsi_iterate_shader(
+ const struct tgsi_token *tokens,
+ struct tgsi_iterate_context *ctx );
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_ITERATE_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
new file mode 100644
index 0000000000..e7bcf4bf75
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
@@ -0,0 +1,172 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+#ifndef OP12_TEX
+#define OP12_TEX(a) OP12(a)
+#endif
+
+#ifndef OP14_TEX
+#define OP14_TEX(a) OP14(a)
+#endif
+
+#ifndef OP00_LBL
+#define OP00_LBL(a) OP00(a)
+#endif
+
+#ifndef OP01_LBL
+#define OP01_LBL(a) OP01(a)
+#endif
+
+OP11(ARL)
+OP11(MOV)
+OP11(LIT)
+OP11(RCP)
+OP11(RSQ)
+OP11(EXP)
+OP11(LOG)
+OP12(MUL)
+OP12(ADD)
+OP12(DP3)
+OP12(DP4)
+OP12(DST)
+OP12(MIN)
+OP12(MAX)
+OP12(SLT)
+OP12(SGE)
+OP13(MAD)
+OP12(SUB)
+OP13(LRP)
+OP13(CND)
+OP13(DP2A)
+OP11(FRC)
+OP13(CLAMP)
+OP11(FLR)
+OP11(ROUND)
+OP11(EX2)
+OP11(LG2)
+OP12(POW)
+OP12(XPD)
+OP11(ABS)
+OP11(RCC)
+OP12(DPH)
+OP11(COS)
+OP11(DDX)
+OP11(DDY)
+OP00(KILP)
+OP11(PK2H)
+OP11(PK2US)
+OP11(PK4B)
+OP11(PK4UB)
+OP12(RFL)
+OP12(SEQ)
+OP12(SFL)
+OP12(SGT)
+OP11(SIN)
+OP12(SLE)
+OP12(SNE)
+OP12(STR)
+OP12_TEX(TEX)
+OP14_TEX(TXD)
+OP12_TEX(TXP)
+OP11(UP2H)
+OP11(UP2US)
+OP11(UP4B)
+OP11(UP4UB)
+OP13(X2D)
+OP11(ARA)
+OP11(ARR)
+OP01(BRA)
+OP00_LBL(CAL)
+OP00(RET)
+OP11(SSG)
+OP13(CMP)
+OP11(SCS)
+OP12_TEX(TXB)
+OP11(NRM)
+OP12(DIV)
+OP12(DP2)
+OP12_TEX(TXL)
+OP00(BRK)
+OP01_LBL(IF)
+OP11(BGNFOR)
+OP01(REP)
+OP00_LBL(ELSE)
+OP00(ENDIF)
+OP10(ENDFOR)
+OP00(ENDREP)
+OP01(PUSHA)
+OP10(POPA)
+OP11(CEIL)
+OP11(I2F)
+OP11(NOT)
+OP11(TRUNC)
+OP12(SHL)
+OP12(SHR)
+OP12(AND)
+OP12(OR)
+OP12(MOD)
+OP12(XOR)
+OP13(SAD)
+OP12_TEX(TXF)
+OP12_TEX(TXQ)
+OP00(CONT)
+OP00(EMIT)
+OP00(ENDPRIM)
+OP00_LBL(BGNLOOP)
+OP00(BGNSUB)
+OP00_LBL(ENDLOOP)
+OP00(ENDSUB)
+OP11(NOISE1)
+OP11(NOISE2)
+OP11(NOISE3)
+OP11(NOISE4)
+OP00(NOP)
+OP11(NRM4)
+OP01(CALLNZ)
+OP01(IFC)
+OP01(BREAKC)
+OP01(KIL)
+OP00(END)
+OP11(SWZ)
+
+
+#undef OP00
+#undef OP01
+#undef OP10
+#undef OP11
+#undef OP12
+#undef OP13
+
+#ifdef OP14
+#undef OP14
+#endif
+
+#undef OP00_LBL
+#undef OP01_LBL
+
+#undef OP12_TEX
+#undef OP14_TEX
+
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c
new file mode 100644
index 0000000000..4870f82b6b
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c
@@ -0,0 +1,352 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi_parse.h"
+#include "tgsi_build.h"
+#include "util/u_memory.h"
+
+void
+tgsi_full_token_init(
+ union tgsi_full_token *full_token )
+{
+ full_token->Token.Type = TGSI_TOKEN_TYPE_DECLARATION;
+}
+
+void
+tgsi_full_token_free(
+ union tgsi_full_token *full_token )
+{
+}
+
+unsigned
+tgsi_parse_init(
+ struct tgsi_parse_context *ctx,
+ const struct tgsi_token *tokens )
+{
+ ctx->FullVersion.Version = *(struct tgsi_version *) &tokens[0];
+ if( ctx->FullVersion.Version.MajorVersion > 1 ) {
+ return TGSI_PARSE_ERROR;
+ }
+
+ ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[1];
+ if( ctx->FullHeader.Header.HeaderSize >= 2 ) {
+ ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[2];
+ }
+ else {
+ ctx->FullHeader.Processor = tgsi_default_processor();
+ }
+
+ ctx->Tokens = tokens;
+ ctx->Position = 1 + ctx->FullHeader.Header.HeaderSize;
+
+ tgsi_full_token_init( &ctx->FullToken );
+
+ return TGSI_PARSE_OK;
+}
+
+void
+tgsi_parse_free(
+ struct tgsi_parse_context *ctx )
+{
+ tgsi_full_token_free( &ctx->FullToken );
+}
+
+boolean
+tgsi_parse_end_of_tokens(
+ struct tgsi_parse_context *ctx )
+{
+ return ctx->Position >=
+ 1 + ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize;
+}
+
+
+/**
+ * This function is used to avoid and work-around type punning/aliasing
+ * warnings. The warnings seem harmless on x86 but on PPC they cause
+ * real failures.
+ */
+static INLINE void
+copy_token(void *dst, const void *src)
+{
+ memcpy(dst, src, 4);
+}
+
+
+/**
+ * Get next 4-byte token, return it at address specified by 'token'
+ */
+static void
+next_token(
+ struct tgsi_parse_context *ctx,
+ void *token )
+{
+ assert( !tgsi_parse_end_of_tokens( ctx ) );
+ copy_token(token, &ctx->Tokens[ctx->Position]);
+ ctx->Position++;
+}
+
+
+void
+tgsi_parse_token(
+ struct tgsi_parse_context *ctx )
+{
+ struct tgsi_token token;
+ unsigned i;
+
+ tgsi_full_token_free( &ctx->FullToken );
+ tgsi_full_token_init( &ctx->FullToken );
+
+ next_token( ctx, &token );
+
+ switch( token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration;
+
+ *decl = tgsi_default_full_declaration();
+ copy_token(&decl->Declaration, &token);
+
+ next_token( ctx, &decl->DeclarationRange );
+
+ if( decl->Declaration.Semantic ) {
+ next_token( ctx, &decl->Semantic );
+ }
+
+ break;
+ }
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate;
+
+ *imm = tgsi_default_full_immediate();
+ copy_token(&imm->Immediate, &token);
+ assert( !imm->Immediate.Extended );
+
+ switch (imm->Immediate.DataType) {
+ case TGSI_IMM_FLOAT32:
+ {
+ uint imm_count = imm->Immediate.NrTokens - 1;
+ for (i = 0; i < imm_count; i++) {
+ next_token(ctx, &imm->u[i]);
+ }
+ }
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ break;
+ }
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction;
+ unsigned extended;
+
+ *inst = tgsi_default_full_instruction();
+ copy_token(&inst->Instruction, &token);
+ extended = inst->Instruction.Extended;
+
+ while( extended ) {
+ struct tgsi_src_register_ext token;
+
+ next_token( ctx, &token );
+
+ switch( token.Type ) {
+ case TGSI_INSTRUCTION_EXT_TYPE_NV:
+ copy_token(&inst->InstructionExtNv, &token);
+ break;
+
+ case TGSI_INSTRUCTION_EXT_TYPE_LABEL:
+ copy_token(&inst->InstructionExtLabel, &token);
+ break;
+
+ case TGSI_INSTRUCTION_EXT_TYPE_TEXTURE:
+ copy_token(&inst->InstructionExtTexture, &token);
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ extended = token.Extended;
+ }
+
+ assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS );
+
+ for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
+ unsigned extended;
+
+ next_token( ctx, &inst->FullDstRegisters[i].DstRegister );
+
+ /*
+ * No support for indirect or multi-dimensional addressing.
+ */
+ assert( !inst->FullDstRegisters[i].DstRegister.Dimension );
+
+ extended = inst->FullDstRegisters[i].DstRegister.Extended;
+
+ while( extended ) {
+ struct tgsi_src_register_ext token;
+
+ next_token( ctx, &token );
+
+ switch( token.Type ) {
+ case TGSI_DST_REGISTER_EXT_TYPE_CONDCODE:
+ copy_token(&inst->FullDstRegisters[i].DstRegisterExtConcode,
+ &token);
+ break;
+
+ case TGSI_DST_REGISTER_EXT_TYPE_MODULATE:
+ copy_token(&inst->FullDstRegisters[i].DstRegisterExtModulate,
+ &token);
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ extended = token.Extended;
+ }
+
+ if( inst->FullDstRegisters[i].DstRegister.Indirect ) {
+ next_token( ctx, &inst->FullDstRegisters[i].DstRegisterInd );
+
+ /*
+ * No support for indirect or multi-dimensional addressing.
+ */
+ assert( !inst->FullDstRegisters[i].DstRegisterInd.Indirect );
+ assert( !inst->FullDstRegisters[i].DstRegisterInd.Dimension );
+ assert( !inst->FullDstRegisters[i].DstRegisterInd.Extended );
+ }
+ }
+
+ assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );
+
+ for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
+ unsigned extended;
+
+ next_token( ctx, &inst->FullSrcRegisters[i].SrcRegister );
+
+ extended = inst->FullSrcRegisters[i].SrcRegister.Extended;
+
+ while( extended ) {
+ struct tgsi_src_register_ext token;
+
+ next_token( ctx, &token );
+
+ switch( token.Type ) {
+ case TGSI_SRC_REGISTER_EXT_TYPE_SWZ:
+ copy_token(&inst->FullSrcRegisters[i].SrcRegisterExtSwz,
+ &token);
+ break;
+
+ case TGSI_SRC_REGISTER_EXT_TYPE_MOD:
+ copy_token(&inst->FullSrcRegisters[i].SrcRegisterExtMod,
+ &token);
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ extended = token.Extended;
+ }
+
+ if( inst->FullSrcRegisters[i].SrcRegister.Indirect ) {
+ next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterInd );
+
+ /*
+ * No support for indirect or multi-dimensional addressing.
+ */
+ assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect );
+ assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension );
+ assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Extended );
+ }
+
+ if( inst->FullSrcRegisters[i].SrcRegister.Dimension ) {
+ next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDim );
+
+ /*
+ * No support for multi-dimensional addressing.
+ */
+ assert( !inst->FullSrcRegisters[i].SrcRegisterDim.Dimension );
+ assert( !inst->FullSrcRegisters[i].SrcRegisterDim.Extended );
+
+ if( inst->FullSrcRegisters[i].SrcRegisterDim.Indirect ) {
+ next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDimInd );
+
+ /*
+ * No support for indirect or multi-dimensional addressing.
+ */
+ assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect );
+ assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension );
+ assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Extended );
+ }
+ }
+ }
+
+ break;
+ }
+
+ default:
+ assert( 0 );
+ }
+}
+
+
+unsigned
+tgsi_num_tokens(const struct tgsi_token *tokens)
+{
+ struct tgsi_parse_context ctx;
+ if (tgsi_parse_init(&ctx, tokens) == TGSI_PARSE_OK) {
+ unsigned len = (ctx.FullHeader.Header.HeaderSize +
+ ctx.FullHeader.Header.BodySize +
+ 1);
+ return len;
+ }
+ return 0;
+}
+
+
+/**
+ * Make a new copy of a token array.
+ */
+struct tgsi_token *
+tgsi_dup_tokens(const struct tgsi_token *tokens)
+{
+ unsigned n = tgsi_num_tokens(tokens);
+ unsigned bytes = n * sizeof(struct tgsi_token);
+ struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes);
+ if (new_tokens)
+ memcpy(new_tokens, tokens, bytes);
+ return new_tokens;
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h
new file mode 100644
index 0000000000..a26ee5ba86
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h
@@ -0,0 +1,149 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_PARSE_H
+#define TGSI_PARSE_H
+
+#include "pipe/p_shader_tokens.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct tgsi_full_version
+{
+ struct tgsi_version Version;
+};
+
+struct tgsi_full_header
+{
+ struct tgsi_header Header;
+ struct tgsi_processor Processor;
+};
+
+struct tgsi_full_dst_register
+{
+ struct tgsi_dst_register DstRegister;
+ struct tgsi_src_register DstRegisterInd;
+ struct tgsi_dst_register_ext_concode DstRegisterExtConcode;
+ struct tgsi_dst_register_ext_modulate DstRegisterExtModulate;
+};
+
+struct tgsi_full_src_register
+{
+ struct tgsi_src_register SrcRegister;
+ struct tgsi_src_register_ext_swz SrcRegisterExtSwz;
+ struct tgsi_src_register_ext_mod SrcRegisterExtMod;
+ struct tgsi_src_register SrcRegisterInd;
+ struct tgsi_dimension SrcRegisterDim;
+ struct tgsi_src_register SrcRegisterDimInd;
+};
+
+struct tgsi_full_declaration
+{
+ struct tgsi_declaration Declaration;
+ struct tgsi_declaration_range DeclarationRange;
+ struct tgsi_declaration_semantic Semantic;
+};
+
+struct tgsi_full_immediate
+{
+ struct tgsi_immediate Immediate;
+ union tgsi_immediate_data u[4];
+};
+
+#define TGSI_FULL_MAX_DST_REGISTERS 2
+#define TGSI_FULL_MAX_SRC_REGISTERS 4 /* TXD has 4 */
+
+struct tgsi_full_instruction
+{
+ struct tgsi_instruction Instruction;
+ struct tgsi_instruction_ext_nv InstructionExtNv;
+ struct tgsi_instruction_ext_label InstructionExtLabel;
+ struct tgsi_instruction_ext_texture InstructionExtTexture;
+ struct tgsi_full_dst_register FullDstRegisters[TGSI_FULL_MAX_DST_REGISTERS];
+ struct tgsi_full_src_register FullSrcRegisters[TGSI_FULL_MAX_SRC_REGISTERS];
+ uint Flags; /**< user-defined usage */
+};
+
+union tgsi_full_token
+{
+ struct tgsi_token Token;
+ struct tgsi_full_declaration FullDeclaration;
+ struct tgsi_full_immediate FullImmediate;
+ struct tgsi_full_instruction FullInstruction;
+};
+
+void
+tgsi_full_token_init(
+ union tgsi_full_token *full_token );
+
+void
+tgsi_full_token_free(
+ union tgsi_full_token *full_token );
+
+struct tgsi_parse_context
+{
+ const struct tgsi_token *Tokens;
+ unsigned Position;
+ struct tgsi_full_version FullVersion;
+ struct tgsi_full_header FullHeader;
+ union tgsi_full_token FullToken;
+};
+
+#define TGSI_PARSE_OK 0
+#define TGSI_PARSE_ERROR 1
+
+unsigned
+tgsi_parse_init(
+ struct tgsi_parse_context *ctx,
+ const struct tgsi_token *tokens );
+
+void
+tgsi_parse_free(
+ struct tgsi_parse_context *ctx );
+
+boolean
+tgsi_parse_end_of_tokens(
+ struct tgsi_parse_context *ctx );
+
+void
+tgsi_parse_token(
+ struct tgsi_parse_context *ctx );
+
+unsigned
+tgsi_num_tokens(const struct tgsi_token *tokens);
+
+struct tgsi_token *
+tgsi_dup_tokens(const struct tgsi_token *tokens);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_PARSE_H */
+
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ppc.c b/src/gallium/auxiliary/tgsi/tgsi_ppc.c
new file mode 100644
index 0000000000..4b1c7d4e01
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_ppc.c
@@ -0,0 +1,1375 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * TGSI to PowerPC code generation.
+ */
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_ARCH_PPC)
+
+#include "util/u_debug.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_sse.h"
+#include "tgsi/tgsi_info.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi_dump.h"
+#include "tgsi_exec.h"
+#include "tgsi_ppc.h"
+#include "rtasm/rtasm_ppc.h"
+
+
+/**
+ * Since it's pretty much impossible to form PPC vector immediates, load
+ * them from memory here:
+ */
+const float ppc_builtin_constants[] ALIGN16_ATTRIB = {
+ 1.0f, -128.0f, 128.0, 0.0
+};
+
+
+#define FOR_EACH_CHANNEL( CHAN )\
+ for (CHAN = 0; CHAN < NUM_CHANNELS; CHAN++)
+
+#define IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
+ ((INST).FullDstRegisters[0].DstRegister.WriteMask & (1 << (CHAN)))
+
+#define IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
+ if (IS_DST0_CHANNEL_ENABLED( INST, CHAN ))
+
+#define FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\
+ FOR_EACH_CHANNEL( CHAN )\
+ IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )
+
+#define CHAN_X 0
+#define CHAN_Y 1
+#define CHAN_Z 2
+#define CHAN_W 3
+
+
+/**
+ * How many TGSI temps should be implemented with real PPC vector registers
+ * rather than memory.
+ */
+#define MAX_PPC_TEMPS 3
+
+
+/**
+ * Context/state used during code gen.
+ */
+struct gen_context
+{
+ struct ppc_function *f;
+ int inputs_reg; /**< GP register pointing to input params */
+ int outputs_reg; /**< GP register pointing to output params */
+ int temps_reg; /**< GP register pointing to temporary "registers" */
+ int immed_reg; /**< GP register pointing to immediates buffer */
+ int const_reg; /**< GP register pointing to constants buffer */
+ int builtins_reg; /**< GP register pointint to built-in constants */
+
+ int offset_reg; /**< used to reduce redundant li instructions */
+ int offset_value;
+
+ int one_vec; /**< vector register with {1.0, 1.0, 1.0, 1.0} */
+ int bit31_vec; /**< vector register with {1<<31, 1<<31, 1<<31, 1<<31} */
+
+ /**
+ * Map TGSI temps to PPC vector temps.
+ * We have 32 PPC vector regs. Use 16 of them for storing 4 TGSI temps.
+ * XXX currently only do this for TGSI temps [0..MAX_PPC_TEMPS-1].
+ */
+ int temps_map[MAX_PPC_TEMPS][4];
+
+ /**
+ * Cache of src registers.
+ * This is used to avoid redundant load instructions.
+ */
+ struct {
+ struct tgsi_full_src_register src;
+ uint chan;
+ uint vec;
+ } regs[12]; /* 3 src regs, 4 channels */
+ uint num_regs;
+};
+
+
+/**
+ * Initialize code generation context.
+ */
+static void
+init_gen_context(struct gen_context *gen, struct ppc_function *func)
+{
+ uint i;
+
+ memset(gen, 0, sizeof(*gen));
+ gen->f = func;
+ gen->inputs_reg = ppc_reserve_register(func, 3); /* first function param */
+ gen->outputs_reg = ppc_reserve_register(func, 4); /* second function param */
+ gen->temps_reg = ppc_reserve_register(func, 5); /* ... */
+ gen->immed_reg = ppc_reserve_register(func, 6);
+ gen->const_reg = ppc_reserve_register(func, 7);
+ gen->builtins_reg = ppc_reserve_register(func, 8);
+ gen->one_vec = -1;
+ gen->bit31_vec = -1;
+ gen->offset_reg = -1;
+ gen->offset_value = -9999999;
+ for (i = 0; i < MAX_PPC_TEMPS; i++) {
+ gen->temps_map[i][0] = ppc_allocate_vec_register(gen->f);
+ gen->temps_map[i][1] = ppc_allocate_vec_register(gen->f);
+ gen->temps_map[i][2] = ppc_allocate_vec_register(gen->f);
+ gen->temps_map[i][3] = ppc_allocate_vec_register(gen->f);
+ }
+}
+
+
+/**
+ * Is the given TGSI register stored as a real PPC vector register?
+ */
+static boolean
+is_ppc_vec_temporary(const struct tgsi_full_src_register *reg)
+{
+ return (reg->SrcRegister.File == TGSI_FILE_TEMPORARY &&
+ reg->SrcRegister.Index < MAX_PPC_TEMPS);
+}
+
+
+/**
+ * Is the given TGSI register stored as a real PPC vector register?
+ */
+static boolean
+is_ppc_vec_temporary_dst(const struct tgsi_full_dst_register *reg)
+{
+ return (reg->DstRegister.File == TGSI_FILE_TEMPORARY &&
+ reg->DstRegister.Index < MAX_PPC_TEMPS);
+}
+
+
+
+/**
+ * All PPC vector load/store instructions form an effective address
+ * by adding the contents of two registers. For example:
+ * lvx v2,r8,r9 # v2 = memory[r8 + r9]
+ * stvx v2,r8,r9 # memory[r8 + r9] = v2;
+ * So our lvx/stvx instructions are typically preceded by an 'li' instruction
+ * to load r9 (above) with an immediate (an offset).
+ * This code emits that 'li' instruction, but only if the offset value is
+ * different than the previous 'li'.
+ * This optimization seems to save about 10% in the instruction count.
+ * Note that we need to unconditionally emit an 'li' inside basic blocks
+ * (such as inside loops).
+ */
+static int
+emit_li_offset(struct gen_context *gen, int offset)
+{
+ if (gen->offset_reg <= 0) {
+ /* allocate a GP register for storing load/store offset */
+ gen->offset_reg = ppc_allocate_register(gen->f);
+ }
+
+ /* emit new 'li' if offset is changing */
+ if (gen->offset_value < 0 || gen->offset_value != offset) {
+ gen->offset_value = offset;
+ ppc_li(gen->f, gen->offset_reg, offset);
+ }
+
+ return gen->offset_reg;
+}
+
+
+/**
+ * Forces subsequent emit_li_offset() calls to emit an 'li'.
+ * To be called at the top of basic blocks.
+ */
+static void
+reset_li_offset(struct gen_context *gen)
+{
+ gen->offset_value = -9999999;
+}
+
+
+
+/**
+ * Load the given vector register with {value, value, value, value}.
+ * The value must be in the ppu_builtin_constants[] array.
+ * We wouldn't need this if there was a simple way to load PPC vector
+ * registers with immediate values!
+ */
+static void
+load_constant_vec(struct gen_context *gen, int dst_vec, float value)
+{
+ uint pos;
+ for (pos = 0; pos < Elements(ppc_builtin_constants); pos++) {
+ if (ppc_builtin_constants[pos] == value) {
+ int offset = pos * 4;
+ int offset_reg = emit_li_offset(gen, offset);
+
+ /* Load 4-byte word into vector register.
+ * The vector slot depends on the effective address we load from.
+ * We know that our builtins start at a 16-byte boundary so we
+ * know that 'swizzle' tells us which vector slot will have the
+ * loaded word. The other vector slots will be undefined.
+ */
+ ppc_lvewx(gen->f, dst_vec, gen->builtins_reg, offset_reg);
+ /* splat word[pos % 4] across the vector reg */
+ ppc_vspltw(gen->f, dst_vec, dst_vec, pos % 4);
+ return;
+ }
+ }
+ assert(0 && "Need to add new constant to ppc_builtin_constants array");
+}
+
+
+/**
+ * Return index of vector register containing {1.0, 1.0, 1.0, 1.0}.
+ */
+static int
+gen_one_vec(struct gen_context *gen)
+{
+ if (gen->one_vec < 0) {
+ gen->one_vec = ppc_allocate_vec_register(gen->f);
+ load_constant_vec(gen, gen->one_vec, 1.0f);
+ }
+ return gen->one_vec;
+}
+
+/**
+ * Return index of vector register containing {1<<31, 1<<31, 1<<31, 1<<31}.
+ */
+static int
+gen_get_bit31_vec(struct gen_context *gen)
+{
+ if (gen->bit31_vec < 0) {
+ gen->bit31_vec = ppc_allocate_vec_register(gen->f);
+ ppc_vspltisw(gen->f, gen->bit31_vec, -1);
+ ppc_vslw(gen->f, gen->bit31_vec, gen->bit31_vec, gen->bit31_vec);
+ }
+ return gen->bit31_vec;
+}
+
+
+/**
+ * Register fetch. Return PPC vector register with result.
+ */
+static int
+emit_fetch(struct gen_context *gen,
+ const struct tgsi_full_src_register *reg,
+ const unsigned chan_index)
+{
+ uint swizzle = tgsi_util_get_full_src_register_extswizzle(reg, chan_index);
+ int dst_vec = -1;
+
+ switch (swizzle) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ switch (reg->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ {
+ int offset = (reg->SrcRegister.Index * 4 + swizzle) * 16;
+ int offset_reg = emit_li_offset(gen, offset);
+ dst_vec = ppc_allocate_vec_register(gen->f);
+ ppc_lvx(gen->f, dst_vec, gen->inputs_reg, offset_reg);
+ }
+ break;
+ case TGSI_FILE_TEMPORARY:
+ if (is_ppc_vec_temporary(reg)) {
+ /* use PPC vec register */
+ dst_vec = gen->temps_map[reg->SrcRegister.Index][swizzle];
+ }
+ else {
+ /* use memory-based temp register "file" */
+ int offset = (reg->SrcRegister.Index * 4 + swizzle) * 16;
+ int offset_reg = emit_li_offset(gen, offset);
+ dst_vec = ppc_allocate_vec_register(gen->f);
+ ppc_lvx(gen->f, dst_vec, gen->temps_reg, offset_reg);
+ }
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ {
+ int offset = (reg->SrcRegister.Index * 4 + swizzle) * 4;
+ int offset_reg = emit_li_offset(gen, offset);
+ dst_vec = ppc_allocate_vec_register(gen->f);
+ /* Load 4-byte word into vector register.
+ * The vector slot depends on the effective address we load from.
+ * We know that our immediates start at a 16-byte boundary so we
+ * know that 'swizzle' tells us which vector slot will have the
+ * loaded word. The other vector slots will be undefined.
+ */
+ ppc_lvewx(gen->f, dst_vec, gen->immed_reg, offset_reg);
+ /* splat word[swizzle] across the vector reg */
+ ppc_vspltw(gen->f, dst_vec, dst_vec, swizzle);
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ {
+ int offset = (reg->SrcRegister.Index * 4 + swizzle) * 4;
+ int offset_reg = emit_li_offset(gen, offset);
+ dst_vec = ppc_allocate_vec_register(gen->f);
+ /* Load 4-byte word into vector register.
+ * The vector slot depends on the effective address we load from.
+ * We know that our constants start at a 16-byte boundary so we
+ * know that 'swizzle' tells us which vector slot will have the
+ * loaded word. The other vector slots will be undefined.
+ */
+ ppc_lvewx(gen->f, dst_vec, gen->const_reg, offset_reg);
+ /* splat word[swizzle] across the vector reg */
+ ppc_vspltw(gen->f, dst_vec, dst_vec, swizzle);
+ }
+ break;
+ default:
+ assert( 0 );
+ }
+ break;
+ case TGSI_EXTSWIZZLE_ZERO:
+ ppc_vzero(gen->f, dst_vec);
+ break;
+ case TGSI_EXTSWIZZLE_ONE:
+ {
+ int one_vec = gen_one_vec(gen);
+ dst_vec = ppc_allocate_vec_register(gen->f);
+ ppc_vmove(gen->f, dst_vec, one_vec);
+ }
+ break;
+ default:
+ assert( 0 );
+ }
+
+ assert(dst_vec >= 0);
+
+ {
+ uint sign_op = tgsi_util_get_full_src_register_sign_mode(reg, chan_index);
+ if (sign_op != TGSI_UTIL_SIGN_KEEP) {
+ int bit31_vec = gen_get_bit31_vec(gen);
+ int dst_vec2;
+
+ if (is_ppc_vec_temporary(reg)) {
+ /* need to use a new temp */
+ dst_vec2 = ppc_allocate_vec_register(gen->f);
+ }
+ else {
+ dst_vec2 = dst_vec;
+ }
+
+ switch (sign_op) {
+ case TGSI_UTIL_SIGN_CLEAR:
+ /* vec = vec & ~bit31 */
+ ppc_vandc(gen->f, dst_vec2, dst_vec, bit31_vec);
+ break;
+ case TGSI_UTIL_SIGN_SET:
+ /* vec = vec | bit31 */
+ ppc_vor(gen->f, dst_vec2, dst_vec, bit31_vec);
+ break;
+ case TGSI_UTIL_SIGN_TOGGLE:
+ /* vec = vec ^ bit31 */
+ ppc_vxor(gen->f, dst_vec2, dst_vec, bit31_vec);
+ break;
+ default:
+ assert(0);
+ }
+ return dst_vec2;
+ }
+ }
+
+ return dst_vec;
+}
+
+
+
+/**
+ * Test if two TGSI src registers refer to the same memory location.
+ * We use this to avoid redundant register loads.
+ */
+static boolean
+equal_src_locs(const struct tgsi_full_src_register *a, uint chan_a,
+ const struct tgsi_full_src_register *b, uint chan_b)
+{
+ int swz_a, swz_b;
+ int sign_a, sign_b;
+ if (a->SrcRegister.File != b->SrcRegister.File)
+ return FALSE;
+ if (a->SrcRegister.Index != b->SrcRegister.Index)
+ return FALSE;
+ swz_a = tgsi_util_get_full_src_register_extswizzle(a, chan_a);
+ swz_b = tgsi_util_get_full_src_register_extswizzle(b, chan_b);
+ if (swz_a != swz_b)
+ return FALSE;
+ sign_a = tgsi_util_get_full_src_register_sign_mode(a, chan_a);
+ sign_b = tgsi_util_get_full_src_register_sign_mode(b, chan_b);
+ if (sign_a != sign_b)
+ return FALSE;
+ return TRUE;
+}
+
+
+/**
+ * Given a TGSI src register and channel index, return the PPC vector
+ * register containing the value. We use a cache to prevent re-loading
+ * the same register multiple times.
+ * \return index of PPC vector register with the desired src operand
+ */
+static int
+get_src_vec(struct gen_context *gen,
+ struct tgsi_full_instruction *inst, int src_reg, uint chan)
+{
+ const const struct tgsi_full_src_register *src =
+ &inst->FullSrcRegisters[src_reg];
+ int vec;
+ uint i;
+
+ /* check the cache */
+ for (i = 0; i < gen->num_regs; i++) {
+ if (equal_src_locs(&gen->regs[i].src, gen->regs[i].chan, src, chan)) {
+ /* cache hit */
+ assert(gen->regs[i].vec >= 0);
+ return gen->regs[i].vec;
+ }
+ }
+
+ /* cache miss: allocate new vec reg and emit fetch/load code */
+ vec = emit_fetch(gen, src, chan);
+ gen->regs[gen->num_regs].src = *src;
+ gen->regs[gen->num_regs].chan = chan;
+ gen->regs[gen->num_regs].vec = vec;
+ gen->num_regs++;
+
+ assert(gen->num_regs <= Elements(gen->regs));
+
+ assert(vec >= 0);
+
+ return vec;
+}
+
+
+/**
+ * Clear the src operand cache. To be called at the end of each emit function.
+ */
+static void
+release_src_vecs(struct gen_context *gen)
+{
+ uint i;
+ for (i = 0; i < gen->num_regs; i++) {
+ const const struct tgsi_full_src_register src = gen->regs[i].src;
+ if (!is_ppc_vec_temporary(&src)) {
+ ppc_release_vec_register(gen->f, gen->regs[i].vec);
+ }
+ }
+ gen->num_regs = 0;
+}
+
+
+
+static int
+get_dst_vec(struct gen_context *gen,
+ const struct tgsi_full_instruction *inst,
+ unsigned chan_index)
+{
+ const struct tgsi_full_dst_register *reg = &inst->FullDstRegisters[0];
+
+ if (is_ppc_vec_temporary_dst(reg)) {
+ int vec = gen->temps_map[reg->DstRegister.Index][chan_index];
+ return vec;
+ }
+ else {
+ return ppc_allocate_vec_register(gen->f);
+ }
+}
+
+
+/**
+ * Register store. Store 'src_vec' at location indicated by 'reg'.
+ * \param free_vec Should the src_vec be released when done?
+ */
+static void
+emit_store(struct gen_context *gen,
+ int src_vec,
+ const struct tgsi_full_instruction *inst,
+ unsigned chan_index,
+ boolean free_vec)
+{
+ const struct tgsi_full_dst_register *reg = &inst->FullDstRegisters[0];
+
+ switch (reg->DstRegister.File) {
+ case TGSI_FILE_OUTPUT:
+ {
+ int offset = (reg->DstRegister.Index * 4 + chan_index) * 16;
+ int offset_reg = emit_li_offset(gen, offset);
+ ppc_stvx(gen->f, src_vec, gen->outputs_reg, offset_reg);
+ }
+ break;
+ case TGSI_FILE_TEMPORARY:
+ if (is_ppc_vec_temporary_dst(reg)) {
+ if (!free_vec) {
+ int dst_vec = gen->temps_map[reg->DstRegister.Index][chan_index];
+ if (dst_vec != src_vec)
+ ppc_vmove(gen->f, dst_vec, src_vec);
+ }
+ free_vec = FALSE;
+ }
+ else {
+ int offset = (reg->DstRegister.Index * 4 + chan_index) * 16;
+ int offset_reg = emit_li_offset(gen, offset);
+ ppc_stvx(gen->f, src_vec, gen->temps_reg, offset_reg);
+ }
+ break;
+#if 0
+ case TGSI_FILE_ADDRESS:
+ emit_addrs(
+ func,
+ xmm,
+ reg->DstRegister.Index,
+ chan_index );
+ break;
+#endif
+ default:
+ assert( 0 );
+ }
+
+#if 0
+ switch( inst->Instruction.Saturate ) {
+ case TGSI_SAT_NONE:
+ break;
+
+ case TGSI_SAT_ZERO_ONE:
+ /* assert( 0 ); */
+ break;
+
+ case TGSI_SAT_MINUS_PLUS_ONE:
+ assert( 0 );
+ break;
+ }
+#endif
+
+ if (free_vec)
+ ppc_release_vec_register(gen->f, src_vec);
+}
+
+
+static void
+emit_scalar_unaryop(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ int v0, v1;
+ uint chan_index;
+
+ v0 = get_src_vec(gen, inst, 0, CHAN_X);
+ v1 = ppc_allocate_vec_register(gen->f);
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_RSQ:
+ /* v1 = 1.0 / sqrt(v0) */
+ ppc_vrsqrtefp(gen->f, v1, v0);
+ break;
+ case TGSI_OPCODE_RCP:
+ /* v1 = 1.0 / v0 */
+ ppc_vrefp(gen->f, v1, v0);
+ break;
+ default:
+ assert(0);
+ }
+
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ emit_store(gen, v1, inst, chan_index, FALSE);
+ }
+
+ release_src_vecs(gen);
+ ppc_release_vec_register(gen->f, v1);
+}
+
+
+static void
+emit_unaryop(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ uint chan_index;
+
+ FOR_EACH_DST0_ENABLED_CHANNEL(*inst, chan_index) {
+ int v0 = get_src_vec(gen, inst, 0, chan_index); /* v0 = srcreg[0] */
+ int v1 = get_dst_vec(gen, inst, chan_index);
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ /* turn off the most significant bit of each vector float word */
+ {
+ int bit31_vec = gen_get_bit31_vec(gen);
+ ppc_vandc(gen->f, v1, v0, bit31_vec); /* v1 = v0 & ~bit31 */
+ }
+ break;
+ case TGSI_OPCODE_FLR:
+ ppc_vrfim(gen->f, v1, v0); /* v1 = floor(v0) */
+ break;
+ case TGSI_OPCODE_FRC:
+ ppc_vrfim(gen->f, v1, v0); /* tmp = floor(v0) */
+ ppc_vsubfp(gen->f, v1, v0, v1); /* v1 = v0 - v1 */
+ break;
+ case TGSI_OPCODE_EX2:
+ ppc_vexptefp(gen->f, v1, v0); /* v1 = 2^v0 */
+ break;
+ case TGSI_OPCODE_LG2:
+ /* XXX this may be broken! */
+ ppc_vlogefp(gen->f, v1, v0); /* v1 = log2(v0) */
+ break;
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ if (v0 != v1)
+ ppc_vmove(gen->f, v1, v0);
+ break;
+ default:
+ assert(0);
+ }
+ emit_store(gen, v1, inst, chan_index, TRUE); /* store v0 */
+ }
+
+ release_src_vecs(gen);
+}
+
+
+static void
+emit_binop(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ int zero_vec = -1;
+ uint chan;
+
+ if (inst->Instruction.Opcode == TGSI_OPCODE_MUL) {
+ zero_vec = ppc_allocate_vec_register(gen->f);
+ ppc_vzero(gen->f, zero_vec);
+ }
+
+ FOR_EACH_DST0_ENABLED_CHANNEL(*inst, chan) {
+ /* fetch src operands */
+ int v0 = get_src_vec(gen, inst, 0, chan);
+ int v1 = get_src_vec(gen, inst, 1, chan);
+ int v2 = get_dst_vec(gen, inst, chan);
+
+ /* emit binop */
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ADD:
+ ppc_vaddfp(gen->f, v2, v0, v1);
+ break;
+ case TGSI_OPCODE_SUB:
+ ppc_vsubfp(gen->f, v2, v0, v1);
+ break;
+ case TGSI_OPCODE_MUL:
+ ppc_vmaddfp(gen->f, v2, v0, v1, zero_vec);
+ break;
+ case TGSI_OPCODE_MIN:
+ ppc_vminfp(gen->f, v2, v0, v1);
+ break;
+ case TGSI_OPCODE_MAX:
+ ppc_vmaxfp(gen->f, v2, v0, v1);
+ break;
+ default:
+ assert(0);
+ }
+
+ /* store v2 */
+ emit_store(gen, v2, inst, chan, TRUE);
+ }
+
+ if (inst->Instruction.Opcode == TGSI_OPCODE_MUL)
+ ppc_release_vec_register(gen->f, zero_vec);
+
+ release_src_vecs(gen);
+}
+
+
+static void
+emit_triop(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ uint chan;
+
+ FOR_EACH_DST0_ENABLED_CHANNEL(*inst, chan) {
+ /* fetch src operands */
+ int v0 = get_src_vec(gen, inst, 0, chan);
+ int v1 = get_src_vec(gen, inst, 1, chan);
+ int v2 = get_src_vec(gen, inst, 2, chan);
+ int v3 = get_dst_vec(gen, inst, chan);
+
+ /* emit ALU */
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_MAD:
+ ppc_vmaddfp(gen->f, v3, v0, v1, v2); /* v3 = v0 * v1 + v2 */
+ break;
+ case TGSI_OPCODE_LRP:
+ ppc_vsubfp(gen->f, v3, v1, v2); /* v3 = v1 - v2 */
+ ppc_vmaddfp(gen->f, v3, v0, v3, v2); /* v3 = v0 * v3 + v2 */
+ break;
+ default:
+ assert(0);
+ }
+
+ /* store v3 */
+ emit_store(gen, v3, inst, chan, TRUE);
+ }
+
+ release_src_vecs(gen);
+}
+
+
+/**
+ * Vector comparisons, resulting in 1.0 or 0.0 values.
+ */
+static void
+emit_inequality(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ uint chan;
+ int one_vec = gen_one_vec(gen);
+
+ FOR_EACH_DST0_ENABLED_CHANNEL(*inst, chan) {
+ /* fetch src operands */
+ int v0 = get_src_vec(gen, inst, 0, chan);
+ int v1 = get_src_vec(gen, inst, 1, chan);
+ int v2 = get_dst_vec(gen, inst, chan);
+ boolean complement = FALSE;
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_SNE:
+ complement = TRUE;
+ /* fall-through */
+ case TGSI_OPCODE_SEQ:
+ ppc_vcmpeqfpx(gen->f, v2, v0, v1); /* v2 = v0 == v1 ? ~0 : 0 */
+ break;
+
+ case TGSI_OPCODE_SGE:
+ complement = TRUE;
+ /* fall-through */
+ case TGSI_OPCODE_SLT:
+ ppc_vcmpgtfpx(gen->f, v2, v1, v0); /* v2 = v1 > v0 ? ~0 : 0 */
+ break;
+
+ case TGSI_OPCODE_SLE:
+ complement = TRUE;
+ /* fall-through */
+ case TGSI_OPCODE_SGT:
+ ppc_vcmpgtfpx(gen->f, v2, v0, v1); /* v2 = v0 > v1 ? ~0 : 0 */
+ break;
+ default:
+ assert(0);
+ }
+
+ /* v2 is now {0,0,0,0} or {~0,~0,~0,~0} */
+
+ if (complement)
+ ppc_vandc(gen->f, v2, one_vec, v2); /* v2 = one_vec & ~v2 */
+ else
+ ppc_vand(gen->f, v2, one_vec, v2); /* v2 = one_vec & v2 */
+
+ /* store v2 */
+ emit_store(gen, v2, inst, chan, TRUE);
+ }
+
+ release_src_vecs(gen);
+}
+
+
+static void
+emit_dotprod(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ int v0, v1, v2;
+ uint chan_index;
+
+ v2 = ppc_allocate_vec_register(gen->f);
+
+ ppc_vzero(gen->f, v2); /* v2 = {0, 0, 0, 0} */
+
+ v0 = get_src_vec(gen, inst, 0, CHAN_X); /* v0 = src0.XXXX */
+ v1 = get_src_vec(gen, inst, 1, CHAN_X); /* v1 = src1.XXXX */
+ ppc_vmaddfp(gen->f, v2, v0, v1, v2); /* v2 = v0 * v1 + v2 */
+
+ v0 = get_src_vec(gen, inst, 0, CHAN_Y); /* v0 = src0.YYYY */
+ v1 = get_src_vec(gen, inst, 1, CHAN_Y); /* v1 = src1.YYYY */
+ ppc_vmaddfp(gen->f, v2, v0, v1, v2); /* v2 = v0 * v1 + v2 */
+
+ v0 = get_src_vec(gen, inst, 0, CHAN_Z); /* v0 = src0.ZZZZ */
+ v1 = get_src_vec(gen, inst, 1, CHAN_Z); /* v1 = src1.ZZZZ */
+ ppc_vmaddfp(gen->f, v2, v0, v1, v2); /* v2 = v0 * v1 + v2 */
+
+ if (inst->Instruction.Opcode == TGSI_OPCODE_DP4) {
+ v0 = get_src_vec(gen, inst, 0, CHAN_W); /* v0 = src0.WWWW */
+ v1 = get_src_vec(gen, inst, 1, CHAN_W); /* v1 = src1.WWWW */
+ ppc_vmaddfp(gen->f, v2, v0, v1, v2); /* v2 = v0 * v1 + v2 */
+ }
+ else if (inst->Instruction.Opcode == TGSI_OPCODE_DPH) {
+ v1 = get_src_vec(gen, inst, 1, CHAN_W); /* v1 = src1.WWWW */
+ ppc_vaddfp(gen->f, v2, v2, v1); /* v2 = v2 + v1 */
+ }
+
+ FOR_EACH_DST0_ENABLED_CHANNEL(*inst, chan_index) {
+ emit_store(gen, v2, inst, chan_index, FALSE); /* store v2, free v2 later */
+ }
+
+ release_src_vecs(gen);
+
+ ppc_release_vec_register(gen->f, v2);
+}
+
+
+/** Approximation for vr = pow(va, vb) */
+static void
+ppc_vec_pow(struct ppc_function *f, int vr, int va, int vb)
+{
+ /* pow(a,b) ~= exp2(log2(a) * b) */
+ int t_vec = ppc_allocate_vec_register(f);
+ int zero_vec = ppc_allocate_vec_register(f);
+
+ ppc_vzero(f, zero_vec);
+
+ ppc_vlogefp(f, t_vec, va); /* t = log2(va) */
+ ppc_vmaddfp(f, t_vec, t_vec, vb, zero_vec); /* t = t * vb + zero */
+ ppc_vexptefp(f, vr, t_vec); /* vr = 2^t */
+
+ ppc_release_vec_register(f, t_vec);
+ ppc_release_vec_register(f, zero_vec);
+}
+
+
+static void
+emit_lit(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ int one_vec = gen_one_vec(gen);
+
+ /* Compute X */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X)) {
+ emit_store(gen, one_vec, inst, CHAN_X, FALSE);
+ }
+
+ /* Compute Y, Z */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y) ||
+ IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ int x_vec;
+ int zero_vec = ppc_allocate_vec_register(gen->f);
+
+ x_vec = get_src_vec(gen, inst, 0, CHAN_X); /* x_vec = src[0].x */
+
+ ppc_vzero(gen->f, zero_vec); /* zero = {0,0,0,0} */
+ ppc_vmaxfp(gen->f, x_vec, x_vec, zero_vec); /* x_vec = max(x_vec, 0) */
+
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ emit_store(gen, x_vec, inst, CHAN_Y, FALSE);
+ }
+
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ int y_vec, w_vec;
+ int z_vec = ppc_allocate_vec_register(gen->f);
+ int pow_vec = ppc_allocate_vec_register(gen->f);
+ int pos_vec = ppc_allocate_vec_register(gen->f);
+ int p128_vec = ppc_allocate_vec_register(gen->f);
+ int n128_vec = ppc_allocate_vec_register(gen->f);
+
+ y_vec = get_src_vec(gen, inst, 0, CHAN_Y); /* y_vec = src[0].y */
+ ppc_vmaxfp(gen->f, y_vec, y_vec, zero_vec); /* y_vec = max(y_vec, 0) */
+
+ w_vec = get_src_vec(gen, inst, 0, CHAN_W); /* w_vec = src[0].w */
+
+ /* clamp W to [-128, 128] */
+ load_constant_vec(gen, p128_vec, 128.0f);
+ load_constant_vec(gen, n128_vec, -128.0f);
+ ppc_vmaxfp(gen->f, w_vec, w_vec, n128_vec); /* w = max(w, -128) */
+ ppc_vminfp(gen->f, w_vec, w_vec, p128_vec); /* w = min(w, 128) */
+
+ /* if temp.x > 0
+ * z = pow(tmp.y, tmp.w)
+ * else
+ * z = 0.0
+ */
+ ppc_vec_pow(gen->f, pow_vec, y_vec, w_vec); /* pow = pow(y, w) */
+ ppc_vcmpgtfpx(gen->f, pos_vec, x_vec, zero_vec); /* pos = x > 0 */
+ ppc_vand(gen->f, z_vec, pow_vec, pos_vec); /* z = pow & pos */
+
+ emit_store(gen, z_vec, inst, CHAN_Z, FALSE);
+
+ ppc_release_vec_register(gen->f, z_vec);
+ ppc_release_vec_register(gen->f, pow_vec);
+ ppc_release_vec_register(gen->f, pos_vec);
+ ppc_release_vec_register(gen->f, p128_vec);
+ ppc_release_vec_register(gen->f, n128_vec);
+ }
+
+ ppc_release_vec_register(gen->f, zero_vec);
+ }
+
+ /* Compute W */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_W)) {
+ emit_store(gen, one_vec, inst, CHAN_W, FALSE);
+ }
+
+ release_src_vecs(gen);
+}
+
+
+static void
+emit_exp(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ const int one_vec = gen_one_vec(gen);
+ int src_vec;
+
+ /* get src arg */
+ src_vec = get_src_vec(gen, inst, 0, CHAN_X);
+
+ /* Compute X = 2^floor(src) */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X)) {
+ int dst_vec = get_dst_vec(gen, inst, CHAN_X);
+ int tmp_vec = ppc_allocate_vec_register(gen->f);
+ ppc_vrfim(gen->f, tmp_vec, src_vec); /* tmp = floor(src); */
+ ppc_vexptefp(gen->f, dst_vec, tmp_vec); /* dst = 2 ^ tmp */
+ emit_store(gen, dst_vec, inst, CHAN_X, TRUE);
+ ppc_release_vec_register(gen->f, tmp_vec);
+ }
+
+ /* Compute Y = src - floor(src) */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ int dst_vec = get_dst_vec(gen, inst, CHAN_Y);
+ int tmp_vec = ppc_allocate_vec_register(gen->f);
+ ppc_vrfim(gen->f, tmp_vec, src_vec); /* tmp = floor(src); */
+ ppc_vsubfp(gen->f, dst_vec, src_vec, tmp_vec); /* dst = src - tmp */
+ emit_store(gen, dst_vec, inst, CHAN_Y, TRUE);
+ ppc_release_vec_register(gen->f, tmp_vec);
+ }
+
+ /* Compute Z = RoughApprox2ToX(src) */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ int dst_vec = get_dst_vec(gen, inst, CHAN_Z);
+ ppc_vexptefp(gen->f, dst_vec, src_vec); /* dst = 2 ^ src */
+ emit_store(gen, dst_vec, inst, CHAN_Z, TRUE);
+ }
+
+ /* Compute W = 1.0 */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_W)) {
+ emit_store(gen, one_vec, inst, CHAN_W, FALSE);
+ }
+
+ release_src_vecs(gen);
+}
+
+
+static void
+emit_log(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ const int bit31_vec = gen_get_bit31_vec(gen);
+ const int one_vec = gen_one_vec(gen);
+ int src_vec, abs_vec;
+
+ /* get src arg */
+ src_vec = get_src_vec(gen, inst, 0, CHAN_X);
+
+ /* compute abs(src) */
+ abs_vec = ppc_allocate_vec_register(gen->f);
+ ppc_vandc(gen->f, abs_vec, src_vec, bit31_vec); /* abs = src & ~bit31 */
+
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X) &&
+ IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+
+ /* compute tmp = floor(log2(abs)) */
+ int tmp_vec = ppc_allocate_vec_register(gen->f);
+ ppc_vlogefp(gen->f, tmp_vec, abs_vec); /* tmp = log2(abs) */
+ ppc_vrfim(gen->f, tmp_vec, tmp_vec); /* tmp = floor(tmp); */
+
+ /* Compute X = tmp */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X)) {
+ emit_store(gen, tmp_vec, inst, CHAN_X, FALSE);
+ }
+
+ /* Compute Y = abs / 2^tmp */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ const int zero_vec = ppc_allocate_vec_register(gen->f);
+ ppc_vzero(gen->f, zero_vec);
+ ppc_vexptefp(gen->f, tmp_vec, tmp_vec); /* tmp = 2 ^ tmp */
+ ppc_vrefp(gen->f, tmp_vec, tmp_vec); /* tmp = 1 / tmp */
+ /* tmp = abs * tmp + zero */
+ ppc_vmaddfp(gen->f, tmp_vec, abs_vec, tmp_vec, zero_vec);
+ emit_store(gen, tmp_vec, inst, CHAN_Y, FALSE);
+ ppc_release_vec_register(gen->f, zero_vec);
+ }
+
+ ppc_release_vec_register(gen->f, tmp_vec);
+ }
+
+ /* Compute Z = RoughApproxLog2(abs) */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ int dst_vec = get_dst_vec(gen, inst, CHAN_Z);
+ ppc_vlogefp(gen->f, dst_vec, abs_vec); /* dst = log2(abs) */
+ emit_store(gen, dst_vec, inst, CHAN_Z, TRUE);
+ }
+
+ /* Compute W = 1.0 */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_W)) {
+ emit_store(gen, one_vec, inst, CHAN_W, FALSE);
+ }
+
+ ppc_release_vec_register(gen->f, abs_vec);
+ release_src_vecs(gen);
+}
+
+
+static void
+emit_pow(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ int s0_vec = get_src_vec(gen, inst, 0, CHAN_X);
+ int s1_vec = get_src_vec(gen, inst, 1, CHAN_X);
+ int pow_vec = ppc_allocate_vec_register(gen->f);
+ int chan;
+
+ ppc_vec_pow(gen->f, pow_vec, s0_vec, s1_vec);
+
+ FOR_EACH_DST0_ENABLED_CHANNEL(*inst, chan) {
+ emit_store(gen, pow_vec, inst, chan, FALSE);
+ }
+
+ ppc_release_vec_register(gen->f, pow_vec);
+
+ release_src_vecs(gen);
+}
+
+
+static void
+emit_xpd(struct gen_context *gen, struct tgsi_full_instruction *inst)
+{
+ int x0_vec, y0_vec, z0_vec;
+ int x1_vec, y1_vec, z1_vec;
+ int zero_vec, tmp_vec;
+ int tmp2_vec;
+
+ zero_vec = ppc_allocate_vec_register(gen->f);
+ ppc_vzero(gen->f, zero_vec);
+
+ tmp_vec = ppc_allocate_vec_register(gen->f);
+ tmp2_vec = ppc_allocate_vec_register(gen->f);
+
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y) ||
+ IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ x0_vec = get_src_vec(gen, inst, 0, CHAN_X);
+ x1_vec = get_src_vec(gen, inst, 1, CHAN_X);
+ }
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X) ||
+ IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ y0_vec = get_src_vec(gen, inst, 0, CHAN_Y);
+ y1_vec = get_src_vec(gen, inst, 1, CHAN_Y);
+ }
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X) ||
+ IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ z0_vec = get_src_vec(gen, inst, 0, CHAN_Z);
+ z1_vec = get_src_vec(gen, inst, 1, CHAN_Z);
+ }
+
+ IF_IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X) {
+ /* tmp = y0 * z1 */
+ ppc_vmaddfp(gen->f, tmp_vec, y0_vec, z1_vec, zero_vec);
+ /* tmp = tmp - z0 * y1*/
+ ppc_vnmsubfp(gen->f, tmp_vec, tmp_vec, z0_vec, y1_vec);
+ emit_store(gen, tmp_vec, inst, CHAN_X, FALSE);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y) {
+ /* tmp = z0 * x1 */
+ ppc_vmaddfp(gen->f, tmp_vec, z0_vec, x1_vec, zero_vec);
+ /* tmp = tmp - x0 * z1 */
+ ppc_vnmsubfp(gen->f, tmp_vec, tmp_vec, x0_vec, z1_vec);
+ emit_store(gen, tmp_vec, inst, CHAN_Y, FALSE);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z) {
+ /* tmp = x0 * y1 */
+ ppc_vmaddfp(gen->f, tmp_vec, x0_vec, y1_vec, zero_vec);
+ /* tmp = tmp - y0 * x1 */
+ ppc_vnmsubfp(gen->f, tmp_vec, tmp_vec, y0_vec, x1_vec);
+ emit_store(gen, tmp_vec, inst, CHAN_Z, FALSE);
+ }
+ /* W is undefined */
+
+ ppc_release_vec_register(gen->f, tmp_vec);
+ ppc_release_vec_register(gen->f, zero_vec);
+ release_src_vecs(gen);
+}
+
+static int
+emit_instruction(struct gen_context *gen,
+ struct tgsi_full_instruction *inst)
+{
+
+ /* we don't handle saturation/clamping yet */
+ if (inst->Instruction.Saturate != TGSI_SAT_NONE)
+ return 0;
+
+ /* need to use extra temps to fix SOA dependencies : */
+ if (tgsi_check_soa_dependencies(inst))
+ return FALSE;
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ case TGSI_OPCODE_ABS:
+ case TGSI_OPCODE_FLR:
+ case TGSI_OPCODE_FRC:
+ case TGSI_OPCODE_EX2:
+ case TGSI_OPCODE_LG2:
+ emit_unaryop(gen, inst);
+ break;
+ case TGSI_OPCODE_RSQ:
+ case TGSI_OPCODE_RCP:
+ emit_scalar_unaryop(gen, inst);
+ break;
+ case TGSI_OPCODE_ADD:
+ case TGSI_OPCODE_SUB:
+ case TGSI_OPCODE_MUL:
+ case TGSI_OPCODE_MIN:
+ case TGSI_OPCODE_MAX:
+ emit_binop(gen, inst);
+ break;
+ case TGSI_OPCODE_SEQ:
+ case TGSI_OPCODE_SNE:
+ case TGSI_OPCODE_SLT:
+ case TGSI_OPCODE_SGT:
+ case TGSI_OPCODE_SLE:
+ case TGSI_OPCODE_SGE:
+ emit_inequality(gen, inst);
+ break;
+ case TGSI_OPCODE_MAD:
+ case TGSI_OPCODE_LRP:
+ emit_triop(gen, inst);
+ break;
+ case TGSI_OPCODE_DP3:
+ case TGSI_OPCODE_DP4:
+ case TGSI_OPCODE_DPH:
+ emit_dotprod(gen, inst);
+ break;
+ case TGSI_OPCODE_LIT:
+ emit_lit(gen, inst);
+ break;
+ case TGSI_OPCODE_LOG:
+ emit_log(gen, inst);
+ break;
+ case TGSI_OPCODE_EXP:
+ emit_exp(gen, inst);
+ break;
+ case TGSI_OPCODE_POW:
+ emit_pow(gen, inst);
+ break;
+ case TGSI_OPCODE_XPD:
+ emit_xpd(gen, inst);
+ break;
+ case TGSI_OPCODE_END:
+ /* normal end */
+ return 1;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+
+static void
+emit_declaration(
+ struct ppc_function *func,
+ struct tgsi_full_declaration *decl )
+{
+ if( decl->Declaration.File == TGSI_FILE_INPUT ) {
+#if 0
+ unsigned first, last, mask;
+ unsigned i, j;
+
+ first = decl->DeclarationRange.First;
+ last = decl->DeclarationRange.Last;
+ mask = decl->Declaration.UsageMask;
+
+ for( i = first; i <= last; i++ ) {
+ for( j = 0; j < NUM_CHANNELS; j++ ) {
+ if( mask & (1 << j) ) {
+ switch( decl->Declaration.Interpolate ) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ emit_coef_a0( func, 0, i, j );
+ emit_inputs( func, 0, i, j );
+ break;
+
+ case TGSI_INTERPOLATE_LINEAR:
+ emit_tempf( func, 0, 0, TGSI_SWIZZLE_X );
+ emit_coef_dadx( func, 1, i, j );
+ emit_tempf( func, 2, 0, TGSI_SWIZZLE_Y );
+ emit_coef_dady( func, 3, i, j );
+ emit_mul( func, 0, 1 ); /* x * dadx */
+ emit_coef_a0( func, 4, i, j );
+ emit_mul( func, 2, 3 ); /* y * dady */
+ emit_add( func, 0, 4 ); /* x * dadx + a0 */
+ emit_add( func, 0, 2 ); /* x * dadx + y * dady + a0 */
+ emit_inputs( func, 0, i, j );
+ break;
+
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ emit_tempf( func, 0, 0, TGSI_SWIZZLE_X );
+ emit_coef_dadx( func, 1, i, j );
+ emit_tempf( func, 2, 0, TGSI_SWIZZLE_Y );
+ emit_coef_dady( func, 3, i, j );
+ emit_mul( func, 0, 1 ); /* x * dadx */
+ emit_tempf( func, 4, 0, TGSI_SWIZZLE_W );
+ emit_coef_a0( func, 5, i, j );
+ emit_rcp( func, 4, 4 ); /* 1.0 / w */
+ emit_mul( func, 2, 3 ); /* y * dady */
+ emit_add( func, 0, 5 ); /* x * dadx + a0 */
+ emit_add( func, 0, 2 ); /* x * dadx + y * dady + a0 */
+ emit_mul( func, 0, 4 ); /* (x * dadx + y * dady + a0) / w */
+ emit_inputs( func, 0, i, j );
+ break;
+
+ default:
+ assert( 0 );
+ break;
+ }
+ }
+ }
+ }
+#endif
+ }
+}
+
+
+
+static void
+emit_prologue(struct ppc_function *func)
+{
+ /* XXX set up stack frame */
+}
+
+
+static void
+emit_epilogue(struct ppc_function *func)
+{
+ ppc_comment(func, -4, "Epilogue:");
+ ppc_return(func);
+ /* XXX restore prev stack frame */
+#if 0
+ debug_printf("PPC: Emitted %u instructions\n", func->num_inst);
+#endif
+}
+
+
+
+/**
+ * Translate a TGSI vertex/fragment shader to PPC code.
+ *
+ * \param tokens the TGSI input shader
+ * \param func the output PPC code/function
+ * \param immediates buffer to place immediates, later passed to PPC func
+ * \return TRUE for success, FALSE if translation failed
+ */
+boolean
+tgsi_emit_ppc(const struct tgsi_token *tokens,
+ struct ppc_function *func,
+ float (*immediates)[4],
+ boolean do_swizzles )
+{
+ static int use_ppc_asm = -1;
+ struct tgsi_parse_context parse;
+ /*boolean instruction_phase = FALSE;*/
+ unsigned ok = 1;
+ uint num_immediates = 0;
+ struct gen_context gen;
+ uint ic = 0;
+
+ if (use_ppc_asm < 0) {
+ /* If GALLIUM_NOPPC is set, don't use PPC codegen */
+ use_ppc_asm = !debug_get_bool_option("GALLIUM_NOPPC", FALSE);
+ }
+ if (!use_ppc_asm)
+ return FALSE;
+
+ if (0) {
+ debug_printf("\n********* TGSI->PPC ********\n");
+ tgsi_dump(tokens, 0);
+ }
+
+ util_init_math();
+
+ init_gen_context(&gen, func);
+
+ emit_prologue(func);
+
+ tgsi_parse_init( &parse, tokens );
+
+ while (!tgsi_parse_end_of_tokens(&parse) && ok) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
+ emit_declaration(func, &parse.FullToken.FullDeclaration );
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (func->print) {
+ _debug_printf("# ");
+ ic++;
+ tgsi_dump_instruction(&parse.FullToken.FullInstruction, ic);
+ }
+
+ ok = emit_instruction(&gen, &parse.FullToken.FullInstruction);
+
+ if (!ok) {
+ uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode;
+ debug_printf("failed to translate tgsi opcode %d (%s) to PPC (%s)\n",
+ opcode,
+ tgsi_get_opcode_name(opcode),
+ parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX ?
+ "vertex shader" : "fragment shader");
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ /* splat each immediate component into a float[4] vector for SoA */
+ {
+ const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
+ uint i;
+ assert(size <= 4);
+ assert(num_immediates < TGSI_EXEC_NUM_IMMEDIATES);
+ for (i = 0; i < size; i++) {
+ immediates[num_immediates][i] =
+ parse.FullToken.FullImmediate.u[i].Float;
+ }
+ num_immediates++;
+ }
+ break;
+
+ default:
+ ok = 0;
+ assert( 0 );
+ }
+ }
+
+ emit_epilogue(func);
+
+ tgsi_parse_free( &parse );
+
+ if (ppc_num_instructions(func) == 0) {
+ /* ran out of memory for instructions */
+ ok = FALSE;
+ }
+
+ if (!ok)
+ debug_printf("TGSI->PPC translation failed\n");
+
+ return ok;
+}
+
+#endif /* PIPE_ARCH_PPC */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ppc.h b/src/gallium/auxiliary/tgsi/tgsi_ppc.h
new file mode 100644
index 0000000000..829ec075e7
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_ppc.h
@@ -0,0 +1,51 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_PPC_H
+#define TGSI_PPC_H
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct tgsi_token;
+struct ppc_function;
+
+extern const float ppc_builtin_constants[];
+
+
+boolean
+tgsi_emit_ppc(const struct tgsi_token *tokens,
+ struct ppc_function *function,
+ float (*immediates)[4],
+ boolean do_swizzles);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_PPC_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
new file mode 100644
index 0000000000..8a13885da9
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
@@ -0,0 +1,385 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "tgsi_sanity.h"
+#include "tgsi_info.h"
+#include "tgsi_iterate.h"
+
+typedef uint reg_flag;
+
+#define BITS_IN_REG_FLAG (sizeof( reg_flag ) * 8)
+
+#define MAX_REGISTERS 256
+#define MAX_REG_FLAGS ((MAX_REGISTERS + BITS_IN_REG_FLAG - 1) / BITS_IN_REG_FLAG)
+
+struct sanity_check_ctx
+{
+ struct tgsi_iterate_context iter;
+
+ reg_flag regs_decl[TGSI_FILE_COUNT][MAX_REG_FLAGS];
+ reg_flag regs_used[TGSI_FILE_COUNT][MAX_REG_FLAGS];
+ boolean regs_ind_used[TGSI_FILE_COUNT];
+ uint num_imms;
+ uint num_instructions;
+ uint index_of_END;
+
+ uint errors;
+ uint warnings;
+};
+
+static void
+report_error(
+ struct sanity_check_ctx *ctx,
+ const char *format,
+ ... )
+{
+ va_list args;
+
+ debug_printf( "Error : " );
+ va_start( args, format );
+ _debug_vprintf( format, args );
+ va_end( args );
+ debug_printf( "\n" );
+ ctx->errors++;
+}
+
+static void
+report_warning(
+ struct sanity_check_ctx *ctx,
+ const char *format,
+ ... )
+{
+ va_list args;
+
+ debug_printf( "Warning: " );
+ va_start( args, format );
+ _debug_vprintf( format, args );
+ va_end( args );
+ debug_printf( "\n" );
+ ctx->warnings++;
+}
+
+static boolean
+check_file_name(
+ struct sanity_check_ctx *ctx,
+ uint file )
+{
+ if (file <= TGSI_FILE_NULL || file >= TGSI_FILE_COUNT) {
+ report_error( ctx, "(%u): Invalid register file name", file );
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static boolean
+is_register_declared(
+ struct sanity_check_ctx *ctx,
+ uint file,
+ int index )
+{
+ assert( index >= 0 && index < MAX_REGISTERS );
+
+ return (ctx->regs_decl[file][index / BITS_IN_REG_FLAG] & (1 << (index % BITS_IN_REG_FLAG))) ? TRUE : FALSE;
+}
+
+static boolean
+is_any_register_declared(
+ struct sanity_check_ctx *ctx,
+ uint file )
+{
+ uint i;
+
+ for (i = 0; i < MAX_REG_FLAGS; i++)
+ if (ctx->regs_decl[file][i])
+ return TRUE;
+ return FALSE;
+}
+
+static boolean
+is_register_used(
+ struct sanity_check_ctx *ctx,
+ uint file,
+ int index )
+{
+ assert( index < MAX_REGISTERS );
+
+ return (ctx->regs_used[file][index / BITS_IN_REG_FLAG] & (1 << (index % BITS_IN_REG_FLAG))) ? TRUE : FALSE;
+}
+
+static const char *file_names[TGSI_FILE_COUNT] =
+{
+ "NULL",
+ "CONST",
+ "IN",
+ "OUT",
+ "TEMP",
+ "SAMP",
+ "ADDR",
+ "IMM",
+ "LOOP"
+};
+
+static boolean
+check_register_usage(
+ struct sanity_check_ctx *ctx,
+ uint file,
+ int index,
+ const char *name,
+ boolean indirect_access )
+{
+ if (!check_file_name( ctx, file ))
+ return FALSE;
+
+ if (indirect_access) {
+ /* Note that 'index' is an offset relative to the value of the
+ * address register. No range checking done here.
+ */
+ if (!is_any_register_declared( ctx, file ))
+ report_error( ctx, "%s: Undeclared %s register", file_names[file], name );
+ ctx->regs_ind_used[file] = TRUE;
+ }
+ else {
+ if (index < 0 || index >= MAX_REGISTERS) {
+ report_error( ctx, "%s[%d]: Invalid %s index", file_names[file], index, name );
+ return FALSE;
+ }
+
+ if (!is_register_declared( ctx, file, index ))
+ report_error( ctx, "%s[%d]: Undeclared %s register", file_names[file], index, name );
+ ctx->regs_used[file][index / BITS_IN_REG_FLAG] |= (1 << (index % BITS_IN_REG_FLAG));
+ }
+ return TRUE;
+}
+
+static boolean
+iter_instruction(
+ struct tgsi_iterate_context *iter,
+ struct tgsi_full_instruction *inst )
+{
+ struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
+ const struct tgsi_opcode_info *info;
+ uint i;
+
+ if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
+ if (ctx->index_of_END != ~0) {
+ report_error( ctx, "Too many END instructions" );
+ }
+ ctx->index_of_END = ctx->num_instructions;
+ }
+
+ info = tgsi_get_opcode_info( inst->Instruction.Opcode );
+ if (info == NULL) {
+ report_error( ctx, "(%u): Invalid instruction opcode", inst->Instruction.Opcode );
+ return TRUE;
+ }
+
+ if (info->num_dst != inst->Instruction.NumDstRegs) {
+ report_error( ctx, "%s: Invalid number of destination operands, should be %u", info->mnemonic, info->num_dst );
+ }
+ if (info->num_src != inst->Instruction.NumSrcRegs) {
+ report_error( ctx, "%s: Invalid number of source operands, should be %u", info->mnemonic, info->num_src );
+ }
+
+ /* Check destination and source registers' validity.
+ * Mark the registers as used.
+ */
+ for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
+ check_register_usage(
+ ctx,
+ inst->FullDstRegisters[i].DstRegister.File,
+ inst->FullDstRegisters[i].DstRegister.Index,
+ "destination",
+ FALSE );
+ }
+ for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+ check_register_usage(
+ ctx,
+ inst->FullSrcRegisters[i].SrcRegister.File,
+ inst->FullSrcRegisters[i].SrcRegister.Index,
+ "source",
+ (boolean)inst->FullSrcRegisters[i].SrcRegister.Indirect );
+ if (inst->FullSrcRegisters[i].SrcRegister.Indirect) {
+ uint file;
+ int index;
+
+ file = inst->FullSrcRegisters[i].SrcRegisterInd.File;
+ index = inst->FullSrcRegisters[i].SrcRegisterInd.Index;
+ check_register_usage(
+ ctx,
+ file,
+ index,
+ "indirect",
+ FALSE );
+ if (!(file == TGSI_FILE_ADDRESS || file == TGSI_FILE_LOOP) || index != 0) {
+ report_warning(ctx, "Indirect register neither ADDR[0] nor LOOP[0]");
+ }
+ }
+ }
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_BGNFOR:
+ case TGSI_OPCODE_ENDFOR:
+ if (inst->FullDstRegisters[0].DstRegister.File != TGSI_FILE_LOOP ||
+ inst->FullDstRegisters[0].DstRegister.Index != 0) {
+ report_error(ctx, "Destination register must be LOOP[0]");
+ }
+ break;
+ }
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_BGNFOR:
+ if (inst->FullSrcRegisters[0].SrcRegister.File != TGSI_FILE_CONSTANT &&
+ inst->FullSrcRegisters[0].SrcRegister.File != TGSI_FILE_IMMEDIATE) {
+ report_error(ctx, "Source register file must be either CONST or IMM");
+ }
+ break;
+ }
+
+ ctx->num_instructions++;
+
+ return TRUE;
+}
+
+static boolean
+iter_declaration(
+ struct tgsi_iterate_context *iter,
+ struct tgsi_full_declaration *decl )
+{
+ struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
+ uint file;
+ uint i;
+
+ /* No declarations allowed after the first instruction.
+ */
+ if (ctx->num_instructions > 0)
+ report_error( ctx, "Instruction expected but declaration found" );
+
+ /* Check registers' validity.
+ * Mark the registers as declared.
+ */
+ file = decl->Declaration.File;
+ if (!check_file_name( ctx, file ))
+ return TRUE;
+ for (i = decl->DeclarationRange.First; i <= decl->DeclarationRange.Last; i++) {
+ if (is_register_declared( ctx, file, i ))
+ report_error( ctx, "%s[%u]: The same register declared more than once", file_names[file], i );
+ ctx->regs_decl[file][i / BITS_IN_REG_FLAG] |= (1 << (i % BITS_IN_REG_FLAG));
+ }
+
+ return TRUE;
+}
+
+static boolean
+iter_immediate(
+ struct tgsi_iterate_context *iter,
+ struct tgsi_full_immediate *imm )
+{
+ struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
+
+ assert( ctx->num_imms < MAX_REGISTERS );
+
+ /* No immediates allowed after the first instruction.
+ */
+ if (ctx->num_instructions > 0)
+ report_error( ctx, "Instruction expected but immediate found" );
+
+ /* Mark the register as declared.
+ */
+ ctx->regs_decl[TGSI_FILE_IMMEDIATE][ctx->num_imms / BITS_IN_REG_FLAG] |= (1 << (ctx->num_imms % BITS_IN_REG_FLAG));
+ ctx->num_imms++;
+
+ /* Check data type validity.
+ */
+ if (imm->Immediate.DataType != TGSI_IMM_FLOAT32) {
+ report_error( ctx, "(%u): Invalid immediate data type", imm->Immediate.DataType );
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+static boolean
+epilog(
+ struct tgsi_iterate_context *iter )
+{
+ struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
+ uint file;
+
+ /* There must be an END instruction somewhere.
+ */
+ if (ctx->index_of_END == ~0) {
+ report_error( ctx, "Missing END instruction" );
+ }
+
+ /* Check if all declared registers were used.
+ */
+ for (file = TGSI_FILE_NULL; file < TGSI_FILE_COUNT; file++) {
+ uint i;
+
+ for (i = 0; i < MAX_REGISTERS; i++) {
+ if (is_register_declared( ctx, file, i ) && !is_register_used( ctx, file, i ) && !ctx->regs_ind_used[file]) {
+ report_warning( ctx, "%s[%u]: Register never used", file_names[file], i );
+ }
+ }
+ }
+
+ /* Print totals, if any.
+ */
+ if (ctx->errors || ctx->warnings)
+ debug_printf( "%u errors, %u warnings\n", ctx->errors, ctx->warnings );
+
+ return TRUE;
+}
+
+boolean
+tgsi_sanity_check(
+ struct tgsi_token *tokens )
+{
+ struct sanity_check_ctx ctx;
+
+ ctx.iter.prolog = NULL;
+ ctx.iter.iterate_instruction = iter_instruction;
+ ctx.iter.iterate_declaration = iter_declaration;
+ ctx.iter.iterate_immediate = iter_immediate;
+ ctx.iter.epilog = epilog;
+
+ memset( ctx.regs_decl, 0, sizeof( ctx.regs_decl ) );
+ memset( ctx.regs_used, 0, sizeof( ctx.regs_used ) );
+ memset( ctx.regs_ind_used, 0, sizeof( ctx.regs_ind_used ) );
+ ctx.num_imms = 0;
+ ctx.num_instructions = 0;
+ ctx.index_of_END = ~0;
+
+ ctx.errors = 0;
+ ctx.warnings = 0;
+
+ if (!tgsi_iterate_shader( tokens, &ctx.iter ))
+ return FALSE;
+
+ return ctx.errors == 0;
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.h b/src/gallium/auxiliary/tgsi/tgsi_sanity.h
new file mode 100644
index 0000000000..ca45e94c7a
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_SANITY_H
+#define TGSI_SANITY_H
+
+#include "pipe/p_shader_tokens.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+/* Check the given token stream for errors and common mistakes.
+ * Diagnostic messages are printed out to the debug output.
+ * Returns TRUE if there are no errors, even though there could be some warnings.
+ */
+boolean
+tgsi_sanity_check(
+ struct tgsi_token *tokens );
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_SANITY_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c
new file mode 100644
index 0000000000..c535788819
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c
@@ -0,0 +1,256 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2008 VMware, Inc. All rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/**
+ * TGSI program scan utility.
+ * Used to determine which registers and instructions are used by a shader.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include "util/u_math.h"
+#include "tgsi/tgsi_build.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
+
+
+
+
+/**
+ * Scan the given TGSI shader to collect information such as number of
+ * registers used, special instructions used, etc.
+ * \return info the result of the scan
+ */
+void
+tgsi_scan_shader(const struct tgsi_token *tokens,
+ struct tgsi_shader_info *info)
+{
+ uint procType, i;
+ struct tgsi_parse_context parse;
+
+ memset(info, 0, sizeof(*info));
+ for (i = 0; i < TGSI_FILE_COUNT; i++)
+ info->file_max[i] = -1;
+
+ /**
+ ** Setup to begin parsing input shader
+ **/
+ if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
+ debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n");
+ return;
+ }
+ procType = parse.FullHeader.Processor.Processor;
+ assert(procType == TGSI_PROCESSOR_FRAGMENT ||
+ procType == TGSI_PROCESSOR_VERTEX ||
+ procType == TGSI_PROCESSOR_GEOMETRY);
+
+
+ /**
+ ** Loop over incoming program tokens/instructions
+ */
+ while( !tgsi_parse_end_of_tokens( &parse ) ) {
+
+ info->num_tokens++;
+
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ const struct tgsi_full_instruction *fullinst
+ = &parse.FullToken.FullInstruction;
+
+ assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
+ info->opcode_count[fullinst->Instruction.Opcode]++;
+
+ /* special case: scan fragment shaders for use of the fog
+ * input/attribute. The X component is fog, the Y component
+ * is the front/back-face flag.
+ */
+ if (procType == TGSI_PROCESSOR_FRAGMENT) {
+ uint i;
+ for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *src =
+ &fullinst->FullSrcRegisters[i];
+ if (src->SrcRegister.File == TGSI_FILE_INPUT) {
+ const int ind = src->SrcRegister.Index;
+ if (info->input_semantic_name[ind] == TGSI_SEMANTIC_FOG) {
+ if (src->SrcRegister.SwizzleX == TGSI_SWIZZLE_X) {
+ info->uses_fogcoord = TRUE;
+ }
+ else if (src->SrcRegister.SwizzleX == TGSI_SWIZZLE_Y) {
+ info->uses_frontfacing = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *fulldecl
+ = &parse.FullToken.FullDeclaration;
+ const uint file = fulldecl->Declaration.File;
+ uint reg;
+ for (reg = fulldecl->DeclarationRange.First;
+ reg <= fulldecl->DeclarationRange.Last;
+ reg++) {
+
+ /* only first 32 regs will appear in this bitfield */
+ info->file_mask[file] |= (1 << reg);
+ info->file_count[file]++;
+ info->file_max[file] = MAX2(info->file_max[file], (int)reg);
+
+ if (file == TGSI_FILE_INPUT) {
+ info->input_semantic_name[reg] = (ubyte)fulldecl->Semantic.SemanticName;
+ info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.SemanticIndex;
+ info->num_inputs++;
+ }
+ else if (file == TGSI_FILE_OUTPUT) {
+ info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.SemanticName;
+ info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.SemanticIndex;
+ info->num_outputs++;
+ }
+
+ /* special case */
+ if (procType == TGSI_PROCESSOR_FRAGMENT &&
+ file == TGSI_FILE_OUTPUT &&
+ fulldecl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION) {
+ info->writes_z = TRUE;
+ }
+ }
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ uint reg = info->immediate_count++;
+ uint file = TGSI_FILE_IMMEDIATE;
+
+ info->file_mask[file] |= (1 << reg);
+ info->file_count[file]++;
+ info->file_max[file] = MAX2(info->file_max[file], (int)reg);
+ }
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+
+ info->uses_kill = (info->opcode_count[TGSI_OPCODE_KIL] ||
+ info->opcode_count[TGSI_OPCODE_KILP]);
+
+ tgsi_parse_free (&parse);
+}
+
+
+
+/**
+ * Check if the given shader is a "passthrough" shader consisting of only
+ * MOV instructions of the form: MOV OUT[n], IN[n]
+ *
+ */
+boolean
+tgsi_is_passthrough_shader(const struct tgsi_token *tokens)
+{
+ struct tgsi_parse_context parse;
+
+ /**
+ ** Setup to begin parsing input shader
+ **/
+ if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) {
+ debug_printf("tgsi_parse_init() failed in tgsi_is_passthrough_shader()!\n");
+ return FALSE;
+ }
+
+ /**
+ ** Loop over incoming program tokens/instructions
+ */
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ struct tgsi_full_instruction *fullinst =
+ &parse.FullToken.FullInstruction;
+ const struct tgsi_full_src_register *src =
+ &fullinst->FullSrcRegisters[0];
+ const struct tgsi_full_dst_register *dst =
+ &fullinst->FullDstRegisters[0];
+
+ /* Do a whole bunch of checks for a simple move */
+ if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV ||
+ src->SrcRegister.File != TGSI_FILE_INPUT ||
+ dst->DstRegister.File != TGSI_FILE_OUTPUT ||
+ src->SrcRegister.Index != dst->DstRegister.Index ||
+
+ src->SrcRegister.Negate ||
+ src->SrcRegisterExtMod.Negate ||
+ src->SrcRegisterExtMod.Absolute ||
+ src->SrcRegisterExtMod.Scale2X ||
+ src->SrcRegisterExtMod.Bias ||
+ src->SrcRegisterExtMod.Complement ||
+
+ src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
+ src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
+ src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
+ src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W ||
+
+ src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
+ src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
+ src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
+ src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W ||
+
+ dst->DstRegister.WriteMask != TGSI_WRITEMASK_XYZW)
+ {
+ tgsi_parse_free(&parse);
+ return FALSE;
+ }
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ /* fall-through */
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ /* fall-through */
+ default:
+ ; /* no-op */
+ }
+ }
+
+ tgsi_parse_free(&parse);
+
+ /* if we get here, it's a pass-through shader */
+ return TRUE;
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.h b/src/gallium/auxiliary/tgsi/tgsi_scan.h
new file mode 100644
index 0000000000..2c1a75bc81
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_SCAN_H
+#define TGSI_SCAN_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+
+
+/**
+ * Shader summary info
+ */
+struct tgsi_shader_info
+{
+ uint num_tokens;
+
+ ubyte num_inputs;
+ ubyte num_outputs;
+ ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; /**< TGSI_SEMANTIC_x */
+ ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
+ ubyte output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; /**< TGSI_SEMANTIC_x */
+ ubyte output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
+
+ uint file_mask[TGSI_FILE_COUNT]; /**< bitmask of declared registers */
+ uint file_count[TGSI_FILE_COUNT]; /**< number of declared registers */
+ int file_max[TGSI_FILE_COUNT]; /**< highest index of declared registers */
+
+ uint immediate_count; /**< number of immediates declared */
+
+ uint opcode_count[TGSI_OPCODE_LAST]; /**< opcode histogram */
+
+ boolean writes_z; /**< does fragment shader write Z value? */
+ boolean uses_kill; /**< KIL or KILP instruction used? */
+ boolean uses_fogcoord; /**< fragment shader uses fog coord? */
+ boolean uses_frontfacing; /**< fragment shader uses front/back-face flag? */
+};
+
+
+extern void
+tgsi_scan_shader(const struct tgsi_token *tokens,
+ struct tgsi_shader_info *info);
+
+
+extern boolean
+tgsi_is_passthrough_shader(const struct tgsi_token *tokens);
+
+
+#endif /* TGSI_SCAN_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
new file mode 100644
index 0000000000..3cdf8b9f35
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
@@ -0,0 +1,2985 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_ARCH_X86)
+
+#include "util/u_debug.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#if defined(PIPE_ARCH_SSE)
+#include "util/u_sse.h"
+#endif
+#include "tgsi/tgsi_info.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi_exec.h"
+#include "tgsi_sse2.h"
+
+#include "rtasm/rtasm_x86sse.h"
+
+/* for 1/sqrt()
+ *
+ * This costs about 100fps (close to 10%) in gears:
+ */
+#define HIGH_PRECISION 1
+
+#define FAST_MATH 1
+
+
+#define FOR_EACH_CHANNEL( CHAN )\
+ for (CHAN = 0; CHAN < NUM_CHANNELS; CHAN++)
+
+#define IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
+ ((INST).FullDstRegisters[0].DstRegister.WriteMask & (1 << (CHAN)))
+
+#define IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
+ if (IS_DST0_CHANNEL_ENABLED( INST, CHAN ))
+
+#define FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\
+ FOR_EACH_CHANNEL( CHAN )\
+ IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )
+
+#define CHAN_X 0
+#define CHAN_Y 1
+#define CHAN_Z 2
+#define CHAN_W 3
+
+#define TEMP_ONE_I TGSI_EXEC_TEMP_ONE_I
+#define TEMP_ONE_C TGSI_EXEC_TEMP_ONE_C
+
+#define TEMP_R0 TGSI_EXEC_TEMP_R0
+#define TEMP_ADDR TGSI_EXEC_TEMP_ADDR
+#define TEMP_EXEC_MASK_I TGSI_EXEC_MASK_I
+#define TEMP_EXEC_MASK_C TGSI_EXEC_MASK_C
+
+
+/**
+ * X86 utility functions.
+ */
+
+static struct x86_reg
+make_xmm(
+ unsigned xmm )
+{
+ return x86_make_reg(
+ file_XMM,
+ (enum x86_reg_name) xmm );
+}
+
+/**
+ * X86 register mapping helpers.
+ */
+
+static struct x86_reg
+get_const_base( void )
+{
+ return x86_make_reg(
+ file_REG32,
+ reg_AX );
+}
+
+static struct x86_reg
+get_machine_base( void )
+{
+ return x86_make_reg(
+ file_REG32,
+ reg_CX );
+}
+
+static struct x86_reg
+get_input_base( void )
+{
+ return x86_make_disp(
+ get_machine_base(),
+ Offset(struct tgsi_exec_machine, Inputs) );
+}
+
+static struct x86_reg
+get_output_base( void )
+{
+ return x86_make_disp(
+ get_machine_base(),
+ Offset(struct tgsi_exec_machine, Outputs) );
+}
+
+static struct x86_reg
+get_temp_base( void )
+{
+ return x86_make_disp(
+ get_machine_base(),
+ Offset(struct tgsi_exec_machine, Temps) );
+}
+
+static struct x86_reg
+get_coef_base( void )
+{
+ return x86_make_reg(
+ file_REG32,
+ reg_BX );
+}
+
+static struct x86_reg
+get_sampler_base( void )
+{
+ return x86_make_reg(
+ file_REG32,
+ reg_DI );
+}
+
+static struct x86_reg
+get_immediate_base( void )
+{
+ return x86_make_reg(
+ file_REG32,
+ reg_DX );
+}
+
+
+/**
+ * Data access helpers.
+ */
+
+
+static struct x86_reg
+get_immediate(
+ unsigned vec,
+ unsigned chan )
+{
+ return x86_make_disp(
+ get_immediate_base(),
+ (vec * 4 + chan) * 4 );
+}
+
+static struct x86_reg
+get_const(
+ unsigned vec,
+ unsigned chan )
+{
+ return x86_make_disp(
+ get_const_base(),
+ (vec * 4 + chan) * 4 );
+}
+
+static struct x86_reg
+get_sampler_ptr(
+ unsigned unit )
+{
+ return x86_make_disp(
+ get_sampler_base(),
+ unit * sizeof( struct tgsi_sampler * ) );
+}
+
+static struct x86_reg
+get_input(
+ unsigned vec,
+ unsigned chan )
+{
+ return x86_make_disp(
+ get_input_base(),
+ (vec * 4 + chan) * 16 );
+}
+
+static struct x86_reg
+get_output(
+ unsigned vec,
+ unsigned chan )
+{
+ return x86_make_disp(
+ get_output_base(),
+ (vec * 4 + chan) * 16 );
+}
+
+static struct x86_reg
+get_temp(
+ unsigned vec,
+ unsigned chan )
+{
+ return x86_make_disp(
+ get_temp_base(),
+ (vec * 4 + chan) * 16 );
+}
+
+static struct x86_reg
+get_coef(
+ unsigned vec,
+ unsigned chan,
+ unsigned member )
+{
+ return x86_make_disp(
+ get_coef_base(),
+ ((vec * 3 + member) * 4 + chan) * 4 );
+}
+
+
+static void
+emit_ret(
+ struct x86_function *func )
+{
+ x86_ret( func );
+}
+
+
+/**
+ * Data fetch helpers.
+ */
+
+/**
+ * Copy a shader constant to xmm register
+ * \param xmm the destination xmm register
+ * \param vec the src const buffer index
+ * \param chan src channel to fetch (X, Y, Z or W)
+ */
+static void
+emit_const(
+ struct x86_function *func,
+ uint xmm,
+ int vec,
+ uint chan,
+ uint indirect,
+ uint indirectFile,
+ int indirectIndex )
+{
+ if (indirect) {
+ /* 'vec' is the offset from the address register's value.
+ * We're loading CONST[ADDR+vec] into an xmm register.
+ */
+ struct x86_reg r0 = get_immediate_base();
+ struct x86_reg r1 = get_coef_base();
+ uint i;
+
+ assert( indirectFile == TGSI_FILE_ADDRESS );
+ assert( indirectIndex == 0 );
+ assert( r0.mod == mod_REG );
+ assert( r1.mod == mod_REG );
+
+ x86_push( func, r0 );
+ x86_push( func, r1 );
+
+ /*
+ * Loop over the four pixels or vertices in the quad.
+ * Get the value of the address (offset) register for pixel/vertex[i],
+ * add it to the src offset and index into the constant buffer.
+ * Note that we're working on SOA data.
+ * If any of the pixel/vertex execution channels are unused their
+ * values will be garbage. It's very important that we don't use
+ * those garbage values as indexes into the constant buffer since
+ * that'll cause segfaults.
+ * The solution is to bitwise-AND the offset with the execution mask
+ * register whose values are either 0 or ~0.
+ * The caller must setup the execution mask register to indicate
+ * which channels are valid/alive before running the shader.
+ * The execution mask will also figure into loops and conditionals
+ * someday.
+ */
+ for (i = 0; i < QUAD_SIZE; i++) {
+ /* r1 = address register[i] */
+ x86_mov( func, r1, x86_make_disp( get_temp( TEMP_ADDR, CHAN_X ), i * 4 ) );
+ /* r0 = execution mask[i] */
+ x86_mov( func, r0, x86_make_disp( get_temp( TEMP_EXEC_MASK_I, TEMP_EXEC_MASK_C ), i * 4 ) );
+ /* r1 = r1 & r0 */
+ x86_and( func, r1, r0 );
+ /* r0 = 'vec', the offset */
+ x86_lea( func, r0, get_const( vec, chan ) );
+
+ /* Quick hack to multiply r1 by 16 -- need to add SHL to rtasm.
+ */
+ x86_add( func, r1, r1 );
+ x86_add( func, r1, r1 );
+ x86_add( func, r1, r1 );
+ x86_add( func, r1, r1 );
+
+ x86_add( func, r0, r1 ); /* r0 = r0 + r1 */
+ x86_mov( func, r1, x86_deref( r0 ) );
+ x86_mov( func, x86_make_disp( get_temp( TEMP_R0, CHAN_X ), i * 4 ), r1 );
+ }
+
+ x86_pop( func, r1 );
+ x86_pop( func, r0 );
+
+ sse_movaps(
+ func,
+ make_xmm( xmm ),
+ get_temp( TEMP_R0, CHAN_X ) );
+ }
+ else {
+ /* 'vec' is the index into the src register file, such as TEMP[vec] */
+ assert( vec >= 0 );
+
+ sse_movss(
+ func,
+ make_xmm( xmm ),
+ get_const( vec, chan ) );
+ sse_shufps(
+ func,
+ make_xmm( xmm ),
+ make_xmm( xmm ),
+ SHUF( 0, 0, 0, 0 ) );
+ }
+}
+
+static void
+emit_immediate(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ sse_movss(
+ func,
+ make_xmm( xmm ),
+ get_immediate( vec, chan ) );
+ sse_shufps(
+ func,
+ make_xmm( xmm ),
+ make_xmm( xmm ),
+ SHUF( 0, 0, 0, 0 ) );
+}
+
+
+/**
+ * Copy a shader input to xmm register
+ * \param xmm the destination xmm register
+ * \param vec the src input attrib
+ * \param chan src channel to fetch (X, Y, Z or W)
+ */
+static void
+emit_inputf(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ sse_movups(
+ func,
+ make_xmm( xmm ),
+ get_input( vec, chan ) );
+}
+
+/**
+ * Store an xmm register to a shader output
+ * \param xmm the source xmm register
+ * \param vec the dest output attrib
+ * \param chan src dest channel to store (X, Y, Z or W)
+ */
+static void
+emit_output(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ sse_movups(
+ func,
+ get_output( vec, chan ),
+ make_xmm( xmm ) );
+}
+
+/**
+ * Copy a shader temporary to xmm register
+ * \param xmm the destination xmm register
+ * \param vec the src temp register
+ * \param chan src channel to fetch (X, Y, Z or W)
+ */
+static void
+emit_tempf(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ sse_movaps(
+ func,
+ make_xmm( xmm ),
+ get_temp( vec, chan ) );
+}
+
+/**
+ * Load an xmm register with an input attrib coefficient (a0, dadx or dady)
+ * \param xmm the destination xmm register
+ * \param vec the src input/attribute coefficient index
+ * \param chan src channel to fetch (X, Y, Z or W)
+ * \param member 0=a0, 1=dadx, 2=dady
+ */
+static void
+emit_coef(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan,
+ unsigned member )
+{
+ sse_movss(
+ func,
+ make_xmm( xmm ),
+ get_coef( vec, chan, member ) );
+ sse_shufps(
+ func,
+ make_xmm( xmm ),
+ make_xmm( xmm ),
+ SHUF( 0, 0, 0, 0 ) );
+}
+
+/**
+ * Data store helpers.
+ */
+
+static void
+emit_inputs(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ sse_movups(
+ func,
+ get_input( vec, chan ),
+ make_xmm( xmm ) );
+}
+
+static void
+emit_temps(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ sse_movaps(
+ func,
+ get_temp( vec, chan ),
+ make_xmm( xmm ) );
+}
+
+static void
+emit_addrs(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ assert( vec == 0 );
+
+ emit_temps(
+ func,
+ xmm,
+ vec + TGSI_EXEC_TEMP_ADDR,
+ chan );
+}
+
+/**
+ * Coefficent fetch helpers.
+ */
+
+static void
+emit_coef_a0(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ emit_coef(
+ func,
+ xmm,
+ vec,
+ chan,
+ 0 );
+}
+
+static void
+emit_coef_dadx(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ emit_coef(
+ func,
+ xmm,
+ vec,
+ chan,
+ 1 );
+}
+
+static void
+emit_coef_dady(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ emit_coef(
+ func,
+ xmm,
+ vec,
+ chan,
+ 2 );
+}
+
+/**
+ * Function call helpers.
+ */
+
+/**
+ * NOTE: In gcc, if the destination uses the SSE intrinsics, then it must be
+ * defined with __attribute__((force_align_arg_pointer)), as we do not guarantee
+ * that the stack pointer is 16 byte aligned, as expected.
+ */
+static void
+emit_func_call(
+ struct x86_function *func,
+ unsigned xmm_save_mask,
+ const struct x86_reg *arg,
+ unsigned nr_args,
+ void (PIPE_CDECL *code)() )
+{
+ struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX );
+ unsigned i, n;
+
+ x86_push(
+ func,
+ x86_make_reg( file_REG32, reg_AX) );
+ x86_push(
+ func,
+ x86_make_reg( file_REG32, reg_CX) );
+ x86_push(
+ func,
+ x86_make_reg( file_REG32, reg_DX) );
+
+ /* Store XMM regs to the stack
+ */
+ for(i = 0, n = 0; i < 8; ++i)
+ if(xmm_save_mask & (1 << i))
+ ++n;
+
+ x86_sub_imm(
+ func,
+ x86_make_reg( file_REG32, reg_SP ),
+ n*16);
+
+ for(i = 0, n = 0; i < 8; ++i)
+ if(xmm_save_mask & (1 << i)) {
+ sse_movups(
+ func,
+ x86_make_disp( x86_make_reg( file_REG32, reg_SP ), n*16 ),
+ make_xmm( i ) );
+ ++n;
+ }
+
+ for (i = 0; i < nr_args; i++) {
+ /* Load the address of the buffer we use for passing arguments and
+ * receiving results:
+ */
+ x86_lea(
+ func,
+ ecx,
+ arg[i] );
+
+ /* Push actual function arguments (currently just the pointer to
+ * the buffer above), and call the function:
+ */
+ x86_push( func, ecx );
+ }
+
+ x86_mov_reg_imm( func, ecx, (unsigned long) code );
+ x86_call( func, ecx );
+
+ /* Pop the arguments (or just add an immediate to esp)
+ */
+ for (i = 0; i < nr_args; i++) {
+ x86_pop(func, ecx );
+ }
+
+ /* Pop the saved XMM regs:
+ */
+ for(i = 0, n = 0; i < 8; ++i)
+ if(xmm_save_mask & (1 << i)) {
+ sse_movups(
+ func,
+ make_xmm( i ),
+ x86_make_disp( x86_make_reg( file_REG32, reg_SP ), n*16 ) );
+ ++n;
+ }
+
+ x86_add_imm(
+ func,
+ x86_make_reg( file_REG32, reg_SP ),
+ n*16);
+
+ /* Restore GP registers in a reverse order.
+ */
+ x86_pop(
+ func,
+ x86_make_reg( file_REG32, reg_DX) );
+ x86_pop(
+ func,
+ x86_make_reg( file_REG32, reg_CX) );
+ x86_pop(
+ func,
+ x86_make_reg( file_REG32, reg_AX) );
+}
+
+static void
+emit_func_call_dst_src1(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst,
+ unsigned xmm_src0,
+ void (PIPE_CDECL *code)() )
+{
+ struct x86_reg store = get_temp( TEMP_R0, 0 );
+ unsigned xmm_mask = ((1 << xmm_save) - 1) & ~(1 << xmm_dst);
+
+ /* Store our input parameters (in xmm regs) to the buffer we use
+ * for passing arguments. We will pass a pointer to this buffer as
+ * the actual function argument.
+ */
+ sse_movaps(
+ func,
+ store,
+ make_xmm( xmm_src0 ) );
+
+ emit_func_call( func,
+ xmm_mask,
+ &store,
+ 1,
+ code );
+
+ sse_movaps(
+ func,
+ make_xmm( xmm_dst ),
+ store );
+}
+
+
+static void
+emit_func_call_dst_src2(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst,
+ unsigned xmm_src0,
+ unsigned xmm_src1,
+ void (PIPE_CDECL *code)() )
+{
+ struct x86_reg store = get_temp( TEMP_R0, 0 );
+ unsigned xmm_mask = ((1 << xmm_save) - 1) & ~(1 << xmm_dst);
+
+ /* Store two inputs to parameter buffer.
+ */
+ sse_movaps(
+ func,
+ store,
+ make_xmm( xmm_src0 ) );
+
+ sse_movaps(
+ func,
+ x86_make_disp( store, 4 * sizeof(float) ),
+ make_xmm( xmm_src1 ) );
+
+
+ /* Emit the call
+ */
+ emit_func_call( func,
+ xmm_mask,
+ &store,
+ 1,
+ code );
+
+ /* Retrieve the results:
+ */
+ sse_movaps(
+ func,
+ make_xmm( xmm_dst ),
+ store );
+}
+
+
+
+
+
+#if defined(PIPE_ARCH_SSE)
+
+/*
+ * Fast SSE2 implementation of special math functions.
+ */
+
+#define POLY0(x, c0) _mm_set1_ps(c0)
+#define POLY1(x, c0, c1) _mm_add_ps(_mm_mul_ps(POLY0(x, c1), x), _mm_set1_ps(c0))
+#define POLY2(x, c0, c1, c2) _mm_add_ps(_mm_mul_ps(POLY1(x, c1, c2), x), _mm_set1_ps(c0))
+#define POLY3(x, c0, c1, c2, c3) _mm_add_ps(_mm_mul_ps(POLY2(x, c1, c2, c3), x), _mm_set1_ps(c0))
+#define POLY4(x, c0, c1, c2, c3, c4) _mm_add_ps(_mm_mul_ps(POLY3(x, c1, c2, c3, c4), x), _mm_set1_ps(c0))
+#define POLY5(x, c0, c1, c2, c3, c4, c5) _mm_add_ps(_mm_mul_ps(POLY4(x, c1, c2, c3, c4, c5), x), _mm_set1_ps(c0))
+
+#define EXP_POLY_DEGREE 3
+#define LOG_POLY_DEGREE 5
+
+/**
+ * See http://www.devmaster.net/forums/showthread.php?p=43580
+ */
+static INLINE __m128
+exp2f4(__m128 x)
+{
+ __m128i ipart;
+ __m128 fpart, expipart, expfpart;
+
+ x = _mm_min_ps(x, _mm_set1_ps( 129.00000f));
+ x = _mm_max_ps(x, _mm_set1_ps(-126.99999f));
+
+ /* ipart = int(x - 0.5) */
+ ipart = _mm_cvtps_epi32(_mm_sub_ps(x, _mm_set1_ps(0.5f)));
+
+ /* fpart = x - ipart */
+ fpart = _mm_sub_ps(x, _mm_cvtepi32_ps(ipart));
+
+ /* expipart = (float) (1 << ipart) */
+ expipart = _mm_castsi128_ps(_mm_slli_epi32(_mm_add_epi32(ipart, _mm_set1_epi32(127)), 23));
+
+ /* minimax polynomial fit of 2**x, in range [-0.5, 0.5[ */
+#if EXP_POLY_DEGREE == 5
+ expfpart = POLY5(fpart, 9.9999994e-1f, 6.9315308e-1f, 2.4015361e-1f, 5.5826318e-2f, 8.9893397e-3f, 1.8775767e-3f);
+#elif EXP_POLY_DEGREE == 4
+ expfpart = POLY4(fpart, 1.0000026f, 6.9300383e-1f, 2.4144275e-1f, 5.2011464e-2f, 1.3534167e-2f);
+#elif EXP_POLY_DEGREE == 3
+ expfpart = POLY3(fpart, 9.9992520e-1f, 6.9583356e-1f, 2.2606716e-1f, 7.8024521e-2f);
+#elif EXP_POLY_DEGREE == 2
+ expfpart = POLY2(fpart, 1.0017247f, 6.5763628e-1f, 3.3718944e-1f);
+#else
+#error
+#endif
+
+ return _mm_mul_ps(expipart, expfpart);
+}
+
+
+/**
+ * See http://www.devmaster.net/forums/showthread.php?p=43580
+ */
+static INLINE __m128
+log2f4(__m128 x)
+{
+ __m128i expmask = _mm_set1_epi32(0x7f800000);
+ __m128i mantmask = _mm_set1_epi32(0x007fffff);
+ __m128 one = _mm_set1_ps(1.0f);
+
+ __m128i i = _mm_castps_si128(x);
+
+ /* exp = (float) exponent(x) */
+ __m128 exp = _mm_cvtepi32_ps(_mm_sub_epi32(_mm_srli_epi32(_mm_and_si128(i, expmask), 23), _mm_set1_epi32(127)));
+
+ /* mant = (float) mantissa(x) */
+ __m128 mant = _mm_or_ps(_mm_castsi128_ps(_mm_and_si128(i, mantmask)), one);
+
+ __m128 logmant;
+
+ /* Minimax polynomial fit of log2(x)/(x - 1), for x in range [1, 2[
+ * These coefficients can be generate with
+ * http://www.boost.org/doc/libs/1_36_0/libs/math/doc/sf_and_dist/html/math_toolkit/toolkit/internals2/minimax.html
+ */
+#if LOG_POLY_DEGREE == 6
+ logmant = POLY5(mant, 3.11578814719469302614f, -3.32419399085241980044f, 2.59883907202499966007f, -1.23152682416275988241f, 0.318212422185251071475f, -0.0344359067839062357313f);
+#elif LOG_POLY_DEGREE == 5
+ logmant = POLY4(mant, 2.8882704548164776201f, -2.52074962577807006663f, 1.48116647521213171641f, -0.465725644288844778798f, 0.0596515482674574969533f);
+#elif LOG_POLY_DEGREE == 4
+ logmant = POLY3(mant, 2.61761038894603480148f, -1.75647175389045657003f, 0.688243882994381274313f, -0.107254423828329604454f);
+#elif LOG_POLY_DEGREE == 3
+ logmant = POLY2(mant, 2.28330284476918490682f, -1.04913055217340124191f, 0.204446009836232697516f);
+#else
+#error
+#endif
+
+ /* This effectively increases the polynomial degree by one, but ensures that log2(1) == 0*/
+ logmant = _mm_mul_ps(logmant, _mm_sub_ps(mant, one));
+
+ return _mm_add_ps(logmant, exp);
+}
+
+
+static INLINE __m128
+powf4(__m128 x, __m128 y)
+{
+ return exp2f4(_mm_mul_ps(log2f4(x), y));
+}
+
+#endif /* PIPE_ARCH_SSE */
+
+
+
+/**
+ * Low-level instruction translators.
+ */
+
+static void
+emit_abs(
+ struct x86_function *func,
+ unsigned xmm )
+{
+ sse_andps(
+ func,
+ make_xmm( xmm ),
+ get_temp(
+ TGSI_EXEC_TEMP_7FFFFFFF_I,
+ TGSI_EXEC_TEMP_7FFFFFFF_C ) );
+}
+
+static void
+emit_add(
+ struct x86_function *func,
+ unsigned xmm_dst,
+ unsigned xmm_src )
+{
+ sse_addps(
+ func,
+ make_xmm( xmm_dst ),
+ make_xmm( xmm_src ) );
+}
+
+static void PIPE_CDECL
+cos4f(
+ float *store )
+{
+ store[0] = cosf( store[0] );
+ store[1] = cosf( store[1] );
+ store[2] = cosf( store[2] );
+ store[3] = cosf( store[3] );
+}
+
+static void
+emit_cos(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst )
+{
+ emit_func_call_dst_src1(
+ func,
+ xmm_save,
+ xmm_dst,
+ xmm_dst,
+ cos4f );
+}
+
+static void PIPE_CDECL
+#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_SSE)
+__attribute__((force_align_arg_pointer))
+#endif
+ex24f(
+ float *store )
+{
+#if defined(PIPE_ARCH_SSE)
+ _mm_store_ps(&store[0], exp2f4( _mm_load_ps(&store[0]) ));
+#else
+ store[0] = util_fast_exp2( store[0] );
+ store[1] = util_fast_exp2( store[1] );
+ store[2] = util_fast_exp2( store[2] );
+ store[3] = util_fast_exp2( store[3] );
+#endif
+}
+
+static void
+emit_ex2(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst )
+{
+ emit_func_call_dst_src1(
+ func,
+ xmm_save,
+ xmm_dst,
+ xmm_dst,
+ ex24f );
+}
+
+static void
+emit_f2it(
+ struct x86_function *func,
+ unsigned xmm )
+{
+ sse2_cvttps2dq(
+ func,
+ make_xmm( xmm ),
+ make_xmm( xmm ) );
+}
+
+static void
+emit_i2f(
+ struct x86_function *func,
+ unsigned xmm )
+{
+ sse2_cvtdq2ps(
+ func,
+ make_xmm( xmm ),
+ make_xmm( xmm ) );
+}
+
+static void PIPE_CDECL
+flr4f(
+ float *store )
+{
+ store[0] = floorf( store[0] );
+ store[1] = floorf( store[1] );
+ store[2] = floorf( store[2] );
+ store[3] = floorf( store[3] );
+}
+
+static void
+emit_flr(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst )
+{
+ emit_func_call_dst_src1(
+ func,
+ xmm_save,
+ xmm_dst,
+ xmm_dst,
+ flr4f );
+}
+
+static void PIPE_CDECL
+frc4f(
+ float *store )
+{
+ store[0] -= floorf( store[0] );
+ store[1] -= floorf( store[1] );
+ store[2] -= floorf( store[2] );
+ store[3] -= floorf( store[3] );
+}
+
+static void
+emit_frc(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst )
+{
+ emit_func_call_dst_src1(
+ func,
+ xmm_save,
+ xmm_dst,
+ xmm_dst,
+ frc4f );
+}
+
+static void PIPE_CDECL
+#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_SSE)
+__attribute__((force_align_arg_pointer))
+#endif
+lg24f(
+ float *store )
+{
+#if defined(PIPE_ARCH_SSE)
+ _mm_store_ps(&store[0], log2f4( _mm_load_ps(&store[0]) ));
+#else
+ store[0] = util_fast_log2( store[0] );
+ store[1] = util_fast_log2( store[1] );
+ store[2] = util_fast_log2( store[2] );
+ store[3] = util_fast_log2( store[3] );
+#endif
+}
+
+static void
+emit_lg2(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst )
+{
+ emit_func_call_dst_src1(
+ func,
+ xmm_save,
+ xmm_dst,
+ xmm_dst,
+ lg24f );
+}
+
+static void
+emit_MOV(
+ struct x86_function *func,
+ unsigned xmm_dst,
+ unsigned xmm_src )
+{
+ sse_movups(
+ func,
+ make_xmm( xmm_dst ),
+ make_xmm( xmm_src ) );
+}
+
+static void
+emit_mul (struct x86_function *func,
+ unsigned xmm_dst,
+ unsigned xmm_src)
+{
+ sse_mulps(
+ func,
+ make_xmm( xmm_dst ),
+ make_xmm( xmm_src ) );
+}
+
+static void
+emit_neg(
+ struct x86_function *func,
+ unsigned xmm )
+{
+ sse_xorps(
+ func,
+ make_xmm( xmm ),
+ get_temp(
+ TGSI_EXEC_TEMP_80000000_I,
+ TGSI_EXEC_TEMP_80000000_C ) );
+}
+
+static void PIPE_CDECL
+#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_SSE)
+__attribute__((force_align_arg_pointer))
+#endif
+pow4f(
+ float *store )
+{
+#if defined(PIPE_ARCH_SSE)
+ _mm_store_ps(&store[0], powf4( _mm_load_ps(&store[0]), _mm_load_ps(&store[4]) ));
+#else
+ store[0] = util_fast_pow( store[0], store[4] );
+ store[1] = util_fast_pow( store[1], store[5] );
+ store[2] = util_fast_pow( store[2], store[6] );
+ store[3] = util_fast_pow( store[3], store[7] );
+#endif
+}
+
+static void
+emit_pow(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst,
+ unsigned xmm_src0,
+ unsigned xmm_src1 )
+{
+ emit_func_call_dst_src2(
+ func,
+ xmm_save,
+ xmm_dst,
+ xmm_src0,
+ xmm_src1,
+ pow4f );
+}
+
+static void
+emit_rcp (
+ struct x86_function *func,
+ unsigned xmm_dst,
+ unsigned xmm_src )
+{
+ /* On Intel CPUs at least, this is only accurate to 12 bits -- not
+ * good enough. Need to either emit a proper divide or use the
+ * iterative technique described below in emit_rsqrt().
+ */
+ sse2_rcpps(
+ func,
+ make_xmm( xmm_dst ),
+ make_xmm( xmm_src ) );
+}
+
+static void PIPE_CDECL
+rnd4f(
+ float *store )
+{
+ store[0] = floorf( store[0] + 0.5f );
+ store[1] = floorf( store[1] + 0.5f );
+ store[2] = floorf( store[2] + 0.5f );
+ store[3] = floorf( store[3] + 0.5f );
+}
+
+static void
+emit_rnd(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst )
+{
+ emit_func_call_dst_src1(
+ func,
+ xmm_save,
+ xmm_dst,
+ xmm_dst,
+ rnd4f );
+}
+
+static void
+emit_rsqrt(
+ struct x86_function *func,
+ unsigned xmm_dst,
+ unsigned xmm_src )
+{
+#if HIGH_PRECISION
+ /* Although rsqrtps() and rcpps() are low precision on some/all SSE
+ * implementations, it is possible to improve its precision at
+ * fairly low cost, using a newton/raphson step, as below:
+ *
+ * x1 = 2 * rcpps(a) - a * rcpps(a) * rcpps(a)
+ * x1 = 0.5 * rsqrtps(a) * [3.0 - (a * rsqrtps(a))* rsqrtps(a)]
+ *
+ * See: http://softwarecommunity.intel.com/articles/eng/1818.htm
+ */
+ {
+ struct x86_reg dst = make_xmm( xmm_dst );
+ struct x86_reg src = make_xmm( xmm_src );
+ struct x86_reg tmp0 = make_xmm( 2 );
+ struct x86_reg tmp1 = make_xmm( 3 );
+
+ assert( xmm_dst != xmm_src );
+ assert( xmm_dst != 2 && xmm_dst != 3 );
+ assert( xmm_src != 2 && xmm_src != 3 );
+
+ sse_movaps( func, dst, get_temp( TGSI_EXEC_TEMP_HALF_I, TGSI_EXEC_TEMP_HALF_C ) );
+ sse_movaps( func, tmp0, get_temp( TGSI_EXEC_TEMP_THREE_I, TGSI_EXEC_TEMP_THREE_C ) );
+ sse_rsqrtps( func, tmp1, src );
+ sse_mulps( func, src, tmp1 );
+ sse_mulps( func, dst, tmp1 );
+ sse_mulps( func, src, tmp1 );
+ sse_subps( func, tmp0, src );
+ sse_mulps( func, dst, tmp0 );
+ }
+#else
+ /* On Intel CPUs at least, this is only accurate to 12 bits -- not
+ * good enough.
+ */
+ sse_rsqrtps(
+ func,
+ make_xmm( xmm_dst ),
+ make_xmm( xmm_src ) );
+#endif
+}
+
+static void
+emit_setsign(
+ struct x86_function *func,
+ unsigned xmm )
+{
+ sse_orps(
+ func,
+ make_xmm( xmm ),
+ get_temp(
+ TGSI_EXEC_TEMP_80000000_I,
+ TGSI_EXEC_TEMP_80000000_C ) );
+}
+
+static void PIPE_CDECL
+sgn4f(
+ float *store )
+{
+ store[0] = store[0] < 0.0f ? -1.0f : store[0] > 0.0f ? 1.0f : 0.0f;
+ store[1] = store[1] < 0.0f ? -1.0f : store[1] > 0.0f ? 1.0f : 0.0f;
+ store[2] = store[2] < 0.0f ? -1.0f : store[2] > 0.0f ? 1.0f : 0.0f;
+ store[3] = store[3] < 0.0f ? -1.0f : store[3] > 0.0f ? 1.0f : 0.0f;
+}
+
+static void
+emit_sgn(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst )
+{
+ emit_func_call_dst_src1(
+ func,
+ xmm_save,
+ xmm_dst,
+ xmm_dst,
+ sgn4f );
+}
+
+static void PIPE_CDECL
+sin4f(
+ float *store )
+{
+ store[0] = sinf( store[0] );
+ store[1] = sinf( store[1] );
+ store[2] = sinf( store[2] );
+ store[3] = sinf( store[3] );
+}
+
+static void
+emit_sin (struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst)
+{
+ emit_func_call_dst_src1(
+ func,
+ xmm_save,
+ xmm_dst,
+ xmm_dst,
+ sin4f );
+}
+
+static void
+emit_sub(
+ struct x86_function *func,
+ unsigned xmm_dst,
+ unsigned xmm_src )
+{
+ sse_subps(
+ func,
+ make_xmm( xmm_dst ),
+ make_xmm( xmm_src ) );
+}
+
+
+
+
+
+
+
+/**
+ * Register fetch.
+ */
+
+static void
+emit_fetch(
+ struct x86_function *func,
+ unsigned xmm,
+ const struct tgsi_full_src_register *reg,
+ const unsigned chan_index )
+{
+ unsigned swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index );
+
+ switch (swizzle) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ switch (reg->SrcRegister.File) {
+ case TGSI_FILE_CONSTANT:
+ emit_const(
+ func,
+ xmm,
+ reg->SrcRegister.Index,
+ swizzle,
+ reg->SrcRegister.Indirect,
+ reg->SrcRegisterInd.File,
+ reg->SrcRegisterInd.Index );
+ break;
+
+ case TGSI_FILE_IMMEDIATE:
+ emit_immediate(
+ func,
+ xmm,
+ reg->SrcRegister.Index,
+ swizzle );
+ break;
+
+ case TGSI_FILE_INPUT:
+ emit_inputf(
+ func,
+ xmm,
+ reg->SrcRegister.Index,
+ swizzle );
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ emit_tempf(
+ func,
+ xmm,
+ reg->SrcRegister.Index,
+ swizzle );
+ break;
+
+ default:
+ assert( 0 );
+ }
+ break;
+
+ case TGSI_EXTSWIZZLE_ZERO:
+ emit_tempf(
+ func,
+ xmm,
+ TGSI_EXEC_TEMP_00000000_I,
+ TGSI_EXEC_TEMP_00000000_C );
+ break;
+
+ case TGSI_EXTSWIZZLE_ONE:
+ emit_tempf(
+ func,
+ xmm,
+ TEMP_ONE_I,
+ TEMP_ONE_C );
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ switch( tgsi_util_get_full_src_register_sign_mode( reg, chan_index ) ) {
+ case TGSI_UTIL_SIGN_CLEAR:
+ emit_abs( func, xmm );
+ break;
+
+ case TGSI_UTIL_SIGN_SET:
+ emit_setsign( func, xmm );
+ break;
+
+ case TGSI_UTIL_SIGN_TOGGLE:
+ emit_neg( func, xmm );
+ break;
+
+ case TGSI_UTIL_SIGN_KEEP:
+ break;
+ }
+}
+
+#define FETCH( FUNC, INST, XMM, INDEX, CHAN )\
+ emit_fetch( FUNC, XMM, &(INST).FullSrcRegisters[INDEX], CHAN )
+
+/**
+ * Register store.
+ */
+
+static void
+emit_store(
+ struct x86_function *func,
+ unsigned xmm,
+ const struct tgsi_full_dst_register *reg,
+ const struct tgsi_full_instruction *inst,
+ unsigned chan_index )
+{
+ switch( reg->DstRegister.File ) {
+ case TGSI_FILE_OUTPUT:
+ emit_output(
+ func,
+ xmm,
+ reg->DstRegister.Index,
+ chan_index );
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ emit_temps(
+ func,
+ xmm,
+ reg->DstRegister.Index,
+ chan_index );
+ break;
+
+ case TGSI_FILE_ADDRESS:
+ emit_addrs(
+ func,
+ xmm,
+ reg->DstRegister.Index,
+ chan_index );
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ switch( inst->Instruction.Saturate ) {
+ case TGSI_SAT_NONE:
+ break;
+
+ case TGSI_SAT_ZERO_ONE:
+ /* assert( 0 ); */
+ break;
+
+ case TGSI_SAT_MINUS_PLUS_ONE:
+ assert( 0 );
+ break;
+ }
+}
+
+#define STORE( FUNC, INST, XMM, INDEX, CHAN )\
+ emit_store( FUNC, XMM, &(INST).FullDstRegisters[INDEX], &(INST), CHAN )
+
+
+static void PIPE_CDECL
+fetch_texel( struct tgsi_sampler **sampler,
+ float *store )
+{
+#if 0
+ uint j;
+
+ debug_printf("%s sampler: %p (%p) store: %p\n",
+ __FUNCTION__,
+ sampler, *sampler,
+ store );
+
+ debug_printf("lodbias %f\n", store[12]);
+
+ for (j = 0; j < 4; j++)
+ debug_printf("sample %d texcoord %f %f\n",
+ j,
+ store[0+j],
+ store[4+j]);
+#endif
+
+ {
+ float rgba[NUM_CHANNELS][QUAD_SIZE];
+ (*sampler)->get_samples(*sampler,
+ &store[0],
+ &store[4],
+ &store[8],
+ 0.0f, /*store[12], lodbias */
+ rgba);
+
+ memcpy( store, rgba, 16 * sizeof(float));
+ }
+
+#if 0
+ for (j = 0; j < 4; j++)
+ debug_printf("sample %d result %f %f %f %f\n",
+ j,
+ store[0+j],
+ store[4+j],
+ store[8+j],
+ store[12+j]);
+#endif
+}
+
+/**
+ * High-level instruction translators.
+ */
+
+static void
+emit_tex( struct x86_function *func,
+ const struct tgsi_full_instruction *inst,
+ boolean lodbias,
+ boolean projected)
+{
+ const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
+ struct x86_reg args[2];
+ unsigned count;
+ unsigned i;
+
+ switch (inst->InstructionExtTexture.Texture) {
+ case TGSI_TEXTURE_1D:
+ count = 1;
+ break;
+ case TGSI_TEXTURE_2D:
+ case TGSI_TEXTURE_RECT:
+ count = 2;
+ break;
+ case TGSI_TEXTURE_SHADOW1D:
+ case TGSI_TEXTURE_SHADOW2D:
+ case TGSI_TEXTURE_SHADOWRECT:
+ case TGSI_TEXTURE_3D:
+ case TGSI_TEXTURE_CUBE:
+ count = 3;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ if (lodbias) {
+ FETCH( func, *inst, 3, 0, 3 );
+ }
+ else {
+ emit_tempf(
+ func,
+ 3,
+ TGSI_EXEC_TEMP_00000000_I,
+ TGSI_EXEC_TEMP_00000000_C );
+
+ }
+
+ /* store lodbias whether enabled or not -- fetch_texel currently
+ * respects it always.
+ */
+ sse_movaps( func,
+ get_temp( TEMP_R0, 3 ),
+ make_xmm( 3 ) );
+
+
+ if (projected) {
+ FETCH( func, *inst, 3, 0, 3 );
+
+ emit_rcp( func, 3, 3 );
+ }
+
+ for (i = 0; i < count; i++) {
+ FETCH( func, *inst, i, 0, i );
+
+ if (projected) {
+ sse_mulps(
+ func,
+ make_xmm( i ),
+ make_xmm( 3 ) );
+ }
+
+ /* Store in the argument buffer:
+ */
+ sse_movaps(
+ func,
+ get_temp( TEMP_R0, i ),
+ make_xmm( i ) );
+ }
+
+ args[0] = get_temp( TEMP_R0, 0 );
+ args[1] = get_sampler_ptr( unit );
+
+
+ emit_func_call( func,
+ 0,
+ args,
+ Elements(args),
+ fetch_texel );
+
+ /* If all four channels are enabled, could use a pointer to
+ * dst[0].x instead of TEMP_R0 for store?
+ */
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, i ) {
+
+ sse_movaps(
+ func,
+ make_xmm( 0 ),
+ get_temp( TEMP_R0, i ) );
+
+ STORE( func, *inst, 0, 0, i );
+ }
+}
+
+
+static void
+emit_kil(
+ struct x86_function *func,
+ const struct tgsi_full_src_register *reg )
+{
+ unsigned uniquemask;
+ unsigned unique_count = 0;
+ unsigned chan_index;
+ unsigned i;
+
+ /* This mask stores component bits that were already tested. Note that
+ * we test if the value is less than zero, so 1.0 and 0.0 need not to be
+ * tested. */
+ uniquemask = (1 << TGSI_EXTSWIZZLE_ZERO) | (1 << TGSI_EXTSWIZZLE_ONE);
+
+ FOR_EACH_CHANNEL( chan_index ) {
+ unsigned swizzle;
+
+ /* unswizzle channel */
+ swizzle = tgsi_util_get_full_src_register_extswizzle(
+ reg,
+ chan_index );
+
+ /* check if the component has not been already tested */
+ if( !(uniquemask & (1 << swizzle)) ) {
+ uniquemask |= 1 << swizzle;
+
+ /* allocate register */
+ emit_fetch(
+ func,
+ unique_count++,
+ reg,
+ chan_index );
+ }
+ }
+
+ x86_push(
+ func,
+ x86_make_reg( file_REG32, reg_AX ) );
+ x86_push(
+ func,
+ x86_make_reg( file_REG32, reg_DX ) );
+
+ for (i = 0 ; i < unique_count; i++ ) {
+ struct x86_reg dataXMM = make_xmm(i);
+
+ sse_cmpps(
+ func,
+ dataXMM,
+ get_temp(
+ TGSI_EXEC_TEMP_00000000_I,
+ TGSI_EXEC_TEMP_00000000_C ),
+ cc_LessThan );
+
+ if( i == 0 ) {
+ sse_movmskps(
+ func,
+ x86_make_reg( file_REG32, reg_AX ),
+ dataXMM );
+ }
+ else {
+ sse_movmskps(
+ func,
+ x86_make_reg( file_REG32, reg_DX ),
+ dataXMM );
+ x86_or(
+ func,
+ x86_make_reg( file_REG32, reg_AX ),
+ x86_make_reg( file_REG32, reg_DX ) );
+ }
+ }
+
+ x86_or(
+ func,
+ get_temp(
+ TGSI_EXEC_TEMP_KILMASK_I,
+ TGSI_EXEC_TEMP_KILMASK_C ),
+ x86_make_reg( file_REG32, reg_AX ) );
+
+ x86_pop(
+ func,
+ x86_make_reg( file_REG32, reg_DX ) );
+ x86_pop(
+ func,
+ x86_make_reg( file_REG32, reg_AX ) );
+}
+
+
+static void
+emit_kilp(
+ struct x86_function *func )
+{
+ /* XXX todo / fix me */
+}
+
+
+static void
+emit_setcc(
+ struct x86_function *func,
+ struct tgsi_full_instruction *inst,
+ enum sse_cc cc )
+{
+ unsigned chan_index;
+
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ FETCH( func, *inst, 1, 1, chan_index );
+ sse_cmpps(
+ func,
+ make_xmm( 0 ),
+ make_xmm( 1 ),
+ cc );
+ sse_andps(
+ func,
+ make_xmm( 0 ),
+ get_temp(
+ TEMP_ONE_I,
+ TEMP_ONE_C ) );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+}
+
+static void
+emit_cmp(
+ struct x86_function *func,
+ struct tgsi_full_instruction *inst )
+{
+ unsigned chan_index;
+
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ FETCH( func, *inst, 1, 1, chan_index );
+ FETCH( func, *inst, 2, 2, chan_index );
+ sse_cmpps(
+ func,
+ make_xmm( 0 ),
+ get_temp(
+ TGSI_EXEC_TEMP_00000000_I,
+ TGSI_EXEC_TEMP_00000000_C ),
+ cc_LessThan );
+ sse_andps(
+ func,
+ make_xmm( 1 ),
+ make_xmm( 0 ) );
+ sse_andnps(
+ func,
+ make_xmm( 0 ),
+ make_xmm( 2 ) );
+ sse_orps(
+ func,
+ make_xmm( 0 ),
+ make_xmm( 1 ) );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+}
+
+
+/**
+ * Check if inst src/dest regs use indirect addressing into temporary
+ * register file.
+ */
+static boolean
+indirect_temp_reference(const struct tgsi_full_instruction *inst)
+{
+ uint i;
+ for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *reg = &inst->FullSrcRegisters[i];
+ if (reg->SrcRegister.File == TGSI_FILE_TEMPORARY &&
+ reg->SrcRegister.Indirect)
+ return TRUE;
+ }
+ for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
+ const struct tgsi_full_dst_register *reg = &inst->FullDstRegisters[i];
+ if (reg->DstRegister.File == TGSI_FILE_TEMPORARY &&
+ reg->DstRegister.Indirect)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static int
+emit_instruction(
+ struct x86_function *func,
+ struct tgsi_full_instruction *inst )
+{
+ unsigned chan_index;
+
+ /* we can't handle indirect addressing into temp register file yet */
+ if (indirect_temp_reference(inst))
+ return FALSE;
+
+ /* we don't handle saturation/clamping yet */
+ if (inst->Instruction.Saturate != TGSI_SAT_NONE)
+ return FALSE;
+
+ /* need to use extra temps to fix SOA dependencies : */
+ if (tgsi_check_soa_dependencies(inst))
+ return FALSE;
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ARL:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ emit_flr(func, 0, 0);
+ emit_f2it( func, 0 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_LIT:
+ if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W ) ) {
+ emit_tempf(
+ func,
+ 0,
+ TEMP_ONE_I,
+ TEMP_ONE_C);
+ if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ) {
+ STORE( func, *inst, 0, 0, CHAN_X );
+ }
+ if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W ) ) {
+ STORE( func, *inst, 0, 0, CHAN_W );
+ }
+ }
+ if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
+ if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ sse_maxps(
+ func,
+ make_xmm( 0 ),
+ get_temp(
+ TGSI_EXEC_TEMP_00000000_I,
+ TGSI_EXEC_TEMP_00000000_C ) );
+ STORE( func, *inst, 0, 0, CHAN_Y );
+ }
+ if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
+ /* XMM[1] = SrcReg[0].yyyy */
+ FETCH( func, *inst, 1, 0, CHAN_Y );
+ /* XMM[1] = max(XMM[1], 0) */
+ sse_maxps(
+ func,
+ make_xmm( 1 ),
+ get_temp(
+ TGSI_EXEC_TEMP_00000000_I,
+ TGSI_EXEC_TEMP_00000000_C ) );
+ /* XMM[2] = SrcReg[0].wwww */
+ FETCH( func, *inst, 2, 0, CHAN_W );
+ /* XMM[2] = min(XMM[2], 128.0) */
+ sse_minps(
+ func,
+ make_xmm( 2 ),
+ get_temp(
+ TGSI_EXEC_TEMP_128_I,
+ TGSI_EXEC_TEMP_128_C ) );
+ /* XMM[2] = max(XMM[2], -128.0) */
+ sse_maxps(
+ func,
+ make_xmm( 2 ),
+ get_temp(
+ TGSI_EXEC_TEMP_MINUS_128_I,
+ TGSI_EXEC_TEMP_MINUS_128_C ) );
+ emit_pow( func, 3, 1, 1, 2 );
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ sse_xorps(
+ func,
+ make_xmm( 2 ),
+ make_xmm( 2 ) );
+ sse_cmpps(
+ func,
+ make_xmm( 2 ),
+ make_xmm( 0 ),
+ cc_LessThan );
+ sse_andps(
+ func,
+ make_xmm( 2 ),
+ make_xmm( 1 ) );
+ STORE( func, *inst, 2, 0, CHAN_Z );
+ }
+ }
+ break;
+
+ case TGSI_OPCODE_RCP:
+ /* TGSI_OPCODE_RECIP */
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ emit_rcp( func, 0, 0 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_RSQ:
+ /* TGSI_OPCODE_RECIPSQRT */
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ emit_abs( func, 0 );
+ emit_rsqrt( func, 1, 0 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 1, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_EXP:
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ emit_MOV( func, 1, 0 );
+ emit_flr( func, 2, 1 );
+ /* dst.x = ex2(floor(src.x)) */
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ emit_MOV( func, 2, 1 );
+ emit_ex2( func, 3, 2 );
+ STORE( func, *inst, 2, 0, CHAN_X );
+ }
+ /* dst.y = src.x - floor(src.x) */
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ emit_MOV( func, 2, 0 );
+ emit_sub( func, 2, 1 );
+ STORE( func, *inst, 2, 0, CHAN_Y );
+ }
+ }
+ /* dst.z = ex2(src.x) */
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ emit_ex2( func, 3, 0 );
+ STORE( func, *inst, 0, 0, CHAN_Z );
+ }
+ }
+ /* dst.w = 1.0 */
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ emit_tempf( func, 0, TEMP_ONE_I, TEMP_ONE_C );
+ STORE( func, *inst, 0, 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_LOG:
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ emit_abs( func, 0 );
+ emit_MOV( func, 1, 0 );
+ emit_lg2( func, 2, 1 );
+ /* dst.z = lg2(abs(src.x)) */
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ STORE( func, *inst, 1, 0, CHAN_Z );
+ }
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ emit_flr( func, 2, 1 );
+ /* dst.x = floor(lg2(abs(src.x))) */
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ STORE( func, *inst, 1, 0, CHAN_X );
+ }
+ /* dst.x = abs(src)/ex2(floor(lg2(abs(src.x)))) */
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ emit_ex2( func, 2, 1 );
+ emit_rcp( func, 1, 1 );
+ emit_mul( func, 0, 1 );
+ STORE( func, *inst, 0, 0, CHAN_Y );
+ }
+ }
+ }
+ /* dst.w = 1.0 */
+ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ emit_tempf( func, 0, TEMP_ONE_I, TEMP_ONE_C );
+ STORE( func, *inst, 0, 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_MUL:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ FETCH( func, *inst, 1, 1, chan_index );
+ emit_mul( func, 0, 1 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_ADD:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ FETCH( func, *inst, 1, 1, chan_index );
+ emit_add( func, 0, 1 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DP3:
+ /* TGSI_OPCODE_DOT3 */
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ FETCH( func, *inst, 1, 1, CHAN_X );
+ emit_mul( func, 0, 1 );
+ FETCH( func, *inst, 1, 0, CHAN_Y );
+ FETCH( func, *inst, 2, 1, CHAN_Y );
+ emit_mul( func, 1, 2 );
+ emit_add( func, 0, 1 );
+ FETCH( func, *inst, 1, 0, CHAN_Z );
+ FETCH( func, *inst, 2, 1, CHAN_Z );
+ emit_mul( func, 1, 2 );
+ emit_add( func, 0, 1 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DP4:
+ /* TGSI_OPCODE_DOT4 */
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ FETCH( func, *inst, 1, 1, CHAN_X );
+ emit_mul( func, 0, 1 );
+ FETCH( func, *inst, 1, 0, CHAN_Y );
+ FETCH( func, *inst, 2, 1, CHAN_Y );
+ emit_mul( func, 1, 2 );
+ emit_add( func, 0, 1 );
+ FETCH( func, *inst, 1, 0, CHAN_Z );
+ FETCH( func, *inst, 2, 1, CHAN_Z );
+ emit_mul(func, 1, 2 );
+ emit_add(func, 0, 1 );
+ FETCH( func, *inst, 1, 0, CHAN_W );
+ FETCH( func, *inst, 2, 1, CHAN_W );
+ emit_mul( func, 1, 2 );
+ emit_add( func, 0, 1 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DST:
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) {
+ emit_tempf(
+ func,
+ 0,
+ TEMP_ONE_I,
+ TEMP_ONE_C );
+ STORE( func, *inst, 0, 0, CHAN_X );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) {
+ FETCH( func, *inst, 0, 0, CHAN_Y );
+ FETCH( func, *inst, 1, 1, CHAN_Y );
+ emit_mul( func, 0, 1 );
+ STORE( func, *inst, 0, 0, CHAN_Y );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) {
+ FETCH( func, *inst, 0, 0, CHAN_Z );
+ STORE( func, *inst, 0, 0, CHAN_Z );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W ) {
+ FETCH( func, *inst, 0, 1, CHAN_W );
+ STORE( func, *inst, 0, 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_MIN:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ FETCH( func, *inst, 1, 1, chan_index );
+ sse_minps(
+ func,
+ make_xmm( 0 ),
+ make_xmm( 1 ) );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_MAX:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ FETCH( func, *inst, 1, 1, chan_index );
+ sse_maxps(
+ func,
+ make_xmm( 0 ),
+ make_xmm( 1 ) );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SLT:
+ /* TGSI_OPCODE_SETLT */
+ emit_setcc( func, inst, cc_LessThan );
+ break;
+
+ case TGSI_OPCODE_SGE:
+ /* TGSI_OPCODE_SETGE */
+ emit_setcc( func, inst, cc_NotLessThan );
+ break;
+
+ case TGSI_OPCODE_MAD:
+ /* TGSI_OPCODE_MADD */
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ FETCH( func, *inst, 1, 1, chan_index );
+ FETCH( func, *inst, 2, 2, chan_index );
+ emit_mul( func, 0, 1 );
+ emit_add( func, 0, 2 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SUB:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ FETCH( func, *inst, 1, 1, chan_index );
+ emit_sub( func, 0, 1 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_LRP:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ FETCH( func, *inst, 1, 1, chan_index );
+ FETCH( func, *inst, 2, 2, chan_index );
+ emit_sub( func, 1, 2 );
+ emit_mul( func, 0, 1 );
+ emit_add( func, 0, 2 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_CND:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_DP2A:
+ FETCH( func, *inst, 0, 0, CHAN_X ); /* xmm0 = src[0].x */
+ FETCH( func, *inst, 1, 1, CHAN_X ); /* xmm1 = src[1].x */
+ emit_mul( func, 0, 1 ); /* xmm0 = xmm0 * xmm1 */
+ FETCH( func, *inst, 1, 0, CHAN_Y ); /* xmm1 = src[0].y */
+ FETCH( func, *inst, 2, 1, CHAN_Y ); /* xmm2 = src[1].y */
+ emit_mul( func, 1, 2 ); /* xmm1 = xmm1 * xmm2 */
+ emit_add( func, 0, 1 ); /* xmm0 = xmm0 + xmm1 */
+ FETCH( func, *inst, 1, 2, CHAN_X ); /* xmm1 = src[2].x */
+ emit_add( func, 0, 1 ); /* xmm0 = xmm0 + xmm1 */
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index ); /* dest[ch] = xmm0 */
+ }
+ break;
+
+ case TGSI_OPCODE_FRC:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ emit_frc( func, 0, 0 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_CLAMP:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_FLR:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ emit_flr( func, 0, 0 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_ROUND:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ emit_rnd( func, 0, 0 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_EX2:
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ emit_ex2( func, 0, 0 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_LG2:
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ emit_lg2( func, 0, 0 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_POW:
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ FETCH( func, *inst, 1, 1, CHAN_X );
+ emit_pow( func, 0, 0, 0, 1 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_XPD:
+ if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
+ FETCH( func, *inst, 1, 1, CHAN_Z );
+ FETCH( func, *inst, 3, 0, CHAN_Z );
+ }
+ if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
+ FETCH( func, *inst, 0, 0, CHAN_Y );
+ FETCH( func, *inst, 4, 1, CHAN_Y );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) {
+ emit_MOV( func, 2, 0 );
+ emit_mul( func, 2, 1 );
+ emit_MOV( func, 5, 3 );
+ emit_mul( func, 5, 4 );
+ emit_sub( func, 2, 5 );
+ STORE( func, *inst, 2, 0, CHAN_X );
+ }
+ if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ||
+ IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
+ FETCH( func, *inst, 2, 1, CHAN_X );
+ FETCH( func, *inst, 5, 0, CHAN_X );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) {
+ emit_mul( func, 3, 2 );
+ emit_mul( func, 1, 5 );
+ emit_sub( func, 3, 1 );
+ STORE( func, *inst, 3, 0, CHAN_Y );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) {
+ emit_mul( func, 5, 4 );
+ emit_mul( func, 0, 2 );
+ emit_sub( func, 5, 0 );
+ STORE( func, *inst, 5, 0, CHAN_Z );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W ) {
+ emit_tempf(
+ func,
+ 0,
+ TEMP_ONE_I,
+ TEMP_ONE_C );
+ STORE( func, *inst, 0, 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_ABS:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ emit_abs( func, 0) ;
+
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_RCC:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_DPH:
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ FETCH( func, *inst, 1, 1, CHAN_X );
+ emit_mul( func, 0, 1 );
+ FETCH( func, *inst, 1, 0, CHAN_Y );
+ FETCH( func, *inst, 2, 1, CHAN_Y );
+ emit_mul( func, 1, 2 );
+ emit_add( func, 0, 1 );
+ FETCH( func, *inst, 1, 0, CHAN_Z );
+ FETCH( func, *inst, 2, 1, CHAN_Z );
+ emit_mul( func, 1, 2 );
+ emit_add( func, 0, 1 );
+ FETCH( func, *inst, 1, 1, CHAN_W );
+ emit_add( func, 0, 1 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_COS:
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ emit_cos( func, 0, 0 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DDX:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_DDY:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_KILP:
+ /* predicated kill */
+ emit_kilp( func );
+ return 0; /* XXX fix me */
+ break;
+
+ case TGSI_OPCODE_KIL:
+ /* conditional kill */
+ emit_kil( func, &inst->FullSrcRegisters[0] );
+ break;
+
+ case TGSI_OPCODE_PK2H:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_PK2US:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_PK4B:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_PK4UB:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_RFL:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SEQ:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SFL:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SGT:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SIN:
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ emit_sin( func, 0, 0 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SLE:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SNE:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_STR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_TEX:
+ emit_tex( func, inst, FALSE, FALSE );
+ break;
+
+ case TGSI_OPCODE_TXD:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_UP2H:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_UP2US:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_UP4B:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_UP4UB:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_X2D:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ARA:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ARR:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ emit_rnd( func, 0, 0 );
+ emit_f2it( func, 0 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_BRA:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_CAL:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_RET:
+ emit_ret( func );
+ break;
+
+ case TGSI_OPCODE_END:
+ break;
+
+ case TGSI_OPCODE_SSG:
+ /* TGSI_OPCODE_SGN */
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ emit_sgn( func, 0, 0 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_CMP:
+ emit_cmp (func, inst);
+ break;
+
+ case TGSI_OPCODE_SCS:
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) {
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ emit_cos( func, 0, 0 );
+ STORE( func, *inst, 0, 0, CHAN_X );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) {
+ FETCH( func, *inst, 0, 0, CHAN_X );
+ emit_sin( func, 0, 0 );
+ STORE( func, *inst, 0, 0, CHAN_Y );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) {
+ emit_tempf(
+ func,
+ 0,
+ TGSI_EXEC_TEMP_00000000_I,
+ TGSI_EXEC_TEMP_00000000_C );
+ STORE( func, *inst, 0, 0, CHAN_Z );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W ) {
+ emit_tempf(
+ func,
+ 0,
+ TEMP_ONE_I,
+ TEMP_ONE_C );
+ STORE( func, *inst, 0, 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_TXB:
+ emit_tex( func, inst, TRUE, FALSE );
+ break;
+
+ case TGSI_OPCODE_NRM:
+ /* fall-through */
+ case TGSI_OPCODE_NRM4:
+ /* 3 or 4-component normalization */
+ {
+ uint dims = (inst->Instruction.Opcode == TGSI_OPCODE_NRM) ? 3 : 4;
+
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X) ||
+ IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y) ||
+ IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z) ||
+ (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_W) && dims == 4)) {
+
+ /* NOTE: Cannot use xmm regs 2/3 here (see emit_rsqrt() above). */
+
+ /* xmm4 = src.x */
+ /* xmm0 = src.x * src.x */
+ FETCH(func, *inst, 0, 0, CHAN_X);
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X)) {
+ emit_MOV(func, 4, 0);
+ }
+ emit_mul(func, 0, 0);
+
+ /* xmm5 = src.y */
+ /* xmm0 = xmm0 + src.y * src.y */
+ FETCH(func, *inst, 1, 0, CHAN_Y);
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ emit_MOV(func, 5, 1);
+ }
+ emit_mul(func, 1, 1);
+ emit_add(func, 0, 1);
+
+ /* xmm6 = src.z */
+ /* xmm0 = xmm0 + src.z * src.z */
+ FETCH(func, *inst, 1, 0, CHAN_Z);
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ emit_MOV(func, 6, 1);
+ }
+ emit_mul(func, 1, 1);
+ emit_add(func, 0, 1);
+
+ if (dims == 4) {
+ /* xmm7 = src.w */
+ /* xmm0 = xmm0 + src.w * src.w */
+ FETCH(func, *inst, 1, 0, CHAN_W);
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_W)) {
+ emit_MOV(func, 7, 1);
+ }
+ emit_mul(func, 1, 1);
+ emit_add(func, 0, 1);
+ }
+
+ /* xmm1 = 1 / sqrt(xmm0) */
+ emit_rsqrt(func, 1, 0);
+
+ /* dst.x = xmm1 * src.x */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X)) {
+ emit_mul(func, 4, 1);
+ STORE(func, *inst, 4, 0, CHAN_X);
+ }
+
+ /* dst.y = xmm1 * src.y */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+ emit_mul(func, 5, 1);
+ STORE(func, *inst, 5, 0, CHAN_Y);
+ }
+
+ /* dst.z = xmm1 * src.z */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+ emit_mul(func, 6, 1);
+ STORE(func, *inst, 6, 0, CHAN_Z);
+ }
+
+ /* dst.w = xmm1 * src.w */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_X) && dims == 4) {
+ emit_mul(func, 7, 1);
+ STORE(func, *inst, 7, 0, CHAN_W);
+ }
+ }
+
+ /* dst0.w = 1.0 */
+ if (IS_DST0_CHANNEL_ENABLED(*inst, CHAN_W) && dims == 3) {
+ emit_tempf(func, 0, TEMP_ONE_I, TEMP_ONE_C);
+ STORE(func, *inst, 0, 0, CHAN_W);
+ }
+ }
+ break;
+
+ case TGSI_OPCODE_DIV:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_DP2:
+ FETCH( func, *inst, 0, 0, CHAN_X ); /* xmm0 = src[0].x */
+ FETCH( func, *inst, 1, 1, CHAN_X ); /* xmm1 = src[1].x */
+ emit_mul( func, 0, 1 ); /* xmm0 = xmm0 * xmm1 */
+ FETCH( func, *inst, 1, 0, CHAN_Y ); /* xmm1 = src[0].y */
+ FETCH( func, *inst, 2, 1, CHAN_Y ); /* xmm2 = src[1].y */
+ emit_mul( func, 1, 2 ); /* xmm1 = xmm1 * xmm2 */
+ emit_add( func, 0, 1 ); /* xmm0 = xmm0 + xmm1 */
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( func, *inst, 0, 0, chan_index ); /* dest[ch] = xmm0 */
+ }
+ break;
+
+ case TGSI_OPCODE_TXL:
+ emit_tex( func, inst, TRUE, FALSE );
+ break;
+
+ case TGSI_OPCODE_TXP:
+ emit_tex( func, inst, FALSE, TRUE );
+ break;
+
+ case TGSI_OPCODE_BRK:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_IF:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_BGNFOR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_REP:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ELSE:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ENDIF:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ENDFOR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ENDREP:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_PUSHA:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_POPA:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_CEIL:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_I2F:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_NOT:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_TRUNC:
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( func, *inst, 0, 0, chan_index );
+ emit_f2it( func, 0 );
+ emit_i2f( func, 0 );
+ STORE( func, *inst, 0, 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SHL:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SHR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_AND:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_OR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_MOD:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_XOR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SAD:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_TXF:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_TXQ:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_CONT:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_EMIT:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ENDPRIM:
+ return 0;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+emit_declaration(
+ struct x86_function *func,
+ struct tgsi_full_declaration *decl )
+{
+ if( decl->Declaration.File == TGSI_FILE_INPUT ) {
+ unsigned first, last, mask;
+ unsigned i, j;
+
+ first = decl->DeclarationRange.First;
+ last = decl->DeclarationRange.Last;
+ mask = decl->Declaration.UsageMask;
+
+ for( i = first; i <= last; i++ ) {
+ for( j = 0; j < NUM_CHANNELS; j++ ) {
+ if( mask & (1 << j) ) {
+ switch( decl->Declaration.Interpolate ) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ emit_coef_a0( func, 0, i, j );
+ emit_inputs( func, 0, i, j );
+ break;
+
+ case TGSI_INTERPOLATE_LINEAR:
+ emit_tempf( func, 0, 0, TGSI_SWIZZLE_X );
+ emit_coef_dadx( func, 1, i, j );
+ emit_tempf( func, 2, 0, TGSI_SWIZZLE_Y );
+ emit_coef_dady( func, 3, i, j );
+ emit_mul( func, 0, 1 ); /* x * dadx */
+ emit_coef_a0( func, 4, i, j );
+ emit_mul( func, 2, 3 ); /* y * dady */
+ emit_add( func, 0, 4 ); /* x * dadx + a0 */
+ emit_add( func, 0, 2 ); /* x * dadx + y * dady + a0 */
+ emit_inputs( func, 0, i, j );
+ break;
+
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ emit_tempf( func, 0, 0, TGSI_SWIZZLE_X );
+ emit_coef_dadx( func, 1, i, j );
+ emit_tempf( func, 2, 0, TGSI_SWIZZLE_Y );
+ emit_coef_dady( func, 3, i, j );
+ emit_mul( func, 0, 1 ); /* x * dadx */
+ emit_tempf( func, 4, 0, TGSI_SWIZZLE_W );
+ emit_coef_a0( func, 5, i, j );
+ emit_rcp( func, 4, 4 ); /* 1.0 / w */
+ emit_mul( func, 2, 3 ); /* y * dady */
+ emit_add( func, 0, 5 ); /* x * dadx + a0 */
+ emit_add( func, 0, 2 ); /* x * dadx + y * dady + a0 */
+ emit_mul( func, 0, 4 ); /* (x * dadx + y * dady + a0) / w */
+ emit_inputs( func, 0, i, j );
+ break;
+
+ default:
+ assert( 0 );
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void aos_to_soa( struct x86_function *func,
+ uint arg_aos,
+ uint arg_machine,
+ uint arg_num,
+ uint arg_stride )
+{
+ struct x86_reg soa_input = x86_make_reg( file_REG32, reg_AX );
+ struct x86_reg aos_input = x86_make_reg( file_REG32, reg_BX );
+ struct x86_reg num_inputs = x86_make_reg( file_REG32, reg_CX );
+ struct x86_reg stride = x86_make_reg( file_REG32, reg_DX );
+ int inner_loop;
+
+
+ /* Save EBX */
+ x86_push( func, x86_make_reg( file_REG32, reg_BX ) );
+
+ x86_mov( func, aos_input, x86_fn_arg( func, arg_aos ) );
+ x86_mov( func, soa_input, x86_fn_arg( func, arg_machine ) );
+ x86_lea( func, soa_input,
+ x86_make_disp( soa_input,
+ Offset(struct tgsi_exec_machine, Inputs) ) );
+ x86_mov( func, num_inputs, x86_fn_arg( func, arg_num ) );
+ x86_mov( func, stride, x86_fn_arg( func, arg_stride ) );
+
+ /* do */
+ inner_loop = x86_get_label( func );
+ {
+ x86_push( func, aos_input );
+ sse_movlps( func, make_xmm( 0 ), x86_make_disp( aos_input, 0 ) );
+ sse_movlps( func, make_xmm( 3 ), x86_make_disp( aos_input, 8 ) );
+ x86_add( func, aos_input, stride );
+ sse_movhps( func, make_xmm( 0 ), x86_make_disp( aos_input, 0 ) );
+ sse_movhps( func, make_xmm( 3 ), x86_make_disp( aos_input, 8 ) );
+ x86_add( func, aos_input, stride );
+ sse_movlps( func, make_xmm( 1 ), x86_make_disp( aos_input, 0 ) );
+ sse_movlps( func, make_xmm( 4 ), x86_make_disp( aos_input, 8 ) );
+ x86_add( func, aos_input, stride );
+ sse_movhps( func, make_xmm( 1 ), x86_make_disp( aos_input, 0 ) );
+ sse_movhps( func, make_xmm( 4 ), x86_make_disp( aos_input, 8 ) );
+ x86_pop( func, aos_input );
+
+ sse_movaps( func, make_xmm( 2 ), make_xmm( 0 ) );
+ sse_movaps( func, make_xmm( 5 ), make_xmm( 3 ) );
+ sse_shufps( func, make_xmm( 0 ), make_xmm( 1 ), 0x88 );
+ sse_shufps( func, make_xmm( 2 ), make_xmm( 1 ), 0xdd );
+ sse_shufps( func, make_xmm( 3 ), make_xmm( 4 ), 0x88 );
+ sse_shufps( func, make_xmm( 5 ), make_xmm( 4 ), 0xdd );
+
+ sse_movups( func, x86_make_disp( soa_input, 0 ), make_xmm( 0 ) );
+ sse_movups( func, x86_make_disp( soa_input, 16 ), make_xmm( 2 ) );
+ sse_movups( func, x86_make_disp( soa_input, 32 ), make_xmm( 3 ) );
+ sse_movups( func, x86_make_disp( soa_input, 48 ), make_xmm( 5 ) );
+
+ /* Advance to next input */
+ x86_lea( func, aos_input, x86_make_disp(aos_input, 16) );
+ x86_lea( func, soa_input, x86_make_disp(soa_input, 64) );
+ }
+ /* while --num_inputs */
+ x86_dec( func, num_inputs );
+ x86_jcc( func, cc_NE, inner_loop );
+
+ /* Restore EBX */
+ x86_pop( func, x86_make_reg( file_REG32, reg_BX ) );
+}
+
+static void soa_to_aos( struct x86_function *func,
+ uint arg_aos,
+ uint arg_machine,
+ uint arg_num,
+ uint arg_stride )
+{
+ struct x86_reg soa_output = x86_make_reg( file_REG32, reg_AX );
+ struct x86_reg aos_output = x86_make_reg( file_REG32, reg_BX );
+ struct x86_reg num_outputs = x86_make_reg( file_REG32, reg_CX );
+ struct x86_reg temp = x86_make_reg( file_REG32, reg_DX );
+ int inner_loop;
+
+ /* Save EBX */
+ x86_push( func, x86_make_reg( file_REG32, reg_BX ) );
+
+ x86_mov( func, aos_output, x86_fn_arg( func, arg_aos ) );
+ x86_mov( func, soa_output, x86_fn_arg( func, arg_machine ) );
+ x86_lea( func, soa_output,
+ x86_make_disp( soa_output,
+ Offset(struct tgsi_exec_machine, Outputs) ) );
+ x86_mov( func, num_outputs, x86_fn_arg( func, arg_num ) );
+
+ /* do */
+ inner_loop = x86_get_label( func );
+ {
+ sse_movups( func, make_xmm( 0 ), x86_make_disp( soa_output, 0 ) );
+ sse_movups( func, make_xmm( 1 ), x86_make_disp( soa_output, 16 ) );
+ sse_movups( func, make_xmm( 3 ), x86_make_disp( soa_output, 32 ) );
+ sse_movups( func, make_xmm( 4 ), x86_make_disp( soa_output, 48 ) );
+
+ sse_movaps( func, make_xmm( 2 ), make_xmm( 0 ) );
+ sse_movaps( func, make_xmm( 5 ), make_xmm( 3 ) );
+ sse_unpcklps( func, make_xmm( 0 ), make_xmm( 1 ) );
+ sse_unpckhps( func, make_xmm( 2 ), make_xmm( 1 ) );
+ sse_unpcklps( func, make_xmm( 3 ), make_xmm( 4 ) );
+ sse_unpckhps( func, make_xmm( 5 ), make_xmm( 4 ) );
+
+ x86_mov( func, temp, x86_fn_arg( func, arg_stride ) );
+ x86_push( func, aos_output );
+ sse_movlps( func, x86_make_disp( aos_output, 0 ), make_xmm( 0 ) );
+ sse_movlps( func, x86_make_disp( aos_output, 8 ), make_xmm( 3 ) );
+ x86_add( func, aos_output, temp );
+ sse_movhps( func, x86_make_disp( aos_output, 0 ), make_xmm( 0 ) );
+ sse_movhps( func, x86_make_disp( aos_output, 8 ), make_xmm( 3 ) );
+ x86_add( func, aos_output, temp );
+ sse_movlps( func, x86_make_disp( aos_output, 0 ), make_xmm( 2 ) );
+ sse_movlps( func, x86_make_disp( aos_output, 8 ), make_xmm( 5 ) );
+ x86_add( func, aos_output, temp );
+ sse_movhps( func, x86_make_disp( aos_output, 0 ), make_xmm( 2 ) );
+ sse_movhps( func, x86_make_disp( aos_output, 8 ), make_xmm( 5 ) );
+ x86_pop( func, aos_output );
+
+ /* Advance to next output */
+ x86_lea( func, aos_output, x86_make_disp(aos_output, 16) );
+ x86_lea( func, soa_output, x86_make_disp(soa_output, 64) );
+ }
+ /* while --num_outputs */
+ x86_dec( func, num_outputs );
+ x86_jcc( func, cc_NE, inner_loop );
+
+ /* Restore EBX */
+ x86_pop( func, x86_make_reg( file_REG32, reg_BX ) );
+}
+
+/**
+ * Translate a TGSI vertex/fragment shader to SSE2 code.
+ * Slightly different things are done for vertex vs. fragment shaders.
+ *
+ * \param tokens the TGSI input shader
+ * \param func the output SSE code/function
+ * \param immediates buffer to place immediates, later passed to SSE func
+ * \param return 1 for success, 0 if translation failed
+ */
+unsigned
+tgsi_emit_sse2(
+ const struct tgsi_token *tokens,
+ struct x86_function *func,
+ float (*immediates)[4],
+ boolean do_swizzles )
+{
+ struct tgsi_parse_context parse;
+ unsigned ok = 1;
+ uint num_immediates = 0;
+
+ util_init_math();
+
+ func->csr = func->store;
+
+ tgsi_parse_init( &parse, tokens );
+
+ /* Can't just use EDI, EBX without save/restoring them:
+ */
+ x86_push( func, x86_make_reg( file_REG32, reg_BX ) );
+ x86_push( func, x86_make_reg( file_REG32, reg_DI ) );
+
+ /*
+ * Different function args for vertex/fragment shaders:
+ */
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX) {
+ if (do_swizzles)
+ aos_to_soa( func,
+ 4, /* aos_input */
+ 1, /* machine */
+ 5, /* num_inputs */
+ 6 ); /* input_stride */
+ }
+
+ x86_mov(
+ func,
+ get_machine_base(),
+ x86_fn_arg( func, 1 ) );
+ x86_mov(
+ func,
+ get_const_base(),
+ x86_fn_arg( func, 2 ) );
+ x86_mov(
+ func,
+ get_immediate_base(),
+ x86_fn_arg( func, 3 ) );
+
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
+ x86_mov(
+ func,
+ get_coef_base(),
+ x86_fn_arg( func, 4 ) );
+ }
+
+ x86_mov(
+ func,
+ get_sampler_base(),
+ x86_make_disp( get_machine_base(),
+ Offset( struct tgsi_exec_machine, Samplers ) ) );
+
+
+ while( !tgsi_parse_end_of_tokens( &parse ) && ok ) {
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
+ emit_declaration(
+ func,
+ &parse.FullToken.FullDeclaration );
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ ok = emit_instruction(
+ func,
+ &parse.FullToken.FullInstruction );
+
+ if (!ok) {
+ uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode;
+ debug_printf("failed to translate tgsi opcode %d (%s) to SSE (%s)\n",
+ opcode,
+ tgsi_get_opcode_name(opcode),
+ parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX ?
+ "vertex shader" : "fragment shader");
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ /* simply copy the immediate values into the next immediates[] slot */
+ {
+ const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
+ uint i;
+ assert(size <= 4);
+ assert(num_immediates < TGSI_EXEC_NUM_IMMEDIATES);
+ for( i = 0; i < size; i++ ) {
+ immediates[num_immediates][i] =
+ parse.FullToken.FullImmediate.u[i].Float;
+ }
+#if 0
+ debug_printf("SSE FS immediate[%d] = %f %f %f %f\n",
+ num_immediates,
+ immediates[num_immediates][0],
+ immediates[num_immediates][1],
+ immediates[num_immediates][2],
+ immediates[num_immediates][3]);
+#endif
+ num_immediates++;
+ }
+ break;
+
+ default:
+ ok = 0;
+ assert( 0 );
+ }
+ }
+
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX) {
+ if (do_swizzles)
+ soa_to_aos( func,
+ 7, /* aos_output */
+ 1, /* machine */
+ 8, /* num_outputs */
+ 9 ); /* output_stride */
+ }
+
+ /* Can't just use EBX, EDI without save/restoring them:
+ */
+ x86_pop( func, x86_make_reg( file_REG32, reg_DI ) );
+ x86_pop( func, x86_make_reg( file_REG32, reg_BX ) );
+
+ emit_ret( func );
+
+ tgsi_parse_free( &parse );
+
+ return ok;
+}
+
+#endif /* PIPE_ARCH_X86 */
+
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.h b/src/gallium/auxiliary/tgsi/tgsi_sse2.h
new file mode 100644
index 0000000000..d81ee3d00e
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.h
@@ -0,0 +1,77 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_SSE2_H
+#define TGSI_SSE2_H
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct tgsi_token;
+struct x86_function;
+struct tgsi_interp_coef;
+
+unsigned
+tgsi_emit_sse2(
+ const struct tgsi_token *tokens,
+ struct x86_function *function,
+ float (*immediates)[4],
+ boolean do_swizzles );
+
+
+/* This is the function prototype generated when do_swizzles is false
+ * -- effectively for fragment shaders.
+ */
+typedef void (PIPE_CDECL *tgsi_sse2_fs_function) (
+ struct tgsi_exec_machine *machine, /* 1 */
+ const float (*constant)[4], /* 2 */
+ const float (*immediate)[4], /* 3 */
+ const struct tgsi_interp_coef *coef /* 4 */
+ );
+
+
+/* This is the function prototype generated when do_swizzles is true
+ * -- effectively for vertex shaders.
+ */
+typedef void (PIPE_CDECL *tgsi_sse2_vs_func) (
+ struct tgsi_exec_machine *machine, /* 1 */
+ const float (*constant)[4], /* 2 */
+ const float (*immediate)[4], /* 3 */
+ const float (*aos_input)[4], /* 4 */
+ uint num_inputs, /* 5 */
+ uint input_stride, /* 6 */
+ float (*aos_output)[4], /* 7 */
+ uint num_outputs, /* 8 */
+ uint output_stride ); /* 9 */
+
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_SSE2_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c
new file mode 100644
index 0000000000..d438450b1e
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_text.c
@@ -0,0 +1,1157 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "tgsi_text.h"
+#include "tgsi_build.h"
+#include "tgsi_info.h"
+#include "tgsi_parse.h"
+#include "tgsi_sanity.h"
+#include "tgsi_util.h"
+
+static boolean is_alpha_underscore( const char *cur )
+{
+ return
+ (*cur >= 'a' && *cur <= 'z') ||
+ (*cur >= 'A' && *cur <= 'Z') ||
+ *cur == '_';
+}
+
+static boolean is_digit( const char *cur )
+{
+ return *cur >= '0' && *cur <= '9';
+}
+
+static boolean is_digit_alpha_underscore( const char *cur )
+{
+ return is_digit( cur ) || is_alpha_underscore( cur );
+}
+
+static boolean uprcase( char c )
+{
+ if (c >= 'a' && c <= 'z')
+ return c += 'A' - 'a';
+ return c;
+}
+
+static boolean str_match_no_case( const char **pcur, const char *str )
+{
+ const char *cur = *pcur;
+
+ while (*str != '\0' && *str == uprcase( *cur )) {
+ str++;
+ cur++;
+ }
+ if (*str == '\0') {
+ *pcur = cur;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Eat zero or more whitespaces.
+ */
+static void eat_opt_white( const char **pcur )
+{
+ while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
+ (*pcur)++;
+}
+
+/* Eat one or more whitespaces.
+ * Return TRUE if at least one whitespace eaten.
+ */
+static boolean eat_white( const char **pcur )
+{
+ const char *cur = *pcur;
+
+ eat_opt_white( pcur );
+ return *pcur > cur;
+}
+
+/* Parse unsigned integer.
+ * No checks for overflow.
+ */
+static boolean parse_uint( const char **pcur, uint *val )
+{
+ const char *cur = *pcur;
+
+ if (is_digit( cur )) {
+ *val = *cur++ - '0';
+ while (is_digit( cur ))
+ *val = *val * 10 + *cur++ - '0';
+ *pcur = cur;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Parse floating point.
+ */
+static boolean parse_float( const char **pcur, float *val )
+{
+ const char *cur = *pcur;
+ boolean integral_part = FALSE;
+ boolean fractional_part = FALSE;
+
+ *val = (float) atof( cur );
+
+ if (*cur == '-' || *cur == '+')
+ cur++;
+ if (is_digit( cur )) {
+ cur++;
+ integral_part = TRUE;
+ while (is_digit( cur ))
+ cur++;
+ }
+ if (*cur == '.') {
+ cur++;
+ if (is_digit( cur )) {
+ cur++;
+ fractional_part = TRUE;
+ while (is_digit( cur ))
+ cur++;
+ }
+ }
+ if (!integral_part && !fractional_part)
+ return FALSE;
+ if (uprcase( *cur ) == 'E') {
+ cur++;
+ if (*cur == '-' || *cur == '+')
+ cur++;
+ if (is_digit( cur )) {
+ cur++;
+ while (is_digit( cur ))
+ cur++;
+ }
+ else
+ return FALSE;
+ }
+ *pcur = cur;
+ return TRUE;
+}
+
+struct translate_ctx
+{
+ const char *text;
+ const char *cur;
+ struct tgsi_token *tokens;
+ struct tgsi_token *tokens_cur;
+ struct tgsi_token *tokens_end;
+ struct tgsi_header *header;
+};
+
+static void report_error( struct translate_ctx *ctx, const char *msg )
+{
+ debug_printf( "\nError: %s", msg );
+}
+
+/* Parse shader header.
+ * Return TRUE for one of the following headers.
+ * FRAG1.1
+ * GEOM1.1
+ * VERT1.1
+ */
+static boolean parse_header( struct translate_ctx *ctx )
+{
+ uint processor;
+
+ if (str_match_no_case( &ctx->cur, "FRAG1.1" ))
+ processor = TGSI_PROCESSOR_FRAGMENT;
+ else if (str_match_no_case( &ctx->cur, "VERT1.1" ))
+ processor = TGSI_PROCESSOR_VERTEX;
+ else if (str_match_no_case( &ctx->cur, "GEOM1.1" ))
+ processor = TGSI_PROCESSOR_GEOMETRY;
+ else {
+ report_error( ctx, "Unknown header" );
+ return FALSE;
+ }
+
+ if (ctx->tokens_cur >= ctx->tokens_end)
+ return FALSE;
+ *(struct tgsi_version *) ctx->tokens_cur++ = tgsi_build_version();
+
+ if (ctx->tokens_cur >= ctx->tokens_end)
+ return FALSE;
+ ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
+ *ctx->header = tgsi_build_header();
+
+ if (ctx->tokens_cur >= ctx->tokens_end)
+ return FALSE;
+ *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
+
+ return TRUE;
+}
+
+static boolean parse_label( struct translate_ctx *ctx, uint *val )
+{
+ const char *cur = ctx->cur;
+
+ if (parse_uint( &cur, val )) {
+ eat_opt_white( &cur );
+ if (*cur == ':') {
+ cur++;
+ ctx->cur = cur;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static const char *file_names[TGSI_FILE_COUNT] =
+{
+ "NULL",
+ "CONST",
+ "IN",
+ "OUT",
+ "TEMP",
+ "SAMP",
+ "ADDR",
+ "IMM",
+ "LOOP"
+};
+
+static boolean
+parse_file( const char **pcur, uint *file )
+{
+ uint i;
+
+ for (i = 0; i < TGSI_FILE_COUNT; i++) {
+ const char *cur = *pcur;
+
+ if (str_match_no_case( &cur, file_names[i] )) {
+ if (!is_digit_alpha_underscore( cur )) {
+ *pcur = cur;
+ *file = i;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+static boolean
+parse_opt_writemask(
+ struct translate_ctx *ctx,
+ uint *writemask )
+{
+ const char *cur;
+
+ cur = ctx->cur;
+ eat_opt_white( &cur );
+ if (*cur == '.') {
+ cur++;
+ *writemask = TGSI_WRITEMASK_NONE;
+ eat_opt_white( &cur );
+ if (uprcase( *cur ) == 'X') {
+ cur++;
+ *writemask |= TGSI_WRITEMASK_X;
+ }
+ if (uprcase( *cur ) == 'Y') {
+ cur++;
+ *writemask |= TGSI_WRITEMASK_Y;
+ }
+ if (uprcase( *cur ) == 'Z') {
+ cur++;
+ *writemask |= TGSI_WRITEMASK_Z;
+ }
+ if (uprcase( *cur ) == 'W') {
+ cur++;
+ *writemask |= TGSI_WRITEMASK_W;
+ }
+
+ if (*writemask == TGSI_WRITEMASK_NONE) {
+ report_error( ctx, "Writemask expected" );
+ return FALSE;
+ }
+
+ ctx->cur = cur;
+ }
+ else {
+ *writemask = TGSI_WRITEMASK_XYZW;
+ }
+ return TRUE;
+}
+
+/* <register_file_bracket> ::= <file> `['
+ */
+static boolean
+parse_register_file_bracket(
+ struct translate_ctx *ctx,
+ uint *file )
+{
+ if (!parse_file( &ctx->cur, file )) {
+ report_error( ctx, "Unknown register file" );
+ return FALSE;
+ }
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != '[') {
+ report_error( ctx, "Expected `['" );
+ return FALSE;
+ }
+ ctx->cur++;
+ return TRUE;
+}
+
+/* <register_file_bracket_index> ::= <register_file_bracket> <uint>
+ */
+static boolean
+parse_register_file_bracket_index(
+ struct translate_ctx *ctx,
+ uint *file,
+ int *index )
+{
+ uint uindex;
+
+ if (!parse_register_file_bracket( ctx, file ))
+ return FALSE;
+ eat_opt_white( &ctx->cur );
+ if (!parse_uint( &ctx->cur, &uindex )) {
+ report_error( ctx, "Expected literal unsigned integer" );
+ return FALSE;
+ }
+ *index = (int) uindex;
+ return TRUE;
+}
+
+/* Parse destination register operand.
+ * <register_dst> ::= <register_file_bracket_index> `]'
+ */
+static boolean
+parse_register_dst(
+ struct translate_ctx *ctx,
+ uint *file,
+ int *index )
+{
+ if (!parse_register_file_bracket_index( ctx, file, index ))
+ return FALSE;
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != ']') {
+ report_error( ctx, "Expected `]'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ return TRUE;
+}
+
+/* Parse source register operand.
+ * <register_src> ::= <register_file_bracket_index> `]' |
+ * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
+ * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
+ * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
+ */
+static boolean
+parse_register_src(
+ struct translate_ctx *ctx,
+ uint *file,
+ int *index,
+ uint *ind_file,
+ int *ind_index,
+ uint *ind_comp)
+{
+ const char *cur;
+ uint uindex;
+
+ *ind_comp = TGSI_SWIZZLE_X;
+ if (!parse_register_file_bracket( ctx, file ))
+ return FALSE;
+ eat_opt_white( &ctx->cur );
+ cur = ctx->cur;
+ if (parse_file( &cur, ind_file )) {
+ if (!parse_register_dst( ctx, ind_file, ind_index ))
+ return FALSE;
+ eat_opt_white( &ctx->cur );
+
+ if (*ctx->cur == '.') {
+ ctx->cur++;
+ eat_opt_white(&ctx->cur);
+
+ switch (uprcase(*ctx->cur)) {
+ case 'X':
+ *ind_comp = TGSI_SWIZZLE_X;
+ break;
+ case 'Y':
+ *ind_comp = TGSI_SWIZZLE_Y;
+ break;
+ case 'Z':
+ *ind_comp = TGSI_SWIZZLE_Z;
+ break;
+ case 'W':
+ *ind_comp = TGSI_SWIZZLE_W;
+ break;
+ default:
+ report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
+ return FALSE;
+ }
+ ctx->cur++;
+ eat_opt_white(&ctx->cur);
+ }
+
+ if (*ctx->cur == '+' || *ctx->cur == '-') {
+ boolean negate;
+
+ negate = *ctx->cur == '-';
+ ctx->cur++;
+ eat_opt_white( &ctx->cur );
+ if (!parse_uint( &ctx->cur, &uindex )) {
+ report_error( ctx, "Expected literal unsigned integer" );
+ return FALSE;
+ }
+ if (negate)
+ *index = -(int) uindex;
+ else
+ *index = (int) uindex;
+ }
+ else {
+ *index = 0;
+ }
+ }
+ else {
+ if (!parse_uint( &ctx->cur, &uindex )) {
+ report_error( ctx, "Expected literal unsigned integer" );
+ return FALSE;
+ }
+ *index = (int) uindex;
+ *ind_file = TGSI_FILE_NULL;
+ *ind_index = 0;
+ }
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != ']') {
+ report_error( ctx, "Expected `]'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ return TRUE;
+}
+
+/* Parse register declaration.
+ * <register_dcl> ::= <register_file_bracket_index> `]' |
+ * <register_file_bracket_index> `..' <index> `]'
+ */
+static boolean
+parse_register_dcl(
+ struct translate_ctx *ctx,
+ uint *file,
+ int *first,
+ int *last )
+{
+ if (!parse_register_file_bracket_index( ctx, file, first ))
+ return FALSE;
+ eat_opt_white( &ctx->cur );
+ if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
+ uint uindex;
+
+ ctx->cur += 2;
+ eat_opt_white( &ctx->cur );
+ if (!parse_uint( &ctx->cur, &uindex )) {
+ report_error( ctx, "Expected literal integer" );
+ return FALSE;
+ }
+ *last = (int) uindex;
+ eat_opt_white( &ctx->cur );
+ }
+ else {
+ *last = *first;
+ }
+ if (*ctx->cur != ']') {
+ report_error( ctx, "Expected `]' or `..'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ return TRUE;
+}
+
+static const char *modulate_names[TGSI_MODULATE_COUNT] =
+{
+ "_1X",
+ "_2X",
+ "_4X",
+ "_8X",
+ "_D2",
+ "_D4",
+ "_D8"
+};
+
+static boolean
+parse_dst_operand(
+ struct translate_ctx *ctx,
+ struct tgsi_full_dst_register *dst )
+{
+ uint file;
+ int index;
+ uint writemask;
+ const char *cur;
+
+ if (!parse_register_dst( ctx, &file, &index ))
+ return FALSE;
+
+ cur = ctx->cur;
+ eat_opt_white( &cur );
+ if (*cur == '_') {
+ uint i;
+
+ for (i = 0; i < TGSI_MODULATE_COUNT; i++) {
+ if (str_match_no_case( &cur, modulate_names[i] )) {
+ if (!is_digit_alpha_underscore( cur )) {
+ dst->DstRegisterExtModulate.Modulate = i;
+ ctx->cur = cur;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!parse_opt_writemask( ctx, &writemask ))
+ return FALSE;
+
+ dst->DstRegister.File = file;
+ dst->DstRegister.Index = index;
+ dst->DstRegister.WriteMask = writemask;
+ return TRUE;
+}
+
+static boolean
+parse_optional_swizzle(
+ struct translate_ctx *ctx,
+ uint swizzle[4],
+ boolean *parsed_swizzle,
+ boolean *parsed_extswizzle )
+{
+ const char *cur = ctx->cur;
+
+ *parsed_swizzle = FALSE;
+ *parsed_extswizzle = FALSE;
+
+ eat_opt_white( &cur );
+ if (*cur == '.') {
+ uint i;
+
+ cur++;
+ eat_opt_white( &cur );
+ for (i = 0; i < 4; i++) {
+ if (uprcase( *cur ) == 'X')
+ swizzle[i] = TGSI_SWIZZLE_X;
+ else if (uprcase( *cur ) == 'Y')
+ swizzle[i] = TGSI_SWIZZLE_Y;
+ else if (uprcase( *cur ) == 'Z')
+ swizzle[i] = TGSI_SWIZZLE_Z;
+ else if (uprcase( *cur ) == 'W')
+ swizzle[i] = TGSI_SWIZZLE_W;
+ else {
+ if (*cur == '0')
+ swizzle[i] = TGSI_EXTSWIZZLE_ZERO;
+ else if (*cur == '1')
+ swizzle[i] = TGSI_EXTSWIZZLE_ONE;
+ else {
+ report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
+ return FALSE;
+ }
+ *parsed_extswizzle = TRUE;
+ }
+ cur++;
+ }
+ *parsed_swizzle = TRUE;
+ ctx->cur = cur;
+ }
+ return TRUE;
+}
+
+static boolean
+parse_src_operand(
+ struct translate_ctx *ctx,
+ struct tgsi_full_src_register *src )
+{
+ const char *cur;
+ float value;
+ uint file;
+ int index;
+ uint ind_file;
+ int ind_index;
+ uint ind_comp;
+ uint swizzle[4];
+ boolean parsed_ext_negate_paren = FALSE;
+ boolean parsed_swizzle;
+ boolean parsed_extswizzle;
+
+ if (*ctx->cur == '-') {
+ cur = ctx->cur;
+ cur++;
+ eat_opt_white( &cur );
+ if (*cur == '(') {
+ cur++;
+ src->SrcRegisterExtMod.Negate = 1;
+ eat_opt_white( &cur );
+ ctx->cur = cur;
+ parsed_ext_negate_paren = TRUE;
+ }
+ else if (*cur == '|') {
+ cur++;
+ src->SrcRegisterExtMod.Negate = 1;
+ src->SrcRegisterExtMod.Absolute = 1;
+ eat_opt_white(&cur);
+ ctx->cur = cur;
+ }
+ }
+ else if (*ctx->cur == '|') {
+ ctx->cur++;
+ eat_opt_white( &ctx->cur );
+ src->SrcRegisterExtMod.Absolute = 1;
+ }
+
+ if (*ctx->cur == '-') {
+ ctx->cur++;
+ eat_opt_white( &ctx->cur );
+ src->SrcRegister.Negate = 1;
+ }
+
+ cur = ctx->cur;
+ if (parse_float( &cur, &value )) {
+ if (value == 2.0f) {
+ eat_opt_white( &cur );
+ if (*cur != '*') {
+ report_error( ctx, "Expected `*'" );
+ return FALSE;
+ }
+ cur++;
+ if (*cur != '(') {
+ report_error( ctx, "Expected `('" );
+ return FALSE;
+ }
+ cur++;
+ src->SrcRegisterExtMod.Scale2X = 1;
+ eat_opt_white( &cur );
+ ctx->cur = cur;
+ }
+ }
+
+ if (*ctx->cur == '(') {
+ ctx->cur++;
+ eat_opt_white( &ctx->cur );
+ src->SrcRegisterExtMod.Bias = 1;
+ }
+
+ cur = ctx->cur;
+ if (parse_float( &cur, &value )) {
+ if (value == 1.0f) {
+ eat_opt_white( &cur );
+ if (*cur != '-') {
+ report_error( ctx, "Expected `-'" );
+ return FALSE;
+ }
+ cur++;
+ if (*cur != '(') {
+ report_error( ctx, "Expected `('" );
+ return FALSE;
+ }
+ cur++;
+ src->SrcRegisterExtMod.Complement = 1;
+ eat_opt_white( &cur );
+ ctx->cur = cur;
+ }
+ }
+
+ if (!parse_register_src(ctx, &file, &index, &ind_file, &ind_index, &ind_comp))
+ return FALSE;
+ src->SrcRegister.File = file;
+ src->SrcRegister.Index = index;
+ if (ind_file != TGSI_FILE_NULL) {
+ src->SrcRegister.Indirect = 1;
+ src->SrcRegisterInd.File = ind_file;
+ src->SrcRegisterInd.Index = ind_index;
+ src->SrcRegisterInd.SwizzleX = ind_comp;
+ src->SrcRegisterInd.SwizzleY = ind_comp;
+ src->SrcRegisterInd.SwizzleZ = ind_comp;
+ src->SrcRegisterInd.SwizzleW = ind_comp;
+ }
+
+ /* Parse optional swizzle.
+ */
+ if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, &parsed_extswizzle )) {
+ if (parsed_extswizzle) {
+ assert( parsed_swizzle );
+
+ src->SrcRegisterExtSwz.ExtSwizzleX = swizzle[0];
+ src->SrcRegisterExtSwz.ExtSwizzleY = swizzle[1];
+ src->SrcRegisterExtSwz.ExtSwizzleZ = swizzle[2];
+ src->SrcRegisterExtSwz.ExtSwizzleW = swizzle[3];
+ }
+ else if (parsed_swizzle) {
+ src->SrcRegister.SwizzleX = swizzle[0];
+ src->SrcRegister.SwizzleY = swizzle[1];
+ src->SrcRegister.SwizzleZ = swizzle[2];
+ src->SrcRegister.SwizzleW = swizzle[3];
+ }
+ }
+
+ if (src->SrcRegisterExtMod.Complement) {
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != ')') {
+ report_error( ctx, "Expected `)'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ }
+
+ if (src->SrcRegisterExtMod.Bias) {
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != ')') {
+ report_error( ctx, "Expected `)'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != '-') {
+ report_error( ctx, "Expected `-'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ eat_opt_white( &ctx->cur );
+ if (!parse_float( &ctx->cur, &value )) {
+ report_error( ctx, "Expected literal floating point" );
+ return FALSE;
+ }
+ if (value != 0.5f) {
+ report_error( ctx, "Expected 0.5" );
+ return FALSE;
+ }
+ }
+
+ if (src->SrcRegisterExtMod.Scale2X) {
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != ')') {
+ report_error( ctx, "Expected `)'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ }
+
+ if (src->SrcRegisterExtMod.Absolute) {
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != '|') {
+ report_error( ctx, "Expected `|'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ }
+
+ if (parsed_ext_negate_paren) {
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != ')') {
+ report_error( ctx, "Expected `)'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ }
+
+ return TRUE;
+}
+
+static const char *texture_names[TGSI_TEXTURE_COUNT] =
+{
+ "UNKNOWN",
+ "1D",
+ "2D",
+ "3D",
+ "CUBE",
+ "RECT",
+ "SHADOW1D",
+ "SHADOW2D",
+ "SHADOWRECT"
+};
+
+static boolean
+match_inst_mnemonic(const char **pcur,
+ const struct tgsi_opcode_info *info)
+{
+ if (str_match_no_case(pcur, info->mnemonic)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static boolean
+parse_instruction(
+ struct translate_ctx *ctx,
+ boolean has_label )
+{
+ uint i;
+ uint saturate = TGSI_SAT_NONE;
+ const struct tgsi_opcode_info *info;
+ struct tgsi_full_instruction inst;
+ uint advance;
+
+ /* Parse instruction name.
+ */
+ eat_opt_white( &ctx->cur );
+ for (i = 0; i < TGSI_OPCODE_LAST; i++) {
+ const char *cur = ctx->cur;
+
+ info = tgsi_get_opcode_info( i );
+ if (match_inst_mnemonic(&cur, info)) {
+ if (str_match_no_case( &cur, "_SATNV" ))
+ saturate = TGSI_SAT_MINUS_PLUS_ONE;
+ else if (str_match_no_case( &cur, "_SAT" ))
+ saturate = TGSI_SAT_ZERO_ONE;
+
+ if (info->num_dst + info->num_src + info->is_tex == 0) {
+ if (!is_digit_alpha_underscore( cur )) {
+ ctx->cur = cur;
+ break;
+ }
+ }
+ else if (*cur == '\0' || eat_white( &cur )) {
+ ctx->cur = cur;
+ break;
+ }
+ }
+ }
+ if (i == TGSI_OPCODE_LAST) {
+ if (has_label)
+ report_error( ctx, "Unknown opcode" );
+ else
+ report_error( ctx, "Expected `DCL', `IMM' or a label" );
+ return FALSE;
+ }
+
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = i;
+ inst.Instruction.Saturate = saturate;
+ inst.Instruction.NumDstRegs = info->num_dst;
+ inst.Instruction.NumSrcRegs = info->num_src;
+
+ /* Parse instruction operands.
+ */
+ for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
+ if (i > 0) {
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != ',') {
+ report_error( ctx, "Expected `,'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ eat_opt_white( &ctx->cur );
+ }
+
+ if (i < info->num_dst) {
+ if (!parse_dst_operand( ctx, &inst.FullDstRegisters[i] ))
+ return FALSE;
+ }
+ else if (i < info->num_dst + info->num_src) {
+ if (!parse_src_operand( ctx, &inst.FullSrcRegisters[i - info->num_dst] ))
+ return FALSE;
+ }
+ else {
+ uint j;
+
+ for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
+ if (str_match_no_case( &ctx->cur, texture_names[j] )) {
+ if (!is_digit_alpha_underscore( ctx->cur )) {
+ inst.InstructionExtTexture.Texture = j;
+ break;
+ }
+ }
+ }
+ if (j == TGSI_TEXTURE_COUNT) {
+ report_error( ctx, "Expected texture target" );
+ return FALSE;
+ }
+ }
+ }
+
+ if (info->is_branch) {
+ uint target;
+
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != ':') {
+ report_error( ctx, "Expected `:'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ eat_opt_white( &ctx->cur );
+ if (!parse_uint( &ctx->cur, &target )) {
+ report_error( ctx, "Expected a label" );
+ return FALSE;
+ }
+ inst.InstructionExtLabel.Label = target;
+ }
+
+ advance = tgsi_build_full_instruction(
+ &inst,
+ ctx->tokens_cur,
+ ctx->header,
+ (uint) (ctx->tokens_end - ctx->tokens_cur) );
+ if (advance == 0)
+ return FALSE;
+ ctx->tokens_cur += advance;
+
+ return TRUE;
+}
+
+static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
+{
+ "POSITION",
+ "COLOR",
+ "BCOLOR",
+ "FOG",
+ "PSIZE",
+ "GENERIC",
+ "NORMAL",
+ "FACE"
+};
+
+static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
+{
+ "CONSTANT",
+ "LINEAR",
+ "PERSPECTIVE"
+};
+
+static boolean parse_declaration( struct translate_ctx *ctx )
+{
+ struct tgsi_full_declaration decl;
+ uint file;
+ int first;
+ int last;
+ uint writemask;
+ const char *cur;
+ uint advance;
+
+ assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT);
+ assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT);
+
+ if (!eat_white( &ctx->cur )) {
+ report_error( ctx, "Syntax error" );
+ return FALSE;
+ }
+ if (!parse_register_dcl( ctx, &file, &first, &last ))
+ return FALSE;
+ if (!parse_opt_writemask( ctx, &writemask ))
+ return FALSE;
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = file;
+ decl.Declaration.UsageMask = writemask;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
+
+ cur = ctx->cur;
+ eat_opt_white( &cur );
+ if (*cur == ',') {
+ uint i;
+
+ 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" );
+ return FALSE;
+ }
+ eat_opt_white( &cur2 );
+ if (*cur2 != ']') {
+ report_error( ctx, "Expected `]'" );
+ return FALSE;
+ }
+ cur2++;
+
+ decl.Semantic.SemanticIndex = index;
+
+ cur = cur2;
+ }
+
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = i;
+
+ ctx->cur = cur;
+ break;
+ }
+ }
+ }
+
+ cur = ctx->cur;
+ eat_opt_white( &cur );
+ if (*cur == ',') {
+ uint i;
+
+ cur++;
+ eat_opt_white( &cur );
+ for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
+ if (str_match_no_case( &cur, interpolate_names[i] )) {
+ if (is_digit_alpha_underscore( cur ))
+ continue;
+ decl.Declaration.Interpolate = i;
+
+ ctx->cur = cur;
+ break;
+ }
+ }
+ if (i == TGSI_INTERPOLATE_COUNT) {
+ report_error( ctx, "Expected semantic or interpolate attribute" );
+ return FALSE;
+ }
+ }
+
+ advance = tgsi_build_full_declaration(
+ &decl,
+ ctx->tokens_cur,
+ ctx->header,
+ (uint) (ctx->tokens_end - ctx->tokens_cur) );
+ if (advance == 0)
+ return FALSE;
+ ctx->tokens_cur += advance;
+
+ return TRUE;
+}
+
+static boolean parse_immediate( struct translate_ctx *ctx )
+{
+ struct tgsi_full_immediate imm;
+ uint i;
+ float values[4];
+ uint advance;
+
+ if (!eat_white( &ctx->cur )) {
+ report_error( ctx, "Syntax error" );
+ return FALSE;
+ }
+ if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) {
+ report_error( ctx, "Expected `FLT32'" );
+ return FALSE;
+ }
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != '{') {
+ report_error( ctx, "Expected `{'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ for (i = 0; i < 4; i++) {
+ eat_opt_white( &ctx->cur );
+ if (i > 0) {
+ if (*ctx->cur != ',') {
+ report_error( ctx, "Expected `,'" );
+ return FALSE;
+ }
+ ctx->cur++;
+ eat_opt_white( &ctx->cur );
+ }
+ if (!parse_float( &ctx->cur, &values[i] )) {
+ report_error( ctx, "Expected literal floating point" );
+ return FALSE;
+ }
+ }
+ eat_opt_white( &ctx->cur );
+ if (*ctx->cur != '}') {
+ report_error( ctx, "Expected `}'" );
+ return FALSE;
+ }
+ ctx->cur++;
+
+ imm = tgsi_default_full_immediate();
+ imm.Immediate.NrTokens += 4;
+ imm.Immediate.DataType = TGSI_IMM_FLOAT32;
+ imm.u[0].Float = values[0];
+ imm.u[1].Float = values[1];
+ imm.u[2].Float = values[2];
+ imm.u[3].Float = values[3];
+
+ advance = tgsi_build_full_immediate(
+ &imm,
+ ctx->tokens_cur,
+ ctx->header,
+ (uint) (ctx->tokens_end - ctx->tokens_cur) );
+ if (advance == 0)
+ return FALSE;
+ ctx->tokens_cur += advance;
+
+ return TRUE;
+}
+
+static boolean translate( struct translate_ctx *ctx )
+{
+ eat_opt_white( &ctx->cur );
+ if (!parse_header( ctx ))
+ return FALSE;
+
+ while (*ctx->cur != '\0') {
+ uint label_val = 0;
+
+ if (!eat_white( &ctx->cur )) {
+ report_error( ctx, "Syntax error" );
+ return FALSE;
+ }
+
+ if (*ctx->cur == '\0')
+ break;
+
+ if (parse_label( ctx, &label_val )) {
+ if (!parse_instruction( ctx, TRUE ))
+ return FALSE;
+ }
+ else if (str_match_no_case( &ctx->cur, "DCL" )) {
+ if (!parse_declaration( ctx ))
+ return FALSE;
+ }
+ else if (str_match_no_case( &ctx->cur, "IMM" )) {
+ if (!parse_immediate( ctx ))
+ return FALSE;
+ }
+ else if (!parse_instruction( ctx, FALSE )) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+boolean
+tgsi_text_translate(
+ const char *text,
+ struct tgsi_token *tokens,
+ uint num_tokens )
+{
+ struct translate_ctx ctx;
+
+ ctx.text = text;
+ ctx.cur = text;
+ ctx.tokens = tokens;
+ ctx.tokens_cur = tokens;
+ ctx.tokens_end = tokens + num_tokens;
+
+ if (!translate( &ctx ))
+ return FALSE;
+
+ return tgsi_sanity_check( tokens );
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.h b/src/gallium/auxiliary/tgsi/tgsi_text.h
new file mode 100644
index 0000000000..8eeeeef140
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_text.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_TEXT_H
+#define TGSI_TEXT_H
+
+#include "pipe/p_shader_tokens.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+boolean
+tgsi_text_translate(
+ const char *text,
+ struct tgsi_token *tokens,
+ uint num_tokens );
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_TEXT_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_transform.c b/src/gallium/auxiliary/tgsi/tgsi_transform.c
new file mode 100644
index 0000000000..bc9c18fd4a
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_transform.c
@@ -0,0 +1,227 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * TGSI program transformation utility.
+ *
+ * Authors: Brian Paul
+ */
+
+#include "util/u_debug.h"
+
+#include "tgsi_transform.h"
+
+
+
+static void
+emit_instruction(struct tgsi_transform_context *ctx,
+ const struct tgsi_full_instruction *inst)
+{
+ uint ti = ctx->ti;
+
+ ti += tgsi_build_full_instruction(inst,
+ ctx->tokens_out + ti,
+ ctx->header,
+ ctx->max_tokens_out - ti);
+ ctx->ti = ti;
+}
+
+
+static void
+emit_declaration(struct tgsi_transform_context *ctx,
+ const struct tgsi_full_declaration *decl)
+{
+ uint ti = ctx->ti;
+
+ ti += tgsi_build_full_declaration(decl,
+ ctx->tokens_out + ti,
+ ctx->header,
+ ctx->max_tokens_out - ti);
+ ctx->ti = ti;
+}
+
+
+static void
+emit_immediate(struct tgsi_transform_context *ctx,
+ const struct tgsi_full_immediate *imm)
+{
+ uint ti = ctx->ti;
+
+ ti += tgsi_build_full_immediate(imm,
+ ctx->tokens_out + ti,
+ ctx->header,
+ ctx->max_tokens_out - ti);
+ ctx->ti = ti;
+}
+
+
+
+/**
+ * Apply user-defined transformations to the input shader to produce
+ * the output shader.
+ * For example, a register search-and-replace operation could be applied
+ * by defining a transform_instruction() callback that examined and changed
+ * the instruction src/dest regs.
+ *
+ * \return number of tokens emitted
+ */
+int
+tgsi_transform_shader(const struct tgsi_token *tokens_in,
+ struct tgsi_token *tokens_out,
+ uint max_tokens_out,
+ struct tgsi_transform_context *ctx)
+{
+ uint procType;
+
+ /* input shader */
+ struct tgsi_parse_context parse;
+
+ /* output shader */
+ struct tgsi_processor *processor;
+
+
+ /**
+ ** callback context init
+ **/
+ ctx->emit_instruction = emit_instruction;
+ ctx->emit_declaration = emit_declaration;
+ ctx->emit_immediate = emit_immediate;
+ ctx->tokens_out = tokens_out;
+ ctx->max_tokens_out = max_tokens_out;
+
+
+ /**
+ ** Setup to begin parsing input shader
+ **/
+ if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) {
+ debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n");
+ return -1;
+ }
+ procType = parse.FullHeader.Processor.Processor;
+ assert(procType == TGSI_PROCESSOR_FRAGMENT ||
+ procType == TGSI_PROCESSOR_VERTEX ||
+ procType == TGSI_PROCESSOR_GEOMETRY);
+
+
+ /**
+ ** Setup output shader
+ **/
+ *(struct tgsi_version *) &tokens_out[0] = tgsi_build_version();
+
+ ctx->header = (struct tgsi_header *) (tokens_out + 1);
+ *ctx->header = tgsi_build_header();
+
+ processor = (struct tgsi_processor *) (tokens_out + 2);
+ *processor = tgsi_build_processor( procType, ctx->header );
+
+ ctx->ti = 3;
+
+
+ /**
+ ** Loop over incoming program tokens/instructions
+ */
+ while( !tgsi_parse_end_of_tokens( &parse ) ) {
+
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ struct tgsi_full_instruction *fullinst
+ = &parse.FullToken.FullInstruction;
+
+ if (ctx->transform_instruction)
+ ctx->transform_instruction(ctx, fullinst);
+ else
+ ctx->emit_instruction(ctx, fullinst);
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ struct tgsi_full_declaration *fulldecl
+ = &parse.FullToken.FullDeclaration;
+
+ if (ctx->transform_declaration)
+ ctx->transform_declaration(ctx, fulldecl);
+ else
+ ctx->emit_declaration(ctx, fulldecl);
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ struct tgsi_full_immediate *fullimm
+ = &parse.FullToken.FullImmediate;
+
+ if (ctx->transform_immediate)
+ ctx->transform_immediate(ctx, fullimm);
+ else
+ ctx->emit_immediate(ctx, fullimm);
+ }
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+
+ if (ctx->epilog) {
+ ctx->epilog(ctx);
+ }
+
+ tgsi_parse_free (&parse);
+
+ return ctx->ti;
+}
+
+
+#include "tgsi_text.h"
+
+extern int tgsi_transform_foo( struct tgsi_token *tokens_out,
+ uint max_tokens_out );
+
+/* This function exists only so that tgsi_text_translate() doesn't get
+ * magic-ed out of the libtgsi.a archive by the build system. Don't
+ * remove unless you know this has been fixed - check on mingw/scons
+ * builds as well.
+ */
+int
+tgsi_transform_foo( struct tgsi_token *tokens_out,
+ uint max_tokens_out )
+{
+ const char *text =
+ "FRAG1.1\n"
+ "DCL IN[0], COLOR, CONSTANT\n"
+ "DCL OUT[0], COLOR\n"
+ " 0: MOV OUT[0], IN[0]\n"
+ " 1: END";
+
+ return tgsi_text_translate( text,
+ tokens_out,
+ max_tokens_out );
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_transform.h b/src/gallium/auxiliary/tgsi/tgsi_transform.h
new file mode 100644
index 0000000000..a121adbaef
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_transform.h
@@ -0,0 +1,92 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_TRANSFORM_H
+#define TGSI_TRANSFORM_H
+
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_build.h"
+
+
+
+/**
+ * Subclass this to add caller-specific data
+ */
+struct tgsi_transform_context
+{
+/**** PUBLIC ***/
+
+ /**
+ * User-defined callbacks invoked per instruction.
+ */
+ void (*transform_instruction)(struct tgsi_transform_context *ctx,
+ struct tgsi_full_instruction *inst);
+
+ void (*transform_declaration)(struct tgsi_transform_context *ctx,
+ struct tgsi_full_declaration *decl);
+
+ void (*transform_immediate)(struct tgsi_transform_context *ctx,
+ struct tgsi_full_immediate *imm);
+
+ /**
+ * Called at end of input program to allow caller to append extra
+ * instructions. Return number of tokens emitted.
+ */
+ void (*epilog)(struct tgsi_transform_context *ctx);
+
+
+/*** PRIVATE ***/
+
+ /**
+ * These are setup by tgsi_transform_shader() and cannot be overridden.
+ * Meant to be called from in the above user callback functions.
+ */
+ void (*emit_instruction)(struct tgsi_transform_context *ctx,
+ const struct tgsi_full_instruction *inst);
+ void (*emit_declaration)(struct tgsi_transform_context *ctx,
+ const struct tgsi_full_declaration *decl);
+ void (*emit_immediate)(struct tgsi_transform_context *ctx,
+ const struct tgsi_full_immediate *imm);
+
+ struct tgsi_header *header;
+ uint max_tokens_out;
+ struct tgsi_token *tokens_out;
+ uint ti;
+};
+
+
+
+extern int
+tgsi_transform_shader(const struct tgsi_token *tokens_in,
+ struct tgsi_token *tokens_out,
+ uint max_tokens_out,
+ struct tgsi_transform_context *ctx);
+
+
+#endif /* TGSI_TRANSFORM_H */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
new file mode 100644
index 0000000000..f7096bd8e2
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -0,0 +1,938 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_ureg.h"
+#include "tgsi/tgsi_info.h"
+#include "tgsi/tgsi_dump.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+union tgsi_any_token {
+ struct tgsi_version version;
+ struct tgsi_header header;
+ struct tgsi_processor processor;
+ struct tgsi_token token;
+ struct tgsi_declaration decl;
+ struct tgsi_declaration_range decl_range;
+ struct tgsi_declaration_semantic decl_semantic;
+ struct tgsi_immediate imm;
+ union tgsi_immediate_data imm_data;
+ struct tgsi_instruction insn;
+ struct tgsi_instruction_ext_nv insn_ext_nv;
+ struct tgsi_instruction_ext_label insn_ext_label;
+ struct tgsi_instruction_ext_texture insn_ext_texture;
+ struct tgsi_instruction_ext_predicate insn_ext_predicate;
+ struct tgsi_src_register src;
+ struct tgsi_src_register_ext_swz src_ext_swz;
+ struct tgsi_src_register_ext_mod src_ext_mod;
+ struct tgsi_dimension dim;
+ struct tgsi_dst_register dst;
+ struct tgsi_dst_register_ext_concode dst_ext_code;
+ struct tgsi_dst_register_ext_modulate dst_ext_mod;
+ struct tgsi_dst_register_ext_predicate dst_ext_pred;
+ unsigned value;
+};
+
+
+struct ureg_tokens {
+ union tgsi_any_token *tokens;
+ unsigned size;
+ unsigned order;
+ unsigned count;
+};
+
+#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS
+#define UREG_MAX_OUTPUT PIPE_MAX_ATTRIBS
+#define UREG_MAX_IMMEDIATE 32
+#define UREG_MAX_TEMP 256
+#define UREG_MAX_ADDR 2
+
+#define DOMAIN_DECL 0
+#define DOMAIN_INSN 1
+
+struct ureg_program
+{
+ unsigned processor;
+ struct pipe_context *pipe;
+
+ struct {
+ unsigned semantic_name;
+ unsigned semantic_index;
+ unsigned interp;
+ } input[UREG_MAX_INPUT];
+ unsigned nr_inputs;
+
+ struct {
+ unsigned semantic_name;
+ unsigned semantic_index;
+ } output[UREG_MAX_OUTPUT];
+ unsigned nr_outputs;
+
+ struct {
+ float v[4];
+ unsigned nr;
+ } immediate[UREG_MAX_IMMEDIATE];
+ unsigned nr_immediates;
+
+ struct ureg_src sampler[PIPE_MAX_SAMPLERS];
+ unsigned nr_samplers;
+
+ unsigned temps_active[UREG_MAX_TEMP / 32];
+ unsigned nr_temps;
+
+ unsigned nr_addrs;
+
+ unsigned nr_constants;
+ unsigned nr_instructions;
+
+ struct ureg_tokens domain[2];
+};
+
+static union tgsi_any_token error_tokens[32];
+
+static void tokens_error( struct ureg_tokens *tokens )
+{
+ tokens->tokens = error_tokens;
+ tokens->size = Elements(error_tokens);
+ tokens->count = 0;
+}
+
+
+static void tokens_expand( struct ureg_tokens *tokens,
+ unsigned count )
+{
+ unsigned old_size = tokens->size * sizeof(unsigned);
+
+ if (tokens->tokens == error_tokens)
+ goto fail;
+
+ while (tokens->count + count > tokens->size) {
+ tokens->size = (1 << ++tokens->order);
+ }
+
+ tokens->tokens = REALLOC(tokens->tokens,
+ old_size,
+ tokens->size * sizeof(unsigned));
+ if (tokens->tokens == NULL)
+ goto fail;
+
+ return;
+
+fail:
+ tokens_error(tokens);
+}
+
+static void set_bad( struct ureg_program *ureg )
+{
+ tokens_error(&ureg->domain[0]);
+}
+
+
+
+static union tgsi_any_token *get_tokens( struct ureg_program *ureg,
+ unsigned domain,
+ unsigned count )
+{
+ struct ureg_tokens *tokens = &ureg->domain[domain];
+ union tgsi_any_token *result;
+
+ if (tokens->count + count > tokens->size)
+ tokens_expand(tokens, count);
+
+ result = &tokens->tokens[tokens->count];
+ tokens->count += count;
+ return result;
+}
+
+
+static union tgsi_any_token *retrieve_token( struct ureg_program *ureg,
+ unsigned domain,
+ unsigned nr )
+{
+ if (ureg->domain[domain].tokens == error_tokens)
+ return &error_tokens[0];
+
+ return &ureg->domain[domain].tokens[nr];
+}
+
+
+
+static INLINE struct ureg_dst
+ureg_dst_register( unsigned file,
+ unsigned index )
+{
+ struct ureg_dst dst;
+
+ dst.File = file;
+ dst.WriteMask = TGSI_WRITEMASK_XYZW;
+ dst.Indirect = 0;
+ dst.IndirectIndex = 0;
+ dst.IndirectSwizzle = 0;
+ dst.Saturate = 0;
+ dst.Index = index;
+ dst.Pad1 = 0;
+ dst.Pad2 = 0;
+
+ return dst;
+}
+
+static INLINE struct ureg_src
+ureg_src_register( unsigned file,
+ unsigned index )
+{
+ struct ureg_src src;
+
+ src.File = file;
+ src.SwizzleX = TGSI_SWIZZLE_X;
+ src.SwizzleY = TGSI_SWIZZLE_Y;
+ src.SwizzleZ = TGSI_SWIZZLE_Z;
+ src.SwizzleW = TGSI_SWIZZLE_W;
+ src.Pad = 0;
+ src.Indirect = 0;
+ src.IndirectIndex = 0;
+ src.IndirectSwizzle = 0;
+ src.Absolute = 0;
+ src.Index = index;
+ src.Negate = 0;
+
+ return src;
+}
+
+
+
+
+static struct ureg_src
+ureg_DECL_input( struct ureg_program *ureg,
+ unsigned name,
+ unsigned index,
+ unsigned interp_mode )
+{
+ unsigned i;
+
+ for (i = 0; i < ureg->nr_inputs; i++) {
+ if (ureg->input[i].semantic_name == name &&
+ ureg->input[i].semantic_index == index)
+ goto out;
+ }
+
+ if (ureg->nr_inputs < UREG_MAX_INPUT) {
+ ureg->input[i].semantic_name = name;
+ ureg->input[i].semantic_index = index;
+ ureg->input[i].interp = interp_mode;
+ ureg->nr_inputs++;
+ }
+ else {
+ set_bad( ureg );
+ }
+
+out:
+ return ureg_src_register( TGSI_FILE_INPUT, i );
+}
+
+
+
+struct ureg_src
+ureg_DECL_fs_input( struct ureg_program *ureg,
+ unsigned name,
+ unsigned index,
+ unsigned interp )
+{
+ assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
+ return ureg_DECL_input( ureg, name, index, interp );
+}
+
+
+struct ureg_src
+ureg_DECL_vs_input( struct ureg_program *ureg,
+ unsigned name,
+ unsigned index )
+{
+ assert(ureg->processor == TGSI_PROCESSOR_VERTEX);
+ return ureg_DECL_input( ureg, name, index, TGSI_INTERPOLATE_CONSTANT );
+}
+
+
+struct ureg_dst
+ureg_DECL_output( struct ureg_program *ureg,
+ unsigned name,
+ unsigned index )
+{
+ unsigned i;
+
+ for (i = 0; i < ureg->nr_outputs; i++) {
+ if (ureg->output[i].semantic_name == name &&
+ ureg->output[i].semantic_index == index)
+ goto out;
+ }
+
+ if (ureg->nr_outputs < UREG_MAX_OUTPUT) {
+ ureg->output[i].semantic_name = name;
+ ureg->output[i].semantic_index = index;
+ ureg->nr_outputs++;
+ }
+ else {
+ set_bad( ureg );
+ }
+
+out:
+ return ureg_dst_register( TGSI_FILE_OUTPUT, i );
+}
+
+
+/* Returns a new constant register. Keep track of which have been
+ * referred to so that we can emit decls later.
+ *
+ * There is nothing in this code to bind this constant to any tracked
+ * value or manage any constant_buffer contents -- that's the
+ * resposibility of the calling code.
+ */
+struct ureg_src ureg_DECL_constant(struct ureg_program *ureg )
+{
+ return ureg_src_register( TGSI_FILE_CONSTANT, ureg->nr_constants++ );
+}
+
+
+/* Allocate a new temporary. Temporaries greater than UREG_MAX_TEMP
+ * are legal, but will not be released.
+ */
+struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
+{
+ unsigned i;
+
+ for (i = 0; i < UREG_MAX_TEMP; i += 32) {
+ int bit = ffs(~ureg->temps_active[i/32]);
+ if (bit != 0) {
+ i += bit - 1;
+ goto out;
+ }
+ }
+
+ /* No reusable temps, so allocate a new one:
+ */
+ i = ureg->nr_temps++;
+
+out:
+ if (i < UREG_MAX_TEMP)
+ ureg->temps_active[i/32] |= 1 << (i % 32);
+
+ if (i >= ureg->nr_temps)
+ ureg->nr_temps = i + 1;
+
+ return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
+}
+
+
+void ureg_release_temporary( struct ureg_program *ureg,
+ struct ureg_dst tmp )
+{
+ if(tmp.File == TGSI_FILE_TEMPORARY)
+ if (tmp.Index < UREG_MAX_TEMP)
+ ureg->temps_active[tmp.Index/32] &= ~(1 << (tmp.Index % 32));
+}
+
+
+/* Allocate a new address register.
+ */
+struct ureg_dst ureg_DECL_address( struct ureg_program *ureg )
+{
+ if (ureg->nr_addrs < UREG_MAX_ADDR)
+ return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ );
+
+ assert( 0 );
+ return ureg_dst_register( TGSI_FILE_ADDRESS, 0 );
+}
+
+/* Allocate a new sampler.
+ */
+struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
+ unsigned nr )
+{
+ unsigned i;
+
+ for (i = 0; i < ureg->nr_samplers; i++)
+ if (ureg->sampler[i].Index == nr)
+ return ureg->sampler[i];
+
+ if (i < PIPE_MAX_SAMPLERS) {
+ ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr );
+ ureg->nr_samplers++;
+ return ureg->sampler[i];
+ }
+
+ assert( 0 );
+ return ureg->sampler[0];
+}
+
+
+
+
+static int match_or_expand_immediate( const float *v,
+ unsigned nr,
+ float *v2,
+ unsigned *nr2,
+ unsigned *swizzle )
+{
+ unsigned i, j;
+
+ *swizzle = 0;
+
+ for (i = 0; i < nr; i++) {
+ boolean found = FALSE;
+
+ for (j = 0; j < *nr2 && !found; j++) {
+ if (v[i] == v2[j]) {
+ *swizzle |= j << (i * 2);
+ found = TRUE;
+ }
+ }
+
+ if (!found) {
+ if (*nr2 >= 4)
+ return FALSE;
+
+ v2[*nr2] = v[i];
+ *swizzle |= *nr2 << (i * 2);
+ (*nr2)++;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+
+struct ureg_src ureg_DECL_immediate( struct ureg_program *ureg,
+ const float *v,
+ unsigned nr )
+{
+ unsigned i, j;
+ unsigned swizzle;
+
+ /* Could do a first pass where we examine all existing immediates
+ * without expanding.
+ */
+
+ for (i = 0; i < ureg->nr_immediates; i++) {
+ if (match_or_expand_immediate( v,
+ nr,
+ ureg->immediate[i].v,
+ &ureg->immediate[i].nr,
+ &swizzle ))
+ goto out;
+ }
+
+ if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) {
+ i = ureg->nr_immediates++;
+ if (match_or_expand_immediate( v,
+ nr,
+ ureg->immediate[i].v,
+ &ureg->immediate[i].nr,
+ &swizzle ))
+ goto out;
+ }
+
+ set_bad( ureg );
+
+out:
+ /* Make sure that all referenced elements are from this immediate.
+ * Has the effect of making size-one immediates into scalars.
+ */
+ for (j = nr; j < 4; j++)
+ swizzle |= (swizzle & 0x3) << (j * 2);
+
+ return ureg_swizzle( ureg_src_register( TGSI_FILE_IMMEDIATE, i ),
+ (swizzle >> 0) & 0x3,
+ (swizzle >> 2) & 0x3,
+ (swizzle >> 4) & 0x3,
+ (swizzle >> 6) & 0x3);
+}
+
+
+void
+ureg_emit_src( struct ureg_program *ureg,
+ struct ureg_src src )
+{
+ unsigned size = (1 +
+ (src.Absolute ? 1 : 0) +
+ (src.Indirect ? 1 : 0));
+
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
+ unsigned n = 0;
+
+ assert(src.File != TGSI_FILE_NULL);
+ assert(src.File != TGSI_FILE_OUTPUT);
+ assert(src.File < TGSI_FILE_COUNT);
+
+ out[n].value = 0;
+ out[n].src.File = src.File;
+ out[n].src.SwizzleX = src.SwizzleX;
+ out[n].src.SwizzleY = src.SwizzleY;
+ out[n].src.SwizzleZ = src.SwizzleZ;
+ out[n].src.SwizzleW = src.SwizzleW;
+ out[n].src.Index = src.Index;
+ out[n].src.Negate = src.Negate;
+ n++;
+
+ if (src.Absolute) {
+ out[0].src.Extended = 1;
+ out[0].src.Negate = 0;
+ out[n].value = 0;
+ out[n].src_ext_mod.Type = TGSI_SRC_REGISTER_EXT_TYPE_MOD;
+ out[n].src_ext_mod.Absolute = 1;
+ out[n].src_ext_mod.Negate = src.Negate;
+ n++;
+ }
+
+ if (src.Indirect) {
+ out[0].src.Indirect = 1;
+ out[n].value = 0;
+ out[n].src.File = TGSI_FILE_ADDRESS;
+ out[n].src.SwizzleX = src.IndirectSwizzle;
+ out[n].src.SwizzleY = src.IndirectSwizzle;
+ out[n].src.SwizzleZ = src.IndirectSwizzle;
+ out[n].src.SwizzleW = src.IndirectSwizzle;
+ out[n].src.Index = src.IndirectIndex;
+ n++;
+ }
+
+ assert(n == size);
+}
+
+
+void
+ureg_emit_dst( struct ureg_program *ureg,
+ struct ureg_dst dst )
+{
+ unsigned size = (1 +
+ (dst.Indirect ? 1 : 0));
+
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
+ unsigned n = 0;
+
+ assert(dst.File != TGSI_FILE_NULL);
+ assert(dst.File != TGSI_FILE_CONSTANT);
+ assert(dst.File != TGSI_FILE_INPUT);
+ assert(dst.File != TGSI_FILE_SAMPLER);
+ 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;
+ out[n].dst.Indirect = dst.Indirect;
+ out[n].dst.Index = dst.Index;
+ n++;
+
+ if (dst.Indirect) {
+ out[n].value = 0;
+ out[n].src.File = TGSI_FILE_ADDRESS;
+ out[n].src.SwizzleX = dst.IndirectSwizzle;
+ out[n].src.SwizzleY = dst.IndirectSwizzle;
+ out[n].src.SwizzleZ = dst.IndirectSwizzle;
+ out[n].src.SwizzleW = dst.IndirectSwizzle;
+ out[n].src.Index = dst.IndirectIndex;
+ n++;
+ }
+
+ assert(n == size);
+}
+
+
+
+unsigned
+ureg_emit_insn(struct ureg_program *ureg,
+ unsigned opcode,
+ boolean saturate,
+ unsigned num_dst,
+ unsigned num_src )
+{
+ union tgsi_any_token *out;
+
+ out = get_tokens( ureg, DOMAIN_INSN, 1 );
+ out[0].value = 0;
+ out[0].insn.Type = TGSI_TOKEN_TYPE_INSTRUCTION;
+ out[0].insn.NrTokens = 0;
+ out[0].insn.Opcode = opcode;
+ out[0].insn.Saturate = saturate;
+ out[0].insn.NumDstRegs = num_dst;
+ out[0].insn.NumSrcRegs = num_src;
+ out[0].insn.Padding = 0;
+ out[0].insn.Extended = 0;
+
+ ureg->nr_instructions++;
+
+ return ureg->domain[DOMAIN_INSN].count - 1;
+}
+
+
+void
+ureg_emit_label(struct ureg_program *ureg,
+ unsigned insn_token,
+ unsigned *label_token )
+{
+ union tgsi_any_token *out, *insn;
+
+ if(!label_token)
+ return;
+
+ out = get_tokens( ureg, DOMAIN_INSN, 1 );
+ insn = retrieve_token( ureg, DOMAIN_INSN, insn_token );
+
+ insn->insn.Extended = 1;
+
+ out[0].value = 0;
+ out[0].insn_ext_label.Type = TGSI_INSTRUCTION_EXT_TYPE_LABEL;
+
+ *label_token = ureg->domain[DOMAIN_INSN].count - 1;
+}
+
+/* Will return a number which can be used in a label to point to the
+ * next instruction to be emitted.
+ */
+unsigned
+ureg_get_instruction_number( struct ureg_program *ureg )
+{
+ return ureg->nr_instructions;
+}
+
+/* Patch a given label (expressed as a token number) to point to a
+ * given instruction (expressed as an instruction number).
+ */
+void
+ureg_fixup_label(struct ureg_program *ureg,
+ unsigned label_token,
+ unsigned instruction_number )
+{
+ union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token );
+
+ assert(out->insn_ext_label.Type == TGSI_INSTRUCTION_EXT_TYPE_LABEL);
+ out->insn_ext_label.Label = instruction_number;
+}
+
+
+void
+ureg_emit_texture(struct ureg_program *ureg,
+ unsigned insn_token,
+ unsigned target )
+{
+ union tgsi_any_token *out, *insn;
+
+ out = get_tokens( ureg, DOMAIN_INSN, 1 );
+ insn = retrieve_token( ureg, DOMAIN_INSN, insn_token );
+
+ insn->insn.Extended = 1;
+
+ out[0].value = 0;
+ out[0].insn_ext_texture.Type = TGSI_INSTRUCTION_EXT_TYPE_TEXTURE;
+ out[0].insn_ext_texture.Texture = target;
+}
+
+
+void
+ureg_fixup_insn_size(struct ureg_program *ureg,
+ unsigned insn )
+{
+ union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn );
+
+ assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
+ out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1;
+}
+
+
+void
+ureg_insn(struct ureg_program *ureg,
+ unsigned opcode,
+ const struct ureg_dst *dst,
+ unsigned nr_dst,
+ const struct ureg_src *src,
+ unsigned nr_src )
+{
+ unsigned insn, i;
+ boolean saturate;
+
+#ifdef DEBUG
+ {
+ const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
+ assert(info);
+ if(info) {
+ assert(nr_dst == info->num_dst);
+ assert(nr_src == info->num_src);
+ }
+ }
+#endif
+
+ saturate = nr_dst ? dst[0].Saturate : FALSE;
+
+ insn = ureg_emit_insn( ureg, opcode, saturate, nr_dst, nr_src );
+
+ for (i = 0; i < nr_dst; i++)
+ ureg_emit_dst( ureg, dst[i] );
+
+ for (i = 0; i < nr_src; i++)
+ ureg_emit_src( ureg, src[i] );
+
+ ureg_fixup_insn_size( ureg, insn );
+}
+
+
+
+static void emit_decl( struct ureg_program *ureg,
+ unsigned file,
+ unsigned index,
+ unsigned semantic_name,
+ unsigned semantic_index,
+ unsigned interp )
+{
+ 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 = file;
+ out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */
+ out[0].decl.Interpolate = interp;
+ out[0].decl.Semantic = 1;
+
+ out[1].value = 0;
+ out[1].decl_range.First =
+ out[1].decl_range.Last = index;
+
+ out[2].value = 0;
+ out[2].decl_semantic.SemanticName = semantic_name;
+ out[2].decl_semantic.SemanticIndex = semantic_index;
+
+}
+
+
+static void emit_decl_range( struct ureg_program *ureg,
+ unsigned file,
+ unsigned first,
+ unsigned count )
+{
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
+
+ out[0].value = 0;
+ out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
+ out[0].decl.NrTokens = 2;
+ out[0].decl.File = file;
+ out[0].decl.UsageMask = 0xf;
+ out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT;
+ out[0].decl.Semantic = 0;
+
+ out[1].value = 0;
+ out[1].decl_range.First = first;
+ out[1].decl_range.Last = first + count - 1;
+}
+
+static void emit_immediate( struct ureg_program *ureg,
+ const float *v )
+{
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 );
+
+ out[0].value = 0;
+ out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
+ out[0].imm.NrTokens = 5;
+ out[0].imm.DataType = TGSI_IMM_FLOAT32;
+ out[0].imm.Padding = 0;
+ out[0].imm.Extended = 0;
+
+ out[1].imm_data.Float = v[0];
+ out[2].imm_data.Float = v[1];
+ out[3].imm_data.Float = v[2];
+ out[4].imm_data.Float = v[3];
+}
+
+
+
+
+static void emit_decls( struct ureg_program *ureg )
+{
+ unsigned i;
+
+ for (i = 0; i < ureg->nr_inputs; i++) {
+ emit_decl( ureg,
+ TGSI_FILE_INPUT,
+ i,
+ ureg->input[i].semantic_name,
+ ureg->input[i].semantic_index,
+ ureg->input[i].interp );
+ }
+
+ for (i = 0; i < ureg->nr_outputs; i++) {
+ emit_decl( ureg,
+ TGSI_FILE_OUTPUT,
+ i,
+ ureg->output[i].semantic_name,
+ ureg->output[i].semantic_index,
+ TGSI_INTERPOLATE_CONSTANT );
+ }
+
+ for (i = 0; i < ureg->nr_samplers; i++) {
+ emit_decl_range( ureg,
+ TGSI_FILE_SAMPLER,
+ ureg->sampler[i].Index, 1 );
+ }
+
+ if (ureg->nr_constants) {
+ emit_decl_range( ureg,
+ TGSI_FILE_CONSTANT,
+ 0, ureg->nr_constants );
+ }
+
+ if (ureg->nr_temps) {
+ emit_decl_range( ureg,
+ TGSI_FILE_TEMPORARY,
+ 0, ureg->nr_temps );
+ }
+
+ if (ureg->nr_addrs) {
+ emit_decl_range( ureg,
+ TGSI_FILE_ADDRESS,
+ 0, ureg->nr_addrs );
+ }
+
+ for (i = 0; i < ureg->nr_immediates; i++) {
+ emit_immediate( ureg,
+ ureg->immediate[i].v );
+ }
+}
+
+/* Append the instruction tokens onto the declarations to build a
+ * contiguous stream suitable to send to the driver.
+ */
+static void copy_instructions( struct ureg_program *ureg )
+{
+ unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count;
+ union tgsi_any_token *out = get_tokens( ureg,
+ DOMAIN_DECL,
+ nr_tokens );
+
+ memcpy(out,
+ ureg->domain[DOMAIN_INSN].tokens,
+ nr_tokens * sizeof out[0] );
+}
+
+
+static void
+fixup_header_size(struct ureg_program *ureg)
+{
+ union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 1 );
+
+ out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 3;
+}
+
+
+static void
+emit_header( struct ureg_program *ureg )
+{
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 );
+
+ out[0].version.MajorVersion = 1;
+ out[0].version.MinorVersion = 1;
+ out[0].version.Padding = 0;
+
+ out[1].header.HeaderSize = 2;
+ out[1].header.BodySize = 0;
+
+ out[2].processor.Processor = ureg->processor;
+ out[2].processor.Padding = 0;
+}
+
+
+const struct tgsi_token *ureg_finalize( struct ureg_program *ureg )
+{
+ const struct tgsi_token *tokens;
+
+ emit_header( ureg );
+ emit_decls( ureg );
+ copy_instructions( ureg );
+ fixup_header_size( ureg );
+
+ if (ureg->domain[0].tokens == error_tokens ||
+ ureg->domain[1].tokens == error_tokens) {
+ debug_printf("%s: error in generated shader\n", __FUNCTION__);
+ assert(0);
+ return NULL;
+ }
+
+ tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
+
+ if (0) {
+ debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__,
+ ureg->domain[DOMAIN_DECL].count);
+ tgsi_dump( tokens, 0 );
+ }
+
+ return tokens;
+}
+
+
+void *ureg_create_shader( struct ureg_program *ureg,
+ struct pipe_context *pipe )
+{
+ struct pipe_shader_state state;
+
+ state.tokens = ureg_finalize(ureg);
+ if(!state.tokens)
+ return NULL;
+
+ if (ureg->processor == TGSI_PROCESSOR_VERTEX)
+ return pipe->create_vs_state( pipe, &state );
+ else
+ return pipe->create_fs_state( pipe, &state );
+}
+
+
+
+
+struct ureg_program *ureg_create( unsigned processor )
+{
+ struct ureg_program *ureg = CALLOC_STRUCT( ureg_program );
+ if (ureg == NULL)
+ return NULL;
+
+ ureg->processor = processor;
+ return ureg;
+}
+
+
+void ureg_destroy( struct ureg_program *ureg )
+{
+ unsigned i;
+
+ for (i = 0; i < Elements(ureg->domain); i++) {
+ if (ureg->domain[i].tokens &&
+ ureg->domain[i].tokens != error_tokens)
+ FREE(ureg->domain[i].tokens);
+ }
+
+ FREE(ureg);
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
new file mode 100644
index 0000000000..acbca59040
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
@@ -0,0 +1,590 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE, INC 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 TGSI_UREG_H
+#define TGSI_UREG_H
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_shader_tokens.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ureg_program;
+
+/* Almost a tgsi_src_register, but we need to pull in the Absolute
+ * flag from the _ext token. Indirect flag always implies ADDR[0].
+ */
+struct ureg_src
+{
+ unsigned File : 4; /* TGSI_FILE_ */
+ unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
+ unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
+ unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
+ unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
+ unsigned Pad : 1; /* BOOL */
+ unsigned Indirect : 1; /* BOOL */
+ unsigned Absolute : 1; /* BOOL */
+ int Index : 16; /* SINT */
+ unsigned Negate : 1; /* BOOL */
+ int IndirectIndex : 16; /* SINT */
+ int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
+};
+
+/* Very similar to a tgsi_dst_register, removing unsupported fields
+ * and adding a Saturate flag. It's easier to push saturate into the
+ * destination register than to try and create a _SAT varient of each
+ * instruction function.
+ */
+struct ureg_dst
+{
+ unsigned File : 4; /* TGSI_FILE_ */
+ unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
+ unsigned Indirect : 1; /* BOOL */
+ unsigned Saturate : 1; /* BOOL */
+ int Index : 16; /* SINT */
+ unsigned Pad1 : 5;
+ unsigned Pad2 : 1; /* BOOL */
+ int IndirectIndex : 16; /* SINT */
+ int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
+};
+
+struct pipe_context;
+
+struct ureg_program *
+ureg_create( unsigned processor );
+
+const struct tgsi_token *
+ureg_finalize( struct ureg_program * );
+
+void *
+ureg_create_shader( struct ureg_program *,
+ struct pipe_context *pipe );
+
+void
+ureg_destroy( struct ureg_program * );
+
+
+/***********************************************************************
+ * Convenience routine:
+ */
+static INLINE void *
+ureg_create_shader_and_destroy( struct ureg_program *p,
+ struct pipe_context *pipe )
+{
+ void *result = ureg_create_shader( p, pipe );
+ ureg_destroy( p );
+ return result;
+}
+
+
+
+/***********************************************************************
+ * Build shader declarations:
+ */
+
+struct ureg_src
+ureg_DECL_fs_input( struct ureg_program *,
+ unsigned semantic_name,
+ unsigned semantic_index,
+ unsigned interp_mode );
+
+struct ureg_src
+ureg_DECL_vs_input( struct ureg_program *,
+ unsigned semantic_name,
+ unsigned semantic_index );
+
+struct ureg_dst
+ureg_DECL_output( struct ureg_program *,
+ unsigned semantic_name,
+ unsigned semantic_index );
+
+struct ureg_src
+ureg_DECL_immediate( struct ureg_program *,
+ const float *v,
+ unsigned nr );
+
+struct ureg_src
+ureg_DECL_constant( struct ureg_program * );
+
+struct ureg_dst
+ureg_DECL_temporary( struct ureg_program * );
+
+void
+ureg_release_temporary( struct ureg_program *ureg,
+ struct ureg_dst tmp );
+
+struct ureg_dst
+ureg_DECL_address( struct ureg_program * );
+
+/* Supply an index to the sampler declaration as this is the hook to
+ * the external pipe_sampler state. Users of this function probably
+ * don't want just any sampler, but a specific one which they've set
+ * up state for in the context.
+ */
+struct ureg_src
+ureg_DECL_sampler( struct ureg_program *,
+ unsigned index );
+
+
+static INLINE struct ureg_src
+ureg_imm4f( struct ureg_program *ureg,
+ float a, float b,
+ float c, float d)
+{
+ float v[4];
+ v[0] = a;
+ v[1] = b;
+ v[2] = c;
+ v[3] = d;
+ return ureg_DECL_immediate( ureg, v, 4 );
+}
+
+static INLINE struct ureg_src
+ureg_imm3f( struct ureg_program *ureg,
+ float a, float b,
+ float c)
+{
+ float v[3];
+ v[0] = a;
+ v[1] = b;
+ v[2] = c;
+ return ureg_DECL_immediate( ureg, v, 3 );
+}
+
+static INLINE struct ureg_src
+ureg_imm2f( struct ureg_program *ureg,
+ float a, float b)
+{
+ float v[2];
+ v[0] = a;
+ v[1] = b;
+ return ureg_DECL_immediate( ureg, v, 2 );
+}
+
+static INLINE struct ureg_src
+ureg_imm1f( struct ureg_program *ureg,
+ float a)
+{
+ float v[1];
+ v[0] = a;
+ return ureg_DECL_immediate( ureg, v, 1 );
+}
+
+/***********************************************************************
+ * Functions for patching up labels
+ */
+
+
+/* Will return a number which can be used in a label to point to the
+ * next instruction to be emitted.
+ */
+unsigned
+ureg_get_instruction_number( struct ureg_program *ureg );
+
+
+/* Patch a given label (expressed as a token number) to point to a
+ * given instruction (expressed as an instruction number).
+ *
+ * Labels are obtained from instruction emitters, eg ureg_CAL().
+ * Instruction numbers are obtained from ureg_get_instruction_number(),
+ * above.
+ */
+void
+ureg_fixup_label(struct ureg_program *ureg,
+ unsigned label_token,
+ unsigned instruction_number );
+
+
+/* Generic instruction emitter. Use if you need to pass the opcode as
+ * a parameter, rather than using the emit_OP() varients below.
+ */
+void
+ureg_insn(struct ureg_program *ureg,
+ unsigned opcode,
+ const struct ureg_dst *dst,
+ unsigned nr_dst,
+ const struct ureg_src *src,
+ unsigned nr_src );
+
+
+/***********************************************************************
+ * Internal instruction helpers, don't call these directly:
+ */
+
+unsigned
+ureg_emit_insn(struct ureg_program *ureg,
+ unsigned opcode,
+ boolean saturate,
+ unsigned num_dst,
+ unsigned num_src );
+
+void
+ureg_emit_label(struct ureg_program *ureg,
+ unsigned insn_token,
+ unsigned *label_token );
+
+void
+ureg_emit_texture(struct ureg_program *ureg,
+ unsigned insn_token,
+ unsigned target );
+
+void
+ureg_emit_dst( struct ureg_program *ureg,
+ struct ureg_dst dst );
+
+void
+ureg_emit_src( struct ureg_program *ureg,
+ struct ureg_src src );
+
+void
+ureg_fixup_insn_size(struct ureg_program *ureg,
+ unsigned insn );
+
+
+#define OP00( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP01( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_src src ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
+ ureg_emit_src( ureg, src ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP00_LBL( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ unsigned *label_token ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
+ ureg_emit_label( ureg, insn, label_token ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP01_LBL( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_src src, \
+ unsigned *label_token ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
+ ureg_emit_label( ureg, insn, label_token ); \
+ ureg_emit_src( ureg, src ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP10( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+
+#define OP11( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst, \
+ struct ureg_src src ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_emit_src( ureg, src ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP12( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst, \
+ struct ureg_src src0, \
+ struct ureg_src src1 ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_emit_src( ureg, src0 ); \
+ ureg_emit_src( ureg, src1 ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP12_TEX( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst, \
+ unsigned target, \
+ struct ureg_src src0, \
+ struct ureg_src src1 ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
+ ureg_emit_texture( ureg, insn, target ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_emit_src( ureg, src0 ); \
+ ureg_emit_src( ureg, src1 ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP13( 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 ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_emit_src( ureg, src0 ); \
+ ureg_emit_src( ureg, src1 ); \
+ ureg_emit_src( ureg, src2 ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP14_TEX( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst, \
+ unsigned target, \
+ 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, 1, 4 ); \
+ ureg_emit_texture( ureg, insn, target ); \
+ 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 ); \
+}
+
+
+/* Use a template include to generate a correctly-typed ureg_OP()
+ * function for each TGSI opcode:
+ */
+#include "tgsi_opcode_tmp.h"
+
+
+/***********************************************************************
+ * Inline helpers for manipulating register structs:
+ */
+static INLINE struct ureg_src
+ureg_negate( struct ureg_src reg )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ reg.Negate ^= 1;
+ return reg;
+}
+
+static INLINE struct ureg_src
+ureg_abs( struct ureg_src reg )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ reg.Absolute = 1;
+ reg.Negate = 0;
+ return reg;
+}
+
+static INLINE struct ureg_src
+ureg_swizzle( struct ureg_src reg,
+ int x, int y, int z, int w )
+{
+ unsigned swz = ( (reg.SwizzleX << 0) |
+ (reg.SwizzleY << 2) |
+ (reg.SwizzleZ << 4) |
+ (reg.SwizzleW << 6));
+
+ assert(reg.File != TGSI_FILE_NULL);
+ assert(x < 4);
+ assert(y < 4);
+ assert(z < 4);
+ assert(w < 4);
+
+ reg.SwizzleX = (swz >> (x*2)) & 0x3;
+ reg.SwizzleY = (swz >> (y*2)) & 0x3;
+ reg.SwizzleZ = (swz >> (z*2)) & 0x3;
+ reg.SwizzleW = (swz >> (w*2)) & 0x3;
+ return reg;
+}
+
+static INLINE struct ureg_src
+ureg_scalar( struct ureg_src reg, int x )
+{
+ return ureg_swizzle(reg, x, x, x, x);
+}
+
+static INLINE struct ureg_dst
+ureg_writemask( struct ureg_dst reg,
+ unsigned writemask )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ reg.WriteMask &= writemask;
+ return reg;
+}
+
+static INLINE struct ureg_dst
+ureg_saturate( struct ureg_dst reg )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ reg.Saturate = 1;
+ return reg;
+}
+
+static INLINE struct ureg_dst
+ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ assert(addr.File == TGSI_FILE_ADDRESS);
+ reg.Indirect = 1;
+ reg.IndirectIndex = addr.Index;
+ reg.IndirectSwizzle = addr.SwizzleX;
+ return reg;
+}
+
+static INLINE struct ureg_src
+ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ assert(addr.File == TGSI_FILE_ADDRESS);
+ reg.Indirect = 1;
+ reg.IndirectIndex = addr.Index;
+ reg.IndirectSwizzle = addr.SwizzleX;
+ return reg;
+}
+
+static INLINE struct ureg_dst
+ureg_dst( struct ureg_src src )
+{
+ struct ureg_dst dst;
+
+ dst.File = src.File;
+ dst.WriteMask = TGSI_WRITEMASK_XYZW;
+ dst.Indirect = src.Indirect;
+ dst.IndirectIndex = src.IndirectIndex;
+ dst.IndirectSwizzle = src.IndirectSwizzle;
+ dst.Saturate = 0;
+ dst.Index = src.Index;
+ dst.Pad1 = 0;
+ dst.Pad2 = 0;
+
+ return dst;
+}
+
+static INLINE struct ureg_src
+ureg_src( struct ureg_dst dst )
+{
+ struct ureg_src src;
+
+ src.File = dst.File;
+ src.SwizzleX = TGSI_SWIZZLE_X;
+ src.SwizzleY = TGSI_SWIZZLE_Y;
+ src.SwizzleZ = TGSI_SWIZZLE_Z;
+ src.SwizzleW = TGSI_SWIZZLE_W;
+ src.Pad = 0;
+ src.Indirect = dst.Indirect;
+ src.IndirectIndex = dst.IndirectIndex;
+ src.IndirectSwizzle = dst.IndirectSwizzle;
+ src.Absolute = 0;
+ src.Index = dst.Index;
+ src.Negate = 0;
+
+ return src;
+}
+
+
+
+static INLINE struct ureg_dst
+ureg_dst_undef( void )
+{
+ struct ureg_dst dst;
+
+ dst.File = TGSI_FILE_NULL;
+ dst.WriteMask = 0;
+ dst.Indirect = 0;
+ dst.IndirectIndex = 0;
+ dst.IndirectSwizzle = 0;
+ dst.Saturate = 0;
+ dst.Index = 0;
+ dst.Pad1 = 0;
+ dst.Pad2 = 0;
+
+ return dst;
+}
+
+static INLINE struct ureg_src
+ureg_src_undef( void )
+{
+ struct ureg_src src;
+
+ src.File = TGSI_FILE_NULL;
+ src.SwizzleX = 0;
+ src.SwizzleY = 0;
+ src.SwizzleZ = 0;
+ src.SwizzleW = 0;
+ src.Pad = 0;
+ src.Indirect = 0;
+ src.IndirectIndex = 0;
+ src.IndirectSwizzle = 0;
+ src.Absolute = 0;
+ src.Index = 0;
+ src.Negate = 0;
+
+ return src;
+}
+
+static INLINE boolean
+ureg_src_is_undef( struct ureg_src src )
+{
+ return src.File == TGSI_FILE_NULL;
+}
+
+static INLINE boolean
+ureg_dst_is_undef( struct ureg_dst dst )
+{
+ return dst.File == TGSI_FILE_NULL;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.c b/src/gallium/auxiliary/tgsi/tgsi_util.c
new file mode 100644
index 0000000000..71f8a6ca40
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_util.c
@@ -0,0 +1,299 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_debug.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi_parse.h"
+#include "tgsi_build.h"
+#include "tgsi_util.h"
+
+union pointer_hack
+{
+ void *pointer;
+ uint64_t uint64;
+};
+
+void *
+tgsi_align_128bit(
+ void *unaligned )
+{
+ union pointer_hack ph;
+
+ ph.uint64 = 0;
+ ph.pointer = unaligned;
+ ph.uint64 = (ph.uint64 + 15) & ~15;
+ return ph.pointer;
+}
+
+unsigned
+tgsi_util_get_src_register_swizzle(
+ const struct tgsi_src_register *reg,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ return reg->SwizzleX;
+ case 1:
+ return reg->SwizzleY;
+ case 2:
+ return reg->SwizzleZ;
+ case 3:
+ return reg->SwizzleW;
+ default:
+ assert( 0 );
+ }
+ return 0;
+}
+
+unsigned
+tgsi_util_get_src_register_extswizzle(
+ const struct tgsi_src_register_ext_swz *reg,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ return reg->ExtSwizzleX;
+ case 1:
+ return reg->ExtSwizzleY;
+ case 2:
+ return reg->ExtSwizzleZ;
+ case 3:
+ return reg->ExtSwizzleW;
+ default:
+ assert( 0 );
+ }
+ return 0;
+}
+
+unsigned
+tgsi_util_get_full_src_register_extswizzle(
+ const struct tgsi_full_src_register *reg,
+ unsigned component )
+{
+ unsigned swizzle;
+
+ /*
+ * First, calculate the extended swizzle for a given channel. This will give
+ * us either a channel index into the simple swizzle or a constant 1 or 0.
+ */
+ swizzle = tgsi_util_get_src_register_extswizzle(
+ &reg->SrcRegisterExtSwz,
+ component );
+
+ assert (TGSI_SWIZZLE_X == TGSI_EXTSWIZZLE_X);
+ assert (TGSI_SWIZZLE_Y == TGSI_EXTSWIZZLE_Y);
+ assert (TGSI_SWIZZLE_Z == TGSI_EXTSWIZZLE_Z);
+ assert (TGSI_SWIZZLE_W == TGSI_EXTSWIZZLE_W);
+ assert (TGSI_EXTSWIZZLE_ZERO > TGSI_SWIZZLE_W);
+ assert (TGSI_EXTSWIZZLE_ONE > TGSI_SWIZZLE_W);
+
+ /*
+ * Second, calculate the simple swizzle for the unswizzled channel index.
+ * Leave the constants intact, they are not affected by the simple swizzle.
+ */
+ if( swizzle <= TGSI_SWIZZLE_W ) {
+ swizzle = tgsi_util_get_src_register_swizzle(
+ &reg->SrcRegister,
+ swizzle );
+ }
+
+ return swizzle;
+}
+
+void
+tgsi_util_set_src_register_swizzle(
+ struct tgsi_src_register *reg,
+ unsigned swizzle,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ reg->SwizzleX = swizzle;
+ break;
+ case 1:
+ reg->SwizzleY = swizzle;
+ break;
+ case 2:
+ reg->SwizzleZ = swizzle;
+ break;
+ case 3:
+ reg->SwizzleW = swizzle;
+ break;
+ default:
+ assert( 0 );
+ }
+}
+
+void
+tgsi_util_set_src_register_extswizzle(
+ struct tgsi_src_register_ext_swz *reg,
+ unsigned swizzle,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ reg->ExtSwizzleX = swizzle;
+ break;
+ case 1:
+ reg->ExtSwizzleY = swizzle;
+ break;
+ case 2:
+ reg->ExtSwizzleZ = swizzle;
+ break;
+ case 3:
+ reg->ExtSwizzleW = swizzle;
+ break;
+ default:
+ assert( 0 );
+ }
+}
+
+unsigned
+tgsi_util_get_src_register_extnegate(
+ const struct tgsi_src_register_ext_swz *reg,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ return reg->NegateX;
+ case 1:
+ return reg->NegateY;
+ case 2:
+ return reg->NegateZ;
+ case 3:
+ return reg->NegateW;
+ default:
+ assert( 0 );
+ }
+ return 0;
+}
+
+void
+tgsi_util_set_src_register_extnegate(
+ struct tgsi_src_register_ext_swz *reg,
+ unsigned negate,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ reg->NegateX = negate;
+ break;
+ case 1:
+ reg->NegateY = negate;
+ break;
+ case 2:
+ reg->NegateZ = negate;
+ break;
+ case 3:
+ reg->NegateW = negate;
+ break;
+ default:
+ assert( 0 );
+ }
+}
+
+unsigned
+tgsi_util_get_full_src_register_sign_mode(
+ const struct tgsi_full_src_register *reg,
+ unsigned component )
+{
+ unsigned sign_mode;
+
+ if( reg->SrcRegisterExtMod.Absolute ) {
+ /* Consider only the post-abs negation. */
+
+ if( reg->SrcRegisterExtMod.Negate ) {
+ sign_mode = TGSI_UTIL_SIGN_SET;
+ }
+ else {
+ sign_mode = TGSI_UTIL_SIGN_CLEAR;
+ }
+ }
+ else {
+ /* Accumulate the three negations. */
+
+ unsigned negate;
+
+ negate = reg->SrcRegister.Negate;
+ if( tgsi_util_get_src_register_extnegate( &reg->SrcRegisterExtSwz, component ) ) {
+ negate = !negate;
+ }
+ if( reg->SrcRegisterExtMod.Negate ) {
+ negate = !negate;
+ }
+
+ if( negate ) {
+ sign_mode = TGSI_UTIL_SIGN_TOGGLE;
+ }
+ else {
+ sign_mode = TGSI_UTIL_SIGN_KEEP;
+ }
+ }
+
+ return sign_mode;
+}
+
+void
+tgsi_util_set_full_src_register_sign_mode(
+ struct tgsi_full_src_register *reg,
+ unsigned sign_mode )
+{
+ reg->SrcRegisterExtSwz.NegateX = 0;
+ reg->SrcRegisterExtSwz.NegateY = 0;
+ reg->SrcRegisterExtSwz.NegateZ = 0;
+ reg->SrcRegisterExtSwz.NegateW = 0;
+
+ switch (sign_mode)
+ {
+ case TGSI_UTIL_SIGN_CLEAR:
+ reg->SrcRegister.Negate = 0;
+ reg->SrcRegisterExtMod.Absolute = 1;
+ reg->SrcRegisterExtMod.Negate = 0;
+ break;
+
+ case TGSI_UTIL_SIGN_SET:
+ reg->SrcRegister.Negate = 0;
+ reg->SrcRegisterExtMod.Absolute = 1;
+ reg->SrcRegisterExtMod.Negate = 1;
+ break;
+
+ case TGSI_UTIL_SIGN_TOGGLE:
+ reg->SrcRegister.Negate = 1;
+ reg->SrcRegisterExtMod.Absolute = 0;
+ reg->SrcRegisterExtMod.Negate = 0;
+ break;
+
+ case TGSI_UTIL_SIGN_KEEP:
+ reg->SrcRegister.Negate = 0;
+ reg->SrcRegisterExtMod.Absolute = 0;
+ reg->SrcRegisterExtMod.Negate = 0;
+ break;
+
+ default:
+ assert( 0 );
+ }
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.h b/src/gallium/auxiliary/tgsi/tgsi_util.h
new file mode 100644
index 0000000000..21eb656327
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_util.h
@@ -0,0 +1,100 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_UTIL_H
+#define TGSI_UTIL_H
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct tgsi_src_register;
+struct tgsi_src_register_ext_swz;
+struct tgsi_full_src_register;
+
+void *
+tgsi_align_128bit(
+ void *unaligned );
+
+unsigned
+tgsi_util_get_src_register_swizzle(
+ const struct tgsi_src_register *reg,
+ unsigned component );
+
+unsigned
+tgsi_util_get_src_register_extswizzle(
+ const struct tgsi_src_register_ext_swz *reg,
+ unsigned component);
+
+unsigned
+tgsi_util_get_full_src_register_extswizzle(
+ const struct tgsi_full_src_register *reg,
+ unsigned component );
+
+void
+tgsi_util_set_src_register_swizzle(
+ struct tgsi_src_register *reg,
+ unsigned swizzle,
+ unsigned component );
+
+void
+tgsi_util_set_src_register_extswizzle(
+ struct tgsi_src_register_ext_swz *reg,
+ unsigned swizzle,
+ unsigned component );
+
+unsigned
+tgsi_util_get_src_register_extnegate(
+ const struct tgsi_src_register_ext_swz *reg,
+ unsigned component );
+
+void
+tgsi_util_set_src_register_extnegate(
+ struct tgsi_src_register_ext_swz *reg,
+ unsigned negate,
+ unsigned component );
+
+#define TGSI_UTIL_SIGN_CLEAR 0 /* Force positive */
+#define TGSI_UTIL_SIGN_SET 1 /* Force negative */
+#define TGSI_UTIL_SIGN_TOGGLE 2 /* Negate */
+#define TGSI_UTIL_SIGN_KEEP 3 /* No change */
+
+unsigned
+tgsi_util_get_full_src_register_sign_mode(
+ const struct tgsi_full_src_register *reg,
+ unsigned component );
+
+void
+tgsi_util_set_full_src_register_sign_mode(
+ struct tgsi_full_src_register *reg,
+ unsigned sign_mode );
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* TGSI_UTIL_H */
diff --git a/src/gallium/auxiliary/translate/Makefile b/src/gallium/auxiliary/translate/Makefile
new file mode 100644
index 0000000000..3c82f8ae03
--- /dev/null
+++ b/src/gallium/auxiliary/translate/Makefile
@@ -0,0 +1,12 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = translate
+
+C_SOURCES = \
+ translate_generic.c \
+ translate_sse.c \
+ translate.c \
+ translate_cache.c
+
+include ../../Makefile.template
diff --git a/src/gallium/auxiliary/translate/SConscript b/src/gallium/auxiliary/translate/SConscript
new file mode 100644
index 0000000000..9553a67537
--- /dev/null
+++ b/src/gallium/auxiliary/translate/SConscript
@@ -0,0 +1,12 @@
+Import('*')
+
+translate = env.ConvenienceLibrary(
+ target = 'translate',
+ source = [
+ 'translate_generic.c',
+ 'translate_sse.c',
+ 'translate.c',
+ 'translate_cache.c',
+ ])
+
+auxiliaries.insert(0, translate)
diff --git a/src/gallium/auxiliary/translate/translate.c b/src/gallium/auxiliary/translate/translate.c
new file mode 100644
index 0000000000..a9b7253bf4
--- /dev/null
+++ b/src/gallium/auxiliary/translate/translate.c
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "pipe/p_config.h"
+#include "pipe/p_state.h"
+#include "translate.h"
+
+struct translate *translate_create( const struct translate_key *key )
+{
+ struct translate *translate = NULL;
+
+#if defined(PIPE_ARCH_X86)
+ translate = translate_sse2_create( key );
+ if (translate)
+ return translate;
+#else
+ (void)translate;
+#endif
+
+ return translate_generic_create( key );
+}
diff --git a/src/gallium/auxiliary/translate/translate.h b/src/gallium/auxiliary/translate/translate.h
new file mode 100644
index 0000000000..34526eb061
--- /dev/null
+++ b/src/gallium/auxiliary/translate/translate.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2008 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * TUNGSTEN GRAPHICS 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.
+ */
+
+
+/**
+ * Vertex fetch/store/convert code. This functionality is used in two places:
+ * 1. Vertex fetch/convert - to grab vertex data from incoming vertex
+ * arrays and convert to format needed by vertex shaders.
+ * 2. Vertex store/emit - to convert simple float[][4] vertex attributes
+ * (which is the organization used throughout the draw/prim pipeline) to
+ * hardware-specific formats and emit into hardware vertex buffers.
+ *
+ *
+ * Authors:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#ifndef _TRANSLATE_H
+#define _TRANSLATE_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+
+struct translate_element
+{
+ enum pipe_format input_format;
+ enum pipe_format output_format;
+ unsigned input_buffer:8;
+ unsigned input_offset:24;
+ unsigned output_offset;
+};
+
+
+struct translate_key {
+ unsigned output_stride;
+ unsigned nr_elements;
+ struct translate_element element[PIPE_MAX_ATTRIBS + 1];
+};
+
+
+struct translate {
+ struct translate_key key;
+
+ void (*release)( struct translate * );
+
+ void (*set_buffer)( struct translate *,
+ unsigned i,
+ const void *ptr,
+ unsigned stride );
+
+ void (PIPE_CDECL *run_elts)( struct translate *,
+ const unsigned *elts,
+ unsigned count,
+ void *output_buffer);
+
+ void (PIPE_CDECL *run)( struct translate *,
+ unsigned start,
+ unsigned count,
+ void *output_buffer);
+};
+
+
+
+#if 0
+struct translate_context *translate_context_create( void );
+void translate_context_destroy( struct translate_context * );
+
+struct translate *translate_lookup_or_create( struct translate_context *tctx,
+ const struct translate_key *key );
+#endif
+
+
+struct translate *translate_create( const struct translate_key *key );
+
+static INLINE int translate_keysize( const struct translate_key *key )
+{
+ return 2 * sizeof(int) + key->nr_elements * sizeof(struct translate_element);
+}
+
+static INLINE int translate_key_compare( const struct translate_key *a,
+ const struct translate_key *b )
+{
+ int keysize = translate_keysize(a);
+ return memcmp(a, b, keysize);
+}
+
+
+static INLINE void translate_key_sanitize( struct translate_key *a )
+{
+ int keysize = translate_keysize(a);
+ char *ptr = (char *)a;
+ memset(ptr + keysize, 0, sizeof(*a) - keysize);
+}
+
+
+/*******************************************************************************
+ * Private:
+ */
+struct translate *translate_sse2_create( const struct translate_key *key );
+
+struct translate *translate_generic_create( const struct translate_key *key );
+
+
+#endif
diff --git a/src/gallium/auxiliary/translate/translate_cache.c b/src/gallium/auxiliary/translate/translate_cache.c
new file mode 100644
index 0000000000..d8069a149c
--- /dev/null
+++ b/src/gallium/auxiliary/translate/translate_cache.c
@@ -0,0 +1,102 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "pipe/p_state.h"
+#include "translate.h"
+#include "translate_cache.h"
+
+#include "cso_cache/cso_cache.h"
+#include "cso_cache/cso_hash.h"
+
+struct translate_cache {
+ struct cso_hash *hash;
+};
+
+struct translate_cache * translate_cache_create( void )
+{
+ struct translate_cache *cache = MALLOC_STRUCT(translate_cache);
+ cache->hash = cso_hash_create();
+ return cache;
+}
+
+
+static INLINE void delete_translates(struct translate_cache *cache)
+{
+ struct cso_hash *hash = cache->hash;
+ struct cso_hash_iter iter = cso_hash_first_node(hash);
+ while (!cso_hash_iter_is_null(iter)) {
+ struct translate *state = (struct translate*)cso_hash_iter_data(iter);
+ iter = cso_hash_iter_next(iter);
+ if (state) {
+ state->release(state);
+ }
+ }
+}
+
+void translate_cache_destroy(struct translate_cache *cache)
+{
+ delete_translates(cache);
+ cso_hash_delete(cache->hash);
+ FREE(cache);
+}
+
+
+static INLINE unsigned translate_hash_key_size(struct translate_key *key)
+{
+ unsigned size = sizeof(struct translate_key) -
+ sizeof(struct translate_element) * (PIPE_MAX_ATTRIBS - key->nr_elements);
+ return size;
+}
+
+static INLINE unsigned create_key(struct translate_key *key)
+{
+ unsigned hash_key;
+ unsigned size = translate_hash_key_size(key);
+ /*debug_printf("key size = %d, (els = %d)\n",
+ size, key->nr_elements);*/
+ hash_key = cso_construct_key(key, size);
+ return hash_key;
+}
+
+struct translate * translate_cache_find(struct translate_cache *cache,
+ struct translate_key *key)
+{
+ unsigned hash_key = create_key(key);
+ struct translate *translate = (struct translate*)
+ cso_hash_find_data_from_template(cache->hash,
+ hash_key,
+ key, sizeof(*key));
+
+ if (!translate) {
+ /* create/insert */
+ translate = translate_create(key);
+ cso_hash_insert(cache->hash, hash_key, translate);
+ }
+
+ return translate;
+}
diff --git a/src/gallium/auxiliary/translate/translate_cache.h b/src/gallium/auxiliary/translate/translate_cache.h
new file mode 100644
index 0000000000..7dba871e57
--- /dev/null
+++ b/src/gallium/auxiliary/translate/translate_cache.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _TRANSLATE_CACHE_H
+#define _TRANSLATE_CACHE_H
+
+
+/*******************************************************************************
+ * Translate cache.
+ * Simply used to cache created translates. Avoids unecessary creation of
+ * translate's if one suitable for a given translate_key has already been
+ * created.
+ *
+ * Note: this functionality depends and requires the CSO module.
+ */
+struct translate_cache;
+
+struct translate_key;
+struct translate;
+
+struct translate_cache *translate_cache_create( void );
+void translate_cache_destroy(struct translate_cache *cache);
+
+/**
+ * Will try to find a translate structure matched by the given key.
+ * If such a structure doesn't exist in the cache the function
+ * will automatically create it, insert it in the cache and
+ * return the created version.
+ *
+ */
+struct translate *translate_cache_find(struct translate_cache *cache,
+ struct translate_key *key);
+
+#endif
diff --git a/src/gallium/auxiliary/translate/translate_generic.c b/src/gallium/auxiliary/translate/translate_generic.c
new file mode 100644
index 0000000000..8d39b64c6c
--- /dev/null
+++ b/src/gallium/auxiliary/translate/translate_generic.c
@@ -0,0 +1,700 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_memory.h"
+#include "pipe/p_state.h"
+#include "translate.h"
+
+
+#define DRAW_DBG 0
+
+typedef void (*fetch_func)(const void *ptr, float *attrib);
+typedef void (*emit_func)(const float *attrib, void *ptr);
+
+
+
+struct translate_generic {
+ struct translate translate;
+
+ struct {
+ fetch_func fetch;
+ unsigned buffer;
+ unsigned input_offset;
+
+ emit_func emit;
+ unsigned output_offset;
+
+ char *input_ptr;
+ unsigned input_stride;
+
+ } attrib[PIPE_MAX_ATTRIBS];
+
+ unsigned nr_attrib;
+};
+
+
+static struct translate_generic *translate_generic( struct translate *translate )
+{
+ return (struct translate_generic *)translate;
+}
+
+/**
+ * Fetch a float[4] vertex attribute from memory, doing format/type
+ * conversion as needed.
+ *
+ * This is probably needed/dupliocated elsewhere, eg format
+ * conversion, texture sampling etc.
+ */
+#define ATTRIB( NAME, SZ, TYPE, FROM, TO ) \
+static void \
+fetch_##NAME(const void *ptr, float *attrib) \
+{ \
+ const float defaults[4] = { 0.0f,0.0f,0.0f,1.0f }; \
+ unsigned i; \
+ \
+ for (i = 0; i < SZ; i++) { \
+ attrib[i] = FROM(i); \
+ } \
+ \
+ for (; i < 4; i++) { \
+ attrib[i] = defaults[i]; \
+ } \
+} \
+ \
+static void \
+emit_##NAME(const float *attrib, void *ptr) \
+{ \
+ unsigned i; \
+ TYPE *out = (TYPE *)ptr; \
+ \
+ for (i = 0; i < SZ; i++) { \
+ out[i] = TO(attrib[i]); \
+ } \
+}
+
+
+#define FROM_64_FLOAT(i) ((float) ((double *) ptr)[i])
+#define FROM_32_FLOAT(i) (((float *) ptr)[i])
+
+#define FROM_8_USCALED(i) ((float) ((unsigned char *) ptr)[i])
+#define FROM_16_USCALED(i) ((float) ((unsigned short *) ptr)[i])
+#define FROM_32_USCALED(i) ((float) ((unsigned int *) ptr)[i])
+
+#define FROM_8_SSCALED(i) ((float) ((char *) ptr)[i])
+#define FROM_16_SSCALED(i) ((float) ((short *) ptr)[i])
+#define FROM_32_SSCALED(i) ((float) ((int *) ptr)[i])
+
+#define FROM_8_UNORM(i) ((float) ((unsigned char *) ptr)[i] / 255.0f)
+#define FROM_16_UNORM(i) ((float) ((unsigned short *) ptr)[i] / 65535.0f)
+#define FROM_32_UNORM(i) ((float) ((unsigned int *) ptr)[i] / 4294967295.0f)
+
+#define FROM_8_SNORM(i) ((float) ((char *) ptr)[i] / 127.0f)
+#define FROM_16_SNORM(i) ((float) ((short *) ptr)[i] / 32767.0f)
+#define FROM_32_SNORM(i) ((float) ((int *) ptr)[i] / 2147483647.0f)
+
+#define FROM_32_FIXED(i) (((int *) ptr)[i] / 65536.0f)
+
+#define TO_64_FLOAT(x) ((double) x)
+#define TO_32_FLOAT(x) (x)
+
+#define TO_8_USCALED(x) ((unsigned char) x)
+#define TO_16_USCALED(x) ((unsigned short) x)
+#define TO_32_USCALED(x) ((unsigned int) x)
+
+#define TO_8_SSCALED(x) ((char) x)
+#define TO_16_SSCALED(x) ((short) x)
+#define TO_32_SSCALED(x) ((int) x)
+
+#define TO_8_UNORM(x) ((unsigned char) (x * 255.0f))
+#define TO_16_UNORM(x) ((unsigned short) (x * 65535.0f))
+#define TO_32_UNORM(x) ((unsigned int) (x * 4294967295.0f))
+
+#define TO_8_SNORM(x) ((char) (x * 127.0f))
+#define TO_16_SNORM(x) ((short) (x * 32767.0f))
+#define TO_32_SNORM(x) ((int) (x * 2147483647.0f))
+
+#define TO_32_FIXED(x) ((int) (x * 65536.0f))
+
+
+
+ATTRIB( R64G64B64A64_FLOAT, 4, double, FROM_64_FLOAT, TO_64_FLOAT )
+ATTRIB( R64G64B64_FLOAT, 3, double, FROM_64_FLOAT, TO_64_FLOAT )
+ATTRIB( R64G64_FLOAT, 2, double, FROM_64_FLOAT, TO_64_FLOAT )
+ATTRIB( R64_FLOAT, 1, double, FROM_64_FLOAT, TO_64_FLOAT )
+
+ATTRIB( R32G32B32A32_FLOAT, 4, float, FROM_32_FLOAT, TO_32_FLOAT )
+ATTRIB( R32G32B32_FLOAT, 3, float, FROM_32_FLOAT, TO_32_FLOAT )
+ATTRIB( R32G32_FLOAT, 2, float, FROM_32_FLOAT, TO_32_FLOAT )
+ATTRIB( R32_FLOAT, 1, float, FROM_32_FLOAT, TO_32_FLOAT )
+
+ATTRIB( R32G32B32A32_USCALED, 4, unsigned, FROM_32_USCALED, TO_32_USCALED )
+ATTRIB( R32G32B32_USCALED, 3, unsigned, FROM_32_USCALED, TO_32_USCALED )
+ATTRIB( R32G32_USCALED, 2, unsigned, FROM_32_USCALED, TO_32_USCALED )
+ATTRIB( R32_USCALED, 1, unsigned, FROM_32_USCALED, TO_32_USCALED )
+
+ATTRIB( R32G32B32A32_SSCALED, 4, int, FROM_32_SSCALED, TO_32_SSCALED )
+ATTRIB( R32G32B32_SSCALED, 3, int, FROM_32_SSCALED, TO_32_SSCALED )
+ATTRIB( R32G32_SSCALED, 2, int, FROM_32_SSCALED, TO_32_SSCALED )
+ATTRIB( R32_SSCALED, 1, int, FROM_32_SSCALED, TO_32_SSCALED )
+
+ATTRIB( R32G32B32A32_UNORM, 4, unsigned, FROM_32_UNORM, TO_32_UNORM )
+ATTRIB( R32G32B32_UNORM, 3, unsigned, FROM_32_UNORM, TO_32_UNORM )
+ATTRIB( R32G32_UNORM, 2, unsigned, FROM_32_UNORM, TO_32_UNORM )
+ATTRIB( R32_UNORM, 1, unsigned, FROM_32_UNORM, TO_32_UNORM )
+
+ATTRIB( R32G32B32A32_SNORM, 4, int, FROM_32_SNORM, TO_32_SNORM )
+ATTRIB( R32G32B32_SNORM, 3, int, FROM_32_SNORM, TO_32_SNORM )
+ATTRIB( R32G32_SNORM, 2, int, FROM_32_SNORM, TO_32_SNORM )
+ATTRIB( R32_SNORM, 1, int, FROM_32_SNORM, TO_32_SNORM )
+
+ATTRIB( R16G16B16A16_USCALED, 4, ushort, FROM_16_USCALED, TO_16_USCALED )
+ATTRIB( R16G16B16_USCALED, 3, ushort, FROM_16_USCALED, TO_16_USCALED )
+ATTRIB( R16G16_USCALED, 2, ushort, FROM_16_USCALED, TO_16_USCALED )
+ATTRIB( R16_USCALED, 1, ushort, FROM_16_USCALED, TO_16_USCALED )
+
+ATTRIB( R16G16B16A16_SSCALED, 4, short, FROM_16_SSCALED, TO_16_SSCALED )
+ATTRIB( R16G16B16_SSCALED, 3, short, FROM_16_SSCALED, TO_16_SSCALED )
+ATTRIB( R16G16_SSCALED, 2, short, FROM_16_SSCALED, TO_16_SSCALED )
+ATTRIB( R16_SSCALED, 1, short, FROM_16_SSCALED, TO_16_SSCALED )
+
+ATTRIB( R16G16B16A16_UNORM, 4, ushort, FROM_16_UNORM, TO_16_UNORM )
+ATTRIB( R16G16B16_UNORM, 3, ushort, FROM_16_UNORM, TO_16_UNORM )
+ATTRIB( R16G16_UNORM, 2, ushort, FROM_16_UNORM, TO_16_UNORM )
+ATTRIB( R16_UNORM, 1, ushort, FROM_16_UNORM, TO_16_UNORM )
+
+ATTRIB( R16G16B16A16_SNORM, 4, short, FROM_16_SNORM, TO_16_SNORM )
+ATTRIB( R16G16B16_SNORM, 3, short, FROM_16_SNORM, TO_16_SNORM )
+ATTRIB( R16G16_SNORM, 2, short, FROM_16_SNORM, TO_16_SNORM )
+ATTRIB( R16_SNORM, 1, short, FROM_16_SNORM, TO_16_SNORM )
+
+ATTRIB( R8G8B8A8_USCALED, 4, ubyte, FROM_8_USCALED, TO_8_USCALED )
+ATTRIB( R8G8B8_USCALED, 3, ubyte, FROM_8_USCALED, TO_8_USCALED )
+ATTRIB( R8G8_USCALED, 2, ubyte, FROM_8_USCALED, TO_8_USCALED )
+ATTRIB( R8_USCALED, 1, ubyte, FROM_8_USCALED, TO_8_USCALED )
+
+ATTRIB( R8G8B8A8_SSCALED, 4, char, FROM_8_SSCALED, TO_8_SSCALED )
+ATTRIB( R8G8B8_SSCALED, 3, char, FROM_8_SSCALED, TO_8_SSCALED )
+ATTRIB( R8G8_SSCALED, 2, char, FROM_8_SSCALED, TO_8_SSCALED )
+ATTRIB( R8_SSCALED, 1, char, FROM_8_SSCALED, TO_8_SSCALED )
+
+ATTRIB( R8G8B8A8_UNORM, 4, ubyte, FROM_8_UNORM, TO_8_UNORM )
+ATTRIB( R8G8B8_UNORM, 3, ubyte, FROM_8_UNORM, TO_8_UNORM )
+ATTRIB( R8G8_UNORM, 2, ubyte, FROM_8_UNORM, TO_8_UNORM )
+ATTRIB( R8_UNORM, 1, ubyte, FROM_8_UNORM, TO_8_UNORM )
+
+ATTRIB( R8G8B8A8_SNORM, 4, char, FROM_8_SNORM, TO_8_SNORM )
+ATTRIB( R8G8B8_SNORM, 3, char, FROM_8_SNORM, TO_8_SNORM )
+ATTRIB( R8G8_SNORM, 2, char, FROM_8_SNORM, TO_8_SNORM )
+ATTRIB( R8_SNORM, 1, char, FROM_8_SNORM, TO_8_SNORM )
+
+ATTRIB( A8R8G8B8_UNORM, 4, ubyte, FROM_8_UNORM, TO_8_UNORM )
+//ATTRIB( R8G8B8A8_UNORM, 4, ubyte, FROM_8_UNORM, TO_8_UNORM )
+
+ATTRIB( R32G32B32A32_FIXED, 4, int, FROM_32_FIXED, TO_32_FIXED )
+ATTRIB( R32G32B32_FIXED, 3, int, FROM_32_FIXED, TO_32_FIXED )
+ATTRIB( R32G32_FIXED, 2, int, FROM_32_FIXED, TO_32_FIXED )
+ATTRIB( R32_FIXED, 1, int, FROM_32_FIXED, TO_32_FIXED )
+
+
+
+static void
+fetch_B8G8R8A8_UNORM(const void *ptr, float *attrib)
+{
+ attrib[2] = FROM_8_UNORM(0);
+ attrib[1] = FROM_8_UNORM(1);
+ attrib[0] = FROM_8_UNORM(2);
+ attrib[3] = FROM_8_UNORM(3);
+}
+
+static void
+emit_B8G8R8A8_UNORM( const float *attrib, void *ptr)
+{
+ ubyte *out = (ubyte *)ptr;
+ out[2] = TO_8_UNORM(attrib[0]);
+ out[1] = TO_8_UNORM(attrib[1]);
+ out[0] = TO_8_UNORM(attrib[2]);
+ out[3] = TO_8_UNORM(attrib[3]);
+}
+
+static void
+fetch_NULL( const void *ptr, float *attrib )
+{
+ attrib[0] = 0;
+ attrib[1] = 0;
+ attrib[2] = 0;
+ attrib[3] = 1;
+}
+
+static void
+emit_NULL( const float *attrib, void *ptr )
+{
+ /* do nothing is the only sensible option */
+}
+
+static fetch_func get_fetch_func( enum pipe_format format )
+{
+ switch (format) {
+ case PIPE_FORMAT_R64_FLOAT:
+ return &fetch_R64_FLOAT;
+ case PIPE_FORMAT_R64G64_FLOAT:
+ return &fetch_R64G64_FLOAT;
+ case PIPE_FORMAT_R64G64B64_FLOAT:
+ return &fetch_R64G64B64_FLOAT;
+ case PIPE_FORMAT_R64G64B64A64_FLOAT:
+ return &fetch_R64G64B64A64_FLOAT;
+
+ case PIPE_FORMAT_R32_FLOAT:
+ return &fetch_R32_FLOAT;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ return &fetch_R32G32_FLOAT;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ return &fetch_R32G32B32_FLOAT;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ return &fetch_R32G32B32A32_FLOAT;
+
+ case PIPE_FORMAT_R32_UNORM:
+ return &fetch_R32_UNORM;
+ case PIPE_FORMAT_R32G32_UNORM:
+ return &fetch_R32G32_UNORM;
+ case PIPE_FORMAT_R32G32B32_UNORM:
+ return &fetch_R32G32B32_UNORM;
+ case PIPE_FORMAT_R32G32B32A32_UNORM:
+ return &fetch_R32G32B32A32_UNORM;
+
+ case PIPE_FORMAT_R32_USCALED:
+ return &fetch_R32_USCALED;
+ case PIPE_FORMAT_R32G32_USCALED:
+ return &fetch_R32G32_USCALED;
+ case PIPE_FORMAT_R32G32B32_USCALED:
+ return &fetch_R32G32B32_USCALED;
+ case PIPE_FORMAT_R32G32B32A32_USCALED:
+ return &fetch_R32G32B32A32_USCALED;
+
+ case PIPE_FORMAT_R32_SNORM:
+ return &fetch_R32_SNORM;
+ case PIPE_FORMAT_R32G32_SNORM:
+ return &fetch_R32G32_SNORM;
+ case PIPE_FORMAT_R32G32B32_SNORM:
+ return &fetch_R32G32B32_SNORM;
+ case PIPE_FORMAT_R32G32B32A32_SNORM:
+ return &fetch_R32G32B32A32_SNORM;
+
+ case PIPE_FORMAT_R32_SSCALED:
+ return &fetch_R32_SSCALED;
+ case PIPE_FORMAT_R32G32_SSCALED:
+ return &fetch_R32G32_SSCALED;
+ case PIPE_FORMAT_R32G32B32_SSCALED:
+ return &fetch_R32G32B32_SSCALED;
+ case PIPE_FORMAT_R32G32B32A32_SSCALED:
+ return &fetch_R32G32B32A32_SSCALED;
+
+ case PIPE_FORMAT_R16_UNORM:
+ return &fetch_R16_UNORM;
+ case PIPE_FORMAT_R16G16_UNORM:
+ return &fetch_R16G16_UNORM;
+ case PIPE_FORMAT_R16G16B16_UNORM:
+ return &fetch_R16G16B16_UNORM;
+ case PIPE_FORMAT_R16G16B16A16_UNORM:
+ return &fetch_R16G16B16A16_UNORM;
+
+ case PIPE_FORMAT_R16_USCALED:
+ return &fetch_R16_USCALED;
+ case PIPE_FORMAT_R16G16_USCALED:
+ return &fetch_R16G16_USCALED;
+ case PIPE_FORMAT_R16G16B16_USCALED:
+ return &fetch_R16G16B16_USCALED;
+ case PIPE_FORMAT_R16G16B16A16_USCALED:
+ return &fetch_R16G16B16A16_USCALED;
+
+ case PIPE_FORMAT_R16_SNORM:
+ return &fetch_R16_SNORM;
+ case PIPE_FORMAT_R16G16_SNORM:
+ return &fetch_R16G16_SNORM;
+ case PIPE_FORMAT_R16G16B16_SNORM:
+ return &fetch_R16G16B16_SNORM;
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ return &fetch_R16G16B16A16_SNORM;
+
+ case PIPE_FORMAT_R16_SSCALED:
+ return &fetch_R16_SSCALED;
+ case PIPE_FORMAT_R16G16_SSCALED:
+ return &fetch_R16G16_SSCALED;
+ case PIPE_FORMAT_R16G16B16_SSCALED:
+ return &fetch_R16G16B16_SSCALED;
+ case PIPE_FORMAT_R16G16B16A16_SSCALED:
+ return &fetch_R16G16B16A16_SSCALED;
+
+ case PIPE_FORMAT_R8_UNORM:
+ return &fetch_R8_UNORM;
+ case PIPE_FORMAT_R8G8_UNORM:
+ return &fetch_R8G8_UNORM;
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ return &fetch_R8G8B8_UNORM;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ return &fetch_R8G8B8A8_UNORM;
+
+ case PIPE_FORMAT_R8_USCALED:
+ return &fetch_R8_USCALED;
+ case PIPE_FORMAT_R8G8_USCALED:
+ return &fetch_R8G8_USCALED;
+ case PIPE_FORMAT_R8G8B8_USCALED:
+ return &fetch_R8G8B8_USCALED;
+ case PIPE_FORMAT_R8G8B8A8_USCALED:
+ return &fetch_R8G8B8A8_USCALED;
+
+ case PIPE_FORMAT_R8_SNORM:
+ return &fetch_R8_SNORM;
+ case PIPE_FORMAT_R8G8_SNORM:
+ return &fetch_R8G8_SNORM;
+ case PIPE_FORMAT_R8G8B8_SNORM:
+ return &fetch_R8G8B8_SNORM;
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
+ return &fetch_R8G8B8A8_SNORM;
+
+ case PIPE_FORMAT_R8_SSCALED:
+ return &fetch_R8_SSCALED;
+ case PIPE_FORMAT_R8G8_SSCALED:
+ return &fetch_R8G8_SSCALED;
+ case PIPE_FORMAT_R8G8B8_SSCALED:
+ return &fetch_R8G8B8_SSCALED;
+ case PIPE_FORMAT_R8G8B8A8_SSCALED:
+ return &fetch_R8G8B8A8_SSCALED;
+
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return &fetch_A8R8G8B8_UNORM;
+
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ return &fetch_B8G8R8A8_UNORM;
+
+ case PIPE_FORMAT_R32_FIXED:
+ return &fetch_R32_FIXED;
+ case PIPE_FORMAT_R32G32_FIXED:
+ return &fetch_R32G32_FIXED;
+ case PIPE_FORMAT_R32G32B32_FIXED:
+ return &fetch_R32G32B32_FIXED;
+ case PIPE_FORMAT_R32G32B32A32_FIXED:
+ return &fetch_R32G32B32A32_FIXED;
+
+ default:
+ assert(0);
+ return &fetch_NULL;
+ }
+}
+
+
+
+
+static emit_func get_emit_func( enum pipe_format format )
+{
+ /* silence warnings */
+ (void) emit_R32G32B32A32_FIXED;
+ (void) emit_R32G32B32_FIXED;
+ (void) emit_R32G32_FIXED;
+ (void) emit_R32_FIXED;
+
+ switch (format) {
+ case PIPE_FORMAT_R64_FLOAT:
+ return &emit_R64_FLOAT;
+ case PIPE_FORMAT_R64G64_FLOAT:
+ return &emit_R64G64_FLOAT;
+ case PIPE_FORMAT_R64G64B64_FLOAT:
+ return &emit_R64G64B64_FLOAT;
+ case PIPE_FORMAT_R64G64B64A64_FLOAT:
+ return &emit_R64G64B64A64_FLOAT;
+
+ case PIPE_FORMAT_R32_FLOAT:
+ return &emit_R32_FLOAT;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ return &emit_R32G32_FLOAT;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ return &emit_R32G32B32_FLOAT;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ return &emit_R32G32B32A32_FLOAT;
+
+ case PIPE_FORMAT_R32_UNORM:
+ return &emit_R32_UNORM;
+ case PIPE_FORMAT_R32G32_UNORM:
+ return &emit_R32G32_UNORM;
+ case PIPE_FORMAT_R32G32B32_UNORM:
+ return &emit_R32G32B32_UNORM;
+ case PIPE_FORMAT_R32G32B32A32_UNORM:
+ return &emit_R32G32B32A32_UNORM;
+
+ case PIPE_FORMAT_R32_USCALED:
+ return &emit_R32_USCALED;
+ case PIPE_FORMAT_R32G32_USCALED:
+ return &emit_R32G32_USCALED;
+ case PIPE_FORMAT_R32G32B32_USCALED:
+ return &emit_R32G32B32_USCALED;
+ case PIPE_FORMAT_R32G32B32A32_USCALED:
+ return &emit_R32G32B32A32_USCALED;
+
+ case PIPE_FORMAT_R32_SNORM:
+ return &emit_R32_SNORM;
+ case PIPE_FORMAT_R32G32_SNORM:
+ return &emit_R32G32_SNORM;
+ case PIPE_FORMAT_R32G32B32_SNORM:
+ return &emit_R32G32B32_SNORM;
+ case PIPE_FORMAT_R32G32B32A32_SNORM:
+ return &emit_R32G32B32A32_SNORM;
+
+ case PIPE_FORMAT_R32_SSCALED:
+ return &emit_R32_SSCALED;
+ case PIPE_FORMAT_R32G32_SSCALED:
+ return &emit_R32G32_SSCALED;
+ case PIPE_FORMAT_R32G32B32_SSCALED:
+ return &emit_R32G32B32_SSCALED;
+ case PIPE_FORMAT_R32G32B32A32_SSCALED:
+ return &emit_R32G32B32A32_SSCALED;
+
+ case PIPE_FORMAT_R16_UNORM:
+ return &emit_R16_UNORM;
+ case PIPE_FORMAT_R16G16_UNORM:
+ return &emit_R16G16_UNORM;
+ case PIPE_FORMAT_R16G16B16_UNORM:
+ return &emit_R16G16B16_UNORM;
+ case PIPE_FORMAT_R16G16B16A16_UNORM:
+ return &emit_R16G16B16A16_UNORM;
+
+ case PIPE_FORMAT_R16_USCALED:
+ return &emit_R16_USCALED;
+ case PIPE_FORMAT_R16G16_USCALED:
+ return &emit_R16G16_USCALED;
+ case PIPE_FORMAT_R16G16B16_USCALED:
+ return &emit_R16G16B16_USCALED;
+ case PIPE_FORMAT_R16G16B16A16_USCALED:
+ return &emit_R16G16B16A16_USCALED;
+
+ case PIPE_FORMAT_R16_SNORM:
+ return &emit_R16_SNORM;
+ case PIPE_FORMAT_R16G16_SNORM:
+ return &emit_R16G16_SNORM;
+ case PIPE_FORMAT_R16G16B16_SNORM:
+ return &emit_R16G16B16_SNORM;
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ return &emit_R16G16B16A16_SNORM;
+
+ case PIPE_FORMAT_R16_SSCALED:
+ return &emit_R16_SSCALED;
+ case PIPE_FORMAT_R16G16_SSCALED:
+ return &emit_R16G16_SSCALED;
+ case PIPE_FORMAT_R16G16B16_SSCALED:
+ return &emit_R16G16B16_SSCALED;
+ case PIPE_FORMAT_R16G16B16A16_SSCALED:
+ return &emit_R16G16B16A16_SSCALED;
+
+ case PIPE_FORMAT_R8_UNORM:
+ return &emit_R8_UNORM;
+ case PIPE_FORMAT_R8G8_UNORM:
+ return &emit_R8G8_UNORM;
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ return &emit_R8G8B8_UNORM;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ return &emit_R8G8B8A8_UNORM;
+
+ case PIPE_FORMAT_R8_USCALED:
+ return &emit_R8_USCALED;
+ case PIPE_FORMAT_R8G8_USCALED:
+ return &emit_R8G8_USCALED;
+ case PIPE_FORMAT_R8G8B8_USCALED:
+ return &emit_R8G8B8_USCALED;
+ case PIPE_FORMAT_R8G8B8A8_USCALED:
+ return &emit_R8G8B8A8_USCALED;
+
+ case PIPE_FORMAT_R8_SNORM:
+ return &emit_R8_SNORM;
+ case PIPE_FORMAT_R8G8_SNORM:
+ return &emit_R8G8_SNORM;
+ case PIPE_FORMAT_R8G8B8_SNORM:
+ return &emit_R8G8B8_SNORM;
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
+ return &emit_R8G8B8A8_SNORM;
+
+ case PIPE_FORMAT_R8_SSCALED:
+ return &emit_R8_SSCALED;
+ case PIPE_FORMAT_R8G8_SSCALED:
+ return &emit_R8G8_SSCALED;
+ case PIPE_FORMAT_R8G8B8_SSCALED:
+ return &emit_R8G8B8_SSCALED;
+ case PIPE_FORMAT_R8G8B8A8_SSCALED:
+ return &emit_R8G8B8A8_SSCALED;
+
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return &emit_A8R8G8B8_UNORM;
+
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ return &emit_B8G8R8A8_UNORM;
+
+ default:
+ assert(0);
+ return &emit_NULL;
+ }
+}
+
+
+
+/**
+ * Fetch vertex attributes for 'count' vertices.
+ */
+static void PIPE_CDECL generic_run_elts( struct translate *translate,
+ const unsigned *elts,
+ unsigned count,
+ void *output_buffer )
+{
+ struct translate_generic *tg = translate_generic(translate);
+ char *vert = output_buffer;
+ unsigned nr_attrs = tg->nr_attrib;
+ unsigned attr;
+ unsigned i;
+
+ /* loop over vertex attributes (vertex shader inputs)
+ */
+ for (i = 0; i < count; i++) {
+ unsigned elt = *elts++;
+
+ for (attr = 0; attr < nr_attrs; attr++) {
+ float data[4];
+
+ const char *src = (tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride * elt);
+
+ char *dst = (vert +
+ tg->attrib[attr].output_offset);
+
+ tg->attrib[attr].fetch( src, data );
+
+ if (0) debug_printf("vert %d/%d attr %d: %f %f %f %f\n",
+ i, elt, attr, data[0], data[1], data[2], data[3]);
+
+ tg->attrib[attr].emit( data, dst );
+ }
+
+ vert += tg->translate.key.output_stride;
+ }
+}
+
+
+
+static void PIPE_CDECL generic_run( struct translate *translate,
+ unsigned start,
+ unsigned count,
+ void *output_buffer )
+{
+ struct translate_generic *tg = translate_generic(translate);
+ char *vert = output_buffer;
+ unsigned nr_attrs = tg->nr_attrib;
+ unsigned attr;
+ unsigned i;
+
+ /* loop over vertex attributes (vertex shader inputs)
+ */
+ for (i = 0; i < count; i++) {
+ unsigned elt = start + i;
+
+ for (attr = 0; attr < nr_attrs; attr++) {
+ float data[4];
+
+ const char *src = (tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride * elt);
+
+ char *dst = (vert +
+ tg->attrib[attr].output_offset);
+
+ tg->attrib[attr].fetch( src, data );
+
+ if (0) debug_printf("vert %d attr %d: %f %f %f %f\n",
+ i, attr, data[0], data[1], data[2], data[3]);
+
+ tg->attrib[attr].emit( data, dst );
+ }
+
+ vert += tg->translate.key.output_stride;
+ }
+}
+
+
+
+static void generic_set_buffer( struct translate *translate,
+ unsigned buf,
+ const void *ptr,
+ unsigned stride )
+{
+ struct translate_generic *tg = translate_generic(translate);
+ unsigned i;
+
+ for (i = 0; i < tg->nr_attrib; i++) {
+ if (tg->attrib[i].buffer == buf) {
+ tg->attrib[i].input_ptr = ((char *)ptr +
+ tg->attrib[i].input_offset);
+ tg->attrib[i].input_stride = stride;
+ }
+ }
+}
+
+
+static void generic_release( struct translate *translate )
+{
+ /* Refcount?
+ */
+ FREE(translate);
+}
+
+struct translate *translate_generic_create( const struct translate_key *key )
+{
+ struct translate_generic *tg = CALLOC_STRUCT(translate_generic);
+ unsigned i;
+
+ if (tg == NULL)
+ return NULL;
+
+ tg->translate.key = *key;
+ tg->translate.release = generic_release;
+ tg->translate.set_buffer = generic_set_buffer;
+ tg->translate.run_elts = generic_run_elts;
+ tg->translate.run = generic_run;
+
+ for (i = 0; i < key->nr_elements; i++) {
+
+ tg->attrib[i].fetch = get_fetch_func(key->element[i].input_format);
+ tg->attrib[i].buffer = key->element[i].input_buffer;
+ tg->attrib[i].input_offset = key->element[i].input_offset;
+
+ tg->attrib[i].emit = get_emit_func(key->element[i].output_format);
+ tg->attrib[i].output_offset = key->element[i].output_offset;
+
+ }
+
+ tg->nr_attrib = key->nr_elements;
+
+
+ return &tg->translate;
+}
diff --git a/src/gallium/auxiliary/translate/translate_sse.c b/src/gallium/auxiliary/translate/translate_sse.c
new file mode 100644
index 0000000000..b62db8d8f3
--- /dev/null
+++ b/src/gallium/auxiliary/translate/translate_sse.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * TUNGSTEN GRAPHICS 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:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_config.h"
+#include "pipe/p_compiler.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "translate.h"
+
+
+#if defined(PIPE_ARCH_X86)
+
+#include "rtasm/rtasm_cpu.h"
+#include "rtasm/rtasm_x86sse.h"
+
+
+#define X 0
+#define Y 1
+#define Z 2
+#define W 3
+
+
+typedef void (PIPE_CDECL *run_func)( struct translate *translate,
+ unsigned start,
+ unsigned count,
+ void *output_buffer );
+
+typedef void (PIPE_CDECL *run_elts_func)( struct translate *translate,
+ const unsigned *elts,
+ unsigned count,
+ void *output_buffer );
+
+struct translate_buffer {
+ const void *base_ptr;
+ unsigned stride;
+ void *ptr; /* updated per vertex */
+};
+
+
+struct translate_sse {
+ struct translate translate;
+
+ struct x86_function linear_func;
+ struct x86_function elt_func;
+ struct x86_function *func;
+
+ boolean loaded_identity;
+ boolean loaded_255;
+ boolean loaded_inv_255;
+
+ float identity[4];
+ float float_255[4];
+ float inv_255[4];
+
+ struct translate_buffer buffer[PIPE_MAX_ATTRIBS];
+ unsigned nr_buffers;
+
+ run_func gen_run;
+ run_elts_func gen_run_elts;
+
+ /* these are actually known values, but putting them in a struct
+ * like this is helpful to keep them in sync across the file.
+ */
+ struct x86_reg tmp_EAX;
+ struct x86_reg idx_EBX; /* either start+i or &elt[i] */
+ struct x86_reg outbuf_ECX;
+ struct x86_reg machine_EDX;
+ struct x86_reg count_ESI; /* decrements to zero */
+};
+
+static int get_offset( const void *a, const void *b )
+{
+ return (const char *)b - (const char *)a;
+}
+
+
+
+static struct x86_reg get_identity( struct translate_sse *p )
+{
+ struct x86_reg reg = x86_make_reg(file_XMM, 6);
+
+ if (!p->loaded_identity) {
+ p->loaded_identity = TRUE;
+ p->identity[0] = 0;
+ p->identity[1] = 0;
+ p->identity[2] = 0;
+ p->identity[3] = 1;
+
+ sse_movups(p->func, reg,
+ x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->identity[0])));
+ }
+
+ return reg;
+}
+
+static struct x86_reg get_255( struct translate_sse *p )
+{
+ struct x86_reg reg = x86_make_reg(file_XMM, 7);
+
+ if (!p->loaded_255) {
+ p->loaded_255 = TRUE;
+ p->float_255[0] =
+ p->float_255[1] =
+ p->float_255[2] =
+ p->float_255[3] = 255.0f;
+
+ sse_movups(p->func, reg,
+ x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->float_255[0])));
+ }
+
+ return reg;
+}
+
+static struct x86_reg get_inv_255( struct translate_sse *p )
+{
+ struct x86_reg reg = x86_make_reg(file_XMM, 5);
+
+ if (!p->loaded_inv_255) {
+ p->loaded_inv_255 = TRUE;
+ p->inv_255[0] =
+ p->inv_255[1] =
+ p->inv_255[2] =
+ p->inv_255[3] = 1.0f / 255.0f;
+
+ sse_movups(p->func, reg,
+ x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->inv_255[0])));
+ }
+
+ return reg;
+}
+
+
+static void emit_load_R32G32B32A32( struct translate_sse *p,
+ struct x86_reg data,
+ struct x86_reg arg0 )
+{
+ sse_movups(p->func, data, arg0);
+}
+
+static void emit_load_R32G32B32( struct translate_sse *p,
+ struct x86_reg data,
+ struct x86_reg arg0 )
+{
+ /* Have to jump through some hoops:
+ *
+ * c 0 0 0
+ * c 0 0 1
+ * 0 0 c 1
+ * a b c 1
+ */
+ sse_movss(p->func, data, x86_make_disp(arg0, 8));
+ sse_shufps(p->func, data, get_identity(p), SHUF(X,Y,Z,W) );
+ sse_shufps(p->func, data, data, SHUF(Y,Z,X,W) );
+ sse_movlps(p->func, data, arg0);
+}
+
+static void emit_load_R32G32( struct translate_sse *p,
+ struct x86_reg data,
+ struct x86_reg arg0 )
+{
+ /* 0 0 0 1
+ * a b 0 1
+ */
+ sse_movups(p->func, data, get_identity(p) );
+ sse_movlps(p->func, data, arg0);
+}
+
+
+static void emit_load_R32( struct translate_sse *p,
+ struct x86_reg data,
+ struct x86_reg arg0 )
+{
+ /* a 0 0 0
+ * a 0 0 1
+ */
+ sse_movss(p->func, data, arg0);
+ sse_orps(p->func, data, get_identity(p) );
+}
+
+
+static void emit_load_R8G8B8A8_UNORM( struct translate_sse *p,
+ struct x86_reg data,
+ struct x86_reg src )
+{
+
+ /* Load and unpack twice:
+ */
+ sse_movss(p->func, data, src);
+ sse2_punpcklbw(p->func, data, get_identity(p));
+ sse2_punpcklbw(p->func, data, get_identity(p));
+
+ /* Convert to float:
+ */
+ sse2_cvtdq2ps(p->func, data, data);
+
+
+ /* Scale by 1/255.0
+ */
+ sse_mulps(p->func, data, get_inv_255(p));
+}
+
+
+
+
+static void emit_store_R32G32B32A32( struct translate_sse *p,
+ struct x86_reg dest,
+ struct x86_reg dataXMM )
+{
+ sse_movups(p->func, dest, dataXMM);
+}
+
+static void emit_store_R32G32B32( struct translate_sse *p,
+ struct x86_reg dest,
+ struct x86_reg dataXMM )
+{
+ /* Emit two, shuffle, emit one.
+ */
+ sse_movlps(p->func, dest, dataXMM);
+ sse_shufps(p->func, dataXMM, dataXMM, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
+ sse_movss(p->func, x86_make_disp(dest,8), dataXMM);
+}
+
+static void emit_store_R32G32( struct translate_sse *p,
+ struct x86_reg dest,
+ struct x86_reg dataXMM )
+{
+ sse_movlps(p->func, dest, dataXMM);
+}
+
+static void emit_store_R32( struct translate_sse *p,
+ struct x86_reg dest,
+ struct x86_reg dataXMM )
+{
+ sse_movss(p->func, dest, dataXMM);
+}
+
+
+
+static void emit_store_R8G8B8A8_UNORM( struct translate_sse *p,
+ struct x86_reg dest,
+ struct x86_reg dataXMM )
+{
+ /* Scale by 255.0
+ */
+ sse_mulps(p->func, dataXMM, get_255(p));
+
+ /* Pack and emit:
+ */
+ sse2_cvtps2dq(p->func, dataXMM, dataXMM);
+ sse2_packssdw(p->func, dataXMM, dataXMM);
+ sse2_packuswb(p->func, dataXMM, dataXMM);
+ sse_movss(p->func, dest, dataXMM);
+}
+
+
+
+
+
+/* Extended swizzles? Maybe later.
+ */
+static void emit_swizzle( struct translate_sse *p,
+ struct x86_reg dest,
+ struct x86_reg src,
+ unsigned char shuffle )
+{
+ sse_shufps(p->func, dest, src, shuffle);
+}
+
+
+static boolean translate_attr( struct translate_sse *p,
+ const struct translate_element *a,
+ struct x86_reg srcECX,
+ struct x86_reg dstEAX)
+{
+ struct x86_reg dataXMM = x86_make_reg(file_XMM, 0);
+
+ switch (a->input_format) {
+ case PIPE_FORMAT_R32_FLOAT:
+ emit_load_R32(p, dataXMM, srcECX);
+ break;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ emit_load_R32G32(p, dataXMM, srcECX);
+ break;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ emit_load_R32G32B32(p, dataXMM, srcECX);
+ break;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ emit_load_R32G32B32A32(p, dataXMM, srcECX);
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ emit_load_R8G8B8A8_UNORM(p, dataXMM, srcECX);
+ emit_swizzle(p, dataXMM, dataXMM, SHUF(Z,Y,X,W));
+ break;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ emit_load_R8G8B8A8_UNORM(p, dataXMM, srcECX);
+ break;
+ default:
+ return FALSE;
+ }
+
+ switch (a->output_format) {
+ case PIPE_FORMAT_R32_FLOAT:
+ emit_store_R32(p, dstEAX, dataXMM);
+ break;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ emit_store_R32G32(p, dstEAX, dataXMM);
+ break;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ emit_store_R32G32B32(p, dstEAX, dataXMM);
+ break;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ emit_store_R32G32B32A32(p, dstEAX, dataXMM);
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ emit_swizzle(p, dataXMM, dataXMM, SHUF(Z,Y,X,W));
+ emit_store_R8G8B8A8_UNORM(p, dstEAX, dataXMM);
+ break;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ emit_store_R8G8B8A8_UNORM(p, dstEAX, dataXMM);
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static boolean init_inputs( struct translate_sse *p,
+ boolean linear )
+{
+ unsigned i;
+ if (linear) {
+ for (i = 0; i < p->nr_buffers; i++) {
+ struct x86_reg buf_stride = x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->buffer[i].stride));
+ struct x86_reg buf_ptr = x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->buffer[i].ptr));
+ struct x86_reg buf_base_ptr = x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->buffer[i].base_ptr));
+ struct x86_reg elt = p->idx_EBX;
+ struct x86_reg tmp = p->tmp_EAX;
+
+
+ /* Calculate pointer to first attrib:
+ */
+ x86_mov(p->func, tmp, buf_stride);
+ x86_imul(p->func, tmp, elt);
+ x86_add(p->func, tmp, buf_base_ptr);
+
+
+ /* In the linear case, keep the buffer pointer instead of the
+ * index number.
+ */
+ if (p->nr_buffers == 1)
+ x86_mov( p->func, elt, tmp );
+ else
+ x86_mov( p->func, buf_ptr, tmp );
+ }
+ }
+
+ return TRUE;
+}
+
+
+static struct x86_reg get_buffer_ptr( struct translate_sse *p,
+ boolean linear,
+ unsigned buf_idx,
+ struct x86_reg elt )
+{
+ if (linear && p->nr_buffers == 1) {
+ return p->idx_EBX;
+ }
+ else if (linear) {
+ struct x86_reg ptr = p->tmp_EAX;
+ struct x86_reg buf_ptr =
+ x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->buffer[buf_idx].ptr));
+
+ x86_mov(p->func, ptr, buf_ptr);
+ return ptr;
+ }
+ else {
+ struct x86_reg ptr = p->tmp_EAX;
+
+ struct x86_reg buf_stride =
+ x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->buffer[buf_idx].stride));
+
+ struct x86_reg buf_base_ptr =
+ x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->buffer[buf_idx].base_ptr));
+
+
+
+ /* Calculate pointer to current attrib:
+ */
+ x86_mov(p->func, ptr, buf_stride);
+ x86_imul(p->func, ptr, elt);
+ x86_add(p->func, ptr, buf_base_ptr);
+ return ptr;
+ }
+}
+
+
+
+static boolean incr_inputs( struct translate_sse *p,
+ boolean linear )
+{
+ if (linear && p->nr_buffers == 1) {
+ struct x86_reg stride = x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->buffer[0].stride));
+
+ x86_add(p->func, p->idx_EBX, stride);
+ sse_prefetchnta(p->func, x86_make_disp(p->idx_EBX, 192));
+ }
+ else if (linear) {
+ unsigned i;
+
+ /* Is this worthwhile??
+ */
+ for (i = 0; i < p->nr_buffers; i++) {
+ struct x86_reg buf_ptr = x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->buffer[i].ptr));
+ struct x86_reg buf_stride = x86_make_disp(p->machine_EDX,
+ get_offset(p, &p->buffer[i].stride));
+
+ x86_mov(p->func, p->tmp_EAX, buf_ptr);
+ x86_add(p->func, p->tmp_EAX, buf_stride);
+ if (i == 0) sse_prefetchnta(p->func, x86_make_disp(p->tmp_EAX, 192));
+ x86_mov(p->func, buf_ptr, p->tmp_EAX);
+ }
+ }
+ else {
+ x86_lea(p->func, p->idx_EBX, x86_make_disp(p->idx_EBX, 4));
+ }
+
+ return TRUE;
+}
+
+
+/* Build run( struct translate *machine,
+ * unsigned start,
+ * unsigned count,
+ * void *output_buffer )
+ * or
+ * run_elts( struct translate *machine,
+ * unsigned *elts,
+ * unsigned count,
+ * void *output_buffer )
+ *
+ * Lots of hardcoding
+ *
+ * EAX -- pointer to current output vertex
+ * ECX -- pointer to current attribute
+ *
+ */
+static boolean build_vertex_emit( struct translate_sse *p,
+ struct x86_function *func,
+ boolean linear )
+{
+ int fixup, label;
+ unsigned j;
+
+ p->tmp_EAX = x86_make_reg(file_REG32, reg_AX);
+ p->idx_EBX = x86_make_reg(file_REG32, reg_BX);
+ p->outbuf_ECX = x86_make_reg(file_REG32, reg_CX);
+ p->machine_EDX = x86_make_reg(file_REG32, reg_DX);
+ p->count_ESI = x86_make_reg(file_REG32, reg_SI);
+
+ p->func = func;
+ p->loaded_inv_255 = FALSE;
+ p->loaded_255 = FALSE;
+ p->loaded_identity = FALSE;
+
+ x86_init_func(p->func);
+
+ /* Push a few regs?
+ */
+ x86_push(p->func, p->idx_EBX);
+ x86_push(p->func, p->count_ESI);
+
+ /* Load arguments into regs:
+ */
+ x86_mov(p->func, p->machine_EDX, x86_fn_arg(p->func, 1));
+ x86_mov(p->func, p->idx_EBX, x86_fn_arg(p->func, 2));
+ x86_mov(p->func, p->count_ESI, x86_fn_arg(p->func, 3));
+ x86_mov(p->func, p->outbuf_ECX, x86_fn_arg(p->func, 4));
+
+ /* Get vertex count, compare to zero
+ */
+ x86_xor(p->func, p->tmp_EAX, p->tmp_EAX);
+ x86_cmp(p->func, p->count_ESI, p->tmp_EAX);
+ fixup = x86_jcc_forward(p->func, cc_E);
+
+ /* always load, needed or not:
+ */
+ init_inputs(p, linear);
+
+ /* Note address for loop jump
+ */
+ label = x86_get_label(p->func);
+ {
+ struct x86_reg elt = linear ? p->idx_EBX : x86_deref(p->idx_EBX);
+ int last_vb = -1;
+ struct x86_reg vb;
+
+ for (j = 0; j < p->translate.key.nr_elements; j++) {
+ const struct translate_element *a = &p->translate.key.element[j];
+
+ /* Figure out source pointer address:
+ */
+ if (a->input_buffer != last_vb) {
+ last_vb = a->input_buffer;
+ vb = get_buffer_ptr(p, linear, a->input_buffer, elt);
+ }
+
+ if (!translate_attr( p, a,
+ x86_make_disp(vb, a->input_offset),
+ x86_make_disp(p->outbuf_ECX, a->output_offset)))
+ return FALSE;
+ }
+
+ /* Next output vertex:
+ */
+ x86_lea(p->func,
+ p->outbuf_ECX,
+ x86_make_disp(p->outbuf_ECX,
+ p->translate.key.output_stride));
+
+ /* Incr index
+ */
+ incr_inputs( p, linear );
+ }
+
+ /* decr count, loop if not zero
+ */
+ x86_dec(p->func, p->count_ESI);
+ x86_jcc(p->func, cc_NZ, label);
+
+ /* Exit mmx state?
+ */
+ if (p->func->need_emms)
+ mmx_emms(p->func);
+
+ /* Land forward jump here:
+ */
+ x86_fixup_fwd_jump(p->func, fixup);
+
+ /* Pop regs and return
+ */
+
+ x86_pop(p->func, p->count_ESI);
+ x86_pop(p->func, p->idx_EBX);
+ x86_ret(p->func);
+
+ return TRUE;
+}
+
+
+
+
+
+
+
+static void translate_sse_set_buffer( struct translate *translate,
+ unsigned buf,
+ const void *ptr,
+ unsigned stride )
+{
+ struct translate_sse *p = (struct translate_sse *)translate;
+
+ if (buf < p->nr_buffers) {
+ p->buffer[buf].base_ptr = (char *)ptr;
+ p->buffer[buf].stride = stride;
+ }
+
+ if (0) debug_printf("%s %d/%d: %p %d\n",
+ __FUNCTION__, buf,
+ p->nr_buffers,
+ ptr, stride);
+}
+
+
+static void translate_sse_release( struct translate *translate )
+{
+ struct translate_sse *p = (struct translate_sse *)translate;
+
+ x86_release_func( &p->linear_func );
+ x86_release_func( &p->elt_func );
+
+ FREE(p);
+}
+
+static void PIPE_CDECL translate_sse_run_elts( struct translate *translate,
+ const unsigned *elts,
+ unsigned count,
+ void *output_buffer )
+{
+ struct translate_sse *p = (struct translate_sse *)translate;
+
+ p->gen_run_elts( translate,
+ elts,
+ count,
+ output_buffer );
+}
+
+static void PIPE_CDECL translate_sse_run( struct translate *translate,
+ unsigned start,
+ unsigned count,
+ void *output_buffer )
+{
+ struct translate_sse *p = (struct translate_sse *)translate;
+
+ p->gen_run( translate,
+ start,
+ count,
+ output_buffer );
+}
+
+
+struct translate *translate_sse2_create( const struct translate_key *key )
+{
+ struct translate_sse *p = NULL;
+ unsigned i;
+
+ if (!rtasm_cpu_has_sse() || !rtasm_cpu_has_sse2())
+ goto fail;
+
+ p = CALLOC_STRUCT( translate_sse );
+ if (p == NULL)
+ goto fail;
+
+ p->translate.key = *key;
+ p->translate.release = translate_sse_release;
+ p->translate.set_buffer = translate_sse_set_buffer;
+ p->translate.run_elts = translate_sse_run_elts;
+ p->translate.run = translate_sse_run;
+
+ for (i = 0; i < key->nr_elements; i++)
+ p->nr_buffers = MAX2( p->nr_buffers, key->element[i].input_buffer + 1 );
+
+ if (0) debug_printf("nr_buffers: %d\n", p->nr_buffers);
+
+ if (!build_vertex_emit(p, &p->linear_func, TRUE))
+ goto fail;
+
+ if (!build_vertex_emit(p, &p->elt_func, FALSE))
+ goto fail;
+
+ p->gen_run = (run_func)x86_get_func(&p->linear_func);
+ if (p->gen_run == NULL)
+ goto fail;
+
+ p->gen_run_elts = (run_elts_func)x86_get_func(&p->elt_func);
+ if (p->gen_run_elts == NULL)
+ goto fail;
+
+ return &p->translate;
+
+ fail:
+ if (p)
+ translate_sse_release( &p->translate );
+
+ return NULL;
+}
+
+
+
+#else
+
+struct translate *translate_sse2_create( const struct translate_key *key )
+{
+ return NULL;
+}
+
+#endif
diff --git a/src/gallium/auxiliary/util/.gitignore b/src/gallium/auxiliary/util/.gitignore
new file mode 100644
index 0000000000..29c586c9b5
--- /dev/null
+++ b/src/gallium/auxiliary/util/.gitignore
@@ -0,0 +1,2 @@
+u_format_access.c
+u_format_table.c
diff --git a/src/gallium/auxiliary/util/Makefile b/src/gallium/auxiliary/util/Makefile
new file mode 100644
index 0000000000..ae8d330a78
--- /dev/null
+++ b/src/gallium/auxiliary/util/Makefile
@@ -0,0 +1,44 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = util
+
+C_SOURCES = \
+ u_debug.c \
+ u_debug_dump.c \
+ u_debug_symbol.c \
+ u_debug_stack.c \
+ u_blit.c \
+ u_cache.c \
+ u_draw_quad.c \
+ u_format.c \
+ u_format_access.c \
+ u_format_table.c \
+ u_gen_mipmap.c \
+ u_handle_table.c \
+ u_hash_table.c \
+ u_hash.c \
+ u_keymap.c \
+ u_linear.c \
+ u_network.c \
+ u_math.c \
+ u_mm.c \
+ u_rect.c \
+ u_simple_shaders.c \
+ u_snprintf.c \
+ u_stream_stdc.c \
+ u_stream_wd.c \
+ u_surface.c \
+ u_tile.c \
+ u_time.c \
+ u_timed_winsys.c \
+ u_upload_mgr.c \
+ u_simple_screen.c
+
+include ../../Makefile.template
+
+u_format_table.c: u_format_table.py u_format_parse.py u_format.csv
+ python u_format_table.py u_format.csv > $@
+
+u_format_access.c: u_format_access.py u_format_parse.py u_format.csv
+ python u_format_access.py u_format.csv > $@
diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript
new file mode 100644
index 0000000000..28a5ab4256
--- /dev/null
+++ b/src/gallium/auxiliary/util/SConscript
@@ -0,0 +1,58 @@
+Import('*')
+
+env.Clone()
+
+env.Append(CPPPATH = ['.'])
+
+env.CodeGenerate(
+ target = 'u_format_table.c',
+ script = 'u_format_table.py',
+ source = ['u_format.csv'],
+ command = 'python $SCRIPT $SOURCE > $TARGET'
+)
+
+env.CodeGenerate(
+ target = 'u_format_access.c',
+ script = 'u_format_access.py',
+ source = ['u_format.csv'],
+ command = 'python $SCRIPT $SOURCE > $TARGET'
+)
+
+util = env.ConvenienceLibrary(
+ target = 'util',
+ source = [
+ 'u_bitmask.c',
+ 'u_blit.c',
+ 'u_cache.c',
+ 'u_debug.c',
+ 'u_debug_dump.c',
+ 'u_debug_memory.c',
+ 'u_debug_profile.c',
+ 'u_debug_stack.c',
+ 'u_debug_symbol.c',
+ 'u_draw_quad.c',
+ 'u_format.c',
+ 'u_format_access.c',
+ 'u_format_table.c',
+ 'u_gen_mipmap.c',
+ 'u_handle_table.c',
+ 'u_hash.c',
+ 'u_hash_table.c',
+ 'u_keymap.c',
+ 'u_network.c',
+ 'u_math.c',
+ 'u_mm.c',
+ 'u_rect.c',
+ 'u_simple_shaders.c',
+ 'u_snprintf.c',
+ 'u_stream_stdc.c',
+ 'u_stream_wd.c',
+ 'u_surface.c',
+ 'u_tile.c',
+ 'u_time.c',
+ 'u_timed_winsys.c',
+ 'u_upload_mgr.c',
+ 'u_simple_screen.c',
+ ])
+
+auxiliaries.insert(0, util)
diff --git a/src/gallium/auxiliary/util/u_bitmask.c b/src/gallium/auxiliary/util/u_bitmask.c
new file mode 100644
index 0000000000..77587c07ec
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_bitmask.c
@@ -0,0 +1,320 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Generic bitmask implementation.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+
+#include "util/u_memory.h"
+#include "util/u_bitmask.h"
+
+
+typedef uint32_t util_bitmask_word;
+
+
+#define UTIL_BITMASK_INITIAL_WORDS 16
+#define UTIL_BITMASK_BITS_PER_BYTE 8
+#define UTIL_BITMASK_BITS_PER_WORD (sizeof(util_bitmask_word) * UTIL_BITMASK_BITS_PER_BYTE)
+
+
+struct util_bitmask
+{
+ util_bitmask_word *words;
+
+ /** Number of bits we can currently hold */
+ unsigned size;
+
+ /** Number of consecutive bits set at the start of the bitmask */
+ unsigned filled;
+};
+
+
+struct util_bitmask *
+util_bitmask_create(void)
+{
+ struct util_bitmask *bm;
+
+ bm = MALLOC_STRUCT(util_bitmask);
+ if(!bm)
+ return NULL;
+
+ bm->words = (util_bitmask_word *)CALLOC(UTIL_BITMASK_INITIAL_WORDS, sizeof(util_bitmask_word));
+ if(!bm->words) {
+ FREE(bm);
+ return NULL;
+ }
+
+ bm->size = UTIL_BITMASK_INITIAL_WORDS * UTIL_BITMASK_BITS_PER_WORD;
+ bm->filled = 0;
+
+ return bm;
+}
+
+
+/**
+ * Resize the bitmask if necessary
+ */
+static INLINE boolean
+util_bitmask_resize(struct util_bitmask *bm,
+ unsigned minimum_index)
+{
+ unsigned minimum_size = minimum_index + 1;
+ unsigned new_size;
+ util_bitmask_word *new_words;
+
+ /* Check integer overflow */
+ if(!minimum_size)
+ return FALSE;
+
+ if(bm->size > minimum_size)
+ return TRUE;
+
+ assert(bm->size % UTIL_BITMASK_BITS_PER_WORD == 0);
+ new_size = bm->size;
+ while(!(new_size > minimum_size)) {
+ new_size *= 2;
+ /* Check integer overflow */
+ if(new_size < bm->size)
+ return FALSE;
+ }
+ assert(new_size);
+ assert(new_size % UTIL_BITMASK_BITS_PER_WORD == 0);
+
+ new_words = (util_bitmask_word *)REALLOC((void *)bm->words,
+ bm->size / UTIL_BITMASK_BITS_PER_BYTE,
+ new_size / UTIL_BITMASK_BITS_PER_BYTE);
+ if(!new_words)
+ return FALSE;
+
+ memset(new_words + bm->size/UTIL_BITMASK_BITS_PER_WORD,
+ 0,
+ (new_size - bm->size)/UTIL_BITMASK_BITS_PER_BYTE);
+
+ bm->size = new_size;
+ bm->words = new_words;
+
+ return TRUE;
+}
+
+
+/**
+ * Lazily update the filled.
+ */
+static INLINE void
+util_bitmask_filled_set(struct util_bitmask *bm,
+ unsigned index)
+{
+ assert(bm->filled <= bm->size);
+ assert(index <= bm->size);
+
+ if(index == bm->filled) {
+ ++bm->filled;
+ assert(bm->filled <= bm->size);
+ }
+}
+
+static INLINE void
+util_bitmask_filled_unset(struct util_bitmask *bm,
+ unsigned index)
+{
+ assert(bm->filled <= bm->size);
+ assert(index <= bm->size);
+
+ if(index < bm->filled)
+ bm->filled = index;
+}
+
+
+unsigned
+util_bitmask_add(struct util_bitmask *bm)
+{
+ unsigned word;
+ unsigned bit;
+ util_bitmask_word mask;
+
+ assert(bm);
+
+ /* linear search for an empty index */
+ word = bm->filled / UTIL_BITMASK_BITS_PER_WORD;
+ bit = bm->filled % UTIL_BITMASK_BITS_PER_WORD;
+ mask = 1 << bit;
+ while(word < bm->size / UTIL_BITMASK_BITS_PER_WORD) {
+ while(bit < UTIL_BITMASK_BITS_PER_WORD) {
+ if(!(bm->words[word] & mask))
+ goto found;
+ ++bm->filled;
+ ++bit;
+ mask <<= 1;
+ }
+ ++word;
+ bit = 0;
+ mask = 1;
+ }
+found:
+
+ /* grow the bitmask if necessary */
+ if(!util_bitmask_resize(bm, bm->filled))
+ return UTIL_BITMASK_INVALID_INDEX;
+
+ assert(!(bm->words[word] & mask));
+ bm->words[word] |= mask;
+
+ return bm->filled++;
+}
+
+
+unsigned
+util_bitmask_set(struct util_bitmask *bm,
+ unsigned index)
+{
+ unsigned word = index / UTIL_BITMASK_BITS_PER_WORD;
+ unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD;
+ util_bitmask_word mask = 1 << bit;
+
+ assert(bm);
+
+ /* grow the bitmask if necessary */
+ if(!util_bitmask_resize(bm, index))
+ return UTIL_BITMASK_INVALID_INDEX;
+
+ bm->words[word] |= mask;
+
+ util_bitmask_filled_set(bm, index);
+
+ return index;
+}
+
+
+void
+util_bitmask_clear(struct util_bitmask *bm,
+ unsigned index)
+{
+ unsigned word = index / UTIL_BITMASK_BITS_PER_WORD;
+ unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD;
+ util_bitmask_word mask = 1 << bit;
+
+ assert(bm);
+
+ if(index >= bm->size)
+ return;
+
+ bm->words[word] &= ~mask;
+
+ util_bitmask_filled_unset(bm, index);
+}
+
+
+boolean
+util_bitmask_get(struct util_bitmask *bm,
+ unsigned index)
+{
+ unsigned word = index / UTIL_BITMASK_BITS_PER_WORD;
+ unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD;
+ util_bitmask_word mask = 1 << bit;
+
+ assert(bm);
+
+ if(index < bm->filled) {
+ assert(bm->words[word] & mask);
+ return TRUE;
+ }
+
+ if(index > bm->size)
+ return FALSE;
+
+ if(bm->words[word] & mask) {
+ util_bitmask_filled_set(bm, index);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+unsigned
+util_bitmask_get_next_index(struct util_bitmask *bm,
+ unsigned index)
+{
+ unsigned word = index / UTIL_BITMASK_BITS_PER_WORD;
+ unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD;
+ util_bitmask_word mask = 1 << bit;
+
+ if(index < bm->filled) {
+ assert(bm->words[word] & mask);
+ return index;
+ }
+
+ if(index >= bm->size) {
+ return UTIL_BITMASK_INVALID_INDEX;
+ }
+
+ /* Do a linear search */
+ while(word < bm->size / UTIL_BITMASK_BITS_PER_WORD) {
+ while(bit < UTIL_BITMASK_BITS_PER_WORD) {
+ if(bm->words[word] & mask) {
+ if(index == bm->filled) {
+ ++bm->filled;
+ assert(bm->filled <= bm->size);
+ }
+ return index;
+ }
+ ++index;
+ ++bit;
+ mask <<= 1;
+ }
+ ++word;
+ bit = 0;
+ mask = 1;
+ }
+
+ return UTIL_BITMASK_INVALID_INDEX;
+}
+
+
+unsigned
+util_bitmask_get_first_index(struct util_bitmask *bm)
+{
+ return util_bitmask_get_next_index(bm, 0);
+}
+
+
+void
+util_bitmask_destroy(struct util_bitmask *bm)
+{
+ assert(bm);
+
+ FREE(bm->words);
+ FREE(bm);
+}
+
diff --git a/src/gallium/auxiliary/util/u_bitmask.h b/src/gallium/auxiliary/util/u_bitmask.h
new file mode 100644
index 0000000000..87f1110296
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_bitmask.h
@@ -0,0 +1,114 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Generic bitmask.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef U_HANDLE_BITMASK_H_
+#define U_HANDLE_BITMASK_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define UTIL_BITMASK_INVALID_INDEX (~0U)
+
+
+/**
+ * Abstract data type to represent arbitrary set of bits.
+ */
+struct util_bitmask;
+
+
+struct util_bitmask *
+util_bitmask_create(void);
+
+
+/**
+ * Search a cleared bit and set it.
+ *
+ * It searches for the first cleared bit.
+ *
+ * Returns the bit index on success, or UTIL_BITMASK_INVALID_INDEX on out of
+ * memory growing the bitmask.
+ */
+unsigned
+util_bitmask_add(struct util_bitmask *bm);
+
+/**
+ * Set a bit.
+ *
+ * Returns the input index on success, or UTIL_BITMASK_INVALID_INDEX on out of
+ * memory growing the bitmask.
+ */
+unsigned
+util_bitmask_set(struct util_bitmask *bm,
+ unsigned index);
+
+void
+util_bitmask_clear(struct util_bitmask *bm,
+ unsigned index);
+
+boolean
+util_bitmask_get(struct util_bitmask *bm,
+ unsigned index);
+
+
+void
+util_bitmask_destroy(struct util_bitmask *bm);
+
+
+/**
+ * Search for the first set bit.
+ *
+ * Returns UTIL_BITMASK_INVALID_INDEX if a set bit cannot be found.
+ */
+unsigned
+util_bitmask_get_first_index(struct util_bitmask *bm);
+
+
+/**
+ * Search for the first set bit, starting from the giving index.
+ *
+ * Returns UTIL_BITMASK_INVALID_INDEX if a set bit cannot be found.
+ */
+unsigned
+util_bitmask_get_next_index(struct util_bitmask *bm,
+ unsigned index);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_HANDLE_BITMASK_H_ */
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
new file mode 100644
index 0000000000..c516317d70
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -0,0 +1,600 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Copy/blit pixel rect between surfaces
+ *
+ * @author Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "util/u_debug.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_state.h"
+
+#include "util/u_blit.h"
+#include "util/u_draw_quad.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_simple_shaders.h"
+#include "util/u_surface.h"
+
+#include "cso_cache/cso_context.h"
+
+
+struct blit_state
+{
+ struct pipe_context *pipe;
+ struct cso_context *cso;
+
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state sampler;
+ struct pipe_viewport_state viewport;
+
+ void *vs;
+ void *fs[TGSI_WRITEMASK_XYZW + 1];
+
+ struct pipe_buffer *vbuf; /**< quad vertices */
+ unsigned vbuf_slot;
+
+ float vertices[4][2][4]; /**< vertex/texcoords for quad */
+};
+
+
+/**
+ * Create state object for blit.
+ * Intended to be created once and re-used for many blit() calls.
+ */
+struct blit_state *
+util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
+{
+ struct blit_state *ctx;
+ uint i;
+
+ ctx = CALLOC_STRUCT(blit_state);
+ if (!ctx)
+ return NULL;
+
+ ctx->pipe = pipe;
+ ctx->cso = cso;
+
+ /* disabled blending/masking */
+ memset(&ctx->blend, 0, sizeof(ctx->blend));
+ ctx->blend.colormask = PIPE_MASK_RGBA;
+
+ /* no-op depth/stencil/alpha */
+ memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
+
+ /* rasterizer */
+ memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
+ ctx->rasterizer.front_winding = PIPE_WINDING_CW;
+ ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
+ ctx->rasterizer.bypass_vs_clip_and_viewport = 1;
+ ctx->rasterizer.gl_rasterization_rules = 1;
+
+ /* samplers */
+ memset(&ctx->sampler, 0, sizeof(ctx->sampler));
+ ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ ctx->sampler.min_img_filter = 0; /* set later */
+ ctx->sampler.mag_img_filter = 0; /* set later */
+ ctx->sampler.normalized_coords = 1;
+
+
+ /* vertex shader - still required to provide the linkage between
+ * fragment shader input semantics and vertex_element/buffers.
+ */
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0 };
+ ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
+ semantic_indexes);
+ }
+
+ /* fragment shader */
+ ctx->fs[TGSI_WRITEMASK_XYZW] = util_make_fragment_tex_shader(pipe);
+ ctx->vbuf = NULL;
+
+ /* init vertex data that doesn't change */
+ for (i = 0; i < 4; i++) {
+ ctx->vertices[i][0][3] = 1.0f; /* w */
+ ctx->vertices[i][1][2] = 0.0f; /* r */
+ ctx->vertices[i][1][3] = 1.0f; /* q */
+ }
+
+ return ctx;
+}
+
+
+/**
+ * Destroy a blit context
+ */
+void
+util_destroy_blit(struct blit_state *ctx)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ unsigned i;
+
+ pipe->delete_vs_state(pipe, ctx->vs);
+
+ for (i = 0; i < Elements(ctx->fs); i++)
+ if (ctx->fs[i])
+ pipe->delete_fs_state(pipe, ctx->fs[i]);
+
+ pipe_buffer_reference(&ctx->vbuf, NULL);
+
+ FREE(ctx);
+}
+
+
+/**
+ * Get offset of next free slot in vertex buffer for quad vertices.
+ */
+static unsigned
+get_next_slot( struct blit_state *ctx )
+{
+ const unsigned max_slots = 4096 / sizeof ctx->vertices;
+
+ if (ctx->vbuf_slot >= max_slots)
+ util_blit_flush( ctx );
+
+ if (!ctx->vbuf) {
+ ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
+ 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ max_slots * sizeof ctx->vertices);
+ }
+
+ return ctx->vbuf_slot++ * sizeof ctx->vertices;
+}
+
+
+/**
+ * Setup vertex data for the textured quad we'll draw.
+ * Note: y=0=top
+ */
+static unsigned
+setup_vertex_data(struct blit_state *ctx,
+ float x0, float y0, float x1, float y1, float z)
+{
+ unsigned offset;
+
+ ctx->vertices[0][0][0] = x0;
+ ctx->vertices[0][0][1] = y0;
+ ctx->vertices[0][0][2] = z;
+ ctx->vertices[0][1][0] = 0.0f; /*s*/
+ ctx->vertices[0][1][1] = 0.0f; /*t*/
+
+ ctx->vertices[1][0][0] = x1;
+ ctx->vertices[1][0][1] = y0;
+ ctx->vertices[1][0][2] = z;
+ ctx->vertices[1][1][0] = 1.0f; /*s*/
+ ctx->vertices[1][1][1] = 0.0f; /*t*/
+
+ ctx->vertices[2][0][0] = x1;
+ ctx->vertices[2][0][1] = y1;
+ ctx->vertices[2][0][2] = z;
+ ctx->vertices[2][1][0] = 1.0f;
+ ctx->vertices[2][1][1] = 1.0f;
+
+ ctx->vertices[3][0][0] = x0;
+ ctx->vertices[3][0][1] = y1;
+ ctx->vertices[3][0][2] = z;
+ ctx->vertices[3][1][0] = 0.0f;
+ ctx->vertices[3][1][1] = 1.0f;
+
+ offset = get_next_slot( ctx );
+
+ pipe_buffer_write(ctx->pipe->screen, ctx->vbuf,
+ offset, sizeof(ctx->vertices), ctx->vertices);
+
+ return offset;
+}
+
+
+/**
+ * Setup vertex data for the textured quad we'll draw.
+ * Note: y=0=top
+ */
+static unsigned
+setup_vertex_data_tex(struct blit_state *ctx,
+ float x0, float y0, float x1, float y1,
+ float s0, float t0, float s1, float t1,
+ float z)
+{
+ unsigned offset;
+
+ ctx->vertices[0][0][0] = x0;
+ ctx->vertices[0][0][1] = y0;
+ ctx->vertices[0][0][2] = z;
+ ctx->vertices[0][1][0] = s0; /*s*/
+ ctx->vertices[0][1][1] = t0; /*t*/
+
+ ctx->vertices[1][0][0] = x1;
+ ctx->vertices[1][0][1] = y0;
+ ctx->vertices[1][0][2] = z;
+ ctx->vertices[1][1][0] = s1; /*s*/
+ ctx->vertices[1][1][1] = t0; /*t*/
+
+ ctx->vertices[2][0][0] = x1;
+ ctx->vertices[2][0][1] = y1;
+ ctx->vertices[2][0][2] = z;
+ ctx->vertices[2][1][0] = s1;
+ ctx->vertices[2][1][1] = t1;
+
+ ctx->vertices[3][0][0] = x0;
+ ctx->vertices[3][0][1] = y1;
+ ctx->vertices[3][0][2] = z;
+ ctx->vertices[3][1][0] = s0;
+ ctx->vertices[3][1][1] = t1;
+
+ offset = get_next_slot( ctx );
+
+ pipe_buffer_write(ctx->pipe->screen, ctx->vbuf,
+ offset, sizeof(ctx->vertices), ctx->vertices);
+
+ return offset;
+}
+
+
+/**
+ * \return TRUE if two regions overlap, FALSE otherwise
+ */
+static boolean
+regions_overlap(int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1)
+{
+ if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
+ return FALSE; /* src completely left of dst */
+
+ if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
+ return FALSE; /* dst completely left of src */
+
+ if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
+ return FALSE; /* src completely above dst */
+
+ if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
+ return FALSE; /* dst completely above src */
+
+ return TRUE; /* some overlap */
+}
+
+
+/**
+ * Copy pixel block from src surface to dst surface.
+ * Overlapping regions are acceptable.
+ * Flipping and stretching are supported.
+ * XXX what about clipping???
+ * XXX need some control over blitting Z and/or stencil.
+ */
+void
+util_blit_pixels_writemask(struct blit_state *ctx,
+ struct pipe_surface *src,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter,
+ uint writemask)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture texTemp, *tex;
+ struct pipe_surface *texSurf;
+ struct pipe_framebuffer_state fb;
+ const int srcW = abs(srcX1 - srcX0);
+ const int srcH = abs(srcY1 - srcY0);
+ const int srcLeft = MIN2(srcX0, srcX1);
+ const int srcTop = MIN2(srcY0, srcY1);
+ unsigned offset;
+ boolean overlap;
+
+ assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
+ filter == PIPE_TEX_MIPFILTER_LINEAR);
+
+ assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0));
+ assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
+
+ /* do the regions overlap? */
+ overlap = util_same_surface(src, dst) &&
+ regions_overlap(srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1);
+
+ /*
+ * Check for simple case: no format conversion, no flipping, no stretching,
+ * no overlapping.
+ * Filter mode should not matter since there's no stretching.
+ */
+ if (dst->format == src->format &&
+ srcX0 < srcX1 &&
+ dstX0 < dstX1 &&
+ srcY0 < srcY1 &&
+ dstY0 < dstY1 &&
+ (dstX1 - dstX0) == (srcX1 - srcX0) &&
+ (dstY1 - dstY0) == (srcY1 - srcY0) &&
+ !overlap) {
+ pipe->surface_copy(pipe,
+ dst, dstX0, dstY0, /* dest */
+ src, srcX0, srcY0, /* src */
+ srcW, srcH); /* size */
+ return;
+ }
+
+ if (srcLeft != srcX0) {
+ /* left-right flip */
+ int tmp = dstX0;
+ dstX0 = dstX1;
+ dstX1 = tmp;
+ }
+
+ if (srcTop != srcY0) {
+ /* up-down flip */
+ int tmp = dstY0;
+ dstY0 = dstY1;
+ dstY1 = tmp;
+ }
+
+ assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
+
+ /*
+ * XXX for now we're always creating a temporary texture.
+ * Strictly speaking that's not always needed.
+ */
+
+ /* create temp texture */
+ memset(&texTemp, 0, sizeof(texTemp));
+ texTemp.target = PIPE_TEXTURE_2D;
+ texTemp.format = src->format;
+ texTemp.last_level = 0;
+ texTemp.width[0] = srcW;
+ texTemp.height[0] = srcH;
+ texTemp.depth[0] = 1;
+ pf_get_block(src->format, &texTemp.block);
+
+ tex = screen->texture_create(screen, &texTemp);
+ if (!tex)
+ return;
+
+ texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* load temp texture */
+ pipe->surface_copy(pipe,
+ texSurf, 0, 0, /* dest */
+ src, srcLeft, srcTop, /* src */
+ srcW, srcH); /* size */
+
+ /* free the surface, update the texture if necessary.
+ */
+ pipe_surface_reference(&texSurf, NULL);
+
+ /* save state (restored below) */
+ cso_save_blend(ctx->cso);
+ cso_save_depth_stencil_alpha(ctx->cso);
+ cso_save_rasterizer(ctx->cso);
+ cso_save_samplers(ctx->cso);
+ cso_save_sampler_textures(ctx->cso);
+ cso_save_framebuffer(ctx->cso);
+ cso_save_fragment_shader(ctx->cso);
+ cso_save_vertex_shader(ctx->cso);
+
+ /* set misc state we care about */
+ cso_set_blend(ctx->cso, &ctx->blend);
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+ cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
+
+ /* sampler */
+ ctx->sampler.min_img_filter = filter;
+ ctx->sampler.mag_img_filter = filter;
+ cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+ cso_single_sampler_done(ctx->cso);
+
+ /* texture */
+ cso_set_sampler_textures(ctx->cso, 1, &tex);
+
+ if (ctx->fs[writemask] == NULL)
+ ctx->fs[writemask] = util_make_fragment_tex_shader_writemask(pipe, writemask);
+
+ /* shaders */
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
+ cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
+
+ /* drawing dest */
+ memset(&fb, 0, sizeof(fb));
+ fb.width = dst->width;
+ fb.height = dst->height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = dst;
+ cso_set_framebuffer(ctx->cso, &fb);
+
+ /* draw quad */
+ offset = setup_vertex_data(ctx,
+ (float) dstX0, (float) dstY0,
+ (float) dstX1, (float) dstY1, z);
+
+ util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ /* restore state we changed */
+ cso_restore_blend(ctx->cso);
+ cso_restore_depth_stencil_alpha(ctx->cso);
+ cso_restore_rasterizer(ctx->cso);
+ cso_restore_samplers(ctx->cso);
+ cso_restore_sampler_textures(ctx->cso);
+ cso_restore_framebuffer(ctx->cso);
+ cso_restore_fragment_shader(ctx->cso);
+ cso_restore_vertex_shader(ctx->cso);
+
+ pipe_texture_reference(&tex, NULL);
+}
+
+
+void
+util_blit_pixels(struct blit_state *ctx,
+ struct pipe_surface *src,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter )
+{
+ util_blit_pixels_writemask( ctx, src,
+ srcX0, srcY0,
+ srcX1, srcY1,
+ dst,
+ dstX0, dstY0,
+ dstX1, dstY1,
+ z, filter,
+ TGSI_WRITEMASK_XYZW );
+}
+
+
+/* Release vertex buffer at end of frame to avoid synchronous
+ * rendering.
+ */
+void util_blit_flush( struct blit_state *ctx )
+{
+ pipe_buffer_reference(&ctx->vbuf, NULL);
+ ctx->vbuf_slot = 0;
+}
+
+
+
+/**
+ * Copy pixel block from src texture to dst surface.
+ * Overlapping regions are acceptable.
+ *
+ * XXX Should support selection of level.
+ * XXX need some control over blitting Z and/or stencil.
+ */
+void
+util_blit_pixels_tex(struct blit_state *ctx,
+ struct pipe_texture *tex,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter)
+{
+ struct pipe_framebuffer_state fb;
+ float s0, t0, s1, t1;
+ unsigned offset;
+
+ assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
+ filter == PIPE_TEX_MIPFILTER_LINEAR);
+
+ assert(tex->width[0] != 0);
+ assert(tex->height[0] != 0);
+
+ s0 = srcX0 / (float)tex->width[0];
+ s1 = srcX1 / (float)tex->width[0];
+ t0 = srcY0 / (float)tex->height[0];
+ t1 = srcY1 / (float)tex->height[0];
+
+ assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ 0));
+
+ /* save state (restored below) */
+ cso_save_blend(ctx->cso);
+ cso_save_depth_stencil_alpha(ctx->cso);
+ cso_save_rasterizer(ctx->cso);
+ cso_save_samplers(ctx->cso);
+ cso_save_sampler_textures(ctx->cso);
+ cso_save_framebuffer(ctx->cso);
+ cso_save_fragment_shader(ctx->cso);
+ cso_save_vertex_shader(ctx->cso);
+
+ /* set misc state we care about */
+ cso_set_blend(ctx->cso, &ctx->blend);
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+ cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
+
+ /* sampler */
+ ctx->sampler.min_img_filter = filter;
+ ctx->sampler.mag_img_filter = filter;
+ cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+ cso_single_sampler_done(ctx->cso);
+
+ /* texture */
+ cso_set_sampler_textures(ctx->cso, 1, &tex);
+
+ /* shaders */
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs[TGSI_WRITEMASK_XYZW]);
+ cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
+
+ /* drawing dest */
+ memset(&fb, 0, sizeof(fb));
+ fb.width = dst->width;
+ fb.height = dst->height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = dst;
+ cso_set_framebuffer(ctx->cso, &fb);
+
+ /* draw quad */
+ offset = setup_vertex_data_tex(ctx,
+ (float) dstX0, (float) dstY0,
+ (float) dstX1, (float) dstY1,
+ s0, t0, s1, t1,
+ z);
+
+ util_draw_vertex_buffer(ctx->pipe,
+ ctx->vbuf, offset,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ /* restore state we changed */
+ cso_restore_blend(ctx->cso);
+ cso_restore_depth_stencil_alpha(ctx->cso);
+ cso_restore_rasterizer(ctx->cso);
+ cso_restore_samplers(ctx->cso);
+ cso_restore_sampler_textures(ctx->cso);
+ cso_restore_framebuffer(ctx->cso);
+ cso_restore_fragment_shader(ctx->cso);
+ cso_restore_vertex_shader(ctx->cso);
+}
diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h
new file mode 100644
index 0000000000..a102021529
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_blit.h
@@ -0,0 +1,93 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef U_BLIT_H
+#define U_BLIT_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_context;
+struct pipe_surface;
+struct pipe_texture;
+struct cso_context;
+
+
+struct blit_state;
+
+
+extern struct blit_state *
+util_create_blit(struct pipe_context *pipe, struct cso_context *cso);
+
+extern void
+util_destroy_blit(struct blit_state *ctx);
+
+extern void
+util_blit_pixels(struct blit_state *ctx,
+ struct pipe_surface *src,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter);
+
+void
+util_blit_pixels_writemask(struct blit_state *ctx,
+ struct pipe_surface *src,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter,
+ uint writemask);
+
+extern void
+util_blit_pixels_tex(struct blit_state *ctx,
+ struct pipe_texture *tex,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter);
+
+/* Call at end of frame to avoid synchronous rendering.
+ */
+extern void
+util_blit_flush( struct blit_state *ctx );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_cache.c b/src/gallium/auxiliary/util/u_cache.c
new file mode 100644
index 0000000000..47c16b1c92
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_cache.c
@@ -0,0 +1,217 @@
+/**************************************************************************
+ *
+ * Copyright 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Simple cache implementation.
+ *
+ * We simply have fixed size array, and destroy previous values on collision.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_cache.h"
+
+
+struct util_cache_entry
+{
+ void *key;
+ void *value;
+
+#ifdef DEBUG
+ unsigned count;
+#endif
+};
+
+
+struct util_cache
+{
+ /** Hash function */
+ uint32_t (*hash)(const void *key);
+
+ /** Compare two keys */
+ int (*compare)(const void *key1, const void *key2);
+
+ /** Destroy a (key, value) pair */
+ void (*destroy)(void *key, void *value);
+
+ uint32_t size;
+
+ struct util_cache_entry *entries;
+
+#ifdef DEBUG
+ unsigned count;
+#endif
+};
+
+
+struct util_cache *
+util_cache_create(uint32_t (*hash)(const void *key),
+ int (*compare)(const void *key1, const void *key2),
+ void (*destroy)(void *key, void *value),
+ uint32_t size)
+{
+ struct util_cache *cache;
+
+ cache = CALLOC_STRUCT(util_cache);
+ if(!cache)
+ return NULL;
+
+ cache->hash = hash;
+ cache->compare = compare;
+ cache->destroy = destroy;
+ cache->size = size;
+
+ cache->entries = CALLOC(size, sizeof(struct util_cache_entry));
+ if(!cache->entries) {
+ FREE(cache);
+ return NULL;
+ }
+
+ return cache;
+}
+
+
+static INLINE struct util_cache_entry *
+util_cache_entry_get(struct util_cache *cache,
+ const void *key)
+{
+ uint32_t hash;
+
+ hash = cache->hash(key);
+
+ return &cache->entries[hash % cache->size];
+}
+
+static INLINE void
+util_cache_entry_destroy(struct util_cache *cache,
+ struct util_cache_entry *entry)
+{
+ void *key = entry->key;
+ void *value = entry->value;
+
+ entry->key = NULL;
+ entry->value = NULL;
+
+ if(key || value)
+ if(cache->destroy)
+ cache->destroy(key, value);
+}
+
+
+void
+util_cache_set(struct util_cache *cache,
+ void *key,
+ void *value)
+{
+ struct util_cache_entry *entry;
+
+ assert(cache);
+ if (!cache)
+ return;
+
+ entry = util_cache_entry_get(cache, key);
+ util_cache_entry_destroy(cache, entry);
+
+#ifdef DEBUG
+ ++entry->count;
+ ++cache->count;
+#endif
+
+ entry->key = key;
+ entry->value = value;
+}
+
+
+void *
+util_cache_get(struct util_cache *cache,
+ const void *key)
+{
+ struct util_cache_entry *entry;
+
+ assert(cache);
+ if (!cache)
+ return NULL;
+
+ entry = util_cache_entry_get(cache, key);
+ if(!entry->key && !entry->value)
+ return NULL;
+
+ if(cache->compare(key, entry->key) != 0)
+ return NULL;
+
+ return entry->value;
+}
+
+
+void
+util_cache_clear(struct util_cache *cache)
+{
+ uint32_t i;
+
+ assert(cache);
+ if (!cache)
+ return;
+
+ for(i = 0; i < cache->size; ++i)
+ util_cache_entry_destroy(cache, &cache->entries[i]);
+}
+
+
+void
+util_cache_destroy(struct util_cache *cache)
+{
+ assert(cache);
+ if (!cache)
+ return;
+
+#ifdef DEBUG
+ if(cache->count >= 20*cache->size) {
+ /* Normal approximation of the Poisson distribution */
+ double mean = (double)cache->count/(double)cache->size;
+ double stddev = sqrt(mean);
+ unsigned i;
+ for(i = 0; i < cache->size; ++i) {
+ double z = fabs(cache->count - mean)/stddev;
+ /* This assert should not fail 99.9999998027% of the times, unless
+ * the hash function is a poor one */
+ assert(z <= 6.0);
+ }
+ }
+#endif
+
+ util_cache_clear(cache);
+
+ FREE(cache->entries);
+ FREE(cache);
+}
diff --git a/src/gallium/auxiliary/util/u_cache.h b/src/gallium/auxiliary/util/u_cache.h
new file mode 100644
index 0000000000..8a612c6585
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_cache.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+ *
+ * Copyright 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Simple cache.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef U_CACHE_H_
+#define U_CACHE_H_
+
+
+#include "pipe/p_compiler.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Least Recently Used (LRU) cache.
+ */
+struct util_cache;
+
+
+/**
+ * Create a cache.
+ *
+ * @param hash hash function
+ * @param compare should return 0 for two equal keys
+ * @param destroy destruction callback (optional)
+ * @param size maximum number of entries
+ */
+struct util_cache *
+util_cache_create(uint32_t (*hash)(const void *key),
+ int (*compare)(const void *key1, const void *key2),
+ void (*destroy)(void *key, void *value),
+ uint32_t size);
+
+void
+util_cache_set(struct util_cache *cache,
+ void *key,
+ void *value);
+
+void *
+util_cache_get(struct util_cache *cache,
+ const void *key);
+
+void
+util_cache_clear(struct util_cache *cache);
+
+void
+util_cache_destroy(struct util_cache *cache);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_CACHE_H_ */
diff --git a/src/gallium/auxiliary/util/u_clear.h b/src/gallium/auxiliary/util/u_clear.h
new file mode 100644
index 0000000000..7c16b32cf9
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_clear.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors:
+ * Michel Dänzer
+ */
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "util/u_pack_color.h"
+
+
+/**
+ * Clear the given buffers to the specified values.
+ * No masking, no scissor (clear entire buffer).
+ */
+static INLINE void
+util_clear(struct pipe_context *pipe,
+ struct pipe_framebuffer_state *framebuffer, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil)
+{
+ if (buffers & PIPE_CLEAR_COLOR) {
+ struct pipe_surface *ps = framebuffer->cbufs[0];
+ unsigned color;
+
+ util_pack_color(rgba, ps->format, &color);
+ pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, color);
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+ struct pipe_surface *ps = framebuffer->zsbuf;
+
+ pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height,
+ util_pack_z_stencil(ps->format, depth, stencil));
+ }
+}
diff --git a/src/gallium/auxiliary/util/u_cpu_detect.c b/src/gallium/auxiliary/util/u_cpu_detect.c
new file mode 100644
index 0000000000..d9f2f8fc28
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_cpu_detect.c
@@ -0,0 +1,506 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Dennis Smit
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Based on the work of Eric Anholt <anholt@FreeBSD.org>
+ */
+
+/* FIXME: clean this entire file up */
+
+#include "u_cpu_detect.h"
+
+#ifdef __linux__
+#define OS_LINUX
+#endif
+#ifdef WIN32
+#define OS_WIN32
+#endif
+
+#if defined(ARCH_POWERPC)
+#if defined(OS_DARWIN)
+#include <sys/sysctl.h>
+#else
+#include <signal.h>
+#include <setjmp.h>
+#endif
+#endif
+
+#if defined(OS_NETBSD) || defined(OS_OPENBSD)
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <machine/cpu.h>
+#endif
+
+#if defined(OS_FREEBSD)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
+#if defined(OS_LINUX)
+#include <signal.h>
+#endif
+
+#if defined(OS_WIN32)
+#include <windows.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+
+static struct cpu_detect_caps __cpu_detect_caps;
+static int __cpu_detect_initialized = 0;
+
+static int has_cpuid(void);
+static int cpuid(unsigned int ax, unsigned int *p);
+
+/* The sigill handlers */
+#if defined(ARCH_X86) /* x86 (linux katmai handler check thing) */
+#if defined(OS_LINUX) && defined(_POSIX_SOURCE) && defined(X86_FXSR_MAGIC)
+static void sigill_handler_sse(int signal, struct sigcontext sc)
+{
+ /* Both the "xorps %%xmm0,%%xmm0" and "divps %xmm0,%%xmm1"
+ * instructions are 3 bytes long. We must increment the instruction
+ * pointer manually to avoid repeated execution of the offending
+ * instruction.
+ *
+ * If the SIGILL is caused by a divide-by-zero when unmasked
+ * exceptions aren't supported, the SIMD FPU status and control
+ * word will be restored at the end of the test, so we don't need
+ * to worry about doing it here. Besides, we may not be able to...
+ */
+ sc.eip += 3;
+
+ __cpu_detect_caps.hasSSE=0;
+}
+
+static void sigfpe_handler_sse(int signal, struct sigcontext sc)
+{
+ if (sc.fpstate->magic != 0xffff) {
+ /* Our signal context has the extended FPU state, so reset the
+ * divide-by-zero exception mask and clear the divide-by-zero
+ * exception bit.
+ */
+ sc.fpstate->mxcsr |= 0x00000200;
+ sc.fpstate->mxcsr &= 0xfffffffb;
+ } else {
+ /* If we ever get here, we're completely hosed.
+ */
+ }
+}
+#endif
+#endif /* OS_LINUX && _POSIX_SOURCE && X86_FXSR_MAGIC */
+
+#if defined(OS_WIN32)
+LONG CALLBACK win32_sig_handler_sse(EXCEPTION_POINTERS* ep)
+{
+ if(ep->ExceptionRecord->ExceptionCode==EXCEPTION_ILLEGAL_INSTRUCTION){
+ ep->ContextRecord->Eip +=3;
+ __cpu_detect_caps.hasSSE=0;
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif /* OS_WIN32 */
+
+
+#if defined(ARCH_POWERPC) && !defined(OS_DARWIN)
+static sigjmp_buf __lv_powerpc_jmpbuf;
+static volatile sig_atomic_t __lv_powerpc_canjump = 0;
+
+static void sigill_handler (int sig);
+
+static void sigill_handler (int sig)
+{
+ if (!__lv_powerpc_canjump) {
+ signal (sig, SIG_DFL);
+ raise (sig);
+ }
+
+ __lv_powerpc_canjump = 0;
+ siglongjmp(__lv_powerpc_jmpbuf, 1);
+}
+
+static void check_os_altivec_support(void)
+{
+#if defined(OS_DARWIN)
+ int sels[2] = {CTL_HW, HW_VECTORUNIT};
+ int has_vu = 0;
+ int len = sizeof (has_vu);
+ int err;
+
+ err = sysctl(sels, 2, &has_vu, &len, NULL, 0);
+
+ if (err == 0) {
+ if (has_vu != 0) {
+ __cpu_detect_caps.hasAltiVec = 1;
+ }
+ }
+#else /* !OS_DARWIN */
+ /* no Darwin, do it the brute-force way */
+ /* this is borrowed from the libmpeg2 library */
+ signal(SIGILL, sigill_handler);
+ if (sigsetjmp(__lv_powerpc_jmpbuf, 1)) {
+ signal(SIGILL, SIG_DFL);
+ } else {
+ __lv_powerpc_canjump = 1;
+
+ __asm __volatile
+ ("mtspr 256, %0\n\t"
+ "vand %%v0, %%v0, %%v0"
+ :
+ : "r" (-1));
+
+ signal(SIGILL, SIG_DFL);
+ __cpu_detect_caps.hasAltiVec = 1;
+ }
+#endif
+}
+#endif
+
+/* If we're running on a processor that can do SSE, let's see if we
+ * are allowed to or not. This will catch 2.4.0 or later kernels that
+ * haven't been configured for a Pentium III but are running on one,
+ * and RedHat patched 2.2 kernels that have broken exception handling
+ * support for user space apps that do SSE.
+ */
+static void check_os_katmai_support(void)
+{
+#if defined(ARCH_X86)
+#if defined(OS_FREEBSD)
+ int has_sse=0, ret;
+ int len = sizeof (has_sse);
+
+ ret = sysctlbyname("hw.instruction_sse", &has_sse, &len, NULL, 0);
+ if (ret || !has_sse)
+ __cpu_detect_caps.hasSSE=0;
+
+#elif defined(OS_NETBSD) || defined(OS_OPENBSD)
+ int has_sse, has_sse2, ret, mib[2];
+ int varlen;
+
+ mib[0] = CTL_MACHDEP;
+ mib[1] = CPU_SSE;
+ varlen = sizeof (has_sse);
+
+ ret = sysctl(mib, 2, &has_sse, &varlen, NULL, 0);
+ if (ret < 0 || !has_sse) {
+ __cpu_detect_caps.hasSSE = 0;
+ } else {
+ __cpu_detect_caps.hasSSE = 1;
+ }
+
+ mib[1] = CPU_SSE2;
+ varlen = sizeof (has_sse2);
+ ret = sysctl(mib, 2, &has_sse2, &varlen, NULL, 0);
+ if (ret < 0 || !has_sse2) {
+ __cpu_detect_caps.hasSSE2 = 0;
+ } else {
+ __cpu_detect_caps.hasSSE2 = 1;
+ }
+ __cpu_detect_caps.hasSSE = 0; /* FIXME ?!?!? */
+
+#elif defined(OS_WIN32)
+ LPTOP_LEVEL_EXCEPTION_FILTER exc_fil;
+ if (__cpu_detect_caps.hasSSE) {
+ exc_fil = SetUnhandledExceptionFilter(win32_sig_handler_sse);
+ __asm __volatile ("xorps %xmm0, %xmm0");
+ SetUnhandledExceptionFilter(exc_fil);
+ }
+#elif defined(OS_LINUX)
+ struct sigaction saved_sigill;
+ struct sigaction saved_sigfpe;
+
+ /* Save the original signal handlers.
+ */
+ sigaction(SIGILL, NULL, &saved_sigill);
+ sigaction(SIGFPE, NULL, &saved_sigfpe);
+
+ signal(SIGILL, (void (*)(int))sigill_handler_sse);
+ signal(SIGFPE, (void (*)(int))sigfpe_handler_sse);
+
+ /* Emulate test for OSFXSR in CR4. The OS will set this bit if it
+ * supports the extended FPU save and restore required for SSE. If
+ * we execute an SSE instruction on a PIII and get a SIGILL, the OS
+ * doesn't support Streaming SIMD Exceptions, even if the processor
+ * does.
+ */
+ if (__cpu_detect_caps.hasSSE) {
+ __asm __volatile ("xorps %xmm1, %xmm0");
+ }
+
+ /* Emulate test for OSXMMEXCPT in CR4. The OS will set this bit if
+ * it supports unmasked SIMD FPU exceptions. If we unmask the
+ * exceptions, do a SIMD divide-by-zero and get a SIGILL, the OS
+ * doesn't support unmasked SIMD FPU exceptions. If we get a SIGFPE
+ * as expected, we're okay but we need to clean up after it.
+ *
+ * Are we being too stringent in our requirement that the OS support
+ * unmasked exceptions? Certain RedHat 2.2 kernels enable SSE by
+ * setting CR4.OSFXSR but don't support unmasked exceptions. Win98
+ * doesn't even support them. We at least know the user-space SSE
+ * support is good in kernels that do support unmasked exceptions,
+ * and therefore to be safe I'm going to leave this test in here.
+ */
+ if (__cpu_detect_caps.hasSSE) {
+ // test_os_katmai_exception_support();
+ }
+
+ /* Restore the original signal handlers.
+ */
+ sigaction(SIGILL, &saved_sigill, NULL);
+ sigaction(SIGFPE, &saved_sigfpe, NULL);
+
+#else
+ /* We can't use POSIX signal handling to test the availability of
+ * SSE, so we disable it by default.
+ */
+ __cpu_detect_caps.hasSSE = 0;
+#endif /* __linux__ */
+#endif
+}
+
+
+static int has_cpuid(void)
+{
+#if defined(ARCH_X86)
+ int a, c;
+
+ __asm __volatile
+ ("pushf\n"
+ "popl %0\n"
+ "movl %0, %1\n"
+ "xorl $0x200000, %0\n"
+ "push %0\n"
+ "popf\n"
+ "pushf\n"
+ "popl %0\n"
+ : "=a" (a), "=c" (c)
+ :
+ : "cc");
+
+ return a != c;
+#else
+ return 0;
+#endif
+}
+
+static int cpuid(unsigned int ax, unsigned int *p)
+{
+#if defined(ARCH_X86)
+ unsigned int flags;
+
+ __asm __volatile
+ ("movl %%ebx, %%esi\n\t"
+ "cpuid\n\t"
+ "xchgl %%ebx, %%esi"
+ : "=a" (p[0]), "=S" (p[1]),
+ "=c" (p[2]), "=d" (p[3])
+ : "0" (ax));
+
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+void cpu_detect_initialize()
+{
+ unsigned int regs[4];
+ unsigned int regs2[4];
+
+ int mib[2], ncpu;
+ int len;
+
+ memset(&__cpu_detect_caps, 0, sizeof (struct cpu_detect_caps));
+
+ /* Check for arch type */
+#if defined(ARCH_MIPS)
+ __cpu_detect_caps.type = CPU_DETECT_TYPE_MIPS;
+#elif defined(ARCH_ALPHA)
+ __cpu_detect_caps.type = CPU_DETECT_TYPE_ALPHA;
+#elif defined(ARCH_SPARC)
+ __cpu_detect_caps.type = CPU_DETECT_TYPE_SPARC;
+#elif defined(ARCH_X86)
+ __cpu_detect_caps.type = CPU_DETECT_TYPE_X86;
+#elif defined(ARCH_POWERPC)
+ __cpu_detect_caps.type = CPU_DETECT_TYPE_POWERPC;
+#else
+ __cpu_detect_caps.type = CPU_DETECT_TYPE_OTHER;
+#endif
+
+ /* Count the number of CPUs in system */
+#if !defined(OS_WIN32) && !defined(OS_UNKNOWN) && defined(_SC_NPROCESSORS_ONLN)
+ __cpu_detect_caps.nrcpu = sysconf(_SC_NPROCESSORS_ONLN);
+ if (__cpu_detect_caps.nrcpu == -1)
+ __cpu_detect_caps.nrcpu = 1;
+
+#elif defined(OS_NETBSD) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+
+ len = sizeof (ncpu);
+ sysctl(mib, 2, &ncpu, &len, NULL, 0);
+ __cpu_detect_caps.nrcpu = ncpu;
+
+#else
+ __cpu_detect_caps.nrcpu = 1;
+#endif
+
+#if defined(ARCH_X86)
+ /* No cpuid, old 486 or lower */
+ if (has_cpuid() == 0)
+ return;
+
+ __cpu_detect_caps.cacheline = 32;
+
+ /* Get max cpuid level */
+ cpuid(0x00000000, regs);
+
+ if (regs[0] >= 0x00000001) {
+ unsigned int cacheline;
+
+ cpuid (0x00000001, regs2);
+
+ __cpu_detect_caps.x86cpuType = (regs2[0] >> 8) & 0xf;
+ if (__cpu_detect_caps.x86cpuType == 0xf)
+ __cpu_detect_caps.x86cpuType = 8 + ((regs2[0] >> 20) & 255); /* use extended family (P4, IA64) */
+
+ /* general feature flags */
+ __cpu_detect_caps.hasTSC = (regs2[3] & (1 << 8 )) >> 8; /* 0x0000010 */
+ __cpu_detect_caps.hasMMX = (regs2[3] & (1 << 23 )) >> 23; /* 0x0800000 */
+ __cpu_detect_caps.hasSSE = (regs2[3] & (1 << 25 )) >> 25; /* 0x2000000 */
+ __cpu_detect_caps.hasSSE2 = (regs2[3] & (1 << 26 )) >> 26; /* 0x4000000 */
+ __cpu_detect_caps.hasSSE3 = (regs2[2] & (1)); /* 0x0000001 */
+ __cpu_detect_caps.hasSSSE3 = (regs2[2] & (1 << 9 )) >> 9; /* 0x0000020 */
+ __cpu_detect_caps.hasMMX2 = __cpu_detect_caps.hasSSE; /* SSE cpus supports mmxext too */
+
+ cacheline = ((regs2[1] >> 8) & 0xFF) * 8;
+ if (cacheline > 0)
+ __cpu_detect_caps.cacheline = cacheline;
+ }
+
+ cpuid(0x80000000, regs);
+
+ if (regs[0] >= 0x80000001) {
+
+ cpuid(0x80000001, regs2);
+
+ __cpu_detect_caps.hasMMX |= (regs2[3] & (1 << 23 )) >> 23; /* 0x0800000 */
+ __cpu_detect_caps.hasMMX2 |= (regs2[3] & (1 << 22 )) >> 22; /* 0x400000 */
+ __cpu_detect_caps.has3DNow = (regs2[3] & (1 << 31 )) >> 31; /* 0x80000000 */
+ __cpu_detect_caps.has3DNowExt = (regs2[3] & (1 << 30 )) >> 30;
+ }
+
+ if (regs[0] >= 0x80000006) {
+ cpuid(0x80000006, regs2);
+ __cpu_detect_caps.cacheline = regs2[2] & 0xFF;
+ }
+
+
+#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_CYGWIN) || defined(OS_OPENBSD)
+ if (__cpu_detect_caps.hasSSE)
+ check_os_katmai_support();
+
+ if (!__cpu_detect_caps.hasSSE) {
+ __cpu_detect_caps.hasSSE2 = 0;
+ __cpu_detect_caps.hasSSE3 = 0;
+ __cpu_detect_caps.hasSSSE3 = 0;
+ }
+#else
+ __cpu_detect_caps.hasSSE = 0;
+ __cpu_detect_caps.hasSSE2 = 0;
+ __cpu_detect_caps.hasSSE3 = 0;
+ __cpu_detect_caps.hasSSSE3 = 0;
+#endif
+#endif /* ARCH_X86 */
+
+#if defined(ARCH_POWERPC)
+ check_os_altivec_support();
+#endif /* ARCH_POWERPC */
+
+ __cpu_detect_initialized = 1;
+}
+
+struct cpu_detect_caps *cpu_detect_get_caps()
+{
+ return &__cpu_detect_caps;
+}
+
+/* The getters and setters for feature flags */
+int cpu_detect_get_tsc()
+{
+ return __cpu_detect_caps.hasTSC;
+}
+
+int cpu_detect_get_mmx()
+{
+ return __cpu_detect_caps.hasMMX;
+}
+
+int cpu_detect_get_mmx2()
+{
+ return __cpu_detect_caps.hasMMX2;
+}
+
+int cpu_detect_get_sse()
+{
+ return __cpu_detect_caps.hasSSE;
+}
+
+int cpu_detect_get_sse2()
+{
+ return __cpu_detect_caps.hasSSE2;
+}
+
+int cpu_detect_get_sse3()
+{
+ return __cpu_detect_caps.hasSSE3;
+}
+
+int cpu_detect_get_ssse3()
+{
+ return __cpu_detect_caps.hasSSSE3;
+}
+
+int cpu_detect_get_3dnow()
+{
+ return __cpu_detect_caps.has3DNow;
+}
+
+int cpu_detect_get_3dnow2()
+{
+ return __cpu_detect_caps.has3DNowExt;
+}
+
+int cpu_detect_get_altivec()
+{
+ return __cpu_detect_caps.hasAltiVec;
+}
+
diff --git a/src/gallium/auxiliary/util/u_cpu_detect.h b/src/gallium/auxiliary/util/u_cpu_detect.h
new file mode 100644
index 0000000000..1612d49286
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_cpu_detect.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Dennis Smit
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ ***************************************************************************/
+
+/*
+ * Based on the work of Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#ifndef _CPU_DETECT_H
+#define _CPU_DETECT_H
+
+typedef enum {
+ CPU_DETECT_TYPE_MIPS,
+ CPU_DETECT_TYPE_ALPHA,
+ CPU_DETECT_TYPE_SPARC,
+ CPU_DETECT_TYPE_X86,
+ CPU_DETECT_TYPE_POWERPC,
+ CPU_DETECT_TYPE_OTHER
+} cpu_detect_type;
+
+struct cpu_detect_caps {
+ cpu_detect_type type;
+ int nrcpu;
+
+ /* Feature flags */
+ int x86cpuType;
+ int cacheline;
+
+ int hasTSC;
+ int hasMMX;
+ int hasMMX2;
+ int hasSSE;
+ int hasSSE2;
+ int hasSSE3;
+ int hasSSSE3;
+ int has3DNow;
+ int has3DNowExt;
+ int hasAltiVec;
+};
+
+/* prototypes */
+void cpu_detect_initialize(void);
+struct cpu_detect_caps *cpu_detect_get_caps(void);
+
+int cpu_detect_get_tsc(void);
+int cpu_detect_get_mmx(void);
+int cpu_detect_get_mmx2(void);
+int cpu_detect_get_sse(void);
+int cpu_detect_get_sse2(void);
+int cpu_detect_get_sse3(void);
+int cpu_detect_get_ssse3(void);
+int cpu_detect_get_3dnow(void);
+int cpu_detect_get_3dnow2(void);
+int cpu_detect_get_altivec(void);
+
+#endif /* _CPU_DETECT_H */
diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c
new file mode 100644
index 0000000000..96d400c839
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug.c
@@ -0,0 +1,823 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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 "pipe/p_config.h"
+
+#include <stdarg.h>
+
+
+#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
+
+#include <windows.h>
+#include <winddi.h>
+
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <types.h>
+
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#endif
+#include <windows.h>
+#include <stdio.h>
+
+#else
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#endif
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_string.h"
+#include "util/u_stream.h"
+#include "util/u_math.h"
+#include "util/u_tile.h"
+
+
+#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
+static INLINE void
+_EngDebugPrint(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ EngDebugPrint("", (PCHAR)format, ap);
+ va_end(ap);
+}
+#endif
+
+
+void _debug_vprintf(const char *format, va_list ap)
+{
+#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+ /* EngDebugPrint does not handle float point arguments, so we need to use
+ * our own vsnprintf implementation. It is also very slow, so buffer until
+ * we find a newline. */
+ static char buf[512] = {'\0'};
+ size_t len = strlen(buf);
+ int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
+ if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
+ _EngDebugPrint("%s", buf);
+ buf[0] = '\0';
+ }
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ /* OutputDebugStringA can be very slow, so buffer until we find a newline. */
+ static char buf[4096] = {'\0'};
+ size_t len = strlen(buf);
+ int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
+ if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
+ OutputDebugStringA(buf);
+ buf[0] = '\0';
+ }
+
+ if(GetConsoleWindow() && !IsDebuggerPresent()) {
+ fflush(stdout);
+ vfprintf(stderr, format, ap);
+ fflush(stderr);
+ }
+
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+ wchar_t *wide_format;
+ long wide_str_len;
+ char buf[512];
+ int ret;
+#if (_WIN32_WCE < 600)
+ ret = vsprintf(buf, format, ap);
+ if(ret < 0){
+ sprintf(buf, "Cant handle debug print!");
+ ret = 25;
+ }
+#else
+ ret = vsprintf_s(buf, 512, format, ap);
+ if(ret < 0){
+ sprintf_s(buf, 512, "Cant handle debug print!");
+ ret = 25;
+ }
+#endif
+ buf[ret] = '\0';
+ /* Format is ascii - needs to be converted to wchar_t for printing */
+ wide_str_len = MultiByteToWideChar(CP_ACP, 0, (const char *) buf, -1, NULL, 0);
+ wide_format = (wchar_t *) malloc((wide_str_len+1) * sizeof(wchar_t));
+ if (wide_format) {
+ MultiByteToWideChar(CP_ACP, 0, (const char *) buf, -1,
+ wide_format, wide_str_len);
+ NKDbgPrintfW(wide_format, wide_format);
+ free(wide_format);
+ }
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+ /* TODO */
+#else /* !PIPE_SUBSYSTEM_WINDOWS */
+ fflush(stdout);
+ vfprintf(stderr, format, ap);
+#endif
+}
+
+
+#ifdef DEBUG
+void debug_print_blob( const char *name,
+ const void *blob,
+ unsigned size )
+{
+ const unsigned *ublob = (const unsigned *)blob;
+ unsigned i;
+
+ debug_printf("%s (%d dwords%s)\n", name, size/4,
+ size%4 ? "... plus a few bytes" : "");
+
+ for (i = 0; i < size/4; i++) {
+ debug_printf("%d:\t%08x\n", i, ublob[i]);
+ }
+}
+#endif
+
+
+#ifndef debug_break
+void debug_break(void)
+{
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ DebugBreak();
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+ EngDebugBreak();
+#else
+ abort();
+#endif
+}
+#endif
+
+
+#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
+static const char *
+find(const char *start, const char *end, char c)
+{
+ const char *p;
+ for(p = start; !end || p != end; ++p) {
+ if(*p == c)
+ return p;
+ if(*p < 32)
+ break;
+ }
+ return NULL;
+}
+
+static int
+compare(const char *start, const char *end, const char *s)
+{
+ const char *p, *q;
+ for(p = start, q = s; p != end && *q != '\0'; ++p, ++q) {
+ if(*p != *q)
+ return 0;
+ }
+ return p == end && *q == '\0';
+}
+
+static void
+copy(char *dst, const char *start, const char *end, size_t n)
+{
+ const char *p;
+ char *q;
+ for(p = start, q = dst, n = n - 1; p != end && n; ++p, ++q, --n)
+ *q = *p;
+ *q = '\0';
+}
+#endif
+
+
+static INLINE const char *
+_debug_get_option(const char *name)
+{
+#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+ /* EngMapFile creates the file if it does not exists, so it must either be
+ * disabled on release versions (or put in a less conspicuous place). */
+#ifdef DEBUG
+ const char *result = NULL;
+ ULONG_PTR iFile = 0;
+ const void *pMap = NULL;
+ const char *sol, *eol, *sep;
+ static char output[1024];
+
+ pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
+ if(pMap) {
+ sol = (const char *)pMap;
+ while(1) {
+ /* TODO: handle LF line endings */
+ eol = find(sol, NULL, '\r');
+ if(!eol || eol == sol)
+ break;
+ sep = find(sol, eol, '=');
+ if(!sep)
+ break;
+ if(compare(sol, sep, name)) {
+ copy(output, sep + 1, eol, sizeof(output));
+ result = output;
+ break;
+ }
+ sol = eol + 2;
+ }
+ EngUnmapFile(iFile);
+ }
+ return result;
+#else
+ return NULL;
+#endif
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+ /* TODO: implement */
+ return NULL;
+#else
+ return getenv(name);
+#endif
+}
+
+const char *
+debug_get_option(const char *name, const char *dfault)
+{
+ const char *result;
+
+ result = _debug_get_option(name);
+ if(!result)
+ result = dfault;
+
+ debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
+
+ return result;
+}
+
+boolean
+debug_get_bool_option(const char *name, boolean dfault)
+{
+ const char *str = _debug_get_option(name);
+ boolean result;
+
+ if(str == NULL)
+ result = dfault;
+ else if(!util_strcmp(str, "n"))
+ result = FALSE;
+ else if(!util_strcmp(str, "no"))
+ result = FALSE;
+ else if(!util_strcmp(str, "0"))
+ result = FALSE;
+ else if(!util_strcmp(str, "f"))
+ result = FALSE;
+ else if(!util_strcmp(str, "false"))
+ result = FALSE;
+ else
+ result = TRUE;
+
+ debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
+
+ return result;
+}
+
+
+long
+debug_get_num_option(const char *name, long dfault)
+{
+ long result;
+ const char *str;
+
+ str = _debug_get_option(name);
+ if(!str)
+ result = dfault;
+ else {
+ long sign;
+ char c;
+ c = *str++;
+ if(c == '-') {
+ sign = -1;
+ c = *str++;
+ }
+ else {
+ sign = 1;
+ }
+ result = 0;
+ while('0' <= c && c <= '9') {
+ result = result*10 + (c - '0');
+ c = *str++;
+ }
+ result *= sign;
+ }
+
+ debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
+
+ return result;
+}
+
+
+unsigned long
+debug_get_flags_option(const char *name,
+ const struct debug_named_value *flags,
+ unsigned long dfault)
+{
+ unsigned long result;
+ const char *str;
+
+ str = _debug_get_option(name);
+ if(!str)
+ result = dfault;
+ else if (!util_strcmp(str, "help")) {
+ result = dfault;
+ while (flags->name) {
+ debug_printf("%s: help for %s: %s [0x%lx]\n", __FUNCTION__, name, flags->name, flags->value);
+ flags++;
+ }
+ }
+ else {
+ result = 0;
+ while( flags->name ) {
+ if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
+ result |= flags->value;
+ ++flags;
+ }
+ }
+
+ if (str) {
+ debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str);
+ }
+ else {
+ debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
+ }
+
+ return result;
+}
+
+
+void _debug_assert_fail(const char *expr,
+ const char *file,
+ unsigned line,
+ const char *function)
+{
+ _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
+#if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE))
+#else
+ if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
+#endif
+ debug_break();
+ else
+ _debug_printf("continuing...\n");
+}
+
+
+const char *
+debug_dump_enum(const struct debug_named_value *names,
+ unsigned long value)
+{
+ static char rest[64];
+
+ while(names->name) {
+ if(names->value == value)
+ return names->name;
+ ++names;
+ }
+
+ util_snprintf(rest, sizeof(rest), "0x%08lx", value);
+ return rest;
+}
+
+
+const char *
+debug_dump_enum_noprefix(const struct debug_named_value *names,
+ const char *prefix,
+ unsigned long value)
+{
+ static char rest[64];
+
+ while(names->name) {
+ if(names->value == value) {
+ const char *name = names->name;
+ while (*name == *prefix) {
+ name++;
+ prefix++;
+ }
+ return name;
+ }
+ ++names;
+ }
+
+
+
+ util_snprintf(rest, sizeof(rest), "0x%08lx", value);
+ return rest;
+}
+
+
+const char *
+debug_dump_flags(const struct debug_named_value *names,
+ unsigned long value)
+{
+ static char output[4096];
+ static char rest[256];
+ int first = 1;
+
+ output[0] = '\0';
+
+ while(names->name) {
+ if((names->value & value) == names->value) {
+ if (!first)
+ util_strncat(output, "|", sizeof(output));
+ else
+ first = 0;
+ util_strncat(output, names->name, sizeof(output));
+ value &= ~names->value;
+ }
+ ++names;
+ }
+
+ if (value) {
+ if (!first)
+ util_strncat(output, "|", sizeof(output));
+ else
+ first = 0;
+
+ util_snprintf(rest, sizeof(rest), "0x%08lx", value);
+ util_strncat(output, rest, sizeof(output));
+ }
+
+ if(first)
+ return "0";
+
+ return output;
+}
+
+
+static const struct debug_named_value pipe_format_names[] = {
+#ifdef DEBUG
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_NONE),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_A1R5G5B5_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_A4R4G4B4_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R5G6B5_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_A2B10G10R10_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_A8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_I8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_L16_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_YCBCR_REV),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_Z16_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_Z32_FLOAT),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_S8Z24_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24S8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_X8Z24_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_Z24X8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_S8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R64_FLOAT),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64_FLOAT),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64_FLOAT),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R64G64B64A64_FLOAT),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_FLOAT),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_FLOAT),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_FLOAT),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_FLOAT),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R32G32B32A32_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R16G16B16A16_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_UNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_USCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_B6G5R5_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_A8B8G8R8_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_X8B8G8R8_SNORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SSCALED),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_L8_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_A8L8_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8A8_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_R8G8B8X8_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_A8R8G8B8_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_X8R8G8B8_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8A8_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_B8G8R8X8_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_X8UB8UG8SR8S_NORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_B6UG5SR5S_NORM),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_RGBA),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_RGBA),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_RGBA),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_SRGB),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT1_SRGBA),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT3_SRGBA),
+ DEBUG_NAMED_VALUE(PIPE_FORMAT_DXT5_SRGBA),
+#endif
+ DEBUG_NAMED_VALUE_END
+};
+
+#ifdef DEBUG
+void debug_print_format(const char *msg, unsigned fmt )
+{
+ debug_printf("%s: %s\n", msg, debug_dump_enum(pipe_format_names, fmt));
+}
+#endif
+
+const char *pf_name( enum pipe_format format )
+{
+ return debug_dump_enum(pipe_format_names, format);
+}
+
+
+#ifdef DEBUG
+void debug_dump_image(const char *prefix,
+ unsigned format, unsigned cpp,
+ unsigned width, unsigned height,
+ unsigned stride,
+ const void *data)
+{
+#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
+ static unsigned no = 0;
+ char filename[256];
+ WCHAR wfilename[sizeof(filename)];
+ ULONG_PTR iFile = 0;
+ struct {
+ unsigned format;
+ unsigned cpp;
+ unsigned width;
+ unsigned height;
+ } header;
+ unsigned char *pMap = NULL;
+ unsigned i;
+
+ util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
+ for(i = 0; i < sizeof(filename); ++i)
+ wfilename[i] = (WCHAR)filename[i];
+
+ pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile);
+ if(!pMap)
+ return;
+
+ header.format = format;
+ header.cpp = cpp;
+ header.width = width;
+ header.height = height;
+ memcpy(pMap, &header, sizeof(header));
+ pMap += sizeof(header);
+
+ for(i = 0; i < height; ++i) {
+ memcpy(pMap, (unsigned char *)data + stride*i, cpp*width);
+ pMap += cpp*width;
+ }
+
+ EngUnmapFile(iFile);
+#endif
+}
+
+void debug_dump_surface(const char *prefix,
+ struct pipe_surface *surface)
+{
+ struct pipe_texture *texture;
+ struct pipe_screen *screen;
+ struct pipe_transfer *transfer;
+ void *data;
+
+ if (!surface)
+ return;
+
+ texture = surface->texture;
+ screen = texture->screen;
+
+ transfer = screen->get_tex_transfer(screen, texture, surface->face,
+ surface->level, surface->zslice,
+ PIPE_TRANSFER_READ, 0, 0, surface->width,
+ surface->height);
+
+ data = screen->transfer_map(screen, transfer);
+ if(!data)
+ goto error;
+
+ debug_dump_image(prefix,
+ transfer->format,
+ transfer->block.size,
+ transfer->nblocksx,
+ transfer->nblocksy,
+ transfer->stride,
+ data);
+
+ screen->transfer_unmap(screen, transfer);
+error:
+ screen->tex_transfer_destroy(transfer);
+}
+
+
+#pragma pack(push,2)
+struct bmp_file_header {
+ uint16_t bfType;
+ uint32_t bfSize;
+ uint16_t bfReserved1;
+ uint16_t bfReserved2;
+ uint32_t bfOffBits;
+};
+#pragma pack(pop)
+
+struct bmp_info_header {
+ uint32_t biSize;
+ int32_t biWidth;
+ int32_t biHeight;
+ uint16_t biPlanes;
+ uint16_t biBitCount;
+ uint32_t biCompression;
+ uint32_t biSizeImage;
+ int32_t biXPelsPerMeter;
+ int32_t biYPelsPerMeter;
+ uint32_t biClrUsed;
+ uint32_t biClrImportant;
+};
+
+struct bmp_rgb_quad {
+ uint8_t rgbBlue;
+ uint8_t rgbGreen;
+ uint8_t rgbRed;
+ uint8_t rgbAlpha;
+};
+
+void
+debug_dump_surface_bmp(const char *filename,
+ struct pipe_surface *surface)
+{
+#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
+ struct pipe_transfer *transfer;
+ struct pipe_texture *texture = surface->texture;
+ struct pipe_screen *screen = texture->screen;
+
+ transfer = screen->get_tex_transfer(screen, texture, surface->face,
+ surface->level, surface->zslice,
+ PIPE_TRANSFER_READ, 0, 0, surface->width,
+ surface->height);
+
+ debug_dump_transfer_bmp(filename, transfer);
+
+ screen->tex_transfer_destroy(transfer);
+#endif
+}
+
+void
+debug_dump_transfer_bmp(const char *filename,
+ struct pipe_transfer *transfer)
+{
+#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
+ float *rgba;
+
+ if (!transfer)
+ goto error1;
+
+ rgba = MALLOC(transfer->width*transfer->height*4*sizeof(float));
+ if(!rgba)
+ goto error1;
+
+ pipe_get_tile_rgba(transfer, 0, 0,
+ transfer->width, transfer->height,
+ rgba);
+
+ debug_dump_float_rgba_bmp(filename,
+ transfer->width, transfer->height,
+ rgba, transfer->width);
+
+ FREE(rgba);
+error1:
+ ;
+#endif
+}
+
+void
+debug_dump_float_rgba_bmp(const char *filename,
+ unsigned width, unsigned height,
+ float *rgba, unsigned stride)
+{
+#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
+ struct util_stream *stream;
+ struct bmp_file_header bmfh;
+ struct bmp_info_header bmih;
+ unsigned x, y;
+
+ if(!rgba)
+ goto error1;
+
+ bmfh.bfType = 0x4d42;
+ bmfh.bfSize = 14 + 40 + height*width*4;
+ bmfh.bfReserved1 = 0;
+ bmfh.bfReserved2 = 0;
+ bmfh.bfOffBits = 14 + 40;
+
+ bmih.biSize = 40;
+ bmih.biWidth = width;
+ bmih.biHeight = height;
+ bmih.biPlanes = 1;
+ bmih.biBitCount = 32;
+ bmih.biCompression = 0;
+ bmih.biSizeImage = height*width*4;
+ bmih.biXPelsPerMeter = 0;
+ bmih.biYPelsPerMeter = 0;
+ bmih.biClrUsed = 0;
+ bmih.biClrImportant = 0;
+
+ stream = util_stream_create(filename, bmfh.bfSize);
+ if(!stream)
+ goto error1;
+
+ util_stream_write(stream, &bmfh, 14);
+ util_stream_write(stream, &bmih, 40);
+
+ y = height;
+ while(y--) {
+ float *ptr = rgba + (stride * y * 4);
+ for(x = 0; x < width; ++x)
+ {
+ struct bmp_rgb_quad pixel;
+ pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
+ pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
+ pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
+ pixel.rgbAlpha = 255;
+ util_stream_write(stream, &pixel, 4);
+ }
+ }
+
+ util_stream_close(stream);
+error1:
+ ;
+#endif
+}
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_debug.h b/src/gallium/auxiliary/util/u_debug.h
new file mode 100644
index 0000000000..1380d98d7e
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug.h
@@ -0,0 +1,384 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Cross-platform debugging helpers.
+ *
+ * For now it just has assert and printf replacements, but it might be extended
+ * with stack trace reports and more advanced logging in the near future.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef U_DEBUG_H_
+#define U_DEBUG_H_
+
+
+#include <stdarg.h>
+
+#include "pipe/p_compiler.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(DBG) || defined(DEBUG)
+#ifndef DEBUG
+#define DEBUG 1
+#endif
+#else
+#ifndef NDEBUG
+#define NDEBUG 1
+#endif
+#endif
+
+
+/* MSVC bebore VC7 does not have the __FUNCTION__ macro */
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#define __FUNCTION__ "???"
+#endif
+
+
+void _debug_vprintf(const char *format, va_list ap);
+
+
+static INLINE void
+_debug_printf(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ _debug_vprintf(format, ap);
+ va_end(ap);
+}
+
+
+/**
+ * Print debug messages.
+ *
+ * The actual channel used to output debug message is platform specific. To
+ * avoid misformating or truncation, follow these rules of thumb:
+ * - output whole lines
+ * - avoid outputing large strings (512 bytes is the current maximum length
+ * that is guaranteed to be printed in all platforms)
+ */
+#if !defined(PIPE_OS_HAIKU)
+static INLINE void
+debug_printf(const char *format, ...)
+{
+#ifdef DEBUG
+ va_list ap;
+ va_start(ap, format);
+ _debug_vprintf(format, ap);
+ va_end(ap);
+#else
+ (void) format; /* silence warning */
+#endif
+}
+
+#endif /* !PIPE_OS_HAIKU */
+
+/*
+ * ... isn't portable so we need to pass arguments in parentheses.
+ *
+ * usage:
+ * debug_printf_once(("awnser: %i\n", 42));
+ */
+#define debug_printf_once(args) \
+ do { \
+ static boolean once = TRUE; \
+ if (once) { \
+ once = FALSE; \
+ debug_printf args; \
+ } \
+ } while (0)
+
+
+#ifdef DEBUG
+#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
+#else
+#define debug_vprintf(_format, _ap) ((void)0)
+#endif
+
+
+#ifdef DEBUG
+/**
+ * Dump a blob in hex to the same place that debug_printf sends its
+ * messages.
+ */
+void debug_print_blob( const char *name, const void *blob, unsigned size );
+
+/* Print a message along with a prettified format string
+ */
+void debug_print_format(const char *msg, unsigned fmt );
+#else
+#define debug_print_blob(_name, _blob, _size) ((void)0)
+#define debug_print_format(_msg, _fmt) ((void)0)
+#endif
+
+
+/**
+ * Hard-coded breakpoint.
+ */
+#ifdef DEBUG
+#if (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)) && defined(PIPE_CC_GCC)
+#define debug_break() __asm("int3")
+#elif defined(PIPE_CC_MSVC)
+#define debug_break() __debugbreak()
+#else
+void debug_break(void);
+#endif
+#else /* !DEBUG */
+#define debug_break() ((void)0)
+#endif /* !DEBUG */
+
+
+long
+debug_get_num_option(const char *name, long dfault);
+
+void _debug_assert_fail(const char *expr,
+ const char *file,
+ unsigned line,
+ const char *function);
+
+
+/**
+ * Assert macro
+ *
+ * Do not expect that the assert call terminates -- errors must be handled
+ * regardless of assert behavior.
+ */
+#ifdef DEBUG
+#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
+#else
+#define debug_assert(expr) ((void)(expr))
+#endif
+
+
+/** Override standard assert macro */
+#ifdef assert
+#undef assert
+#endif
+#define assert(expr) debug_assert(expr)
+
+
+/**
+ * Output the current function name.
+ */
+#ifdef DEBUG
+#define debug_checkpoint() \
+ _debug_printf("%s\n", __FUNCTION__)
+#else
+#define debug_checkpoint() \
+ ((void)0)
+#endif
+
+
+/**
+ * Output the full source code position.
+ */
+#ifdef DEBUG
+#define debug_checkpoint_full() \
+ _debug_printf("%s:%u:%s", __FILE__, __LINE__, __FUNCTION__)
+#else
+#define debug_checkpoint_full() \
+ ((void)0)
+#endif
+
+
+/**
+ * Output a warning message. Muted on release version.
+ */
+#ifdef DEBUG
+#define debug_warning(__msg) \
+ _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
+#else
+#define debug_warning(__msg) \
+ ((void)0)
+#endif
+
+
+/**
+ * Output an error message. Not muted on release version.
+ */
+#ifdef DEBUG
+#define debug_error(__msg) \
+ _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
+#else
+#define debug_error(__msg) \
+ _debug_printf("error: %s\n", __msg)
+#endif
+
+
+/**
+ * Used by debug_dump_enum and debug_dump_flags to describe symbols.
+ */
+struct debug_named_value
+{
+ const char *name;
+ unsigned long value;
+};
+
+
+/**
+ * Some C pre-processor magic to simplify creating named values.
+ *
+ * Example:
+ * @code
+ * static const debug_named_value my_names[] = {
+ * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
+ * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
+ * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
+ * DEBUG_NAMED_VALUE_END
+ * };
+ *
+ * ...
+ * debug_printf("%s = %s\n",
+ * name,
+ * debug_dump_enum(my_names, my_value));
+ * ...
+ * @endcode
+ */
+#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol}
+#define DEBUG_NAMED_VALUE_END {NULL, 0}
+
+
+/**
+ * Convert a enum value to a string.
+ */
+const char *
+debug_dump_enum(const struct debug_named_value *names,
+ unsigned long value);
+
+const char *
+debug_dump_enum_noprefix(const struct debug_named_value *names,
+ const char *prefix,
+ unsigned long value);
+
+
+/**
+ * Convert binary flags value to a string.
+ */
+const char *
+debug_dump_flags(const struct debug_named_value *names,
+ unsigned long value);
+
+
+/**
+ * Get option.
+ *
+ * It is an alias for getenv on Linux.
+ *
+ * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
+ * endings with one option per line as
+ *
+ * NAME=value
+ *
+ * This file must be terminated with an extra empty line.
+ */
+const char *
+debug_get_option(const char *name, const char *dfault);
+
+boolean
+debug_get_bool_option(const char *name, boolean dfault);
+
+long
+debug_get_num_option(const char *name, long dfault);
+
+unsigned long
+debug_get_flags_option(const char *name,
+ const struct debug_named_value *flags,
+ unsigned long dfault);
+
+
+void *
+debug_malloc(const char *file, unsigned line, const char *function,
+ size_t size);
+
+void
+debug_free(const char *file, unsigned line, const char *function,
+ void *ptr);
+
+void *
+debug_calloc(const char *file, unsigned line, const char *function,
+ size_t count, size_t size );
+
+void *
+debug_realloc(const char *file, unsigned line, const char *function,
+ void *old_ptr, size_t old_size, size_t new_size );
+
+unsigned long
+debug_memory_begin(void);
+
+void
+debug_memory_end(unsigned long beginning);
+
+
+#if defined(PROFILE) && defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+
+void
+debug_profile_start(void);
+
+void
+debug_profile_stop(void);
+
+#endif
+
+
+#ifdef DEBUG
+struct pipe_surface;
+struct pipe_transfer;
+void debug_dump_image(const char *prefix,
+ unsigned format, unsigned cpp,
+ unsigned width, unsigned height,
+ unsigned stride,
+ const void *data);
+void debug_dump_surface(const char *prefix,
+ struct pipe_surface *surface);
+void debug_dump_surface_bmp(const char *filename,
+ struct pipe_surface *surface);
+void debug_dump_transfer_bmp(const char *filename,
+ struct pipe_transfer *transfer);
+void debug_dump_float_rgba_bmp(const char *filename,
+ unsigned width, unsigned height,
+ float *rgba, unsigned stride);
+#else
+#define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0)
+#define debug_dump_surface(prefix, surface) ((void)0)
+#define debug_dump_surface_bmp(filename, surface) ((void)0)
+#define debug_dump_transfer_bmp(filename, transfer) ((void)0)
+#define debug_dump_rgba_float_bmp(filename, width, height, rgba, stride) ((void)0)
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_H_ */
diff --git a/src/gallium/auxiliary/util/u_debug_dump.c b/src/gallium/auxiliary/util/u_debug_dump.c
new file mode 100644
index 0000000000..6bdecde048
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_dump.c
@@ -0,0 +1,189 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "util/u_debug.h"
+#include "util/u_debug_dump.h"
+
+
+#define DEBUG_DUMP_INVALID_NAME "<invalid>"
+
+
+#if 0
+static const char *
+debug_dump_strip_prefix(const char *name,
+ const char *prefix)
+{
+ const char *stripped;
+ assert(name);
+ assert(prefix);
+ stripped = name;
+ while(*prefix) {
+ if(*stripped != *prefix)
+ return name;
+
+ ++stripped;
+ ++prefix;
+ }
+ return stripped;
+}
+#endif
+
+static const char *
+debug_dump_enum_continuous(unsigned value,
+ unsigned num_names,
+ const char **names)
+{
+ if (value >= num_names)
+ return DEBUG_DUMP_INVALID_NAME;
+ return names[value];
+}
+
+
+#define DEFINE_DEBUG_DUMP_CONTINUOUS(_name) \
+ const char * \
+ debug_dump_##_name(unsigned value, boolean shortened) \
+ { \
+ if(shortened) \
+ return debug_dump_enum_continuous(value, Elements(debug_dump_##_name##_short_names), debug_dump_##_name##_short_names); \
+ else \
+ return debug_dump_enum_continuous(value, Elements(debug_dump_##_name##_names), debug_dump_##_name##_names); \
+ }
+
+
+static const char *
+debug_dump_blend_factor_names[] = {
+ DEBUG_DUMP_INVALID_NAME, /* 0x0 */
+ "PIPE_BLENDFACTOR_ONE",
+ "PIPE_BLENDFACTOR_SRC_COLOR",
+ "PIPE_BLENDFACTOR_SRC_ALPHA",
+ "PIPE_BLENDFACTOR_DST_ALPHA",
+ "PIPE_BLENDFACTOR_DST_COLOR",
+ "PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE",
+ "PIPE_BLENDFACTOR_CONST_COLOR",
+ "PIPE_BLENDFACTOR_CONST_ALPHA",
+ "PIPE_BLENDFACTOR_SRC1_COLOR",
+ "PIPE_BLENDFACTOR_SRC1_ALPHA",
+ DEBUG_DUMP_INVALID_NAME, /* 0x0b */
+ DEBUG_DUMP_INVALID_NAME, /* 0x0c */
+ DEBUG_DUMP_INVALID_NAME, /* 0x0d */
+ DEBUG_DUMP_INVALID_NAME, /* 0x0e */
+ DEBUG_DUMP_INVALID_NAME, /* 0x0f */
+ DEBUG_DUMP_INVALID_NAME, /* 0x10 */
+ "PIPE_BLENDFACTOR_ZERO",
+ "PIPE_BLENDFACTOR_INV_SRC_COLOR",
+ "PIPE_BLENDFACTOR_INV_SRC_ALPHA",
+ "PIPE_BLENDFACTOR_INV_DST_ALPHA",
+ "PIPE_BLENDFACTOR_INV_DST_COLOR",
+ DEBUG_DUMP_INVALID_NAME, /* 0x16 */
+ "PIPE_BLENDFACTOR_INV_CONST_COLOR",
+ "PIPE_BLENDFACTOR_INV_CONST_ALPHA",
+ "PIPE_BLENDFACTOR_INV_SRC1_COLOR",
+ "PIPE_BLENDFACTOR_INV_SRC1_ALPHA"
+};
+
+static const char *
+debug_dump_blend_factor_short_names[] = {
+ DEBUG_DUMP_INVALID_NAME, /* 0x0 */
+ "one",
+ "src_color",
+ "src_alpha",
+ "dst_alpha",
+ "dst_color",
+ "src_alpha_saturate",
+ "const_color",
+ "const_alpha",
+ "src1_color",
+ "src1_alpha",
+ DEBUG_DUMP_INVALID_NAME, /* 0x0b */
+ DEBUG_DUMP_INVALID_NAME, /* 0x0c */
+ DEBUG_DUMP_INVALID_NAME, /* 0x0d */
+ DEBUG_DUMP_INVALID_NAME, /* 0x0e */
+ DEBUG_DUMP_INVALID_NAME, /* 0x0f */
+ DEBUG_DUMP_INVALID_NAME, /* 0x10 */
+ "zero",
+ "inv_src_color",
+ "inv_src_alpha",
+ "inv_dst_alpha",
+ "inv_dst_color",
+ DEBUG_DUMP_INVALID_NAME, /* 0x16 */
+ "inv_const_color",
+ "inv_const_alpha",
+ "inv_src1_color",
+ "inv_src1_alpha"
+};
+
+DEFINE_DEBUG_DUMP_CONTINUOUS(blend_factor)
+
+
+static const char *
+debug_dump_blend_func_names[] = {
+ "PIPE_BLEND_ADD",
+ "PIPE_BLEND_SUBTRACT",
+ "PIPE_BLEND_REVERSE_SUBTRACT",
+ "PIPE_BLEND_MIN",
+ "PIPE_BLEND_MAX"
+};
+
+static const char *
+debug_dump_blend_func_short_names[] = {
+ "add",
+ "sub",
+ "rev_sub",
+ "min",
+ "max"
+};
+
+DEFINE_DEBUG_DUMP_CONTINUOUS(blend_func)
+
+
+static const char *
+debug_dump_func_names[] = {
+ "PIPE_FUNC_NEVER",
+ "PIPE_FUNC_LESS",
+ "PIPE_FUNC_EQUAL",
+ "PIPE_FUNC_LEQUAL",
+ "PIPE_FUNC_GREATER",
+ "PIPE_FUNC_NOTEQUAL",
+ "PIPE_FUNC_GEQUAL",
+ "PIPE_FUNC_ALWAYS"
+};
+
+static const char *
+debug_dump_func_short_names[] = {
+ "never",
+ "less",
+ "equal",
+ "less_equal",
+ "greater",
+ "not_equal",
+ "greater_equal",
+ "always"
+};
+
+DEFINE_DEBUG_DUMP_CONTINUOUS(func)
diff --git a/src/gallium/auxiliary/util/u_debug_dump.h b/src/gallium/auxiliary/util/u_debug_dump.h
new file mode 100644
index 0000000000..102935559c
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_dump.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Dump data in human/machine readable format.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef U_DEBUG_DUMP_H_
+#define U_DEBUG_DUMP_H_
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+const char *
+debug_dump_blend_factor(unsigned value, boolean shortened);
+
+const char *
+debug_dump_blend_func(unsigned value, boolean shortened);
+
+const char *
+debug_dump_func(unsigned value, boolean shortened);
+
+
+/* FIXME: Move the other debug_dump_xxx functions out of u_debug.h into here. */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_H_ */
diff --git a/src/gallium/auxiliary/util/u_debug_memory.c b/src/gallium/auxiliary/util/u_debug_memory.c
new file mode 100644
index 0000000000..7623cb9398
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_memory.c
@@ -0,0 +1,324 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Memory debugging.
+ *
+ * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+#include <windows.h>
+#include <winddi.h>
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+#include <wdm.h>
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#include "util/u_debug.h"
+#include "util/u_debug_stack.h"
+#include "util/u_double_list.h"
+
+
+#define DEBUG_MEMORY_MAGIC 0x6e34090aU
+#define DEBUG_MEMORY_STACK 0 /* XXX: disabled until we have symbol lookup */
+
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) && !defined(WINCE)
+#define real_malloc(_size) EngAllocMem(0, _size, 'D3AG')
+#define real_free(_ptr) EngFreeMem(_ptr)
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+#define real_malloc(_size) ExAllocatePool(0, _size)
+#define real_free(_ptr) ExFreePool(_ptr)
+#else
+#define real_malloc(_size) malloc(_size)
+#define real_free(_ptr) free(_ptr)
+#endif
+
+
+struct debug_memory_header
+{
+ struct list_head head;
+
+ unsigned long no;
+ const char *file;
+ unsigned line;
+ const char *function;
+#if DEBUG_MEMORY_STACK
+ struct debug_stack_frame backtrace[DEBUG_MEMORY_STACK];
+#endif
+ size_t size;
+
+ unsigned magic;
+};
+
+struct debug_memory_footer
+{
+ unsigned magic;
+};
+
+
+static struct list_head list = { &list, &list };
+
+static unsigned long last_no = 0;
+
+
+static INLINE struct debug_memory_header *
+header_from_data(void *data)
+{
+ if(data)
+ return (struct debug_memory_header *)((char *)data - sizeof(struct debug_memory_header));
+ else
+ return NULL;
+}
+
+static INLINE void *
+data_from_header(struct debug_memory_header *hdr)
+{
+ if(hdr)
+ return (void *)((char *)hdr + sizeof(struct debug_memory_header));
+ else
+ return NULL;
+}
+
+static INLINE struct debug_memory_footer *
+footer_from_header(struct debug_memory_header *hdr)
+{
+ if(hdr)
+ return (struct debug_memory_footer *)((char *)hdr + sizeof(struct debug_memory_header) + hdr->size);
+ else
+ return NULL;
+}
+
+
+void *
+debug_malloc(const char *file, unsigned line, const char *function,
+ size_t size)
+{
+ struct debug_memory_header *hdr;
+ struct debug_memory_footer *ftr;
+
+ hdr = real_malloc(sizeof(*hdr) + size + sizeof(*ftr));
+ if(!hdr) {
+ debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
+ file, line, function,
+ (long unsigned)size);
+ return NULL;
+ }
+
+ hdr->no = last_no++;
+ hdr->file = file;
+ hdr->line = line;
+ hdr->function = function;
+ hdr->size = size;
+ hdr->magic = DEBUG_MEMORY_MAGIC;
+
+#if DEBUG_MEMORY_STACK
+ debug_backtrace_capture(hdr->backtrace, 0, DEBUG_MEMORY_STACK);
+#endif
+
+ ftr = footer_from_header(hdr);
+ ftr->magic = DEBUG_MEMORY_MAGIC;
+
+ LIST_ADDTAIL(&hdr->head, &list);
+
+ return data_from_header(hdr);
+}
+
+void
+debug_free(const char *file, unsigned line, const char *function,
+ void *ptr)
+{
+ struct debug_memory_header *hdr;
+ struct debug_memory_footer *ftr;
+
+ if(!ptr)
+ return;
+
+ hdr = header_from_data(ptr);
+ if(hdr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
+ file, line, function,
+ ptr);
+ debug_assert(0);
+ return;
+ }
+
+ ftr = footer_from_header(hdr);
+ if(ftr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: buffer overflow %p\n",
+ hdr->file, hdr->line, hdr->function,
+ ptr);
+ debug_assert(0);
+ }
+
+ LIST_DEL(&hdr->head);
+ hdr->magic = 0;
+ ftr->magic = 0;
+
+ real_free(hdr);
+}
+
+void *
+debug_calloc(const char *file, unsigned line, const char *function,
+ size_t count, size_t size )
+{
+ void *ptr = debug_malloc( file, line, function, count * size );
+ if( ptr )
+ memset( ptr, 0, count * size );
+ return ptr;
+}
+
+void *
+debug_realloc(const char *file, unsigned line, const char *function,
+ void *old_ptr, size_t old_size, size_t new_size )
+{
+ struct debug_memory_header *old_hdr, *new_hdr;
+ struct debug_memory_footer *old_ftr, *new_ftr;
+ void *new_ptr;
+
+ if(!old_ptr)
+ return debug_malloc( file, line, function, new_size );
+
+ if(!new_size) {
+ debug_free( file, line, function, old_ptr );
+ return NULL;
+ }
+
+ old_hdr = header_from_data(old_ptr);
+ if(old_hdr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: reallocating bad or corrupted memory %p\n",
+ file, line, function,
+ old_ptr);
+ debug_assert(0);
+ return NULL;
+ }
+
+ old_ftr = footer_from_header(old_hdr);
+ if(old_ftr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: buffer overflow %p\n",
+ old_hdr->file, old_hdr->line, old_hdr->function,
+ old_ptr);
+ debug_assert(0);
+ }
+
+ /* alloc new */
+ new_hdr = real_malloc(sizeof(*new_hdr) + new_size + sizeof(*new_ftr));
+ if(!new_hdr) {
+ debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
+ file, line, function,
+ (long unsigned)new_size);
+ return NULL;
+ }
+ new_hdr->no = old_hdr->no;
+ new_hdr->file = old_hdr->file;
+ new_hdr->line = old_hdr->line;
+ new_hdr->function = old_hdr->function;
+ new_hdr->size = new_size;
+ new_hdr->magic = DEBUG_MEMORY_MAGIC;
+
+ new_ftr = footer_from_header(new_hdr);
+ new_ftr->magic = DEBUG_MEMORY_MAGIC;
+
+ LIST_REPLACE(&old_hdr->head, &new_hdr->head);
+
+ /* copy data */
+ new_ptr = data_from_header(new_hdr);
+ memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size );
+
+ /* free old */
+ old_hdr->magic = 0;
+ old_ftr->magic = 0;
+ real_free(old_hdr);
+
+ return new_ptr;
+}
+
+unsigned long
+debug_memory_begin(void)
+{
+ return last_no;
+}
+
+void
+debug_memory_end(unsigned long start_no)
+{
+ size_t total_size = 0;
+ struct list_head *entry;
+
+ if(start_no == last_no)
+ return;
+
+ entry = list.prev;
+ for (; entry != &list; entry = entry->prev) {
+ struct debug_memory_header *hdr;
+ void *ptr;
+ struct debug_memory_footer *ftr;
+
+ hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
+ ptr = data_from_header(hdr);
+ ftr = footer_from_header(hdr);
+
+ if(hdr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: bad or corrupted memory %p\n",
+ hdr->file, hdr->line, hdr->function,
+ ptr);
+ debug_assert(0);
+ }
+
+ if((start_no <= hdr->no && hdr->no < last_no) ||
+ (last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))) {
+ debug_printf("%s:%u:%s: %u bytes at %p not freed\n",
+ hdr->file, hdr->line, hdr->function,
+ hdr->size, ptr);
+#if DEBUG_MEMORY_STACK
+ debug_backtrace_dump(hdr->backtrace, DEBUG_MEMORY_STACK);
+#endif
+ total_size += hdr->size;
+ }
+
+ if(ftr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: buffer overflow %p\n",
+ hdr->file, hdr->line, hdr->function,
+ ptr);
+ debug_assert(0);
+ }
+ }
+
+ if(total_size) {
+ debug_printf("Total of %u KB of system memory apparently leaked\n",
+ (total_size + 1023)/1024);
+ }
+ else {
+ debug_printf("No memory leaks detected.\n");
+ }
+}
diff --git a/src/gallium/auxiliary/util/u_debug_profile.c b/src/gallium/auxiliary/util/u_debug_profile.c
new file mode 100644
index 0000000000..6d8b244c3a
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_profile.c
@@ -0,0 +1,320 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Poor-man profiling.
+ *
+ * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ *
+ * @sa http://blogs.msdn.com/joshpoley/archive/2008/03/12/poor-man-s-profiler.aspx
+ * @sa http://www.johnpanzer.com/aci_cuj/index.html
+ */
+
+#include "pipe/p_config.h"
+
+#if defined(PROFILE) && defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+
+#include <windows.h>
+#include <winddi.h>
+
+#include "util/u_debug.h"
+#include "util/u_string.h"
+
+
+#define PROFILE_TABLE_SIZE (1024*1024)
+#define FILE_NAME_SIZE 256
+
+struct debug_profile_entry
+{
+ uintptr_t caller;
+ uintptr_t callee;
+ uint64_t samples;
+};
+
+static unsigned long enabled = 0;
+
+static WCHAR wFileName[FILE_NAME_SIZE] = L"\\??\\c:\\00000000.prof";
+static ULONG_PTR iFile = 0;
+
+static struct debug_profile_entry *table = NULL;
+static unsigned long free_table_entries = 0;
+static unsigned long max_table_entries = 0;
+
+uint64_t start_stamp = 0;
+uint64_t end_stamp = 0;
+
+
+static void
+debug_profile_entry(uintptr_t caller, uintptr_t callee, uint64_t samples)
+{
+ unsigned hash = ( caller + callee ) & PROFILE_TABLE_SIZE - 1;
+
+ while(1) {
+ if(table[hash].caller == 0 && table[hash].callee == 0) {
+ table[hash].caller = caller;
+ table[hash].callee = callee;
+ table[hash].samples = samples;
+ --free_table_entries;
+ break;
+ }
+ else if(table[hash].caller == caller && table[hash].callee == callee) {
+ table[hash].samples += samples;
+ break;
+ }
+ else {
+ ++hash;
+ }
+ }
+}
+
+
+static uintptr_t caller_stack[1024];
+static unsigned last_caller = 0;
+
+
+static int64_t delta(void) {
+ int64_t result = end_stamp - start_stamp;
+ if(result > UINT64_C(0xffffffff))
+ result = 0;
+ return result;
+}
+
+
+static void __cdecl
+debug_profile_enter(uintptr_t callee)
+{
+ uintptr_t caller = last_caller ? caller_stack[last_caller - 1] : 0;
+
+ if (caller)
+ debug_profile_entry(caller, 0, delta());
+ debug_profile_entry(caller, callee, 1);
+ caller_stack[last_caller++] = callee;
+}
+
+
+static void __cdecl
+debug_profile_exit(uintptr_t callee)
+{
+ debug_profile_entry(callee, 0, delta());
+ if(last_caller)
+ --last_caller;
+}
+
+
+/**
+ * Called at the start of every method or function.
+ *
+ * @sa http://msdn.microsoft.com/en-us/library/c63a9b7h.aspx
+ */
+void __declspec(naked) __cdecl
+_penter(void) {
+ _asm {
+ push eax
+ mov eax, [enabled]
+ test eax, eax
+ jz skip
+
+ push edx
+
+ rdtsc
+ mov dword ptr [end_stamp], eax
+ mov dword ptr [end_stamp+4], edx
+
+ xor eax, eax
+ mov [enabled], eax
+
+ mov eax, [esp+8]
+
+ push ebx
+ push ecx
+ push ebp
+ push edi
+ push esi
+
+ push eax
+ call debug_profile_enter
+ add esp, 4
+
+ pop esi
+ pop edi
+ pop ebp
+ pop ecx
+ pop ebx
+
+ mov eax, 1
+ mov [enabled], eax
+
+ rdtsc
+ mov dword ptr [start_stamp], eax
+ mov dword ptr [start_stamp+4], edx
+
+ pop edx
+skip:
+ pop eax
+ ret
+ }
+}
+
+
+/**
+ * Called at the end of Calls the end of every method or function.
+ *
+ * @sa http://msdn.microsoft.com/en-us/library/xc11y76y.aspx
+ */
+void __declspec(naked) __cdecl
+_pexit(void) {
+ _asm {
+ push eax
+ mov eax, [enabled]
+ test eax, eax
+ jz skip
+
+ push edx
+
+ rdtsc
+ mov dword ptr [end_stamp], eax
+ mov dword ptr [end_stamp+4], edx
+
+ xor eax, eax
+ mov [enabled], eax
+
+ mov eax, [esp+8]
+
+ push ebx
+ push ecx
+ push ebp
+ push edi
+ push esi
+
+ push eax
+ call debug_profile_exit
+ add esp, 4
+
+ pop esi
+ pop edi
+ pop ebp
+ pop ecx
+ pop ebx
+
+ mov eax, 1
+ mov [enabled], eax
+
+ rdtsc
+ mov dword ptr [start_stamp], eax
+ mov dword ptr [start_stamp+4], edx
+
+ pop edx
+skip:
+ pop eax
+ ret
+ }
+}
+
+
+/**
+ * Reference function for calibration.
+ */
+void __declspec(naked)
+__debug_profile_reference(void) {
+ _asm {
+ call _penter
+ call _pexit
+ ret
+ }
+}
+
+
+void
+debug_profile_start(void)
+{
+ WCHAR *p;
+
+ // increment starting from the less significant digit
+ p = &wFileName[14];
+ while(1) {
+ if(*p == '9') {
+ *p-- = '0';
+ }
+ else {
+ *p += 1;
+ break;
+ }
+ }
+
+ table = EngMapFile(wFileName,
+ PROFILE_TABLE_SIZE*sizeof(struct debug_profile_entry),
+ &iFile);
+ if(table) {
+ unsigned i;
+
+ free_table_entries = max_table_entries = PROFILE_TABLE_SIZE;
+ memset(table, 0, PROFILE_TABLE_SIZE*sizeof(struct debug_profile_entry));
+
+ table[0].caller = (uintptr_t)&__debug_profile_reference;
+ table[0].callee = 0;
+ table[0].samples = 0;
+ --free_table_entries;
+
+ _asm {
+ push edx
+ push eax
+
+ rdtsc
+ mov dword ptr [start_stamp], eax
+ mov dword ptr [start_stamp+4], edx
+
+ pop edx
+ pop eax
+ }
+
+ last_caller = 0;
+
+ enabled = 1;
+
+ for(i = 0; i < 8; ++i) {
+ _asm {
+ call __debug_profile_reference
+ }
+ }
+ }
+}
+
+
+void
+debug_profile_stop(void)
+{
+ enabled = 0;
+
+ if(iFile)
+ EngUnmapFile(iFile);
+ iFile = 0;
+ table = NULL;
+ free_table_entries = max_table_entries = 0;
+}
+
+#endif /* PROFILE */
diff --git a/src/gallium/auxiliary/util/u_debug_stack.c b/src/gallium/auxiliary/util/u_debug_stack.c
new file mode 100644
index 0000000000..528a1c394b
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_stack.c
@@ -0,0 +1,107 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Stack backtracing.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include "u_debug.h"
+#include "u_debug_symbol.h"
+#include "u_debug_stack.h"
+
+
+void
+debug_backtrace_capture(struct debug_stack_frame *backtrace,
+ unsigned start_frame,
+ unsigned nr_frames)
+{
+ const void **frame_pointer = NULL;
+ unsigned i = 0;
+
+ if(!nr_frames)
+ return;
+
+#if defined(PIPE_CC_GCC)
+ frame_pointer = ((const void **)__builtin_frame_address(1));
+#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
+ __asm {
+ mov frame_pointer, ebp
+ }
+ frame_pointer = (const void **)frame_pointer[0];
+#else
+ frame_pointer = NULL;
+#endif
+
+
+#ifdef PIPE_ARCH_X86
+ while(nr_frames) {
+ const void **next_frame_pointer;
+
+ if(!frame_pointer)
+ break;
+
+ if(start_frame)
+ --start_frame;
+ else {
+ backtrace[i++].function = frame_pointer[1];
+ --nr_frames;
+ }
+
+ next_frame_pointer = (const void **)frame_pointer[0];
+
+ /* Limit the stack walk to avoid referencing undefined memory */
+ if((uintptr_t)next_frame_pointer <= (uintptr_t)frame_pointer ||
+ (uintptr_t)next_frame_pointer > (uintptr_t)frame_pointer + 64*1024)
+ break;
+
+ frame_pointer = next_frame_pointer;
+ }
+#endif
+
+ while(nr_frames) {
+ backtrace[i++].function = NULL;
+ --nr_frames;
+ }
+}
+
+
+void
+debug_backtrace_dump(const struct debug_stack_frame *backtrace,
+ unsigned nr_frames)
+{
+ unsigned i;
+
+ for(i = 0; i < nr_frames; ++i) {
+ if(!backtrace[i].function)
+ break;
+ debug_symbol_print(backtrace[i].function);
+ }
+}
+
diff --git a/src/gallium/auxiliary/util/u_debug_stack.h b/src/gallium/auxiliary/util/u_debug_stack.h
new file mode 100644
index 0000000000..f50f04e0f7
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_stack.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_DEBUG_STACK_H_
+#define U_DEBUG_STACK_H_
+
+
+/**
+ * @file
+ * Stack backtracing.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct debug_stack_frame
+{
+ const void *function;
+};
+
+
+void
+debug_backtrace_capture(struct debug_stack_frame *backtrace,
+ unsigned start_frame,
+ unsigned nr_frames);
+
+void
+debug_backtrace_dump(const struct debug_stack_frame *backtrace,
+ unsigned nr_frames);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_STACK_H_ */
diff --git a/src/gallium/auxiliary/util/u_debug_symbol.c b/src/gallium/auxiliary/util/u_debug_symbol.c
new file mode 100644
index 0000000000..811931f81b
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_symbol.c
@@ -0,0 +1,250 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Symbol lookup.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include "pipe/p_compiler.h"
+
+#include "u_debug.h"
+#include "u_debug_symbol.h"
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) && defined(PIPE_ARCH_X86)
+
+#include <windows.h>
+#include <stddef.h>
+#include <imagehlp.h>
+
+/*
+ * TODO: Cleanup code.
+ * TODO: Support x86_64
+ */
+
+static BOOL bSymInitialized = FALSE;
+
+static HMODULE hModule_Imagehlp = NULL;
+
+typedef BOOL (WINAPI *PFNSYMINITIALIZE)(HANDLE, LPSTR, BOOL);
+static PFNSYMINITIALIZE pfnSymInitialize = NULL;
+
+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")))
+ )
+ return pfnSymInitialize(hProcess, UserSearchPath, fInvadeProcess);
+ else
+ return FALSE;
+}
+
+typedef BOOL (WINAPI *PFNSYMCLEANUP)(HANDLE);
+static PFNSYMCLEANUP pfnSymCleanup = NULL;
+
+static
+BOOL WINAPI j_SymCleanup(HANDLE hProcess)
+{
+ if(
+ (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
+ (pfnSymCleanup || (pfnSymCleanup = (PFNSYMCLEANUP) GetProcAddress(hModule_Imagehlp, "SymCleanup")))
+ )
+ return pfnSymCleanup(hProcess);
+ else
+ return FALSE;
+}
+
+typedef DWORD (WINAPI *PFNSYMSETOPTIONS)(DWORD);
+static PFNSYMSETOPTIONS pfnSymSetOptions = NULL;
+
+static
+DWORD WINAPI j_SymSetOptions(DWORD SymOptions)
+{
+ if(
+ (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
+ (pfnSymSetOptions || (pfnSymSetOptions = (PFNSYMSETOPTIONS) GetProcAddress(hModule_Imagehlp, "SymSetOptions")))
+ )
+ return pfnSymSetOptions(SymOptions);
+ else
+ return FALSE;
+}
+
+typedef BOOL (WINAPI *PFNSYMUNDNAME)(PIMAGEHLP_SYMBOL, PSTR, DWORD);
+static PFNSYMUNDNAME pfnSymUnDName = NULL;
+
+static
+BOOL WINAPI j_SymUnDName(PIMAGEHLP_SYMBOL Symbol, PSTR UnDecName, DWORD UnDecNameLength)
+{
+ if(
+ (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
+ (pfnSymUnDName || (pfnSymUnDName = (PFNSYMUNDNAME) GetProcAddress(hModule_Imagehlp, "SymUnDName")))
+ )
+ return pfnSymUnDName(Symbol, UnDecName, UnDecNameLength);
+ else
+ return FALSE;
+}
+
+typedef PFUNCTION_TABLE_ACCESS_ROUTINE PFNSYMFUNCTIONTABLEACCESS;
+static PFNSYMFUNCTIONTABLEACCESS pfnSymFunctionTableAccess = NULL;
+
+static
+PVOID WINAPI j_SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase)
+{
+ if(
+ (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
+ (pfnSymFunctionTableAccess || (pfnSymFunctionTableAccess = (PFNSYMFUNCTIONTABLEACCESS) GetProcAddress(hModule_Imagehlp, "SymFunctionTableAccess")))
+ )
+ return pfnSymFunctionTableAccess(hProcess, AddrBase);
+ else
+ return NULL;
+}
+
+typedef PGET_MODULE_BASE_ROUTINE PFNSYMGETMODULEBASE;
+static PFNSYMGETMODULEBASE pfnSymGetModuleBase = NULL;
+
+static
+DWORD WINAPI j_SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
+{
+ if(
+ (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
+ (pfnSymGetModuleBase || (pfnSymGetModuleBase = (PFNSYMGETMODULEBASE) GetProcAddress(hModule_Imagehlp, "SymGetModuleBase")))
+ )
+ return pfnSymGetModuleBase(hProcess, dwAddr);
+ else
+ return 0;
+}
+
+typedef BOOL (WINAPI *PFNSTACKWALK)(DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID, PREAD_PROCESS_MEMORY_ROUTINE, PFUNCTION_TABLE_ACCESS_ROUTINE, PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE);
+static PFNSTACKWALK pfnStackWalk = NULL;
+
+static
+BOOL WINAPI j_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
+)
+{
+ if(
+ (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
+ (pfnStackWalk || (pfnStackWalk = (PFNSTACKWALK) GetProcAddress(hModule_Imagehlp, "StackWalk")))
+ )
+ return pfnStackWalk(
+ MachineType,
+ hProcess,
+ hThread,
+ StackFrame,
+ ContextRecord,
+ ReadMemoryRoutine,
+ FunctionTableAccessRoutine,
+ GetModuleBaseRoutine,
+ TranslateAddress
+ );
+ else
+ return FALSE;
+}
+
+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);
+ else
+ return FALSE;
+}
+
+typedef BOOL (WINAPI *PFNSYMGETLINEFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_LINE);
+static PFNSYMGETLINEFROMADDR pfnSymGetLineFromAddr = NULL;
+
+static
+BOOL WINAPI j_SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
+{
+ if(
+ (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
+ (pfnSymGetLineFromAddr || (pfnSymGetLineFromAddr = (PFNSYMGETLINEFROMADDR) GetProcAddress(hModule_Imagehlp, "SymGetLineFromAddr")))
+ )
+ return pfnSymGetLineFromAddr(hProcess, dwAddr, pdwDisplacement, Line);
+ else
+ return FALSE;
+}
+
+
+static INLINE boolean
+debug_symbol_print_imagehlp(const void *addr)
+{
+ 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
+
+ hProcess = GetCurrentProcess();
+
+ pSymbol->SizeOfStruct = sizeof(symbolBuffer);
+ pSymbol->MaxNameLength = sizeof(symbolBuffer) - offsetof(IMAGEHLP_SYMBOL, Name);
+
+ if(!bSymInitialized) {
+ j_SymSetOptions(/* SYMOPT_UNDNAME | */ SYMOPT_LOAD_LINES);
+ if(j_SymInitialize(hProcess, NULL, TRUE))
+ bSymInitialized = TRUE;
+ }
+
+ if(!j_SymGetSymFromAddr(hProcess, (DWORD)addr, &dwDisplacement, pSymbol))
+ return FALSE;
+
+ debug_printf("\t%s\n", pSymbol->Name);
+
+ return TRUE;
+
+}
+#endif
+
+
+void
+debug_symbol_print(const void *addr)
+{
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) && defined(PIPE_ARCH_X86)
+ if(debug_symbol_print_imagehlp(addr))
+ return;
+#endif
+
+ debug_printf("\t%p\n", addr);
+}
diff --git a/src/gallium/auxiliary/util/u_debug_symbol.h b/src/gallium/auxiliary/util/u_debug_symbol.h
new file mode 100644
index 0000000000..021586987b
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_symbol.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_DEBUG_SYMBOL_H_
+#define U_DEBUG_SYMBOL_H_
+
+
+/**
+ * @file
+ * Symbol lookup.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void
+debug_symbol_print(const void *addr);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_SYMBOL_H_ */
diff --git a/src/gallium/auxiliary/util/u_double_list.h b/src/gallium/auxiliary/util/u_double_list.h
new file mode 100644
index 0000000000..53bb1342dd
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_double_list.h
@@ -0,0 +1,102 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
+ * 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.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * List macros heavily inspired by the Linux kernel
+ * list handling. No list looping yet.
+ *
+ * Is not threadsafe, so common operations need to
+ * be protected using an external mutex.
+ */
+
+#ifndef _U_DOUBLE_LIST_H_
+#define _U_DOUBLE_LIST_H_
+
+
+#include <stddef.h>
+
+
+struct list_head
+{
+ struct list_head *prev;
+ struct list_head *next;
+};
+
+
+#define LIST_INITHEAD(__item) \
+ do { \
+ (__item)->prev = (__item); \
+ (__item)->next = (__item); \
+ } while (0)
+
+#define LIST_ADD(__item, __list) \
+ do { \
+ (__item)->prev = (__list); \
+ (__item)->next = (__list)->next; \
+ (__list)->next->prev = (__item); \
+ (__list)->next = (__item); \
+ } while (0)
+
+#define LIST_ADDTAIL(__item, __list) \
+ do { \
+ (__item)->next = (__list); \
+ (__item)->prev = (__list)->prev; \
+ (__list)->prev->next = (__item); \
+ (__list)->prev = (__item); \
+ } while(0)
+
+#define LIST_REPLACE(__from, __to) \
+ do { \
+ (__to)->prev = (__from)->prev; \
+ (__to)->next = (__from)->next; \
+ (__from)->next->prev = (__to); \
+ (__from)->prev->next = (__to); \
+ } while (0)
+
+#define LIST_DEL(__item) \
+ do { \
+ (__item)->prev->next = (__item)->next; \
+ (__item)->next->prev = (__item)->prev; \
+ } while(0)
+
+#define LIST_DELINIT(__item) \
+ do { \
+ (__item)->prev->next = (__item)->next; \
+ (__item)->next->prev = (__item)->prev; \
+ (__item)->next = (__item); \
+ (__item)->prev = (__item); \
+ } while(0)
+
+#define LIST_ENTRY(__type, __item, __field) \
+ ((__type *)(((char *)(__item)) - offsetof(__type, __field)))
+
+#define LIST_IS_EMPTY(__list) \
+ ((__list)->next == (__list))
+
+
+#endif /*_U_DOUBLE_LIST_H_*/
diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c
new file mode 100644
index 0000000000..4110485fb1
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_draw_quad.c
@@ -0,0 +1,134 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_draw_quad.h"
+
+
+/**
+ * Draw a simple vertex buffer / primitive.
+ * Limited to float[4] vertex attribs, tightly packed.
+ */
+void
+util_draw_vertex_buffer(struct pipe_context *pipe,
+ struct pipe_buffer *vbuf,
+ uint offset,
+ uint prim_type,
+ uint num_verts,
+ uint num_attribs)
+{
+ struct pipe_vertex_buffer vbuffer;
+ struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+ uint i;
+
+ assert(num_attribs <= PIPE_MAX_ATTRIBS);
+
+ /* tell pipe about the vertex buffer */
+ memset(&vbuffer, 0, sizeof(vbuffer));
+ 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);
+
+ /* tell pipe about the vertex attributes */
+ for (i = 0; i < num_attribs; i++) {
+ velements[i].src_offset = i * 4 * sizeof(float);
+ velements[i].vertex_buffer_index = 0;
+ velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ velements[i].nr_components = 4;
+ }
+ pipe->set_vertex_elements(pipe, num_attribs, velements);
+
+ /* draw */
+ pipe->draw_arrays(pipe, prim_type, 0, num_verts);
+}
+
+
+
+/**
+ * Draw screen-aligned textured quad.
+ * Note: this function allocs/destroys a vertex buffer and isn't especially
+ * efficient.
+ */
+void
+util_draw_texquad(struct pipe_context *pipe,
+ float x0, float y0, float x1, float y1, float z)
+{
+ struct pipe_buffer *vbuf;
+ uint numAttribs = 2, vertexBytes, i, j;
+
+ vertexBytes = 4 * (4 * numAttribs * sizeof(float));
+
+ /* XXX create one-time */
+ vbuf = pipe_buffer_create(pipe->screen, 32,
+ PIPE_BUFFER_USAGE_VERTEX, vertexBytes);
+ if (vbuf) {
+ float *v = (float *) pipe_buffer_map(pipe->screen, vbuf,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ if (v) {
+ /*
+ * Load vertex buffer
+ */
+ for (i = j = 0; i < 4; i++) {
+ v[j + 2] = z; /* z */
+ v[j + 3] = 1.0; /* w */
+ v[j + 6] = 0.0; /* r */
+ v[j + 7] = 1.0; /* q */
+ j += 8;
+ }
+
+ v[0] = x0;
+ v[1] = y0;
+ v[4] = 0.0; /*s*/
+ v[5] = 0.0; /*t*/
+
+ v[8] = x1;
+ v[9] = y0;
+ v[12] = 1.0;
+ v[13] = 0.0;
+
+ v[16] = x1;
+ v[17] = y1;
+ v[20] = 1.0;
+ v[21] = 1.0;
+
+ v[24] = x0;
+ v[25] = y1;
+ v[28] = 0.0;
+ v[29] = 1.0;
+
+ pipe_buffer_unmap(pipe->screen, vbuf);
+ util_draw_vertex_buffer(pipe, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
+ }
+
+ pipe_buffer_reference(&vbuf, NULL);
+ }
+}
diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h
new file mode 100644
index 0000000000..00d3f5b715
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_draw_quad.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_DRAWQUAD_H
+#define U_DRAWQUAD_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct pipe_buffer;
+
+extern void
+util_draw_vertex_buffer(struct pipe_context *pipe,
+ struct pipe_buffer *vbuf, uint offset,
+ uint num_attribs, uint num_verts, uint prim_type);
+
+
+extern void
+util_draw_texquad(struct pipe_context *pipe,
+ float x0, float y0, float x1, float y1, float z);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_fifo.h b/src/gallium/auxiliary/util/u_fifo.h
new file mode 100644
index 0000000000..9e007de1ad
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_fifo.h
@@ -0,0 +1,94 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 Jakob Bornecrantz
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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 U_FIFO_H
+#define U_FIFO_H
+
+#include "util/u_memory.h"
+
+struct util_fifo
+{
+ size_t head;
+ size_t tail;
+ size_t num;
+ size_t size;
+};
+
+static INLINE struct util_fifo *
+u_fifo_create(size_t size)
+{
+ struct util_fifo *fifo;
+ fifo = MALLOC(sizeof(*fifo) + size * sizeof(void*));
+
+ fifo->head = 0;
+ fifo->tail = 0;
+ fifo->num = 0;
+ fifo->size = size;
+
+ return fifo;
+}
+
+static INLINE boolean
+u_fifo_add(struct util_fifo *fifo, void *ptr)
+{
+ void **array = (void**)&fifo[1];
+ if (fifo->num >= fifo->size)
+ return FALSE;
+
+ if (++fifo->head >= fifo->size)
+ fifo->head = 0;
+
+ array[fifo->head] = ptr;
+
+ ++fifo->num;
+
+ return TRUE;
+}
+
+static INLINE boolean
+u_fifo_pop(struct util_fifo *fifo, void **ptr)
+{
+ void **array = (void**)&fifo[1];
+
+ if (!fifo->num)
+ return FALSE;
+
+ if (++fifo->tail >= fifo->size)
+ fifo->tail = 0;
+
+ *ptr = array[fifo->tail];
+
+ ++fifo->num;
+
+ return TRUE;
+}
+
+static INLINE void
+u_fifo_destroy(struct util_fifo *fifo)
+{
+ FREE(fifo);
+}
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_format.c b/src/gallium/auxiliary/util/u_format.c
new file mode 100644
index 0000000000..98ea13b60b
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_format.c
@@ -0,0 +1,46 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Vmware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "u_format.h"
+
+
+const struct util_format_description *
+util_format_description(enum pipe_format format)
+{
+ const struct util_format_description *desc = util_format_description_table;
+
+ while(TRUE) {
+ if(desc->format == format)
+ return desc;
+
+ if(desc->format == PIPE_FORMAT_NONE)
+ return NULL;
+
+ ++desc;
+ };
+}
diff --git a/src/gallium/auxiliary/util/u_format.csv b/src/gallium/auxiliary/util/u_format.csv
new file mode 100644
index 0000000000..6e82983e58
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_format.csv
@@ -0,0 +1,99 @@
+PIPE_FORMAT_A8R8G8B8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , zyxw, rgb
+PIPE_FORMAT_X8R8G8B8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , zyx1, rgb
+PIPE_FORMAT_B8G8R8A8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , yzwx, rgb
+PIPE_FORMAT_B8G8R8X8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , yzw1, rgb
+PIPE_FORMAT_A1R5G5B5_UNORM , arith , 1, 1, un1 , un5 , un5 , un5 , zyxw, rgb
+PIPE_FORMAT_A4R4G4B4_UNORM , arith , 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb
+PIPE_FORMAT_R5G6B5_UNORM , arith , 1, 1, un5 , un6 , un5 , , zyx1, rgb
+PIPE_FORMAT_A2B10G10R10_UNORM , arith , 1, 1, un10, un10, un10, un2 , xyzw, rgb
+PIPE_FORMAT_L8_UNORM , arith , 1, 1, un8 , , , , xxx1, rgb
+PIPE_FORMAT_A8_UNORM , arith , 1, 1, un8 , , , , 000x, rgb
+PIPE_FORMAT_I8_UNORM , arith , 1, 1, un8 , , , , xxxx, rgb
+PIPE_FORMAT_A8L8_UNORM , arith , 1, 1, un8 , un8 , , , xxxy, rgb
+PIPE_FORMAT_L16_UNORM , arith , 1, 1, un16, , , , xxx1, rgb
+PIPE_FORMAT_Z16_UNORM , array , 1, 1, un16, , , , x___, zs
+PIPE_FORMAT_Z32_UNORM , array , 1, 1, un32, , , , x___, zs
+PIPE_FORMAT_Z32_FLOAT , array , 1, 1, f32 , , , , x___, zs
+PIPE_FORMAT_S8Z24_UNORM , arith , 1, 1, un24, un8 , , , xy__, zs
+PIPE_FORMAT_Z24S8_UNORM , arith , 1, 1, un8 , un24, , , yx__, zs
+PIPE_FORMAT_X8Z24_UNORM , arith , 1, 1, un24, un8 , , , x___, zs
+PIPE_FORMAT_Z24X8_UNORM , arith , 1, 1, un8 , un24, , , y___, zs
+PIPE_FORMAT_S8_UNORM , array , 1, 1, un8 , , , , _x__, zs
+PIPE_FORMAT_R64_FLOAT , array , 1, 1, f64 , , , , x001, rgb
+PIPE_FORMAT_R64G64_FLOAT , array , 1, 1, f64 , f64 , , , xy01, rgb
+PIPE_FORMAT_R64G64B64_FLOAT , array , 1, 1, f64 , f64 , f64 , , xyz1, rgb
+PIPE_FORMAT_R64G64B64A64_FLOAT , array , 1, 1, f64 , f64 , f64 , f64 , xyzw, rgb
+PIPE_FORMAT_R32_FLOAT , array , 1, 1, f32 , , , , x001, rgb
+PIPE_FORMAT_R32G32_FLOAT , array , 1, 1, f32 , f32 , , , xy01, rgb
+PIPE_FORMAT_R32G32B32_FLOAT , array , 1, 1, f32 , f32 , f32 , , xyz1, rgb
+PIPE_FORMAT_R32G32B32A32_FLOAT , array , 1, 1, f32 , f32 , f32 , f32 , xyzw, rgb
+PIPE_FORMAT_R32_UNORM , array , 1, 1, un32, , , , x001, rgb
+PIPE_FORMAT_R32G32_UNORM , array , 1, 1, un32, un32, , , xy01, rgb
+PIPE_FORMAT_R32G32B32_UNORM , array , 1, 1, un32, un32, un32, , xyz1, rgb
+PIPE_FORMAT_R32G32B32A32_UNORM , array , 1, 1, un32, un32, un32, un32, xyzw, rgb
+PIPE_FORMAT_R32_USCALED , array , 1, 1, u32 , , , , x001, rgb
+PIPE_FORMAT_R32G32_USCALED , array , 1, 1, u32 , u32 , , , xy01, rgb
+PIPE_FORMAT_R32G32B32_USCALED , array , 1, 1, u32 , u32 , u32 , , xyz1, rgb
+PIPE_FORMAT_R32G32B32A32_USCALED , array , 1, 1, u32 , u32 , u32 , u32 , xyzw, rgb
+PIPE_FORMAT_R32_SNORM , array , 1, 1, sn32, , , , x001, rgb
+PIPE_FORMAT_R32G32_SNORM , array , 1, 1, sn32, sn32, , , xy01, rgb
+PIPE_FORMAT_R32G32B32_SNORM , array , 1, 1, sn32, sn32, sn32, , xyz1, rgb
+PIPE_FORMAT_R32G32B32A32_SNORM , array , 1, 1, sn32, sn32, sn32, sn32, xyzw, rgb
+PIPE_FORMAT_R32_SSCALED , array , 1, 1, s32 , , , , x001, rgb
+PIPE_FORMAT_R32G32_SSCALED , array , 1, 1, s32 , s32 , , , xy01, rgb
+PIPE_FORMAT_R32G32B32_SSCALED , array , 1, 1, s32 , s32 , s32 , , xyz1, rgb
+PIPE_FORMAT_R32G32B32A32_SSCALED , array , 1, 1, s32 , s32 , s32 , s32 , xyzw, rgb
+PIPE_FORMAT_R16_UNORM , array , 1, 1, un16, , , , x001, rgb
+PIPE_FORMAT_R16G16_UNORM , array , 1, 1, un16, un16, , , xy01, rgb
+PIPE_FORMAT_R16G16B16_UNORM , array , 1, 1, un16, un16, un16, , xyz1, rgb
+PIPE_FORMAT_R16G16B16A16_UNORM , array , 1, 1, un16, un16, un16, un16, xyzw, rgb
+PIPE_FORMAT_R16_USCALED , array , 1, 1, u16 , , , , x001, rgb
+PIPE_FORMAT_R16G16_USCALED , array , 1, 1, u16 , u16 , , , xy01, rgb
+PIPE_FORMAT_R16G16B16_USCALED , array , 1, 1, u16 , u16 , u16 , , xyz1, rgb
+PIPE_FORMAT_R16G16B16A16_USCALED , array , 1, 1, u16 , u16 , u16 , u16 , xyzw, rgb
+PIPE_FORMAT_R16_SNORM , array , 1, 1, sn16, , , , x001, rgb
+PIPE_FORMAT_R16G16_SNORM , array , 1, 1, sn16, sn16, , , xy01, rgb
+PIPE_FORMAT_R16G16B16_SNORM , array , 1, 1, sn16, sn16, sn16, , xyz1, rgb
+PIPE_FORMAT_R16G16B16A16_SNORM , array , 1, 1, sn16, sn16, sn16, sn16, xyzw, rgb
+PIPE_FORMAT_R16_SSCALED , array , 1, 1, s16 , , , , x001, rgb
+PIPE_FORMAT_R16G16_SSCALED , array , 1, 1, s16 , s16 , , , xy01, rgb
+PIPE_FORMAT_R16G16B16_SSCALED , array , 1, 1, s16 , s16 , s16 , , xyz1, rgb
+PIPE_FORMAT_R16G16B16A16_SSCALED , array , 1, 1, s16 , s16 , s16 , s16 , xyzw, rgb
+PIPE_FORMAT_R8_UNORM , array , 1, 1, un8 , , , , x001, rgb
+PIPE_FORMAT_R8G8_UNORM , array , 1, 1, un8 , un8 , , , xy01, rgb
+PIPE_FORMAT_R8G8B8_UNORM , array , 1, 1, un8 , un8 , un8 , , xyz1, rgb
+PIPE_FORMAT_R8G8B8A8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , xyzw, rgb
+PIPE_FORMAT_R8G8B8X8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , xyz1, rgb
+PIPE_FORMAT_R8_USCALED , array , 1, 1, u8 , , , , x001, rgb
+PIPE_FORMAT_R8G8_USCALED , array , 1, 1, u8 , u8 , , , xy01, rgb
+PIPE_FORMAT_R8G8B8_USCALED , array , 1, 1, u8 , u8 , u8 , , xyz1, rgb
+PIPE_FORMAT_R8G8B8A8_USCALED , array , 1, 1, u8 , u8 , u8 , u8 , xyzw, rgb
+PIPE_FORMAT_R8G8B8X8_USCALED , array , 1, 1, u8 , u8 , u8 , u8 , xyz1, rgb
+PIPE_FORMAT_R8_SNORM , array , 1, 1, sn8 , , , , x001, rgb
+PIPE_FORMAT_R8G8_SNORM , array , 1, 1, sn8 , sn8 , , , xy01, rgb
+PIPE_FORMAT_R8G8B8_SNORM , array , 1, 1, sn8 , sn8 , sn8 , , xyz1, rgb
+PIPE_FORMAT_R8G8B8A8_SNORM , array , 1, 1, sn8 , sn8 , sn8 , sn8 , xyzw, rgb
+PIPE_FORMAT_R8G8B8X8_SNORM , array , 1, 1, sn8 , sn8 , sn8 , sn8 , xyz1, rgb
+PIPE_FORMAT_B6G5R5_SNORM , arith , 1, 1, sn5 , sn5 , sn6 , , zyx1, rgb
+PIPE_FORMAT_A8B8G8R8_SNORM , arith , 1, 1, sn8 , sn8 , sn8 , sn8 , zyxw, rgb
+PIPE_FORMAT_X8B8G8R8_SNORM , arith , 1, 1, sn8 , sn8 , sn8 , sn8 , zyx1, rgb
+PIPE_FORMAT_R8_SSCALED , array , 1, 1, s8 , , , , x001, rgb
+PIPE_FORMAT_R8G8_SSCALED , array , 1, 1, s8 , s8 , , , xy01, rgb
+PIPE_FORMAT_R8G8B8_SSCALED , array , 1, 1, s8 , s8 , s8 , , xyz1, rgb
+PIPE_FORMAT_R8G8B8A8_SSCALED , array , 1, 1, s8 , s8 , s8 , s8 , xyzw, rgb
+PIPE_FORMAT_R8G8B8X8_SSCALED , array , 1, 1, s8 , s8 , s8 , s8 , xyz1, rgb
+PIPE_FORMAT_R32_FIXED , array , 1, 1, h32 , , , , x001, rgb
+PIPE_FORMAT_R32G32_FIXED , array , 1, 1, h32 , h32 , , , xy01, rgb
+PIPE_FORMAT_R32G32B32_FIXED , array , 1, 1, h32 , h32 , h32 , , xyz1, rgb
+PIPE_FORMAT_R32G32B32A32_FIXED , array , 1, 1, h32 , h32 , h32 , h32 , xyzw, rgb
+PIPE_FORMAT_L8_SRGB , arith , 1, 1, u8 , , , , xxx1, srgb
+PIPE_FORMAT_A8L8_SRGB , arith , 1, 1, u8 , u8 , , , xxxy, srgb
+PIPE_FORMAT_R8G8B8_SRGB , arith , 1, 1, u8 , u8 , u8 , , xyz1, srgb
+PIPE_FORMAT_R8G8B8A8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , xyzw, srgb
+PIPE_FORMAT_R8G8B8X8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , xyz1, srgb
+PIPE_FORMAT_A8R8G8B8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , wxyz, srgb
+PIPE_FORMAT_X8R8G8B8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , 1xyz, srgb
+PIPE_FORMAT_B8G8R8A8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , zyxw, srgb
+PIPE_FORMAT_B8G8R8X8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , zyx1, srgb
+PIPE_FORMAT_X8UB8UG8SR8S_NORM , arith , 1, 1, sn8 , sn8 , un8 , x8 , 1zyx, rgb
+PIPE_FORMAT_B6UG5SR5S_NORM , arith , 1, 1, sn5 , sn5 , un6 , , xyz1, rgb
diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h
new file mode 100644
index 0000000000..7b5b7fcda5
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_format.h
@@ -0,0 +1,138 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Vmware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef U_FORMAT_H
+#define U_FORMAT_H
+
+
+#include "pipe/p_format.h"
+
+
+enum util_format_layout {
+ UTIL_FORMAT_LAYOUT_SCALAR = 0,
+ UTIL_FORMAT_LAYOUT_ARITH = 1,
+ UTIL_FORMAT_LAYOUT_ARRAY = 2,
+ UTIL_FORMAT_LAYOUT_YUV = 3,
+ UTIL_FORMAT_LAYOUT_DXT = 4
+};
+
+
+struct util_format_block
+{
+ /** Block width in pixels */
+ unsigned width;
+
+ /** Block height in pixels */
+ unsigned height;
+
+ /** Block size in bytes */
+ unsigned bits;
+};
+
+
+enum util_format_type {
+ UTIL_FORMAT_TYPE_VOID = 0,
+ UTIL_FORMAT_TYPE_UNSIGNED = 1,
+ UTIL_FORMAT_TYPE_SIGNED = 2,
+ UTIL_FORMAT_TYPE_FIXED = 3,
+ UTIL_FORMAT_TYPE_FLOAT = 4
+};
+
+
+enum util_format_swizzle {
+ UTIL_FORMAT_SWIZZLE_X = 0,
+ UTIL_FORMAT_SWIZZLE_Y = 1,
+ UTIL_FORMAT_SWIZZLE_Z = 2,
+ UTIL_FORMAT_SWIZZLE_W = 3,
+ UTIL_FORMAT_SWIZZLE_0 = 4,
+ UTIL_FORMAT_SWIZZLE_1 = 5,
+ UTIL_FORMAT_SWIZZLE_NONE = 6
+};
+
+
+enum util_format_colorspace {
+ UTIL_FORMAT_COLORSPACE_RGB = 0,
+ UTIL_FORMAT_COLORSPACE_SRGB = 1,
+ UTIL_FORMAT_COLORSPACE_YUV = 2,
+ UTIL_FORMAT_COLORSPACE_ZS = 3,
+};
+
+
+struct util_format_channel_description
+{
+ unsigned type:6;
+ unsigned normalized:1;
+ unsigned size:9;
+};
+
+
+struct util_format_description
+{
+ enum pipe_format format;
+ const char *name;
+ struct util_format_block block;
+ enum util_format_layout layout;
+ struct util_format_channel_description channel[4];
+ unsigned char swizzle[4];
+ enum util_format_colorspace colorspace;
+};
+
+
+extern const struct util_format_description
+util_format_description_table[];
+
+
+const struct util_format_description *
+util_format_description(enum pipe_format format);
+
+
+void
+util_format_read_4f(enum pipe_format format,
+ float *dst, unsigned dst_stride,
+ const void *src, unsigned src_stride,
+ unsigned x, unsigned y, unsigned w, unsigned h);
+
+void
+util_format_write_4f(enum pipe_format format,
+ const float *src, unsigned src_stride,
+ void *dst, unsigned dst_stride,
+ unsigned x, unsigned y, unsigned w, unsigned h);
+
+void
+util_format_read_4ub(enum pipe_format format,
+ uint8_t *dst, unsigned dst_stride,
+ const void *src, unsigned src_stride,
+ unsigned x, unsigned y, unsigned w, unsigned h);
+
+void
+util_format_write_4ub(enum pipe_format format,
+ const uint8_t *src, unsigned src_stride,
+ void *dst, unsigned dst_stride,
+ unsigned x, unsigned y, unsigned w, unsigned h);
+
+#endif /* ! U_FORMAT_H */
diff --git a/src/gallium/auxiliary/util/u_format_access.py b/src/gallium/auxiliary/util/u_format_access.py
new file mode 100644
index 0000000000..eeb1a9657f
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_format_access.py
@@ -0,0 +1,498 @@
+#!/usr/bin/env python
+
+'''
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Pixel format accessor functions.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+'''
+
+
+import sys
+
+from u_format_parse import *
+
+
+def short_name(format):
+ '''Make up a short norm for a format, suitable to be used as suffix in
+ function names.'''
+
+ name = format.name
+ if name.startswith('PIPE_FORMAT_'):
+ name = name[len('PIPE_FORMAT_'):]
+ name = name.lower()
+ return name
+
+
+def is_format_supported(format):
+ '''Determines whether we actually have the plumbing necessary to generate the
+ to read/write to/from this format.'''
+
+ # FIXME: Ideally we would support any format combination here.
+
+ # XXX: It should be straightforward to support srgb
+ if format.colorspace not in ('rgb', 'zs'):
+ return False
+
+ if format.layout not in (ARITH, ARRAY):
+ return False
+
+ for i in range(4):
+ type = format.in_types[i]
+ if type.kind not in (VOID, UNSIGNED, FLOAT):
+ return False
+
+ # We can only read a color from a depth/stencil format if the depth channel is present
+ if format.colorspace == 'zs' and format.out_swizzle[0] == SWIZZLE_NONE:
+ return False
+
+ return True
+
+
+def native_type(format):
+ '''Get the native appropriate for a format.'''
+
+ if format.layout == ARITH:
+ # For arithmetic pixel formats return the integer type that matches the whole pixel
+ return 'uint%u_t' % format.block_size()
+ elif format.layout == ARRAY:
+ # For array pixel formats return the integer type that matches the color channel
+ type = format.in_types[0]
+ if type.kind == UNSIGNED:
+ return 'uint%u_t' % type.size
+ elif type.kind == SIGNED:
+ return 'int%u_t' % type.size
+ elif type.kind == FLOAT:
+ if type.size == 32:
+ return 'float'
+ elif type.size == 64:
+ return 'double'
+ else:
+ assert False
+ else:
+ assert False
+ else:
+ assert False
+
+
+def intermediate_native_type(bits, sign):
+ '''Find a native type adequate to hold intermediate results of the request bit size.'''
+
+ bytes = 4 # don't use anything smaller than 32bits
+ while bytes * 8 < bits:
+ bytes *= 2
+ bits = bytes*8
+
+ if sign:
+ return 'int%u_t' % bits
+ else:
+ return 'uint%u_t' % bits
+
+
+def get_one_shift(type):
+ '''Get the number of the bit that matches unity for this type.'''
+ if type.kind == 'FLOAT':
+ assert False
+ if not type.norm:
+ return 0
+ if type.kind == UNSIGNED:
+ return type.size
+ if type.kind == SIGNED:
+ return type.size - 1
+ if type.kind == FIXED:
+ return type.size / 2
+ assert False
+
+
+def get_one(type):
+ '''Get the value of unity for this type.'''
+ if type.kind == 'FLOAT' or not type.norm:
+ return 1
+ else:
+ return (1 << get_one_shift(type)) - 1
+
+
+def generate_clamp():
+ '''Code generate the clamping functions for each type.
+
+ We don't use a macro so that arguments with side effects,
+ like *src_pixel++ are correctly handled.
+ '''
+
+ for suffix, native_type in [
+ ('', 'double'),
+ ('f', 'float'),
+ ('ui', 'unsigned int'),
+ ('si', 'int'),
+ ]:
+ print 'static INLINE %s' % native_type
+ print 'clamp%s(%s value, %s lbound, %s ubound)' % (suffix, native_type, native_type, native_type)
+ print '{'
+ print ' if(value < lbound)'
+ print ' return lbound;'
+ print ' if(value > ubound)'
+ print ' return ubound;'
+ print ' return value;'
+ print '}'
+ print
+
+
+def clamp_expr(src_type, dst_type, dst_native_type, value):
+ '''Generate the expression to clamp the value in the source type to the
+ destination type range.'''
+
+ if src_type == dst_type:
+ return value
+
+ # Pick the approriate clamp function
+ if src_type.kind == FLOAT:
+ if src_type.size == 32:
+ func = 'clampf'
+ elif src_type.size == 64:
+ func = 'clamp'
+ else:
+ assert False
+ elif src_type.kind == UNSIGNED:
+ func = 'clampui'
+ elif src_type.kind == SIGNED:
+ func = 'clampsi'
+ else:
+ assert False
+
+ # Clamp floats to [-1, 1] or [0, 1] range
+ if src_type.kind == FLOAT and dst_type.norm:
+ max = 1
+ if src_type.sign and dst_type.sign:
+ min = -1
+ else:
+ min = 0
+ return '%s(%s, %s, %s)' % (func, value, min, max)
+
+ # FIXME: Also clamp scaled values
+
+ return value
+
+
+def conversion_expr(src_type, dst_type, dst_native_type, value):
+ '''Generate the expression to convert a value between two types.'''
+
+ if src_type == dst_type:
+ return value
+
+ if src_type.kind == FLOAT and dst_type.kind == FLOAT:
+ return '(%s)%s' % (dst_native_type, value)
+
+ if not src_type.norm and not dst_type.norm:
+ return '(%s)%s' % (dst_native_type, value)
+
+ value = clamp_expr(src_type, dst_type, dst_native_type, value)
+
+ if dst_type.kind == FLOAT:
+ if src_type.norm:
+ one = get_one(src_type)
+ if src_type.size <= 23:
+ scale = '(1.0f/0x%x)' % one
+ else:
+ # bigger than single precision mantissa, use double
+ scale = '(1.0/0x%x)' % one
+ value = '(%s * %s)' % (value, scale)
+ return '(%s)%s' % (dst_native_type, value)
+
+ if src_type.kind == FLOAT:
+ if dst_type.norm:
+ dst_one = get_one(dst_type)
+ if dst_type.size <= 23:
+ scale = '0x%x' % dst_one
+ else:
+ # bigger than single precision mantissa, use double
+ scale = '(double)0x%x' % dst_one
+ value = '(%s * %s)' % (value, scale)
+ return '(%s)%s' % (dst_native_type, value)
+
+ if src_type.kind == dst_type.kind:
+ src_one = get_one(src_type)
+ dst_one = get_one(dst_type)
+
+ if src_one > dst_one and src_type.norm and dst_type.norm:
+ # We can just bitshift
+ src_shift = get_one_shift(src_type)
+ dst_shift = get_one_shift(dst_type)
+ value = '(%s >> %s)' % (value, src_shift - dst_shift)
+ else:
+ # We need to rescale using an intermediate type big enough to hold the multiplication of both
+ tmp_native_type = intermediate_native_type(src_type.size + dst_type.size, src_type.sign and dst_type.sign)
+ value = '(%s)%s' % (tmp_native_type, value)
+ value = '%s * 0x%x / 0x%x' % (value, dst_one, src_one)
+ value = '(%s)%s' % (dst_native_type, value)
+ return value
+
+ assert False
+
+
+def generate_format_read(format, dst_type, dst_native_type, dst_suffix):
+ '''Generate the function to read pixels from a particular format'''
+
+ name = short_name(format)
+
+ src_native_type = native_type(format)
+
+ print 'static void'
+ print 'util_format_%s_read_%s(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, dst_suffix, dst_native_type)
+ print '{'
+ print ' unsigned x, y;'
+ print ' const uint8_t *src_row = src + y0*src_stride;'
+ print ' %s *dst_row = dst;' % dst_native_type
+ print ' for (y = 0; y < h; ++y) {'
+ print ' const %s *src_pixel = (const %s *)(src_row + x0*%u);' % (src_native_type, src_native_type, format.stride())
+ print ' %s *dst_pixel = dst_row;' %dst_native_type
+ print ' for (x = 0; x < w; ++x) {'
+
+ names = ['']*4
+ if format.colorspace == 'rgb':
+ for i in range(4):
+ swizzle = format.out_swizzle[i]
+ if swizzle < 4:
+ names[swizzle] += 'rgba'[i]
+ elif format.colorspace == 'zs':
+ swizzle = format.out_swizzle[0]
+ if swizzle < 4:
+ names[swizzle] = 'z'
+ else:
+ assert False
+ else:
+ assert False
+
+ if format.layout == ARITH:
+ print ' %s pixel = *src_pixel++;' % src_native_type
+ shift = 0;
+ for i in range(4):
+ src_type = format.in_types[i]
+ width = src_type.size
+ if names[i]:
+ value = 'pixel'
+ mask = (1 << width) - 1
+ if shift:
+ value = '(%s >> %u)' % (value, shift)
+ if shift + width < format.block_size():
+ value = '(%s & 0x%x)' % (value, mask)
+ value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ print ' %s %s = %s;' % (dst_native_type, names[i], value)
+ shift += width
+ elif format.layout == ARRAY:
+ for i in range(4):
+ src_type = format.in_types[i]
+ if names[i]:
+ value = '(*src_pixel++)'
+ value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ print ' %s %s = %s;' % (dst_native_type, names[i], value)
+ else:
+ assert False
+
+ for i in range(4):
+ if format.colorspace == 'rgb':
+ swizzle = format.out_swizzle[i]
+ if swizzle < 4:
+ value = names[swizzle]
+ elif swizzle == SWIZZLE_0:
+ value = '0'
+ elif swizzle == SWIZZLE_1:
+ value = '1'
+ else:
+ assert False
+ elif format.colorspace == 'zs':
+ if i < 3:
+ value = 'z'
+ else:
+ value = '1'
+ else:
+ assert False
+ print ' *dst_pixel++ = %s; /* %s */' % (value, 'rgba'[i])
+
+ print ' }'
+ print ' src_row += src_stride;'
+ print ' dst_row += dst_stride/sizeof(%s);' % dst_native_type
+ print ' }'
+ print '}'
+ print
+
+
+def generate_format_write(format, src_type, src_native_type, src_suffix):
+ '''Generate the function to write pixels to a particular format'''
+
+ name = short_name(format)
+
+ dst_native_type = native_type(format)
+
+ print 'static void'
+ print 'util_format_%s_write_%s(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, src_suffix, src_native_type)
+ print '{'
+ print ' unsigned x, y;'
+ print ' uint8_t *dst_row = dst + y0*dst_stride;'
+ print ' const %s *src_row = src;' % src_native_type
+ print ' for (y = 0; y < h; ++y) {'
+ print ' %s *dst_pixel = (%s *)(dst_row + x0*%u);' % (dst_native_type, dst_native_type, format.stride())
+ print ' const %s *src_pixel = src_row;' %src_native_type
+ print ' for (x = 0; x < w; ++x) {'
+
+ inv_swizzle = [None]*4
+ if format.colorspace == 'rgb':
+ for i in range(4):
+ swizzle = format.out_swizzle[i]
+ if swizzle < 4:
+ inv_swizzle[swizzle] = i
+ elif format.colorspace == 'zs':
+ swizzle = format.out_swizzle[0]
+ if swizzle < 4:
+ inv_swizzle[swizzle] = 0
+ else:
+ assert False
+
+ if format.layout == ARITH:
+ print ' %s pixel = 0;' % dst_native_type
+ shift = 0;
+ for i in range(4):
+ dst_type = format.in_types[i]
+ width = dst_type.size
+ if inv_swizzle[i] is not None:
+ value = 'src_pixel[%u]' % inv_swizzle[i]
+ value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ if shift:
+ value = '(%s << %u)' % (value, shift)
+ print ' pixel |= %s;' % value
+ shift += width
+ print ' *dst_pixel++ = pixel;'
+ elif format.layout == ARRAY:
+ for i in range(4):
+ dst_type = format.in_types[i]
+ if inv_swizzle[i] is not None:
+ value = 'src_pixel[%u]' % inv_swizzle[i]
+ value = conversion_expr(src_type, dst_type, dst_native_type, value)
+ print ' *dst_pixel++ = %s;' % value
+ else:
+ assert False
+ print ' src_pixel += 4;'
+
+ print ' }'
+ print ' dst_row += dst_stride;'
+ print ' src_row += src_stride/sizeof(%s);' % src_native_type
+ print ' }'
+ print '}'
+ print
+
+
+def generate_read(formats, dst_type, dst_native_type, dst_suffix):
+ '''Generate the dispatch function to read pixels from any format'''
+
+ for format in formats:
+ if is_format_supported(format):
+ generate_format_read(format, dst_type, dst_native_type, dst_suffix)
+
+ print 'void'
+ print 'util_format_read_%s(enum pipe_format format, %s *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (dst_suffix, dst_native_type)
+ print '{'
+ print ' void (*func)(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % dst_native_type
+ print ' switch(format) {'
+ for format in formats:
+ if is_format_supported(format):
+ print ' case %s:' % format.name
+ print ' func = &util_format_%s_read_%s;' % (short_name(format), dst_suffix)
+ print ' break;'
+ print ' default:'
+ print ' debug_printf("unsupported format\\n");'
+ print ' return;'
+ print ' }'
+ print ' func(dst, dst_stride, (const uint8_t *)src, src_stride, x, y, w, h);'
+ print '}'
+ print
+
+
+def generate_write(formats, src_type, src_native_type, src_suffix):
+ '''Generate the dispatch function to write pixels to any format'''
+
+ for format in formats:
+ if is_format_supported(format):
+ generate_format_write(format, src_type, src_native_type, src_suffix)
+
+ print 'void'
+ print 'util_format_write_%s(enum pipe_format format, const %s *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (src_suffix, src_native_type)
+
+ print '{'
+ print ' void (*func)(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % src_native_type
+ print ' switch(format) {'
+ for format in formats:
+ if is_format_supported(format):
+ print ' case %s:' % format.name
+ print ' func = &util_format_%s_write_%s;' % (short_name(format), src_suffix)
+ print ' break;'
+ print ' default:'
+ print ' debug_printf("unsupported format\\n");'
+ print ' return;'
+ print ' }'
+ print ' func(src, src_stride, (uint8_t *)dst, dst_stride, x, y, w, h);'
+ print '}'
+ print
+
+
+def main():
+ formats = []
+ for arg in sys.argv[1:]:
+ formats.extend(parse(arg))
+
+ print '/* This file is autogenerated by u_format_access.py from u_format.csv. Do not edit directly. */'
+ print
+ # This will print the copyright message on the top of this file
+ print __doc__.strip()
+ print
+ print '#include "pipe/p_compiler.h"'
+ print '#include "u_format.h"'
+ print '#include "u_math.h"'
+ print
+
+ generate_clamp()
+
+ type = Type(FLOAT, False, 32)
+ native_type = 'float'
+ suffix = '4f'
+
+ generate_read(formats, type, native_type, suffix)
+ generate_write(formats, type, native_type, suffix)
+
+ type = Type(UNSIGNED, True, 8)
+ native_type = 'uint8_t'
+ suffix = '4ub'
+
+ generate_read(formats, type, native_type, suffix)
+ generate_write(formats, type, native_type, suffix)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/auxiliary/util/u_format_parse.py b/src/gallium/auxiliary/util/u_format_parse.py
new file mode 100755
index 0000000000..493aff7112
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_format_parse.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+
+'''
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+'''
+
+
+import sys
+
+
+VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
+
+SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
+
+ARITH = 'arith'
+ARRAY = 'array'
+
+
+class Type:
+ '''Describe the type of a color channel.'''
+
+ def __init__(self, kind, norm, size):
+ self.kind = kind
+ self.norm = norm
+ self.size = size
+ self.sign = kind in (SIGNED, FIXED, FLOAT)
+
+ def __str__(self):
+ s = str(self.kind)
+ if self.norm:
+ s += 'n'
+ s += str(self.size)
+ return s
+
+ def __eq__(self, other):
+ return self.kind == other.kind and self.norm == other.norm and self.size == other.size
+
+
+class Format:
+ '''Describe a pixel format.'''
+
+ def __init__(self, name, layout, block_width, block_height, in_types, out_swizzle, colorspace):
+ self.name = name
+ self.layout = layout
+ self.block_width = block_width
+ self.block_height = block_height
+ self.in_types = in_types
+ self.out_swizzle = out_swizzle
+ self.name = name
+ self.colorspace = colorspace
+
+ def __str__(self):
+ return self.name
+
+ def block_size(self):
+ size = 0
+ for type in self.in_types:
+ size += type.size
+ return size
+
+ def stride(self):
+ return self.block_size()/8
+
+
+_kind_parse_map = {
+ '': VOID,
+ 'x': VOID,
+ 'u': UNSIGNED,
+ 's': SIGNED,
+ 'h': FIXED,
+ 'f': FLOAT,
+}
+
+_swizzle_parse_map = {
+ 'x': SWIZZLE_X,
+ 'y': SWIZZLE_Y,
+ 'z': SWIZZLE_Z,
+ 'w': SWIZZLE_W,
+ '0': SWIZZLE_0,
+ '1': SWIZZLE_1,
+ '_': SWIZZLE_NONE,
+}
+
+def parse(filename):
+ '''Parse the format descrition in CSV format in terms of the
+ Type and Format classes above.'''
+
+ stream = open(filename)
+ formats = []
+ for line in stream:
+ line = line.rstrip()
+ fields = [field.strip() for field in line.split(',')]
+ name = fields[0]
+ layout = fields[1]
+ block_width, block_height = map(int, fields[2:4])
+ in_types = []
+ for field in fields[4:8]:
+ if field:
+ kind = _kind_parse_map[field[0]]
+ if field[1] == 'n':
+ norm = True
+ size = int(field[2:])
+ else:
+ norm = False
+ size = int(field[1:])
+ else:
+ kind = VOID
+ norm = False
+ size = 0
+ in_type = Type(kind, norm, size)
+ in_types.append(in_type)
+ out_swizzle = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
+ colorspace = fields[9]
+ formats.append(Format(name, layout, block_width, block_height, in_types, out_swizzle, colorspace))
+ return formats
+
diff --git a/src/gallium/auxiliary/util/u_format_table.py b/src/gallium/auxiliary/util/u_format_table.py
new file mode 100755
index 0000000000..8834568e8e
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_format_table.py
@@ -0,0 +1,144 @@
+#!/usr/bin/env python
+
+'''
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+'''
+
+
+import sys
+
+from u_format_parse import *
+
+
+def layout_map(layout):
+ return 'UTIL_FORMAT_LAYOUT_' + str(layout).upper()
+
+
+def colorspace_map(colorspace):
+ return 'UTIL_FORMAT_COLORSPACE_' + str(colorspace).upper()
+
+
+colorspace_channels_map = {
+ 'rgb': 'rgba',
+ 'rgba': 'rgba',
+ 'zs': 'zs',
+ 'yuv': ['y1', 'y2', 'u', 'v'],
+ 'dxt': []
+}
+
+
+kind_map = {
+ VOID: "UTIL_FORMAT_TYPE_VOID",
+ UNSIGNED: "UTIL_FORMAT_TYPE_UNSIGNED",
+ SIGNED: "UTIL_FORMAT_TYPE_SIGNED",
+ FIXED: "UTIL_FORMAT_TYPE_FIXED",
+ FLOAT: "UTIL_FORMAT_TYPE_FLOAT",
+}
+
+
+def bool_map(value):
+ if value:
+ return "TRUE"
+ else:
+ return "FALSE"
+
+
+swizzle_map = {
+ SWIZZLE_X: "UTIL_FORMAT_SWIZZLE_X",
+ SWIZZLE_Y: "UTIL_FORMAT_SWIZZLE_Y",
+ SWIZZLE_Z: "UTIL_FORMAT_SWIZZLE_Z",
+ SWIZZLE_W: "UTIL_FORMAT_SWIZZLE_W",
+ SWIZZLE_0: "UTIL_FORMAT_SWIZZLE_0",
+ SWIZZLE_1: "UTIL_FORMAT_SWIZZLE_1",
+ SWIZZLE_NONE: "UTIL_FORMAT_SWIZZLE_NONE",
+}
+
+
+def write_format_table(formats):
+ print '/* This file is autogenerated by u_format_table.py from u_format.csv. Do not edit directly. */'
+ print
+ # This will print the copyright message on the top of this file
+ print __doc__.strip()
+ print
+ print '#include "u_format.h"'
+ print
+ print 'const struct util_format_description'
+ print 'util_format_description_table[] = '
+ print "{"
+ for format in formats:
+ print " {"
+ print " %s," % (format.name,)
+ print " \"%s\"," % (format.name,)
+ print " {%u, %u, %u}, /* block */" % (format.block_width, format.block_height, format.block_size())
+ print " %s," % (layout_map(format.layout),)
+ print " {"
+ for i in range(4):
+ type = format.in_types[i]
+ if i < 3:
+ sep = ","
+ else:
+ sep = ""
+ print " {%s, %s, %u}%s /* %s */" % (kind_map[type.kind], bool_map(type.norm), type.size, sep, "xyzw"[i])
+ print " },"
+ print " {"
+ for i in range(4):
+ swizzle = format.out_swizzle[i]
+ if i < 3:
+ sep = ","
+ else:
+ sep = ""
+ try:
+ comment = layout_channels_map[format.layout][i]
+ except:
+ comment = 'ignored'
+ print " %s%s /* %s */" % (swizzle_map[swizzle], sep, comment)
+ print " },"
+ print " %s," % (colorspace_map(format.colorspace),)
+ print " },"
+ print " {"
+ print " PIPE_FORMAT_NONE,"
+ print " \"PIPE_FORMAT_NONE\","
+ print " {0, 0, 0},"
+ print " 0,"
+ print " {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},"
+ print " {0, 0, 0, 0},"
+ print " 0"
+ print " },"
+ print "};"
+
+
+def main():
+
+ formats = []
+ for arg in sys.argv[1:]:
+ formats.extend(parse(arg))
+ write_format_table(formats)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
new file mode 100644
index 0000000000..f06c0e463d
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -0,0 +1,1613 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2008 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Mipmap generation utility
+ *
+ * @author Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "util/u_debug.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_state.h"
+
+#include "util/u_memory.h"
+#include "util/u_draw_quad.h"
+#include "util/u_gen_mipmap.h"
+#include "util/u_simple_shaders.h"
+
+#include "cso_cache/cso_context.h"
+
+
+struct gen_mipmap_state
+{
+ struct pipe_context *pipe;
+ struct cso_context *cso;
+
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state sampler;
+
+ void *vs;
+ void *fs;
+
+ struct pipe_buffer *vbuf; /**< quad vertices */
+ unsigned vbuf_slot;
+
+ float vertices[4][2][4]; /**< vertex/texcoords for quad */
+};
+
+
+
+enum dtype
+{
+ DTYPE_UBYTE,
+ DTYPE_UBYTE_3_3_2,
+ DTYPE_USHORT,
+ DTYPE_USHORT_4_4_4_4,
+ DTYPE_USHORT_5_6_5,
+ DTYPE_USHORT_1_5_5_5_REV,
+ DTYPE_UINT,
+ DTYPE_FLOAT,
+ DTYPE_HALF_FLOAT
+};
+
+
+typedef ushort half_float;
+
+
+static half_float
+float_to_half(float f)
+{
+ /* XXX fix this */
+ return 0;
+}
+
+static float
+half_to_float(half_float h)
+{
+ /* XXX fix this */
+ return 0.0f;
+}
+
+
+
+
+/**
+ * \name Support macros for do_row and do_row_3d
+ *
+ * The macro madness is here for two reasons. First, it compacts the code
+ * slightly. Second, it makes it much easier to adjust the specifics of the
+ * filter to tune the rounding characteristics.
+ */
+/*@{*/
+#define DECLARE_ROW_POINTERS(t, e) \
+ const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
+ const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
+ const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
+ const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
+ t(*dst)[e] = (t(*)[e]) dstRow
+
+#define DECLARE_ROW_POINTERS0(t) \
+ const t *rowA = (const t *) srcRowA; \
+ const t *rowB = (const t *) srcRowB; \
+ const t *rowC = (const t *) srcRowC; \
+ const t *rowD = (const t *) srcRowD; \
+ t *dst = (t *) dstRow
+
+#define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
+ ((unsigned) Aj + (unsigned) Ak \
+ + (unsigned) Bj + (unsigned) Bk \
+ + (unsigned) Cj + (unsigned) Ck \
+ + (unsigned) Dj + (unsigned) Dk \
+ + 4) >> 3
+
+#define FILTER_3D(e) \
+ do { \
+ dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
+ rowB[j][e], rowB[k][e], \
+ rowC[j][e], rowC[k][e], \
+ rowD[j][e], rowD[k][e]); \
+ } while(0)
+
+#define FILTER_F_3D(e) \
+ do { \
+ dst[i][e] = (rowA[j][e] + rowA[k][e] \
+ + rowB[j][e] + rowB[k][e] \
+ + rowC[j][e] + rowC[k][e] \
+ + rowD[j][e] + rowD[k][e]) * 0.125F; \
+ } while(0)
+
+#define FILTER_HF_3D(e) \
+ do { \
+ const float aj = half_to_float(rowA[j][e]); \
+ const float ak = half_to_float(rowA[k][e]); \
+ const float bj = half_to_float(rowB[j][e]); \
+ const float bk = half_to_float(rowB[k][e]); \
+ const float cj = half_to_float(rowC[j][e]); \
+ const float ck = half_to_float(rowC[k][e]); \
+ const float dj = half_to_float(rowD[j][e]); \
+ const float dk = half_to_float(rowD[k][e]); \
+ dst[i][e] = float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
+ * 0.125F); \
+ } while(0)
+/*@}*/
+
+
+/**
+ * Average together two rows of a source image to produce a single new
+ * row in the dest image. It's legal for the two source rows to point
+ * to the same data. The source width must be equal to either the
+ * dest width or two times the dest width.
+ * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
+ * \param comps number of components per pixel (1..4)
+ */
+static void
+do_row(enum dtype datatype, uint comps, int srcWidth,
+ const void *srcRowA, const void *srcRowB,
+ int dstWidth, void *dstRow)
+{
+ const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
+ const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
+
+ assert(comps >= 1);
+ assert(comps <= 4);
+
+ /* This assertion is no longer valid with non-power-of-2 textures
+ assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
+ */
+
+ if (datatype == DTYPE_UBYTE && comps == 4) {
+ uint i, j, k;
+ const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA;
+ const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB;
+ ubyte(*dst)[4] = (ubyte(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
+ }
+ }
+ else if (datatype == DTYPE_UBYTE && comps == 3) {
+ uint i, j, k;
+ const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA;
+ const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB;
+ ubyte(*dst)[3] = (ubyte(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ }
+ }
+ else if (datatype == DTYPE_UBYTE && comps == 2) {
+ uint i, j, k;
+ const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA;
+ const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB;
+ ubyte(*dst)[2] = (ubyte(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
+ }
+ }
+ else if (datatype == DTYPE_UBYTE && comps == 1) {
+ uint i, j, k;
+ const ubyte *rowA = (const ubyte *) srcRowA;
+ const ubyte *rowB = (const ubyte *) srcRowB;
+ ubyte *dst = (ubyte *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
+ }
+ }
+
+ else if (datatype == DTYPE_USHORT && comps == 4) {
+ uint i, j, k;
+ const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA;
+ const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB;
+ ushort(*dst)[4] = (ushort(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
+ }
+ }
+ else if (datatype == DTYPE_USHORT && comps == 3) {
+ uint i, j, k;
+ const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA;
+ const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB;
+ ushort(*dst)[3] = (ushort(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ }
+ }
+ else if (datatype == DTYPE_USHORT && comps == 2) {
+ uint i, j, k;
+ const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA;
+ const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB;
+ ushort(*dst)[2] = (ushort(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ }
+ }
+ else if (datatype == DTYPE_USHORT && comps == 1) {
+ uint i, j, k;
+ const ushort *rowA = (const ushort *) srcRowA;
+ const ushort *rowB = (const ushort *) srcRowB;
+ ushort *dst = (ushort *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
+ }
+ }
+
+ else if (datatype == DTYPE_FLOAT && comps == 4) {
+ uint i, j, k;
+ const float(*rowA)[4] = (const float(*)[4]) srcRowA;
+ const float(*rowB)[4] = (const float(*)[4]) srcRowB;
+ float(*dst)[4] = (float(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] +
+ rowB[j][0] + rowB[k][0]) * 0.25F;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] +
+ rowB[j][1] + rowB[k][1]) * 0.25F;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] +
+ rowB[j][2] + rowB[k][2]) * 0.25F;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] +
+ rowB[j][3] + rowB[k][3]) * 0.25F;
+ }
+ }
+ else if (datatype == DTYPE_FLOAT && comps == 3) {
+ uint i, j, k;
+ const float(*rowA)[3] = (const float(*)[3]) srcRowA;
+ const float(*rowB)[3] = (const float(*)[3]) srcRowB;
+ float(*dst)[3] = (float(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] +
+ rowB[j][0] + rowB[k][0]) * 0.25F;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] +
+ rowB[j][1] + rowB[k][1]) * 0.25F;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] +
+ rowB[j][2] + rowB[k][2]) * 0.25F;
+ }
+ }
+ else if (datatype == DTYPE_FLOAT && comps == 2) {
+ uint i, j, k;
+ const float(*rowA)[2] = (const float(*)[2]) srcRowA;
+ const float(*rowB)[2] = (const float(*)[2]) srcRowB;
+ float(*dst)[2] = (float(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] +
+ rowB[j][0] + rowB[k][0]) * 0.25F;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] +
+ rowB[j][1] + rowB[k][1]) * 0.25F;
+ }
+ }
+ else if (datatype == DTYPE_FLOAT && comps == 1) {
+ uint i, j, k;
+ const float *rowA = (const float *) srcRowA;
+ const float *rowB = (const float *) srcRowB;
+ float *dst = (float *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
+ }
+ }
+
+#if 0
+ else if (datatype == HALF_DTYPE_FLOAT && comps == 4) {
+ uint i, j, k, comp;
+ const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
+ const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
+ half_float(*dst)[4] = (half_float(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ for (comp = 0; comp < 4; comp++) {
+ float aj, ak, bj, bk;
+ aj = half_to_float(rowA[j][comp]);
+ ak = half_to_float(rowA[k][comp]);
+ bj = half_to_float(rowB[j][comp]);
+ bk = half_to_float(rowB[k][comp]);
+ dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+ }
+ else if (datatype == DTYPE_HALF_FLOAT && comps == 3) {
+ uint i, j, k, comp;
+ const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA;
+ const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB;
+ half_float(*dst)[3] = (half_float(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ for (comp = 0; comp < 3; comp++) {
+ float aj, ak, bj, bk;
+ aj = half_to_float(rowA[j][comp]);
+ ak = half_to_float(rowA[k][comp]);
+ bj = half_to_float(rowB[j][comp]);
+ bk = half_to_float(rowB[k][comp]);
+ dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+ }
+ else if (datatype == DTYPE_HALF_FLOAT && comps == 2) {
+ uint i, j, k, comp;
+ const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA;
+ const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB;
+ half_float(*dst)[2] = (half_float(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ for (comp = 0; comp < 2; comp++) {
+ float aj, ak, bj, bk;
+ aj = half_to_float(rowA[j][comp]);
+ ak = half_to_float(rowA[k][comp]);
+ bj = half_to_float(rowB[j][comp]);
+ bk = half_to_float(rowB[k][comp]);
+ dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+ }
+ else if (datatype == DTYPE_HALF_FLOAT && comps == 1) {
+ uint i, j, k;
+ const half_float *rowA = (const half_float *) srcRowA;
+ const half_float *rowB = (const half_float *) srcRowB;
+ half_float *dst = (half_float *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ float aj, ak, bj, bk;
+ aj = half_to_float(rowA[j]);
+ ak = half_to_float(rowA[k]);
+ bj = half_to_float(rowB[j]);
+ bk = half_to_float(rowB[k]);
+ dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+#endif
+
+ else if (datatype == DTYPE_UINT && comps == 1) {
+ uint i, j, k;
+ const uint *rowA = (const uint *) srcRowA;
+ const uint *rowB = (const uint *) srcRowB;
+ uint *dst = (uint *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
+ }
+ }
+
+ else if (datatype == DTYPE_USHORT_5_6_5 && comps == 3) {
+ uint i, j, k;
+ const ushort *rowA = (const ushort *) srcRowA;
+ const ushort *rowB = (const ushort *) srcRowB;
+ ushort *dst = (ushort *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0x1f;
+ const int rowAr1 = rowA[k] & 0x1f;
+ const int rowBr0 = rowB[j] & 0x1f;
+ const int rowBr1 = rowB[k] & 0x1f;
+ const int rowAg0 = (rowA[j] >> 5) & 0x3f;
+ const int rowAg1 = (rowA[k] >> 5) & 0x3f;
+ const int rowBg0 = (rowB[j] >> 5) & 0x3f;
+ const int rowBg1 = (rowB[k] >> 5) & 0x3f;
+ const int rowAb0 = (rowA[j] >> 11) & 0x1f;
+ const int rowAb1 = (rowA[k] >> 11) & 0x1f;
+ const int rowBb0 = (rowB[j] >> 11) & 0x1f;
+ const int rowBb1 = (rowB[k] >> 11) & 0x1f;
+ const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ dst[i] = (blue << 11) | (green << 5) | red;
+ }
+ }
+ else if (datatype == DTYPE_USHORT_4_4_4_4 && comps == 4) {
+ uint i, j, k;
+ const ushort *rowA = (const ushort *) srcRowA;
+ const ushort *rowB = (const ushort *) srcRowB;
+ ushort *dst = (ushort *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0xf;
+ const int rowAr1 = rowA[k] & 0xf;
+ const int rowBr0 = rowB[j] & 0xf;
+ const int rowBr1 = rowB[k] & 0xf;
+ const int rowAg0 = (rowA[j] >> 4) & 0xf;
+ const int rowAg1 = (rowA[k] >> 4) & 0xf;
+ const int rowBg0 = (rowB[j] >> 4) & 0xf;
+ const int rowBg1 = (rowB[k] >> 4) & 0xf;
+ const int rowAb0 = (rowA[j] >> 8) & 0xf;
+ const int rowAb1 = (rowA[k] >> 8) & 0xf;
+ const int rowBb0 = (rowB[j] >> 8) & 0xf;
+ const int rowBb1 = (rowB[k] >> 8) & 0xf;
+ const int rowAa0 = (rowA[j] >> 12) & 0xf;
+ const int rowAa1 = (rowA[k] >> 12) & 0xf;
+ const int rowBa0 = (rowB[j] >> 12) & 0xf;
+ const int rowBa1 = (rowB[k] >> 12) & 0xf;
+ const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
+ dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
+ }
+ }
+ else if (datatype == DTYPE_USHORT_1_5_5_5_REV && comps == 4) {
+ uint i, j, k;
+ const ushort *rowA = (const ushort *) srcRowA;
+ const ushort *rowB = (const ushort *) srcRowB;
+ ushort *dst = (ushort *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0x1f;
+ const int rowAr1 = rowA[k] & 0x1f;
+ const int rowBr0 = rowB[j] & 0x1f;
+ const int rowBr1 = rowB[k] & 0x1f;
+ const int rowAg0 = (rowA[j] >> 5) & 0x1f;
+ const int rowAg1 = (rowA[k] >> 5) & 0x1f;
+ const int rowBg0 = (rowB[j] >> 5) & 0x1f;
+ const int rowBg1 = (rowB[k] >> 5) & 0x1f;
+ const int rowAb0 = (rowA[j] >> 10) & 0x1f;
+ const int rowAb1 = (rowA[k] >> 10) & 0x1f;
+ const int rowBb0 = (rowB[j] >> 10) & 0x1f;
+ const int rowBb1 = (rowB[k] >> 10) & 0x1f;
+ const int rowAa0 = (rowA[j] >> 15) & 0x1;
+ const int rowAa1 = (rowA[k] >> 15) & 0x1;
+ const int rowBa0 = (rowB[j] >> 15) & 0x1;
+ const int rowBa1 = (rowB[k] >> 15) & 0x1;
+ const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
+ dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
+ }
+ }
+ else if (datatype == DTYPE_UBYTE_3_3_2 && comps == 3) {
+ uint i, j, k;
+ const ubyte *rowA = (const ubyte *) srcRowA;
+ const ubyte *rowB = (const ubyte *) srcRowB;
+ ubyte *dst = (ubyte *) dstRow;
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0x3;
+ const int rowAr1 = rowA[k] & 0x3;
+ const int rowBr0 = rowB[j] & 0x3;
+ const int rowBr1 = rowB[k] & 0x3;
+ const int rowAg0 = (rowA[j] >> 2) & 0x7;
+ const int rowAg1 = (rowA[k] >> 2) & 0x7;
+ const int rowBg0 = (rowB[j] >> 2) & 0x7;
+ const int rowBg1 = (rowB[k] >> 2) & 0x7;
+ const int rowAb0 = (rowA[j] >> 5) & 0x7;
+ const int rowAb1 = (rowA[k] >> 5) & 0x7;
+ const int rowBb0 = (rowB[j] >> 5) & 0x7;
+ const int rowBb1 = (rowB[k] >> 5) & 0x7;
+ const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ dst[i] = (blue << 5) | (green << 2) | red;
+ }
+ }
+ else {
+ debug_printf("bad format in do_row()");
+ }
+}
+
+
+/**
+ * Average together four rows of a source image to produce a single new
+ * row in the dest image. It's legal for the two source rows to point
+ * to the same data. The source width must be equal to either the
+ * dest width or two times the dest width.
+ *
+ * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
+ * \c GL_FLOAT, etc.
+ * \param comps number of components per pixel (1..4)
+ * \param srcWidth Width of a row in the source data
+ * \param srcRowA Pointer to one of the rows of source data
+ * \param srcRowB Pointer to one of the rows of source data
+ * \param srcRowC Pointer to one of the rows of source data
+ * \param srcRowD Pointer to one of the rows of source data
+ * \param dstWidth Width of a row in the destination data
+ * \param srcRowA Pointer to the row of destination data
+ */
+static void
+do_row_3D(enum dtype datatype, uint comps, int srcWidth,
+ const void *srcRowA, const void *srcRowB,
+ const void *srcRowC, const void *srcRowD,
+ int dstWidth, void *dstRow)
+{
+ const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
+ const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
+ uint i, j, k;
+
+ assert(comps >= 1);
+ assert(comps <= 4);
+
+ if ((datatype == DTYPE_UBYTE) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(ubyte, 4);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ FILTER_3D(2);
+ FILTER_3D(3);
+ }
+ }
+ else if ((datatype == DTYPE_UBYTE) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(ubyte, 3);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ FILTER_3D(2);
+ }
+ }
+ else if ((datatype == DTYPE_UBYTE) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(ubyte, 2);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ }
+ }
+ else if ((datatype == DTYPE_UBYTE) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(ubyte, 1);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ }
+ }
+ else if ((datatype == DTYPE_USHORT) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(ushort, 4);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ FILTER_3D(2);
+ FILTER_3D(3);
+ }
+ }
+ else if ((datatype == DTYPE_USHORT) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(ushort, 3);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ FILTER_3D(2);
+ }
+ }
+ else if ((datatype == DTYPE_USHORT) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(ushort, 2);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ }
+ }
+ else if ((datatype == DTYPE_USHORT) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(ushort, 1);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ }
+ }
+ else if ((datatype == DTYPE_FLOAT) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(float, 4);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_F_3D(0);
+ FILTER_F_3D(1);
+ FILTER_F_3D(2);
+ FILTER_F_3D(3);
+ }
+ }
+ else if ((datatype == DTYPE_FLOAT) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(float, 3);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_F_3D(0);
+ FILTER_F_3D(1);
+ FILTER_F_3D(2);
+ }
+ }
+ else if ((datatype == DTYPE_FLOAT) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(float, 2);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_F_3D(0);
+ FILTER_F_3D(1);
+ }
+ }
+ else if ((datatype == DTYPE_FLOAT) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(float, 1);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_F_3D(0);
+ }
+ }
+ else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(half_float, 4);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_HF_3D(0);
+ FILTER_HF_3D(1);
+ FILTER_HF_3D(2);
+ FILTER_HF_3D(3);
+ }
+ }
+ else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(half_float, 4);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_HF_3D(0);
+ FILTER_HF_3D(1);
+ FILTER_HF_3D(2);
+ }
+ }
+ else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(half_float, 4);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_HF_3D(0);
+ FILTER_HF_3D(1);
+ }
+ }
+ else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(half_float, 4);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_HF_3D(0);
+ }
+ }
+ else if ((datatype == DTYPE_UINT) && (comps == 1)) {
+ const uint *rowA = (const uint *) srcRowA;
+ const uint *rowB = (const uint *) srcRowB;
+ const uint *rowC = (const uint *) srcRowC;
+ const uint *rowD = (const uint *) srcRowD;
+ float *dst = (float *) dstRow;
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
+ + ((uint64_t) rowB[j] + (uint64_t) rowB[k])
+ + ((uint64_t) rowC[j] + (uint64_t) rowC[k])
+ + ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
+ dst[i] = (float)((double) tmp * 0.125);
+ }
+ }
+ else if ((datatype == DTYPE_USHORT_5_6_5) && (comps == 3)) {
+ DECLARE_ROW_POINTERS0(ushort);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0x1f;
+ const int rowAr1 = rowA[k] & 0x1f;
+ const int rowBr0 = rowB[j] & 0x1f;
+ const int rowBr1 = rowB[k] & 0x1f;
+ const int rowCr0 = rowC[j] & 0x1f;
+ const int rowCr1 = rowC[k] & 0x1f;
+ const int rowDr0 = rowD[j] & 0x1f;
+ const int rowDr1 = rowD[k] & 0x1f;
+ const int rowAg0 = (rowA[j] >> 5) & 0x3f;
+ const int rowAg1 = (rowA[k] >> 5) & 0x3f;
+ const int rowBg0 = (rowB[j] >> 5) & 0x3f;
+ const int rowBg1 = (rowB[k] >> 5) & 0x3f;
+ const int rowCg0 = (rowC[j] >> 5) & 0x3f;
+ const int rowCg1 = (rowC[k] >> 5) & 0x3f;
+ const int rowDg0 = (rowD[j] >> 5) & 0x3f;
+ const int rowDg1 = (rowD[k] >> 5) & 0x3f;
+ const int rowAb0 = (rowA[j] >> 11) & 0x1f;
+ const int rowAb1 = (rowA[k] >> 11) & 0x1f;
+ const int rowBb0 = (rowB[j] >> 11) & 0x1f;
+ const int rowBb1 = (rowB[k] >> 11) & 0x1f;
+ const int rowCb0 = (rowC[j] >> 11) & 0x1f;
+ const int rowCb1 = (rowC[k] >> 11) & 0x1f;
+ const int rowDb0 = (rowD[j] >> 11) & 0x1f;
+ const int rowDb1 = (rowD[k] >> 11) & 0x1f;
+ const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
+ rowCr0, rowCr1, rowDr0, rowDr1);
+ const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
+ rowCg0, rowCg1, rowDg0, rowDg1);
+ const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
+ rowCb0, rowCb1, rowDb0, rowDb1);
+ dst[i] = (b << 11) | (g << 5) | r;
+ }
+ }
+ else if ((datatype == DTYPE_USHORT_4_4_4_4) && (comps == 4)) {
+ DECLARE_ROW_POINTERS0(ushort);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0xf;
+ const int rowAr1 = rowA[k] & 0xf;
+ const int rowBr0 = rowB[j] & 0xf;
+ const int rowBr1 = rowB[k] & 0xf;
+ const int rowCr0 = rowC[j] & 0xf;
+ const int rowCr1 = rowC[k] & 0xf;
+ const int rowDr0 = rowD[j] & 0xf;
+ const int rowDr1 = rowD[k] & 0xf;
+ const int rowAg0 = (rowA[j] >> 4) & 0xf;
+ const int rowAg1 = (rowA[k] >> 4) & 0xf;
+ const int rowBg0 = (rowB[j] >> 4) & 0xf;
+ const int rowBg1 = (rowB[k] >> 4) & 0xf;
+ const int rowCg0 = (rowC[j] >> 4) & 0xf;
+ const int rowCg1 = (rowC[k] >> 4) & 0xf;
+ const int rowDg0 = (rowD[j] >> 4) & 0xf;
+ const int rowDg1 = (rowD[k] >> 4) & 0xf;
+ const int rowAb0 = (rowA[j] >> 8) & 0xf;
+ const int rowAb1 = (rowA[k] >> 8) & 0xf;
+ const int rowBb0 = (rowB[j] >> 8) & 0xf;
+ const int rowBb1 = (rowB[k] >> 8) & 0xf;
+ const int rowCb0 = (rowC[j] >> 8) & 0xf;
+ const int rowCb1 = (rowC[k] >> 8) & 0xf;
+ const int rowDb0 = (rowD[j] >> 8) & 0xf;
+ const int rowDb1 = (rowD[k] >> 8) & 0xf;
+ const int rowAa0 = (rowA[j] >> 12) & 0xf;
+ const int rowAa1 = (rowA[k] >> 12) & 0xf;
+ const int rowBa0 = (rowB[j] >> 12) & 0xf;
+ const int rowBa1 = (rowB[k] >> 12) & 0xf;
+ const int rowCa0 = (rowC[j] >> 12) & 0xf;
+ const int rowCa1 = (rowC[k] >> 12) & 0xf;
+ const int rowDa0 = (rowD[j] >> 12) & 0xf;
+ const int rowDa1 = (rowD[k] >> 12) & 0xf;
+ const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
+ rowCr0, rowCr1, rowDr0, rowDr1);
+ const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
+ rowCg0, rowCg1, rowDg0, rowDg1);
+ const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
+ rowCb0, rowCb1, rowDb0, rowDb1);
+ const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
+ rowCa0, rowCa1, rowDa0, rowDa1);
+
+ dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
+ }
+ }
+ else if ((datatype == DTYPE_USHORT_1_5_5_5_REV) && (comps == 4)) {
+ DECLARE_ROW_POINTERS0(ushort);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0x1f;
+ const int rowAr1 = rowA[k] & 0x1f;
+ const int rowBr0 = rowB[j] & 0x1f;
+ const int rowBr1 = rowB[k] & 0x1f;
+ const int rowCr0 = rowC[j] & 0x1f;
+ const int rowCr1 = rowC[k] & 0x1f;
+ const int rowDr0 = rowD[j] & 0x1f;
+ const int rowDr1 = rowD[k] & 0x1f;
+ const int rowAg0 = (rowA[j] >> 5) & 0x1f;
+ const int rowAg1 = (rowA[k] >> 5) & 0x1f;
+ const int rowBg0 = (rowB[j] >> 5) & 0x1f;
+ const int rowBg1 = (rowB[k] >> 5) & 0x1f;
+ const int rowCg0 = (rowC[j] >> 5) & 0x1f;
+ const int rowCg1 = (rowC[k] >> 5) & 0x1f;
+ const int rowDg0 = (rowD[j] >> 5) & 0x1f;
+ const int rowDg1 = (rowD[k] >> 5) & 0x1f;
+ const int rowAb0 = (rowA[j] >> 10) & 0x1f;
+ const int rowAb1 = (rowA[k] >> 10) & 0x1f;
+ const int rowBb0 = (rowB[j] >> 10) & 0x1f;
+ const int rowBb1 = (rowB[k] >> 10) & 0x1f;
+ const int rowCb0 = (rowC[j] >> 10) & 0x1f;
+ const int rowCb1 = (rowC[k] >> 10) & 0x1f;
+ const int rowDb0 = (rowD[j] >> 10) & 0x1f;
+ const int rowDb1 = (rowD[k] >> 10) & 0x1f;
+ const int rowAa0 = (rowA[j] >> 15) & 0x1;
+ const int rowAa1 = (rowA[k] >> 15) & 0x1;
+ const int rowBa0 = (rowB[j] >> 15) & 0x1;
+ const int rowBa1 = (rowB[k] >> 15) & 0x1;
+ const int rowCa0 = (rowC[j] >> 15) & 0x1;
+ const int rowCa1 = (rowC[k] >> 15) & 0x1;
+ const int rowDa0 = (rowD[j] >> 15) & 0x1;
+ const int rowDa1 = (rowD[k] >> 15) & 0x1;
+ const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
+ rowCr0, rowCr1, rowDr0, rowDr1);
+ const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
+ rowCg0, rowCg1, rowDg0, rowDg1);
+ const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
+ rowCb0, rowCb1, rowDb0, rowDb1);
+ const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
+ rowCa0, rowCa1, rowDa0, rowDa1);
+
+ dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
+ }
+ }
+ else if ((datatype == DTYPE_UBYTE_3_3_2) && (comps == 3)) {
+ DECLARE_ROW_POINTERS0(ushort);
+
+ for (i = j = 0, k = k0; i < (uint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const int rowAr0 = rowA[j] & 0x3;
+ const int rowAr1 = rowA[k] & 0x3;
+ const int rowBr0 = rowB[j] & 0x3;
+ const int rowBr1 = rowB[k] & 0x3;
+ const int rowCr0 = rowC[j] & 0x3;
+ const int rowCr1 = rowC[k] & 0x3;
+ const int rowDr0 = rowD[j] & 0x3;
+ const int rowDr1 = rowD[k] & 0x3;
+ const int rowAg0 = (rowA[j] >> 2) & 0x7;
+ const int rowAg1 = (rowA[k] >> 2) & 0x7;
+ const int rowBg0 = (rowB[j] >> 2) & 0x7;
+ const int rowBg1 = (rowB[k] >> 2) & 0x7;
+ const int rowCg0 = (rowC[j] >> 2) & 0x7;
+ const int rowCg1 = (rowC[k] >> 2) & 0x7;
+ const int rowDg0 = (rowD[j] >> 2) & 0x7;
+ const int rowDg1 = (rowD[k] >> 2) & 0x7;
+ const int rowAb0 = (rowA[j] >> 5) & 0x7;
+ const int rowAb1 = (rowA[k] >> 5) & 0x7;
+ const int rowBb0 = (rowB[j] >> 5) & 0x7;
+ const int rowBb1 = (rowB[k] >> 5) & 0x7;
+ const int rowCb0 = (rowC[j] >> 5) & 0x7;
+ const int rowCb1 = (rowC[k] >> 5) & 0x7;
+ const int rowDb0 = (rowD[j] >> 5) & 0x7;
+ const int rowDb1 = (rowD[k] >> 5) & 0x7;
+ const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
+ rowCr0, rowCr1, rowDr0, rowDr1);
+ const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
+ rowCg0, rowCg1, rowDg0, rowDg1);
+ const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
+ rowCb0, rowCb1, rowDb0, rowDb1);
+ dst[i] = (b << 5) | (g << 2) | r;
+ }
+ }
+ else {
+ debug_printf("bad format in do_row_3D()");
+ }
+}
+
+
+
+static void
+format_to_type_comps(enum pipe_format pformat,
+ enum dtype *datatype, uint *comps)
+{
+ /* XXX I think this could be implemented in terms of the pf_*() functions */
+ switch (pformat) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_R8G8B8A8_SRGB:
+ case PIPE_FORMAT_R8G8B8X8_SRGB:
+ case PIPE_FORMAT_A8R8G8B8_SRGB:
+ case PIPE_FORMAT_X8R8G8B8_SRGB:
+ case PIPE_FORMAT_B8G8R8A8_SRGB:
+ case PIPE_FORMAT_B8G8R8X8_SRGB:
+ case PIPE_FORMAT_R8G8B8_SRGB:
+ *datatype = DTYPE_UBYTE;
+ *comps = 4;
+ return;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ *datatype = DTYPE_USHORT_1_5_5_5_REV;
+ *comps = 4;
+ return;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ *datatype = DTYPE_USHORT_4_4_4_4;
+ *comps = 4;
+ return;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ *datatype = DTYPE_USHORT_5_6_5;
+ *comps = 3;
+ return;
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_L8_SRGB:
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ *datatype = DTYPE_UBYTE;
+ *comps = 1;
+ return;
+ case PIPE_FORMAT_A8L8_UNORM:
+ case PIPE_FORMAT_A8L8_SRGB:
+ *datatype = DTYPE_UBYTE;
+ *comps = 2;
+ return;
+ default:
+ assert(0);
+ *datatype = DTYPE_UBYTE;
+ *comps = 0;
+ break;
+ }
+}
+
+
+static void
+reduce_1d(enum pipe_format pformat,
+ int srcWidth, const ubyte *srcPtr,
+ int dstWidth, ubyte *dstPtr)
+{
+ enum dtype datatype;
+ uint comps;
+
+ format_to_type_comps(pformat, &datatype, &comps);
+
+ /* we just duplicate the input row, kind of hack, saves code */
+ do_row(datatype, comps,
+ srcWidth, srcPtr, srcPtr,
+ dstWidth, dstPtr);
+}
+
+
+/**
+ * Strides are in bytes. If zero, it'll be computed as width * bpp.
+ */
+static void
+reduce_2d(enum pipe_format pformat,
+ int srcWidth, int srcHeight,
+ int srcRowStride, const ubyte *srcPtr,
+ int dstWidth, int dstHeight,
+ int dstRowStride, ubyte *dstPtr)
+{
+ enum dtype datatype;
+ uint comps;
+ const int bpt = pf_get_size(pformat);
+ const ubyte *srcA, *srcB;
+ ubyte *dst;
+ int row;
+
+ format_to_type_comps(pformat, &datatype, &comps);
+
+ if (!srcRowStride)
+ srcRowStride = bpt * srcWidth;
+
+ if (!dstRowStride)
+ dstRowStride = bpt * dstWidth;
+
+ /* Compute src and dst pointers */
+ srcA = srcPtr;
+ if (srcHeight > 1)
+ srcB = srcA + srcRowStride;
+ else
+ srcB = srcA;
+ dst = dstPtr;
+
+ for (row = 0; row < dstHeight; row++) {
+ do_row(datatype, comps,
+ srcWidth, srcA, srcB,
+ dstWidth, dst);
+ srcA += 2 * srcRowStride;
+ srcB += 2 * srcRowStride;
+ dst += dstRowStride;
+ }
+}
+
+
+static void
+reduce_3d(enum pipe_format pformat,
+ int srcWidth, int srcHeight, int srcDepth,
+ int srcRowStride, const ubyte *srcPtr,
+ int dstWidth, int dstHeight, int dstDepth,
+ int dstRowStride, ubyte *dstPtr)
+{
+ const int bpt = pf_get_size(pformat);
+ const int border = 0;
+ int img, row;
+ int bytesPerSrcImage, bytesPerDstImage;
+ int bytesPerSrcRow, bytesPerDstRow;
+ int srcImageOffset, srcRowOffset;
+ enum dtype datatype;
+ uint comps;
+
+ format_to_type_comps(pformat, &datatype, &comps);
+
+ bytesPerSrcImage = srcWidth * srcHeight * bpt;
+ bytesPerDstImage = dstWidth * dstHeight * bpt;
+
+ bytesPerSrcRow = srcWidth * bpt;
+ bytesPerDstRow = dstWidth * bpt;
+
+ /* Offset between adjacent src images to be averaged together */
+ srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
+
+ /* Offset between adjacent src rows to be averaged together */
+ srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
+
+ /*
+ * Need to average together up to 8 src pixels for each dest pixel.
+ * Break that down into 3 operations:
+ * 1. take two rows from source image and average them together.
+ * 2. take two rows from next source image and average them together.
+ * 3. take the two averaged rows and average them for the final dst row.
+ */
+
+ /*
+ _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
+ srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
+ */
+
+ for (img = 0; img < dstDepth; img++) {
+ /* first source image pointer, skipping border */
+ const ubyte *imgSrcA = srcPtr
+ + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
+ + img * (bytesPerSrcImage + srcImageOffset);
+ /* second source image pointer, skipping border */
+ const ubyte *imgSrcB = imgSrcA + srcImageOffset;
+ /* address of the dest image, skipping border */
+ ubyte *imgDst = dstPtr
+ + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
+ + img * bytesPerDstImage;
+
+ /* setup the four source row pointers and the dest row pointer */
+ const ubyte *srcImgARowA = imgSrcA;
+ const ubyte *srcImgARowB = imgSrcA + srcRowOffset;
+ const ubyte *srcImgBRowA = imgSrcB;
+ const ubyte *srcImgBRowB = imgSrcB + srcRowOffset;
+ ubyte *dstImgRow = imgDst;
+
+ for (row = 0; row < dstHeight; row++) {
+ do_row_3D(datatype, comps, srcWidth,
+ srcImgARowA, srcImgARowB,
+ srcImgBRowA, srcImgBRowB,
+ dstWidth, dstImgRow);
+
+ /* advance to next rows */
+ srcImgARowA += bytesPerSrcRow + srcRowOffset;
+ srcImgARowB += bytesPerSrcRow + srcRowOffset;
+ srcImgBRowA += bytesPerSrcRow + srcRowOffset;
+ srcImgBRowB += bytesPerSrcRow + srcRowOffset;
+ dstImgRow += bytesPerDstRow;
+ }
+ }
+}
+
+
+
+
+static void
+make_1d_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const uint zslice = 0;
+ uint dstLevel;
+
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ struct pipe_transfer *srcTrans, *dstTrans;
+ void *srcMap, *dstMap;
+
+ srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
+ PIPE_TRANSFER_READ, 0, 0,
+ pt->width[srcLevel],
+ pt->height[srcLevel]);
+ dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ pt->width[dstLevel],
+ pt->height[dstLevel]);
+
+ srcMap = (ubyte *) screen->transfer_map(screen, srcTrans);
+ dstMap = (ubyte *) screen->transfer_map(screen, dstTrans);
+
+ reduce_1d(pt->format,
+ srcTrans->width, srcMap,
+ dstTrans->width, dstMap);
+
+ screen->transfer_unmap(screen, srcTrans);
+ screen->transfer_unmap(screen, dstTrans);
+
+ screen->tex_transfer_destroy(srcTrans);
+ screen->tex_transfer_destroy(dstTrans);
+ }
+}
+
+
+static void
+make_2d_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const uint zslice = 0;
+ uint dstLevel;
+
+ assert(pt->block.width == 1);
+ assert(pt->block.height == 1);
+
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ struct pipe_transfer *srcTrans, *dstTrans;
+ ubyte *srcMap, *dstMap;
+
+ srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
+ PIPE_TRANSFER_READ, 0, 0,
+ pt->width[srcLevel],
+ pt->height[srcLevel]);
+ dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ pt->width[dstLevel],
+ pt->height[dstLevel]);
+
+ srcMap = (ubyte *) screen->transfer_map(screen, srcTrans);
+ dstMap = (ubyte *) screen->transfer_map(screen, dstTrans);
+
+ reduce_2d(pt->format,
+ srcTrans->width, srcTrans->height,
+ srcTrans->stride, srcMap,
+ dstTrans->width, dstTrans->height,
+ dstTrans->stride, dstMap);
+
+ screen->transfer_unmap(screen, srcTrans);
+ screen->transfer_unmap(screen, dstTrans);
+
+ screen->tex_transfer_destroy(srcTrans);
+ screen->tex_transfer_destroy(dstTrans);
+ }
+}
+
+
+static void
+make_3d_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel)
+{
+#if 0
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ uint dstLevel, zslice = 0;
+
+ assert(pt->block.width == 1);
+ assert(pt->block.height == 1);
+
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ struct pipe_transfer *srcTrans, *dstTrans;
+ ubyte *srcMap, *dstMap;
+
+ srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
+ PIPE_TRANSFER_READ, 0, 0,
+ pt->width[srcLevel],
+ pt->height[srcLevel]);
+ dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ pt->width[dstLevel],
+ pt->height[dstLevel]);
+
+ srcMap = (ubyte *) screen->transfer_map(screen, srcTrans);
+ dstMap = (ubyte *) screen->transfer_map(screen, dstTrans);
+
+ reduce_3d(pt->format,
+ srcTrans->width, srcTrans->height,
+ srcTrans->stride, srcMap,
+ dstTrans->width, dstTrans->height,
+ dstTrans->stride, dstMap);
+
+ screen->transfer_unmap(screen, srcTrans);
+ screen->transfer_unmap(screen, dstTrans);
+
+ screen->tex_transfer_destroy(srcTrans);
+ screen->tex_transfer_destroy(dstTrans);
+ }
+#else
+ (void) reduce_3d;
+#endif
+}
+
+
+static void
+fallback_gen_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel)
+{
+ switch (pt->target) {
+ case PIPE_TEXTURE_1D:
+ make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ break;
+ case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_CUBE:
+ make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ break;
+ case PIPE_TEXTURE_3D:
+ make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Create a mipmap generation context.
+ * The idea is to create one of these and re-use it each time we need to
+ * generate a mipmap.
+ */
+struct gen_mipmap_state *
+util_create_gen_mipmap(struct pipe_context *pipe,
+ struct cso_context *cso)
+{
+ struct gen_mipmap_state *ctx;
+ uint i;
+
+ ctx = CALLOC_STRUCT(gen_mipmap_state);
+ if (!ctx)
+ return NULL;
+
+ ctx->pipe = pipe;
+ ctx->cso = cso;
+
+ /* disabled blending/masking */
+ memset(&ctx->blend, 0, sizeof(ctx->blend));
+ ctx->blend.colormask = PIPE_MASK_RGBA;
+
+ /* no-op depth/stencil/alpha */
+ memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
+
+ /* rasterizer */
+ memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
+ ctx->rasterizer.front_winding = PIPE_WINDING_CW;
+ ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
+ ctx->rasterizer.bypass_vs_clip_and_viewport = 1;
+ ctx->rasterizer.gl_rasterization_rules = 1;
+
+ /* sampler state */
+ memset(&ctx->sampler, 0, sizeof(ctx->sampler));
+ ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ ctx->sampler.normalized_coords = 1;
+
+ /* vertex shader - still needed to specify mapping from fragment
+ * shader input semantics to vertex elements
+ */
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0 };
+ ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
+ semantic_indexes);
+ }
+
+ /* fragment shader */
+ ctx->fs = util_make_fragment_tex_shader(pipe);
+
+ /* vertex data that doesn't change */
+ for (i = 0; i < 4; i++) {
+ ctx->vertices[i][0][2] = 0.0f; /* z */
+ ctx->vertices[i][0][3] = 1.0f; /* w */
+ ctx->vertices[i][1][3] = 1.0f; /* q */
+ }
+
+ /* Note: the actual vertex buffer is allocated as needed below */
+
+ return ctx;
+}
+
+
+/**
+ * Get next "slot" of vertex space in the vertex buffer.
+ * We're allocating one large vertex buffer and using it piece by piece.
+ */
+static unsigned
+get_next_slot(struct gen_mipmap_state *ctx)
+{
+ const unsigned max_slots = 4096 / sizeof ctx->vertices;
+
+ if (ctx->vbuf_slot >= max_slots)
+ util_gen_mipmap_flush( ctx );
+
+ if (!ctx->vbuf) {
+ ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
+ 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ max_slots * sizeof ctx->vertices);
+ }
+
+ return ctx->vbuf_slot++ * sizeof ctx->vertices;
+}
+
+
+static unsigned
+set_vertex_data(struct gen_mipmap_state *ctx,
+ enum pipe_texture_target tex_target,
+ uint face, float width, float height)
+{
+ unsigned offset;
+
+ /* vert[0].position */
+ ctx->vertices[0][0][0] = 0.0f; /*x*/
+ ctx->vertices[0][0][1] = 0.0f; /*y*/
+
+ /* vert[1].position */
+ ctx->vertices[1][0][0] = width;
+ ctx->vertices[1][0][1] = 0.0f;
+
+ /* vert[2].position */
+ ctx->vertices[2][0][0] = width;
+ ctx->vertices[2][0][1] = height;
+
+ /* vert[3].position */
+ ctx->vertices[3][0][0] = 0.0f;
+ ctx->vertices[3][0][1] = height;
+
+ /* Setup vertex texcoords. This is a little tricky for cube maps. */
+ if (tex_target == PIPE_TEXTURE_CUBE) {
+ static const float st[4][2] = {
+ {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
+ };
+ float rx, ry, rz;
+ uint i;
+
+ /* loop over quad verts */
+ for (i = 0; i < 4; i++) {
+ /* Compute sc = +/-scale and tc = +/-scale.
+ * Not +/-1 to avoid cube face selection ambiguity near the edges,
+ * though that can still sometimes happen with this scale factor...
+ */
+ const float scale = 0.9999f;
+ const float sc = (2.0f * st[i][0] - 1.0f) * scale;
+ const float tc = (2.0f * st[i][1] - 1.0f) * scale;
+
+ switch (face) {
+ case PIPE_TEX_FACE_POS_X:
+ rx = 1.0f;
+ ry = -tc;
+ rz = -sc;
+ break;
+ case PIPE_TEX_FACE_NEG_X:
+ rx = -1.0f;
+ ry = -tc;
+ rz = sc;
+ break;
+ case PIPE_TEX_FACE_POS_Y:
+ rx = sc;
+ ry = 1.0f;
+ rz = tc;
+ break;
+ case PIPE_TEX_FACE_NEG_Y:
+ rx = sc;
+ ry = -1.0f;
+ rz = -tc;
+ break;
+ case PIPE_TEX_FACE_POS_Z:
+ rx = sc;
+ ry = -tc;
+ rz = 1.0f;
+ break;
+ case PIPE_TEX_FACE_NEG_Z:
+ rx = -sc;
+ ry = -tc;
+ rz = -1.0f;
+ break;
+ default:
+ assert(0);
+ }
+
+ ctx->vertices[i][1][0] = rx; /*s*/
+ ctx->vertices[i][1][1] = ry; /*t*/
+ ctx->vertices[i][1][2] = rz; /*r*/
+ }
+ }
+ else {
+ /* 1D/2D */
+ ctx->vertices[0][1][0] = 0.0f; /*s*/
+ ctx->vertices[0][1][1] = 0.0f; /*t*/
+ ctx->vertices[0][1][2] = 0.0f; /*r*/
+
+ ctx->vertices[1][1][0] = 1.0f;
+ ctx->vertices[1][1][1] = 0.0f;
+ ctx->vertices[1][1][2] = 0.0f;
+
+ ctx->vertices[2][1][0] = 1.0f;
+ ctx->vertices[2][1][1] = 1.0f;
+ ctx->vertices[2][1][2] = 0.0f;
+
+ ctx->vertices[3][1][0] = 0.0f;
+ ctx->vertices[3][1][1] = 1.0f;
+ ctx->vertices[3][1][2] = 0.0f;
+ }
+
+ offset = get_next_slot( ctx );
+
+ pipe_buffer_write(ctx->pipe->screen, ctx->vbuf,
+ offset, sizeof(ctx->vertices), ctx->vertices);
+
+ return offset;
+}
+
+
+
+/**
+ * Destroy a mipmap generation context
+ */
+void
+util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
+{
+ struct pipe_context *pipe = ctx->pipe;
+
+ pipe->delete_vs_state(pipe, ctx->vs);
+ pipe->delete_fs_state(pipe, ctx->fs);
+
+ pipe_buffer_reference(&ctx->vbuf, NULL);
+
+ FREE(ctx);
+}
+
+
+
+/* Release vertex buffer at end of frame to avoid synchronous
+ * rendering.
+ */
+void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
+{
+ pipe_buffer_reference(&ctx->vbuf, NULL);
+ ctx->vbuf_slot = 0;
+}
+
+
+/**
+ * Generate mipmap images. It's assumed all needed texture memory is
+ * already allocated.
+ *
+ * \param pt the texture to generate mipmap levels for
+ * \param face which cube face to generate mipmaps for (0 for non-cube maps)
+ * \param baseLevel the first mipmap level to use as a src
+ * \param lastLevel the last mipmap level to generate
+ * \param filter the minification filter used to generate mipmap levels with
+ * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
+ */
+void
+util_gen_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel, uint filter)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_framebuffer_state fb;
+ uint dstLevel;
+ uint zslice = 0;
+ uint offset;
+
+ /* check if we can render in the texture's format */
+ if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
+ return;
+ }
+
+ /* save state (restored below) */
+ cso_save_blend(ctx->cso);
+ cso_save_depth_stencil_alpha(ctx->cso);
+ cso_save_rasterizer(ctx->cso);
+ cso_save_samplers(ctx->cso);
+ cso_save_sampler_textures(ctx->cso);
+ cso_save_framebuffer(ctx->cso);
+ cso_save_fragment_shader(ctx->cso);
+ cso_save_vertex_shader(ctx->cso);
+
+ /* bind our state */
+ cso_set_blend(ctx->cso, &ctx->blend);
+ cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+ cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
+
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
+ cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
+
+ /* init framebuffer state */
+ memset(&fb, 0, sizeof(fb));
+ fb.nr_cbufs = 1;
+
+ /* set min/mag to same filter for faster sw speed */
+ ctx->sampler.mag_img_filter = filter;
+ ctx->sampler.min_img_filter = filter;
+
+ /*
+ * XXX for small mipmap levels, it may be faster to use the software
+ * fallback path...
+ */
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+
+ struct pipe_surface *surf =
+ screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /*
+ * Setup framebuffer / dest surface
+ */
+ fb.cbufs[0] = surf;
+ fb.width = pt->width[dstLevel];
+ fb.height = pt->height[dstLevel];
+ cso_set_framebuffer(ctx->cso, &fb);
+
+ /*
+ * Setup sampler state
+ * Note: we should only have to set the min/max LOD clamps to ensure
+ * we grab texels from the right mipmap level. But some hardware
+ * has trouble with min clamping so we also set the lod_bias to
+ * try to work around that.
+ */
+ ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
+ ctx->sampler.lod_bias = (float) srcLevel;
+ cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+ cso_single_sampler_done(ctx->cso);
+
+ cso_set_sampler_textures(ctx->cso, 1, &pt);
+
+ /* quad coords in window coords (bypassing vs, clip and viewport) */
+ offset = set_vertex_data(ctx,
+ pt->target,
+ face,
+ (float) pt->width[dstLevel],
+ (float) pt->height[dstLevel]);
+
+ util_draw_vertex_buffer(ctx->pipe,
+ ctx->vbuf,
+ offset,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* need to signal that the texture has changed _after_ rendering to it */
+ pipe_surface_reference( &surf, NULL );
+ }
+
+ /* restore state we changed */
+ cso_restore_blend(ctx->cso);
+ cso_restore_depth_stencil_alpha(ctx->cso);
+ cso_restore_rasterizer(ctx->cso);
+ cso_restore_samplers(ctx->cso);
+ cso_restore_sampler_textures(ctx->cso);
+ cso_restore_framebuffer(ctx->cso);
+ cso_restore_fragment_shader(ctx->cso);
+ cso_restore_vertex_shader(ctx->cso);
+}
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h
new file mode 100644
index 0000000000..54608f9466
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_GENMIPMAP_H
+#define U_GENMIPMAP_H
+
+#include "pipe/p_state.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_context;
+struct pipe_texture;
+struct cso_context;
+
+struct gen_mipmap_state;
+
+
+extern struct gen_mipmap_state *
+util_create_gen_mipmap(struct pipe_context *pipe, struct cso_context *cso);
+
+
+extern void
+util_destroy_gen_mipmap(struct gen_mipmap_state *ctx);
+
+/* Release vertex buffer at end of frame to avoid synchronous
+ * rendering.
+ */
+extern void
+util_gen_mipmap_flush( struct gen_mipmap_state *ctx );
+
+
+extern void
+util_gen_mipmap(struct gen_mipmap_state *ctx,
+ struct pipe_texture *pt,
+ uint face, uint baseLevel, uint lastLevel, uint filter);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_handle_table.c b/src/gallium/auxiliary/util/u_handle_table.c
new file mode 100644
index 0000000000..3703718a62
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_handle_table.c
@@ -0,0 +1,298 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Generic handle table implementation.
+ *
+ * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+
+#include "util/u_memory.h"
+#include "util/u_handle_table.h"
+
+
+#define HANDLE_TABLE_INITIAL_SIZE 16
+
+
+struct handle_table
+{
+ /** Object array. Empty handles have a null object */
+ void **objects;
+
+ /** Number of objects the handle can currently hold */
+ unsigned size;
+ /** Number of consecutive objects allocated at the start of the table */
+ unsigned filled;
+
+ /** Optional object destructor */
+ void (*destroy)(void *object);
+};
+
+
+struct handle_table *
+handle_table_create(void)
+{
+ struct handle_table *ht;
+
+ ht = MALLOC_STRUCT(handle_table);
+ if(!ht)
+ return NULL;
+
+ ht->objects = (void **)CALLOC(HANDLE_TABLE_INITIAL_SIZE, sizeof(void *));
+ if(!ht->objects) {
+ FREE(ht);
+ return NULL;
+ }
+
+ ht->size = HANDLE_TABLE_INITIAL_SIZE;
+ ht->filled = 0;
+
+ ht->destroy = NULL;
+
+ return ht;
+}
+
+
+void
+handle_table_set_destroy(struct handle_table *ht,
+ void (*destroy)(void *object))
+{
+ assert(ht);
+ if (!ht)
+ return;
+ ht->destroy = destroy;
+}
+
+
+/**
+ * Resize the table if necessary
+ */
+static INLINE int
+handle_table_resize(struct handle_table *ht,
+ unsigned minimum_size)
+{
+ unsigned new_size;
+ void **new_objects;
+
+ if(ht->size > minimum_size)
+ return ht->size;
+
+ new_size = ht->size;
+ while(!(new_size > minimum_size))
+ new_size *= 2;
+ assert(new_size);
+
+ new_objects = (void **)REALLOC((void *)ht->objects,
+ ht->size*sizeof(void *),
+ new_size*sizeof(void *));
+ if(!new_objects)
+ return 0;
+
+ memset(new_objects + ht->size, 0, (new_size - ht->size)*sizeof(void *));
+
+ ht->size = new_size;
+ ht->objects = new_objects;
+
+ return ht->size;
+}
+
+
+static INLINE void
+handle_table_clear(struct handle_table *ht,
+ unsigned index)
+{
+ void *object;
+
+ /* The order here is important so that the object being destroyed is not
+ * present in the table when seen by the destroy callback, because the
+ * destroy callback may directly or indirectly call the other functions in
+ * this module.
+ */
+
+ object = ht->objects[index];
+ if(object) {
+ ht->objects[index] = NULL;
+
+ if(ht->destroy)
+ ht->destroy(object);
+ }
+}
+
+
+unsigned
+handle_table_add(struct handle_table *ht,
+ void *object)
+{
+ unsigned index;
+ unsigned handle;
+
+ assert(ht);
+ assert(object);
+ if(!object || !ht)
+ return 0;
+
+ /* linear search for an empty handle */
+ while(ht->filled < ht->size) {
+ if(!ht->objects[ht->filled])
+ break;
+ ++ht->filled;
+ }
+
+ index = ht->filled;
+ handle = index + 1;
+
+ /* check integer overflow */
+ if(!handle)
+ return 0;
+
+ /* grow the table if necessary */
+ if(!handle_table_resize(ht, index))
+ return 0;
+
+ assert(!ht->objects[index]);
+ ht->objects[index] = object;
+ ++ht->filled;
+
+ return handle;
+}
+
+
+unsigned
+handle_table_set(struct handle_table *ht,
+ unsigned handle,
+ void *object)
+{
+ unsigned index;
+
+ assert(ht);
+ assert(handle);
+ if(!handle || !ht)
+ return 0;
+
+ assert(object);
+ if(!object)
+ return 0;
+
+ index = handle - 1;
+
+ /* grow the table if necessary */
+ if(!handle_table_resize(ht, index))
+ return 0;
+
+ handle_table_clear(ht, index);
+
+ ht->objects[index] = object;
+
+ return handle;
+}
+
+
+void *
+handle_table_get(struct handle_table *ht,
+ unsigned handle)
+{
+ void *object;
+
+ assert(ht);
+ assert(handle);
+ if(!handle || !ht || handle > ht->size)
+ return NULL;
+
+ object = ht->objects[handle - 1];
+
+ return object;
+}
+
+
+void
+handle_table_remove(struct handle_table *ht,
+ unsigned handle)
+{
+ void *object;
+ unsigned index;
+
+ assert(ht);
+ assert(handle);
+ if(!handle || !ht || handle > ht->size)
+ return;
+
+ index = handle - 1;
+ object = ht->objects[index];
+ if(!object)
+ return;
+
+ handle_table_clear(ht, index);
+
+ if(index < ht->filled)
+ ht->filled = index;
+}
+
+
+unsigned
+handle_table_get_next_handle(struct handle_table *ht,
+ unsigned handle)
+{
+ unsigned index;
+
+ for(index = handle; index < ht->size; ++index) {
+ if(ht->objects[index])
+ return index + 1;
+ }
+
+ return 0;
+}
+
+
+unsigned
+handle_table_get_first_handle(struct handle_table *ht)
+{
+ return handle_table_get_next_handle(ht, 0);
+}
+
+
+void
+handle_table_destroy(struct handle_table *ht)
+{
+ unsigned index;
+ assert(ht);
+
+ if (!ht)
+ return;
+
+ if(ht->destroy)
+ for(index = 0; index < ht->size; ++index)
+ handle_table_clear(ht, index);
+
+ FREE(ht->objects);
+ FREE(ht);
+}
+
diff --git a/src/gallium/auxiliary/util/u_handle_table.h b/src/gallium/auxiliary/util/u_handle_table.h
new file mode 100644
index 0000000000..d080135c9f
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_handle_table.h
@@ -0,0 +1,116 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Generic handle table.
+ *
+ * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef U_HANDLE_TABLE_H_
+#define U_HANDLE_TABLE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Abstract data type to map integer handles to objects.
+ *
+ * Also referred as "pointer array".
+ */
+struct handle_table;
+
+
+struct handle_table *
+handle_table_create(void);
+
+
+/**
+ * Set an optional destructor callback.
+ *
+ * If set, it will be called during handle_table_remove and
+ * handle_table_destroy calls.
+ */
+void
+handle_table_set_destroy(struct handle_table *ht,
+ void (*destroy)(void *object));
+
+
+/**
+ * Add a new object.
+ *
+ * Returns a zero handle on failure (out of memory).
+ */
+unsigned
+handle_table_add(struct handle_table *ht,
+ void *object);
+
+/**
+ * Returns zero on failure (out of memory).
+ */
+unsigned
+handle_table_set(struct handle_table *ht,
+ unsigned handle,
+ void *object);
+
+/**
+ * Fetch an existing object.
+ *
+ * Returns NULL for an invalid handle.
+ */
+void *
+handle_table_get(struct handle_table *ht,
+ unsigned handle);
+
+
+void
+handle_table_remove(struct handle_table *ht,
+ unsigned handle);
+
+
+void
+handle_table_destroy(struct handle_table *ht);
+
+
+unsigned
+handle_table_get_first_handle(struct handle_table *ht);
+
+
+unsigned
+handle_table_get_next_handle(struct handle_table *ht,
+ unsigned handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_HANDLE_TABLE_H_ */
diff --git a/src/gallium/auxiliary/util/u_hash.c b/src/gallium/auxiliary/util/u_hash.c
new file mode 100644
index 0000000000..b67653ec70
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_hash.c
@@ -0,0 +1,121 @@
+/**************************************************************************
+ *
+ * Copyright 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Hash functions implementation.
+ *
+ * @author Jose Fonseca
+ */
+
+
+#include "u_hash.h"
+
+
+static const uint32_t
+util_crc32_table[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+
+/**
+ * @sa http://www.w3.org/TR/PNG/#D-CRCAppendix
+ */
+uint32_t
+util_hash_crc32(const void *data, size_t size)
+{
+ uint8_t *p = (uint8_t *)data;
+ uint32_t crc = 0xffffffff;
+
+ while (size--)
+ crc = util_crc32_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+
+ return crc;
+}
diff --git a/src/gallium/auxiliary/util/u_hash.h b/src/gallium/auxiliary/util/u_hash.h
new file mode 100644
index 0000000000..8d92b07c85
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_hash.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+ *
+ * Copyright 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Hash functions.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef U_HASH_H_
+#define U_HASH_H_
+
+
+#include "pipe/p_compiler.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+uint32_t
+util_hash_crc32(const void *data, size_t size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_HASH_H_ */
diff --git a/src/gallium/auxiliary/util/u_hash_table.c b/src/gallium/auxiliary/util/u_hash_table.c
new file mode 100644
index 0000000000..8c2a8f454c
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_hash_table.c
@@ -0,0 +1,292 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * General purpose hash table implementation.
+ *
+ * Just uses the cso_hash for now, but it might be better switch to a linear
+ * probing hash table implementation at some point -- as it is said they have
+ * better lookup and cache performance and it appears to be possible to write
+ * a lock-free implementation of such hash tables .
+ *
+ * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+
+#include "cso_cache/cso_hash.h"
+
+#include "util/u_memory.h"
+#include "util/u_hash_table.h"
+
+
+struct hash_table
+{
+ struct cso_hash *cso;
+
+ /** Hash function */
+ unsigned (*hash)(void *key);
+
+ /** Compare two keys */
+ int (*compare)(void *key1, void *key2);
+
+ /* TODO: key, value destructors? */
+};
+
+
+struct hash_table_item
+{
+ void *key;
+ void *value;
+};
+
+
+static INLINE struct hash_table_item *
+hash_table_item(struct cso_hash_iter iter)
+{
+ return (struct hash_table_item *)cso_hash_iter_data(iter);
+}
+
+
+struct hash_table *
+hash_table_create(unsigned (*hash)(void *key),
+ int (*compare)(void *key1, void *key2))
+{
+ struct hash_table *ht;
+
+ ht = MALLOC_STRUCT(hash_table);
+ if(!ht)
+ return NULL;
+
+ ht->cso = cso_hash_create();
+ if(!ht->cso) {
+ FREE(ht);
+ return NULL;
+ }
+
+ ht->hash = hash;
+ ht->compare = compare;
+
+ return ht;
+}
+
+
+static INLINE struct cso_hash_iter
+hash_table_find_iter(struct hash_table *ht,
+ void *key,
+ unsigned key_hash)
+{
+ struct cso_hash_iter iter;
+ struct hash_table_item *item;
+
+ iter = cso_hash_find(ht->cso, key_hash);
+ while (!cso_hash_iter_is_null(iter)) {
+ item = (struct hash_table_item *)cso_hash_iter_data(iter);
+ if (!ht->compare(item->key, key))
+ break;
+ iter = cso_hash_iter_next(iter);
+ }
+
+ return iter;
+}
+
+
+static INLINE struct hash_table_item *
+hash_table_find_item(struct hash_table *ht,
+ void *key,
+ unsigned key_hash)
+{
+ struct cso_hash_iter iter;
+ struct hash_table_item *item;
+
+ iter = cso_hash_find(ht->cso, key_hash);
+ while (!cso_hash_iter_is_null(iter)) {
+ item = (struct hash_table_item *)cso_hash_iter_data(iter);
+ if (!ht->compare(item->key, key))
+ return item;
+ iter = cso_hash_iter_next(iter);
+ }
+
+ return NULL;
+}
+
+
+enum pipe_error
+hash_table_set(struct hash_table *ht,
+ void *key,
+ void *value)
+{
+ unsigned key_hash;
+ struct hash_table_item *item;
+ struct cso_hash_iter iter;
+
+ assert(ht);
+ if (!ht)
+ return PIPE_ERROR_BAD_INPUT;
+
+ key_hash = ht->hash(key);
+
+ item = hash_table_find_item(ht, key, key_hash);
+ if(item) {
+ /* TODO: key/value destruction? */
+ item->value = value;
+ return PIPE_OK;
+ }
+
+ item = MALLOC_STRUCT(hash_table_item);
+ if(!item)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ item->key = key;
+ item->value = value;
+
+ iter = cso_hash_insert(ht->cso, key_hash, item);
+ if(cso_hash_iter_is_null(iter)) {
+ FREE(item);
+ return PIPE_ERROR_OUT_OF_MEMORY;
+ }
+
+ return PIPE_OK;
+}
+
+
+void *
+hash_table_get(struct hash_table *ht,
+ void *key)
+{
+ unsigned key_hash;
+ struct hash_table_item *item;
+
+ assert(ht);
+ if (!ht)
+ return NULL;
+
+ key_hash = ht->hash(key);
+
+ item = hash_table_find_item(ht, key, key_hash);
+ if(!item)
+ return NULL;
+
+ return item->value;
+}
+
+
+void
+hash_table_remove(struct hash_table *ht,
+ void *key)
+{
+ unsigned key_hash;
+ struct cso_hash_iter iter;
+ struct hash_table_item *item;
+
+ assert(ht);
+ if (!ht)
+ return;
+
+ key_hash = ht->hash(key);
+
+ iter = hash_table_find_iter(ht, key, key_hash);
+ if(cso_hash_iter_is_null(iter))
+ return;
+
+ item = hash_table_item(iter);
+ assert(item);
+ FREE(item);
+
+ cso_hash_erase(ht->cso, iter);
+}
+
+
+void
+hash_table_clear(struct hash_table *ht)
+{
+ struct cso_hash_iter iter;
+ struct hash_table_item *item;
+
+ assert(ht);
+ if (!ht)
+ return;
+
+ iter = cso_hash_first_node(ht->cso);
+ while (!cso_hash_iter_is_null(iter)) {
+ item = (struct hash_table_item *)cso_hash_take(ht->cso, cso_hash_iter_key(iter));
+ FREE(item);
+ iter = cso_hash_first_node(ht->cso);
+ }
+}
+
+
+enum pipe_error
+hash_table_foreach(struct hash_table *ht,
+ enum pipe_error (*callback)(void *key, void *value, void *data),
+ void *data)
+{
+ struct cso_hash_iter iter;
+ struct hash_table_item *item;
+ enum pipe_error result;
+
+ assert(ht);
+ if (!ht)
+ return PIPE_ERROR_BAD_INPUT;
+
+ iter = cso_hash_first_node(ht->cso);
+ while (!cso_hash_iter_is_null(iter)) {
+ item = (struct hash_table_item *)cso_hash_iter_data(iter);
+ result = callback(item->key, item->value, data);
+ if(result != PIPE_OK)
+ return result;
+ iter = cso_hash_iter_next(iter);
+ }
+
+ return PIPE_OK;
+}
+
+
+void
+hash_table_destroy(struct hash_table *ht)
+{
+ struct cso_hash_iter iter;
+ struct hash_table_item *item;
+
+ assert(ht);
+ if (!ht)
+ return;
+
+ iter = cso_hash_first_node(ht->cso);
+ while (!cso_hash_iter_is_null(iter)) {
+ item = (struct hash_table_item *)cso_hash_iter_data(iter);
+ FREE(item);
+ iter = cso_hash_iter_next(iter);
+ }
+
+ cso_hash_delete(ht->cso);
+
+ FREE(ht);
+}
diff --git a/src/gallium/auxiliary/util/u_hash_table.h b/src/gallium/auxiliary/util/u_hash_table.h
new file mode 100644
index 0000000000..feee881582
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_hash_table.h
@@ -0,0 +1,95 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * General purpose hash table.
+ *
+ * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef U_HASH_TABLE_H_
+#define U_HASH_TABLE_H_
+
+
+#include "pipe/p_error.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Generic purpose hash table.
+ */
+struct hash_table;
+
+
+/**
+ * Create an hash table.
+ *
+ * @param hash hash function
+ * @param compare should return 0 for two equal keys.
+ */
+struct hash_table *
+hash_table_create(unsigned (*hash)(void *key),
+ int (*compare)(void *key1, void *key2));
+
+
+enum pipe_error
+hash_table_set(struct hash_table *ht,
+ void *key,
+ void *value);
+
+void *
+hash_table_get(struct hash_table *ht,
+ void *key);
+
+
+void
+hash_table_remove(struct hash_table *ht,
+ void *key);
+
+
+void
+hash_table_clear(struct hash_table *ht);
+
+
+enum pipe_error
+hash_table_foreach(struct hash_table *ht,
+ enum pipe_error (*callback)(void *key, void *value, void *data),
+ void *data);
+
+void
+hash_table_destroy(struct hash_table *ht);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_HASH_TABLE_H_ */
diff --git a/src/gallium/auxiliary/util/u_keymap.c b/src/gallium/auxiliary/util/u_keymap.c
new file mode 100644
index 0000000000..508a2ee063
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_keymap.c
@@ -0,0 +1,319 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Key lookup/associative container.
+ *
+ * Like Jose's u_hash_table, based on CSO cache code for now.
+ *
+ * Author: Brian Paul
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_error.h"
+
+#include "cso_cache/cso_hash.h"
+
+#include "util/u_memory.h"
+#include "util/u_keymap.h"
+
+
+struct keymap
+{
+ struct cso_hash *cso;
+ unsigned key_size;
+ unsigned max_entries; /* XXX not obeyed net */
+ unsigned num_entries;
+ keymap_delete_func delete_func;
+};
+
+
+struct keymap_item
+{
+ void *key, *value;
+};
+
+
+/**
+ * This the default key-delete function used when the client doesn't
+ * provide one.
+ */
+static void
+default_delete_func(const struct keymap *map,
+ const void *key, void *data, void *user)
+{
+ FREE((void*) data);
+}
+
+
+static INLINE struct keymap_item *
+hash_table_item(struct cso_hash_iter iter)
+{
+ return (struct keymap_item *) cso_hash_iter_data(iter);
+}
+
+
+/**
+ * Return 4-byte hash key for a block of bytes.
+ */
+static unsigned
+hash(const void *key, unsigned keySize)
+{
+ unsigned i, hash;
+
+ keySize /= 4; /* convert from bytes to uints */
+
+ hash = 0;
+ for (i = 0; i < keySize; i++) {
+ hash ^= (i + 1) * ((const unsigned *) key)[i];
+ }
+
+ /*hash = hash ^ (hash >> 11) ^ (hash >> 22);*/
+
+ return hash;
+}
+
+
+/**
+ * Create a new map.
+ * \param keySize size of the keys in bytes
+ * \param maxEntries max number of entries to allow (~0 = infinity)
+ * \param deleteFunc optional callback to call when entries
+ * are deleted/replaced
+ */
+struct keymap *
+util_new_keymap(unsigned keySize, unsigned maxEntries,
+ keymap_delete_func deleteFunc)
+{
+ struct keymap *map = MALLOC_STRUCT(keymap);
+ if (!map)
+ return NULL;
+
+ map->cso = cso_hash_create();
+ if (!map->cso) {
+ FREE(map);
+ return NULL;
+ }
+
+ map->max_entries = maxEntries;
+ map->num_entries = 0;
+ map->key_size = keySize;
+ map->delete_func = deleteFunc ? deleteFunc : default_delete_func;
+
+ return map;
+}
+
+
+/**
+ * Delete/free a keymap and all entries. The deleteFunc that was given at
+ * create time will be called for each entry.
+ * \param user user-provided pointer passed through to the delete callback
+ */
+void
+util_delete_keymap(struct keymap *map, void *user)
+{
+ util_keymap_remove_all(map, user);
+ cso_hash_delete(map->cso);
+ FREE(map);
+}
+
+
+static INLINE struct cso_hash_iter
+hash_table_find_iter(const struct keymap *map, const void *key,
+ unsigned key_hash)
+{
+ struct cso_hash_iter iter;
+ struct keymap_item *item;
+
+ iter = cso_hash_find(map->cso, key_hash);
+ while (!cso_hash_iter_is_null(iter)) {
+ item = (struct keymap_item *) cso_hash_iter_data(iter);
+ if (!memcmp(item->key, key, map->key_size))
+ break;
+ iter = cso_hash_iter_next(iter);
+ }
+
+ return iter;
+}
+
+
+static INLINE struct keymap_item *
+hash_table_find_item(const struct keymap *map, const void *key,
+ unsigned key_hash)
+{
+ struct cso_hash_iter iter = hash_table_find_iter(map, key, key_hash);
+ if (cso_hash_iter_is_null(iter)) {
+ return NULL;
+ }
+ else {
+ return hash_table_item(iter);
+ }
+}
+
+
+/**
+ * Insert a new key + data pointer into the table.
+ * Note: we create a copy of the key, but not the data!
+ * If the key is already present in the table, replace the existing
+ * entry (calling the delete callback on the previous entry).
+ * If the maximum capacity of the map is reached an old entry
+ * will be deleted (the delete callback will be called).
+ */
+boolean
+util_keymap_insert(struct keymap *map, const void *key,
+ const void *data, void *user)
+{
+ unsigned key_hash;
+ struct keymap_item *item;
+ struct cso_hash_iter iter;
+
+ assert(map);
+ if (!map)
+ return FALSE;
+
+ key_hash = hash(key, map->key_size);
+
+ item = hash_table_find_item(map, key, key_hash);
+ if (item) {
+ /* call delete callback for old entry/item */
+ map->delete_func(map, item->key, item->value, user);
+ item->value = (void *) data;
+ return TRUE;
+ }
+
+ item = MALLOC_STRUCT(keymap_item);
+ if (!item)
+ return FALSE;
+
+ item->key = mem_dup(key, map->key_size);
+ item->value = (void *) data;
+
+ iter = cso_hash_insert(map->cso, key_hash, item);
+ if (cso_hash_iter_is_null(iter)) {
+ FREE(item);
+ return FALSE;
+ }
+
+ map->num_entries++;
+
+ return TRUE;
+}
+
+
+/**
+ * Look up a key in the map and return the associated data pointer.
+ */
+const void *
+util_keymap_lookup(const struct keymap *map, const void *key)
+{
+ unsigned key_hash;
+ struct keymap_item *item;
+
+ assert(map);
+ if (!map)
+ return NULL;
+
+ key_hash = hash(key, map->key_size);
+
+ item = hash_table_find_item(map, key, key_hash);
+ if (!item)
+ return NULL;
+
+ return item->value;
+}
+
+
+/**
+ * Remove an entry from the map.
+ * The delete callback will be called if the given key/entry is found.
+ * \param user passed to the delete callback as the last param.
+ */
+void
+util_keymap_remove(struct keymap *map, const void *key, void *user)
+{
+ unsigned key_hash;
+ struct cso_hash_iter iter;
+ struct keymap_item *item;
+
+ assert(map);
+ if (!map)
+ return;
+
+ key_hash = hash(key, map->key_size);
+
+ iter = hash_table_find_iter(map, key, key_hash);
+ if (cso_hash_iter_is_null(iter))
+ return;
+
+ item = hash_table_item(iter);
+ assert(item);
+ if (!item)
+ return;
+ map->delete_func(map, item->key, item->value, user);
+ FREE(item->key);
+ FREE(item);
+
+ map->num_entries--;
+
+ cso_hash_erase(map->cso, iter);
+}
+
+
+/**
+ * Remove all entries from the map, calling the delete callback for each.
+ * \param user passed to the delete callback as the last param.
+ */
+void
+util_keymap_remove_all(struct keymap *map, void *user)
+{
+ struct cso_hash_iter iter;
+ struct keymap_item *item;
+
+ assert(map);
+ if (!map)
+ return;
+
+ iter = cso_hash_first_node(map->cso);
+ while (!cso_hash_iter_is_null(iter)) {
+ item = (struct keymap_item *)
+ cso_hash_take(map->cso, cso_hash_iter_key(iter));
+ map->delete_func(map, item->key, item->value, user);
+ FREE(item->key);
+ FREE(item);
+ iter = cso_hash_first_node(map->cso);
+ }
+}
+
+
+extern void
+util_keymap_info(const struct keymap *map)
+{
+ debug_printf("Keymap %p: %u of max %u entries\n",
+ (void *) map, map->num_entries, map->max_entries);
+}
diff --git a/src/gallium/auxiliary/util/u_keymap.h b/src/gallium/auxiliary/util/u_keymap.h
new file mode 100644
index 0000000000..8d60a76fc3
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_keymap.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_KEYMAP_H
+#define U_KEYMAP_H
+
+#include "pipe/p_compiler.h"
+
+
+/** opaque keymap type */
+struct keymap;
+
+
+/** Delete/callback function type */
+typedef void (*keymap_delete_func)(const struct keymap *map,
+ const void *key, void *data,
+ void *user);
+
+
+extern struct keymap *
+util_new_keymap(unsigned keySize, unsigned maxEntries,
+ keymap_delete_func deleteFunc);
+
+extern void
+util_delete_keymap(struct keymap *map, void *user);
+
+extern boolean
+util_keymap_insert(struct keymap *map, const void *key,
+ const void *data, void *user);
+
+extern const void *
+util_keymap_lookup(const struct keymap *map, const void *key);
+
+extern void
+util_keymap_remove(struct keymap *map, const void *key, void *user);
+
+extern void
+util_keymap_remove_all(struct keymap *map, void *user);
+
+extern void
+util_keymap_info(const struct keymap *map);
+
+
+#endif /* U_KEYMAP_H */
diff --git a/src/gallium/auxiliary/util/u_linear.c b/src/gallium/auxiliary/util/u_linear.c
new file mode 100644
index 0000000000..a1dce3f5cf
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_linear.c
@@ -0,0 +1,101 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Functions for converting tiled data to linear and vice versa.
+ */
+
+
+#include "util/u_debug.h"
+#include "u_linear.h"
+
+void
+pipe_linear_to_tile(size_t src_stride, const void *src_ptr,
+ struct pipe_tile_info *t, void *dst_ptr)
+{
+ int x, y, z;
+ char *ptr;
+ size_t bytes = t->cols * t->block.size;
+ char *dst_ptr2 = (char *) dst_ptr;
+
+ assert(pipe_linear_check_tile(t));
+
+ /* lets write lineary to the tiled buffer */
+ for (y = 0; y < t->tiles_y; y++) {
+ for (x = 0; x < t->tiles_x; x++) {
+ /* this inner loop could be replace with SSE magic */
+ ptr = (char*)src_ptr + src_stride * t->rows * y + bytes * x;
+ for (z = 0; z < t->rows; z++) {
+ memcpy(dst_ptr2, ptr, bytes);
+ dst_ptr2 += bytes;
+ ptr += src_stride;
+ }
+ }
+ }
+}
+
+void pipe_linear_from_tile(struct pipe_tile_info *t, const void *src_ptr,
+ size_t dst_stride, void *dst_ptr)
+{
+ int x, y, z;
+ char *ptr;
+ size_t bytes = t->cols * t->block.size;
+ const char *src_ptr2 = (const char *) src_ptr;
+
+ /* lets read lineary from the tiled buffer */
+ for (y = 0; y < t->tiles_y; y++) {
+ for (x = 0; x < t->tiles_x; x++) {
+ /* this inner loop could be replace with SSE magic */
+ ptr = (char*)dst_ptr + dst_stride * t->rows * y + bytes * x;
+ for (z = 0; z < t->rows; z++) {
+ memcpy(ptr, src_ptr2, bytes);
+ src_ptr2 += bytes;
+ ptr += dst_stride;
+ }
+ }
+ }
+}
+
+void
+pipe_linear_fill_info(struct pipe_tile_info *t,
+ const struct pipe_format_block *block,
+ unsigned tile_width, unsigned tile_height,
+ unsigned tiles_x, unsigned tiles_y)
+{
+ t->block = *block;
+
+ t->tile.width = tile_width;
+ t->tile.height = tile_height;
+ t->cols = t->tile.width / t->block.width;
+ t->rows = t->tile.height / t->block.height;
+ t->tile.size = t->cols * t->rows * t->block.size;
+
+ t->tiles_x = tiles_x;
+ t->tiles_y = tiles_y;
+ t->stride = t->cols * t->tiles_x * t->block.size;
+ t->size = t->tiles_x * t->tiles_y * t->tile.size;
+}
diff --git a/src/gallium/auxiliary/util/u_linear.h b/src/gallium/auxiliary/util/u_linear.h
new file mode 100644
index 0000000000..b74308ffa3
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_linear.h
@@ -0,0 +1,92 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Functions for converting tiled data to linear and vice versa.
+ */
+
+
+#ifndef U_LINEAR_H
+#define U_LINEAR_H
+
+#include "pipe/p_format.h"
+
+struct pipe_tile_info
+{
+ unsigned size;
+ unsigned stride;
+
+ /* The number of tiles */
+ unsigned tiles_x;
+ unsigned tiles_y;
+
+ /* size of each tile expressed in blocks */
+ unsigned cols;
+ unsigned rows;
+
+ /* Describe the tile in pixels */
+ struct pipe_format_block tile;
+
+ /* Describe each block within the tile */
+ struct pipe_format_block block;
+};
+
+void pipe_linear_to_tile(size_t src_stride, const void *src_ptr,
+ struct pipe_tile_info *t, void *dst_ptr);
+
+void pipe_linear_from_tile(struct pipe_tile_info *t, const void *src_ptr,
+ size_t dst_stride, void *dst_ptr);
+
+/**
+ * Convenience function to fillout a pipe_tile_info struct.
+ * @t info to fill out.
+ * @block block info about pixel layout
+ * @tile_width the width of the tile in pixels
+ * @tile_height the height of the tile in pixels
+ * @tiles_x number of tiles in x axis
+ * @tiles_y number of tiles in y axis
+ */
+void pipe_linear_fill_info(struct pipe_tile_info *t,
+ const struct pipe_format_block *block,
+ unsigned tile_width, unsigned tile_height,
+ unsigned tiles_x, unsigned tiles_y);
+
+static INLINE boolean pipe_linear_check_tile(const struct pipe_tile_info *t)
+{
+ if (t->tile.size != t->block.size * t->cols * t->rows)
+ return FALSE;
+
+ if (t->stride != t->block.size * t->cols * t->tiles_x)
+ return FALSE;
+
+ if (t->size < t->stride * t->rows * t->tiles_y)
+ return FALSE;
+
+ return TRUE;
+}
+
+#endif /* U_LINEAR_H */
diff --git a/src/gallium/auxiliary/util/u_math.c b/src/gallium/auxiliary/util/u_math.c
new file mode 100644
index 0000000000..2811475fa0
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_math.c
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+
+#include "util/u_math.h"
+
+
+/** 2^x, for x in [-1.0, 1.0) */
+float pow2_table[POW2_TABLE_SIZE];
+
+
+static void
+init_pow2_table(void)
+{
+ int i;
+ for (i = 0; i < POW2_TABLE_SIZE; i++)
+ pow2_table[i] = (float) pow(2.0, (i - POW2_TABLE_OFFSET) / POW2_TABLE_SCALE);
+}
+
+
+/** log2(x), for x in [1.0, 2.0) */
+float log2_table[LOG2_TABLE_SIZE];
+
+
+static void
+init_log2_table(void)
+{
+ unsigned i;
+ for (i = 0; i < LOG2_TABLE_SIZE; i++)
+ log2_table[i] = (float) log2(1.0 + i * (1.0 / LOG2_TABLE_SCALE));
+}
+
+
+/**
+ * One time init for math utilities.
+ */
+void
+util_init_math(void)
+{
+ static boolean initialized = FALSE;
+ if (!initialized) {
+ init_pow2_table();
+ init_log2_table();
+ initialized = TRUE;
+ }
+}
+
+
diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h
new file mode 100644
index 0000000000..b12c97dfb4
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_math.h
@@ -0,0 +1,516 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Math utilities and approximations for common math functions.
+ * Reduced precision is usually acceptable in shaders...
+ *
+ * "fast" is used in the names of functions which are low-precision,
+ * or at least lower-precision than the normal C lib functions.
+ */
+
+
+#ifndef U_MATH_H
+#define U_MATH_H
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+__inline double ceil(double val)
+{
+ double ceil_val;
+
+ if ((val - (long) val) == 0) {
+ ceil_val = val;
+ }
+ else {
+ if (val > 0) {
+ ceil_val = (long) val + 1;
+ }
+ else {
+ ceil_val = (long) val;
+ }
+ }
+
+ return ceil_val;
+}
+
+#ifndef PIPE_SUBSYSTEM_WINDOWS_CE_OGL
+__inline double floor(double val)
+{
+ double floor_val;
+
+ if ((val - (long) val) == 0) {
+ floor_val = val;
+ }
+ else {
+ if (val > 0) {
+ floor_val = (long) val;
+ }
+ else {
+ floor_val = (long) val - 1;
+ }
+ }
+
+ return floor_val;
+}
+#endif
+
+#pragma function(pow)
+__inline double __cdecl pow(double val, double exponent)
+{
+ /* XXX */
+ assert(0);
+ return 0;
+}
+
+#pragma function(log)
+__inline double __cdecl log(double val)
+{
+ /* XXX */
+ assert(0);
+ return 0;
+}
+
+#pragma function(atan2)
+__inline double __cdecl atan2(double val)
+{
+ /* XXX */
+ assert(0);
+ return 0;
+}
+#else
+#include <math.h>
+#include <stdarg.h>
+#endif
+
+
+#if defined(_MSC_VER)
+
+#if _MSC_VER < 1400 && !defined(__cplusplus) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+
+static INLINE float cosf( float f )
+{
+ return (float) cos( (double) f );
+}
+
+static INLINE float sinf( float f )
+{
+ return (float) sin( (double) f );
+}
+
+static INLINE float ceilf( float f )
+{
+ return (float) ceil( (double) f );
+}
+
+static INLINE float floorf( float f )
+{
+ return (float) floor( (double) f );
+}
+
+static INLINE float powf( float f, float g )
+{
+ return (float) pow( (double) f, (double) g );
+}
+
+static INLINE float sqrtf( float f )
+{
+ return (float) sqrt( (double) f );
+}
+
+static INLINE float fabsf( float f )
+{
+ return (float) fabs( (double) f );
+}
+
+static INLINE float logf( float f )
+{
+ return (float) log( (double) f );
+}
+
+#else
+/* Work-around an extra semi-colon in VS 2005 logf definition */
+#ifdef logf
+#undef logf
+#define logf(x) ((float)log((double)(x)))
+#endif /* logf */
+#endif
+
+static INLINE double log2( double x )
+{
+ const double invln2 = 1.442695041;
+ return log( x ) * invln2;
+}
+
+#endif /* _MSC_VER */
+
+
+
+
+
+#define POW2_TABLE_SIZE_LOG2 9
+#define POW2_TABLE_SIZE (1 << POW2_TABLE_SIZE_LOG2)
+#define POW2_TABLE_OFFSET (POW2_TABLE_SIZE/2)
+#define POW2_TABLE_SCALE ((float)(POW2_TABLE_SIZE/2))
+extern float pow2_table[POW2_TABLE_SIZE];
+
+
+/**
+ * Initialize math module. This should be called before using any
+ * other functions in this module.
+ */
+extern void
+util_init_math(void);
+
+
+union fi {
+ float f;
+ int32_t i;
+ uint32_t ui;
+};
+
+
+/**
+ * Fast version of 2^x
+ * Identity: exp2(a + b) = exp2(a) * exp2(b)
+ * Let ipart = int(x)
+ * Let fpart = x - ipart;
+ * So, exp2(x) = exp2(ipart) * exp2(fpart)
+ * Compute exp2(ipart) with i << ipart
+ * Compute exp2(fpart) with lookup table.
+ */
+static INLINE float
+util_fast_exp2(float x)
+{
+ int32_t ipart;
+ float fpart, mpart;
+ union fi epart;
+
+ if(x > 129.00000f)
+ return 3.402823466e+38f;
+
+ if (x < -126.99999f)
+ return 0.0f;
+
+ ipart = (int32_t) x;
+ fpart = x - (float) ipart;
+
+ /* same as
+ * epart.f = (float) (1 << ipart)
+ * but faster and without integer overflow for ipart > 31
+ */
+ epart.i = (ipart + 127 ) << 23;
+
+ mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)];
+
+ return epart.f * mpart;
+}
+
+
+/**
+ * Fast approximation to exp(x).
+ */
+static INLINE float
+util_fast_exp(float x)
+{
+ const float k = 1.44269f; /* = log2(e) */
+ return util_fast_exp2(k * x);
+}
+
+
+#define LOG2_TABLE_SIZE_LOG2 16
+#define LOG2_TABLE_SCALE (1 << LOG2_TABLE_SIZE_LOG2)
+#define LOG2_TABLE_SIZE (LOG2_TABLE_SCALE + 1)
+extern float log2_table[LOG2_TABLE_SIZE];
+
+
+/**
+ * Fast approximation to log2(x).
+ */
+static INLINE float
+util_fast_log2(float x)
+{
+ union fi num;
+ float epart, mpart;
+ num.f = x;
+ epart = (float)(((num.i & 0x7f800000) >> 23) - 127);
+ /* mpart = log2_table[mantissa*LOG2_TABLE_SCALE + 0.5] */
+ mpart = log2_table[((num.i & 0x007fffff) + (1 << (22 - LOG2_TABLE_SIZE_LOG2))) >> (23 - LOG2_TABLE_SIZE_LOG2)];
+ return epart + mpart;
+}
+
+
+/**
+ * Fast approximation to x^y.
+ */
+static INLINE float
+util_fast_pow(float x, float y)
+{
+ return util_fast_exp2(util_fast_log2(x) * y);
+}
+
+
+/**
+ * Floor(x), returned as int.
+ */
+static INLINE int
+util_ifloor(float f)
+{
+ int ai, bi;
+ double af, bf;
+ union fi u;
+ af = (3 << 22) + 0.5 + (double) f;
+ bf = (3 << 22) + 0.5 - (double) f;
+ u.f = (float) af; ai = u.i;
+ u.f = (float) bf; bi = u.i;
+ return (ai - bi) >> 1;
+}
+
+
+/**
+ * Round float to nearest int.
+ */
+static INLINE int
+util_iround(float f)
+{
+#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86)
+ int r;
+ __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
+ return r;
+#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
+ int r;
+ _asm {
+ fld f
+ fistp r
+ }
+ return r;
+#else
+ if (f >= 0.0f)
+ return (int) (f + 0.5f);
+ else
+ return (int) (f - 0.5f);
+#endif
+}
+
+
+
+/**
+ * Test if x is NaN or +/- infinity.
+ */
+static INLINE boolean
+util_is_inf_or_nan(float x)
+{
+ union fi tmp;
+ tmp.f = x;
+ return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);
+}
+
+
+/**
+ * Test whether x is a power of two.
+ */
+static INLINE boolean
+util_is_pot(unsigned x)
+{
+ return (x & (x - 1)) == 0;
+}
+
+
+/**
+ * Find first bit set in word. Least significant bit is 1.
+ * Return 0 if no bits set.
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+static INLINE
+unsigned long ffs( unsigned long u )
+{
+ unsigned long i;
+ if (_BitScanForward(&i, u))
+ return i + 1;
+ else
+ return 0;
+}
+#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
+static INLINE
+unsigned ffs( unsigned u )
+{
+ unsigned i;
+
+ if (u == 0) {
+ return 0;
+ }
+
+ __asm bsf eax, [u]
+ __asm inc eax
+ __asm mov [i], eax
+
+ return i;
+}
+#elif defined(__MINGW32__)
+#define ffs __builtin_ffs
+#endif
+
+#ifdef __MINGW32__
+#define ffs __builtin_ffs
+#endif
+
+
+/* Could also binary search for the highest bit.
+ */
+static INLINE unsigned
+util_unsigned_logbase2(unsigned n)
+{
+ unsigned log2 = 0;
+ while (n >>= 1)
+ ++log2;
+ return log2;
+}
+
+
+/**
+ * Return float bits.
+ */
+static INLINE unsigned
+fui( float f )
+{
+ union fi fi;
+ fi.f = f;
+ return fi.ui;
+}
+
+
+/**
+ * Convert ubyte to float in [0, 1].
+ * XXX a 256-entry lookup table would be slightly faster.
+ */
+static INLINE float
+ubyte_to_float(ubyte ub)
+{
+ return (float) ub * (1.0f / 255.0f);
+}
+
+
+/**
+ * Convert float in [0,1] to ubyte in [0,255] with clamping.
+ */
+static INLINE ubyte
+float_to_ubyte(float f)
+{
+ const int ieee_0996 = 0x3f7f0000; /* 0.996 or so */
+ union fi tmp;
+
+ tmp.f = f;
+ if (tmp.i < 0) {
+ return (ubyte) 0;
+ }
+ else if (tmp.i >= ieee_0996) {
+ return (ubyte) 255;
+ }
+ else {
+ tmp.f = tmp.f * (255.0f/256.0f) + 32768.0f;
+ return (ubyte) tmp.i;
+ }
+}
+
+
+/**
+ * Calc log base 2
+ */
+static INLINE unsigned
+util_logbase2(unsigned n)
+{
+ unsigned log2 = 0;
+ while (n >>= 1)
+ ++log2;
+ return log2;
+}
+
+
+/**
+ * Clamp X to [MIN, MAX].
+ * This is a macro to allow float, int, uint, etc. types.
+ */
+#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
+
+#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) )
+#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
+
+
+static INLINE int
+align(int value, int alignment)
+{
+ return (value + alignment - 1) & ~(alignment - 1);
+}
+
+static INLINE unsigned
+minify(unsigned value)
+{
+ return MAX2(1, value >> 1);
+}
+
+#ifndef COPY_4V
+#define COPY_4V( DST, SRC ) \
+do { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+ (DST)[2] = (SRC)[2]; \
+ (DST)[3] = (SRC)[3]; \
+} while (0)
+#endif
+
+
+#ifndef COPY_4FV
+#define COPY_4FV( DST, SRC ) COPY_4V(DST, SRC)
+#endif
+
+
+#ifndef ASSIGN_4V
+#define ASSIGN_4V( DST, V0, V1, V2, V3 ) \
+do { \
+ (DST)[0] = (V0); \
+ (DST)[1] = (V1); \
+ (DST)[2] = (V2); \
+ (DST)[3] = (V3); \
+} while (0)
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_MATH_H */
diff --git a/src/gallium/auxiliary/util/u_memory.h b/src/gallium/auxiliary/util/u_memory.h
new file mode 100644
index 0000000000..c3f8c91833
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_memory.h
@@ -0,0 +1,242 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Memory functions
+ */
+
+
+#ifndef U_MEMORY_H
+#define U_MEMORY_H
+
+
+#include "util/u_pointer.h"
+#include "util/u_debug.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Define ENOMEM for WINCE */
+#if (_WIN32_WCE < 600)
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#endif
+
+
+#if defined(PIPE_OS_WINDOWS) && defined(DEBUG)
+
+/* memory debugging */
+
+#include "util/u_debug.h"
+
+#define MALLOC( _size ) \
+ debug_malloc( __FILE__, __LINE__, __FUNCTION__, _size )
+#define CALLOC( _count, _size ) \
+ debug_calloc(__FILE__, __LINE__, __FUNCTION__, _count, _size )
+#define FREE( _ptr ) \
+ debug_free( __FILE__, __LINE__, __FUNCTION__, _ptr )
+#define REALLOC( _ptr, _old_size, _size ) \
+ debug_realloc( __FILE__, __LINE__, __FUNCTION__, _ptr, _old_size, _size )
+
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+
+void * __stdcall
+EngAllocMem(
+ unsigned long Flags,
+ unsigned long MemSize,
+ unsigned long Tag );
+
+void __stdcall
+EngFreeMem(
+ void *Mem );
+
+#define MALLOC( _size ) EngAllocMem( 0, _size, 'D3AG' )
+#define _FREE( _ptr ) EngFreeMem( _ptr )
+
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+
+void *
+ExAllocatePool(
+ unsigned long PoolType,
+ size_t NumberOfBytes);
+
+void
+ExFreePool(void *P);
+
+#define MALLOC(_size) ExAllocatePool(0, _size)
+#define _FREE(_ptr) ExFreePool(_ptr)
+
+#else
+
+#define MALLOC( SIZE ) malloc( SIZE )
+#define CALLOC( COUNT, SIZE ) calloc( COUNT, SIZE )
+#define FREE( PTR ) free( PTR )
+
+static INLINE void *
+_REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
+{
+ (void) old_size;
+ return realloc(old_ptr, new_size);
+}
+#define REALLOC( a, b, c ) _REALLOC( a, b, c )
+#endif
+
+
+#ifndef CALLOC
+static INLINE void *
+CALLOC( unsigned count, unsigned size )
+{
+ void *ptr = MALLOC( count * size );
+ if( ptr ) {
+ memset( ptr, 0, count * size );
+ }
+ return ptr;
+}
+#endif /* !CALLOC */
+
+#ifndef FREE
+static INLINE void
+FREE( void *ptr )
+{
+ if( ptr ) {
+ _FREE( ptr );
+ }
+}
+#endif /* !FREE */
+
+#ifndef REALLOC
+static INLINE void *
+REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
+{
+ void *new_ptr = NULL;
+
+ if (new_size != 0) {
+ unsigned copy_size = old_size < new_size ? old_size : new_size;
+ new_ptr = MALLOC( new_size );
+ if (new_ptr && old_ptr && copy_size) {
+ memcpy( new_ptr, old_ptr, copy_size );
+ }
+ }
+
+ FREE( old_ptr );
+ return new_ptr;
+}
+#endif /* !REALLOC */
+
+
+#define MALLOC_STRUCT(T) (struct T *) MALLOC(sizeof(struct T))
+
+#define CALLOC_STRUCT(T) (struct T *) CALLOC(1, sizeof(struct T))
+
+#define CALLOC_VARIANT_LENGTH_STRUCT(T,more_size) ((struct T *) CALLOC(1, sizeof(struct T) + more_size))
+
+
+/**
+ * Return memory on given byte alignment
+ */
+static INLINE void *
+align_malloc(size_t bytes, uint alignment)
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+ void *mem;
+ alignment = (alignment + (uint)sizeof(void*) - 1) & ~((uint)sizeof(void*) - 1);
+ if(posix_memalign(& mem, alignment, bytes) != 0)
+ return NULL;
+ return mem;
+#else
+ char *ptr, *buf;
+
+ assert( alignment > 0 );
+
+ ptr = (char *) MALLOC(bytes + alignment + sizeof(void *));
+ if (!ptr)
+ return NULL;
+
+ buf = (char *) align_pointer( ptr + sizeof(void *), alignment );
+ *(char **)(buf - sizeof(void *)) = ptr;
+
+ return buf;
+#endif /* defined(HAVE_POSIX_MEMALIGN) */
+}
+
+/**
+ * Free memory returned by align_malloc().
+ */
+static INLINE void
+align_free(void *ptr)
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+ FREE(ptr);
+#else
+ if (ptr) {
+ void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
+ void *realAddr = *cubbyHole;
+ FREE(realAddr);
+ }
+#endif /* defined(HAVE_POSIX_MEMALIGN) */
+}
+
+
+/**
+ * Duplicate a block of memory.
+ */
+static INLINE void *
+mem_dup(const void *src, uint size)
+{
+ void *dup = MALLOC(size);
+ if (dup)
+ memcpy(dup, src, size);
+ return dup;
+}
+
+
+/**
+ * Number of elements in an array.
+ */
+#ifndef Elements
+#define Elements(x) (sizeof(x)/sizeof((x)[0]))
+#endif
+
+
+/**
+ * Offset of a field in a struct, in bytes.
+ */
+#define Offset(TYPE, MEMBER) ((unsigned)&(((TYPE *)NULL)->MEMBER))
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* U_MEMORY_H */
diff --git a/src/gallium/auxiliary/util/u_mm.c b/src/gallium/auxiliary/util/u_mm.c
new file mode 100644
index 0000000000..4b75d4ba1d
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_mm.c
@@ -0,0 +1,289 @@
+/**************************************************************************
+ *
+ * Copyright (C) 1999 Wittawat Yamwong
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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
+ * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+
+#include "util/u_memory.h"
+#include "util/u_mm.h"
+
+
+void
+u_mmDumpMemInfo(const struct mem_block *heap)
+{
+ debug_printf("Memory heap %p:\n", (void *) heap);
+ if (heap == 0) {
+ debug_printf(" heap == 0\n");
+ }
+ else {
+ const struct mem_block *p;
+
+ for (p = heap->next; p != heap; p = p->next) {
+ debug_printf(" Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size,
+ p->free ? 'F':'.',
+ p->reserved ? 'R':'.');
+ }
+
+ debug_printf("\nFree list:\n");
+
+ for (p = heap->next_free; p != heap; p = p->next_free) {
+ debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size,
+ p->free ? 'F':'.',
+ p->reserved ? 'R':'.');
+ }
+
+ }
+ debug_printf("End of memory blocks\n");
+}
+
+
+struct mem_block *
+u_mmInit(int ofs, int size)
+{
+ struct mem_block *heap, *block;
+
+ if (size <= 0)
+ return NULL;
+
+ heap = CALLOC_STRUCT(mem_block);
+ if (!heap)
+ return NULL;
+
+ block = CALLOC_STRUCT(mem_block);
+ if (!block) {
+ FREE(heap);
+ return NULL;
+ }
+
+ heap->next = block;
+ heap->prev = block;
+ heap->next_free = block;
+ heap->prev_free = block;
+
+ block->heap = heap;
+ block->next = heap;
+ block->prev = heap;
+ block->next_free = heap;
+ block->prev_free = heap;
+
+ block->ofs = ofs;
+ block->size = size;
+ block->free = 1;
+
+ return heap;
+}
+
+
+static struct mem_block *
+SliceBlock(struct mem_block *p,
+ int startofs, int size,
+ int reserved, int alignment)
+{
+ struct mem_block *newblock;
+
+ /* break left [p, newblock, p->next], then p = newblock */
+ if (startofs > p->ofs) {
+ newblock = CALLOC_STRUCT(mem_block);
+ if (!newblock)
+ return NULL;
+ newblock->ofs = startofs;
+ newblock->size = p->size - (startofs - p->ofs);
+ newblock->free = 1;
+ newblock->heap = p->heap;
+
+ newblock->next = p->next;
+ newblock->prev = p;
+ p->next->prev = newblock;
+ p->next = newblock;
+
+ newblock->next_free = p->next_free;
+ newblock->prev_free = p;
+ p->next_free->prev_free = newblock;
+ p->next_free = newblock;
+
+ p->size -= newblock->size;
+ p = newblock;
+ }
+
+ /* break right, also [p, newblock, p->next] */
+ if (size < p->size) {
+ newblock = CALLOC_STRUCT(mem_block);
+ if (!newblock)
+ return NULL;
+ newblock->ofs = startofs + size;
+ newblock->size = p->size - size;
+ newblock->free = 1;
+ newblock->heap = p->heap;
+
+ newblock->next = p->next;
+ newblock->prev = p;
+ p->next->prev = newblock;
+ p->next = newblock;
+
+ newblock->next_free = p->next_free;
+ newblock->prev_free = p;
+ p->next_free->prev_free = newblock;
+ p->next_free = newblock;
+
+ p->size = size;
+ }
+
+ /* p = middle block */
+ p->free = 0;
+
+ /* Remove p from the free list:
+ */
+ p->next_free->prev_free = p->prev_free;
+ p->prev_free->next_free = p->next_free;
+
+ p->next_free = 0;
+ p->prev_free = 0;
+
+ p->reserved = reserved;
+ return p;
+}
+
+
+struct mem_block *
+u_mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch)
+{
+ struct mem_block *p;
+ const int mask = (1 << align2)-1;
+ int startofs = 0;
+ int endofs;
+
+ assert(size >= 0);
+ assert(align2 >= 0);
+ assert(align2 <= 12); /* sanity check, 2^12 (4KB) enough? */
+
+ if (!heap || align2 < 0 || size <= 0)
+ return NULL;
+
+ for (p = heap->next_free; p != heap; p = p->next_free) {
+ assert(p->free);
+
+ startofs = (p->ofs + mask) & ~mask;
+ if ( startofs < startSearch ) {
+ startofs = startSearch;
+ }
+ endofs = startofs+size;
+ if (endofs <= (p->ofs+p->size))
+ break;
+ }
+
+ if (p == heap)
+ return NULL;
+
+ assert(p->free);
+ p = SliceBlock(p,startofs,size,0,mask+1);
+
+ return p;
+}
+
+
+struct mem_block *
+u_mmFindBlock(struct mem_block *heap, int start)
+{
+ struct mem_block *p;
+
+ for (p = heap->next; p != heap; p = p->next) {
+ if (p->ofs == start)
+ return p;
+ }
+
+ return NULL;
+}
+
+
+static INLINE int
+Join2Blocks(struct mem_block *p)
+{
+ /* XXX there should be some assertions here */
+
+ /* NOTE: heap->free == 0 */
+
+ if (p->free && p->next->free) {
+ struct mem_block *q = p->next;
+
+ assert(p->ofs + p->size == q->ofs);
+ p->size += q->size;
+
+ p->next = q->next;
+ q->next->prev = p;
+
+ q->next_free->prev_free = q->prev_free;
+ q->prev_free->next_free = q->next_free;
+
+ FREE(q);
+ return 1;
+ }
+ return 0;
+}
+
+int
+u_mmFreeMem(struct mem_block *b)
+{
+ if (!b)
+ return 0;
+
+ if (b->free) {
+ debug_printf("block already free\n");
+ return -1;
+ }
+ if (b->reserved) {
+ debug_printf("block is reserved\n");
+ return -1;
+ }
+
+ b->free = 1;
+ b->next_free = b->heap->next_free;
+ b->prev_free = b->heap;
+ b->next_free->prev_free = b;
+ b->prev_free->next_free = b;
+
+ Join2Blocks(b);
+ if (b->prev != b->heap)
+ Join2Blocks(b->prev);
+
+ return 0;
+}
+
+
+void
+u_mmDestroy(struct mem_block *heap)
+{
+ struct mem_block *p;
+
+ if (!heap)
+ return;
+
+ for (p = heap->next; p != heap; ) {
+ struct mem_block *next = p->next;
+ FREE(p);
+ p = next;
+ }
+
+ FREE(heap);
+}
diff --git a/src/gallium/auxiliary/util/u_mm.h b/src/gallium/auxiliary/util/u_mm.h
new file mode 100644
index 0000000000..6b158aae6e
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_mm.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+ *
+ * Copyright (C) 1999 Wittawat Yamwong
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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
+ * Memory manager code. Primarily used by device drivers to manage texture
+ * heaps, etc.
+ */
+
+
+#ifndef _U_MM_H_
+#define _U_MM_H_
+
+
+struct mem_block {
+ struct mem_block *next, *prev;
+ struct mem_block *next_free, *prev_free;
+ struct mem_block *heap;
+ int ofs,size;
+ unsigned int free:1;
+ unsigned int reserved:1;
+};
+
+
+
+/**
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+extern struct mem_block *u_mmInit(int ofs, int size);
+
+/**
+ * Allocate 'size' bytes with 2^align2 bytes alignment,
+ * restrict the search to free memory after 'startSearch'
+ * depth and back buffers should be in different 4mb banks
+ * to get better page hits if possible
+ * input: size = size of block
+ * align2 = 2^align2 bytes alignment
+ * startSearch = linear offset from start of heap to begin search
+ * return: pointer to the allocated block, 0 if error
+ */
+extern struct mem_block *u_mmAllocMem(struct mem_block *heap, int size, int align2,
+ int startSearch);
+
+/**
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+extern int u_mmFreeMem(struct mem_block *b);
+
+/**
+ * Free block starts at offset
+ * input: pointer to a heap, start offset
+ * return: pointer to a block
+ */
+extern struct mem_block *u_mmFindBlock(struct mem_block *heap, int start);
+
+/**
+ * destroy MM
+ */
+extern void u_mmDestroy(struct mem_block *mmInit);
+
+/**
+ * For debugging purposes.
+ */
+extern void u_mmDumpMemInfo(const struct mem_block *mmInit);
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_network.c b/src/gallium/auxiliary/util/u_network.c
new file mode 100644
index 0000000000..bc4b758406
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_network.c
@@ -0,0 +1,188 @@
+
+#include "pipe/p_compiler.h"
+#include "util/u_network.h"
+#include "util/u_debug.h"
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+# include <winsock2.h>
+# include <windows.h>
+#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU)
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <unistd.h>
+# include <fcntl.h>
+# include <netdb.h>
+#else
+# warning "No socket implementation"
+#endif
+
+boolean
+u_socket_init()
+{
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
+ wVersionRequested = MAKEWORD(1, 1);
+
+ err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0) {
+ debug_printf("WSAStartup failed with error: %d\n", err);
+ return FALSE;
+ }
+ return TRUE;
+#elif defined(PIPE_HAVE_SOCKETS)
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+void
+u_socket_stop()
+{
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ WSACleanup();
+#endif
+}
+
+void
+u_socket_close(int s)
+{
+ if (s < 0)
+ return;
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU)
+ shutdown(s, SHUT_RDWR);
+ close(s);
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ shutdown(s, SD_BOTH);
+ closesocket(s);
+#else
+ assert(0);
+#endif
+}
+
+int u_socket_accept(int s)
+{
+#if defined(PIPE_HAVE_SOCKETS)
+ return accept(s, NULL, NULL);
+#else
+ return -1;
+#endif
+}
+
+int
+u_socket_send(int s, void *data, size_t size)
+{
+#if defined(PIPE_HAVE_SOCKETS)
+ return send(s, data, size, 0);
+#else
+ return -1;
+#endif
+}
+
+int
+u_socket_peek(int s, void *data, size_t size)
+{
+#if defined(PIPE_HAVE_SOCKETS)
+ return recv(s, data, size, MSG_PEEK);
+#else
+ return -1;
+#endif
+}
+
+int
+u_socket_recv(int s, void *data, size_t size)
+{
+#if defined(PIPE_HAVE_SOCKETS)
+ return recv(s, data, size, 0);
+#else
+ return -1;
+#endif
+}
+
+int
+u_socket_connect(const char *hostname, uint16_t port)
+{
+#if defined(PIPE_HAVE_SOCKETS)
+ int s;
+ struct sockaddr_in sa;
+ struct hostent *host = NULL;
+
+ memset(&sa, 0, sizeof(struct sockaddr_in));
+ host = gethostbyname(hostname);
+ if (!host)
+ return -1;
+
+ memcpy((char *)&sa.sin_addr,host->h_addr,host->h_length);
+ sa.sin_family= host->h_addrtype;
+ sa.sin_port = htons(port);
+
+ s = socket(host->h_addrtype, SOCK_STREAM, IPPROTO_TCP);
+ if (s < 0)
+ return -1;
+
+ if (connect(s, (struct sockaddr *)&sa, sizeof(sa))) {
+ u_socket_close(s);
+ return -1;
+ }
+
+ return s;
+#else
+ assert(0);
+ return -1;
+#endif
+}
+
+int
+u_socket_listen_on_port(uint16_t portnum)
+{
+#if defined(PIPE_HAVE_SOCKETS)
+ int s;
+ struct sockaddr_in sa;
+ memset(&sa, 0, sizeof(struct sockaddr_in));
+
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(portnum);
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (s < 0)
+ return -1;
+
+ if (bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1) {
+ u_socket_close(s);
+ return -1;
+ }
+
+ listen(s, 0);
+
+ return s;
+#else
+ assert(0);
+ return -1;
+#endif
+}
+
+void
+u_socket_block(int s, boolean block)
+{
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU)
+ int old = fcntl(s, F_GETFL, 0);
+ if (old == -1)
+ return;
+
+ /* TODO obey block */
+ if (block)
+ fcntl(s, F_SETFL, old & ~O_NONBLOCK);
+ else
+ fcntl(s, F_SETFL, old | O_NONBLOCK);
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ u_long iMode = block ? 0 : 1;
+ ioctlsocket(s, FIONBIO, &iMode);
+#else
+ assert(0);
+#endif
+}
diff --git a/src/gallium/auxiliary/util/u_network.h b/src/gallium/auxiliary/util/u_network.h
new file mode 100644
index 0000000000..8c778f492c
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_network.h
@@ -0,0 +1,24 @@
+
+#ifndef _U_NETWORK_H_
+#define _U_NETWORK_H_
+
+#include "pipe/p_compiler.h"
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+# define PIPE_HAVE_SOCKETS
+#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU)
+# define PIPE_HAVE_SOCKETS
+#endif
+
+boolean u_socket_init(void);
+void u_socket_stop(void);
+void u_socket_close(int s);
+int u_socket_listen_on_port(uint16_t portnum);
+int u_socket_accept(int s);
+int u_socket_connect(const char *host, uint16_t port);
+int u_socket_send(int s, void *data, size_t size);
+int u_socket_peek(int s, void *data, size_t size);
+int u_socket_recv(int s, void *data, size_t size);
+void u_socket_block(int s, boolean block);
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h
new file mode 100644
index 0000000000..eda883b3b9
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_pack_color.h
@@ -0,0 +1,502 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Functions to produce packed colors/Z from floats.
+ */
+
+
+#ifndef U_PACK_COLOR_H
+#define U_PACK_COLOR_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "util/u_math.h"
+
+
+/**
+ * Pack ubyte R,G,B,A into dest pixel.
+ */
+static INLINE void
+util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a,
+ enum pipe_format format, void *dest)
+{
+ switch (format) {
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (r << 24) | (g << 16) | (b << 8) | a;
+ }
+ return;
+ case PIPE_FORMAT_R8G8B8X8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (r << 24) | (g << 16) | (b << 8) | 0xff;
+ }
+ return;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ return;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (0xff << 24) | (r << 16) | (g << 8) | b;
+ }
+ return;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (b << 24) | (g << 16) | (r << 8) | a;
+ }
+ return;
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (b << 24) | (g << 16) | (r << 8) | 0xff;
+ }
+ return;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ {
+ ushort *d = (ushort *) dest;
+ *d = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
+ }
+ return;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ {
+ ushort *d = (ushort *) dest;
+ *d = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
+ }
+ return;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ {
+ ushort *d = (ushort *) dest;
+ *d = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
+ }
+ return;
+ case PIPE_FORMAT_A8_UNORM:
+ {
+ ubyte *d = (ubyte *) dest;
+ *d = a;
+ }
+ return;
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ {
+ ubyte *d = (ubyte *) dest;
+ *d = r;
+ }
+ return;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ {
+ float *d = (float *) dest;
+ d[0] = (float)r / 255.0f;
+ d[1] = (float)g / 255.0f;
+ d[2] = (float)b / 255.0f;
+ d[3] = (float)a / 255.0f;
+ }
+ return;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ {
+ float *d = (float *) dest;
+ d[0] = (float)r / 255.0f;
+ d[1] = (float)g / 255.0f;
+ d[2] = (float)b / 255.0f;
+ }
+ return;
+
+ /* XXX lots more cases to add */
+ default:
+ debug_print_format("gallium: unhandled format in util_pack_color_ub()", format);
+ assert(0);
+ }
+}
+
+
+/**
+ * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255].
+ */
+static INLINE void
+util_unpack_color_ub(enum pipe_format format, const void *src,
+ ubyte *r, ubyte *g, ubyte *b, ubyte *a)
+{
+ switch (format) {
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ {
+ uint p = ((const uint *) src)[0];
+ *r = (ubyte) ((p >> 24) & 0xff);
+ *g = (ubyte) ((p >> 16) & 0xff);
+ *b = (ubyte) ((p >> 8) & 0xff);
+ *a = (ubyte) ((p >> 0) & 0xff);
+ }
+ return;
+ case PIPE_FORMAT_R8G8B8X8_UNORM:
+ {
+ uint p = ((const uint *) src)[0];
+ *r = (ubyte) ((p >> 24) & 0xff);
+ *g = (ubyte) ((p >> 16) & 0xff);
+ *b = (ubyte) ((p >> 8) & 0xff);
+ *a = (ubyte) 0xff;
+ }
+ return;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ {
+ uint p = ((const uint *) src)[0];
+ *r = (ubyte) ((p >> 16) & 0xff);
+ *g = (ubyte) ((p >> 8) & 0xff);
+ *b = (ubyte) ((p >> 0) & 0xff);
+ *a = (ubyte) ((p >> 24) & 0xff);
+ }
+ return;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ {
+ uint p = ((const uint *) src)[0];
+ *r = (ubyte) ((p >> 16) & 0xff);
+ *g = (ubyte) ((p >> 8) & 0xff);
+ *b = (ubyte) ((p >> 0) & 0xff);
+ *a = (ubyte) 0xff;
+ }
+ return;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ {
+ uint p = ((const uint *) src)[0];
+ *r = (ubyte) ((p >> 8) & 0xff);
+ *g = (ubyte) ((p >> 16) & 0xff);
+ *b = (ubyte) ((p >> 24) & 0xff);
+ *a = (ubyte) ((p >> 0) & 0xff);
+ }
+ return;
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ {
+ uint p = ((const uint *) src)[0];
+ *r = (ubyte) ((p >> 8) & 0xff);
+ *g = (ubyte) ((p >> 16) & 0xff);
+ *b = (ubyte) ((p >> 24) & 0xff);
+ *a = (ubyte) 0xff;
+ }
+ return;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ {
+ ushort p = ((const ushort *) src)[0];
+ *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7));
+ *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3));
+ *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
+ *a = (ubyte) 0xff;
+ }
+ return;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ {
+ ushort p = ((const ushort *) src)[0];
+ *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
+ *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
+ *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
+ *a = (ubyte) (0xff * (p >> 15));
+ }
+ return;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ {
+ ushort p = ((const ushort *) src)[0];
+ *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf));
+ *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf));
+ *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf));
+ *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf));
+ }
+ return;
+ case PIPE_FORMAT_A8_UNORM:
+ {
+ ubyte p = ((const ubyte *) src)[0];
+ *r = *g = *b = (ubyte) 0xff;
+ *a = p;
+ }
+ return;
+ case PIPE_FORMAT_L8_UNORM:
+ {
+ ubyte p = ((const ubyte *) src)[0];
+ *r = *g = *b = p;
+ *a = (ubyte) 0xff;
+ }
+ return;
+ case PIPE_FORMAT_I8_UNORM:
+ {
+ ubyte p = ((const ubyte *) src)[0];
+ *r = *g = *b = *a = p;
+ }
+ return;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ {
+ const float *p = (const float *) src;
+ *r = float_to_ubyte(p[0]);
+ *g = float_to_ubyte(p[1]);
+ *b = float_to_ubyte(p[2]);
+ *a = float_to_ubyte(p[3]);
+ }
+ return;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ {
+ const float *p = (const float *) src;
+ *r = float_to_ubyte(p[0]);
+ *g = float_to_ubyte(p[1]);
+ *b = float_to_ubyte(p[2]);
+ *a = (ubyte) 0xff;
+ }
+ return;
+
+ case PIPE_FORMAT_R32G32_FLOAT:
+ {
+ const float *p = (const float *) src;
+ *r = float_to_ubyte(p[0]);
+ *g = float_to_ubyte(p[1]);
+ *b = *a = (ubyte) 0xff;
+ }
+ return;
+
+ case PIPE_FORMAT_R32_FLOAT:
+ {
+ const float *p = (const float *) src;
+ *r = float_to_ubyte(p[0]);
+ *g = *b = *a = (ubyte) 0xff;
+ }
+ return;
+
+ /* XXX lots more cases to add */
+ default:
+ debug_print_format("gallium: unhandled format in util_unpack_color_ub()",
+ format);
+ assert(0);
+ }
+}
+
+
+
+/**
+ * Note rgba outside [0,1] will be clamped for int pixel formats.
+ */
+static INLINE void
+util_pack_color(const float rgba[4], enum pipe_format format, void *dest)
+{
+ ubyte r, g, b, a;
+
+ if (pf_size_x(format) <= 8) {
+ /* format uses 8-bit components or less */
+ r = float_to_ubyte(rgba[0]);
+ g = float_to_ubyte(rgba[1]);
+ b = float_to_ubyte(rgba[2]);
+ a = float_to_ubyte(rgba[3]);
+ }
+
+ switch (format) {
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (r << 24) | (g << 16) | (b << 8) | a;
+ }
+ return;
+ case PIPE_FORMAT_R8G8B8X8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (r << 24) | (g << 16) | (b << 8) | 0xff;
+ }
+ return;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ return;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (0xff << 24) | (r << 16) | (g << 8) | b;
+ }
+ return;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (b << 24) | (g << 16) | (r << 8) | a;
+ }
+ return;
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ {
+ uint *d = (uint *) dest;
+ *d = (b << 24) | (g << 16) | (r << 8) | 0xff;
+ }
+ return;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ {
+ ushort *d = (ushort *) dest;
+ *d = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
+ }
+ return;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ {
+ ushort *d = (ushort *) dest;
+ *d = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
+ }
+ return;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ {
+ ushort *d = (ushort *) dest;
+ *d = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
+ }
+ return;
+ case PIPE_FORMAT_A8_UNORM:
+ {
+ ubyte *d = (ubyte *) dest;
+ *d = a;
+ }
+ return;
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ {
+ ubyte *d = (ubyte *) dest;
+ *d = r;
+ }
+ return;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ {
+ float *d = (float *) dest;
+ d[0] = rgba[0];
+ d[1] = rgba[1];
+ d[2] = rgba[2];
+ d[3] = rgba[3];
+ }
+ return;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ {
+ float *d = (float *) dest;
+ d[0] = rgba[0];
+ d[1] = rgba[1];
+ d[2] = rgba[2];
+ }
+ return;
+ /* XXX lots more cases to add */
+ default:
+ debug_print_format("gallium: unhandled format in util_pack_color()", format);
+ assert(0);
+ }
+}
+
+
+/**
+ * Note: it's assumed that z is in [0,1]
+ */
+static INLINE uint
+util_pack_z(enum pipe_format format, double z)
+{
+ if (z == 0.0)
+ return 0;
+
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ if (z == 1.0)
+ return 0xffff;
+ return (uint) (z * 0xffff);
+ case PIPE_FORMAT_Z32_UNORM:
+ /* special-case to avoid overflow */
+ if (z == 1.0)
+ return 0xffffffff;
+ return (uint) (z * 0xffffffff);
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ if (z == 1.0)
+ return 0xffffff;
+ return (uint) (z * 0xffffff);
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ if (z == 1.0)
+ return 0xffffff00;
+ return ((uint) (z * 0xffffff)) << 8;
+ case PIPE_FORMAT_S8_UNORM:
+ /* this case can get it via util_pack_z_stencil() */
+ return 0;
+ default:
+ debug_print_format("gallium: unhandled format in util_pack_z()", format);
+ assert(0);
+ return 0;
+ }
+}
+
+
+/**
+ * Pack Z and/or stencil values into a 32-bit value described by format.
+ * Note: it's assumed that z is in [0,1] and s in [0,255]
+ */
+static INLINE uint
+util_pack_z_stencil(enum pipe_format format, double z, uint s)
+{
+ unsigned packed = util_pack_z(format, z);
+
+ switch (format) {
+ case PIPE_FORMAT_S8Z24_UNORM:
+ packed |= s << 24;
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ packed |= s;
+ break;
+ case PIPE_FORMAT_S8_UNORM:
+ packed |= s;
+ break;
+ default:
+ break;
+ }
+
+ return packed;
+}
+
+
+/**
+ * Pack 4 ubytes into a 4-byte word
+ */
+static INLINE unsigned
+pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3)
+{
+ return ((((unsigned int)b0) << 0) |
+ (((unsigned int)b1) << 8) |
+ (((unsigned int)b2) << 16) |
+ (((unsigned int)b3) << 24));
+}
+
+
+/**
+ * Pack/convert 4 floats into one 4-byte word.
+ */
+static INLINE unsigned
+pack_ui32_float4(float a, float b, float c, float d)
+{
+ return pack_ub4( float_to_ubyte(a),
+ float_to_ubyte(b),
+ float_to_ubyte(c),
+ float_to_ubyte(d) );
+}
+
+
+
+#endif /* U_PACK_COLOR_H */
diff --git a/src/gallium/auxiliary/util/u_pointer.h b/src/gallium/auxiliary/util/u_pointer.h
new file mode 100644
index 0000000000..e1af9f11cb
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_pointer.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_POINTER_H
+#define U_POINTER_H
+
+#include "pipe/p_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static INLINE intptr_t
+pointer_to_intptr( const void *p )
+{
+ union {
+ const void *p;
+ intptr_t i;
+ } pi;
+ pi.p = p;
+ return pi.i;
+}
+
+static INLINE void *
+intptr_to_pointer( intptr_t i )
+{
+ union {
+ void *p;
+ intptr_t i;
+ } pi;
+ pi.i = i;
+ return pi.p;
+}
+
+static INLINE uintptr_t
+pointer_to_uintptr( const void *ptr )
+{
+ union {
+ const void *p;
+ uintptr_t u;
+ } pu;
+ pu.p = ptr;
+ return pu.u;
+}
+
+static INLINE void *
+uintptr_to_pointer( uintptr_t u )
+{
+ union {
+ void *p;
+ uintptr_t u;
+ } pu;
+ pu.u = u;
+ return pu.p;
+}
+
+/**
+ * Return a pointer aligned to next multiple of N bytes.
+ */
+static INLINE void *
+align_pointer( const void *unaligned, uintptr_t alignment )
+{
+ uintptr_t aligned = (pointer_to_uintptr( unaligned ) + alignment - 1) & ~(alignment - 1);
+ return uintptr_to_pointer( aligned );
+}
+
+
+/**
+ * Return a pointer aligned to next multiple of 16 bytes.
+ */
+static INLINE void *
+align16( void *unaligned )
+{
+ return align_pointer( unaligned, 16 );
+}
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_POINTER_H */
diff --git a/src/gallium/auxiliary/util/u_prim.h b/src/gallium/auxiliary/util/u_prim.h
new file mode 100644
index 0000000000..a9b533eea7
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_prim.h
@@ -0,0 +1,138 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef U_BLIT_H
+#define U_BLIT_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pipe/p_defines.h"
+
+static INLINE boolean u_validate_pipe_prim( unsigned pipe_prim, unsigned nr )
+{
+ boolean ok = TRUE;
+
+ switch (pipe_prim) {
+ case PIPE_PRIM_POINTS:
+ ok = (nr >= 1);
+ break;
+ case PIPE_PRIM_LINES:
+ ok = (nr >= 2);
+ break;
+ case PIPE_PRIM_LINE_STRIP:
+ case PIPE_PRIM_LINE_LOOP:
+ ok = (nr >= 2);
+ break;
+ case PIPE_PRIM_TRIANGLES:
+ ok = (nr >= 3);
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ case PIPE_PRIM_TRIANGLE_FAN:
+ case PIPE_PRIM_POLYGON:
+ ok = (nr >= 3);
+ break;
+ case PIPE_PRIM_QUADS:
+ ok = (nr >= 4);
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ ok = (nr >= 4);
+ break;
+ default:
+ ok = 0;
+ break;
+ }
+
+ return ok;
+}
+
+
+static INLINE boolean u_trim_pipe_prim( unsigned pipe_prim, unsigned *nr )
+{
+ boolean ok = TRUE;
+
+ switch (pipe_prim) {
+ case PIPE_PRIM_POINTS:
+ ok = (*nr >= 1);
+ break;
+ case PIPE_PRIM_LINES:
+ ok = (*nr >= 2);
+ *nr -= (*nr % 2);
+ break;
+ case PIPE_PRIM_LINE_STRIP:
+ case PIPE_PRIM_LINE_LOOP:
+ ok = (*nr >= 2);
+ break;
+ case PIPE_PRIM_TRIANGLES:
+ ok = (*nr >= 3);
+ *nr -= (*nr % 3);
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ case PIPE_PRIM_TRIANGLE_FAN:
+ case PIPE_PRIM_POLYGON:
+ ok = (*nr >= 3);
+ break;
+ case PIPE_PRIM_QUADS:
+ ok = (*nr >= 4);
+ *nr -= (*nr % 4);
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ ok = (*nr >= 4);
+ *nr -= (*nr % 2);
+ break;
+ default:
+ ok = 0;
+ break;
+ }
+
+ if (!ok)
+ *nr = 0;
+
+ return ok;
+}
+
+
+static INLINE unsigned u_reduced_prim( unsigned pipe_prim )
+{
+ switch (pipe_prim) {
+ case PIPE_PRIM_POINTS:
+ return PIPE_PRIM_POINTS;
+
+ case PIPE_PRIM_LINES:
+ case PIPE_PRIM_LINE_STRIP:
+ case PIPE_PRIM_LINE_LOOP:
+ return PIPE_PRIM_LINES;
+
+ default:
+ return PIPE_PRIM_TRIANGLES;
+ }
+}
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_rect.c b/src/gallium/auxiliary/util/u_rect.c
new file mode 100644
index 0000000000..9866b6fc8a
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_rect.c
@@ -0,0 +1,301 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Rectangle-related helper functions.
+ */
+
+
+#include "pipe/p_defines.h"
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "util/u_rect.h"
+
+
+/**
+ * Copy 2D rect from one place to another.
+ * Position and sizes are in pixels.
+ * src_pitch may be negative to do vertical flip of pixels from source.
+ */
+void
+util_copy_rect(ubyte * dst,
+ const struct pipe_format_block *block,
+ unsigned dst_stride,
+ unsigned dst_x,
+ unsigned dst_y,
+ unsigned width,
+ unsigned height,
+ const ubyte * src,
+ int src_stride,
+ unsigned src_x,
+ int src_y)
+{
+ unsigned i;
+ int src_stride_pos = src_stride < 0 ? -src_stride : src_stride;
+
+ assert(block->size > 0);
+ assert(block->width > 0);
+ assert(block->height > 0);
+ assert(src_x >= 0);
+ assert(src_y >= 0);
+ assert(dst_x >= 0);
+ assert(dst_y >= 0);
+
+ dst_x /= block->width;
+ dst_y /= block->height;
+ width = (width + block->width - 1)/block->width;
+ height = (height + block->height - 1)/block->height;
+ src_x /= block->width;
+ src_y /= block->height;
+
+ dst += dst_x * block->size;
+ src += src_x * block->size;
+ dst += dst_y * dst_stride;
+ src += src_y * src_stride_pos;
+ width *= block->size;
+
+ if (width == dst_stride && width == src_stride)
+ memcpy(dst, src, height * width);
+ else {
+ for (i = 0; i < height; i++) {
+ memcpy(dst, src, width);
+ dst += dst_stride;
+ src += src_stride;
+ }
+ }
+}
+
+void
+util_fill_rect(ubyte * dst,
+ const struct pipe_format_block *block,
+ unsigned dst_stride,
+ unsigned dst_x,
+ unsigned dst_y,
+ unsigned width,
+ unsigned height,
+ uint32_t value)
+{
+ unsigned i, j;
+ unsigned width_size;
+
+ assert(block->size > 0);
+ assert(block->width > 0);
+ assert(block->height > 0);
+ assert(dst_x >= 0);
+ assert(dst_y >= 0);
+
+ dst_x /= block->width;
+ dst_y /= block->height;
+ width = (width + block->width - 1)/block->width;
+ height = (height + block->height - 1)/block->height;
+
+ dst += dst_x * block->size;
+ dst += dst_y * dst_stride;
+ width_size = width * block->size;
+
+ switch (block->size) {
+ case 1:
+ if(dst_stride == width_size)
+ memset(dst, (ubyte) value, height * width_size);
+ else {
+ for (i = 0; i < height; i++) {
+ memset(dst, (ubyte) value, width_size);
+ dst += dst_stride;
+ }
+ }
+ break;
+ case 2:
+ for (i = 0; i < height; i++) {
+ uint16_t *row = (uint16_t *)dst;
+ for (j = 0; j < width; j++)
+ *row++ = (uint16_t) value;
+ dst += dst_stride;
+ }
+ break;
+ case 4:
+ for (i = 0; i < height; i++) {
+ uint32_t *row = (uint32_t *)dst;
+ for (j = 0; j < width; j++)
+ *row++ = value;
+ dst += dst_stride;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+
+
+/**
+ * Fallback function for pipe->surface_copy().
+ * Note: (X,Y)=(0,0) is always the upper-left corner.
+ * if do_flip, flip the image vertically on its way from src rect to dst rect.
+ * XXX should probably put this in new u_surface.c file...
+ */
+void
+util_surface_copy(struct pipe_context *pipe,
+ boolean do_flip,
+ struct pipe_surface *dst,
+ unsigned dst_x, unsigned dst_y,
+ struct pipe_surface *src,
+ unsigned src_x, unsigned src_y,
+ unsigned w, unsigned h)
+{
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_transfer *src_trans, *dst_trans;
+ void *dst_map;
+ const void *src_map;
+
+ assert(src->texture && dst->texture);
+ if (!src->texture || !dst->texture)
+ return;
+ src_trans = screen->get_tex_transfer(screen,
+ src->texture,
+ src->face,
+ src->level,
+ src->zslice,
+ PIPE_TRANSFER_READ,
+ src_x, src_y, w, h);
+
+ dst_trans = screen->get_tex_transfer(screen,
+ dst->texture,
+ dst->face,
+ dst->level,
+ dst->zslice,
+ PIPE_TRANSFER_WRITE,
+ dst_x, dst_y, w, h);
+
+ assert(dst_trans->block.size == src_trans->block.size);
+ assert(dst_trans->block.width == src_trans->block.width);
+ assert(dst_trans->block.height == src_trans->block.height);
+
+ src_map = pipe->screen->transfer_map(screen, src_trans);
+ dst_map = pipe->screen->transfer_map(screen, dst_trans);
+
+ assert(src_map);
+ assert(dst_map);
+
+ if (src_map && dst_map) {
+ /* If do_flip, invert src_y position and pass negative src stride */
+ util_copy_rect(dst_map,
+ &dst_trans->block,
+ dst_trans->stride,
+ 0, 0,
+ w, h,
+ src_map,
+ do_flip ? -(int) src_trans->stride : src_trans->stride,
+ 0,
+ do_flip ? h - 1 : 0);
+ }
+
+ pipe->screen->transfer_unmap(pipe->screen, src_trans);
+ pipe->screen->transfer_unmap(pipe->screen, dst_trans);
+
+ screen->tex_transfer_destroy(src_trans);
+ screen->tex_transfer_destroy(dst_trans);
+}
+
+
+
+#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
+
+
+/**
+ * Fallback for pipe->surface_fill() function.
+ * XXX should probably put this in new u_surface.c file...
+ */
+void
+util_surface_fill(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height, unsigned value)
+{
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_transfer *dst_trans;
+ void *dst_map;
+
+ assert(dst->texture);
+ if (!dst->texture)
+ return;
+ dst_trans = screen->get_tex_transfer(screen,
+ dst->texture,
+ dst->face,
+ dst->level,
+ dst->zslice,
+ PIPE_TRANSFER_WRITE,
+ dstx, dsty, width, height);
+
+ dst_map = pipe->screen->transfer_map(screen, dst_trans);
+
+ assert(dst_map);
+
+ if (dst_map) {
+ assert(dst_trans->stride > 0);
+
+ switch (dst_trans->block.size) {
+ case 1:
+ case 2:
+ case 4:
+ util_fill_rect(dst_map, &dst_trans->block, dst_trans->stride,
+ 0, 0, width, height, value);
+ break;
+ case 8:
+ {
+ /* expand the 4-byte clear value to an 8-byte value */
+ ushort *row = (ushort *) dst_map;
+ ushort val0 = UBYTE_TO_USHORT((value >> 0) & 0xff);
+ ushort val1 = UBYTE_TO_USHORT((value >> 8) & 0xff);
+ ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
+ ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
+ unsigned i, j;
+ val0 = (val0 << 8) | val0;
+ val1 = (val1 << 8) | val1;
+ val2 = (val2 << 8) | val2;
+ val3 = (val3 << 8) | val3;
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ row[j*4+0] = val0;
+ row[j*4+1] = val1;
+ row[j*4+2] = val2;
+ row[j*4+3] = val3;
+ }
+ row += dst_trans->stride/2;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+
+ pipe->screen->transfer_unmap(pipe->screen, dst_trans);
+ screen->tex_transfer_destroy(dst_trans);
+}
diff --git a/src/gallium/auxiliary/util/u_rect.h b/src/gallium/auxiliary/util/u_rect.h
new file mode 100644
index 0000000000..daa50834d3
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_rect.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Pipe copy/fill rect helpers.
+ */
+
+
+#ifndef U_RECT_H
+#define U_RECT_H
+
+
+#include "pipe/p_format.h"
+
+struct pipe_context;
+struct pipe_surface;
+
+
+extern void
+util_copy_rect(ubyte * dst, const struct pipe_format_block *block,
+ unsigned dst_stride, unsigned dst_x, unsigned dst_y,
+ unsigned width, unsigned height, const ubyte * src,
+ int src_stride, unsigned src_x, int src_y);
+
+extern void
+util_fill_rect(ubyte * dst, const struct pipe_format_block *block,
+ unsigned dst_stride, unsigned dst_x, unsigned dst_y,
+ unsigned width, unsigned height, uint32_t value);
+
+
+extern void
+util_surface_copy(struct pipe_context *pipe,
+ boolean do_flip,
+ struct pipe_surface *dst,
+ unsigned dst_x, unsigned dst_y,
+ struct pipe_surface *src,
+ unsigned src_x, unsigned src_y,
+ unsigned w, unsigned h);
+
+extern void
+util_surface_fill(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height, unsigned value);
+
+
+#endif /* U_RECT_H */
diff --git a/src/gallium/auxiliary/util/u_simple_list.h b/src/gallium/auxiliary/util/u_simple_list.h
new file mode 100644
index 0000000000..f5f43b0faa
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_simple_list.h
@@ -0,0 +1,197 @@
+/**
+ * \file simple_list.h
+ * Simple macros for type-safe, intrusive lists.
+ *
+ * Intended to work with a list sentinal which is created as an empty
+ * list. Insert & delete are O(1).
+ *
+ * \author
+ * (C) 1997, Keith Whitwell
+ */
+
+/*
+ * 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 _U_SIMPLE_LIST_H_
+#define _U_SIMPLE_LIST_H_
+
+/**
+ * Remove an element from list.
+ *
+ * \param elem element to remove.
+ */
+#define remove_from_list(elem) \
+do { \
+ (elem)->next->prev = (elem)->prev; \
+ (elem)->prev->next = (elem)->next; \
+} while (0)
+
+/**
+ * Insert an element to the list head.
+ *
+ * \param list list.
+ * \param elem element to insert.
+ */
+#define insert_at_head(list, elem) \
+do { \
+ (elem)->prev = list; \
+ (elem)->next = (list)->next; \
+ (list)->next->prev = elem; \
+ (list)->next = elem; \
+} while(0)
+
+/**
+ * Insert an element to the list tail.
+ *
+ * \param list list.
+ * \param elem element to insert.
+ */
+#define insert_at_tail(list, elem) \
+do { \
+ (elem)->next = list; \
+ (elem)->prev = (list)->prev; \
+ (list)->prev->next = elem; \
+ (list)->prev = elem; \
+} while(0)
+
+/**
+ * Move an element to the list head.
+ *
+ * \param list list.
+ * \param elem element to move.
+ */
+#define move_to_head(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_head(list, elem); \
+} while (0)
+
+/**
+ * Move an element to the list tail.
+ *
+ * \param list list.
+ * \param elem element to move.
+ */
+#define move_to_tail(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_tail(list, elem); \
+} while (0)
+
+/**
+ * Make a empty list empty.
+ *
+ * \param sentinal list (sentinal element).
+ */
+#define make_empty_list(sentinal) \
+do { \
+ (sentinal)->next = sentinal; \
+ (sentinal)->prev = sentinal; \
+} while (0)
+
+/**
+ * Get list first element.
+ *
+ * \param list list.
+ *
+ * \return pointer to first element.
+ */
+#define first_elem(list) ((list)->next)
+
+/**
+ * Get list last element.
+ *
+ * \param list list.
+ *
+ * \return pointer to last element.
+ */
+#define last_elem(list) ((list)->prev)
+
+/**
+ * Get next element.
+ *
+ * \param elem element.
+ *
+ * \return pointer to next element.
+ */
+#define next_elem(elem) ((elem)->next)
+
+/**
+ * Get previous element.
+ *
+ * \param elem element.
+ *
+ * \return pointer to previous element.
+ */
+#define prev_elem(elem) ((elem)->prev)
+
+/**
+ * Test whether element is at end of the list.
+ *
+ * \param list list.
+ * \param elem element.
+ *
+ * \return non-zero if element is at end of list, or zero otherwise.
+ */
+#define at_end(list, elem) ((elem) == (list))
+
+/**
+ * Test if a list is empty.
+ *
+ * \param list list.
+ *
+ * \return non-zero if list empty, or zero otherwise.
+ */
+#define is_empty_list(list) ((list)->next == (list))
+
+/**
+ * Walk through the elements of a list.
+ *
+ * \param ptr pointer to the current element.
+ * \param list list.
+ *
+ * \note It should be followed by a { } block or a single statement, as in a \c
+ * for loop.
+ */
+#define foreach(ptr, list) \
+ for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next )
+
+/**
+ * Walk through the elements of a list.
+ *
+ * Same as #foreach but lets you unlink the current value during a list
+ * traversal. Useful for freeing a list, element by element.
+ *
+ * \param ptr pointer to the current element.
+ * \param t temporary pointer.
+ * \param list list.
+ *
+ * \note It should be followed by a { } block or a single statement, as in a \c
+ * for loop.
+ */
+#define foreach_s(ptr, t, list) \
+ for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
+
+#endif /* _U_SIMPLE_LIST_H_ */
diff --git a/src/gallium/auxiliary/util/u_simple_screen.c b/src/gallium/auxiliary/util/u_simple_screen.c
new file mode 100644
index 0000000000..5238299015
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_simple_screen.c
@@ -0,0 +1,153 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "u_simple_screen.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+
+static struct pipe_buffer *
+pass_buffer_create(struct pipe_screen *screen,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct pipe_buffer *buffer =
+ screen->winsys->buffer_create(screen->winsys, alignment, usage, size);
+
+ buffer->screen = screen;
+
+ return buffer;
+}
+
+static struct pipe_buffer *
+pass_user_buffer_create(struct pipe_screen *screen,
+ void *ptr,
+ unsigned bytes)
+{
+ struct pipe_buffer *buffer =
+ screen->winsys->user_buffer_create(screen->winsys, ptr, bytes);
+
+ buffer->screen = screen;
+
+ return buffer;
+}
+
+static struct pipe_buffer *
+pass_surface_buffer_create(struct pipe_screen *screen,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ struct pipe_buffer *buffer =
+ screen->winsys->surface_buffer_create(screen->winsys, width, height,
+ format, usage, tex_usage, stride);
+
+ buffer->screen = screen;
+
+ return buffer;
+}
+
+static void *
+pass_buffer_map(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned usage)
+{
+ return screen->winsys->buffer_map(screen->winsys, buf, usage);
+}
+
+static void
+pass_buffer_unmap(struct pipe_screen *screen,
+ struct pipe_buffer *buf)
+{
+ screen->winsys->buffer_unmap(screen->winsys, buf);
+}
+
+static void
+pass_buffer_destroy(struct pipe_buffer *buf)
+{
+ buf->screen->winsys->buffer_destroy(buf);
+}
+
+
+static void
+pass_flush_frontbuffer(struct pipe_screen *screen,
+ struct pipe_surface *surf,
+ void *context_private)
+{
+ screen->winsys->flush_frontbuffer(screen->winsys, surf, context_private);
+}
+
+static void
+pass_fence_reference(struct pipe_screen *screen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ screen->winsys->fence_reference(screen->winsys, ptr, fence);
+}
+
+static int
+pass_fence_signalled(struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return screen->winsys->fence_signalled(screen->winsys, fence, flag);
+}
+
+static int
+pass_fence_finish(struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return screen->winsys->fence_finish(screen->winsys, fence, flag);
+}
+
+void
+u_simple_screen_init(struct pipe_screen *screen)
+{
+ screen->buffer_create = pass_buffer_create;
+ screen->user_buffer_create = pass_user_buffer_create;
+ screen->surface_buffer_create = pass_surface_buffer_create;
+
+ screen->buffer_map = pass_buffer_map;
+ screen->buffer_unmap = pass_buffer_unmap;
+ screen->buffer_destroy = pass_buffer_destroy;
+ screen->flush_frontbuffer = pass_flush_frontbuffer;
+ screen->fence_reference = pass_fence_reference;
+ screen->fence_signalled = pass_fence_signalled;
+ screen->fence_finish = pass_fence_finish;
+}
+
+const char *
+u_simple_screen_winsys_name(struct pipe_screen *screen)
+{
+ return screen->winsys->get_name(screen->winsys);
+}
diff --git a/src/gallium/auxiliary/util/u_simple_screen.h b/src/gallium/auxiliary/util/u_simple_screen.h
new file mode 100644
index 0000000000..6612a8a7c0
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_simple_screen.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_SIMPLE_SCREEN_H
+#define U_SIMPLE_SCREEN_H
+
+struct pipe_screen;
+struct pipe_winsys;
+
+/**
+ * The following function initializes a simple passthrough screen.
+ *
+ * All the relevant screen function pointers will forwarded to the
+ * winsys.
+ */
+void u_simple_screen_init(struct pipe_screen *screen);
+
+/**
+ * Returns the name of the winsys associated with this screen.
+ */
+const char* u_simple_screen_winsys_name(struct pipe_screen *screen);
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
new file mode 100644
index 0000000000..e5fc9b0cee
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -0,0 +1,153 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Simple vertex/fragment shader generators.
+ *
+ * @author Brian Paul
+ */
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_simple_shaders.h"
+#include "tgsi/tgsi_ureg.h"
+
+
+
+/**
+ * Make simple vertex pass-through shader.
+ */
+void *
+util_make_vertex_passthrough_shader(struct pipe_context *pipe,
+ uint num_attribs,
+ const uint *semantic_names,
+ const uint *semantic_indexes)
+
+{
+ struct ureg_program *ureg;
+ uint i;
+
+ ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
+ if (ureg == NULL)
+ return NULL;
+
+ for (i = 0; i < num_attribs; i++) {
+ struct ureg_src src;
+ struct ureg_dst dst;
+
+ src = ureg_DECL_vs_input( ureg,
+ semantic_names[i],
+ semantic_indexes[i]);
+
+ dst = ureg_DECL_output( ureg,
+ semantic_names[i],
+ semantic_indexes[i]);
+
+ ureg_MOV( ureg, dst, src );
+ }
+
+ ureg_END( ureg );
+
+ return ureg_create_shader_and_destroy( ureg, pipe );
+}
+
+
+
+
+/**
+ * Make simple fragment texture shader:
+ * IMM {0,0,0,1} // (if writemask != 0xf)
+ * MOV OUT[0], IMM[0] // (if writemask != 0xf)
+ * TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
+ * END;
+ */
+void *
+util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
+ unsigned writemask )
+{
+ struct ureg_program *ureg;
+ struct ureg_src sampler;
+ struct ureg_src tex;
+ struct ureg_dst out;
+
+ ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+ if (ureg == NULL)
+ return NULL;
+
+ sampler = ureg_DECL_sampler( ureg, 0 );
+
+ tex = ureg_DECL_fs_input( ureg,
+ TGSI_SEMANTIC_GENERIC, 0,
+ TGSI_INTERPOLATE_PERSPECTIVE );
+
+ out = ureg_DECL_output( ureg,
+ TGSI_SEMANTIC_COLOR,
+ 0 );
+
+ ureg_TEX( ureg, out, TGSI_TEXTURE_2D, tex, sampler );
+ ureg_END( ureg );
+
+ return ureg_create_shader_and_destroy( ureg, pipe );
+}
+
+void *
+util_make_fragment_tex_shader(struct pipe_context *pipe )
+{
+ return util_make_fragment_tex_shader_writemask( pipe,
+ TGSI_WRITEMASK_XYZW );
+}
+
+
+
+/**
+ * Make simple fragment color pass-through shader.
+ */
+void *
+util_make_fragment_passthrough_shader(struct pipe_context *pipe)
+{
+ struct ureg_program *ureg;
+ struct ureg_src src;
+ struct ureg_dst dst;
+
+ ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+ if (ureg == NULL)
+ return NULL;
+
+ src = ureg_DECL_fs_input( ureg, TGSI_SEMANTIC_COLOR, 0,
+ TGSI_INTERPOLATE_PERSPECTIVE );
+
+ dst = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 );
+
+ ureg_MOV( ureg, dst, src );
+ ureg_END( ureg );
+
+ return ureg_create_shader_and_destroy( ureg, pipe );
+}
+
+
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
new file mode 100644
index 0000000000..d2e80d6eb4
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef U_SIMPLE_SHADERS_H
+#define U_SIMPLE_SHADERS_H
+
+
+#include "pipe/p_compiler.h"
+
+
+struct pipe_context;
+struct pipe_shader_state;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern void *
+util_make_vertex_passthrough_shader(struct pipe_context *pipe,
+ uint num_attribs,
+ const uint *semantic_names,
+ const uint *semantic_indexes);
+
+
+extern void *
+util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
+ unsigned writemask );
+
+extern void *
+util_make_fragment_tex_shader(struct pipe_context *pipe);
+
+
+extern void *
+util_make_fragment_passthrough_shader(struct pipe_context *pipe);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_snprintf.c b/src/gallium/auxiliary/util/u_snprintf.c
new file mode 100644
index 0000000000..65bdd0df2b
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_snprintf.c
@@ -0,0 +1,1497 @@
+/*
+ * Copyright (c) 1995 Patrick Powell.
+ *
+ * This code is based on code written by Patrick Powell <papowell@astart.com>.
+ * It may be used for any purpose as long as this notice remains intact on all
+ * source code distributions.
+ */
+
+/*
+ * Copyright (c) 2008 Holger Weiss.
+ *
+ * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
+ * My changes to the code may freely be used, modified and/or redistributed for
+ * any purpose. It would be nice if additions and fixes to this file (including
+ * trivial code cleanups) would be sent back in order to let me include them in
+ * the version available at <http://www.jhweiss.de/software/snprintf.html>.
+ * However, this is not a requirement for using or redistributing (possibly
+ * modified) versions of this file, nor is leaving this notice intact mandatory.
+ */
+
+/*
+ * History
+ *
+ * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
+ *
+ * Fixed the detection of infinite floating point values on IRIX (and
+ * possibly other systems) and applied another few minor cleanups.
+ *
+ * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
+ *
+ * Added a lot of new features, fixed many bugs, and incorporated various
+ * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
+ * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
+ * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
+ * projects. The additions include: support the "e", "E", "g", "G", and
+ * "F" conversion specifiers (and use conversion style "f" or "F" for the
+ * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
+ * "t", and "z" length modifiers; support the "#" flag and the (non-C99)
+ * "'" flag; use localeconv(3) (if available) to get both the current
+ * locale's decimal point character and the separator between groups of
+ * digits; fix the handling of various corner cases of field width and
+ * precision specifications; fix various floating point conversion bugs;
+ * handle infinite and NaN floating point values; don't attempt to write to
+ * the output buffer (which may be NULL) if a size of zero was specified;
+ * check for integer overflow of the field width, precision, and return
+ * values and during the floating point conversion; use the OUTCHAR() macro
+ * instead of a function for better performance; provide asprintf(3) and
+ * vasprintf(3) functions; add new test cases. The replacement functions
+ * have been renamed to use an "rpl_" prefix, the function calls in the
+ * main project (and in this file) must be redefined accordingly for each
+ * replacement function which is needed (by using Autoconf or other means).
+ * Various other minor improvements have been applied and the coding style
+ * was cleaned up for consistency.
+ *
+ * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
+ *
+ * C99 compliant snprintf(3) and vsnprintf(3) functions return the number
+ * of characters that would have been written to a sufficiently sized
+ * buffer (excluding the '\0'). The original code simply returned the
+ * length of the resulting output string, so that's been fixed.
+ *
+ * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
+ *
+ * The original code assumed that both snprintf(3) and vsnprintf(3) were
+ * missing. Some systems only have snprintf(3) but not vsnprintf(3), so
+ * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
+ *
+ * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
+ *
+ * The PGP code was using unsigned hexadecimal formats. Unfortunately,
+ * unsigned formats simply didn't work.
+ *
+ * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
+ *
+ * Ok, added some minimal floating point support, which means this probably
+ * requires libm on most operating systems. Don't yet support the exponent
+ * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just
+ * wasn't being exercised in ways which showed it, so that's been fixed.
+ * Also, formatted the code to Mutt conventions, and removed dead code left
+ * over from the original. Also, there is now a builtin-test, run with:
+ * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
+ *
+ * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
+ *
+ * This was ugly. It is still ugly. I opted out of floating point
+ * numbers, but the formatter understands just about everything from the
+ * normal C string format, at least as far as I can tell from the Solaris
+ * 2.5 printf(3S) man page.
+ */
+
+/*
+ * ToDo
+ *
+ * - Add wide character support.
+ * - Add support for "%a" and "%A" conversions.
+ * - Create test routines which predefine the expected results. Our test cases
+ * usually expose bugs in system implementations rather than in ours :-)
+ */
+
+/*
+ * Usage
+ *
+ * 1) The following preprocessor macros should be defined to 1 if the feature or
+ * file in question is available on the target system (by using Autoconf or
+ * other means), though basic functionality should be available as long as
+ * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
+ *
+ * HAVE_VSNPRINTF
+ * HAVE_SNPRINTF
+ * HAVE_VASPRINTF
+ * HAVE_ASPRINTF
+ * HAVE_STDARG_H
+ * HAVE_STDDEF_H
+ * HAVE_STDINT_H
+ * HAVE_STDLIB_H
+ * HAVE_INTTYPES_H
+ * HAVE_LOCALE_H
+ * HAVE_LOCALECONV
+ * HAVE_LCONV_DECIMAL_POINT
+ * HAVE_LCONV_THOUSANDS_SEP
+ * HAVE_LONG_DOUBLE
+ * HAVE_LONG_LONG_INT
+ * HAVE_UNSIGNED_LONG_LONG_INT
+ * HAVE_INTMAX_T
+ * HAVE_UINTMAX_T
+ * HAVE_UINTPTR_T
+ * HAVE_PTRDIFF_T
+ * HAVE_VA_COPY
+ * HAVE___VA_COPY
+ *
+ * 2) The calls to the functions which should be replaced must be redefined
+ * throughout the project files (by using Autoconf or other means):
+ *
+ * #define vsnprintf rpl_vsnprintf
+ * #define snprintf rpl_snprintf
+ * #define vasprintf rpl_vasprintf
+ * #define asprintf rpl_asprintf
+ *
+ * 3) The required replacement functions should be declared in some header file
+ * included throughout the project files:
+ *
+ * #if HAVE_CONFIG_H
+ * #include <config.h>
+ * #endif
+ * #if HAVE_STDARG_H
+ * #include <stdarg.h>
+ * #if !HAVE_VSNPRINTF
+ * int rpl_vsnprintf(char *, size_t, const char *, va_list);
+ * #endif
+ * #if !HAVE_SNPRINTF
+ * int rpl_snprintf(char *, size_t, const char *, ...);
+ * #endif
+ * #if !HAVE_VASPRINTF
+ * int rpl_vasprintf(char **, const char *, va_list);
+ * #endif
+ * #if !HAVE_ASPRINTF
+ * int rpl_asprintf(char **, const char *, ...);
+ * #endif
+ * #endif
+ *
+ * Autoconf macros for handling step 1 and step 2 are available at
+ * <http://www.jhweiss.de/software/snprintf.html>.
+ */
+
+#include "pipe/p_config.h"
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#else
+#ifdef WIN32
+#define vsnprintf util_vsnprintf
+#define snprintf util_snprintf
+#define HAVE_VSNPRINTF 0
+#define HAVE_SNPRINTF 0
+#define HAVE_VASPRINTF 1 /* not needed */
+#define HAVE_ASPRINTF 1 /* not needed */
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDINT_H 0
+#define HAVE_STDLIB_H 1
+#define HAVE_INTTYPES_H 0
+#define HAVE_LOCALE_H 0
+#define HAVE_LOCALECONV 0
+#define HAVE_LCONV_DECIMAL_POINT 0
+#define HAVE_LCONV_THOUSANDS_SEP 0
+#define HAVE_LONG_DOUBLE 0
+#define HAVE_LONG_LONG_INT 1
+#define HAVE_UNSIGNED_LONG_LONG_INT 1
+#define HAVE_INTMAX_T 0
+#define HAVE_UINTMAX_T 0
+#define HAVE_UINTPTR_T 1
+#define HAVE_PTRDIFF_T 1
+#define HAVE_VA_COPY 0
+#define HAVE___VA_COPY 0
+#else
+#define HAVE_VSNPRINTF 1
+#define HAVE_SNPRINTF 1
+#define HAVE_VASPRINTF 1
+#define HAVE_ASPRINTF 1
+#endif
+#endif /* HAVE_CONFIG_H */
+
+#if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF
+#include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
+#ifdef VA_START
+#undef VA_START
+#endif /* defined(VA_START) */
+#ifdef VA_SHIFT
+#undef VA_SHIFT
+#endif /* defined(VA_SHIFT) */
+#if HAVE_STDARG_H
+#include <stdarg.h>
+#define VA_START(ap, last) va_start(ap, last)
+#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
+#else /* Assume <varargs.h> is available. */
+#include <varargs.h>
+#define VA_START(ap, last) va_start(ap) /* "last" is ignored. */
+#define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
+#endif /* HAVE_STDARG_H */
+
+#if !HAVE_VASPRINTF
+#if HAVE_STDLIB_H
+#include <stdlib.h> /* For malloc(3). */
+#endif /* HAVE_STDLIB_H */
+#ifdef VA_COPY
+#undef VA_COPY
+#endif /* defined(VA_COPY) */
+#ifdef VA_END_COPY
+#undef VA_END_COPY
+#endif /* defined(VA_END_COPY) */
+#if HAVE_VA_COPY
+#define VA_COPY(dest, src) va_copy(dest, src)
+#define VA_END_COPY(ap) va_end(ap)
+#elif HAVE___VA_COPY
+#define VA_COPY(dest, src) __va_copy(dest, src)
+#define VA_END_COPY(ap) va_end(ap)
+#else
+#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
+#define VA_END_COPY(ap) /* No-op. */
+#define NEED_MYMEMCPY 1
+static void *mymemcpy(void *, void *, size_t);
+#endif /* HAVE_VA_COPY */
+#endif /* !HAVE_VASPRINTF */
+
+#if !HAVE_VSNPRINTF
+#include <limits.h> /* For *_MAX. */
+#if HAVE_INTTYPES_H
+#include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */
+#endif /* HAVE_INTTYPES_H */
+#if HAVE_LOCALE_H
+#include <locale.h> /* For localeconv(3). */
+#endif /* HAVE_LOCALE_H */
+#if HAVE_STDDEF_H
+#include <stddef.h> /* For ptrdiff_t. */
+#endif /* HAVE_STDDEF_H */
+#if HAVE_STDINT_H
+#include <stdint.h> /* For intmax_t. */
+#endif /* HAVE_STDINT_H */
+
+/* Support for unsigned long long int. We may also need ULLONG_MAX. */
+#ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */
+#ifdef UINT_MAX
+#define ULONG_MAX UINT_MAX
+#else
+#define ULONG_MAX INT_MAX
+#endif /* defined(UINT_MAX) */
+#endif /* !defined(ULONG_MAX) */
+#ifdef ULLONG
+#undef ULLONG
+#endif /* defined(ULLONG) */
+#if HAVE_UNSIGNED_LONG_LONG_INT
+#define ULLONG unsigned long long int
+#ifndef ULLONG_MAX
+#define ULLONG_MAX ULONG_MAX
+#endif /* !defined(ULLONG_MAX) */
+#else
+#define ULLONG unsigned long int
+#ifdef ULLONG_MAX
+#undef ULLONG_MAX
+#endif /* defined(ULLONG_MAX) */
+#define ULLONG_MAX ULONG_MAX
+#endif /* HAVE_LONG_LONG_INT */
+
+/* Support for uintmax_t. We also need UINTMAX_MAX. */
+#ifdef UINTMAX_T
+#undef UINTMAX_T
+#endif /* defined(UINTMAX_T) */
+#if HAVE_UINTMAX_T || defined(uintmax_t)
+#define UINTMAX_T uintmax_t
+#ifndef UINTMAX_MAX
+#define UINTMAX_MAX ULLONG_MAX
+#endif /* !defined(UINTMAX_MAX) */
+#else
+#define UINTMAX_T ULLONG
+#ifdef UINTMAX_MAX
+#undef UINTMAX_MAX
+#endif /* defined(UINTMAX_MAX) */
+#define UINTMAX_MAX ULLONG_MAX
+#endif /* HAVE_UINTMAX_T || defined(uintmax_t) */
+
+/* Support for long double. */
+#ifndef LDOUBLE
+#if HAVE_LONG_DOUBLE
+#define LDOUBLE long double
+#else
+#define LDOUBLE double
+#endif /* HAVE_LONG_DOUBLE */
+#endif /* !defined(LDOUBLE) */
+
+/* Support for long long int. */
+#ifndef LLONG
+#if HAVE_LONG_LONG_INT
+#define LLONG long long int
+#else
+#define LLONG long int
+#endif /* HAVE_LONG_LONG_INT */
+#endif /* !defined(LLONG) */
+
+/* Support for intmax_t. */
+#ifndef INTMAX_T
+#if HAVE_INTMAX_T || defined(intmax_t)
+#define INTMAX_T intmax_t
+#else
+#define INTMAX_T LLONG
+#endif /* HAVE_INTMAX_T || defined(intmax_t) */
+#endif /* !defined(INTMAX_T) */
+
+/* Support for uintptr_t. */
+#ifndef UINTPTR_T
+#if HAVE_UINTPTR_T || defined(uintptr_t)
+#define UINTPTR_T uintptr_t
+#else
+#define UINTPTR_T unsigned long int
+#endif /* HAVE_UINTPTR_T || defined(uintptr_t) */
+#endif /* !defined(UINTPTR_T) */
+
+/* WinCE5.0 does not have uintptr_t defined */
+#if (_WIN32_WCE < 600)
+#ifdef UINTPTR_T
+#undef UINTPTR_T
+#endif
+#define UINTPTR_T unsigned long int
+#endif
+
+
+/* Support for ptrdiff_t. */
+#ifndef PTRDIFF_T
+#if HAVE_PTRDIFF_T || defined(ptrdiff_t)
+#define PTRDIFF_T ptrdiff_t
+#else
+#define PTRDIFF_T long int
+#endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
+#endif /* !defined(PTRDIFF_T) */
+
+/*
+ * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
+ * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an
+ * unsigned type if necessary. This should work just fine in practice.
+ */
+#ifndef UPTRDIFF_T
+#define UPTRDIFF_T PTRDIFF_T
+#endif /* !defined(UPTRDIFF_T) */
+
+/*
+ * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
+ * However, we'll simply use size_t and convert it to a signed type if
+ * necessary. This should work just fine in practice.
+ */
+#ifndef SSIZE_T
+#define SSIZE_T size_t
+#endif /* !defined(SSIZE_T) */
+
+/* Either ERANGE or E2BIG should be available everywhere. */
+#ifndef ERANGE
+#define ERANGE E2BIG
+#endif /* !defined(ERANGE) */
+#ifndef EOVERFLOW
+#define EOVERFLOW ERANGE
+#endif /* !defined(EOVERFLOW) */
+
+/*
+ * Buffer size to hold the octal string representation of UINT128_MAX without
+ * nul-termination ("3777777777777777777777777777777777777777777").
+ */
+#ifdef MAX_CONVERT_LENGTH
+#undef MAX_CONVERT_LENGTH
+#endif /* defined(MAX_CONVERT_LENGTH) */
+#define MAX_CONVERT_LENGTH 43
+
+/* Format read states. */
+#define PRINT_S_DEFAULT 0
+#define PRINT_S_FLAGS 1
+#define PRINT_S_WIDTH 2
+#define PRINT_S_DOT 3
+#define PRINT_S_PRECISION 4
+#define PRINT_S_MOD 5
+#define PRINT_S_CONV 6
+
+/* Format flags. */
+#define PRINT_F_MINUS (1 << 0)
+#define PRINT_F_PLUS (1 << 1)
+#define PRINT_F_SPACE (1 << 2)
+#define PRINT_F_NUM (1 << 3)
+#define PRINT_F_ZERO (1 << 4)
+#define PRINT_F_QUOTE (1 << 5)
+#define PRINT_F_UP (1 << 6)
+#define PRINT_F_UNSIGNED (1 << 7)
+#define PRINT_F_TYPE_G (1 << 8)
+#define PRINT_F_TYPE_E (1 << 9)
+
+/* Conversion flags. */
+#define PRINT_C_CHAR 1
+#define PRINT_C_SHORT 2
+#define PRINT_C_LONG 3
+#define PRINT_C_LLONG 4
+#define PRINT_C_LDOUBLE 5
+#define PRINT_C_SIZE 6
+#define PRINT_C_PTRDIFF 7
+#define PRINT_C_INTMAX 8
+
+#ifndef MAX
+#define MAX(x, y) ((x >= y) ? x : y)
+#endif /* !defined(MAX) */
+#ifndef CHARTOINT
+#define CHARTOINT(ch) (ch - '0')
+#endif /* !defined(CHARTOINT) */
+#ifndef ISDIGIT
+#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
+#endif /* !defined(ISDIGIT) */
+#ifndef ISNAN
+#define ISNAN(x) (x != x)
+#endif /* !defined(ISNAN) */
+#ifndef ISINF
+#define ISINF(x) (x != 0.0 && x + x == x)
+#endif /* !defined(ISINF) */
+
+#ifdef OUTCHAR
+#undef OUTCHAR
+#endif /* defined(OUTCHAR) */
+#define OUTCHAR(str, len, size, ch) \
+do { \
+ if (len + 1 < size) \
+ str[len] = ch; \
+ (len)++; \
+} while (/* CONSTCOND */ 0)
+
+static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
+static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
+static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
+static void printsep(char *, size_t *, size_t);
+static int getnumsep(int);
+static int getexponent(LDOUBLE);
+static int convert(UINTMAX_T, char *, size_t, int, int);
+static UINTMAX_T cast(LDOUBLE);
+static UINTMAX_T myround(LDOUBLE);
+static LDOUBLE mypow10(int);
+
+int
+util_vsnprintf(char *str, size_t size, const char *format, va_list args)
+{
+ LDOUBLE fvalue;
+ INTMAX_T value;
+ unsigned char cvalue;
+ const char *strvalue;
+ INTMAX_T *intmaxptr;
+ PTRDIFF_T *ptrdiffptr;
+ SSIZE_T *sizeptr;
+ LLONG *llongptr;
+ long int *longptr;
+ int *intptr;
+ short int *shortptr;
+ signed char *charptr;
+ size_t len = 0;
+ int overflow = 0;
+ int base = 0;
+ int cflags = 0;
+ int flags = 0;
+ int width = 0;
+ int precision = -1;
+ int state = PRINT_S_DEFAULT;
+ char ch = *format++;
+
+ /*
+ * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
+ * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer
+ * even if a size larger than zero was specified. At least NetBSD's
+ * snprintf(3) does the same, as well as other versions of this file.
+ * (Though some of these versions will write to a non-NULL buffer even
+ * if a size of zero was specified, which violates the standard.)
+ */
+ if (str == NULL && size != 0)
+ size = 0;
+
+ while (ch != '\0')
+ switch (state) {
+ case PRINT_S_DEFAULT:
+ if (ch == '%')
+ state = PRINT_S_FLAGS;
+ else
+ OUTCHAR(str, len, size, ch);
+ ch = *format++;
+ break;
+ case PRINT_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= PRINT_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= PRINT_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= PRINT_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= PRINT_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= PRINT_F_ZERO;
+ ch = *format++;
+ break;
+ case '\'': /* SUSv2 flag (not in C99). */
+ flags |= PRINT_F_QUOTE;
+ ch = *format++;
+ break;
+ default:
+ state = PRINT_S_WIDTH;
+ break;
+ }
+ break;
+ case PRINT_S_WIDTH:
+ if (ISDIGIT(ch)) {
+ ch = CHARTOINT(ch);
+ if (width > (INT_MAX - ch) / 10) {
+ overflow = 1;
+ goto out;
+ }
+ width = 10 * width + ch;
+ ch = *format++;
+ } else if (ch == '*') {
+ /*
+ * C99 says: "A negative field width argument is
+ * taken as a `-' flag followed by a positive
+ * field width." (7.19.6.1, 5)
+ */
+ if ((width = va_arg(args, int)) < 0) {
+ flags |= PRINT_F_MINUS;
+ width = -width;
+ }
+ ch = *format++;
+ state = PRINT_S_DOT;
+ } else
+ state = PRINT_S_DOT;
+ break;
+ case PRINT_S_DOT:
+ if (ch == '.') {
+ state = PRINT_S_PRECISION;
+ ch = *format++;
+ } else
+ state = PRINT_S_MOD;
+ break;
+ case PRINT_S_PRECISION:
+ if (precision == -1)
+ precision = 0;
+ if (ISDIGIT(ch)) {
+ ch = CHARTOINT(ch);
+ if (precision > (INT_MAX - ch) / 10) {
+ overflow = 1;
+ goto out;
+ }
+ precision = 10 * precision + ch;
+ ch = *format++;
+ } else if (ch == '*') {
+ /*
+ * C99 says: "A negative precision argument is
+ * taken as if the precision were omitted."
+ * (7.19.6.1, 5)
+ */
+ if ((precision = va_arg(args, int)) < 0)
+ precision = -1;
+ ch = *format++;
+ state = PRINT_S_MOD;
+ } else
+ state = PRINT_S_MOD;
+ break;
+ case PRINT_S_MOD:
+ switch (ch) {
+ case 'h':
+ ch = *format++;
+ if (ch == 'h') { /* It's a char. */
+ ch = *format++;
+ cflags = PRINT_C_CHAR;
+ } else
+ cflags = PRINT_C_SHORT;
+ break;
+ case 'l':
+ ch = *format++;
+ if (ch == 'l') { /* It's a long long. */
+ ch = *format++;
+ cflags = PRINT_C_LLONG;
+ } else
+ cflags = PRINT_C_LONG;
+ break;
+ case 'L':
+ cflags = PRINT_C_LDOUBLE;
+ ch = *format++;
+ break;
+ case 'j':
+ cflags = PRINT_C_INTMAX;
+ ch = *format++;
+ break;
+ case 't':
+ cflags = PRINT_C_PTRDIFF;
+ ch = *format++;
+ break;
+ case 'z':
+ cflags = PRINT_C_SIZE;
+ ch = *format++;
+ break;
+ }
+ state = PRINT_S_CONV;
+ break;
+ case PRINT_S_CONV:
+ switch (ch) {
+ case 'd':
+ /* FALLTHROUGH */
+ case 'i':
+ switch (cflags) {
+ case PRINT_C_CHAR:
+ value = (signed char)va_arg(args, int);
+ break;
+ case PRINT_C_SHORT:
+ value = (short int)va_arg(args, int);
+ break;
+ case PRINT_C_LONG:
+ value = va_arg(args, long int);
+ break;
+ case PRINT_C_LLONG:
+ value = va_arg(args, LLONG);
+ break;
+ case PRINT_C_SIZE:
+ value = va_arg(args, SSIZE_T);
+ break;
+ case PRINT_C_INTMAX:
+ value = va_arg(args, INTMAX_T);
+ break;
+ case PRINT_C_PTRDIFF:
+ value = va_arg(args, PTRDIFF_T);
+ break;
+ default:
+ value = va_arg(args, int);
+ break;
+ }
+ fmtint(str, &len, size, value, 10, width,
+ precision, flags);
+ break;
+ case 'X':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'x':
+ base = 16;
+ /* FALLTHROUGH */
+ case 'o':
+ if (base == 0)
+ base = 8;
+ /* FALLTHROUGH */
+ case 'u':
+ if (base == 0)
+ base = 10;
+ flags |= PRINT_F_UNSIGNED;
+ switch (cflags) {
+ case PRINT_C_CHAR:
+ value = (unsigned char)va_arg(args,
+ unsigned int);
+ break;
+ case PRINT_C_SHORT:
+ value = (unsigned short int)va_arg(args,
+ unsigned int);
+ break;
+ case PRINT_C_LONG:
+ value = va_arg(args, unsigned long int);
+ break;
+ case PRINT_C_LLONG:
+ value = va_arg(args, ULLONG);
+ break;
+ case PRINT_C_SIZE:
+ value = va_arg(args, size_t);
+ break;
+ case PRINT_C_INTMAX:
+ value = va_arg(args, UINTMAX_T);
+ break;
+ case PRINT_C_PTRDIFF:
+ value = va_arg(args, UPTRDIFF_T);
+ break;
+ default:
+ value = va_arg(args, unsigned int);
+ break;
+ }
+ fmtint(str, &len, size, value, base, width,
+ precision, flags);
+ break;
+ case 'A':
+ /* Not yet supported, we'll use "%F". */
+ /* FALLTHROUGH */
+ case 'F':
+ flags |= PRINT_F_UP;
+ case 'a':
+ /* Not yet supported, we'll use "%f". */
+ /* FALLTHROUGH */
+ case 'f':
+ if (cflags == PRINT_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ fmtflt(str, &len, size, fvalue, width,
+ precision, flags, &overflow);
+ if (overflow)
+ goto out;
+ break;
+ case 'E':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'e':
+ flags |= PRINT_F_TYPE_E;
+ if (cflags == PRINT_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ fmtflt(str, &len, size, fvalue, width,
+ precision, flags, &overflow);
+ if (overflow)
+ goto out;
+ break;
+ case 'G':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'g':
+ flags |= PRINT_F_TYPE_G;
+ if (cflags == PRINT_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ /*
+ * If the precision is zero, it is treated as
+ * one (cf. C99: 7.19.6.1, 8).
+ */
+ if (precision == 0)
+ precision = 1;
+ fmtflt(str, &len, size, fvalue, width,
+ precision, flags, &overflow);
+ if (overflow)
+ goto out;
+ break;
+ case 'c':
+ cvalue = (unsigned char)va_arg(args, int);
+ OUTCHAR(str, len, size, cvalue);
+ break;
+ case 's':
+ strvalue = va_arg(args, char *);
+ fmtstr(str, &len, size, strvalue, width,
+ precision, flags);
+ break;
+ case 'p':
+ /*
+ * C99 says: "The value of the pointer is
+ * converted to a sequence of printing
+ * characters, in an implementation-defined
+ * manner." (C99: 7.19.6.1, 8)
+ */
+ if ((strvalue = va_arg(args, void *)) == NULL)
+ /*
+ * We use the glibc format. BSD prints
+ * "0x0", SysV "0".
+ */
+ fmtstr(str, &len, size, "(nil)", width,
+ -1, flags);
+ else {
+ /*
+ * We use the BSD/glibc format. SysV
+ * omits the "0x" prefix (which we emit
+ * using the PRINT_F_NUM flag).
+ */
+ flags |= PRINT_F_NUM;
+ flags |= PRINT_F_UNSIGNED;
+ fmtint(str, &len, size,
+ (UINTPTR_T)strvalue, 16, width,
+ precision, flags);
+ }
+ break;
+ case 'n':
+ switch (cflags) {
+ case PRINT_C_CHAR:
+ charptr = va_arg(args, signed char *);
+ *charptr = (signed char)len;
+ break;
+ case PRINT_C_SHORT:
+ shortptr = va_arg(args, short int *);
+ *shortptr = (short int)len;
+ break;
+ case PRINT_C_LONG:
+ longptr = va_arg(args, long int *);
+ *longptr = (long int)len;
+ break;
+ case PRINT_C_LLONG:
+ llongptr = va_arg(args, LLONG *);
+ *llongptr = (LLONG)len;
+ break;
+ case PRINT_C_SIZE:
+ /*
+ * C99 says that with the "z" length
+ * modifier, "a following `n' conversion
+ * specifier applies to a pointer to a
+ * signed integer type corresponding to
+ * size_t argument." (7.19.6.1, 7)
+ */
+ sizeptr = va_arg(args, SSIZE_T *);
+ *sizeptr = len;
+ break;
+ case PRINT_C_INTMAX:
+ intmaxptr = va_arg(args, INTMAX_T *);
+ *intmaxptr = len;
+ break;
+ case PRINT_C_PTRDIFF:
+ ptrdiffptr = va_arg(args, PTRDIFF_T *);
+ *ptrdiffptr = len;
+ break;
+ default:
+ intptr = va_arg(args, int *);
+ *intptr = (int)len;
+ break;
+ }
+ break;
+ case '%': /* Print a "%" character verbatim. */
+ OUTCHAR(str, len, size, ch);
+ break;
+ default: /* Skip other characters. */
+ break;
+ }
+ ch = *format++;
+ state = PRINT_S_DEFAULT;
+ base = cflags = flags = width = 0;
+ precision = -1;
+ break;
+ }
+out:
+ if (len < size)
+ str[len] = '\0';
+ else if (size > 0)
+ str[size - 1] = '\0';
+
+ if (overflow || len >= INT_MAX) {
+ return -1;
+ }
+ return (int)len;
+}
+
+static void
+fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
+ int precision, int flags)
+{
+ int padlen, strln; /* Amount to pad. */
+ int noprecision = (precision == -1);
+
+ if (value == NULL) /* We're forgiving. */
+ value = "(null)";
+
+ /* If a precision was specified, don't read the string past it. */
+ for (strln = 0; value[strln] != '\0' &&
+ (noprecision || strln < precision); strln++)
+ continue;
+
+ if ((padlen = width - strln) < 0)
+ padlen = 0;
+ if (flags & PRINT_F_MINUS) /* Left justify. */
+ padlen = -padlen;
+
+ while (padlen > 0) { /* Leading spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen--;
+ }
+ while (*value != '\0' && (noprecision || precision-- > 0)) {
+ OUTCHAR(str, *len, size, *value);
+ value++;
+ }
+ while (padlen < 0) { /* Trailing spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen++;
+ }
+}
+
+static void
+fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
+ int precision, int flags)
+{
+ UINTMAX_T uvalue;
+ char iconvert[MAX_CONVERT_LENGTH];
+ char sign = 0;
+ char hexprefix = 0;
+ int spadlen = 0; /* Amount to space pad. */
+ int zpadlen = 0; /* Amount to zero pad. */
+ int pos;
+ int separators = (flags & PRINT_F_QUOTE);
+ int noprecision = (precision == -1);
+
+ if (flags & PRINT_F_UNSIGNED)
+ uvalue = value;
+ else {
+ uvalue = (value >= 0) ? value : -value;
+ if (value < 0)
+ sign = '-';
+ else if (flags & PRINT_F_PLUS) /* Do a sign. */
+ sign = '+';
+ else if (flags & PRINT_F_SPACE)
+ sign = ' ';
+ }
+
+ pos = convert(uvalue, iconvert, sizeof(iconvert), base,
+ flags & PRINT_F_UP);
+
+ if (flags & PRINT_F_NUM && uvalue != 0) {
+ /*
+ * C99 says: "The result is converted to an `alternative form'.
+ * For `o' conversion, it increases the precision, if and only
+ * if necessary, to force the first digit of the result to be a
+ * zero (if the value and precision are both 0, a single 0 is
+ * printed). For `x' (or `X') conversion, a nonzero result has
+ * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
+ */
+ switch (base) {
+ case 8:
+ if (precision <= pos)
+ precision = pos + 1;
+ break;
+ case 16:
+ hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
+ break;
+ }
+ }
+
+ if (separators) /* Get the number of group separators we'll print. */
+ separators = getnumsep(pos);
+
+ zpadlen = precision - pos - separators;
+ spadlen = width /* Minimum field width. */
+ - separators /* Number of separators. */
+ - MAX(precision, pos) /* Number of integer digits. */
+ - ((sign != 0) ? 1 : 0) /* Will we print a sign? */
+ - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */
+
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (spadlen < 0)
+ spadlen = 0;
+
+ /*
+ * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
+ * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a
+ * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
+ */
+ if (flags & PRINT_F_MINUS) /* Left justify. */
+ spadlen = -spadlen;
+ else if (flags & PRINT_F_ZERO && noprecision) {
+ zpadlen += spadlen;
+ spadlen = 0;
+ }
+ while (spadlen > 0) { /* Leading spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ spadlen--;
+ }
+ if (sign != 0) /* Sign. */
+ OUTCHAR(str, *len, size, sign);
+ if (hexprefix != 0) { /* A "0x" or "0X" prefix. */
+ OUTCHAR(str, *len, size, '0');
+ OUTCHAR(str, *len, size, hexprefix);
+ }
+ while (zpadlen > 0) { /* Leading zeros. */
+ OUTCHAR(str, *len, size, '0');
+ zpadlen--;
+ }
+ while (pos > 0) { /* The actual digits. */
+ pos--;
+ OUTCHAR(str, *len, size, iconvert[pos]);
+ if (separators > 0 && pos > 0 && pos % 3 == 0)
+ printsep(str, len, size);
+ }
+ while (spadlen < 0) { /* Trailing spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ spadlen++;
+ }
+}
+
+static void
+fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
+ int precision, int flags, int *overflow)
+{
+ LDOUBLE ufvalue;
+ UINTMAX_T intpart;
+ UINTMAX_T fracpart;
+ UINTMAX_T mask;
+ const char *infnan = NULL;
+ char iconvert[MAX_CONVERT_LENGTH];
+ char fconvert[MAX_CONVERT_LENGTH];
+ char econvert[4]; /* "e-12" (without nul-termination). */
+ char esign = 0;
+ char sign = 0;
+ int leadfraczeros = 0;
+ int exponent = 0;
+ int emitpoint = 0;
+ int omitzeros = 0;
+ int omitcount = 0;
+ int padlen = 0;
+ int epos = 0;
+ int fpos = 0;
+ int ipos = 0;
+ int separators = (flags & PRINT_F_QUOTE);
+ int estyle = (flags & PRINT_F_TYPE_E);
+#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
+ struct lconv *lc = localeconv();
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
+
+ /*
+ * AIX' man page says the default is 0, but C99 and at least Solaris'
+ * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
+ * defaults to 6.
+ */
+ if (precision == -1)
+ precision = 6;
+
+ if (fvalue < 0.0)
+ sign = '-';
+ else if (flags & PRINT_F_PLUS) /* Do a sign. */
+ sign = '+';
+ else if (flags & PRINT_F_SPACE)
+ sign = ' ';
+
+ if (ISNAN(fvalue))
+ infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
+ else if (ISINF(fvalue))
+ infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
+
+ if (infnan != NULL) {
+ if (sign != 0)
+ iconvert[ipos++] = sign;
+ while (*infnan != '\0')
+ iconvert[ipos++] = *infnan++;
+ fmtstr(str, len, size, iconvert, width, ipos, flags);
+ return;
+ }
+
+ /* "%e" (or "%E") or "%g" (or "%G") conversion. */
+ if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
+ if (flags & PRINT_F_TYPE_G) {
+ /*
+ * For "%g" (and "%G") conversions, the precision
+ * specifies the number of significant digits, which
+ * includes the digits in the integer part. The
+ * conversion will or will not be using "e-style" (like
+ * "%e" or "%E" conversions) depending on the precision
+ * and on the exponent. However, the exponent can be
+ * affected by rounding the converted value, so we'll
+ * leave this decision for later. Until then, we'll
+ * assume that we're going to do an "e-style" conversion
+ * (in order to get the exponent calculated). For
+ * "e-style", the precision must be decremented by one.
+ */
+ precision--;
+ /*
+ * For "%g" (and "%G") conversions, trailing zeros are
+ * removed from the fractional portion of the result
+ * unless the "#" flag was specified.
+ */
+ if (!(flags & PRINT_F_NUM))
+ omitzeros = 1;
+ }
+ exponent = getexponent(fvalue);
+ estyle = 1;
+ }
+
+again:
+ /*
+ * Sorry, we only support 9, 19, or 38 digits (that is, the number of
+ * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
+ * minus one) past the decimal point due to our conversion method.
+ */
+ switch (sizeof(UINTMAX_T)) {
+ case 16:
+ if (precision > 38)
+ precision = 38;
+ break;
+ case 8:
+ if (precision > 19)
+ precision = 19;
+ break;
+ default:
+ if (precision > 9)
+ precision = 9;
+ break;
+ }
+
+ ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
+ if (estyle) /* We want exactly one integer digit. */
+ ufvalue /= mypow10(exponent);
+
+ if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
+ *overflow = 1;
+ return;
+ }
+
+ /*
+ * Factor of ten with the number of digits needed for the fractional
+ * part. For example, if the precision is 3, the mask will be 1000.
+ */
+#if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+ mask = (unsigned long)mypow10(precision);
+#else
+ mask = (UINTMAX_T)mypow10(precision);
+#endif
+ /*
+ * We "cheat" by converting the fractional part to integer by
+ * multiplying by a factor of ten.
+ */
+ if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
+ /*
+ * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
+ * (because precision = 3). Now, myround(1000 * 0.99962) will
+ * return 1000. So, the integer part must be incremented by one
+ * and the fractional part must be set to zero.
+ */
+ intpart++;
+ fracpart = 0;
+ if (estyle && intpart == 10) {
+ /*
+ * The value was rounded up to ten, but we only want one
+ * integer digit if using "e-style". So, the integer
+ * part must be set to one and the exponent must be
+ * incremented by one.
+ */
+ intpart = 1;
+ exponent++;
+ }
+ }
+
+ /*
+ * Now that we know the real exponent, we can check whether or not to
+ * use "e-style" for "%g" (and "%G") conversions. If we don't need
+ * "e-style", the precision must be adjusted and the integer and
+ * fractional parts must be recalculated from the original value.
+ *
+ * C99 says: "Let P equal the precision if nonzero, 6 if the precision
+ * is omitted, or 1 if the precision is zero. Then, if a conversion
+ * with style `E' would have an exponent of X:
+ *
+ * - if P > X >= -4, the conversion is with style `f' (or `F') and
+ * precision P - (X + 1).
+ *
+ * - otherwise, the conversion is with style `e' (or `E') and precision
+ * P - 1." (7.19.6.1, 8)
+ *
+ * Note that we had decremented the precision by one.
+ */
+ if (flags & PRINT_F_TYPE_G && estyle &&
+ precision + 1 > exponent && exponent >= -4) {
+ precision -= exponent;
+ estyle = 0;
+ goto again;
+ }
+
+ if (estyle) {
+ if (exponent < 0) {
+ exponent = -exponent;
+ esign = '-';
+ } else
+ esign = '+';
+
+ /*
+ * Convert the exponent. The sizeof(econvert) is 4. So, the
+ * econvert buffer can hold e.g. "e+99" and "e-99". We don't
+ * support an exponent which contains more than two digits.
+ * Therefore, the following stores are safe.
+ */
+ epos = convert(exponent, econvert, 2, 10, 0);
+ /*
+ * C99 says: "The exponent always contains at least two digits,
+ * and only as many more digits as necessary to represent the
+ * exponent." (7.19.6.1, 8)
+ */
+ if (epos == 1)
+ econvert[epos++] = '0';
+ econvert[epos++] = esign;
+ econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
+ }
+
+ /* Convert the integer part and the fractional part. */
+ ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
+ if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */
+ fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
+
+ leadfraczeros = precision - fpos;
+
+ if (omitzeros) {
+ if (fpos > 0) /* Omit trailing fractional part zeros. */
+ while (omitcount < fpos && fconvert[omitcount] == '0')
+ omitcount++;
+ else { /* The fractional part is zero, omit it completely. */
+ omitcount = precision;
+ leadfraczeros = 0;
+ }
+ precision -= omitcount;
+ }
+
+ /*
+ * Print a decimal point if either the fractional part is non-zero
+ * and/or the "#" flag was specified.
+ */
+ if (precision > 0 || flags & PRINT_F_NUM)
+ emitpoint = 1;
+ if (separators) /* Get the number of group separators we'll print. */
+ separators = getnumsep(ipos);
+
+ padlen = width /* Minimum field width. */
+ - ipos /* Number of integer digits. */
+ - epos /* Number of exponent characters. */
+ - precision /* Number of fractional digits. */
+ - separators /* Number of group separators. */
+ - (emitpoint ? 1 : 0) /* Will we print a decimal point? */
+ - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */
+
+ if (padlen < 0)
+ padlen = 0;
+
+ /*
+ * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
+ * ignored." (7.19.6.1, 6)
+ */
+ if (flags & PRINT_F_MINUS) /* Left justifty. */
+ padlen = -padlen;
+ else if (flags & PRINT_F_ZERO && padlen > 0) {
+ if (sign != 0) { /* Sign. */
+ OUTCHAR(str, *len, size, sign);
+ sign = 0;
+ }
+ while (padlen > 0) { /* Leading zeros. */
+ OUTCHAR(str, *len, size, '0');
+ padlen--;
+ }
+ }
+ while (padlen > 0) { /* Leading spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen--;
+ }
+ if (sign != 0) /* Sign. */
+ OUTCHAR(str, *len, size, sign);
+ while (ipos > 0) { /* Integer part. */
+ ipos--;
+ OUTCHAR(str, *len, size, iconvert[ipos]);
+ if (separators > 0 && ipos > 0 && ipos % 3 == 0)
+ printsep(str, len, size);
+ }
+ if (emitpoint) { /* Decimal point. */
+#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
+ if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
+ OUTCHAR(str, *len, size, *lc->decimal_point);
+ else /* We'll always print some decimal point character. */
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
+ OUTCHAR(str, *len, size, '.');
+ }
+ while (leadfraczeros > 0) { /* Leading fractional part zeros. */
+ OUTCHAR(str, *len, size, '0');
+ leadfraczeros--;
+ }
+ while (fpos > omitcount) { /* The remaining fractional part. */
+ fpos--;
+ OUTCHAR(str, *len, size, fconvert[fpos]);
+ }
+ while (epos > 0) { /* Exponent. */
+ epos--;
+ OUTCHAR(str, *len, size, econvert[epos]);
+ }
+ while (padlen < 0) { /* Trailing spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen++;
+ }
+}
+
+static void
+printsep(char *str, size_t *len, size_t size)
+{
+#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
+ struct lconv *lc = localeconv();
+ int i;
+
+ if (lc->thousands_sep != NULL)
+ for (i = 0; lc->thousands_sep[i] != '\0'; i++)
+ OUTCHAR(str, *len, size, lc->thousands_sep[i]);
+ else
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
+ OUTCHAR(str, *len, size, ',');
+}
+
+static int
+getnumsep(int digits)
+{
+ int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
+#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
+ int strln;
+ struct lconv *lc = localeconv();
+
+ /* We support an arbitrary separator length (including zero). */
+ if (lc->thousands_sep != NULL) {
+ for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
+ continue;
+ separators *= strln;
+ }
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
+ return separators;
+}
+
+static int
+getexponent(LDOUBLE value)
+{
+ LDOUBLE tmp = (value >= 0.0) ? value : -value;
+ int exponent = 0;
+
+ /*
+ * We check for 99 > exponent > -99 in order to work around possible
+ * endless loops which could happen (at least) in the second loop (at
+ * least) if we're called with an infinite value. However, we checked
+ * for infinity before calling this function using our ISINF() macro, so
+ * this might be somewhat paranoid.
+ */
+ while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
+ tmp *= 10;
+ while (tmp >= 10.0 && ++exponent < 99)
+ tmp /= 10;
+
+ return exponent;
+}
+
+static int
+convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
+{
+ const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
+ size_t pos = 0;
+
+ /* We return an unterminated buffer with the digits in reverse order. */
+ do {
+ buf[pos++] = digits[value % base];
+ value /= base;
+ } while (value != 0 && pos < size);
+
+ return (int)pos;
+}
+
+static UINTMAX_T
+cast(LDOUBLE value)
+{
+ UINTMAX_T result;
+
+ /*
+ * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
+ * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
+ * it may be increased to the nearest higher representable value for the
+ * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE
+ * value although converting the latter to UINTMAX_T would overflow.
+ */
+ if (value >= UINTMAX_MAX)
+ return UINTMAX_MAX;
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+ result = (unsigned long)value;
+#else
+ result = (UINTMAX_T)value;
+#endif
+ /*
+ * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
+ * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
+ * the standard). Sigh.
+ */
+ return (result <= value) ? result : result - 1;
+}
+
+static UINTMAX_T
+myround(LDOUBLE value)
+{
+ UINTMAX_T intpart = cast(value);
+
+ return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
+}
+
+static LDOUBLE
+mypow10(int exponent)
+{
+ LDOUBLE result = 1;
+
+ while (exponent > 0) {
+ result *= 10;
+ exponent--;
+ }
+ while (exponent < 0) {
+ result /= 10;
+ exponent++;
+ }
+ return result;
+}
+#endif /* !HAVE_VSNPRINTF */
+
+#if !HAVE_VASPRINTF
+#if NEED_MYMEMCPY
+void *
+mymemcpy(void *dst, void *src, size_t len)
+{
+ const char *from = src;
+ char *to = dst;
+
+ /* No need for optimization, we use this only to replace va_copy(3). */
+ while (len-- > 0)
+ *to++ = *from++;
+ return dst;
+}
+#endif /* NEED_MYMEMCPY */
+
+int
+util_vasprintf(char **ret, const char *format, va_list ap)
+{
+ size_t size;
+ int len;
+ va_list aq;
+
+ VA_COPY(aq, ap);
+ len = vsnprintf(NULL, 0, format, aq);
+ VA_END_COPY(aq);
+ if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
+ return -1;
+ return vsnprintf(*ret, size, format, ap);
+}
+#endif /* !HAVE_VASPRINTF */
+
+#if !HAVE_SNPRINTF
+#if HAVE_STDARG_H
+int
+util_snprintf(char *str, size_t size, const char *format, ...)
+#else
+int
+util_snprintf(va_alist) va_dcl
+#endif /* HAVE_STDARG_H */
+{
+#if !HAVE_STDARG_H
+ char *str;
+ size_t size;
+ char *format;
+#endif /* HAVE_STDARG_H */
+ va_list ap;
+ int len;
+
+ VA_START(ap, format);
+ VA_SHIFT(ap, str, char *);
+ VA_SHIFT(ap, size, size_t);
+ VA_SHIFT(ap, format, const char *);
+ len = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return len;
+}
+#endif /* !HAVE_SNPRINTF */
+
+#if !HAVE_ASPRINTF
+#if HAVE_STDARG_H
+int
+util_asprintf(char **ret, const char *format, ...)
+#else
+int
+util_asprintf(va_alist) va_dcl
+#endif /* HAVE_STDARG_H */
+{
+#if !HAVE_STDARG_H
+ char **ret;
+ char *format;
+#endif /* HAVE_STDARG_H */
+ va_list ap;
+ int len;
+
+ VA_START(ap, format);
+ VA_SHIFT(ap, ret, char **);
+ VA_SHIFT(ap, format, const char *);
+ len = vasprintf(ret, format, ap);
+ va_end(ap);
+ return len;
+}
+#endif /* !HAVE_ASPRINTF */
+#else /* Dummy declaration to avoid empty translation unit warnings. */
+int main(void);
+#endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
+
+
+/* vim: set joinspaces textwidth=80: */
diff --git a/src/gallium/auxiliary/util/u_sse.h b/src/gallium/auxiliary/util/u_sse.h
new file mode 100644
index 0000000000..e2a8491e62
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_sse.h
@@ -0,0 +1,77 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SSE intrinsics portability header.
+ *
+ * Although the SSE intrinsics are support by all modern x86 and x86-64
+ * compilers, there are some intrisincs missing in some implementations
+ * (especially older MSVC versions). This header abstracts that away.
+ */
+
+#ifndef U_SSE_H_
+#define U_SSE_H_
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_ARCH_SSE)
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+
+/* MSVC before VC8 does not support the _mm_castxxx_yyy */
+#if defined(_MSC_VER) && _MSC_VER < 1500
+
+union __declspec(align(16)) m128_types {
+ __m128 m128;
+ __m128i m128i;
+ __m128d m128d;
+};
+
+static __inline __m128
+_mm_castsi128_ps(__m128i a)
+{
+ union m128_types u;
+ u.m128i = a;
+ return u.m128;
+}
+
+static __inline __m128i
+_mm_castps_si128(__m128 a)
+{
+ union m128_types u;
+ u.m128 = a;
+ return u.m128i;
+}
+
+#endif /* defined(_MSC_VER) && _MSC_VER < 1500 */
+
+#endif /* PIPE_ARCH_X86 || PIPE_ARCH_X86_64 */
+
+#endif /* U_SSE_H_ */
diff --git a/src/gallium/auxiliary/util/u_stream.h b/src/gallium/auxiliary/util/u_stream.h
new file mode 100644
index 0000000000..a9d0f0121a
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_stream.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Cross-platform sequential access stream abstraction.
+ */
+
+#ifndef U_STREAM_H
+#define U_STREAM_H
+
+
+#include "pipe/p_compiler.h"
+
+
+struct util_stream;
+
+
+/**
+ * Create a stream
+ * @param filename relative or absolute path (necessary for windows)
+ * @param optional maximum file size (0 for a growable size).
+ */
+struct util_stream *
+util_stream_create(const char *filename, size_t max_size);
+
+boolean
+util_stream_write(struct util_stream *stream, const void *data, size_t size);
+
+void
+util_stream_flush(struct util_stream *stream);
+
+void
+util_stream_close(struct util_stream *stream);
+
+
+#endif /* U_STREAM_H */
diff --git a/src/gallium/auxiliary/util/u_stream_stdc.c b/src/gallium/auxiliary/util/u_stream_stdc.c
new file mode 100644
index 0000000000..5cd05b2904
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_stream_stdc.c
@@ -0,0 +1,106 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Stream implementation based on the Standard C Library.
+ */
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU)
+
+#include <stdio.h>
+
+#include "util/u_memory.h"
+
+#include "u_stream.h"
+
+
+struct util_stream
+{
+ FILE *file;
+};
+
+
+struct util_stream *
+util_stream_create(const char *filename, size_t max_size)
+{
+ struct util_stream *stream;
+
+ (void)max_size;
+
+ stream = CALLOC_STRUCT(util_stream);
+ if(!stream)
+ goto error1;
+
+ stream->file = fopen(filename, "w");
+ if(!stream->file)
+ goto error2;
+
+ return stream;
+
+error2:
+ FREE(stream);
+error1:
+ return NULL;
+}
+
+
+boolean
+util_stream_write(struct util_stream *stream, const void *data, size_t size)
+{
+ if(!stream)
+ return FALSE;
+
+ return fwrite(data, size, 1, stream->file) == size ? TRUE : FALSE;
+}
+
+
+void
+util_stream_flush(struct util_stream *stream)
+{
+ if(!stream)
+ return;
+
+ fflush(stream->file);
+}
+
+
+void
+util_stream_close(struct util_stream *stream)
+{
+ if(!stream)
+ return;
+
+ fclose(stream->file);
+
+ FREE(stream);
+}
+
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_stream_wd.c b/src/gallium/auxiliary/util/u_stream_wd.c
new file mode 100644
index 0000000000..864489e775
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_stream_wd.c
@@ -0,0 +1,224 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Stream implementation for the Windows Display driver.
+ */
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+
+#include <windows.h>
+#include <winddi.h>
+
+#include "util/u_memory.h"
+#include "util/u_string.h"
+
+#include "u_stream.h"
+
+
+#define MAP_FILE_SIZE (4*1024*1024)
+
+
+struct util_stream
+{
+ char filename[MAX_PATH + 1];
+ WCHAR wFileName[MAX_PATH + 1];
+ boolean growable;
+ size_t map_size;
+ ULONG_PTR iFile;
+ char *pMap;
+ size_t written;
+ unsigned suffix;
+};
+
+
+static INLINE boolean
+util_stream_map(struct util_stream *stream)
+{
+ ULONG BytesInUnicodeString;
+ static char filename[MAX_PATH + 1];
+ unsigned filename_len;
+
+ if(stream->growable)
+ filename_len = util_snprintf(filename,
+ sizeof(filename),
+ "%s.%04x",
+ stream->filename,
+ stream->suffix++);
+ else
+ filename_len = util_snprintf(filename,
+ sizeof(filename),
+ "%s",
+ stream->filename);
+
+ EngMultiByteToUnicodeN(
+ stream->wFileName,
+ sizeof(stream->wFileName),
+ &BytesInUnicodeString,
+ filename,
+ filename_len);
+
+ stream->pMap = EngMapFile(stream->wFileName, stream->map_size, &stream->iFile);
+ if(!stream->pMap)
+ return FALSE;
+
+ memset(stream->pMap, 0, stream->map_size);
+ stream->written = 0;
+
+ return TRUE;
+}
+
+
+static INLINE void
+util_stream_unmap(struct util_stream *stream)
+{
+ EngUnmapFile(stream->iFile);
+ if(stream->written < stream->map_size) {
+ /* Truncate file size */
+ stream->pMap = EngMapFile(stream->wFileName, stream->written, &stream->iFile);
+ if(stream->pMap)
+ EngUnmapFile(stream->iFile);
+ }
+
+ stream->pMap = NULL;
+}
+
+
+static INLINE void
+util_stream_full_qualified_filename(char *dst, size_t size, const char *src)
+{
+ boolean need_drive, need_root;
+
+ if((('A' <= src[0] && src[0] <= 'Z') || ('a' <= src[0] && src[0] <= 'z')) && src[1] == ':') {
+ need_drive = FALSE;
+ need_root = src[2] == '\\' ? FALSE : TRUE;
+ }
+ else {
+ need_drive = TRUE;
+ need_root = src[0] == '\\' ? FALSE : TRUE;
+ }
+
+ util_snprintf(dst, size,
+ "\\??\\%s%s%s",
+ need_drive ? "C:" : "",
+ need_root ? "\\" : "",
+ src);
+}
+
+
+struct util_stream *
+util_stream_create(const char *filename, size_t max_size)
+{
+ struct util_stream *stream;
+
+ stream = CALLOC_STRUCT(util_stream);
+ if(!stream)
+ goto error1;
+
+ util_stream_full_qualified_filename(stream->filename,
+ sizeof(stream->filename),
+ filename);
+
+ if(max_size) {
+ stream->growable = FALSE;
+ stream->map_size = max_size;
+ }
+ else {
+ stream->growable = TRUE;
+ stream->map_size = MAP_FILE_SIZE;
+ }
+
+ if(!util_stream_map(stream))
+ goto error2;
+
+ return stream;
+
+error2:
+ FREE(stream);
+error1:
+ return NULL;
+}
+
+
+static INLINE void
+util_stream_copy(struct util_stream *stream, const char *data, size_t size)
+{
+ assert(stream->written + size <= stream->map_size);
+ memcpy(stream->pMap + stream->written, data, size);
+ stream->written += size;
+}
+
+
+boolean
+util_stream_write(struct util_stream *stream, const void *data, size_t size)
+{
+ if(!stream)
+ return FALSE;
+
+ if(!stream->pMap)
+ return FALSE;
+
+ while(stream->written + size > stream->map_size) {
+ size_t step = stream->map_size - stream->written;
+ util_stream_copy(stream, data, step);
+ data = (const char *)data + step;
+ size -= step;
+
+ util_stream_unmap(stream);
+ if(!stream->growable || !util_stream_map(stream))
+ return FALSE;
+ }
+
+ util_stream_copy(stream, data, size);
+
+ return TRUE;
+}
+
+
+void
+util_stream_flush(struct util_stream *stream)
+{
+ (void)stream;
+}
+
+
+void
+util_stream_close(struct util_stream *stream)
+{
+ if(!stream)
+ return;
+
+ util_stream_unmap(stream);
+
+ FREE(stream);
+}
+
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_string.h b/src/gallium/auxiliary/util/u_string.h
new file mode 100644
index 0000000000..cc7992d739
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_string.h
@@ -0,0 +1,220 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Platform independent functions for string manipulation.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef U_STRING_H_
+#define U_STRING_H_
+
+#if !defined(WIN32) && !defined(XF86_LIBC_H)
+#include <stdio.h>
+#endif
+#include <stddef.h>
+#include <stdarg.h>
+
+#include "pipe/p_compiler.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef WIN32
+
+int util_vsnprintf(char *, size_t, const char *, va_list);
+int util_snprintf(char *str, size_t size, const char *format, ...);
+
+static INLINE void
+util_vsprintf(char *str, const char *format, va_list ap)
+{
+ util_vsnprintf(str, (size_t)-1, format, ap);
+}
+
+static INLINE void
+util_sprintf(char *str, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ util_vsnprintf(str, (size_t)-1, format, ap);
+ va_end(ap);
+}
+
+static INLINE char *
+util_strchr(const char *s, char c)
+{
+ while(*s) {
+ if(*s == c)
+ return (char *)s;
+ ++s;
+ }
+ return NULL;
+}
+
+static INLINE char*
+util_strncat(char *dst, const char *src, size_t n)
+{
+ char *p = dst + strlen(dst);
+ const char *q = src;
+ size_t i;
+
+ for (i = 0; i < n && *q != '\0'; ++i)
+ *p++ = *q++;
+ *p = '\0';
+
+ return dst;
+}
+
+static INLINE int
+util_strcmp(const char *s1, const char *s2)
+{
+ unsigned char u1, u2;
+
+ while (1) {
+ u1 = (unsigned char) *s1++;
+ u2 = (unsigned char) *s2++;
+ if (u1 != u2)
+ return u1 - u2;
+ if (u1 == '\0')
+ return 0;
+ }
+ return 0;
+}
+
+static INLINE int
+util_strncmp(const char *s1, const char *s2, size_t n)
+{
+ unsigned char u1, u2;
+
+ while (n-- > 0) {
+ u1 = (unsigned char) *s1++;
+ u2 = (unsigned char) *s2++;
+ if (u1 != u2)
+ return u1 - u2;
+ if (u1 == '\0')
+ return 0;
+ }
+ return 0;
+}
+
+static INLINE char *
+util_strstr(const char *haystack, const char *needle)
+{
+ const char *p = haystack;
+ size_t len = strlen(needle);
+
+ for (; (p = util_strchr(p, *needle)) != 0; p++) {
+ if (util_strncmp(p, needle, len) == 0) {
+ return (char *)p;
+ }
+ }
+ return NULL;
+}
+
+static INLINE void *
+util_memmove(void *dest, const void *src, size_t n)
+{
+ char *p = (char *)dest;
+ const char *q = (const char *)src;
+ if (dest < src) {
+ while (n--)
+ *p++ = *q++;
+ }
+ else
+ {
+ p += n;
+ q += n;
+ while (n--)
+ *--p = *--q;
+ }
+ return dest;
+}
+
+
+#else
+
+#define util_vsnprintf vsnprintf
+#define util_snprintf snprintf
+#define util_vsprintf vsprintf
+#define util_sprintf sprintf
+#define util_strchr strchr
+#define util_strcmp strcmp
+#define util_strncmp strncmp
+#define util_strncat strncat
+#define util_strstr strstr
+#define util_memmove memmove
+
+#endif
+
+
+/**
+ * Printable string buffer
+ */
+struct util_strbuf
+{
+ char *str;
+ char *ptr;
+ size_t left;
+};
+
+
+static INLINE void
+util_strbuf_init(struct util_strbuf *sbuf, char *str, size_t size)
+{
+ sbuf->str = str;
+ sbuf->str[0] = 0;
+ sbuf->ptr = sbuf->str;
+ sbuf->left = size;
+}
+
+
+static INLINE void
+util_strbuf_printf(struct util_strbuf *sbuf, const char *format, ...)
+{
+ if(sbuf->left > 1) {
+ size_t written;
+ va_list ap;
+ va_start(ap, format);
+ written = util_vsnprintf(sbuf->ptr, sbuf->left, format, ap);
+ va_end(ap);
+ sbuf->ptr += written;
+ sbuf->left -= written;
+ }
+}
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_STRING_H_ */
diff --git a/src/gallium/auxiliary/util/u_surface.c b/src/gallium/auxiliary/util/u_surface.c
new file mode 100644
index 0000000000..85e443204e
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_surface.c
@@ -0,0 +1,113 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Surface utility functions.
+ *
+ * @author Brian Paul
+ */
+
+
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+
+#include "util/u_surface.h"
+
+
+/**
+ * Helper to quickly create an RGBA rendering surface of a certain size.
+ * \param textureOut returns the new texture
+ * \param surfaceOut returns the new surface
+ * \return TRUE for success, FALSE if failure
+ */
+boolean
+util_create_rgba_surface(struct pipe_screen *screen,
+ uint width, uint height,
+ struct pipe_texture **textureOut,
+ struct pipe_surface **surfaceOut)
+{
+ static const enum pipe_format rgbaFormats[] = {
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_NONE
+ };
+ const uint target = PIPE_TEXTURE_2D;
+ const uint usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ enum pipe_format format = PIPE_FORMAT_NONE;
+ struct pipe_texture templ;
+ uint i;
+
+ /* Choose surface format */
+ for (i = 0; rgbaFormats[i]; i++) {
+ if (screen->is_format_supported(screen, rgbaFormats[i],
+ target, usage, 0)) {
+ format = rgbaFormats[i];
+ break;
+ }
+ }
+ if (format == PIPE_FORMAT_NONE)
+ return FALSE; /* unable to get an rgba format!?! */
+
+ /* create texture */
+ memset(&templ, 0, sizeof(templ));
+ templ.target = target;
+ templ.format = format;
+ templ.last_level = 0;
+ templ.width[0] = width;
+ templ.height[0] = height;
+ templ.depth[0] = 1;
+ pf_get_block(format, &templ.block);
+ templ.tex_usage = usage;
+
+ *textureOut = screen->texture_create(screen, &templ);
+ if (!*textureOut)
+ return FALSE;
+
+ /* create surface / view into texture */
+ *surfaceOut = screen->get_tex_surface(screen, *textureOut, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE);
+ if (!*surfaceOut) {
+ pipe_texture_reference(textureOut, NULL);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * Release the surface and texture from util_create_rgba_surface().
+ */
+void
+util_destroy_rgba_surface(struct pipe_texture *texture,
+ struct pipe_surface *surface)
+{
+ pipe_surface_reference(&surface, NULL);
+ pipe_texture_reference(&texture, NULL);
+}
+
diff --git a/src/gallium/auxiliary/util/u_surface.h b/src/gallium/auxiliary/util/u_surface.h
new file mode 100644
index 0000000000..ce84ed7ad0
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_surface.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef U_SURFACE_H
+#define U_SURFACE_H
+
+
+#include "pipe/p_compiler.h"
+
+
+struct pipe_screen;
+struct pipe_texture;
+struct pipe_surface;
+
+
+/**
+ * Are s1 and s2 the same surface?
+ * Surfaces are basically views into textures so check if the two surfaces
+ * name the same part of the same texture.
+ */
+static INLINE boolean
+util_same_surface(const struct pipe_surface *s1, const struct pipe_surface *s2)
+{
+ return (s1->texture == s2->texture &&
+ s1->face == s2->face &&
+ s1->level == s2->level &&
+ s1->zslice == s2->zslice);
+}
+
+
+
+
+extern boolean
+util_create_rgba_surface(struct pipe_screen *screen,
+ uint width, uint height,
+ struct pipe_texture **textureOut,
+ struct pipe_surface **surfaceOut);
+
+
+extern void
+util_destroy_rgba_surface(struct pipe_texture *texture,
+ struct pipe_surface *surface);
+
+
+#endif /* U_SURFACE_H */
diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c
new file mode 100644
index 0000000000..0d6489c26e
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_tile.c
@@ -0,0 +1,1526 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * RGBA/float tile get/put functions.
+ * Usable both by drivers and state trackers.
+ */
+
+
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_rect.h"
+#include "util/u_tile.h"
+
+
+/**
+ * Move raw block of pixels from transfer object to user memory.
+ */
+void
+pipe_get_tile_raw(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ void *dst, int dst_stride)
+{
+ struct pipe_screen *screen = pt->texture->screen;
+ const void *src;
+
+ if (dst_stride == 0)
+ dst_stride = pf_get_nblocksx(&pt->block, w) * pt->block.size;
+
+ if (pipe_clip_tile(x, y, &w, &h, pt))
+ return;
+
+ src = screen->transfer_map(screen, pt);
+ assert(src);
+ if(!src)
+ return;
+
+ util_copy_rect(dst, &pt->block, dst_stride, 0, 0, w, h, src, pt->stride, x, y);
+
+ screen->transfer_unmap(screen, pt);
+}
+
+
+/**
+ * Move raw block of pixels from user memory to transfer object.
+ */
+void
+pipe_put_tile_raw(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ const void *src, int src_stride)
+{
+ struct pipe_screen *screen = pt->texture->screen;
+ void *dst;
+
+ if (src_stride == 0)
+ src_stride = pf_get_nblocksx(&pt->block, w) * pt->block.size;
+
+ if (pipe_clip_tile(x, y, &w, &h, pt))
+ return;
+
+ dst = screen->transfer_map(screen, pt);
+ assert(dst);
+ if(!dst)
+ return;
+
+ util_copy_rect(dst, &pt->block, pt->stride, x, y, w, h, src, src_stride, 0, 0);
+
+ screen->transfer_unmap(screen, pt);
+}
+
+
+
+
+/** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */
+#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
+
+#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
+ us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
+
+
+
+/*** PIPE_FORMAT_A8R8G8B8_UNORM ***/
+
+static void
+a8r8g8b8_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ const unsigned pixel = *src++;
+ pRow[0] = ubyte_to_float((pixel >> 16) & 0xff);
+ pRow[1] = ubyte_to_float((pixel >> 8) & 0xff);
+ pRow[2] = ubyte_to_float((pixel >> 0) & 0xff);
+ pRow[3] = ubyte_to_float((pixel >> 24) & 0xff);
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+a8r8g8b8_put_tile_rgba(unsigned *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r, g, b, a;
+ r = float_to_ubyte(pRow[0]);
+ g = float_to_ubyte(pRow[1]);
+ b = float_to_ubyte(pRow[2]);
+ a = float_to_ubyte(pRow[3]);
+ *dst++ = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_X8R8G8B8_UNORM ***/
+
+static void
+x8r8g8b8_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ const unsigned pixel = *src++;
+ pRow[0] = ubyte_to_float((pixel >> 16) & 0xff);
+ pRow[1] = ubyte_to_float((pixel >> 8) & 0xff);
+ pRow[2] = ubyte_to_float((pixel >> 0) & 0xff);
+ pRow[3] = 1.0F;
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+x8r8g8b8_put_tile_rgba(unsigned *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r, g, b;
+ r = float_to_ubyte(pRow[0]);
+ g = float_to_ubyte(pRow[1]);
+ b = float_to_ubyte(pRow[2]);
+ *dst++ = (0xff << 24) | (r << 16) | (g << 8) | b;
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_B8G8R8A8_UNORM ***/
+
+static void
+b8g8r8a8_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ const unsigned pixel = *src++;
+ pRow[0] = ubyte_to_float((pixel >> 8) & 0xff);
+ pRow[1] = ubyte_to_float((pixel >> 16) & 0xff);
+ pRow[2] = ubyte_to_float((pixel >> 24) & 0xff);
+ pRow[3] = ubyte_to_float((pixel >> 0) & 0xff);
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+b8g8r8a8_put_tile_rgba(unsigned *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r, g, b, a;
+ r = float_to_ubyte(pRow[0]);
+ g = float_to_ubyte(pRow[1]);
+ b = float_to_ubyte(pRow[2]);
+ a = float_to_ubyte(pRow[3]);
+ *dst++ = (b << 24) | (g << 16) | (r << 8) | a;
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_A1R5G5B5_UNORM ***/
+
+static void
+a1r5g5b5_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ const ushort pixel = *src++;
+ pRow[0] = ((pixel >> 10) & 0x1f) * (1.0f / 31.0f);
+ pRow[1] = ((pixel >> 5) & 0x1f) * (1.0f / 31.0f);
+ pRow[2] = ((pixel ) & 0x1f) * (1.0f / 31.0f);
+ pRow[3] = ((pixel >> 15) ) * 1.0f;
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+a1r5g5b5_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r, g, b, a;
+ r = float_to_ubyte(pRow[0]);
+ g = float_to_ubyte(pRow[1]);
+ b = float_to_ubyte(pRow[2]);
+ a = float_to_ubyte(pRow[3]);
+ r = r >> 3; /* 5 bits */
+ g = g >> 3; /* 5 bits */
+ b = b >> 3; /* 5 bits */
+ a = a >> 7; /* 1 bit */
+ *dst++ = (a << 15) | (r << 10) | (g << 5) | b;
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_A4R4G4B4_UNORM ***/
+
+static void
+a4r4g4b4_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ const ushort pixel = *src++;
+ pRow[0] = ((pixel >> 8) & 0xf) * (1.0f / 15.0f);
+ pRow[1] = ((pixel >> 4) & 0xf) * (1.0f / 15.0f);
+ pRow[2] = ((pixel ) & 0xf) * (1.0f / 15.0f);
+ pRow[3] = ((pixel >> 12) ) * (1.0f / 15.0f);
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+a4r4g4b4_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r, g, b, a;
+ r = float_to_ubyte(pRow[0]);
+ g = float_to_ubyte(pRow[1]);
+ b = float_to_ubyte(pRow[2]);
+ a = float_to_ubyte(pRow[3]);
+ r >>= 4;
+ g >>= 4;
+ b >>= 4;
+ a >>= 4;
+ *dst++ = (a << 12) | (r << 16) | (g << 4) | b;
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_R5G6B5_UNORM ***/
+
+static void
+r5g6b5_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ const ushort pixel = *src++;
+ pRow[0] = ((pixel >> 11) & 0x1f) * (1.0f / 31.0f);
+ pRow[1] = ((pixel >> 5) & 0x3f) * (1.0f / 63.0f);
+ pRow[2] = ((pixel ) & 0x1f) * (1.0f / 31.0f);
+ pRow[3] = 1.0f;
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+r5g6b5_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ uint r = (uint) (CLAMP(pRow[0], 0.0, 1.0) * 31.0);
+ uint g = (uint) (CLAMP(pRow[1], 0.0, 1.0) * 63.0);
+ uint b = (uint) (CLAMP(pRow[2], 0.0, 1.0) * 31.0);
+ *dst++ = (r << 11) | (g << 5) | (b);
+ }
+ p += src_stride;
+ }
+}
+
+
+
+/*** PIPE_FORMAT_R8G8B8_UNORM ***/
+
+static void
+r8g8b8_get_tile_rgba(const ubyte *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ pRow[0] = ubyte_to_float(src[0]);
+ pRow[1] = ubyte_to_float(src[1]);
+ pRow[2] = ubyte_to_float(src[2]);
+ pRow[3] = 1.0f;
+ src += 3;
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+r8g8b8_put_tile_rgba(ubyte *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ dst[0] = float_to_ubyte(pRow[0]);
+ dst[1] = float_to_ubyte(pRow[1]);
+ dst[2] = float_to_ubyte(pRow[2]);
+ dst += 3;
+ }
+ p += src_stride;
+ }
+}
+
+
+
+/*** PIPE_FORMAT_Z16_UNORM ***/
+
+/**
+ * Return each Z value as four floats in [0,1].
+ */
+static void
+z16_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ const float scale = 1.0f / 65535.0f;
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] =
+ pRow[3] = *src++ * scale;
+ }
+ p += dst_stride;
+ }
+}
+
+
+
+
+/*** PIPE_FORMAT_L8_UNORM ***/
+
+static void
+l8_get_tile_rgba(const ubyte *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, src++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] = ubyte_to_float(*src);
+ pRow[3] = 1.0;
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+l8_put_tile_rgba(ubyte *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r;
+ r = float_to_ubyte(pRow[0]);
+ *dst++ = (ubyte) r;
+ }
+ p += src_stride;
+ }
+}
+
+
+
+/*** PIPE_FORMAT_A8_UNORM ***/
+
+static void
+a8_get_tile_rgba(const ubyte *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, src++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] = 0.0;
+ pRow[3] = ubyte_to_float(*src);
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+a8_put_tile_rgba(ubyte *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned a;
+ a = float_to_ubyte(pRow[3]);
+ *dst++ = (ubyte) a;
+ }
+ p += src_stride;
+ }
+}
+
+
+
+/*** PIPE_FORMAT_R16_SNORM ***/
+
+static void
+r16_get_tile_rgba(const short *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, src++, pRow += 4) {
+ pRow[0] = SHORT_TO_FLOAT(src[0]);
+ pRow[1] =
+ pRow[2] = 0.0;
+ pRow[3] = 1.0;
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+r16_put_tile_rgba(short *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, dst++, pRow += 4) {
+ UNCLAMPED_FLOAT_TO_SHORT(dst[0], pRow[0]);
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_R16G16B16A16_SNORM ***/
+
+static void
+r16g16b16a16_get_tile_rgba(const short *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, src += 4, pRow += 4) {
+ pRow[0] = SHORT_TO_FLOAT(src[0]);
+ pRow[1] = SHORT_TO_FLOAT(src[1]);
+ pRow[2] = SHORT_TO_FLOAT(src[2]);
+ pRow[3] = SHORT_TO_FLOAT(src[3]);
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+r16g16b16a16_put_tile_rgba(short *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, dst += 4, pRow += 4) {
+ UNCLAMPED_FLOAT_TO_SHORT(dst[0], pRow[0]);
+ UNCLAMPED_FLOAT_TO_SHORT(dst[1], pRow[1]);
+ UNCLAMPED_FLOAT_TO_SHORT(dst[2], pRow[2]);
+ UNCLAMPED_FLOAT_TO_SHORT(dst[3], pRow[3]);
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_R8G8B8A8_SRGB ***/
+
+/**
+ * Convert an 8-bit sRGB value from non-linear space to a
+ * linear RGB value in [0, 1].
+ * Implemented with a 256-entry lookup table.
+ */
+static INLINE float
+srgb_to_linear(ubyte cs8)
+{
+ static float table[256];
+ static boolean tableReady = FALSE;
+ if (!tableReady) {
+ /* compute lookup table now */
+ uint i;
+ for (i = 0; i < 256; i++) {
+ const float cs = ubyte_to_float(i);
+ if (cs <= 0.04045) {
+ table[i] = cs / 12.92f;
+ }
+ else {
+ table[i] = (float) powf((cs + 0.055) / 1.055, 2.4);
+ }
+ }
+ tableReady = TRUE;
+ }
+ return table[cs8];
+}
+
+
+/**
+ * Convert linear float in [0,1] to an srgb ubyte value in [0,255].
+ * XXX this hasn't been tested (render to srgb surface).
+ * XXX this needs optimization.
+ */
+static INLINE ubyte
+linear_to_srgb(float cl)
+{
+ if (cl >= 1.0F)
+ return 255;
+ else if (cl >= 0.0031308F)
+ return float_to_ubyte(1.055F * powf(cl, 0.41666F) - 0.055F);
+ else if (cl > 0.0F)
+ return float_to_ubyte(12.92F * cl);
+ else
+ return 0.0;
+}
+
+
+static void
+a8r8g8b8_srgb_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ const unsigned pixel = *src++;
+ pRow[0] = srgb_to_linear((pixel >> 16) & 0xff);
+ pRow[1] = srgb_to_linear((pixel >> 8) & 0xff);
+ pRow[2] = srgb_to_linear((pixel >> 0) & 0xff);
+ pRow[3] = ubyte_to_float((pixel >> 24) & 0xff);
+ }
+ p += dst_stride;
+ }
+}
+
+static void
+a8r8g8b8_srgb_put_tile_rgba(unsigned *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r, g, b, a;
+ r = linear_to_srgb(pRow[0]);
+ g = linear_to_srgb(pRow[1]);
+ b = linear_to_srgb(pRow[2]);
+ a = float_to_ubyte(pRow[3]);
+ *dst++ = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_A8L8_SRGB ***/
+
+static void
+a8l8_srgb_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ ushort p = *src++;
+ pRow[0] =
+ pRow[1] =
+ pRow[2] = srgb_to_linear(p & 0xff);
+ pRow[3] = ubyte_to_float(p >> 8);
+ }
+ p += dst_stride;
+ }
+}
+
+static void
+a8l8_srgb_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r, a;
+ r = linear_to_srgb(pRow[0]);
+ a = float_to_ubyte(pRow[3]);
+ *dst++ = (a << 8) | r;
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_L8_SRGB ***/
+
+static void
+l8_srgb_get_tile_rgba(const ubyte *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, src++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] = srgb_to_linear(*src);
+ pRow[3] = 1.0;
+ }
+ p += dst_stride;
+ }
+}
+
+static void
+l8_srgb_put_tile_rgba(ubyte *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r;
+ r = linear_to_srgb(pRow[0]);
+ *dst++ = (ubyte) r;
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_I8_UNORM ***/
+
+static void
+i8_get_tile_rgba(const ubyte *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, src++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] =
+ pRow[3] = ubyte_to_float(*src);
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+i8_put_tile_rgba(ubyte *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r;
+ r = float_to_ubyte(pRow[0]);
+ *dst++ = (ubyte) r;
+ }
+ p += src_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_A8L8_UNORM ***/
+
+static void
+a8l8_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ ushort p = *src++;
+ pRow[0] =
+ pRow[1] =
+ pRow[2] = ubyte_to_float(p & 0xff);
+ pRow[3] = ubyte_to_float(p >> 8);
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+a8l8_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const float *p,
+ unsigned src_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ const float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ unsigned r, a;
+ r = float_to_ubyte(pRow[0]);
+ a = float_to_ubyte(pRow[3]);
+ *dst++ = (a << 8) | r;
+ }
+ p += src_stride;
+ }
+}
+
+
+
+
+/*** PIPE_FORMAT_Z32_UNORM ***/
+
+/**
+ * Return each Z value as four floats in [0,1].
+ */
+static void
+z32_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ const double scale = 1.0 / (double) 0xffffffff;
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] =
+ pRow[3] = (float) (*src++ * scale);
+ }
+ p += dst_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_S8Z24_UNORM ***/
+
+/**
+ * Return Z component as four float in [0,1]. Stencil part ignored.
+ */
+static void
+s8z24_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ const double scale = 1.0 / ((1 << 24) - 1);
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] =
+ pRow[3] = (float) (scale * (*src++ & 0xffffff));
+ }
+ p += dst_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_Z24S8_UNORM ***/
+
+/**
+ * Return Z component as four float in [0,1]. Stencil part ignored.
+ */
+static void
+z24s8_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ const double scale = 1.0 / ((1 << 24) - 1);
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] =
+ pRow[3] = (float) (scale * (*src++ >> 8));
+ }
+ p += dst_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_Z32_FLOAT ***/
+
+/**
+ * Return each Z value as four floats in [0,1].
+ */
+static void
+z32f_get_tile_rgba(const float *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] =
+ pRow[3] = *src++;
+ }
+ p += dst_stride;
+ }
+}
+
+
+/*** PIPE_FORMAT_YCBCR / PIPE_FORMAT_YCBCR_REV ***/
+
+/**
+ * Convert YCbCr (or YCrCb) to RGBA.
+ */
+static void
+ycbcr_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride,
+ boolean rev)
+{
+ const float scale = 1.0f / 255.0f;
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ /* do two texels at a time */
+ for (j = 0; j < (w & ~1); j += 2, src += 2) {
+ const ushort t0 = src[0];
+ const ushort t1 = src[1];
+ const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */
+ const ubyte y1 = (t1 >> 8) & 0xff; /* luminance */
+ ubyte cb, cr;
+ float r, g, b;
+
+ if (rev) {
+ cb = t1 & 0xff; /* chroma U */
+ cr = t0 & 0xff; /* chroma V */
+ }
+ else {
+ cb = t0 & 0xff; /* chroma U */
+ cr = t1 & 0xff; /* chroma V */
+ }
+
+ /* even pixel: y0,cr,cb */
+ r = 1.164f * (y0-16) + 1.596f * (cr-128);
+ g = 1.164f * (y0-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
+ b = 1.164f * (y0-16) + 2.018f * (cb-128);
+ pRow[0] = r * scale;
+ pRow[1] = g * scale;
+ pRow[2] = b * scale;
+ pRow[3] = 1.0f;
+ pRow += 4;
+
+ /* odd pixel: use y1,cr,cb */
+ r = 1.164f * (y1-16) + 1.596f * (cr-128);
+ g = 1.164f * (y1-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
+ b = 1.164f * (y1-16) + 2.018f * (cb-128);
+ pRow[0] = r * scale;
+ pRow[1] = g * scale;
+ pRow[2] = b * scale;
+ pRow[3] = 1.0f;
+ pRow += 4;
+
+ }
+ /* do the last texel */
+ if (w & 1) {
+ const ushort t0 = src[0];
+ const ushort t1 = src[1];
+ const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */
+ ubyte cb, cr;
+ float r, g, b;
+
+ if (rev) {
+ cb = t1 & 0xff; /* chroma U */
+ cr = t0 & 0xff; /* chroma V */
+ }
+ else {
+ cb = t0 & 0xff; /* chroma U */
+ cr = t1 & 0xff; /* chroma V */
+ }
+
+ /* even pixel: y0,cr,cb */
+ r = 1.164f * (y0-16) + 1.596f * (cr-128);
+ g = 1.164f * (y0-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
+ b = 1.164f * (y0-16) + 2.018f * (cb-128);
+ pRow[0] = r * scale;
+ pRow[1] = g * scale;
+ pRow[2] = b * scale;
+ pRow[3] = 1.0f;
+ pRow += 4;
+ }
+ p += dst_stride;
+ }
+}
+
+
+static void
+fake_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ float *p,
+ unsigned dst_stride)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ float *pRow = p;
+ for (j = 0; j < w; j++, pRow += 4) {
+ pRow[0] =
+ pRow[1] =
+ pRow[2] =
+ pRow[3] = (i ^ j) & 1 ? 1.0f : 0.0f;
+ }
+ p += dst_stride;
+ }
+}
+
+
+void
+pipe_tile_raw_to_rgba(enum pipe_format format,
+ void *src,
+ uint w, uint h,
+ float *dst, unsigned dst_stride)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ a8r8g8b8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ x8r8g8b8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ b8g8r8a8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ a1r5g5b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ a4r4g4b4_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ r5g6b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ r8g8b8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_L8_UNORM:
+ l8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_A8_UNORM:
+ a8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_I8_UNORM:
+ i8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_A8L8_UNORM:
+ a8l8_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_R16_SNORM:
+ r16_get_tile_rgba((short *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ r16g16b16a16_get_tile_rgba((short *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_A8R8G8B8_SRGB:
+ a8r8g8b8_srgb_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_A8L8_SRGB:
+ a8l8_srgb_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_L8_SRGB:
+ l8_srgb_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_Z32_UNORM:
+ z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ z24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_Z32_FLOAT:
+ z32f_get_tile_rgba((float *) src, w, h, dst, dst_stride);
+ break;
+ case PIPE_FORMAT_YCBCR:
+ ycbcr_get_tile_rgba((ushort *) src, w, h, dst, dst_stride, FALSE);
+ break;
+ case PIPE_FORMAT_YCBCR_REV:
+ ycbcr_get_tile_rgba((ushort *) src, w, h, dst, dst_stride, TRUE);
+ break;
+ default:
+ debug_printf("%s: unsupported format %s\n", __FUNCTION__, pf_name(format));
+ fake_get_tile_rgba(src, w, h, dst, dst_stride);
+ }
+}
+
+
+void
+pipe_get_tile_rgba(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ float *p)
+{
+ unsigned dst_stride = w * 4;
+ void *packed;
+
+ if (pipe_clip_tile(x, y, &w, &h, pt))
+ return;
+
+ packed = MALLOC(pf_get_nblocks(&pt->block, w, h) * pt->block.size);
+
+ if (!packed)
+ return;
+
+ if(pt->format == PIPE_FORMAT_YCBCR || pt->format == PIPE_FORMAT_YCBCR_REV)
+ assert((x & 1) == 0);
+
+ pipe_get_tile_raw(pt, x, y, w, h, packed, 0);
+
+ pipe_tile_raw_to_rgba(pt->format, packed, w, h, p, dst_stride);
+
+ FREE(packed);
+}
+
+
+void
+pipe_put_tile_rgba(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ const float *p)
+{
+ unsigned src_stride = w * 4;
+ void *packed;
+
+ if (pipe_clip_tile(x, y, &w, &h, pt))
+ return;
+
+ packed = MALLOC(pf_get_nblocks(&pt->block, w, h) * pt->block.size);
+
+ if (!packed)
+ return;
+
+ switch (pt->format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ a8r8g8b8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ x8r8g8b8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ b8g8r8a8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ a1r5g5b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ r5g6b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ r8g8b8_put_tile_rgba((ubyte *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ assert(0);
+ break;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ a4r4g4b4_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_L8_UNORM:
+ l8_put_tile_rgba((ubyte *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_A8_UNORM:
+ a8_put_tile_rgba((ubyte *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_I8_UNORM:
+ i8_put_tile_rgba((ubyte *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_A8L8_UNORM:
+ a8l8_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_R16_SNORM:
+ r16_put_tile_rgba((short *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ r16g16b16a16_put_tile_rgba((short *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_A8R8G8B8_SRGB:
+ a8r8g8b8_srgb_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_A8L8_SRGB:
+ a8l8_srgb_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_L8_SRGB:
+ l8_srgb_put_tile_rgba((ubyte *) packed, w, h, p, src_stride);
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/
+ break;
+ case PIPE_FORMAT_Z32_UNORM:
+ /*z32_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ /*s8z24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
+ break;
+ default:
+ debug_printf("%s: unsupported format %s\n", __FUNCTION__, pf_name(pt->format));
+ }
+
+ pipe_put_tile_raw(pt, x, y, w, h, packed, 0);
+
+ FREE(packed);
+}
+
+
+/**
+ * Get a block of Z values, converted to 32-bit range.
+ */
+void
+pipe_get_tile_z(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ uint *z)
+{
+ struct pipe_screen *screen = pt->texture->screen;
+ const uint dstStride = w;
+ ubyte *map;
+ uint *pDest = z;
+ uint i, j;
+
+ if (pipe_clip_tile(x, y, &w, &h, pt))
+ return;
+
+ map = (ubyte *)screen->transfer_map(screen, pt);
+ if (!map) {
+ assert(0);
+ return;
+ }
+
+ switch (pt->format) {
+ case PIPE_FORMAT_Z32_UNORM:
+ {
+ const uint *ptrc
+ = (const uint *)(map + y * pt->stride + x*4);
+ for (i = 0; i < h; i++) {
+ memcpy(pDest, ptrc, 4 * w);
+ pDest += dstStride;
+ ptrc += pt->stride/4;
+ }
+ }
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ {
+ const uint *ptrc
+ = (const uint *)(map + y * pt->stride + x*4);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ /* convert 24-bit Z to 32-bit Z */
+ pDest[j] = (ptrc[j] << 8) | ((ptrc[j] >> 16) & 0xff);
+ }
+ pDest += dstStride;
+ ptrc += pt->stride/4;
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ {
+ const uint *ptrc
+ = (const uint *)(map + y * pt->stride + x*4);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ /* convert 24-bit Z to 32-bit Z */
+ pDest[j] = (ptrc[j] & 0xffffff00) | ((ptrc[j] >> 24) & 0xff);
+ }
+ pDest += dstStride;
+ ptrc += pt->stride/4;
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ {
+ const ushort *ptrc
+ = (const ushort *)(map + y * pt->stride + x*2);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ /* convert 16-bit Z to 32-bit Z */
+ pDest[j] = (ptrc[j] << 16) | ptrc[j];
+ }
+ pDest += dstStride;
+ ptrc += pt->stride/2;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ screen->transfer_unmap(screen, pt);
+}
+
+
+void
+pipe_put_tile_z(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ const uint *zSrc)
+{
+ struct pipe_screen *screen = pt->texture->screen;
+ const uint srcStride = w;
+ const uint *ptrc = zSrc;
+ ubyte *map;
+ uint i, j;
+
+ if (pipe_clip_tile(x, y, &w, &h, pt))
+ return;
+
+ map = (ubyte *)screen->transfer_map(screen, pt);
+ if (!map) {
+ assert(0);
+ return;
+ }
+
+ switch (pt->format) {
+ case PIPE_FORMAT_Z32_UNORM:
+ {
+ uint *pDest = (uint *) (map + y * pt->stride + x*4);
+ for (i = 0; i < h; i++) {
+ memcpy(pDest, ptrc, 4 * w);
+ pDest += pt->stride/4;
+ ptrc += srcStride;
+ }
+ }
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ {
+ uint *pDest = (uint *) (map + y * pt->stride + x*4);
+ assert(pt->usage == PIPE_TRANSFER_READ_WRITE);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ /* convert 32-bit Z to 24-bit Z, preserve stencil */
+ pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8;
+ }
+ pDest += pt->stride/4;
+ ptrc += srcStride;
+ }
+ }
+ break;
+ case PIPE_FORMAT_X8Z24_UNORM:
+ {
+ uint *pDest = (uint *) (map + y * pt->stride + x*4);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ /* convert 32-bit Z to 24-bit Z (0 stencil) */
+ pDest[j] = ptrc[j] >> 8;
+ }
+ pDest += pt->stride/4;
+ ptrc += srcStride;
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ {
+ uint *pDest = (uint *) (map + y * pt->stride + x*4);
+ assert(pt->usage == PIPE_TRANSFER_READ_WRITE);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ /* convert 32-bit Z to 24-bit Z, preserve stencil */
+ pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00);
+ }
+ pDest += pt->stride/4;
+ ptrc += srcStride;
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z24X8_UNORM:
+ {
+ uint *pDest = (uint *) (map + y * pt->stride + x*4);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ /* convert 32-bit Z to 24-bit Z (0 stencil) */
+ pDest[j] = ptrc[j] & 0xffffff00;
+ }
+ pDest += pt->stride/4;
+ ptrc += srcStride;
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ {
+ ushort *pDest = (ushort *) (map + y * pt->stride + x*2);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ /* convert 32-bit Z to 16-bit Z */
+ pDest[j] = ptrc[j] >> 16;
+ }
+ pDest += pt->stride/2;
+ ptrc += srcStride;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ screen->transfer_unmap(screen, pt);
+}
+
+
diff --git a/src/gallium/auxiliary/util/u_tile.h b/src/gallium/auxiliary/util/u_tile.h
new file mode 100644
index 0000000000..1453af38b8
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_tile.h
@@ -0,0 +1,101 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef P_TILE_H
+#define P_TILE_H
+
+#include "pipe/p_compiler.h"
+
+struct pipe_transfer;
+
+
+/**
+ * Clip tile against transfer dims.
+ * \return TRUE if tile is totally clipped, FALSE otherwise
+ */
+static INLINE boolean
+pipe_clip_tile(uint x, uint y, uint *w, uint *h, const struct pipe_transfer *pt)
+{
+ if (x >= pt->width)
+ return TRUE;
+ if (y >= pt->height)
+ return TRUE;
+ if (x + *w > pt->width)
+ *w = pt->width - x;
+ if (y + *h > pt->height)
+ *h = pt->height - y;
+ return FALSE;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+pipe_get_tile_raw(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ void *p, int dst_stride);
+
+void
+pipe_put_tile_raw(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ const void *p, int src_stride);
+
+
+void
+pipe_get_tile_rgba(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ float *p);
+
+void
+pipe_put_tile_rgba(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ const float *p);
+
+
+void
+pipe_get_tile_z(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ uint *z);
+
+void
+pipe_put_tile_z(struct pipe_transfer *pt,
+ uint x, uint y, uint w, uint h,
+ const uint *z);
+
+void
+pipe_tile_raw_to_rgba(enum pipe_format format,
+ void *src,
+ uint w, uint h,
+ float *dst, unsigned dst_stride);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_time.c b/src/gallium/auxiliary/util/u_time.c
new file mode 100644
index 0000000000..b958a98635
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_time.c
@@ -0,0 +1,225 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * OS independent time-manipulation functions.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU)
+#include <sys/time.h>
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+#include <windows.h>
+#include <winddi.h>
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+#include <windows.h>
+extern VOID KeQuerySystemTime(PLARGE_INTEGER);
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+#include <windows.h>
+#else
+#error Unsupported OS
+#endif
+
+#include "util/u_time.h"
+
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+
+static int64_t frequency = 0;
+
+static INLINE void
+util_time_get_frequency(void)
+{
+ if(!frequency) {
+#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+ LONGLONG temp;
+ EngQueryPerformanceFrequency(&temp);
+ frequency = temp;
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+ LARGE_INTEGER temp;
+ QueryPerformanceFrequency(&temp);
+ frequency = temp.QuadPart;
+#endif
+ }
+}
+#endif
+
+
+void
+util_time_get(struct util_time *t)
+{
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU)
+ gettimeofday(&t->tv, NULL);
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+ LONGLONG temp;
+ EngQueryPerformanceCounter(&temp);
+ t->counter = temp;
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+ /* Updated every 10 miliseconds, measured in units of 100 nanoseconds.
+ * http://msdn.microsoft.com/en-us/library/ms801642.aspx */
+ LARGE_INTEGER temp;
+ KeQuerySystemTime(&temp);
+ t->counter = temp.QuadPart;
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+ LARGE_INTEGER temp;
+ QueryPerformanceCounter(&temp);
+ t->counter = temp.QuadPart;
+#endif
+}
+
+
+void
+util_time_add(const struct util_time *t1,
+ int64_t usecs,
+ struct util_time *t2)
+{
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU)
+ t2->tv.tv_sec = t1->tv.tv_sec + usecs / 1000000;
+ t2->tv.tv_usec = t1->tv.tv_usec + usecs % 1000000;
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+ util_time_get_frequency();
+ t2->counter = t1->counter + (usecs * frequency + INT64_C(999999))/INT64_C(1000000);
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+ /* 1 tick = 100 nano seconds. */
+ t2->counter = t1->counter + usecs * 10;
+#else
+ LARGE_INTEGER temp;
+ LONGLONG freq;
+ freq = temp.QuadPart;
+ t2->counter = t1->counter + (usecs * freq)/1000000L;
+#endif
+}
+
+
+int64_t
+util_time_diff(const struct util_time *t1,
+ const struct util_time *t2)
+{
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU)
+ return (t2->tv.tv_usec - t1->tv.tv_usec) +
+ (t2->tv.tv_sec - t1->tv.tv_sec)*1000000;
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+ util_time_get_frequency();
+ return (t2->counter - t1->counter)*INT64_C(1000000)/frequency;
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+ return (t2->counter - t1->counter)/10;
+#endif
+}
+
+
+
+uint64_t
+util_time_micros( void )
+{
+ struct util_time t1;
+
+ util_time_get(&t1);
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU)
+ return t1.tv.tv_usec + t1.tv.tv_sec*1000000LL;
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+ util_time_get_frequency();
+ return t1.counter*INT64_C(1000000)/frequency;
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+ return t1.counter/10;
+#endif
+}
+
+
+
+/**
+ * Compare two time values.
+ *
+ * Not publicly available because it does not take in account wrap-arounds.
+ * Use util_time_timeout instead.
+ */
+static INLINE int
+util_time_compare(const struct util_time *t1,
+ const struct util_time *t2)
+{
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU)
+ if (t1->tv.tv_sec < t2->tv.tv_sec)
+ return -1;
+ else if(t1->tv.tv_sec > t2->tv.tv_sec)
+ return 1;
+ else if (t1->tv.tv_usec < t2->tv.tv_usec)
+ return -1;
+ else if(t1->tv.tv_usec > t2->tv.tv_usec)
+ return 1;
+ else
+ return 0;
+#elif defined(PIPE_OS_WINDOWS)
+ if (t1->counter < t2->counter)
+ return -1;
+ else if(t1->counter > t2->counter)
+ return 1;
+ else
+ return 0;
+#endif
+}
+
+
+boolean
+util_time_timeout(const struct util_time *start,
+ const struct util_time *end,
+ const struct util_time *curr)
+{
+ if(util_time_compare(start, end) <= 0)
+ return !(util_time_compare(start, curr) <= 0 && util_time_compare(curr, end) < 0);
+ else
+ return !(util_time_compare(start, curr) <= 0 || util_time_compare(curr, end) < 0);
+}
+
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+void util_time_sleep(unsigned usecs)
+{
+ LONGLONG start, curr, end;
+
+ EngQueryPerformanceCounter(&start);
+
+ if(!frequency)
+ EngQueryPerformanceFrequency(&frequency);
+
+ end = start + (usecs * frequency + 999999LL)/1000000LL;
+
+ do {
+ EngQueryPerformanceCounter(&curr);
+ } while(start <= curr && curr < end ||
+ end < start && (curr < end || start <= curr));
+}
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+void util_time_sleep(unsigned usecs)
+{
+ Sleep((usecs + 999)/ 1000);
+}
+#endif
diff --git a/src/gallium/auxiliary/util/u_time.h b/src/gallium/auxiliary/util/u_time.h
new file mode 100644
index 0000000000..a6189a247b
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_time.h
@@ -0,0 +1,109 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * OS independent time-manipulation functions.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef U_TIME_H_
+#define U_TIME_H_
+
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE)
+#include <time.h> /* timeval */
+#include <unistd.h> /* usleep */
+#endif
+
+#if defined(PIPE_OS_HAIKU)
+#include <sys/time.h> /* timeval */
+#include <unistd.h>
+#endif
+
+#include "pipe/p_compiler.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Time abstraction.
+ *
+ * Do not access this structure directly. Use the provided function instead.
+ */
+struct util_time
+{
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU)
+ struct timeval tv;
+#else
+ int64_t counter;
+#endif
+};
+
+
+void
+util_time_get(struct util_time *t);
+
+void
+util_time_add(const struct util_time *t1,
+ int64_t usecs,
+ struct util_time *t2);
+
+uint64_t
+util_time_micros( void );
+
+int64_t
+util_time_diff(const struct util_time *t1,
+ const struct util_time *t2);
+
+/**
+ * Returns non-zero when the timeout expires.
+ */
+boolean
+util_time_timeout(const struct util_time *start,
+ const struct util_time *end,
+ const struct util_time *curr);
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU)
+#define util_time_sleep usleep
+#else
+void
+util_time_sleep(unsigned usecs);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_TIME_H_ */
diff --git a/src/gallium/auxiliary/util/u_timed_winsys.c b/src/gallium/auxiliary/util/u_timed_winsys.c
new file mode 100644
index 0000000000..178acdca4d
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_timed_winsys.c
@@ -0,0 +1,318 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+/*
+ * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ */
+
+#include "pipe/p_state.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "u_timed_winsys.h"
+#include "util/u_memory.h"
+#include "util/u_time.h"
+
+
+struct timed_winsys {
+ struct pipe_winsys base;
+ struct pipe_winsys *backend;
+ uint64_t last_dump;
+ struct {
+ const char *name_key;
+ double total;
+ unsigned calls;
+ } funcs[13];
+};
+
+
+static struct timed_winsys *timed_winsys( struct pipe_winsys *winsys )
+{
+ return (struct timed_winsys *)winsys;
+}
+
+
+static uint64_t time_start( void )
+{
+ return util_time_micros();
+}
+
+
+static void time_display( struct pipe_winsys *winsys )
+{
+ struct timed_winsys *tws = timed_winsys(winsys);
+ unsigned i;
+ double overall = 0;
+
+ for (i = 0; i < Elements(tws->funcs); i++) {
+ if (tws->funcs[i].name_key) {
+ debug_printf("*** %-25s %5.3fms (%d calls, avg %.3fms)\n",
+ tws->funcs[i].name_key,
+ tws->funcs[i].total,
+ tws->funcs[i].calls,
+ tws->funcs[i].total / tws->funcs[i].calls);
+ overall += tws->funcs[i].total;
+ tws->funcs[i].calls = 0;
+ tws->funcs[i].total = 0;
+ }
+ }
+
+ debug_printf("*** %-25s %5.3fms\n",
+ "OVERALL WINSYS",
+ overall);
+}
+
+static void time_finish( struct pipe_winsys *winsys,
+ long long startval,
+ unsigned idx,
+ const char *name )
+{
+ struct timed_winsys *tws = timed_winsys(winsys);
+ uint64_t endval = util_time_micros();
+ double elapsed = (endval - startval)/1000.0;
+
+ if (endval - startval > 1000LL)
+ debug_printf("*** %s %.3f\n", name, elapsed );
+
+ assert( tws->funcs[idx].name_key == name ||
+ tws->funcs[idx].name_key == NULL);
+
+ tws->funcs[idx].name_key = name;
+ tws->funcs[idx].total += elapsed;
+ tws->funcs[idx].calls++;
+
+ if (endval - tws->last_dump > 10LL * 1000LL * 1000LL) {
+ time_display( winsys );
+ tws->last_dump = endval;
+ }
+}
+
+
+/* Pipe has no concept of pools, but the psb driver passes a flag that
+ * can be mapped onto pools in the backend.
+ */
+static struct pipe_buffer *
+timed_buffer_create(struct pipe_winsys *winsys,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size )
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ struct pipe_buffer *buf =
+ backend->buffer_create( backend, alignment, usage, size );
+
+ time_finish(winsys, start, 0, __FUNCTION__);
+
+ return buf;
+}
+
+
+
+
+static struct pipe_buffer *
+timed_user_buffer_create(struct pipe_winsys *winsys,
+ void *data,
+ unsigned bytes)
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ struct pipe_buffer *buf = backend->user_buffer_create( backend, data, bytes );
+
+ time_finish(winsys, start, 1, __FUNCTION__);
+
+ return buf;
+}
+
+
+static void *
+timed_buffer_map(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf,
+ unsigned flags)
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ void *map = backend->buffer_map( backend, buf, flags );
+
+ time_finish(winsys, start, 2, __FUNCTION__);
+
+ return map;
+}
+
+
+static void
+timed_buffer_unmap(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf)
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ backend->buffer_unmap( backend, buf );
+
+ time_finish(winsys, start, 3, __FUNCTION__);
+}
+
+
+static void
+timed_buffer_destroy(struct pipe_buffer *buf)
+{
+ struct pipe_winsys *winsys = buf->screen->winsys;
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ backend->buffer_destroy( buf );
+
+ time_finish(winsys, start, 4, __FUNCTION__);
+}
+
+
+static void
+timed_flush_frontbuffer( struct pipe_winsys *winsys,
+ struct pipe_surface *surf,
+ void *context_private)
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ backend->flush_frontbuffer( backend, surf, context_private );
+
+ time_finish(winsys, start, 5, __FUNCTION__);
+}
+
+
+
+
+static struct pipe_buffer *
+timed_surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ struct pipe_buffer *ret = backend->surface_buffer_create( backend, width, height,
+ format, usage, tex_usage, stride );
+
+ time_finish(winsys, start, 7, __FUNCTION__);
+
+ return ret;
+}
+
+
+static const char *
+timed_get_name( struct pipe_winsys *winsys )
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ const char *ret = backend->get_name( backend );
+
+ time_finish(winsys, start, 9, __FUNCTION__);
+
+ return ret;
+}
+
+static void
+timed_fence_reference(struct pipe_winsys *winsys,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ backend->fence_reference( backend, ptr, fence );
+
+ time_finish(winsys, start, 10, __FUNCTION__);
+}
+
+
+static int
+timed_fence_signalled( struct pipe_winsys *winsys,
+ struct pipe_fence_handle *fence,
+ unsigned flag )
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ int ret = backend->fence_signalled( backend, fence, flag );
+
+ time_finish(winsys, start, 11, __FUNCTION__);
+
+ return ret;
+}
+
+static int
+timed_fence_finish( struct pipe_winsys *winsys,
+ struct pipe_fence_handle *fence,
+ unsigned flag )
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ uint64_t start = time_start();
+
+ int ret = backend->fence_finish( backend, fence, flag );
+
+ time_finish(winsys, start, 12, __FUNCTION__);
+
+ return ret;
+}
+
+static void
+timed_winsys_destroy( struct pipe_winsys *winsys )
+{
+ struct pipe_winsys *backend = timed_winsys(winsys)->backend;
+ backend->destroy( backend );
+ FREE(winsys);
+}
+
+
+
+struct pipe_winsys *u_timed_winsys_create( struct pipe_winsys *backend )
+{
+ struct timed_winsys *ws = CALLOC_STRUCT(timed_winsys);
+
+ ws->base.user_buffer_create = timed_user_buffer_create;
+ ws->base.buffer_map = timed_buffer_map;
+ ws->base.buffer_unmap = timed_buffer_unmap;
+ ws->base.buffer_destroy = timed_buffer_destroy;
+ ws->base.buffer_create = timed_buffer_create;
+ ws->base.surface_buffer_create = timed_surface_buffer_create;
+ ws->base.flush_frontbuffer = timed_flush_frontbuffer;
+ ws->base.get_name = timed_get_name;
+ ws->base.fence_reference = timed_fence_reference;
+ ws->base.fence_signalled = timed_fence_signalled;
+ ws->base.fence_finish = timed_fence_finish;
+ ws->base.destroy = timed_winsys_destroy;
+
+ ws->backend = backend;
+
+ return &ws->base;
+}
+
diff --git a/src/gallium/auxiliary/util/u_timed_winsys.h b/src/gallium/auxiliary/util/u_timed_winsys.h
new file mode 100644
index 0000000000..542365112d
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_timed_winsys.h
@@ -0,0 +1,41 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+/*
+ * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ */
+
+
+#ifndef U_TIMED_WINSYS_H
+#define U_TIMED_WINSYS_H
+
+
+struct pipe_winsys;
+struct pipe_winsys *u_timed_winsys_create( struct pipe_winsys *backend );
+
+
+#endif
diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c b/src/gallium/auxiliary/util/u_upload_mgr.c
new file mode 100644
index 0000000000..eb635c9f14
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_upload_mgr.c
@@ -0,0 +1,230 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Helper utility for uploading user buffers & other data, and
+ * coalescing small buffers into larger ones.
+ */
+
+#include "pipe/p_error.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_screen.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "u_upload_mgr.h"
+
+
+struct u_upload_mgr {
+ struct pipe_screen *screen;
+
+ unsigned default_size;
+ unsigned alignment;
+ unsigned usage;
+
+ /* The active buffer:
+ */
+ struct pipe_buffer *buffer;
+ unsigned size;
+ unsigned offset;
+};
+
+
+struct u_upload_mgr *u_upload_create( struct pipe_screen *screen,
+ unsigned default_size,
+ unsigned alignment,
+ unsigned usage )
+{
+ struct u_upload_mgr *upload = CALLOC_STRUCT( u_upload_mgr );
+
+ upload->default_size = default_size;
+ upload->screen = screen;
+ upload->alignment = alignment;
+ upload->usage = usage;
+ upload->buffer = NULL;
+
+ return upload;
+}
+
+
+static INLINE enum pipe_error
+my_buffer_write(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset, unsigned size, unsigned dirty_size,
+ const void *data)
+{
+ uint8_t *map;
+
+ assert(offset < buf->size);
+ assert(offset + size <= buf->size);
+ assert(dirty_size >= size);
+ assert(size);
+
+ map = pipe_buffer_map_range(screen, buf, offset, size,
+ PIPE_BUFFER_USAGE_CPU_WRITE |
+ PIPE_BUFFER_USAGE_FLUSH_EXPLICIT);
+ if (map == NULL)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ memcpy(map + offset, data, size);
+ pipe_buffer_flush_mapped_range(screen, buf, offset, dirty_size);
+ pipe_buffer_unmap(screen, buf);
+
+ return PIPE_OK;
+}
+
+/* Release old buffer.
+ *
+ * This must usually be called prior to firing the command stream
+ * which references the upload buffer, as many memory managers will
+ * cause subsequent maps of a fired buffer to wait.
+ *
+ * Can improve this with a change to pipe_buffer_write to use the
+ * DONT_WAIT bit, but for now, it's easiest just to grab a new buffer.
+ */
+void u_upload_flush( struct u_upload_mgr *upload )
+{
+ pipe_buffer_reference( &upload->buffer, NULL );
+ upload->size = 0;
+}
+
+
+void u_upload_destroy( struct u_upload_mgr *upload )
+{
+ u_upload_flush( upload );
+ FREE( upload );
+}
+
+
+static enum pipe_error
+u_upload_alloc_buffer( struct u_upload_mgr *upload,
+ unsigned min_size )
+{
+ unsigned size;
+
+ /* Release old buffer, if present:
+ */
+ u_upload_flush( upload );
+
+ /* Allocate a new one:
+ */
+ size = align(MAX2(upload->default_size, min_size), 4096);
+
+ upload->buffer = pipe_buffer_create( upload->screen,
+ upload->alignment,
+ upload->usage | PIPE_BUFFER_USAGE_CPU_WRITE,
+ size );
+ if (upload->buffer == NULL)
+ goto fail;
+
+ upload->size = size;
+
+ upload->offset = 0;
+ return 0;
+
+fail:
+ if (upload->buffer)
+ pipe_buffer_reference( &upload->buffer, NULL );
+
+ return PIPE_ERROR_OUT_OF_MEMORY;
+}
+
+
+enum pipe_error u_upload_data( struct u_upload_mgr *upload,
+ unsigned size,
+ const void *data,
+ unsigned *out_offset,
+ struct pipe_buffer **outbuf )
+{
+ unsigned alloc_size = align( size, upload->alignment );
+ enum pipe_error ret = PIPE_OK;
+
+ if (upload->offset + alloc_size > upload->size) {
+ ret = u_upload_alloc_buffer( upload, alloc_size );
+ if (ret)
+ return ret;
+ }
+
+ /* Copy the data, using map_range if available:
+ */
+ ret = my_buffer_write( upload->screen,
+ upload->buffer,
+ upload->offset,
+ size,
+ alloc_size,
+ data );
+ if (ret)
+ return ret;
+
+ /* Emit the return values:
+ */
+ pipe_buffer_reference( outbuf, upload->buffer );
+ *out_offset = upload->offset;
+ upload->offset += alloc_size;
+ return PIPE_OK;
+}
+
+
+/* As above, but upload the full contents of a buffer. Useful for
+ * uploading user buffers, avoids generating an explosion of GPU
+ * buffers if you have an app that does lots of small vertex buffer
+ * renders or DrawElements calls.
+ */
+enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
+ unsigned offset,
+ unsigned size,
+ struct pipe_buffer *inbuf,
+ unsigned *out_offset,
+ struct pipe_buffer **outbuf )
+{
+ enum pipe_error ret = PIPE_OK;
+ const char *map = NULL;
+
+ map = (const char *)pipe_buffer_map(
+ upload->screen, inbuf, PIPE_BUFFER_USAGE_CPU_READ );
+
+ if (map == NULL) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ if (0)
+ debug_printf("upload ptr %p ofs %d sz %d\n", map, offset, size);
+
+ ret = u_upload_data( upload,
+ size,
+ map + offset,
+ out_offset,
+ outbuf );
+ if (ret)
+ goto done;
+
+done:
+ if (map)
+ pipe_buffer_unmap( upload->screen, inbuf );
+
+ return ret;
+}
diff --git a/src/gallium/auxiliary/util/u_upload_mgr.h b/src/gallium/auxiliary/util/u_upload_mgr.h
new file mode 100644
index 0000000000..745b5834af
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_upload_mgr.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Helper utility for uploading user buffers & other data, and
+ * coalescing small buffers into larger ones.
+ */
+
+#ifndef U_UPLOAD_MGR_H
+#define U_UPLOAD_MGR_H
+
+struct pipe_screen;
+struct pipe_buffer;
+struct u_upload_mgr;
+
+
+struct u_upload_mgr *u_upload_create( struct pipe_screen *screen,
+ unsigned default_size,
+ unsigned alignment,
+ unsigned usage );
+
+void u_upload_destroy( struct u_upload_mgr *upload );
+
+/* Unmap and release old buffer.
+ *
+ * This must usually be called prior to firing the command stream
+ * which references the upload buffer, as many memory managers either
+ * don't like firing a mapped buffer or cause subsequent maps of a
+ * fired buffer to wait. For now, it's easiest just to grab a new
+ * buffer.
+ */
+void u_upload_flush( struct u_upload_mgr *upload );
+
+
+enum pipe_error u_upload_data( struct u_upload_mgr *upload,
+ unsigned size,
+ const void *data,
+ unsigned *out_offset,
+ struct pipe_buffer **outbuf );
+
+
+enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
+ unsigned offset,
+ unsigned size,
+ struct pipe_buffer *inbuf,
+ unsigned *out_offset,
+ struct pipe_buffer **outbuf );
+
+
+
+#endif
+
diff --git a/src/gallium/drivers/Makefile b/src/gallium/drivers/Makefile
new file mode 100644
index 0000000000..9fe9b2c11d
--- /dev/null
+++ b/src/gallium/drivers/Makefile
@@ -0,0 +1,12 @@
+# src/gallium/drivers/Makefile
+TOP = ../../..
+include $(TOP)/configs/current
+
+SUBDIRS = $(GALLIUM_DRIVERS_DIRS)
+
+default install clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) $@) || exit 1; \
+ fi \
+ done
diff --git a/src/gallium/drivers/cell/Makefile b/src/gallium/drivers/cell/Makefile
new file mode 100644
index 0000000000..47aef7b05f
--- /dev/null
+++ b/src/gallium/drivers/cell/Makefile
@@ -0,0 +1,12 @@
+# Cell Gallium driver Makefile
+
+
+default:
+ ( cd spu ; make )
+ ( cd ppu ; make )
+
+
+
+clean:
+ ( cd spu ; make clean )
+ ( cd ppu ; make clean )
diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h
new file mode 100644
index 0000000000..d5f5c7bbba
--- /dev/null
+++ b/src/gallium/drivers/cell/common.h
@@ -0,0 +1,376 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Types and tokens which are common to the SPU and PPU code.
+ */
+
+
+#ifndef CELL_COMMON_H
+#define CELL_COMMON_H
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+
+
+/** The standard assert macro doesn't seem to work reliably */
+#define ASSERT(x) \
+ if (!(x)) { \
+ ubyte *p = NULL; \
+ fprintf(stderr, "%s:%d: %s(): assertion %s failed.\n", \
+ __FILE__, __LINE__, __FUNCTION__, #x); \
+ *p = 0; \
+ exit(1); \
+ }
+
+
+
+#define JOIN(x, y) JOIN_AGAIN(x, y)
+#define JOIN_AGAIN(x, y) x ## y
+
+#define STATIC_ASSERT(e) \
+{typedef char JOIN(assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1];}
+
+
+
+/** for sanity checking */
+#define ASSERT_ALIGN16(ptr) \
+ ASSERT((((unsigned long) (ptr)) & 0xf) == 0);
+
+
+/** round up value to next multiple of 4 */
+#define ROUNDUP4(k) (((k) + 0x3) & ~0x3)
+
+/** round up value to next multiple of 8 */
+#define ROUNDUP8(k) (((k) + 0x7) & ~0x7)
+
+/** round up value to next multiple of 16 */
+#define ROUNDUP16(k) (((k) + 0xf) & ~0xf)
+
+
+#define CELL_MAX_SPUS 8
+
+#define CELL_MAX_SAMPLERS 4
+#define CELL_MAX_TEXTURE_LEVELS 12 /* 2k x 2k */
+#define CELL_MAX_CONSTANTS 32 /**< number of float[4] constants */
+#define CELL_MAX_WIDTH 1024 /**< max framebuffer width */
+#define CELL_MAX_HEIGHT 1024 /**< max framebuffer width */
+
+#define TILE_SIZE 32
+
+
+/**
+ * The low byte of a mailbox word contains the command opcode.
+ * Remaining higher bytes are command specific.
+ */
+#define CELL_CMD_OPCODE_MASK 0xff
+
+#define CELL_CMD_EXIT 1
+#define CELL_CMD_CLEAR_SURFACE 2
+#define CELL_CMD_FINISH 3
+#define CELL_CMD_RENDER 4
+#define CELL_CMD_BATCH 5
+#define CELL_CMD_RELEASE_VERTS 6
+#define CELL_CMD_STATE_FRAMEBUFFER 10
+#define CELL_CMD_STATE_FRAGMENT_OPS 11
+#define CELL_CMD_STATE_SAMPLER 12
+#define CELL_CMD_STATE_TEXTURE 13
+#define CELL_CMD_STATE_VERTEX_INFO 14
+#define CELL_CMD_STATE_VIEWPORT 15
+#define CELL_CMD_STATE_UNIFORMS 16
+#define CELL_CMD_STATE_VS_ARRAY_INFO 17
+#define CELL_CMD_STATE_BIND_VS 18
+#define CELL_CMD_STATE_FRAGMENT_PROGRAM 19
+#define CELL_CMD_STATE_ATTRIB_FETCH 20
+#define CELL_CMD_STATE_FS_CONSTANTS 21
+#define CELL_CMD_STATE_RASTERIZER 22
+#define CELL_CMD_VS_EXECUTE 23
+#define CELL_CMD_FLUSH_BUFFER_RANGE 24
+#define CELL_CMD_FENCE 25
+
+
+/** Command/batch buffers */
+#define CELL_NUM_BUFFERS 4
+#define CELL_BUFFER_SIZE (4*1024) /**< 16KB would be the max */
+
+#define CELL_BUFFER_STATUS_FREE 10
+#define CELL_BUFFER_STATUS_USED 20
+
+/** Debug flags */
+#define CELL_DEBUG_CHECKER (1 << 0)
+#define CELL_DEBUG_ASM (1 << 1)
+#define CELL_DEBUG_SYNC (1 << 2)
+#define CELL_DEBUG_FRAGMENT_OPS (1 << 3)
+#define CELL_DEBUG_FRAGMENT_OP_FALLBACK (1 << 4)
+#define CELL_DEBUG_CMD (1 << 5)
+#define CELL_DEBUG_CACHE (1 << 6)
+
+#define CELL_FENCE_IDLE 0
+#define CELL_FENCE_EMITTED 1
+#define CELL_FENCE_SIGNALLED 2
+
+#define CELL_FACING_FRONT 0
+#define CELL_FACING_BACK 1
+
+struct cell_fence
+{
+ /** There's a 16-byte status qword per SPU */
+ volatile uint status[CELL_MAX_SPUS][4];
+};
+
+#ifdef __SPU__
+typedef vector unsigned int opcode_t;
+#else
+typedef unsigned int opcode_t[4];
+#endif
+
+/**
+ * Fence command sent to SPUs. In response, the SPUs will write
+ * CELL_FENCE_STATUS_SIGNALLED back to the fence status word in main memory.
+ */
+struct cell_command_fence
+{
+ opcode_t opcode; /**< CELL_CMD_FENCE */
+ struct cell_fence *fence;
+ uint32_t pad_[3];
+};
+
+
+/**
+ * Command to specify per-fragment operations state and generated code.
+ * Note that this is a variant-length structure, allocated with as
+ * much memory as needed to hold the generated code; the "code"
+ * field *must* be the last field in the structure. Also, the entire
+ * length of the structure (including the variant code field) must be
+ * a multiple of 8 bytes; we require that this structure itself be
+ * a multiple of 8 bytes, and that the generated code also be a multiple
+ * of 8 bytes.
+ *
+ * Also note that the dsa, blend, blend_color fields are really only needed
+ * for the fallback/C per-pixel code. They're not used when we generate
+ * dynamic SPU fragment code (which is the normal case), and will eventually
+ * be removed from this structure.
+ */
+struct cell_command_fragment_ops
+{
+ opcode_t opcode; /**< CELL_CMD_STATE_FRAGMENT_OPS */
+
+ /* Fields for the fallback case */
+ struct pipe_depth_stencil_alpha_state dsa;
+ struct pipe_blend_state blend;
+ struct pipe_blend_color blend_color;
+
+ /* Fields for the generated SPU code */
+ unsigned total_code_size;
+ unsigned front_code_index;
+ unsigned back_code_index;
+ /* this field has variant length, and must be the last field in
+ * the structure
+ */
+ unsigned code[0];
+};
+
+
+/** Max instructions for fragment programs */
+#define SPU_MAX_FRAGMENT_PROGRAM_INSTS 512
+
+/**
+ * Command to send a fragment program to SPUs.
+ */
+struct cell_command_fragment_program
+{
+ opcode_t opcode; /**< CELL_CMD_STATE_FRAGMENT_PROGRAM */
+ uint num_inst; /**< Number of instructions */
+ uint32_t pad[3];
+ unsigned code[SPU_MAX_FRAGMENT_PROGRAM_INSTS];
+};
+
+
+/**
+ * Tell SPUs about the framebuffer size, location
+ */
+struct cell_command_framebuffer
+{
+ opcode_t opcode; /**< CELL_CMD_STATE_FRAMEBUFFER */
+ int width, height;
+ void *color_start, *depth_start;
+ enum pipe_format color_format, depth_format;
+ uint32_t pad_[2];
+};
+
+
+/**
+ * Tell SPUs about rasterizer state.
+ */
+struct cell_command_rasterizer
+{
+ opcode_t opcode; /**< CELL_CMD_STATE_RASTERIZER */
+ struct pipe_rasterizer_state rasterizer;
+};
+
+
+/**
+ * Clear framebuffer to the given value/color.
+ */
+struct cell_command_clear_surface
+{
+ opcode_t opcode; /**< CELL_CMD_CLEAR_SURFACE */
+ uint surface; /**< Temporary: 0=color, 1=Z */
+ uint value;
+ uint32_t pad[2];
+};
+
+
+/**
+ * Array info used by the vertex shader's vertex puller.
+ */
+struct cell_array_info
+{
+ uint64_t base; /**< Base address of the 0th element. */
+ uint attr; /**< Attribute that this state is for. */
+ uint pitch; /**< Byte pitch from one entry to the next. */
+ uint size;
+ uint function_offset;
+};
+
+
+struct cell_attribute_fetch_code
+{
+ uint64_t base;
+ uint size;
+};
+
+
+struct cell_buffer_range
+{
+ uint64_t base;
+ unsigned size;
+};
+
+
+struct cell_shader_info
+{
+ uint64_t declarations;
+ uint64_t instructions;
+ uint64_t immediates;
+
+ unsigned num_outputs;
+ unsigned num_declarations;
+ unsigned num_instructions;
+ unsigned num_immediates;
+};
+
+
+#define SPU_VERTS_PER_BATCH 64
+struct cell_command_vs
+{
+ opcode_t opcode; /**< CELL_CMD_VS_EXECUTE */
+ uint64_t vOut[SPU_VERTS_PER_BATCH];
+ unsigned num_elts;
+ unsigned elts[SPU_VERTS_PER_BATCH];
+ float plane[12][4];
+ unsigned nr_planes;
+ unsigned nr_attrs;
+};
+
+
+struct cell_command_render
+{
+ opcode_t opcode; /**< CELL_CMD_RENDER */
+ uint prim_type; /**< PIPE_PRIM_x */
+ uint num_verts;
+ uint vertex_size; /**< bytes per vertex */
+ uint num_indexes;
+ uint vertex_buf; /**< which cell->buffer[] contains the vertex data */
+ float xmin, ymin, xmax, ymax; /* XXX another dummy field */
+ uint min_index;
+ boolean inline_verts;
+ uint32_t pad_[1];
+};
+
+
+struct cell_command_release_verts
+{
+ opcode_t opcode; /**< CELL_CMD_RELEASE_VERTS */
+ uint vertex_buf; /**< in [0, CELL_NUM_BUFFERS-1] */
+ uint32_t pad_[3];
+};
+
+
+struct cell_command_sampler
+{
+ opcode_t opcode; /**< CELL_CMD_STATE_SAMPLER */
+ uint unit;
+ struct pipe_sampler_state state;
+ uint32_t pad_[2];
+};
+
+
+struct cell_command_texture
+{
+ opcode_t opcode; /**< CELL_CMD_STATE_TEXTURE */
+ uint target; /**< PIPE_TEXTURE_x */
+ uint unit;
+ void *start[CELL_MAX_TEXTURE_LEVELS]; /**< Address in main memory */
+ ushort width[CELL_MAX_TEXTURE_LEVELS];
+ ushort height[CELL_MAX_TEXTURE_LEVELS];
+ ushort depth[CELL_MAX_TEXTURE_LEVELS];
+};
+
+
+#define MAX_SPU_FUNCTIONS 12
+/**
+ * Used to tell the PPU about the address of particular functions in the
+ * SPU's address space.
+ */
+struct cell_spu_function_info
+{
+ uint num;
+ char names[MAX_SPU_FUNCTIONS][16];
+ uint addrs[MAX_SPU_FUNCTIONS];
+ char pad[12]; /**< Pad struct to multiple of 16 bytes (256 currently) */
+};
+
+
+/** This is the object passed to spe_create_thread() */
+struct cell_init_info
+{
+ unsigned id;
+ unsigned num_spus;
+ unsigned debug_flags; /**< mask of CELL_DEBUG_x flags */
+ float inv_timebase; /**< 1.0/timebase, for perf measurement */
+
+ /** Buffers for command batches, vertex/index data */
+ ubyte *buffers[CELL_NUM_BUFFERS];
+ uint *buffer_status; /**< points at cell_context->buffer_status */
+
+ struct cell_spu_function_info *spu_functions;
+} ALIGN16_ATTRIB;
+
+
+#endif /* CELL_COMMON_H */
diff --git a/src/gallium/drivers/cell/ppu/Makefile b/src/gallium/drivers/cell/ppu/Makefile
new file mode 100644
index 0000000000..c92f8e5cba
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/Makefile
@@ -0,0 +1,86 @@
+# Gallium3D Cell driver: PPU code
+
+# This makefile builds the libcell.a library which gets pulled into
+# the main libGL.so library
+
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+
+# This is the "top-level" cell PPU driver code, will get pulled into libGL.so
+# by the winsys Makefile.
+CELL_LIB = ../libcell.a
+
+
+# This is the SPU code. We'd like to be able to put this into the libcell.a
+# archive with the PPU code, but nesting .a libs doesn't seem to work.
+# So, it's pulled into libGL.so in gallium/winsys/xlib/Makefile
+SPU_CODE_MODULE = ../spu/g3d_spu.a
+
+
+SOURCES = \
+ cell_batch.c \
+ cell_clear.c \
+ cell_context.c \
+ cell_draw_arrays.c \
+ cell_fence.c \
+ cell_flush.c \
+ cell_gen_fragment.c \
+ cell_gen_fp.c \
+ cell_state_derived.c \
+ cell_state_emit.c \
+ cell_state_shader.c \
+ cell_pipe_state.c \
+ cell_screen.c \
+ cell_state_vertex.c \
+ cell_spu.c \
+ cell_surface.c \
+ cell_texture.c \
+ cell_vbuf.c \
+ cell_vertex_fetch.c \
+ cell_vertex_shader.c
+
+
+OBJECTS = $(SOURCES:.c=.o) \
+
+INCLUDE_DIRS = \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/src/gallium/drivers
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+.c.s:
+ $(CC) -S $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+default: $(CELL_LIB)
+
+
+$(CELL_LIB): $(OBJECTS) $(SPU_CODE_MODULE)
+# ar -ru $(CELL_LIB) $(OBJECTS) $(SPU_CODE_MODULE) # doesn't work
+ ar -ru $(CELL_LIB) $(OBJECTS)
+
+#$(PROG): $(PPU_OBJECTS)
+# $(CC) -o $(PROG) $(PPU_OBJECTS) $(SPU_CODE_MODULE) $(PPU_LFLAGS)
+
+
+
+clean:
+ rm -f *.o *~ $(CELL_LIB)
+
+
+
+depend: $(SOURCES)
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDE_DIRS) $(SOURCES) 2> /dev/null
+
+include depend
+
+
+
diff --git a/src/gallium/drivers/cell/ppu/cell_batch.c b/src/gallium/drivers/cell/ppu/cell_batch.c
new file mode 100644
index 0000000000..fe144f8b84
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_batch.c
@@ -0,0 +1,260 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "cell_context.h"
+#include "cell_batch.h"
+#include "cell_fence.h"
+#include "cell_spu.h"
+
+
+
+/**
+ * Search the buffer pool for an empty/free buffer and return its index.
+ * Buffers are used for storing vertex data, state and commands which
+ * will be sent to the SPUs.
+ * If no empty buffers are available, wait for one.
+ * \return buffer index in [0, CELL_NUM_BUFFERS-1]
+ */
+uint
+cell_get_empty_buffer(struct cell_context *cell)
+{
+ static uint prev_buffer = 0;
+ uint buf = (prev_buffer + 1) % CELL_NUM_BUFFERS;
+ uint tries = 0;
+
+ /* Find a buffer that's marked as free by all SPUs */
+ while (1) {
+ uint spu, num_free = 0;
+
+ for (spu = 0; spu < cell->num_spus; spu++) {
+ if (cell->buffer_status[spu][buf][0] == CELL_BUFFER_STATUS_FREE) {
+ num_free++;
+
+ if (num_free == cell->num_spus) {
+ /* found a free buffer, now mark status as used */
+ for (spu = 0; spu < cell->num_spus; spu++) {
+ cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED;
+ }
+ /*
+ printf("PPU: ALLOC BUFFER %u, %u tries\n", buf, tries);
+ */
+ prev_buffer = buf;
+
+ /* release tex buffer associated w/ prev use of this batch buf */
+ cell_free_fenced_buffers(cell, &cell->fenced_buffers[buf]);
+
+ return buf;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ /* try next buf */
+ buf = (buf + 1) % CELL_NUM_BUFFERS;
+
+ tries++;
+ if (tries == 100) {
+ /*
+ printf("PPU WAITING for buffer...\n");
+ */
+ }
+ }
+}
+
+
+/**
+ * Append a fence command to the current batch buffer.
+ * Note that we're sure there's always room for this because of the
+ * adjusted size check in cell_batch_free_space().
+ */
+static void
+emit_fence(struct cell_context *cell)
+{
+ const uint batch = cell->cur_batch;
+ const uint size = cell->buffer_size[batch];
+ struct cell_command_fence *fence_cmd;
+ struct cell_fence *fence = &cell->fenced_buffers[batch].fence;
+ uint i;
+
+ /* set fence status to emitted, not yet signalled */
+ for (i = 0; i < cell->num_spus; i++) {
+ fence->status[i][0] = CELL_FENCE_EMITTED;
+ }
+
+ STATIC_ASSERT(sizeof(struct cell_command_fence) % 16 == 0);
+ ASSERT(size % 16 == 0);
+ ASSERT(size + sizeof(struct cell_command_fence) <= CELL_BUFFER_SIZE);
+
+ fence_cmd = (struct cell_command_fence *) (cell->buffer[batch] + size);
+ fence_cmd->opcode[0] = CELL_CMD_FENCE;
+ fence_cmd->fence = fence;
+
+ /* update batch buffer size */
+ cell->buffer_size[batch] = size + sizeof(struct cell_command_fence);
+}
+
+
+/**
+ * Flush the current batch buffer to the SPUs.
+ * An empty buffer will be found and set as the new current batch buffer
+ * for subsequent commands/data.
+ */
+void
+cell_batch_flush(struct cell_context *cell)
+{
+ static boolean flushing = FALSE;
+ uint batch = cell->cur_batch;
+ uint size = cell->buffer_size[batch];
+ uint spu, cmd_word;
+
+ assert(!flushing);
+
+ if (size == 0)
+ return;
+
+ /* Before we use this batch buffer, make sure any fenced texture buffers
+ * are released.
+ */
+ if (cell->fenced_buffers[batch].head) {
+ emit_fence(cell);
+ size = cell->buffer_size[batch];
+ }
+
+ flushing = TRUE;
+
+ assert(batch < CELL_NUM_BUFFERS);
+
+ /*
+ printf("cell_batch_dispatch: buf %u at %p, size %u\n",
+ batch, &cell->buffer[batch][0], size);
+ */
+
+ /*
+ * Build "BATCH" command and send to all SPUs.
+ */
+ cmd_word = CELL_CMD_BATCH | (batch << 8) | (size << 16);
+
+ for (spu = 0; spu < cell->num_spus; spu++) {
+ assert(cell->buffer_status[spu][batch][0] == CELL_BUFFER_STATUS_USED);
+ send_mbox_message(cell_global.spe_contexts[spu], cmd_word);
+ }
+
+ /* When the SPUs are done copying the buffer into their locals stores
+ * they'll write a BUFFER_STATUS_FREE message into the buffer_status[]
+ * array indicating that the PPU can re-use the buffer.
+ */
+
+ batch = cell_get_empty_buffer(cell);
+
+ cell->buffer_size[batch] = 0; /* empty */
+ cell->cur_batch = batch;
+
+ flushing = FALSE;
+}
+
+
+/**
+ * Return the number of bytes free in the current batch buffer.
+ */
+uint
+cell_batch_free_space(const struct cell_context *cell)
+{
+ uint free = CELL_BUFFER_SIZE - cell->buffer_size[cell->cur_batch];
+ free -= sizeof(struct cell_command_fence);
+ return free;
+}
+
+
+/**
+ * Allocate space in the current batch buffer for 'bytes' space.
+ * Bytes must be a multiple of 16 bytes. Allocation will be 16 byte aligned.
+ * \return address in batch buffer to put data
+ */
+void *
+cell_batch_alloc16(struct cell_context *cell, uint bytes)
+{
+ void *pos;
+ uint size;
+
+ ASSERT(bytes % 16 == 0);
+ ASSERT(bytes <= CELL_BUFFER_SIZE);
+ ASSERT(cell->cur_batch >= 0);
+
+#ifdef ASSERT
+ {
+ uint spu;
+ for (spu = 0; spu < cell->num_spus; spu++) {
+ ASSERT(cell->buffer_status[spu][cell->cur_batch][0]
+ == CELL_BUFFER_STATUS_USED);
+ }
+ }
+#endif
+
+ size = cell->buffer_size[cell->cur_batch];
+
+ if (bytes > cell_batch_free_space(cell)) {
+ cell_batch_flush(cell);
+ size = 0;
+ }
+
+ ASSERT(size % 16 == 0);
+ ASSERT(size + bytes <= CELL_BUFFER_SIZE);
+
+ pos = (void *) (cell->buffer[cell->cur_batch] + size);
+
+ cell->buffer_size[cell->cur_batch] = size + bytes;
+
+ return pos;
+}
+
+
+/**
+ * One-time init of batch buffers.
+ */
+void
+cell_init_batch_buffers(struct cell_context *cell)
+{
+ uint spu, buf;
+
+ /* init command, vertex/index buffer info */
+ for (buf = 0; buf < CELL_NUM_BUFFERS; buf++) {
+ cell->buffer_size[buf] = 0;
+
+ /* init batch buffer status values,
+ * mark 0th buffer as used, rest as free.
+ */
+ for (spu = 0; spu < cell->num_spus; spu++) {
+ if (buf == 0)
+ cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED;
+ else
+ cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_FREE;
+ }
+ }
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_batch.h b/src/gallium/drivers/cell/ppu/cell_batch.h
new file mode 100644
index 0000000000..290136031a
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_batch.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_BATCH_H
+#define CELL_BATCH_H
+
+#include "pipe/p_compiler.h"
+
+
+struct cell_context;
+
+
+extern uint
+cell_get_empty_buffer(struct cell_context *cell);
+
+extern void
+cell_batch_flush(struct cell_context *cell);
+
+extern uint
+cell_batch_free_space(const struct cell_context *cell);
+
+extern void *
+cell_batch_alloc16(struct cell_context *cell, uint bytes);
+
+extern void
+cell_init_batch_buffers(struct cell_context *cell);
+
+
+#endif /* CELL_BATCH_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_clear.c b/src/gallium/drivers/cell/ppu/cell_clear.c
new file mode 100644
index 0000000000..79ad687ea9
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_clear.c
@@ -0,0 +1,92 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Authors
+ * Brian Paul
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdint.h>
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_pack_color.h"
+#include "cell/common.h"
+#include "cell_clear.h"
+#include "cell_context.h"
+#include "cell_batch.h"
+#include "cell_flush.h"
+#include "cell_spu.h"
+#include "cell_state.h"
+
+
+/**
+ * Called via pipe->clear()
+ */
+void
+cell_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
+ double depth, unsigned stencil)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ if (cell->dirty)
+ cell_update_derived(cell);
+
+ if (buffers & PIPE_CLEAR_COLOR) {
+ uint surfIndex = 0;
+ uint clearValue;
+
+ util_pack_color(rgba, cell->framebuffer.cbufs[0]->format, &clearValue);
+
+ /* Build a CLEAR command and place it in the current batch buffer */
+ STATIC_ASSERT(sizeof(struct cell_command_clear_surface) % 16 == 0);
+ struct cell_command_clear_surface *clr
+ = (struct cell_command_clear_surface *)
+ cell_batch_alloc16(cell, sizeof(*clr));
+ clr->opcode[0] = CELL_CMD_CLEAR_SURFACE;
+ clr->surface = surfIndex;
+ clr->value = clearValue;
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+ uint surfIndex = 1;
+ uint clearValue;
+
+ clearValue = util_pack_z_stencil(cell->framebuffer.zsbuf->format,
+ depth, stencil);
+
+ /* Build a CLEAR command and place it in the current batch buffer */
+ STATIC_ASSERT(sizeof(struct cell_command_clear_surface) % 16 == 0);
+ struct cell_command_clear_surface *clr
+ = (struct cell_command_clear_surface *)
+ cell_batch_alloc16(cell, sizeof(*clr));
+ clr->opcode[0] = CELL_CMD_CLEAR_SURFACE;
+ clr->surface = surfIndex;
+ clr->value = clearValue;
+ }
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_clear.h b/src/gallium/drivers/cell/ppu/cell_clear.h
new file mode 100644
index 0000000000..08e091adfd
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_clear.h
@@ -0,0 +1,41 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_CLEAR_H
+#define CELL_CLEAR_H
+
+
+struct pipe_context;
+
+
+extern void
+cell_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
+ double depth, unsigned stencil);
+
+
+#endif /* CELL_CLEAR_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c
new file mode 100644
index 0000000000..ebb7a7acc4
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_context.c
@@ -0,0 +1,208 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Authors
+ * Brian Paul
+ */
+
+
+#include <stdio.h>
+
+#include "pipe/p_defines.h"
+#include "pipe/p_format.h"
+#include "util/u_memory.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_screen.h"
+
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+
+#include "cell/common.h"
+#include "cell_batch.h"
+#include "cell_clear.h"
+#include "cell_context.h"
+#include "cell_draw_arrays.h"
+#include "cell_fence.h"
+#include "cell_flush.h"
+#include "cell_state.h"
+#include "cell_surface.h"
+#include "cell_spu.h"
+#include "cell_pipe_state.h"
+#include "cell_texture.h"
+#include "cell_vbuf.h"
+
+
+
+static void
+cell_destroy_context( struct pipe_context *pipe )
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ util_delete_keymap(cell->fragment_ops_cache, NULL);
+
+ cell_spu_exit(cell);
+
+ align_free(cell);
+}
+
+
+static struct draw_context *
+cell_draw_create(struct cell_context *cell)
+{
+ struct draw_context *draw = draw_create();
+
+#if 0 /* broken */
+ if (getenv("GALLIUM_CELL_VS")) {
+ /* plug in SPU-based vertex transformation code */
+ draw->shader_queue_flush = cell_vertex_shader_queue_flush;
+ draw->driver_private = cell;
+ }
+#endif
+
+ return draw;
+}
+
+
+static const struct debug_named_value cell_debug_flags[] = {
+ {"checker", CELL_DEBUG_CHECKER},/**< modulate tile clear color by SPU ID */
+ {"asm", CELL_DEBUG_ASM}, /**< dump SPU asm code */
+ {"sync", CELL_DEBUG_SYNC}, /**< SPUs do synchronous DMA */
+ {"fragops", CELL_DEBUG_FRAGMENT_OPS}, /**< SPUs emit fragment ops debug messages*/
+ {"fragopfallback", CELL_DEBUG_FRAGMENT_OP_FALLBACK}, /**< SPUs use reference implementation for fragment ops*/
+ {"cmd", CELL_DEBUG_CMD}, /**< SPUs dump command buffer info */
+ {"cache", CELL_DEBUG_CACHE}, /**< report texture cache stats on exit */
+ {NULL, 0}
+};
+
+static unsigned int
+cell_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static unsigned int
+cell_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+struct pipe_context *
+cell_create_context(struct pipe_screen *screen,
+ struct cell_winsys *cws)
+{
+ struct cell_context *cell;
+ uint i;
+
+ /* some fields need to be 16-byte aligned, so align the whole object */
+ cell = (struct cell_context*) align_malloc(sizeof(struct cell_context), 16);
+ if (!cell)
+ return NULL;
+
+ memset(cell, 0, sizeof(*cell));
+
+ cell->winsys = cws;
+ cell->pipe.winsys = screen->winsys;
+ cell->pipe.screen = screen;
+ cell->pipe.destroy = cell_destroy_context;
+
+ cell->pipe.clear = cell_clear;
+ cell->pipe.flush = cell_flush;
+
+ cell->pipe.is_texture_referenced = cell_is_texture_referenced;
+ cell->pipe.is_buffer_referenced = cell_is_buffer_referenced;
+
+#if 0
+ cell->pipe.begin_query = cell_begin_query;
+ cell->pipe.end_query = cell_end_query;
+ cell->pipe.wait_query = cell_wait_query;
+#endif
+
+ cell_init_draw_functions(cell);
+ cell_init_state_functions(cell);
+ cell_init_shader_functions(cell);
+ cell_init_surface_functions(cell);
+ cell_init_vertex_functions(cell);
+
+ cell->draw = cell_draw_create(cell);
+
+ /* Create cache of fragment ops generated code */
+ cell->fragment_ops_cache =
+ util_new_keymap(sizeof(struct cell_fragment_ops_key), ~0, NULL);
+
+ cell_init_vbuf(cell);
+
+ draw_set_rasterize_stage(cell->draw, cell->vbuf);
+
+ /* convert all points/lines to tris for the time being */
+ draw_wide_point_threshold(cell->draw, 0.0);
+ draw_wide_line_threshold(cell->draw, 0.0);
+
+ /* get env vars or read config file to get debug flags */
+ cell->debug_flags = debug_get_flags_option("CELL_DEBUG",
+ cell_debug_flags,
+ 0 );
+
+ for (i = 0; i < CELL_NUM_BUFFERS; i++)
+ cell_fence_init(&cell->fenced_buffers[i].fence);
+
+
+ /*
+ * SPU stuff
+ */
+ /* This call only works with SDK 3.0. Anyone still using 2.1??? */
+ cell->num_cells = spe_cpu_info_get(SPE_COUNT_PHYSICAL_CPU_NODES, -1);
+ cell->num_spus = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, -1);
+ if (cell->debug_flags) {
+ printf("Cell: found %d Cell(s) with %u SPUs\n",
+ cell->num_cells, cell->num_spus);
+ }
+ if (getenv("CELL_NUM_SPUS")) {
+ cell->num_spus = atoi(getenv("CELL_NUM_SPUS"));
+ assert(cell->num_spus > 0);
+ }
+
+ cell_start_spus(cell);
+
+ cell_init_batch_buffers(cell);
+
+ /* make sure SPU initializations are done before proceeding */
+ cell_flush_int(cell, CELL_FLUSH_WAIT);
+
+ return &cell->pipe;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h
new file mode 100644
index 0000000000..5c3188e7f9
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_context.h
@@ -0,0 +1,202 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_CONTEXT_H
+#define CELL_CONTEXT_H
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_vbuf.h"
+#include "cell_winsys.h"
+#include "cell/common.h"
+#include "rtasm/rtasm_ppc_spe.h"
+#include "tgsi/tgsi_scan.h"
+#include "util/u_keymap.h"
+
+
+struct cell_vbuf_render;
+
+
+/**
+ * Cell vertex shader state, subclass of pipe_shader_state.
+ */
+struct cell_vertex_shader_state
+{
+ struct pipe_shader_state shader;
+ struct tgsi_shader_info info;
+ void *draw_data;
+};
+
+
+/**
+ * Cell fragment shader state, subclass of pipe_shader_state.
+ */
+struct cell_fragment_shader_state
+{
+ struct pipe_shader_state shader;
+ struct tgsi_shader_info info;
+ struct spe_function code;
+ void *data;
+};
+
+
+/**
+ * Key for mapping per-fragment state to cached SPU machine code.
+ * keymap(cell_fragment_ops_key) => cell_command_fragment_ops
+ */
+struct cell_fragment_ops_key
+{
+ struct pipe_blend_state blend;
+ struct pipe_blend_color blend_color;
+ struct pipe_depth_stencil_alpha_state dsa;
+ enum pipe_format color_format;
+ enum pipe_format zs_format;
+};
+
+
+struct cell_buffer_node;
+
+/**
+ * Fenced buffer list. List of buffers which can be unreferenced after
+ * the fence has been executed/signalled.
+ */
+struct cell_buffer_list
+{
+ struct cell_fence fence ALIGN16_ATTRIB;
+ struct cell_buffer_node *head;
+};
+
+
+/**
+ * Per-context state, subclass of pipe_context.
+ */
+struct cell_context
+{
+ struct pipe_context pipe;
+
+ struct cell_winsys *winsys;
+
+ const struct pipe_blend_state *blend;
+ const struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
+ uint num_samplers;
+ const struct pipe_depth_stencil_alpha_state *depth_stencil;
+ const struct pipe_rasterizer_state *rasterizer;
+ const struct cell_vertex_shader_state *vs;
+ const struct cell_fragment_shader_state *fs;
+
+ struct spe_function logic_op;
+
+ struct pipe_blend_color blend_color;
+ struct pipe_clip_state clip;
+ struct pipe_constant_buffer constants[2];
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_poly_stipple poly_stipple;
+ struct pipe_scissor_state scissor;
+ struct cell_texture *texture[PIPE_MAX_SAMPLERS];
+ uint num_textures;
+ struct pipe_viewport_state viewport;
+ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ uint num_vertex_buffers;
+ struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
+ uint num_vertex_elements;
+
+ ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS];
+ ubyte *zsbuf_map;
+
+ uint dirty;
+ uint dirty_textures; /* bitmask of texture units */
+ uint dirty_samplers; /* bitmask of sampler units */
+
+ /** Cache of code generated for per-fragment ops */
+ struct keymap *fragment_ops_cache;
+
+ /** The primitive drawing context */
+ struct draw_context *draw;
+ struct draw_stage *render_stage;
+
+ /** For post-transformed vertex buffering: */
+ struct cell_vbuf_render *vbuf_render;
+ struct draw_stage *vbuf;
+
+ struct vertex_info vertex_info;
+
+ /** Mapped constant buffers */
+ void *mapped_constants[PIPE_SHADER_TYPES];
+
+ struct cell_spu_function_info spu_functions ALIGN16_ATTRIB;
+
+ uint num_cells, num_spus;
+
+ /** Buffers for command batches, vertex/index data */
+ uint buffer_size[CELL_NUM_BUFFERS];
+ ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE] ALIGN16_ATTRIB;
+
+ int cur_batch; /**< which buffer is being filled w/ commands */
+
+ /** [4] to ensure 16-byte alignment for each status word */
+ uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4] ALIGN16_ATTRIB;
+
+
+ /** Associated with each command/batch buffer is a list of pipe_buffers
+ * that are fenced. When the last command in a buffer is executed, the
+ * fence will be signalled, indicating that any pipe_buffers preceeding
+ * that fence can be unreferenced (and probably freed).
+ */
+ struct cell_buffer_list fenced_buffers[CELL_NUM_BUFFERS];
+
+
+ struct spe_function attrib_fetch;
+ unsigned attrib_fetch_offsets[PIPE_MAX_ATTRIBS];
+
+ unsigned debug_flags;
+};
+
+
+
+
+static INLINE struct cell_context *
+cell_context(struct pipe_context *pipe)
+{
+ return (struct cell_context *) pipe;
+}
+
+
+extern struct pipe_context *
+cell_create_context(struct pipe_screen *screen, struct cell_winsys *cws);
+
+extern void
+cell_vertex_shader_queue_flush(struct draw_context *draw);
+
+
+/* XXX find a better home for this */
+extern void cell_update_vertex_fetch(struct draw_context *draw);
+
+
+#endif /* CELL_CONTEXT_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
new file mode 100644
index 0000000000..644496db40
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
@@ -0,0 +1,191 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Brian Paul
+ * Keith Whitwell
+ */
+
+
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+
+#include "cell_context.h"
+#include "cell_draw_arrays.h"
+#include "cell_state.h"
+#include "cell_flush.h"
+
+#include "draw/draw_context.h"
+
+
+
+static void
+cell_map_constant_buffers(struct cell_context *sp)
+{
+ struct pipe_winsys *ws = sp->pipe.winsys;
+ uint i;
+ for (i = 0; i < 2; i++) {
+ if (sp->constants[i].buffer && sp->constants[i].buffer->size) {
+ sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ cell_flush_buffer_range(sp, sp->mapped_constants[i],
+ sp->constants[i].buffer->size);
+ }
+ }
+
+ draw_set_mapped_constant_buffer(sp->draw,
+ sp->mapped_constants[PIPE_SHADER_VERTEX],
+ sp->constants[PIPE_SHADER_VERTEX].buffer->size);
+}
+
+static void
+cell_unmap_constant_buffers(struct cell_context *sp)
+{
+ struct pipe_winsys *ws = sp->pipe.winsys;
+ uint i;
+ for (i = 0; i < 2; i++) {
+ if (sp->constants[i].buffer && sp->constants[i].buffer->size)
+ ws->buffer_unmap(ws, sp->constants[i].buffer);
+ sp->mapped_constants[i] = NULL;
+ }
+}
+
+
+
+/**
+ * Draw vertex arrays, with optional indexing.
+ * Basically, map the vertex buffers (and drawing surfaces), then hand off
+ * the drawing to the 'draw' module.
+ *
+ * XXX should the element buffer be specified/bound with a separate function?
+ */
+static boolean
+cell_draw_range_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned min_index,
+ unsigned max_index,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct cell_context *sp = cell_context(pipe);
+ struct draw_context *draw = sp->draw;
+ unsigned i;
+
+ if (sp->dirty)
+ cell_update_derived( sp );
+
+#if 0
+ cell_map_surfaces(sp);
+#endif
+ cell_map_constant_buffers(sp);
+
+ /*
+ * Map vertex buffers
+ */
+ for (i = 0; i < sp->num_vertex_buffers; i++) {
+ void *buf = pipe_buffer_map(pipe->screen,
+ sp->vertex_buffer[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ cell_flush_buffer_range(sp, buf, sp->vertex_buffer[i].buffer->size);
+ draw_set_mapped_vertex_buffer(draw, i, buf);
+ }
+ /* Map index buffer, if present */
+ if (indexBuffer) {
+ void *mapped_indexes = pipe_buffer_map(pipe->screen,
+ indexBuffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes);
+ }
+ else {
+ /* no index/element buffer */
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+
+ /* draw! */
+ draw_arrays(draw, mode, start, count);
+
+ /*
+ * unmap vertex/index buffers - will cause draw module to flush
+ */
+ for (i = 0; i < sp->num_vertex_buffers; i++) {
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer);
+ }
+ if (indexBuffer) {
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ pipe_buffer_unmap(pipe->screen, indexBuffer);
+ }
+
+ /* Note: leave drawing surfaces mapped */
+ cell_unmap_constant_buffers(sp);
+
+ return TRUE;
+}
+
+
+static boolean
+cell_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+{
+ return cell_draw_range_elements( pipe, indexBuffer,
+ indexSize,
+ 0, 0xffffffff,
+ mode, start, count );
+}
+
+
+static boolean
+cell_draw_arrays(struct pipe_context *pipe, unsigned mode,
+ unsigned start, unsigned count)
+{
+ return cell_draw_elements(pipe, NULL, 0, mode, start, count);
+}
+
+
+static void
+cell_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags)
+{
+ struct cell_context *cell = cell_context(pipe);
+ draw_set_edgeflags(cell->draw, edgeflags);
+}
+
+
+
+void
+cell_init_draw_functions(struct cell_context *cell)
+{
+ cell->pipe.draw_arrays = cell_draw_arrays;
+ cell->pipe.draw_elements = cell_draw_elements;
+ cell->pipe.draw_range_elements = cell_draw_range_elements;
+ cell->pipe.set_edgeflags = cell_set_edgeflags;
+}
+
diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.h b/src/gallium/drivers/cell/ppu/cell_draw_arrays.h
new file mode 100644
index 0000000000..148873aa67
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef CELL_DRAW_ARRAYS_H
+#define CELL_DRAW_ARRAYS_H
+
+
+extern void
+cell_init_draw_functions(struct cell_context *cell);
+
+
+#endif /* CELL_DRAW_ARRAYS_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_fence.c b/src/gallium/drivers/cell/ppu/cell_fence.c
new file mode 100644
index 0000000000..13125a9fa3
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_fence.c
@@ -0,0 +1,164 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <unistd.h>
+#include "util/u_memory.h"
+#include "pipe/p_inlines.h"
+#include "cell_context.h"
+#include "cell_batch.h"
+#include "cell_fence.h"
+#include "cell_texture.h"
+
+
+void
+cell_fence_init(struct cell_fence *fence)
+{
+ uint i;
+ ASSERT_ALIGN16(fence->status);
+ for (i = 0; i < CELL_MAX_SPUS; i++) {
+ fence->status[i][0] = CELL_FENCE_IDLE;
+ }
+}
+
+
+boolean
+cell_fence_signalled(const struct cell_context *cell,
+ const struct cell_fence *fence)
+{
+ uint i;
+ for (i = 0; i < cell->num_spus; i++) {
+ if (fence->status[i][0] != CELL_FENCE_SIGNALLED)
+ return FALSE;
+ /*assert(fence->status[i][0] == CELL_FENCE_EMITTED);*/
+ }
+ return TRUE;
+}
+
+
+void
+cell_fence_finish(const struct cell_context *cell,
+ const struct cell_fence *fence)
+{
+ while (!cell_fence_signalled(cell, fence)) {
+ usleep(10);
+ }
+
+#ifdef DEBUG
+ {
+ uint i;
+ for (i = 0; i < cell->num_spus; i++) {
+ assert(fence->status[i][0] == CELL_FENCE_SIGNALLED);
+ }
+ }
+#endif
+}
+
+
+
+
+struct cell_buffer_node
+{
+ struct pipe_buffer *buffer;
+ struct cell_buffer_node *next;
+};
+
+
+static void
+cell_add_buffer_to_list(struct cell_context *cell,
+ struct cell_buffer_list *list,
+ struct pipe_buffer *buffer)
+{
+ struct pipe_screen *ps = cell->pipe.screen;
+ struct cell_buffer_node *node = CALLOC_STRUCT(cell_buffer_node);
+ /* create new list node which references the buffer, insert at head */
+ if (node) {
+ pipe_buffer_reference(&node->buffer, buffer);
+ node->next = list->head;
+ list->head = node;
+ }
+}
+
+
+/**
+ * Wait for completion of the given fence, then unreference any buffers
+ * on the list.
+ * This typically unrefs/frees texture buffers after any rendering which uses
+ * them has completed.
+ */
+void
+cell_free_fenced_buffers(struct cell_context *cell,
+ struct cell_buffer_list *list)
+{
+ if (list->head) {
+ struct pipe_screen *ps = cell->pipe.screen;
+ struct cell_buffer_node *node;
+
+ cell_fence_finish(cell, &list->fence);
+
+ /* traverse the list, unreferencing buffers, freeing nodes */
+ node = list->head;
+ while (node) {
+ struct cell_buffer_node *next = node->next;
+ assert(node->buffer);
+ pipe_buffer_unmap(ps, node->buffer);
+#if 0
+ printf("Unref buffer %p\n", node->buffer);
+ if (node->buffer->reference.count == 1)
+ printf(" Delete!\n");
+#endif
+ pipe_buffer_reference(&node->buffer, NULL);
+ FREE(node);
+ node = next;
+ }
+ list->head = NULL;
+ }
+}
+
+
+/**
+ * This should be called for each render command.
+ * Any texture buffers that are current bound will be added to a fenced
+ * list to be freed later when the fence is executed/signalled.
+ */
+void
+cell_add_fenced_textures(struct cell_context *cell)
+{
+ struct cell_buffer_list *list = &cell->fenced_buffers[cell->cur_batch];
+ uint i;
+
+ for (i = 0; i < cell->num_textures; i++) {
+ struct cell_texture *ct = cell->texture[i];
+ if (ct) {
+#if 0
+ printf("Adding texture %p buffer %p to list\n",
+ ct, ct->tiled_buffer[level]);
+#endif
+ if (ct->buffer)
+ cell_add_buffer_to_list(cell, list, ct->buffer);
+ }
+ }
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_fence.h b/src/gallium/drivers/cell/ppu/cell_fence.h
new file mode 100644
index 0000000000..536b4ba411
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_fence.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_FENCE_H
+#define CELL_FENCE_H
+
+
+extern void
+cell_fence_init(struct cell_fence *fence);
+
+
+extern boolean
+cell_fence_signalled(const struct cell_context *cell,
+ const struct cell_fence *fence);
+
+
+extern void
+cell_fence_finish(const struct cell_context *cell,
+ const struct cell_fence *fence);
+
+
+
+extern void
+cell_free_fenced_buffers(struct cell_context *cell,
+ struct cell_buffer_list *list);
+
+
+extern void
+cell_add_fenced_textures(struct cell_context *cell);
+
+
+#endif /* CELL_FENCE_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_flush.c b/src/gallium/drivers/cell/ppu/cell_flush.c
new file mode 100644
index 0000000000..8275c9dc9c
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_flush.c
@@ -0,0 +1,112 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "cell_context.h"
+#include "cell_batch.h"
+#include "cell_flush.h"
+#include "cell_spu.h"
+#include "cell_render.h"
+#include "draw/draw_context.h"
+
+
+/**
+ * Called via pipe->flush()
+ */
+void
+cell_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ if (fence) {
+ *fence = NULL;
+ /* XXX: Implement real fencing */
+ flags |= CELL_FLUSH_WAIT;
+ }
+
+ if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_RENDER_CACHE))
+ flags |= CELL_FLUSH_WAIT;
+
+ draw_flush( cell->draw );
+ cell_flush_int(cell, flags);
+}
+
+
+/**
+ * Cell internal flush function. Send the current batch buffer to all SPUs.
+ * If flags & CELL_FLUSH_WAIT, do not return until the SPUs are idle.
+ * \param flags bitmask of flags CELL_FLUSH_WAIT, or zero
+ */
+void
+cell_flush_int(struct cell_context *cell, unsigned flags)
+{
+ static boolean flushing = FALSE; /* recursion catcher */
+ uint i;
+
+ ASSERT(!flushing);
+ flushing = TRUE;
+
+ if (flags & CELL_FLUSH_WAIT) {
+ STATIC_ASSERT(sizeof(opcode_t) % 16 == 0);
+ opcode_t *cmd = (opcode_t*) cell_batch_alloc16(cell, sizeof(opcode_t));
+ *cmd[0] = CELL_CMD_FINISH;
+ }
+
+ cell_batch_flush(cell);
+
+#if 0
+ /* Send CMD_FINISH to all SPUs */
+ for (i = 0; i < cell->num_spus; i++) {
+ send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_FINISH);
+ }
+#endif
+
+ if (flags & CELL_FLUSH_WAIT) {
+ /* Wait for ack */
+ for (i = 0; i < cell->num_spus; i++) {
+ uint k = wait_mbox_message(cell_global.spe_contexts[i]);
+ assert(k == CELL_CMD_FINISH);
+ }
+ }
+
+ flushing = FALSE;
+}
+
+
+void
+cell_flush_buffer_range(struct cell_context *cell, void *ptr,
+ unsigned size)
+{
+ STATIC_ASSERT((sizeof(opcode_t) + sizeof(struct cell_buffer_range)) % 16 == 0);
+ uint32_t *batch = (uint32_t*)cell_batch_alloc16(cell,
+ sizeof(opcode_t) + sizeof(struct cell_buffer_range));
+ struct cell_buffer_range *br = (struct cell_buffer_range *) &batch[4];
+ batch[0] = CELL_CMD_FLUSH_BUFFER_RANGE;
+ br->base = (uintptr_t) ptr;
+ br->size = size;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_flush.h b/src/gallium/drivers/cell/ppu/cell_flush.h
new file mode 100644
index 0000000000..509ae6239a
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_flush.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_FLUSH
+#define CELL_FLUSH
+
+#define CELL_FLUSH_WAIT 0x80000000
+
+extern void
+cell_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence);
+
+extern void
+cell_flush_int(struct cell_context *cell, unsigned flags);
+
+extern void
+cell_flush_buffer_range(struct cell_context *cell, void *ptr,
+ unsigned size);
+
+#endif
diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fp.c b/src/gallium/drivers/cell/ppu/cell_gen_fp.c
new file mode 100644
index 0000000000..312621fd53
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_gen_fp.c
@@ -0,0 +1,2046 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2009 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+
+/**
+ * Generate SPU fragment program/shader code.
+ *
+ * Note that we generate SOA-style code here. So each TGSI instruction
+ * operates on four pixels (and is translated into four SPU instructions,
+ * generally speaking).
+ *
+ * \author Brian Paul
+ */
+
+#include <math.h>
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_exec.h"
+#include "tgsi/tgsi_dump.h"
+#include "rtasm/rtasm_ppc_spe.h"
+#include "util/u_memory.h"
+#include "cell_context.h"
+#include "cell_gen_fp.h"
+
+
+#define MAX_TEMPS 16
+#define MAX_IMMED 8
+
+#define CHAN_X 0
+#define CHAN_Y 1
+#define CHAN_Z 2
+#define CHAN_W 3
+
+/**
+ * Context needed during code generation.
+ */
+struct codegen
+{
+ struct cell_context *cell;
+ int inputs_reg; /**< 1st function parameter */
+ int outputs_reg; /**< 2nd function parameter */
+ int constants_reg; /**< 3rd function parameter */
+ int temp_regs[MAX_TEMPS][4]; /**< maps TGSI temps to SPE registers */
+ int imm_regs[MAX_IMMED][4]; /**< maps TGSI immediates to SPE registers */
+
+ int num_imm; /**< number of immediates */
+
+ int one_reg; /**< register containing {1.0, 1.0, 1.0, 1.0} */
+
+ int addr_reg; /**< address register, integer values */
+
+ /** Per-instruction temps / intermediate temps */
+ int num_itemps;
+ int itemps[12];
+
+ /** Current IF/ELSE/ENDIF nesting level */
+ int if_nesting;
+ /** Current BGNLOOP/ENDLOOP nesting level */
+ int loop_nesting;
+ /** Location of start of current loop */
+ int loop_start;
+
+ /** Index of if/conditional mask register */
+ int cond_mask_reg;
+ /** Index of loop mask register */
+ int loop_mask_reg;
+
+ /** Index of master execution mask register */
+ int exec_mask_reg;
+
+ /** KIL mask: indicates which fragments have been killed */
+ int kill_mask_reg;
+
+ int frame_size; /**< Stack frame size, in words */
+
+ struct spe_function *f;
+ boolean error;
+};
+
+
+/**
+ * Allocate an intermediate temporary register.
+ */
+static int
+get_itemp(struct codegen *gen)
+{
+ int t = spe_allocate_available_register(gen->f);
+ assert(gen->num_itemps < Elements(gen->itemps));
+ gen->itemps[gen->num_itemps++] = t;
+ return t;
+}
+
+/**
+ * Free all intermediate temporary registers. To be called after each
+ * instruction has been emitted.
+ */
+static void
+free_itemps(struct codegen *gen)
+{
+ int i;
+ for (i = 0; i < gen->num_itemps; i++) {
+ spe_release_register(gen->f, gen->itemps[i]);
+ }
+ gen->num_itemps = 0;
+}
+
+
+/**
+ * Return index of an SPE register containing {1.0, 1.0, 1.0, 1.0}.
+ * The register is allocated and initialized upon the first call.
+ */
+static int
+get_const_one_reg(struct codegen *gen)
+{
+ if (gen->one_reg <= 0) {
+ gen->one_reg = spe_allocate_available_register(gen->f);
+
+ spe_indent(gen->f, 4);
+ spe_comment(gen->f, -4, "init constant reg = 1.0:");
+
+ /* one = {1.0, 1.0, 1.0, 1.0} */
+ spe_load_float(gen->f, gen->one_reg, 1.0f);
+
+ spe_indent(gen->f, -4);
+ }
+
+ return gen->one_reg;
+}
+
+
+/**
+ * Return index of the address register.
+ * Used for indirect register loads/stores.
+ */
+static int
+get_address_reg(struct codegen *gen)
+{
+ if (gen->addr_reg <= 0) {
+ gen->addr_reg = spe_allocate_available_register(gen->f);
+
+ spe_indent(gen->f, 4);
+ spe_comment(gen->f, -4, "init address reg = 0:");
+
+ /* init addr = {0, 0, 0, 0} */
+ spe_zero(gen->f, gen->addr_reg);
+
+ spe_indent(gen->f, -4);
+ }
+
+ return gen->addr_reg;
+}
+
+
+/**
+ * Return index of the master execution mask.
+ * The register is allocated an initialized upon the first call.
+ *
+ * The master execution mask controls which pixels in a quad are
+ * modified, according to surrounding conditionals, loops, etc.
+ */
+static int
+get_exec_mask_reg(struct codegen *gen)
+{
+ if (gen->exec_mask_reg <= 0) {
+ gen->exec_mask_reg = spe_allocate_available_register(gen->f);
+
+ /* XXX this may not be needed */
+ spe_comment(gen->f, 0*-4, "initialize master execution mask = ~0");
+ spe_load_int(gen->f, gen->exec_mask_reg, ~0);
+ }
+
+ return gen->exec_mask_reg;
+}
+
+
+/** Return index of the conditional (if/else) execution mask register */
+static int
+get_cond_mask_reg(struct codegen *gen)
+{
+ if (gen->cond_mask_reg <= 0) {
+ gen->cond_mask_reg = spe_allocate_available_register(gen->f);
+ }
+
+ return gen->cond_mask_reg;
+}
+
+
+/** Return index of the loop execution mask register */
+static int
+get_loop_mask_reg(struct codegen *gen)
+{
+ if (gen->loop_mask_reg <= 0) {
+ gen->loop_mask_reg = spe_allocate_available_register(gen->f);
+ }
+
+ return gen->loop_mask_reg;
+}
+
+
+
+static boolean
+is_register_src(struct codegen *gen, int channel,
+ const struct tgsi_full_src_register *src)
+{
+ int swizzle = tgsi_util_get_full_src_register_extswizzle(src, channel);
+ int sign_op = tgsi_util_get_full_src_register_sign_mode(src, channel);
+
+ if (swizzle > TGSI_SWIZZLE_W || sign_op != TGSI_UTIL_SIGN_KEEP) {
+ return FALSE;
+ }
+ if (src->SrcRegister.File == TGSI_FILE_TEMPORARY ||
+ src->SrcRegister.File == TGSI_FILE_IMMEDIATE) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static boolean
+is_memory_dst(struct codegen *gen, int channel,
+ const struct tgsi_full_dst_register *dst)
+{
+ if (dst->DstRegister.File == TGSI_FILE_OUTPUT) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+
+/**
+ * Return the index of the SPU temporary containing the named TGSI
+ * source register. If the TGSI register is a TGSI_FILE_TEMPORARY we
+ * just return the corresponding SPE register. If the TGIS register
+ * is TGSI_FILE_INPUT/CONSTANT/IMMEDIATE we allocate a new SPE register
+ * and emit an SPE load instruction.
+ */
+static int
+get_src_reg(struct codegen *gen,
+ int channel,
+ const struct tgsi_full_src_register *src)
+{
+ int reg = -1;
+ int swizzle = tgsi_util_get_full_src_register_extswizzle(src, channel);
+ boolean reg_is_itemp = FALSE;
+ uint sign_op;
+
+ assert(swizzle >= TGSI_SWIZZLE_X);
+ assert(swizzle <= TGSI_EXTSWIZZLE_ONE);
+
+ if (swizzle == TGSI_EXTSWIZZLE_ONE) {
+ /* Load const one float and early out */
+ reg = get_const_one_reg(gen);
+ }
+ else if (swizzle == TGSI_EXTSWIZZLE_ZERO) {
+ /* Load const zero float and early out */
+ reg = get_itemp(gen);
+ spe_xor(gen->f, reg, reg, reg);
+ }
+ else {
+ int index = src->SrcRegister.Index;
+
+ assert(swizzle < 4);
+
+ if (src->SrcRegister.Indirect) {
+ /* XXX unfinished */
+ }
+
+ switch (src->SrcRegister.File) {
+ case TGSI_FILE_TEMPORARY:
+ reg = gen->temp_regs[index][swizzle];
+ break;
+ case TGSI_FILE_INPUT:
+ {
+ /* offset is measured in quadwords, not bytes */
+ int offset = index * 4 + swizzle;
+ reg = get_itemp(gen);
+ reg_is_itemp = TRUE;
+ /* Load: reg = memory[(machine_reg) + offset] */
+ spe_lqd(gen->f, reg, gen->inputs_reg, offset * 16);
+ }
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ reg = gen->imm_regs[index][swizzle];
+ break;
+ case TGSI_FILE_CONSTANT:
+ {
+ /* offset is measured in quadwords, not bytes */
+ int offset = index * 4 + swizzle;
+ reg = get_itemp(gen);
+ reg_is_itemp = TRUE;
+ /* Load: reg = memory[(machine_reg) + offset] */
+ spe_lqd(gen->f, reg, gen->constants_reg, offset * 16);
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ /*
+ * Handle absolute value, negate or set-negative of src register.
+ */
+ sign_op = tgsi_util_get_full_src_register_sign_mode(src, channel);
+ if (sign_op != TGSI_UTIL_SIGN_KEEP) {
+ /*
+ * All sign ops are done by manipulating bit 31, the IEEE float sign bit.
+ */
+ const int bit31mask_reg = get_itemp(gen);
+ int result_reg;
+
+ if (reg_is_itemp) {
+ /* re-use 'reg' for the result */
+ result_reg = reg;
+ }
+ else {
+ /* alloc a new reg for the result */
+ result_reg = get_itemp(gen);
+ }
+
+ /* mask with bit 31 set, the rest cleared */
+ spe_load_uint(gen->f, bit31mask_reg, (1 << 31));
+
+ if (sign_op == TGSI_UTIL_SIGN_CLEAR) {
+ spe_andc(gen->f, result_reg, reg, bit31mask_reg);
+ }
+ else if (sign_op == TGSI_UTIL_SIGN_SET) {
+ spe_and(gen->f, result_reg, reg, bit31mask_reg);
+ }
+ else {
+ assert(sign_op == TGSI_UTIL_SIGN_TOGGLE);
+ spe_xor(gen->f, result_reg, reg, bit31mask_reg);
+ }
+
+ reg = result_reg;
+ }
+
+ return reg;
+}
+
+
+/**
+ * Return the index of an SPE register to use for the given TGSI register.
+ * If the TGSI register is TGSI_FILE_TEMPORARAY, the index of the
+ * corresponding SPE register is returned. If the TGSI register is
+ * TGSI_FILE_OUTPUT we allocate an intermediate temporary register.
+ * See store_dest_reg() below...
+ */
+static int
+get_dst_reg(struct codegen *gen,
+ int channel,
+ const struct tgsi_full_dst_register *dest)
+{
+ int reg = -1;
+
+ switch (dest->DstRegister.File) {
+ case TGSI_FILE_TEMPORARY:
+ if (gen->if_nesting > 0 || gen->loop_nesting > 0)
+ reg = get_itemp(gen);
+ else
+ reg = gen->temp_regs[dest->DstRegister.Index][channel];
+ break;
+ case TGSI_FILE_OUTPUT:
+ reg = get_itemp(gen);
+ break;
+ default:
+ assert(0);
+ }
+
+ return reg;
+}
+
+
+/**
+ * When a TGSI instruction is writing to an output register, this
+ * function emits the SPE store instruction to store the value_reg.
+ * \param value_reg the SPE register containing the value to store.
+ * This would have been returned by get_dst_reg().
+ */
+static void
+store_dest_reg(struct codegen *gen,
+ int value_reg, int channel,
+ const struct tgsi_full_dst_register *dest)
+{
+ /*
+ * XXX need to implement dst reg clamping/saturation
+ */
+#if 0
+ switch (inst->Instruction.Saturate) {
+ case TGSI_SAT_NONE:
+ break;
+ case TGSI_SAT_ZERO_ONE:
+ break;
+ case TGSI_SAT_MINUS_PLUS_ONE:
+ break;
+ default:
+ assert( 0 );
+ }
+#endif
+
+ switch (dest->DstRegister.File) {
+ case TGSI_FILE_TEMPORARY:
+ if (gen->if_nesting > 0 || gen->loop_nesting > 0) {
+ int d_reg = gen->temp_regs[dest->DstRegister.Index][channel];
+ int exec_reg = get_exec_mask_reg(gen);
+ /* Mix d with new value according to exec mask:
+ * d[i] = mask_reg[i] ? value_reg : d_reg
+ */
+ spe_selb(gen->f, d_reg, d_reg, value_reg, exec_reg);
+ }
+ else {
+ /* we're not inside a condition or loop: do nothing special */
+
+ }
+ break;
+ case TGSI_FILE_OUTPUT:
+ {
+ /* offset is measured in quadwords, not bytes */
+ int offset = dest->DstRegister.Index * 4 + channel;
+ if (gen->if_nesting > 0 || gen->loop_nesting > 0) {
+ int exec_reg = get_exec_mask_reg(gen);
+ int curval_reg = get_itemp(gen);
+ /* First read the current value from memory:
+ * Load: curval = memory[(machine_reg) + offset]
+ */
+ spe_lqd(gen->f, curval_reg, gen->outputs_reg, offset * 16);
+ /* Mix curval with newvalue according to exec mask:
+ * d[i] = mask_reg[i] ? value_reg : d_reg
+ */
+ spe_selb(gen->f, curval_reg, curval_reg, value_reg, exec_reg);
+ /* Store: memory[(machine_reg) + offset] = curval */
+ spe_stqd(gen->f, curval_reg, gen->outputs_reg, offset * 16);
+ }
+ else {
+ /* Store: memory[(machine_reg) + offset] = reg */
+ spe_stqd(gen->f, value_reg, gen->outputs_reg, offset * 16);
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+
+static void
+emit_prologue(struct codegen *gen)
+{
+ gen->frame_size = 1024; /* XXX temporary, should be dynamic */
+
+ spe_comment(gen->f, 0, "Function prologue:");
+
+ /* save $lr on stack # stqd $lr,16($sp) */
+ spe_stqd(gen->f, SPE_REG_RA, SPE_REG_SP, 16);
+
+ if (gen->frame_size >= 512) {
+ /* offset is too large for ai instruction */
+ int offset_reg = spe_allocate_available_register(gen->f);
+ int sp_reg = spe_allocate_available_register(gen->f);
+ /* offset = -framesize */
+ spe_load_int(gen->f, offset_reg, -gen->frame_size);
+ /* sp = $sp */
+ spe_move(gen->f, sp_reg, SPE_REG_SP);
+ /* $sp = $sp + offset_reg */
+ spe_a(gen->f, SPE_REG_SP, SPE_REG_SP, offset_reg);
+ /* save $sp in stack frame */
+ spe_stqd(gen->f, sp_reg, SPE_REG_SP, 0);
+ /* clean up */
+ spe_release_register(gen->f, offset_reg);
+ spe_release_register(gen->f, sp_reg);
+ }
+ else {
+ /* save stack pointer # stqd $sp,-frameSize($sp) */
+ spe_stqd(gen->f, SPE_REG_SP, SPE_REG_SP, -gen->frame_size);
+
+ /* adjust stack pointer # ai $sp,$sp,-frameSize */
+ spe_ai(gen->f, SPE_REG_SP, SPE_REG_SP, -gen->frame_size);
+ }
+}
+
+
+static void
+emit_epilogue(struct codegen *gen)
+{
+ const int return_reg = 3;
+
+ spe_comment(gen->f, 0, "Function epilogue:");
+
+ spe_comment(gen->f, 0, "return the killed mask");
+ if (gen->kill_mask_reg > 0) {
+ /* shader called KIL, return the "alive" mask */
+ spe_move(gen->f, return_reg, gen->kill_mask_reg);
+ }
+ else {
+ /* return {0,0,0,0} */
+ spe_load_uint(gen->f, return_reg, 0);
+ }
+
+ spe_comment(gen->f, 0, "restore stack and return");
+ if (gen->frame_size >= 512) {
+ /* offset is too large for ai instruction */
+ int offset_reg = spe_allocate_available_register(gen->f);
+ /* offset = framesize */
+ spe_load_int(gen->f, offset_reg, gen->frame_size);
+ /* $sp = $sp + offset */
+ spe_a(gen->f, SPE_REG_SP, SPE_REG_SP, offset_reg);
+ /* clean up */
+ spe_release_register(gen->f, offset_reg);
+ }
+ else {
+ /* restore stack pointer # ai $sp,$sp,frameSize */
+ spe_ai(gen->f, SPE_REG_SP, SPE_REG_SP, gen->frame_size);
+ }
+
+ /* restore $lr # lqd $lr,16($sp) */
+ spe_lqd(gen->f, SPE_REG_RA, SPE_REG_SP, 16);
+
+ /* return from function call */
+ spe_bi(gen->f, SPE_REG_RA, 0, 0);
+}
+
+
+#define FOR_EACH_ENABLED_CHANNEL(inst, ch) \
+ for (ch = 0; ch < 4; ch++) \
+ if (inst->FullDstRegisters[0].DstRegister.WriteMask & (1 << ch))
+
+
+static boolean
+emit_ARL(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch = 0, src_reg, addr_reg;
+
+ src_reg = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ addr_reg = get_address_reg(gen);
+
+ /* convert float to int */
+ spe_cflts(gen->f, addr_reg, src_reg, 0);
+
+ free_itemps(gen);
+
+ return TRUE;
+}
+
+
+static boolean
+emit_MOV(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, src_reg[4], dst_reg[4];
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ src_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ dst_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ if (is_register_src(gen, ch, &inst->FullSrcRegisters[0]) &&
+ is_memory_dst(gen, ch, &inst->FullDstRegisters[0])) {
+ /* special-case: register to memory store */
+ store_dest_reg(gen, src_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+ else {
+ spe_move(gen->f, dst_reg[ch], src_reg[ch]);
+ store_dest_reg(gen, dst_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+ }
+
+ free_itemps(gen);
+
+ return TRUE;
+}
+
+/**
+ * Emit binary operation
+ */
+static boolean
+emit_binop(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s1_reg[4], s2_reg[4], d_reg[4];
+
+ /* Loop over Red/Green/Blue/Alpha channels, fetch src operands */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ s2_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[1]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ }
+
+ /* Loop over Red/Green/Blue/Alpha channels, do the op, store results */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ /* Emit actual SPE instruction: d = s1 + s2 */
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ADD:
+ spe_fa(gen->f, d_reg[ch], s1_reg[ch], s2_reg[ch]);
+ break;
+ case TGSI_OPCODE_SUB:
+ spe_fs(gen->f, d_reg[ch], s1_reg[ch], s2_reg[ch]);
+ break;
+ case TGSI_OPCODE_MUL:
+ spe_fm(gen->f, d_reg[ch], s1_reg[ch], s2_reg[ch]);
+ break;
+ default:
+ ;
+ }
+ }
+
+ /* Store the result (a no-op for TGSI_FILE_TEMPORARY dests) */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+
+ /* Free any intermediate temps we allocated */
+ free_itemps(gen);
+
+ return TRUE;
+}
+
+
+/**
+ * Emit multiply add. See emit_ADD for comments.
+ */
+static boolean
+emit_MAD(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s1_reg[4], s2_reg[4], s3_reg[4], d_reg[4];
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ s2_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[1]);
+ s3_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[2]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ }
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_fma(gen->f, d_reg[ch], s1_reg[ch], s2_reg[ch], s3_reg[ch]);
+ }
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+/**
+ * Emit linear interpolate. See emit_ADD for comments.
+ */
+static boolean
+emit_LERP(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s1_reg[4], s2_reg[4], s3_reg[4], d_reg[4], tmp_reg[4];
+
+ /* setup/get src/dst/temp regs */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ s2_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[1]);
+ s3_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[2]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ tmp_reg[ch] = get_itemp(gen);
+ }
+
+ /* d = s3 + s1(s2 - s3) */
+ /* do all subtracts, then all fma, then all stores to better pipeline */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_fs(gen->f, tmp_reg[ch], s2_reg[ch], s3_reg[ch]);
+ }
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_fma(gen->f, d_reg[ch], tmp_reg[ch], s1_reg[ch], s3_reg[ch]);
+ }
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+
+/**
+ * Emit reciprocal or recip sqrt.
+ */
+static boolean
+emit_RCP_RSQ(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s1_reg[4], d_reg[4], tmp_reg[4];
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ tmp_reg[ch] = get_itemp(gen);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ if (inst->Instruction.Opcode == TGSI_OPCODE_RCP) {
+ /* tmp = 1/s1 */
+ spe_frest(gen->f, tmp_reg[ch], s1_reg[ch]);
+ }
+ else {
+ /* tmp = 1/sqrt(s1) */
+ spe_frsqest(gen->f, tmp_reg[ch], s1_reg[ch]);
+ }
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ /* d = float_interp(s1, tmp) */
+ spe_fi(gen->f, d_reg[ch], s1_reg[ch], tmp_reg[ch]);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+/**
+ * Emit absolute value. See emit_ADD for comments.
+ */
+static boolean
+emit_ABS(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s1_reg[4], d_reg[4];
+ const int bit31mask_reg = get_itemp(gen);
+
+ /* mask with bit 31 set, the rest cleared */
+ spe_load_uint(gen->f, bit31mask_reg, (1 << 31));
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ }
+
+ /* d = sign bit cleared in s1 */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_andc(gen->f, d_reg[ch], s1_reg[ch], bit31mask_reg);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+/**
+ * Emit 3 component dot product. See emit_ADD for comments.
+ */
+static boolean
+emit_DP3(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch;
+ int s1x_reg, s1y_reg, s1z_reg;
+ int s2x_reg, s2y_reg, s2z_reg;
+ int t0_reg = get_itemp(gen), t1_reg = get_itemp(gen);
+
+ s1x_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[0]);
+ s2x_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[1]);
+ s1y_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[0]);
+ s2y_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[1]);
+ s1z_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[0]);
+ s2z_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[1]);
+
+ /* t0 = x0 * x1 */
+ spe_fm(gen->f, t0_reg, s1x_reg, s2x_reg);
+
+ /* t1 = y0 * y1 */
+ spe_fm(gen->f, t1_reg, s1y_reg, s2y_reg);
+
+ /* t0 = z0 * z1 + t0 */
+ spe_fma(gen->f, t0_reg, s1z_reg, s2z_reg, t0_reg);
+
+ /* t0 = t0 + t1 */
+ spe_fa(gen->f, t0_reg, t0_reg, t1_reg);
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ int d_reg = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ spe_move(gen->f, d_reg, t0_reg);
+ store_dest_reg(gen, d_reg, ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+/**
+ * Emit 4 component dot product. See emit_ADD for comments.
+ */
+static boolean
+emit_DP4(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch;
+ int s0x_reg, s0y_reg, s0z_reg, s0w_reg;
+ int s1x_reg, s1y_reg, s1z_reg, s1w_reg;
+ int t0_reg = get_itemp(gen), t1_reg = get_itemp(gen);
+
+ s0x_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[0]);
+ s1x_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[1]);
+ s0y_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[0]);
+ s1y_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[1]);
+ s0z_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[0]);
+ s1z_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[1]);
+ s0w_reg = get_src_reg(gen, CHAN_W, &inst->FullSrcRegisters[0]);
+ s1w_reg = get_src_reg(gen, CHAN_W, &inst->FullSrcRegisters[1]);
+
+ /* t0 = x0 * x1 */
+ spe_fm(gen->f, t0_reg, s0x_reg, s1x_reg);
+
+ /* t1 = y0 * y1 */
+ spe_fm(gen->f, t1_reg, s0y_reg, s1y_reg);
+
+ /* t0 = z0 * z1 + t0 */
+ spe_fma(gen->f, t0_reg, s0z_reg, s1z_reg, t0_reg);
+
+ /* t1 = w0 * w1 + t1 */
+ spe_fma(gen->f, t1_reg, s0w_reg, s1w_reg, t1_reg);
+
+ /* t0 = t0 + t1 */
+ spe_fa(gen->f, t0_reg, t0_reg, t1_reg);
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ int d_reg = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ spe_move(gen->f, d_reg, t0_reg);
+ store_dest_reg(gen, d_reg, ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+/**
+ * Emit homogeneous dot product. See emit_ADD for comments.
+ */
+static boolean
+emit_DPH(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ /* XXX rewrite this function to look more like DP3/DP4 */
+ int ch;
+ int s1_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[0]);
+ int s2_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[1]);
+ int tmp_reg = get_itemp(gen);
+
+ /* t = x0 * x1 */
+ spe_fm(gen->f, tmp_reg, s1_reg, s2_reg);
+
+ s1_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[0]);
+ s2_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[1]);
+ /* t = y0 * y1 + t */
+ spe_fma(gen->f, tmp_reg, s1_reg, s2_reg, tmp_reg);
+
+ s1_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[0]);
+ s2_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[1]);
+ /* t = z0 * z1 + t */
+ spe_fma(gen->f, tmp_reg, s1_reg, s2_reg, tmp_reg);
+
+ s2_reg = get_src_reg(gen, CHAN_W, &inst->FullSrcRegisters[1]);
+ /* t = w1 + t */
+ spe_fa(gen->f, tmp_reg, s2_reg, tmp_reg);
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ int d_reg = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ spe_move(gen->f, d_reg, tmp_reg);
+ store_dest_reg(gen, tmp_reg, ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+/**
+ * Emit 3-component vector normalize.
+ */
+static boolean
+emit_NRM3(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch;
+ int src_reg[3];
+ int t0_reg = get_itemp(gen), t1_reg = get_itemp(gen);
+
+ src_reg[0] = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[0]);
+ src_reg[1] = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[0]);
+ src_reg[2] = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[0]);
+
+ /* t0 = x * x */
+ spe_fm(gen->f, t0_reg, src_reg[0], src_reg[0]);
+
+ /* t1 = y * y */
+ spe_fm(gen->f, t1_reg, src_reg[1], src_reg[1]);
+
+ /* t0 = z * z + t0 */
+ spe_fma(gen->f, t0_reg, src_reg[2], src_reg[2], t0_reg);
+
+ /* t0 = t0 + t1 */
+ spe_fa(gen->f, t0_reg, t0_reg, t1_reg);
+
+ /* t1 = 1.0 / sqrt(t0) */
+ spe_frsqest(gen->f, t1_reg, t0_reg);
+ spe_fi(gen->f, t1_reg, t0_reg, t1_reg);
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ int d_reg = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ /* dst = src[ch] * t1 */
+ spe_fm(gen->f, d_reg, src_reg[ch], t1_reg);
+ store_dest_reg(gen, d_reg, ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+/**
+ * Emit cross product. See emit_ADD for comments.
+ */
+static boolean
+emit_XPD(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int s1_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[0]);
+ int s2_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[1]);
+ int tmp_reg = get_itemp(gen);
+
+ /* t = z0 * y1 */
+ spe_fm(gen->f, tmp_reg, s1_reg, s2_reg);
+
+ s1_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[0]);
+ s2_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[1]);
+ /* t = y0 * z1 - t */
+ spe_fms(gen->f, tmp_reg, s1_reg, s2_reg, tmp_reg);
+
+ if (inst->FullDstRegisters[0].DstRegister.WriteMask & (1 << CHAN_X)) {
+ store_dest_reg(gen, tmp_reg, CHAN_X, &inst->FullDstRegisters[0]);
+ }
+
+ s1_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[0]);
+ s2_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[1]);
+ /* t = x0 * z1 */
+ spe_fm(gen->f, tmp_reg, s1_reg, s2_reg);
+
+ s1_reg = get_src_reg(gen, CHAN_Z, &inst->FullSrcRegisters[0]);
+ s2_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[1]);
+ /* t = z0 * x1 - t */
+ spe_fms(gen->f, tmp_reg, s1_reg, s2_reg, tmp_reg);
+
+ if (inst->FullDstRegisters[0].DstRegister.WriteMask & (1 << CHAN_Y)) {
+ store_dest_reg(gen, tmp_reg, CHAN_Y, &inst->FullDstRegisters[0]);
+ }
+
+ s1_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[0]);
+ s2_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[1]);
+ /* t = y0 * x1 */
+ spe_fm(gen->f, tmp_reg, s1_reg, s2_reg);
+
+ s1_reg = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[0]);
+ s2_reg = get_src_reg(gen, CHAN_Y, &inst->FullSrcRegisters[1]);
+ /* t = x0 * y1 - t */
+ spe_fms(gen->f, tmp_reg, s1_reg, s2_reg, tmp_reg);
+
+ if (inst->FullDstRegisters[0].DstRegister.WriteMask & (1 << CHAN_Z)) {
+ store_dest_reg(gen, tmp_reg, CHAN_Z, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+/**
+ * Emit inequality instruction.
+ * Note that the SPE fcgt instruction produces 0x0 and 0xffffffff as
+ * the result but OpenGL/TGSI needs 0.0 and 1.0 results.
+ * We can easily convert 0x0/0xffffffff to 0.0/1.0 with a bitwise AND.
+ */
+static boolean
+emit_inequality(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s1_reg[4], s2_reg[4], d_reg[4], one_reg;
+ bool complement = FALSE;
+
+ one_reg = get_const_one_reg(gen);
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ s2_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[1]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_SGT:
+ spe_fcgt(gen->f, d_reg[ch], s1_reg[ch], s2_reg[ch]);
+ break;
+ case TGSI_OPCODE_SLT:
+ spe_fcgt(gen->f, d_reg[ch], s2_reg[ch], s1_reg[ch]);
+ break;
+ case TGSI_OPCODE_SGE:
+ spe_fcgt(gen->f, d_reg[ch], s2_reg[ch], s1_reg[ch]);
+ complement = TRUE;
+ break;
+ case TGSI_OPCODE_SLE:
+ spe_fcgt(gen->f, d_reg[ch], s1_reg[ch], s2_reg[ch]);
+ complement = TRUE;
+ break;
+ case TGSI_OPCODE_SEQ:
+ spe_fceq(gen->f, d_reg[ch], s1_reg[ch], s2_reg[ch]);
+ break;
+ case TGSI_OPCODE_SNE:
+ spe_fceq(gen->f, d_reg[ch], s1_reg[ch], s2_reg[ch]);
+ complement = TRUE;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ /* convert d from 0x0/0xffffffff to 0.0/1.0 */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ /* d = d & one_reg */
+ if (complement)
+ spe_andc(gen->f, d_reg[ch], one_reg, d_reg[ch]);
+ else
+ spe_and(gen->f, d_reg[ch], one_reg, d_reg[ch]);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+/**
+ * Emit compare.
+ */
+static boolean
+emit_CMP(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch;
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ int s1_reg = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ int s2_reg = get_src_reg(gen, ch, &inst->FullSrcRegisters[1]);
+ int s3_reg = get_src_reg(gen, ch, &inst->FullSrcRegisters[2]);
+ int d_reg = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ int zero_reg = get_itemp(gen);
+
+ spe_zero(gen->f, zero_reg);
+
+ /* d = (s1 < 0) ? s2 : s3 */
+ spe_fcgt(gen->f, d_reg, zero_reg, s1_reg);
+ spe_selb(gen->f, d_reg, s3_reg, s2_reg, d_reg);
+
+ store_dest_reg(gen, d_reg, ch, &inst->FullDstRegisters[0]);
+ free_itemps(gen);
+ }
+
+ return TRUE;
+}
+
+/**
+ * Emit trunc.
+ * Convert float to signed int
+ * Convert signed int to float
+ */
+static boolean
+emit_TRUNC(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s1_reg[4], d_reg[4];
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ }
+
+ /* Convert float to int */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_cflts(gen->f, d_reg[ch], s1_reg[ch], 0);
+ }
+
+ /* Convert int to float */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_csflt(gen->f, d_reg[ch], d_reg[ch], 0);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+/**
+ * Emit floor.
+ * If negative int subtract one
+ * Convert float to signed int
+ * Convert signed int to float
+ */
+static boolean
+emit_FLR(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s1_reg[4], d_reg[4], tmp_reg[4], zero_reg, one_reg;
+
+ zero_reg = get_itemp(gen);
+ spe_zero(gen->f, zero_reg);
+ one_reg = get_const_one_reg(gen);
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ tmp_reg[ch] = get_itemp(gen);
+ }
+
+ /* If negative, subtract 1.0 */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_fcgt(gen->f, tmp_reg[ch], zero_reg, s1_reg[ch]);
+ }
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_selb(gen->f, tmp_reg[ch], zero_reg, one_reg, tmp_reg[ch]);
+ }
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_fs(gen->f, tmp_reg[ch], s1_reg[ch], tmp_reg[ch]);
+ }
+
+ /* Convert float to int */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_cflts(gen->f, tmp_reg[ch], tmp_reg[ch], 0);
+ }
+
+ /* Convert int to float */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_csflt(gen->f, d_reg[ch], tmp_reg[ch], 0);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+/**
+ * Compute frac = Input - FLR(Input)
+ */
+static boolean
+emit_FRC(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s1_reg[4], d_reg[4], tmp_reg[4], zero_reg, one_reg;
+
+ zero_reg = get_itemp(gen);
+ spe_zero(gen->f, zero_reg);
+ one_reg = get_const_one_reg(gen);
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ tmp_reg[ch] = get_itemp(gen);
+ }
+
+ /* If negative, subtract 1.0 */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_fcgt(gen->f, tmp_reg[ch], zero_reg, s1_reg[ch]);
+ }
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_selb(gen->f, tmp_reg[ch], zero_reg, one_reg, tmp_reg[ch]);
+ }
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_fs(gen->f, tmp_reg[ch], s1_reg[ch], tmp_reg[ch]);
+ }
+
+ /* Convert float to int */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_cflts(gen->f, tmp_reg[ch], tmp_reg[ch], 0);
+ }
+
+ /* Convert int to float */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_csflt(gen->f, tmp_reg[ch], tmp_reg[ch], 0);
+ }
+
+ /* d = s1 - FLR(s1) */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_fs(gen->f, d_reg[ch], s1_reg[ch], tmp_reg[ch]);
+ }
+
+ /* store result */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+#if 0
+static void
+print_functions(struct cell_context *cell)
+{
+ struct cell_spu_function_info *funcs = &cell->spu_functions;
+ uint i;
+ for (i = 0; i < funcs->num; i++) {
+ printf("SPU func %u: %s at %u\n",
+ i, funcs->names[i], funcs->addrs[i]);
+ }
+}
+#endif
+
+
+static uint
+lookup_function(struct cell_context *cell, const char *funcname)
+{
+ const struct cell_spu_function_info *funcs = &cell->spu_functions;
+ uint i, addr = 0;
+ for (i = 0; i < funcs->num; i++) {
+ if (strcmp(funcs->names[i], funcname) == 0) {
+ addr = funcs->addrs[i];
+ }
+ }
+ assert(addr && "spu function not found");
+ return addr / 4; /* discard 2 least significant bits */
+}
+
+
+/**
+ * Emit code to call a SPU function.
+ * Used to implement instructions like SIN/COS/POW/TEX/etc.
+ * If scalar, only the X components of the src regs are used, and the
+ * result is replicated across the dest register's XYZW components.
+ */
+static boolean
+emit_function_call(struct codegen *gen,
+ const struct tgsi_full_instruction *inst,
+ char *funcname, uint num_args, boolean scalar)
+{
+ const uint addr = lookup_function(gen->cell, funcname);
+ char comment[100];
+ int s_regs[3];
+ int func_called = FALSE;
+ uint a, ch;
+ int retval_reg = -1;
+
+ assert(num_args <= 3);
+
+ snprintf(comment, sizeof(comment), "CALL %s:", funcname);
+ spe_comment(gen->f, -4, comment);
+
+ if (scalar) {
+ for (a = 0; a < num_args; a++) {
+ s_regs[a] = get_src_reg(gen, CHAN_X, &inst->FullSrcRegisters[a]);
+ }
+ /* we'll call the function, put the return value in this register,
+ * then replicate it across all write-enabled components in d_reg.
+ */
+ retval_reg = spe_allocate_available_register(gen->f);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ int d_reg;
+ ubyte usedRegs[SPE_NUM_REGS];
+ uint i, numUsed;
+
+ if (!scalar) {
+ for (a = 0; a < num_args; a++) {
+ s_regs[a] = get_src_reg(gen, ch, &inst->FullSrcRegisters[a]);
+ }
+ }
+
+ d_reg = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+
+ if (!scalar || !func_called) {
+ /* for a scalar function, we'll really only call the function once */
+
+ numUsed = spe_get_registers_used(gen->f, usedRegs);
+ assert(numUsed < gen->frame_size / 16 - 2);
+
+ /* save registers to stack */
+ for (i = 0; i < numUsed; i++) {
+ uint reg = usedRegs[i];
+ int offset = 2 + i;
+ spe_stqd(gen->f, reg, SPE_REG_SP, 16 * offset);
+ }
+
+ /* setup function arguments */
+ for (a = 0; a < num_args; a++) {
+ spe_move(gen->f, 3 + a, s_regs[a]);
+ }
+
+ /* branch to function, save return addr */
+ spe_brasl(gen->f, SPE_REG_RA, addr);
+
+ /* save function's return value */
+ if (scalar)
+ spe_move(gen->f, retval_reg, 3);
+ else
+ spe_move(gen->f, d_reg, 3);
+
+ /* restore registers from stack */
+ for (i = 0; i < numUsed; i++) {
+ uint reg = usedRegs[i];
+ if (reg != d_reg && reg != retval_reg) {
+ int offset = 2 + i;
+ spe_lqd(gen->f, reg, SPE_REG_SP, 16 * offset);
+ }
+ }
+
+ func_called = TRUE;
+ }
+
+ if (scalar) {
+ spe_move(gen->f, d_reg, retval_reg);
+ }
+
+ store_dest_reg(gen, d_reg, ch, &inst->FullDstRegisters[0]);
+ free_itemps(gen);
+ }
+
+ if (scalar) {
+ spe_release_register(gen->f, retval_reg);
+ }
+
+ return TRUE;
+}
+
+
+static boolean
+emit_TEX(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ const uint target = inst->InstructionExtTexture.Texture;
+ const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
+ uint addr;
+ int ch;
+ int coord_regs[4], d_regs[4];
+
+ switch (target) {
+ case TGSI_TEXTURE_1D:
+ case TGSI_TEXTURE_2D:
+ addr = lookup_function(gen->cell, "spu_tex_2d");
+ break;
+ case TGSI_TEXTURE_3D:
+ addr = lookup_function(gen->cell, "spu_tex_3d");
+ break;
+ case TGSI_TEXTURE_CUBE:
+ addr = lookup_function(gen->cell, "spu_tex_cube");
+ break;
+ default:
+ ASSERT(0 && "unsupported texture target");
+ return FALSE;
+ }
+
+ assert(inst->FullSrcRegisters[1].SrcRegister.File == TGSI_FILE_SAMPLER);
+
+ spe_comment(gen->f, -4, "CALL tex:");
+
+ /* get src/dst reg info */
+ for (ch = 0; ch < 4; ch++) {
+ coord_regs[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ d_regs[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ }
+
+ {
+ ubyte usedRegs[SPE_NUM_REGS];
+ uint i, numUsed;
+
+ numUsed = spe_get_registers_used(gen->f, usedRegs);
+ assert(numUsed < gen->frame_size / 16 - 2);
+
+ /* save registers to stack */
+ for (i = 0; i < numUsed; i++) {
+ uint reg = usedRegs[i];
+ int offset = 2 + i;
+ spe_stqd(gen->f, reg, SPE_REG_SP, 16 * offset);
+ }
+
+ /* setup function arguments (XXX depends on target) */
+ for (i = 0; i < 4; i++) {
+ spe_move(gen->f, 3 + i, coord_regs[i]);
+ }
+ spe_load_uint(gen->f, 7, unit); /* sampler unit */
+
+ /* branch to function, save return addr */
+ spe_brasl(gen->f, SPE_REG_RA, addr);
+
+ /* save function's return values (four pixel's colors) */
+ for (i = 0; i < 4; i++) {
+ spe_move(gen->f, d_regs[i], 3 + i);
+ }
+
+ /* restore registers from stack */
+ for (i = 0; i < numUsed; i++) {
+ uint reg = usedRegs[i];
+ if (reg != d_regs[0] &&
+ reg != d_regs[1] &&
+ reg != d_regs[2] &&
+ reg != d_regs[3]) {
+ int offset = 2 + i;
+ spe_lqd(gen->f, reg, SPE_REG_SP, 16 * offset);
+ }
+ }
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_regs[ch], ch, &inst->FullDstRegisters[0]);
+ free_itemps(gen);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * KILL if any of src reg values are less than zero.
+ */
+static boolean
+emit_KIL(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch;
+ int s_regs[4], kil_reg = -1, cmp_reg, zero_reg;
+
+ spe_comment(gen->f, -4, "CALL kil:");
+
+ /* zero = {0,0,0,0} */
+ zero_reg = get_itemp(gen);
+ spe_zero(gen->f, zero_reg);
+
+ cmp_reg = get_itemp(gen);
+
+ /* get src regs */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s_regs[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ }
+
+ /* test if any src regs are < 0 */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ if (kil_reg >= 0) {
+ /* cmp = 0 > src ? : ~0 : 0 */
+ spe_fcgt(gen->f, cmp_reg, zero_reg, s_regs[ch]);
+ /* kil = kil | cmp */
+ spe_or(gen->f, kil_reg, kil_reg, cmp_reg);
+ }
+ else {
+ kil_reg = get_itemp(gen);
+ /* kil = 0 > src ? : ~0 : 0 */
+ spe_fcgt(gen->f, kil_reg, zero_reg, s_regs[ch]);
+ }
+ }
+
+ if (gen->if_nesting || gen->loop_nesting) {
+ /* may have been a conditional kil */
+ spe_and(gen->f, kil_reg, kil_reg, gen->exec_mask_reg);
+ }
+
+ /* allocate the kill mask reg if needed */
+ if (gen->kill_mask_reg <= 0) {
+ gen->kill_mask_reg = spe_allocate_available_register(gen->f);
+ spe_move(gen->f, gen->kill_mask_reg, kil_reg);
+ }
+ else {
+ spe_or(gen->f, gen->kill_mask_reg, gen->kill_mask_reg, kil_reg);
+ }
+
+ free_itemps(gen);
+
+ return TRUE;
+}
+
+
+
+/**
+ * Emit min or max.
+ */
+static boolean
+emit_MIN_MAX(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int ch, s0_reg[4], s1_reg[4], d_reg[4], tmp_reg[4];
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ s0_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ s1_reg[ch] = get_src_reg(gen, ch, &inst->FullSrcRegisters[1]);
+ d_reg[ch] = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+ tmp_reg[ch] = get_itemp(gen);
+ }
+
+ /* d = (s0 > s1) ? s0 : s1 */
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ if (inst->Instruction.Opcode == TGSI_OPCODE_MAX)
+ spe_fcgt(gen->f, tmp_reg[ch], s0_reg[ch], s1_reg[ch]);
+ else
+ spe_fcgt(gen->f, tmp_reg[ch], s1_reg[ch], s0_reg[ch]);
+ }
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ spe_selb(gen->f, d_reg[ch], s1_reg[ch], s0_reg[ch], tmp_reg[ch]);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ store_dest_reg(gen, d_reg[ch], ch, &inst->FullDstRegisters[0]);
+ }
+
+ free_itemps(gen);
+ return TRUE;
+}
+
+
+/**
+ * Emit code to update the execution mask.
+ * This needs to be done whenever the execution status of a conditional
+ * or loop is changed.
+ */
+static void
+emit_update_exec_mask(struct codegen *gen)
+{
+ const int exec_reg = get_exec_mask_reg(gen);
+ const int cond_reg = gen->cond_mask_reg;
+ const int loop_reg = gen->loop_mask_reg;
+
+ spe_comment(gen->f, 0, "Update master execution mask");
+
+ if (gen->if_nesting > 0 && gen->loop_nesting > 0) {
+ /* exec_mask = cond_mask & loop_mask */
+ assert(cond_reg > 0);
+ assert(loop_reg > 0);
+ spe_and(gen->f, exec_reg, cond_reg, loop_reg);
+ }
+ else if (gen->if_nesting > 0) {
+ assert(cond_reg > 0);
+ spe_move(gen->f, exec_reg, cond_reg);
+ }
+ else if (gen->loop_nesting > 0) {
+ assert(loop_reg > 0);
+ spe_move(gen->f, exec_reg, loop_reg);
+ }
+ else {
+ spe_load_int(gen->f, exec_reg, ~0x0);
+ }
+}
+
+
+static boolean
+emit_IF(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ const int channel = 0;
+ int cond_reg;
+
+ cond_reg = get_cond_mask_reg(gen);
+
+ /* XXX push cond exec mask */
+
+ spe_comment(gen->f, 0, "init conditional exec mask = ~0:");
+ spe_load_int(gen->f, cond_reg, ~0);
+
+ /* update conditional execution mask with the predicate register */
+ int tmp_reg = get_itemp(gen);
+ int s1_reg = get_src_reg(gen, channel, &inst->FullSrcRegisters[0]);
+
+ /* tmp = (s1_reg == 0) */
+ spe_ceqi(gen->f, tmp_reg, s1_reg, 0);
+ /* tmp = !tmp */
+ spe_complement(gen->f, tmp_reg, tmp_reg);
+ /* cond_mask = cond_mask & tmp */
+ spe_and(gen->f, cond_reg, cond_reg, tmp_reg);
+
+ gen->if_nesting++;
+
+ /* update the master execution mask */
+ emit_update_exec_mask(gen);
+
+ free_itemps(gen);
+
+ return TRUE;
+}
+
+
+static boolean
+emit_ELSE(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ const int cond_reg = get_cond_mask_reg(gen);
+
+ spe_comment(gen->f, 0, "cond exec mask = !cond exec mask");
+ spe_complement(gen->f, cond_reg, cond_reg);
+ emit_update_exec_mask(gen);
+
+ return TRUE;
+}
+
+
+static boolean
+emit_ENDIF(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ /* XXX todo: pop cond exec mask */
+
+ gen->if_nesting--;
+
+ emit_update_exec_mask(gen);
+
+ return TRUE;
+}
+
+
+static boolean
+emit_BGNLOOP(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ int exec_reg, loop_reg;
+
+ exec_reg = get_exec_mask_reg(gen);
+ loop_reg = get_loop_mask_reg(gen);
+
+ /* XXX push loop_exec mask */
+
+ spe_comment(gen->f, 0*-4, "initialize loop exec mask = ~0");
+ spe_load_int(gen->f, loop_reg, ~0x0);
+
+ gen->loop_nesting++;
+ gen->loop_start = spe_code_size(gen->f); /* in bytes */
+
+ return TRUE;
+}
+
+
+static boolean
+emit_ENDLOOP(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ const int loop_reg = get_loop_mask_reg(gen);
+ const int tmp_reg = get_itemp(gen);
+ int offset;
+
+ /* tmp_reg = exec[0] | exec[1] | exec[2] | exec[3] */
+ spe_orx(gen->f, tmp_reg, loop_reg);
+
+ offset = gen->loop_start - spe_code_size(gen->f); /* in bytes */
+
+ /* branch back to top of loop if tmp_reg != 0 */
+ spe_brnz(gen->f, tmp_reg, offset / 4);
+
+ /* XXX pop loop_exec mask */
+
+ gen->loop_nesting--;
+
+ emit_update_exec_mask(gen);
+
+ return TRUE;
+}
+
+
+static boolean
+emit_BRK(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ const int exec_reg = get_exec_mask_reg(gen);
+ const int loop_reg = get_loop_mask_reg(gen);
+
+ assert(gen->loop_nesting > 0);
+
+ spe_comment(gen->f, 0, "loop exec mask &= ~master exec mask");
+ spe_andc(gen->f, loop_reg, loop_reg, exec_reg);
+
+ emit_update_exec_mask(gen);
+
+ return TRUE;
+}
+
+
+static boolean
+emit_CONT(struct codegen *gen, const struct tgsi_full_instruction *inst)
+{
+ assert(gen->loop_nesting > 0);
+
+ return TRUE;
+}
+
+
+static boolean
+emit_DDX_DDY(struct codegen *gen, const struct tgsi_full_instruction *inst,
+ boolean ddx)
+{
+ int ch;
+
+ FOR_EACH_ENABLED_CHANNEL(inst, ch) {
+ int s_reg = get_src_reg(gen, ch, &inst->FullSrcRegisters[0]);
+ int d_reg = get_dst_reg(gen, ch, &inst->FullDstRegisters[0]);
+
+ int t1_reg = get_itemp(gen);
+ int t2_reg = get_itemp(gen);
+
+ spe_splat_word(gen->f, t1_reg, s_reg, 0); /* upper-left pixel */
+ if (ddx) {
+ spe_splat_word(gen->f, t2_reg, s_reg, 1); /* upper-right pixel */
+ }
+ else {
+ spe_splat_word(gen->f, t2_reg, s_reg, 2); /* lower-left pixel */
+ }
+ spe_fs(gen->f, d_reg, t2_reg, t1_reg);
+
+ free_itemps(gen);
+ }
+
+ return TRUE;
+}
+
+
+
+
+/**
+ * Emit END instruction.
+ * We just return from the shader function at this point.
+ *
+ * Note that there may be more code after this that would be
+ * called by TGSI_OPCODE_CALL.
+ */
+static boolean
+emit_END(struct codegen *gen)
+{
+ emit_epilogue(gen);
+ return TRUE;
+}
+
+
+/**
+ * Emit code for the given instruction. Just a big switch stmt.
+ */
+static boolean
+emit_instruction(struct codegen *gen,
+ const struct tgsi_full_instruction *inst)
+{
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ARL:
+ return emit_ARL(gen, inst);
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ return emit_MOV(gen, inst);
+ case TGSI_OPCODE_ADD:
+ case TGSI_OPCODE_SUB:
+ case TGSI_OPCODE_MUL:
+ return emit_binop(gen, inst);
+ case TGSI_OPCODE_MAD:
+ return emit_MAD(gen, inst);
+ case TGSI_OPCODE_LERP:
+ return emit_LRP(gen, inst);
+ case TGSI_OPCODE_DP3:
+ return emit_DP3(gen, inst);
+ case TGSI_OPCODE_DP4:
+ return emit_DP4(gen, inst);
+ case TGSI_OPCODE_DPH:
+ return emit_DPH(gen, inst);
+ case TGSI_OPCODE_NRM:
+ return emit_NRM3(gen, inst);
+ case TGSI_OPCODE_XPD:
+ return emit_XPD(gen, inst);
+ case TGSI_OPCODE_RCP:
+ case TGSI_OPCODE_RSQ:
+ return emit_RCP_RSQ(gen, inst);
+ case TGSI_OPCODE_ABS:
+ return emit_ABS(gen, inst);
+ case TGSI_OPCODE_SGT:
+ case TGSI_OPCODE_SLT:
+ case TGSI_OPCODE_SGE:
+ case TGSI_OPCODE_SLE:
+ case TGSI_OPCODE_SEQ:
+ case TGSI_OPCODE_SNE:
+ return emit_inequality(gen, inst);
+ case TGSI_OPCODE_CMP:
+ return emit_CMP(gen, inst);
+ case TGSI_OPCODE_MIN:
+ case TGSI_OPCODE_MAX:
+ return emit_MIN_MAX(gen, inst);
+ case TGSI_OPCODE_TRUNC:
+ return emit_TRUNC(gen, inst);
+ case TGSI_OPCODE_FLR:
+ return emit_FLR(gen, inst);
+ case TGSI_OPCODE_FRC:
+ return emit_FRC(gen, inst);
+ case TGSI_OPCODE_END:
+ return emit_END(gen);
+
+ case TGSI_OPCODE_COS:
+ return emit_function_call(gen, inst, "spu_cos", 1, TRUE);
+ case TGSI_OPCODE_SIN:
+ return emit_function_call(gen, inst, "spu_sin", 1, TRUE);
+ case TGSI_OPCODE_POW:
+ return emit_function_call(gen, inst, "spu_pow", 2, TRUE);
+ case TGSI_OPCODE_EX2:
+ return emit_function_call(gen, inst, "spu_exp2", 1, TRUE);
+ case TGSI_OPCODE_LG2:
+ return emit_function_call(gen, inst, "spu_log2", 1, TRUE);
+ case TGSI_OPCODE_TEX:
+ /* fall-through for now */
+ case TGSI_OPCODE_TXD:
+ /* fall-through for now */
+ case TGSI_OPCODE_TXB:
+ /* fall-through for now */
+ case TGSI_OPCODE_TXL:
+ /* fall-through for now */
+ case TGSI_OPCODE_TXP:
+ return emit_TEX(gen, inst);
+ case TGSI_OPCODE_KIL:
+ return emit_KIL(gen, inst);
+
+ case TGSI_OPCODE_IF:
+ return emit_IF(gen, inst);
+ case TGSI_OPCODE_ELSE:
+ return emit_ELSE(gen, inst);
+ case TGSI_OPCODE_ENDIF:
+ return emit_ENDIF(gen, inst);
+
+ case TGSI_OPCODE_BGNLOOP:
+ return emit_BGNLOOP(gen, inst);
+ case TGSI_OPCODE_ENDLOOP:
+ return emit_ENDLOOP(gen, inst);
+ case TGSI_OPCODE_BRK:
+ return emit_BRK(gen, inst);
+ case TGSI_OPCODE_CONT:
+ return emit_CONT(gen, inst);
+
+ case TGSI_OPCODE_DDX:
+ return emit_DDX_DDY(gen, inst, TRUE);
+ case TGSI_OPCODE_DDY:
+ return emit_DDX_DDY(gen, inst, FALSE);
+
+ /* XXX lots more cases to do... */
+
+ default:
+ fprintf(stderr, "Cell: unimplemented TGSI instruction %d!\n",
+ inst->Instruction.Opcode);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+/**
+ * Emit code for a TGSI immediate value (vector of four floats).
+ * This involves register allocation and initialization.
+ * XXX the initialization should be done by a "prepare" stage, not
+ * per quad execution!
+ */
+static boolean
+emit_immediate(struct codegen *gen, const struct tgsi_full_immediate *immed)
+{
+ int ch;
+
+ assert(gen->num_imm < MAX_TEMPS);
+
+ for (ch = 0; ch < 4; ch++) {
+ float val = immed->u[ch].Float;
+
+ if (ch > 0 && val == immed->u[ch - 1].Float) {
+ /* re-use previous register */
+ gen->imm_regs[gen->num_imm][ch] = gen->imm_regs[gen->num_imm][ch - 1];
+ }
+ else {
+ char str[100];
+ int reg = spe_allocate_available_register(gen->f);
+
+ if (reg < 0)
+ return FALSE;
+
+ sprintf(str, "init $%d = %f", reg, val);
+ spe_comment(gen->f, 0, str);
+
+ /* update immediate map */
+ gen->imm_regs[gen->num_imm][ch] = reg;
+
+ /* emit initializer instruction */
+ spe_load_float(gen->f, reg, val);
+ }
+ }
+
+ gen->num_imm++;
+
+ return TRUE;
+}
+
+
+
+/**
+ * Emit "code" for a TGSI declaration.
+ * We only care about TGSI TEMPORARY register declarations at this time.
+ * For each TGSI TEMPORARY we allocate four SPE registers.
+ */
+static boolean
+emit_declaration(struct cell_context *cell,
+ struct codegen *gen, const struct tgsi_full_declaration *decl)
+{
+ int i, ch;
+
+ switch (decl->Declaration.File) {
+ case TGSI_FILE_TEMPORARY:
+ for (i = decl->DeclarationRange.First;
+ i <= decl->DeclarationRange.Last;
+ i++) {
+ assert(i < MAX_TEMPS);
+ for (ch = 0; ch < 4; ch++) {
+ gen->temp_regs[i][ch] = spe_allocate_available_register(gen->f);
+ if (gen->temp_regs[i][ch] < 0)
+ return FALSE; /* out of regs */
+ }
+
+ /* XXX if we run out of SPE registers, we need to spill
+ * to SPU memory. someday...
+ */
+
+ {
+ char buf[100];
+ sprintf(buf, "TGSI temp[%d] maps to SPU regs [$%d $%d $%d $%d]", i,
+ gen->temp_regs[i][0], gen->temp_regs[i][1],
+ gen->temp_regs[i][2], gen->temp_regs[i][3]);
+ spe_comment(gen->f, 0, buf);
+ }
+ }
+ break;
+ default:
+ ; /* ignore */
+ }
+
+ return TRUE;
+}
+
+
+
+/**
+ * Translate TGSI shader code to SPE instructions. This is done when
+ * the state tracker gives us a new shader (via pipe->create_fs_state()).
+ *
+ * \param cell the rendering context (in)
+ * \param tokens the TGSI shader (in)
+ * \param f the generated function (out)
+ */
+boolean
+cell_gen_fragment_program(struct cell_context *cell,
+ const struct tgsi_token *tokens,
+ struct spe_function *f)
+{
+ struct tgsi_parse_context parse;
+ struct codegen gen;
+ uint ic = 0;
+
+ memset(&gen, 0, sizeof(gen));
+ gen.cell = cell;
+ gen.f = f;
+
+ /* For SPE function calls: reg $3 = first param, $4 = second param, etc. */
+ gen.inputs_reg = 3; /* pointer to inputs array */
+ gen.outputs_reg = 4; /* pointer to outputs array */
+ gen.constants_reg = 5; /* pointer to constants array */
+
+ spe_init_func(f, SPU_MAX_FRAGMENT_PROGRAM_INSTS * SPE_INST_SIZE);
+ spe_allocate_register(f, gen.inputs_reg);
+ spe_allocate_register(f, gen.outputs_reg);
+ spe_allocate_register(f, gen.constants_reg);
+
+ if (cell->debug_flags & CELL_DEBUG_ASM) {
+ spe_print_code(f, TRUE);
+ spe_indent(f, 2*8);
+ printf("Begin %s\n", __FUNCTION__);
+ tgsi_dump(tokens, 0);
+ }
+
+ tgsi_parse_init(&parse, tokens);
+
+ emit_prologue(&gen);
+
+ while (!tgsi_parse_end_of_tokens(&parse) && !gen.error) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ if (f->print) {
+ _debug_printf(" # ");
+ tgsi_dump_immediate(&parse.FullToken.FullImmediate);
+ }
+ if (!emit_immediate(&gen, &parse.FullToken.FullImmediate))
+ gen.error = TRUE;
+ break;
+
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ if (f->print) {
+ _debug_printf(" # ");
+ tgsi_dump_declaration(&parse.FullToken.FullDeclaration);
+ }
+ if (!emit_declaration(cell, &gen, &parse.FullToken.FullDeclaration))
+ gen.error = TRUE;
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (f->print) {
+ _debug_printf(" # ");
+ ic++;
+ tgsi_dump_instruction(&parse.FullToken.FullInstruction, ic);
+ }
+ if (!emit_instruction(&gen, &parse.FullToken.FullInstruction))
+ gen.error = TRUE;
+ break;
+
+ default:
+ assert(0);
+ }
+ }
+
+ if (gen.error) {
+ /* terminate the SPE code */
+ return emit_END(&gen);
+ }
+
+ if (cell->debug_flags & CELL_DEBUG_ASM) {
+ printf("cell_gen_fragment_program nr instructions: %d\n", f->num_inst);
+ printf("End %s\n", __FUNCTION__);
+ }
+
+ tgsi_parse_free( &parse );
+
+ return !gen.error;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fp.h b/src/gallium/drivers/cell/ppu/cell_gen_fp.h
new file mode 100644
index 0000000000..99faea7046
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_gen_fp.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+
+#ifndef CELL_GEN_FP_H
+#define CELL_GEN_FP_H
+
+
+
+extern boolean
+cell_gen_fragment_program(struct cell_context *cell,
+ const struct tgsi_token *tokens,
+ struct spe_function *f);
+
+
+#endif /* CELL_GEN_FP_H */
+
diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c
new file mode 100644
index 0000000000..66d4b3b6a3
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c
@@ -0,0 +1,2181 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Generate SPU per-fragment code (actually per-quad code).
+ * \author Brian Paul
+ * \author Bob Ellison
+ */
+
+
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "rtasm/rtasm_ppc_spe.h"
+#include "cell_context.h"
+#include "cell_gen_fragment.h"
+
+
+
+/** Do extra optimizations? */
+#define OPTIMIZATIONS 1
+
+
+/**
+ * Generate SPE code to perform Z/depth testing.
+ *
+ * \param dsa Gallium depth/stencil/alpha state to gen code for
+ * \param f SPE function to append instruction onto.
+ * \param mask_reg register containing quad/pixel "alive" mask (in/out)
+ * \param ifragZ_reg register containing integer fragment Z values (in)
+ * \param ifbZ_reg register containing integer frame buffer Z values (in/out)
+ * \param zmask_reg register containing result of Z test/comparison (out)
+ *
+ * Returns TRUE if the Z-buffer needs to be updated.
+ */
+static boolean
+gen_depth_test(struct spe_function *f,
+ const struct pipe_depth_stencil_alpha_state *dsa,
+ int mask_reg, int ifragZ_reg, int ifbZ_reg, int zmask_reg)
+{
+ /* NOTE: we use clgt below, not cgt, because we want to compare _unsigned_
+ * quantities. This only makes a difference for 32-bit Z values though.
+ */
+ ASSERT(dsa->depth.enabled);
+
+ switch (dsa->depth.func) {
+ case PIPE_FUNC_EQUAL:
+ /* zmask = (ifragZ == ref) */
+ spe_ceq(f, zmask_reg, ifragZ_reg, ifbZ_reg);
+ /* mask = (mask & zmask) */
+ spe_and(f, mask_reg, mask_reg, zmask_reg);
+ break;
+
+ case PIPE_FUNC_NOTEQUAL:
+ /* zmask = (ifragZ == ref) */
+ spe_ceq(f, zmask_reg, ifragZ_reg, ifbZ_reg);
+ /* mask = (mask & ~zmask) */
+ spe_andc(f, mask_reg, mask_reg, zmask_reg);
+ break;
+
+ case PIPE_FUNC_GREATER:
+ /* zmask = (ifragZ > ref) */
+ spe_clgt(f, zmask_reg, ifragZ_reg, ifbZ_reg);
+ /* mask = (mask & zmask) */
+ spe_and(f, mask_reg, mask_reg, zmask_reg);
+ break;
+
+ case PIPE_FUNC_LESS:
+ /* zmask = (ref > ifragZ) */
+ spe_clgt(f, zmask_reg, ifbZ_reg, ifragZ_reg);
+ /* mask = (mask & zmask) */
+ spe_and(f, mask_reg, mask_reg, zmask_reg);
+ break;
+
+ case PIPE_FUNC_LEQUAL:
+ /* zmask = (ifragZ > ref) */
+ spe_clgt(f, zmask_reg, ifragZ_reg, ifbZ_reg);
+ /* mask = (mask & ~zmask) */
+ spe_andc(f, mask_reg, mask_reg, zmask_reg);
+ break;
+
+ case PIPE_FUNC_GEQUAL:
+ /* zmask = (ref > ifragZ) */
+ spe_clgt(f, zmask_reg, ifbZ_reg, ifragZ_reg);
+ /* mask = (mask & ~zmask) */
+ spe_andc(f, mask_reg, mask_reg, zmask_reg);
+ break;
+
+ case PIPE_FUNC_NEVER:
+ spe_il(f, mask_reg, 0); /* mask = {0,0,0,0} */
+ spe_move(f, zmask_reg, mask_reg); /* zmask = mask */
+ break;
+
+ case PIPE_FUNC_ALWAYS:
+ /* mask unchanged */
+ spe_il(f, zmask_reg, ~0); /* zmask = {~0,~0,~0,~0} */
+ break;
+
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ if (dsa->depth.writemask) {
+ /*
+ * If (ztest passed) {
+ * framebufferZ = fragmentZ;
+ * }
+ * OR,
+ * framebufferZ = (ztest_passed ? fragmentZ : framebufferZ;
+ */
+ spe_selb(f, ifbZ_reg, ifbZ_reg, ifragZ_reg, mask_reg);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * Generate SPE code to perform alpha testing.
+ *
+ * \param dsa Gallium depth/stencil/alpha state to gen code for
+ * \param f SPE function to append instruction onto.
+ * \param mask_reg register containing quad/pixel "alive" mask (in/out)
+ * \param fragA_reg register containing four fragment alpha values (in)
+ */
+static void
+gen_alpha_test(const struct pipe_depth_stencil_alpha_state *dsa,
+ struct spe_function *f, int mask_reg, int fragA_reg)
+{
+ int ref_reg = spe_allocate_available_register(f);
+ int amask_reg = spe_allocate_available_register(f);
+
+ ASSERT(dsa->alpha.enabled);
+
+ if ((dsa->alpha.func != PIPE_FUNC_NEVER) &&
+ (dsa->alpha.func != PIPE_FUNC_ALWAYS)) {
+ /* load/splat the alpha reference float value */
+ spe_load_float(f, ref_reg, dsa->alpha.ref_value);
+ }
+
+ /* emit code to do the alpha comparison, updating 'mask' */
+ switch (dsa->alpha.func) {
+ case PIPE_FUNC_EQUAL:
+ /* amask = (fragA == ref) */
+ spe_fceq(f, amask_reg, fragA_reg, ref_reg);
+ /* mask = (mask & amask) */
+ spe_and(f, mask_reg, mask_reg, amask_reg);
+ break;
+
+ case PIPE_FUNC_NOTEQUAL:
+ /* amask = (fragA == ref) */
+ spe_fceq(f, amask_reg, fragA_reg, ref_reg);
+ /* mask = (mask & ~amask) */
+ spe_andc(f, mask_reg, mask_reg, amask_reg);
+ break;
+
+ case PIPE_FUNC_GREATER:
+ /* amask = (fragA > ref) */
+ spe_fcgt(f, amask_reg, fragA_reg, ref_reg);
+ /* mask = (mask & amask) */
+ spe_and(f, mask_reg, mask_reg, amask_reg);
+ break;
+
+ case PIPE_FUNC_LESS:
+ /* amask = (ref > fragA) */
+ spe_fcgt(f, amask_reg, ref_reg, fragA_reg);
+ /* mask = (mask & amask) */
+ spe_and(f, mask_reg, mask_reg, amask_reg);
+ break;
+
+ case PIPE_FUNC_LEQUAL:
+ /* amask = (fragA > ref) */
+ spe_fcgt(f, amask_reg, fragA_reg, ref_reg);
+ /* mask = (mask & ~amask) */
+ spe_andc(f, mask_reg, mask_reg, amask_reg);
+ break;
+
+ case PIPE_FUNC_GEQUAL:
+ /* amask = (ref > fragA) */
+ spe_fcgt(f, amask_reg, ref_reg, fragA_reg);
+ /* mask = (mask & ~amask) */
+ spe_andc(f, mask_reg, mask_reg, amask_reg);
+ break;
+
+ case PIPE_FUNC_NEVER:
+ spe_il(f, mask_reg, 0); /* mask = [0,0,0,0] */
+ break;
+
+ case PIPE_FUNC_ALWAYS:
+ /* no-op, mask unchanged */
+ break;
+
+ default:
+ ASSERT(0);
+ break;
+ }
+
+#if OPTIMIZATIONS
+ /* if mask == {0,0,0,0} we're all done, return */
+ {
+ /* re-use amask reg here */
+ int tmp_reg = amask_reg;
+ /* tmp[0] = (mask[0] | mask[1] | mask[2] | mask[3]) */
+ spe_orx(f, tmp_reg, mask_reg);
+ /* if tmp[0] == 0 then return from function call */
+ spe_biz(f, tmp_reg, SPE_REG_RA, 0, 0);
+ }
+#endif
+
+ spe_release_register(f, ref_reg);
+ spe_release_register(f, amask_reg);
+}
+
+
+/**
+ * This pair of functions is used inline to allocate and deallocate
+ * optional constant registers. Once a constant is discovered to be
+ * needed, we will likely need it again, so we don't want to deallocate
+ * it and have to allocate and load it again unnecessarily.
+ */
+static INLINE void
+setup_optional_register(struct spe_function *f,
+ int *r)
+{
+ if (*r < 0)
+ *r = spe_allocate_available_register(f);
+}
+
+static INLINE void
+release_optional_register(struct spe_function *f,
+ int r)
+{
+ if (r >= 0)
+ spe_release_register(f, r);
+}
+
+static INLINE void
+setup_const_register(struct spe_function *f,
+ int *r,
+ float value)
+{
+ if (*r >= 0)
+ return;
+ setup_optional_register(f, r);
+ spe_load_float(f, *r, value);
+}
+
+static INLINE void
+release_const_register(struct spe_function *f,
+ int r)
+{
+ release_optional_register(f, r);
+}
+
+
+
+/**
+ * Unpack/convert framebuffer colors from four 32-bit packed colors
+ * (fbRGBA) to four float RGBA vectors (fbR, fbG, fbB, fbA).
+ * Each 8-bit color component is expanded into a float in [0.0, 1.0].
+ */
+static void
+unpack_colors(struct spe_function *f,
+ enum pipe_format color_format,
+ int fbRGBA_reg,
+ int fbR_reg, int fbG_reg, int fbB_reg, int fbA_reg)
+{
+ int mask0_reg = spe_allocate_available_register(f);
+ int mask1_reg = spe_allocate_available_register(f);
+ int mask2_reg = spe_allocate_available_register(f);
+ int mask3_reg = spe_allocate_available_register(f);
+
+ spe_load_int(f, mask0_reg, 0xff);
+ spe_load_int(f, mask1_reg, 0xff00);
+ spe_load_int(f, mask2_reg, 0xff0000);
+ spe_load_int(f, mask3_reg, 0xff000000);
+
+ spe_comment(f, 0, "Unpack framebuffer colors, convert to floats");
+
+ switch (color_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ /* fbB = fbRGBA & mask */
+ spe_and(f, fbB_reg, fbRGBA_reg, mask0_reg);
+
+ /* fbG = fbRGBA & mask */
+ spe_and(f, fbG_reg, fbRGBA_reg, mask1_reg);
+
+ /* fbR = fbRGBA & mask */
+ spe_and(f, fbR_reg, fbRGBA_reg, mask2_reg);
+
+ /* fbA = fbRGBA & mask */
+ spe_and(f, fbA_reg, fbRGBA_reg, mask3_reg);
+
+ /* fbG = fbG >> 8 */
+ spe_roti(f, fbG_reg, fbG_reg, -8);
+
+ /* fbR = fbR >> 16 */
+ spe_roti(f, fbR_reg, fbR_reg, -16);
+
+ /* fbA = fbA >> 24 */
+ spe_roti(f, fbA_reg, fbA_reg, -24);
+ break;
+
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ /* fbA = fbRGBA & mask */
+ spe_and(f, fbA_reg, fbRGBA_reg, mask0_reg);
+
+ /* fbR = fbRGBA & mask */
+ spe_and(f, fbR_reg, fbRGBA_reg, mask1_reg);
+
+ /* fbG = fbRGBA & mask */
+ spe_and(f, fbG_reg, fbRGBA_reg, mask2_reg);
+
+ /* fbB = fbRGBA & mask */
+ spe_and(f, fbB_reg, fbRGBA_reg, mask3_reg);
+
+ /* fbR = fbR >> 8 */
+ spe_roti(f, fbR_reg, fbR_reg, -8);
+
+ /* fbG = fbG >> 16 */
+ spe_roti(f, fbG_reg, fbG_reg, -16);
+
+ /* fbB = fbB >> 24 */
+ spe_roti(f, fbB_reg, fbB_reg, -24);
+ break;
+
+ default:
+ ASSERT(0);
+ }
+
+ /* convert int[4] in [0,255] to float[4] in [0.0, 1.0] */
+ spe_cuflt(f, fbR_reg, fbR_reg, 8);
+ spe_cuflt(f, fbG_reg, fbG_reg, 8);
+ spe_cuflt(f, fbB_reg, fbB_reg, 8);
+ spe_cuflt(f, fbA_reg, fbA_reg, 8);
+
+ spe_release_register(f, mask0_reg);
+ spe_release_register(f, mask1_reg);
+ spe_release_register(f, mask2_reg);
+ spe_release_register(f, mask3_reg);
+}
+
+
+/**
+ * Generate SPE code to implement the given blend mode for a quad of pixels.
+ * \param f SPE function to append instruction onto.
+ * \param fragR_reg register with fragment red values (float) (in/out)
+ * \param fragG_reg register with fragment green values (float) (in/out)
+ * \param fragB_reg register with fragment blue values (float) (in/out)
+ * \param fragA_reg register with fragment alpha values (float) (in/out)
+ * \param fbRGBA_reg register with packed framebuffer colors (integer) (in)
+ */
+static void
+gen_blend(const struct pipe_blend_state *blend,
+ const struct pipe_blend_color *blend_color,
+ struct spe_function *f,
+ enum pipe_format color_format,
+ int fragR_reg, int fragG_reg, int fragB_reg, int fragA_reg,
+ int fbRGBA_reg)
+{
+ int term1R_reg = spe_allocate_available_register(f);
+ int term1G_reg = spe_allocate_available_register(f);
+ int term1B_reg = spe_allocate_available_register(f);
+ int term1A_reg = spe_allocate_available_register(f);
+
+ int term2R_reg = spe_allocate_available_register(f);
+ int term2G_reg = spe_allocate_available_register(f);
+ int term2B_reg = spe_allocate_available_register(f);
+ int term2A_reg = spe_allocate_available_register(f);
+
+ int fbR_reg = spe_allocate_available_register(f);
+ int fbG_reg = spe_allocate_available_register(f);
+ int fbB_reg = spe_allocate_available_register(f);
+ int fbA_reg = spe_allocate_available_register(f);
+
+ int tmp_reg = spe_allocate_available_register(f);
+
+ /* Optional constant registers we might or might not end up using;
+ * if we do use them, make sure we only allocate them once by
+ * keeping a flag on each one.
+ */
+ int one_reg = -1;
+ int constR_reg = -1, constG_reg = -1, constB_reg = -1, constA_reg = -1;
+
+ ASSERT(blend->blend_enable);
+
+ /* packed RGBA -> float colors */
+ unpack_colors(f, color_format, fbRGBA_reg,
+ fbR_reg, fbG_reg, fbB_reg, fbA_reg);
+
+ /*
+ * Compute Src RGB terms. We're actually looking for the value
+ * of (the appropriate RGB factors) * (the incoming source RGB color),
+ * because in some cases (like PIPE_BLENDFACTOR_ONE and
+ * PIPE_BLENDFACTOR_ZERO) we can avoid doing unnecessary math.
+ */
+ switch (blend->rgb_src_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ /* factors = (1,1,1), so term = (R,G,B) */
+ spe_move(f, term1R_reg, fragR_reg);
+ spe_move(f, term1G_reg, fragG_reg);
+ spe_move(f, term1B_reg, fragB_reg);
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ /* factors = (0,0,0), so term = (0,0,0) */
+ spe_load_float(f, term1R_reg, 0.0f);
+ spe_load_float(f, term1G_reg, 0.0f);
+ spe_load_float(f, term1B_reg, 0.0f);
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ /* factors = (R,G,B), so term = (R*R, G*G, B*B) */
+ spe_fm(f, term1R_reg, fragR_reg, fragR_reg);
+ spe_fm(f, term1G_reg, fragG_reg, fragG_reg);
+ spe_fm(f, term1B_reg, fragB_reg, fragB_reg);
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ /* factors = (A,A,A), so term = (R*A, G*A, B*A) */
+ spe_fm(f, term1R_reg, fragR_reg, fragA_reg);
+ spe_fm(f, term1G_reg, fragG_reg, fragA_reg);
+ spe_fm(f, term1B_reg, fragB_reg, fragA_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ /* factors = (1-R,1-G,1-B), so term = (R*(1-R), G*(1-G), B*(1-B))
+ * or in other words term = (R-R*R, G-G*G, B-B*B)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term1R_reg, fragR_reg, fragR_reg, fragR_reg);
+ spe_fnms(f, term1G_reg, fragG_reg, fragG_reg, fragG_reg);
+ spe_fnms(f, term1B_reg, fragB_reg, fragB_reg, fragB_reg);
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ /* factors = (Rfb,Gfb,Bfb), so term = (R*Rfb, G*Gfb, B*Bfb) */
+ spe_fm(f, term1R_reg, fragR_reg, fbR_reg);
+ spe_fm(f, term1G_reg, fragG_reg, fbG_reg);
+ spe_fm(f, term1B_reg, fragB_reg, fbB_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ /* factors = (1-Rfb,1-Gfb,1-Bfb), so term = (R*(1-Rfb),G*(1-Gfb),B*(1-Bfb))
+ * or term = (R-R*Rfb, G-G*Gfb, B-B*Bfb)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term1R_reg, fragR_reg, fbR_reg, fragR_reg);
+ spe_fnms(f, term1G_reg, fragG_reg, fbG_reg, fragG_reg);
+ spe_fnms(f, term1B_reg, fragB_reg, fbB_reg, fragB_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ /* factors = (1-A,1-A,1-A), so term = (R*(1-A),G*(1-A),B*(1-A))
+ * or term = (R-R*A,G-G*A,B-B*A)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term1R_reg, fragR_reg, fragA_reg, fragR_reg);
+ spe_fnms(f, term1G_reg, fragG_reg, fragA_reg, fragG_reg);
+ spe_fnms(f, term1B_reg, fragB_reg, fragA_reg, fragB_reg);
+ break;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ /* factors = (Afb, Afb, Afb), so term = (R*Afb, G*Afb, B*Afb) */
+ spe_fm(f, term1R_reg, fragR_reg, fbA_reg);
+ spe_fm(f, term1G_reg, fragG_reg, fbA_reg);
+ spe_fm(f, term1B_reg, fragB_reg, fbA_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ /* factors = (1-Afb, 1-Afb, 1-Afb), so term = (R*(1-Afb),G*(1-Afb),B*(1-Afb))
+ * or term = (R-R*Afb,G-G*Afb,b-B*Afb)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term1R_reg, fragR_reg, fbA_reg, fragR_reg);
+ spe_fnms(f, term1G_reg, fragG_reg, fbA_reg, fragG_reg);
+ spe_fnms(f, term1B_reg, fragB_reg, fbA_reg, fragB_reg);
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ /* We need the optional constant color registers */
+ setup_const_register(f, &constR_reg, blend_color->color[0]);
+ setup_const_register(f, &constG_reg, blend_color->color[1]);
+ setup_const_register(f, &constB_reg, blend_color->color[2]);
+ /* now, factor = (Rc,Gc,Bc), so term = (R*Rc,G*Gc,B*Bc) */
+ spe_fm(f, term1R_reg, fragR_reg, constR_reg);
+ spe_fm(f, term1G_reg, fragG_reg, constG_reg);
+ spe_fm(f, term1B_reg, fragB_reg, constB_reg);
+ break;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ /* we'll need the optional constant alpha register */
+ setup_const_register(f, &constA_reg, blend_color->color[3]);
+ /* factor = (Ac,Ac,Ac), so term = (R*Ac,G*Ac,B*Ac) */
+ spe_fm(f, term1R_reg, fragR_reg, constA_reg);
+ spe_fm(f, term1G_reg, fragG_reg, constA_reg);
+ spe_fm(f, term1B_reg, fragB_reg, constA_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ /* We need the optional constant color registers */
+ setup_const_register(f, &constR_reg, blend_color->color[0]);
+ setup_const_register(f, &constG_reg, blend_color->color[1]);
+ setup_const_register(f, &constB_reg, blend_color->color[2]);
+ /* factor = (1-Rc,1-Gc,1-Bc), so term = (R*(1-Rc),G*(1-Gc),B*(1-Bc))
+ * or term = (R-R*Rc, G-G*Gc, B-B*Bc)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term1R_reg, fragR_reg, constR_reg, fragR_reg);
+ spe_fnms(f, term1G_reg, fragG_reg, constG_reg, fragG_reg);
+ spe_fnms(f, term1B_reg, fragB_reg, constB_reg, fragB_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ /* We need the optional constant color registers */
+ setup_const_register(f, &constR_reg, blend_color->color[0]);
+ setup_const_register(f, &constG_reg, blend_color->color[1]);
+ setup_const_register(f, &constB_reg, blend_color->color[2]);
+ /* factor = (1-Ac,1-Ac,1-Ac), so term = (R*(1-Ac),G*(1-Ac),B*(1-Ac))
+ * or term = (R-R*Ac,G-G*Ac,B-B*Ac)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term1R_reg, fragR_reg, constA_reg, fragR_reg);
+ spe_fnms(f, term1G_reg, fragG_reg, constA_reg, fragG_reg);
+ spe_fnms(f, term1B_reg, fragB_reg, constA_reg, fragB_reg);
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ /* We'll need the optional {1,1,1,1} register */
+ setup_const_register(f, &one_reg, 1.0f);
+ /* factor = (min(A,1-Afb),min(A,1-Afb),min(A,1-Afb)), so
+ * term = (R*min(A,1-Afb), G*min(A,1-Afb), B*min(A,1-Afb))
+ * We could expand the term (as a*min(b,c) == min(a*b,a*c)
+ * as long as a is positive), but then we'd have to do three
+ * spe_float_min() functions instead of one, so this is simpler.
+ */
+ /* tmp = 1 - Afb */
+ spe_fs(f, tmp_reg, one_reg, fbA_reg);
+ /* tmp = min(A,tmp) */
+ spe_float_min(f, tmp_reg, fragA_reg, tmp_reg);
+ /* term = R*tmp */
+ spe_fm(f, term1R_reg, fragR_reg, tmp_reg);
+ spe_fm(f, term1G_reg, fragG_reg, tmp_reg);
+ spe_fm(f, term1B_reg, fragB_reg, tmp_reg);
+ break;
+
+ /* These are special D3D cases involving a second color output
+ * from the fragment shader. I'm not sure we can support them
+ * yet... XXX
+ */
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Compute Src Alpha term. Like the above, we're looking for
+ * the full term A*factor, not just the factor itself, because
+ * in many cases we can avoid doing unnecessary multiplies.
+ */
+ switch (blend->alpha_src_factor) {
+ case PIPE_BLENDFACTOR_ZERO:
+ /* factor = 0, so term = 0 */
+ spe_load_float(f, term1A_reg, 0.0f);
+ break;
+
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* fall through */
+ case PIPE_BLENDFACTOR_ONE:
+ /* factor = 1, so term = A */
+ spe_move(f, term1A_reg, fragA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ /* factor = A, so term = A*A */
+ spe_fm(f, term1A_reg, fragA_reg, fragA_reg);
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ spe_fm(f, term1A_reg, fragA_reg, fragA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ /* factor = 1-A, so term = A*(1-A) = A-A*A */
+ /* fnms(a,b,c,d) computes a = d - b*c */
+ spe_fnms(f, term1A_reg, fragA_reg, fragA_reg, fragA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_DST_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ /* factor = Afb, so term = A*Afb */
+ spe_fm(f, term1A_reg, fragA_reg, fbA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ /* factor = 1-Afb, so term = A*(1-Afb) = A - A*Afb */
+ /* fnms(a,b,c,d) computes a = d - b*c */
+ spe_fnms(f, term1A_reg, fragA_reg, fbA_reg, fragA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_CONST_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ /* We need the optional constA_reg register */
+ setup_const_register(f, &constA_reg, blend_color->color[3]);
+ /* factor = Ac, so term = A*Ac */
+ spe_fm(f, term1A_reg, fragA_reg, constA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ /* We need the optional constA_reg register */
+ setup_const_register(f, &constA_reg, blend_color->color[3]);
+ /* factor = 1-Ac, so term = A*(1-Ac) = A-A*Ac */
+ /* fnms(a,b,c,d) computes a = d - b*c */
+ spe_fnms(f, term1A_reg, fragA_reg, constA_reg, fragA_reg);
+ break;
+
+ /* These are special D3D cases involving a second color output
+ * from the fragment shader. I'm not sure we can support them
+ * yet... XXX
+ */
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Compute Dest RGB term. Like the above, we're looking for
+ * the full term (Rfb,Gfb,Bfb)*(factor), not just the factor itself, because
+ * in many cases we can avoid doing unnecessary multiplies.
+ */
+ switch (blend->rgb_dst_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ /* factors = (1,1,1), so term = (Rfb,Gfb,Bfb) */
+ spe_move(f, term2R_reg, fbR_reg);
+ spe_move(f, term2G_reg, fbG_reg);
+ spe_move(f, term2B_reg, fbB_reg);
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ /* factor s= (0,0,0), so term = (0,0,0) */
+ spe_load_float(f, term2R_reg, 0.0f);
+ spe_load_float(f, term2G_reg, 0.0f);
+ spe_load_float(f, term2B_reg, 0.0f);
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ /* factors = (R,G,B), so term = (R*Rfb, G*Gfb, B*Bfb) */
+ spe_fm(f, term2R_reg, fbR_reg, fragR_reg);
+ spe_fm(f, term2G_reg, fbG_reg, fragG_reg);
+ spe_fm(f, term2B_reg, fbB_reg, fragB_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ /* factors = (1-R,1-G,1-B), so term = (Rfb*(1-R), Gfb*(1-G), Bfb*(1-B))
+ * or in other words term = (Rfb-Rfb*R, Gfb-Gfb*G, Bfb-Bfb*B)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term2R_reg, fragR_reg, fbR_reg, fbR_reg);
+ spe_fnms(f, term2G_reg, fragG_reg, fbG_reg, fbG_reg);
+ spe_fnms(f, term2B_reg, fragB_reg, fbB_reg, fbB_reg);
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ /* factors = (A,A,A), so term = (Rfb*A, Gfb*A, Bfb*A) */
+ spe_fm(f, term2R_reg, fbR_reg, fragA_reg);
+ spe_fm(f, term2G_reg, fbG_reg, fragA_reg);
+ spe_fm(f, term2B_reg, fbB_reg, fragA_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ /* factors = (1-A,1-A,1-A) so term = (Rfb-Rfb*A,Gfb-Gfb*A,Bfb-Bfb*A) */
+ /* fnms(a,b,c,d) computes a = d - b*c */
+ spe_fnms(f, term2R_reg, fbR_reg, fragA_reg, fbR_reg);
+ spe_fnms(f, term2G_reg, fbG_reg, fragA_reg, fbG_reg);
+ spe_fnms(f, term2B_reg, fbB_reg, fragA_reg, fbB_reg);
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ /* factors = (Rfb,Gfb,Bfb), so term = (Rfb*Rfb, Gfb*Gfb, Bfb*Bfb) */
+ spe_fm(f, term2R_reg, fbR_reg, fbR_reg);
+ spe_fm(f, term2G_reg, fbG_reg, fbG_reg);
+ spe_fm(f, term2B_reg, fbB_reg, fbB_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ /* factors = (1-Rfb,1-Gfb,1-Bfb), so term = (Rfb*(1-Rfb),Gfb*(1-Gfb),Bfb*(1-Bfb))
+ * or term = (Rfb-Rfb*Rfb, Gfb-Gfb*Gfb, Bfb-Bfb*Bfb)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term2R_reg, fbR_reg, fbR_reg, fbR_reg);
+ spe_fnms(f, term2G_reg, fbG_reg, fbG_reg, fbG_reg);
+ spe_fnms(f, term2B_reg, fbB_reg, fbB_reg, fbB_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ /* factors = (Afb, Afb, Afb), so term = (Rfb*Afb, Gfb*Afb, Bfb*Afb) */
+ spe_fm(f, term2R_reg, fbR_reg, fbA_reg);
+ spe_fm(f, term2G_reg, fbG_reg, fbA_reg);
+ spe_fm(f, term2B_reg, fbB_reg, fbA_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ /* factors = (1-Afb, 1-Afb, 1-Afb), so term = (Rfb*(1-Afb),Gfb*(1-Afb),Bfb*(1-Afb))
+ * or term = (Rfb-Rfb*Afb,Gfb-Gfb*Afb,Bfb-Bfb*Afb)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term2R_reg, fbR_reg, fbA_reg, fbR_reg);
+ spe_fnms(f, term2G_reg, fbG_reg, fbA_reg, fbG_reg);
+ spe_fnms(f, term2B_reg, fbB_reg, fbA_reg, fbB_reg);
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ /* We need the optional constant color registers */
+ setup_const_register(f, &constR_reg, blend_color->color[0]);
+ setup_const_register(f, &constG_reg, blend_color->color[1]);
+ setup_const_register(f, &constB_reg, blend_color->color[2]);
+ /* now, factor = (Rc,Gc,Bc), so term = (Rfb*Rc,Gfb*Gc,Bfb*Bc) */
+ spe_fm(f, term2R_reg, fbR_reg, constR_reg);
+ spe_fm(f, term2G_reg, fbG_reg, constG_reg);
+ spe_fm(f, term2B_reg, fbB_reg, constB_reg);
+ break;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ /* we'll need the optional constant alpha register */
+ setup_const_register(f, &constA_reg, blend_color->color[3]);
+ /* factor = (Ac,Ac,Ac), so term = (Rfb*Ac,Gfb*Ac,Bfb*Ac) */
+ spe_fm(f, term2R_reg, fbR_reg, constA_reg);
+ spe_fm(f, term2G_reg, fbG_reg, constA_reg);
+ spe_fm(f, term2B_reg, fbB_reg, constA_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ /* We need the optional constant color registers */
+ setup_const_register(f, &constR_reg, blend_color->color[0]);
+ setup_const_register(f, &constG_reg, blend_color->color[1]);
+ setup_const_register(f, &constB_reg, blend_color->color[2]);
+ /* factor = (1-Rc,1-Gc,1-Bc), so term = (Rfb*(1-Rc),Gfb*(1-Gc),Bfb*(1-Bc))
+ * or term = (Rfb-Rfb*Rc, Gfb-Gfb*Gc, Bfb-Bfb*Bc)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term2R_reg, fbR_reg, constR_reg, fbR_reg);
+ spe_fnms(f, term2G_reg, fbG_reg, constG_reg, fbG_reg);
+ spe_fnms(f, term2B_reg, fbB_reg, constB_reg, fbB_reg);
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ /* We need the optional constant color registers */
+ setup_const_register(f, &constR_reg, blend_color->color[0]);
+ setup_const_register(f, &constG_reg, blend_color->color[1]);
+ setup_const_register(f, &constB_reg, blend_color->color[2]);
+ /* factor = (1-Ac,1-Ac,1-Ac), so term = (Rfb*(1-Ac),Gfb*(1-Ac),Bfb*(1-Ac))
+ * or term = (Rfb-Rfb*Ac,Gfb-Gfb*Ac,Bfb-Bfb*Ac)
+ * fnms(a,b,c,d) computes a = d - b*c
+ */
+ spe_fnms(f, term2R_reg, fbR_reg, constA_reg, fbR_reg);
+ spe_fnms(f, term2G_reg, fbG_reg, constA_reg, fbG_reg);
+ spe_fnms(f, term2B_reg, fbB_reg, constA_reg, fbB_reg);
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* not supported for dest RGB */
+ ASSERT(0);
+ break;
+
+ /* These are special D3D cases involving a second color output
+ * from the fragment shader. I'm not sure we can support them
+ * yet... XXX
+ */
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Compute Dest Alpha term. Like the above, we're looking for
+ * the full term Afb*factor, not just the factor itself, because
+ * in many cases we can avoid doing unnecessary multiplies.
+ */
+ switch (blend->alpha_dst_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ /* factor = 1, so term = Afb */
+ spe_move(f, term2A_reg, fbA_reg);
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ /* factor = 0, so term = 0 */
+ spe_load_float(f, term2A_reg, 0.0f);
+ break;
+
+ case PIPE_BLENDFACTOR_SRC_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ /* factor = A, so term = Afb*A */
+ spe_fm(f, term2A_reg, fbA_reg, fragA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ /* factor = 1-A, so term = Afb*(1-A) = Afb-Afb*A */
+ /* fnms(a,b,c,d) computes a = d - b*c */
+ spe_fnms(f, term2A_reg, fbA_reg, fragA_reg, fbA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_DST_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ /* factor = Afb, so term = Afb*Afb */
+ spe_fm(f, term2A_reg, fbA_reg, fbA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ /* factor = 1-Afb, so term = Afb*(1-Afb) = Afb - Afb*Afb */
+ /* fnms(a,b,c,d) computes a = d - b*c */
+ spe_fnms(f, term2A_reg, fbA_reg, fbA_reg, fbA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_CONST_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ /* We need the optional constA_reg register */
+ setup_const_register(f, &constA_reg, blend_color->color[3]);
+ /* factor = Ac, so term = Afb*Ac */
+ spe_fm(f, term2A_reg, fbA_reg, constA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA: /* fall through */
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ /* We need the optional constA_reg register */
+ setup_const_register(f, &constA_reg, blend_color->color[3]);
+ /* factor = 1-Ac, so term = Afb*(1-Ac) = Afb-Afb*Ac */
+ /* fnms(a,b,c,d) computes a = d - b*c */
+ spe_fnms(f, term2A_reg, fbA_reg, constA_reg, fbA_reg);
+ break;
+
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* not supported for dest alpha */
+ ASSERT(0);
+ break;
+
+ /* These are special D3D cases involving a second color output
+ * from the fragment shader. I'm not sure we can support them
+ * yet... XXX
+ */
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Combine Src/Dest RGB terms as per the blend equation.
+ */
+ switch (blend->rgb_func) {
+ case PIPE_BLEND_ADD:
+ spe_fa(f, fragR_reg, term1R_reg, term2R_reg);
+ spe_fa(f, fragG_reg, term1G_reg, term2G_reg);
+ spe_fa(f, fragB_reg, term1B_reg, term2B_reg);
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ spe_fs(f, fragR_reg, term1R_reg, term2R_reg);
+ spe_fs(f, fragG_reg, term1G_reg, term2G_reg);
+ spe_fs(f, fragB_reg, term1B_reg, term2B_reg);
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ spe_fs(f, fragR_reg, term2R_reg, term1R_reg);
+ spe_fs(f, fragG_reg, term2G_reg, term1G_reg);
+ spe_fs(f, fragB_reg, term2B_reg, term1B_reg);
+ break;
+ case PIPE_BLEND_MIN:
+ spe_float_min(f, fragR_reg, term1R_reg, term2R_reg);
+ spe_float_min(f, fragG_reg, term1G_reg, term2G_reg);
+ spe_float_min(f, fragB_reg, term1B_reg, term2B_reg);
+ break;
+ case PIPE_BLEND_MAX:
+ spe_float_max(f, fragR_reg, term1R_reg, term2R_reg);
+ spe_float_max(f, fragG_reg, term1G_reg, term2G_reg);
+ spe_float_max(f, fragB_reg, term1B_reg, term2B_reg);
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Combine Src/Dest A term
+ */
+ switch (blend->alpha_func) {
+ case PIPE_BLEND_ADD:
+ spe_fa(f, fragA_reg, term1A_reg, term2A_reg);
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ spe_fs(f, fragA_reg, term1A_reg, term2A_reg);
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ spe_fs(f, fragA_reg, term2A_reg, term1A_reg);
+ break;
+ case PIPE_BLEND_MIN:
+ spe_float_min(f, fragA_reg, term1A_reg, term2A_reg);
+ break;
+ case PIPE_BLEND_MAX:
+ spe_float_max(f, fragA_reg, term1A_reg, term2A_reg);
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ spe_release_register(f, term1R_reg);
+ spe_release_register(f, term1G_reg);
+ spe_release_register(f, term1B_reg);
+ spe_release_register(f, term1A_reg);
+
+ spe_release_register(f, term2R_reg);
+ spe_release_register(f, term2G_reg);
+ spe_release_register(f, term2B_reg);
+ spe_release_register(f, term2A_reg);
+
+ spe_release_register(f, fbR_reg);
+ spe_release_register(f, fbG_reg);
+ spe_release_register(f, fbB_reg);
+ spe_release_register(f, fbA_reg);
+
+ spe_release_register(f, tmp_reg);
+
+ /* Free any optional registers that actually got used */
+ release_const_register(f, one_reg);
+ release_const_register(f, constR_reg);
+ release_const_register(f, constG_reg);
+ release_const_register(f, constB_reg);
+ release_const_register(f, constA_reg);
+}
+
+
+static void
+gen_logicop(const struct pipe_blend_state *blend,
+ struct spe_function *f,
+ int fragRGBA_reg, int fbRGBA_reg)
+{
+ /* We've got four 32-bit RGBA packed pixels in each of
+ * fragRGBA_reg and fbRGBA_reg, not sets of floating-point
+ * reds, greens, blues, and alphas.
+ * */
+ ASSERT(blend->logicop_enable);
+
+ switch(blend->logicop_func) {
+ case PIPE_LOGICOP_CLEAR: /* 0 */
+ spe_zero(f, fragRGBA_reg);
+ break;
+ case PIPE_LOGICOP_NOR: /* ~(s | d) */
+ spe_nor(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg);
+ break;
+ case PIPE_LOGICOP_AND_INVERTED: /* ~s & d */
+ /* andc R, A, B computes R = A & ~B */
+ spe_andc(f, fragRGBA_reg, fbRGBA_reg, fragRGBA_reg);
+ break;
+ case PIPE_LOGICOP_COPY_INVERTED: /* ~s */
+ spe_complement(f, fragRGBA_reg, fragRGBA_reg);
+ break;
+ case PIPE_LOGICOP_AND_REVERSE: /* s & ~d */
+ /* andc R, A, B computes R = A & ~B */
+ spe_andc(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg);
+ break;
+ case PIPE_LOGICOP_INVERT: /* ~d */
+ /* Note that (A nor A) == ~(A|A) == ~A */
+ spe_nor(f, fragRGBA_reg, fbRGBA_reg, fbRGBA_reg);
+ break;
+ case PIPE_LOGICOP_XOR: /* s ^ d */
+ spe_xor(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg);
+ break;
+ case PIPE_LOGICOP_NAND: /* ~(s & d) */
+ spe_nand(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg);
+ break;
+ case PIPE_LOGICOP_AND: /* s & d */
+ spe_and(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg);
+ break;
+ case PIPE_LOGICOP_EQUIV: /* ~(s ^ d) */
+ spe_xor(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg);
+ spe_complement(f, fragRGBA_reg, fragRGBA_reg);
+ break;
+ case PIPE_LOGICOP_NOOP: /* d */
+ spe_move(f, fragRGBA_reg, fbRGBA_reg);
+ break;
+ case PIPE_LOGICOP_OR_INVERTED: /* ~s | d */
+ /* orc R, A, B computes R = A | ~B */
+ spe_orc(f, fragRGBA_reg, fbRGBA_reg, fragRGBA_reg);
+ break;
+ case PIPE_LOGICOP_COPY: /* s */
+ break;
+ case PIPE_LOGICOP_OR_REVERSE: /* s | ~d */
+ /* orc R, A, B computes R = A | ~B */
+ spe_orc(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg);
+ break;
+ case PIPE_LOGICOP_OR: /* s | d */
+ spe_or(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg);
+ break;
+ case PIPE_LOGICOP_SET: /* 1 */
+ spe_load_int(f, fragRGBA_reg, 0xffffffff);
+ break;
+ default:
+ ASSERT(0);
+ }
+}
+
+
+/**
+ * Generate code to pack a quad of float colors into four 32-bit integers.
+ *
+ * \param f SPE function to append instruction onto.
+ * \param color_format the dest color packing format
+ * \param r_reg register containing four red values (in/clobbered)
+ * \param g_reg register containing four green values (in/clobbered)
+ * \param b_reg register containing four blue values (in/clobbered)
+ * \param a_reg register containing four alpha values (in/clobbered)
+ * \param rgba_reg register to store the packed RGBA colors (out)
+ */
+static void
+gen_pack_colors(struct spe_function *f,
+ enum pipe_format color_format,
+ int r_reg, int g_reg, int b_reg, int a_reg,
+ int rgba_reg)
+{
+ int rg_reg = spe_allocate_available_register(f);
+ int ba_reg = spe_allocate_available_register(f);
+
+ /* Convert float[4] in [0.0,1.0] to int[4] in [0,~0], with clamping */
+ spe_cfltu(f, r_reg, r_reg, 32);
+ spe_cfltu(f, g_reg, g_reg, 32);
+ spe_cfltu(f, b_reg, b_reg, 32);
+ spe_cfltu(f, a_reg, a_reg, 32);
+
+ /* Shift the most significant bytes to the least significant positions.
+ * I.e.: reg = reg >> 24
+ */
+ spe_rotmi(f, r_reg, r_reg, -24);
+ spe_rotmi(f, g_reg, g_reg, -24);
+ spe_rotmi(f, b_reg, b_reg, -24);
+ spe_rotmi(f, a_reg, a_reg, -24);
+
+ /* Shift the color bytes according to the surface format */
+ if (color_format == PIPE_FORMAT_A8R8G8B8_UNORM) {
+ spe_roti(f, g_reg, g_reg, 8); /* green <<= 8 */
+ spe_roti(f, r_reg, r_reg, 16); /* red <<= 16 */
+ spe_roti(f, a_reg, a_reg, 24); /* alpha <<= 24 */
+ }
+ else if (color_format == PIPE_FORMAT_B8G8R8A8_UNORM) {
+ spe_roti(f, r_reg, r_reg, 8); /* red <<= 8 */
+ spe_roti(f, g_reg, g_reg, 16); /* green <<= 16 */
+ spe_roti(f, b_reg, b_reg, 24); /* blue <<= 24 */
+ }
+ else {
+ ASSERT(0);
+ }
+
+ /* Merge red, green, blue, alpha registers to make packed RGBA colors.
+ * Eg: after shifting according to color_format we might have:
+ * R = {0x00ff0000, 0x00110000, 0x00220000, 0x00330000}
+ * G = {0x0000ff00, 0x00004400, 0x00005500, 0x00006600}
+ * B = {0x000000ff, 0x00000077, 0x00000088, 0x00000099}
+ * A = {0xff000000, 0xaa000000, 0xbb000000, 0xcc000000}
+ * OR-ing all those together gives us four packed colors:
+ * RGBA = {0xffffffff, 0xaa114477, 0xbb225588, 0xcc336699}
+ */
+ spe_or(f, rg_reg, r_reg, g_reg);
+ spe_or(f, ba_reg, a_reg, b_reg);
+ spe_or(f, rgba_reg, rg_reg, ba_reg);
+
+ spe_release_register(f, rg_reg);
+ spe_release_register(f, ba_reg);
+}
+
+
+static void
+gen_colormask(struct spe_function *f,
+ uint colormask,
+ enum pipe_format color_format,
+ int fragRGBA_reg, int fbRGBA_reg)
+{
+ /* We've got four 32-bit RGBA packed pixels in each of
+ * fragRGBA_reg and fbRGBA_reg, not sets of floating-point
+ * reds, greens, blues, and alphas. Further, the pixels
+ * are packed according to the given color format, not
+ * necessarily RGBA...
+ */
+ uint r_mask;
+ uint g_mask;
+ uint b_mask;
+ uint a_mask;
+
+ /* Calculate exactly where the bits for any particular color
+ * end up, so we can mask them correctly.
+ */
+ switch(color_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ /* ARGB */
+ a_mask = 0xff000000;
+ r_mask = 0x00ff0000;
+ g_mask = 0x0000ff00;
+ b_mask = 0x000000ff;
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ /* BGRA */
+ b_mask = 0xff000000;
+ g_mask = 0x00ff0000;
+ r_mask = 0x0000ff00;
+ a_mask = 0x000000ff;
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ /* For each R, G, B, and A component we're supposed to mask out,
+ * clear its bits. Then our mask operation later will work
+ * as expected.
+ */
+ if (!(colormask & PIPE_MASK_R)) {
+ r_mask = 0;
+ }
+ if (!(colormask & PIPE_MASK_G)) {
+ g_mask = 0;
+ }
+ if (!(colormask & PIPE_MASK_B)) {
+ b_mask = 0;
+ }
+ if (!(colormask & PIPE_MASK_A)) {
+ a_mask = 0;
+ }
+
+ /* Get a temporary register to hold the mask that will be applied
+ * to the fragment
+ */
+ int colormask_reg = spe_allocate_available_register(f);
+
+ /* The actual mask we're going to use is an OR of the remaining R, G, B,
+ * and A masks. Load the result value into our temporary register.
+ */
+ spe_load_uint(f, colormask_reg, r_mask | g_mask | b_mask | a_mask);
+
+ /* Use the mask register to select between the fragment color
+ * values and the frame buffer color values. Wherever the
+ * mask has a 0 bit, the current frame buffer color should override
+ * the fragment color. Wherever the mask has a 1 bit, the
+ * fragment color should persevere. The Select Bits (selb rt, rA, rB, rM)
+ * instruction will select bits from its first operand rA wherever the
+ * the mask bits rM are 0, and from its second operand rB wherever the
+ * mask bits rM are 1. That means that the frame buffer color is the
+ * first operand, and the fragment color the second.
+ */
+ spe_selb(f, fragRGBA_reg, fbRGBA_reg, fragRGBA_reg, colormask_reg);
+
+ /* Release the temporary register and we're done */
+ spe_release_register(f, colormask_reg);
+}
+
+
+/**
+ * This function is annoyingly similar to gen_depth_test(), above, except
+ * that instead of comparing two varying values (i.e. fragment and buffer),
+ * we're comparing a varying value with a static value. As such, we have
+ * access to the Compare Immediate instructions where we don't in
+ * gen_depth_test(), which is what makes us very different.
+ *
+ * There's some added complexity if there's a non-trivial state->mask
+ * value; then stencil and reference both must be masked
+ *
+ * The return value in the stencil_pass_reg is a bitmask of valid
+ * fragments that also passed the stencil test. The bitmask of valid
+ * fragments that failed would be found in
+ * (fragment_mask_reg & ~stencil_pass_reg).
+ */
+static void
+gen_stencil_test(struct spe_function *f,
+ const struct pipe_stencil_state *state,
+ uint stencil_max_value,
+ int fragment_mask_reg,
+ int fbS_reg,
+ int stencil_pass_reg)
+{
+ /* Generate code that puts the set of passing fragments into the
+ * stencil_pass_reg register, taking into account whether each fragment
+ * was active to begin with.
+ */
+ switch (state->func) {
+ case PIPE_FUNC_EQUAL:
+ if (state->valuemask == stencil_max_value) {
+ /* stencil_pass = fragment_mask & (s == reference) */
+ spe_compare_equal_uint(f, stencil_pass_reg, fbS_reg, state->ref_value);
+ spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ }
+ else {
+ /* stencil_pass = fragment_mask & ((s&mask) == (reference&mask)) */
+ uint tmp_masked_stencil = spe_allocate_available_register(f);
+ spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
+ spe_compare_equal_uint(f, stencil_pass_reg, tmp_masked_stencil,
+ state->valuemask & state->ref_value);
+ spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ spe_release_register(f, tmp_masked_stencil);
+ }
+ break;
+
+ case PIPE_FUNC_NOTEQUAL:
+ if (state->valuemask == stencil_max_value) {
+ /* stencil_pass = fragment_mask & ~(s == reference) */
+ spe_compare_equal_uint(f, stencil_pass_reg, fbS_reg, state->ref_value);
+ spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ }
+ else {
+ /* stencil_pass = fragment_mask & ~((s&mask) == (reference&mask)) */
+ int tmp_masked_stencil = spe_allocate_available_register(f);
+ spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
+ spe_compare_equal_uint(f, stencil_pass_reg, tmp_masked_stencil,
+ state->valuemask & state->ref_value);
+ spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ spe_release_register(f, tmp_masked_stencil);
+ }
+ break;
+
+ case PIPE_FUNC_LESS:
+ if (state->valuemask == stencil_max_value) {
+ /* stencil_pass = fragment_mask & (reference < s) */
+ spe_compare_greater_uint(f, stencil_pass_reg, fbS_reg, state->ref_value);
+ spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ }
+ else {
+ /* stencil_pass = fragment_mask & ((reference&mask) < (s & mask)) */
+ int tmp_masked_stencil = spe_allocate_available_register(f);
+ spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
+ spe_compare_greater_uint(f, stencil_pass_reg, tmp_masked_stencil,
+ state->valuemask & state->ref_value);
+ spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ spe_release_register(f, tmp_masked_stencil);
+ }
+ break;
+
+ case PIPE_FUNC_GREATER:
+ if (state->valuemask == stencil_max_value) {
+ /* stencil_pass = fragment_mask & (reference > s) */
+ /* There's no convenient Compare Less Than Immediate instruction, so
+ * we'll have to do this one the harder way, by loading a register and
+ * comparing directly. Compare Logical Greater Than Word (clgt)
+ * treats its operands as unsigned - no sign extension.
+ */
+ int tmp_reg = spe_allocate_available_register(f);
+ spe_load_uint(f, tmp_reg, state->ref_value);
+ spe_clgt(f, stencil_pass_reg, tmp_reg, fbS_reg);
+ spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ spe_release_register(f, tmp_reg);
+ }
+ else {
+ /* stencil_pass = fragment_mask & ((reference&mask) > (s&mask)) */
+ int tmp_reg = spe_allocate_available_register(f);
+ int tmp_masked_stencil = spe_allocate_available_register(f);
+ spe_load_uint(f, tmp_reg, state->valuemask & state->ref_value);
+ spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
+ spe_clgt(f, stencil_pass_reg, tmp_reg, tmp_masked_stencil);
+ spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ spe_release_register(f, tmp_reg);
+ spe_release_register(f, tmp_masked_stencil);
+ }
+ break;
+
+ case PIPE_FUNC_GEQUAL:
+ if (state->valuemask == stencil_max_value) {
+ /* stencil_pass = fragment_mask & (reference >= s)
+ * = fragment_mask & ~(s > reference) */
+ spe_compare_greater_uint(f, stencil_pass_reg, fbS_reg,
+ state->ref_value);
+ spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ }
+ else {
+ /* stencil_pass = fragment_mask & ~((s&mask) > (reference&mask)) */
+ int tmp_masked_stencil = spe_allocate_available_register(f);
+ spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
+ spe_compare_greater_uint(f, stencil_pass_reg, tmp_masked_stencil,
+ state->valuemask & state->ref_value);
+ spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ spe_release_register(f, tmp_masked_stencil);
+ }
+ break;
+
+ case PIPE_FUNC_LEQUAL:
+ if (state->valuemask == stencil_max_value) {
+ /* stencil_pass = fragment_mask & (reference <= s) ]
+ * = fragment_mask & ~(reference > s) */
+ /* As above, we have to do this by loading a register */
+ int tmp_reg = spe_allocate_available_register(f);
+ spe_load_uint(f, tmp_reg, state->ref_value);
+ spe_clgt(f, stencil_pass_reg, tmp_reg, fbS_reg);
+ spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ spe_release_register(f, tmp_reg);
+ }
+ else {
+ /* stencil_pass = fragment_mask & ~((reference&mask) > (s&mask)) */
+ int tmp_reg = spe_allocate_available_register(f);
+ int tmp_masked_stencil = spe_allocate_available_register(f);
+ spe_load_uint(f, tmp_reg, state->ref_value & state->valuemask);
+ spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
+ spe_clgt(f, stencil_pass_reg, tmp_reg, tmp_masked_stencil);
+ spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
+ spe_release_register(f, tmp_reg);
+ spe_release_register(f, tmp_masked_stencil);
+ }
+ break;
+
+ case PIPE_FUNC_NEVER:
+ /* stencil_pass = fragment_mask & 0 = 0 */
+ spe_load_uint(f, stencil_pass_reg, 0);
+ break;
+
+ case PIPE_FUNC_ALWAYS:
+ /* stencil_pass = fragment_mask & 1 = fragment_mask */
+ spe_move(f, stencil_pass_reg, fragment_mask_reg);
+ break;
+ }
+
+ /* The fragments that passed the stencil test are now in stencil_pass_reg.
+ * The fragments that failed would be (fragment_mask_reg & ~stencil_pass_reg).
+ */
+}
+
+
+/**
+ * This function generates code that calculates a set of new stencil values
+ * given the earlier values and the operation to apply. It does not
+ * apply any tests. It is intended to be called up to 3 times
+ * (for the stencil fail operation, for the stencil pass-z fail operation,
+ * and for the stencil pass-z pass operation) to collect up to three
+ * possible sets of values, and for the caller to combine them based
+ * on the result of the tests.
+ *
+ * stencil_max_value should be (2^n - 1) where n is the number of bits
+ * in the stencil buffer - in other words, it should be usable as a mask.
+ */
+static void
+gen_stencil_values(struct spe_function *f,
+ uint stencil_op,
+ uint stencil_ref_value,
+ uint stencil_max_value,
+ int fbS_reg,
+ int newS_reg)
+{
+ /* The code below assumes that newS_reg and fbS_reg are not the same
+ * register; if they can be, the calculations below will have to use
+ * an additional temporary register. For now, mark the assumption
+ * with an assertion that will fail if they are the same.
+ */
+ ASSERT(fbS_reg != newS_reg);
+
+ /* The code also assumes the the stencil_max_value is of the form
+ * 2^n-1 and can therefore be used as a mask for the valid bits in
+ * addition to a maximum. Make sure this is the case as well.
+ * The clever math below exploits the fact that incrementing a
+ * binary number serves to flip all the bits of a number starting at
+ * the LSB and continuing to (and including) the first zero bit
+ * found. That means that a number and its increment will always
+ * have at least one bit in common (the high order bit, if nothing
+ * else) *unless* the number is zero, *or* the number is of a form
+ * consisting of some number of 1s in the low-order bits followed
+ * by nothing but 0s in the high-order bits. The latter case
+ * implies it's of the form 2^n-1.
+ */
+ ASSERT(stencil_max_value > 0 && ((stencil_max_value + 1) & stencil_max_value) == 0);
+
+ switch(stencil_op) {
+ case PIPE_STENCIL_OP_KEEP:
+ /* newS = S */
+ spe_move(f, newS_reg, fbS_reg);
+ break;
+
+ case PIPE_STENCIL_OP_ZERO:
+ /* newS = 0 */
+ spe_zero(f, newS_reg);
+ break;
+
+ case PIPE_STENCIL_OP_REPLACE:
+ /* newS = stencil reference value */
+ spe_load_uint(f, newS_reg, stencil_ref_value);
+ break;
+
+ case PIPE_STENCIL_OP_INCR: {
+ /* newS = (s == max ? max : s + 1) */
+ int equals_reg = spe_allocate_available_register(f);
+
+ spe_compare_equal_uint(f, equals_reg, fbS_reg, stencil_max_value);
+ /* Add Word Immediate computes rT = rA + 10-bit signed immediate */
+ spe_ai(f, newS_reg, fbS_reg, 1);
+ /* Select from the current value or the new value based on the equality test */
+ spe_selb(f, newS_reg, newS_reg, fbS_reg, equals_reg);
+
+ spe_release_register(f, equals_reg);
+ break;
+ }
+ case PIPE_STENCIL_OP_DECR: {
+ /* newS = (s == 0 ? 0 : s - 1) */
+ int equals_reg = spe_allocate_available_register(f);
+
+ spe_compare_equal_uint(f, equals_reg, fbS_reg, 0);
+ /* Add Word Immediate with a (-1) value works */
+ spe_ai(f, newS_reg, fbS_reg, -1);
+ /* Select from the current value or the new value based on the equality test */
+ spe_selb(f, newS_reg, newS_reg, fbS_reg, equals_reg);
+
+ spe_release_register(f, equals_reg);
+ break;
+ }
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ /* newS = (s == max ? 0 : s + 1), but since max is 2^n-1, we can
+ * do a normal add and mask off the correct bits
+ */
+ spe_ai(f, newS_reg, fbS_reg, 1);
+ spe_and_uint(f, newS_reg, newS_reg, stencil_max_value);
+ break;
+
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ /* newS = (s == 0 ? max : s - 1), but we'll pull the same mask trick as above */
+ spe_ai(f, newS_reg, fbS_reg, -1);
+ spe_and_uint(f, newS_reg, newS_reg, stencil_max_value);
+ break;
+
+ case PIPE_STENCIL_OP_INVERT:
+ /* newS = ~s. We take advantage of the mask/max value to invert only
+ * the valid bits for the field so we don't have to do an extra "and".
+ */
+ spe_xor_uint(f, newS_reg, fbS_reg, stencil_max_value);
+ break;
+
+ default:
+ ASSERT(0);
+ }
+}
+
+
+/**
+ * This function generates code to get all the necessary possible
+ * stencil values. For each of the output registers (fail_reg,
+ * zfail_reg, and zpass_reg), it either allocates a new register
+ * and calculates a new set of values based on the stencil operation,
+ * or it reuses a register allocation and calculation done for an
+ * earlier (matching) operation, or it reuses the fbS_reg register
+ * (if the stencil operation is KEEP, which doesn't change the
+ * stencil buffer).
+ *
+ * Since this function allocates a variable number of registers,
+ * to avoid incurring complex logic to free them, they should
+ * be allocated after a spe_allocate_register_set() call
+ * and released by the corresponding spe_release_register_set() call.
+ */
+static void
+gen_get_stencil_values(struct spe_function *f,
+ const struct pipe_stencil_state *stencil,
+ const uint depth_enabled,
+ int fbS_reg,
+ int *fail_reg,
+ int *zfail_reg,
+ int *zpass_reg)
+{
+ uint zfail_op;
+
+ /* Stenciling had better be enabled here */
+ ASSERT(stencil->enabled);
+
+ /* If the depth test is not enabled, it is treated as though it always
+ * passes, which means that the zfail_op is not considered - a
+ * failing stencil test triggers the fail_op, and a passing one
+ * triggers the zpass_op
+ *
+ * As an optimization, override calculation of the zfail_op values
+ * if they aren't going to be used. By setting the value of
+ * the operation to PIPE_STENCIL_OP_KEEP, its value will be assumed
+ * to match the incoming stencil values, and no calculation will
+ * be done.
+ */
+ if (depth_enabled) {
+ zfail_op = stencil->zfail_op;
+ }
+ else {
+ zfail_op = PIPE_STENCIL_OP_KEEP;
+ }
+
+ /* One-sided or front-facing stencil */
+ if (stencil->fail_op == PIPE_STENCIL_OP_KEEP) {
+ *fail_reg = fbS_reg;
+ }
+ else {
+ *fail_reg = spe_allocate_available_register(f);
+ gen_stencil_values(f, stencil->fail_op, stencil->ref_value,
+ 0xff, fbS_reg, *fail_reg);
+ }
+
+ /* Check the possibly overridden value, not the structure value */
+ if (zfail_op == PIPE_STENCIL_OP_KEEP) {
+ *zfail_reg = fbS_reg;
+ }
+ else if (zfail_op == stencil->fail_op) {
+ *zfail_reg = *fail_reg;
+ }
+ else {
+ *zfail_reg = spe_allocate_available_register(f);
+ gen_stencil_values(f, stencil->zfail_op, stencil->ref_value,
+ 0xff, fbS_reg, *zfail_reg);
+ }
+
+ if (stencil->zpass_op == PIPE_STENCIL_OP_KEEP) {
+ *zpass_reg = fbS_reg;
+ }
+ else if (stencil->zpass_op == stencil->fail_op) {
+ *zpass_reg = *fail_reg;
+ }
+ else if (stencil->zpass_op == zfail_op) {
+ *zpass_reg = *zfail_reg;
+ }
+ else {
+ *zpass_reg = spe_allocate_available_register(f);
+ gen_stencil_values(f, stencil->zpass_op, stencil->ref_value,
+ 0xff, fbS_reg, *zpass_reg);
+ }
+}
+
+/**
+ * Note that fbZ_reg may *not* be set on entry, if in fact
+ * the depth test is not enabled. This function must not use
+ * the register if depth is not enabled.
+ */
+static boolean
+gen_stencil_depth_test(struct spe_function *f,
+ const struct pipe_depth_stencil_alpha_state *dsa,
+ const uint facing,
+ const int mask_reg, const int fragZ_reg,
+ const int fbZ_reg, const int fbS_reg)
+{
+ /* True if we've generated code that could require writeback to the
+ * depth and/or stencil buffers
+ */
+ boolean modified_buffers = FALSE;
+
+ boolean need_to_calculate_stencil_values;
+ boolean need_to_writemask_stencil_values;
+
+ struct pipe_stencil_state *stencil;
+
+ /* Registers. We may or may not actually allocate these, depending
+ * on whether the state values indicate that we need them.
+ */
+ int stencil_pass_reg, stencil_fail_reg;
+ int stencil_fail_values, stencil_pass_depth_fail_values, stencil_pass_depth_pass_values;
+ int stencil_writemask_reg;
+ int zmask_reg;
+ int newS_reg;
+
+ /* Stenciling is quite complex: up to six different configurable stencil
+ * operations/calculations can be required (three each for front-facing
+ * and back-facing fragments). Many of those operations will likely
+ * be identical, so there's good reason to try to avoid calculating
+ * the same values more than once (which unfortunately makes the code less
+ * straightforward).
+ *
+ * To make register management easier, we start a new
+ * register set; we can release all the registers in the set at
+ * once, and avoid having to keep track of exactly which registers
+ * we allocate. We can still allocate and free registers as
+ * desired (if we know we no longer need a register), but we don't
+ * have to spend the complexity to track the more difficult variant
+ * register usage scenarios.
+ */
+ spe_comment(f, 0, "Allocating stencil register set");
+ spe_allocate_register_set(f);
+
+ /* The facing we're given is the fragment facing; it doesn't
+ * exactly match the stencil facing. If stencil is enabled,
+ * but two-sided stencil is *not* enabled, we use the same
+ * stencil settings for both front- and back-facing fragments.
+ * We only use the "back-facing" stencil for backfacing fragments
+ * if two-sided stenciling is enabled.
+ */
+ if (facing == CELL_FACING_BACK && dsa->stencil[1].enabled) {
+ stencil = &dsa->stencil[1];
+ }
+ else {
+ stencil = &dsa->stencil[0];
+ }
+
+ /* Calculate the writemask. If the writemask is trivial (either
+ * all 0s, meaning that we don't need to calculate any stencil values
+ * because they're not going to change the stencil anyway, or all 1s,
+ * meaning that we have to calculate the stencil values but do not
+ * need to mask them), we can avoid generating code. Don't forget
+ * that we need to consider backfacing stencil, if enabled.
+ *
+ * Note that if the backface stencil is *not* enabled, the backface
+ * stencil will have the same values as the frontface stencil.
+ */
+ if (stencil->fail_op == PIPE_STENCIL_OP_KEEP &&
+ stencil->zfail_op == PIPE_STENCIL_OP_KEEP &&
+ stencil->zpass_op == PIPE_STENCIL_OP_KEEP) {
+ need_to_calculate_stencil_values = FALSE;
+ need_to_writemask_stencil_values = FALSE;
+ }
+ else if (stencil->writemask == 0x0) {
+ /* All changes are writemasked out, so no need to calculate
+ * what those changes might be, and no need to write anything back.
+ */
+ need_to_calculate_stencil_values = FALSE;
+ need_to_writemask_stencil_values = FALSE;
+ }
+ else if (stencil->writemask == 0xff) {
+ /* Still trivial, but a little less so. We need to write the stencil
+ * values, but we don't need to mask them.
+ */
+ need_to_calculate_stencil_values = TRUE;
+ need_to_writemask_stencil_values = FALSE;
+ }
+ else {
+ /* The general case: calculate, mask, and write */
+ need_to_calculate_stencil_values = TRUE;
+ need_to_writemask_stencil_values = TRUE;
+
+ /* While we're here, generate code that calculates what the
+ * writemask should be. If backface stenciling is enabled,
+ * and the backface writemask is not the same as the frontface
+ * writemask, we'll have to generate code that merges the
+ * two masks into a single effective mask based on fragment facing.
+ */
+ spe_comment(f, 0, "Computing stencil writemask");
+ stencil_writemask_reg = spe_allocate_available_register(f);
+ spe_load_uint(f, stencil_writemask_reg, dsa->stencil[facing].writemask);
+ }
+
+ /* At least one-sided stenciling must be on. Generate code that
+ * runs the stencil test on the basic/front-facing stencil, leaving
+ * the mask of passing stencil bits in stencil_pass_reg. This mask will
+ * be used both to mask the set of active pixels, and also to
+ * determine how the stencil buffer changes.
+ *
+ * This test will *not* change the value in mask_reg (because we don't
+ * yet know whether to apply the two-sided stencil or one-sided stencil).
+ */
+ spe_comment(f, 0, "Running basic stencil test");
+ stencil_pass_reg = spe_allocate_available_register(f);
+ gen_stencil_test(f, stencil, 0xff, mask_reg, fbS_reg, stencil_pass_reg);
+
+ /* Generate code that, given the mask of valid fragments and the
+ * mask of valid fragments that passed the stencil test, computes
+ * the mask of valid fragments that failed the stencil test. We
+ * have to do this before we run a depth test (because the
+ * depth test should not be performed on fragments that failed the
+ * stencil test, and because the depth test will update the
+ * mask of valid fragments based on the results of the depth test).
+ */
+ spe_comment(f, 0, "Computing stencil fail mask and updating fragment mask");
+ stencil_fail_reg = spe_allocate_available_register(f);
+ spe_andc(f, stencil_fail_reg, mask_reg, stencil_pass_reg);
+ /* Now remove the stenciled-out pixels from the valid fragment mask,
+ * so we can later use the valid fragment mask in the depth test.
+ */
+ spe_and(f, mask_reg, mask_reg, stencil_pass_reg);
+
+ /* We may not need to calculate stencil values, if the writemask is off */
+ if (need_to_calculate_stencil_values) {
+ /* Generate code that calculates exactly which stencil values we need,
+ * without calculating the same value twice (say, if two different
+ * stencil ops have the same value). This code will work for one-sided
+ * and two-sided stenciling (so that we take into account that operations
+ * may match between front and back stencils), and will also take into
+ * account whether the depth test is enabled (if the depth test is off,
+ * we don't need any of the zfail results, because the depth test always
+ * is considered to pass if it is disabled). Any register value that
+ * does not need to be calculated will come back with the same value
+ * that's in fbS_reg.
+ *
+ * This function will allocate a variant number of registers that
+ * will be released as part of the register set.
+ */
+ spe_comment(f, 0, facing == CELL_FACING_FRONT
+ ? "Computing front-facing stencil values"
+ : "Computing back-facing stencil values");
+ gen_get_stencil_values(f, stencil, dsa->depth.enabled, fbS_reg,
+ &stencil_fail_values, &stencil_pass_depth_fail_values,
+ &stencil_pass_depth_pass_values);
+ }
+
+ /* We now have all the stencil values we need. We also need
+ * the results of the depth test to figure out which
+ * stencil values will become the new stencil values. (Even if
+ * we aren't actually calculating stencil values, we need to apply
+ * the depth test if it's enabled.)
+ *
+ * The code generated by gen_depth_test() returns the results of the
+ * test in the given register, but also alters the mask_reg based
+ * on the results of the test.
+ */
+ if (dsa->depth.enabled) {
+ spe_comment(f, 0, "Running stencil depth test");
+ zmask_reg = spe_allocate_available_register(f);
+ modified_buffers |= gen_depth_test(f, dsa, mask_reg, fragZ_reg,
+ fbZ_reg, zmask_reg);
+ }
+
+ if (need_to_calculate_stencil_values) {
+
+ /* If we need to writemask the stencil values before going into
+ * the stencil buffer, we'll have to use a new register to
+ * hold the new values. If not, we can just keep using the
+ * current register.
+ */
+ if (need_to_writemask_stencil_values) {
+ newS_reg = spe_allocate_available_register(f);
+ spe_comment(f, 0, "Saving current stencil values for writemasking");
+ spe_move(f, newS_reg, fbS_reg);
+ }
+ else {
+ newS_reg = fbS_reg;
+ }
+
+ /* Merge in the selected stencil fail values */
+ if (stencil_fail_values != fbS_reg) {
+ spe_comment(f, 0, "Loading stencil fail values");
+ spe_selb(f, newS_reg, newS_reg, stencil_fail_values, stencil_fail_reg);
+ modified_buffers = TRUE;
+ }
+
+ /* Same for the stencil pass/depth fail values. If this calculation
+ * is not needed (say, if depth test is off), then the
+ * stencil_pass_depth_fail_values register will be equal to fbS_reg
+ * and we'll skip the calculation.
+ */
+ if (stencil_pass_depth_fail_values != fbS_reg) {
+ /* We don't actually have a stencil pass/depth fail mask yet.
+ * Calculate it here from the stencil passing mask and the
+ * depth passing mask. Note that zmask_reg *must* have been
+ * set above if we're here.
+ */
+ uint stencil_pass_depth_fail_mask =
+ spe_allocate_available_register(f);
+
+ spe_comment(f, 0, "Loading stencil pass/depth fail values");
+ spe_andc(f, stencil_pass_depth_fail_mask, stencil_pass_reg, zmask_reg);
+
+ spe_selb(f, newS_reg, newS_reg, stencil_pass_depth_fail_values,
+ stencil_pass_depth_fail_mask);
+
+ spe_release_register(f, stencil_pass_depth_fail_mask);
+ modified_buffers = TRUE;
+ }
+
+ /* Same for the stencil pass/depth pass mask. Note that we
+ * *can* get here with zmask_reg being unset (if the depth
+ * test is off but the stencil test is on). In this case,
+ * we assume the depth test passes, and don't need to mask
+ * the stencil pass mask with the Z mask.
+ */
+ if (stencil_pass_depth_pass_values != fbS_reg) {
+ if (dsa->depth.enabled) {
+ uint stencil_pass_depth_pass_mask = spe_allocate_available_register(f);
+ /* We'll need a separate register */
+ spe_comment(f, 0, "Loading stencil pass/depth pass values");
+ spe_and(f, stencil_pass_depth_pass_mask, stencil_pass_reg, zmask_reg);
+ spe_selb(f, newS_reg, newS_reg, stencil_pass_depth_pass_values, stencil_pass_depth_pass_mask);
+ spe_release_register(f, stencil_pass_depth_pass_mask);
+ }
+ else {
+ /* We can use the same stencil-pass register */
+ spe_comment(f, 0, "Loading stencil pass values");
+ spe_selb(f, newS_reg, newS_reg, stencil_pass_depth_pass_values, stencil_pass_reg);
+ }
+ modified_buffers = TRUE;
+ }
+
+ /* Almost done. If we need to writemask, do it now, leaving the
+ * results in the fbS_reg register passed in. If we don't need
+ * to writemask, then the results are *already* in the fbS_reg,
+ * so there's nothing more to do.
+ */
+
+ if (need_to_writemask_stencil_values && modified_buffers) {
+ /* The Select Bytes command makes a fine writemask. Where
+ * the mask is 0, the first (original) values are retained,
+ * effectively masking out changes. Where the mask is 1, the
+ * second (new) values are retained, incorporating changes.
+ */
+ spe_comment(f, 0, "Writemasking new stencil values");
+ spe_selb(f, fbS_reg, fbS_reg, newS_reg, stencil_writemask_reg);
+ }
+
+ } /* done calculating stencil values */
+
+ /* The stencil and/or depth values have been applied, and the
+ * mask_reg, fbS_reg, and fbZ_reg values have been updated.
+ * We're all done, except that we've allocated a fair number
+ * of registers that we didn't bother tracking. Release all
+ * those registers as part of the register set, and go home.
+ */
+ spe_comment(f, 0, "Releasing stencil register set");
+ spe_release_register_set(f);
+
+ /* Return TRUE if we could have modified the stencil and/or
+ * depth buffers.
+ */
+ return modified_buffers;
+}
+
+
+/**
+ * Generate depth and/or stencil test code.
+ * \param cell context
+ * \param dsa depth/stencil/alpha state
+ * \param f spe function to emit
+ * \param facing either CELL_FACING_FRONT or CELL_FACING_BACK
+ * \param mask_reg register containing the pixel alive/dead mask
+ * \param depth_tile_reg register containing address of z/stencil tile
+ * \param quad_offset_reg offset to quad from start of tile
+ * \param fragZ_reg register containg fragment Z values
+ */
+static void
+gen_depth_stencil(struct cell_context *cell,
+ const struct pipe_depth_stencil_alpha_state *dsa,
+ struct spe_function *f,
+ uint facing,
+ int mask_reg,
+ int depth_tile_reg,
+ int quad_offset_reg,
+ int fragZ_reg)
+
+{
+ const enum pipe_format zs_format = cell->framebuffer.zsbuf->format;
+ boolean write_depth_stencil;
+
+ /* framebuffer's combined z/stencil values register */
+ int fbZS_reg = spe_allocate_available_register(f);
+
+ /* Framebufer Z values register */
+ int fbZ_reg = spe_allocate_available_register(f);
+
+ /* Framebuffer stencil values register (may not be used) */
+ int fbS_reg = spe_allocate_available_register(f);
+
+ /* 24-bit mask register (may not be used) */
+ int zmask_reg = spe_allocate_available_register(f);
+
+ /**
+ * The following code:
+ * 1. fetch quad of packed Z/S values from the framebuffer tile.
+ * 2. extract the separate the Z and S values from packed values
+ * 3. convert fragment Z values from float in [0,1] to 32/24/16-bit ints
+ *
+ * The instructions for doing this are interleaved for better performance.
+ */
+ spe_comment(f, 0, "Fetch Z/stencil quad from tile");
+
+ switch(zs_format) {
+ case PIPE_FORMAT_S8Z24_UNORM: /* fall through */
+ case PIPE_FORMAT_X8Z24_UNORM:
+ /* prepare mask to extract Z vals from ZS vals */
+ spe_load_uint(f, zmask_reg, 0x00ffffff);
+
+ /* convert fragment Z from [0,1] to 32-bit ints */
+ spe_cfltu(f, fragZ_reg, fragZ_reg, 32);
+
+ /* Load: fbZS_reg = memory[depth_tile_reg + offset_reg] */
+ spe_lqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg);
+
+ /* right shift 32-bit fragment Z to 24 bits */
+ spe_rotmi(f, fragZ_reg, fragZ_reg, -8);
+
+ /* extract 24-bit Z values from ZS values by masking */
+ spe_and(f, fbZ_reg, fbZS_reg, zmask_reg);
+
+ /* extract 8-bit stencil values by shifting */
+ spe_rotmi(f, fbS_reg, fbZS_reg, -24);
+ break;
+
+ case PIPE_FORMAT_Z24S8_UNORM: /* fall through */
+ case PIPE_FORMAT_Z24X8_UNORM:
+ /* convert fragment Z from [0,1] to 32-bit ints */
+ spe_cfltu(f, fragZ_reg, fragZ_reg, 32);
+
+ /* Load: fbZS_reg = memory[depth_tile_reg + offset_reg] */
+ spe_lqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg);
+
+ /* right shift 32-bit fragment Z to 24 bits */
+ spe_rotmi(f, fragZ_reg, fragZ_reg, -8);
+
+ /* extract 24-bit Z values from ZS values by shifting */
+ spe_rotmi(f, fbZ_reg, fbZS_reg, -8);
+
+ /* extract 8-bit stencil values by masking */
+ spe_and_uint(f, fbS_reg, fbZS_reg, 0x000000ff);
+ break;
+
+ case PIPE_FORMAT_Z32_UNORM:
+ /* Load: fbZ_reg = memory[depth_tile_reg + offset_reg] */
+ spe_lqx(f, fbZ_reg, depth_tile_reg, quad_offset_reg);
+
+ /* convert fragment Z from [0,1] to 32-bit ints */
+ spe_cfltu(f, fragZ_reg, fragZ_reg, 32);
+
+ /* No stencil, so can't do anything there */
+ break;
+
+ case PIPE_FORMAT_Z16_UNORM:
+ /* XXX This code for 16bpp Z is broken! */
+
+ /* Load: fbZS_reg = memory[depth_tile_reg + offset_reg] */
+ spe_lqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg);
+
+ /* Copy over 4 32-bit values */
+ spe_move(f, fbZ_reg, fbZS_reg);
+
+ /* convert Z from [0,1] to 16-bit ints */
+ spe_cfltu(f, fragZ_reg, fragZ_reg, 32);
+ spe_rotmi(f, fragZ_reg, fragZ_reg, -16);
+ /* No stencil */
+ break;
+
+ default:
+ ASSERT(0); /* invalid format */
+ }
+
+ /* If stencil is enabled, use the stencil-specific code
+ * generator to generate both the stencil and depth (if needed)
+ * tests. Otherwise, if only depth is enabled, generate
+ * a quick depth test. The test generators themselves will
+ * report back whether the depth/stencil buffer has to be
+ * written back.
+ */
+ if (dsa->stencil[0].enabled) {
+ /* This will perform the stencil and depth tests, and update
+ * the mask_reg, fbZ_reg, and fbS_reg as required by the
+ * tests.
+ */
+ ASSERT(fbS_reg >= 0);
+ spe_comment(f, 0, "Perform stencil test");
+
+ /* Note that fbZ_reg may not be set on entry, if stenciling
+ * is enabled but there's no Z-buffer. The
+ * gen_stencil_depth_test() function must ignore the
+ * fbZ_reg register if depth is not enabled.
+ */
+ write_depth_stencil = gen_stencil_depth_test(f, dsa, facing,
+ mask_reg, fragZ_reg,
+ fbZ_reg, fbS_reg);
+ }
+ else if (dsa->depth.enabled) {
+ int zmask_reg = spe_allocate_available_register(f);
+ ASSERT(fbZ_reg >= 0);
+ spe_comment(f, 0, "Perform depth test");
+ write_depth_stencil = gen_depth_test(f, dsa, mask_reg, fragZ_reg,
+ fbZ_reg, zmask_reg);
+ spe_release_register(f, zmask_reg);
+ }
+ else {
+ write_depth_stencil = FALSE;
+ }
+
+ if (write_depth_stencil) {
+ /* Merge latest Z and Stencil values into fbZS_reg.
+ * fbZ_reg has four Z vals in bits [23..0] or bits [15..0].
+ * fbS_reg has four 8-bit Z values in bits [7..0].
+ */
+ spe_comment(f, 0, "Store quad's depth/stencil values in tile");
+ if (zs_format == PIPE_FORMAT_S8Z24_UNORM ||
+ zs_format == PIPE_FORMAT_X8Z24_UNORM) {
+ spe_shli(f, fbS_reg, fbS_reg, 24); /* fbS = fbS << 24 */
+ spe_or(f, fbZS_reg, fbS_reg, fbZ_reg); /* fbZS = fbS | fbZ */
+ }
+ else if (zs_format == PIPE_FORMAT_Z24S8_UNORM ||
+ zs_format == PIPE_FORMAT_Z24X8_UNORM) {
+ spe_shli(f, fbZ_reg, fbZ_reg, 8); /* fbZ = fbZ << 8 */
+ spe_or(f, fbZS_reg, fbS_reg, fbZ_reg); /* fbZS = fbS | fbZ */
+ }
+ else if (zs_format == PIPE_FORMAT_Z32_UNORM) {
+ spe_move(f, fbZS_reg, fbZ_reg); /* fbZS = fbZ */
+ }
+ else if (zs_format == PIPE_FORMAT_Z16_UNORM) {
+ spe_move(f, fbZS_reg, fbZ_reg); /* fbZS = fbZ */
+ }
+ else if (zs_format == PIPE_FORMAT_S8_UNORM) {
+ ASSERT(0); /* XXX to do */
+ }
+ else {
+ ASSERT(0); /* bad zs_format */
+ }
+
+ /* Store: memory[depth_tile_reg + quad_offset_reg] = fbZS */
+ spe_stqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg);
+ }
+
+ /* Don't need these any more */
+ spe_release_register(f, fbZS_reg);
+ spe_release_register(f, fbZ_reg);
+ spe_release_register(f, fbS_reg);
+ spe_release_register(f, zmask_reg);
+}
+
+
+
+/**
+ * Generate SPE code to implement the fragment operations (alpha test,
+ * depth test, stencil test, blending, colormask, and final
+ * framebuffer write) as specified by the current context state.
+ *
+ * Logically, this code will be called after running the fragment
+ * shader. But under some circumstances we could run some of this
+ * code before the fragment shader to cull fragments/quads that are
+ * totally occluded/discarded.
+ *
+ * XXX we only support PIPE_FORMAT_Z24S8_UNORM z/stencil buffer right now.
+ *
+ * See the spu_default_fragment_ops() function to see how the per-fragment
+ * operations would be done with ordinary C code.
+ * The code we generate here though has no branches, is SIMD, etc and
+ * should be much faster.
+ *
+ * \param cell the rendering context (in)
+ * \param facing whether the generated code is for front-facing or
+ * back-facing fragments
+ * \param f the generated function (in/out); on input, the function
+ * must already have been initialized. On exit, whatever
+ * instructions within the generated function have had
+ * the fragment ops appended.
+ */
+void
+cell_gen_fragment_function(struct cell_context *cell,
+ const uint facing,
+ struct spe_function *f)
+{
+ const struct pipe_depth_stencil_alpha_state *dsa = cell->depth_stencil;
+ const struct pipe_blend_state *blend = cell->blend;
+ const struct pipe_blend_color *blend_color = &cell->blend_color;
+ const enum pipe_format color_format = cell->framebuffer.cbufs[0]->format;
+
+ /* For SPE function calls: reg $3 = first param, $4 = second param, etc. */
+ const int x_reg = 3; /* uint */
+ const int y_reg = 4; /* uint */
+ const int color_tile_reg = 5; /* tile_t * */
+ const int depth_tile_reg = 6; /* tile_t * */
+ const int fragZ_reg = 7; /* vector float */
+ const int fragR_reg = 8; /* vector float */
+ const int fragG_reg = 9; /* vector float */
+ const int fragB_reg = 10; /* vector float */
+ const int fragA_reg = 11; /* vector float */
+ const int mask_reg = 12; /* vector uint */
+
+ ASSERT(facing == CELL_FACING_FRONT || facing == CELL_FACING_BACK);
+
+ /* offset of quad from start of tile
+ * XXX assuming 4-byte pixels for color AND Z/stencil!!!!
+ */
+ int quad_offset_reg;
+
+ int fbRGBA_reg; /**< framebuffer's RGBA colors for quad */
+
+ if (cell->debug_flags & CELL_DEBUG_ASM) {
+ spe_print_code(f, TRUE);
+ spe_indent(f, 8);
+ spe_comment(f, -4, facing == CELL_FACING_FRONT
+ ? "Begin front-facing per-fragment ops"
+ : "Begin back-facing per-fragment ops");
+ }
+
+ spe_allocate_register(f, x_reg);
+ spe_allocate_register(f, y_reg);
+ spe_allocate_register(f, color_tile_reg);
+ spe_allocate_register(f, depth_tile_reg);
+ spe_allocate_register(f, fragZ_reg);
+ spe_allocate_register(f, fragR_reg);
+ spe_allocate_register(f, fragG_reg);
+ spe_allocate_register(f, fragB_reg);
+ spe_allocate_register(f, fragA_reg);
+ spe_allocate_register(f, mask_reg);
+
+ quad_offset_reg = spe_allocate_available_register(f);
+ fbRGBA_reg = spe_allocate_available_register(f);
+
+ /* compute offset of quad from start of tile, in bytes */
+ {
+ int x2_reg = spe_allocate_available_register(f);
+ int y2_reg = spe_allocate_available_register(f);
+
+ ASSERT(TILE_SIZE == 32);
+
+ spe_comment(f, 0, "Compute quad offset within tile");
+ spe_rotmi(f, y2_reg, y_reg, -1); /* y2 = y / 2 */
+ spe_rotmi(f, x2_reg, x_reg, -1); /* x2 = x / 2 */
+ spe_shli(f, y2_reg, y2_reg, 4); /* y2 *= 16 */
+ spe_a(f, quad_offset_reg, y2_reg, x2_reg); /* offset = y2 + x2 */
+ spe_shli(f, quad_offset_reg, quad_offset_reg, 4); /* offset *= 16 */
+
+ spe_release_register(f, x2_reg);
+ spe_release_register(f, y2_reg);
+ }
+
+ /* Generate the alpha test, if needed. */
+ if (dsa->alpha.enabled) {
+ gen_alpha_test(dsa, f, mask_reg, fragA_reg);
+ }
+
+ /* generate depth and/or stencil test code */
+ if (dsa->depth.enabled || dsa->stencil[0].enabled) {
+ gen_depth_stencil(cell, dsa, f,
+ facing,
+ mask_reg,
+ depth_tile_reg,
+ quad_offset_reg,
+ fragZ_reg);
+ }
+
+ /* Get framebuffer quad/colors. We'll need these for blending,
+ * color masking, and to obey the quad/pixel mask.
+ * Load: fbRGBA_reg = memory[color_tile + quad_offset]
+ * Note: if mask={~0,~0,~0,~0} and we're not blending or colormasking
+ * we could skip this load.
+ */
+ spe_comment(f, 0, "Fetch quad colors from tile");
+ spe_lqx(f, fbRGBA_reg, color_tile_reg, quad_offset_reg);
+
+ if (blend->blend_enable) {
+ spe_comment(f, 0, "Perform blending");
+ gen_blend(blend, blend_color, f, color_format,
+ fragR_reg, fragG_reg, fragB_reg, fragA_reg, fbRGBA_reg);
+ }
+
+ /*
+ * Write fragment colors to framebuffer/tile.
+ * This involves converting the fragment colors from float[4] to the
+ * tile's specific format and obeying the quad/pixel mask.
+ */
+ {
+ int rgba_reg = spe_allocate_available_register(f);
+
+ /* Pack four float colors as four 32-bit int colors */
+ spe_comment(f, 0, "Convert float quad colors to packed int framebuffer colors");
+ gen_pack_colors(f, color_format,
+ fragR_reg, fragG_reg, fragB_reg, fragA_reg,
+ rgba_reg);
+
+ if (blend->logicop_enable) {
+ spe_comment(f, 0, "Compute logic op");
+ gen_logicop(blend, f, rgba_reg, fbRGBA_reg);
+ }
+
+ if (blend->colormask != PIPE_MASK_RGBA) {
+ spe_comment(f, 0, "Compute color mask");
+ gen_colormask(f, blend->colormask, color_format, rgba_reg, fbRGBA_reg);
+ }
+
+ /* Mix fragment colors with framebuffer colors using the quad/pixel mask:
+ * if (mask[i])
+ * rgba[i] = rgba[i];
+ * else
+ * rgba[i] = framebuffer[i];
+ */
+ spe_selb(f, rgba_reg, fbRGBA_reg, rgba_reg, mask_reg);
+
+ /* Store updated quad in tile:
+ * memory[color_tile + quad_offset] = rgba_reg;
+ */
+ spe_comment(f, 0, "Store quad colors into color tile");
+ spe_stqx(f, rgba_reg, color_tile_reg, quad_offset_reg);
+
+ spe_release_register(f, rgba_reg);
+ }
+
+ //printf("gen_fragment_ops nr instructions: %u\n", f->num_inst);
+
+ spe_bi(f, SPE_REG_RA, 0, 0); /* return from function call */
+
+ spe_release_register(f, fbRGBA_reg);
+ spe_release_register(f, quad_offset_reg);
+
+ if (cell->debug_flags & CELL_DEBUG_ASM) {
+ char buffer[1024];
+ sprintf(buffer, "End %s-facing per-fragment ops: %d instructions",
+ facing == CELL_FACING_FRONT ? "front" : "back", f->num_inst);
+ spe_comment(f, -4, buffer);
+ }
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.h b/src/gallium/drivers/cell/ppu/cell_gen_fragment.h
new file mode 100644
index 0000000000..21b35d1faf
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_GEN_FRAGMENT_H
+#define CELL_GEN_FRAGMENT_H
+
+
+extern void
+cell_gen_fragment_function(struct cell_context *cell, const uint facing, struct spe_function *f);
+
+
+#endif /* CELL_GEN_FRAGMENT_H */
+
diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
new file mode 100644
index 0000000000..ccd0fef6e8
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
@@ -0,0 +1,407 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "util/u_memory.h"
+#include "pipe/p_inlines.h"
+#include "draw/draw_context.h"
+#include "cell_context.h"
+#include "cell_flush.h"
+#include "cell_pipe_state.h"
+#include "cell_state.h"
+#include "cell_texture.h"
+
+
+
+static void *
+cell_create_blend_state(struct pipe_context *pipe,
+ const struct pipe_blend_state *blend)
+{
+ return mem_dup(blend, sizeof(*blend));
+}
+
+
+static void
+cell_bind_blend_state(struct pipe_context *pipe, void *blend)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ draw_flush(cell->draw);
+
+ cell->blend = (struct pipe_blend_state *) blend;
+ cell->dirty |= CELL_NEW_BLEND;
+}
+
+
+static void
+cell_delete_blend_state(struct pipe_context *pipe, void *blend)
+{
+ FREE(blend);
+}
+
+
+static void
+cell_set_blend_color(struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ draw_flush(cell->draw);
+
+ cell->blend_color = *blend_color;
+
+ cell->dirty |= CELL_NEW_BLEND;
+}
+
+
+
+
+static void *
+cell_create_depth_stencil_alpha_state(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *dsa)
+{
+ return mem_dup(dsa, sizeof(*dsa));
+}
+
+
+static void
+cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe,
+ void *dsa)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ draw_flush(cell->draw);
+
+ cell->depth_stencil = (struct pipe_depth_stencil_alpha_state *) dsa;
+ cell->dirty |= CELL_NEW_DEPTH_STENCIL;
+}
+
+
+static void
+cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *dsa)
+{
+ FREE(dsa);
+}
+
+
+static void
+cell_set_clip_state(struct pipe_context *pipe,
+ const struct pipe_clip_state *clip)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ /* pass the clip state to the draw module */
+ draw_set_clip_state(cell->draw, clip);
+}
+
+
+
+/* Called when driver state tracker notices changes to the viewport
+ * matrix:
+ */
+static void
+cell_set_viewport_state( struct pipe_context *pipe,
+ const struct pipe_viewport_state *viewport )
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ cell->viewport = *viewport; /* struct copy */
+ cell->dirty |= CELL_NEW_VIEWPORT;
+
+ /* pass the viewport info to the draw module */
+ draw_set_viewport_state(cell->draw, viewport);
+
+ /* Using tnl/ and vf/ modules is temporary while getting started.
+ * Full pipe will have vertex shader, vertex fetch of its own.
+ */
+}
+
+
+static void
+cell_set_scissor_state( struct pipe_context *pipe,
+ const struct pipe_scissor_state *scissor )
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ memcpy( &cell->scissor, scissor, sizeof(*scissor) );
+ cell->dirty |= CELL_NEW_SCISSOR;
+}
+
+
+static void
+cell_set_polygon_stipple( struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple )
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ memcpy( &cell->poly_stipple, stipple, sizeof(*stipple) );
+ cell->dirty |= CELL_NEW_STIPPLE;
+}
+
+
+
+static void *
+cell_create_rasterizer_state(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *rasterizer)
+{
+ return mem_dup(rasterizer, sizeof(*rasterizer));
+}
+
+
+static void
+cell_bind_rasterizer_state(struct pipe_context *pipe, void *rast)
+{
+ struct pipe_rasterizer_state *rasterizer =
+ (struct pipe_rasterizer_state *) rast;
+ struct cell_context *cell = cell_context(pipe);
+
+ /* pass-through to draw module */
+ draw_set_rasterizer_state(cell->draw, rasterizer);
+
+ cell->rasterizer = rasterizer;
+
+ cell->dirty |= CELL_NEW_RASTERIZER;
+}
+
+
+static void
+cell_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer)
+{
+ FREE(rasterizer);
+}
+
+
+
+static void *
+cell_create_sampler_state(struct pipe_context *pipe,
+ const struct pipe_sampler_state *sampler)
+{
+ return mem_dup(sampler, sizeof(*sampler));
+}
+
+
+static void
+cell_bind_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **samplers)
+{
+ struct cell_context *cell = cell_context(pipe);
+ uint i, changed = 0x0;
+
+ assert(num <= CELL_MAX_SAMPLERS);
+
+ draw_flush(cell->draw);
+
+ for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
+ struct pipe_sampler_state *new_samp = i < num ? samplers[i] : NULL;
+ if (cell->sampler[i] != new_samp) {
+ cell->sampler[i] = new_samp;
+ changed |= (1 << i);
+ }
+ }
+
+ if (changed) {
+ cell->dirty |= CELL_NEW_SAMPLER;
+ cell->dirty_samplers |= changed;
+ }
+}
+
+
+static void
+cell_delete_sampler_state(struct pipe_context *pipe,
+ void *sampler)
+{
+ FREE( sampler );
+}
+
+
+
+static void
+cell_set_sampler_textures(struct pipe_context *pipe,
+ unsigned num, struct pipe_texture **texture)
+{
+ struct cell_context *cell = cell_context(pipe);
+ uint i, changed = 0x0;
+
+ assert(num <= CELL_MAX_SAMPLERS);
+
+ for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
+ struct cell_texture *new_tex = cell_texture(i < num ? texture[i] : NULL);
+ struct cell_texture *old_tex = cell->texture[i];
+ if (old_tex != new_tex) {
+
+ pipe_texture_reference((struct pipe_texture **) &cell->texture[i],
+ (struct pipe_texture *) new_tex);
+
+ changed |= (1 << i);
+ }
+ }
+
+ cell->num_textures = num;
+
+ if (changed) {
+ cell->dirty |= CELL_NEW_TEXTURE;
+ cell->dirty_textures |= changed;
+ }
+}
+
+
+/**
+ * Map color and z/stencil framebuffer surfaces.
+ */
+static void
+cell_map_surfaces(struct cell_context *cell)
+{
+ struct pipe_screen *screen = cell->pipe.screen;
+ uint i;
+
+ for (i = 0; i < 1; i++) {
+ struct pipe_surface *ps = cell->framebuffer.cbufs[i];
+ if (ps) {
+ struct cell_texture *ct = cell_texture(ps->texture);
+ cell->cbuf_map[i] = screen->buffer_map(screen,
+ ct->buffer,
+ (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE));
+ }
+ }
+
+ {
+ struct pipe_surface *ps = cell->framebuffer.zsbuf;
+ if (ps) {
+ struct cell_texture *ct = cell_texture(ps->texture);
+ cell->zsbuf_map = screen->buffer_map(screen,
+ ct->buffer,
+ (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE));
+ }
+ }
+}
+
+
+/**
+ * Unmap color and z/stencil framebuffer surfaces.
+ */
+static void
+cell_unmap_surfaces(struct cell_context *cell)
+{
+ struct pipe_screen *screen = cell->pipe.screen;
+ uint i;
+
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ struct pipe_surface *ps = cell->framebuffer.cbufs[i];
+ if (ps && cell->cbuf_map[i]) {
+ struct cell_texture *ct = cell_texture(ps->texture);
+ assert(ps->texture);
+ assert(ct->buffer);
+
+ screen->buffer_unmap(screen, ct->buffer);
+ cell->cbuf_map[i] = NULL;
+ }
+ }
+
+ {
+ struct pipe_surface *ps = cell->framebuffer.zsbuf;
+ if (ps && cell->zsbuf_map) {
+ struct cell_texture *ct = cell_texture(ps->texture);
+ screen->buffer_unmap(screen, ct->buffer);
+ cell->zsbuf_map = NULL;
+ }
+ }
+}
+
+
+static void
+cell_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ if (1 /*memcmp(&cell->framebuffer, fb, sizeof(*fb))*/) {
+ uint i;
+
+ /* unmap old surfaces */
+ cell_unmap_surfaces(cell);
+
+ /* Finish any pending rendering to the current surface before
+ * installing a new surface!
+ */
+ cell_flush_int(cell, CELL_FLUSH_WAIT);
+
+ /* update my state
+ * (this is also where old surfaces will finally get freed)
+ */
+ cell->framebuffer.width = fb->width;
+ cell->framebuffer.height = fb->height;
+ cell->framebuffer.nr_cbufs = fb->nr_cbufs;
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&cell->framebuffer.cbufs[i], fb->cbufs[i]);
+ }
+ pipe_surface_reference(&cell->framebuffer.zsbuf, fb->zsbuf);
+
+ /* map new surfaces */
+ cell_map_surfaces(cell);
+
+ cell->dirty |= CELL_NEW_FRAMEBUFFER;
+ }
+}
+
+
+
+void
+cell_init_state_functions(struct cell_context *cell)
+{
+ cell->pipe.create_blend_state = cell_create_blend_state;
+ cell->pipe.bind_blend_state = cell_bind_blend_state;
+ cell->pipe.delete_blend_state = cell_delete_blend_state;
+
+ cell->pipe.create_sampler_state = cell_create_sampler_state;
+ cell->pipe.bind_sampler_states = cell_bind_sampler_states;
+ cell->pipe.delete_sampler_state = cell_delete_sampler_state;
+
+ cell->pipe.set_sampler_textures = cell_set_sampler_textures;
+
+ cell->pipe.create_depth_stencil_alpha_state = cell_create_depth_stencil_alpha_state;
+ cell->pipe.bind_depth_stencil_alpha_state = cell_bind_depth_stencil_alpha_state;
+ cell->pipe.delete_depth_stencil_alpha_state = cell_delete_depth_stencil_alpha_state;
+
+ cell->pipe.create_rasterizer_state = cell_create_rasterizer_state;
+ cell->pipe.bind_rasterizer_state = cell_bind_rasterizer_state;
+ cell->pipe.delete_rasterizer_state = cell_delete_rasterizer_state;
+
+ cell->pipe.set_blend_color = cell_set_blend_color;
+ cell->pipe.set_clip_state = cell_set_clip_state;
+
+ cell->pipe.set_framebuffer_state = cell_set_framebuffer_state;
+
+ cell->pipe.set_polygon_stipple = cell_set_polygon_stipple;
+ cell->pipe.set_scissor_state = cell_set_scissor_state;
+ cell->pipe.set_viewport_state = cell_set_viewport_state;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.h b/src/gallium/drivers/cell/ppu/cell_pipe_state.h
new file mode 100644
index 0000000000..1889bd52ff
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_PIPE_STATE_H
+#define CELL_PIPE_STATE_H
+
+
+struct cell_context;
+
+extern void
+cell_init_state_functions(struct cell_context *cell);
+
+
+#endif /* CELL_PIPE_STATE_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_render.c b/src/gallium/drivers/cell/ppu/cell_render.c
new file mode 100644
index 0000000000..79cb8df82f
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_render.c
@@ -0,0 +1,211 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Last stage of 'draw' pipeline: send tris to SPUs.
+ * \author Brian Paul
+ */
+
+#include "cell_context.h"
+#include "cell_render.h"
+#include "cell_spu.h"
+#include "util/u_memory.h"
+#include "draw/draw_private.h"
+
+
+struct render_stage {
+ struct draw_stage stage; /**< This must be first (base class) */
+
+ struct cell_context *cell;
+};
+
+
+static INLINE struct render_stage *
+render_stage(struct draw_stage *stage)
+{
+ return (struct render_stage *) stage;
+}
+
+
+static void render_begin( struct draw_stage *stage )
+{
+#if 0
+ struct render_stage *render = render_stage(stage);
+ struct cell_context *sp = render->cell;
+ const struct pipe_shader_state *fs = &render->cell->fs->shader;
+ render->quad.nr_attrs = render->cell->nr_frag_attrs;
+
+ render->firstFpInput = fs->input_semantic_name[0];
+
+ sp->quad.first->begin(sp->quad.first);
+#endif
+}
+
+
+static void render_end( struct draw_stage *stage )
+{
+}
+
+
+static void reset_stipple_counter( struct draw_stage *stage )
+{
+ struct render_stage *render = render_stage(stage);
+ /*render->cell->line_stipple_counter = 0;*/
+}
+
+
+static void
+render_point(struct draw_stage *stage, struct prim_header *prim)
+{
+}
+
+
+static void
+render_line(struct draw_stage *stage, struct prim_header *prim)
+{
+}
+
+
+/** Write a vertex into the prim buffer */
+static void
+save_vertex(struct cell_prim_buffer *buf, uint pos,
+ const struct vertex_header *vert)
+{
+ uint attr, j;
+
+ for (attr = 0; attr < 2; attr++) {
+ for (j = 0; j < 4; j++) {
+ buf->vertex[pos][attr][j] = vert->data[attr][j];
+ }
+ }
+
+ /* update bounding box */
+ if (vert->data[0][0] < buf->xmin)
+ buf->xmin = vert->data[0][0];
+ if (vert->data[0][0] > buf->xmax)
+ buf->xmax = vert->data[0][0];
+ if (vert->data[0][1] < buf->ymin)
+ buf->ymin = vert->data[0][1];
+ if (vert->data[0][1] > buf->ymax)
+ buf->ymax = vert->data[0][1];
+}
+
+
+static void
+render_tri(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct render_stage *rs = render_stage(stage);
+ struct cell_context *cell = rs->cell;
+ struct cell_prim_buffer *buf = &cell->prim_buffer;
+ uint i;
+
+ if (buf->num_verts + 3 > CELL_MAX_VERTS) {
+ cell_flush_prim_buffer(cell);
+ }
+
+ i = buf->num_verts;
+ assert(i+2 <= CELL_MAX_VERTS);
+ save_vertex(buf, i+0, prim->v[0]);
+ save_vertex(buf, i+1, prim->v[1]);
+ save_vertex(buf, i+2, prim->v[2]);
+ buf->num_verts += 3;
+}
+
+
+/**
+ * Send the a RENDER command to all SPUs to have them render the prims
+ * in the current prim_buffer.
+ */
+void
+cell_flush_prim_buffer(struct cell_context *cell)
+{
+ uint i;
+
+ if (cell->prim_buffer.num_verts == 0)
+ return;
+
+ for (i = 0; i < cell->num_spus; i++) {
+ struct cell_command_render *render = &cell_global.command[i].render;
+ render->prim_type = PIPE_PRIM_TRIANGLES;
+ render->num_verts = cell->prim_buffer.num_verts;
+ render->front_winding = cell->rasterizer->front_winding;
+ render->vertex_size = cell->vertex_info->size * 4;
+ render->xmin = cell->prim_buffer.xmin;
+ render->ymin = cell->prim_buffer.ymin;
+ render->xmax = cell->prim_buffer.xmax;
+ render->ymax = cell->prim_buffer.ymax;
+ render->vertex_data = &cell->prim_buffer.vertex;
+ ASSERT_ALIGN16(render->vertex_data);
+ send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_RENDER);
+ }
+
+ cell->prim_buffer.num_verts = 0;
+
+ cell->prim_buffer.xmin = 1e100;
+ cell->prim_buffer.ymin = 1e100;
+ cell->prim_buffer.xmax = -1e100;
+ cell->prim_buffer.ymax = -1e100;
+
+ /* XXX temporary, need to double-buffer the prim buffer until we get
+ * a real command buffer/list system.
+ */
+ cell_flush(&cell->pipe, 0x0);
+}
+
+
+
+static void render_destroy( struct draw_stage *stage )
+{
+ FREE( stage );
+}
+
+
+/**
+ * Create a new draw/render stage. This will be plugged into the
+ * draw module as the last pipeline stage.
+ */
+struct draw_stage *cell_draw_render_stage( struct cell_context *cell )
+{
+ struct render_stage *render = CALLOC_STRUCT(render_stage);
+
+ render->cell = cell;
+ render->stage.draw = cell->draw;
+ render->stage.begin = render_begin;
+ render->stage.point = render_point;
+ render->stage.line = render_line;
+ render->stage.tri = render_tri;
+ render->stage.end = render_end;
+ render->stage.reset_stipple_counter = reset_stipple_counter;
+ render->stage.destroy = render_destroy;
+
+ /*
+ render->quad.coef = render->coef;
+ render->quad.posCoef = &render->posCoef;
+ */
+
+ return &render->stage;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_render.h b/src/gallium/drivers/cell/ppu/cell_render.h
new file mode 100644
index 0000000000..826dcbafeb
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_render.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef CELL_RENDER_H
+#define CELL_RENDER_H
+
+struct cell_context;
+struct draw_stage;
+
+extern void
+cell_flush_prim_buffer(struct cell_context *cell);
+
+extern struct draw_stage *cell_draw_render_stage( struct cell_context *cell );
+
+#endif /* CELL_RENDER_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_screen.c b/src/gallium/drivers/cell/ppu/cell_screen.c
new file mode 100644
index 0000000000..bd48ce7005
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_screen.c
@@ -0,0 +1,178 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "util/u_simple_screen.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+
+#include "cell/common.h"
+#include "cell_screen.h"
+#include "cell_texture.h"
+#include "cell_winsys.h"
+
+
+static const char *
+cell_get_vendor(struct pipe_screen *screen)
+{
+ return "Tungsten Graphics, Inc.";
+}
+
+
+static const char *
+cell_get_name(struct pipe_screen *screen)
+{
+ return "Cell";
+}
+
+
+static int
+cell_get_param(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return CELL_MAX_SAMPLERS;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 1;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 1;
+ case PIPE_CAP_GLSL:
+ return 1;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 0;
+ case PIPE_CAP_POINT_SPRITE:
+ return 1;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 1;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 1;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 10;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return CELL_MAX_TEXTURE_LEVELS;
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 8; /* max 128x128x128 */
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return CELL_MAX_TEXTURE_LEVELS;
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1; /* XXX not really true */
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ return 0; /* XXX to do */
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+static float
+cell_get_paramf(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 255.0; /* arbitrary */
+
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 255.0; /* arbitrary */
+
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 0.0;
+
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 16.0; /* arbitrary */
+
+ default:
+ return 0;
+ }
+}
+
+
+static boolean
+cell_is_format_supported( struct pipe_screen *screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags )
+{
+ /* cell supports most formats, XXX for now anyway */
+ if (format == PIPE_FORMAT_DXT5_RGBA ||
+ format == PIPE_FORMAT_R8G8B8A8_SRGB)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+
+static void
+cell_destroy_screen( struct pipe_screen *screen )
+{
+ struct pipe_winsys *winsys = screen->winsys;
+
+ if(winsys->destroy)
+ winsys->destroy(winsys);
+
+ FREE(screen);
+}
+
+
+/**
+ * Create a new pipe_screen object
+ * Note: we're not presently subclassing pipe_screen (no cell_screen) but
+ * that would be the place to put SPU thread/context info...
+ */
+struct pipe_screen *
+cell_create_screen(struct pipe_winsys *winsys)
+{
+ struct pipe_screen *screen = CALLOC_STRUCT(pipe_screen);
+
+ if (!screen)
+ return NULL;
+
+ screen->winsys = winsys;
+
+ screen->destroy = cell_destroy_screen;
+
+ screen->get_name = cell_get_name;
+ screen->get_vendor = cell_get_vendor;
+ screen->get_param = cell_get_param;
+ screen->get_paramf = cell_get_paramf;
+ screen->is_format_supported = cell_is_format_supported;
+
+ cell_init_screen_texture_funcs(screen);
+ u_simple_screen_init(screen);
+
+ return screen;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_screen.h b/src/gallium/drivers/cell/ppu/cell_screen.h
new file mode 100644
index 0000000000..c7e15889d6
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_screen.h
@@ -0,0 +1,41 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_SCREEN_H
+#define CELL_SCREEN_H
+
+
+struct pipe_screen;
+struct pipe_winsys;
+
+
+extern struct pipe_screen *
+cell_create_screen(struct pipe_winsys *winsys);
+
+
+#endif /* CELL_SCREEN_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_spu.c b/src/gallium/drivers/cell/ppu/cell_spu.c
new file mode 100644
index 0000000000..28e5e6d706
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_spu.c
@@ -0,0 +1,219 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Utility/wrappers for communicating with the SPUs.
+ */
+
+
+#include <pthread.h>
+
+#include "cell_spu.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+#include "util/u_memory.h"
+#include "cell/common.h"
+
+
+/*
+helpful headers:
+/opt/ibm/cell-sdk/prototype/src/include/ppu/cbe_mfc.h
+*/
+
+
+/**
+ * Cell/SPU info that's not per-context.
+ */
+struct cell_global_info cell_global;
+
+
+/**
+ * Scan /proc/cpuinfo to determine the timebase for the system.
+ * This is used by the SPUs to convert 'decrementer' ticks to seconds.
+ * There may be a better way to get this value...
+ */
+static unsigned
+get_timebase(void)
+{
+ FILE *f = fopen("/proc/cpuinfo", "r");
+ unsigned timebase;
+
+ assert(f);
+ while (!feof(f)) {
+ char line[80];
+ fgets(line, sizeof(line), f);
+ if (strncmp(line, "timebase", 8) == 0) {
+ char *colon = strchr(line, ':');
+ if (colon) {
+ timebase = atoi(colon + 2);
+ break;
+ }
+ }
+ }
+ fclose(f);
+
+ return timebase;
+}
+
+
+/**
+ * Write a 1-word message to the given SPE mailbox.
+ */
+void
+send_mbox_message(spe_context_ptr_t ctx, unsigned int msg)
+{
+ spe_in_mbox_write(ctx, &msg, 1, SPE_MBOX_ALL_BLOCKING);
+}
+
+
+/**
+ * Wait for a 1-word message to arrive in given mailbox.
+ */
+uint
+wait_mbox_message(spe_context_ptr_t ctx)
+{
+ do {
+ unsigned data;
+ int count = spe_out_mbox_read(ctx, &data, 1);
+
+ if (count == 1) {
+ return data;
+ }
+
+ if (count < 0) {
+ /* error */ ;
+ }
+ } while (1);
+}
+
+
+/**
+ * Called by pthread_create() to spawn an SPU thread.
+ */
+static void *
+cell_thread_function(void *arg)
+{
+ struct cell_init_info *init = (struct cell_init_info *) arg;
+ unsigned entry = SPE_DEFAULT_ENTRY;
+
+ ASSERT_ALIGN16(init);
+
+ if (spe_context_run(cell_global.spe_contexts[init->id], &entry, 0,
+ init, NULL, NULL) < 0) {
+ fprintf(stderr, "spe_context_run() failed\n");
+ exit(1);
+ }
+
+ pthread_exit(NULL);
+}
+
+
+/**
+ * Create the SPU threads. This is done once during driver initialization.
+ * This involves setting the the "init" message which is sent to each SPU.
+ * The init message specifies an SPU id, total number of SPUs, location
+ * and number of batch buffers, etc.
+ */
+void
+cell_start_spus(struct cell_context *cell)
+{
+ static boolean one_time_init = FALSE;
+ uint i, j;
+ uint timebase = get_timebase();
+
+ if (one_time_init) {
+ fprintf(stderr, "PPU: Multiple rendering contexts not yet supported "
+ "on Cell.\n");
+ abort();
+ }
+
+ one_time_init = TRUE;
+
+ assert(cell->num_spus <= CELL_MAX_SPUS);
+
+ ASSERT_ALIGN16(&cell_global.inits[0]);
+ ASSERT_ALIGN16(&cell_global.inits[1]);
+
+ /*
+ * Initialize the global 'inits' structure for each SPU.
+ * A pointer to the init struct will be passed to each SPU.
+ * The SPUs will then each grab their init info with mfc_get().
+ */
+ for (i = 0; i < cell->num_spus; i++) {
+ cell_global.inits[i].id = i;
+ cell_global.inits[i].num_spus = cell->num_spus;
+ cell_global.inits[i].debug_flags = cell->debug_flags;
+ cell_global.inits[i].inv_timebase = 1000.0f / timebase;
+
+ for (j = 0; j < CELL_NUM_BUFFERS; j++) {
+ cell_global.inits[i].buffers[j] = cell->buffer[j];
+ }
+ cell_global.inits[i].buffer_status = &cell->buffer_status[0][0][0];
+
+ cell_global.inits[i].spu_functions = &cell->spu_functions;
+
+ cell_global.spe_contexts[i] = spe_context_create(0, NULL);
+ if (!cell_global.spe_contexts[i]) {
+ fprintf(stderr, "spe_context_create() failed\n");
+ exit(1);
+ }
+
+ if (spe_program_load(cell_global.spe_contexts[i], &g3d_spu)) {
+ fprintf(stderr, "spe_program_load() failed\n");
+ exit(1);
+ }
+
+ pthread_create(&cell_global.spe_threads[i], /* returned thread handle */
+ NULL, /* pthread attribs */
+ &cell_thread_function, /* start routine */
+ &cell_global.inits[i]); /* thread argument */
+ }
+}
+
+
+/**
+ * Tell all the SPUs to stop/exit.
+ * This is done when the driver's exiting / cleaning up.
+ */
+void
+cell_spu_exit(struct cell_context *cell)
+{
+ uint i;
+
+ for (i = 0; i < cell->num_spus; i++) {
+ send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_EXIT);
+ }
+
+ /* wait for threads to exit */
+ for (i = 0; i < cell->num_spus; i++) {
+ void *value;
+ pthread_join(cell_global.spe_threads[i], &value);
+ cell_global.spe_threads[i] = 0;
+ cell_global.spe_contexts[i] = 0;
+ }
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_spu.h b/src/gallium/drivers/cell/ppu/cell_spu.h
new file mode 100644
index 0000000000..c93958a9ed
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_spu.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef CELL_SPU
+#define CELL_SPU
+
+
+#include <libspe2.h>
+#include <pthread.h>
+#include "cell/common.h"
+
+#include "cell_context.h"
+
+
+/**
+ * Global vars, for now anyway.
+ */
+struct cell_global_info
+{
+ /**
+ * SPU/SPE handles, etc
+ */
+ spe_context_ptr_t spe_contexts[CELL_MAX_SPUS];
+ pthread_t spe_threads[CELL_MAX_SPUS];
+
+ /**
+ * Data sent to SPUs at start-up
+ */
+ struct cell_init_info inits[CELL_MAX_SPUS];
+};
+
+
+extern struct cell_global_info cell_global;
+
+
+/** This is the handle for the actual SPE code */
+extern spe_program_handle_t g3d_spu;
+
+
+extern void
+send_mbox_message(spe_context_ptr_t ctx, unsigned int msg);
+
+extern uint
+wait_mbox_message(spe_context_ptr_t ctx);
+
+
+extern void
+cell_start_spus(struct cell_context *cell);
+
+
+extern void
+cell_spu_exit(struct cell_context *cell);
+
+
+#endif /* CELL_SPU */
diff --git a/src/gallium/drivers/cell/ppu/cell_state.h b/src/gallium/drivers/cell/ppu/cell_state.h
new file mode 100644
index 0000000000..b193170f9c
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_state.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_STATE_H
+#define CELL_STATE_H
+
+
+#define CELL_NEW_VIEWPORT 0x1
+#define CELL_NEW_RASTERIZER 0x2
+#define CELL_NEW_FS 0x4
+#define CELL_NEW_BLEND 0x8
+#define CELL_NEW_CLIP 0x10
+#define CELL_NEW_SCISSOR 0x20
+#define CELL_NEW_STIPPLE 0x40
+#define CELL_NEW_FRAMEBUFFER 0x80
+#define CELL_NEW_ALPHA_TEST 0x100
+#define CELL_NEW_DEPTH_STENCIL 0x200
+#define CELL_NEW_SAMPLER 0x400
+#define CELL_NEW_TEXTURE 0x800
+#define CELL_NEW_VERTEX 0x1000
+#define CELL_NEW_VS 0x2000
+#define CELL_NEW_VS_CONSTANTS 0x4000
+#define CELL_NEW_FS_CONSTANTS 0x8000
+#define CELL_NEW_VERTEX_INFO 0x10000
+
+
+extern void
+cell_update_derived( struct cell_context *softpipe );
+
+
+extern void
+cell_init_shader_functions(struct cell_context *cell);
+
+
+extern void
+cell_init_vertex_functions(struct cell_context *cell);
+
+
+#endif /* CELL_STATE_H */
+
diff --git a/src/gallium/drivers/cell/ppu/cell_state_derived.c b/src/gallium/drivers/cell/ppu/cell_state_derived.c
new file mode 100644
index 0000000000..efc4f78364
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_state_derived.c
@@ -0,0 +1,170 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "draw/draw_vertex.h"
+#include "cell_context.h"
+#include "cell_batch.h"
+#include "cell_state.h"
+#include "cell_state_emit.h"
+
+
+/**
+ * Determine how to map vertex program outputs to fragment program inputs.
+ * Basically, this will be used when computing the triangle interpolation
+ * coefficients from the post-transform vertex attributes.
+ */
+static void
+calculate_vertex_layout( struct cell_context *cell )
+{
+ const struct cell_fragment_shader_state *fs = cell->fs;
+ const enum interp_mode colorInterp
+ = cell->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
+ struct vertex_info *vinfo = &cell->vertex_info;
+ uint i;
+ int src;
+
+#if 0
+ if (cell->vbuf) {
+ /* if using the post-transform vertex buffer, tell draw_vbuf to
+ * simply emit the whole post-xform vertex as-is:
+ */
+ struct vertex_info *vinfo_vbuf = &cell->vertex_info_vbuf;
+ vinfo_vbuf->num_attribs = 0;
+ draw_emit_vertex_attr(vinfo_vbuf, EMIT_ALL, INTERP_NONE, 0);
+ vinfo_vbuf->size = 4 * vs->num_outputs + sizeof(struct vertex_header)/4;
+ }
+#endif
+
+ /* reset vinfo */
+ vinfo->num_attribs = 0;
+
+ /* we always want to emit vertex pos */
+ src = draw_find_vs_output(cell->draw, TGSI_SEMANTIC_POSITION, 0);
+ assert(src >= 0);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_POS, src);
+
+
+ /*
+ * Loop over fragment shader inputs, searching for the matching output
+ * from the vertex shader.
+ */
+ for (i = 0; i < fs->info.num_inputs; i++) {
+ switch (fs->info.input_semantic_name[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ /* already done above */
+ break;
+
+ case TGSI_SEMANTIC_COLOR:
+ src = draw_find_vs_output(cell->draw, TGSI_SEMANTIC_COLOR,
+ fs->info.input_semantic_index[i]);
+ assert(src >= 0);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
+ break;
+
+ case TGSI_SEMANTIC_FOG:
+ src = draw_find_vs_output(cell->draw, TGSI_SEMANTIC_FOG, 0);
+#if 1
+ if (src < 0) /* XXX temp hack, try demos/fogcoord.c with this */
+ src = 0;
+#endif
+ assert(src >= 0);
+ draw_emit_vertex_attr(vinfo, EMIT_1F, INTERP_PERSPECTIVE, src);
+ break;
+
+ case TGSI_SEMANTIC_GENERIC:
+ /* this includes texcoords and varying vars */
+ src = draw_find_vs_output(cell->draw, TGSI_SEMANTIC_GENERIC,
+ fs->info.input_semantic_index[i]);
+ assert(src >= 0);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ break;
+
+ default:
+ assert(0);
+ }
+ }
+
+ draw_compute_vertex_size(vinfo);
+
+ /* XXX only signal this if format really changes */
+ cell->dirty |= CELL_NEW_VERTEX_INFO;
+}
+
+
+#if 0
+/**
+ * Recompute cliprect from scissor bounds, scissor enable and surface size.
+ */
+static void
+compute_cliprect(struct cell_context *sp)
+{
+ uint surfWidth = sp->framebuffer.width;
+ uint surfHeight = sp->framebuffer.height;
+
+ if (sp->rasterizer->scissor) {
+ /* clip to scissor rect */
+ sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
+ sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
+ sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
+ sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
+ }
+ else {
+ /* clip to surface bounds */
+ sp->cliprect.minx = 0;
+ sp->cliprect.miny = 0;
+ sp->cliprect.maxx = surfWidth;
+ sp->cliprect.maxy = surfHeight;
+ }
+}
+#endif
+
+
+
+/**
+ * Update derived state, send current state to SPUs prior to rendering.
+ */
+void cell_update_derived( struct cell_context *cell )
+{
+ if (cell->dirty & (CELL_NEW_RASTERIZER |
+ CELL_NEW_FS |
+ CELL_NEW_VS))
+ calculate_vertex_layout( cell );
+
+#if 0
+ if (cell->dirty & (CELL_NEW_SCISSOR |
+ CELL_NEW_DEPTH_STENCIL_ALPHA |
+ CELL_NEW_FRAMEBUFFER))
+ compute_cliprect(cell);
+#endif
+
+ cell_emit_state(cell);
+
+ cell->dirty = 0;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c
new file mode 100644
index 0000000000..9479c0898f
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c
@@ -0,0 +1,344 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+#include "cell_context.h"
+#include "cell_gen_fragment.h"
+#include "cell_state.h"
+#include "cell_state_emit.h"
+#include "cell_batch.h"
+#include "cell_texture.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+
+
+/**
+ * Find/create a cell_command_fragment_ops object corresponding to the
+ * current blend/stencil/z/colormask/etc. state.
+ */
+static struct cell_command_fragment_ops *
+lookup_fragment_ops(struct cell_context *cell)
+{
+ struct cell_fragment_ops_key key;
+ struct cell_command_fragment_ops *ops;
+
+ /*
+ * Build key
+ */
+ memset(&key, 0, sizeof(key));
+ key.blend = *cell->blend;
+ key.blend_color = cell->blend_color;
+ key.dsa = *cell->depth_stencil;
+
+ if (cell->framebuffer.cbufs[0])
+ key.color_format = cell->framebuffer.cbufs[0]->format;
+ else
+ key.color_format = PIPE_FORMAT_NONE;
+
+ if (cell->framebuffer.zsbuf)
+ key.zs_format = cell->framebuffer.zsbuf->format;
+ else
+ key.zs_format = PIPE_FORMAT_NONE;
+
+ /*
+ * Look up key in cache.
+ */
+ ops = (struct cell_command_fragment_ops *)
+ util_keymap_lookup(cell->fragment_ops_cache, &key);
+
+ /*
+ * If not found, create/save new fragment ops command.
+ */
+ if (!ops) {
+ struct spe_function spe_code_front, spe_code_back;
+ unsigned int facing_dependent, total_code_size;
+
+ if (0)
+ debug_printf("**** Create New Fragment Ops\n");
+
+ /* Prepare the buffer that will hold the generated code. The
+ * "0" passed in for the size means that the SPE code will
+ * use a default size.
+ */
+ spe_init_func(&spe_code_front, 0);
+ spe_init_func(&spe_code_back, 0);
+
+ /* Generate new code. Always generate new code for both front-facing
+ * and back-facing fragments, even if it's the same code in both
+ * cases.
+ */
+ cell_gen_fragment_function(cell, CELL_FACING_FRONT, &spe_code_front);
+ cell_gen_fragment_function(cell, CELL_FACING_BACK, &spe_code_back);
+
+ /* Make sure the code is a multiple of 8 bytes long; this is
+ * required to ensure that the dual pipe instruction alignment
+ * is correct. It's also important for the SPU unpacking,
+ * which assumes 8-byte boundaries.
+ */
+ unsigned int front_code_size = spe_code_size(&spe_code_front);
+ while (front_code_size % 8 != 0) {
+ spe_lnop(&spe_code_front);
+ front_code_size = spe_code_size(&spe_code_front);
+ }
+ unsigned int back_code_size = spe_code_size(&spe_code_back);
+ while (back_code_size % 8 != 0) {
+ spe_lnop(&spe_code_back);
+ back_code_size = spe_code_size(&spe_code_back);
+ }
+
+ /* Determine whether the code we generated is facing-dependent, by
+ * determining whether the generated code is different for the front-
+ * and back-facing fragments.
+ */
+ if (front_code_size == back_code_size && memcmp(spe_code_front.store, spe_code_back.store, front_code_size) == 0) {
+ /* Code is identical; only need one copy. */
+ facing_dependent = 0;
+ total_code_size = front_code_size;
+ }
+ else {
+ /* Code is different for front-facing and back-facing fragments.
+ * Need to send both copies.
+ */
+ facing_dependent = 1;
+ total_code_size = front_code_size + back_code_size;
+ }
+
+ /* alloc new fragment ops command. Note that this structure
+ * has variant length based on the total code size required.
+ */
+ ops = CALLOC_VARIANT_LENGTH_STRUCT(cell_command_fragment_ops, total_code_size);
+ /* populate the new cell_command_fragment_ops object */
+ ops->opcode[0] = CELL_CMD_STATE_FRAGMENT_OPS;
+ ops->total_code_size = total_code_size;
+ ops->front_code_index = 0;
+ memcpy(ops->code, spe_code_front.store, front_code_size);
+ if (facing_dependent) {
+ /* We have separate front- and back-facing code. Append the
+ * back-facing code to the buffer. Be careful because the code
+ * size is in bytes, but the buffer is of unsigned elements.
+ */
+ ops->back_code_index = front_code_size / sizeof(spe_code_front.store[0]);
+ memcpy(ops->code + ops->back_code_index, spe_code_back.store, back_code_size);
+ }
+ else {
+ /* Use the same code for front- and back-facing fragments */
+ ops->back_code_index = ops->front_code_index;
+ }
+
+ /* Set the fields for the fallback case. Note that these fields
+ * (and the whole fallback case) will eventually go away.
+ */
+ ops->dsa = *cell->depth_stencil;
+ ops->blend = *cell->blend;
+ ops->blend_color = cell->blend_color;
+
+ /* insert cell_command_fragment_ops object into keymap/cache */
+ util_keymap_insert(cell->fragment_ops_cache, &key, ops, NULL);
+
+ /* release rtasm buffer */
+ spe_release_func(&spe_code_front);
+ spe_release_func(&spe_code_back);
+ }
+ else {
+ if (0)
+ debug_printf("**** Re-use Fragment Ops\n");
+ }
+
+ return ops;
+}
+
+
+
+static void
+emit_state_cmd(struct cell_context *cell, uint cmd,
+ const void *state, uint state_size)
+{
+ uint32_t *dst = (uint32_t *)
+ cell_batch_alloc16(cell, ROUNDUP16(sizeof(opcode_t) + state_size));
+ *dst = cmd;
+ memcpy(dst + 4, state, state_size);
+}
+
+
+/**
+ * For state marked as 'dirty', construct a state-update command block
+ * and insert it into the current batch buffer.
+ */
+void
+cell_emit_state(struct cell_context *cell)
+{
+ if (cell->dirty & CELL_NEW_FRAMEBUFFER) {
+ struct pipe_surface *cbuf = cell->framebuffer.cbufs[0];
+ struct pipe_surface *zbuf = cell->framebuffer.zsbuf;
+ STATIC_ASSERT(sizeof(struct cell_command_framebuffer) % 16 == 0);
+ struct cell_command_framebuffer *fb
+ = cell_batch_alloc16(cell, sizeof(*fb));
+ fb->opcode[0] = CELL_CMD_STATE_FRAMEBUFFER;
+ fb->color_start = cell->cbuf_map[0];
+ fb->color_format = cbuf->format;
+ fb->depth_start = cell->zsbuf_map;
+ fb->depth_format = zbuf ? zbuf->format : PIPE_FORMAT_NONE;
+ fb->width = cell->framebuffer.width;
+ fb->height = cell->framebuffer.height;
+#if 0
+ printf("EMIT color format %s\n", pf_name(fb->color_format));
+ printf("EMIT depth format %s\n", pf_name(fb->depth_format));
+#endif
+ }
+
+ if (cell->dirty & (CELL_NEW_RASTERIZER)) {
+ STATIC_ASSERT(sizeof(struct cell_command_rasterizer) % 16 == 0);
+ struct cell_command_rasterizer *rast =
+ cell_batch_alloc16(cell, sizeof(*rast));
+ rast->opcode[0] = CELL_CMD_STATE_RASTERIZER;
+ rast->rasterizer = *cell->rasterizer;
+ }
+
+ if (cell->dirty & (CELL_NEW_FS)) {
+ /* Send new fragment program to SPUs */
+ STATIC_ASSERT(sizeof(struct cell_command_fragment_program) % 16 == 0);
+ struct cell_command_fragment_program *fp
+ = cell_batch_alloc16(cell, sizeof(*fp));
+ fp->opcode[0] = CELL_CMD_STATE_FRAGMENT_PROGRAM;
+ fp->num_inst = cell->fs->code.num_inst;
+ memcpy(&fp->code, cell->fs->code.store,
+ SPU_MAX_FRAGMENT_PROGRAM_INSTS * SPE_INST_SIZE);
+ if (0) {
+ int i;
+ printf("PPU Emit CELL_CMD_STATE_FRAGMENT_PROGRAM:\n");
+ for (i = 0; i < fp->num_inst; i++) {
+ printf(" %3d: 0x%08x\n", i, fp->code[i]);
+ }
+ }
+ }
+
+ if (cell->dirty & (CELL_NEW_FS_CONSTANTS)) {
+ const uint shader = PIPE_SHADER_FRAGMENT;
+ const uint num_const = cell->constants[shader].buffer->size / sizeof(float);
+ uint i, j;
+ float *buf = cell_batch_alloc16(cell, ROUNDUP16(32 + num_const * sizeof(float)));
+ uint32_t *ibuf = (uint32_t *) buf;
+ const float *constants = pipe_buffer_map(cell->pipe.screen,
+ cell->constants[shader].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ ibuf[0] = CELL_CMD_STATE_FS_CONSTANTS;
+ ibuf[4] = num_const;
+ j = 8;
+ for (i = 0; i < num_const; i++) {
+ buf[j++] = constants[i];
+ }
+ pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader].buffer);
+ }
+
+ if (cell->dirty & (CELL_NEW_FRAMEBUFFER |
+ CELL_NEW_DEPTH_STENCIL |
+ CELL_NEW_BLEND)) {
+ struct cell_command_fragment_ops *fops, *fops_cmd;
+ /* Note that cell_command_fragment_ops is a variant-sized record */
+ fops = lookup_fragment_ops(cell);
+ fops_cmd = cell_batch_alloc16(cell, ROUNDUP16(sizeof(*fops_cmd) + fops->total_code_size));
+ memcpy(fops_cmd, fops, sizeof(*fops) + fops->total_code_size);
+ }
+
+ if (cell->dirty & CELL_NEW_SAMPLER) {
+ uint i;
+ for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
+ if (cell->dirty_samplers & (1 << i)) {
+ if (cell->sampler[i]) {
+ STATIC_ASSERT(sizeof(struct cell_command_sampler) % 16 == 0);
+ struct cell_command_sampler *sampler
+ = cell_batch_alloc16(cell, sizeof(*sampler));
+ sampler->opcode[0] = CELL_CMD_STATE_SAMPLER;
+ sampler->unit = i;
+ sampler->state = *cell->sampler[i];
+ }
+ }
+ }
+ cell->dirty_samplers = 0x0;
+ }
+
+ if (cell->dirty & CELL_NEW_TEXTURE) {
+ uint i;
+ for (i = 0;i < CELL_MAX_SAMPLERS; i++) {
+ if (cell->dirty_textures & (1 << i)) {
+ STATIC_ASSERT(sizeof(struct cell_command_texture) % 16 == 0);
+ struct cell_command_texture *texture =
+ (struct cell_command_texture *)
+ cell_batch_alloc16(cell, sizeof(*texture));
+
+ texture->opcode[0] = CELL_CMD_STATE_TEXTURE;
+ texture->unit = i;
+ if (cell->texture[i]) {
+ struct cell_texture *ct = cell->texture[i];
+ uint level;
+ for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
+ texture->start[level] = (ct->mapped +
+ ct->level_offset[level]);
+ texture->width[level] = ct->base.width[level];
+ texture->height[level] = ct->base.height[level];
+ texture->depth[level] = ct->base.depth[level];
+ }
+ texture->target = ct->base.target;
+ }
+ else {
+ uint level;
+ for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
+ texture->start[level] = NULL;
+ texture->width[level] = 0;
+ texture->height[level] = 0;
+ texture->depth[level] = 0;
+ }
+ texture->target = 0;
+ }
+ }
+ }
+ cell->dirty_textures = 0x0;
+ }
+
+ if (cell->dirty & CELL_NEW_VERTEX_INFO) {
+ emit_state_cmd(cell, CELL_CMD_STATE_VERTEX_INFO,
+ &cell->vertex_info, sizeof(struct vertex_info));
+ }
+
+#if 0
+ if (cell->dirty & CELL_NEW_VS) {
+ const struct draw_context *const draw = cell->draw;
+ struct cell_shader_info info;
+
+ info.num_outputs = draw_num_vs_outputs(draw);
+ info.declarations = (uintptr_t) draw->vs.machine.Declarations;
+ info.num_declarations = draw->vs.machine.NumDeclarations;
+ info.instructions = (uintptr_t) draw->vs.machine.Instructions;
+ info.num_instructions = draw->vs.machine.NumInstructions;
+ info.immediates = (uintptr_t) draw->vs.machine.Imms;
+ info.num_immediates = draw->vs.machine.ImmLimit / 4;
+
+ emit_state_cmd(cell, CELL_CMD_STATE_BIND_VS, &info, sizeof(info));
+ }
+#endif
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.h b/src/gallium/drivers/cell/ppu/cell_state_emit.h
new file mode 100644
index 0000000000..59f8affe8d
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_state_emit.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef CELL_STATE_EMIT_H
+#define CELL_STATE_EMIT_H
+
+
+extern void
+cell_emit_state(struct cell_context *cell);
+
+
+#endif /* CELL_STATE_EMIT_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c
new file mode 100644
index 0000000000..d97c22b2ef
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c
@@ -0,0 +1,1430 @@
+/*
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file
+ * Generate code to perform all per-fragment operations.
+ *
+ * Code generated by these functions perform both alpha, depth, and stencil
+ * testing as well as alpha blending.
+ *
+ * \note
+ * Occlusion query is not supported, but this is the right place to add that
+ * support.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "cell_context.h"
+
+#include "rtasm/rtasm_ppc_spe.h"
+
+
+/**
+ * Generate code to perform alpha testing.
+ *
+ * The code generated by this function uses the register specificed by
+ * \c mask as both an input and an output.
+ *
+ * \param dsa Current alpha-test state
+ * \param f Function to which code should be appended
+ * \param mask Index of register containing active fragment mask
+ * \param alphas Index of register containing per-fragment alpha values
+ *
+ * \note Emits a maximum of 6 instructions.
+ */
+static void
+emit_alpha_test(struct pipe_depth_stencil_alpha_state *dsa,
+ struct spe_function *f, int mask, int alphas)
+{
+ /* If the alpha function is either NEVER or ALWAYS, there is no need to
+ * load the reference value into a register. ALWAYS is a fairly common
+ * case, and this optimization saves 2 instructions.
+ */
+ if (dsa->alpha.enabled
+ && (dsa->alpha.func != PIPE_FUNC_NEVER)
+ && (dsa->alpha.func != PIPE_FUNC_ALWAYS)) {
+ int ref = spe_allocate_available_register(f);
+ int tmp_a = spe_allocate_available_register(f);
+ int tmp_b = spe_allocate_available_register(f);
+ union {
+ float f;
+ unsigned u;
+ } ref_val;
+ boolean complement = FALSE;
+
+ ref_val.f = dsa->alpha.ref;
+
+ spe_il(f, ref, ref_val.u & 0x0000ffff);
+ spe_ilh(f, ref, ref_val.u >> 16);
+
+ switch (dsa->alpha.func) {
+ case PIPE_FUNC_NOTEQUAL:
+ complement = TRUE;
+ /* FALLTHROUGH */
+
+ case PIPE_FUNC_EQUAL:
+ spe_fceq(f, tmp_a, ref, alphas);
+ break;
+
+ case PIPE_FUNC_LEQUAL:
+ complement = TRUE;
+ /* FALLTHROUGH */
+
+ case PIPE_FUNC_GREATER:
+ spe_fcgt(f, tmp_a, ref, alphas);
+ break;
+
+ case PIPE_FUNC_LESS:
+ complement = TRUE;
+ /* FALLTHROUGH */
+
+ case PIPE_FUNC_GEQUAL:
+ spe_fcgt(f, tmp_a, ref, alphas);
+ spe_fceq(f, tmp_b, ref, alphas);
+ spe_or(f, tmp_a, tmp_b, tmp_a);
+ break;
+
+ case PIPE_FUNC_ALWAYS:
+ case PIPE_FUNC_NEVER:
+ default:
+ assert(0);
+ break;
+ }
+
+ if (complement) {
+ spe_andc(f, mask, mask, tmp_a);
+ } else {
+ spe_and(f, mask, mask, tmp_a);
+ }
+
+ spe_release_register(f, ref);
+ spe_release_register(f, tmp_a);
+ spe_release_register(f, tmp_b);
+ } else if (dsa->alpha.enabled && (dsa->alpha.func == PIPE_FUNC_NEVER)) {
+ spe_il(f, mask, 0);
+ }
+}
+
+
+/**
+ * Generate code to perform Z testing. Four Z values are tested at once.
+ * \param dsa Current depth-test state
+ * \param f Function to which code should be appended
+ * \param mask Index of register to contain depth-pass mask
+ * \param stored Index of register containing values from depth buffer
+ * \param calculated Index of register containing per-fragment depth values
+ *
+ * \return
+ * If the calculated depth comparison mask is the actual mask, \c FALSE is
+ * returned. If the calculated depth comparison mask is the compliment of
+ * the actual mask, \c TRUE is returned.
+ *
+ * \note Emits a maximum of 3 instructions.
+ */
+static boolean
+emit_depth_test(struct pipe_depth_stencil_alpha_state *dsa,
+ struct spe_function *f, int mask, int stored, int calculated)
+{
+ unsigned func = (dsa->depth.enabled)
+ ? dsa->depth.func : PIPE_FUNC_ALWAYS;
+ int tmp = spe_allocate_available_register(f);
+ boolean compliment = FALSE;
+
+ switch (func) {
+ case PIPE_FUNC_NEVER:
+ spe_il(f, mask, 0);
+ break;
+
+ case PIPE_FUNC_NOTEQUAL:
+ compliment = TRUE;
+ /* FALLTHROUGH */
+ case PIPE_FUNC_EQUAL:
+ spe_ceq(f, mask, calculated, stored);
+ break;
+
+ case PIPE_FUNC_LEQUAL:
+ compliment = TRUE;
+ /* FALLTHROUGH */
+ case PIPE_FUNC_GREATER:
+ spe_clgt(f, mask, calculated, stored);
+ break;
+
+ case PIPE_FUNC_LESS:
+ compliment = TRUE;
+ /* FALLTHROUGH */
+ case PIPE_FUNC_GEQUAL:
+ spe_clgt(f, mask, calculated, stored);
+ spe_ceq(f, tmp, calculated, stored);
+ spe_or(f, mask, mask, tmp);
+ break;
+
+ case PIPE_FUNC_ALWAYS:
+ spe_il(f, mask, ~0);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ spe_release_register(f, tmp);
+ return compliment;
+}
+
+
+/**
+ * Generate code to apply the stencil operation (after testing).
+ * \note Emits a maximum of 5 instructions.
+ *
+ * \warning
+ * Since \c out and \c in might be the same register, this routine cannot
+ * generate code that uses \c out as a temporary.
+ */
+static void
+emit_stencil_op(struct spe_function *f,
+ int out, int in, int mask, unsigned op, unsigned ref)
+{
+ const int clamp = spe_allocate_available_register(f);
+ const int clamp_mask = spe_allocate_available_register(f);
+ const int result = spe_allocate_available_register(f);
+
+ switch(op) {
+ case PIPE_STENCIL_OP_KEEP:
+ assert(0);
+ case PIPE_STENCIL_OP_ZERO:
+ spe_il(f, result, 0);
+ break;
+ case PIPE_STENCIL_OP_REPLACE:
+ spe_il(f, result, ref);
+ break;
+ case PIPE_STENCIL_OP_INCR:
+ /* clamp = [0xff, 0xff, 0xff, 0xff] */
+ spe_il(f, clamp, 0x0ff);
+ /* result[i] = in[i] + 1 */
+ spe_ai(f, result, in, 1);
+ /* clamp_mask[i] = (result[i] > 0xff) */
+ spe_clgti(f, clamp_mask, result, 0x0ff);
+ /* result[i] = clamp_mask[i] ? clamp[i] : result[i] */
+ spe_selb(f, result, result, clamp, clamp_mask);
+ break;
+ case PIPE_STENCIL_OP_DECR:
+ spe_il(f, clamp, 0);
+ spe_ai(f, result, in, -1);
+
+ /* If "(s-1) < 0" in signed arithemtic, then "(s-1) > MAX" in unsigned
+ * arithmetic.
+ */
+ spe_clgti(f, clamp_mask, result, 0x0ff);
+ spe_selb(f, result, result, clamp, clamp_mask);
+ break;
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ spe_ai(f, result, in, 1);
+ break;
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ spe_ai(f, result, in, -1);
+ break;
+ case PIPE_STENCIL_OP_INVERT:
+ spe_nor(f, result, in, in);
+ break;
+ default:
+ assert(0);
+ }
+
+ spe_selb(f, out, in, result, mask);
+
+ spe_release_register(f, result);
+ spe_release_register(f, clamp_mask);
+ spe_release_register(f, clamp);
+}
+
+
+/**
+ * Generate code to do stencil test. Four pixels are tested at once.
+ * \param dsa Depth / stencil test state
+ * \param face 0 for front face, 1 for back face
+ * \param f Function to append instructions to
+ * \param mask Register containing mask of fragments passing the
+ * alpha test
+ * \param depth_mask Register containing mask of fragments passing the
+ * depth test
+ * \param depth_compliment Is \c depth_mask the compliment of the actual mask?
+ * \param stencil Register containing values from stencil buffer
+ * \param depth_pass Register to store mask of fragments passing stencil test
+ * and depth test
+ *
+ * \note
+ * Emits a maximum of 10 + (3 * 5) = 25 instructions.
+ */
+static int
+emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
+ unsigned face,
+ struct spe_function *f,
+ int mask,
+ int depth_mask,
+ boolean depth_complement,
+ int stencil,
+ int depth_pass)
+{
+ int stencil_fail = spe_allocate_available_register(f);
+ int depth_fail = spe_allocate_available_register(f);
+ int stencil_mask = spe_allocate_available_register(f);
+ int stencil_pass = spe_allocate_available_register(f);
+ int face_stencil = spe_allocate_available_register(f);
+ int stencil_src = stencil;
+ const unsigned ref = (dsa->stencil[face].ref_value
+ & dsa->stencil[face].valuemask);
+ boolean complement = FALSE;
+ int stored;
+ int tmp = spe_allocate_available_register(f);
+
+
+ if ((dsa->stencil[face].func != PIPE_FUNC_NEVER)
+ && (dsa->stencil[face].func != PIPE_FUNC_ALWAYS)
+ && (dsa->stencil[face].valuemask != 0x0ff)) {
+ stored = spe_allocate_available_register(f);
+ spe_andi(f, stored, stencil, dsa->stencil[face].valuemask);
+ } else {
+ stored = stencil;
+ }
+
+
+ switch (dsa->stencil[face].func) {
+ case PIPE_FUNC_NEVER:
+ spe_il(f, stencil_mask, 0); /* stencil_mask[0..3] = [0,0,0,0] */
+ break;
+
+ case PIPE_FUNC_NOTEQUAL:
+ complement = TRUE;
+ /* FALLTHROUGH */
+ case PIPE_FUNC_EQUAL:
+ /* stencil_mask[i] = (stored[i] == ref) */
+ spe_ceqi(f, stencil_mask, stored, ref);
+ break;
+
+ case PIPE_FUNC_LEQUAL:
+ complement = TRUE;
+ /* FALLTHROUGH */
+ case PIPE_FUNC_GREATER:
+ complement = TRUE;
+ /* stencil_mask[i] = (stored[i] > ref) */
+ spe_clgti(f, stencil_mask, stored, ref);
+ break;
+
+ case PIPE_FUNC_LESS:
+ complement = TRUE;
+ /* FALLTHROUGH */
+ case PIPE_FUNC_GEQUAL:
+ /* stencil_mask[i] = (stored[i] > ref) */
+ spe_clgti(f, stencil_mask, stored, ref);
+ /* tmp[i] = (stored[i] == ref) */
+ spe_ceqi(f, tmp, stored, ref);
+ /* stencil_mask[i] = stencil_mask[i] | tmp[i] */
+ spe_or(f, stencil_mask, stencil_mask, tmp);
+ break;
+
+ case PIPE_FUNC_ALWAYS:
+ /* See comment below. */
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ if (stored != stencil) {
+ spe_release_register(f, stored);
+ }
+ spe_release_register(f, tmp);
+
+
+ /* ALWAYS is a very common stencil-test, so some effort is applied to
+ * optimize that case. The stencil-pass mask is the same as the input
+ * fragment mask. This makes the stencil-test (above) a no-op, and the
+ * input fragment mask can be "renamed" the stencil-pass mask.
+ */
+ if (dsa->stencil[face].func == PIPE_FUNC_ALWAYS) {
+ spe_release_register(f, stencil_pass);
+ stencil_pass = mask;
+ } else {
+ if (complement) {
+ spe_andc(f, stencil_pass, mask, stencil_mask);
+ } else {
+ spe_and(f, stencil_pass, mask, stencil_mask);
+ }
+ }
+
+ if (depth_complement) {
+ spe_andc(f, depth_pass, stencil_pass, depth_mask);
+ } else {
+ spe_and(f, depth_pass, stencil_pass, depth_mask);
+ }
+
+
+ /* Conditionally emit code to update the stencil value under various
+ * condititons. Note that there is no need to generate code under the
+ * following circumstances:
+ *
+ * - Stencil write mask is zero.
+ * - For stencil-fail if the stencil test is ALWAYS
+ * - For depth-fail if the stencil test is NEVER
+ * - For depth-pass if the stencil test is NEVER
+ * - Any of the 3 conditions if the operation is KEEP
+ */
+ if (dsa->stencil[face].writemask != 0) {
+ if ((dsa->stencil[face].func != PIPE_FUNC_ALWAYS)
+ && (dsa->stencil[face].fail_op != PIPE_STENCIL_OP_KEEP)) {
+ if (complement) {
+ spe_and(f, stencil_fail, mask, stencil_mask);
+ } else {
+ spe_andc(f, stencil_fail, mask, stencil_mask);
+ }
+
+ emit_stencil_op(f, face_stencil, stencil_src, stencil_fail,
+ dsa->stencil[face].fail_op,
+ dsa->stencil[face].ref_value);
+
+ stencil_src = face_stencil;
+ }
+
+ if ((dsa->stencil[face].func != PIPE_FUNC_NEVER)
+ && (dsa->stencil[face].zfail_op != PIPE_STENCIL_OP_KEEP)) {
+ if (depth_complement) {
+ spe_and(f, depth_fail, stencil_pass, depth_mask);
+ } else {
+ spe_andc(f, depth_fail, stencil_pass, depth_mask);
+ }
+
+ emit_stencil_op(f, face_stencil, stencil_src, depth_fail,
+ dsa->stencil[face].zfail_op,
+ dsa->stencil[face].ref_value);
+ stencil_src = face_stencil;
+ }
+
+ if ((dsa->stencil[face].func != PIPE_FUNC_NEVER)
+ && (dsa->stencil[face].zpass_op != PIPE_STENCIL_OP_KEEP)) {
+ emit_stencil_op(f, face_stencil, stencil_src, depth_pass,
+ dsa->stencil[face].zpass_op,
+ dsa->stencil[face].ref_value);
+ stencil_src = face_stencil;
+ }
+ }
+
+ spe_release_register(f, stencil_fail);
+ spe_release_register(f, depth_fail);
+ spe_release_register(f, stencil_mask);
+ if (stencil_pass != mask) {
+ spe_release_register(f, stencil_pass);
+ }
+
+ /* If all of the stencil operations were KEEP or the stencil write mask was
+ * zero, "stencil_src" will still be set to "stencil". In this case
+ * release the "face_stencil" register. Otherwise apply the stencil write
+ * mask to select bits from the calculated stencil value and the previous
+ * stencil value.
+ */
+ if (stencil_src == stencil) {
+ spe_release_register(f, face_stencil);
+ } else if (dsa->stencil[face].writemask != 0x0ff) {
+ int tmp = spe_allocate_available_register(f);
+
+ spe_il(f, tmp, dsa->stencil[face].writemask);
+ spe_selb(f, stencil_src, stencil, stencil_src, tmp);
+
+ spe_release_register(f, tmp);
+ }
+
+ return stencil_src;
+}
+
+
+void
+cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa)
+{
+ struct pipe_depth_stencil_alpha_state *const dsa = &cdsa->base;
+ struct spe_function *const f = &cdsa->code;
+
+ /* This code generates a maximum of 6 (alpha test) + 3 (depth test)
+ * + 25 (front stencil) + 25 (back stencil) + 4 = 63 instructions. Round
+ * up to 64 to make it a happy power-of-two.
+ */
+ spe_init_func(f, SPE_INST_SIZE * 64);
+
+
+ /* Allocate registers for the function's input parameters. Cleverly (and
+ * clever code is usually dangerous, but I couldn't resist) the generated
+ * function returns a structure. Returned structures start with register
+ * 3, and the structure fields are ordered to match up exactly with the
+ * input parameters.
+ */
+ int mask = spe_allocate_register(f, 3);
+ int depth = spe_allocate_register(f, 4);
+ int stencil = spe_allocate_register(f, 5);
+ int zvals = spe_allocate_register(f, 6);
+ int frag_a = spe_allocate_register(f, 7);
+ int facing = spe_allocate_register(f, 8);
+
+ int depth_mask = spe_allocate_available_register(f);
+
+ boolean depth_complement;
+
+
+ emit_alpha_test(dsa, f, mask, frag_a);
+
+ depth_complement = emit_depth_test(dsa, f, depth_mask, depth, zvals);
+
+ if (dsa->stencil[0].enabled) {
+ const int front_depth_pass = spe_allocate_available_register(f);
+ int front_stencil = emit_stencil_test(dsa, 0, f, mask,
+ depth_mask, depth_complement,
+ stencil, front_depth_pass);
+
+ if (dsa->stencil[1].enabled) {
+ const int back_depth_pass = spe_allocate_available_register(f);
+ int back_stencil = emit_stencil_test(dsa, 1, f, mask,
+ depth_mask, depth_complement,
+ stencil, back_depth_pass);
+
+ /* If the front facing stencil value and the back facing stencil
+ * value are stored in the same register, there is no need to select
+ * a value based on the facing. This can happen if the stencil value
+ * was not modified due to the write masks being zero, the stencil
+ * operations being KEEP, etc.
+ */
+ if (front_stencil != back_stencil) {
+ spe_selb(f, stencil, back_stencil, front_stencil, facing);
+ }
+
+ if (back_stencil != stencil) {
+ spe_release_register(f, back_stencil);
+ }
+
+ if (front_stencil != stencil) {
+ spe_release_register(f, front_stencil);
+ }
+
+ spe_selb(f, mask, back_depth_pass, front_depth_pass, facing);
+
+ spe_release_register(f, back_depth_pass);
+ } else {
+ if (front_stencil != stencil) {
+ spe_or(f, stencil, front_stencil, front_stencil);
+ spe_release_register(f, front_stencil);
+ }
+ spe_or(f, mask, front_depth_pass, front_depth_pass);
+ }
+
+ spe_release_register(f, front_depth_pass);
+ } else if (dsa->depth.enabled) {
+ if (depth_complement) {
+ spe_andc(f, mask, mask, depth_mask);
+ } else {
+ spe_and(f, mask, mask, depth_mask);
+ }
+ }
+
+ if (dsa->depth.writemask) {
+ spe_selb(f, depth, depth, zvals, mask);
+ }
+
+ spe_bi(f, 0, 0, 0); /* return from function call */
+
+
+#if 0
+ {
+ const uint32_t *p = f->store;
+ unsigned i;
+
+ printf("# alpha (%sabled)\n",
+ (dsa->alpha.enabled) ? "en" : "dis");
+ printf("# func: %u\n", dsa->alpha.func);
+ printf("# ref: %.2f\n", dsa->alpha.ref);
+
+ printf("# depth (%sabled)\n",
+ (dsa->depth.enabled) ? "en" : "dis");
+ printf("# func: %u\n", dsa->depth.func);
+
+ for (i = 0; i < 2; i++) {
+ printf("# %s stencil (%sabled)\n",
+ (i == 0) ? "front" : "back",
+ (dsa->stencil[i].enabled) ? "en" : "dis");
+
+ printf("# func: %u\n", dsa->stencil[i].func);
+ printf("# op (sf, zf, zp): %u %u %u\n",
+ dsa->stencil[i].fail_op,
+ dsa->stencil[i].zfail_op,
+ dsa->stencil[i].zpass_op);
+ printf("# ref value / value mask / write mask: %02x %02x %02x\n",
+ dsa->stencil[i].ref_value,
+ dsa->stencil[i].valuemask,
+ dsa->stencil[i].writemask);
+ }
+
+ printf("\t.text\n");
+ for (/* empty */; p < f->csr; p++) {
+ printf("\t.long\t0x%04x\n", *p);
+ }
+ fflush(stdout);
+ }
+#endif
+}
+
+
+/**
+ * \note Emits a maximum of 3 instructions
+ */
+static int
+emit_alpha_factor_calculation(struct spe_function *f,
+ unsigned factor,
+ int src_alpha, int dst_alpha, int const_alpha)
+{
+ int factor_reg;
+ int tmp;
+
+
+ switch (factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ factor_reg = -1;
+ break;
+
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ factor_reg = spe_allocate_available_register(f);
+
+ spe_or(f, factor_reg, src_alpha, src_alpha);
+ break;
+
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ factor_reg = dst_alpha;
+ break;
+
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ factor_reg = -1;
+ break;
+
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ factor_reg = spe_allocate_available_register(f);
+
+ tmp = spe_allocate_available_register(f);
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+ spe_fs(f, factor_reg, tmp, const_alpha);
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ factor_reg = const_alpha;
+ break;
+
+ case PIPE_BLENDFACTOR_ZERO:
+ factor_reg = -1;
+ break;
+
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ tmp = spe_allocate_available_register(f);
+ factor_reg = spe_allocate_available_register(f);
+
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+ spe_fs(f, factor_reg, tmp, src_alpha);
+
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ tmp = spe_allocate_available_register(f);
+ factor_reg = spe_allocate_available_register(f);
+
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+ spe_fs(f, factor_reg, tmp, dst_alpha);
+
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ default:
+ assert(0);
+ factor_reg = -1;
+ break;
+ }
+
+ return factor_reg;
+}
+
+
+/**
+ * \note Emits a maximum of 6 instructions
+ */
+static void
+emit_color_factor_calculation(struct spe_function *f,
+ unsigned sF, unsigned mask,
+ const int *src,
+ const int *dst,
+ const int *const_color,
+ int *factor)
+{
+ int tmp;
+ unsigned i;
+
+
+ factor[0] = -1;
+ factor[1] = -1;
+ factor[2] = -1;
+ factor[3] = -1;
+
+ switch (sF) {
+ case PIPE_BLENDFACTOR_ONE:
+ break;
+
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ for (i = 0; i < 3; ++i) {
+ if ((mask & (1U << i)) != 0) {
+ factor[i] = spe_allocate_available_register(f);
+ spe_or(f, factor[i], src[i], src[i]);
+ }
+ }
+ break;
+
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ factor[0] = spe_allocate_available_register(f);
+ factor[1] = factor[0];
+ factor[2] = factor[0];
+
+ spe_or(f, factor[0], src[3], src[3]);
+ break;
+
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ factor[0] = dst[3];
+ factor[1] = dst[3];
+ factor[2] = dst[3];
+ break;
+
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ factor[0] = dst[0];
+ factor[1] = dst[1];
+ factor[2] = dst[2];
+ break;
+
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ tmp = spe_allocate_available_register(f);
+ factor[0] = spe_allocate_available_register(f);
+ factor[1] = factor[0];
+ factor[2] = factor[0];
+
+ /* Alpha saturate means min(As, 1-Ad).
+ */
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+ spe_fs(f, tmp, tmp, dst[3]);
+ spe_fcgt(f, factor[0], tmp, src[3]);
+ spe_selb(f, factor[0], src[3], tmp, factor[0]);
+
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ tmp = spe_allocate_available_register(f);
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+
+ for (i = 0; i < 3; i++) {
+ factor[i] = spe_allocate_available_register(f);
+
+ spe_fs(f, factor[i], tmp, const_color[i]);
+ }
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ for (i = 0; i < 3; i++) {
+ factor[i] = const_color[i];
+ }
+ break;
+
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ factor[0] = spe_allocate_available_register(f);
+ factor[1] = factor[0];
+ factor[2] = factor[0];
+
+ tmp = spe_allocate_available_register(f);
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+ spe_fs(f, factor[0], tmp, const_color[3]);
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ factor[0] = const_color[3];
+ factor[1] = factor[0];
+ factor[2] = factor[0];
+ break;
+
+ case PIPE_BLENDFACTOR_ZERO:
+ break;
+
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ tmp = spe_allocate_available_register(f);
+
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+
+ for (i = 0; i < 3; ++i) {
+ if ((mask & (1U << i)) != 0) {
+ factor[i] = spe_allocate_available_register(f);
+ spe_fs(f, factor[i], tmp, src[i]);
+ }
+ }
+
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ tmp = spe_allocate_available_register(f);
+ factor[0] = spe_allocate_available_register(f);
+ factor[1] = factor[0];
+ factor[2] = factor[0];
+
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+ spe_fs(f, factor[0], tmp, src[3]);
+
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ tmp = spe_allocate_available_register(f);
+ factor[0] = spe_allocate_available_register(f);
+ factor[1] = factor[0];
+ factor[2] = factor[0];
+
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+ spe_fs(f, factor[0], tmp, dst[3]);
+
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ tmp = spe_allocate_available_register(f);
+
+ spe_il(f, tmp, 1);
+ spe_cuflt(f, tmp, tmp, 0);
+
+ for (i = 0; i < 3; ++i) {
+ if ((mask & (1U << i)) != 0) {
+ factor[i] = spe_allocate_available_register(f);
+ spe_fs(f, factor[i], tmp, dst[i]);
+ }
+ }
+
+ spe_release_register(f, tmp);
+ break;
+
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ default:
+ assert(0);
+ }
+}
+
+
+static void
+emit_blend_calculation(struct spe_function *f,
+ unsigned func, unsigned sF, unsigned dF,
+ int src, int src_factor, int dst, int dst_factor)
+{
+ int tmp = spe_allocate_available_register(f);
+
+ switch (func) {
+ case PIPE_BLEND_ADD:
+ if (sF == PIPE_BLENDFACTOR_ONE) {
+ if (dF == PIPE_BLENDFACTOR_ZERO) {
+ /* Do nothing. */
+ } else if (dF == PIPE_BLENDFACTOR_ONE) {
+ spe_fa(f, src, src, dst);
+ }
+ } else if (sF == PIPE_BLENDFACTOR_ZERO) {
+ if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_il(f, src, 0);
+ } else if (dF == PIPE_BLENDFACTOR_ONE) {
+ spe_or(f, src, dst, dst);
+ } else {
+ spe_fm(f, src, dst, dst_factor);
+ }
+ } else if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_fm(f, src, src, src_factor);
+ } else {
+ spe_fm(f, tmp, dst, dst_factor);
+ spe_fma(f, src, src, src_factor, tmp);
+ }
+ break;
+
+ case PIPE_BLEND_SUBTRACT:
+ if (sF == PIPE_BLENDFACTOR_ONE) {
+ if (dF == PIPE_BLENDFACTOR_ZERO) {
+ /* Do nothing. */
+ } else if (dF == PIPE_BLENDFACTOR_ONE) {
+ spe_fs(f, src, src, dst);
+ }
+ } else if (sF == PIPE_BLENDFACTOR_ZERO) {
+ if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_il(f, src, 0);
+ } else if (dF == PIPE_BLENDFACTOR_ONE) {
+ spe_il(f, tmp, 0);
+ spe_fs(f, src, tmp, dst);
+ } else {
+ spe_fm(f, src, dst, dst_factor);
+ }
+ } else if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_fm(f, src, src, src_factor);
+ } else {
+ spe_fm(f, tmp, dst, dst_factor);
+ spe_fms(f, src, src, src_factor, tmp);
+ }
+ break;
+
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ if (sF == PIPE_BLENDFACTOR_ONE) {
+ if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_il(f, tmp, 0);
+ spe_fs(f, src, tmp, src);
+ } else if (dF == PIPE_BLENDFACTOR_ONE) {
+ spe_fs(f, src, dst, src);
+ }
+ } else if (sF == PIPE_BLENDFACTOR_ZERO) {
+ if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_il(f, src, 0);
+ } else if (dF == PIPE_BLENDFACTOR_ONE) {
+ spe_or(f, src, dst, dst);
+ } else {
+ spe_fm(f, src, dst, dst_factor);
+ }
+ } else if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_fm(f, src, src, src_factor);
+ } else {
+ spe_fm(f, tmp, src, src_factor);
+ spe_fms(f, src, src, dst_factor, tmp);
+ }
+ break;
+
+ case PIPE_BLEND_MIN:
+ spe_cgt(f, tmp, src, dst);
+ spe_selb(f, src, src, dst, tmp);
+ break;
+
+ case PIPE_BLEND_MAX:
+ spe_cgt(f, tmp, src, dst);
+ spe_selb(f, src, dst, src, tmp);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ spe_release_register(f, tmp);
+}
+
+
+/**
+ * Generate code to perform alpha blending on the SPE
+ */
+void
+cell_generate_alpha_blend(struct cell_blend_state *cb)
+{
+ struct pipe_blend_state *const b = &cb->base;
+ struct spe_function *const f = &cb->code;
+
+ /* This code generates a maximum of 3 (source alpha factor)
+ * + 3 (destination alpha factor) + (3 * 6) (source color factor)
+ * + (3 * 6) (destination color factor) + (4 * 2) (blend equation)
+ * + 4 (fragment mask) + 1 (return) = 55 instlructions. Round up to 64 to
+ * make it a happy power-of-two.
+ */
+ spe_init_func(f, SPE_INST_SIZE * 64);
+
+
+ const int frag[4] = {
+ spe_allocate_register(f, 3),
+ spe_allocate_register(f, 4),
+ spe_allocate_register(f, 5),
+ spe_allocate_register(f, 6),
+ };
+ const int pixel[4] = {
+ spe_allocate_register(f, 7),
+ spe_allocate_register(f, 8),
+ spe_allocate_register(f, 9),
+ spe_allocate_register(f, 10),
+ };
+ const int const_color[4] = {
+ spe_allocate_register(f, 11),
+ spe_allocate_register(f, 12),
+ spe_allocate_register(f, 13),
+ spe_allocate_register(f, 14),
+ };
+ unsigned func[4];
+ unsigned sF[4];
+ unsigned dF[4];
+ unsigned i;
+ int src_factor[4];
+ int dst_factor[4];
+
+
+ /* Does the selected blend mode make use of the source / destination
+ * color (RGB) blend factors?
+ */
+ boolean need_color_factor = b->blend_enable
+ && (b->rgb_func != PIPE_BLEND_MIN)
+ && (b->rgb_func != PIPE_BLEND_MAX);
+
+ /* Does the selected blend mode make use of the source / destination
+ * alpha blend factors?
+ */
+ boolean need_alpha_factor = b->blend_enable
+ && (b->alpha_func != PIPE_BLEND_MIN)
+ && (b->alpha_func != PIPE_BLEND_MAX);
+
+
+ if (b->blend_enable) {
+ sF[0] = b->rgb_src_factor;
+ sF[1] = sF[0];
+ sF[2] = sF[0];
+ switch (b->alpha_src_factor & 0x0f) {
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ sF[3] = PIPE_BLENDFACTOR_ONE;
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ sF[3] = b->alpha_src_factor + 1;
+ break;
+ default:
+ sF[3] = b->alpha_src_factor;
+ }
+
+ dF[0] = b->rgb_dst_factor;
+ dF[1] = dF[0];
+ dF[2] = dF[0];
+ switch (b->alpha_dst_factor & 0x0f) {
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ dF[3] = b->alpha_dst_factor + 1;
+ break;
+ default:
+ dF[3] = b->alpha_dst_factor;
+ }
+
+ func[0] = b->rgb_func;
+ func[1] = func[0];
+ func[2] = func[0];
+ func[3] = b->alpha_func;
+ } else {
+ sF[0] = PIPE_BLENDFACTOR_ONE;
+ sF[1] = PIPE_BLENDFACTOR_ONE;
+ sF[2] = PIPE_BLENDFACTOR_ONE;
+ sF[3] = PIPE_BLENDFACTOR_ONE;
+ dF[0] = PIPE_BLENDFACTOR_ZERO;
+ dF[1] = PIPE_BLENDFACTOR_ZERO;
+ dF[2] = PIPE_BLENDFACTOR_ZERO;
+ dF[3] = PIPE_BLENDFACTOR_ZERO;
+
+ func[0] = PIPE_BLEND_ADD;
+ func[1] = PIPE_BLEND_ADD;
+ func[2] = PIPE_BLEND_ADD;
+ func[3] = PIPE_BLEND_ADD;
+ }
+
+
+ /* If alpha writing is enabled and the alpha blend mode requires use of
+ * the alpha factor, calculate the alpha factor.
+ */
+ if (((b->colormask & 8) != 0) && need_alpha_factor) {
+ src_factor[3] = emit_alpha_factor_calculation(f, sF[3], const_color[3],
+ frag[3], pixel[3]);
+
+ /* If the alpha destination blend factor is the same as the alpha source
+ * blend factor, re-use the previously calculated value.
+ */
+ dst_factor[3] = (dF[3] == sF[3])
+ ? src_factor[3]
+ : emit_alpha_factor_calculation(f, dF[3], const_color[3],
+ frag[3], pixel[3]);
+ }
+
+
+ if (sF[0] == sF[3]) {
+ src_factor[0] = src_factor[3];
+ src_factor[1] = src_factor[3];
+ src_factor[2] = src_factor[3];
+ } else if (sF[0] == dF[3]) {
+ src_factor[0] = dst_factor[3];
+ src_factor[1] = dst_factor[3];
+ src_factor[2] = dst_factor[3];
+ } else if (need_color_factor) {
+ emit_color_factor_calculation(f,
+ b->rgb_src_factor,
+ b->colormask,
+ frag, pixel, const_color, src_factor);
+ }
+
+
+ if (dF[0] == sF[3]) {
+ dst_factor[0] = src_factor[3];
+ dst_factor[1] = src_factor[3];
+ dst_factor[2] = src_factor[3];
+ } else if (dF[0] == dF[3]) {
+ dst_factor[0] = dst_factor[3];
+ dst_factor[1] = dst_factor[3];
+ dst_factor[2] = dst_factor[3];
+ } else if (dF[0] == sF[0]) {
+ dst_factor[0] = src_factor[0];
+ dst_factor[1] = src_factor[1];
+ dst_factor[2] = src_factor[2];
+ } else if (need_color_factor) {
+ emit_color_factor_calculation(f,
+ b->rgb_dst_factor,
+ b->colormask,
+ frag, pixel, const_color, dst_factor);
+ }
+
+
+
+ for (i = 0; i < 4; ++i) {
+ if ((b->colormask & (1U << i)) != 0) {
+ emit_blend_calculation(f,
+ func[i], sF[i], dF[i],
+ frag[i], src_factor[i],
+ pixel[i], dst_factor[i]);
+ }
+ }
+
+ spe_bi(f, 0, 0, 0);
+
+#if 0
+ {
+ const uint32_t *p = f->store;
+
+ printf("# %u instructions\n", f->csr - f->store);
+ printf("# blend (%sabled)\n",
+ (cb->base.blend_enable) ? "en" : "dis");
+ printf("# RGB func / sf / df: %u %u %u\n",
+ cb->base.rgb_func,
+ cb->base.rgb_src_factor,
+ cb->base.rgb_dst_factor);
+ printf("# ALP func / sf / df: %u %u %u\n",
+ cb->base.alpha_func,
+ cb->base.alpha_src_factor,
+ cb->base.alpha_dst_factor);
+
+ printf("\t.text\n");
+ for (/* empty */; p < f->csr; p++) {
+ printf("\t.long\t0x%04x\n", *p);
+ }
+ fflush(stdout);
+ }
+#endif
+}
+
+
+static int
+PC_OFFSET(const struct spe_function *f, const void *d)
+{
+ const intptr_t pc = (intptr_t) &f->store[f->num_inst];
+ const intptr_t ea = ~0x0f & (intptr_t) d;
+
+ return (ea - pc) >> 2;
+}
+
+
+/**
+ * Generate code to perform color conversion and logic op
+ *
+ * \bug
+ * The code generated by this function should also perform dithering.
+ *
+ * \bug
+ * The code generated by this function should also perform color-write
+ * masking.
+ *
+ * \bug
+ * Only two framebuffer formats are supported at this time.
+ */
+void
+cell_generate_logic_op(struct spe_function *f,
+ const struct pipe_blend_state *blend,
+ struct pipe_surface *surf)
+{
+ const unsigned logic_op = (blend->logicop_enable)
+ ? blend->logicop_func : PIPE_LOGICOP_COPY;
+
+ /* This code generates a maximum of 37 instructions. An additional 32
+ * bytes (equiv. to 8 instructions) are needed for data storage. Round up
+ * to 64 to make it a happy power-of-two.
+ */
+ spe_init_func(f, SPE_INST_SIZE * 64);
+
+
+ /* Pixel colors in framebuffer format in AoS layout.
+ */
+ const int pixel[4] = {
+ spe_allocate_register(f, 3),
+ spe_allocate_register(f, 4),
+ spe_allocate_register(f, 5),
+ spe_allocate_register(f, 6),
+ };
+
+ /* Fragment colors stored as floats in SoA layout.
+ */
+ const int frag[4] = {
+ spe_allocate_register(f, 7),
+ spe_allocate_register(f, 8),
+ spe_allocate_register(f, 9),
+ spe_allocate_register(f, 10),
+ };
+
+ const int mask = spe_allocate_register(f, 11);
+
+
+ /* Short-circuit the noop and invert cases.
+ */
+ if ((logic_op == PIPE_LOGICOP_NOOP) || (blend->colormask == 0)) {
+ spe_bi(f, 0, 0, 0);
+ return;
+ } else if (logic_op == PIPE_LOGICOP_INVERT) {
+ spe_nor(f, pixel[0], pixel[0], pixel[0]);
+ spe_nor(f, pixel[1], pixel[1], pixel[1]);
+ spe_nor(f, pixel[2], pixel[2], pixel[2]);
+ spe_nor(f, pixel[3], pixel[3], pixel[3]);
+ spe_bi(f, 0, 0, 0);
+ return;
+ }
+
+
+ const int tmp[4] = {
+ spe_allocate_available_register(f),
+ spe_allocate_available_register(f),
+ spe_allocate_available_register(f),
+ spe_allocate_available_register(f),
+ };
+
+ const int shuf_xpose_hi = spe_allocate_available_register(f);
+ const int shuf_xpose_lo = spe_allocate_available_register(f);
+ const int shuf_color = spe_allocate_available_register(f);
+
+
+ /* Pointer to the begining of the function's private data area.
+ */
+ uint32_t *const data = ((uint32_t *) f->store) + (64 - 8);
+
+
+ /* Convert fragment colors to framebuffer format in AoS layout.
+ */
+ switch (surf->format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ data[0] = 0x00010203;
+ data[1] = 0x10111213;
+ data[2] = 0x04050607;
+ data[3] = 0x14151617;
+ data[4] = 0x0c000408;
+ data[5] = 0x80808080;
+ data[6] = 0x80808080;
+ data[7] = 0x80808080;
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ data[0] = 0x03020100;
+ data[1] = 0x13121110;
+ data[2] = 0x07060504;
+ data[3] = 0x17161514;
+ data[4] = 0x0804000c;
+ data[5] = 0x80808080;
+ data[6] = 0x80808080;
+ data[7] = 0x80808080;
+ break;
+ default:
+ fprintf(stderr, "CELL: Bad pixel format in cell_generate_logic_op()");
+ ASSERT(0);
+ }
+
+ spe_ilh(f, tmp[0], 0x0808);
+ spe_lqr(f, shuf_xpose_hi, PC_OFFSET(f, data+0));
+ spe_lqr(f, shuf_color, PC_OFFSET(f, data+4));
+ spe_a(f, shuf_xpose_lo, shuf_xpose_hi, tmp[0]);
+
+ spe_shufb(f, tmp[0], frag[0], frag[2], shuf_xpose_hi);
+ spe_shufb(f, tmp[1], frag[0], frag[2], shuf_xpose_lo);
+ spe_shufb(f, tmp[2], frag[1], frag[3], shuf_xpose_hi);
+ spe_shufb(f, tmp[3], frag[1], frag[3], shuf_xpose_lo);
+
+ spe_shufb(f, frag[0], tmp[0], tmp[2], shuf_xpose_hi);
+ spe_shufb(f, frag[1], tmp[0], tmp[2], shuf_xpose_lo);
+ spe_shufb(f, frag[2], tmp[1], tmp[3], shuf_xpose_hi);
+ spe_shufb(f, frag[3], tmp[1], tmp[3], shuf_xpose_lo);
+
+ spe_cfltu(f, frag[0], frag[0], 32);
+ spe_cfltu(f, frag[1], frag[1], 32);
+ spe_cfltu(f, frag[2], frag[2], 32);
+ spe_cfltu(f, frag[3], frag[3], 32);
+
+ spe_shufb(f, frag[0], frag[0], pixel[0], shuf_color);
+ spe_shufb(f, frag[1], frag[1], pixel[1], shuf_color);
+ spe_shufb(f, frag[2], frag[2], pixel[2], shuf_color);
+ spe_shufb(f, frag[3], frag[3], pixel[3], shuf_color);
+
+
+ /* If logic op is enabled, perform the requested logical operation on the
+ * converted fragment colors and the pixel colors.
+ */
+ switch (logic_op) {
+ case PIPE_LOGICOP_CLEAR:
+ spe_il(f, frag[0], 0);
+ spe_il(f, frag[1], 0);
+ spe_il(f, frag[2], 0);
+ spe_il(f, frag[3], 0);
+ break;
+ case PIPE_LOGICOP_NOR:
+ spe_nor(f, frag[0], frag[0], pixel[0]);
+ spe_nor(f, frag[1], frag[1], pixel[1]);
+ spe_nor(f, frag[2], frag[2], pixel[2]);
+ spe_nor(f, frag[3], frag[3], pixel[3]);
+ break;
+ case PIPE_LOGICOP_AND_INVERTED:
+ spe_andc(f, frag[0], pixel[0], frag[0]);
+ spe_andc(f, frag[1], pixel[1], frag[1]);
+ spe_andc(f, frag[2], pixel[2], frag[2]);
+ spe_andc(f, frag[3], pixel[3], frag[3]);
+ break;
+ case PIPE_LOGICOP_COPY_INVERTED:
+ spe_nor(f, frag[0], frag[0], frag[0]);
+ spe_nor(f, frag[1], frag[1], frag[1]);
+ spe_nor(f, frag[2], frag[2], frag[2]);
+ spe_nor(f, frag[3], frag[3], frag[3]);
+ break;
+ case PIPE_LOGICOP_AND_REVERSE:
+ spe_andc(f, frag[0], frag[0], pixel[0]);
+ spe_andc(f, frag[1], frag[1], pixel[1]);
+ spe_andc(f, frag[2], frag[2], pixel[2]);
+ spe_andc(f, frag[3], frag[3], pixel[3]);
+ break;
+ case PIPE_LOGICOP_XOR:
+ spe_xor(f, frag[0], frag[0], pixel[0]);
+ spe_xor(f, frag[1], frag[1], pixel[1]);
+ spe_xor(f, frag[2], frag[2], pixel[2]);
+ spe_xor(f, frag[3], frag[3], pixel[3]);
+ break;
+ case PIPE_LOGICOP_NAND:
+ spe_nand(f, frag[0], frag[0], pixel[0]);
+ spe_nand(f, frag[1], frag[1], pixel[1]);
+ spe_nand(f, frag[2], frag[2], pixel[2]);
+ spe_nand(f, frag[3], frag[3], pixel[3]);
+ break;
+ case PIPE_LOGICOP_AND:
+ spe_and(f, frag[0], frag[0], pixel[0]);
+ spe_and(f, frag[1], frag[1], pixel[1]);
+ spe_and(f, frag[2], frag[2], pixel[2]);
+ spe_and(f, frag[3], frag[3], pixel[3]);
+ break;
+ case PIPE_LOGICOP_EQUIV:
+ spe_eqv(f, frag[0], frag[0], pixel[0]);
+ spe_eqv(f, frag[1], frag[1], pixel[1]);
+ spe_eqv(f, frag[2], frag[2], pixel[2]);
+ spe_eqv(f, frag[3], frag[3], pixel[3]);
+ break;
+ case PIPE_LOGICOP_OR_INVERTED:
+ spe_orc(f, frag[0], pixel[0], frag[0]);
+ spe_orc(f, frag[1], pixel[1], frag[1]);
+ spe_orc(f, frag[2], pixel[2], frag[2]);
+ spe_orc(f, frag[3], pixel[3], frag[3]);
+ break;
+ case PIPE_LOGICOP_COPY:
+ break;
+ case PIPE_LOGICOP_OR_REVERSE:
+ spe_orc(f, frag[0], frag[0], pixel[0]);
+ spe_orc(f, frag[1], frag[1], pixel[1]);
+ spe_orc(f, frag[2], frag[2], pixel[2]);
+ spe_orc(f, frag[3], frag[3], pixel[3]);
+ break;
+ case PIPE_LOGICOP_OR:
+ spe_or(f, frag[0], frag[0], pixel[0]);
+ spe_or(f, frag[1], frag[1], pixel[1]);
+ spe_or(f, frag[2], frag[2], pixel[2]);
+ spe_or(f, frag[3], frag[3], pixel[3]);
+ break;
+ case PIPE_LOGICOP_SET:
+ spe_il(f, frag[0], ~0);
+ spe_il(f, frag[1], ~0);
+ spe_il(f, frag[2], ~0);
+ spe_il(f, frag[3], ~0);
+ break;
+
+ /* These two cases are short-circuited above.
+ */
+ case PIPE_LOGICOP_INVERT:
+ case PIPE_LOGICOP_NOOP:
+ default:
+ assert(0);
+ }
+
+
+ /* Apply fragment mask.
+ */
+ spe_ilh(f, tmp[0], 0x0000);
+ spe_ilh(f, tmp[1], 0x0404);
+ spe_ilh(f, tmp[2], 0x0808);
+ spe_ilh(f, tmp[3], 0x0c0c);
+
+ spe_shufb(f, tmp[0], mask, mask, tmp[0]);
+ spe_shufb(f, tmp[1], mask, mask, tmp[1]);
+ spe_shufb(f, tmp[2], mask, mask, tmp[2]);
+ spe_shufb(f, tmp[3], mask, mask, tmp[3]);
+
+ spe_selb(f, pixel[0], pixel[0], frag[0], tmp[0]);
+ spe_selb(f, pixel[1], pixel[1], frag[1], tmp[1]);
+ spe_selb(f, pixel[2], pixel[2], frag[2], tmp[2]);
+ spe_selb(f, pixel[3], pixel[3], frag[3], tmp[3]);
+
+ spe_bi(f, 0, 0, 0);
+
+#if 0
+ {
+ const uint32_t *p = f->store;
+ unsigned i;
+
+ printf("# %u instructions\n", f->csr - f->store);
+
+ printf("\t.text\n");
+ for (i = 0; i < 64; i++) {
+ printf("\t.long\t0x%04x\n", p[i]);
+ }
+ fflush(stdout);
+ }
+#endif
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.h b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.h
new file mode 100644
index 0000000000..a8267a5133
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.h
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef CELL_STATE_PER_FRAGMENT_H
+#define CELL_STATE_PER_FRAGMENT_H
+
+extern void
+cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa);
+
+extern void
+cell_generate_alpha_blend(struct cell_blend_state *cb);
+
+extern void
+cell_generate_logic_op(struct spe_function *f,
+ const struct pipe_blend_state *blend,
+ struct pipe_surface *surf);
+
+#endif /* CELL_STATE_PER_FRAGMENT_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_state_shader.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c
new file mode 100644
index 0000000000..6568c784fe
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_state_shader.c
@@ -0,0 +1,217 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "draw/draw_context.h"
+#include "tgsi/tgsi_parse.h"
+
+#include "cell_context.h"
+#include "cell_state.h"
+#include "cell_gen_fp.h"
+
+
+/** cast wrapper */
+static INLINE struct cell_fragment_shader_state *
+cell_fragment_shader_state(void *shader)
+{
+ return (struct cell_fragment_shader_state *) shader;
+}
+
+
+/** cast wrapper */
+static INLINE struct cell_vertex_shader_state *
+cell_vertex_shader_state(void *shader)
+{
+ return (struct cell_vertex_shader_state *) shader;
+}
+
+
+/**
+ * Create fragment shader state.
+ * Called via pipe->create_fs_state()
+ */
+static void *
+cell_create_fs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct cell_context *cell = cell_context(pipe);
+ struct cell_fragment_shader_state *cfs;
+
+ cfs = CALLOC_STRUCT(cell_fragment_shader_state);
+ if (!cfs)
+ return NULL;
+
+ cfs->shader.tokens = tgsi_dup_tokens(templ->tokens);
+ if (!cfs->shader.tokens) {
+ FREE(cfs);
+ return NULL;
+ }
+
+ tgsi_scan_shader(templ->tokens, &cfs->info);
+
+ cell_gen_fragment_program(cell, cfs->shader.tokens, &cfs->code);
+
+ return cfs;
+}
+
+
+/**
+ * Called via pipe->bind_fs_state()
+ */
+static void
+cell_bind_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ cell->fs = cell_fragment_shader_state(fs);
+
+ cell->dirty |= CELL_NEW_FS;
+}
+
+
+/**
+ * Called via pipe->delete_fs_state()
+ */
+static void
+cell_delete_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct cell_fragment_shader_state *cfs = cell_fragment_shader_state(fs);
+
+ spe_release_func(&cfs->code);
+
+ FREE((void *) cfs->shader.tokens);
+ FREE(cfs);
+}
+
+
+/**
+ * Create vertex shader state.
+ * Called via pipe->create_vs_state()
+ */
+static void *
+cell_create_vs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct cell_context *cell = cell_context(pipe);
+ struct cell_vertex_shader_state *cvs;
+
+ cvs = CALLOC_STRUCT(cell_vertex_shader_state);
+ if (!cvs)
+ return NULL;
+
+ cvs->shader.tokens = tgsi_dup_tokens(templ->tokens);
+ if (!cvs->shader.tokens) {
+ FREE(cvs);
+ return NULL;
+ }
+
+ tgsi_scan_shader(templ->tokens, &cvs->info);
+
+ cvs->draw_data = draw_create_vertex_shader(cell->draw, &cvs->shader);
+ if (cvs->draw_data == NULL) {
+ FREE( (void *) cvs->shader.tokens );
+ FREE( cvs );
+ return NULL;
+ }
+
+ return cvs;
+}
+
+
+/**
+ * Called via pipe->bind_vs_state()
+ */
+static void
+cell_bind_vs_state(struct pipe_context *pipe, void *vs)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ cell->vs = cell_vertex_shader_state(vs);
+
+ draw_bind_vertex_shader(cell->draw,
+ (cell->vs ? cell->vs->draw_data : NULL));
+
+ cell->dirty |= CELL_NEW_VS;
+}
+
+
+/**
+ * Called via pipe->delete_vs_state()
+ */
+static void
+cell_delete_vs_state(struct pipe_context *pipe, void *vs)
+{
+ struct cell_context *cell = cell_context(pipe);
+ struct cell_vertex_shader_state *cvs = cell_vertex_shader_state(vs);
+
+ draw_delete_vertex_shader(cell->draw, cvs->draw_data);
+ FREE( (void *) cvs->shader.tokens );
+ FREE( cvs );
+}
+
+
+/**
+ * Called via pipe->set_constant_buffer()
+ */
+static void
+cell_set_constant_buffer(struct pipe_context *pipe,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ assert(shader < PIPE_SHADER_TYPES);
+ assert(index == 0);
+
+ draw_flush(cell->draw);
+
+ /* note: reference counting */
+ pipe_buffer_reference(&cell->constants[shader].buffer, buf->buffer);
+
+ if (shader == PIPE_SHADER_VERTEX)
+ cell->dirty |= CELL_NEW_VS_CONSTANTS;
+ else if (shader == PIPE_SHADER_FRAGMENT)
+ cell->dirty |= CELL_NEW_FS_CONSTANTS;
+}
+
+
+void
+cell_init_shader_functions(struct cell_context *cell)
+{
+ cell->pipe.create_fs_state = cell_create_fs_state;
+ cell->pipe.bind_fs_state = cell_bind_fs_state;
+ cell->pipe.delete_fs_state = cell_delete_fs_state;
+
+ cell->pipe.create_vs_state = cell_create_vs_state;
+ cell->pipe.bind_vs_state = cell_bind_vs_state;
+ cell->pipe.delete_vs_state = cell_delete_vs_state;
+
+ cell->pipe.set_constant_buffer = cell_set_constant_buffer;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_state_vertex.c b/src/gallium/drivers/cell/ppu/cell_state_vertex.c
new file mode 100644
index 0000000000..fbe55c8472
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_state_vertex.c
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "cell_context.h"
+#include "cell_state.h"
+
+#include "draw/draw_context.h"
+
+
+static void
+cell_set_vertex_elements(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_element *elements)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ assert(count <= PIPE_MAX_ATTRIBS);
+
+ memcpy(cell->vertex_element, elements, count * sizeof(elements[0]));
+ cell->num_vertex_elements = count;
+
+ cell->dirty |= CELL_NEW_VERTEX;
+
+ draw_set_vertex_elements(cell->draw, count, elements);
+}
+
+
+static void
+cell_set_vertex_buffers(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_buffer *buffers)
+{
+ struct cell_context *cell = cell_context(pipe);
+
+ assert(count <= PIPE_MAX_ATTRIBS);
+
+ memcpy(cell->vertex_buffer, buffers, count * sizeof(buffers[0]));
+ cell->num_vertex_buffers = count;
+
+ cell->dirty |= CELL_NEW_VERTEX;
+
+ draw_set_vertex_buffers(cell->draw, count, buffers);
+}
+
+
+void
+cell_init_vertex_functions(struct cell_context *cell)
+{
+ cell->pipe.set_vertex_buffers = cell_set_vertex_buffers;
+ cell->pipe.set_vertex_elements = cell_set_vertex_elements;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_surface.c b/src/gallium/drivers/cell/ppu/cell_surface.c
new file mode 100644
index 0000000000..ffb8595d82
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_surface.c
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_rect.h"
+#include "cell_context.h"
+#include "cell_surface.h"
+
+
+static void
+cell_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ util_surface_copy(pipe, FALSE,
+ dest, destx, desty,
+ src, srcx, srcy,
+ width, height);
+}
+
+void
+cell_init_surface_functions(struct cell_context *cell)
+{
+ cell->pipe.surface_copy = cell_surface_copy;
+ cell->pipe.surface_fill = util_surface_fill;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_surface.h b/src/gallium/drivers/cell/ppu/cell_surface.h
new file mode 100644
index 0000000000..9e58f32944
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_surface.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef CELL_SURFACE_H
+#define CELL_SURFACE_H
+
+
+struct cell_context;
+
+
+extern void
+cell_init_surface_functions(struct cell_context *cell);
+
+
+#endif /* SP_SURFACE_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c
new file mode 100644
index 0000000000..6a63a0e6ce
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_texture.c
@@ -0,0 +1,497 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Michel Dänzer <michel@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "cell_context.h"
+#include "cell_state.h"
+#include "cell_texture.h"
+
+
+
+static void
+cell_texture_layout(struct cell_texture *ct)
+{
+ struct pipe_texture *pt = &ct->base;
+ unsigned level;
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+ unsigned depth = pt->depth[0];
+
+ ct->buffer_size = 0;
+
+ for (level = 0; level <= pt->last_level; level++) {
+ unsigned size;
+ unsigned w_tile, h_tile;
+
+ assert(level < CELL_MAX_TEXTURE_LEVELS);
+
+ /* width, height, rounded up to tile size */
+ w_tile = align(width, TILE_SIZE);
+ h_tile = align(height, TILE_SIZE);
+
+ pt->width[level] = width;
+ pt->height[level] = height;
+ pt->depth[level] = depth;
+ pt->nblocksx[level] = pf_get_nblocksx(&pt->block, w_tile);
+ pt->nblocksy[level] = pf_get_nblocksy(&pt->block, h_tile);
+
+ ct->stride[level] = pt->nblocksx[level] * pt->block.size;
+
+ ct->level_offset[level] = ct->buffer_size;
+
+ size = pt->nblocksx[level] * pt->nblocksy[level] * pt->block.size;
+ if (pt->target == PIPE_TEXTURE_CUBE)
+ size *= 6;
+ else
+ size *= depth;
+
+ ct->buffer_size += size;
+
+ width = minify(width);
+ height = minify(height);
+ depth = minify(depth);
+ }
+}
+
+
+static struct pipe_texture *
+cell_texture_create(struct pipe_screen *screen,
+ const struct pipe_texture *templat)
+{
+ struct cell_texture *ct = CALLOC_STRUCT(cell_texture);
+ if (!ct)
+ return NULL;
+
+ ct->base = *templat;
+ pipe_reference_init(&ct->base.reference, 1);
+ ct->base.screen = screen;
+
+ cell_texture_layout(ct);
+
+ ct->buffer = screen->buffer_create(screen, 32, PIPE_BUFFER_USAGE_PIXEL,
+ ct->buffer_size);
+
+ if (!ct->buffer) {
+ FREE(ct);
+ return NULL;
+ }
+
+ return &ct->base;
+}
+
+
+static void
+cell_texture_destroy(struct pipe_texture *pt)
+{
+ struct cell_texture *ct = cell_texture(pt);
+
+ if (ct->mapped) {
+ pipe_buffer_unmap(ct->buffer->screen, ct->buffer);
+ ct->mapped = NULL;
+ }
+
+ pipe_buffer_reference(&ct->buffer, NULL);
+
+ FREE(ct);
+}
+
+
+
+/**
+ * Convert image from linear layout to tiled layout. 4-byte pixels.
+ */
+static void
+twiddle_image_uint(uint w, uint h, uint tile_size, uint *dst,
+ uint src_stride, const uint *src)
+{
+ const uint tile_size2 = tile_size * tile_size;
+ const uint h_t = (h + tile_size - 1) / tile_size;
+ const uint w_t = (w + tile_size - 1) / tile_size;
+
+ uint it, jt; /* tile counters */
+ uint i, j; /* intra-tile counters */
+
+ src_stride /= 4; /* convert from bytes to pixels */
+
+ /* loop over dest tiles */
+ for (it = 0; it < h_t; it++) {
+ for (jt = 0; jt < w_t; jt++) {
+ /* start of dest tile: */
+ uint *tdst = dst + (it * w_t + jt) * tile_size2;
+
+ /* compute size of this tile (may be smaller than tile_size) */
+ /* XXX note: a compiler bug was found here. That's why the code
+ * looks as it does.
+ */
+ uint tile_width = w - jt * tile_size;
+ tile_width = MIN2(tile_width, tile_size);
+ uint tile_height = h - it * tile_size;
+ tile_height = MIN2(tile_height, tile_size);
+
+ /* loop over texels in the tile */
+ for (i = 0; i < tile_height; i++) {
+ for (j = 0; j < tile_width; j++) {
+ const uint srci = it * tile_size + i;
+ const uint srcj = jt * tile_size + j;
+ ASSERT(srci < h);
+ ASSERT(srcj < w);
+ tdst[i * tile_size + j] = src[srci * src_stride + srcj];
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * For Cell. Basically, rearrange the pixels/quads from this layout:
+ * +--+--+--+--+
+ * |p0|p1|p2|p3|....
+ * +--+--+--+--+
+ *
+ * to this layout:
+ * +--+--+
+ * |p0|p1|....
+ * +--+--+
+ * |p2|p3|
+ * +--+--+
+ */
+static void
+twiddle_tile(const uint *tileIn, uint *tileOut)
+{
+ int y, x;
+
+ for (y = 0; y < TILE_SIZE; y+=2) {
+ for (x = 0; x < TILE_SIZE; x+=2) {
+ int k = 4 * (y/2 * TILE_SIZE/2 + x/2);
+ tileOut[y * TILE_SIZE + (x + 0)] = tileIn[k];
+ tileOut[y * TILE_SIZE + (x + 1)] = tileIn[k+1];
+ tileOut[(y + 1) * TILE_SIZE + (x + 0)] = tileIn[k+2];
+ tileOut[(y + 1) * TILE_SIZE + (x + 1)] = tileIn[k+3];
+ }
+ }
+}
+
+
+/**
+ * Convert image from tiled layout to linear layout. 4-byte pixels.
+ */
+static void
+untwiddle_image_uint(uint w, uint h, uint tile_size, uint *dst,
+ uint dst_stride, const uint *src)
+{
+ const uint tile_size2 = tile_size * tile_size;
+ const uint h_t = (h + tile_size - 1) / tile_size;
+ const uint w_t = (w + tile_size - 1) / tile_size;
+ uint *tile_buf;
+ uint it, jt; /* tile counters */
+ uint i, j; /* intra-tile counters */
+
+ dst_stride /= 4; /* convert from bytes to pixels */
+
+ tile_buf = align_malloc(tile_size * tile_size * 4, 16);
+
+ /* loop over src tiles */
+ for (it = 0; it < h_t; it++) {
+ for (jt = 0; jt < w_t; jt++) {
+ /* start of src tile: */
+ const uint *tsrc = src + (it * w_t + jt) * tile_size2;
+
+ twiddle_tile(tsrc, tile_buf);
+ tsrc = tile_buf;
+
+ /* compute size of this tile (may be smaller than tile_size) */
+ /* XXX note: a compiler bug was found here. That's why the code
+ * looks as it does.
+ */
+ uint tile_width = w - jt * tile_size;
+ tile_width = MIN2(tile_width, tile_size);
+ uint tile_height = h - it * tile_size;
+ tile_height = MIN2(tile_height, tile_size);
+
+ /* loop over texels in the tile */
+ for (i = 0; i < tile_height; i++) {
+ for (j = 0; j < tile_width; j++) {
+ uint dsti = it * tile_size + i;
+ uint dstj = jt * tile_size + j;
+ ASSERT(dsti < h);
+ ASSERT(dstj < w);
+ dst[dsti * dst_stride + dstj] = tsrc[i * tile_size + j];
+ }
+ }
+ }
+ }
+
+ align_free(tile_buf);
+}
+
+
+static struct pipe_surface *
+cell_get_tex_surface(struct pipe_screen *screen,
+ struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned usage)
+{
+ struct cell_texture *ct = cell_texture(pt);
+ struct pipe_surface *ps;
+
+ ps = CALLOC_STRUCT(pipe_surface);
+ if (ps) {
+ pipe_reference_init(&ps->reference, 1);
+ pipe_texture_reference(&ps->texture, pt);
+ ps->format = pt->format;
+ ps->width = pt->width[level];
+ ps->height = pt->height[level];
+ ps->offset = ct->level_offset[level];
+ /* XXX may need to override usage flags (see sp_texture.c) */
+ ps->usage = usage;
+ ps->face = face;
+ ps->level = level;
+ ps->zslice = zslice;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ps->offset += face * pt->nblocksy[level] * ct->stride[level];
+ }
+ else if (pt->target == PIPE_TEXTURE_3D) {
+ ps->offset += zslice * pt->nblocksy[level] * ct->stride[level];
+ }
+ else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+ }
+ return ps;
+}
+
+
+static void
+cell_tex_surface_destroy(struct pipe_surface *surf)
+{
+ pipe_texture_reference(&surf->texture, NULL);
+ FREE(surf);
+}
+
+
+/**
+ * Create new pipe_transfer object.
+ * This is used by the user to put tex data into a texture (and get it
+ * back out for glGetTexImage).
+ */
+static struct pipe_transfer *
+cell_get_tex_transfer(struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct cell_texture *ct = cell_texture(texture);
+ struct cell_transfer *ctrans;
+
+ assert(texture);
+ assert(level <= texture->last_level);
+
+ ctrans = CALLOC_STRUCT(cell_transfer);
+ if (ctrans) {
+ struct pipe_transfer *pt = &ctrans->base;
+ pipe_texture_reference(&pt->texture, texture);
+ pt->format = texture->format;
+ pt->block = texture->block;
+ pt->x = x;
+ pt->y = y;
+ pt->width = w;
+ pt->height = h;
+ pt->nblocksx = texture->nblocksx[level];
+ pt->nblocksy = texture->nblocksy[level];
+ pt->stride = ct->stride[level];
+ pt->usage = usage;
+ pt->face = face;
+ pt->level = level;
+ pt->zslice = zslice;
+
+ ctrans->offset = ct->level_offset[level];
+
+ if (texture->target == PIPE_TEXTURE_CUBE) {
+ ctrans->offset += face * pt->nblocksy * pt->stride;
+ }
+ else if (texture->target == PIPE_TEXTURE_3D) {
+ ctrans->offset += zslice * pt->nblocksy * pt->stride;
+ }
+ else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+ return pt;
+ }
+ return NULL;
+}
+
+
+static void
+cell_tex_transfer_destroy(struct pipe_transfer *t)
+{
+ struct cell_transfer *transfer = cell_transfer(t);
+ /* Effectively do the texture_update work here - if texture images
+ * needed post-processing to put them into hardware layout, this is
+ * where it would happen. For cell, nothing to do.
+ */
+ assert (transfer->base.texture);
+ pipe_texture_reference(&transfer->base.texture, NULL);
+ FREE(transfer);
+}
+
+
+/**
+ * Return pointer to texture image data in linear layout.
+ */
+static void *
+cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer)
+{
+ struct cell_transfer *ctrans = cell_transfer(transfer);
+ struct pipe_texture *pt = transfer->texture;
+ struct cell_texture *ct = cell_texture(pt);
+ const uint level = ctrans->base.level;
+ const uint texWidth = pt->width[level];
+ const uint texHeight = pt->height[level];
+ const uint stride = ct->stride[level];
+ unsigned flags = 0x0;
+ unsigned size;
+
+ assert(transfer->texture);
+
+ if (transfer->usage != PIPE_TRANSFER_READ) {
+ flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
+ }
+
+ if (transfer->usage != PIPE_TRANSFER_WRITE) {
+ flags |= PIPE_BUFFER_USAGE_CPU_READ;
+ }
+
+ if (!ct->mapped) {
+ /* map now */
+ ct->mapped = pipe_buffer_map(screen, ct->buffer, flags);
+ }
+
+ /*
+ * Create a buffer of ordinary memory for the linear texture.
+ * This is the memory that the user will read/write.
+ */
+ size = pt->nblocksx[level] * pt->nblocksy[level] * pt->block.size;
+
+ ctrans->map = align_malloc(size, 16);
+ if (!ctrans->map)
+ return NULL; /* out of memory */
+
+ if (transfer->usage == PIPE_TRANSFER_READ ||
+ transfer->usage == PIPE_TRANSFER_READ_WRITE) {
+ /* need to untwiddle the texture to make a linear version */
+ const uint bpp = pf_get_size(ct->base.format);
+ if (bpp == 4) {
+ const uint *src = (uint *) (ct->mapped + ctrans->offset);
+ uint *dst = ctrans->map;
+ untwiddle_image_uint(texWidth, texHeight, TILE_SIZE,
+ dst, stride, src);
+ }
+ else {
+ // xxx fix
+ }
+ }
+
+ return ctrans->map;
+}
+
+
+/**
+ * Called when user is done reading/writing texture data.
+ * If new data was written, this is where we convert the linear data
+ * to tiled data.
+ */
+static void
+cell_transfer_unmap(struct pipe_screen *screen,
+ struct pipe_transfer *transfer)
+{
+ struct cell_transfer *ctrans = cell_transfer(transfer);
+ struct pipe_texture *pt = transfer->texture;
+ struct cell_texture *ct = cell_texture(pt);
+ const uint level = ctrans->base.level;
+ const uint texWidth = pt->width[level];
+ const uint texHeight = pt->height[level];
+ const uint stride = ct->stride[level];
+
+ if (!ct->mapped) {
+ /* map now */
+ ct->mapped = pipe_buffer_map(screen, ct->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ }
+
+ if (transfer->usage == PIPE_TRANSFER_WRITE ||
+ transfer->usage == PIPE_TRANSFER_READ_WRITE) {
+ /* The user wrote new texture data into the mapped buffer.
+ * We need to convert the new linear data into the twiddled/tiled format.
+ */
+ const uint bpp = pf_get_size(ct->base.format);
+ if (bpp == 4) {
+ const uint *src = ctrans->map;
+ uint *dst = (uint *) (ct->mapped + ctrans->offset);
+ twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst, stride, src);
+ }
+ else {
+ // xxx fix
+ }
+ }
+
+ align_free(ctrans->map);
+ ctrans->map = NULL;
+}
+
+
+void
+cell_init_screen_texture_funcs(struct pipe_screen *screen)
+{
+ screen->texture_create = cell_texture_create;
+ screen->texture_destroy = cell_texture_destroy;
+
+ screen->get_tex_surface = cell_get_tex_surface;
+ screen->tex_surface_destroy = cell_tex_surface_destroy;
+
+ screen->get_tex_transfer = cell_get_tex_transfer;
+ screen->tex_transfer_destroy = cell_tex_transfer_destroy;
+
+ screen->transfer_map = cell_transfer_map;
+ screen->transfer_unmap = cell_transfer_unmap;
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_texture.h b/src/gallium/drivers/cell/ppu/cell_texture.h
new file mode 100644
index 0000000000..3ffc0bfdb5
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_texture.h
@@ -0,0 +1,86 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef CELL_TEXTURE_H
+#define CELL_TEXTURE_H
+
+
+struct cell_context;
+struct pipe_texture;
+
+
+/**
+ * Subclass of pipe_texture
+ */
+struct cell_texture
+{
+ struct pipe_texture base;
+
+ unsigned long level_offset[CELL_MAX_TEXTURE_LEVELS];
+ unsigned long stride[CELL_MAX_TEXTURE_LEVELS];
+
+ /** The tiled texture data is held in this buffer */
+ struct pipe_buffer *buffer;
+ unsigned long buffer_size;
+
+ /** The buffer above, mapped. This is the memory from which the
+ * SPUs will fetch texels. This texture data is in the tiled layout.
+ */
+ ubyte *mapped;
+};
+
+
+struct cell_transfer
+{
+ struct pipe_transfer base;
+
+ unsigned long offset;
+ void *map;
+};
+
+
+/** cast wrapper */
+static INLINE struct cell_texture *
+cell_texture(struct pipe_texture *pt)
+{
+ return (struct cell_texture *) pt;
+}
+
+
+/** cast wrapper */
+static INLINE struct cell_transfer *
+cell_transfer(struct pipe_transfer *pt)
+{
+ return (struct cell_transfer *) pt;
+}
+
+
+extern void
+cell_init_screen_texture_funcs(struct pipe_screen *screen);
+
+
+#endif /* CELL_TEXTURE_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_vbuf.c b/src/gallium/drivers/cell/ppu/cell_vbuf.c
new file mode 100644
index 0000000000..cfaffb52a8
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_vbuf.c
@@ -0,0 +1,332 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Vertex buffer code. The draw module transforms vertices to window
+ * coords, etc. and emits the vertices into buffer supplied by this module.
+ * When a vertex buffer is full, or we flush, we'll send the vertex data
+ * to the SPUs.
+ *
+ * Authors
+ * Brian Paul
+ */
+
+
+#include "cell_batch.h"
+#include "cell_context.h"
+#include "cell_fence.h"
+#include "cell_flush.h"
+#include "cell_spu.h"
+#include "cell_vbuf.h"
+#include "draw/draw_vbuf.h"
+#include "util/u_memory.h"
+
+
+/** Allow vertex data to be inlined after RENDER command */
+#define ALLOW_INLINE_VERTS 1
+
+
+/**
+ * Subclass of vbuf_render because we need a cell_context pointer in
+ * a few places.
+ */
+struct cell_vbuf_render
+{
+ struct vbuf_render base;
+ struct cell_context *cell;
+ uint prim; /**< PIPE_PRIM_x */
+ uint vertex_size; /**< in bytes */
+ void *vertex_buffer; /**< just for debug, really */
+ uint vertex_buf; /**< in [0, CELL_NUM_BUFFERS-1] */
+ uint vertex_buffer_size; /**< size in bytes */
+};
+
+
+/** cast wrapper */
+static struct cell_vbuf_render *
+cell_vbuf_render(struct vbuf_render *vbr)
+{
+ return (struct cell_vbuf_render *) vbr;
+}
+
+
+
+static const struct vertex_info *
+cell_vbuf_get_vertex_info(struct vbuf_render *vbr)
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ return &cvbr->cell->vertex_info;
+}
+
+
+static boolean
+cell_vbuf_allocate_vertices(struct vbuf_render *vbr,
+ ushort vertex_size, ushort nr_vertices)
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ unsigned size = vertex_size * nr_vertices;
+ /*printf("Alloc verts %u * %u\n", vertex_size, nr_vertices);*/
+
+ assert(cvbr->vertex_buf == ~0);
+ cvbr->vertex_buf = cell_get_empty_buffer(cvbr->cell);
+ cvbr->vertex_buffer = cvbr->cell->buffer[cvbr->vertex_buf];
+ cvbr->vertex_buffer_size = size;
+ cvbr->vertex_size = vertex_size;
+
+ return cvbr->vertex_buffer != NULL;
+}
+
+
+static void
+cell_vbuf_release_vertices(struct vbuf_render *vbr)
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ struct cell_context *cell = cvbr->cell;
+
+ /*
+ printf("%s vertex_buf = %u count = %u\n",
+ __FUNCTION__, cvbr->vertex_buf, vertices_used);
+ */
+
+ /* Make sure texture buffers aren't released until we're done rendering
+ * with them.
+ */
+ cell_add_fenced_textures(cell);
+
+ /* Tell SPUs they can release the vert buf */
+ if (cvbr->vertex_buf != ~0U) {
+ STATIC_ASSERT(sizeof(struct cell_command_release_verts) % 16 == 0);
+ struct cell_command_release_verts *release
+ = (struct cell_command_release_verts *)
+ cell_batch_alloc16(cell, sizeof(struct cell_command_release_verts));
+ release->opcode[0] = CELL_CMD_RELEASE_VERTS;
+ release->vertex_buf = cvbr->vertex_buf;
+ }
+
+ cvbr->vertex_buf = ~0;
+ cell_flush_int(cell, 0x0);
+
+ cvbr->vertex_buffer = NULL;
+}
+
+
+static void *
+cell_vbuf_map_vertices(struct vbuf_render *vbr)
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ return cvbr->vertex_buffer;
+}
+
+
+static void
+cell_vbuf_unmap_vertices(struct vbuf_render *vbr,
+ ushort min_index,
+ ushort max_index )
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
+ /* do nothing */
+}
+
+
+
+static boolean
+cell_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ cvbr->prim = prim;
+ /*printf("cell_set_prim %u\n", prim);*/
+ return TRUE;
+}
+
+
+static void
+cell_vbuf_draw(struct vbuf_render *vbr,
+ const ushort *indices,
+ uint nr_indices)
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ struct cell_context *cell = cvbr->cell;
+ float xmin, ymin, xmax, ymax;
+ uint i;
+ uint nr_vertices = 0, min_index = ~0;
+ const void *vertices = cvbr->vertex_buffer;
+ const uint vertex_size = cvbr->vertex_size;
+
+ for (i = 0; i < nr_indices; i++) {
+ if (indices[i] > nr_vertices)
+ nr_vertices = indices[i];
+ if (indices[i] < min_index)
+ min_index = indices[i];
+ }
+ nr_vertices++;
+
+#if 0
+ /*if (min_index > 0)*/
+ printf("%s min_index = %u\n", __FUNCTION__, min_index);
+#endif
+
+#if 0
+ printf("cell_vbuf_draw() nr_indices = %u nr_verts = %u\n",
+ nr_indices, nr_vertices);
+ printf(" ");
+ for (i = 0; i < nr_indices; i += 3) {
+ printf("%u %u %u, ", indices[i+0], indices[i+1], indices[i+2]);
+ }
+ printf("\n");
+#elif 0
+ printf("cell_vbuf_draw() nr_indices = %u nr_verts = %u indexes = [%u %u %u ...]\n",
+ nr_indices, nr_vertices,
+ indices[0], indices[1], indices[2]);
+ printf("ind space = %u, vert space = %u, space = %u\n",
+ nr_indices * 2,
+ nr_vertices * 4 * cell->vertex_info.size,
+ cell_batch_free_space(cell));
+#endif
+
+ /* compute x/y bounding box */
+ xmin = ymin = 1e50;
+ xmax = ymax = -1e50;
+ for (i = min_index; i < nr_vertices; i++) {
+ const float *v = (float *) ((ubyte *) vertices + i * vertex_size);
+ if (v[0] < xmin)
+ xmin = v[0];
+ if (v[0] > xmax)
+ xmax = v[0];
+ if (v[1] < ymin)
+ ymin = v[1];
+ if (v[1] > ymax)
+ ymax = v[1];
+ }
+#if 0
+ printf("PPU Bounds %g, %g .. %g, %g\n", xmin, ymin, xmax, ymax);
+ fflush(stdout);
+#endif
+
+ if (cvbr->prim != PIPE_PRIM_TRIANGLES)
+ return; /* only render tris for now */
+
+ /* build/insert batch RENDER command */
+ {
+ const uint index_bytes = ROUNDUP16(nr_indices * 2);
+ const uint vertex_bytes = ROUNDUP16(nr_vertices * 4 * cell->vertex_info.size);
+ STATIC_ASSERT(sizeof(struct cell_command_render) % 16 == 0);
+ const uint batch_size = sizeof(struct cell_command_render) + index_bytes;
+
+ struct cell_command_render *render
+ = (struct cell_command_render *)
+ cell_batch_alloc16(cell, batch_size);
+
+ render->opcode[0] = CELL_CMD_RENDER;
+ render->prim_type = cvbr->prim;
+
+ render->num_indexes = nr_indices;
+ render->min_index = min_index;
+
+ /* append indices after render command */
+ memcpy(render + 1, indices, nr_indices * 2);
+
+ /* if there's room, append vertices after the indices, else leave
+ * vertices in the original/separate buffer.
+ */
+ render->vertex_size = 4 * cell->vertex_info.size;
+ render->num_verts = nr_vertices;
+ if (ALLOW_INLINE_VERTS &&
+ min_index == 0 &&
+ vertex_bytes + 16 <= cell_batch_free_space(cell)) {
+ /* vertex data inlined, after indices, at 16-byte boundary */
+ void *dst = cell_batch_alloc16(cell, vertex_bytes);
+ memcpy(dst, vertices, vertex_bytes);
+ render->inline_verts = TRUE;
+ render->vertex_buf = ~0;
+ }
+ else {
+ /* vertex data in separate buffer */
+ render->inline_verts = FALSE;
+ ASSERT(cvbr->vertex_buf >= 0);
+ render->vertex_buf = cvbr->vertex_buf;
+ }
+
+ render->xmin = xmin;
+ render->ymin = ymin;
+ render->xmax = xmax;
+ render->ymax = ymax;
+ }
+
+#if 0
+ /* helpful for debug */
+ cell_flush_int(cell, CELL_FLUSH_WAIT);
+#endif
+}
+
+
+static void
+cell_vbuf_destroy(struct vbuf_render *vbr)
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ cvbr->cell->vbuf_render = NULL;
+ FREE(cvbr);
+}
+
+
+/**
+ * Initialize the post-transform vertex buffer information for the given
+ * context.
+ */
+void
+cell_init_vbuf(struct cell_context *cell)
+{
+ assert(cell->draw);
+
+ cell->vbuf_render = CALLOC_STRUCT(cell_vbuf_render);
+
+ /* The max number of indexes is what can fix into a batch buffer,
+ * minus the render and release-verts commands.
+ */
+ cell->vbuf_render->base.max_indices
+ = (CELL_BUFFER_SIZE
+ - sizeof(struct cell_command_render)
+ - sizeof(struct cell_command_release_verts))
+ / sizeof(ushort);
+ cell->vbuf_render->base.max_vertex_buffer_bytes = CELL_BUFFER_SIZE;
+
+ cell->vbuf_render->base.get_vertex_info = cell_vbuf_get_vertex_info;
+ cell->vbuf_render->base.allocate_vertices = cell_vbuf_allocate_vertices;
+ cell->vbuf_render->base.map_vertices = cell_vbuf_map_vertices;
+ cell->vbuf_render->base.unmap_vertices = cell_vbuf_unmap_vertices;
+ cell->vbuf_render->base.set_primitive = cell_vbuf_set_primitive;
+ cell->vbuf_render->base.draw = cell_vbuf_draw;
+ cell->vbuf_render->base.release_vertices = cell_vbuf_release_vertices;
+ cell->vbuf_render->base.destroy = cell_vbuf_destroy;
+
+ cell->vbuf_render->cell = cell;
+#if 1
+ cell->vbuf_render->vertex_buf = ~0;
+#endif
+
+ cell->vbuf = draw_vbuf_stage(cell->draw, &cell->vbuf_render->base);
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_vbuf.h b/src/gallium/drivers/cell/ppu/cell_vbuf.h
new file mode 100644
index 0000000000..d265cbf770
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_vbuf.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef CELL_VBUF_H
+#define CELL_VBUF_H
+
+
+struct cell_context;
+
+extern void
+cell_init_vbuf(struct cell_context *cell);
+
+
+#endif /* CELL_VBUF_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c b/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c
new file mode 100644
index 0000000000..9cba537d9e
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c
@@ -0,0 +1,346 @@
+/*
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <inttypes.h>
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+#include "pipe/p_format.h"
+
+#include "../auxiliary/draw/draw_context.h"
+#include "../auxiliary/draw/draw_private.h"
+
+#include "cell_context.h"
+#include "rtasm/rtasm_ppc_spe.h"
+
+
+/**
+ * Emit a 4x4 matrix transpose operation
+ *
+ * \param p Function that the transpose operation is to be appended to
+ * \param row0 Register containing row 0 of the source matrix
+ * \param row1 Register containing row 1 of the source matrix
+ * \param row2 Register containing row 2 of the source matrix
+ * \param row3 Register containing row 3 of the source matrix
+ * \param dest_ptr Register containing the address of the destination matrix
+ * \param shuf_ptr Register containing the address of the shuffled data
+ * \param count Number of colums to actually be written to the destination
+ *
+ * \note
+ * This function assumes that the registers named by \c row0, \c row1,
+ * \c row2, and \c row3 are scratch and can be modified by the generated code.
+ * Furthermore, these registers will be released, via calls to
+ * \c release_register, by this function.
+ *
+ * \note
+ * This function requires that four temporary are available on entry.
+ */
+static void
+emit_matrix_transpose(struct spe_function *p,
+ unsigned row0, unsigned row1, unsigned row2,
+ unsigned row3, unsigned dest_ptr,
+ unsigned shuf_ptr, unsigned count)
+{
+ int shuf_hi = spe_allocate_available_register(p);
+ int shuf_lo = spe_allocate_available_register(p);
+ int t1 = spe_allocate_available_register(p);
+ int t2 = spe_allocate_available_register(p);
+ int t3;
+ int t4;
+ int col0;
+ int col1;
+ int col2;
+ int col3;
+
+
+ spe_lqd(p, shuf_hi, shuf_ptr, 3*16);
+ spe_lqd(p, shuf_lo, shuf_ptr, 4*16);
+ spe_shufb(p, t1, row0, row2, shuf_hi);
+ spe_shufb(p, t2, row0, row2, shuf_lo);
+
+
+ /* row0 and row2 are now no longer needed. Re-use those registers as
+ * temporaries.
+ */
+ t3 = row0;
+ t4 = row2;
+
+ spe_shufb(p, t3, row1, row3, shuf_hi);
+ spe_shufb(p, t4, row1, row3, shuf_lo);
+
+
+ /* row1 and row3 are now no longer needed. Re-use those registers as
+ * temporaries.
+ */
+ col0 = row1;
+ col1 = row3;
+
+ spe_shufb(p, col0, t1, t3, shuf_hi);
+ if (count > 1) {
+ spe_shufb(p, col1, t1, t3, shuf_lo);
+ }
+
+ /* t1 and t3 are now no longer needed. Re-use those registers as
+ * temporaries.
+ */
+ col2 = t1;
+ col3 = t3;
+
+ if (count > 2) {
+ spe_shufb(p, col2, t2, t4, shuf_hi);
+ }
+
+ if (count > 3) {
+ spe_shufb(p, col3, t2, t4, shuf_lo);
+ }
+
+
+ /* Store the results. Remember that the stqd instruction is encoded using
+ * the qword offset (stand-alone assemblers to the byte-offset to
+ * qword-offset conversion for you), so the byte-offset needs be divided by
+ * 16.
+ */
+ switch (count) {
+ case 4:
+ spe_stqd(p, col3, dest_ptr, 3 * 16);
+ case 3:
+ spe_stqd(p, col2, dest_ptr, 2 * 16);
+ case 2:
+ spe_stqd(p, col1, dest_ptr, 1 * 16);
+ case 1:
+ spe_stqd(p, col0, dest_ptr, 0 * 16);
+ }
+
+
+ /* Release all of the temporary registers used.
+ */
+ spe_release_register(p, col0);
+ spe_release_register(p, col1);
+ spe_release_register(p, col2);
+ spe_release_register(p, col3);
+ spe_release_register(p, shuf_hi);
+ spe_release_register(p, shuf_lo);
+ spe_release_register(p, t2);
+ spe_release_register(p, t4);
+}
+
+
+#if 0
+/* This appears to not be used currently */
+static void
+emit_fetch(struct spe_function *p,
+ unsigned in_ptr, unsigned *offset,
+ unsigned out_ptr, unsigned shuf_ptr,
+ enum pipe_format format)
+{
+ const unsigned count = (pf_size_x(format) != 0) + (pf_size_y(format) != 0)
+ + (pf_size_z(format) != 0) + (pf_size_w(format) != 0);
+ const unsigned type = pf_type(format);
+ const unsigned bytes = pf_size_x(format);
+
+ int v0 = spe_allocate_available_register(p);
+ int v1 = spe_allocate_available_register(p);
+ int v2 = spe_allocate_available_register(p);
+ int v3 = spe_allocate_available_register(p);
+ int tmp = spe_allocate_available_register(p);
+ int float_zero = -1;
+ int float_one = -1;
+ float scale_signed = 0.0;
+ float scale_unsigned = 0.0;
+
+ spe_lqd(p, v0, in_ptr, (0 + offset[0]) * 16);
+ spe_lqd(p, v1, in_ptr, (1 + offset[0]) * 16);
+ spe_lqd(p, v2, in_ptr, (2 + offset[0]) * 16);
+ spe_lqd(p, v3, in_ptr, (3 + offset[0]) * 16);
+ offset[0] += 4;
+
+ switch (bytes) {
+ case 1:
+ scale_signed = 1.0f / 127.0f;
+ scale_unsigned = 1.0f / 255.0f;
+ spe_lqd(p, tmp, shuf_ptr, 1 * 16);
+ spe_shufb(p, v0, v0, v0, tmp);
+ spe_shufb(p, v1, v1, v1, tmp);
+ spe_shufb(p, v2, v2, v2, tmp);
+ spe_shufb(p, v3, v3, v3, tmp);
+ break;
+ case 2:
+ scale_signed = 1.0f / 32767.0f;
+ scale_unsigned = 1.0f / 65535.0f;
+ spe_lqd(p, tmp, shuf_ptr, 2 * 16);
+ spe_shufb(p, v0, v0, v0, tmp);
+ spe_shufb(p, v1, v1, v1, tmp);
+ spe_shufb(p, v2, v2, v2, tmp);
+ spe_shufb(p, v3, v3, v3, tmp);
+ break;
+ case 4:
+ scale_signed = 1.0f / 2147483647.0f;
+ scale_unsigned = 1.0f / 4294967295.0f;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ switch (type) {
+ case PIPE_FORMAT_TYPE_FLOAT:
+ break;
+ case PIPE_FORMAT_TYPE_UNORM:
+ spe_ilhu(p, tmp, ((unsigned) scale_unsigned) >> 16);
+ spe_iohl(p, tmp, ((unsigned) scale_unsigned) & 0x0ffff);
+ spe_cuflt(p, v0, v0, 0);
+ spe_fm(p, v0, v0, tmp);
+ break;
+ case PIPE_FORMAT_TYPE_SNORM:
+ spe_ilhu(p, tmp, ((unsigned) scale_signed) >> 16);
+ spe_iohl(p, tmp, ((unsigned) scale_signed) & 0x0ffff);
+ spe_csflt(p, v0, v0, 0);
+ spe_fm(p, v0, v0, tmp);
+ break;
+ case PIPE_FORMAT_TYPE_USCALED:
+ spe_cuflt(p, v0, v0, 0);
+ break;
+ case PIPE_FORMAT_TYPE_SSCALED:
+ spe_csflt(p, v0, v0, 0);
+ break;
+ }
+
+
+ if (count < 4) {
+ float_one = spe_allocate_available_register(p);
+ spe_il(p, float_one, 1);
+ spe_cuflt(p, float_one, float_one, 0);
+
+ if (count < 3) {
+ float_zero = spe_allocate_available_register(p);
+ spe_il(p, float_zero, 0);
+ }
+ }
+
+ spe_release_register(p, tmp);
+
+ emit_matrix_transpose(p, v0, v1, v2, v3, out_ptr, shuf_ptr, count);
+
+ switch (count) {
+ case 1:
+ spe_stqd(p, float_zero, out_ptr, 1 * 16);
+ case 2:
+ spe_stqd(p, float_zero, out_ptr, 2 * 16);
+ case 3:
+ spe_stqd(p, float_one, out_ptr, 3 * 16);
+ }
+
+ if (float_zero != -1) {
+ spe_release_register(p, float_zero);
+ }
+
+ if (float_one != -1) {
+ spe_release_register(p, float_one);
+ }
+}
+#endif
+
+
+void cell_update_vertex_fetch(struct draw_context *draw)
+{
+#if 0
+ struct cell_context *const cell =
+ (struct cell_context *) draw->driver_private;
+ struct spe_function *p = &cell->attrib_fetch;
+ unsigned function_index[PIPE_MAX_ATTRIBS];
+ unsigned unique_attr_formats;
+ int out_ptr;
+ int in_ptr;
+ int shuf_ptr;
+ unsigned i;
+ unsigned j;
+
+
+ /* Determine how many unique input attribute formats there are. At the
+ * same time, store the index of the lowest numbered attribute that has
+ * the same format as any non-unique format.
+ */
+ unique_attr_formats = 1;
+ function_index[0] = 0;
+ for (i = 1; i < draw->vertex_fetch.nr_attrs; i++) {
+ const enum pipe_format curr_fmt = draw->vertex_element[i].src_format;
+
+ for (j = 0; j < i; j++) {
+ if (curr_fmt == draw->vertex_element[j].src_format) {
+ break;
+ }
+ }
+
+ if (j == i) {
+ unique_attr_formats++;
+ }
+
+ function_index[i] = j;
+ }
+
+
+ /* Each fetch function can be a maximum of 34 instructions (note: this is
+ * actually a slight over-estimate).
+ */
+ spe_init_func(p, 34 * SPE_INST_SIZE * unique_attr_formats);
+
+
+ /* Allocate registers for the function's input parameters.
+ */
+ out_ptr = spe_allocate_register(p, 3);
+ in_ptr = spe_allocate_register(p, 4);
+ shuf_ptr = spe_allocate_register(p, 5);
+
+
+ /* Generate code for the individual attribute fetch functions.
+ */
+ for (i = 0; i < draw->vertex_fetch.nr_attrs; i++) {
+ unsigned offset;
+
+ if (function_index[i] == i) {
+ cell->attrib_fetch_offsets[i] = (unsigned) ((void *) p->csr
+ - (void *) p->store);
+
+ offset = 0;
+ emit_fetch(p, in_ptr, &offset, out_ptr, shuf_ptr,
+ draw->vertex_element[i].src_format);
+ spe_bi(p, 0, 0, 0);
+
+ /* Round up to the next 16-byte boundary.
+ */
+ if ((((unsigned) p->store) & 0x0f) != 0) {
+ const unsigned align = ((unsigned) p->store) & 0x0f;
+ p->store = (uint32_t *) (((void *) p->store) + align);
+ }
+ } else {
+ /* Use the same function entry-point as a previously seen attribute
+ * with the same format.
+ */
+ cell->attrib_fetch_offsets[i] =
+ cell->attrib_fetch_offsets[function_index[i]];
+ }
+ }
+#else
+ assert(0);
+#endif
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c
new file mode 100644
index 0000000000..403cf6d50f
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c
@@ -0,0 +1,146 @@
+/*
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file cell_vertex_shader.c
+ * Vertex shader interface routines for Cell.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_math.h"
+
+#include "cell_context.h"
+#include "cell_draw_arrays.h"
+#include "cell_flush.h"
+#include "cell_spu.h"
+#include "cell_batch.h"
+
+#include "cell/common.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+
+/**
+ * Run the vertex shader on all vertices in the vertex queue.
+ * Called by the draw module when the vertx cache needs to be flushed.
+ */
+void
+cell_vertex_shader_queue_flush(struct draw_context *draw)
+{
+#if 0
+ struct cell_context *const cell =
+ (struct cell_context *) draw->driver_private;
+ struct cell_command_vs *const vs = &cell_global.command[0].vs;
+ uint64_t *batch;
+ struct cell_array_info *array_info;
+ unsigned i, j;
+ struct cell_attribute_fetch_code *cf;
+
+ assert(draw->vs.queue_nr != 0);
+
+ /* XXX: do this on statechange:
+ */
+ draw_update_vertex_fetch(draw);
+ cell_update_vertex_fetch(draw);
+
+
+ batch = cell_batch_alloc(cell, sizeof(batch[0]) + sizeof(*cf));
+ batch[0] = CELL_CMD_STATE_ATTRIB_FETCH;
+ cf = (struct cell_attribute_fetch_code *) (&batch[1]);
+ cf->base = (uint64_t) cell->attrib_fetch.store;
+ cf->size = ROUNDUP16((unsigned)((void *) cell->attrib_fetch.csr
+ - (void *) cell->attrib_fetch.store));
+
+
+ for (i = 0; i < draw->vertex_fetch.nr_attrs; i++) {
+ const enum pipe_format format = draw->vertex_element[i].src_format;
+ const unsigned count = ((pf_size_x(format) != 0)
+ + (pf_size_y(format) != 0)
+ + (pf_size_z(format) != 0)
+ + (pf_size_w(format) != 0));
+ const unsigned size = pf_size_x(format) * count;
+
+ batch = cell_batch_alloc(cell, sizeof(batch[0]) + sizeof(*array_info));
+
+ batch[0] = CELL_CMD_STATE_VS_ARRAY_INFO;
+
+ array_info = (struct cell_array_info *) &batch[1];
+ assert(draw->vertex_fetch.src_ptr[i] != NULL);
+ array_info->base = (uintptr_t) draw->vertex_fetch.src_ptr[i];
+ array_info->attr = i;
+ array_info->pitch = draw->vertex_fetch.pitch[i];
+ array_info->size = size;
+ array_info->function_offset = cell->attrib_fetch_offsets[i];
+ }
+
+ batch = cell_batch_alloc(cell, sizeof(batch[0])
+ + sizeof(struct pipe_viewport_state));
+ batch[0] = CELL_CMD_STATE_VIEWPORT;
+ (void) memcpy(&batch[1], &draw->viewport,
+ sizeof(struct pipe_viewport_state));
+
+ {
+ uint64_t uniforms = (uintptr_t) draw->user.constants;
+
+ batch = cell_batch_alloc(cell, 2 *sizeof(batch[0]));
+ batch[0] = CELL_CMD_STATE_UNIFORMS;
+ batch[1] = uniforms;
+ }
+
+ cell_batch_flush(cell);
+
+ vs->opcode = CELL_CMD_VS_EXECUTE;
+ vs->nr_attrs = draw->vertex_fetch.nr_attrs;
+
+ (void) memcpy(vs->plane, draw->plane, sizeof(draw->plane));
+ vs->nr_planes = draw->nr_planes;
+
+ for (i = 0; i < draw->vs.queue_nr; i += SPU_VERTS_PER_BATCH) {
+ const unsigned n = MIN2(SPU_VERTS_PER_BATCH, draw->vs.queue_nr - i);
+
+ for (j = 0; j < n; j++) {
+ vs->elts[j] = draw->vs.queue[i + j].elt;
+ vs->vOut[j] = (uintptr_t) draw->vs.queue[i + j].vertex;
+ }
+
+ for (/* empty */; j < SPU_VERTS_PER_BATCH; j++) {
+ vs->elts[j] = vs->elts[0];
+ vs->vOut[j] = (uintptr_t) draw->vs.queue[i + j].vertex;
+ }
+
+ vs->num_elts = n;
+ send_mbox_message(cell_global.spe_contexts[0], CELL_CMD_VS_EXECUTE);
+
+ cell_flush_int(cell, CELL_FLUSH_WAIT);
+ }
+
+ draw->vs.post_nr = draw->vs.queue_nr;
+ draw->vs.queue_nr = 0;
+#else
+ assert(0);
+#endif
+}
diff --git a/src/gallium/drivers/cell/ppu/cell_winsys.h b/src/gallium/drivers/cell/ppu/cell_winsys.h
new file mode 100644
index 0000000000..ae2af5696b
--- /dev/null
+++ b/src/gallium/drivers/cell/ppu/cell_winsys.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef CELL_WINSYS_H
+#define CELL_WINSYS_H
+
+#include "pipe/p_compiler.h"
+
+
+/**
+ * Very simple winsys at this time.
+ * Will probably eventually add SPU control info.
+ */
+struct cell_winsys
+{
+ uint preferredFormat;
+};
+
+
+extern struct cell_winsys *
+cell_get_winsys(uint format);
+
+
+
+#endif
diff --git a/src/gallium/drivers/cell/spu/.gitignore b/src/gallium/drivers/cell/spu/.gitignore
new file mode 100644
index 0000000000..2be9a2d324
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/.gitignore
@@ -0,0 +1 @@
+g3d_spu
diff --git a/src/gallium/drivers/cell/spu/Makefile b/src/gallium/drivers/cell/spu/Makefile
new file mode 100644
index 0000000000..3cc52301da
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/Makefile
@@ -0,0 +1,83 @@
+# Gallium3D Cell driver: SPU code
+
+# This makefile builds the g3d_spu.a file that's linked into the
+# PPU code/library.
+
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+
+PROG = g3d
+
+PROG_SPU = $(PROG)_spu
+PROG_SPU_A = $(PROG)_spu.a
+PROG_SPU_EMBED_O = $(PROG)_spu-embed.o
+
+
+SOURCES = \
+ spu_command.c \
+ spu_dcache.c \
+ spu_funcs.c \
+ spu_main.c \
+ spu_per_fragment_op.c \
+ spu_render.c \
+ spu_texture.c \
+ spu_tile.c \
+ spu_tri.c
+
+OLD_SOURCES = \
+ spu_exec.c \
+ spu_util.c \
+ spu_vertex_fetch.c \
+ spu_vertex_shader.c
+
+
+SPU_OBJECTS = $(SOURCES:.c=.o)
+
+SPU_ASM_OUT = $(SOURCES:.c=.s)
+
+
+INCLUDE_DIRS = \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/src/gallium/drivers
+
+
+.c.o:
+ $(SPU_CC) $(SPU_CFLAGS) -c $<
+
+.c.s:
+ $(SPU_CC) $(SPU_CFLAGS) -O3 -S $<
+
+
+# The .a file will be linked into the main/PPU executable
+default: $(PROG_SPU_A)
+
+$(PROG_SPU_A): $(PROG_SPU_EMBED_O)
+ $(SPU_AR) $(SPU_AR_FLAGS) $(PROG_SPU_A) $(PROG_SPU_EMBED_O)
+
+$(PROG_SPU_EMBED_O): $(PROG_SPU)
+ $(SPU_EMBED) $(SPU_EMBED_FLAGS) $(PROG_SPU) $(PROG_SPU) $(PROG_SPU_EMBED_O)
+
+$(PROG_SPU): $(SPU_OBJECTS)
+ $(SPU_CC) -o $(PROG_SPU) $(SPU_OBJECTS) $(SPU_LFLAGS)
+
+
+
+asmfiles: $(SPU_ASM_OUT)
+
+
+clean:
+ rm -f *~ *.o *.a *.d *.s $(PROG_SPU)
+
+
+
+depend: $(SOURCES)
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDE_DIRS) $(SOURCES) 2> /dev/null
+
+include depend
+
diff --git a/src/gallium/drivers/cell/spu/spu_colorpack.h b/src/gallium/drivers/cell/spu/spu_colorpack.h
new file mode 100644
index 0000000000..d7ce005524
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_colorpack.h
@@ -0,0 +1,145 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+
+#ifndef SPU_COLORPACK_H
+#define SPU_COLORPACK_H
+
+
+#include <transpose_matrix4x4.h>
+#include <spu_intrinsics.h>
+
+
+static INLINE unsigned int
+spu_pack_R8G8B8A8(vector float rgba)
+{
+ vector unsigned int out = spu_convtu(rgba, 32);
+
+ out = spu_shuffle(out, out, ((vector unsigned char) {
+ 0, 4, 8, 12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }) );
+
+ return spu_extract(out, 0);
+}
+
+
+static INLINE unsigned int
+spu_pack_A8R8G8B8(vector float rgba)
+{
+ vector unsigned int out = spu_convtu(rgba, 32);
+ out = spu_shuffle(out, out, ((vector unsigned char) {
+ 12, 0, 4, 8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0}) );
+ return spu_extract(out, 0);
+}
+
+
+static INLINE unsigned int
+spu_pack_B8G8R8A8(vector float rgba)
+{
+ vector unsigned int out = spu_convtu(rgba, 32);
+ out = spu_shuffle(out, out, ((vector unsigned char) {
+ 8, 4, 0, 12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0}) );
+ return spu_extract(out, 0);
+}
+
+
+static INLINE unsigned int
+spu_pack_color_shuffle(vector float rgba, vector unsigned char shuffle)
+{
+ vector unsigned int out = spu_convtu(rgba, 32);
+ out = spu_shuffle(out, out, shuffle);
+ return spu_extract(out, 0);
+}
+
+
+static INLINE vector float
+spu_unpack_B8G8R8A8(uint color)
+{
+ vector unsigned int color_u4 = spu_splats(color);
+ color_u4 = spu_shuffle(color_u4, color_u4,
+ ((vector unsigned char) {
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 3, 3, 3, 3}) );
+ return spu_convtf(color_u4, 32);
+}
+
+
+static INLINE vector float
+spu_unpack_A8R8G8B8(uint color)
+{
+ vector unsigned int color_u4 = spu_splats(color);
+ color_u4 = spu_shuffle(color_u4, color_u4,
+ ((vector unsigned char) {
+ 1, 1, 1, 1,
+ 2, 2, 2, 2,
+ 3, 3, 3, 3,
+ 0, 0, 0, 0}) );
+ return spu_convtf(color_u4, 32);
+}
+
+
+/**
+ * \param color_in - array of 32-bit packed ARGB colors
+ * \param color_out - returns float colors in RRRR, GGGG, BBBB, AAAA order
+ */
+static INLINE void
+spu_unpack_A8R8G8B8_transpose4(const vector unsigned int color_in[4],
+ vector float color_out[4])
+{
+ vector unsigned int c0;
+
+ c0 = spu_shuffle(color_in[0], color_in[0],
+ ((vector unsigned char) {
+ 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0}) );
+ color_out[0] = spu_convtf(c0, 32);
+
+ c0 = spu_shuffle(color_in[1], color_in[1],
+ ((vector unsigned char) {
+ 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0}) );
+ color_out[1] = spu_convtf(c0, 32);
+
+ c0 = spu_shuffle(color_in[2], color_in[2],
+ ((vector unsigned char) {
+ 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0}) );
+ color_out[2] = spu_convtf(c0, 32);
+
+ c0 = spu_shuffle(color_in[3], color_in[3],
+ ((vector unsigned char) {
+ 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0}) );
+ color_out[3] = spu_convtf(c0, 32);
+
+ _transpose_matrix4x4(color_out, color_out);
+}
+
+
+
+#endif /* SPU_COLORPACK_H */
diff --git a/src/gallium/drivers/cell/spu/spu_command.c b/src/gallium/drivers/cell/spu/spu_command.c
new file mode 100644
index 0000000000..5c0179d954
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_command.c
@@ -0,0 +1,815 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * SPU command processing code
+ */
+
+
+#include <stdio.h>
+#include <libmisc.h>
+
+#include "pipe/p_defines.h"
+
+#include "spu_command.h"
+#include "spu_main.h"
+#include "spu_render.h"
+#include "spu_per_fragment_op.h"
+#include "spu_texture.h"
+#include "spu_tile.h"
+#include "spu_vertex_shader.h"
+#include "spu_dcache.h"
+#include "cell/common.h"
+
+
+struct spu_vs_context draw;
+
+
+/**
+ * Buffers containing dynamically generated SPU code:
+ */
+static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS]
+ ALIGN16_ATTRIB;
+
+
+
+static INLINE int
+align(int value, int alignment)
+{
+ return (value + alignment - 1) & ~(alignment - 1);
+}
+
+
+
+/**
+ * Tell the PPU that this SPU has finished copying a buffer to
+ * local store and that it may be reused by the PPU.
+ * This is done by writting a 16-byte batch-buffer-status block back into
+ * main memory (in cell_context->buffer_status[]).
+ */
+static void
+release_buffer(uint buffer)
+{
+ /* Evidently, using less than a 16-byte status doesn't work reliably */
+ static const vector unsigned int status = {CELL_BUFFER_STATUS_FREE,
+ CELL_BUFFER_STATUS_FREE,
+ CELL_BUFFER_STATUS_FREE,
+ CELL_BUFFER_STATUS_FREE};
+ const uint index = 4 * (spu.init.id * CELL_NUM_BUFFERS + buffer);
+ uint *dst = spu.init.buffer_status + index;
+
+ ASSERT(buffer < CELL_NUM_BUFFERS);
+
+ mfc_put((void *) &status, /* src in local memory */
+ (unsigned int) dst, /* dst in main memory */
+ sizeof(status), /* size */
+ TAG_MISC, /* tag is unimportant */
+ 0, /* tid */
+ 0 /* rid */);
+}
+
+
+/**
+ * Write CELL_FENCE_SIGNALLED back to the fence status qword in main memory.
+ * There's a qword of status per SPU.
+ */
+static void
+cmd_fence(struct cell_command_fence *fence_cmd)
+{
+ static const vector unsigned int status = {CELL_FENCE_SIGNALLED,
+ CELL_FENCE_SIGNALLED,
+ CELL_FENCE_SIGNALLED,
+ CELL_FENCE_SIGNALLED};
+ uint *dst = (uint *) fence_cmd->fence;
+ dst += 4 * spu.init.id; /* main store/memory address, not local store */
+ ASSERT_ALIGN16(dst);
+ mfc_put((void *) &status, /* src in local memory */
+ (unsigned int) dst, /* dst in main memory */
+ sizeof(status), /* size */
+ TAG_FENCE, /* tag */
+ 0, /* tid */
+ 0 /* rid */);
+}
+
+
+static void
+cmd_clear_surface(const struct cell_command_clear_surface *clear)
+{
+ D_PRINTF(CELL_DEBUG_CMD, "CLEAR SURF %u to 0x%08x\n", clear->surface, clear->value);
+
+ if (clear->surface == 0) {
+ spu.fb.color_clear_value = clear->value;
+ if (spu.init.debug_flags & CELL_DEBUG_CHECKER) {
+ uint x = (spu.init.id << 4) | (spu.init.id << 12) |
+ (spu.init.id << 20) | (spu.init.id << 28);
+ spu.fb.color_clear_value ^= x;
+ }
+ }
+ else {
+ spu.fb.depth_clear_value = clear->value;
+ }
+
+#define CLEAR_OPT 1
+#if CLEAR_OPT
+
+ /* Simply set all tiles' status to CLEAR.
+ * When we actually begin rendering into a tile, we'll initialize it to
+ * the clear value. If any tiles go untouched during the frame,
+ * really_clear_tiles() will set them to the clear value.
+ */
+ if (clear->surface == 0) {
+ memset(spu.ctile_status, TILE_STATUS_CLEAR, sizeof(spu.ctile_status));
+ }
+ else {
+ memset(spu.ztile_status, TILE_STATUS_CLEAR, sizeof(spu.ztile_status));
+ }
+
+#else
+
+ /*
+ * This path clears the whole framebuffer to the clear color right now.
+ */
+
+ /*
+ printf("SPU: %s num=%d w=%d h=%d\n",
+ __FUNCTION__, num_tiles, spu.fb.width_tiles, spu.fb.height_tiles);
+ */
+
+ /* init a single tile to the clear value */
+ if (clear->surface == 0) {
+ clear_c_tile(&spu.ctile);
+ }
+ else {
+ clear_z_tile(&spu.ztile);
+ }
+
+ /* walk over my tiles, writing the 'clear' tile's data */
+ {
+ const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
+ uint i;
+ for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
+ uint tx = i % spu.fb.width_tiles;
+ uint ty = i / spu.fb.width_tiles;
+ if (clear->surface == 0)
+ put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
+ else
+ put_tile(tx, ty, &spu.ztile, TAG_SURFACE_CLEAR, 1);
+ }
+ }
+
+ if (spu.init.debug_flags & CELL_DEBUG_SYNC) {
+ wait_on_mask(1 << TAG_SURFACE_CLEAR);
+ }
+
+#endif /* CLEAR_OPT */
+
+ D_PRINTF(CELL_DEBUG_CMD, "CLEAR SURF done\n");
+}
+
+
+static void
+cmd_release_verts(const struct cell_command_release_verts *release)
+{
+ D_PRINTF(CELL_DEBUG_CMD, "RELEASE VERTS %u\n", release->vertex_buf);
+ ASSERT(release->vertex_buf != ~0U);
+ release_buffer(release->vertex_buf);
+}
+
+
+/**
+ * Process a CELL_CMD_STATE_FRAGMENT_OPS command.
+ * This involves installing new fragment ops SPU code.
+ * If this function is never called, we'll use a regular C fallback function
+ * for fragment processing.
+ */
+static void
+cmd_state_fragment_ops(const struct cell_command_fragment_ops *fops)
+{
+ D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FRAGMENT_OPS\n");
+
+ /* Copy state info (for fallback case only - this will eventually
+ * go away when the fallback case goes away)
+ */
+ memcpy(&spu.depth_stencil_alpha, &fops->dsa, sizeof(fops->dsa));
+ memcpy(&spu.blend, &fops->blend, sizeof(fops->blend));
+ memcpy(&spu.blend_color, &fops->blend_color, sizeof(fops->blend_color));
+
+ /* Make sure the SPU knows which buffers it's expected to read when
+ * it's told to pull tiles.
+ */
+ spu.read_depth_stencil = (spu.depth_stencil_alpha.depth.enabled || spu.depth_stencil_alpha.stencil[0].enabled);
+
+ /* If we're forcing the fallback code to be used (for debug purposes),
+ * install that. Otherwise install the incoming SPU code.
+ */
+ if ((spu.init.debug_flags & CELL_DEBUG_FRAGMENT_OP_FALLBACK) != 0) {
+ static unsigned int warned = 0;
+ if (!warned) {
+ fprintf(stderr, "Cell Warning: using fallback per-fragment code\n");
+ warned = 1;
+ }
+ /* The following two lines aren't really necessary if you
+ * know the debug flags won't change during a run, and if you
+ * know that the function pointers are initialized correctly.
+ * We set them here to allow a person to change the debug
+ * flags during a run (from inside a debugger).
+ */
+ spu.fragment_ops[CELL_FACING_FRONT] = spu_fallback_fragment_ops;
+ spu.fragment_ops[CELL_FACING_BACK] = spu_fallback_fragment_ops;
+ return;
+ }
+
+ /* Make sure the SPU code buffer is large enough to hold the incoming code.
+ * Note that we *don't* use align_malloc() and align_free(), because
+ * those utility functions are *not* available in SPU code.
+ * */
+ if (spu.fragment_ops_code_size < fops->total_code_size) {
+ if (spu.fragment_ops_code != NULL) {
+ free(spu.fragment_ops_code);
+ }
+ spu.fragment_ops_code_size = fops->total_code_size;
+ spu.fragment_ops_code = malloc(fops->total_code_size);
+ if (spu.fragment_ops_code == NULL) {
+ /* Whoops. */
+ fprintf(stderr, "CELL Warning: failed to allocate fragment ops code (%d bytes) - using fallback\n", fops->total_code_size);
+ spu.fragment_ops_code = NULL;
+ spu.fragment_ops_code_size = 0;
+ spu.fragment_ops[CELL_FACING_FRONT] = spu_fallback_fragment_ops;
+ spu.fragment_ops[CELL_FACING_BACK] = spu_fallback_fragment_ops;
+ return;
+ }
+ }
+
+ /* Copy the SPU code from the command buffer to the spu buffer */
+ memcpy(spu.fragment_ops_code, fops->code, fops->total_code_size);
+
+ /* Set the pointers for the front-facing and back-facing fragments
+ * to the specified offsets within the code. Note that if the
+ * front-facing and back-facing code are the same, they'll have
+ * the same offset.
+ */
+ spu.fragment_ops[CELL_FACING_FRONT] = (spu_fragment_ops_func) &spu.fragment_ops_code[fops->front_code_index];
+ spu.fragment_ops[CELL_FACING_BACK] = (spu_fragment_ops_func) &spu.fragment_ops_code[fops->back_code_index];
+}
+
+static void
+cmd_state_fragment_program(const struct cell_command_fragment_program *fp)
+{
+ D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FRAGMENT_PROGRAM\n");
+ /* Copy SPU code from batch buffer to spu buffer */
+ memcpy(spu.fragment_program_code, fp->code,
+ SPU_MAX_FRAGMENT_PROGRAM_INSTS * 4);
+#if 01
+ /* Point function pointer at new code */
+ spu.fragment_program = (spu_fragment_program_func)spu.fragment_program_code;
+#endif
+}
+
+
+static uint
+cmd_state_fs_constants(const qword *buffer, uint pos)
+{
+ const uint num_const = spu_extract((vector unsigned int)buffer[pos+1], 0);
+ const float *constants = (const float *) &buffer[pos+2];
+ uint i;
+
+ D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FS_CONSTANTS (%u)\n", num_const);
+
+ /* Expand each float to float[4] for SOA execution */
+ for (i = 0; i < num_const; i++) {
+ D_PRINTF(CELL_DEBUG_CMD, " const[%u] = %f\n", i, constants[i]);
+ spu.constants[i] = spu_splats(constants[i]);
+ }
+
+ /* return new buffer pos (in 16-byte words) */
+ return pos + 2 + (ROUNDUP16(num_const * sizeof(float)) / 16);
+}
+
+
+static void
+cmd_state_framebuffer(const struct cell_command_framebuffer *cmd)
+{
+ D_PRINTF(CELL_DEBUG_CMD, "FRAMEBUFFER: %d x %d at %p, cformat 0x%x zformat 0x%x\n",
+ cmd->width,
+ cmd->height,
+ cmd->color_start,
+ cmd->color_format,
+ cmd->depth_format);
+
+ ASSERT_ALIGN16(cmd->color_start);
+ ASSERT_ALIGN16(cmd->depth_start);
+
+ spu.fb.color_start = cmd->color_start;
+ spu.fb.depth_start = cmd->depth_start;
+ spu.fb.color_format = cmd->color_format;
+ spu.fb.depth_format = cmd->depth_format;
+ spu.fb.width = cmd->width;
+ spu.fb.height = cmd->height;
+ spu.fb.width_tiles = (spu.fb.width + TILE_SIZE - 1) / TILE_SIZE;
+ spu.fb.height_tiles = (spu.fb.height + TILE_SIZE - 1) / TILE_SIZE;
+
+ switch (spu.fb.depth_format) {
+ case PIPE_FORMAT_Z32_UNORM:
+ spu.fb.zsize = 4;
+ spu.fb.zscale = (float) 0xffffffffu;
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ spu.fb.zsize = 4;
+ spu.fb.zscale = (float) 0x00ffffffu;
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ spu.fb.zsize = 2;
+ spu.fb.zscale = (float) 0xffffu;
+ break;
+ default:
+ spu.fb.zsize = 0;
+ break;
+ }
+}
+
+
+/**
+ * Tex texture mask_s/t and scale_s/t fields depend on the texture size and
+ * sampler wrap modes.
+ */
+static void
+update_tex_masks(struct spu_texture *texture,
+ const struct pipe_sampler_state *sampler)
+{
+ uint i;
+
+ for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
+ int width = texture->level[i].width;
+ int height = texture->level[i].height;
+
+ if (sampler->wrap_s == PIPE_TEX_WRAP_REPEAT)
+ texture->level[i].mask_s = spu_splats(width - 1);
+ else
+ texture->level[i].mask_s = spu_splats(~0);
+
+ if (sampler->wrap_t == PIPE_TEX_WRAP_REPEAT)
+ texture->level[i].mask_t = spu_splats(height - 1);
+ else
+ texture->level[i].mask_t = spu_splats(~0);
+
+ if (sampler->normalized_coords) {
+ texture->level[i].scale_s = spu_splats((float) width);
+ texture->level[i].scale_t = spu_splats((float) height);
+ }
+ else {
+ texture->level[i].scale_s = spu_splats(1.0f);
+ texture->level[i].scale_t = spu_splats(1.0f);
+ }
+ }
+}
+
+
+static void
+cmd_state_sampler(const struct cell_command_sampler *sampler)
+{
+ uint unit = sampler->unit;
+
+ D_PRINTF(CELL_DEBUG_CMD, "SAMPLER [%u]\n", unit);
+
+ spu.sampler[unit] = sampler->state;
+
+ switch (spu.sampler[unit].min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ spu.min_sample_texture_2d[unit] = sample_texture_2d_bilinear;
+ break;
+ case PIPE_TEX_FILTER_ANISO:
+ /* fall-through, for now */
+ case PIPE_TEX_FILTER_NEAREST:
+ spu.min_sample_texture_2d[unit] = sample_texture_2d_nearest;
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ switch (spu.sampler[sampler->unit].mag_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ spu.mag_sample_texture_2d[unit] = sample_texture_2d_bilinear;
+ break;
+ case PIPE_TEX_FILTER_ANISO:
+ /* fall-through, for now */
+ case PIPE_TEX_FILTER_NEAREST:
+ spu.mag_sample_texture_2d[unit] = sample_texture_2d_nearest;
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ switch (spu.sampler[sampler->unit].min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ spu.sample_texture_2d[unit] = sample_texture_2d_lod;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ spu.sample_texture_2d[unit] = spu.mag_sample_texture_2d[unit];
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ update_tex_masks(&spu.texture[unit], &spu.sampler[unit]);
+}
+
+
+static void
+cmd_state_texture(const struct cell_command_texture *texture)
+{
+ const uint unit = texture->unit;
+ uint i;
+
+ D_PRINTF(CELL_DEBUG_CMD, "TEXTURE [%u]\n", texture->unit);
+
+ spu.texture[unit].max_level = 0;
+ spu.texture[unit].target = texture->target;
+
+ for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
+ uint width = texture->width[i];
+ uint height = texture->height[i];
+ uint depth = texture->depth[i];
+
+ D_PRINTF(CELL_DEBUG_CMD, " LEVEL %u: at %p size[0] %u x %u\n", i,
+ texture->start[i], texture->width[i], texture->height[i]);
+
+ spu.texture[unit].level[i].start = texture->start[i];
+ spu.texture[unit].level[i].width = width;
+ spu.texture[unit].level[i].height = height;
+ spu.texture[unit].level[i].depth = depth;
+
+ spu.texture[unit].level[i].tiles_per_row =
+ (width + TILE_SIZE - 1) / TILE_SIZE;
+
+ spu.texture[unit].level[i].bytes_per_image =
+ 4 * align(width, TILE_SIZE) * align(height, TILE_SIZE) * depth;
+
+ spu.texture[unit].level[i].max_s = spu_splats((int) width - 1);
+ spu.texture[unit].level[i].max_t = spu_splats((int) height - 1);
+
+ if (texture->start[i])
+ spu.texture[unit].max_level = i;
+ }
+
+ update_tex_masks(&spu.texture[unit], &spu.sampler[unit]);
+}
+
+
+static void
+cmd_state_vertex_info(const struct vertex_info *vinfo)
+{
+ D_PRINTF(CELL_DEBUG_CMD, "VERTEX_INFO num_attribs=%u\n", vinfo->num_attribs);
+ ASSERT(vinfo->num_attribs >= 1);
+ ASSERT(vinfo->num_attribs <= 8);
+ memcpy(&spu.vertex_info, vinfo, sizeof(*vinfo));
+}
+
+
+static void
+cmd_state_vs_array_info(const struct cell_array_info *vs_info)
+{
+ const unsigned attr = vs_info->attr;
+
+ ASSERT(attr < PIPE_MAX_ATTRIBS);
+ draw.vertex_fetch.src_ptr[attr] = vs_info->base;
+ draw.vertex_fetch.pitch[attr] = vs_info->pitch;
+ draw.vertex_fetch.size[attr] = vs_info->size;
+ draw.vertex_fetch.code_offset[attr] = vs_info->function_offset;
+ draw.vertex_fetch.dirty = 1;
+}
+
+
+static void
+cmd_state_attrib_fetch(const struct cell_attribute_fetch_code *code)
+{
+ mfc_get(attribute_fetch_code_buffer,
+ (unsigned int) code->base, /* src */
+ code->size,
+ TAG_BATCH_BUFFER,
+ 0, /* tid */
+ 0 /* rid */);
+ wait_on_mask(1 << TAG_BATCH_BUFFER);
+
+ draw.vertex_fetch.code = attribute_fetch_code_buffer;
+}
+
+
+static void
+cmd_finish(void)
+{
+ D_PRINTF(CELL_DEBUG_CMD, "FINISH\n");
+ really_clear_tiles(0);
+ /* wait for all outstanding DMAs to finish */
+ mfc_write_tag_mask(~0);
+ mfc_read_tag_status_all();
+ /* send mbox message to PPU */
+ spu_write_out_mbox(CELL_CMD_FINISH);
+}
+
+
+/**
+ * Execute a batch of commands which was sent to us by the PPU.
+ * See the cell_emit_state.c code to see where the commands come from.
+ *
+ * The opcode param encodes the location of the buffer and its size.
+ */
+static void
+cmd_batch(uint opcode)
+{
+ const uint buf = (opcode >> 8) & 0xff;
+ uint size = (opcode >> 16);
+ qword buffer[CELL_BUFFER_SIZE / 16] ALIGN16_ATTRIB;
+ const unsigned usize = ROUNDUP16(size) / sizeof(buffer[0]);
+ uint pos;
+
+ D_PRINTF(CELL_DEBUG_CMD, "BATCH buffer %u, len %u, from %p\n",
+ buf, size, spu.init.buffers[buf]);
+
+ ASSERT((opcode & CELL_CMD_OPCODE_MASK) == CELL_CMD_BATCH);
+
+ ASSERT_ALIGN16(spu.init.buffers[buf]);
+
+ size = ROUNDUP16(size);
+
+ ASSERT_ALIGN16(spu.init.buffers[buf]);
+
+ mfc_get(buffer, /* dest */
+ (unsigned int) spu.init.buffers[buf], /* src */
+ size,
+ TAG_BATCH_BUFFER,
+ 0, /* tid */
+ 0 /* rid */);
+ wait_on_mask(1 << TAG_BATCH_BUFFER);
+
+ /* Tell PPU we're done copying the buffer to local store */
+ D_PRINTF(CELL_DEBUG_CMD, "release batch buf %u\n", buf);
+ release_buffer(buf);
+
+ /*
+ * Loop over commands in the batch buffer
+ */
+ for (pos = 0; pos < usize; /* no incr */) {
+ switch (si_to_uint(buffer[pos])) {
+ /*
+ * rendering commands
+ */
+ case CELL_CMD_CLEAR_SURFACE:
+ {
+ struct cell_command_clear_surface *clr
+ = (struct cell_command_clear_surface *) &buffer[pos];
+ cmd_clear_surface(clr);
+ pos += sizeof(*clr) / 16;
+ }
+ break;
+ case CELL_CMD_RENDER:
+ {
+ struct cell_command_render *render
+ = (struct cell_command_render *) &buffer[pos];
+ uint pos_incr;
+ cmd_render(render, &pos_incr);
+ pos += ((pos_incr+1)&~1) / 2; // should 'fix' cmd_render return
+ }
+ break;
+ /*
+ * state-update commands
+ */
+ case CELL_CMD_STATE_FRAMEBUFFER:
+ {
+ struct cell_command_framebuffer *fb
+ = (struct cell_command_framebuffer *) &buffer[pos];
+ cmd_state_framebuffer(fb);
+ pos += sizeof(*fb) / 16;
+ }
+ break;
+ case CELL_CMD_STATE_FRAGMENT_OPS:
+ {
+ struct cell_command_fragment_ops *fops
+ = (struct cell_command_fragment_ops *) &buffer[pos];
+ cmd_state_fragment_ops(fops);
+ /* This is a variant-sized command */
+ pos += ROUNDUP16(sizeof(*fops) + fops->total_code_size) / 16;
+ }
+ break;
+ case CELL_CMD_STATE_FRAGMENT_PROGRAM:
+ {
+ struct cell_command_fragment_program *fp
+ = (struct cell_command_fragment_program *) &buffer[pos];
+ cmd_state_fragment_program(fp);
+ pos += sizeof(*fp) / 16;
+ }
+ break;
+ case CELL_CMD_STATE_FS_CONSTANTS:
+ pos = cmd_state_fs_constants(buffer, pos);
+ break;
+ case CELL_CMD_STATE_RASTERIZER:
+ {
+ struct cell_command_rasterizer *rast =
+ (struct cell_command_rasterizer *) &buffer[pos];
+ spu.rasterizer = rast->rasterizer;
+ pos += sizeof(*rast) / 16;
+ }
+ break;
+ case CELL_CMD_STATE_SAMPLER:
+ {
+ struct cell_command_sampler *sampler
+ = (struct cell_command_sampler *) &buffer[pos];
+ cmd_state_sampler(sampler);
+ pos += sizeof(*sampler) / 16;
+ }
+ break;
+ case CELL_CMD_STATE_TEXTURE:
+ {
+ struct cell_command_texture *texture
+ = (struct cell_command_texture *) &buffer[pos];
+ cmd_state_texture(texture);
+ pos += sizeof(*texture) / 16;
+ }
+ break;
+ case CELL_CMD_STATE_VERTEX_INFO:
+ cmd_state_vertex_info((struct vertex_info *) &buffer[pos+1]);
+ pos += 1 + ROUNDUP16(sizeof(struct vertex_info)) / 16;
+ break;
+ case CELL_CMD_STATE_VIEWPORT:
+ (void) memcpy(& draw.viewport, &buffer[pos+1],
+ sizeof(struct pipe_viewport_state));
+ pos += 1 + ROUNDUP16(sizeof(struct pipe_viewport_state)) / 16;
+ break;
+ case CELL_CMD_STATE_UNIFORMS:
+ draw.constants = (const float (*)[4]) (uintptr_t)spu_extract((vector unsigned int)buffer[pos+1],0);
+ pos += 2;
+ break;
+ case CELL_CMD_STATE_VS_ARRAY_INFO:
+ cmd_state_vs_array_info((struct cell_array_info *) &buffer[pos+1]);
+ pos += 1 + ROUNDUP16(sizeof(struct cell_array_info)) / 16;
+ break;
+ case CELL_CMD_STATE_BIND_VS:
+#if 0
+ spu_bind_vertex_shader(&draw,
+ (struct cell_shader_info *) &buffer[pos+1]);
+#endif
+ pos += 1 + ROUNDUP16(sizeof(struct cell_shader_info)) / 16;
+ break;
+ case CELL_CMD_STATE_ATTRIB_FETCH:
+ cmd_state_attrib_fetch((struct cell_attribute_fetch_code *)
+ &buffer[pos+1]);
+ pos += 1 + ROUNDUP16(sizeof(struct cell_attribute_fetch_code)) / 16;
+ break;
+ /*
+ * misc commands
+ */
+ case CELL_CMD_FINISH:
+ cmd_finish();
+ pos += 1;
+ break;
+ case CELL_CMD_FENCE:
+ {
+ struct cell_command_fence *fence_cmd =
+ (struct cell_command_fence *) &buffer[pos];
+ cmd_fence(fence_cmd);
+ pos += sizeof(*fence_cmd) / 16;
+ }
+ break;
+ case CELL_CMD_RELEASE_VERTS:
+ {
+ struct cell_command_release_verts *release
+ = (struct cell_command_release_verts *) &buffer[pos];
+ cmd_release_verts(release);
+ pos += sizeof(*release) / 16;
+ }
+ break;
+ case CELL_CMD_FLUSH_BUFFER_RANGE: {
+ struct cell_buffer_range *br = (struct cell_buffer_range *)
+ &buffer[pos+1];
+
+ spu_dcache_mark_dirty((unsigned) br->base, br->size);
+ pos += 1 + ROUNDUP16(sizeof(struct cell_buffer_range)) / 16;
+ break;
+ }
+ default:
+ printf("SPU %u: bad opcode: 0x%x\n", spu.init.id, si_to_uint(buffer[pos]));
+ ASSERT(0);
+ break;
+ }
+ }
+
+ D_PRINTF(CELL_DEBUG_CMD, "BATCH complete\n");
+}
+
+
+#define PERF 0
+
+
+/**
+ * Main loop for SPEs: Get a command, execute it, repeat.
+ */
+void
+command_loop(void)
+{
+ int exitFlag = 0;
+ uint t0, t1;
+
+ D_PRINTF(CELL_DEBUG_CMD, "Enter command loop\n");
+
+ while (!exitFlag) {
+ unsigned opcode;
+
+ D_PRINTF(CELL_DEBUG_CMD, "Wait for cmd...\n");
+
+ if (PERF)
+ spu_write_decrementer(~0);
+
+ /* read/wait from mailbox */
+ opcode = (unsigned int) spu_read_in_mbox();
+ D_PRINTF(CELL_DEBUG_CMD, "got cmd 0x%x\n", opcode);
+
+ if (PERF)
+ t0 = spu_read_decrementer();
+
+ switch (opcode & CELL_CMD_OPCODE_MASK) {
+ case CELL_CMD_EXIT:
+ D_PRINTF(CELL_DEBUG_CMD, "EXIT\n");
+ exitFlag = 1;
+ break;
+ case CELL_CMD_VS_EXECUTE:
+#if 0
+ spu_execute_vertex_shader(&draw, &cmd.vs);
+#endif
+ break;
+ case CELL_CMD_BATCH:
+ cmd_batch(opcode);
+ break;
+ default:
+ printf("Bad opcode 0x%x!\n", opcode & CELL_CMD_OPCODE_MASK);
+ }
+
+ if (PERF) {
+ t1 = spu_read_decrementer();
+ printf("wait mbox time: %gms batch time: %gms\n",
+ (~0u - t0) * spu.init.inv_timebase,
+ (t0 - t1) * spu.init.inv_timebase);
+ }
+ }
+
+ D_PRINTF(CELL_DEBUG_CMD, "Exit command loop\n");
+
+ if (spu.init.debug_flags & CELL_DEBUG_CACHE)
+ spu_dcache_report();
+}
+
+/* Initialize this module; we manage the fragment ops buffer here. */
+void
+spu_command_init(void)
+{
+ /* Install default/fallback fragment processing function.
+ * This will normally be overriden by a code-gen'd function
+ * unless CELL_FORCE_FRAGMENT_OPS_FALLBACK is set.
+ */
+ spu.fragment_ops[CELL_FACING_FRONT] = spu_fallback_fragment_ops;
+ spu.fragment_ops[CELL_FACING_BACK] = spu_fallback_fragment_ops;
+
+ /* Set up the basic empty buffer for code-gen'ed fragment ops */
+ spu.fragment_ops_code = NULL;
+ spu.fragment_ops_code_size = 0;
+}
+
+void
+spu_command_close(void)
+{
+ /* Deallocate the code-gen buffer for fragment ops, and reset the
+ * fragment ops functions to their initial setting (just to leave
+ * things in a good state).
+ */
+ if (spu.fragment_ops_code != NULL) {
+ free(spu.fragment_ops_code);
+ }
+ spu_command_init();
+}
diff --git a/src/gallium/drivers/cell/spu/spu_command.h b/src/gallium/drivers/cell/spu/spu_command.h
new file mode 100644
index 0000000000..83dcdade28
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_command.h
@@ -0,0 +1,35 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+extern void
+command_loop(void);
+
+extern void
+spu_command_init(void);
+
+extern void
+spu_command_close(void);
diff --git a/src/gallium/drivers/cell/spu/spu_dcache.c b/src/gallium/drivers/cell/spu/spu_dcache.c
new file mode 100644
index 0000000000..a6d67634fd
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_dcache.c
@@ -0,0 +1,145 @@
+/*
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "cell/common.h"
+#include "spu_main.h"
+#include "spu_dcache.h"
+
+#define CACHELINE_LOG2SIZE 7
+#define LINE_SIZE (1U << 7)
+#define ALIGN_MASK (~(LINE_SIZE - 1))
+
+#define CACHE_NAME data
+#define CACHED_TYPE qword
+#define CACHE_TYPE CACHE_TYPE_RO
+#define CACHE_SET_TAGID(set) (((set) & 0x03) + TAG_DCACHE0)
+#define CACHE_LOG2NNWAY 2
+#define CACHE_LOG2NSETS 6
+#ifdef DEBUG
+#define CACHE_STATS 1
+#endif
+#include <cache-api.h>
+
+/* Yes folks, this is ugly.
+ */
+#undef CACHE_NWAY
+#undef CACHE_NSETS
+#define CACHE_NAME data
+#define CACHE_NWAY 4
+#define CACHE_NSETS (1U << 6)
+
+
+/**
+ * Fetch between arbitrary number of bytes from an unaligned address
+ *
+ * \param dst Destination data buffer
+ * \param ea Main memory effective address of source data
+ * \param size Number of bytes to read
+ *
+ * \warning
+ * As is hinted by the type of the \c dst pointer, this function writes
+ * multiples of 16-bytes.
+ */
+void
+spu_dcache_fetch_unaligned(qword *dst, unsigned ea, unsigned size)
+{
+ const int shift = ea & 0x0f;
+ const unsigned read_size = ROUNDUP16(size + shift);
+ const unsigned last_read = ROUNDUP16(ea + size);
+ const qword *const last_write = dst + (ROUNDUP16(size) / 16);
+ unsigned i;
+
+
+ if (shift == 0) {
+ /* Data is already aligned. Fetch directly into the destination buffer.
+ */
+ for (i = 0; i < size; i += 16) {
+ *(dst++) = cache_rd(data, ea + i);
+ }
+ } else {
+ qword hi;
+
+
+ /* Please exercise extreme caution when modifying this code. This code
+ * must not read past the end of the page containing the source data,
+ * and it must not write more than ((size + 15) / 16) qwords to the
+ * destination buffer.
+ */
+ ea &= ~0x0f;
+ hi = cache_rd(data, ea);
+ for (i = 16; i < read_size; i += 16) {
+ qword lo = cache_rd(data, ea + i);
+
+ *(dst++) = si_or((qword) spu_slqwbyte(hi, shift),
+ (qword) spu_rlmaskqwbyte(lo, shift - 16));
+ hi = lo;
+ }
+
+ if (dst != last_write) {
+ *(dst++) = si_or((qword) spu_slqwbyte(hi, shift), si_il(0));
+ }
+ }
+
+ ASSERT((ea + i) == last_read);
+ ASSERT(dst == last_write);
+}
+
+
+/**
+ * Notify the cache that a range of main memory may have been modified
+ */
+void
+spu_dcache_mark_dirty(unsigned ea, unsigned size)
+{
+ unsigned i;
+ const unsigned aligned_start = (ea & ALIGN_MASK);
+ const unsigned aligned_end = (ea + size + (LINE_SIZE - 1))
+ & ALIGN_MASK;
+
+
+ for (i = 0; i < (CACHE_NWAY * CACHE_NSETS); i++) {
+ const unsigned entry = __cache_dir[i];
+ const unsigned addr = entry & ~0x0f;
+
+ __cache_dir[i] = ((addr >= aligned_start) && (addr < aligned_end))
+ ? (entry & ~CACHELINE_VALID) : entry;
+ }
+}
+
+
+/**
+ * Print cache utilization report
+ */
+void
+spu_dcache_report(void)
+{
+#ifdef CACHE_STATS
+ if (spu.init.id == 0) {
+ printf("SPU 0: Texture cache report:\n");
+ cache_pr_stats(data);
+ }
+#endif
+}
+
+
diff --git a/src/gallium/drivers/cell/spu/spu_dcache.h b/src/gallium/drivers/cell/spu/spu_dcache.h
new file mode 100644
index 0000000000..39a19eb31b
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_dcache.h
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SPU_DCACHE_H
+#define SPU_DCACHE_H
+
+extern void
+spu_dcache_fetch_unaligned(qword *dst, unsigned ea, unsigned size);
+
+extern void
+spu_dcache_mark_dirty(unsigned ea, unsigned size);
+
+extern void
+spu_dcache_report(void);
+
+#endif /* SPU_DCACHE_H */
diff --git a/src/gallium/drivers/cell/spu/spu_exec.c b/src/gallium/drivers/cell/spu/spu_exec.c
new file mode 100644
index 0000000000..0eaae2e451
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_exec.c
@@ -0,0 +1,1907 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * TGSI interpretor/executor.
+ *
+ * Flow control information:
+ *
+ * Since we operate on 'quads' (4 pixels or 4 vertices in parallel)
+ * flow control statements (IF/ELSE/ENDIF, LOOP/ENDLOOP) require special
+ * care since a condition may be true for some quad components but false
+ * for other components.
+ *
+ * We basically execute all statements (even if they're in the part of
+ * an IF/ELSE clause that's "not taken") and use a special mask to
+ * control writing to destination registers. This is the ExecMask.
+ * See store_dest().
+ *
+ * The ExecMask is computed from three other masks (CondMask, LoopMask and
+ * ContMask) which are controlled by the flow control instructions (namely:
+ * (IF/ELSE/ENDIF, LOOP/ENDLOOP and CONT).
+ *
+ *
+ * Authors:
+ * Michal Krol
+ * Brian Paul
+ */
+
+#include <transpose_matrix4x4.h>
+#include <simdmath/ceilf4.h>
+#include <simdmath/cosf4.h>
+#include <simdmath/divf4.h>
+#include <simdmath/floorf4.h>
+#include <simdmath/log2f4.h>
+#include <simdmath/powf4.h>
+#include <simdmath/sinf4.h>
+#include <simdmath/sqrtf4.h>
+#include <simdmath/truncf4.h>
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "spu_exec.h"
+#include "spu_main.h"
+#include "spu_vertex_shader.h"
+#include "spu_dcache.h"
+#include "cell/common.h"
+
+#define TILE_TOP_LEFT 0
+#define TILE_TOP_RIGHT 1
+#define TILE_BOTTOM_LEFT 2
+#define TILE_BOTTOM_RIGHT 3
+
+/*
+ * Shorthand locations of various utility registers (_I = Index, _C = Channel)
+ */
+#define TEMP_0_I TGSI_EXEC_TEMP_00000000_I
+#define TEMP_0_C TGSI_EXEC_TEMP_00000000_C
+#define TEMP_7F_I TGSI_EXEC_TEMP_7FFFFFFF_I
+#define TEMP_7F_C TGSI_EXEC_TEMP_7FFFFFFF_C
+#define TEMP_80_I TGSI_EXEC_TEMP_80000000_I
+#define TEMP_80_C TGSI_EXEC_TEMP_80000000_C
+#define TEMP_FF_I TGSI_EXEC_TEMP_FFFFFFFF_I
+#define TEMP_FF_C TGSI_EXEC_TEMP_FFFFFFFF_C
+#define TEMP_1_I TGSI_EXEC_TEMP_ONE_I
+#define TEMP_1_C TGSI_EXEC_TEMP_ONE_C
+#define TEMP_2_I TGSI_EXEC_TEMP_TWO_I
+#define TEMP_2_C TGSI_EXEC_TEMP_TWO_C
+#define TEMP_128_I TGSI_EXEC_TEMP_128_I
+#define TEMP_128_C TGSI_EXEC_TEMP_128_C
+#define TEMP_M128_I TGSI_EXEC_TEMP_MINUS_128_I
+#define TEMP_M128_C TGSI_EXEC_TEMP_MINUS_128_C
+#define TEMP_KILMASK_I TGSI_EXEC_TEMP_KILMASK_I
+#define TEMP_KILMASK_C TGSI_EXEC_TEMP_KILMASK_C
+#define TEMP_OUTPUT_I TGSI_EXEC_TEMP_OUTPUT_I
+#define TEMP_OUTPUT_C TGSI_EXEC_TEMP_OUTPUT_C
+#define TEMP_PRIMITIVE_I TGSI_EXEC_TEMP_PRIMITIVE_I
+#define TEMP_PRIMITIVE_C TGSI_EXEC_TEMP_PRIMITIVE_C
+#define TEMP_R0 TGSI_EXEC_TEMP_R0
+
+#define FOR_EACH_CHANNEL(CHAN)\
+ for (CHAN = 0; CHAN < 4; CHAN++)
+
+#define IS_CHANNEL_ENABLED(INST, CHAN)\
+ ((INST).FullDstRegisters[0].DstRegister.WriteMask & (1 << (CHAN)))
+
+#define IS_CHANNEL_ENABLED2(INST, CHAN)\
+ ((INST).FullDstRegisters[1].DstRegister.WriteMask & (1 << (CHAN)))
+
+#define FOR_EACH_ENABLED_CHANNEL(INST, CHAN)\
+ FOR_EACH_CHANNEL( CHAN )\
+ if (IS_CHANNEL_ENABLED( INST, CHAN ))
+
+#define FOR_EACH_ENABLED_CHANNEL2(INST, CHAN)\
+ FOR_EACH_CHANNEL( CHAN )\
+ if (IS_CHANNEL_ENABLED2( INST, CHAN ))
+
+
+/** The execution mask depends on the conditional mask and the loop mask */
+#define UPDATE_EXEC_MASK(MACH) \
+ MACH->ExecMask = MACH->CondMask & MACH->LoopMask & MACH->ContMask & MACH->FuncMask
+
+
+#define CHAN_X 0
+#define CHAN_Y 1
+#define CHAN_Z 2
+#define CHAN_W 3
+
+
+
+/**
+ * Initialize machine state by expanding tokens to full instructions,
+ * allocating temporary storage, setting up constants, etc.
+ * After this, we can call spu_exec_machine_run() many times.
+ */
+void
+spu_exec_machine_init(struct spu_exec_machine *mach,
+ uint numSamplers,
+ struct spu_sampler *samplers,
+ unsigned processor)
+{
+ const qword zero = si_il(0);
+ const qword not_zero = si_il(~0);
+
+ (void) numSamplers;
+ mach->Samplers = samplers;
+ mach->Processor = processor;
+ mach->Addrs = &mach->Temps[TGSI_EXEC_NUM_TEMPS];
+
+ /* Setup constants. */
+ mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].q = zero;
+ mach->Temps[TEMP_FF_I].xyzw[TEMP_FF_C].q = not_zero;
+ mach->Temps[TEMP_7F_I].xyzw[TEMP_7F_C].q = si_shli(not_zero, -1);
+ mach->Temps[TEMP_80_I].xyzw[TEMP_80_C].q = si_shli(not_zero, 31);
+
+ mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].q = (qword) spu_splats(1.0f);
+ mach->Temps[TEMP_2_I].xyzw[TEMP_2_C].q = (qword) spu_splats(2.0f);
+ mach->Temps[TEMP_128_I].xyzw[TEMP_128_C].q = (qword) spu_splats(128.0f);
+ mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C].q = (qword) spu_splats(-128.0f);
+}
+
+
+static INLINE qword
+micro_abs(qword src)
+{
+ return si_rotmi(si_shli(src, 1), -1);
+}
+
+static INLINE qword
+micro_ceil(qword src)
+{
+ return (qword) _ceilf4((vec_float4) src);
+}
+
+static INLINE qword
+micro_cos(qword src)
+{
+ return (qword) _cosf4((vec_float4) src);
+}
+
+static const qword br_shuf = {
+ TILE_BOTTOM_RIGHT + 0, TILE_BOTTOM_RIGHT + 1,
+ TILE_BOTTOM_RIGHT + 2, TILE_BOTTOM_RIGHT + 3,
+ TILE_BOTTOM_RIGHT + 0, TILE_BOTTOM_RIGHT + 1,
+ TILE_BOTTOM_RIGHT + 2, TILE_BOTTOM_RIGHT + 3,
+ TILE_BOTTOM_RIGHT + 0, TILE_BOTTOM_RIGHT + 1,
+ TILE_BOTTOM_RIGHT + 2, TILE_BOTTOM_RIGHT + 3,
+ TILE_BOTTOM_RIGHT + 0, TILE_BOTTOM_RIGHT + 1,
+ TILE_BOTTOM_RIGHT + 2, TILE_BOTTOM_RIGHT + 3,
+};
+
+static const qword bl_shuf = {
+ TILE_BOTTOM_LEFT + 0, TILE_BOTTOM_LEFT + 1,
+ TILE_BOTTOM_LEFT + 2, TILE_BOTTOM_LEFT + 3,
+ TILE_BOTTOM_LEFT + 0, TILE_BOTTOM_LEFT + 1,
+ TILE_BOTTOM_LEFT + 2, TILE_BOTTOM_LEFT + 3,
+ TILE_BOTTOM_LEFT + 0, TILE_BOTTOM_LEFT + 1,
+ TILE_BOTTOM_LEFT + 2, TILE_BOTTOM_LEFT + 3,
+ TILE_BOTTOM_LEFT + 0, TILE_BOTTOM_LEFT + 1,
+ TILE_BOTTOM_LEFT + 2, TILE_BOTTOM_LEFT + 3,
+};
+
+static const qword tl_shuf = {
+ TILE_TOP_LEFT + 0, TILE_TOP_LEFT + 1,
+ TILE_TOP_LEFT + 2, TILE_TOP_LEFT + 3,
+ TILE_TOP_LEFT + 0, TILE_TOP_LEFT + 1,
+ TILE_TOP_LEFT + 2, TILE_TOP_LEFT + 3,
+ TILE_TOP_LEFT + 0, TILE_TOP_LEFT + 1,
+ TILE_TOP_LEFT + 2, TILE_TOP_LEFT + 3,
+ TILE_TOP_LEFT + 0, TILE_TOP_LEFT + 1,
+ TILE_TOP_LEFT + 2, TILE_TOP_LEFT + 3,
+};
+
+static qword
+micro_ddx(qword src)
+{
+ qword bottom_right = si_shufb(src, src, br_shuf);
+ qword bottom_left = si_shufb(src, src, bl_shuf);
+
+ return si_fs(bottom_right, bottom_left);
+}
+
+static qword
+micro_ddy(qword src)
+{
+ qword top_left = si_shufb(src, src, tl_shuf);
+ qword bottom_left = si_shufb(src, src, bl_shuf);
+
+ return si_fs(top_left, bottom_left);
+}
+
+static INLINE qword
+micro_div(qword src0, qword src1)
+{
+ return (qword) _divf4((vec_float4) src0, (vec_float4) src1);
+}
+
+static qword
+micro_flr(qword src)
+{
+ return (qword) _floorf4((vec_float4) src);
+}
+
+static qword
+micro_frc(qword src)
+{
+ return si_fs(src, (qword) _floorf4((vec_float4) src));
+}
+
+static INLINE qword
+micro_ge(qword src0, qword src1)
+{
+ return si_or(si_fceq(src0, src1), si_fcgt(src0, src1));
+}
+
+static qword
+micro_lg2(qword src)
+{
+ return (qword) _log2f4((vec_float4) src);
+}
+
+static INLINE qword
+micro_lt(qword src0, qword src1)
+{
+ const qword tmp = si_or(si_fceq(src0, src1), si_fcgt(src0, src1));
+
+ return si_xori(tmp, 0xff);
+}
+
+static INLINE qword
+micro_max(qword src0, qword src1)
+{
+ return si_selb(src1, src0, si_fcgt(src0, src1));
+}
+
+static INLINE qword
+micro_min(qword src0, qword src1)
+{
+ return si_selb(src0, src1, si_fcgt(src0, src1));
+}
+
+static qword
+micro_neg(qword src)
+{
+ return si_xor(src, (qword) spu_splats(0x80000000));
+}
+
+static qword
+micro_set_sign(qword src)
+{
+ return si_or(src, (qword) spu_splats(0x80000000));
+}
+
+static qword
+micro_pow(qword src0, qword src1)
+{
+ return (qword) _powf4((vec_float4) src0, (vec_float4) src1);
+}
+
+static qword
+micro_rnd(qword src)
+{
+ const qword half = (qword) spu_splats(0.5f);
+
+ /* May be able to use _roundf4. There may be some difference, though.
+ */
+ return (qword) _floorf4((vec_float4) si_fa(src, half));
+}
+
+static INLINE qword
+micro_ishr(qword src0, qword src1)
+{
+ return si_rotma(src0, si_sfi(src1, 0));
+}
+
+static qword
+micro_trunc(qword src)
+{
+ return (qword) _truncf4((vec_float4) src);
+}
+
+static qword
+micro_sin(qword src)
+{
+ return (qword) _sinf4((vec_float4) src);
+}
+
+static INLINE qword
+micro_sqrt(qword src)
+{
+ return (qword) _sqrtf4((vec_float4) src);
+}
+
+static void
+fetch_src_file_channel(
+ const struct spu_exec_machine *mach,
+ const uint file,
+ const uint swizzle,
+ const union spu_exec_channel *index,
+ union spu_exec_channel *chan )
+{
+ switch( swizzle ) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ switch( file ) {
+ case TGSI_FILE_CONSTANT: {
+ unsigned i;
+
+ for (i = 0; i < 4; i++) {
+ const float *ptr = mach->Consts[index->i[i]];
+ float tmp[4];
+
+ spu_dcache_fetch_unaligned((qword *) tmp,
+ (uintptr_t)(ptr + swizzle),
+ sizeof(float));
+
+ chan->f[i] = tmp[0];
+ }
+ break;
+ }
+
+ case TGSI_FILE_INPUT:
+ chan->u[0] = mach->Inputs[index->i[0]].xyzw[swizzle].u[0];
+ chan->u[1] = mach->Inputs[index->i[1]].xyzw[swizzle].u[1];
+ chan->u[2] = mach->Inputs[index->i[2]].xyzw[swizzle].u[2];
+ chan->u[3] = mach->Inputs[index->i[3]].xyzw[swizzle].u[3];
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ chan->u[0] = mach->Temps[index->i[0]].xyzw[swizzle].u[0];
+ chan->u[1] = mach->Temps[index->i[1]].xyzw[swizzle].u[1];
+ chan->u[2] = mach->Temps[index->i[2]].xyzw[swizzle].u[2];
+ chan->u[3] = mach->Temps[index->i[3]].xyzw[swizzle].u[3];
+ break;
+
+ case TGSI_FILE_IMMEDIATE:
+ ASSERT( index->i[0] < (int) mach->ImmLimit );
+ ASSERT( index->i[1] < (int) mach->ImmLimit );
+ ASSERT( index->i[2] < (int) mach->ImmLimit );
+ ASSERT( index->i[3] < (int) mach->ImmLimit );
+
+ chan->f[0] = mach->Imms[index->i[0]][swizzle];
+ chan->f[1] = mach->Imms[index->i[1]][swizzle];
+ chan->f[2] = mach->Imms[index->i[2]][swizzle];
+ chan->f[3] = mach->Imms[index->i[3]][swizzle];
+ break;
+
+ case TGSI_FILE_ADDRESS:
+ chan->u[0] = mach->Addrs[index->i[0]].xyzw[swizzle].u[0];
+ chan->u[1] = mach->Addrs[index->i[1]].xyzw[swizzle].u[1];
+ chan->u[2] = mach->Addrs[index->i[2]].xyzw[swizzle].u[2];
+ chan->u[3] = mach->Addrs[index->i[3]].xyzw[swizzle].u[3];
+ break;
+
+ case TGSI_FILE_OUTPUT:
+ /* vertex/fragment output vars can be read too */
+ chan->u[0] = mach->Outputs[index->i[0]].xyzw[swizzle].u[0];
+ chan->u[1] = mach->Outputs[index->i[1]].xyzw[swizzle].u[1];
+ chan->u[2] = mach->Outputs[index->i[2]].xyzw[swizzle].u[2];
+ chan->u[3] = mach->Outputs[index->i[3]].xyzw[swizzle].u[3];
+ break;
+
+ default:
+ ASSERT( 0 );
+ }
+ break;
+
+ case TGSI_EXTSWIZZLE_ZERO:
+ *chan = mach->Temps[TEMP_0_I].xyzw[TEMP_0_C];
+ break;
+
+ case TGSI_EXTSWIZZLE_ONE:
+ *chan = mach->Temps[TEMP_1_I].xyzw[TEMP_1_C];
+ break;
+
+ default:
+ ASSERT( 0 );
+ }
+}
+
+static void
+fetch_source(
+ const struct spu_exec_machine *mach,
+ union spu_exec_channel *chan,
+ const struct tgsi_full_src_register *reg,
+ const uint chan_index )
+{
+ union spu_exec_channel index;
+ uint swizzle;
+
+ index.i[0] =
+ index.i[1] =
+ index.i[2] =
+ index.i[3] = reg->SrcRegister.Index;
+
+ if (reg->SrcRegister.Indirect) {
+ union spu_exec_channel index2;
+ union spu_exec_channel indir_index;
+
+ index2.i[0] =
+ index2.i[1] =
+ index2.i[2] =
+ index2.i[3] = reg->SrcRegisterInd.Index;
+
+ swizzle = tgsi_util_get_src_register_swizzle(&reg->SrcRegisterInd,
+ CHAN_X);
+ fetch_src_file_channel(
+ mach,
+ reg->SrcRegisterInd.File,
+ swizzle,
+ &index2,
+ &indir_index );
+
+ index.q = si_a(index.q, indir_index.q);
+ }
+
+ if( reg->SrcRegister.Dimension ) {
+ switch( reg->SrcRegister.File ) {
+ case TGSI_FILE_INPUT:
+ index.q = si_mpyi(index.q, 17);
+ break;
+ case TGSI_FILE_CONSTANT:
+ index.q = si_shli(index.q, 12);
+ break;
+ default:
+ ASSERT( 0 );
+ }
+
+ index.i[0] += reg->SrcRegisterDim.Index;
+ index.i[1] += reg->SrcRegisterDim.Index;
+ index.i[2] += reg->SrcRegisterDim.Index;
+ index.i[3] += reg->SrcRegisterDim.Index;
+
+ if (reg->SrcRegisterDim.Indirect) {
+ union spu_exec_channel index2;
+ union spu_exec_channel indir_index;
+
+ index2.i[0] =
+ index2.i[1] =
+ index2.i[2] =
+ index2.i[3] = reg->SrcRegisterDimInd.Index;
+
+ swizzle = tgsi_util_get_src_register_swizzle( &reg->SrcRegisterDimInd, CHAN_X );
+ fetch_src_file_channel(
+ mach,
+ reg->SrcRegisterDimInd.File,
+ swizzle,
+ &index2,
+ &indir_index );
+
+ index.q = si_a(index.q, indir_index.q);
+ }
+ }
+
+ swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index );
+ fetch_src_file_channel(
+ mach,
+ reg->SrcRegister.File,
+ swizzle,
+ &index,
+ chan );
+
+ switch (tgsi_util_get_full_src_register_sign_mode( reg, chan_index )) {
+ case TGSI_UTIL_SIGN_CLEAR:
+ chan->q = micro_abs(chan->q);
+ break;
+
+ case TGSI_UTIL_SIGN_SET:
+ chan->q = micro_set_sign(chan->q);
+ break;
+
+ case TGSI_UTIL_SIGN_TOGGLE:
+ chan->q = micro_neg(chan->q);
+ break;
+
+ case TGSI_UTIL_SIGN_KEEP:
+ break;
+ }
+
+ if (reg->SrcRegisterExtMod.Complement) {
+ chan->q = si_fs(mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].q, chan->q);
+ }
+}
+
+static void
+store_dest(
+ struct spu_exec_machine *mach,
+ const union spu_exec_channel *chan,
+ const struct tgsi_full_dst_register *reg,
+ const struct tgsi_full_instruction *inst,
+ uint chan_index )
+{
+ union spu_exec_channel *dst;
+
+ switch( reg->DstRegister.File ) {
+ case TGSI_FILE_NULL:
+ return;
+
+ case TGSI_FILE_OUTPUT:
+ dst = &mach->Outputs[mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0]
+ + reg->DstRegister.Index].xyzw[chan_index];
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ dst = &mach->Temps[reg->DstRegister.Index].xyzw[chan_index];
+ break;
+
+ case TGSI_FILE_ADDRESS:
+ dst = &mach->Addrs[reg->DstRegister.Index].xyzw[chan_index];
+ break;
+
+ default:
+ ASSERT( 0 );
+ return;
+ }
+
+ switch (inst->Instruction.Saturate)
+ {
+ case TGSI_SAT_NONE:
+ if (mach->ExecMask & 0x1)
+ dst->i[0] = chan->i[0];
+ if (mach->ExecMask & 0x2)
+ dst->i[1] = chan->i[1];
+ if (mach->ExecMask & 0x4)
+ dst->i[2] = chan->i[2];
+ if (mach->ExecMask & 0x8)
+ dst->i[3] = chan->i[3];
+ break;
+
+ case TGSI_SAT_ZERO_ONE:
+ /* XXX need to obey ExecMask here */
+ dst->q = micro_max(chan->q, mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].q);
+ dst->q = micro_min(dst->q, mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].q);
+ break;
+
+ case TGSI_SAT_MINUS_PLUS_ONE:
+ ASSERT( 0 );
+ break;
+
+ default:
+ ASSERT( 0 );
+ }
+}
+
+#define FETCH(VAL,INDEX,CHAN)\
+ fetch_source (mach, VAL, &inst->FullSrcRegisters[INDEX], CHAN)
+
+#define STORE(VAL,INDEX,CHAN)\
+ store_dest (mach, VAL, &inst->FullDstRegisters[INDEX], inst, CHAN )
+
+
+/**
+ * Execute ARB-style KIL which is predicated by a src register.
+ * Kill fragment if any of the four values is less than zero.
+ */
+static void
+exec_kil(struct spu_exec_machine *mach,
+ const struct tgsi_full_instruction *inst)
+{
+ uint uniquemask;
+ uint chan_index;
+ uint kilmask = 0; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */
+ union spu_exec_channel r[1];
+
+ /* This mask stores component bits that were already tested. Note that
+ * we test if the value is less than zero, so 1.0 and 0.0 need not to be
+ * tested. */
+ uniquemask = (1 << TGSI_EXTSWIZZLE_ZERO) | (1 << TGSI_EXTSWIZZLE_ONE);
+
+ for (chan_index = 0; chan_index < 4; chan_index++)
+ {
+ uint swizzle;
+ uint i;
+
+ /* unswizzle channel */
+ swizzle = tgsi_util_get_full_src_register_extswizzle (
+ &inst->FullSrcRegisters[0],
+ chan_index);
+
+ /* check if the component has not been already tested */
+ if (uniquemask & (1 << swizzle))
+ continue;
+ uniquemask |= 1 << swizzle;
+
+ FETCH(&r[0], 0, chan_index);
+ for (i = 0; i < 4; i++)
+ if (r[0].f[i] < 0.0f)
+ kilmask |= 1 << i;
+ }
+
+ mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask;
+}
+
+/**
+ * Execute NVIDIA-style KIL which is predicated by a condition code.
+ * Kill fragment if the condition code is TRUE.
+ */
+static void
+exec_kilp(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst)
+{
+ uint kilmask = 0; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */
+
+ /* TODO: build kilmask from CC mask */
+
+ mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask;
+}
+
+/*
+ * Fetch a texel using STR texture coordinates.
+ */
+static void
+fetch_texel( struct spu_sampler *sampler,
+ const union spu_exec_channel *s,
+ const union spu_exec_channel *t,
+ const union spu_exec_channel *p,
+ float lodbias, /* XXX should be float[4] */
+ union spu_exec_channel *r,
+ union spu_exec_channel *g,
+ union spu_exec_channel *b,
+ union spu_exec_channel *a )
+{
+ qword rgba[4];
+ qword out[4];
+
+ sampler->get_samples(sampler, s->f, t->f, p->f, lodbias,
+ (float (*)[4]) rgba);
+
+ _transpose_matrix4x4((vec_float4 *) out, (vec_float4 *) rgba);
+ r->q = out[0];
+ g->q = out[1];
+ b->q = out[2];
+ a->q = out[3];
+}
+
+
+static void
+exec_tex(struct spu_exec_machine *mach,
+ const struct tgsi_full_instruction *inst,
+ boolean biasLod, boolean projected)
+{
+ const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
+ union spu_exec_channel r[8];
+ uint chan_index;
+ float lodBias;
+
+ /* printf("Sampler %u unit %u\n", sampler, unit); */
+
+ switch (inst->InstructionExtTexture.Texture) {
+ case TGSI_TEXTURE_1D:
+
+ FETCH(&r[0], 0, CHAN_X);
+
+ if (projected) {
+ FETCH(&r[1], 0, CHAN_W);
+ r[0].q = micro_div(r[0].q, r[1].q);
+ }
+
+ if (biasLod) {
+ FETCH(&r[1], 0, CHAN_W);
+ lodBias = r[2].f[0];
+ }
+ else
+ lodBias = 0.0;
+
+ fetch_texel(&mach->Samplers[unit],
+ &r[0], NULL, NULL, lodBias, /* S, T, P, BIAS */
+ &r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
+ break;
+
+ case TGSI_TEXTURE_2D:
+ case TGSI_TEXTURE_RECT:
+
+ FETCH(&r[0], 0, CHAN_X);
+ FETCH(&r[1], 0, CHAN_Y);
+ FETCH(&r[2], 0, CHAN_Z);
+
+ if (projected) {
+ FETCH(&r[3], 0, CHAN_W);
+ r[0].q = micro_div(r[0].q, r[3].q);
+ r[1].q = micro_div(r[1].q, r[3].q);
+ r[2].q = micro_div(r[2].q, r[3].q);
+ }
+
+ if (biasLod) {
+ FETCH(&r[3], 0, CHAN_W);
+ lodBias = r[3].f[0];
+ }
+ else
+ lodBias = 0.0;
+
+ fetch_texel(&mach->Samplers[unit],
+ &r[0], &r[1], &r[2], lodBias, /* inputs */
+ &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 (projected) {
+ FETCH(&r[3], 0, CHAN_W);
+ r[0].q = micro_div(r[0].q, r[3].q);
+ r[1].q = micro_div(r[1].q, r[3].q);
+ r[2].q = micro_div(r[2].q, r[3].q);
+ }
+
+ if (biasLod) {
+ FETCH(&r[3], 0, CHAN_W);
+ lodBias = r[3].f[0];
+ }
+ else
+ lodBias = 0.0;
+
+ fetch_texel(&mach->Samplers[unit],
+ &r[0], &r[1], &r[2], lodBias,
+ &r[0], &r[1], &r[2], &r[3]);
+ break;
+
+ default:
+ ASSERT (0);
+ }
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[chan_index], 0, chan_index );
+ }
+}
+
+
+
+static void
+constant_interpolation(
+ struct spu_exec_machine *mach,
+ unsigned attrib,
+ unsigned chan )
+{
+ unsigned i;
+
+ for( i = 0; i < QUAD_SIZE; i++ ) {
+ mach->Inputs[attrib].xyzw[chan].f[i] = mach->InterpCoefs[attrib].a0[chan];
+ }
+}
+
+static void
+linear_interpolation(
+ struct spu_exec_machine *mach,
+ unsigned attrib,
+ unsigned chan )
+{
+ const float x = mach->QuadPos.xyzw[0].f[0];
+ const float y = mach->QuadPos.xyzw[1].f[0];
+ const float dadx = mach->InterpCoefs[attrib].dadx[chan];
+ const float dady = mach->InterpCoefs[attrib].dady[chan];
+ const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y;
+ mach->Inputs[attrib].xyzw[chan].f[0] = a0;
+ mach->Inputs[attrib].xyzw[chan].f[1] = a0 + dadx;
+ mach->Inputs[attrib].xyzw[chan].f[2] = a0 + dady;
+ mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady;
+}
+
+static void
+perspective_interpolation(
+ struct spu_exec_machine *mach,
+ unsigned attrib,
+ unsigned chan )
+{
+ const float x = mach->QuadPos.xyzw[0].f[0];
+ const float y = mach->QuadPos.xyzw[1].f[0];
+ const float dadx = mach->InterpCoefs[attrib].dadx[chan];
+ const float dady = mach->InterpCoefs[attrib].dady[chan];
+ const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y;
+ const float *w = mach->QuadPos.xyzw[3].f;
+ /* divide by W here */
+ mach->Inputs[attrib].xyzw[chan].f[0] = a0 / w[0];
+ mach->Inputs[attrib].xyzw[chan].f[1] = (a0 + dadx) / w[1];
+ mach->Inputs[attrib].xyzw[chan].f[2] = (a0 + dady) / w[2];
+ mach->Inputs[attrib].xyzw[chan].f[3] = (a0 + dadx + dady) / w[3];
+}
+
+
+typedef void (* interpolation_func)(
+ struct spu_exec_machine *mach,
+ unsigned attrib,
+ unsigned chan );
+
+static void
+exec_declaration(struct spu_exec_machine *mach,
+ const struct tgsi_full_declaration *decl)
+{
+ if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) {
+ if( decl->Declaration.File == TGSI_FILE_INPUT ) {
+ unsigned first, last, mask;
+ interpolation_func interp;
+
+ first = decl->DeclarationRange.First;
+ last = decl->DeclarationRange.Last;
+ mask = decl->Declaration.UsageMask;
+
+ switch( decl->Declaration.Interpolate ) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ interp = constant_interpolation;
+ break;
+
+ case TGSI_INTERPOLATE_LINEAR:
+ interp = linear_interpolation;
+ break;
+
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ interp = perspective_interpolation;
+ break;
+
+ default:
+ ASSERT( 0 );
+ }
+
+ if( mask == TGSI_WRITEMASK_XYZW ) {
+ unsigned i, j;
+
+ for( i = first; i <= last; i++ ) {
+ for( j = 0; j < NUM_CHANNELS; j++ ) {
+ interp( mach, i, j );
+ }
+ }
+ }
+ else {
+ unsigned i, j;
+
+ for( j = 0; j < NUM_CHANNELS; j++ ) {
+ if( mask & (1 << j) ) {
+ for( i = first; i <= last; i++ ) {
+ interp( mach, i, j );
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void
+exec_instruction(
+ struct spu_exec_machine *mach,
+ const struct tgsi_full_instruction *inst,
+ int *pc )
+{
+ uint chan_index;
+ union spu_exec_channel r[8];
+
+ (*pc)++;
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ARL:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = si_cflts(r[0].q, 0);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_LIT:
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_X );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y ) || IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ FETCH( &r[0], 0, CHAN_X );
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ r[0].q = micro_max(r[0].q, mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].q);
+ STORE( &r[0], 0, CHAN_Y );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ FETCH( &r[1], 0, CHAN_Y );
+ r[1].q = micro_max(r[1].q, mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].q);
+
+ FETCH( &r[2], 0, CHAN_W );
+ r[2].q = micro_min(r[2].q, mach->Temps[TEMP_128_I].xyzw[TEMP_128_C].q);
+ r[2].q = micro_max(r[2].q, mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C].q);
+ r[1].q = micro_pow(r[1].q, r[2].q);
+
+ /* r0 = (r0 > 0.0) ? r1 : 0.0
+ */
+ r[0].q = si_fcgt(r[0].q, mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].q);
+ r[0].q = si_selb(mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].q, r[1].q,
+ r[0].q);
+ STORE( &r[0], 0, CHAN_Z );
+ }
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_RCP:
+ FETCH( &r[0], 0, CHAN_X );
+ r[0].q = micro_div(mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].q, r[0].q);
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_RSQ:
+ FETCH( &r[0], 0, CHAN_X );
+ r[0].q = micro_sqrt(r[0].q);
+ r[0].q = micro_div(mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].q, r[0].q);
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_EXP:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_LOG:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_MUL:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index )
+ {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+
+ r[0].q = si_fm(r[0].q, r[1].q);
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_ADD:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ r[0].q = si_fa(r[0].q, r[1].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DP3:
+ /* TGSI_OPCODE_DOT3 */
+ FETCH( &r[0], 0, CHAN_X );
+ FETCH( &r[1], 1, CHAN_X );
+ r[0].q = si_fm(r[0].q, r[1].q);
+
+ FETCH( &r[1], 0, CHAN_Y );
+ FETCH( &r[2], 1, CHAN_Y );
+ r[0].q = si_fma(r[1].q, r[2].q, r[0].q);
+
+
+ FETCH( &r[1], 0, CHAN_Z );
+ FETCH( &r[2], 1, CHAN_Z );
+ r[0].q = si_fma(r[1].q, r[2].q, r[0].q);
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DP4:
+ /* TGSI_OPCODE_DOT4 */
+ FETCH(&r[0], 0, CHAN_X);
+ FETCH(&r[1], 1, CHAN_X);
+
+ r[0].q = si_fm(r[0].q, r[1].q);
+
+ FETCH(&r[1], 0, CHAN_Y);
+ FETCH(&r[2], 1, CHAN_Y);
+
+ r[0].q = si_fma(r[1].q, r[2].q, r[0].q);
+
+ FETCH(&r[1], 0, CHAN_Z);
+ FETCH(&r[2], 1, CHAN_Z);
+
+ r[0].q = si_fma(r[1].q, r[2].q, r[0].q);
+
+ FETCH(&r[1], 0, CHAN_W);
+ FETCH(&r[2], 1, CHAN_W);
+
+ r[0].q = si_fma(r[1].q, r[2].q, r[0].q);
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DST:
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_X );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ FETCH( &r[0], 0, CHAN_Y );
+ FETCH( &r[1], 1, CHAN_Y);
+ r[0].q = si_fm(r[0].q, r[1].q);
+ STORE( &r[0], 0, CHAN_Y );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ FETCH( &r[0], 0, CHAN_Z );
+ STORE( &r[0], 0, CHAN_Z );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ FETCH( &r[0], 1, CHAN_W );
+ STORE( &r[0], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_MIN:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+
+ r[0].q = micro_min(r[0].q, r[1].q);
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_MAX:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+
+ r[0].q = micro_max(r[0].q, r[1].q);
+
+ STORE(&r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SLT:
+ /* TGSI_OPCODE_SETLT */
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+
+ r[0].q = micro_ge(r[0].q, r[1].q);
+ r[0].q = si_xori(r[0].q, 0xff);
+
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SGE:
+ /* TGSI_OPCODE_SETGE */
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ r[0].q = micro_ge(r[0].q, r[1].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_MAD:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ FETCH( &r[2], 2, chan_index );
+ r[0].q = si_fma(r[0].q, r[1].q, r[2].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SUB:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+
+ r[0].q = si_fs(r[0].q, r[1].q);
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_LRP:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+ FETCH(&r[2], 2, chan_index);
+
+ r[1].q = si_fs(r[1].q, r[2].q);
+ r[0].q = si_fma(r[0].q, r[1].q, r[2].q);
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_CND:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_DP2A:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_FRC:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = micro_frc(r[0].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_CLAMP:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_FLR:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = micro_flr(r[0].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_ROUND:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = micro_rnd(r[0].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_EX2:
+ FETCH(&r[0], 0, CHAN_X);
+
+ r[0].q = micro_pow(mach->Temps[TEMP_2_I].xyzw[TEMP_2_C].q, r[0].q);
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_LG2:
+ FETCH( &r[0], 0, CHAN_X );
+ r[0].q = micro_lg2(r[0].q);
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_POW:
+ FETCH(&r[0], 0, CHAN_X);
+ FETCH(&r[1], 1, CHAN_X);
+
+ r[0].q = micro_pow(r[0].q, r[1].q);
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_XPD:
+ /* TGSI_OPCODE_XPD */
+ FETCH(&r[0], 0, CHAN_Y);
+ FETCH(&r[1], 1, CHAN_Z);
+ FETCH(&r[3], 0, CHAN_Z);
+ FETCH(&r[4], 1, CHAN_Y);
+
+ /* r2 = (r0 * r1) - (r3 * r5)
+ */
+ r[2].q = si_fm(r[3].q, r[5].q);
+ r[2].q = si_fms(r[0].q, r[1].q, r[2].q);
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+ STORE( &r[2], 0, CHAN_X );
+ }
+
+ FETCH(&r[2], 1, CHAN_X);
+ FETCH(&r[5], 0, CHAN_X);
+
+ /* r3 = (r3 * r2) - (r1 * r5)
+ */
+ r[1].q = si_fm(r[1].q, r[5].q);
+ r[3].q = si_fms(r[3].q, r[2].q, r[1].q);
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+ STORE( &r[3], 0, CHAN_Y );
+ }
+
+ /* r5 = (r5 * r4) - (r0 * r2)
+ */
+ r[0].q = si_fm(r[0].q, r[2].q);
+ r[5].q = si_fms(r[5].q, r[4].q, r[0].q);
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+ STORE( &r[5], 0, CHAN_Z );
+ }
+
+ if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_ABS:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+
+ r[0].q = micro_abs(r[0].q);
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_RCC:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_DPH:
+ FETCH(&r[0], 0, CHAN_X);
+ FETCH(&r[1], 1, CHAN_X);
+
+ r[0].q = si_fm(r[0].q, r[1].q);
+
+ FETCH(&r[1], 0, CHAN_Y);
+ FETCH(&r[2], 1, CHAN_Y);
+
+ r[0].q = si_fma(r[1].q, r[2].q, r[0].q);
+
+ FETCH(&r[1], 0, CHAN_Z);
+ FETCH(&r[2], 1, CHAN_Z);
+
+ r[0].q = si_fma(r[1].q, r[2].q, r[0].q);
+
+ FETCH(&r[1], 1, CHAN_W);
+
+ r[0].q = si_fa(r[0].q, r[1].q);
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_COS:
+ FETCH(&r[0], 0, CHAN_X);
+
+ r[0].q = micro_cos(r[0].q);
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DDX:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = micro_ddx(r[0].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_DDY:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = micro_ddy(r[0].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_KILP:
+ exec_kilp (mach, inst);
+ break;
+
+ case TGSI_OPCODE_KIL:
+ exec_kil (mach, inst);
+ break;
+
+ case TGSI_OPCODE_PK2H:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_PK2US:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_PK4B:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_PK4UB:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_RFL:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_SEQ:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+
+ r[0].q = si_fceq(r[0].q, r[1].q);
+
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SFL:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_SGT:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ r[0].q = si_fcgt(r[0].q, r[1].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SIN:
+ FETCH( &r[0], 0, CHAN_X );
+ r[0].q = micro_sin(r[0].q);
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SLE:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+
+ r[0].q = si_fcgt(r[0].q, r[1].q);
+ r[0].q = si_xori(r[0].q, 0xff);
+
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SNE:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+
+ r[0].q = si_fceq(r[0].q, r[1].q);
+ r[0].q = si_xori(r[0].q, 0xff);
+
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_STR:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_TEX:
+ /* simple texture lookup */
+ /* src[0] = texcoord */
+ /* src[1] = sampler unit */
+ exec_tex(mach, inst, FALSE, FALSE);
+ break;
+
+ case TGSI_OPCODE_TXB:
+ /* Texture lookup with lod bias */
+ /* src[0] = texcoord (src[0].w = load bias) */
+ /* src[1] = sampler unit */
+ exec_tex(mach, inst, TRUE, FALSE);
+ break;
+
+ case TGSI_OPCODE_TXD:
+ /* Texture lookup with explict partial derivatives */
+ /* src[0] = texcoord */
+ /* src[1] = d[strq]/dx */
+ /* src[2] = d[strq]/dy */
+ /* src[3] = sampler unit */
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_TXL:
+ /* Texture lookup with explit LOD */
+ /* src[0] = texcoord (src[0].w = load bias) */
+ /* src[1] = sampler unit */
+ exec_tex(mach, inst, TRUE, FALSE);
+ break;
+
+ case TGSI_OPCODE_TXP:
+ /* Texture lookup with projection */
+ /* src[0] = texcoord (src[0].w = projection) */
+ /* src[1] = sampler unit */
+ exec_tex(mach, inst, TRUE, TRUE);
+ break;
+
+ case TGSI_OPCODE_UP2H:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_UP2US:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_UP4B:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_UP4UB:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_X2D:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_ARA:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_ARR:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_BRA:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_CAL:
+ /* skip the call if no execution channels are enabled */
+ if (mach->ExecMask) {
+ /* do the call */
+
+ /* push the Cond, Loop, Cont stacks */
+ ASSERT(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
+ mach->CondStack[mach->CondStackTop++] = mach->CondMask;
+ ASSERT(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
+ ASSERT(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->ContStack[mach->ContStackTop++] = mach->ContMask;
+
+ ASSERT(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING);
+ mach->FuncStack[mach->FuncStackTop++] = mach->FuncMask;
+
+ /* note that PC was already incremented above */
+ mach->CallStack[mach->CallStackTop++] = *pc;
+ *pc = inst->InstructionExtLabel.Label;
+ }
+ break;
+
+ case TGSI_OPCODE_RET:
+ mach->FuncMask &= ~mach->ExecMask;
+ UPDATE_EXEC_MASK(mach);
+
+ if (mach->ExecMask == 0x0) {
+ /* really return now (otherwise, keep executing */
+
+ if (mach->CallStackTop == 0) {
+ /* returning from main() */
+ *pc = -1;
+ return;
+ }
+ *pc = mach->CallStack[--mach->CallStackTop];
+
+ /* pop the Cond, Loop, Cont stacks */
+ ASSERT(mach->CondStackTop > 0);
+ mach->CondMask = mach->CondStack[--mach->CondStackTop];
+ ASSERT(mach->LoopStackTop > 0);
+ mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
+ ASSERT(mach->ContStackTop > 0);
+ mach->ContMask = mach->ContStack[--mach->ContStackTop];
+ ASSERT(mach->FuncStackTop > 0);
+ mach->FuncMask = mach->FuncStack[--mach->FuncStackTop];
+
+ UPDATE_EXEC_MASK(mach);
+ }
+ break;
+
+ case TGSI_OPCODE_SSG:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_CMP:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH(&r[0], 0, chan_index);
+ FETCH(&r[1], 1, chan_index);
+ FETCH(&r[2], 2, chan_index);
+
+ /* r0 = (r0 < 0.0) ? r1 : r2
+ */
+ r[3].q = si_xor(r[3].q, r[3].q);
+ r[0].q = micro_lt(r[0].q, r[3].q);
+ r[0].q = si_selb(r[1].q, r[2].q, r[0].q);
+
+ STORE(&r[0], 0, chan_index);
+ }
+ break;
+
+ case TGSI_OPCODE_SCS:
+ if( IS_CHANNEL_ENABLED( *inst, CHAN_X ) || IS_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
+ FETCH( &r[0], 0, CHAN_X );
+ }
+ if( IS_CHANNEL_ENABLED( *inst, CHAN_X ) ) {
+ r[1].q = micro_cos(r[0].q);
+ STORE( &r[1], 0, CHAN_X );
+ }
+ if( IS_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
+ r[1].q = micro_sin(r[0].q);
+ STORE( &r[1], 0, CHAN_Y );
+ }
+ if( IS_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
+ STORE( &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], 0, CHAN_Z );
+ }
+ if( IS_CHANNEL_ENABLED( *inst, CHAN_W ) ) {
+ STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+ }
+ break;
+
+ case TGSI_OPCODE_NRM:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_DIV:
+ ASSERT( 0 );
+ break;
+
+ case TGSI_OPCODE_DP2:
+ FETCH( &r[0], 0, CHAN_X );
+ FETCH( &r[1], 1, CHAN_X );
+ r[0].q = si_fm(r[0].q, r[1].q);
+
+ FETCH( &r[1], 0, CHAN_Y );
+ FETCH( &r[2], 1, CHAN_Y );
+ r[0].q = si_fma(r[1].q, r[2].q, r[0].q);
+
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_IF:
+ /* push CondMask */
+ ASSERT(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
+ mach->CondStack[mach->CondStackTop++] = mach->CondMask;
+ FETCH( &r[0], 0, CHAN_X );
+ /* update CondMask */
+ if( ! r[0].u[0] ) {
+ mach->CondMask &= ~0x1;
+ }
+ if( ! r[0].u[1] ) {
+ mach->CondMask &= ~0x2;
+ }
+ if( ! r[0].u[2] ) {
+ mach->CondMask &= ~0x4;
+ }
+ if( ! r[0].u[3] ) {
+ mach->CondMask &= ~0x8;
+ }
+ UPDATE_EXEC_MASK(mach);
+ /* Todo: If CondMask==0, jump to ELSE */
+ break;
+
+ case TGSI_OPCODE_ELSE:
+ /* invert CondMask wrt previous mask */
+ {
+ uint prevMask;
+ ASSERT(mach->CondStackTop > 0);
+ prevMask = mach->CondStack[mach->CondStackTop - 1];
+ mach->CondMask = ~mach->CondMask & prevMask;
+ UPDATE_EXEC_MASK(mach);
+ /* Todo: If CondMask==0, jump to ENDIF */
+ }
+ break;
+
+ case TGSI_OPCODE_ENDIF:
+ /* pop CondMask */
+ ASSERT(mach->CondStackTop > 0);
+ mach->CondMask = mach->CondStack[--mach->CondStackTop];
+ UPDATE_EXEC_MASK(mach);
+ break;
+
+ case TGSI_OPCODE_END:
+ /* halt execution */
+ *pc = -1;
+ break;
+
+ case TGSI_OPCODE_REP:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_ENDREP:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_PUSHA:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_POPA:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_CEIL:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = micro_ceil(r[0].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_I2F:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = si_csflt(r[0].q, 0);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_NOT:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = si_xorbi(r[0].q, 0xff);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_TRUNC:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ r[0].q = micro_trunc(r[0].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SHL:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+
+ r[0].q = si_shl(r[0].q, r[1].q);
+
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SHR:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ r[0].q = micro_ishr(r[0].q, r[1].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_AND:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ r[0].q = si_and(r[0].q, r[1].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_OR:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ r[0].q = si_or(r[0].q, r[1].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_MOD:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_XOR:
+ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+ FETCH( &r[0], 0, chan_index );
+ FETCH( &r[1], 1, chan_index );
+ r[0].q = si_xor(r[0].q, r[1].q);
+ STORE( &r[0], 0, chan_index );
+ }
+ break;
+
+ case TGSI_OPCODE_SAD:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_TXF:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_TXQ:
+ ASSERT (0);
+ break;
+
+ case TGSI_OPCODE_EMIT:
+ mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] += 16;
+ mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]]++;
+ break;
+
+ case TGSI_OPCODE_ENDPRIM:
+ mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]++;
+ mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]] = 0;
+ break;
+
+ case TGSI_OPCODE_BGNFOR:
+ /* fall-through (for now) */
+ case TGSI_OPCODE_BGNLOOP:
+ /* push LoopMask and ContMasks */
+ ASSERT(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
+ ASSERT(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->ContStack[mach->ContStackTop++] = mach->ContMask;
+ break;
+
+ case TGSI_OPCODE_ENDFOR:
+ /* fall-through (for now at least) */
+ case TGSI_OPCODE_ENDLOOP:
+ /* Restore ContMask, but don't pop */
+ ASSERT(mach->ContStackTop > 0);
+ mach->ContMask = mach->ContStack[mach->ContStackTop - 1];
+ if (mach->LoopMask) {
+ /* repeat loop: jump to instruction just past BGNLOOP */
+ *pc = inst->InstructionExtLabel.Label + 1;
+ }
+ else {
+ /* exit loop: pop LoopMask */
+ ASSERT(mach->LoopStackTop > 0);
+ mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
+ /* pop ContMask */
+ ASSERT(mach->ContStackTop > 0);
+ mach->ContMask = mach->ContStack[--mach->ContStackTop];
+ }
+ UPDATE_EXEC_MASK(mach);
+ break;
+
+ case TGSI_OPCODE_BRK:
+ /* turn off loop channels for each enabled exec channel */
+ mach->LoopMask &= ~mach->ExecMask;
+ /* Todo: if mach->LoopMask == 0, jump to end of loop */
+ UPDATE_EXEC_MASK(mach);
+ break;
+
+ case TGSI_OPCODE_CONT:
+ /* turn off cont channels for each enabled exec channel */
+ mach->ContMask &= ~mach->ExecMask;
+ /* Todo: if mach->LoopMask == 0, jump to end of loop */
+ UPDATE_EXEC_MASK(mach);
+ break;
+
+ case TGSI_OPCODE_BGNSUB:
+ /* no-op */
+ break;
+
+ case TGSI_OPCODE_ENDSUB:
+ /* no-op */
+ break;
+
+ case TGSI_OPCODE_NOISE1:
+ ASSERT( 0 );
+ break;
+
+ case TGSI_OPCODE_NOISE2:
+ ASSERT( 0 );
+ break;
+
+ case TGSI_OPCODE_NOISE3:
+ ASSERT( 0 );
+ break;
+
+ case TGSI_OPCODE_NOISE4:
+ ASSERT( 0 );
+ break;
+
+ case TGSI_OPCODE_NOP:
+ break;
+
+ default:
+ ASSERT( 0 );
+ }
+}
+
+
+/**
+ * Run TGSI interpreter.
+ * \return bitmask of "alive" quad components
+ */
+uint
+spu_exec_machine_run( struct spu_exec_machine *mach )
+{
+ uint i;
+ int pc = 0;
+
+ mach->CondMask = 0xf;
+ mach->LoopMask = 0xf;
+ mach->ContMask = 0xf;
+ mach->FuncMask = 0xf;
+ mach->ExecMask = 0xf;
+
+ mach->CondStackTop = 0; /* temporarily subvert this ASSERTion */
+ ASSERT(mach->CondStackTop == 0);
+ ASSERT(mach->LoopStackTop == 0);
+ ASSERT(mach->ContStackTop == 0);
+ ASSERT(mach->CallStackTop == 0);
+
+ mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0;
+ mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] = 0;
+
+ if( mach->Processor == TGSI_PROCESSOR_GEOMETRY ) {
+ mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0] = 0;
+ mach->Primitives[0] = 0;
+ }
+
+
+ /* execute declarations (interpolants) */
+ if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) {
+ for (i = 0; i < mach->NumDeclarations; i++) {
+ union {
+ struct tgsi_full_declaration decl;
+ qword buffer[ROUNDUP16(sizeof(struct tgsi_full_declaration)) / 16];
+ } d ALIGN16_ATTRIB;
+ unsigned ea = (unsigned) (mach->Declarations + pc);
+
+ spu_dcache_fetch_unaligned(d.buffer, ea, sizeof(d.decl));
+
+ exec_declaration( mach, &d.decl );
+ }
+ }
+
+ /* execute instructions, until pc is set to -1 */
+ while (pc != -1) {
+ union {
+ struct tgsi_full_instruction inst;
+ qword buffer[ROUNDUP16(sizeof(struct tgsi_full_instruction)) / 16];
+ } i ALIGN16_ATTRIB;
+ unsigned ea = (unsigned) (mach->Instructions + pc);
+
+ spu_dcache_fetch_unaligned(i.buffer, ea, sizeof(i.inst));
+ exec_instruction( mach, & i.inst, &pc );
+ }
+
+#if 0
+ /* we scale from floats in [0,1] to Zbuffer ints in sp_quad_depth_test.c */
+ if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
+ /*
+ * Scale back depth component.
+ */
+ for (i = 0; i < 4; i++)
+ mach->Outputs[0].xyzw[2].f[i] *= ctx->DrawBuffer->_DepthMaxF;
+ }
+#endif
+
+ return ~mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
+}
+
+
diff --git a/src/gallium/drivers/cell/spu/spu_exec.h b/src/gallium/drivers/cell/spu/spu_exec.h
new file mode 100644
index 0000000000..8605679940
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_exec.h
@@ -0,0 +1,172 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#if !defined SPU_EXEC_H
+#define SPU_EXEC_H
+
+#include "pipe/p_compiler.h"
+#include "tgsi/tgsi_exec.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Registers may be treated as float, signed int or unsigned int.
+ */
+union spu_exec_channel
+{
+ float f[QUAD_SIZE];
+ int i[QUAD_SIZE];
+ unsigned u[QUAD_SIZE];
+ qword q;
+};
+
+/**
+ * A vector[RGBA] of channels[4 pixels]
+ */
+struct spu_exec_vector
+{
+ union spu_exec_channel xyzw[NUM_CHANNELS];
+};
+
+/**
+ * For fragment programs, information for computing fragment input
+ * values from plane equation of the triangle/line.
+ */
+struct spu_interp_coef
+{
+ float a0[NUM_CHANNELS]; /* in an xyzw layout */
+ float dadx[NUM_CHANNELS];
+ float dady[NUM_CHANNELS];
+};
+
+
+struct softpipe_tile_cache; /**< Opaque to TGSI */
+
+/**
+ * Information for sampling textures, which must be implemented
+ * by code outside the TGSI executor.
+ */
+struct spu_sampler
+{
+ const struct pipe_sampler_state *state;
+ struct pipe_texture *texture;
+ /** Get samples for four fragments in a quad */
+ void (*get_samples)(struct spu_sampler *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE]);
+ void *pipe; /*XXX temporary*/
+ struct softpipe_tile_cache *cache;
+};
+
+
+/**
+ * Run-time virtual machine state for executing TGSI shader.
+ */
+struct spu_exec_machine
+{
+ /*
+ * 32 program temporaries
+ * 4 internal temporaries
+ * 1 address
+ */
+ struct spu_exec_vector Temps[TGSI_EXEC_NUM_TEMPS
+ + TGSI_EXEC_NUM_TEMP_EXTRAS + 1]
+ ALIGN16_ATTRIB;
+
+ struct spu_exec_vector *Addrs;
+
+ struct spu_sampler *Samplers;
+
+ float Imms[TGSI_EXEC_NUM_IMMEDIATES][4];
+ unsigned ImmLimit;
+ float (*Consts)[4];
+ struct spu_exec_vector *Inputs;
+ struct spu_exec_vector *Outputs;
+ unsigned Processor;
+
+ /* GEOMETRY processor only. */
+ unsigned *Primitives;
+
+ /* FRAGMENT processor only. */
+ const struct spu_interp_coef *InterpCoefs;
+ struct spu_exec_vector QuadPos;
+
+ /* Conditional execution masks */
+ uint CondMask; /**< For IF/ELSE/ENDIF */
+ uint LoopMask; /**< For BGNLOOP/ENDLOOP */
+ uint ContMask; /**< For loop CONT statements */
+ uint FuncMask; /**< For function calls */
+ uint ExecMask; /**< = CondMask & LoopMask */
+
+ /** Condition mask stack (for nested conditionals) */
+ uint CondStack[TGSI_EXEC_MAX_COND_NESTING];
+ int CondStackTop;
+
+ /** Loop mask stack (for nested loops) */
+ uint LoopStack[TGSI_EXEC_MAX_LOOP_NESTING];
+ int LoopStackTop;
+
+ /** Loop continue mask stack (see comments in tgsi_exec.c) */
+ uint ContStack[TGSI_EXEC_MAX_LOOP_NESTING];
+ int ContStackTop;
+
+ /** Function execution mask stack (for executing subroutine code) */
+ uint FuncStack[TGSI_EXEC_MAX_CALL_NESTING];
+ int FuncStackTop;
+
+ /** Function call stack for saving/restoring the program counter */
+ uint CallStack[TGSI_EXEC_MAX_CALL_NESTING];
+ int CallStackTop;
+
+ struct tgsi_full_instruction *Instructions;
+ uint NumInstructions;
+
+ struct tgsi_full_declaration *Declarations;
+ uint NumDeclarations;
+};
+
+
+extern void
+spu_exec_machine_init(struct spu_exec_machine *mach,
+ uint numSamplers,
+ struct spu_sampler *samplers,
+ unsigned processor);
+
+extern uint
+spu_exec_machine_run( struct spu_exec_machine *mach );
+
+
+#if defined __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* SPU_EXEC_H */
diff --git a/src/gallium/drivers/cell/spu/spu_funcs.c b/src/gallium/drivers/cell/spu/spu_funcs.c
new file mode 100644
index 0000000000..ff3d609d25
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_funcs.c
@@ -0,0 +1,173 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * SPU functions accessed by shaders.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include <string.h>
+#include <libmisc.h>
+#include <math.h>
+#include <cos14_v.h>
+#include <sin14_v.h>
+#include <simdmath/exp2f4.h>
+#include <simdmath/log2f4.h>
+#include <simdmath/powf4.h>
+
+#include "cell/common.h"
+#include "spu_main.h"
+#include "spu_funcs.h"
+#include "spu_texture.h"
+
+
+/** For "return"-ing four vectors */
+struct vec_4x4
+{
+ vector float v[4];
+};
+
+
+static vector float
+spu_cos(vector float x)
+{
+ return _cos14_v(x);
+}
+
+static vector float
+spu_sin(vector float x)
+{
+ return _sin14_v(x);
+}
+
+static vector float
+spu_pow(vector float x, vector float y)
+{
+ return _powf4(x, y);
+}
+
+static vector float
+spu_exp2(vector float x)
+{
+ return _exp2f4(x);
+}
+
+static vector float
+spu_log2(vector float x)
+{
+ return _log2f4(x);
+}
+
+
+static struct vec_4x4
+spu_tex_2d(vector float s, vector float t, vector float r, vector float q,
+ unsigned unit)
+{
+ struct vec_4x4 colors;
+ (void) r;
+ (void) q;
+ spu.sample_texture_2d[unit](s, t, unit, 0, 0, colors.v);
+ return colors;
+}
+
+static struct vec_4x4
+spu_tex_3d(vector float s, vector float t, vector float r, vector float q,
+ unsigned unit)
+{
+ struct vec_4x4 colors;
+ (void) r;
+ (void) q;
+ spu.sample_texture_2d[unit](s, t, unit, 0, 0, colors.v);
+ return colors;
+}
+
+static struct vec_4x4
+spu_tex_cube(vector float s, vector float t, vector float r, vector float q,
+ unsigned unit)
+{
+ struct vec_4x4 colors;
+ (void) q;
+ sample_texture_cube(s, t, r, unit, colors.v);
+ return colors;
+}
+
+
+/**
+ * Add named function to list of "exported" functions that will be
+ * made available to the PPU-hosted code generator.
+ */
+static void
+export_func(struct cell_spu_function_info *spu_functions,
+ const char *name, void *addr)
+{
+ uint n = spu_functions->num;
+ ASSERT(strlen(name) < 16);
+ strcpy(spu_functions->names[n], name);
+ spu_functions->addrs[n] = (uint) addr;
+ spu_functions->num++;
+ ASSERT(spu_functions->num <= 16);
+}
+
+
+/**
+ * Return info about the SPU's function to the PPU / main memory.
+ * The PPU needs to know the address of some SPU-side functions so
+ * that we can generate shader code with function calls.
+ */
+void
+return_function_info(void)
+{
+ struct cell_spu_function_info funcs ALIGN16_ATTRIB;
+ int tag = TAG_MISC;
+
+ ASSERT(sizeof(funcs) == 256); /* must be multiple of 16 bytes */
+
+ funcs.num = 0;
+ export_func(&funcs, "spu_cos", &spu_cos);
+ export_func(&funcs, "spu_sin", &spu_sin);
+ export_func(&funcs, "spu_pow", &spu_pow);
+ export_func(&funcs, "spu_exp2", &spu_exp2);
+ export_func(&funcs, "spu_log2", &spu_log2);
+ export_func(&funcs, "spu_tex_2d", &spu_tex_2d);
+ export_func(&funcs, "spu_tex_3d", &spu_tex_3d);
+ export_func(&funcs, "spu_tex_cube", &spu_tex_cube);
+
+ /* Send the function info back to the PPU / main memory */
+ mfc_put((void *) &funcs, /* src in local store */
+ (unsigned int) spu.init.spu_functions, /* dst in main memory */
+ sizeof(funcs), /* bytes */
+ tag,
+ 0, /* tid */
+ 0 /* rid */);
+ wait_on_mask(1 << tag);
+}
+
+
+
diff --git a/src/gallium/drivers/cell/spu/spu_funcs.h b/src/gallium/drivers/cell/spu/spu_funcs.h
new file mode 100644
index 0000000000..3adb6ae99f
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_funcs.h
@@ -0,0 +1,35 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SPU_FUNCS_H
+#define SPU_FUNCS_H
+
+extern void
+return_function_info(void);
+
+#endif
+
diff --git a/src/gallium/drivers/cell/spu/spu_main.c b/src/gallium/drivers/cell/spu/spu_main.c
new file mode 100644
index 0000000000..97c86d194d
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_main.c
@@ -0,0 +1,117 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/* main() for Cell SPU code */
+
+
+#include <stdio.h>
+#include <libmisc.h>
+
+#include "pipe/p_defines.h"
+
+#include "spu_funcs.h"
+#include "spu_command.h"
+#include "spu_main.h"
+#include "spu_per_fragment_op.h"
+#include "spu_texture.h"
+//#include "spu_test.h"
+#include "cell/common.h"
+
+
+/*
+helpful headers:
+/usr/lib/gcc/spu/4.1.1/include/spu_mfcio.h
+/opt/cell/sdk/usr/include/libmisc.h
+*/
+
+struct spu_global spu;
+
+
+static void
+one_time_init(void)
+{
+ memset(spu.ctile_status, TILE_STATUS_DEFINED, sizeof(spu.ctile_status));
+ memset(spu.ztile_status, TILE_STATUS_DEFINED, sizeof(spu.ztile_status));
+ invalidate_tex_cache();
+}
+
+/* In some versions of the SDK the SPE main takes 'unsigned long' as a
+ * parameter. In others it takes 'unsigned long long'. Use a define to
+ * select between the two.
+ */
+#ifdef SPU_MAIN_PARAM_LONG_LONG
+typedef unsigned long long main_param_t;
+#else
+typedef unsigned long main_param_t;
+#endif
+
+/**
+ * SPE entrypoint.
+ */
+int
+main(main_param_t speid, main_param_t argp)
+{
+ int tag = 0;
+
+ (void) speid;
+
+ ASSERT(sizeof(tile_t) == TILE_SIZE * TILE_SIZE * 4);
+ ASSERT(sizeof(struct cell_command_render) % 8 == 0);
+ ASSERT(sizeof(struct cell_command_fragment_ops) % 8 == 0);
+ ASSERT(((unsigned long) &spu.fragment_program_code) % 8 == 0);
+
+ one_time_init();
+ spu_command_init();
+
+ D_PRINTF(CELL_DEBUG_CMD, "main() speid=%lu\n", (unsigned long) speid);
+ D_PRINTF(CELL_DEBUG_FRAGMENT_OP_FALLBACK, "using fragment op fallback\n");
+
+ /* get initialization data */
+ mfc_get(&spu.init, /* dest */
+ (unsigned int) argp, /* src */
+ sizeof(struct cell_init_info), /* bytes */
+ tag,
+ 0, /* tid */
+ 0 /* rid */);
+ wait_on_mask( 1 << tag );
+
+ if (spu.init.id == 0) {
+ return_function_info();
+ }
+
+#if 0
+ if (spu.init.id==0)
+ spu_test_misc(spu.init.id);
+#endif
+
+ command_loop();
+
+ spu_command_close();
+
+ return 0;
+}
diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h
new file mode 100644
index 0000000000..33767e7c51
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_main.h
@@ -0,0 +1,254 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SPU_MAIN_H
+#define SPU_MAIN_H
+
+
+#include <spu_mfcio.h>
+
+#include "cell/common.h"
+#include "draw/draw_vertex.h"
+#include "pipe/p_state.h"
+
+
+#if DEBUG
+/* These debug macros use the unusual construction ", ##__VA_ARGS__"
+ * which expands to the expected comma + args if variadic arguments
+ * are supplied, but swallows the comma if there are no variadic
+ * arguments (which avoids syntax errors that would otherwise occur).
+ */
+#define D_PRINTF(flag, format,...) \
+ if (spu.init.debug_flags & (flag)) \
+ printf("SPU %u: " format, spu.init.id, ##__VA_ARGS__)
+#else
+#define D_PRINTF(...)
+#endif
+
+
+/**
+ * A tile is basically a TILE_SIZE x TILE_SIZE block of 4-byte pixels.
+ * The data may be addressed through several different types.
+ */
+typedef union {
+ ushort us[TILE_SIZE][TILE_SIZE];
+ uint ui[TILE_SIZE][TILE_SIZE];
+ vector unsigned short us8[TILE_SIZE/2][TILE_SIZE/4];
+ vector unsigned int ui4[TILE_SIZE/2][TILE_SIZE/2];
+} tile_t;
+
+
+#define TILE_STATUS_CLEAR 1
+#define TILE_STATUS_DEFINED 2 /**< defined in FB, but not in local store */
+#define TILE_STATUS_CLEAN 3 /**< in local store, but not changed */
+#define TILE_STATUS_DIRTY 4 /**< modified locally, but not put back yet */
+#define TILE_STATUS_GETTING 5 /**< mfc_get() called but not yet arrived */
+
+
+/** Function for sampling textures */
+typedef void (*spu_sample_texture_2d_func)(vector float s,
+ vector float t,
+ uint unit, uint level, uint face,
+ vector float colors[4]);
+
+
+/** Function for performing per-fragment ops */
+typedef void (*spu_fragment_ops_func)(uint x, uint y,
+ tile_t *colorTile,
+ tile_t *depthStencilTile,
+ vector float fragZ,
+ vector float fragRed,
+ vector float fragGreen,
+ vector float fragBlue,
+ vector float fragAlpha,
+ vector unsigned int mask);
+
+/** Function for running fragment program */
+typedef vector unsigned int (*spu_fragment_program_func)(vector float *inputs,
+ vector float *outputs,
+ vector float *constants);
+
+
+struct spu_framebuffer
+{
+ void *color_start; /**< addr of color surface in main memory */
+ void *depth_start; /**< addr of depth surface in main memory */
+ enum pipe_format color_format;
+ enum pipe_format depth_format;
+ uint width, height; /**< size in pixels */
+ uint width_tiles, height_tiles; /**< width and height in tiles */
+
+ uint color_clear_value;
+ uint depth_clear_value;
+
+ uint zsize; /**< 0, 2 or 4 bytes per Z */
+ float zscale; /**< 65535.0, 2^24-1 or 2^32-1 */
+} ALIGN16_ATTRIB;
+
+
+/** per-texture level info */
+struct spu_texture_level
+{
+ void *start;
+ ushort width, height, depth;
+ ushort tiles_per_row;
+ uint bytes_per_image;
+ /** texcoord scale factors */
+ vector float scale_s, scale_t, scale_r;
+ /** texcoord masks (if REPEAT then size-1, else ~0) */
+ vector signed int mask_s, mask_t, mask_r;
+ /** texcoord clamp limits */
+ vector signed int max_s, max_t, max_r;
+} ALIGN16_ATTRIB;
+
+
+struct spu_texture
+{
+ struct spu_texture_level level[CELL_MAX_TEXTURE_LEVELS];
+ uint max_level;
+ uint target; /**< PIPE_TEXTURE_x */
+} ALIGN16_ATTRIB;
+
+
+/**
+ * All SPU global/context state will be in a singleton object of this type:
+ */
+struct spu_global
+{
+ /** One-time init/constant info */
+ struct cell_init_info init;
+
+ /*
+ * Current state
+ */
+ struct spu_framebuffer fb;
+ struct pipe_depth_stencil_alpha_state depth_stencil_alpha;
+ struct pipe_blend_state blend;
+ struct pipe_blend_color blend_color;
+ struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS];
+ struct pipe_rasterizer_state rasterizer;
+ struct spu_texture texture[PIPE_MAX_SAMPLERS];
+ struct vertex_info vertex_info;
+
+ /** Current color and Z tiles */
+ tile_t ctile ALIGN16_ATTRIB;
+ tile_t ztile ALIGN16_ATTRIB;
+
+ /** Read depth/stencil tiles? */
+ boolean read_depth_stencil;
+
+ /** Current tiles' status */
+ ubyte cur_ctile_status, cur_ztile_status;
+
+ /** Status of all tiles in framebuffer */
+ ubyte ctile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB;
+ ubyte ztile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB;
+
+ /** Current fragment ops machine code, at 8-byte boundary */
+ uint *fragment_ops_code;
+ uint fragment_ops_code_size;
+ /** Current fragment ops functions, 0 = frontfacing, 1 = backfacing */
+ spu_fragment_ops_func fragment_ops[2];
+
+ /** Current fragment program machine code, at 8-byte boundary */
+ uint fragment_program_code[SPU_MAX_FRAGMENT_PROGRAM_INSTS] ALIGN8_ATTRIB;
+ /** Current fragment ops function */
+ spu_fragment_program_func fragment_program;
+
+ /** Current texture sampler function */
+ spu_sample_texture_2d_func sample_texture_2d[CELL_MAX_SAMPLERS];
+ spu_sample_texture_2d_func min_sample_texture_2d[CELL_MAX_SAMPLERS];
+ spu_sample_texture_2d_func mag_sample_texture_2d[CELL_MAX_SAMPLERS];
+
+ /** Fragment program constants */
+ vector float constants[4 * CELL_MAX_CONSTANTS];
+
+} ALIGN16_ATTRIB;
+
+
+extern struct spu_global spu;
+
+
+
+/* DMA TAGS */
+
+#define TAG_SURFACE_CLEAR 10
+#define TAG_VERTEX_BUFFER 11
+#define TAG_READ_TILE_COLOR 12
+#define TAG_READ_TILE_Z 13
+#define TAG_WRITE_TILE_COLOR 14
+#define TAG_WRITE_TILE_Z 15
+#define TAG_INDEX_BUFFER 16
+#define TAG_BATCH_BUFFER 17
+#define TAG_MISC 18
+#define TAG_DCACHE0 20
+#define TAG_DCACHE1 21
+#define TAG_DCACHE2 22
+#define TAG_DCACHE3 23
+#define TAG_FENCE 24
+
+
+static INLINE void
+wait_on_mask(unsigned tagMask)
+{
+ mfc_write_tag_mask( tagMask );
+ /* wait for completion of _any_ DMAs specified by tagMask */
+ mfc_read_tag_status_any();
+}
+
+
+static INLINE void
+wait_on_mask_all(unsigned tagMask)
+{
+ mfc_write_tag_mask( tagMask );
+ /* wait for completion of _any_ DMAs specified by tagMask */
+ mfc_read_tag_status_all();
+}
+
+
+
+
+
+static INLINE void
+memset16(ushort *d, ushort value, uint count)
+{
+ uint i;
+ for (i = 0; i < count; i++)
+ d[i] = value;
+}
+
+
+static INLINE void
+memset32(uint *d, uint value, uint count)
+{
+ uint i;
+ for (i = 0; i < count; i++)
+ d[i] = value;
+}
+
+
+#endif /* SPU_MAIN_H */
diff --git a/src/gallium/drivers/cell/spu/spu_per_fragment_op.c b/src/gallium/drivers/cell/spu/spu_per_fragment_op.c
new file mode 100644
index 0000000000..eba9f95cf1
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_per_fragment_op.c
@@ -0,0 +1,631 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \author Brian Paul
+ */
+
+
+#include <transpose_matrix4x4.h>
+#include "pipe/p_format.h"
+#include "spu_main.h"
+#include "spu_colorpack.h"
+#include "spu_per_fragment_op.h"
+
+
+#define LINEAR_QUAD_LAYOUT 1
+
+
+static INLINE vector float
+spu_min(vector float a, vector float b)
+{
+ vector unsigned int m;
+ m = spu_cmpgt(a, b); /* m = a > b ? ~0 : 0 */
+ return spu_sel(a, b, m);
+}
+
+
+static INLINE vector float
+spu_max(vector float a, vector float b)
+{
+ vector unsigned int m;
+ m = spu_cmpgt(a, b); /* m = a > b ? ~0 : 0 */
+ return spu_sel(b, a, m);
+}
+
+
+/**
+ * Called by rasterizer for each quad after the shader has run. Do
+ * all the per-fragment operations including alpha test, z test,
+ * stencil test, blend, colormask and logicops. This is a
+ * fallback/debug function. In reality we'll use a generated function
+ * produced by the PPU. But this function is useful for
+ * debug/validation.
+ */
+void
+spu_fallback_fragment_ops(uint x, uint y,
+ tile_t *colorTile,
+ tile_t *depthStencilTile,
+ vector float fragZ,
+ vector float fragR,
+ vector float fragG,
+ vector float fragB,
+ vector float fragA,
+ vector unsigned int mask)
+{
+ vector float frag_aos[4];
+ unsigned int fbc0, fbc1, fbc2, fbc3 ; /* framebuffer/tile colors */
+ unsigned int fragc0, fragc1, fragc2, fragc3; /* fragment colors */
+
+ /*
+ * Do alpha test
+ */
+ if (spu.depth_stencil_alpha.alpha.enabled) {
+ vector float ref = spu_splats(spu.depth_stencil_alpha.alpha.ref_value);
+ vector unsigned int amask;
+
+ switch (spu.depth_stencil_alpha.alpha.func) {
+ case PIPE_FUNC_LESS:
+ amask = spu_cmpgt(ref, fragA); /* mask = (fragA < ref) */
+ break;
+ case PIPE_FUNC_GREATER:
+ amask = spu_cmpgt(fragA, ref); /* mask = (fragA > ref) */
+ break;
+ case PIPE_FUNC_GEQUAL:
+ amask = spu_cmpgt(ref, fragA);
+ amask = spu_nor(amask, amask);
+ break;
+ case PIPE_FUNC_LEQUAL:
+ amask = spu_cmpgt(fragA, ref);
+ amask = spu_nor(amask, amask);
+ break;
+ case PIPE_FUNC_EQUAL:
+ amask = spu_cmpeq(ref, fragA);
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ amask = spu_cmpeq(ref, fragA);
+ amask = spu_nor(amask, amask);
+ break;
+ case PIPE_FUNC_ALWAYS:
+ amask = spu_splats(0xffffffffU);
+ break;
+ case PIPE_FUNC_NEVER:
+ amask = spu_splats( 0x0U);
+ break;
+ default:
+ ;
+ }
+
+ mask = spu_and(mask, amask);
+ }
+
+
+ /*
+ * Z and/or stencil testing...
+ */
+ if (spu.depth_stencil_alpha.depth.enabled ||
+ spu.depth_stencil_alpha.stencil[0].enabled) {
+
+ /* get four Z/Stencil values from tile */
+ vector unsigned int mask24 = spu_splats((unsigned int)0x00ffffffU);
+ vector unsigned int ifbZS = depthStencilTile->ui4[y/2][x/2];
+ vector unsigned int ifbZ = spu_and(ifbZS, mask24);
+ vector unsigned int ifbS = spu_andc(ifbZS, mask24);
+
+ if (spu.depth_stencil_alpha.stencil[0].enabled) {
+ /* do stencil test */
+ ASSERT(spu.fb.depth_format == PIPE_FORMAT_S8Z24_UNORM);
+
+ }
+ else if (spu.depth_stencil_alpha.depth.enabled) {
+ /* do depth test */
+
+ ASSERT(spu.fb.depth_format == PIPE_FORMAT_S8Z24_UNORM ||
+ spu.fb.depth_format == PIPE_FORMAT_X8Z24_UNORM);
+
+ vector unsigned int ifragZ;
+ vector unsigned int zmask;
+
+ /* convert four fragZ from float to uint */
+ fragZ = spu_mul(fragZ, spu_splats((float) 0xffffff));
+ ifragZ = spu_convtu(fragZ, 0);
+
+ /* do depth comparison, setting zmask with results */
+ switch (spu.depth_stencil_alpha.depth.func) {
+ case PIPE_FUNC_LESS:
+ zmask = spu_cmpgt(ifbZ, ifragZ); /* mask = (ifragZ < ifbZ) */
+ break;
+ case PIPE_FUNC_GREATER:
+ zmask = spu_cmpgt(ifragZ, ifbZ); /* mask = (ifbZ > ifragZ) */
+ break;
+ case PIPE_FUNC_GEQUAL:
+ zmask = spu_cmpgt(ifbZ, ifragZ);
+ zmask = spu_nor(zmask, zmask);
+ break;
+ case PIPE_FUNC_LEQUAL:
+ zmask = spu_cmpgt(ifragZ, ifbZ);
+ zmask = spu_nor(zmask, zmask);
+ break;
+ case PIPE_FUNC_EQUAL:
+ zmask = spu_cmpeq(ifbZ, ifragZ);
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ zmask = spu_cmpeq(ifbZ, ifragZ);
+ zmask = spu_nor(zmask, zmask);
+ break;
+ case PIPE_FUNC_ALWAYS:
+ zmask = spu_splats(0xffffffffU);
+ break;
+ case PIPE_FUNC_NEVER:
+ zmask = spu_splats( 0x0U);
+ break;
+ default:
+ ;
+ }
+
+ mask = spu_and(mask, zmask);
+
+ /* merge framebuffer Z and fragment Z according to the mask */
+ ifbZ = spu_or(spu_and(ifragZ, mask),
+ spu_andc(ifbZ, mask));
+ }
+
+ if (spu_extract(spu_orx(mask), 0)) {
+ /* put new fragment Z/Stencil values back into Z/Stencil tile */
+ depthStencilTile->ui4[y/2][x/2] = spu_or(ifbZ, ifbS);
+
+ spu.cur_ztile_status = TILE_STATUS_DIRTY;
+ }
+ }
+
+
+ /*
+ * If we'll need the current framebuffer/tile colors for blending
+ * or logicop or colormask, fetch them now.
+ */
+ if (spu.blend.blend_enable ||
+ spu.blend.logicop_enable ||
+ spu.blend.colormask != 0xf) {
+
+#if LINEAR_QUAD_LAYOUT /* See comments/diagram below */
+ fbc0 = colorTile->ui[y][x*2+0];
+ fbc1 = colorTile->ui[y][x*2+1];
+ fbc2 = colorTile->ui[y][x*2+2];
+ fbc3 = colorTile->ui[y][x*2+3];
+#else
+ fbc0 = colorTile->ui[y+0][x+0];
+ fbc1 = colorTile->ui[y+0][x+1];
+ fbc2 = colorTile->ui[y+1][x+0];
+ fbc3 = colorTile->ui[y+1][x+1];
+#endif
+ }
+
+
+ /*
+ * Do blending
+ */
+ if (spu.blend.blend_enable) {
+ /* blending terms, misc regs */
+ vector float term1r, term1g, term1b, term1a;
+ vector float term2r, term2g, term2b, term2a;
+ vector float one, tmp;
+
+ vector float fbRGBA[4]; /* current framebuffer colors */
+
+ /* convert framebuffer colors from packed int to vector float */
+ {
+ vector float temp[4]; /* float colors in AOS form */
+ switch (spu.fb.color_format) {
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ temp[0] = spu_unpack_B8G8R8A8(fbc0);
+ temp[1] = spu_unpack_B8G8R8A8(fbc1);
+ temp[2] = spu_unpack_B8G8R8A8(fbc2);
+ temp[3] = spu_unpack_B8G8R8A8(fbc3);
+ break;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ temp[0] = spu_unpack_A8R8G8B8(fbc0);
+ temp[1] = spu_unpack_A8R8G8B8(fbc1);
+ temp[2] = spu_unpack_A8R8G8B8(fbc2);
+ temp[3] = spu_unpack_A8R8G8B8(fbc3);
+ break;
+ default:
+ ASSERT(0);
+ }
+ _transpose_matrix4x4(fbRGBA, temp); /* fbRGBA = transpose(temp) */
+ }
+
+ /*
+ * Compute Src RGB terms (fragment color * factor)
+ */
+ switch (spu.blend.rgb_src_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ term1r = fragR;
+ term1g = fragG;
+ term1b = fragB;
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ term1r =
+ term1g =
+ term1b = spu_splats(0.0f);
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ term1r = spu_mul(fragR, fragR);
+ term1g = spu_mul(fragG, fragG);
+ term1b = spu_mul(fragB, fragB);
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ term1r = spu_mul(fragR, fragA);
+ term1g = spu_mul(fragG, fragA);
+ term1b = spu_mul(fragB, fragA);
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ term1r = spu_mul(fragR, fbRGBA[0]);
+ term1g = spu_mul(fragG, fbRGBA[1]);
+ term1b = spu_mul(fragB, fbRGBA[1]);
+ break;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ term1r = spu_mul(fragR, fbRGBA[3]);
+ term1g = spu_mul(fragG, fbRGBA[3]);
+ term1b = spu_mul(fragB, fbRGBA[3]);
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ term1r = spu_mul(fragR, spu_splats(spu.blend_color.color[0]));
+ term1g = spu_mul(fragG, spu_splats(spu.blend_color.color[1]));
+ term1b = spu_mul(fragB, spu_splats(spu.blend_color.color[2]));
+ break;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ term1r = spu_mul(fragR, spu_splats(spu.blend_color.color[3]));
+ term1g = spu_mul(fragG, spu_splats(spu.blend_color.color[3]));
+ term1b = spu_mul(fragB, spu_splats(spu.blend_color.color[3]));
+ break;
+ /* XXX more cases */
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Compute Src Alpha term (fragment alpha * factor)
+ */
+ switch (spu.blend.alpha_src_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ term1a = fragA;
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ term1a = spu_splats(0.0f);
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ term1a = spu_mul(fragA, fragA);
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ term1a = spu_mul(fragA, fbRGBA[3]);
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ term1a = spu_mul(fragR, spu_splats(spu.blend_color.color[3]));
+ break;
+ /* XXX more cases */
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Compute Dest RGB terms (framebuffer color * factor)
+ */
+ switch (spu.blend.rgb_dst_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ term2r = fbRGBA[0];
+ term2g = fbRGBA[1];
+ term2b = fbRGBA[2];
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ term2r =
+ term2g =
+ term2b = spu_splats(0.0f);
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ term2r = spu_mul(fbRGBA[0], fragR);
+ term2g = spu_mul(fbRGBA[1], fragG);
+ term2b = spu_mul(fbRGBA[2], fragB);
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ term2r = spu_mul(fbRGBA[0], fragA);
+ term2g = spu_mul(fbRGBA[1], fragA);
+ term2b = spu_mul(fbRGBA[2], fragA);
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ one = spu_splats(1.0f);
+ tmp = spu_sub(one, fragA);
+ term2r = spu_mul(fbRGBA[0], tmp);
+ term2g = spu_mul(fbRGBA[1], tmp);
+ term2b = spu_mul(fbRGBA[2], tmp);
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ term2r = spu_mul(fbRGBA[0], fbRGBA[0]);
+ term2g = spu_mul(fbRGBA[1], fbRGBA[1]);
+ term2b = spu_mul(fbRGBA[2], fbRGBA[2]);
+ break;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ term2r = spu_mul(fbRGBA[0], fbRGBA[3]);
+ term2g = spu_mul(fbRGBA[1], fbRGBA[3]);
+ term2b = spu_mul(fbRGBA[2], fbRGBA[3]);
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ term2r = spu_mul(fbRGBA[0], spu_splats(spu.blend_color.color[0]));
+ term2g = spu_mul(fbRGBA[1], spu_splats(spu.blend_color.color[1]));
+ term2b = spu_mul(fbRGBA[2], spu_splats(spu.blend_color.color[2]));
+ break;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ term2r = spu_mul(fbRGBA[0], spu_splats(spu.blend_color.color[3]));
+ term2g = spu_mul(fbRGBA[1], spu_splats(spu.blend_color.color[3]));
+ term2b = spu_mul(fbRGBA[2], spu_splats(spu.blend_color.color[3]));
+ break;
+ /* XXX more cases */
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Compute Dest Alpha term (framebuffer alpha * factor)
+ */
+ switch (spu.blend.alpha_dst_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ term2a = fbRGBA[3];
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ term2a = spu_splats(0.0f);
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ term2a = spu_mul(fbRGBA[3], fragA);
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ one = spu_splats(1.0f);
+ tmp = spu_sub(one, fragA);
+ term2a = spu_mul(fbRGBA[3], tmp);
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ term2a = spu_mul(fbRGBA[3], fbRGBA[3]);
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ term2a = spu_mul(fbRGBA[3], spu_splats(spu.blend_color.color[3]));
+ break;
+ /* XXX more cases */
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Combine Src/Dest RGB terms
+ */
+ switch (spu.blend.rgb_func) {
+ case PIPE_BLEND_ADD:
+ fragR = spu_add(term1r, term2r);
+ fragG = spu_add(term1g, term2g);
+ fragB = spu_add(term1b, term2b);
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ fragR = spu_sub(term1r, term2r);
+ fragG = spu_sub(term1g, term2g);
+ fragB = spu_sub(term1b, term2b);
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ fragR = spu_sub(term2r, term1r);
+ fragG = spu_sub(term2g, term1g);
+ fragB = spu_sub(term2b, term1b);
+ break;
+ case PIPE_BLEND_MIN:
+ fragR = spu_min(term1r, term2r);
+ fragG = spu_min(term1g, term2g);
+ fragB = spu_min(term1b, term2b);
+ break;
+ case PIPE_BLEND_MAX:
+ fragR = spu_max(term1r, term2r);
+ fragG = spu_max(term1g, term2g);
+ fragB = spu_max(term1b, term2b);
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Combine Src/Dest A term
+ */
+ switch (spu.blend.alpha_func) {
+ case PIPE_BLEND_ADD:
+ fragA = spu_add(term1a, term2a);
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ fragA = spu_sub(term1a, term2a);
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ fragA = spu_sub(term2a, term1a);
+ break;
+ case PIPE_BLEND_MIN:
+ fragA = spu_min(term1a, term2a);
+ break;
+ case PIPE_BLEND_MAX:
+ fragA = spu_max(term1a, term2a);
+ break;
+ default:
+ ASSERT(0);
+ }
+ }
+
+
+ /*
+ * Convert RRRR,GGGG,BBBB,AAAA to RGBA,RGBA,RGBA,RGBA.
+ */
+#if 0
+ /* original code */
+ {
+ vector float frag_soa[4];
+ frag_soa[0] = fragR;
+ frag_soa[1] = fragG;
+ frag_soa[2] = fragB;
+ frag_soa[3] = fragA;
+ _transpose_matrix4x4(frag_aos, frag_soa);
+ }
+#else
+ /* short-cut relying on function parameter layout: */
+ _transpose_matrix4x4(frag_aos, &fragR);
+ (void) fragG;
+ (void) fragB;
+#endif
+
+ /*
+ * Pack fragment float colors into 32-bit RGBA words.
+ */
+ switch (spu.fb.color_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ fragc0 = spu_pack_A8R8G8B8(frag_aos[0]);
+ fragc1 = spu_pack_A8R8G8B8(frag_aos[1]);
+ fragc2 = spu_pack_A8R8G8B8(frag_aos[2]);
+ fragc3 = spu_pack_A8R8G8B8(frag_aos[3]);
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ fragc0 = spu_pack_B8G8R8A8(frag_aos[0]);
+ fragc1 = spu_pack_B8G8R8A8(frag_aos[1]);
+ fragc2 = spu_pack_B8G8R8A8(frag_aos[2]);
+ fragc3 = spu_pack_B8G8R8A8(frag_aos[3]);
+ break;
+ default:
+ fprintf(stderr, "SPU: Bad pixel format in spu_default_fragment_ops\n");
+ ASSERT(0);
+ }
+
+
+ /*
+ * Do color masking
+ */
+ if (spu.blend.colormask != 0xf) {
+ uint cmask = 0x0; /* each byte corresponds to a color channel */
+
+ /* Form bitmask depending on color buffer format and colormask bits */
+ switch (spu.fb.color_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ if (spu.blend.colormask & PIPE_MASK_R)
+ cmask |= 0x00ff0000; /* red */
+ if (spu.blend.colormask & PIPE_MASK_G)
+ cmask |= 0x0000ff00; /* green */
+ if (spu.blend.colormask & PIPE_MASK_B)
+ cmask |= 0x000000ff; /* blue */
+ if (spu.blend.colormask & PIPE_MASK_A)
+ cmask |= 0xff000000; /* alpha */
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ if (spu.blend.colormask & PIPE_MASK_R)
+ cmask |= 0x0000ff00; /* red */
+ if (spu.blend.colormask & PIPE_MASK_G)
+ cmask |= 0x00ff0000; /* green */
+ if (spu.blend.colormask & PIPE_MASK_B)
+ cmask |= 0xff000000; /* blue */
+ if (spu.blend.colormask & PIPE_MASK_A)
+ cmask |= 0x000000ff; /* alpha */
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ /*
+ * Apply color mask to the 32-bit packed colors.
+ * if (cmask[i])
+ * frag color[i] = frag color[i];
+ * else
+ * frag color[i] = framebuffer color[i];
+ */
+ fragc0 = (fragc0 & cmask) | (fbc0 & ~cmask);
+ fragc1 = (fragc1 & cmask) | (fbc1 & ~cmask);
+ fragc2 = (fragc2 & cmask) | (fbc2 & ~cmask);
+ fragc3 = (fragc3 & cmask) | (fbc3 & ~cmask);
+ }
+
+
+ /*
+ * Do logic ops
+ */
+ if (spu.blend.logicop_enable) {
+ /* XXX to do */
+ /* apply logicop to 32-bit packed colors (fragcx and fbcx) */
+ }
+
+
+ /*
+ * If mask is non-zero, mark tile as dirty.
+ */
+ if (spu_extract(spu_orx(mask), 0)) {
+ spu.cur_ctile_status = TILE_STATUS_DIRTY;
+ }
+ else {
+ /* write no fragments */
+ return;
+ }
+
+
+ /*
+ * Write new fragment/quad colors to the framebuffer/tile.
+ * Only write pixels where the corresponding mask word is set.
+ */
+#if LINEAR_QUAD_LAYOUT
+ /*
+ * Quad layout:
+ * +--+--+--+--+
+ * |p0|p1|p2|p3|...
+ * +--+--+--+--+
+ */
+ if (spu_extract(mask, 0))
+ colorTile->ui[y][x*2] = fragc0;
+ if (spu_extract(mask, 1))
+ colorTile->ui[y][x*2+1] = fragc1;
+ if (spu_extract(mask, 2))
+ colorTile->ui[y][x*2+2] = fragc2;
+ if (spu_extract(mask, 3))
+ colorTile->ui[y][x*2+3] = fragc3;
+#else
+ /*
+ * Quad layout:
+ * +--+--+
+ * |p0|p1|...
+ * +--+--+
+ * |p2|p3|...
+ * +--+--+
+ */
+ if (spu_extract(mask, 0))
+ colorTile->ui[y+0][x+0] = fragc0;
+ if (spu_extract(mask, 1))
+ colorTile->ui[y+0][x+1] = fragc1;
+ if (spu_extract(mask, 2))
+ colorTile->ui[y+1][x+0] = fragc2;
+ if (spu_extract(mask, 3))
+ colorTile->ui[y+1][x+1] = fragc3;
+#endif
+}
diff --git a/src/gallium/drivers/cell/spu/spu_per_fragment_op.h b/src/gallium/drivers/cell/spu/spu_per_fragment_op.h
new file mode 100644
index 0000000000..f817abf046
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_per_fragment_op.h
@@ -0,0 +1,44 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SPU_PER_FRAGMENT_OP
+#define SPU_PER_FRAGMENT_OP
+
+
+extern void
+spu_fallback_fragment_ops(uint x, uint y,
+ tile_t *colorTile,
+ tile_t *depthStencilTile,
+ vector float fragZ,
+ vector float fragRed,
+ vector float fragGreen,
+ vector float fragBlue,
+ vector float fragAlpha,
+ vector unsigned int mask);
+
+
+#endif /* SPU_PER_FRAGMENT_OP */
diff --git a/src/gallium/drivers/cell/spu/spu_render.c b/src/gallium/drivers/cell/spu/spu_render.c
new file mode 100644
index 0000000000..5ffb7073ab
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_render.c
@@ -0,0 +1,356 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <stdio.h>
+#include <libmisc.h>
+#include <spu_mfcio.h>
+
+#include "spu_main.h"
+#include "spu_render.h"
+#include "spu_shuffle.h"
+#include "spu_tri.h"
+#include "spu_tile.h"
+#include "cell/common.h"
+#include "util/u_memory.h"
+
+
+/**
+ * Given a rendering command's bounding box (in pixels) compute the
+ * location of the corresponding screen tile bounding box.
+ */
+static INLINE void
+tile_bounding_box(const struct cell_command_render *render,
+ uint *txmin, uint *tymin,
+ uint *box_num_tiles, uint *box_width_tiles)
+{
+#if 0
+ /* Debug: full-window bounding box */
+ uint txmax = spu.fb.width_tiles - 1;
+ uint tymax = spu.fb.height_tiles - 1;
+ *txmin = 0;
+ *tymin = 0;
+ *box_num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
+ *box_width_tiles = spu.fb.width_tiles;
+ (void) render;
+ (void) txmax;
+ (void) tymax;
+#else
+ uint txmax, tymax, box_height_tiles;
+
+ *txmin = (uint) render->xmin / TILE_SIZE;
+ *tymin = (uint) render->ymin / TILE_SIZE;
+ txmax = (uint) render->xmax / TILE_SIZE;
+ tymax = (uint) render->ymax / TILE_SIZE;
+ if (txmax >= spu.fb.width_tiles)
+ txmax = spu.fb.width_tiles-1;
+ if (tymax >= spu.fb.height_tiles)
+ tymax = spu.fb.height_tiles-1;
+ *box_width_tiles = txmax - *txmin + 1;
+ box_height_tiles = tymax - *tymin + 1;
+ *box_num_tiles = *box_width_tiles * box_height_tiles;
+#endif
+#if 0
+ printf("SPU %u: bounds: %g, %g ... %g, %g\n", spu.init.id,
+ render->xmin, render->ymin, render->xmax, render->ymax);
+ printf("SPU %u: tiles: %u, %u .. %u, %u\n",
+ spu.init.id, *txmin, *tymin, txmax, tymax);
+ ASSERT(render->xmin <= render->xmax);
+ ASSERT(render->ymin <= render->ymax);
+#endif
+}
+
+
+/** Check if the tile at (tx,ty) belongs to this SPU */
+static INLINE boolean
+my_tile(uint tx, uint ty)
+{
+ return (spu.fb.width_tiles * ty + tx) % spu.init.num_spus == spu.init.id;
+}
+
+
+/**
+ * Start fetching non-clear color/Z tiles from main memory
+ */
+static INLINE void
+get_cz_tiles(uint tx, uint ty)
+{
+ if (spu.read_depth_stencil) {
+ if (spu.cur_ztile_status != TILE_STATUS_CLEAR) {
+ //printf("SPU %u: getting Z tile %u, %u\n", spu.init.id, tx, ty);
+ get_tile(tx, ty, &spu.ztile, TAG_READ_TILE_Z, 1);
+ spu.cur_ztile_status = TILE_STATUS_GETTING;
+ }
+ }
+
+ if (spu.cur_ctile_status != TILE_STATUS_CLEAR) {
+ //printf("SPU %u: getting C tile %u, %u\n", spu.init.id, tx, ty);
+ get_tile(tx, ty, &spu.ctile, TAG_READ_TILE_COLOR, 0);
+ spu.cur_ctile_status = TILE_STATUS_GETTING;
+ }
+}
+
+
+/**
+ * Start putting dirty color/Z tiles back to main memory
+ */
+static INLINE void
+put_cz_tiles(uint tx, uint ty)
+{
+ if (spu.cur_ztile_status == TILE_STATUS_DIRTY) {
+ /* tile was modified and needs to be written back */
+ //printf("SPU %u: put dirty Z tile %u, %u\n", spu.init.id, tx, ty);
+ put_tile(tx, ty, &spu.ztile, TAG_WRITE_TILE_Z, 1);
+ spu.cur_ztile_status = TILE_STATUS_DEFINED;
+ }
+ else if (spu.cur_ztile_status == TILE_STATUS_GETTING) {
+ /* tile was never used */
+ spu.cur_ztile_status = TILE_STATUS_DEFINED;
+ //printf("SPU %u: put getting Z tile %u, %u\n", spu.init.id, tx, ty);
+ }
+
+ if (spu.cur_ctile_status == TILE_STATUS_DIRTY) {
+ /* tile was modified and needs to be written back */
+ //printf("SPU %u: put dirty C tile %u, %u\n", spu.init.id, tx, ty);
+ put_tile(tx, ty, &spu.ctile, TAG_WRITE_TILE_COLOR, 0);
+ spu.cur_ctile_status = TILE_STATUS_DEFINED;
+ }
+ else if (spu.cur_ctile_status == TILE_STATUS_GETTING) {
+ /* tile was never used */
+ spu.cur_ctile_status = TILE_STATUS_DEFINED;
+ //printf("SPU %u: put getting C tile %u, %u\n", spu.init.id, tx, ty);
+ }
+}
+
+
+/**
+ * Wait for 'put' of color/z tiles to complete.
+ */
+static INLINE void
+wait_put_cz_tiles(void)
+{
+ wait_on_mask(1 << TAG_WRITE_TILE_COLOR);
+ if (spu.read_depth_stencil) {
+ wait_on_mask(1 << TAG_WRITE_TILE_Z);
+ }
+}
+
+
+/**
+ * Render primitives
+ * \param pos_incr returns value indicating how may words to skip after
+ * this command in the batch buffer
+ */
+void
+cmd_render(const struct cell_command_render *render, uint *pos_incr)
+{
+ /* we'll DMA into these buffers */
+ ubyte vertex_data[CELL_BUFFER_SIZE] ALIGN16_ATTRIB;
+ const uint vertex_size = render->vertex_size; /* in bytes */
+ /*const*/ uint total_vertex_bytes = render->num_verts * vertex_size;
+ uint index_bytes;
+ const ubyte *vertices;
+ const ushort *indexes;
+ uint i, j;
+ uint num_tiles;
+
+ D_PRINTF(CELL_DEBUG_CMD,
+ "RENDER prim=%u num_vert=%u num_ind=%u inline_vert=%u\n",
+ render->prim_type,
+ render->num_verts,
+ render->num_indexes,
+ render->inline_verts);
+
+ ASSERT(sizeof(*render) % 4 == 0);
+ ASSERT(total_vertex_bytes % 16 == 0);
+ ASSERT(render->prim_type == PIPE_PRIM_TRIANGLES);
+ ASSERT(render->num_indexes % 3 == 0);
+
+
+ /* indexes are right after the render command in the batch buffer */
+ indexes = (const ushort *) (render + 1);
+ index_bytes = ROUNDUP8(render->num_indexes * 2);
+ *pos_incr = index_bytes / 8 + sizeof(*render) / 8;
+
+
+ if (render->inline_verts) {
+ /* Vertices are after indexes in batch buffer at next 16-byte addr */
+ vertices = (const ubyte *) render + (*pos_incr * 8);
+ vertices = (const ubyte *) align_pointer((void *) vertices, 16);
+ ASSERT_ALIGN16(vertices);
+ *pos_incr = ((vertices + total_vertex_bytes) - (ubyte *) render) / 8;
+ }
+ else {
+ /* Begin DMA fetch of vertex buffer */
+ ubyte *src = spu.init.buffers[render->vertex_buf];
+ ubyte *dest = vertex_data;
+
+ /* skip vertex data we won't use */
+#if 01
+ src += render->min_index * vertex_size;
+ dest += render->min_index * vertex_size;
+ total_vertex_bytes -= render->min_index * vertex_size;
+#endif
+ ASSERT(total_vertex_bytes % 16 == 0);
+ ASSERT_ALIGN16(dest);
+ ASSERT_ALIGN16(src);
+
+ mfc_get(dest, /* in vertex_data[] array */
+ (unsigned int) src, /* src in main memory */
+ total_vertex_bytes, /* size */
+ TAG_VERTEX_BUFFER,
+ 0, /* tid */
+ 0 /* rid */);
+
+ vertices = vertex_data;
+
+ wait_on_mask(1 << TAG_VERTEX_BUFFER);
+ }
+
+
+ /**
+ ** find tiles which intersect the prim bounding box
+ **/
+ uint txmin, tymin, box_width_tiles, box_num_tiles;
+ tile_bounding_box(render, &txmin, &tymin,
+ &box_num_tiles, &box_width_tiles);
+
+
+ /* make sure any pending clears have completed */
+ wait_on_mask(1 << TAG_SURFACE_CLEAR); /* XXX temporary */
+
+
+ num_tiles = 0;
+
+ /**
+ ** loop over tiles, rendering tris
+ **/
+ for (i = 0; i < box_num_tiles; i++) {
+ const uint tx = txmin + i % box_width_tiles;
+ const uint ty = tymin + i / box_width_tiles;
+
+ ASSERT(tx < spu.fb.width_tiles);
+ ASSERT(ty < spu.fb.height_tiles);
+
+ if (!my_tile(tx, ty))
+ continue;
+
+ num_tiles++;
+
+ spu.cur_ctile_status = spu.ctile_status[ty][tx];
+ spu.cur_ztile_status = spu.ztile_status[ty][tx];
+
+ get_cz_tiles(tx, ty);
+
+ uint drawn = 0;
+
+ const qword vertex_sizes = (qword)spu_splats(vertex_size);
+ const qword verticess = (qword)spu_splats((uint)vertices);
+
+ ASSERT_ALIGN16(&indexes[0]);
+
+ const uint num_indexes = render->num_indexes;
+
+ /* loop over tris
+ * &indexes[0] will be 16 byte aligned. This loop is heavily unrolled
+ * avoiding variable rotates when extracting vertex indices.
+ */
+ for (j = 0; j < num_indexes; j += 24) {
+ /* Load three vectors, containing 24 ushort indices */
+ const qword* lower_qword = (qword*)&indexes[j];
+ const qword indices0 = lower_qword[0];
+ const qword indices1 = lower_qword[1];
+ const qword indices2 = lower_qword[2];
+
+ /* stores three indices for each tri n in slots 0, 1 and 2 of vsn */
+ /* Straightforward rotates for these */
+ qword vs0 = indices0;
+ qword vs1 = si_shlqbyi(indices0, 6);
+ qword vs3 = si_shlqbyi(indices1, 2);
+ qword vs4 = si_shlqbyi(indices1, 8);
+ qword vs6 = si_shlqbyi(indices2, 4);
+ qword vs7 = si_shlqbyi(indices2, 10);
+
+ /* For tri 2 and 5, the three indices are split across two machine
+ * words - rotate and combine */
+ const qword tmp2a = si_shlqbyi(indices0, 12);
+ const qword tmp2b = si_rotqmbyi(indices1, 12|16);
+ qword vs2 = si_selb(tmp2a, tmp2b, si_fsmh(si_from_uint(0x20)));
+
+ const qword tmp5a = si_shlqbyi(indices1, 14);
+ const qword tmp5b = si_rotqmbyi(indices2, 14|16);
+ qword vs5 = si_selb(tmp5a, tmp5b, si_fsmh(si_from_uint(0x60)));
+
+ /* unpack indices from halfword slots to word slots */
+ vs0 = si_shufb(vs0, vs0, SHUFB8(0,A,0,B,0,C,0,0));
+ vs1 = si_shufb(vs1, vs1, SHUFB8(0,A,0,B,0,C,0,0));
+ vs2 = si_shufb(vs2, vs2, SHUFB8(0,A,0,B,0,C,0,0));
+ vs3 = si_shufb(vs3, vs3, SHUFB8(0,A,0,B,0,C,0,0));
+ vs4 = si_shufb(vs4, vs4, SHUFB8(0,A,0,B,0,C,0,0));
+ vs5 = si_shufb(vs5, vs5, SHUFB8(0,A,0,B,0,C,0,0));
+ vs6 = si_shufb(vs6, vs6, SHUFB8(0,A,0,B,0,C,0,0));
+ vs7 = si_shufb(vs7, vs7, SHUFB8(0,A,0,B,0,C,0,0));
+
+ /* Calculate address of vertex in vertices[] */
+ vs0 = si_mpya(vs0, vertex_sizes, verticess);
+ vs1 = si_mpya(vs1, vertex_sizes, verticess);
+ vs2 = si_mpya(vs2, vertex_sizes, verticess);
+ vs3 = si_mpya(vs3, vertex_sizes, verticess);
+ vs4 = si_mpya(vs4, vertex_sizes, verticess);
+ vs5 = si_mpya(vs5, vertex_sizes, verticess);
+ vs6 = si_mpya(vs6, vertex_sizes, verticess);
+ vs7 = si_mpya(vs7, vertex_sizes, verticess);
+
+ /* Select the appropriate call based on the number of vertices
+ * remaining */
+ switch(num_indexes - j) {
+ default: drawn += tri_draw(vs7, tx, ty);
+ case 21: drawn += tri_draw(vs6, tx, ty);
+ case 18: drawn += tri_draw(vs5, tx, ty);
+ case 15: drawn += tri_draw(vs4, tx, ty);
+ case 12: drawn += tri_draw(vs3, tx, ty);
+ case 9: drawn += tri_draw(vs2, tx, ty);
+ case 6: drawn += tri_draw(vs1, tx, ty);
+ case 3: drawn += tri_draw(vs0, tx, ty);
+ }
+ }
+
+ //printf("SPU %u: drew %u of %u\n", spu.init.id, drawn, render->num_indexes/3);
+
+ /* write color/z tiles back to main framebuffer, if dirtied */
+ put_cz_tiles(tx, ty);
+
+ wait_put_cz_tiles(); /* XXX seems unnecessary... */
+
+ spu.ctile_status[ty][tx] = spu.cur_ctile_status;
+ spu.ztile_status[ty][tx] = spu.cur_ztile_status;
+ }
+
+ D_PRINTF(CELL_DEBUG_CMD,
+ "RENDER done (%u tiles hit)\n",
+ num_tiles);
+}
diff --git a/src/gallium/drivers/cell/spu/spu_render.h b/src/gallium/drivers/cell/spu/spu_render.h
new file mode 100644
index 0000000000..493434f087
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_render.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef SPU_RENDER_H
+#define SPU_RENDER_H
+
+#include "cell/common.h"
+
+extern void
+cmd_render(const struct cell_command_render *render, uint *pos_incr);
+
+#endif /* SPU_RENDER_H */
+
diff --git a/src/gallium/drivers/cell/spu/spu_shuffle.h b/src/gallium/drivers/cell/spu/spu_shuffle.h
new file mode 100644
index 0000000000..74f2a0b6d2
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_shuffle.h
@@ -0,0 +1,186 @@
+#ifndef SPU_SHUFFLE_H
+#define SPU_SHUFFLE_H
+
+/*
+ * Generate shuffle patterns with minimal fuss.
+ *
+ * Based on ideas from
+ * http://www.insomniacgames.com/tech/articles/0408/files/shuffles.pdf
+ *
+ * A-P indicates 0-15th position in first vector
+ * a-p indicates 0-15th position in second vector
+ *
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * |00|01|02|03|04|05|06|07|08|09|0a|0b|0c|0d|0e|0f|
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | A| B| C| D|
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | A| B| C| D| E| F| G| H|
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | A| B| C| D| E| F| G| H| I| J| K| L| M| N| O| P|
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *
+ * x or X indicates 0xff
+ * 8 indicates 0x80
+ * 0 indicates 0x00
+ *
+ * The macros SHUFFLE4() SHUFFLE8() and SHUFFLE16() provide a const vector
+ * unsigned char literal suitable for use with spu_shuffle().
+ *
+ * The macros SHUFB4() SHUFB8() and SHUFB16() provide a const qword vector
+ * literal suitable for use with si_shufb().
+ *
+ *
+ * For example :
+ * SHUFB4(A,A,A,A)
+ * expands to :
+ * ((const qword){0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3})
+ *
+ * SHUFFLE8(A,B,a,b,C,c,8,8)
+ * expands to :
+ * ((const vector unsigned char){0x00,0x01,0x02,0x03,0x10,0x11,0x12,0x13,
+ * 0x04,0x05,0x14,0x15,0xe0,0xe0,0xe0,0xe0})
+ *
+ */
+
+#include <spu_intrinsics.h>
+
+#define SHUFFLE_PATTERN_4_A__ 0x00, 0x01, 0x02, 0x03
+#define SHUFFLE_PATTERN_4_B__ 0x04, 0x05, 0x06, 0x07
+#define SHUFFLE_PATTERN_4_C__ 0x08, 0x09, 0x0a, 0x0b
+#define SHUFFLE_PATTERN_4_D__ 0x0c, 0x0d, 0x0e, 0x0f
+#define SHUFFLE_PATTERN_4_a__ 0x10, 0x11, 0x12, 0x13
+#define SHUFFLE_PATTERN_4_b__ 0x14, 0x15, 0x16, 0x17
+#define SHUFFLE_PATTERN_4_c__ 0x18, 0x19, 0x1a, 0x1b
+#define SHUFFLE_PATTERN_4_d__ 0x1c, 0x1d, 0x1e, 0x1f
+#define SHUFFLE_PATTERN_4_X__ 0xc0, 0xc0, 0xc0, 0xc0
+#define SHUFFLE_PATTERN_4_x__ 0xc0, 0xc0, 0xc0, 0xc0
+#define SHUFFLE_PATTERN_4_0__ 0x80, 0x80, 0x80, 0x80
+#define SHUFFLE_PATTERN_4_8__ 0xe0, 0xe0, 0xe0, 0xe0
+
+#define SHUFFLE_VECTOR_4__(A, B, C, D) \
+ SHUFFLE_PATTERN_4_##A##__, \
+ SHUFFLE_PATTERN_4_##B##__, \
+ SHUFFLE_PATTERN_4_##C##__, \
+ SHUFFLE_PATTERN_4_##D##__
+
+#define SHUFFLE4(A, B, C, D) \
+ ((const vector unsigned char){ \
+ SHUFFLE_VECTOR_4__(A, B, C, D) \
+ })
+
+#define SHUFB4(A, B, C, D) \
+ ((const qword){ \
+ SHUFFLE_VECTOR_4__(A, B, C, D) \
+ })
+
+
+#define SHUFFLE_PATTERN_8_A__ 0x00, 0x01
+#define SHUFFLE_PATTERN_8_B__ 0x02, 0x03
+#define SHUFFLE_PATTERN_8_C__ 0x04, 0x05
+#define SHUFFLE_PATTERN_8_D__ 0x06, 0x07
+#define SHUFFLE_PATTERN_8_E__ 0x08, 0x09
+#define SHUFFLE_PATTERN_8_F__ 0x0a, 0x0b
+#define SHUFFLE_PATTERN_8_G__ 0x0c, 0x0d
+#define SHUFFLE_PATTERN_8_H__ 0x0e, 0x0f
+#define SHUFFLE_PATTERN_8_a__ 0x10, 0x11
+#define SHUFFLE_PATTERN_8_b__ 0x12, 0x13
+#define SHUFFLE_PATTERN_8_c__ 0x14, 0x15
+#define SHUFFLE_PATTERN_8_d__ 0x16, 0x17
+#define SHUFFLE_PATTERN_8_e__ 0x18, 0x19
+#define SHUFFLE_PATTERN_8_f__ 0x1a, 0x1b
+#define SHUFFLE_PATTERN_8_g__ 0x1c, 0x1d
+#define SHUFFLE_PATTERN_8_h__ 0x1e, 0x1f
+#define SHUFFLE_PATTERN_8_X__ 0xc0, 0xc0
+#define SHUFFLE_PATTERN_8_x__ 0xc0, 0xc0
+#define SHUFFLE_PATTERN_8_0__ 0x80, 0x80
+#define SHUFFLE_PATTERN_8_8__ 0xe0, 0xe0
+
+
+#define SHUFFLE_VECTOR_8__(A, B, C, D, E, F, G, H) \
+ SHUFFLE_PATTERN_8_##A##__, \
+ SHUFFLE_PATTERN_8_##B##__, \
+ SHUFFLE_PATTERN_8_##C##__, \
+ SHUFFLE_PATTERN_8_##D##__, \
+ SHUFFLE_PATTERN_8_##E##__, \
+ SHUFFLE_PATTERN_8_##F##__, \
+ SHUFFLE_PATTERN_8_##G##__, \
+ SHUFFLE_PATTERN_8_##H##__
+
+#define SHUFFLE8(A, B, C, D, E, F, G, H) \
+ ((const vector unsigned char){ \
+ SHUFFLE_VECTOR_8__(A, B, C, D, E, F, G, H) \
+ })
+
+#define SHUFB8(A, B, C, D, E, F, G, H) \
+ ((const qword){ \
+ SHUFFLE_VECTOR_8__(A, B, C, D, E, F, G, H) \
+ })
+
+
+#define SHUFFLE_PATTERN_16_A__ 0x00
+#define SHUFFLE_PATTERN_16_B__ 0x01
+#define SHUFFLE_PATTERN_16_C__ 0x02
+#define SHUFFLE_PATTERN_16_D__ 0x03
+#define SHUFFLE_PATTERN_16_E__ 0x04
+#define SHUFFLE_PATTERN_16_F__ 0x05
+#define SHUFFLE_PATTERN_16_G__ 0x06
+#define SHUFFLE_PATTERN_16_H__ 0x07
+#define SHUFFLE_PATTERN_16_I__ 0x08
+#define SHUFFLE_PATTERN_16_J__ 0x09
+#define SHUFFLE_PATTERN_16_K__ 0x0a
+#define SHUFFLE_PATTERN_16_L__ 0x0b
+#define SHUFFLE_PATTERN_16_M__ 0x0c
+#define SHUFFLE_PATTERN_16_N__ 0x0d
+#define SHUFFLE_PATTERN_16_O__ 0x0e
+#define SHUFFLE_PATTERN_16_P__ 0x0f
+#define SHUFFLE_PATTERN_16_a__ 0x10
+#define SHUFFLE_PATTERN_16_b__ 0x11
+#define SHUFFLE_PATTERN_16_c__ 0x12
+#define SHUFFLE_PATTERN_16_d__ 0x13
+#define SHUFFLE_PATTERN_16_e__ 0x14
+#define SHUFFLE_PATTERN_16_f__ 0x15
+#define SHUFFLE_PATTERN_16_g__ 0x16
+#define SHUFFLE_PATTERN_16_h__ 0x17
+#define SHUFFLE_PATTERN_16_i__ 0x18
+#define SHUFFLE_PATTERN_16_j__ 0x19
+#define SHUFFLE_PATTERN_16_k__ 0x1a
+#define SHUFFLE_PATTERN_16_l__ 0x1b
+#define SHUFFLE_PATTERN_16_m__ 0x1c
+#define SHUFFLE_PATTERN_16_n__ 0x1d
+#define SHUFFLE_PATTERN_16_o__ 0x1e
+#define SHUFFLE_PATTERN_16_p__ 0x1f
+#define SHUFFLE_PATTERN_16_X__ 0xc0
+#define SHUFFLE_PATTERN_16_x__ 0xc0
+#define SHUFFLE_PATTERN_16_0__ 0x80
+#define SHUFFLE_PATTERN_16_8__ 0xe0
+
+#define SHUFFLE_VECTOR_16__(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
+ SHUFFLE_PATTERN_16_##A##__, \
+ SHUFFLE_PATTERN_16_##B##__, \
+ SHUFFLE_PATTERN_16_##C##__, \
+ SHUFFLE_PATTERN_16_##D##__, \
+ SHUFFLE_PATTERN_16_##E##__, \
+ SHUFFLE_PATTERN_16_##F##__, \
+ SHUFFLE_PATTERN_16_##G##__, \
+ SHUFFLE_PATTERN_16_##H##__, \
+ SHUFFLE_PATTERN_16_##I##__, \
+ SHUFFLE_PATTERN_16_##J##__, \
+ SHUFFLE_PATTERN_16_##K##__, \
+ SHUFFLE_PATTERN_16_##L##__, \
+ SHUFFLE_PATTERN_16_##M##__, \
+ SHUFFLE_PATTERN_16_##N##__, \
+ SHUFFLE_PATTERN_16_##O##__, \
+ SHUFFLE_PATTERN_16_##P##__
+
+#define SHUFFLE16(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
+ ((const vector unsigned char){ \
+ SHUFFLE_VECTOR_16__(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
+ })
+
+#define SHUFB16(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
+ ((const qword){ \
+ SHUFFLE_VECTOR_16__(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
+ })
+
+#endif
diff --git a/src/gallium/drivers/cell/spu/spu_texture.c b/src/gallium/drivers/cell/spu/spu_texture.c
new file mode 100644
index 0000000000..69784c8978
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_texture.c
@@ -0,0 +1,641 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <math.h>
+
+#include "pipe/p_compiler.h"
+#include "spu_main.h"
+#include "spu_texture.h"
+#include "spu_tile.h"
+#include "spu_colorpack.h"
+#include "spu_dcache.h"
+
+
+/**
+ * Mark all tex cache entries as invalid.
+ */
+void
+invalidate_tex_cache(void)
+{
+ uint lvl;
+ for (lvl = 0; lvl < CELL_MAX_TEXTURE_LEVELS; lvl++) {
+ uint unit = 0;
+ uint bytes = 4 * spu.texture[unit].level[lvl].width
+ * spu.texture[unit].level[lvl].height;
+
+ if (spu.texture[unit].target == PIPE_TEXTURE_CUBE)
+ bytes *= 6;
+ else if (spu.texture[unit].target == PIPE_TEXTURE_3D)
+ bytes *= spu.texture[unit].level[lvl].depth;
+
+ spu_dcache_mark_dirty((unsigned) spu.texture[unit].level[lvl].start, bytes);
+ }
+}
+
+
+/**
+ * Get four texels from locations (x[0], y[0]), (x[1], y[1]) ...
+ *
+ * NOTE: in the typical case of bilinear filtering, the four texels
+ * are in a 2x2 group so we could get by with just two dcache fetches
+ * (two side-by-side texels per fetch). But when bilinear filtering
+ * wraps around a texture edge, we'll probably need code like we have
+ * now.
+ * FURTHERMORE: since we're rasterizing a quad of 2x2 pixels at a time,
+ * it's quite likely that the four pixels in a quad will need some of the
+ * same texels. So look into doing texture fetches for four pixels at
+ * a time.
+ */
+static void
+get_four_texels(const struct spu_texture_level *tlevel, uint face,
+ vec_int4 x, vec_int4 y,
+ vec_uint4 *texels)
+{
+ unsigned texture_ea = (uintptr_t) tlevel->start;
+ const vec_int4 tile_x = spu_rlmask(x, -5); /* tile_x = x / 32 */
+ const vec_int4 tile_y = spu_rlmask(y, -5); /* tile_y = y / 32 */
+ const qword offset_x = si_andi((qword) x, 0x1f); /* offset_x = x & 0x1f */
+ const qword offset_y = si_andi((qword) y, 0x1f); /* offset_y = y & 0x1f */
+
+ const qword tiles_per_row = (qword) spu_splats(tlevel->tiles_per_row);
+ const qword tile_size = (qword) spu_splats((unsigned) sizeof(tile_t));
+
+ qword tile_offset = si_mpya((qword) tile_y, tiles_per_row, (qword) tile_x);
+ tile_offset = si_mpy((qword) tile_offset, tile_size);
+
+ qword texel_offset = si_a(si_mpyui(offset_y, 32), offset_x);
+ texel_offset = si_mpyui(texel_offset, 4);
+
+ vec_uint4 offset = (vec_uint4) si_a(tile_offset, texel_offset);
+
+ texture_ea = texture_ea + face * tlevel->bytes_per_image;
+
+ spu_dcache_fetch_unaligned((qword *) & texels[0],
+ texture_ea + spu_extract(offset, 0), 4);
+ spu_dcache_fetch_unaligned((qword *) & texels[1],
+ texture_ea + spu_extract(offset, 1), 4);
+ spu_dcache_fetch_unaligned((qword *) & texels[2],
+ texture_ea + spu_extract(offset, 2), 4);
+ spu_dcache_fetch_unaligned((qword *) & texels[3],
+ texture_ea + spu_extract(offset, 3), 4);
+}
+
+
+/** clamp vec to [0, max] */
+static INLINE vector signed int
+spu_clamp(vector signed int vec, vector signed int max)
+{
+ static const vector signed int zero = {0,0,0,0};
+ vector unsigned int c;
+ c = spu_cmpgt(vec, zero); /* c = vec > zero ? ~0 : 0 */
+ vec = spu_sel(zero, vec, c);
+ c = spu_cmpgt(vec, max); /* c = vec > max ? ~0 : 0 */
+ vec = spu_sel(vec, max, c);
+ return vec;
+}
+
+
+
+/**
+ * Do nearest texture sampling for four pixels.
+ * \param colors returned colors in SOA format (rrrr, gggg, bbbb, aaaa).
+ */
+void
+sample_texture_2d_nearest(vector float s, vector float t,
+ uint unit, uint level, uint face,
+ vector float colors[4])
+{
+ const struct spu_texture_level *tlevel = &spu.texture[unit].level[level];
+ vector float ss = spu_mul(s, tlevel->scale_s);
+ vector float tt = spu_mul(t, tlevel->scale_t);
+ vector signed int is = spu_convts(ss, 0);
+ vector signed int it = spu_convts(tt, 0);
+ vec_uint4 texels[4];
+
+ /* PIPE_TEX_WRAP_REPEAT */
+ is = spu_and(is, tlevel->mask_s);
+ it = spu_and(it, tlevel->mask_t);
+
+ /* PIPE_TEX_WRAP_CLAMP */
+ is = spu_clamp(is, tlevel->max_s);
+ it = spu_clamp(it, tlevel->max_t);
+
+ get_four_texels(tlevel, face, is, it, texels);
+
+ /* convert four packed ARGBA pixels to float RRRR,GGGG,BBBB,AAAA */
+ spu_unpack_A8R8G8B8_transpose4(texels, colors);
+}
+
+
+/**
+ * Do bilinear texture sampling for four pixels.
+ * \param colors returned colors in SOA format (rrrr, gggg, bbbb, aaaa).
+ */
+void
+sample_texture_2d_bilinear(vector float s, vector float t,
+ uint unit, uint level, uint face,
+ vector float colors[4])
+{
+ const struct spu_texture_level *tlevel = &spu.texture[unit].level[level];
+ static const vector float half = {-0.5f, -0.5f, -0.5f, -0.5f};
+
+ vector float ss = spu_madd(s, tlevel->scale_s, half);
+ vector float tt = spu_madd(t, tlevel->scale_t, half);
+
+ vector signed int is0 = spu_convts(ss, 0);
+ vector signed int it0 = spu_convts(tt, 0);
+
+ /* is + 1, it + 1 */
+ vector signed int is1 = spu_add(is0, 1);
+ vector signed int it1 = spu_add(it0, 1);
+
+ /* PIPE_TEX_WRAP_REPEAT */
+ is0 = spu_and(is0, tlevel->mask_s);
+ it0 = spu_and(it0, tlevel->mask_t);
+ is1 = spu_and(is1, tlevel->mask_s);
+ it1 = spu_and(it1, tlevel->mask_t);
+
+ /* PIPE_TEX_WRAP_CLAMP */
+ is0 = spu_clamp(is0, tlevel->max_s);
+ it0 = spu_clamp(it0, tlevel->max_t);
+ is1 = spu_clamp(is1, tlevel->max_s);
+ it1 = spu_clamp(it1, tlevel->max_t);
+
+ /* get packed int texels */
+ vector unsigned int texels[16];
+ get_four_texels(tlevel, face, is0, it0, texels + 0); /* upper-left */
+ get_four_texels(tlevel, face, is1, it0, texels + 4); /* upper-right */
+ get_four_texels(tlevel, face, is0, it1, texels + 8); /* lower-left */
+ get_four_texels(tlevel, face, is1, it1, texels + 12); /* lower-right */
+
+ /* convert packed int texels to float colors */
+ vector float ftexels[16];
+ spu_unpack_A8R8G8B8_transpose4(texels + 0, ftexels + 0);
+ spu_unpack_A8R8G8B8_transpose4(texels + 4, ftexels + 4);
+ spu_unpack_A8R8G8B8_transpose4(texels + 8, ftexels + 8);
+ spu_unpack_A8R8G8B8_transpose4(texels + 12, ftexels + 12);
+
+ /* Compute weighting factors in [0,1]
+ * Multiply texcoord by 1024, AND with 1023, convert back to float.
+ */
+ vector float ss1024 = spu_mul(ss, spu_splats(1024.0f));
+ vector signed int iss1024 = spu_convts(ss1024, 0);
+ iss1024 = spu_and(iss1024, 1023);
+ vector float sWeights0 = spu_convtf(iss1024, 10);
+
+ vector float tt1024 = spu_mul(tt, spu_splats(1024.0f));
+ vector signed int itt1024 = spu_convts(tt1024, 0);
+ itt1024 = spu_and(itt1024, 1023);
+ vector float tWeights0 = spu_convtf(itt1024, 10);
+
+ /* 1 - sWeight and 1 - tWeight */
+ vector float sWeights1 = spu_sub(spu_splats(1.0f), sWeights0);
+ vector float tWeights1 = spu_sub(spu_splats(1.0f), tWeights0);
+
+ /* reds, for four pixels */
+ ftexels[ 0] = spu_mul(ftexels[ 0], spu_mul(sWeights1, tWeights1)); /*ul*/
+ ftexels[ 4] = spu_mul(ftexels[ 4], spu_mul(sWeights0, tWeights1)); /*ur*/
+ ftexels[ 8] = spu_mul(ftexels[ 8], spu_mul(sWeights1, tWeights0)); /*ll*/
+ ftexels[12] = spu_mul(ftexels[12], spu_mul(sWeights0, tWeights0)); /*lr*/
+ colors[0] = spu_add(spu_add(ftexels[0], ftexels[4]),
+ spu_add(ftexels[8], ftexels[12]));
+
+ /* greens, for four pixels */
+ ftexels[ 1] = spu_mul(ftexels[ 1], spu_mul(sWeights1, tWeights1)); /*ul*/
+ ftexels[ 5] = spu_mul(ftexels[ 5], spu_mul(sWeights0, tWeights1)); /*ur*/
+ ftexels[ 9] = spu_mul(ftexels[ 9], spu_mul(sWeights1, tWeights0)); /*ll*/
+ ftexels[13] = spu_mul(ftexels[13], spu_mul(sWeights0, tWeights0)); /*lr*/
+ colors[1] = spu_add(spu_add(ftexels[1], ftexels[5]),
+ spu_add(ftexels[9], ftexels[13]));
+
+ /* blues, for four pixels */
+ ftexels[ 2] = spu_mul(ftexels[ 2], spu_mul(sWeights1, tWeights1)); /*ul*/
+ ftexels[ 6] = spu_mul(ftexels[ 6], spu_mul(sWeights0, tWeights1)); /*ur*/
+ ftexels[10] = spu_mul(ftexels[10], spu_mul(sWeights1, tWeights0)); /*ll*/
+ ftexels[14] = spu_mul(ftexels[14], spu_mul(sWeights0, tWeights0)); /*lr*/
+ colors[2] = spu_add(spu_add(ftexels[2], ftexels[6]),
+ spu_add(ftexels[10], ftexels[14]));
+
+ /* alphas, for four pixels */
+ ftexels[ 3] = spu_mul(ftexels[ 3], spu_mul(sWeights1, tWeights1)); /*ul*/
+ ftexels[ 7] = spu_mul(ftexels[ 7], spu_mul(sWeights0, tWeights1)); /*ur*/
+ ftexels[11] = spu_mul(ftexels[11], spu_mul(sWeights1, tWeights0)); /*ll*/
+ ftexels[15] = spu_mul(ftexels[15], spu_mul(sWeights0, tWeights0)); /*lr*/
+ colors[3] = spu_add(spu_add(ftexels[3], ftexels[7]),
+ spu_add(ftexels[11], ftexels[15]));
+}
+
+
+
+/**
+ * Adapted from /opt/cell/sdk/usr/spu/include/transpose_matrix4x4.h
+ */
+static INLINE void
+transpose(vector unsigned int *mOut0,
+ vector unsigned int *mOut1,
+ vector unsigned int *mOut2,
+ vector unsigned int *mOut3,
+ vector unsigned int *mIn)
+{
+ vector unsigned int abcd, efgh, ijkl, mnop; /* input vectors */
+ vector unsigned int aeim, bfjn, cgko, dhlp; /* output vectors */
+ vector unsigned int aibj, ckdl, emfn, gohp; /* intermediate vectors */
+
+ vector unsigned char shufflehi = ((vector unsigned char) {
+ 0x00, 0x01, 0x02, 0x03,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x14, 0x15, 0x16, 0x17});
+ vector unsigned char shufflelo = ((vector unsigned char) {
+ 0x08, 0x09, 0x0A, 0x0B,
+ 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F});
+ abcd = *(mIn+0);
+ efgh = *(mIn+1);
+ ijkl = *(mIn+2);
+ mnop = *(mIn+3);
+
+ aibj = spu_shuffle(abcd, ijkl, shufflehi);
+ ckdl = spu_shuffle(abcd, ijkl, shufflelo);
+ emfn = spu_shuffle(efgh, mnop, shufflehi);
+ gohp = spu_shuffle(efgh, mnop, shufflelo);
+
+ aeim = spu_shuffle(aibj, emfn, shufflehi);
+ bfjn = spu_shuffle(aibj, emfn, shufflelo);
+ cgko = spu_shuffle(ckdl, gohp, shufflehi);
+ dhlp = spu_shuffle(ckdl, gohp, shufflelo);
+
+ *mOut0 = aeim;
+ *mOut1 = bfjn;
+ *mOut2 = cgko;
+ *mOut3 = dhlp;
+}
+
+
+/**
+ * Bilinear filtering, using int instead of float arithmetic for computing
+ * sample weights.
+ */
+void
+sample_texture_2d_bilinear_int(vector float s, vector float t,
+ uint unit, uint level, uint face,
+ vector float colors[4])
+{
+ const struct spu_texture_level *tlevel = &spu.texture[unit].level[level];
+ static const vector float half = {-0.5f, -0.5f, -0.5f, -0.5f};
+
+ /* Scale texcoords by size of texture, and add half pixel bias */
+ vector float ss = spu_madd(s, tlevel->scale_s, half);
+ vector float tt = spu_madd(t, tlevel->scale_t, half);
+
+ /* convert float coords to fixed-pt coords with 7 fraction bits */
+ vector signed int is = spu_convts(ss, 7); /* XXX really need floor() here */
+ vector signed int it = spu_convts(tt, 7); /* XXX really need floor() here */
+
+ /* compute integer texel weights in [0, 127] */
+ vector signed int sWeights0 = spu_and(is, 127);
+ vector signed int tWeights0 = spu_and(it, 127);
+ vector signed int sWeights1 = spu_sub(127, sWeights0);
+ vector signed int tWeights1 = spu_sub(127, tWeights0);
+
+ /* texel coords: is0 = is / 128, it0 = is / 128 */
+ vector signed int is0 = spu_rlmask(is, -7);
+ vector signed int it0 = spu_rlmask(it, -7);
+
+ /* texel coords: i1 = is0 + 1, it1 = it0 + 1 */
+ vector signed int is1 = spu_add(is0, 1);
+ vector signed int it1 = spu_add(it0, 1);
+
+ /* PIPE_TEX_WRAP_REPEAT */
+ is0 = spu_and(is0, tlevel->mask_s);
+ it0 = spu_and(it0, tlevel->mask_t);
+ is1 = spu_and(is1, tlevel->mask_s);
+ it1 = spu_and(it1, tlevel->mask_t);
+
+ /* PIPE_TEX_WRAP_CLAMP */
+ is0 = spu_clamp(is0, tlevel->max_s);
+ it0 = spu_clamp(it0, tlevel->max_t);
+ is1 = spu_clamp(is1, tlevel->max_s);
+ it1 = spu_clamp(it1, tlevel->max_t);
+
+ /* get packed int texels */
+ vector unsigned int texels[16];
+ get_four_texels(tlevel, face, is0, it0, texels + 0); /* upper-left */
+ get_four_texels(tlevel, face, is1, it0, texels + 4); /* upper-right */
+ get_four_texels(tlevel, face, is0, it1, texels + 8); /* lower-left */
+ get_four_texels(tlevel, face, is1, it1, texels + 12); /* lower-right */
+
+ /* twiddle packed 32-bit BGRA pixels into RGBA as four unsigned ints */
+ {
+ static const unsigned char ZERO = 0x80;
+ int i;
+ for (i = 0; i < 16; i++) {
+ texels[i] = spu_shuffle(texels[i], texels[i],
+ ((vector unsigned char) {
+ ZERO, ZERO, ZERO, 1,
+ ZERO, ZERO, ZERO, 2,
+ ZERO, ZERO, ZERO, 3,
+ ZERO, ZERO, ZERO, 0}));
+ }
+ }
+
+ /* convert RGBA,RGBA,RGBA,RGBA to RRRR,GGGG,BBBB,AAAA */
+ vector unsigned int texel0, texel1, texel2, texel3, texel4, texel5, texel6, texel7,
+ texel8, texel9, texel10, texel11, texel12, texel13, texel14, texel15;
+ transpose(&texel0, &texel1, &texel2, &texel3, texels + 0);
+ transpose(&texel4, &texel5, &texel6, &texel7, texels + 4);
+ transpose(&texel8, &texel9, &texel10, &texel11, texels + 8);
+ transpose(&texel12, &texel13, &texel14, &texel15, texels + 12);
+
+ /* computed weighted colors */
+ vector unsigned int c0, c1, c2, c3, cSum;
+
+ /* red */
+ c0 = (vector unsigned int) si_mpy((qword) texel0, si_mpy((qword) sWeights1, (qword) tWeights1)); /*ul*/
+ c1 = (vector unsigned int) si_mpy((qword) texel4, si_mpy((qword) sWeights0, (qword) tWeights1)); /*ur*/
+ c2 = (vector unsigned int) si_mpy((qword) texel8, si_mpy((qword) sWeights1, (qword) tWeights0)); /*ll*/
+ c3 = (vector unsigned int) si_mpy((qword) texel12, si_mpy((qword) sWeights0, (qword) tWeights0)); /*lr*/
+ cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
+ colors[0] = spu_convtf(cSum, 22);
+
+ /* green */
+ c0 = (vector unsigned int) si_mpy((qword) texel1, si_mpy((qword) sWeights1, (qword) tWeights1)); /*ul*/
+ c1 = (vector unsigned int) si_mpy((qword) texel5, si_mpy((qword) sWeights0, (qword) tWeights1)); /*ur*/
+ c2 = (vector unsigned int) si_mpy((qword) texel9, si_mpy((qword) sWeights1, (qword) tWeights0)); /*ll*/
+ c3 = (vector unsigned int) si_mpy((qword) texel13, si_mpy((qword) sWeights0, (qword) tWeights0)); /*lr*/
+ cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
+ colors[1] = spu_convtf(cSum, 22);
+
+ /* blue */
+ c0 = (vector unsigned int) si_mpy((qword) texel2, si_mpy((qword) sWeights1, (qword) tWeights1)); /*ul*/
+ c1 = (vector unsigned int) si_mpy((qword) texel6, si_mpy((qword) sWeights0, (qword) tWeights1)); /*ur*/
+ c2 = (vector unsigned int) si_mpy((qword) texel10, si_mpy((qword) sWeights1, (qword) tWeights0)); /*ll*/
+ c3 = (vector unsigned int) si_mpy((qword) texel14, si_mpy((qword) sWeights0, (qword) tWeights0)); /*lr*/
+ cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
+ colors[2] = spu_convtf(cSum, 22);
+
+ /* alpha */
+ c0 = (vector unsigned int) si_mpy((qword) texel3, si_mpy((qword) sWeights1, (qword) tWeights1)); /*ul*/
+ c1 = (vector unsigned int) si_mpy((qword) texel7, si_mpy((qword) sWeights0, (qword) tWeights1)); /*ur*/
+ c2 = (vector unsigned int) si_mpy((qword) texel11, si_mpy((qword) sWeights1, (qword) tWeights0)); /*ll*/
+ c3 = (vector unsigned int) si_mpy((qword) texel15, si_mpy((qword) sWeights0, (qword) tWeights0)); /*lr*/
+ cSum = spu_add(spu_add(c0, c1), spu_add(c2, c3));
+ colors[3] = spu_convtf(cSum, 22);
+}
+
+
+
+/**
+ * Compute level of detail factor from texcoords.
+ */
+static INLINE float
+compute_lambda_2d(uint unit, vector float s, vector float t)
+{
+ uint baseLevel = 0;
+ float width = spu.texture[unit].level[baseLevel].width;
+ float height = spu.texture[unit].level[baseLevel].width;
+ float dsdx = width * (spu_extract(s, 1) - spu_extract(s, 0));
+ float dsdy = width * (spu_extract(s, 2) - spu_extract(s, 0));
+ float dtdx = height * (spu_extract(t, 1) - spu_extract(t, 0));
+ float dtdy = height * (spu_extract(t, 2) - spu_extract(t, 0));
+#if 0
+ /* ideal value */
+ float x = dsdx * dsdx + dtdx * dtdx;
+ float y = dsdy * dsdy + dtdy * dtdy;
+ float rho = x > y ? x : y;
+ rho = sqrtf(rho);
+#else
+ /* approximation */
+ dsdx = fabsf(dsdx);
+ dsdy = fabsf(dsdy);
+ dtdx = fabsf(dtdx);
+ dtdy = fabsf(dtdy);
+ float rho = (dsdx + dsdy + dtdx + dtdy) * 0.5;
+#endif
+ float lambda = logf(rho) * 1.442695f; /* compute logbase2(rho) */
+ return lambda;
+}
+
+
+/**
+ * Blend two sets of colors according to weight.
+ */
+static void
+blend_colors(vector float c0[4], const vector float c1[4], float weight)
+{
+ vector float t = spu_splats(weight);
+ vector float dc0 = spu_sub(c1[0], c0[0]);
+ vector float dc1 = spu_sub(c1[1], c0[1]);
+ vector float dc2 = spu_sub(c1[2], c0[2]);
+ vector float dc3 = spu_sub(c1[3], c0[3]);
+ c0[0] = spu_madd(dc0, t, c0[0]);
+ c0[1] = spu_madd(dc1, t, c0[1]);
+ c0[2] = spu_madd(dc2, t, c0[2]);
+ c0[3] = spu_madd(dc3, t, c0[3]);
+}
+
+
+/**
+ * Texture sampling with level of detail selection and possibly mipmap
+ * interpolation.
+ */
+void
+sample_texture_2d_lod(vector float s, vector float t,
+ uint unit, uint level_ignored, uint face,
+ vector float colors[4])
+{
+ /*
+ * Note that we're computing a lambda/lod here that's used for all
+ * four pixels in the quad.
+ */
+ float lambda = compute_lambda_2d(unit, s, t);
+
+ (void) face;
+ (void) level_ignored;
+
+ /* apply lod bias */
+ lambda += spu.sampler[unit].lod_bias;
+
+ /* clamp */
+ if (lambda < spu.sampler[unit].min_lod)
+ lambda = spu.sampler[unit].min_lod;
+ else if (lambda > spu.sampler[unit].max_lod)
+ lambda = spu.sampler[unit].max_lod;
+
+ if (lambda <= 0.0f) {
+ /* magnify */
+ spu.mag_sample_texture_2d[unit](s, t, unit, 0, face, colors);
+ }
+ else {
+ /* minify */
+ if (spu.sampler[unit].min_img_filter == PIPE_TEX_FILTER_LINEAR) {
+ /* sample two mipmap levels and interpolate */
+ int level = (int) lambda;
+ if (level > (int) spu.texture[unit].max_level)
+ level = spu.texture[unit].max_level;
+ spu.min_sample_texture_2d[unit](s, t, unit, level, face, colors);
+ if (spu.sampler[unit].min_img_filter == PIPE_TEX_FILTER_LINEAR) {
+ /* sample second mipmap level */
+ float weight = lambda - (float) level;
+ level++;
+ if (level <= (int) spu.texture[unit].max_level) {
+ vector float colors2[4];
+ spu.min_sample_texture_2d[unit](s, t, unit, level, face, colors2);
+ blend_colors(colors, colors2, weight);
+ }
+ }
+ }
+ else {
+ /* sample one mipmap level */
+ int level = (int) (lambda + 0.5f);
+ if (level > (int) spu.texture[unit].max_level)
+ level = spu.texture[unit].max_level;
+ spu.min_sample_texture_2d[unit](s, t, unit, level, face, colors);
+ }
+ }
+}
+
+
+/** XXX need a SIMD version of this */
+static unsigned
+choose_cube_face(float rx, float ry, float rz, float *newS, float *newT)
+{
+ /*
+ major axis
+ direction target sc tc ma
+ ---------- ------------------------------- --- --- ---
+ +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
+ -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
+ +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
+ -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
+ +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
+ -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
+ */
+ const float arx = fabsf(rx);
+ const float ary = fabsf(ry);
+ const float arz = fabsf(rz);
+ unsigned face;
+ float sc, tc, ma;
+
+ if (arx > ary && arx > arz) {
+ if (rx >= 0.0F) {
+ face = PIPE_TEX_FACE_POS_X;
+ sc = -rz;
+ tc = -ry;
+ ma = arx;
+ }
+ else {
+ face = PIPE_TEX_FACE_NEG_X;
+ sc = rz;
+ tc = -ry;
+ ma = arx;
+ }
+ }
+ else if (ary > arx && ary > arz) {
+ if (ry >= 0.0F) {
+ face = PIPE_TEX_FACE_POS_Y;
+ sc = rx;
+ tc = rz;
+ ma = ary;
+ }
+ else {
+ face = PIPE_TEX_FACE_NEG_Y;
+ sc = rx;
+ tc = -rz;
+ ma = ary;
+ }
+ }
+ else {
+ if (rz > 0.0F) {
+ face = PIPE_TEX_FACE_POS_Z;
+ sc = rx;
+ tc = -ry;
+ ma = arz;
+ }
+ else {
+ face = PIPE_TEX_FACE_NEG_Z;
+ sc = -rx;
+ tc = -ry;
+ ma = arz;
+ }
+ }
+
+ *newS = (sc / ma + 1.0F) * 0.5F;
+ *newT = (tc / ma + 1.0F) * 0.5F;
+
+ return face;
+}
+
+
+
+void
+sample_texture_cube(vector float s, vector float t, vector float r,
+ uint unit, vector float colors[4])
+{
+ uint p, faces[4], level = 0;
+ float newS[4], newT[4];
+
+ /* Compute cube faces referenced by the four sets of texcoords.
+ * XXX we should SIMD-ize this.
+ */
+ for (p = 0; p < 4; p++) {
+ float rx = spu_extract(s, p);
+ float ry = spu_extract(t, p);
+ float rz = spu_extract(r, p);
+ faces[p] = choose_cube_face(rx, ry, rz, &newS[p], &newT[p]);
+ }
+
+ if (faces[0] == faces[1] &&
+ faces[0] == faces[2] &&
+ faces[0] == faces[3]) {
+ /* GOOD! All four texcoords refer to the same cube face */
+ s = (vector float) {newS[0], newS[1], newS[2], newS[3]};
+ t = (vector float) {newT[0], newT[1], newT[2], newT[3]};
+ spu.sample_texture_2d[unit](s, t, unit, level, faces[0], colors);
+ }
+ else {
+ /* BAD! The four texcoords refer to different faces */
+ for (p = 0; p < 4; p++) {
+ vector float c[4];
+
+ spu.sample_texture_2d[unit](spu_splats(newS[p]), spu_splats(newT[p]),
+ unit, level, faces[p], c);
+
+ float red = spu_extract(c[0], p);
+ float green = spu_extract(c[1], p);
+ float blue = spu_extract(c[2], p);
+ float alpha = spu_extract(c[3], p);
+
+ colors[0] = spu_insert(red, colors[0], p);
+ colors[1] = spu_insert(green, colors[1], p);
+ colors[2] = spu_insert(blue, colors[2], p);
+ colors[3] = spu_insert(alpha, colors[3], p);
+ }
+ }
+}
diff --git a/src/gallium/drivers/cell/spu/spu_texture.h b/src/gallium/drivers/cell/spu/spu_texture.h
new file mode 100644
index 0000000000..7b75b007b5
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_texture.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SPU_TEXTURE_H
+#define SPU_TEXTURE_H
+
+
+#include "pipe/p_compiler.h"
+
+
+extern void
+invalidate_tex_cache(void);
+
+
+extern void
+sample_texture_2d_nearest(vector float s, vector float t,
+ uint unit, uint level, uint face,
+ vector float colors[4]);
+
+
+extern void
+sample_texture_2d_bilinear(vector float s, vector float t,
+ uint unit, uint level, uint face,
+ vector float colors[4]);
+
+extern void
+sample_texture_2d_bilinear_int(vector float s, vector float t,
+ uint unit, uint level, uint face,
+ vector float colors[4]);
+
+
+extern void
+sample_texture_2d_lod(vector float s, vector float t,
+ uint unit, uint level, uint face,
+ vector float colors[4]);
+
+
+extern void
+sample_texture_cube(vector float s, vector float t, vector float r,
+ uint unit, vector float colors[4]);
+
+
+#endif /* SPU_TEXTURE_H */
diff --git a/src/gallium/drivers/cell/spu/spu_tile.c b/src/gallium/drivers/cell/spu/spu_tile.c
new file mode 100644
index 0000000000..6905015a48
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_tile.c
@@ -0,0 +1,126 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+
+#include "spu_tile.h"
+#include "spu_main.h"
+
+
+/**
+ * Get tile of color or Z values from main memory, put into SPU memory.
+ */
+void
+get_tile(uint tx, uint ty, tile_t *tile, int tag, int zBuf)
+{
+ const uint offset = ty * spu.fb.width_tiles + tx;
+ const uint bytesPerTile = TILE_SIZE * TILE_SIZE * (zBuf ? spu.fb.zsize : 4);
+ const ubyte *src = zBuf ? spu.fb.depth_start : spu.fb.color_start;
+
+ src += offset * bytesPerTile;
+
+ ASSERT(tx < spu.fb.width_tiles);
+ ASSERT(ty < spu.fb.height_tiles);
+ ASSERT_ALIGN16(tile);
+ /*
+ printf("get_tile: dest: %p src: 0x%x size: %d\n",
+ tile, (unsigned int) src, bytesPerTile);
+ */
+ mfc_get(tile->ui, /* dest in local memory */
+ (unsigned int) src, /* src in main memory */
+ bytesPerTile,
+ tag,
+ 0, /* tid */
+ 0 /* rid */);
+}
+
+
+/**
+ * Move tile of color or Z values from SPU memory to main memory.
+ */
+void
+put_tile(uint tx, uint ty, const tile_t *tile, int tag, int zBuf)
+{
+ const uint offset = ty * spu.fb.width_tiles + tx;
+ const uint bytesPerTile = TILE_SIZE * TILE_SIZE * (zBuf ? spu.fb.zsize : 4);
+ ubyte *dst = zBuf ? spu.fb.depth_start : spu.fb.color_start;
+
+ dst += offset * bytesPerTile;
+
+ ASSERT(tx < spu.fb.width_tiles);
+ ASSERT(ty < spu.fb.height_tiles);
+ ASSERT_ALIGN16(tile);
+ /*
+ printf("SPU %u: put_tile: src: %p dst: 0x%x size: %d\n",
+ spu.init.id,
+ tile, (unsigned int) dst, bytesPerTile);
+ */
+ mfc_put((void *) tile->ui, /* src in local memory */
+ (unsigned int) dst, /* dst in main memory */
+ bytesPerTile,
+ tag,
+ 0, /* tid */
+ 0 /* rid */);
+}
+
+
+/**
+ * For tiles whose status is TILE_STATUS_CLEAR, write solid-filled
+ * tiles back to the main framebuffer.
+ */
+void
+really_clear_tiles(uint surfaceIndex)
+{
+ const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
+ uint i;
+
+ if (surfaceIndex == 0) {
+ clear_c_tile(&spu.ctile);
+
+ for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
+ uint tx = i % spu.fb.width_tiles;
+ uint ty = i / spu.fb.width_tiles;
+ if (spu.ctile_status[ty][tx] == TILE_STATUS_CLEAR) {
+ put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
+ }
+ }
+ }
+ else {
+ clear_z_tile(&spu.ztile);
+
+ for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
+ uint tx = i % spu.fb.width_tiles;
+ uint ty = i / spu.fb.width_tiles;
+ if (spu.ztile_status[ty][tx] == TILE_STATUS_CLEAR)
+ put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 1);
+ }
+ }
+
+#if 0
+ wait_on_mask(1 << TAG_SURFACE_CLEAR);
+#endif
+}
diff --git a/src/gallium/drivers/cell/spu/spu_tile.h b/src/gallium/drivers/cell/spu/spu_tile.h
new file mode 100644
index 0000000000..7bfb52be8f
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_tile.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SPU_TILE_H
+#define SPU_TILE_H
+
+
+#include <libmisc.h>
+#include <spu_mfcio.h>
+#include "spu_main.h"
+#include "cell/common.h"
+
+
+
+extern void
+get_tile(uint tx, uint ty, tile_t *tile, int tag, int zBuf);
+
+extern void
+put_tile(uint tx, uint ty, const tile_t *tile, int tag, int zBuf);
+
+extern void
+really_clear_tiles(uint surfaceIndex);
+
+
+static INLINE void
+clear_c_tile(tile_t *ctile)
+{
+ memset32((uint*) ctile->ui,
+ spu.fb.color_clear_value,
+ TILE_SIZE * TILE_SIZE);
+}
+
+
+static INLINE void
+clear_z_tile(tile_t *ztile)
+{
+ if (spu.fb.zsize == 2) {
+ memset16((ushort*) ztile->us,
+ spu.fb.depth_clear_value,
+ TILE_SIZE * TILE_SIZE);
+ }
+ else {
+ ASSERT(spu.fb.zsize != 0);
+ memset32((uint*) ztile->ui,
+ spu.fb.depth_clear_value,
+ TILE_SIZE * TILE_SIZE);
+ }
+}
+
+
+#endif /* SPU_TILE_H */
diff --git a/src/gallium/drivers/cell/spu/spu_tri.c b/src/gallium/drivers/cell/spu/spu_tri.c
new file mode 100644
index 0000000000..58be001be4
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_tri.c
@@ -0,0 +1,843 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Triangle rendering within a tile.
+ */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "util/u_math.h"
+#include "spu_colorpack.h"
+#include "spu_main.h"
+#include "spu_shuffle.h"
+#include "spu_texture.h"
+#include "spu_tile.h"
+#include "spu_tri.h"
+
+
+/** Masks are uint[4] vectors with each element being 0 or 0xffffffff */
+typedef vector unsigned int mask_t;
+
+
+
+/**
+ * Simplified types taken from other parts of Gallium
+ */
+struct vertex_header {
+ vector float data[1];
+};
+
+
+
+/* XXX fix this */
+#undef CEILF
+#define CEILF(X) ((float) (int) ((X) + 0.99999f))
+
+
+#define QUAD_TOP_LEFT 0
+#define QUAD_TOP_RIGHT 1
+#define QUAD_BOTTOM_LEFT 2
+#define QUAD_BOTTOM_RIGHT 3
+#define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT)
+#define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT)
+#define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT)
+#define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
+#define MASK_ALL 0xf
+
+
+#define CHAN0 0
+#define CHAN1 1
+#define CHAN2 2
+#define CHAN3 3
+
+
+#define DEBUG_VERTS 0
+
+/**
+ * Triangle edge info
+ */
+struct edge {
+ union {
+ struct {
+ float dx; /**< X(v1) - X(v0), used only during setup */
+ float dy; /**< Y(v1) - Y(v0), used only during setup */
+ };
+ vec_float4 ds; /**< vector accessor for dx and dy */
+ };
+ float dxdy; /**< dx/dy */
+ float sx, sy; /**< first sample point coord */
+ int lines; /**< number of lines on this edge */
+};
+
+
+struct interp_coef
+{
+ vector float a0;
+ vector float dadx;
+ vector float dady;
+};
+
+
+/**
+ * Triangle setup info (derived from draw_stage).
+ * Also used for line drawing (taking some liberties).
+ */
+struct setup_stage {
+
+ /* Vertices are just an array of floats making up each attribute in
+ * turn. Currently fixed at 4 floats, but should change in time.
+ * Codegen will help cope with this.
+ */
+ union {
+ struct {
+ const struct vertex_header *vmin;
+ const struct vertex_header *vmid;
+ const struct vertex_header *vmax;
+ const struct vertex_header *vprovoke;
+ };
+ qword vertex_headers;
+ };
+
+ struct edge ebot;
+ struct edge etop;
+ struct edge emaj;
+
+ float oneOverArea; /* XXX maybe make into vector? */
+
+ uint facing;
+
+ uint tx, ty; /**< position of current tile (x, y) */
+
+ union {
+ struct {
+ int cliprect_minx;
+ int cliprect_miny;
+ int cliprect_maxx;
+ int cliprect_maxy;
+ };
+ qword cliprect;
+ };
+
+ struct interp_coef coef[PIPE_MAX_SHADER_INPUTS];
+
+ struct {
+ vec_int4 quad; /**< [0] = row0, [1] = row1; {left[0],left[1],right[0],right[1]} */
+ int y;
+ unsigned y_flags;
+ unsigned mask; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
+ } span;
+};
+
+
+static struct setup_stage setup;
+
+
+static INLINE vector float
+splatx(vector float v)
+{
+ return spu_splats(spu_extract(v, CHAN0));
+}
+
+static INLINE vector float
+splaty(vector float v)
+{
+ return spu_splats(spu_extract(v, CHAN1));
+}
+
+static INLINE vector float
+splatz(vector float v)
+{
+ return spu_splats(spu_extract(v, CHAN2));
+}
+
+static INLINE vector float
+splatw(vector float v)
+{
+ return spu_splats(spu_extract(v, CHAN3));
+}
+
+
+/**
+ * Setup fragment shader inputs by evaluating triangle's vertex
+ * attribute coefficient info.
+ * \param x quad x pos
+ * \param y quad y pos
+ * \param fragZ returns quad Z values
+ * \param fragInputs returns fragment program inputs
+ * Note: this code could be incorporated into the fragment program
+ * itself to avoid the loop and switch.
+ */
+static void
+eval_inputs(float x, float y, vector float *fragZ, vector float fragInputs[])
+{
+ static const vector float deltaX = (const vector float) {0, 1, 0, 1};
+ static const vector float deltaY = (const vector float) {0, 0, 1, 1};
+
+ const uint posSlot = 0;
+ const vector float pos = setup.coef[posSlot].a0;
+ const vector float dposdx = setup.coef[posSlot].dadx;
+ const vector float dposdy = setup.coef[posSlot].dady;
+ const vector float fragX = spu_splats(x) + deltaX;
+ const vector float fragY = spu_splats(y) + deltaY;
+ vector float fragW, wInv;
+ uint i;
+
+ *fragZ = splatz(pos) + fragX * splatz(dposdx) + fragY * splatz(dposdy);
+ fragW = splatw(pos) + fragX * splatw(dposdx) + fragY * splatw(dposdy);
+ wInv = spu_re(fragW); /* 1 / w */
+
+ /* loop over fragment program inputs */
+ for (i = 0; i < spu.vertex_info.num_attribs; i++) {
+ uint attr = i + 1;
+ enum interp_mode interp = spu.vertex_info.attrib[attr].interp_mode;
+
+ /* constant term */
+ vector float a0 = setup.coef[attr].a0;
+ vector float r0 = splatx(a0);
+ vector float r1 = splaty(a0);
+ vector float r2 = splatz(a0);
+ vector float r3 = splatw(a0);
+
+ if (interp == INTERP_LINEAR || interp == INTERP_PERSPECTIVE) {
+ /* linear term */
+ vector float dadx = setup.coef[attr].dadx;
+ vector float dady = setup.coef[attr].dady;
+ /* Use SPU intrinsics here to get slightly better code.
+ * originally: r0 += fragX * splatx(dadx) + fragY * splatx(dady);
+ */
+ r0 = spu_madd(fragX, splatx(dadx), spu_madd(fragY, splatx(dady), r0));
+ r1 = spu_madd(fragX, splaty(dadx), spu_madd(fragY, splaty(dady), r1));
+ r2 = spu_madd(fragX, splatz(dadx), spu_madd(fragY, splatz(dady), r2));
+ r3 = spu_madd(fragX, splatw(dadx), spu_madd(fragY, splatw(dady), r3));
+ if (interp == INTERP_PERSPECTIVE) {
+ /* perspective term */
+ r0 *= wInv;
+ r1 *= wInv;
+ r2 *= wInv;
+ r3 *= wInv;
+ }
+ }
+ fragInputs[CHAN0] = r0;
+ fragInputs[CHAN1] = r1;
+ fragInputs[CHAN2] = r2;
+ fragInputs[CHAN3] = r3;
+ fragInputs += 4;
+ }
+}
+
+
+/**
+ * Emit a quad (pass to next stage). No clipping is done.
+ * Note: about 1/5 to 1/7 of the time, mask is zero and this function
+ * should be skipped. But adding the test for that slows things down
+ * overall.
+ */
+static INLINE void
+emit_quad( int x, int y, mask_t mask)
+{
+ /* If any bits in mask are set... */
+ if (spu_extract(spu_orx(mask), 0)) {
+ const int ix = x - setup.cliprect_minx;
+ const int iy = y - setup.cliprect_miny;
+
+ spu.cur_ctile_status = TILE_STATUS_DIRTY;
+ spu.cur_ztile_status = TILE_STATUS_DIRTY;
+
+ {
+ /*
+ * Run fragment shader, execute per-fragment ops, update fb/tile.
+ */
+ vector float inputs[4*4], outputs[2*4];
+ vector unsigned int kill_mask;
+ vector float fragZ;
+
+ eval_inputs((float) x, (float) y, &fragZ, inputs);
+
+ ASSERT(spu.fragment_program);
+ ASSERT(spu.fragment_ops);
+
+ /* Execute the current fragment program */
+ kill_mask = spu.fragment_program(inputs, outputs, spu.constants);
+
+ mask = spu_andc(mask, kill_mask);
+
+ /* Execute per-fragment/quad operations, including:
+ * alpha test, z test, stencil test, blend and framebuffer writing.
+ * Note that there are two different fragment operations functions
+ * that can be called, one for front-facing fragments, and one
+ * for back-facing fragments. (Often the two are the same;
+ * but in some cases, like two-sided stenciling, they can be
+ * very different.) So choose the correct function depending
+ * on the calculated facing.
+ */
+ spu.fragment_ops[setup.facing](ix, iy, &spu.ctile, &spu.ztile,
+ fragZ,
+ outputs[0*4+0],
+ outputs[0*4+1],
+ outputs[0*4+2],
+ outputs[0*4+3],
+ mask);
+ }
+ }
+}
+
+
+/**
+ * Given an X or Y coordinate, return the block/quad coordinate that it
+ * belongs to.
+ */
+static INLINE int
+block(int x)
+{
+ return x & ~1;
+}
+
+
+/**
+ * Render a horizontal span of quads
+ */
+static void
+flush_spans(void)
+{
+ int minleft, maxright;
+
+ const int l0 = spu_extract(setup.span.quad, 0);
+ const int l1 = spu_extract(setup.span.quad, 1);
+ const int r0 = spu_extract(setup.span.quad, 2);
+ const int r1 = spu_extract(setup.span.quad, 3);
+
+ switch (setup.span.y_flags) {
+ case 0x3:
+ /* both odd and even lines written (both quad rows) */
+ minleft = MIN2(l0, l1);
+ maxright = MAX2(r0, r1);
+ break;
+
+ case 0x1:
+ /* only even line written (quad top row) */
+ minleft = l0;
+ maxright = r0;
+ break;
+
+ case 0x2:
+ /* only odd line written (quad bottom row) */
+ minleft = l1;
+ maxright = r1;
+ break;
+
+ default:
+ return;
+ }
+
+ /* OK, we're very likely to need the tile data now.
+ * clear or finish waiting if needed.
+ */
+ if (spu.cur_ctile_status == TILE_STATUS_GETTING) {
+ /* wait for mfc_get() to complete */
+ //printf("SPU: %u: waiting for ctile\n", spu.init.id);
+ wait_on_mask(1 << TAG_READ_TILE_COLOR);
+ spu.cur_ctile_status = TILE_STATUS_CLEAN;
+ }
+ else if (spu.cur_ctile_status == TILE_STATUS_CLEAR) {
+ //printf("SPU %u: clearing C tile %u, %u\n", spu.init.id, setup.tx, setup.ty);
+ clear_c_tile(&spu.ctile);
+ spu.cur_ctile_status = TILE_STATUS_DIRTY;
+ }
+ ASSERT(spu.cur_ctile_status != TILE_STATUS_DEFINED);
+
+ if (spu.read_depth_stencil) {
+ if (spu.cur_ztile_status == TILE_STATUS_GETTING) {
+ /* wait for mfc_get() to complete */
+ //printf("SPU: %u: waiting for ztile\n", spu.init.id);
+ wait_on_mask(1 << TAG_READ_TILE_Z);
+ spu.cur_ztile_status = TILE_STATUS_CLEAN;
+ }
+ else if (spu.cur_ztile_status == TILE_STATUS_CLEAR) {
+ //printf("SPU %u: clearing Z tile %u, %u\n", spu.init.id, setup.tx, setup.ty);
+ clear_z_tile(&spu.ztile);
+ spu.cur_ztile_status = TILE_STATUS_DIRTY;
+ }
+ ASSERT(spu.cur_ztile_status != TILE_STATUS_DEFINED);
+ }
+
+ /* XXX this loop could be moved into the above switch cases... */
+
+ /* Setup for mask calculation */
+ const vec_int4 quad_LlRr = setup.span.quad;
+ const vec_int4 quad_RrLl = spu_rlqwbyte(quad_LlRr, 8);
+ const vec_int4 quad_LLll = spu_shuffle(quad_LlRr, quad_LlRr, SHUFFLE4(A,A,B,B));
+ const vec_int4 quad_RRrr = spu_shuffle(quad_RrLl, quad_RrLl, SHUFFLE4(A,A,B,B));
+
+ const vec_int4 twos = spu_splats(2);
+
+ const int x = block(minleft);
+ vec_int4 xs = {x, x+1, x, x+1};
+
+ for (; spu_extract(xs, 0) <= block(maxright); xs += twos) {
+ /**
+ * Computes mask to indicate which pixels in the 2x2 quad are actually
+ * inside the triangle's bounds.
+ */
+
+ /* Calculate ({x,x+1,x,x+1} >= {l[0],l[0],l[1],l[1]}) */
+ const mask_t gt_LLll_xs = spu_cmpgt(quad_LLll, xs);
+ const mask_t gte_xs_LLll = spu_nand(gt_LLll_xs, gt_LLll_xs);
+
+ /* Calculate ({r[0],r[0],r[1],r[1]} > {x,x+1,x,x+1}) */
+ const mask_t gt_RRrr_xs = spu_cmpgt(quad_RRrr, xs);
+
+ /* Combine results to create mask */
+ const mask_t mask = spu_and(gte_xs_LLll, gt_RRrr_xs);
+
+ emit_quad(spu_extract(xs, 0), setup.span.y, mask);
+ }
+
+ setup.span.y = 0;
+ setup.span.y_flags = 0;
+ /* Zero right elements */
+ setup.span.quad = spu_shuffle(setup.span.quad, setup.span.quad, SHUFFLE4(A,B,0,0));
+}
+
+
+#if DEBUG_VERTS
+static void
+print_vertex(const struct vertex_header *v)
+{
+ uint i;
+ fprintf(stderr, " Vertex: (%p)\n", v);
+ for (i = 0; i < spu.vertex_info.num_attribs; i++) {
+ fprintf(stderr, " %d: %f %f %f %f\n", i,
+ spu_extract(v->data[i], 0),
+ spu_extract(v->data[i], 1),
+ spu_extract(v->data[i], 2),
+ spu_extract(v->data[i], 3));
+ }
+}
+#endif
+
+/* Returns the minimum of each slot of two vec_float4s as qwords.
+ * i.e. return[n] = min(q0[n],q1[n]);
+ */
+static qword
+minfq(qword q0, qword q1)
+{
+ const qword q0q1m = si_fcgt(q0, q1);
+ return si_selb(q0, q1, q0q1m);
+}
+
+/* Returns the minimum of each slot of three vec_float4s as qwords.
+ * i.e. return[n] = min(q0[n],q1[n],q2[n]);
+ */
+static qword
+min3fq(qword q0, qword q1, qword q2)
+{
+ return minfq(minfq(q0, q1), q2);
+}
+
+/* Returns the maximum of each slot of two vec_float4s as qwords.
+ * i.e. return[n] = min(q0[n],q1[n],q2[n]);
+ */
+static qword
+maxfq(qword q0, qword q1) {
+ const qword q0q1m = si_fcgt(q0, q1);
+ return si_selb(q1, q0, q0q1m);
+}
+
+/* Returns the maximum of each slot of three vec_float4s as qwords.
+ * i.e. return[n] = min(q0[n],q1[n],q2[n]);
+ */
+static qword
+max3fq(qword q0, qword q1, qword q2) {
+ return maxfq(maxfq(q0, q1), q2);
+}
+
+/**
+ * Sort vertices from top to bottom.
+ * Compute area and determine front vs. back facing.
+ * Do coarse clip test against tile bounds
+ * \return FALSE if tri is totally outside tile, TRUE otherwise
+ */
+static boolean
+setup_sort_vertices(const qword vs)
+{
+ float area, sign;
+
+#if DEBUG_VERTS
+ if (spu.init.id==0) {
+ fprintf(stderr, "SPU %u: Triangle:\n", spu.init.id);
+ print_vertex(v0);
+ print_vertex(v1);
+ print_vertex(v2);
+ }
+#endif
+
+ {
+ /* Load the float values for various processing... */
+ const qword f0 = (qword)(((const struct vertex_header*)si_to_ptr(vs))->data[0]);
+ const qword f1 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 4)))->data[0]);
+ const qword f2 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 8)))->data[0]);
+
+ /* Check if triangle is completely outside the tile bounds
+ * Find the min and max x and y positions of the three poits */
+ const qword minf = min3fq(f0, f1, f2);
+ const qword maxf = max3fq(f0, f1, f2);
+
+ /* Compare min and max against cliprect vals */
+ const qword maxsmins = si_shufb(maxf, minf, SHUFB4(A,B,a,b));
+ const qword outside = si_fcgt(maxsmins, si_csflt(setup.cliprect, 0));
+
+ /* Use a little magic to work out of the tri is visible or not */
+ if(si_to_uint(si_xori(si_gb(outside), 0xc))) return FALSE;
+
+ /* determine bottom to top order of vertices */
+ /* A table of shuffle patterns for putting vertex_header pointers into
+ correct order. Quite magical. */
+ const qword sort_order_patterns[] = {
+ SHUFB4(A,B,C,C),
+ SHUFB4(C,A,B,C),
+ SHUFB4(A,C,B,C),
+ SHUFB4(B,C,A,C),
+ SHUFB4(B,A,C,C),
+ SHUFB4(C,B,A,C) };
+
+ /* Collate y values into two vectors for comparison.
+ Using only one shuffle constant! ;) */
+ const qword y_02_ = si_shufb(f0, f2, SHUFB4(0,B,b,C));
+ const qword y_10_ = si_shufb(f1, f0, SHUFB4(0,B,b,C));
+ const qword y_012 = si_shufb(y_02_, f1, SHUFB4(0,B,b,C));
+ const qword y_120 = si_shufb(y_10_, f2, SHUFB4(0,B,b,C));
+
+ /* Perform comparison: {y0,y1,y2} > {y1,y2,y0} */
+ const qword compare = si_fcgt(y_012, y_120);
+ /* Compress the result of the comparison into 4 bits */
+ const qword gather = si_gb(compare);
+ /* Subtract one to attain the index into the LUT. Magical. */
+ const unsigned int index = si_to_uint(gather) - 1;
+
+ /* Load the appropriate pattern and construct the desired vector. */
+ setup.vertex_headers = si_shufb(vs, vs, sort_order_patterns[index]);
+
+ /* Using the result of the comparison, set sign.
+ Very magical. */
+ sign = ((si_to_uint(si_cntb(gather)) == 2) ? 1.0f : -1.0f);
+ }
+
+ setup.ebot.ds = spu_sub(setup.vmid->data[0], setup.vmin->data[0]);
+ setup.emaj.ds = spu_sub(setup.vmax->data[0], setup.vmin->data[0]);
+ setup.etop.ds = spu_sub(setup.vmax->data[0], setup.vmid->data[0]);
+
+ /*
+ * Compute triangle's area. Use 1/area to compute partial
+ * derivatives of attributes later.
+ */
+ area = setup.emaj.dx * setup.ebot.dy - setup.ebot.dx * setup.emaj.dy;
+
+ setup.oneOverArea = 1.0f / area;
+
+ /* The product of area * sign indicates front/back orientation (0/1).
+ * Just in case someone gets the bright idea of switching the front
+ * and back constants without noticing that we're assuming their
+ * values in this operation, also assert that the values are
+ * what we think they are.
+ */
+ ASSERT(CELL_FACING_FRONT == 0);
+ ASSERT(CELL_FACING_BACK == 1);
+ setup.facing = (area * sign > 0.0f)
+ ^ (spu.rasterizer.front_winding == PIPE_WINDING_CW);
+
+ return TRUE;
+}
+
+
+/**
+ * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
+ * The value value comes from vertex->data[slot].
+ * The result will be put into setup.coef[slot].a0.
+ * \param slot which attribute slot
+ */
+static INLINE void
+const_coeff4(uint slot)
+{
+ setup.coef[slot].dadx = (vector float) {0.0, 0.0, 0.0, 0.0};
+ setup.coef[slot].dady = (vector float) {0.0, 0.0, 0.0, 0.0};
+ setup.coef[slot].a0 = setup.vprovoke->data[slot];
+}
+
+
+/**
+ * As above, but interp setup all four vector components.
+ */
+static INLINE void
+tri_linear_coeff4(uint slot)
+{
+ const vector float vmin_d = setup.vmin->data[slot];
+ const vector float vmid_d = setup.vmid->data[slot];
+ const vector float vmax_d = setup.vmax->data[slot];
+ const vector float xxxx = spu_splats(spu_extract(setup.vmin->data[0], 0) - 0.5f);
+ const vector float yyyy = spu_splats(spu_extract(setup.vmin->data[0], 1) - 0.5f);
+
+ vector float botda = vmid_d - vmin_d;
+ vector float majda = vmax_d - vmin_d;
+
+ vector float a = spu_sub(spu_mul(spu_splats(setup.ebot.dy), majda),
+ spu_mul(botda, spu_splats(setup.emaj.dy)));
+ vector float b = spu_sub(spu_mul(spu_splats(setup.emaj.dx), botda),
+ spu_mul(majda, spu_splats(setup.ebot.dx)));
+
+ setup.coef[slot].dadx = spu_mul(a, spu_splats(setup.oneOverArea));
+ setup.coef[slot].dady = spu_mul(b, spu_splats(setup.oneOverArea));
+
+ vector float tempx = spu_mul(setup.coef[slot].dadx, xxxx);
+ vector float tempy = spu_mul(setup.coef[slot].dady, yyyy);
+
+ setup.coef[slot].a0 = spu_sub(vmin_d, spu_add(tempx, tempy));
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a triangle.
+ * We basically multiply the vertex value by 1/w before computing
+ * the plane coefficients (a0, dadx, dady).
+ * Later, when we compute the value at a particular fragment position we'll
+ * divide the interpolated value by the interpolated W at that fragment.
+ */
+static void
+tri_persp_coeff4(uint slot)
+{
+ const vector float xxxx = spu_splats(spu_extract(setup.vmin->data[0], 0) - 0.5f);
+ const vector float yyyy = spu_splats(spu_extract(setup.vmin->data[0], 1) - 0.5f);
+
+ const vector float vmin_w = spu_splats(spu_extract(setup.vmin->data[0], 3));
+ const vector float vmid_w = spu_splats(spu_extract(setup.vmid->data[0], 3));
+ const vector float vmax_w = spu_splats(spu_extract(setup.vmax->data[0], 3));
+
+ vector float vmin_d = setup.vmin->data[slot];
+ vector float vmid_d = setup.vmid->data[slot];
+ vector float vmax_d = setup.vmax->data[slot];
+
+ vmin_d = spu_mul(vmin_d, vmin_w);
+ vmid_d = spu_mul(vmid_d, vmid_w);
+ vmax_d = spu_mul(vmax_d, vmax_w);
+
+ vector float botda = vmid_d - vmin_d;
+ vector float majda = vmax_d - vmin_d;
+
+ vector float a = spu_sub(spu_mul(spu_splats(setup.ebot.dy), majda),
+ spu_mul(botda, spu_splats(setup.emaj.dy)));
+ vector float b = spu_sub(spu_mul(spu_splats(setup.emaj.dx), botda),
+ spu_mul(majda, spu_splats(setup.ebot.dx)));
+
+ setup.coef[slot].dadx = spu_mul(a, spu_splats(setup.oneOverArea));
+ setup.coef[slot].dady = spu_mul(b, spu_splats(setup.oneOverArea));
+
+ vector float tempx = spu_mul(setup.coef[slot].dadx, xxxx);
+ vector float tempy = spu_mul(setup.coef[slot].dady, yyyy);
+
+ setup.coef[slot].a0 = spu_sub(vmin_d, spu_add(tempx, tempy));
+}
+
+
+
+/**
+ * Compute the setup.coef[] array dadx, dady, a0 values.
+ * Must be called after setup.vmin,vmid,vmax,vprovoke are initialized.
+ */
+static void
+setup_tri_coefficients(void)
+{
+ uint i;
+
+ for (i = 0; i < spu.vertex_info.num_attribs; i++) {
+ switch (spu.vertex_info.attrib[i].interp_mode) {
+ case INTERP_NONE:
+ break;
+ case INTERP_CONSTANT:
+ const_coeff4(i);
+ break;
+ case INTERP_POS:
+ /* fall-through */
+ case INTERP_LINEAR:
+ tri_linear_coeff4(i);
+ break;
+ case INTERP_PERSPECTIVE:
+ tri_persp_coeff4(i);
+ break;
+ default:
+ ASSERT(0);
+ }
+ }
+}
+
+
+static void
+setup_tri_edges(void)
+{
+ float vmin_x = spu_extract(setup.vmin->data[0], 0) + 0.5f;
+ float vmid_x = spu_extract(setup.vmid->data[0], 0) + 0.5f;
+
+ float vmin_y = spu_extract(setup.vmin->data[0], 1) - 0.5f;
+ float vmid_y = spu_extract(setup.vmid->data[0], 1) - 0.5f;
+ float vmax_y = spu_extract(setup.vmax->data[0], 1) - 0.5f;
+
+ setup.emaj.sy = CEILF(vmin_y);
+ setup.emaj.lines = (int) CEILF(vmax_y - setup.emaj.sy);
+ setup.emaj.dxdy = setup.emaj.dx / setup.emaj.dy;
+ setup.emaj.sx = vmin_x + (setup.emaj.sy - vmin_y) * setup.emaj.dxdy;
+
+ setup.etop.sy = CEILF(vmid_y);
+ setup.etop.lines = (int) CEILF(vmax_y - setup.etop.sy);
+ setup.etop.dxdy = setup.etop.dx / setup.etop.dy;
+ setup.etop.sx = vmid_x + (setup.etop.sy - vmid_y) * setup.etop.dxdy;
+
+ setup.ebot.sy = CEILF(vmin_y);
+ setup.ebot.lines = (int) CEILF(vmid_y - setup.ebot.sy);
+ setup.ebot.dxdy = setup.ebot.dx / setup.ebot.dy;
+ setup.ebot.sx = vmin_x + (setup.ebot.sy - vmin_y) * setup.ebot.dxdy;
+}
+
+
+/**
+ * Render the upper or lower half of a triangle.
+ * Scissoring/cliprect is applied here too.
+ */
+static void
+subtriangle(struct edge *eleft, struct edge *eright, unsigned lines)
+{
+ const int minx = setup.cliprect_minx;
+ const int maxx = setup.cliprect_maxx;
+ const int miny = setup.cliprect_miny;
+ const int maxy = setup.cliprect_maxy;
+ int y, start_y, finish_y;
+ int sy = (int)eleft->sy;
+
+ ASSERT((int)eleft->sy == (int) eright->sy);
+
+ /* clip top/bottom */
+ start_y = sy;
+ finish_y = sy + lines;
+
+ if (start_y < miny)
+ start_y = miny;
+
+ if (finish_y > maxy)
+ finish_y = maxy;
+
+ start_y -= sy;
+ finish_y -= sy;
+
+ /*
+ _mesa_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
+ */
+
+ for (y = start_y; y < finish_y; y++) {
+
+ /* avoid accumulating adds as floats don't have the precision to
+ * accurately iterate large triangle edges that way. luckily we
+ * can just multiply these days.
+ *
+ * this is all drowned out by the attribute interpolation anyway.
+ */
+ int left = (int)(eleft->sx + y * eleft->dxdy);
+ int right = (int)(eright->sx + y * eright->dxdy);
+
+ /* clip left/right */
+ if (left < minx)
+ left = minx;
+ if (right > maxx)
+ right = maxx;
+
+ if (left < right) {
+ int _y = sy + y;
+ if (block(_y) != setup.span.y) {
+ flush_spans();
+ setup.span.y = block(_y);
+ }
+
+ int offset = _y&1;
+ vec_int4 quad_LlRr = {left, left, right, right};
+ /* Store left and right in 0 or 1 row of quad based on offset */
+ setup.span.quad = spu_sel(quad_LlRr, setup.span.quad, spu_maskw(5<<offset));
+ setup.span.y_flags |= 1<<offset;
+ }
+ }
+
+
+ /* save the values so that emaj can be restarted:
+ */
+ eleft->sx += lines * eleft->dxdy;
+ eright->sx += lines * eright->dxdy;
+ eleft->sy += lines;
+ eright->sy += lines;
+}
+
+
+/**
+ * Draw triangle into tile at (tx, ty) (tile coords)
+ * The tile data should have already been fetched.
+ */
+boolean
+tri_draw(const qword vs,
+ uint tx, uint ty)
+{
+ setup.tx = tx;
+ setup.ty = ty;
+
+ /* set clipping bounds to tile bounds */
+ const qword clipbase = (qword)((vec_uint4){tx, ty});
+ const qword clipmin = si_mpyui(clipbase, TILE_SIZE);
+ const qword clipmax = si_ai(clipmin, TILE_SIZE);
+ setup.cliprect = si_shufb(clipmin, clipmax, SHUFB4(A,B,a,b));
+
+ if(!setup_sort_vertices(vs)) {
+ return FALSE; /* totally clipped */
+ }
+
+ setup_tri_coefficients();
+ setup_tri_edges();
+
+ setup.span.y = 0;
+ setup.span.y_flags = 0;
+ /* Zero right elements */
+ setup.span.quad = spu_shuffle(setup.span.quad, setup.span.quad, SHUFFLE4(A,B,0,0));
+
+ if (setup.oneOverArea < 0.0) {
+ /* emaj on left */
+ subtriangle( &setup.emaj, &setup.ebot, setup.ebot.lines );
+ subtriangle( &setup.emaj, &setup.etop, setup.etop.lines );
+ }
+ else {
+ /* emaj on right */
+ subtriangle( &setup.ebot, &setup.emaj, setup.ebot.lines );
+ subtriangle( &setup.etop, &setup.emaj, setup.etop.lines );
+ }
+
+ flush_spans();
+
+ return TRUE;
+}
diff --git a/src/gallium/drivers/cell/spu/spu_tri.h b/src/gallium/drivers/cell/spu/spu_tri.h
new file mode 100644
index 0000000000..82e3b19ad7
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_tri.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef SPU_TRI_H
+#define SPU_TRI_H
+
+
+extern boolean
+tri_draw(const qword vs, uint tx, uint ty);
+
+
+#endif /* SPU_TRI_H */
diff --git a/src/gallium/drivers/cell/spu/spu_util.c b/src/gallium/drivers/cell/spu/spu_util.c
new file mode 100644
index 0000000000..af25dd3718
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_util.c
@@ -0,0 +1,167 @@
+
+#include "cell/common.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_debug.h"
+#include "tgsi/tgsi_parse.h"
+//#include "tgsi_build.h"
+#include "tgsi/tgsi_util.h"
+
+unsigned
+tgsi_util_get_src_register_swizzle(
+ const struct tgsi_src_register *reg,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ return reg->SwizzleX;
+ case 1:
+ return reg->SwizzleY;
+ case 2:
+ return reg->SwizzleZ;
+ case 3:
+ return reg->SwizzleW;
+ default:
+ ASSERT( 0 );
+ }
+ return 0;
+}
+
+unsigned
+tgsi_util_get_src_register_extswizzle(
+ const struct tgsi_src_register_ext_swz *reg,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ return reg->ExtSwizzleX;
+ case 1:
+ return reg->ExtSwizzleY;
+ case 2:
+ return reg->ExtSwizzleZ;
+ case 3:
+ return reg->ExtSwizzleW;
+ default:
+ ASSERT( 0 );
+ }
+ return 0;
+}
+
+unsigned
+tgsi_util_get_full_src_register_extswizzle(
+ const struct tgsi_full_src_register *reg,
+ unsigned component )
+{
+ unsigned swizzle;
+
+ /*
+ * First, calculate the extended swizzle for a given channel. This will give
+ * us either a channel index into the simple swizzle or a constant 1 or 0.
+ */
+ swizzle = tgsi_util_get_src_register_extswizzle(
+ &reg->SrcRegisterExtSwz,
+ component );
+
+ ASSERT (TGSI_SWIZZLE_X == TGSI_EXTSWIZZLE_X);
+ ASSERT (TGSI_SWIZZLE_Y == TGSI_EXTSWIZZLE_Y);
+ ASSERT (TGSI_SWIZZLE_Z == TGSI_EXTSWIZZLE_Z);
+ ASSERT (TGSI_SWIZZLE_W == TGSI_EXTSWIZZLE_W);
+ ASSERT (TGSI_EXTSWIZZLE_ZERO > TGSI_SWIZZLE_W);
+ ASSERT (TGSI_EXTSWIZZLE_ONE > TGSI_SWIZZLE_W);
+
+ /*
+ * Second, calculate the simple swizzle for the unswizzled channel index.
+ * Leave the constants intact, they are not affected by the simple swizzle.
+ */
+ if( swizzle <= TGSI_SWIZZLE_W ) {
+ swizzle = tgsi_util_get_src_register_swizzle(
+ &reg->SrcRegister,
+ component );
+ }
+
+ return swizzle;
+}
+
+unsigned
+tgsi_util_get_src_register_extnegate(
+ const struct tgsi_src_register_ext_swz *reg,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ return reg->NegateX;
+ case 1:
+ return reg->NegateY;
+ case 2:
+ return reg->NegateZ;
+ case 3:
+ return reg->NegateW;
+ default:
+ ASSERT( 0 );
+ }
+ return 0;
+}
+
+void
+tgsi_util_set_src_register_extnegate(
+ struct tgsi_src_register_ext_swz *reg,
+ unsigned negate,
+ unsigned component )
+{
+ switch( component ) {
+ case 0:
+ reg->NegateX = negate;
+ break;
+ case 1:
+ reg->NegateY = negate;
+ break;
+ case 2:
+ reg->NegateZ = negate;
+ break;
+ case 3:
+ reg->NegateW = negate;
+ break;
+ default:
+ ASSERT( 0 );
+ }
+}
+
+unsigned
+tgsi_util_get_full_src_register_sign_mode(
+ const struct tgsi_full_src_register *reg,
+ unsigned component )
+{
+ unsigned sign_mode;
+
+ if( reg->SrcRegisterExtMod.Absolute ) {
+ /* Consider only the post-abs negation. */
+
+ if( reg->SrcRegisterExtMod.Negate ) {
+ sign_mode = TGSI_UTIL_SIGN_SET;
+ }
+ else {
+ sign_mode = TGSI_UTIL_SIGN_CLEAR;
+ }
+ }
+ else {
+ /* Accumulate the three negations. */
+
+ unsigned negate;
+
+ negate = reg->SrcRegister.Negate;
+ if( tgsi_util_get_src_register_extnegate( &reg->SrcRegisterExtSwz, component ) ) {
+ negate = !negate;
+ }
+ if( reg->SrcRegisterExtMod.Negate ) {
+ negate = !negate;
+ }
+
+ if( negate ) {
+ sign_mode = TGSI_UTIL_SIGN_TOGGLE;
+ }
+ else {
+ sign_mode = TGSI_UTIL_SIGN_KEEP;
+ }
+ }
+
+ return sign_mode;
+}
diff --git a/src/gallium/drivers/cell/spu/spu_vertex_fetch.c b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c
new file mode 100644
index 0000000000..03375d84a5
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c
@@ -0,0 +1,145 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+#include "spu_exec.h"
+#include "spu_vertex_shader.h"
+#include "spu_main.h"
+#include "spu_dcache.h"
+
+typedef void (*spu_fetch_func)(qword *out, const qword *in,
+ const qword *shuffle_data);
+
+
+static const qword fetch_shuffle_data[5] ALIGN16_ATTRIB = {
+ /* Shuffle used by CVT_64_FLOAT
+ */
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ },
+
+ /* Shuffle used by CVT_8_USCALED and CVT_8_SSCALED
+ */
+ {
+ 0x00, 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80,
+ 0x02, 0x80, 0x80, 0x80, 0x03, 0x80, 0x80, 0x80,
+ },
+
+ /* Shuffle used by CVT_16_USCALED and CVT_16_SSCALED
+ */
+ {
+ 0x00, 0x01, 0x80, 0x80, 0x02, 0x03, 0x80, 0x80,
+ 0x04, 0x05, 0x80, 0x80, 0x06, 0x07, 0x80, 0x80,
+ },
+
+ /* High value shuffle used by trans4x4.
+ */
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17
+ },
+
+ /* Low value shuffle used by trans4x4.
+ */
+ {
+ 0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F
+ }
+};
+
+
+/**
+ * Fetch vertex attributes for 'count' vertices.
+ */
+static void generic_vertex_fetch(struct spu_vs_context *draw,
+ struct spu_exec_machine *machine,
+ const unsigned *elts,
+ unsigned count)
+{
+ unsigned nr_attrs = draw->vertex_fetch.nr_attrs;
+ unsigned attr;
+
+ ASSERT(count <= 4);
+
+#if DRAW_DBG
+ printf("SPU: %s count = %u, nr_attrs = %u\n",
+ __FUNCTION__, count, nr_attrs);
+#endif
+
+ /* loop over vertex attributes (vertex shader inputs)
+ */
+ for (attr = 0; attr < nr_attrs; attr++) {
+ const unsigned pitch = draw->vertex_fetch.pitch[attr];
+ const uint64_t src = draw->vertex_fetch.src_ptr[attr];
+ const spu_fetch_func fetch = (spu_fetch_func)
+ (draw->vertex_fetch.code + draw->vertex_fetch.code_offset[attr]);
+ unsigned i;
+ unsigned idx;
+ const unsigned bytes_per_entry = draw->vertex_fetch.size[attr];
+ const unsigned quads_per_entry = (bytes_per_entry + 15) / 16;
+ qword in[2 * 4] ALIGN16_ATTRIB;
+
+
+ /* Fetch four attributes for four vertices.
+ */
+ idx = 0;
+ for (i = 0; i < count; i++) {
+ const uint64_t addr = src + (elts[i] * pitch);
+
+#if DRAW_DBG
+ printf("SPU: fetching = 0x%llx\n", addr);
+#endif
+
+ spu_dcache_fetch_unaligned(& in[idx], addr, bytes_per_entry);
+ idx += quads_per_entry;
+ }
+
+ /* Be nice and zero out any missing vertices.
+ */
+ (void) memset(& in[idx], 0, (8 - idx) * sizeof(qword));
+
+
+ /* Convert all 4 vertices to vectors of float.
+ */
+ (*fetch)(&machine->Inputs[attr].xyzw[0].q, in, fetch_shuffle_data);
+ }
+}
+
+
+void spu_update_vertex_fetch( struct spu_vs_context *draw )
+{
+ draw->vertex_fetch.fetch_func = generic_vertex_fetch;
+}
diff --git a/src/gallium/drivers/cell/spu/spu_vertex_shader.c b/src/gallium/drivers/cell/spu/spu_vertex_shader.c
new file mode 100644
index 0000000000..fbe5b34d39
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_vertex_shader.c
@@ -0,0 +1,244 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ * Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <spu_mfcio.h>
+
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "draw/draw_private.h"
+#include "draw/draw_context.h"
+#include "cell/common.h"
+#include "spu_vertex_shader.h"
+#include "spu_exec.h"
+#include "spu_main.h"
+
+
+#define MAX_VERTEX_SIZE ((2 + PIPE_MAX_SHADER_OUTPUTS) * 4 * sizeof(float))
+
+
+#define CLIP_RIGHT_BIT 0x01
+#define CLIP_LEFT_BIT 0x02
+#define CLIP_TOP_BIT 0x04
+#define CLIP_BOTTOM_BIT 0x08
+#define CLIP_FAR_BIT 0x10
+#define CLIP_NEAR_BIT 0x20
+
+
+static INLINE float
+dot4(const float *a, const float *b)
+{
+ return (a[0]*b[0] +
+ a[1]*b[1] +
+ a[2]*b[2] +
+ a[3]*b[3]);
+}
+
+static INLINE unsigned
+compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
+{
+ unsigned mask = 0;
+ unsigned i;
+
+ /* Do the hardwired planes first:
+ */
+ if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
+ if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
+ if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
+ if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
+ if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
+ if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
+
+ /* Followed by any remaining ones:
+ */
+ for (i = 6; i < nr; i++) {
+ if (dot4(clip, plane[i]) < 0)
+ mask |= (1<<i);
+ }
+
+ return mask;
+}
+
+
+/**
+ * Transform vertices with the current vertex program/shader
+ * Up to four vertices can be shaded at a time.
+ * \param vbuffer the input vertex data
+ * \param elts indexes of four input vertices
+ * \param count number of vertices to shade [1..4]
+ * \param vOut array of pointers to four output vertices
+ */
+static void
+run_vertex_program(struct spu_vs_context *draw,
+ unsigned elts[4], unsigned count,
+ const uint64_t *vOut)
+{
+ struct spu_exec_machine *machine = &draw->machine;
+ unsigned int j;
+
+ ALIGN16_DECL(struct spu_exec_vector, inputs, PIPE_MAX_ATTRIBS);
+ ALIGN16_DECL(struct spu_exec_vector, outputs, PIPE_MAX_ATTRIBS);
+ const float *scale = draw->viewport.scale;
+ const float *trans = draw->viewport.translate;
+
+ ASSERT(count <= 4);
+
+ machine->Processor = TGSI_PROCESSOR_VERTEX;
+
+ ASSERT_ALIGN16(draw->constants);
+ machine->Consts = (float (*)[4]) draw->constants;
+
+ machine->Inputs = ALIGN16_ASSIGN(inputs);
+ machine->Outputs = ALIGN16_ASSIGN(outputs);
+
+ spu_vertex_fetch( draw, machine, elts, count );
+
+ /* run shader */
+ spu_exec_machine_run( machine );
+
+
+ /* store machine results */
+ for (j = 0; j < count; j++) {
+ unsigned slot;
+ float x, y, z, w;
+ unsigned char buffer[sizeof(struct vertex_header)
+ + MAX_VERTEX_SIZE] ALIGN16_ATTRIB;
+ struct vertex_header *const tmpOut =
+ (struct vertex_header *) buffer;
+ const unsigned vert_size = ROUNDUP16(sizeof(struct vertex_header)
+ + (sizeof(float) * 4
+ * draw->num_vs_outputs));
+
+ mfc_get(tmpOut, vOut[j], vert_size, TAG_VERTEX_BUFFER, 0, 0);
+ wait_on_mask(1 << TAG_VERTEX_BUFFER);
+
+
+ /* Handle attr[0] (position) specially:
+ *
+ * XXX: Computing the clipmask should be done in the vertex
+ * program as a set of DP4 instructions appended to the
+ * user-provided code.
+ */
+ x = tmpOut->clip[0] = machine->Outputs[0].xyzw[0].f[j];
+ y = tmpOut->clip[1] = machine->Outputs[0].xyzw[1].f[j];
+ z = tmpOut->clip[2] = machine->Outputs[0].xyzw[2].f[j];
+ w = tmpOut->clip[3] = machine->Outputs[0].xyzw[3].f[j];
+
+ tmpOut->clipmask = compute_clipmask(tmpOut->clip, draw->plane,
+ draw->nr_planes);
+ tmpOut->edgeflag = 1;
+
+ /* divide by w */
+ w = 1.0f / w;
+ x *= w;
+ y *= w;
+ z *= w;
+
+ /* Viewport mapping */
+ tmpOut->data[0][0] = x * scale[0] + trans[0];
+ tmpOut->data[0][1] = y * scale[1] + trans[1];
+ tmpOut->data[0][2] = z * scale[2] + trans[2];
+ tmpOut->data[0][3] = w;
+
+ /* Remaining attributes are packed into sequential post-transform
+ * vertex attrib slots.
+ */
+ for (slot = 1; slot < draw->num_vs_outputs; slot++) {
+ tmpOut->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
+ tmpOut->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
+ tmpOut->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
+ tmpOut->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
+ }
+
+ mfc_put(tmpOut, vOut[j], vert_size, TAG_VERTEX_BUFFER, 0, 0);
+ } /* loop over vertices */
+}
+
+
+unsigned char immediates[(sizeof(float) * 4 * TGSI_EXEC_NUM_IMMEDIATES) + 32]
+ ALIGN16_ATTRIB;
+
+
+void
+spu_bind_vertex_shader(struct spu_vs_context *draw,
+ struct cell_shader_info *vs)
+{
+ const unsigned immediate_addr = vs->immediates;
+ const unsigned immediate_size =
+ ROUNDUP16((sizeof(float) * 4 * vs->num_immediates)
+ + (immediate_addr & 0x0f));
+
+
+ mfc_get(immediates, immediate_addr & ~0x0f, immediate_size,
+ TAG_VERTEX_BUFFER, 0, 0);
+
+ draw->machine.Instructions = (struct tgsi_full_instruction *)
+ vs->instructions;
+ draw->machine.NumInstructions = vs->num_instructions;
+
+ draw->machine.Declarations = (struct tgsi_full_declaration *)
+ vs->declarations;
+ draw->machine.NumDeclarations = vs->num_declarations;
+
+ draw->num_vs_outputs = vs->num_outputs;
+
+ /* specify the shader to interpret/execute */
+ spu_exec_machine_init(&draw->machine,
+ PIPE_MAX_SAMPLERS,
+ NULL /*samplers*/,
+ PIPE_SHADER_VERTEX);
+
+ wait_on_mask(1 << TAG_VERTEX_BUFFER);
+
+ (void) memcpy(& draw->machine.Imms, &immediates[immediate_addr & 0x0f],
+ sizeof(float) * 4 * vs->num_immediates);
+}
+
+
+void
+spu_execute_vertex_shader(struct spu_vs_context *draw,
+ const struct cell_command_vs *vs)
+{
+ unsigned i;
+
+ (void) memcpy(draw->plane, vs->plane, sizeof(float) * 4 * vs->nr_planes);
+ draw->nr_planes = vs->nr_planes;
+ draw->vertex_fetch.nr_attrs = vs->nr_attrs;
+
+ for (i = 0; i < vs->num_elts; i += 4) {
+ const unsigned batch_size = MIN2(vs->num_elts - i, 4);
+
+ run_vertex_program(draw, & vs->elts[i], batch_size, &vs->vOut[i]);
+ }
+}
diff --git a/src/gallium/drivers/cell/spu/spu_vertex_shader.h b/src/gallium/drivers/cell/spu/spu_vertex_shader.h
new file mode 100644
index 0000000000..4c74f5e74d
--- /dev/null
+++ b/src/gallium/drivers/cell/spu/spu_vertex_shader.h
@@ -0,0 +1,66 @@
+#ifndef SPU_VERTEX_SHADER_H
+#define SPU_VERTEX_SHADER_H
+
+#include "cell/common.h"
+#include "pipe/p_format.h"
+#include "spu_exec.h"
+
+struct spu_vs_context;
+
+typedef void (*spu_full_fetch_func)( struct spu_vs_context *draw,
+ struct spu_exec_machine *machine,
+ const unsigned *elts,
+ unsigned count );
+
+struct spu_vs_context {
+ struct pipe_viewport_state viewport;
+
+ struct {
+ uint64_t src_ptr[PIPE_MAX_ATTRIBS];
+ unsigned pitch[PIPE_MAX_ATTRIBS];
+ unsigned size[PIPE_MAX_ATTRIBS];
+ unsigned code_offset[PIPE_MAX_ATTRIBS];
+ unsigned nr_attrs;
+ boolean dirty;
+
+ spu_full_fetch_func fetch_func;
+ void *code;
+ } vertex_fetch;
+
+ /* Clip derived state:
+ */
+ float plane[12][4];
+ unsigned nr_planes;
+
+ struct spu_exec_machine machine;
+ const float (*constants)[4];
+
+ unsigned num_vs_outputs;
+};
+
+extern void spu_update_vertex_fetch(struct spu_vs_context *draw);
+
+static INLINE void spu_vertex_fetch(struct spu_vs_context *draw,
+ struct spu_exec_machine *machine,
+ const unsigned *elts,
+ unsigned count)
+{
+ if (draw->vertex_fetch.dirty) {
+ spu_update_vertex_fetch(draw);
+ draw->vertex_fetch.dirty = 0;
+ }
+
+ (*draw->vertex_fetch.fetch_func)(draw, machine, elts, count);
+}
+
+struct cell_command_vs;
+
+extern void
+spu_bind_vertex_shader(struct spu_vs_context *draw,
+ struct cell_shader_info *vs);
+
+extern void
+spu_execute_vertex_shader(struct spu_vs_context *draw,
+ const struct cell_command_vs *vs);
+
+#endif /* SPU_VERTEX_SHADER_H */
diff --git a/src/gallium/drivers/failover/Makefile b/src/gallium/drivers/failover/Makefile
new file mode 100644
index 0000000000..dfb7f5dcf6
--- /dev/null
+++ b/src/gallium/drivers/failover/Makefile
@@ -0,0 +1,11 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = failover
+
+C_SOURCES = \
+ fo_state.c \
+ fo_state_emit.c \
+ fo_context.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/failover/SConscript b/src/gallium/drivers/failover/SConscript
new file mode 100644
index 0000000000..f8e9b1b491
--- /dev/null
+++ b/src/gallium/drivers/failover/SConscript
@@ -0,0 +1,13 @@
+Import('*')
+
+env = env.Clone()
+
+failover = env.ConvenienceLibrary(
+ target = 'failover',
+ source = [
+ 'fo_state.c',
+ 'fo_state_emit.c',
+ 'fo_context.c',
+ ])
+
+Export('failover')
diff --git a/src/gallium/drivers/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c
new file mode 100644
index 0000000000..37184eac7b
--- /dev/null
+++ b/src/gallium/drivers/failover/fo_context.c
@@ -0,0 +1,182 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_memory.h"
+#include "pipe/p_context.h"
+
+#include "fo_context.h"
+#include "fo_winsys.h"
+
+
+
+static void failover_destroy( struct pipe_context *pipe )
+{
+ struct failover_context *failover = failover_context( pipe );
+
+ free( failover );
+}
+
+
+
+static boolean failover_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count)
+{
+ struct failover_context *failover = failover_context( pipe );
+
+ /* If there has been any statechange since last time, try hardware
+ * rendering again:
+ */
+ if (failover->dirty) {
+ failover->mode = FO_HW;
+ }
+
+ /* Try hardware:
+ */
+ if (failover->mode == FO_HW) {
+ if (!failover->hw->draw_elements( failover->hw,
+ indexBuffer,
+ indexSize,
+ prim,
+ start,
+ count )) {
+
+ failover->hw->flush( failover->hw, ~0, NULL );
+ failover->mode = FO_SW;
+ }
+ }
+
+ /* Possibly try software:
+ */
+ if (failover->mode == FO_SW) {
+
+ if (failover->dirty)
+ failover_state_emit( failover );
+
+ failover->sw->draw_elements( failover->sw,
+ indexBuffer,
+ indexSize,
+ prim,
+ start,
+ count );
+
+ /* Be ready to switch back to hardware rendering without an
+ * intervening flush. Unlikely to be much performance impact to
+ * this:
+ */
+ failover->sw->flush( failover->sw, ~0, NULL );
+ }
+
+ return TRUE;
+}
+
+
+static boolean failover_draw_arrays( struct pipe_context *pipe,
+ unsigned prim, unsigned start, unsigned count)
+{
+ return failover_draw_elements(pipe, NULL, 0, prim, start, count);
+}
+
+static unsigned int
+failover_is_texture_referenced( struct pipe_context *_pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ struct failover_context *failover = failover_context( _pipe );
+ struct pipe_context *pipe = (failover->mode == FO_HW) ?
+ failover->hw : failover->sw;
+
+ return pipe->is_texture_referenced(pipe, texture, face, level);
+}
+
+static unsigned int
+failover_is_buffer_referenced( struct pipe_context *_pipe,
+ struct pipe_buffer *buf)
+{
+ struct failover_context *failover = failover_context( _pipe );
+ struct pipe_context *pipe = (failover->mode == FO_HW) ?
+ failover->hw : failover->sw;
+
+ return pipe->is_buffer_referenced(pipe, buf);
+}
+
+struct pipe_context *failover_create( struct pipe_context *hw,
+ struct pipe_context *sw )
+{
+ struct failover_context *failover = CALLOC_STRUCT(failover_context);
+ if (failover == NULL)
+ return NULL;
+
+ failover->hw = hw;
+ failover->sw = sw;
+ failover->pipe.winsys = hw->winsys;
+ failover->pipe.screen = hw->screen;
+ failover->pipe.destroy = failover_destroy;
+#if 0
+ failover->pipe.is_format_supported = hw->is_format_supported;
+ failover->pipe.get_name = hw->get_name;
+ failover->pipe.get_vendor = hw->get_vendor;
+ failover->pipe.get_param = hw->get_param;
+ failover->pipe.get_paramf = hw->get_paramf;
+#endif
+
+ failover->pipe.draw_arrays = failover_draw_arrays;
+ failover->pipe.draw_elements = failover_draw_elements;
+ failover->pipe.clear = hw->clear;
+
+ /* No software occlusion fallback (or other optional functionality)
+ * at this point - if the hardware doesn't support it, don't
+ * advertise it to the application.
+ */
+ failover->pipe.begin_query = hw->begin_query;
+ failover->pipe.end_query = hw->end_query;
+
+ failover_init_state_functions( failover );
+
+ failover->pipe.surface_copy = hw->surface_copy;
+ failover->pipe.surface_fill = hw->surface_fill;
+
+#if 0
+ failover->pipe.texture_create = hw->texture_create;
+ failover->pipe.texture_destroy = hw->texture_destroy;
+ failover->pipe.get_tex_surface = hw->get_tex_surface;
+ failover->pipe.texture_update = hw->texture_update;
+#endif
+
+ failover->pipe.flush = hw->flush;
+ failover->pipe.is_texture_referenced = failover_is_texture_referenced;
+ failover->pipe.is_buffer_referenced = failover_is_buffer_referenced;
+
+ failover->dirty = 0;
+
+ return &failover->pipe;
+}
+
diff --git a/src/gallium/drivers/failover/fo_context.h b/src/gallium/drivers/failover/fo_context.h
new file mode 100644
index 0000000000..9ba86ba866
--- /dev/null
+++ b/src/gallium/drivers/failover/fo_context.h
@@ -0,0 +1,125 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef FO_CONTEXT_H
+#define FO_CONTEXT_H
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+
+
+
+#define FO_NEW_VIEWPORT 0x1
+#define FO_NEW_RASTERIZER 0x2
+#define FO_NEW_FRAGMENT_SHADER 0x4
+#define FO_NEW_BLEND 0x8
+#define FO_NEW_CLIP 0x10
+#define FO_NEW_SCISSOR 0x20
+#define FO_NEW_STIPPLE 0x40
+#define FO_NEW_FRAMEBUFFER 0x80
+#define FO_NEW_ALPHA_TEST 0x100
+#define FO_NEW_DEPTH_STENCIL 0x200
+#define FO_NEW_SAMPLER 0x400
+#define FO_NEW_TEXTURE 0x800
+#define FO_NEW_VERTEX 0x2000
+#define FO_NEW_VERTEX_SHADER 0x4000
+#define FO_NEW_BLEND_COLOR 0x8000
+#define FO_NEW_CLEAR_COLOR 0x10000
+#define FO_NEW_VERTEX_BUFFER 0x20000
+#define FO_NEW_VERTEX_ELEMENT 0x40000
+
+
+
+#define FO_HW 0
+#define FO_SW 1
+
+struct fo_state {
+ void *sw_state;
+ void *hw_state;
+};
+struct failover_context {
+ struct pipe_context pipe; /**< base class */
+
+
+ /* The most recent drawing state as set by the driver:
+ */
+ const struct fo_state *blend;
+ const struct fo_state *sampler[PIPE_MAX_SAMPLERS];
+ const struct fo_state *depth_stencil;
+ const struct fo_state *rasterizer;
+ const struct fo_state *fragment_shader;
+ const struct fo_state *vertex_shader;
+
+ struct pipe_blend_color blend_color;
+ struct pipe_clip_state clip;
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_poly_stipple poly_stipple;
+ struct pipe_scissor_state scissor;
+ struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
+ struct pipe_viewport_state viewport;
+ struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
+ struct pipe_vertex_element vertex_elements[PIPE_MAX_ATTRIBS];
+
+ uint num_vertex_buffers;
+ uint num_vertex_elements;
+
+ void *sw_sampler_state[PIPE_MAX_SAMPLERS];
+ void *hw_sampler_state[PIPE_MAX_SAMPLERS];
+
+ unsigned dirty;
+
+ unsigned num_samplers;
+ unsigned num_textures;
+
+ unsigned mode;
+ struct pipe_context *hw;
+ struct pipe_context *sw;
+};
+
+
+
+void failover_init_state_functions( struct failover_context *failover );
+void failover_state_emit( struct failover_context *failover );
+
+static INLINE struct failover_context *
+failover_context( struct pipe_context *pipe )
+{
+ return (struct failover_context *)pipe;
+}
+
+/* Internal functions
+ */
+void
+failover_set_constant_buffer(struct pipe_context *pipe,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf);
+
+
+#endif /* FO_CONTEXT_H */
diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c
new file mode 100644
index 0000000000..c8eb926299
--- /dev/null
+++ b/src/gallium/drivers/failover/fo_state.c
@@ -0,0 +1,481 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "fo_context.h"
+
+
+/* This looks like a lot of work at the moment - we're keeping a
+ * duplicate copy of the state up-to-date.
+ *
+ * This can change in two ways:
+ * - With constant state objects we would only need to save a pointer,
+ * not the whole object.
+ * - By adding a callback in the state tracker to re-emit state. The
+ * state tracker knows the current state already and can re-emit it
+ * without additional complexity.
+ *
+ * This works as a proof-of-concept, but a final version will have
+ * lower overheads.
+ */
+
+
+
+static void *
+failover_create_blend_state( struct pipe_context *pipe,
+ const struct pipe_blend_state *blend )
+{
+ struct fo_state *state = malloc(sizeof(struct fo_state));
+ struct failover_context *failover = failover_context(pipe);
+
+ state->sw_state = failover->sw->create_blend_state(failover->sw, blend);
+ state->hw_state = failover->hw->create_blend_state(failover->hw, blend);
+
+ return state;
+}
+
+static void
+failover_bind_blend_state( struct pipe_context *pipe,
+ void *blend )
+{
+ struct failover_context *failover = failover_context(pipe);
+ struct fo_state *state = (struct fo_state *)blend;
+ failover->blend = state;
+ failover->dirty |= FO_NEW_BLEND;
+ failover->sw->bind_blend_state( failover->sw, state->sw_state );
+ failover->hw->bind_blend_state( failover->hw, state->hw_state );
+}
+
+static void
+failover_delete_blend_state( struct pipe_context *pipe,
+ void *blend )
+{
+ struct fo_state *state = (struct fo_state*)blend;
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->sw->delete_blend_state(failover->sw, state->sw_state);
+ failover->hw->delete_blend_state(failover->hw, state->hw_state);
+ state->sw_state = 0;
+ state->hw_state = 0;
+ free(state);
+}
+
+static void
+failover_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color )
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->blend_color = *blend_color;
+ failover->dirty |= FO_NEW_BLEND_COLOR;
+ failover->sw->set_blend_color( failover->sw, blend_color );
+ failover->hw->set_blend_color( failover->hw, blend_color );
+}
+
+static void
+failover_set_clip_state( struct pipe_context *pipe,
+ const struct pipe_clip_state *clip )
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->clip = *clip;
+ failover->dirty |= FO_NEW_CLIP;
+ failover->sw->set_clip_state( failover->sw, clip );
+ failover->hw->set_clip_state( failover->hw, clip );
+}
+
+
+static void *
+failover_create_depth_stencil_state(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *templ)
+{
+ struct fo_state *state = malloc(sizeof(struct fo_state));
+ struct failover_context *failover = failover_context(pipe);
+
+ state->sw_state = failover->sw->create_depth_stencil_alpha_state(failover->sw, templ);
+ state->hw_state = failover->hw->create_depth_stencil_alpha_state(failover->hw, templ);
+
+ return state;
+}
+
+static void
+failover_bind_depth_stencil_state(struct pipe_context *pipe,
+ void *depth_stencil)
+{
+ struct failover_context *failover = failover_context(pipe);
+ struct fo_state *state = (struct fo_state *)depth_stencil;
+ failover->depth_stencil = state;
+ failover->dirty |= FO_NEW_DEPTH_STENCIL;
+ failover->sw->bind_depth_stencil_alpha_state(failover->sw, state->sw_state);
+ failover->hw->bind_depth_stencil_alpha_state(failover->hw, state->hw_state);
+}
+
+static void
+failover_delete_depth_stencil_state(struct pipe_context *pipe,
+ void *ds)
+{
+ struct fo_state *state = (struct fo_state*)ds;
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->sw->delete_depth_stencil_alpha_state(failover->sw, state->sw_state);
+ failover->hw->delete_depth_stencil_alpha_state(failover->hw, state->hw_state);
+ state->sw_state = 0;
+ state->hw_state = 0;
+ free(state);
+}
+
+static void
+failover_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *framebuffer)
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->framebuffer = *framebuffer;
+ failover->dirty |= FO_NEW_FRAMEBUFFER;
+ failover->sw->set_framebuffer_state( failover->sw, framebuffer );
+ failover->hw->set_framebuffer_state( failover->hw, framebuffer );
+}
+
+
+static void *
+failover_create_fs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct fo_state *state = malloc(sizeof(struct fo_state));
+ struct failover_context *failover = failover_context(pipe);
+
+ state->sw_state = failover->sw->create_fs_state(failover->sw, templ);
+ state->hw_state = failover->hw->create_fs_state(failover->hw, templ);
+
+ return state;
+}
+
+static void
+failover_bind_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct failover_context *failover = failover_context(pipe);
+ struct fo_state *state = (struct fo_state*)fs;
+ failover->fragment_shader = state;
+ failover->dirty |= FO_NEW_FRAGMENT_SHADER;
+ failover->sw->bind_fs_state(failover->sw, state->sw_state);
+ failover->hw->bind_fs_state(failover->hw, state->hw_state);
+}
+
+static void
+failover_delete_fs_state(struct pipe_context *pipe,
+ void *fs)
+{
+ struct fo_state *state = (struct fo_state*)fs;
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->sw->delete_fs_state(failover->sw, state->sw_state);
+ failover->hw->delete_fs_state(failover->hw, state->hw_state);
+ state->sw_state = 0;
+ state->hw_state = 0;
+ free(state);
+}
+
+static void *
+failover_create_vs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct fo_state *state = malloc(sizeof(struct fo_state));
+ struct failover_context *failover = failover_context(pipe);
+
+ state->sw_state = failover->sw->create_vs_state(failover->sw, templ);
+ state->hw_state = failover->hw->create_vs_state(failover->hw, templ);
+
+ return state;
+}
+
+static void
+failover_bind_vs_state(struct pipe_context *pipe,
+ void *vs)
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ struct fo_state *state = (struct fo_state*)vs;
+ failover->vertex_shader = state;
+ failover->dirty |= FO_NEW_VERTEX_SHADER;
+ failover->sw->bind_vs_state(failover->sw, state->sw_state);
+ failover->hw->bind_vs_state(failover->hw, state->hw_state);
+}
+
+static void
+failover_delete_vs_state(struct pipe_context *pipe,
+ void *vs)
+{
+ struct fo_state *state = (struct fo_state*)vs;
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->sw->delete_vs_state(failover->sw, state->sw_state);
+ failover->hw->delete_vs_state(failover->hw, state->hw_state);
+ state->sw_state = 0;
+ state->hw_state = 0;
+ free(state);
+}
+
+static void
+failover_set_polygon_stipple( struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple )
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->poly_stipple = *stipple;
+ failover->dirty |= FO_NEW_STIPPLE;
+ failover->sw->set_polygon_stipple( failover->sw, stipple );
+ failover->hw->set_polygon_stipple( failover->hw, stipple );
+}
+
+
+static void *
+failover_create_rasterizer_state(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *templ)
+{
+ struct fo_state *state = malloc(sizeof(struct fo_state));
+ struct failover_context *failover = failover_context(pipe);
+
+ state->sw_state = failover->sw->create_rasterizer_state(failover->sw, templ);
+ state->hw_state = failover->hw->create_rasterizer_state(failover->hw, templ);
+
+ return state;
+}
+
+static void
+failover_bind_rasterizer_state(struct pipe_context *pipe,
+ void *raster)
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ struct fo_state *state = (struct fo_state*)raster;
+ failover->rasterizer = state;
+ failover->dirty |= FO_NEW_RASTERIZER;
+ failover->sw->bind_rasterizer_state(failover->sw, state->sw_state);
+ failover->hw->bind_rasterizer_state(failover->hw, state->hw_state);
+}
+
+static void
+failover_delete_rasterizer_state(struct pipe_context *pipe,
+ void *raster)
+{
+ struct fo_state *state = (struct fo_state*)raster;
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->sw->delete_rasterizer_state(failover->sw, state->sw_state);
+ failover->hw->delete_rasterizer_state(failover->hw, state->hw_state);
+ state->sw_state = 0;
+ state->hw_state = 0;
+ free(state);
+}
+
+
+static void
+failover_set_scissor_state( struct pipe_context *pipe,
+ const struct pipe_scissor_state *scissor )
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->scissor = *scissor;
+ failover->dirty |= FO_NEW_SCISSOR;
+ failover->sw->set_scissor_state( failover->sw, scissor );
+ failover->hw->set_scissor_state( failover->hw, scissor );
+}
+
+
+static void *
+failover_create_sampler_state(struct pipe_context *pipe,
+ const struct pipe_sampler_state *templ)
+{
+ struct fo_state *state = malloc(sizeof(struct fo_state));
+ struct failover_context *failover = failover_context(pipe);
+
+ state->sw_state = failover->sw->create_sampler_state(failover->sw, templ);
+ state->hw_state = failover->hw->create_sampler_state(failover->hw, templ);
+
+ return state;
+}
+
+static void
+failover_bind_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **sampler)
+{
+ struct failover_context *failover = failover_context(pipe);
+ struct fo_state *state = (struct fo_state*)sampler;
+ uint i;
+ assert(num <= PIPE_MAX_SAMPLERS);
+ /* Check for no-op */
+ if (num == failover->num_samplers &&
+ !memcmp(failover->sampler, sampler, num * sizeof(void *)))
+ return;
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ failover->sw_sampler_state[i] = i < num ? state[i].sw_state : NULL;
+ failover->hw_sampler_state[i] = i < num ? state[i].hw_state : NULL;
+ }
+ failover->dirty |= FO_NEW_SAMPLER;
+ failover->num_samplers = num;
+ failover->sw->bind_sampler_states(failover->sw, num,
+ failover->sw_sampler_state);
+ failover->hw->bind_sampler_states(failover->hw, num,
+ failover->hw_sampler_state);
+}
+
+static void
+failover_delete_sampler_state(struct pipe_context *pipe, void *sampler)
+{
+ struct fo_state *state = (struct fo_state*)sampler;
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->sw->delete_sampler_state(failover->sw, state->sw_state);
+ failover->hw->delete_sampler_state(failover->hw, state->hw_state);
+ state->sw_state = 0;
+ state->hw_state = 0;
+ free(state);
+}
+
+
+static void
+failover_set_sampler_textures(struct pipe_context *pipe,
+ unsigned num,
+ struct pipe_texture **texture)
+{
+ struct failover_context *failover = failover_context(pipe);
+ uint i;
+
+ assert(num <= PIPE_MAX_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == failover->num_textures &&
+ !memcmp(failover->texture, texture, num * sizeof(struct pipe_texture *)))
+ return;
+ for (i = 0; i < num; i++)
+ pipe_texture_reference((struct pipe_texture **) &failover->texture[i],
+ texture[i]);
+ for (i = num; i < failover->num_textures; i++)
+ pipe_texture_reference((struct pipe_texture **) &failover->texture[i],
+ NULL);
+ failover->dirty |= FO_NEW_TEXTURE;
+ failover->num_textures = num;
+ failover->sw->set_sampler_textures( failover->sw, num, texture );
+ failover->hw->set_sampler_textures( failover->hw, num, texture );
+}
+
+
+static void
+failover_set_viewport_state( struct pipe_context *pipe,
+ const struct pipe_viewport_state *viewport )
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ failover->viewport = *viewport;
+ failover->dirty |= FO_NEW_VIEWPORT;
+ failover->sw->set_viewport_state( failover->sw, viewport );
+ failover->hw->set_viewport_state( failover->hw, viewport );
+}
+
+
+static void
+failover_set_vertex_buffers(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_buffer *vertex_buffers)
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ memcpy(failover->vertex_buffers, vertex_buffers,
+ count * sizeof(vertex_buffers[0]));
+ failover->dirty |= FO_NEW_VERTEX_BUFFER;
+ failover->num_vertex_buffers = count;
+ failover->sw->set_vertex_buffers( failover->sw, count, vertex_buffers );
+ failover->hw->set_vertex_buffers( failover->hw, count, vertex_buffers );
+}
+
+
+static void
+failover_set_vertex_elements(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_element *vertex_elements)
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ memcpy(failover->vertex_elements, vertex_elements,
+ count * sizeof(vertex_elements[0]));
+
+ failover->dirty |= FO_NEW_VERTEX_ELEMENT;
+ failover->num_vertex_elements = count;
+ failover->sw->set_vertex_elements( failover->sw, count, vertex_elements );
+ failover->hw->set_vertex_elements( failover->hw, count, vertex_elements );
+}
+
+void
+failover_set_constant_buffer(struct pipe_context *pipe,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf)
+{
+ struct failover_context *failover = failover_context(pipe);
+
+ assert(shader < PIPE_SHADER_TYPES);
+ assert(index == 0);
+
+ failover->sw->set_constant_buffer(failover->sw, shader, index, buf);
+ failover->hw->set_constant_buffer(failover->hw, shader, index, buf);
+}
+
+
+void
+failover_init_state_functions( struct failover_context *failover )
+{
+ failover->pipe.create_blend_state = failover_create_blend_state;
+ failover->pipe.bind_blend_state = failover_bind_blend_state;
+ failover->pipe.delete_blend_state = failover_delete_blend_state;
+ failover->pipe.create_sampler_state = failover_create_sampler_state;
+ failover->pipe.bind_sampler_states = failover_bind_sampler_states;
+ failover->pipe.delete_sampler_state = failover_delete_sampler_state;
+ failover->pipe.create_depth_stencil_alpha_state = failover_create_depth_stencil_state;
+ failover->pipe.bind_depth_stencil_alpha_state = failover_bind_depth_stencil_state;
+ failover->pipe.delete_depth_stencil_alpha_state = failover_delete_depth_stencil_state;
+ failover->pipe.create_rasterizer_state = failover_create_rasterizer_state;
+ failover->pipe.bind_rasterizer_state = failover_bind_rasterizer_state;
+ failover->pipe.delete_rasterizer_state = failover_delete_rasterizer_state;
+ failover->pipe.create_fs_state = failover_create_fs_state;
+ failover->pipe.bind_fs_state = failover_bind_fs_state;
+ failover->pipe.delete_fs_state = failover_delete_fs_state;
+ failover->pipe.create_vs_state = failover_create_vs_state;
+ failover->pipe.bind_vs_state = failover_bind_vs_state;
+ failover->pipe.delete_vs_state = failover_delete_vs_state;
+
+ failover->pipe.set_blend_color = failover_set_blend_color;
+ failover->pipe.set_clip_state = failover_set_clip_state;
+ failover->pipe.set_framebuffer_state = failover_set_framebuffer_state;
+ failover->pipe.set_polygon_stipple = failover_set_polygon_stipple;
+ failover->pipe.set_scissor_state = failover_set_scissor_state;
+ failover->pipe.set_sampler_textures = failover_set_sampler_textures;
+ failover->pipe.set_viewport_state = failover_set_viewport_state;
+ failover->pipe.set_vertex_buffers = failover_set_vertex_buffers;
+ failover->pipe.set_vertex_elements = failover_set_vertex_elements;
+ failover->pipe.set_constant_buffer = failover_set_constant_buffer;
+}
diff --git a/src/gallium/drivers/failover/fo_state_emit.c b/src/gallium/drivers/failover/fo_state_emit.c
new file mode 100644
index 0000000000..bd4fce9d20
--- /dev/null
+++ b/src/gallium/drivers/failover/fo_state_emit.c
@@ -0,0 +1,117 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "fo_context.h"
+
+/* This looks like a lot of work at the moment - we're keeping a
+ * duplicate copy of the state up-to-date.
+ *
+ * This can change in two ways:
+ * - With constant state objects we would only need to save a pointer,
+ * not the whole object.
+ * - By adding a callback in the state tracker to re-emit state. The
+ * state tracker knows the current state already and can re-emit it
+ * without additional complexity.
+ *
+ * This works as a proof-of-concept, but a final version will have
+ * lower overheads.
+ */
+
+
+/* Bring the software pipe uptodate with current state.
+ *
+ * With constant state objects we would probably just send all state
+ * to both rasterizers all the time???
+ */
+void
+failover_state_emit( struct failover_context *failover )
+{
+ if (failover->dirty & FO_NEW_BLEND)
+ failover->sw->bind_blend_state( failover->sw,
+ failover->blend->sw_state );
+
+ if (failover->dirty & FO_NEW_BLEND_COLOR)
+ failover->sw->set_blend_color( failover->sw, &failover->blend_color );
+
+ if (failover->dirty & FO_NEW_CLIP)
+ failover->sw->set_clip_state( failover->sw, &failover->clip );
+
+ if (failover->dirty & FO_NEW_DEPTH_STENCIL)
+ failover->sw->bind_depth_stencil_alpha_state( failover->sw,
+ failover->depth_stencil->sw_state );
+
+ if (failover->dirty & FO_NEW_FRAMEBUFFER)
+ failover->sw->set_framebuffer_state( failover->sw, &failover->framebuffer );
+
+ if (failover->dirty & FO_NEW_FRAGMENT_SHADER)
+ failover->sw->bind_fs_state( failover->sw,
+ failover->fragment_shader->sw_state );
+
+ if (failover->dirty & FO_NEW_VERTEX_SHADER)
+ failover->sw->bind_vs_state( failover->sw,
+ failover->vertex_shader->sw_state );
+
+ if (failover->dirty & FO_NEW_STIPPLE)
+ failover->sw->set_polygon_stipple( failover->sw, &failover->poly_stipple );
+
+ if (failover->dirty & FO_NEW_RASTERIZER)
+ failover->sw->bind_rasterizer_state( failover->sw,
+ failover->rasterizer->sw_state );
+
+ if (failover->dirty & FO_NEW_SCISSOR)
+ failover->sw->set_scissor_state( failover->sw, &failover->scissor );
+
+ if (failover->dirty & FO_NEW_VIEWPORT)
+ failover->sw->set_viewport_state( failover->sw, &failover->viewport );
+
+ if (failover->dirty & FO_NEW_SAMPLER) {
+ failover->sw->bind_sampler_states( failover->sw, failover->num_samplers,
+ failover->sw_sampler_state );
+ }
+
+ if (failover->dirty & FO_NEW_TEXTURE) {
+ failover->sw->set_sampler_textures( failover->sw, failover->num_textures,
+ failover->texture );
+ }
+
+ if (failover->dirty & FO_NEW_VERTEX_BUFFER) {
+ failover->sw->set_vertex_buffers( failover->sw,
+ failover->num_vertex_buffers,
+ failover->vertex_buffers );
+ }
+
+ if (failover->dirty & FO_NEW_VERTEX_ELEMENT) {
+ failover->sw->set_vertex_elements( failover->sw,
+ failover->num_vertex_elements,
+ failover->vertex_elements );
+ }
+
+ failover->dirty = 0;
+}
diff --git a/src/gallium/drivers/failover/fo_winsys.h b/src/gallium/drivers/failover/fo_winsys.h
new file mode 100644
index 0000000000..a8ce997a1f
--- /dev/null
+++ b/src/gallium/drivers/failover/fo_winsys.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef FO_WINSYS_H
+#define FO_WINSYS_H
+
+
+/* This is the interface that failover requires any window system
+ * hosting it to implement. This is the only include file in failover
+ * which is public.
+ */
+
+
+struct pipe_context;
+
+
+struct pipe_context *failover_create( struct pipe_context *hw,
+ struct pipe_context *sw );
+
+
+#endif /* FO_WINSYS_H */
diff --git a/src/gallium/drivers/i915simple/Makefile b/src/gallium/drivers/i915simple/Makefile
new file mode 100644
index 0000000000..fb533c1796
--- /dev/null
+++ b/src/gallium/drivers/i915simple/Makefile
@@ -0,0 +1,28 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = i915simple
+
+C_SOURCES = \
+ i915_blit.c \
+ i915_buffer.c \
+ i915_clear.c \
+ i915_flush.c \
+ i915_context.c \
+ i915_debug.c \
+ i915_debug_fp.c \
+ i915_state.c \
+ i915_state_immediate.c \
+ i915_state_dynamic.c \
+ i915_state_derived.c \
+ i915_state_emit.c \
+ i915_state_sampler.c \
+ i915_screen.c \
+ i915_prim_emit.c \
+ i915_prim_vbuf.c \
+ i915_texture.c \
+ i915_fpc_emit.c \
+ i915_fpc_translate.c \
+ i915_surface.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/i915simple/SConscript b/src/gallium/drivers/i915simple/SConscript
new file mode 100644
index 0000000000..778c4ed0fd
--- /dev/null
+++ b/src/gallium/drivers/i915simple/SConscript
@@ -0,0 +1,30 @@
+Import('*')
+
+env = env.Clone()
+
+i915simple = env.ConvenienceLibrary(
+ target = 'i915simple',
+ source = [
+ 'i915_blit.c',
+ 'i915_buffer.c',
+ 'i915_clear.c',
+ 'i915_context.c',
+ 'i915_debug.c',
+ 'i915_debug_fp.c',
+ 'i915_flush.c',
+ 'i915_fpc_emit.c',
+ 'i915_fpc_translate.c',
+ 'i915_prim_emit.c',
+ 'i915_prim_vbuf.c',
+ 'i915_screen.c',
+ 'i915_state.c',
+ 'i915_state_derived.c',
+ 'i915_state_dynamic.c',
+ 'i915_state_emit.c',
+ 'i915_state_immediate.c',
+ 'i915_state_sampler.c',
+ 'i915_surface.c',
+ 'i915_texture.c',
+ ])
+
+Export('i915simple')
diff --git a/src/gallium/drivers/i915simple/i915_batch.h b/src/gallium/drivers/i915simple/i915_batch.h
new file mode 100644
index 0000000000..b813784723
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_batch.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef I915_BATCH_H
+#define I915_BATCH_H
+
+#include "intel_batchbuffer.h"
+
+#define BEGIN_BATCH(dwords, relocs) \
+ (intel_batchbuffer_check(i915->batch, dwords, relocs))
+
+#define OUT_BATCH(dword) \
+ intel_batchbuffer_dword(i915->batch, dword)
+
+#define OUT_RELOC(buf, usage, offset) \
+ intel_batchbuffer_reloc(i915->batch, buf, usage, offset)
+
+#define FLUSH_BATCH(fence) do { \
+ intel_batchbuffer_flush(i915->batch, fence); \
+ i915->hardware_dirty = ~0; \
+} while (0)
+
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_blit.c b/src/gallium/drivers/i915simple/i915_blit.c
new file mode 100644
index 0000000000..83dfc33528
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_blit.c
@@ -0,0 +1,151 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "i915_blit.h"
+#include "i915_reg.h"
+#include "i915_batch.h"
+#include "i915_debug.h"
+
+#define FILE_DEBUG_FLAG DEBUG_BLIT
+
+void
+i915_fill_blit(struct i915_context *i915,
+ unsigned cpp,
+ unsigned short dst_pitch,
+ struct intel_buffer *dst_buffer,
+ unsigned dst_offset,
+ short x, short y,
+ short w, short h,
+ unsigned color)
+{
+ unsigned BR13, CMD;
+
+
+ I915_DBG(i915,
+ "%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
+ __FUNCTION__,
+ dst_buffer, dst_pitch, dst_offset, x, y, w, h);
+
+ switch (cpp) {
+ case 1:
+ case 2:
+ case 3:
+ BR13 = (((int) dst_pitch) & 0xffff) |
+ (0xF0 << 16) | (1 << 24);
+ CMD = XY_COLOR_BLT_CMD;
+ break;
+ case 4:
+ BR13 = (((int) dst_pitch) & 0xffff) |
+ (0xF0 << 16) | (1 << 24) | (1 << 25);
+ CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
+ XY_COLOR_BLT_WRITE_RGB);
+ break;
+ default:
+ return;
+ }
+
+ if (!BEGIN_BATCH(6, 1)) {
+ FLUSH_BATCH(NULL);
+ assert(BEGIN_BATCH(6, 1));
+ }
+ OUT_BATCH(CMD);
+ OUT_BATCH(BR13);
+ OUT_BATCH((y << 16) | x);
+ OUT_BATCH(((y + h) << 16) | (x + w));
+ OUT_RELOC(dst_buffer, INTEL_USAGE_2D_TARGET, dst_offset);
+ OUT_BATCH(color);
+ FLUSH_BATCH(NULL);
+}
+
+void
+i915_copy_blit(struct i915_context *i915,
+ unsigned do_flip,
+ unsigned cpp,
+ unsigned short src_pitch,
+ struct intel_buffer *src_buffer,
+ unsigned src_offset,
+ unsigned short dst_pitch,
+ struct intel_buffer *dst_buffer,
+ unsigned dst_offset,
+ short src_x, short src_y,
+ short dst_x, short dst_y,
+ short w, short h)
+{
+ unsigned CMD, BR13;
+ int dst_y2 = dst_y + h;
+ int dst_x2 = dst_x + w;
+
+
+ I915_DBG(i915,
+ "%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,
+ dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
+
+ switch (cpp) {
+ case 1:
+ case 2:
+ case 3:
+ BR13 = (((int) dst_pitch) & 0xffff) |
+ (0xCC << 16) | (1 << 24);
+ CMD = XY_SRC_COPY_BLT_CMD;
+ break;
+ case 4:
+ BR13 = (((int) dst_pitch) & 0xffff) |
+ (0xCC << 16) | (1 << 24) | (1 << 25);
+ CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ break;
+ default:
+ return;
+ }
+
+ if (dst_y2 < dst_y || dst_x2 < dst_x) {
+ return;
+ }
+
+ /* Hardware can handle negative pitches but loses the ability to do
+ * proper overlapping blits in that case. We don't really have a
+ * need for either at this stage.
+ */
+ assert (dst_pitch > 0 && src_pitch > 0);
+
+ if (!BEGIN_BATCH(8, 2)) {
+ FLUSH_BATCH(NULL);
+ assert(BEGIN_BATCH(8, 2));
+ }
+ OUT_BATCH(CMD);
+ OUT_BATCH(BR13);
+ OUT_BATCH((dst_y << 16) | dst_x);
+ OUT_BATCH((dst_y2 << 16) | dst_x2);
+ OUT_RELOC(dst_buffer, INTEL_USAGE_2D_TARGET, dst_offset);
+ OUT_BATCH((src_y << 16) | src_x);
+ OUT_BATCH(((int) src_pitch & 0xffff));
+ OUT_RELOC(src_buffer, INTEL_USAGE_2D_SOURCE, src_offset);
+ FLUSH_BATCH(NULL);
+}
diff --git a/src/gallium/drivers/i915simple/i915_blit.h b/src/gallium/drivers/i915simple/i915_blit.h
new file mode 100644
index 0000000000..8ce3220cfd
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_blit.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef I915_BLIT_H
+#define I915_BLIT_H
+
+#include "i915_context.h"
+
+extern void i915_copy_blit(struct i915_context *i915,
+ unsigned do_flip,
+ unsigned cpp,
+ unsigned short src_pitch,
+ struct intel_buffer *src_buffer,
+ unsigned src_offset,
+ unsigned short dst_pitch,
+ struct intel_buffer *dst_buffer,
+ unsigned dst_offset,
+ short srcx, short srcy,
+ short dstx, short dsty,
+ short w, short h);
+
+extern void i915_fill_blit(struct i915_context *i915,
+ unsigned cpp,
+ unsigned short dst_pitch,
+ struct intel_buffer *dst_buffer,
+ unsigned dst_offset,
+ short x, short y,
+ short w, short h, unsigned color);
+
+
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_buffer.c b/src/gallium/drivers/i915simple/i915_buffer.c
new file mode 100644
index 0000000000..effeba1297
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_buffer.c
@@ -0,0 +1,136 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 Jakob Bornecrantz
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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 "i915_screen.h"
+#include "i915_buffer.h"
+
+struct intel_buffer;
+
+struct i915_buffer
+{
+ struct pipe_buffer base;
+
+ struct intel_buffer *ibuf; /** hw buffer */
+
+ void *data; /**< user and malloc data */
+ boolean own; /**< we own the data incase of malloc */
+};
+
+static INLINE struct i915_buffer *
+i915_buffer(struct pipe_buffer *buffer)
+{
+ return (struct i915_buffer *)buffer;
+}
+
+static struct pipe_buffer *
+i915_buffer_create(struct pipe_screen *screen,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct i915_buffer *buf = CALLOC_STRUCT(i915_buffer);
+
+ if (!buf)
+ return NULL;
+
+ pipe_reference_init(&buf->base.reference, 1);
+ buf->base.alignment = alignment;
+ buf->base.screen = screen;
+ buf->base.usage = usage;
+ buf->base.size = size;
+ buf->data = MALLOC(size);
+ buf->own = TRUE;
+
+ if (!buf->data)
+ goto err;
+
+ return &buf->base;
+
+err:
+ FREE(buf);
+ return NULL;
+}
+
+static struct pipe_buffer *
+i915_user_buffer_create(struct pipe_screen *screen,
+ void *ptr,
+ unsigned bytes)
+{
+ struct i915_buffer *buf = CALLOC_STRUCT(i915_buffer);
+
+ if (!buf)
+ return NULL;
+
+ pipe_reference_init(&buf->base.reference, 1);
+ buf->base.alignment = 0;
+ buf->base.screen = screen;
+ buf->base.usage = 0;
+ buf->base.size = bytes;
+ buf->data = ptr;
+ buf->own = FALSE;
+
+ return &buf->base;
+}
+
+static void *
+i915_buffer_map(struct pipe_screen *screen,
+ struct pipe_buffer *buffer,
+ unsigned usage)
+{
+ struct i915_buffer *buf = i915_buffer(buffer);
+ assert(!buf->ibuf);
+ return buf->data;
+}
+
+static void
+i915_buffer_unmap(struct pipe_screen *screen,
+ struct pipe_buffer *buffer)
+{
+ struct i915_buffer *buf = i915_buffer(buffer);
+ assert(!buf->ibuf);
+}
+
+static void
+i915_buffer_destroy(struct pipe_buffer *buffer)
+{
+ struct i915_buffer *buf = i915_buffer(buffer);
+ assert(!buf->ibuf);
+
+ if (buf->own)
+ FREE(buf->data);
+ FREE(buf);
+}
+
+void i915_init_screen_buffer_functions(struct i915_screen *screen)
+{
+ screen->base.buffer_create = i915_buffer_create;
+ screen->base.user_buffer_create = i915_user_buffer_create;
+ screen->base.buffer_map = i915_buffer_map;
+ screen->base.buffer_map_range = NULL;
+ screen->base.buffer_flush_mapped_range = NULL;
+ screen->base.buffer_unmap = i915_buffer_unmap;
+ screen->base.buffer_destroy = i915_buffer_destroy;
+}
diff --git a/src/gallium/drivers/i915simple/i915_buffer.h b/src/gallium/drivers/i915simple/i915_buffer.h
new file mode 100644
index 0000000000..80fda7c62f
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_buffer.h
@@ -0,0 +1,31 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 Jakob Bornecrantz
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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 I915_BUFFER_H
+#define I915_BUFFER_H
+
+void i915_init_screen_buffer_functions(struct i915_screen *screen);
+
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_clear.c b/src/gallium/drivers/i915simple/i915_clear.c
new file mode 100644
index 0000000000..90530f2826
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_clear.c
@@ -0,0 +1,48 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors:
+ * Brian Paul
+ */
+
+
+#include "util/u_clear.h"
+#include "i915_context.h"
+#include "i915_state.h"
+
+
+/**
+ * Clear the given buffers to the specified values.
+ * No masking, no scissor (clear entire buffer).
+ */
+void
+i915_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
+ double depth, unsigned stencil)
+{
+ util_clear(pipe, &i915_context(pipe)->framebuffer, buffers, rgba, depth,
+ stencil);
+}
diff --git a/src/gallium/drivers/i915simple/i915_context.c b/src/gallium/drivers/i915simple/i915_context.c
new file mode 100644
index 0000000000..b43f735245
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_context.c
@@ -0,0 +1,237 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "i915_context.h"
+#include "i915_state.h"
+#include "i915_screen.h"
+#include "i915_batch.h"
+#include "i915_texture.h"
+#include "i915_reg.h"
+
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+#include "pipe/p_screen.h"
+
+
+/*
+ * Draw functions
+ */
+
+
+static boolean
+i915_draw_range_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned min_index,
+ unsigned max_index,
+ unsigned prim, unsigned start, unsigned count)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ struct draw_context *draw = i915->draw;
+ unsigned i;
+
+ if (i915->dirty)
+ i915_update_derived(i915);
+
+ /*
+ * Map vertex buffers
+ */
+ for (i = 0; i < i915->num_vertex_buffers; i++) {
+ void *buf = pipe_buffer_map(pipe->screen, i915->vertex_buffer[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_vertex_buffer(draw, i, buf);
+ }
+
+ /*
+ * Map index buffer, if present
+ */
+ if (indexBuffer) {
+ void *mapped_indexes = pipe_buffer_map(pipe->screen, indexBuffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer_range(draw, indexSize,
+ min_index,
+ max_index,
+ mapped_indexes);
+ } else {
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+
+ draw_set_mapped_constant_buffer(draw,
+ i915->current.constants[PIPE_SHADER_VERTEX],
+ (i915->current.num_user_constants[PIPE_SHADER_VERTEX] *
+ 4 * sizeof(float)));
+
+ /*
+ * Do the drawing
+ */
+ draw_arrays(i915->draw, prim, start, count);
+
+ /*
+ * unmap vertex/index buffers
+ */
+ for (i = 0; i < i915->num_vertex_buffers; i++) {
+ pipe_buffer_unmap(pipe->screen, i915->vertex_buffer[i].buffer);
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ }
+
+ if (indexBuffer) {
+ pipe_buffer_unmap(pipe->screen, indexBuffer);
+ draw_set_mapped_element_buffer_range(draw, 0, start, start + count - 1, NULL);
+ }
+
+ return TRUE;
+}
+
+static boolean
+i915_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count)
+{
+ return i915_draw_range_elements(pipe, indexBuffer,
+ indexSize,
+ 0, 0xffffffff,
+ prim, start, count);
+}
+
+static boolean
+i915_draw_arrays(struct pipe_context *pipe,
+ unsigned prim, unsigned start, unsigned count)
+{
+ return i915_draw_elements(pipe, NULL, 0, prim, start, count);
+}
+
+
+/*
+ * Is referenced functions
+ */
+
+
+static unsigned int
+i915_is_texture_referenced(struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Return the corrent result. We can't alays return referenced
+ * since it causes a double flush within the vbo module.
+ */
+#if 0
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+#else
+ return 0;
+#endif
+}
+
+static unsigned int
+i915_is_buffer_referenced(struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Return the corrent result. We can't alays return referenced
+ * since it causes a double flush within the vbo module.
+ */
+#if 0
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+#else
+ return 0;
+#endif
+}
+
+
+/*
+ * Generic context functions
+ */
+
+
+static void i915_destroy(struct pipe_context *pipe)
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ draw_destroy(i915->draw);
+
+ if(i915->batch)
+ i915->iws->batchbuffer_destroy(i915->batch);
+
+ FREE(i915);
+}
+
+struct pipe_context *
+i915_create_context(struct pipe_screen *screen)
+{
+ struct i915_context *i915;
+
+ i915 = CALLOC_STRUCT(i915_context);
+ if (i915 == NULL)
+ return NULL;
+
+ i915->iws = i915_screen(screen)->iws;
+ i915->base.winsys = NULL;
+ i915->base.screen = screen;
+
+ i915->base.destroy = i915_destroy;
+
+ i915->base.clear = i915_clear;
+
+ i915->base.draw_arrays = i915_draw_arrays;
+ i915->base.draw_elements = i915_draw_elements;
+ i915->base.draw_range_elements = i915_draw_range_elements;
+
+ i915->base.is_texture_referenced = i915_is_texture_referenced;
+ i915->base.is_buffer_referenced = i915_is_buffer_referenced;
+
+ /*
+ * Create drawing context and plug our rendering stage into it.
+ */
+ i915->draw = draw_create();
+ assert(i915->draw);
+ if (!debug_get_bool_option("I915_NO_VBUF", FALSE)) {
+ draw_set_rasterize_stage(i915->draw, i915_draw_vbuf_stage(i915));
+ } else {
+ draw_set_rasterize_stage(i915->draw, i915_draw_render_stage(i915));
+ }
+
+ i915_init_surface_functions(i915);
+ i915_init_state_functions(i915);
+ i915_init_flush_functions(i915);
+
+ draw_install_aaline_stage(i915->draw, &i915->base);
+ draw_install_aapoint_stage(i915->draw, &i915->base);
+
+ i915->dirty = ~0;
+ i915->hardware_dirty = ~0;
+
+ /* Batch stream debugging is a bit hacked up at the moment:
+ */
+ i915->batch = i915->iws->batchbuffer_create(i915->iws);
+
+ return &i915->base;
+}
diff --git a/src/gallium/drivers/i915simple/i915_context.h b/src/gallium/drivers/i915simple/i915_context.h
new file mode 100644
index 0000000000..234b441ce6
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_context.h
@@ -0,0 +1,350 @@
+ /**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef I915_CONTEXT_H
+#define I915_CONTEXT_H
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "draw/draw_vertex.h"
+
+#include "tgsi/tgsi_scan.h"
+
+
+struct intel_winsys;
+struct intel_buffer;
+struct intel_batchbuffer;
+
+
+#define I915_TEX_UNITS 8
+
+#define I915_DYNAMIC_MODES4 0
+#define I915_DYNAMIC_DEPTHSCALE_0 1 /* just the header */
+#define I915_DYNAMIC_DEPTHSCALE_1 2
+#define I915_DYNAMIC_IAB 3
+#define I915_DYNAMIC_BC_0 4 /* just the header */
+#define I915_DYNAMIC_BC_1 5
+#define I915_DYNAMIC_BFO_0 6
+#define I915_DYNAMIC_BFO_1 7
+#define I915_DYNAMIC_STP_0 8
+#define I915_DYNAMIC_STP_1 9
+#define I915_DYNAMIC_SC_ENA_0 10
+#define I915_DYNAMIC_SC_RECT_0 11
+#define I915_DYNAMIC_SC_RECT_1 12
+#define I915_DYNAMIC_SC_RECT_2 13
+#define I915_MAX_DYNAMIC 14
+
+
+#define I915_IMMEDIATE_S0 0
+#define I915_IMMEDIATE_S1 1
+#define I915_IMMEDIATE_S2 2
+#define I915_IMMEDIATE_S3 3
+#define I915_IMMEDIATE_S4 4
+#define I915_IMMEDIATE_S5 5
+#define I915_IMMEDIATE_S6 6
+#define I915_IMMEDIATE_S7 7
+#define I915_MAX_IMMEDIATE 8
+
+/* These must mach the order of LI0_STATE_* bits, as they will be used
+ * to generate hardware packets:
+ */
+#define I915_CACHE_STATIC 0
+#define I915_CACHE_DYNAMIC 1 /* handled specially */
+#define I915_CACHE_SAMPLER 2
+#define I915_CACHE_MAP 3
+#define I915_CACHE_PROGRAM 4
+#define I915_CACHE_CONSTANTS 5
+#define I915_MAX_CACHE 6
+
+#define I915_MAX_CONSTANT 32
+
+
+/** See constant_flags[] below */
+#define I915_CONSTFLAG_USER 0x1f
+
+
+/**
+ * Subclass of pipe_shader_state
+ */
+struct i915_fragment_shader
+{
+ struct pipe_shader_state state;
+
+ struct tgsi_shader_info info;
+
+ uint *program;
+ uint program_len;
+
+ /**
+ * constants introduced during translation.
+ * These are placed at the end of the constant buffer and grow toward
+ * the beginning (eg: slot 31, 30 29, ...)
+ * User-provided constants start at 0.
+ * This allows both types of constants to co-exist (until there's too many)
+ * and doesn't require regenerating/changing the fragment program to
+ * shuffle constants around.
+ */
+ uint num_constants;
+ float constants[I915_MAX_CONSTANT][4];
+
+ /**
+ * Status of each constant
+ * if I915_CONSTFLAG_PARAM, the value must be taken from the corresponding
+ * slot of the user's constant buffer. (set by pipe->set_constant_buffer())
+ * Else, the bitmask indicates which components are occupied by immediates.
+ */
+ ubyte constant_flags[I915_MAX_CONSTANT];
+};
+
+
+struct i915_cache_context;
+
+/* Use to calculate differences between state emitted to hardware and
+ * current driver-calculated state.
+ */
+struct i915_state
+{
+ unsigned immediate[I915_MAX_IMMEDIATE];
+ unsigned dynamic[I915_MAX_DYNAMIC];
+
+ float constants[PIPE_SHADER_TYPES][I915_MAX_CONSTANT][4];
+ /** number of constants passed in through a constant buffer */
+ uint num_user_constants[PIPE_SHADER_TYPES];
+
+ /* texture sampler state */
+ unsigned sampler[I915_TEX_UNITS][3];
+ unsigned sampler_enable_flags;
+ unsigned sampler_enable_nr;
+
+ /* texture image buffers */
+ unsigned texbuffer[I915_TEX_UNITS][2];
+
+ /** Describes the current hardware vertex layout */
+ struct vertex_info vertex_info;
+
+ unsigned id; /* track lost context events */
+};
+
+struct i915_blend_state {
+ unsigned iab;
+ unsigned modes4;
+ unsigned LIS5;
+ unsigned LIS6;
+};
+
+struct i915_depth_stencil_state {
+ unsigned stencil_modes4;
+ unsigned bfo[2];
+ unsigned stencil_LIS5;
+ unsigned depth_LIS6;
+};
+
+struct i915_rasterizer_state {
+ int light_twoside : 1;
+ unsigned st;
+ enum interp_mode color_interp;
+
+ unsigned LIS4;
+ unsigned LIS7;
+ unsigned sc[1];
+
+ const struct pipe_rasterizer_state *templ;
+
+ union { float f; unsigned u; } ds[2];
+};
+
+struct i915_sampler_state {
+ unsigned state[3];
+ const struct pipe_sampler_state *templ;
+ unsigned minlod;
+ unsigned maxlod;
+};
+
+struct i915_texture {
+ struct pipe_texture base;
+
+ /* Derived from the above:
+ */
+ unsigned stride;
+ unsigned depth_stride; /* per-image on i945? */
+ unsigned total_nblocksy;
+
+ unsigned sw_tiled; /**< tiled with software flags */
+ unsigned hw_tiled; /**< tiled with hardware fences */
+
+ unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS];
+
+ /* Explicitly store the offset of each image for each cube face or
+ * depth value. Pretty much have to accept that hardware formats
+ * are going to be so diverse that there is no unified way to
+ * compute the offsets of depth/cube images within a mipmap level,
+ * so have to store them as a lookup table:
+ */
+ unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS]; /**< array [depth] of offsets */
+
+ /* The data is held here:
+ */
+ struct intel_buffer *buffer;
+};
+
+struct i915_context
+{
+ struct pipe_context base;
+
+ struct intel_winsys *iws;
+
+ struct draw_context *draw;
+
+ /* The most recent drawing state as set by the driver:
+ */
+ const struct i915_blend_state *blend;
+ const struct i915_sampler_state *sampler[PIPE_MAX_SAMPLERS];
+ const struct i915_depth_stencil_state *depth_stencil;
+ const struct i915_rasterizer_state *rasterizer;
+
+ struct i915_fragment_shader *fs;
+
+ struct pipe_blend_color blend_color;
+ struct pipe_clip_state clip;
+ struct pipe_constant_buffer constants[PIPE_SHADER_TYPES];
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_poly_stipple poly_stipple;
+ struct pipe_scissor_state scissor;
+ struct i915_texture *texture[PIPE_MAX_SAMPLERS];
+ struct pipe_viewport_state viewport;
+ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+
+ unsigned dirty;
+
+ unsigned num_samplers;
+ unsigned num_textures;
+ unsigned num_vertex_elements;
+ unsigned num_vertex_buffers;
+
+ struct intel_batchbuffer *batch;
+
+ /** Vertex buffer */
+ struct intel_buffer *vbo;
+ size_t vbo_offset;
+ unsigned vbo_flushed;
+
+ struct i915_state current;
+ unsigned hardware_dirty;
+
+ unsigned debug;
+};
+
+/* A flag for each state_tracker state object:
+ */
+#define I915_NEW_VIEWPORT 0x1
+#define I915_NEW_RASTERIZER 0x2
+#define I915_NEW_FS 0x4
+#define I915_NEW_BLEND 0x8
+#define I915_NEW_CLIP 0x10
+#define I915_NEW_SCISSOR 0x20
+#define I915_NEW_STIPPLE 0x40
+#define I915_NEW_FRAMEBUFFER 0x80
+#define I915_NEW_ALPHA_TEST 0x100
+#define I915_NEW_DEPTH_STENCIL 0x200
+#define I915_NEW_SAMPLER 0x400
+#define I915_NEW_TEXTURE 0x800
+#define I915_NEW_CONSTANTS 0x1000
+#define I915_NEW_VBO 0x2000
+#define I915_NEW_VS 0x4000
+
+
+/* Driver's internally generated state flags:
+ */
+#define I915_NEW_VERTEX_FORMAT 0x10000
+
+
+/* Dirty flags for hardware emit
+ */
+#define I915_HW_STATIC (1<<I915_CACHE_STATIC)
+#define I915_HW_DYNAMIC (1<<I915_CACHE_DYNAMIC)
+#define I915_HW_SAMPLER (1<<I915_CACHE_SAMPLER)
+#define I915_HW_MAP (1<<I915_CACHE_MAP)
+#define I915_HW_PROGRAM (1<<I915_CACHE_PROGRAM)
+#define I915_HW_CONSTANTS (1<<I915_CACHE_CONSTANTS)
+#define I915_HW_IMMEDIATE (1<<(I915_MAX_CACHE+0))
+#define I915_HW_INVARIENT (1<<(I915_MAX_CACHE+1))
+
+
+/***********************************************************************
+ * i915_prim_emit.c:
+ */
+struct draw_stage *i915_draw_render_stage( struct i915_context *i915 );
+
+
+/***********************************************************************
+ * i915_prim_vbuf.c:
+ */
+struct draw_stage *i915_draw_vbuf_stage( struct i915_context *i915 );
+
+
+/***********************************************************************
+ * i915_state_emit.c:
+ */
+void i915_emit_hardware_state(struct i915_context *i915 );
+
+
+
+/***********************************************************************
+ * i915_clear.c:
+ */
+void i915_clear( struct pipe_context *pipe, unsigned buffers, const float *rgba,
+ double depth, unsigned stencil);
+
+
+/***********************************************************************
+ * i915_surface.c:
+ */
+void i915_init_surface_functions( struct i915_context *i915 );
+
+void i915_init_state_functions( struct i915_context *i915 );
+void i915_init_flush_functions( struct i915_context *i915 );
+void i915_init_string_functions( struct i915_context *i915 );
+
+
+
+
+/***********************************************************************
+ * Inline conversion functions. These are better-typed than the
+ * macros used previously:
+ */
+static INLINE struct i915_context *
+i915_context( struct pipe_context *pipe )
+{
+ return (struct i915_context *)pipe;
+}
+
+
+
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_debug.c b/src/gallium/drivers/i915simple/i915_debug.c
new file mode 100644
index 0000000000..ce92d1af9a
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_debug.c
@@ -0,0 +1,898 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "i915_reg.h"
+#include "i915_context.h"
+#include "i915_debug.h"
+#include "i915_batch.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_debug.h"
+
+
+static void
+PRINTF(
+ struct debug_stream *stream,
+ const char *fmt,
+ ... )
+{
+ va_list args;
+
+ va_start( args, fmt );
+ debug_vprintf( fmt, args );
+ va_end( args );
+}
+
+
+static boolean debug( struct debug_stream *stream, const char *name, unsigned len )
+{
+ unsigned i;
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+
+ if (len == 0) {
+ PRINTF(stream, "Error - zero length packet (0x%08x)\n", stream->ptr[0]);
+ assert(0);
+ return FALSE;
+ }
+
+ if (stream->print_addresses)
+ PRINTF(stream, "%08x: ", stream->offset);
+
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ for (i = 0; i < len; i++)
+ PRINTF(stream, "\t0x%08x\n", ptr[i]);
+ PRINTF(stream, "\n");
+
+ stream->offset += len * sizeof(unsigned);
+
+ return TRUE;
+}
+
+
+static const char *get_prim_name( unsigned val )
+{
+ switch (val & PRIM3D_MASK) {
+ case PRIM3D_TRILIST: return "TRILIST"; break;
+ case PRIM3D_TRISTRIP: return "TRISTRIP"; break;
+ case PRIM3D_TRISTRIP_RVRSE: return "TRISTRIP_RVRSE"; break;
+ case PRIM3D_TRIFAN: return "TRIFAN"; break;
+ case PRIM3D_POLY: return "POLY"; break;
+ case PRIM3D_LINELIST: return "LINELIST"; break;
+ case PRIM3D_LINESTRIP: return "LINESTRIP"; break;
+ case PRIM3D_RECTLIST: return "RECTLIST"; break;
+ case PRIM3D_POINTLIST: return "POINTLIST"; break;
+ case PRIM3D_DIB: return "DIB"; break;
+ case PRIM3D_CLEAR_RECT: return "CLEAR_RECT"; break;
+ case PRIM3D_ZONE_INIT: return "ZONE_INIT"; break;
+ default: return "????"; break;
+ }
+}
+
+static boolean debug_prim( struct debug_stream *stream, const char *name,
+ boolean dump_floats,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ const char *prim = get_prim_name( ptr[0] );
+ unsigned i;
+
+
+
+ PRINTF(stream, "%s %s (%d dwords):\n", name, prim, len);
+ PRINTF(stream, "\t0x%08x\n", ptr[0]);
+ for (i = 1; i < len; i++) {
+ if (dump_floats)
+ PRINTF(stream, "\t0x%08x // %f\n", ptr[i], *(float *)&ptr[i]);
+ else
+ PRINTF(stream, "\t0x%08x\n", ptr[i]);
+ }
+
+
+ PRINTF(stream, "\n");
+
+ stream->offset += len * sizeof(unsigned);
+
+ return TRUE;
+}
+
+
+
+
+static boolean debug_program( struct debug_stream *stream, const char *name, unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+
+ if (len == 0) {
+ PRINTF(stream, "Error - zero length packet (0x%08x)\n", stream->ptr[0]);
+ assert(0);
+ return FALSE;
+ }
+
+ if (stream->print_addresses)
+ PRINTF(stream, "%08x: ", stream->offset);
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ i915_disassemble_program( stream, ptr, len );
+
+ stream->offset += len * sizeof(unsigned);
+ return TRUE;
+}
+
+
+static boolean debug_chain( struct debug_stream *stream, const char *name, unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ unsigned old_offset = stream->offset + len * sizeof(unsigned);
+ unsigned i;
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ for (i = 0; i < len; i++)
+ PRINTF(stream, "\t0x%08x\n", ptr[i]);
+
+ stream->offset = ptr[1] & ~0x3;
+
+ if (stream->offset < old_offset)
+ PRINTF(stream, "\n... skipping backwards from 0x%x --> 0x%x ...\n\n",
+ old_offset, stream->offset );
+ else
+ PRINTF(stream, "\n... skipping from 0x%x --> 0x%x ...\n\n",
+ old_offset, stream->offset );
+
+
+ return TRUE;
+}
+
+
+static boolean debug_variable_length_prim( struct debug_stream *stream )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ const char *prim = get_prim_name( ptr[0] );
+ unsigned i, len;
+
+ ushort *idx = (ushort *)(ptr+1);
+ for (i = 0; idx[i] != 0xffff; i++)
+ ;
+
+ len = 1+(i+2)/2;
+
+ PRINTF(stream, "3DPRIM, %s variable length %d indicies (%d dwords):\n", prim, i, len);
+ for (i = 0; i < len; i++)
+ PRINTF(stream, "\t0x%08x\n", ptr[i]);
+ PRINTF(stream, "\n");
+
+ stream->offset += len * sizeof(unsigned);
+ return TRUE;
+}
+
+
+static void
+BITS(
+ struct debug_stream *stream,
+ unsigned dw,
+ unsigned hi,
+ unsigned lo,
+ const char *fmt,
+ ... )
+{
+ va_list args;
+ unsigned himask = ~0UL >> (31 - (hi));
+
+ PRINTF(stream, "\t\t ");
+
+ va_start( args, fmt );
+ debug_vprintf( fmt, args );
+ va_end( args );
+
+ PRINTF(stream, ": 0x%x\n", ((dw) & himask) >> (lo));
+}
+
+#ifdef DEBUG
+#define MBZ( dw, hi, lo) do { \
+ unsigned x = (dw) >> (lo); \
+ unsigned lomask = (1 << (lo)) - 1; \
+ unsigned himask; \
+ himask = (1UL << (hi)) - 1; \
+ assert ((x & himask & ~lomask) == 0); \
+} while (0)
+#else
+#define MBZ( dw, hi, lo) do { \
+} while (0)
+#endif
+
+static void
+FLAG(
+ struct debug_stream *stream,
+ unsigned dw,
+ unsigned bit,
+ const char *fmt,
+ ... )
+{
+ if (((dw) >> (bit)) & 1) {
+ va_list args;
+
+ PRINTF(stream, "\t\t ");
+
+ va_start( args, fmt );
+ debug_vprintf( fmt, args );
+ va_end( args );
+
+ PRINTF(stream, "\n");
+ }
+}
+
+static boolean debug_load_immediate( struct debug_stream *stream,
+ const char *name,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ unsigned bits = (ptr[0] >> 4) & 0xff;
+ unsigned j = 0;
+
+ PRINTF(stream, "%s (%d dwords, flags: %x):\n", name, len, bits);
+ PRINTF(stream, "\t0x%08x\n", ptr[j++]);
+
+ if (bits & (1<<0)) {
+ PRINTF(stream, "\t LIS0: 0x%08x\n", ptr[j]);
+ PRINTF(stream, "\t vb address: 0x%08x\n", (ptr[j] & ~0x3));
+ BITS(stream, ptr[j], 0, 0, "vb invalidate disable");
+ j++;
+ }
+ if (bits & (1<<1)) {
+ PRINTF(stream, "\t LIS1: 0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 29, 24, "vb dword width");
+ BITS(stream, ptr[j], 21, 16, "vb dword pitch");
+ BITS(stream, ptr[j], 15, 0, "vb max index");
+ j++;
+ }
+ if (bits & (1<<2)) {
+ int i;
+ PRINTF(stream, "\t LIS2: 0x%08x\n", ptr[j]);
+ for (i = 0; i < 8; i++) {
+ unsigned tc = (ptr[j] >> (i * 4)) & 0xf;
+ if (tc != 0xf)
+ BITS(stream, tc, 3, 0, "tex coord %d", i);
+ }
+ j++;
+ }
+ if (bits & (1<<3)) {
+ PRINTF(stream, "\t LIS3: 0x%08x\n", ptr[j]);
+ j++;
+ }
+ if (bits & (1<<4)) {
+ PRINTF(stream, "\t LIS4: 0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 31, 23, "point width");
+ BITS(stream, ptr[j], 22, 19, "line width");
+ FLAG(stream, ptr[j], 18, "alpha flatshade");
+ FLAG(stream, ptr[j], 17, "fog flatshade");
+ FLAG(stream, ptr[j], 16, "spec flatshade");
+ FLAG(stream, ptr[j], 15, "rgb flatshade");
+ BITS(stream, ptr[j], 14, 13, "cull mode");
+ FLAG(stream, ptr[j], 12, "vfmt: point width");
+ FLAG(stream, ptr[j], 11, "vfmt: specular/fog");
+ FLAG(stream, ptr[j], 10, "vfmt: rgba");
+ FLAG(stream, ptr[j], 9, "vfmt: depth offset");
+ BITS(stream, ptr[j], 8, 6, "vfmt: position (2==xyzw)");
+ FLAG(stream, ptr[j], 5, "force dflt diffuse");
+ FLAG(stream, ptr[j], 4, "force dflt specular");
+ FLAG(stream, ptr[j], 3, "local depth offset enable");
+ FLAG(stream, ptr[j], 2, "vfmt: fp32 fog coord");
+ FLAG(stream, ptr[j], 1, "sprite point");
+ FLAG(stream, ptr[j], 0, "antialiasing");
+ j++;
+ }
+ if (bits & (1<<5)) {
+ PRINTF(stream, "\t LIS5: 0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 31, 28, "rgba write disables");
+ FLAG(stream, ptr[j], 27, "force dflt point width");
+ FLAG(stream, ptr[j], 26, "last pixel enable");
+ FLAG(stream, ptr[j], 25, "global z offset enable");
+ FLAG(stream, ptr[j], 24, "fog enable");
+ BITS(stream, ptr[j], 23, 16, "stencil ref");
+ BITS(stream, ptr[j], 15, 13, "stencil test");
+ BITS(stream, ptr[j], 12, 10, "stencil fail op");
+ BITS(stream, ptr[j], 9, 7, "stencil pass z fail op");
+ BITS(stream, ptr[j], 6, 4, "stencil pass z pass op");
+ FLAG(stream, ptr[j], 3, "stencil write enable");
+ FLAG(stream, ptr[j], 2, "stencil test enable");
+ FLAG(stream, ptr[j], 1, "color dither enable");
+ FLAG(stream, ptr[j], 0, "logiop enable");
+ j++;
+ }
+ if (bits & (1<<6)) {
+ PRINTF(stream, "\t LIS6: 0x%08x\n", ptr[j]);
+ FLAG(stream, ptr[j], 31, "alpha test enable");
+ BITS(stream, ptr[j], 30, 28, "alpha func");
+ BITS(stream, ptr[j], 27, 20, "alpha ref");
+ FLAG(stream, ptr[j], 19, "depth test enable");
+ BITS(stream, ptr[j], 18, 16, "depth func");
+ FLAG(stream, ptr[j], 15, "blend enable");
+ BITS(stream, ptr[j], 14, 12, "blend func");
+ BITS(stream, ptr[j], 11, 8, "blend src factor");
+ BITS(stream, ptr[j], 7, 4, "blend dst factor");
+ FLAG(stream, ptr[j], 3, "depth write enable");
+ FLAG(stream, ptr[j], 2, "color write enable");
+ BITS(stream, ptr[j], 1, 0, "provoking vertex");
+ j++;
+ }
+
+
+ PRINTF(stream, "\n");
+
+ assert(j == len);
+
+ stream->offset += len * sizeof(unsigned);
+
+ return TRUE;
+}
+
+
+
+static boolean debug_load_indirect( struct debug_stream *stream,
+ const char *name,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ unsigned bits = (ptr[0] >> 8) & 0x3f;
+ unsigned i, j = 0;
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ PRINTF(stream, "\t0x%08x\n", ptr[j++]);
+
+ for (i = 0; i < 6; i++) {
+ if (bits & (1<<i)) {
+ switch (1<<(8+i)) {
+ case LI0_STATE_STATIC_INDIRECT:
+ PRINTF(stream, " STATIC: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++;
+ PRINTF(stream, " 0x%08x\n", ptr[j++]);
+ break;
+ case LI0_STATE_DYNAMIC_INDIRECT:
+ PRINTF(stream, " DYNAMIC: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++;
+ break;
+ case LI0_STATE_SAMPLER:
+ PRINTF(stream, " SAMPLER: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++;
+ PRINTF(stream, " 0x%08x\n", ptr[j++]);
+ break;
+ case LI0_STATE_MAP:
+ PRINTF(stream, " MAP: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++;
+ PRINTF(stream, " 0x%08x\n", ptr[j++]);
+ break;
+ case LI0_STATE_PROGRAM:
+ PRINTF(stream, " PROGRAM: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++;
+ PRINTF(stream, " 0x%08x\n", ptr[j++]);
+ break;
+ case LI0_STATE_CONSTANTS:
+ PRINTF(stream, " CONSTANTS: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++;
+ PRINTF(stream, " 0x%08x\n", ptr[j++]);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ }
+
+ if (bits == 0) {
+ PRINTF(stream, "\t DUMMY: 0x%08x\n", ptr[j++]);
+ }
+
+ PRINTF(stream, "\n");
+
+
+ assert(j == len);
+
+ stream->offset += len * sizeof(unsigned);
+
+ return TRUE;
+}
+
+static void BR13( struct debug_stream *stream,
+ unsigned val )
+{
+ PRINTF(stream, "\t0x%08x\n", val);
+ FLAG(stream, val, 30, "clipping enable");
+ BITS(stream, val, 25, 24, "color depth (3==32bpp)");
+ BITS(stream, val, 23, 16, "raster op");
+ BITS(stream, val, 15, 0, "dest pitch");
+}
+
+
+static void BR22( struct debug_stream *stream,
+ unsigned val )
+{
+ PRINTF(stream, "\t0x%08x\n", val);
+ BITS(stream, val, 31, 16, "dest y1");
+ BITS(stream, val, 15, 0, "dest x1");
+}
+
+static void BR23( struct debug_stream *stream,
+ unsigned val )
+{
+ PRINTF(stream, "\t0x%08x\n", val);
+ BITS(stream, val, 31, 16, "dest y2");
+ BITS(stream, val, 15, 0, "dest x2");
+}
+
+static void BR09( struct debug_stream *stream,
+ unsigned val )
+{
+ PRINTF(stream, "\t0x%08x -- dest address\n", val);
+}
+
+static void BR26( struct debug_stream *stream,
+ unsigned val )
+{
+ PRINTF(stream, "\t0x%08x\n", val);
+ BITS(stream, val, 31, 16, "src y1");
+ BITS(stream, val, 15, 0, "src x1");
+}
+
+static void BR11( struct debug_stream *stream,
+ unsigned val )
+{
+ PRINTF(stream, "\t0x%08x\n", val);
+ BITS(stream, val, 15, 0, "src pitch");
+}
+
+static void BR12( struct debug_stream *stream,
+ unsigned val )
+{
+ PRINTF(stream, "\t0x%08x -- src address\n", val);
+}
+
+static void BR16( struct debug_stream *stream,
+ unsigned val )
+{
+ PRINTF(stream, "\t0x%08x -- color\n", val);
+}
+
+static boolean debug_copy_blit( struct debug_stream *stream,
+ const char *name,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ int j = 0;
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ PRINTF(stream, "\t0x%08x\n", ptr[j++]);
+
+ BR13(stream, ptr[j++]);
+ BR22(stream, ptr[j++]);
+ BR23(stream, ptr[j++]);
+ BR09(stream, ptr[j++]);
+ BR26(stream, ptr[j++]);
+ BR11(stream, ptr[j++]);
+ BR12(stream, ptr[j++]);
+
+ stream->offset += len * sizeof(unsigned);
+ assert(j == len);
+ return TRUE;
+}
+
+static boolean debug_color_blit( struct debug_stream *stream,
+ const char *name,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ int j = 0;
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ PRINTF(stream, "\t0x%08x\n", ptr[j++]);
+
+ BR13(stream, ptr[j++]);
+ BR22(stream, ptr[j++]);
+ BR23(stream, ptr[j++]);
+ BR09(stream, ptr[j++]);
+ BR16(stream, ptr[j++]);
+
+ stream->offset += len * sizeof(unsigned);
+ assert(j == len);
+ return TRUE;
+}
+
+static boolean debug_modes4( struct debug_stream *stream,
+ const char *name,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ int j = 0;
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ PRINTF(stream, "\t0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 21, 18, "logicop func");
+ FLAG(stream, ptr[j], 17, "stencil test mask modify-enable");
+ FLAG(stream, ptr[j], 16, "stencil write mask modify-enable");
+ BITS(stream, ptr[j], 15, 8, "stencil test mask");
+ BITS(stream, ptr[j], 7, 0, "stencil write mask");
+ j++;
+
+ stream->offset += len * sizeof(unsigned);
+ assert(j == len);
+ return TRUE;
+}
+
+static boolean debug_map_state( struct debug_stream *stream,
+ const char *name,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ unsigned j = 0;
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ PRINTF(stream, "\t0x%08x\n", ptr[j++]);
+
+ {
+ PRINTF(stream, "\t0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 15, 0, "map mask");
+ j++;
+ }
+
+ while (j < len) {
+ {
+ PRINTF(stream, "\t TMn.0: 0x%08x\n", ptr[j]);
+ PRINTF(stream, "\t map address: 0x%08x\n", (ptr[j] & ~0x3));
+ FLAG(stream, ptr[j], 1, "vertical line stride");
+ FLAG(stream, ptr[j], 0, "vertical line stride offset");
+ j++;
+ }
+
+ {
+ PRINTF(stream, "\t TMn.1: 0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 31, 21, "height");
+ BITS(stream, ptr[j], 20, 10, "width");
+ BITS(stream, ptr[j], 9, 7, "surface format");
+ BITS(stream, ptr[j], 6, 3, "texel format");
+ FLAG(stream, ptr[j], 2, "use fence regs");
+ FLAG(stream, ptr[j], 1, "tiled surface");
+ FLAG(stream, ptr[j], 0, "tile walk ymajor");
+ j++;
+ }
+ {
+ PRINTF(stream, "\t TMn.2: 0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 31, 21, "dword pitch");
+ BITS(stream, ptr[j], 20, 15, "cube face enables");
+ BITS(stream, ptr[j], 14, 9, "max lod");
+ FLAG(stream, ptr[j], 8, "mip layout right");
+ BITS(stream, ptr[j], 7, 0, "depth");
+ j++;
+ }
+ }
+
+ stream->offset += len * sizeof(unsigned);
+ assert(j == len);
+ return TRUE;
+}
+
+static boolean debug_sampler_state( struct debug_stream *stream,
+ const char *name,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ unsigned j = 0;
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ PRINTF(stream, "\t0x%08x\n", ptr[j++]);
+
+ {
+ PRINTF(stream, "\t0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 15, 0, "sampler mask");
+ j++;
+ }
+
+ while (j < len) {
+ {
+ PRINTF(stream, "\t TSn.0: 0x%08x\n", ptr[j]);
+ FLAG(stream, ptr[j], 31, "reverse gamma");
+ FLAG(stream, ptr[j], 30, "planar to packed");
+ FLAG(stream, ptr[j], 29, "yuv->rgb");
+ BITS(stream, ptr[j], 28, 27, "chromakey index");
+ BITS(stream, ptr[j], 26, 22, "base mip level");
+ BITS(stream, ptr[j], 21, 20, "mip mode filter");
+ BITS(stream, ptr[j], 19, 17, "mag mode filter");
+ BITS(stream, ptr[j], 16, 14, "min mode filter");
+ BITS(stream, ptr[j], 13, 5, "lod bias (s4.4)");
+ FLAG(stream, ptr[j], 4, "shadow enable");
+ FLAG(stream, ptr[j], 3, "max-aniso-4");
+ BITS(stream, ptr[j], 2, 0, "shadow func");
+ j++;
+ }
+
+ {
+ PRINTF(stream, "\t TSn.1: 0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 31, 24, "min lod");
+ MBZ( ptr[j], 23, 18 );
+ FLAG(stream, ptr[j], 17, "kill pixel enable");
+ FLAG(stream, ptr[j], 16, "keyed tex filter mode");
+ FLAG(stream, ptr[j], 15, "chromakey enable");
+ BITS(stream, ptr[j], 14, 12, "tcx wrap mode");
+ BITS(stream, ptr[j], 11, 9, "tcy wrap mode");
+ BITS(stream, ptr[j], 8, 6, "tcz wrap mode");
+ FLAG(stream, ptr[j], 5, "normalized coords");
+ BITS(stream, ptr[j], 4, 1, "map (surface) index");
+ FLAG(stream, ptr[j], 0, "EAST deinterlacer enable");
+ j++;
+ }
+ {
+ PRINTF(stream, "\t TSn.2: 0x%08x (default color)\n", ptr[j]);
+ j++;
+ }
+ }
+
+ stream->offset += len * sizeof(unsigned);
+ assert(j == len);
+ return TRUE;
+}
+
+static boolean debug_dest_vars( struct debug_stream *stream,
+ const char *name,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ int j = 0;
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ PRINTF(stream, "\t0x%08x\n", ptr[j++]);
+
+ {
+ PRINTF(stream, "\t0x%08x\n", ptr[j]);
+ FLAG(stream, ptr[j], 31, "early classic ztest");
+ FLAG(stream, ptr[j], 30, "opengl tex default color");
+ FLAG(stream, ptr[j], 29, "bypass iz");
+ FLAG(stream, ptr[j], 28, "lod preclamp");
+ BITS(stream, ptr[j], 27, 26, "dither pattern");
+ FLAG(stream, ptr[j], 25, "linear gamma blend");
+ FLAG(stream, ptr[j], 24, "debug dither");
+ BITS(stream, ptr[j], 23, 20, "dstorg x");
+ BITS(stream, ptr[j], 19, 16, "dstorg y");
+ MBZ (ptr[j], 15, 15 );
+ BITS(stream, ptr[j], 14, 12, "422 write select");
+ BITS(stream, ptr[j], 11, 8, "cbuf format");
+ BITS(stream, ptr[j], 3, 2, "zbuf format");
+ FLAG(stream, ptr[j], 1, "vert line stride");
+ FLAG(stream, ptr[j], 1, "vert line stride offset");
+ j++;
+ }
+
+ stream->offset += len * sizeof(unsigned);
+ assert(j == len);
+ return TRUE;
+}
+
+static boolean debug_buf_info( struct debug_stream *stream,
+ const char *name,
+ unsigned len )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ int j = 0;
+
+ PRINTF(stream, "%s (%d dwords):\n", name, len);
+ PRINTF(stream, "\t0x%08x\n", ptr[j++]);
+
+ {
+ PRINTF(stream, "\t0x%08x\n", ptr[j]);
+ BITS(stream, ptr[j], 28, 28, "aux buffer id");
+ BITS(stream, ptr[j], 27, 24, "buffer id (7=depth, 3=back)");
+ FLAG(stream, ptr[j], 23, "use fence regs");
+ FLAG(stream, ptr[j], 22, "tiled surface");
+ FLAG(stream, ptr[j], 21, "tile walk ymajor");
+ MBZ (ptr[j], 20, 14);
+ BITS(stream, ptr[j], 13, 2, "dword pitch");
+ MBZ (ptr[j], 2, 0);
+ j++;
+ }
+
+ PRINTF(stream, "\t0x%08x -- buffer base address\n", ptr[j++]);
+
+ stream->offset += len * sizeof(unsigned);
+ assert(j == len);
+ return TRUE;
+}
+
+static boolean i915_debug_packet( struct debug_stream *stream )
+{
+ unsigned *ptr = (unsigned *)(stream->ptr + stream->offset);
+ unsigned cmd = *ptr;
+
+ switch (((cmd >> 29) & 0x7)) {
+ case 0x0:
+ switch ((cmd >> 23) & 0x3f) {
+ case 0x0:
+ return debug(stream, "MI_NOOP", 1);
+ case 0x3:
+ return debug(stream, "MI_WAIT_FOR_EVENT", 1);
+ case 0x4:
+ return debug(stream, "MI_FLUSH", 1);
+ case 0xA:
+ debug(stream, "MI_BATCH_BUFFER_END", 1);
+ return FALSE;
+ case 0x22:
+ return debug(stream, "MI_LOAD_REGISTER_IMM", 3);
+ case 0x31:
+ return debug_chain(stream, "MI_BATCH_BUFFER_START", 2);
+ default:
+ (void)debug(stream, "UNKNOWN 0x0 case!", 1);
+ assert(0);
+ break;
+ }
+ break;
+ case 0x1:
+ (void) debug(stream, "UNKNOWN 0x1 case!", 1);
+ assert(0);
+ break;
+ case 0x2:
+ switch ((cmd >> 22) & 0xff) {
+ case 0x50:
+ return debug_color_blit(stream, "XY_COLOR_BLT", (cmd & 0xff) + 2);
+ case 0x53:
+ return debug_copy_blit(stream, "XY_SRC_COPY_BLT", (cmd & 0xff) + 2);
+ default:
+ return debug(stream, "blit command", (cmd & 0xff) + 2);
+ }
+ break;
+ case 0x3:
+ switch ((cmd >> 24) & 0x1f) {
+ case 0x6:
+ return debug(stream, "3DSTATE_ANTI_ALIASING", 1);
+ case 0x7:
+ return debug(stream, "3DSTATE_RASTERIZATION_RULES", 1);
+ case 0x8:
+ return debug(stream, "3DSTATE_BACKFACE_STENCIL_OPS", 2);
+ case 0x9:
+ return debug(stream, "3DSTATE_BACKFACE_STENCIL_MASKS", 1);
+ case 0xb:
+ return debug(stream, "3DSTATE_INDEPENDENT_ALPHA_BLEND", 1);
+ case 0xc:
+ return debug(stream, "3DSTATE_MODES5", 1);
+ case 0xd:
+ return debug_modes4(stream, "3DSTATE_MODES4", 1);
+ case 0x15:
+ return debug(stream, "3DSTATE_FOG_COLOR", 1);
+ case 0x16:
+ return debug(stream, "3DSTATE_COORD_SET_BINDINGS", 1);
+ case 0x1c:
+ /* 3DState16NP */
+ switch((cmd >> 19) & 0x1f) {
+ case 0x10:
+ return debug(stream, "3DSTATE_SCISSOR_ENABLE", 1);
+ case 0x11:
+ return debug(stream, "3DSTATE_DEPTH_SUBRECTANGLE_DISABLE", 1);
+ default:
+ (void) debug(stream, "UNKNOWN 0x1c case!", 1);
+ assert(0);
+ break;
+ }
+ break;
+ case 0x1d:
+ /* 3DStateMW */
+ switch ((cmd >> 16) & 0xff) {
+ case 0x0:
+ return debug_map_state(stream, "3DSTATE_MAP_STATE", (cmd & 0x1f) + 2);
+ case 0x1:
+ return debug_sampler_state(stream, "3DSTATE_SAMPLER_STATE", (cmd & 0x1f) + 2);
+ case 0x4:
+ return debug_load_immediate(stream, "3DSTATE_LOAD_STATE_IMMEDIATE", (cmd & 0xf) + 2);
+ case 0x5:
+ return debug_program(stream, "3DSTATE_PIXEL_SHADER_PROGRAM", (cmd & 0x1ff) + 2);
+ case 0x6:
+ return debug(stream, "3DSTATE_PIXEL_SHADER_CONSTANTS", (cmd & 0xff) + 2);
+ case 0x7:
+ return debug_load_indirect(stream, "3DSTATE_LOAD_INDIRECT", (cmd & 0xff) + 2);
+ case 0x80:
+ return debug(stream, "3DSTATE_DRAWING_RECTANGLE", (cmd & 0xffff) + 2);
+ case 0x81:
+ return debug(stream, "3DSTATE_SCISSOR_RECTANGLE", (cmd & 0xffff) + 2);
+ case 0x83:
+ return debug(stream, "3DSTATE_SPAN_STIPPLE", (cmd & 0xffff) + 2);
+ case 0x85:
+ return debug_dest_vars(stream, "3DSTATE_DEST_BUFFER_VARS", (cmd & 0xffff) + 2);
+ case 0x88:
+ return debug(stream, "3DSTATE_CONSTANT_BLEND_COLOR", (cmd & 0xffff) + 2);
+ case 0x89:
+ return debug(stream, "3DSTATE_FOG_MODE", (cmd & 0xffff) + 2);
+ case 0x8e:
+ return debug_buf_info(stream, "3DSTATE_BUFFER_INFO", (cmd & 0xffff) + 2);
+ case 0x97:
+ return debug(stream, "3DSTATE_DEPTH_OFFSET_SCALE", (cmd & 0xffff) + 2);
+ case 0x98:
+ return debug(stream, "3DSTATE_DEFAULT_Z", (cmd & 0xffff) + 2);
+ case 0x99:
+ return debug(stream, "3DSTATE_DEFAULT_DIFFUSE", (cmd & 0xffff) + 2);
+ case 0x9a:
+ return debug(stream, "3DSTATE_DEFAULT_SPECULAR", (cmd & 0xffff) + 2);
+ case 0x9c:
+ return debug(stream, "3DSTATE_CLEAR_PARAMETERS", (cmd & 0xffff) + 2);
+ default:
+ assert(0);
+ return 0;
+ }
+ break;
+ case 0x1e:
+ if (cmd & (1 << 23))
+ return debug(stream, "???", (cmd & 0xffff) + 1);
+ else
+ return debug(stream, "", 1);
+ break;
+ case 0x1f:
+ if ((cmd & (1 << 23)) == 0)
+ return debug_prim(stream, "3DPRIM (inline)", 1, (cmd & 0x1ffff) + 2);
+ else if (cmd & (1 << 17))
+ {
+ if ((cmd & 0xffff) == 0)
+ return debug_variable_length_prim(stream);
+ else
+ return debug_prim(stream, "3DPRIM (indexed)", 0, (((cmd & 0xffff) + 1) / 2) + 1);
+ }
+ else
+ return debug_prim(stream, "3DPRIM (indirect sequential)", 0, 2);
+ break;
+ default:
+ return debug(stream, "", 0);
+ }
+ default:
+ assert(0);
+ return 0;
+ }
+
+ assert(0);
+ return 0;
+}
+
+
+
+void
+i915_dump_batchbuffer( struct intel_batchbuffer *batch )
+{
+ struct debug_stream stream;
+ unsigned *start = (unsigned*)batch->map;
+ unsigned *end = (unsigned*)batch->ptr;
+ unsigned long bytes = (unsigned long) (end - start) * 4;
+ boolean done = FALSE;
+
+ stream.offset = 0;
+ stream.ptr = (char *)start;
+ stream.print_addresses = 0;
+
+ if (!start || !end) {
+ debug_printf( "\n\nBATCH: ???\n");
+ return;
+ }
+
+ debug_printf( "\n\nBATCH: (%d)\n", bytes / 4);
+
+ while (!done &&
+ stream.offset < bytes)
+ {
+ if (!i915_debug_packet( &stream ))
+ break;
+
+ assert(stream.offset <= bytes &&
+ stream.offset >= 0);
+ }
+
+ debug_printf( "END-BATCH\n\n\n");
+}
+
+
diff --git a/src/gallium/drivers/i915simple/i915_debug.h b/src/gallium/drivers/i915simple/i915_debug.h
new file mode 100644
index 0000000000..dd9b86e17b
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_debug.h
@@ -0,0 +1,114 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef I915_DEBUG_H
+#define I915_DEBUG_H
+
+#include <stdarg.h>
+
+struct i915_context;
+
+struct debug_stream
+{
+ unsigned offset; /* current gtt offset */
+ char *ptr; /* pointer to gtt offset zero */
+ char *end; /* pointer to gtt offset zero */
+ unsigned print_addresses;
+};
+
+
+/* Internal functions
+ */
+void i915_disassemble_program(struct debug_stream *stream,
+ const unsigned *program, unsigned sz);
+
+void i915_print_ureg(const char *msg, unsigned ureg);
+
+
+#define DEBUG_BATCH 0x1
+#define DEBUG_BLIT 0x2
+#define DEBUG_BUFFER 0x4
+#define DEBUG_CONSTANTS 0x8
+#define DEBUG_CONTEXT 0x10
+#define DEBUG_DRAW 0x20
+#define DEBUG_DYNAMIC 0x40
+#define DEBUG_FLUSH 0x80
+#define DEBUG_MAP 0x100
+#define DEBUG_PROGRAM 0x200
+#define DEBUG_REGIONS 0x400
+#define DEBUG_SAMPLER 0x800
+#define DEBUG_STATIC 0x1000
+#define DEBUG_SURFACE 0x2000
+#define DEBUG_WINSYS 0x4000
+
+#include "pipe/p_compiler.h"
+
+#if defined(DEBUG) && defined(FILE_DEBUG_FLAG)
+
+#include "pipe/internal/p_winsys_screen.h"
+
+static INLINE void
+I915_DBG(
+ struct i915_context *i915,
+ const char *fmt,
+ ... )
+{
+ if ((i915)->debug & FILE_DEBUG_FLAG) {
+ va_list args;
+
+ va_start( args, fmt );
+ debug_vprintf( fmt, args );
+ va_end( args );
+ }
+}
+
+#else
+
+static INLINE void
+I915_DBG(
+ struct i915_context *i915,
+ const char *fmt,
+ ... )
+{
+ (void) i915;
+ (void) fmt;
+}
+
+#endif
+
+
+struct intel_batchbuffer;
+
+void i915_dump_batchbuffer( struct intel_batchbuffer *i915 );
+
+void i915_debug_init( struct i915_context *i915 );
+
+
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_debug_fp.c b/src/gallium/drivers/i915simple/i915_debug_fp.c
new file mode 100644
index 0000000000..9c5b117b6d
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_debug_fp.c
@@ -0,0 +1,363 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "i915_reg.h"
+#include "i915_debug.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_memory.h"
+
+
+static void
+PRINTF(
+ struct debug_stream *stream,
+ const char *fmt,
+ ... )
+{
+ va_list args;
+
+ va_start( args, fmt );
+ debug_vprintf( fmt, args );
+ va_end( args );
+}
+
+
+static const char *opcodes[0x20] = {
+ "NOP",
+ "ADD",
+ "MOV",
+ "MUL",
+ "MAD",
+ "DP2ADD",
+ "DP3",
+ "DP4",
+ "FRC",
+ "RCP",
+ "RSQ",
+ "EXP",
+ "LOG",
+ "CMP",
+ "MIN",
+ "MAX",
+ "FLR",
+ "MOD",
+ "TRC",
+ "SGE",
+ "SLT",
+ "TEXLD",
+ "TEXLDP",
+ "TEXLDB",
+ "TEXKILL",
+ "DCL",
+ "0x1a",
+ "0x1b",
+ "0x1c",
+ "0x1d",
+ "0x1e",
+ "0x1f",
+};
+
+
+static const int args[0x20] = {
+ 0, /* 0 nop */
+ 2, /* 1 add */
+ 1, /* 2 mov */
+ 2, /* 3 m ul */
+ 3, /* 4 mad */
+ 3, /* 5 dp2add */
+ 2, /* 6 dp3 */
+ 2, /* 7 dp4 */
+ 1, /* 8 frc */
+ 1, /* 9 rcp */
+ 1, /* a rsq */
+ 1, /* b exp */
+ 1, /* c log */
+ 3, /* d cmp */
+ 2, /* e min */
+ 2, /* f max */
+ 1, /* 10 flr */
+ 1, /* 11 mod */
+ 1, /* 12 trc */
+ 2, /* 13 sge */
+ 2, /* 14 slt */
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+
+static const char *regname[0x8] = {
+ "R",
+ "T",
+ "CONST",
+ "S",
+ "OC",
+ "OD",
+ "U",
+ "UNKNOWN",
+};
+
+static void
+print_reg_type_nr(struct debug_stream *stream, unsigned type, unsigned nr)
+{
+ switch (type) {
+ case REG_TYPE_T:
+ switch (nr) {
+ case T_DIFFUSE:
+ PRINTF(stream, "T_DIFFUSE");
+ return;
+ case T_SPECULAR:
+ PRINTF(stream, "T_SPECULAR");
+ return;
+ case T_FOG_W:
+ PRINTF(stream, "T_FOG_W");
+ return;
+ default:
+ PRINTF(stream, "T_TEX%d", nr);
+ return;
+ }
+ case REG_TYPE_OC:
+ if (nr == 0) {
+ PRINTF(stream, "oC");
+ return;
+ }
+ break;
+ case REG_TYPE_OD:
+ if (nr == 0) {
+ PRINTF(stream, "oD");
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ PRINTF(stream, "%s[%d]", regname[type], nr);
+}
+
+#define REG_SWIZZLE_MASK 0x7777
+#define REG_NEGATE_MASK 0x8888
+
+#define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \
+ (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \
+ (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \
+ (SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
+
+
+static void
+print_reg_neg_swizzle(struct debug_stream *stream, unsigned reg)
+{
+ int i;
+
+ if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW &&
+ (reg & REG_NEGATE_MASK) == 0)
+ return;
+
+ PRINTF(stream, ".");
+
+ for (i = 3; i >= 0; i--) {
+ if (reg & (1 << ((i * 4) + 3)))
+ PRINTF(stream, "-");
+
+ switch ((reg >> (i * 4)) & 0x7) {
+ case 0:
+ PRINTF(stream, "x");
+ break;
+ case 1:
+ PRINTF(stream, "y");
+ break;
+ case 2:
+ PRINTF(stream, "z");
+ break;
+ case 3:
+ PRINTF(stream, "w");
+ break;
+ case 4:
+ PRINTF(stream, "0");
+ break;
+ case 5:
+ PRINTF(stream, "1");
+ break;
+ default:
+ PRINTF(stream, "?");
+ break;
+ }
+ }
+}
+
+
+static void
+print_src_reg(struct debug_stream *stream, unsigned dword)
+{
+ unsigned nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK;
+ unsigned type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK;
+ print_reg_type_nr(stream, type, nr);
+ print_reg_neg_swizzle(stream, dword);
+}
+
+
+static void
+print_dest_reg(struct debug_stream *stream, unsigned dword)
+{
+ unsigned nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK;
+ unsigned type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK;
+ print_reg_type_nr(stream, type, nr);
+ if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL)
+ return;
+ PRINTF(stream, ".");
+ if (dword & A0_DEST_CHANNEL_X)
+ PRINTF(stream, "x");
+ if (dword & A0_DEST_CHANNEL_Y)
+ PRINTF(stream, "y");
+ if (dword & A0_DEST_CHANNEL_Z)
+ PRINTF(stream, "z");
+ if (dword & A0_DEST_CHANNEL_W)
+ PRINTF(stream, "w");
+}
+
+
+#define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT))
+#define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT))
+#define GET_SRC2_REG(r) (r)
+
+
+static void
+print_arith_op(struct debug_stream *stream,
+ unsigned opcode, const unsigned * program)
+{
+ if (opcode != A0_NOP) {
+ print_dest_reg(stream, program[0]);
+ if (program[0] & A0_DEST_SATURATE)
+ PRINTF(stream, " = SATURATE ");
+ else
+ PRINTF(stream, " = ");
+ }
+
+ PRINTF(stream, "%s ", opcodes[opcode]);
+
+ print_src_reg(stream, GET_SRC0_REG(program[0], program[1]));
+ if (args[opcode] == 1) {
+ PRINTF(stream, "\n");
+ return;
+ }
+
+ PRINTF(stream, ", ");
+ print_src_reg(stream, GET_SRC1_REG(program[1], program[2]));
+ if (args[opcode] == 2) {
+ PRINTF(stream, "\n");
+ return;
+ }
+
+ PRINTF(stream, ", ");
+ print_src_reg(stream, GET_SRC2_REG(program[2]));
+ PRINTF(stream, "\n");
+ return;
+}
+
+
+static void
+print_tex_op(struct debug_stream *stream,
+ unsigned opcode, const unsigned * program)
+{
+ print_dest_reg(stream, program[0] | A0_DEST_CHANNEL_ALL);
+ PRINTF(stream, " = ");
+
+ PRINTF(stream, "%s ", opcodes[opcode]);
+
+ PRINTF(stream, "S[%d],", program[0] & T0_SAMPLER_NR_MASK);
+
+ print_reg_type_nr(stream,
+ (program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) &
+ REG_TYPE_MASK,
+ (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK);
+ PRINTF(stream, "\n");
+}
+
+static void
+print_texkil_op(struct debug_stream *stream,
+ unsigned opcode, const unsigned * program)
+{
+ PRINTF(stream, "TEXKIL ");
+
+ print_reg_type_nr(stream,
+ (program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) &
+ REG_TYPE_MASK,
+ (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK);
+ PRINTF(stream, "\n");
+}
+
+static void
+print_dcl_op(struct debug_stream *stream,
+ unsigned opcode, const unsigned * program)
+{
+ PRINTF(stream, "%s ", opcodes[opcode]);
+ print_dest_reg(stream,
+ program[0] | A0_DEST_CHANNEL_ALL);
+ PRINTF(stream, "\n");
+}
+
+
+void
+i915_disassemble_program(struct debug_stream *stream,
+ const unsigned * program, unsigned sz)
+{
+ unsigned i;
+
+ PRINTF(stream, "\t\tBEGIN\n");
+
+ assert((program[0] & 0x1ff) + 2 == sz);
+
+ program++;
+ for (i = 1; i < sz; i += 3, program += 3) {
+ unsigned opcode = program[0] & (0x1f << 24);
+
+ PRINTF(stream, "\t\t");
+
+ if ((int) opcode >= A0_NOP && opcode <= A0_SLT)
+ print_arith_op(stream, opcode >> 24, program);
+ else if (opcode >= T0_TEXLD && opcode < T0_TEXKILL)
+ print_tex_op(stream, opcode >> 24, program);
+ else if (opcode == T0_TEXKILL)
+ print_texkil_op(stream, opcode >> 24, program);
+ else if (opcode == D0_DCL)
+ print_dcl_op(stream, opcode >> 24, program);
+ else
+ PRINTF(stream, "Unknown opcode 0x%x\n", opcode);
+ }
+
+ PRINTF(stream, "\t\tEND\n\n");
+}
+
+
diff --git a/src/gallium/drivers/i915simple/i915_flush.c b/src/gallium/drivers/i915simple/i915_flush.c
new file mode 100644
index 0000000000..1582168eba
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_flush.c
@@ -0,0 +1,86 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_defines.h"
+#include "draw/draw_context.h"
+#include "i915_context.h"
+#include "i915_reg.h"
+#include "i915_batch.h"
+
+
+static void i915_flush( struct pipe_context *pipe,
+ unsigned flags,
+ struct pipe_fence_handle **fence )
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ draw_flush(i915->draw);
+
+#if 0
+ /* Do we need to emit an MI_FLUSH command to flush the hardware
+ * caches?
+ */
+ if (flags & (PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE)) {
+ unsigned flush = MI_FLUSH;
+
+ if (!(flags & PIPE_FLUSH_RENDER_CACHE))
+ flush |= INHIBIT_FLUSH_RENDER_CACHE;
+
+ if (flags & PIPE_FLUSH_TEXTURE_CACHE)
+ flush |= FLUSH_MAP_CACHE;
+
+ if (!BEGIN_BATCH(1, 0)) {
+ FLUSH_BATCH(NULL);
+ assert(BEGIN_BATCH(1, 0));
+ }
+ OUT_BATCH( flush );
+ }
+#endif
+
+#if 0
+ if (i915->batch->map == i915->batch->ptr) {
+ return;
+ }
+#endif
+
+ /* If there are no flags, just flush pending commands to hardware:
+ */
+ FLUSH_BATCH(fence);
+ i915->vbo_flushed = 1;
+}
+
+
+
+void i915_init_flush_functions( struct i915_context *i915 )
+{
+ i915->base.flush = i915_flush;
+}
diff --git a/src/gallium/drivers/i915simple/i915_fpc.h b/src/gallium/drivers/i915simple/i915_fpc.h
new file mode 100644
index 0000000000..2f0f99d046
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_fpc.h
@@ -0,0 +1,207 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef I915_FPC_H
+#define I915_FPC_H
+
+
+#include "i915_context.h"
+#include "i915_reg.h"
+
+
+
+#define I915_PROGRAM_SIZE 192
+
+
+
+/**
+ * Program translation state
+ */
+struct i915_fp_compile {
+ struct i915_fragment_shader *shader; /* the shader we're compiling */
+
+ boolean used_constants[I915_MAX_CONSTANT];
+
+ /** maps TGSI immediate index to constant slot */
+ uint num_immediates;
+ uint immediates_map[I915_MAX_CONSTANT];
+ float immediates[I915_MAX_CONSTANT][4];
+
+ boolean first_instruction;
+
+ uint declarations[I915_PROGRAM_SIZE];
+ uint program[I915_PROGRAM_SIZE];
+
+ uint *csr; /**< Cursor, points into program. */
+
+ uint *decl; /**< Cursor, points into declarations. */
+
+ uint decl_s; /**< flags for which s regs need to be decl'd */
+ uint decl_t; /**< flags for which t regs need to be decl'd */
+
+ uint temp_flag; /**< Tracks temporary regs which are in use */
+ uint utemp_flag; /**< Tracks TYPE_U temporary regs which are in use */
+
+ uint nr_tex_indirect;
+ uint nr_tex_insn;
+ uint nr_alu_insn;
+ uint nr_decl_insn;
+
+ boolean error; /**< Set if i915_program_error() is called */
+ uint wpos_tex;
+ uint NumNativeInstructions;
+ uint NumNativeAluInstructions;
+ uint NumNativeTexInstructions;
+ uint NumNativeTexIndirections;
+};
+
+
+/* Having zero and one in here makes the definition of swizzle a lot
+ * easier.
+ */
+#define UREG_TYPE_SHIFT 29
+#define UREG_NR_SHIFT 24
+#define UREG_CHANNEL_X_NEGATE_SHIFT 23
+#define UREG_CHANNEL_X_SHIFT 20
+#define UREG_CHANNEL_Y_NEGATE_SHIFT 19
+#define UREG_CHANNEL_Y_SHIFT 16
+#define UREG_CHANNEL_Z_NEGATE_SHIFT 15
+#define UREG_CHANNEL_Z_SHIFT 12
+#define UREG_CHANNEL_W_NEGATE_SHIFT 11
+#define UREG_CHANNEL_W_SHIFT 8
+#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5
+#define UREG_CHANNEL_ZERO_SHIFT 4
+#define UREG_CHANNEL_ONE_NEGATE_MBZ 1
+#define UREG_CHANNEL_ONE_SHIFT 0
+
+#define UREG_BAD 0xffffffff /* not a valid ureg */
+
+#define X SRC_X
+#define Y SRC_Y
+#define Z SRC_Z
+#define W SRC_W
+#define ZERO SRC_ZERO
+#define ONE SRC_ONE
+
+/* Construct a ureg:
+ */
+#define UREG( type, nr ) (((type)<< UREG_TYPE_SHIFT) | \
+ ((nr) << UREG_NR_SHIFT) | \
+ (X << UREG_CHANNEL_X_SHIFT) | \
+ (Y << UREG_CHANNEL_Y_SHIFT) | \
+ (Z << UREG_CHANNEL_Z_SHIFT) | \
+ (W << UREG_CHANNEL_W_SHIFT) | \
+ (ZERO << UREG_CHANNEL_ZERO_SHIFT) | \
+ (ONE << UREG_CHANNEL_ONE_SHIFT))
+
+#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20))
+#define CHANNEL_SRC( src, channel ) (src>>(channel*4))
+
+#define GET_UREG_TYPE(reg) (((reg)>>UREG_TYPE_SHIFT)&REG_TYPE_MASK)
+#define GET_UREG_NR(reg) (((reg)>>UREG_NR_SHIFT)&REG_NR_MASK)
+
+
+
+#define UREG_XYZW_CHANNEL_MASK 0x00ffff00
+
+/* One neat thing about the UREG representation:
+ */
+static INLINE int
+swizzle(int reg, uint x, uint y, uint z, uint w)
+{
+ assert(x <= SRC_ONE);
+ assert(y <= SRC_ONE);
+ assert(z <= SRC_ONE);
+ assert(w <= SRC_ONE);
+ return ((reg & ~UREG_XYZW_CHANNEL_MASK) |
+ CHANNEL_SRC(GET_CHANNEL_SRC(reg, x), 0) |
+ CHANNEL_SRC(GET_CHANNEL_SRC(reg, y), 1) |
+ CHANNEL_SRC(GET_CHANNEL_SRC(reg, z), 2) |
+ CHANNEL_SRC(GET_CHANNEL_SRC(reg, w), 3));
+}
+
+
+
+/***********************************************************************
+ * Public interface for the compiler
+ */
+extern void
+i915_translate_fragment_program( struct i915_context *i915,
+ struct i915_fragment_shader *fs);
+
+
+
+extern uint i915_get_temp(struct i915_fp_compile *p);
+extern uint i915_get_utemp(struct i915_fp_compile *p);
+extern void i915_release_utemps(struct i915_fp_compile *p);
+
+
+extern uint i915_emit_texld(struct i915_fp_compile *p,
+ uint dest,
+ uint destmask,
+ uint sampler, uint coord, uint op);
+
+extern uint i915_emit_arith(struct i915_fp_compile *p,
+ uint op,
+ uint dest,
+ uint mask,
+ uint saturate,
+ uint src0, uint src1, uint src2);
+
+extern uint i915_emit_decl(struct i915_fp_compile *p,
+ uint type, uint nr, uint d0_flags);
+
+
+extern uint i915_emit_const1f(struct i915_fp_compile *p, float c0);
+
+extern uint i915_emit_const2f(struct i915_fp_compile *p,
+ float c0, float c1);
+
+extern uint i915_emit_const4fv(struct i915_fp_compile *p,
+ const float * c);
+
+extern uint i915_emit_const4f(struct i915_fp_compile *p,
+ float c0, float c1,
+ float c2, float c3);
+
+
+/*======================================================================
+ * i915_fpc_debug.c
+ */
+extern void i915_disassemble_program(const uint * program, uint sz);
+
+
+/*======================================================================
+ * i915_fpc_translate.c
+ */
+
+extern void
+i915_program_error(struct i915_fp_compile *p, const char *msg, ...);
+
+
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_fpc_emit.c b/src/gallium/drivers/i915simple/i915_fpc_emit.c
new file mode 100644
index 0000000000..b054ce41d3
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_fpc_emit.c
@@ -0,0 +1,375 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "i915_reg.h"
+#include "i915_context.h"
+#include "i915_fpc.h"
+#include "util/u_math.h"
+
+
+#define A0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
+#define D0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
+#define T0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
+#define A0_SRC0( reg ) (((reg)&UREG_MASK)>>UREG_A0_SRC0_SHIFT_LEFT)
+#define A1_SRC0( reg ) (((reg)&UREG_MASK)<<UREG_A1_SRC0_SHIFT_RIGHT)
+#define A1_SRC1( reg ) (((reg)&UREG_MASK)>>UREG_A1_SRC1_SHIFT_LEFT)
+#define A2_SRC1( reg ) (((reg)&UREG_MASK)<<UREG_A2_SRC1_SHIFT_RIGHT)
+#define A2_SRC2( reg ) (((reg)&UREG_MASK)>>UREG_A2_SRC2_SHIFT_LEFT)
+
+/* These are special, and don't have swizzle/negate bits.
+ */
+#define T0_SAMPLER( reg ) (GET_UREG_NR(reg)<<T0_SAMPLER_NR_SHIFT)
+#define T1_ADDRESS_REG( reg ) ((GET_UREG_NR(reg)<<T1_ADDRESS_REG_NR_SHIFT) | \
+ (GET_UREG_TYPE(reg)<<T1_ADDRESS_REG_TYPE_SHIFT))
+
+
+/* Macros for translating UREG's into the various register fields used
+ * by the I915 programmable unit.
+ */
+#define UREG_A0_DEST_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_DEST_TYPE_SHIFT)
+#define UREG_A0_SRC0_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_SRC0_TYPE_SHIFT)
+#define UREG_A1_SRC0_SHIFT_RIGHT (A1_SRC0_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
+#define UREG_A1_SRC1_SHIFT_LEFT (UREG_TYPE_SHIFT - A1_SRC1_TYPE_SHIFT)
+#define UREG_A2_SRC1_SHIFT_RIGHT (A2_SRC1_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
+#define UREG_A2_SRC2_SHIFT_LEFT (UREG_TYPE_SHIFT - A2_SRC2_TYPE_SHIFT)
+
+#define UREG_MASK 0xffffff00
+#define UREG_TYPE_NR_MASK ((REG_TYPE_MASK << UREG_TYPE_SHIFT) | \
+ (REG_NR_MASK << UREG_NR_SHIFT))
+
+
+uint
+i915_get_temp(struct i915_fp_compile *p)
+{
+ int bit = ffs(~p->temp_flag);
+ if (!bit) {
+ i915_program_error(p, "i915_get_temp: out of temporaries\n");
+ return 0;
+ }
+
+ p->temp_flag |= 1 << (bit - 1);
+ return bit - 1;
+}
+
+
+static void
+i915_release_temp(struct i915_fp_compile *p, int reg)
+{
+ p->temp_flag &= ~(1 << reg);
+}
+
+
+/**
+ * Get unpreserved temporary, a temp whose value is not preserved between
+ * PS program phases.
+ */
+uint
+i915_get_utemp(struct i915_fp_compile * p)
+{
+ int bit = ffs(~p->utemp_flag);
+ if (!bit) {
+ i915_program_error(p, "i915_get_utemp: out of temporaries\n");
+ return 0;
+ }
+
+ p->utemp_flag |= 1 << (bit - 1);
+ return UREG(REG_TYPE_U, (bit - 1));
+}
+
+void
+i915_release_utemps(struct i915_fp_compile *p)
+{
+ p->utemp_flag = ~0x7;
+}
+
+
+uint
+i915_emit_decl(struct i915_fp_compile *p,
+ uint type, uint nr, uint d0_flags)
+{
+ uint reg = UREG(type, nr);
+
+ if (type == REG_TYPE_T) {
+ if (p->decl_t & (1 << nr))
+ return reg;
+
+ p->decl_t |= (1 << nr);
+ }
+ else if (type == REG_TYPE_S) {
+ if (p->decl_s & (1 << nr))
+ return reg;
+
+ p->decl_s |= (1 << nr);
+ }
+ else
+ return reg;
+
+ *(p->decl++) = (D0_DCL | D0_DEST(reg) | d0_flags);
+ *(p->decl++) = D1_MBZ;
+ *(p->decl++) = D2_MBZ;
+
+ p->nr_decl_insn++;
+ return reg;
+}
+
+uint
+i915_emit_arith(struct i915_fp_compile * p,
+ uint op,
+ uint dest,
+ uint mask,
+ uint saturate, uint src0, uint src1, uint src2)
+{
+ uint c[3];
+ uint nr_const = 0;
+
+ assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
+ dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
+ assert(dest);
+
+ if (GET_UREG_TYPE(src0) == REG_TYPE_CONST)
+ c[nr_const++] = 0;
+ if (GET_UREG_TYPE(src1) == REG_TYPE_CONST)
+ c[nr_const++] = 1;
+ if (GET_UREG_TYPE(src2) == REG_TYPE_CONST)
+ c[nr_const++] = 2;
+
+ /* Recursively call this function to MOV additional const values
+ * into temporary registers. Use utemp registers for this -
+ * currently shouldn't be possible to run out, but keep an eye on
+ * this.
+ */
+ if (nr_const > 1) {
+ uint s[3], first, i, old_utemp_flag;
+
+ s[0] = src0;
+ s[1] = src1;
+ s[2] = src2;
+ old_utemp_flag = p->utemp_flag;
+
+ first = GET_UREG_NR(s[c[0]]);
+ for (i = 1; i < nr_const; i++) {
+ if (GET_UREG_NR(s[c[i]]) != first) {
+ uint tmp = i915_get_utemp(p);
+
+ i915_emit_arith(p, A0_MOV, tmp, A0_DEST_CHANNEL_ALL, 0,
+ s[c[i]], 0, 0);
+ s[c[i]] = tmp;
+ }
+ }
+
+ src0 = s[0];
+ src1 = s[1];
+ src2 = s[2];
+ p->utemp_flag = old_utemp_flag; /* restore */
+ }
+
+ *(p->csr++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0));
+ *(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1));
+ *(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2));
+
+ p->nr_alu_insn++;
+ return dest;
+}
+
+
+/**
+ * Emit a texture load or texkill instruction.
+ * \param dest the dest i915 register
+ * \param destmask the dest register writemask
+ * \param sampler the i915 sampler register
+ * \param coord the i915 source texcoord operand
+ * \param opcode the instruction opcode
+ */
+uint i915_emit_texld( struct i915_fp_compile *p,
+ uint dest,
+ uint destmask,
+ uint sampler,
+ uint coord,
+ uint opcode )
+{
+ const uint k = UREG(GET_UREG_TYPE(coord), GET_UREG_NR(coord));
+ int temp = -1;
+
+ if (coord != k) {
+ /* texcoord is swizzled or negated. Need to allocate a new temporary
+ * register (a utemp / unpreserved temp) won't do.
+ */
+ uint tempReg;
+
+ temp = i915_get_temp(p); /* get temp reg index */
+ tempReg = UREG(REG_TYPE_R, temp); /* make i915 register */
+
+ i915_emit_arith( p, A0_MOV,
+ tempReg, A0_DEST_CHANNEL_ALL, /* dest reg, writemask */
+ 0, /* saturate */
+ coord, 0, 0 ); /* src0, src1, src2 */
+
+ /* new src texcoord is tempReg */
+ coord = tempReg;
+ }
+
+ /* Don't worry about saturate as we only support
+ */
+ if (destmask != A0_DEST_CHANNEL_ALL) {
+ /* if not writing to XYZW... */
+ uint tmp = i915_get_utemp(p);
+ i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, opcode );
+ i915_emit_arith( p, A0_MOV, dest, destmask, 0, tmp, 0, 0 );
+ /* XXX release utemp here? */
+ }
+ else {
+ assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
+ assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
+
+ /* is the sampler coord a texcoord input reg? */
+ if (GET_UREG_TYPE(coord) != REG_TYPE_T) {
+ p->nr_tex_indirect++;
+ }
+
+ *(p->csr++) = (opcode |
+ T0_DEST( dest ) |
+ T0_SAMPLER( sampler ));
+
+ *(p->csr++) = T1_ADDRESS_REG( coord );
+ *(p->csr++) = T2_MBZ;
+
+ p->nr_tex_insn++;
+ }
+
+ if (temp >= 0)
+ i915_release_temp(p, temp);
+
+ return dest;
+}
+
+
+uint
+i915_emit_const1f(struct i915_fp_compile * p, float c0)
+{
+ struct i915_fragment_shader *ifs = p->shader;
+ unsigned reg, idx;
+
+ if (c0 == 0.0)
+ return swizzle(UREG(REG_TYPE_R, 0), ZERO, ZERO, ZERO, ZERO);
+ if (c0 == 1.0)
+ return swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE);
+
+ for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
+ if (ifs->constant_flags[reg] == I915_CONSTFLAG_USER)
+ continue;
+ for (idx = 0; idx < 4; idx++) {
+ if (!(ifs->constant_flags[reg] & (1 << idx)) ||
+ ifs->constants[reg][idx] == c0) {
+ ifs->constants[reg][idx] = c0;
+ ifs->constant_flags[reg] |= 1 << idx;
+ if (reg + 1 > ifs->num_constants)
+ ifs->num_constants = reg + 1;
+ return swizzle(UREG(REG_TYPE_CONST, reg), idx, ZERO, ZERO, ONE);
+ }
+ }
+ }
+
+ i915_program_error(p, "i915_emit_const1f: out of constants\n");
+ return 0;
+}
+
+uint
+i915_emit_const2f(struct i915_fp_compile * p, float c0, float c1)
+{
+ struct i915_fragment_shader *ifs = p->shader;
+ unsigned reg, idx;
+
+ if (c0 == 0.0)
+ return swizzle(i915_emit_const1f(p, c1), ZERO, X, Z, W);
+ if (c0 == 1.0)
+ return swizzle(i915_emit_const1f(p, c1), ONE, X, Z, W);
+
+ if (c1 == 0.0)
+ return swizzle(i915_emit_const1f(p, c0), X, ZERO, Z, W);
+ if (c1 == 1.0)
+ return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W);
+
+ for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
+ if (ifs->constant_flags[reg] == 0xf ||
+ ifs->constant_flags[reg] == I915_CONSTFLAG_USER)
+ continue;
+ for (idx = 0; idx < 3; idx++) {
+ if (!(ifs->constant_flags[reg] & (3 << idx))) {
+ ifs->constants[reg][idx + 0] = c0;
+ ifs->constants[reg][idx + 1] = c1;
+ ifs->constant_flags[reg] |= 3 << idx;
+ if (reg + 1 > ifs->num_constants)
+ ifs->num_constants = reg + 1;
+ return swizzle(UREG(REG_TYPE_CONST, reg), idx, idx + 1, ZERO, ONE);
+ }
+ }
+ }
+
+ i915_program_error(p, "i915_emit_const2f: out of constants\n");
+ return 0;
+}
+
+
+
+uint
+i915_emit_const4f(struct i915_fp_compile * p,
+ float c0, float c1, float c2, float c3)
+{
+ struct i915_fragment_shader *ifs = p->shader;
+ unsigned reg;
+
+ for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
+ if (ifs->constant_flags[reg] == 0xf &&
+ ifs->constants[reg][0] == c0 &&
+ ifs->constants[reg][1] == c1 &&
+ ifs->constants[reg][2] == c2 &&
+ ifs->constants[reg][3] == c3) {
+ return UREG(REG_TYPE_CONST, reg);
+ }
+ else if (ifs->constant_flags[reg] == 0) {
+
+ ifs->constants[reg][0] = c0;
+ ifs->constants[reg][1] = c1;
+ ifs->constants[reg][2] = c2;
+ ifs->constants[reg][3] = c3;
+ ifs->constant_flags[reg] = 0xf;
+ if (reg + 1 > ifs->num_constants)
+ ifs->num_constants = reg + 1;
+ return UREG(REG_TYPE_CONST, reg);
+ }
+ }
+
+ i915_program_error(p, "i915_emit_const4f: out of constants\n");
+ return 0;
+}
+
+
+uint
+i915_emit_const4fv(struct i915_fp_compile * p, const float * c)
+{
+ return i915_emit_const4f(p, c[0], c[1], c[2], c[3]);
+}
diff --git a/src/gallium/drivers/i915simple/i915_fpc_translate.c b/src/gallium/drivers/i915simple/i915_fpc_translate.c
new file mode 100644
index 0000000000..89504ced27
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_fpc_translate.c
@@ -0,0 +1,1202 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <stdarg.h>
+
+#include "i915_reg.h"
+#include "i915_context.h"
+#include "i915_fpc.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_string.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "draw/draw_vertex.h"
+
+
+/**
+ * Simple pass-through fragment shader to use when we don't have
+ * a real shader (or it fails to compile for some reason).
+ */
+static unsigned passthrough[] =
+{
+ _3DSTATE_PIXEL_SHADER_PROGRAM | ((2*3)-1),
+
+ /* declare input color:
+ */
+ (D0_DCL |
+ (REG_TYPE_T << D0_TYPE_SHIFT) |
+ (T_DIFFUSE << D0_NR_SHIFT) |
+ D0_CHANNEL_ALL),
+ 0,
+ 0,
+
+ /* move to output color:
+ */
+ (A0_MOV |
+ (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
+ A0_DEST_CHANNEL_ALL |
+ (REG_TYPE_T << A0_SRC0_TYPE_SHIFT) |
+ (T_DIFFUSE << A0_SRC0_NR_SHIFT)),
+ 0x01230000, /* .xyzw */
+ 0
+};
+
+
+/* 1, -1/3!, 1/5!, -1/7! */
+static const float sin_constants[4] = { 1.0,
+ -1.0f / (3 * 2 * 1),
+ 1.0f / (5 * 4 * 3 * 2 * 1),
+ -1.0f / (7 * 6 * 5 * 4 * 3 * 2 * 1)
+};
+
+/* 1, -1/2!, 1/4!, -1/6! */
+static const float cos_constants[4] = { 1.0,
+ -1.0f / (2 * 1),
+ 1.0f / (4 * 3 * 2 * 1),
+ -1.0f / (6 * 5 * 4 * 3 * 2 * 1)
+};
+
+
+
+/**
+ * component-wise negation of ureg
+ */
+static INLINE int
+negate(int reg, int x, int y, int z, int w)
+{
+ /* Another neat thing about the UREG representation */
+ return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) |
+ ((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) |
+ ((z & 1) << UREG_CHANNEL_Z_NEGATE_SHIFT) |
+ ((w & 1) << UREG_CHANNEL_W_NEGATE_SHIFT));
+}
+
+
+/**
+ * In the event of a translation failure, we'll generate a simple color
+ * pass-through program.
+ */
+static void
+i915_use_passthrough_shader(struct i915_fragment_shader *fs)
+{
+ fs->program = (uint *) MALLOC(sizeof(passthrough));
+ if (fs->program) {
+ memcpy(fs->program, passthrough, sizeof(passthrough));
+ fs->program_len = Elements(passthrough);
+ }
+ fs->num_constants = 0;
+}
+
+
+void
+i915_program_error(struct i915_fp_compile *p, const char *msg, ...)
+{
+ va_list args;
+ char buffer[1024];
+
+ debug_printf("i915_program_error: ");
+ va_start( args, msg );
+ util_vsnprintf( buffer, sizeof(buffer), msg, args );
+ va_end( args );
+ debug_printf(buffer);
+ debug_printf("\n");
+
+ p->error = 1;
+}
+
+
+
+/**
+ * Construct a ureg for the given source register. Will emit
+ * constants, apply swizzling and negation as needed.
+ */
+static uint
+src_vector(struct i915_fp_compile *p,
+ const struct tgsi_full_src_register *source)
+{
+ uint index = source->SrcRegister.Index;
+ uint src = 0, sem_name, sem_ind;
+
+ switch (source->SrcRegister.File) {
+ case TGSI_FILE_TEMPORARY:
+ if (source->SrcRegister.Index >= I915_MAX_TEMPORARY) {
+ i915_program_error(p, "Exceeded max temporary reg");
+ return 0;
+ }
+ src = UREG(REG_TYPE_R, index);
+ break;
+ case TGSI_FILE_INPUT:
+ /* XXX: Packing COL1, FOGC into a single attribute works for
+ * texenv programs, but will fail for real fragment programs
+ * that use these attributes and expect them to be a full 4
+ * components wide. Could use a texcoord to pass these
+ * attributes if necessary, but that won't work in the general
+ * case.
+ *
+ * We also use a texture coordinate to pass wpos when possible.
+ */
+
+ sem_name = p->shader->info.input_semantic_name[index];
+ sem_ind = p->shader->info.input_semantic_index[index];
+
+ switch (sem_name) {
+ case TGSI_SEMANTIC_POSITION:
+ debug_printf("SKIP SEM POS\n");
+ /*
+ assert(p->wpos_tex != -1);
+ src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL);
+ */
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ if (sem_ind == 0) {
+ src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
+ }
+ else {
+ /* secondary color */
+ assert(sem_ind == 1);
+ src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ);
+ src = swizzle(src, X, Y, Z, ONE);
+ }
+ break;
+ case TGSI_SEMANTIC_FOG:
+ src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W);
+ src = swizzle(src, W, W, W, W);
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ /* usually a texcoord */
+ src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + sem_ind, D0_CHANNEL_ALL);
+ break;
+ default:
+ i915_program_error(p, "Bad source->Index");
+ return 0;
+ }
+ break;
+
+ case TGSI_FILE_IMMEDIATE:
+ assert(index < p->num_immediates);
+ index = p->immediates_map[index];
+ /* fall-through */
+ case TGSI_FILE_CONSTANT:
+ src = UREG(REG_TYPE_CONST, index);
+ break;
+
+ default:
+ i915_program_error(p, "Bad source->File");
+ return 0;
+ }
+
+ if (source->SrcRegister.Extended) {
+ src = swizzle(src,
+ source->SrcRegisterExtSwz.ExtSwizzleX,
+ source->SrcRegisterExtSwz.ExtSwizzleY,
+ source->SrcRegisterExtSwz.ExtSwizzleZ,
+ source->SrcRegisterExtSwz.ExtSwizzleW);
+ }
+ else {
+ src = swizzle(src,
+ source->SrcRegister.SwizzleX,
+ source->SrcRegister.SwizzleY,
+ source->SrcRegister.SwizzleZ,
+ source->SrcRegister.SwizzleW);
+ }
+
+
+ /* There's both negate-all-components and per-component negation.
+ * Try to handle both here.
+ */
+ {
+ int nx = source->SrcRegisterExtSwz.NegateX;
+ int ny = source->SrcRegisterExtSwz.NegateY;
+ int nz = source->SrcRegisterExtSwz.NegateZ;
+ int nw = source->SrcRegisterExtSwz.NegateW;
+ if (source->SrcRegister.Negate) {
+ nx = !nx;
+ ny = !ny;
+ nz = !nz;
+ nw = !nw;
+ }
+ src = negate(src, nx, ny, nz, nw);
+ }
+
+ /* no abs() or post-abs negation */
+#if 0
+ /* XXX assertions disabled to allow arbfplight.c to run */
+ /* XXX enable these assertions, or fix things */
+ assert(!source->SrcRegisterExtMod.Absolute);
+ assert(!source->SrcRegisterExtMod.Negate);
+#endif
+ return src;
+}
+
+
+/**
+ * Construct a ureg for a destination register.
+ */
+static uint
+get_result_vector(struct i915_fp_compile *p,
+ const struct tgsi_full_dst_register *dest)
+{
+ switch (dest->DstRegister.File) {
+ case TGSI_FILE_OUTPUT:
+ {
+ uint sem_name = p->shader->info.output_semantic_name[dest->DstRegister.Index];
+ switch (sem_name) {
+ case TGSI_SEMANTIC_POSITION:
+ return UREG(REG_TYPE_OD, 0);
+ case TGSI_SEMANTIC_COLOR:
+ return UREG(REG_TYPE_OC, 0);
+ default:
+ i915_program_error(p, "Bad inst->DstReg.Index/semantics");
+ return 0;
+ }
+ }
+ case TGSI_FILE_TEMPORARY:
+ return UREG(REG_TYPE_R, dest->DstRegister.Index);
+ default:
+ i915_program_error(p, "Bad inst->DstReg.File");
+ return 0;
+ }
+}
+
+
+/**
+ * Compute flags for saturation and writemask.
+ */
+static uint
+get_result_flags(const struct tgsi_full_instruction *inst)
+{
+ const uint writeMask
+ = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ uint flags = 0x0;
+
+ if (inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE)
+ flags |= A0_DEST_SATURATE;
+
+ if (writeMask & TGSI_WRITEMASK_X)
+ flags |= A0_DEST_CHANNEL_X;
+ if (writeMask & TGSI_WRITEMASK_Y)
+ flags |= A0_DEST_CHANNEL_Y;
+ if (writeMask & TGSI_WRITEMASK_Z)
+ flags |= A0_DEST_CHANNEL_Z;
+ if (writeMask & TGSI_WRITEMASK_W)
+ flags |= A0_DEST_CHANNEL_W;
+
+ return flags;
+}
+
+
+/**
+ * Convert TGSI_TEXTURE_x token to DO_SAMPLE_TYPE_x token
+ */
+static uint
+translate_tex_src_target(struct i915_fp_compile *p, uint tex)
+{
+ switch (tex) {
+ case TGSI_TEXTURE_SHADOW1D:
+ /* fall-through */
+ case TGSI_TEXTURE_1D:
+ return D0_SAMPLE_TYPE_2D;
+
+ case TGSI_TEXTURE_SHADOW2D:
+ /* fall-through */
+ case TGSI_TEXTURE_2D:
+ return D0_SAMPLE_TYPE_2D;
+
+ case TGSI_TEXTURE_SHADOWRECT:
+ /* fall-through */
+ case TGSI_TEXTURE_RECT:
+ return D0_SAMPLE_TYPE_2D;
+
+ case TGSI_TEXTURE_3D:
+ return D0_SAMPLE_TYPE_VOLUME;
+
+ case TGSI_TEXTURE_CUBE:
+ return D0_SAMPLE_TYPE_CUBE;
+
+ default:
+ i915_program_error(p, "TexSrc type");
+ return 0;
+ }
+}
+
+
+/**
+ * Generate texel lookup instruction.
+ */
+static void
+emit_tex(struct i915_fp_compile *p,
+ const struct tgsi_full_instruction *inst,
+ uint opcode)
+{
+ uint texture = inst->InstructionExtTexture.Texture;
+ uint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
+ uint tex = translate_tex_src_target( p, texture );
+ uint sampler = i915_emit_decl(p, REG_TYPE_S, unit, tex);
+ uint coord = src_vector( p, &inst->FullSrcRegisters[0]);
+
+ i915_emit_texld( p,
+ get_result_vector( p, &inst->FullDstRegisters[0] ),
+ get_result_flags( inst ),
+ sampler,
+ coord,
+ opcode);
+}
+
+
+/**
+ * Generate a simple arithmetic instruction
+ * \param opcode the i915 opcode
+ * \param numArgs the number of input/src arguments
+ */
+static void
+emit_simple_arith(struct i915_fp_compile *p,
+ const struct tgsi_full_instruction *inst,
+ uint opcode, uint numArgs)
+{
+ uint arg1, arg2, arg3;
+
+ assert(numArgs <= 3);
+
+ arg1 = (numArgs < 1) ? 0 : src_vector( p, &inst->FullSrcRegisters[0] );
+ arg2 = (numArgs < 2) ? 0 : src_vector( p, &inst->FullSrcRegisters[1] );
+ arg3 = (numArgs < 3) ? 0 : src_vector( p, &inst->FullSrcRegisters[2] );
+
+ i915_emit_arith( p,
+ opcode,
+ get_result_vector( p, &inst->FullDstRegisters[0]),
+ get_result_flags( inst ), 0,
+ arg1,
+ arg2,
+ arg3 );
+}
+
+
+/** As above, but swap the first two src regs */
+static void
+emit_simple_arith_swap2(struct i915_fp_compile *p,
+ const struct tgsi_full_instruction *inst,
+ uint opcode, uint numArgs)
+{
+ struct tgsi_full_instruction inst2;
+
+ assert(numArgs == 2);
+
+ /* transpose first two registers */
+ inst2 = *inst;
+ inst2.FullSrcRegisters[0] = inst->FullSrcRegisters[1];
+ inst2.FullSrcRegisters[1] = inst->FullSrcRegisters[0];
+
+ emit_simple_arith(p, &inst2, opcode, numArgs);
+}
+
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+/*
+ * Translate TGSI instruction to i915 instruction.
+ *
+ * Possible concerns:
+ *
+ * SIN, COS -- could use another taylor step?
+ * LIT -- results seem a little different to sw mesa
+ * LOG -- different to mesa on negative numbers, but this is conformant.
+ */
+static void
+i915_translate_instruction(struct i915_fp_compile *p,
+ const struct tgsi_full_instruction *inst)
+{
+ uint writemask;
+ uint src0, src1, src2, flags;
+ uint tmp = 0;
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ i915_emit_arith(p,
+ A0_MAX,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ src0, negate(src0, 1, 1, 1, 1), 0);
+ break;
+
+ case TGSI_OPCODE_ADD:
+ emit_simple_arith(p, inst, A0_ADD, 2);
+ break;
+
+ case TGSI_OPCODE_CMP:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ src1 = src_vector(p, &inst->FullSrcRegisters[1]);
+ src2 = src_vector(p, &inst->FullSrcRegisters[2]);
+ i915_emit_arith(p, A0_CMP,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst),
+ 0, src0, src2, src1); /* NOTE: order of src2, src1 */
+ break;
+
+ case TGSI_OPCODE_COS:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ tmp = i915_get_utemp(p);
+
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_X, 0,
+ src0, i915_emit_const1f(p, 1.0f / (float) (M_PI * 2.0)), 0);
+
+ i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0);
+
+ /* By choosing different taylor constants, could get rid of this mul:
+ */
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_X, 0,
+ tmp, i915_emit_const1f(p, (float) (M_PI * 2.0)), 0);
+
+ /*
+ * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1
+ * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, 1
+ * t0 = MUL t0.xxz1 t0.z111 ; x^6 x^4 x^2 1
+ * result = DP4 t0, cos_constants
+ */
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_XY, 0,
+ swizzle(tmp, X, X, ONE, ONE),
+ swizzle(tmp, X, ONE, ONE, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_XYZ, 0,
+ swizzle(tmp, X, Y, X, ONE),
+ swizzle(tmp, X, X, ONE, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_XYZ, 0,
+ swizzle(tmp, X, X, Z, ONE),
+ swizzle(tmp, Z, ONE, ONE, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_DP4,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ swizzle(tmp, ONE, Z, Y, X),
+ i915_emit_const4fv(p, cos_constants), 0);
+ break;
+
+ case TGSI_OPCODE_DP3:
+ emit_simple_arith(p, inst, A0_DP3, 2);
+ break;
+
+ case TGSI_OPCODE_DP4:
+ emit_simple_arith(p, inst, A0_DP4, 2);
+ break;
+
+ case TGSI_OPCODE_DPH:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ src1 = src_vector(p, &inst->FullSrcRegisters[1]);
+
+ i915_emit_arith(p,
+ A0_DP4,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ swizzle(src0, X, Y, Z, ONE), src1, 0);
+ break;
+
+ case TGSI_OPCODE_DST:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ src1 = src_vector(p, &inst->FullSrcRegisters[1]);
+
+ /* result[0] = 1 * 1;
+ * result[1] = a[1] * b[1];
+ * result[2] = a[2] * 1;
+ * result[3] = 1 * b[3];
+ */
+ i915_emit_arith(p,
+ A0_MUL,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ swizzle(src0, ONE, Y, Z, ONE),
+ swizzle(src1, ONE, Y, ONE, W), 0);
+ break;
+
+ case TGSI_OPCODE_END:
+ /* no-op */
+ break;
+
+ case TGSI_OPCODE_EX2:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+
+ i915_emit_arith(p,
+ A0_EXP,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ swizzle(src0, X, X, X, X), 0, 0);
+ break;
+
+ case TGSI_OPCODE_FLR:
+ emit_simple_arith(p, inst, A0_FLR, 1);
+ break;
+
+ case TGSI_OPCODE_FRC:
+ emit_simple_arith(p, inst, A0_FRC, 1);
+ break;
+
+ case TGSI_OPCODE_KIL:
+ /* kill if src[0].x < 0 || src[0].y < 0 ... */
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ tmp = i915_get_utemp(p);
+
+ i915_emit_texld(p,
+ tmp, /* dest reg: a dummy reg */
+ A0_DEST_CHANNEL_ALL, /* dest writemask */
+ 0, /* sampler */
+ src0, /* coord*/
+ T0_TEXKILL); /* opcode */
+ break;
+
+ case TGSI_OPCODE_KILP:
+ assert(0); /* not tested yet */
+ break;
+
+ case TGSI_OPCODE_LG2:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+
+ i915_emit_arith(p,
+ A0_LOG,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ swizzle(src0, X, X, X, X), 0, 0);
+ break;
+
+ case TGSI_OPCODE_LIT:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ tmp = i915_get_utemp(p);
+
+ /* tmp = max( a.xyzw, a.00zw )
+ * XXX: Clamp tmp.w to -128..128
+ * tmp.y = log(tmp.y)
+ * tmp.y = tmp.w * tmp.y
+ * tmp.y = exp(tmp.y)
+ * result = cmp (a.11-x1, a.1x01, a.1xy1 )
+ */
+ i915_emit_arith(p, A0_MAX, tmp, A0_DEST_CHANNEL_ALL, 0,
+ src0, swizzle(src0, ZERO, ZERO, Z, W), 0);
+
+ i915_emit_arith(p, A0_LOG, tmp, A0_DEST_CHANNEL_Y, 0,
+ swizzle(tmp, Y, Y, Y, Y), 0, 0);
+
+ i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_Y, 0,
+ swizzle(tmp, ZERO, Y, ZERO, ZERO),
+ swizzle(tmp, ZERO, W, ZERO, ZERO), 0);
+
+ i915_emit_arith(p, A0_EXP, tmp, A0_DEST_CHANNEL_Y, 0,
+ swizzle(tmp, Y, Y, Y, Y), 0, 0);
+
+ i915_emit_arith(p, A0_CMP,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ negate(swizzle(tmp, ONE, ONE, X, ONE), 0, 0, 1, 0),
+ swizzle(tmp, ONE, X, ZERO, ONE),
+ swizzle(tmp, ONE, X, Y, ONE));
+
+ break;
+
+ case TGSI_OPCODE_LRP:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ src1 = src_vector(p, &inst->FullSrcRegisters[1]);
+ src2 = src_vector(p, &inst->FullSrcRegisters[2]);
+ flags = get_result_flags(inst);
+ tmp = i915_get_utemp(p);
+
+ /* b*a + c*(1-a)
+ *
+ * b*a + c - ca
+ *
+ * tmp = b*a + c,
+ * result = (-c)*a + tmp
+ */
+ i915_emit_arith(p, A0_MAD, tmp,
+ flags & A0_DEST_CHANNEL_ALL, 0, src1, src0, src2);
+
+ i915_emit_arith(p, A0_MAD,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ flags, 0, negate(src2, 1, 1, 1, 1), src0, tmp);
+ break;
+
+ case TGSI_OPCODE_MAD:
+ emit_simple_arith(p, inst, A0_MAD, 3);
+ break;
+
+ case TGSI_OPCODE_MAX:
+ emit_simple_arith(p, inst, A0_MAX, 2);
+ break;
+
+ case TGSI_OPCODE_MIN:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ src1 = src_vector(p, &inst->FullSrcRegisters[1]);
+ tmp = i915_get_utemp(p);
+ flags = get_result_flags(inst);
+
+ i915_emit_arith(p,
+ A0_MAX,
+ tmp, flags & A0_DEST_CHANNEL_ALL, 0,
+ negate(src0, 1, 1, 1, 1),
+ negate(src1, 1, 1, 1, 1), 0);
+
+ i915_emit_arith(p,
+ A0_MOV,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ flags, 0, negate(tmp, 1, 1, 1, 1), 0, 0);
+ break;
+
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ emit_simple_arith(p, inst, A0_MOV, 1);
+ break;
+
+ case TGSI_OPCODE_MUL:
+ emit_simple_arith(p, inst, A0_MUL, 2);
+ break;
+
+ case TGSI_OPCODE_POW:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ src1 = src_vector(p, &inst->FullSrcRegisters[1]);
+ tmp = i915_get_utemp(p);
+ flags = get_result_flags(inst);
+
+ /* XXX: masking on intermediate values, here and elsewhere.
+ */
+ i915_emit_arith(p,
+ A0_LOG,
+ tmp, A0_DEST_CHANNEL_X, 0,
+ swizzle(src0, X, X, X, X), 0, 0);
+
+ i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_X, 0, tmp, src1, 0);
+
+ i915_emit_arith(p,
+ A0_EXP,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ flags, 0, swizzle(tmp, X, X, X, X), 0, 0);
+ break;
+
+ case TGSI_OPCODE_RET:
+ /* XXX: no-op? */
+ break;
+
+ case TGSI_OPCODE_RCP:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+
+ i915_emit_arith(p,
+ A0_RCP,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ swizzle(src0, X, X, X, X), 0, 0);
+ break;
+
+ case TGSI_OPCODE_RSQ:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+
+ i915_emit_arith(p,
+ A0_RSQ,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ swizzle(src0, X, X, X, X), 0, 0);
+ break;
+
+ case TGSI_OPCODE_SCS:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ tmp = i915_get_utemp(p);
+
+ /*
+ * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1
+ * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x
+ * t1 = MUL t0.xyyw t0.yz11 ; x^7 x^5 x^3 x
+ * scs.x = DP4 t1, sin_constants
+ * t1 = MUL t0.xxz1 t0.z111 ; x^6 x^4 x^2 1
+ * scs.y = DP4 t1, cos_constants
+ */
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_XY, 0,
+ swizzle(src0, X, X, ONE, ONE),
+ swizzle(src0, X, ONE, ONE, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_ALL, 0,
+ swizzle(tmp, X, Y, X, Y),
+ swizzle(tmp, X, X, ONE, ONE), 0);
+
+ writemask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+
+ if (writemask & TGSI_WRITEMASK_Y) {
+ uint tmp1;
+
+ if (writemask & TGSI_WRITEMASK_X)
+ tmp1 = i915_get_utemp(p);
+ else
+ tmp1 = tmp;
+
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp1, A0_DEST_CHANNEL_ALL, 0,
+ swizzle(tmp, X, Y, Y, W),
+ swizzle(tmp, X, Z, ONE, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_DP4,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ A0_DEST_CHANNEL_Y, 0,
+ swizzle(tmp1, W, Z, Y, X),
+ i915_emit_const4fv(p, sin_constants), 0);
+ }
+
+ if (writemask & TGSI_WRITEMASK_X) {
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_XYZ, 0,
+ swizzle(tmp, X, X, Z, ONE),
+ swizzle(tmp, Z, ONE, ONE, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_DP4,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ A0_DEST_CHANNEL_X, 0,
+ swizzle(tmp, ONE, Z, Y, X),
+ i915_emit_const4fv(p, cos_constants), 0);
+ }
+ break;
+
+ case TGSI_OPCODE_SGE:
+ emit_simple_arith(p, inst, A0_SGE, 2);
+ break;
+
+ case TGSI_OPCODE_SLE:
+ /* like SGE, but swap reg0, reg1 */
+ emit_simple_arith_swap2(p, inst, A0_SGE, 2);
+ break;
+
+ case TGSI_OPCODE_SIN:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ tmp = i915_get_utemp(p);
+
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_X, 0,
+ src0, i915_emit_const1f(p, 1.0f / (float) (M_PI * 2.0)), 0);
+
+ i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0);
+
+ /* By choosing different taylor constants, could get rid of this mul:
+ */
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_X, 0,
+ tmp, i915_emit_const1f(p, (float) (M_PI * 2.0)), 0);
+
+ /*
+ * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1
+ * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x
+ * t1 = MUL t0.xyyw t0.yz11 ; x^7 x^5 x^3 x
+ * result = DP4 t1.wzyx, sin_constants
+ */
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_XY, 0,
+ swizzle(tmp, X, X, ONE, ONE),
+ swizzle(tmp, X, ONE, ONE, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_ALL, 0,
+ swizzle(tmp, X, Y, X, Y),
+ swizzle(tmp, X, X, ONE, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_ALL, 0,
+ swizzle(tmp, X, Y, Y, W),
+ swizzle(tmp, X, Z, ONE, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_DP4,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ swizzle(tmp, W, Z, Y, X),
+ i915_emit_const4fv(p, sin_constants), 0);
+ break;
+
+ case TGSI_OPCODE_SLT:
+ emit_simple_arith(p, inst, A0_SLT, 2);
+ break;
+
+ case TGSI_OPCODE_SGT:
+ /* like SLT, but swap reg0, reg1 */
+ emit_simple_arith_swap2(p, inst, A0_SLT, 2);
+ break;
+
+ case TGSI_OPCODE_SUB:
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ src1 = src_vector(p, &inst->FullSrcRegisters[1]);
+
+ i915_emit_arith(p,
+ A0_ADD,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ src0, negate(src1, 1, 1, 1, 1), 0);
+ break;
+
+ case TGSI_OPCODE_TEX:
+ emit_tex(p, inst, T0_TEXLD);
+ break;
+
+ case TGSI_OPCODE_TXB:
+ emit_tex(p, inst, T0_TEXLDB);
+ break;
+
+ case TGSI_OPCODE_TXP:
+ emit_tex(p, inst, T0_TEXLDP);
+ break;
+
+ case TGSI_OPCODE_XPD:
+ /* Cross product:
+ * result.x = src0.y * src1.z - src0.z * src1.y;
+ * result.y = src0.z * src1.x - src0.x * src1.z;
+ * result.z = src0.x * src1.y - src0.y * src1.x;
+ * result.w = undef;
+ */
+ src0 = src_vector(p, &inst->FullSrcRegisters[0]);
+ src1 = src_vector(p, &inst->FullSrcRegisters[1]);
+ tmp = i915_get_utemp(p);
+
+ i915_emit_arith(p,
+ A0_MUL,
+ tmp, A0_DEST_CHANNEL_ALL, 0,
+ swizzle(src0, Z, X, Y, ONE),
+ swizzle(src1, Y, Z, X, ONE), 0);
+
+ i915_emit_arith(p,
+ A0_MAD,
+ get_result_vector(p, &inst->FullDstRegisters[0]),
+ get_result_flags(inst), 0,
+ swizzle(src0, Y, Z, X, ONE),
+ swizzle(src1, Z, X, Y, ONE),
+ negate(tmp, 1, 1, 1, 0));
+ break;
+
+ default:
+ i915_program_error(p, "bad opcode %d", inst->Instruction.Opcode);
+ p->error = 1;
+ return;
+ }
+
+ i915_release_utemps(p);
+}
+
+
+/**
+ * Translate TGSI fragment shader into i915 hardware instructions.
+ * \param p the translation state
+ * \param tokens the TGSI token array
+ */
+static void
+i915_translate_instructions(struct i915_fp_compile *p,
+ const struct tgsi_token *tokens)
+{
+ struct i915_fragment_shader *ifs = p->shader;
+ struct tgsi_parse_context parse;
+
+ tgsi_parse_init( &parse, tokens );
+
+ while( !tgsi_parse_end_of_tokens( &parse ) ) {
+
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ if (parse.FullToken.FullDeclaration.Declaration.File
+ == TGSI_FILE_CONSTANT) {
+ uint i;
+ for (i = parse.FullToken.FullDeclaration.DeclarationRange.First;
+ i <= parse.FullToken.FullDeclaration.DeclarationRange.Last;
+ i++) {
+ assert(ifs->constant_flags[i] == 0x0);
+ ifs->constant_flags[i] = I915_CONSTFLAG_USER;
+ ifs->num_constants = MAX2(ifs->num_constants, i + 1);
+ }
+ }
+ else if (parse.FullToken.FullDeclaration.Declaration.File
+ == TGSI_FILE_TEMPORARY) {
+ uint i;
+ for (i = parse.FullToken.FullDeclaration.DeclarationRange.First;
+ i <= parse.FullToken.FullDeclaration.DeclarationRange.Last;
+ i++) {
+ assert(i < I915_MAX_TEMPORARY);
+ /* XXX just use shader->info->file_mask[TGSI_FILE_TEMPORARY] */
+ p->temp_flag |= (1 << i); /* mark temp as used */
+ }
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ const struct tgsi_full_immediate *imm
+ = &parse.FullToken.FullImmediate;
+ const uint pos = p->num_immediates++;
+ uint j;
+ assert( imm->Immediate.NrTokens <= 4 + 1 );
+ for (j = 0; j < imm->Immediate.NrTokens - 1; j++) {
+ p->immediates[pos][j] = imm->u[j].Float;
+ }
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (p->first_instruction) {
+ /* resolve location of immediates */
+ uint i, j;
+ for (i = 0; i < p->num_immediates; i++) {
+ /* find constant slot for this immediate */
+ for (j = 0; j < I915_MAX_CONSTANT; j++) {
+ if (ifs->constant_flags[j] == 0x0) {
+ memcpy(ifs->constants[j],
+ p->immediates[i],
+ 4 * sizeof(float));
+ /*printf("immediate %d maps to const %d\n", i, j);*/
+ ifs->constant_flags[j] = 0xf; /* all four comps used */
+ p->immediates_map[i] = j;
+ ifs->num_constants = MAX2(ifs->num_constants, j + 1);
+ break;
+ }
+ }
+ }
+
+ p->first_instruction = FALSE;
+ }
+
+ i915_translate_instruction(p, &parse.FullToken.FullInstruction);
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ } /* while */
+
+ tgsi_parse_free (&parse);
+}
+
+
+static struct i915_fp_compile *
+i915_init_compile(struct i915_context *i915,
+ struct i915_fragment_shader *ifs)
+{
+ struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile);
+
+ p->shader = ifs;
+
+ /* Put new constants at end of const buffer, growing downward.
+ * The problem is we don't know how many user-defined constants might
+ * be specified with pipe->set_constant_buffer().
+ * Should pre-scan the user's program to determine the highest-numbered
+ * constant referenced.
+ */
+ ifs->num_constants = 0;
+ memset(ifs->constant_flags, 0, sizeof(ifs->constant_flags));
+
+ p->first_instruction = TRUE;
+
+ p->nr_tex_indirect = 1; /* correct? */
+ p->nr_tex_insn = 0;
+ p->nr_alu_insn = 0;
+ p->nr_decl_insn = 0;
+
+ p->csr = p->program;
+ p->decl = p->declarations;
+ p->decl_s = 0;
+ p->decl_t = 0;
+ p->temp_flag = ~0x0 << I915_MAX_TEMPORARY;
+ p->utemp_flag = ~0x7;
+
+ p->wpos_tex = -1;
+
+ /* initialize the first program word */
+ *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM;
+
+ return p;
+}
+
+
+/* Copy compile results to the fragment program struct and destroy the
+ * compilation context.
+ */
+static void
+i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
+{
+ struct i915_fragment_shader *ifs = p->shader;
+ unsigned long program_size = (unsigned long) (p->csr - p->program);
+ unsigned long decl_size = (unsigned long) (p->decl - p->declarations);
+
+ if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT)
+ i915_program_error(p, "Exceeded max nr indirect texture lookups");
+
+ if (p->nr_tex_insn > I915_MAX_TEX_INSN)
+ i915_program_error(p, "Exceeded max TEX instructions");
+
+ if (p->nr_alu_insn > I915_MAX_ALU_INSN)
+ i915_program_error(p, "Exceeded max ALU instructions");
+
+ if (p->nr_decl_insn > I915_MAX_DECL_INSN)
+ i915_program_error(p, "Exceeded max DECL instructions");
+
+ if (p->error) {
+ p->NumNativeInstructions = 0;
+ p->NumNativeAluInstructions = 0;
+ p->NumNativeTexInstructions = 0;
+ p->NumNativeTexIndirections = 0;
+
+ i915_use_passthrough_shader(ifs);
+ }
+ else {
+ p->NumNativeInstructions
+ = p->nr_alu_insn + p->nr_tex_insn + p->nr_decl_insn;
+ p->NumNativeAluInstructions = p->nr_alu_insn;
+ p->NumNativeTexInstructions = p->nr_tex_insn;
+ p->NumNativeTexIndirections = p->nr_tex_indirect;
+
+ /* patch in the program length */
+ p->declarations[0] |= program_size + decl_size - 2;
+
+ /* Copy compilation results to fragment program struct:
+ */
+ assert(!ifs->program);
+ ifs->program
+ = (uint *) MALLOC((program_size + decl_size) * sizeof(uint));
+ if (ifs->program) {
+ ifs->program_len = program_size + decl_size;
+
+ memcpy(ifs->program,
+ p->declarations,
+ decl_size * sizeof(uint));
+
+ memcpy(ifs->program + decl_size,
+ p->program,
+ program_size * sizeof(uint));
+ }
+ }
+
+ /* Release the compilation struct:
+ */
+ FREE(p);
+}
+
+
+/**
+ * Find an unused texture coordinate slot to use for fragment WPOS.
+ * Update p->fp->wpos_tex with the result (-1 if no used texcoord slot is found).
+ */
+static void
+i915_find_wpos_space(struct i915_fp_compile *p)
+{
+#if 0
+ const uint inputs
+ = p->shader->inputs_read | (1 << TGSI_ATTRIB_POS); /*XXX hack*/
+ uint i;
+
+ p->wpos_tex = -1;
+
+ if (inputs & (1 << TGSI_ATTRIB_POS)) {
+ for (i = 0; i < I915_TEX_UNITS; i++) {
+ if ((inputs & (1 << (TGSI_ATTRIB_TEX0 + i))) == 0) {
+ p->wpos_tex = i;
+ return;
+ }
+ }
+
+ i915_program_error(p, "No free texcoord for wpos value");
+ }
+#else
+ if (p->shader->info.input_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
+ /* frag shader using the fragment position input */
+#if 0
+ assert(0);
+#endif
+ }
+#endif
+}
+
+
+
+
+/**
+ * Rather than trying to intercept and jiggle depth writes during
+ * emit, just move the value into its correct position at the end of
+ * the program:
+ */
+static void
+i915_fixup_depth_write(struct i915_fp_compile *p)
+{
+ /* XXX assuming pos/depth is always in output[0] */
+ if (p->shader->info.output_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
+ const uint depth = UREG(REG_TYPE_OD, 0);
+
+ i915_emit_arith(p,
+ A0_MOV, /* opcode */
+ depth, /* dest reg */
+ A0_DEST_CHANNEL_W, /* write mask */
+ 0, /* saturate? */
+ swizzle(depth, X, Y, Z, Z), /* src0 */
+ 0, 0 /* src1, src2 */);
+ }
+}
+
+
+void
+i915_translate_fragment_program( struct i915_context *i915,
+ struct i915_fragment_shader *fs)
+{
+ struct i915_fp_compile *p = i915_init_compile(i915, fs);
+ const struct tgsi_token *tokens = fs->state.tokens;
+
+ i915_find_wpos_space(p);
+
+#if 0
+ tgsi_dump(tokens, 0);
+#endif
+
+ i915_translate_instructions(p, tokens);
+ i915_fixup_depth_write(p);
+
+ i915_fini_compile(i915, p);
+}
diff --git a/src/gallium/drivers/i915simple/i915_prim_emit.c b/src/gallium/drivers/i915simple/i915_prim_emit.c
new file mode 100644
index 0000000000..d9a5c40ab9
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_prim_emit.c
@@ -0,0 +1,219 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "draw/draw_pipe.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_pack_color.h"
+
+#include "i915_context.h"
+#include "i915_reg.h"
+#include "i915_state.h"
+#include "i915_batch.h"
+
+
+
+/**
+ * Primitive emit to hardware. No support for vertex buffers or any
+ * nice fast paths.
+ */
+struct setup_stage {
+ struct draw_stage stage; /**< This must be first (base class) */
+
+ struct i915_context *i915;
+};
+
+
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct setup_stage *setup_stage( struct draw_stage *stage )
+{
+ return (struct setup_stage *)stage;
+}
+
+
+/**
+ * Extract the needed fields from vertex_header and emit i915 dwords.
+ * Recall that the vertices are constructed by the 'draw' module and
+ * have a couple of slots at the beginning (1-dword header, 4-dword
+ * clip pos) that we ignore here.
+ */
+static INLINE void
+emit_hw_vertex( struct i915_context *i915,
+ const struct vertex_header *vertex)
+{
+ const struct vertex_info *vinfo = &i915->current.vertex_info;
+ uint i;
+ uint count = 0; /* for debug/sanity */
+
+ assert(!i915->dirty);
+
+ for (i = 0; i < vinfo->num_attribs; i++) {
+ const uint j = vinfo->attrib[i].src_index;
+ const float *attrib = vertex->data[j];
+ switch (vinfo->attrib[i].emit) {
+ case EMIT_1F:
+ OUT_BATCH( fui(attrib[0]) );
+ count++;
+ break;
+ case EMIT_2F:
+ OUT_BATCH( fui(attrib[0]) );
+ OUT_BATCH( fui(attrib[1]) );
+ count += 2;
+ break;
+ case EMIT_3F:
+ OUT_BATCH( fui(attrib[0]) );
+ OUT_BATCH( fui(attrib[1]) );
+ OUT_BATCH( fui(attrib[2]) );
+ count += 3;
+ break;
+ case EMIT_4F:
+ OUT_BATCH( fui(attrib[0]) );
+ OUT_BATCH( fui(attrib[1]) );
+ OUT_BATCH( fui(attrib[2]) );
+ OUT_BATCH( fui(attrib[3]) );
+ count += 4;
+ break;
+ case EMIT_4UB:
+ OUT_BATCH( pack_ub4(float_to_ubyte( attrib[2] ),
+ float_to_ubyte( attrib[1] ),
+ float_to_ubyte( attrib[0] ),
+ float_to_ubyte( attrib[3] )) );
+ count += 1;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ assert(count == vinfo->size);
+}
+
+
+
+static INLINE void
+emit_prim( struct draw_stage *stage,
+ struct prim_header *prim,
+ unsigned hwprim,
+ unsigned nr )
+{
+ struct i915_context *i915 = setup_stage(stage)->i915;
+ unsigned vertex_size;
+ unsigned i;
+
+ if (i915->dirty)
+ i915_update_derived( i915 );
+
+ if (i915->hardware_dirty)
+ i915_emit_hardware_state( i915 );
+
+ /* need to do this after validation! */
+ vertex_size = i915->current.vertex_info.size * 4; /* in bytes */
+ assert(vertex_size >= 12); /* never smaller than 12 bytes */
+
+ if (!BEGIN_BATCH( 1 + nr * vertex_size / 4, 0 )) {
+ FLUSH_BATCH(NULL);
+
+ /* Make sure state is re-emitted after a flush:
+ */
+ i915_update_derived( i915 );
+ i915_emit_hardware_state( i915 );
+
+ if (!BEGIN_BATCH( 1 + nr * vertex_size / 4, 0 )) {
+ assert(0);
+ return;
+ }
+ }
+
+ /* Emit each triangle as a single primitive. I told you this was
+ * simple.
+ */
+ OUT_BATCH(_3DPRIMITIVE |
+ hwprim |
+ ((4 + vertex_size * nr)/4 - 2));
+
+ for (i = 0; i < nr; i++)
+ emit_hw_vertex(i915, prim->v[i]);
+}
+
+
+static void
+setup_tri( struct draw_stage *stage, struct prim_header *prim )
+{
+ emit_prim( stage, prim, PRIM3D_TRILIST, 3 );
+}
+
+
+static void
+setup_line(struct draw_stage *stage, struct prim_header *prim)
+{
+ emit_prim( stage, prim, PRIM3D_LINELIST, 2 );
+}
+
+
+static void
+setup_point(struct draw_stage *stage, struct prim_header *prim)
+{
+ emit_prim( stage, prim, PRIM3D_POINTLIST, 1 );
+}
+
+
+static void setup_flush( struct draw_stage *stage, unsigned flags )
+{
+}
+
+static void reset_stipple_counter( struct draw_stage *stage )
+{
+}
+
+static void render_destroy( struct draw_stage *stage )
+{
+ FREE( stage );
+}
+
+
+/**
+ * Create a new primitive setup/render stage. This gets plugged into
+ * the 'draw' module's pipeline.
+ */
+struct draw_stage *i915_draw_render_stage( struct i915_context *i915 )
+{
+ struct setup_stage *setup = CALLOC_STRUCT(setup_stage);
+
+ setup->i915 = i915;
+ setup->stage.draw = i915->draw;
+ setup->stage.point = setup_point;
+ setup->stage.line = setup_line;
+ setup->stage.tri = setup_tri;
+ setup->stage.flush = setup_flush;
+ setup->stage.reset_stipple_counter = reset_stipple_counter;
+ setup->stage.destroy = render_destroy;
+
+ return &setup->stage;
+}
diff --git a/src/gallium/drivers/i915simple/i915_prim_vbuf.c b/src/gallium/drivers/i915simple/i915_prim_vbuf.c
new file mode 100644
index 0000000000..b3a7774fd6
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_prim_vbuf.c
@@ -0,0 +1,616 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Build post-transformation, post-clipping vertex buffers and element
+ * lists by hooking into the end of the primitive pipeline and
+ * manipulating the vertex_id field in the vertex headers.
+ *
+ * XXX: work in progress
+ *
+ * \author José Fonseca <jrfonseca@tungstengraphics.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "draw/draw_context.h"
+#include "draw/draw_vbuf.h"
+#include "util/u_debug.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_fifo.h"
+
+#include "i915_context.h"
+#include "i915_reg.h"
+#include "i915_batch.h"
+#include "i915_state.h"
+
+
+/**
+ * Primitive renderer for i915.
+ */
+struct i915_vbuf_render {
+ struct vbuf_render base;
+
+ struct i915_context *i915;
+
+ /** Vertex size in bytes */
+ size_t vertex_size;
+
+ /** Software primitive */
+ unsigned prim;
+
+ /** Hardware primitive */
+ unsigned hwprim;
+
+ /** Genereate a vertex list */
+ unsigned fallback;
+
+ /* Stuff for the vbo */
+ struct intel_buffer *vbo;
+ size_t vbo_size;
+ size_t vbo_offset;
+ void *vbo_ptr;
+ size_t vbo_max_used;
+
+ /* stuff for the pool */
+ struct util_fifo *pool_fifo;
+ unsigned pool_used;
+ unsigned pool_buffer_size;
+ boolean pool_not_used;
+};
+
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct i915_vbuf_render *
+i915_vbuf_render(struct vbuf_render *render)
+{
+ assert(render);
+ return (struct i915_vbuf_render *)render;
+}
+
+static const struct vertex_info *
+i915_vbuf_render_get_vertex_info(struct vbuf_render *render)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+
+ if (i915->dirty) {
+ /* make sure we have up to date vertex layout */
+ i915_update_derived(i915);
+ }
+
+ return &i915->current.vertex_info;
+}
+
+static boolean
+i915_vbuf_render_reserve(struct i915_vbuf_render *i915_render, size_t size)
+{
+ struct i915_context *i915 = i915_render->i915;
+
+ if (i915_render->vbo_size < size + i915_render->vbo_offset)
+ return FALSE;
+
+ if (i915->vbo_flushed)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size)
+{
+ struct i915_context *i915 = i915_render->i915;
+ struct intel_winsys *iws = i915->iws;
+
+ if (i915_render->vbo) {
+ if (i915_render->pool_not_used)
+ iws->buffer_destroy(iws, i915_render->vbo);
+ else
+ u_fifo_add(i915_render->pool_fifo, i915_render->vbo);
+ i915_render->vbo = NULL;
+ }
+
+ i915->vbo_flushed = 0;
+
+ i915_render->vbo_size = MAX2(size, i915_render->pool_buffer_size);
+ i915_render->vbo_offset = 0;
+
+ if (i915_render->vbo_size != i915_render->pool_buffer_size) {
+ i915_render->pool_not_used = TRUE;
+ i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size, 64,
+ INTEL_NEW_VERTEX);
+ } else {
+ i915_render->pool_not_used = FALSE;
+
+ if (i915_render->pool_used >= 2) {
+ FLUSH_BATCH(NULL);
+ i915->vbo_flushed = 0;
+ i915_render->pool_used = 0;
+ }
+ u_fifo_pop(i915_render->pool_fifo, (void**)&i915_render->vbo);
+ }
+}
+
+static boolean
+i915_vbuf_render_allocate_vertices(struct vbuf_render *render,
+ ushort vertex_size,
+ ushort nr_vertices)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ size_t size = (size_t)vertex_size * (size_t)nr_vertices;
+
+ /* FIXME: handle failure */
+ assert(!i915->vbo);
+
+ if (!i915_vbuf_render_reserve(i915_render, size)) {
+
+ if (i915->vbo_flushed)
+ i915_render->pool_used = 0;
+
+ i915_vbuf_render_new_buf(i915_render, size);
+ }
+
+ i915_render->vertex_size = vertex_size;
+ i915->vbo = i915_render->vbo;
+ i915->vbo_offset = i915_render->vbo_offset;
+ i915->dirty |= I915_NEW_VBO;
+
+ if (!i915_render->vbo)
+ return FALSE;
+ return TRUE;
+}
+
+static void *
+i915_vbuf_render_map_vertices(struct vbuf_render *render)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ struct intel_winsys *iws = i915->iws;
+
+ if (i915->vbo_flushed)
+ debug_printf("%s bad vbo flush occured stalling on hw\n");
+
+ i915_render->vbo_ptr = iws->buffer_map(iws, i915_render->vbo, TRUE);
+
+ return (unsigned char *)i915_render->vbo_ptr + i915->vbo_offset;
+}
+
+static void
+i915_vbuf_render_unmap_vertices(struct vbuf_render *render,
+ ushort min_index,
+ ushort max_index)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ struct intel_winsys *iws = i915->iws;
+
+ i915_render->vbo_max_used = MAX2(i915_render->vbo_max_used, i915_render->vertex_size * (max_index + 1));
+ iws->buffer_unmap(iws, i915_render->vbo);
+}
+
+static boolean
+i915_vbuf_render_set_primitive(struct vbuf_render *render,
+ unsigned prim)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ i915_render->prim = prim;
+
+ switch(prim) {
+ case PIPE_PRIM_POINTS:
+ i915_render->hwprim = PRIM3D_POINTLIST;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_LINES:
+ i915_render->hwprim = PRIM3D_LINELIST;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_LINE_LOOP:
+ i915_render->hwprim = PRIM3D_LINELIST;
+ i915_render->fallback = PIPE_PRIM_LINE_LOOP;
+ return TRUE;
+ case PIPE_PRIM_LINE_STRIP:
+ i915_render->hwprim = PRIM3D_LINESTRIP;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_TRIANGLES:
+ i915_render->hwprim = PRIM3D_TRILIST;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ i915_render->hwprim = PRIM3D_TRISTRIP;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ i915_render->hwprim = PRIM3D_TRIFAN;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_QUADS:
+ i915_render->hwprim = PRIM3D_TRILIST;
+ i915_render->fallback = PIPE_PRIM_QUADS;
+ return TRUE;
+ case PIPE_PRIM_QUAD_STRIP:
+ i915_render->hwprim = PRIM3D_TRILIST;
+ i915_render->fallback = PIPE_PRIM_QUAD_STRIP;
+ return TRUE;
+ case PIPE_PRIM_POLYGON:
+ i915_render->hwprim = PRIM3D_POLY;
+ i915_render->fallback = 0;
+ return TRUE;
+ default:
+ /* FIXME: Actually, can handle a lot more just fine... */
+ return FALSE;
+ }
+}
+
+/**
+ * Used for fallbacks in draw_arrays
+ */
+static void
+draw_arrays_generate_indices(struct vbuf_render *render,
+ unsigned start, uint nr,
+ unsigned type)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ unsigned i;
+ unsigned end = start + nr;
+ switch(type) {
+ case 0:
+ for (i = start; i+1 < end; i += 2)
+ OUT_BATCH((i+0) | (i+1) << 16);
+ if (i < end)
+ OUT_BATCH(i);
+ break;
+ case PIPE_PRIM_LINE_LOOP:
+ if (nr >= 2) {
+ for (i = start + 1; i < end; i++)
+ OUT_BATCH((i-0) | (i+0) << 16);
+ OUT_BATCH((i-0) | ( start) << 16);
+ }
+ break;
+ case PIPE_PRIM_QUADS:
+ for (i = start; i + 3 < end; i += 4) {
+ OUT_BATCH((i+0) | (i+1) << 16);
+ OUT_BATCH((i+3) | (i+1) << 16);
+ OUT_BATCH((i+2) | (i+3) << 16);
+ }
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = start; i + 3 < end; i += 2) {
+ OUT_BATCH((i+0) | (i+1) << 16);
+ OUT_BATCH((i+3) | (i+2) << 16);
+ OUT_BATCH((i+0) | (i+3) << 16);
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static unsigned
+draw_arrays_calc_nr_indices(uint nr, unsigned type)
+{
+ switch (type) {
+ case 0:
+ return nr;
+ case PIPE_PRIM_LINE_LOOP:
+ if (nr >= 2)
+ return nr * 2;
+ else
+ return 0;
+ case PIPE_PRIM_QUADS:
+ return (nr / 4) * 6;
+ case PIPE_PRIM_QUAD_STRIP:
+ return ((nr - 2) / 2) * 6;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static void
+draw_arrays_fallback(struct vbuf_render *render,
+ unsigned start,
+ uint nr)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ unsigned nr_indices;
+
+ if (i915->dirty)
+ i915_update_derived(i915);
+
+ if (i915->hardware_dirty)
+ i915_emit_hardware_state(i915);
+
+ nr_indices = draw_arrays_calc_nr_indices(nr, i915_render->fallback);
+ if (!nr_indices)
+ return;
+
+ if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) {
+ FLUSH_BATCH(NULL);
+
+ /* Make sure state is re-emitted after a flush:
+ */
+ i915_update_derived(i915);
+ i915_emit_hardware_state(i915);
+ i915->vbo_flushed = 1;
+
+ if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) {
+ assert(0);
+ goto out;
+ }
+ }
+ OUT_BATCH(_3DPRIMITIVE |
+ PRIM_INDIRECT |
+ i915_render->hwprim |
+ PRIM_INDIRECT_ELTS |
+ nr_indices);
+
+ draw_arrays_generate_indices(render, start, nr, i915_render->fallback);
+
+out:
+ return;
+}
+
+static void
+i915_vbuf_render_draw_arrays(struct vbuf_render *render,
+ unsigned start,
+ uint nr)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+
+ if (i915_render->fallback) {
+ draw_arrays_fallback(render, start, nr);
+ return;
+ }
+
+ /* JB: TODO submit direct cmds */
+ draw_arrays_fallback(render, start, nr);
+}
+
+/**
+ * Used for normal and fallback emitting of indices
+ * If type is zero normal operation assumed.
+ */
+static void
+draw_generate_indices(struct vbuf_render *render,
+ const ushort *indices,
+ uint nr_indices,
+ unsigned type)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ unsigned i;
+
+ switch(type) {
+ case 0:
+ for (i = 0; i + 1 < nr_indices; i += 2) {
+ OUT_BATCH(indices[i] | indices[i+1] << 16);
+ }
+ if (i < nr_indices) {
+ OUT_BATCH(indices[i]);
+ }
+ break;
+ case PIPE_PRIM_LINE_LOOP:
+ if (nr_indices >= 2) {
+ for (i = 1; i < nr_indices; i++)
+ OUT_BATCH(indices[i-1] | indices[i] << 16);
+ OUT_BATCH(indices[i-1] | indices[0] << 16);
+ }
+ break;
+ case PIPE_PRIM_QUADS:
+ for (i = 0; i + 3 < nr_indices; i += 4) {
+ OUT_BATCH(indices[i+0] | indices[i+1] << 16);
+ OUT_BATCH(indices[i+3] | indices[i+1] << 16);
+ OUT_BATCH(indices[i+2] | indices[i+3] << 16);
+ }
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = 0; i + 3 < nr_indices; i += 2) {
+ OUT_BATCH(indices[i+0] | indices[i+1] << 16);
+ OUT_BATCH(indices[i+3] | indices[i+2] << 16);
+ OUT_BATCH(indices[i+0] | indices[i+3] << 16);
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static unsigned
+draw_calc_nr_indices(uint nr_indices, unsigned type)
+{
+ switch (type) {
+ case 0:
+ return nr_indices;
+ case PIPE_PRIM_LINE_LOOP:
+ if (nr_indices >= 2)
+ return nr_indices * 2;
+ else
+ return 0;
+ case PIPE_PRIM_QUADS:
+ return (nr_indices / 4) * 6;
+ case PIPE_PRIM_QUAD_STRIP:
+ return ((nr_indices - 2) / 2) * 6;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static void
+i915_vbuf_render_draw(struct vbuf_render *render,
+ const ushort *indices,
+ uint nr_indices)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ unsigned save_nr_indices;
+
+ save_nr_indices = nr_indices;
+
+ nr_indices = draw_calc_nr_indices(nr_indices, i915_render->fallback);
+ if (!nr_indices)
+ return;
+
+ if (i915->dirty)
+ i915_update_derived(i915);
+
+ if (i915->hardware_dirty)
+ i915_emit_hardware_state(i915);
+
+ if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) {
+ FLUSH_BATCH(NULL);
+
+ /* Make sure state is re-emitted after a flush:
+ */
+ i915_update_derived(i915);
+ i915_emit_hardware_state(i915);
+ i915->vbo_flushed = 1;
+
+ if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) {
+ assert(0);
+ goto out;
+ }
+ }
+
+ OUT_BATCH(_3DPRIMITIVE |
+ PRIM_INDIRECT |
+ i915_render->hwprim |
+ PRIM_INDIRECT_ELTS |
+ nr_indices);
+ draw_generate_indices(render,
+ indices,
+ save_nr_indices,
+ i915_render->fallback);
+
+out:
+ return;
+}
+
+static void
+i915_vbuf_render_release_vertices(struct vbuf_render *render)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+
+ assert(i915->vbo);
+
+ i915_render->vbo_offset += i915_render->vbo_max_used;
+ i915_render->vbo_max_used = 0;
+ i915->vbo = NULL;
+ i915->dirty |= I915_NEW_VBO;
+}
+
+static void
+i915_vbuf_render_destroy(struct vbuf_render *render)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ FREE(i915_render);
+}
+
+/**
+ * Create a new primitive render.
+ */
+static struct vbuf_render *
+i915_vbuf_render_create(struct i915_context *i915)
+{
+ struct i915_vbuf_render *i915_render = CALLOC_STRUCT(i915_vbuf_render);
+ struct intel_winsys *iws = i915->iws;
+ int i;
+
+ i915_render->i915 = i915;
+
+ i915_render->base.max_vertex_buffer_bytes = 128*1024;
+
+ /* NOTE: it must be such that state and vertices indices fit in a single
+ * batch buffer.
+ */
+ i915_render->base.max_indices = 16*1024;
+
+ i915_render->base.get_vertex_info = i915_vbuf_render_get_vertex_info;
+ i915_render->base.allocate_vertices = i915_vbuf_render_allocate_vertices;
+ i915_render->base.map_vertices = i915_vbuf_render_map_vertices;
+ i915_render->base.unmap_vertices = i915_vbuf_render_unmap_vertices;
+ i915_render->base.set_primitive = i915_vbuf_render_set_primitive;
+ i915_render->base.draw = i915_vbuf_render_draw;
+ i915_render->base.draw_arrays = i915_vbuf_render_draw_arrays;
+ i915_render->base.release_vertices = i915_vbuf_render_release_vertices;
+ i915_render->base.destroy = i915_vbuf_render_destroy;
+
+
+ i915_render->vbo = NULL;
+ i915_render->vbo_size = 0;
+ i915_render->vbo_offset = 0;
+
+ i915_render->pool_used = FALSE;
+ i915_render->pool_buffer_size = 128 * 4096;
+ i915_render->pool_fifo = u_fifo_create(6);
+ for (i = 0; i < 6; i++)
+ u_fifo_add(i915_render->pool_fifo,
+ iws->buffer_create(iws, i915_render->pool_buffer_size, 64,
+ INTEL_NEW_VERTEX));
+
+#if 0
+ /* TODO JB: is this realy needed? */
+ i915_render->vbo_ptr = iws->buffer_map(iws, i915_render->vbo, TRUE);
+ iws->buffer_unmap(iws, i915_render->vbo);
+#endif
+
+ return &i915_render->base;
+}
+
+/**
+ * Create a new primitive vbuf/render stage.
+ */
+struct draw_stage *i915_draw_vbuf_stage(struct i915_context *i915)
+{
+ struct vbuf_render *render;
+ struct draw_stage *stage;
+
+ render = i915_vbuf_render_create(i915);
+ if(!render)
+ return NULL;
+
+ stage = draw_vbuf_stage(i915->draw, render);
+ if(!stage) {
+ render->destroy(render);
+ return NULL;
+ }
+ /** TODO JB: this shouldn't be here */
+ draw_set_render(i915->draw, render);
+
+ return stage;
+}
diff --git a/src/gallium/drivers/i915simple/i915_reg.h b/src/gallium/drivers/i915simple/i915_reg.h
new file mode 100644
index 0000000000..04620fec68
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_reg.h
@@ -0,0 +1,978 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef I915_REG_H
+#define I915_REG_H
+
+
+#define I915_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
+
+#define CMD_3D (0x3<<29)
+
+#define PRIM3D_INLINE (CMD_3D | (0x1f<<24))
+#define PRIM3D_TRILIST (0x0<<18)
+#define PRIM3D_TRISTRIP (0x1<<18)
+#define PRIM3D_TRISTRIP_RVRSE (0x2<<18)
+#define PRIM3D_TRIFAN (0x3<<18)
+#define PRIM3D_POLY (0x4<<18)
+#define PRIM3D_LINELIST (0x5<<18)
+#define PRIM3D_LINESTRIP (0x6<<18)
+#define PRIM3D_RECTLIST (0x7<<18)
+#define PRIM3D_POINTLIST (0x8<<18)
+#define PRIM3D_DIB (0x9<<18)
+#define PRIM3D_CLEAR_RECT (0xa<<18)
+#define PRIM3D_ZONE_INIT (0xd<<18)
+#define PRIM3D_MASK (0x1f<<18)
+
+/* p137 */
+#define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24))
+#define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16)
+#define AA_LINE_ECAAR_WIDTH_0_5 0
+#define AA_LINE_ECAAR_WIDTH_1_0 (1<<14)
+#define AA_LINE_ECAAR_WIDTH_2_0 (2<<14)
+#define AA_LINE_ECAAR_WIDTH_4_0 (3<<14)
+#define AA_LINE_REGION_WIDTH_ENABLE (1<<8)
+#define AA_LINE_REGION_WIDTH_0_5 0
+#define AA_LINE_REGION_WIDTH_1_0 (1<<6)
+#define AA_LINE_REGION_WIDTH_2_0 (2<<6)
+#define AA_LINE_REGION_WIDTH_4_0 (3<<6)
+
+/* 3DSTATE_BACKFACE_STENCIL_OPS, p138*/
+#define _3DSTATE_BACKFACE_STENCIL_OPS (CMD_3D | (0x8<<24))
+#define BFO_ENABLE_STENCIL_REF (1<<23)
+#define BFO_STENCIL_REF_SHIFT 15
+#define BFO_STENCIL_REF_MASK (0xff<<15)
+#define BFO_ENABLE_STENCIL_FUNCS (1<<14)
+#define BFO_STENCIL_TEST_SHIFT 11
+#define BFO_STENCIL_TEST_MASK (0x7<<11)
+#define BFO_STENCIL_FAIL_SHIFT 8
+#define BFO_STENCIL_FAIL_MASK (0x7<<8)
+#define BFO_STENCIL_PASS_Z_FAIL_SHIFT 5
+#define BFO_STENCIL_PASS_Z_FAIL_MASK (0x7<<5)
+#define BFO_STENCIL_PASS_Z_PASS_SHIFT 2
+#define BFO_STENCIL_PASS_Z_PASS_MASK (0x7<<2)
+#define BFO_ENABLE_STENCIL_TWO_SIDE (1<<1)
+#define BFO_STENCIL_TWO_SIDE (1<<0)
+
+
+/* 3DSTATE_BACKFACE_STENCIL_MASKS, p140 */
+#define _3DSTATE_BACKFACE_STENCIL_MASKS (CMD_3D | (0x9<<24))
+#define BFM_ENABLE_STENCIL_TEST_MASK (1<<17)
+#define BFM_ENABLE_STENCIL_WRITE_MASK (1<<16)
+#define BFM_STENCIL_TEST_MASK_SHIFT 8
+#define BFM_STENCIL_TEST_MASK_MASK (0xff<<8)
+#define BFM_STENCIL_WRITE_MASK_SHIFT 0
+#define BFM_STENCIL_WRITE_MASK_MASK (0xff<<0)
+
+
+
+/* 3DSTATE_BIN_CONTROL p141 */
+
+/* p143 */
+#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
+/* Dword 1 */
+#define BUF_3D_ID_COLOR_BACK (0x3<<24)
+#define BUF_3D_ID_DEPTH (0x7<<24)
+#define BUF_3D_USE_FENCE (1<<23)
+#define BUF_3D_TILED_SURFACE (1<<22)
+#define BUF_3D_TILE_WALK_X 0
+#define BUF_3D_TILE_WALK_Y (1<<21)
+#define BUF_3D_PITCH(x) (((x)/4)<<2)
+/* Dword 2 */
+#define BUF_3D_ADDR(x) ((x) & ~0x3)
+
+
+/* 3DSTATE_CHROMA_KEY */
+
+/* 3DSTATE_CLEAR_PARAMETERS, p150 */
+#define _3DSTATE_CLEAR_PARAMETERS (CMD_3D | (0x1d<<24) | (0x9c<<16) | 5)
+/* Dword 1 */
+#define CLEARPARAM_CLEAR_RECT (1 << 16)
+#define CLEARPARAM_ZONE_INIT (0 << 16)
+#define CLEARPARAM_WRITE_COLOR (1 << 2)
+#define CLEARPARAM_WRITE_DEPTH (1 << 1)
+#define CLEARPARAM_WRITE_STENCIL (1 << 0)
+
+/* 3DSTATE_CONSTANT_BLEND_COLOR, p153 */
+#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16))
+
+
+
+/* 3DSTATE_COORD_SET_BINDINGS, p154 */
+#define _3DSTATE_COORD_SET_BINDINGS (CMD_3D | (0x16<<24))
+#define CSB_TCB(iunit, eunit) ((eunit)<<(iunit*3))
+
+/* p156 */
+#define _3DSTATE_DFLT_DIFFUSE_CMD (CMD_3D | (0x1d<<24) | (0x99<<16))
+
+/* p157 */
+#define _3DSTATE_DFLT_SPEC_CMD (CMD_3D | (0x1d<<24) | (0x9a<<16))
+
+/* p158 */
+#define _3DSTATE_DFLT_Z_CMD (CMD_3D | (0x1d<<24) | (0x98<<16))
+
+
+/* 3DSTATE_DEPTH_OFFSET_SCALE, p159 */
+#define _3DSTATE_DEPTH_OFFSET_SCALE (CMD_3D | (0x1d<<24) | (0x97<<16))
+/* scale in dword 1 */
+
+
+/* 3DSTATE_DEPTH_SUBRECT_DISABLE, p160 */
+#define _3DSTATE_DEPTH_SUBRECT_DISABLE (CMD_3D | (0x1c<<24) | (0x11<<19) | 0x2)
+
+/* p161 */
+#define _3DSTATE_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16))
+/* Dword 1 */
+#define TEX_DEFAULT_COLOR_OGL (0<<30)
+#define TEX_DEFAULT_COLOR_D3D (1<<30)
+#define ZR_EARLY_DEPTH (1<<29)
+#define LOD_PRECLAMP_OGL (1<<28)
+#define LOD_PRECLAMP_D3D (0<<28)
+#define DITHER_FULL_ALWAYS (0<<26)
+#define DITHER_FULL_ON_FB_BLEND (1<<26)
+#define DITHER_CLAMPED_ALWAYS (2<<26)
+#define LINEAR_GAMMA_BLEND_32BPP (1<<25)
+#define DEBUG_DISABLE_ENH_DITHER (1<<24)
+#define DSTORG_HORT_BIAS(x) ((x)<<20)
+#define DSTORG_VERT_BIAS(x) ((x)<<16)
+#define COLOR_4_2_2_CHNL_WRT_ALL 0
+#define COLOR_4_2_2_CHNL_WRT_Y (1<<12)
+#define COLOR_4_2_2_CHNL_WRT_CR (2<<12)
+#define COLOR_4_2_2_CHNL_WRT_CB (3<<12)
+#define COLOR_4_2_2_CHNL_WRT_CRCB (4<<12)
+#define COLOR_BUF_8BIT 0
+#define COLOR_BUF_RGB555 (1<<8)
+#define COLOR_BUF_RGB565 (2<<8)
+#define COLOR_BUF_ARGB8888 (3<<8)
+#define DEPTH_FRMT_16_FIXED 0
+#define DEPTH_FRMT_16_FLOAT (1<<2)
+#define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2)
+#define VERT_LINE_STRIDE_1 (1<<1)
+#define VERT_LINE_STRIDE_0 (0<<1)
+#define VERT_LINE_STRIDE_OFS_1 1
+#define VERT_LINE_STRIDE_OFS_0 0
+
+/* p166 */
+#define _3DSTATE_DRAW_RECT_CMD (CMD_3D|(0x1d<<24)|(0x80<<16)|3)
+/* Dword 1 */
+#define DRAW_RECT_DIS_DEPTH_OFS (1<<30)
+#define DRAW_DITHER_OFS_X(x) ((x)<<26)
+#define DRAW_DITHER_OFS_Y(x) ((x)<<24)
+/* Dword 2 */
+#define DRAW_YMIN(x) ((x)<<16)
+#define DRAW_XMIN(x) (x)
+/* Dword 3 */
+#define DRAW_YMAX(x) ((x)<<16)
+#define DRAW_XMAX(x) (x)
+/* Dword 4 */
+#define DRAW_YORG(x) ((x)<<16)
+#define DRAW_XORG(x) (x)
+
+
+/* 3DSTATE_FILTER_COEFFICIENTS_4X4, p170 */
+
+/* 3DSTATE_FILTER_COEFFICIENTS_6X5, p172 */
+
+
+/* _3DSTATE_FOG_COLOR, p173 */
+#define _3DSTATE_FOG_COLOR_CMD (CMD_3D|(0x15<<24))
+#define FOG_COLOR_RED(x) ((x)<<16)
+#define FOG_COLOR_GREEN(x) ((x)<<8)
+#define FOG_COLOR_BLUE(x) (x)
+
+/* _3DSTATE_FOG_MODE, p174 */
+#define _3DSTATE_FOG_MODE_CMD (CMD_3D|(0x1d<<24)|(0x89<<16)|2)
+/* Dword 1 */
+#define FMC1_FOGFUNC_MODIFY_ENABLE (1<<31)
+#define FMC1_FOGFUNC_VERTEX (0<<28)
+#define FMC1_FOGFUNC_PIXEL_EXP (1<<28)
+#define FMC1_FOGFUNC_PIXEL_EXP2 (2<<28)
+#define FMC1_FOGFUNC_PIXEL_LINEAR (3<<28)
+#define FMC1_FOGFUNC_MASK (3<<28)
+#define FMC1_FOGINDEX_MODIFY_ENABLE (1<<27)
+#define FMC1_FOGINDEX_Z (0<<25)
+#define FMC1_FOGINDEX_W (1<<25)
+#define FMC1_C1_C2_MODIFY_ENABLE (1<<24)
+#define FMC1_DENSITY_MODIFY_ENABLE (1<<23)
+#define FMC1_C1_ONE (1<<13)
+#define FMC1_C1_MASK (0xffff<<4)
+/* Dword 2 */
+#define FMC2_C2_ONE (1<<16)
+/* Dword 3 */
+#define FMC3_D_ONE (1<<16)
+
+
+
+/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p177 */
+#define _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24))
+#define IAB_MODIFY_ENABLE (1<<23)
+#define IAB_ENABLE (1<<22)
+#define IAB_MODIFY_FUNC (1<<21)
+#define IAB_FUNC_SHIFT 16
+#define IAB_MODIFY_SRC_FACTOR (1<<11)
+#define IAB_SRC_FACTOR_SHIFT 6
+#define IAB_SRC_FACTOR_MASK (BLENDFACT_MASK<<6)
+#define IAB_MODIFY_DST_FACTOR (1<<5)
+#define IAB_DST_FACTOR_SHIFT 0
+#define IAB_DST_FACTOR_MASK (BLENDFACT_MASK<<0)
+
+
+#define BLENDFUNC_ADD 0x0
+#define BLENDFUNC_SUBTRACT 0x1
+#define BLENDFUNC_REVERSE_SUBTRACT 0x2
+#define BLENDFUNC_MIN 0x3
+#define BLENDFUNC_MAX 0x4
+#define BLENDFUNC_MASK 0x7
+
+/* 3DSTATE_LOAD_INDIRECT, p180 */
+
+#define _3DSTATE_LOAD_INDIRECT (CMD_3D|(0x1d<<24)|(0x7<<16))
+#define LI0_STATE_STATIC_INDIRECT (0x01<<8)
+#define LI0_STATE_DYNAMIC_INDIRECT (0x02<<8)
+#define LI0_STATE_SAMPLER (0x04<<8)
+#define LI0_STATE_MAP (0x08<<8)
+#define LI0_STATE_PROGRAM (0x10<<8)
+#define LI0_STATE_CONSTANTS (0x20<<8)
+
+#define SIS0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define SIS0_FORCE_LOAD (1<<1)
+#define SIS0_BUFFER_VALID (1<<0)
+#define SIS1_BUFFER_LENGTH(x) ((x)&0xff)
+
+#define DIS0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define DIS0_BUFFER_RESET (1<<1)
+#define DIS0_BUFFER_VALID (1<<0)
+
+#define SSB0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define SSB0_FORCE_LOAD (1<<1)
+#define SSB0_BUFFER_VALID (1<<0)
+#define SSB1_BUFFER_LENGTH(x) ((x)&0xff)
+
+#define MSB0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define MSB0_FORCE_LOAD (1<<1)
+#define MSB0_BUFFER_VALID (1<<0)
+#define MSB1_BUFFER_LENGTH(x) ((x)&0xff)
+
+#define PSP0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define PSP0_FORCE_LOAD (1<<1)
+#define PSP0_BUFFER_VALID (1<<0)
+#define PSP1_BUFFER_LENGTH(x) ((x)&0xff)
+
+#define PSC0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define PSC0_FORCE_LOAD (1<<1)
+#define PSC0_BUFFER_VALID (1<<0)
+#define PSC1_BUFFER_LENGTH(x) ((x)&0xff)
+
+
+
+
+
+/* _3DSTATE_RASTERIZATION_RULES */
+#define _3DSTATE_RASTER_RULES_CMD (CMD_3D|(0x07<<24))
+#define ENABLE_POINT_RASTER_RULE (1<<15)
+#define OGL_POINT_RASTER_RULE (1<<13)
+#define ENABLE_TEXKILL_3D_4D (1<<10)
+#define TEXKILL_3D (0<<9)
+#define TEXKILL_4D (1<<9)
+#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8)
+#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5)
+#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6)
+#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3)
+
+/* _3DSTATE_SCISSOR_ENABLE, p256 */
+#define _3DSTATE_SCISSOR_ENABLE_CMD (CMD_3D|(0x1c<<24)|(0x10<<19))
+#define ENABLE_SCISSOR_RECT ((1<<1) | 1)
+#define DISABLE_SCISSOR_RECT (1<<1)
+
+/* _3DSTATE_SCISSOR_RECTANGLE_0, p257 */
+#define _3DSTATE_SCISSOR_RECT_0_CMD (CMD_3D|(0x1d<<24)|(0x81<<16)|1)
+/* Dword 1 */
+#define SCISSOR_RECT_0_YMIN(x) ((x)<<16)
+#define SCISSOR_RECT_0_XMIN(x) (x)
+/* Dword 2 */
+#define SCISSOR_RECT_0_YMAX(x) ((x)<<16)
+#define SCISSOR_RECT_0_XMAX(x) (x)
+
+/* p189 */
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_1 ((0x3<<29)|(0x1d<<24)|(0x04<<16))
+#define I1_LOAD_S(n) (1<<(4+n))
+
+#define S0_VB_OFFSET_MASK 0xffffffc
+#define S0_AUTO_CACHE_INV_DISABLE (1<<0)
+
+#define S1_VERTEX_WIDTH_SHIFT 24
+#define S1_VERTEX_WIDTH_MASK (0x3f<<24)
+#define S1_VERTEX_PITCH_SHIFT 16
+#define S1_VERTEX_PITCH_MASK (0x3f<<16)
+
+#define TEXCOORDFMT_2D 0x0
+#define TEXCOORDFMT_3D 0x1
+#define TEXCOORDFMT_4D 0x2
+#define TEXCOORDFMT_1D 0x3
+#define TEXCOORDFMT_2D_16 0x4
+#define TEXCOORDFMT_4D_16 0x5
+#define TEXCOORDFMT_NOT_PRESENT 0xf
+#define S2_TEXCOORD_FMT0_MASK 0xf
+#define S2_TEXCOORD_FMT1_SHIFT 4
+#define S2_TEXCOORD_FMT(unit, type) ((type)<<(unit*4))
+#define S2_TEXCOORD_NONE (~0)
+
+/* S3 not interesting */
+
+#define S4_POINT_WIDTH_SHIFT 23
+#define S4_POINT_WIDTH_MASK (0x1ff<<23)
+#define S4_LINE_WIDTH_SHIFT 19
+#define S4_LINE_WIDTH_ONE (0x2<<19)
+#define S4_LINE_WIDTH_MASK (0xf<<19)
+#define S4_FLATSHADE_ALPHA (1<<18)
+#define S4_FLATSHADE_FOG (1<<17)
+#define S4_FLATSHADE_SPECULAR (1<<16)
+#define S4_FLATSHADE_COLOR (1<<15)
+#define S4_CULLMODE_BOTH (0<<13)
+#define S4_CULLMODE_NONE (1<<13)
+#define S4_CULLMODE_CW (2<<13)
+#define S4_CULLMODE_CCW (3<<13)
+#define S4_CULLMODE_MASK (3<<13)
+#define S4_VFMT_POINT_WIDTH (1<<12)
+#define S4_VFMT_SPEC_FOG (1<<11)
+#define S4_VFMT_COLOR (1<<10)
+#define S4_VFMT_DEPTH_OFFSET (1<<9)
+#define S4_VFMT_XYZ (1<<6)
+#define S4_VFMT_XYZW (2<<6)
+#define S4_VFMT_XY (3<<6)
+#define S4_VFMT_XYW (4<<6)
+#define S4_VFMT_XYZW_MASK (7<<6)
+#define S4_FORCE_DEFAULT_DIFFUSE (1<<5)
+#define S4_FORCE_DEFAULT_SPECULAR (1<<4)
+#define S4_LOCAL_DEPTH_OFFSET_ENABLE (1<<3)
+#define S4_VFMT_FOG_PARAM (1<<2)
+#define S4_SPRITE_POINT_ENABLE (1<<1)
+#define S4_LINE_ANTIALIAS_ENABLE (1<<0)
+
+#define S4_VFMT_MASK (S4_VFMT_POINT_WIDTH | \
+ S4_VFMT_SPEC_FOG | \
+ S4_VFMT_COLOR | \
+ S4_VFMT_DEPTH_OFFSET | \
+ S4_VFMT_XYZW_MASK | \
+ S4_VFMT_FOG_PARAM)
+
+
+#define S5_WRITEDISABLE_ALPHA (1<<31)
+#define S5_WRITEDISABLE_RED (1<<30)
+#define S5_WRITEDISABLE_GREEN (1<<29)
+#define S5_WRITEDISABLE_BLUE (1<<28)
+#define S5_WRITEDISABLE_MASK (0xf<<28)
+#define S5_FORCE_DEFAULT_POINT_SIZE (1<<27)
+#define S5_LAST_PIXEL_ENABLE (1<<26)
+#define S5_GLOBAL_DEPTH_OFFSET_ENABLE (1<<25)
+#define S5_FOG_ENABLE (1<<24)
+#define S5_STENCIL_REF_SHIFT 16
+#define S5_STENCIL_REF_MASK (0xff<<16)
+#define S5_STENCIL_TEST_FUNC_SHIFT 13
+#define S5_STENCIL_TEST_FUNC_MASK (0x7<<13)
+#define S5_STENCIL_FAIL_SHIFT 10
+#define S5_STENCIL_FAIL_MASK (0x7<<10)
+#define S5_STENCIL_PASS_Z_FAIL_SHIFT 7
+#define S5_STENCIL_PASS_Z_FAIL_MASK (0x7<<7)
+#define S5_STENCIL_PASS_Z_PASS_SHIFT 4
+#define S5_STENCIL_PASS_Z_PASS_MASK (0x7<<4)
+#define S5_STENCIL_WRITE_ENABLE (1<<3)
+#define S5_STENCIL_TEST_ENABLE (1<<2)
+#define S5_COLOR_DITHER_ENABLE (1<<1)
+#define S5_LOGICOP_ENABLE (1<<0)
+
+
+#define S6_ALPHA_TEST_ENABLE (1<<31)
+#define S6_ALPHA_TEST_FUNC_SHIFT 28
+#define S6_ALPHA_TEST_FUNC_MASK (0x7<<28)
+#define S6_ALPHA_REF_SHIFT 20
+#define S6_ALPHA_REF_MASK (0xff<<20)
+#define S6_DEPTH_TEST_ENABLE (1<<19)
+#define S6_DEPTH_TEST_FUNC_SHIFT 16
+#define S6_DEPTH_TEST_FUNC_MASK (0x7<<16)
+#define S6_CBUF_BLEND_ENABLE (1<<15)
+#define S6_CBUF_BLEND_FUNC_SHIFT 12
+#define S6_CBUF_BLEND_FUNC_MASK (0x7<<12)
+#define S6_CBUF_SRC_BLEND_FACT_SHIFT 8
+#define S6_CBUF_SRC_BLEND_FACT_MASK (0xf<<8)
+#define S6_CBUF_DST_BLEND_FACT_SHIFT 4
+#define S6_CBUF_DST_BLEND_FACT_MASK (0xf<<4)
+#define S6_DEPTH_WRITE_ENABLE (1<<3)
+#define S6_COLOR_WRITE_ENABLE (1<<2)
+#define S6_TRISTRIP_PV_SHIFT 0
+#define S6_TRISTRIP_PV_MASK (0x3<<0)
+
+#define S7_DEPTH_OFFSET_CONST_MASK ~0
+
+
+
+#define DST_BLND_FACT(f) ((f)<<S6_CBUF_DST_BLEND_FACT_SHIFT)
+#define SRC_BLND_FACT(f) ((f)<<S6_CBUF_SRC_BLEND_FACT_SHIFT)
+#define DST_ABLND_FACT(f) ((f)<<IAB_DST_FACTOR_SHIFT)
+#define SRC_ABLND_FACT(f) ((f)<<IAB_SRC_FACTOR_SHIFT)
+
+
+
+
+/* 3DSTATE_MAP_DEINTERLACER_PARAMETERS */
+
+/* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */
+#define _3DSTATE_MAP_PALETTE_LOAD_32 (CMD_3D|(0x1d<<24)|(0x8f<<16))
+/* subsequent dwords up to length (max 16) are ARGB8888 color values */
+
+/* _3DSTATE_MODES_4, p218 */
+#define _3DSTATE_MODES_4_CMD (CMD_3D|(0x0d<<24))
+#define ENABLE_LOGIC_OP_FUNC (1<<23)
+#define LOGIC_OP_FUNC(x) ((x)<<18)
+#define LOGICOP_MASK (0xf<<18)
+#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
+#define ENABLE_STENCIL_TEST_MASK (1<<17)
+#define STENCIL_TEST_MASK(x) (((x)&0xff)<<8)
+#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
+#define ENABLE_STENCIL_WRITE_MASK (1<<16)
+#define STENCIL_WRITE_MASK(x) ((x)&0xff)
+
+/* _3DSTATE_MODES_5, p220 */
+#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))
+#define PIPELINE_FLUSH_RENDER_CACHE (1<<18)
+#define PIPELINE_FLUSH_TEXTURE_CACHE (1<<16)
+
+
+/* p221 */
+#define _3DSTATE_PIXEL_SHADER_CONSTANTS (CMD_3D|(0x1d<<24)|(0x6<<16))
+#define PS1_REG(n) (1<<(n))
+#define PS2_CONST_X(n) (n)
+#define PS3_CONST_Y(n) (n)
+#define PS4_CONST_Z(n) (n)
+#define PS5_CONST_W(n) (n)
+
+/* 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.
+ */
+#define _3DSTATE_PIXEL_SHADER_PROGRAM (CMD_3D|(0x1d<<24)|(0x5<<16))
+
+#define REG_TYPE_R 0 /* temporary regs, no need to
+ * dcl, must be written before
+ * read -- Preserved between
+ * phases.
+ */
+#define REG_TYPE_T 1 /* Interpolated values, must be
+ * dcl'ed before use.
+ *
+ * 0..7: texture coord,
+ * 8: diffuse spec,
+ * 9: specular color,
+ * 10: fog parameter in w.
+ */
+#define REG_TYPE_CONST 2 /* Restriction: only one const
+ * can be referenced per
+ * instruction, though it may be
+ * selected for multiple inputs.
+ * Constants not initialized
+ * default to zero.
+ */
+#define REG_TYPE_S 3 /* sampler */
+#define REG_TYPE_OC 4 /* output color (rgba) */
+#define REG_TYPE_OD 5 /* output depth (w), xyz are
+ * temporaries. If not written,
+ * interpolated depth is used?
+ */
+#define REG_TYPE_U 6 /* unpreserved temporaries */
+#define REG_TYPE_MASK 0x7
+#define REG_NR_MASK 0xf
+
+
+/* REG_TYPE_T:
+ */
+#define T_TEX0 0
+#define T_TEX1 1
+#define T_TEX2 2
+#define T_TEX3 3
+#define T_TEX4 4
+#define T_TEX5 5
+#define T_TEX6 6
+#define T_TEX7 7
+#define T_DIFFUSE 8
+#define T_SPECULAR 9
+#define T_FOG_W 10 /* interpolated fog is in W coord */
+
+/* Arithmetic instructions */
+
+/* .replicate_swizzle == selection and replication of a particular
+ * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww
+ */
+#define A0_NOP (0x0<<24) /* no operation */
+#define A0_ADD (0x1<<24) /* dst = src0 + src1 */
+#define A0_MOV (0x2<<24) /* dst = src0 */
+#define A0_MUL (0x3<<24) /* dst = src0 * src1 */
+#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */
+#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */
+#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */
+#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */
+#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */
+#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */
+#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */
+#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */
+#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */
+#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */
+#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */
+#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */
+#define A0_FLR (0x10<<24) /* dst = floor(src0) */
+#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */
+#define A0_TRC (0x12<<24) /* dst = int(src0) */
+#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */
+#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */
+#define A0_DEST_SATURATE (1<<22)
+#define A0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+#define A0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define A0_DEST_CHANNEL_X (1<<10)
+#define A0_DEST_CHANNEL_Y (2<<10)
+#define A0_DEST_CHANNEL_Z (4<<10)
+#define A0_DEST_CHANNEL_W (8<<10)
+#define A0_DEST_CHANNEL_ALL (0xf<<10)
+#define A0_DEST_CHANNEL_SHIFT 10
+#define A0_SRC0_TYPE_SHIFT 7
+#define A0_SRC0_NR_SHIFT 2
+
+#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y)
+#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z)
+
+
+#define SRC_X 0
+#define SRC_Y 1
+#define SRC_Z 2
+#define SRC_W 3
+#define SRC_ZERO 4
+#define SRC_ONE 5
+
+#define A1_SRC0_CHANNEL_X_NEGATE (1<<31)
+#define A1_SRC0_CHANNEL_X_SHIFT 28
+#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27)
+#define A1_SRC0_CHANNEL_Y_SHIFT 24
+#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23)
+#define A1_SRC0_CHANNEL_Z_SHIFT 20
+#define A1_SRC0_CHANNEL_W_NEGATE (1<<19)
+#define A1_SRC0_CHANNEL_W_SHIFT 16
+#define A1_SRC1_TYPE_SHIFT 13
+#define A1_SRC1_NR_SHIFT 8
+#define A1_SRC1_CHANNEL_X_NEGATE (1<<7)
+#define A1_SRC1_CHANNEL_X_SHIFT 4
+#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3)
+#define A1_SRC1_CHANNEL_Y_SHIFT 0
+
+#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31)
+#define A2_SRC1_CHANNEL_Z_SHIFT 28
+#define A2_SRC1_CHANNEL_W_NEGATE (1<<27)
+#define A2_SRC1_CHANNEL_W_SHIFT 24
+#define A2_SRC2_TYPE_SHIFT 21
+#define A2_SRC2_NR_SHIFT 16
+#define A2_SRC2_CHANNEL_X_NEGATE (1<<15)
+#define A2_SRC2_CHANNEL_X_SHIFT 12
+#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11)
+#define A2_SRC2_CHANNEL_Y_SHIFT 8
+#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7)
+#define A2_SRC2_CHANNEL_Z_SHIFT 4
+#define A2_SRC2_CHANNEL_W_NEGATE (1<<3)
+#define A2_SRC2_CHANNEL_W_SHIFT 0
+
+
+
+/* Texture instructions */
+#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared
+ * sampler and address, and output
+ * filtered texel data to destination
+ * register */
+#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a
+ * perspective divide of the texture
+ * coordinate .xyz values by .w before
+ * sampling. */
+#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the
+ * computed LOD by w. Only S4.6 two's
+ * comp is used. This implies that a
+ * float to fixed conversion is
+ * done. */
+#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling
+ * operation. Simply kills the pixel
+ * if any channel of the address
+ * register is < 0.0. */
+#define T0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+/* Note: U (unpreserved) regs do not retain their values between
+ * phases (cannot be used for feedback)
+ *
+ * Note: oC and OD registers can only be used as the destination of a
+ * texture instruction once per phase (this is an implementation
+ * restriction).
+ */
+#define T0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */
+#define T0_SAMPLER_NR_MASK (0xf<<0)
+
+#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */
+/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */
+#define T1_ADDRESS_REG_NR_SHIFT 17
+#define T2_MBZ 0
+
+/* Declaration instructions */
+#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib)
+ * register or an s (sampler)
+ * register. */
+#define D0_SAMPLE_TYPE_SHIFT 22
+#define D0_SAMPLE_TYPE_2D (0x0<<22)
+#define D0_SAMPLE_TYPE_CUBE (0x1<<22)
+#define D0_SAMPLE_TYPE_VOLUME (0x2<<22)
+#define D0_SAMPLE_TYPE_MASK (0x3<<22)
+
+#define D0_TYPE_SHIFT 19
+/* Allow: T, S */
+#define D0_NR_SHIFT 14
+/* Allow T: 0..10, S: 0..15 */
+#define D0_CHANNEL_X (1<<10)
+#define D0_CHANNEL_Y (2<<10)
+#define D0_CHANNEL_Z (4<<10)
+#define D0_CHANNEL_W (8<<10)
+#define D0_CHANNEL_ALL (0xf<<10)
+#define D0_CHANNEL_NONE (0<<10)
+
+#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y)
+#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z)
+
+/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse
+ * or specular declarations.
+ *
+ * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw)
+ *
+ * Must be zero for S (sampler) dcls
+ */
+#define D1_MBZ 0
+#define D2_MBZ 0
+
+
+
+/* p207 */
+#define _3DSTATE_MAP_STATE (CMD_3D|(0x1d<<24)|(0x0<<16))
+
+#define MS1_MAPMASK_SHIFT 0
+#define MS1_MAPMASK_MASK (0x8fff<<0)
+
+#define MS2_UNTRUSTED_SURFACE (1<<31)
+#define MS2_ADDRESS_MASK 0xfffffffc
+#define MS2_VERTICAL_LINE_STRIDE (1<<1)
+#define MS2_VERTICAL_OFFSET (1<<1)
+
+#define MS3_HEIGHT_SHIFT 21
+#define MS3_WIDTH_SHIFT 10
+#define MS3_PALETTE_SELECT (1<<9)
+#define MS3_MAPSURF_FORMAT_SHIFT 7
+#define MS3_MAPSURF_FORMAT_MASK (0x7<<7)
+#define MAPSURF_8BIT (1<<7)
+#define MAPSURF_16BIT (2<<7)
+#define MAPSURF_32BIT (3<<7)
+#define MAPSURF_422 (5<<7)
+#define MAPSURF_COMPRESSED (6<<7)
+#define MAPSURF_4BIT_INDEXED (7<<7)
+#define MS3_MT_FORMAT_MASK (0x7 << 3)
+#define MS3_MT_FORMAT_SHIFT 3
+#define MT_4BIT_IDX_ARGB8888 (7<<3) /* SURFACE_4BIT_INDEXED */
+#define MT_8BIT_I8 (0<<3) /* SURFACE_8BIT */
+#define MT_8BIT_L8 (1<<3)
+#define MT_8BIT_A8 (4<<3)
+#define MT_8BIT_MONO8 (5<<3)
+#define MT_16BIT_RGB565 (0<<3) /* SURFACE_16BIT */
+#define MT_16BIT_ARGB1555 (1<<3)
+#define MT_16BIT_ARGB4444 (2<<3)
+#define MT_16BIT_AY88 (3<<3)
+#define MT_16BIT_88DVDU (5<<3)
+#define MT_16BIT_BUMP_655LDVDU (6<<3)
+#define MT_16BIT_I16 (7<<3)
+#define MT_16BIT_L16 (8<<3)
+#define MT_16BIT_A16 (9<<3)
+#define MT_32BIT_ARGB8888 (0<<3) /* SURFACE_32BIT */
+#define MT_32BIT_ABGR8888 (1<<3)
+#define MT_32BIT_XRGB8888 (2<<3)
+#define MT_32BIT_XBGR8888 (3<<3)
+#define MT_32BIT_QWVU8888 (4<<3)
+#define MT_32BIT_AXVU8888 (5<<3)
+#define MT_32BIT_LXVU8888 (6<<3)
+#define MT_32BIT_XLVU8888 (7<<3)
+#define MT_32BIT_ARGB2101010 (8<<3)
+#define MT_32BIT_ABGR2101010 (9<<3)
+#define MT_32BIT_AWVU2101010 (0xA<<3)
+#define MT_32BIT_GR1616 (0xB<<3)
+#define MT_32BIT_VU1616 (0xC<<3)
+#define MT_32BIT_xI824 (0xD<<3)
+#define MT_32BIT_xA824 (0xE<<3)
+#define MT_32BIT_xL824 (0xF<<3)
+#define MT_422_YCRCB_SWAPY (0<<3) /* SURFACE_422 */
+#define MT_422_YCRCB_NORMAL (1<<3)
+#define MT_422_YCRCB_SWAPUV (2<<3)
+#define MT_422_YCRCB_SWAPUVY (3<<3)
+#define MT_COMPRESS_DXT1 (0<<3) /* SURFACE_COMPRESSED */
+#define MT_COMPRESS_DXT2_3 (1<<3)
+#define MT_COMPRESS_DXT4_5 (2<<3)
+#define MT_COMPRESS_FXT1 (3<<3)
+#define MT_COMPRESS_DXT1_RGB (4<<3)
+#define MS3_USE_FENCE_REGS (1<<2)
+#define MS3_TILED_SURFACE (1<<1)
+#define MS3_TILE_WALK (1<<0)
+
+#define MS4_PITCH_SHIFT 21
+#define MS4_CUBE_FACE_ENA_NEGX (1<<20)
+#define MS4_CUBE_FACE_ENA_POSX (1<<19)
+#define MS4_CUBE_FACE_ENA_NEGY (1<<18)
+#define MS4_CUBE_FACE_ENA_POSY (1<<17)
+#define MS4_CUBE_FACE_ENA_NEGZ (1<<16)
+#define MS4_CUBE_FACE_ENA_POSZ (1<<15)
+#define MS4_CUBE_FACE_ENA_MASK (0x3f<<15)
+#define MS4_MAX_LOD_SHIFT 9
+#define MS4_MAX_LOD_MASK (0x3f<<9)
+#define MS4_MIP_LAYOUT_LEGACY (0<<8)
+#define MS4_MIP_LAYOUT_BELOW_LPT (0<<8)
+#define MS4_MIP_LAYOUT_RIGHT_LPT (1<<8)
+#define MS4_VOLUME_DEPTH_SHIFT 0
+#define MS4_VOLUME_DEPTH_MASK (0xff<<0)
+
+/* p244 */
+#define _3DSTATE_SAMPLER_STATE (CMD_3D|(0x1d<<24)|(0x1<<16))
+
+#define SS1_MAPMASK_SHIFT 0
+#define SS1_MAPMASK_MASK (0x8fff<<0)
+
+#define SS2_REVERSE_GAMMA_ENABLE (1<<31)
+#define SS2_PACKED_TO_PLANAR_ENABLE (1<<30)
+#define SS2_COLORSPACE_CONVERSION (1<<29)
+#define SS2_CHROMAKEY_SHIFT 27
+#define SS2_BASE_MIP_LEVEL_SHIFT 22
+#define SS2_BASE_MIP_LEVEL_MASK (0x1f<<22)
+#define SS2_MIP_FILTER_SHIFT 20
+#define SS2_MIP_FILTER_MASK (0x3<<20)
+#define MIPFILTER_NONE 0
+#define MIPFILTER_NEAREST 1
+#define MIPFILTER_LINEAR 3
+#define SS2_MAG_FILTER_SHIFT 17
+#define SS2_MAG_FILTER_MASK (0x7<<17)
+#define FILTER_NEAREST 0
+#define FILTER_LINEAR 1
+#define FILTER_ANISOTROPIC 2
+#define FILTER_4X4_1 3
+#define FILTER_4X4_2 4
+#define FILTER_4X4_FLAT 5
+#define FILTER_6X5_MONO 6 /* XXX - check */
+#define SS2_MIN_FILTER_SHIFT 14
+#define SS2_MIN_FILTER_MASK (0x7<<14)
+#define SS2_LOD_BIAS_SHIFT 5
+#define SS2_LOD_BIAS_ONE (0x10<<5)
+#define SS2_LOD_BIAS_MASK (0x1ff<<5)
+/* Shadow requires:
+ * MT_X8{I,L,A}24 or MT_{I,L,A}16 texture format
+ * FILTER_4X4_x MIN and MAG filters
+ */
+#define SS2_SHADOW_ENABLE (1<<4)
+#define SS2_MAX_ANISO_MASK (1<<3)
+#define SS2_MAX_ANISO_2 (0<<3)
+#define SS2_MAX_ANISO_4 (1<<3)
+#define SS2_SHADOW_FUNC_SHIFT 0
+#define SS2_SHADOW_FUNC_MASK (0x7<<0)
+/* SS2_SHADOW_FUNC values: see COMPAREFUNC_* */
+
+#define SS3_MIN_LOD_SHIFT 24
+#define SS3_MIN_LOD_ONE (0x10<<24)
+#define SS3_MIN_LOD_MASK (0xff<<24)
+#define SS3_KILL_PIXEL_ENABLE (1<<17)
+#define SS3_TCX_ADDR_MODE_SHIFT 12
+#define SS3_TCX_ADDR_MODE_MASK (0x7<<12)
+#define TEXCOORDMODE_WRAP 0
+#define TEXCOORDMODE_MIRROR 1
+#define TEXCOORDMODE_CLAMP_EDGE 2
+#define TEXCOORDMODE_CUBE 3
+#define TEXCOORDMODE_CLAMP_BORDER 4
+#define TEXCOORDMODE_MIRROR_ONCE 5
+#define SS3_TCY_ADDR_MODE_SHIFT 9
+#define SS3_TCY_ADDR_MODE_MASK (0x7<<9)
+#define SS3_TCZ_ADDR_MODE_SHIFT 6
+#define SS3_TCZ_ADDR_MODE_MASK (0x7<<6)
+#define SS3_NORMALIZED_COORDS (1<<5)
+#define SS3_TEXTUREMAP_INDEX_SHIFT 1
+#define SS3_TEXTUREMAP_INDEX_MASK (0xf<<1)
+#define SS3_DEINTERLACER_ENABLE (1<<0)
+
+#define SS4_BORDER_COLOR_MASK (~0)
+
+/* 3DSTATE_SPAN_STIPPLE, p258
+ */
+#define _3DSTATE_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define ST1_ENABLE (1<<16)
+#define ST1_MASK (0xffff)
+
+#define _3DSTATE_DEFAULT_Z ((0x3<<29)|(0x1d<<24)|(0x98<<16))
+#define _3DSTATE_DEFAULT_DIFFUSE ((0x3<<29)|(0x1d<<24)|(0x99<<16))
+#define _3DSTATE_DEFAULT_SPECULAR ((0x3<<29)|(0x1d<<24)|(0x9a<<16))
+
+
+#define MI_FLUSH ((0<<29)|(4<<23))
+#define FLUSH_MAP_CACHE (1<<0)
+#define INHIBIT_FLUSH_RENDER_CACHE (1<<2)
+
+
+#define CMD_3D (0x3<<29)
+
+
+#define _3DPRIMITIVE ((0x3<<29)|(0x1f<<24))
+#define PRIM_INDIRECT (1<<23)
+#define PRIM_INLINE (0<<23)
+#define PRIM_INDIRECT_SEQUENTIAL (0<<17)
+#define PRIM_INDIRECT_ELTS (1<<17)
+
+#define PRIM3D_TRILIST (0x0<<18)
+#define PRIM3D_TRISTRIP (0x1<<18)
+#define PRIM3D_TRISTRIP_RVRSE (0x2<<18)
+#define PRIM3D_TRIFAN (0x3<<18)
+#define PRIM3D_POLY (0x4<<18)
+#define PRIM3D_LINELIST (0x5<<18)
+#define PRIM3D_LINESTRIP (0x6<<18)
+#define PRIM3D_RECTLIST (0x7<<18)
+#define PRIM3D_POINTLIST (0x8<<18)
+#define PRIM3D_DIB (0x9<<18)
+#define PRIM3D_MASK (0x1f<<18)
+
+#define I915PACKCOLOR4444(r,g,b,a) \
+ ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
+
+#define I915PACKCOLOR1555(r,g,b,a) \
+ ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
+ ((a) ? 0x8000 : 0))
+
+#define I915PACKCOLOR565(r,g,b) \
+ ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
+
+#define I915PACKCOLOR8888(r,g,b,a) \
+ ((a<<24) | (r<<16) | (g<<8) | b)
+
+
+
+
+#define BR00_BITBLT_CLIENT 0x40000000
+#define BR00_OP_COLOR_BLT 0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR13_SOLID_PATTERN 0x80000000
+
+#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|0x4)
+#define XY_COLOR_BLT_WRITE_ALPHA (1<<21)
+#define XY_COLOR_BLT_WRITE_RGB (1<<20)
+
+#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
+
+#define MI_WAIT_FOR_EVENT ((0x3<<23))
+#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
+#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
+
+#define MI_BATCH_BUFFER (0x30<<23)
+#define MI_BATCH_BUFFER_START (0x31<<23)
+#define MI_BATCH_BUFFER_END (0xa<<23)
+
+
+
+#define COMPAREFUNC_ALWAYS 0
+#define COMPAREFUNC_NEVER 0x1
+#define COMPAREFUNC_LESS 0x2
+#define COMPAREFUNC_EQUAL 0x3
+#define COMPAREFUNC_LEQUAL 0x4
+#define COMPAREFUNC_GREATER 0x5
+#define COMPAREFUNC_NOTEQUAL 0x6
+#define COMPAREFUNC_GEQUAL 0x7
+
+#define STENCILOP_KEEP 0
+#define STENCILOP_ZERO 0x1
+#define STENCILOP_REPLACE 0x2
+#define STENCILOP_INCRSAT 0x3
+#define STENCILOP_DECRSAT 0x4
+#define STENCILOP_INCR 0x5
+#define STENCILOP_DECR 0x6
+#define STENCILOP_INVERT 0x7
+
+#define LOGICOP_CLEAR 0
+#define LOGICOP_NOR 0x1
+#define LOGICOP_AND_INV 0x2
+#define LOGICOP_COPY_INV 0x3
+#define LOGICOP_AND_RVRSE 0x4
+#define LOGICOP_INV 0x5
+#define LOGICOP_XOR 0x6
+#define LOGICOP_NAND 0x7
+#define LOGICOP_AND 0x8
+#define LOGICOP_EQUIV 0x9
+#define LOGICOP_NOOP 0xa
+#define LOGICOP_OR_INV 0xb
+#define LOGICOP_COPY 0xc
+#define LOGICOP_OR_RVRSE 0xd
+#define LOGICOP_OR 0xe
+#define LOGICOP_SET 0xf
+
+#define BLENDFACT_ZERO 0x01
+#define BLENDFACT_ONE 0x02
+#define BLENDFACT_SRC_COLR 0x03
+#define BLENDFACT_INV_SRC_COLR 0x04
+#define BLENDFACT_SRC_ALPHA 0x05
+#define BLENDFACT_INV_SRC_ALPHA 0x06
+#define BLENDFACT_DST_ALPHA 0x07
+#define BLENDFACT_INV_DST_ALPHA 0x08
+#define BLENDFACT_DST_COLR 0x09
+#define BLENDFACT_INV_DST_COLR 0x0a
+#define BLENDFACT_SRC_ALPHA_SATURATE 0x0b
+#define BLENDFACT_CONST_COLOR 0x0c
+#define BLENDFACT_INV_CONST_COLOR 0x0d
+#define BLENDFACT_CONST_ALPHA 0x0e
+#define BLENDFACT_INV_CONST_ALPHA 0x0f
+#define BLENDFACT_MASK 0x0f
+
+#define PCI_CHIP_I915_G 0x2582
+#define PCI_CHIP_I915_GM 0x2592
+#define PCI_CHIP_I945_G 0x2772
+#define PCI_CHIP_I945_GM 0x27A2
+#define PCI_CHIP_I945_GME 0x27AE
+#define PCI_CHIP_G33_G 0x29C2
+#define PCI_CHIP_Q35_G 0x29B2
+#define PCI_CHIP_Q33_G 0x29D2
+
+
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_screen.c b/src/gallium/drivers/i915simple/i915_screen.c
new file mode 100644
index 0000000000..9f017a14cc
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_screen.c
@@ -0,0 +1,300 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_string.h"
+
+#include "i915_reg.h"
+#include "i915_context.h"
+#include "i915_screen.h"
+#include "i915_buffer.h"
+#include "i915_texture.h"
+#include "intel_winsys.h"
+
+
+/*
+ * Probe functions
+ */
+
+
+static const char *
+i915_get_vendor(struct pipe_screen *screen)
+{
+ return "Tungsten Graphics, Inc.";
+}
+
+static const char *
+i915_get_name(struct pipe_screen *screen)
+{
+ static char buffer[128];
+ const char *chipset;
+
+ switch (i915_screen(screen)->pci_id) {
+ case PCI_CHIP_I915_G:
+ chipset = "915G";
+ break;
+ case PCI_CHIP_I915_GM:
+ chipset = "915GM";
+ break;
+ case PCI_CHIP_I945_G:
+ chipset = "945G";
+ break;
+ case PCI_CHIP_I945_GM:
+ chipset = "945GM";
+ break;
+ case PCI_CHIP_I945_GME:
+ chipset = "945GME";
+ break;
+ case PCI_CHIP_G33_G:
+ chipset = "G33";
+ break;
+ case PCI_CHIP_Q35_G:
+ chipset = "Q35";
+ break;
+ case PCI_CHIP_Q33_G:
+ chipset = "Q33";
+ break;
+ default:
+ chipset = "unknown";
+ break;
+ }
+
+ util_snprintf(buffer, sizeof(buffer), "i915 (chipset: %s)", chipset);
+ return buffer;
+}
+
+static int
+i915_get_param(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return 8;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 1;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 1;
+ case PIPE_CAP_GLSL:
+ return 0;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 0;
+ case PIPE_CAP_POINT_SPRITE:
+ return 0;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 1;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 0;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 1;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 11; /* max 1024x1024 */
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 8; /* max 128x128x128 */
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 11; /* max 1024x1024 */
+ default:
+ return 0;
+ }
+}
+
+static float
+i915_get_paramf(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 7.5;
+
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 255.0;
+
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 4.0;
+
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 16.0;
+
+ default:
+ return 0;
+ }
+}
+
+static boolean
+i915_is_format_supported(struct pipe_screen *screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ static const enum pipe_format tex_supported[] = {
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_I8_UNORM,
+ PIPE_FORMAT_A8L8_UNORM,
+ PIPE_FORMAT_YCBCR,
+ PIPE_FORMAT_YCBCR_REV,
+ PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_FORMAT_NONE /* list terminator */
+ };
+ static const enum pipe_format surface_supported[] = {
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_FORMAT_NONE /* list terminator */
+ };
+ const enum pipe_format *list;
+ uint i;
+
+ if(tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET)
+ list = surface_supported;
+ else
+ list = tex_supported;
+
+ for (i = 0; list[i] != PIPE_FORMAT_NONE; i++) {
+ if (list[i] == format)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Fence functions
+ */
+
+
+static void
+i915_fence_reference(struct pipe_screen *screen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ struct i915_screen *is = i915_screen(screen);
+
+ is->iws->fence_reference(is->iws, ptr, fence);
+}
+
+static int
+i915_fence_signalled(struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
+{
+ struct i915_screen *is = i915_screen(screen);
+
+ return is->iws->fence_signalled(is->iws, fence);
+}
+
+static int
+i915_fence_finish(struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
+{
+ struct i915_screen *is = i915_screen(screen);
+
+ return is->iws->fence_finish(is->iws, fence);
+}
+
+
+/*
+ * Generic functions
+ */
+
+
+static void
+i915_destroy_screen(struct pipe_screen *screen)
+{
+ struct i915_screen *is = i915_screen(screen);
+
+ if (is->iws)
+ is->iws->destroy(is->iws);
+
+ FREE(is);
+}
+
+/**
+ * Create a new i915_screen object
+ */
+struct pipe_screen *
+i915_create_screen(struct intel_winsys *iws, uint pci_id)
+{
+ struct i915_screen *is = CALLOC_STRUCT(i915_screen);
+
+ if (!is)
+ return NULL;
+
+ switch (pci_id) {
+ case PCI_CHIP_I915_G:
+ case PCI_CHIP_I915_GM:
+ is->is_i945 = FALSE;
+ break;
+
+ case PCI_CHIP_I945_G:
+ case PCI_CHIP_I945_GM:
+ case PCI_CHIP_I945_GME:
+ case PCI_CHIP_G33_G:
+ case PCI_CHIP_Q33_G:
+ case PCI_CHIP_Q35_G:
+ is->is_i945 = TRUE;
+ break;
+
+ default:
+ debug_printf("%s: unknown pci id 0x%x, cannot create screen\n",
+ __FUNCTION__, pci_id);
+ return NULL;
+ }
+
+ is->pci_id = pci_id;
+ is->iws = iws;
+
+ is->base.winsys = NULL;
+
+ is->base.destroy = i915_destroy_screen;
+
+ is->base.get_name = i915_get_name;
+ is->base.get_vendor = i915_get_vendor;
+ is->base.get_param = i915_get_param;
+ is->base.get_paramf = i915_get_paramf;
+ is->base.is_format_supported = i915_is_format_supported;
+
+ is->base.fence_reference = i915_fence_reference;
+ is->base.fence_signalled = i915_fence_signalled;
+ is->base.fence_finish = i915_fence_finish;
+
+ i915_init_screen_texture_functions(is);
+ i915_init_screen_buffer_functions(is);
+
+ return &is->base;
+}
diff --git a/src/gallium/drivers/i915simple/i915_screen.h b/src/gallium/drivers/i915simple/i915_screen.h
new file mode 100644
index 0000000000..5126485caa
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_screen.h
@@ -0,0 +1,80 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef I915_SCREEN_H
+#define I915_SCREEN_H
+
+#include "pipe/p_state.h"
+#include "pipe/p_screen.h"
+
+
+struct intel_winsys;
+
+
+/**
+ * Subclass of pipe_screen
+ */
+struct i915_screen
+{
+ struct pipe_screen base;
+
+ struct intel_winsys *iws;
+
+ boolean is_i945;
+ uint pci_id;
+};
+
+/**
+ * Subclass of pipe_transfer
+ */
+struct i915_transfer
+{
+ struct pipe_transfer base;
+
+ unsigned offset;
+};
+
+
+/*
+ * Cast wrappers
+ */
+
+
+static INLINE struct i915_screen *
+i915_screen(struct pipe_screen *pscreen)
+{
+ return (struct i915_screen *) pscreen;
+}
+
+static INLINE struct i915_transfer *
+i915_transfer(struct pipe_transfer *transfer)
+{
+ return (struct i915_transfer *)transfer;
+}
+
+
+#endif /* I915_SCREEN_H */
diff --git a/src/gallium/drivers/i915simple/i915_state.c b/src/gallium/drivers/i915simple/i915_state.c
new file mode 100644
index 0000000000..0087dfa410
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_state.c
@@ -0,0 +1,788 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "draw/draw_context.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_parse.h"
+
+#include "i915_context.h"
+#include "i915_reg.h"
+#include "i915_state.h"
+#include "i915_state_inlines.h"
+#include "i915_fpc.h"
+
+/* The i915 (and related graphics cores) do not support GL_CLAMP. The
+ * Intel drivers for "other operating systems" implement GL_CLAMP as
+ * GL_CLAMP_TO_EDGE, so the same is done here.
+ */
+static unsigned
+translate_wrap_mode(unsigned wrap)
+{
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ return TEXCOORDMODE_WRAP;
+ case PIPE_TEX_WRAP_CLAMP:
+ return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ return TEXCOORDMODE_CLAMP_EDGE;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ return TEXCOORDMODE_CLAMP_BORDER;
+// case PIPE_TEX_WRAP_MIRRORED_REPEAT:
+// return TEXCOORDMODE_MIRROR;
+ default:
+ return TEXCOORDMODE_WRAP;
+ }
+}
+
+static unsigned translate_img_filter( unsigned filter )
+{
+ switch (filter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ return FILTER_NEAREST;
+ case PIPE_TEX_FILTER_LINEAR:
+ return FILTER_LINEAR;
+ case PIPE_TEX_FILTER_ANISO:
+ return FILTER_ANISOTROPIC;
+ default:
+ assert(0);
+ return FILTER_NEAREST;
+ }
+}
+
+static unsigned translate_mip_filter( unsigned filter )
+{
+ switch (filter) {
+ case PIPE_TEX_MIPFILTER_NONE:
+ return MIPFILTER_NONE;
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ return MIPFILTER_NEAREST;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ return MIPFILTER_LINEAR;
+ default:
+ assert(0);
+ return MIPFILTER_NONE;
+ }
+}
+
+
+/* None of this state is actually used for anything yet.
+ */
+static void *
+i915_create_blend_state(struct pipe_context *pipe,
+ const struct pipe_blend_state *blend)
+{
+ struct i915_blend_state *cso_data = CALLOC_STRUCT( i915_blend_state );
+
+ {
+ unsigned eqRGB = blend->rgb_func;
+ unsigned srcRGB = blend->rgb_src_factor;
+ unsigned dstRGB = blend->rgb_dst_factor;
+
+ unsigned eqA = blend->alpha_func;
+ unsigned srcA = blend->alpha_src_factor;
+ unsigned dstA = blend->alpha_dst_factor;
+
+ /* Special handling for MIN/MAX filter modes handled at
+ * state_tracker level.
+ */
+
+ if (srcA != srcRGB ||
+ dstA != dstRGB ||
+ eqA != eqRGB) {
+
+ cso_data->iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+ IAB_MODIFY_ENABLE |
+ IAB_ENABLE |
+ IAB_MODIFY_FUNC |
+ IAB_MODIFY_SRC_FACTOR |
+ IAB_MODIFY_DST_FACTOR |
+ SRC_ABLND_FACT(i915_translate_blend_factor(srcA)) |
+ DST_ABLND_FACT(i915_translate_blend_factor(dstA)) |
+ (i915_translate_blend_func(eqA) << IAB_FUNC_SHIFT));
+ }
+ else {
+ cso_data->iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+ IAB_MODIFY_ENABLE |
+ 0);
+ }
+ }
+
+ cso_data->modes4 |= (_3DSTATE_MODES_4_CMD |
+ ENABLE_LOGIC_OP_FUNC |
+ LOGIC_OP_FUNC(i915_translate_logic_op(blend->logicop_func)));
+
+ if (blend->logicop_enable)
+ cso_data->LIS5 |= S5_LOGICOP_ENABLE;
+
+ if (blend->dither)
+ cso_data->LIS5 |= S5_COLOR_DITHER_ENABLE;
+
+ if ((blend->colormask & PIPE_MASK_R) == 0)
+ cso_data->LIS5 |= S5_WRITEDISABLE_RED;
+
+ if ((blend->colormask & PIPE_MASK_G) == 0)
+ cso_data->LIS5 |= S5_WRITEDISABLE_GREEN;
+
+ if ((blend->colormask & PIPE_MASK_B) == 0)
+ cso_data->LIS5 |= S5_WRITEDISABLE_BLUE;
+
+ if ((blend->colormask & PIPE_MASK_A) == 0)
+ cso_data->LIS5 |= S5_WRITEDISABLE_ALPHA;
+
+ if (blend->blend_enable) {
+ unsigned funcRGB = blend->rgb_func;
+ unsigned srcRGB = blend->rgb_src_factor;
+ unsigned dstRGB = blend->rgb_dst_factor;
+
+ cso_data->LIS6 |= (S6_CBUF_BLEND_ENABLE |
+ SRC_BLND_FACT(i915_translate_blend_factor(srcRGB)) |
+ DST_BLND_FACT(i915_translate_blend_factor(dstRGB)) |
+ (i915_translate_blend_func(funcRGB) << S6_CBUF_BLEND_FUNC_SHIFT));
+ }
+
+ return cso_data;
+}
+
+static void i915_bind_blend_state(struct pipe_context *pipe,
+ void *blend)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
+
+ i915->blend = (struct i915_blend_state*)blend;
+
+ i915->dirty |= I915_NEW_BLEND;
+}
+
+
+static void i915_delete_blend_state(struct pipe_context *pipe, void *blend)
+{
+ FREE(blend);
+}
+
+static void i915_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color )
+{
+ struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
+
+ i915->blend_color = *blend_color;
+
+ i915->dirty |= I915_NEW_BLEND;
+}
+
+static void *
+i915_create_sampler_state(struct pipe_context *pipe,
+ const struct pipe_sampler_state *sampler)
+{
+ struct i915_sampler_state *cso = CALLOC_STRUCT( i915_sampler_state );
+ const unsigned ws = sampler->wrap_s;
+ const unsigned wt = sampler->wrap_t;
+ const unsigned wr = sampler->wrap_r;
+ unsigned minFilt, magFilt;
+ unsigned mipFilt;
+
+ cso->templ = sampler;
+
+ mipFilt = translate_mip_filter(sampler->min_mip_filter);
+ minFilt = translate_img_filter( sampler->min_img_filter );
+ magFilt = translate_img_filter( sampler->mag_img_filter );
+
+ if (sampler->max_anisotropy > 2.0) {
+ cso->state[0] |= SS2_MAX_ANISO_4;
+ }
+
+ {
+ int b = (int) (sampler->lod_bias * 16.0);
+ b = CLAMP(b, -256, 255);
+ cso->state[0] |= ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
+ }
+
+ /* Shadow:
+ */
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE)
+ {
+ cso->state[0] |= (SS2_SHADOW_ENABLE |
+ i915_translate_compare_func(sampler->compare_func));
+
+ minFilt = FILTER_4X4_FLAT;
+ magFilt = FILTER_4X4_FLAT;
+ }
+
+ cso->state[0] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
+ (mipFilt << SS2_MIP_FILTER_SHIFT) |
+ (magFilt << SS2_MAG_FILTER_SHIFT));
+
+ cso->state[1] |=
+ ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) |
+ (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
+ (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));
+
+ if (sampler->normalized_coords)
+ cso->state[1] |= SS3_NORMALIZED_COORDS;
+
+ {
+ int minlod = (int) (16.0 * sampler->min_lod);
+ int maxlod = (int) (16.0 * sampler->max_lod);
+ minlod = CLAMP(minlod, 0, 16 * 11);
+ maxlod = CLAMP(maxlod, 0, 16 * 11);
+
+ if (minlod > maxlod)
+ maxlod = minlod;
+
+ cso->minlod = minlod;
+ cso->maxlod = maxlod;
+ }
+
+ {
+ ubyte r = float_to_ubyte(sampler->border_color[0]);
+ ubyte g = float_to_ubyte(sampler->border_color[1]);
+ ubyte b = float_to_ubyte(sampler->border_color[2]);
+ ubyte a = float_to_ubyte(sampler->border_color[3]);
+ cso->state[2] = I915PACKCOLOR8888(r, g, b, a);
+ }
+ return cso;
+}
+
+static void i915_bind_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **sampler)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ unsigned i;
+
+ assert(num <= PIPE_MAX_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == i915->num_samplers &&
+ !memcmp(i915->sampler, sampler, num * sizeof(void *)))
+ return;
+
+ draw_flush(i915->draw);
+
+ for (i = 0; i < num; ++i)
+ i915->sampler[i] = sampler[i];
+ for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
+ i915->sampler[i] = NULL;
+
+ i915->num_samplers = num;
+
+ i915->dirty |= I915_NEW_SAMPLER;
+}
+
+static void i915_delete_sampler_state(struct pipe_context *pipe,
+ void *sampler)
+{
+ FREE(sampler);
+}
+
+
+/** XXX move someday? Or consolidate all these simple state setters
+ * into one file.
+ */
+
+static void *
+i915_create_depth_stencil_state(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *depth_stencil)
+{
+ struct i915_depth_stencil_state *cso = CALLOC_STRUCT( i915_depth_stencil_state );
+
+ {
+ int testmask = depth_stencil->stencil[0].valuemask & 0xff;
+ int writemask = depth_stencil->stencil[0].writemask & 0xff;
+
+ cso->stencil_modes4 |= (_3DSTATE_MODES_4_CMD |
+ ENABLE_STENCIL_TEST_MASK |
+ STENCIL_TEST_MASK(testmask) |
+ ENABLE_STENCIL_WRITE_MASK |
+ STENCIL_WRITE_MASK(writemask));
+ }
+
+ if (depth_stencil->stencil[0].enabled) {
+ int test = i915_translate_compare_func(depth_stencil->stencil[0].func);
+ int fop = i915_translate_stencil_op(depth_stencil->stencil[0].fail_op);
+ int dfop = i915_translate_stencil_op(depth_stencil->stencil[0].zfail_op);
+ int dpop = i915_translate_stencil_op(depth_stencil->stencil[0].zpass_op);
+ int ref = depth_stencil->stencil[0].ref_value & 0xff;
+
+ cso->stencil_LIS5 |= (S5_STENCIL_TEST_ENABLE |
+ S5_STENCIL_WRITE_ENABLE |
+ (ref << S5_STENCIL_REF_SHIFT) |
+ (test << S5_STENCIL_TEST_FUNC_SHIFT) |
+ (fop << S5_STENCIL_FAIL_SHIFT) |
+ (dfop << S5_STENCIL_PASS_Z_FAIL_SHIFT) |
+ (dpop << S5_STENCIL_PASS_Z_PASS_SHIFT));
+ }
+
+ if (depth_stencil->stencil[1].enabled) {
+ int test = i915_translate_compare_func(depth_stencil->stencil[1].func);
+ int fop = i915_translate_stencil_op(depth_stencil->stencil[1].fail_op);
+ int dfop = i915_translate_stencil_op(depth_stencil->stencil[1].zfail_op);
+ int dpop = i915_translate_stencil_op(depth_stencil->stencil[1].zpass_op);
+ int ref = depth_stencil->stencil[1].ref_value & 0xff;
+ int tmask = depth_stencil->stencil[1].valuemask & 0xff;
+ int wmask = depth_stencil->stencil[1].writemask & 0xff;
+
+ cso->bfo[0] = (_3DSTATE_BACKFACE_STENCIL_OPS |
+ BFO_ENABLE_STENCIL_FUNCS |
+ BFO_ENABLE_STENCIL_TWO_SIDE |
+ BFO_ENABLE_STENCIL_REF |
+ BFO_STENCIL_TWO_SIDE |
+ (ref << BFO_STENCIL_REF_SHIFT) |
+ (test << BFO_STENCIL_TEST_SHIFT) |
+ (fop << BFO_STENCIL_FAIL_SHIFT) |
+ (dfop << BFO_STENCIL_PASS_Z_FAIL_SHIFT) |
+ (dpop << BFO_STENCIL_PASS_Z_PASS_SHIFT));
+
+ cso->bfo[1] = (_3DSTATE_BACKFACE_STENCIL_MASKS |
+ BFM_ENABLE_STENCIL_TEST_MASK |
+ BFM_ENABLE_STENCIL_WRITE_MASK |
+ (tmask << BFM_STENCIL_TEST_MASK_SHIFT) |
+ (wmask << BFM_STENCIL_WRITE_MASK_SHIFT));
+ }
+ else {
+ /* This actually disables two-side stencil: The bit set is a
+ * modify-enable bit to indicate we are changing the two-side
+ * setting. Then there is a symbolic zero to show that we are
+ * setting the flag to zero/off.
+ */
+ cso->bfo[0] = (_3DSTATE_BACKFACE_STENCIL_OPS |
+ BFO_ENABLE_STENCIL_TWO_SIDE |
+ 0);
+ cso->bfo[1] = 0;
+ }
+
+ if (depth_stencil->depth.enabled) {
+ int func = i915_translate_compare_func(depth_stencil->depth.func);
+
+ cso->depth_LIS6 |= (S6_DEPTH_TEST_ENABLE |
+ (func << S6_DEPTH_TEST_FUNC_SHIFT));
+
+ if (depth_stencil->depth.writemask)
+ cso->depth_LIS6 |= S6_DEPTH_WRITE_ENABLE;
+ }
+
+ if (depth_stencil->alpha.enabled) {
+ int test = i915_translate_compare_func(depth_stencil->alpha.func);
+ ubyte refByte = float_to_ubyte(depth_stencil->alpha.ref_value);
+
+ cso->depth_LIS6 |= (S6_ALPHA_TEST_ENABLE |
+ (test << S6_ALPHA_TEST_FUNC_SHIFT) |
+ (((unsigned) refByte) << S6_ALPHA_REF_SHIFT));
+ }
+
+ return cso;
+}
+
+static void i915_bind_depth_stencil_state(struct pipe_context *pipe,
+ void *depth_stencil)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
+
+ i915->depth_stencil = (const struct i915_depth_stencil_state *)depth_stencil;
+
+ i915->dirty |= I915_NEW_DEPTH_STENCIL;
+}
+
+static void i915_delete_depth_stencil_state(struct pipe_context *pipe,
+ void *depth_stencil)
+{
+ FREE(depth_stencil);
+}
+
+
+static void i915_set_scissor_state( struct pipe_context *pipe,
+ const struct pipe_scissor_state *scissor )
+{
+ struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
+
+ memcpy( &i915->scissor, scissor, sizeof(*scissor) );
+ i915->dirty |= I915_NEW_SCISSOR;
+}
+
+
+static void i915_set_polygon_stipple( struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple )
+{
+}
+
+
+
+static void *
+i915_create_fs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ struct i915_fragment_shader *ifs = CALLOC_STRUCT(i915_fragment_shader);
+ if (!ifs)
+ return NULL;
+
+ ifs->state.tokens = tgsi_dup_tokens(templ->tokens);
+
+ tgsi_scan_shader(templ->tokens, &ifs->info);
+
+ /* The shader's compiled to i915 instructions here */
+ i915_translate_fragment_program(i915, ifs);
+
+ return ifs;
+}
+
+static void
+i915_bind_fs_state(struct pipe_context *pipe, void *shader)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
+
+ i915->fs = (struct i915_fragment_shader*) shader;
+
+ i915->dirty |= I915_NEW_FS;
+}
+
+static
+void i915_delete_fs_state(struct pipe_context *pipe, void *shader)
+{
+ struct i915_fragment_shader *ifs = (struct i915_fragment_shader *) shader;
+
+ if (ifs->program)
+ FREE(ifs->program);
+ ifs->program_len = 0;
+
+ FREE((struct tgsi_token *)ifs->state.tokens);
+
+ FREE(ifs);
+}
+
+
+static void *
+i915_create_vs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ /* just pass-through to draw module */
+ return draw_create_vertex_shader(i915->draw, templ);
+}
+
+static void i915_bind_vs_state(struct pipe_context *pipe, void *shader)
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ /* just pass-through to draw module */
+ draw_bind_vertex_shader(i915->draw, (struct draw_vertex_shader *) shader);
+
+ i915->dirty |= I915_NEW_VS;
+}
+
+static void i915_delete_vs_state(struct pipe_context *pipe, void *shader)
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ /* just pass-through to draw module */
+ draw_delete_vertex_shader(i915->draw, (struct draw_vertex_shader *) shader);
+}
+
+static void i915_set_constant_buffer(struct pipe_context *pipe,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ struct pipe_screen *screen = pipe->screen;
+ draw_flush(i915->draw);
+
+ assert(shader < PIPE_SHADER_TYPES);
+ assert(index == 0);
+
+ /* Make a copy of shader constants.
+ * During fragment program translation we may add additional
+ * constants to the array.
+ *
+ * We want to consider the situation where some user constants
+ * (ex: a material color) may change frequently but the shader program
+ * stays the same. In that case we should only be updating the first
+ * N constants, leaving any extras from shader translation alone.
+ */
+ if (buf) {
+ void *mapped;
+ if (buf->buffer && buf->buffer->size &&
+ (mapped = pipe_buffer_map(screen, buf->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ))) {
+ memcpy(i915->current.constants[shader], mapped, buf->buffer->size);
+ pipe_buffer_unmap(screen, buf->buffer);
+ i915->current.num_user_constants[shader]
+ = buf->buffer->size / (4 * sizeof(float));
+ }
+ else {
+ i915->current.num_user_constants[shader] = 0;
+ }
+ }
+
+ i915->dirty |= I915_NEW_CONSTANTS;
+}
+
+
+static void i915_set_sampler_textures(struct pipe_context *pipe,
+ unsigned num,
+ struct pipe_texture **texture)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ uint i;
+
+ assert(num <= PIPE_MAX_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == i915->num_textures &&
+ !memcmp(i915->texture, texture, num * sizeof(struct pipe_texture *)))
+ return;
+
+ /* Fixes wrong texture in texobj with VBUF */
+ draw_flush(i915->draw);
+
+ for (i = 0; i < num; i++)
+ pipe_texture_reference((struct pipe_texture **) &i915->texture[i],
+ texture[i]);
+
+ for (i = num; i < i915->num_textures; i++)
+ pipe_texture_reference((struct pipe_texture **) &i915->texture[i],
+ NULL);
+
+ i915->num_textures = num;
+
+ i915->dirty |= I915_NEW_TEXTURE;
+}
+
+
+
+static void i915_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
+
+ i915->framebuffer = *fb; /* struct copy */
+
+ i915->dirty |= I915_NEW_FRAMEBUFFER;
+}
+
+
+
+static void i915_set_clip_state( struct pipe_context *pipe,
+ const struct pipe_clip_state *clip )
+{
+ struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
+
+ draw_set_clip_state(i915->draw, clip);
+
+ i915->dirty |= I915_NEW_CLIP;
+}
+
+
+
+/* Called when driver state tracker notices changes to the viewport
+ * matrix:
+ */
+static void i915_set_viewport_state( struct pipe_context *pipe,
+ const struct pipe_viewport_state *viewport )
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ i915->viewport = *viewport; /* struct copy */
+
+ /* pass the viewport info to the draw module */
+ draw_set_viewport_state(i915->draw, &i915->viewport);
+
+ i915->dirty |= I915_NEW_VIEWPORT;
+}
+
+
+static void *
+i915_create_rasterizer_state(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *rasterizer)
+{
+ struct i915_rasterizer_state *cso = CALLOC_STRUCT( i915_rasterizer_state );
+
+ cso->templ = rasterizer;
+ cso->color_interp = rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
+ cso->light_twoside = rasterizer->light_twoside;
+ cso->ds[0].u = _3DSTATE_DEPTH_OFFSET_SCALE;
+ cso->ds[1].f = rasterizer->offset_scale;
+ if (rasterizer->poly_stipple_enable) {
+ cso->st |= ST1_ENABLE;
+ }
+
+ if (rasterizer->scissor)
+ cso->sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT;
+ else
+ cso->sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT;
+
+ switch (rasterizer->cull_mode) {
+ case PIPE_WINDING_NONE:
+ cso->LIS4 |= S4_CULLMODE_NONE;
+ break;
+ case PIPE_WINDING_CW:
+ cso->LIS4 |= S4_CULLMODE_CW;
+ break;
+ case PIPE_WINDING_CCW:
+ cso->LIS4 |= S4_CULLMODE_CCW;
+ break;
+ case PIPE_WINDING_BOTH:
+ cso->LIS4 |= S4_CULLMODE_BOTH;
+ break;
+ }
+
+ {
+ int line_width = CLAMP((int)(rasterizer->line_width * 2), 1, 0xf);
+
+ cso->LIS4 |= line_width << S4_LINE_WIDTH_SHIFT;
+
+ if (rasterizer->line_smooth)
+ cso->LIS4 |= S4_LINE_ANTIALIAS_ENABLE;
+ }
+
+ {
+ int point_size = CLAMP((int) rasterizer->point_size, 1, 0xff);
+
+ cso->LIS4 |= point_size << S4_POINT_WIDTH_SHIFT;
+ }
+
+ if (rasterizer->flatshade) {
+ cso->LIS4 |= (S4_FLATSHADE_ALPHA |
+ S4_FLATSHADE_COLOR |
+ S4_FLATSHADE_SPECULAR);
+ }
+
+ cso->LIS7 = fui( rasterizer->offset_units );
+
+
+ return cso;
+}
+
+static void i915_bind_rasterizer_state( struct pipe_context *pipe,
+ void *raster )
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ i915->rasterizer = (struct i915_rasterizer_state *)raster;
+
+ /* pass-through to draw module */
+ draw_set_rasterizer_state(i915->draw,
+ (i915->rasterizer ? i915->rasterizer->templ : NULL));
+
+ i915->dirty |= I915_NEW_RASTERIZER;
+}
+
+static void i915_delete_rasterizer_state(struct pipe_context *pipe,
+ void *raster)
+{
+ FREE(raster);
+}
+
+static void i915_set_vertex_buffers(struct pipe_context *pipe,
+ unsigned count,
+ 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);
+
+ memcpy(i915->vertex_buffer, buffers, count * sizeof(buffers[0]));
+ i915->num_vertex_buffers = count;
+
+ /* pass-through to draw module */
+ draw_set_vertex_buffers(i915->draw, count, buffers);
+}
+
+static void i915_set_vertex_elements(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_element *elements)
+{
+ 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);
+
+ i915->num_vertex_elements = count;
+ /* pass-through to draw module */
+ draw_set_vertex_elements(i915->draw, count, elements);
+}
+
+
+static void i915_set_edgeflags(struct pipe_context *pipe,
+ const unsigned *bitfield)
+{
+ /* TODO do something here */
+}
+
+void
+i915_init_state_functions( struct i915_context *i915 )
+{
+ i915->base.set_edgeflags = i915_set_edgeflags;
+ i915->base.create_blend_state = i915_create_blend_state;
+ i915->base.bind_blend_state = i915_bind_blend_state;
+ i915->base.delete_blend_state = i915_delete_blend_state;
+
+ i915->base.create_sampler_state = i915_create_sampler_state;
+ i915->base.bind_sampler_states = i915_bind_sampler_states;
+ i915->base.delete_sampler_state = i915_delete_sampler_state;
+
+ i915->base.create_depth_stencil_alpha_state = i915_create_depth_stencil_state;
+ i915->base.bind_depth_stencil_alpha_state = i915_bind_depth_stencil_state;
+ i915->base.delete_depth_stencil_alpha_state = i915_delete_depth_stencil_state;
+
+ i915->base.create_rasterizer_state = i915_create_rasterizer_state;
+ i915->base.bind_rasterizer_state = i915_bind_rasterizer_state;
+ i915->base.delete_rasterizer_state = i915_delete_rasterizer_state;
+ i915->base.create_fs_state = i915_create_fs_state;
+ i915->base.bind_fs_state = i915_bind_fs_state;
+ i915->base.delete_fs_state = i915_delete_fs_state;
+ i915->base.create_vs_state = i915_create_vs_state;
+ i915->base.bind_vs_state = i915_bind_vs_state;
+ i915->base.delete_vs_state = i915_delete_vs_state;
+
+ i915->base.set_blend_color = i915_set_blend_color;
+ i915->base.set_clip_state = i915_set_clip_state;
+ i915->base.set_constant_buffer = i915_set_constant_buffer;
+ i915->base.set_framebuffer_state = i915_set_framebuffer_state;
+
+ i915->base.set_polygon_stipple = i915_set_polygon_stipple;
+ i915->base.set_scissor_state = i915_set_scissor_state;
+ i915->base.set_sampler_textures = i915_set_sampler_textures;
+ i915->base.set_viewport_state = i915_set_viewport_state;
+ i915->base.set_vertex_buffers = i915_set_vertex_buffers;
+ i915->base.set_vertex_elements = i915_set_vertex_elements;
+}
diff --git a/src/gallium/drivers/i915simple/i915_state.h b/src/gallium/drivers/i915simple/i915_state.h
new file mode 100644
index 0000000000..86c6b0027d
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_state.h
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef I915_STATE_H
+#define I915_STATE_H
+
+struct i915_context;
+
+
+struct i915_tracked_state {
+ unsigned dirty;
+ void (*update)( struct i915_context * );
+};
+
+void i915_update_immediate( struct i915_context *i915 );
+void i915_update_dynamic( struct i915_context *i915 );
+void i915_update_derived( struct i915_context *i915 );
+void i915_update_samplers( struct i915_context *i915 );
+void i915_update_textures(struct i915_context *i915);
+
+void i915_emit_hardware_state( struct i915_context *i915 );
+
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_state_derived.c b/src/gallium/drivers/i915simple/i915_state_derived.c
new file mode 100644
index 0000000000..178d4e8781
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_state_derived.c
@@ -0,0 +1,183 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "draw/draw_vertex.h"
+#include "i915_context.h"
+#include "i915_state.h"
+#include "i915_reg.h"
+#include "i915_fpc.h"
+
+
+
+/**
+ * Determine the hardware vertex layout.
+ * Depends on vertex/fragment shader state.
+ */
+static void calculate_vertex_layout( struct i915_context *i915 )
+{
+ const struct i915_fragment_shader *fs = i915->fs;
+ const enum interp_mode colorInterp = i915->rasterizer->color_interp;
+ struct vertex_info vinfo;
+ boolean texCoords[8], colors[2], fog, needW;
+ uint i;
+ int src;
+
+ memset(texCoords, 0, sizeof(texCoords));
+ colors[0] = colors[1] = fog = needW = FALSE;
+ memset(&vinfo, 0, sizeof(vinfo));
+
+ /* Determine which fragment program inputs are needed. Setup HW vertex
+ * layout below, in the HW-specific attribute order.
+ */
+ for (i = 0; i < fs->info.num_inputs; i++) {
+ switch (fs->info.input_semantic_name[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ assert(fs->info.input_semantic_index[i] < 2);
+ colors[fs->info.input_semantic_index[i]] = TRUE;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ /* usually a texcoord */
+ {
+ const uint unit = fs->info.input_semantic_index[i];
+ assert(unit < 8);
+ texCoords[unit] = TRUE;
+ needW = TRUE;
+ }
+ break;
+ case TGSI_SEMANTIC_FOG:
+ fog = TRUE;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+
+ /* pos */
+ src = draw_find_vs_output(i915->draw, TGSI_SEMANTIC_POSITION, 0);
+ if (needW) {
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src);
+ vinfo.hwfmt[0] |= S4_VFMT_XYZW;
+ vinfo.attrib[0].emit = EMIT_4F;
+ }
+ else {
+ draw_emit_vertex_attr(&vinfo, EMIT_3F, INTERP_LINEAR, src);
+ vinfo.hwfmt[0] |= S4_VFMT_XYZ;
+ vinfo.attrib[0].emit = EMIT_3F;
+ }
+
+ /* hardware point size */
+ /* XXX todo */
+
+ /* primary color */
+ if (colors[0]) {
+ src = draw_find_vs_output(i915->draw, TGSI_SEMANTIC_COLOR, 0);
+ draw_emit_vertex_attr(&vinfo, EMIT_4UB, colorInterp, src);
+ vinfo.hwfmt[0] |= S4_VFMT_COLOR;
+ }
+
+ /* secondary color */
+ if (colors[1]) {
+ src = draw_find_vs_output(i915->draw, TGSI_SEMANTIC_COLOR, 1);
+ draw_emit_vertex_attr(&vinfo, EMIT_4UB, colorInterp, src);
+ vinfo.hwfmt[0] |= S4_VFMT_SPEC_FOG;
+ }
+
+ /* fog coord, not fog blend factor */
+ if (fog) {
+ src = draw_find_vs_output(i915->draw, TGSI_SEMANTIC_FOG, 0);
+ draw_emit_vertex_attr(&vinfo, EMIT_1F, INTERP_PERSPECTIVE, src);
+ vinfo.hwfmt[0] |= S4_VFMT_FOG_PARAM;
+ }
+
+ /* texcoords */
+ for (i = 0; i < 8; i++) {
+ uint hwtc;
+ if (texCoords[i]) {
+ hwtc = TEXCOORDFMT_4D;
+ src = draw_find_vs_output(i915->draw, TGSI_SEMANTIC_GENERIC, i);
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ }
+ else {
+ hwtc = TEXCOORDFMT_NOT_PRESENT;
+ }
+ vinfo.hwfmt[1] |= hwtc << (i * 4);
+ }
+
+ draw_compute_vertex_size(&vinfo);
+
+ if (memcmp(&i915->current.vertex_info, &vinfo, sizeof(vinfo))) {
+ /* Need to set this flag so that the LIS2/4 registers get set.
+ * It also means the i915_update_immediate() function must be called
+ * after this one, in i915_update_derived().
+ */
+ i915->dirty |= I915_NEW_VERTEX_FORMAT;
+
+ memcpy(&i915->current.vertex_info, &vinfo, sizeof(vinfo));
+ }
+}
+
+
+
+
+/* Hopefully this will remain quite simple, otherwise need to pull in
+ * something like the state tracker mechanism.
+ */
+void i915_update_derived( struct i915_context *i915 )
+{
+ if (i915->dirty & (I915_NEW_RASTERIZER | I915_NEW_FS | I915_NEW_VS))
+ calculate_vertex_layout( i915 );
+
+ if (i915->dirty & (I915_NEW_SAMPLER | I915_NEW_TEXTURE))
+ i915_update_samplers(i915);
+
+ if (i915->dirty & I915_NEW_TEXTURE)
+ i915_update_textures(i915);
+
+ if (i915->dirty)
+ i915_update_immediate( i915 );
+
+ if (i915->dirty)
+ i915_update_dynamic( i915 );
+
+ if (i915->dirty & I915_NEW_FS) {
+ i915->hardware_dirty |= I915_HW_PROGRAM; /* XXX right? */
+ }
+
+ /* HW emit currently references framebuffer state directly:
+ */
+ if (i915->dirty & I915_NEW_FRAMEBUFFER)
+ i915->hardware_dirty |= I915_HW_STATIC;
+
+ i915->dirty = 0;
+}
diff --git a/src/gallium/drivers/i915simple/i915_state_dynamic.c b/src/gallium/drivers/i915simple/i915_state_dynamic.c
new file mode 100644
index 0000000000..86126a5a15
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_state_dynamic.c
@@ -0,0 +1,310 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "i915_batch.h"
+#include "i915_state_inlines.h"
+#include "i915_context.h"
+#include "i915_reg.h"
+#include "i915_state.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_pack_color.h"
+
+#define FILE_DEBUG_FLAG DEBUG_STATE
+
+/* State that we have chosen to store in the DYNAMIC segment of the
+ * i915 indirect state mechanism.
+ *
+ * Can't cache these in the way we do the static state, as there is no
+ * start/size in the command packet, instead an 'end' value that gets
+ * incremented.
+ *
+ * Additionally, there seems to be a requirement to re-issue the full
+ * (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 )
+{
+ unsigned i;
+
+ for (i = 0; i < dwords; i++)
+ i915->current.dynamic[offset + i] = src[i];
+
+ i915->hardware_dirty |= I915_HW_DYNAMIC;
+}
+
+
+/***********************************************************************
+ * Modes4: stencil masks and logicop
+ */
+static void upload_MODES4( struct i915_context *i915 )
+{
+ unsigned modes4 = 0;
+
+ /* I915_NEW_STENCIL */
+ modes4 |= i915->depth_stencil->stencil_modes4;
+ /* I915_NEW_BLEND */
+ modes4 |= i915->blend->modes4;
+
+ /* Always, so that we know when state is in-active:
+ */
+ set_dynamic_indirect( i915,
+ I915_DYNAMIC_MODES4,
+ &modes4,
+ 1 );
+}
+
+const struct i915_tracked_state i915_upload_MODES4 = {
+ I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL,
+ upload_MODES4
+};
+
+
+
+
+/***********************************************************************
+ */
+
+static void upload_BFO( struct i915_context *i915 )
+{
+ set_dynamic_indirect( i915,
+ I915_DYNAMIC_BFO_0,
+ &(i915->depth_stencil->bfo[0]),
+ 2 );
+}
+
+const struct i915_tracked_state i915_upload_BFO = {
+ I915_NEW_DEPTH_STENCIL,
+ upload_BFO
+};
+
+
+/***********************************************************************
+ */
+
+
+static void upload_BLENDCOLOR( struct i915_context *i915 )
+{
+ unsigned bc[2];
+
+ memset( bc, 0, sizeof(bc) );
+
+ /* I915_NEW_BLEND {_COLOR}
+ */
+ {
+ const float *color = i915->blend_color.color;
+
+ bc[0] = _3DSTATE_CONST_BLEND_COLOR_CMD;
+ bc[1] = pack_ui32_float4( color[0],
+ color[1],
+ color[2],
+ color[3] );
+ }
+
+ set_dynamic_indirect( i915,
+ I915_DYNAMIC_BC_0,
+ bc,
+ 2 );
+}
+
+const struct i915_tracked_state i915_upload_BLENDCOLOR = {
+ I915_NEW_BLEND,
+ upload_BLENDCOLOR
+};
+
+/***********************************************************************
+ */
+
+
+static void upload_IAB( struct i915_context *i915 )
+{
+ unsigned iab = i915->blend->iab;
+
+
+ set_dynamic_indirect( i915,
+ I915_DYNAMIC_IAB,
+ &iab,
+ 1 );
+}
+
+const struct i915_tracked_state i915_upload_IAB = {
+ I915_NEW_BLEND,
+ upload_IAB
+};
+
+
+/***********************************************************************
+ */
+
+
+
+static void upload_DEPTHSCALE( struct i915_context *i915 )
+{
+ set_dynamic_indirect( i915,
+ I915_DYNAMIC_DEPTHSCALE_0,
+ &(i915->rasterizer->ds[0].u),
+ 2 );
+}
+
+const struct i915_tracked_state i915_upload_DEPTHSCALE = {
+ I915_NEW_RASTERIZER,
+ upload_DEPTHSCALE
+};
+
+
+
+/***********************************************************************
+ * Polygon stipple
+ *
+ * The i915 supports a 4x4 stipple natively, GL wants 32x32.
+ * Fortunately stipple is usually a repeating pattern.
+ *
+ * XXX: does stipple pattern need to be adjusted according to
+ * the window position?
+ *
+ * XXX: possibly need workaround for conform paths test.
+ */
+
+static void upload_STIPPLE( struct i915_context *i915 )
+{
+ unsigned st[2];
+
+ st[0] = _3DSTATE_STIPPLE;
+ st[1] = 0;
+
+ /* I915_NEW_RASTERIZER
+ */
+ st[1] |= i915->rasterizer->st;
+
+
+ /* I915_NEW_STIPPLE
+ */
+ {
+ const ubyte *mask = (const ubyte *)i915->poly_stipple.stipple;
+ ubyte p[4];
+
+ p[0] = mask[12] & 0xf;
+ p[1] = mask[8] & 0xf;
+ p[2] = mask[4] & 0xf;
+ p[3] = mask[0] & 0xf;
+
+ /* Not sure what to do about fallbacks, so for now just dont:
+ */
+ st[1] |= ((p[0] << 0) |
+ (p[1] << 4) |
+ (p[2] << 8) |
+ (p[3] << 12));
+ }
+
+
+ set_dynamic_indirect( i915,
+ I915_DYNAMIC_STP_0,
+ &st[0],
+ 2 );
+}
+
+
+const struct i915_tracked_state i915_upload_STIPPLE = {
+ I915_NEW_RASTERIZER | I915_NEW_STIPPLE,
+ upload_STIPPLE
+};
+
+
+
+/***********************************************************************
+ * Scissor.
+ */
+static void upload_SCISSOR_ENABLE( struct i915_context *i915 )
+{
+ set_dynamic_indirect( i915,
+ I915_DYNAMIC_SC_ENA_0,
+ &(i915->rasterizer->sc[0]),
+ 1 );
+}
+
+const struct i915_tracked_state i915_upload_SCISSOR_ENABLE = {
+ I915_NEW_RASTERIZER,
+ upload_SCISSOR_ENABLE
+};
+
+
+
+static void upload_SCISSOR_RECT( struct i915_context *i915 )
+{
+ unsigned x1 = i915->scissor.minx;
+ unsigned y1 = i915->scissor.miny;
+ unsigned x2 = i915->scissor.maxx;
+ unsigned y2 = i915->scissor.maxy;
+ unsigned sc[3];
+
+ sc[0] = _3DSTATE_SCISSOR_RECT_0_CMD;
+ sc[1] = (y1 << 16) | (x1 & 0xffff);
+ sc[2] = (y2 << 16) | (x2 & 0xffff);
+
+ set_dynamic_indirect( i915,
+ I915_DYNAMIC_SC_RECT_0,
+ &sc[0],
+ 3 );
+}
+
+
+const struct i915_tracked_state i915_upload_SCISSOR_RECT = {
+ I915_NEW_SCISSOR,
+ upload_SCISSOR_RECT
+};
+
+
+
+
+
+
+static const struct i915_tracked_state *atoms[] = {
+ &i915_upload_MODES4,
+ &i915_upload_BFO,
+ &i915_upload_BLENDCOLOR,
+ &i915_upload_IAB,
+ &i915_upload_DEPTHSCALE,
+ &i915_upload_STIPPLE,
+ &i915_upload_SCISSOR_ENABLE,
+ &i915_upload_SCISSOR_RECT
+};
+
+/* These will be dynamic indirect state commands, but for now just end
+ * up on the batch buffer with everything else.
+ */
+void i915_update_dynamic( struct i915_context *i915 )
+{
+ int i;
+
+ for (i = 0; i < Elements(atoms); i++)
+ if (i915->dirty & atoms[i]->dirty)
+ atoms[i]->update( i915 );
+}
+
diff --git a/src/gallium/drivers/i915simple/i915_state_emit.c b/src/gallium/drivers/i915simple/i915_state_emit.c
new file mode 100644
index 0000000000..a3d4e3b04e
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_state_emit.c
@@ -0,0 +1,402 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "i915_reg.h"
+#include "i915_context.h"
+#include "i915_batch.h"
+#include "i915_reg.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+static unsigned translate_format( enum pipe_format format )
+{
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return COLOR_BUF_ARGB8888;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return COLOR_BUF_RGB565;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static unsigned translate_depth_format( enum pipe_format zformat )
+{
+ switch (zformat) {
+ case PIPE_FORMAT_S8Z24_UNORM:
+ return DEPTH_FRMT_24_FIXED_8_OTHER;
+ case PIPE_FORMAT_Z16_UNORM:
+ return DEPTH_FRMT_16_FIXED;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+/**
+ * Examine framebuffer state to determine width, height.
+ */
+static boolean
+framebuffer_size(const struct pipe_framebuffer_state *fb,
+ uint *width, uint *height)
+{
+ if (fb->cbufs[0]) {
+ *width = fb->cbufs[0]->width;
+ *height = fb->cbufs[0]->height;
+ return TRUE;
+ }
+ else if (fb->zsbuf) {
+ *width = fb->zsbuf->width;
+ *height = fb->zsbuf->height;
+ return TRUE;
+ }
+ else {
+ *width = *height = 0;
+ return FALSE;
+ }
+}
+
+
+/* Push the state into the sarea and/or texture memory.
+ */
+void
+i915_emit_hardware_state(struct i915_context *i915 )
+{
+ /* XXX: there must be an easier way */
+ const unsigned dwords = ( 14 +
+ 7 +
+ I915_MAX_DYNAMIC +
+ 8 +
+ 2 + I915_TEX_UNITS*3 +
+ 2 + I915_TEX_UNITS*3 +
+ 2 + I915_MAX_CONSTANT*4 +
+#if 0
+ i915->current.program_len +
+#else
+ i915->fs->program_len +
+#endif
+ 6
+ ) * 3/2; /* plus 50% margin */
+ const unsigned relocs = ( I915_TEX_UNITS +
+ 3
+ ) * 3/2; /* plus 50% margin */
+
+#if 0
+ debug_printf("i915_emit_hardware_state: %d dwords, %d relocs\n", dwords, relocs);
+#endif
+
+ if(!BEGIN_BATCH(dwords, relocs)) {
+ FLUSH_BATCH(NULL);
+ assert(BEGIN_BATCH(dwords, relocs));
+ }
+
+ /* 14 dwords, 0 relocs */
+ if (i915->hardware_dirty & I915_HW_INVARIENT)
+ {
+ OUT_BATCH(_3DSTATE_AA_CMD |
+ AA_LINE_ECAAR_WIDTH_ENABLE |
+ AA_LINE_ECAAR_WIDTH_1_0 |
+ AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
+
+ OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
+ OUT_BATCH(0);
+
+ OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
+ OUT_BATCH(0);
+
+ OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
+ OUT_BATCH(0);
+
+ OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS |
+ CSB_TCB(0, 0) |
+ CSB_TCB(1, 1) |
+ CSB_TCB(2, 2) |
+ CSB_TCB(3, 3) |
+ CSB_TCB(4, 4) |
+ CSB_TCB(5, 5) |
+ CSB_TCB(6, 6) |
+ CSB_TCB(7, 7));
+
+ OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) |
+ 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
+ */
+ OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0);
+ OUT_BATCH(0);
+ }
+
+ /* 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,
+ INTEL_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]);
+ }
+
+ /* I915_MAX_DYNAMIC dwords, 0 relocs */
+ if (i915->hardware_dirty & I915_HW_DYNAMIC)
+ {
+ int i;
+ for (i = 0; i < I915_MAX_DYNAMIC; i++) {
+ OUT_BATCH(i915->current.dynamic[i]);
+ }
+ }
+
+ /* 8 dwords, 2 relocs */
+ if (i915->hardware_dirty & I915_HW_STATIC)
+ {
+ struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
+ struct pipe_surface *depth_surface = i915->framebuffer.zsbuf;
+
+ if (cbuf_surface) {
+ unsigned ctile = BUF_3D_USE_FENCE;
+ struct i915_texture *tex = (struct i915_texture *)
+ cbuf_surface->texture;
+ assert(tex);
+
+ if (tex && tex->sw_tiled) {
+ ctile = BUF_3D_TILED_SURFACE;
+ }
+
+ OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
+
+ OUT_BATCH(BUF_3D_ID_COLOR_BACK |
+ BUF_3D_PITCH(tex->stride) | /* pitch in bytes */
+ ctile);
+
+ OUT_RELOC(tex->buffer,
+ INTEL_USAGE_RENDER,
+ cbuf_surface->offset);
+ }
+
+ /* What happens if no zbuf??
+ */
+ if (depth_surface) {
+ unsigned ztile = BUF_3D_USE_FENCE;
+ struct i915_texture *tex = (struct i915_texture *)
+ depth_surface->texture;
+ assert(tex);
+
+ if (tex && tex->sw_tiled) {
+ ztile = BUF_3D_TILED_SURFACE;
+ }
+
+ OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
+
+ OUT_BATCH(BUF_3D_ID_DEPTH |
+ BUF_3D_PITCH(tex->stride) | /* pitch in bytes */
+ ztile);
+
+ OUT_RELOC(tex->buffer,
+ INTEL_USAGE_RENDER,
+ depth_surface->offset);
+ }
+
+ {
+ unsigned cformat, zformat = 0;
+
+ if (cbuf_surface)
+ cformat = cbuf_surface->format;
+ else
+ cformat = PIPE_FORMAT_A8R8G8B8_UNORM; /* arbitrary */
+ cformat = translate_format(cformat);
+
+ if (depth_surface)
+ zformat = translate_depth_format( i915->framebuffer.zsbuf->format );
+
+ OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
+ OUT_BATCH(DSTORG_HORT_BIAS(0x8) | /* .5 */
+ DSTORG_VERT_BIAS(0x8) | /* .5 */
+ LOD_PRECLAMP_OGL |
+ TEX_DEFAULT_COLOR_OGL |
+ cformat |
+ zformat );
+ }
+ }
+
+#if 01
+ /* texture images */
+ /* 2 + I915_TEX_UNITS*3 dwords, I915_TEX_UNITS relocs */
+ if (i915->hardware_dirty & (I915_HW_MAP | I915_HW_SAMPLER))
+ {
+ const uint nr = i915->current.sampler_enable_nr;
+ if (nr) {
+ const uint enabled = i915->current.sampler_enable_flags;
+ uint unit;
+ uint count = 0;
+ OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr));
+ OUT_BATCH(enabled);
+ for (unit = 0; unit < I915_TEX_UNITS; unit++) {
+ if (enabled & (1 << unit)) {
+ struct intel_buffer *buf = i915->texture[unit]->buffer;
+ uint offset = 0;
+ assert(buf);
+
+ count++;
+
+ OUT_RELOC(buf, INTEL_USAGE_SAMPLER, offset);
+ OUT_BATCH(i915->current.texbuffer[unit][0]); /* MS3 */
+ OUT_BATCH(i915->current.texbuffer[unit][1]); /* MS4 */
+ }
+ }
+ assert(count == nr);
+ }
+ }
+#endif
+
+#if 01
+ /* samplers */
+ /* 2 + I915_TEX_UNITS*3 dwords, 0 relocs */
+ if (i915->hardware_dirty & I915_HW_SAMPLER)
+ {
+ if (i915->current.sampler_enable_nr) {
+ int i;
+
+ OUT_BATCH( _3DSTATE_SAMPLER_STATE |
+ (3 * i915->current.sampler_enable_nr) );
+
+ OUT_BATCH( i915->current.sampler_enable_flags );
+
+ for (i = 0; i < I915_TEX_UNITS; i++) {
+ if (i915->current.sampler_enable_flags & (1<<i)) {
+ OUT_BATCH( i915->current.sampler[i][0] );
+ OUT_BATCH( i915->current.sampler[i][1] );
+ OUT_BATCH( i915->current.sampler[i][2] );
+ }
+ }
+ }
+ }
+#endif
+
+ /* constants */
+ /* 2 + I915_MAX_CONSTANT*4 dwords, 0 relocs */
+ if (i915->hardware_dirty & I915_HW_PROGRAM)
+ {
+ /* Collate the user-defined constants with the fragment shader's
+ * immediates according to the constant_flags[] array.
+ */
+ const uint nr = i915->fs->num_constants;
+ if (nr) {
+ uint i;
+
+ OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) );
+ OUT_BATCH( (1 << (nr - 1)) | ((1 << (nr - 1)) - 1) );
+
+ for (i = 0; i < nr; i++) {
+ const uint *c;
+ if (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER) {
+ /* grab user-defined constant */
+ c = (uint *) i915->current.constants[PIPE_SHADER_FRAGMENT][i];
+ }
+ else {
+ /* emit program constant */
+ c = (uint *) i915->fs->constants[i];
+ }
+#if 0 /* debug */
+ {
+ float *f = (float *) c;
+ printf("Const %2d: %f %f %f %f %s\n", i, f[0], f[1], f[2], f[3],
+ (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER
+ ? "user" : "immediate"));
+ }
+#endif
+ OUT_BATCH(*c++);
+ OUT_BATCH(*c++);
+ OUT_BATCH(*c++);
+ OUT_BATCH(*c++);
+ }
+ }
+ }
+
+ /* Fragment program */
+ /* i915->current.program_len dwords, 0 relocs */
+ if (i915->hardware_dirty & I915_HW_PROGRAM)
+ {
+ uint i;
+ /* we should always have, at least, a pass-through program */
+ assert(i915->fs->program_len > 0);
+ for (i = 0; i < i915->fs->program_len; i++) {
+ OUT_BATCH(i915->fs->program[i]);
+ }
+ }
+
+ /* drawing surface size */
+ /* 6 dwords, 0 relocs */
+ {
+ uint w, h;
+ boolean k = framebuffer_size(&i915->framebuffer, &w, &h);
+ (void)k;
+ assert(k);
+
+ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(((w - 1) & 0xffff) | ((h - 1) << 16));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ }
+
+
+ i915->hardware_dirty = 0;
+}
diff --git a/src/gallium/drivers/i915simple/i915_state_immediate.c b/src/gallium/drivers/i915simple/i915_state_immediate.c
new file mode 100644
index 0000000000..8c16bb4e27
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_state_immediate.c
@@ -0,0 +1,225 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "i915_state_inlines.h"
+#include "i915_context.h"
+#include "i915_state.h"
+#include "i915_reg.h"
+#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.
+ */
+
+
+
+
+/***********************************************************************
+ * S0,S1: Vertex buffer state.
+ */
+static void upload_S0S1(struct i915_context *i915)
+{
+ unsigned LIS0, LIS1;
+
+ /* INTEL_NEW_VBO */
+ /* TODO: re-use vertex buffers here? */
+ LIS0 = i915->vbo_offset;
+
+ /* INTEL_NEW_VERTEX_SIZE -- do this where the vertex size is calculated!
+ */
+ {
+ unsigned vertex_size = i915->current.vertex_info.size;
+
+ LIS1 = ((vertex_size << 24) |
+ (vertex_size << 16));
+ }
+
+ /* INTEL_NEW_VBO */
+ /* TODO: use a vertex generation number to track vbo changes */
+ 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;
+ }
+}
+
+const struct i915_tracked_state i915_upload_S0S1 = {
+ I915_NEW_VBO | I915_NEW_VERTEX_FORMAT,
+ upload_S0S1
+};
+
+
+
+
+/***********************************************************************
+ * S4: Vertex format, rasterization state
+ */
+static void upload_S2S4(struct i915_context *i915)
+{
+ unsigned LIS2, LIS4;
+
+ /* I915_NEW_VERTEX_FORMAT */
+ {
+ 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;
+ }
+}
+
+
+const struct i915_tracked_state i915_upload_S2S4 = {
+ I915_NEW_RASTERIZER | I915_NEW_VERTEX_FORMAT,
+ upload_S2S4
+};
+
+
+
+/***********************************************************************
+ *
+ */
+static void upload_S5( struct i915_context *i915 )
+{
+ unsigned LIS5 = 0;
+
+ LIS5 |= i915->depth_stencil->stencil_LIS5;
+
+ LIS5 |= i915->blend->LIS5;
+
+#if 0
+ /* I915_NEW_RASTERIZER */
+ if (i915->state.Polygon->OffsetFill) {
+ 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;
+ }
+}
+
+const struct i915_tracked_state i915_upload_S5 = {
+ (I915_NEW_DEPTH_STENCIL | I915_NEW_BLEND | I915_NEW_RASTERIZER),
+ upload_S5
+};
+
+
+/***********************************************************************
+ */
+static void upload_S6( struct i915_context *i915 )
+{
+ unsigned LIS6 = (2 << S6_TRISTRIP_PV_SHIFT);
+
+ /* I915_NEW_FRAMEBUFFER
+ */
+ if (i915->framebuffer.cbufs[0])
+ LIS6 |= S6_COLOR_WRITE_ENABLE;
+
+ /* I915_NEW_BLEND
+ */
+ LIS6 |= i915->blend->LIS6;
+
+ /* I915_NEW_DEPTH
+ */
+ 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;
+ }
+}
+
+const struct i915_tracked_state i915_upload_S6 = {
+ I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER,
+ upload_S6
+};
+
+
+/***********************************************************************
+ */
+static void upload_S7( struct i915_context *i915 )
+{
+ unsigned LIS7;
+
+ /* I915_NEW_RASTERIZER
+ */
+ 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;
+ }
+}
+
+const struct i915_tracked_state i915_upload_S7 = {
+ I915_NEW_RASTERIZER,
+ upload_S7
+};
+
+
+static const struct i915_tracked_state *atoms[] = {
+ &i915_upload_S0S1,
+ &i915_upload_S2S4,
+ &i915_upload_S5,
+ &i915_upload_S6,
+ &i915_upload_S7
+};
+
+/*
+ */
+void i915_update_immediate( struct i915_context *i915 )
+{
+ int i;
+
+ for (i = 0; i < Elements(atoms); i++)
+ if (i915->dirty & atoms[i]->dirty)
+ atoms[i]->update( i915 );
+}
diff --git a/src/gallium/drivers/i915simple/i915_state_inlines.h b/src/gallium/drivers/i915simple/i915_state_inlines.h
new file mode 100644
index 0000000000..378de8f9c4
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_state_inlines.h
@@ -0,0 +1,230 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef I915_STATE_INLINES_H
+#define I915_STATE_INLINES_H
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_defines.h"
+#include "i915_reg.h"
+
+
+static INLINE unsigned
+i915_translate_compare_func(unsigned func)
+{
+ switch (func) {
+ case PIPE_FUNC_NEVER:
+ return COMPAREFUNC_NEVER;
+ case PIPE_FUNC_LESS:
+ return COMPAREFUNC_LESS;
+ case PIPE_FUNC_LEQUAL:
+ return COMPAREFUNC_LEQUAL;
+ case PIPE_FUNC_GREATER:
+ return COMPAREFUNC_GREATER;
+ case PIPE_FUNC_GEQUAL:
+ return COMPAREFUNC_GEQUAL;
+ case PIPE_FUNC_NOTEQUAL:
+ return COMPAREFUNC_NOTEQUAL;
+ case PIPE_FUNC_EQUAL:
+ return COMPAREFUNC_EQUAL;
+ case PIPE_FUNC_ALWAYS:
+ return COMPAREFUNC_ALWAYS;
+ default:
+ return COMPAREFUNC_ALWAYS;
+ }
+}
+
+static INLINE unsigned
+i915_translate_stencil_op(unsigned op)
+{
+ switch (op) {
+ case PIPE_STENCIL_OP_KEEP:
+ return STENCILOP_KEEP;
+ case PIPE_STENCIL_OP_ZERO:
+ return STENCILOP_ZERO;
+ case PIPE_STENCIL_OP_REPLACE:
+ return STENCILOP_REPLACE;
+ case PIPE_STENCIL_OP_INCR:
+ return STENCILOP_INCRSAT;
+ case PIPE_STENCIL_OP_DECR:
+ return STENCILOP_DECRSAT;
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ return STENCILOP_INCR;
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ return STENCILOP_DECR;
+ case PIPE_STENCIL_OP_INVERT:
+ return STENCILOP_INVERT;
+ default:
+ return STENCILOP_ZERO;
+ }
+}
+
+static INLINE unsigned
+i915_translate_blend_factor(unsigned factor)
+{
+ switch (factor) {
+ case PIPE_BLENDFACTOR_ZERO:
+ return BLENDFACT_ZERO;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ return BLENDFACT_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_ONE:
+ return BLENDFACT_ONE;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ return BLENDFACT_SRC_COLR;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ return BLENDFACT_INV_SRC_COLR;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ return BLENDFACT_DST_COLR;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ return BLENDFACT_INV_DST_COLR;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ return BLENDFACT_INV_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ return BLENDFACT_DST_ALPHA;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ return BLENDFACT_INV_DST_ALPHA;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ return BLENDFACT_SRC_ALPHA_SATURATE;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ return BLENDFACT_CONST_COLOR;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ return BLENDFACT_INV_CONST_COLOR;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ return BLENDFACT_CONST_ALPHA;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ return BLENDFACT_INV_CONST_ALPHA;
+ default:
+ return BLENDFACT_ZERO;
+ }
+}
+
+static INLINE unsigned
+i915_translate_blend_func(unsigned mode)
+{
+ switch (mode) {
+ case PIPE_BLEND_ADD:
+ return BLENDFUNC_ADD;
+ case PIPE_BLEND_MIN:
+ return BLENDFUNC_MIN;
+ case PIPE_BLEND_MAX:
+ return BLENDFUNC_MAX;
+ case PIPE_BLEND_SUBTRACT:
+ return BLENDFUNC_SUBTRACT;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ return BLENDFUNC_REVERSE_SUBTRACT;
+ default:
+ return 0;
+ }
+}
+
+
+static INLINE unsigned
+i915_translate_logic_op(unsigned opcode)
+{
+ switch (opcode) {
+ case PIPE_LOGICOP_CLEAR:
+ return LOGICOP_CLEAR;
+ case PIPE_LOGICOP_AND:
+ return LOGICOP_AND;
+ case PIPE_LOGICOP_AND_REVERSE:
+ return LOGICOP_AND_RVRSE;
+ case PIPE_LOGICOP_COPY:
+ return LOGICOP_COPY;
+ case PIPE_LOGICOP_COPY_INVERTED:
+ return LOGICOP_COPY_INV;
+ case PIPE_LOGICOP_AND_INVERTED:
+ return LOGICOP_AND_INV;
+ case PIPE_LOGICOP_NOOP:
+ return LOGICOP_NOOP;
+ case PIPE_LOGICOP_XOR:
+ return LOGICOP_XOR;
+ case PIPE_LOGICOP_OR:
+ return LOGICOP_OR;
+ case PIPE_LOGICOP_OR_INVERTED:
+ return LOGICOP_OR_INV;
+ case PIPE_LOGICOP_NOR:
+ return LOGICOP_NOR;
+ case PIPE_LOGICOP_EQUIV:
+ return LOGICOP_EQUIV;
+ case PIPE_LOGICOP_INVERT:
+ return LOGICOP_INV;
+ case PIPE_LOGICOP_OR_REVERSE:
+ return LOGICOP_OR_RVRSE;
+ case PIPE_LOGICOP_NAND:
+ return LOGICOP_NAND;
+ case PIPE_LOGICOP_SET:
+ return LOGICOP_SET;
+ default:
+ return LOGICOP_SET;
+ }
+}
+
+
+
+static INLINE boolean i915_validate_vertices( unsigned hw_prim, unsigned nr )
+{
+ boolean ok;
+
+ switch (hw_prim) {
+ case PRIM3D_POINTLIST:
+ ok = (nr >= 1);
+ assert(ok);
+ break;
+ case PRIM3D_LINELIST:
+ ok = (nr >= 2) && (nr % 2) == 0;
+ assert(ok);
+ break;
+ case PRIM3D_LINESTRIP:
+ ok = (nr >= 2);
+ assert(ok);
+ break;
+ case PRIM3D_TRILIST:
+ ok = (nr >= 3) && (nr % 3) == 0;
+ assert(ok);
+ break;
+ case PRIM3D_TRISTRIP:
+ ok = (nr >= 3);
+ assert(ok);
+ break;
+ case PRIM3D_TRIFAN:
+ ok = (nr >= 3);
+ assert(ok);
+ break;
+ case PRIM3D_POLY:
+ ok = (nr >= 3);
+ assert(ok);
+ break;
+ default:
+ assert(0);
+ ok = 0;
+ break;
+ }
+
+ return ok;
+}
+
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_state_sampler.c b/src/gallium/drivers/i915simple/i915_state_sampler.c
new file mode 100644
index 0000000000..c5e9084d12
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_state_sampler.c
@@ -0,0 +1,299 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "util/u_memory.h"
+
+#include "i915_state_inlines.h"
+#include "i915_context.h"
+#include "i915_reg.h"
+#include "i915_state.h"
+
+
+/*
+ * A note about min_lod & max_lod.
+ *
+ * There is a circular dependancy between the sampler state
+ * and the map state to be submitted to hw.
+ *
+ * Two condition must be meet:
+ * min_lod =< max_lod == true
+ * max_lod =< last_level == true
+ *
+ *
+ * This is all fine and dandy if it where for the fact that max_lod
+ * is set on the map state instead of the sampler state. That is
+ * the max_lod we submit on map is:
+ * max_lod = MIN2(last_level, max_lod);
+ *
+ * So we need to update the map state when we change samplers and
+ * we need to be change the sampler state when map state is changed.
+ * The first part is done by calling i915_update_texture in
+ * i915_update_samplers and the second part is done else where in
+ * code tracking the state changes.
+ */
+
+static void
+i915_update_texture(struct i915_context *i915,
+ uint unit,
+ const struct i915_texture *tex,
+ const struct i915_sampler_state *sampler,
+ uint state[6]);
+/**
+ * Compute i915 texture sampling state.
+ *
+ * Recalculate all state from scratch. Perhaps not the most
+ * efficient, but this has gotten complex enough that we need
+ * something which is understandable and reliable.
+ * \param state returns the 3 words of compute state
+ */
+static void update_sampler(struct i915_context *i915,
+ uint unit,
+ const struct i915_sampler_state *sampler,
+ const struct i915_texture *tex,
+ unsigned state[3] )
+{
+ const struct pipe_texture *pt = &tex->base;
+ unsigned minlod, lastlod;
+
+ /* Need to do this after updating the maps, which call the
+ * intel_finalize_mipmap_tree and hence can update firstLevel:
+ */
+ state[0] = sampler->state[0];
+ state[1] = sampler->state[1];
+ state[2] = sampler->state[2];
+
+ if (pt->format == PIPE_FORMAT_YCBCR ||
+ pt->format == PIPE_FORMAT_YCBCR_REV)
+ state[0] |= SS2_COLORSPACE_CONVERSION;
+
+ /* 3D textures don't seem to respect the border color.
+ * Fallback if there's ever a danger that they might refer to
+ * it.
+ *
+ * Effectively this means fallback on 3D clamp or
+ * clamp_to_border.
+ *
+ * XXX: Check if this is true on i945.
+ * XXX: Check if this bug got fixed in release silicon.
+ */
+#if 0
+ {
+ const unsigned ws = sampler->templ->wrap_s;
+ const unsigned wt = sampler->templ->wrap_t;
+ const unsigned wr = sampler->templ->wrap_r;
+ if (pt->target == PIPE_TEXTURE_3D &&
+ (sampler->templ->min_img_filter != PIPE_TEX_FILTER_NEAREST ||
+ sampler->templ->mag_img_filter != PIPE_TEX_FILTER_NEAREST) &&
+ (ws == PIPE_TEX_WRAP_CLAMP ||
+ wt == PIPE_TEX_WRAP_CLAMP ||
+ wr == PIPE_TEX_WRAP_CLAMP ||
+ ws == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||
+ wt == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||
+ wr == PIPE_TEX_WRAP_CLAMP_TO_BORDER)) {
+ if (i915->conformance_mode > 0) {
+ assert(0);
+ /* sampler->fallback = true; */
+ /* TODO */
+ }
+ }
+ }
+#endif
+
+ /* See note at the top of file */
+ minlod = sampler->minlod;
+ lastlod = pt->last_level << 4;
+
+ if (lastlod < minlod) {
+ minlod = lastlod;
+ }
+
+ state[1] |= (sampler->minlod << SS3_MIN_LOD_SHIFT);
+ state[1] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
+}
+
+
+void i915_update_samplers( struct i915_context *i915 )
+{
+ uint unit;
+
+ i915->current.sampler_enable_nr = 0;
+ i915->current.sampler_enable_flags = 0x0;
+
+ for (unit = 0; unit < i915->num_textures && unit < i915->num_samplers;
+ unit++) {
+ /* determine unit enable/disable by looking for a bound texture */
+ /* could also examine the fragment program? */
+ if (i915->texture[unit]) {
+ update_sampler( i915,
+ unit,
+ i915->sampler[unit], /* sampler state */
+ i915->texture[unit], /* texture */
+ i915->current.sampler[unit] /* the result */
+ );
+ i915_update_texture( i915,
+ unit,
+ i915->texture[unit], /* texture */
+ i915->sampler[unit], /* sampler state */
+ i915->current.texbuffer[unit] );
+
+ i915->current.sampler_enable_nr++;
+ i915->current.sampler_enable_flags |= (1 << unit);
+ }
+ }
+
+ i915->hardware_dirty |= I915_HW_SAMPLER | I915_HW_MAP;
+}
+
+
+static uint
+translate_texture_format(enum pipe_format pipeFormat)
+{
+ switch (pipeFormat) {
+ case PIPE_FORMAT_L8_UNORM:
+ return MAPSURF_8BIT | MT_8BIT_L8;
+ case PIPE_FORMAT_I8_UNORM:
+ return MAPSURF_8BIT | MT_8BIT_I8;
+ case PIPE_FORMAT_A8_UNORM:
+ return MAPSURF_8BIT | MT_8BIT_A8;
+ case PIPE_FORMAT_A8L8_UNORM:
+ return MAPSURF_16BIT | MT_16BIT_AY88;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return MAPSURF_16BIT | MT_16BIT_RGB565;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ return MAPSURF_16BIT | MT_16BIT_ARGB1555;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ return MAPSURF_16BIT | MT_16BIT_ARGB4444;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return MAPSURF_32BIT | MT_32BIT_ARGB8888;
+ case PIPE_FORMAT_YCBCR_REV:
+ return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
+ case PIPE_FORMAT_YCBCR:
+ return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
+#if 0
+ case PIPE_FORMAT_RGB_FXT1:
+ case PIPE_FORMAT_RGBA_FXT1:
+ return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
+#endif
+ case PIPE_FORMAT_Z16_UNORM:
+ return (MAPSURF_16BIT | MT_16BIT_L16);
+#if 0
+ case PIPE_FORMAT_RGBA_DXT1:
+ case PIPE_FORMAT_RGB_DXT1:
+ return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
+ case PIPE_FORMAT_RGBA_DXT3:
+ return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
+ case PIPE_FORMAT_RGBA_DXT5:
+ return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
+#endif
+ case PIPE_FORMAT_S8Z24_UNORM:
+ return (MAPSURF_32BIT | MT_32BIT_xI824);
+ default:
+ debug_printf("i915: translate_texture_format() bad image format %x\n",
+ pipeFormat);
+ assert(0);
+ return 0;
+ }
+}
+
+
+static void
+i915_update_texture(struct i915_context *i915,
+ uint unit,
+ const struct i915_texture *tex,
+ const struct i915_sampler_state *sampler,
+ uint state[6])
+{
+ const struct pipe_texture *pt = &tex->base;
+ uint format, pitch;
+ const uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
+ const uint num_levels = pt->last_level;
+ unsigned max_lod = num_levels * 4;
+ unsigned tiled = MS3_USE_FENCE_REGS;
+
+ assert(tex);
+ assert(width);
+ assert(height);
+ assert(depth);
+
+ format = translate_texture_format(pt->format);
+ pitch = tex->stride;
+
+ assert(format);
+ assert(pitch);
+
+ if (tex->sw_tiled) {
+ assert(!((pitch - 1) & pitch));
+ tiled = MS3_TILED_SURFACE;
+ }
+
+ /* MS3 state */
+ state[0] =
+ (((height - 1) << MS3_HEIGHT_SHIFT)
+ | ((width - 1) << MS3_WIDTH_SHIFT)
+ | format
+ | tiled);
+
+ /*
+ * XXX When min_filter != mag_filter and there's just one mipmap level,
+ * set max_lod = 1 to make sure i915 chooses between min/mag filtering.
+ */
+
+ /* See note at the top of file */
+ if (max_lod > (sampler->maxlod >> 2))
+ max_lod = sampler->maxlod >> 2;
+
+ /* MS4 state */
+ state[1] =
+ ((((pitch / 4) - 1) << MS4_PITCH_SHIFT)
+ | MS4_CUBE_FACE_ENA_MASK
+ | ((max_lod) << MS4_MAX_LOD_SHIFT)
+ | ((depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
+}
+
+
+void
+i915_update_textures(struct i915_context *i915)
+{
+ uint unit;
+
+ for (unit = 0; unit < i915->num_textures && unit < i915->num_samplers;
+ unit++) {
+ /* determine unit enable/disable by looking for a bound texture */
+ /* could also examine the fragment program? */
+ if (i915->texture[unit]) {
+ i915_update_texture( i915,
+ unit,
+ i915->texture[unit], /* texture */
+ i915->sampler[unit], /* sampler state */
+ i915->current.texbuffer[unit] );
+ }
+ }
+
+ i915->hardware_dirty |= I915_HW_MAP;
+}
diff --git a/src/gallium/drivers/i915simple/i915_surface.c b/src/gallium/drivers/i915simple/i915_surface.c
new file mode 100644
index 0000000000..ab8331f3e6
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_surface.c
@@ -0,0 +1,94 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "i915_context.h"
+#include "i915_blit.h"
+#include "i915_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_tile.h"
+#include "util/u_rect.h"
+
+
+/* Assumes all values are within bounds -- no checking at this level -
+ * do it higher up if required.
+ */
+static void
+i915_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ struct pipe_surface *src,
+ unsigned srcx, unsigned srcy, unsigned width, unsigned height)
+{
+ struct i915_texture *dst_tex = (struct i915_texture *)dst->texture;
+ struct i915_texture *src_tex = (struct i915_texture *)src->texture;
+
+ assert( dst != src );
+ assert( dst_tex->base.block.size == src_tex->base.block.size );
+ assert( dst_tex->base.block.width == src_tex->base.block.height );
+ assert( dst_tex->base.block.height == src_tex->base.block.height );
+ assert( dst_tex->base.block.width == 1 );
+ assert( dst_tex->base.block.height == 1 );
+
+ i915_copy_blit( i915_context(pipe),
+ FALSE,
+ dst_tex->base.block.size,
+ (unsigned short) src_tex->stride, src_tex->buffer, src->offset,
+ (unsigned short) dst_tex->stride, dst_tex->buffer, dst->offset,
+ (short) srcx, (short) srcy, (short) dstx, (short) dsty, (short) width, (short) height );
+}
+
+
+static void
+i915_surface_fill(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height, unsigned value)
+{
+ struct i915_texture *tex = (struct i915_texture *)dst->texture;
+
+ assert(tex->base.block.width == 1);
+ assert(tex->base.block.height == 1);
+
+ i915_fill_blit( i915_context(pipe),
+ tex->base.block.size,
+ (unsigned short) tex->stride,
+ tex->buffer, dst->offset,
+ (short) dstx, (short) dsty,
+ (short) width, (short) height,
+ value );
+}
+
+
+void
+i915_init_surface_functions(struct i915_context *i915)
+{
+ i915->base.surface_copy = i915_surface_copy;
+ i915->base.surface_fill = i915_surface_fill;
+}
diff --git a/src/gallium/drivers/i915simple/i915_texture.c b/src/gallium/drivers/i915simple/i915_texture.c
new file mode 100644
index 0000000000..6a6c654271
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_texture.c
@@ -0,0 +1,911 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Michel Dänzer <michel@tungstengraphics.com>
+ */
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "i915_context.h"
+#include "i915_texture.h"
+#include "i915_debug.h"
+#include "i915_screen.h"
+#include "intel_winsys.h"
+
+
+/*
+ * Helper function and arrays
+ */
+
+
+/**
+ * Initial offset for Cube map.
+ */
+static const int initial_offsets[6][2] = {
+ {0, 0},
+ {0, 2},
+ {1, 0},
+ {1, 2},
+ {1, 1},
+ {1, 3}
+};
+
+/**
+ * Step offsets for Cube map.
+ */
+static const int step_offsets[6][2] = {
+ {0, 2},
+ {0, 2},
+ {-1, 2},
+ {-1, 2},
+ {-1, 1},
+ {-1, 1}
+};
+
+static unsigned
+power_of_two(unsigned x)
+{
+ unsigned value = 1;
+ while (value < x)
+ value = value << 1;
+ return value;
+}
+
+static unsigned
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+
+/*
+ * More advanced helper funcs
+ */
+
+
+static void
+i915_miptree_set_level_info(struct i915_texture *tex,
+ unsigned level,
+ unsigned nr_images,
+ unsigned w, unsigned h, unsigned d)
+{
+ struct pipe_texture *pt = &tex->base;
+
+ assert(level < PIPE_MAX_TEXTURE_LEVELS);
+
+ pt->width[level] = w;
+ pt->height[level] = h;
+ pt->depth[level] = d;
+
+ pt->nblocksx[level] = pf_get_nblocksx(&pt->block, w);
+ pt->nblocksy[level] = pf_get_nblocksy(&pt->block, h);
+
+ tex->nr_images[level] = nr_images;
+
+ /*
+ DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
+ level, w, h, d, x, y, tex->level_offset[level]);
+ */
+
+ /* Not sure when this would happen, but anyway:
+ */
+ if (tex->image_offset[level]) {
+ FREE(tex->image_offset[level]);
+ tex->image_offset[level] = NULL;
+ }
+
+ assert(nr_images);
+ assert(!tex->image_offset[level]);
+
+ tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
+ tex->image_offset[level][0] = 0;
+}
+
+static void
+i915_miptree_set_image_offset(struct i915_texture *tex,
+ unsigned level, unsigned img, unsigned x, unsigned y)
+{
+ if (img == 0 && level == 0)
+ assert(x == 0 && y == 0);
+
+ assert(img < tex->nr_images[level]);
+
+ tex->image_offset[level][img] = y * tex->stride + x * tex->base.block.size;
+
+ /*
+ printf("%s level %d img %d pos %d,%d image_offset %x\n",
+ __FUNCTION__, level, img, x, y, tex->image_offset[level][img]);
+ */
+}
+
+
+/*
+ * i915 layout functions, some used by i945
+ */
+
+
+/**
+ * Special case to deal with scanout textures.
+ */
+static boolean
+i915_scanout_layout(struct i915_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+
+ if (pt->last_level > 0 || pt->block.size != 4)
+ return 0;
+
+ i915_miptree_set_level_info(tex, 0, 1,
+ tex->base.width[0],
+ tex->base.height[0],
+ 1);
+ i915_miptree_set_image_offset(tex, 0, 0, 0, 0);
+
+ if (tex->base.width[0] >= 240) {
+ tex->stride = power_of_two(tex->base.nblocksx[0] * pt->block.size);
+ tex->total_nblocksy = round_up(tex->base.nblocksy[0], 8);
+ tex->hw_tiled = INTEL_TILE_X;
+ } else if (tex->base.width[0] == 64 && tex->base.height[0] == 64) {
+ tex->stride = power_of_two(tex->base.nblocksx[0] * pt->block.size);
+ tex->total_nblocksy = round_up(tex->base.nblocksy[0], 8);
+ } else {
+ return FALSE;
+ }
+
+ debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
+ tex->base.width[0], tex->base.height[0], pt->block.size,
+ tex->stride, tex->total_nblocksy, tex->stride * tex->total_nblocksy);
+
+ return TRUE;
+}
+
+static void
+i915_miptree_layout_2d(struct i915_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+ unsigned level;
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+ unsigned nblocksx = pt->nblocksx[0];
+ unsigned nblocksy = pt->nblocksy[0];
+
+ tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
+ tex->total_nblocksy = 0;
+
+ for (level = 0; level <= pt->last_level; level++) {
+ i915_miptree_set_level_info(tex, level, 1, width, height, 1);
+ i915_miptree_set_image_offset(tex, level, 0, 0, tex->total_nblocksy);
+
+ nblocksy = round_up(MAX2(2, nblocksy), 2);
+
+ tex->total_nblocksy += nblocksy;
+
+ width = minify(width);
+ height = minify(height);
+ nblocksx = pf_get_nblocksx(&pt->block, width);
+ nblocksy = pf_get_nblocksy(&pt->block, height);
+ }
+}
+
+static void
+i915_miptree_layout_3d(struct i915_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+ unsigned level;
+
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+ unsigned depth = pt->depth[0];
+ unsigned nblocksx = pt->nblocksx[0];
+ unsigned nblocksy = pt->nblocksy[0];
+ unsigned stack_nblocksy = 0;
+
+ /* Calculate the size of a single slice.
+ */
+ tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
+
+ /* XXX: hardware expects/requires 9 levels at minimum.
+ */
+ for (level = 0; level <= MAX2(8, pt->last_level); level++) {
+ i915_miptree_set_level_info(tex, level, depth, width, height, depth);
+
+ stack_nblocksy += MAX2(2, nblocksy);
+
+ width = minify(width);
+ height = minify(height);
+ depth = minify(depth);
+ nblocksx = pf_get_nblocksx(&pt->block, width);
+ nblocksy = pf_get_nblocksy(&pt->block, height);
+ }
+
+ /* Fixup depth image_offsets:
+ */
+ depth = pt->depth[0];
+ for (level = 0; level <= pt->last_level; level++) {
+ unsigned i;
+ for (i = 0; i < depth; i++)
+ i915_miptree_set_image_offset(tex, level, i, 0, i * stack_nblocksy);
+
+ depth = minify(depth);
+ }
+
+ /* Multiply slice size by texture depth for total size. It's
+ * remarkable how wasteful of memory the i915 texture layouts
+ * are. They are largely fixed in the i945.
+ */
+ tex->total_nblocksy = stack_nblocksy * pt->depth[0];
+}
+
+static void
+i915_miptree_layout_cube(struct i915_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+ unsigned width = pt->width[0], height = pt->height[0];
+ const unsigned nblocks = pt->nblocksx[0];
+ unsigned level;
+ unsigned face;
+
+ assert(width == height); /* cubemap images are square */
+
+ /* double pitch for cube layouts */
+ tex->stride = round_up(nblocks * pt->block.size * 2, 4);
+ tex->total_nblocksy = nblocks * 4;
+
+ for (level = 0; level <= pt->last_level; level++) {
+ i915_miptree_set_level_info(tex, level, 6, width, height, 1);
+ width /= 2;
+ height /= 2;
+ }
+
+ for (face = 0; face < 6; face++) {
+ unsigned x = initial_offsets[face][0] * nblocks;
+ unsigned y = initial_offsets[face][1] * nblocks;
+ unsigned d = nblocks;
+
+ for (level = 0; level <= pt->last_level; level++) {
+ i915_miptree_set_image_offset(tex, level, face, x, y);
+ d >>= 1;
+ x += step_offsets[face][0] * d;
+ y += step_offsets[face][1] * d;
+ }
+ }
+}
+
+static boolean
+i915_miptree_layout(struct i915_texture * tex)
+{
+ struct pipe_texture *pt = &tex->base;
+
+ switch (pt->target) {
+ case PIPE_TEXTURE_1D:
+ case PIPE_TEXTURE_2D:
+ i915_miptree_layout_2d(tex);
+ break;
+ case PIPE_TEXTURE_3D:
+ i915_miptree_layout_3d(tex);
+ break;
+ case PIPE_TEXTURE_CUBE:
+ i915_miptree_layout_cube(tex);
+ break;
+ default:
+ assert(0);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * i945 layout functions
+ */
+
+
+static void
+i945_miptree_layout_2d(struct i915_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+ const int align_x = 2, align_y = 4;
+ unsigned level;
+ unsigned x = 0;
+ unsigned y = 0;
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+ unsigned nblocksx = pt->nblocksx[0];
+ unsigned nblocksy = pt->nblocksy[0];
+
+ /* used for scanouts that need special layouts */
+ if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_PRIMARY)
+ if (i915_scanout_layout(tex))
+ return;
+
+ tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
+
+ /* May need to adjust pitch to accomodate the placement of
+ * the 2nd mipmap level. This occurs when the alignment
+ * constraints of mipmap placement push the right edge of the
+ * 2nd mipmap level out past the width of its parent.
+ */
+ if (pt->last_level > 0) {
+ unsigned mip1_nblocksx
+ = align(pf_get_nblocksx(&pt->block, minify(width)), align_x)
+ + pf_get_nblocksx(&pt->block, minify(minify(width)));
+
+ if (mip1_nblocksx > nblocksx)
+ tex->stride = mip1_nblocksx * pt->block.size;
+ }
+
+ /* Pitch must be a whole number of dwords
+ */
+ tex->stride = align(tex->stride, 64);
+ tex->total_nblocksy = 0;
+
+ for (level = 0; level <= pt->last_level; level++) {
+ i915_miptree_set_level_info(tex, level, 1, width, height, 1);
+ i915_miptree_set_image_offset(tex, level, 0, x, y);
+
+ nblocksy = align(nblocksy, align_y);
+
+ /* Because the images are packed better, the final offset
+ * might not be the maximal one:
+ */
+ tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy);
+
+ /* Layout_below: step right after second mipmap level.
+ */
+ if (level == 1) {
+ x += align(nblocksx, align_x);
+ }
+ else {
+ y += nblocksy;
+ }
+
+ width = minify(width);
+ height = minify(height);
+ nblocksx = pf_get_nblocksx(&pt->block, width);
+ nblocksy = pf_get_nblocksy(&pt->block, height);
+ }
+}
+
+static void
+i945_miptree_layout_3d(struct i915_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+ unsigned depth = pt->depth[0];
+ unsigned nblocksx = pt->nblocksx[0];
+ unsigned nblocksy = pt->nblocksy[0];
+ unsigned pack_x_pitch, pack_x_nr;
+ unsigned pack_y_pitch;
+ unsigned level;
+
+ tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
+ tex->total_nblocksy = 0;
+
+ pack_y_pitch = MAX2(pt->nblocksy[0], 2);
+ pack_x_pitch = tex->stride / pt->block.size;
+ pack_x_nr = 1;
+
+ for (level = 0; level <= pt->last_level; level++) {
+ int x = 0;
+ int y = 0;
+ unsigned q, j;
+
+ i915_miptree_set_level_info(tex, level, depth, width, height, depth);
+
+ for (q = 0; q < depth;) {
+ for (j = 0; j < pack_x_nr && q < depth; j++, q++) {
+ i915_miptree_set_image_offset(tex, level, q, x, y + tex->total_nblocksy);
+ x += pack_x_pitch;
+ }
+
+ x = 0;
+ y += pack_y_pitch;
+ }
+
+ tex->total_nblocksy += y;
+
+ if (pack_x_pitch > 4) {
+ pack_x_pitch >>= 1;
+ pack_x_nr <<= 1;
+ assert(pack_x_pitch * pack_x_nr * pt->block.size <= tex->stride);
+ }
+
+ if (pack_y_pitch > 2) {
+ pack_y_pitch >>= 1;
+ }
+
+ width = minify(width);
+ height = minify(height);
+ depth = minify(depth);
+ nblocksx = pf_get_nblocksx(&pt->block, width);
+ nblocksy = pf_get_nblocksy(&pt->block, height);
+ }
+}
+
+static void
+i945_miptree_layout_cube(struct i915_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+ unsigned level;
+
+ const unsigned nblocks = pt->nblocksx[0];
+ unsigned face;
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+
+ /*
+ printf("%s %i, %i\n", __FUNCTION__, pt->width[0], pt->height[0]);
+ */
+
+ assert(width == height); /* cubemap images are square */
+
+ /*
+ * XXX Should only be used for compressed formats. But lets
+ * keep this code active just in case.
+ *
+ * Depending on the size of the largest images, pitch can be
+ * determined either by the old-style packing of cubemap faces,
+ * or the final row of 4x4, 2x2 and 1x1 faces below this.
+ */
+ if (nblocks > 32)
+ tex->stride = round_up(nblocks * pt->block.size * 2, 4);
+ else
+ tex->stride = 14 * 8 * pt->block.size;
+
+ tex->total_nblocksy = nblocks * 4;
+
+ /* Set all the levels to effectively occupy the whole rectangular region.
+ */
+ for (level = 0; level <= pt->last_level; level++) {
+ i915_miptree_set_level_info(tex, level, 6, width, height, 1);
+ width /= 2;
+ height /= 2;
+ }
+
+ for (face = 0; face < 6; face++) {
+ unsigned x = initial_offsets[face][0] * nblocks;
+ unsigned y = initial_offsets[face][1] * nblocks;
+ unsigned d = nblocks;
+
+#if 0 /* Fix and enable this code for compressed formats */
+ if (nblocks == 4 && face >= 4) {
+ y = tex->total_height - 4;
+ x = (face - 4) * 8;
+ }
+ else if (nblocks < 4 && (face > 0)) {
+ y = tex->total_height - 4;
+ x = face * 8;
+ }
+#endif
+
+ for (level = 0; level <= pt->last_level; level++) {
+ i915_miptree_set_image_offset(tex, level, face, x, y);
+
+ d >>= 1;
+
+#if 0 /* Fix and enable this code for compressed formats */
+ switch (d) {
+ case 4:
+ switch (face) {
+ case PIPE_TEX_FACE_POS_X:
+ case PIPE_TEX_FACE_NEG_X:
+ x += step_offsets[face][0] * d;
+ y += step_offsets[face][1] * d;
+ break;
+ case PIPE_TEX_FACE_POS_Y:
+ case PIPE_TEX_FACE_NEG_Y:
+ y += 12;
+ x -= 8;
+ break;
+ case PIPE_TEX_FACE_POS_Z:
+ case PIPE_TEX_FACE_NEG_Z:
+ y = tex->total_height - 4;
+ x = (face - 4) * 8;
+ break;
+ }
+ case 2:
+ y = tex->total_height - 4;
+ x = 16 + face * 8;
+ break;
+
+ case 1:
+ x += 48;
+ break;
+ default:
+#endif
+ x += step_offsets[face][0] * d;
+ y += step_offsets[face][1] * d;
+#if 0
+ break;
+ }
+#endif
+ }
+ }
+}
+
+static boolean
+i945_miptree_layout(struct i915_texture * tex)
+{
+ struct pipe_texture *pt = &tex->base;
+
+ switch (pt->target) {
+ case PIPE_TEXTURE_1D:
+ case PIPE_TEXTURE_2D:
+ i945_miptree_layout_2d(tex);
+ break;
+ case PIPE_TEXTURE_3D:
+ i945_miptree_layout_3d(tex);
+ break;
+ case PIPE_TEXTURE_CUBE:
+ i945_miptree_layout_cube(tex);
+ break;
+ default:
+ assert(0);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Screen texture functions
+ */
+
+
+static struct pipe_texture *
+i915_texture_create(struct pipe_screen *screen,
+ const struct pipe_texture *templat)
+{
+ struct i915_screen *is = i915_screen(screen);
+ struct intel_winsys *iws = is->iws;
+ struct i915_texture *tex = CALLOC_STRUCT(i915_texture);
+ size_t tex_size;
+ unsigned buf_usage = 0;
+
+ if (!tex)
+ return NULL;
+
+ tex->base = *templat;
+ pipe_reference_init(&tex->base.reference, 1);
+ tex->base.screen = screen;
+
+ tex->base.nblocksx[0] = pf_get_nblocksx(&tex->base.block, tex->base.width[0]);
+ tex->base.nblocksy[0] = pf_get_nblocksy(&tex->base.block, tex->base.height[0]);
+
+ if (is->is_i945) {
+ if (!i945_miptree_layout(tex))
+ goto fail;
+ } else {
+ if (!i915_miptree_layout(tex))
+ goto fail;
+ }
+
+ tex_size = tex->stride * tex->total_nblocksy;
+
+
+
+ /* for scanouts and cursors, cursors arn't scanouts */
+ if (templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY && templat->width[0] != 64)
+ buf_usage = INTEL_NEW_SCANOUT;
+ else
+ buf_usage = INTEL_NEW_TEXTURE;
+
+ tex->buffer = iws->buffer_create(iws, tex_size, 64, buf_usage);
+ if (!tex->buffer)
+ goto fail;
+
+ /* setup any hw fences */
+ if (tex->hw_tiled) {
+ assert(tex->sw_tiled == INTEL_TILE_NONE);
+ iws->buffer_set_fence_reg(iws, tex->buffer, tex->stride, tex->hw_tiled);
+ }
+
+
+#if 0
+ void *ptr = ws->buffer_map(ws, tex->buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ memset(ptr, 0x80, tex_size);
+ ws->buffer_unmap(ws, tex->buffer);
+#endif
+
+ return &tex->base;
+
+fail:
+ FREE(tex);
+ return NULL;
+}
+
+static struct pipe_texture *
+i915_texture_blanket(struct pipe_screen * screen,
+ const struct pipe_texture *base,
+ const unsigned *stride,
+ struct pipe_buffer *buffer)
+{
+#if 0
+ struct i915_texture *tex;
+ assert(screen);
+
+ /* Only supports one type */
+ if (base->target != PIPE_TEXTURE_2D ||
+ base->last_level != 0 ||
+ base->depth[0] != 1) {
+ return NULL;
+ }
+
+ tex = CALLOC_STRUCT(i915_texture);
+ if (!tex)
+ return NULL;
+
+ tex->base = *base;
+ pipe_reference_init(&tex->base.reference, 1);
+ tex->base.screen = screen;
+
+ tex->stride = stride[0];
+
+ i915_miptree_set_level_info(tex, 0, 1, base->width[0], base->height[0], 1);
+ i915_miptree_set_image_offset(tex, 0, 0, 0, 0);
+
+ pipe_buffer_reference(&tex->buffer, buffer);
+
+ return &tex->base;
+#else
+ return NULL;
+#endif
+}
+
+static void
+i915_texture_destroy(struct pipe_texture *pt)
+{
+ struct i915_texture *tex = (struct i915_texture *)pt;
+ struct intel_winsys *iws = i915_screen(pt->screen)->iws;
+ uint i;
+
+ /*
+ DBG("%s deleting %p\n", __FUNCTION__, (void *) tex);
+ */
+
+ iws->buffer_destroy(iws, tex->buffer);
+
+ for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
+ if (tex->image_offset[i])
+ FREE(tex->image_offset[i]);
+
+ FREE(tex);
+}
+
+
+/*
+ * Screen surface functions
+ */
+
+
+static struct pipe_surface *
+i915_get_tex_surface(struct pipe_screen *screen,
+ struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned flags)
+{
+ struct i915_texture *tex = (struct i915_texture *)pt;
+ struct pipe_surface *ps;
+ unsigned offset; /* in bytes */
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ offset = tex->image_offset[level][face];
+ }
+ else if (pt->target == PIPE_TEXTURE_3D) {
+ offset = tex->image_offset[level][zslice];
+ }
+ else {
+ offset = tex->image_offset[level][0];
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+
+ ps = CALLOC_STRUCT(pipe_surface);
+ if (ps) {
+ pipe_reference_init(&ps->reference, 1);
+ pipe_texture_reference(&ps->texture, pt);
+ ps->format = pt->format;
+ ps->width = pt->width[level];
+ ps->height = pt->height[level];
+ ps->offset = offset;
+ ps->usage = flags;
+ }
+ return ps;
+}
+
+static void
+i915_tex_surface_destroy(struct pipe_surface *surf)
+{
+ pipe_texture_reference(&surf->texture, NULL);
+ FREE(surf);
+}
+
+
+/*
+ * Screen transfer functions
+ */
+
+
+static struct pipe_transfer*
+i915_get_tex_transfer(struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage, unsigned x, unsigned y,
+ unsigned w, unsigned h)
+{
+ struct i915_texture *tex = (struct i915_texture *)texture;
+ struct i915_transfer *trans;
+ unsigned offset; /* in bytes */
+
+ if (texture->target == PIPE_TEXTURE_CUBE) {
+ offset = tex->image_offset[level][face];
+ }
+ else if (texture->target == PIPE_TEXTURE_3D) {
+ offset = tex->image_offset[level][zslice];
+ }
+ else {
+ offset = tex->image_offset[level][0];
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+
+ trans = CALLOC_STRUCT(i915_transfer);
+ if (trans) {
+ pipe_texture_reference(&trans->base.texture, texture);
+ trans->base.format = trans->base.format;
+ trans->base.x = x;
+ trans->base.y = y;
+ trans->base.width = w;
+ trans->base.height = h;
+ trans->base.block = texture->block;
+ trans->base.nblocksx = texture->nblocksx[level];
+ trans->base.nblocksy = texture->nblocksy[level];
+ trans->base.stride = tex->stride;
+ trans->offset = offset;
+ trans->base.usage = usage;
+ }
+ return &trans->base;
+}
+
+static void *
+i915_transfer_map(struct pipe_screen *screen,
+ struct pipe_transfer *transfer)
+{
+ struct i915_texture *tex = (struct i915_texture *)transfer->texture;
+ struct intel_winsys *iws = i915_screen(tex->base.screen)->iws;
+ char *map;
+ boolean write = FALSE;
+
+ if (transfer->usage != PIPE_TRANSFER_READ)
+ write = TRUE;
+
+ map = iws->buffer_map(iws, tex->buffer, write);
+ if (map == NULL)
+ return NULL;
+
+ return map + i915_transfer(transfer)->offset +
+ transfer->y / transfer->block.height * transfer->stride +
+ transfer->x / transfer->block.width * transfer->block.size;
+}
+
+static void
+i915_transfer_unmap(struct pipe_screen *screen,
+ struct pipe_transfer *transfer)
+{
+ struct i915_texture *tex = (struct i915_texture *)transfer->texture;
+ struct intel_winsys *iws = i915_screen(tex->base.screen)->iws;
+ iws->buffer_unmap(iws, tex->buffer);
+}
+
+static void
+i915_tex_transfer_destroy(struct pipe_transfer *trans)
+{
+ pipe_texture_reference(&trans->texture, NULL);
+ FREE(trans);
+}
+
+
+/*
+ * Other texture functions
+ */
+
+
+void
+i915_init_screen_texture_functions(struct i915_screen *is)
+{
+ is->base.texture_create = i915_texture_create;
+ is->base.texture_blanket = i915_texture_blanket;
+ is->base.texture_destroy = i915_texture_destroy;
+ is->base.get_tex_surface = i915_get_tex_surface;
+ is->base.tex_surface_destroy = i915_tex_surface_destroy;
+ is->base.get_tex_transfer = i915_get_tex_transfer;
+ is->base.transfer_map = i915_transfer_map;
+ is->base.transfer_unmap = i915_transfer_unmap;
+ is->base.tex_transfer_destroy = i915_tex_transfer_destroy;
+}
+
+struct pipe_texture *
+i915_texture_blanket_intel(struct pipe_screen *screen,
+ struct pipe_texture *base,
+ unsigned stride,
+ struct intel_buffer *buffer)
+{
+ struct i915_texture *tex;
+ assert(screen);
+
+ /* Only supports one type */
+ if (base->target != PIPE_TEXTURE_2D ||
+ base->last_level != 0 ||
+ base->depth[0] != 1) {
+ return NULL;
+ }
+
+ tex = CALLOC_STRUCT(i915_texture);
+ if (!tex)
+ return NULL;
+
+ tex->base = *base;
+ pipe_reference_init(&tex->base.reference, 1);
+ tex->base.screen = screen;
+
+ tex->stride = stride;
+
+ i915_miptree_set_level_info(tex, 0, 1, base->width[0], base->height[0], 1);
+ i915_miptree_set_image_offset(tex, 0, 0, 0, 0);
+
+ tex->buffer = buffer;
+
+ return &tex->base;
+}
+
+boolean
+i915_get_texture_buffer_intel(struct pipe_texture *texture,
+ struct intel_buffer **buffer,
+ unsigned *stride)
+{
+ struct i915_texture *tex = (struct i915_texture *)texture;
+
+ if (!texture)
+ return FALSE;
+
+ *stride = tex->stride;
+ *buffer = tex->buffer;
+
+ return TRUE;
+}
diff --git a/src/gallium/drivers/i915simple/i915_texture.h b/src/gallium/drivers/i915simple/i915_texture.h
new file mode 100644
index 0000000000..51a1dd984c
--- /dev/null
+++ b/src/gallium/drivers/i915simple/i915_texture.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef I915_TEXTURE_H
+#define I915_TEXTURE_H
+
+struct i915_screen;
+
+extern void
+i915_init_screen_texture_functions(struct i915_screen *is);
+
+#endif /* I915_TEXTURE_H */
diff --git a/src/gallium/drivers/i915simple/intel_batchbuffer.h b/src/gallium/drivers/i915simple/intel_batchbuffer.h
new file mode 100644
index 0000000000..db12dfd2ac
--- /dev/null
+++ b/src/gallium/drivers/i915simple/intel_batchbuffer.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef INTEL_BATCH_H
+#define INTEL_BATCH_H
+
+#include "intel_winsys.h"
+
+static INLINE boolean
+intel_batchbuffer_check(struct intel_batchbuffer *batch,
+ size_t dwords,
+ size_t relocs)
+{
+ return dwords * 4 <= batch->size - (batch->ptr - batch->map) &&
+ relocs <= (batch->max_relocs - batch->relocs);
+}
+
+static INLINE size_t
+intel_batchbuffer_space(struct intel_batchbuffer *batch)
+{
+ return batch->size - (batch->ptr - batch->map);
+}
+
+static INLINE void
+intel_batchbuffer_dword(struct intel_batchbuffer *batch,
+ unsigned dword)
+{
+ if (intel_batchbuffer_space(batch) < 4)
+ return;
+
+ *(unsigned *)batch->ptr = dword;
+ batch->ptr += 4;
+}
+
+static INLINE void
+intel_batchbuffer_write(struct intel_batchbuffer *batch,
+ void *data,
+ size_t size)
+{
+ if (intel_batchbuffer_space(batch) < size)
+ return;
+
+ memcpy(data, batch->ptr, size);
+ batch->ptr += size;
+}
+
+static INLINE int
+intel_batchbuffer_reloc(struct intel_batchbuffer *batch,
+ struct intel_buffer *buffer,
+ enum intel_buffer_usage usage,
+ size_t offset)
+{
+ return batch->iws->batchbuffer_reloc(batch, buffer, usage, offset);
+}
+
+static INLINE void
+intel_batchbuffer_flush(struct intel_batchbuffer *batch,
+ struct pipe_fence_handle **fence)
+{
+ batch->iws->batchbuffer_flush(batch, fence);
+}
+
+#endif
diff --git a/src/gallium/drivers/i915simple/intel_winsys.h b/src/gallium/drivers/i915simple/intel_winsys.h
new file mode 100644
index 0000000000..42c5e7470e
--- /dev/null
+++ b/src/gallium/drivers/i915simple/intel_winsys.h
@@ -0,0 +1,230 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 Jakob Bornecrantz
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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 INTEL_WINSYS_H
+#define INTEL_WINSYS_H
+
+#include "pipe/p_compiler.h"
+
+struct intel_winsys;
+struct intel_buffer;
+struct intel_batchbuffer;
+struct pipe_texture;
+struct pipe_fence_handle;
+
+enum intel_buffer_usage
+{
+ /* use on textures */
+ INTEL_USAGE_RENDER = 0x01,
+ INTEL_USAGE_SAMPLER = 0x02,
+ INTEL_USAGE_2D_TARGET = 0x04,
+ INTEL_USAGE_2D_SOURCE = 0x08,
+ /* use on vertex */
+ INTEL_USAGE_VERTEX = 0x10,
+};
+
+enum intel_buffer_type
+{
+ INTEL_NEW_TEXTURE,
+ INTEL_NEW_SCANOUT, /**< a texture used for scanning out from */
+ INTEL_NEW_VERTEX,
+};
+
+enum intel_buffer_tile
+{
+ INTEL_TILE_NONE,
+ INTEL_TILE_X,
+ INTEL_TILE_Y,
+};
+
+struct intel_batchbuffer {
+
+ struct intel_winsys *iws;
+
+ /**
+ * Values exported to speed up the writing the batchbuffer,
+ * instead of having to go trough a accesor function for
+ * each dword written.
+ */
+ /*{@*/
+ uint8_t *map;
+ uint8_t *ptr;
+ size_t size;
+
+ size_t relocs;
+ size_t max_relocs;
+ /*@}*/
+};
+
+struct intel_winsys {
+
+ /**
+ * Batchbuffer functions.
+ */
+ /*@{*/
+ /**
+ * Create a new batchbuffer.
+ */
+ struct intel_batchbuffer *(*batchbuffer_create)(struct intel_winsys *iws);
+
+ /**
+ * Emit a relocation to a buffer.
+ * Target position in batchbuffer is the same as ptr.
+ *
+ * @batch
+ * @reloc buffer address to be inserted into target.
+ * @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.
+ */
+ int (*batchbuffer_reloc)(struct intel_batchbuffer *batch,
+ struct intel_buffer *reloc,
+ enum intel_buffer_usage usage,
+ unsigned offset);
+
+ /**
+ * Flush a bufferbatch.
+ */
+ void (*batchbuffer_flush)(struct intel_batchbuffer *batch,
+ struct pipe_fence_handle **fence);
+
+ /**
+ * Destroy a batchbuffer.
+ */
+ void (*batchbuffer_destroy)(struct intel_batchbuffer *batch);
+ /*@}*/
+
+
+ /**
+ * Buffer functions.
+ */
+ /*@{*/
+ /**
+ * Create a buffer.
+ */
+ struct intel_buffer *(*buffer_create)(struct intel_winsys *iws,
+ unsigned size, unsigned alignment,
+ enum intel_buffer_type type);
+
+ /**
+ * Fence a buffer with a fence reg.
+ * Not to be confused with pipe_fence_handle.
+ */
+ int (*buffer_set_fence_reg)(struct intel_winsys *iws,
+ struct intel_buffer *buffer,
+ unsigned stride,
+ enum intel_buffer_tile tile);
+
+ /**
+ * Map a buffer.
+ */
+ void *(*buffer_map)(struct intel_winsys *iws,
+ struct intel_buffer *buffer,
+ boolean write);
+
+ /**
+ * Unmap a buffer.
+ */
+ void (*buffer_unmap)(struct intel_winsys *iws,
+ struct intel_buffer *buffer);
+
+ /**
+ * Write to a buffer.
+ *
+ * Arguments follows pwrite(2)
+ */
+ int (*buffer_write)(struct intel_winsys *iws,
+ struct intel_buffer *dst,
+ const void *src,
+ size_t size,
+ size_t offset);
+
+ void (*buffer_destroy)(struct intel_winsys *iws,
+ struct intel_buffer *buffer);
+ /*@}*/
+
+
+ /**
+ * Fence functions.
+ */
+ /*@{*/
+ /**
+ * Reference fence and set ptr to fence.
+ */
+ void (*fence_reference)(struct intel_winsys *iws,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence);
+
+ /**
+ * Check if a fence has finished.
+ */
+ int (*fence_signalled)(struct intel_winsys *iws,
+ struct pipe_fence_handle *fence);
+
+ /**
+ * Wait on a fence to finish.
+ */
+ int (*fence_finish)(struct intel_winsys *iws,
+ struct pipe_fence_handle *fence);
+ /*@}*/
+
+
+ /**
+ * Destroy the winsys.
+ */
+ void (*destroy)(struct intel_winsys *iws);
+};
+
+
+/**
+ * Create i915 pipe_screen.
+ */
+struct pipe_screen *i915_create_screen(struct intel_winsys *iws, unsigned pci_id);
+
+/**
+ * Create a i915 pipe_context.
+ */
+struct pipe_context *i915_create_context(struct pipe_screen *screen);
+
+/**
+ * Get the intel_winsys buffer backing the texture.
+ *
+ * TODO UGLY
+ */
+boolean i915_get_texture_buffer_intel(struct pipe_texture *texture,
+ struct intel_buffer **buffer,
+ unsigned *stride);
+
+/**
+ * Wrap a intel_winsys buffer with a texture blanket.
+ *
+ * TODO UGLY
+ */
+struct pipe_texture * i915_texture_blanket_intel(struct pipe_screen *screen,
+ struct pipe_texture *tmplt,
+ unsigned pitch,
+ struct intel_buffer *buffer);
+
+#endif
diff --git a/src/gallium/drivers/i965simple/Makefile b/src/gallium/drivers/i965simple/Makefile
new file mode 100644
index 0000000000..19182afa75
--- /dev/null
+++ b/src/gallium/drivers/i965simple/Makefile
@@ -0,0 +1,52 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = i965simple
+
+C_SOURCES = \
+ brw_blit.c \
+ brw_flush.c \
+ brw_screen.c \
+ brw_surface.c \
+ brw_cc.c \
+ brw_clip.c \
+ brw_clip_line.c \
+ brw_clip_point.c \
+ brw_clip_state.c \
+ brw_clip_tri.c \
+ brw_clip_util.c \
+ brw_context.c \
+ brw_curbe.c \
+ brw_draw.c \
+ brw_draw_upload.c \
+ brw_eu.c \
+ brw_eu_debug.c \
+ brw_eu_emit.c \
+ brw_eu_util.c \
+ brw_gs.c \
+ brw_gs_emit.c \
+ brw_gs_state.c \
+ brw_misc_state.c \
+ brw_sf.c \
+ brw_sf_emit.c \
+ brw_sf_state.c \
+ brw_state.c \
+ brw_state_batch.c \
+ brw_state_cache.c \
+ brw_state_pool.c \
+ brw_state_upload.c \
+ brw_tex_layout.c \
+ brw_urb.c \
+ brw_util.c \
+ brw_vs.c \
+ brw_vs_emit.c \
+ brw_vs_state.c \
+ brw_wm.c \
+ brw_wm_iz.c \
+ brw_wm_decl.c \
+ brw_wm_glsl.c \
+ brw_wm_sampler_state.c \
+ brw_wm_state.c \
+ brw_wm_surface_state.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/i965simple/SConscript b/src/gallium/drivers/i965simple/SConscript
new file mode 100644
index 0000000000..43fc2a4005
--- /dev/null
+++ b/src/gallium/drivers/i965simple/SConscript
@@ -0,0 +1,54 @@
+Import('*')
+
+env = env.Clone()
+
+i965simple = env.ConvenienceLibrary(
+ target = 'i965simple',
+ source = [
+ 'brw_blit.c',
+ 'brw_cc.c',
+ 'brw_clip.c',
+ 'brw_clip_line.c',
+ 'brw_clip_point.c',
+ 'brw_clip_state.c',
+ 'brw_clip_tri.c',
+ 'brw_clip_util.c',
+ 'brw_context.c',
+ 'brw_curbe.c',
+ 'brw_draw.c',
+ 'brw_draw_upload.c',
+ 'brw_eu.c',
+ 'brw_eu_debug.c',
+ 'brw_eu_emit.c',
+ 'brw_eu_util.c',
+ 'brw_flush.c',
+ 'brw_gs.c',
+ 'brw_gs_emit.c',
+ 'brw_gs_state.c',
+ 'brw_misc_state.c',
+ 'brw_screen.c',
+ 'brw_sf.c',
+ 'brw_sf_emit.c',
+ 'brw_sf_state.c',
+ 'brw_state.c',
+ 'brw_state_batch.c',
+ 'brw_state_cache.c',
+ 'brw_state_pool.c',
+ 'brw_state_upload.c',
+ 'brw_surface.c',
+ 'brw_tex_layout.c',
+ 'brw_urb.c',
+ 'brw_util.c',
+ 'brw_vs.c',
+ 'brw_vs_emit.c',
+ 'brw_vs_state.c',
+ 'brw_wm.c',
+ 'brw_wm_decl.c',
+ 'brw_wm_glsl.c',
+ 'brw_wm_iz.c',
+ 'brw_wm_sampler_state.c',
+ 'brw_wm_state.c',
+ 'brw_wm_surface_state.c',
+ ])
+
+Export('i965simple')
diff --git a/src/gallium/drivers/i965simple/brw_batch.h b/src/gallium/drivers/i965simple/brw_batch.h
new file mode 100644
index 0000000000..5f5932a488
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_batch.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef BRW_BATCH_H
+#define BRW_BATCH_H
+
+#include "brw_winsys.h"
+
+#define BATCH_LOCALS
+
+#define INTEL_BATCH_NO_CLIPRECTS 0x1
+#define INTEL_BATCH_CLIPRECTS 0x2
+
+#define BEGIN_BATCH( dwords, relocs ) \
+ brw->winsys->batch_start(brw->winsys, dwords, relocs)
+
+#define OUT_BATCH( dword ) \
+ brw->winsys->batch_dword(brw->winsys, dword)
+
+#define OUT_RELOC( buf, flags, delta ) \
+ brw->winsys->batch_reloc(brw->winsys, buf, flags, delta)
+
+#define ADVANCE_BATCH() \
+ brw->winsys->batch_end( brw->winsys )
+
+/* XXX: this is bogus - need proper handling for out-of-memory in batchbuffer.
+ */
+#define FLUSH_BATCH(fence) do { \
+ brw->winsys->batch_flush(brw->winsys, fence); \
+ brw->hardware_dirty = ~0; \
+} while (0)
+
+#define BRW_BATCH_STRUCT(brw, s) brw_batchbuffer_data( brw->winsys, (s), sizeof(*(s)))
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_blit.c b/src/gallium/drivers/i965simple/brw_blit.c
new file mode 100644
index 0000000000..4d11f8d2ab
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_blit.c
@@ -0,0 +1,218 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "brw_batch.h"
+#include "brw_blit.h"
+#include "brw_context.h"
+#include "brw_reg.h"
+
+#include "pipe/p_context.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+#define FILE_DEBUG_FLAG DEBUG_BLIT
+
+void brw_fill_blit(struct brw_context *brw,
+ unsigned cpp,
+ short dst_pitch,
+ struct pipe_buffer *dst_buffer,
+ unsigned dst_offset,
+ boolean dst_tiled,
+ short x, short y,
+ short w, short h,
+ unsigned color)
+{
+ unsigned BR13, CMD;
+ BATCH_LOCALS;
+
+ dst_pitch *= cpp;
+
+ switch(cpp) {
+ case 1:
+ case 2:
+ case 3:
+ BR13 = (0xF0 << 16) | (1<<24);
+ CMD = XY_COLOR_BLT_CMD;
+ break;
+ case 4:
+ BR13 = (0xF0 << 16) | (1<<24) | (1<<25);
+ CMD = XY_COLOR_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
+ break;
+ default:
+ return;
+ }
+
+ if (dst_tiled) {
+ CMD |= XY_DST_TILED;
+ dst_pitch /= 4;
+ }
+
+ BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
+ OUT_BATCH( CMD );
+ OUT_BATCH( dst_pitch | BR13 );
+ OUT_BATCH( (y << 16) | x );
+ OUT_BATCH( ((y+h) << 16) | (x+w) );
+ OUT_RELOC( dst_buffer, BRW_BUFFER_ACCESS_WRITE, dst_offset );
+ OUT_BATCH( color );
+ ADVANCE_BATCH();
+}
+
+static unsigned translate_raster_op(unsigned logicop)
+{
+ switch(logicop) {
+ case PIPE_LOGICOP_CLEAR: return 0x00;
+ case PIPE_LOGICOP_AND: return 0x88;
+ case PIPE_LOGICOP_AND_REVERSE: return 0x44;
+ case PIPE_LOGICOP_COPY: return 0xCC;
+ case PIPE_LOGICOP_AND_INVERTED: return 0x22;
+ case PIPE_LOGICOP_NOOP: return 0xAA;
+ case PIPE_LOGICOP_XOR: return 0x66;
+ case PIPE_LOGICOP_OR: return 0xEE;
+ case PIPE_LOGICOP_NOR: return 0x11;
+ case PIPE_LOGICOP_EQUIV: return 0x99;
+ case PIPE_LOGICOP_INVERT: return 0x55;
+ case PIPE_LOGICOP_OR_REVERSE: return 0xDD;
+ case PIPE_LOGICOP_COPY_INVERTED: return 0x33;
+ case PIPE_LOGICOP_OR_INVERTED: return 0xBB;
+ case PIPE_LOGICOP_NAND: return 0x77;
+ case PIPE_LOGICOP_SET: return 0xFF;
+ default: return 0;
+ }
+}
+
+
+/* Copy BitBlt
+ */
+void brw_copy_blit(struct brw_context *brw,
+ unsigned do_flip,
+ unsigned cpp,
+ short src_pitch,
+ struct pipe_buffer *src_buffer,
+ unsigned src_offset,
+ boolean src_tiled,
+ short dst_pitch,
+ struct pipe_buffer *dst_buffer,
+ unsigned dst_offset,
+ boolean dst_tiled,
+ short src_x, short src_y,
+ short dst_x, short dst_y,
+ short w, short h,
+ unsigned logic_op)
+{
+ unsigned CMD, BR13;
+ int dst_y2 = dst_y + h;
+ int dst_x2 = dst_x + w;
+ BATCH_LOCALS;
+
+
+ DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d op:%d\n",
+ __FUNCTION__,
+ src_buffer, src_pitch, src_x, src_y,
+ dst_buffer, dst_pitch, dst_x, dst_y,
+ w,h,logic_op);
+
+ assert( logic_op - PIPE_LOGICOP_CLEAR >= 0 );
+ assert( logic_op - PIPE_LOGICOP_CLEAR < 0x10 );
+
+ src_pitch *= cpp;
+ dst_pitch *= cpp;
+
+ switch(cpp) {
+ case 1:
+ case 2:
+ case 3:
+ BR13 = (translate_raster_op(logic_op) << 16) | (1<<24);
+ CMD = XY_SRC_COPY_BLT_CMD;
+ break;
+ case 4:
+ BR13 = (translate_raster_op(logic_op) << 16) | (1<<24) |
+ (1<<25);
+ CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
+ break;
+ default:
+ return;
+ }
+
+ if (src_tiled) {
+ CMD |= XY_SRC_TILED;
+ src_pitch /= 4;
+ }
+
+ if (dst_tiled) {
+ CMD |= XY_DST_TILED;
+ dst_pitch /= 4;
+ }
+
+ if (dst_y2 < dst_y ||
+ dst_x2 < dst_x) {
+ return;
+ }
+
+ dst_pitch &= 0xffff;
+ src_pitch &= 0xffff;
+
+ /* Initial y values don't seem to work with negative pitches. If
+ * we adjust the offsets manually (below), it seems to work fine.
+ *
+ * On the other hand, if we always adjust, the hardware doesn't
+ * know which blit directions to use, so overlapping copypixels get
+ * the wrong result.
+ */
+ if (dst_pitch > 0 && src_pitch > 0) {
+ BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
+ OUT_BATCH( CMD );
+ OUT_BATCH( dst_pitch | BR13 );
+ OUT_BATCH( (dst_y << 16) | dst_x );
+ OUT_BATCH( (dst_y2 << 16) | dst_x2 );
+ OUT_RELOC( dst_buffer, BRW_BUFFER_ACCESS_WRITE,
+ dst_offset );
+ OUT_BATCH( (src_y << 16) | src_x );
+ OUT_BATCH( src_pitch );
+ OUT_RELOC( src_buffer, BRW_BUFFER_ACCESS_READ,
+ src_offset );
+ ADVANCE_BATCH();
+ }
+ else {
+ BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
+ OUT_BATCH( CMD );
+ OUT_BATCH( (dst_pitch & 0xffff) | BR13 );
+ OUT_BATCH( (0 << 16) | dst_x );
+ OUT_BATCH( (h << 16) | dst_x2 );
+ OUT_RELOC( dst_buffer, BRW_BUFFER_ACCESS_WRITE,
+ dst_offset + dst_y * dst_pitch );
+ OUT_BATCH( (src_pitch & 0xffff) );
+ OUT_RELOC( src_buffer, BRW_BUFFER_ACCESS_READ,
+ src_offset + src_y * src_pitch );
+ ADVANCE_BATCH();
+ }
+}
+
+
+
diff --git a/src/gallium/drivers/i965simple/brw_blit.h b/src/gallium/drivers/i965simple/brw_blit.h
new file mode 100644
index 0000000000..111c5d91d3
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_blit.h
@@ -0,0 +1,33 @@
+#ifndef BRW_BLIT_H
+#define BRW_BLIT_H
+
+#include "pipe/p_compiler.h"
+
+struct pipe_buffer;
+struct brw_context;
+
+void brw_fill_blit(struct brw_context *intel,
+ unsigned cpp,
+ short dst_pitch,
+ struct pipe_buffer *dst_buffer,
+ unsigned dst_offset,
+ boolean dst_tiled,
+ short x, short y,
+ short w, short h,
+ unsigned color);
+void brw_copy_blit(struct brw_context *intel,
+ unsigned do_flip,
+ unsigned cpp,
+ short src_pitch,
+ struct pipe_buffer *src_buffer,
+ unsigned src_offset,
+ boolean src_tiled,
+ short dst_pitch,
+ struct pipe_buffer *dst_buffer,
+ unsigned dst_offset,
+ boolean dst_tiled,
+ short src_x, short src_y,
+ short dst_x, short dst_y,
+ short w, short h,
+ unsigned logic_op);
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_cc.c b/src/gallium/drivers/i965simple/brw_cc.c
new file mode 100644
index 0000000000..3668123e2e
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_cc.c
@@ -0,0 +1,269 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+#include "brw_util.h"
+
+
+static int brw_translate_compare_func(int func)
+{
+ switch(func) {
+ case PIPE_FUNC_NEVER:
+ return BRW_COMPAREFUNCTION_NEVER;
+ case PIPE_FUNC_LESS:
+ return BRW_COMPAREFUNCTION_LESS;
+ case PIPE_FUNC_LEQUAL:
+ return BRW_COMPAREFUNCTION_LEQUAL;
+ case PIPE_FUNC_GREATER:
+ return BRW_COMPAREFUNCTION_GREATER;
+ case PIPE_FUNC_GEQUAL:
+ return BRW_COMPAREFUNCTION_GEQUAL;
+ case PIPE_FUNC_NOTEQUAL:
+ return BRW_COMPAREFUNCTION_NOTEQUAL;
+ case PIPE_FUNC_EQUAL:
+ return BRW_COMPAREFUNCTION_EQUAL;
+ case PIPE_FUNC_ALWAYS:
+ return BRW_COMPAREFUNCTION_ALWAYS;
+ }
+
+ debug_printf("Unknown value in %s: %x\n", __FUNCTION__, func);
+ return BRW_COMPAREFUNCTION_ALWAYS;
+}
+
+static int brw_translate_stencil_op(int op)
+{
+ switch(op) {
+ case PIPE_STENCIL_OP_KEEP:
+ return BRW_STENCILOP_KEEP;
+ case PIPE_STENCIL_OP_ZERO:
+ return BRW_STENCILOP_ZERO;
+ case PIPE_STENCIL_OP_REPLACE:
+ return BRW_STENCILOP_REPLACE;
+ case PIPE_STENCIL_OP_INCR:
+ return BRW_STENCILOP_INCRSAT;
+ case PIPE_STENCIL_OP_DECR:
+ return BRW_STENCILOP_DECRSAT;
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ return BRW_STENCILOP_INCR;
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ return BRW_STENCILOP_DECR;
+ case PIPE_STENCIL_OP_INVERT:
+ return BRW_STENCILOP_INVERT;
+ default:
+ return BRW_STENCILOP_ZERO;
+ }
+}
+
+
+static int brw_translate_logic_op(int opcode)
+{
+ switch(opcode) {
+ case PIPE_LOGICOP_CLEAR:
+ return BRW_LOGICOPFUNCTION_CLEAR;
+ case PIPE_LOGICOP_AND:
+ return BRW_LOGICOPFUNCTION_AND;
+ case PIPE_LOGICOP_AND_REVERSE:
+ return BRW_LOGICOPFUNCTION_AND_REVERSE;
+ case PIPE_LOGICOP_COPY:
+ return BRW_LOGICOPFUNCTION_COPY;
+ case PIPE_LOGICOP_COPY_INVERTED:
+ return BRW_LOGICOPFUNCTION_COPY_INVERTED;
+ case PIPE_LOGICOP_AND_INVERTED:
+ return BRW_LOGICOPFUNCTION_AND_INVERTED;
+ case PIPE_LOGICOP_NOOP:
+ return BRW_LOGICOPFUNCTION_NOOP;
+ case PIPE_LOGICOP_XOR:
+ return BRW_LOGICOPFUNCTION_XOR;
+ case PIPE_LOGICOP_OR:
+ return BRW_LOGICOPFUNCTION_OR;
+ case PIPE_LOGICOP_OR_INVERTED:
+ return BRW_LOGICOPFUNCTION_OR_INVERTED;
+ case PIPE_LOGICOP_NOR:
+ return BRW_LOGICOPFUNCTION_NOR;
+ case PIPE_LOGICOP_EQUIV:
+ return BRW_LOGICOPFUNCTION_EQUIV;
+ case PIPE_LOGICOP_INVERT:
+ return BRW_LOGICOPFUNCTION_INVERT;
+ case PIPE_LOGICOP_OR_REVERSE:
+ return BRW_LOGICOPFUNCTION_OR_REVERSE;
+ case PIPE_LOGICOP_NAND:
+ return BRW_LOGICOPFUNCTION_NAND;
+ case PIPE_LOGICOP_SET:
+ return BRW_LOGICOPFUNCTION_SET;
+ default:
+ return BRW_LOGICOPFUNCTION_SET;
+ }
+}
+
+
+static void upload_cc_vp( struct brw_context *brw )
+{
+ struct brw_cc_viewport ccv;
+
+ memset(&ccv, 0, sizeof(ccv));
+
+ ccv.min_depth = 0.0;
+ ccv.max_depth = 1.0;
+
+ brw->cc.vp_gs_offset = brw_cache_data( &brw->cache[BRW_CC_VP], &ccv );
+}
+
+const struct brw_tracked_state brw_cc_vp = {
+ .dirty = {
+ .brw = BRW_NEW_SCENE,
+ .cache = 0
+ },
+ .update = upload_cc_vp
+};
+
+
+static void upload_cc_unit( struct brw_context *brw )
+{
+ struct brw_cc_unit_state cc;
+
+ memset(&cc, 0, sizeof(cc));
+
+ /* BRW_NEW_DEPTH_STENCIL */
+ if (brw->attribs.DepthStencil->stencil[0].enabled) {
+ cc.cc0.stencil_enable = brw->attribs.DepthStencil->stencil[0].enabled;
+ cc.cc0.stencil_func = brw_translate_compare_func(brw->attribs.DepthStencil->stencil[0].func);
+ cc.cc0.stencil_fail_op = brw_translate_stencil_op(brw->attribs.DepthStencil->stencil[0].fail_op);
+ cc.cc0.stencil_pass_depth_fail_op = brw_translate_stencil_op(
+ brw->attribs.DepthStencil->stencil[0].zfail_op);
+ cc.cc0.stencil_pass_depth_pass_op = brw_translate_stencil_op(
+ brw->attribs.DepthStencil->stencil[0].zpass_op);
+ cc.cc1.stencil_ref = brw->attribs.DepthStencil->stencil[0].ref_value;
+ cc.cc1.stencil_write_mask = brw->attribs.DepthStencil->stencil[0].writemask;
+ cc.cc1.stencil_test_mask = brw->attribs.DepthStencil->stencil[0].valuemask;
+
+ if (brw->attribs.DepthStencil->stencil[1].enabled) {
+ cc.cc0.bf_stencil_enable = brw->attribs.DepthStencil->stencil[1].enabled;
+ cc.cc0.bf_stencil_func = brw_translate_compare_func(
+ brw->attribs.DepthStencil->stencil[1].func);
+ cc.cc0.bf_stencil_fail_op = brw_translate_stencil_op(
+ brw->attribs.DepthStencil->stencil[1].fail_op);
+ cc.cc0.bf_stencil_pass_depth_fail_op = brw_translate_stencil_op(
+ brw->attribs.DepthStencil->stencil[1].zfail_op);
+ cc.cc0.bf_stencil_pass_depth_pass_op = brw_translate_stencil_op(
+ brw->attribs.DepthStencil->stencil[1].zpass_op);
+ cc.cc1.bf_stencil_ref = brw->attribs.DepthStencil->stencil[1].ref_value;
+ cc.cc2.bf_stencil_write_mask = brw->attribs.DepthStencil->stencil[1].writemask;
+ cc.cc2.bf_stencil_test_mask = brw->attribs.DepthStencil->stencil[1].valuemask;
+ }
+
+ /* Not really sure about this:
+ */
+ if (brw->attribs.DepthStencil->stencil[0].writemask ||
+ brw->attribs.DepthStencil->stencil[1].writemask)
+ cc.cc0.stencil_write_enable = 1;
+ }
+
+ /* BRW_NEW_BLEND */
+ if (brw->attribs.Blend->logicop_enable) {
+ cc.cc2.logicop_enable = 1;
+ cc.cc5.logicop_func = brw_translate_logic_op( brw->attribs.Blend->logicop_func );
+ }
+ else if (brw->attribs.Blend->blend_enable) {
+ int eqRGB = brw->attribs.Blend->rgb_func;
+ int eqA = brw->attribs.Blend->alpha_func;
+ int srcRGB = brw->attribs.Blend->rgb_src_factor;
+ int dstRGB = brw->attribs.Blend->rgb_dst_factor;
+ int srcA = brw->attribs.Blend->alpha_src_factor;
+ int dstA = brw->attribs.Blend->alpha_dst_factor;
+
+ if (eqRGB == PIPE_BLEND_MIN || eqRGB == PIPE_BLEND_MAX) {
+ srcRGB = dstRGB = PIPE_BLENDFACTOR_ONE;
+ }
+
+ if (eqA == PIPE_BLEND_MIN || eqA == PIPE_BLEND_MAX) {
+ srcA = dstA = PIPE_BLENDFACTOR_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.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 ||
+ dstA != dstRGB ||
+ eqA != eqRGB);
+ }
+
+ /* BRW_NEW_ALPHATEST
+ */
+ if (brw->attribs.DepthStencil->alpha.enabled) {
+ cc.cc3.alpha_test = 1;
+ cc.cc3.alpha_test_func =
+ brw_translate_compare_func(brw->attribs.DepthStencil->alpha.func);
+
+ cc.cc7.alpha_ref.ub[0] = float_to_ubyte(brw->attribs.DepthStencil->alpha.ref_value);
+
+ cc.cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
+ }
+
+ if (brw->attribs.Blend->dither) {
+ cc.cc5.dither_enable = 1;
+ cc.cc6.y_dither_offset = 0;
+ cc.cc6.x_dither_offset = 0;
+ }
+
+ if (brw->attribs.DepthStencil->depth.enabled) {
+ cc.cc2.depth_test = brw->attribs.DepthStencil->depth.enabled;
+ cc.cc2.depth_test_function = brw_translate_compare_func(brw->attribs.DepthStencil->depth.func);
+ cc.cc2.depth_write_enable = brw->attribs.DepthStencil->depth.writemask;
+ }
+
+ /* CACHE_NEW_CC_VP */
+ cc.cc4.cc_viewport_state_offset = brw->cc.vp_gs_offset >> 5;
+
+ if (BRW_DEBUG & DEBUG_STATS)
+ cc.cc5.statistics_enable = 1;
+
+ brw->cc.state_gs_offset = brw_cache_data( &brw->cache[BRW_CC_UNIT], &cc );
+}
+
+const struct brw_tracked_state brw_cc_unit = {
+ .dirty = {
+ .brw = BRW_NEW_DEPTH_STENCIL | BRW_NEW_BLEND | BRW_NEW_ALPHA_TEST,
+ .cache = CACHE_NEW_CC_VP
+ },
+ .update = upload_cc_unit
+};
+
diff --git a/src/gallium/drivers/i965simple/brw_clip.c b/src/gallium/drivers/i965simple/brw_clip.c
new file mode 100644
index 0000000000..268124cc53
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_clip.c
@@ -0,0 +1,206 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_state.h"
+#include "brw_clip.h"
+
+#define FRONT_UNFILLED_BIT 0x1
+#define BACK_UNFILLED_BIT 0x2
+
+
+static void compile_clip_prog( struct brw_context *brw,
+ struct brw_clip_prog_key *key )
+{
+ struct brw_clip_compile c;
+ const unsigned *program;
+ unsigned program_size;
+ unsigned delta;
+ unsigned i;
+
+ memset(&c, 0, sizeof(c));
+
+ /* Begin the compilation:
+ */
+ brw_init_compile(&c.func);
+
+ c.func.single_program_flow = 1;
+
+ c.key = *key;
+
+
+ /* Need to locate the two positions present in vertex + header.
+ * These are currently hardcoded:
+ */
+ c.header_position_offset = ATTR_SIZE;
+
+ for (i = 0, delta = REG_SIZE; i < PIPE_MAX_SHADER_OUTPUTS; i++)
+ if (c.key.attrs & (1<<i)) {
+ c.offset[i] = delta;
+ delta += ATTR_SIZE;
+ }
+
+ c.nr_attrs = brw_count_bits(c.key.attrs);
+ c.nr_regs = (c.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */
+ c.nr_bytes = c.nr_regs * REG_SIZE;
+
+ c.prog_data.clip_mode = c.key.clip_mode; /* XXX */
+
+ /* For some reason the thread is spawned with only 4 channels
+ * unmasked.
+ */
+ brw_set_mask_control(&c.func, BRW_MASK_DISABLE);
+
+
+ /* Would ideally have the option of producing a program which could
+ * do all three:
+ */
+ switch (key->primitive) {
+ case PIPE_PRIM_TRIANGLES:
+#if 0
+ if (key->do_unfilled)
+ brw_emit_unfilled_clip( &c );
+ else
+#endif
+ brw_emit_tri_clip( &c );
+ break;
+ case PIPE_PRIM_LINES:
+ brw_emit_line_clip( &c );
+ break;
+ case PIPE_PRIM_POINTS:
+ brw_emit_point_clip( &c );
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+
+
+ /* get the program
+ */
+ program = brw_get_program(&c.func, &program_size);
+
+ /* Upload
+ */
+ brw->clip.prog_gs_offset = brw_upload_cache( &brw->cache[BRW_CLIP_PROG],
+ &c.key,
+ sizeof(c.key),
+ program,
+ program_size,
+ &c.prog_data,
+ &brw->clip.prog_data );
+}
+
+
+static boolean search_cache( struct brw_context *brw,
+ struct brw_clip_prog_key *key )
+{
+ return brw_search_cache(&brw->cache[BRW_CLIP_PROG],
+ key, sizeof(*key),
+ &brw->clip.prog_data,
+ &brw->clip.prog_gs_offset);
+}
+
+
+
+
+/* Calculate interpolants for triangle and line rasterization.
+ */
+static void upload_clip_prog(struct brw_context *brw)
+{
+ struct brw_clip_prog_key key;
+
+ memset(&key, 0, sizeof(key));
+
+ /* Populate the key:
+ */
+ /* BRW_NEW_REDUCED_PRIMITIVE */
+ key.primitive = brw->reduced_primitive;
+ /* CACHE_NEW_VS_PROG */
+ key.attrs = brw->vs.prog_data->outputs_written;
+ /* BRW_NEW_RASTER */
+ key.do_flat_shading = (brw->attribs.Raster->flatshade);
+ /* BRW_NEW_CLIP */
+ key.nr_userclip = brw->attribs.Clip.nr; /* XXX */
+
+#if 0
+ key.clip_mode = BRW_CLIPMODE_NORMAL;
+
+ if (key.primitive == PIPE_PRIM_TRIANGLES) {
+ if (brw->attribs.Raster->cull_mode == PIPE_WINDING_BOTH)
+ key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
+ else {
+ if (brw->attribs.Raster->fill_cw != PIPE_POLYGON_MODE_FILL ||
+ brw->attribs.Raster->fill_ccw != PIPE_POLYGON_MODE_FILL)
+ key.do_unfilled = 1;
+
+ /* Most cases the fixed function units will handle. Cases where
+ * one or more polygon faces are unfilled will require help:
+ */
+ if (key.do_unfilled) {
+ key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;
+
+ if (brw->attribs.Raster->offset_cw ||
+ brw->attribs.Raster->offset_ccw) {
+ key.offset_units = brw->attribs.Raster->offset_units;
+ key.offset_factor = brw->attribs.Raster->offset_scale;
+ }
+ key.fill_ccw = brw->attribs.Raster->fill_ccw;
+ key.fill_cw = brw->attribs.Raster->fill_cw;
+ key.offset_ccw = brw->attribs.Raster->offset_ccw;
+ key.offset_cw = brw->attribs.Raster->offset_cw;
+ if (brw->attribs.Raster->light_twoside &&
+ key.fill_cw != CLIP_CULL)
+ key.copy_bfc_cw = 1;
+ }
+ }
+ }
+#else
+ key.clip_mode = BRW_CLIPMODE_ACCEPT_ALL;
+#endif
+
+ if (!search_cache(brw, &key))
+ compile_clip_prog( brw, &key );
+}
+
+const struct brw_tracked_state brw_clip_prog = {
+ .dirty = {
+ .brw = (BRW_NEW_RASTERIZER |
+ BRW_NEW_CLIP |
+ BRW_NEW_REDUCED_PRIMITIVE),
+ .cache = CACHE_NEW_VS_PROG
+ },
+ .update = upload_clip_prog
+};
diff --git a/src/gallium/drivers/i965simple/brw_clip.h b/src/gallium/drivers/i965simple/brw_clip.h
new file mode 100644
index 0000000000..d70fc094ff
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_clip.h
@@ -0,0 +1,170 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef BRW_CLIP_H
+#define BRW_CLIP_H
+
+
+#include "brw_context.h"
+#include "brw_eu.h"
+
+#define MAX_VERTS (3+6+6)
+
+/* Note that if unfilled primitives are being emitted, we have to fix
+ * up polygon offset and flatshading at this point:
+ */
+struct brw_clip_prog_key {
+ unsigned attrs:32;
+ unsigned primitive:4;
+ unsigned nr_userclip:3;
+ unsigned do_flat_shading:1;
+ unsigned do_unfilled:1;
+ unsigned fill_cw:2; /* includes cull information */
+ unsigned fill_ccw:2; /* includes cull information */
+ unsigned offset_cw:1;
+ unsigned offset_ccw:1;
+ unsigned pad0:17;
+
+ unsigned copy_bfc_cw:1;
+ unsigned copy_bfc_ccw:1;
+ unsigned clip_mode:3;
+ unsigned pad1:27;
+
+ float offset_factor;
+ float offset_units;
+};
+
+
+#define CLIP_LINE 0
+#define CLIP_POINT 1
+#define CLIP_FILL 2
+#define CLIP_CULL 3
+
+
+#define PRIM_MASK (0x1f)
+
+struct brw_clip_compile {
+ struct brw_compile func;
+ struct brw_clip_prog_key key;
+ struct brw_clip_prog_data prog_data;
+
+ struct {
+ struct brw_reg R0;
+ struct brw_reg vertex[MAX_VERTS];
+
+ struct brw_reg t;
+ struct brw_reg t0, t1;
+ struct brw_reg dp0, dp1;
+
+ struct brw_reg dpPrev;
+ struct brw_reg dp;
+ struct brw_reg loopcount;
+ struct brw_reg nr_verts;
+ struct brw_reg planemask;
+
+ struct brw_reg inlist;
+ struct brw_reg outlist;
+ struct brw_reg freelist;
+
+ struct brw_reg dir;
+ struct brw_reg tmp0, tmp1;
+ struct brw_reg offset;
+
+ struct brw_reg fixed_planes;
+ struct brw_reg plane_equation;
+ } reg;
+
+ /* 3 different ways of expressing vertex size:
+ */
+ unsigned nr_attrs;
+ unsigned nr_regs;
+ unsigned nr_bytes;
+
+ unsigned first_tmp;
+ unsigned last_tmp;
+
+ boolean need_direction;
+
+ unsigned last_mrf;
+
+ unsigned header_position_offset;
+ unsigned offset[PIPE_MAX_ATTRIBS];
+};
+
+#define ATTR_SIZE (4*4)
+
+/* Points are only culled, so no need for a clip routine, however it
+ * works out easier to have a dummy one.
+ */
+void brw_emit_unfilled_clip( struct brw_clip_compile *c );
+void brw_emit_tri_clip( struct brw_clip_compile *c );
+void brw_emit_line_clip( struct brw_clip_compile *c );
+void brw_emit_point_clip( struct brw_clip_compile *c );
+
+/* brw_clip_tri.c, for use by the unfilled clip routine:
+ */
+void brw_clip_tri_init_vertices( struct brw_clip_compile *c );
+void brw_clip_tri_flat_shade( struct brw_clip_compile *c );
+void brw_clip_tri( struct brw_clip_compile *c );
+void brw_clip_tri_emit_polygon( struct brw_clip_compile *c );
+void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
+ unsigned nr_verts );
+
+
+/* Utils:
+ */
+
+void brw_clip_interp_vertex( struct brw_clip_compile *c,
+ struct brw_indirect dest_ptr,
+ struct brw_indirect v0_ptr, /* from */
+ struct brw_indirect v1_ptr, /* to */
+ struct brw_reg t0,
+ boolean force_edgeflag );
+
+void brw_clip_init_planes( struct brw_clip_compile *c );
+
+void brw_clip_emit_vue(struct brw_clip_compile *c,
+ struct brw_indirect vert,
+ boolean allocate,
+ boolean eot,
+ unsigned header);
+
+void brw_clip_kill_thread(struct brw_clip_compile *c);
+
+struct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c );
+struct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c );
+
+void brw_clip_copy_colors( struct brw_clip_compile *c,
+ unsigned to, unsigned from );
+
+void brw_clip_init_clipmask( struct brw_clip_compile *c );
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_clip_line.c b/src/gallium/drivers/i965simple/brw_clip_line.c
new file mode 100644
index 0000000000..75d9e5fcda
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_clip_line.c
@@ -0,0 +1,245 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_clip.h"
+
+
+
+static void brw_clip_line_alloc_regs( struct brw_clip_compile *c )
+{
+ unsigned i = 0,j;
+
+ /* Register usage is static, precompute here:
+ */
+ c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
+
+ if (c->key.nr_userclip) {
+ c->reg.fixed_planes = brw_vec4_grf(i, 0);
+ i += (6 + c->key.nr_userclip + 1) / 2;
+
+ c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
+ }
+ else
+ c->prog_data.curb_read_length = 0;
+
+
+ /* Payload vertices plus space for more generated vertices:
+ */
+ for (j = 0; j < 4; j++) {
+ c->reg.vertex[j] = brw_vec4_grf(i, 0);
+ i += c->nr_regs;
+ }
+
+ c->reg.t = brw_vec1_grf(i, 0);
+ c->reg.t0 = brw_vec1_grf(i, 1);
+ c->reg.t1 = brw_vec1_grf(i, 2);
+ c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
+ c->reg.plane_equation = brw_vec4_grf(i, 4);
+ i++;
+
+ c->reg.dp0 = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
+ c->reg.dp1 = brw_vec1_grf(i, 4);
+ i++;
+
+ if (!c->key.nr_userclip) {
+ c->reg.fixed_planes = brw_vec8_grf(i, 0);
+ i++;
+ }
+
+
+ c->first_tmp = i;
+ c->last_tmp = i;
+
+ c->prog_data.urb_read_length = c->nr_regs; /* ? */
+ c->prog_data.total_grf = i;
+}
+
+
+
+/* Line clipping, more or less following the following algorithm:
+ *
+ * for (p=0;p<MAX_PLANES;p++) {
+ * if (clipmask & (1 << p)) {
+ * float dp0 = DOTPROD( vtx0, plane[p] );
+ * float dp1 = DOTPROD( vtx1, plane[p] );
+ *
+ * if (IS_NEGATIVE(dp1)) {
+ * float t = dp1 / (dp1 - dp0);
+ * if (t > t1) t1 = t;
+ * } else {
+ * float t = dp0 / (dp0 - dp1);
+ * if (t > t0) t0 = t;
+ * }
+ *
+ * if (t0 + t1 >= 1.0)
+ * return;
+ * }
+ * }
+ *
+ * interp( ctx, newvtx0, vtx0, vtx1, t0 );
+ * interp( ctx, newvtx1, vtx1, vtx0, t1 );
+ *
+ */
+static void clip_and_emit_line( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_indirect vtx0 = brw_indirect(0, 0);
+ struct brw_indirect vtx1 = brw_indirect(1, 0);
+ struct brw_indirect newvtx0 = brw_indirect(2, 0);
+ struct brw_indirect newvtx1 = brw_indirect(3, 0);
+ struct brw_indirect plane_ptr = brw_indirect(4, 0);
+ struct brw_instruction *plane_loop;
+ struct brw_instruction *plane_active;
+ struct brw_instruction *is_negative;
+ struct brw_instruction *is_neg2;
+ struct brw_instruction *not_culled;
+ struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD);
+
+ brw_MOV(p, get_addr_reg(vtx0), brw_address(c->reg.vertex[0]));
+ brw_MOV(p, get_addr_reg(vtx1), brw_address(c->reg.vertex[1]));
+ brw_MOV(p, get_addr_reg(newvtx0), brw_address(c->reg.vertex[2]));
+ brw_MOV(p, get_addr_reg(newvtx1), brw_address(c->reg.vertex[3]));
+ brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
+
+ /* Note: init t0, t1 together:
+ */
+ brw_MOV(p, vec2(c->reg.t0), brw_imm_f(0));
+
+ brw_clip_init_planes(c);
+ brw_clip_init_clipmask(c);
+
+ /* -ve rhw workaround */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
+ brw_imm_ud(1<<20));
+ brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ plane_loop = brw_DO(p, BRW_EXECUTE_1);
+ {
+ /* if (planemask & 1)
+ */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_AND(p, v1_null_ud, c->reg.planemask, brw_imm_ud(1));
+
+ plane_active = brw_IF(p, BRW_EXECUTE_1);
+ {
+ if (c->key.nr_userclip)
+ brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
+ else
+ brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
+
+#if 0
+ /* dp = DP4(vtx->position, plane)
+ */
+ brw_DP4(p, vec4(c->reg.dp0), deref_4f(vtx0, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
+
+ /* if (IS_NEGATIVE(dp1))
+ */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
+ brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
+#else
+ #warning "disabled"
+#endif
+ is_negative = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
+ brw_math_invert(p, c->reg.t, c->reg.t);
+ brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);
+
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
+ brw_MOV(p, c->reg.t1, c->reg.t);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ }
+ is_negative = brw_ELSE(p, is_negative);
+ {
+ /* Coming back in. We know that both cannot be negative
+ * because the line would have been culled in that case.
+ */
+
+ /* If both are positive, do nothing */
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
+ is_neg2 = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
+ brw_math_invert(p, c->reg.t, c->reg.t);
+ brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);
+
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
+ brw_MOV(p, c->reg.t0, c->reg.t);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ }
+ brw_ENDIF(p, is_neg2);
+ }
+ brw_ENDIF(p, is_negative);
+ }
+ brw_ENDIF(p, plane_active);
+
+ /* plane_ptr++;
+ */
+ brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
+
+ /* while (planemask>>=1) != 0
+ */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
+ }
+ brw_WHILE(p, plane_loop);
+
+ brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1);
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0));
+ not_culled = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, FALSE);
+ brw_clip_interp_vertex(c, newvtx1, vtx1, vtx0, c->reg.t1, FALSE);
+
+ brw_clip_emit_vue(c, newvtx0, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_START);
+ brw_clip_emit_vue(c, newvtx1, 0, 1, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_END);
+ }
+ brw_ENDIF(p, not_culled);
+ brw_clip_kill_thread(c);
+}
+
+
+
+void brw_emit_line_clip( struct brw_clip_compile *c )
+{
+ brw_clip_line_alloc_regs(c);
+
+ if (c->key.do_flat_shading)
+ brw_clip_copy_colors(c, 0, 1);
+
+ clip_and_emit_line(c);
+}
diff --git a/src/gallium/drivers/i965simple/brw_clip_point.c b/src/gallium/drivers/i965simple/brw_clip_point.c
new file mode 100644
index 0000000000..6fce7210d1
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_clip_point.c
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_clip.h"
+
+
+/* Point clipping, nothing to do?
+ */
+void brw_emit_point_clip( struct brw_clip_compile *c )
+{
+ /* Send an empty message to kill the thread:
+ */
+ brw_clip_tri_alloc_regs(c, 0);
+ brw_clip_kill_thread(c);
+}
diff --git a/src/gallium/drivers/i965simple/brw_clip_state.c b/src/gallium/drivers/i965simple/brw_clip_state.c
new file mode 100644
index 0000000000..8e78dd51be
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_clip_state.c
@@ -0,0 +1,93 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+
+static void upload_clip_unit( struct brw_context *brw )
+{
+ struct brw_clip_unit_state clip;
+
+ memset(&clip, 0, sizeof(clip));
+
+ /* CACHE_NEW_CLIP_PROG */
+ clip.thread0.grf_reg_count =
+ align(brw->clip.prog_data->total_grf, 16) / 16 - 1;
+ clip.thread0.kernel_start_pointer = brw->clip.prog_gs_offset >> 6;
+ clip.thread3.urb_entry_read_length = brw->clip.prog_data->urb_read_length;
+ clip.thread3.const_urb_entry_read_length = brw->clip.prog_data->curb_read_length;
+ clip.clip5.clip_mode = brw->clip.prog_data->clip_mode;
+
+ /* BRW_NEW_CURBE_OFFSETS */
+ clip.thread3.const_urb_entry_read_offset = brw->curbe.clip_start * 2;
+
+ /* BRW_NEW_URB_FENCE */
+ clip.thread4.nr_urb_entries = brw->urb.nr_clip_entries;
+ clip.thread4.urb_entry_allocation_size = brw->urb.vsize - 1;
+ clip.thread4.max_threads = 1; /* 2 threads */
+
+ if (BRW_DEBUG & DEBUG_STATS)
+ clip.thread4.stats_enable = 1;
+
+ /* CONSTANT */
+ clip.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
+ clip.thread1.single_program_flow = 1;
+ clip.thread3.dispatch_grf_start_reg = 1;
+ clip.thread3.urb_entry_read_offset = 0;
+ clip.clip5.userclip_enable_flags = 0x7f;
+ clip.clip5.userclip_must_clip = 1;
+ clip.clip5.guard_band_enable = 0;
+ clip.clip5.viewport_z_clip_enable = 1;
+ clip.clip5.viewport_xy_clip_enable = 1;
+ clip.clip5.vertex_position_space = BRW_CLIP_NDCSPACE;
+ clip.clip5.api_mode = BRW_CLIP_API_OGL;
+ clip.clip6.clipper_viewport_state_ptr = 0;
+ clip.viewport_xmin = -1;
+ clip.viewport_xmax = 1;
+ clip.viewport_ymin = -1;
+ clip.viewport_ymax = 1;
+
+ brw->clip.state_gs_offset = brw_cache_data( &brw->cache[BRW_CLIP_UNIT], &clip );
+}
+
+
+const struct brw_tracked_state brw_clip_unit = {
+ .dirty = {
+ .brw = (BRW_NEW_CURBE_OFFSETS |
+ BRW_NEW_URB_FENCE),
+ .cache = CACHE_NEW_CLIP_PROG
+ },
+ .update = upload_clip_unit
+};
diff --git a/src/gallium/drivers/i965simple/brw_clip_tri.c b/src/gallium/drivers/i965simple/brw_clip_tri.c
new file mode 100644
index 0000000000..c5da7b825e
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_clip_tri.c
@@ -0,0 +1,566 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_clip.h"
+
+static struct brw_reg get_tmp( struct brw_clip_compile *c )
+{
+ struct brw_reg tmp = brw_vec4_grf(c->last_tmp, 0);
+
+ if (++c->last_tmp > c->prog_data.total_grf)
+ c->prog_data.total_grf = c->last_tmp;
+
+ return tmp;
+}
+
+static void release_tmps( struct brw_clip_compile *c )
+{
+ c->last_tmp = c->first_tmp;
+}
+
+
+void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
+ unsigned nr_verts )
+{
+ unsigned i = 0,j;
+
+ /* Register usage is static, precompute here:
+ */
+ c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
+
+ if (c->key.nr_userclip) {
+ c->reg.fixed_planes = brw_vec4_grf(i, 0);
+ i += (6 + c->key.nr_userclip + 1) / 2;
+
+ c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
+ }
+ else
+ c->prog_data.curb_read_length = 0;
+
+
+ /* Payload vertices plus space for more generated vertices:
+ */
+ for (j = 0; j < nr_verts; j++) {
+ c->reg.vertex[j] = brw_vec4_grf(i, 0);
+ i += c->nr_regs;
+ }
+
+ if (c->nr_attrs & 1) {
+ for (j = 0; j < 3; j++) {
+ unsigned delta = c->nr_attrs*16 + 32;
+ brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
+ }
+ }
+
+ c->reg.t = brw_vec1_grf(i, 0);
+ c->reg.loopcount = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_UD);
+ c->reg.nr_verts = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD);
+ c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
+ c->reg.plane_equation = brw_vec4_grf(i, 4);
+ i++;
+
+ c->reg.dpPrev = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
+ c->reg.dp = brw_vec1_grf(i, 4);
+ i++;
+
+ c->reg.inlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
+ i++;
+
+ c->reg.outlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
+ i++;
+
+ c->reg.freelist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
+ i++;
+
+ if (!c->key.nr_userclip) {
+ c->reg.fixed_planes = brw_vec8_grf(i, 0);
+ i++;
+ }
+
+ if (c->key.do_unfilled) {
+ c->reg.dir = brw_vec4_grf(i, 0);
+ c->reg.offset = brw_vec4_grf(i, 4);
+ i++;
+ c->reg.tmp0 = brw_vec4_grf(i, 0);
+ c->reg.tmp1 = brw_vec4_grf(i, 4);
+ i++;
+ }
+
+ c->first_tmp = i;
+ c->last_tmp = i;
+
+ c->prog_data.urb_read_length = c->nr_regs; /* ? */
+ c->prog_data.total_grf = i;
+}
+
+
+
+void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
+ struct brw_instruction *is_rev;
+
+ /* Initial list of indices for incoming vertexes:
+ */
+ brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
+ brw_CMP(p,
+ vec1(brw_null_reg()),
+ BRW_CONDITIONAL_EQ,
+ tmp0,
+ brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
+
+ /* XXX: Is there an easier way to do this? Need to reverse every
+ * second tristrip element: Can ignore sometimes?
+ */
+ is_rev = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) );
+ brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) );
+ if (c->need_direction)
+ brw_MOV(p, c->reg.dir, brw_imm_f(-1));
+ }
+ is_rev = brw_ELSE(p, is_rev);
+ {
+ brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) );
+ brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) );
+ if (c->need_direction)
+ brw_MOV(p, c->reg.dir, brw_imm_f(1));
+ }
+ brw_ENDIF(p, is_rev);
+
+ brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) );
+ brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
+ brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
+}
+
+
+
+void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *is_poly;
+ struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
+
+ brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
+ brw_CMP(p,
+ vec1(brw_null_reg()),
+ BRW_CONDITIONAL_EQ,
+ tmp0,
+ brw_imm_ud(_3DPRIM_POLYGON));
+
+ is_poly = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_copy_colors(c, 1, 0);
+ brw_clip_copy_colors(c, 2, 0);
+ }
+ is_poly = brw_ELSE(p, is_poly);
+ {
+ brw_clip_copy_colors(c, 0, 2);
+ brw_clip_copy_colors(c, 1, 2);
+ }
+ brw_ENDIF(p, is_poly);
+}
+
+
+
+/* Use mesa's clipping algorithms, translated to GEN4 assembly.
+ */
+void brw_clip_tri( struct brw_clip_compile *c )
+{
+#if 0
+ struct brw_compile *p = &c->func;
+ struct brw_indirect vtx = brw_indirect(0, 0);
+ struct brw_indirect vtxPrev = brw_indirect(1, 0);
+ struct brw_indirect vtxOut = brw_indirect(2, 0);
+ struct brw_indirect plane_ptr = brw_indirect(3, 0);
+ struct brw_indirect inlist_ptr = brw_indirect(4, 0);
+ struct brw_indirect outlist_ptr = brw_indirect(5, 0);
+ struct brw_indirect freelist_ptr = brw_indirect(6, 0);
+ struct brw_instruction *plane_loop;
+ struct brw_instruction *plane_active;
+ struct brw_instruction *vertex_loop;
+ struct brw_instruction *next_test;
+ struct brw_instruction *prev_test;
+
+ brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
+ brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
+ brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
+ brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
+
+ brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
+
+ plane_loop = brw_DO(p, BRW_EXECUTE_1);
+ {
+ /* if (planemask & 1)
+ */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
+
+ plane_active = brw_IF(p, BRW_EXECUTE_1);
+ {
+ /* vtxOut = freelist_ptr++
+ */
+ brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
+ brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
+
+ if (c->key.nr_userclip)
+ brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
+ else
+ brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
+
+ brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
+ brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
+
+ vertex_loop = brw_DO(p, BRW_EXECUTE_1);
+ {
+ /* vtx = *input_ptr;
+ */
+ brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
+
+ /* IS_NEGATIVE(prev) */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
+ brw_DP4(p, vec4(c->reg.dpPrev), deref_4f(vtxPrev, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
+ prev_test = brw_IF(p, BRW_EXECUTE_1);
+ {
+ /* IS_POSITIVE(next)
+ */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_GE);
+ brw_DP4(p, vec4(c->reg.dp), deref_4f(vtx, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
+ next_test = brw_IF(p, BRW_EXECUTE_1);
+ {
+
+ /* Coming back in.
+ */
+ brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
+ brw_math_invert(p, c->reg.t, c->reg.t);
+ brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
+
+ /* If (vtxOut == 0) vtxOut = vtxPrev
+ */
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
+ brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev) );
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, FALSE);
+
+ /* *outlist_ptr++ = vtxOut;
+ * nr_verts++;
+ * vtxOut = 0;
+ */
+ brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
+ brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
+ brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
+ brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
+ }
+ brw_ENDIF(p, next_test);
+
+ }
+ prev_test = brw_ELSE(p, prev_test);
+ {
+ /* *outlist_ptr++ = vtxPrev;
+ * nr_verts++;
+ */
+ brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
+ brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
+ brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
+
+ /* IS_NEGATIVE(next)
+ */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
+ brw_DP4(p, vec4(c->reg.dp), deref_4f(vtx, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
+ next_test = brw_IF(p, BRW_EXECUTE_1);
+ {
+ /* Going out of bounds. Avoid division by zero as we
+ * know dp != dpPrev from DIFFERENT_SIGNS, above.
+ */
+ brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
+ brw_math_invert(p, c->reg.t, c->reg.t);
+ brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
+
+ /* If (vtxOut == 0) vtxOut = vtx
+ */
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
+ brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx) );
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, TRUE);
+
+ /* *outlist_ptr++ = vtxOut;
+ * nr_verts++;
+ * vtxOut = 0;
+ */
+ brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
+ brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
+ brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
+ brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
+ }
+ brw_ENDIF(p, next_test);
+ }
+ brw_ENDIF(p, prev_test);
+
+ /* vtxPrev = vtx;
+ * inlist_ptr++;
+ */
+ brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
+ brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
+
+ /* while (--loopcount != 0)
+ */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
+ }
+ brw_WHILE(p, vertex_loop);
+
+ /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
+ * inlist = outlist
+ * inlist_ptr = &inlist[0]
+ * outlist_ptr = &outlist[0]
+ */
+ brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
+ brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
+ brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
+ brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
+ brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
+ }
+ brw_ENDIF(p, plane_active);
+
+ /* plane_ptr++;
+ */
+ brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
+
+ /* nr_verts >= 3
+ */
+ brw_CMP(p,
+ vec1(brw_null_reg()),
+ BRW_CONDITIONAL_GE,
+ c->reg.nr_verts,
+ brw_imm_ud(3));
+
+ /* && (planemask>>=1) != 0
+ */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
+ }
+ brw_WHILE(p, plane_loop);
+#else
+ #warning "disabled"
+#endif
+}
+
+
+
+void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *loop, *if_insn;
+
+ /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
+ */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
+ brw_ADD(p,
+ c->reg.loopcount,
+ c->reg.nr_verts,
+ brw_imm_d(-2));
+
+ if_insn = brw_IF(p, BRW_EXECUTE_1);
+ {
+ struct brw_indirect v0 = brw_indirect(0, 0);
+ struct brw_indirect vptr = brw_indirect(1, 0);
+
+ brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
+ brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
+
+ brw_clip_emit_vue(c, v0, 1, 0, ((_3DPRIM_TRIFAN << 2) | R02_PRIM_START));
+
+ brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
+ brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
+
+ loop = brw_DO(p, BRW_EXECUTE_1);
+ {
+ brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_TRIFAN << 2));
+
+ brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
+ brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
+
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
+ }
+ brw_WHILE(p, loop);
+
+ brw_clip_emit_vue(c, v0, 0, 1, ((_3DPRIM_TRIFAN << 2) | R02_PRIM_END));
+ }
+ brw_ENDIF(p, if_insn);
+}
+
+static void do_clip_tri( struct brw_clip_compile *c )
+{
+ brw_clip_init_planes(c);
+
+ brw_clip_tri(c);
+}
+
+
+static void maybe_do_clip_tri( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *do_clip;
+
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
+ do_clip = brw_IF(p, BRW_EXECUTE_1);
+ {
+ do_clip_tri(c);
+ }
+ brw_ENDIF(p, do_clip);
+}
+
+static void brw_clip_test( struct brw_clip_compile *c )
+{
+#if 0
+ struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
+ struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
+ struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
+ struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
+
+ struct brw_reg v0 = get_tmp(c);
+ struct brw_reg v1 = get_tmp(c);
+ struct brw_reg v2 = get_tmp(c);
+
+ struct brw_indirect vt0 = brw_indirect(0, 0);
+ struct brw_indirect vt1 = brw_indirect(1, 0);
+ struct brw_indirect vt2 = brw_indirect(2, 0);
+
+ struct brw_compile *p = &c->func;
+
+ brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
+ brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
+ brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
+ brw_MOV(p, v0, deref_4f(vt0, c->offset[VERT_RESULT_HPOS]));
+ brw_MOV(p, v1, deref_4f(vt1, c->offset[VERT_RESULT_HPOS]));
+ brw_MOV(p, v2, deref_4f(vt2, c->offset[VERT_RESULT_HPOS]));
+
+ /* test nearz, xmin, ymin plane */
+ brw_CMP(p, t1, BRW_CONDITIONAL_LE, negate(v0), get_element(v0, 3));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_CMP(p, t2, BRW_CONDITIONAL_LE, negate(v1), get_element(v1, 3));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_CMP(p, t3, BRW_CONDITIONAL_LE, negate(v2), get_element(v2, 3));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_XOR(p, t, t1, t2);
+ brw_XOR(p, t1, t2, t3);
+ brw_OR(p, t, t, t1);
+
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 0), brw_imm_ud(0));
+ brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 1), brw_imm_ud(0));
+ brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 2), brw_imm_ud(0));
+ brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ /* test farz, xmax, ymax plane */
+ brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, get_element(v0, 3));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, get_element(v1, 3));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, get_element(v2, 3));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ brw_XOR(p, t, t1, t2);
+ brw_XOR(p, t1, t2, t3);
+ brw_OR(p, t, t, t1);
+
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 0), brw_imm_ud(0));
+ brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 1), brw_imm_ud(0));
+ brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 2), brw_imm_ud(0));
+ brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ release_tmps(c);
+#else
+ #warning "disabled"
+#endif
+}
+
+
+void brw_emit_tri_clip( struct brw_clip_compile *c )
+{
+ struct brw_instruction *neg_rhw;
+ struct brw_compile *p = &c->func;
+ brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
+ brw_clip_tri_init_vertices(c);
+ brw_clip_init_clipmask(c);
+
+ /* if -ve rhw workaround bit is set,
+ do cliptest */
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
+ brw_imm_ud(1<<20));
+ neg_rhw = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_test(c);
+ }
+ brw_ENDIF(p, neg_rhw);
+
+ /* Can't push into do_clip_tri because with polygon (or quad)
+ * flatshading, need to apply the flatshade here because we don't
+ * respect the PV when converting to trifan for emit:
+ */
+ if (c->key.do_flat_shading)
+ brw_clip_tri_flat_shade(c);
+
+ if (c->key.clip_mode == BRW_CLIPMODE_NORMAL)
+ do_clip_tri(c);
+ else
+ maybe_do_clip_tri(c);
+
+ brw_clip_tri_emit_polygon(c);
+
+ /* Send an empty message to kill the thread:
+ */
+ brw_clip_kill_thread(c);
+}
diff --git a/src/gallium/drivers/i965simple/brw_clip_unfilled.c b/src/gallium/drivers/i965simple/brw_clip_unfilled.c
new file mode 100644
index 0000000000..b774a76dd6
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_clip_unfilled.c
@@ -0,0 +1,477 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_clip.h"
+
+
+
+/* This is performed against the original triangles, so no indirection
+ * required:
+BZZZT!
+ */
+static void compute_tri_direction( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg e = c->reg.tmp0;
+ struct brw_reg f = c->reg.tmp1;
+ struct brw_reg v0 = byte_offset(c->reg.vertex[0], c->offset[VERT_RESULT_HPOS]);
+ struct brw_reg v1 = byte_offset(c->reg.vertex[1], c->offset[VERT_RESULT_HPOS]);
+ struct brw_reg v2 = byte_offset(c->reg.vertex[2], c->offset[VERT_RESULT_HPOS]);
+
+
+ /* Calculate the vectors of two edges of the triangle:
+ */
+ brw_ADD(p, e, v0, negate(v2));
+ brw_ADD(p, f, v1, negate(v2));
+
+ /* Take their crossproduct:
+ */
+ brw_set_access_mode(p, BRW_ALIGN_16);
+ brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, 1,2,0,3), brw_swizzle(f,2,0,1,3));
+ brw_MAC(p, vec4(e), negate(brw_swizzle(e, 2,0,1,3)), brw_swizzle(f,1,2,0,3));
+ brw_set_access_mode(p, BRW_ALIGN_1);
+
+ brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e));
+}
+
+
+static void cull_direction( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *ccw;
+ unsigned conditional;
+
+ assert (!(c->key.fill_ccw == CLIP_CULL &&
+ c->key.fill_cw == CLIP_CULL));
+
+ if (c->key.fill_ccw == CLIP_CULL)
+ conditional = BRW_CONDITIONAL_GE;
+ else
+ conditional = BRW_CONDITIONAL_L;
+
+ brw_CMP(p,
+ vec1(brw_null_reg()),
+ conditional,
+ get_element(c->reg.dir, 2),
+ brw_imm_f(0));
+
+ ccw = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_kill_thread(c);
+ }
+ brw_ENDIF(p, ccw);
+}
+
+
+
+static void copy_bfc( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *ccw;
+ unsigned conditional;
+
+ /* Do we have any colors to copy?
+ */
+ if (!(c->offset[VERT_RESULT_COL0] && c->offset[VERT_RESULT_BFC0]) &&
+ !(c->offset[VERT_RESULT_COL1] && c->offset[VERT_RESULT_BFC1]))
+ return;
+
+ /* In some wierd degnerate cases we can end up testing the
+ * direction twice, once for culling and once for bfc copying. Oh
+ * well, that's what you get for setting wierd GL state.
+ */
+ if (c->key.copy_bfc_ccw)
+ conditional = BRW_CONDITIONAL_GE;
+ else
+ conditional = BRW_CONDITIONAL_L;
+
+ brw_CMP(p,
+ vec1(brw_null_reg()),
+ conditional,
+ get_element(c->reg.dir, 2),
+ brw_imm_f(0));
+
+ ccw = brw_IF(p, BRW_EXECUTE_1);
+ {
+ unsigned i;
+
+ for (i = 0; i < 3; i++) {
+ if (c->offset[VERT_RESULT_COL0] && c->offset[VERT_RESULT_BFC0])
+ brw_MOV(p,
+ byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_COL0]),
+ byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_BFC0]));
+
+ if (c->offset[VERT_RESULT_COL1] && c->offset[VERT_RESULT_BFC1])
+ brw_MOV(p,
+ byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_COL1]),
+ byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_BFC1]));
+ }
+ }
+ brw_ENDIF(p, ccw);
+}
+
+
+
+
+/*
+ float iz = 1.0 / dir.z;
+ float ac = dir.x * iz;
+ float bc = dir.y * iz;
+ offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
+ offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor;
+ offset *= MRD;
+*/
+static void compute_offset( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg off = c->reg.offset;
+ struct brw_reg dir = c->reg.dir;
+
+ brw_math_invert(p, get_element(off, 2), get_element(dir, 2));
+ brw_MUL(p, vec2(off), dir, get_element(off, 2));
+
+ brw_CMP(p,
+ vec1(brw_null_reg()),
+ BRW_CONDITIONAL_GE,
+ brw_abs(get_element(off, 0)),
+ brw_abs(get_element(off, 1)));
+
+ brw_SEL(p, vec1(off), brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1)));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ brw_MUL(p, vec1(off), off, brw_imm_f(c->key.offset_factor));
+ brw_ADD(p, vec1(off), off, brw_imm_f(c->key.offset_units));
+}
+
+
+static void merge_edgeflags( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *is_poly;
+ struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);
+
+ brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
+ brw_CMP(p,
+ vec1(brw_null_reg()),
+ BRW_CONDITIONAL_EQ,
+ tmp0,
+ brw_imm_ud(_3DPRIM_POLYGON));
+
+ /* Get away with using reg.vertex because we know that this is not
+ * a _3DPRIM_TRISTRIP_REVERSE:
+ */
+ is_poly = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ);
+ brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));
+ brw_MOV(p, byte_offset(c->reg.vertex[0], c->offset[VERT_RESULT_EDGE]), brw_imm_f(0));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ);
+ brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));
+ brw_MOV(p, byte_offset(c->reg.vertex[2], c->offset[VERT_RESULT_EDGE]), brw_imm_f(0));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ }
+ brw_ENDIF(p, is_poly);
+}
+
+
+
+static void apply_one_offset( struct brw_clip_compile *c,
+ struct brw_indirect vert )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg pos = deref_4f(vert, c->offset[VERT_RESULT_HPOS]);
+ struct brw_reg z = get_element(pos, 2);
+
+ brw_ADD(p, z, z, vec1(c->reg.offset));
+}
+
+
+
+/***********************************************************************
+ * Output clipped polygon as an unfilled primitive:
+ */
+static void emit_lines(struct brw_clip_compile *c,
+ boolean do_offset)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *loop;
+ struct brw_instruction *draw_edge;
+ struct brw_indirect v0 = brw_indirect(0, 0);
+ struct brw_indirect v1 = brw_indirect(1, 0);
+ struct brw_indirect v0ptr = brw_indirect(2, 0);
+ struct brw_indirect v1ptr = brw_indirect(3, 0);
+
+ /* Need a seperate loop for offset:
+ */
+ if (do_offset) {
+ brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
+ brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
+
+ loop = brw_DO(p, BRW_EXECUTE_1);
+ {
+ brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
+ brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
+
+ apply_one_offset(c, v0);
+
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
+ brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
+ }
+ brw_WHILE(p, loop);
+ }
+
+ /* v1ptr = &inlist[nr_verts]
+ * *v1ptr = v0
+ */
+ brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
+ brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
+ brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
+ brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
+ brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));
+
+ loop = brw_DO(p, BRW_EXECUTE_1);
+ {
+ brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
+ brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
+ brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
+
+ /* draw edge if edgeflag != 0 */
+ brw_CMP(p,
+ vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
+ deref_1f(v0, c->offset[VERT_RESULT_EDGE]),
+ brw_imm_f(0));
+ draw_edge = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_START);
+ brw_clip_emit_vue(c, v1, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_END);
+ }
+ brw_ENDIF(p, draw_edge);
+
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
+ }
+ brw_WHILE(p, loop);
+}
+
+
+
+static void emit_points(struct brw_clip_compile *c,
+ boolean do_offset )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *loop;
+ struct brw_instruction *draw_point;
+
+ struct brw_indirect v0 = brw_indirect(0, 0);
+ struct brw_indirect v0ptr = brw_indirect(2, 0);
+
+ brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
+ brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
+
+ loop = brw_DO(p, BRW_EXECUTE_1);
+ {
+ brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
+ brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
+
+ /* draw if edgeflag != 0
+ */
+ brw_CMP(p,
+ vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
+ deref_1f(v0, c->offset[VERT_RESULT_EDGE]),
+ brw_imm_f(0));
+ draw_point = brw_IF(p, BRW_EXECUTE_1);
+ {
+ if (do_offset)
+ apply_one_offset(c, v0);
+
+ brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_POINTLIST << 2) | R02_PRIM_START | R02_PRIM_END);
+ }
+ brw_ENDIF(p, draw_point);
+
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
+ }
+ brw_WHILE(p, loop);
+}
+
+
+
+
+
+
+
+static void emit_primitives( struct brw_clip_compile *c,
+ unsigned mode,
+ boolean do_offset )
+{
+ switch (mode) {
+ case CLIP_FILL:
+ brw_clip_tri_emit_polygon(c);
+ break;
+
+ case CLIP_LINE:
+ emit_lines(c, do_offset);
+ break;
+
+ case CLIP_POINT:
+ emit_points(c, do_offset);
+ break;
+
+ case CLIP_CULL:
+ assert(0);
+ break;
+ }
+}
+
+
+
+static void emit_unfilled_primitives( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *ccw;
+
+ /* Direction culling has already been done.
+ */
+ if (c->key.fill_ccw != c->key.fill_cw &&
+ c->key.fill_ccw != CLIP_CULL &&
+ c->key.fill_cw != CLIP_CULL)
+ {
+ brw_CMP(p,
+ vec1(brw_null_reg()),
+ BRW_CONDITIONAL_GE,
+ get_element(c->reg.dir, 2),
+ brw_imm_f(0));
+
+ ccw = brw_IF(p, BRW_EXECUTE_1);
+ {
+ emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
+ }
+ ccw = brw_ELSE(p, ccw);
+ {
+ emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
+ }
+ brw_ENDIF(p, ccw);
+ }
+ else if (c->key.fill_cw != CLIP_CULL) {
+ emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
+ }
+ else if (c->key.fill_ccw != CLIP_CULL) {
+ emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
+ }
+}
+
+
+
+
+static void check_nr_verts( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *if_insn;
+
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3));
+ if_insn = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_kill_thread(c);
+ }
+ brw_ENDIF(p, if_insn);
+}
+
+
+void brw_emit_unfilled_clip( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *do_clip;
+
+
+ c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) ||
+ (c->key.fill_ccw != c->key.fill_cw) ||
+ c->key.fill_ccw == CLIP_CULL ||
+ c->key.fill_cw == CLIP_CULL ||
+ c->key.copy_bfc_cw ||
+ c->key.copy_bfc_ccw);
+
+ brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
+ brw_clip_tri_init_vertices(c);
+
+ assert(c->offset[VERT_RESULT_EDGE]);
+
+ if (c->key.fill_ccw == CLIP_CULL &&
+ c->key.fill_cw == CLIP_CULL) {
+ brw_clip_kill_thread(c);
+ return;
+ }
+
+ merge_edgeflags(c);
+
+ /* Need to use the inlist indirection here:
+ */
+ if (c->need_direction)
+ compute_tri_direction(c);
+
+ if (c->key.fill_ccw == CLIP_CULL ||
+ c->key.fill_cw == CLIP_CULL)
+ cull_direction(c);
+
+ if (c->key.offset_ccw ||
+ c->key.offset_cw)
+ compute_offset(c);
+
+ if (c->key.copy_bfc_ccw ||
+ c->key.copy_bfc_cw)
+ copy_bfc(c);
+
+ /* Need to do this whether we clip or not:
+ */
+ if (c->key.do_flat_shading)
+ brw_clip_tri_flat_shade(c);
+
+ brw_clip_init_clipmask(c);
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
+ do_clip = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_init_planes(c);
+ brw_clip_tri(c);
+ check_nr_verts(c);
+ }
+ brw_ENDIF(p, do_clip);
+
+ emit_unfilled_primitives(c);
+ brw_clip_kill_thread(c);
+}
+
+
+
diff --git a/src/gallium/drivers/i965simple/brw_clip_util.c b/src/gallium/drivers/i965simple/brw_clip_util.c
new file mode 100644
index 0000000000..6d58ceafff
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_clip_util.c
@@ -0,0 +1,351 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_clip.h"
+
+
+
+
+
+static struct brw_reg get_tmp( struct brw_clip_compile *c )
+{
+ struct brw_reg tmp = brw_vec4_grf(c->last_tmp, 0);
+
+ if (++c->last_tmp > c->prog_data.total_grf)
+ c->prog_data.total_grf = c->last_tmp;
+
+ return tmp;
+}
+
+static void release_tmp( struct brw_clip_compile *c, struct brw_reg tmp )
+{
+ if (tmp.nr == c->last_tmp-1)
+ c->last_tmp--;
+}
+
+
+static struct brw_reg make_plane_ud(unsigned x, unsigned y, unsigned z, unsigned w)
+{
+ return brw_imm_ud((w<<24) | (z<<16) | (y<<8) | x);
+}
+
+
+void brw_clip_init_planes( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+
+ if (!c->key.nr_userclip) {
+ brw_MOV(p, get_element_ud(c->reg.fixed_planes, 0), make_plane_ud( 0, 0, 0xff, 1));
+ brw_MOV(p, get_element_ud(c->reg.fixed_planes, 1), make_plane_ud( 0, 0, 1, 1));
+ brw_MOV(p, get_element_ud(c->reg.fixed_planes, 2), make_plane_ud( 0, 0xff, 0, 1));
+ brw_MOV(p, get_element_ud(c->reg.fixed_planes, 3), make_plane_ud( 0, 1, 0, 1));
+ brw_MOV(p, get_element_ud(c->reg.fixed_planes, 4), make_plane_ud(0xff, 0, 0, 1));
+ brw_MOV(p, get_element_ud(c->reg.fixed_planes, 5), make_plane_ud( 1, 0, 0, 1));
+ }
+}
+
+
+
+#define W 3
+
+/* Project 'pos' to screen space (or back again), overwrite with results:
+ */
+static void brw_clip_project_position(struct brw_clip_compile *c, struct brw_reg pos )
+{
+ struct brw_compile *p = &c->func;
+
+ /* calc rhw
+ */
+ brw_math_invert(p, get_element(pos, W), get_element(pos, W));
+
+ /* value.xyz *= value.rhw
+ */
+ brw_set_access_mode(p, BRW_ALIGN_16);
+ brw_MUL(p, brw_writemask(pos, TGSI_WRITEMASK_XYZ), pos, brw_swizzle1(pos, W));
+ brw_set_access_mode(p, BRW_ALIGN_1);
+}
+
+
+static void brw_clip_project_vertex( struct brw_clip_compile *c,
+ struct brw_indirect vert_addr )
+{
+#if 0
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp = get_tmp(c);
+
+ /* Fixup position. Extract from the original vertex and re-project
+ * to screen space:
+ */
+ brw_MOV(p, tmp, deref_4f(vert_addr, c->offset[VERT_RESULT_HPOS]));
+ brw_clip_project_position(c, tmp);
+ brw_MOV(p, deref_4f(vert_addr, c->header_position_offset), tmp);
+
+ release_tmp(c, tmp);
+#else
+ #warning "disabled"
+#endif
+}
+
+
+
+
+/* Interpolate between two vertices and put the result into a0.0.
+ * Increment a0.0 accordingly.
+ */
+void brw_clip_interp_vertex( struct brw_clip_compile *c,
+ struct brw_indirect dest_ptr,
+ struct brw_indirect v0_ptr, /* from */
+ struct brw_indirect v1_ptr, /* to */
+ struct brw_reg t0,
+ boolean force_edgeflag)
+{
+#if 0
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp = get_tmp(c);
+ unsigned i;
+
+ /* Just copy the vertex header:
+ */
+ brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);
+
+ /* Iterate over each attribute (could be done in pairs?)
+ */
+ for (i = 0; i < c->nr_attrs; i++) {
+ unsigned delta = i*16 + 32;
+
+ if (delta == c->offset[VERT_RESULT_EDGE]) {
+ if (force_edgeflag)
+ brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
+ else
+ brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta));
+ }
+ else {
+ /* Interpolate:
+ *
+ * New = attr0 + t*attr1 - t*attr0
+ */
+ brw_MUL(p,
+ vec4(brw_null_reg()),
+ deref_4f(v1_ptr, delta),
+ t0);
+
+ brw_MAC(p,
+ tmp,
+ negate(deref_4f(v0_ptr, delta)),
+ t0);
+
+ brw_ADD(p,
+ deref_4f(dest_ptr, delta),
+ deref_4f(v0_ptr, delta),
+ tmp);
+ }
+ }
+
+ if (i & 1) {
+ unsigned delta = i*16 + 32;
+ brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
+ }
+
+ release_tmp(c, tmp);
+
+ /* Recreate the projected (NDC) coordinate in the new vertex
+ * header:
+ */
+ brw_clip_project_vertex(c, dest_ptr );
+#else
+ #warning "disabled"
+#endif
+}
+
+
+
+
+#define MAX_MRF 16
+
+void brw_clip_emit_vue(struct brw_clip_compile *c,
+ struct brw_indirect vert,
+ boolean allocate,
+ boolean eot,
+ unsigned header)
+{
+ struct brw_compile *p = &c->func;
+ unsigned start = c->last_mrf;
+
+ assert(!(allocate && eot));
+
+ /* Cycle through mrf regs - probably futile as we have to wait for
+ * the allocation response anyway. Also, the order this function
+ * is invoked doesn't correspond to the order the instructions will
+ * be executed, so it won't have any effect in many cases.
+ */
+#if 0
+ if (start + c->nr_regs + 1 >= MAX_MRF)
+ start = 0;
+
+ c->last_mrf = start + c->nr_regs + 1;
+#endif
+
+ /* Copy the vertex from vertn into m1..mN+1:
+ */
+ brw_copy_from_indirect(p, brw_message_reg(start+1), vert, c->nr_regs);
+
+ /* Overwrite PrimType and PrimStart in the message header, for
+ * each vertex in turn:
+ */
+ brw_MOV(p, get_element_ud(c->reg.R0, 2), brw_imm_ud(header));
+
+
+ /* Send each vertex as a seperate write to the urb. This
+ * is different to the concept in brw_sf_emit.c, where
+ * subsequent writes are used to build up a single urb
+ * entry. Each of these writes instantiates a seperate
+ * urb entry - (I think... what about 'allocate'?)
+ */
+ brw_urb_WRITE(p,
+ allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
+ start,
+ c->reg.R0,
+ allocate,
+ 1, /* used */
+ c->nr_regs + 1, /* msg length */
+ allocate ? 1 : 0, /* response_length */
+ eot, /* eot */
+ 1, /* writes_complete */
+ 0, /* urb offset */
+ BRW_URB_SWIZZLE_NONE);
+}
+
+
+
+void brw_clip_kill_thread(struct brw_clip_compile *c)
+{
+ struct brw_compile *p = &c->func;
+
+ /* Send an empty message to kill the thread and release any
+ * allocated urb entry:
+ */
+ brw_urb_WRITE(p,
+ retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
+ 0,
+ c->reg.R0,
+ 0, /* allocate */
+ 0, /* used */
+ 0, /* msg len */
+ 0, /* response len */
+ 1, /* eot */
+ 1, /* writes complete */
+ 0,
+ BRW_URB_SWIZZLE_NONE);
+}
+
+
+
+
+struct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c )
+{
+ return brw_address(c->reg.fixed_planes);
+}
+
+
+struct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c )
+{
+ if (c->key.nr_userclip) {
+ return brw_imm_uw(16);
+ }
+ else {
+ return brw_imm_uw(4);
+ }
+}
+
+
+/* If flatshading, distribute color from provoking vertex prior to
+ * clipping.
+ */
+void brw_clip_copy_colors( struct brw_clip_compile *c,
+ unsigned to, unsigned from )
+{
+#if 0
+ struct brw_compile *p = &c->func;
+
+ if (c->offset[VERT_RESULT_COL0])
+ brw_MOV(p,
+ byte_offset(c->reg.vertex[to], c->offset[VERT_RESULT_COL0]),
+ byte_offset(c->reg.vertex[from], c->offset[VERT_RESULT_COL0]));
+
+ if (c->offset[VERT_RESULT_COL1])
+ brw_MOV(p,
+ byte_offset(c->reg.vertex[to], c->offset[VERT_RESULT_COL1]),
+ byte_offset(c->reg.vertex[from], c->offset[VERT_RESULT_COL1]));
+
+ if (c->offset[VERT_RESULT_BFC0])
+ brw_MOV(p,
+ byte_offset(c->reg.vertex[to], c->offset[VERT_RESULT_BFC0]),
+ byte_offset(c->reg.vertex[from], c->offset[VERT_RESULT_BFC0]));
+
+ if (c->offset[VERT_RESULT_BFC1])
+ brw_MOV(p,
+ byte_offset(c->reg.vertex[to], c->offset[VERT_RESULT_BFC1]),
+ byte_offset(c->reg.vertex[from], c->offset[VERT_RESULT_BFC1]));
+#else
+ #warning "disabled"
+#endif
+}
+
+
+
+void brw_clip_init_clipmask( struct brw_clip_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg incoming = get_element_ud(c->reg.R0, 2);
+
+ /* Shift so that lowest outcode bit is rightmost:
+ */
+ brw_SHR(p, c->reg.planemask, incoming, brw_imm_ud(26));
+
+ if (c->key.nr_userclip) {
+ struct brw_reg tmp = retype(vec1(get_tmp(c)), BRW_REGISTER_TYPE_UD);
+
+ /* Rearrange userclip outcodes so that they come directly after
+ * the fixed plane bits.
+ */
+ brw_AND(p, tmp, incoming, brw_imm_ud(0x3f<<14));
+ brw_SHR(p, tmp, tmp, brw_imm_ud(8));
+ brw_OR(p, c->reg.planemask, c->reg.planemask, tmp);
+
+ release_tmp(c, tmp);
+ }
+}
+
diff --git a/src/gallium/drivers/i965simple/brw_context.c b/src/gallium/drivers/i965simple/brw_context.c
new file mode 100644
index 0000000000..9b33285bc7
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_context.c
@@ -0,0 +1,139 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_defines.h"
+#include "brw_draw.h"
+#include "brw_vs.h"
+#include "brw_tex_layout.h"
+#include "brw_winsys.h"
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_context.h"
+#include "util/u_memory.h"
+#include "pipe/p_screen.h"
+
+
+#ifndef BRW_DEBUG
+int BRW_DEBUG = (0);
+#endif
+
+
+static void brw_destroy(struct pipe_context *pipe)
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ if(brw->winsys->destroy)
+ brw->winsys->destroy(brw->winsys);
+
+ FREE(brw);
+}
+
+
+static void brw_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+ unsigned clearValue)
+{
+ int x, y, w, h;
+ /* FIXME: corny... */
+
+ x = 0;
+ y = 0;
+ w = ps->width;
+ h = ps->height;
+
+ pipe->surface_fill(pipe, ps, x, y, w, h, clearValue);
+}
+
+static unsigned int
+brw_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static unsigned int
+brw_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+struct pipe_context *brw_create(struct pipe_screen *screen,
+ struct brw_winsys *brw_winsys,
+ unsigned pci_id)
+{
+ struct brw_context *brw;
+
+ debug_printf("%s: creating brw_context with pci id 0x%x\n",
+ __FUNCTION__, pci_id);
+
+ brw = CALLOC_STRUCT(brw_context);
+ if (brw == NULL)
+ return NULL;
+
+ brw->winsys = brw_winsys;
+ brw->pipe.winsys = screen->winsys;
+ brw->pipe.screen = screen;
+
+ brw->pipe.destroy = brw_destroy;
+ brw->pipe.clear = brw_clear;
+
+ brw->pipe.is_texture_referenced = brw_is_texture_referenced;
+ brw->pipe.is_buffer_referenced = brw_is_buffer_referenced;
+
+ brw_init_surface_functions(brw);
+ brw_init_texture_functions(brw);
+ brw_init_state_functions(brw);
+ brw_init_flush_functions(brw);
+ brw_init_draw_functions( brw );
+
+
+ brw_init_state( brw );
+
+ brw->pci_id = pci_id;
+ brw->dirty = ~0;
+ brw->hardware_dirty = ~0;
+
+ memset(&brw->wm.bind, ~0, sizeof(brw->wm.bind));
+
+ return &brw->pipe;
+}
+
diff --git a/src/gallium/drivers/i965simple/brw_context.h b/src/gallium/drivers/i965simple/brw_context.h
new file mode 100644
index 0000000000..3079485180
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_context.h
@@ -0,0 +1,684 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRWCONTEXT_INC
+#define BRWCONTEXT_INC
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "tgsi/tgsi_scan.h"
+
+#include "brw_structs.h"
+#include "brw_winsys.h"
+
+
+/* Glossary:
+ *
+ * URB - uniform resource buffer. A mid-sized buffer which is
+ * partitioned between the fixed function units and used for passing
+ * values (vertices, primitives, constants) between them.
+ *
+ * CURBE - constant URB entry. An urb region (entry) used to hold
+ * constant values which the fixed function units can be instructed to
+ * preload into the GRF when spawining a thread.
+ *
+ * VUE - vertex URB entry. An urb entry holding a vertex and usually
+ * a vertex header. The header contains control information and
+ * things like primitive type, Begin/end flags and clip codes.
+ *
+ * PUE - primitive URB entry. An urb entry produced by the setup (SF)
+ * unit holding rasterization and interpolation parameters.
+ *
+ * GRF - general register file. One of several register files
+ * addressable by programmed threads. The inputs (r0, payload, curbe,
+ * urb) of the thread are preloaded to this area before the thread is
+ * spawned. The registers are individually 8 dwords wide and suitable
+ * for general usage. Registers holding thread input values are not
+ * special and may be overwritten.
+ *
+ * MRF - message register file. Threads communicate (and terminate)
+ * by sending messages. Message parameters are placed in contigous
+ * MRF registers. All program output is via these messages. URB
+ * entries are populated by sending a message to the shared URB
+ * function containing the new data, together with a control word,
+ * often an unmodified copy of R0.
+ *
+ * R0 - GRF register 0. Typically holds control information used when
+ * sending messages to other threads.
+ *
+ * EU or GEN4 EU: The name of the programmable subsystem of the
+ * i965 hardware. Threads are executed by the EU, the registers
+ * described above are part of the EU architecture.
+ *
+ * Fixed function units:
+ *
+ * CS - Command streamer. Notional first unit, little software
+ * interaction. Holds the URB entries used for constant data, ie the
+ * CURBEs.
+ *
+ * VF/VS - Vertex Fetch / Vertex Shader. The fixed function part of
+ * this unit is responsible for pulling vertices out of vertex buffers
+ * in vram and injecting them into the processing pipe as VUEs. If
+ * enabled, it first passes them to a VS thread which is a good place
+ * for the driver to implement any active vertex shader.
+ *
+ * GS - Geometry Shader. This corresponds to a new DX10 concept. If
+ * enabled, incoming strips etc are passed to GS threads in individual
+ * line/triangle/point units. The GS thread may perform arbitary
+ * computation and emit whatever primtives with whatever vertices it
+ * chooses. This makes GS an excellent place to implement GL's
+ * unfilled polygon modes, though of course it is capable of much
+ * more. Additionally, GS is used to translate away primitives not
+ * handled by latter units, including Quads and Lineloops.
+ *
+ * CS - Clipper. Mesa's clipping algorithms are imported to run on
+ * this unit. The fixed function part performs cliptesting against
+ * the 6 fixed clipplanes and makes descisions on whether or not the
+ * incoming primitive needs to be passed to a thread for clipping.
+ * User clip planes are handled via cooperation with the VS thread.
+ *
+ * SF - Strips Fans or Setup: Triangles are prepared for
+ * rasterization. Interpolation coefficients are calculated.
+ * Flatshading and two-side lighting usually performed here.
+ *
+ * WM - Windower. Interpolation of vertex attributes performed here.
+ * Fragment shader implemented here. SIMD aspects of EU taken full
+ * advantage of, as pixels are processed in blocks of 16.
+ *
+ * CC - Color Calculator. No EU threads associated with this unit.
+ * Handles blending and (presumably) depth and stencil testing.
+ */
+
+#define BRW_MAX_CURBE (32*16)
+
+struct brw_context;
+struct brw_winsys;
+
+
+/* Raised when we receive new state across the pipe interface:
+ */
+#define BRW_NEW_VIEWPORT 0x1
+#define BRW_NEW_RASTERIZER 0x2
+#define BRW_NEW_FS 0x4
+#define BRW_NEW_BLEND 0x8
+#define BRW_NEW_CLIP 0x10
+#define BRW_NEW_SCISSOR 0x20
+#define BRW_NEW_STIPPLE 0x40
+#define BRW_NEW_FRAMEBUFFER 0x80
+#define BRW_NEW_ALPHA_TEST 0x100
+#define BRW_NEW_DEPTH_STENCIL 0x200
+#define BRW_NEW_SAMPLER 0x400
+#define BRW_NEW_TEXTURE 0x800
+#define BRW_NEW_CONSTANTS 0x1000
+#define BRW_NEW_VBO 0x2000
+#define BRW_NEW_VS 0x4000
+
+/* Raised for other internal events:
+ */
+#define BRW_NEW_URB_FENCE 0x10000
+#define BRW_NEW_PSP 0x20000
+#define BRW_NEW_CURBE_OFFSETS 0x40000
+#define BRW_NEW_REDUCED_PRIMITIVE 0x80000
+#define BRW_NEW_PRIMITIVE 0x100000
+#define BRW_NEW_SCENE 0x200000
+#define BRW_NEW_SF_LINKAGE 0x400000
+
+extern int BRW_DEBUG;
+
+#define DEBUG_TEXTURE 0x1
+#define DEBUG_STATE 0x2
+#define DEBUG_IOCTL 0x4
+#define DEBUG_PRIMS 0x8
+#define DEBUG_VERTS 0x10
+#define DEBUG_FALLBACKS 0x20
+#define DEBUG_VERBOSE 0x40
+#define DEBUG_DRI 0x80
+#define DEBUG_DMA 0x100
+#define DEBUG_SANITY 0x200
+#define DEBUG_SYNC 0x400
+#define DEBUG_SLEEP 0x800
+#define DEBUG_PIXEL 0x1000
+#define DEBUG_STATS 0x2000
+#define DEBUG_TILE 0x4000
+#define DEBUG_SINGLE_THREAD 0x8000
+#define DEBUG_WM 0x10000
+#define DEBUG_URB 0x20000
+#define DEBUG_VS 0x40000
+#define DEBUG_BATCH 0x80000
+#define DEBUG_BUFMGR 0x100000
+#define DEBUG_BLIT 0x200000
+#define DEBUG_REGION 0x400000
+#define DEBUG_MIPTREE 0x800000
+
+#define DBG(...) do { \
+ if (BRW_DEBUG & FILE_DEBUG_FLAG) \
+ debug_printf(__VA_ARGS__); \
+} while(0)
+
+#define PRINT(...) do { \
+ debug_printf(__VA_ARGS__); \
+} while(0)
+
+struct brw_state_flags {
+ unsigned cache;
+ unsigned brw;
+};
+
+
+struct brw_vertex_program {
+ struct pipe_shader_state program;
+ struct tgsi_shader_info info;
+ int id;
+};
+
+
+struct brw_fragment_program {
+ struct pipe_shader_state program;
+ struct tgsi_shader_info info;
+
+ boolean UsesDepth; /* XXX add this to tgsi_shader_info? */
+ int id;
+};
+
+
+struct pipe_setup_linkage {
+ struct {
+ unsigned vp_output:5;
+ unsigned interp_mode:4;
+ unsigned bf_vp_output:5;
+ } fp_input[PIPE_MAX_SHADER_INPUTS];
+
+ unsigned fp_input_count:5;
+ unsigned max_vp_output:5;
+};
+
+
+
+struct brw_texture {
+ struct pipe_texture base;
+
+ /* Derived from the above:
+ */
+ unsigned stride;
+ unsigned depth_pitch; /* per-image on i945? */
+ unsigned total_nblocksy;
+
+ unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS];
+
+ /* Explicitly store the offset of each image for each cube face or
+ * depth value. Pretty much have to accept that hardware formats
+ * are going to be so diverse that there is no unified way to
+ * compute the offsets of depth/cube images within a mipmap level,
+ * so have to store them as a lookup table:
+ */
+ unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS]; /**< array [depth] of offsets */
+
+ /* Includes image offset tables:
+ */
+ unsigned level_offset[PIPE_MAX_TEXTURE_LEVELS];
+
+ /* The data is held here:
+ */
+ struct pipe_buffer *buffer;
+};
+
+/* Data about a particular attempt to compile a program. Note that
+ * there can be many of these, each in a different GL state
+ * corresponding to a different brw_wm_prog_key struct, with different
+ * compiled programs:
+ */
+/* Data about a particular attempt to compile a program. Note that
+ * there can be many of these, each in a different GL state
+ * corresponding to a different brw_wm_prog_key struct, with different
+ * compiled programs:
+ */
+
+struct brw_wm_prog_data {
+ unsigned curb_read_length;
+ unsigned urb_read_length;
+
+ unsigned first_curbe_grf;
+ unsigned total_grf;
+ unsigned total_scratch;
+
+ /* Internally generated constants for the CURBE. These are loaded
+ * ahead of the data from the constant buffer.
+ */
+ const float internal_const[8];
+ unsigned nr_internal_consts;
+ unsigned max_const;
+
+ boolean error;
+};
+
+struct brw_sf_prog_data {
+ unsigned urb_read_length;
+ unsigned total_grf;
+
+ /* Each vertex may have upto 12 attributes, 4 components each,
+ * except WPOS which requires only 2. (11*4 + 2) == 44 ==> 11
+ * rows.
+ *
+ * Actually we use 4 for each, so call it 12 rows.
+ */
+ unsigned urb_entry_size;
+};
+
+struct brw_clip_prog_data {
+ unsigned curb_read_length; /* user planes? */
+ unsigned clip_mode;
+ unsigned urb_read_length;
+ unsigned total_grf;
+};
+
+struct brw_gs_prog_data {
+ unsigned urb_read_length;
+ unsigned total_grf;
+};
+
+struct brw_vs_prog_data {
+ unsigned curb_read_length;
+ unsigned urb_read_length;
+ unsigned total_grf;
+ unsigned outputs_written;
+
+ unsigned inputs_read;
+
+ unsigned max_const;
+
+ float imm_buf[PIPE_MAX_CONSTANT][4];
+ unsigned num_imm;
+ unsigned num_consts;
+
+ /* Used for calculating urb partitions:
+ */
+ unsigned urb_entry_size;
+};
+
+
+#define BRW_MAX_TEX_UNIT 8
+#define BRW_WM_MAX_SURF BRW_MAX_TEX_UNIT + 1
+
+/* Create a fixed sized struct for caching binding tables:
+ */
+struct brw_surface_binding_table {
+ unsigned surf_ss_offset[BRW_WM_MAX_SURF];
+};
+
+
+struct brw_cache;
+
+struct brw_mem_pool {
+ struct pipe_buffer *buffer;
+
+ unsigned size;
+ unsigned offset; /* offset of first free byte */
+
+ struct brw_context *brw;
+};
+
+struct brw_cache_item {
+ unsigned hash;
+ unsigned key_size; /* for variable-sized keys */
+ const void *key;
+
+ unsigned offset; /* offset within pool's buffer */
+ unsigned data_size;
+
+ struct brw_cache_item *next;
+};
+
+
+
+struct brw_cache {
+ unsigned id;
+
+ const char *name;
+
+ struct brw_context *brw;
+ struct brw_mem_pool *pool;
+
+ struct brw_cache_item **items;
+ unsigned size, n_items;
+
+ unsigned key_size; /* for fixed-size keys */
+ unsigned aux_size;
+
+ unsigned last_addr; /* offset of active item */
+};
+
+
+
+
+/* Considered adding a member to this struct to document which flags
+ * an update might raise so that ordering of the state atoms can be
+ * checked or derived at runtime. Dropped the idea in favor of having
+ * a debug mode where the state is monitored for flags which are
+ * raised that have already been tested against.
+ */
+struct brw_tracked_state {
+ struct brw_state_flags dirty;
+ void (*update)( struct brw_context *brw );
+};
+
+
+/* Flags for brw->state.cache.
+ */
+#define CACHE_NEW_CC_VP (1<<BRW_CC_VP)
+#define CACHE_NEW_CC_UNIT (1<<BRW_CC_UNIT)
+#define CACHE_NEW_WM_PROG (1<<BRW_WM_PROG)
+#define CACHE_NEW_SAMPLER_DEFAULT_COLOR (1<<BRW_SAMPLER_DEFAULT_COLOR)
+#define CACHE_NEW_SAMPLER (1<<BRW_SAMPLER)
+#define CACHE_NEW_WM_UNIT (1<<BRW_WM_UNIT)
+#define CACHE_NEW_SF_PROG (1<<BRW_SF_PROG)
+#define CACHE_NEW_SF_VP (1<<BRW_SF_VP)
+#define CACHE_NEW_SF_UNIT (1<<BRW_SF_UNIT)
+#define CACHE_NEW_VS_UNIT (1<<BRW_VS_UNIT)
+#define CACHE_NEW_VS_PROG (1<<BRW_VS_PROG)
+#define CACHE_NEW_GS_UNIT (1<<BRW_GS_UNIT)
+#define CACHE_NEW_GS_PROG (1<<BRW_GS_PROG)
+#define CACHE_NEW_CLIP_VP (1<<BRW_CLIP_VP)
+#define CACHE_NEW_CLIP_UNIT (1<<BRW_CLIP_UNIT)
+#define CACHE_NEW_CLIP_PROG (1<<BRW_CLIP_PROG)
+#define CACHE_NEW_SURFACE (1<<BRW_SS_SURFACE)
+#define CACHE_NEW_SURF_BIND (1<<BRW_SS_SURF_BIND)
+
+
+
+
+enum brw_mempool_id {
+ BRW_GS_POOL,
+ BRW_SS_POOL,
+ BRW_MAX_POOL
+};
+
+
+struct brw_cached_batch_item {
+ struct header *header;
+ unsigned sz;
+ struct brw_cached_batch_item *next;
+};
+
+
+
+/* Protect against a future where PIPE_MAX_ATTRIBS > 32. Wouldn't life
+ * be easier if C allowed arrays of packed elements?
+ */
+#define ATTRIB_BIT_DWORDS ((PIPE_MAX_ATTRIBS+31)/32)
+
+
+
+
+struct brw_vertex_info {
+ unsigned varying; /* varying:1[PIPE_MAX_ATTRIBS] */
+ unsigned sizes[ATTRIB_BIT_DWORDS * 2]; /* sizes:2[PIPE_MAX_ATTRIBS] */
+};
+
+
+
+
+
+struct brw_context
+{
+ struct pipe_context pipe;
+ struct brw_winsys *winsys;
+
+ unsigned primitive;
+ unsigned reduced_primitive;
+
+ boolean emit_state_always;
+
+ struct {
+ struct brw_state_flags dirty;
+ } state;
+
+
+ struct {
+ const struct pipe_blend_state *Blend;
+ const struct pipe_depth_stencil_alpha_state *DepthStencil;
+ const struct pipe_poly_stipple *PolygonStipple;
+ const struct pipe_rasterizer_state *Raster;
+ const struct pipe_sampler_state *Samplers[PIPE_MAX_SAMPLERS];
+ const struct brw_vertex_program *VertexProgram;
+ const struct brw_fragment_program *FragmentProgram;
+
+ struct pipe_clip_state Clip;
+ struct pipe_blend_color BlendColor;
+ struct pipe_scissor_state Scissor;
+ struct pipe_viewport_state Viewport;
+ struct pipe_framebuffer_state FrameBuffer;
+
+ const struct pipe_constant_buffer *Constants[2];
+ const struct brw_texture *Texture[PIPE_MAX_SAMPLERS];
+ } attribs;
+
+ unsigned num_samplers;
+ unsigned num_textures;
+
+ struct brw_mem_pool pool[BRW_MAX_POOL];
+ struct brw_cache cache[BRW_MAX_CACHE];
+ struct brw_cached_batch_item *cached_batch_items;
+
+ struct {
+
+ /* Arrays with buffer objects to copy non-bufferobj arrays into
+ * for upload:
+ */
+ const struct pipe_vertex_buffer *vbo_array[PIPE_MAX_ATTRIBS];
+
+ struct brw_vertex_element_state inputs[PIPE_MAX_ATTRIBS];
+
+#define BRW_NR_UPLOAD_BUFS 17
+#define BRW_UPLOAD_INIT_SIZE (128*1024)
+
+ /* Summary of size and varying of active arrays, so we can check
+ * for changes to this state:
+ */
+ struct brw_vertex_info info;
+ } vb;
+
+
+ unsigned hardware_dirty;
+ unsigned dirty;
+ unsigned pci_id;
+ /* BRW_NEW_URB_ALLOCATIONS:
+ */
+ struct {
+ unsigned vsize; /* vertex size plus header in urb registers */
+ unsigned csize; /* constant buffer size in urb registers */
+ unsigned sfsize; /* setup data size in urb registers */
+
+ boolean constrained;
+
+ unsigned nr_vs_entries;
+ unsigned nr_gs_entries;
+ unsigned nr_clip_entries;
+ unsigned nr_sf_entries;
+ unsigned nr_cs_entries;
+
+/* unsigned vs_size; */
+/* unsigned gs_size; */
+/* unsigned clip_size; */
+/* unsigned sf_size; */
+/* unsigned cs_size; */
+
+ unsigned vs_start;
+ unsigned gs_start;
+ unsigned clip_start;
+ unsigned sf_start;
+ unsigned cs_start;
+ } urb;
+
+
+ /* BRW_NEW_CURBE_OFFSETS:
+ */
+ struct {
+ unsigned wm_start;
+ unsigned wm_size;
+ unsigned clip_start;
+ unsigned clip_size;
+ unsigned vs_start;
+ unsigned vs_size;
+ unsigned total_size;
+
+ unsigned gs_offset;
+
+ float *last_buf;
+ unsigned last_bufsz;
+ } curbe;
+
+ struct {
+ struct brw_vs_prog_data *prog_data;
+
+ unsigned prog_gs_offset;
+ unsigned state_gs_offset;
+ } vs;
+
+ struct {
+ struct brw_gs_prog_data *prog_data;
+
+ boolean prog_active;
+ unsigned prog_gs_offset;
+ unsigned state_gs_offset;
+ } gs;
+
+ struct {
+ struct brw_clip_prog_data *prog_data;
+
+ unsigned prog_gs_offset;
+ unsigned vp_gs_offset;
+ unsigned state_gs_offset;
+ } clip;
+
+
+ struct {
+ struct brw_sf_prog_data *prog_data;
+
+ struct pipe_setup_linkage linkage;
+
+ unsigned prog_gs_offset;
+ unsigned vp_gs_offset;
+ unsigned state_gs_offset;
+ } sf;
+
+ struct {
+ struct brw_wm_prog_data *prog_data;
+
+// struct brw_wm_compiler *compile_data;
+
+
+ /**
+ * Array of sampler state uploaded at sampler_gs_offset of BRW_SAMPLER
+ * cache
+ */
+ struct brw_sampler_state sampler[BRW_MAX_TEX_UNIT];
+
+ unsigned render_surf;
+ unsigned nr_surfaces;
+
+ unsigned max_threads;
+ struct pipe_buffer *scratch_buffer;
+ unsigned scratch_buffer_size;
+
+ unsigned sampler_count;
+ unsigned sampler_gs_offset;
+
+ struct brw_surface_binding_table bind;
+ unsigned bind_ss_offset;
+
+ unsigned prog_gs_offset;
+ unsigned state_gs_offset;
+ } wm;
+
+
+ struct {
+ unsigned vp_gs_offset;
+ unsigned state_gs_offset;
+ } cc;
+
+
+ /* Used to give every program string a unique id
+ */
+ unsigned program_id;
+};
+
+
+#define BRW_PACKCOLOR8888(r,g,b,a) ((r<<24) | (g<<16) | (b<<8) | a)
+
+
+/*======================================================================
+ * brw_vtbl.c
+ */
+void brw_do_flush( struct brw_context *brw,
+ unsigned flags );
+
+
+/*======================================================================
+ * brw_state.c
+ */
+void brw_validate_state(struct brw_context *brw);
+void brw_init_state(struct brw_context *brw);
+void brw_destroy_state(struct brw_context *brw);
+
+
+/*======================================================================
+ * brw_tex.c
+ */
+void brwUpdateTextureState( struct brw_context *brw );
+
+
+/* brw_urb.c
+ */
+void brw_upload_urb_fence(struct brw_context *brw);
+
+void brw_upload_constant_buffer_state(struct brw_context *brw);
+
+void brw_init_surface_functions(struct brw_context *brw);
+void brw_init_state_functions(struct brw_context *brw);
+void brw_init_flush_functions(struct brw_context *brw);
+void brw_init_string_functions(struct brw_context *brw);
+
+/*======================================================================
+ * Inline conversion functions. These are better-typed than the
+ * macros used previously:
+ */
+static inline struct brw_context *
+brw_context( struct pipe_context *ctx )
+{
+ return (struct brw_context *)ctx;
+}
+
+#endif
+
diff --git a/src/gallium/drivers/i965simple/brw_curbe.c b/src/gallium/drivers/i965simple/brw_curbe.c
new file mode 100644
index 0000000000..904cde8e30
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_curbe.c
@@ -0,0 +1,369 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+
+#include "brw_context.h"
+#include "brw_defines.h"
+#include "brw_state.h"
+#include "brw_batch.h"
+#include "brw_util.h"
+#include "brw_wm.h"
+#include "pipe/p_state.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#define FILE_DEBUG_FLAG DEBUG_FALLBACKS
+
+/* Partition the CURBE between the various users of constant values:
+ */
+static void calculate_curbe_offsets( struct brw_context *brw )
+{
+ /* CACHE_NEW_WM_PROG */
+ unsigned nr_fp_regs = align(brw->wm.prog_data->max_const, 16);
+
+ /* BRW_NEW_VERTEX_PROGRAM */
+ unsigned nr_vp_regs = align(brw->vs.prog_data->max_const, 16);
+ unsigned nr_clip_regs = 0;
+ unsigned total_regs;
+
+#if 0
+ /* BRW_NEW_CLIP ? */
+ if (brw->attribs.Transform->ClipPlanesEnabled) {
+ unsigned nr_planes = 6 + brw_count_bits(brw->attribs.Transform->ClipPlanesEnabled);
+ nr_clip_regs = align(nr_planes * 4, 16);
+ }
+#endif
+
+
+ total_regs = nr_fp_regs + nr_vp_regs + nr_clip_regs;
+
+ /* This can happen - what to do? Probably rather than falling
+ * back, the best thing to do is emit programs which code the
+ * constants as immediate values. Could do this either as a static
+ * cap on WM and VS, or adaptively.
+ *
+ * Unfortunately, this is currently dependent on the results of the
+ * program generation process (in the case of wm), so this would
+ * introduce the need to re-generate programs in the event of a
+ * curbe allocation failure.
+ */
+ /* Max size is 32 - just large enough to
+ * hold the 128 parameters allowed by
+ * the fragment and vertex program
+ * api's. It's not clear what happens
+ * when both VP and FP want to use 128
+ * parameters, though.
+ */
+ assert(total_regs <= 32);
+
+ /* Lazy resize:
+ */
+ if (nr_fp_regs > brw->curbe.wm_size ||
+ nr_vp_regs > brw->curbe.vs_size ||
+ nr_clip_regs != brw->curbe.clip_size ||
+ (total_regs < brw->curbe.total_size / 4 &&
+ brw->curbe.total_size > 16)) {
+
+ unsigned reg = 0;
+
+ /* Calculate a new layout:
+ */
+ reg = 0;
+ brw->curbe.wm_start = reg;
+ brw->curbe.wm_size = nr_fp_regs; reg += nr_fp_regs;
+ brw->curbe.clip_start = reg;
+ brw->curbe.clip_size = nr_clip_regs; reg += nr_clip_regs;
+ brw->curbe.vs_start = reg;
+ brw->curbe.vs_size = nr_vp_regs; reg += nr_vp_regs;
+ brw->curbe.total_size = reg;
+
+#if 0
+ if (0)
+ DBG("curbe wm %d+%d clip %d+%d vs %d+%d\n",
+ brw->curbe.wm_start,
+ brw->curbe.wm_size,
+ brw->curbe.clip_start,
+ brw->curbe.clip_size,
+ brw->curbe.vs_start,
+ brw->curbe.vs_size );
+#endif
+
+ brw->state.dirty.brw |= BRW_NEW_CURBE_OFFSETS;
+ }
+}
+
+
+const struct brw_tracked_state brw_curbe_offsets = {
+ .dirty = {
+ .brw = (BRW_NEW_CLIP |
+ BRW_NEW_VS),
+ .cache = CACHE_NEW_WM_PROG
+ },
+ .update = calculate_curbe_offsets
+};
+
+
+
+/* Define the number of curbes within CS's urb allocation. Multiple
+ * urb entries -> multiple curbes. These will be used by
+ * fixed-function hardware in a double-buffering scheme to avoid a
+ * pipeline stall each time the contents of the curbe is changed.
+ */
+void brw_upload_constant_buffer_state(struct brw_context *brw)
+{
+ struct brw_constant_buffer_state cbs;
+ memset(&cbs, 0, sizeof(cbs));
+
+ /* 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.
+ */
+ cbs.header.opcode = CMD_CONST_BUFFER_STATE;
+ cbs.header.length = sizeof(cbs)/4 - 2;
+
+ /* BRW_NEW_URB_FENCE */
+ cbs.bits0.nr_urb_entries = brw->urb.nr_cs_entries;
+ cbs.bits0.urb_entry_size = brw->urb.csize - 1;
+
+ assert(brw->urb.nr_cs_entries);
+ BRW_CACHED_BATCH_STRUCT(brw, &cbs);
+}
+
+
+static float fixed_plane[6][4] = {
+ { 0, 0, -1, 1 },
+ { 0, 0, 1, 1 },
+ { 0, -1, 0, 1 },
+ { 0, 1, 0, 1 },
+ {-1, 0, 0, 1 },
+ { 1, 0, 0, 1 }
+};
+
+/* Upload a new set of constants. Too much variability to go into the
+ * cache mechanism, but maybe would benefit from a comparison against
+ * the current uploaded set of constants.
+ */
+static void upload_constant_buffer(struct brw_context *brw)
+{
+ struct brw_mem_pool *pool = &brw->pool[BRW_GS_POOL];
+ unsigned sz = brw->curbe.total_size;
+ unsigned bufsz = sz * sizeof(float);
+ float *buf;
+ unsigned i;
+
+
+ if (sz == 0) {
+ struct brw_constant_buffer cb;
+ cb.header.opcode = CMD_CONST_BUFFER;
+ cb.header.length = sizeof(cb)/4 - 2;
+ cb.header.valid = 0;
+ cb.bits0.buffer_length = 0;
+ cb.bits0.buffer_address = 0;
+ BRW_BATCH_STRUCT(brw, &cb);
+
+ if (brw->curbe.last_buf) {
+ free(brw->curbe.last_buf);
+ brw->curbe.last_buf = NULL;
+ brw->curbe.last_bufsz = 0;
+ }
+
+ return;
+ }
+
+ buf = (float *)malloc(bufsz);
+
+ memset(buf, 0, bufsz);
+
+ if (brw->curbe.wm_size) {
+ unsigned offset = brw->curbe.wm_start * 16;
+
+ /* First the constant buffer constants:
+ */
+
+ /* Then any internally generated constants:
+ */
+ for (i = 0; i < brw->wm.prog_data->nr_internal_consts; i++)
+ buf[offset + i] = brw->wm.prog_data->internal_const[i];
+
+ assert(brw->wm.prog_data->max_const ==
+ brw->wm.prog_data->nr_internal_consts);
+ }
+
+
+ /* The clipplanes are actually delivered to both CLIP and VS units.
+ * VS uses them to calculate the outcode bitmasks.
+ */
+ if (brw->curbe.clip_size) {
+ unsigned offset = brw->curbe.clip_start * 16;
+ unsigned j;
+
+ /* If any planes are going this way, send them all this way:
+ */
+ for (i = 0; i < 6; i++) {
+ buf[offset + i * 4 + 0] = fixed_plane[i][0];
+ buf[offset + i * 4 + 1] = fixed_plane[i][1];
+ buf[offset + i * 4 + 2] = fixed_plane[i][2];
+ buf[offset + i * 4 + 3] = fixed_plane[i][3];
+ }
+
+ /* Clip planes: BRW_NEW_CLIP:
+ */
+ for (j = 0; j < brw->attribs.Clip.nr; j++) {
+ buf[offset + i * 4 + 0] = brw->attribs.Clip.ucp[j][0];
+ buf[offset + i * 4 + 1] = brw->attribs.Clip.ucp[j][1];
+ buf[offset + i * 4 + 2] = brw->attribs.Clip.ucp[j][2];
+ buf[offset + i * 4 + 3] = brw->attribs.Clip.ucp[j][3];
+ i++;
+ }
+ }
+
+
+ if (brw->curbe.vs_size) {
+ unsigned offset = brw->curbe.vs_start * 16;
+ /*unsigned nr = vp->max_const;*/
+ const struct pipe_constant_buffer *cbuffer = brw->attribs.Constants[0];
+ struct pipe_winsys *ws = brw->pipe.winsys;
+ /* FIXME: buffer size is num_consts + num_immediates */
+ if (brw->vs.prog_data->num_consts) {
+ /* map the vertex constant buffer and copy to curbe: */
+ void *data = ws->buffer_map(ws, cbuffer->buffer, 0);
+ /* FIXME: this is wrong. the cbuffer->buffer->size currently
+ * represents size of consts + immediates. so if we'll
+ * have both we'll copy over the end of the buffer
+ * with the subsequent memcpy */
+ memcpy(&buf[offset], data, cbuffer->buffer->size);
+ ws->buffer_unmap(ws, cbuffer->buffer);
+ offset += cbuffer->buffer->size;
+ }
+ /*immediates*/
+ if (brw->vs.prog_data->num_imm) {
+ memcpy(&buf[offset], brw->vs.prog_data->imm_buf,
+ brw->vs.prog_data->num_imm * 4 * sizeof(float));
+ }
+ }
+
+ if (1) {
+ for (i = 0; i < sz; i+=4)
+ debug_printf("curbe %d.%d: %f %f %f %f\n", i/8, i&4,
+ buf[i+0], buf[i+1], buf[i+2], buf[i+3]);
+
+ debug_printf("last_buf %p buf %p sz %d/%d cmp %d\n",
+ brw->curbe.last_buf, buf,
+ bufsz, brw->curbe.last_bufsz,
+ brw->curbe.last_buf ? memcmp(buf, brw->curbe.last_buf, bufsz) : -1);
+ }
+
+ if (brw->curbe.last_buf &&
+ bufsz == brw->curbe.last_bufsz &&
+ memcmp(buf, brw->curbe.last_buf, bufsz) == 0) {
+ free(buf);
+/* return; */
+ }
+ else {
+ if (brw->curbe.last_buf)
+ free(brw->curbe.last_buf);
+ brw->curbe.last_buf = buf;
+ brw->curbe.last_bufsz = bufsz;
+
+
+ if (!brw_pool_alloc(pool,
+ bufsz,
+ 1 << 6,
+ &brw->curbe.gs_offset)) {
+ debug_printf("out of GS memory for curbe\n");
+ assert(0);
+ return;
+ }
+
+
+ /* Copy data to the buffer:
+ */
+ brw->winsys->buffer_subdata_typed(brw->winsys,
+ pool->buffer,
+ brw->curbe.gs_offset,
+ bufsz,
+ buf,
+ BRW_CONSTANT_BUFFER );
+ }
+
+ /* TODO: only emit the constant_buffer packet when necessary, ie:
+ - contents have changed
+ - offset has changed
+ - hw requirements due to other packets emitted.
+ */
+ {
+ struct brw_constant_buffer cb;
+
+ memset(&cb, 0, sizeof(cb));
+
+ cb.header.opcode = CMD_CONST_BUFFER;
+ cb.header.length = sizeof(cb)/4 - 2;
+ cb.header.valid = 1;
+ cb.bits0.buffer_length = sz - 1;
+ cb.bits0.buffer_address = brw->curbe.gs_offset >> 6;
+
+ /* Because this provokes an action (ie copy the constants into the
+ * URB), it shouldn't be shortcircuited if identical to the
+ * previous time - because eg. the urb destination may have
+ * changed, or the urb contents different to last time.
+ *
+ * Note that the data referred to is actually copied internally,
+ * not just used in place according to passed pointer.
+ *
+ * It appears that the CS unit takes care of using each available
+ * URB entry (Const URB Entry == CURBE) in turn, and issuing
+ * flushes as necessary when doublebuffering of CURBEs isn't
+ * possible.
+ */
+ BRW_BATCH_STRUCT(brw, &cb);
+ }
+}
+
+/* This tracked state is unique in that the state it monitors varies
+ * dynamically depending on the parameters tracked by the fragment and
+ * vertex programs. This is the template used as a starting point,
+ * each context will maintain a copy of this internally and update as
+ * required.
+ */
+const struct brw_tracked_state brw_constant_buffer = {
+ .dirty = {
+ .brw = (BRW_NEW_CLIP |
+ BRW_NEW_CONSTANTS |
+ BRW_NEW_URB_FENCE | /* Implicit - hardware requires this, not used above */
+ BRW_NEW_PSP | /* Implicit - hardware requires this, not used above */
+ BRW_NEW_CURBE_OFFSETS),
+ .cache = (CACHE_NEW_WM_PROG)
+ },
+ .update = upload_constant_buffer
+};
+
diff --git a/src/gallium/drivers/i965simple/brw_defines.h b/src/gallium/drivers/i965simple/brw_defines.h
new file mode 100644
index 0000000000..715d2d2d01
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_defines.h
@@ -0,0 +1,870 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRW_DEFINES_H
+#define BRW_DEFINES_H
+
+/*
+ */
+#define MI_NOOP 0x00
+#define MI_USER_INTERRUPT 0x02
+#define MI_WAIT_FOR_EVENT 0x03
+#define MI_FLUSH 0x04
+#define MI_REPORT_HEAD 0x07
+#define MI_ARB_ON_OFF 0x08
+#define MI_BATCH_BUFFER_END 0x0A
+#define MI_OVERLAY_FLIP 0x11
+#define MI_LOAD_SCAN_LINES_INCL 0x12
+#define MI_LOAD_SCAN_LINES_EXCL 0x13
+#define MI_DISPLAY_BUFFER_INFO 0x14
+#define MI_SET_CONTEXT 0x18
+#define MI_STORE_DATA_IMM 0x20
+#define MI_STORE_DATA_INDEX 0x21
+#define MI_LOAD_REGISTER_IMM 0x22
+#define MI_STORE_REGISTER_MEM 0x24
+#define MI_BATCH_BUFFER_START 0x31
+
+#define MI_SYNCHRONOUS_FLIP 0x0
+#define MI_ASYNCHRONOUS_FLIP 0x1
+
+#define MI_BUFFER_SECURE 0x0
+#define MI_BUFFER_NONSECURE 0x1
+
+#define MI_ARBITRATE_AT_CHAIN_POINTS 0x0
+#define MI_ARBITRATE_BETWEEN_INSTS 0x1
+#define MI_NO_ARBITRATION 0x3
+
+#define MI_CONDITION_CODE_WAIT_DISABLED 0x0
+#define MI_CONDITION_CODE_WAIT_0 0x1
+#define MI_CONDITION_CODE_WAIT_1 0x2
+#define MI_CONDITION_CODE_WAIT_2 0x3
+#define MI_CONDITION_CODE_WAIT_3 0x4
+#define MI_CONDITION_CODE_WAIT_4 0x5
+
+#define MI_DISPLAY_PIPE_A 0x0
+#define MI_DISPLAY_PIPE_B 0x1
+
+#define MI_DISPLAY_PLANE_A 0x0
+#define MI_DISPLAY_PLANE_B 0x1
+#define MI_DISPLAY_PLANE_C 0x2
+
+#define MI_STANDARD_FLIP 0x0
+#define MI_ENQUEUE_FLIP_PERFORM_BASE_FRAME_NUMBER_LOAD 0x1
+#define MI_ENQUEUE_FLIP_TARGET_FRAME_NUMBER_RELATIVE 0x2
+#define MI_ENQUEUE_FLIP_ABSOLUTE_TARGET_FRAME_NUMBER 0x3
+
+#define MI_PHYSICAL_ADDRESS 0x0
+#define MI_VIRTUAL_ADDRESS 0x1
+
+#define MI_BUFFER_MEMORY_MAIN 0x0
+#define MI_BUFFER_MEMORY_GTT 0x2
+#define MI_BUFFER_MEMORY_PER_PROCESS_GTT 0x3
+
+#define MI_FLIP_CONTINUE 0x0
+#define MI_FLIP_ON 0x1
+#define MI_FLIP_OFF 0x2
+
+#define MI_UNTRUSTED_REGISTER_SPACE 0x0
+#define MI_TRUSTED_REGISTER_SPACE 0x1
+
+/* 3D state:
+ */
+#define _3DOP_3DSTATE_PIPELINED 0x0
+#define _3DOP_3DSTATE_NONPIPELINED 0x1
+#define _3DOP_3DCONTROL 0x2
+#define _3DOP_3DPRIMITIVE 0x3
+
+#define _3DSTATE_PIPELINED_POINTERS 0x00
+#define _3DSTATE_BINDING_TABLE_POINTERS 0x01
+#define _3DSTATE_VERTEX_BUFFERS 0x08
+#define _3DSTATE_VERTEX_ELEMENTS 0x09
+#define _3DSTATE_INDEX_BUFFER 0x0A
+#define _3DSTATE_VF_STATISTICS 0x0B
+#define _3DSTATE_DRAWING_RECTANGLE 0x00
+#define _3DSTATE_CONSTANT_COLOR 0x01
+#define _3DSTATE_SAMPLER_PALETTE_LOAD 0x02
+#define _3DSTATE_CHROMA_KEY 0x04
+#define _3DSTATE_DEPTH_BUFFER 0x05
+#define _3DSTATE_POLY_STIPPLE_OFFSET 0x06
+#define _3DSTATE_POLY_STIPPLE_PATTERN 0x07
+#define _3DSTATE_LINE_STIPPLE 0x08
+#define _3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP 0x09
+#define _3DCONTROL 0x00
+#define _3DPRIMITIVE 0x00
+
+#define PIPE_CONTROL_NOWRITE 0x00
+#define PIPE_CONTROL_WRITEIMMEDIATE 0x01
+#define PIPE_CONTROL_WRITEDEPTH 0x02
+#define PIPE_CONTROL_WRITETIMESTAMP 0x03
+
+#define PIPE_CONTROL_GTTWRITE_PROCESS_LOCAL 0x00
+#define PIPE_CONTROL_GTTWRITE_GLOBAL 0x01
+
+#define _3DPRIM_POINTLIST 0x01
+#define _3DPRIM_LINELIST 0x02
+#define _3DPRIM_LINESTRIP 0x03
+#define _3DPRIM_TRILIST 0x04
+#define _3DPRIM_TRISTRIP 0x05
+#define _3DPRIM_TRIFAN 0x06
+#define _3DPRIM_QUADLIST 0x07
+#define _3DPRIM_QUADSTRIP 0x08
+#define _3DPRIM_LINELIST_ADJ 0x09
+#define _3DPRIM_LINESTRIP_ADJ 0x0A
+#define _3DPRIM_TRILIST_ADJ 0x0B
+#define _3DPRIM_TRISTRIP_ADJ 0x0C
+#define _3DPRIM_TRISTRIP_REVERSE 0x0D
+#define _3DPRIM_POLYGON 0x0E
+#define _3DPRIM_RECTLIST 0x0F
+#define _3DPRIM_LINELOOP 0x10
+#define _3DPRIM_POINTLIST_BF 0x11
+#define _3DPRIM_LINESTRIP_CONT 0x12
+#define _3DPRIM_LINESTRIP_BF 0x13
+#define _3DPRIM_LINESTRIP_CONT_BF 0x14
+#define _3DPRIM_TRIFAN_NOSTIPPLE 0x15
+
+#define _3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL 0
+#define _3DPRIM_VERTEXBUFFER_ACCESS_RANDOM 1
+
+#define BRW_ANISORATIO_2 0
+#define BRW_ANISORATIO_4 1
+#define BRW_ANISORATIO_6 2
+#define BRW_ANISORATIO_8 3
+#define BRW_ANISORATIO_10 4
+#define BRW_ANISORATIO_12 5
+#define BRW_ANISORATIO_14 6
+#define BRW_ANISORATIO_16 7
+
+#define BRW_BLENDFACTOR_ONE 0x1
+#define BRW_BLENDFACTOR_SRC_COLOR 0x2
+#define BRW_BLENDFACTOR_SRC_ALPHA 0x3
+#define BRW_BLENDFACTOR_DST_ALPHA 0x4
+#define BRW_BLENDFACTOR_DST_COLOR 0x5
+#define BRW_BLENDFACTOR_SRC_ALPHA_SATURATE 0x6
+#define BRW_BLENDFACTOR_CONST_COLOR 0x7
+#define BRW_BLENDFACTOR_CONST_ALPHA 0x8
+#define BRW_BLENDFACTOR_SRC1_COLOR 0x9
+#define BRW_BLENDFACTOR_SRC1_ALPHA 0x0A
+#define BRW_BLENDFACTOR_ZERO 0x11
+#define BRW_BLENDFACTOR_INV_SRC_COLOR 0x12
+#define BRW_BLENDFACTOR_INV_SRC_ALPHA 0x13
+#define BRW_BLENDFACTOR_INV_DST_ALPHA 0x14
+#define BRW_BLENDFACTOR_INV_DST_COLOR 0x15
+#define BRW_BLENDFACTOR_INV_CONST_COLOR 0x17
+#define BRW_BLENDFACTOR_INV_CONST_ALPHA 0x18
+#define BRW_BLENDFACTOR_INV_SRC1_COLOR 0x19
+#define BRW_BLENDFACTOR_INV_SRC1_ALPHA 0x1A
+
+#define BRW_BLENDFUNCTION_ADD 0
+#define BRW_BLENDFUNCTION_SUBTRACT 1
+#define BRW_BLENDFUNCTION_REVERSE_SUBTRACT 2
+#define BRW_BLENDFUNCTION_MIN 3
+#define BRW_BLENDFUNCTION_MAX 4
+
+#define BRW_ALPHATEST_FORMAT_UNORM8 0
+#define BRW_ALPHATEST_FORMAT_FLOAT32 1
+
+#define BRW_CHROMAKEY_KILL_ON_ANY_MATCH 0
+#define BRW_CHROMAKEY_REPLACE_BLACK 1
+
+#define BRW_CLIP_API_OGL 0
+#define BRW_CLIP_API_DX 1
+
+#define BRW_CLIPMODE_NORMAL 0
+#define BRW_CLIPMODE_CLIP_ALL 1
+#define BRW_CLIPMODE_CLIP_NON_REJECTED 2
+#define BRW_CLIPMODE_REJECT_ALL 3
+#define BRW_CLIPMODE_ACCEPT_ALL 4
+
+#define BRW_CLIP_NDCSPACE 0
+#define BRW_CLIP_SCREENSPACE 1
+
+#define BRW_COMPAREFUNCTION_ALWAYS 0
+#define BRW_COMPAREFUNCTION_NEVER 1
+#define BRW_COMPAREFUNCTION_LESS 2
+#define BRW_COMPAREFUNCTION_EQUAL 3
+#define BRW_COMPAREFUNCTION_LEQUAL 4
+#define BRW_COMPAREFUNCTION_GREATER 5
+#define BRW_COMPAREFUNCTION_NOTEQUAL 6
+#define BRW_COMPAREFUNCTION_GEQUAL 7
+
+#define BRW_COVERAGE_PIXELS_HALF 0
+#define BRW_COVERAGE_PIXELS_1 1
+#define BRW_COVERAGE_PIXELS_2 2
+#define BRW_COVERAGE_PIXELS_4 3
+
+#define BRW_CULLMODE_BOTH 0
+#define BRW_CULLMODE_NONE 1
+#define BRW_CULLMODE_FRONT 2
+#define BRW_CULLMODE_BACK 3
+
+#define BRW_DEFAULTCOLOR_R8G8B8A8_UNORM 0
+#define BRW_DEFAULTCOLOR_R32G32B32A32_FLOAT 1
+
+#define BRW_DEPTHFORMAT_D32_FLOAT_S8X24_UINT 0
+#define BRW_DEPTHFORMAT_D32_FLOAT 1
+#define BRW_DEPTHFORMAT_D24_UNORM_S8_UINT 2
+#define BRW_DEPTHFORMAT_D16_UNORM 5
+
+#define BRW_FLOATING_POINT_IEEE_754 0
+#define BRW_FLOATING_POINT_NON_IEEE_754 1
+
+#define BRW_FRONTWINDING_CW 0
+#define BRW_FRONTWINDING_CCW 1
+
+#define BRW_SPRITE_POINT_ENABLE 16
+
+#define BRW_INDEX_BYTE 0
+#define BRW_INDEX_WORD 1
+#define BRW_INDEX_DWORD 2
+
+#define BRW_LOGICOPFUNCTION_CLEAR 0
+#define BRW_LOGICOPFUNCTION_NOR 1
+#define BRW_LOGICOPFUNCTION_AND_INVERTED 2
+#define BRW_LOGICOPFUNCTION_COPY_INVERTED 3
+#define BRW_LOGICOPFUNCTION_AND_REVERSE 4
+#define BRW_LOGICOPFUNCTION_INVERT 5
+#define BRW_LOGICOPFUNCTION_XOR 6
+#define BRW_LOGICOPFUNCTION_NAND 7
+#define BRW_LOGICOPFUNCTION_AND 8
+#define BRW_LOGICOPFUNCTION_EQUIV 9
+#define BRW_LOGICOPFUNCTION_NOOP 10
+#define BRW_LOGICOPFUNCTION_OR_INVERTED 11
+#define BRW_LOGICOPFUNCTION_COPY 12
+#define BRW_LOGICOPFUNCTION_OR_REVERSE 13
+#define BRW_LOGICOPFUNCTION_OR 14
+#define BRW_LOGICOPFUNCTION_SET 15
+
+#define BRW_MAPFILTER_NEAREST 0x0
+#define BRW_MAPFILTER_LINEAR 0x1
+#define BRW_MAPFILTER_ANISOTROPIC 0x2
+
+#define BRW_MIPFILTER_NONE 0
+#define BRW_MIPFILTER_NEAREST 1
+#define BRW_MIPFILTER_LINEAR 3
+
+#define BRW_POLYGON_FRONT_FACING 0
+#define BRW_POLYGON_BACK_FACING 1
+
+#define BRW_PREFILTER_ALWAYS 0x0
+#define BRW_PREFILTER_NEVER 0x1
+#define BRW_PREFILTER_LESS 0x2
+#define BRW_PREFILTER_EQUAL 0x3
+#define BRW_PREFILTER_LEQUAL 0x4
+#define BRW_PREFILTER_GREATER 0x5
+#define BRW_PREFILTER_NOTEQUAL 0x6
+#define BRW_PREFILTER_GEQUAL 0x7
+
+#define BRW_PROVOKING_VERTEX_0 0
+#define BRW_PROVOKING_VERTEX_1 1
+#define BRW_PROVOKING_VERTEX_2 2
+
+#define BRW_RASTRULE_UPPER_LEFT 0
+#define BRW_RASTRULE_UPPER_RIGHT 1
+/* These are listed as "Reserved, but not seen as useful"
+ * in Intel documentation (page 212, "Point Rasterization Rule",
+ * section 7.4 "SF Pipeline State Summary", of document
+ * "Intel® 965 Express Chipset Family and Intel® G35 Express
+ * Chipset Graphics Controller Programmer's Reference Manual,
+ * Volume 2: 3D/Media", Revision 1.0b as of January 2008,
+ * available at
+ * http://intellinuxgraphics.org/documentation.html
+ * at the time of this writing).
+ *
+ * These appear to be supported on at least some
+ * i965-family devices, and the BRW_RASTRULE_LOWER_RIGHT
+ * is useful when using OpenGL to render to a FBO
+ * (which has the pixel coordinate Y orientation inverted
+ * with respect to the normal OpenGL pixel coordinate system).
+ */
+#define BRW_RASTRULE_LOWER_LEFT 2
+#define BRW_RASTRULE_LOWER_RIGHT 3
+
+#define BRW_RENDERTARGET_CLAMPRANGE_UNORM 0
+#define BRW_RENDERTARGET_CLAMPRANGE_SNORM 1
+#define BRW_RENDERTARGET_CLAMPRANGE_FORMAT 2
+
+#define BRW_STENCILOP_KEEP 0
+#define BRW_STENCILOP_ZERO 1
+#define BRW_STENCILOP_REPLACE 2
+#define BRW_STENCILOP_INCRSAT 3
+#define BRW_STENCILOP_DECRSAT 4
+#define BRW_STENCILOP_INCR 5
+#define BRW_STENCILOP_DECR 6
+#define BRW_STENCILOP_INVERT 7
+
+#define BRW_SURFACE_MIPMAPLAYOUT_BELOW 0
+#define BRW_SURFACE_MIPMAPLAYOUT_RIGHT 1
+
+#define BRW_SURFACEFORMAT_R32G32B32A32_FLOAT 0x000
+#define BRW_SURFACEFORMAT_R32G32B32A32_SINT 0x001
+#define BRW_SURFACEFORMAT_R32G32B32A32_UINT 0x002
+#define BRW_SURFACEFORMAT_R32G32B32A32_UNORM 0x003
+#define BRW_SURFACEFORMAT_R32G32B32A32_SNORM 0x004
+#define BRW_SURFACEFORMAT_R64G64_FLOAT 0x005
+#define BRW_SURFACEFORMAT_R32G32B32X32_FLOAT 0x006
+#define BRW_SURFACEFORMAT_R32G32B32A32_SSCALED 0x007
+#define BRW_SURFACEFORMAT_R32G32B32A32_USCALED 0x008
+#define BRW_SURFACEFORMAT_R32G32B32_FLOAT 0x040
+#define BRW_SURFACEFORMAT_R32G32B32_SINT 0x041
+#define BRW_SURFACEFORMAT_R32G32B32_UINT 0x042
+#define BRW_SURFACEFORMAT_R32G32B32_UNORM 0x043
+#define BRW_SURFACEFORMAT_R32G32B32_SNORM 0x044
+#define BRW_SURFACEFORMAT_R32G32B32_SSCALED 0x045
+#define BRW_SURFACEFORMAT_R32G32B32_USCALED 0x046
+#define BRW_SURFACEFORMAT_R16G16B16A16_UNORM 0x080
+#define BRW_SURFACEFORMAT_R16G16B16A16_SNORM 0x081
+#define BRW_SURFACEFORMAT_R16G16B16A16_SINT 0x082
+#define BRW_SURFACEFORMAT_R16G16B16A16_UINT 0x083
+#define BRW_SURFACEFORMAT_R16G16B16A16_FLOAT 0x084
+#define BRW_SURFACEFORMAT_R32G32_FLOAT 0x085
+#define BRW_SURFACEFORMAT_R32G32_SINT 0x086
+#define BRW_SURFACEFORMAT_R32G32_UINT 0x087
+#define BRW_SURFACEFORMAT_R32_FLOAT_X8X24_TYPELESS 0x088
+#define BRW_SURFACEFORMAT_X32_TYPELESS_G8X24_UINT 0x089
+#define BRW_SURFACEFORMAT_L32A32_FLOAT 0x08A
+#define BRW_SURFACEFORMAT_R32G32_UNORM 0x08B
+#define BRW_SURFACEFORMAT_R32G32_SNORM 0x08C
+#define BRW_SURFACEFORMAT_R64_FLOAT 0x08D
+#define BRW_SURFACEFORMAT_R16G16B16X16_UNORM 0x08E
+#define BRW_SURFACEFORMAT_R16G16B16X16_FLOAT 0x08F
+#define BRW_SURFACEFORMAT_A32X32_FLOAT 0x090
+#define BRW_SURFACEFORMAT_L32X32_FLOAT 0x091
+#define BRW_SURFACEFORMAT_I32X32_FLOAT 0x092
+#define BRW_SURFACEFORMAT_R16G16B16A16_SSCALED 0x093
+#define BRW_SURFACEFORMAT_R16G16B16A16_USCALED 0x094
+#define BRW_SURFACEFORMAT_R32G32_SSCALED 0x095
+#define BRW_SURFACEFORMAT_R32G32_USCALED 0x096
+#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM 0x0C0
+#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB 0x0C1
+#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM 0x0C2
+#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM_SRGB 0x0C3
+#define BRW_SURFACEFORMAT_R10G10B10A2_UINT 0x0C4
+#define BRW_SURFACEFORMAT_R10G10B10_SNORM_A2_UNORM 0x0C5
+#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM 0x0C7
+#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM_SRGB 0x0C8
+#define BRW_SURFACEFORMAT_R8G8B8A8_SNORM 0x0C9
+#define BRW_SURFACEFORMAT_R8G8B8A8_SINT 0x0CA
+#define BRW_SURFACEFORMAT_R8G8B8A8_UINT 0x0CB
+#define BRW_SURFACEFORMAT_R16G16_UNORM 0x0CC
+#define BRW_SURFACEFORMAT_R16G16_SNORM 0x0CD
+#define BRW_SURFACEFORMAT_R16G16_SINT 0x0CE
+#define BRW_SURFACEFORMAT_R16G16_UINT 0x0CF
+#define BRW_SURFACEFORMAT_R16G16_FLOAT 0x0D0
+#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM 0x0D1
+#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM_SRGB 0x0D2
+#define BRW_SURFACEFORMAT_R11G11B10_FLOAT 0x0D3
+#define BRW_SURFACEFORMAT_R32_SINT 0x0D6
+#define BRW_SURFACEFORMAT_R32_UINT 0x0D7
+#define BRW_SURFACEFORMAT_R32_FLOAT 0x0D8
+#define BRW_SURFACEFORMAT_R24_UNORM_X8_TYPELESS 0x0D9
+#define BRW_SURFACEFORMAT_X24_TYPELESS_G8_UINT 0x0DA
+#define BRW_SURFACEFORMAT_L16A16_UNORM 0x0DF
+#define BRW_SURFACEFORMAT_I24X8_UNORM 0x0E0
+#define BRW_SURFACEFORMAT_L24X8_UNORM 0x0E1
+#define BRW_SURFACEFORMAT_A24X8_UNORM 0x0E2
+#define BRW_SURFACEFORMAT_I32_FLOAT 0x0E3
+#define BRW_SURFACEFORMAT_L32_FLOAT 0x0E4
+#define BRW_SURFACEFORMAT_A32_FLOAT 0x0E5
+#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM 0x0E9
+#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM_SRGB 0x0EA
+#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM 0x0EB
+#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM_SRGB 0x0EC
+#define BRW_SURFACEFORMAT_R9G9B9E5_SHAREDEXP 0x0ED
+#define BRW_SURFACEFORMAT_B10G10R10X2_UNORM 0x0EE
+#define BRW_SURFACEFORMAT_L16A16_FLOAT 0x0F0
+#define BRW_SURFACEFORMAT_R32_UNORM 0x0F1
+#define BRW_SURFACEFORMAT_R32_SNORM 0x0F2
+#define BRW_SURFACEFORMAT_R10G10B10X2_USCALED 0x0F3
+#define BRW_SURFACEFORMAT_R8G8B8A8_SSCALED 0x0F4
+#define BRW_SURFACEFORMAT_R8G8B8A8_USCALED 0x0F5
+#define BRW_SURFACEFORMAT_R16G16_SSCALED 0x0F6
+#define BRW_SURFACEFORMAT_R16G16_USCALED 0x0F7
+#define BRW_SURFACEFORMAT_R32_SSCALED 0x0F8
+#define BRW_SURFACEFORMAT_R32_USCALED 0x0F9
+#define BRW_SURFACEFORMAT_B5G6R5_UNORM 0x100
+#define BRW_SURFACEFORMAT_B5G6R5_UNORM_SRGB 0x101
+#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM 0x102
+#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM_SRGB 0x103
+#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM 0x104
+#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM_SRGB 0x105
+#define BRW_SURFACEFORMAT_R8G8_UNORM 0x106
+#define BRW_SURFACEFORMAT_R8G8_SNORM 0x107
+#define BRW_SURFACEFORMAT_R8G8_SINT 0x108
+#define BRW_SURFACEFORMAT_R8G8_UINT 0x109
+#define BRW_SURFACEFORMAT_R16_UNORM 0x10A
+#define BRW_SURFACEFORMAT_R16_SNORM 0x10B
+#define BRW_SURFACEFORMAT_R16_SINT 0x10C
+#define BRW_SURFACEFORMAT_R16_UINT 0x10D
+#define BRW_SURFACEFORMAT_R16_FLOAT 0x10E
+#define BRW_SURFACEFORMAT_I16_UNORM 0x111
+#define BRW_SURFACEFORMAT_L16_UNORM 0x112
+#define BRW_SURFACEFORMAT_A16_UNORM 0x113
+#define BRW_SURFACEFORMAT_L8A8_UNORM 0x114
+#define BRW_SURFACEFORMAT_I16_FLOAT 0x115
+#define BRW_SURFACEFORMAT_L16_FLOAT 0x116
+#define BRW_SURFACEFORMAT_A16_FLOAT 0x117
+#define BRW_SURFACEFORMAT_R5G5_SNORM_B6_UNORM 0x119
+#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM 0x11A
+#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM_SRGB 0x11B
+#define BRW_SURFACEFORMAT_R8G8_SSCALED 0x11C
+#define BRW_SURFACEFORMAT_R8G8_USCALED 0x11D
+#define BRW_SURFACEFORMAT_R16_SSCALED 0x11E
+#define BRW_SURFACEFORMAT_R16_USCALED 0x11F
+#define BRW_SURFACEFORMAT_R8_UNORM 0x140
+#define BRW_SURFACEFORMAT_R8_SNORM 0x141
+#define BRW_SURFACEFORMAT_R8_SINT 0x142
+#define BRW_SURFACEFORMAT_R8_UINT 0x143
+#define BRW_SURFACEFORMAT_A8_UNORM 0x144
+#define BRW_SURFACEFORMAT_I8_UNORM 0x145
+#define BRW_SURFACEFORMAT_L8_UNORM 0x146
+#define BRW_SURFACEFORMAT_P4A4_UNORM 0x147
+#define BRW_SURFACEFORMAT_A4P4_UNORM 0x148
+#define BRW_SURFACEFORMAT_R8_SSCALED 0x149
+#define BRW_SURFACEFORMAT_R8_USCALED 0x14A
+#define BRW_SURFACEFORMAT_R1_UINT 0x181
+#define BRW_SURFACEFORMAT_YCRCB_NORMAL 0x182
+#define BRW_SURFACEFORMAT_YCRCB_SWAPUVY 0x183
+#define BRW_SURFACEFORMAT_BC1_UNORM 0x186
+#define BRW_SURFACEFORMAT_BC2_UNORM 0x187
+#define BRW_SURFACEFORMAT_BC3_UNORM 0x188
+#define BRW_SURFACEFORMAT_BC4_UNORM 0x189
+#define BRW_SURFACEFORMAT_BC5_UNORM 0x18A
+#define BRW_SURFACEFORMAT_BC1_UNORM_SRGB 0x18B
+#define BRW_SURFACEFORMAT_BC2_UNORM_SRGB 0x18C
+#define BRW_SURFACEFORMAT_BC3_UNORM_SRGB 0x18D
+#define BRW_SURFACEFORMAT_MONO8 0x18E
+#define BRW_SURFACEFORMAT_YCRCB_SWAPUV 0x18F
+#define BRW_SURFACEFORMAT_YCRCB_SWAPY 0x190
+#define BRW_SURFACEFORMAT_DXT1_RGB 0x191
+#define BRW_SURFACEFORMAT_FXT1 0x192
+#define BRW_SURFACEFORMAT_R8G8B8_UNORM 0x193
+#define BRW_SURFACEFORMAT_R8G8B8_SNORM 0x194
+#define BRW_SURFACEFORMAT_R8G8B8_SSCALED 0x195
+#define BRW_SURFACEFORMAT_R8G8B8_USCALED 0x196
+#define BRW_SURFACEFORMAT_R64G64B64A64_FLOAT 0x197
+#define BRW_SURFACEFORMAT_R64G64B64_FLOAT 0x198
+#define BRW_SURFACEFORMAT_BC4_SNORM 0x199
+#define BRW_SURFACEFORMAT_BC5_SNORM 0x19A
+#define BRW_SURFACEFORMAT_R16G16B16_UNORM 0x19C
+#define BRW_SURFACEFORMAT_R16G16B16_SNORM 0x19D
+#define BRW_SURFACEFORMAT_R16G16B16_SSCALED 0x19E
+#define BRW_SURFACEFORMAT_R16G16B16_USCALED 0x19F
+
+#define BRW_SURFACERETURNFORMAT_FLOAT32 0
+#define BRW_SURFACERETURNFORMAT_S1 1
+
+#define BRW_SURFACE_1D 0
+#define BRW_SURFACE_2D 1
+#define BRW_SURFACE_3D 2
+#define BRW_SURFACE_CUBE 3
+#define BRW_SURFACE_BUFFER 4
+#define BRW_SURFACE_NULL 7
+
+#define BRW_TEXCOORDMODE_WRAP 0
+#define BRW_TEXCOORDMODE_MIRROR 1
+#define BRW_TEXCOORDMODE_CLAMP 2
+#define BRW_TEXCOORDMODE_CUBE 3
+#define BRW_TEXCOORDMODE_CLAMP_BORDER 4
+#define BRW_TEXCOORDMODE_MIRROR_ONCE 5
+
+#define BRW_THREAD_PRIORITY_NORMAL 0
+#define BRW_THREAD_PRIORITY_HIGH 1
+
+#define BRW_TILEWALK_XMAJOR 0
+#define BRW_TILEWALK_YMAJOR 1
+
+#define BRW_VERTEX_SUBPIXEL_PRECISION_8BITS 0
+#define BRW_VERTEX_SUBPIXEL_PRECISION_4BITS 1
+
+#define BRW_VERTEXBUFFER_ACCESS_VERTEXDATA 0
+#define BRW_VERTEXBUFFER_ACCESS_INSTANCEDATA 1
+
+#define BRW_VFCOMPONENT_NOSTORE 0
+#define BRW_VFCOMPONENT_STORE_SRC 1
+#define BRW_VFCOMPONENT_STORE_0 2
+#define BRW_VFCOMPONENT_STORE_1_FLT 3
+#define BRW_VFCOMPONENT_STORE_1_INT 4
+#define BRW_VFCOMPONENT_STORE_VID 5
+#define BRW_VFCOMPONENT_STORE_IID 6
+#define BRW_VFCOMPONENT_STORE_PID 7
+
+
+
+/* Execution Unit (EU) defines
+ */
+
+#define BRW_ALIGN_1 0
+#define BRW_ALIGN_16 1
+
+#define BRW_ADDRESS_DIRECT 0
+#define BRW_ADDRESS_REGISTER_INDIRECT_REGISTER 1
+
+#define BRW_CHANNEL_X 0
+#define BRW_CHANNEL_Y 1
+#define BRW_CHANNEL_Z 2
+#define BRW_CHANNEL_W 3
+
+#define BRW_COMPRESSION_NONE 0
+#define BRW_COMPRESSION_2NDHALF 1
+#define BRW_COMPRESSION_COMPRESSED 2
+
+#define BRW_CONDITIONAL_NONE 0
+#define BRW_CONDITIONAL_Z 1
+#define BRW_CONDITIONAL_NZ 2
+#define BRW_CONDITIONAL_EQ 1 /* Z */
+#define BRW_CONDITIONAL_NEQ 2 /* NZ */
+#define BRW_CONDITIONAL_G 3
+#define BRW_CONDITIONAL_GE 4
+#define BRW_CONDITIONAL_L 5
+#define BRW_CONDITIONAL_LE 6
+#define BRW_CONDITIONAL_C 7
+#define BRW_CONDITIONAL_O 8
+
+#define BRW_DEBUG_NONE 0
+#define BRW_DEBUG_BREAKPOINT 1
+
+#define BRW_DEPENDENCY_NORMAL 0
+#define BRW_DEPENDENCY_NOTCLEARED 1
+#define BRW_DEPENDENCY_NOTCHECKED 2
+#define BRW_DEPENDENCY_DISABLE 3
+
+#define BRW_EXECUTE_1 0
+#define BRW_EXECUTE_2 1
+#define BRW_EXECUTE_4 2
+#define BRW_EXECUTE_8 3
+#define BRW_EXECUTE_16 4
+#define BRW_EXECUTE_32 5
+
+#define BRW_HORIZONTAL_STRIDE_0 0
+#define BRW_HORIZONTAL_STRIDE_1 1
+#define BRW_HORIZONTAL_STRIDE_2 2
+#define BRW_HORIZONTAL_STRIDE_4 3
+
+#define BRW_INSTRUCTION_NORMAL 0
+#define BRW_INSTRUCTION_SATURATE 1
+
+#define BRW_MASK_ENABLE 0
+#define BRW_MASK_DISABLE 1
+
+#define BRW_OPCODE_MOV 1
+#define BRW_OPCODE_SEL 2
+#define BRW_OPCODE_NOT 4
+#define BRW_OPCODE_AND 5
+#define BRW_OPCODE_OR 6
+#define BRW_OPCODE_XOR 7
+#define BRW_OPCODE_SHR 8
+#define BRW_OPCODE_SHL 9
+#define BRW_OPCODE_RSR 10
+#define BRW_OPCODE_RSL 11
+#define BRW_OPCODE_ASR 12
+#define BRW_OPCODE_CMP 16
+#define BRW_OPCODE_JMPI 32
+#define BRW_OPCODE_IF 34
+#define BRW_OPCODE_IFF 35
+#define BRW_OPCODE_ELSE 36
+#define BRW_OPCODE_ENDIF 37
+#define BRW_OPCODE_DO 38
+#define BRW_OPCODE_WHILE 39
+#define BRW_OPCODE_BREAK 40
+#define BRW_OPCODE_CONTINUE 41
+#define BRW_OPCODE_HALT 42
+#define BRW_OPCODE_MSAVE 44
+#define BRW_OPCODE_MRESTORE 45
+#define BRW_OPCODE_PUSH 46
+#define BRW_OPCODE_POP 47
+#define BRW_OPCODE_WAIT 48
+#define BRW_OPCODE_SEND 49
+#define BRW_OPCODE_ADD 64
+#define BRW_OPCODE_MUL 65
+#define BRW_OPCODE_AVG 66
+#define BRW_OPCODE_FRC 67
+#define BRW_OPCODE_RNDU 68
+#define BRW_OPCODE_RNDD 69
+#define BRW_OPCODE_RNDE 70
+#define BRW_OPCODE_RNDZ 71
+#define BRW_OPCODE_MAC 72
+#define BRW_OPCODE_MACH 73
+#define BRW_OPCODE_LZD 74
+#define BRW_OPCODE_SAD2 80
+#define BRW_OPCODE_SADA2 81
+#define BRW_OPCODE_DP4 84
+#define BRW_OPCODE_DPH 85
+#define BRW_OPCODE_DP3 86
+#define BRW_OPCODE_DP2 87
+#define BRW_OPCODE_DPA2 88
+#define BRW_OPCODE_LINE 89
+#define BRW_OPCODE_NOP 126
+
+#define BRW_PREDICATE_NONE 0
+#define BRW_PREDICATE_NORMAL 1
+#define BRW_PREDICATE_ALIGN1_ANYV 2
+#define BRW_PREDICATE_ALIGN1_ALLV 3
+#define BRW_PREDICATE_ALIGN1_ANY2H 4
+#define BRW_PREDICATE_ALIGN1_ALL2H 5
+#define BRW_PREDICATE_ALIGN1_ANY4H 6
+#define BRW_PREDICATE_ALIGN1_ALL4H 7
+#define BRW_PREDICATE_ALIGN1_ANY8H 8
+#define BRW_PREDICATE_ALIGN1_ALL8H 9
+#define BRW_PREDICATE_ALIGN1_ANY16H 10
+#define BRW_PREDICATE_ALIGN1_ALL16H 11
+#define BRW_PREDICATE_ALIGN16_REPLICATE_X 2
+#define BRW_PREDICATE_ALIGN16_REPLICATE_Y 3
+#define BRW_PREDICATE_ALIGN16_REPLICATE_Z 4
+#define BRW_PREDICATE_ALIGN16_REPLICATE_W 5
+#define BRW_PREDICATE_ALIGN16_ANY4H 6
+#define BRW_PREDICATE_ALIGN16_ALL4H 7
+
+#define BRW_ARCHITECTURE_REGISTER_FILE 0
+#define BRW_GENERAL_REGISTER_FILE 1
+#define BRW_MESSAGE_REGISTER_FILE 2
+#define BRW_IMMEDIATE_VALUE 3
+
+#define BRW_REGISTER_TYPE_UD 0
+#define BRW_REGISTER_TYPE_D 1
+#define BRW_REGISTER_TYPE_UW 2
+#define BRW_REGISTER_TYPE_W 3
+#define BRW_REGISTER_TYPE_UB 4
+#define BRW_REGISTER_TYPE_B 5
+#define BRW_REGISTER_TYPE_VF 5 /* packed float vector, immediates only? */
+#define BRW_REGISTER_TYPE_HF 6
+#define BRW_REGISTER_TYPE_V 6 /* packed int vector, immediates only, uword dest only */
+#define BRW_REGISTER_TYPE_F 7
+
+#define BRW_ARF_NULL 0x00
+#define BRW_ARF_ADDRESS 0x10
+#define BRW_ARF_ACCUMULATOR 0x20
+#define BRW_ARF_FLAG 0x30
+#define BRW_ARF_MASK 0x40
+#define BRW_ARF_MASK_STACK 0x50
+#define BRW_ARF_MASK_STACK_DEPTH 0x60
+#define BRW_ARF_STATE 0x70
+#define BRW_ARF_CONTROL 0x80
+#define BRW_ARF_NOTIFICATION_COUNT 0x90
+#define BRW_ARF_IP 0xA0
+
+#define BRW_AMASK 0
+#define BRW_IMASK 1
+#define BRW_LMASK 2
+#define BRW_CMASK 3
+
+
+
+#define BRW_THREAD_NORMAL 0
+#define BRW_THREAD_ATOMIC 1
+#define BRW_THREAD_SWITCH 2
+
+#define BRW_VERTICAL_STRIDE_0 0
+#define BRW_VERTICAL_STRIDE_1 1
+#define BRW_VERTICAL_STRIDE_2 2
+#define BRW_VERTICAL_STRIDE_4 3
+#define BRW_VERTICAL_STRIDE_8 4
+#define BRW_VERTICAL_STRIDE_16 5
+#define BRW_VERTICAL_STRIDE_32 6
+#define BRW_VERTICAL_STRIDE_64 7
+#define BRW_VERTICAL_STRIDE_128 8
+#define BRW_VERTICAL_STRIDE_256 9
+#define BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL 0xF
+
+#define BRW_WIDTH_1 0
+#define BRW_WIDTH_2 1
+#define BRW_WIDTH_4 2
+#define BRW_WIDTH_8 3
+#define BRW_WIDTH_16 4
+
+#define BRW_STATELESS_BUFFER_BOUNDARY_1K 0
+#define BRW_STATELESS_BUFFER_BOUNDARY_2K 1
+#define BRW_STATELESS_BUFFER_BOUNDARY_4K 2
+#define BRW_STATELESS_BUFFER_BOUNDARY_8K 3
+#define BRW_STATELESS_BUFFER_BOUNDARY_16K 4
+#define BRW_STATELESS_BUFFER_BOUNDARY_32K 5
+#define BRW_STATELESS_BUFFER_BOUNDARY_64K 6
+#define BRW_STATELESS_BUFFER_BOUNDARY_128K 7
+#define BRW_STATELESS_BUFFER_BOUNDARY_256K 8
+#define BRW_STATELESS_BUFFER_BOUNDARY_512K 9
+#define BRW_STATELESS_BUFFER_BOUNDARY_1M 10
+#define BRW_STATELESS_BUFFER_BOUNDARY_2M 11
+
+#define BRW_POLYGON_FACING_FRONT 0
+#define BRW_POLYGON_FACING_BACK 1
+
+#define BRW_MESSAGE_TARGET_NULL 0
+#define BRW_MESSAGE_TARGET_MATH 1
+#define BRW_MESSAGE_TARGET_SAMPLER 2
+#define BRW_MESSAGE_TARGET_GATEWAY 3
+#define BRW_MESSAGE_TARGET_DATAPORT_READ 4
+#define BRW_MESSAGE_TARGET_DATAPORT_WRITE 5
+#define BRW_MESSAGE_TARGET_URB 6
+#define BRW_MESSAGE_TARGET_THREAD_SPAWNER 7
+
+#define BRW_SAMPLER_RETURN_FORMAT_FLOAT32 0
+#define BRW_SAMPLER_RETURN_FORMAT_UINT32 2
+#define BRW_SAMPLER_RETURN_FORMAT_SINT32 3
+
+#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE 0
+#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE 0
+#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS 0
+#define BRW_SAMPLER_MESSAGE_SIMD8_KILLPIX 1
+#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD 1
+#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD 1
+#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_GRADIENTS 2
+#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS 2
+#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE 0
+#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE 2
+#define BRW_SAMPLER_MESSAGE_SIMD4X2_RESINFO 2
+#define BRW_SAMPLER_MESSAGE_SIMD8_RESINFO 2
+#define BRW_SAMPLER_MESSAGE_SIMD16_RESINFO 2
+#define BRW_SAMPLER_MESSAGE_SIMD4X2_LD 3
+#define BRW_SAMPLER_MESSAGE_SIMD8_LD 3
+#define BRW_SAMPLER_MESSAGE_SIMD16_LD 3
+
+#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDLOW 0
+#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDHIGH 1
+#define BRW_DATAPORT_OWORD_BLOCK_2_OWORDS 2
+#define BRW_DATAPORT_OWORD_BLOCK_4_OWORDS 3
+#define BRW_DATAPORT_OWORD_BLOCK_8_OWORDS 4
+
+#define BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD 0
+#define BRW_DATAPORT_OWORD_DUAL_BLOCK_4OWORDS 2
+
+#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS 2
+#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS 3
+
+#define BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ 0
+#define BRW_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ 1
+#define BRW_DATAPORT_READ_MESSAGE_DWORD_BLOCK_READ 2
+#define BRW_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ 3
+
+#define BRW_DATAPORT_READ_TARGET_DATA_CACHE 0
+#define BRW_DATAPORT_READ_TARGET_RENDER_CACHE 1
+#define BRW_DATAPORT_READ_TARGET_SAMPLER_CACHE 2
+
+#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE 0
+#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED 1
+#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01 2
+#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23 3
+#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01 4
+
+#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE 0
+#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE 1
+#define BRW_DATAPORT_WRITE_MESSAGE_DWORD_BLOCK_WRITE 2
+#define BRW_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE 3
+#define BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE 4
+#define BRW_DATAPORT_WRITE_MESSAGE_STREAMED_VERTEX_BUFFER_WRITE 5
+#define BRW_DATAPORT_WRITE_MESSAGE_FLUSH_RENDER_CACHE 7
+
+#define BRW_MATH_FUNCTION_INV 1
+#define BRW_MATH_FUNCTION_LOG 2
+#define BRW_MATH_FUNCTION_EXP 3
+#define BRW_MATH_FUNCTION_SQRT 4
+#define BRW_MATH_FUNCTION_RSQ 5
+#define BRW_MATH_FUNCTION_SIN 6 /* was 7 */
+#define BRW_MATH_FUNCTION_COS 7 /* was 8 */
+#define BRW_MATH_FUNCTION_SINCOS 8 /* was 6 */
+#define BRW_MATH_FUNCTION_TAN 9
+#define BRW_MATH_FUNCTION_POW 10
+#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER 11
+#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT 12
+#define BRW_MATH_FUNCTION_INT_DIV_REMAINDER 13
+
+#define BRW_MATH_INTEGER_UNSIGNED 0
+#define BRW_MATH_INTEGER_SIGNED 1
+
+#define BRW_MATH_PRECISION_FULL 0
+#define BRW_MATH_PRECISION_PARTIAL 1
+
+#define BRW_MATH_SATURATE_NONE 0
+#define BRW_MATH_SATURATE_SATURATE 1
+
+#define BRW_MATH_DATA_VECTOR 0
+#define BRW_MATH_DATA_SCALAR 1
+
+#define BRW_URB_OPCODE_WRITE 0
+
+#define BRW_URB_SWIZZLE_NONE 0
+#define BRW_URB_SWIZZLE_INTERLEAVE 1
+#define BRW_URB_SWIZZLE_TRANSPOSE 2
+
+#define BRW_SCRATCH_SPACE_SIZE_1K 0
+#define BRW_SCRATCH_SPACE_SIZE_2K 1
+#define BRW_SCRATCH_SPACE_SIZE_4K 2
+#define BRW_SCRATCH_SPACE_SIZE_8K 3
+#define BRW_SCRATCH_SPACE_SIZE_16K 4
+#define BRW_SCRATCH_SPACE_SIZE_32K 5
+#define BRW_SCRATCH_SPACE_SIZE_64K 6
+#define BRW_SCRATCH_SPACE_SIZE_128K 7
+#define BRW_SCRATCH_SPACE_SIZE_256K 8
+#define BRW_SCRATCH_SPACE_SIZE_512K 9
+#define BRW_SCRATCH_SPACE_SIZE_1M 10
+#define BRW_SCRATCH_SPACE_SIZE_2M 11
+
+
+
+
+#define CMD_URB_FENCE 0x6000
+#define CMD_CONST_BUFFER_STATE 0x6001
+#define CMD_CONST_BUFFER 0x6002
+
+#define CMD_STATE_BASE_ADDRESS 0x6101
+#define CMD_STATE_INSN_POINTER 0x6102
+#define CMD_PIPELINE_SELECT 0x6104
+
+#define CMD_PIPELINED_STATE_POINTERS 0x7800
+#define CMD_BINDING_TABLE_PTRS 0x7801
+#define CMD_VERTEX_BUFFER 0x7808
+#define CMD_VERTEX_ELEMENT 0x7809
+#define CMD_INDEX_BUFFER 0x780a
+#define CMD_VF_STATISTICS 0x780b
+
+#define CMD_DRAW_RECT 0x7900
+#define CMD_BLEND_CONSTANT_COLOR 0x7901
+#define CMD_CHROMA_KEY 0x7904
+#define CMD_DEPTH_BUFFER 0x7905
+#define CMD_POLY_STIPPLE_OFFSET 0x7906
+#define CMD_POLY_STIPPLE_PATTERN 0x7907
+#define CMD_LINE_STIPPLE_PATTERN 0x7908
+#define CMD_GLOBAL_DEPTH_OFFSET_CLAMP 0x7909
+
+#define CMD_PIPE_CONTROL 0x7a00
+
+#define CMD_3D_PRIM 0x7b00
+
+#define CMD_MI_FLUSH 0x0200
+
+
+/* Various values from the R0 vertex header:
+ */
+#define R02_PRIM_END 0x1
+#define R02_PRIM_START 0x2
+
+
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_draw.c b/src/gallium/drivers/i965simple/brw_draw.c
new file mode 100644
index 0000000000..49d80cb41c
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_draw.c
@@ -0,0 +1,226 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <stdlib.h>
+
+#include "brw_batch.h"
+#include "brw_draw.h"
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_state.h"
+
+#include "pipe/p_context.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_prim.h"
+
+static unsigned hw_prim[PIPE_PRIM_POLYGON+1] = {
+ _3DPRIM_POINTLIST,
+ _3DPRIM_LINELIST,
+ _3DPRIM_LINELOOP,
+ _3DPRIM_LINESTRIP,
+ _3DPRIM_TRILIST,
+ _3DPRIM_TRISTRIP,
+ _3DPRIM_TRIFAN,
+ _3DPRIM_QUADLIST,
+ _3DPRIM_QUADSTRIP,
+ _3DPRIM_POLYGON
+};
+
+
+/* When the primitive changes, set a state bit and re-validate. Not
+ * the nicest and would rather deal with this by having all the
+ * programs be immune to the active primitive (ie. cope with all
+ * possibilities). That may not be realistic however.
+ */
+static void brw_set_prim(struct brw_context *brw, int prim)
+{
+ PRINT("PRIM: %d\n", prim);
+
+ /* Slight optimization to avoid the GS program when not needed:
+ */
+ if (prim == PIPE_PRIM_QUAD_STRIP &&
+ brw->attribs.Raster->flatshade &&
+ brw->attribs.Raster->fill_cw == PIPE_POLYGON_MODE_FILL &&
+ brw->attribs.Raster->fill_ccw == PIPE_POLYGON_MODE_FILL)
+ prim = PIPE_PRIM_TRIANGLE_STRIP;
+
+ if (prim != brw->primitive) {
+ brw->primitive = prim;
+ brw->state.dirty.brw |= BRW_NEW_PRIMITIVE;
+
+ if (u_reduced_prim(prim) != brw->reduced_primitive) {
+ brw->reduced_primitive = u_reduced_prim(prim);
+ brw->state.dirty.brw |= BRW_NEW_REDUCED_PRIMITIVE;
+ }
+
+ brw_validate_state(brw);
+ }
+
+}
+
+
+static unsigned trim(int prim, unsigned length)
+{
+ if (prim == PIPE_PRIM_QUAD_STRIP)
+ return length > 3 ? (length - length % 2) : 0;
+ else if (prim == PIPE_PRIM_QUADS)
+ return length - length % 4;
+ else
+ return length;
+}
+
+
+
+static boolean brw_emit_prim( struct brw_context *brw,
+ boolean indexed,
+ unsigned start,
+ unsigned count )
+
+{
+ struct brw_3d_primitive prim_packet;
+
+ if (BRW_DEBUG & DEBUG_PRIMS)
+ PRINT("PRIM: %d %d %d\n", brw->primitive, start, count);
+
+ prim_packet.header.opcode = CMD_3D_PRIM;
+ prim_packet.header.length = sizeof(prim_packet)/4 - 2;
+ prim_packet.header.pad = 0;
+ prim_packet.header.topology = hw_prim[brw->primitive];
+ prim_packet.header.indexed = indexed;
+
+ prim_packet.verts_per_instance = trim(brw->primitive, count);
+ prim_packet.start_vert_location = start;
+ prim_packet.instance_count = 1;
+ prim_packet.start_instance_location = 0;
+ prim_packet.base_vert_location = 0;
+
+ if (prim_packet.verts_per_instance == 0)
+ return TRUE;
+
+ return brw_batchbuffer_data( brw->winsys,
+ &prim_packet,
+ sizeof(prim_packet) );
+}
+
+
+/* May fail if out of video memory for texture or vbo upload, or on
+ * fallback conditions.
+ */
+static boolean brw_try_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *index_buffer,
+ unsigned index_size,
+ unsigned mode,
+ unsigned start,
+ unsigned count )
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ /* Set the first primitive ahead of validate_state:
+ */
+ brw_set_prim(brw, mode);
+
+ /* Upload index, vertex data:
+ */
+ if (index_buffer &&
+ !brw_upload_indices( brw, index_buffer, index_size, start, count ))
+ return FALSE;
+
+ if (!brw_upload_vertex_buffers(brw))
+ return FALSE;
+
+ if (!brw_upload_vertex_elements( brw ))
+ return FALSE;
+
+ /* XXX: Need to separate validate and upload of state.
+ */
+ if (brw->state.dirty.brw)
+ brw_validate_state( brw );
+
+ if (!brw_emit_prim(brw, index_buffer != NULL,
+ start, count))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
+static boolean brw_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode,
+ unsigned start,
+ unsigned count )
+{
+ if (!brw_try_draw_elements( pipe,
+ indexBuffer,
+ indexSize,
+ mode, start, count ))
+ {
+ /* flush ? */
+
+ if (!brw_try_draw_elements( pipe,
+ indexBuffer,
+ indexSize,
+ mode, start,
+ count )) {
+ assert(0);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+static boolean brw_draw_arrays( struct pipe_context *pipe,
+ unsigned mode,
+ unsigned start,
+ unsigned count )
+{
+ if (!brw_try_draw_elements( pipe, NULL, 0, mode, start, count )) {
+ /* flush ? */
+
+ if (!brw_try_draw_elements( pipe, NULL, 0, mode, start, count )) {
+ assert(0);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+void brw_init_draw_functions( struct brw_context *brw )
+{
+ brw->pipe.draw_arrays = brw_draw_arrays;
+ brw->pipe.draw_elements = brw_draw_elements;
+}
+
+
diff --git a/src/gallium/drivers/i965simple/brw_draw.h b/src/gallium/drivers/i965simple/brw_draw.h
new file mode 100644
index 0000000000..62fe0d5d0e
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_draw.h
@@ -0,0 +1,55 @@
+ /**************************************************************************
+ *
+ * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef BRW_DRAW_H
+#define BRW_DRAW_H
+
+#include "pipe/p_context.h"
+
+struct brw_context;
+
+
+
+void brw_init_draw_functions( struct brw_context *brw );
+
+
+boolean brw_upload_vertices( struct brw_context *brw,
+ unsigned min_index,
+ unsigned max_index );
+
+boolean brw_upload_indices(struct brw_context *brw,
+ const struct pipe_buffer *index_buffer,
+ int ib_size, int start, int count);
+
+boolean brw_upload_vertex_buffers( struct brw_context *brw );
+boolean brw_upload_vertex_elements( struct brw_context *brw );
+
+unsigned brw_translate_surface_format( unsigned id );
+
+
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_draw_upload.c b/src/gallium/drivers/i965simple/brw_draw_upload.c
new file mode 100644
index 0000000000..2d9ca3f2ea
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_draw_upload.c
@@ -0,0 +1,300 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <stdlib.h>
+
+#include "brw_batch.h"
+#include "brw_draw.h"
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_state.h"
+
+
+struct brw_array_state {
+ union header_union header;
+
+ struct {
+ union {
+ struct {
+ unsigned pitch:11;
+ unsigned pad:15;
+ unsigned access_type:1;
+ unsigned vb_index:5;
+ } bits;
+ unsigned dword;
+ } vb0;
+
+ struct pipe_buffer *buffer;
+ unsigned offset;
+
+ unsigned max_index;
+ unsigned instance_data_step_rate;
+
+ } vb[BRW_VBP_MAX];
+};
+
+
+
+unsigned brw_translate_surface_format( unsigned id )
+{
+ switch (id) {
+ case PIPE_FORMAT_R64_FLOAT:
+ return BRW_SURFACEFORMAT_R64_FLOAT;
+ case PIPE_FORMAT_R64G64_FLOAT:
+ return BRW_SURFACEFORMAT_R64G64_FLOAT;
+ case PIPE_FORMAT_R64G64B64_FLOAT:
+ return BRW_SURFACEFORMAT_R64G64B64_FLOAT;
+ case PIPE_FORMAT_R64G64B64A64_FLOAT:
+ return BRW_SURFACEFORMAT_R64G64B64A64_FLOAT;
+
+ case PIPE_FORMAT_R32_FLOAT:
+ return BRW_SURFACEFORMAT_R32_FLOAT;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ return BRW_SURFACEFORMAT_R32G32_FLOAT;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ return BRW_SURFACEFORMAT_R32G32B32_FLOAT;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ return BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
+
+ case PIPE_FORMAT_R32_UNORM:
+ return BRW_SURFACEFORMAT_R32_UNORM;
+ case PIPE_FORMAT_R32G32_UNORM:
+ return BRW_SURFACEFORMAT_R32G32_UNORM;
+ case PIPE_FORMAT_R32G32B32_UNORM:
+ return BRW_SURFACEFORMAT_R32G32B32_UNORM;
+ case PIPE_FORMAT_R32G32B32A32_UNORM:
+ return BRW_SURFACEFORMAT_R32G32B32A32_UNORM;
+
+ case PIPE_FORMAT_R32_USCALED:
+ return BRW_SURFACEFORMAT_R32_USCALED;
+ case PIPE_FORMAT_R32G32_USCALED:
+ return BRW_SURFACEFORMAT_R32G32_USCALED;
+ case PIPE_FORMAT_R32G32B32_USCALED:
+ return BRW_SURFACEFORMAT_R32G32B32_USCALED;
+ case PIPE_FORMAT_R32G32B32A32_USCALED:
+ return BRW_SURFACEFORMAT_R32G32B32A32_USCALED;
+
+ case PIPE_FORMAT_R32_SNORM:
+ return BRW_SURFACEFORMAT_R32_SNORM;
+ case PIPE_FORMAT_R32G32_SNORM:
+ return BRW_SURFACEFORMAT_R32G32_SNORM;
+ case PIPE_FORMAT_R32G32B32_SNORM:
+ return BRW_SURFACEFORMAT_R32G32B32_SNORM;
+ case PIPE_FORMAT_R32G32B32A32_SNORM:
+ return BRW_SURFACEFORMAT_R32G32B32A32_SNORM;
+
+ case PIPE_FORMAT_R32_SSCALED:
+ return BRW_SURFACEFORMAT_R32_SSCALED;
+ case PIPE_FORMAT_R32G32_SSCALED:
+ return BRW_SURFACEFORMAT_R32G32_SSCALED;
+ case PIPE_FORMAT_R32G32B32_SSCALED:
+ return BRW_SURFACEFORMAT_R32G32B32_SSCALED;
+ case PIPE_FORMAT_R32G32B32A32_SSCALED:
+ return BRW_SURFACEFORMAT_R32G32B32A32_SSCALED;
+
+ case PIPE_FORMAT_R16_UNORM:
+ return BRW_SURFACEFORMAT_R16_UNORM;
+ case PIPE_FORMAT_R16G16_UNORM:
+ return BRW_SURFACEFORMAT_R16G16_UNORM;
+ case PIPE_FORMAT_R16G16B16_UNORM:
+ return BRW_SURFACEFORMAT_R16G16B16_UNORM;
+ case PIPE_FORMAT_R16G16B16A16_UNORM:
+ return BRW_SURFACEFORMAT_R16G16B16A16_UNORM;
+
+ case PIPE_FORMAT_R16_USCALED:
+ return BRW_SURFACEFORMAT_R16_USCALED;
+ case PIPE_FORMAT_R16G16_USCALED:
+ return BRW_SURFACEFORMAT_R16G16_USCALED;
+ case PIPE_FORMAT_R16G16B16_USCALED:
+ return BRW_SURFACEFORMAT_R16G16B16_USCALED;
+ case PIPE_FORMAT_R16G16B16A16_USCALED:
+ return BRW_SURFACEFORMAT_R16G16B16A16_USCALED;
+
+ case PIPE_FORMAT_R16_SNORM:
+ return BRW_SURFACEFORMAT_R16_SNORM;
+ case PIPE_FORMAT_R16G16_SNORM:
+ return BRW_SURFACEFORMAT_R16G16_SNORM;
+ case PIPE_FORMAT_R16G16B16_SNORM:
+ return BRW_SURFACEFORMAT_R16G16B16_SNORM;
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ return BRW_SURFACEFORMAT_R16G16B16A16_SNORM;
+
+ case PIPE_FORMAT_R16_SSCALED:
+ return BRW_SURFACEFORMAT_R16_SSCALED;
+ case PIPE_FORMAT_R16G16_SSCALED:
+ return BRW_SURFACEFORMAT_R16G16_SSCALED;
+ case PIPE_FORMAT_R16G16B16_SSCALED:
+ return BRW_SURFACEFORMAT_R16G16B16_SSCALED;
+ case PIPE_FORMAT_R16G16B16A16_SSCALED:
+ return BRW_SURFACEFORMAT_R16G16B16A16_SSCALED;
+
+ case PIPE_FORMAT_R8_UNORM:
+ return BRW_SURFACEFORMAT_R8_UNORM;
+ case PIPE_FORMAT_R8G8_UNORM:
+ return BRW_SURFACEFORMAT_R8G8_UNORM;
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ return BRW_SURFACEFORMAT_R8G8B8_UNORM;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ return BRW_SURFACEFORMAT_R8G8B8A8_UNORM;
+
+ case PIPE_FORMAT_R8_USCALED:
+ return BRW_SURFACEFORMAT_R8_USCALED;
+ case PIPE_FORMAT_R8G8_USCALED:
+ return BRW_SURFACEFORMAT_R8G8_USCALED;
+ case PIPE_FORMAT_R8G8B8_USCALED:
+ return BRW_SURFACEFORMAT_R8G8B8_USCALED;
+ case PIPE_FORMAT_R8G8B8A8_USCALED:
+ return BRW_SURFACEFORMAT_R8G8B8A8_USCALED;
+
+ case PIPE_FORMAT_R8_SNORM:
+ return BRW_SURFACEFORMAT_R8_SNORM;
+ case PIPE_FORMAT_R8G8_SNORM:
+ return BRW_SURFACEFORMAT_R8G8_SNORM;
+ case PIPE_FORMAT_R8G8B8_SNORM:
+ return BRW_SURFACEFORMAT_R8G8B8_SNORM;
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
+ return BRW_SURFACEFORMAT_R8G8B8A8_SNORM;
+
+ case PIPE_FORMAT_R8_SSCALED:
+ return BRW_SURFACEFORMAT_R8_SSCALED;
+ case PIPE_FORMAT_R8G8_SSCALED:
+ return BRW_SURFACEFORMAT_R8G8_SSCALED;
+ case PIPE_FORMAT_R8G8B8_SSCALED:
+ return BRW_SURFACEFORMAT_R8G8B8_SSCALED;
+ case PIPE_FORMAT_R8G8B8A8_SSCALED:
+ return BRW_SURFACEFORMAT_R8G8B8A8_SSCALED;
+
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static unsigned get_index_type(int type)
+{
+ switch (type) {
+ case 1: return BRW_INDEX_BYTE;
+ case 2: return BRW_INDEX_WORD;
+ case 4: return BRW_INDEX_DWORD;
+ default: assert(0); return 0;
+ }
+}
+
+
+boolean brw_upload_vertex_buffers( struct brw_context *brw )
+{
+ struct brw_array_state vbp;
+ unsigned nr_enabled = 0;
+ unsigned i;
+
+ memset(&vbp, 0, sizeof(vbp));
+
+ /* This is a hardware limit:
+ */
+
+ for (i = 0; i < BRW_VEP_MAX; i++)
+ {
+ if (brw->vb.vbo_array[i] == NULL) {
+ nr_enabled = i;
+ break;
+ }
+
+ vbp.vb[i].vb0.bits.pitch = brw->vb.vbo_array[i]->stride;
+ vbp.vb[i].vb0.bits.pad = 0;
+ vbp.vb[i].vb0.bits.access_type = BRW_VERTEXBUFFER_ACCESS_VERTEXDATA;
+ vbp.vb[i].vb0.bits.vb_index = i;
+ vbp.vb[i].offset = brw->vb.vbo_array[i]->buffer_offset;
+ vbp.vb[i].buffer = brw->vb.vbo_array[i]->buffer;
+ vbp.vb[i].max_index = brw->vb.vbo_array[i]->max_index;
+ }
+
+
+ vbp.header.bits.length = (1 + nr_enabled * 4) - 2;
+ vbp.header.bits.opcode = CMD_VERTEX_BUFFER;
+
+ BEGIN_BATCH(vbp.header.bits.length+2, 0);
+ OUT_BATCH( vbp.header.dword );
+
+ for (i = 0; i < nr_enabled; i++) {
+ OUT_BATCH( vbp.vb[i].vb0.dword );
+ OUT_RELOC( vbp.vb[i].buffer, PIPE_BUFFER_USAGE_GPU_READ,
+ vbp.vb[i].offset);
+ OUT_BATCH( vbp.vb[i].max_index );
+ OUT_BATCH( vbp.vb[i].instance_data_step_rate );
+ }
+ ADVANCE_BATCH();
+ return TRUE;
+}
+
+
+
+boolean brw_upload_vertex_elements( struct brw_context *brw )
+{
+ struct brw_vertex_element_packet vep;
+
+ unsigned i;
+ unsigned nr_enabled = brw->attribs.VertexProgram->info.num_inputs;
+
+ memset(&vep, 0, sizeof(vep));
+
+ for (i = 0; i < nr_enabled; i++)
+ vep.ve[i] = brw->vb.inputs[i];
+
+
+ vep.header.length = (1 + nr_enabled * sizeof(vep.ve[0])/4) - 2;
+ vep.header.opcode = CMD_VERTEX_ELEMENT;
+ brw_cached_batch_struct(brw, &vep, 4 + nr_enabled * sizeof(vep.ve[0]));
+
+ return TRUE;
+}
+
+boolean brw_upload_indices( struct brw_context *brw,
+ const struct pipe_buffer *index_buffer,
+ int ib_size, int start, int count)
+{
+ /* 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(ib_size);
+ ib.header.bits.cut_index_enable = 0;
+
+
+ BEGIN_BATCH(4, 0);
+ OUT_BATCH( ib.header.dword );
+ OUT_RELOC( index_buffer, PIPE_BUFFER_USAGE_GPU_READ, start);
+ OUT_RELOC( index_buffer, PIPE_BUFFER_USAGE_GPU_READ, start + count);
+ OUT_BATCH( 0 );
+ ADVANCE_BATCH();
+ }
+ return TRUE;
+}
diff --git a/src/gallium/drivers/i965simple/brw_eu.c b/src/gallium/drivers/i965simple/brw_eu.c
new file mode 100644
index 0000000000..e2002d1821
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_eu.c
@@ -0,0 +1,130 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_defines.h"
+#include "brw_eu.h"
+
+
+
+/* How does predicate control work when execution_size != 8? Do I
+ * need to test/set for 0xffff when execution_size is 16?
+ */
+void brw_set_predicate_control_flag_value( struct brw_compile *p, unsigned value )
+{
+ p->current->header.predicate_control = BRW_PREDICATE_NONE;
+
+ if (value != 0xff) {
+ if (value != p->flag_value) {
+ brw_push_insn_state(p);
+ brw_MOV(p, brw_flag_reg(), brw_imm_uw(value));
+ p->flag_value = value;
+ brw_pop_insn_state(p);
+ }
+
+ p->current->header.predicate_control = BRW_PREDICATE_NORMAL;
+ }
+}
+
+void brw_set_predicate_control( struct brw_compile *p, unsigned pc )
+{
+ p->current->header.predicate_control = pc;
+}
+
+void brw_set_conditionalmod( struct brw_compile *p, unsigned conditional )
+{
+ p->current->header.destreg__conditonalmod = conditional;
+}
+
+void brw_set_access_mode( struct brw_compile *p, unsigned access_mode )
+{
+ p->current->header.access_mode = access_mode;
+}
+
+void brw_set_compression_control( struct brw_compile *p, boolean compression_control )
+{
+ p->current->header.compression_control = compression_control;
+}
+
+void brw_set_mask_control( struct brw_compile *p, unsigned value )
+{
+ p->current->header.mask_control = value;
+}
+
+void brw_set_saturate( struct brw_compile *p, unsigned value )
+{
+ p->current->header.saturate = value;
+}
+
+void brw_push_insn_state( struct brw_compile *p )
+{
+ assert(p->current != &p->stack[BRW_EU_MAX_INSN_STACK-1]);
+ memcpy(p->current+1, p->current, sizeof(struct brw_instruction));
+ p->current++;
+}
+
+void brw_pop_insn_state( struct brw_compile *p )
+{
+ assert(p->current != p->stack);
+ p->current--;
+}
+
+
+/***********************************************************************
+ */
+void brw_init_compile( struct brw_compile *p )
+{
+ p->nr_insn = 0;
+ p->current = p->stack;
+ memset(p->current, 0, sizeof(p->current[0]));
+
+ /* Some defaults?
+ */
+ brw_set_mask_control(p, BRW_MASK_ENABLE); /* what does this do? */
+ brw_set_saturate(p, 0);
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_set_predicate_control_flag_value(p, 0xff);
+}
+
+
+const unsigned *brw_get_program( struct brw_compile *p,
+ unsigned *sz )
+{
+ unsigned i;
+
+ for (i = 0; i < 8; i++)
+ brw_NOP(p);
+
+ *sz = p->nr_insn * sizeof(struct brw_instruction);
+ return (const unsigned *)p->store;
+}
+
diff --git a/src/gallium/drivers/i965simple/brw_eu.h b/src/gallium/drivers/i965simple/brw_eu.h
new file mode 100644
index 0000000000..23151ae9ed
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_eu.h
@@ -0,0 +1,888 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRW_EU_H
+#define BRW_EU_H
+
+#include "brw_structs.h"
+#include "brw_defines.h"
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_shader_tokens.h"
+
+#define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6))
+#define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
+
+#define BRW_SWIZZLE_NOOP BRW_SWIZZLE4(0,1,2,3)
+#define BRW_SWIZZLE_XYZW BRW_SWIZZLE4(0,1,2,3)
+#define BRW_SWIZZLE_XXXX BRW_SWIZZLE4(0,0,0,0)
+#define BRW_SWIZZLE_XYXY BRW_SWIZZLE4(0,1,0,1)
+
+
+#define REG_SIZE (8*4)
+
+
+/* These aren't hardware structs, just something useful for us to pass around:
+ *
+ * Align1 operation has a lot of control over input ranges. Used in
+ * WM programs to implement shaders decomposed into "channel serial"
+ * or "structure of array" form:
+ */
+struct brw_reg
+{
+ unsigned type:4;
+ unsigned file:2;
+ unsigned nr:8;
+ unsigned subnr:5; /* :1 in align16 */
+ unsigned negate:1; /* source only */
+ unsigned abs:1; /* source only */
+ unsigned vstride:4; /* source only */
+ unsigned width:3; /* src only, align1 only */
+ unsigned hstride:2; /* src only, align1 only */
+ unsigned address_mode:1; /* relative addressing, hopefully! */
+ unsigned pad0:1;
+
+ union {
+ struct {
+ unsigned swizzle:8; /* src only, align16 only */
+ unsigned writemask:4; /* dest only, align16 only */
+ int indirect_offset:10; /* relative addressing offset */
+ unsigned pad1:10; /* two dwords total */
+ } bits;
+
+ float f;
+ int d;
+ unsigned ud;
+ } dw1;
+};
+
+
+struct brw_indirect {
+ unsigned addr_subnr:4;
+ int addr_offset:10;
+ unsigned pad:18;
+};
+
+
+#define BRW_EU_MAX_INSN_STACK 5
+#define BRW_EU_MAX_INSN 1200
+
+struct brw_compile {
+ struct brw_instruction store[BRW_EU_MAX_INSN];
+ unsigned nr_insn;
+
+ /* Allow clients to push/pop instruction state:
+ */
+ struct brw_instruction stack[BRW_EU_MAX_INSN_STACK];
+ struct brw_instruction *current;
+
+ unsigned flag_value;
+ boolean single_program_flow;
+};
+
+
+
+static __inline int type_sz( unsigned type )
+{
+ switch( type ) {
+ case BRW_REGISTER_TYPE_UD:
+ case BRW_REGISTER_TYPE_D:
+ case BRW_REGISTER_TYPE_F:
+ return 4;
+ case BRW_REGISTER_TYPE_HF:
+ case BRW_REGISTER_TYPE_UW:
+ case BRW_REGISTER_TYPE_W:
+ return 2;
+ case BRW_REGISTER_TYPE_UB:
+ case BRW_REGISTER_TYPE_B:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static __inline struct brw_reg brw_reg( unsigned file,
+ unsigned nr,
+ unsigned subnr,
+ unsigned type,
+ unsigned vstride,
+ unsigned width,
+ unsigned hstride,
+ unsigned swizzle,
+ unsigned writemask)
+{
+
+ struct brw_reg reg;
+ reg.type = type;
+ reg.file = file;
+ reg.nr = nr;
+ reg.subnr = subnr * type_sz(type);
+ reg.negate = 0;
+ reg.abs = 0;
+ reg.vstride = vstride;
+ reg.width = width;
+ reg.hstride = hstride;
+ reg.address_mode = BRW_ADDRESS_DIRECT;
+ reg.pad0 = 0;
+
+ /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
+ * set swizzle and writemask to W, as the lower bits of subnr will
+ * be lost when converted to align16. This is probably too much to
+ * keep track of as you'd want it adjusted by suboffset(), etc.
+ * Perhaps fix up when converting to align16?
+ */
+ reg.dw1.bits.swizzle = swizzle;
+ reg.dw1.bits.writemask = writemask;
+ reg.dw1.bits.indirect_offset = 0;
+ reg.dw1.bits.pad1 = 0;
+ return reg;
+}
+
+static __inline struct brw_reg brw_vec16_reg( unsigned file,
+ unsigned nr,
+ unsigned subnr )
+{
+ return brw_reg(file,
+ nr,
+ subnr,
+ BRW_REGISTER_TYPE_F,
+ BRW_VERTICAL_STRIDE_16,
+ BRW_WIDTH_16,
+ BRW_HORIZONTAL_STRIDE_1,
+ BRW_SWIZZLE_XYZW,
+ TGSI_WRITEMASK_XYZW);
+}
+
+static __inline struct brw_reg brw_vec8_reg( unsigned file,
+ unsigned nr,
+ unsigned subnr )
+{
+ return brw_reg(file,
+ nr,
+ subnr,
+ BRW_REGISTER_TYPE_F,
+ BRW_VERTICAL_STRIDE_8,
+ BRW_WIDTH_8,
+ BRW_HORIZONTAL_STRIDE_1,
+ BRW_SWIZZLE_XYZW,
+ TGSI_WRITEMASK_XYZW);
+}
+
+
+static __inline struct brw_reg brw_vec4_reg( unsigned file,
+ unsigned nr,
+ unsigned subnr )
+{
+ return brw_reg(file,
+ nr,
+ subnr,
+ BRW_REGISTER_TYPE_F,
+ BRW_VERTICAL_STRIDE_4,
+ BRW_WIDTH_4,
+ BRW_HORIZONTAL_STRIDE_1,
+ BRW_SWIZZLE_XYZW,
+ TGSI_WRITEMASK_XYZW);
+}
+
+
+static __inline struct brw_reg brw_vec2_reg( unsigned file,
+ unsigned nr,
+ unsigned subnr )
+{
+ return brw_reg(file,
+ nr,
+ subnr,
+ BRW_REGISTER_TYPE_F,
+ BRW_VERTICAL_STRIDE_2,
+ BRW_WIDTH_2,
+ BRW_HORIZONTAL_STRIDE_1,
+ BRW_SWIZZLE_XYXY,
+ TGSI_WRITEMASK_XY);
+}
+
+static __inline struct brw_reg brw_vec1_reg( unsigned file,
+ unsigned nr,
+ unsigned subnr )
+{
+ return brw_reg(file,
+ nr,
+ subnr,
+ BRW_REGISTER_TYPE_F,
+ BRW_VERTICAL_STRIDE_0,
+ BRW_WIDTH_1,
+ BRW_HORIZONTAL_STRIDE_0,
+ BRW_SWIZZLE_XXXX,
+ TGSI_WRITEMASK_X);
+}
+
+
+static __inline struct brw_reg retype( struct brw_reg reg,
+ unsigned type )
+{
+ reg.type = type;
+ return reg;
+}
+
+static __inline struct brw_reg suboffset( struct brw_reg reg,
+ unsigned delta )
+{
+ reg.subnr += delta * type_sz(reg.type);
+ return reg;
+}
+
+
+static __inline struct brw_reg offset( struct brw_reg reg,
+ unsigned delta )
+{
+ reg.nr += delta;
+ return reg;
+}
+
+
+static __inline struct brw_reg byte_offset( struct brw_reg reg,
+ unsigned bytes )
+{
+ unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
+ reg.nr = newoffset / REG_SIZE;
+ reg.subnr = newoffset % REG_SIZE;
+ return reg;
+}
+
+
+static __inline struct brw_reg brw_uw16_reg( unsigned file,
+ unsigned nr,
+ unsigned subnr )
+{
+ return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
+}
+
+static __inline struct brw_reg brw_uw8_reg( unsigned file,
+ unsigned nr,
+ unsigned subnr )
+{
+ return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
+}
+
+static __inline struct brw_reg brw_uw1_reg( unsigned file,
+ unsigned nr,
+ unsigned subnr )
+{
+ return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
+}
+
+static __inline struct brw_reg brw_imm_reg( unsigned type )
+{
+ return brw_reg( BRW_IMMEDIATE_VALUE,
+ 0,
+ 0,
+ type,
+ BRW_VERTICAL_STRIDE_0,
+ BRW_WIDTH_1,
+ BRW_HORIZONTAL_STRIDE_0,
+ 0,
+ 0);
+}
+
+static __inline struct brw_reg brw_imm_f( float f )
+{
+ struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
+ imm.dw1.f = f;
+ return imm;
+}
+
+static __inline struct brw_reg brw_imm_d( int d )
+{
+ struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D);
+ imm.dw1.d = d;
+ return imm;
+}
+
+static __inline struct brw_reg brw_imm_ud( unsigned ud )
+{
+ struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD);
+ imm.dw1.ud = ud;
+ return imm;
+}
+
+static __inline struct brw_reg brw_imm_uw( ushort uw )
+{
+ struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
+ imm.dw1.ud = uw;
+ return imm;
+}
+
+static __inline struct brw_reg brw_imm_w( short w )
+{
+ struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
+ imm.dw1.d = w;
+ return imm;
+}
+
+/* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
+ * numbers alias with _V and _VF below:
+ */
+
+/* Vector of eight signed half-byte values:
+ */
+static __inline struct brw_reg brw_imm_v( unsigned v )
+{
+ struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V);
+ imm.vstride = BRW_VERTICAL_STRIDE_0;
+ imm.width = BRW_WIDTH_8;
+ imm.hstride = BRW_HORIZONTAL_STRIDE_1;
+ imm.dw1.ud = v;
+ return imm;
+}
+
+/* Vector of four 8-bit float values:
+ */
+static __inline struct brw_reg brw_imm_vf( unsigned v )
+{
+ struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
+ imm.vstride = BRW_VERTICAL_STRIDE_0;
+ imm.width = BRW_WIDTH_4;
+ imm.hstride = BRW_HORIZONTAL_STRIDE_1;
+ imm.dw1.ud = v;
+ return imm;
+}
+
+#define VF_ZERO 0x0
+#define VF_ONE 0x30
+#define VF_NEG (1<<7)
+
+static __inline struct brw_reg brw_imm_vf4( unsigned v0,
+ unsigned v1,
+ unsigned v2,
+ unsigned v3)
+{
+ struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
+ imm.vstride = BRW_VERTICAL_STRIDE_0;
+ imm.width = BRW_WIDTH_4;
+ imm.hstride = BRW_HORIZONTAL_STRIDE_1;
+ imm.dw1.ud = ((v0 << 0) |
+ (v1 << 8) |
+ (v2 << 16) |
+ (v3 << 24));
+ return imm;
+}
+
+
+static __inline struct brw_reg brw_address( struct brw_reg reg )
+{
+ return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
+}
+
+
+static __inline struct brw_reg brw_vec1_grf( unsigned nr,
+ unsigned subnr )
+{
+ return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
+}
+
+static __inline struct brw_reg brw_vec8_grf( unsigned nr,
+ unsigned subnr )
+{
+ return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
+}
+
+static __inline struct brw_reg brw_vec4_grf( unsigned nr,
+ unsigned subnr )
+{
+ return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
+}
+
+
+static __inline struct brw_reg brw_vec2_grf( unsigned nr,
+ unsigned subnr )
+{
+ return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
+}
+
+static __inline struct brw_reg brw_uw8_grf( unsigned nr,
+ unsigned subnr )
+{
+ return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
+}
+
+static __inline struct brw_reg brw_null_reg( void )
+{
+ return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE,
+ BRW_ARF_NULL,
+ 0);
+}
+
+static __inline struct brw_reg brw_address_reg( unsigned subnr )
+{
+ return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
+ BRW_ARF_ADDRESS,
+ subnr);
+}
+
+/* If/else instructions break in align16 mode if writemask & swizzle
+ * aren't xyzw. This goes against the convention for other scalar
+ * regs:
+ */
+static __inline struct brw_reg brw_ip_reg( void )
+{
+ return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
+ BRW_ARF_IP,
+ 0,
+ BRW_REGISTER_TYPE_UD,
+ BRW_VERTICAL_STRIDE_4, /* ? */
+ BRW_WIDTH_1,
+ BRW_HORIZONTAL_STRIDE_0,
+ BRW_SWIZZLE_XYZW, /* NOTE! */
+ TGSI_WRITEMASK_XYZW); /* NOTE! */
+}
+
+static __inline struct brw_reg brw_acc_reg( void )
+{
+ return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE,
+ BRW_ARF_ACCUMULATOR,
+ 0);
+}
+
+
+static __inline struct brw_reg brw_flag_reg( void )
+{
+ return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
+ BRW_ARF_FLAG,
+ 0);
+}
+
+
+static __inline struct brw_reg brw_mask_reg( unsigned subnr )
+{
+ return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
+ BRW_ARF_MASK,
+ subnr);
+}
+
+static __inline struct brw_reg brw_message_reg( unsigned nr )
+{
+ return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE,
+ nr,
+ 0);
+}
+
+
+
+
+/* This is almost always called with a numeric constant argument, so
+ * make things easy to evaluate at compile time:
+ */
+static __inline unsigned cvt( unsigned val )
+{
+ switch (val) {
+ case 0: return 0;
+ case 1: return 1;
+ case 2: return 2;
+ case 4: return 3;
+ case 8: return 4;
+ case 16: return 5;
+ case 32: return 6;
+ }
+ return 0;
+}
+
+static __inline struct brw_reg stride( struct brw_reg reg,
+ unsigned vstride,
+ unsigned width,
+ unsigned hstride )
+{
+
+ reg.vstride = cvt(vstride);
+ reg.width = cvt(width) - 1;
+ reg.hstride = cvt(hstride);
+ return reg;
+}
+
+static __inline struct brw_reg vec16( struct brw_reg reg )
+{
+ return stride(reg, 16,16,1);
+}
+
+static __inline struct brw_reg vec8( struct brw_reg reg )
+{
+ return stride(reg, 8,8,1);
+}
+
+static __inline struct brw_reg vec4( struct brw_reg reg )
+{
+ return stride(reg, 4,4,1);
+}
+
+static __inline struct brw_reg vec2( struct brw_reg reg )
+{
+ return stride(reg, 2,2,1);
+}
+
+static __inline struct brw_reg vec1( struct brw_reg reg )
+{
+ return stride(reg, 0,1,0);
+}
+
+static __inline struct brw_reg get_element( struct brw_reg reg, unsigned elt )
+{
+ return vec1(suboffset(reg, elt));
+}
+
+static __inline struct brw_reg get_element_ud( struct brw_reg reg, unsigned elt )
+{
+ return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt));
+}
+
+
+static __inline struct brw_reg brw_swizzle( struct brw_reg reg,
+ unsigned x,
+ unsigned y,
+ unsigned z,
+ unsigned w)
+{
+ reg.dw1.bits.swizzle = BRW_SWIZZLE4(BRW_GET_SWZ(reg.dw1.bits.swizzle, x),
+ BRW_GET_SWZ(reg.dw1.bits.swizzle, y),
+ BRW_GET_SWZ(reg.dw1.bits.swizzle, z),
+ BRW_GET_SWZ(reg.dw1.bits.swizzle, w));
+ return reg;
+}
+
+
+static __inline struct brw_reg brw_swizzle1( struct brw_reg reg,
+ unsigned x )
+{
+ return brw_swizzle(reg, x, x, x, x);
+}
+
+static __inline struct brw_reg brw_writemask( struct brw_reg reg,
+ unsigned mask )
+{
+ reg.dw1.bits.writemask &= mask;
+ return reg;
+}
+
+static __inline struct brw_reg brw_set_writemask( struct brw_reg reg,
+ unsigned mask )
+{
+ reg.dw1.bits.writemask = mask;
+ return reg;
+}
+
+static __inline struct brw_reg negate( struct brw_reg reg )
+{
+ reg.negate ^= 1;
+ return reg;
+}
+
+static __inline struct brw_reg brw_abs( struct brw_reg reg )
+{
+ reg.abs = 1;
+ return reg;
+}
+
+/***********************************************************************
+ */
+static __inline struct brw_reg brw_vec4_indirect( unsigned subnr,
+ int offset )
+{
+ struct brw_reg reg = brw_vec4_grf(0, 0);
+ reg.subnr = subnr;
+ reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
+ reg.dw1.bits.indirect_offset = offset;
+ return reg;
+}
+
+static __inline struct brw_reg brw_vec1_indirect( unsigned subnr,
+ int offset )
+{
+ struct brw_reg reg = brw_vec1_grf(0, 0);
+ reg.subnr = subnr;
+ reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
+ reg.dw1.bits.indirect_offset = offset;
+ return reg;
+}
+
+static __inline struct brw_reg deref_4f(struct brw_indirect ptr, int offset)
+{
+ return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
+}
+
+static __inline struct brw_reg deref_1f(struct brw_indirect ptr, int offset)
+{
+ return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
+}
+
+static __inline struct brw_reg deref_4b(struct brw_indirect ptr, int offset)
+{
+ return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B);
+}
+
+static __inline struct brw_reg deref_1uw(struct brw_indirect ptr, int offset)
+{
+ return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW);
+}
+
+static __inline struct brw_reg deref_1ud(struct brw_indirect ptr, int offset)
+{
+ return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD);
+}
+
+static __inline struct brw_reg get_addr_reg(struct brw_indirect ptr)
+{
+ return brw_address_reg(ptr.addr_subnr);
+}
+
+static __inline struct brw_indirect brw_indirect_offset( struct brw_indirect ptr, int offset )
+{
+ ptr.addr_offset += offset;
+ return ptr;
+}
+
+static __inline struct brw_indirect brw_indirect( unsigned addr_subnr, int offset )
+{
+ struct brw_indirect ptr;
+ ptr.addr_subnr = addr_subnr;
+ ptr.addr_offset = offset;
+ ptr.pad = 0;
+ return ptr;
+}
+
+static __inline struct brw_instruction *current_insn( struct brw_compile *p)
+{
+ return &p->store[p->nr_insn];
+}
+
+void brw_pop_insn_state( struct brw_compile *p );
+void brw_push_insn_state( struct brw_compile *p );
+void brw_set_mask_control( struct brw_compile *p, unsigned value );
+void brw_set_saturate( struct brw_compile *p, unsigned value );
+void brw_set_access_mode( struct brw_compile *p, unsigned access_mode );
+void brw_set_compression_control( struct brw_compile *p, boolean control );
+void brw_set_predicate_control_flag_value( struct brw_compile *p, unsigned value );
+void brw_set_predicate_control( struct brw_compile *p, unsigned pc );
+void brw_set_conditionalmod( struct brw_compile *p, unsigned conditional );
+
+void brw_init_compile( struct brw_compile *p );
+const unsigned *brw_get_program( struct brw_compile *p, unsigned *sz );
+
+
+struct brw_instruction *brw_alu1( struct brw_compile *p,
+ unsigned opcode,
+ struct brw_reg dest,
+ struct brw_reg src );
+
+struct brw_instruction *brw_alu2(struct brw_compile *p,
+ unsigned opcode,
+ struct brw_reg dest,
+ struct brw_reg src0,
+ struct brw_reg src1 );
+
+/* Helpers for regular instructions:
+ */
+#define ALU1(OP) \
+struct brw_instruction *brw_##OP(struct brw_compile *p, \
+ struct brw_reg dest, \
+ struct brw_reg src0);
+
+#define ALU2(OP) \
+struct brw_instruction *brw_##OP(struct brw_compile *p, \
+ struct brw_reg dest, \
+ struct brw_reg src0, \
+ struct brw_reg src1);
+
+ALU1(MOV)
+ALU2(SEL)
+ALU1(NOT)
+ALU2(AND)
+ALU2(OR)
+ALU2(XOR)
+ALU2(SHR)
+ALU2(SHL)
+ALU2(RSR)
+ALU2(RSL)
+ALU2(ASR)
+ALU2(JMPI)
+ALU2(ADD)
+ALU2(MUL)
+ALU1(FRC)
+ALU1(RNDD)
+ALU2(MAC)
+ALU2(MACH)
+ALU1(LZD)
+ALU2(DP4)
+ALU2(DPH)
+ALU2(DP3)
+ALU2(DP2)
+ALU2(LINE)
+
+#undef ALU1
+#undef ALU2
+
+
+
+/* Helpers for SEND instruction:
+ */
+void brw_urb_WRITE(struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned msg_reg_nr,
+ struct brw_reg src0,
+ boolean allocate,
+ boolean used,
+ unsigned msg_length,
+ unsigned response_length,
+ boolean eot,
+ boolean writes_complete,
+ unsigned offset,
+ unsigned swizzle);
+
+void brw_fb_WRITE(struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned msg_reg_nr,
+ struct brw_reg src0,
+ unsigned binding_table_index,
+ unsigned msg_length,
+ unsigned response_length,
+ boolean eot);
+
+void brw_SAMPLE(struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned msg_reg_nr,
+ struct brw_reg src0,
+ unsigned binding_table_index,
+ unsigned sampler,
+ unsigned writemask,
+ unsigned msg_type,
+ unsigned response_length,
+ unsigned msg_length,
+ boolean eot);
+
+void brw_math_16( struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned function,
+ unsigned saturate,
+ unsigned msg_reg_nr,
+ struct brw_reg src,
+ unsigned precision );
+
+void brw_math( struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned function,
+ unsigned saturate,
+ unsigned msg_reg_nr,
+ struct brw_reg src,
+ unsigned data_type,
+ unsigned precision );
+
+void brw_dp_READ_16( struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned msg_reg_nr,
+ unsigned scratch_offset );
+
+void brw_dp_WRITE_16( struct brw_compile *p,
+ struct brw_reg src,
+ unsigned msg_reg_nr,
+ unsigned scratch_offset );
+
+/* If/else/endif. Works by manipulating the execution flags on each
+ * channel.
+ */
+struct brw_instruction *brw_IF(struct brw_compile *p,
+ unsigned execute_size);
+
+struct brw_instruction *brw_ELSE(struct brw_compile *p,
+ struct brw_instruction *if_insn);
+
+void brw_ENDIF(struct brw_compile *p,
+ struct brw_instruction *if_or_else_insn);
+
+
+/* DO/WHILE loops:
+ */
+struct brw_instruction *brw_DO(struct brw_compile *p,
+ unsigned execute_size);
+
+struct brw_instruction *brw_WHILE(struct brw_compile *p,
+ struct brw_instruction *patch_insn);
+
+struct brw_instruction *brw_BREAK(struct brw_compile *p);
+struct brw_instruction *brw_CONT(struct brw_compile *p);
+/* Forward jumps:
+ */
+void brw_land_fwd_jump(struct brw_compile *p,
+ struct brw_instruction *jmp_insn);
+
+
+
+void brw_NOP(struct brw_compile *p);
+
+/* Special case: there is never a destination, execution size will be
+ * taken from src0:
+ */
+void brw_CMP(struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned conditional,
+ struct brw_reg src0,
+ struct brw_reg src1);
+
+void brw_print_reg( struct brw_reg reg );
+
+
+/***********************************************************************
+ * brw_eu_util.c:
+ */
+
+void brw_copy_indirect_to_indirect(struct brw_compile *p,
+ struct brw_indirect dst_ptr,
+ struct brw_indirect src_ptr,
+ unsigned count);
+
+void brw_copy_from_indirect(struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_indirect ptr,
+ unsigned count);
+
+void brw_copy4(struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg src,
+ unsigned count);
+
+void brw_copy8(struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg src,
+ unsigned count);
+
+void brw_math_invert( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg src);
+
+void brw_set_src1( struct brw_instruction *insn,
+ struct brw_reg reg );
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_eu_debug.c b/src/gallium/drivers/i965simple/brw_eu_debug.c
new file mode 100644
index 0000000000..4adfb0c02f
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_eu_debug.c
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "util/u_debug.h"
+
+#include "brw_eu.h"
+
+void brw_print_reg( struct brw_reg hwreg )
+{
+ static const char *file[] = {
+ "arf",
+ "grf",
+ "msg",
+ "imm"
+ };
+
+ static const char *type[] = {
+ "ud",
+ "d",
+ "uw",
+ "w",
+ "ub",
+ "vf",
+ "hf",
+ "f"
+ };
+
+ debug_printf("%s%s",
+ hwreg.abs ? "abs/" : "",
+ hwreg.negate ? "-" : "");
+
+ if (hwreg.file == BRW_GENERAL_REGISTER_FILE &&
+ hwreg.nr % 2 == 0 &&
+ hwreg.subnr == 0 &&
+ hwreg.vstride == BRW_VERTICAL_STRIDE_8 &&
+ hwreg.width == BRW_WIDTH_8 &&
+ hwreg.hstride == BRW_HORIZONTAL_STRIDE_1 &&
+ hwreg.type == BRW_REGISTER_TYPE_F) {
+ debug_printf("vec%d", hwreg.nr);
+ }
+ else if (hwreg.file == BRW_GENERAL_REGISTER_FILE &&
+ hwreg.vstride == BRW_VERTICAL_STRIDE_0 &&
+ hwreg.width == BRW_WIDTH_1 &&
+ hwreg.hstride == BRW_HORIZONTAL_STRIDE_0 &&
+ hwreg.type == BRW_REGISTER_TYPE_F) {
+ debug_printf("scl%d.%d", hwreg.nr, hwreg.subnr / 4);
+ }
+ else {
+ debug_printf("%s%d.%d<%d;%d,%d>:%s",
+ file[hwreg.file],
+ hwreg.nr,
+ hwreg.subnr / type_sz(hwreg.type),
+ hwreg.vstride ? (1<<(hwreg.vstride-1)) : 0,
+ 1<<hwreg.width,
+ hwreg.hstride ? (1<<(hwreg.hstride-1)) : 0,
+ type[hwreg.type]);
+ }
+}
+
+
+
diff --git a/src/gallium/drivers/i965simple/brw_eu_emit.c b/src/gallium/drivers/i965simple/brw_eu_emit.c
new file mode 100644
index 0000000000..400a80b6fb
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_eu_emit.c
@@ -0,0 +1,1080 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_defines.h"
+#include "brw_eu.h"
+
+
+
+
+/***********************************************************************
+ * Internal helper for constructing instructions
+ */
+
+static void guess_execution_size( struct brw_instruction *insn,
+ struct brw_reg reg )
+{
+ if (reg.width == BRW_WIDTH_8 &&
+ insn->header.compression_control == BRW_COMPRESSION_COMPRESSED)
+ insn->header.execution_size = BRW_EXECUTE_16;
+ else
+ insn->header.execution_size = reg.width; /* note - definitions are compatible */
+}
+
+
+static void brw_set_dest( struct brw_instruction *insn,
+ struct brw_reg dest )
+{
+ insn->bits1.da1.dest_reg_file = dest.file;
+ insn->bits1.da1.dest_reg_type = dest.type;
+ insn->bits1.da1.dest_address_mode = dest.address_mode;
+
+ if (dest.address_mode == BRW_ADDRESS_DIRECT) {
+ insn->bits1.da1.dest_reg_nr = dest.nr;
+
+ if (insn->header.access_mode == BRW_ALIGN_1) {
+ insn->bits1.da1.dest_subreg_nr = dest.subnr;
+ insn->bits1.da1.dest_horiz_stride = BRW_HORIZONTAL_STRIDE_1;
+ }
+ else {
+ insn->bits1.da16.dest_subreg_nr = dest.subnr / 16;
+ insn->bits1.da16.dest_writemask = dest.dw1.bits.writemask;
+ }
+ }
+ else {
+ insn->bits1.ia1.dest_subreg_nr = dest.subnr;
+
+ /* These are different sizes in align1 vs align16:
+ */
+ if (insn->header.access_mode == BRW_ALIGN_1) {
+ insn->bits1.ia1.dest_indirect_offset = dest.dw1.bits.indirect_offset;
+ insn->bits1.ia1.dest_horiz_stride = BRW_HORIZONTAL_STRIDE_1;
+ }
+ else {
+ insn->bits1.ia16.dest_indirect_offset = dest.dw1.bits.indirect_offset;
+ }
+ }
+
+ /* NEW: Set the execution size based on dest.width and
+ * insn->compression_control:
+ */
+ guess_execution_size(insn, dest);
+}
+
+static void brw_set_src0( struct brw_instruction *insn,
+ struct brw_reg reg )
+{
+ assert(reg.file != BRW_MESSAGE_REGISTER_FILE);
+
+ insn->bits1.da1.src0_reg_file = reg.file;
+ insn->bits1.da1.src0_reg_type = reg.type;
+ insn->bits2.da1.src0_abs = reg.abs;
+ insn->bits2.da1.src0_negate = reg.negate;
+ insn->bits2.da1.src0_address_mode = reg.address_mode;
+
+ if (reg.file == BRW_IMMEDIATE_VALUE) {
+ insn->bits3.ud = reg.dw1.ud;
+
+ /* Required to set some fields in src1 as well:
+ */
+ insn->bits1.da1.src1_reg_file = 0; /* arf */
+ insn->bits1.da1.src1_reg_type = reg.type;
+ }
+ else
+ {
+ if (reg.address_mode == BRW_ADDRESS_DIRECT) {
+ if (insn->header.access_mode == BRW_ALIGN_1) {
+ insn->bits2.da1.src0_subreg_nr = reg.subnr;
+ insn->bits2.da1.src0_reg_nr = reg.nr;
+ }
+ else {
+ insn->bits2.da16.src0_subreg_nr = reg.subnr / 16;
+ insn->bits2.da16.src0_reg_nr = reg.nr;
+ }
+ }
+ else {
+ insn->bits2.ia1.src0_subreg_nr = reg.subnr;
+
+ if (insn->header.access_mode == BRW_ALIGN_1) {
+ insn->bits2.ia1.src0_indirect_offset = reg.dw1.bits.indirect_offset;
+ }
+ else {
+ insn->bits2.ia16.src0_subreg_nr = reg.dw1.bits.indirect_offset;
+ }
+ }
+
+ if (insn->header.access_mode == BRW_ALIGN_1) {
+ if (reg.width == BRW_WIDTH_1 &&
+ insn->header.execution_size == BRW_EXECUTE_1) {
+ insn->bits2.da1.src0_horiz_stride = BRW_HORIZONTAL_STRIDE_0;
+ insn->bits2.da1.src0_width = BRW_WIDTH_1;
+ insn->bits2.da1.src0_vert_stride = BRW_VERTICAL_STRIDE_0;
+ }
+ else {
+ insn->bits2.da1.src0_horiz_stride = reg.hstride;
+ insn->bits2.da1.src0_width = reg.width;
+ insn->bits2.da1.src0_vert_stride = reg.vstride;
+ }
+ }
+ else {
+ insn->bits2.da16.src0_swz_x = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_X);
+ insn->bits2.da16.src0_swz_y = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Y);
+ insn->bits2.da16.src0_swz_z = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Z);
+ insn->bits2.da16.src0_swz_w = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_W);
+
+ /* This is an oddity of the fact we're using the same
+ * descriptions for registers in align_16 as align_1:
+ */
+ if (reg.vstride == BRW_VERTICAL_STRIDE_8)
+ insn->bits2.da16.src0_vert_stride = BRW_VERTICAL_STRIDE_4;
+ else
+ insn->bits2.da16.src0_vert_stride = reg.vstride;
+ }
+ }
+}
+
+
+void brw_set_src1( struct brw_instruction *insn,
+ struct brw_reg reg )
+{
+ assert(reg.file != BRW_MESSAGE_REGISTER_FILE);
+
+ insn->bits1.da1.src1_reg_file = reg.file;
+ insn->bits1.da1.src1_reg_type = reg.type;
+ insn->bits3.da1.src1_abs = reg.abs;
+ insn->bits3.da1.src1_negate = reg.negate;
+
+ /* Only src1 can be immediate in two-argument instructions.
+ */
+ assert(insn->bits1.da1.src0_reg_file != BRW_IMMEDIATE_VALUE);
+
+ if (reg.file == BRW_IMMEDIATE_VALUE) {
+ insn->bits3.ud = reg.dw1.ud;
+ }
+ else {
+ /* This is a hardware restriction, which may or may not be lifted
+ * in the future:
+ */
+ assert (reg.address_mode == BRW_ADDRESS_DIRECT);
+ //assert (reg.file == BRW_GENERAL_REGISTER_FILE);
+
+ if (insn->header.access_mode == BRW_ALIGN_1) {
+ insn->bits3.da1.src1_subreg_nr = reg.subnr;
+ insn->bits3.da1.src1_reg_nr = reg.nr;
+ }
+ else {
+ insn->bits3.da16.src1_subreg_nr = reg.subnr / 16;
+ insn->bits3.da16.src1_reg_nr = reg.nr;
+ }
+
+ if (insn->header.access_mode == BRW_ALIGN_1) {
+ if (reg.width == BRW_WIDTH_1 &&
+ insn->header.execution_size == BRW_EXECUTE_1) {
+ insn->bits3.da1.src1_horiz_stride = BRW_HORIZONTAL_STRIDE_0;
+ insn->bits3.da1.src1_width = BRW_WIDTH_1;
+ insn->bits3.da1.src1_vert_stride = BRW_VERTICAL_STRIDE_0;
+ }
+ else {
+ insn->bits3.da1.src1_horiz_stride = reg.hstride;
+ insn->bits3.da1.src1_width = reg.width;
+ insn->bits3.da1.src1_vert_stride = reg.vstride;
+ }
+ }
+ else {
+ insn->bits3.da16.src1_swz_x = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_X);
+ insn->bits3.da16.src1_swz_y = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Y);
+ insn->bits3.da16.src1_swz_z = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Z);
+ insn->bits3.da16.src1_swz_w = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_W);
+
+ /* This is an oddity of the fact we're using the same
+ * descriptions for registers in align_16 as align_1:
+ */
+ if (reg.vstride == BRW_VERTICAL_STRIDE_8)
+ insn->bits3.da16.src1_vert_stride = BRW_VERTICAL_STRIDE_4;
+ else
+ insn->bits3.da16.src1_vert_stride = reg.vstride;
+ }
+ }
+}
+
+
+
+static void brw_set_math_message( struct brw_instruction *insn,
+ unsigned msg_length,
+ unsigned response_length,
+ unsigned function,
+ unsigned integer_type,
+ boolean low_precision,
+ boolean saturate,
+ unsigned dataType )
+{
+ brw_set_src1(insn, brw_imm_d(0));
+
+ insn->bits3.math.function = function;
+ insn->bits3.math.int_type = integer_type;
+ insn->bits3.math.precision = low_precision;
+ insn->bits3.math.saturate = saturate;
+ insn->bits3.math.data_type = dataType;
+ insn->bits3.math.response_length = response_length;
+ insn->bits3.math.msg_length = msg_length;
+ insn->bits3.math.msg_target = BRW_MESSAGE_TARGET_MATH;
+ insn->bits3.math.end_of_thread = 0;
+}
+
+static void brw_set_urb_message( struct brw_instruction *insn,
+ boolean allocate,
+ boolean used,
+ unsigned msg_length,
+ unsigned response_length,
+ boolean end_of_thread,
+ boolean complete,
+ unsigned offset,
+ unsigned swizzle_control )
+{
+ brw_set_src1(insn, brw_imm_d(0));
+
+ insn->bits3.urb.opcode = 0; /* ? */
+ insn->bits3.urb.offset = offset;
+ insn->bits3.urb.swizzle_control = swizzle_control;
+ insn->bits3.urb.allocate = allocate;
+ insn->bits3.urb.used = used; /* ? */
+ insn->bits3.urb.complete = complete;
+ insn->bits3.urb.response_length = response_length;
+ insn->bits3.urb.msg_length = msg_length;
+ insn->bits3.urb.msg_target = BRW_MESSAGE_TARGET_URB;
+ insn->bits3.urb.end_of_thread = end_of_thread;
+}
+
+static void brw_set_dp_write_message( struct brw_instruction *insn,
+ unsigned binding_table_index,
+ unsigned msg_control,
+ unsigned msg_type,
+ unsigned msg_length,
+ unsigned pixel_scoreboard_clear,
+ unsigned response_length,
+ unsigned end_of_thread )
+{
+ brw_set_src1(insn, brw_imm_d(0));
+
+ insn->bits3.dp_write.binding_table_index = binding_table_index;
+ insn->bits3.dp_write.msg_control = msg_control;
+ insn->bits3.dp_write.pixel_scoreboard_clear = pixel_scoreboard_clear;
+ insn->bits3.dp_write.msg_type = msg_type;
+ insn->bits3.dp_write.send_commit_msg = 0;
+ insn->bits3.dp_write.response_length = response_length;
+ insn->bits3.dp_write.msg_length = msg_length;
+ insn->bits3.dp_write.msg_target = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
+ insn->bits3.urb.end_of_thread = end_of_thread;
+}
+
+static void brw_set_dp_read_message( struct brw_instruction *insn,
+ unsigned binding_table_index,
+ unsigned msg_control,
+ unsigned msg_type,
+ unsigned target_cache,
+ unsigned msg_length,
+ unsigned response_length,
+ unsigned end_of_thread )
+{
+ brw_set_src1(insn, brw_imm_d(0));
+
+ insn->bits3.dp_read.binding_table_index = binding_table_index;
+ insn->bits3.dp_read.msg_control = msg_control;
+ insn->bits3.dp_read.msg_type = msg_type;
+ insn->bits3.dp_read.target_cache = target_cache;
+ insn->bits3.dp_read.response_length = response_length;
+ insn->bits3.dp_read.msg_length = msg_length;
+ insn->bits3.dp_read.msg_target = BRW_MESSAGE_TARGET_DATAPORT_READ;
+ insn->bits3.dp_read.end_of_thread = end_of_thread;
+}
+
+static void brw_set_sampler_message( struct brw_instruction *insn,
+ unsigned binding_table_index,
+ unsigned sampler,
+ unsigned msg_type,
+ unsigned response_length,
+ unsigned msg_length,
+ boolean eot)
+{
+ brw_set_src1(insn, brw_imm_d(0));
+
+ insn->bits3.sampler.binding_table_index = binding_table_index;
+ insn->bits3.sampler.sampler = sampler;
+ insn->bits3.sampler.msg_type = msg_type;
+ insn->bits3.sampler.return_format = BRW_SAMPLER_RETURN_FORMAT_FLOAT32;
+ insn->bits3.sampler.response_length = response_length;
+ insn->bits3.sampler.msg_length = msg_length;
+ insn->bits3.sampler.end_of_thread = eot;
+ insn->bits3.sampler.msg_target = BRW_MESSAGE_TARGET_SAMPLER;
+}
+
+
+
+static struct brw_instruction *next_insn( struct brw_compile *p,
+ unsigned opcode )
+{
+ struct brw_instruction *insn;
+
+ assert(p->nr_insn + 1 < BRW_EU_MAX_INSN);
+
+ insn = &p->store[p->nr_insn++];
+ memcpy(insn, p->current, sizeof(*insn));
+
+ /* Reset this one-shot flag:
+ */
+
+ if (p->current->header.destreg__conditonalmod) {
+ p->current->header.destreg__conditonalmod = 0;
+ p->current->header.predicate_control = BRW_PREDICATE_NORMAL;
+ }
+
+ insn->header.opcode = opcode;
+ return insn;
+}
+
+
+struct brw_instruction *brw_alu1( struct brw_compile *p,
+ unsigned opcode,
+ struct brw_reg dest,
+ struct brw_reg src )
+{
+ struct brw_instruction *insn = next_insn(p, opcode);
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src);
+ return insn;
+}
+
+struct brw_instruction *brw_alu2(struct brw_compile *p,
+ unsigned opcode,
+ struct brw_reg dest,
+ struct brw_reg src0,
+ struct brw_reg src1 )
+{
+ struct brw_instruction *insn = next_insn(p, opcode);
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src0);
+ brw_set_src1(insn, src1);
+ return insn;
+}
+
+
+/***********************************************************************
+ * Convenience routines.
+ */
+#define ALU1(OP) \
+struct brw_instruction *brw_##OP(struct brw_compile *p, \
+ struct brw_reg dest, \
+ struct brw_reg src0) \
+{ \
+ return brw_alu1(p, BRW_OPCODE_##OP, dest, src0); \
+}
+
+#define ALU2(OP) \
+struct brw_instruction *brw_##OP(struct brw_compile *p, \
+ struct brw_reg dest, \
+ struct brw_reg src0, \
+ struct brw_reg src1) \
+{ \
+ return brw_alu2(p, BRW_OPCODE_##OP, dest, src0, src1); \
+}
+
+
+ALU1(MOV)
+ALU2(SEL)
+ALU1(NOT)
+ALU2(AND)
+ALU2(OR)
+ALU2(XOR)
+ALU2(SHR)
+ALU2(SHL)
+ALU2(RSR)
+ALU2(RSL)
+ALU2(ASR)
+ALU2(ADD)
+ALU2(MUL)
+ALU1(FRC)
+ALU1(RNDD)
+ALU2(MAC)
+ALU2(MACH)
+ALU1(LZD)
+ALU2(DP4)
+ALU2(DPH)
+ALU2(DP3)
+ALU2(DP2)
+ALU2(LINE)
+
+
+
+
+void brw_NOP(struct brw_compile *p)
+{
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_NOP);
+ brw_set_dest(insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD));
+ brw_set_src0(insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD));
+ brw_set_src1(insn, brw_imm_ud(0x0));
+}
+
+
+
+
+
+/***********************************************************************
+ * Comparisons, if/else/endif
+ */
+
+struct brw_instruction *brw_JMPI(struct brw_compile *p,
+ struct brw_reg dest,
+ struct brw_reg src0,
+ struct brw_reg src1)
+{
+ struct brw_instruction *insn = brw_alu2(p, BRW_OPCODE_JMPI, dest, src0, src1);
+
+ p->current->header.predicate_control = BRW_PREDICATE_NONE;
+
+ return insn;
+}
+
+/* EU takes the value from the flag register and pushes it onto some
+ * sort of a stack (presumably merging with any flag value already on
+ * the stack). Within an if block, the flags at the top of the stack
+ * control execution on each channel of the unit, eg. on each of the
+ * 16 pixel values in our wm programs.
+ *
+ * When the matching 'else' instruction is reached (presumably by
+ * countdown of the instruction count patched in by our ELSE/ENDIF
+ * functions), the relevent flags are inverted.
+ *
+ * When the matching 'endif' instruction is reached, the flags are
+ * popped off. If the stack is now empty, normal execution resumes.
+ *
+ * No attempt is made to deal with stack overflow (14 elements?).
+ */
+struct brw_instruction *brw_IF(struct brw_compile *p, unsigned execute_size)
+{
+ struct brw_instruction *insn;
+
+ if (p->single_program_flow) {
+ assert(execute_size == BRW_EXECUTE_1);
+
+ insn = next_insn(p, BRW_OPCODE_ADD);
+ insn->header.predicate_inverse = 1;
+ } else {
+ insn = next_insn(p, BRW_OPCODE_IF);
+ }
+
+ /* Override the defaults for this instruction:
+ */
+ brw_set_dest(insn, brw_ip_reg());
+ brw_set_src0(insn, brw_ip_reg());
+ brw_set_src1(insn, brw_imm_d(0x0));
+
+ insn->header.execution_size = execute_size;
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.predicate_control = BRW_PREDICATE_NORMAL;
+ insn->header.mask_control = BRW_MASK_ENABLE;
+
+ p->current->header.predicate_control = BRW_PREDICATE_NONE;
+
+ return insn;
+}
+
+
+struct brw_instruction *brw_ELSE(struct brw_compile *p,
+ struct brw_instruction *if_insn)
+{
+ struct brw_instruction *insn;
+
+ if (p->single_program_flow) {
+ insn = next_insn(p, BRW_OPCODE_ADD);
+ } else {
+ insn = next_insn(p, BRW_OPCODE_ELSE);
+ }
+
+ brw_set_dest(insn, brw_ip_reg());
+ brw_set_src0(insn, brw_ip_reg());
+ brw_set_src1(insn, brw_imm_d(0x0));
+
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.execution_size = if_insn->header.execution_size;
+ insn->header.mask_control = BRW_MASK_ENABLE;
+
+ /* Patch the if instruction to point at this instruction.
+ */
+ if (p->single_program_flow) {
+ assert(if_insn->header.opcode == BRW_OPCODE_ADD);
+
+ if_insn->bits3.ud = (insn - if_insn + 1) * 16;
+ } else {
+ assert(if_insn->header.opcode == BRW_OPCODE_IF);
+
+ if_insn->bits3.if_else.jump_count = insn - if_insn;
+ if_insn->bits3.if_else.pop_count = 1;
+ if_insn->bits3.if_else.pad0 = 0;
+ }
+
+ return insn;
+}
+
+void brw_ENDIF(struct brw_compile *p,
+ struct brw_instruction *patch_insn)
+{
+ if (p->single_program_flow) {
+ /* In single program flow mode, there's no need to execute an ENDIF,
+ * since we don't need to do any stack operations, and if we're executing
+ * currently, we want to just continue executing.
+ */
+ struct brw_instruction *next = &p->store[p->nr_insn];
+
+ assert(patch_insn->header.opcode == BRW_OPCODE_ADD);
+
+ patch_insn->bits3.ud = (next - patch_insn) * 16;
+ } else {
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_ENDIF);
+
+ brw_set_dest(insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD));
+ brw_set_src0(insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD));
+ brw_set_src1(insn, brw_imm_d(0x0));
+
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.execution_size = patch_insn->header.execution_size;
+ insn->header.mask_control = BRW_MASK_ENABLE;
+
+ assert(patch_insn->bits3.if_else.jump_count == 0);
+
+ /* Patch the if or else instructions to point at this or the next
+ * instruction respectively.
+ */
+ if (patch_insn->header.opcode == BRW_OPCODE_IF) {
+ /* Automagically turn it into an IFF:
+ */
+ patch_insn->header.opcode = BRW_OPCODE_IFF;
+ patch_insn->bits3.if_else.jump_count = insn - patch_insn + 1;
+ patch_insn->bits3.if_else.pop_count = 0;
+ patch_insn->bits3.if_else.pad0 = 0;
+ } else if (patch_insn->header.opcode == BRW_OPCODE_ELSE) {
+ patch_insn->bits3.if_else.jump_count = insn - patch_insn + 1;
+ patch_insn->bits3.if_else.pop_count = 1;
+ patch_insn->bits3.if_else.pad0 = 0;
+ } else {
+ assert(0);
+ }
+
+ /* Also pop item off the stack in the endif instruction:
+ */
+ insn->bits3.if_else.jump_count = 0;
+ insn->bits3.if_else.pop_count = 1;
+ insn->bits3.if_else.pad0 = 0;
+ }
+}
+
+struct brw_instruction *brw_BREAK(struct brw_compile *p)
+{
+ struct brw_instruction *insn;
+ insn = next_insn(p, BRW_OPCODE_BREAK);
+ brw_set_dest(insn, brw_ip_reg());
+ brw_set_src0(insn, brw_ip_reg());
+ brw_set_src1(insn, brw_imm_d(0x0));
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.execution_size = BRW_EXECUTE_8;
+ insn->header.mask_control = BRW_MASK_DISABLE;
+ insn->bits3.if_else.pad0 = 0;
+ return insn;
+}
+
+struct brw_instruction *brw_CONT(struct brw_compile *p)
+{
+ struct brw_instruction *insn;
+ insn = next_insn(p, BRW_OPCODE_CONTINUE);
+ brw_set_dest(insn, brw_ip_reg());
+ brw_set_src0(insn, brw_ip_reg());
+ brw_set_src1(insn, brw_imm_d(0x0));
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.execution_size = BRW_EXECUTE_8;
+ insn->header.mask_control = BRW_MASK_DISABLE;
+ insn->bits3.if_else.pad0 = 0;
+ return insn;
+}
+
+/* DO/WHILE loop:
+ */
+struct brw_instruction *brw_DO(struct brw_compile *p, unsigned execute_size)
+{
+ if (p->single_program_flow) {
+ return &p->store[p->nr_insn];
+ } else {
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_DO);
+
+ /* Override the defaults for this instruction:
+ */
+ brw_set_dest(insn, brw_null_reg());
+ brw_set_src0(insn, brw_null_reg());
+ brw_set_src1(insn, brw_null_reg());
+
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.execution_size = execute_size;
+ insn->header.predicate_control = BRW_PREDICATE_NONE;
+ /* insn->header.mask_control = BRW_MASK_ENABLE; */
+ insn->header.mask_control = BRW_MASK_DISABLE;
+
+ return insn;
+ }
+}
+
+
+
+struct brw_instruction *brw_WHILE(struct brw_compile *p,
+ struct brw_instruction *do_insn)
+{
+ struct brw_instruction *insn;
+
+ if (p->single_program_flow)
+ insn = next_insn(p, BRW_OPCODE_ADD);
+ else
+ insn = next_insn(p, BRW_OPCODE_WHILE);
+
+ brw_set_dest(insn, brw_ip_reg());
+ brw_set_src0(insn, brw_ip_reg());
+ brw_set_src1(insn, brw_imm_d(0x0));
+
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+
+ if (p->single_program_flow) {
+ insn->header.execution_size = BRW_EXECUTE_1;
+
+ insn->bits3.d = (do_insn - insn) * 16;
+ } else {
+ insn->header.execution_size = do_insn->header.execution_size;
+
+ assert(do_insn->header.opcode == BRW_OPCODE_DO);
+ insn->bits3.if_else.jump_count = do_insn - insn;
+ insn->bits3.if_else.pop_count = 0;
+ insn->bits3.if_else.pad0 = 0;
+ }
+
+/* insn->header.mask_control = BRW_MASK_ENABLE; */
+
+ insn->header.mask_control = BRW_MASK_DISABLE;
+ p->current->header.predicate_control = BRW_PREDICATE_NONE;
+ return insn;
+}
+
+
+/* FORWARD JUMPS:
+ */
+void brw_land_fwd_jump(struct brw_compile *p,
+ struct brw_instruction *jmp_insn)
+{
+ struct brw_instruction *landing = &p->store[p->nr_insn];
+
+ assert(jmp_insn->header.opcode == BRW_OPCODE_JMPI);
+ assert(jmp_insn->bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE);
+
+ jmp_insn->bits3.ud = (landing - jmp_insn) - 1;
+}
+
+
+
+/* To integrate with the above, it makes sense that the comparison
+ * instruction should populate the flag register. It might be simpler
+ * just to use the flag reg for most WM tasks?
+ */
+void brw_CMP(struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned conditional,
+ struct brw_reg src0,
+ struct brw_reg src1)
+{
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_CMP);
+
+ insn->header.destreg__conditonalmod = conditional;
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src0);
+ brw_set_src1(insn, src1);
+
+/* guess_execution_size(insn, src0); */
+
+
+ /* Make it so that future instructions will use the computed flag
+ * value until brw_set_predicate_control_flag_value() is called
+ * again.
+ */
+ if (dest.file == BRW_ARCHITECTURE_REGISTER_FILE &&
+ dest.nr == 0) {
+ p->current->header.predicate_control = BRW_PREDICATE_NORMAL;
+ p->flag_value = 0xff;
+ }
+}
+
+
+
+/***********************************************************************
+ * Helpers for the various SEND message types:
+ */
+
+/* Invert 8 values
+ */
+void brw_math( struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned function,
+ unsigned saturate,
+ unsigned msg_reg_nr,
+ struct brw_reg src,
+ unsigned data_type,
+ unsigned precision )
+{
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+ unsigned msg_length = (function == BRW_MATH_FUNCTION_POW) ? 2 : 1;
+ unsigned response_length = (function == BRW_MATH_FUNCTION_SINCOS) ? 2 : 1;
+
+ /* Example code doesn't set predicate_control for send
+ * instructions.
+ */
+ insn->header.predicate_control = 0;
+ insn->header.destreg__conditonalmod = msg_reg_nr;
+
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src);
+ brw_set_math_message(insn,
+ msg_length, response_length,
+ function,
+ BRW_MATH_INTEGER_UNSIGNED,
+ precision,
+ saturate,
+ data_type);
+}
+
+/* Use 2 send instructions to invert 16 elements
+ */
+void brw_math_16( struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned function,
+ unsigned saturate,
+ unsigned msg_reg_nr,
+ struct brw_reg src,
+ unsigned precision )
+{
+ struct brw_instruction *insn;
+ unsigned msg_length = (function == BRW_MATH_FUNCTION_POW) ? 2 : 1;
+ unsigned response_length = (function == BRW_MATH_FUNCTION_SINCOS) ? 2 : 1;
+
+ /* First instruction:
+ */
+ brw_push_insn_state(p);
+ brw_set_predicate_control_flag_value(p, 0xff);
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+
+ insn = next_insn(p, BRW_OPCODE_SEND);
+ insn->header.destreg__conditonalmod = msg_reg_nr;
+
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src);
+ brw_set_math_message(insn,
+ msg_length, response_length,
+ function,
+ BRW_MATH_INTEGER_UNSIGNED,
+ precision,
+ saturate,
+ BRW_MATH_DATA_VECTOR);
+
+ /* Second instruction:
+ */
+ insn = next_insn(p, BRW_OPCODE_SEND);
+ insn->header.compression_control = BRW_COMPRESSION_2NDHALF;
+ insn->header.destreg__conditonalmod = msg_reg_nr+1;
+
+ brw_set_dest(insn, offset(dest,1));
+ brw_set_src0(insn, src);
+ brw_set_math_message(insn,
+ msg_length, response_length,
+ function,
+ BRW_MATH_INTEGER_UNSIGNED,
+ precision,
+ saturate,
+ BRW_MATH_DATA_VECTOR);
+
+ brw_pop_insn_state(p);
+}
+
+
+
+
+void brw_dp_WRITE_16( struct brw_compile *p,
+ struct brw_reg src,
+ unsigned msg_reg_nr,
+ unsigned scratch_offset )
+{
+ {
+ brw_push_insn_state(p);
+ brw_set_mask_control(p, BRW_MASK_DISABLE);
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+
+ brw_MOV(p,
+ retype(brw_vec1_grf(0, 2), BRW_REGISTER_TYPE_D),
+ brw_imm_d(scratch_offset));
+
+ brw_pop_insn_state(p);
+ }
+
+ {
+ unsigned msg_length = 3;
+ struct brw_reg dest = retype(brw_null_reg(), BRW_REGISTER_TYPE_UW);
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+
+ insn->header.predicate_control = 0; /* XXX */
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.destreg__conditonalmod = msg_reg_nr;
+
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src);
+
+ brw_set_dp_write_message(insn,
+ 255, /* bti */
+ BRW_DATAPORT_OWORD_BLOCK_4_OWORDS, /* msg_control */
+ BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE, /* msg_type */
+ msg_length,
+ 0, /* pixel scoreboard */
+ 0, /* response_length */
+ 0); /* eot */
+ }
+
+}
+
+
+void brw_dp_READ_16( struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned msg_reg_nr,
+ unsigned scratch_offset )
+{
+ {
+ brw_push_insn_state(p);
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_set_mask_control(p, BRW_MASK_DISABLE);
+
+ brw_MOV(p,
+ retype(brw_vec1_grf(0, 2), BRW_REGISTER_TYPE_D),
+ brw_imm_d(scratch_offset));
+
+ brw_pop_insn_state(p);
+ }
+
+ {
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+
+ insn->header.predicate_control = 0; /* XXX */
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.destreg__conditonalmod = msg_reg_nr;
+
+ brw_set_dest(insn, dest); /* UW? */
+ brw_set_src0(insn, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW));
+
+ brw_set_dp_read_message(insn,
+ 255, /* bti */
+ 3, /* msg_control */
+ BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, /* msg_type */
+ 1, /* target cache */
+ 1, /* msg_length */
+ 2, /* response_length */
+ 0); /* eot */
+ }
+}
+
+
+void brw_fb_WRITE(struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned msg_reg_nr,
+ struct brw_reg src0,
+ unsigned binding_table_index,
+ unsigned msg_length,
+ unsigned response_length,
+ boolean eot)
+{
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+
+ insn->header.predicate_control = 0; /* XXX */
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.destreg__conditonalmod = msg_reg_nr;
+
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src0);
+ brw_set_dp_write_message(insn,
+ binding_table_index,
+ BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE, /* msg_control */
+ BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE, /* msg_type */
+ msg_length,
+ 1, /* pixel scoreboard */
+ response_length,
+ eot);
+}
+
+
+
+void brw_SAMPLE(struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned msg_reg_nr,
+ struct brw_reg src0,
+ unsigned binding_table_index,
+ unsigned sampler,
+ unsigned writemask,
+ unsigned msg_type,
+ unsigned response_length,
+ unsigned msg_length,
+ boolean eot)
+{
+ boolean need_stall = 0;
+
+ if(writemask == 0) {
+/* debug_printf("%s: zero writemask??\n", __FUNCTION__); */
+ return;
+ }
+
+ /* Hardware doesn't do destination dependency checking on send
+ * instructions properly. Add a workaround which generates the
+ * dependency by other means. In practice it seems like this bug
+ * only crops up for texture samples, and only where registers are
+ * written by the send and then written again later without being
+ * read in between. Luckily for us, we already track that
+ * information and use it to modify the writemask for the
+ * instruction, so that is a guide for whether a workaround is
+ * needed.
+ */
+ if (writemask != TGSI_WRITEMASK_XYZW) {
+ unsigned dst_offset = 0;
+ unsigned i, newmask = 0, len = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (writemask & (1<<i))
+ break;
+ dst_offset += 2;
+ }
+ for (; i < 4; i++) {
+ if (!(writemask & (1<<i)))
+ break;
+ newmask |= 1<<i;
+ len++;
+ }
+
+ if (newmask != writemask) {
+ need_stall = 1;
+/* debug_printf("need stall %x %x\n", newmask , writemask); */
+ }
+ else {
+ struct brw_reg m1 = brw_message_reg(msg_reg_nr);
+
+ newmask = ~newmask & TGSI_WRITEMASK_XYZW;
+
+ brw_push_insn_state(p);
+
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_set_mask_control(p, BRW_MASK_DISABLE);
+
+ brw_MOV(p, m1, brw_vec8_grf(0,0));
+ brw_MOV(p, get_element_ud(m1, 2), brw_imm_ud(newmask << 12));
+
+ brw_pop_insn_state(p);
+
+ src0 = retype(brw_null_reg(), BRW_REGISTER_TYPE_UW);
+ dest = offset(dest, dst_offset);
+ response_length = len * 2;
+ }
+ }
+
+ {
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+
+ insn->header.predicate_control = 0; /* XXX */
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.destreg__conditonalmod = msg_reg_nr;
+
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src0);
+ brw_set_sampler_message(insn,
+ binding_table_index,
+ sampler,
+ msg_type,
+ response_length,
+ msg_length,
+ eot);
+ }
+
+ if (need_stall)
+ {
+ struct brw_reg reg = vec8(offset(dest, response_length-1));
+
+ /* mov (8) r9.0<1>:f r9.0<8;8,1>:f { Align1 }
+ */
+ brw_push_insn_state(p);
+ brw_set_compression_control(p, FALSE);
+ brw_MOV(p, reg, reg);
+ brw_pop_insn_state(p);
+ }
+
+}
+
+/* All these variables are pretty confusing - we might be better off
+ * using bitmasks and macros for this, in the old style. Or perhaps
+ * just having the caller instantiate the fields in dword3 itself.
+ */
+void brw_urb_WRITE(struct brw_compile *p,
+ struct brw_reg dest,
+ unsigned msg_reg_nr,
+ struct brw_reg src0,
+ boolean allocate,
+ boolean used,
+ unsigned msg_length,
+ unsigned response_length,
+ boolean eot,
+ boolean writes_complete,
+ unsigned offset,
+ unsigned swizzle)
+{
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+
+ assert(msg_length < 16);
+
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src0);
+ brw_set_src1(insn, brw_imm_d(0));
+
+ insn->header.destreg__conditonalmod = msg_reg_nr;
+
+ brw_set_urb_message(insn,
+ allocate,
+ used,
+ msg_length,
+ response_length,
+ eot,
+ writes_complete,
+ offset,
+ swizzle);
+}
+
diff --git a/src/gallium/drivers/i965simple/brw_eu_util.c b/src/gallium/drivers/i965simple/brw_eu_util.c
new file mode 100644
index 0000000000..3a65b141f0
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_eu_util.c
@@ -0,0 +1,126 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_defines.h"
+#include "brw_eu.h"
+
+
+void brw_math_invert( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg src)
+{
+ brw_math( p,
+ dst,
+ BRW_MATH_FUNCTION_INV,
+ BRW_MATH_SATURATE_NONE,
+ 0,
+ src,
+ BRW_MATH_PRECISION_FULL,
+ BRW_MATH_DATA_VECTOR );
+}
+
+
+
+void brw_copy4(struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg src,
+ unsigned count)
+{
+ unsigned i;
+
+ dst = vec4(dst);
+ src = vec4(src);
+
+ for (i = 0; i < count; i++)
+ {
+ unsigned delta = i*32;
+ brw_MOV(p, byte_offset(dst, delta), byte_offset(src, delta));
+ brw_MOV(p, byte_offset(dst, delta+16), byte_offset(src, delta+16));
+ }
+}
+
+
+void brw_copy8(struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg src,
+ unsigned count)
+{
+ unsigned i;
+
+ dst = vec8(dst);
+ src = vec8(src);
+
+ for (i = 0; i < count; i++)
+ {
+ unsigned delta = i*32;
+ brw_MOV(p, byte_offset(dst, delta), byte_offset(src, delta));
+ }
+}
+
+
+void brw_copy_indirect_to_indirect(struct brw_compile *p,
+ struct brw_indirect dst_ptr,
+ struct brw_indirect src_ptr,
+ unsigned count)
+{
+ unsigned i;
+
+ for (i = 0; i < count; i++)
+ {
+ unsigned delta = i*32;
+ brw_MOV(p, deref_4f(dst_ptr, delta), deref_4f(src_ptr, delta));
+ brw_MOV(p, deref_4f(dst_ptr, delta+16), deref_4f(src_ptr, delta+16));
+ }
+}
+
+
+void brw_copy_from_indirect(struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_indirect ptr,
+ unsigned count)
+{
+ unsigned i;
+
+ dst = vec4(dst);
+
+ for (i = 0; i < count; i++)
+ {
+ unsigned delta = i*32;
+ brw_MOV(p, byte_offset(dst, delta), deref_4f(ptr, delta));
+ brw_MOV(p, byte_offset(dst, delta+16), deref_4f(ptr, delta+16));
+ }
+}
+
+
+
+
diff --git a/src/gallium/drivers/i965simple/brw_flush.c b/src/gallium/drivers/i965simple/brw_flush.c
new file mode 100644
index 0000000000..e6001c30d9
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_flush.c
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_defines.h"
+#include "brw_context.h"
+#include "brw_defines.h"
+#include "brw_batch.h"
+
+
+static void brw_flush( struct pipe_context *pipe,
+ unsigned flags,
+ struct pipe_fence_handle **fence )
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ /* Do we need to emit an MI_FLUSH command to flush the hardware
+ * caches?
+ */
+ if (flags & (PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE)) {
+ struct brw_mi_flush flush;
+
+ memset(&flush, 0, sizeof(flush));
+ flush.opcode = CMD_MI_FLUSH;
+
+ if (!(flags & PIPE_FLUSH_RENDER_CACHE))
+ flush.flags |= BRW_INHIBIT_FLUSH_RENDER_CACHE;
+
+ if (flags & PIPE_FLUSH_TEXTURE_CACHE)
+ flush.flags |= BRW_FLUSH_READ_CACHE;
+
+ BRW_BATCH_STRUCT(brw, &flush);
+ }
+
+ /* If there are no flags, just flush pending commands to hardware:
+ */
+ FLUSH_BATCH( fence );
+}
+
+
+
+void brw_init_flush_functions( struct brw_context *brw )
+{
+ brw->pipe.flush = brw_flush;
+}
diff --git a/src/gallium/drivers/i965simple/brw_gs.c b/src/gallium/drivers/i965simple/brw_gs.c
new file mode 100644
index 0000000000..de60868ccc
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_gs.c
@@ -0,0 +1,196 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_state.h"
+#include "brw_gs.h"
+
+
+
+static void compile_gs_prog( struct brw_context *brw,
+ struct brw_gs_prog_key *key )
+{
+ struct brw_gs_compile c;
+ const unsigned *program;
+ unsigned program_size;
+
+ memset(&c, 0, sizeof(c));
+
+ c.key = *key;
+
+ /* Need to locate the two positions present in vertex + header.
+ * These are currently hardcoded:
+ */
+ c.nr_attrs = brw_count_bits(c.key.attrs);
+ c.nr_regs = (c.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */
+ c.nr_bytes = c.nr_regs * REG_SIZE;
+
+
+ /* Begin the compilation:
+ */
+ brw_init_compile(&c.func);
+
+ c.func.single_program_flow = 1;
+
+ /* For some reason the thread is spawned with only 4 channels
+ * unmasked.
+ */
+ brw_set_mask_control(&c.func, BRW_MASK_DISABLE);
+
+
+ /* Note that primitives which don't require a GS program have
+ * already been weeded out by this stage:
+ */
+ switch (key->primitive) {
+ case PIPE_PRIM_QUADS:
+ brw_gs_quads( &c );
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ brw_gs_quad_strip( &c );
+ break;
+ case PIPE_PRIM_LINE_LOOP:
+ brw_gs_lines( &c );
+ break;
+ case PIPE_PRIM_LINES:
+ if (key->hint_gs_always)
+ brw_gs_lines( &c );
+ else {
+ return;
+ }
+ break;
+ case PIPE_PRIM_TRIANGLES:
+ if (key->hint_gs_always)
+ brw_gs_tris( &c );
+ else {
+ return;
+ }
+ break;
+ case PIPE_PRIM_POINTS:
+ if (key->hint_gs_always)
+ brw_gs_points( &c );
+ else {
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+
+ /* get the program
+ */
+ program = brw_get_program(&c.func, &program_size);
+
+ /* Upload
+ */
+ brw->gs.prog_gs_offset = brw_upload_cache( &brw->cache[BRW_GS_PROG],
+ &c.key,
+ sizeof(c.key),
+ program,
+ program_size,
+ &c.prog_data,
+ &brw->gs.prog_data );
+}
+
+
+static boolean search_cache( struct brw_context *brw,
+ struct brw_gs_prog_key *key )
+{
+ return brw_search_cache(&brw->cache[BRW_GS_PROG],
+ key, sizeof(*key),
+ &brw->gs.prog_data,
+ &brw->gs.prog_gs_offset);
+}
+
+
+static const int gs_prim[PIPE_PRIM_POLYGON+1] = {
+ PIPE_PRIM_POINTS,
+ PIPE_PRIM_LINES,
+ PIPE_PRIM_LINE_LOOP,
+ PIPE_PRIM_LINES,
+ PIPE_PRIM_TRIANGLES,
+ PIPE_PRIM_TRIANGLES,
+ PIPE_PRIM_TRIANGLES,
+ PIPE_PRIM_QUADS,
+ PIPE_PRIM_QUAD_STRIP,
+ PIPE_PRIM_TRIANGLES
+};
+
+static void populate_key( struct brw_context *brw,
+ struct brw_gs_prog_key *key )
+{
+ memset(key, 0, sizeof(*key));
+
+ /* CACHE_NEW_VS_PROG */
+ key->attrs = brw->vs.prog_data->outputs_written;
+
+ /* BRW_NEW_PRIMITIVE */
+ key->primitive = gs_prim[brw->primitive];
+
+ key->hint_gs_always = 0; /* debug code? */
+
+ key->need_gs_prog = (key->hint_gs_always ||
+ brw->primitive == PIPE_PRIM_QUADS ||
+ brw->primitive == PIPE_PRIM_QUAD_STRIP ||
+ brw->primitive == PIPE_PRIM_LINE_LOOP);
+}
+
+/* Calculate interpolants for triangle and line rasterization.
+ */
+static void upload_gs_prog( struct brw_context *brw )
+{
+ struct brw_gs_prog_key key;
+
+ /* Populate the key:
+ */
+ populate_key(brw, &key);
+
+ if (brw->gs.prog_active != key.need_gs_prog) {
+ brw->state.dirty.cache |= CACHE_NEW_GS_PROG;
+ brw->gs.prog_active = key.need_gs_prog;
+ }
+
+ if (brw->gs.prog_active) {
+ if (!search_cache(brw, &key))
+ compile_gs_prog( brw, &key );
+ }
+}
+
+
+const struct brw_tracked_state brw_gs_prog = {
+ .dirty = {
+ .brw = BRW_NEW_PRIMITIVE,
+ .cache = CACHE_NEW_VS_PROG
+ },
+ .update = upload_gs_prog
+};
diff --git a/src/gallium/drivers/i965simple/brw_gs.h b/src/gallium/drivers/i965simple/brw_gs.h
new file mode 100644
index 0000000000..f09141c6aa
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_gs.h
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRW_GS_H
+#define BRW_GS_H
+
+
+#include "brw_context.h"
+#include "brw_eu.h"
+
+#define MAX_GS_VERTS (4)
+
+struct brw_gs_prog_key {
+ unsigned attrs:32;
+ unsigned primitive:4;
+ unsigned hint_gs_always:1;
+ unsigned need_gs_prog:1;
+ unsigned pad:26;
+};
+
+struct brw_gs_compile {
+ struct brw_compile func;
+ struct brw_gs_prog_key key;
+ struct brw_gs_prog_data prog_data;
+
+ struct {
+ struct brw_reg R0;
+ struct brw_reg vertex[MAX_GS_VERTS];
+ } reg;
+
+ /* 3 different ways of expressing vertex size:
+ */
+ unsigned nr_attrs;
+ unsigned nr_regs;
+ unsigned nr_bytes;
+};
+
+#define ATTR_SIZE (4*4)
+
+void brw_gs_quads( struct brw_gs_compile *c );
+void brw_gs_quad_strip( struct brw_gs_compile *c );
+void brw_gs_tris( struct brw_gs_compile *c );
+void brw_gs_lines( struct brw_gs_compile *c );
+void brw_gs_points( struct brw_gs_compile *c );
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_gs_emit.c b/src/gallium/drivers/i965simple/brw_gs_emit.c
new file mode 100644
index 0000000000..c3cc90b10f
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_gs_emit.c
@@ -0,0 +1,148 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_gs.h"
+
+static void brw_gs_alloc_regs( struct brw_gs_compile *c,
+ unsigned nr_verts )
+{
+ unsigned i = 0,j;
+
+ /* Register usage is static, precompute here:
+ */
+ c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
+
+ /* Payload vertices plus space for more generated vertices:
+ */
+ for (j = 0; j < nr_verts; j++) {
+ c->reg.vertex[j] = brw_vec4_grf(i, 0);
+ i += c->nr_regs;
+ }
+
+ c->prog_data.urb_read_length = c->nr_regs;
+ c->prog_data.total_grf = i;
+}
+
+
+static void brw_gs_emit_vue(struct brw_gs_compile *c,
+ struct brw_reg vert,
+ boolean last,
+ unsigned header)
+{
+ struct brw_compile *p = &c->func;
+ boolean allocate = !last;
+
+ /* Overwrite PrimType and PrimStart in the message header, for
+ * each vertex in turn:
+ */
+ brw_MOV(p, get_element_ud(c->reg.R0, 2), brw_imm_ud(header));
+
+ /* Copy the vertex from vertn into m1..mN+1:
+ */
+ brw_copy8(p, brw_message_reg(1), vert, c->nr_regs);
+
+ /* Send each vertex as a seperate write to the urb. This is
+ * different to the concept in brw_sf_emit.c, where subsequent
+ * writes are used to build up a single urb entry. Each of these
+ * writes instantiates a seperate urb entry, and a new one must be
+ * allocated each time.
+ */
+ brw_urb_WRITE(p,
+ allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
+ 0,
+ c->reg.R0,
+ allocate,
+ 1, /* used */
+ c->nr_regs + 1, /* msg length */
+ allocate ? 1 : 0, /* response length */
+ allocate ? 0 : 1, /* eot */
+ 1, /* writes_complete */
+ 0, /* urb offset */
+ BRW_URB_SWIZZLE_NONE);
+}
+
+
+
+void brw_gs_quads( struct brw_gs_compile *c )
+{
+ brw_gs_alloc_regs(c, 4);
+
+ /* Use polygons for correct edgeflag behaviour. Note that vertex 3
+ * is the PV for quads, but vertex 0 for polygons:
+ */
+ brw_gs_emit_vue(c, c->reg.vertex[3], 0, ((_3DPRIM_POLYGON << 2) | R02_PRIM_START));
+ brw_gs_emit_vue(c, c->reg.vertex[0], 0, (_3DPRIM_POLYGON << 2));
+ brw_gs_emit_vue(c, c->reg.vertex[1], 0, (_3DPRIM_POLYGON << 2));
+ brw_gs_emit_vue(c, c->reg.vertex[2], 1, ((_3DPRIM_POLYGON << 2) | R02_PRIM_END));
+}
+
+void brw_gs_quad_strip( struct brw_gs_compile *c )
+{
+ brw_gs_alloc_regs(c, 4);
+
+ brw_gs_emit_vue(c, c->reg.vertex[2], 0, ((_3DPRIM_POLYGON << 2) | R02_PRIM_START));
+ brw_gs_emit_vue(c, c->reg.vertex[3], 0, (_3DPRIM_POLYGON << 2));
+ brw_gs_emit_vue(c, c->reg.vertex[0], 0, (_3DPRIM_POLYGON << 2));
+ brw_gs_emit_vue(c, c->reg.vertex[1], 1, ((_3DPRIM_POLYGON << 2) | R02_PRIM_END));
+}
+
+void brw_gs_tris( struct brw_gs_compile *c )
+{
+ brw_gs_alloc_regs(c, 3);
+ brw_gs_emit_vue(c, c->reg.vertex[0], 0, ((_3DPRIM_TRILIST << 2) | R02_PRIM_START));
+ brw_gs_emit_vue(c, c->reg.vertex[1], 0, (_3DPRIM_TRILIST << 2));
+ brw_gs_emit_vue(c, c->reg.vertex[2], 1, ((_3DPRIM_TRILIST << 2) | R02_PRIM_END));
+}
+
+void brw_gs_lines( struct brw_gs_compile *c )
+{
+ brw_gs_alloc_regs(c, 2);
+ brw_gs_emit_vue(c, c->reg.vertex[0], 0, ((_3DPRIM_LINESTRIP << 2) | R02_PRIM_START));
+ brw_gs_emit_vue(c, c->reg.vertex[1], 1, ((_3DPRIM_LINESTRIP << 2) | R02_PRIM_END));
+}
+
+void brw_gs_points( struct brw_gs_compile *c )
+{
+ brw_gs_alloc_regs(c, 1);
+ brw_gs_emit_vue(c, c->reg.vertex[0], 1, ((_3DPRIM_POINTLIST << 2) | R02_PRIM_START | R02_PRIM_END));
+}
+
+
+
+
+
+
+
+
diff --git a/src/gallium/drivers/i965simple/brw_gs_state.c b/src/gallium/drivers/i965simple/brw_gs_state.c
new file mode 100644
index 0000000000..5b8016b2e9
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_gs_state.c
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+
+
+static void upload_gs_unit( struct brw_context *brw )
+{
+ struct brw_gs_unit_state gs;
+
+ memset(&gs, 0, sizeof(gs));
+
+ /* CACHE_NEW_GS_PROG */
+ if (brw->gs.prog_active) {
+ gs.thread0.grf_reg_count =
+ align(brw->gs.prog_data->total_grf, 16) / 16 - 1;
+ gs.thread0.kernel_start_pointer = brw->gs.prog_gs_offset >> 6;
+ gs.thread3.urb_entry_read_length = brw->gs.prog_data->urb_read_length;
+ }
+ else {
+ gs.thread0.grf_reg_count = 0;
+ gs.thread0.kernel_start_pointer = 0;
+ gs.thread3.urb_entry_read_length = 1;
+ }
+
+ /* BRW_NEW_URB_FENCE */
+ gs.thread4.nr_urb_entries = brw->urb.nr_gs_entries;
+ gs.thread4.urb_entry_allocation_size = brw->urb.vsize - 1;
+
+ gs.thread4.max_threads = 0; /* Hardware requirement */
+
+ if (BRW_DEBUG & DEBUG_STATS)
+ gs.thread4.stats_enable = 1;
+
+ /* CONSTANT */
+ gs.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
+ gs.thread1.single_program_flow = 1;
+ gs.thread3.dispatch_grf_start_reg = 1;
+ gs.thread3.const_urb_entry_read_offset = 0;
+ gs.thread3.const_urb_entry_read_length = 0;
+ gs.thread3.urb_entry_read_offset = 0;
+
+
+ brw->gs.state_gs_offset = brw_cache_data( &brw->cache[BRW_GS_UNIT], &gs );
+}
+
+
+const struct brw_tracked_state brw_gs_unit = {
+ .dirty = {
+ .brw = (BRW_NEW_CURBE_OFFSETS |
+ BRW_NEW_URB_FENCE),
+ .cache = CACHE_NEW_GS_PROG
+ },
+ .update = upload_gs_unit
+};
diff --git a/src/gallium/drivers/i965simple/brw_misc_state.c b/src/gallium/drivers/i965simple/brw_misc_state.c
new file mode 100644
index 0000000000..99ff4403a5
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_misc_state.c
@@ -0,0 +1,488 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_batch.h"
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+
+
+
+
+
+/***********************************************************************
+ * Blend color
+ */
+
+static void upload_blend_constant_color(struct brw_context *brw)
+{
+ struct brw_blend_constant_color bcc;
+
+ memset(&bcc, 0, sizeof(bcc));
+ bcc.header.opcode = CMD_BLEND_CONSTANT_COLOR;
+ bcc.header.length = sizeof(bcc)/4-2;
+ bcc.blend_constant_color[0] = brw->attribs.BlendColor.color[0];
+ bcc.blend_constant_color[1] = brw->attribs.BlendColor.color[1];
+ bcc.blend_constant_color[2] = brw->attribs.BlendColor.color[2];
+ bcc.blend_constant_color[3] = brw->attribs.BlendColor.color[3];
+
+ BRW_CACHED_BATCH_STRUCT(brw, &bcc);
+}
+
+
+const struct brw_tracked_state brw_blend_constant_color = {
+ .dirty = {
+ .brw = BRW_NEW_BLEND,
+ .cache = 0
+ },
+ .update = upload_blend_constant_color
+};
+
+
+/***********************************************************************
+ * Drawing rectangle
+ */
+static void upload_drawing_rect(struct brw_context *brw)
+{
+ struct brw_drawrect bdr;
+
+ memset(&bdr, 0, sizeof(bdr));
+ bdr.header.opcode = CMD_DRAW_RECT;
+ bdr.header.length = sizeof(bdr)/4 - 2;
+ bdr.xmin = 0;
+ bdr.ymin = 0;
+ bdr.xmax = brw->attribs.FrameBuffer.cbufs[0]->width;
+ bdr.ymax = brw->attribs.FrameBuffer.cbufs[0]->height;
+ bdr.xorg = 0;
+ bdr.yorg = 0;
+
+ /* Can't use BRW_CACHED_BATCH_STRUCT because this is also emitted
+ * uncached in brw_draw.c:
+ */
+ BRW_BATCH_STRUCT(brw, &bdr);
+}
+
+const struct brw_tracked_state brw_drawing_rect = {
+ .dirty = {
+ .brw = BRW_NEW_SCENE,
+ .cache = 0
+ },
+ .update = upload_drawing_rect
+};
+
+/**
+ * Upload the binding table pointers, which point each stage's array of surface
+ * state pointers.
+ *
+ * The binding table pointers are relative to the surface state base address,
+ * which is the BRW_SS_POOL cache buffer.
+ */
+static void upload_binding_table_pointers(struct brw_context *brw)
+{
+ struct brw_binding_table_pointers btp;
+ memset(&btp, 0, sizeof(btp));
+
+ btp.header.opcode = CMD_BINDING_TABLE_PTRS;
+ btp.header.length = sizeof(btp)/4 - 2;
+ btp.vs = 0;
+ btp.gs = 0;
+ btp.clp = 0;
+ btp.sf = 0;
+ btp.wm = brw->wm.bind_ss_offset;
+
+ BRW_CACHED_BATCH_STRUCT(brw, &btp);
+}
+
+const struct brw_tracked_state brw_binding_table_pointers = {
+ .dirty = {
+ .brw = 0,
+ .cache = CACHE_NEW_SURF_BIND
+ },
+ .update = upload_binding_table_pointers,
+};
+
+
+/**
+ * Upload pointers to the per-stage state.
+ *
+ * The state pointers in this packet are all relative to the general state
+ * base address set by CMD_STATE_BASE_ADDRESS, which is the BRW_GS_POOL buffer.
+ */
+static void upload_pipelined_state_pointers(struct brw_context *brw )
+{
+ struct brw_pipelined_state_pointers psp;
+ memset(&psp, 0, sizeof(psp));
+
+ psp.header.opcode = CMD_PIPELINED_STATE_POINTERS;
+ psp.header.length = sizeof(psp)/4 - 2;
+
+ psp.vs.offset = brw->vs.state_gs_offset >> 5;
+ psp.sf.offset = brw->sf.state_gs_offset >> 5;
+ psp.wm.offset = brw->wm.state_gs_offset >> 5;
+ psp.cc.offset = brw->cc.state_gs_offset >> 5;
+
+ /* GS gets turned on and off regularly. Need to re-emit URB fence
+ * after this occurs.
+ */
+ if (brw->gs.prog_active) {
+ psp.gs.offset = brw->gs.state_gs_offset >> 5;
+ psp.gs.enable = 1;
+ }
+
+ if (0) {
+ psp.clp.offset = brw->clip.state_gs_offset >> 5;
+ psp.clp.enable = 1;
+ }
+
+
+ if (BRW_CACHED_BATCH_STRUCT(brw, &psp))
+ brw->state.dirty.brw |= BRW_NEW_PSP;
+}
+
+const struct brw_tracked_state brw_pipelined_state_pointers = {
+ .dirty = {
+ .brw = 0,
+ .cache = (CACHE_NEW_VS_UNIT |
+ CACHE_NEW_GS_UNIT |
+ CACHE_NEW_GS_PROG |
+ CACHE_NEW_CLIP_UNIT |
+ CACHE_NEW_SF_UNIT |
+ CACHE_NEW_WM_UNIT |
+ CACHE_NEW_CC_UNIT)
+ },
+ .update = upload_pipelined_state_pointers
+};
+
+static void upload_psp_urb_cbs(struct brw_context *brw )
+{
+ upload_pipelined_state_pointers(brw);
+ brw_upload_urb_fence(brw);
+ brw_upload_constant_buffer_state(brw);
+}
+
+
+const struct brw_tracked_state brw_psp_urb_cbs = {
+ .dirty = {
+ .brw = BRW_NEW_URB_FENCE,
+ .cache = (CACHE_NEW_VS_UNIT |
+ CACHE_NEW_GS_UNIT |
+ CACHE_NEW_GS_PROG |
+ CACHE_NEW_CLIP_UNIT |
+ CACHE_NEW_SF_UNIT |
+ CACHE_NEW_WM_UNIT |
+ CACHE_NEW_CC_UNIT)
+ },
+ .update = upload_psp_urb_cbs
+};
+
+/**
+ * Upload the depthbuffer offset and format.
+ *
+ * We have to do this per state validation as we need to emit the relocation
+ * in the batch buffer.
+ */
+static void upload_depthbuffer(struct brw_context *brw)
+{
+ struct pipe_surface *depth_surface = brw->attribs.FrameBuffer.zsbuf;
+
+ BEGIN_BATCH(5, INTEL_BATCH_NO_CLIPRECTS);
+ OUT_BATCH(CMD_DEPTH_BUFFER << 16 | (5 - 2));
+ if (depth_surface == NULL) {
+ OUT_BATCH((BRW_DEPTHFORMAT_D32_FLOAT << 18) |
+ (BRW_SURFACE_NULL << 29));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ } else {
+ unsigned int format;
+ struct brw_texture *tex = (struct brw_texture *)depth_surface->texture;
+ assert(depth_surface->block.width == 1);
+ assert(depth_surface->block.height == 1);
+ switch (depth_surface->block.size) {
+ case 2:
+ format = BRW_DEPTHFORMAT_D16_UNORM;
+ break;
+ case 4:
+ if (depth_surface->format == PIPE_FORMAT_Z32_FLOAT)
+ format = BRW_DEPTHFORMAT_D32_FLOAT;
+ else
+ format = BRW_DEPTHFORMAT_D24_UNORM_S8_UINT;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ OUT_BATCH((depth_surface->stride - 1) |
+ (format << 18) |
+ (BRW_TILEWALK_YMAJOR << 26) |
+// (depth_surface->region->tiled << 27) |
+ (BRW_SURFACE_2D << 29));
+ OUT_RELOC(tex->buffer,
+ PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE, 0);
+ OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) |
+ ((depth_surface->stride/depth_surface->block.size - 1) << 6) |
+ ((depth_surface->height - 1) << 19));
+ OUT_BATCH(0);
+ }
+ ADVANCE_BATCH();
+}
+
+const struct brw_tracked_state brw_depthbuffer = {
+ .dirty = {
+ .brw = BRW_NEW_SCENE,
+ .cache = 0
+ },
+ .update = upload_depthbuffer,
+};
+
+
+
+
+/***********************************************************************
+ * Polygon stipple packet
+ */
+
+static void upload_polygon_stipple(struct brw_context *brw)
+{
+ struct brw_polygon_stipple bps;
+ unsigned i;
+
+ memset(&bps, 0, sizeof(bps));
+ bps.header.opcode = CMD_POLY_STIPPLE_PATTERN;
+ bps.header.length = sizeof(bps)/4-2;
+
+ /* XXX: state tracker should send *all* state down initially!
+ */
+ if (brw->attribs.PolygonStipple)
+ for (i = 0; i < 32; i++)
+ bps.stipple[i] = brw->attribs.PolygonStipple->stipple[31 - i]; /* invert */
+
+ BRW_CACHED_BATCH_STRUCT(brw, &bps);
+}
+
+const struct brw_tracked_state brw_polygon_stipple = {
+ .dirty = {
+ .brw = BRW_NEW_STIPPLE,
+ .cache = 0
+ },
+ .update = upload_polygon_stipple
+};
+
+
+/***********************************************************************
+ * Line stipple packet
+ */
+
+static void upload_line_stipple(struct brw_context *brw)
+{
+ struct brw_line_stipple bls;
+ float tmp;
+ int tmpi;
+
+ memset(&bls, 0, sizeof(bls));
+ bls.header.opcode = CMD_LINE_STIPPLE_PATTERN;
+ bls.header.length = sizeof(bls)/4 - 2;
+
+ bls.bits0.pattern = brw->attribs.Raster->line_stipple_pattern;
+ bls.bits1.repeat_count = brw->attribs.Raster->line_stipple_factor;
+
+ tmp = 1.0 / (float) brw->attribs.Raster->line_stipple_factor;
+ tmpi = tmp * (1<<13);
+
+
+ bls.bits1.inverse_repeat_count = tmpi;
+
+ BRW_CACHED_BATCH_STRUCT(brw, &bls);
+}
+
+const struct brw_tracked_state brw_line_stipple = {
+ .dirty = {
+ .brw = BRW_NEW_STIPPLE,
+ .cache = 0
+ },
+ .update = upload_line_stipple
+};
+
+
+/***********************************************************************
+ * Misc constant state packets
+ */
+
+static void upload_pipe_control(struct brw_context *brw)
+{
+ struct brw_pipe_control pc;
+
+ return;
+
+ memset(&pc, 0, sizeof(pc));
+
+ pc.header.opcode = CMD_PIPE_CONTROL;
+ pc.header.length = sizeof(pc)/4 - 2;
+ pc.header.post_sync_operation = PIPE_CONTROL_NOWRITE;
+
+ pc.header.instruction_state_cache_flush_enable = 1;
+
+ pc.bits1.dest_addr_type = PIPE_CONTROL_GTTWRITE_GLOBAL;
+
+ BRW_BATCH_STRUCT(brw, &pc);
+}
+
+const struct brw_tracked_state brw_pipe_control = {
+ .dirty = {
+ .brw = BRW_NEW_SCENE,
+ .cache = 0
+ },
+ .update = upload_pipe_control
+};
+
+
+/***********************************************************************
+ * Misc invarient state packets
+ */
+
+static void upload_invarient_state( struct brw_context *brw )
+{
+ {
+ struct brw_mi_flush flush;
+
+ memset(&flush, 0, sizeof(flush));
+ flush.opcode = CMD_MI_FLUSH;
+ flush.flags = BRW_FLUSH_STATE_CACHE | BRW_FLUSH_READ_CACHE;
+ BRW_BATCH_STRUCT(brw, &flush);
+ }
+
+ {
+ /* 0x61040000 Pipeline Select */
+ /* PipelineSelect : 0 */
+ struct brw_pipeline_select ps;
+
+ memset(&ps, 0, sizeof(ps));
+ ps.header.opcode = CMD_PIPELINE_SELECT;
+ ps.header.pipeline_select = 0;
+ BRW_BATCH_STRUCT(brw, &ps);
+ }
+
+ {
+ struct brw_global_depth_offset_clamp gdo;
+ memset(&gdo, 0, sizeof(gdo));
+
+ /* Disable depth offset clamping.
+ */
+ gdo.header.opcode = CMD_GLOBAL_DEPTH_OFFSET_CLAMP;
+ gdo.header.length = sizeof(gdo)/4 - 2;
+ gdo.depth_offset_clamp = 0.0;
+
+ BRW_BATCH_STRUCT(brw, &gdo);
+ }
+
+
+ /* 0x61020000 State Instruction Pointer */
+ {
+ struct brw_system_instruction_pointer sip;
+ memset(&sip, 0, sizeof(sip));
+
+ sip.header.opcode = CMD_STATE_INSN_POINTER;
+ sip.header.length = 0;
+ sip.bits0.pad = 0;
+ sip.bits0.system_instruction_pointer = 0;
+ BRW_BATCH_STRUCT(brw, &sip);
+ }
+
+
+ {
+ struct brw_vf_statistics vfs;
+ memset(&vfs, 0, sizeof(vfs));
+
+ vfs.opcode = CMD_VF_STATISTICS;
+ if (BRW_DEBUG & DEBUG_STATS)
+ vfs.statistics_enable = 1;
+
+ BRW_BATCH_STRUCT(brw, &vfs);
+ }
+
+
+ {
+ struct brw_polygon_stipple_offset bpso;
+
+ memset(&bpso, 0, sizeof(bpso));
+ bpso.header.opcode = CMD_POLY_STIPPLE_OFFSET;
+ bpso.header.length = sizeof(bpso)/4-2;
+ bpso.bits0.x_offset = 0;
+ bpso.bits0.y_offset = 0;
+
+ BRW_BATCH_STRUCT(brw, &bpso);
+ }
+}
+
+const struct brw_tracked_state brw_invarient_state = {
+ .dirty = {
+ .brw = BRW_NEW_SCENE,
+ .cache = 0
+ },
+ .update = upload_invarient_state
+};
+
+/**
+ * Define the base addresses which some state is referenced from.
+ *
+ * This allows us to avoid having to emit relocations in many places for
+ * cached state, and instead emit pointers inside of large, mostly-static
+ * state pools. This comes at the expense of memory, and more expensive cache
+ * misses.
+ */
+static void upload_state_base_address( struct brw_context *brw )
+{
+ /* Output the structure (brw_state_base_address) directly to the
+ * batchbuffer, so we can emit relocations inline.
+ */
+ BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
+ OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2));
+ OUT_RELOC(brw->pool[BRW_GS_POOL].buffer,
+ PIPE_BUFFER_USAGE_GPU_READ,
+ 1); /* General state base address */
+ OUT_RELOC(brw->pool[BRW_SS_POOL].buffer,
+ PIPE_BUFFER_USAGE_GPU_READ,
+ 1); /* Surface state base address */
+ OUT_BATCH(1); /* Indirect object base address */
+ OUT_BATCH(1); /* General state upper bound */
+ OUT_BATCH(1); /* Indirect object upper bound */
+ ADVANCE_BATCH();
+}
+
+
+const struct brw_tracked_state brw_state_base_address = {
+ .dirty = {
+ .brw = BRW_NEW_SCENE,
+ .cache = 0
+ },
+ .update = upload_state_base_address
+};
diff --git a/src/gallium/drivers/i965simple/brw_reg.h b/src/gallium/drivers/i965simple/brw_reg.h
new file mode 100644
index 0000000000..9e885c3b3b
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_reg.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#define CMD_MI (0x0 << 29)
+#define CMD_2D (0x2 << 29)
+#define CMD_3D (0x3 << 29)
+
+#define MI_BATCH_BUFFER_END (CMD_MI | 0xA << 23)
+
+/* Stalls command execution waiting for the given events to have occurred. */
+#define MI_WAIT_FOR_EVENT (CMD_MI | (0x3 << 23))
+#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
+#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
+
+/* Primitive dispatch on 830-945 */
+#define _3DPRIMITIVE (CMD_3D | (0x1f << 24))
+#define PRIM_INDIRECT (1<<23)
+#define PRIM_INLINE (0<<23)
+#define PRIM_INDIRECT_SEQUENTIAL (0<<17)
+#define PRIM_INDIRECT_ELTS (1<<17)
+
+#define PRIM3D_TRILIST (0x0<<18)
+#define PRIM3D_TRISTRIP (0x1<<18)
+#define PRIM3D_TRISTRIP_RVRSE (0x2<<18)
+#define PRIM3D_TRIFAN (0x3<<18)
+#define PRIM3D_POLY (0x4<<18)
+#define PRIM3D_LINELIST (0x5<<18)
+#define PRIM3D_LINESTRIP (0x6<<18)
+#define PRIM3D_RECTLIST (0x7<<18)
+#define PRIM3D_POINTLIST (0x8<<18)
+#define PRIM3D_DIB (0x9<<18)
+#define PRIM3D_MASK (0x1f<<18)
+
+#define XY_SETUP_BLT_CMD (CMD_2D | (0x01 << 22) | 6)
+
+#define XY_COLOR_BLT_CMD (CMD_2D | (0x50 << 22) | 4)
+
+#define XY_SRC_COPY_BLT_CMD (CMD_2D | (0x53 << 22) | 6)
+
+/* BR00 */
+#define XY_BLT_WRITE_ALPHA (1 << 21)
+#define XY_BLT_WRITE_RGB (1 << 20)
+#define XY_SRC_TILED (1 << 15)
+#define XY_DST_TILED (1 << 11)
+
+/* BR13 */
+#define BR13_565 (0x1 << 24)
+#define BR13_8888 (0x3 << 24)
+
+#define FENCE_LINEAR 0
+#define FENCE_XMAJOR 1
+#define FENCE_YMAJOR 2
diff --git a/src/gallium/drivers/i965simple/brw_screen.c b/src/gallium/drivers/i965simple/brw_screen.c
new file mode 100644
index 0000000000..b22e105f10
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_screen.c
@@ -0,0 +1,246 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_string.h"
+#include "util/u_simple_screen.h"
+
+#include "brw_context.h"
+#include "brw_screen.h"
+#include "brw_tex_layout.h"
+
+
+static const char *
+brw_get_vendor( struct pipe_screen *screen )
+{
+ return "Tungsten Graphics, Inc.";
+}
+
+
+static const char *
+brw_get_name( struct pipe_screen *screen )
+{
+ static char buffer[128];
+ const char *chipset;
+
+ switch (brw_screen(screen)->pci_id) {
+ case PCI_CHIP_I965_Q:
+ chipset = "Intel(R) 965Q";
+ break;
+ case PCI_CHIP_I965_G:
+ case PCI_CHIP_I965_G_1:
+ chipset = "Intel(R) 965G";
+ break;
+ case PCI_CHIP_I965_GM:
+ chipset = "Intel(R) 965GM";
+ break;
+ case PCI_CHIP_I965_GME:
+ chipset = "Intel(R) 965GME/GLE";
+ break;
+ default:
+ chipset = "unknown";
+ break;
+ }
+
+ util_snprintf(buffer, sizeof(buffer), "i965 (chipset: %s)", chipset);
+ return buffer;
+}
+
+
+static int
+brw_get_param(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return 8;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 1;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 1;
+ case PIPE_CAP_GLSL:
+ return 0;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 0;
+ case PIPE_CAP_POINT_SPRITE:
+ return 0;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 1;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 0;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 1;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 11; /* max 1024x1024 */
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 8; /* max 128x128x128 */
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 11; /* max 1024x1024 */
+ default:
+ return 0;
+ }
+}
+
+
+static float
+brw_get_paramf(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 7.5;
+
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 255.0;
+
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 4.0;
+
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 16.0;
+
+ default:
+ return 0;
+ }
+}
+
+
+static boolean
+brw_is_format_supported( struct pipe_screen *screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags )
+{
+#if 0
+ /* XXX: This is broken -- rewrite if still needed. */
+ static const unsigned tex_supported[] = {
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_I8_UNORM,
+ PIPE_FORMAT_L8A8_UNORM,
+ PIPE_FORMAT_YCBCR,
+ PIPE_FORMAT_YCBCR_REV,
+ PIPE_FORMAT_S8_Z24,
+ };
+
+
+ /* Actually a lot more than this - add later:
+ */
+ static const unsigned render_supported[] = {
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ };
+
+ /*
+ */
+ static const unsigned z_stencil_supported[] = {
+ PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_S8Z24_UNORM,
+ };
+
+ switch (type) {
+ case PIPE_RENDER_FORMAT:
+ *numFormats = Elements(render_supported);
+ return render_supported;
+
+ case PIPE_TEX_FORMAT:
+ *numFormats = Elements(tex_supported);
+ return render_supported;
+
+ case PIPE_Z_STENCIL_FORMAT:
+ *numFormats = Elements(render_supported);
+ return render_supported;
+
+ default:
+ *numFormats = 0;
+ return NULL;
+ }
+#else
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ return TRUE;
+ default:
+ return FALSE;
+ };
+ return FALSE;
+#endif
+}
+
+
+static void
+brw_destroy_screen( struct pipe_screen *screen )
+{
+ struct pipe_winsys *winsys = screen->winsys;
+
+ if(winsys->destroy)
+ winsys->destroy(winsys);
+
+ FREE(screen);
+}
+
+
+/**
+ * Create a new brw_screen object
+ */
+struct pipe_screen *
+brw_create_screen(struct pipe_winsys *winsys, uint pci_id)
+{
+ struct brw_screen *brwscreen = CALLOC_STRUCT(brw_screen);
+
+ if (!brwscreen)
+ return NULL;
+
+ brwscreen->pci_id = pci_id;
+
+ brwscreen->screen.winsys = winsys;
+
+ brwscreen->screen.destroy = brw_destroy_screen;
+
+ brwscreen->screen.get_name = brw_get_name;
+ brwscreen->screen.get_vendor = brw_get_vendor;
+ brwscreen->screen.get_param = brw_get_param;
+ brwscreen->screen.get_paramf = brw_get_paramf;
+ brwscreen->screen.is_format_supported = brw_is_format_supported;
+
+ brw_init_screen_texture_funcs(&brwscreen->screen);
+ u_simple_screen_init(&brwscreen->screen);
+
+ return &brwscreen->screen;
+}
diff --git a/src/gallium/drivers/i965simple/brw_screen.h b/src/gallium/drivers/i965simple/brw_screen.h
new file mode 100644
index 0000000000..d3c70387e6
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_screen.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef BRW_SCREEN_H
+#define BRW_SCREEN_H
+
+
+#include "pipe/p_screen.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Subclass of pipe_screen
+ */
+struct brw_screen
+{
+ struct pipe_screen screen;
+
+ uint pci_id;
+};
+
+
+/** cast wrapper */
+static INLINE struct brw_screen *
+brw_screen(struct pipe_screen *pscreen)
+{
+ return (struct brw_screen *) pscreen;
+}
+
+
+extern struct pipe_screen *
+brw_create_screen(struct pipe_winsys *winsys, uint pci_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BRW_SCREEN_H */
diff --git a/src/gallium/drivers/i965simple/brw_sf.c b/src/gallium/drivers/i965simple/brw_sf.c
new file mode 100644
index 0000000000..b82a2e143b
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_sf.c
@@ -0,0 +1,351 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_sf.h"
+#include "brw_state.h"
+#include "tgsi/tgsi_parse.h"
+
+
+static void compile_sf_prog( struct brw_context *brw,
+ struct brw_sf_prog_key *key )
+{
+ struct brw_sf_compile c;
+ const unsigned *program;
+ unsigned program_size;
+
+ memset(&c, 0, sizeof(c));
+
+ /* Begin the compilation:
+ */
+ brw_init_compile(&c.func);
+
+ c.key = *key;
+
+
+ c.nr_attrs = c.key.vp_output_count;
+ c.nr_attr_regs = (c.nr_attrs+1)/2;
+
+ c.nr_setup_attrs = c.key.fp_input_count + 1; /* +1 for position */
+ c.nr_setup_regs = (c.nr_setup_attrs+1)/2;
+
+ c.prog_data.urb_read_length = c.nr_attr_regs;
+ c.prog_data.urb_entry_size = c.nr_setup_regs * 2;
+
+
+ /* Which primitive? Or all three?
+ */
+ switch (key->primitive) {
+ case SF_TRIANGLES:
+ c.nr_verts = 3;
+ brw_emit_tri_setup( &c );
+ break;
+ case SF_LINES:
+ c.nr_verts = 2;
+ brw_emit_line_setup( &c );
+ break;
+ case SF_POINTS:
+ c.nr_verts = 1;
+ brw_emit_point_setup( &c );
+ break;
+
+ case SF_UNFILLED_TRIS:
+ default:
+ assert(0);
+ return;
+ }
+
+
+
+ /* get the program
+ */
+ program = brw_get_program(&c.func, &program_size);
+
+ /* Upload
+ */
+ brw->sf.prog_gs_offset = brw_upload_cache( &brw->cache[BRW_SF_PROG],
+ &c.key,
+ sizeof(c.key),
+ program,
+ program_size,
+ &c.prog_data,
+ &brw->sf.prog_data );
+}
+
+
+static boolean search_cache( struct brw_context *brw,
+ struct brw_sf_prog_key *key )
+{
+ return brw_search_cache(&brw->cache[BRW_SF_PROG],
+ key, sizeof(*key),
+ &brw->sf.prog_data,
+ &brw->sf.prog_gs_offset);
+}
+
+
+/* Calculate interpolants for triangle and line rasterization.
+ */
+static void upload_sf_prog( struct brw_context *brw )
+{
+ const struct brw_fragment_program *fs = brw->attribs.FragmentProgram;
+ struct brw_sf_prog_key key;
+ struct tgsi_parse_context parse;
+ int i, done = 0;
+
+
+ memset(&key, 0, sizeof(key));
+
+ /* Populate the key, noting state dependencies:
+ */
+ /* CACHE_NEW_VS_PROG */
+ key.vp_output_count = brw->vs.prog_data->outputs_written;
+
+ /* BRW_NEW_FS */
+ key.fp_input_count = brw->attribs.FragmentProgram->info.file_max[TGSI_FILE_INPUT] + 1;
+
+
+ /* BRW_NEW_REDUCED_PRIMITIVE */
+ switch (brw->reduced_primitive) {
+ case PIPE_PRIM_TRIANGLES:
+// if (key.attrs & (1<<VERT_RESULT_EDGE))
+// key.primitive = SF_UNFILLED_TRIS;
+// else
+ key.primitive = SF_TRIANGLES;
+ break;
+ case PIPE_PRIM_LINES:
+ key.primitive = SF_LINES;
+ break;
+ case PIPE_PRIM_POINTS:
+ key.primitive = SF_POINTS;
+ break;
+ }
+
+
+
+ /* Scan fp inputs to figure out what interpolation modes are
+ * required for each incoming vp output. There is an assumption
+ * that the state tracker makes sure there is a 1:1 linkage between
+ * these sets of attributes (XXX: position??)
+ */
+ tgsi_parse_init( &parse, fs->program.tokens );
+ while( !done &&
+ !tgsi_parse_end_of_tokens( &parse ) )
+ {
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_INPUT)
+ {
+ int first = parse.FullToken.FullDeclaration.DeclarationRange.First;
+ int last = parse.FullToken.FullDeclaration.DeclarationRange.Last;
+ int interp_mode = parse.FullToken.FullDeclaration.Declaration.Interpolate;
+ //int semantic = parse.FullToken.FullDeclaration.Semantic.SemanticName;
+ //int semantic_index = parse.FullToken.FullDeclaration.Semantic.SemanticIndex;
+
+ debug_printf("fs input %d..%d interp mode %d\n", first, last, interp_mode);
+
+ switch (interp_mode) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ for (i = first; i <= last; i++)
+ key.const_mask |= (1 << i);
+ break;
+ case TGSI_INTERPOLATE_LINEAR:
+ for (i = first; i <= last; i++)
+ key.linear_mask |= (1 << i);
+ break;
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ for (i = first; i <= last; i++)
+ key.persp_mask |= (1 << i);
+ break;
+ default:
+ break;
+ }
+
+ /* Also need stuff for flat shading, twosided color.
+ */
+
+ }
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ /* Hack: Adjust for position. Optimize away when not required (ie
+ * for perspective interpolation).
+ */
+ key.persp_mask <<= 1;
+ key.linear_mask <<= 1;
+ key.linear_mask |= 1;
+ key.const_mask <<= 1;
+
+ debug_printf("key.persp_mask: %x\n", key.persp_mask);
+ debug_printf("key.linear_mask: %x\n", key.linear_mask);
+ debug_printf("key.const_mask: %x\n", key.const_mask);
+
+
+// key.do_point_sprite = brw->attribs.Point->PointSprite;
+// key.SpriteOrigin = brw->attribs.Point->SpriteOrigin;
+
+// key.do_flat_shading = (brw->attribs.Raster->flatshade);
+// key.do_twoside_color = (brw->attribs.Light->Enabled && brw->attribs.Light->Model.TwoSide);
+
+// if (key.do_twoside_color)
+// key.frontface_ccw = (brw->attribs.Polygon->FrontFace == GL_CCW);
+
+
+ if (!search_cache(brw, &key))
+ compile_sf_prog( brw, &key );
+}
+
+
+const struct brw_tracked_state brw_sf_prog = {
+ .dirty = {
+ .brw = (BRW_NEW_RASTERIZER |
+ BRW_NEW_REDUCED_PRIMITIVE |
+ BRW_NEW_VS |
+ BRW_NEW_FS),
+ .cache = 0,
+ },
+ .update = upload_sf_prog
+};
+
+
+
+#if 0
+/* Build a struct like the one we'd like the state tracker to pass to
+ * us.
+ */
+static void update_sf_linkage( struct brw_context *brw )
+{
+ const struct brw_vertex_program *vs = brw->attribs.VertexProgram;
+ const struct brw_fragment_program *fs = brw->attribs.FragmentProgram;
+ struct pipe_setup_linkage state;
+ struct tgsi_parse_context parse;
+
+ int i, j;
+ int nr_vp_outputs = 0;
+ int done = 0;
+
+ struct {
+ unsigned semantic:8;
+ unsigned semantic_index:16;
+ } fp_semantic[32], vp_semantic[32];
+
+ memset(&state, 0, sizeof(state));
+
+ state.fp_input_count = 0;
+
+
+
+
+
+
+ assert(state.fp_input_count == fs->program.num_inputs);
+
+
+ /* Then scan vp outputs
+ */
+ done = 0;
+ tgsi_parse_init( &parse, vs->program.tokens );
+ while( !done &&
+ !tgsi_parse_end_of_tokens( &parse ) )
+ {
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_INPUT)
+ {
+ int first = parse.FullToken.FullDeclaration.DeclarationRange.First;
+ int last = parse.FullToken.FullDeclaration.DeclarationRange.Last;
+
+ for (i = first; i < last; i++) {
+ vp_semantic[i].semantic =
+ parse.FullToken.FullDeclaration.Semantic.SemanticName;
+ vp_semantic[i].semantic_index =
+ parse.FullToken.FullDeclaration.Semantic.SemanticIndex;
+ }
+
+ assert(last > nr_vp_outputs);
+ nr_vp_outputs = last;
+ }
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+
+ /* Now match based on semantic information.
+ */
+ for (i = 0; i< state.fp_input_count; i++) {
+ for (j = 0; j < nr_vp_outputs; j++) {
+ if (fp_semantic[i].semantic == vp_semantic[j].semantic &&
+ fp_semantic[i].semantic_index == vp_semantic[j].semantic_index) {
+ state.fp_input[i].vp_output = j;
+ }
+ }
+ if (fp_semantic[i].semantic == TGSI_SEMANTIC_COLOR) {
+ for (j = 0; j < nr_vp_outputs; j++) {
+ if (TGSI_SEMANTIC_BCOLOR == vp_semantic[j].semantic &&
+ fp_semantic[i].semantic_index == vp_semantic[j].semantic_index) {
+ state.fp_input[i].bf_vp_output = j;
+ }
+ }
+ }
+ }
+
+ if (memcmp(&brw->sf.linkage, &state, sizeof(state)) != 0) {
+ brw->sf.linkage = state;
+ brw->state.dirty.brw |= BRW_NEW_SF_LINKAGE;
+ }
+}
+
+
+const struct brw_tracked_state brw_sf_linkage = {
+ .dirty = {
+ .brw = (BRW_NEW_VS |
+ BRW_NEW_FS),
+ .cache = 0,
+ },
+ .update = update_sf_linkage
+};
+
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_sf.h b/src/gallium/drivers/i965simple/brw_sf.h
new file mode 100644
index 0000000000..b7ada47560
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_sf.h
@@ -0,0 +1,122 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRW_SF_H
+#define BRW_SF_H
+
+#include "brw_context.h"
+#include "brw_eu.h"
+
+
+#define SF_POINTS 0
+#define SF_LINES 1
+#define SF_TRIANGLES 2
+#define SF_UNFILLED_TRIS 3
+
+
+
+struct brw_sf_prog_key {
+ unsigned vp_output_count:5;
+ unsigned fp_input_count:5;
+
+ unsigned primitive:2;
+ unsigned do_twoside_color:1;
+ unsigned do_flat_shading:1;
+ unsigned frontface_ccw:1;
+ unsigned do_point_sprite:1;
+
+ /* Interpolation masks;
+ */
+ unsigned linear_mask;
+ unsigned persp_mask;
+ unsigned const_mask;
+
+
+// int SpriteOrigin;
+};
+
+struct brw_sf_point_tex {
+ boolean CoordReplace;
+};
+
+struct brw_sf_compile {
+ struct brw_compile func;
+ struct brw_sf_prog_key key;
+ struct brw_sf_prog_data prog_data;
+
+ struct brw_reg pv;
+ struct brw_reg det;
+ struct brw_reg dx0;
+ struct brw_reg dx2;
+ struct brw_reg dy0;
+ struct brw_reg dy2;
+
+ /* z and 1/w passed in seperately:
+ */
+ struct brw_reg z[3];
+ struct brw_reg inv_w[3];
+
+ /* The vertices:
+ */
+ struct brw_reg vert[3];
+
+ /* Temporaries, allocated after last vertex reg.
+ */
+ struct brw_reg inv_det;
+ struct brw_reg a1_sub_a0;
+ struct brw_reg a2_sub_a0;
+ struct brw_reg tmp;
+
+ struct brw_reg m1Cx;
+ struct brw_reg m2Cy;
+ struct brw_reg m3C0;
+
+ unsigned nr_verts;
+ unsigned nr_attrs;
+ unsigned nr_attr_regs;
+ unsigned nr_setup_attrs;
+ unsigned nr_setup_regs;
+#if 0
+ ubyte attr_to_idx[VERT_RESULT_MAX];
+ ubyte idx_to_attr[VERT_RESULT_MAX];
+ struct brw_sf_point_tex point_attrs[VERT_RESULT_MAX];
+#endif
+};
+
+
+void brw_emit_tri_setup( struct brw_sf_compile *c );
+void brw_emit_line_setup( struct brw_sf_compile *c );
+void brw_emit_point_setup( struct brw_sf_compile *c );
+void brw_emit_point_sprite_setup( struct brw_sf_compile *c );
+void brw_emit_anyprim_setup( struct brw_sf_compile *c );
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_sf_emit.c b/src/gallium/drivers/i965simple/brw_sf_emit.c
new file mode 100644
index 0000000000..78d6fa5e9e
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_sf_emit.c
@@ -0,0 +1,382 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_defines.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_util.h"
+#include "brw_sf.h"
+
+
+
+/***********************************************************************
+ * Triangle setup.
+ */
+
+
+static void alloc_regs( struct brw_sf_compile *c )
+{
+ unsigned reg, i;
+
+ /* Values computed by fixed function unit:
+ */
+ c->pv = retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_UD);
+ c->det = brw_vec1_grf(1, 2);
+ c->dx0 = brw_vec1_grf(1, 3);
+ c->dx2 = brw_vec1_grf(1, 4);
+ c->dy0 = brw_vec1_grf(1, 5);
+ c->dy2 = brw_vec1_grf(1, 6);
+
+ /* z and 1/w passed in seperately:
+ */
+ c->z[0] = brw_vec1_grf(2, 0);
+ c->inv_w[0] = brw_vec1_grf(2, 1);
+ c->z[1] = brw_vec1_grf(2, 2);
+ c->inv_w[1] = brw_vec1_grf(2, 3);
+ c->z[2] = brw_vec1_grf(2, 4);
+ c->inv_w[2] = brw_vec1_grf(2, 5);
+
+ /* The vertices:
+ */
+ reg = 3;
+ for (i = 0; i < c->nr_verts; i++) {
+ c->vert[i] = brw_vec8_grf(reg, 0);
+ reg += c->nr_attr_regs;
+ }
+
+ /* Temporaries, allocated after last vertex reg.
+ */
+ c->inv_det = brw_vec1_grf(reg, 0); reg++;
+ c->a1_sub_a0 = brw_vec8_grf(reg, 0); reg++;
+ c->a2_sub_a0 = brw_vec8_grf(reg, 0); reg++;
+ c->tmp = brw_vec8_grf(reg, 0); reg++;
+
+ /* Note grf allocation:
+ */
+ c->prog_data.total_grf = reg;
+
+
+ /* Outputs of this program - interpolation coefficients for
+ * rasterization:
+ */
+ c->m1Cx = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 1, 0);
+ c->m2Cy = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 2, 0);
+ c->m3C0 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 3, 0);
+}
+
+
+static void copy_z_inv_w( struct brw_sf_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ unsigned i;
+
+ brw_push_insn_state(p);
+
+ /* Copy both scalars with a single MOV:
+ */
+ for (i = 0; i < c->nr_verts; i++)
+ brw_MOV(p, vec2(suboffset(c->vert[i], 2)), vec2(c->z[i]));
+
+ brw_pop_insn_state(p);
+}
+
+
+static void invert_det( struct brw_sf_compile *c)
+{
+ brw_math(&c->func,
+ c->inv_det,
+ BRW_MATH_FUNCTION_INV,
+ BRW_MATH_SATURATE_NONE,
+ 0,
+ c->det,
+ BRW_MATH_DATA_SCALAR,
+ BRW_MATH_PRECISION_FULL);
+
+}
+
+#define NON_PERPECTIVE_ATTRS (FRAG_BIT_WPOS | \
+ FRAG_BIT_COL0 | \
+ FRAG_BIT_COL1)
+
+static boolean calculate_masks( struct brw_sf_compile *c,
+ unsigned reg,
+ ushort *pc,
+ ushort *pc_persp,
+ ushort *pc_linear)
+{
+ boolean is_last_attr = (reg == c->nr_setup_regs - 1);
+ unsigned persp_mask = c->key.persp_mask;
+ unsigned linear_mask = c->key.linear_mask;
+
+ debug_printf("persp_mask: %x\n", persp_mask);
+ debug_printf("linear_mask: %x\n", linear_mask);
+
+ *pc_persp = 0;
+ *pc_linear = 0;
+ *pc = 0xf;
+
+ if (persp_mask & (1 << (reg*2)))
+ *pc_persp = 0xf;
+
+ if (linear_mask & (1 << (reg*2)))
+ *pc_linear = 0xf;
+
+ /* Maybe only processs one attribute on the final round:
+ */
+ if (reg*2+1 < c->nr_setup_attrs) {
+ *pc |= 0xf0;
+
+ if (persp_mask & (1 << (reg*2+1)))
+ *pc_persp |= 0xf0;
+
+ if (linear_mask & (1 << (reg*2+1)))
+ *pc_linear |= 0xf0;
+ }
+
+ debug_printf("pc: %x\n", *pc);
+ debug_printf("pc_persp: %x\n", *pc_persp);
+ debug_printf("pc_linear: %x\n", *pc_linear);
+
+
+ return is_last_attr;
+}
+
+
+
+void brw_emit_tri_setup( struct brw_sf_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ unsigned i;
+
+ debug_printf("%s START ==============\n", __FUNCTION__);
+
+ c->nr_verts = 3;
+ alloc_regs(c);
+ invert_det(c);
+ copy_z_inv_w(c);
+
+
+ for (i = 0; i < c->nr_setup_regs; i++)
+ {
+ /* Pair of incoming attributes:
+ */
+ struct brw_reg a0 = offset(c->vert[0], i);
+ struct brw_reg a1 = offset(c->vert[1], i);
+ struct brw_reg a2 = offset(c->vert[2], i);
+ ushort pc = 0, pc_persp = 0, pc_linear = 0;
+ boolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
+
+ if (pc_persp)
+ {
+ brw_set_predicate_control_flag_value(p, pc_persp);
+ brw_MUL(p, a0, a0, c->inv_w[0]);
+ brw_MUL(p, a1, a1, c->inv_w[1]);
+ brw_MUL(p, a2, a2, c->inv_w[2]);
+ }
+
+
+ /* Calculate coefficients for interpolated values:
+ */
+ if (pc_linear)
+ {
+ brw_set_predicate_control_flag_value(p, pc_linear);
+
+ brw_ADD(p, c->a1_sub_a0, a1, negate(a0));
+ brw_ADD(p, c->a2_sub_a0, a2, negate(a0));
+
+ /* calculate dA/dx
+ */
+ brw_MUL(p, brw_null_reg(), c->a1_sub_a0, c->dy2);
+ brw_MAC(p, c->tmp, c->a2_sub_a0, negate(c->dy0));
+ brw_MUL(p, c->m1Cx, c->tmp, c->inv_det);
+
+ /* calculate dA/dy
+ */
+ brw_MUL(p, brw_null_reg(), c->a2_sub_a0, c->dx0);
+ brw_MAC(p, c->tmp, c->a1_sub_a0, negate(c->dx2));
+ brw_MUL(p, c->m2Cy, c->tmp, c->inv_det);
+ }
+
+ {
+ brw_set_predicate_control_flag_value(p, pc);
+ /* start point for interpolation
+ */
+ brw_MOV(p, c->m3C0, a0);
+
+ /* Copy m0..m3 to URB. m0 is implicitly copied from r0 in
+ * the send instruction:
+ */
+ brw_urb_WRITE(p,
+ brw_null_reg(),
+ 0,
+ brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
+ 0, /* allocate */
+ 1, /* used */
+ 4, /* msg len */
+ 0, /* response len */
+ last, /* eot */
+ last, /* writes complete */
+ i*4, /* offset */
+ BRW_URB_SWIZZLE_TRANSPOSE); /* XXX: Swizzle control "SF to windower" */
+ }
+ }
+
+ debug_printf("%s DONE ==============\n", __FUNCTION__);
+
+}
+
+
+
+void brw_emit_line_setup( struct brw_sf_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ unsigned i;
+
+
+ c->nr_verts = 2;
+ alloc_regs(c);
+ invert_det(c);
+ copy_z_inv_w(c);
+
+ for (i = 0; i < c->nr_setup_regs; i++)
+ {
+ /* Pair of incoming attributes:
+ */
+ struct brw_reg a0 = offset(c->vert[0], i);
+ struct brw_reg a1 = offset(c->vert[1], i);
+ ushort pc, pc_persp, pc_linear;
+ boolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
+
+ if (pc_persp)
+ {
+ brw_set_predicate_control_flag_value(p, pc_persp);
+ brw_MUL(p, a0, a0, c->inv_w[0]);
+ brw_MUL(p, a1, a1, c->inv_w[1]);
+ }
+
+ /* Calculate coefficients for position, color:
+ */
+ if (pc_linear) {
+ brw_set_predicate_control_flag_value(p, pc_linear);
+
+ brw_ADD(p, c->a1_sub_a0, a1, negate(a0));
+
+ brw_MUL(p, c->tmp, c->a1_sub_a0, c->dx0);
+ brw_MUL(p, c->m1Cx, c->tmp, c->inv_det);
+
+ brw_MUL(p, c->tmp, c->a1_sub_a0, c->dy0);
+ brw_MUL(p, c->m2Cy, c->tmp, c->inv_det);
+ }
+
+ {
+ brw_set_predicate_control_flag_value(p, pc);
+
+ /* start point for interpolation
+ */
+ brw_MOV(p, c->m3C0, a0);
+
+ /* Copy m0..m3 to URB.
+ */
+ brw_urb_WRITE(p,
+ brw_null_reg(),
+ 0,
+ brw_vec8_grf(0, 0),
+ 0, /* allocate */
+ 1, /* used */
+ 4, /* msg len */
+ 0, /* response len */
+ last, /* eot */
+ last, /* writes complete */
+ i*4, /* urb destination offset */
+ BRW_URB_SWIZZLE_TRANSPOSE);
+ }
+ }
+}
+
+
+/* Points setup - several simplifications as all attributes are
+ * constant across the face of the point (point sprites excluded!)
+ */
+void brw_emit_point_setup( struct brw_sf_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ unsigned i;
+
+ c->nr_verts = 1;
+ alloc_regs(c);
+ copy_z_inv_w(c);
+
+ brw_MOV(p, c->m1Cx, brw_imm_ud(0)); /* zero - move out of loop */
+ brw_MOV(p, c->m2Cy, brw_imm_ud(0)); /* zero - move out of loop */
+
+ for (i = 0; i < c->nr_setup_regs; i++)
+ {
+ struct brw_reg a0 = offset(c->vert[0], i);
+ ushort pc, pc_persp, pc_linear;
+ boolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
+
+ if (pc_persp)
+ {
+ /* This seems odd as the values are all constant, but the
+ * fragment shader will be expecting it:
+ */
+ brw_set_predicate_control_flag_value(p, pc_persp);
+ brw_MUL(p, a0, a0, c->inv_w[0]);
+ }
+
+
+ /* The delta values are always zero, just send the starting
+ * coordinate. Again, this is to fit in with the interpolation
+ * code in the fragment shader.
+ */
+ {
+ brw_set_predicate_control_flag_value(p, pc);
+
+ brw_MOV(p, c->m3C0, a0); /* constant value */
+
+ /* Copy m0..m3 to URB.
+ */
+ brw_urb_WRITE(p,
+ brw_null_reg(),
+ 0,
+ brw_vec8_grf(0, 0),
+ 0, /* allocate */
+ 1, /* used */
+ 4, /* msg len */
+ 0, /* response len */
+ last, /* eot */
+ last, /* writes complete */
+ i*4, /* urb destination offset */
+ BRW_URB_SWIZZLE_TRANSPOSE);
+ }
+ }
+}
diff --git a/src/gallium/drivers/i965simple/brw_sf_state.c b/src/gallium/drivers/i965simple/brw_sf_state.c
new file mode 100644
index 0000000000..2a5de61c21
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_sf_state.c
@@ -0,0 +1,181 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+
+static void upload_sf_vp(struct brw_context *brw)
+{
+ struct brw_sf_viewport sfv;
+
+ memset(&sfv, 0, sizeof(sfv));
+
+
+ /* BRW_NEW_VIEWPORT */
+ {
+ const float *scale = brw->attribs.Viewport.scale;
+ const float *trans = brw->attribs.Viewport.translate;
+
+ sfv.viewport.m00 = scale[0];
+ sfv.viewport.m11 = scale[1];
+ sfv.viewport.m22 = scale[2];
+ sfv.viewport.m30 = trans[0];
+ sfv.viewport.m31 = trans[1];
+ sfv.viewport.m32 = trans[2];
+ }
+
+ /* _NEW_SCISSOR */
+ sfv.scissor.xmin = brw->attribs.Scissor.minx;
+ sfv.scissor.xmax = brw->attribs.Scissor.maxx - 1;
+ sfv.scissor.ymin = brw->attribs.Scissor.miny;
+ sfv.scissor.ymax = brw->attribs.Scissor.maxy - 1;
+
+ brw->sf.vp_gs_offset = brw_cache_data( &brw->cache[BRW_SF_VP], &sfv );
+}
+
+const struct brw_tracked_state brw_sf_vp = {
+ .dirty = {
+ .brw = (BRW_NEW_SCISSOR |
+ BRW_NEW_VIEWPORT),
+ .cache = 0
+ },
+ .update = upload_sf_vp
+};
+
+static void upload_sf_unit( struct brw_context *brw )
+{
+ struct brw_sf_unit_state sf;
+ memset(&sf, 0, sizeof(sf));
+
+ /* CACHE_NEW_SF_PROG */
+ sf.thread0.grf_reg_count = align(brw->sf.prog_data->total_grf, 16) / 16 - 1;
+ sf.thread0.kernel_start_pointer = brw->sf.prog_gs_offset >> 6;
+ sf.thread3.urb_entry_read_length = brw->sf.prog_data->urb_read_length;
+
+ sf.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
+ sf.thread3.dispatch_grf_start_reg = 3;
+ sf.thread3.urb_entry_read_offset = 1;
+
+ /* BRW_NEW_URB_FENCE */
+ sf.thread4.nr_urb_entries = brw->urb.nr_sf_entries;
+ sf.thread4.urb_entry_allocation_size = brw->urb.sfsize - 1;
+ sf.thread4.max_threads = MIN2(12, brw->urb.nr_sf_entries / 2) - 1;
+
+ if (BRW_DEBUG & DEBUG_SINGLE_THREAD)
+ sf.thread4.max_threads = 0;
+
+ if (BRW_DEBUG & DEBUG_STATS)
+ sf.thread4.stats_enable = 1;
+
+ /* CACHE_NEW_SF_VP */
+ sf.sf5.sf_viewport_state_offset = brw->sf.vp_gs_offset >> 5;
+ sf.sf5.viewport_transform = 1;
+
+ /* BRW_NEW_RASTER */
+ if (brw->attribs.Raster->scissor)
+ sf.sf6.scissor = 1;
+
+#if 0
+ if (brw->attribs.Polygon->FrontFace == GL_CCW)
+ sf.sf5.front_winding = BRW_FRONTWINDING_CCW;
+ else
+ sf.sf5.front_winding = BRW_FRONTWINDING_CW;
+
+
+ if (brw->attribs.Polygon->CullFlag) {
+ switch (brw->attribs.Polygon->CullFaceMode) {
+ case GL_FRONT:
+ sf.sf6.cull_mode = BRW_CULLMODE_FRONT;
+ break;
+ case GL_BACK:
+ sf.sf6.cull_mode = BRW_CULLMODE_BACK;
+ break;
+ case GL_FRONT_AND_BACK:
+ sf.sf6.cull_mode = BRW_CULLMODE_BOTH;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else
+ sf.sf6.cull_mode = BRW_CULLMODE_NONE;
+#else
+ sf.sf5.front_winding = BRW_FRONTWINDING_CCW;
+ sf.sf6.cull_mode = BRW_CULLMODE_NONE;
+#endif
+
+ sf.sf6.line_width = CLAMP(brw->attribs.Raster->line_width, 1.0, 5.0) * (1<<1);
+
+ sf.sf6.line_endcap_aa_region_width = 1;
+ if (brw->attribs.Raster->line_smooth)
+ sf.sf6.aa_enable = 1;
+ else if (sf.sf6.line_width <= 0x2)
+ sf.sf6.line_width = 0;
+
+ sf.sf6.point_rast_rule = 1; /* opengl conventions */
+
+ sf.sf7.sprite_point = brw->attribs.Raster->point_sprite;
+ sf.sf7.point_size = CLAMP(brw->attribs.Raster->line_width, 1.0, 255.0) * (1<<3);
+ sf.sf7.use_point_size_state = !brw->attribs.Raster->point_size_per_vertex;
+
+ /* might be BRW_NEW_PRIMITIVE if we have to adjust pv for polygons:
+ */
+ sf.sf7.trifan_pv = 2;
+ sf.sf7.linestrip_pv = 1;
+ sf.sf7.tristrip_pv = 2;
+ sf.sf7.line_last_pixel_enable = 0;
+
+ /* Set bias for OpenGL rasterization rules:
+ */
+ sf.sf6.dest_org_vbias = 0x8;
+ sf.sf6.dest_org_hbias = 0x8;
+
+ brw->sf.state_gs_offset = brw_cache_data( &brw->cache[BRW_SF_UNIT], &sf );
+}
+
+
+const struct brw_tracked_state brw_sf_unit = {
+ .dirty = {
+ .brw = (BRW_NEW_RASTERIZER |
+ BRW_NEW_URB_FENCE),
+ .cache = (CACHE_NEW_SF_VP |
+ CACHE_NEW_SF_PROG)
+ },
+ .update = upload_sf_unit
+};
+
+
diff --git a/src/gallium/drivers/i965simple/brw_shader_info.c b/src/gallium/drivers/i965simple/brw_shader_info.c
new file mode 100644
index 0000000000..86d877d7ef
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_shader_info.c
@@ -0,0 +1,48 @@
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+
+
+/**
+ * XXX this obsolete new and no longer compiled.
+ */
+void brw_shader_info(const struct tgsi_token *tokens,
+ struct brw_shader_info *info )
+{
+ struct tgsi_parse_context parse;
+ int done = 0;
+
+ tgsi_parse_init( &parse, tokens );
+
+ while( !done &&
+ !tgsi_parse_end_of_tokens( &parse ) )
+ {
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration;
+ unsigned last = decl->DeclarationRange.Last;
+
+ // Broken by crazy wpos init:
+ //assert( info->nr_regs[decl->Declaration.File] <= last);
+
+ info->nr_regs[decl->Declaration.File] = MAX2(info->nr_regs[decl->Declaration.File],
+ last+1);
+ break;
+ }
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ tgsi_parse_free (&parse);
+
+}
diff --git a/src/gallium/drivers/i965simple/brw_state.c b/src/gallium/drivers/i965simple/brw_state.c
new file mode 100644
index 0000000000..b47f5373f3
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_state.c
@@ -0,0 +1,469 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Zack Rusin <zack@tungstengraphics.com>
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_memory.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_parse.h"
+
+#include "brw_context.h"
+#include "brw_defines.h"
+#include "brw_state.h"
+#include "brw_draw.h"
+
+
+#define DUP( TYPE, VAL ) \
+do { \
+ struct TYPE *x = malloc(sizeof(*x)); \
+ memcpy(x, VAL, sizeof(*x) ); \
+ return x; \
+} while (0)
+
+/************************************************************************
+ * Blend
+ */
+static void *
+brw_create_blend_state(struct pipe_context *pipe,
+ const struct pipe_blend_state *blend)
+{
+ DUP( pipe_blend_state, blend );
+}
+
+static void brw_bind_blend_state(struct pipe_context *pipe,
+ void *blend)
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ brw->attribs.Blend = (struct pipe_blend_state*)blend;
+ brw->state.dirty.brw |= BRW_NEW_BLEND;
+}
+
+
+static void brw_delete_blend_state(struct pipe_context *pipe, void *blend)
+{
+ free(blend);
+}
+
+static void brw_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color )
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ brw->attribs.BlendColor = *blend_color;
+
+ brw->state.dirty.brw |= BRW_NEW_BLEND;
+}
+
+/************************************************************************
+ * Sampler
+ */
+
+static void *
+brw_create_sampler_state(struct pipe_context *pipe,
+ const struct pipe_sampler_state *sampler)
+{
+ DUP( pipe_sampler_state, sampler );
+}
+
+static void brw_bind_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **sampler)
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ assert(num <= PIPE_MAX_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == brw->num_samplers &&
+ !memcmp(brw->attribs.Samplers, sampler, num * sizeof(void *)))
+ return;
+
+ memcpy(brw->attribs.Samplers, sampler, num * sizeof(void *));
+ memset(&brw->attribs.Samplers[num], 0, (PIPE_MAX_SAMPLERS - num) *
+ sizeof(void *));
+
+ brw->num_samplers = num;
+
+ brw->state.dirty.brw |= BRW_NEW_SAMPLER;
+}
+
+static void brw_delete_sampler_state(struct pipe_context *pipe,
+ void *sampler)
+{
+ free(sampler);
+}
+
+
+/************************************************************************
+ * Depth stencil
+ */
+
+static void *
+brw_create_depth_stencil_state(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *depth_stencil)
+{
+ DUP( pipe_depth_stencil_alpha_state, depth_stencil );
+}
+
+static void brw_bind_depth_stencil_state(struct pipe_context *pipe,
+ void *depth_stencil)
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ brw->attribs.DepthStencil = (const struct pipe_depth_stencil_alpha_state *)depth_stencil;
+
+ brw->state.dirty.brw |= BRW_NEW_DEPTH_STENCIL;
+}
+
+static void brw_delete_depth_stencil_state(struct pipe_context *pipe,
+ void *depth_stencil)
+{
+ free(depth_stencil);
+}
+
+/************************************************************************
+ * Scissor
+ */
+static void brw_set_scissor_state( struct pipe_context *pipe,
+ const struct pipe_scissor_state *scissor )
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ memcpy( &brw->attribs.Scissor, scissor, sizeof(*scissor) );
+ brw->state.dirty.brw |= BRW_NEW_SCISSOR;
+}
+
+
+/************************************************************************
+ * Stipple
+ */
+
+static void brw_set_polygon_stipple( struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple )
+{
+}
+
+
+/************************************************************************
+ * Fragment shader
+ */
+
+static void * brw_create_fs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *shader)
+{
+ struct brw_fragment_program *brw_fp = CALLOC_STRUCT(brw_fragment_program);
+
+ brw_fp->program.tokens = tgsi_dup_tokens(shader->tokens);
+ brw_fp->id = brw_context(pipe)->program_id++;
+
+ tgsi_scan_shader(shader->tokens, &brw_fp->info);
+
+#if 0
+ brw_shader_info(shader->tokens,
+ &brw_fp->info2);
+#endif
+
+ tgsi_dump(shader->tokens, 0);
+
+
+ return (void *)brw_fp;
+}
+
+static void brw_bind_fs_state(struct pipe_context *pipe, void *shader)
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ brw->attribs.FragmentProgram = (struct brw_fragment_program *)shader;
+ brw->state.dirty.brw |= BRW_NEW_FS;
+}
+
+static void brw_delete_fs_state(struct pipe_context *pipe, void *shader)
+{
+ struct brw_fragment_program *brw_fp = (struct brw_fragment_program *) shader;
+
+ FREE((void *) brw_fp->program.tokens);
+ FREE(brw_fp);
+}
+
+
+/************************************************************************
+ * Vertex shader and other TNL state
+ */
+
+static void *brw_create_vs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *shader)
+{
+ struct brw_vertex_program *brw_vp = CALLOC_STRUCT(brw_vertex_program);
+
+ brw_vp->program.tokens = tgsi_dup_tokens(shader->tokens);
+ brw_vp->id = brw_context(pipe)->program_id++;
+
+ tgsi_scan_shader(shader->tokens, &brw_vp->info);
+
+#if 0
+ brw_shader_info(shader->tokens,
+ &brw_vp->info2);
+#endif
+ tgsi_dump(shader->tokens, 0);
+
+ return (void *)brw_vp;
+}
+
+static void brw_bind_vs_state(struct pipe_context *pipe, void *vs)
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ brw->attribs.VertexProgram = (struct brw_vertex_program *)vs;
+ brw->state.dirty.brw |= BRW_NEW_VS;
+
+ debug_printf("YYYYYYYYYYYYY BINDING VERTEX SHADER\n");
+}
+
+static void brw_delete_vs_state(struct pipe_context *pipe, void *shader)
+{
+ struct brw_vertex_program *brw_vp = (struct brw_vertex_program *) shader;
+
+ FREE((void *) brw_vp->program.tokens);
+ FREE(brw_vp);
+}
+
+
+static void brw_set_clip_state( struct pipe_context *pipe,
+ const struct pipe_clip_state *clip )
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ brw->attribs.Clip = *clip;
+}
+
+
+static void brw_set_viewport_state( struct pipe_context *pipe,
+ const struct pipe_viewport_state *viewport )
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ brw->attribs.Viewport = *viewport; /* struct copy */
+ brw->state.dirty.brw |= BRW_NEW_VIEWPORT;
+
+ /* pass the viewport info to the draw module */
+ //draw_set_viewport_state(brw->draw, viewport);
+}
+
+
+static void brw_set_vertex_buffers(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_buffer *buffers)
+{
+ struct brw_context *brw = brw_context(pipe);
+ memcpy(brw->vb.vbo_array, buffers, count * sizeof(buffers[0]));
+}
+
+static void brw_set_vertex_elements(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_element *elements)
+{
+ /* flush ? */
+ struct brw_context *brw = brw_context(pipe);
+ uint i;
+
+ assert(count <= PIPE_MAX_ATTRIBS);
+
+ for (i = 0; i < count; i++) {
+ struct brw_vertex_element_state el;
+ memset(&el, 0, sizeof(el));
+
+ el.ve0.src_offset = elements[i].src_offset;
+ el.ve0.src_format = brw_translate_surface_format(elements[i].src_format);
+ el.ve0.valid = 1;
+ el.ve0.vertex_buffer_index = elements[i].vertex_buffer_index;
+
+ el.ve1.dst_offset = i * 4;
+
+ el.ve1.vfcomponent3 = BRW_VFCOMPONENT_STORE_SRC;
+ el.ve1.vfcomponent2 = BRW_VFCOMPONENT_STORE_SRC;
+ el.ve1.vfcomponent1 = BRW_VFCOMPONENT_STORE_SRC;
+ el.ve1.vfcomponent0 = BRW_VFCOMPONENT_STORE_SRC;
+
+ switch (elements[i].nr_components) {
+ case 1: el.ve1.vfcomponent1 = BRW_VFCOMPONENT_STORE_0;
+ case 2: el.ve1.vfcomponent2 = BRW_VFCOMPONENT_STORE_0;
+ case 3: el.ve1.vfcomponent3 = BRW_VFCOMPONENT_STORE_1_FLT;
+ break;
+ }
+
+ brw->vb.inputs[i] = el;
+ }
+}
+
+
+
+/************************************************************************
+ * Constant buffers
+ */
+
+static void brw_set_constant_buffer(struct pipe_context *pipe,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf)
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ assert(buf == 0 || index == 0);
+
+ brw->attribs.Constants[shader] = buf;
+ brw->state.dirty.brw |= BRW_NEW_CONSTANTS;
+}
+
+
+/************************************************************************
+ * Texture surfaces
+ */
+
+
+static void brw_set_sampler_textures(struct pipe_context *pipe,
+ unsigned num,
+ struct pipe_texture **texture)
+{
+ struct brw_context *brw = brw_context(pipe);
+ uint i;
+
+ assert(num <= PIPE_MAX_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == brw->num_textures &&
+ !memcmp(brw->attribs.Texture, texture, num *
+ sizeof(struct pipe_texture *)))
+ return;
+
+ for (i = 0; i < num; i++)
+ pipe_texture_reference((struct pipe_texture **) &brw->attribs.Texture[i],
+ texture[i]);
+
+ for (i = num; i < brw->num_textures; i++)
+ pipe_texture_reference((struct pipe_texture **) &brw->attribs.Texture[i],
+ NULL);
+
+ brw->num_textures = num;
+
+ brw->state.dirty.brw |= BRW_NEW_TEXTURE;
+}
+
+
+/************************************************************************
+ * Render targets, etc
+ */
+
+static void brw_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ brw->attribs.FrameBuffer = *fb; /* struct copy */
+
+ brw->state.dirty.brw |= BRW_NEW_FRAMEBUFFER;
+}
+
+
+
+/************************************************************************
+ * Rasterizer state
+ */
+
+static void *
+brw_create_rasterizer_state(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *rasterizer)
+{
+ DUP(pipe_rasterizer_state, rasterizer);
+}
+
+static void brw_bind_rasterizer_state( struct pipe_context *pipe,
+ void *setup )
+{
+ struct brw_context *brw = brw_context(pipe);
+
+ brw->attribs.Raster = (struct pipe_rasterizer_state *)setup;
+
+ /* Also pass-through to draw module:
+ */
+ //draw_set_rasterizer_state(brw->draw, setup);
+
+ brw->state.dirty.brw |= BRW_NEW_RASTERIZER;
+}
+
+static void brw_delete_rasterizer_state(struct pipe_context *pipe,
+ void *setup)
+{
+ free(setup);
+}
+
+
+
+void
+brw_init_state_functions( struct brw_context *brw )
+{
+ brw->pipe.create_blend_state = brw_create_blend_state;
+ brw->pipe.bind_blend_state = brw_bind_blend_state;
+ brw->pipe.delete_blend_state = brw_delete_blend_state;
+
+ brw->pipe.create_sampler_state = brw_create_sampler_state;
+ brw->pipe.bind_sampler_states = brw_bind_sampler_states;
+ brw->pipe.delete_sampler_state = brw_delete_sampler_state;
+
+ brw->pipe.create_depth_stencil_alpha_state = brw_create_depth_stencil_state;
+ brw->pipe.bind_depth_stencil_alpha_state = brw_bind_depth_stencil_state;
+ brw->pipe.delete_depth_stencil_alpha_state = brw_delete_depth_stencil_state;
+
+ brw->pipe.create_rasterizer_state = brw_create_rasterizer_state;
+ brw->pipe.bind_rasterizer_state = brw_bind_rasterizer_state;
+ brw->pipe.delete_rasterizer_state = brw_delete_rasterizer_state;
+ brw->pipe.create_fs_state = brw_create_fs_state;
+ brw->pipe.bind_fs_state = brw_bind_fs_state;
+ brw->pipe.delete_fs_state = brw_delete_fs_state;
+ brw->pipe.create_vs_state = brw_create_vs_state;
+ brw->pipe.bind_vs_state = brw_bind_vs_state;
+ brw->pipe.delete_vs_state = brw_delete_vs_state;
+
+ brw->pipe.set_blend_color = brw_set_blend_color;
+ brw->pipe.set_clip_state = brw_set_clip_state;
+ brw->pipe.set_constant_buffer = brw_set_constant_buffer;
+ brw->pipe.set_framebuffer_state = brw_set_framebuffer_state;
+
+// brw->pipe.set_feedback_state = brw_set_feedback_state;
+// brw->pipe.set_feedback_buffer = brw_set_feedback_buffer;
+
+ brw->pipe.set_polygon_stipple = brw_set_polygon_stipple;
+ brw->pipe.set_scissor_state = brw_set_scissor_state;
+ brw->pipe.set_sampler_textures = brw_set_sampler_textures;
+ brw->pipe.set_viewport_state = brw_set_viewport_state;
+ brw->pipe.set_vertex_buffers = brw_set_vertex_buffers;
+ brw->pipe.set_vertex_elements = brw_set_vertex_elements;
+}
diff --git a/src/gallium/drivers/i965simple/brw_state.h b/src/gallium/drivers/i965simple/brw_state.h
new file mode 100644
index 0000000000..de0a6371b8
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_state.h
@@ -0,0 +1,151 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRW_STATE_H
+#define BRW_STATE_H
+
+#include "brw_context.h"
+#include "brw_winsys.h"
+
+
+const struct brw_tracked_state brw_blend_constant_color;
+const struct brw_tracked_state brw_cc_unit;
+const struct brw_tracked_state brw_cc_vp;
+const struct brw_tracked_state brw_clip_prog;
+const struct brw_tracked_state brw_clip_unit;
+const struct brw_tracked_state brw_constant_buffer_state;
+const struct brw_tracked_state brw_constant_buffer;
+const struct brw_tracked_state brw_curbe_offsets;
+const struct brw_tracked_state brw_invarient_state;
+const struct brw_tracked_state brw_gs_prog;
+const struct brw_tracked_state brw_gs_unit;
+const struct brw_tracked_state brw_drawing_rect;
+const struct brw_tracked_state brw_line_stipple;
+const struct brw_tracked_state brw_pipelined_state_pointers;
+const struct brw_tracked_state brw_binding_table_pointers;
+const struct brw_tracked_state brw_depthbuffer;
+const struct brw_tracked_state brw_polygon_stipple_offset;
+const struct brw_tracked_state brw_polygon_stipple;
+const struct brw_tracked_state brw_program_parameters;
+const struct brw_tracked_state brw_recalculate_urb_fence;
+const struct brw_tracked_state brw_sf_prog;
+const struct brw_tracked_state brw_sf_unit;
+const struct brw_tracked_state brw_sf_vp;
+const struct brw_tracked_state brw_state_base_address;
+const struct brw_tracked_state brw_urb_fence;
+const struct brw_tracked_state brw_vertex_state;
+const struct brw_tracked_state brw_vs_prog;
+const struct brw_tracked_state brw_vs_unit;
+const struct brw_tracked_state brw_wm_prog;
+const struct brw_tracked_state brw_wm_samplers;
+const struct brw_tracked_state brw_wm_surfaces;
+const struct brw_tracked_state brw_wm_unit;
+
+const struct brw_tracked_state brw_psp_urb_cbs;
+
+const struct brw_tracked_state brw_active_vertprog;
+const struct brw_tracked_state brw_tnl_vertprog;
+const struct brw_tracked_state brw_pipe_control;
+
+const struct brw_tracked_state brw_clear_surface_cache;
+const struct brw_tracked_state brw_clear_batch_cache;
+
+/***********************************************************************
+ * brw_state_cache.c
+ */
+unsigned brw_cache_data(struct brw_cache *cache,
+ const void *data );
+
+unsigned brw_cache_data_sz(struct brw_cache *cache,
+ const void *data,
+ unsigned data_sz);
+
+unsigned brw_upload_cache( struct brw_cache *cache,
+ const void *key,
+ unsigned key_sz,
+ const void *data,
+ unsigned data_sz,
+ const void *aux,
+ void *aux_return );
+
+boolean brw_search_cache( struct brw_cache *cache,
+ const void *key,
+ unsigned key_size,
+ void *aux_return,
+ unsigned *offset_return);
+
+void brw_init_caches( struct brw_context *brw );
+void brw_destroy_caches( struct brw_context *brw );
+
+static inline struct pipe_buffer *brw_cache_buffer(struct brw_context *brw,
+ enum brw_cache_id id)
+{
+ return brw->cache[id].pool->buffer;
+}
+
+/***********************************************************************
+ * brw_state_batch.c
+ */
+#define BRW_CACHED_BATCH_STRUCT(brw, s) brw_cached_batch_struct( brw, (s), sizeof(*(s)) )
+
+boolean brw_cached_batch_struct( struct brw_context *brw,
+ const void *data,
+ unsigned sz );
+
+void brw_destroy_batch_cache( struct brw_context *brw );
+
+
+/***********************************************************************
+ * brw_state_pool.c
+ */
+void brw_init_pools( struct brw_context *brw );
+void brw_destroy_pools( struct brw_context *brw );
+
+boolean brw_pool_alloc( struct brw_mem_pool *pool,
+ unsigned size,
+ unsigned alignment,
+ unsigned *offset_return);
+
+void brw_pool_fence( struct brw_context *brw,
+ struct brw_mem_pool *pool,
+ unsigned fence );
+
+
+void brw_pool_check_wrap( struct brw_context *brw,
+ struct brw_mem_pool *pool );
+
+void brw_clear_all_caches( struct brw_context *brw );
+void brw_invalidate_pools( struct brw_context *brw );
+void brw_clear_batch_cache_flush( struct brw_context *brw );
+
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_state_batch.c b/src/gallium/drivers/i965simple/brw_state_batch.c
new file mode 100644
index 0000000000..43a1c89fc4
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_state_batch.c
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_state.h"
+#include "brw_winsys.h"
+
+#include "util/u_memory.h"
+
+/* A facility similar to the data caching code above, which aims to
+ * prevent identical commands being issued repeatedly.
+ */
+boolean brw_cached_batch_struct( struct brw_context *brw,
+ const void *data,
+ unsigned sz )
+{
+ struct brw_cached_batch_item *item = brw->cached_batch_items;
+ struct header *newheader = (struct header *)data;
+
+ if (brw->emit_state_always) {
+ brw_batchbuffer_data(brw->winsys, data, sz);
+ return TRUE;
+ }
+
+ while (item) {
+ if (item->header->opcode == newheader->opcode) {
+ if (item->sz == sz && memcmp(item->header, newheader, sz) == 0)
+ return 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);
+ brw_batchbuffer_data(brw->winsys, data, sz);
+ return TRUE;
+}
+
+static void 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;
+
+
+ brw_clear_all_caches(brw);
+
+ brw_invalidate_pools(brw);
+}
+
+void brw_clear_batch_cache_flush( struct brw_context *brw )
+{
+ clear_batch_cache(brw);
+
+/* brw_do_flush(brw, BRW_FLUSH_STATE_CACHE|BRW_FLUSH_READ_CACHE); */
+
+ brw->state.dirty.brw |= ~0;
+ brw->state.dirty.cache |= ~0;
+}
+
+
+
+void brw_destroy_batch_cache( struct brw_context *brw )
+{
+ clear_batch_cache(brw);
+}
diff --git a/src/gallium/drivers/i965simple/brw_state_cache.c b/src/gallium/drivers/i965simple/brw_state_cache.c
new file mode 100644
index 0000000000..094248fa69
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_state_cache.c
@@ -0,0 +1,443 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_state.h"
+
+#include "brw_wm.h"
+#include "brw_vs.h"
+#include "brw_clip.h"
+#include "brw_sf.h"
+#include "brw_gs.h"
+
+#include "util/u_memory.h"
+
+
+
+/***********************************************************************
+ * Check cache for uploaded version of struct, else upload new one.
+ * Fail when memory is exhausted.
+ *
+ * XXX: FIXME: Currently search is so slow it would be quicker to
+ * regenerate the data every time...
+ */
+
+static unsigned hash_key( const void *key, unsigned key_size )
+{
+ unsigned *ikey = (unsigned *)key;
+ unsigned hash = 0, i;
+
+ assert(key_size % 4 == 0);
+
+ /* I'm sure this can be improved on:
+ */
+ for (i = 0; i < key_size/4; i++)
+ hash ^= ikey[i];
+
+ return hash;
+}
+
+static struct brw_cache_item *search_cache( struct brw_cache *cache,
+ unsigned hash,
+ const void *key,
+ unsigned key_size)
+{
+ struct brw_cache_item *c;
+
+ for (c = cache->items[hash % cache->size]; c; c = c->next) {
+ if (c->hash == hash &&
+ c->key_size == key_size &&
+ memcmp(c->key, key, key_size) == 0)
+ return c;
+ }
+
+ return NULL;
+}
+
+
+static void rehash( struct brw_cache *cache )
+{
+ struct brw_cache_item **items;
+ struct brw_cache_item *c, *next;
+ unsigned size, i;
+
+ size = cache->size * 3;
+ items = (struct brw_cache_item**) MALLOC(size * sizeof(*items));
+ memset(items, 0, size * sizeof(*items));
+
+ for (i = 0; i < cache->size; i++)
+ for (c = cache->items[i]; c; c = next) {
+ next = c->next;
+ c->next = items[c->hash % size];
+ items[c->hash % size] = c;
+ }
+
+ FREE(cache->items);
+ cache->items = items;
+ cache->size = size;
+}
+
+
+boolean brw_search_cache( struct brw_cache *cache,
+ const void *key,
+ unsigned key_size,
+ void *aux_return,
+ unsigned *offset_return)
+{
+ struct brw_cache_item *item;
+ unsigned addr = 0;
+ unsigned hash = hash_key(key, key_size);
+
+ item = search_cache(cache, hash, key, key_size);
+
+ if (item) {
+ if (aux_return)
+ *(void **)aux_return = (void *)((char *)item->key + item->key_size);
+
+ *offset_return = addr = item->offset;
+ }
+
+ if (item == NULL || addr != cache->last_addr) {
+ cache->brw->state.dirty.cache |= 1<<cache->id;
+ cache->last_addr = addr;
+ }
+
+ return item != NULL;
+}
+
+unsigned brw_upload_cache( struct brw_cache *cache,
+ const void *key,
+ unsigned key_size,
+ const void *data,
+ unsigned data_size,
+ const void *aux,
+ void *aux_return )
+{
+ unsigned offset;
+ struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
+ unsigned hash = hash_key(key, key_size);
+ void *tmp = MALLOC(key_size + cache->aux_size);
+
+ if (!brw_pool_alloc(cache->pool, data_size, 1 << 6, &offset)) {
+ /* Should not be possible:
+ */
+ debug_printf("brw_pool_alloc failed\n");
+ exit(1);
+ }
+
+ memcpy(tmp, key, key_size);
+
+ if (cache->aux_size)
+ memcpy(tmp+key_size, aux, cache->aux_size);
+
+ item->key = tmp;
+ item->hash = hash;
+ item->key_size = key_size;
+ item->offset = offset;
+ item->data_size = data_size;
+
+ if (++cache->n_items > cache->size * 1.5)
+ rehash(cache);
+
+ hash %= cache->size;
+ item->next = cache->items[hash];
+ cache->items[hash] = item;
+
+ if (aux_return) {
+ assert(cache->aux_size);
+ *(void **)aux_return = (void *)((char *)item->key + item->key_size);
+ }
+
+ if (BRW_DEBUG & DEBUG_STATE)
+ debug_printf("upload %s: %d bytes to pool buffer %p offset %x\n",
+ cache->name,
+ data_size,
+ (void*)cache->pool->buffer,
+ offset);
+
+ /* Copy data to the buffer:
+ */
+ cache->brw->winsys->buffer_subdata_typed(cache->brw->winsys,
+ cache->pool->buffer,
+ offset,
+ data_size,
+ data,
+ cache->id);
+
+ cache->brw->state.dirty.cache |= 1<<cache->id;
+ cache->last_addr = offset;
+
+ return offset;
+}
+
+/* This doesn't really work with aux data. Use search/upload instead
+ */
+unsigned brw_cache_data_sz(struct brw_cache *cache,
+ const void *data,
+ unsigned data_size)
+{
+ unsigned addr;
+
+ if (!brw_search_cache(cache, data, data_size, NULL, &addr)) {
+ addr = brw_upload_cache(cache,
+ data, data_size,
+ data, data_size,
+ NULL, NULL);
+ }
+
+ return addr;
+}
+
+unsigned brw_cache_data(struct brw_cache *cache,
+ const void *data)
+{
+ return brw_cache_data_sz(cache, data, cache->key_size);
+}
+
+enum pool_type {
+ DW_SURFACE_STATE,
+ DW_GENERAL_STATE
+};
+
+static void brw_init_cache( struct brw_context *brw,
+ const char *name,
+ unsigned id,
+ unsigned key_size,
+ unsigned aux_size,
+ enum pool_type pool_type)
+{
+ struct brw_cache *cache = &brw->cache[id];
+ cache->brw = brw;
+ cache->id = id;
+ cache->name = name;
+ cache->items = NULL;
+
+ cache->size = 7;
+ cache->n_items = 0;
+ cache->items = (struct brw_cache_item **)
+ CALLOC(cache->size, sizeof(struct brw_cache_item));
+
+
+ cache->key_size = key_size;
+ cache->aux_size = aux_size;
+ switch (pool_type) {
+ case DW_GENERAL_STATE: cache->pool = &brw->pool[BRW_GS_POOL]; break;
+ case DW_SURFACE_STATE: cache->pool = &brw->pool[BRW_SS_POOL]; break;
+ default: assert(0); break;
+ }
+}
+
+void brw_init_caches( struct brw_context *brw )
+{
+
+ brw_init_cache(brw,
+ "CC_VP",
+ BRW_CC_VP,
+ sizeof(struct brw_cc_viewport),
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "CC_UNIT",
+ BRW_CC_UNIT,
+ sizeof(struct brw_cc_unit_state),
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "WM_PROG",
+ BRW_WM_PROG,
+ sizeof(struct brw_wm_prog_key),
+ sizeof(struct brw_wm_prog_data),
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "SAMPLER_DEFAULT_COLOR",
+ BRW_SAMPLER_DEFAULT_COLOR,
+ sizeof(struct brw_sampler_default_color),
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "SAMPLER",
+ BRW_SAMPLER,
+ 0, /* variable key/data size */
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "WM_UNIT",
+ BRW_WM_UNIT,
+ sizeof(struct brw_wm_unit_state),
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "SF_PROG",
+ BRW_SF_PROG,
+ sizeof(struct brw_sf_prog_key),
+ sizeof(struct brw_sf_prog_data),
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "SF_VP",
+ BRW_SF_VP,
+ sizeof(struct brw_sf_viewport),
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "SF_UNIT",
+ BRW_SF_UNIT,
+ sizeof(struct brw_sf_unit_state),
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "VS_UNIT",
+ BRW_VS_UNIT,
+ sizeof(struct brw_vs_unit_state),
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "VS_PROG",
+ BRW_VS_PROG,
+ sizeof(struct brw_vs_prog_key),
+ sizeof(struct brw_vs_prog_data),
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "CLIP_UNIT",
+ BRW_CLIP_UNIT,
+ sizeof(struct brw_clip_unit_state),
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "CLIP_PROG",
+ BRW_CLIP_PROG,
+ sizeof(struct brw_clip_prog_key),
+ sizeof(struct brw_clip_prog_data),
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "GS_UNIT",
+ BRW_GS_UNIT,
+ sizeof(struct brw_gs_unit_state),
+ 0,
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "GS_PROG",
+ BRW_GS_PROG,
+ sizeof(struct brw_gs_prog_key),
+ sizeof(struct brw_gs_prog_data),
+ DW_GENERAL_STATE);
+
+ brw_init_cache(brw,
+ "SS_SURFACE",
+ BRW_SS_SURFACE,
+ sizeof(struct brw_surface_state),
+ 0,
+ DW_SURFACE_STATE);
+
+ brw_init_cache(brw,
+ "SS_SURF_BIND",
+ BRW_SS_SURF_BIND,
+ sizeof(struct brw_surface_binding_table),
+ 0,
+ DW_SURFACE_STATE);
+}
+
+
+/* When we lose hardware context, need to invalidate the surface cache
+ * as these structs must be explicitly re-uploaded. They are subject
+ * to fixup by the memory manager as they contain absolute agp
+ * offsets, so we need to ensure there is a fresh version of the
+ * struct available to receive the fixup.
+ *
+ * XXX: Need to ensure that there aren't two versions of a surface or
+ * bufferobj with different backing data active in the same buffer at
+ * once? Otherwise the cache could confuse them. Maybe better not to
+ * cache at all?
+ *
+ * --> Isn't this the same as saying need to ensure batch is flushed
+ * before new data is uploaded to an existing buffer? We
+ * already try to make sure of that.
+ */
+static void clear_cache( struct brw_cache *cache )
+{
+ struct brw_cache_item *c, *next;
+ unsigned i;
+
+ for (i = 0; i < cache->size; i++) {
+ for (c = cache->items[i]; c; c = next) {
+ next = c->next;
+ free((void *)c->key);
+ free(c);
+ }
+ cache->items[i] = NULL;
+ }
+
+ cache->n_items = 0;
+}
+
+void brw_clear_all_caches( struct brw_context *brw )
+{
+ int i;
+
+ if (BRW_DEBUG & DEBUG_STATE)
+ debug_printf("%s\n", __FUNCTION__);
+
+ for (i = 0; i < BRW_MAX_CACHE; i++)
+ clear_cache(&brw->cache[i]);
+
+ if (brw->curbe.last_buf) {
+ FREE(brw->curbe.last_buf);
+ brw->curbe.last_buf = NULL;
+ }
+
+ brw->state.dirty.brw |= ~0;
+ brw->state.dirty.cache |= ~0;
+}
+
+
+
+
+
+void brw_destroy_caches( struct brw_context *brw )
+{
+ unsigned i;
+
+ for (i = 0; i < BRW_MAX_CACHE; i++)
+ clear_cache(&brw->cache[i]);
+}
diff --git a/src/gallium/drivers/i965simple/brw_state_pool.c b/src/gallium/drivers/i965simple/brw_state_pool.c
new file mode 100644
index 0000000000..e91263cb1f
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_state_pool.c
@@ -0,0 +1,138 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/** @file brw_state_pool.c
+ * Implements the state pool allocator.
+ *
+ * For the 965, we create two state pools for state cache entries. Objects
+ * will be allocated into the pools depending on which state base address
+ * their pointer is relative to in other 965 state.
+ *
+ * The state pools are relatively simple: As objects are allocated, increment
+ * the offset to allocate space. When the pool is "full" (rather, close to
+ * full), we reset the pool and reset the state cache entries that point into
+ * the pool.
+ */
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_inlines.h"
+#include "brw_context.h"
+#include "brw_state.h"
+
+boolean brw_pool_alloc( struct brw_mem_pool *pool,
+ unsigned size,
+ unsigned alignment,
+ unsigned *offset_return)
+{
+ unsigned fixup = align(pool->offset, alignment) - pool->offset;
+
+ size = align(size, 4);
+
+ if (pool->offset + fixup + size >= pool->size) {
+ debug_printf("%s failed\n", __FUNCTION__);
+ assert(0);
+ exit(0);
+ }
+
+ pool->offset += fixup;
+ *offset_return = pool->offset;
+ pool->offset += size;
+
+ return TRUE;
+}
+
+static
+void brw_invalidate_pool( struct brw_mem_pool *pool )
+{
+ if (BRW_DEBUG & DEBUG_STATE)
+ debug_printf("\n\n\n %s \n\n\n", __FUNCTION__);
+
+ pool->offset = 0;
+
+ brw_clear_all_caches(pool->brw);
+}
+
+
+static void brw_init_pool( struct brw_context *brw,
+ unsigned pool_id,
+ unsigned size )
+{
+ struct brw_mem_pool *pool = &brw->pool[pool_id];
+
+ pool->size = size;
+ pool->brw = brw;
+
+ pool->buffer = pipe_buffer_create(brw->pipe.screen,
+ 4096,
+ 0 /* DRM_BO_FLAG_MEM_TT */,
+ size);
+}
+
+static void brw_destroy_pool( struct brw_context *brw,
+ unsigned pool_id )
+{
+ struct brw_mem_pool *pool = &brw->pool[pool_id];
+
+ pipe_buffer_reference( pool->brw->pipe.screen,
+ &pool->buffer,
+ NULL );
+}
+
+
+void brw_pool_check_wrap( struct brw_context *brw,
+ struct brw_mem_pool *pool )
+{
+ if (pool->offset > (pool->size * 3) / 4) {
+ brw->state.dirty.brw |= BRW_NEW_SCENE;
+ }
+
+}
+
+void brw_init_pools( struct brw_context *brw )
+{
+ brw_init_pool(brw, BRW_GS_POOL, 0x80000);
+ brw_init_pool(brw, BRW_SS_POOL, 0x80000);
+}
+
+void brw_destroy_pools( struct brw_context *brw )
+{
+ brw_destroy_pool(brw, BRW_GS_POOL);
+ brw_destroy_pool(brw, BRW_SS_POOL);
+}
+
+
+void brw_invalidate_pools( struct brw_context *brw )
+{
+ brw_invalidate_pool(&brw->pool[BRW_GS_POOL]);
+ brw_invalidate_pool(&brw->pool[BRW_SS_POOL]);
+}
diff --git a/src/gallium/drivers/i965simple/brw_state_upload.c b/src/gallium/drivers/i965simple/brw_state_upload.c
new file mode 100644
index 0000000000..bac9161b5f
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_state_upload.c
@@ -0,0 +1,202 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_state.h"
+
+#include "util/u_memory.h"
+
+/* This is used to initialize brw->state.atoms[]. We could use this
+ * list directly except for a single atom, brw_constant_buffer, which
+ * has a .dirty value which changes according to the parameters of the
+ * current fragment and vertex programs, and so cannot be a static
+ * value.
+ */
+const struct brw_tracked_state *atoms[] =
+{
+ &brw_vs_prog,
+ &brw_gs_prog,
+ &brw_clip_prog,
+ &brw_sf_prog,
+ &brw_wm_prog,
+
+ /* Once all the programs are done, we know how large urb entry
+ * sizes need to be and can decide if we need to change the urb
+ * layout.
+ */
+ &brw_curbe_offsets,
+ &brw_recalculate_urb_fence,
+
+
+ &brw_cc_vp,
+ &brw_cc_unit,
+
+ &brw_wm_surfaces, /* must do before samplers */
+ &brw_wm_samplers,
+
+ &brw_wm_unit,
+ &brw_sf_vp,
+ &brw_sf_unit,
+ &brw_vs_unit, /* always required, enabled or not */
+ &brw_clip_unit,
+ &brw_gs_unit,
+
+ /* Command packets:
+ */
+ &brw_invarient_state,
+ &brw_state_base_address,
+ &brw_pipe_control,
+
+ &brw_binding_table_pointers,
+ &brw_blend_constant_color,
+
+ &brw_drawing_rect,
+ &brw_depthbuffer,
+
+ &brw_polygon_stipple,
+ &brw_line_stipple,
+
+ &brw_psp_urb_cbs,
+
+ &brw_constant_buffer
+};
+
+
+void brw_init_state( struct brw_context *brw )
+{
+ brw_init_pools(brw);
+ brw_init_caches(brw);
+
+ brw->state.dirty.brw = ~0;
+ brw->emit_state_always = 0;
+}
+
+
+void brw_destroy_state( struct brw_context *brw )
+{
+ brw_destroy_caches(brw);
+ brw_destroy_batch_cache(brw);
+ brw_destroy_pools(brw);
+}
+
+/***********************************************************************
+ */
+
+static boolean check_state( const struct brw_state_flags *a,
+ const struct brw_state_flags *b )
+{
+ return ((a->brw & b->brw) ||
+ (a->cache & b->cache));
+}
+
+static void accumulate_state( struct brw_state_flags *a,
+ const struct brw_state_flags *b )
+{
+ a->brw |= b->brw;
+ a->cache |= b->cache;
+}
+
+
+static void xor_states( struct brw_state_flags *result,
+ const struct brw_state_flags *a,
+ const struct brw_state_flags *b )
+{
+ result->brw = a->brw ^ b->brw;
+ result->cache = a->cache ^ b->cache;
+}
+
+
+/***********************************************************************
+ * Emit all state:
+ */
+void brw_validate_state( struct brw_context *brw )
+{
+ struct brw_state_flags *state = &brw->state.dirty;
+ unsigned i;
+
+ if (brw->emit_state_always)
+ state->brw |= ~0;
+
+ if (state->cache == 0 &&
+ state->brw == 0)
+ return;
+
+ if (brw->state.dirty.brw & BRW_NEW_SCENE)
+ brw_clear_batch_cache_flush(brw);
+
+ if (BRW_DEBUG) {
+ /* Debug version which enforces various sanity checks on the
+ * state flags which are generated and checked to help ensure
+ * state atoms are ordered correctly in the list.
+ */
+ struct brw_state_flags examined, prev;
+ memset(&examined, 0, sizeof(examined));
+ prev = *state;
+
+ for (i = 0; i < Elements(atoms); i++) {
+ const struct brw_tracked_state *atom = atoms[i];
+ struct brw_state_flags generated;
+
+ assert(atom->dirty.brw ||
+ atom->dirty.cache);
+ assert(atom->update);
+
+ if (check_state(state, &atom->dirty)) {
+ atom->update( brw );
+ }
+
+ accumulate_state(&examined, &atom->dirty);
+
+ /* generated = (prev ^ state)
+ * if (examined & generated)
+ * fail;
+ */
+ xor_states(&generated, &prev, state);
+ assert(!check_state(&examined, &generated));
+ prev = *state;
+ }
+ }
+ else {
+ for (i = 0; i < Elements(atoms); i++) {
+ const struct brw_tracked_state *atom = atoms[i];
+
+ assert(atom->dirty.brw ||
+ atom->dirty.cache);
+ assert(atom->update);
+
+ if (check_state(state, &atom->dirty))
+ atom->update( brw );
+ }
+ }
+
+ memset(state, 0, sizeof(*state));
+}
diff --git a/src/gallium/drivers/i965simple/brw_structs.h b/src/gallium/drivers/i965simple/brw_structs.h
new file mode 100644
index 0000000000..bbb087e95d
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_structs.h
@@ -0,0 +1,1348 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRW_STRUCTS_H
+#define BRW_STRUCTS_H
+
+#include "pipe/p_compiler.h"
+
+/* Command packets:
+ */
+struct header
+{
+ unsigned length:16;
+ unsigned opcode:16;
+};
+
+
+union header_union
+{
+ struct header bits;
+ unsigned dword;
+};
+
+struct brw_3d_control
+{
+ struct
+ {
+ unsigned length:8;
+ unsigned notify_enable:1;
+ unsigned pad:3;
+ unsigned wc_flush_enable:1;
+ unsigned depth_stall_enable:1;
+ unsigned operation:2;
+ unsigned opcode:16;
+ } header;
+
+ struct
+ {
+ unsigned pad:2;
+ unsigned dest_addr_type:1;
+ unsigned dest_addr:29;
+ } dest;
+
+ unsigned dword2;
+ unsigned dword3;
+};
+
+
+struct brw_3d_primitive
+{
+ struct
+ {
+ unsigned length:8;
+ unsigned pad:2;
+ unsigned topology:5;
+ unsigned indexed:1;
+ unsigned opcode:16;
+ } header;
+
+ unsigned verts_per_instance;
+ unsigned start_vert_location;
+ unsigned instance_count;
+ unsigned start_instance_location;
+ unsigned base_vert_location;
+};
+
+/* These seem to be passed around as function args, so it works out
+ * better to keep them as #defines:
+ */
+#define BRW_FLUSH_READ_CACHE 0x1
+#define BRW_FLUSH_STATE_CACHE 0x2
+#define BRW_INHIBIT_FLUSH_RENDER_CACHE 0x4
+#define BRW_FLUSH_SNAPSHOT_COUNTERS 0x8
+
+struct brw_mi_flush
+{
+ unsigned flags:4;
+ unsigned pad:12;
+ unsigned opcode:16;
+};
+
+struct brw_vf_statistics
+{
+ unsigned statistics_enable:1;
+ unsigned pad:15;
+ unsigned opcode:16;
+};
+
+
+
+struct brw_binding_table_pointers
+{
+ struct header header;
+ unsigned vs;
+ unsigned gs;
+ unsigned clp;
+ unsigned sf;
+ unsigned wm;
+};
+
+
+struct brw_blend_constant_color
+{
+ struct header header;
+ float blend_constant_color[4];
+};
+
+
+struct brw_depthbuffer
+{
+ union header_union header;
+
+ union {
+ struct {
+ unsigned pitch:18;
+ unsigned format:3;
+ unsigned pad:4;
+ unsigned depth_offset_disable:1;
+ unsigned tile_walk:1;
+ unsigned tiled_surface:1;
+ unsigned pad2:1;
+ unsigned surface_type:3;
+ } bits;
+ unsigned dword;
+ } dword1;
+
+ unsigned dword2_base_addr;
+
+ union {
+ struct {
+ unsigned pad:1;
+ unsigned mipmap_layout:1;
+ unsigned lod:4;
+ unsigned width:13;
+ unsigned height:13;
+ } bits;
+ unsigned dword;
+ } dword3;
+
+ union {
+ struct {
+ unsigned pad:12;
+ unsigned min_array_element:9;
+ unsigned depth:11;
+ } bits;
+ unsigned dword;
+ } dword4;
+};
+
+struct brw_drawrect
+{
+ struct header header;
+ unsigned xmin:16;
+ unsigned ymin:16;
+ unsigned xmax:16;
+ unsigned ymax:16;
+ unsigned xorg:16;
+ unsigned yorg:16;
+};
+
+
+
+
+struct brw_global_depth_offset_clamp
+{
+ struct header header;
+ float depth_offset_clamp;
+};
+
+struct brw_indexbuffer
+{
+ union {
+ struct
+ {
+ unsigned length:8;
+ unsigned index_format:2;
+ unsigned cut_index_enable:1;
+ unsigned pad:5;
+ unsigned opcode:16;
+ } bits;
+ unsigned dword;
+
+ } header;
+
+ unsigned buffer_start;
+ unsigned buffer_end;
+};
+
+
+struct brw_line_stipple
+{
+ struct header header;
+
+ struct
+ {
+ unsigned pattern:16;
+ unsigned pad:16;
+ } bits0;
+
+ struct
+ {
+ unsigned repeat_count:9;
+ unsigned pad:7;
+ unsigned inverse_repeat_count:16;
+ } bits1;
+};
+
+
+struct brw_pipelined_state_pointers
+{
+ struct header header;
+
+ struct {
+ unsigned pad:5;
+ unsigned offset:27;
+ } vs;
+
+ struct
+ {
+ unsigned enable:1;
+ unsigned pad:4;
+ unsigned offset:27;
+ } gs;
+
+ struct
+ {
+ unsigned enable:1;
+ unsigned pad:4;
+ unsigned offset:27;
+ } clp;
+
+ struct
+ {
+ unsigned pad:5;
+ unsigned offset:27;
+ } sf;
+
+ struct
+ {
+ unsigned pad:5;
+ unsigned offset:27;
+ } wm;
+
+ struct
+ {
+ unsigned pad:5;
+ unsigned offset:27; /* KW: check me! */
+ } cc;
+};
+
+
+struct brw_polygon_stipple_offset
+{
+ struct header header;
+
+ struct {
+ unsigned y_offset:5;
+ unsigned pad:3;
+ unsigned x_offset:5;
+ unsigned pad0:19;
+ } bits0;
+};
+
+
+
+struct brw_polygon_stipple
+{
+ struct header header;
+ unsigned stipple[32];
+};
+
+
+
+struct brw_pipeline_select
+{
+ struct
+ {
+ unsigned pipeline_select:1;
+ unsigned pad:15;
+ unsigned opcode:16;
+ } header;
+};
+
+
+struct brw_pipe_control
+{
+ struct
+ {
+ unsigned length:8;
+ unsigned notify_enable:1;
+ unsigned pad:2;
+ unsigned instruction_state_cache_flush_enable:1;
+ unsigned write_cache_flush_enable:1;
+ unsigned depth_stall_enable:1;
+ unsigned post_sync_operation:2;
+
+ unsigned opcode:16;
+ } header;
+
+ struct
+ {
+ unsigned pad:2;
+ unsigned dest_addr_type:1;
+ unsigned dest_addr:29;
+ } bits1;
+
+ unsigned data0;
+ unsigned data1;
+};
+
+
+struct brw_urb_fence
+{
+ struct
+ {
+ unsigned length:8;
+ unsigned vs_realloc:1;
+ unsigned gs_realloc:1;
+ unsigned clp_realloc:1;
+ unsigned sf_realloc:1;
+ unsigned vfe_realloc:1;
+ unsigned cs_realloc:1;
+ unsigned pad:2;
+ unsigned opcode:16;
+ } header;
+
+ struct
+ {
+ unsigned vs_fence:10;
+ unsigned gs_fence:10;
+ unsigned clp_fence:10;
+ unsigned pad:2;
+ } bits0;
+
+ struct
+ {
+ unsigned sf_fence:10;
+ unsigned vf_fence:10;
+ unsigned cs_fence:10;
+ unsigned pad:2;
+ } bits1;
+};
+
+struct brw_constant_buffer_state /* previously brw_command_streamer */
+{
+ struct header header;
+
+ struct
+ {
+ unsigned nr_urb_entries:3;
+ unsigned pad:1;
+ unsigned urb_entry_size:5;
+ unsigned pad0:23;
+ } bits0;
+};
+
+struct brw_constant_buffer
+{
+ struct
+ {
+ unsigned length:8;
+ unsigned valid:1;
+ unsigned pad:7;
+ unsigned opcode:16;
+ } header;
+
+ struct
+ {
+ unsigned buffer_length:6;
+ unsigned buffer_address:26;
+ } bits0;
+};
+
+struct brw_state_base_address
+{
+ struct header header;
+
+ struct
+ {
+ unsigned modify_enable:1;
+ unsigned pad:4;
+ unsigned general_state_address:27;
+ } bits0;
+
+ struct
+ {
+ unsigned modify_enable:1;
+ unsigned pad:4;
+ unsigned surface_state_address:27;
+ } bits1;
+
+ struct
+ {
+ unsigned modify_enable:1;
+ unsigned pad:4;
+ unsigned indirect_object_state_address:27;
+ } bits2;
+
+ struct
+ {
+ unsigned modify_enable:1;
+ unsigned pad:11;
+ unsigned general_state_upper_bound:20;
+ } bits3;
+
+ struct
+ {
+ unsigned modify_enable:1;
+ unsigned pad:11;
+ unsigned indirect_object_state_upper_bound:20;
+ } bits4;
+};
+
+struct brw_state_prefetch
+{
+ struct header header;
+
+ struct
+ {
+ unsigned prefetch_count:3;
+ unsigned pad:3;
+ unsigned prefetch_pointer:26;
+ } bits0;
+};
+
+struct brw_system_instruction_pointer
+{
+ struct header header;
+
+ struct
+ {
+ unsigned pad:4;
+ unsigned system_instruction_pointer:28;
+ } bits0;
+};
+
+
+
+
+/* State structs for the various fixed function units:
+ */
+
+
+struct thread0
+{
+ unsigned pad0:1;
+ unsigned grf_reg_count:3;
+ unsigned pad1:2;
+ unsigned kernel_start_pointer:26;
+};
+
+struct thread1
+{
+ unsigned ext_halt_exception_enable:1;
+ unsigned sw_exception_enable:1;
+ unsigned mask_stack_exception_enable:1;
+ unsigned timeout_exception_enable:1;
+ unsigned illegal_op_exception_enable:1;
+ unsigned pad0:3;
+ unsigned depth_coef_urb_read_offset:6; /* WM only */
+ unsigned pad1:2;
+ unsigned floating_point_mode:1;
+ unsigned thread_priority:1;
+ unsigned binding_table_entry_count:8;
+ unsigned pad3:5;
+ unsigned single_program_flow:1;
+};
+
+struct thread2
+{
+ unsigned per_thread_scratch_space:4;
+ unsigned pad0:6;
+ unsigned scratch_space_base_pointer:22;
+};
+
+
+struct thread3
+{
+ unsigned dispatch_grf_start_reg:4;
+ unsigned urb_entry_read_offset:6;
+ unsigned pad0:1;
+ unsigned urb_entry_read_length:6;
+ unsigned pad1:1;
+ unsigned const_urb_entry_read_offset:6;
+ unsigned pad2:1;
+ unsigned const_urb_entry_read_length:6;
+ unsigned pad3:1;
+};
+
+
+
+struct brw_clip_unit_state
+{
+ struct thread0 thread0;
+ struct
+ {
+ unsigned pad0:7;
+ unsigned sw_exception_enable:1;
+ unsigned pad1:3;
+ unsigned mask_stack_exception_enable:1;
+ unsigned pad2:1;
+ unsigned illegal_op_exception_enable:1;
+ unsigned pad3:2;
+ unsigned floating_point_mode:1;
+ unsigned thread_priority:1;
+ unsigned binding_table_entry_count:8;
+ unsigned pad4:5;
+ unsigned single_program_flow:1;
+ } thread1;
+
+ struct thread2 thread2;
+ struct thread3 thread3;
+
+ struct
+ {
+ unsigned pad0:9;
+ unsigned gs_output_stats:1; /* not always */
+ unsigned stats_enable:1;
+ unsigned nr_urb_entries:7;
+ unsigned pad1:1;
+ unsigned urb_entry_allocation_size:5;
+ unsigned pad2:1;
+ unsigned max_threads:1; /* may be less */
+ unsigned pad3:6;
+ } thread4;
+
+ struct
+ {
+ unsigned pad0:13;
+ unsigned clip_mode:3;
+ unsigned userclip_enable_flags:8;
+ unsigned userclip_must_clip:1;
+ unsigned pad1:1;
+ unsigned guard_band_enable:1;
+ unsigned viewport_z_clip_enable:1;
+ unsigned viewport_xy_clip_enable:1;
+ unsigned vertex_position_space:1;
+ unsigned api_mode:1;
+ unsigned pad2:1;
+ } clip5;
+
+ struct
+ {
+ unsigned pad0:5;
+ unsigned clipper_viewport_state_ptr:27;
+ } clip6;
+
+
+ float viewport_xmin;
+ float viewport_xmax;
+ float viewport_ymin;
+ float viewport_ymax;
+};
+
+
+
+struct brw_cc_unit_state
+{
+ struct
+ {
+ unsigned pad0:3;
+ unsigned bf_stencil_pass_depth_pass_op:3;
+ unsigned bf_stencil_pass_depth_fail_op:3;
+ unsigned bf_stencil_fail_op:3;
+ unsigned bf_stencil_func:3;
+ unsigned bf_stencil_enable:1;
+ unsigned pad1:2;
+ unsigned stencil_write_enable:1;
+ unsigned stencil_pass_depth_pass_op:3;
+ unsigned stencil_pass_depth_fail_op:3;
+ unsigned stencil_fail_op:3;
+ unsigned stencil_func:3;
+ unsigned stencil_enable:1;
+ } cc0;
+
+
+ struct
+ {
+ unsigned bf_stencil_ref:8;
+ unsigned stencil_write_mask:8;
+ unsigned stencil_test_mask:8;
+ unsigned stencil_ref:8;
+ } cc1;
+
+
+ struct
+ {
+ unsigned logicop_enable:1;
+ unsigned pad0:10;
+ unsigned depth_write_enable:1;
+ unsigned depth_test_function:3;
+ unsigned depth_test:1;
+ unsigned bf_stencil_write_mask:8;
+ unsigned bf_stencil_test_mask:8;
+ } cc2;
+
+
+ struct
+ {
+ unsigned pad0:8;
+ unsigned alpha_test_func:3;
+ unsigned alpha_test:1;
+ unsigned blend_enable:1;
+ unsigned ia_blend_enable:1;
+ unsigned pad1:1;
+ unsigned alpha_test_format:1;
+ unsigned pad2:16;
+ } cc3;
+
+ struct
+ {
+ unsigned pad0:5;
+ unsigned cc_viewport_state_offset:27;
+ } cc4;
+
+ struct
+ {
+ unsigned pad0:2;
+ unsigned ia_dest_blend_factor:5;
+ unsigned ia_src_blend_factor:5;
+ unsigned ia_blend_function:3;
+ unsigned statistics_enable:1;
+ unsigned logicop_func:4;
+ unsigned pad1:11;
+ unsigned dither_enable:1;
+ } cc5;
+
+ struct
+ {
+ unsigned clamp_post_alpha_blend:1;
+ unsigned clamp_pre_alpha_blend:1;
+ unsigned clamp_range:2;
+ unsigned pad0:11;
+ unsigned y_dither_offset:2;
+ unsigned x_dither_offset:2;
+ unsigned dest_blend_factor:5;
+ unsigned src_blend_factor:5;
+ unsigned blend_function:3;
+ } cc6;
+
+ struct {
+ union {
+ float f;
+ ubyte ub[4];
+ } alpha_ref;
+ } cc7;
+};
+
+
+
+struct brw_sf_unit_state
+{
+ struct thread0 thread0;
+ struct thread1 thread1;
+ struct thread2 thread2;
+ struct thread3 thread3;
+
+ struct
+ {
+ unsigned pad0:10;
+ unsigned stats_enable:1;
+ unsigned nr_urb_entries:7;
+ unsigned pad1:1;
+ unsigned urb_entry_allocation_size:5;
+ unsigned pad2:1;
+ unsigned max_threads:6;
+ unsigned pad3:1;
+ } thread4;
+
+ struct
+ {
+ unsigned front_winding:1;
+ unsigned viewport_transform:1;
+ unsigned pad0:3;
+ unsigned sf_viewport_state_offset:27;
+ } sf5;
+
+ struct
+ {
+ unsigned pad0:9;
+ unsigned dest_org_vbias:4;
+ unsigned dest_org_hbias:4;
+ unsigned scissor:1;
+ unsigned disable_2x2_trifilter:1;
+ unsigned disable_zero_pix_trifilter:1;
+ unsigned point_rast_rule:2;
+ unsigned line_endcap_aa_region_width:2;
+ unsigned line_width:4;
+ unsigned fast_scissor_disable:1;
+ unsigned cull_mode:2;
+ unsigned aa_enable:1;
+ } sf6;
+
+ struct
+ {
+ unsigned point_size:11;
+ unsigned use_point_size_state:1;
+ unsigned subpixel_precision:1;
+ unsigned sprite_point:1;
+ unsigned pad0:11;
+ unsigned trifan_pv:2;
+ unsigned linestrip_pv:2;
+ unsigned tristrip_pv:2;
+ unsigned line_last_pixel_enable:1;
+ } sf7;
+
+};
+
+
+struct brw_gs_unit_state
+{
+ struct thread0 thread0;
+ struct thread1 thread1;
+ struct thread2 thread2;
+ struct thread3 thread3;
+
+ struct
+ {
+ unsigned pad0:10;
+ unsigned stats_enable:1;
+ unsigned nr_urb_entries:7;
+ unsigned pad1:1;
+ unsigned urb_entry_allocation_size:5;
+ unsigned pad2:1;
+ unsigned max_threads:1;
+ unsigned pad3:6;
+ } thread4;
+
+ struct
+ {
+ unsigned sampler_count:3;
+ unsigned pad0:2;
+ unsigned sampler_state_pointer:27;
+ } gs5;
+
+
+ struct
+ {
+ unsigned max_vp_index:4;
+ unsigned pad0:26;
+ unsigned reorder_enable:1;
+ unsigned pad1:1;
+ } gs6;
+};
+
+
+struct brw_vs_unit_state
+{
+ struct thread0 thread0;
+ struct thread1 thread1;
+ struct thread2 thread2;
+ struct thread3 thread3;
+
+ struct
+ {
+ unsigned pad0:10;
+ unsigned stats_enable:1;
+ unsigned nr_urb_entries:7;
+ unsigned pad1:1;
+ unsigned urb_entry_allocation_size:5;
+ unsigned pad2:1;
+ unsigned max_threads:4;
+ unsigned pad3:3;
+ } thread4;
+
+ struct
+ {
+ unsigned sampler_count:3;
+ unsigned pad0:2;
+ unsigned sampler_state_pointer:27;
+ } vs5;
+
+ struct
+ {
+ unsigned vs_enable:1;
+ unsigned vert_cache_disable:1;
+ unsigned pad0:30;
+ } vs6;
+};
+
+
+struct brw_wm_unit_state
+{
+ struct thread0 thread0;
+ struct thread1 thread1;
+ struct thread2 thread2;
+ struct thread3 thread3;
+
+ struct {
+ unsigned stats_enable:1;
+ unsigned pad0:1;
+ unsigned sampler_count:3;
+ unsigned sampler_state_pointer:27;
+ } wm4;
+
+ struct
+ {
+ unsigned enable_8_pix:1;
+ unsigned enable_16_pix:1;
+ unsigned enable_32_pix:1;
+ unsigned pad0:7;
+ unsigned legacy_global_depth_bias:1;
+ unsigned line_stipple:1;
+ unsigned depth_offset:1;
+ unsigned polygon_stipple:1;
+ unsigned line_aa_region_width:2;
+ unsigned line_endcap_aa_region_width:2;
+ unsigned early_depth_test:1;
+ unsigned thread_dispatch_enable:1;
+ unsigned program_uses_depth:1;
+ unsigned program_computes_depth:1;
+ unsigned program_uses_killpixel:1;
+ unsigned legacy_line_rast: 1;
+ unsigned pad1:1;
+ unsigned max_threads:6;
+ unsigned pad2:1;
+ } wm5;
+
+ float global_depth_offset_constant;
+ float global_depth_offset_scale;
+};
+
+struct brw_sampler_default_color {
+ float color[4];
+};
+
+struct brw_sampler_state
+{
+
+ struct
+ {
+ unsigned shadow_function:3;
+ unsigned lod_bias:11;
+ unsigned min_filter:3;
+ unsigned mag_filter:3;
+ unsigned mip_filter:2;
+ unsigned base_level:5;
+ unsigned pad:1;
+ unsigned lod_preclamp:1;
+ unsigned default_color_mode:1;
+ unsigned pad0:1;
+ unsigned disable:1;
+ } ss0;
+
+ struct
+ {
+ unsigned r_wrap_mode:3;
+ unsigned t_wrap_mode:3;
+ unsigned s_wrap_mode:3;
+ unsigned pad:3;
+ unsigned max_lod:10;
+ unsigned min_lod:10;
+ } ss1;
+
+
+ struct
+ {
+ unsigned pad:5;
+ unsigned default_color_pointer:27;
+ } ss2;
+
+ struct
+ {
+ unsigned pad:19;
+ unsigned max_aniso:3;
+ unsigned chroma_key_mode:1;
+ unsigned chroma_key_index:2;
+ unsigned chroma_key_enable:1;
+ unsigned monochrome_filter_width:3;
+ unsigned monochrome_filter_height:3;
+ } ss3;
+};
+
+
+struct brw_clipper_viewport
+{
+ float xmin;
+ float xmax;
+ float ymin;
+ float ymax;
+};
+
+struct brw_cc_viewport
+{
+ float min_depth;
+ float max_depth;
+};
+
+struct brw_sf_viewport
+{
+ struct {
+ float m00;
+ float m11;
+ float m22;
+ float m30;
+ float m31;
+ float m32;
+ } viewport;
+
+ struct {
+ short xmin;
+ short ymin;
+ short xmax;
+ short ymax;
+ } scissor;
+};
+
+/* Documented in the subsystem/shared-functions/sampler chapter...
+ */
+struct brw_surface_state
+{
+ struct {
+ unsigned cube_pos_z:1;
+ unsigned cube_neg_z:1;
+ unsigned cube_pos_y:1;
+ unsigned cube_neg_y:1;
+ unsigned cube_pos_x:1;
+ unsigned cube_neg_x:1;
+ unsigned pad:4;
+ unsigned mipmap_layout_mode:1;
+ unsigned vert_line_stride_ofs:1;
+ unsigned vert_line_stride:1;
+ unsigned color_blend:1;
+ unsigned writedisable_blue:1;
+ unsigned writedisable_green:1;
+ unsigned writedisable_red:1;
+ unsigned writedisable_alpha:1;
+ unsigned surface_format:9;
+ unsigned data_return_format:1;
+ unsigned pad0:1;
+ unsigned surface_type:3;
+ } ss0;
+
+ struct {
+ unsigned base_addr;
+ } ss1;
+
+ struct {
+ unsigned pad:2;
+ unsigned mip_count:4;
+ unsigned width:13;
+ unsigned height:13;
+ } ss2;
+
+ struct {
+ unsigned tile_walk:1;
+ unsigned tiled_surface:1;
+ unsigned pad:1;
+ unsigned pitch:18;
+ unsigned depth:11;
+ } ss3;
+
+ struct {
+ unsigned pad:19;
+ unsigned min_array_elt:9;
+ unsigned min_lod:4;
+ } ss4;
+};
+
+
+
+struct brw_vertex_buffer_state
+{
+ struct {
+ unsigned pitch:11;
+ unsigned pad:15;
+ unsigned access_type:1;
+ unsigned vb_index:5;
+ } vb0;
+
+ unsigned start_addr;
+ unsigned max_index;
+#if 1
+ unsigned instance_data_step_rate; /* not included for sequential/random vertices? */
+#endif
+};
+
+#define BRW_VBP_MAX 17
+
+struct brw_vb_array_state {
+ struct header header;
+ struct brw_vertex_buffer_state vb[BRW_VBP_MAX];
+};
+
+
+struct brw_vertex_element_state
+{
+ struct
+ {
+ unsigned src_offset:11;
+ unsigned pad:5;
+ unsigned src_format:9;
+ unsigned pad0:1;
+ unsigned valid:1;
+ unsigned vertex_buffer_index:5;
+ } ve0;
+
+ struct
+ {
+ unsigned dst_offset:8;
+ unsigned pad:8;
+ unsigned vfcomponent3:4;
+ unsigned vfcomponent2:4;
+ unsigned vfcomponent1:4;
+ unsigned vfcomponent0:4;
+ } ve1;
+};
+
+#define BRW_VEP_MAX 18
+
+struct brw_vertex_element_packet {
+ struct header header;
+ struct brw_vertex_element_state ve[BRW_VEP_MAX]; /* note: less than _TNL_ATTRIB_MAX */
+};
+
+
+struct brw_urb_immediate {
+ unsigned opcode:4;
+ unsigned offset:6;
+ unsigned swizzle_control:2;
+ unsigned pad:1;
+ unsigned allocate:1;
+ unsigned used:1;
+ unsigned complete:1;
+ unsigned response_length:4;
+ unsigned msg_length:4;
+ unsigned msg_target:4;
+ unsigned pad1:3;
+ unsigned end_of_thread:1;
+};
+
+/* Instruction format for the execution units:
+ */
+
+struct brw_instruction
+{
+ struct
+ {
+ unsigned opcode:7;
+ unsigned pad:1;
+ unsigned access_mode:1;
+ unsigned mask_control:1;
+ unsigned dependency_control:2;
+ unsigned compression_control:2;
+ unsigned thread_control:2;
+ unsigned predicate_control:4;
+ unsigned predicate_inverse:1;
+ unsigned execution_size:3;
+ unsigned destreg__conditonalmod:4; /* destreg - send, conditionalmod - others */
+ unsigned pad0:2;
+ unsigned debug_control:1;
+ unsigned saturate:1;
+ } header;
+
+ union {
+ struct
+ {
+ unsigned dest_reg_file:2;
+ unsigned dest_reg_type:3;
+ unsigned src0_reg_file:2;
+ unsigned src0_reg_type:3;
+ unsigned src1_reg_file:2;
+ unsigned src1_reg_type:3;
+ unsigned pad:1;
+ unsigned dest_subreg_nr:5;
+ unsigned dest_reg_nr:8;
+ unsigned dest_horiz_stride:2;
+ unsigned dest_address_mode:1;
+ } da1;
+
+ struct
+ {
+ unsigned dest_reg_file:2;
+ unsigned dest_reg_type:3;
+ unsigned src0_reg_file:2;
+ unsigned src0_reg_type:3;
+ unsigned pad:6;
+ int dest_indirect_offset:10; /* offset against the deref'd address reg */
+ unsigned dest_subreg_nr:3; /* subnr for the address reg a0.x */
+ unsigned dest_horiz_stride:2;
+ unsigned dest_address_mode:1;
+ } ia1;
+
+ struct
+ {
+ unsigned dest_reg_file:2;
+ unsigned dest_reg_type:3;
+ unsigned src0_reg_file:2;
+ unsigned src0_reg_type:3;
+ unsigned src1_reg_file:2;
+ unsigned src1_reg_type:3;
+ unsigned pad0:1;
+ unsigned dest_writemask:4;
+ unsigned dest_subreg_nr:1;
+ unsigned dest_reg_nr:8;
+ unsigned pad1:2;
+ unsigned dest_address_mode:1;
+ } da16;
+
+ struct
+ {
+ unsigned dest_reg_file:2;
+ unsigned dest_reg_type:3;
+ unsigned src0_reg_file:2;
+ unsigned src0_reg_type:3;
+ unsigned pad0:6;
+ unsigned dest_writemask:4;
+ int dest_indirect_offset:6;
+ unsigned dest_subreg_nr:3;
+ unsigned pad1:2;
+ unsigned dest_address_mode:1;
+ } ia16;
+ } bits1;
+
+
+ union {
+ struct
+ {
+ unsigned src0_subreg_nr:5;
+ unsigned src0_reg_nr:8;
+ unsigned src0_abs:1;
+ unsigned src0_negate:1;
+ unsigned src0_address_mode:1;
+ unsigned src0_horiz_stride:2;
+ unsigned src0_width:3;
+ unsigned src0_vert_stride:4;
+ unsigned flag_reg_nr:1;
+ unsigned pad:6;
+ } da1;
+
+ struct
+ {
+ int src0_indirect_offset:10;
+ unsigned src0_subreg_nr:3;
+ unsigned src0_abs:1;
+ unsigned src0_negate:1;
+ unsigned src0_address_mode:1;
+ unsigned src0_horiz_stride:2;
+ unsigned src0_width:3;
+ unsigned src0_vert_stride:4;
+ unsigned flag_reg_nr:1;
+ unsigned pad:6;
+ } ia1;
+
+ struct
+ {
+ unsigned src0_swz_x:2;
+ unsigned src0_swz_y:2;
+ unsigned src0_subreg_nr:1;
+ unsigned src0_reg_nr:8;
+ unsigned src0_abs:1;
+ unsigned src0_negate:1;
+ unsigned src0_address_mode:1;
+ unsigned src0_swz_z:2;
+ unsigned src0_swz_w:2;
+ unsigned pad0:1;
+ unsigned src0_vert_stride:4;
+ unsigned flag_reg_nr:1;
+ unsigned pad1:6;
+ } da16;
+
+ struct
+ {
+ unsigned src0_swz_x:2;
+ unsigned src0_swz_y:2;
+ int src0_indirect_offset:6;
+ unsigned src0_subreg_nr:3;
+ unsigned src0_abs:1;
+ unsigned src0_negate:1;
+ unsigned src0_address_mode:1;
+ unsigned src0_swz_z:2;
+ unsigned src0_swz_w:2;
+ unsigned pad0:1;
+ unsigned src0_vert_stride:4;
+ unsigned flag_reg_nr:1;
+ unsigned pad1:6;
+ } ia16;
+
+ } bits2;
+
+ union
+ {
+ struct
+ {
+ unsigned src1_subreg_nr:5;
+ unsigned src1_reg_nr:8;
+ unsigned src1_abs:1;
+ unsigned src1_negate:1;
+ unsigned pad:1;
+ unsigned src1_horiz_stride:2;
+ unsigned src1_width:3;
+ unsigned src1_vert_stride:4;
+ unsigned pad0:7;
+ } da1;
+
+ struct
+ {
+ unsigned src1_swz_x:2;
+ unsigned src1_swz_y:2;
+ unsigned src1_subreg_nr:1;
+ unsigned src1_reg_nr:8;
+ unsigned src1_abs:1;
+ unsigned src1_negate:1;
+ unsigned pad0:1;
+ unsigned src1_swz_z:2;
+ unsigned src1_swz_w:2;
+ unsigned pad1:1;
+ unsigned src1_vert_stride:4;
+ unsigned pad2:7;
+ } da16;
+
+ struct
+ {
+ int src1_indirect_offset:10;
+ unsigned src1_subreg_nr:3;
+ unsigned src1_abs:1;
+ unsigned src1_negate:1;
+ unsigned pad0:1;
+ unsigned src1_horiz_stride:2;
+ unsigned src1_width:3;
+ unsigned src1_vert_stride:4;
+ unsigned flag_reg_nr:1;
+ unsigned pad1:6;
+ } ia1;
+
+ struct
+ {
+ unsigned src1_swz_x:2;
+ unsigned src1_swz_y:2;
+ int src1_indirect_offset:6;
+ unsigned src1_subreg_nr:3;
+ unsigned src1_abs:1;
+ unsigned src1_negate:1;
+ unsigned pad0:1;
+ unsigned src1_swz_z:2;
+ unsigned src1_swz_w:2;
+ unsigned pad1:1;
+ unsigned src1_vert_stride:4;
+ unsigned flag_reg_nr:1;
+ unsigned pad2:6;
+ } ia16;
+
+
+ struct
+ {
+ int jump_count:16; /* note: signed */
+ unsigned pop_count:4;
+ unsigned pad0:12;
+ } if_else;
+
+ struct {
+ unsigned function:4;
+ unsigned int_type:1;
+ unsigned precision:1;
+ unsigned saturate:1;
+ unsigned data_type:1;
+ unsigned pad0:8;
+ unsigned response_length:4;
+ unsigned msg_length:4;
+ unsigned msg_target:4;
+ unsigned pad1:3;
+ unsigned end_of_thread:1;
+ } math;
+
+ struct {
+ unsigned binding_table_index:8;
+ unsigned sampler:4;
+ unsigned return_format:2;
+ unsigned msg_type:2;
+ unsigned response_length:4;
+ unsigned msg_length:4;
+ unsigned msg_target:4;
+ unsigned pad1:3;
+ unsigned end_of_thread:1;
+ } sampler;
+
+ struct brw_urb_immediate urb;
+
+ struct {
+ unsigned binding_table_index:8;
+ unsigned msg_control:4;
+ unsigned msg_type:2;
+ unsigned target_cache:2;
+ unsigned response_length:4;
+ unsigned msg_length:4;
+ unsigned msg_target:4;
+ unsigned pad1:3;
+ unsigned end_of_thread:1;
+ } dp_read;
+
+ struct {
+ unsigned binding_table_index:8;
+ unsigned msg_control:3;
+ unsigned pixel_scoreboard_clear:1;
+ unsigned msg_type:3;
+ unsigned send_commit_msg:1;
+ unsigned response_length:4;
+ unsigned msg_length:4;
+ unsigned msg_target:4;
+ unsigned pad1:3;
+ unsigned end_of_thread:1;
+ } dp_write;
+
+ struct {
+ unsigned pad:16;
+ unsigned response_length:4;
+ unsigned msg_length:4;
+ unsigned msg_target:4;
+ unsigned pad1:3;
+ unsigned end_of_thread:1;
+ } generic;
+
+ int d;
+ unsigned ud;
+ } bits3;
+};
+
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_surface.c b/src/gallium/drivers/i965simple/brw_surface.c
new file mode 100644
index 0000000000..724a69b2ee
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_surface.c
@@ -0,0 +1,126 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "brw_blit.h"
+#include "brw_context.h"
+#include "brw_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_tile.h"
+#include "util/u_rect.h"
+
+
+
+/* Assumes all values are within bounds -- no checking at this level -
+ * do it higher up if required.
+ */
+static void
+brw_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ struct pipe_surface *src,
+ unsigned srcx, unsigned srcy, unsigned width, unsigned height)
+{
+ assert( dst != src );
+ assert( dst->block.size == src->block.size );
+ assert( dst->block.width == src->block.height );
+ assert( dst->block.height == src->block.height );
+
+ if (0) {
+ void *dst_map = pipe->screen->surface_map( pipe->screen,
+ dst,
+ PIPE_BUFFER_USAGE_CPU_WRITE );
+
+ const void *src_map = pipe->screen->surface_map( pipe->screen,
+ src,
+ PIPE_BUFFER_USAGE_CPU_READ );
+
+ util_copy_rect(dst_map,
+ &dst->block,
+ dst->stride,
+ dstx, dsty,
+ width, height,
+ src_map,
+ src->stride,
+ srcx, srcy);
+
+ pipe->screen->surface_unmap(pipe->screen, src);
+ pipe->screen->surface_unmap(pipe->screen, dst);
+ }
+ else {
+ struct brw_texture *dst_tex = (struct brw_texture *)dst->texture;
+ struct brw_texture *src_tex = (struct brw_texture *)src->texture;
+ assert(dst->block.width == 1);
+ assert(dst->block.height == 1);
+ brw_copy_blit(brw_context(pipe),
+ FALSE,
+ dst->block.size,
+ (short) src->stride/src->block.size, src_tex->buffer, src->offset, FALSE,
+ (short) dst->stride/dst->block.size, dst_tex->buffer, dst->offset, FALSE,
+ (short) srcx, (short) srcy, (short) dstx, (short) dsty,
+ (short) width, (short) height, PIPE_LOGICOP_COPY);
+ }
+}
+
+
+static void
+brw_surface_fill(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height, unsigned value)
+{
+ if (0) {
+ void *dst_map = pipe->screen->surface_map( pipe->screen,
+ dst,
+ PIPE_BUFFER_USAGE_CPU_WRITE );
+
+ util_fill_rect(dst_map, &dst->block, dst->stride, dstx, dsty, width, height, value);
+
+ pipe->screen->surface_unmap(pipe->screen, dst);
+ }
+ else {
+ struct brw_texture *tex = (struct brw_texture *)dst->texture;
+ assert(dst->block.width == 1);
+ assert(dst->block.height == 1);
+ brw_fill_blit(brw_context(pipe),
+ dst->block.size,
+ (short) dst->stride/dst->block.size,
+ tex->buffer, dst->offset, FALSE,
+ (short) dstx, (short) dsty,
+ (short) width, (short) height,
+ value);
+ }
+}
+
+
+void
+brw_init_surface_functions(struct brw_context *brw)
+{
+ brw->pipe.surface_copy = brw_surface_copy;
+ brw->pipe.surface_fill = brw_surface_fill;
+}
diff --git a/src/gallium/drivers/i965simple/brw_tex_layout.c b/src/gallium/drivers/i965simple/brw_tex_layout.c
new file mode 100644
index 0000000000..998ffaeac4
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_tex_layout.c
@@ -0,0 +1,380 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+/* Code to layout images in a mipmap tree for i965.
+ */
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "brw_context.h"
+#include "brw_tex_layout.h"
+
+
+#define FILE_DEBUG_FLAG DEBUG_TEXTURE
+
+#if 0
+unsigned intel_compressed_alignment(unsigned internalFormat)
+{
+ unsigned alignment = 4;
+
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ alignment = 8;
+ break;
+
+ default:
+ break;
+ }
+
+ return alignment;
+}
+#endif
+
+
+static void intel_miptree_set_image_offset(struct brw_texture *tex,
+ unsigned level,
+ unsigned img,
+ unsigned x, unsigned y)
+{
+ struct pipe_texture *pt = &tex->base;
+ if (img == 0 && level == 0)
+ assert(x == 0 && y == 0);
+ assert(img < tex->nr_images[level]);
+
+ tex->image_offset[level][img] = y * tex->stride + x * pt->block.size;
+}
+
+static void intel_miptree_set_level_info(struct brw_texture *tex,
+ unsigned level,
+ unsigned nr_images,
+ unsigned x, unsigned y,
+ unsigned w, unsigned h, unsigned d)
+{
+ struct pipe_texture *pt = &tex->base;
+
+ assert(level < PIPE_MAX_TEXTURE_LEVELS);
+
+ pt->width[level] = w;
+ pt->height[level] = h;
+ pt->depth[level] = d;
+
+ pt->nblocksx[level] = pf_get_nblocksx(&pt->block, w);
+ pt->nblocksy[level] = pf_get_nblocksy(&pt->block, h);
+
+ tex->level_offset[level] = y * tex->stride + x * tex->base.block.size;
+ tex->nr_images[level] = nr_images;
+
+ /*
+ DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
+ level, w, h, d, x, y, tex->level_offset[level]);
+ */
+
+ /* Not sure when this would happen, but anyway:
+ */
+ if (tex->image_offset[level]) {
+ FREE(tex->image_offset[level]);
+ tex->image_offset[level] = NULL;
+ }
+
+ assert(nr_images);
+ assert(!tex->image_offset[level]);
+
+ tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
+ tex->image_offset[level][0] = 0;
+}
+
+static void i945_miptree_layout_2d(struct brw_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+ const int align_x = 2, align_y = 4;
+ unsigned level;
+ unsigned x = 0;
+ unsigned y = 0;
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+ unsigned nblocksx = pt->nblocksx[0];
+ unsigned nblocksy = pt->nblocksy[0];
+
+ tex->stride = align(pt->nblocksx[0] * pt->block.size, 4);
+
+ /* May need to adjust pitch to accomodate the placement of
+ * the 2nd mipmap level. This occurs when the alignment
+ * constraints of mipmap placement push the right edge of the
+ * 2nd mipmap level out past the width of its parent.
+ */
+ if (pt->last_level > 0) {
+ unsigned mip1_nblocksx
+ = align(pf_get_nblocksx(&pt->block, minify(width)), align_x)
+ + pf_get_nblocksx(&pt->block, minify(minify(width)));
+
+ if (mip1_nblocksx > nblocksx)
+ tex->stride = mip1_nblocksx * pt->block.size;
+ }
+
+ /* Pitch must be a whole number of dwords
+ */
+ tex->stride = align(tex->stride, 64);
+ tex->total_nblocksy = 0;
+
+ for (level = 0; level <= pt->last_level; level++) {
+ intel_miptree_set_level_info(tex, level, 1, x, y, width,
+ height, 1);
+
+ nblocksy = align(nblocksy, align_y);
+
+ /* Because the images are packed better, the final offset
+ * might not be the maximal one:
+ */
+ tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy);
+
+ /* Layout_below: step right after second mipmap level.
+ */
+ if (level == 1) {
+ x += align(nblocksx, align_x);
+ }
+ else {
+ y += nblocksy;
+ }
+
+ width = minify(width);
+ height = minify(height);
+ nblocksx = pf_get_nblocksx(&pt->block, width);
+ nblocksy = pf_get_nblocksy(&pt->block, height);
+ }
+}
+
+static boolean brw_miptree_layout(struct brw_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+ /* XXX: these vary depending on image format:
+ */
+/* int align_w = 4; */
+
+ switch (pt->target) {
+ case PIPE_TEXTURE_CUBE:
+ case PIPE_TEXTURE_3D: {
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+ unsigned depth = pt->depth[0];
+ unsigned nblocksx = pt->nblocksx[0];
+ unsigned nblocksy = pt->nblocksy[0];
+ unsigned pack_x_pitch, pack_x_nr;
+ unsigned pack_y_pitch;
+ unsigned level;
+ unsigned align_h = 2;
+ unsigned align_w = 4;
+
+ tex->total_nblocksy = 0;
+
+ tex->stride = align(pt->nblocksx[0], 4);
+ pack_y_pitch = align(pt->nblocksy[0], align_h);
+
+ pack_x_pitch = tex->stride / pt->block.size;
+ pack_x_nr = 1;
+
+ for (level = 0; level <= pt->last_level; level++) {
+ unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
+ int x = 0;
+ int y = 0;
+ uint q, j;
+
+ intel_miptree_set_level_info(tex, level, nr_images,
+ 0, tex->total_nblocksy,
+ width, height, depth);
+
+ for (q = 0; q < nr_images;) {
+ for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
+ intel_miptree_set_image_offset(tex, level, q, x, y);
+ x += pack_x_pitch;
+ }
+
+ x = 0;
+ y += pack_y_pitch;
+ }
+
+
+ tex->total_nblocksy += y;
+ width = minify(width);
+ height = minify(height);
+ depth = minify(depth);
+ nblocksx = pf_get_nblocksx(&pt->block, width);
+ nblocksy = pf_get_nblocksy(&pt->block, height);
+
+ if (pf_is_compressed(pt->format)) {
+ pack_y_pitch = (height + 3) / 4;
+
+ if (pack_x_pitch > align(width, align_w)) {
+ pack_x_pitch = align(width, align_w);
+ pack_x_nr <<= 1;
+ }
+ } else {
+ if (pack_x_pitch > 4) {
+ pack_x_pitch >>= 1;
+ pack_x_nr <<= 1;
+ assert(pack_x_pitch * pack_x_nr * pt->block.size <= tex->stride);
+ }
+
+ if (pack_y_pitch > 2) {
+ pack_y_pitch >>= 1;
+ pack_y_pitch = align(pack_y_pitch, align_h);
+ }
+ }
+
+ }
+ break;
+ }
+
+ default:
+ i945_miptree_layout_2d(tex);
+ break;
+ }
+#if 0
+ PRINT("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
+ pt->pitch,
+ pt->total_nblocksy,
+ pt->block.size,
+ pt->stride * pt->total_nblocksy );
+#endif
+
+ return TRUE;
+}
+
+
+static struct pipe_texture *
+brw_texture_create_screen(struct pipe_screen *screen,
+ const struct pipe_texture *templat)
+{
+ struct brw_texture *tex = CALLOC_STRUCT(brw_texture);
+
+ if (tex) {
+ tex->base = *templat;
+ pipe_reference_init(&tex->base.reference, 1);
+
+ tex->base.nblocksx[0] = pf_get_nblocksx(&tex->base.block, tex->base.width[0]);
+ tex->base.nblocksy[0] = pf_get_nblocksy(&tex->base.block, tex->base.height[0]);
+
+ if (brw_miptree_layout(tex))
+ tex->buffer = screen->buffer_create(screen, 64,
+ PIPE_BUFFER_USAGE_PIXEL,
+ tex->stride *
+ tex->total_nblocksy);
+
+ if (!tex->buffer) {
+ FREE(tex);
+ return NULL;
+ }
+ }
+
+ return &tex->base;
+}
+
+
+static void
+brw_texture_destroy_screen(struct pipe_texture *pt)
+{
+ struct brw_texture *tex = (struct brw_texture *)pt;
+ uint i;
+
+ /*
+ DBG("%s deleting %p\n", __FUNCTION__, (void *) tex);
+ */
+
+ pipe_buffer_reference(&tex->buffer, NULL);
+
+ for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
+ if (tex->image_offset[i])
+ free(tex->image_offset[i]);
+
+ free(tex);
+}
+
+
+static struct pipe_surface *
+brw_get_tex_surface_screen(struct pipe_screen *screen,
+ struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice)
+{
+ struct brw_texture *tex = (struct brw_texture *)pt;
+ struct pipe_surface *ps;
+ unsigned offset; /* in bytes */
+
+ offset = tex->level_offset[level];
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ offset += tex->image_offset[level][face];
+ }
+ else if (pt->target == PIPE_TEXTURE_3D) {
+ offset += tex->image_offset[level][zslice];
+ }
+ else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+
+ ps = CALLOC_STRUCT(pipe_surface);
+ if (ps) {
+ pipe_reference_init(&ps->reference, 1);
+ pipe_texture_reference(&ps->texture, pt);
+ ps->format = pt->format;
+ ps->width = pt->width[level];
+ ps->height = pt->height[level];
+ ps->block = pt->block;
+ ps->nblocksx = pt->nblocksx[level];
+ ps->nblocksy = pt->nblocksy[level];
+ ps->stride = tex->stride;
+ ps->offset = offset;
+ }
+ return ps;
+}
+
+
+void
+brw_init_texture_functions(struct brw_context *brw)
+{
+// brw->pipe.texture_update = brw_texture_update;
+}
+
+
+void
+brw_init_screen_texture_funcs(struct pipe_screen *screen)
+{
+ screen->texture_create = brw_texture_create_screen;
+ screen->texture_destroy = brw_texture_destroy_screen;
+ screen->get_tex_surface = brw_get_tex_surface_screen;
+}
+
diff --git a/src/gallium/drivers/i965simple/brw_tex_layout.h b/src/gallium/drivers/i965simple/brw_tex_layout.h
new file mode 100644
index 0000000000..a6b6ba8146
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_tex_layout.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+
+
+#ifndef BRW_TEX_LAYOUT_H
+#define BRW_TEX_LAYOUT_H
+
+
+struct brw_context;
+struct pipe_screen;
+
+
+extern void
+brw_init_texture_functions(struct brw_context *brw);
+
+extern void
+brw_init_screen_texture_funcs(struct pipe_screen *screen);
+
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_urb.c b/src/gallium/drivers/i965simple/brw_urb.c
new file mode 100644
index 0000000000..101a4367b9
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_urb.c
@@ -0,0 +1,186 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+//#include "brw_state.h"
+#include "brw_batch.h"
+#include "brw_defines.h"
+
+#define VS 0
+#define GS 1
+#define CLP 2
+#define SF 3
+#define CS 4
+
+/* XXX: Are the min_entry_size numbers useful?
+ * XXX: Verify min_nr_entries, esp for VS.
+ * XXX: Verify SF min_entry_size.
+ */
+static const struct {
+ unsigned min_nr_entries;
+ unsigned preferred_nr_entries;
+ unsigned min_entry_size;
+ unsigned max_entry_size;
+} limits[CS+1] = {
+ { 8, 32, 1, 5 }, /* vs */
+ { 4, 8, 1, 5 }, /* gs */
+ { 6, 8, 1, 5 }, /* clp */
+ { 1, 8, 1, 12 }, /* sf */
+ { 1, 4, 1, 32 } /* cs */
+};
+
+
+static boolean check_urb_layout( struct brw_context *brw )
+{
+ brw->urb.vs_start = 0;
+ brw->urb.gs_start = brw->urb.nr_vs_entries * brw->urb.vsize;
+ brw->urb.clip_start = brw->urb.gs_start + brw->urb.nr_gs_entries * brw->urb.vsize;
+ brw->urb.sf_start = brw->urb.clip_start + brw->urb.nr_clip_entries * brw->urb.vsize;
+ brw->urb.cs_start = brw->urb.sf_start + brw->urb.nr_sf_entries * brw->urb.sfsize;
+
+ return brw->urb.cs_start + brw->urb.nr_cs_entries * brw->urb.csize <= 256;
+}
+
+/* Most minimal update, forces re-emit of URB fence packet after GS
+ * unit turned on/off.
+ */
+static void recalculate_urb_fence( struct brw_context *brw )
+{
+ unsigned csize = brw->curbe.total_size;
+ unsigned vsize = brw->vs.prog_data->urb_entry_size;
+ unsigned sfsize = brw->sf.prog_data->urb_entry_size;
+
+ if (csize < limits[CS].min_entry_size)
+ csize = limits[CS].min_entry_size;
+
+ if (vsize < limits[VS].min_entry_size)
+ vsize = limits[VS].min_entry_size;
+
+ if (sfsize < limits[SF].min_entry_size)
+ sfsize = limits[SF].min_entry_size;
+
+ if (brw->urb.vsize < vsize ||
+ brw->urb.sfsize < sfsize ||
+ brw->urb.csize < csize ||
+ (brw->urb.constrained && (brw->urb.vsize > brw->urb.vsize ||
+ brw->urb.sfsize > brw->urb.sfsize ||
+ brw->urb.csize > brw->urb.csize))) {
+
+
+ brw->urb.csize = csize;
+ brw->urb.sfsize = sfsize;
+ brw->urb.vsize = vsize;
+
+ brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
+ brw->urb.nr_gs_entries = limits[GS].preferred_nr_entries;
+ brw->urb.nr_clip_entries = limits[CLP].preferred_nr_entries;
+ brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;
+ brw->urb.nr_cs_entries = limits[CS].preferred_nr_entries;
+
+ if (!check_urb_layout(brw)) {
+ brw->urb.nr_vs_entries = limits[VS].min_nr_entries;
+ brw->urb.nr_gs_entries = limits[GS].min_nr_entries;
+ brw->urb.nr_clip_entries = limits[CLP].min_nr_entries;
+ brw->urb.nr_sf_entries = limits[SF].min_nr_entries;
+ brw->urb.nr_cs_entries = limits[CS].min_nr_entries;
+
+ brw->urb.constrained = 1;
+
+ if (!check_urb_layout(brw)) {
+ /* This is impossible, given the maximal sizes of urb
+ * entries and the values for minimum nr of entries
+ * provided above.
+ */
+ debug_printf("couldn't calculate URB layout!\n");
+ exit(1);
+ }
+
+ if (BRW_DEBUG & (DEBUG_URB|DEBUG_FALLBACKS))
+ debug_printf("URB CONSTRAINED\n");
+ }
+ else
+ brw->urb.constrained = 0;
+
+ if (BRW_DEBUG & DEBUG_URB)
+ debug_printf("URB fence: %d ..VS.. %d ..GS.. %d ..CLP.. %d ..SF.. %d ..CS.. %d\n",
+ brw->urb.vs_start,
+ brw->urb.gs_start,
+ brw->urb.clip_start,
+ brw->urb.sf_start,
+ brw->urb.cs_start,
+ 256);
+
+ brw->state.dirty.brw |= BRW_NEW_URB_FENCE;
+ }
+}
+
+
+const struct brw_tracked_state brw_recalculate_urb_fence = {
+ .dirty = {
+ .brw = BRW_NEW_CURBE_OFFSETS,
+ .cache = (CACHE_NEW_VS_PROG |
+ CACHE_NEW_SF_PROG)
+ },
+ .update = recalculate_urb_fence
+};
+
+
+
+
+
+void brw_upload_urb_fence(struct brw_context *brw)
+{
+ struct brw_urb_fence uf;
+ memset(&uf, 0, sizeof(uf));
+
+ uf.header.opcode = CMD_URB_FENCE;
+ uf.header.length = sizeof(uf)/4-2;
+ uf.header.vs_realloc = 1;
+ uf.header.gs_realloc = 1;
+ uf.header.clp_realloc = 1;
+ uf.header.sf_realloc = 1;
+ uf.header.vfe_realloc = 1;
+ uf.header.cs_realloc = 1;
+
+ /* The ordering below is correct, not the layout in the
+ * instruction.
+ *
+ * There are 256 urb reg pairs in total.
+ */
+ uf.bits0.vs_fence = brw->urb.gs_start;
+ uf.bits0.gs_fence = brw->urb.clip_start;
+ uf.bits0.clp_fence = brw->urb.sf_start;
+ uf.bits1.sf_fence = brw->urb.cs_start;
+ uf.bits1.cs_fence = 256;
+
+ BRW_BATCH_STRUCT(brw, &uf);
+}
diff --git a/src/gallium/drivers/i965simple/brw_util.c b/src/gallium/drivers/i965simple/brw_util.c
new file mode 100644
index 0000000000..42391d7c8c
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_util.c
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_util.h"
+#include "brw_defines.h"
+
+#include "pipe/p_defines.h"
+
+unsigned brw_count_bits( unsigned val )
+{
+ unsigned i;
+ for (i = 0; val ; val >>= 1)
+ if (val & 1)
+ i++;
+ return i;
+}
+
+
+unsigned brw_translate_blend_equation( int mode )
+{
+ switch (mode) {
+ case PIPE_BLEND_ADD:
+ return BRW_BLENDFUNCTION_ADD;
+ case PIPE_BLEND_MIN:
+ return BRW_BLENDFUNCTION_MIN;
+ case PIPE_BLEND_MAX:
+ return BRW_BLENDFUNCTION_MAX;
+ case PIPE_BLEND_SUBTRACT:
+ return BRW_BLENDFUNCTION_SUBTRACT;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ return BRW_BLENDFUNCTION_REVERSE_SUBTRACT;
+ default:
+ assert(0);
+ return BRW_BLENDFUNCTION_ADD;
+ }
+}
+
+unsigned brw_translate_blend_factor( int factor )
+{
+ switch(factor) {
+ case PIPE_BLENDFACTOR_ZERO:
+ return BRW_BLENDFACTOR_ZERO;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ return BRW_BLENDFACTOR_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_ONE:
+ return BRW_BLENDFACTOR_ONE;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ return BRW_BLENDFACTOR_SRC_COLOR;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ return BRW_BLENDFACTOR_INV_SRC_COLOR;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ return BRW_BLENDFACTOR_DST_COLOR;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ return BRW_BLENDFACTOR_INV_DST_COLOR;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ return BRW_BLENDFACTOR_INV_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ return BRW_BLENDFACTOR_DST_ALPHA;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ return BRW_BLENDFACTOR_INV_DST_ALPHA;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ return BRW_BLENDFACTOR_SRC_ALPHA_SATURATE;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ return BRW_BLENDFACTOR_CONST_COLOR;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ return BRW_BLENDFACTOR_INV_CONST_COLOR;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ return BRW_BLENDFACTOR_CONST_ALPHA;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ return BRW_BLENDFACTOR_INV_CONST_ALPHA;
+ default:
+ assert(0);
+ return BRW_BLENDFACTOR_ZERO;
+ }
+}
diff --git a/src/gallium/drivers/i965simple/brw_util.h b/src/gallium/drivers/i965simple/brw_util.h
new file mode 100644
index 0000000000..d60e5934db
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_util.h
@@ -0,0 +1,43 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRW_UTIL_H
+#define BRW_UTIL_H
+
+#include "pipe/p_state.h"
+
+extern unsigned brw_count_bits( unsigned val );
+extern unsigned brw_translate_blend_factor( int factor );
+extern unsigned brw_translate_blend_equation( int mode );
+
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_vs.c b/src/gallium/drivers/i965simple/brw_vs.c
new file mode 100644
index 0000000000..92327e896d
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_vs.c
@@ -0,0 +1,120 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_vs.h"
+#include "brw_util.h"
+#include "brw_state.h"
+
+
+static void do_vs_prog( struct brw_context *brw,
+ const struct brw_vertex_program *vp,
+ struct brw_vs_prog_key *key )
+{
+ unsigned program_size;
+ const unsigned *program;
+ struct brw_vs_compile c;
+
+ memset(&c, 0, sizeof(c));
+ memcpy(&c.key, key, sizeof(*key));
+
+ brw_init_compile(&c.func);
+ c.vp = vp;
+
+ c.prog_data.outputs_written = vp->info.num_outputs;
+ c.prog_data.inputs_read = vp->info.num_inputs;
+
+#if 0
+ if (c.key.copy_edgeflag) {
+ c.prog_data.outputs_written |= 1<<VERT_RESULT_EDGE;
+ c.prog_data.inputs_read |= 1<<VERT_ATTRIB_EDGEFLAG;
+ }
+#endif
+
+ /* Emit GEN4 code.
+ */
+ brw_vs_emit(&c);
+
+ /* get the program
+ */
+ program = brw_get_program(&c.func, &program_size);
+
+ /*
+ */
+ brw->vs.prog_gs_offset = brw_upload_cache( &brw->cache[BRW_VS_PROG],
+ &c.key,
+ sizeof(c.key),
+ program,
+ program_size,
+ &c.prog_data,
+ &brw->vs.prog_data);
+}
+
+
+static void brw_upload_vs_prog( struct brw_context *brw )
+{
+ struct brw_vs_prog_key key;
+ const struct brw_vertex_program *vp = brw->attribs.VertexProgram;
+
+ assert(vp);
+
+ memset(&key, 0, sizeof(key));
+
+ /* Just upload the program verbatim for now. Always send it all
+ * the inputs it asks for, whether they are varying or not.
+ */
+ key.program_string_id = vp->id;
+ key.nr_userclip = brw->attribs.Clip.nr;
+ key.copy_edgeflag = (brw->attribs.Raster->fill_cw != PIPE_POLYGON_MODE_FILL ||
+ brw->attribs.Raster->fill_ccw != PIPE_POLYGON_MODE_FILL);
+
+ /* Make an early check for the key.
+ */
+ if (brw_search_cache(&brw->cache[BRW_VS_PROG],
+ &key, sizeof(key),
+ &brw->vs.prog_data,
+ &brw->vs.prog_gs_offset))
+ return;
+
+ do_vs_prog(brw, vp, &key);
+}
+
+
+/* See brw_vs.c:
+ */
+const struct brw_tracked_state brw_vs_prog = {
+ .dirty = {
+ .brw = BRW_NEW_VS,
+ .cache = 0
+ },
+ .update = brw_upload_vs_prog
+};
diff --git a/src/gallium/drivers/i965simple/brw_vs.h b/src/gallium/drivers/i965simple/brw_vs.h
new file mode 100644
index 0000000000..070f9dfcae
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_vs.h
@@ -0,0 +1,82 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRW_VS_H
+#define BRW_VS_H
+
+
+#include "brw_context.h"
+#include "brw_eu.h"
+
+
+struct brw_vs_prog_key {
+ unsigned program_string_id;
+ unsigned nr_userclip:4;
+ unsigned copy_edgeflag:1;
+ unsigned know_w_is_one:1;
+ unsigned pad:26;
+};
+
+
+struct brw_vs_compile {
+ struct brw_compile func;
+ struct brw_vs_prog_key key;
+ struct brw_vs_prog_data prog_data;
+
+ const struct brw_vertex_program *vp;
+
+ unsigned nr_inputs;
+
+ unsigned first_output;
+ unsigned nr_outputs;
+
+ unsigned first_tmp;
+ unsigned last_tmp;
+
+ struct brw_reg r0;
+ struct brw_reg r1;
+ struct brw_reg regs[12][128];
+ struct brw_reg tmp;
+ struct brw_reg stack;
+
+ struct {
+ boolean used_in_src;
+ struct brw_reg reg;
+ } output_regs[128];
+
+ struct brw_reg userplane[6];
+
+};
+
+void brw_vs_emit( struct brw_vs_compile *c );
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_vs_emit.c b/src/gallium/drivers/i965simple/brw_vs_emit.c
new file mode 100644
index 0000000000..3ee82d95b3
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_vs_emit.c
@@ -0,0 +1,1330 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_context.h"
+#include "brw_vs.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+
+struct brw_prog_info {
+ unsigned num_temps;
+ unsigned num_addrs;
+ unsigned num_consts;
+
+ unsigned writes_psize;
+
+ unsigned pos_idx;
+ unsigned result_edge_idx;
+ unsigned edge_flag_idx;
+ unsigned psize_idx;
+};
+
+/* Do things as simply as possible. Allocate and populate all regs
+ * ahead of time.
+ */
+static void brw_vs_alloc_regs( struct brw_vs_compile *c,
+ struct brw_prog_info *info )
+{
+ unsigned i, reg = 0, mrf;
+ unsigned nr_params;
+
+ /* r0 -- reserved as usual
+ */
+ c->r0 = brw_vec8_grf(reg, 0); reg++;
+
+ /* User clip planes from curbe:
+ */
+ if (c->key.nr_userclip) {
+ for (i = 0; i < c->key.nr_userclip; i++) {
+ c->userplane[i] = stride( brw_vec4_grf(reg+3+i/2, (i%2) * 4), 0, 4, 1);
+ }
+
+ /* Deal with curbe alignment:
+ */
+ reg += ((6+c->key.nr_userclip+3)/4)*2;
+ }
+
+ /* Vertex program parameters from curbe:
+ */
+ nr_params = c->prog_data.max_const;
+ for (i = 0; i < nr_params; i++) {
+ c->regs[TGSI_FILE_CONSTANT][i] = stride(brw_vec4_grf(reg+i/2, (i%2) * 4), 0, 4, 1);
+ }
+ reg += (nr_params+1)/2;
+ c->prog_data.curb_read_length = reg - 1;
+
+
+
+ /* Allocate input regs:
+ */
+ c->nr_inputs = c->vp->info.num_inputs;
+ for (i = 0; i < c->nr_inputs; i++) {
+ c->regs[TGSI_FILE_INPUT][i] = brw_vec8_grf(reg, 0);
+ reg++;
+ }
+
+
+ /* Allocate outputs: TODO: could organize the non-position outputs
+ * to go straight into message regs.
+ */
+ c->nr_outputs = 0;
+ c->first_output = reg;
+ mrf = 4;
+ for (i = 0; i < c->vp->info.num_outputs; i++) {
+ c->nr_outputs++;
+#if 0
+ if (i == VERT_RESULT_HPOS) {
+ c->regs[TGSI_FILE_OUTPUT][i] = brw_vec8_grf(reg, 0);
+ reg++;
+ }
+ else if (i == VERT_RESULT_PSIZ) {
+ c->regs[TGSI_FILE_OUTPUT][i] = brw_vec8_grf(reg, 0);
+ reg++;
+ mrf++; /* just a placeholder? XXX fix later stages & remove this */
+ }
+ else {
+ c->regs[TGSI_FILE_OUTPUT][i] = brw_message_reg(mrf);
+ mrf++;
+ }
+#else
+ /*treat pos differently for now */
+ if (i == info->pos_idx) {
+ c->regs[TGSI_FILE_OUTPUT][i] = brw_vec8_grf(reg, 0);
+ reg++;
+ } else {
+ c->regs[TGSI_FILE_OUTPUT][i] = brw_message_reg(mrf);
+ mrf++;
+ }
+#endif
+ }
+
+ /* Allocate program temporaries:
+ */
+ for (i = 0; i < info->num_temps; i++) {
+ c->regs[TGSI_FILE_TEMPORARY][i] = brw_vec8_grf(reg, 0);
+ reg++;
+ }
+
+ /* Address reg(s). Don't try to use the internal address reg until
+ * deref time.
+ */
+ for (i = 0; i < info->num_addrs; i++) {
+ c->regs[TGSI_FILE_ADDRESS][i] = brw_reg(BRW_GENERAL_REGISTER_FILE,
+ reg,
+ 0,
+ BRW_REGISTER_TYPE_D,
+ BRW_VERTICAL_STRIDE_8,
+ BRW_WIDTH_8,
+ BRW_HORIZONTAL_STRIDE_1,
+ BRW_SWIZZLE_XXXX,
+ TGSI_WRITEMASK_X);
+ reg++;
+ }
+
+ for (i = 0; i < 128; i++) {
+ if (c->output_regs[i].used_in_src) {
+ c->output_regs[i].reg = brw_vec8_grf(reg, 0);
+ reg++;
+ }
+ }
+
+ c->stack = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, reg, 0);
+ reg += 2;
+
+
+ /* Some opcodes need an internal temporary:
+ */
+ c->first_tmp = reg;
+ c->last_tmp = reg; /* for allocation purposes */
+
+ /* Each input reg holds data from two vertices. The
+ * urb_read_length is the number of registers read from *each*
+ * vertex urb, so is half the amount:
+ */
+ c->prog_data.urb_read_length = (c->nr_inputs+1)/2;
+
+ c->prog_data.urb_entry_size = (c->nr_outputs+2+3)/4;
+ c->prog_data.total_grf = reg;
+}
+
+
+static struct brw_reg get_tmp( struct brw_vs_compile *c )
+{
+ struct brw_reg tmp = brw_vec8_grf(c->last_tmp, 0);
+
+ if (++c->last_tmp > c->prog_data.total_grf)
+ c->prog_data.total_grf = c->last_tmp;
+
+ return tmp;
+}
+
+static void release_tmp( struct brw_vs_compile *c, struct brw_reg tmp )
+{
+ if (tmp.nr == c->last_tmp-1)
+ c->last_tmp--;
+}
+
+static void release_tmps( struct brw_vs_compile *c )
+{
+ c->last_tmp = c->first_tmp;
+}
+
+
+static void unalias1( struct brw_vs_compile *c,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ void (*func)( struct brw_vs_compile *,
+ struct brw_reg,
+ struct brw_reg ))
+{
+ if (dst.file == arg0.file && dst.nr == arg0.nr) {
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp = brw_writemask(get_tmp(c), dst.dw1.bits.writemask);
+ func(c, tmp, arg0);
+ brw_MOV(p, dst, tmp);
+ }
+ else {
+ func(c, dst, arg0);
+ }
+}
+
+static void unalias2( struct brw_vs_compile *c,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1,
+ void (*func)( struct brw_vs_compile *,
+ struct brw_reg,
+ struct brw_reg,
+ struct brw_reg ))
+{
+ if ((dst.file == arg0.file && dst.nr == arg0.nr) ||
+ (dst.file == arg1.file && dst.nr == arg1.nr)) {
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp = brw_writemask(get_tmp(c), dst.dw1.bits.writemask);
+ func(c, tmp, arg0, arg1);
+ brw_MOV(p, dst, tmp);
+ }
+ else {
+ func(c, dst, arg0, arg1);
+ }
+}
+
+static void emit_sop( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1,
+ unsigned cond)
+{
+ brw_push_insn_state(p);
+ brw_CMP(p, brw_null_reg(), cond, arg0, arg1);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_MOV(p, dst, brw_imm_f(1.0f));
+ brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+ brw_MOV(p, dst, brw_imm_f(0.0f));
+ brw_pop_insn_state(p);
+}
+
+static void emit_seq( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1 )
+{
+ emit_sop(p, dst, arg0, arg1, BRW_CONDITIONAL_EQ);
+}
+
+static void emit_sne( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1 )
+{
+ emit_sop(p, dst, arg0, arg1, BRW_CONDITIONAL_NEQ);
+}
+static void emit_slt( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1 )
+{
+ emit_sop(p, dst, arg0, arg1, BRW_CONDITIONAL_L);
+}
+
+static void emit_sle( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1 )
+{
+ emit_sop(p, dst, arg0, arg1, BRW_CONDITIONAL_LE);
+}
+
+static void emit_sgt( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1 )
+{
+ emit_sop(p, dst, arg0, arg1, BRW_CONDITIONAL_G);
+}
+
+static void emit_sge( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1 )
+{
+ emit_sop(p, dst, arg0, arg1, BRW_CONDITIONAL_GE);
+}
+
+static void emit_max( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1 )
+{
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0, arg1);
+ brw_SEL(p, dst, arg1, arg0);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+}
+
+static void emit_min( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1 )
+{
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0, arg1);
+ brw_SEL(p, dst, arg0, arg1);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+}
+
+
+static void emit_math1( struct brw_vs_compile *c,
+ unsigned function,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ unsigned precision)
+{
+ /* There are various odd behaviours with SEND on the simulator. In
+ * addition there are documented issues with the fact that the GEN4
+ * processor doesn't do dependency control properly on SEND
+ * results. So, on balance, this kludge to get around failures
+ * with writemasked math results looks like it might be necessary
+ * whether that turns out to be a simulator bug or not:
+ */
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp = dst;
+ boolean need_tmp = (dst.dw1.bits.writemask != 0xf ||
+ dst.file != BRW_GENERAL_REGISTER_FILE);
+
+ if (need_tmp)
+ tmp = get_tmp(c);
+
+ brw_math(p,
+ tmp,
+ function,
+ BRW_MATH_SATURATE_NONE,
+ 2,
+ arg0,
+ BRW_MATH_DATA_SCALAR,
+ precision);
+
+ if (need_tmp) {
+ brw_MOV(p, dst, tmp);
+ release_tmp(c, tmp);
+ }
+}
+
+static void emit_math2( struct brw_vs_compile *c,
+ unsigned function,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1,
+ unsigned precision)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp = dst;
+ boolean need_tmp = (dst.dw1.bits.writemask != 0xf ||
+ dst.file != BRW_GENERAL_REGISTER_FILE);
+
+ if (need_tmp)
+ tmp = get_tmp(c);
+
+ brw_MOV(p, brw_message_reg(3), arg1);
+
+ brw_math(p,
+ tmp,
+ function,
+ BRW_MATH_SATURATE_NONE,
+ 2,
+ arg0,
+ BRW_MATH_DATA_SCALAR,
+ precision);
+
+ if (need_tmp) {
+ brw_MOV(p, dst, tmp);
+ release_tmp(c, tmp);
+ }
+}
+
+
+
+static void emit_exp_noalias( struct brw_vs_compile *c,
+ struct brw_reg dst,
+ struct brw_reg arg0 )
+{
+ struct brw_compile *p = &c->func;
+
+
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_X) {
+ struct brw_reg tmp = get_tmp(c);
+ struct brw_reg tmp_d = retype(tmp, BRW_REGISTER_TYPE_D);
+
+ /* tmp_d = floor(arg0.x) */
+ brw_RNDD(p, tmp_d, brw_swizzle1(arg0, 0));
+
+ /* result[0] = 2.0 ^ tmp */
+
+ /* Adjust exponent for floating point:
+ * exp += 127
+ */
+ brw_ADD(p, brw_writemask(tmp_d, TGSI_WRITEMASK_X), tmp_d, brw_imm_d(127));
+
+ /* Install exponent and sign.
+ * Excess drops off the edge:
+ */
+ brw_SHL(p, brw_writemask(retype(dst, BRW_REGISTER_TYPE_D), TGSI_WRITEMASK_X),
+ tmp_d, brw_imm_d(23));
+
+ release_tmp(c, tmp);
+ }
+
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_Y) {
+ /* result[1] = arg0.x - floor(arg0.x) */
+ brw_FRC(p, brw_writemask(dst, TGSI_WRITEMASK_Y), brw_swizzle1(arg0, 0));
+ }
+
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_Z) {
+ /* As with the LOG instruction, we might be better off just
+ * doing a taylor expansion here, seeing as we have to do all
+ * the prep work.
+ *
+ * If mathbox partial precision is too low, consider also:
+ * result[3] = result[0] * EXP(result[1])
+ */
+ emit_math1(c,
+ BRW_MATH_FUNCTION_EXP,
+ brw_writemask(dst, TGSI_WRITEMASK_Z),
+ brw_swizzle1(arg0, 0),
+ BRW_MATH_PRECISION_PARTIAL);
+ }
+
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_W) {
+ /* result[3] = 1.0; */
+ brw_MOV(p, brw_writemask(dst, TGSI_WRITEMASK_W), brw_imm_f(1));
+ }
+}
+
+
+static void emit_log_noalias( struct brw_vs_compile *c,
+ struct brw_reg dst,
+ struct brw_reg arg0 )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp = dst;
+ struct brw_reg tmp_ud = retype(tmp, BRW_REGISTER_TYPE_UD);
+ struct brw_reg arg0_ud = retype(arg0, BRW_REGISTER_TYPE_UD);
+ boolean need_tmp = (dst.dw1.bits.writemask != 0xf ||
+ dst.file != BRW_GENERAL_REGISTER_FILE);
+
+ if (need_tmp) {
+ tmp = get_tmp(c);
+ tmp_ud = retype(tmp, BRW_REGISTER_TYPE_UD);
+ }
+
+ /* Perform mant = frexpf(fabsf(x), &exp), adjust exp and mnt
+ * according to spec:
+ *
+ * These almost look likey they could be joined up, but not really
+ * practical:
+ *
+ * result[0].f = (x.i & ((1<<31)-1) >> 23) - 127
+ * result[1].i = (x.i & ((1<<23)-1) + (127<<23)
+ */
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_XZ) {
+ brw_AND(p,
+ brw_writemask(tmp_ud, TGSI_WRITEMASK_X),
+ brw_swizzle1(arg0_ud, 0),
+ brw_imm_ud((1U<<31)-1));
+
+ brw_SHR(p,
+ brw_writemask(tmp_ud, TGSI_WRITEMASK_X),
+ tmp_ud,
+ brw_imm_ud(23));
+
+ brw_ADD(p,
+ brw_writemask(tmp, TGSI_WRITEMASK_X),
+ retype(tmp_ud, BRW_REGISTER_TYPE_D), /* does it matter? */
+ brw_imm_d(-127));
+ }
+
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_YZ) {
+ brw_AND(p,
+ brw_writemask(tmp_ud, TGSI_WRITEMASK_Y),
+ brw_swizzle1(arg0_ud, 0),
+ brw_imm_ud((1<<23)-1));
+
+ brw_OR(p,
+ brw_writemask(tmp_ud, TGSI_WRITEMASK_Y),
+ tmp_ud,
+ brw_imm_ud(127<<23));
+ }
+
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_Z) {
+ /* result[2] = result[0] + LOG2(result[1]); */
+
+ /* Why bother? The above is just a hint how to do this with a
+ * taylor series. Maybe we *should* use a taylor series as by
+ * the time all the above has been done it's almost certainly
+ * quicker than calling the mathbox, even with low precision.
+ *
+ * Options are:
+ * - result[0] + mathbox.LOG2(result[1])
+ * - mathbox.LOG2(arg0.x)
+ * - result[0] + inline_taylor_approx(result[1])
+ */
+ emit_math1(c,
+ BRW_MATH_FUNCTION_LOG,
+ brw_writemask(tmp, TGSI_WRITEMASK_Z),
+ brw_swizzle1(tmp, 1),
+ BRW_MATH_PRECISION_FULL);
+
+ brw_ADD(p,
+ brw_writemask(tmp, TGSI_WRITEMASK_Z),
+ brw_swizzle1(tmp, 2),
+ brw_swizzle1(tmp, 0));
+ }
+
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_W) {
+ /* result[3] = 1.0; */
+ brw_MOV(p, brw_writemask(tmp, TGSI_WRITEMASK_W), brw_imm_f(1));
+ }
+
+ if (need_tmp) {
+ brw_MOV(p, dst, tmp);
+ release_tmp(c, tmp);
+ }
+}
+
+
+
+
+/* Need to unalias - consider swizzles: r0 = DST r0.xxxx r1
+ */
+static void emit_dst_noalias( struct brw_vs_compile *c,
+ struct brw_reg dst,
+ struct brw_reg arg0,
+ struct brw_reg arg1)
+{
+ struct brw_compile *p = &c->func;
+
+ /* There must be a better way to do this:
+ */
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_X)
+ brw_MOV(p, brw_writemask(dst, TGSI_WRITEMASK_X), brw_imm_f(1.0));
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_Y)
+ brw_MUL(p, brw_writemask(dst, TGSI_WRITEMASK_Y), arg0, arg1);
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_Z)
+ brw_MOV(p, brw_writemask(dst, TGSI_WRITEMASK_Z), arg0);
+ if (dst.dw1.bits.writemask & TGSI_WRITEMASK_W)
+ brw_MOV(p, brw_writemask(dst, TGSI_WRITEMASK_W), arg1);
+}
+
+static void emit_xpd( struct brw_compile *p,
+ struct brw_reg dst,
+ struct brw_reg t,
+ struct brw_reg u)
+{
+ brw_MUL(p, brw_null_reg(), brw_swizzle(t, 1,2,0,3), brw_swizzle(u,2,0,1,3));
+ brw_MAC(p, dst, negate(brw_swizzle(t, 2,0,1,3)), brw_swizzle(u,1,2,0,3));
+}
+
+
+
+static void emit_lit_noalias( struct brw_vs_compile *c,
+ struct brw_reg dst,
+ struct brw_reg arg0 )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *if_insn;
+ struct brw_reg tmp = dst;
+ boolean need_tmp = (dst.file != BRW_GENERAL_REGISTER_FILE);
+
+ if (need_tmp)
+ tmp = get_tmp(c);
+
+ brw_MOV(p, brw_writemask(dst, TGSI_WRITEMASK_YZ), brw_imm_f(0));
+ brw_MOV(p, brw_writemask(dst, TGSI_WRITEMASK_XW), brw_imm_f(1));
+
+ /* Need to use BRW_EXECUTE_8 and also do an 8-wide compare in order
+ * to get all channels active inside the IF. In the clipping code
+ * we run with NoMask, so it's not an option and we can use
+ * BRW_EXECUTE_1 for all comparisions.
+ */
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_G, brw_swizzle1(arg0,0), brw_imm_f(0));
+ if_insn = brw_IF(p, BRW_EXECUTE_8);
+ {
+ brw_MOV(p, brw_writemask(dst, TGSI_WRITEMASK_Y), brw_swizzle1(arg0,0));
+
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_G, brw_swizzle1(arg0,1), brw_imm_f(0));
+ brw_MOV(p, brw_writemask(tmp, TGSI_WRITEMASK_Z), brw_swizzle1(arg0,1));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ emit_math2(c,
+ BRW_MATH_FUNCTION_POW,
+ brw_writemask(dst, TGSI_WRITEMASK_Z),
+ brw_swizzle1(tmp, 2),
+ brw_swizzle1(arg0, 3),
+ BRW_MATH_PRECISION_PARTIAL);
+ }
+
+ brw_ENDIF(p, if_insn);
+}
+
+
+
+
+
+/* TODO: relative addressing!
+ */
+static struct brw_reg get_reg( struct brw_vs_compile *c,
+ unsigned file,
+ unsigned index )
+{
+ switch (file) {
+ case TGSI_FILE_TEMPORARY:
+ case TGSI_FILE_INPUT:
+ case TGSI_FILE_OUTPUT:
+ assert(c->regs[file][index].nr != 0);
+ return c->regs[file][index];
+ case TGSI_FILE_CONSTANT:
+ assert(c->regs[TGSI_FILE_CONSTANT][index + c->prog_data.num_imm].nr != 0);
+ return c->regs[TGSI_FILE_CONSTANT][index + c->prog_data.num_imm];
+ case TGSI_FILE_IMMEDIATE:
+ assert(c->regs[TGSI_FILE_CONSTANT][index].nr != 0);
+ return c->regs[TGSI_FILE_CONSTANT][index];
+ case TGSI_FILE_ADDRESS:
+ assert(index == 0);
+ return c->regs[file][index];
+
+ case TGSI_FILE_NULL: /* undef values */
+ return brw_null_reg();
+
+ default:
+ assert(0);
+ return brw_null_reg();
+ }
+}
+
+
+
+static struct brw_reg deref( struct brw_vs_compile *c,
+ struct brw_reg arg,
+ int offset)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp = vec4(get_tmp(c));
+ struct brw_reg vp_address = retype(vec1(get_reg(c, TGSI_FILE_ADDRESS, 0)), BRW_REGISTER_TYPE_UW);
+ unsigned byte_offset = arg.nr * 32 + arg.subnr + offset * 16;
+ struct brw_reg indirect = brw_vec4_indirect(0,0);
+
+ {
+ brw_push_insn_state(p);
+ brw_set_access_mode(p, BRW_ALIGN_1);
+
+ /* This is pretty clunky - load the address register twice and
+ * fetch each 4-dword value in turn. There must be a way to do
+ * this in a single pass, but I couldn't get it to work.
+ */
+ brw_ADD(p, brw_address_reg(0), vp_address, brw_imm_d(byte_offset));
+ brw_MOV(p, tmp, indirect);
+
+ brw_ADD(p, brw_address_reg(0), suboffset(vp_address, 8), brw_imm_d(byte_offset));
+ brw_MOV(p, suboffset(tmp, 4), indirect);
+
+ brw_pop_insn_state(p);
+ }
+
+ return vec8(tmp);
+}
+
+
+static void emit_arl( struct brw_vs_compile *c,
+ struct brw_reg dst,
+ struct brw_reg arg0 )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg tmp = dst;
+ boolean need_tmp = (dst.file != BRW_GENERAL_REGISTER_FILE);
+
+ if (need_tmp)
+ tmp = get_tmp(c);
+
+ brw_RNDD(p, tmp, arg0);
+ brw_MUL(p, dst, tmp, brw_imm_d(16));
+
+ if (need_tmp)
+ release_tmp(c, tmp);
+}
+
+
+/* Will return mangled results for SWZ op. The emit_swz() function
+ * ignores this result and recalculates taking extended swizzles into
+ * account.
+ */
+static struct brw_reg get_arg( struct brw_vs_compile *c,
+ struct tgsi_src_register *src )
+{
+ struct brw_reg reg;
+
+ if (src->File == TGSI_FILE_NULL)
+ return brw_null_reg();
+
+#if 0
+ if (src->RelAddr)
+ reg = deref(c, c->regs[PROGRAM_STATE_VAR][0], src->Index);
+ else
+#endif
+ reg = get_reg(c, src->File, src->Index);
+
+ /* Convert 3-bit swizzle to 2-bit.
+ */
+ reg.dw1.bits.swizzle = BRW_SWIZZLE4(src->SwizzleX,
+ src->SwizzleY,
+ src->SwizzleZ,
+ src->SwizzleW);
+
+ /* Note this is ok for non-swizzle instructions:
+ */
+ reg.negate = src->Negate ? 1 : 0;
+
+ return reg;
+}
+
+
+static struct brw_reg get_dst( struct brw_vs_compile *c,
+ const struct tgsi_dst_register *dst )
+{
+ struct brw_reg reg = get_reg(c, dst->File, dst->Index);
+
+ reg.dw1.bits.writemask = dst->WriteMask;
+
+ return reg;
+}
+
+
+
+
+static void emit_swz( struct brw_vs_compile *c,
+ struct brw_reg dst,
+ struct tgsi_src_register src )
+{
+ struct brw_compile *p = &c->func;
+ unsigned zeros_mask = 0;
+ unsigned ones_mask = 0;
+ unsigned src_mask = 0;
+ ubyte src_swz[4];
+ boolean need_tmp = (src.Negate &&
+ dst.file != BRW_GENERAL_REGISTER_FILE);
+ struct brw_reg tmp = dst;
+ unsigned i;
+
+ if (need_tmp)
+ tmp = get_tmp(c);
+
+ for (i = 0; i < 4; i++) {
+ if (dst.dw1.bits.writemask & (1<<i)) {
+ ubyte s = 0;
+ switch(i) {
+ case 0:
+ s = src.SwizzleX;
+ break;
+ s = src.SwizzleY;
+ case 1:
+ break;
+ s = src.SwizzleZ;
+ case 2:
+ break;
+ s = src.SwizzleW;
+ case 3:
+ break;
+ }
+ switch (s) {
+ case TGSI_SWIZZLE_X:
+ case TGSI_SWIZZLE_Y:
+ case TGSI_SWIZZLE_Z:
+ case TGSI_SWIZZLE_W:
+ src_mask |= 1<<i;
+ src_swz[i] = s;
+ break;
+ case TGSI_EXTSWIZZLE_ZERO:
+ zeros_mask |= 1<<i;
+ break;
+ case TGSI_EXTSWIZZLE_ONE:
+ ones_mask |= 1<<i;
+ break;
+ }
+ }
+ }
+
+ /* Do src first, in case dst aliases src:
+ */
+ if (src_mask) {
+ struct brw_reg arg0;
+
+#if 0
+ if (src.RelAddr)
+ arg0 = deref(c, c->regs[PROGRAM_STATE_VAR][0], src.Index);
+ else
+#endif
+ arg0 = get_reg(c, src.File, src.Index);
+
+ arg0 = brw_swizzle(arg0,
+ src_swz[0], src_swz[1],
+ src_swz[2], src_swz[3]);
+
+ brw_MOV(p, brw_writemask(tmp, src_mask), arg0);
+ }
+
+ if (zeros_mask)
+ brw_MOV(p, brw_writemask(tmp, zeros_mask), brw_imm_f(0));
+
+ if (ones_mask)
+ brw_MOV(p, brw_writemask(tmp, ones_mask), brw_imm_f(1));
+
+ if (src.Negate)
+ brw_MOV(p, brw_writemask(tmp, src.Negate), negate(tmp));
+
+ if (need_tmp) {
+ brw_MOV(p, dst, tmp);
+ release_tmp(c, tmp);
+ }
+}
+
+
+
+/* Post-vertex-program processing. Send the results to the URB.
+ */
+static void emit_vertex_write( struct brw_vs_compile *c, struct brw_prog_info *info)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg m0 = brw_message_reg(0);
+ struct brw_reg pos = c->regs[TGSI_FILE_OUTPUT][info->pos_idx];
+ struct brw_reg ndc;
+
+ if (c->key.copy_edgeflag) {
+ brw_MOV(p,
+ get_reg(c, TGSI_FILE_OUTPUT, info->result_edge_idx),
+ get_reg(c, TGSI_FILE_INPUT, info->edge_flag_idx));
+ }
+
+
+ /* Build ndc coords? TODO: Shortcircuit when w is known to be one.
+ */
+ if (!c->key.know_w_is_one) {
+ ndc = get_tmp(c);
+ emit_math1(c, BRW_MATH_FUNCTION_INV, ndc, brw_swizzle1(pos, 3), BRW_MATH_PRECISION_FULL);
+ brw_MUL(p, brw_writemask(ndc, TGSI_WRITEMASK_XYZ), pos, ndc);
+ }
+ else {
+ ndc = pos;
+ }
+
+ /* This includes the workaround for -ve rhw, so is no longer an
+ * optional step:
+ */
+ if (info->writes_psize ||
+ c->key.nr_userclip ||
+ !c->key.know_w_is_one)
+ {
+ struct brw_reg header1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
+ unsigned i;
+
+ brw_MOV(p, header1, brw_imm_ud(0));
+
+ brw_set_access_mode(p, BRW_ALIGN_16);
+
+ if (info->writes_psize) {
+ struct brw_reg psiz = c->regs[TGSI_FILE_OUTPUT][info->psize_idx];
+ brw_MUL(p, brw_writemask(header1, TGSI_WRITEMASK_W),
+ brw_swizzle1(psiz, 0), brw_imm_f(1<<11));
+ brw_AND(p, brw_writemask(header1, TGSI_WRITEMASK_W), header1,
+ brw_imm_ud(0x7ff<<8));
+ }
+
+
+ for (i = 0; i < c->key.nr_userclip; i++) {
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
+ brw_DP4(p, brw_null_reg(), pos, c->userplane[i]);
+ brw_OR(p, brw_writemask(header1, TGSI_WRITEMASK_W), header1, brw_imm_ud(1<<i));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ }
+
+
+ /* i965 clipping workaround:
+ * 1) Test for -ve rhw
+ * 2) If set,
+ * set ndc = (0,0,0,0)
+ * set ucp[6] = 1
+ *
+ * Later, clipping will detect ucp[6] and ensure the primitive is
+ * clipped against all fixed planes.
+ */
+ if (!c->key.know_w_is_one) {
+ brw_CMP(p,
+ vec8(brw_null_reg()),
+ BRW_CONDITIONAL_L,
+ brw_swizzle1(ndc, 3),
+ brw_imm_f(0));
+
+ brw_OR(p, brw_writemask(header1, TGSI_WRITEMASK_W), header1, brw_imm_ud(1<<6));
+ brw_MOV(p, ndc, brw_imm_f(0));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ }
+
+ brw_set_access_mode(p, BRW_ALIGN_1); /* why? */
+ brw_MOV(p, retype(brw_message_reg(1), BRW_REGISTER_TYPE_UD), header1);
+ brw_set_access_mode(p, BRW_ALIGN_16);
+
+ release_tmp(c, header1);
+ }
+ else {
+ brw_MOV(p, retype(brw_message_reg(1), BRW_REGISTER_TYPE_UD), brw_imm_ud(0));
+ }
+
+
+ /* Emit the (interleaved) headers for the two vertices - an 8-reg
+ * of zeros followed by two sets of NDC coordinates:
+ */
+ brw_set_access_mode(p, BRW_ALIGN_1);
+ brw_MOV(p, offset(m0, 2), ndc);
+ brw_MOV(p, offset(m0, 3), pos);
+
+
+ brw_urb_WRITE(p,
+ brw_null_reg(), /* dest */
+ 0, /* starting mrf reg nr */
+ c->r0, /* src */
+ 0, /* allocate */
+ 1, /* used */
+ c->nr_outputs + 3, /* msg len */
+ 0, /* response len */
+ 1, /* eot */
+ 1, /* writes complete */
+ 0, /* urb destination offset */
+ BRW_URB_SWIZZLE_INTERLEAVE);
+
+}
+
+static void
+post_vs_emit( struct brw_vs_compile *c, struct brw_instruction *end_inst )
+{
+ struct tgsi_parse_context parse;
+ const struct tgsi_token *tokens = c->vp->program.tokens;
+ tgsi_parse_init(&parse, tokens);
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+ if (parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION) {
+#if 0
+ struct brw_instruction *brw_inst1, *brw_inst2;
+ const struct tgsi_full_instruction *inst1, *inst2;
+ int offset;
+ inst1 = &parse.FullToken.FullInstruction;
+ brw_inst1 = inst1->Data;
+ switch (inst1->Opcode) {
+ case TGSI_OPCODE_CAL:
+ case TGSI_OPCODE_BRA:
+ target_insn = inst1->BranchTarget;
+ inst2 = &c->vp->program.Base.Instructions[target_insn];
+ brw_inst2 = inst2->Data;
+ offset = brw_inst2 - brw_inst1;
+ brw_set_src1(brw_inst1, brw_imm_d(offset*16));
+ break;
+ case TGSI_OPCODE_END:
+ offset = end_inst - brw_inst1;
+ brw_set_src1(brw_inst1, brw_imm_d(offset*16));
+ break;
+ default:
+ break;
+ }
+#endif
+ }
+ }
+ tgsi_parse_free(&parse);
+}
+
+static void process_declaration(const struct tgsi_full_declaration *decl,
+ struct brw_prog_info *info)
+{
+ int first = decl->DeclarationRange.First;
+ int last = decl->DeclarationRange.Last;
+
+ switch(decl->Declaration.File) {
+ case TGSI_FILE_CONSTANT:
+ info->num_consts += last - first + 1;
+ break;
+ case TGSI_FILE_INPUT: {
+ }
+ break;
+ case TGSI_FILE_OUTPUT: {
+ assert(last == first); /* for now */
+ if (decl->Declaration.Semantic) {
+ switch (decl->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION: {
+ info->pos_idx = first;
+ }
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ break;
+ case TGSI_SEMANTIC_BCOLOR:
+ break;
+ case TGSI_SEMANTIC_FOG:
+ break;
+ case TGSI_SEMANTIC_PSIZE: {
+ info->writes_psize = TRUE;
+ info->psize_idx = first;
+ }
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ break;
+ }
+ }
+ }
+ break;
+ case TGSI_FILE_TEMPORARY: {
+ info->num_temps += (last - first) + 1;
+ }
+ break;
+ case TGSI_FILE_SAMPLER: {
+ }
+ break;
+ case TGSI_FILE_ADDRESS: {
+ info->num_addrs += (last - first) + 1;
+ }
+ break;
+ case TGSI_FILE_IMMEDIATE: {
+ }
+ break;
+ case TGSI_FILE_NULL: {
+ }
+ break;
+ }
+}
+
+static void process_instruction(struct brw_vs_compile *c,
+ struct tgsi_full_instruction *inst,
+ struct brw_prog_info *info)
+{
+ struct brw_reg args[3], dst;
+ struct brw_compile *p = &c->func;
+ /*struct brw_indirect stack_index = brw_indirect(0, 0);*/
+ unsigned i;
+ unsigned index;
+ unsigned file;
+ /*FIXME: might not be the only one*/
+ const struct tgsi_dst_register *dst_reg = &inst->FullDstRegisters[0].DstRegister;
+ /*
+ struct brw_instruction *if_inst[MAX_IFSN];
+ unsigned insn, if_insn = 0;
+ */
+
+ for (i = 0; i < 3; i++) {
+ struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
+ index = src->SrcRegister.Index;
+ file = src->SrcRegister.File;
+ if (file == TGSI_FILE_OUTPUT && c->output_regs[index].used_in_src)
+ args[i] = c->output_regs[index].reg;
+ else
+ args[i] = get_arg(c, &src->SrcRegister);
+ }
+
+ /* Get dest regs. Note that it is possible for a reg to be both
+ * dst and arg, given the static allocation of registers. So
+ * care needs to be taken emitting multi-operation instructions.
+ */
+ index = dst_reg->Index;
+ file = dst_reg->File;
+ if (file == TGSI_FILE_OUTPUT && c->output_regs[index].used_in_src)
+ dst = c->output_regs[index].reg;
+ else
+ dst = get_dst(c, dst_reg);
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ brw_MOV(p, dst, brw_abs(args[0]));
+ break;
+ case TGSI_OPCODE_ADD:
+ brw_ADD(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_DP3:
+ brw_DP3(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_DP4:
+ brw_DP4(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_DPH:
+ brw_DPH(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_DST:
+ unalias2(c, dst, args[0], args[1], emit_dst_noalias);
+ break;
+ case TGSI_OPCODE_EXP:
+ unalias1(c, dst, args[0], emit_exp_noalias);
+ break;
+ case TGSI_OPCODE_EX2:
+ emit_math1(c, BRW_MATH_FUNCTION_EXP, dst, args[0], BRW_MATH_PRECISION_FULL);
+ break;
+ case TGSI_OPCODE_ARL:
+ emit_arl(c, dst, args[0]);
+ break;
+ case TGSI_OPCODE_FLR:
+ brw_RNDD(p, dst, args[0]);
+ break;
+ case TGSI_OPCODE_FRC:
+ brw_FRC(p, dst, args[0]);
+ break;
+ case TGSI_OPCODE_LOG:
+ unalias1(c, dst, args[0], emit_log_noalias);
+ break;
+ case TGSI_OPCODE_LG2:
+ emit_math1(c, BRW_MATH_FUNCTION_LOG, dst, args[0], BRW_MATH_PRECISION_FULL);
+ break;
+ case TGSI_OPCODE_LIT:
+ unalias1(c, dst, args[0], emit_lit_noalias);
+ break;
+ case TGSI_OPCODE_MAD:
+ brw_MOV(p, brw_acc_reg(), args[2]);
+ brw_MAC(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_MAX:
+ emit_max(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_MIN:
+ emit_min(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+#if 0
+ /* The args[0] value can't be used here as it won't have
+ * correctly encoded the full swizzle:
+ */
+ emit_swz(c, dst, inst->SrcReg[0] );
+#endif
+ brw_MOV(p, dst, args[0]);
+ break;
+ case TGSI_OPCODE_MUL:
+ brw_MUL(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_POW:
+ emit_math2(c, BRW_MATH_FUNCTION_POW, dst, args[0], args[1], BRW_MATH_PRECISION_FULL);
+ break;
+ case TGSI_OPCODE_RCP:
+ emit_math1(c, BRW_MATH_FUNCTION_INV, dst, args[0], BRW_MATH_PRECISION_FULL);
+ break;
+ case TGSI_OPCODE_RSQ:
+ emit_math1(c, BRW_MATH_FUNCTION_RSQ, dst, args[0], BRW_MATH_PRECISION_FULL);
+ break;
+
+ case TGSI_OPCODE_SEQ:
+ emit_seq(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_SNE:
+ emit_sne(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_SGE:
+ emit_sge(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_SGT:
+ emit_sgt(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_SLT:
+ emit_slt(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_SLE:
+ emit_sle(p, dst, args[0], args[1]);
+ break;
+ case TGSI_OPCODE_SUB:
+ brw_ADD(p, dst, args[0], negate(args[1]));
+ break;
+ case TGSI_OPCODE_XPD:
+ emit_xpd(p, dst, args[0], args[1]);
+ break;
+#if 0
+ case TGSI_OPCODE_IF:
+ assert(if_insn < MAX_IFSN);
+ if_inst[if_insn++] = brw_IF(p, BRW_EXECUTE_8);
+ break;
+ case TGSI_OPCODE_ELSE:
+ if_inst[if_insn-1] = brw_ELSE(p, if_inst[if_insn-1]);
+ break;
+ case TGSI_OPCODE_ENDIF:
+ assert(if_insn > 0);
+ brw_ENDIF(p, if_inst[--if_insn]);
+ break;
+ case TGSI_OPCODE_BRA:
+ brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+ brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
+ brw_set_predicate_control_flag_value(p, 0xff);
+ break;
+ case TGSI_OPCODE_CAL:
+ brw_set_access_mode(p, BRW_ALIGN_1);
+ brw_ADD(p, deref_1uw(stack_index, 0), brw_ip_reg(), brw_imm_d(3*16));
+ brw_set_access_mode(p, BRW_ALIGN_16);
+ brw_ADD(p, get_addr_reg(stack_index),
+ get_addr_reg(stack_index), brw_imm_d(4));
+ inst->Data = &p->store[p->nr_insn];
+ brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
+ break;
+#endif
+ case TGSI_OPCODE_RET:
+#if 0
+ brw_ADD(p, get_addr_reg(stack_index),
+ get_addr_reg(stack_index), brw_imm_d(-4));
+ brw_set_access_mode(p, BRW_ALIGN_1);
+ brw_MOV(p, brw_ip_reg(), deref_1uw(stack_index, 0));
+ brw_set_access_mode(p, BRW_ALIGN_16);
+#else
+ /*brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));*/
+#endif
+ break;
+ case TGSI_OPCODE_END:
+ brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
+ break;
+ case TGSI_OPCODE_BGNSUB:
+ case TGSI_OPCODE_ENDSUB:
+ break;
+ default:
+ debug_printf("Unsupport opcode %d in vertex shader\n", inst->Instruction.Opcode);
+ break;
+ }
+
+ if (dst_reg->File == TGSI_FILE_OUTPUT
+ && dst_reg->Index != info->pos_idx
+ && c->output_regs[dst_reg->Index].used_in_src)
+ brw_MOV(p, get_dst(c, dst_reg), dst);
+
+ release_tmps(c);
+}
+
+/* Emit the fragment program instructions here.
+ */
+void brw_vs_emit(struct brw_vs_compile *c)
+{
+#define MAX_IFSN 32
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *end_inst;
+ struct tgsi_parse_context parse;
+ struct brw_indirect stack_index = brw_indirect(0, 0);
+ const struct tgsi_token *tokens = c->vp->program.tokens;
+ struct brw_prog_info prog_info;
+ unsigned allocated_registers = 0;
+ memset(&prog_info, 0, sizeof(struct brw_prog_info));
+
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_set_access_mode(p, BRW_ALIGN_16);
+
+ tgsi_parse_init(&parse, tokens);
+ /* Message registers can't be read, so copy the output into GRF register
+ if they are used in source registers */
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+ unsigned i;
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION: {
+ const struct tgsi_full_instruction *inst = &parse.FullToken.FullInstruction;
+ for (i = 0; i < 3; ++i) {
+ const struct tgsi_src_register *src = &inst->FullSrcRegisters[i].SrcRegister;
+ unsigned index = src->Index;
+ unsigned file = src->File;
+ if (file == TGSI_FILE_OUTPUT)
+ c->output_regs[index].used_in_src = TRUE;
+ }
+ }
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+ }
+ tgsi_parse_free(&parse);
+
+ tgsi_parse_init(&parse, tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION: {
+ struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration;
+ process_declaration(decl, &prog_info);
+ }
+ break;
+ case TGSI_TOKEN_TYPE_IMMEDIATE: {
+ struct tgsi_full_immediate *imm = &parse.FullToken.FullImmediate;
+ assert(imm->Immediate.NrTokens == 4 + 1);
+ c->prog_data.imm_buf[c->prog_data.num_imm][0] = imm->u[0].Float;
+ c->prog_data.imm_buf[c->prog_data.num_imm][1] = imm->u[1].Float;
+ c->prog_data.imm_buf[c->prog_data.num_imm][2] = imm->u[2].Float;
+ c->prog_data.imm_buf[c->prog_data.num_imm][3] = imm->u[3].Float;
+ c->prog_data.num_imm++;
+ }
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION: {
+ struct tgsi_full_instruction *inst = &parse.FullToken.FullInstruction;
+ if (!allocated_registers) {
+ /* first instruction (declerations finished).
+ * now that we know what vars are being used allocate
+ * registers for them.*/
+ c->prog_data.num_consts = prog_info.num_consts;
+ c->prog_data.max_const = prog_info.num_consts + c->prog_data.num_imm;
+ brw_vs_alloc_regs(c, &prog_info);
+
+ brw_set_access_mode(p, BRW_ALIGN_1);
+ brw_MOV(p, get_addr_reg(stack_index), brw_address(c->stack));
+ brw_set_access_mode(p, BRW_ALIGN_16);
+ allocated_registers = 1;
+ }
+ process_instruction(c, inst, &prog_info);
+ }
+ break;
+ }
+ }
+
+ end_inst = &p->store[p->nr_insn];
+ emit_vertex_write(c, &prog_info);
+ post_vs_emit(c, end_inst);
+ tgsi_parse_free(&parse);
+
+}
diff --git a/src/gallium/drivers/i965simple/brw_vs_state.c b/src/gallium/drivers/i965simple/brw_vs_state.c
new file mode 100644
index 0000000000..1eaff87892
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_vs_state.c
@@ -0,0 +1,103 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+static void upload_vs_unit( struct brw_context *brw )
+{
+ struct brw_vs_unit_state vs;
+
+ memset(&vs, 0, sizeof(vs));
+
+ /* CACHE_NEW_VS_PROG */
+ vs.thread0.kernel_start_pointer = brw->vs.prog_gs_offset >> 6;
+ vs.thread0.grf_reg_count = align(brw->vs.prog_data->total_grf, 16) / 16 - 1;
+ vs.thread3.urb_entry_read_length = brw->vs.prog_data->urb_read_length;
+ vs.thread3.const_urb_entry_read_length = brw->vs.prog_data->curb_read_length;
+ vs.thread3.dispatch_grf_start_reg = 1;
+
+
+ /* BRW_NEW_URB_FENCE */
+ vs.thread4.nr_urb_entries = brw->urb.nr_vs_entries;
+ vs.thread4.urb_entry_allocation_size = brw->urb.vsize - 1;
+ vs.thread4.max_threads = MIN2(
+ MAX2(0, (brw->urb.nr_vs_entries - 6) / 2 - 1),
+ 15);
+
+
+
+ if (BRW_DEBUG & DEBUG_SINGLE_THREAD)
+ vs.thread4.max_threads = 0;
+
+ /* BRW_NEW_CURBE_OFFSETS, _NEW_TRANSFORM */
+ if (0 /*brw->attribs.Clip->ClipPlanesEnabled*/) {
+ /* Note that we read in the userclip planes as well, hence
+ * clip_start:
+ */
+ vs.thread3.const_urb_entry_read_offset = brw->curbe.clip_start * 2;
+ }
+ else {
+ vs.thread3.const_urb_entry_read_offset = brw->curbe.vs_start * 2;
+ }
+
+ vs.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
+ vs.thread3.urb_entry_read_offset = 0;
+
+ /* No samplers for ARB_vp programs:
+ */
+ vs.vs5.sampler_count = 0;
+
+ if (BRW_DEBUG & DEBUG_STATS)
+ vs.thread4.stats_enable = 1;
+
+ /* Vertex program always enabled:
+ */
+ vs.vs6.vs_enable = 1;
+
+ brw->vs.state_gs_offset = brw_cache_data( &brw->cache[BRW_VS_UNIT], &vs );
+}
+
+
+const struct brw_tracked_state brw_vs_unit = {
+ .dirty = {
+ .brw = (BRW_NEW_CLIP |
+ BRW_NEW_CURBE_OFFSETS |
+ BRW_NEW_URB_FENCE),
+ .cache = CACHE_NEW_VS_PROG
+ },
+ .update = upload_vs_unit
+};
diff --git a/src/gallium/drivers/i965simple/brw_winsys.h b/src/gallium/drivers/i965simple/brw_winsys.h
new file mode 100644
index 0000000000..ec1e400418
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_winsys.h
@@ -0,0 +1,209 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * This is the interface that i965simple requires any window system
+ * hosting it to implement. This is the only include file in i965simple
+ * which is public.
+ *
+ */
+
+#ifndef BRW_WINSYS_H
+#define BRW_WINSYS_H
+
+
+#include "pipe/p_defines.h"
+
+
+/* Pipe drivers are (meant to be!) independent of both GL and the
+ * window system. The window system provides a buffer manager and a
+ * set of additional hooks for things like command buffer submission,
+ * etc.
+ *
+ * There clearly has to be some agreement between the window system
+ * driver and the hardware driver about the format of command buffers,
+ * etc.
+ */
+
+struct pipe_buffer;
+struct pipe_fence_handle;
+struct pipe_winsys;
+struct pipe_screen;
+
+
+/* The pipe driver currently understands the following chipsets:
+ */
+#define PCI_CHIP_I965_G 0x29A2
+#define PCI_CHIP_I965_Q 0x2992
+#define PCI_CHIP_I965_G_1 0x2982
+#define PCI_CHIP_I965_GM 0x2A02
+#define PCI_CHIP_I965_GME 0x2A12
+
+
+/* These are the names of all the state caches managed by the driver.
+ *
+ * When data is uploaded to a buffer with buffer_subdata, we use the
+ * special version of that function below so that information about
+ * what type of data this is can be passed to the winsys backend.
+ * That in turn allows the correct flags to be set in the aub file
+ * dump to allow human-readable file dumps later on.
+ */
+
+enum brw_cache_id {
+ BRW_CC_VP,
+ BRW_CC_UNIT,
+ BRW_WM_PROG,
+ BRW_SAMPLER_DEFAULT_COLOR,
+ BRW_SAMPLER,
+ BRW_WM_UNIT,
+ BRW_SF_PROG,
+ BRW_SF_VP,
+ BRW_SF_UNIT,
+ BRW_VS_UNIT,
+ BRW_VS_PROG,
+ BRW_GS_UNIT,
+ BRW_GS_PROG,
+ BRW_CLIP_VP,
+ BRW_CLIP_UNIT,
+ BRW_CLIP_PROG,
+ BRW_SS_SURFACE,
+ BRW_SS_SURF_BIND,
+
+ BRW_MAX_CACHE
+};
+
+#define BRW_CONSTANT_BUFFER BRW_MAX_CACHE
+
+/**
+ * Additional winsys interface for i965simple.
+ *
+ * It is an over-simple batchbuffer mechanism. Will want to improve the
+ * performance of this, perhaps based on the cmdstream stuff. It
+ * would be pretty impossible to implement swz on top of this
+ * interface.
+ *
+ * Will also need additions/changes to implement static/dynamic
+ * indirect state.
+ */
+struct brw_winsys {
+
+ void (*destroy)(struct brw_winsys *);
+
+ /**
+ * Reserve space on batch buffer.
+ *
+ * Returns a null pointer if there is insufficient space in the batch buffer
+ * to hold the requested number of dwords and relocations.
+ *
+ * The number of dwords should also include the number of relocations.
+ */
+ unsigned *(*batch_start)(struct brw_winsys *sws,
+ unsigned dwords,
+ unsigned relocs);
+
+ void (*batch_dword)(struct brw_winsys *sws,
+ unsigned dword);
+
+ /**
+ * Emit a relocation to a buffer.
+ *
+ * Used not only when the buffer addresses are not pinned, but also to
+ * ensure refered buffers will not be destroyed until the current batch
+ * buffer execution is finished.
+ *
+ * The access flags is a combination of I915_BUFFER_ACCESS_WRITE and
+ * I915_BUFFER_ACCESS_READ macros.
+ */
+ void (*batch_reloc)(struct brw_winsys *sws,
+ struct pipe_buffer *buf,
+ unsigned access_flags,
+ unsigned delta);
+
+
+ /* Not used yet, but really want this:
+ */
+ void (*batch_end)( struct brw_winsys *sws );
+
+ /**
+ * Flush the batch buffer.
+ *
+ * Fence argument must point to NULL or to a previous fence, and the caller
+ * must call fence_reference when done with the fence.
+ */
+ void (*batch_flush)(struct brw_winsys *sws,
+ struct pipe_fence_handle **fence);
+
+
+ /* A version of buffer_subdata that includes information for the
+ * simulator:
+ */
+ void (*buffer_subdata_typed)(struct brw_winsys *sws,
+ struct pipe_buffer *buf,
+ unsigned long offset,
+ unsigned long size,
+ const void *data,
+ unsigned data_type);
+
+
+ /* A cheat so we don't have to think about relocations in a couple
+ * of places yet:
+ */
+ unsigned (*get_buffer_offset)( struct brw_winsys *sws,
+ struct pipe_buffer *buf,
+ unsigned flags );
+
+};
+
+#define BRW_BUFFER_ACCESS_WRITE 0x1
+#define BRW_BUFFER_ACCESS_READ 0x2
+
+#define BRW_BUFFER_USAGE_LIT_VERTEX (PIPE_BUFFER_USAGE_CUSTOM << 0)
+
+
+struct pipe_context *brw_create(struct pipe_screen *,
+ struct brw_winsys *,
+ unsigned pci_id);
+
+static inline boolean brw_batchbuffer_data(struct brw_winsys *winsys,
+ const void *data,
+ unsigned bytes)
+{
+ static const unsigned incr = sizeof(unsigned);
+ uint i;
+ const unsigned *udata = (const unsigned*)(data);
+ unsigned size = bytes/incr;
+
+ winsys->batch_start(winsys, size, 0);
+ for (i = 0; i < size; ++i) {
+ winsys->batch_dword(winsys, udata[i]);
+ }
+ winsys->batch_end(winsys);
+
+ return (i == size);
+}
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_wm.c b/src/gallium/drivers/i965simple/brw_wm.c
new file mode 100644
index 0000000000..10161f2d2f
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_wm.c
@@ -0,0 +1,209 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_util.h"
+#include "brw_wm.h"
+#include "brw_eu.h"
+#include "brw_state.h"
+#include "util/u_memory.h"
+
+
+
+static void do_wm_prog( struct brw_context *brw,
+ struct brw_fragment_program *fp,
+ struct brw_wm_prog_key *key)
+{
+ struct brw_wm_compile *c = CALLOC_STRUCT(brw_wm_compile);
+ const unsigned *program;
+ unsigned program_size;
+
+ c->key = *key;
+ c->fp = fp;
+
+ c->delta_xy[0] = brw_null_reg();
+ c->delta_xy[1] = brw_null_reg();
+ c->pixel_xy[0] = brw_null_reg();
+ c->pixel_xy[1] = brw_null_reg();
+ c->pixel_w = brw_null_reg();
+
+
+ debug_printf("XXXXXXXX FP\n");
+
+ brw_wm_glsl_emit(c);
+
+ /* get the program
+ */
+ program = brw_get_program(&c->func, &program_size);
+
+ /*
+ */
+ brw->wm.prog_gs_offset = brw_upload_cache( &brw->cache[BRW_WM_PROG],
+ &c->key,
+ sizeof(c->key),
+ program,
+ program_size,
+ &c->prog_data,
+ &brw->wm.prog_data );
+
+ FREE(c);
+}
+
+
+
+static void brw_wm_populate_key( struct brw_context *brw,
+ struct brw_wm_prog_key *key )
+{
+ /* BRW_NEW_FRAGMENT_PROGRAM */
+ struct brw_fragment_program *fp =
+ (struct brw_fragment_program *)brw->attribs.FragmentProgram;
+ unsigned lookup = 0;
+ unsigned line_aa;
+
+ memset(key, 0, sizeof(*key));
+
+ /* Build the index for table lookup
+ */
+ /* BRW_NEW_DEPTH_STENCIL */
+ if (fp->info.uses_kill ||
+ brw->attribs.DepthStencil->alpha.enabled)
+ lookup |= IZ_PS_KILL_ALPHATEST_BIT;
+
+ if (fp->info.writes_z)
+ lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
+
+ if (brw->attribs.DepthStencil->depth.enabled)
+ lookup |= IZ_DEPTH_TEST_ENABLE_BIT;
+
+ if (brw->attribs.DepthStencil->depth.enabled &&
+ brw->attribs.DepthStencil->depth.writemask) /* ?? */
+ lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;
+
+ if (brw->attribs.DepthStencil->stencil[0].enabled) {
+ lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
+
+ if (brw->attribs.DepthStencil->stencil[0].writemask ||
+ brw->attribs.DepthStencil->stencil[1].writemask)
+ lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
+ }
+
+ /* XXX: when should this be disabled?
+ */
+ if (1)
+ lookup |= IZ_EARLY_DEPTH_TEST_BIT;
+
+
+ line_aa = AA_NEVER;
+
+ /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */
+ if (brw->attribs.Raster->line_smooth) {
+ if (brw->reduced_primitive == PIPE_PRIM_LINES) {
+ line_aa = AA_ALWAYS;
+ }
+ else if (brw->reduced_primitive == PIPE_PRIM_TRIANGLES) {
+ if (brw->attribs.Raster->fill_ccw == PIPE_POLYGON_MODE_LINE) {
+ line_aa = AA_SOMETIMES;
+
+ if (brw->attribs.Raster->fill_cw == PIPE_POLYGON_MODE_LINE ||
+ (brw->attribs.Raster->cull_mode == PIPE_WINDING_CW))
+ line_aa = AA_ALWAYS;
+ }
+ else if (brw->attribs.Raster->fill_cw == PIPE_POLYGON_MODE_LINE) {
+ line_aa = AA_SOMETIMES;
+
+ if (brw->attribs.Raster->cull_mode == PIPE_WINDING_CCW)
+ line_aa = AA_ALWAYS;
+ }
+ }
+ }
+
+ brw_wm_lookup_iz(line_aa,
+ lookup,
+ key);
+
+
+#if 0
+ /* BRW_NEW_SAMPLER
+ *
+ * Not doing any of this at the moment:
+ */
+ for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
+ const struct pipe_sampler_state *unit = brw->attribs.Samplers[i];
+
+ if (unit) {
+
+ if (unit->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ key->shadowtex_mask |= 1<<i;
+ }
+ if (t->Image[0][t->BaseLevel]->InternalFormat == GL_YCBCR_MESA)
+ key->yuvtex_mask |= 1<<i;
+ }
+ }
+#endif
+
+
+ /* Extra info:
+ */
+ key->program_string_id = fp->id;
+
+}
+
+
+static void brw_upload_wm_prog( struct brw_context *brw )
+{
+ struct brw_wm_prog_key key;
+ struct brw_fragment_program *fp = (struct brw_fragment_program *)
+ brw->attribs.FragmentProgram;
+
+ brw_wm_populate_key(brw, &key);
+
+ /* Make an early check for the key.
+ */
+ if (brw_search_cache(&brw->cache[BRW_WM_PROG],
+ &key, sizeof(key),
+ &brw->wm.prog_data,
+ &brw->wm.prog_gs_offset))
+ return;
+
+ do_wm_prog(brw, fp, &key);
+}
+
+
+const struct brw_tracked_state brw_wm_prog = {
+ .dirty = {
+ .brw = (BRW_NEW_FS |
+ BRW_NEW_REDUCED_PRIMITIVE),
+ .cache = 0
+ },
+ .update = brw_upload_wm_prog
+};
+
diff --git a/src/gallium/drivers/i965simple/brw_wm.h b/src/gallium/drivers/i965simple/brw_wm.h
new file mode 100644
index 0000000000..b29c4393f0
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_wm.h
@@ -0,0 +1,142 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef BRW_WM_H
+#define BRW_WM_H
+
+
+#include "brw_context.h"
+#include "brw_eu.h"
+
+/* A big lookup table is used to figure out which and how many
+ * additional regs will inserted before the main payload in the WM
+ * program execution. These mainly relate to depth and stencil
+ * processing and the early-depth-test optimization.
+ */
+#define IZ_PS_KILL_ALPHATEST_BIT 0x1
+#define IZ_PS_COMPUTES_DEPTH_BIT 0x2
+#define IZ_DEPTH_WRITE_ENABLE_BIT 0x4
+#define IZ_DEPTH_TEST_ENABLE_BIT 0x8
+#define IZ_STENCIL_WRITE_ENABLE_BIT 0x10
+#define IZ_STENCIL_TEST_ENABLE_BIT 0x20
+#define IZ_EARLY_DEPTH_TEST_BIT 0x40
+#define IZ_BIT_MAX 0x80
+
+#define AA_NEVER 0
+#define AA_SOMETIMES 1
+#define AA_ALWAYS 2
+
+struct brw_wm_prog_key {
+ unsigned source_depth_reg:3;
+ unsigned aa_dest_stencil_reg:3;
+ unsigned dest_depth_reg:3;
+ unsigned nr_depth_regs:3;
+ unsigned shadowtex_mask:8;
+ unsigned computes_depth:1; /* could be derived from program string */
+ unsigned source_depth_to_render_target:1;
+ unsigned runtime_check_aads_emit:1;
+
+ unsigned yuvtex_mask:8;
+
+ unsigned program_string_id;
+};
+
+
+
+
+
+#define PROGRAM_INTERNAL_PARAM
+#define MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS 1024 /* 72 for GL_ARB_f_p */
+#define BRW_WM_MAX_INSN (MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS*3 + PIPE_MAX_ATTRIBS + 3)
+#define BRW_WM_MAX_GRF 128 /* hardware limit */
+#define BRW_WM_MAX_VREG (BRW_WM_MAX_INSN * 4)
+#define BRW_WM_MAX_REF (BRW_WM_MAX_INSN * 12)
+#define BRW_WM_MAX_PARAM 256
+#define BRW_WM_MAX_CONST 256
+#define BRW_WM_MAX_KILLS MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS
+
+#define PAYLOAD_DEPTH (PIPE_MAX_ATTRIBS)
+
+#define MAX_IFSN 32
+#define MAX_LOOP_DEPTH 32
+
+struct brw_wm_compile {
+ struct brw_compile func;
+ struct brw_wm_prog_key key;
+ struct brw_wm_prog_data prog_data; /* result */
+
+ struct brw_fragment_program *fp;
+
+ unsigned grf_limit;
+ unsigned max_wm_grf;
+
+
+ struct brw_reg pixel_xy[2];
+ struct brw_reg delta_xy[2];
+ struct brw_reg pixel_w;
+
+
+ struct brw_reg wm_regs[8][32][4];
+
+ struct brw_reg payload_depth[4];
+ struct brw_reg payload_coef[16];
+
+ struct brw_reg emit_mask_reg;
+
+ struct brw_instruction *if_inst[MAX_IFSN];
+ int if_insn;
+
+ struct brw_instruction *loop_inst[MAX_LOOP_DEPTH];
+ int loop_insn;
+
+ struct brw_instruction *inst0;
+ struct brw_instruction *inst1;
+
+ struct brw_reg stack;
+ struct brw_indirect stack_index;
+
+ unsigned reg_index;
+
+ unsigned tmp_start;
+ unsigned tmp_index;
+};
+
+
+
+void brw_wm_lookup_iz( unsigned line_aa,
+ unsigned lookup,
+ struct brw_wm_prog_key *key );
+
+void brw_wm_glsl_emit(struct brw_wm_compile *c);
+void brw_wm_emit_decls(struct brw_wm_compile *c);
+
+#endif
diff --git a/src/gallium/drivers/i965simple/brw_wm_decl.c b/src/gallium/drivers/i965simple/brw_wm_decl.c
new file mode 100644
index 0000000000..d50e66f613
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_wm_decl.c
@@ -0,0 +1,392 @@
+
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_wm.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+
+static struct brw_reg alloc_tmp(struct brw_wm_compile *c)
+{
+ c->tmp_index++;
+ c->reg_index = MAX2(c->reg_index, c->tmp_start + c->tmp_index);
+ return brw_vec8_grf(c->tmp_start + c->tmp_index, 0);
+}
+
+static void release_tmps(struct brw_wm_compile *c)
+{
+ c->tmp_index = 0;
+}
+
+
+
+static int is_null( struct brw_reg reg )
+{
+ return (reg.file == BRW_ARCHITECTURE_REGISTER_FILE &&
+ reg.nr == BRW_ARF_NULL);
+}
+
+static void emit_pixel_xy( struct brw_wm_compile *c )
+{
+ if (is_null(c->pixel_xy[0])) {
+
+ struct brw_compile *p = &c->func;
+ struct brw_reg r1_uw = retype(brw_vec1_grf(1, 0), BRW_REGISTER_TYPE_UW);
+
+ c->pixel_xy[0] = vec8(retype(alloc_tmp(c), BRW_REGISTER_TYPE_UW));
+ c->pixel_xy[1] = vec8(retype(alloc_tmp(c), BRW_REGISTER_TYPE_UW));
+
+ /* Calculate pixel centers by adding 1 or 0 to each of the
+ * micro-tile coordinates passed in r1.
+ */
+ brw_ADD(p,
+ c->pixel_xy[0],
+ stride(suboffset(r1_uw, 4), 2, 4, 0),
+ brw_imm_v(0x10101010));
+
+ brw_ADD(p,
+ c->pixel_xy[1],
+ stride(suboffset(r1_uw, 5), 2, 4, 0),
+ brw_imm_v(0x11001100));
+ }
+}
+
+
+
+
+
+
+static void emit_delta_xy( struct brw_wm_compile *c )
+{
+ if (is_null(c->delta_xy[0])) {
+ struct brw_compile *p = &c->func;
+ struct brw_reg r1 = brw_vec1_grf(1, 0);
+
+ emit_pixel_xy(c);
+
+ c->delta_xy[0] = alloc_tmp(c);
+ c->delta_xy[1] = alloc_tmp(c);
+
+ /* Calc delta X,Y by subtracting origin in r1 from the pixel
+ * centers.
+ */
+ brw_ADD(p,
+ c->delta_xy[0],
+ retype(c->pixel_xy[0], BRW_REGISTER_TYPE_UW),
+ negate(r1));
+
+ brw_ADD(p,
+ c->delta_xy[1],
+ retype(c->pixel_xy[1], BRW_REGISTER_TYPE_UW),
+ negate(suboffset(r1,1)));
+ }
+}
+
+
+
+#if 0
+static void emit_pixel_w( struct brw_wm_compile *c )
+{
+ if (is_null(c->pixel_w)) {
+ struct brw_compile *p = &c->func;
+
+ struct brw_reg interp_wpos = c->coef_wpos;
+
+ c->pixel_w = alloc_tmp(c);
+
+ emit_delta_xy(c);
+
+ /* Calc 1/w - just linterp wpos[3] optimized by putting the
+ * result straight into a message reg.
+ */
+ struct brw_reg interp3 = brw_vec1_grf(interp_wpos.nr+1, 4);
+ brw_LINE(p, brw_null_reg(), interp3, c->delta_xy[0]);
+ brw_MAC(p, brw_message_reg(2), suboffset(interp3, 1), c->delta_xy[1]);
+
+ /* Calc w */
+ brw_math_16( p,
+ c->pixel_w,
+ BRW_MATH_FUNCTION_INV,
+ BRW_MATH_SATURATE_NONE,
+ 2,
+ brw_null_reg(),
+ BRW_MATH_PRECISION_FULL);
+ }
+}
+#endif
+
+
+static void emit_cinterp(struct brw_wm_compile *c,
+ int idx,
+ int mask )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg interp[4];
+ struct brw_reg coef = c->payload_coef[idx];
+ int i;
+
+ interp[0] = brw_vec1_grf(coef.nr, 0);
+ interp[1] = brw_vec1_grf(coef.nr, 4);
+ interp[2] = brw_vec1_grf(coef.nr+1, 0);
+ interp[3] = brw_vec1_grf(coef.nr+1, 4);
+
+ for(i = 0; i < 4; i++ ) {
+ if (mask & (1<<i)) {
+ struct brw_reg dst = c->wm_regs[TGSI_FILE_INPUT][idx][i];
+ brw_MOV(p, dst, suboffset(interp[i],3));
+ }
+ }
+}
+
+static void emit_linterp(struct brw_wm_compile *c,
+ int idx,
+ int mask )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg interp[4];
+ struct brw_reg coef = c->payload_coef[idx];
+ int i;
+
+ emit_delta_xy(c);
+
+ interp[0] = brw_vec1_grf(coef.nr, 0);
+ interp[1] = brw_vec1_grf(coef.nr, 4);
+ interp[2] = brw_vec1_grf(coef.nr+1, 0);
+ interp[3] = brw_vec1_grf(coef.nr+1, 4);
+
+ for(i = 0; i < 4; i++ ) {
+ if (mask & (1<<i)) {
+ struct brw_reg dst = c->wm_regs[TGSI_FILE_INPUT][idx][i];
+ brw_LINE(p, brw_null_reg(), interp[i], c->delta_xy[0]);
+ brw_MAC(p, dst, suboffset(interp[i],1), c->delta_xy[1]);
+ }
+ }
+}
+
+#if 0
+static void emit_pinterp(struct brw_wm_compile *c,
+ int idx,
+ int mask )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg interp[4];
+ struct brw_reg coef = c->payload_coef[idx];
+ int i;
+
+ get_delta_xy(c);
+ get_pixel_w(c);
+
+ interp[0] = brw_vec1_grf(coef.nr, 0);
+ interp[1] = brw_vec1_grf(coef.nr, 4);
+ interp[2] = brw_vec1_grf(coef.nr+1, 0);
+ interp[3] = brw_vec1_grf(coef.nr+1, 4);
+
+ for(i = 0; i < 4; i++ ) {
+ if (mask & (1<<i)) {
+ struct brw_reg dst = allocate_reg(c, TGSI_FILE_INPUT, idx, i);
+ brw_LINE(p, brw_null_reg(), interp[i], c->delta_xy[0]);
+ brw_MAC(p, dst, suboffset(interp[i],1), c->delta_xy[1]);
+ brw_MUL(p, dst, dst, c->pixel_w);
+ }
+ }
+}
+#endif
+
+
+
+#if 0
+static void emit_wpos( )
+{
+ struct prog_dst_register dst = dst_reg(PROGRAM_INPUT, idx);
+ struct tgsi_full_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
+ struct tgsi_full_src_register deltas = get_delta_xy(c);
+ struct tgsi_full_src_register arg2;
+ unsigned opcode;
+
+ opcode = WM_LINTERP;
+ arg2 = src_undef();
+
+ /* Have to treat wpos.xy specially:
+ */
+ emit_op(c,
+ WM_WPOSXY,
+ dst_mask(dst, WRITEMASK_XY),
+ 0, 0, 0,
+ get_pixel_xy(c),
+ src_undef(),
+ src_undef());
+
+ dst = dst_mask(dst, WRITEMASK_ZW);
+
+ /* PROGRAM_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw
+ */
+ emit_op(c,
+ WM_LINTERP,
+ dst,
+ 0, 0, 0,
+ interp,
+ deltas,
+ arg2);
+}
+#endif
+
+
+
+
+/* Perform register allocation:
+ *
+ * -- r0???
+ * -- passthrough depth regs (and stencil/aa??)
+ * -- curbe ??
+ * -- inputs (coefficients)
+ *
+ * Use a totally static register allocation. This will perform poorly
+ * but is an easy way to get started (again).
+ */
+static void prealloc_reg(struct brw_wm_compile *c)
+{
+ int i, j;
+ int nr_curbe_regs = 0;
+
+ /* R0, then some depth related regs:
+ */
+ for (i = 0; i < c->key.nr_depth_regs; i++) {
+ c->payload_depth[i] = brw_vec8_grf(i*2, 0);
+ c->reg_index += 2;
+ }
+
+
+ /* Then a copy of our part of the CURBE entry:
+ */
+ {
+ int nr_constants = c->fp->info.file_max[TGSI_FILE_CONSTANT] + 1;
+ int index = 0;
+
+ /* XXX number of constants, or highest numbered constant? */
+ assert(nr_constants == c->fp->info.file_count[TGSI_FILE_CONSTANT]);
+
+ c->prog_data.max_const = 4*nr_constants;
+ for (i = 0; i < nr_constants; i++) {
+ for (j = 0; j < 4; j++, index++)
+ c->wm_regs[TGSI_FILE_CONSTANT][i][j] = brw_vec1_grf(c->reg_index + index/8,
+ index%8);
+ }
+
+ nr_curbe_regs = 2*((4*nr_constants+15)/16);
+ c->reg_index += nr_curbe_regs;
+ }
+
+ /* Adjust for parameter coefficients for position, which are
+ * currently always provided.
+ */
+// c->position_coef[i] = brw_vec8_grf(c->reg_index, 0);
+ c->reg_index += 2;
+
+ /* Next we receive the plane coefficients for parameter
+ * interpolation:
+ */
+ assert(c->fp->info.file_max[TGSI_FILE_INPUT] == c->fp->info.num_inputs);
+ for (i = 0; i < c->fp->info.file_max[TGSI_FILE_INPUT] + 1; i++) {
+ c->payload_coef[i] = brw_vec8_grf(c->reg_index, 0);
+ c->reg_index += 2;
+ }
+
+ c->prog_data.first_curbe_grf = c->key.nr_depth_regs * 2;
+ c->prog_data.urb_read_length = (c->fp->info.num_inputs + 1) * 2;
+ c->prog_data.curb_read_length = nr_curbe_regs;
+
+ /* That's the end of the payload, now we can start allocating registers.
+ */
+ c->emit_mask_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0);
+ c->reg_index++;
+
+ c->stack = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0);
+ c->reg_index += 2;
+
+ /* Now allocate room for the interpolated inputs and staging
+ * registers for the outputs:
+ */
+ /* XXX do we want to loop over the _number_ of inputs/outputs or loop
+ * to the highest input/output index that's used?
+ * Probably the same, actually.
+ */
+ assert(c->fp->info.file_max[TGSI_FILE_INPUT] + 1 == c->fp->info.num_inputs);
+ assert(c->fp->info.file_max[TGSI_FILE_OUTPUT] + 1 == c->fp->info.num_outputs);
+ for (i = 0; i < c->fp->info.file_max[TGSI_FILE_INPUT] + 1; i++)
+ for (j = 0; j < 4; j++)
+ c->wm_regs[TGSI_FILE_INPUT][i][j] = brw_vec8_grf( c->reg_index++, 0 );
+
+ for (i = 0; i < c->fp->info.file_max[TGSI_FILE_OUTPUT] + 1; i++)
+ for (j = 0; j < 4; j++)
+ c->wm_regs[TGSI_FILE_OUTPUT][i][j] = brw_vec8_grf( c->reg_index++, 0 );
+
+ /* Beyond this we should only need registers for internal temporaries:
+ */
+ c->tmp_start = c->reg_index;
+}
+
+
+
+
+
+/* Need to interpolate fragment program inputs in as a preamble to the
+ * shader. A more sophisticated compiler would do this on demand, but
+ * we'll do it up front:
+ */
+void brw_wm_emit_decls(struct brw_wm_compile *c)
+{
+ struct tgsi_parse_context parse;
+ int done = 0;
+
+ prealloc_reg(c);
+
+ tgsi_parse_init( &parse, c->fp->program.tokens );
+
+ while( !done &&
+ !tgsi_parse_end_of_tokens( &parse ) )
+ {
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration;
+ unsigned first = decl->DeclarationRange.First;
+ unsigned last = decl->DeclarationRange.Last;
+ unsigned mask = decl->Declaration.UsageMask; /* ? */
+ unsigned i;
+
+ if (decl->Declaration.File != TGSI_FILE_INPUT)
+ break;
+
+ for( i = first; i <= last; i++ ) {
+ switch (decl->Declaration.Interpolate) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ emit_cinterp(c, i, mask);
+ break;
+
+ case TGSI_INTERPOLATE_LINEAR:
+ emit_linterp(c, i, mask);
+ break;
+
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ //emit_pinterp(c, i, mask);
+ emit_linterp(c, i, mask);
+ break;
+ }
+ }
+ break;
+ }
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ tgsi_parse_free (&parse);
+
+ release_tmps(c);
+}
diff --git a/src/gallium/drivers/i965simple/brw_wm_glsl.c b/src/gallium/drivers/i965simple/brw_wm_glsl.c
new file mode 100644
index 0000000000..db75963932
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_wm_glsl.c
@@ -0,0 +1,1076 @@
+
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_wm.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+
+
+
+static int get_scalar_dst_index(struct tgsi_full_instruction *inst)
+{
+ struct tgsi_dst_register dst = inst->FullDstRegisters[0].DstRegister;
+ int i;
+ for (i = 0; i < 4; i++)
+ if (dst.WriteMask & (1<<i))
+ break;
+ return i;
+}
+
+static struct brw_reg alloc_tmp(struct brw_wm_compile *c)
+{
+ c->tmp_index++;
+ c->reg_index = MAX2(c->reg_index, c->tmp_index);
+ return brw_vec8_grf(c->tmp_start + c->tmp_index, 0);
+}
+
+static void release_tmps(struct brw_wm_compile *c)
+{
+ c->tmp_index = 0;
+}
+
+
+static struct brw_reg
+get_reg(struct brw_wm_compile *c, int file, int index, int component )
+{
+ switch (file) {
+ case TGSI_FILE_NULL:
+ return brw_null_reg();
+
+ case TGSI_FILE_SAMPLER:
+ /* Should never get here:
+ */
+ assert (0);
+ return brw_null_reg();
+
+ case TGSI_FILE_IMMEDIATE:
+ /* These need a different path:
+ */
+ assert(0);
+ return brw_null_reg();
+
+
+ case TGSI_FILE_CONSTANT:
+ case TGSI_FILE_INPUT:
+ case TGSI_FILE_OUTPUT:
+ case TGSI_FILE_TEMPORARY:
+ case TGSI_FILE_ADDRESS:
+ return c->wm_regs[file][index][component];
+
+ default:
+ assert(0);
+ return brw_null_reg();
+ }
+}
+
+
+static struct brw_reg get_dst_reg(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst,
+ int component)
+{
+ return get_reg(c,
+ inst->FullDstRegisters[0].DstRegister.File,
+ inst->FullDstRegisters[0].DstRegister.Index,
+ component);
+}
+
+static int get_swz( struct tgsi_src_register src, int index )
+{
+ switch (index & 3) {
+ case 0: return src.SwizzleX;
+ case 1: return src.SwizzleY;
+ case 2: return src.SwizzleZ;
+ case 3: return src.SwizzleW;
+ default: return 0;
+ }
+}
+
+static int get_ext_swz( struct tgsi_src_register_ext_swz src, int index )
+{
+ switch (index & 3) {
+ case 0: return src.ExtSwizzleX;
+ case 1: return src.ExtSwizzleY;
+ case 2: return src.ExtSwizzleZ;
+ case 3: return src.ExtSwizzleW;
+ default: return 0;
+ }
+}
+
+static struct brw_reg get_src_reg(struct brw_wm_compile *c,
+ struct tgsi_full_src_register *src,
+ int index)
+{
+ struct brw_reg reg;
+ int component = index;
+ int neg = 0;
+ int abs = 0;
+
+ if (src->SrcRegister.Negate)
+ neg = 1;
+
+ component = get_swz(src->SrcRegister, component);
+
+ /* Yes, there are multiple negates:
+ */
+ switch (component & 3) {
+ case 0: neg ^= src->SrcRegisterExtSwz.NegateX; break;
+ case 1: neg ^= src->SrcRegisterExtSwz.NegateY; break;
+ case 2: neg ^= src->SrcRegisterExtSwz.NegateZ; break;
+ case 3: neg ^= src->SrcRegisterExtSwz.NegateW; break;
+ }
+
+ /* And multiple swizzles, fun isn't it:
+ */
+ component = get_ext_swz(src->SrcRegisterExtSwz, component);
+
+ /* Not handling indirect lookups yet:
+ */
+ assert(src->SrcRegister.Indirect == 0);
+
+ /* Don't know what dimension means:
+ */
+ assert(src->SrcRegister.Dimension == 0);
+
+ /* Will never handle any of this stuff:
+ */
+ assert(src->SrcRegisterExtMod.Complement == 0);
+ assert(src->SrcRegisterExtMod.Bias == 0);
+ assert(src->SrcRegisterExtMod.Scale2X == 0);
+
+ if (src->SrcRegisterExtMod.Absolute)
+ abs = 1;
+
+ /* Another negate! This is a post-absolute negate, which we
+ * can't do. Need to clean the crap out of tgsi somehow.
+ */
+ assert(src->SrcRegisterExtMod.Negate == 0);
+
+ switch( component ) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ reg = get_reg(c,
+ src->SrcRegister.File,
+ src->SrcRegister.Index,
+ component );
+
+ if (neg)
+ reg = negate(reg);
+
+ if (abs)
+ reg = brw_abs(reg);
+
+ break;
+
+ /* XXX: this won't really work in the general case, but we know
+ * that the extended swizzle is only allowed in the SWZ
+ * instruction (right??), in which case using an immediate
+ * directly will work.
+ */
+ case TGSI_EXTSWIZZLE_ZERO:
+ reg = brw_imm_f(0);
+ break;
+
+ case TGSI_EXTSWIZZLE_ONE:
+ if (neg && !abs)
+ reg = brw_imm_f(-1.0);
+ else
+ reg = brw_imm_f(1.0);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+
+ return reg;
+}
+
+static void emit_abs( struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+
+ int i;
+ struct brw_compile *p = &c->func;
+ brw_set_saturate(p, inst->Instruction.Saturate != TGSI_SAT_NONE);
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ struct brw_reg src, dst;
+ dst = get_dst_reg(c, inst, i);
+ src = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ brw_MOV(p, dst, brw_abs(src)); /* NOTE */
+ }
+ }
+ brw_set_saturate(p, 0);
+}
+
+
+static void emit_xpd(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ int i;
+ struct brw_compile *p = &c->func;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ for (i = 0; i < 4; i++) {
+ unsigned i2 = (i+2)%3;
+ unsigned i1 = (i+1)%3;
+ if (mask & (1<<i)) {
+ struct brw_reg src0, src1, dst;
+ dst = get_dst_reg(c, inst, i);
+ src0 = negate(get_src_reg(c, &inst->FullSrcRegisters[0], i2));
+ src1 = get_src_reg(c, &inst->FullSrcRegisters[1], i1);
+ brw_MUL(p, brw_null_reg(), src0, src1);
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], i1);
+ src1 = get_src_reg(c, &inst->FullSrcRegisters[1], i2);
+ brw_set_saturate(p, inst->Instruction.Saturate != TGSI_SAT_NONE);
+ brw_MAC(p, dst, src0, src1);
+ brw_set_saturate(p, 0);
+ }
+ }
+ brw_set_saturate(p, 0);
+}
+
+static void emit_dp3(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_reg src0[3], src1[3], dst;
+ int i;
+ struct brw_compile *p = &c->func;
+ for (i = 0; i < 3; i++) {
+ src0[i] = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ src1[i] = get_src_reg(c, &inst->FullSrcRegisters[1], i);
+ }
+
+ dst = get_dst_reg(c, inst, get_scalar_dst_index(inst));
+ brw_MUL(p, brw_null_reg(), src0[0], src1[0]);
+ brw_MAC(p, brw_null_reg(), src0[1], src1[1]);
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ brw_MAC(p, dst, src0[2], src1[2]);
+ brw_set_saturate(p, 0);
+}
+
+static void emit_dp4(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_reg src0[4], src1[4], dst;
+ int i;
+ struct brw_compile *p = &c->func;
+ for (i = 0; i < 4; i++) {
+ src0[i] = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ src1[i] = get_src_reg(c, &inst->FullSrcRegisters[1], i);
+ }
+ dst = get_dst_reg(c, inst, get_scalar_dst_index(inst));
+ brw_MUL(p, brw_null_reg(), src0[0], src1[0]);
+ brw_MAC(p, brw_null_reg(), src0[1], src1[1]);
+ brw_MAC(p, brw_null_reg(), src0[2], src1[2]);
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ brw_MAC(p, dst, src0[3], src1[3]);
+ brw_set_saturate(p, 0);
+}
+
+static void emit_dph(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_reg src0[4], src1[4], dst;
+ int i;
+ struct brw_compile *p = &c->func;
+ for (i = 0; i < 4; i++) {
+ src0[i] = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ src1[i] = get_src_reg(c, &inst->FullSrcRegisters[1], i);
+ }
+ dst = get_dst_reg(c, inst, get_scalar_dst_index(inst));
+ brw_MUL(p, brw_null_reg(), src0[0], src1[0]);
+ brw_MAC(p, brw_null_reg(), src0[1], src1[1]);
+ brw_MAC(p, dst, src0[2], src1[2]);
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ brw_ADD(p, dst, src0[3], src1[3]);
+ brw_set_saturate(p, 0);
+}
+
+static void emit_math1(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst, unsigned func)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg src0, dst;
+
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], 0);
+ dst = get_dst_reg(c, inst, get_scalar_dst_index(inst));
+ brw_MOV(p, brw_message_reg(2), src0);
+ brw_math(p,
+ dst,
+ func,
+ ((inst->Instruction.Saturate != TGSI_SAT_NONE)
+ ? BRW_MATH_SATURATE_SATURATE
+ : BRW_MATH_SATURATE_NONE),
+ 2,
+ brw_null_reg(),
+ BRW_MATH_DATA_VECTOR,
+ BRW_MATH_PRECISION_FULL);
+}
+
+
+static void emit_alu2(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst,
+ unsigned opcode)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg src0, src1, dst;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ int i;
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ for (i = 0 ; i < 4; i++) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ src1 = get_src_reg(c, &inst->FullSrcRegisters[1], i);
+ brw_alu2(p, opcode, dst, src0, src1);
+ }
+ }
+ brw_set_saturate(p, 0);
+}
+
+
+static void emit_alu1(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst,
+ unsigned opcode)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg src0, dst;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ int i;
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ for (i = 0 ; i < 4; i++) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ brw_alu1(p, opcode, dst, src0);
+ }
+ }
+ if (inst->Instruction.Saturate != TGSI_SAT_NONE)
+ brw_set_saturate(p, 0);
+}
+
+
+static void emit_max(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ struct brw_reg src0, src1, dst;
+ int i;
+ brw_push_insn_state(p);
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ src1 = get_src_reg(c, &inst->FullSrcRegisters[1], i);
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ brw_MOV(p, dst, src0);
+ brw_set_saturate(p, 0);
+
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, src0, src1);
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+ brw_MOV(p, dst, src1);
+ brw_set_saturate(p, 0);
+ brw_set_predicate_control_flag_value(p, 0xff);
+ }
+ }
+ brw_pop_insn_state(p);
+}
+
+static void emit_min(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ struct brw_reg src0, src1, dst;
+ int i;
+ brw_push_insn_state(p);
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ src1 = get_src_reg(c, &inst->FullSrcRegisters[1], i);
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ brw_MOV(p, dst, src0);
+ brw_set_saturate(p, 0);
+
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, src1, src0);
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+ brw_MOV(p, dst, src1);
+ brw_set_saturate(p, 0);
+ brw_set_predicate_control_flag_value(p, 0xff);
+ }
+ }
+ brw_pop_insn_state(p);
+}
+
+static void emit_pow(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg dst, src0, src1;
+ dst = get_dst_reg(c, inst, get_scalar_dst_index(inst));
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], 0);
+ src1 = get_src_reg(c, &inst->FullSrcRegisters[1], 0);
+
+ brw_MOV(p, brw_message_reg(2), src0);
+ brw_MOV(p, brw_message_reg(3), src1);
+
+ brw_math(p,
+ dst,
+ BRW_MATH_FUNCTION_POW,
+ (inst->Instruction.Saturate != TGSI_SAT_NONE
+ ? BRW_MATH_SATURATE_SATURATE
+ : BRW_MATH_SATURATE_NONE),
+ 2,
+ brw_null_reg(),
+ BRW_MATH_DATA_VECTOR,
+ BRW_MATH_PRECISION_FULL);
+}
+
+static void emit_lrp(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ struct brw_reg dst, tmp1, tmp2, src0, src1, src2;
+ int i;
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+
+ src1 = get_src_reg(c, &inst->FullSrcRegisters[1], i);
+
+ if (src1.nr == dst.nr) {
+ tmp1 = alloc_tmp(c);
+ brw_MOV(p, tmp1, src1);
+ } else
+ tmp1 = src1;
+
+ src2 = get_src_reg(c, &inst->FullSrcRegisters[2], i);
+ if (src2.nr == dst.nr) {
+ tmp2 = alloc_tmp(c);
+ brw_MOV(p, tmp2, src2);
+ } else
+ tmp2 = src2;
+
+ brw_ADD(p, dst, negate(src0), brw_imm_f(1.0));
+ brw_MUL(p, brw_null_reg(), dst, tmp2);
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ brw_MAC(p, dst, src0, tmp1);
+ brw_set_saturate(p, 0);
+ }
+ release_tmps(c);
+ }
+}
+
+static void emit_kil(struct brw_wm_compile *c)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg depth = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);
+ brw_push_insn_state(p);
+ brw_set_mask_control(p, BRW_MASK_DISABLE);
+ brw_NOT(p, c->emit_mask_reg, brw_mask_reg(1)); //IMASK
+ brw_AND(p, depth, c->emit_mask_reg, depth);
+ brw_pop_insn_state(p);
+}
+
+static void emit_mad(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ struct brw_reg dst, src0, src1, src2;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ src1 = get_src_reg(c, &inst->FullSrcRegisters[1], i);
+ src2 = get_src_reg(c, &inst->FullSrcRegisters[2], i);
+ brw_MUL(p, dst, src0, src1);
+
+ brw_set_saturate(p, (inst->Instruction.Saturate != TGSI_SAT_NONE) ? 1 : 0);
+ brw_ADD(p, dst, dst, src2);
+ brw_set_saturate(p, 0);
+ }
+ }
+}
+
+static void emit_sop(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst, unsigned cond)
+{
+ struct brw_compile *p = &c->func;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ struct brw_reg dst, src0, src1;
+ int i;
+
+ brw_push_insn_state(p);
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+ src1 = get_src_reg(c, &inst->FullSrcRegisters[1], i);
+ brw_CMP(p, brw_null_reg(), cond, src0, src1);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_MOV(p, dst, brw_imm_f(0.0));
+ brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+ brw_MOV(p, dst, brw_imm_f(1.0));
+ }
+ }
+ brw_pop_insn_state(p);
+}
+
+
+static void emit_ddx(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ struct brw_reg interp[4];
+ struct brw_reg dst;
+ struct brw_reg src0, w;
+ unsigned nr, i;
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], 0);
+ w = get_src_reg(c, &inst->FullSrcRegisters[1], 3);
+ nr = src0.nr;
+ interp[0] = brw_vec1_grf(nr, 0);
+ interp[1] = brw_vec1_grf(nr, 4);
+ interp[2] = brw_vec1_grf(nr+1, 0);
+ interp[3] = brw_vec1_grf(nr+1, 4);
+ brw_set_saturate(p, inst->Instruction.Saturate != TGSI_SAT_NONE);
+ for(i = 0; i < 4; i++ ) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ brw_MOV(p, dst, interp[i]);
+ brw_MUL(p, dst, dst, w);
+ }
+ }
+ brw_set_saturate(p, 0);
+}
+
+static void emit_ddy(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ unsigned mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ struct brw_reg interp[4];
+ struct brw_reg dst;
+ struct brw_reg src0, w;
+ unsigned nr, i;
+
+ src0 = get_src_reg(c, &inst->FullSrcRegisters[0], 0);
+ nr = src0.nr;
+ w = get_src_reg(c, &inst->FullSrcRegisters[1], 3);
+ interp[0] = brw_vec1_grf(nr, 0);
+ interp[1] = brw_vec1_grf(nr, 4);
+ interp[2] = brw_vec1_grf(nr+1, 0);
+ interp[3] = brw_vec1_grf(nr+1, 4);
+ brw_set_saturate(p, inst->Instruction.Saturate != TGSI_SAT_NONE);
+ for(i = 0; i < 4; i++ ) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ brw_MOV(p, dst, suboffset(interp[i], 1));
+ brw_MUL(p, dst, dst, w);
+ }
+ }
+ brw_set_saturate(p, 0);
+}
+
+/* TODO
+ BIAS on SIMD8 not workind yet...
+*/
+static void emit_txb(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+#if 0
+ struct brw_compile *p = &c->func;
+ struct brw_reg payload_reg = c->payload_depth[0];
+ struct brw_reg dst[4], src[4];
+ unsigned i;
+ for (i = 0; i < 4; i++)
+ dst[i] = get_dst_reg(c, inst, i);
+ for (i = 0; i < 4; i++)
+ src[i] = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+
+#if 0
+ switch (inst->TexSrcTarget) {
+ case TEXTURE_1D_INDEX:
+ brw_MOV(p, brw_message_reg(2), src[0]);
+ brw_MOV(p, brw_message_reg(3), brw_imm_f(0));
+ brw_MOV(p, brw_message_reg(4), brw_imm_f(0));
+ break;
+ case TEXTURE_2D_INDEX:
+ case TEXTURE_RECT_INDEX:
+ brw_MOV(p, brw_message_reg(2), src[0]);
+ brw_MOV(p, brw_message_reg(3), src[1]);
+ brw_MOV(p, brw_message_reg(4), brw_imm_f(0));
+ break;
+ default:
+ brw_MOV(p, brw_message_reg(2), src[0]);
+ brw_MOV(p, brw_message_reg(3), src[1]);
+ brw_MOV(p, brw_message_reg(4), src[2]);
+ break;
+ }
+#else
+ brw_MOV(p, brw_message_reg(2), src[0]);
+ brw_MOV(p, brw_message_reg(3), src[1]);
+ brw_MOV(p, brw_message_reg(4), brw_imm_f(0));
+#endif
+
+ brw_MOV(p, brw_message_reg(5), src[3]);
+ brw_MOV(p, brw_message_reg(6), brw_imm_f(0));
+ brw_SAMPLE(p,
+ retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
+ 1,
+ retype(payload_reg, BRW_REGISTER_TYPE_UW),
+ inst->TexSrcUnit + 1, /* surface */
+ inst->TexSrcUnit, /* sampler */
+ inst->FullDstRegisters[0].DstRegister.WriteMask,
+ BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
+ 4,
+ 4,
+ 0);
+#endif
+}
+
+static void emit_tex(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+#if 0
+ struct brw_compile *p = &c->func;
+ struct brw_reg payload_reg = c->payload_depth[0];
+ struct brw_reg dst[4], src[4];
+ unsigned msg_len;
+ unsigned i, nr;
+ unsigned emit;
+ boolean shadow = (c->key.shadowtex_mask & (1<<inst->TexSrcUnit)) ? 1 : 0;
+
+ for (i = 0; i < 4; i++)
+ dst[i] = get_dst_reg(c, inst, i);
+ for (i = 0; i < 4; i++)
+ src[i] = get_src_reg(c, &inst->FullSrcRegisters[0], i);
+
+#if 0
+ switch (inst->TexSrcTarget) {
+ case TEXTURE_1D_INDEX:
+ emit = WRITEMASK_X;
+ nr = 1;
+ break;
+ case TEXTURE_2D_INDEX:
+ case TEXTURE_RECT_INDEX:
+ emit = WRITEMASK_XY;
+ nr = 2;
+ break;
+ default:
+ emit = WRITEMASK_XYZ;
+ nr = 3;
+ break;
+ }
+#else
+ emit = WRITEMASK_XY;
+ nr = 2;
+#endif
+
+ msg_len = 1;
+
+ for (i = 0; i < nr; i++) {
+ static const unsigned swz[4] = {0,1,2,2};
+ if (emit & (1<<i))
+ brw_MOV(p, brw_message_reg(msg_len+1), src[swz[i]]);
+ else
+ brw_MOV(p, brw_message_reg(msg_len+1), brw_imm_f(0));
+ msg_len += 1;
+ }
+
+ if (shadow) {
+ brw_MOV(p, brw_message_reg(5), brw_imm_f(0));
+ brw_MOV(p, brw_message_reg(6), src[2]);
+ }
+
+ brw_SAMPLE(p,
+ retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
+ 1,
+ retype(payload_reg, BRW_REGISTER_TYPE_UW),
+ inst->TexSrcUnit + 1, /* surface */
+ inst->TexSrcUnit, /* sampler */
+ inst->FullDstRegisters[0].DstRegister.WriteMask,
+ BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE,
+ 4,
+ shadow ? 6 : 4,
+ 0);
+
+ if (shadow)
+ brw_MOV(p, dst[3], brw_imm_f(1.0));
+#endif
+}
+
+
+
+
+
+
+
+
+static void emit_fb_write(struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ int nr = 2;
+ int channel;
+ int base_reg = 0;
+
+ // src0 = output color
+ // src1 = payload_depth[0]
+ // src2 = output depth
+ // dst = ???
+
+
+
+ /* Reserve a space for AA - may not be needed:
+ */
+ if (c->key.aa_dest_stencil_reg)
+ nr += 1;
+
+ {
+ brw_push_insn_state(p);
+ for (channel = 0; channel < 4; channel++) {
+ struct brw_reg src0 = c->wm_regs[TGSI_FILE_OUTPUT][0][channel];
+
+ /* mov (8) m2.0<1>:ud r28.0<8;8,1>:ud { Align1 } */
+ /* mov (8) m6.0<1>:ud r29.0<8;8,1>:ud { Align1 SecHalf } */
+ brw_MOV(p, brw_message_reg(nr + channel), src0);
+ }
+ /* skip over the regs populated above: */
+ nr += 8;
+ brw_pop_insn_state(p);
+ }
+
+
+ /* Pass through control information:
+ */
+ /* mov (8) m1.0<1>:ud r1.0<8;8,1>:ud { Align1 NoMask } */
+ {
+ brw_push_insn_state(p);
+ brw_set_mask_control(p, BRW_MASK_DISABLE); /* ? */
+ brw_MOV(p,
+ brw_message_reg(base_reg + 1),
+ brw_vec8_grf(1, 0));
+ brw_pop_insn_state(p);
+ }
+
+ /* Send framebuffer write message: */
+ brw_fb_WRITE(p,
+ retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW),
+ base_reg,
+ retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
+ 0, /* render surface always 0 */
+ nr,
+ 0,
+ 1);
+
+}
+
+
+static void brw_wm_emit_instruction( struct brw_wm_compile *c,
+ struct tgsi_full_instruction *inst )
+{
+ struct brw_compile *p = &c->func;
+
+#if 0
+ if (inst->CondUpdate)
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ else
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NONE);
+#else
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NONE);
+#endif
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ emit_abs(c, inst);
+ break;
+ case TGSI_OPCODE_ADD:
+ emit_alu2(c, inst, BRW_OPCODE_ADD);
+ break;
+ case TGSI_OPCODE_SUB:
+ assert(0);
+// emit_alu2(c, inst, BRW_OPCODE_SUB);
+ break;
+ case TGSI_OPCODE_FRC:
+ emit_alu1(c, inst, BRW_OPCODE_FRC);
+ break;
+ case TGSI_OPCODE_FLR:
+ assert(0);
+// emit_alu1(c, inst, BRW_OPCODE_FLR);
+ break;
+ case TGSI_OPCODE_LRP:
+ emit_lrp(c, inst);
+ break;
+ case TGSI_OPCODE_INT:
+ emit_alu1(c, inst, BRW_OPCODE_RNDD);
+ break;
+ case TGSI_OPCODE_MOV:
+ emit_alu1(c, inst, BRW_OPCODE_MOV);
+ break;
+ case TGSI_OPCODE_DP3:
+ emit_dp3(c, inst);
+ break;
+ case TGSI_OPCODE_DP4:
+ emit_dp4(c, inst);
+ break;
+ case TGSI_OPCODE_XPD:
+ emit_xpd(c, inst);
+ break;
+ case TGSI_OPCODE_DPH:
+ emit_dph(c, inst);
+ break;
+ case TGSI_OPCODE_RCP:
+ emit_math1(c, inst, BRW_MATH_FUNCTION_INV);
+ break;
+ case TGSI_OPCODE_RSQ:
+ emit_math1(c, inst, BRW_MATH_FUNCTION_RSQ);
+ break;
+ case TGSI_OPCODE_SIN:
+ emit_math1(c, inst, BRW_MATH_FUNCTION_SIN);
+ break;
+ case TGSI_OPCODE_COS:
+ emit_math1(c, inst, BRW_MATH_FUNCTION_COS);
+ break;
+ case TGSI_OPCODE_EX2:
+ emit_math1(c, inst, BRW_MATH_FUNCTION_EXP);
+ break;
+ case TGSI_OPCODE_LG2:
+ emit_math1(c, inst, BRW_MATH_FUNCTION_LOG);
+ break;
+ case TGSI_OPCODE_MAX:
+ emit_max(c, inst);
+ break;
+ case TGSI_OPCODE_MIN:
+ emit_min(c, inst);
+ break;
+ case TGSI_OPCODE_DDX:
+ emit_ddx(c, inst);
+ break;
+ case TGSI_OPCODE_DDY:
+ emit_ddy(c, inst);
+ break;
+ case TGSI_OPCODE_SLT:
+ emit_sop(c, inst, BRW_CONDITIONAL_L);
+ break;
+ case TGSI_OPCODE_SLE:
+ emit_sop(c, inst, BRW_CONDITIONAL_LE);
+ break;
+ case TGSI_OPCODE_SGT:
+ emit_sop(c, inst, BRW_CONDITIONAL_G);
+ break;
+ case TGSI_OPCODE_SGE:
+ emit_sop(c, inst, BRW_CONDITIONAL_GE);
+ break;
+ case TGSI_OPCODE_SEQ:
+ emit_sop(c, inst, BRW_CONDITIONAL_EQ);
+ break;
+ case TGSI_OPCODE_SNE:
+ emit_sop(c, inst, BRW_CONDITIONAL_NEQ);
+ break;
+ case TGSI_OPCODE_MUL:
+ emit_alu2(c, inst, BRW_OPCODE_MUL);
+ break;
+ case TGSI_OPCODE_POW:
+ emit_pow(c, inst);
+ break;
+ case TGSI_OPCODE_MAD:
+ emit_mad(c, inst);
+ break;
+ case TGSI_OPCODE_TEX:
+ emit_tex(c, inst);
+ break;
+ case TGSI_OPCODE_TXB:
+ emit_txb(c, inst);
+ break;
+ case TGSI_OPCODE_TEXKILL:
+ emit_kil(c);
+ break;
+ case TGSI_OPCODE_IF:
+ assert(c->if_insn < MAX_IFSN);
+ c->if_inst[c->if_insn++] = brw_IF(p, BRW_EXECUTE_8);
+ break;
+ case TGSI_OPCODE_ELSE:
+ c->if_inst[c->if_insn-1] = brw_ELSE(p, c->if_inst[c->if_insn-1]);
+ break;
+ case TGSI_OPCODE_ENDIF:
+ assert(c->if_insn > 0);
+ brw_ENDIF(p, c->if_inst[--c->if_insn]);
+ break;
+ case TGSI_OPCODE_BGNSUB:
+ case TGSI_OPCODE_ENDSUB:
+ break;
+ case TGSI_OPCODE_CAL:
+ brw_push_insn_state(p);
+ brw_set_mask_control(p, BRW_MASK_DISABLE);
+ brw_set_access_mode(p, BRW_ALIGN_1);
+ brw_ADD(p, deref_1ud(c->stack_index, 0), brw_ip_reg(), brw_imm_d(3*16));
+ brw_set_access_mode(p, BRW_ALIGN_16);
+ brw_ADD(p,
+ get_addr_reg(c->stack_index),
+ get_addr_reg(c->stack_index), brw_imm_d(4));
+// orig_inst = inst->Data;
+// orig_inst->Data = &p->store[p->nr_insn];
+ assert(0);
+ brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
+ brw_pop_insn_state(p);
+ break;
+
+ case TGSI_OPCODE_RET:
+#if 0
+ brw_push_insn_state(p);
+ brw_set_mask_control(p, BRW_MASK_DISABLE);
+ brw_ADD(p,
+ get_addr_reg(c->stack_index),
+ get_addr_reg(c->stack_index), brw_imm_d(-4));
+ brw_set_access_mode(p, BRW_ALIGN_1);
+ brw_MOV(p, brw_ip_reg(), deref_1ud(c->stack_index, 0));
+ brw_set_access_mode(p, BRW_ALIGN_16);
+ brw_pop_insn_state(p);
+#else
+ emit_fb_write(c, inst);
+#endif
+
+ break;
+ case TGSI_OPCODE_BGNFOR:
+ c->loop_inst[c->loop_insn++] = brw_DO(p, BRW_EXECUTE_8);
+ break;
+ case TGSI_OPCODE_BRK:
+ brw_BREAK(p);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ break;
+ case TGSI_OPCODE_CONT:
+ brw_CONT(p);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ break;
+ case TGSI_OPCODE_ENDFOR:
+ c->loop_insn--;
+ c->inst0 = c->inst1 = brw_WHILE(p, c->loop_inst[c->loop_insn]);
+ /* patch all the BREAK instructions from
+ last BGNFOR */
+ while (c->inst0 > c->loop_inst[c->loop_insn]) {
+ c->inst0--;
+ if (c->inst0->header.opcode == BRW_OPCODE_BREAK) {
+ c->inst0->bits3.if_else.jump_count = c->inst1 - c->inst0 + 1;
+ c->inst0->bits3.if_else.pop_count = 0;
+ } else if (c->inst0->header.opcode == BRW_OPCODE_CONTINUE) {
+ c->inst0->bits3.if_else.jump_count = c->inst1 - c->inst0;
+ c->inst0->bits3.if_else.pop_count = 0;
+ }
+ }
+ break;
+ case TGSI_OPCODE_END:
+ emit_fb_write(c, inst);
+ break;
+
+ default:
+ debug_printf("unsupported IR in fragment shader %d\n",
+ inst->Instruction.Opcode);
+ }
+#if 0
+ if (inst->CondUpdate)
+ brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+ else
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+#endif
+}
+
+
+
+
+
+
+void brw_wm_glsl_emit(struct brw_wm_compile *c)
+{
+ struct tgsi_parse_context parse;
+ struct brw_compile *p = &c->func;
+
+ brw_init_compile(&c->func);
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+
+ c->reg_index = 0;
+ c->if_insn = 0;
+ c->loop_insn = 0;
+ c->stack_index = brw_indirect(0,0);
+
+ /* Do static register allocation and parameter interpolation:
+ */
+ brw_wm_emit_decls( c );
+
+ /* Emit the actual program. All done with very direct translation,
+ * hopefully we can improve on this shortly...
+ */
+ brw_MOV(p, get_addr_reg(c->stack_index), brw_address(c->stack));
+
+ tgsi_parse_init( &parse, c->fp->program.tokens );
+
+ while( !tgsi_parse_end_of_tokens( &parse ) )
+ {
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ /* already done */
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ /* not handled yet */
+ assert(0);
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ brw_wm_emit_instruction(c, &parse.FullToken.FullInstruction);
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+
+ tgsi_parse_free (&parse);
+
+ /* Fix up call targets:
+ */
+#if 0
+ {
+ unsigned nr_insns = c->fp->program.Base.NumInstructions;
+ unsigned insn, target_insn;
+ struct tgsi_full_instruction *inst1, *inst2;
+ struct brw_instruction *brw_inst1, *brw_inst2;
+ int offset;
+ for (insn = 0; insn < nr_insns; insn++) {
+ inst1 = &c->fp->program.Base.Instructions[insn];
+ brw_inst1 = inst1->Data;
+ switch (inst1->Opcode) {
+ case TGSI_OPCODE_CAL:
+ target_insn = inst1->BranchTarget;
+ inst2 = &c->fp->program.Base.Instructions[target_insn];
+ brw_inst2 = inst2->Data;
+ offset = brw_inst2 - brw_inst1;
+ brw_set_src1(brw_inst1, brw_imm_d(offset*16));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+#endif
+
+ c->prog_data.total_grf = c->reg_index;
+ c->prog_data.total_scratch = 0;
+}
diff --git a/src/gallium/drivers/i965simple/brw_wm_iz.c b/src/gallium/drivers/i965simple/brw_wm_iz.c
new file mode 100644
index 0000000000..6c5f25bf39
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_wm_iz.c
@@ -0,0 +1,214 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_wm.h"
+
+
+#undef P /* prompted depth */
+#undef C /* computed */
+#undef N /* non-promoted? */
+
+#define P 0
+#define C 1
+#define N 2
+
+const struct {
+ unsigned mode:2;
+ unsigned sd_present:1;
+ unsigned sd_to_rt:1;
+ unsigned dd_present:1;
+ unsigned ds_present:1;
+} wm_iz_table[IZ_BIT_MAX] =
+{
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { C, 0, 1, 0, 0 },
+ { C, 0, 1, 0, 0 },
+ { C, 1, 1, 0, 0 },
+ { C, 1, 1, 0, 0 },
+ { C, 0, 1, 0, 0 },
+ { C, 0, 1, 0, 0 },
+ { C, 1, 1, 1, 0 },
+ { C, 1, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 1, 1, 1, 0 },
+ { C, 1, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { C, 0, 1, 0, 0 },
+ { C, 0, 1, 0, 0 },
+ { C, 1, 1, 0, 0 },
+ { C, 1, 1, 0, 0 },
+ { C, 0, 1, 0, 0 },
+ { C, 0, 1, 0, 0 },
+ { C, 1, 1, 1, 0 },
+ { C, 1, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 1, 1, 1, 0 },
+ { C, 1, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 0, 0, 0, 1 },
+ { C, 0, 0, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { C, 1, 1, 0, 1 },
+ { C, 1, 1, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { C, 1, 1, 1, 1 },
+ { C, 1, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 1, 1, 1, 1 },
+ { C, 1, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 0, 0, 0, 1 },
+ { C, 0, 0, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { C, 1, 1, 0, 1 },
+ { C, 1, 1, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { C, 1, 1, 1, 1 },
+ { C, 1, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 1, 1, 1, 1 },
+ { C, 1, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { N, 1, 1, 0, 0 },
+ { N, 0, 1, 0, 0 },
+ { N, 0, 1, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { P, 0, 0, 0, 0 },
+ { N, 1, 1, 0, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { N, 1, 1, 0, 0 },
+ { N, 0, 1, 0, 0 },
+ { N, 0, 1, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { P, 0, 0, 0, 0 },
+ { N, 1, 1, 0, 0 },
+ { C, 0, 1, 1, 0 },
+ { C, 0, 1, 1, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { N, 1, 1, 0, 1 },
+ { N, 0, 1, 0, 1 },
+ { N, 0, 1, 0, 1 },
+ { P, 0, 0, 0, 0 },
+ { P, 0, 0, 0, 0 },
+ { C, 0, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { P, 0, 0, 0, 0 },
+ { N, 1, 1, 0, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { P, 0, 0, 0, 0 },
+ { C, 0, 0, 0, 1 },
+ { P, 0, 0, 0, 0 },
+ { C, 0, 1, 0, 1 },
+ { P, 0, 0, 0, 0 },
+ { C, 1, 1, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { C, 0, 1, 0, 1 },
+ { P, 0, 0, 0, 0 },
+ { C, 1, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { P, 0, 0, 0, 0 },
+ { C, 1, 1, 1, 1 },
+ { C, 0, 1, 1, 1 },
+ { C, 0, 1, 1, 1 }
+};
+
+void brw_wm_lookup_iz( unsigned line_aa,
+ unsigned lookup,
+ struct brw_wm_prog_key *key )
+{
+ unsigned reg = 2;
+
+ assert (lookup < IZ_BIT_MAX);
+
+ if (lookup & IZ_PS_COMPUTES_DEPTH_BIT)
+ key->computes_depth = 1;
+
+ if (wm_iz_table[lookup].sd_present) {
+ key->source_depth_reg = reg;
+ reg += 2;
+ }
+
+ if (wm_iz_table[lookup].sd_to_rt)
+ key->source_depth_to_render_target = 1;
+
+ if (wm_iz_table[lookup].ds_present || line_aa != AA_NEVER) {
+ key->aa_dest_stencil_reg = reg;
+ key->runtime_check_aads_emit = (!wm_iz_table[lookup].ds_present &&
+ line_aa == AA_SOMETIMES);
+ reg++;
+ }
+
+ if (wm_iz_table[lookup].dd_present) {
+ key->dest_depth_reg = reg;
+ reg+=2;
+ }
+
+ key->nr_depth_regs = (reg+1)/2;
+}
+
diff --git a/src/gallium/drivers/i965simple/brw_wm_sampler_state.c b/src/gallium/drivers/i965simple/brw_wm_sampler_state.c
new file mode 100644
index 0000000000..52b2909a65
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_wm_sampler_state.c
@@ -0,0 +1,275 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+
+#define COMPAREFUNC_ALWAYS 0
+#define COMPAREFUNC_NEVER 0x1
+#define COMPAREFUNC_LESS 0x2
+#define COMPAREFUNC_EQUAL 0x3
+#define COMPAREFUNC_LEQUAL 0x4
+#define COMPAREFUNC_GREATER 0x5
+#define COMPAREFUNC_NOTEQUAL 0x6
+#define COMPAREFUNC_GEQUAL 0x7
+
+/* Samplers aren't strictly wm state from the hardware's perspective,
+ * but that is the only situation in which we use them in this driver.
+ */
+
+static int intel_translate_shadow_compare_func(unsigned func)
+{
+ switch(func) {
+ case PIPE_FUNC_NEVER:
+ return COMPAREFUNC_ALWAYS;
+ case PIPE_FUNC_LESS:
+ return COMPAREFUNC_LEQUAL;
+ case PIPE_FUNC_LEQUAL:
+ return COMPAREFUNC_LESS;
+ case PIPE_FUNC_GREATER:
+ return COMPAREFUNC_GEQUAL;
+ case PIPE_FUNC_GEQUAL:
+ return COMPAREFUNC_GREATER;
+ case PIPE_FUNC_NOTEQUAL:
+ return COMPAREFUNC_EQUAL;
+ case PIPE_FUNC_EQUAL:
+ return COMPAREFUNC_NOTEQUAL;
+ case PIPE_FUNC_ALWAYS:
+ return COMPAREFUNC_NEVER;
+ }
+
+ debug_printf("Unknown value in %s: %x\n", __FUNCTION__, func);
+ return COMPAREFUNC_NEVER;
+}
+
+/* The brw (and related graphics cores) do not support GL_CLAMP. The
+ * Intel drivers for "other operating systems" implement GL_CLAMP as
+ * GL_CLAMP_TO_EDGE, so the same is done here.
+ */
+static unsigned translate_wrap_mode( int wrap )
+{
+ switch( wrap ) {
+ case PIPE_TEX_WRAP_REPEAT:
+ return BRW_TEXCOORDMODE_WRAP;
+ case PIPE_TEX_WRAP_CLAMP:
+ return BRW_TEXCOORDMODE_CLAMP;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ return BRW_TEXCOORDMODE_CLAMP; /* conform likes it this way */
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ return BRW_TEXCOORDMODE_CLAMP_BORDER;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ return BRW_TEXCOORDMODE_MIRROR;
+ default:
+ return BRW_TEXCOORDMODE_WRAP;
+ }
+}
+
+
+static unsigned U_FIXED(float value, unsigned frac_bits)
+{
+ value *= (1<<frac_bits);
+ return value < 0 ? 0 : value;
+}
+
+static int S_FIXED(float value, unsigned frac_bits)
+{
+ return value * (1<<frac_bits);
+}
+
+
+static unsigned upload_default_color( struct brw_context *brw,
+ const float *color )
+{
+ struct brw_sampler_default_color sdc;
+
+ COPY_4V(sdc.color, color);
+
+ return brw_cache_data( &brw->cache[BRW_SAMPLER_DEFAULT_COLOR], &sdc );
+}
+
+
+/*
+ */
+static void brw_update_sampler_state( const struct pipe_sampler_state *pipe_sampler,
+ unsigned sdc_gs_offset,
+ struct brw_sampler_state *sampler)
+{
+ memset(sampler, 0, sizeof(*sampler));
+
+ switch (pipe_sampler->min_mip_filter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_ANISO:
+ sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
+ break;
+ default:
+ break;
+ }
+
+ switch (pipe_sampler->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
+ break;
+ default:
+ break;
+ }
+ /* Set Anisotropy:
+ */
+ switch (pipe_sampler->mag_img_filter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_ANISO:
+ sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
+ break;
+ default:
+ break;
+ }
+
+ if (pipe_sampler->max_anisotropy > 2.0) {
+ sampler->ss3.max_aniso = MAX2((pipe_sampler->max_anisotropy - 2) / 2,
+ BRW_ANISORATIO_16);
+ }
+
+ sampler->ss1.s_wrap_mode = translate_wrap_mode(pipe_sampler->wrap_s);
+ sampler->ss1.r_wrap_mode = translate_wrap_mode(pipe_sampler->wrap_r);
+ sampler->ss1.t_wrap_mode = translate_wrap_mode(pipe_sampler->wrap_t);
+
+ /* Fulsim complains if I don't do this. Hardware doesn't mind:
+ */
+#if 0
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP_ARB) {
+ sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ }
+#endif
+
+ /* Set shadow function:
+ */
+ if (pipe_sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ /* Shadowing is "enabled" by emitting a particular sampler
+ * message (sample_c). So need to recompile WM program when
+ * shadow comparison is enabled on each/any texture unit.
+ */
+ sampler->ss0.shadow_function = intel_translate_shadow_compare_func(pipe_sampler->compare_func);
+ }
+
+ /* Set LOD bias:
+ */
+ sampler->ss0.lod_bias = S_FIXED(CLAMP(pipe_sampler->lod_bias, -16, 15), 6);
+
+ sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
+ sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
+
+ /* Set BaseMipLevel, MaxLOD, MinLOD:
+ *
+ * XXX: I don't think that using firstLevel, lastLevel works,
+ * because we always setup the surface state as if firstLevel ==
+ * level zero. Probably have to subtract firstLevel from each of
+ * these:
+ */
+ sampler->ss0.base_level = U_FIXED(0, 1);
+
+ sampler->ss1.max_lod = U_FIXED(MIN2(MAX2(pipe_sampler->max_lod, 0), 13), 6);
+ sampler->ss1.min_lod = U_FIXED(MIN2(MAX2(pipe_sampler->min_lod, 0), 13), 6);
+
+ sampler->ss2.default_color_pointer = sdc_gs_offset >> 5;
+}
+
+
+
+/* All samplers must be uploaded in a single contiguous array, which
+ * complicates various things. However, this is still too confusing -
+ * FIXME: simplify all the different new texture state flags.
+ */
+static void upload_wm_samplers(struct brw_context *brw)
+{
+ unsigned unit;
+ unsigned sampler_count = 0;
+
+ /* BRW_NEW_SAMPLER */
+ for (unit = 0; unit < brw->num_textures && unit < brw->num_samplers;
+ unit++) {
+ /* determine unit enable/disable by looking for a bound texture */
+ if (brw->attribs.Texture[unit]) {
+ const struct pipe_sampler_state *sampler = brw->attribs.Samplers[unit];
+ unsigned sdc_gs_offset = upload_default_color(brw, sampler->border_color);
+
+ brw_update_sampler_state(sampler,
+ sdc_gs_offset,
+ &brw->wm.sampler[unit]);
+
+ sampler_count = unit + 1;
+ }
+ }
+
+ if (brw->wm.sampler_count != sampler_count) {
+ brw->wm.sampler_count = sampler_count;
+ brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
+ }
+
+ brw->wm.sampler_gs_offset = 0;
+
+ if (brw->wm.sampler_count)
+ brw->wm.sampler_gs_offset =
+ brw_cache_data_sz(&brw->cache[BRW_SAMPLER],
+ brw->wm.sampler,
+ sizeof(struct brw_sampler_state) * brw->wm.sampler_count);
+}
+
+const struct brw_tracked_state brw_wm_samplers = {
+ .dirty = {
+ .brw = BRW_NEW_SAMPLER,
+ .cache = 0
+ },
+ .update = upload_wm_samplers
+};
+
diff --git a/src/gallium/drivers/i965simple/brw_wm_state.c b/src/gallium/drivers/i965simple/brw_wm_state.c
new file mode 100644
index 0000000000..37a9bf919c
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_wm_state.c
@@ -0,0 +1,195 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+#include "brw_wm.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+/***********************************************************************
+ * WM unit - fragment programs and rasterization
+ */
+static void upload_wm_unit(struct brw_context *brw )
+{
+ struct brw_wm_unit_state wm;
+ unsigned max_threads;
+ unsigned per_thread;
+
+ if (BRW_DEBUG & DEBUG_SINGLE_THREAD)
+ max_threads = 0;
+ else
+ max_threads = 31;
+
+
+ memset(&wm, 0, sizeof(wm));
+
+ /* CACHE_NEW_WM_PROG */
+ wm.thread0.grf_reg_count = align(brw->wm.prog_data->total_grf, 16) / 16 - 1;
+ wm.thread0.kernel_start_pointer = brw->wm.prog_gs_offset >> 6;
+ wm.thread3.dispatch_grf_start_reg = brw->wm.prog_data->first_curbe_grf;
+ wm.thread3.urb_entry_read_length = brw->wm.prog_data->urb_read_length;
+ wm.thread3.const_urb_entry_read_length = brw->wm.prog_data->curb_read_length;
+
+ wm.wm5.max_threads = max_threads;
+
+ per_thread = align(brw->wm.prog_data->total_scratch, 1024);
+ assert(per_thread <= 12 * 1024);
+
+#if 0
+ if (brw->wm.prog_data->total_scratch) {
+ unsigned total = per_thread * (max_threads + 1);
+
+ /* Scratch space -- just have to make sure there is sufficient
+ * allocated for the active program and current number of threads.
+ */
+ brw->wm.scratch_buffer_size = total;
+ if (brw->wm.scratch_buffer &&
+ brw->wm.scratch_buffer_size > brw->wm.scratch_buffer->size) {
+ dri_bo_unreference(brw->wm.scratch_buffer);
+ brw->wm.scratch_buffer = NULL;
+ }
+ if (!brw->wm.scratch_buffer) {
+ brw->wm.scratch_buffer = dri_bo_alloc(intel->intelScreen->bufmgr,
+ "wm scratch",
+ brw->wm.scratch_buffer_size,
+ 4096, DRM_BO_FLAG_MEM_TT);
+ }
+ }
+ /* XXX: Scratch buffers are not implemented correectly.
+ *
+ * The scratch offset to be programmed into wm is relative to the general
+ * state base address. However, using dri_bo_alloc/dri_bo_emit_reloc (or
+ * the previous bmGenBuffers scheme), we get an offset relative to the
+ * start of framebuffer. Even before then, it was broken in other ways,
+ * so just fail for now if we hit that path.
+ */
+ assert(brw->wm.prog_data->total_scratch == 0);
+#endif
+
+ /* CACHE_NEW_SURFACE */
+ wm.thread1.binding_table_entry_count = brw->wm.nr_surfaces;
+
+ /* BRW_NEW_CURBE_OFFSETS */
+ wm.thread3.const_urb_entry_read_offset = brw->curbe.wm_start * 2;
+
+ wm.thread3.urb_entry_read_offset = 0;
+ wm.thread1.depth_coef_urb_read_offset = 1;
+ wm.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
+
+ /* CACHE_NEW_SAMPLER */
+ wm.wm4.sampler_count = (brw->wm.sampler_count + 1) / 4;
+ wm.wm4.sampler_state_pointer = brw->wm.sampler_gs_offset >> 5;
+
+ /* BRW_NEW_FRAGMENT_PROGRAM */
+ {
+ const struct brw_fragment_program *fp = brw->attribs.FragmentProgram;
+
+ if (fp->UsesDepth)
+ wm.wm5.program_uses_depth = 1; /* as far as we can tell */
+
+ if (fp->info.writes_z)
+ wm.wm5.program_computes_depth = 1;
+
+ /* BRW_NEW_ALPHA_TEST */
+ if (fp->info.uses_kill ||
+ brw->attribs.DepthStencil->alpha.enabled)
+ wm.wm5.program_uses_killpixel = 1;
+
+ wm.wm5.enable_8_pix = 1;
+ }
+
+ wm.wm5.thread_dispatch_enable = 1; /* AKA: color_write */
+ wm.wm5.legacy_line_rast = 0;
+ wm.wm5.legacy_global_depth_bias = 0;
+ wm.wm5.early_depth_test = 1; /* never need to disable */
+ wm.wm5.line_aa_region_width = 0;
+ wm.wm5.line_endcap_aa_region_width = 1;
+
+ /* BRW_NEW_RASTERIZER */
+ if (brw->attribs.Raster->poly_stipple_enable)
+ wm.wm5.polygon_stipple = 1;
+
+#if 0
+ if (brw->attribs.Polygon->OffsetFill) {
+ wm.wm5.depth_offset = 1;
+ /* Something wierd going on with legacy_global_depth_bias,
+ * offset_constant, scaling and MRD. This value passes glean
+ * but gives some odd results elsewere (eg. the
+ * quad-offset-units test).
+ */
+ wm.global_depth_offset_constant = brw->attribs.Polygon->OffsetUnits * 2;
+
+ /* This is the only value that passes glean:
+ */
+ wm.global_depth_offset_scale = brw->attribs.Polygon->OffsetFactor;
+ }
+#endif
+
+ if (brw->attribs.Raster->line_stipple_enable) {
+ wm.wm5.line_stipple = 1;
+ }
+
+ if (BRW_DEBUG & DEBUG_STATS)
+ wm.wm4.stats_enable = 1;
+
+ brw->wm.state_gs_offset = brw_cache_data( &brw->cache[BRW_WM_UNIT], &wm );
+
+ if (brw->wm.prog_data->total_scratch) {
+ /*
+ dri_emit_reloc(brw->cache[BRW_WM_UNIT].pool->buffer,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
+ (per_thread / 1024) - 1,
+ brw->wm.state_gs_offset +
+ ((char *)&wm.thread2 - (char *)&wm),
+ brw->wm.scratch_buffer);
+ */
+ } else {
+ wm.thread2.scratch_space_base_pointer = 0;
+ }
+}
+
+const struct brw_tracked_state brw_wm_unit = {
+ .dirty = {
+ .brw = (BRW_NEW_RASTERIZER |
+ BRW_NEW_ALPHA_TEST |
+ BRW_NEW_FS |
+ BRW_NEW_CURBE_OFFSETS),
+
+ .cache = (CACHE_NEW_SURFACE |
+ CACHE_NEW_WM_PROG |
+ CACHE_NEW_SAMPLER)
+ },
+ .update = upload_wm_unit
+};
+
diff --git a/src/gallium/drivers/i965simple/brw_wm_surface_state.c b/src/gallium/drivers/i965simple/brw_wm_surface_state.c
new file mode 100644
index 0000000000..b5b9e0e702
--- /dev/null
+++ b/src/gallium/drivers/i965simple/brw_wm_surface_state.c
@@ -0,0 +1,305 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+
+static unsigned translate_tex_target( enum pipe_texture_target target )
+{
+ switch (target) {
+ case PIPE_TEXTURE_1D:
+ return BRW_SURFACE_1D;
+
+ case PIPE_TEXTURE_2D:
+ return BRW_SURFACE_2D;
+
+ case PIPE_TEXTURE_3D:
+ return BRW_SURFACE_3D;
+
+ case PIPE_TEXTURE_CUBE:
+ return BRW_SURFACE_CUBE;
+
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static unsigned translate_tex_format( enum pipe_format pipe_format )
+{
+ switch( pipe_format ) {
+ case PIPE_FORMAT_L8_UNORM:
+ return BRW_SURFACEFORMAT_L8_UNORM;
+
+ case PIPE_FORMAT_I8_UNORM:
+ return BRW_SURFACEFORMAT_I8_UNORM;
+
+ case PIPE_FORMAT_A8_UNORM:
+ return BRW_SURFACEFORMAT_A8_UNORM;
+
+ case PIPE_FORMAT_A8L8_UNORM:
+ return BRW_SURFACEFORMAT_L8A8_UNORM;
+
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ assert(0); /* not supported for sampling */
+ return BRW_SURFACEFORMAT_R8G8B8_UNORM;
+
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ return BRW_SURFACEFORMAT_R8G8B8A8_UNORM;
+
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return BRW_SURFACEFORMAT_B5G6R5_UNORM;
+
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ return BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
+
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ return BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
+
+ case PIPE_FORMAT_YCBCR_REV:
+ return BRW_SURFACEFORMAT_YCRCB_NORMAL;
+
+ case PIPE_FORMAT_YCBCR:
+ return BRW_SURFACEFORMAT_YCRCB_SWAPUVY;
+#if 0
+ case PIPE_FORMAT_RGB_FXT1:
+ case PIPE_FORMAT_RGBA_FXT1:
+ return BRW_SURFACEFORMAT_FXT1;
+#endif
+
+ case PIPE_FORMAT_Z16_UNORM:
+ return BRW_SURFACEFORMAT_I16_UNORM;
+#if 0
+ case PIPE_FORMAT_RGB_DXT1:
+ return BRW_SURFACEFORMAT_DXT1_RGB;
+
+ case PIPE_FORMAT_RGBA_DXT1:
+ return BRW_SURFACEFORMAT_BC1_UNORM;
+
+ case PIPE_FORMAT_RGBA_DXT3:
+ return BRW_SURFACEFORMAT_BC2_UNORM;
+
+ case PIPE_FORMAT_RGBA_DXT5:
+ return BRW_SURFACEFORMAT_BC3_UNORM;
+
+ case PIPE_FORMAT_SRGBA8:
+ return BRW_SURFACEFORMAT_R8G8B8A8_UNORM_SRGB;
+ case PIPE_FORMAT_SRGB_DXT1:
+ return BRW_SURFACEFORMAT_BC1_UNORM_SRGB;
+#endif
+
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static unsigned brw_buffer_offset(struct brw_context *brw,
+ struct pipe_buffer *buffer)
+{
+ return brw->winsys->get_buffer_offset(brw->winsys,
+ buffer,
+ 0);
+}
+
+static
+void brw_update_texture_surface( struct brw_context *brw,
+ unsigned unit )
+{
+ const struct brw_texture *tObj = brw->attribs.Texture[unit];
+ struct brw_surface_state surf;
+
+ memset(&surf, 0, sizeof(surf));
+
+ surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
+ surf.ss0.surface_type = translate_tex_target(tObj->base.target);
+ surf.ss0.surface_format = translate_tex_format(tObj->base.format);
+
+ /* This is ok for all textures with channel width 8bit or less:
+ */
+/* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
+
+ /* Updated in emit_reloc */
+ surf.ss1.base_addr = brw_buffer_offset( brw, tObj->buffer );
+
+ surf.ss2.mip_count = tObj->base.last_level;
+ surf.ss2.width = tObj->base.width[0] - 1;
+ surf.ss2.height = tObj->base.height[0] - 1;
+
+ surf.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
+ surf.ss3.tiled_surface = 0; /* always zero */
+ surf.ss3.pitch = tObj->stride - 1;
+ surf.ss3.depth = tObj->base.depth[0] - 1;
+
+ surf.ss4.min_lod = 0;
+
+ if (tObj->base.target == PIPE_TEXTURE_CUBE) {
+ 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;
+ }
+
+ brw->wm.bind.surf_ss_offset[unit + 1] =
+ brw_cache_data( &brw->cache[BRW_SS_SURFACE], &surf );
+}
+
+
+
+#define OFFSET(TYPE, FIELD) ( (unsigned)&(((TYPE *)0)->FIELD) )
+
+
+static void upload_wm_surfaces(struct brw_context *brw )
+{
+ unsigned i;
+
+ {
+ struct brw_surface_state surf;
+
+ /* BRW_NEW_FRAMEBUFFER
+ */
+ struct pipe_surface *pipe_surface = brw->attribs.FrameBuffer.cbufs[0];/*fixme*/
+ struct brw_texture *tex = (struct brw_texture *)pipe_surface->texture;
+
+ memset(&surf, 0, sizeof(surf));
+
+ if (pipe_surface != NULL) {
+ if (pipe_surface->block.size == 4)
+ surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+ else
+ surf.ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+
+ surf.ss0.surface_type = BRW_SURFACE_2D;
+
+ surf.ss1.base_addr = brw_buffer_offset( brw, tex->buffer );
+
+ surf.ss2.width = pipe_surface->width - 1;
+ surf.ss2.height = pipe_surface->height - 1;
+ surf.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
+ surf.ss3.tiled_surface = 0;
+ surf.ss3.pitch = pipe_surface->stride - 1;
+ } else {
+ surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+ surf.ss0.surface_type = BRW_SURFACE_NULL;
+ }
+
+ /* BRW_NEW_BLEND */
+ surf.ss0.color_blend = (!brw->attribs.Blend->logicop_enable &&
+ brw->attribs.Blend->blend_enable);
+
+
+ surf.ss0.writedisable_red = !(brw->attribs.Blend->colormask & PIPE_MASK_R);
+ surf.ss0.writedisable_green = !(brw->attribs.Blend->colormask & PIPE_MASK_G);
+ surf.ss0.writedisable_blue = !(brw->attribs.Blend->colormask & PIPE_MASK_B);
+ surf.ss0.writedisable_alpha = !(brw->attribs.Blend->colormask & PIPE_MASK_A);
+
+
+
+
+ brw->wm.bind.surf_ss_offset[0] = brw_cache_data( &brw->cache[BRW_SS_SURFACE], &surf );
+
+ brw->wm.nr_surfaces = 1;
+ }
+
+
+ /* BRW_NEW_TEXTURE
+ */
+ for (i = 0; i < brw->num_textures && i < brw->num_samplers; i++) {
+ const struct brw_texture *texUnit = brw->attribs.Texture[i];
+
+ if (texUnit &&
+ texUnit->base.reference.count/*(texUnit->reference.count > 0) == really used */) {
+
+ brw_update_texture_surface(brw, i);
+
+ brw->wm.nr_surfaces = i+2;
+ }
+ else {
+ brw->wm.bind.surf_ss_offset[i+1] = 0;
+ }
+ }
+
+ brw->wm.bind_ss_offset = brw_cache_data( &brw->cache[BRW_SS_SURF_BIND],
+ &brw->wm.bind );
+}
+
+
+/* KW: Will find a different way to acheive this, see for example the
+ * state caches with relocs in the i915 swz driver.
+ */
+#if 0
+static void emit_reloc_wm_surfaces(struct brw_context *brw)
+{
+ int unit;
+
+ if (brw->state.draw_region != NULL) {
+ /* Emit framebuffer relocation */
+ dri_emit_reloc(brw_cache_buffer(brw, BRW_SS_SURFACE),
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
+ 0,
+ brw->wm.bind.surf_ss_offset[0] +
+ offsetof(struct brw_surface_state, ss1),
+ brw->state.draw_region->buffer);
+ }
+
+ /* Emit relocations for texture buffers */
+ for (unit = 0; unit < BRW_MAX_TEX_UNIT; unit++) {
+ struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[unit];
+ struct gl_texture_object *tObj = texUnit->_Current;
+ struct intel_texture_object *intelObj = intel_texture_object(tObj);
+
+ if (texUnit->_ReallyEnabled && intelObj->mt != NULL) {
+ dri_emit_reloc(brw_cache_buffer(brw, BRW_SS_SURFACE),
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ 0,
+ brw->wm.bind.surf_ss_offset[unit + 1] +
+ offsetof(struct brw_surface_state, ss1),
+ intelObj->mt->region->buffer);
+ }
+ }
+}
+#endif
+
+const struct brw_tracked_state brw_wm_surfaces = {
+ .dirty = {
+ .brw = (BRW_NEW_FRAMEBUFFER |
+ BRW_NEW_BLEND |
+ BRW_NEW_TEXTURE),
+ .cache = 0
+ },
+ .update = upload_wm_surfaces,
+};
diff --git a/src/gallium/drivers/identity/Makefile b/src/gallium/drivers/identity/Makefile
new file mode 100644
index 0000000000..e32b9102e5
--- /dev/null
+++ b/src/gallium/drivers/identity/Makefile
@@ -0,0 +1,12 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = identity
+
+C_SOURCES = \
+ id_objects.c \
+ id_context.c \
+ id_screen.c \
+ id_drm.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/identity/SConscript b/src/gallium/drivers/identity/SConscript
new file mode 100644
index 0000000000..7f079dd0a8
--- /dev/null
+++ b/src/gallium/drivers/identity/SConscript
@@ -0,0 +1,13 @@
+Import('*')
+
+env = env.Clone()
+
+identity = env.ConvenienceLibrary(
+ target = 'identity',
+ source = [
+ 'id_screen.c',
+ 'id_context.c',
+ 'id_objects.c',
+ ])
+
+Export('identity')
diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c
new file mode 100644
index 0000000000..4e700089e3
--- /dev/null
+++ b/src/gallium/drivers/identity/id_context.c
@@ -0,0 +1,719 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_context.h"
+#include "util/u_memory.h"
+
+#include "id_public.h"
+#include "id_context.h"
+#include "id_objects.h"
+
+
+static void
+identity_destroy(struct pipe_context *_pipe)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->destroy(pipe);
+
+ free(id_pipe);
+}
+
+static void
+identity_set_edgeflags(struct pipe_context *_pipe,
+ const unsigned *bitfield)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->set_edgeflags(pipe,
+ bitfield);
+}
+
+static boolean
+identity_draw_arrays(struct pipe_context *_pipe,
+ unsigned prim,
+ unsigned start,
+ unsigned count)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ return pipe->draw_arrays(pipe,
+ prim,
+ start,
+ count);
+}
+
+static boolean
+identity_draw_elements(struct pipe_context *_pipe,
+ struct pipe_buffer *_indexBuffer,
+ unsigned indexSize,
+ unsigned prim,
+ unsigned start,
+ unsigned count)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct identity_buffer *id_buffer = identity_buffer(_indexBuffer);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_buffer *indexBuffer = id_buffer->buffer;
+
+ return pipe->draw_elements(pipe,
+ indexBuffer,
+ indexSize,
+ prim,
+ start,
+ count);
+}
+
+static boolean
+identity_draw_range_elements(struct pipe_context *_pipe,
+ struct pipe_buffer *_indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct identity_buffer *id_buffer = identity_buffer(_indexBuffer);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_buffer *indexBuffer = id_buffer->buffer;
+
+ return pipe->draw_range_elements(pipe,
+ indexBuffer,
+ indexSize,
+ minIndex,
+ maxIndex,
+ mode,
+ start,
+ count);
+}
+
+static struct pipe_query *
+identity_create_query(struct pipe_context *_pipe,
+ unsigned query_type)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ return pipe->create_query(pipe,
+ query_type);
+}
+
+static void
+identity_destroy_query(struct pipe_context *_pipe,
+ struct pipe_query *query)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->destroy_query(pipe,
+ query);
+}
+
+static void
+identity_begin_query(struct pipe_context *_pipe,
+ struct pipe_query *query)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->begin_query(pipe,
+ query);
+}
+
+static void
+identity_end_query(struct pipe_context *_pipe,
+ struct pipe_query *query)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->end_query(pipe,
+ query);
+}
+
+static boolean
+identity_get_query_result(struct pipe_context *_pipe,
+ struct pipe_query *query,
+ boolean wait,
+ uint64_t *result)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ return pipe->get_query_result(pipe,
+ query,
+ wait,
+ result);
+}
+
+static void *
+identity_create_blend_state(struct pipe_context *_pipe,
+ const struct pipe_blend_state *blend)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ return pipe->create_blend_state(pipe,
+ blend);
+}
+
+static void
+identity_bind_blend_state(struct pipe_context *_pipe,
+ void *blend)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->bind_blend_state(pipe,
+ blend);
+}
+
+static void
+identity_delete_blend_state(struct pipe_context *_pipe,
+ void *blend)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->delete_blend_state(pipe,
+ blend);
+}
+
+static void *
+identity_create_sampler_state(struct pipe_context *_pipe,
+ const struct pipe_sampler_state *sampler)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ return pipe->create_sampler_state(pipe,
+ sampler);
+}
+
+static void
+identity_bind_sampler_states(struct pipe_context *_pipe,
+ unsigned num,
+ void **samplers)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->bind_sampler_states(pipe,
+ num,
+ samplers);
+}
+
+static void
+identity_delete_sampler_state(struct pipe_context *_pipe,
+ void *sampler)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->delete_sampler_state(pipe,
+ sampler);
+}
+
+static void *
+identity_create_rasterizer_state(struct pipe_context *_pipe,
+ const struct pipe_rasterizer_state *rasterizer)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ return pipe->create_rasterizer_state(pipe,
+ rasterizer);
+}
+
+static void
+identity_bind_rasterizer_state(struct pipe_context *_pipe,
+ void *rasterizer)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->bind_rasterizer_state(pipe,
+ rasterizer);
+}
+
+static void
+identity_delete_rasterizer_state(struct pipe_context *_pipe,
+ void *rasterizer)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->delete_rasterizer_state(pipe,
+ rasterizer);
+}
+
+static void *
+identity_create_depth_stencil_alpha_state(struct pipe_context *_pipe,
+ const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ return pipe->create_depth_stencil_alpha_state(pipe,
+ depth_stencil_alpha);
+}
+
+static void
+identity_bind_depth_stencil_alpha_state(struct pipe_context *_pipe,
+ void *depth_stencil_alpha)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->bind_depth_stencil_alpha_state(pipe,
+ depth_stencil_alpha);
+}
+
+static void
+identity_delete_depth_stencil_alpha_state(struct pipe_context *_pipe,
+ void *depth_stencil_alpha)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->delete_depth_stencil_alpha_state(pipe,
+ depth_stencil_alpha);
+}
+
+static void *
+identity_create_fs_state(struct pipe_context *_pipe,
+ const struct pipe_shader_state *fs)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ return pipe->create_fs_state(pipe,
+ fs);
+}
+
+static void
+identity_bind_fs_state(struct pipe_context *_pipe,
+ void *fs)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->bind_fs_state(pipe,
+ fs);
+}
+
+static void
+identity_delete_fs_state(struct pipe_context *_pipe,
+ void *fs)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->delete_fs_state(pipe,
+ fs);
+}
+
+static void *
+identity_create_vs_state(struct pipe_context *_pipe,
+ const struct pipe_shader_state *vs)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ return pipe->create_vs_state(pipe,
+ vs);
+}
+
+static void
+identity_bind_vs_state(struct pipe_context *_pipe,
+ void *vs)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->bind_vs_state(pipe,
+ vs);
+}
+
+static void
+identity_delete_vs_state(struct pipe_context *_pipe,
+ void *vs)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->delete_vs_state(pipe,
+ vs);
+}
+
+static void
+identity_set_blend_color(struct pipe_context *_pipe,
+ const struct pipe_blend_color *blend_color)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->set_blend_color(pipe,
+ blend_color);
+}
+
+static void
+identity_set_clip_state(struct pipe_context *_pipe,
+ const struct pipe_clip_state *clip)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->set_clip_state(pipe,
+ clip);
+}
+
+static void
+identity_set_constant_buffer(struct pipe_context *_pipe,
+ uint shader,
+ uint index,
+ const struct pipe_constant_buffer *_buffer)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_constant_buffer unwrapped_buffer;
+ struct pipe_constant_buffer *buffer = NULL;
+
+ /* unwrap the input state */
+ if (_buffer) {
+ unwrapped_buffer.buffer = identity_buffer_unwrap(_buffer->buffer);
+ buffer = &unwrapped_buffer;
+ }
+
+ pipe->set_constant_buffer(pipe,
+ shader,
+ index,
+ buffer);
+}
+
+static void
+identity_set_framebuffer_state(struct pipe_context *_pipe,
+ const struct pipe_framebuffer_state *_state)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_framebuffer_state unwrapped_state;
+ struct pipe_framebuffer_state *state = NULL;
+ unsigned i;
+
+ /* unwrap the input state */
+ if (_state) {
+ memcpy(&unwrapped_state, _state, sizeof(unwrapped_state));
+ for(i = 0; i < _state->nr_cbufs; i++)
+ unwrapped_state.cbufs[i] = identity_surface_unwrap(_state->cbufs[i]);
+ for (; i < PIPE_MAX_COLOR_BUFS; i++)
+ unwrapped_state.cbufs[i] = NULL;
+ unwrapped_state.zsbuf = identity_surface_unwrap(_state->zsbuf);
+ state = &unwrapped_state;
+ }
+
+ pipe->set_framebuffer_state(pipe,
+ state);
+}
+
+static void
+identity_set_polygon_stipple(struct pipe_context *_pipe,
+ const struct pipe_poly_stipple *poly_stipple)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->set_polygon_stipple(pipe,
+ poly_stipple);
+}
+
+static void
+identity_set_scissor_state(struct pipe_context *_pipe,
+ const struct pipe_scissor_state *scissor)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->set_scissor_state(pipe,
+ scissor);
+}
+
+static void
+identity_set_viewport_state(struct pipe_context *_pipe,
+ const struct pipe_viewport_state *viewport)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->set_viewport_state(pipe,
+ viewport);
+}
+
+static void
+identity_set_sampler_textures(struct pipe_context *_pipe,
+ unsigned num_textures,
+ struct pipe_texture **_textures)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_texture *unwrapped_textures[PIPE_MAX_SAMPLERS];
+ struct pipe_texture **textures = NULL;
+ unsigned i;
+
+ if (_textures) {
+ for (i = 0; i < num_textures; i++)
+ unwrapped_textures[i] = identity_texture_unwrap(_textures[i]);
+ for (; i < PIPE_MAX_SAMPLERS; i++)
+ unwrapped_textures[i] = NULL;
+
+ textures = unwrapped_textures;
+ }
+
+ pipe->set_sampler_textures(pipe,
+ num_textures,
+ textures);
+}
+
+static void
+identity_set_vertex_buffers(struct pipe_context *_pipe,
+ unsigned num_buffers,
+ const struct pipe_vertex_buffer *_buffers)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_vertex_buffer unwrapped_buffers[PIPE_MAX_SHADER_INPUTS];
+ struct pipe_vertex_buffer *buffers = NULL;
+ unsigned i;
+
+ if (num_buffers) {
+ memcpy(unwrapped_buffers, _buffers, num_buffers * sizeof(*_buffers));
+ for (i = 0; i < num_buffers; i++)
+ unwrapped_buffers[i].buffer = identity_buffer_unwrap(_buffers[i].buffer);
+ buffers = unwrapped_buffers;
+ }
+
+ pipe->set_vertex_buffers(pipe,
+ num_buffers,
+ buffers);
+}
+
+static void
+identity_set_vertex_elements(struct pipe_context *_pipe,
+ unsigned num_elements,
+ const struct pipe_vertex_element *vertex_elements)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->set_vertex_elements(pipe,
+ num_elements,
+ vertex_elements);
+}
+
+static void
+identity_surface_copy(struct pipe_context *_pipe,
+ struct pipe_surface *_dst,
+ unsigned dstx,
+ unsigned dsty,
+ struct pipe_surface *_src,
+ unsigned srcx,
+ unsigned srcy,
+ unsigned width,
+ unsigned height)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct identity_surface *id_surface_dst = identity_surface(_dst);
+ struct identity_surface *id_surface_src = identity_surface(_src);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_surface *dst = id_surface_dst->surface;
+ struct pipe_surface *src = id_surface_src->surface;
+
+ pipe->surface_copy(pipe,
+ dst,
+ dstx,
+ dsty,
+ src,
+ srcx,
+ srcy,
+ width,
+ height);
+}
+
+static void
+identity_surface_fill(struct pipe_context *_pipe,
+ struct pipe_surface *_dst,
+ unsigned dstx,
+ unsigned dsty,
+ unsigned width,
+ unsigned height,
+ unsigned value)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct identity_surface *id_surface_dst = identity_surface(_dst);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_surface *dst = id_surface_dst->surface;
+
+ pipe->surface_fill(pipe,
+ dst,
+ dstx,
+ dsty,
+ width,
+ height,
+ value);
+}
+
+static void
+identity_clear(struct pipe_context *_pipe,
+ unsigned buffers,
+ const float *rgba,
+ double depth,
+ unsigned stencil)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->clear(pipe,
+ buffers,
+ rgba,
+ depth,
+ stencil);
+}
+
+static void
+identity_flush(struct pipe_context *_pipe,
+ unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct pipe_context *pipe = id_pipe->pipe;
+
+ pipe->flush(pipe,
+ flags,
+ fence);
+}
+
+static unsigned int
+identity_is_texture_referenced(struct pipe_context *_pipe,
+ struct pipe_texture *_texture,
+ unsigned face,
+ unsigned level)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct identity_texture *id_texture = identity_texture(_texture);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_texture *texture = id_texture->texture;
+
+ return pipe->is_texture_referenced(pipe,
+ texture,
+ face,
+ level);
+}
+
+static unsigned int
+identity_is_buffer_referenced(struct pipe_context *_pipe,
+ struct pipe_buffer *_buffer)
+{
+ struct identity_context *id_pipe = identity_context(_pipe);
+ struct identity_buffer *id_buffer = identity_buffer(_buffer);
+ struct pipe_context *pipe = id_pipe->pipe;
+ struct pipe_buffer *buffer = id_buffer->buffer;
+
+ return pipe->is_buffer_referenced(pipe,
+ buffer);
+}
+
+struct pipe_context *
+identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
+{
+ struct identity_context *id_pipe;
+ (void)identity_screen(_screen);
+
+ id_pipe = CALLOC_STRUCT(identity_context);
+ if (!id_pipe) {
+ return NULL;
+ }
+
+ id_pipe->base.winsys = NULL;
+ id_pipe->base.screen = _screen;
+ id_pipe->base.priv = pipe->priv;
+ id_pipe->base.draw = NULL;
+
+ id_pipe->base.destroy = identity_destroy;
+ id_pipe->base.set_edgeflags = identity_set_edgeflags;
+ id_pipe->base.draw_arrays = identity_draw_arrays;
+ id_pipe->base.draw_elements = identity_draw_elements;
+ id_pipe->base.draw_range_elements = identity_draw_range_elements;
+ id_pipe->base.create_query = identity_create_query;
+ id_pipe->base.destroy_query = identity_destroy_query;
+ id_pipe->base.begin_query = identity_begin_query;
+ id_pipe->base.end_query = identity_end_query;
+ id_pipe->base.get_query_result = identity_get_query_result;
+ id_pipe->base.create_blend_state = identity_create_blend_state;
+ id_pipe->base.bind_blend_state = identity_bind_blend_state;
+ id_pipe->base.delete_blend_state = identity_delete_blend_state;
+ id_pipe->base.create_sampler_state = identity_create_sampler_state;
+ id_pipe->base.bind_sampler_states = identity_bind_sampler_states;
+ id_pipe->base.delete_sampler_state = identity_delete_sampler_state;
+ id_pipe->base.create_rasterizer_state = identity_create_rasterizer_state;
+ id_pipe->base.bind_rasterizer_state = identity_bind_rasterizer_state;
+ id_pipe->base.delete_rasterizer_state = identity_delete_rasterizer_state;
+ id_pipe->base.create_depth_stencil_alpha_state = identity_create_depth_stencil_alpha_state;
+ id_pipe->base.bind_depth_stencil_alpha_state = identity_bind_depth_stencil_alpha_state;
+ id_pipe->base.delete_depth_stencil_alpha_state = identity_delete_depth_stencil_alpha_state;
+ id_pipe->base.create_fs_state = identity_create_fs_state;
+ id_pipe->base.bind_fs_state = identity_bind_fs_state;
+ id_pipe->base.delete_fs_state = identity_delete_fs_state;
+ id_pipe->base.create_vs_state = identity_create_vs_state;
+ id_pipe->base.bind_vs_state = identity_bind_vs_state;
+ id_pipe->base.delete_vs_state = identity_delete_vs_state;
+ id_pipe->base.set_blend_color = identity_set_blend_color;
+ id_pipe->base.set_clip_state = identity_set_clip_state;
+ id_pipe->base.set_constant_buffer = identity_set_constant_buffer;
+ id_pipe->base.set_framebuffer_state = identity_set_framebuffer_state;
+ id_pipe->base.set_polygon_stipple = identity_set_polygon_stipple;
+ id_pipe->base.set_scissor_state = identity_set_scissor_state;
+ id_pipe->base.set_viewport_state = identity_set_viewport_state;
+ id_pipe->base.set_sampler_textures = identity_set_sampler_textures;
+ id_pipe->base.set_vertex_buffers = identity_set_vertex_buffers;
+ id_pipe->base.set_vertex_elements = identity_set_vertex_elements;
+ id_pipe->base.surface_copy = identity_surface_copy;
+ id_pipe->base.surface_fill = identity_surface_fill;
+ id_pipe->base.clear = identity_clear;
+ id_pipe->base.flush = identity_flush;
+ id_pipe->base.is_texture_referenced = identity_is_texture_referenced;
+ id_pipe->base.is_buffer_referenced = identity_is_buffer_referenced;
+
+ id_pipe->pipe = pipe;
+
+ return &id_pipe->base;
+}
diff --git a/src/gallium/drivers/identity/id_context.h b/src/gallium/drivers/identity/id_context.h
new file mode 100644
index 0000000000..75b73fc7df
--- /dev/null
+++ b/src/gallium/drivers/identity/id_context.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ID_CONTEXT_H
+#define ID_CONTEXT_H
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+
+
+struct identity_context {
+ struct pipe_context base; /**< base class */
+
+ struct pipe_context *pipe;
+};
+
+
+static INLINE struct identity_context *
+identity_context(struct pipe_context *pipe)
+{
+ return (struct identity_context *)pipe;
+}
+
+#endif /* ID_CONTEXT_H */
diff --git a/src/gallium/drivers/identity/id_drm.c b/src/gallium/drivers/identity/id_drm.c
new file mode 100644
index 0000000000..14f68ac0d0
--- /dev/null
+++ b/src/gallium/drivers/identity/id_drm.c
@@ -0,0 +1,173 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "state_tracker/drm_api.h"
+
+#include "util/u_memory.h"
+#include "identity/id_drm.h"
+#include "identity/id_screen.h"
+#include "identity/id_public.h"
+#include "identity/id_screen.h"
+#include "identity/id_objects.h"
+
+struct identity_drm_api
+{
+ struct drm_api base;
+
+ struct drm_api *api;
+};
+
+static INLINE struct identity_drm_api *
+identity_drm_api(struct drm_api *_api)
+{
+ return (struct identity_drm_api *)_api;
+}
+
+static struct pipe_screen *
+identity_drm_create_screen(struct drm_api *_api, int fd,
+ struct drm_create_screen_arg *arg)
+{
+ struct identity_drm_api *id_api = identity_drm_api(_api);
+ struct drm_api *api = id_api->api;
+ struct pipe_screen *screen;
+
+ if (arg && arg->mode != DRM_CREATE_NORMAL)
+ return NULL;
+
+ screen = api->create_screen(api, fd, arg);
+
+ return identity_screen_create(screen);
+}
+
+static struct pipe_context *
+identity_drm_create_context(struct drm_api *_api,
+ struct pipe_screen *_screen)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_drm_api *id_api = identity_drm_api(_api);
+ struct pipe_screen *screen = id_screen->screen;
+ struct drm_api *api = id_api->api;
+ struct pipe_context *pipe;
+
+ pipe = api->create_context(api, screen);
+
+ pipe = identity_context_create(_screen, pipe);
+
+ return pipe;
+}
+
+static struct pipe_texture *
+identity_drm_texture_from_shared_handle(struct drm_api *_api,
+ struct pipe_screen *_screen,
+ struct pipe_texture *templ,
+ const char *name,
+ unsigned stride,
+ unsigned handle)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_drm_api *id_api = identity_drm_api(_api);
+ struct pipe_screen *screen = id_screen->screen;
+ struct drm_api *api = id_api->api;
+ struct pipe_texture *result;
+
+ result = api->texture_from_shared_handle(api, screen, templ, name, stride, handle);
+
+ result = identity_texture_create(identity_screen(_screen), result);
+
+ return result;
+}
+
+static boolean
+identity_drm_shared_handle_from_texture(struct drm_api *_api,
+ struct pipe_screen *_screen,
+ struct pipe_texture *_texture,
+ unsigned *stride,
+ unsigned *handle)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_texture *id_texture = identity_texture(_texture);
+ struct identity_drm_api *id_api = identity_drm_api(_api);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_texture *texture = id_texture->texture;
+ struct drm_api *api = id_api->api;
+
+ return api->shared_handle_from_texture(api, screen, texture, stride, handle);
+}
+
+static boolean
+identity_drm_local_handle_from_texture(struct drm_api *_api,
+ struct pipe_screen *_screen,
+ struct pipe_texture *_texture,
+ unsigned *stride,
+ unsigned *handle)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_texture *id_texture = identity_texture(_texture);
+ struct identity_drm_api *id_api = identity_drm_api(_api);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_texture *texture = id_texture->texture;
+ struct drm_api *api = id_api->api;
+
+ return api->local_handle_from_texture(api, screen, texture, stride, handle);
+}
+
+static void
+identity_drm_destroy(struct drm_api *_api)
+{
+ struct identity_drm_api *id_api = identity_drm_api(_api);
+ struct drm_api *api = id_api->api;
+ api->destroy(api);
+
+ free(id_api);
+}
+
+struct drm_api *
+identity_drm_create(struct drm_api *api)
+{
+ struct identity_drm_api *id_api;
+
+ if (!api)
+ goto error;
+
+ id_api = CALLOC_STRUCT(identity_drm_api);
+
+ if (!id_api)
+ goto error;
+
+ id_api->base.create_screen = identity_drm_create_screen;
+ id_api->base.create_context = identity_drm_create_context;
+ id_api->base.texture_from_shared_handle = identity_drm_texture_from_shared_handle;
+ id_api->base.shared_handle_from_texture = identity_drm_shared_handle_from_texture;
+ id_api->base.local_handle_from_texture = identity_drm_local_handle_from_texture;
+ id_api->base.destroy = identity_drm_destroy;
+ id_api->api = api;
+
+ return &id_api->base;
+
+error:
+ return api;
+}
diff --git a/src/gallium/drivers/identity/id_drm.h b/src/gallium/drivers/identity/id_drm.h
new file mode 100644
index 0000000000..cf2ad2ce07
--- /dev/null
+++ b/src/gallium/drivers/identity/id_drm.h
@@ -0,0 +1,35 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ID_DRM_H
+#define ID_DRM_H
+
+struct drm_api;
+
+struct drm_api* identity_drm_create(struct drm_api *api);
+
+#endif /* ID_DRM_H */
diff --git a/src/gallium/drivers/identity/id_objects.c b/src/gallium/drivers/identity/id_objects.c
new file mode 100644
index 0000000000..e893e59940
--- /dev/null
+++ b/src/gallium/drivers/identity/id_objects.c
@@ -0,0 +1,182 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+
+#include "id_public.h"
+#include "id_screen.h"
+#include "id_objects.h"
+
+struct pipe_buffer *
+identity_buffer_create(struct identity_screen *id_screen,
+ struct pipe_buffer *buffer)
+{
+ struct identity_buffer *id_buffer;
+
+ if(!buffer)
+ goto error;
+
+ assert(buffer->screen == id_screen->screen);
+
+ id_buffer = CALLOC_STRUCT(identity_buffer);
+ if(!id_buffer)
+ goto error;
+
+ memcpy(&id_buffer->base, buffer, sizeof(struct pipe_buffer));
+
+ pipe_reference_init(&id_buffer->base.reference, 1);
+ id_buffer->base.screen = &id_screen->base;
+ id_buffer->buffer = buffer;
+
+ return &id_buffer->base;
+
+error:
+ pipe_buffer_reference(&buffer, NULL);
+ return NULL;
+}
+
+void
+identity_buffer_destroy(struct identity_buffer *id_buffer)
+{
+ pipe_buffer_reference(&id_buffer->buffer, NULL);
+ FREE(id_buffer);
+}
+
+
+struct pipe_texture *
+identity_texture_create(struct identity_screen *id_screen,
+ struct pipe_texture *texture)
+{
+ struct identity_texture *id_texture;
+
+ if(!texture)
+ goto error;
+
+ assert(texture->screen == id_screen->screen);
+
+ id_texture = CALLOC_STRUCT(identity_texture);
+ if(!id_texture)
+ goto error;
+
+ memcpy(&id_texture->base, texture, sizeof(struct pipe_texture));
+
+ pipe_reference_init(&id_texture->base.reference, 1);
+ id_texture->base.screen = &id_screen->base;
+ id_texture->texture = texture;
+
+ return &id_texture->base;
+
+error:
+ pipe_texture_reference(&texture, NULL);
+ return NULL;
+}
+
+void
+identity_texture_destroy(struct identity_texture *id_texture)
+{
+ pipe_texture_reference(&id_texture->texture, NULL);
+ FREE(id_texture);
+}
+
+
+struct pipe_surface *
+identity_surface_create(struct identity_texture *id_texture,
+ struct pipe_surface *surface)
+{
+ struct identity_surface *id_surface;
+
+ if(!surface)
+ goto error;
+
+ assert(surface->texture == id_texture->texture);
+
+ id_surface = CALLOC_STRUCT(identity_surface);
+ if(!id_surface)
+ goto error;
+
+ memcpy(&id_surface->base, surface, sizeof(struct pipe_surface));
+
+ pipe_reference_init(&id_surface->base.reference, 1);
+ id_surface->base.texture = NULL;
+ pipe_texture_reference(&id_surface->base.texture, &id_texture->base);
+ id_surface->surface = surface;
+
+ return &id_surface->base;
+
+error:
+ pipe_surface_reference(&surface, NULL);
+ return NULL;
+}
+
+void
+identity_surface_destroy(struct identity_surface *id_surface)
+{
+ pipe_texture_reference(&id_surface->base.texture, NULL);
+ pipe_surface_reference(&id_surface->surface, NULL);
+ FREE(id_surface);
+}
+
+
+struct pipe_transfer *
+identity_transfer_create(struct identity_texture *id_texture,
+ struct pipe_transfer *transfer)
+{
+ struct identity_transfer *id_transfer;
+
+ if(!transfer)
+ goto error;
+
+ assert(transfer->texture == id_texture->texture);
+
+ id_transfer = CALLOC_STRUCT(identity_transfer);
+ if(!id_transfer)
+ goto error;
+
+ memcpy(&id_transfer->base, transfer, sizeof(struct pipe_transfer));
+
+ id_transfer->base.texture = NULL;
+ pipe_texture_reference(&id_transfer->base.texture, &id_texture->base);
+ id_transfer->transfer = transfer;
+ assert(id_transfer->base.texture == &id_texture->base);
+
+ return &id_transfer->base;
+
+error:
+ transfer->texture->screen->tex_transfer_destroy(transfer);
+ return NULL;
+}
+
+void
+identity_transfer_destroy(struct identity_transfer *id_transfer)
+{
+ struct identity_screen *id_screen = identity_screen(id_transfer->base.texture->screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ pipe_texture_reference(&id_transfer->base.texture, NULL);
+ screen->tex_transfer_destroy(id_transfer->transfer);
+ FREE(id_transfer);
+}
diff --git a/src/gallium/drivers/identity/id_objects.h b/src/gallium/drivers/identity/id_objects.h
new file mode 100644
index 0000000000..ce58faa3c7
--- /dev/null
+++ b/src/gallium/drivers/identity/id_objects.h
@@ -0,0 +1,169 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ID_OBJECTS_H
+#define ID_OBJECTS_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+
+#include "id_screen.h"
+
+
+struct identity_buffer
+{
+ struct pipe_buffer base;
+
+ struct pipe_buffer *buffer;
+};
+
+
+struct identity_texture
+{
+ struct pipe_texture base;
+
+ struct pipe_texture *texture;
+};
+
+
+struct identity_surface
+{
+ struct pipe_surface base;
+
+ struct pipe_surface *surface;
+};
+
+
+struct identity_transfer
+{
+ struct pipe_transfer base;
+
+ struct pipe_transfer *transfer;
+};
+
+
+static INLINE struct identity_buffer *
+identity_buffer(struct pipe_buffer *_buffer)
+{
+ if(!_buffer)
+ return NULL;
+ (void)identity_screen(_buffer->screen);
+ return (struct identity_buffer *)_buffer;
+}
+
+static INLINE struct identity_texture *
+identity_texture(struct pipe_texture *_texture)
+{
+ if(!_texture)
+ return NULL;
+ (void)identity_screen(_texture->screen);
+ return (struct identity_texture *)_texture;
+}
+
+static INLINE struct identity_surface *
+identity_surface(struct pipe_surface *_surface)
+{
+ if(!_surface)
+ return NULL;
+ (void)identity_texture(_surface->texture);
+ return (struct identity_surface *)_surface;
+}
+
+static INLINE struct identity_transfer *
+identity_transfer(struct pipe_transfer *_transfer)
+{
+ if(!_transfer)
+ return NULL;
+ (void)identity_texture(_transfer->texture);
+ return (struct identity_transfer *)_transfer;
+}
+
+
+static INLINE struct pipe_buffer *
+identity_buffer_unwrap(struct pipe_buffer *_buffer)
+{
+ if(!_buffer)
+ return NULL;
+ return identity_buffer(_buffer)->buffer;
+}
+
+static INLINE struct pipe_texture *
+identity_texture_unwrap(struct pipe_texture *_texture)
+{
+ if(!_texture)
+ return NULL;
+ return identity_texture(_texture)->texture;
+}
+
+static INLINE struct pipe_surface *
+identity_surface_unwrap(struct pipe_surface *_surface)
+{
+ if(!_surface)
+ return NULL;
+ return identity_surface(_surface)->surface;
+}
+
+static INLINE struct pipe_transfer *
+identity_transfer_unwrap(struct pipe_transfer *_transfer)
+{
+ if(!_transfer)
+ return NULL;
+ return identity_transfer(_transfer)->transfer;
+}
+
+
+struct pipe_buffer *
+identity_buffer_create(struct identity_screen *id_screen,
+ struct pipe_buffer *buffer);
+
+void
+identity_buffer_destroy(struct identity_buffer *id_buffer);
+
+struct pipe_texture *
+identity_texture_create(struct identity_screen *id_screen,
+ struct pipe_texture *texture);
+
+void
+identity_texture_destroy(struct identity_texture *id_texture);
+
+struct pipe_surface *
+identity_surface_create(struct identity_texture *id_texture,
+ struct pipe_surface *surface);
+
+void
+identity_surface_destroy(struct identity_surface *id_surface);
+
+struct pipe_transfer *
+identity_transfer_create(struct identity_texture *id_texture,
+ struct pipe_transfer *transfer);
+
+void
+identity_transfer_destroy(struct identity_transfer *id_transfer);
+
+
+#endif /* ID_OBJECTS_H */
diff --git a/src/gallium/drivers/identity/id_public.h b/src/gallium/drivers/identity/id_public.h
new file mode 100644
index 0000000000..cac14cfd60
--- /dev/null
+++ b/src/gallium/drivers/identity/id_public.h
@@ -0,0 +1,40 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ID_PUBLIC_H
+#define ID_PUBLIC_H
+
+struct pipe_screen;
+struct pipe_context;
+
+struct pipe_screen *
+identity_screen_create(struct pipe_screen *screen);
+
+struct pipe_context *
+identity_context_create(struct pipe_screen *screen, struct pipe_context *pipe);
+
+#endif /* PT_PUBLIC_H */
diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c
new file mode 100644
index 0000000000..26439637d0
--- /dev/null
+++ b/src/gallium/drivers/identity/id_screen.c
@@ -0,0 +1,483 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+#include "util/u_memory.h"
+
+#include "id_public.h"
+#include "id_screen.h"
+#include "id_objects.h"
+
+
+static void
+identity_screen_destroy(struct pipe_screen *_screen)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ screen->destroy(screen);
+
+ FREE(id_screen);
+}
+
+static const char *
+identity_screen_get_name(struct pipe_screen *_screen)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ return screen->get_name(screen);
+}
+
+static const char *
+identity_screen_get_vendor(struct pipe_screen *_screen)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ return screen->get_vendor(screen);
+}
+
+static int
+identity_screen_get_param(struct pipe_screen *_screen,
+ int param)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ return screen->get_param(screen,
+ param);
+}
+
+static float
+identity_screen_get_paramf(struct pipe_screen *_screen,
+ int param)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ return screen->get_paramf(screen,
+ param);
+}
+
+static boolean
+identity_screen_is_format_supported(struct pipe_screen *_screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ return screen->is_format_supported(screen,
+ format,
+ target,
+ tex_usage,
+ geom_flags);
+}
+
+static struct pipe_texture *
+identity_screen_texture_create(struct pipe_screen *_screen,
+ const struct pipe_texture *templat)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_texture *result;
+
+ result = screen->texture_create(screen,
+ templat);
+
+ if (result)
+ return identity_texture_create(id_screen, result);
+ return NULL;
+}
+
+static struct pipe_texture *
+identity_screen_texture_blanket(struct pipe_screen *_screen,
+ const struct pipe_texture *templat,
+ const unsigned *stride,
+ struct pipe_buffer *_buffer)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_buffer *id_buffer = identity_buffer(_buffer);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_buffer *buffer = id_buffer->buffer;
+ struct pipe_texture *result;
+
+ result = screen->texture_blanket(screen,
+ templat,
+ stride,
+ buffer);
+
+ if (result)
+ return identity_texture_create(id_screen, result);
+ return NULL;
+}
+
+static void
+identity_screen_texture_destroy(struct pipe_texture *_texture)
+{
+ identity_texture_destroy(identity_texture(_texture));
+}
+
+static struct pipe_surface *
+identity_screen_get_tex_surface(struct pipe_screen *_screen,
+ struct pipe_texture *_texture,
+ unsigned face,
+ unsigned level,
+ unsigned zslice,
+ unsigned usage)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_texture *id_texture = identity_texture(_texture);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_texture *texture = id_texture->texture;
+ struct pipe_surface *result;
+
+ result = screen->get_tex_surface(screen,
+ texture,
+ face,
+ level,
+ zslice,
+ usage);
+
+ if (result)
+ return identity_surface_create(id_texture, result);
+ return NULL;
+}
+
+static void
+identity_screen_tex_surface_destroy(struct pipe_surface *_surface)
+{
+ identity_surface_destroy(identity_surface(_surface));
+}
+
+static struct pipe_transfer *
+identity_screen_get_tex_transfer(struct pipe_screen *_screen,
+ struct pipe_texture *_texture,
+ unsigned face,
+ unsigned level,
+ unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x,
+ unsigned y,
+ unsigned w,
+ unsigned h)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_texture *id_texture = identity_texture(_texture);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_texture *texture = id_texture->texture;
+ struct pipe_transfer *result;
+
+ result = screen->get_tex_transfer(screen,
+ texture,
+ face,
+ level,
+ zslice,
+ usage,
+ x,
+ y,
+ w,
+ h);
+
+ if (result)
+ return identity_transfer_create(id_texture, result);
+ return NULL;
+}
+
+static void
+identity_screen_tex_transfer_destroy(struct pipe_transfer *_transfer)
+{
+ identity_transfer_destroy(identity_transfer(_transfer));
+}
+
+static void *
+identity_screen_transfer_map(struct pipe_screen *_screen,
+ struct pipe_transfer *_transfer)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_transfer *id_transfer = identity_transfer(_transfer);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_transfer *transfer = id_transfer->transfer;
+
+ return screen->transfer_map(screen,
+ transfer);
+}
+
+static void
+identity_screen_transfer_unmap(struct pipe_screen *_screen,
+ struct pipe_transfer *_transfer)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_transfer *id_transfer = identity_transfer(_transfer);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_transfer *transfer = id_transfer->transfer;
+
+ screen->transfer_unmap(screen,
+ transfer);
+}
+
+static struct pipe_buffer *
+identity_screen_buffer_create(struct pipe_screen *_screen,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_buffer *result;
+
+ result = screen->buffer_create(screen,
+ alignment,
+ usage,
+ size);
+
+ if (result)
+ return identity_buffer_create(id_screen, result);
+ return NULL;
+}
+
+static struct pipe_buffer *
+identity_screen_user_buffer_create(struct pipe_screen *_screen,
+ void *ptr,
+ unsigned bytes)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_buffer *result;
+
+ result = screen->user_buffer_create(screen,
+ ptr,
+ bytes);
+
+ if (result)
+ return identity_buffer_create(id_screen, result);
+ return NULL;
+}
+
+static struct pipe_buffer *
+identity_screen_surface_buffer_create(struct pipe_screen *_screen,
+ unsigned width,
+ unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_buffer *result;
+
+ result = screen->surface_buffer_create(screen,
+ width,
+ height,
+ format,
+ usage,
+ tex_usage,
+ stride);
+
+ if (result)
+ return identity_buffer_create(id_screen, result);
+ return NULL;
+}
+
+static void *
+identity_screen_buffer_map(struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer,
+ unsigned usage)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_buffer *id_buffer = identity_buffer(_buffer);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_buffer *buffer = id_buffer->buffer;
+
+ return screen->buffer_map(screen,
+ buffer,
+ usage);
+}
+
+static void *
+identity_screen_buffer_map_range(struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer,
+ unsigned offset,
+ unsigned length,
+ unsigned usage)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_buffer *id_buffer = identity_buffer(_buffer);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_buffer *buffer = id_buffer->buffer;
+
+ return screen->buffer_map_range(screen,
+ buffer,
+ offset,
+ length,
+ usage);
+}
+
+static void
+identity_screen_buffer_flush_mapped_range(struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer,
+ unsigned offset,
+ unsigned length)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_buffer *id_buffer = identity_buffer(_buffer);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_buffer *buffer = id_buffer->buffer;
+
+ screen->buffer_flush_mapped_range(screen,
+ buffer,
+ offset,
+ length);
+}
+
+static void
+identity_screen_buffer_unmap(struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_buffer *id_buffer = identity_buffer(_buffer);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_buffer *buffer = id_buffer->buffer;
+
+ screen->buffer_unmap(screen,
+ buffer);
+}
+
+static void
+identity_screen_buffer_destroy(struct pipe_buffer *_buffer)
+{
+ identity_buffer_destroy(identity_buffer(_buffer));
+}
+
+static void
+identity_screen_flush_frontbuffer(struct pipe_screen *_screen,
+ struct pipe_surface *_surface,
+ void *context_private)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct identity_surface *id_surface = identity_surface(_surface);
+ struct pipe_screen *screen = id_screen->screen;
+ struct pipe_surface *surface = id_surface->surface;
+
+ screen->flush_frontbuffer(screen,
+ surface,
+ context_private);
+}
+
+static void
+identity_screen_fence_reference(struct pipe_screen *_screen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ screen->fence_reference(screen,
+ ptr,
+ fence);
+}
+
+static int
+identity_screen_fence_signalled(struct pipe_screen *_screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ return screen->fence_signalled(screen,
+ fence,
+ flags);
+}
+
+static int
+identity_screen_fence_finish(struct pipe_screen *_screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
+{
+ struct identity_screen *id_screen = identity_screen(_screen);
+ struct pipe_screen *screen = id_screen->screen;
+
+ return screen->fence_finish(screen,
+ fence,
+ flags);
+}
+
+struct pipe_screen *
+identity_screen_create(struct pipe_screen *screen)
+{
+ struct identity_screen *id_screen;
+
+ id_screen = CALLOC_STRUCT(identity_screen);
+ if (!id_screen) {
+ return NULL;
+ }
+
+ id_screen->base.winsys = NULL;
+
+ id_screen->base.destroy = identity_screen_destroy;
+ id_screen->base.get_name = identity_screen_get_name;
+ id_screen->base.get_vendor = identity_screen_get_vendor;
+ id_screen->base.get_param = identity_screen_get_param;
+ id_screen->base.get_paramf = identity_screen_get_paramf;
+ id_screen->base.is_format_supported = identity_screen_is_format_supported;
+ id_screen->base.texture_create = identity_screen_texture_create;
+ id_screen->base.texture_blanket = identity_screen_texture_blanket;
+ id_screen->base.texture_destroy = identity_screen_texture_destroy;
+ id_screen->base.get_tex_surface = identity_screen_get_tex_surface;
+ id_screen->base.tex_surface_destroy = identity_screen_tex_surface_destroy;
+ id_screen->base.get_tex_transfer = identity_screen_get_tex_transfer;
+ id_screen->base.tex_transfer_destroy = identity_screen_tex_transfer_destroy;
+ id_screen->base.transfer_map = identity_screen_transfer_map;
+ id_screen->base.transfer_unmap = identity_screen_transfer_unmap;
+ id_screen->base.buffer_create = identity_screen_buffer_create;
+ id_screen->base.user_buffer_create = identity_screen_user_buffer_create;
+ id_screen->base.surface_buffer_create = identity_screen_surface_buffer_create;
+ if (screen->buffer_map)
+ id_screen->base.buffer_map = identity_screen_buffer_map;
+ if (screen->buffer_map_range)
+ id_screen->base.buffer_map_range = identity_screen_buffer_map_range;
+ if (screen->buffer_flush_mapped_range)
+ id_screen->base.buffer_flush_mapped_range = identity_screen_buffer_flush_mapped_range;
+ if (screen->buffer_unmap)
+ id_screen->base.buffer_unmap = identity_screen_buffer_unmap;
+ id_screen->base.buffer_destroy = identity_screen_buffer_destroy;
+ id_screen->base.flush_frontbuffer = identity_screen_flush_frontbuffer;
+ id_screen->base.fence_reference = identity_screen_fence_reference;
+ id_screen->base.fence_signalled = identity_screen_fence_signalled;
+ id_screen->base.fence_finish = identity_screen_fence_finish;
+
+ id_screen->screen = screen;
+
+ return &id_screen->base;
+}
diff --git a/src/gallium/drivers/identity/id_screen.h b/src/gallium/drivers/identity/id_screen.h
new file mode 100644
index 0000000000..2c4f129089
--- /dev/null
+++ b/src/gallium/drivers/identity/id_screen.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ID_SCREEN_H
+#define ID_SCREEN_H
+
+#include "pipe/p_screen.h"
+#include "pipe/p_defines.h"
+
+
+struct identity_screen {
+ struct pipe_screen base;
+
+ struct pipe_screen *screen;
+};
+
+
+static INLINE struct identity_screen *
+identity_screen(struct pipe_screen *screen)
+{
+ return (struct identity_screen *)screen;
+}
+
+#endif /* ID_SCREEN_H */
diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile
new file mode 100644
index 0000000000..06c586e6bb
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/Makefile
@@ -0,0 +1,55 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = llvmpipe
+
+C_SOURCES = \
+ lp_bld_alpha.c \
+ lp_bld_arit.c \
+ lp_bld_blend_aos.c \
+ lp_bld_blend_logicop.c \
+ lp_bld_blend_soa.c \
+ lp_bld_const.c \
+ lp_bld_conv.c \
+ lp_bld_debug.c \
+ lp_bld_depth.c \
+ lp_bld_flow.c \
+ lp_bld_format_aos.c \
+ lp_bld_format_soa.c \
+ lp_bld_interp.c \
+ lp_bld_intr.c \
+ lp_bld_logic.c \
+ lp_bld_sample_soa.c \
+ lp_bld_swizzle.c \
+ lp_bld_struct.c \
+ lp_bld_tgsi_soa.c \
+ lp_bld_type.c \
+ lp_buffer.c \
+ lp_clear.c \
+ lp_context.c \
+ lp_draw_arrays.c \
+ lp_flush.c \
+ lp_jit.c \
+ lp_prim_setup.c \
+ lp_prim_vbuf.c \
+ lp_setup.c \
+ lp_query.c \
+ lp_screen.c \
+ lp_state_blend.c \
+ lp_state_clip.c \
+ lp_state_derived.c \
+ lp_state_fs.c \
+ lp_state_rasterizer.c \
+ lp_state_sampler.c \
+ lp_state_surface.c \
+ lp_state_vertex.c \
+ lp_state_vs.c \
+ lp_surface.c \
+ lp_tex_cache.c \
+ lp_tex_sample_c.c \
+ lp_tex_sample_llvm.c \
+ lp_texture.c \
+ lp_tile_cache.c \
+ lp_tile_soa.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/llvmpipe/README b/src/gallium/drivers/llvmpipe/README
new file mode 100644
index 0000000000..89d08834a3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/README
@@ -0,0 +1,149 @@
+LLVMPIPE -- a fork of softpipe that employs LLVM for code generation.
+
+
+Status
+======
+
+Done so far is:
+
+ - the whole fragment pipeline is code generated in a single function
+
+ - input interpolation
+
+ - depth testing
+
+ - texture sampling (not all state/formats are supported)
+
+ - fragment shader TGSI translation
+ - same level of support as the TGSI SSE2 exec machine, with the exception
+ we don't fallback to TGSI interpretation when an unsupported opcode is
+ found, but just ignore it
+ - done in SoA layout
+ - input interpolation also code generated
+
+ - alpha testing
+
+ - blend (including logic ops)
+ - both in SoA and AoS layouts, but only the former used for now
+
+ - code is generic
+ - intermediates can be vectors of floats, ubytes, fixed point, etc, and of
+ any width and length
+ - not all operations are implemented for these types yet though
+
+Most mesa/progs/demos/* work.
+
+To do (probably by this order):
+
+ - code generate stipple and stencil testing
+
+ - translate the remaining bits of texture sampling state
+
+ - translate TGSI control flow instructions, and all other remaining opcodes
+
+ - integrate with the draw module for VS code generation
+
+ - code generate the triangle setup and rasterization
+
+
+Requirements
+============
+
+ - Linux
+
+ - udis86, http://udis86.sourceforge.net/ . Use my repository, which decodes
+ opcodes not yet supported by upstream.
+
+ git clone git://people.freedesktop.org/~jrfonseca/udis86
+ cd udis86
+ ./configure --with-pic
+ make
+ sudo make install
+
+ - LLVM 2.5. On Debian based distributions do:
+
+ aptitude install llvm-dev
+
+ There is a typo in one of the llvm-dev 2.5 headers, that causes compilation
+ errors in the debug build:
+
+ --- /usr/include/llvm-c/Core.h.orig 2009-08-10 15:38:54.000000000 +0100
+ +++ /usr/include/llvm-c/Core.h 2009-08-10 15:38:25.000000000 +0100
+ @@ -831,7 +831,7 @@
+ template<typename T>
+ inline T **unwrap(LLVMValueRef *Vals, unsigned Length) {
+ #if DEBUG
+ - for (LLVMValueRef *I = Vals, E = Vals + Length; I != E; ++I)
+ + for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I)
+ cast<T>(*I);
+ #endif
+ return reinterpret_cast<T**>(Vals);
+
+ - A x86 or amd64 processor with support for sse2, sse3, and sse4.1 SIMD
+ instructions. This is necessary because we emit several SSE intrinsics for
+ convenience. See /proc/cpuinfo to know what your CPU supports.
+
+ - scons
+
+
+Building
+========
+
+To build everything invoke scons as:
+
+ scons debug=yes statetrackers=mesa drivers=llvmpipe winsys=xlib dri=false -k
+
+Alternatively, you can build it with GNU make, if you prefer, by invoking it as
+
+ make linux-llvm
+
+but the rest of these instructions assume that scons is used.
+
+
+Using
+=====
+
+Building will create a drop-in alternative for libGL.so. To use it set the
+environment variables:
+
+ export LD_LIBRARY_PATH=$PWD/build/linux-x86_64-debug/lib:$LD_LIBRARY_PATH
+
+or
+
+ export LD_LIBRARY_PATH=$PWD/build/linux-x86-debug/lib:$LD_LIBRARY_PATH
+
+For performance evaluation pass debug=no to scons, and use the corresponding
+lib directory without the "-debug" suffix.
+
+
+Unit testing
+============
+
+Building will also create several unit tests in
+build/linux-???-debug/gallium/drivers/llvmpipe:
+
+ - lp_test_blend: blending
+ - lp_test_conv: SIMD vector conversion
+ - lp_test_format: pixel unpacking/packing
+
+Some of this tests can output results and benchmarks to a tab-separated-file
+for posterior analysis, e.g.:
+
+ build/linux-x86_64-debug/gallium/drivers/llvmpipe/lp_test_blend -o blend.tsv
+
+
+Development Notes
+=================
+
+- When looking to this code by the first time start in lp_state_fs.c, and
+ then skim through the lp_bld_* functions called in there, and the comments
+ at the top of the lp_bld_*.c functions.
+
+- All lp_bld_*.[ch] are isolated from the rest of the driver, and could/may be
+ put in a stand-alone Gallium state -> LLVM IR translation module.
+
+- We use LLVM-C bindings for now. They are not documented, but follow the C++
+ interfaces very closely, and appear to be complete enough for code
+ generation. See
+ http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html
+ for a stand-alone example.
diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript
new file mode 100644
index 0000000000..dea4b703c4
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/SConscript
@@ -0,0 +1,84 @@
+Import('*')
+
+env = env.Clone()
+
+env.Tool('llvm')
+if env.has_key('LLVM_VERSION') is False:
+ print 'warning: LLVM not found: not building llvmpipe'
+ Return()
+
+env.Tool('udis86')
+
+llvmpipe = env.ConvenienceLibrary(
+ target = 'llvmpipe',
+ source = [
+ 'lp_bld_alpha.c',
+ 'lp_bld_arit.c',
+ 'lp_bld_blend_aos.c',
+ 'lp_bld_blend_logicop.c',
+ 'lp_bld_blend_soa.c',
+ 'lp_bld_const.c',
+ 'lp_bld_conv.c',
+ 'lp_bld_debug.c',
+ 'lp_bld_depth.c',
+ 'lp_bld_flow.c',
+ 'lp_bld_format_aos.c',
+ 'lp_bld_format_soa.c',
+ 'lp_bld_interp.c',
+ 'lp_bld_intr.c',
+ 'lp_bld_sample_soa.c',
+ 'lp_bld_struct.c',
+ 'lp_bld_logic.c',
+ 'lp_bld_swizzle.c',
+ 'lp_bld_tgsi_soa.c',
+ 'lp_bld_type.c',
+ 'lp_buffer.c',
+ 'lp_clear.c',
+ 'lp_context.c',
+ 'lp_draw_arrays.c',
+ 'lp_flush.c',
+ 'lp_jit.c',
+ 'lp_prim_setup.c',
+ 'lp_prim_vbuf.c',
+ 'lp_setup.c',
+ 'lp_query.c',
+ 'lp_screen.c',
+ 'lp_state_blend.c',
+ 'lp_state_clip.c',
+ 'lp_state_derived.c',
+ 'lp_state_fs.c',
+ 'lp_state_rasterizer.c',
+ 'lp_state_sampler.c',
+ 'lp_state_surface.c',
+ 'lp_state_vertex.c',
+ 'lp_state_vs.c',
+ 'lp_surface.c',
+ 'lp_tex_cache.c',
+ 'lp_tex_sample_c.c',
+ 'lp_tex_sample_llvm.c',
+ 'lp_texture.c',
+ 'lp_tile_cache.c',
+ 'lp_tile_soa.c',
+ ])
+
+
+env = env.Clone()
+
+env.Prepend(LIBS = [llvmpipe] + auxiliaries)
+
+env.Program(
+ target = 'lp_test_format',
+ source = ['lp_test_format.c'],
+)
+
+env.Program(
+ target = 'lp_test_blend',
+ source = ['lp_test_blend.c', 'lp_test_main.c'],
+)
+
+env.Program(
+ target = 'lp_test_conv',
+ source = ['lp_test_conv.c', 'lp_test_main.c'],
+)
+
+Export('llvmpipe')
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c
new file mode 100644
index 0000000000..49c2f911af
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c
@@ -0,0 +1,64 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Alpha testing to LLVM IR translation.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include "pipe/p_state.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_arit.h"
+#include "lp_bld_logic.h"
+#include "lp_bld_flow.h"
+#include "lp_bld_debug.h"
+#include "lp_bld_alpha.h"
+
+
+void
+lp_build_alpha_test(LLVMBuilderRef builder,
+ const struct pipe_alpha_state *state,
+ union lp_type type,
+ struct lp_build_mask_context *mask,
+ LLVMValueRef alpha,
+ LLVMValueRef ref)
+{
+ struct lp_build_context bld;
+
+ lp_build_context_init(&bld, builder, type);
+
+ if(state->enabled) {
+ LLVMValueRef test = lp_build_cmp(&bld, state->func, alpha, ref);
+
+ lp_build_name(test, "alpha_mask");
+
+ lp_build_mask_update(mask, test);
+ }
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.h b/src/gallium/drivers/llvmpipe/lp_bld_alpha.h
new file mode 100644
index 0000000000..9dbcdb4daa
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_alpha.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Alpha testing to LLVM IR translation.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef LP_BLD_ALPHA_H
+#define LP_BLD_ALPHA_H
+
+
+#include <llvm-c/Core.h>
+
+struct pipe_alpha_state;
+union lp_type;
+struct lp_build_mask_context;
+
+
+void
+lp_build_alpha_test(LLVMBuilderRef builder,
+ const struct pipe_alpha_state *state,
+ union lp_type type,
+ struct lp_build_mask_context *mask,
+ LLVMValueRef alpha,
+ LLVMValueRef ref);
+
+
+#endif /* !LP_BLD_ALPHA_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_arit.c b/src/gallium/drivers/llvmpipe/lp_bld_arit.c
new file mode 100644
index 0000000000..be7442d00a
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_arit.c
@@ -0,0 +1,1082 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Helper
+ *
+ * LLVM IR doesn't support all basic arithmetic operations we care about (most
+ * notably min/max and saturated operations), and it is often necessary to
+ * resort machine-specific intrinsics directly. The functions here hide all
+ * these implementation details from the other modules.
+ *
+ * We also do simple expressions simplification here. Reasons are:
+ * - it is very easy given we have all necessary information readily available
+ * - LLVM optimization passes fail to simplify several vector expressions
+ * - We often know value constraints which the optimization passes have no way
+ * of knowing, such as when source arguments are known to be in [0, 1] range.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "util/u_memory.h"
+#include "util/u_debug.h"
+#include "util/u_string.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_intr.h"
+#include "lp_bld_logic.h"
+#include "lp_bld_arit.h"
+
+
+/**
+ * Generate min(a, b)
+ * No checks for special case values of a or b = 1 or 0 are done.
+ */
+static LLVMValueRef
+lp_build_min_simple(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ const union lp_type type = bld->type;
+ const char *intrinsic = NULL;
+ LLVMValueRef cond;
+
+ /* TODO: optimize the constant case */
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width * type.length == 128) {
+ if(type.floating) {
+ if(type.width == 32)
+ intrinsic = "llvm.x86.sse.min.ps";
+ if(type.width == 64)
+ intrinsic = "llvm.x86.sse2.min.pd";
+ }
+ else {
+ if(type.width == 8 && !type.sign)
+ intrinsic = "llvm.x86.sse2.pminu.b";
+ if(type.width == 8 && type.sign)
+ intrinsic = "llvm.x86.sse41.pminsb";
+ if(type.width == 16 && !type.sign)
+ intrinsic = "llvm.x86.sse41.pminuw";
+ if(type.width == 16 && type.sign)
+ intrinsic = "llvm.x86.sse2.pmins.w";
+ if(type.width == 32 && !type.sign)
+ intrinsic = "llvm.x86.sse41.pminud";
+ if(type.width == 32 && type.sign)
+ intrinsic = "llvm.x86.sse41.pminsd";
+ }
+ }
+#endif
+
+ if(intrinsic)
+ return lp_build_intrinsic_binary(bld->builder, intrinsic, lp_build_vec_type(bld->type), a, b);
+
+ cond = lp_build_cmp(bld, PIPE_FUNC_LESS, a, b);
+ return lp_build_select(bld, cond, a, b);
+}
+
+
+/**
+ * Generate max(a, b)
+ * No checks for special case values of a or b = 1 or 0 are done.
+ */
+static LLVMValueRef
+lp_build_max_simple(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ const union lp_type type = bld->type;
+ const char *intrinsic = NULL;
+ LLVMValueRef cond;
+
+ /* TODO: optimize the constant case */
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width * type.length == 128) {
+ if(type.floating) {
+ if(type.width == 32)
+ intrinsic = "llvm.x86.sse.max.ps";
+ if(type.width == 64)
+ intrinsic = "llvm.x86.sse2.max.pd";
+ }
+ else {
+ if(type.width == 8 && !type.sign)
+ intrinsic = "llvm.x86.sse2.pmaxu.b";
+ if(type.width == 8 && type.sign)
+ intrinsic = "llvm.x86.sse41.pmaxsb";
+ if(type.width == 16 && !type.sign)
+ intrinsic = "llvm.x86.sse41.pmaxuw";
+ if(type.width == 16 && type.sign)
+ intrinsic = "llvm.x86.sse2.pmaxs.w";
+ if(type.width == 32 && !type.sign)
+ intrinsic = "llvm.x86.sse41.pmaxud";
+ if(type.width == 32 && type.sign)
+ intrinsic = "llvm.x86.sse41.pmaxsd";
+ }
+ }
+#endif
+
+ if(intrinsic)
+ return lp_build_intrinsic_binary(bld->builder, intrinsic, lp_build_vec_type(bld->type), a, b);
+
+ cond = lp_build_cmp(bld, PIPE_FUNC_GREATER, a, b);
+ return lp_build_select(bld, cond, a, b);
+}
+
+
+/**
+ * Generate 1 - a, or ~a depending on bld->type.
+ */
+LLVMValueRef
+lp_build_comp(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ const union lp_type type = bld->type;
+
+ if(a == bld->one)
+ return bld->zero;
+ if(a == bld->zero)
+ return bld->one;
+
+ if(type.norm && !type.floating && !type.fixed && !type.sign) {
+ if(LLVMIsConstant(a))
+ return LLVMConstNot(a);
+ else
+ return LLVMBuildNot(bld->builder, a, "");
+ }
+
+ if(LLVMIsConstant(a))
+ return LLVMConstSub(bld->one, a);
+ else
+ return LLVMBuildSub(bld->builder, bld->one, a, "");
+}
+
+
+/**
+ * Generate a + b
+ */
+LLVMValueRef
+lp_build_add(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ const union lp_type type = bld->type;
+ LLVMValueRef res;
+
+ if(a == bld->zero)
+ return b;
+ if(b == bld->zero)
+ return a;
+ if(a == bld->undef || b == bld->undef)
+ return bld->undef;
+
+ if(bld->type.norm) {
+ const char *intrinsic = NULL;
+
+ if(a == bld->one || b == bld->one)
+ return bld->one;
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width * type.length == 128 &&
+ !type.floating && !type.fixed) {
+ if(type.width == 8)
+ intrinsic = type.sign ? "llvm.x86.sse2.padds.b" : "llvm.x86.sse2.paddus.b";
+ if(type.width == 16)
+ intrinsic = type.sign ? "llvm.x86.sse2.padds.w" : "llvm.x86.sse2.paddus.w";
+ }
+#endif
+
+ if(intrinsic)
+ return lp_build_intrinsic_binary(bld->builder, intrinsic, lp_build_vec_type(bld->type), a, b);
+ }
+
+ if(LLVMIsConstant(a) && LLVMIsConstant(b))
+ res = LLVMConstAdd(a, b);
+ else
+ res = LLVMBuildAdd(bld->builder, a, b, "");
+
+ /* clamp to ceiling of 1.0 */
+ if(bld->type.norm && (bld->type.floating || bld->type.fixed))
+ res = lp_build_min_simple(bld, res, bld->one);
+
+ /* XXX clamp to floor of -1 or 0??? */
+
+ return res;
+}
+
+
+/**
+ * Generate a - b
+ */
+LLVMValueRef
+lp_build_sub(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ const union lp_type type = bld->type;
+ LLVMValueRef res;
+
+ if(b == bld->zero)
+ return a;
+ if(a == bld->undef || b == bld->undef)
+ return bld->undef;
+ if(a == b)
+ return bld->zero;
+
+ if(bld->type.norm) {
+ const char *intrinsic = NULL;
+
+ if(b == bld->one)
+ return bld->zero;
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width * type.length == 128 &&
+ !type.floating && !type.fixed) {
+ if(type.width == 8)
+ intrinsic = type.sign ? "llvm.x86.sse2.psubs.b" : "llvm.x86.sse2.psubus.b";
+ if(type.width == 16)
+ intrinsic = type.sign ? "llvm.x86.sse2.psubs.w" : "llvm.x86.sse2.psubus.w";
+ }
+#endif
+
+ if(intrinsic)
+ return lp_build_intrinsic_binary(bld->builder, intrinsic, lp_build_vec_type(bld->type), a, b);
+ }
+
+ if(LLVMIsConstant(a) && LLVMIsConstant(b))
+ res = LLVMConstSub(a, b);
+ else
+ res = LLVMBuildSub(bld->builder, a, b, "");
+
+ if(bld->type.norm && (bld->type.floating || bld->type.fixed))
+ res = lp_build_max_simple(bld, res, bld->zero);
+
+ return res;
+}
+
+
+/**
+ * Build shuffle vectors that match PUNPCKLxx and PUNPCKHxx instructions.
+ */
+static LLVMValueRef
+lp_build_unpack_shuffle(unsigned n, unsigned lo_hi)
+{
+ LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+ unsigned i, j;
+
+ assert(n <= LP_MAX_VECTOR_LENGTH);
+ assert(lo_hi < 2);
+
+ for(i = 0, j = lo_hi*n/2; i < n; i += 2, ++j) {
+ elems[i + 0] = LLVMConstInt(LLVMInt32Type(), 0 + j, 0);
+ elems[i + 1] = LLVMConstInt(LLVMInt32Type(), n + j, 0);
+ }
+
+ return LLVMConstVector(elems, n);
+}
+
+
+/**
+ * Build constant int vector of width 'n' and value 'c'.
+ */
+static LLVMValueRef
+lp_build_const_vec(LLVMTypeRef type, unsigned n, long long c)
+{
+ LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+ unsigned i;
+
+ assert(n <= LP_MAX_VECTOR_LENGTH);
+
+ for(i = 0; i < n; ++i)
+ elems[i] = LLVMConstInt(type, c, 0);
+
+ return LLVMConstVector(elems, n);
+}
+
+
+/**
+ * Normalized 8bit multiplication.
+ *
+ * - alpha plus one
+ *
+ * makes the following approximation to the division (Sree)
+ *
+ * a*b/255 ~= (a*(b + 1)) >> 256
+ *
+ * which is the fastest method that satisfies the following OpenGL criteria
+ *
+ * 0*0 = 0 and 255*255 = 255
+ *
+ * - geometric series
+ *
+ * takes the geometric series approximation to the division
+ *
+ * t/255 = (t >> 8) + (t >> 16) + (t >> 24) ..
+ *
+ * in this case just the first two terms to fit in 16bit arithmetic
+ *
+ * t/255 ~= (t + (t >> 8)) >> 8
+ *
+ * note that just by itself it doesn't satisfies the OpenGL criteria, as
+ * 255*255 = 254, so the special case b = 255 must be accounted or roundoff
+ * must be used
+ *
+ * - geometric series plus rounding
+ *
+ * when using a geometric series division instead of truncating the result
+ * use roundoff in the approximation (Jim Blinn)
+ *
+ * t/255 ~= (t + (t >> 8) + 0x80) >> 8
+ *
+ * achieving the exact results
+ *
+ * @sa Alvy Ray Smith, Image Compositing Fundamentals, Tech Memo 4, Aug 15, 1995,
+ * ftp://ftp.alvyray.com/Acrobat/4_Comp.pdf
+ * @sa Michael Herf, The "double blend trick", May 2000,
+ * http://www.stereopsis.com/doubleblend.html
+ */
+static LLVMValueRef
+lp_build_mul_u8n(LLVMBuilderRef builder,
+ LLVMValueRef a, LLVMValueRef b)
+{
+ static LLVMValueRef c01 = NULL;
+ static LLVMValueRef c08 = NULL;
+ static LLVMValueRef c80 = NULL;
+ LLVMValueRef ab;
+
+ if(!c01) c01 = lp_build_const_vec(LLVMInt16Type(), 8, 0x01);
+ if(!c08) c08 = lp_build_const_vec(LLVMInt16Type(), 8, 0x08);
+ if(!c80) c80 = lp_build_const_vec(LLVMInt16Type(), 8, 0x80);
+
+#if 0
+
+ /* a*b/255 ~= (a*(b + 1)) >> 256 */
+ b = LLVMBuildAdd(builder, b, c01, "");
+ ab = LLVMBuildMul(builder, a, b, "");
+
+#else
+
+ /* t/255 ~= (t + (t >> 8) + 0x80) >> 8 */
+ ab = LLVMBuildMul(builder, a, b, "");
+ ab = LLVMBuildAdd(builder, ab, LLVMBuildLShr(builder, ab, c08, ""), "");
+ ab = LLVMBuildAdd(builder, ab, c80, "");
+
+#endif
+
+ ab = LLVMBuildLShr(builder, ab, c08, "");
+
+ return ab;
+}
+
+
+/**
+ * Generate a * b
+ */
+LLVMValueRef
+lp_build_mul(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ const union lp_type type = bld->type;
+
+ if(a == bld->zero)
+ return bld->zero;
+ if(a == bld->one)
+ return b;
+ if(b == bld->zero)
+ return bld->zero;
+ if(b == bld->one)
+ return a;
+ if(a == bld->undef || b == bld->undef)
+ return bld->undef;
+
+ if(!type.floating && !type.fixed && type.norm) {
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width == 8 && type.length == 16) {
+ LLVMTypeRef i16x8 = LLVMVectorType(LLVMInt16Type(), 8);
+ LLVMTypeRef i8x16 = LLVMVectorType(LLVMInt8Type(), 16);
+ static LLVMValueRef ml = NULL;
+ static LLVMValueRef mh = NULL;
+ LLVMValueRef al, ah, bl, bh;
+ LLVMValueRef abl, abh;
+ LLVMValueRef ab;
+
+ if(!ml) ml = lp_build_unpack_shuffle(16, 0);
+ if(!mh) mh = lp_build_unpack_shuffle(16, 1);
+
+ /* PUNPCKLBW, PUNPCKHBW */
+ al = LLVMBuildShuffleVector(bld->builder, a, bld->zero, ml, "");
+ bl = LLVMBuildShuffleVector(bld->builder, b, bld->zero, ml, "");
+ ah = LLVMBuildShuffleVector(bld->builder, a, bld->zero, mh, "");
+ bh = LLVMBuildShuffleVector(bld->builder, b, bld->zero, mh, "");
+
+ /* NOP */
+ al = LLVMBuildBitCast(bld->builder, al, i16x8, "");
+ bl = LLVMBuildBitCast(bld->builder, bl, i16x8, "");
+ ah = LLVMBuildBitCast(bld->builder, ah, i16x8, "");
+ bh = LLVMBuildBitCast(bld->builder, bh, i16x8, "");
+
+ /* PMULLW, PSRLW, PADDW */
+ abl = lp_build_mul_u8n(bld->builder, al, bl);
+ abh = lp_build_mul_u8n(bld->builder, ah, bh);
+
+ /* PACKUSWB */
+ ab = lp_build_intrinsic_binary(bld->builder, "llvm.x86.sse2.packuswb.128" , i16x8, abl, abh);
+
+ /* NOP */
+ ab = LLVMBuildBitCast(bld->builder, ab, i8x16, "");
+
+ return ab;
+ }
+#endif
+
+ /* FIXME */
+ assert(0);
+ }
+
+ if(LLVMIsConstant(a) && LLVMIsConstant(b))
+ return LLVMConstMul(a, b);
+
+ return LLVMBuildMul(bld->builder, a, b, "");
+}
+
+
+/**
+ * Generate a / b
+ */
+LLVMValueRef
+lp_build_div(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ const union lp_type type = bld->type;
+
+ if(a == bld->zero)
+ return bld->zero;
+ if(a == bld->one)
+ return lp_build_rcp(bld, b);
+ if(b == bld->zero)
+ return bld->undef;
+ if(b == bld->one)
+ return a;
+ if(a == bld->undef || b == bld->undef)
+ return bld->undef;
+
+ if(LLVMIsConstant(a) && LLVMIsConstant(b))
+ return LLVMConstFDiv(a, b);
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width == 32 && type.length == 4)
+ return lp_build_mul(bld, a, lp_build_rcp(bld, b));
+#endif
+
+ return LLVMBuildFDiv(bld->builder, a, b, "");
+}
+
+
+LLVMValueRef
+lp_build_lerp(struct lp_build_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef v0,
+ LLVMValueRef v1)
+{
+ return lp_build_add(bld, v0, lp_build_mul(bld, x, lp_build_sub(bld, v1, v0)));
+}
+
+
+LLVMValueRef
+lp_build_lerp_2d(struct lp_build_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef y,
+ LLVMValueRef v00,
+ LLVMValueRef v01,
+ LLVMValueRef v10,
+ LLVMValueRef v11)
+{
+ LLVMValueRef v0 = lp_build_lerp(bld, x, v00, v01);
+ LLVMValueRef v1 = lp_build_lerp(bld, x, v10, v11);
+ return lp_build_lerp(bld, y, v0, v1);
+}
+
+
+/**
+ * Generate min(a, b)
+ * Do checks for special cases.
+ */
+LLVMValueRef
+lp_build_min(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ if(a == bld->undef || b == bld->undef)
+ return bld->undef;
+
+ if(a == b)
+ return a;
+
+ if(bld->type.norm) {
+ if(a == bld->zero || b == bld->zero)
+ return bld->zero;
+ if(a == bld->one)
+ return b;
+ if(b == bld->one)
+ return a;
+ }
+
+ return lp_build_min_simple(bld, a, b);
+}
+
+
+/**
+ * Generate max(a, b)
+ * Do checks for special cases.
+ */
+LLVMValueRef
+lp_build_max(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ if(a == bld->undef || b == bld->undef)
+ return bld->undef;
+
+ if(a == b)
+ return a;
+
+ if(bld->type.norm) {
+ if(a == bld->one || b == bld->one)
+ return bld->one;
+ if(a == bld->zero)
+ return b;
+ if(b == bld->zero)
+ return a;
+ }
+
+ return lp_build_max_simple(bld, a, b);
+}
+
+
+/**
+ * Generate abs(a)
+ */
+LLVMValueRef
+lp_build_abs(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ const union lp_type type = bld->type;
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+
+ if(!type.sign)
+ return a;
+
+ if(type.floating) {
+ /* Mask out the sign bit */
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
+ LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long)1 << type.width) - 1);
+ a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
+ a = LLVMBuildAnd(bld->builder, a, mask, "");
+ a = LLVMBuildBitCast(bld->builder, a, vec_type, "");
+ return a;
+ }
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width*type.length == 128) {
+ switch(type.width) {
+ case 8:
+ return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.b.128", vec_type, a);
+ case 16:
+ return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.w.128", vec_type, a);
+ case 32:
+ return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.d.128", vec_type, a);
+ }
+ }
+#endif
+
+ return lp_build_max(bld, a, LLVMBuildNeg(bld->builder, a, ""));
+}
+
+
+enum lp_build_round_sse41_mode
+{
+ LP_BUILD_ROUND_SSE41_NEAREST = 0,
+ LP_BUILD_ROUND_SSE41_FLOOR = 1,
+ LP_BUILD_ROUND_SSE41_CEIL = 2,
+ LP_BUILD_ROUND_SSE41_TRUNCATE = 3
+};
+
+
+static INLINE LLVMValueRef
+lp_build_round_sse41(struct lp_build_context *bld,
+ LLVMValueRef a,
+ enum lp_build_round_sse41_mode mode)
+{
+ const union lp_type type = bld->type;
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ const char *intrinsic;
+
+ assert(type.floating);
+ assert(type.width*type.length == 128);
+
+ switch(type.width) {
+ case 32:
+ intrinsic = "llvm.x86.sse41.round.ps";
+ break;
+ case 64:
+ intrinsic = "llvm.x86.sse41.round.pd";
+ break;
+ default:
+ assert(0);
+ return bld->undef;
+ }
+
+ return lp_build_intrinsic_binary(bld->builder, intrinsic, vec_type, a,
+ LLVMConstInt(LLVMInt32Type(), mode, 0));
+}
+
+
+LLVMValueRef
+lp_build_floor(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ const union lp_type type = bld->type;
+
+ assert(type.floating);
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ return lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_FLOOR);
+#endif
+
+ /* FIXME */
+ assert(0);
+ return bld->undef;
+}
+
+
+/**
+ * Convert to integer, through whichever rounding method that's fastest,
+ * typically truncating to zero.
+ */
+LLVMValueRef
+lp_build_int(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ const union lp_type type = bld->type;
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
+
+ assert(type.floating);
+
+ return LLVMBuildFPToSI(bld->builder, a, int_vec_type, "");
+}
+
+
+LLVMValueRef
+lp_build_ifloor(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ a = lp_build_floor(bld, a);
+ a = lp_build_int(bld, a);
+ return a;
+}
+
+
+LLVMValueRef
+lp_build_sqrt(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ const union lp_type type = bld->type;
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ char intrinsic[32];
+
+ /* TODO: optimize the constant case */
+ /* TODO: optimize the constant case */
+
+ assert(type.floating);
+ util_snprintf(intrinsic, sizeof intrinsic, "llvm.sqrt.v%uf%u", type.length, type.width);
+
+ return lp_build_intrinsic_unary(bld->builder, intrinsic, vec_type, a);
+}
+
+
+LLVMValueRef
+lp_build_rcp(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ const union lp_type type = bld->type;
+
+ if(a == bld->zero)
+ return bld->undef;
+ if(a == bld->one)
+ return bld->one;
+ if(a == bld->undef)
+ return bld->undef;
+
+ assert(type.floating);
+
+ if(LLVMIsConstant(a))
+ return LLVMConstFDiv(bld->one, a);
+
+ /* XXX: is this really necessary? */
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width == 32 && type.length == 4)
+ return lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rcp.ps", lp_build_vec_type(type), a);
+#endif
+
+ return LLVMBuildFDiv(bld->builder, bld->one, a, "");
+}
+
+
+/**
+ * Generate 1/sqrt(a)
+ */
+LLVMValueRef
+lp_build_rsqrt(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ const union lp_type type = bld->type;
+
+ assert(type.floating);
+
+ /* XXX: is this really necessary? */
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width == 32 && type.length == 4)
+ return lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rsqrt.ps", lp_build_vec_type(type), a);
+#endif
+
+ return lp_build_rcp(bld, lp_build_sqrt(bld, a));
+}
+
+
+/**
+ * Generate cos(a)
+ */
+LLVMValueRef
+lp_build_cos(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ const union lp_type type = bld->type;
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ char intrinsic[32];
+
+ /* TODO: optimize the constant case */
+
+ assert(type.floating);
+ util_snprintf(intrinsic, sizeof intrinsic, "llvm.cos.v%uf%u", type.length, type.width);
+
+ return lp_build_intrinsic_unary(bld->builder, intrinsic, vec_type, a);
+}
+
+
+/**
+ * Generate sin(a)
+ */
+LLVMValueRef
+lp_build_sin(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ const union lp_type type = bld->type;
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ char intrinsic[32];
+
+ /* TODO: optimize the constant case */
+
+ assert(type.floating);
+ util_snprintf(intrinsic, sizeof intrinsic, "llvm.sin.v%uf%u", type.length, type.width);
+
+ return lp_build_intrinsic_unary(bld->builder, intrinsic, vec_type, a);
+}
+
+
+/**
+ * Generate pow(x, y)
+ */
+LLVMValueRef
+lp_build_pow(struct lp_build_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef y)
+{
+ /* TODO: optimize the constant case */
+ if(LLVMIsConstant(x) && LLVMIsConstant(y))
+ debug_printf("%s: inefficient/imprecise constant arithmetic\n");
+
+ return lp_build_exp2(bld, lp_build_mul(bld, lp_build_log2(bld, x), y));
+}
+
+
+/**
+ * Generate exp(x)
+ */
+LLVMValueRef
+lp_build_exp(struct lp_build_context *bld,
+ LLVMValueRef x)
+{
+ /* log2(e) = 1/log(2) */
+ LLVMValueRef log2e = lp_build_const_scalar(bld->type, 1.4426950408889634);
+
+ return lp_build_mul(bld, log2e, lp_build_exp2(bld, x));
+}
+
+
+/**
+ * Generate log(x)
+ */
+LLVMValueRef
+lp_build_log(struct lp_build_context *bld,
+ LLVMValueRef x)
+{
+ /* log(2) */
+ LLVMValueRef log2 = lp_build_const_scalar(bld->type, 1.4426950408889634);
+
+ return lp_build_mul(bld, log2, lp_build_exp2(bld, x));
+}
+
+
+#define EXP_POLY_DEGREE 3
+#define LOG_POLY_DEGREE 5
+
+
+/**
+ * Generate polynomial.
+ * Ex: x^2 * coeffs[0] + x * coeffs[1] + coeffs[2].
+ */
+static LLVMValueRef
+lp_build_polynomial(struct lp_build_context *bld,
+ LLVMValueRef x,
+ const double *coeffs,
+ unsigned num_coeffs)
+{
+ const union lp_type type = bld->type;
+ LLVMValueRef res = NULL;
+ unsigned i;
+
+ /* TODO: optimize the constant case */
+ if(LLVMIsConstant(x))
+ debug_printf("%s: inefficient/imprecise constant arithmetic\n");
+
+ for (i = num_coeffs; i--; ) {
+ LLVMValueRef coeff = lp_build_const_scalar(type, coeffs[i]);
+ if(res)
+ res = lp_build_add(bld, coeff, lp_build_mul(bld, x, res));
+ else
+ res = coeff;
+ }
+
+ if(res)
+ return res;
+ else
+ return bld->undef;
+}
+
+
+/**
+ * Minimax polynomial fit of 2**x, in range [-0.5, 0.5[
+ */
+const double lp_build_exp2_polynomial[] = {
+#if EXP_POLY_DEGREE == 5
+ 9.9999994e-1, 6.9315308e-1, 2.4015361e-1, 5.5826318e-2, 8.9893397e-3, 1.8775767e-3
+#elif EXP_POLY_DEGREE == 4
+ 1.0000026, 6.9300383e-1, 2.4144275e-1, 5.2011464e-2, 1.3534167e-2
+#elif EXP_POLY_DEGREE == 3
+ 9.9992520e-1, 6.9583356e-1, 2.2606716e-1, 7.8024521e-2
+#elif EXP_POLY_DEGREE == 2
+ 1.0017247, 6.5763628e-1, 3.3718944e-1
+#else
+#error
+#endif
+};
+
+
+void
+lp_build_exp2_approx(struct lp_build_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef *p_exp2_int_part,
+ LLVMValueRef *p_frac_part,
+ LLVMValueRef *p_exp2)
+{
+ const union lp_type type = bld->type;
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
+ LLVMValueRef ipart = NULL;
+ LLVMValueRef fpart = NULL;
+ LLVMValueRef expipart = NULL;
+ LLVMValueRef expfpart = NULL;
+ LLVMValueRef res = NULL;
+
+ if(p_exp2_int_part || p_frac_part || p_exp2) {
+ /* TODO: optimize the constant case */
+ if(LLVMIsConstant(x))
+ debug_printf("%s: inefficient/imprecise constant arithmetic\n");
+
+ assert(type.floating && type.width == 32);
+
+ x = lp_build_min(bld, x, lp_build_const_scalar(type, 129.0));
+ x = lp_build_max(bld, x, lp_build_const_scalar(type, -126.99999));
+
+ /* ipart = int(x - 0.5) */
+ ipart = LLVMBuildSub(bld->builder, x, lp_build_const_scalar(type, 0.5f), "");
+ ipart = LLVMBuildFPToSI(bld->builder, ipart, int_vec_type, "");
+
+ /* fpart = x - ipart */
+ fpart = LLVMBuildSIToFP(bld->builder, ipart, vec_type, "");
+ fpart = LLVMBuildSub(bld->builder, x, fpart, "");
+ }
+
+ if(p_exp2_int_part || p_exp2) {
+ /* expipart = (float) (1 << ipart) */
+ expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_int_const_scalar(type, 127), "");
+ expipart = LLVMBuildShl(bld->builder, expipart, lp_build_int_const_scalar(type, 23), "");
+ expipart = LLVMBuildBitCast(bld->builder, expipart, vec_type, "");
+ }
+
+ if(p_exp2) {
+ expfpart = lp_build_polynomial(bld, fpart, lp_build_exp2_polynomial,
+ Elements(lp_build_exp2_polynomial));
+
+ res = LLVMBuildMul(bld->builder, expipart, expfpart, "");
+ }
+
+ if(p_exp2_int_part)
+ *p_exp2_int_part = expipart;
+
+ if(p_frac_part)
+ *p_frac_part = fpart;
+
+ if(p_exp2)
+ *p_exp2 = res;
+}
+
+
+LLVMValueRef
+lp_build_exp2(struct lp_build_context *bld,
+ LLVMValueRef x)
+{
+ LLVMValueRef res;
+ lp_build_exp2_approx(bld, x, NULL, NULL, &res);
+ return res;
+}
+
+
+/**
+ * Minimax polynomial fit of log2(x)/(x - 1), for x in range [1, 2[
+ * These coefficients can be generate with
+ * http://www.boost.org/doc/libs/1_36_0/libs/math/doc/sf_and_dist/html/math_toolkit/toolkit/internals2/minimax.html
+ */
+const double lp_build_log2_polynomial[] = {
+#if LOG_POLY_DEGREE == 6
+ 3.11578814719469302614, -3.32419399085241980044, 2.59883907202499966007, -1.23152682416275988241, 0.318212422185251071475, -0.0344359067839062357313
+#elif LOG_POLY_DEGREE == 5
+ 2.8882704548164776201, -2.52074962577807006663, 1.48116647521213171641, -0.465725644288844778798, 0.0596515482674574969533
+#elif LOG_POLY_DEGREE == 4
+ 2.61761038894603480148, -1.75647175389045657003, 0.688243882994381274313, -0.107254423828329604454
+#elif LOG_POLY_DEGREE == 3
+ 2.28330284476918490682, -1.04913055217340124191, 0.204446009836232697516
+#else
+#error
+#endif
+};
+
+
+/**
+ * See http://www.devmaster.net/forums/showthread.php?p=43580
+ */
+void
+lp_build_log2_approx(struct lp_build_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef *p_exp,
+ LLVMValueRef *p_floor_log2,
+ LLVMValueRef *p_log2)
+{
+ const union lp_type type = bld->type;
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
+
+ LLVMValueRef expmask = lp_build_int_const_scalar(type, 0x7f800000);
+ LLVMValueRef mantmask = lp_build_int_const_scalar(type, 0x007fffff);
+ LLVMValueRef one = LLVMConstBitCast(bld->one, int_vec_type);
+
+ LLVMValueRef i = NULL;
+ LLVMValueRef exp = NULL;
+ LLVMValueRef mant = NULL;
+ LLVMValueRef logexp = NULL;
+ LLVMValueRef logmant = NULL;
+ LLVMValueRef res = NULL;
+
+ if(p_exp || p_floor_log2 || p_log2) {
+ /* TODO: optimize the constant case */
+ if(LLVMIsConstant(x))
+ debug_printf("%s: inefficient/imprecise constant arithmetic\n");
+
+ assert(type.floating && type.width == 32);
+
+ i = LLVMBuildBitCast(bld->builder, x, int_vec_type, "");
+
+ /* exp = (float) exponent(x) */
+ exp = LLVMBuildAnd(bld->builder, i, expmask, "");
+ }
+
+ if(p_floor_log2 || p_log2) {
+ logexp = LLVMBuildLShr(bld->builder, exp, lp_build_int_const_scalar(type, 23), "");
+ logexp = LLVMBuildSub(bld->builder, logexp, lp_build_int_const_scalar(type, 127), "");
+ logexp = LLVMBuildSIToFP(bld->builder, logexp, vec_type, "");
+ }
+
+ if(p_log2) {
+ /* mant = (float) mantissa(x) */
+ mant = LLVMBuildAnd(bld->builder, i, mantmask, "");
+ mant = LLVMBuildOr(bld->builder, mant, one, "");
+ mant = LLVMBuildSIToFP(bld->builder, mant, vec_type, "");
+
+ logmant = lp_build_polynomial(bld, mant, lp_build_log2_polynomial,
+ Elements(lp_build_log2_polynomial));
+
+ /* This effectively increases the polynomial degree by one, but ensures that log2(1) == 0*/
+ logmant = LLVMBuildMul(bld->builder, logmant, LLVMBuildMul(bld->builder, mant, bld->one, ""), "");
+
+ res = LLVMBuildAdd(bld->builder, logmant, logexp, "");
+ }
+
+ if(p_exp)
+ *p_exp = exp;
+
+ if(p_floor_log2)
+ *p_floor_log2 = logexp;
+
+ if(p_log2)
+ *p_log2 = res;
+}
+
+
+LLVMValueRef
+lp_build_log2(struct lp_build_context *bld,
+ LLVMValueRef x)
+{
+ LLVMValueRef res;
+ lp_build_log2_approx(bld, x, NULL, NULL, &res);
+ return res;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_arit.h b/src/gallium/drivers/llvmpipe/lp_bld_arit.h
new file mode 100644
index 0000000000..383c3c3313
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_arit.h
@@ -0,0 +1,175 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Helper arithmetic functions.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifndef LP_BLD_ARIT_H
+#define LP_BLD_ARIT_H
+
+
+#include <llvm-c/Core.h>
+
+
+union lp_type type;
+struct lp_build_context;
+
+
+/**
+ * Complement, i.e., 1 - a.
+ */
+LLVMValueRef
+lp_build_comp(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_add(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+LLVMValueRef
+lp_build_sub(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+LLVMValueRef
+lp_build_mul(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+LLVMValueRef
+lp_build_div(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+LLVMValueRef
+lp_build_lerp(struct lp_build_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef v0,
+ LLVMValueRef v1);
+
+/**
+ * Bilinear interpolation.
+ *
+ * Values indices are in v_{yx}.
+ */
+LLVMValueRef
+lp_build_lerp_2d(struct lp_build_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef y,
+ LLVMValueRef v00,
+ LLVMValueRef v01,
+ LLVMValueRef v10,
+ LLVMValueRef v11);
+
+LLVMValueRef
+lp_build_min(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+LLVMValueRef
+lp_build_max(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+LLVMValueRef
+lp_build_abs(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_floor(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_int(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_ifloor(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_sqrt(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_rcp(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_rsqrt(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_cos(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_sin(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_pow(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+LLVMValueRef
+lp_build_exp(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_log(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_exp2(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+LLVMValueRef
+lp_build_log2(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+void
+lp_build_exp2_approx(struct lp_build_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef *p_exp2_int_part,
+ LLVMValueRef *p_frac_part,
+ LLVMValueRef *p_exp2);
+
+void
+lp_build_log2_approx(struct lp_build_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef *p_exp,
+ LLVMValueRef *p_floor_log2,
+ LLVMValueRef *p_log2);
+
+#endif /* !LP_BLD_ARIT_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend.h b/src/gallium/drivers/llvmpipe/lp_bld_blend.h
new file mode 100644
index 0000000000..d19e18846c
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_blend.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_BLD_BLEND_H
+#define LP_BLD_BLEND_H
+
+
+/**
+ * @file
+ * LLVM IR building helpers interfaces.
+ *
+ * We use LLVM-C bindings for now. They are not documented, but follow the C++
+ * interfaces very closely, and appear to be complete enough for code
+ * genration. See
+ * http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html
+ * for a standalone example.
+ */
+
+#include <llvm-c/Core.h>
+
+#include "pipe/p_format.h"
+
+
+struct pipe_blend_state;
+union lp_type;
+struct lp_build_context;
+
+
+/**
+ * Whether the blending function is commutative or not.
+ */
+boolean
+lp_build_blend_func_commutative(unsigned func);
+
+
+/**
+ * Whether the blending functions are the reverse of each other.
+ */
+boolean
+lp_build_blend_func_reverse(unsigned rgb_func, unsigned alpha_func);
+
+
+LLVMValueRef
+lp_build_blend_func(struct lp_build_context *bld,
+ unsigned func,
+ LLVMValueRef term1,
+ LLVMValueRef term2);
+
+
+LLVMValueRef
+lp_build_blend_aos(LLVMBuilderRef builder,
+ const struct pipe_blend_state *blend,
+ union lp_type type,
+ LLVMValueRef src,
+ LLVMValueRef dst,
+ LLVMValueRef const_,
+ unsigned alpha_swizzle);
+
+
+void
+lp_build_blend_soa(LLVMBuilderRef builder,
+ const struct pipe_blend_state *blend,
+ union lp_type type,
+ LLVMValueRef src[4],
+ LLVMValueRef dst[4],
+ LLVMValueRef const_[4],
+ LLVMValueRef res[4]);
+
+
+/**
+ * Apply a logic op.
+ *
+ * src/dst parameters are packed values. It should work regardless the inputs
+ * are scalars, or a vector.
+ */
+LLVMValueRef
+lp_build_logicop(LLVMBuilderRef builder,
+ unsigned logicop_func,
+ LLVMValueRef src,
+ LLVMValueRef dst);
+
+
+#endif /* !LP_BLD_BLEND_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c
new file mode 100644
index 0000000000..c11a9398f8
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c
@@ -0,0 +1,356 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Blend LLVM IR generation -- AoS layout.
+ *
+ * AoS blending is in general much slower than SoA, but there are some cases
+ * where it might be faster. In particular, if a pixel is rendered only once
+ * then the overhead of tiling and untiling will dominate over the speedup that
+ * SoA gives. So we might want to detect such cases and fallback to AoS in the
+ * future, but for now this function is here for historical/benchmarking
+ * purposes.
+ *
+ * Run lp_blend_test after any change to this file.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "pipe/p_state.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_arit.h"
+#include "lp_bld_logic.h"
+#include "lp_bld_swizzle.h"
+#include "lp_bld_blend.h"
+#include "lp_bld_debug.h"
+
+
+/**
+ * We may the same values several times, so we keep them here to avoid
+ * recomputing them. Also reusing the values allows us to do simplifications
+ * that LLVM optimization passes wouldn't normally be able to do.
+ */
+struct lp_build_blend_aos_context
+{
+ struct lp_build_context base;
+
+ LLVMValueRef src;
+ LLVMValueRef dst;
+ LLVMValueRef const_;
+
+ LLVMValueRef inv_src;
+ LLVMValueRef inv_dst;
+ LLVMValueRef inv_const;
+ LLVMValueRef saturate;
+
+ LLVMValueRef rgb_src_factor;
+ LLVMValueRef alpha_src_factor;
+ LLVMValueRef rgb_dst_factor;
+ LLVMValueRef alpha_dst_factor;
+};
+
+
+static LLVMValueRef
+lp_build_blend_factor_unswizzled(struct lp_build_blend_aos_context *bld,
+ unsigned factor,
+ boolean alpha)
+{
+ switch (factor) {
+ case PIPE_BLENDFACTOR_ZERO:
+ return bld->base.zero;
+ case PIPE_BLENDFACTOR_ONE:
+ return bld->base.one;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ return bld->src;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ return bld->dst;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ if(alpha)
+ return bld->base.one;
+ else {
+ if(!bld->inv_dst)
+ bld->inv_dst = lp_build_comp(&bld->base, bld->dst);
+ if(!bld->saturate)
+ bld->saturate = lp_build_min(&bld->base, bld->src, bld->inv_dst);
+ return bld->saturate;
+ }
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ return bld->const_;
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ /* TODO */
+ assert(0);
+ return bld->base.zero;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ if(!bld->inv_src)
+ bld->inv_src = lp_build_comp(&bld->base, bld->src);
+ return bld->inv_src;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ if(!bld->inv_dst)
+ bld->inv_dst = lp_build_comp(&bld->base, bld->dst);
+ return bld->inv_dst;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ if(!bld->inv_const)
+ bld->inv_const = lp_build_comp(&bld->base, bld->const_);
+ return bld->inv_const;
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ /* TODO */
+ assert(0);
+ return bld->base.zero;
+ default:
+ assert(0);
+ return bld->base.zero;
+ }
+}
+
+
+enum lp_build_blend_swizzle {
+ LP_BUILD_BLEND_SWIZZLE_RGBA = 0,
+ LP_BUILD_BLEND_SWIZZLE_AAAA = 1,
+};
+
+
+/**
+ * How should we shuffle the base factor.
+ */
+static enum lp_build_blend_swizzle
+lp_build_blend_factor_swizzle(unsigned factor)
+{
+ switch (factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ case PIPE_BLENDFACTOR_ZERO:
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ return LP_BUILD_BLEND_SWIZZLE_RGBA;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ return LP_BUILD_BLEND_SWIZZLE_AAAA;
+ default:
+ assert(0);
+ return LP_BUILD_BLEND_SWIZZLE_RGBA;
+ }
+}
+
+
+static LLVMValueRef
+lp_build_blend_swizzle(struct lp_build_blend_aos_context *bld,
+ LLVMValueRef rgb,
+ LLVMValueRef alpha,
+ enum lp_build_blend_swizzle rgb_swizzle,
+ unsigned alpha_swizzle)
+{
+ if(rgb == alpha) {
+ if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_RGBA)
+ return rgb;
+ if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_AAAA)
+ return lp_build_broadcast_aos(&bld->base, rgb, alpha_swizzle);
+ }
+ else {
+ if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_RGBA) {
+ boolean cond[4] = {0, 0, 0, 0};
+ cond[alpha_swizzle] = 1;
+ return lp_build_select_aos(&bld->base, alpha, rgb, cond);
+ }
+ if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_AAAA) {
+ unsigned char swizzle[4];
+ swizzle[0] = alpha_swizzle;
+ swizzle[1] = alpha_swizzle;
+ swizzle[2] = alpha_swizzle;
+ swizzle[3] = alpha_swizzle;
+ swizzle[alpha_swizzle] += 4;
+ return lp_build_swizzle2_aos(&bld->base, rgb, alpha, swizzle);
+ }
+ }
+ assert(0);
+ return bld->base.undef;
+}
+
+
+/**
+ * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml
+ */
+static LLVMValueRef
+lp_build_blend_factor(struct lp_build_blend_aos_context *bld,
+ LLVMValueRef factor1,
+ unsigned rgb_factor,
+ unsigned alpha_factor,
+ unsigned alpha_swizzle)
+{
+ LLVMValueRef rgb_factor_;
+ LLVMValueRef alpha_factor_;
+ LLVMValueRef factor2;
+ enum lp_build_blend_swizzle rgb_swizzle;
+
+ rgb_factor_ = lp_build_blend_factor_unswizzled(bld, rgb_factor, FALSE);
+ alpha_factor_ = lp_build_blend_factor_unswizzled(bld, alpha_factor, TRUE);
+
+ rgb_swizzle = lp_build_blend_factor_swizzle(rgb_factor);
+
+ factor2 = lp_build_blend_swizzle(bld, rgb_factor_, alpha_factor_, rgb_swizzle, alpha_swizzle);
+
+ return lp_build_mul(&bld->base, factor1, factor2);
+}
+
+
+boolean
+lp_build_blend_func_commutative(unsigned func)
+{
+ switch (func) {
+ case PIPE_BLEND_ADD:
+ case PIPE_BLEND_MIN:
+ case PIPE_BLEND_MAX:
+ return TRUE;
+ case PIPE_BLEND_SUBTRACT:
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ return FALSE;
+ default:
+ assert(0);
+ return TRUE;
+ }
+}
+
+
+boolean
+lp_build_blend_func_reverse(unsigned rgb_func, unsigned alpha_func)
+{
+ if(rgb_func == alpha_func)
+ return FALSE;
+ if(rgb_func == PIPE_BLEND_SUBTRACT && alpha_func == PIPE_BLEND_REVERSE_SUBTRACT)
+ return TRUE;
+ if(rgb_func == PIPE_BLEND_REVERSE_SUBTRACT && alpha_func == PIPE_BLEND_SUBTRACT)
+ return TRUE;
+ return FALSE;
+}
+
+
+/**
+ * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml
+ */
+LLVMValueRef
+lp_build_blend_func(struct lp_build_context *bld,
+ unsigned func,
+ LLVMValueRef term1,
+ LLVMValueRef term2)
+{
+ switch (func) {
+ case PIPE_BLEND_ADD:
+ return lp_build_add(bld, term1, term2);
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ return lp_build_sub(bld, term1, term2);
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ return lp_build_sub(bld, term2, term1);
+ case PIPE_BLEND_MIN:
+ return lp_build_min(bld, term1, term2);
+ case PIPE_BLEND_MAX:
+ return lp_build_max(bld, term1, term2);
+ default:
+ assert(0);
+ return bld->zero;
+ }
+}
+
+
+LLVMValueRef
+lp_build_blend_aos(LLVMBuilderRef builder,
+ const struct pipe_blend_state *blend,
+ union lp_type type,
+ LLVMValueRef src,
+ LLVMValueRef dst,
+ LLVMValueRef const_,
+ unsigned alpha_swizzle)
+{
+ struct lp_build_blend_aos_context bld;
+ LLVMValueRef src_term;
+ LLVMValueRef dst_term;
+
+ /* FIXME */
+ assert(blend->colormask == 0xf);
+
+ if(!blend->blend_enable)
+ return src;
+
+ /* It makes no sense to blend unless values are normalized */
+ assert(type.norm);
+
+ /* Setup build context */
+ memset(&bld, 0, sizeof bld);
+ lp_build_context_init(&bld.base, builder, type);
+ bld.src = src;
+ bld.dst = dst;
+ bld.const_ = const_;
+
+ /* TODO: There are still a few optimization opportunities here. For certain
+ * combinations it is possible to reorder the operations and therefore saving
+ * some instructions. */
+
+ src_term = lp_build_blend_factor(&bld, src, blend->rgb_src_factor, blend->alpha_src_factor, alpha_swizzle);
+ dst_term = lp_build_blend_factor(&bld, dst, blend->rgb_dst_factor, blend->alpha_dst_factor, alpha_swizzle);
+
+ lp_build_name(src_term, "src_term");
+ lp_build_name(dst_term, "dst_term");
+
+ if(blend->rgb_func == blend->alpha_func) {
+ return lp_build_blend_func(&bld.base, blend->rgb_func, src_term, dst_term);
+ }
+ else {
+ /* Seperate RGB / A functions */
+
+ LLVMValueRef rgb;
+ LLVMValueRef alpha;
+
+ rgb = lp_build_blend_func(&bld.base, blend->rgb_func, src_term, dst_term);
+ alpha = lp_build_blend_func(&bld.base, blend->alpha_func, src_term, dst_term);
+
+ return lp_build_blend_swizzle(&bld, rgb, alpha, LP_BUILD_BLEND_SWIZZLE_RGBA, alpha_swizzle);
+ }
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_logicop.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_logicop.c
new file mode 100644
index 0000000000..88321f62a2
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_logicop.c
@@ -0,0 +1,108 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Blend LLVM IR generation -- logic ops.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "pipe/p_state.h"
+
+#include "lp_bld_blend.h"
+
+
+LLVMValueRef
+lp_build_logicop(LLVMBuilderRef builder,
+ unsigned logicop_func,
+ LLVMValueRef src,
+ LLVMValueRef dst)
+{
+ LLVMTypeRef type;
+ LLVMValueRef res;
+
+ type = LLVMTypeOf(src);
+
+ switch (logicop_func) {
+ case PIPE_LOGICOP_CLEAR:
+ res = LLVMConstNull(type);
+ break;
+ case PIPE_LOGICOP_NOR:
+ res = LLVMBuildNot(builder, LLVMBuildOr(builder, src, dst, ""), "");
+ break;
+ case PIPE_LOGICOP_AND_INVERTED:
+ res = LLVMBuildAnd(builder, LLVMBuildNot(builder, src, ""), dst, "");
+ break;
+ case PIPE_LOGICOP_COPY_INVERTED:
+ res = LLVMBuildNot(builder, src, "");
+ break;
+ case PIPE_LOGICOP_AND_REVERSE:
+ res = LLVMBuildAnd(builder, src, LLVMBuildNot(builder, dst, ""), "");
+ break;
+ case PIPE_LOGICOP_INVERT:
+ res = LLVMBuildNot(builder, dst, "");
+ break;
+ case PIPE_LOGICOP_XOR:
+ res = LLVMBuildXor(builder, src, dst, "");
+ break;
+ case PIPE_LOGICOP_NAND:
+ res = LLVMBuildNot(builder, LLVMBuildAnd(builder, src, dst, ""), "");
+ break;
+ case PIPE_LOGICOP_AND:
+ res = LLVMBuildAnd(builder, src, dst, "");
+ break;
+ case PIPE_LOGICOP_EQUIV:
+ res = LLVMBuildNot(builder, LLVMBuildXor(builder, src, dst, ""), "");
+ break;
+ case PIPE_LOGICOP_NOOP:
+ res = dst;
+ break;
+ case PIPE_LOGICOP_OR_INVERTED:
+ res = LLVMBuildOr(builder, LLVMBuildNot(builder, src, ""), dst, "");
+ break;
+ case PIPE_LOGICOP_COPY:
+ res = src;
+ break;
+ case PIPE_LOGICOP_OR_REVERSE:
+ res = LLVMBuildOr(builder, src, LLVMBuildNot(builder, dst, ""), "");
+ break;
+ case PIPE_LOGICOP_OR:
+ res = LLVMBuildOr(builder, src, dst, "");
+ break;
+ case PIPE_LOGICOP_SET:
+ res = LLVMConstAllOnes(type);
+ break;
+ default:
+ assert(0);
+ res = src;
+ }
+
+ return res;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c
new file mode 100644
index 0000000000..b92254a7d6
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c
@@ -0,0 +1,298 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Blend LLVM IR generation -- SoA layout.
+ *
+ * Blending in SoA is much faster than AoS, especially when separate rgb/alpha
+ * factors/functions are used, since no channel masking/shuffling is necessary
+ * and we can achieve the full throughput of the SIMD operations. Furthermore
+ * the fragment shader output is also in SoA, so it fits nicely with the rest of
+ * the fragment pipeline.
+ *
+ * The drawback is that to be displayed the color buffer needs to be in AoS
+ * layout, so we need to tile/untile the color buffer before/after rendering.
+ * A color buffer like
+ *
+ * R11 G11 B11 A11 R12 G12 B12 A12 R13 G13 B13 A13 R14 G14 B14 A14 ...
+ * R21 G21 B21 A21 R22 G22 B22 A22 R23 G23 B23 A23 R24 G24 B24 A24 ...
+ *
+ * R31 G31 B31 A31 R32 G32 B32 A32 R33 G33 B33 A33 R34 G34 B34 A34 ...
+ * R41 G41 B41 A41 R42 G42 B42 A42 R43 G43 B43 A43 R44 G44 B44 A44 ...
+ *
+ * ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+ *
+ * will actually be stored in memory as
+ *
+ * R11 R12 R21 R22 R13 R14 R23 R24 ... G11 G12 G21 G22 G13 G14 G23 G24 ... B11 B12 B21 B22 B13 B14 B23 B24 ... A11 A12 A21 A22 A13 A14 A23 A24 ...
+ * R31 R32 R41 R42 R33 R34 R43 R44 ... G31 G32 G41 G42 G33 G34 G43 G44 ... B31 B32 B41 B42 B33 B34 B43 B44 ... A31 A32 A41 A42 A33 A34 A43 A44 ...
+ * ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+ *
+ * NOTE: Run lp_blend_test after any change to this file.
+ *
+ * You can also run lp_blend_test to obtain AoS vs SoA benchmarks. Invoking it
+ * as:
+ *
+ * lp_blend_test -o blend.tsv
+ *
+ * will generate a tab-seperated-file with the test results and performance
+ * measurements.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "pipe/p_state.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_arit.h"
+#include "lp_bld_blend.h"
+
+
+/**
+ * We may the same values several times, so we keep them here to avoid
+ * recomputing them. Also reusing the values allows us to do simplifications
+ * that LLVM optimization passes wouldn't normally be able to do.
+ */
+struct lp_build_blend_soa_context
+{
+ struct lp_build_context base;
+
+ LLVMValueRef src[4];
+ LLVMValueRef dst[4];
+ LLVMValueRef con[4];
+
+ LLVMValueRef inv_src[4];
+ LLVMValueRef inv_dst[4];
+ LLVMValueRef inv_con[4];
+
+ LLVMValueRef src_alpha_saturate;
+
+ /**
+ * We store all factors in a table in order to eliminate redundant
+ * multiplications later.
+ */
+ LLVMValueRef factor[2][2][4];
+
+ /**
+ * Table with all terms.
+ */
+ LLVMValueRef term[2][4];
+};
+
+
+static LLVMValueRef
+lp_build_blend_soa_factor(struct lp_build_blend_soa_context *bld,
+ unsigned factor, unsigned i)
+{
+ /*
+ * Compute src/first term RGB
+ */
+ switch (factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ return bld->base.one;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ return bld->src[i];
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ return bld->src[3];
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ return bld->dst[i];
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ return bld->dst[3];
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ if(i == 3)
+ return bld->base.one;
+ else {
+ if(!bld->inv_dst[3])
+ bld->inv_dst[3] = lp_build_comp(&bld->base, bld->dst[3]);
+ if(!bld->src_alpha_saturate)
+ bld->src_alpha_saturate = lp_build_min(&bld->base, bld->src[3], bld->inv_dst[3]);
+ return bld->src_alpha_saturate;
+ }
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ return bld->con[i];
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ return bld->con[3];
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ /* TODO */
+ assert(0);
+ return bld->base.zero;
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ /* TODO */
+ assert(0);
+ return bld->base.zero;
+ case PIPE_BLENDFACTOR_ZERO:
+ return bld->base.zero;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ if(!bld->inv_src[i])
+ bld->inv_src[i] = lp_build_comp(&bld->base, bld->src[i]);
+ return bld->inv_src[i];
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ if(!bld->inv_src[3])
+ bld->inv_src[3] = lp_build_comp(&bld->base, bld->src[3]);
+ return bld->inv_src[3];
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ if(!bld->inv_dst[i])
+ bld->inv_dst[i] = lp_build_comp(&bld->base, bld->dst[i]);
+ return bld->inv_dst[i];
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ if(!bld->inv_dst[3])
+ bld->inv_dst[3] = lp_build_comp(&bld->base, bld->dst[3]);
+ return bld->inv_dst[3];
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ if(!bld->inv_con[i])
+ bld->inv_con[i] = lp_build_comp(&bld->base, bld->con[i]);
+ return bld->inv_con[i];
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ if(!bld->inv_con[3])
+ bld->inv_con[3] = lp_build_comp(&bld->base, bld->con[3]);
+ return bld->inv_con[3];
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ /* TODO */
+ assert(0);
+ return bld->base.zero;
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ /* TODO */
+ assert(0);
+ return bld->base.zero;
+ default:
+ assert(0);
+ return bld->base.zero;
+ }
+}
+
+
+/**
+ * Generate blend code in SOA mode.
+ * \param src src/fragment color
+ * \param dst dst/framebuffer color
+ * \param con constant blend color
+ * \param res the result/output
+ */
+void
+lp_build_blend_soa(LLVMBuilderRef builder,
+ const struct pipe_blend_state *blend,
+ union lp_type type,
+ LLVMValueRef src[4],
+ LLVMValueRef dst[4],
+ LLVMValueRef con[4],
+ LLVMValueRef res[4])
+{
+ struct lp_build_blend_soa_context bld;
+ unsigned i, j, k;
+
+ /* Setup build context */
+ memset(&bld, 0, sizeof bld);
+ lp_build_context_init(&bld.base, builder, type);
+ for (i = 0; i < 4; ++i) {
+ bld.src[i] = src[i];
+ bld.dst[i] = dst[i];
+ bld.con[i] = con[i];
+ }
+
+ for (i = 0; i < 4; ++i) {
+ if (blend->colormask & (1 << i)) {
+ if (blend->logicop_enable) {
+ if(!type.floating) {
+ res[i] = lp_build_logicop(builder, blend->logicop_func, src[i], dst[i]);
+ }
+ else
+ res[i] = dst[i];
+ }
+ else if (blend->blend_enable) {
+ unsigned src_factor = i < 3 ? blend->rgb_src_factor : blend->alpha_src_factor;
+ unsigned dst_factor = i < 3 ? blend->rgb_dst_factor : blend->alpha_dst_factor;
+ unsigned func = i < 3 ? blend->rgb_func : blend->alpha_func;
+ boolean func_commutative = lp_build_blend_func_commutative(func);
+
+ /* It makes no sense to blend unless values are normalized */
+ assert(type.norm);
+
+ /*
+ * Compute src/dst factors.
+ */
+
+ bld.factor[0][0][i] = src[i];
+ bld.factor[0][1][i] = lp_build_blend_soa_factor(&bld, src_factor, i);
+ bld.factor[1][0][i] = dst[i];
+ bld.factor[1][1][i] = lp_build_blend_soa_factor(&bld, dst_factor, i);
+
+ /*
+ * Compute src/dst terms
+ */
+
+ for(k = 0; k < 2; ++k) {
+ /* See if this multiplication has been previously computed */
+ for(j = 0; j < i; ++j) {
+ if((bld.factor[k][0][j] == bld.factor[k][0][i] &&
+ bld.factor[k][1][j] == bld.factor[k][1][i]) ||
+ (bld.factor[k][0][j] == bld.factor[k][1][i] &&
+ bld.factor[k][1][j] == bld.factor[k][0][i]))
+ break;
+ }
+
+ if(j < i)
+ bld.term[k][i] = bld.term[k][j];
+ else
+ bld.term[k][i] = lp_build_mul(&bld.base, bld.factor[k][0][i], bld.factor[k][1][i]);
+ }
+
+ /*
+ * Combine terms
+ */
+
+ /* See if this function has been previously applied */
+ for(j = 0; j < i; ++j) {
+ unsigned prev_func = j < 3 ? blend->rgb_func : blend->alpha_func;
+ unsigned func_reverse = lp_build_blend_func_reverse(func, prev_func);
+
+ if((!func_reverse &&
+ bld.term[0][j] == bld.term[0][i] &&
+ bld.term[1][j] == bld.term[1][i]) ||
+ ((func_commutative || func_reverse) &&
+ bld.term[0][j] == bld.term[1][i] &&
+ bld.term[1][j] == bld.term[0][i]))
+ break;
+ }
+
+ if(j < i)
+ res[i] = res[j];
+ else
+ res[i] = lp_build_blend_func(&bld.base, func, bld.term[0][i], bld.term[1][i]);
+ }
+ else {
+ res[i] = src[i];
+ }
+ }
+ else {
+ res[i] = dst[i];
+ }
+ }
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_const.c b/src/gallium/drivers/llvmpipe/lp_bld_const.c
new file mode 100644
index 0000000000..21487365ea
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_const.c
@@ -0,0 +1,369 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Helper functions for constant building.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include <float.h>
+
+#include "util/u_debug.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+
+
+unsigned
+lp_mantissa(union lp_type type)
+{
+ assert(type.floating);
+
+ if(type.floating) {
+ switch(type.width) {
+ case 32:
+ return 23;
+ case 64:
+ return 53;
+ default:
+ assert(0);
+ return 0;
+ }
+ }
+ else {
+ if(type.sign)
+ return type.width - 1;
+ else
+ return type.width;
+ }
+}
+
+
+/**
+ * Shift of the unity.
+ *
+ * Same as lp_const_scale(), but in terms of shifts.
+ */
+unsigned
+lp_const_shift(union lp_type type)
+{
+ if(type.floating)
+ return 0;
+ else if(type.fixed)
+ return type.width/2;
+ else if(type.norm)
+ return type.sign ? type.width - 1 : type.width;
+ else
+ return 0;
+}
+
+
+unsigned
+lp_const_offset(union lp_type type)
+{
+ if(type.floating || type.fixed)
+ return 0;
+ else if(type.norm)
+ return 1;
+ else
+ return 0;
+}
+
+
+/**
+ * Scaling factor between the LLVM native value and its interpretation.
+ *
+ * This is 1.0 for all floating types and unnormalized integers, and something
+ * else for the fixed points types and normalized integers.
+ */
+double
+lp_const_scale(union lp_type type)
+{
+ unsigned long long llscale;
+ double dscale;
+
+ llscale = (unsigned long long)1 << lp_const_shift(type);
+ llscale -= lp_const_offset(type);
+ dscale = (double)llscale;
+ assert((unsigned long long)dscale == llscale);
+
+ return dscale;
+}
+
+
+/**
+ * Minimum value representable by the type.
+ */
+double
+lp_const_min(union lp_type type)
+{
+ unsigned bits;
+
+ if(!type.sign)
+ return 0.0;
+
+ if(type.norm)
+ return -1.0;
+
+ if (type.floating) {
+ switch(type.width) {
+ case 32:
+ return -FLT_MAX;
+ case 64:
+ return -DBL_MAX;
+ default:
+ assert(0);
+ return 0.0;
+ }
+ }
+
+ if(type.fixed)
+ /* FIXME: consider the fractional bits? */
+ bits = type.width / 2 - 1;
+ else
+ bits = type.width - 1;
+
+ return (double)-((long long)1 << bits);
+}
+
+
+/**
+ * Maximum value representable by the type.
+ */
+double
+lp_const_max(union lp_type type)
+{
+ unsigned bits;
+
+ if(type.norm)
+ return 1.0;
+
+ if (type.floating) {
+ switch(type.width) {
+ case 32:
+ return FLT_MAX;
+ case 64:
+ return DBL_MAX;
+ default:
+ assert(0);
+ return 0.0;
+ }
+ }
+
+ if(type.fixed)
+ bits = type.width / 2;
+ else
+ bits = type.width;
+
+ if(type.sign)
+ bits -= 1;
+
+ return (double)(((unsigned long long)1 << bits) - 1);
+}
+
+
+double
+lp_const_eps(union lp_type type)
+{
+ if (type.floating) {
+ switch(type.width) {
+ case 32:
+ return FLT_EPSILON;
+ case 64:
+ return DBL_EPSILON;
+ default:
+ assert(0);
+ return 0.0;
+ }
+ }
+ else {
+ double scale = lp_const_scale(type);
+ return 1.0/scale;
+ }
+}
+
+
+LLVMValueRef
+lp_build_undef(union lp_type type)
+{
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ return LLVMGetUndef(vec_type);
+}
+
+
+LLVMValueRef
+lp_build_zero(union lp_type type)
+{
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ return LLVMConstNull(vec_type);
+}
+
+
+LLVMValueRef
+lp_build_one(union lp_type type)
+{
+ LLVMTypeRef elem_type;
+ LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+ unsigned i;
+
+ assert(type.length <= LP_MAX_VECTOR_LENGTH);
+
+ elem_type = lp_build_elem_type(type);
+
+ if(type.floating)
+ elems[0] = LLVMConstReal(elem_type, 1.0);
+ else if(type.fixed)
+ elems[0] = LLVMConstInt(elem_type, 1LL << (type.width/2), 0);
+ else if(!type.norm)
+ elems[0] = LLVMConstInt(elem_type, 1, 0);
+ else if(type.sign)
+ elems[0] = LLVMConstInt(elem_type, (1LL << (type.width - 1)) - 1, 0);
+ else {
+ /* special case' -- 1.0 for normalized types is more easily attained if
+ * we start with a vector consisting of all bits set */
+ LLVMTypeRef vec_type = LLVMVectorType(elem_type, type.length);
+ LLVMValueRef vec = LLVMConstAllOnes(vec_type);
+
+#if 0
+ if(type.sign)
+ /* TODO: Unfortunately this caused "Tried to create a shift operation
+ * on a non-integer type!" */
+ vec = LLVMConstLShr(vec, lp_build_int_const_scalar(type, 1));
+#endif
+
+ return vec;
+ }
+
+ for(i = 1; i < type.length; ++i)
+ elems[i] = elems[0];
+
+ return LLVMConstVector(elems, type.length);
+}
+
+
+LLVMValueRef
+lp_build_const_scalar(union lp_type type,
+ double val)
+{
+ LLVMTypeRef elem_type = lp_build_elem_type(type);
+ LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+ unsigned i;
+
+ assert(type.length <= LP_MAX_VECTOR_LENGTH);
+
+ if(type.floating) {
+ elems[0] = LLVMConstReal(elem_type, val);
+ }
+ else {
+ double dscale = lp_const_scale(type);
+
+ elems[0] = LLVMConstInt(elem_type, val*dscale + 0.5, 0);
+ }
+
+ for(i = 1; i < type.length; ++i)
+ elems[i] = elems[0];
+
+ return LLVMConstVector(elems, type.length);
+}
+
+
+LLVMValueRef
+lp_build_int_const_scalar(union lp_type type,
+ long long val)
+{
+ LLVMTypeRef elem_type = lp_build_int_elem_type(type);
+ LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+ unsigned i;
+
+ assert(type.length <= LP_MAX_VECTOR_LENGTH);
+
+ for(i = 0; i < type.length; ++i)
+ elems[i] = LLVMConstInt(elem_type, val, type.sign ? 1 : 0);
+
+ return LLVMConstVector(elems, type.length);
+}
+
+
+LLVMValueRef
+lp_build_const_aos(union lp_type type,
+ double r, double g, double b, double a,
+ const unsigned char *swizzle)
+{
+ const unsigned char default_swizzle[4] = {0, 1, 2, 3};
+ LLVMTypeRef elem_type;
+ LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+ unsigned i;
+
+ assert(type.length % 4 == 0);
+ assert(type.length <= LP_MAX_VECTOR_LENGTH);
+
+ elem_type = lp_build_elem_type(type);
+
+ if(swizzle == NULL)
+ swizzle = default_swizzle;
+
+ if(type.floating) {
+ elems[swizzle[0]] = LLVMConstReal(elem_type, r);
+ elems[swizzle[1]] = LLVMConstReal(elem_type, g);
+ elems[swizzle[2]] = LLVMConstReal(elem_type, b);
+ elems[swizzle[3]] = LLVMConstReal(elem_type, a);
+ }
+ else {
+ double dscale = lp_const_scale(type);
+
+ elems[swizzle[0]] = LLVMConstInt(elem_type, r*dscale + 0.5, 0);
+ elems[swizzle[1]] = LLVMConstInt(elem_type, g*dscale + 0.5, 0);
+ elems[swizzle[2]] = LLVMConstInt(elem_type, b*dscale + 0.5, 0);
+ elems[swizzle[3]] = LLVMConstInt(elem_type, a*dscale + 0.5, 0);
+ }
+
+ for(i = 4; i < type.length; ++i)
+ elems[i] = elems[i % 4];
+
+ return LLVMConstVector(elems, type.length);
+}
+
+
+LLVMValueRef
+lp_build_const_mask_aos(union lp_type type,
+ boolean cond[4])
+{
+ LLVMTypeRef elem_type = LLVMIntType(type.width);
+ LLVMValueRef masks[LP_MAX_VECTOR_LENGTH];
+ unsigned i, j;
+
+ assert(type.length <= LP_MAX_VECTOR_LENGTH);
+
+ for(j = 0; j < type.length; j += 4)
+ for(i = 0; i < 4; ++i)
+ masks[j + i] = LLVMConstInt(elem_type, cond[i] ? ~0 : 0, 0);
+
+ return LLVMConstVector(masks, type.length);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_const.h b/src/gallium/drivers/llvmpipe/lp_bld_const.h
new file mode 100644
index 0000000000..1934530ea3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_const.h
@@ -0,0 +1,108 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Helper functions for constant building.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifndef LP_BLD_CONST_H
+#define LP_BLD_CONST_H
+
+
+#include <llvm-c/Core.h>
+
+#include <pipe/p_compiler.h>
+
+
+union lp_type type;
+
+
+unsigned
+lp_mantissa(union lp_type type);
+
+
+unsigned
+lp_const_shift(union lp_type type);
+
+
+unsigned
+lp_const_offset(union lp_type type);
+
+
+double
+lp_const_scale(union lp_type type);
+
+double
+lp_const_min(union lp_type type);
+
+
+double
+lp_const_max(union lp_type type);
+
+
+double
+lp_const_eps(union lp_type type);
+
+
+LLVMValueRef
+lp_build_undef(union lp_type type);
+
+
+LLVMValueRef
+lp_build_zero(union lp_type type);
+
+
+LLVMValueRef
+lp_build_one(union lp_type type);
+
+
+LLVMValueRef
+lp_build_const_scalar(union lp_type type,
+ double val);
+
+
+LLVMValueRef
+lp_build_int_const_scalar(union lp_type type,
+ long long val);
+
+
+LLVMValueRef
+lp_build_const_aos(union lp_type type,
+ double r, double g, double b, double a,
+ const unsigned char *swizzle);
+
+
+LLVMValueRef
+lp_build_const_mask_aos(union lp_type type,
+ boolean cond[4]);
+
+
+#endif /* !LP_BLD_CONST_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_conv.c b/src/gallium/drivers/llvmpipe/lp_bld_conv.c
new file mode 100644
index 0000000000..cd01496d54
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_conv.c
@@ -0,0 +1,702 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Helper functions for type conversions.
+ *
+ * We want to use the fastest type for a given computation whenever feasible.
+ * The other side of this is that we need to be able convert between several
+ * types accurately and efficiently.
+ *
+ * Conversion between types of different bit width is quite complex since a
+ *
+ * To remember there are a few invariants in type conversions:
+ *
+ * - register width must remain constant:
+ *
+ * src_type.width * src_type.length == dst_type.width * dst_type.length
+ *
+ * - total number of elements must remain constant:
+ *
+ * src_type.length * num_srcs == dst_type.length * num_dsts
+ *
+ * It is not always possible to do the conversion both accurately and
+ * efficiently, usually due to lack of adequate machine instructions. In these
+ * cases it is important not to cut shortcuts here and sacrifice accuracy, as
+ * there this functions can be used anywhere. In the future we might have a
+ * precision parameter which can gauge the accuracy vs efficiency compromise,
+ * but for now if the data conversion between two stages happens to be the
+ * bottleneck, then most likely should just avoid converting at all and run
+ * both stages with the same type.
+ *
+ * Make sure to run lp_test_conv unit test after any change to this file.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "util/u_debug.h"
+#include "util/u_math.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_intr.h"
+#include "lp_bld_arit.h"
+#include "lp_bld_conv.h"
+
+
+/**
+ * Special case for converting clamped IEEE-754 floats to unsigned norms.
+ *
+ * The mathematical voodoo below may seem excessive but it is actually
+ * paramount we do it this way for several reasons. First, there is no single
+ * precision FP to unsigned integer conversion Intel SSE instruction. Second,
+ * secondly, even if there was, since the FP's mantissa takes only a fraction
+ * of register bits the typically scale and cast approach would require double
+ * precision for accurate results, and therefore half the throughput
+ *
+ * Although the result values can be scaled to an arbitrary bit width specified
+ * by dst_width, the actual result type will have the same width.
+ */
+LLVMValueRef
+lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
+ union lp_type src_type,
+ unsigned dst_width,
+ LLVMValueRef src)
+{
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(src_type);
+ LLVMValueRef res;
+ unsigned mantissa;
+ unsigned n;
+ unsigned long long ubound;
+ unsigned long long mask;
+ double scale;
+ double bias;
+
+ assert(src_type.floating);
+
+ mantissa = lp_mantissa(src_type);
+
+ /* We cannot carry more bits than the mantissa */
+ n = MIN2(mantissa, dst_width);
+
+ /* This magic coefficients will make the desired result to appear in the
+ * lowest significant bits of the mantissa.
+ */
+ ubound = ((unsigned long long)1 << n);
+ mask = ubound - 1;
+ scale = (double)mask/ubound;
+ bias = (double)((unsigned long long)1 << (mantissa - n));
+
+ res = LLVMBuildMul(builder, src, lp_build_const_scalar(src_type, scale), "");
+ res = LLVMBuildAdd(builder, res, lp_build_const_scalar(src_type, bias), "");
+ res = LLVMBuildBitCast(builder, res, int_vec_type, "");
+
+ if(dst_width > n) {
+ int shift = dst_width - n;
+ res = LLVMBuildShl(builder, res, lp_build_int_const_scalar(src_type, shift), "");
+
+ /* TODO: Fill in the empty lower bits for additional precision? */
+#if 0
+ {
+ LLVMValueRef msb;
+ msb = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, dst_width - 1), "");
+ msb = LLVMBuildShl(builder, msb, lp_build_int_const_scalar(src_type, shift), "");
+ msb = LLVMBuildSub(builder, msb, lp_build_int_const_scalar(src_type, 1), "");
+ res = LLVMBuildOr(builder, res, msb, "");
+ }
+#elif 0
+ while(shift > 0) {
+ res = LLVMBuildOr(builder, res, LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, n), ""), "");
+ shift -= n;
+ n *= 2;
+ }
+#endif
+ }
+ else
+ res = LLVMBuildAnd(builder, res, lp_build_int_const_scalar(src_type, mask), "");
+
+ return res;
+}
+
+
+/**
+ * Inverse of lp_build_clamped_float_to_unsigned_norm above.
+ */
+LLVMValueRef
+lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
+ unsigned src_width,
+ union lp_type dst_type,
+ LLVMValueRef src)
+{
+ LLVMTypeRef vec_type = lp_build_vec_type(dst_type);
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(dst_type);
+ LLVMValueRef bias_;
+ LLVMValueRef res;
+ unsigned mantissa;
+ unsigned n;
+ unsigned long long ubound;
+ unsigned long long mask;
+ double scale;
+ double bias;
+
+ mantissa = lp_mantissa(dst_type);
+
+ 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));
+
+ res = src;
+
+ if(src_width > mantissa) {
+ int shift = src_width - mantissa;
+ res = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(dst_type, shift), "");
+ }
+
+ bias_ = lp_build_const_scalar(dst_type, bias);
+
+ res = LLVMBuildOr(builder,
+ res,
+ LLVMBuildBitCast(builder, bias_, int_vec_type, ""), "");
+
+ res = LLVMBuildBitCast(builder, res, vec_type, "");
+
+ res = LLVMBuildSub(builder, res, bias_, "");
+ res = LLVMBuildMul(builder, res, lp_build_const_scalar(dst_type, scale), "");
+
+ return res;
+}
+
+
+/**
+ * Build shuffle vectors that match PUNPCKLxx and PUNPCKHxx instructions.
+ */
+static LLVMValueRef
+lp_build_const_unpack_shuffle(unsigned n, unsigned lo_hi)
+{
+ LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+ unsigned i, j;
+
+ assert(n <= LP_MAX_VECTOR_LENGTH);
+ assert(lo_hi < 2);
+
+ /* TODO: cache results in a static table */
+
+ for(i = 0, j = lo_hi*n/2; i < n; i += 2, ++j) {
+ elems[i + 0] = LLVMConstInt(LLVMInt32Type(), 0 + j, 0);
+ elems[i + 1] = LLVMConstInt(LLVMInt32Type(), n + j, 0);
+ }
+
+ return LLVMConstVector(elems, n);
+}
+
+
+/**
+ * Build shuffle vectors that match PACKxx instructions.
+ */
+static LLVMValueRef
+lp_build_const_pack_shuffle(unsigned n)
+{
+ LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+ unsigned i;
+
+ assert(n <= LP_MAX_VECTOR_LENGTH);
+
+ /* TODO: cache results in a static table */
+
+ for(i = 0; i < n; ++i)
+ elems[i] = LLVMConstInt(LLVMInt32Type(), 2*i, 0);
+
+ return LLVMConstVector(elems, n);
+}
+
+
+/**
+ * Expand the bit width.
+ *
+ * This will only change the number of bits the values are represented, not the
+ * values themselves.
+ */
+static void
+lp_build_expand(LLVMBuilderRef builder,
+ union lp_type src_type,
+ union lp_type dst_type,
+ LLVMValueRef src,
+ LLVMValueRef *dst, unsigned num_dsts)
+{
+ unsigned num_tmps;
+ unsigned i;
+
+ /* Register width must remain constant */
+ assert(src_type.width * src_type.length == dst_type.width * dst_type.length);
+
+ /* We must not loose or gain channels. Only precision */
+ assert(src_type.length == dst_type.length * num_dsts);
+
+ num_tmps = 1;
+ dst[0] = src;
+
+ while(src_type.width < dst_type.width) {
+ union lp_type new_type = src_type;
+ LLVMTypeRef new_vec_type;
+
+ new_type.width *= 2;
+ new_type.length /= 2;
+ new_vec_type = lp_build_vec_type(new_type);
+
+ for(i = num_tmps; i--; ) {
+ LLVMValueRef zero;
+ LLVMValueRef shuffle_lo;
+ LLVMValueRef shuffle_hi;
+ LLVMValueRef lo;
+ LLVMValueRef hi;
+
+ zero = lp_build_zero(src_type);
+ shuffle_lo = lp_build_const_unpack_shuffle(src_type.length, 0);
+ shuffle_hi = lp_build_const_unpack_shuffle(src_type.length, 1);
+
+ /* PUNPCKLBW, PUNPCKHBW */
+ lo = LLVMBuildShuffleVector(builder, dst[i], zero, shuffle_lo, "");
+ hi = LLVMBuildShuffleVector(builder, dst[i], zero, shuffle_hi, "");
+
+ dst[2*i + 0] = LLVMBuildBitCast(builder, lo, new_vec_type, "");
+ dst[2*i + 1] = LLVMBuildBitCast(builder, hi, new_vec_type, "");
+ }
+
+ src_type = new_type;
+
+ num_tmps *= 2;
+ }
+
+ assert(num_tmps == num_dsts);
+}
+
+
+/**
+ * Non-interleaved pack.
+ *
+ * This will move values as
+ *
+ * lo = __ l0 __ l1 __ l2 __.. __ ln
+ * hi = __ h0 __ h1 __ h2 __.. __ hn
+ * res = l0 l1 l2 .. ln h0 h1 h2 .. hn
+ *
+ * TODO: handle saturation consistently.
+ */
+static LLVMValueRef
+lp_build_pack2(LLVMBuilderRef builder,
+ union lp_type src_type,
+ union lp_type dst_type,
+ boolean clamped,
+ LLVMValueRef lo,
+ LLVMValueRef hi)
+{
+ LLVMTypeRef src_vec_type = lp_build_vec_type(src_type);
+ LLVMTypeRef dst_vec_type = lp_build_vec_type(dst_type);
+ LLVMValueRef shuffle;
+ LLVMValueRef res;
+
+ /* Register width must remain constant */
+ assert(src_type.width * src_type.length == dst_type.width * dst_type.length);
+
+ /* We must not loose or gain channels. Only precision */
+ assert(src_type.length * 2 == dst_type.length);
+
+ assert(!src_type.floating);
+ assert(!dst_type.floating);
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(src_type.width * src_type.length == 128) {
+ /* All X86 non-interleaved pack instructions all take signed inputs and
+ * saturate them, so saturate beforehand. */
+ if(!src_type.sign && !clamped) {
+ struct lp_build_context bld;
+ unsigned dst_bits = dst_type.sign ? dst_type.width - 1 : dst_type.width;
+ LLVMValueRef dst_max = lp_build_int_const_scalar(src_type, ((unsigned long long)1 << dst_bits) - 1);
+ lp_build_context_init(&bld, builder, src_type);
+ lo = lp_build_min(&bld, lo, dst_max);
+ hi = lp_build_min(&bld, hi, dst_max);
+ }
+
+ switch(src_type.width) {
+ case 32:
+ if(dst_type.sign)
+ res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", src_vec_type, lo, hi);
+ else
+ /* PACKUSDW is the only instrinsic with a consistent signature */
+ return lp_build_intrinsic_binary(builder, "llvm.x86.sse41.packusdw", dst_vec_type, lo, hi);
+ break;
+
+ case 16:
+ if(dst_type.sign)
+ res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packsswb.128", src_vec_type, lo, hi);
+ else
+ res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packuswb.128", src_vec_type, lo, hi);
+ break;
+
+ default:
+ assert(0);
+ return LLVMGetUndef(dst_vec_type);
+ break;
+ }
+
+ res = LLVMBuildBitCast(builder, res, dst_vec_type, "");
+ return res;
+ }
+#endif
+
+ lo = LLVMBuildBitCast(builder, lo, dst_vec_type, "");
+ hi = LLVMBuildBitCast(builder, hi, dst_vec_type, "");
+
+ shuffle = lp_build_const_pack_shuffle(dst_type.length);
+
+ res = LLVMBuildShuffleVector(builder, lo, hi, shuffle, "");
+
+ return res;
+}
+
+
+/**
+ * Truncate the bit width.
+ *
+ * TODO: Handle saturation consistently.
+ */
+static LLVMValueRef
+lp_build_trunc(LLVMBuilderRef builder,
+ union lp_type src_type,
+ union lp_type dst_type,
+ boolean clamped,
+ const LLVMValueRef *src, unsigned num_srcs)
+{
+ LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH];
+ unsigned i;
+
+ /* Register width must remain constant */
+ assert(src_type.width * src_type.length == dst_type.width * dst_type.length);
+
+ /* We must not loose or gain channels. Only precision */
+ assert(src_type.length * num_srcs == dst_type.length);
+
+ for(i = 0; i < num_srcs; ++i)
+ tmp[i] = src[i];
+
+ while(src_type.width > dst_type.width) {
+ union lp_type new_type = src_type;
+
+ new_type.width /= 2;
+ new_type.length *= 2;
+
+ /* Take in consideration the sign changes only in the last step */
+ if(new_type.width == dst_type.width)
+ new_type.sign = dst_type.sign;
+
+ num_srcs /= 2;
+
+ for(i = 0; i < num_srcs; ++i)
+ tmp[i] = lp_build_pack2(builder, src_type, new_type, clamped,
+ tmp[2*i + 0], tmp[2*i + 1]);
+
+ src_type = new_type;
+ }
+
+ assert(num_srcs == 1);
+
+ return tmp[0];
+}
+
+
+/**
+ * Generic type conversion.
+ *
+ * TODO: Take a precision argument, or even better, add a new precision member
+ * to the lp_type union.
+ */
+void
+lp_build_conv(LLVMBuilderRef builder,
+ union lp_type src_type,
+ union lp_type dst_type,
+ const LLVMValueRef *src, unsigned num_srcs,
+ LLVMValueRef *dst, unsigned num_dsts)
+{
+ union lp_type tmp_type;
+ LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH];
+ unsigned num_tmps;
+ unsigned i;
+
+ /* Register width must remain constant */
+ assert(src_type.width * src_type.length == dst_type.width * dst_type.length);
+
+ /* We must not loose or gain channels. Only precision */
+ assert(src_type.length * num_srcs == dst_type.length * num_dsts);
+
+ assert(src_type.length <= LP_MAX_VECTOR_LENGTH);
+ assert(dst_type.length <= LP_MAX_VECTOR_LENGTH);
+
+ tmp_type = src_type;
+ for(i = 0; i < num_srcs; ++i)
+ tmp[i] = src[i];
+ num_tmps = num_srcs;
+
+ /*
+ * Clamp if necessary
+ */
+
+ if(src_type.value != dst_type.value) {
+ struct lp_build_context bld;
+ double src_min = lp_const_min(src_type);
+ double dst_min = lp_const_min(dst_type);
+ double src_max = lp_const_max(src_type);
+ double dst_max = lp_const_max(dst_type);
+ LLVMValueRef thres;
+
+ lp_build_context_init(&bld, builder, tmp_type);
+
+ if(src_min < dst_min) {
+ if(dst_min == 0.0)
+ thres = bld.zero;
+ else
+ thres = lp_build_const_scalar(src_type, dst_min);
+ for(i = 0; i < num_tmps; ++i)
+ tmp[i] = lp_build_max(&bld, tmp[i], thres);
+ }
+
+ if(src_max > dst_max) {
+ if(dst_max == 1.0)
+ thres = bld.one;
+ else
+ thres = lp_build_const_scalar(src_type, dst_max);
+ for(i = 0; i < num_tmps; ++i)
+ tmp[i] = lp_build_min(&bld, tmp[i], thres);
+ }
+ }
+
+ /*
+ * Scale to the narrowest range
+ */
+
+ if(dst_type.floating) {
+ /* Nothing to do */
+ }
+ else if(tmp_type.floating) {
+ if(!dst_type.fixed && !dst_type.sign && dst_type.norm) {
+ for(i = 0; i < num_tmps; ++i) {
+ tmp[i] = lp_build_clamped_float_to_unsigned_norm(builder,
+ tmp_type,
+ dst_type.width,
+ tmp[i]);
+ }
+ tmp_type.floating = FALSE;
+ }
+ else {
+ double dst_scale = lp_const_scale(dst_type);
+ LLVMTypeRef tmp_vec_type;
+
+ if (dst_scale != 1.0) {
+ LLVMValueRef scale = lp_build_const_scalar(tmp_type, dst_scale);
+ for(i = 0; i < num_tmps; ++i)
+ tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
+ }
+
+ /* Use an equally sized integer for intermediate computations */
+ tmp_type.floating = FALSE;
+ tmp_vec_type = lp_build_vec_type(tmp_type);
+ for(i = 0; i < num_tmps; ++i) {
+#if 0
+ if(dst_type.sign)
+ tmp[i] = LLVMBuildFPToSI(builder, tmp[i], tmp_vec_type, "");
+ else
+ tmp[i] = LLVMBuildFPToUI(builder, tmp[i], tmp_vec_type, "");
+#else
+ /* FIXME: there is no SSE counterpart for LLVMBuildFPToUI */
+ tmp[i] = LLVMBuildFPToSI(builder, tmp[i], tmp_vec_type, "");
+#endif
+ }
+ }
+ }
+ else {
+ unsigned src_shift = lp_const_shift(src_type);
+ unsigned dst_shift = lp_const_shift(dst_type);
+
+ /* FIXME: compensate different offsets too */
+ if(src_shift > dst_shift) {
+ LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, src_shift - dst_shift);
+ for(i = 0; i < num_tmps; ++i)
+ if(src_type.sign)
+ tmp[i] = LLVMBuildAShr(builder, tmp[i], shift, "");
+ else
+ tmp[i] = LLVMBuildLShr(builder, tmp[i], shift, "");
+ }
+ }
+
+ /*
+ * Truncate or expand bit width
+ */
+
+ assert(!tmp_type.floating || tmp_type.width == dst_type.width);
+
+ if(tmp_type.width > dst_type.width) {
+ assert(num_dsts == 1);
+ tmp[0] = lp_build_trunc(builder, tmp_type, dst_type, TRUE, tmp, num_tmps);
+ tmp_type.width = dst_type.width;
+ tmp_type.length = dst_type.length;
+ num_tmps = 1;
+ }
+
+ if(tmp_type.width < dst_type.width) {
+ assert(num_tmps == 1);
+ lp_build_expand(builder, tmp_type, dst_type, tmp[0], tmp, num_dsts);
+ tmp_type.width = dst_type.width;
+ tmp_type.length = dst_type.length;
+ num_tmps = num_dsts;
+ }
+
+ assert(tmp_type.width == dst_type.width);
+ assert(tmp_type.length == dst_type.length);
+ assert(num_tmps == num_dsts);
+
+ /*
+ * Scale to the widest range
+ */
+
+ if(src_type.floating) {
+ /* Nothing to do */
+ }
+ else if(!src_type.floating && dst_type.floating) {
+ if(!src_type.fixed && !src_type.sign && src_type.norm) {
+ for(i = 0; i < num_tmps; ++i) {
+ tmp[i] = lp_build_unsigned_norm_to_float(builder,
+ src_type.width,
+ dst_type,
+ tmp[i]);
+ }
+ tmp_type.floating = TRUE;
+ }
+ else {
+ double src_scale = lp_const_scale(src_type);
+ LLVMTypeRef tmp_vec_type;
+
+ /* Use an equally sized integer for intermediate computations */
+ tmp_type.floating = TRUE;
+ tmp_type.sign = TRUE;
+ tmp_vec_type = lp_build_vec_type(tmp_type);
+ for(i = 0; i < num_tmps; ++i) {
+#if 0
+ if(dst_type.sign)
+ tmp[i] = LLVMBuildSIToFP(builder, tmp[i], tmp_vec_type, "");
+ else
+ tmp[i] = LLVMBuildUIToFP(builder, tmp[i], tmp_vec_type, "");
+#else
+ /* FIXME: there is no SSE counterpart for LLVMBuildUIToFP */
+ tmp[i] = LLVMBuildSIToFP(builder, tmp[i], tmp_vec_type, "");
+#endif
+ }
+
+ if (src_scale != 1.0) {
+ LLVMValueRef scale = lp_build_const_scalar(tmp_type, 1.0/src_scale);
+ for(i = 0; i < num_tmps; ++i)
+ tmp[i] = LLVMBuildMul(builder, tmp[i], scale, "");
+ }
+ }
+ }
+ else {
+ unsigned src_shift = lp_const_shift(src_type);
+ unsigned dst_shift = lp_const_shift(dst_type);
+
+ /* FIXME: compensate different offsets too */
+ if(src_shift < dst_shift) {
+ LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, dst_shift - src_shift);
+ for(i = 0; i < num_tmps; ++i)
+ tmp[i] = LLVMBuildShl(builder, tmp[i], shift, "");
+ }
+ }
+
+ for(i = 0; i < num_dsts; ++i)
+ dst[i] = tmp[i];
+}
+
+
+/**
+ * Bit mask conversion.
+ *
+ * This will convert the integer masks that match the given types.
+ *
+ * The mask values should 0 or -1, i.e., all bits either set to zero or one.
+ * Any other value will likely cause in unpredictable results.
+ *
+ * This is basically a very trimmed down version of lp_build_conv.
+ */
+void
+lp_build_conv_mask(LLVMBuilderRef builder,
+ union lp_type src_type,
+ union lp_type dst_type,
+ const LLVMValueRef *src, unsigned num_srcs,
+ LLVMValueRef *dst, unsigned num_dsts)
+{
+ /* Register width must remain constant */
+ assert(src_type.width * src_type.length == dst_type.width * dst_type.length);
+
+ /* We must not loose or gain channels. Only precision */
+ assert(src_type.length * num_srcs == dst_type.length * num_dsts);
+
+ /*
+ * Drop
+ *
+ * We assume all values are 0 or -1
+ */
+
+ src_type.floating = FALSE;
+ src_type.fixed = FALSE;
+ src_type.sign = TRUE;
+ src_type.norm = FALSE;
+
+ dst_type.floating = FALSE;
+ dst_type.fixed = FALSE;
+ dst_type.sign = TRUE;
+ dst_type.norm = FALSE;
+
+ /*
+ * Truncate or expand bit width
+ */
+
+ if(src_type.width > dst_type.width) {
+ assert(num_dsts == 1);
+ dst[0] = lp_build_trunc(builder, src_type, dst_type, TRUE, src, num_srcs);
+ }
+ else if(src_type.width < dst_type.width) {
+ assert(num_srcs == 1);
+ lp_build_expand(builder, src_type, dst_type, src[0], dst, num_dsts);
+ }
+ else {
+ assert(num_srcs == num_dsts);
+ memcpy(dst, src, num_dsts * sizeof *dst);
+ }
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_conv.h b/src/gallium/drivers/llvmpipe/lp_bld_conv.h
new file mode 100644
index 0000000000..05c1ef2a10
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_conv.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Helper functions for type conversions.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifndef LP_BLD_CONV_H
+#define LP_BLD_CONV_H
+
+
+#include <llvm-c/Core.h>
+
+
+union lp_type type;
+
+
+LLVMValueRef
+lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
+ union lp_type src_type,
+ unsigned dst_width,
+ LLVMValueRef src);
+
+LLVMValueRef
+lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
+ unsigned src_width,
+ union lp_type dst_type,
+ LLVMValueRef src);
+
+
+void
+lp_build_conv(LLVMBuilderRef builder,
+ union lp_type src_type,
+ union lp_type dst_type,
+ const LLVMValueRef *srcs, unsigned num_srcs,
+ LLVMValueRef *dsts, unsigned num_dsts);
+
+void
+lp_build_conv_mask(LLVMBuilderRef builder,
+ union lp_type src_type,
+ union lp_type dst_type,
+ const LLVMValueRef *src, unsigned num_srcs,
+ LLVMValueRef *dst, unsigned num_dsts);
+
+#endif /* !LP_BLD_CONV_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_debug.c b/src/gallium/drivers/llvmpipe/lp_bld_debug.c
new file mode 100644
index 0000000000..59d8f492e6
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_debug.c
@@ -0,0 +1,125 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifdef HAVE_UDIS86
+#include <udis86.h>
+#endif
+
+#include "util/u_math.h"
+#include "util/u_debug.h"
+#include "lp_bld_debug.h"
+
+
+/**
+ * Check alignment.
+ *
+ * It is important that this check is not implemented as a macro or inlined
+ * function, as the compiler assumptions in respect to alignment of global
+ * and stack variables would often make the check a no op, defeating the
+ * whole purpose of the exercise.
+ */
+boolean
+lp_check_alignment(const void *ptr, unsigned alignment)
+{
+ assert(util_is_pot(alignment));
+ return ((uintptr_t)ptr & (alignment - 1)) == 0;
+}
+
+
+void
+lp_disassemble(const void* func)
+{
+#ifdef HAVE_UDIS86
+ ud_t ud_obj;
+ uint64_t max_jmp_pc;
+
+ ud_init(&ud_obj);
+
+ ud_set_input_buffer(&ud_obj, (void*)func, 0xffff);
+
+ max_jmp_pc = (uint64_t) (uintptr_t) func;
+ ud_set_pc(&ud_obj, max_jmp_pc);
+
+#ifdef PIPE_ARCH_X86
+ ud_set_mode(&ud_obj, 32);
+#endif
+#ifdef PIPE_ARCH_X86_64
+ ud_set_mode(&ud_obj, 64);
+#endif
+
+ ud_set_syntax(&ud_obj, UD_SYN_ATT);
+
+ while (ud_disassemble(&ud_obj)) {
+
+#ifdef PIPE_ARCH_X86
+ debug_printf("%08lx: ", (unsigned long)ud_insn_off(&ud_obj));
+#endif
+#ifdef PIPE_ARCH_X86_64
+ debug_printf("%016llx: ", (unsigned long long)ud_insn_off(&ud_obj));
+#endif
+
+#if 0
+ debug_printf("%-16s ", ud_insn_hex(&ud_obj));
+#endif
+
+ debug_printf("%s\n", ud_insn_asm(&ud_obj));
+
+ if(ud_obj.mnemonic != UD_Icall) {
+ unsigned i;
+ for(i = 0; i < 3; ++i) {
+ const struct ud_operand *op = &ud_obj.operand[i];
+ if (op->type == UD_OP_JIMM){
+ uint64_t pc = ud_obj.pc;
+
+ switch (op->size) {
+ case 8:
+ pc += op->lval.sbyte;
+ break;
+ case 16:
+ pc += op->lval.sword;
+ break;
+ case 32:
+ pc += op->lval.sdword;
+ break;
+ default:
+ break;
+ }
+ if(pc > max_jmp_pc)
+ max_jmp_pc = pc;
+ }
+ }
+ }
+
+ if (ud_insn_off(&ud_obj) >= max_jmp_pc && ud_obj.mnemonic == UD_Iret)
+ break;
+ }
+ debug_printf("\n");
+#else
+ (void)func;
+#endif
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_debug.h b/src/gallium/drivers/llvmpipe/lp_bld_debug.h
new file mode 100644
index 0000000000..583e6132b4
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_debug.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef LP_BLD_DEBUG_H
+#define LP_BLD_DEBUG_H
+
+
+#include <llvm-c/Core.h>
+
+#include "pipe/p_compiler.h"
+#include "util/u_string.h"
+
+
+static INLINE void
+lp_build_name(LLVMValueRef val, const char *format, ...)
+{
+#ifdef DEBUG
+ char name[32];
+ va_list ap;
+ va_start(ap, format);
+ util_vsnprintf(name, sizeof name, format, ap);
+ va_end(ap);
+ LLVMSetValueName(val, name);
+#else
+ (void)val;
+ (void)format;
+#endif
+}
+
+
+boolean
+lp_check_alignment(const void *ptr, unsigned alignment);
+
+
+void
+lp_disassemble(const void* func);
+
+
+#endif /* !LP_BLD_DEBUG_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
new file mode 100644
index 0000000000..e5fe81193f
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
@@ -0,0 +1,216 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Depth/stencil testing to LLVM IR translation.
+ *
+ * To be done accurately/efficiently the depth/stencil test must be done with
+ * the same type/format of the depth/stencil buffer, which implies massaging
+ * the incoming depths to fit into place. Using a more straightforward
+ * type/format for depth/stencil values internally and only convert when
+ * flushing would avoid this, but it would most likely result in depth fighting
+ * artifacts.
+ *
+ * We are free to use a different pixel layout though. Since our basic
+ * processing unit is a quad (2x2 pixel block) we store the depth/stencil
+ * values tiled, a quad at time. That is, a depth buffer containing
+ *
+ * Z11 Z12 Z13 Z14 ...
+ * Z21 Z22 Z23 Z24 ...
+ * Z31 Z32 Z33 Z34 ...
+ * Z41 Z42 Z43 Z44 ...
+ * ... ... ... ... ...
+ *
+ * will actually be stored in memory as
+ *
+ * Z11 Z12 Z21 Z22 Z13 Z14 Z23 Z24 ...
+ * Z31 Z32 Z41 Z42 Z33 Z34 Z43 Z44 ...
+ * ... ... ... ... ... ... ... ... ...
+ *
+ * FIXME: Code generate stencil test
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include "pipe/p_state.h"
+#include "util/u_format.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_logic.h"
+#include "lp_bld_flow.h"
+#include "lp_bld_debug.h"
+#include "lp_bld_depth.h"
+
+
+/**
+ * Return a type appropriate for depth/stencil testing.
+ */
+union lp_type
+lp_depth_type(const struct util_format_description *format_desc,
+ unsigned length)
+{
+ union lp_type type;
+ unsigned swizzle;
+
+ assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
+ assert(format_desc->block.width == 1);
+ assert(format_desc->block.height == 1);
+
+ swizzle = format_desc->swizzle[0];
+ assert(swizzle < 4);
+
+ type.value = 0;
+ type.width = format_desc->block.bits;
+
+ if(format_desc->channel[swizzle].type == UTIL_FORMAT_TYPE_FLOAT) {
+ type.floating = TRUE;
+ assert(swizzle = 0);
+ assert(format_desc->channel[swizzle].size == format_desc->block.bits);
+ }
+ else if(format_desc->channel[swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED) {
+ assert(format_desc->block.bits <= 32);
+ if(format_desc->channel[swizzle].normalized)
+ type.norm = TRUE;
+ }
+ else
+ assert(0);
+
+ assert(type.width <= length);
+ type.length = length / type.width;
+
+ return type;
+}
+
+
+/**
+ * Depth test.
+ */
+void
+lp_build_depth_test(LLVMBuilderRef builder,
+ const struct pipe_depth_state *state,
+ union lp_type type,
+ const struct util_format_description *format_desc,
+ struct lp_build_mask_context *mask,
+ LLVMValueRef src,
+ LLVMValueRef dst_ptr)
+{
+ struct lp_build_context bld;
+ unsigned z_swizzle;
+ LLVMValueRef dst;
+ LLVMValueRef z_bitmask = NULL;
+ LLVMValueRef test;
+
+ if(!state->enabled)
+ return;
+
+ assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
+ assert(format_desc->block.width == 1);
+ assert(format_desc->block.height == 1);
+
+ z_swizzle = format_desc->swizzle[0];
+ if(z_swizzle == UTIL_FORMAT_SWIZZLE_NONE)
+ return;
+
+ /* Sanity checking */
+ assert(z_swizzle < 4);
+ assert(format_desc->block.bits == type.width);
+ if(type.floating) {
+ assert(z_swizzle == 0);
+ assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_FLOAT);
+ assert(format_desc->channel[z_swizzle].size == format_desc->block.bits);
+ }
+ else {
+ assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED);
+ assert(format_desc->channel[z_swizzle].normalized);
+ assert(!type.fixed);
+ assert(!type.sign);
+ assert(type.norm);
+ }
+
+ /* Setup build context */
+ lp_build_context_init(&bld, builder, type);
+
+ dst = LLVMBuildLoad(builder, dst_ptr, "");
+
+ lp_build_name(dst, "zsbuf");
+
+ /* Align the source depth bits with the destination's, and mask out any
+ * stencil or padding bits from both */
+ if(format_desc->channel[z_swizzle].size == format_desc->block.bits) {
+ assert(z_swizzle == 0);
+ /* nothing to do */
+ }
+ else {
+ unsigned padding_left;
+ unsigned padding_right;
+ unsigned chan;
+
+ assert(format_desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
+ assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED);
+ assert(format_desc->channel[z_swizzle].size <= format_desc->block.bits);
+ assert(format_desc->channel[z_swizzle].normalized);
+
+ padding_right = 0;
+ for(chan = 0; chan < z_swizzle; ++chan)
+ padding_right += format_desc->channel[chan].size;
+ padding_left = format_desc->block.bits -
+ (padding_right + format_desc->channel[z_swizzle].size);
+
+ if(padding_left || padding_right) {
+ const unsigned long long mask_left = ((unsigned long long)1 << (format_desc->block.bits - padding_left)) - 1;
+ const unsigned long long mask_right = ((unsigned long long)1 << (padding_right)) - 1;
+ z_bitmask = lp_build_int_const_scalar(type, mask_left ^ mask_right);
+ }
+
+ if(padding_left)
+ src = LLVMBuildLShr(builder, src, lp_build_int_const_scalar(type, padding_left), "");
+ if(padding_right)
+ src = LLVMBuildAnd(builder, src, z_bitmask, "");
+ if(padding_left || padding_right)
+ dst = LLVMBuildAnd(builder, dst, z_bitmask, "");
+ }
+
+ lp_build_name(dst, "zsbuf.z");
+
+ test = lp_build_cmp(&bld, state->func, src, dst);
+ lp_build_mask_update(mask, test);
+
+ if(state->writemask) {
+ if(z_bitmask)
+ z_bitmask = LLVMBuildAnd(builder, mask->value, z_bitmask, "");
+ else
+ z_bitmask = mask->value;
+
+ dst = lp_build_select(&bld, z_bitmask, src, dst);
+ LLVMBuildStore(builder, dst, dst_ptr);
+ }
+
+ /* FIXME */
+ assert(!state->occlusion_count);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.h b/src/gallium/drivers/llvmpipe/lp_bld_depth.h
new file mode 100644
index 0000000000..5d2e042fcc
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Depth/stencil testing to LLVM IR translation.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef LP_BLD_DEPTH_H
+#define LP_BLD_DEPTH_H
+
+
+#include <llvm-c/Core.h>
+
+
+struct pipe_depth_state;
+struct util_format_description;
+union lp_type;
+struct lp_build_mask_context;
+
+
+union lp_type
+lp_depth_type(const struct util_format_description *format_desc,
+ unsigned length);
+
+
+void
+lp_build_depth_test(LLVMBuilderRef builder,
+ const struct pipe_depth_state *state,
+ union lp_type type,
+ const struct util_format_description *format_desc,
+ struct lp_build_mask_context *mask,
+ LLVMValueRef src,
+ LLVMValueRef dst_ptr);
+
+
+#endif /* !LP_BLD_DEPTH_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_flow.c b/src/gallium/drivers/llvmpipe/lp_bld_flow.c
new file mode 100644
index 0000000000..69ed014ff3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_flow.c
@@ -0,0 +1,493 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * LLVM control flow build helpers.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_flow.h"
+
+
+#define LP_BUILD_FLOW_MAX_VARIABLES 32
+#define LP_BUILD_FLOW_MAX_DEPTH 32
+
+
+/**
+ * Enumeration of all possible flow constructs.
+ */
+enum lp_build_flow_construct_kind {
+ lP_BUILD_FLOW_SCOPE,
+ LP_BUILD_FLOW_SKIP,
+};
+
+
+/**
+ * Variable declaration scope.
+ */
+struct lp_build_flow_scope
+{
+ /** Number of variables declared in this scope */
+ unsigned num_variables;
+};
+
+
+/**
+ * Early exit. Useful to skip to the end of a function or block when
+ * the execution mask becomes zero or when there is an error condition.
+ */
+struct lp_build_flow_skip
+{
+ /** Block to skip to */
+ LLVMBasicBlockRef block;
+
+ /** Number of variables declared at the beginning */
+ unsigned num_variables;
+
+ LLVMValueRef *phi;
+};
+
+
+/**
+ * Union of all possible flow constructs' data
+ */
+union lp_build_flow_construct_data
+{
+ struct lp_build_flow_scope scope;
+ struct lp_build_flow_skip skip;
+};
+
+
+/**
+ * Element of the flow construct stack.
+ */
+struct lp_build_flow_construct
+{
+ enum lp_build_flow_construct_kind kind;
+ union lp_build_flow_construct_data data;
+};
+
+
+/**
+ * All necessary data to generate LLVM control flow constructs.
+ *
+ * Besides keeping track of the control flow construct themselves we also
+ * need to keep track of variables in order to generate SSA Phi values.
+ */
+struct lp_build_flow_context
+{
+ LLVMBuilderRef builder;
+
+ /**
+ * Control flow stack.
+ */
+ struct lp_build_flow_construct constructs[LP_BUILD_FLOW_MAX_DEPTH];
+ unsigned num_constructs;
+
+ /**
+ * Variable stack
+ */
+ LLVMValueRef *variables[LP_BUILD_FLOW_MAX_VARIABLES];
+ unsigned num_variables;
+};
+
+
+struct lp_build_flow_context *
+lp_build_flow_create(LLVMBuilderRef builder)
+{
+ struct lp_build_flow_context *flow;
+
+ flow = CALLOC_STRUCT(lp_build_flow_context);
+ if(!flow)
+ return NULL;
+
+ flow->builder = builder;
+
+ return flow;
+}
+
+
+void
+lp_build_flow_destroy(struct lp_build_flow_context *flow)
+{
+ assert(flow->num_constructs == 0);
+ assert(flow->num_variables == 0);
+ FREE(flow);
+}
+
+
+static union lp_build_flow_construct_data *
+lp_build_flow_push(struct lp_build_flow_context *flow,
+ enum lp_build_flow_construct_kind kind)
+{
+ assert(flow->num_constructs < LP_BUILD_FLOW_MAX_DEPTH);
+ if(flow->num_constructs >= LP_BUILD_FLOW_MAX_DEPTH)
+ return NULL;
+
+ flow->constructs[flow->num_constructs].kind = kind;
+ return &flow->constructs[flow->num_constructs++].data;
+}
+
+
+static union lp_build_flow_construct_data *
+lp_build_flow_peek(struct lp_build_flow_context *flow,
+ enum lp_build_flow_construct_kind kind)
+{
+ assert(flow->num_constructs);
+ if(!flow->num_constructs)
+ return NULL;
+
+ assert(flow->constructs[flow->num_constructs - 1].kind == kind);
+ if(flow->constructs[flow->num_constructs - 1].kind != kind)
+ return NULL;
+
+ return &flow->constructs[flow->num_constructs - 1].data;
+}
+
+
+static union lp_build_flow_construct_data *
+lp_build_flow_pop(struct lp_build_flow_context *flow,
+ enum lp_build_flow_construct_kind kind)
+{
+ assert(flow->num_constructs);
+ if(!flow->num_constructs)
+ return NULL;
+
+ assert(flow->constructs[flow->num_constructs - 1].kind == kind);
+ if(flow->constructs[flow->num_constructs - 1].kind != kind)
+ return NULL;
+
+ return &flow->constructs[--flow->num_constructs].data;
+}
+
+
+/**
+ * Begin a variable scope.
+ *
+ *
+ */
+void
+lp_build_flow_scope_begin(struct lp_build_flow_context *flow)
+{
+ struct lp_build_flow_scope *scope;
+
+ scope = &lp_build_flow_push(flow, lP_BUILD_FLOW_SCOPE)->scope;
+ if(!scope)
+ return;
+
+ scope->num_variables = 0;
+}
+
+
+/**
+ * Declare a variable.
+ *
+ * A variable is a named entity which can have different LLVMValueRef's at
+ * different points of the program. This is relevant for control flow because
+ * when there are mutiple branches to a same location we need to replace
+ * the variable's value with a Phi function as explained in
+ * http://en.wikipedia.org/wiki/Static_single_assignment_form .
+ *
+ * We keep track of variables by keeping around a pointer to where their
+ * current.
+ *
+ * There are a few cautions to observe:
+ *
+ * - Variable's value must not be NULL. If there is no initial value then
+ * LLVMGetUndef() should be used.
+ *
+ * - Variable's value must be kept up-to-date. If the variable is going to be
+ * modified by a function then a pointer should be passed so that its value
+ * is accurate. Failure to do this will cause some of the variables'
+ * transient values to be lost, leading to wrong results.
+ *
+ * - A program should be written from top to bottom, by always appending
+ * instructions to the bottom with a single LLVMBuilderRef. Inserting and/or
+ * modifying existing statements will most likely lead to wrong results.
+ *
+ */
+void
+lp_build_flow_scope_declare(struct lp_build_flow_context *flow,
+ LLVMValueRef *variable)
+{
+ struct lp_build_flow_scope *scope;
+
+ scope = &lp_build_flow_peek(flow, lP_BUILD_FLOW_SCOPE)->scope;
+ if(!scope)
+ return;
+
+ assert(*variable);
+ if(!*variable)
+ return;
+
+ assert(flow->num_variables < LP_BUILD_FLOW_MAX_VARIABLES);
+ if(flow->num_variables >= LP_BUILD_FLOW_MAX_VARIABLES)
+ return;
+
+ flow->variables[flow->num_variables++] = variable;
+ ++scope->num_variables;
+}
+
+
+void
+lp_build_flow_scope_end(struct lp_build_flow_context *flow)
+{
+ struct lp_build_flow_scope *scope;
+
+ scope = &lp_build_flow_pop(flow, lP_BUILD_FLOW_SCOPE)->scope;
+ if(!scope)
+ return;
+
+ assert(flow->num_variables >= scope->num_variables);
+ if(flow->num_variables < scope->num_variables) {
+ flow->num_variables = 0;
+ return;
+ }
+
+ flow->num_variables -= scope->num_variables;
+}
+
+
+static LLVMBasicBlockRef
+lp_build_flow_insert_block(struct lp_build_flow_context *flow)
+{
+ LLVMBasicBlockRef current_block;
+ LLVMBasicBlockRef next_block;
+ LLVMBasicBlockRef new_block;
+
+ current_block = LLVMGetInsertBlock(flow->builder);
+
+ next_block = LLVMGetNextBasicBlock(current_block);
+ if(next_block) {
+ new_block = LLVMInsertBasicBlock(next_block, "");
+ }
+ else {
+ LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
+ new_block = LLVMAppendBasicBlock(function, "");
+ }
+
+ return new_block;
+}
+
+void
+lp_build_flow_skip_begin(struct lp_build_flow_context *flow)
+{
+ struct lp_build_flow_skip *skip;
+ LLVMBuilderRef builder;
+ unsigned i;
+
+ skip = &lp_build_flow_push(flow, LP_BUILD_FLOW_SKIP)->skip;
+ if(!skip)
+ return;
+
+ skip->block = lp_build_flow_insert_block(flow);
+ skip->num_variables = flow->num_variables;
+ if(!skip->num_variables) {
+ skip->phi = NULL;
+ return;
+ }
+
+ skip->phi = MALLOC(skip->num_variables * sizeof *skip->phi);
+ if(!skip->phi) {
+ skip->num_variables = 0;
+ return;
+ }
+
+ builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(builder, skip->block);
+
+ for(i = 0; i < skip->num_variables; ++i)
+ skip->phi[i] = LLVMBuildPhi(builder, LLVMTypeOf(*flow->variables[i]), "");
+
+ LLVMDisposeBuilder(builder);
+}
+
+
+void
+lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow,
+ LLVMValueRef cond)
+{
+ struct lp_build_flow_skip *skip;
+ LLVMBasicBlockRef current_block;
+ LLVMBasicBlockRef new_block;
+ unsigned i;
+
+ skip = &lp_build_flow_peek(flow, LP_BUILD_FLOW_SKIP)->skip;
+ if(!skip)
+ return;
+
+ current_block = LLVMGetInsertBlock(flow->builder);
+
+ new_block = lp_build_flow_insert_block(flow);
+
+ for(i = 0; i < skip->num_variables; ++i) {
+ assert(*flow->variables[i]);
+ LLVMAddIncoming(skip->phi[i], flow->variables[i], &current_block, 1);
+ }
+
+ LLVMBuildCondBr(flow->builder, cond, skip->block, new_block);
+
+ LLVMPositionBuilderAtEnd(flow->builder, new_block);
+ }
+
+
+void
+lp_build_flow_skip_end(struct lp_build_flow_context *flow)
+{
+ struct lp_build_flow_skip *skip;
+ LLVMBasicBlockRef current_block;
+ unsigned i;
+
+ skip = &lp_build_flow_pop(flow, LP_BUILD_FLOW_SKIP)->skip;
+ if(!skip)
+ return;
+
+ current_block = LLVMGetInsertBlock(flow->builder);
+
+ for(i = 0; i < skip->num_variables; ++i) {
+ assert(*flow->variables[i]);
+ LLVMAddIncoming(skip->phi[i], flow->variables[i], &current_block, 1);
+ *flow->variables[i] = skip->phi[i];
+ }
+
+ LLVMBuildBr(flow->builder, skip->block);
+ LLVMPositionBuilderAtEnd(flow->builder, skip->block);
+
+ FREE(skip->phi);
+}
+
+
+static void
+lp_build_mask_check(struct lp_build_mask_context *mask)
+{
+ LLVMBuilderRef builder = mask->flow->builder;
+ LLVMValueRef cond;
+
+ cond = LLVMBuildICmp(builder,
+ LLVMIntEQ,
+ LLVMBuildBitCast(builder, mask->value, mask->reg_type, ""),
+ LLVMConstNull(mask->reg_type),
+ "");
+
+ lp_build_flow_skip_cond_break(mask->flow, cond);
+}
+
+
+void
+lp_build_mask_begin(struct lp_build_mask_context *mask,
+ struct lp_build_flow_context *flow,
+ union lp_type type,
+ LLVMValueRef value)
+{
+ memset(mask, 0, sizeof *mask);
+
+ mask->flow = flow;
+ mask->reg_type = LLVMIntType(type.width * type.length);
+ mask->value = value;
+
+ lp_build_flow_scope_begin(flow);
+ lp_build_flow_scope_declare(flow, &mask->value);
+ lp_build_flow_skip_begin(flow);
+
+ lp_build_mask_check(mask);
+}
+
+
+void
+lp_build_mask_update(struct lp_build_mask_context *mask,
+ LLVMValueRef value)
+{
+ mask->value = LLVMBuildAnd( mask->flow->builder, mask->value, value, "");
+
+ lp_build_mask_check(mask);
+}
+
+
+LLVMValueRef
+lp_build_mask_end(struct lp_build_mask_context *mask)
+{
+ lp_build_flow_skip_end(mask->flow);
+ lp_build_flow_scope_end(mask->flow);
+ return mask->value;
+}
+
+
+
+void
+lp_build_loop_begin(LLVMBuilderRef builder,
+ LLVMValueRef start,
+ struct lp_build_loop_state *state)
+{
+ LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
+ LLVMValueRef function = LLVMGetBasicBlockParent(block);
+
+ state->block = LLVMAppendBasicBlock(function, "loop");
+
+ LLVMBuildBr(builder, state->block);
+
+ LLVMPositionBuilderAtEnd(builder, state->block);
+
+ state->counter = LLVMBuildPhi(builder, LLVMTypeOf(start), "");
+
+ LLVMAddIncoming(state->counter, &start, &block, 1);
+
+}
+
+
+void
+lp_build_loop_end(LLVMBuilderRef builder,
+ LLVMValueRef end,
+ LLVMValueRef step,
+ struct lp_build_loop_state *state)
+{
+ LLVMBasicBlockRef block = LLVMGetInsertBlock(builder);
+ LLVMValueRef function = LLVMGetBasicBlockParent(block);
+ LLVMValueRef next;
+ LLVMValueRef cond;
+ LLVMBasicBlockRef after_block;
+
+ if (!step)
+ step = LLVMConstInt(LLVMTypeOf(end), 1, 0);
+
+ next = LLVMBuildAdd(builder, state->counter, step, "");
+
+ cond = LLVMBuildICmp(builder, LLVMIntNE, next, end, "");
+
+ after_block = LLVMAppendBasicBlock(function, "");
+
+ LLVMBuildCondBr(builder, cond, after_block, state->block);
+
+ LLVMAddIncoming(state->counter, &next, &block, 1);
+
+ LLVMPositionBuilderAtEnd(builder, after_block);
+}
+
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_flow.h b/src/gallium/drivers/llvmpipe/lp_bld_flow.h
new file mode 100644
index 0000000000..9d76e3064d
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_flow.h
@@ -0,0 +1,129 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * LLVM control flow build helpers.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef LP_BLD_FLOW_H
+#define LP_BLD_FLOW_H
+
+
+#include <llvm-c/Core.h>
+
+
+union lp_type;
+
+
+struct lp_build_flow_context;
+
+
+struct lp_build_flow_context *
+lp_build_flow_create(LLVMBuilderRef builder);
+
+void
+lp_build_flow_destroy(struct lp_build_flow_context *flow);
+
+void
+lp_build_flow_scope_begin(struct lp_build_flow_context *flow);
+
+void
+lp_build_flow_scope_declare(struct lp_build_flow_context *flow,
+ LLVMValueRef *variable);
+
+void
+lp_build_flow_scope_end(struct lp_build_flow_context *flow);
+
+void
+lp_build_flow_skip_begin(struct lp_build_flow_context *flow);
+
+void
+lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow,
+ LLVMValueRef cond);
+
+void
+lp_build_flow_skip_end(struct lp_build_flow_context *flow);
+
+
+struct lp_build_mask_context
+{
+ struct lp_build_flow_context *flow;
+
+ LLVMTypeRef reg_type;
+
+ LLVMValueRef value;
+};
+
+
+void
+lp_build_mask_begin(struct lp_build_mask_context *mask,
+ struct lp_build_flow_context *flow,
+ union lp_type type,
+ LLVMValueRef value);
+
+/**
+ * Bitwise AND the mask with the given value, if a previous mask was set.
+ */
+void
+lp_build_mask_update(struct lp_build_mask_context *mask,
+ LLVMValueRef value);
+
+LLVMValueRef
+lp_build_mask_end(struct lp_build_mask_context *mask);
+
+
+/**
+ * LLVM's IR doesn't represent for-loops directly. Furthermore it
+ * it requires creating code blocks, branches, phi variables, so it
+ * requires a fair amount of code.
+ *
+ * @sa http://www.llvm.org/docs/tutorial/LangImpl5.html#for
+ */
+struct lp_build_loop_state
+{
+ LLVMBasicBlockRef block;
+ LLVMValueRef counter;
+};
+
+
+void
+lp_build_loop_begin(LLVMBuilderRef builder,
+ LLVMValueRef start,
+ struct lp_build_loop_state *state);
+
+
+void
+lp_build_loop_end(LLVMBuilderRef builder,
+ LLVMValueRef end,
+ LLVMValueRef step,
+ struct lp_build_loop_state *state);
+
+
+
+#endif /* !LP_BLD_FLOW_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_format.h b/src/gallium/drivers/llvmpipe/lp_bld_format.h
new file mode 100644
index 0000000000..5ee0656093
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_format.h
@@ -0,0 +1,119 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_BLD_H
+#define LP_BLD_H
+
+
+/**
+ * @file
+ * Pixel format helpers.
+ */
+
+#include <llvm-c/Core.h>
+
+#include "pipe/p_format.h"
+
+struct util_format_description;
+union lp_type;
+
+
+/**
+ * Unpack a pixel into its RGBA components.
+ *
+ * @param packed integer.
+ *
+ * @return RGBA in a 4 floats vector.
+ */
+LLVMValueRef
+lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
+ enum pipe_format format,
+ LLVMValueRef packed);
+
+
+/**
+ * Pack a pixel.
+ *
+ * @param rgba 4 float vector with the unpacked components.
+ */
+LLVMValueRef
+lp_build_pack_rgba_aos(LLVMBuilderRef builder,
+ enum pipe_format format,
+ LLVMValueRef rgba);
+
+
+/**
+ * Load a pixel into its RGBA components.
+ *
+ * @param ptr value with the pointer to the packed pixel. Pointer type is
+ * irrelevant.
+ *
+ * @return RGBA in a 4 floats vector.
+ */
+LLVMValueRef
+lp_build_load_rgba_aos(LLVMBuilderRef builder,
+ enum pipe_format format,
+ LLVMValueRef ptr);
+
+
+/**
+ * Store a pixel.
+ *
+ * @param rgba 4 float vector with the unpacked components.
+ */
+void
+lp_build_store_rgba_aos(LLVMBuilderRef builder,
+ enum pipe_format format,
+ LLVMValueRef ptr,
+ LLVMValueRef rgba);
+
+LLVMValueRef
+lp_build_gather(LLVMBuilderRef builder,
+ unsigned length,
+ unsigned src_width,
+ unsigned dst_width,
+ LLVMValueRef base_ptr,
+ LLVMValueRef offsets);
+
+
+void
+lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
+ const struct util_format_description *format_desc,
+ union lp_type type,
+ LLVMValueRef packed,
+ LLVMValueRef *rgba);
+
+
+void
+lp_build_load_rgba_soa(LLVMBuilderRef builder,
+ const struct util_format_description *format_desc,
+ union lp_type type,
+ LLVMValueRef base_ptr,
+ LLVMValueRef offsets,
+ LLVMValueRef *rgba);
+
+#endif /* !LP_BLD_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c b/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c
new file mode 100644
index 0000000000..b9b5d84bed
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c
@@ -0,0 +1,303 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_format.h"
+
+#include "lp_bld_format.h"
+
+
+LLVMValueRef
+lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
+ enum pipe_format format,
+ LLVMValueRef packed)
+{
+ const struct util_format_description *desc;
+ LLVMTypeRef type;
+ LLVMValueRef shifted, casted, scaled, masked;
+ LLVMValueRef shifts[4];
+ LLVMValueRef masks[4];
+ LLVMValueRef scales[4];
+ LLVMValueRef swizzles[4];
+ LLVMValueRef aux[4];
+ bool normalized;
+ int empty_channel;
+ unsigned shift;
+ unsigned i;
+
+ desc = util_format_description(format);
+
+ /* FIXME: Support more formats */
+ assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
+ assert(desc->block.width == 1);
+ assert(desc->block.height == 1);
+ assert(desc->block.bits <= 32);
+
+ type = LLVMIntType(desc->block.bits);
+
+ /* Do the intermediate integer computations with 32bit integers since it
+ * matches floating point size */
+ if (desc->block.bits < 32)
+ packed = LLVMBuildZExt(builder, packed, LLVMInt32Type(), "");
+
+ /* Broadcast the packed value to all four channels */
+ packed = LLVMBuildInsertElement(builder,
+ LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)),
+ packed,
+ LLVMConstNull(LLVMInt32Type()),
+ "");
+ packed = LLVMBuildShuffleVector(builder,
+ packed,
+ LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)),
+ LLVMConstNull(LLVMVectorType(LLVMInt32Type(), 4)),
+ "");
+
+ /* Initialize vector constants */
+ normalized = FALSE;
+ empty_channel = -1;
+ shift = 0;
+ for (i = 0; i < 4; ++i) {
+ unsigned bits = desc->channel[i].size;
+
+ if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
+ shifts[i] = LLVMGetUndef(LLVMInt32Type());
+ masks[i] = LLVMConstNull(LLVMInt32Type());
+ scales[i] = LLVMConstNull(LLVMFloatType());
+ empty_channel = i;
+ }
+ else {
+ unsigned mask = (1 << bits) - 1;
+
+ assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
+ assert(bits < 32);
+
+ shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0);
+ masks[i] = LLVMConstInt(LLVMInt32Type(), mask, 0);
+
+ if (desc->channel[i].normalized) {
+ scales[i] = LLVMConstReal(LLVMFloatType(), 1.0/mask);
+ normalized = TRUE;
+ }
+ else
+ scales[i] = LLVMConstReal(LLVMFloatType(), 1.0);
+ }
+
+ shift += bits;
+ }
+
+ shifted = LLVMBuildLShr(builder, packed, LLVMConstVector(shifts, 4), "");
+ masked = LLVMBuildAnd(builder, shifted, LLVMConstVector(masks, 4), "");
+ // UIToFP can't be expressed in SSE2
+ casted = LLVMBuildSIToFP(builder, masked, LLVMVectorType(LLVMFloatType(), 4), "");
+
+ if (normalized)
+ scaled = LLVMBuildMul(builder, casted, LLVMConstVector(scales, 4), "");
+ else
+ scaled = casted;
+
+ for (i = 0; i < 4; ++i)
+ aux[i] = LLVMGetUndef(LLVMFloatType());
+
+ for (i = 0; i < 4; ++i) {
+ enum util_format_swizzle swizzle = desc->swizzle[i];
+
+ switch (swizzle) {
+ case UTIL_FORMAT_SWIZZLE_X:
+ case UTIL_FORMAT_SWIZZLE_Y:
+ case UTIL_FORMAT_SWIZZLE_Z:
+ case UTIL_FORMAT_SWIZZLE_W:
+ swizzles[i] = LLVMConstInt(LLVMInt32Type(), swizzle, 0);
+ break;
+ case UTIL_FORMAT_SWIZZLE_0:
+ assert(empty_channel >= 0);
+ swizzles[i] = LLVMConstInt(LLVMInt32Type(), empty_channel, 0);
+ break;
+ case UTIL_FORMAT_SWIZZLE_1:
+ swizzles[i] = LLVMConstInt(LLVMInt32Type(), 4, 0);
+ aux[0] = LLVMConstReal(LLVMFloatType(), 1.0);
+ break;
+ case UTIL_FORMAT_SWIZZLE_NONE:
+ swizzles[i] = LLVMGetUndef(LLVMFloatType());
+ assert(0);
+ break;
+ }
+ }
+
+ return LLVMBuildShuffleVector(builder, scaled, LLVMConstVector(aux, 4), LLVMConstVector(swizzles, 4), "");
+}
+
+
+LLVMValueRef
+lp_build_pack_rgba_aos(LLVMBuilderRef builder,
+ enum pipe_format format,
+ LLVMValueRef rgba)
+{
+ const struct util_format_description *desc;
+ LLVMTypeRef type;
+ LLVMValueRef packed = NULL;
+ LLVMValueRef swizzles[4];
+ LLVMValueRef shifted, casted, scaled, unswizzled;
+ LLVMValueRef shifts[4];
+ LLVMValueRef scales[4];
+ bool normalized;
+ unsigned shift;
+ unsigned i, j;
+
+ desc = util_format_description(format);
+
+ assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
+ assert(desc->block.width == 1);
+ assert(desc->block.height == 1);
+
+ type = LLVMIntType(desc->block.bits);
+
+ /* Unswizzle the color components into the source vector. */
+ for (i = 0; i < 4; ++i) {
+ for (j = 0; j < 4; ++j) {
+ if (desc->swizzle[j] == i)
+ break;
+ }
+ if (j < 4)
+ swizzles[i] = LLVMConstInt(LLVMInt32Type(), j, 0);
+ else
+ swizzles[i] = LLVMGetUndef(LLVMInt32Type());
+ }
+
+ unswizzled = LLVMBuildShuffleVector(builder, rgba,
+ LLVMGetUndef(LLVMVectorType(LLVMFloatType(), 4)),
+ LLVMConstVector(swizzles, 4), "");
+
+ normalized = FALSE;
+ shift = 0;
+ for (i = 0; i < 4; ++i) {
+ unsigned bits = desc->channel[i].size;
+
+ if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
+ shifts[i] = LLVMGetUndef(LLVMInt32Type());
+ scales[i] = LLVMGetUndef(LLVMFloatType());
+ }
+ else {
+ unsigned mask = (1 << bits) - 1;
+
+ assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
+ assert(bits < 32);
+
+ shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0);
+
+ if (desc->channel[i].normalized) {
+ scales[i] = LLVMConstReal(LLVMFloatType(), mask);
+ normalized = TRUE;
+ }
+ else
+ scales[i] = LLVMConstReal(LLVMFloatType(), 1.0);
+ }
+
+ shift += bits;
+ }
+
+ if (normalized)
+ scaled = LLVMBuildMul(builder, unswizzled, LLVMConstVector(scales, 4), "");
+ else
+ scaled = unswizzled;
+
+ casted = LLVMBuildFPToSI(builder, scaled, LLVMVectorType(LLVMInt32Type(), 4), "");
+
+ shifted = LLVMBuildShl(builder, casted, LLVMConstVector(shifts, 4), "");
+
+ /* Bitwise or all components */
+ for (i = 0; i < 4; ++i) {
+ if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) {
+ LLVMValueRef component = LLVMBuildExtractElement(builder, shifted, LLVMConstInt(LLVMInt32Type(), i, 0), "");
+ if (packed)
+ packed = LLVMBuildOr(builder, packed, component, "");
+ else
+ packed = component;
+ }
+ }
+
+ if (!packed)
+ packed = LLVMGetUndef(LLVMInt32Type());
+
+ if (desc->block.bits < 32)
+ packed = LLVMBuildTrunc(builder, packed, type, "");
+
+ return packed;
+}
+
+
+LLVMValueRef
+lp_build_load_rgba_aos(LLVMBuilderRef builder,
+ enum pipe_format format,
+ LLVMValueRef ptr)
+{
+ const struct util_format_description *desc;
+ LLVMTypeRef type;
+ LLVMValueRef packed;
+
+ desc = util_format_description(format);
+
+ /* FIXME: Support more formats */
+ assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
+ assert(desc->block.width == 1);
+ assert(desc->block.height == 1);
+ assert(desc->block.bits <= 32);
+
+ type = LLVMIntType(desc->block.bits);
+
+ ptr = LLVMBuildBitCast(builder, ptr, LLVMPointerType(type, 0), "");
+
+ packed = LLVMBuildLoad(builder, ptr, "");
+
+ return lp_build_unpack_rgba_aos(builder, format, packed);
+}
+
+
+void
+lp_build_store_rgba_aos(LLVMBuilderRef builder,
+ enum pipe_format format,
+ LLVMValueRef ptr,
+ LLVMValueRef rgba)
+{
+ const struct util_format_description *desc;
+ LLVMTypeRef type;
+ LLVMValueRef packed;
+
+ desc = util_format_description(format);
+
+ assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
+ assert(desc->block.width == 1);
+ assert(desc->block.height == 1);
+
+ type = LLVMIntType(desc->block.bits);
+
+ packed = lp_build_pack_rgba_aos(builder, format, rgba);
+
+ ptr = LLVMBuildBitCast(builder, ptr, LLVMPointerType(type, 0), "");
+
+ LLVMBuildStore(builder, packed, ptr);
+}
+
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_format_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_format_soa.c
new file mode 100644
index 0000000000..569e8d10a3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_format_soa.c
@@ -0,0 +1,208 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_format.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_conv.h"
+#include "lp_bld_format.h"
+
+
+/**
+ * Gather elements from scatter positions in memory into a single vector.
+ *
+ * @param src_width src element width
+ * @param dst_width result element width (source will be expanded to fit)
+ * @param length length of the offsets,
+ * @param base_ptr base pointer, should be a i8 pointer type.
+ * @param offsets vector with offsets
+ */
+LLVMValueRef
+lp_build_gather(LLVMBuilderRef builder,
+ unsigned length,
+ unsigned src_width,
+ unsigned dst_width,
+ LLVMValueRef base_ptr,
+ LLVMValueRef offsets)
+{
+ LLVMTypeRef src_type = LLVMIntType(src_width);
+ LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0);
+ LLVMTypeRef dst_elem_type = LLVMIntType(dst_width);
+ LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length);
+ LLVMValueRef res;
+ unsigned i;
+
+ res = LLVMGetUndef(dst_vec_type);
+ for(i = 0; i < length; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ LLVMValueRef elem_offset;
+ LLVMValueRef elem_ptr;
+ LLVMValueRef elem;
+
+ elem_offset = LLVMBuildExtractElement(builder, offsets, index, "");
+ elem_ptr = LLVMBuildGEP(builder, base_ptr, &elem_offset, 1, "");
+ elem_ptr = LLVMBuildBitCast(builder, elem_ptr, src_ptr_type, "");
+ elem = LLVMBuildLoad(builder, elem_ptr, "");
+
+ assert(src_width <= dst_width);
+ if(src_width > dst_width)
+ elem = LLVMBuildTrunc(builder, elem, dst_elem_type, "");
+ if(src_width < dst_width)
+ elem = LLVMBuildZExt(builder, elem, dst_elem_type, "");
+
+ res = LLVMBuildInsertElement(builder, res, elem, index, "");
+ }
+
+ return res;
+}
+
+
+static LLVMValueRef
+lp_build_format_swizzle(union lp_type type,
+ const LLVMValueRef *inputs,
+ enum util_format_swizzle swizzle)
+{
+ switch (swizzle) {
+ case UTIL_FORMAT_SWIZZLE_X:
+ case UTIL_FORMAT_SWIZZLE_Y:
+ case UTIL_FORMAT_SWIZZLE_Z:
+ case UTIL_FORMAT_SWIZZLE_W:
+ return inputs[swizzle];
+ case UTIL_FORMAT_SWIZZLE_0:
+ return lp_build_zero(type);
+ case UTIL_FORMAT_SWIZZLE_1:
+ return lp_build_one(type);
+ case UTIL_FORMAT_SWIZZLE_NONE:
+ return lp_build_undef(type);
+ default:
+ assert(0);
+ return lp_build_undef(type);
+ }
+}
+
+
+void
+lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
+ const struct util_format_description *format_desc,
+ union lp_type type,
+ LLVMValueRef packed,
+ LLVMValueRef *rgba)
+{
+ LLVMValueRef inputs[4];
+ unsigned start;
+ unsigned chan;
+
+ /* FIXME: Support more formats */
+ assert(format_desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
+ assert(format_desc->block.width == 1);
+ assert(format_desc->block.height == 1);
+ assert(format_desc->block.bits <= 32);
+
+ /* Decode the input vector components */
+ start = 0;
+ for (chan = 0; chan < 4; ++chan) {
+ unsigned width = format_desc->channel[chan].size;
+ unsigned stop = start + width;
+ LLVMValueRef input;
+
+ input = packed;
+
+ switch(format_desc->channel[chan].type) {
+ case UTIL_FORMAT_TYPE_VOID:
+ input = NULL;
+ break;
+
+ case UTIL_FORMAT_TYPE_UNSIGNED:
+ if(type.floating) {
+ if(start)
+ input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(type, start), "");
+ if(stop < format_desc->block.bits) {
+ unsigned mask = ((unsigned long long)1 << width) - 1;
+ input = LLVMBuildAnd(builder, input, lp_build_int_const_scalar(type, mask), "");
+ }
+
+ if(format_desc->channel[chan].normalized)
+ input = lp_build_unsigned_norm_to_float(builder, width, type, input);
+ else
+ input = LLVMBuildFPToSI(builder, input, lp_build_vec_type(type), "");
+ }
+ else {
+ /* FIXME */
+ assert(0);
+ input = lp_build_undef(type);
+ }
+ break;
+
+ default:
+ /* fall through */
+ input = lp_build_undef(type);
+ break;
+ }
+
+ inputs[chan] = input;
+
+ start = stop;
+ }
+
+ if(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
+ enum util_format_swizzle swizzle = format_desc->swizzle[0];
+ LLVMValueRef depth = lp_build_format_swizzle(type, inputs, swizzle);
+ rgba[2] = rgba[1] = rgba[0] = depth;
+ rgba[3] = lp_build_one(type);
+ }
+ else {
+ for (chan = 0; chan < 4; ++chan) {
+ enum util_format_swizzle swizzle = format_desc->swizzle[chan];
+ rgba[chan] = lp_build_format_swizzle(type, inputs, swizzle);
+ }
+ }
+}
+
+
+void
+lp_build_load_rgba_soa(LLVMBuilderRef builder,
+ const struct util_format_description *format_desc,
+ union lp_type type,
+ LLVMValueRef base_ptr,
+ LLVMValueRef offsets,
+ LLVMValueRef *rgba)
+{
+ LLVMValueRef packed;
+
+ assert(format_desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
+ assert(format_desc->block.width == 1);
+ assert(format_desc->block.height == 1);
+ assert(format_desc->block.bits <= 32);
+
+ packed = lp_build_gather(builder,
+ type.length, format_desc->block.bits, type.width,
+ base_ptr, offsets);
+
+ lp_build_unpack_rgba_soa(builder, format_desc, type, packed, rgba);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.c b/src/gallium/drivers/llvmpipe/lp_bld_interp.c
new file mode 100644
index 0000000000..cfe20a0d75
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.c
@@ -0,0 +1,377 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Position and shader input interpolation.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include "pipe/p_shader_tokens.h"
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "tgsi/tgsi_parse.h"
+#include "lp_bld_debug.h"
+#include "lp_bld_const.h"
+#include "lp_bld_arit.h"
+#include "lp_bld_swizzle.h"
+#include "lp_bld_interp.h"
+
+
+static void
+attrib_name(LLVMValueRef val, unsigned attrib, unsigned chan, const char *suffix)
+{
+ if(attrib == 0)
+ lp_build_name(val, "pos.%c%s", "xyzw"[chan], suffix);
+ else
+ lp_build_name(val, "input%u.%c%s", attrib - 1, "xyzw"[chan], suffix);
+}
+
+
+static void
+coeffs_init(struct lp_build_interp_soa_context *bld,
+ LLVMValueRef a0_ptr,
+ LLVMValueRef dadx_ptr,
+ LLVMValueRef dady_ptr)
+{
+ LLVMBuilderRef builder = bld->base.builder;
+ unsigned attrib;
+ unsigned chan;
+
+ for(attrib = 0; attrib < bld->num_attribs; ++attrib) {
+ unsigned mask = bld->mask[attrib];
+ unsigned mode = bld->mode[attrib];
+ for(chan = 0; chan < NUM_CHANNELS; ++chan) {
+ if(mask & (1 << chan)) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), attrib*NUM_CHANNELS + chan, 0);
+ LLVMValueRef a0 = NULL;
+ LLVMValueRef dadx = NULL;
+ LLVMValueRef dady = NULL;
+
+ switch( mode ) {
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ /* fall-through */
+
+ case TGSI_INTERPOLATE_LINEAR:
+ dadx = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dadx_ptr, &index, 1, ""), "");
+ dady = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dady_ptr, &index, 1, ""), "");
+ dadx = lp_build_broadcast_scalar(&bld->base, dadx);
+ dady = lp_build_broadcast_scalar(&bld->base, dady);
+ attrib_name(dadx, attrib, chan, ".dadx");
+ attrib_name(dady, attrib, chan, ".dady");
+ /* fall-through */
+
+ case TGSI_INTERPOLATE_CONSTANT:
+ a0 = LLVMBuildLoad(builder, LLVMBuildGEP(builder, a0_ptr, &index, 1, ""), "");
+ a0 = lp_build_broadcast_scalar(&bld->base, a0);
+ attrib_name(a0, attrib, chan, ".dady");
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ bld->a0 [attrib][chan] = a0;
+ bld->dadx[attrib][chan] = dadx;
+ bld->dady[attrib][chan] = dady;
+ }
+ }
+ }
+}
+
+
+/**
+ * Small vector x scale multiplication optimization.
+ *
+ * TODO: Should be elsewhere.
+ */
+static LLVMValueRef
+coeff_multiply(struct lp_build_interp_soa_context *bld,
+ LLVMValueRef coeff,
+ int step)
+{
+ LLVMValueRef factor;
+
+ switch(step) {
+ case 0:
+ return bld->base.zero;
+ case 1:
+ return coeff;
+ case 2:
+ return lp_build_add(&bld->base, coeff, coeff);
+ default:
+ factor = lp_build_const_scalar(bld->base.type, (double)step);
+ return lp_build_mul(&bld->base, coeff, factor);
+ }
+}
+
+
+/**
+ * Multiply the dadx and dady with the xstep and ystep respectively.
+ */
+static void
+coeffs_update(struct lp_build_interp_soa_context *bld)
+{
+ unsigned attrib;
+ unsigned chan;
+
+ for(attrib = 0; attrib < bld->num_attribs; ++attrib) {
+ unsigned mask = bld->mask[attrib];
+ unsigned mode = bld->mode[attrib];
+ if (mode != TGSI_INTERPOLATE_CONSTANT) {
+ for(chan = 0; chan < NUM_CHANNELS; ++chan) {
+ if(mask & (1 << chan)) {
+ bld->dadx[attrib][chan] = coeff_multiply(bld, bld->dadx[attrib][chan], bld->xstep);
+ bld->dady[attrib][chan] = coeff_multiply(bld, bld->dady[attrib][chan], bld->ystep);
+ }
+ }
+ }
+ }
+}
+
+
+static void
+attribs_init(struct lp_build_interp_soa_context *bld)
+{
+ LLVMValueRef x = bld->pos[0];
+ LLVMValueRef y = bld->pos[1];
+ LLVMValueRef oow = NULL;
+ unsigned attrib;
+ unsigned chan;
+
+ for(attrib = 0; attrib < bld->num_attribs; ++attrib) {
+ unsigned mask = bld->mask[attrib];
+ unsigned mode = bld->mode[attrib];
+ for(chan = 0; chan < NUM_CHANNELS; ++chan) {
+ if(mask & (1 << chan)) {
+ LLVMValueRef a0 = bld->a0 [attrib][chan];
+ LLVMValueRef dadx = bld->dadx[attrib][chan];
+ LLVMValueRef dady = bld->dady[attrib][chan];
+ LLVMValueRef res;
+
+ res = a0;
+
+ if (mode != TGSI_INTERPOLATE_CONSTANT) {
+ res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, x, dadx));
+ res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, y, dady));
+ }
+
+ /* Keep the value of the attribue before perspective divide for faster updates */
+ bld->attribs_pre[attrib][chan] = res;
+
+ if (mode == TGSI_INTERPOLATE_PERSPECTIVE) {
+ LLVMValueRef w = bld->pos[3];
+ assert(attrib != 0);
+ if(!oow)
+ oow = lp_build_rcp(&bld->base, w);
+ res = lp_build_mul(&bld->base, res, oow);
+ }
+
+ attrib_name(res, attrib, chan, "");
+
+ bld->attribs[attrib][chan] = res;
+ }
+ }
+ }
+}
+
+
+static void
+attribs_update(struct lp_build_interp_soa_context *bld)
+{
+ LLVMValueRef oow = NULL;
+ unsigned attrib;
+ unsigned chan;
+
+ for(attrib = 0; attrib < bld->num_attribs; ++attrib) {
+ unsigned mask = bld->mask[attrib];
+ unsigned mode = bld->mode[attrib];
+
+ if (mode != TGSI_INTERPOLATE_CONSTANT) {
+ for(chan = 0; chan < NUM_CHANNELS; ++chan) {
+ if(mask & (1 << chan)) {
+ LLVMValueRef dadx = bld->dadx[attrib][chan];
+ LLVMValueRef dady = bld->dady[attrib][chan];
+ LLVMValueRef res;
+
+ res = bld->attribs_pre[attrib][chan];
+
+ if(bld->xstep)
+ res = lp_build_add(&bld->base, res, dadx);
+
+ if(bld->ystep)
+ res = lp_build_add(&bld->base, res, dady);
+
+ bld->attribs_pre[attrib][chan] = res;
+
+ if (mode == TGSI_INTERPOLATE_PERSPECTIVE) {
+ LLVMValueRef w = bld->pos[3];
+ assert(attrib != 0);
+ if(!oow)
+ oow = lp_build_rcp(&bld->base, w);
+ res = lp_build_mul(&bld->base, res, oow);
+ }
+
+ attrib_name(res, attrib, chan, "");
+
+ bld->attribs[attrib][chan] = res;
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Generate the position vectors.
+ *
+ * Parameter x0, y0 are the integer values with the quad upper left coordinates.
+ */
+static void
+pos_init(struct lp_build_interp_soa_context *bld,
+ LLVMValueRef x0,
+ LLVMValueRef y0)
+{
+ lp_build_name(x0, "pos.x");
+ lp_build_name(y0, "pos.y");
+
+ bld->attribs[0][0] = x0;
+ bld->attribs[0][1] = y0;
+}
+
+
+static void
+pos_update(struct lp_build_interp_soa_context *bld)
+{
+ LLVMValueRef x = bld->attribs[0][0];
+ LLVMValueRef y = bld->attribs[0][1];
+
+ if(bld->xstep)
+ x = lp_build_add(&bld->base, x, lp_build_const_scalar(bld->base.type, bld->xstep));
+
+ if(bld->ystep)
+ y = lp_build_add(&bld->base, y, lp_build_const_scalar(bld->base.type, bld->ystep));
+
+ lp_build_name(x, "pos.x");
+ lp_build_name(y, "pos.y");
+
+ bld->attribs[0][0] = x;
+ bld->attribs[0][1] = y;
+}
+
+
+void
+lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
+ const struct tgsi_token *tokens,
+ LLVMBuilderRef builder,
+ union lp_type type,
+ LLVMValueRef a0_ptr,
+ LLVMValueRef dadx_ptr,
+ LLVMValueRef dady_ptr,
+ LLVMValueRef x0,
+ LLVMValueRef y0,
+ int xstep,
+ int ystep)
+{
+ struct tgsi_parse_context parse;
+ struct tgsi_full_declaration *decl;
+
+ memset(bld, 0, sizeof *bld);
+
+ lp_build_context_init(&bld->base, builder, type);
+
+ /* For convenience */
+ bld->pos = bld->attribs[0];
+ bld->inputs = (const LLVMValueRef (*)[NUM_CHANNELS]) bld->attribs[1];
+
+ /* Position */
+ bld->num_attribs = 1;
+ bld->mask[0] = TGSI_WRITEMASK_ZW;
+ bld->mode[0] = TGSI_INTERPOLATE_LINEAR;
+
+ /* Inputs */
+ tgsi_parse_init( &parse, tokens );
+ while( !tgsi_parse_end_of_tokens( &parse ) ) {
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ decl = &parse.FullToken.FullDeclaration;
+ if( decl->Declaration.File == TGSI_FILE_INPUT ) {
+ unsigned first, last, mask;
+ unsigned attrib;
+
+ first = decl->DeclarationRange.First;
+ last = decl->DeclarationRange.Last;
+ mask = decl->Declaration.UsageMask;
+
+ for( attrib = first; attrib <= last; ++attrib ) {
+ bld->mask[1 + attrib] = mask;
+ bld->mode[1 + attrib] = decl->Declaration.Interpolate;
+ }
+
+ bld->num_attribs = MAX2(bld->num_attribs, 1 + last + 1);
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+ tgsi_parse_free( &parse );
+
+ coeffs_init(bld, a0_ptr, dadx_ptr, dady_ptr);
+
+ pos_init(bld, x0, y0);
+
+ attribs_init(bld);
+
+ bld->xstep = xstep;
+ bld->ystep = ystep;
+
+ coeffs_update(bld);
+}
+
+
+/**
+ * Advance the position and inputs with the xstep and ystep.
+ */
+void
+lp_build_interp_soa_update(struct lp_build_interp_soa_context *bld)
+{
+ pos_update(bld);
+
+ attribs_update(bld);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.h b/src/gallium/drivers/llvmpipe/lp_bld_interp.h
new file mode 100644
index 0000000000..9194f6233a
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.h
@@ -0,0 +1,99 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Position and shader input interpolation.
+ *
+ * Special attention is given to the interpolation of side by side quads.
+ * Multiplications are made only for the first quad. Interpolation of
+ * inputs for posterior quads are done exclusively with additions, and
+ * perspective divide if necessary.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef LP_BLD_INTERP_H
+#define LP_BLD_INTERP_H
+
+
+#include <llvm-c/Core.h>
+
+#include "tgsi/tgsi_exec.h"
+
+#include "lp_bld_type.h"
+
+
+struct tgsi_token;
+
+
+struct lp_build_interp_soa_context
+{
+ struct lp_build_context base;
+
+ unsigned num_attribs;
+ unsigned mask[1 + PIPE_MAX_SHADER_INPUTS];
+ unsigned mode[1 + PIPE_MAX_SHADER_INPUTS];
+
+ LLVMValueRef a0 [1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
+ LLVMValueRef dadx[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
+ LLVMValueRef dady[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
+
+ int xstep;
+ int ystep;
+
+ /* Attribute values before perspective divide */
+ LLVMValueRef attribs_pre[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
+
+ LLVMValueRef attribs[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
+
+ /*
+ * Convenience pointers. Callers may access this one.
+ */
+ const LLVMValueRef *pos;
+ const LLVMValueRef (*inputs)[NUM_CHANNELS];
+};
+
+
+void
+lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
+ const struct tgsi_token *tokens,
+ LLVMBuilderRef builder,
+ union lp_type type,
+ LLVMValueRef a0_ptr,
+ LLVMValueRef dadx_ptr,
+ LLVMValueRef dady_ptr,
+ LLVMValueRef x0,
+ LLVMValueRef y0,
+ int xstep,
+ int ystep);
+
+void
+lp_build_interp_soa_update(struct lp_build_interp_soa_context *bld);
+
+
+#endif /* LP_BLD_INTERP_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_intr.c b/src/gallium/drivers/llvmpipe/lp_bld_intr.c
new file mode 100644
index 0000000000..9895749d56
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_intr.c
@@ -0,0 +1,192 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Helpers for emiting intrinsic calls.
+ *
+ * LLVM vanilla IR doesn't represent all basic arithmetic operations we care
+ * about, and it is often necessary to resort target-specific intrinsics for
+ * performance, convenience.
+ *
+ * Ideally we would like to stay away from target specific intrinsics and
+ * move all the instruction selection logic into upstream LLVM where it belongs.
+ *
+ * These functions are also used for calling C functions provided by us from
+ * generated LLVM code.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "util/u_debug.h"
+
+#include "lp_bld_intr.h"
+
+
+LLVMValueRef
+lp_declare_intrinsic(LLVMModuleRef module,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMTypeRef *arg_types,
+ unsigned num_args)
+{
+ LLVMTypeRef function_type;
+ LLVMValueRef function;
+
+ assert(!LLVMGetNamedFunction(module, name));
+
+ function_type = LLVMFunctionType(ret_type, arg_types, num_args, 0);
+ function = LLVMAddFunction(module, name, function_type);
+
+ LLVMSetFunctionCallConv(function, LLVMCCallConv);
+ LLVMSetLinkage(function, LLVMExternalLinkage);
+
+ assert(LLVMIsDeclaration(function));
+
+ if(name[0] == 'l' &&
+ name[1] == 'l' &&
+ name[2] == 'v' &&
+ name[3] == 'm' &&
+ name[4] == '.')
+ assert(LLVMGetIntrinsicID(function));
+
+ return function;
+}
+
+
+LLVMValueRef
+lp_build_intrinsic(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef *args,
+ unsigned num_args)
+{
+ LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)));
+ LLVMValueRef function;
+
+ function = LLVMGetNamedFunction(module, name);
+ if(!function) {
+ LLVMTypeRef arg_types[LP_MAX_FUNC_ARGS];
+ unsigned i;
+
+ assert(num_args <= LP_MAX_FUNC_ARGS);
+
+ for(i = 0; i < num_args; ++i) {
+ assert(args[i]);
+ arg_types[i] = LLVMTypeOf(args[i]);
+ }
+
+ function = lp_declare_intrinsic(module, name, ret_type, arg_types, num_args);
+ }
+
+ return LLVMBuildCall(builder, function, args, num_args, "");
+}
+
+
+LLVMValueRef
+lp_build_intrinsic_unary(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef a)
+{
+ return lp_build_intrinsic(builder, name, ret_type, &a, 1);
+}
+
+
+LLVMValueRef
+lp_build_intrinsic_binary(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ LLVMValueRef args[2];
+
+ args[0] = a;
+ args[1] = b;
+
+ return lp_build_intrinsic(builder, name, ret_type, args, 2);
+}
+
+
+LLVMValueRef
+lp_build_intrinsic_map(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef *args,
+ unsigned num_args)
+{
+ LLVMTypeRef ret_elem_type = LLVMGetElementType(ret_type);
+ unsigned n = LLVMGetVectorSize(ret_type);
+ unsigned i, j;
+ LLVMValueRef res;
+
+ assert(num_args <= LP_MAX_FUNC_ARGS);
+
+ res = LLVMGetUndef(ret_type);
+ for(i = 0; i < n; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ LLVMValueRef arg_elems[LP_MAX_FUNC_ARGS];
+ LLVMValueRef res_elem;
+ for(j = 0; j < num_args; ++j)
+ arg_elems[j] = LLVMBuildExtractElement(builder, args[j], index, "");
+ res_elem = lp_build_intrinsic(builder, name, ret_elem_type, arg_elems, num_args);
+ res = LLVMBuildInsertElement(builder, res, res_elem, index, "");
+ }
+
+ return res;
+}
+
+
+LLVMValueRef
+lp_build_intrinsic_map_unary(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef a)
+{
+ return lp_build_intrinsic_map(builder, name, ret_type, &a, 1);
+}
+
+
+LLVMValueRef
+lp_build_intrinsic_map_binary(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ LLVMValueRef args[2];
+
+ args[0] = a;
+ args[1] = b;
+
+ return lp_build_intrinsic_map(builder, name, ret_type, args, 2);
+}
+
+
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_intr.h b/src/gallium/drivers/llvmpipe/lp_bld_intr.h
new file mode 100644
index 0000000000..f813f27074
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_intr.h
@@ -0,0 +1,102 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Helper functions for calling intrinsics.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifndef LP_BLD_INTR_H
+#define LP_BLD_INTR_H
+
+
+#include <llvm-c/Core.h>
+
+
+/**
+ * Max number of arguments in an intrinsic.
+ */
+#define LP_MAX_FUNC_ARGS 32
+
+
+LLVMValueRef
+lp_declare_intrinsic(LLVMModuleRef module,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMTypeRef *arg_types,
+ unsigned num_args);
+
+LLVMValueRef
+lp_build_intrinsic(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef *args,
+ unsigned num_args);
+
+
+LLVMValueRef
+lp_build_intrinsic_unary(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef a);
+
+
+LLVMValueRef
+lp_build_intrinsic_binary(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+
+LLVMValueRef
+lp_build_intrinsic_map(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef *args,
+ unsigned num_args);
+
+
+LLVMValueRef
+lp_build_intrinsic_map_unary(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef a);
+
+
+LLVMValueRef
+lp_build_intrinsic_map_binary(LLVMBuilderRef builder,
+ const char *name,
+ LLVMTypeRef ret_type,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+
+#endif /* !LP_BLD_INTR_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_logic.c b/src/gallium/drivers/llvmpipe/lp_bld_logic.c
new file mode 100644
index 0000000000..d566780e5d
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_logic.c
@@ -0,0 +1,394 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Helper functions for logical operations.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_intr.h"
+#include "lp_bld_logic.h"
+
+
+LLVMValueRef
+lp_build_cmp(struct lp_build_context *bld,
+ unsigned func,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ const union lp_type type = bld->type;
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
+ LLVMValueRef zeros = LLVMConstNull(int_vec_type);
+ LLVMValueRef ones = LLVMConstAllOnes(int_vec_type);
+ LLVMValueRef cond;
+ LLVMValueRef res;
+ unsigned i;
+
+ if(func == PIPE_FUNC_NEVER)
+ return zeros;
+ if(func == PIPE_FUNC_ALWAYS)
+ return ones;
+
+ /* TODO: optimize the constant case */
+
+ /* XXX: It is not clear if we should use the ordered or unordered operators */
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ if(type.width * type.length == 128) {
+ if(type.floating) {
+ LLVMValueRef args[3];
+ unsigned cc;
+ boolean swap;
+
+ swap = FALSE;
+ switch(func) {
+ case PIPE_FUNC_EQUAL:
+ cc = 0;
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ cc = 4;
+ break;
+ case PIPE_FUNC_LESS:
+ cc = 1;
+ break;
+ case PIPE_FUNC_LEQUAL:
+ cc = 2;
+ break;
+ case PIPE_FUNC_GREATER:
+ cc = 1;
+ swap = TRUE;
+ break;
+ case PIPE_FUNC_GEQUAL:
+ cc = 2;
+ swap = TRUE;
+ break;
+ default:
+ assert(0);
+ return bld->undef;
+ }
+
+ if(swap) {
+ args[0] = b;
+ args[1] = a;
+ }
+ else {
+ args[0] = a;
+ args[1] = b;
+ }
+
+ args[2] = LLVMConstInt(LLVMInt8Type(), cc, 0);
+ res = lp_build_intrinsic(bld->builder,
+ "llvm.x86.sse.cmp.ps",
+ vec_type,
+ args, 3);
+ res = LLVMBuildBitCast(bld->builder, res, int_vec_type, "");
+ return res;
+ }
+ else {
+ static const struct {
+ unsigned swap:1;
+ unsigned eq:1;
+ unsigned gt:1;
+ unsigned not:1;
+ } table[] = {
+ {0, 0, 0, 1}, /* PIPE_FUNC_NEVER */
+ {1, 0, 1, 0}, /* PIPE_FUNC_LESS */
+ {0, 1, 0, 0}, /* PIPE_FUNC_EQUAL */
+ {0, 0, 1, 1}, /* PIPE_FUNC_LEQUAL */
+ {0, 0, 1, 0}, /* PIPE_FUNC_GREATER */
+ {0, 1, 0, 1}, /* PIPE_FUNC_NOTEQUAL */
+ {1, 0, 1, 1}, /* PIPE_FUNC_GEQUAL */
+ {0, 0, 0, 0} /* PIPE_FUNC_ALWAYS */
+ };
+ const char *pcmpeq;
+ const char *pcmpgt;
+ LLVMValueRef args[2];
+ LLVMValueRef res;
+
+ switch (type.width) {
+ case 8:
+ pcmpeq = "llvm.x86.sse2.pcmpeq.b";
+ pcmpgt = "llvm.x86.sse2.pcmpgt.b";
+ break;
+ case 16:
+ pcmpeq = "llvm.x86.sse2.pcmpeq.w";
+ pcmpgt = "llvm.x86.sse2.pcmpgt.w";
+ break;
+ case 32:
+ pcmpeq = "llvm.x86.sse2.pcmpeq.d";
+ pcmpgt = "llvm.x86.sse2.pcmpgt.d";
+ break;
+ default:
+ assert(0);
+ return bld->undef;
+ }
+
+ /* There are no signed byte and unsigned word/dword comparison
+ * instructions. So flip the sign bit so that the results match.
+ */
+ if(table[func].gt &&
+ ((type.width == 8 && type.sign) ||
+ (type.width != 8 && !type.sign))) {
+ LLVMValueRef msb = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1));
+ a = LLVMBuildXor(bld->builder, a, msb, "");
+ b = LLVMBuildXor(bld->builder, b, msb, "");
+ }
+
+ if(table[func].swap) {
+ args[0] = b;
+ args[1] = a;
+ }
+ else {
+ args[0] = a;
+ args[1] = b;
+ }
+
+ if(table[func].eq)
+ res = lp_build_intrinsic(bld->builder, pcmpeq, vec_type, args, 2);
+ else if (table[func].gt)
+ res = lp_build_intrinsic(bld->builder, pcmpgt, vec_type, args, 2);
+ else
+ res = LLVMConstNull(vec_type);
+
+ if(table[func].not)
+ res = LLVMBuildNot(bld->builder, res, "");
+
+ return res;
+ }
+ }
+#endif
+
+ if(type.floating) {
+ LLVMRealPredicate op;
+ switch(func) {
+ case PIPE_FUNC_NEVER:
+ op = LLVMRealPredicateFalse;
+ break;
+ case PIPE_FUNC_ALWAYS:
+ op = LLVMRealPredicateTrue;
+ break;
+ case PIPE_FUNC_EQUAL:
+ op = LLVMRealUEQ;
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ op = LLVMRealUNE;
+ break;
+ case PIPE_FUNC_LESS:
+ op = LLVMRealULT;
+ break;
+ case PIPE_FUNC_LEQUAL:
+ op = LLVMRealULE;
+ break;
+ case PIPE_FUNC_GREATER:
+ op = LLVMRealUGT;
+ break;
+ case PIPE_FUNC_GEQUAL:
+ op = LLVMRealUGE;
+ break;
+ default:
+ assert(0);
+ return bld->undef;
+ }
+
+#if 0
+ /* XXX: Although valid IR, no LLVM target currently support this */
+ cond = LLVMBuildFCmp(bld->builder, op, a, b, "");
+ res = LLVMBuildSelect(bld->builder, cond, ones, zeros, "");
+#else
+ debug_printf("%s: warning: using slow element-wise vector comparison\n",
+ __FUNCTION__);
+ res = LLVMGetUndef(int_vec_type);
+ for(i = 0; i < type.length; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ cond = LLVMBuildFCmp(bld->builder, op,
+ LLVMBuildExtractElement(bld->builder, a, index, ""),
+ LLVMBuildExtractElement(bld->builder, b, index, ""),
+ "");
+ cond = LLVMBuildSelect(bld->builder, cond,
+ LLVMConstExtractElement(ones, index),
+ LLVMConstExtractElement(zeros, index),
+ "");
+ res = LLVMBuildInsertElement(bld->builder, res, cond, index, "");
+ }
+#endif
+ }
+ else {
+ LLVMIntPredicate op;
+ switch(func) {
+ case PIPE_FUNC_EQUAL:
+ op = LLVMIntEQ;
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ op = LLVMIntNE;
+ break;
+ case PIPE_FUNC_LESS:
+ op = type.sign ? LLVMIntSLT : LLVMIntULT;
+ break;
+ case PIPE_FUNC_LEQUAL:
+ op = type.sign ? LLVMIntSLE : LLVMIntULE;
+ break;
+ case PIPE_FUNC_GREATER:
+ op = type.sign ? LLVMIntSGT : LLVMIntUGT;
+ break;
+ case PIPE_FUNC_GEQUAL:
+ op = type.sign ? LLVMIntSGE : LLVMIntUGE;
+ break;
+ default:
+ assert(0);
+ return bld->undef;
+ }
+
+#if 0
+ /* XXX: Although valid IR, no LLVM target currently support this */
+ cond = LLVMBuildICmp(bld->builder, op, a, b, "");
+ res = LLVMBuildSelect(bld->builder, cond, ones, zeros, "");
+#else
+ debug_printf("%s: warning: using slow element-wise vector comparison\n",
+ __FUNCTION__);
+ res = LLVMGetUndef(int_vec_type);
+ for(i = 0; i < type.length; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ cond = LLVMBuildICmp(bld->builder, op,
+ LLVMBuildExtractElement(bld->builder, a, index, ""),
+ LLVMBuildExtractElement(bld->builder, b, index, ""),
+ "");
+ cond = LLVMBuildSelect(bld->builder, cond,
+ LLVMConstExtractElement(ones, index),
+ LLVMConstExtractElement(zeros, index),
+ "");
+ res = LLVMBuildInsertElement(bld->builder, res, cond, index, "");
+ }
+#endif
+ }
+
+ return res;
+}
+
+
+LLVMValueRef
+lp_build_select(struct lp_build_context *bld,
+ LLVMValueRef mask,
+ LLVMValueRef a,
+ LLVMValueRef b)
+{
+ union lp_type type = bld->type;
+ LLVMValueRef res;
+
+ if(a == b)
+ return a;
+
+ if(type.floating) {
+ LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
+ a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
+ b = LLVMBuildBitCast(bld->builder, b, int_vec_type, "");
+ }
+
+ a = LLVMBuildAnd(bld->builder, a, mask, "");
+
+ /* This often gets translated to PANDN, but sometimes the NOT is
+ * pre-computed and stored in another constant. The best strategy depends
+ * on available registers, so it is not a big deal -- hopefully LLVM does
+ * the right decision attending the rest of the program.
+ */
+ b = LLVMBuildAnd(bld->builder, b, LLVMBuildNot(bld->builder, mask, ""), "");
+
+ res = LLVMBuildOr(bld->builder, a, b, "");
+
+ if(type.floating) {
+ LLVMTypeRef vec_type = lp_build_vec_type(type);
+ res = LLVMBuildBitCast(bld->builder, res, vec_type, "");
+ }
+
+ return res;
+}
+
+
+LLVMValueRef
+lp_build_select_aos(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b,
+ boolean cond[4])
+{
+ const union lp_type type = bld->type;
+ const unsigned n = type.length;
+ unsigned i, j;
+
+ if(a == b)
+ return a;
+ if(cond[0] && cond[1] && cond[2] && cond[3])
+ return a;
+ if(!cond[0] && !cond[1] && !cond[2] && !cond[3])
+ return b;
+ if(a == bld->undef || b == bld->undef)
+ return bld->undef;
+
+ /*
+ * There are three major ways of accomplishing this:
+ * - with a shuffle,
+ * - with a select,
+ * - or with a bit mask.
+ *
+ * Select isn't supported for vector types yet.
+ * The flip between these is empirical and might need to be.
+ */
+ if (n <= 4) {
+ /*
+ * Shuffle.
+ */
+ LLVMTypeRef elem_type = LLVMInt32Type();
+ LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
+
+ for(j = 0; j < n; j += 4)
+ for(i = 0; i < 4; ++i)
+ shuffles[j + i] = LLVMConstInt(elem_type, (cond[i] ? 0 : n) + j + i, 0);
+
+ return LLVMBuildShuffleVector(bld->builder, a, b, LLVMConstVector(shuffles, n), "");
+ }
+ else {
+#if 0
+ /* XXX: Unfortunately select of vectors do not work */
+ /* Use a select */
+ LLVMTypeRef elem_type = LLVMInt1Type();
+ LLVMValueRef cond[LP_MAX_VECTOR_LENGTH];
+
+ for(j = 0; j < n; j += 4)
+ for(i = 0; i < 4; ++i)
+ cond[j + i] = LLVMConstInt(elem_type, cond[i] ? 1 : 0, 0);
+
+ return LLVMBuildSelect(bld->builder, LLVMConstVector(cond, n), a, b, "");
+#else
+ LLVMValueRef mask = lp_build_const_mask_aos(type, cond);
+ return lp_build_select(bld, mask, a, b);
+#endif
+ }
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_logic.h b/src/gallium/drivers/llvmpipe/lp_bld_logic.h
new file mode 100644
index 0000000000..29b9e1c45b
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_logic.h
@@ -0,0 +1,72 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Helper functions for logical operations.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifndef LP_BLD_LOGIC_H
+#define LP_BLD_LOGIC_H
+
+
+#include <llvm-c/Core.h>
+
+#include "pipe/p_defines.h" /* For PIPE_FUNC_xxx */
+
+
+union lp_type type;
+struct lp_build_context;
+
+
+/**
+ * @param func is one of PIPE_FUNC_xxx
+ */
+LLVMValueRef
+lp_build_cmp(struct lp_build_context *bld,
+ unsigned func,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+
+LLVMValueRef
+lp_build_select(struct lp_build_context *bld,
+ LLVMValueRef mask,
+ LLVMValueRef a,
+ LLVMValueRef b);
+
+LLVMValueRef
+lp_build_select_aos(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b,
+ boolean cond[4]);
+
+
+#endif /* !LP_BLD_LOGIC_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_sample.h b/src/gallium/drivers/llvmpipe/lp_bld_sample.h
new file mode 100644
index 0000000000..6f565af76d
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_sample.h
@@ -0,0 +1,135 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Texture sampling.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef LP_BLD_SAMPLE_H
+#define LP_BLD_SAMPLE_H
+
+
+#include <llvm-c/Core.h>
+
+struct pipe_texture;
+struct pipe_sampler_state;
+union lp_type;
+
+
+/**
+ * Sampler static state.
+ *
+ * These are the bits of state from pipe_texture and pipe_sampler_state that
+ * are embedded in the generated code.
+ */
+struct lp_sampler_static_state
+{
+ /* pipe_texture's state */
+ enum pipe_format format;
+ unsigned target:2;
+ unsigned pot_width:1;
+ unsigned pot_height:1;
+ unsigned pot_depth:1;
+
+ /* pipe_sampler_state's state */
+ unsigned wrap_s:3;
+ unsigned wrap_t:3;
+ unsigned wrap_r:3;
+ unsigned min_img_filter:2;
+ unsigned min_mip_filter:2;
+ unsigned mag_img_filter:2;
+ unsigned compare_mode:1;
+ unsigned compare_func:3;
+ unsigned normalized_coords:1;
+ unsigned prefilter:4;
+};
+
+
+/**
+ * Sampler dynamic state.
+ *
+ * These are the bits of state from pipe_texture and pipe_sampler_state that
+ * are computed in runtime.
+ *
+ * There are obtained through callbacks, as we don't want to tie the texture
+ * sampling code generation logic to any particular texture layout or pipe
+ * driver.
+ */
+struct lp_sampler_dynamic_state
+{
+
+ /** Obtain the base texture width. */
+ LLVMValueRef
+ (*width)( struct lp_sampler_dynamic_state *state,
+ LLVMBuilderRef builder,
+ unsigned unit);
+
+ /** Obtain the base texture height. */
+ LLVMValueRef
+ (*height)( struct lp_sampler_dynamic_state *state,
+ LLVMBuilderRef builder,
+ unsigned unit);
+
+ LLVMValueRef
+ (*stride)( struct lp_sampler_dynamic_state *state,
+ LLVMBuilderRef builder,
+ unsigned unit);
+
+ LLVMValueRef
+ (*data_ptr)( struct lp_sampler_dynamic_state *state,
+ LLVMBuilderRef builder,
+ unsigned unit);
+
+};
+
+
+/**
+ * Derive the sampler static state.
+ */
+void
+lp_sampler_static_state(struct lp_sampler_static_state *state,
+ const struct pipe_texture *texture,
+ const struct pipe_sampler_state *sampler);
+
+
+void
+lp_build_sample_soa(LLVMBuilderRef builder,
+ const struct lp_sampler_static_state *static_state,
+ struct lp_sampler_dynamic_state *dynamic_state,
+ union lp_type fp_type,
+ unsigned unit,
+ unsigned num_coords,
+ const LLVMValueRef *coords,
+ LLVMValueRef lodbias,
+ LLVMValueRef *texel);
+
+
+
+#endif /* LP_BLD_SAMPLE_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_sample_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_sample_soa.c
new file mode 100644
index 0000000000..3ca25b0e76
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_sample_soa.c
@@ -0,0 +1,411 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Texture sampling.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
+#include "lp_bld_debug.h"
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_arit.h"
+#include "lp_bld_logic.h"
+#include "lp_bld_swizzle.h"
+#include "lp_bld_format.h"
+#include "lp_bld_sample.h"
+
+
+void
+lp_sampler_static_state(struct lp_sampler_static_state *state,
+ const struct pipe_texture *texture,
+ const struct pipe_sampler_state *sampler)
+{
+ memset(state, 0, sizeof *state);
+
+ if(!texture)
+ return;
+
+ if(!sampler)
+ return;
+
+ state->format = texture->format;
+ state->target = texture->target;
+ state->pot_width = util_is_pot(texture->width[0]);
+ state->pot_height = util_is_pot(texture->height[0]);
+ state->pot_depth = util_is_pot(texture->depth[0]);
+
+ state->wrap_s = sampler->wrap_s;
+ state->wrap_t = sampler->wrap_t;
+ state->wrap_r = sampler->wrap_r;
+ state->min_img_filter = sampler->min_img_filter;
+ state->min_mip_filter = sampler->min_mip_filter;
+ state->mag_img_filter = sampler->mag_img_filter;
+ if(sampler->compare_mode) {
+ state->compare_mode = sampler->compare_mode;
+ state->compare_func = sampler->compare_func;
+ }
+ state->normalized_coords = sampler->normalized_coords;
+ state->prefilter = sampler->prefilter;
+}
+
+
+
+/**
+ * Keep all information for sampling code generation in a single place.
+ */
+struct lp_build_sample_context
+{
+ LLVMBuilderRef builder;
+
+ const struct lp_sampler_static_state *static_state;
+
+ struct lp_sampler_dynamic_state *dynamic_state;
+
+ const struct util_format_description *format_desc;
+
+ /** Incoming coordinates type and build context */
+ union lp_type coord_type;
+ struct lp_build_context coord_bld;
+
+ /** Integer coordinates */
+ union lp_type int_coord_type;
+ struct lp_build_context int_coord_bld;
+
+ /** Output texels type and build context */
+ union lp_type texel_type;
+ struct lp_build_context texel_bld;
+};
+
+
+static void
+lp_build_sample_texel(struct lp_build_sample_context *bld,
+ LLVMValueRef x,
+ LLVMValueRef y,
+ LLVMValueRef y_stride,
+ LLVMValueRef data_ptr,
+ LLVMValueRef *texel)
+{
+ struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
+ LLVMValueRef x_stride;
+ LLVMValueRef offset;
+
+ x_stride = lp_build_const_scalar(bld->int_coord_type, bld->format_desc->block.bits/8);
+
+ if(bld->format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
+ LLVMValueRef x_lo, x_hi;
+ LLVMValueRef y_lo, y_hi;
+ LLVMValueRef x_stride_lo, x_stride_hi;
+ LLVMValueRef y_stride_lo, y_stride_hi;
+ LLVMValueRef x_offset_lo, x_offset_hi;
+ LLVMValueRef y_offset_lo, y_offset_hi;
+ LLVMValueRef offset_lo, offset_hi;
+
+ x_lo = LLVMBuildAnd(bld->builder, x, int_coord_bld->one, "");
+ y_lo = LLVMBuildAnd(bld->builder, y, int_coord_bld->one, "");
+
+ x_hi = LLVMBuildLShr(bld->builder, x, int_coord_bld->one, "");
+ y_hi = LLVMBuildLShr(bld->builder, y, int_coord_bld->one, "");
+
+ x_stride_lo = x_stride;
+ y_stride_lo = lp_build_const_scalar(bld->int_coord_type, 2*bld->format_desc->block.bits/8);
+
+ x_stride_hi = lp_build_const_scalar(bld->int_coord_type, 4*bld->format_desc->block.bits/8);
+ y_stride_hi = LLVMBuildShl(bld->builder, y_stride, int_coord_bld->one, "");
+
+ x_offset_lo = lp_build_mul(int_coord_bld, x_lo, x_stride_lo);
+ y_offset_lo = lp_build_mul(int_coord_bld, y_lo, y_stride_lo);
+ offset_lo = lp_build_add(int_coord_bld, x_offset_lo, y_offset_lo);
+
+ x_offset_hi = lp_build_mul(int_coord_bld, x_hi, x_stride_hi);
+ y_offset_hi = lp_build_mul(int_coord_bld, y_hi, y_stride_hi);
+ offset_hi = lp_build_add(int_coord_bld, x_offset_hi, y_offset_hi);
+
+ offset = lp_build_add(int_coord_bld, offset_hi, offset_lo);
+ }
+ else {
+ LLVMValueRef x_offset;
+ LLVMValueRef y_offset;
+
+ x_offset = lp_build_mul(int_coord_bld, x, x_stride);
+ y_offset = lp_build_mul(int_coord_bld, y, y_stride);
+
+ offset = lp_build_add(int_coord_bld, x_offset, y_offset);
+ }
+
+ lp_build_load_rgba_soa(bld->builder,
+ bld->format_desc,
+ bld->texel_type,
+ data_ptr,
+ offset,
+ texel);
+}
+
+
+static LLVMValueRef
+lp_build_sample_wrap(struct lp_build_sample_context *bld,
+ LLVMValueRef coord,
+ LLVMValueRef length,
+ boolean is_pot,
+ unsigned wrap_mode)
+{
+ struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
+ LLVMValueRef length_minus_one;
+
+ length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one);
+
+ switch(wrap_mode) {
+ case PIPE_TEX_WRAP_REPEAT:
+ if(is_pot)
+ coord = LLVMBuildAnd(bld->builder, coord, length_minus_one, "");
+ else
+ /* Signed remainder won't give the right results for negative
+ * dividends but unsigned remainder does.*/
+ coord = LLVMBuildURem(bld->builder, coord, length, "");
+ break;
+
+ case PIPE_TEX_WRAP_CLAMP:
+ coord = lp_build_max(int_coord_bld, coord, int_coord_bld->zero);
+ coord = lp_build_min(int_coord_bld, coord, length_minus_one);
+ break;
+
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ /* FIXME */
+ default:
+ assert(0);
+ }
+
+ return coord;
+}
+
+
+static void
+lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
+ LLVMValueRef s,
+ LLVMValueRef t,
+ LLVMValueRef width,
+ LLVMValueRef height,
+ LLVMValueRef stride,
+ LLVMValueRef data_ptr,
+ LLVMValueRef *texel)
+{
+ LLVMValueRef x;
+ LLVMValueRef y;
+
+ x = lp_build_ifloor(&bld->coord_bld, s);
+ y = lp_build_ifloor(&bld->coord_bld, t);
+
+ x = lp_build_sample_wrap(bld, x, width, bld->static_state->pot_width, bld->static_state->wrap_s);
+ y = lp_build_sample_wrap(bld, y, height, bld->static_state->pot_height, bld->static_state->wrap_t);
+
+ lp_build_sample_texel(bld, x, y, stride, data_ptr, texel);
+}
+
+
+static void
+lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
+ LLVMValueRef s,
+ LLVMValueRef t,
+ LLVMValueRef width,
+ LLVMValueRef height,
+ LLVMValueRef stride,
+ LLVMValueRef data_ptr,
+ LLVMValueRef *texel)
+{
+ LLVMValueRef half;
+ LLVMValueRef s_ipart;
+ LLVMValueRef t_ipart;
+ LLVMValueRef s_fpart;
+ LLVMValueRef t_fpart;
+ LLVMValueRef x0, x1;
+ LLVMValueRef y0, y1;
+ LLVMValueRef neighbors[2][2][4];
+ unsigned chan;
+
+ half = lp_build_const_scalar(bld->coord_type, 0.5);
+ s = lp_build_sub(&bld->coord_bld, s, half);
+ t = lp_build_sub(&bld->coord_bld, t, half);
+
+ s_ipart = lp_build_floor(&bld->coord_bld, s);
+ t_ipart = lp_build_floor(&bld->coord_bld, t);
+
+ s_fpart = lp_build_sub(&bld->coord_bld, s, s_ipart);
+ t_fpart = lp_build_sub(&bld->coord_bld, t, t_ipart);
+
+ x0 = lp_build_int(&bld->coord_bld, s_ipart);
+ y0 = lp_build_int(&bld->coord_bld, t_ipart);
+
+ x0 = lp_build_sample_wrap(bld, x0, width, bld->static_state->pot_width, bld->static_state->wrap_s);
+ y0 = lp_build_sample_wrap(bld, y0, height, bld->static_state->pot_height, bld->static_state->wrap_t);
+
+ x1 = lp_build_add(&bld->int_coord_bld, x0, bld->int_coord_bld.one);
+ y1 = lp_build_add(&bld->int_coord_bld, y0, bld->int_coord_bld.one);
+
+ x1 = lp_build_sample_wrap(bld, x1, width, bld->static_state->pot_width, bld->static_state->wrap_s);
+ y1 = lp_build_sample_wrap(bld, y1, height, bld->static_state->pot_height, bld->static_state->wrap_t);
+
+ lp_build_sample_texel(bld, x0, y0, stride, data_ptr, neighbors[0][0]);
+ lp_build_sample_texel(bld, x1, y0, stride, data_ptr, neighbors[0][1]);
+ lp_build_sample_texel(bld, x0, y1, stride, data_ptr, neighbors[1][0]);
+ lp_build_sample_texel(bld, x1, y1, stride, data_ptr, neighbors[1][1]);
+
+ /* TODO: Don't interpolate missing channels */
+ for(chan = 0; chan < 4; ++chan) {
+ texel[chan] = lp_build_lerp_2d(&bld->texel_bld,
+ s_fpart, t_fpart,
+ neighbors[0][0][chan],
+ neighbors[0][1][chan],
+ neighbors[1][0][chan],
+ neighbors[1][1][chan]);
+ }
+}
+
+
+static void
+lp_build_sample_compare(struct lp_build_sample_context *bld,
+ LLVMValueRef p,
+ LLVMValueRef *texel)
+{
+ struct lp_build_context *texel_bld = &bld->texel_bld;
+ LLVMValueRef res;
+ unsigned chan;
+
+ if(!bld->static_state->compare_mode)
+ return;
+
+ /* TODO: Compare before swizzling, to avoid redundant computations */
+ res = NULL;
+ for(chan = 0; chan < 4; ++chan) {
+ LLVMValueRef cmp;
+ cmp = lp_build_cmp(texel_bld, bld->static_state->compare_func, p, texel[chan]);
+ cmp = lp_build_select(texel_bld, cmp, texel_bld->one, texel_bld->zero);
+
+ if(res)
+ res = lp_build_add(texel_bld, res, cmp);
+ else
+ res = cmp;
+ }
+
+ assert(res);
+ res = lp_build_mul(texel_bld, res, lp_build_const_scalar(texel_bld->type, 0.25));
+
+ /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
+ for(chan = 0; chan < 3; ++chan)
+ texel[chan] = res;
+ texel[3] = texel_bld->one;
+}
+
+
+void
+lp_build_sample_soa(LLVMBuilderRef builder,
+ const struct lp_sampler_static_state *static_state,
+ struct lp_sampler_dynamic_state *dynamic_state,
+ union lp_type type,
+ unsigned unit,
+ unsigned num_coords,
+ const LLVMValueRef *coords,
+ LLVMValueRef lodbias,
+ LLVMValueRef *texel)
+{
+ struct lp_build_sample_context bld;
+ LLVMValueRef width;
+ LLVMValueRef height;
+ LLVMValueRef stride;
+ LLVMValueRef data_ptr;
+ LLVMValueRef s;
+ LLVMValueRef t;
+ LLVMValueRef p;
+
+ /* Setup our build context */
+ memset(&bld, 0, sizeof bld);
+ bld.builder = builder;
+ bld.static_state = static_state;
+ bld.dynamic_state = dynamic_state;
+ bld.format_desc = util_format_description(static_state->format);
+ bld.coord_type = type;
+ bld.int_coord_type = lp_int_type(type);
+ bld.texel_type = type;
+ lp_build_context_init(&bld.coord_bld, builder, bld.coord_type);
+ lp_build_context_init(&bld.int_coord_bld, builder, bld.int_coord_type);
+ lp_build_context_init(&bld.texel_bld, builder, bld.texel_type);
+
+ /* Get the dynamic state */
+ width = dynamic_state->width(dynamic_state, builder, unit);
+ height = dynamic_state->height(dynamic_state, builder, unit);
+ stride = dynamic_state->stride(dynamic_state, builder, unit);
+ data_ptr = dynamic_state->data_ptr(dynamic_state, builder, unit);
+
+ s = coords[0];
+ t = coords[1];
+ p = coords[2];
+
+ width = lp_build_broadcast_scalar(&bld.int_coord_bld, width);
+ height = lp_build_broadcast_scalar(&bld.int_coord_bld, height);
+ stride = lp_build_broadcast_scalar(&bld.int_coord_bld, stride);
+
+ if(static_state->target == PIPE_TEXTURE_1D)
+ t = bld.coord_bld.zero;
+
+ if(static_state->normalized_coords) {
+ LLVMTypeRef coord_vec_type = lp_build_vec_type(bld.coord_type);
+ LLVMValueRef fp_width = LLVMBuildSIToFP(builder, width, coord_vec_type, "");
+ LLVMValueRef fp_height = LLVMBuildSIToFP(builder, height, coord_vec_type, "");
+ s = lp_build_mul(&bld.coord_bld, s, fp_width);
+ t = lp_build_mul(&bld.coord_bld, t, fp_height);
+ }
+
+ switch (static_state->min_img_filter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ lp_build_sample_2d_nearest_soa(&bld, s, t, width, height, stride, data_ptr, texel);
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ case PIPE_TEX_FILTER_ANISO:
+ lp_build_sample_2d_linear_soa(&bld, s, t, width, height, stride, data_ptr, texel);
+ break;
+ default:
+ assert(0);
+ }
+
+ /* FIXME: respect static_state->min_mip_filter */;
+ /* FIXME: respect static_state->mag_img_filter */;
+ /* FIXME: respect static_state->prefilter */;
+
+ lp_build_sample_compare(&bld, p, texel);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_struct.c b/src/gallium/drivers/llvmpipe/lp_bld_struct.c
new file mode 100644
index 0000000000..3998ac374f
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_struct.c
@@ -0,0 +1,72 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Helper functions for manipulation structures.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+
+#include "lp_bld_debug.h"
+#include "lp_bld_struct.h"
+
+
+LLVMValueRef
+lp_build_struct_get_ptr(LLVMBuilderRef builder,
+ LLVMValueRef ptr,
+ unsigned member,
+ const char *name)
+{
+ LLVMValueRef indices[2];
+ LLVMValueRef member_ptr;
+ indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
+ indices[1] = LLVMConstInt(LLVMInt32Type(), member, 0);
+ member_ptr = LLVMBuildGEP(builder, ptr, indices, Elements(indices), "");
+ lp_build_name(member_ptr, "%s.%s_ptr", LLVMGetValueName(ptr), name);
+ return member_ptr;
+}
+
+
+LLVMValueRef
+lp_build_struct_get(LLVMBuilderRef builder,
+ LLVMValueRef ptr,
+ unsigned member,
+ const char *name)
+{
+ LLVMValueRef member_ptr;
+ LLVMValueRef res;
+ member_ptr = lp_build_struct_get_ptr(builder, ptr, member, name);
+ res = LLVMBuildLoad(builder, member_ptr, "");
+ lp_build_name(res, "%s.%s", LLVMGetValueName(ptr), name);
+ return res;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_struct.h b/src/gallium/drivers/llvmpipe/lp_bld_struct.h
new file mode 100644
index 0000000000..740392f561
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_struct.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Helper functions for type conversions.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifndef LP_BLD_STRUCT_H
+#define LP_BLD_STRUCT_H
+
+
+#include <llvm-c/Core.h>
+#include <llvm-c/Target.h>
+
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+
+
+#define LP_CHECK_STRUCT_SIZE(_ctype, _ltarget, _ltype) \
+ assert(LLVMABISizeOfType(_ltarget, _ltype) == \
+ sizeof(_ctype))
+
+#define LP_CHECK_MEMBER_OFFSET(_ctype, _cmember, _ltarget, _ltype, _lindex) \
+ assert(LLVMOffsetOfElement(_ltarget, _ltype, _lindex) == \
+ offsetof(_ctype, _cmember))
+
+
+/**
+ * Get value pointer to a structure member.
+ */
+LLVMValueRef
+lp_build_struct_get_ptr(LLVMBuilderRef builder,
+ LLVMValueRef ptr,
+ unsigned member,
+ const char *name);
+
+/**
+ * Get the value of a structure member.
+ */
+LLVMValueRef
+lp_build_struct_get(LLVMBuilderRef builder,
+ LLVMValueRef ptr,
+ unsigned member,
+ const char *name);
+
+
+#endif /* !LP_BLD_STRUCT_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_swizzle.c b/src/gallium/drivers/llvmpipe/lp_bld_swizzle.c
new file mode 100644
index 0000000000..ac7eed9379
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_swizzle.c
@@ -0,0 +1,238 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Helper functions for swizzling/shuffling.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "util/u_debug.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_logic.h"
+#include "lp_bld_swizzle.h"
+
+
+LLVMValueRef
+lp_build_broadcast(LLVMBuilderRef builder,
+ LLVMTypeRef vec_type,
+ LLVMValueRef scalar)
+{
+ const unsigned n = LLVMGetVectorSize(vec_type);
+ LLVMValueRef res;
+ unsigned i;
+
+ res = LLVMGetUndef(vec_type);
+ for(i = 0; i < n; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ res = LLVMBuildInsertElement(builder, res, scalar, index, "");
+ }
+
+ return res;
+}
+
+
+LLVMValueRef
+lp_build_broadcast_scalar(struct lp_build_context *bld,
+ LLVMValueRef scalar)
+{
+ const union lp_type type = bld->type;
+ LLVMValueRef res;
+ unsigned i;
+
+ res = bld->undef;
+ for(i = 0; i < type.length; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ res = LLVMBuildInsertElement(bld->builder, res, scalar, index, "");
+ }
+
+ return res;
+}
+
+
+LLVMValueRef
+lp_build_broadcast_aos(struct lp_build_context *bld,
+ LLVMValueRef a,
+ unsigned channel)
+{
+ const union lp_type type = bld->type;
+ const unsigned n = type.length;
+ unsigned i, j;
+
+ if(a == bld->undef || a == bld->zero || a == bld->one)
+ return a;
+
+ /* XXX: SSE3 has PSHUFB which should be better than bitmasks, but forcing
+ * using shuffles here actually causes worst results. More investigation is
+ * needed. */
+ if (n <= 4) {
+ /*
+ * Shuffle.
+ */
+ LLVMTypeRef elem_type = LLVMInt32Type();
+ LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
+
+ for(j = 0; j < n; j += 4)
+ for(i = 0; i < 4; ++i)
+ shuffles[j + i] = LLVMConstInt(elem_type, j + channel, 0);
+
+ return LLVMBuildShuffleVector(bld->builder, a, bld->undef, LLVMConstVector(shuffles, n), "");
+ }
+ else {
+ /*
+ * Bit mask and recursive shifts
+ *
+ * XYZW XYZW .... XYZW <= input
+ * 0Y00 0Y00 .... 0Y00
+ * YY00 YY00 .... YY00
+ * YYYY YYYY .... YYYY <= output
+ */
+ union lp_type type4 = type;
+ const char shifts[4][2] = {
+ { 1, 2},
+ {-1, 2},
+ { 1, -2},
+ {-1, -2}
+ };
+ boolean cond[4];
+ unsigned i;
+
+ memset(cond, 0, sizeof cond);
+ cond[channel] = 1;
+
+ a = LLVMBuildAnd(bld->builder, a, lp_build_const_mask_aos(type, cond), "");
+
+ type4.width *= 4;
+ type4.length /= 4;
+
+ a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(type4), "");
+
+ for(i = 0; i < 2; ++i) {
+ LLVMValueRef tmp = NULL;
+ int shift = shifts[channel][i];
+
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
+ shift = -shift;
+#endif
+
+ if(shift > 0)
+ tmp = LLVMBuildLShr(bld->builder, a, lp_build_int_const_scalar(type4, shift*type.width), "");
+ if(shift < 0)
+ tmp = LLVMBuildShl(bld->builder, a, lp_build_int_const_scalar(type4, -shift*type.width), "");
+
+ assert(tmp);
+ if(tmp)
+ a = LLVMBuildOr(bld->builder, a, tmp, "");
+ }
+
+ return LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(type), "");
+ }
+}
+
+
+LLVMValueRef
+lp_build_swizzle1_aos(struct lp_build_context *bld,
+ LLVMValueRef a,
+ unsigned char swizzle[4])
+{
+ const unsigned n = bld->type.length;
+ unsigned i, j;
+
+ if(a == bld->undef || a == bld->zero || a == bld->one)
+ return a;
+
+ if(swizzle[0] == swizzle[1] && swizzle[1] == swizzle[2] && swizzle[2] == swizzle[3])
+ return lp_build_broadcast_aos(bld, a, swizzle[0]);
+
+ {
+ /*
+ * Shuffle.
+ */
+ LLVMTypeRef elem_type = LLVMInt32Type();
+ LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
+
+ for(j = 0; j < n; j += 4)
+ for(i = 0; i < 4; ++i)
+ shuffles[j + i] = LLVMConstInt(elem_type, j + swizzle[i], 0);
+
+ return LLVMBuildShuffleVector(bld->builder, a, bld->undef, LLVMConstVector(shuffles, n), "");
+ }
+}
+
+
+LLVMValueRef
+lp_build_swizzle2_aos(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b,
+ unsigned char swizzle[4])
+{
+ const unsigned n = bld->type.length;
+ unsigned i, j;
+
+ if(swizzle[0] < 4 && swizzle[1] < 4 && swizzle[2] < 4 && swizzle[3] < 4)
+ return lp_build_swizzle1_aos(bld, a, swizzle);
+
+ if(a == b) {
+ swizzle[0] %= 4;
+ swizzle[1] %= 4;
+ swizzle[2] %= 4;
+ swizzle[3] %= 4;
+ return lp_build_swizzle1_aos(bld, a, swizzle);
+ }
+
+ if(swizzle[0] % 4 == 0 &&
+ swizzle[1] % 4 == 1 &&
+ swizzle[2] % 4 == 2 &&
+ swizzle[3] % 4 == 3) {
+ boolean cond[4];
+ cond[0] = swizzle[0] / 4;
+ cond[1] = swizzle[1] / 4;
+ cond[2] = swizzle[2] / 4;
+ cond[3] = swizzle[3] / 4;
+ return lp_build_select_aos(bld, a, b, cond);
+ }
+
+ {
+ /*
+ * Shuffle.
+ */
+ LLVMTypeRef elem_type = LLVMInt32Type();
+ LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
+
+ for(j = 0; j < n; j += 4)
+ for(i = 0; i < 4; ++i)
+ shuffles[j + i] = LLVMConstInt(elem_type, j + (swizzle[i] % 4) + (swizzle[i] / 4 * n), 0);
+
+ return LLVMBuildShuffleVector(bld->builder, a, b, LLVMConstVector(shuffles, n), "");
+ }
+}
+
+
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_swizzle.h b/src/gallium/drivers/llvmpipe/lp_bld_swizzle.h
new file mode 100644
index 0000000000..d7dd6a8a60
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_swizzle.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Helper functions for swizzling/shuffling.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifndef LP_BLD_SWIZZLE_H
+#define LP_BLD_SWIZZLE_H
+
+
+#include <llvm-c/Core.h>
+
+
+union lp_type type;
+struct lp_build_context;
+
+
+LLVMValueRef
+lp_build_broadcast(LLVMBuilderRef builder,
+ LLVMTypeRef vec_type,
+ LLVMValueRef scalar);
+
+
+LLVMValueRef
+lp_build_broadcast_scalar(struct lp_build_context *bld,
+ LLVMValueRef scalar);
+
+
+/**
+ * Broadcast one channel of a vector composed of arrays of XYZW structures into
+ * all four channel.
+ */
+LLVMValueRef
+lp_build_broadcast_aos(struct lp_build_context *bld,
+ LLVMValueRef a,
+ unsigned channel);
+
+
+/**
+ * Swizzle a vector consisting of an array of XYZW structs.
+ *
+ * @param swizzle is the in [0,4[ range.
+ */
+LLVMValueRef
+lp_build_swizzle1_aos(struct lp_build_context *bld,
+ LLVMValueRef a,
+ unsigned char swizzle[4]);
+
+
+/**
+ * Swizzle two vector consisting of an array of XYZW structs.
+ *
+ * @param swizzle is the in [0,8[ range. Values in [4,8[ range refer to b.
+ */
+LLVMValueRef
+lp_build_swizzle2_aos(struct lp_build_context *bld,
+ LLVMValueRef a,
+ LLVMValueRef b,
+ unsigned char swizzle[4]);
+
+
+#endif /* !LP_BLD_SWIZZLE_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h b/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h
new file mode 100644
index 0000000000..10c251c416
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * TGSI to LLVM IR translation.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef LP_BLD_TGSI_H
+#define LP_BLD_TGSI_H
+
+#include <llvm-c/Core.h>
+
+
+struct tgsi_token;
+union lp_type;
+struct lp_build_context;
+struct lp_build_mask_context;
+
+
+/**
+ * Sampler code generation interface.
+ *
+ * Although texture sampling is a requirement for TGSI translation, it is
+ * a very different problem with several different approaches to it. This
+ * structure establishes an interface for texture sampling code generation, so
+ * that we can easily use different texture sampling strategies.
+ */
+struct lp_build_sampler_soa
+{
+ void
+ (*destroy)( struct lp_build_sampler_soa *sampler );
+
+ void
+ (*emit_fetch_texel)( struct lp_build_sampler_soa *sampler,
+ LLVMBuilderRef builder,
+ union lp_type type,
+ unsigned unit,
+ unsigned num_coords,
+ const LLVMValueRef *coords,
+ LLVMValueRef lodbias,
+ LLVMValueRef *texel);
+};
+
+
+void
+lp_build_tgsi_soa(LLVMBuilderRef builder,
+ const struct tgsi_token *tokens,
+ union lp_type type,
+ struct lp_build_mask_context *mask,
+ LLVMValueRef consts_ptr,
+ const LLVMValueRef *pos,
+ const LLVMValueRef (*inputs)[4],
+ LLVMValueRef (*outputs)[4],
+ struct lp_build_sampler_soa *sampler);
+
+
+#endif /* LP_BLD_TGSI_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c
new file mode 100644
index 0000000000..4756811dc3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c
@@ -0,0 +1,1339 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * TGSI to LLVM IR translation -- SoA.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ *
+ * Based on tgsi_sse2.c code written by Michal Krol, Keith Whitwell,
+ * Brian Paul, and others.
+ */
+
+#include "pipe/p_config.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_debug.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_info.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_exec.h"
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_intr.h"
+#include "lp_bld_arit.h"
+#include "lp_bld_logic.h"
+#include "lp_bld_swizzle.h"
+#include "lp_bld_flow.h"
+#include "lp_bld_tgsi.h"
+#include "lp_bld_debug.h"
+
+
+#define LP_MAX_TEMPS 256
+#define LP_MAX_IMMEDIATES 256
+
+
+#define FOR_EACH_CHANNEL( CHAN )\
+ for (CHAN = 0; CHAN < NUM_CHANNELS; CHAN++)
+
+#define IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
+ ((INST)->FullDstRegisters[0].DstRegister.WriteMask & (1 << (CHAN)))
+
+#define IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
+ if (IS_DST0_CHANNEL_ENABLED( INST, CHAN ))
+
+#define FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\
+ FOR_EACH_CHANNEL( CHAN )\
+ IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )
+
+#define CHAN_X 0
+#define CHAN_Y 1
+#define CHAN_Z 2
+#define CHAN_W 3
+
+
+struct lp_build_tgsi_soa_context
+{
+ struct lp_build_context base;
+
+ LLVMValueRef consts_ptr;
+ const LLVMValueRef *pos;
+ const LLVMValueRef (*inputs)[NUM_CHANNELS];
+ LLVMValueRef (*outputs)[NUM_CHANNELS];
+
+ struct lp_build_sampler_soa *sampler;
+
+ LLVMValueRef immediates[LP_MAX_IMMEDIATES][NUM_CHANNELS];
+ LLVMValueRef temps[LP_MAX_TEMPS][NUM_CHANNELS];
+
+ struct lp_build_mask_context *mask;
+};
+
+
+/**
+ * Register fetch.
+ */
+static LLVMValueRef
+emit_fetch(
+ struct lp_build_tgsi_soa_context *bld,
+ const struct tgsi_full_instruction *inst,
+ unsigned index,
+ const unsigned chan_index )
+{
+ const struct tgsi_full_src_register *reg = &inst->FullSrcRegisters[index];
+ unsigned swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index );
+ LLVMValueRef res;
+
+ switch (swizzle) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+
+ switch (reg->SrcRegister.File) {
+ case TGSI_FILE_CONSTANT: {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), reg->SrcRegister.Index*4 + swizzle, 0);
+ LLVMValueRef scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr, &index, 1, "");
+ LLVMValueRef scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
+ res = lp_build_broadcast_scalar(&bld->base, scalar);
+ break;
+ }
+
+ case TGSI_FILE_IMMEDIATE:
+ res = bld->immediates[reg->SrcRegister.Index][swizzle];
+ assert(res);
+ break;
+
+ case TGSI_FILE_INPUT:
+ res = bld->inputs[reg->SrcRegister.Index][swizzle];
+ assert(res);
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ res = bld->temps[reg->SrcRegister.Index][swizzle];
+ if(!res)
+ return bld->base.undef;
+ break;
+
+ default:
+ assert( 0 );
+ return bld->base.undef;
+ }
+ break;
+
+ case TGSI_EXTSWIZZLE_ZERO:
+ res = bld->base.zero;
+ break;
+
+ case TGSI_EXTSWIZZLE_ONE:
+ res = bld->base.one;
+ break;
+
+ default:
+ assert( 0 );
+ return bld->base.undef;
+ }
+
+ switch( tgsi_util_get_full_src_register_sign_mode( reg, chan_index ) ) {
+ case TGSI_UTIL_SIGN_CLEAR:
+ res = lp_build_abs( &bld->base, res );
+ break;
+
+ case TGSI_UTIL_SIGN_SET:
+ /* TODO: Use bitwese OR for floating point */
+ res = lp_build_abs( &bld->base, res );
+ res = LLVMBuildNeg( bld->base.builder, res, "" );
+ break;
+
+ case TGSI_UTIL_SIGN_TOGGLE:
+ res = LLVMBuildNeg( bld->base.builder, res, "" );
+ break;
+
+ case TGSI_UTIL_SIGN_KEEP:
+ break;
+ }
+
+ return res;
+}
+
+
+/**
+ * Register store.
+ */
+static void
+emit_store(
+ struct lp_build_tgsi_soa_context *bld,
+ const struct tgsi_full_instruction *inst,
+ unsigned index,
+ unsigned chan_index,
+ LLVMValueRef value)
+{
+ const struct tgsi_full_dst_register *reg = &inst->FullDstRegisters[index];
+
+ switch( inst->Instruction.Saturate ) {
+ case TGSI_SAT_NONE:
+ break;
+
+ case TGSI_SAT_ZERO_ONE:
+ value = lp_build_max(&bld->base, value, bld->base.zero);
+ value = lp_build_min(&bld->base, value, bld->base.one);
+ break;
+
+ case TGSI_SAT_MINUS_PLUS_ONE:
+ value = lp_build_max(&bld->base, value, lp_build_const_scalar(bld->base.type, -1.0));
+ value = lp_build_min(&bld->base, value, bld->base.one);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ switch( reg->DstRegister.File ) {
+ case TGSI_FILE_OUTPUT:
+ bld->outputs[reg->DstRegister.Index][chan_index] = value;
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ bld->temps[reg->DstRegister.Index][chan_index] = value;
+ break;
+
+ case TGSI_FILE_ADDRESS:
+ /* FIXME */
+ assert(0);
+ break;
+
+ default:
+ assert( 0 );
+ }
+}
+
+
+/**
+ * High-level instruction translators.
+ */
+
+static void
+emit_tex( struct lp_build_tgsi_soa_context *bld,
+ const struct tgsi_full_instruction *inst,
+ boolean apply_lodbias,
+ boolean projected)
+{
+ const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
+ LLVMValueRef lodbias;
+ LLVMValueRef oow;
+ LLVMValueRef coords[3];
+ LLVMValueRef texel[4];
+ unsigned num_coords;
+ unsigned i;
+
+ switch (inst->InstructionExtTexture.Texture) {
+ case TGSI_TEXTURE_1D:
+ num_coords = 1;
+ break;
+ case TGSI_TEXTURE_2D:
+ case TGSI_TEXTURE_RECT:
+ num_coords = 2;
+ break;
+ case TGSI_TEXTURE_SHADOW1D:
+ case TGSI_TEXTURE_SHADOW2D:
+ case TGSI_TEXTURE_SHADOWRECT:
+ case TGSI_TEXTURE_3D:
+ case TGSI_TEXTURE_CUBE:
+ num_coords = 3;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ if(apply_lodbias)
+ lodbias = emit_fetch( bld, inst, 0, 3 );
+ else
+ lodbias = bld->base.zero;
+
+ if (projected) {
+ oow = emit_fetch( bld, inst, 0, 3 );
+ oow = lp_build_rcp(&bld->base, oow);
+ }
+
+ for (i = 0; i < num_coords; i++) {
+ coords[i] = emit_fetch( bld, inst, 0, i );
+ if (projected)
+ coords[i] = lp_build_mul(&bld->base, coords[i], oow);
+ }
+
+ bld->sampler->emit_fetch_texel(bld->sampler,
+ bld->base.builder,
+ bld->base.type,
+ unit, num_coords, coords, lodbias,
+ texel);
+
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, i ) {
+ emit_store( bld, inst, 0, i, texel[i] );
+ }
+}
+
+
+static void
+emit_kil(
+ struct lp_build_tgsi_soa_context *bld,
+ const struct tgsi_full_instruction *inst )
+{
+ const struct tgsi_full_src_register *reg = &inst->FullSrcRegisters[0];
+ LLVMValueRef terms[NUM_CHANNELS];
+ LLVMValueRef mask;
+ unsigned chan_index;
+
+ memset(&terms, 0, sizeof terms);
+
+ FOR_EACH_CHANNEL( chan_index ) {
+ unsigned swizzle;
+
+ /* Unswizzle channel */
+ swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index );
+
+ /* Note that we test if the value is less than zero, so 1.0 and 0.0 need
+ * not to be tested. */
+ if(swizzle == TGSI_EXTSWIZZLE_ZERO || swizzle == TGSI_EXTSWIZZLE_ONE)
+ continue;
+
+ /* Check if the component has not been already tested. */
+ assert(swizzle < NUM_CHANNELS);
+ if( !terms[swizzle] )
+ /* TODO: change the comparison operator instead of setting the sign */
+ terms[swizzle] = emit_fetch(bld, inst, 0, chan_index );
+ }
+
+ mask = NULL;
+ FOR_EACH_CHANNEL( chan_index ) {
+ if(terms[chan_index]) {
+ LLVMValueRef chan_mask;
+
+ chan_mask = lp_build_cmp(&bld->base, PIPE_FUNC_GEQUAL, terms[chan_index], bld->base.zero);
+
+ if(mask)
+ mask = LLVMBuildAnd(bld->base.builder, mask, chan_mask, "");
+ else
+ mask = chan_mask;
+ }
+ }
+
+ if(mask)
+ lp_build_mask_update(bld->mask, mask);
+}
+
+
+/**
+ * Check if inst src/dest regs use indirect addressing into temporary
+ * register file.
+ */
+static boolean
+indirect_temp_reference(const struct tgsi_full_instruction *inst)
+{
+ uint i;
+ for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *reg = &inst->FullSrcRegisters[i];
+ if (reg->SrcRegister.File == TGSI_FILE_TEMPORARY &&
+ reg->SrcRegister.Indirect)
+ return TRUE;
+ }
+ for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
+ const struct tgsi_full_dst_register *reg = &inst->FullDstRegisters[i];
+ if (reg->DstRegister.File == TGSI_FILE_TEMPORARY &&
+ reg->DstRegister.Indirect)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static int
+emit_instruction(
+ struct lp_build_tgsi_soa_context *bld,
+ struct tgsi_full_instruction *inst )
+{
+ unsigned chan_index;
+ LLVMValueRef src0, src1, src2;
+ LLVMValueRef tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ LLVMValueRef dst0;
+
+ /* we can't handle indirect addressing into temp register file yet */
+ if (indirect_temp_reference(inst))
+ return FALSE;
+
+ switch (inst->Instruction.Opcode) {
+#if 0
+ case TGSI_OPCODE_ARL:
+ /* FIXME */
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ emit_flr(bld, 0, 0);
+ emit_f2it( bld, 0 );
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+#endif
+
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_LIT:
+ if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ) {
+ emit_store( bld, inst, 0, CHAN_X, bld->base.one);
+ }
+ if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ) {
+ src0 = emit_fetch( bld, inst, 0, CHAN_X );
+ dst0 = lp_build_max( &bld->base, src0, bld->base.zero);
+ emit_store( bld, inst, 0, CHAN_Y, dst0);
+ }
+ if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) ) {
+ /* XMM[1] = SrcReg[0].yyyy */
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Y );
+ /* XMM[1] = max(XMM[1], 0) */
+ tmp1 = lp_build_max( &bld->base, tmp1, bld->base.zero);
+ /* XMM[2] = SrcReg[0].wwww */
+ tmp2 = emit_fetch( bld, inst, 0, CHAN_W );
+ tmp1 = lp_build_pow( &bld->base, tmp1, tmp2);
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp2 = lp_build_cmp(&bld->base, PIPE_FUNC_GREATER, tmp0, bld->base.zero);
+ dst0 = lp_build_select(&bld->base, tmp2, tmp1, bld->base.zero);
+ emit_store( bld, inst, 0, CHAN_Z, dst0);
+ }
+ if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) ) {
+ emit_store( bld, inst, 0, CHAN_W, bld->base.one);
+ }
+ break;
+
+ case TGSI_OPCODE_RCP:
+ /* TGSI_OPCODE_RECIP */
+ src0 = emit_fetch( bld, inst, 0, CHAN_X );
+ dst0 = lp_build_rcp(&bld->base, src0);
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, dst0 );
+ }
+ break;
+
+ case TGSI_OPCODE_RSQ:
+ /* TGSI_OPCODE_RECIPSQRT */
+ src0 = emit_fetch( bld, inst, 0, CHAN_X );
+ src0 = lp_build_abs(&bld->base, src0);
+ dst0 = lp_build_rsqrt(&bld->base, src0);
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, dst0 );
+ }
+ break;
+
+ case TGSI_OPCODE_EXP:
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ||
+ IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) {
+ LLVMValueRef *p_exp2_int_part = NULL;
+ LLVMValueRef *p_frac_part = NULL;
+ LLVMValueRef *p_exp2 = NULL;
+
+ src0 = emit_fetch( bld, inst, 0, CHAN_X );
+
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ))
+ p_exp2_int_part = &tmp0;
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ))
+ p_frac_part = &tmp1;
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ))
+ p_exp2 = &tmp2;
+
+ lp_build_exp2_approx(&bld->base, src0, p_exp2_int_part, p_frac_part, p_exp2);
+
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ))
+ emit_store( bld, inst, 0, CHAN_X, tmp0);
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ))
+ emit_store( bld, inst, 0, CHAN_Y, tmp1);
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ))
+ emit_store( bld, inst, 0, CHAN_Z, tmp2);
+ }
+ /* dst.w = 1.0 */
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_W )) {
+ tmp0 = bld->base.one;
+ emit_store( bld, inst, 0, CHAN_W, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_LOG:
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ||
+ IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) {
+ LLVMValueRef *p_floor_log2;
+ LLVMValueRef *p_exp;
+ LLVMValueRef *p_log2;
+
+ src0 = emit_fetch( bld, inst, 0, CHAN_X );
+ src0 = lp_build_abs( &bld->base, src0 );
+
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ))
+ p_floor_log2 = &tmp0;
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ))
+ p_exp = &tmp1;
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ))
+ p_log2 = &tmp2;
+
+ lp_build_log2_approx(&bld->base, src0, p_exp, p_floor_log2, p_log2);
+
+ /* dst.x = floor(lg2(abs(src.x))) */
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ))
+ emit_store( bld, inst, 0, CHAN_X, tmp0);
+ /* dst.y = abs(src)/ex2(floor(lg2(abs(src.x)))) */
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y )) {
+ tmp1 = lp_build_div( &bld->base, src0, tmp1);
+ emit_store( bld, inst, 0, CHAN_Y, tmp1);
+ }
+ /* dst.z = lg2(abs(src.x)) */
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ))
+ emit_store( bld, inst, 0, CHAN_Z, tmp2);
+ }
+ /* dst.w = 1.0 */
+ if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_W )) {
+ tmp0 = bld->base.one;
+ emit_store( bld, inst, 0, CHAN_W, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_MUL:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ dst0 = lp_build_mul(&bld->base, src0, src1);
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_ADD:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ dst0 = lp_build_add(&bld->base, src0, src1);
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_DP3:
+ /* TGSI_OPCODE_DOT3 */
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp1 = emit_fetch( bld, inst, 1, CHAN_X );
+ tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Y );
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_Y );
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Z );
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_Z );
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_DP4:
+ /* TGSI_OPCODE_DOT4 */
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp1 = emit_fetch( bld, inst, 1, CHAN_X );
+ tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Y );
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_Y );
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Z );
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_Z );
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_W );
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_W );
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_DST:
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) {
+ tmp0 = bld->base.one;
+ emit_store( bld, inst, 0, CHAN_X, tmp0);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) {
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_Y );
+ tmp1 = emit_fetch( bld, inst, 1, CHAN_Y );
+ tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
+ emit_store( bld, inst, 0, CHAN_Y, tmp0);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) {
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_Z );
+ emit_store( bld, inst, 0, CHAN_Z, tmp0);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) {
+ tmp0 = emit_fetch( bld, inst, 1, CHAN_W );
+ emit_store( bld, inst, 0, CHAN_W, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_MIN:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ dst0 = lp_build_min( &bld->base, src0, src1 );
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_MAX:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ dst0 = lp_build_max( &bld->base, src0, src1 );
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_SLT:
+ /* TGSI_OPCODE_SETLT */
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_LESS, src0, src1 );
+ dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_SGE:
+ /* TGSI_OPCODE_SETGE */
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GEQUAL, src0, src1 );
+ dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_MAD:
+ /* TGSI_OPCODE_MADD */
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ tmp1 = emit_fetch( bld, inst, 1, chan_index );
+ tmp2 = emit_fetch( bld, inst, 2, chan_index );
+ tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp2);
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_SUB:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ tmp1 = emit_fetch( bld, inst, 1, chan_index );
+ tmp0 = lp_build_sub( &bld->base, tmp0, tmp1);
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_LRP:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ src2 = emit_fetch( bld, inst, 2, chan_index );
+ tmp0 = lp_build_sub( &bld->base, src1, src2 );
+ tmp0 = lp_build_mul( &bld->base, src0, tmp0 );
+ dst0 = lp_build_add( &bld->base, tmp0, src2 );
+ emit_store( bld, inst, 0, chan_index, dst0 );
+ }
+ break;
+
+ case TGSI_OPCODE_CND:
+ /* FIXME */
+ return 0;
+ break;
+
+ case TGSI_OPCODE_DP2A:
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); /* xmm0 = src[0].x */
+ tmp1 = emit_fetch( bld, inst, 1, CHAN_X ); /* xmm1 = src[1].x */
+ tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 * xmm1 */
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); /* xmm1 = src[0].y */
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_Y ); /* xmm2 = src[1].y */
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); /* xmm1 = xmm1 * xmm2 */
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 + xmm1 */
+ tmp1 = emit_fetch( bld, inst, 2, CHAN_X ); /* xmm1 = src[2].x */
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 + xmm1 */
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, tmp0); /* dest[ch] = xmm0 */
+ }
+ break;
+
+#if 0
+ case TGSI_OPCODE_FRC:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ emit_frc( bld, 0, 0 );
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_CLAMP:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_FLR:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ emit_flr( bld, 0, 0 );
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_ROUND:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ emit_rnd( bld, 0, 0 );
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+#endif
+
+ case TGSI_OPCODE_EX2: {
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp0 = lp_build_exp2( &bld->base, tmp0);
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+ }
+
+ case TGSI_OPCODE_LG2:
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp0 = lp_build_log2( &bld->base, tmp0);
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_POW:
+ src0 = emit_fetch( bld, inst, 0, CHAN_X );
+ src1 = emit_fetch( bld, inst, 1, CHAN_X );
+ dst0 = lp_build_pow( &bld->base, src0, src1 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, dst0 );
+ }
+ break;
+
+ case TGSI_OPCODE_XPD:
+ if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ) {
+ tmp1 = emit_fetch( bld, inst, 1, CHAN_Z );
+ tmp3 = emit_fetch( bld, inst, 0, CHAN_Z );
+ }
+ if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ||
+ IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) ) {
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_Y );
+ tmp4 = emit_fetch( bld, inst, 1, CHAN_Y );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) {
+ tmp2 = tmp0;
+ tmp2 = lp_build_mul( &bld->base, tmp2, tmp1);
+ tmp5 = tmp3;
+ tmp5 = lp_build_mul( &bld->base, tmp5, tmp4);
+ tmp2 = lp_build_sub( &bld->base, tmp2, tmp5);
+ emit_store( bld, inst, 0, CHAN_X, tmp2);
+ }
+ if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ||
+ IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) ) {
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_X );
+ tmp5 = emit_fetch( bld, inst, 0, CHAN_X );
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) {
+ tmp3 = lp_build_mul( &bld->base, tmp3, tmp2);
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp5);
+ tmp3 = lp_build_sub( &bld->base, tmp3, tmp1);
+ emit_store( bld, inst, 0, CHAN_Y, tmp3);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) {
+ tmp5 = lp_build_mul( &bld->base, tmp5, tmp4);
+ tmp0 = lp_build_mul( &bld->base, tmp0, tmp2);
+ tmp5 = lp_build_sub( &bld->base, tmp5, tmp0);
+ emit_store( bld, inst, 0, CHAN_Z, tmp5);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) {
+ tmp0 = bld->base.one;
+ emit_store( bld, inst, 0, CHAN_W, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_ABS:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ tmp0 = lp_build_abs( &bld->base, tmp0 ) ;
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_RCC:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_DPH:
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp1 = emit_fetch( bld, inst, 1, CHAN_X );
+ tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Y );
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_Y );
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Z );
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_Z );
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+ tmp1 = emit_fetch( bld, inst, 1, CHAN_W );
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_COS:
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp0 = lp_build_cos( &bld->base, tmp0 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_DDX:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_DDY:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_KILP:
+ /* predicated kill */
+ /* FIXME */
+ return 0;
+ break;
+
+ case TGSI_OPCODE_KIL:
+ /* conditional kill */
+ emit_kil( bld, inst );
+ break;
+
+ case TGSI_OPCODE_PK2H:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_PK2US:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_PK4B:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_PK4UB:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_RFL:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SEQ:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_EQUAL, src0, src1 );
+ dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_SFL:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SGT:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GREATER, src0, src1 );
+ dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_SIN:
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp0 = lp_build_sin( &bld->base, tmp0 );
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_SLE:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_LEQUAL, src0, src1 );
+ dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_SNE:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_NOTEQUAL, src0, src1 );
+ dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_STR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_TEX:
+ emit_tex( bld, inst, FALSE, FALSE );
+ break;
+
+ case TGSI_OPCODE_TXD:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_UP2H:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_UP2US:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_UP4B:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_UP4UB:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_X2D:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ARA:
+ return 0;
+ break;
+
+#if 0
+ case TGSI_OPCODE_ARR:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ emit_rnd( bld, 0, 0 );
+ emit_f2it( bld, 0 );
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+#endif
+
+ case TGSI_OPCODE_BRA:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_CAL:
+ return 0;
+ break;
+
+#if 0
+ case TGSI_OPCODE_RET:
+ emit_ret( bld );
+ break;
+#endif
+
+ case TGSI_OPCODE_END:
+ break;
+
+#if 0
+ case TGSI_OPCODE_SSG:
+ /* TGSI_OPCODE_SGN */
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ emit_sgn( bld, 0, 0 );
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+#endif
+
+ case TGSI_OPCODE_CMP:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ src0 = emit_fetch( bld, inst, 0, chan_index );
+ src1 = emit_fetch( bld, inst, 1, chan_index );
+ src2 = emit_fetch( bld, inst, 2, chan_index );
+ tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_LESS, src0, bld->base.zero );
+ dst0 = lp_build_select( &bld->base, tmp0, src1, src2);
+ emit_store( bld, inst, 0, chan_index, dst0);
+ }
+ break;
+
+ case TGSI_OPCODE_SCS:
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) {
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp0 = lp_build_cos( &bld->base, tmp0 );
+ emit_store( bld, inst, 0, CHAN_X, tmp0);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) {
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
+ tmp0 = lp_build_sin( &bld->base, tmp0 );
+ emit_store( bld, inst, 0, CHAN_Y, tmp0);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) {
+ tmp0 = bld->base.zero;
+ emit_store( bld, inst, 0, CHAN_Z, tmp0);
+ }
+ IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) {
+ tmp0 = bld->base.one;
+ emit_store( bld, inst, 0, CHAN_W, tmp0);
+ }
+ break;
+
+ case TGSI_OPCODE_TXB:
+ emit_tex( bld, inst, TRUE, FALSE );
+ break;
+
+ case TGSI_OPCODE_NRM:
+ /* fall-through */
+ case TGSI_OPCODE_NRM4:
+ /* 3 or 4-component normalization */
+ {
+ uint dims = (inst->Instruction.Opcode == TGSI_OPCODE_NRM) ? 3 : 4;
+
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X) ||
+ IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y) ||
+ IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z) ||
+ (IS_DST0_CHANNEL_ENABLED(inst, CHAN_W) && dims == 4)) {
+
+ /* NOTE: Cannot use xmm regs 2/3 here (see emit_rsqrt() above). */
+
+ /* xmm4 = src.x */
+ /* xmm0 = src.x * src.x */
+ tmp0 = emit_fetch(bld, inst, 0, CHAN_X);
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X)) {
+ tmp4 = tmp0;
+ }
+ tmp0 = lp_build_mul( &bld->base, tmp0, tmp0);
+
+ /* xmm5 = src.y */
+ /* xmm0 = xmm0 + src.y * src.y */
+ tmp1 = emit_fetch(bld, inst, 0, CHAN_Y);
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y)) {
+ tmp5 = tmp1;
+ }
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp1);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+
+ /* xmm6 = src.z */
+ /* xmm0 = xmm0 + src.z * src.z */
+ tmp1 = emit_fetch(bld, inst, 0, CHAN_Z);
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z)) {
+ tmp6 = tmp1;
+ }
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp1);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+
+ if (dims == 4) {
+ /* xmm7 = src.w */
+ /* xmm0 = xmm0 + src.w * src.w */
+ tmp1 = emit_fetch(bld, inst, 0, CHAN_W);
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_W)) {
+ tmp7 = tmp1;
+ }
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp1);
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
+ }
+
+ /* xmm1 = 1 / sqrt(xmm0) */
+ tmp1 = lp_build_rsqrt( &bld->base, tmp0);
+
+ /* dst.x = xmm1 * src.x */
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X)) {
+ tmp4 = lp_build_mul( &bld->base, tmp4, tmp1);
+ emit_store(bld, inst, 0, CHAN_X, tmp4);
+ }
+
+ /* dst.y = xmm1 * src.y */
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y)) {
+ tmp5 = lp_build_mul( &bld->base, tmp5, tmp1);
+ emit_store(bld, inst, 0, CHAN_Y, tmp5);
+ }
+
+ /* dst.z = xmm1 * src.z */
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z)) {
+ tmp6 = lp_build_mul( &bld->base, tmp6, tmp1);
+ emit_store(bld, inst, 0, CHAN_Z, tmp6);
+ }
+
+ /* dst.w = xmm1 * src.w */
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X) && dims == 4) {
+ tmp7 = lp_build_mul( &bld->base, tmp7, tmp1);
+ emit_store(bld, inst, 0, CHAN_W, tmp7);
+ }
+ }
+
+ /* dst0.w = 1.0 */
+ if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_W) && dims == 3) {
+ tmp0 = bld->base.one;
+ emit_store(bld, inst, 0, CHAN_W, tmp0);
+ }
+ }
+ break;
+
+ case TGSI_OPCODE_DIV:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_DP2:
+ tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); /* xmm0 = src[0].x */
+ tmp1 = emit_fetch( bld, inst, 1, CHAN_X ); /* xmm1 = src[1].x */
+ tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 * xmm1 */
+ tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); /* xmm1 = src[0].y */
+ tmp2 = emit_fetch( bld, inst, 1, CHAN_Y ); /* xmm2 = src[1].y */
+ tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); /* xmm1 = xmm1 * xmm2 */
+ tmp0 = lp_build_add( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 + xmm1 */
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ emit_store( bld, inst, 0, chan_index, tmp0); /* dest[ch] = xmm0 */
+ }
+ break;
+
+ case TGSI_OPCODE_TXL:
+ emit_tex( bld, inst, TRUE, FALSE );
+ break;
+
+ case TGSI_OPCODE_TXP:
+ emit_tex( bld, inst, FALSE, TRUE );
+ break;
+
+ case TGSI_OPCODE_BRK:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_IF:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_BGNFOR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_REP:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ELSE:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ENDIF:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ENDFOR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ENDREP:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_PUSHA:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_POPA:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_CEIL:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_I2F:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_NOT:
+ return 0;
+ break;
+
+#if 0
+ case TGSI_OPCODE_TRUNC:
+ FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
+ tmp0 = emit_fetch( bld, inst, 0, chan_index );
+ emit_f2it( bld, 0 );
+ emit_i2f( bld, 0 );
+ emit_store( bld, inst, 0, chan_index, tmp0);
+ }
+ break;
+#endif
+
+ case TGSI_OPCODE_SHL:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SHR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_AND:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_OR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_MOD:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_XOR:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_SAD:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_TXF:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_TXQ:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_CONT:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_EMIT:
+ return 0;
+ break;
+
+ case TGSI_OPCODE_ENDPRIM:
+ return 0;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+
+void
+lp_build_tgsi_soa(LLVMBuilderRef builder,
+ const struct tgsi_token *tokens,
+ union lp_type type,
+ struct lp_build_mask_context *mask,
+ LLVMValueRef consts_ptr,
+ const LLVMValueRef *pos,
+ const LLVMValueRef (*inputs)[NUM_CHANNELS],
+ LLVMValueRef (*outputs)[NUM_CHANNELS],
+ struct lp_build_sampler_soa *sampler)
+{
+ struct lp_build_tgsi_soa_context bld;
+ struct tgsi_parse_context parse;
+ uint num_immediates = 0;
+ unsigned i;
+
+ /* Setup build context */
+ memset(&bld, 0, sizeof bld);
+ lp_build_context_init(&bld.base, builder, type);
+ bld.mask = mask;
+ bld.pos = pos;
+ bld.inputs = inputs;
+ bld.outputs = outputs;
+ bld.consts_ptr = consts_ptr;
+ bld.sampler = sampler;
+
+ tgsi_parse_init( &parse, tokens );
+
+ while( !tgsi_parse_end_of_tokens( &parse ) ) {
+ tgsi_parse_token( &parse );
+
+ switch( parse.FullToken.Token.Type ) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ /* Inputs already interpolated */
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ if (!emit_instruction( &bld, &parse.FullToken.FullInstruction )) {
+ unsigned opcode = parse.FullToken.FullInstruction.Instruction.Opcode;
+ const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode);
+ _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
+ info ? info->mnemonic : "<invalid>");
+ }
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ /* simply copy the immediate values into the next immediates[] slot */
+ {
+ const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
+ assert(size <= 4);
+ assert(num_immediates < LP_MAX_IMMEDIATES);
+ for( i = 0; i < size; ++i )
+ bld.immediates[num_immediates][i] =
+ lp_build_const_scalar(type, parse.FullToken.FullImmediate.u[i].Float);
+ for( i = size; i < 4; ++i )
+ bld.immediates[num_immediates][i] = bld.base.undef;
+ num_immediates++;
+ }
+ break;
+
+ default:
+ assert( 0 );
+ }
+ }
+
+ tgsi_parse_free( &parse );
+}
+
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_type.c b/src/gallium/drivers/llvmpipe/lp_bld_type.c
new file mode 100644
index 0000000000..577644b7ab
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_type.c
@@ -0,0 +1,181 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_debug.h"
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+
+
+LLVMTypeRef
+lp_build_elem_type(union lp_type type)
+{
+ if (type.floating) {
+ switch(type.width) {
+ case 32:
+ return LLVMFloatType();
+ break;
+ case 64:
+ return LLVMDoubleType();
+ break;
+ default:
+ assert(0);
+ return LLVMFloatType();
+ }
+ }
+ else {
+ return LLVMIntType(type.width);
+ }
+}
+
+
+LLVMTypeRef
+lp_build_vec_type(union lp_type type)
+{
+ LLVMTypeRef elem_type = lp_build_elem_type(type);
+ return LLVMVectorType(elem_type, type.length);
+}
+
+
+/**
+ * This function is a mirror of lp_build_elem_type() above.
+ *
+ * XXX: I'm not sure if it wouldn't be easier/efficient to just recreate the
+ * type and check for identity.
+ */
+boolean
+lp_check_elem_type(union lp_type type, LLVMTypeRef elem_type)
+{
+ LLVMTypeKind elem_kind;
+
+ assert(elem_type);
+ if(!elem_type)
+ return FALSE;
+
+ elem_kind = LLVMGetTypeKind(elem_type);
+
+ if (type.floating) {
+ switch(type.width) {
+ case 32:
+ if(elem_kind != LLVMFloatTypeKind)
+ return FALSE;
+ break;
+ case 64:
+ if(elem_kind != LLVMDoubleTypeKind)
+ return FALSE;
+ break;
+ default:
+ assert(0);
+ return FALSE;
+ }
+ }
+ else {
+ if(elem_kind != LLVMIntegerTypeKind)
+ return FALSE;
+
+ if(LLVMGetIntTypeWidth(elem_type) != type.width)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+boolean
+lp_check_vec_type(union lp_type type, LLVMTypeRef vec_type)
+{
+ LLVMTypeRef elem_type;
+
+ assert(vec_type);
+ if(!vec_type)
+ return FALSE;
+
+ if(LLVMGetTypeKind(vec_type) != LLVMVectorTypeKind)
+ return FALSE;
+
+ if(LLVMGetVectorSize(vec_type) != type.length)
+ return FALSE;
+
+ elem_type = LLVMGetElementType(vec_type);
+
+ return lp_check_elem_type(type, elem_type);
+}
+
+
+boolean
+lp_check_value(union lp_type type, LLVMValueRef val)
+{
+ LLVMTypeRef vec_type;
+
+ assert(val);
+ if(!val)
+ return FALSE;
+
+ vec_type = LLVMTypeOf(val);
+
+ return lp_check_vec_type(type, vec_type);
+}
+
+
+LLVMTypeRef
+lp_build_int_elem_type(union lp_type type)
+{
+ return LLVMIntType(type.width);
+}
+
+
+LLVMTypeRef
+lp_build_int_vec_type(union lp_type type)
+{
+ LLVMTypeRef elem_type = lp_build_int_elem_type(type);
+ return LLVMVectorType(elem_type, type.length);
+}
+
+
+union lp_type
+lp_int_type(union lp_type type)
+{
+ union lp_type int_type;
+ int_type.value = 0;
+ int_type.width = type.width;
+ int_type.length = type.length;
+ return int_type;
+}
+
+
+void
+lp_build_context_init(struct lp_build_context *bld,
+ LLVMBuilderRef builder,
+ union lp_type type)
+{
+ bld->builder = builder;
+ bld->type = type;
+ bld->undef = lp_build_undef(type);
+ bld->zero = lp_build_zero(type);
+ bld->one = lp_build_one(type);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_type.h b/src/gallium/drivers/llvmpipe/lp_bld_type.h
new file mode 100644
index 0000000000..9933e0b45c
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_bld_type.h
@@ -0,0 +1,178 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Convenient representation of SIMD types.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifndef LP_BLD_TYPE_H
+#define LP_BLD_TYPE_H
+
+
+#include <llvm-c/Core.h>
+
+#include <pipe/p_compiler.h>
+
+
+/**
+ * Several functions can only cope with vectors of length up to this value.
+ * You may need to increase that value if you want to represent bigger vectors.
+ */
+#define LP_MAX_VECTOR_LENGTH 16
+
+#define LP_MAX_TYPE_WIDTH 64
+
+
+/**
+ * The LLVM type system can't conveniently express all the things we care about
+ * on the types used for intermediate computations, such as signed vs unsigned,
+ * normalized values, or fixed point.
+ */
+union lp_type {
+ struct {
+ /**
+ * Floating-point. Cannot be used with fixed. Integer numbers are
+ * represented by this zero.
+ */
+ unsigned floating:1;
+
+ /**
+ * Fixed-point. Cannot be used with floating. Integer numbers are
+ * represented by this zero.
+ */
+ unsigned fixed:1;
+
+ /**
+ * Whether it can represent negative values or not.
+ *
+ * If this is not set for floating point, it means that all values are
+ * assumed to be positive.
+ */
+ unsigned sign:1;
+
+ /**
+ * Whether values are normalized to fit [0, 1] interval, or [-1, 1]
+ * interval for signed types.
+ *
+ * For integer types it means the representable integer range should be
+ * interpreted as the interval above.
+ *
+ * For floating and fixed point formats it means the values should be
+ * clamped to the interval above.
+ */
+ unsigned norm:1;
+
+ /**
+ * Element width.
+ *
+ * For fixed point values, the fixed point is assumed to be at half the
+ * width.
+ */
+ unsigned width:14;
+
+ /**
+ * Vector length.
+ *
+ * width*length should be a power of two greater or equal to eight.
+ *
+ * @sa LP_MAX_VECTOR_LENGTH
+ */
+ unsigned length:14;
+ };
+ uint32_t value;
+};
+
+
+/**
+ * We need most of the information here in order to correctly and efficiently
+ * translate an arithmetic operation into LLVM IR. Putting it here avoids the
+ * trouble of passing it as parameters.
+ */
+struct lp_build_context
+{
+ LLVMBuilderRef builder;
+
+ /**
+ * This not only describes the input/output LLVM types, but also whether
+ * to normalize/clamp the results.
+ */
+ union lp_type type;
+
+ /** Same as lp_build_undef(type) */
+ LLVMValueRef undef;
+
+ /** Same as lp_build_zero(type) */
+ LLVMValueRef zero;
+
+ /** Same as lp_build_one(type) */
+ LLVMValueRef one;
+};
+
+
+LLVMTypeRef
+lp_build_elem_type(union lp_type type);
+
+
+LLVMTypeRef
+lp_build_vec_type(union lp_type type);
+
+
+boolean
+lp_check_elem_type(union lp_type type, LLVMTypeRef elem_type);
+
+
+boolean
+lp_check_vec_type(union lp_type type, LLVMTypeRef vec_type);
+
+
+boolean
+lp_check_value(union lp_type type, LLVMValueRef val);
+
+
+LLVMTypeRef
+lp_build_int_elem_type(union lp_type type);
+
+
+LLVMTypeRef
+lp_build_int_vec_type(union lp_type type);
+
+
+union lp_type
+lp_int_type(union lp_type type);
+
+
+void
+lp_build_context_init(struct lp_build_context *bld,
+ LLVMBuilderRef builder,
+ union lp_type type);
+
+
+#endif /* !LP_BLD_TYPE_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_buffer.c b/src/gallium/drivers/llvmpipe/lp_buffer.c
new file mode 100644
index 0000000000..66f1f8e138
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_buffer.c
@@ -0,0 +1,150 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "lp_winsys.h"
+#include "lp_screen.h"
+#include "lp_texture.h"
+#include "lp_buffer.h"
+
+
+static void *
+llvmpipe_buffer_map(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned flags)
+{
+ struct llvmpipe_buffer *llvmpipe_buf = llvmpipe_buffer(buf);
+ return llvmpipe_buf->data;
+}
+
+
+static void
+llvmpipe_buffer_unmap(struct pipe_screen *screen,
+ struct pipe_buffer *buf)
+{
+}
+
+
+static void
+llvmpipe_buffer_destroy(struct pipe_buffer *buf)
+{
+ struct llvmpipe_buffer *sbuf = llvmpipe_buffer(buf);
+
+ if (!sbuf->userBuffer)
+ align_free(sbuf->data);
+
+ FREE(sbuf);
+}
+
+
+static struct pipe_buffer *
+llvmpipe_buffer_create(struct pipe_screen *screen,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct llvmpipe_buffer *buffer = CALLOC_STRUCT(llvmpipe_buffer);
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.screen = screen;
+ buffer->base.alignment = MAX2(alignment, 16);
+ buffer->base.usage = usage;
+ buffer->base.size = size;
+
+ buffer->data = align_malloc(size, alignment);
+
+ return &buffer->base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+llvmpipe_user_buffer_create(struct pipe_screen *screen,
+ void *ptr,
+ unsigned bytes)
+{
+ struct llvmpipe_buffer *buffer;
+
+ buffer = CALLOC_STRUCT(llvmpipe_buffer);
+ if(!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.screen = screen;
+ buffer->base.size = bytes;
+ buffer->userBuffer = TRUE;
+ buffer->data = ptr;
+
+ return &buffer->base;
+}
+
+
+static void
+llvmpipe_fence_reference(struct pipe_screen *screen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+}
+
+
+static int
+llvmpipe_fence_signalled(struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+static int
+llvmpipe_fence_finish(struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+void
+llvmpipe_init_screen_buffer_funcs(struct pipe_screen *screen)
+{
+ screen->buffer_create = llvmpipe_buffer_create;
+ screen->user_buffer_create = llvmpipe_user_buffer_create;
+ screen->buffer_map = llvmpipe_buffer_map;
+ screen->buffer_unmap = llvmpipe_buffer_unmap;
+ screen->buffer_destroy = llvmpipe_buffer_destroy;
+
+ screen->fence_reference = llvmpipe_fence_reference;
+ screen->fence_signalled = llvmpipe_fence_signalled;
+ screen->fence_finish = llvmpipe_fence_finish;
+
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_buffer.h b/src/gallium/drivers/llvmpipe/lp_buffer.h
new file mode 100644
index 0000000000..d6b8184a0b
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_buffer.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_BUFFER_H
+#define LP_BUFFER_H
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+
+
+struct llvmpipe_buffer
+{
+ struct pipe_buffer base;
+ boolean userBuffer; /** Is this a user-space buffer? */
+ void *data;
+};
+
+
+/** Cast wrapper */
+static INLINE struct llvmpipe_buffer *
+llvmpipe_buffer( struct pipe_buffer *buf )
+{
+ return (struct llvmpipe_buffer *)buf;
+}
+
+
+void
+llvmpipe_init_screen_buffer_funcs(struct pipe_screen *screen);
+
+
+#endif /* LP_BUFFER_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_clear.c b/src/gallium/drivers/llvmpipe/lp_clear.c
new file mode 100644
index 0000000000..bdcff94b9b
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_clear.c
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Brian Paul
+ * Michel Dänzer
+ */
+
+
+#include "pipe/p_defines.h"
+#include "util/u_pack_color.h"
+#include "lp_clear.h"
+#include "lp_context.h"
+#include "lp_surface.h"
+#include "lp_state.h"
+#include "lp_tile_cache.h"
+
+
+/**
+ * Clear the given buffers to the specified values.
+ * No masking, no scissor (clear entire buffer).
+ */
+void
+llvmpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
+ double depth, unsigned stencil)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+ unsigned cv;
+ uint i;
+
+ if (llvmpipe->no_rast)
+ return;
+
+#if 0
+ llvmpipe_update_derived(llvmpipe); /* not needed?? */
+#endif
+
+ if (buffers & PIPE_CLEAR_COLOR) {
+ for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) {
+ struct pipe_surface *ps = llvmpipe->framebuffer.cbufs[i];
+
+ util_pack_color(rgba, ps->format, &cv);
+ lp_tile_cache_clear(llvmpipe->cbuf_cache[i], rgba, cv);
+ }
+ llvmpipe->dirty_render_cache = TRUE;
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+ struct pipe_surface *ps = llvmpipe->framebuffer.zsbuf;
+
+ cv = util_pack_z_stencil(ps->format, depth, stencil);
+
+ /* non-cached surface */
+ pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv);
+ }
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_clear.h b/src/gallium/drivers/llvmpipe/lp_clear.h
new file mode 100644
index 0000000000..6d4ffccdf4
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_clear.h
@@ -0,0 +1,43 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Brian Paul
+ */
+
+#ifndef LP_CLEAR_H
+#define LP_CLEAR_H
+
+#include "pipe/p_state.h"
+struct pipe_context;
+
+extern void
+llvmpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
+ double depth, unsigned stencil);
+
+
+#endif /* LP_CLEAR_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c
new file mode 100644
index 0000000000..a4b2bd8c2a
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -0,0 +1,295 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2008 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "lp_clear.h"
+#include "lp_context.h"
+#include "lp_flush.h"
+#include "lp_prim_setup.h"
+#include "lp_prim_vbuf.h"
+#include "lp_state.h"
+#include "lp_surface.h"
+#include "lp_tile_cache.h"
+#include "lp_tex_cache.h"
+#include "lp_texture.h"
+#include "lp_winsys.h"
+#include "lp_query.h"
+
+
+
+/**
+ * Map any drawing surfaces which aren't already mapped
+ */
+void
+llvmpipe_map_transfers(struct llvmpipe_context *lp)
+{
+ struct pipe_screen *screen = lp->pipe.screen;
+ struct pipe_surface *zsbuf = lp->framebuffer.zsbuf;
+ unsigned i;
+
+ for (i = 0; i < lp->framebuffer.nr_cbufs; i++) {
+ lp_tile_cache_map_transfers(lp->cbuf_cache[i]);
+ }
+
+ if(zsbuf) {
+ if(!lp->zsbuf_transfer)
+ lp->zsbuf_transfer = screen->get_tex_transfer(screen, zsbuf->texture,
+ zsbuf->face, zsbuf->level, zsbuf->zslice,
+ PIPE_TRANSFER_READ_WRITE,
+ 0, 0, zsbuf->width, zsbuf->height);
+ if(lp->zsbuf_transfer && !lp->zsbuf_map)
+ lp->zsbuf_map = screen->transfer_map(screen, lp->zsbuf_transfer);
+
+ }
+}
+
+
+/**
+ * Unmap any mapped drawing surfaces
+ */
+void
+llvmpipe_unmap_transfers(struct llvmpipe_context *lp)
+{
+ uint i;
+
+ for (i = 0; i < lp->framebuffer.nr_cbufs; i++) {
+ lp_tile_cache_unmap_transfers(lp->cbuf_cache[i]);
+ }
+
+ if(lp->zsbuf_transfer) {
+ struct pipe_screen *screen = lp->pipe.screen;
+
+ if(lp->zsbuf_map) {
+ screen->transfer_unmap(screen, lp->zsbuf_transfer);
+ lp->zsbuf_map = NULL;
+ }
+ }
+}
+
+
+static void llvmpipe_destroy( struct pipe_context *pipe )
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
+ uint i;
+
+ if (llvmpipe->draw)
+ draw_destroy( llvmpipe->draw );
+
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
+ lp_destroy_tile_cache(llvmpipe->cbuf_cache[i]);
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ lp_destroy_tex_tile_cache(llvmpipe->tex_cache[i]);
+
+ for (i = 0; i < Elements(llvmpipe->constants); i++) {
+ if (llvmpipe->constants[i].buffer) {
+ pipe_buffer_reference(&llvmpipe->constants[i].buffer, NULL);
+ }
+ }
+
+ align_free( llvmpipe );
+}
+
+static unsigned int
+llvmpipe_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
+ unsigned i;
+
+ if(llvmpipe->dirty_render_cache) {
+ for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) {
+ if(llvmpipe->framebuffer.cbufs[i] &&
+ llvmpipe->framebuffer.cbufs[i]->texture == texture)
+ return PIPE_REFERENCED_FOR_WRITE;
+ }
+ if(llvmpipe->framebuffer.zsbuf &&
+ llvmpipe->framebuffer.zsbuf->texture == texture)
+ return PIPE_REFERENCED_FOR_WRITE;
+ }
+
+ return PIPE_UNREFERENCED;
+}
+
+static unsigned int
+llvmpipe_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ return PIPE_UNREFERENCED;
+}
+
+struct pipe_context *
+llvmpipe_create( struct pipe_screen *screen )
+{
+ struct llvmpipe_context *llvmpipe;
+ uint i;
+
+ llvmpipe = align_malloc(sizeof(struct llvmpipe_context), 16);
+ if (!llvmpipe)
+ return NULL;
+
+ util_init_math();
+
+ memset(llvmpipe, 0, sizeof *llvmpipe);
+
+ llvmpipe->pipe.winsys = screen->winsys;
+ llvmpipe->pipe.screen = screen;
+ llvmpipe->pipe.destroy = llvmpipe_destroy;
+
+ /* state setters */
+ llvmpipe->pipe.create_blend_state = llvmpipe_create_blend_state;
+ llvmpipe->pipe.bind_blend_state = llvmpipe_bind_blend_state;
+ llvmpipe->pipe.delete_blend_state = llvmpipe_delete_blend_state;
+
+ llvmpipe->pipe.create_sampler_state = llvmpipe_create_sampler_state;
+ llvmpipe->pipe.bind_sampler_states = llvmpipe_bind_sampler_states;
+ llvmpipe->pipe.delete_sampler_state = llvmpipe_delete_sampler_state;
+
+ llvmpipe->pipe.create_depth_stencil_alpha_state = llvmpipe_create_depth_stencil_state;
+ llvmpipe->pipe.bind_depth_stencil_alpha_state = llvmpipe_bind_depth_stencil_state;
+ llvmpipe->pipe.delete_depth_stencil_alpha_state = llvmpipe_delete_depth_stencil_state;
+
+ llvmpipe->pipe.create_rasterizer_state = llvmpipe_create_rasterizer_state;
+ llvmpipe->pipe.bind_rasterizer_state = llvmpipe_bind_rasterizer_state;
+ llvmpipe->pipe.delete_rasterizer_state = llvmpipe_delete_rasterizer_state;
+
+ llvmpipe->pipe.create_fs_state = llvmpipe_create_fs_state;
+ llvmpipe->pipe.bind_fs_state = llvmpipe_bind_fs_state;
+ llvmpipe->pipe.delete_fs_state = llvmpipe_delete_fs_state;
+
+ llvmpipe->pipe.create_vs_state = llvmpipe_create_vs_state;
+ llvmpipe->pipe.bind_vs_state = llvmpipe_bind_vs_state;
+ llvmpipe->pipe.delete_vs_state = llvmpipe_delete_vs_state;
+
+ llvmpipe->pipe.set_blend_color = llvmpipe_set_blend_color;
+ llvmpipe->pipe.set_clip_state = llvmpipe_set_clip_state;
+ llvmpipe->pipe.set_constant_buffer = llvmpipe_set_constant_buffer;
+ llvmpipe->pipe.set_framebuffer_state = llvmpipe_set_framebuffer_state;
+ llvmpipe->pipe.set_polygon_stipple = llvmpipe_set_polygon_stipple;
+ llvmpipe->pipe.set_scissor_state = llvmpipe_set_scissor_state;
+ llvmpipe->pipe.set_sampler_textures = llvmpipe_set_sampler_textures;
+ llvmpipe->pipe.set_viewport_state = llvmpipe_set_viewport_state;
+
+ llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers;
+ llvmpipe->pipe.set_vertex_elements = llvmpipe_set_vertex_elements;
+
+ llvmpipe->pipe.draw_arrays = llvmpipe_draw_arrays;
+ llvmpipe->pipe.draw_elements = llvmpipe_draw_elements;
+ llvmpipe->pipe.draw_range_elements = llvmpipe_draw_range_elements;
+ llvmpipe->pipe.set_edgeflags = llvmpipe_set_edgeflags;
+
+
+ llvmpipe->pipe.clear = llvmpipe_clear;
+ llvmpipe->pipe.flush = llvmpipe_flush;
+
+ llvmpipe->pipe.is_texture_referenced = llvmpipe_is_texture_referenced;
+ llvmpipe->pipe.is_buffer_referenced = llvmpipe_is_buffer_referenced;
+
+ llvmpipe_init_query_funcs( llvmpipe );
+ llvmpipe_init_texture_funcs( llvmpipe );
+
+ /*
+ * Alloc caches for accessing drawing surfaces and textures.
+ */
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
+ llvmpipe->cbuf_cache[i] = lp_create_tile_cache( screen );
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ llvmpipe->tex_cache[i] = lp_create_tex_tile_cache( screen );
+
+
+ /* vertex shader samplers */
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ llvmpipe->tgsi.vert_samplers[i].base.get_samples = lp_get_samples;
+ llvmpipe->tgsi.vert_samplers[i].processor = TGSI_PROCESSOR_VERTEX;
+ llvmpipe->tgsi.vert_samplers[i].cache = llvmpipe->tex_cache[i];
+ llvmpipe->tgsi.vert_samplers_list[i] = &llvmpipe->tgsi.vert_samplers[i];
+ }
+
+ /* fragment shader samplers */
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ llvmpipe->tgsi.frag_samplers[i].base.get_samples = lp_get_samples;
+ llvmpipe->tgsi.frag_samplers[i].processor = TGSI_PROCESSOR_FRAGMENT;
+ llvmpipe->tgsi.frag_samplers[i].cache = llvmpipe->tex_cache[i];
+ llvmpipe->tgsi.frag_samplers_list[i] = &llvmpipe->tgsi.frag_samplers[i];
+ }
+
+ /*
+ * Create drawing context and plug our rendering stage into it.
+ */
+ llvmpipe->draw = draw_create();
+ if (!llvmpipe->draw)
+ goto fail;
+
+ draw_texture_samplers(llvmpipe->draw,
+ PIPE_MAX_SAMPLERS,
+ (struct tgsi_sampler **)
+ llvmpipe->tgsi.vert_samplers_list);
+
+ llvmpipe->setup = lp_draw_render_stage(llvmpipe);
+ if (!llvmpipe->setup)
+ goto fail;
+
+ if (debug_get_bool_option( "LP_NO_RAST", FALSE ))
+ llvmpipe->no_rast = TRUE;
+
+ if (debug_get_bool_option( "LP_NO_VBUF", FALSE )) {
+ /* Deprecated path -- vbuf is the intended interface to the draw module:
+ */
+ draw_set_rasterize_stage(llvmpipe->draw, llvmpipe->setup);
+ }
+ else {
+ lp_init_vbuf(llvmpipe);
+ }
+
+ /* plug in AA line/point stages */
+ draw_install_aaline_stage(llvmpipe->draw, &llvmpipe->pipe);
+ draw_install_aapoint_stage(llvmpipe->draw, &llvmpipe->pipe);
+
+#if USE_DRAW_STAGE_PSTIPPLE
+ /* Do polygon stipple w/ texture map + frag prog? */
+ draw_install_pstipple_stage(llvmpipe->draw, &llvmpipe->pipe);
+#endif
+
+ lp_init_surface_functions(llvmpipe);
+
+ return &llvmpipe->pipe;
+
+ fail:
+ llvmpipe_destroy(&llvmpipe->pipe);
+ return NULL;
+}
+
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
new file mode 100644
index 0000000000..8d5a0d4f1f
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -0,0 +1,155 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef LP_CONTEXT_H
+#define LP_CONTEXT_H
+
+#include "pipe/p_context.h"
+
+#include "draw/draw_vertex.h"
+
+#include "lp_tex_sample.h"
+#include "lp_jit.h"
+
+
+struct llvmpipe_vbuf_render;
+struct draw_context;
+struct draw_stage;
+struct llvmpipe_tile_cache;
+struct llvmpipe_tex_tile_cache;
+struct lp_fragment_shader;
+struct lp_vertex_shader;
+struct lp_blend_state;
+
+
+struct llvmpipe_context {
+ struct pipe_context pipe; /**< base class */
+
+ /** Constant state objects */
+ const struct pipe_blend_state *blend;
+ const struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
+ const struct pipe_depth_stencil_alpha_state *depth_stencil;
+ const struct pipe_rasterizer_state *rasterizer;
+ struct lp_fragment_shader *fs;
+ const struct lp_vertex_shader *vs;
+
+ /** Other rendering state */
+ struct pipe_blend_color blend_color[4][16];
+ struct pipe_clip_state clip;
+ struct pipe_constant_buffer constants[PIPE_SHADER_TYPES];
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_poly_stipple poly_stipple;
+ struct pipe_scissor_state scissor;
+ struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
+ struct pipe_viewport_state viewport;
+ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
+
+ unsigned num_samplers;
+ unsigned num_textures;
+ unsigned num_vertex_elements;
+ unsigned num_vertex_buffers;
+
+ unsigned dirty; /**< Mask of LP_NEW_x flags */
+
+ /* Counter for occlusion queries. Note this supports overlapping
+ * queries.
+ */
+ uint64_t occlusion_count;
+ unsigned active_query_count;
+
+ /** Mapped vertex buffers */
+ ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS];
+
+ /** Mapped constant buffers */
+ void *mapped_constants[PIPE_SHADER_TYPES];
+
+ /** Vertex format */
+ struct vertex_info vertex_info;
+ struct vertex_info vertex_info_vbuf;
+
+ /** Which vertex shader output slot contains point size */
+ int psize_slot;
+
+ /* The reduced version of the primitive supplied by the state
+ * tracker.
+ */
+ unsigned reduced_api_prim;
+
+ /* The reduced primitive after unfilled triangles, wide-line
+ * decomposition, etc, are taken into account. This is the
+ * primitive actually rasterized.
+ */
+ unsigned reduced_prim;
+
+ /** Derived from scissor and surface bounds: */
+ struct pipe_scissor_state cliprect;
+
+ unsigned line_stipple_counter;
+
+ /** TGSI exec things */
+ struct {
+ struct lp_shader_sampler vert_samplers[PIPE_MAX_SAMPLERS];
+ struct lp_shader_sampler *vert_samplers_list[PIPE_MAX_SAMPLERS];
+ struct lp_shader_sampler frag_samplers[PIPE_MAX_SAMPLERS];
+ struct lp_shader_sampler *frag_samplers_list[PIPE_MAX_SAMPLERS];
+ } tgsi;
+
+ /** The primitive drawing context */
+ struct draw_context *draw;
+ struct draw_stage *setup;
+ struct draw_stage *vbuf;
+ struct llvmpipe_vbuf_render *vbuf_render;
+
+ boolean dirty_render_cache;
+
+ struct llvmpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS];
+
+ /* TODO: we shouldn't be using external interfaces internally like this */
+ struct pipe_transfer *zsbuf_transfer;
+ uint8_t *zsbuf_map;
+
+ unsigned tex_timestamp;
+ struct llvmpipe_tex_tile_cache *tex_cache[PIPE_MAX_SAMPLERS];
+
+ unsigned no_rast : 1;
+
+ struct lp_jit_context jit_context;
+};
+
+
+static INLINE struct llvmpipe_context *
+llvmpipe_context( struct pipe_context *pipe )
+{
+ return (struct llvmpipe_context *)pipe;
+}
+
+#endif /* LP_CONTEXT_H */
+
diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
new file mode 100644
index 0000000000..89772e62d3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
@@ -0,0 +1,192 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Brian Paul
+ * Keith Whitwell
+ */
+
+
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_prim.h"
+
+#include "lp_buffer.h"
+#include "lp_context.h"
+#include "lp_state.h"
+
+#include "draw/draw_context.h"
+
+
+
+static void
+llvmpipe_map_constant_buffers(struct llvmpipe_context *lp)
+{
+ struct pipe_screen *screen = lp->pipe.screen;
+ uint i, size;
+
+ for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+ if (lp->constants[i].buffer && lp->constants[i].buffer->size)
+ lp->mapped_constants[i] = screen->buffer_map(screen, lp->constants[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ }
+
+ if (lp->constants[PIPE_SHADER_VERTEX].buffer)
+ size = lp->constants[PIPE_SHADER_VERTEX].buffer->size;
+ else
+ size = 0;
+
+ lp->jit_context.constants = lp->mapped_constants[PIPE_SHADER_FRAGMENT];
+
+ draw_set_mapped_constant_buffer(lp->draw,
+ lp->mapped_constants[PIPE_SHADER_VERTEX],
+ size);
+}
+
+
+static void
+llvmpipe_unmap_constant_buffers(struct llvmpipe_context *lp)
+{
+ struct pipe_screen *screen = lp->pipe.screen;
+ uint i;
+
+ /* really need to flush all prims since the vert/frag shaders const buffers
+ * are going away now.
+ */
+ draw_flush(lp->draw);
+
+ draw_set_mapped_constant_buffer(lp->draw, NULL, 0);
+
+ lp->jit_context.constants = NULL;
+
+ for (i = 0; i < 2; i++) {
+ if (lp->constants[i].buffer && lp->constants[i].buffer->size)
+ screen->buffer_unmap(screen, lp->constants[i].buffer);
+ lp->mapped_constants[i] = NULL;
+ }
+}
+
+
+boolean
+llvmpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
+ unsigned start, unsigned count)
+{
+ return llvmpipe_draw_elements(pipe, NULL, 0, mode, start, count);
+}
+
+
+/**
+ * Draw vertex arrays, with optional indexing.
+ * Basically, map the vertex buffers (and drawing surfaces), then hand off
+ * the drawing to the 'draw' module.
+ */
+boolean
+llvmpipe_draw_range_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned min_index,
+ unsigned max_index,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct llvmpipe_context *lp = llvmpipe_context(pipe);
+ struct draw_context *draw = lp->draw;
+ unsigned i;
+
+ lp->reduced_api_prim = u_reduced_prim(mode);
+
+ if (lp->dirty)
+ llvmpipe_update_derived( lp );
+
+ llvmpipe_map_transfers(lp);
+ llvmpipe_map_constant_buffers(lp);
+
+ /*
+ * Map vertex buffers
+ */
+ for (i = 0; i < lp->num_vertex_buffers; i++) {
+ void *buf = llvmpipe_buffer(lp->vertex_buffer[i].buffer)->data;
+ draw_set_mapped_vertex_buffer(draw, i, buf);
+ }
+
+ /* Map index buffer, if present */
+ if (indexBuffer) {
+ void *mapped_indexes = llvmpipe_buffer(indexBuffer)->data;
+ draw_set_mapped_element_buffer_range(draw, indexSize,
+ min_index,
+ max_index,
+ mapped_indexes);
+ }
+ else {
+ /* no index/element buffer */
+ draw_set_mapped_element_buffer_range(draw, 0, start,
+ start + count - 1, NULL);
+ }
+
+ /* draw! */
+ draw_arrays(draw, mode, start, count);
+
+ /*
+ * unmap vertex/index buffers - will cause draw module to flush
+ */
+ for (i = 0; i < lp->num_vertex_buffers; i++) {
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ }
+ if (indexBuffer) {
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+
+ /* Note: leave drawing surfaces mapped */
+ llvmpipe_unmap_constant_buffers(lp);
+
+ lp->dirty_render_cache = TRUE;
+
+ return TRUE;
+}
+
+
+boolean
+llvmpipe_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+{
+ return llvmpipe_draw_range_elements( pipe, indexBuffer,
+ indexSize,
+ 0, 0xffffffff,
+ mode, start, count );
+}
+
+
+void
+llvmpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags)
+{
+ struct llvmpipe_context *lp = llvmpipe_context(pipe);
+ draw_set_edgeflags(lp->draw, edgeflags);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c
new file mode 100644
index 0000000000..b5c1c95bb7
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_flush.c
@@ -0,0 +1,98 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_defines.h"
+#include "draw/draw_context.h"
+#include "lp_flush.h"
+#include "lp_context.h"
+#include "lp_surface.h"
+#include "lp_state.h"
+#include "lp_tile_cache.h"
+#include "lp_tex_cache.h"
+#include "lp_winsys.h"
+
+
+void
+llvmpipe_flush( struct pipe_context *pipe,
+ unsigned flags,
+ struct pipe_fence_handle **fence )
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+ uint i;
+
+ draw_flush(llvmpipe->draw);
+
+ if (flags & PIPE_FLUSH_SWAPBUFFERS) {
+ /* If this is a swapbuffers, just flush color buffers.
+ *
+ * The zbuffer changes are not discarded, but held in the cache
+ * in the hope that a later clear will wipe them out.
+ */
+ for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++)
+ if (llvmpipe->cbuf_cache[i])
+ lp_flush_tile_cache(llvmpipe->cbuf_cache[i]);
+
+ /* Need this call for hardware buffers before swapbuffers.
+ *
+ * there should probably be another/different flush-type function
+ * that's called before swapbuffers because we don't always want
+ * to unmap surfaces when flushing.
+ */
+ llvmpipe_unmap_transfers(llvmpipe);
+ }
+ else if (flags & PIPE_FLUSH_RENDER_CACHE) {
+ for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++)
+ if (llvmpipe->cbuf_cache[i])
+ lp_flush_tile_cache(llvmpipe->cbuf_cache[i]);
+
+ /* FIXME: untile zsbuf! */
+
+ llvmpipe->dirty_render_cache = FALSE;
+ }
+
+ /* Enable to dump BMPs of the color/depth buffers each frame */
+#if 0
+ if(flags & PIPE_FLUSH_FRAME) {
+ static unsigned frame_no = 1;
+ static char filename[256];
+ util_snprintf(filename, sizeof(filename), "cbuf_%u.bmp", frame_no);
+ debug_dump_surface_bmp(filename, llvmpipe->framebuffer.cbufs[0]);
+ util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no);
+ debug_dump_surface_bmp(filename, llvmpipe->framebuffer.zsbuf);
+ ++frame_no;
+ }
+#endif
+
+ if (fence)
+ *fence = NULL;
+}
+
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.h b/src/gallium/drivers/llvmpipe/lp_flush.h
new file mode 100644
index 0000000000..10b2b52583
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_flush.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_FLUSH_H
+#define LP_FLUSH_H
+
+struct pipe_context;
+struct pipe_fence_handle;
+
+void llvmpipe_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence);
+
+#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c
new file mode 100644
index 0000000000..9465f763d5
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_jit.c
@@ -0,0 +1,173 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * C - JIT interfaces
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include <llvm-c/Transforms/Scalar.h>
+
+#include "util/u_memory.h"
+#include "lp_screen.h"
+#include "lp_bld_intr.h"
+#include "lp_jit.h"
+
+
+static void
+lp_jit_init_globals(struct llvmpipe_screen *screen)
+{
+ LLVMTypeRef texture_type;
+
+ /* struct lp_jit_texture */
+ {
+ LLVMTypeRef elem_types[4];
+
+ elem_types[LP_JIT_TEXTURE_WIDTH] = LLVMInt32Type();
+ elem_types[LP_JIT_TEXTURE_HEIGHT] = LLVMInt32Type();
+ elem_types[LP_JIT_TEXTURE_STRIDE] = LLVMInt32Type();
+ elem_types[LP_JIT_TEXTURE_DATA] = LLVMPointerType(LLVMInt8Type(), 0);
+
+ texture_type = LLVMStructType(elem_types, Elements(elem_types), 0);
+
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, width,
+ screen->target, texture_type,
+ LP_JIT_TEXTURE_WIDTH);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, height,
+ screen->target, texture_type,
+ LP_JIT_TEXTURE_HEIGHT);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, stride,
+ screen->target, texture_type,
+ LP_JIT_TEXTURE_STRIDE);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, data,
+ screen->target, texture_type,
+ LP_JIT_TEXTURE_DATA);
+ LP_CHECK_STRUCT_SIZE(struct lp_jit_texture,
+ screen->target, texture_type);
+
+ LLVMAddTypeName(screen->module, "texture", texture_type);
+ }
+
+ /* struct lp_jit_context */
+ {
+ LLVMTypeRef elem_types[5];
+ LLVMTypeRef context_type;
+
+ elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* constants */
+ elem_types[1] = LLVMPointerType(LLVMInt8Type(), 0); /* samplers */
+ elem_types[2] = LLVMFloatType(); /* alpha_ref_value */
+ elem_types[3] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */
+ elem_types[4] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */
+
+ context_type = LLVMStructType(elem_types, Elements(elem_types), 0);
+
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, constants,
+ screen->target, context_type, 0);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, samplers,
+ screen->target, context_type, 1);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value,
+ screen->target, context_type, 2);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color,
+ screen->target, context_type, 3);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
+ screen->target, context_type,
+ LP_JIT_CONTEXT_TEXTURES_INDEX);
+ LP_CHECK_STRUCT_SIZE(struct lp_jit_context,
+ screen->target, context_type);
+
+ LLVMAddTypeName(screen->module, "context", context_type);
+
+ screen->context_ptr_type = LLVMPointerType(context_type, 0);
+ }
+
+ /* fetch_texel
+ */
+ {
+ LLVMTypeRef ret_type;
+ LLVMTypeRef arg_types[3];
+ LLVMValueRef fetch_texel;
+
+ ret_type = LLVMVoidType();
+ arg_types[0] = LLVMPointerType(LLVMInt8Type(), 0); /* samplers */
+ arg_types[1] = LLVMInt32Type(); /* unit */
+ arg_types[2] = LLVMPointerType(LLVMVectorType(LLVMFloatType(), 4), 0); /* store */
+
+ fetch_texel = lp_declare_intrinsic(screen->module, "fetch_texel",
+ ret_type, arg_types, Elements(arg_types));
+
+ LLVMAddGlobalMapping(screen->engine, fetch_texel, lp_fetch_texel_soa);
+ }
+
+#ifdef DEBUG
+ LLVMDumpModule(screen->module);
+#endif
+}
+
+
+void
+lp_jit_screen_cleanup(struct llvmpipe_screen *screen)
+{
+ if(screen->engine)
+ LLVMDisposeExecutionEngine(screen->engine);
+
+ if(screen->pass)
+ LLVMDisposePassManager(screen->pass);
+}
+
+
+void
+lp_jit_screen_init(struct llvmpipe_screen *screen)
+{
+ char *error = NULL;
+
+ screen->module = LLVMModuleCreateWithName("llvmpipe");
+
+ screen->provider = LLVMCreateModuleProviderForExistingModule(screen->module);
+
+ if (LLVMCreateJITCompiler(&screen->engine, screen->provider, 1, &error)) {
+ fprintf(stderr, "%s\n", error);
+ LLVMDisposeMessage(error);
+ abort();
+ }
+
+ screen->target = LLVMGetExecutionEngineTargetData(screen->engine);
+
+ screen->pass = LLVMCreateFunctionPassManager(screen->provider);
+ LLVMAddTargetData(screen->target, screen->pass);
+ /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
+ * but there are more on SVN. */
+ LLVMAddConstantPropagationPass(screen->pass);
+ LLVMAddInstructionCombiningPass(screen->pass);
+ LLVMAddPromoteMemoryToRegisterPass(screen->pass);
+ LLVMAddGVNPass(screen->pass);
+ LLVMAddCFGSimplificationPass(screen->pass);
+
+ lp_jit_init_globals(screen);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h
new file mode 100644
index 0000000000..58f716ede2
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_jit.h
@@ -0,0 +1,135 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * C - JIT interfaces
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef LP_JIT_H
+#define LP_JIT_H
+
+
+#include "lp_bld_struct.h"
+
+#include "pipe/p_state.h"
+
+
+struct tgsi_sampler;
+struct llvmpipe_screen;
+
+
+struct lp_jit_texture
+{
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ const void *data;
+};
+
+
+enum {
+ LP_JIT_TEXTURE_WIDTH = 0,
+ LP_JIT_TEXTURE_HEIGHT,
+ LP_JIT_TEXTURE_STRIDE,
+ LP_JIT_TEXTURE_DATA
+};
+
+
+
+/**
+ * This structure is passed directly to the generated fragment shader.
+ *
+ * It contains the derived state.
+ *
+ * Changes here must be reflected in the lp_jit_context_* macros and
+ * lp_jit_init_types function. Changes to the ordering should be avoided.
+ *
+ * Only use types with a clear size and padding here, in particular prefer the
+ * stdint.h types to the basic integer types.
+ */
+struct lp_jit_context
+{
+ const float *constants;
+
+ struct tgsi_sampler **samplers;
+
+ float alpha_ref_value;
+
+ /* FIXME: store (also?) in floats */
+ uint8_t *blend_color;
+
+ struct lp_jit_texture textures[PIPE_MAX_SAMPLERS];
+};
+
+
+#define lp_jit_context_constants(_builder, _ptr) \
+ lp_build_struct_get(_builder, _ptr, 0, "constants")
+
+#define lp_jit_context_samplers(_builder, _ptr) \
+ lp_build_struct_get(_builder, _ptr, 1, "samplers")
+
+#define lp_jit_context_alpha_ref_value(_builder, _ptr) \
+ lp_build_struct_get(_builder, _ptr, 2, "alpha_ref_value")
+
+#define lp_jit_context_blend_color(_builder, _ptr) \
+ lp_build_struct_get(_builder, _ptr, 3, "blend_color")
+
+#define LP_JIT_CONTEXT_TEXTURES_INDEX 4
+
+#define lp_jit_context_textures(_builder, _ptr) \
+ lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES_INDEX, "textures")
+
+
+typedef void
+(*lp_jit_frag_func)(struct lp_jit_context *context,
+ uint32_t x,
+ uint32_t y,
+ const void *a0,
+ const void *dadx,
+ const void *dady,
+ uint32_t *mask,
+ void *color,
+ void *depth);
+
+void PIPE_CDECL
+lp_fetch_texel_soa( struct tgsi_sampler **samplers,
+ uint32_t unit,
+ float *store );
+
+
+void
+lp_jit_screen_cleanup(struct llvmpipe_screen *screen);
+
+
+void
+lp_jit_screen_init(struct llvmpipe_screen *screen);
+
+
+#endif /* LP_JIT_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_prim_setup.c b/src/gallium/drivers/llvmpipe/lp_prim_setup.c
new file mode 100644
index 0000000000..b14f8fb99d
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_prim_setup.c
@@ -0,0 +1,190 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief A draw stage that drives our triangle setup routines from
+ * within the draw pipeline. One of two ways to drive setup, the
+ * other being in lp_prim_vbuf.c.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Brian Paul
+ */
+
+
+#include "lp_context.h"
+#include "lp_setup.h"
+#include "lp_state.h"
+#include "lp_prim_setup.h"
+#include "draw/draw_pipe.h"
+#include "draw/draw_vertex.h"
+#include "util/u_memory.h"
+
+/**
+ * Triangle setup info (derived from draw_stage).
+ * Also used for line drawing (taking some liberties).
+ */
+struct setup_stage {
+ struct draw_stage stage; /**< This must be first (base class) */
+
+ struct setup_context *setup;
+};
+
+
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct setup_stage *setup_stage( struct draw_stage *stage )
+{
+ return (struct setup_stage *)stage;
+}
+
+
+typedef const float (*cptrf4)[4];
+
+static void
+do_tri(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct setup_stage *setup = setup_stage( stage );
+
+ llvmpipe_setup_tri( setup->setup,
+ (cptrf4)prim->v[0]->data,
+ (cptrf4)prim->v[1]->data,
+ (cptrf4)prim->v[2]->data );
+}
+
+static void
+do_line(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct setup_stage *setup = setup_stage( stage );
+
+ llvmpipe_setup_line( setup->setup,
+ (cptrf4)prim->v[0]->data,
+ (cptrf4)prim->v[1]->data );
+}
+
+static void
+do_point(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct setup_stage *setup = setup_stage( stage );
+
+ llvmpipe_setup_point( setup->setup,
+ (cptrf4)prim->v[0]->data );
+}
+
+
+
+
+static void setup_begin( struct draw_stage *stage )
+{
+ struct setup_stage *setup = setup_stage(stage);
+
+ llvmpipe_setup_prepare( setup->setup );
+
+ stage->point = do_point;
+ stage->line = do_line;
+ stage->tri = do_tri;
+}
+
+
+static void setup_first_point( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ setup_begin(stage);
+ stage->point( stage, header );
+}
+
+static void setup_first_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ setup_begin(stage);
+ stage->line( stage, header );
+}
+
+
+static void setup_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ setup_begin(stage);
+ stage->tri( stage, header );
+}
+
+
+
+static void setup_flush( struct draw_stage *stage,
+ unsigned flags )
+{
+ stage->point = setup_first_point;
+ stage->line = setup_first_line;
+ stage->tri = setup_first_tri;
+}
+
+
+static void reset_stipple_counter( struct draw_stage *stage )
+{
+}
+
+
+static void render_destroy( struct draw_stage *stage )
+{
+ struct setup_stage *ssetup = setup_stage(stage);
+ llvmpipe_setup_destroy_context(ssetup->setup);
+ FREE( stage );
+}
+
+
+/**
+ * Create a new primitive setup/render stage.
+ */
+struct draw_stage *lp_draw_render_stage( struct llvmpipe_context *llvmpipe )
+{
+ struct setup_stage *sstage = CALLOC_STRUCT(setup_stage);
+
+ sstage->setup = llvmpipe_setup_create_context(llvmpipe);
+ sstage->stage.draw = llvmpipe->draw;
+ sstage->stage.point = setup_first_point;
+ sstage->stage.line = setup_first_line;
+ sstage->stage.tri = setup_first_tri;
+ sstage->stage.flush = setup_flush;
+ sstage->stage.reset_stipple_counter = reset_stipple_counter;
+ sstage->stage.destroy = render_destroy;
+
+ return (struct draw_stage *)sstage;
+}
+
+struct setup_context *
+lp_draw_setup_context( struct draw_stage *stage )
+{
+ struct setup_stage *ssetup = setup_stage(stage);
+ return ssetup->setup;
+}
+
+void
+lp_draw_flush( struct draw_stage *stage )
+{
+ stage->flush( stage, 0 );
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_prim_setup.h b/src/gallium/drivers/llvmpipe/lp_prim_setup.h
new file mode 100644
index 0000000000..da6cae6375
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_prim_setup.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef LP_PRIM_SETUP_H
+#define LP_PRIM_SETUP_H
+
+
+/**
+ * vbuf is a special stage to gather the stream of triangles, lines, points
+ * together and reconstruct vertex buffers for hardware upload.
+ *
+ * First attempt, work in progress.
+ *
+ * TODO:
+ * - separate out vertex buffer building and primitive emit, ie >1 draw per vb.
+ * - tell vbuf stage how to build hw vertices directly
+ * - pass vbuf stage a buffer pointer for direct emit to agp/vram.
+ *
+ *
+ *
+ * Vertices are just an array of floats, with all the attributes
+ * packed. We currently assume a layout like:
+ *
+ * attr[0][0..3] - window position
+ * attr[1..n][0..3] - remaining attributes.
+ *
+ * Attributes are assumed to be 4 floats wide but are packed so that
+ * all the enabled attributes run contiguously.
+ */
+
+
+struct draw_stage;
+struct llvmpipe_context;
+
+
+typedef void (*vbuf_draw_func)( struct pipe_context *pipe,
+ unsigned prim,
+ const ushort *elements,
+ unsigned nr_elements,
+ const void *vertex_buffer,
+ unsigned nr_vertices );
+
+
+extern struct draw_stage *
+lp_draw_render_stage( struct llvmpipe_context *llvmpipe );
+
+extern struct setup_context *
+lp_draw_setup_context( struct draw_stage * );
+
+extern void
+lp_draw_flush( struct draw_stage * );
+
+
+extern struct draw_stage *
+lp_draw_vbuf_stage( struct draw_context *draw_context,
+ struct pipe_context *pipe,
+ vbuf_draw_func draw );
+
+
+#endif /* LP_PRIM_SETUP_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c b/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c
new file mode 100644
index 0000000000..c394dcb61d
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c
@@ -0,0 +1,607 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Interface between 'draw' module's output and the llvmpipe rasterizer/setup
+ * code. When the 'draw' module has finished filling a vertex buffer, the
+ * draw_arrays() functions below will be called. Loop over the vertices and
+ * call the point/line/tri setup functions.
+ *
+ * Authors
+ * Brian Paul
+ */
+
+
+#include "lp_context.h"
+#include "lp_state.h"
+#include "lp_prim_vbuf.h"
+#include "lp_prim_setup.h"
+#include "lp_setup.h"
+#include "draw/draw_context.h"
+#include "draw/draw_vbuf.h"
+#include "util/u_memory.h"
+#include "util/u_prim.h"
+
+
+#define LP_MAX_VBUF_INDEXES 1024
+#define LP_MAX_VBUF_SIZE 4096
+
+typedef const float (*cptrf4)[4];
+
+/**
+ * Subclass of vbuf_render.
+ */
+struct llvmpipe_vbuf_render
+{
+ struct vbuf_render base;
+ struct llvmpipe_context *llvmpipe;
+ uint prim;
+ uint vertex_size;
+ uint nr_vertices;
+ uint vertex_buffer_size;
+ void *vertex_buffer;
+};
+
+
+/** cast wrapper */
+static struct llvmpipe_vbuf_render *
+llvmpipe_vbuf_render(struct vbuf_render *vbr)
+{
+ return (struct llvmpipe_vbuf_render *) vbr;
+}
+
+
+static const struct vertex_info *
+lp_vbuf_get_vertex_info(struct vbuf_render *vbr)
+{
+ struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
+ return llvmpipe_get_vbuf_vertex_info(cvbr->llvmpipe);
+}
+
+
+static boolean
+lp_vbuf_allocate_vertices(struct vbuf_render *vbr,
+ ushort vertex_size, ushort nr_vertices)
+{
+ struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
+ unsigned size = vertex_size * nr_vertices;
+
+ if (cvbr->vertex_buffer_size < size) {
+ align_free(cvbr->vertex_buffer);
+ cvbr->vertex_buffer = align_malloc(size, 16);
+ cvbr->vertex_buffer_size = size;
+ }
+
+ cvbr->vertex_size = vertex_size;
+ cvbr->nr_vertices = nr_vertices;
+
+ return cvbr->vertex_buffer != NULL;
+}
+
+static void
+lp_vbuf_release_vertices(struct vbuf_render *vbr)
+{
+#if 0
+ {
+ struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
+ const struct vertex_info *info =
+ llvmpipe_get_vbuf_vertex_info(cvbr->llvmpipe);
+ const float *vtx = (const float *) cvbr->vertex_buffer;
+ uint i, j;
+ debug_printf("%s (vtx_size = %u, vtx_used = %u)\n",
+ __FUNCTION__, cvbr->vertex_size, cvbr->nr_vertices);
+ for (i = 0; i < cvbr->nr_vertices; i++) {
+ for (j = 0; j < info->num_attribs; j++) {
+ uint k;
+ switch (info->attrib[j].emit) {
+ case EMIT_4F: k = 4; break;
+ case EMIT_3F: k = 3; break;
+ case EMIT_2F: k = 2; break;
+ case EMIT_1F: k = 1; break;
+ default: assert(0);
+ }
+ debug_printf("Vert %u attr %u: ", i, j);
+ while (k-- > 0) {
+ debug_printf("%g ", vtx[0]);
+ vtx++;
+ }
+ debug_printf("\n");
+ }
+ }
+ }
+#endif
+
+ /* keep the old allocation for next time */
+}
+
+static void *
+lp_vbuf_map_vertices(struct vbuf_render *vbr)
+{
+ struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
+ return cvbr->vertex_buffer;
+}
+
+static void
+lp_vbuf_unmap_vertices(struct vbuf_render *vbr,
+ ushort min_index,
+ ushort max_index )
+{
+ struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
+ assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
+ /* do nothing */
+}
+
+
+static boolean
+lp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
+{
+ struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
+
+ /* XXX: break this dependency - make setup_context live under
+ * llvmpipe, rename the old "setup" draw stage to something else.
+ */
+ struct setup_context *setup_ctx = lp_draw_setup_context(cvbr->llvmpipe->setup);
+
+ llvmpipe_setup_prepare( setup_ctx );
+
+ cvbr->llvmpipe->reduced_prim = u_reduced_prim(prim);
+ cvbr->prim = prim;
+ return TRUE;
+
+}
+
+
+static INLINE cptrf4 get_vert( const void *vertex_buffer,
+ int index,
+ int stride )
+{
+ return (cptrf4)((char *)vertex_buffer + index * stride);
+}
+
+
+/**
+ * draw elements / indexed primitives
+ */
+static void
+lp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)
+{
+ struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
+ struct llvmpipe_context *llvmpipe = cvbr->llvmpipe;
+ const unsigned stride = llvmpipe->vertex_info_vbuf.size * sizeof(float);
+ const void *vertex_buffer = cvbr->vertex_buffer;
+ unsigned i;
+
+ /* XXX: break this dependency - make setup_context live under
+ * llvmpipe, rename the old "setup" draw stage to something else.
+ */
+ struct draw_stage *setup = llvmpipe->setup;
+ struct setup_context *setup_ctx = lp_draw_setup_context(setup);
+
+ switch (cvbr->prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < nr; i++) {
+ llvmpipe_setup_point( setup_ctx,
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 1; i < nr; i += 2) {
+ llvmpipe_setup_line( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ for (i = 1; i < nr; i ++) {
+ llvmpipe_setup_line( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ for (i = 1; i < nr; i ++) {
+ llvmpipe_setup_line( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ if (nr) {
+ llvmpipe_setup_line( setup_ctx,
+ get_vert(vertex_buffer, indices[nr-1], stride),
+ get_vert(vertex_buffer, indices[0], stride) );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 2; i < nr; i += 3) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-2], stride) );
+ }
+ }
+ else {
+ for (i = 2; i < nr; i += 3) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 2; i < nr; i += 1) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
+ get_vert(vertex_buffer, indices[i-(i&1)], stride),
+ get_vert(vertex_buffer, indices[i-2], stride) );
+ }
+ }
+ else {
+ for (i = 2; i < nr; i += 1) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
+ get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 2; i < nr; i += 1) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride) );
+ }
+ }
+ else {
+ for (i = 2; i < nr; i += 1) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUADS:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 3; i < nr; i += 4) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-3], stride) );
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-3], stride) );
+ }
+ }
+ else {
+ for (i = 3; i < nr; i += 4) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 3; i < nr; i += 2) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-3], stride));
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-3], stride) );
+ }
+ }
+ else {
+ for (i = 3; i < nr; i += 2) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ /* Almost same as tri fan but the _first_ vertex specifies the flat
+ * shading color. Note that the first polygon vertex is passed as
+ * the last triangle vertex here.
+ * flatshade_first state makes no difference.
+ */
+ for (i = 2; i < nr; i += 1) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[0], stride) );
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ /* XXX: why are we calling this??? If we had to call something, it
+ * would be a function in lp_setup.c:
+ */
+ lp_draw_flush( setup );
+}
+
+
+/**
+ * This function is hit when the draw module is working in pass-through mode.
+ * It's up to us to convert the vertex array into point/line/tri prims.
+ */
+static void
+lp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
+{
+ struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
+ struct llvmpipe_context *llvmpipe = cvbr->llvmpipe;
+ const unsigned stride = llvmpipe->vertex_info_vbuf.size * sizeof(float);
+ const void *vertex_buffer =
+ (void *) get_vert(cvbr->vertex_buffer, start, stride);
+ unsigned i;
+
+ /* XXX: break this dependency - make setup_context live under
+ * llvmpipe, rename the old "setup" draw stage to something else.
+ */
+ struct draw_stage *setup = llvmpipe->setup;
+ struct setup_context *setup_ctx = lp_draw_setup_context(setup);
+
+ switch (cvbr->prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < nr; i++) {
+ llvmpipe_setup_point( setup_ctx,
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 1; i < nr; i += 2) {
+ llvmpipe_setup_line( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ for (i = 1; i < nr; i ++) {
+ llvmpipe_setup_line( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ for (i = 1; i < nr; i ++) {
+ llvmpipe_setup_line( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ if (nr) {
+ llvmpipe_setup_line( setup_ctx,
+ get_vert(vertex_buffer, nr-1, stride),
+ get_vert(vertex_buffer, 0, stride) );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 2; i < nr; i += 3) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-2, stride) );
+ }
+ }
+ else {
+ for (i = 2; i < nr; i += 3) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 2; i < nr; i++) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i+(i&1)-1, stride),
+ get_vert(vertex_buffer, i-(i&1), stride),
+ get_vert(vertex_buffer, i-2, stride) );
+ }
+ }
+ else {
+ for (i = 2; i < nr; i++) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i+(i&1)-2, stride),
+ get_vert(vertex_buffer, i-(i&1)-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 2; i < nr; i += 1) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, 0, stride),
+ get_vert(vertex_buffer, i-1, stride) );
+ }
+ }
+ else {
+ for (i = 2; i < nr; i += 1) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, 0, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUADS:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 3; i < nr; i += 4) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-3, stride) );
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-3, stride) );
+ }
+ }
+ else {
+ for (i = 3; i < nr; i += 4) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ if (llvmpipe->rasterizer->flatshade_first) {
+ for (i = 3; i < nr; i += 2) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-3, stride) );
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-3, stride) );
+ }
+ }
+ else {
+ for (i = 3; i < nr; i += 2) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ /* Almost same as tri fan but the _first_ vertex specifies the flat
+ * shading color. Note that the first polygon vertex is passed as
+ * the last triangle vertex here.
+ * flatshade_first state makes no difference.
+ */
+ for (i = 2; i < nr; i += 1) {
+ llvmpipe_setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, 0, stride) );
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+
+
+static void
+lp_vbuf_destroy(struct vbuf_render *vbr)
+{
+ struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
+ cvbr->llvmpipe->vbuf_render = NULL;
+ FREE(cvbr);
+}
+
+
+/**
+ * Initialize the post-transform vertex buffer information for the given
+ * context.
+ */
+void
+lp_init_vbuf(struct llvmpipe_context *lp)
+{
+ assert(lp->draw);
+
+ lp->vbuf_render = CALLOC_STRUCT(llvmpipe_vbuf_render);
+
+ lp->vbuf_render->base.max_indices = LP_MAX_VBUF_INDEXES;
+ lp->vbuf_render->base.max_vertex_buffer_bytes = LP_MAX_VBUF_SIZE;
+
+ lp->vbuf_render->base.get_vertex_info = lp_vbuf_get_vertex_info;
+ lp->vbuf_render->base.allocate_vertices = lp_vbuf_allocate_vertices;
+ lp->vbuf_render->base.map_vertices = lp_vbuf_map_vertices;
+ lp->vbuf_render->base.unmap_vertices = lp_vbuf_unmap_vertices;
+ lp->vbuf_render->base.set_primitive = lp_vbuf_set_primitive;
+ lp->vbuf_render->base.draw = lp_vbuf_draw;
+ lp->vbuf_render->base.draw_arrays = lp_vbuf_draw_arrays;
+ lp->vbuf_render->base.release_vertices = lp_vbuf_release_vertices;
+ lp->vbuf_render->base.destroy = lp_vbuf_destroy;
+
+ lp->vbuf_render->llvmpipe = lp;
+
+ lp->vbuf = draw_vbuf_stage(lp->draw, &lp->vbuf_render->base);
+
+ draw_set_rasterize_stage(lp->draw, lp->vbuf);
+
+ draw_set_render(lp->draw, &lp->vbuf_render->base);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_prim_vbuf.h b/src/gallium/drivers/llvmpipe/lp_prim_vbuf.h
new file mode 100644
index 0000000000..6c4e6063e6
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_prim_vbuf.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_VBUF_H
+#define LP_VBUF_H
+
+
+struct llvmpipe_context;
+
+extern void
+lp_init_vbuf(struct llvmpipe_context *llvmpipe);
+
+
+#endif /* LP_VBUF_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_quad.h b/src/gallium/drivers/llvmpipe/lp_quad.h
new file mode 100644
index 0000000000..7eb05de77a
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_quad.h
@@ -0,0 +1,114 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef LP_QUAD_H
+#define LP_QUAD_H
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_exec.h"
+
+
+#define QUAD_PRIM_POINT 1
+#define QUAD_PRIM_LINE 2
+#define QUAD_PRIM_TRI 3
+
+
+/* The rasterizer generates 2x2 quads of fragment and feeds them to
+ * the current fp_machine (see below).
+ * Remember that Y=0=top with Y increasing down the window.
+ */
+#define QUAD_TOP_LEFT 0
+#define QUAD_TOP_RIGHT 1
+#define QUAD_BOTTOM_LEFT 2
+#define QUAD_BOTTOM_RIGHT 3
+
+#define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT)
+#define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT)
+#define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT)
+#define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
+#define MASK_ALL 0xf
+
+
+/**
+ * Quad stage inputs (pos, coverage, front/back face, etc)
+ */
+struct quad_header_input
+{
+ int x0, y0; /**< quad window pos, always even */
+ float coverage[QUAD_SIZE]; /**< fragment coverage for antialiasing */
+ unsigned facing:1; /**< Front (0) or back (1) facing? */
+ unsigned prim:2; /**< QUAD_PRIM_POINT, LINE, TRI */
+};
+
+
+/**
+ * Quad stage inputs/outputs.
+ */
+struct quad_header_inout
+{
+ unsigned mask:4;
+};
+
+
+/**
+ * Quad stage outputs (color & depth).
+ */
+struct quad_header_output
+{
+ /** colors in SOA format (rrrr, gggg, bbbb, aaaa) */
+ float ALIGN16_ATTRIB color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][QUAD_SIZE];
+};
+
+
+/**
+ * Input interpolation coefficients
+ */
+struct quad_interp_coef
+{
+ float ALIGN16_ATTRIB a0[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
+ float ALIGN16_ATTRIB dadx[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
+ float ALIGN16_ATTRIB dady[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
+};
+
+
+/**
+ * Encodes everything we need to know about a 2x2 pixel block. Uses
+ * "Channel-Serial" or "SoA" layout.
+ */
+struct quad_header {
+ struct quad_header_input input;
+ struct quad_header_inout inout;
+
+ /* Redundant/duplicated:
+ */
+ const struct quad_interp_coef *coef;
+};
+
+#endif /* LP_QUAD_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c
new file mode 100644
index 0000000000..5554285425
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_query.c
@@ -0,0 +1,111 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "lp_context.h"
+#include "lp_query.h"
+#include "lp_state.h"
+
+struct llvmpipe_query {
+ uint64_t start;
+ uint64_t end;
+};
+
+
+static struct llvmpipe_query *llvmpipe_query( struct pipe_query *p )
+{
+ return (struct llvmpipe_query *)p;
+}
+
+static struct pipe_query *
+llvmpipe_create_query(struct pipe_context *pipe,
+ unsigned type)
+{
+ assert(type == PIPE_QUERY_OCCLUSION_COUNTER);
+ return (struct pipe_query *)CALLOC_STRUCT( llvmpipe_query );
+}
+
+
+static void
+llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+ FREE(q);
+}
+
+
+static void
+llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
+ struct llvmpipe_query *sq = llvmpipe_query(q);
+
+ sq->start = llvmpipe->occlusion_count;
+ llvmpipe->active_query_count++;
+ llvmpipe->dirty |= LP_NEW_QUERY;
+}
+
+
+static void
+llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
+ struct llvmpipe_query *sq = llvmpipe_query(q);
+
+ llvmpipe->active_query_count--;
+ sq->end = llvmpipe->occlusion_count;
+ llvmpipe->dirty |= LP_NEW_QUERY;
+}
+
+
+static boolean
+llvmpipe_get_query_result(struct pipe_context *pipe,
+ struct pipe_query *q,
+ boolean wait,
+ uint64_t *result )
+{
+ struct llvmpipe_query *sq = llvmpipe_query(q);
+ *result = sq->end - sq->start;
+ return TRUE;
+}
+
+
+void llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe )
+{
+ llvmpipe->pipe.create_query = llvmpipe_create_query;
+ llvmpipe->pipe.destroy_query = llvmpipe_destroy_query;
+ llvmpipe->pipe.begin_query = llvmpipe_begin_query;
+ llvmpipe->pipe.end_query = llvmpipe_end_query;
+ llvmpipe->pipe.get_query_result = llvmpipe_get_query_result;
+}
+
+
diff --git a/src/gallium/drivers/llvmpipe/lp_query.h b/src/gallium/drivers/llvmpipe/lp_query.h
new file mode 100644
index 0000000000..fa9fcd8713
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_query.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell
+ */
+
+#ifndef LP_QUERY_H
+#define LP_QUERY_H
+
+struct llvmpipe_context;
+extern void llvmpipe_init_query_funcs(struct llvmpipe_context * );
+
+
+#endif /* LP_QUERY_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
new file mode 100644
index 0000000000..125035771e
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -0,0 +1,243 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "util/u_simple_screen.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+
+#include "lp_texture.h"
+#include "lp_buffer.h"
+#include "lp_winsys.h"
+#include "lp_jit.h"
+#include "lp_screen.h"
+
+
+static const char *
+llvmpipe_get_vendor(struct pipe_screen *screen)
+{
+ return "VMware, Inc.";
+}
+
+
+static const char *
+llvmpipe_get_name(struct pipe_screen *screen)
+{
+ return "llvmpipe";
+}
+
+
+static int
+llvmpipe_get_param(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return PIPE_MAX_SAMPLERS;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ return PIPE_MAX_SAMPLERS;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 1;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 1;
+ case PIPE_CAP_GLSL:
+ return 1;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 0;
+ case PIPE_CAP_POINT_SPRITE:
+ return 1;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return PIPE_MAX_COLOR_BUFS;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 1;
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ return 1;
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 1;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 13; /* max 4Kx4K */
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 8; /* max 128x128x128 */
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 13; /* max 4Kx4K */
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ return 1;
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+static float
+llvmpipe_get_paramf(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 255.0; /* arbitrary */
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 255.0; /* arbitrary */
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 16.0; /* not actually signficant at this time */
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 16.0; /* arbitrary */
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ * Query format support for creating a texture, drawing surface, etc.
+ * \param format the format to test
+ * \param type one of PIPE_TEXTURE, PIPE_SURFACE
+ */
+static boolean
+llvmpipe_is_format_supported( struct pipe_screen *_screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags )
+{
+ struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
+ struct llvmpipe_winsys *winsys = screen->winsys;
+
+ assert(target == PIPE_TEXTURE_1D ||
+ target == PIPE_TEXTURE_2D ||
+ target == PIPE_TEXTURE_3D ||
+ target == PIPE_TEXTURE_CUBE);
+
+ if(format == PIPE_FORMAT_Z16_UNORM)
+ return FALSE;
+ if(format == PIPE_FORMAT_S8_UNORM)
+ return FALSE;
+
+ switch(format) {
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT5_RGBA:
+ return FALSE;
+ default:
+ break;
+ }
+
+ if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET)
+ return winsys->is_displaytarget_format_supported(winsys, format);
+
+ return TRUE;
+}
+
+
+static struct pipe_buffer *
+llvmpipe_surface_buffer_create(struct pipe_screen *screen,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned tex_usage,
+ unsigned usage,
+ unsigned *stride)
+{
+ /* This function should never be used */
+ assert(0);
+ return NULL;
+}
+
+
+static void
+llvmpipe_flush_frontbuffer(struct pipe_screen *_screen,
+ struct pipe_surface *surface,
+ void *context_private)
+{
+ struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
+ struct llvmpipe_winsys *winsys = screen->winsys;
+ struct llvmpipe_texture *texture = llvmpipe_texture(surface->texture);
+
+ assert(texture->dt);
+ if (texture->dt)
+ winsys->displaytarget_display(winsys, texture->dt, context_private);
+}
+
+
+static void
+llvmpipe_destroy_screen( struct pipe_screen *_screen )
+{
+ struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
+
+ struct pipe_winsys *winsys = _screen->winsys;
+
+ lp_jit_screen_cleanup(screen);
+
+ if(winsys->destroy)
+ winsys->destroy(winsys);
+
+ FREE(screen);
+}
+
+
+
+/**
+ * Create a new pipe_screen object
+ * Note: we're not presently subclassing pipe_screen (no llvmpipe_screen).
+ */
+struct pipe_screen *
+llvmpipe_create_screen(struct llvmpipe_winsys *winsys)
+{
+ struct llvmpipe_screen *screen = CALLOC_STRUCT(llvmpipe_screen);
+
+ if (!screen)
+ return NULL;
+
+ screen->winsys = winsys;
+
+ screen->base.destroy = llvmpipe_destroy_screen;
+
+ screen->base.get_name = llvmpipe_get_name;
+ screen->base.get_vendor = llvmpipe_get_vendor;
+ screen->base.get_param = llvmpipe_get_param;
+ screen->base.get_paramf = llvmpipe_get_paramf;
+ screen->base.is_format_supported = llvmpipe_is_format_supported;
+
+ screen->base.surface_buffer_create = llvmpipe_surface_buffer_create;
+ screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer;
+
+ llvmpipe_init_screen_texture_funcs(&screen->base);
+ llvmpipe_init_screen_buffer_funcs(&screen->base);
+
+ lp_jit_screen_init(screen);
+
+ return &screen->base;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.h b/src/gallium/drivers/llvmpipe/lp_screen.h
new file mode 100644
index 0000000000..4a1b4d6f3e
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_screen.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ * @author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef LP_SCREEN_H
+#define LP_SCREEN_H
+
+#include <llvm-c/Core.h>
+#include <llvm-c/Analysis.h>
+#include <llvm-c/Target.h>
+#include <llvm-c/ExecutionEngine.h>
+
+#include "pipe/p_screen.h"
+#include "pipe/p_defines.h"
+
+
+struct llvmpipe_winsys;
+
+
+struct llvmpipe_screen
+{
+ struct pipe_screen base;
+
+ struct llvmpipe_winsys *winsys;
+
+ LLVMModuleRef module;
+ LLVMExecutionEngineRef engine;
+ LLVMModuleProviderRef provider;
+ LLVMTargetDataRef target;
+ LLVMPassManagerRef pass;
+
+ LLVMTypeRef context_ptr_type;
+
+ /* Increments whenever textures are modified. Contexts can track
+ * this.
+ */
+ unsigned timestamp;
+};
+
+
+
+
+static INLINE struct llvmpipe_screen *
+llvmpipe_screen( struct pipe_screen *pipe )
+{
+ return (struct llvmpipe_screen *)pipe;
+}
+
+
+#endif /* LP_SCREEN_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
new file mode 100644
index 0000000000..2d2fc19a65
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -0,0 +1,1483 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Primitive rasterization/rendering (points, lines, triangles)
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Brian Paul
+ */
+
+#include "lp_context.h"
+#include "lp_prim_setup.h"
+#include "lp_quad.h"
+#include "lp_setup.h"
+#include "lp_state.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vertex.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_thread.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "lp_bld_debug.h"
+#include "lp_tile_cache.h"
+#include "lp_tile_soa.h"
+
+
+#define DEBUG_VERTS 0
+#define DEBUG_FRAGS 0
+
+/**
+ * Triangle edge info
+ */
+struct edge {
+ float dx; /**< X(v1) - X(v0), used only during setup */
+ float dy; /**< Y(v1) - Y(v0), used only during setup */
+ float dxdy; /**< dx/dy */
+ float sx, sy; /**< first sample point coord */
+ int lines; /**< number of lines on this edge */
+};
+
+
+#define MAX_QUADS 16
+
+
+/**
+ * Triangle setup info (derived from draw_stage).
+ * Also used for line drawing (taking some liberties).
+ */
+struct setup_context {
+ struct llvmpipe_context *llvmpipe;
+
+ /* Vertices are just an array of floats making up each attribute in
+ * turn. Currently fixed at 4 floats, but should change in time.
+ * Codegen will help cope with this.
+ */
+ const float (*vmax)[4];
+ const float (*vmid)[4];
+ const float (*vmin)[4];
+ const float (*vprovoke)[4];
+
+ struct edge ebot;
+ struct edge etop;
+ struct edge emaj;
+
+ float oneoverarea;
+ int facing;
+
+ struct quad_header quad[MAX_QUADS];
+ struct quad_header *quad_ptrs[MAX_QUADS];
+ unsigned count;
+
+ struct quad_interp_coef coef;
+
+ struct {
+ int left[2]; /**< [0] = row0, [1] = row1 */
+ int right[2];
+ int y;
+ } span;
+
+#if DEBUG_FRAGS
+ uint numFragsEmitted; /**< per primitive */
+ uint numFragsWritten; /**< per primitive */
+#endif
+
+ unsigned winding; /* which winding to cull */
+};
+
+
+
+/**
+ * Execute fragment shader for the four fragments in the quad.
+ */
+static void
+shade_quads(struct llvmpipe_context *llvmpipe,
+ struct quad_header *quads[],
+ unsigned nr)
+{
+ struct lp_fragment_shader *fs = llvmpipe->fs;
+ struct quad_header *quad = quads[0];
+ const unsigned x = quad->input.x0;
+ const unsigned y = quad->input.y0;
+ uint8_t *tile = lp_get_cached_tile(llvmpipe->cbuf_cache[0], x, y);
+ uint8_t *color;
+ void *depth;
+ uint32_t ALIGN16_ATTRIB mask[4][NUM_CHANNELS];
+ unsigned chan_index;
+ unsigned q;
+
+ assert(fs->current);
+ if(!fs->current)
+ return;
+
+ /* Sanity checks */
+ assert(nr * QUAD_SIZE == TILE_VECTOR_HEIGHT * TILE_VECTOR_WIDTH);
+ assert(x % TILE_VECTOR_WIDTH == 0);
+ assert(y % TILE_VECTOR_HEIGHT == 0);
+ for (q = 0; q < nr; ++q) {
+ assert(quads[q]->input.x0 == x + q*2);
+ assert(quads[q]->input.y0 == y);
+ }
+
+ /* mask */
+ for (q = 0; q < 4; ++q)
+ for (chan_index = 0; chan_index < NUM_CHANNELS; ++chan_index)
+ mask[q][chan_index] = quads[q]->inout.mask & (1 << chan_index) ? ~0 : 0;
+
+ /* color buffer */
+ color = &TILE_PIXEL(tile, x & (TILE_SIZE-1), y & (TILE_SIZE-1), 0);
+
+ /* depth buffer */
+ if(llvmpipe->zsbuf_map) {
+ assert((x % 2) == 0);
+ assert((y % 2) == 0);
+ depth = llvmpipe->zsbuf_map +
+ y*llvmpipe->zsbuf_transfer->stride +
+ 2*x*llvmpipe->zsbuf_transfer->block.size;
+ }
+ else
+ depth = NULL;
+
+ /* XXX: This will most likely fail on 32bit x86 without -mstackrealign */
+ assert(lp_check_alignment(mask, 16));
+
+ assert(lp_check_alignment(depth, 16));
+ assert(lp_check_alignment(color, 16));
+ assert(lp_check_alignment(llvmpipe->jit_context.blend_color, 16));
+
+ /* run shader */
+ fs->current->jit_function( &llvmpipe->jit_context,
+ x, y,
+ quad->coef->a0,
+ quad->coef->dadx,
+ quad->coef->dady,
+ &mask[0][0],
+ color,
+ depth);
+}
+
+
+
+
+/**
+ * Do triangle cull test using tri determinant (sign indicates orientation)
+ * \return true if triangle is to be culled.
+ */
+static INLINE boolean
+cull_tri(const struct setup_context *setup, float det)
+{
+ if (det != 0) {
+ /* if (det < 0 then Z points toward camera and triangle is
+ * counter-clockwise winding.
+ */
+ unsigned winding = (det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW;
+
+ if ((winding & setup->winding) == 0)
+ return FALSE;
+ }
+
+ /* Culled:
+ */
+ return TRUE;
+}
+
+
+
+/**
+ * Clip setup->quad against the scissor/surface bounds.
+ */
+static INLINE void
+quad_clip( struct setup_context *setup, struct quad_header *quad )
+{
+ const struct pipe_scissor_state *cliprect = &setup->llvmpipe->cliprect;
+ const int minx = (int) cliprect->minx;
+ const int maxx = (int) cliprect->maxx;
+ const int miny = (int) cliprect->miny;
+ const int maxy = (int) cliprect->maxy;
+
+ if (quad->input.x0 >= maxx ||
+ quad->input.y0 >= maxy ||
+ quad->input.x0 + 1 < minx ||
+ quad->input.y0 + 1 < miny) {
+ /* totally clipped */
+ quad->inout.mask = 0x0;
+ return;
+ }
+ if (quad->input.x0 < minx)
+ quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
+ if (quad->input.y0 < miny)
+ quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
+ if (quad->input.x0 == maxx - 1)
+ quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
+ if (quad->input.y0 == maxy - 1)
+ quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
+}
+
+
+
+/**
+ * Given an X or Y coordinate, return the block/quad coordinate that it
+ * belongs to.
+ */
+static INLINE int block( int x )
+{
+ return x & ~(2-1);
+}
+
+static INLINE int block_x( int x )
+{
+ return x & ~(TILE_VECTOR_WIDTH - 1);
+}
+
+
+/**
+ * Emit a quad (pass to next stage) with clipping.
+ */
+static INLINE void
+clip_emit_quad( struct setup_context *setup, struct quad_header *quad )
+{
+ quad_clip( setup, quad );
+
+ if (quad->inout.mask) {
+ struct llvmpipe_context *lp = setup->llvmpipe;
+
+#if 1
+ /* XXX: The blender expects 4 quads. This is far from efficient, but
+ * until we codegenerate single-quad variants of the fragment pipeline
+ * we need this hack. */
+ const unsigned nr_quads = TILE_VECTOR_HEIGHT*TILE_VECTOR_WIDTH/QUAD_SIZE;
+ struct quad_header quads[nr_quads];
+ struct quad_header *quad_ptrs[nr_quads];
+ int x0 = block_x(quad->input.x0);
+ unsigned i;
+
+ for(i = 0; i < nr_quads; ++i) {
+ int x = x0 + 2*i;
+ if(x == quad->input.x0)
+ memcpy(&quads[i], quad, sizeof quads[i]);
+ else {
+ memset(&quads[i], 0, sizeof quads[i]);
+ quads[i].input.x0 = x;
+ quads[i].input.y0 = quad->input.y0;
+ quads[i].coef = quad->coef;
+ }
+ quad_ptrs[i] = &quads[i];
+ }
+
+ shade_quads( lp, quad_ptrs, nr_quads );
+#else
+ shade_quads( lp, &quad, 1 );
+#endif
+ }
+}
+
+
+/**
+ * Render a horizontal span of quads
+ */
+static void flush_spans( struct setup_context *setup )
+{
+ const int step = TILE_VECTOR_WIDTH;
+ const int xleft0 = setup->span.left[0];
+ const int xleft1 = setup->span.left[1];
+ const int xright0 = setup->span.right[0];
+ const int xright1 = setup->span.right[1];
+
+
+ int minleft = block_x(MIN2(xleft0, xleft1));
+ int maxright = MAX2(xright0, xright1);
+ int x;
+
+ for (x = minleft; x < maxright; x += step) {
+ unsigned skip_left0 = CLAMP(xleft0 - x, 0, step);
+ unsigned skip_left1 = CLAMP(xleft1 - x, 0, step);
+ unsigned skip_right0 = CLAMP(x + step - xright0, 0, step);
+ unsigned skip_right1 = CLAMP(x + step - xright1, 0, step);
+ unsigned lx = x;
+ const unsigned nr_quads = TILE_VECTOR_HEIGHT*TILE_VECTOR_WIDTH/QUAD_SIZE;
+ unsigned q = 0;
+
+ unsigned skipmask_left0 = (1U << skip_left0) - 1U;
+ unsigned skipmask_left1 = (1U << skip_left1) - 1U;
+
+ /* These calculations fail when step == 32 and skip_right == 0.
+ */
+ unsigned skipmask_right0 = ~0U << (unsigned)(step - skip_right0);
+ unsigned skipmask_right1 = ~0U << (unsigned)(step - skip_right1);
+
+ unsigned mask0 = ~skipmask_left0 & ~skipmask_right0;
+ unsigned mask1 = ~skipmask_left1 & ~skipmask_right1;
+
+ if (mask0 | mask1) {
+ for(q = 0; q < nr_quads; ++q) {
+ unsigned quadmask = (mask0 & 3) | ((mask1 & 3) << 2);
+ setup->quad[q].input.x0 = lx;
+ setup->quad[q].input.y0 = setup->span.y;
+ setup->quad[q].inout.mask = quadmask;
+ setup->quad_ptrs[q] = &setup->quad[q];
+ mask0 >>= 2;
+ mask1 >>= 2;
+ lx += 2;
+ }
+ assert(!(mask0 | mask1));
+
+ shade_quads(setup->llvmpipe, setup->quad_ptrs, nr_quads );
+ }
+ }
+
+
+ setup->span.y = 0;
+ setup->span.right[0] = 0;
+ setup->span.right[1] = 0;
+ setup->span.left[0] = 1000000; /* greater than right[0] */
+ setup->span.left[1] = 1000000; /* greater than right[1] */
+}
+
+
+#if DEBUG_VERTS
+static void print_vertex(const struct setup_context *setup,
+ const float (*v)[4])
+{
+ int i;
+ debug_printf(" Vertex: (%p)\n", v);
+ for (i = 0; i < setup->quad[0].nr_attrs; i++) {
+ debug_printf(" %d: %f %f %f %f\n", i,
+ v[i][0], v[i][1], v[i][2], v[i][3]);
+ if (util_is_inf_or_nan(v[i][0])) {
+ debug_printf(" NaN!\n");
+ }
+ }
+}
+#endif
+
+/**
+ * Sort the vertices from top to bottom order, setting up the triangle
+ * edge fields (ebot, emaj, etop).
+ * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
+ */
+static boolean setup_sort_vertices( struct setup_context *setup,
+ float det,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4] )
+{
+ setup->vprovoke = v2;
+
+ /* determine bottom to top order of vertices */
+ {
+ float y0 = v0[0][1];
+ float y1 = v1[0][1];
+ float y2 = v2[0][1];
+ if (y0 <= y1) {
+ if (y1 <= y2) {
+ /* y0<=y1<=y2 */
+ setup->vmin = v0;
+ setup->vmid = v1;
+ setup->vmax = v2;
+ }
+ else if (y2 <= y0) {
+ /* y2<=y0<=y1 */
+ setup->vmin = v2;
+ setup->vmid = v0;
+ setup->vmax = v1;
+ }
+ else {
+ /* y0<=y2<=y1 */
+ setup->vmin = v0;
+ setup->vmid = v2;
+ setup->vmax = v1;
+ }
+ }
+ else {
+ if (y0 <= y2) {
+ /* y1<=y0<=y2 */
+ setup->vmin = v1;
+ setup->vmid = v0;
+ setup->vmax = v2;
+ }
+ else if (y2 <= y1) {
+ /* y2<=y1<=y0 */
+ setup->vmin = v2;
+ setup->vmid = v1;
+ setup->vmax = v0;
+ }
+ else {
+ /* y1<=y2<=y0 */
+ setup->vmin = v1;
+ setup->vmid = v2;
+ setup->vmax = v0;
+ }
+ }
+ }
+
+ setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0];
+ setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1];
+ setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
+ setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
+ setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0];
+ setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1];
+
+ /*
+ * Compute triangle's area. Use 1/area to compute partial
+ * derivatives of attributes later.
+ *
+ * The area will be the same as prim->det, but the sign may be
+ * different depending on how the vertices get sorted above.
+ *
+ * To determine whether the primitive is front or back facing we
+ * use the prim->det value because its sign is correct.
+ */
+ {
+ const float area = (setup->emaj.dx * setup->ebot.dy -
+ setup->ebot.dx * setup->emaj.dy);
+
+ setup->oneoverarea = 1.0f / area;
+
+ /*
+ debug_printf("%s one-over-area %f area %f det %f\n",
+ __FUNCTION__, setup->oneoverarea, area, det );
+ */
+ if (util_is_inf_or_nan(setup->oneoverarea))
+ return FALSE;
+ }
+
+ /* We need to know if this is a front or back-facing triangle for:
+ * - the GLSL gl_FrontFacing fragment attribute (bool)
+ * - two-sided stencil test
+ */
+ setup->facing =
+ ((det > 0.0) ^
+ (setup->llvmpipe->rasterizer->front_winding == PIPE_WINDING_CW));
+
+ return TRUE;
+}
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a triangle.
+ */
+static void tri_pos_coeff( struct setup_context *setup,
+ uint vertSlot, unsigned i)
+{
+ float botda = setup->vmid[vertSlot][i] - setup->vmin[vertSlot][i];
+ float majda = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
+ float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+ float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+ float dadx = a * setup->oneoverarea;
+ float dady = b * setup->oneoverarea;
+
+ assert(i <= 3);
+
+ setup->coef.dadx[0][i] = dadx;
+ setup->coef.dady[0][i] = dady;
+
+ /* calculate a0 as the value which would be sampled for the
+ * fragment at (0,0), taking into account that we want to sample at
+ * pixel centers, in other words (0.5, 0.5).
+ *
+ * this is neat but unfortunately not a good way to do things for
+ * triangles with very large values of dadx or dady as it will
+ * result in the subtraction and re-addition from a0 of a very
+ * large number, which means we'll end up loosing a lot of the
+ * fractional bits and precision from a0. the way to fix this is
+ * to define a0 as the sample at a pixel center somewhere near vmin
+ * instead - i'll switch to this later.
+ */
+ setup->coef.a0[0][i] = (setup->vmin[vertSlot][i] -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+
+ /*
+ debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
+ slot, "xyzw"[i],
+ setup->coef[slot].a0[i],
+ setup->coef[slot].dadx[i],
+ setup->coef[slot].dady[i]);
+ */
+}
+
+
+/**
+ * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
+ * The value value comes from vertex[slot][i].
+ * The result will be put into setup->coef[slot].a0[i].
+ * \param slot which attribute slot
+ * \param i which component of the slot (0..3)
+ */
+static void const_pos_coeff( struct setup_context *setup,
+ uint vertSlot, unsigned i)
+{
+ setup->coef.dadx[0][i] = 0;
+ setup->coef.dady[0][i] = 0;
+
+ /* need provoking vertex info!
+ */
+ setup->coef.a0[0][i] = setup->vprovoke[vertSlot][i];
+}
+
+
+/**
+ * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
+ * The value value comes from vertex[slot][i].
+ * The result will be put into setup->coef[slot].a0[i].
+ * \param slot which attribute slot
+ * \param i which component of the slot (0..3)
+ */
+static void const_coeff( struct setup_context *setup,
+ unsigned attrib,
+ uint vertSlot)
+{
+ unsigned i;
+ for (i = 0; i < NUM_CHANNELS; ++i) {
+ setup->coef.dadx[1 + attrib][i] = 0;
+ setup->coef.dady[1 + attrib][i] = 0;
+
+ /* need provoking vertex info!
+ */
+ setup->coef.a0[1 + attrib][i] = setup->vprovoke[vertSlot][i];
+ }
+}
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a triangle.
+ */
+static void tri_linear_coeff( struct setup_context *setup,
+ unsigned attrib,
+ uint vertSlot)
+{
+ unsigned i;
+ for (i = 0; i < NUM_CHANNELS; ++i) {
+ float botda = setup->vmid[vertSlot][i] - setup->vmin[vertSlot][i];
+ float majda = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
+ float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+ float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+ float dadx = a * setup->oneoverarea;
+ float dady = b * setup->oneoverarea;
+
+ assert(i <= 3);
+
+ setup->coef.dadx[1 + attrib][i] = dadx;
+ setup->coef.dady[1 + attrib][i] = dady;
+
+ /* calculate a0 as the value which would be sampled for the
+ * fragment at (0,0), taking into account that we want to sample at
+ * pixel centers, in other words (0.5, 0.5).
+ *
+ * this is neat but unfortunately not a good way to do things for
+ * triangles with very large values of dadx or dady as it will
+ * result in the subtraction and re-addition from a0 of a very
+ * large number, which means we'll end up loosing a lot of the
+ * fractional bits and precision from a0. the way to fix this is
+ * to define a0 as the sample at a pixel center somewhere near vmin
+ * instead - i'll switch to this later.
+ */
+ setup->coef.a0[1 + attrib][i] = (setup->vmin[vertSlot][i] -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+
+ /*
+ debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
+ slot, "xyzw"[i],
+ setup->coef[slot].a0[i],
+ setup->coef[slot].dadx[i],
+ setup->coef[slot].dady[i]);
+ */
+ }
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a triangle.
+ * We basically multiply the vertex value by 1/w before computing
+ * the plane coefficients (a0, dadx, dady).
+ * Later, when we compute the value at a particular fragment position we'll
+ * divide the interpolated value by the interpolated W at that fragment.
+ */
+static void tri_persp_coeff( struct setup_context *setup,
+ unsigned attrib,
+ uint vertSlot)
+{
+ unsigned i;
+ for (i = 0; i < NUM_CHANNELS; ++i) {
+ /* premultiply by 1/w (v[0][3] is always W):
+ */
+ float mina = setup->vmin[vertSlot][i] * setup->vmin[0][3];
+ float mida = setup->vmid[vertSlot][i] * setup->vmid[0][3];
+ float maxa = setup->vmax[vertSlot][i] * setup->vmax[0][3];
+ float botda = mida - mina;
+ float majda = maxa - mina;
+ float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+ float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+ float dadx = a * setup->oneoverarea;
+ float dady = b * setup->oneoverarea;
+
+ /*
+ debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
+ setup->vmin[vertSlot][i],
+ setup->vmid[vertSlot][i],
+ setup->vmax[vertSlot][i]
+ );
+ */
+ assert(i <= 3);
+
+ setup->coef.dadx[1 + attrib][i] = dadx;
+ setup->coef.dady[1 + attrib][i] = dady;
+ setup->coef.a0[1 + attrib][i] = (mina -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+ }
+}
+
+
+/**
+ * Special coefficient setup for gl_FragCoord.
+ * X and Y are trivial, though Y has to be inverted for OpenGL.
+ * Z and W are copied from posCoef which should have already been computed.
+ * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
+ */
+static void
+setup_fragcoord_coeff(struct setup_context *setup, uint slot)
+{
+ /*X*/
+ setup->coef.a0[1 + slot][0] = 0;
+ setup->coef.dadx[1 + slot][0] = 1.0;
+ setup->coef.dady[1 + slot][0] = 0.0;
+ /*Y*/
+ setup->coef.a0[1 + slot][1] = 0.0;
+ setup->coef.dadx[1 + slot][1] = 0.0;
+ setup->coef.dady[1 + slot][1] = 1.0;
+ /*Z*/
+ setup->coef.a0[1 + slot][2] = setup->coef.a0[0][2];
+ setup->coef.dadx[1 + slot][2] = setup->coef.dadx[0][2];
+ setup->coef.dady[1 + slot][2] = setup->coef.dady[0][2];
+ /*W*/
+ setup->coef.a0[1 + slot][3] = setup->coef.a0[0][3];
+ setup->coef.dadx[1 + slot][3] = setup->coef.dadx[0][3];
+ setup->coef.dady[1 + slot][3] = setup->coef.dady[0][3];
+}
+
+
+
+/**
+ * Compute the setup->coef[] array dadx, dady, a0 values.
+ * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
+ */
+static void setup_tri_coefficients( struct setup_context *setup )
+{
+ struct llvmpipe_context *llvmpipe = setup->llvmpipe;
+ const struct lp_fragment_shader *lpfs = llvmpipe->fs;
+ const struct vertex_info *vinfo = llvmpipe_get_vertex_info(llvmpipe);
+ uint fragSlot;
+
+ /* z and w are done by linear interpolation:
+ */
+ tri_pos_coeff(setup, 0, 2);
+ tri_pos_coeff(setup, 0, 3);
+
+ /* setup interpolation for all the remaining attributes:
+ */
+ for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) {
+ const uint vertSlot = vinfo->attrib[fragSlot].src_index;
+
+ switch (vinfo->attrib[fragSlot].interp_mode) {
+ case INTERP_CONSTANT:
+ const_coeff(setup, fragSlot, vertSlot);
+ break;
+ case INTERP_LINEAR:
+ tri_linear_coeff(setup, fragSlot, vertSlot);
+ break;
+ case INTERP_PERSPECTIVE:
+ tri_persp_coeff(setup, fragSlot, vertSlot);
+ break;
+ case INTERP_POS:
+ setup_fragcoord_coeff(setup, fragSlot);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (lpfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
+ setup->coef.a0[1 + fragSlot][0] = 1.0f - setup->facing;
+ setup->coef.dadx[1 + fragSlot][0] = 0.0;
+ setup->coef.dady[1 + fragSlot][0] = 0.0;
+ }
+ }
+}
+
+
+
+static void setup_tri_edges( struct setup_context *setup )
+{
+ float vmin_x = setup->vmin[0][0] + 0.5f;
+ float vmid_x = setup->vmid[0][0] + 0.5f;
+
+ float vmin_y = setup->vmin[0][1] - 0.5f;
+ float vmid_y = setup->vmid[0][1] - 0.5f;
+ float vmax_y = setup->vmax[0][1] - 0.5f;
+
+ setup->emaj.sy = ceilf(vmin_y);
+ setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
+ setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy;
+ setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
+
+ setup->etop.sy = ceilf(vmid_y);
+ setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
+ setup->etop.dxdy = setup->etop.dx / setup->etop.dy;
+ setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
+
+ setup->ebot.sy = ceilf(vmin_y);
+ setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
+ setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy;
+ setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
+}
+
+
+/**
+ * Render the upper or lower half of a triangle.
+ * Scissoring/cliprect is applied here too.
+ */
+static void subtriangle( struct setup_context *setup,
+ struct edge *eleft,
+ struct edge *eright,
+ unsigned lines )
+{
+ const struct pipe_scissor_state *cliprect = &setup->llvmpipe->cliprect;
+ const int minx = (int) cliprect->minx;
+ const int maxx = (int) cliprect->maxx;
+ const int miny = (int) cliprect->miny;
+ const int maxy = (int) cliprect->maxy;
+ int y, start_y, finish_y;
+ int sy = (int)eleft->sy;
+
+ assert((int)eleft->sy == (int) eright->sy);
+
+ /* clip top/bottom */
+ start_y = sy;
+ if (start_y < miny)
+ start_y = miny;
+
+ finish_y = sy + lines;
+ if (finish_y > maxy)
+ finish_y = maxy;
+
+ start_y -= sy;
+ finish_y -= sy;
+
+ /*
+ debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
+ */
+
+ for (y = start_y; y < finish_y; y++) {
+
+ /* avoid accumulating adds as floats don't have the precision to
+ * accurately iterate large triangle edges that way. luckily we
+ * can just multiply these days.
+ *
+ * this is all drowned out by the attribute interpolation anyway.
+ */
+ int left = (int)(eleft->sx + y * eleft->dxdy);
+ int right = (int)(eright->sx + y * eright->dxdy);
+
+ /* clip left/right */
+ if (left < minx)
+ left = minx;
+ if (right > maxx)
+ right = maxx;
+
+ if (left < right) {
+ int _y = sy + y;
+ if (block(_y) != setup->span.y) {
+ flush_spans(setup);
+ setup->span.y = block(_y);
+ }
+
+ setup->span.left[_y&1] = left;
+ setup->span.right[_y&1] = right;
+ }
+ }
+
+
+ /* save the values so that emaj can be restarted:
+ */
+ eleft->sx += lines * eleft->dxdy;
+ eright->sx += lines * eright->dxdy;
+ eleft->sy += lines;
+ eright->sy += lines;
+}
+
+
+/**
+ * Recalculate prim's determinant. This is needed as we don't have
+ * get this information through the vbuf_render interface & we must
+ * calculate it here.
+ */
+static float
+calc_det( const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4] )
+{
+ /* edge vectors e = v0 - v2, f = v1 - v2 */
+ const float ex = v0[0][0] - v2[0][0];
+ const float ey = v0[0][1] - v2[0][1];
+ const float fx = v1[0][0] - v2[0][0];
+ const float fy = v1[0][1] - v2[0][1];
+
+ /* det = cross(e,f).z */
+ return ex * fy - ey * fx;
+}
+
+
+/**
+ * Do setup for triangle rasterization, then render the triangle.
+ */
+void llvmpipe_setup_tri( struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4] )
+{
+ float det;
+
+#if DEBUG_VERTS
+ debug_printf("Setup triangle:\n");
+ print_vertex(setup, v0);
+ print_vertex(setup, v1);
+ print_vertex(setup, v2);
+#endif
+
+ if (setup->llvmpipe->no_rast)
+ return;
+
+ det = calc_det(v0, v1, v2);
+ /*
+ debug_printf("%s\n", __FUNCTION__ );
+ */
+
+#if DEBUG_FRAGS
+ setup->numFragsEmitted = 0;
+ setup->numFragsWritten = 0;
+#endif
+
+ if (cull_tri( setup, det ))
+ return;
+
+ if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
+ return;
+ setup_tri_coefficients( setup );
+ setup_tri_edges( setup );
+
+ assert(setup->llvmpipe->reduced_prim == PIPE_PRIM_TRIANGLES);
+
+ setup->span.y = 0;
+ setup->span.right[0] = 0;
+ setup->span.right[1] = 0;
+ /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
+
+ /* init_constant_attribs( setup ); */
+
+ if (setup->oneoverarea < 0.0) {
+ /* emaj on left:
+ */
+ subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
+ subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
+ }
+ else {
+ /* emaj on right:
+ */
+ subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
+ subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
+ }
+
+ flush_spans( setup );
+
+#if DEBUG_FRAGS
+ printf("Tri: %u frags emitted, %u written\n",
+ setup->numFragsEmitted,
+ setup->numFragsWritten);
+#endif
+}
+
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a line.
+ */
+static void
+linear_pos_coeff(struct setup_context *setup,
+ uint vertSlot, uint i)
+{
+ const float da = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
+ const float dadx = da * setup->emaj.dx * setup->oneoverarea;
+ const float dady = da * setup->emaj.dy * setup->oneoverarea;
+ setup->coef.dadx[0][i] = dadx;
+ setup->coef.dady[0][i] = dady;
+ setup->coef.a0[0][i] = (setup->vmin[vertSlot][i] -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+}
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a line.
+ */
+static void
+line_linear_coeff(struct setup_context *setup,
+ unsigned attrib,
+ uint vertSlot)
+{
+ unsigned i;
+ for (i = 0; i < NUM_CHANNELS; ++i) {
+ const float da = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
+ const float dadx = da * setup->emaj.dx * setup->oneoverarea;
+ const float dady = da * setup->emaj.dy * setup->oneoverarea;
+ setup->coef.dadx[1 + attrib][i] = dadx;
+ setup->coef.dady[1 + attrib][i] = dady;
+ setup->coef.a0[1 + attrib][i] = (setup->vmin[vertSlot][i] -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+ }
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a line.
+ */
+static void
+line_persp_coeff(struct setup_context *setup,
+ unsigned attrib,
+ uint vertSlot)
+{
+ unsigned i;
+ for (i = 0; i < NUM_CHANNELS; ++i) {
+ /* XXX double-check/verify this arithmetic */
+ const float a0 = setup->vmin[vertSlot][i] * setup->vmin[0][3];
+ const float a1 = setup->vmax[vertSlot][i] * setup->vmax[0][3];
+ const float da = a1 - a0;
+ const float dadx = da * setup->emaj.dx * setup->oneoverarea;
+ const float dady = da * setup->emaj.dy * setup->oneoverarea;
+ setup->coef.dadx[1 + attrib][i] = dadx;
+ setup->coef.dady[1 + attrib][i] = dady;
+ setup->coef.a0[1 + attrib][i] = (setup->vmin[vertSlot][i] -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+ }
+}
+
+
+/**
+ * Compute the setup->coef[] array dadx, dady, a0 values.
+ * Must be called after setup->vmin,vmax are initialized.
+ */
+static INLINE boolean
+setup_line_coefficients(struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4])
+{
+ struct llvmpipe_context *llvmpipe = setup->llvmpipe;
+ const struct lp_fragment_shader *lpfs = llvmpipe->fs;
+ const struct vertex_info *vinfo = llvmpipe_get_vertex_info(llvmpipe);
+ uint fragSlot;
+ float area;
+
+ /* use setup->vmin, vmax to point to vertices */
+ if (llvmpipe->rasterizer->flatshade_first)
+ setup->vprovoke = v0;
+ else
+ setup->vprovoke = v1;
+ setup->vmin = v0;
+ setup->vmax = v1;
+
+ setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
+ setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
+
+ /* NOTE: this is not really area but something proportional to it */
+ area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy;
+ if (area == 0.0f || util_is_inf_or_nan(area))
+ return FALSE;
+ setup->oneoverarea = 1.0f / area;
+
+ /* z and w are done by linear interpolation:
+ */
+ linear_pos_coeff(setup, 0, 2);
+ linear_pos_coeff(setup, 0, 3);
+
+ /* setup interpolation for all the remaining attributes:
+ */
+ for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) {
+ const uint vertSlot = vinfo->attrib[fragSlot].src_index;
+
+ switch (vinfo->attrib[fragSlot].interp_mode) {
+ case INTERP_CONSTANT:
+ const_coeff(setup, fragSlot, vertSlot);
+ break;
+ case INTERP_LINEAR:
+ line_linear_coeff(setup, fragSlot, vertSlot);
+ break;
+ case INTERP_PERSPECTIVE:
+ line_persp_coeff(setup, fragSlot, vertSlot);
+ break;
+ case INTERP_POS:
+ setup_fragcoord_coeff(setup, fragSlot);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (lpfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
+ setup->coef.a0[1 + fragSlot][0] = 1.0f - setup->facing;
+ setup->coef.dadx[1 + fragSlot][0] = 0.0;
+ setup->coef.dady[1 + fragSlot][0] = 0.0;
+ }
+ }
+ return TRUE;
+}
+
+
+/**
+ * Plot a pixel in a line segment.
+ */
+static INLINE void
+plot(struct setup_context *setup, int x, int y)
+{
+ const int iy = y & 1;
+ const int ix = x & 1;
+ const int quadX = x - ix;
+ const int quadY = y - iy;
+ const int mask = (1 << ix) << (2 * iy);
+
+ if (quadX != setup->quad[0].input.x0 ||
+ quadY != setup->quad[0].input.y0)
+ {
+ /* flush prev quad, start new quad */
+
+ if (setup->quad[0].input.x0 != -1)
+ clip_emit_quad( setup, &setup->quad[0] );
+
+ setup->quad[0].input.x0 = quadX;
+ setup->quad[0].input.y0 = quadY;
+ setup->quad[0].inout.mask = 0x0;
+ }
+
+ setup->quad[0].inout.mask |= mask;
+}
+
+
+/**
+ * Do setup for line rasterization, then render the line.
+ * Single-pixel width, no stipple, etc. We rely on the 'draw' module
+ * to handle stippling and wide lines.
+ */
+void
+llvmpipe_setup_line(struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4])
+{
+ int x0 = (int) v0[0][0];
+ int x1 = (int) v1[0][0];
+ int y0 = (int) v0[0][1];
+ int y1 = (int) v1[0][1];
+ int dx = x1 - x0;
+ int dy = y1 - y0;
+ int xstep, ystep;
+
+#if DEBUG_VERTS
+ debug_printf("Setup line:\n");
+ print_vertex(setup, v0);
+ print_vertex(setup, v1);
+#endif
+
+ if (setup->llvmpipe->no_rast)
+ return;
+
+ if (dx == 0 && dy == 0)
+ return;
+
+ if (!setup_line_coefficients(setup, v0, v1))
+ return;
+
+ assert(v0[0][0] < 1.0e9);
+ assert(v0[0][1] < 1.0e9);
+ assert(v1[0][0] < 1.0e9);
+ assert(v1[0][1] < 1.0e9);
+
+ if (dx < 0) {
+ dx = -dx; /* make positive */
+ xstep = -1;
+ }
+ else {
+ xstep = 1;
+ }
+
+ if (dy < 0) {
+ dy = -dy; /* make positive */
+ ystep = -1;
+ }
+ else {
+ ystep = 1;
+ }
+
+ assert(dx >= 0);
+ assert(dy >= 0);
+ assert(setup->llvmpipe->reduced_prim == PIPE_PRIM_LINES);
+
+ setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1;
+ setup->quad[0].inout.mask = 0x0;
+
+ /* XXX temporary: set coverage to 1.0 so the line appears
+ * if AA mode happens to be enabled.
+ */
+ setup->quad[0].input.coverage[0] =
+ setup->quad[0].input.coverage[1] =
+ setup->quad[0].input.coverage[2] =
+ setup->quad[0].input.coverage[3] = 1.0;
+
+ if (dx > dy) {
+ /*** X-major line ***/
+ int i;
+ const int errorInc = dy + dy;
+ int error = errorInc - dx;
+ const int errorDec = error - dx;
+
+ for (i = 0; i < dx; i++) {
+ plot(setup, x0, y0);
+
+ x0 += xstep;
+ if (error < 0) {
+ error += errorInc;
+ }
+ else {
+ error += errorDec;
+ y0 += ystep;
+ }
+ }
+ }
+ else {
+ /*** Y-major line ***/
+ int i;
+ const int errorInc = dx + dx;
+ int error = errorInc - dy;
+ const int errorDec = error - dy;
+
+ for (i = 0; i < dy; i++) {
+ plot(setup, x0, y0);
+
+ y0 += ystep;
+ if (error < 0) {
+ error += errorInc;
+ }
+ else {
+ error += errorDec;
+ x0 += xstep;
+ }
+ }
+ }
+
+ /* draw final quad */
+ if (setup->quad[0].inout.mask) {
+ clip_emit_quad( setup, &setup->quad[0] );
+ }
+}
+
+
+static void
+point_persp_coeff(struct setup_context *setup,
+ const float (*vert)[4],
+ unsigned attrib,
+ uint vertSlot)
+{
+ unsigned i;
+ for(i = 0; i < NUM_CHANNELS; ++i) {
+ setup->coef.dadx[1 + attrib][i] = 0.0F;
+ setup->coef.dady[1 + attrib][i] = 0.0F;
+ setup->coef.a0[1 + attrib][i] = vert[vertSlot][i] * vert[0][3];
+ }
+}
+
+
+/**
+ * Do setup for point rasterization, then render the point.
+ * Round or square points...
+ * XXX could optimize a lot for 1-pixel points.
+ */
+void
+llvmpipe_setup_point( struct setup_context *setup,
+ const float (*v0)[4] )
+{
+ struct llvmpipe_context *llvmpipe = setup->llvmpipe;
+ const struct lp_fragment_shader *lpfs = llvmpipe->fs;
+ const int sizeAttr = setup->llvmpipe->psize_slot;
+ const float size
+ = sizeAttr > 0 ? v0[sizeAttr][0]
+ : setup->llvmpipe->rasterizer->point_size;
+ const float halfSize = 0.5F * size;
+ const boolean round = (boolean) setup->llvmpipe->rasterizer->point_smooth;
+ const float x = v0[0][0]; /* Note: data[0] is always position */
+ const float y = v0[0][1];
+ const struct vertex_info *vinfo = llvmpipe_get_vertex_info(llvmpipe);
+ uint fragSlot;
+
+#if DEBUG_VERTS
+ debug_printf("Setup point:\n");
+ print_vertex(setup, v0);
+#endif
+
+ if (llvmpipe->no_rast)
+ return;
+
+ assert(setup->llvmpipe->reduced_prim == PIPE_PRIM_POINTS);
+
+ /* For points, all interpolants are constant-valued.
+ * However, for point sprites, we'll need to setup texcoords appropriately.
+ * XXX: which coefficients are the texcoords???
+ * We may do point sprites as textured quads...
+ *
+ * KW: We don't know which coefficients are texcoords - ultimately
+ * the choice of what interpolation mode to use for each attribute
+ * should be determined by the fragment program, using
+ * per-attribute declaration statements that include interpolation
+ * mode as a parameter. So either the fragment program will have
+ * to be adjusted for pointsprite vs normal point behaviour, or
+ * otherwise a special interpolation mode will have to be defined
+ * which matches the required behaviour for point sprites. But -
+ * the latter is not a feature of normal hardware, and as such
+ * probably should be ruled out on that basis.
+ */
+ setup->vprovoke = v0;
+
+ /* setup Z, W */
+ const_pos_coeff(setup, 0, 2);
+ const_pos_coeff(setup, 0, 3);
+
+ for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) {
+ const uint vertSlot = vinfo->attrib[fragSlot].src_index;
+
+ switch (vinfo->attrib[fragSlot].interp_mode) {
+ case INTERP_CONSTANT:
+ /* fall-through */
+ case INTERP_LINEAR:
+ const_coeff(setup, fragSlot, vertSlot);
+ break;
+ case INTERP_PERSPECTIVE:
+ point_persp_coeff(setup, setup->vprovoke, fragSlot, vertSlot);
+ break;
+ case INTERP_POS:
+ setup_fragcoord_coeff(setup, fragSlot);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (lpfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
+ setup->coef.a0[1 + fragSlot][0] = 1.0f - setup->facing;
+ setup->coef.dadx[1 + fragSlot][0] = 0.0;
+ setup->coef.dady[1 + fragSlot][0] = 0.0;
+ }
+ }
+
+
+ if (halfSize <= 0.5 && !round) {
+ /* special case for 1-pixel points */
+ const int ix = ((int) x) & 1;
+ const int iy = ((int) y) & 1;
+ setup->quad[0].input.x0 = (int) x - ix;
+ setup->quad[0].input.y0 = (int) y - iy;
+ setup->quad[0].inout.mask = (1 << ix) << (2 * iy);
+ clip_emit_quad( setup, &setup->quad[0] );
+ }
+ else {
+ if (round) {
+ /* rounded points */
+ const int ixmin = block((int) (x - halfSize));
+ const int ixmax = block((int) (x + halfSize));
+ const int iymin = block((int) (y - halfSize));
+ const int iymax = block((int) (y + halfSize));
+ const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */
+ const float rmax = halfSize + 0.7071F;
+ const float rmin2 = MAX2(0.0F, rmin * rmin);
+ const float rmax2 = rmax * rmax;
+ const float cscale = 1.0F / (rmax2 - rmin2);
+ int ix, iy;
+
+ for (iy = iymin; iy <= iymax; iy += 2) {
+ for (ix = ixmin; ix <= ixmax; ix += 2) {
+ float dx, dy, dist2, cover;
+
+ setup->quad[0].inout.mask = 0x0;
+
+ dx = (ix + 0.5f) - x;
+ dy = (iy + 0.5f) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
+ setup->quad[0].inout.mask |= MASK_TOP_LEFT;
+ }
+
+ dx = (ix + 1.5f) - x;
+ dy = (iy + 0.5f) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
+ setup->quad[0].inout.mask |= MASK_TOP_RIGHT;
+ }
+
+ dx = (ix + 0.5f) - x;
+ dy = (iy + 1.5f) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
+ setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT;
+ }
+
+ dx = (ix + 1.5f) - x;
+ dy = (iy + 1.5f) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
+ setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT;
+ }
+
+ if (setup->quad[0].inout.mask) {
+ setup->quad[0].input.x0 = ix;
+ setup->quad[0].input.y0 = iy;
+ clip_emit_quad( setup, &setup->quad[0] );
+ }
+ }
+ }
+ }
+ else {
+ /* square points */
+ const int xmin = (int) (x + 0.75 - halfSize);
+ const int ymin = (int) (y + 0.25 - halfSize);
+ const int xmax = xmin + (int) size;
+ const int ymax = ymin + (int) size;
+ /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
+ const int ixmin = block(xmin);
+ const int ixmax = block(xmax - 1);
+ const int iymin = block(ymin);
+ const int iymax = block(ymax - 1);
+ int ix, iy;
+
+ /*
+ debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
+ */
+ for (iy = iymin; iy <= iymax; iy += 2) {
+ uint rowMask = 0xf;
+ if (iy < ymin) {
+ /* above the top edge */
+ rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
+ }
+ if (iy + 1 >= ymax) {
+ /* below the bottom edge */
+ rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
+ }
+
+ for (ix = ixmin; ix <= ixmax; ix += 2) {
+ uint mask = rowMask;
+
+ if (ix < xmin) {
+ /* fragment is past left edge of point, turn off left bits */
+ mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
+ }
+ if (ix + 1 >= xmax) {
+ /* past the right edge */
+ mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
+ }
+
+ setup->quad[0].inout.mask = mask;
+ setup->quad[0].input.x0 = ix;
+ setup->quad[0].input.y0 = iy;
+ clip_emit_quad( setup, &setup->quad[0] );
+ }
+ }
+ }
+ }
+}
+
+void llvmpipe_setup_prepare( struct setup_context *setup )
+{
+ struct llvmpipe_context *lp = setup->llvmpipe;
+
+ if (lp->dirty) {
+ llvmpipe_update_derived(lp);
+ }
+
+ if (lp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
+ lp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL &&
+ lp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) {
+ /* we'll do culling */
+ setup->winding = lp->rasterizer->cull_mode;
+ }
+ else {
+ /* 'draw' will do culling */
+ setup->winding = PIPE_WINDING_NONE;
+ }
+}
+
+
+
+void llvmpipe_setup_destroy_context( struct setup_context *setup )
+{
+ align_free( setup );
+}
+
+
+/**
+ * Create a new primitive setup/render stage.
+ */
+struct setup_context *llvmpipe_setup_create_context( struct llvmpipe_context *llvmpipe )
+{
+ struct setup_context *setup;
+ unsigned i;
+
+ setup = align_malloc(sizeof(struct setup_context), 16);
+ if (!setup)
+ return NULL;
+
+ memset(setup, 0, sizeof *setup);
+ setup->llvmpipe = llvmpipe;
+
+ for (i = 0; i < MAX_QUADS; i++) {
+ setup->quad[i].coef = &setup->coef;
+ }
+
+ setup->span.left[0] = 1000000; /* greater than right[0] */
+ setup->span.left[1] = 1000000; /* greater than right[1] */
+
+ return setup;
+}
+
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h
new file mode 100644
index 0000000000..89c43da046
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_setup.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+#ifndef LP_SETUP_H
+#define LP_SETUP_H
+
+struct setup_context;
+struct llvmpipe_context;
+
+void
+llvmpipe_setup_tri( struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4] );
+
+void
+llvmpipe_setup_line(struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4]);
+
+void
+llvmpipe_setup_point( struct setup_context *setup,
+ const float (*v0)[4] );
+
+
+struct setup_context *llvmpipe_setup_create_context( struct llvmpipe_context *llvmpipe );
+void llvmpipe_setup_prepare( struct setup_context *setup );
+void llvmpipe_setup_destroy_context( struct setup_context *setup );
+
+#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h
new file mode 100644
index 0000000000..7b26ce61a3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state.h
@@ -0,0 +1,230 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef LP_STATE_H
+#define LP_STATE_H
+
+#include <llvm-c/Core.h>
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+#include "lp_jit.h"
+#include "lp_bld_sample.h" /* for struct lp_sampler_static_state */
+
+
+#define LP_NEW_VIEWPORT 0x1
+#define LP_NEW_RASTERIZER 0x2
+#define LP_NEW_FS 0x4
+#define LP_NEW_BLEND 0x8
+#define LP_NEW_CLIP 0x10
+#define LP_NEW_SCISSOR 0x20
+#define LP_NEW_STIPPLE 0x40
+#define LP_NEW_FRAMEBUFFER 0x80
+#define LP_NEW_DEPTH_STENCIL_ALPHA 0x100
+#define LP_NEW_CONSTANTS 0x200
+#define LP_NEW_SAMPLER 0x400
+#define LP_NEW_TEXTURE 0x800
+#define LP_NEW_VERTEX 0x1000
+#define LP_NEW_VS 0x2000
+#define LP_NEW_QUERY 0x4000
+
+
+struct tgsi_sampler;
+struct vertex_info;
+struct pipe_context;
+struct llvmpipe_context;
+
+struct lp_fragment_shader;
+
+
+struct lp_fragment_shader_variant_key
+{
+ enum pipe_format zsbuf_format;
+ struct pipe_depth_state depth;
+ struct pipe_alpha_state alpha;
+ struct pipe_blend_state blend;
+
+ struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS];
+};
+
+
+struct lp_fragment_shader_variant
+{
+ struct lp_fragment_shader *shader;
+
+ struct lp_fragment_shader_variant_key key;
+
+ LLVMValueRef function;
+
+ lp_jit_frag_func jit_function;
+
+ struct lp_fragment_shader_variant *next;
+};
+
+
+/**
+ * Subclass of pipe_shader_state (though it doesn't really need to be).
+ *
+ * This is starting to look an awful lot like a quad pipeline stage...
+ */
+struct lp_fragment_shader
+{
+ struct pipe_shader_state base;
+
+ struct tgsi_shader_info info;
+
+ struct lp_fragment_shader_variant *variants;
+
+ struct lp_fragment_shader_variant *current;
+};
+
+
+/** Subclass of pipe_shader_state */
+struct lp_vertex_shader {
+ struct pipe_shader_state shader;
+ struct draw_vertex_shader *draw_data;
+};
+
+
+
+void *
+llvmpipe_create_blend_state(struct pipe_context *,
+ const struct pipe_blend_state *);
+void llvmpipe_bind_blend_state(struct pipe_context *,
+ void *);
+void llvmpipe_delete_blend_state(struct pipe_context *,
+ void *);
+
+void *
+llvmpipe_create_sampler_state(struct pipe_context *,
+ const struct pipe_sampler_state *);
+void llvmpipe_bind_sampler_states(struct pipe_context *, unsigned, void **);
+void llvmpipe_delete_sampler_state(struct pipe_context *, void *);
+
+void *
+llvmpipe_create_depth_stencil_state(struct pipe_context *,
+ const struct pipe_depth_stencil_alpha_state *);
+void llvmpipe_bind_depth_stencil_state(struct pipe_context *, void *);
+void llvmpipe_delete_depth_stencil_state(struct pipe_context *, void *);
+
+void *
+llvmpipe_create_rasterizer_state(struct pipe_context *,
+ const struct pipe_rasterizer_state *);
+void llvmpipe_bind_rasterizer_state(struct pipe_context *, void *);
+void llvmpipe_delete_rasterizer_state(struct pipe_context *, void *);
+
+void llvmpipe_set_framebuffer_state( struct pipe_context *,
+ const struct pipe_framebuffer_state * );
+
+void llvmpipe_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color );
+
+void llvmpipe_set_clip_state( struct pipe_context *,
+ const struct pipe_clip_state * );
+
+void llvmpipe_set_constant_buffer(struct pipe_context *,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf);
+
+void *llvmpipe_create_fs_state(struct pipe_context *,
+ const struct pipe_shader_state *);
+void llvmpipe_bind_fs_state(struct pipe_context *, void *);
+void llvmpipe_delete_fs_state(struct pipe_context *, void *);
+void *llvmpipe_create_vs_state(struct pipe_context *,
+ const struct pipe_shader_state *);
+void llvmpipe_bind_vs_state(struct pipe_context *, void *);
+void llvmpipe_delete_vs_state(struct pipe_context *, void *);
+
+void llvmpipe_set_polygon_stipple( struct pipe_context *,
+ const struct pipe_poly_stipple * );
+
+void llvmpipe_set_scissor_state( struct pipe_context *,
+ const struct pipe_scissor_state * );
+
+void llvmpipe_set_sampler_textures( struct pipe_context *,
+ unsigned num,
+ struct pipe_texture ** );
+
+void llvmpipe_set_viewport_state( struct pipe_context *,
+ const struct pipe_viewport_state * );
+
+void llvmpipe_set_vertex_elements(struct pipe_context *,
+ unsigned count,
+ const struct pipe_vertex_element *);
+
+void llvmpipe_set_vertex_buffers(struct pipe_context *,
+ unsigned count,
+ const struct pipe_vertex_buffer *);
+
+void llvmpipe_update_fs(struct llvmpipe_context *lp);
+
+void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe );
+
+
+boolean llvmpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
+ unsigned start, unsigned count);
+
+boolean llvmpipe_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count);
+boolean
+llvmpipe_draw_range_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned min_index,
+ unsigned max_index,
+ unsigned mode, unsigned start, unsigned count);
+
+void
+llvmpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags);
+
+
+void
+llvmpipe_map_transfers(struct llvmpipe_context *lp);
+
+void
+llvmpipe_unmap_transfers(struct llvmpipe_context *lp);
+
+void
+llvmpipe_map_texture_surfaces(struct llvmpipe_context *lp);
+
+void
+llvmpipe_unmap_texture_surfaces(struct llvmpipe_context *lp);
+
+
+struct vertex_info *
+llvmpipe_get_vertex_info(struct llvmpipe_context *llvmpipe);
+
+struct vertex_info *
+llvmpipe_get_vbuf_vertex_info(struct llvmpipe_context *llvmpipe);
+
+
+#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_state_blend.c b/src/gallium/drivers/llvmpipe/lp_state_blend.c
new file mode 100644
index 0000000000..3f03bd0057
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_blend.c
@@ -0,0 +1,114 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ * @author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_debug_dump.h"
+#include "lp_screen.h"
+#include "lp_context.h"
+#include "lp_state.h"
+
+
+void *
+llvmpipe_create_blend_state(struct pipe_context *pipe,
+ const struct pipe_blend_state *blend)
+{
+ return mem_dup(blend, sizeof(*blend));
+}
+
+void llvmpipe_bind_blend_state( struct pipe_context *pipe,
+ void *blend )
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ llvmpipe->blend = blend;
+
+ llvmpipe->dirty |= LP_NEW_BLEND;
+}
+
+void llvmpipe_delete_blend_state(struct pipe_context *pipe,
+ void *blend)
+{
+ FREE( blend );
+}
+
+
+void llvmpipe_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color )
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+ unsigned i, j;
+
+ memcpy(&llvmpipe->blend_color, blend_color, sizeof *blend_color);
+
+ if(!llvmpipe->jit_context.blend_color)
+ llvmpipe->jit_context.blend_color = align_malloc(4 * 16, 16);
+ for (i = 0; i < 4; ++i) {
+ uint8_t c = float_to_ubyte(blend_color->color[i]);
+ for (j = 0; j < 16; ++j)
+ llvmpipe->jit_context.blend_color[i*4 + j] = c;
+ }
+}
+
+
+/** XXX move someday? Or consolidate all these simple state setters
+ * into one file.
+ */
+
+
+void *
+llvmpipe_create_depth_stencil_state(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *depth_stencil)
+{
+ return mem_dup(depth_stencil, sizeof(*depth_stencil));
+}
+
+void
+llvmpipe_bind_depth_stencil_state(struct pipe_context *pipe,
+ void *depth_stencil)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ llvmpipe->depth_stencil = (const struct pipe_depth_stencil_alpha_state *)depth_stencil;
+
+ if(llvmpipe->depth_stencil)
+ llvmpipe->jit_context.alpha_ref_value = llvmpipe->depth_stencil->alpha.ref_value;
+
+ llvmpipe->dirty |= LP_NEW_DEPTH_STENCIL_ALPHA;
+}
+
+void
+llvmpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth)
+{
+ FREE( depth );
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_clip.c b/src/gallium/drivers/llvmpipe/lp_state_clip.c
new file mode 100644
index 0000000000..df68f27acc
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_clip.c
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "lp_context.h"
+#include "lp_state.h"
+#include "draw/draw_context.h"
+
+
+void llvmpipe_set_clip_state( struct pipe_context *pipe,
+ const struct pipe_clip_state *clip )
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ /* pass the clip state to the draw module */
+ draw_set_clip_state(llvmpipe->draw, clip);
+}
+
+
+void llvmpipe_set_viewport_state( struct pipe_context *pipe,
+ const struct pipe_viewport_state *viewport )
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ /* pass the viewport info to the draw module */
+ draw_set_viewport_state(llvmpipe->draw, viewport);
+
+ llvmpipe->viewport = *viewport; /* struct copy */
+ llvmpipe->dirty |= LP_NEW_VIEWPORT;
+}
+
+
+void llvmpipe_set_scissor_state( struct pipe_context *pipe,
+ const struct pipe_scissor_state *scissor )
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ draw_flush(llvmpipe->draw);
+
+ llvmpipe->scissor = *scissor; /* struct copy */
+ llvmpipe->dirty |= LP_NEW_SCISSOR;
+}
+
+
+void llvmpipe_set_polygon_stipple( struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple )
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ draw_flush(llvmpipe->draw);
+
+ llvmpipe->poly_stipple = *stipple; /* struct copy */
+ llvmpipe->dirty |= LP_NEW_STIPPLE;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
new file mode 100644
index 0000000000..e87976b9f3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -0,0 +1,260 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_private.h"
+#include "lp_context.h"
+#include "lp_screen.h"
+#include "lp_tex_cache.h"
+#include "lp_state.h"
+
+
+/**
+ * Mark the current vertex layout as "invalid".
+ * We'll validate the vertex layout later, when we start to actually
+ * render a point or line or tri.
+ */
+static void
+invalidate_vertex_layout(struct llvmpipe_context *llvmpipe)
+{
+ llvmpipe->vertex_info.num_attribs = 0;
+}
+
+
+/**
+ * The vertex info describes how to convert the post-transformed vertices
+ * (simple float[][4]) used by the 'draw' module into vertices for
+ * rasterization.
+ *
+ * This function validates the vertex layout and returns a pointer to a
+ * vertex_info object.
+ */
+struct vertex_info *
+llvmpipe_get_vertex_info(struct llvmpipe_context *llvmpipe)
+{
+ struct vertex_info *vinfo = &llvmpipe->vertex_info;
+
+ if (vinfo->num_attribs == 0) {
+ /* compute vertex layout now */
+ const struct lp_fragment_shader *lpfs = llvmpipe->fs;
+ const enum interp_mode colorInterp
+ = llvmpipe->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
+ uint i;
+
+ if (llvmpipe->vbuf) {
+ /* if using the post-transform vertex buffer, tell draw_vbuf to
+ * simply emit the whole post-xform vertex as-is:
+ */
+ struct vertex_info *vinfo_vbuf = &llvmpipe->vertex_info_vbuf;
+ const uint num = draw_num_vs_outputs(llvmpipe->draw);
+ uint i;
+
+ /* No longer any need to try and emit draw vertex_header info.
+ */
+ vinfo_vbuf->num_attribs = 0;
+ for (i = 0; i < num; i++) {
+ draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
+ }
+ draw_compute_vertex_size(vinfo_vbuf);
+ }
+
+ /*
+ * Loop over fragment shader inputs, searching for the matching output
+ * from the vertex shader.
+ */
+ vinfo->num_attribs = 0;
+ for (i = 0; i < lpfs->info.num_inputs; i++) {
+ int src;
+ switch (lpfs->info.input_semantic_name[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ src = draw_find_vs_output(llvmpipe->draw,
+ TGSI_SEMANTIC_POSITION, 0);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_POS, src);
+ break;
+
+ case TGSI_SEMANTIC_COLOR:
+ src = draw_find_vs_output(llvmpipe->draw, TGSI_SEMANTIC_COLOR,
+ lpfs->info.input_semantic_index[i]);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
+ break;
+
+ case TGSI_SEMANTIC_FOG:
+ src = draw_find_vs_output(llvmpipe->draw, TGSI_SEMANTIC_FOG, 0);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ break;
+
+ case TGSI_SEMANTIC_GENERIC:
+ case TGSI_SEMANTIC_FACE:
+ /* this includes texcoords and varying vars */
+ src = draw_find_vs_output(llvmpipe->draw, TGSI_SEMANTIC_GENERIC,
+ lpfs->info.input_semantic_index[i]);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ break;
+
+ default:
+ assert(0);
+ }
+ }
+
+ llvmpipe->psize_slot = draw_find_vs_output(llvmpipe->draw,
+ TGSI_SEMANTIC_PSIZE, 0);
+ if (llvmpipe->psize_slot > 0) {
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
+ llvmpipe->psize_slot);
+ }
+
+ draw_compute_vertex_size(vinfo);
+ }
+
+ return vinfo;
+}
+
+
+/**
+ * Called from vbuf module.
+ *
+ * Note that there's actually two different vertex layouts in llvmpipe.
+ *
+ * The normal one is computed in llvmpipe_get_vertex_info() above and is
+ * used by the point/line/tri "setup" code.
+ *
+ * The other one (this one) is only used by the vbuf module (which is
+ * not normally used by default but used in testing). For the vbuf module,
+ * we basically want to pass-through the draw module's vertex layout as-is.
+ * When the llvmpipe vbuf code begins drawing, the normal vertex layout
+ * will come into play again.
+ */
+struct vertex_info *
+llvmpipe_get_vbuf_vertex_info(struct llvmpipe_context *llvmpipe)
+{
+ (void) llvmpipe_get_vertex_info(llvmpipe);
+ return &llvmpipe->vertex_info_vbuf;
+}
+
+
+/**
+ * Recompute cliprect from scissor bounds, scissor enable and surface size.
+ */
+static void
+compute_cliprect(struct llvmpipe_context *lp)
+{
+ /* LP_NEW_FRAMEBUFFER
+ */
+ uint surfWidth = lp->framebuffer.width;
+ uint surfHeight = lp->framebuffer.height;
+
+ /* LP_NEW_RASTERIZER
+ */
+ if (lp->rasterizer->scissor) {
+
+ /* LP_NEW_SCISSOR
+ *
+ * clip to scissor rect:
+ */
+ lp->cliprect.minx = MAX2(lp->scissor.minx, 0);
+ lp->cliprect.miny = MAX2(lp->scissor.miny, 0);
+ lp->cliprect.maxx = MIN2(lp->scissor.maxx, surfWidth);
+ lp->cliprect.maxy = MIN2(lp->scissor.maxy, surfHeight);
+ }
+ else {
+ /* clip to surface bounds */
+ lp->cliprect.minx = 0;
+ lp->cliprect.miny = 0;
+ lp->cliprect.maxx = surfWidth;
+ lp->cliprect.maxy = surfHeight;
+ }
+}
+
+
+static void
+update_tgsi_samplers( struct llvmpipe_context *llvmpipe )
+{
+ unsigned i;
+
+ /* vertex shader samplers */
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ llvmpipe->tgsi.vert_samplers[i].sampler = llvmpipe->sampler[i];
+ llvmpipe->tgsi.vert_samplers[i].texture = llvmpipe->texture[i];
+ llvmpipe->tgsi.frag_samplers[i].base.get_samples = lp_get_samples;
+ }
+
+ /* fragment shader samplers */
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ llvmpipe->tgsi.frag_samplers[i].sampler = llvmpipe->sampler[i];
+ llvmpipe->tgsi.frag_samplers[i].texture = llvmpipe->texture[i];
+ llvmpipe->tgsi.frag_samplers[i].base.get_samples = lp_get_samples;
+ }
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ lp_tex_tile_cache_validate_texture( llvmpipe->tex_cache[i] );
+ }
+
+ llvmpipe->jit_context.samplers = (struct tgsi_sampler **)llvmpipe->tgsi.frag_samplers_list;
+}
+
+/* Hopefully this will remain quite simple, otherwise need to pull in
+ * something like the state tracker mechanism.
+ */
+void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
+{
+ struct llvmpipe_screen *lp_screen = llvmpipe_screen(llvmpipe->pipe.screen);
+
+ /* Check for updated textures.
+ */
+ if (llvmpipe->tex_timestamp != lp_screen->timestamp) {
+ llvmpipe->tex_timestamp = lp_screen->timestamp;
+ llvmpipe->dirty |= LP_NEW_TEXTURE;
+ }
+
+ if (llvmpipe->dirty & (LP_NEW_SAMPLER |
+ LP_NEW_TEXTURE))
+ update_tgsi_samplers( llvmpipe );
+
+ if (llvmpipe->dirty & (LP_NEW_RASTERIZER |
+ LP_NEW_FS |
+ LP_NEW_VS))
+ invalidate_vertex_layout( llvmpipe );
+
+ if (llvmpipe->dirty & (LP_NEW_SCISSOR |
+ LP_NEW_RASTERIZER |
+ LP_NEW_FRAMEBUFFER))
+ compute_cliprect(llvmpipe);
+
+ if (llvmpipe->dirty & (LP_NEW_FS |
+ LP_NEW_BLEND |
+ LP_NEW_DEPTH_STENCIL_ALPHA |
+ LP_NEW_SAMPLER |
+ LP_NEW_TEXTURE))
+ llvmpipe_update_fs( llvmpipe );
+
+
+ llvmpipe->dirty = 0;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
new file mode 100644
index 0000000000..618cf1ffb8
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -0,0 +1,762 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Code generate the whole fragment pipeline.
+ *
+ * The fragment pipeline consists of the following stages:
+ * - stipple (TBI)
+ * - early depth test
+ * - fragment shader
+ * - alpha test
+ * - depth/stencil test (stencil TBI)
+ * - blending
+ *
+ * This file has only the glue to assembly the fragment pipeline. The actual
+ * plumbing of converting Gallium state into LLVM IR is done elsewhere, in the
+ * lp_bld_*.[ch] files, and in a complete generic and reusable way. Here we
+ * muster the LLVM JIT execution engine to create a function that follows an
+ * established binary interface and that can be called from C directly.
+ *
+ * A big source of complexity here is that we often want to run different
+ * stages with different precisions and data types and precisions. For example,
+ * the fragment shader needs typically to be done in floats, but the
+ * depth/stencil test and blending is better done in the type that most closely
+ * matches the depth/stencil and color buffer respectively.
+ *
+ * Since the width of a SIMD vector register stays the same regardless of the
+ * element type, different types imply different number of elements, so we must
+ * code generate more instances of the stages with larger types to be able to
+ * feed/consume the stages with smaller types.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "util/u_format.h"
+#include "util/u_debug_dump.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_scan.h"
+#include "tgsi/tgsi_parse.h"
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_conv.h"
+#include "lp_bld_intr.h"
+#include "lp_bld_logic.h"
+#include "lp_bld_depth.h"
+#include "lp_bld_interp.h"
+#include "lp_bld_tgsi.h"
+#include "lp_bld_alpha.h"
+#include "lp_bld_blend.h"
+#include "lp_bld_swizzle.h"
+#include "lp_bld_flow.h"
+#include "lp_bld_debug.h"
+#include "lp_screen.h"
+#include "lp_context.h"
+#include "lp_state.h"
+#include "lp_quad.h"
+#include "lp_tex_sample.h"
+
+
+static const unsigned char quad_offset_x[4] = {0, 1, 0, 1};
+static const unsigned char quad_offset_y[4] = {0, 0, 1, 1};
+
+
+/*
+ * Derive from the quad's upper left scalar coordinates the coordinates for
+ * all other quad pixels
+ */
+static void
+generate_pos0(LLVMBuilderRef builder,
+ LLVMValueRef x,
+ LLVMValueRef y,
+ LLVMValueRef *x0,
+ LLVMValueRef *y0)
+{
+ LLVMTypeRef int_elem_type = LLVMInt32Type();
+ LLVMTypeRef int_vec_type = LLVMVectorType(int_elem_type, QUAD_SIZE);
+ LLVMTypeRef elem_type = LLVMFloatType();
+ LLVMTypeRef vec_type = LLVMVectorType(elem_type, QUAD_SIZE);
+ LLVMValueRef x_offsets[QUAD_SIZE];
+ LLVMValueRef y_offsets[QUAD_SIZE];
+ unsigned i;
+
+ x = lp_build_broadcast(builder, int_vec_type, x);
+ y = lp_build_broadcast(builder, int_vec_type, y);
+
+ for(i = 0; i < QUAD_SIZE; ++i) {
+ x_offsets[i] = LLVMConstInt(int_elem_type, quad_offset_x[i], 0);
+ y_offsets[i] = LLVMConstInt(int_elem_type, quad_offset_y[i], 0);
+ }
+
+ x = LLVMBuildAdd(builder, x, LLVMConstVector(x_offsets, QUAD_SIZE), "");
+ y = LLVMBuildAdd(builder, y, LLVMConstVector(y_offsets, QUAD_SIZE), "");
+
+ *x0 = LLVMBuildSIToFP(builder, x, vec_type, "");
+ *y0 = LLVMBuildSIToFP(builder, y, vec_type, "");
+}
+
+
+/**
+ * Generate the depth test.
+ */
+static void
+generate_depth(LLVMBuilderRef builder,
+ const struct lp_fragment_shader_variant_key *key,
+ union lp_type src_type,
+ struct lp_build_mask_context *mask,
+ LLVMValueRef src,
+ LLVMValueRef dst_ptr)
+{
+ const struct util_format_description *format_desc;
+ union lp_type dst_type;
+
+ if(!key->depth.enabled)
+ return;
+
+ format_desc = util_format_description(key->zsbuf_format);
+ assert(format_desc);
+
+ /* Pick the depth type. */
+ dst_type = lp_depth_type(format_desc, src_type.width*src_type.length);
+
+ /* FIXME: Cope with a depth test type with a different bit width. */
+ assert(dst_type.width == src_type.width);
+ assert(dst_type.length == src_type.length);
+
+#if 1
+ src = lp_build_clamped_float_to_unsigned_norm(builder,
+ src_type,
+ dst_type.width,
+ src);
+#else
+ lp_build_conv(builder, src_type, dst_type, &src, 1, &src, 1);
+#endif
+
+ lp_build_depth_test(builder,
+ &key->depth,
+ dst_type,
+ format_desc,
+ mask,
+ src,
+ dst_ptr);
+}
+
+
+/**
+ * Generate the fragment shader, depth/stencil test, and alpha tests.
+ */
+static void
+generate_fs(struct llvmpipe_context *lp,
+ struct lp_fragment_shader *shader,
+ const struct lp_fragment_shader_variant_key *key,
+ LLVMBuilderRef builder,
+ union lp_type type,
+ LLVMValueRef context_ptr,
+ unsigned i,
+ const struct lp_build_interp_soa_context *interp,
+ struct lp_build_sampler_soa *sampler,
+ LLVMValueRef *pmask,
+ LLVMValueRef *color,
+ LLVMValueRef depth_ptr)
+{
+ const struct tgsi_token *tokens = shader->base.tokens;
+ LLVMTypeRef elem_type;
+ LLVMTypeRef vec_type;
+ LLVMTypeRef int_vec_type;
+ LLVMValueRef consts_ptr;
+ LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
+ LLVMValueRef z = interp->pos[2];
+ struct lp_build_flow_context *flow;
+ struct lp_build_mask_context mask;
+ boolean early_depth_test;
+ unsigned attrib;
+ unsigned chan;
+
+ elem_type = lp_build_elem_type(type);
+ vec_type = lp_build_vec_type(type);
+ int_vec_type = lp_build_int_vec_type(type);
+
+ consts_ptr = lp_jit_context_constants(builder, context_ptr);
+
+ flow = lp_build_flow_create(builder);
+
+ memset(outputs, 0, sizeof outputs);
+
+ lp_build_flow_scope_begin(flow);
+
+ /* Declare the color and z variables */
+ for(chan = 0; chan < NUM_CHANNELS; ++chan) {
+ color[chan] = LLVMGetUndef(vec_type);
+ lp_build_flow_scope_declare(flow, &color[chan]);
+ }
+ lp_build_flow_scope_declare(flow, &z);
+
+ lp_build_mask_begin(&mask, flow, type, *pmask);
+
+ early_depth_test =
+ key->depth.enabled &&
+ !key->alpha.enabled &&
+ !shader->info.uses_kill &&
+ !shader->info.writes_z;
+
+ if(early_depth_test)
+ generate_depth(builder, key,
+ type, &mask,
+ z, depth_ptr);
+
+ lp_build_tgsi_soa(builder, tokens, type, &mask,
+ consts_ptr, interp->pos, interp->inputs,
+ outputs, sampler);
+
+ for (attrib = 0; attrib < shader->info.num_outputs; ++attrib) {
+ for(chan = 0; chan < NUM_CHANNELS; ++chan) {
+ if(outputs[attrib][chan]) {
+ lp_build_name(outputs[attrib][chan], "output%u.%u.%c", i, attrib, "xyzw"[chan]);
+
+ switch (shader->info.output_semantic_name[attrib]) {
+ case TGSI_SEMANTIC_COLOR:
+ {
+ unsigned cbuf = shader->info.output_semantic_index[attrib];
+
+ lp_build_name(outputs[attrib][chan], "color%u.%u.%c", i, attrib, "rgba"[chan]);
+
+ /* Alpha test */
+ /* XXX: should the alpha reference value be passed separately? */
+ if(cbuf == 0 && chan == 3) {
+ LLVMValueRef alpha = outputs[attrib][chan];
+ LLVMValueRef alpha_ref_value;
+ alpha_ref_value = lp_jit_context_alpha_ref_value(builder, context_ptr);
+ alpha_ref_value = lp_build_broadcast(builder, vec_type, alpha_ref_value);
+ lp_build_alpha_test(builder, &key->alpha, type,
+ &mask, alpha, alpha_ref_value);
+ }
+
+ if(cbuf == 0)
+ color[chan] = outputs[attrib][chan];
+
+ break;
+ }
+
+ case TGSI_SEMANTIC_POSITION:
+ if(chan == 2)
+ z = outputs[attrib][chan];
+ break;
+ }
+ }
+ }
+ }
+
+ if(!early_depth_test)
+ generate_depth(builder, key,
+ type, &mask,
+ z, depth_ptr);
+
+ lp_build_mask_end(&mask);
+
+ lp_build_flow_scope_end(flow);
+
+ lp_build_flow_destroy(flow);
+
+ *pmask = mask.value;
+
+}
+
+
+/**
+ * Generate color blending and color output.
+ */
+static void
+generate_blend(const struct pipe_blend_state *blend,
+ LLVMBuilderRef builder,
+ union lp_type type,
+ LLVMValueRef context_ptr,
+ LLVMValueRef mask,
+ LLVMValueRef *src,
+ LLVMValueRef dst_ptr)
+{
+ struct lp_build_context bld;
+ struct lp_build_flow_context *flow;
+ struct lp_build_mask_context mask_ctx;
+ LLVMTypeRef vec_type;
+ LLVMTypeRef int_vec_type;
+ LLVMValueRef const_ptr;
+ LLVMValueRef con[4];
+ LLVMValueRef dst[4];
+ LLVMValueRef res[4];
+ unsigned chan;
+
+ lp_build_context_init(&bld, builder, type);
+
+ flow = lp_build_flow_create(builder);
+ lp_build_mask_begin(&mask_ctx, flow, type, mask);
+
+ vec_type = lp_build_vec_type(type);
+ int_vec_type = lp_build_int_vec_type(type);
+
+ const_ptr = lp_jit_context_blend_color(builder, context_ptr);
+ const_ptr = LLVMBuildBitCast(builder, const_ptr,
+ LLVMPointerType(vec_type, 0), "");
+
+ for(chan = 0; chan < 4; ++chan) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0);
+ con[chan] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), "");
+
+ dst[chan] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dst_ptr, &index, 1, ""), "");
+
+ lp_build_name(con[chan], "con.%c", "rgba"[chan]);
+ lp_build_name(dst[chan], "dst.%c", "rgba"[chan]);
+ }
+
+ lp_build_blend_soa(builder, blend, type, src, dst, con, res);
+
+ for(chan = 0; chan < 4; ++chan) {
+ if(blend->colormask & (1 << chan)) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0);
+ lp_build_name(res[chan], "res.%c", "rgba"[chan]);
+ res[chan] = lp_build_select(&bld, mask, res[chan], dst[chan]);
+ LLVMBuildStore(builder, res[chan], LLVMBuildGEP(builder, dst_ptr, &index, 1, ""));
+ }
+ }
+
+ lp_build_mask_end(&mask_ctx);
+ lp_build_flow_destroy(flow);
+}
+
+
+/**
+ * Generate the runtime callable function for the whole fragment pipeline.
+ */
+static struct lp_fragment_shader_variant *
+generate_fragment(struct llvmpipe_context *lp,
+ struct lp_fragment_shader *shader,
+ const struct lp_fragment_shader_variant_key *key)
+{
+ struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen);
+ struct lp_fragment_shader_variant *variant;
+ union lp_type fs_type;
+ union lp_type blend_type;
+ LLVMTypeRef fs_elem_type;
+ LLVMTypeRef fs_vec_type;
+ LLVMTypeRef fs_int_vec_type;
+ LLVMTypeRef blend_vec_type;
+ LLVMTypeRef blend_int_vec_type;
+ LLVMTypeRef arg_types[9];
+ LLVMTypeRef func_type;
+ LLVMValueRef context_ptr;
+ LLVMValueRef x;
+ LLVMValueRef y;
+ LLVMValueRef a0_ptr;
+ LLVMValueRef dadx_ptr;
+ LLVMValueRef dady_ptr;
+ LLVMValueRef mask_ptr;
+ LLVMValueRef color_ptr;
+ LLVMValueRef depth_ptr;
+ LLVMBasicBlockRef block;
+ LLVMBuilderRef builder;
+ LLVMValueRef x0;
+ LLVMValueRef y0;
+ struct lp_build_sampler_soa *sampler;
+ struct lp_build_interp_soa_context interp;
+ LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH];
+ LLVMValueRef fs_out_color[NUM_CHANNELS][LP_MAX_VECTOR_LENGTH];
+ LLVMValueRef blend_mask;
+ LLVMValueRef blend_in_color[NUM_CHANNELS];
+ unsigned num_fs;
+ unsigned i;
+ unsigned chan;
+
+#ifdef DEBUG
+ tgsi_dump(shader->base.tokens, 0);
+ if(key->depth.enabled) {
+ debug_printf("depth.func = %s\n", debug_dump_func(key->depth.func, TRUE));
+ debug_printf("depth.writemask = %u\n", key->depth.writemask);
+ debug_printf("depth.occlusion_count = %u\n", key->depth.occlusion_count);
+ }
+ if(key->alpha.enabled) {
+ debug_printf("alpha.func = %s\n", debug_dump_func(key->alpha.func, TRUE));
+ debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value);
+ }
+ if(key->blend.logicop_enable) {
+ debug_printf("blend.logicop_func = %u\n", key->blend.logicop_func);
+ }
+ else if(key->blend.blend_enable) {
+ debug_printf("blend.rgb_func = %s\n", debug_dump_blend_func (key->blend.rgb_func, TRUE));
+ debug_printf("rgb_src_factor = %s\n", debug_dump_blend_factor(key->blend.rgb_src_factor, TRUE));
+ debug_printf("rgb_dst_factor = %s\n", debug_dump_blend_factor(key->blend.rgb_dst_factor, TRUE));
+ debug_printf("alpha_func = %s\n", debug_dump_blend_func (key->blend.alpha_func, TRUE));
+ debug_printf("alpha_src_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_src_factor, TRUE));
+ debug_printf("alpha_dst_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_dst_factor, TRUE));
+ }
+ debug_printf("blend.colormask = 0x%x\n", key->blend.colormask);
+#endif
+
+ variant = CALLOC_STRUCT(lp_fragment_shader_variant);
+ if(!variant)
+ return NULL;
+
+ variant->shader = shader;
+ memcpy(&variant->key, key, sizeof *key);
+
+ /* TODO: actually pick these based on the fs and color buffer
+ * characteristics. */
+
+ fs_type.value = 0;
+ fs_type.floating = TRUE; /* floating point values */
+ fs_type.sign = TRUE; /* values are signed */
+ fs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */
+ fs_type.width = 32; /* 32-bit float */
+ fs_type.length = 4; /* 4 element per vector */
+ num_fs = 4;
+
+ blend_type.value = 0;
+ blend_type.floating = FALSE; /* values are integers */
+ blend_type.sign = FALSE; /* values are unsigned */
+ blend_type.norm = TRUE; /* values are in [0,1] or [-1,1] */
+ blend_type.width = 8; /* 8-bit ubyte values */
+ blend_type.length = 16; /* 16 elements per vector */
+
+ /*
+ * Generate the function prototype. Any change here must be reflected in
+ * lp_jit.h's lp_jit_frag_func function pointer type, and vice-versa.
+ */
+
+ fs_elem_type = lp_build_elem_type(fs_type);
+ fs_vec_type = lp_build_vec_type(fs_type);
+ fs_int_vec_type = lp_build_int_vec_type(fs_type);
+
+ blend_vec_type = lp_build_vec_type(blend_type);
+ blend_int_vec_type = lp_build_int_vec_type(blend_type);
+
+ arg_types[0] = screen->context_ptr_type; /* context */
+ arg_types[1] = LLVMInt32Type(); /* x */
+ arg_types[2] = LLVMInt32Type(); /* y */
+ arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */
+ arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */
+ arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */
+ arg_types[6] = LLVMPointerType(fs_int_vec_type, 0); /* mask */
+ arg_types[7] = LLVMPointerType(blend_vec_type, 0); /* color */
+ arg_types[8] = LLVMPointerType(fs_int_vec_type, 0); /* depth */
+
+ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
+
+ variant->function = LLVMAddFunction(screen->module, "shader", func_type);
+ LLVMSetFunctionCallConv(variant->function, LLVMCCallConv);
+ for(i = 0; i < Elements(arg_types); ++i)
+ if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind)
+ LLVMAddAttribute(LLVMGetParam(variant->function, i), LLVMNoAliasAttribute);
+
+ context_ptr = LLVMGetParam(variant->function, 0);
+ x = LLVMGetParam(variant->function, 1);
+ y = LLVMGetParam(variant->function, 2);
+ a0_ptr = LLVMGetParam(variant->function, 3);
+ dadx_ptr = LLVMGetParam(variant->function, 4);
+ dady_ptr = LLVMGetParam(variant->function, 5);
+ mask_ptr = LLVMGetParam(variant->function, 6);
+ color_ptr = LLVMGetParam(variant->function, 7);
+ depth_ptr = LLVMGetParam(variant->function, 8);
+
+ lp_build_name(context_ptr, "context");
+ lp_build_name(x, "x");
+ lp_build_name(y, "y");
+ lp_build_name(a0_ptr, "a0");
+ lp_build_name(dadx_ptr, "dadx");
+ lp_build_name(dady_ptr, "dady");
+ lp_build_name(mask_ptr, "mask");
+ lp_build_name(color_ptr, "color");
+ lp_build_name(depth_ptr, "depth");
+
+ /*
+ * Function body
+ */
+
+ block = LLVMAppendBasicBlock(variant->function, "entry");
+ builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(builder, block);
+
+ generate_pos0(builder, x, y, &x0, &y0);
+
+ lp_build_interp_soa_init(&interp, shader->base.tokens, builder, fs_type,
+ a0_ptr, dadx_ptr, dady_ptr,
+ x0, y0, 2, 0);
+
+#if 0
+ /* C texture sampling */
+ sampler = lp_c_sampler_soa_create(context_ptr);
+#else
+ /* code generated texture sampling */
+ sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr);
+#endif
+
+ for(i = 0; i < num_fs; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ LLVMValueRef out_color[NUM_CHANNELS];
+ LLVMValueRef depth_ptr_i;
+
+ if(i != 0)
+ lp_build_interp_soa_update(&interp);
+
+ fs_mask[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, mask_ptr, &index, 1, ""), "");
+ depth_ptr_i = LLVMBuildGEP(builder, depth_ptr, &index, 1, "");
+
+ generate_fs(lp, shader, key,
+ builder,
+ fs_type,
+ context_ptr,
+ i,
+ &interp,
+ sampler,
+ &fs_mask[i],
+ out_color,
+ depth_ptr_i);
+
+ for(chan = 0; chan < NUM_CHANNELS; ++chan)
+ fs_out_color[chan][i] = out_color[chan];
+ }
+
+ sampler->destroy(sampler);
+
+ /*
+ * Convert the fs's output color and mask to fit to the blending type.
+ */
+
+ for(chan = 0; chan < NUM_CHANNELS; ++chan) {
+ lp_build_conv(builder, fs_type, blend_type,
+ fs_out_color[chan], num_fs,
+ &blend_in_color[chan], 1);
+ lp_build_name(blend_in_color[chan], "color.%c", "rgba"[chan]);
+
+ }
+
+ lp_build_conv_mask(builder, fs_type, blend_type,
+ fs_mask, num_fs,
+ &blend_mask, 1);
+
+ /*
+ * Blending.
+ */
+
+ generate_blend(&key->blend,
+ builder,
+ blend_type,
+ context_ptr,
+ blend_mask,
+ blend_in_color,
+ color_ptr);
+
+ LLVMBuildRetVoid(builder);
+
+ LLVMDisposeBuilder(builder);
+
+ /*
+ * Translate the LLVM IR into machine code.
+ */
+
+ LLVMRunFunctionPassManager(screen->pass, variant->function);
+
+#ifdef DEBUG
+ LLVMDumpValue(variant->function);
+ debug_printf("\n");
+#endif
+
+ if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) {
+ LLVMDumpValue(variant->function);
+ abort();
+ }
+
+ variant->jit_function = (lp_jit_frag_func)LLVMGetPointerToGlobal(screen->engine, variant->function);
+
+#ifdef DEBUG
+ lp_disassemble(variant->jit_function);
+#endif
+
+ variant->next = shader->variants;
+ shader->variants = variant;
+
+ return variant;
+}
+
+
+void *
+llvmpipe_create_fs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct lp_fragment_shader *shader;
+
+ shader = CALLOC_STRUCT(lp_fragment_shader);
+ if (!shader)
+ return NULL;
+
+ /* get/save the summary info for this shader */
+ tgsi_scan_shader(templ->tokens, &shader->info);
+
+ /* we need to keep a local copy of the tokens */
+ shader->base.tokens = tgsi_dup_tokens(templ->tokens);
+
+ return shader;
+}
+
+
+void
+llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ llvmpipe->fs = (struct lp_fragment_shader *) fs;
+
+ llvmpipe->dirty |= LP_NEW_FS;
+}
+
+
+void
+llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+ struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
+ struct lp_fragment_shader *shader = fs;
+ struct lp_fragment_shader_variant *variant;
+
+ assert(fs != llvmpipe->fs);
+
+ variant = shader->variants;
+ while(variant) {
+ struct lp_fragment_shader_variant *next = variant->next;
+
+ if(variant->function) {
+ if(variant->jit_function)
+ LLVMFreeMachineCodeForFunction(screen->engine, variant->function);
+ LLVMDeleteFunction(variant->function);
+ }
+
+ FREE(variant);
+
+ variant = next;
+ }
+
+ FREE((void *) shader->base.tokens);
+ FREE(shader);
+}
+
+
+
+void
+llvmpipe_set_constant_buffer(struct pipe_context *pipe,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ assert(shader < PIPE_SHADER_TYPES);
+ assert(index == 0);
+
+ /* note: reference counting */
+ pipe_buffer_reference(&llvmpipe->constants[shader].buffer,
+ buf ? buf->buffer : NULL);
+
+ llvmpipe->dirty |= LP_NEW_CONSTANTS;
+}
+
+
+/**
+ * We need to generate several variants of the fragment pipeline to match
+ * all the combinations of the contributing state atoms.
+ *
+ * TODO: there is actually no reason to tie this to context state -- the
+ * generated code could be cached globally in the screen.
+ */
+static void
+make_variant_key(struct llvmpipe_context *lp,
+ struct lp_fragment_shader *shader,
+ struct lp_fragment_shader_variant_key *key)
+{
+ unsigned i;
+
+ memset(key, 0, sizeof *key);
+
+ if(lp->framebuffer.zsbuf &&
+ lp->depth_stencil->depth.enabled) {
+ key->zsbuf_format = lp->framebuffer.zsbuf->format;
+ memcpy(&key->depth, &lp->depth_stencil->depth, sizeof key->depth);
+ }
+
+ key->alpha.enabled = lp->depth_stencil->alpha.enabled;
+ if(key->alpha.enabled)
+ key->alpha.func = lp->depth_stencil->alpha.func;
+ /* alpha.ref_value is passed in jit_context */
+
+ if(lp->framebuffer.cbufs[0]) {
+ const struct util_format_description *format_desc;
+ unsigned chan;
+
+ memcpy(&key->blend, lp->blend, sizeof key->blend);
+
+ format_desc = util_format_description(lp->framebuffer.cbufs[0]->format);
+ assert(format_desc->layout == UTIL_FORMAT_COLORSPACE_RGB ||
+ format_desc->layout == UTIL_FORMAT_COLORSPACE_SRGB);
+
+ /* mask out color channels not present in the color buffer */
+ for(chan = 0; chan < 4; ++chan) {
+ enum util_format_swizzle swizzle = format_desc->swizzle[chan];
+ if(swizzle > 4)
+ key->blend.colormask &= ~(1 << chan);
+ }
+ }
+
+ for(i = 0; i < PIPE_MAX_SAMPLERS; ++i)
+ if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i))
+ lp_sampler_static_state(&key->sampler[i], lp->texture[i], lp->sampler[i]);
+}
+
+
+void
+llvmpipe_update_fs(struct llvmpipe_context *lp)
+{
+ struct lp_fragment_shader *shader = lp->fs;
+ struct lp_fragment_shader_variant_key key;
+ struct lp_fragment_shader_variant *variant;
+
+ make_variant_key(lp, shader, &key);
+
+ variant = shader->variants;
+ while(variant) {
+ if(memcmp(&variant->key, &key, sizeof key) == 0)
+ break;
+
+ variant = variant->next;
+ }
+
+ if(!variant)
+ variant = generate_fragment(lp, shader, &key);
+
+ shader->current = variant;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
new file mode 100644
index 0000000000..4561c6b845
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
@@ -0,0 +1,62 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "lp_context.h"
+#include "lp_state.h"
+#include "draw/draw_context.h"
+
+
+
+void *
+llvmpipe_create_rasterizer_state(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *rast)
+{
+ return mem_dup(rast, sizeof(*rast));
+}
+
+void llvmpipe_bind_rasterizer_state(struct pipe_context *pipe,
+ void *setup)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ /* pass-through to draw module */
+ draw_set_rasterizer_state(llvmpipe->draw, setup);
+
+ llvmpipe->rasterizer = (struct pipe_rasterizer_state *)setup;
+
+ llvmpipe->dirty |= LP_NEW_RASTERIZER;
+}
+
+void llvmpipe_delete_rasterizer_state(struct pipe_context *pipe,
+ void *rasterizer)
+{
+ FREE( rasterizer );
+}
+
+
diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
new file mode 100644
index 0000000000..c69d90c723
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
@@ -0,0 +1,127 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors:
+ * Brian Paul
+ */
+
+#include "util/u_memory.h"
+
+#include "draw/draw_context.h"
+
+#include "lp_context.h"
+#include "lp_context.h"
+#include "lp_state.h"
+#include "lp_texture.h"
+#include "lp_tex_cache.h"
+#include "draw/draw_context.h"
+
+
+
+void *
+llvmpipe_create_sampler_state(struct pipe_context *pipe,
+ const struct pipe_sampler_state *sampler)
+{
+ return mem_dup(sampler, sizeof(*sampler));
+}
+
+
+void
+llvmpipe_bind_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **sampler)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+ unsigned i;
+
+ assert(num <= PIPE_MAX_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == llvmpipe->num_samplers &&
+ !memcmp(llvmpipe->sampler, sampler, num * sizeof(void *)))
+ return;
+
+ draw_flush(llvmpipe->draw);
+
+ for (i = 0; i < num; ++i)
+ llvmpipe->sampler[i] = sampler[i];
+ for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
+ llvmpipe->sampler[i] = NULL;
+
+ llvmpipe->num_samplers = num;
+
+ llvmpipe->dirty |= LP_NEW_SAMPLER;
+}
+
+
+void
+llvmpipe_set_sampler_textures(struct pipe_context *pipe,
+ unsigned num, struct pipe_texture **texture)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+ uint i;
+
+ assert(num <= PIPE_MAX_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == llvmpipe->num_textures &&
+ !memcmp(llvmpipe->texture, texture, num * sizeof(struct pipe_texture *)))
+ return;
+
+ draw_flush(llvmpipe->draw);
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ struct pipe_texture *tex = i < num ? texture[i] : NULL;
+
+ pipe_texture_reference(&llvmpipe->texture[i], tex);
+ lp_tex_tile_cache_set_texture(llvmpipe->tex_cache[i], tex);
+
+ if(tex) {
+ struct llvmpipe_texture *lp_tex = llvmpipe_texture(tex);
+ struct lp_jit_texture *jit_tex = &llvmpipe->jit_context.textures[i];
+ jit_tex->width = tex->width[0];
+ jit_tex->height = tex->height[0];
+ jit_tex->stride = lp_tex->stride[0];
+ if(!lp_tex->dt)
+ jit_tex->data = lp_tex->data;
+ }
+ }
+
+ llvmpipe->num_textures = num;
+
+ llvmpipe->dirty |= LP_NEW_TEXTURE;
+}
+
+
+void
+llvmpipe_delete_sampler_state(struct pipe_context *pipe,
+ void *sampler)
+{
+ FREE( sampler );
+}
+
+
+
diff --git a/src/gallium/drivers/llvmpipe/lp_state_surface.c b/src/gallium/drivers/llvmpipe/lp_state_surface.c
new file mode 100644
index 0000000000..177a26b7b1
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_surface.c
@@ -0,0 +1,106 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "lp_context.h"
+#include "lp_state.h"
+#include "lp_surface.h"
+#include "lp_tile_cache.h"
+
+#include "draw/draw_context.h"
+
+
+/**
+ * XXX this might get moved someday
+ * Set the framebuffer surface info: color buffers, zbuffer, stencil buffer.
+ * Here, we flush the old surfaces and update the tile cache to point to the new
+ * surfaces.
+ */
+void
+llvmpipe_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct llvmpipe_context *lp = llvmpipe_context(pipe);
+ uint i;
+
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ /* check if changing cbuf */
+ if (lp->framebuffer.cbufs[i] != fb->cbufs[i]) {
+ /* flush old */
+ lp_flush_tile_cache(lp->cbuf_cache[i]);
+
+ /* assign new */
+ lp->framebuffer.cbufs[i] = fb->cbufs[i];
+
+ /* update cache */
+ lp_tile_cache_set_surface(lp->cbuf_cache[i], fb->cbufs[i]);
+ }
+ }
+
+ lp->framebuffer.nr_cbufs = fb->nr_cbufs;
+
+ /* zbuf changing? */
+ if (lp->framebuffer.zsbuf != fb->zsbuf) {
+
+ if(lp->zsbuf_transfer) {
+ struct pipe_screen *screen = pipe->screen;
+
+ if(lp->zsbuf_map) {
+ screen->transfer_unmap(screen, lp->zsbuf_transfer);
+ lp->zsbuf_map = NULL;
+ }
+
+ screen->tex_transfer_destroy(lp->zsbuf_transfer);
+ lp->zsbuf_transfer = NULL;
+ }
+
+ /* assign new */
+ lp->framebuffer.zsbuf = fb->zsbuf;
+
+ /* Tell draw module how deep the Z/depth buffer is */
+ if (lp->framebuffer.zsbuf) {
+ int depth_bits;
+ double mrd;
+ depth_bits = pf_get_component_bits(lp->framebuffer.zsbuf->format,
+ PIPE_FORMAT_COMP_Z);
+ if (depth_bits > 16) {
+ mrd = 0.0000001;
+ }
+ else {
+ mrd = 0.00002;
+ }
+ draw_set_mrd(lp->draw, mrd);
+ }
+ }
+
+ lp->framebuffer.width = fb->width;
+ lp->framebuffer.height = fb->height;
+
+ lp->dirty |= LP_NEW_FRAMEBUFFER;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c
new file mode 100644
index 0000000000..1a17631a4c
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "lp_context.h"
+#include "lp_state.h"
+#include "lp_surface.h"
+
+#include "draw/draw_context.h"
+
+
+void
+llvmpipe_set_vertex_elements(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_element *attribs)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ assert(count <= PIPE_MAX_ATTRIBS);
+
+ memcpy(llvmpipe->vertex_element, attribs,
+ count * sizeof(struct pipe_vertex_element));
+ llvmpipe->num_vertex_elements = count;
+
+ llvmpipe->dirty |= LP_NEW_VERTEX;
+
+ draw_set_vertex_elements(llvmpipe->draw, count, attribs);
+}
+
+
+void
+llvmpipe_set_vertex_buffers(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_buffer *buffers)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ assert(count <= PIPE_MAX_ATTRIBS);
+
+ memcpy(llvmpipe->vertex_buffer, buffers, count * sizeof(buffers[0]));
+ llvmpipe->num_vertex_buffers = count;
+
+ llvmpipe->dirty |= LP_NEW_VERTEX;
+
+ draw_set_vertex_buffers(llvmpipe->draw, count, buffers);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_vs.c b/src/gallium/drivers/llvmpipe/lp_state_vs.c
new file mode 100644
index 0000000000..15c3029614
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_vs.c
@@ -0,0 +1,96 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_defines.h"
+#include "tgsi/tgsi_parse.h"
+#include "util/u_memory.h"
+#include "draw/draw_context.h"
+
+#include "lp_context.h"
+#include "lp_state.h"
+
+
+void *
+llvmpipe_create_vs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+ struct lp_vertex_shader *state;
+
+ state = CALLOC_STRUCT(lp_vertex_shader);
+ if (state == NULL )
+ goto fail;
+
+ /* copy shader tokens, the ones passed in will go away.
+ */
+ state->shader.tokens = tgsi_dup_tokens(templ->tokens);
+ if (state->shader.tokens == NULL)
+ goto fail;
+
+ state->draw_data = draw_create_vertex_shader(llvmpipe->draw, templ);
+ if (state->draw_data == NULL)
+ goto fail;
+
+ return state;
+
+fail:
+ if (state) {
+ FREE( (void *)state->shader.tokens );
+ FREE( state->draw_data );
+ FREE( state );
+ }
+ return NULL;
+}
+
+
+void
+llvmpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ llvmpipe->vs = (const struct lp_vertex_shader *)vs;
+
+ draw_bind_vertex_shader(llvmpipe->draw,
+ (llvmpipe->vs ? llvmpipe->vs->draw_data : NULL));
+
+ llvmpipe->dirty |= LP_NEW_VS;
+}
+
+
+void
+llvmpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ struct lp_vertex_shader *state =
+ (struct lp_vertex_shader *)vs;
+
+ draw_delete_vertex_shader(llvmpipe->draw, state->draw_data);
+ FREE( state );
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c
new file mode 100644
index 0000000000..6110b0a193
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_surface.c
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_rect.h"
+#include "lp_context.h"
+#include "lp_surface.h"
+
+
+static void
+lp_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ util_surface_copy(pipe, FALSE,
+ dest, destx, desty,
+ src, srcx, srcy,
+ width, height);
+}
+
+void
+lp_init_surface_functions(struct llvmpipe_context *lp)
+{
+ lp->pipe.surface_copy = lp_surface_copy;
+ lp->pipe.surface_fill = util_surface_fill;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_surface.h b/src/gallium/drivers/llvmpipe/lp_surface.h
new file mode 100644
index 0000000000..4d78a53c4f
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_surface.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef LP_SURFACE_H
+#define LP_SURFACE_H
+
+
+struct llvmpipe_context;
+
+
+extern void
+lp_init_surface_functions(struct llvmpipe_context *lp);
+
+
+#endif /* LP_SURFACE_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_test.h b/src/gallium/drivers/llvmpipe/lp_test.h
new file mode 100644
index 0000000000..69aaae26e0
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_test.h
@@ -0,0 +1,128 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Shared testing code.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#ifndef LP_TEST_H
+#define LP_TEST_H
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <float.h>
+
+#include <llvm-c/Core.h>
+#include <llvm-c/Analysis.h>
+#include <llvm-c/ExecutionEngine.h>
+#include <llvm-c/Target.h>
+#include <llvm-c/BitWriter.h>
+#include <llvm-c/Transforms/Scalar.h>
+
+#include "pipe/p_state.h"
+#include "util/u_format.h"
+#include "util/u_math.h"
+#include "util/u_debug_dump.h"
+
+#include "lp_bld_type.h"
+
+
+void
+write_tsv_header(FILE *fp);
+
+
+boolean
+test_some(unsigned verbose, FILE *fp, unsigned long n);
+
+
+boolean
+test_all(unsigned verbose, FILE *fp);
+
+
+static INLINE uint64_t
+rdtsc(void)
+{
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+ uint32_t hi, lo;
+ __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+ return ((uint64_t)lo) | (((uint64_t)hi) << 32);
+#else
+ return 0;
+#endif
+}
+
+
+float
+random_float(void);
+
+
+void
+dump_type(FILE *fp, union lp_type type);
+
+
+double
+read_elem(union lp_type type, const void *src, unsigned index);
+
+
+void
+write_elem(union lp_type type, void *dst, unsigned index, double src);
+
+
+void
+random_elem(union lp_type type, void *dst, unsigned index);
+
+
+void
+read_vec(union lp_type type, const void *src, double *dst);
+
+
+void
+write_vec(union lp_type type, void *dst, const double *src);
+
+
+void
+random_vec(union lp_type type, void *dst);
+
+
+boolean
+compare_vec_with_eps(union lp_type type, const void *res, const void *ref, double eps);
+
+
+boolean
+compare_vec(union lp_type type, const void *res, const void *ref);
+
+
+void
+dump_vec(FILE *fp, union lp_type type, const void *src);
+
+
+#endif /* !LP_TEST_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c
new file mode 100644
index 0000000000..8dfad468e3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c
@@ -0,0 +1,881 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Unit tests for blend LLVM IR generation
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ *
+ * Blend computation code derived from code written by
+ * @author Brian Paul <brian@vmware.com>
+ */
+
+
+#include "lp_bld_type.h"
+#include "lp_bld_arit.h"
+#include "lp_bld_blend.h"
+#include "lp_bld_debug.h"
+#include "lp_test.h"
+
+
+enum vector_mode
+{
+ AoS = 0,
+ SoA = 1
+};
+
+
+typedef void (*blend_test_ptr_t)(const void *src, const void *dst, const void *con, void *res);
+
+
+void
+write_tsv_header(FILE *fp)
+{
+ fprintf(fp,
+ "result\t"
+ "cycles_per_channel\t"
+ "mode\t"
+ "type\t"
+ "sep_func\t"
+ "sep_src_factor\t"
+ "sep_dst_factor\t"
+ "rgb_func\t"
+ "rgb_src_factor\t"
+ "rgb_dst_factor\t"
+ "alpha_func\t"
+ "alpha_src_factor\t"
+ "alpha_dst_factor\n");
+
+ fflush(fp);
+}
+
+
+static void
+write_tsv_row(FILE *fp,
+ const struct pipe_blend_state *blend,
+ enum vector_mode mode,
+ union lp_type type,
+ double cycles,
+ boolean success)
+{
+ fprintf(fp, "%s\t", success ? "pass" : "fail");
+
+ if (mode == AoS) {
+ fprintf(fp, "%.1f\t", cycles / type.length);
+ fprintf(fp, "aos\t");
+ }
+
+ if (mode == SoA) {
+ fprintf(fp, "%.1f\t", cycles / (4 * type.length));
+ fprintf(fp, "soa\t");
+ }
+
+ fprintf(fp, "%s%u%sx%u\t",
+ type.floating ? "f" : (type.fixed ? "h" : (type.sign ? "s" : "u")),
+ type.width,
+ type.norm ? "n" : "",
+ type.length);
+
+ fprintf(fp,
+ "%s\t%s\t%s\t",
+ blend->rgb_func != blend->alpha_func ? "true" : "false",
+ blend->rgb_src_factor != blend->alpha_src_factor ? "true" : "false",
+ blend->rgb_dst_factor != blend->alpha_dst_factor ? "true" : "false");
+
+ fprintf(fp,
+ "%s\t%s\t%s\t%s\t%s\t%s\n",
+ debug_dump_blend_func(blend->rgb_func, TRUE),
+ debug_dump_blend_factor(blend->rgb_src_factor, TRUE),
+ debug_dump_blend_factor(blend->rgb_dst_factor, TRUE),
+ debug_dump_blend_func(blend->alpha_func, TRUE),
+ debug_dump_blend_factor(blend->alpha_src_factor, TRUE),
+ debug_dump_blend_factor(blend->alpha_dst_factor, TRUE));
+
+ fflush(fp);
+}
+
+
+static void
+dump_blend_type(FILE *fp,
+ const struct pipe_blend_state *blend,
+ enum vector_mode mode,
+ union lp_type type)
+{
+ fprintf(fp, "%s", mode ? "soa" : "aos");
+
+ fprintf(fp, " type=%s%u%sx%u",
+ type.floating ? "f" : (type.fixed ? "h" : (type.sign ? "s" : "u")),
+ type.width,
+ type.norm ? "n" : "",
+ type.length);
+
+ fprintf(fp,
+ " %s=%s %s=%s %s=%s %s=%s %s=%s %s=%s",
+ "rgb_func", debug_dump_blend_func(blend->rgb_func, TRUE),
+ "rgb_src_factor", debug_dump_blend_factor(blend->rgb_src_factor, TRUE),
+ "rgb_dst_factor", debug_dump_blend_factor(blend->rgb_dst_factor, TRUE),
+ "alpha_func", debug_dump_blend_func(blend->alpha_func, TRUE),
+ "alpha_src_factor", debug_dump_blend_factor(blend->alpha_src_factor, TRUE),
+ "alpha_dst_factor", debug_dump_blend_factor(blend->alpha_dst_factor, TRUE));
+
+ fprintf(fp, " ...\n");
+ fflush(fp);
+}
+
+
+static LLVMValueRef
+add_blend_test(LLVMModuleRef module,
+ const struct pipe_blend_state *blend,
+ enum vector_mode mode,
+ union lp_type type)
+{
+ LLVMTypeRef ret_type;
+ LLVMTypeRef vec_type;
+ LLVMTypeRef args[4];
+ LLVMValueRef func;
+ LLVMValueRef src_ptr;
+ LLVMValueRef dst_ptr;
+ LLVMValueRef const_ptr;
+ LLVMValueRef res_ptr;
+ LLVMBasicBlockRef block;
+ LLVMBuilderRef builder;
+
+ ret_type = LLVMInt64Type();
+ vec_type = lp_build_vec_type(type);
+
+ args[3] = args[2] = args[1] = args[0] = LLVMPointerType(vec_type, 0);
+ func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidType(), args, 4, 0));
+ LLVMSetFunctionCallConv(func, LLVMCCallConv);
+ src_ptr = LLVMGetParam(func, 0);
+ dst_ptr = LLVMGetParam(func, 1);
+ const_ptr = LLVMGetParam(func, 2);
+ res_ptr = LLVMGetParam(func, 3);
+
+ block = LLVMAppendBasicBlock(func, "entry");
+ builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(builder, block);
+
+ if (mode == AoS) {
+ LLVMValueRef src;
+ LLVMValueRef dst;
+ LLVMValueRef con;
+ LLVMValueRef res;
+
+ src = LLVMBuildLoad(builder, src_ptr, "src");
+ dst = LLVMBuildLoad(builder, dst_ptr, "dst");
+ con = LLVMBuildLoad(builder, const_ptr, "const");
+
+ res = lp_build_blend_aos(builder, blend, type, src, dst, con, 3);
+
+ lp_build_name(res, "res");
+
+ LLVMBuildStore(builder, res, res_ptr);
+ }
+
+ if (mode == SoA) {
+ LLVMValueRef src[4];
+ LLVMValueRef dst[4];
+ LLVMValueRef con[4];
+ LLVMValueRef res[4];
+ unsigned i;
+
+ for(i = 0; i < 4; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ src[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, src_ptr, &index, 1, ""), "");
+ dst[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dst_ptr, &index, 1, ""), "");
+ con[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, const_ptr, &index, 1, ""), "");
+ lp_build_name(src[i], "src.%c", "rgba"[i]);
+ lp_build_name(con[i], "con.%c", "rgba"[i]);
+ lp_build_name(dst[i], "dst.%c", "rgba"[i]);
+ }
+
+ lp_build_blend_soa(builder, blend, type, src, dst, con, res);
+
+ for(i = 0; i < 4; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ lp_build_name(res[i], "res.%c", "rgba"[i]);
+ LLVMBuildStore(builder, res[i], LLVMBuildGEP(builder, res_ptr, &index, 1, ""));
+ }
+ }
+
+ LLVMBuildRetVoid(builder);;
+
+ LLVMDisposeBuilder(builder);
+ return func;
+}
+
+
+/** Add and limit result to ceiling of 1.0 */
+#define ADD_SAT(R, A, B) \
+do { \
+ R = (A) + (B); if (R > 1.0f) R = 1.0f; \
+} while (0)
+
+/** Subtract and limit result to floor of 0.0 */
+#define SUB_SAT(R, A, B) \
+do { \
+ R = (A) - (B); if (R < 0.0f) R = 0.0f; \
+} while (0)
+
+
+static void
+compute_blend_ref_term(unsigned rgb_factor,
+ unsigned alpha_factor,
+ const double *factor,
+ const double *src,
+ const double *dst,
+ const double *con,
+ double *term)
+{
+ double temp;
+
+ switch (rgb_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ term[0] = factor[0]; /* R */
+ term[1] = factor[1]; /* G */
+ term[2] = factor[2]; /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ term[0] = factor[0] * src[0]; /* R */
+ term[1] = factor[1] * src[1]; /* G */
+ term[2] = factor[2] * src[2]; /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ term[0] = factor[0] * src[3]; /* R */
+ term[1] = factor[1] * src[3]; /* G */
+ term[2] = factor[2] * src[3]; /* B */
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ term[0] = factor[0] * dst[0]; /* R */
+ term[1] = factor[1] * dst[1]; /* G */
+ term[2] = factor[2] * dst[2]; /* B */
+ break;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ term[0] = factor[0] * dst[3]; /* R */
+ term[1] = factor[1] * dst[3]; /* G */
+ term[2] = factor[2] * dst[3]; /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ temp = MIN2(src[3], 1.0f - dst[3]);
+ term[0] = factor[0] * temp; /* R */
+ term[1] = factor[1] * temp; /* G */
+ term[2] = factor[2] * temp; /* B */
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ term[0] = factor[0] * con[0]; /* R */
+ term[1] = factor[1] * con[1]; /* G */
+ term[2] = factor[2] * con[2]; /* B */
+ break;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ term[0] = factor[0] * con[3]; /* R */
+ term[1] = factor[1] * con[3]; /* G */
+ term[2] = factor[2] * con[3]; /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ term[0] = 0.0f; /* R */
+ term[1] = 0.0f; /* G */
+ term[2] = 0.0f; /* B */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ term[0] = factor[0] * (1.0f - src[0]); /* R */
+ term[1] = factor[1] * (1.0f - src[1]); /* G */
+ term[2] = factor[2] * (1.0f - src[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ term[0] = factor[0] * (1.0f - src[3]); /* R */
+ term[1] = factor[1] * (1.0f - src[3]); /* G */
+ term[2] = factor[2] * (1.0f - src[3]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ term[0] = factor[0] * (1.0f - dst[3]); /* R */
+ term[1] = factor[1] * (1.0f - dst[3]); /* G */
+ term[2] = factor[2] * (1.0f - dst[3]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ term[0] = factor[0] * (1.0f - dst[0]); /* R */
+ term[1] = factor[1] * (1.0f - dst[1]); /* G */
+ term[2] = factor[2] * (1.0f - dst[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ term[0] = factor[0] * (1.0f - con[0]); /* R */
+ term[1] = factor[1] * (1.0f - con[1]); /* G */
+ term[2] = factor[2] * (1.0f - con[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ term[0] = factor[0] * (1.0f - con[3]); /* R */
+ term[1] = factor[1] * (1.0f - con[3]); /* G */
+ term[2] = factor[2] * (1.0f - con[3]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ assert(0); /* to do */
+ break;
+ default:
+ assert(0);
+ }
+
+ /*
+ * Compute src/first term A
+ */
+ switch (alpha_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ term[3] = factor[3]; /* A */
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ term[3] = factor[3] * src[3]; /* A */
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ term[3] = factor[3] * dst[3]; /* A */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ term[3] = src[3]; /* A */
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ term[3] = factor[3] * con[3]; /* A */
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ term[3] = 0.0f; /* A */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ term[3] = factor[3] * (1.0f - src[3]); /* A */
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ term[3] = factor[3] * (1.0f - dst[3]); /* A */
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ term[3] = factor[3] * (1.0f - con[3]);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+static void
+compute_blend_ref(const struct pipe_blend_state *blend,
+ const double *src,
+ const double *dst,
+ const double *con,
+ double *res)
+{
+ double src_term[4];
+ double dst_term[4];
+
+ compute_blend_ref_term(blend->rgb_src_factor, blend->alpha_src_factor, src, src, dst, con, src_term);
+ compute_blend_ref_term(blend->rgb_dst_factor, blend->alpha_dst_factor, dst, src, dst, con, dst_term);
+
+ /*
+ * Combine RGB terms
+ */
+ switch (blend->rgb_func) {
+ case PIPE_BLEND_ADD:
+ ADD_SAT(res[0], src_term[0], dst_term[0]); /* R */
+ ADD_SAT(res[1], src_term[1], dst_term[1]); /* G */
+ ADD_SAT(res[2], src_term[2], dst_term[2]); /* B */
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ SUB_SAT(res[0], src_term[0], dst_term[0]); /* R */
+ SUB_SAT(res[1], src_term[1], dst_term[1]); /* G */
+ SUB_SAT(res[2], src_term[2], dst_term[2]); /* B */
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ SUB_SAT(res[0], dst_term[0], src_term[0]); /* R */
+ SUB_SAT(res[1], dst_term[1], src_term[1]); /* G */
+ SUB_SAT(res[2], dst_term[2], src_term[2]); /* B */
+ break;
+ case PIPE_BLEND_MIN:
+ res[0] = MIN2(src_term[0], dst_term[0]); /* R */
+ res[1] = MIN2(src_term[1], dst_term[1]); /* G */
+ res[2] = MIN2(src_term[2], dst_term[2]); /* B */
+ break;
+ case PIPE_BLEND_MAX:
+ res[0] = MAX2(src_term[0], dst_term[0]); /* R */
+ res[1] = MAX2(src_term[1], dst_term[1]); /* G */
+ res[2] = MAX2(src_term[2], dst_term[2]); /* B */
+ break;
+ default:
+ assert(0);
+ }
+
+ /*
+ * Combine A terms
+ */
+ switch (blend->alpha_func) {
+ case PIPE_BLEND_ADD:
+ ADD_SAT(res[3], src_term[3], dst_term[3]); /* A */
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ SUB_SAT(res[3], src_term[3], dst_term[3]); /* A */
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ SUB_SAT(res[3], dst_term[3], src_term[3]); /* A */
+ break;
+ case PIPE_BLEND_MIN:
+ res[3] = MIN2(src_term[3], dst_term[3]); /* A */
+ break;
+ case PIPE_BLEND_MAX:
+ res[3] = MAX2(src_term[3], dst_term[3]); /* A */
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+static boolean
+test_one(unsigned verbose,
+ FILE *fp,
+ const struct pipe_blend_state *blend,
+ enum vector_mode mode,
+ union lp_type type)
+{
+ LLVMModuleRef module = NULL;
+ LLVMValueRef func = NULL;
+ LLVMExecutionEngineRef engine = NULL;
+ LLVMModuleProviderRef provider = NULL;
+ LLVMPassManagerRef pass = NULL;
+ char *error = NULL;
+ blend_test_ptr_t blend_test_ptr;
+ boolean success;
+ const unsigned n = 32;
+ int64_t cycles[n];
+ double cycles_avg = 0.0;
+ unsigned i, j;
+
+ if(verbose >= 1)
+ dump_blend_type(stdout, blend, mode, type);
+
+ module = LLVMModuleCreateWithName("test");
+
+ func = add_blend_test(module, blend, mode, type);
+
+ if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) {
+ LLVMDumpModule(module);
+ abort();
+ }
+ LLVMDisposeMessage(error);
+
+ provider = LLVMCreateModuleProviderForExistingModule(module);
+ if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
+ if(verbose < 1)
+ dump_blend_type(stderr, blend, mode, type);
+ fprintf(stderr, "%s\n", error);
+ LLVMDisposeMessage(error);
+ abort();
+ }
+
+#if 0
+ pass = LLVMCreatePassManager();
+ LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
+ /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
+ * but there are more on SVN. */
+ LLVMAddConstantPropagationPass(pass);
+ LLVMAddInstructionCombiningPass(pass);
+ LLVMAddPromoteMemoryToRegisterPass(pass);
+ LLVMAddGVNPass(pass);
+ LLVMAddCFGSimplificationPass(pass);
+ LLVMRunPassManager(pass, module);
+#else
+ (void)pass;
+#endif
+
+ if(verbose >= 2)
+ LLVMDumpModule(module);
+
+ blend_test_ptr = (blend_test_ptr_t)LLVMGetPointerToGlobal(engine, func);
+
+ if(verbose >= 2)
+ lp_disassemble(blend_test_ptr);
+
+ success = TRUE;
+ for(i = 0; i < n && success; ++i) {
+ if(mode == AoS) {
+ uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ uint8_t con[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ uint8_t res[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ uint8_t ref[LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ int64_t start_counter = 0;
+ int64_t end_counter = 0;
+
+ random_vec(type, src);
+ random_vec(type, dst);
+ random_vec(type, con);
+
+ {
+ double fsrc[LP_MAX_VECTOR_LENGTH];
+ double fdst[LP_MAX_VECTOR_LENGTH];
+ double fcon[LP_MAX_VECTOR_LENGTH];
+ double fref[LP_MAX_VECTOR_LENGTH];
+
+ read_vec(type, src, fsrc);
+ read_vec(type, dst, fdst);
+ read_vec(type, con, fcon);
+
+ for(j = 0; j < type.length; j += 4)
+ compute_blend_ref(blend, fsrc + j, fdst + j, fcon + j, fref + j);
+
+ write_vec(type, ref, fref);
+ }
+
+ start_counter = rdtsc();
+ blend_test_ptr(src, dst, con, res);
+ end_counter = rdtsc();
+
+ cycles[i] = end_counter - start_counter;
+
+ if(!compare_vec(type, res, ref)) {
+ success = FALSE;
+
+ if(verbose < 1)
+ dump_blend_type(stderr, blend, mode, type);
+ fprintf(stderr, "MISMATCH\n");
+
+ fprintf(stderr, " Src: ");
+ dump_vec(stderr, type, src);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Dst: ");
+ dump_vec(stderr, type, dst);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Con: ");
+ dump_vec(stderr, type, con);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Res: ");
+ dump_vec(stderr, type, res);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Ref: ");
+ dump_vec(stderr, type, ref);
+ fprintf(stderr, "\n");
+ }
+ }
+
+ if(mode == SoA) {
+ const unsigned stride = type.length*type.width/8;
+ uint8_t src[4*LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ uint8_t dst[4*LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ uint8_t con[4*LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ uint8_t res[4*LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ uint8_t ref[4*LP_MAX_VECTOR_LENGTH*LP_MAX_TYPE_WIDTH/8];
+ int64_t start_counter = 0;
+ int64_t end_counter = 0;
+ boolean mismatch;
+
+ for(j = 0; j < 4; ++j) {
+ random_vec(type, src + j*stride);
+ random_vec(type, dst + j*stride);
+ random_vec(type, con + j*stride);
+ }
+
+ {
+ double fsrc[4];
+ double fdst[4];
+ double fcon[4];
+ double fref[4];
+ unsigned k;
+
+ for(k = 0; k < type.length; ++k) {
+ for(j = 0; j < 4; ++j) {
+ fsrc[j] = read_elem(type, src + j*stride, k);
+ fdst[j] = read_elem(type, dst + j*stride, k);
+ fcon[j] = read_elem(type, con + j*stride, k);
+ }
+
+ compute_blend_ref(blend, fsrc, fdst, fcon, fref);
+
+ for(j = 0; j < 4; ++j)
+ write_elem(type, ref + j*stride, k, fref[j]);
+ }
+ }
+
+ start_counter = rdtsc();
+ blend_test_ptr(src, dst, con, res);
+ end_counter = rdtsc();
+
+ cycles[i] = end_counter - start_counter;
+
+ mismatch = FALSE;
+ for (j = 0; j < 4; ++j)
+ if(!compare_vec(type, res + j*stride, ref + j*stride))
+ mismatch = TRUE;
+
+ if (mismatch) {
+ success = FALSE;
+
+ if(verbose < 1)
+ dump_blend_type(stderr, blend, mode, type);
+ fprintf(stderr, "MISMATCH\n");
+ for(j = 0; j < 4; ++j) {
+ char channel = "RGBA"[j];
+ fprintf(stderr, " Src%c: ", channel);
+ dump_vec(stderr, type, src + j*stride);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Dst%c: ", channel);
+ dump_vec(stderr, type, dst + j*stride);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Con%c: ", channel);
+ dump_vec(stderr, type, con + j*stride);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Res%c: ", channel);
+ dump_vec(stderr, type, res + j*stride);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Ref%c: ", channel);
+ dump_vec(stderr, type, ref + j*stride);
+ fprintf(stderr, "\n");
+ }
+ }
+ }
+ }
+
+ /*
+ * Unfortunately the output of cycle counter is not very reliable as it comes
+ * -- sometimes we get outliers (due IRQs perhaps?) which are
+ * better removed to avoid random or biased data.
+ */
+ {
+ double sum = 0.0, sum2 = 0.0;
+ double avg, std;
+ unsigned m;
+
+ for(i = 0; i < n; ++i) {
+ sum += cycles[i];
+ sum2 += cycles[i]*cycles[i];
+ }
+
+ avg = sum/n;
+ std = sqrtf((sum2 - n*avg*avg)/n);
+
+ m = 0;
+ sum = 0.0;
+ for(i = 0; i < n; ++i) {
+ if(fabs(cycles[i] - avg) <= 4.0*std) {
+ sum += cycles[i];
+ ++m;
+ }
+ }
+
+ cycles_avg = sum/m;
+
+ }
+
+ if(fp)
+ write_tsv_row(fp, blend, mode, type, cycles_avg, success);
+
+ if (!success) {
+ if(verbose < 2)
+ LLVMDumpModule(module);
+ LLVMWriteBitcodeToFile(module, "blend.bc");
+ fprintf(stderr, "blend.bc written\n");
+ fprintf(stderr, "Invoke as \"llc -o - blend.bc\"\n");
+ abort();
+ }
+
+ LLVMFreeMachineCodeForFunction(engine, func);
+
+ LLVMDisposeExecutionEngine(engine);
+ if(pass)
+ LLVMDisposePassManager(pass);
+
+ return success;
+}
+
+
+const unsigned
+blend_factors[] = {
+ PIPE_BLENDFACTOR_ZERO,
+ PIPE_BLENDFACTOR_ONE,
+ PIPE_BLENDFACTOR_SRC_COLOR,
+ PIPE_BLENDFACTOR_SRC_ALPHA,
+ PIPE_BLENDFACTOR_DST_COLOR,
+ PIPE_BLENDFACTOR_DST_ALPHA,
+ PIPE_BLENDFACTOR_CONST_COLOR,
+ PIPE_BLENDFACTOR_CONST_ALPHA,
+#if 0
+ PIPE_BLENDFACTOR_SRC1_COLOR,
+ PIPE_BLENDFACTOR_SRC1_ALPHA,
+#endif
+ PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE,
+ PIPE_BLENDFACTOR_INV_SRC_COLOR,
+ PIPE_BLENDFACTOR_INV_SRC_ALPHA,
+ PIPE_BLENDFACTOR_INV_DST_COLOR,
+ PIPE_BLENDFACTOR_INV_DST_ALPHA,
+ PIPE_BLENDFACTOR_INV_CONST_COLOR,
+ PIPE_BLENDFACTOR_INV_CONST_ALPHA,
+#if 0
+ PIPE_BLENDFACTOR_INV_SRC1_COLOR,
+ PIPE_BLENDFACTOR_INV_SRC1_ALPHA,
+#endif
+};
+
+
+const unsigned
+blend_funcs[] = {
+ PIPE_BLEND_ADD,
+ PIPE_BLEND_SUBTRACT,
+ PIPE_BLEND_REVERSE_SUBTRACT,
+ PIPE_BLEND_MIN,
+ PIPE_BLEND_MAX
+};
+
+
+const union lp_type blend_types[] = {
+ /* float, fixed, sign, norm, width, len */
+ {{ TRUE, FALSE, FALSE, TRUE, 32, 4 }}, /* f32 x 4 */
+ {{ FALSE, FALSE, FALSE, TRUE, 8, 16 }}, /* u8n x 16 */
+};
+
+
+const unsigned num_funcs = sizeof(blend_funcs)/sizeof(blend_funcs[0]);
+const unsigned num_factors = sizeof(blend_factors)/sizeof(blend_factors[0]);
+const unsigned num_types = sizeof(blend_types)/sizeof(blend_types[0]);
+
+
+boolean
+test_all(unsigned verbose, FILE *fp)
+{
+ const unsigned *rgb_func;
+ const unsigned *rgb_src_factor;
+ const unsigned *rgb_dst_factor;
+ const unsigned *alpha_func;
+ const unsigned *alpha_src_factor;
+ const unsigned *alpha_dst_factor;
+ struct pipe_blend_state blend;
+ enum vector_mode mode;
+ const union lp_type *type;
+ bool success = TRUE;
+
+ for(rgb_func = blend_funcs; rgb_func < &blend_funcs[num_funcs]; ++rgb_func) {
+ for(alpha_func = blend_funcs; alpha_func < &blend_funcs[num_funcs]; ++alpha_func) {
+ for(rgb_src_factor = blend_factors; rgb_src_factor < &blend_factors[num_factors]; ++rgb_src_factor) {
+ for(rgb_dst_factor = blend_factors; rgb_dst_factor <= rgb_src_factor; ++rgb_dst_factor) {
+ for(alpha_src_factor = blend_factors; alpha_src_factor < &blend_factors[num_factors]; ++alpha_src_factor) {
+ for(alpha_dst_factor = blend_factors; alpha_dst_factor <= alpha_src_factor; ++alpha_dst_factor) {
+ for(mode = 0; mode < 2; ++mode) {
+ for(type = blend_types; type < &blend_types[num_types]; ++type) {
+
+ if(*rgb_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE ||
+ *alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
+ continue;
+
+ memset(&blend, 0, sizeof blend);
+ blend.blend_enable = 1;
+ blend.rgb_func = *rgb_func;
+ blend.rgb_src_factor = *rgb_src_factor;
+ blend.rgb_dst_factor = *rgb_dst_factor;
+ blend.alpha_func = *alpha_func;
+ blend.alpha_src_factor = *alpha_src_factor;
+ blend.alpha_dst_factor = *alpha_dst_factor;
+ blend.colormask = PIPE_MASK_RGBA;
+
+ if(!test_one(verbose, fp, &blend, mode, *type))
+ success = FALSE;
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return success;
+}
+
+
+boolean
+test_some(unsigned verbose, FILE *fp, unsigned long n)
+{
+ const unsigned *rgb_func;
+ const unsigned *rgb_src_factor;
+ const unsigned *rgb_dst_factor;
+ const unsigned *alpha_func;
+ const unsigned *alpha_src_factor;
+ const unsigned *alpha_dst_factor;
+ struct pipe_blend_state blend;
+ enum vector_mode mode;
+ const union lp_type *type;
+ unsigned long i;
+ bool success = TRUE;
+
+ for(i = 0; i < n; ++i) {
+ rgb_func = &blend_funcs[random() % num_funcs];
+ alpha_func = &blend_funcs[random() % num_funcs];
+ rgb_src_factor = &blend_factors[random() % num_factors];
+ alpha_src_factor = &blend_factors[random() % num_factors];
+
+ do {
+ rgb_dst_factor = &blend_factors[random() % num_factors];
+ } while(*rgb_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE);
+
+ do {
+ alpha_dst_factor = &blend_factors[random() % num_factors];
+ } while(*alpha_dst_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE);
+
+ mode = random() & 1;
+
+ type = &blend_types[random() % num_types];
+
+ memset(&blend, 0, sizeof blend);
+ blend.blend_enable = 1;
+ blend.rgb_func = *rgb_func;
+ blend.rgb_src_factor = *rgb_src_factor;
+ blend.rgb_dst_factor = *rgb_dst_factor;
+ blend.alpha_func = *alpha_func;
+ blend.alpha_src_factor = *alpha_src_factor;
+ blend.alpha_dst_factor = *alpha_dst_factor;
+ blend.colormask = PIPE_MASK_RGBA;
+
+ if(!test_one(verbose, fp, &blend, mode, *type))
+ success = FALSE;
+ }
+
+ return success;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c
new file mode 100644
index 0000000000..e6489834af
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c
@@ -0,0 +1,427 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Unit tests for type conversion.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_conv.h"
+#include "lp_bld_debug.h"
+#include "lp_test.h"
+
+
+typedef void (*conv_test_ptr_t)(const void *src, const void *dst);
+
+
+void
+write_tsv_header(FILE *fp)
+{
+ fprintf(fp,
+ "result\t"
+ "cycles_per_channel\t"
+ "src_type\t"
+ "dst_type\n");
+
+ fflush(fp);
+}
+
+
+static void
+write_tsv_row(FILE *fp,
+ union lp_type src_type,
+ union lp_type dst_type,
+ double cycles,
+ boolean success)
+{
+ fprintf(fp, "%s\t", success ? "pass" : "fail");
+
+ fprintf(fp, "%.1f\t", cycles / MAX2(src_type.length, dst_type.length));
+
+ dump_type(fp, src_type);
+ fprintf(fp, "\t");
+
+ dump_type(fp, dst_type);
+ fprintf(fp, "\n");
+
+ fflush(fp);
+}
+
+
+static void
+dump_conv_types(FILE *fp,
+ union lp_type src_type,
+ union lp_type dst_type)
+{
+ fprintf(fp, "src_type=");
+ dump_type(fp, src_type);
+
+ fprintf(fp, " dst_type=");
+ dump_type(fp, dst_type);
+
+ fprintf(fp, " ...\n");
+ fflush(fp);
+}
+
+
+static LLVMValueRef
+add_conv_test(LLVMModuleRef module,
+ union lp_type src_type, unsigned num_srcs,
+ union lp_type dst_type, unsigned num_dsts)
+{
+ LLVMTypeRef args[2];
+ LLVMValueRef func;
+ LLVMValueRef src_ptr;
+ LLVMValueRef dst_ptr;
+ LLVMBasicBlockRef block;
+ LLVMBuilderRef builder;
+ LLVMValueRef src[LP_MAX_VECTOR_LENGTH];
+ LLVMValueRef dst[LP_MAX_VECTOR_LENGTH];
+ unsigned i;
+
+ args[0] = LLVMPointerType(lp_build_vec_type(src_type), 0);
+ args[1] = LLVMPointerType(lp_build_vec_type(dst_type), 0);
+
+ func = LLVMAddFunction(module, "test", LLVMFunctionType(LLVMVoidType(), args, 2, 0));
+ LLVMSetFunctionCallConv(func, LLVMCCallConv);
+ src_ptr = LLVMGetParam(func, 0);
+ dst_ptr = LLVMGetParam(func, 1);
+
+ block = LLVMAppendBasicBlock(func, "entry");
+ builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(builder, block);
+
+ for(i = 0; i < num_srcs; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ LLVMValueRef ptr = LLVMBuildGEP(builder, src_ptr, &index, 1, "");
+ src[i] = LLVMBuildLoad(builder, ptr, "");
+ }
+
+ lp_build_conv(builder, src_type, dst_type, src, num_srcs, dst, num_dsts);
+
+ for(i = 0; i < num_dsts; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ LLVMValueRef ptr = LLVMBuildGEP(builder, dst_ptr, &index, 1, "");
+ LLVMBuildStore(builder, dst[i], ptr);
+ }
+
+ LLVMBuildRetVoid(builder);;
+
+ LLVMDisposeBuilder(builder);
+ return func;
+}
+
+
+static boolean
+test_one(unsigned verbose,
+ FILE *fp,
+ union lp_type src_type,
+ union lp_type dst_type)
+{
+ LLVMModuleRef module = NULL;
+ LLVMValueRef func = NULL;
+ LLVMExecutionEngineRef engine = NULL;
+ LLVMModuleProviderRef provider = NULL;
+ LLVMPassManagerRef pass = NULL;
+ char *error = NULL;
+ conv_test_ptr_t conv_test_ptr;
+ boolean success;
+ const unsigned n = 32;
+ int64_t cycles[n];
+ double cycles_avg = 0.0;
+ unsigned num_srcs;
+ unsigned num_dsts;
+ double eps;
+ unsigned i, j;
+
+ if(verbose >= 1)
+ dump_conv_types(stdout, src_type, dst_type);
+
+ if(src_type.length > dst_type.length) {
+ num_srcs = 1;
+ num_dsts = src_type.length/dst_type.length;
+ }
+ else {
+ num_dsts = 1;
+ num_srcs = dst_type.length/src_type.length;
+ }
+
+ assert(src_type.width * src_type.length == dst_type.width * dst_type.length);
+
+ /* We must not loose or gain channels. Only precision */
+ assert(src_type.length * num_srcs == dst_type.length * num_dsts);
+
+ eps = MAX2(lp_const_eps(src_type), lp_const_eps(dst_type));
+
+ module = LLVMModuleCreateWithName("test");
+
+ func = add_conv_test(module, src_type, num_srcs, dst_type, num_dsts);
+
+ if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) {
+ LLVMDumpModule(module);
+ abort();
+ }
+ LLVMDisposeMessage(error);
+
+ provider = LLVMCreateModuleProviderForExistingModule(module);
+ if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
+ if(verbose < 1)
+ dump_conv_types(stderr, src_type, dst_type);
+ fprintf(stderr, "%s\n", error);
+ LLVMDisposeMessage(error);
+ abort();
+ }
+
+#if 0
+ pass = LLVMCreatePassManager();
+ LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
+ /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
+ * but there are more on SVN. */
+ LLVMAddConstantPropagationPass(pass);
+ LLVMAddInstructionCombiningPass(pass);
+ LLVMAddPromoteMemoryToRegisterPass(pass);
+ LLVMAddGVNPass(pass);
+ LLVMAddCFGSimplificationPass(pass);
+ LLVMRunPassManager(pass, module);
+#else
+ (void)pass;
+#endif
+
+ if(verbose >= 2)
+ LLVMDumpModule(module);
+
+ conv_test_ptr = (conv_test_ptr_t)LLVMGetPointerToGlobal(engine, func);
+
+ if(verbose >= 2)
+ lp_disassemble(conv_test_ptr);
+
+ success = TRUE;
+ for(i = 0; i < n && success; ++i) {
+ unsigned src_stride = src_type.length*src_type.width/8;
+ unsigned dst_stride = dst_type.length*dst_type.width/8;
+ uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
+ uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
+ double fref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
+ uint8_t ref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
+ int64_t start_counter = 0;
+ int64_t end_counter = 0;
+
+ for(j = 0; j < num_srcs; ++j) {
+ random_vec(src_type, src + j*src_stride);
+ read_vec(src_type, src + j*src_stride, fref + j*src_type.length);
+ }
+
+ for(j = 0; j < num_dsts; ++j) {
+ write_vec(dst_type, ref + j*dst_stride, fref + j*dst_type.length);
+ }
+
+ start_counter = rdtsc();
+ conv_test_ptr(src, dst);
+ end_counter = rdtsc();
+
+ cycles[i] = end_counter - start_counter;
+
+ for(j = 0; j < num_dsts; ++j) {
+ if(!compare_vec_with_eps(dst_type, dst + j*dst_stride, ref + j*dst_stride, eps))
+ success = FALSE;
+ }
+
+ if (!success) {
+ if(verbose < 1)
+ dump_conv_types(stderr, src_type, dst_type);
+ fprintf(stderr, "MISMATCH\n");
+
+ for(j = 0; j < num_srcs; ++j) {
+ fprintf(stderr, " Src%u: ", j);
+ dump_vec(stderr, src_type, src + j*src_stride);
+ fprintf(stderr, "\n");
+ }
+
+#if 1
+ fprintf(stderr, " Ref: ");
+ for(j = 0; j < src_type.length*num_srcs; ++j)
+ fprintf(stderr, " %f", fref[j]);
+ fprintf(stderr, "\n");
+#endif
+
+ for(j = 0; j < num_dsts; ++j) {
+ fprintf(stderr, " Dst%u: ", j);
+ dump_vec(stderr, dst_type, dst + j*dst_stride);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Ref%u: ", j);
+ dump_vec(stderr, dst_type, ref + j*dst_stride);
+ fprintf(stderr, "\n");
+ }
+ }
+ }
+
+ /*
+ * Unfortunately the output of cycle counter is not very reliable as it comes
+ * -- sometimes we get outliers (due IRQs perhaps?) which are
+ * better removed to avoid random or biased data.
+ */
+ {
+ double sum = 0.0, sum2 = 0.0;
+ double avg, std;
+ unsigned m;
+
+ for(i = 0; i < n; ++i) {
+ sum += cycles[i];
+ sum2 += cycles[i]*cycles[i];
+ }
+
+ avg = sum/n;
+ std = sqrtf((sum2 - n*avg*avg)/n);
+
+ m = 0;
+ sum = 0.0;
+ for(i = 0; i < n; ++i) {
+ if(fabs(cycles[i] - avg) <= 4.0*std) {
+ sum += cycles[i];
+ ++m;
+ }
+ }
+
+ cycles_avg = sum/m;
+
+ }
+
+ if(fp)
+ write_tsv_row(fp, src_type, dst_type, cycles_avg, success);
+
+ if (!success) {
+ static boolean firsttime = TRUE;
+ if(firsttime) {
+ if(verbose < 2)
+ LLVMDumpModule(module);
+ LLVMWriteBitcodeToFile(module, "conv.bc");
+ fprintf(stderr, "conv.bc written\n");
+ fprintf(stderr, "Invoke as \"llc -o - conv.bc\"\n");
+ firsttime = FALSE;
+ //abort();
+ }
+ }
+
+ LLVMFreeMachineCodeForFunction(engine, func);
+
+ LLVMDisposeExecutionEngine(engine);
+ if(pass)
+ LLVMDisposePassManager(pass);
+
+ return success;
+}
+
+
+const union lp_type conv_types[] = {
+ /* float, fixed, sign, norm, width, len */
+
+ {{ TRUE, FALSE, TRUE, TRUE, 32, 4 }},
+ {{ TRUE, FALSE, TRUE, FALSE, 32, 4 }},
+ {{ TRUE, FALSE, FALSE, TRUE, 32, 4 }},
+ {{ TRUE, FALSE, FALSE, FALSE, 32, 4 }},
+
+ /* TODO: test fixed formats too */
+
+ {{ FALSE, FALSE, TRUE, TRUE, 16, 8 }},
+ {{ FALSE, FALSE, TRUE, FALSE, 16, 8 }},
+ {{ FALSE, FALSE, FALSE, TRUE, 16, 8 }},
+ {{ FALSE, FALSE, FALSE, FALSE, 16, 8 }},
+
+ {{ FALSE, FALSE, TRUE, TRUE, 32, 4 }},
+ {{ FALSE, FALSE, TRUE, FALSE, 32, 4 }},
+ {{ FALSE, FALSE, FALSE, TRUE, 32, 4 }},
+ {{ FALSE, FALSE, FALSE, FALSE, 32, 4 }},
+
+ {{ FALSE, FALSE, TRUE, TRUE, 16, 8 }},
+ {{ FALSE, FALSE, TRUE, FALSE, 16, 8 }},
+ {{ FALSE, FALSE, FALSE, TRUE, 16, 8 }},
+ {{ FALSE, FALSE, FALSE, FALSE, 16, 8 }},
+
+ {{ FALSE, FALSE, TRUE, TRUE, 8, 16 }},
+ {{ FALSE, FALSE, TRUE, FALSE, 8, 16 }},
+ {{ FALSE, FALSE, FALSE, TRUE, 8, 16 }},
+ {{ FALSE, FALSE, FALSE, FALSE, 8, 16 }},
+};
+
+
+const unsigned num_types = sizeof(conv_types)/sizeof(conv_types[0]);
+
+
+boolean
+test_all(unsigned verbose, FILE *fp)
+{
+ const union lp_type *src_type;
+ const union lp_type *dst_type;
+ bool success = TRUE;
+
+ for(src_type = conv_types; src_type < &conv_types[num_types]; ++src_type) {
+ for(dst_type = conv_types; dst_type < &conv_types[num_types]; ++dst_type) {
+
+ if(src_type == dst_type)
+ continue;
+
+ if(src_type->norm != dst_type->norm)
+ continue;
+
+ if(!test_one(verbose, fp, *src_type, *dst_type))
+ success = FALSE;
+
+ }
+ }
+
+ return success;
+}
+
+
+boolean
+test_some(unsigned verbose, FILE *fp, unsigned long n)
+{
+ const union lp_type *src_type;
+ const union lp_type *dst_type;
+ unsigned long i;
+ bool success = TRUE;
+
+ for(i = 0; i < n; ++i) {
+ src_type = &conv_types[random() % num_types];
+
+ do {
+ dst_type = &conv_types[random() % num_types];
+ } while (src_type == dst_type || src_type->norm != dst_type->norm);
+
+ if(!test_one(verbose, fp, *src_type, *dst_type))
+ success = FALSE;
+ }
+
+ return success;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c
new file mode 100644
index 0000000000..d8455e5649
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_test_format.c
@@ -0,0 +1,272 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <llvm-c/Core.h>
+#include <llvm-c/Analysis.h>
+#include <llvm-c/ExecutionEngine.h>
+#include <llvm-c/Target.h>
+#include <llvm-c/Transforms/Scalar.h>
+
+#include "util/u_format.h"
+
+#include "lp_bld_flow.h"
+#include "lp_bld_format.h"
+
+
+struct pixel_test_case
+{
+ enum pipe_format format;
+ uint32_t packed;
+ double unpacked[4];
+};
+
+
+struct pixel_test_case test_cases[] =
+{
+ {PIPE_FORMAT_R5G6B5_UNORM, 0x0000, {0.0, 0.0, 0.0, 1.0}},
+ {PIPE_FORMAT_R5G6B5_UNORM, 0x001f, {0.0, 0.0, 1.0, 1.0}},
+ {PIPE_FORMAT_R5G6B5_UNORM, 0x07e0, {0.0, 1.0, 0.0, 1.0}},
+ {PIPE_FORMAT_R5G6B5_UNORM, 0xf800, {1.0, 0.0, 0.0, 1.0}},
+ {PIPE_FORMAT_R5G6B5_UNORM, 0xffff, {1.0, 1.0, 1.0, 1.0}},
+
+ {PIPE_FORMAT_A1R5G5B5_UNORM, 0x0000, {0.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_A1R5G5B5_UNORM, 0x001f, {0.0, 0.0, 1.0, 0.0}},
+ {PIPE_FORMAT_A1R5G5B5_UNORM, 0x03e0, {0.0, 1.0, 0.0, 0.0}},
+ {PIPE_FORMAT_A1R5G5B5_UNORM, 0x7c00, {1.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_A1R5G5B5_UNORM, 0x8000, {0.0, 0.0, 0.0, 1.0}},
+ {PIPE_FORMAT_A1R5G5B5_UNORM, 0xffff, {1.0, 1.0, 1.0, 1.0}},
+
+ {PIPE_FORMAT_A8R8G8B8_UNORM, 0x00000000, {0.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_A8R8G8B8_UNORM, 0x000000ff, {0.0, 0.0, 1.0, 0.0}},
+ {PIPE_FORMAT_A8R8G8B8_UNORM, 0x0000ff00, {0.0, 1.0, 0.0, 0.0}},
+ {PIPE_FORMAT_A8R8G8B8_UNORM, 0x00ff0000, {1.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_A8R8G8B8_UNORM, 0xff000000, {0.0, 0.0, 0.0, 1.0}},
+ {PIPE_FORMAT_A8R8G8B8_UNORM, 0xffffffff, {1.0, 1.0, 1.0, 1.0}},
+
+#if 0
+ {PIPE_FORMAT_R8G8B8A8_UNORM, 0x00000000, {0.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_R8G8B8A8_UNORM, 0x000000ff, {0.0, 0.0, 0.0, 1.0}},
+ {PIPE_FORMAT_R8G8B8A8_UNORM, 0x0000ff00, {0.0, 0.0, 1.0, 0.0}},
+ {PIPE_FORMAT_R8G8B8A8_UNORM, 0x00ff0000, {0.0, 1.0, 0.0, 0.0}},
+ {PIPE_FORMAT_R8G8B8A8_UNORM, 0xff000000, {1.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_R8G8B8A8_UNORM, 0xffffffff, {1.0, 1.0, 1.0, 1.0}},
+#endif
+
+ {PIPE_FORMAT_B8G8R8A8_UNORM, 0x00000000, {0.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_B8G8R8A8_UNORM, 0x000000ff, {0.0, 0.0, 0.0, 1.0}},
+ {PIPE_FORMAT_B8G8R8A8_UNORM, 0x0000ff00, {1.0, 0.0, 0.0, 0.0}},
+ {PIPE_FORMAT_B8G8R8A8_UNORM, 0x00ff0000, {0.0, 1.0, 0.0, 0.0}},
+ {PIPE_FORMAT_B8G8R8A8_UNORM, 0xff000000, {0.0, 0.0, 1.0, 0.0}},
+ {PIPE_FORMAT_B8G8R8A8_UNORM, 0xffffffff, {1.0, 1.0, 1.0, 1.0}},
+};
+
+
+typedef void (*load_ptr_t)(const void *, float *);
+
+
+static LLVMValueRef
+add_load_rgba_test(LLVMModuleRef module,
+ enum pipe_format format)
+{
+ LLVMTypeRef args[2];
+ LLVMValueRef func;
+ LLVMValueRef ptr;
+ LLVMValueRef rgba_ptr;
+ LLVMBasicBlockRef block;
+ LLVMBuilderRef builder;
+ LLVMValueRef rgba;
+ struct lp_build_loop_state loop;
+
+ args[0] = LLVMPointerType(LLVMInt8Type(), 0);
+ args[1] = LLVMPointerType(LLVMVectorType(LLVMFloatType(), 4), 0);
+
+ func = LLVMAddFunction(module, "load", LLVMFunctionType(LLVMVoidType(), args, 2, 0));
+ LLVMSetFunctionCallConv(func, LLVMCCallConv);
+ ptr = LLVMGetParam(func, 0);
+ rgba_ptr = LLVMGetParam(func, 1);
+
+ block = LLVMAppendBasicBlock(func, "entry");
+ builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(builder, block);
+
+ lp_build_loop_begin(builder, LLVMConstInt(LLVMInt32Type(), 1, 0), &loop);
+
+ rgba = lp_build_load_rgba_aos(builder, format, ptr);
+ LLVMBuildStore(builder, rgba, rgba_ptr);
+
+ lp_build_loop_end(builder, LLVMConstInt(LLVMInt32Type(), 4, 0), NULL, &loop);
+
+ LLVMBuildRetVoid(builder);
+
+ LLVMDisposeBuilder(builder);
+ return func;
+}
+
+
+typedef void (*store_ptr_t)(void *, const float *);
+
+
+static LLVMValueRef
+add_store_rgba_test(LLVMModuleRef module,
+ enum pipe_format format)
+{
+ LLVMTypeRef args[2];
+ LLVMValueRef func;
+ LLVMValueRef ptr;
+ LLVMValueRef rgba_ptr;
+ LLVMBasicBlockRef block;
+ LLVMBuilderRef builder;
+ LLVMValueRef rgba;
+
+ args[0] = LLVMPointerType(LLVMInt8Type(), 0);
+ args[1] = LLVMPointerType(LLVMVectorType(LLVMFloatType(), 4), 0);
+
+ func = LLVMAddFunction(module, "store", LLVMFunctionType(LLVMVoidType(), args, 2, 0));
+ LLVMSetFunctionCallConv(func, LLVMCCallConv);
+ ptr = LLVMGetParam(func, 0);
+ rgba_ptr = LLVMGetParam(func, 1);
+
+ block = LLVMAppendBasicBlock(func, "entry");
+ builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(builder, block);
+
+ rgba = LLVMBuildLoad(builder, rgba_ptr, "");
+
+ lp_build_store_rgba_aos(builder, format, ptr, rgba);
+
+ LLVMBuildRetVoid(builder);
+
+ LLVMDisposeBuilder(builder);
+ return func;
+}
+
+
+static boolean
+test_format(const struct pixel_test_case *test)
+{
+ LLVMModuleRef module = NULL;
+ LLVMValueRef load = NULL;
+ LLVMValueRef store = NULL;
+ LLVMExecutionEngineRef engine = NULL;
+ LLVMModuleProviderRef provider = NULL;
+ LLVMPassManagerRef pass = NULL;
+ char *error = NULL;
+ const struct util_format_description *desc;
+ load_ptr_t load_ptr;
+ store_ptr_t store_ptr;
+ float unpacked[4];
+ unsigned packed;
+ boolean success;
+ unsigned i;
+
+ desc = util_format_description(test->format);
+ fprintf(stderr, "%s\n", desc->name);
+
+ module = LLVMModuleCreateWithName("test");
+
+ load = add_load_rgba_test(module, test->format);
+ store = add_store_rgba_test(module, test->format);
+
+ if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) {
+ LLVMDumpModule(module);
+ abort();
+ }
+ LLVMDisposeMessage(error);
+
+ provider = LLVMCreateModuleProviderForExistingModule(module);
+ if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
+ fprintf(stderr, "%s\n", error);
+ LLVMDisposeMessage(error);
+ abort();
+ }
+
+#if 0
+ pass = LLVMCreatePassManager();
+ LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
+ /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
+ * but there are more on SVN. */
+ LLVMAddConstantPropagationPass(pass);
+ LLVMAddInstructionCombiningPass(pass);
+ LLVMAddPromoteMemoryToRegisterPass(pass);
+ LLVMAddGVNPass(pass);
+ LLVMAddCFGSimplificationPass(pass);
+ LLVMRunPassManager(pass, module);
+#else
+ (void)pass;
+#endif
+
+ load_ptr = (load_ptr_t) LLVMGetPointerToGlobal(engine, load);
+ store_ptr = (store_ptr_t)LLVMGetPointerToGlobal(engine, store);
+
+ memset(unpacked, 0, sizeof unpacked);
+ packed = 0;
+
+ load_ptr(&test->packed, unpacked);
+ store_ptr(&packed, unpacked);
+
+ success = TRUE;
+ if(test->packed != packed)
+ success = FALSE;
+ for(i = 0; i < 4; ++i)
+ if(test->unpacked[i] != unpacked[i])
+ success = FALSE;
+
+ if (!success) {
+ printf("FAILED\n");
+ printf(" Packed: %08x\n", test->packed);
+ printf(" %08x\n", packed);
+ printf(" Unpacked: %f %f %f %f\n", unpacked[0], unpacked[1], unpacked[2], unpacked[3]);
+ printf(" %f %f %f %f\n", test->unpacked[0], test->unpacked[1], test->unpacked[2], test->unpacked[3]);
+ LLVMDumpModule(module);
+ }
+
+ LLVMFreeMachineCodeForFunction(engine, store);
+ LLVMFreeMachineCodeForFunction(engine, load);
+
+ LLVMDisposeExecutionEngine(engine);
+ if(pass)
+ LLVMDisposePassManager(pass);
+
+ return success;
+}
+
+
+int main(int argc, char **argv)
+{
+ unsigned i;
+ int ret;
+
+ for (i = 0; i < sizeof(test_cases)/sizeof(test_cases[0]); ++i)
+ if(!test_format(&test_cases[i]))
+ ret = 1;
+
+ return ret;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_test_main.c b/src/gallium/drivers/llvmpipe/lp_test_main.c
new file mode 100644
index 0000000000..49213fb4f0
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_test_main.c
@@ -0,0 +1,384 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Shared testing code.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "lp_bld_const.h"
+#include "lp_test.h"
+
+
+void
+dump_type(FILE *fp,
+ union lp_type type)
+{
+ fprintf(fp, "%s%s%u%sx%u",
+ type.sign ? (type.floating || type.fixed ? "" : "s") : "u",
+ type.floating ? "f" : (type.fixed ? "h" : "i"),
+ type.width,
+ type.norm ? "n" : "",
+ type.length);
+}
+
+
+double
+read_elem(union lp_type type, const void *src, unsigned index)
+{
+ double scale = lp_const_scale(type);
+ double value;
+ assert(index < type.length);
+ if (type.floating) {
+ switch(type.width) {
+ case 32:
+ value = *((const float *)src + index);
+ break;
+ case 64:
+ value = *((const double *)src + index);
+ break;
+ default:
+ assert(0);
+ return 0.0;
+ }
+ }
+ else {
+ if(type.sign) {
+ switch(type.width) {
+ case 8:
+ value = *((const int8_t *)src + index);
+ break;
+ case 16:
+ value = *((const int16_t *)src + index);
+ break;
+ case 32:
+ value = *((const int32_t *)src + index);
+ break;
+ case 64:
+ value = *((const int64_t *)src + index);
+ break;
+ default:
+ assert(0);
+ return 0.0;
+ }
+ }
+ else {
+ switch(type.width) {
+ case 8:
+ value = *((const uint8_t *)src + index);
+ break;
+ case 16:
+ value = *((const uint16_t *)src + index);
+ break;
+ case 32:
+ value = *((const uint32_t *)src + index);
+ break;
+ case 64:
+ value = *((const uint64_t *)src + index);
+ break;
+ default:
+ assert(0);
+ return 0.0;
+ }
+ }
+ }
+ return value/scale;
+}
+
+
+void
+write_elem(union lp_type type, void *dst, unsigned index, double value)
+{
+ assert(index < type.length);
+ if(!type.sign && value < 0.0)
+ value = 0.0;
+ if(type.norm && value < -1.0)
+ value = -1.0;
+ if(type.norm && value > 1.0)
+ value = 1.0;
+ if (type.floating) {
+ switch(type.width) {
+ case 32:
+ *((float *)dst + index) = (float)(value);
+ break;
+ case 64:
+ *((double *)dst + index) = value;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ else {
+ double scale = lp_const_scale(type);
+ value = round(value*scale);
+ if(type.sign) {
+ long long lvalue = (long long)value;
+ lvalue = MIN2(lvalue, ((long long)1 << (type.width - 1)) - 1);
+ switch(type.width) {
+ case 8:
+ *((int8_t *)dst + index) = (int8_t)lvalue;
+ break;
+ case 16:
+ *((int16_t *)dst + index) = (int16_t)lvalue;
+ break;
+ case 32:
+ *((int32_t *)dst + index) = (int32_t)lvalue;
+ break;
+ case 64:
+ *((int64_t *)dst + index) = (int64_t)lvalue;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ else {
+ unsigned long long lvalue = (long long)value;
+ lvalue = MIN2(lvalue, ((unsigned long long)1 << type.width) - 1);
+ switch(type.width) {
+ case 8:
+ *((uint8_t *)dst + index) = (uint8_t)lvalue;
+ break;
+ case 16:
+ *((uint16_t *)dst + index) = (uint16_t)lvalue;
+ break;
+ case 32:
+ *((uint32_t *)dst + index) = (uint32_t)lvalue;
+ break;
+ case 64:
+ *((uint64_t *)dst + index) = (uint64_t)lvalue;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+}
+
+
+void
+random_elem(union lp_type type, void *dst, unsigned index)
+{
+ double value;
+ assert(index < type.length);
+ value = (double)random()/(double)RAND_MAX;
+ if(!type.norm) {
+ unsigned long long mask;
+ if (type.floating)
+ mask = ~(unsigned long long)0;
+ else if (type.fixed)
+ mask = ((unsigned long long)1 << (type.width / 2)) - 1;
+ else if (type.sign)
+ mask = ((unsigned long long)1 << (type.width - 1)) - 1;
+ else
+ mask = ((unsigned long long)1 << type.width) - 1;
+ value += (double)(mask & random());
+ }
+ if(!type.sign)
+ if(random() & 1)
+ value = -value;
+ write_elem(type, dst, index, value);
+}
+
+
+void
+read_vec(union lp_type type, const void *src, double *dst)
+{
+ unsigned i;
+ for (i = 0; i < type.length; ++i)
+ dst[i] = read_elem(type, src, i);
+}
+
+
+void
+write_vec(union lp_type type, void *dst, const double *src)
+{
+ unsigned i;
+ for (i = 0; i < type.length; ++i)
+ write_elem(type, dst, i, src[i]);
+}
+
+
+float
+random_float(void)
+{
+ return (float)((double)random()/(double)RAND_MAX);
+}
+
+
+void
+random_vec(union lp_type type, void *dst)
+{
+ unsigned i;
+ for (i = 0; i < type.length; ++i)
+ random_elem(type, dst, i);
+}
+
+
+boolean
+compare_vec_with_eps(union lp_type type, const void *res, const void *ref, double eps)
+{
+ unsigned i;
+ for (i = 0; i < type.length; ++i) {
+ double res_elem = read_elem(type, res, i);
+ double ref_elem = read_elem(type, ref, i);
+ double delta = fabs(res_elem - ref_elem);
+ if(delta >= 2.0*eps)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+boolean
+compare_vec(union lp_type type, const void *res, const void *ref)
+{
+ double eps = lp_const_eps(type);
+ return compare_vec_with_eps(type, res, ref, eps);
+}
+
+
+void
+dump_vec(FILE *fp, union lp_type type, const void *src)
+{
+ unsigned i;
+ for (i = 0; i < type.length; ++i) {
+ if(i)
+ fprintf(fp, " ");
+ if (type.floating) {
+ double value;
+ switch(type.width) {
+ case 32:
+ value = *((const float *)src + i);
+ break;
+ case 64:
+ value = *((const double *)src + i);
+ break;
+ default:
+ assert(0);
+ value = 0.0;
+ }
+ fprintf(fp, "%f", value);
+ }
+ else {
+ if(type.sign && !type.norm) {
+ long long value;
+ const char *format;
+ switch(type.width) {
+ case 8:
+ value = *((const int8_t *)src + i);
+ format = "%3lli";
+ break;
+ case 16:
+ value = *((const int16_t *)src + i);
+ format = "%5lli";
+ break;
+ case 32:
+ value = *((const int32_t *)src + i);
+ format = "%10lli";
+ break;
+ case 64:
+ value = *((const int64_t *)src + i);
+ format = "%20lli";
+ break;
+ default:
+ assert(0);
+ value = 0.0;
+ format = "?";
+ }
+ fprintf(fp, format, value);
+ }
+ else {
+ unsigned long long value;
+ const char *format;
+ switch(type.width) {
+ case 8:
+ value = *((const uint8_t *)src + i);
+ format = type.norm ? "%2x" : "%4llu";
+ break;
+ case 16:
+ value = *((const uint16_t *)src + i);
+ format = type.norm ? "%4x" : "%6llx";
+ break;
+ case 32:
+ value = *((const uint32_t *)src + i);
+ format = type.norm ? "%8x" : "%11llx";
+ break;
+ case 64:
+ value = *((const uint64_t *)src + i);
+ format = type.norm ? "%16x" : "%21llx";
+ break;
+ default:
+ assert(0);
+ value = 0.0;
+ format = "?";
+ }
+ fprintf(fp, format, value);
+ }
+ }
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ unsigned verbose = 0;
+ FILE *fp = NULL;
+ unsigned long n = 1000;
+ unsigned i;
+ boolean success;
+
+ for(i = 1; i < argc; ++i) {
+ if(strcmp(argv[i], "-v") == 0)
+ ++verbose;
+ else if(strcmp(argv[i], "-o") == 0)
+ fp = fopen(argv[++i], "wt");
+ else
+ n = atoi(argv[i]);
+ }
+
+ if(fp) {
+ /* Warm up the caches */
+ test_some(0, NULL, 100);
+
+ write_tsv_header(fp);
+ }
+
+ if(n)
+ success = test_some(verbose, fp, n);
+ else
+ success = test_all(verbose, fp);
+
+ if(fp)
+ fclose(fp);
+
+ return success ? 0 : 1;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_tex_cache.c b/src/gallium/drivers/llvmpipe/lp_tex_cache.c
new file mode 100644
index 0000000000..773e848242
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_tex_cache.c
@@ -0,0 +1,304 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Texture tile caching.
+ *
+ * Author:
+ * Brian Paul
+ */
+
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_tile.h"
+#include "util/u_format.h"
+#include "lp_context.h"
+#include "lp_surface.h"
+#include "lp_texture.h"
+#include "lp_tex_cache.h"
+
+
+
+/**
+ * Return the position in the cache for the tile that contains win pos (x,y).
+ * We currently use a direct mapped cache so this is like a hack key.
+ * At some point we should investige something more sophisticated, like
+ * a LRU replacement policy.
+ */
+#define CACHE_POS(x, y) \
+ (((x) + (y) * 5) % NUM_ENTRIES)
+
+
+
+/**
+ * Is the tile at (x,y) in cleared state?
+ */
+static INLINE uint
+is_clear_flag_set(const uint *bitvec, union tex_tile_address addr)
+{
+ int pos, bit;
+ pos = addr.bits.y * (MAX_TEX_WIDTH / TEX_TILE_SIZE) + addr.bits.x;
+ assert(pos / 32 < (MAX_TEX_WIDTH / TEX_TILE_SIZE) * (MAX_TEX_HEIGHT / TEX_TILE_SIZE) / 32);
+ bit = bitvec[pos / 32] & (1 << (pos & 31));
+ return bit;
+}
+
+
+/**
+ * Mark the tile at (x,y) as not cleared.
+ */
+static INLINE void
+clear_clear_flag(uint *bitvec, union tex_tile_address addr)
+{
+ int pos;
+ pos = addr.bits.y * (MAX_TEX_WIDTH / TEX_TILE_SIZE) + addr.bits.x;
+ assert(pos / 32 < (MAX_TEX_WIDTH / TEX_TILE_SIZE) * (MAX_TEX_HEIGHT / TEX_TILE_SIZE) / 32);
+ bitvec[pos / 32] &= ~(1 << (pos & 31));
+}
+
+
+struct llvmpipe_tex_tile_cache *
+lp_create_tex_tile_cache( struct pipe_screen *screen )
+{
+ struct llvmpipe_tex_tile_cache *tc;
+ uint pos;
+
+ tc = CALLOC_STRUCT( llvmpipe_tex_tile_cache );
+ if (tc) {
+ tc->screen = screen;
+ for (pos = 0; pos < NUM_ENTRIES; pos++) {
+ tc->entries[pos].addr.bits.invalid = 1;
+ }
+ tc->last_tile = &tc->entries[0]; /* any tile */
+ }
+ return tc;
+}
+
+
+void
+lp_destroy_tex_tile_cache(struct llvmpipe_tex_tile_cache *tc)
+{
+ struct pipe_screen *screen;
+ uint pos;
+
+ for (pos = 0; pos < NUM_ENTRIES; pos++) {
+ /*assert(tc->entries[pos].x < 0);*/
+ }
+ if (tc->transfer) {
+ screen = tc->transfer->texture->screen;
+ screen->tex_transfer_destroy(tc->transfer);
+ }
+ if (tc->tex_trans) {
+ screen = tc->tex_trans->texture->screen;
+ screen->tex_transfer_destroy(tc->tex_trans);
+ }
+
+ FREE( tc );
+}
+
+
+void
+lp_tex_tile_cache_map_transfers(struct llvmpipe_tex_tile_cache *tc)
+{
+ if (tc->transfer && !tc->transfer_map)
+ tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer);
+
+ if (tc->tex_trans && !tc->tex_trans_map)
+ tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans);
+}
+
+
+void
+lp_tex_tile_cache_unmap_transfers(struct llvmpipe_tex_tile_cache *tc)
+{
+ if (tc->transfer_map) {
+ tc->screen->transfer_unmap(tc->screen, tc->transfer);
+ tc->transfer_map = NULL;
+ }
+
+ if (tc->tex_trans_map) {
+ tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
+ tc->tex_trans_map = NULL;
+ }
+}
+
+void
+lp_tex_tile_cache_validate_texture(struct llvmpipe_tex_tile_cache *tc)
+{
+ if (tc->texture) {
+ struct llvmpipe_texture *lpt = llvmpipe_texture(tc->texture);
+ if (lpt->timestamp != tc->timestamp) {
+ /* texture was modified, invalidate all cached tiles */
+ uint i;
+ debug_printf("INV %d %d\n", tc->timestamp, lpt->timestamp);
+ for (i = 0; i < NUM_ENTRIES; i++) {
+ tc->entries[i].addr.bits.invalid = 1;
+ }
+
+ tc->timestamp = lpt->timestamp;
+ }
+ }
+}
+
+/**
+ * Specify the texture to cache.
+ */
+void
+lp_tex_tile_cache_set_texture(struct llvmpipe_tex_tile_cache *tc,
+ struct pipe_texture *texture)
+{
+ uint i;
+
+ assert(!tc->transfer);
+
+ if (tc->texture != texture) {
+ pipe_texture_reference(&tc->texture, texture);
+
+ if (tc->tex_trans) {
+ struct pipe_screen *screen = tc->tex_trans->texture->screen;
+
+ if (tc->tex_trans_map) {
+ screen->transfer_unmap(screen, tc->tex_trans);
+ tc->tex_trans_map = NULL;
+ }
+
+ screen->tex_transfer_destroy(tc->tex_trans);
+ tc->tex_trans = NULL;
+ }
+
+ /* mark as entries as invalid/empty */
+ /* XXX we should try to avoid this when the teximage hasn't changed */
+ for (i = 0; i < NUM_ENTRIES; i++) {
+ tc->entries[i].addr.bits.invalid = 1;
+ }
+
+ tc->tex_face = -1; /* any invalid value here */
+ }
+}
+
+
+/**
+ * Given the texture face, level, zslice, x and y values, compute
+ * the cache entry position/index where we'd hope to find the
+ * cached texture tile.
+ * This is basically a direct-map cache.
+ * XXX There's probably lots of ways in which we can improve this.
+ */
+static INLINE uint
+tex_cache_pos( union tex_tile_address addr )
+{
+ uint entry = (addr.bits.x +
+ addr.bits.y * 9 +
+ addr.bits.z * 3 +
+ addr.bits.face +
+ addr.bits.level * 7);
+
+ return entry % NUM_ENTRIES;
+}
+
+/**
+ * Similar to lp_get_cached_tile() but for textures.
+ * Tiles are read-only and indexed with more params.
+ */
+const struct llvmpipe_cached_tex_tile *
+lp_find_cached_tex_tile(struct llvmpipe_tex_tile_cache *tc,
+ union tex_tile_address addr )
+{
+ struct pipe_screen *screen = tc->screen;
+ struct llvmpipe_cached_tex_tile *tile;
+
+ tile = tc->entries + tex_cache_pos( addr );
+
+ if (addr.value != tile->addr.value) {
+
+ /* cache miss. Most misses are because we've invaldiated the
+ * texture cache previously -- most commonly on binding a new
+ * texture. Currently we effectively flush the cache on texture
+ * bind.
+ */
+#if 0
+ _debug_printf("miss at %u: x=%d y=%d z=%d face=%d level=%d\n"
+ " tile %u: x=%d y=%d z=%d face=%d level=%d\n",
+ pos, x/TEX_TILE_SIZE, y/TEX_TILE_SIZE, z, face, level,
+ pos, tile->addr.bits.x, tile->addr.bits.y, tile->z, tile->face, tile->level);
+#endif
+
+ /* check if we need to get a new transfer */
+ if (!tc->tex_trans ||
+ tc->tex_face != addr.bits.face ||
+ tc->tex_level != addr.bits.level ||
+ tc->tex_z != addr.bits.z) {
+ /* get new transfer (view into texture) */
+
+ if (tc->tex_trans) {
+ if (tc->tex_trans_map) {
+ tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
+ tc->tex_trans_map = NULL;
+ }
+
+ screen->tex_transfer_destroy(tc->tex_trans);
+ tc->tex_trans = NULL;
+ }
+
+ tc->tex_trans =
+ screen->get_tex_transfer(screen, tc->texture,
+ addr.bits.face,
+ addr.bits.level,
+ addr.bits.z,
+ PIPE_TRANSFER_READ, 0, 0,
+ tc->texture->width[addr.bits.level],
+ tc->texture->height[addr.bits.level]);
+
+ tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans);
+
+ tc->tex_face = addr.bits.face;
+ tc->tex_level = addr.bits.level;
+ tc->tex_z = addr.bits.z;
+ }
+
+ {
+ unsigned x = addr.bits.x * TEX_TILE_SIZE;
+ unsigned y = addr.bits.y * TEX_TILE_SIZE;
+ unsigned w = TEX_TILE_SIZE;
+ unsigned h = TEX_TILE_SIZE;
+
+ if (pipe_clip_tile(x, y, &w, &h, tc->tex_trans)) {
+ assert(0);
+ }
+
+ util_format_read_4ub(tc->tex_trans->format,
+ (uint8_t *)tile->color, sizeof tile->color[0],
+ tc->tex_trans_map, tc->tex_trans->stride,
+ x, y, w, h);
+ }
+
+ tile->addr = addr;
+ }
+
+ tc->last_tile = tile;
+ return tile;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_tex_cache.h b/src/gallium/drivers/llvmpipe/lp_tex_cache.h
new file mode 100644
index 0000000000..9fa6c36812
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_tex_cache.h
@@ -0,0 +1,151 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_TEX_CACHE_H
+#define LP_TEX_CACHE_H
+
+
+#include "pipe/p_compiler.h"
+
+
+struct llvmpipe_context;
+struct llvmpipe_tex_tile_cache;
+
+
+/**
+ * Cache tile size (width and height). This needs to be a power of two.
+ */
+#define TEX_TILE_SIZE 64
+
+
+/* If we need to support > 4096, just expand this to be a 64 bit
+ * union, or consider tiling in Z as well.
+ */
+union tex_tile_address {
+ struct {
+ unsigned x:6; /* 4096 / TEX_TILE_SIZE */
+ unsigned y:6; /* 4096 / TEX_TILE_SIZE */
+ unsigned z:12; /* 4096 -- z not tiled */
+ unsigned face:3;
+ unsigned level:4;
+ unsigned invalid:1;
+ } bits;
+ unsigned value;
+};
+
+
+struct llvmpipe_cached_tex_tile
+{
+ union tex_tile_address addr;
+ uint8_t color[TEX_TILE_SIZE][TEX_TILE_SIZE][4];
+};
+
+#define NUM_ENTRIES 50
+
+
+/** XXX move these */
+#define MAX_TEX_WIDTH 2048
+#define MAX_TEX_HEIGHT 2048
+
+
+struct llvmpipe_tex_tile_cache
+{
+ struct pipe_screen *screen;
+ struct pipe_surface *surface; /**< the surface we're caching */
+ struct pipe_transfer *transfer;
+ void *transfer_map;
+
+ struct pipe_texture *texture; /**< if caching a texture */
+ unsigned timestamp;
+
+ struct llvmpipe_cached_tex_tile entries[NUM_ENTRIES];
+
+ struct pipe_transfer *tex_trans;
+ void *tex_trans_map;
+ int tex_face, tex_level, tex_z;
+
+ struct llvmpipe_cached_tex_tile *last_tile; /**< most recently retrieved tile */
+};
+
+
+extern struct llvmpipe_tex_tile_cache *
+lp_create_tex_tile_cache( struct pipe_screen *screen );
+
+extern void
+lp_destroy_tex_tile_cache(struct llvmpipe_tex_tile_cache *tc);
+
+extern void
+lp_tex_tile_cache_map_transfers(struct llvmpipe_tex_tile_cache *tc);
+
+extern void
+lp_tex_tile_cache_unmap_transfers(struct llvmpipe_tex_tile_cache *tc);
+
+extern void
+lp_tex_tile_cache_set_texture(struct llvmpipe_tex_tile_cache *tc,
+ struct pipe_texture *texture);
+
+void
+lp_tex_tile_cache_validate_texture(struct llvmpipe_tex_tile_cache *tc);
+
+extern const struct llvmpipe_cached_tex_tile *
+lp_find_cached_tex_tile(struct llvmpipe_tex_tile_cache *tc,
+ union tex_tile_address addr );
+
+static INLINE const union tex_tile_address
+tex_tile_address( unsigned x,
+ unsigned y,
+ unsigned z,
+ unsigned face,
+ unsigned level )
+{
+ union tex_tile_address addr;
+
+ addr.value = 0;
+ addr.bits.x = x / TEX_TILE_SIZE;
+ addr.bits.y = y / TEX_TILE_SIZE;
+ addr.bits.z = z;
+ addr.bits.face = face;
+ addr.bits.level = level;
+
+ return addr;
+}
+
+/* Quickly retrieve tile if it matches last lookup.
+ */
+static INLINE const struct llvmpipe_cached_tex_tile *
+lp_get_cached_tex_tile(struct llvmpipe_tex_tile_cache *tc,
+ union tex_tile_address addr )
+{
+ if (tc->last_tile->addr.value == addr.value)
+ return tc->last_tile;
+
+ return lp_find_cached_tex_tile( tc, addr );
+}
+
+
+#endif /* LP_TEX_CACHE_H */
+
diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.h b/src/gallium/drivers/llvmpipe/lp_tex_sample.h
new file mode 100644
index 0000000000..9ad1bde956
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.h
@@ -0,0 +1,101 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_TEX_SAMPLE_H
+#define LP_TEX_SAMPLE_H
+
+
+#include <llvm-c/Core.h>
+
+#include "tgsi/tgsi_exec.h"
+
+
+struct llvmpipe_tex_tile_cache;
+struct lp_sampler_static_state;
+
+
+/**
+ * Subclass of tgsi_sampler
+ */
+struct lp_shader_sampler
+{
+ struct tgsi_sampler base; /**< base class */
+
+ unsigned processor;
+
+ /* For lp_get_samples_2d_linear_POT:
+ */
+ unsigned xpot;
+ unsigned ypot;
+ unsigned level;
+
+ const struct pipe_texture *texture;
+ const struct pipe_sampler_state *sampler;
+
+ struct llvmpipe_tex_tile_cache *cache;
+};
+
+
+
+static INLINE struct lp_shader_sampler *
+lp_shader_sampler(const struct tgsi_sampler *sampler)
+{
+ return (struct lp_shader_sampler *) sampler;
+}
+
+
+
+extern void
+lp_get_samples(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE]);
+
+
+/**
+ * Texture sampling code generator that just calls lp_get_samples C function
+ * for the actual sampling computation.
+ *
+ * @param context_ptr LLVM value with the pointer to the struct lp_jit_context.
+ */
+struct lp_build_sampler_soa *
+lp_c_sampler_soa_create(LLVMValueRef context_ptr);
+
+
+/**
+ * Pure-LLVM texture sampling code generator.
+ *
+ * @param context_ptr LLVM value with the pointer to the struct lp_jit_context.
+ */
+struct lp_build_sampler_soa *
+lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *key,
+ LLVMValueRef context_ptr);
+
+
+#endif /* LP_TEX_SAMPLE_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample_c.c b/src/gallium/drivers/llvmpipe/lp_tex_sample_c.c
new file mode 100644
index 0000000000..9a876f404d
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_tex_sample_c.c
@@ -0,0 +1,1713 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2008 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/**
+ * Texture sampling
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+#include "lp_context.h"
+#include "lp_quad.h"
+#include "lp_surface.h"
+#include "lp_texture.h"
+#include "lp_tex_sample.h"
+#include "lp_tex_cache.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+
+
+/*
+ * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
+ * see 1-pixel bands of improperly weighted linear-filtered textures.
+ * The tests/texwrap.c demo is a good test.
+ * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
+ * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
+ */
+#define FRAC(f) ((f) - util_ifloor(f))
+
+
+/**
+ * Linear interpolation macro
+ */
+static INLINE float
+lerp(float a, float v0, float v1)
+{
+ return v0 + a * (v1 - v0);
+}
+
+
+/**
+ * Do 2D/biliner interpolation of float values.
+ * v00, v10, v01 and v11 are typically four texture samples in a square/box.
+ * a and b are the horizontal and vertical interpolants.
+ * It's important that this function is inlined when compiled with
+ * optimization! If we find that's not true on some systems, convert
+ * to a macro.
+ */
+static INLINE float
+lerp_2d(float a, float b,
+ float v00, float v10, float v01, float v11)
+{
+ const float temp0 = lerp(a, v00, v10);
+ const float temp1 = lerp(a, v01, v11);
+ return lerp(b, temp0, temp1);
+}
+
+
+/**
+ * As above, but 3D interpolation of 8 values.
+ */
+static INLINE float
+lerp_3d(float a, float b, float c,
+ float v000, float v100, float v010, float v110,
+ float v001, float v101, float v011, float v111)
+{
+ const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
+ const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
+ return lerp(c, temp0, temp1);
+}
+
+
+
+/**
+ * If A is a signed integer, A % B doesn't give the right value for A < 0
+ * (in terms of texture repeat). Just casting to unsigned fixes that.
+ */
+#define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))
+
+
+/**
+ * Apply texture coord wrapping mode and return integer texture indexes
+ * for a vector of four texcoords (S or T or P).
+ * \param wrapMode PIPE_TEX_WRAP_x
+ * \param s the incoming texcoords
+ * \param size the texture image size
+ * \param icoord returns the integer texcoords
+ * \return integer texture index
+ */
+static INLINE void
+nearest_texcoord_4(unsigned wrapMode, const float s[4], unsigned size,
+ int icoord[4])
+{
+ uint ch;
+ switch (wrapMode) {
+ case PIPE_TEX_WRAP_REPEAT:
+ /* s limited to [0,1) */
+ /* i limited to [0,size-1] */
+ for (ch = 0; ch < 4; ch++) {
+ int i = util_ifloor(s[ch] * size);
+ icoord[ch] = REMAINDER(i, size);
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP:
+ /* s limited to [0,1] */
+ /* i limited to [0,size-1] */
+ for (ch = 0; ch < 4; ch++) {
+ if (s[ch] <= 0.0F)
+ icoord[ch] = 0;
+ else if (s[ch] >= 1.0F)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(s[ch] * size);
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [0, size-1] */
+ const float min = 1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ if (s[ch] < min)
+ icoord[ch] = 0;
+ else if (s[ch] > max)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(s[ch] * size);
+ }
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [-1, size] */
+ const float min = -1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ if (s[ch] <= min)
+ icoord[ch] = -1;
+ else if (s[ch] >= max)
+ icoord[ch] = size;
+ else
+ icoord[ch] = util_ifloor(s[ch] * size);
+ }
+ }
+ return;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ {
+ const float min = 1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ const int flr = util_ifloor(s[ch]);
+ float u;
+ if (flr & 1)
+ u = 1.0F - (s[ch] - (float) flr);
+ else
+ u = s[ch] - (float) flr;
+ if (u < min)
+ icoord[ch] = 0;
+ else if (u > max)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(u * size);
+ }
+ }
+ return;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ /* s limited to [0,1] */
+ /* i limited to [0,size-1] */
+ const float u = fabsf(s[ch]);
+ if (u <= 0.0F)
+ icoord[ch] = 0;
+ else if (u >= 1.0F)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(u * size);
+ }
+ return;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [0, size-1] */
+ const float min = 1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ const float u = fabsf(s[ch]);
+ if (u < min)
+ icoord[ch] = 0;
+ else if (u > max)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(u * size);
+ }
+ }
+ return;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [0, size-1] */
+ const float min = -1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ const float u = fabsf(s[ch]);
+ if (u < min)
+ icoord[ch] = -1;
+ else if (u > max)
+ icoord[ch] = size;
+ else
+ icoord[ch] = util_ifloor(u * size);
+ }
+ }
+ return;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Used to compute texel locations for linear sampling for four texcoords.
+ * \param wrapMode PIPE_TEX_WRAP_x
+ * \param s the texcoords
+ * \param size the texture image size
+ * \param icoord0 returns first texture indexes
+ * \param icoord1 returns second texture indexes (usually icoord0 + 1)
+ * \param w returns blend factor/weight between texture indexes
+ * \param icoord returns the computed integer texture coords
+ */
+static INLINE void
+linear_texcoord_4(unsigned wrapMode, const float s[4], unsigned size,
+ int icoord0[4], int icoord1[4], float w[4])
+{
+ uint ch;
+
+ switch (wrapMode) {
+ case PIPE_TEX_WRAP_REPEAT:
+ for (ch = 0; ch < 4; ch++) {
+ float u = s[ch] * size - 0.5F;
+ icoord0[ch] = REMAINDER(util_ifloor(u), size);
+ icoord1[ch] = REMAINDER(icoord0[ch] + 1, size);
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ float u = CLAMP(s[ch], 0.0F, 1.0F);
+ u = u * size - 0.5f;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ for (ch = 0; ch < 4; ch++) {
+ float u = CLAMP(s[ch], 0.0F, 1.0F);
+ u = u * size - 0.5f;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ if (icoord0[ch] < 0)
+ icoord0[ch] = 0;
+ if (icoord1[ch] >= (int) size)
+ icoord1[ch] = size - 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ {
+ const float min = -1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ float u = CLAMP(s[ch], min, max);
+ u = u * size - 0.5f;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ }
+ break;;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ for (ch = 0; ch < 4; ch++) {
+ const int flr = util_ifloor(s[ch]);
+ float u;
+ if (flr & 1)
+ u = 1.0F - (s[ch] - (float) flr);
+ else
+ u = s[ch] - (float) flr;
+ u = u * size - 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ if (icoord0[ch] < 0)
+ icoord0[ch] = 0;
+ if (icoord1[ch] >= (int) size)
+ icoord1[ch] = size - 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ float u = fabsf(s[ch]);
+ if (u >= 1.0F)
+ u = (float) size;
+ else
+ u *= size;
+ u -= 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ for (ch = 0; ch < 4; ch++) {
+ float u = fabsf(s[ch]);
+ if (u >= 1.0F)
+ u = (float) size;
+ else
+ u *= size;
+ u -= 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ if (icoord0[ch] < 0)
+ icoord0[ch] = 0;
+ if (icoord1[ch] >= (int) size)
+ icoord1[ch] = size - 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ {
+ const float min = -1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ float u = fabsf(s[ch]);
+ if (u <= min)
+ u = min * size;
+ else if (u >= max)
+ u = max * size;
+ else
+ u *= size;
+ u -= 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ }
+ break;;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * For RECT textures / unnormalized texcoords
+ * Only a subset of wrap modes supported.
+ */
+static INLINE void
+nearest_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size,
+ int icoord[4])
+{
+ uint ch;
+ switch (wrapMode) {
+ case PIPE_TEX_WRAP_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ int i = util_ifloor(s[ch]);
+ icoord[ch]= CLAMP(i, 0, (int) size-1);
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ /* fall-through */
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ for (ch = 0; ch < 4; ch++) {
+ icoord[ch]= util_ifloor( CLAMP(s[ch], 0.5F, (float) size - 0.5F) );
+ }
+ return;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * For RECT textures / unnormalized texcoords.
+ * Only a subset of wrap modes supported.
+ */
+static INLINE void
+linear_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size,
+ int icoord0[4], int icoord1[4], float w[4])
+{
+ uint ch;
+ switch (wrapMode) {
+ case PIPE_TEX_WRAP_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ /* Not exactly what the spec says, but it matches NVIDIA output */
+ float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f);
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ /* fall-through */
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ for (ch = 0; ch < 4; ch++) {
+ float u = CLAMP(s[ch], 0.5F, (float) size - 0.5F);
+ u -= 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ if (icoord1[ch] > (int) size - 1)
+ icoord1[ch] = size - 1;
+ w[ch] = FRAC(u);
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+static unsigned
+choose_cube_face(float rx, float ry, float rz, float *newS, float *newT)
+{
+ /*
+ major axis
+ direction target sc tc ma
+ ---------- ------------------------------- --- --- ---
+ +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
+ -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
+ +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
+ -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
+ +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
+ -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
+ */
+ const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
+ unsigned face;
+ float sc, tc, ma;
+
+ if (arx > ary && arx > arz) {
+ if (rx >= 0.0F) {
+ face = PIPE_TEX_FACE_POS_X;
+ sc = -rz;
+ tc = -ry;
+ ma = arx;
+ }
+ else {
+ face = PIPE_TEX_FACE_NEG_X;
+ sc = rz;
+ tc = -ry;
+ ma = arx;
+ }
+ }
+ else if (ary > arx && ary > arz) {
+ if (ry >= 0.0F) {
+ face = PIPE_TEX_FACE_POS_Y;
+ sc = rx;
+ tc = rz;
+ ma = ary;
+ }
+ else {
+ face = PIPE_TEX_FACE_NEG_Y;
+ sc = rx;
+ tc = -rz;
+ ma = ary;
+ }
+ }
+ else {
+ if (rz > 0.0F) {
+ face = PIPE_TEX_FACE_POS_Z;
+ sc = rx;
+ tc = -ry;
+ ma = arz;
+ }
+ else {
+ face = PIPE_TEX_FACE_NEG_Z;
+ sc = -rx;
+ tc = -ry;
+ ma = arz;
+ }
+ }
+
+ *newS = ( sc / ma + 1.0F ) * 0.5F;
+ *newT = ( tc / ma + 1.0F ) * 0.5F;
+
+ return face;
+}
+
+
+/**
+ * Examine the quad's texture coordinates to compute the partial
+ * derivatives w.r.t X and Y, then compute lambda (level of detail).
+ *
+ * This is only done for fragment shaders, not vertex shaders.
+ */
+static float
+compute_lambda(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias)
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ const struct pipe_texture *texture = samp->texture;
+ const struct pipe_sampler_state *sampler = samp->sampler;
+ float rho, lambda;
+
+ if (samp->processor == TGSI_PROCESSOR_VERTEX)
+ return lodbias;
+
+ assert(sampler->normalized_coords);
+
+ assert(s);
+ {
+ float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT];
+ float dsdy = s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT];
+ dsdx = fabsf(dsdx);
+ dsdy = fabsf(dsdy);
+ rho = MAX2(dsdx, dsdy) * texture->width[0];
+ }
+ if (t) {
+ float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT];
+ float dtdy = t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT];
+ float max;
+ dtdx = fabsf(dtdx);
+ dtdy = fabsf(dtdy);
+ max = MAX2(dtdx, dtdy) * texture->height[0];
+ rho = MAX2(rho, max);
+ }
+ if (p) {
+ float dpdx = p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT];
+ float dpdy = p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT];
+ float max;
+ dpdx = fabsf(dpdx);
+ dpdy = fabsf(dpdy);
+ max = MAX2(dpdx, dpdy) * texture->depth[0];
+ rho = MAX2(rho, max);
+ }
+
+ lambda = util_fast_log2(rho);
+ lambda += lodbias + sampler->lod_bias;
+ lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod);
+
+ return lambda;
+}
+
+
+/**
+ * Do several things here:
+ * 1. Compute lambda from the texcoords, if needed
+ * 2. Determine if we're minifying or magnifying
+ * 3. If minifying, choose mipmap levels
+ * 4. Return image filter to use within mipmap images
+ * \param level0 Returns first mipmap level to sample from
+ * \param level1 Returns second mipmap level to sample from
+ * \param levelBlend Returns blend factor between levels, in [0,1]
+ * \param imgFilter Returns either the min or mag filter, depending on lambda
+ */
+static void
+choose_mipmap_levels(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ unsigned *level0, unsigned *level1, float *levelBlend,
+ unsigned *imgFilter)
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ const struct pipe_texture *texture = samp->texture;
+ const struct pipe_sampler_state *sampler = samp->sampler;
+
+ if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
+ /* no mipmap selection needed */
+ *level0 = *level1 = CLAMP((int) sampler->min_lod,
+ 0, (int) texture->last_level);
+
+ if (sampler->min_img_filter != sampler->mag_img_filter) {
+ /* non-mipmapped texture, but still need to determine if doing
+ * minification or magnification.
+ */
+ float lambda = compute_lambda(tgsi_sampler, s, t, p, lodbias);
+ if (lambda <= 0.0) {
+ *imgFilter = sampler->mag_img_filter;
+ }
+ else {
+ *imgFilter = sampler->min_img_filter;
+ }
+ }
+ else {
+ *imgFilter = sampler->mag_img_filter;
+ }
+ }
+ else {
+ float lambda = compute_lambda(tgsi_sampler, s, t, p, lodbias);
+
+ if (lambda <= 0.0) { /* XXX threshold depends on the filter */
+ /* magnifying */
+ *imgFilter = sampler->mag_img_filter;
+ *level0 = *level1 = 0;
+ }
+ else {
+ /* minifying */
+ *imgFilter = sampler->min_img_filter;
+
+ /* choose mipmap level(s) and compute the blend factor between them */
+ if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
+ /* Nearest mipmap level */
+ const int lvl = (int) (lambda + 0.5);
+ *level0 =
+ *level1 = CLAMP(lvl, 0, (int) texture->last_level);
+ }
+ else {
+ /* Linear interpolation between mipmap levels */
+ const int lvl = (int) lambda;
+ *level0 = CLAMP(lvl, 0, (int) texture->last_level);
+ *level1 = CLAMP(lvl + 1, 0, (int) texture->last_level);
+ *levelBlend = FRAC(lambda); /* blending weight between levels */
+ }
+ }
+ }
+}
+
+
+/**
+ * Get a texel from a texture, using the texture tile cache.
+ *
+ * \param face the cube face in 0..5
+ * \param level the mipmap level
+ * \param x the x coord of texel within 2D image
+ * \param y the y coord of texel within 2D image
+ * \param z which slice of a 3D texture
+ * \param rgba the quad to put the texel/color into
+ * \param j which element of the rgba quad to write to
+ *
+ * XXX maybe move this into lp_tile_cache.c and merge with the
+ * lp_get_cached_tile_tex() function. Also, get 4 texels instead of 1...
+ */
+static void
+get_texel_quad_2d(const struct tgsi_sampler *tgsi_sampler,
+ unsigned face, unsigned level, int x, int y,
+ const uint8_t *out[4])
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+
+ const struct llvmpipe_cached_tex_tile *tile
+ = lp_get_cached_tex_tile(samp->cache,
+ tex_tile_address(x, y, 0, face, level));
+
+ y %= TEX_TILE_SIZE;
+ x %= TEX_TILE_SIZE;
+
+ out[0] = &tile->color[y ][x ][0];
+ out[1] = &tile->color[y ][x+1][0];
+ out[2] = &tile->color[y+1][x ][0];
+ out[3] = &tile->color[y+1][x+1][0];
+}
+
+static INLINE const uint8_t *
+get_texel_2d_ptr(const struct tgsi_sampler *tgsi_sampler,
+ unsigned face, unsigned level, int x, int y)
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+
+ const struct llvmpipe_cached_tex_tile *tile
+ = lp_get_cached_tex_tile(samp->cache,
+ tex_tile_address(x, y, 0, face, level));
+
+ y %= TEX_TILE_SIZE;
+ x %= TEX_TILE_SIZE;
+
+ return &tile->color[y][x][0];
+}
+
+
+static void
+get_texel_quad_2d_mt(const struct tgsi_sampler *tgsi_sampler,
+ unsigned face, unsigned level,
+ int x0, int y0,
+ int x1, int y1,
+ const uint8_t *out[4])
+{
+ unsigned i;
+
+ for (i = 0; i < 4; i++) {
+ unsigned tx = (i & 1) ? x1 : x0;
+ unsigned ty = (i >> 1) ? y1 : y0;
+
+ out[i] = get_texel_2d_ptr( tgsi_sampler, face, level, tx, ty );
+ }
+}
+
+static void
+get_texel(const struct tgsi_sampler *tgsi_sampler,
+ unsigned face, unsigned level, int x, int y, int z,
+ float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j)
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ const struct pipe_texture *texture = samp->texture;
+ const struct pipe_sampler_state *sampler = samp->sampler;
+
+ if (x < 0 || x >= (int) texture->width[level] ||
+ y < 0 || y >= (int) texture->height[level] ||
+ z < 0 || z >= (int) texture->depth[level]) {
+ rgba[0][j] = sampler->border_color[0];
+ rgba[1][j] = sampler->border_color[1];
+ rgba[2][j] = sampler->border_color[2];
+ rgba[3][j] = sampler->border_color[3];
+ }
+ else {
+ const unsigned tx = x % TEX_TILE_SIZE;
+ const unsigned ty = y % TEX_TILE_SIZE;
+ const struct llvmpipe_cached_tex_tile *tile;
+
+ tile = lp_get_cached_tex_tile(samp->cache,
+ tex_tile_address(x, y, z, face, level));
+
+ rgba[0][j] = ubyte_to_float(tile->color[ty][tx][0]);
+ rgba[1][j] = ubyte_to_float(tile->color[ty][tx][1]);
+ rgba[2][j] = ubyte_to_float(tile->color[ty][tx][2]);
+ rgba[3][j] = ubyte_to_float(tile->color[ty][tx][3]);
+ if (0)
+ {
+ debug_printf("Get texel %f %f %f %f from %s\n",
+ rgba[0][j], rgba[1][j], rgba[2][j], rgba[3][j],
+ pf_name(texture->format));
+ }
+ }
+}
+
+
+/**
+ * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
+ * When we sampled the depth texture, the depth value was put into all
+ * RGBA channels. We look at the red channel here.
+ * \param rgba quad of (depth) texel values
+ * \param p texture 'P' components for four pixels in quad
+ * \param j which pixel in the quad to test [0..3]
+ */
+static INLINE void
+shadow_compare(const struct pipe_sampler_state *sampler,
+ float rgba[NUM_CHANNELS][QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ uint j)
+{
+ int k;
+ switch (sampler->compare_func) {
+ case PIPE_FUNC_LESS:
+ k = p[j] < rgba[0][j];
+ break;
+ case PIPE_FUNC_LEQUAL:
+ k = p[j] <= rgba[0][j];
+ break;
+ case PIPE_FUNC_GREATER:
+ k = p[j] > rgba[0][j];
+ break;
+ case PIPE_FUNC_GEQUAL:
+ k = p[j] >= rgba[0][j];
+ break;
+ case PIPE_FUNC_EQUAL:
+ k = p[j] == rgba[0][j];
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ k = p[j] != rgba[0][j];
+ break;
+ case PIPE_FUNC_ALWAYS:
+ k = 1;
+ break;
+ case PIPE_FUNC_NEVER:
+ k = 0;
+ break;
+ default:
+ k = 0;
+ assert(0);
+ break;
+ }
+
+ /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
+ rgba[0][j] = rgba[1][j] = rgba[2][j] = (float) k;
+ rgba[3][j] = 1.0F;
+}
+
+
+/**
+ * As above, but do four z/texture comparisons.
+ */
+static INLINE void
+shadow_compare4(const struct pipe_sampler_state *sampler,
+ float rgba[NUM_CHANNELS][QUAD_SIZE],
+ const float p[QUAD_SIZE])
+{
+ int j, k0, k1, k2, k3;
+ float val;
+
+ /* compare four texcoords vs. four texture samples */
+ switch (sampler->compare_func) {
+ case PIPE_FUNC_LESS:
+ k0 = p[0] < rgba[0][0];
+ k1 = p[1] < rgba[0][1];
+ k2 = p[2] < rgba[0][2];
+ k3 = p[3] < rgba[0][3];
+ break;
+ case PIPE_FUNC_LEQUAL:
+ k0 = p[0] <= rgba[0][0];
+ k1 = p[1] <= rgba[0][1];
+ k2 = p[2] <= rgba[0][2];
+ k3 = p[3] <= rgba[0][3];
+ break;
+ case PIPE_FUNC_GREATER:
+ k0 = p[0] > rgba[0][0];
+ k1 = p[1] > rgba[0][1];
+ k2 = p[2] > rgba[0][2];
+ k3 = p[3] > rgba[0][3];
+ break;
+ case PIPE_FUNC_GEQUAL:
+ k0 = p[0] >= rgba[0][0];
+ k1 = p[1] >= rgba[0][1];
+ k2 = p[2] >= rgba[0][2];
+ k3 = p[3] >= rgba[0][3];
+ break;
+ case PIPE_FUNC_EQUAL:
+ k0 = p[0] == rgba[0][0];
+ k1 = p[1] == rgba[0][1];
+ k2 = p[2] == rgba[0][2];
+ k3 = p[3] == rgba[0][3];
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ k0 = p[0] != rgba[0][0];
+ k1 = p[1] != rgba[0][1];
+ k2 = p[2] != rgba[0][2];
+ k3 = p[3] != rgba[0][3];
+ break;
+ case PIPE_FUNC_ALWAYS:
+ k0 = k1 = k2 = k3 = 1;
+ break;
+ case PIPE_FUNC_NEVER:
+ k0 = k1 = k2 = k3 = 0;
+ break;
+ default:
+ k0 = k1 = k2 = k3 = 0;
+ assert(0);
+ break;
+ }
+
+ /* convert four pass/fail values to an intensity in [0,1] */
+ val = 0.25F * (k0 + k1 + k2 + k3);
+
+ /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
+ for (j = 0; j < 4; j++) {
+ rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
+ rgba[3][j] = 1.0F;
+ }
+}
+
+
+
+static void
+lp_get_samples_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ unsigned j;
+ unsigned level = samp->level;
+ unsigned xpot = 1 << (samp->xpot - level);
+ unsigned ypot = 1 << (samp->ypot - level);
+ unsigned xmax = (xpot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, xpot) - 1; */
+ unsigned ymax = (ypot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, ypot) - 1; */
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int c;
+
+ float u = s[j] * xpot - 0.5F;
+ float v = t[j] * ypot - 0.5F;
+
+ int uflr = util_ifloor(u);
+ int vflr = util_ifloor(v);
+
+ float xw = u - (float)uflr;
+ float yw = v - (float)vflr;
+
+ int x0 = uflr & (xpot - 1);
+ int y0 = vflr & (ypot - 1);
+
+ const uint8_t *tx[4];
+
+
+ /* Can we fetch all four at once:
+ */
+ if (x0 < xmax && y0 < ymax)
+ {
+ get_texel_quad_2d(tgsi_sampler, 0, level, x0, y0, tx);
+ }
+ else
+ {
+ unsigned x1 = (x0 + 1) & (xpot - 1);
+ unsigned y1 = (y0 + 1) & (ypot - 1);
+ get_texel_quad_2d_mt(tgsi_sampler, 0, level,
+ x0, y0, x1, y1, tx);
+ }
+
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp_2d(xw, yw,
+ ubyte_to_float(tx[0][c]), ubyte_to_float(tx[1][c]),
+ ubyte_to_float(tx[2][c]), ubyte_to_float(tx[3][c]));
+ }
+ }
+}
+
+
+static void
+lp_get_samples_2d_nearest_repeat_POT(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ unsigned j;
+ unsigned level = samp->level;
+ unsigned xpot = 1 << (samp->xpot - level);
+ unsigned ypot = 1 << (samp->ypot - level);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int c;
+
+ float u = s[j] * xpot;
+ float v = t[j] * ypot;
+
+ int uflr = util_ifloor(u);
+ int vflr = util_ifloor(v);
+
+ int x0 = uflr & (xpot - 1);
+ int y0 = vflr & (ypot - 1);
+
+ const uint8_t *out = get_texel_2d_ptr(tgsi_sampler, 0, level, x0, y0);
+
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = ubyte_to_float(out[c]);
+ }
+ }
+}
+
+
+static void
+lp_get_samples_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ unsigned j;
+ unsigned level = samp->level;
+ unsigned xpot = 1 << (samp->xpot - level);
+ unsigned ypot = 1 << (samp->ypot - level);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int c;
+
+ float u = s[j] * xpot;
+ float v = t[j] * ypot;
+
+ int x0, y0;
+ const uint8_t *out;
+
+ x0 = util_ifloor(u);
+ if (x0 < 0)
+ x0 = 0;
+ else if (x0 > xpot - 1)
+ x0 = xpot - 1;
+
+ y0 = util_ifloor(v);
+ if (y0 < 0)
+ y0 = 0;
+ else if (y0 > ypot - 1)
+ y0 = ypot - 1;
+
+ out = get_texel_2d_ptr(tgsi_sampler, 0, level, x0, y0);
+
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = ubyte_to_float(out[c]);
+ }
+ }
+}
+
+
+static void
+lp_get_samples_2d_linear_mip_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ const struct pipe_texture *texture = samp->texture;
+ int level0;
+ float lambda;
+
+ lambda = compute_lambda(tgsi_sampler, s, t, p, lodbias);
+ level0 = (int)lambda;
+
+ if (lambda < 0.0) {
+ samp->level = 0;
+ lp_get_samples_2d_linear_repeat_POT( tgsi_sampler,
+ s, t, p, 0, rgba );
+ }
+ else if (level0 >= texture->last_level) {
+ samp->level = texture->last_level;
+ lp_get_samples_2d_linear_repeat_POT( tgsi_sampler,
+ s, t, p, 0, rgba );
+ }
+ else {
+ float levelBlend = lambda - level0;
+ float rgba0[4][4];
+ float rgba1[4][4];
+ int c,j;
+
+ samp->level = level0;
+ lp_get_samples_2d_linear_repeat_POT( tgsi_sampler,
+ s, t, p, 0, rgba0 );
+
+ samp->level = level0+1;
+ lp_get_samples_2d_linear_repeat_POT( tgsi_sampler,
+ s, t, p, 0, rgba1 );
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]);
+ }
+ }
+ }
+}
+
+/**
+ * Common code for sampling 1D/2D/cube textures.
+ * Could probably extend for 3D...
+ */
+static void
+lp_get_samples_2d_common(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE],
+ const unsigned faces[4])
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ const struct pipe_texture *texture = samp->texture;
+ const struct pipe_sampler_state *sampler = samp->sampler;
+ unsigned level0, level1, j, imgFilter;
+ int width, height;
+ float levelBlend;
+
+ choose_mipmap_levels(tgsi_sampler, s, t, p,
+ lodbias,
+ &level0, &level1, &levelBlend, &imgFilter);
+
+ assert(sampler->normalized_coords);
+
+ width = texture->width[level0];
+ height = texture->height[level0];
+
+ assert(width > 0);
+
+ switch (imgFilter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ {
+ int x[4], y[4];
+ nearest_texcoord_4(sampler->wrap_s, s, width, x);
+ nearest_texcoord_4(sampler->wrap_t, t, height, y);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ shadow_compare(sampler, rgba, p, j);
+ }
+
+ if (level0 != level1) {
+ /* get texels from second mipmap level and blend */
+ float rgba2[4][4];
+ unsigned c;
+ x[j] /= 2;
+ y[j] /= 2;
+ get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0,
+ rgba2, j);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
+ shadow_compare(sampler, rgba2, p, j);
+ }
+
+ for (c = 0; c < NUM_CHANNELS; c++) {
+ rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
+ }
+ }
+ }
+ }
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ case PIPE_TEX_FILTER_ANISO:
+ {
+ int x0[4], y0[4], x1[4], y1[4];
+ float xw[4], yw[4]; /* weights */
+
+ linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw);
+ linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ float tx[4][4]; /* texels */
+ int c;
+ get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0);
+ get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1);
+ get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2);
+ get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ shadow_compare4(sampler, tx, p);
+ }
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp_2d(xw[j], yw[j],
+ tx[c][0], tx[c][1],
+ tx[c][2], tx[c][3]);
+ }
+
+ if (level0 != level1) {
+ /* get texels from second mipmap level and blend */
+ float rgba2[4][4];
+
+ /* XXX: This is incorrect -- will often end up with (x0
+ * == x1 && y0 == y1), meaning that we fetch the same
+ * texel four times and linearly interpolate between
+ * identical values. The correct approach would be to
+ * call linear_texcoord again for the second level.
+ */
+ x0[j] /= 2;
+ y0[j] /= 2;
+ x1[j] /= 2;
+ y1[j] /= 2;
+ get_texel(tgsi_sampler, faces[j], level1, x0[j], y0[j], 0, tx, 0);
+ get_texel(tgsi_sampler, faces[j], level1, x1[j], y0[j], 0, tx, 1);
+ get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2);
+ get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
+ shadow_compare4(sampler, tx, p);
+ }
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba2[c][j] = lerp_2d(xw[j], yw[j],
+ tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
+ }
+
+ for (c = 0; c < NUM_CHANNELS; c++) {
+ rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+static INLINE void
+lp_get_samples_1d(struct tgsi_sampler *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ static const unsigned faces[4] = {0, 0, 0, 0};
+ static const float tzero[4] = {0, 0, 0, 0};
+ lp_get_samples_2d_common(sampler, s, tzero, NULL,
+ lodbias, rgba, faces);
+}
+
+
+static INLINE void
+lp_get_samples_2d(struct tgsi_sampler *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ static const unsigned faces[4] = {0, 0, 0, 0};
+ lp_get_samples_2d_common(sampler, s, t, p,
+ lodbias, rgba, faces);
+}
+
+
+static INLINE void
+lp_get_samples_3d(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ const struct pipe_texture *texture = samp->texture;
+ const struct pipe_sampler_state *sampler = samp->sampler;
+ /* get/map pipe_surfaces corresponding to 3D tex slices */
+ unsigned level0, level1, j, imgFilter;
+ int width, height, depth;
+ float levelBlend;
+ const uint face = 0;
+
+ choose_mipmap_levels(tgsi_sampler, s, t, p,
+ lodbias,
+ &level0, &level1, &levelBlend, &imgFilter);
+
+ assert(sampler->normalized_coords);
+
+ width = texture->width[level0];
+ height = texture->height[level0];
+ depth = texture->depth[level0];
+
+ assert(width > 0);
+ assert(height > 0);
+ assert(depth > 0);
+
+ switch (imgFilter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ {
+ int x[4], y[4], z[4];
+ nearest_texcoord_4(sampler->wrap_s, s, width, x);
+ nearest_texcoord_4(sampler->wrap_t, t, height, y);
+ nearest_texcoord_4(sampler->wrap_r, p, depth, z);
+ for (j = 0; j < QUAD_SIZE; j++) {
+ get_texel(tgsi_sampler, face, level0, x[j], y[j], z[j], rgba, j);
+ if (level0 != level1) {
+ /* get texels from second mipmap level and blend */
+ float rgba2[4][4];
+ unsigned c;
+ x[j] /= 2;
+ y[j] /= 2;
+ z[j] /= 2;
+ get_texel(tgsi_sampler, face, level1, x[j], y[j], z[j], rgba2, j);
+ for (c = 0; c < NUM_CHANNELS; c++) {
+ rgba[c][j] = lerp(levelBlend, rgba2[c][j], rgba[c][j]);
+ }
+ }
+ }
+ }
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ case PIPE_TEX_FILTER_ANISO:
+ {
+ int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4];
+ float xw[4], yw[4], zw[4]; /* interpolation weights */
+ linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw);
+ linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw);
+ linear_texcoord_4(sampler->wrap_r, p, depth, z0, z1, zw);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int c;
+ float tx0[4][4], tx1[4][4];
+ get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z0[j], tx0, 0);
+ get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z0[j], tx0, 1);
+ get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z0[j], tx0, 2);
+ get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z0[j], tx0, 3);
+ get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z1[j], tx1, 0);
+ get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z1[j], tx1, 1);
+ get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z1[j], tx1, 2);
+ get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z1[j], tx1, 3);
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j],
+ tx0[c][0], tx0[c][1],
+ tx0[c][2], tx0[c][3],
+ tx1[c][0], tx1[c][1],
+ tx1[c][2], tx1[c][3]);
+ }
+
+ if (level0 != level1) {
+ /* get texels from second mipmap level and blend */
+ float rgba2[4][4];
+ x0[j] /= 2;
+ y0[j] /= 2;
+ z0[j] /= 2;
+ x1[j] /= 2;
+ y1[j] /= 2;
+ z1[j] /= 2;
+ get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z0[j], tx0, 0);
+ get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z0[j], tx0, 1);
+ get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z0[j], tx0, 2);
+ get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z0[j], tx0, 3);
+ get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z1[j], tx1, 0);
+ get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z1[j], tx1, 1);
+ get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z1[j], tx1, 2);
+ get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z1[j], tx1, 3);
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba2[c][j] = lerp_3d(xw[j], yw[j], zw[j],
+ tx0[c][0], tx0[c][1],
+ tx0[c][2], tx0[c][3],
+ tx1[c][0], tx1[c][1],
+ tx1[c][2], tx1[c][3]);
+ }
+
+ /* blend mipmap levels */
+ for (c = 0; c < NUM_CHANNELS; c++) {
+ rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+static void
+lp_get_samples_cube(struct tgsi_sampler *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ unsigned faces[QUAD_SIZE], j;
+ float ssss[4], tttt[4];
+ for (j = 0; j < QUAD_SIZE; j++) {
+ faces[j] = choose_cube_face(s[j], t[j], p[j], ssss + j, tttt + j);
+ }
+ lp_get_samples_2d_common(sampler, ssss, tttt, NULL,
+ lodbias, rgba, faces);
+}
+
+
+static void
+lp_get_samples_rect(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ const struct pipe_texture *texture = samp->texture;
+ const struct pipe_sampler_state *sampler = samp->sampler;
+ const uint face = 0;
+ unsigned level0, level1, j, imgFilter;
+ int width, height;
+ float levelBlend;
+
+ choose_mipmap_levels(tgsi_sampler, s, t, p,
+ lodbias,
+ &level0, &level1, &levelBlend, &imgFilter);
+
+ /* texture RECTS cannot be mipmapped */
+ assert(level0 == level1);
+
+ width = texture->width[level0];
+ height = texture->height[level0];
+
+ assert(width > 0);
+
+ switch (imgFilter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ {
+ int x[4], y[4];
+ nearest_texcoord_unnorm_4(sampler->wrap_s, s, width, x);
+ nearest_texcoord_unnorm_4(sampler->wrap_t, t, height, y);
+ for (j = 0; j < QUAD_SIZE; j++) {
+ get_texel(tgsi_sampler, face, level0, x[j], y[j], 0, rgba, j);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ shadow_compare(sampler, rgba, p, j);
+ }
+ }
+ }
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ case PIPE_TEX_FILTER_ANISO:
+ {
+ int x0[4], y0[4], x1[4], y1[4];
+ float xw[4], yw[4]; /* weights */
+ linear_texcoord_unnorm_4(sampler->wrap_s, s, width, x0, x1, xw);
+ linear_texcoord_unnorm_4(sampler->wrap_t, t, height, y0, y1, yw);
+ for (j = 0; j < QUAD_SIZE; j++) {
+ float tx[4][4]; /* texels */
+ int c;
+ get_texel(tgsi_sampler, face, level0, x0[j], y0[j], 0, tx, 0);
+ get_texel(tgsi_sampler, face, level0, x1[j], y0[j], 0, tx, 1);
+ get_texel(tgsi_sampler, face, level0, x0[j], y1[j], 0, tx, 2);
+ get_texel(tgsi_sampler, face, level0, x1[j], y1[j], 0, tx, 3);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ shadow_compare4(sampler, tx, p);
+ }
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp_2d(xw[j], yw[j],
+ tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
+ }
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Error condition handler
+ */
+static INLINE void
+lp_get_samples_null(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ int i,j;
+
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < 4; j++)
+ rgba[i][j] = 1.0;
+}
+
+/**
+ * Called via tgsi_sampler::get_samples() when using a sampler for the
+ * first time. Determine the actual sampler function, link it in and
+ * call it.
+ */
+void
+lp_get_samples(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler);
+ const struct pipe_texture *texture = samp->texture;
+ const struct pipe_sampler_state *sampler = samp->sampler;
+
+ /* Default to the 'undefined' case:
+ */
+ tgsi_sampler->get_samples = lp_get_samples_null;
+
+ if (!texture) {
+ assert(0); /* is this legal?? */
+ goto out;
+ }
+
+ if (!sampler->normalized_coords) {
+ assert (texture->target == PIPE_TEXTURE_2D);
+ tgsi_sampler->get_samples = lp_get_samples_rect;
+ goto out;
+ }
+
+ switch (texture->target) {
+ case PIPE_TEXTURE_1D:
+ tgsi_sampler->get_samples = lp_get_samples_1d;
+ break;
+ case PIPE_TEXTURE_2D:
+ tgsi_sampler->get_samples = lp_get_samples_2d;
+ break;
+ case PIPE_TEXTURE_3D:
+ tgsi_sampler->get_samples = lp_get_samples_3d;
+ break;
+ case PIPE_TEXTURE_CUBE:
+ tgsi_sampler->get_samples = lp_get_samples_cube;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* Do this elsewhere:
+ */
+ samp->xpot = util_unsigned_logbase2( samp->texture->width[0] );
+ samp->ypot = util_unsigned_logbase2( samp->texture->height[0] );
+
+ /* Try to hook in a faster sampler. Ultimately we'll have to
+ * code-generate these. Luckily most of this looks like it is
+ * orthogonal state within the sampler.
+ */
+ if (texture->target == PIPE_TEXTURE_2D &&
+ sampler->min_img_filter == sampler->mag_img_filter &&
+ sampler->wrap_s == sampler->wrap_t &&
+ sampler->compare_mode == FALSE &&
+ sampler->normalized_coords)
+ {
+ if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
+ samp->level = CLAMP((int) sampler->min_lod,
+ 0, (int) texture->last_level);
+
+ if (sampler->wrap_s == PIPE_TEX_WRAP_REPEAT) {
+ switch (sampler->min_img_filter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ tgsi_sampler->get_samples = lp_get_samples_2d_nearest_repeat_POT;
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ tgsi_sampler->get_samples = lp_get_samples_2d_linear_repeat_POT;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (sampler->wrap_s == PIPE_TEX_WRAP_CLAMP) {
+ switch (sampler->min_img_filter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ tgsi_sampler->get_samples = lp_get_samples_2d_nearest_clamp_POT;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
+ if (sampler->wrap_s == PIPE_TEX_WRAP_REPEAT) {
+ switch (sampler->min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ tgsi_sampler->get_samples = lp_get_samples_2d_linear_mip_linear_repeat_POT;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ else if (0) {
+ _debug_printf("target %d/%d min_mip %d/%d min_img %d/%d wrap %d/%d compare %d/%d norm %d/%d\n",
+ texture->target, PIPE_TEXTURE_2D,
+ sampler->min_mip_filter, PIPE_TEX_MIPFILTER_NONE,
+ sampler->min_img_filter, sampler->mag_img_filter,
+ sampler->wrap_s, sampler->wrap_t,
+ sampler->compare_mode, FALSE,
+ sampler->normalized_coords, TRUE);
+ }
+
+out:
+ tgsi_sampler->get_samples( tgsi_sampler, s, t, p, lodbias, rgba );
+}
+
+
+void PIPE_CDECL
+lp_fetch_texel_soa( struct tgsi_sampler **samplers,
+ uint32_t unit,
+ float *store )
+{
+ struct tgsi_sampler *sampler = samplers[unit];
+
+#if 0
+ uint j;
+
+ debug_printf("%s sampler: %p (%p) store: %p\n",
+ __FUNCTION__,
+ sampler, *sampler,
+ store );
+
+ debug_printf("lodbias %f\n", store[12]);
+
+ for (j = 0; j < 4; j++)
+ debug_printf("sample %d texcoord %f %f\n",
+ j,
+ store[0+j],
+ store[4+j]);
+#endif
+
+ {
+ float rgba[NUM_CHANNELS][QUAD_SIZE];
+ sampler->get_samples(sampler,
+ &store[0],
+ &store[4],
+ &store[8],
+ 0.0f, /*store[12], lodbias */
+ rgba);
+ memcpy(store, rgba, sizeof rgba);
+ }
+
+#if 0
+ for (j = 0; j < 4; j++)
+ debug_printf("sample %d result %f %f %f %f\n",
+ j,
+ store[0+j],
+ store[4+j],
+ store[8+j],
+ store[12+j]);
+#endif
+}
+
+
+#include "lp_bld_type.h"
+#include "lp_bld_intr.h"
+#include "lp_bld_tgsi.h"
+
+
+struct lp_c_sampler_soa
+{
+ struct lp_build_sampler_soa base;
+
+ LLVMValueRef context_ptr;
+
+ LLVMValueRef samplers_ptr;
+
+ /** Coords/texels store */
+ LLVMValueRef store_ptr;
+};
+
+
+static void
+lp_c_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
+{
+ FREE(sampler);
+}
+
+
+static void
+lp_c_sampler_soa_emit_fetch_texel(struct lp_build_sampler_soa *_sampler,
+ LLVMBuilderRef builder,
+ union lp_type type,
+ unsigned unit,
+ unsigned num_coords,
+ const LLVMValueRef *coords,
+ LLVMValueRef lodbias,
+ LLVMValueRef *texel)
+{
+ struct lp_c_sampler_soa *sampler = (struct lp_c_sampler_soa *)_sampler;
+ LLVMTypeRef vec_type = LLVMTypeOf(coords[0]);
+ LLVMValueRef args[3];
+ unsigned i;
+
+ if(!sampler->samplers_ptr)
+ sampler->samplers_ptr = lp_jit_context_samplers(builder, sampler->context_ptr);
+
+ if(!sampler->store_ptr)
+ sampler->store_ptr = LLVMBuildArrayAlloca(builder,
+ vec_type,
+ LLVMConstInt(LLVMInt32Type(), 4, 0),
+ "texel_store");
+
+ for (i = 0; i < num_coords; i++) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ LLVMValueRef coord_ptr = LLVMBuildGEP(builder, sampler->store_ptr, &index, 1, "");
+ LLVMBuildStore(builder, coords[i], coord_ptr);
+ }
+
+ args[0] = sampler->samplers_ptr;
+ args[1] = LLVMConstInt(LLVMInt32Type(), unit, 0);
+ args[2] = sampler->store_ptr;
+
+ lp_build_intrinsic(builder, "fetch_texel", LLVMVoidType(), args, 3);
+
+ for (i = 0; i < NUM_CHANNELS; ++i) {
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ LLVMValueRef texel_ptr = LLVMBuildGEP(builder, sampler->store_ptr, &index, 1, "");
+ texel[i] = LLVMBuildLoad(builder, texel_ptr, "");
+ }
+}
+
+
+struct lp_build_sampler_soa *
+lp_c_sampler_soa_create(LLVMValueRef context_ptr)
+{
+ struct lp_c_sampler_soa *sampler;
+
+ sampler = CALLOC_STRUCT(lp_c_sampler_soa);
+ if(!sampler)
+ return NULL;
+
+ sampler->base.destroy = lp_c_sampler_soa_destroy;
+ sampler->base.emit_fetch_texel = lp_c_sampler_soa_emit_fetch_texel;
+ sampler->context_ptr = context_ptr;
+
+ return &sampler->base;
+}
+
diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c
new file mode 100644
index 0000000000..7d31705d01
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c
@@ -0,0 +1,196 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Texture sampling code generation
+ *
+ * This file is nothing more than ugly glue between three largely independent
+ * entities:
+ * - TGSI -> LLVM translation (i.e., lp_build_tgsi_soa)
+ * - texture sampling code generation (i.e., lp_build_sample_soa)
+ * - LLVM pipe driver
+ *
+ * All interesting code is in the functions mentioned above. There is really
+ * nothing to see here.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "lp_bld_debug.h"
+#include "lp_bld_type.h"
+#include "lp_bld_intr.h"
+#include "lp_bld_sample.h"
+#include "lp_bld_tgsi.h"
+#include "lp_state.h"
+#include "lp_tex_sample.h"
+
+
+/**
+ * This provides the bridge between the sampler state store in lp_jit_context
+ * and lp_jit_texture and the sampler code generator. It provides the
+ * texture layout information required by the texture sampler code generator
+ * in terms of the state stored in lp_jit_context and lp_jit_texture in runtime.
+ */
+struct llvmpipe_sampler_dynamic_state
+{
+ struct lp_sampler_dynamic_state base;
+
+ const struct lp_sampler_static_state *static_state;
+
+ LLVMValueRef context_ptr;
+};
+
+
+/**
+ * This is the bridge between our sampler and the TGSI translator.
+ */
+struct lp_llvm_sampler_soa
+{
+ struct lp_build_sampler_soa base;
+
+ struct llvmpipe_sampler_dynamic_state dynamic_state;
+};
+
+
+/**
+ * Fetch the specified member of the lp_jit_texture structure.
+ *
+ * @sa http://llvm.org/docs/GetElementPtr.html
+ */
+static LLVMValueRef
+lp_llvm_texture_member(struct lp_sampler_dynamic_state *base,
+ LLVMBuilderRef builder,
+ unsigned unit,
+ unsigned member_index,
+ const char *member_name)
+{
+ struct llvmpipe_sampler_dynamic_state *state = (struct llvmpipe_sampler_dynamic_state *)base;
+ LLVMValueRef indices[4];
+ LLVMValueRef ptr;
+ LLVMValueRef res;
+
+ assert(unit < PIPE_MAX_SAMPLERS);
+
+ /* context[0] */
+ indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
+ /* context[0].textures */
+ indices[1] = LLVMConstInt(LLVMInt32Type(), LP_JIT_CONTEXT_TEXTURES_INDEX, 0);
+ /* context[0].textures[unit] */
+ indices[2] = LLVMConstInt(LLVMInt32Type(), unit, 0);
+ /* context[0].textures[unit].member */
+ indices[3] = LLVMConstInt(LLVMInt32Type(), member_index, 0);
+
+ ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
+
+ res = LLVMBuildLoad(builder, ptr, "");
+
+ lp_build_name(res, "context.texture%u.%s", unit, member_name);
+
+ return res;
+}
+
+
+/**
+ * Helper macro to instantiate the functions that generate the code to fetch
+ * the members of lp_jit_texture to fulfill the sampler code generator requests.
+ *
+ * This complexity is the price we have to pay to keep the texture sampler code
+ * generator a reusable module without dependencies to llvmpipe internals.
+ */
+#define LP_LLVM_TEXTURE_MEMBER(_name, _index) \
+ static LLVMValueRef \
+ lp_llvm_texture_##_name( struct lp_sampler_dynamic_state *base, \
+ LLVMBuilderRef builder, \
+ unsigned unit) \
+ { \
+ return lp_llvm_texture_member(base, builder, unit, _index, #_name ); \
+ }
+
+
+LP_LLVM_TEXTURE_MEMBER(width, LP_JIT_TEXTURE_WIDTH)
+LP_LLVM_TEXTURE_MEMBER(height, LP_JIT_TEXTURE_HEIGHT)
+LP_LLVM_TEXTURE_MEMBER(stride, LP_JIT_TEXTURE_STRIDE)
+LP_LLVM_TEXTURE_MEMBER(data_ptr, LP_JIT_TEXTURE_DATA)
+
+
+static void
+lp_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
+{
+ FREE(sampler);
+}
+
+
+static void
+lp_llvm_sampler_soa_emit_fetch_texel(struct lp_build_sampler_soa *base,
+ LLVMBuilderRef builder,
+ union lp_type type,
+ unsigned unit,
+ unsigned num_coords,
+ const LLVMValueRef *coords,
+ LLVMValueRef lodbias,
+ LLVMValueRef *texel)
+{
+ struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
+
+ assert(unit < PIPE_MAX_SAMPLERS);
+
+ lp_build_sample_soa(builder,
+ &sampler->dynamic_state.static_state[unit],
+ &sampler->dynamic_state.base,
+ type,
+ unit,
+ num_coords,
+ coords,
+ lodbias,
+ texel);
+}
+
+
+struct lp_build_sampler_soa *
+lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
+ LLVMValueRef context_ptr)
+{
+ struct lp_llvm_sampler_soa *sampler;
+
+ sampler = CALLOC_STRUCT(lp_llvm_sampler_soa);
+ if(!sampler)
+ return NULL;
+
+ sampler->base.destroy = lp_llvm_sampler_soa_destroy;
+ sampler->base.emit_fetch_texel = lp_llvm_sampler_soa_emit_fetch_texel;
+ sampler->dynamic_state.base.width = lp_llvm_texture_width;
+ sampler->dynamic_state.base.height = lp_llvm_texture_height;
+ sampler->dynamic_state.base.stride = lp_llvm_texture_stride;
+ sampler->dynamic_state.base.data_ptr = lp_llvm_texture_data_ptr;
+ sampler->dynamic_state.static_state = static_state;
+ sampler->dynamic_state.context_ptr = context_ptr;
+
+ return &sampler->base;
+}
+
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
new file mode 100644
index 0000000000..724d437833
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -0,0 +1,429 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Michel Dänzer <michel@tungstengraphics.com>
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "lp_context.h"
+#include "lp_state.h"
+#include "lp_texture.h"
+#include "lp_tex_cache.h"
+#include "lp_screen.h"
+#include "lp_winsys.h"
+
+
+/* Simple, maximally packed layout.
+ */
+
+
+/* Conventional allocation path for non-display textures:
+ */
+static boolean
+llvmpipe_texture_layout(struct llvmpipe_screen *screen,
+ struct llvmpipe_texture * lpt)
+{
+ struct pipe_texture *pt = &lpt->base;
+ unsigned level;
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+ unsigned depth = pt->depth[0];
+
+ unsigned buffer_size = 0;
+
+ pf_get_block(lpt->base.format, &lpt->base.block);
+
+ for (level = 0; level <= pt->last_level; level++) {
+ pt->width[level] = width;
+ pt->height[level] = height;
+ pt->depth[level] = depth;
+ pt->nblocksx[level] = pf_get_nblocksx(&pt->block, width);
+ pt->nblocksy[level] = pf_get_nblocksy(&pt->block, height);
+ lpt->stride[level] = align(pt->nblocksx[level]*pt->block.size, 16);
+
+ lpt->level_offset[level] = buffer_size;
+
+ buffer_size += (pt->nblocksy[level] *
+ ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
+ lpt->stride[level]);
+
+ width = minify(width);
+ height = minify(height);
+ depth = minify(depth);
+ }
+
+ lpt->data = align_malloc(buffer_size, 16);
+
+ return lpt->data != NULL;
+}
+
+static boolean
+llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
+ struct llvmpipe_texture * lpt)
+{
+ struct llvmpipe_winsys *winsys = screen->winsys;
+
+ pf_get_block(lpt->base.format, &lpt->base.block);
+ lpt->base.nblocksx[0] = pf_get_nblocksx(&lpt->base.block, lpt->base.width[0]);
+ lpt->base.nblocksy[0] = pf_get_nblocksy(&lpt->base.block, lpt->base.height[0]);
+
+ lpt->dt = winsys->displaytarget_create(winsys,
+ lpt->base.format,
+ lpt->base.width[0],
+ lpt->base.height[0],
+ 16,
+ &lpt->stride[0] );
+
+ return lpt->dt != NULL;
+}
+
+
+
+
+
+static struct pipe_texture *
+llvmpipe_texture_create(struct pipe_screen *_screen,
+ const struct pipe_texture *templat)
+{
+ struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
+ struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture);
+ if (!lpt)
+ return NULL;
+
+ lpt->base = *templat;
+ pipe_reference_init(&lpt->base.reference, 1);
+ lpt->base.screen = &screen->base;
+
+ /* XXX: The xlib state tracker is brain-dead and will request
+ * PIPE_FORMAT_Z16_UNORM no matter how much we tell it we don't support it.
+ */
+ if(lpt->base.format == PIPE_FORMAT_Z16_UNORM)
+ lpt->base.format = PIPE_FORMAT_Z32_UNORM;
+
+ if (lpt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_PRIMARY)) {
+ if (!llvmpipe_displaytarget_layout(screen, lpt))
+ goto fail;
+ }
+ else {
+ if (!llvmpipe_texture_layout(screen, lpt))
+ goto fail;
+ }
+
+ return &lpt->base;
+
+ fail:
+ FREE(lpt);
+ return NULL;
+}
+
+
+static struct pipe_texture *
+llvmpipe_texture_blanket(struct pipe_screen * screen,
+ const struct pipe_texture *base,
+ const unsigned *stride,
+ struct pipe_buffer *buffer)
+{
+ /* FIXME */
+#if 0
+ struct llvmpipe_texture *lpt;
+ assert(screen);
+
+ /* Only supports one type */
+ if (base->target != PIPE_TEXTURE_2D ||
+ base->last_level != 0 ||
+ base->depth[0] != 1) {
+ return NULL;
+ }
+
+ lpt = CALLOC_STRUCT(llvmpipe_texture);
+ if (!lpt)
+ return NULL;
+
+ lpt->base = *base;
+ pipe_reference_init(&lpt->base.reference, 1);
+ lpt->base.screen = screen;
+ lpt->base.nblocksx[0] = pf_get_nblocksx(&lpt->base.block, lpt->base.width[0]);
+ lpt->base.nblocksy[0] = pf_get_nblocksy(&lpt->base.block, lpt->base.height[0]);
+ lpt->stride[0] = stride[0];
+
+ pipe_buffer_reference(&lpt->buffer, buffer);
+
+ return &lpt->base;
+#else
+ return NULL;
+#endif
+}
+
+
+static void
+llvmpipe_texture_destroy(struct pipe_texture *pt)
+{
+ struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen);
+ struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
+
+ if(lpt->dt) {
+ struct llvmpipe_winsys *winsys = screen->winsys;
+ winsys->displaytarget_destroy(winsys, lpt->dt);
+ }
+ else
+ align_free(lpt->data);
+
+ FREE(lpt);
+}
+
+
+static struct pipe_surface *
+llvmpipe_get_tex_surface(struct pipe_screen *screen,
+ struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned usage)
+{
+ struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
+ struct pipe_surface *ps;
+
+ assert(level <= pt->last_level);
+
+ ps = CALLOC_STRUCT(pipe_surface);
+ if (ps) {
+ pipe_reference_init(&ps->reference, 1);
+ pipe_texture_reference(&ps->texture, pt);
+ ps->format = pt->format;
+ ps->width = pt->width[level];
+ ps->height = pt->height[level];
+ ps->offset = lpt->level_offset[level];
+ ps->usage = usage;
+
+ /* Because we are llvmpipe, anything that the state tracker
+ * thought was going to be done with the GPU will actually get
+ * done with the CPU. Let's adjust the flags to take that into
+ * account.
+ */
+ if (ps->usage & PIPE_BUFFER_USAGE_GPU_WRITE) {
+ /* GPU_WRITE means "render" and that can involve reads (blending) */
+ ps->usage |= PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_CPU_READ;
+ }
+
+ if (ps->usage & PIPE_BUFFER_USAGE_GPU_READ)
+ ps->usage |= PIPE_BUFFER_USAGE_CPU_READ;
+
+ if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE |
+ PIPE_BUFFER_USAGE_GPU_WRITE)) {
+ /* Mark the surface as dirty. The tile cache will look for this. */
+ lpt->timestamp++;
+ llvmpipe_screen(screen)->timestamp++;
+ }
+
+ ps->face = face;
+ ps->level = level;
+ ps->zslice = zslice;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ps->offset += face * pt->nblocksy[level] * lpt->stride[level];
+ }
+ else if (pt->target == PIPE_TEXTURE_3D) {
+ ps->offset += zslice * pt->nblocksy[level] * lpt->stride[level];
+ }
+ else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+ }
+ return ps;
+}
+
+
+static void
+llvmpipe_tex_surface_destroy(struct pipe_surface *surf)
+{
+ /* Effectively do the texture_update work here - if texture images
+ * needed post-processing to put them into hardware layout, this is
+ * where it would happen. For llvmpipe, nothing to do.
+ */
+ assert(surf->texture);
+ pipe_texture_reference(&surf->texture, NULL);
+ FREE(surf);
+}
+
+
+static struct pipe_transfer *
+llvmpipe_get_tex_transfer(struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct llvmpipe_texture *lptex = llvmpipe_texture(texture);
+ struct llvmpipe_transfer *lpt;
+
+ assert(texture);
+ assert(level <= texture->last_level);
+
+ lpt = CALLOC_STRUCT(llvmpipe_transfer);
+ if (lpt) {
+ struct pipe_transfer *pt = &lpt->base;
+ pipe_texture_reference(&pt->texture, texture);
+ pt->format = texture->format;
+ pt->block = texture->block;
+ pt->x = x;
+ pt->y = y;
+ pt->width = w;
+ pt->height = h;
+ pt->nblocksx = texture->nblocksx[level];
+ pt->nblocksy = texture->nblocksy[level];
+ pt->stride = lptex->stride[level];
+ pt->usage = usage;
+ pt->face = face;
+ pt->level = level;
+ pt->zslice = zslice;
+
+ lpt->offset = lptex->level_offset[level];
+
+ if (texture->target == PIPE_TEXTURE_CUBE) {
+ lpt->offset += face * pt->nblocksy * pt->stride;
+ }
+ else if (texture->target == PIPE_TEXTURE_3D) {
+ lpt->offset += zslice * pt->nblocksy * pt->stride;
+ }
+ else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+ return pt;
+ }
+ return NULL;
+}
+
+
+static void
+llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer)
+{
+ /* Effectively do the texture_update work here - if texture images
+ * needed post-processing to put them into hardware layout, this is
+ * where it would happen. For llvmpipe, nothing to do.
+ */
+ assert (transfer->texture);
+ pipe_texture_reference(&transfer->texture, NULL);
+ FREE(transfer);
+}
+
+
+static void *
+llvmpipe_transfer_map( struct pipe_screen *_screen,
+ struct pipe_transfer *transfer )
+{
+ struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
+ ubyte *map, *xfer_map;
+ struct llvmpipe_texture *lpt;
+
+ assert(transfer->texture);
+ lpt = llvmpipe_texture(transfer->texture);
+
+ if(lpt->dt) {
+ struct llvmpipe_winsys *winsys = screen->winsys;
+ unsigned flags = 0;
+
+ if (transfer->usage != PIPE_TRANSFER_READ) {
+ flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
+ }
+
+ if (transfer->usage != PIPE_TRANSFER_WRITE) {
+ flags |= PIPE_BUFFER_USAGE_CPU_READ;
+ }
+
+ map = winsys->displaytarget_map(winsys, lpt->dt, flags);
+ if (map == NULL)
+ return NULL;
+ }
+ else
+ map = lpt->data;
+
+ /* May want to different things here depending on read/write nature
+ * of the map:
+ */
+ if (transfer->texture && transfer->usage != PIPE_TRANSFER_READ)
+ {
+ /* Do something to notify sharing contexts of a texture change.
+ * In llvmpipe, that would mean flushing the texture cache.
+ */
+ screen->timestamp++;
+ }
+
+ xfer_map = map + llvmpipe_transfer(transfer)->offset +
+ transfer->y / transfer->block.height * transfer->stride +
+ transfer->x / transfer->block.width * transfer->block.size;
+ /*printf("map = %p xfer map = %p\n", map, xfer_map);*/
+ return xfer_map;
+}
+
+
+static void
+llvmpipe_transfer_unmap(struct pipe_screen *_screen,
+ struct pipe_transfer *transfer)
+{
+ struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
+ struct llvmpipe_texture *lpt;
+
+ assert(transfer->texture);
+ lpt = llvmpipe_texture(transfer->texture);
+
+ if(lpt->dt) {
+ struct llvmpipe_winsys *winsys = screen->winsys;
+ winsys->displaytarget_unmap(winsys, lpt->dt);
+ }
+}
+
+
+void
+llvmpipe_init_texture_funcs(struct llvmpipe_context *lp)
+{
+}
+
+
+void
+llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen)
+{
+ screen->texture_create = llvmpipe_texture_create;
+ screen->texture_blanket = llvmpipe_texture_blanket;
+ screen->texture_destroy = llvmpipe_texture_destroy;
+
+ screen->get_tex_surface = llvmpipe_get_tex_surface;
+ screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;
+
+ screen->get_tex_transfer = llvmpipe_get_tex_transfer;
+ screen->tex_transfer_destroy = llvmpipe_tex_transfer_destroy;
+ screen->transfer_map = llvmpipe_transfer_map;
+ screen->transfer_unmap = llvmpipe_transfer_unmap;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h
new file mode 100644
index 0000000000..00a20763e4
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_texture.h
@@ -0,0 +1,90 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_TEXTURE_H
+#define LP_TEXTURE_H
+
+
+#include "pipe/p_state.h"
+
+
+struct pipe_context;
+struct pipe_screen;
+struct llvmpipe_context;
+struct llvmpipe_displaytarget;
+
+struct llvmpipe_texture
+{
+ struct pipe_texture base;
+
+ unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned stride[PIPE_MAX_TEXTURE_LEVELS];
+
+ /**
+ * Display target, for textures with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET
+ * usage.
+ */
+ struct llvmpipe_displaytarget *dt;
+
+ /**
+ * Malloc'ed data for regular textures, or a mapping to dt above.
+ */
+ void *data;
+
+ unsigned timestamp;
+};
+
+struct llvmpipe_transfer
+{
+ struct pipe_transfer base;
+
+ unsigned long offset;
+};
+
+
+/** cast wrappers */
+static INLINE struct llvmpipe_texture *
+llvmpipe_texture(struct pipe_texture *pt)
+{
+ return (struct llvmpipe_texture *) pt;
+}
+
+static INLINE struct llvmpipe_transfer *
+llvmpipe_transfer(struct pipe_transfer *pt)
+{
+ return (struct llvmpipe_transfer *) pt;
+}
+
+
+extern void
+llvmpipe_init_texture_funcs( struct llvmpipe_context *llvmpipe );
+
+extern void
+llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen);
+
+
+#endif /* LP_TEXTURE */
diff --git a/src/gallium/drivers/llvmpipe/lp_tile_cache.c b/src/gallium/drivers/llvmpipe/lp_tile_cache.c
new file mode 100644
index 0000000000..143afec3d3
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_tile_cache.c
@@ -0,0 +1,299 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Texture tile caching.
+ *
+ * Author:
+ * Brian Paul
+ */
+
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_tile.h"
+#include "util/u_rect.h"
+#include "lp_context.h"
+#include "lp_surface.h"
+#include "lp_texture.h"
+#include "lp_tile_soa.h"
+#include "lp_tile_cache.h"
+
+
+struct llvmpipe_tile_cache *
+lp_create_tile_cache( struct pipe_screen *screen )
+{
+ struct llvmpipe_tile_cache *tc;
+
+ tc = CALLOC_STRUCT( llvmpipe_tile_cache );
+ if(!tc)
+ return NULL;
+
+ tc->screen = screen;
+
+ return tc;
+}
+
+
+void
+lp_destroy_tile_cache(struct llvmpipe_tile_cache *tc)
+{
+ struct pipe_screen *screen;
+ unsigned x, y;
+
+ for (y = 0; y < MAX_HEIGHT; y += TILE_SIZE) {
+ for (x = 0; x < MAX_WIDTH; x += TILE_SIZE) {
+ struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
+
+ if(tile->color)
+ align_free(tile->color);
+ }
+ }
+
+ if (tc->transfer) {
+ screen = tc->transfer->texture->screen;
+ screen->tex_transfer_destroy(tc->transfer);
+ }
+
+ FREE( tc );
+}
+
+
+/**
+ * Specify the surface to cache.
+ */
+void
+lp_tile_cache_set_surface(struct llvmpipe_tile_cache *tc,
+ struct pipe_surface *ps)
+{
+ if (tc->transfer) {
+ struct pipe_screen *screen = tc->transfer->texture->screen;
+
+ if (ps == tc->surface)
+ return;
+
+ if (tc->transfer_map) {
+ screen->transfer_unmap(screen, tc->transfer);
+ tc->transfer_map = NULL;
+ }
+
+ screen->tex_transfer_destroy(tc->transfer);
+ tc->transfer = NULL;
+ }
+
+ tc->surface = ps;
+
+ if (ps) {
+ struct pipe_screen *screen = ps->texture->screen;
+ unsigned x, y;
+
+ tc->transfer = screen->get_tex_transfer(screen, ps->texture, ps->face,
+ ps->level, ps->zslice,
+ PIPE_TRANSFER_READ_WRITE,
+ 0, 0, ps->width, ps->height);
+
+ for (y = 0; y < ps->height; y += TILE_SIZE) {
+ for (x = 0; x < ps->width; x += TILE_SIZE) {
+ struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
+
+ tile->status = LP_TILE_STATUS_UNDEFINED;
+
+ if(!tile->color)
+ tile->color = align_malloc( TILE_SIZE*TILE_SIZE*NUM_CHANNELS, 16 );
+ }
+ }
+ }
+}
+
+
+/**
+ * Return the transfer being cached.
+ */
+struct pipe_surface *
+lp_tile_cache_get_surface(struct llvmpipe_tile_cache *tc)
+{
+ return tc->surface;
+}
+
+
+void
+lp_tile_cache_map_transfers(struct llvmpipe_tile_cache *tc)
+{
+ if (tc->transfer && !tc->transfer_map)
+ tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer);
+}
+
+
+void
+lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache *tc)
+{
+ if (tc->transfer_map) {
+ tc->screen->transfer_unmap(tc->screen, tc->transfer);
+ tc->transfer_map = NULL;
+ }
+}
+
+
+/**
+ * Set a tile to a solid color.
+ */
+static void
+clear_tile(struct llvmpipe_cached_tile *tile,
+ uint8_t clear_color[4])
+{
+ if (clear_color[0] == clear_color[1] &&
+ clear_color[1] == clear_color[2] &&
+ clear_color[2] == clear_color[3]) {
+ memset(tile->color, clear_color[0], TILE_SIZE * TILE_SIZE * 4);
+ }
+ else {
+ uint x, y, chan;
+ for (y = 0; y < TILE_SIZE; y++)
+ for (x = 0; x < TILE_SIZE; x++)
+ for (chan = 0; chan < 4; ++chan)
+ TILE_PIXEL(tile->color, x, y, chan) = clear_color[chan];
+ }
+}
+
+
+/**
+ * Flush the tile cache: write all dirty tiles back to the transfer.
+ * any tiles "flagged" as cleared will be "really" cleared.
+ */
+void
+lp_flush_tile_cache(struct llvmpipe_tile_cache *tc)
+{
+ struct pipe_transfer *pt = tc->transfer;
+ unsigned x, y;
+
+ if(!pt)
+ return;
+
+ /* push the tile to all positions marked as clear */
+ for (y = 0; y < pt->height; y += TILE_SIZE) {
+ for (x = 0; x < pt->width; x += TILE_SIZE) {
+ struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
+
+ switch(tile->status) {
+ case LP_TILE_STATUS_UNDEFINED:
+ break;
+
+ case LP_TILE_STATUS_CLEAR: {
+ /**
+ * Actually clear the tiles which were flagged as being in a clear state.
+ */
+
+ struct pipe_screen *screen = pt->texture->screen;
+ unsigned tw = TILE_SIZE;
+ unsigned th = TILE_SIZE;
+ void *dst;
+
+ if (pipe_clip_tile(x, y, &tw, &th, pt))
+ continue;
+
+ dst = screen->transfer_map(screen, pt);
+ assert(dst);
+ if(!dst)
+ continue;
+
+ util_fill_rect(dst, &pt->block, pt->stride,
+ x, y, tw, th,
+ tc->clear_val);
+
+ screen->transfer_unmap(screen, pt);
+ break;
+ }
+
+ case LP_TILE_STATUS_DEFINED:
+ lp_put_tile_rgba_soa(pt, x, y, tile->color);
+ break;
+ }
+ }
+ }
+}
+
+
+/**
+ * Get a tile from the cache.
+ * \param x, y position of tile, in pixels
+ */
+void *
+lp_get_cached_tile(struct llvmpipe_tile_cache *tc,
+ unsigned x, unsigned y )
+{
+ struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
+ struct pipe_transfer *pt = tc->transfer;
+
+ switch(tile->status) {
+ case LP_TILE_STATUS_CLEAR:
+ /* don't get tile from framebuffer, just clear it */
+ clear_tile(tile, tc->clear_color);
+ tile->status = LP_TILE_STATUS_DEFINED;
+ break;
+
+ case LP_TILE_STATUS_UNDEFINED:
+ /* get new tile data from transfer */
+ lp_get_tile_rgba_soa(pt, x, y, tile->color);
+ tile->status = LP_TILE_STATUS_DEFINED;
+ break;
+
+ case LP_TILE_STATUS_DEFINED:
+ /* nothing to do */
+ break;
+ }
+
+ return tile->color;
+}
+
+
+/**
+ * When a whole surface is being cleared to a value we can avoid
+ * fetching tiles above.
+ * Save the color and set a 'clearflag' for each tile of the screen.
+ */
+void
+lp_tile_cache_clear(struct llvmpipe_tile_cache *tc, const float *rgba,
+ uint clearValue)
+{
+ struct pipe_transfer *pt = tc->transfer;
+ const unsigned w = pt->width;
+ const unsigned h = pt->height;
+ unsigned x, y, chan;
+
+ for(chan = 0; chan < 4; ++chan)
+ tc->clear_color[chan] = float_to_ubyte(rgba[chan]);
+
+ tc->clear_val = clearValue;
+
+ /* push the tile to all positions marked as clear */
+ for (y = 0; y < h; y += TILE_SIZE) {
+ for (x = 0; x < w; x += TILE_SIZE) {
+ struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
+ tile->status = LP_TILE_STATUS_CLEAR;
+ }
+ }
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_tile_cache.h b/src/gallium/drivers/llvmpipe/lp_tile_cache.h
new file mode 100644
index 0000000000..6d8ba5ece7
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_tile_cache.h
@@ -0,0 +1,106 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_TILE_CACHE_H
+#define LP_TILE_CACHE_H
+
+
+#include "pipe/p_compiler.h"
+#include "lp_tile_soa.h"
+
+
+enum llvmpipe_tile_status
+{
+ LP_TILE_STATUS_UNDEFINED = 0,
+ LP_TILE_STATUS_CLEAR = 1,
+ LP_TILE_STATUS_DEFINED = 2
+};
+
+
+struct llvmpipe_cached_tile
+{
+ enum llvmpipe_tile_status status;
+
+ /** color in SOA format */
+ uint8_t *color;
+};
+
+
+/** XXX move these */
+#define MAX_WIDTH 2048
+#define MAX_HEIGHT 2048
+
+
+struct llvmpipe_tile_cache
+{
+ struct pipe_screen *screen;
+ struct pipe_surface *surface; /**< the surface we're caching */
+ struct pipe_transfer *transfer;
+ void *transfer_map;
+
+ struct llvmpipe_cached_tile entries[MAX_WIDTH/TILE_SIZE][MAX_HEIGHT/TILE_SIZE];
+
+ uint8_t clear_color[4]; /**< for color bufs */
+ uint clear_val; /**< for z+stencil, or packed color clear value */
+
+ struct llvmpipe_cached_tile *last_tile; /**< most recently retrieved tile */
+};
+
+
+extern struct llvmpipe_tile_cache *
+lp_create_tile_cache( struct pipe_screen *screen );
+
+extern void
+lp_destroy_tile_cache(struct llvmpipe_tile_cache *tc);
+
+extern void
+lp_tile_cache_set_surface(struct llvmpipe_tile_cache *tc,
+ struct pipe_surface *lps);
+
+extern struct pipe_surface *
+lp_tile_cache_get_surface(struct llvmpipe_tile_cache *tc);
+
+extern void
+lp_tile_cache_map_transfers(struct llvmpipe_tile_cache *tc);
+
+extern void
+lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache *tc);
+
+extern void
+lp_flush_tile_cache(struct llvmpipe_tile_cache *tc);
+
+extern void
+lp_tile_cache_clear(struct llvmpipe_tile_cache *tc, const float *rgba,
+ uint clearValue);
+
+extern void *
+lp_get_cached_tile(struct llvmpipe_tile_cache *tc,
+ unsigned x, unsigned y );
+
+
+#endif /* LP_TILE_CACHE_H */
+
diff --git a/src/gallium/drivers/llvmpipe/lp_tile_soa.c b/src/gallium/drivers/llvmpipe/lp_tile_soa.c
new file mode 100644
index 0000000000..4e4ccb31cc
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_tile_soa.c
@@ -0,0 +1,931 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * RGBA/float tile get/put functions.
+ * Usable both by drivers and state trackers.
+ */
+
+
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_rect.h"
+#include "util/u_tile.h"
+#include "lp_tile_cache.h"
+#include "lp_tile_soa.h"
+
+
+const unsigned char
+tile_offset[TILE_VECTOR_HEIGHT][TILE_VECTOR_WIDTH] = {
+ { 0, 1, 4, 5, 8, 9, 12, 13},
+ { 2, 3, 6, 7, 10, 11, 14, 15}
+};
+
+
+
+/*** PIPE_FORMAT_A8R8G8B8_UNORM ***/
+
+static void
+a8r8g8b8_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ const unsigned pixel = *src++;
+ TILE_PIXEL(p, j, i, 0) = (pixel >> 16) & 0xff;
+ TILE_PIXEL(p, j, i, 1) = (pixel >> 8) & 0xff;
+ TILE_PIXEL(p, j, i, 2) = (pixel >> 0) & 0xff;
+ TILE_PIXEL(p, j, i, 3) = (pixel >> 24) & 0xff;
+ }
+ }
+}
+
+
+static void
+a8r8g8b8_put_tile_rgba(unsigned *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ unsigned r, g, b, a;
+ r = TILE_PIXEL(p, j, i, 0);
+ g = TILE_PIXEL(p, j, i, 1);
+ b = TILE_PIXEL(p, j, i, 2);
+ a = TILE_PIXEL(p, j, i, 3);
+ *dst++ = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_A8R8G8B8_UNORM ***/
+
+static void
+x8r8g8b8_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ const unsigned pixel = *src++;
+ TILE_PIXEL(p, j, i, 0) = (pixel >> 16) & 0xff;
+ TILE_PIXEL(p, j, i, 1) = (pixel >> 8) & 0xff;
+ TILE_PIXEL(p, j, i, 2) = (pixel >> 0) & 0xff;
+ TILE_PIXEL(p, j, i, 3) = 0xff;
+ }
+ }
+}
+
+
+static void
+x8r8g8b8_put_tile_rgba(unsigned *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ unsigned r, g, b;
+ r = TILE_PIXEL(p, j, i, 0);
+ g = TILE_PIXEL(p, j, i, 1);
+ b = TILE_PIXEL(p, j, i, 2);
+ *dst++ = (0xff << 24) | (r << 16) | (g << 8) | b;
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_B8G8R8A8_UNORM ***/
+
+static void
+b8g8r8a8_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ const unsigned pixel = *src++;
+ TILE_PIXEL(p, j, i, 0) = (pixel >> 8) & 0xff;
+ TILE_PIXEL(p, j, i, 1) = (pixel >> 16) & 0xff;
+ TILE_PIXEL(p, j, i, 2) = (pixel >> 24) & 0xff;
+ TILE_PIXEL(p, j, i, 3) = (pixel >> 0) & 0xff;
+ }
+ }
+}
+
+
+static void
+b8g8r8a8_put_tile_rgba(unsigned *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ unsigned r, g, b, a;
+ r = TILE_PIXEL(p, j, i, 0);
+ g = TILE_PIXEL(p, j, i, 1);
+ b = TILE_PIXEL(p, j, i, 2);
+ a = TILE_PIXEL(p, j, i, 3);
+ *dst++ = (b << 24) | (g << 16) | (r << 8) | a;
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_A1R5G5B5_UNORM ***/
+
+static void
+a1r5g5b5_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ const ushort pixel = *src++;
+ TILE_PIXEL(p, j, i, 0) = ((pixel >> 10) & 0x1f) * 255 / 31;
+ TILE_PIXEL(p, j, i, 1) = ((pixel >> 5) & 0x1f) * 255 / 31;
+ TILE_PIXEL(p, j, i, 2) = ((pixel ) & 0x1f) * 255 / 31;
+ TILE_PIXEL(p, j, i, 3) = ((pixel >> 15) ) * 255;
+ }
+ }
+}
+
+
+static void
+a1r5g5b5_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ unsigned r, g, b, a;
+ r = TILE_PIXEL(p, j, i, 0);
+ g = TILE_PIXEL(p, j, i, 1);
+ b = TILE_PIXEL(p, j, i, 2);
+ a = TILE_PIXEL(p, j, i, 3);
+ r = r >> 3; /* 5 bits */
+ g = g >> 3; /* 5 bits */
+ b = b >> 3; /* 5 bits */
+ a = a >> 7; /* 1 bit */
+ *dst++ = (a << 15) | (r << 10) | (g << 5) | b;
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_A4R4G4B4_UNORM ***/
+
+static void
+a4r4g4b4_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ const ushort pixel = *src++;
+ TILE_PIXEL(p, j, i, 0) = ((pixel >> 8) & 0xf) * 255 / 15;
+ TILE_PIXEL(p, j, i, 1) = ((pixel >> 4) & 0xf) * 255 / 15;
+ TILE_PIXEL(p, j, i, 2) = ((pixel ) & 0xf) * 255 / 15;
+ TILE_PIXEL(p, j, i, 3) = ((pixel >> 12) ) * 255 / 15;
+ }
+ }
+}
+
+
+static void
+a4r4g4b4_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ unsigned r, g, b, a;
+ r = TILE_PIXEL(p, j, i, 0);
+ g = TILE_PIXEL(p, j, i, 1);
+ b = TILE_PIXEL(p, j, i, 2);
+ a = TILE_PIXEL(p, j, i, 3);
+ r >>= 4;
+ g >>= 4;
+ b >>= 4;
+ a >>= 4;
+ *dst++ = (a << 12) | (r << 16) | (g << 4) | b;
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_R5G6B5_UNORM ***/
+
+static void
+r5g6b5_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ const ushort pixel = *src++;
+ TILE_PIXEL(p, j, i, 0) = ((pixel >> 11) & 0x1f) * 255 / 31;
+ TILE_PIXEL(p, j, i, 1) = ((pixel >> 5) & 0x3f) * 255 / 63;
+ TILE_PIXEL(p, j, i, 2) = ((pixel ) & 0x1f) * 255 / 31;
+ TILE_PIXEL(p, j, i, 3) = 255;
+ }
+ }
+}
+
+
+static void
+r5g6b5_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ uint r = (uint) TILE_PIXEL(p, j, i, 0) * 31 / 255;
+ uint g = (uint) TILE_PIXEL(p, j, i, 1) * 63 / 255;
+ uint b = (uint) TILE_PIXEL(p, j, i, 2) * 31 / 255;
+ *dst++ = (r << 11) | (g << 5) | (b);
+ }
+ }
+}
+
+
+
+/*** PIPE_FORMAT_Z16_UNORM ***/
+
+/**
+ * Return each Z value as four floats in [0,1].
+ */
+static void
+z16_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ const float scale = 1.0f / 65535.0f;
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) =
+ TILE_PIXEL(p, j, i, 3) = *src++ * scale;
+ }
+ }
+}
+
+
+
+
+/*** PIPE_FORMAT_L8_UNORM ***/
+
+static void
+l8_get_tile_rgba(const ubyte *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++, src++) {
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) = *src;
+ TILE_PIXEL(p, j, i, 3) = 255;
+ }
+ }
+}
+
+
+static void
+l8_put_tile_rgba(ubyte *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ unsigned r;
+ r = TILE_PIXEL(p, j, i, 0);
+ *dst++ = (ubyte) r;
+ }
+ }
+}
+
+
+
+/*** PIPE_FORMAT_A8_UNORM ***/
+
+static void
+a8_get_tile_rgba(const ubyte *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++, src++) {
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) = 0;
+ TILE_PIXEL(p, j, i, 3) = *src;
+ }
+ }
+}
+
+
+static void
+a8_put_tile_rgba(ubyte *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ unsigned a;
+ a = TILE_PIXEL(p, j, i, 3);
+ *dst++ = (ubyte) a;
+ }
+ }
+}
+
+
+
+/*** PIPE_FORMAT_R16_SNORM ***/
+
+static void
+r16_get_tile_rgba(const short *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++, src++) {
+ TILE_PIXEL(p, j, i, 0) = MAX2(src[0] >> 7, 0);
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) = 0;
+ TILE_PIXEL(p, j, i, 3) = 255;
+ }
+ }
+}
+
+
+static void
+r16_put_tile_rgba(short *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++, dst++) {
+ dst[0] = TILE_PIXEL(p, j, i, 0) << 7;
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_R16G16B16A16_SNORM ***/
+
+static void
+r16g16b16a16_get_tile_rgba(const short *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++, src += 4) {
+ TILE_PIXEL(p, j, i, 0) = src[0] >> 8;
+ TILE_PIXEL(p, j, i, 1) = src[1] >> 8;
+ TILE_PIXEL(p, j, i, 2) = src[2] >> 8;
+ TILE_PIXEL(p, j, i, 3) = src[3] >> 8;
+ }
+ }
+}
+
+
+static void
+r16g16b16a16_put_tile_rgba(short *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++, dst += 4) {
+ dst[0] = TILE_PIXEL(p, j, i, 0) << 8;
+ dst[1] = TILE_PIXEL(p, j, i, 1) << 8;
+ dst[2] = TILE_PIXEL(p, j, i, 2) << 8;
+ dst[3] = TILE_PIXEL(p, j, i, 3) << 8;
+ }
+ }
+}
+
+
+
+/*** PIPE_FORMAT_I8_UNORM ***/
+
+static void
+i8_get_tile_rgba(const ubyte *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++, src++) {
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) =
+ TILE_PIXEL(p, j, i, 3) = *src;
+ }
+ }
+}
+
+
+static void
+i8_put_tile_rgba(ubyte *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ unsigned r;
+ r = TILE_PIXEL(p, j, i, 0);
+ *dst++ = (ubyte) r;
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_A8L8_UNORM ***/
+
+static void
+a8l8_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ ushort ra = *src++;
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) = ra & 0xff;
+ TILE_PIXEL(p, j, i, 3) = ra >> 8;
+ }
+ }
+}
+
+
+static void
+a8l8_put_tile_rgba(ushort *dst,
+ unsigned w, unsigned h,
+ const uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ unsigned r, a;
+ r = TILE_PIXEL(p, j, i, 0);
+ a = TILE_PIXEL(p, j, i, 3);
+ *dst++ = (a << 8) | r;
+ }
+ }
+}
+
+
+
+
+/*** PIPE_FORMAT_Z32_UNORM ***/
+
+/**
+ * Return each Z value as four floats in [0,1].
+ */
+static void
+z32_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ const double scale = 1.0 / (double) 0xffffffff;
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) =
+ TILE_PIXEL(p, j, i, 3) = (float) (*src++ * scale);
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_S8Z24_UNORM ***/
+
+/**
+ * Return Z component as four float in [0,1]. Stencil part ignored.
+ */
+static void
+s8z24_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ const double scale = 1.0 / ((1 << 24) - 1);
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) =
+ TILE_PIXEL(p, j, i, 3) = (float) (scale * (*src++ & 0xffffff));
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_Z24S8_UNORM ***/
+
+/**
+ * Return Z component as four float in [0,1]. Stencil part ignored.
+ */
+static void
+z24s8_get_tile_rgba(const unsigned *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ const double scale = 1.0 / ((1 << 24) - 1);
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) =
+ TILE_PIXEL(p, j, i, 3) = (float) (scale * (*src++ >> 8));
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_Z32_FLOAT ***/
+
+/**
+ * Return each Z value as four floats in [0,1].
+ */
+static void
+z32f_get_tile_rgba(const float *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) =
+ TILE_PIXEL(p, j, i, 3) = *src++;
+ }
+ }
+}
+
+
+/*** PIPE_FORMAT_YCBCR / PIPE_FORMAT_YCBCR_REV ***/
+
+/**
+ * Convert YCbCr (or YCrCb) to RGBA.
+ */
+static void
+ycbcr_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ uint8_t *p,
+ boolean rev)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ /* do two texels at a time */
+ for (j = 0; j < (w & ~1); j += 2, src += 2) {
+ const ushort t0 = src[0];
+ const ushort t1 = src[1];
+ const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */
+ const ubyte y1 = (t1 >> 8) & 0xff; /* luminance */
+ ubyte cb, cr;
+ float r, g, b;
+
+ if (rev) {
+ cb = t1 & 0xff; /* chroma U */
+ cr = t0 & 0xff; /* chroma V */
+ }
+ else {
+ cb = t0 & 0xff; /* chroma U */
+ cr = t1 & 0xff; /* chroma V */
+ }
+
+ /* even pixel: y0,cr,cb */
+ r = 1.164f * (y0-16) + 1.596f * (cr-128);
+ g = 1.164f * (y0-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
+ b = 1.164f * (y0-16) + 2.018f * (cb-128);
+ TILE_PIXEL(p, j, i, 0) = r;
+ TILE_PIXEL(p, j, i, 1) = g;
+ TILE_PIXEL(p, j, i, 2) = b;
+ TILE_PIXEL(p, j, i, 3) = 255;
+
+ /* odd pixel: use y1,cr,cb */
+ r = 1.164f * (y1-16) + 1.596f * (cr-128);
+ g = 1.164f * (y1-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
+ b = 1.164f * (y1-16) + 2.018f * (cb-128);
+ TILE_PIXEL(p, j + 1, i, 0) = r;
+ TILE_PIXEL(p, j + 1, i, 1) = g;
+ TILE_PIXEL(p, j + 1, i, 2) = b;
+ TILE_PIXEL(p, j + 1, i, 3) = 255;
+ }
+ /* do the last texel */
+ if (w & 1) {
+ const ushort t0 = src[0];
+ const ushort t1 = src[1];
+ const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */
+ ubyte cb, cr;
+ float r, g, b;
+
+ if (rev) {
+ cb = t1 & 0xff; /* chroma U */
+ cr = t0 & 0xff; /* chroma V */
+ }
+ else {
+ cb = t0 & 0xff; /* chroma U */
+ cr = t1 & 0xff; /* chroma V */
+ }
+
+ /* even pixel: y0,cr,cb */
+ r = 1.164f * (y0-16) + 1.596f * (cr-128);
+ g = 1.164f * (y0-16) - 0.813f * (cr-128) - 0.391f * (cb-128);
+ b = 1.164f * (y0-16) + 2.018f * (cb-128);
+ TILE_PIXEL(p, j, i, 0) = r;
+ TILE_PIXEL(p, j, i, 1) = g;
+ TILE_PIXEL(p, j, i, 2) = b;
+ TILE_PIXEL(p, j, i, 3) = 255;
+ }
+ }
+}
+
+
+static void
+fake_get_tile_rgba(const ushort *src,
+ unsigned w, unsigned h,
+ uint8_t *p)
+{
+ unsigned i, j;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ TILE_PIXEL(p, j, i, 0) =
+ TILE_PIXEL(p, j, i, 1) =
+ TILE_PIXEL(p, j, i, 2) =
+ TILE_PIXEL(p, j, i, 3) = (i ^ j) & 1 ? 255 : 0;
+ }
+ }
+}
+
+
+static void
+lp_tile_raw_to_rgba_soa(enum pipe_format format,
+ void *src,
+ uint w, uint h,
+ uint8_t *p)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ a8r8g8b8_get_tile_rgba((unsigned *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ x8r8g8b8_get_tile_rgba((unsigned *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ b8g8r8a8_get_tile_rgba((unsigned *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ a1r5g5b5_get_tile_rgba((ushort *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ a4r4g4b4_get_tile_rgba((ushort *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ r5g6b5_get_tile_rgba((ushort *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_L8_UNORM:
+ l8_get_tile_rgba((ubyte *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_A8_UNORM:
+ a8_get_tile_rgba((ubyte *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_I8_UNORM:
+ i8_get_tile_rgba((ubyte *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_A8L8_UNORM:
+ a8l8_get_tile_rgba((ushort *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_R16_SNORM:
+ r16_get_tile_rgba((short *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ r16g16b16a16_get_tile_rgba((short *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ z16_get_tile_rgba((ushort *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_Z32_UNORM:
+ z32_get_tile_rgba((unsigned *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ s8z24_get_tile_rgba((unsigned *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ z24s8_get_tile_rgba((unsigned *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_Z32_FLOAT:
+ z32f_get_tile_rgba((float *) src, w, h, p);
+ break;
+ case PIPE_FORMAT_YCBCR:
+ ycbcr_get_tile_rgba((ushort *) src, w, h, p, FALSE);
+ break;
+ case PIPE_FORMAT_YCBCR_REV:
+ ycbcr_get_tile_rgba((ushort *) src, w, h, p, TRUE);
+ break;
+ default:
+ debug_printf("%s: unsupported format %s\n", __FUNCTION__, pf_name(format));
+ fake_get_tile_rgba(src, w, h, p);
+ }
+}
+
+
+void
+lp_get_tile_rgba_soa(struct pipe_transfer *pt,
+ uint x, uint y,
+ uint8_t *p)
+{
+ uint w = TILE_SIZE, h = TILE_SIZE;
+ void *packed;
+
+ if (pipe_clip_tile(x, y, &w, &h, pt))
+ return;
+
+ packed = MALLOC(pf_get_nblocks(&pt->block, w, h) * pt->block.size);
+
+ if (!packed)
+ return;
+
+ if(pt->format == PIPE_FORMAT_YCBCR || pt->format == PIPE_FORMAT_YCBCR_REV)
+ assert((x & 1) == 0);
+
+ pipe_get_tile_raw(pt, x, y, w, h, packed, 0);
+
+ lp_tile_raw_to_rgba_soa(pt->format, packed, w, h, p);
+
+ FREE(packed);
+}
+
+
+void
+lp_put_tile_rgba_soa(struct pipe_transfer *pt,
+ uint x, uint y,
+ const uint8_t *p)
+{
+ uint w = TILE_SIZE, h = TILE_SIZE;
+ void *packed;
+
+ if (pipe_clip_tile(x, y, &w, &h, pt))
+ return;
+
+ packed = MALLOC(pf_get_nblocks(&pt->block, w, h) * pt->block.size);
+
+ if (!packed)
+ return;
+
+ switch (pt->format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ a8r8g8b8_put_tile_rgba((unsigned *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ x8r8g8b8_put_tile_rgba((unsigned *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ b8g8r8a8_put_tile_rgba((unsigned *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ a1r5g5b5_put_tile_rgba((ushort *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ r5g6b5_put_tile_rgba((ushort *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ assert(0);
+ break;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ a4r4g4b4_put_tile_rgba((ushort *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_L8_UNORM:
+ l8_put_tile_rgba((ubyte *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_A8_UNORM:
+ a8_put_tile_rgba((ubyte *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_I8_UNORM:
+ i8_put_tile_rgba((ubyte *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_A8L8_UNORM:
+ a8l8_put_tile_rgba((ushort *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_R16_SNORM:
+ r16_put_tile_rgba((short *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ r16g16b16a16_put_tile_rgba((short *) packed, w, h, p);
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ /*z16_put_tile_rgba((ushort *) packed, w, h, p);*/
+ break;
+ case PIPE_FORMAT_Z32_UNORM:
+ /*z32_put_tile_rgba((unsigned *) packed, w, h, p);*/
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ /*s8z24_put_tile_rgba((unsigned *) packed, w, h, p);*/
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p);*/
+ break;
+ default:
+ debug_printf("%s: unsupported format %s\n", __FUNCTION__, pf_name(pt->format));
+ }
+
+ pipe_put_tile_raw(pt, x, y, w, h, packed, 0);
+
+ FREE(packed);
+}
+
+
diff --git a/src/gallium/drivers/llvmpipe/lp_tile_soa.h b/src/gallium/drivers/llvmpipe/lp_tile_soa.h
new file mode 100644
index 0000000000..3d8c703b73
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_tile_soa.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef LP_TILE_SOA_H
+#define LP_TILE_SOA_H
+
+#include "pipe/p_compiler.h"
+#include "tgsi/tgsi_exec.h" // for NUM_CHANNELS
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_transfer;
+
+
+/**
+ * Cache tile size (width and height). This needs to be a power of two.
+ */
+#define TILE_SIZE 64
+
+
+#define TILE_VECTOR_HEIGHT 2
+#define TILE_VECTOR_WIDTH 8
+
+extern const unsigned char
+tile_offset[TILE_VECTOR_HEIGHT][TILE_VECTOR_WIDTH];
+
+#define TILE_C_STRIDE (TILE_VECTOR_HEIGHT*TILE_VECTOR_WIDTH)
+#define TILE_X_STRIDE (NUM_CHANNELS*TILE_C_STRIDE)
+#define TILE_Y_STRIDE (TILE_VECTOR_HEIGHT*TILE_SIZE*NUM_CHANNELS)
+
+#define TILE_PIXEL(_p, _x, _y, _c) \
+ ((_p)[((_y)/TILE_VECTOR_HEIGHT)*TILE_Y_STRIDE + \
+ ((_x)/TILE_VECTOR_WIDTH)*TILE_X_STRIDE + \
+ (_c)*TILE_C_STRIDE + \
+ tile_offset[(_y) % TILE_VECTOR_HEIGHT][(_x) % TILE_VECTOR_WIDTH]])
+
+
+void
+lp_get_tile_rgba_soa(struct pipe_transfer *pt,
+ uint x, uint y,
+ uint8_t *p);
+
+void
+lp_put_tile_rgba_soa(struct pipe_transfer *pt,
+ uint x, uint y,
+ const uint8_t *p);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_winsys.h b/src/gallium/drivers/llvmpipe/lp_winsys.h
new file mode 100644
index 0000000000..595481c2cb
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_winsys.h
@@ -0,0 +1,128 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * llvmpipe public interface.
+ */
+
+
+#ifndef LP_WINSYS_H
+#define LP_WINSYS_H
+
+
+#include "pipe/p_compiler.h" // for boolean
+#include "pipe/p_format.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_screen;
+struct pipe_context;
+
+
+/**
+ * Opaque pointer.
+ */
+struct llvmpipe_displaytarget;
+
+
+/**
+ * This is the interface that llvmpipe expects any window system
+ * hosting it to implement.
+ *
+ * llvmpipe is for the most part a self sufficient driver. The only thing it
+ * does not know is how to display a surface.
+ */
+struct llvmpipe_winsys
+{
+ void
+ (*destroy)( struct llvmpipe_winsys *ws );
+
+ boolean
+ (*is_displaytarget_format_supported)( struct llvmpipe_winsys *ws,
+ enum pipe_format format );
+
+ /**
+ * Allocate storage for a render target.
+ *
+ * Often surfaces which are meant to be blitted to the front screen (i.e.,
+ * display targets) must be allocated with special characteristics, memory
+ * pools, or obtained directly from the windowing system.
+ *
+ * This callback is invoked by the pipe_screen when creating a texture marked
+ * with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET flag to get the underlying
+ * storage.
+ */
+ struct llvmpipe_displaytarget *
+ (*displaytarget_create)( struct llvmpipe_winsys *ws,
+ enum pipe_format format,
+ unsigned width, unsigned height,
+ unsigned alignment,
+ unsigned *stride );
+
+ void *
+ (*displaytarget_map)( struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt,
+ unsigned flags );
+
+ void
+ (*displaytarget_unmap)( struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt );
+
+ /**
+ * @sa pipe_screen:flush_frontbuffer.
+ *
+ * This call will likely become asynchronous eventually.
+ */
+ void
+ (*displaytarget_display)( struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt,
+ void *context_private );
+
+ void
+ (*displaytarget_destroy)( struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt );
+};
+
+
+struct pipe_context *
+llvmpipe_create( struct pipe_screen * );
+
+
+struct pipe_screen *
+llvmpipe_create_screen( struct llvmpipe_winsys * );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LP_WINSYS_H */
diff --git a/src/gallium/drivers/llvmpipe/sp2lp.sh b/src/gallium/drivers/llvmpipe/sp2lp.sh
new file mode 100755
index 0000000000..c45a81ce3c
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/sp2lp.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Port changes from softpipe to llvmpipe. Invoke as
+#
+# sp2lp.sh <commit>
+#
+# Note that this will only affect llvmpipe -- you still need to actually
+# cherry-pick/merge the softpipe changes themselves if they affect directories
+# outside src/gallium/drivers/softpipe
+
+git format-patch \
+ --keep-subject \
+ --relative=src/gallium/drivers/softpipe \
+ --src-prefix=a/src/gallium/drivers/llvmpipe/ \
+ --dst-prefix=b/src/gallium/drivers/llvmpipe/ \
+ --stdout "$1^1..$1" \
+| sed \
+ -e 's/\<softpipe\>/llvmpipe/g' \
+ -e 's/\<sp\>/lp/g' \
+ -e 's/\<softpipe_/llvmpipe_/g' \
+ -e 's/\<sp_/lp_/g' \
+ -e 's/\<SP_/LP_/g' \
+ -e 's/\<SOFTPIPE_/LLVMPIPE_/g' \
+ -e 's/\<spt\>/lpt/g' \
+ -e 's/\<sps\>/lps/g' \
+ -e 's/\<spfs\>/lpfs/g' \
+ -e 's/\<sptex\>/lptex/g' \
+ -e 's/\<setup_\(point\|line\|tri\)\>/llvmpipe_\0/g' \
+ -e 's/\<llvmpipe_cached_tile\>/llvmpipe_cached_tex_tile/g' \
+ -e 's/_get_cached_tile_tex\>/_get_cached_tex_tile/g' \
+ -e 's/\<TILE_SIZE\>/TEX_TILE_SIZE/g' \
+ -e 's/\<tile_address\>/tex_tile_address/g' \
+ -e 's/\<tile->data\.color\>/tile->color/g' \
+| patch -p1
diff --git a/src/gallium/drivers/nouveau/Makefile b/src/gallium/drivers/nouveau/Makefile
new file mode 100644
index 0000000000..dbe8a6e7bf
--- /dev/null
+++ b/src/gallium/drivers/nouveau/Makefile
@@ -0,0 +1,8 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nouveau
+
+C_SOURCES = nouveau_screen.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/nouveau/nouveau_gldefs.h b/src/gallium/drivers/nouveau/nouveau_gldefs.h
new file mode 100644
index 0000000000..ff97aaa9af
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_gldefs.h
@@ -0,0 +1,196 @@
+#ifndef __NOUVEAU_GLDEFS_H__
+#define __NOUVEAU_GLDEFS_H__
+
+static INLINE unsigned
+nvgl_blend_func(unsigned factor)
+{
+ switch (factor) {
+ case PIPE_BLENDFACTOR_ZERO:
+ return 0x0000;
+ case PIPE_BLENDFACTOR_ONE:
+ return 0x0001;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ return 0x0300;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ return 0x0301;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ return 0x0302;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ return 0x0303;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ return 0x0304;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ return 0x0305;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ return 0x0306;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ return 0x0307;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ return 0x0308;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ return 0x8001;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ return 0x8002;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ return 0x8003;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ return 0x8004;
+ default:
+ return 0x0000;
+ }
+}
+
+static INLINE unsigned
+nvgl_blend_eqn(unsigned func)
+{
+ switch (func) {
+ case PIPE_BLEND_ADD:
+ return 0x8006;
+ case PIPE_BLEND_MIN:
+ return 0x8007;
+ case PIPE_BLEND_MAX:
+ return 0x8008;
+ case PIPE_BLEND_SUBTRACT:
+ return 0x800a;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ return 0x800b;
+ default:
+ return 0x8006;
+ }
+}
+
+static INLINE unsigned
+nvgl_logicop_func(unsigned func)
+{
+ switch (func) {
+ case PIPE_LOGICOP_CLEAR:
+ return 0x1500;
+ case PIPE_LOGICOP_NOR:
+ return 0x1508;
+ case PIPE_LOGICOP_AND_INVERTED:
+ return 0x1504;
+ case PIPE_LOGICOP_COPY_INVERTED:
+ return 0x150c;
+ case PIPE_LOGICOP_AND_REVERSE:
+ return 0x1502;
+ case PIPE_LOGICOP_INVERT:
+ return 0x150a;
+ case PIPE_LOGICOP_XOR:
+ return 0x1506;
+ case PIPE_LOGICOP_NAND:
+ return 0x150e;
+ case PIPE_LOGICOP_AND:
+ return 0x1501;
+ case PIPE_LOGICOP_EQUIV:
+ return 0x1509;
+ case PIPE_LOGICOP_NOOP:
+ return 0x1505;
+ case PIPE_LOGICOP_OR_INVERTED:
+ return 0x150d;
+ case PIPE_LOGICOP_COPY:
+ return 0x1503;
+ case PIPE_LOGICOP_OR_REVERSE:
+ return 0x150b;
+ case PIPE_LOGICOP_OR:
+ return 0x1507;
+ case PIPE_LOGICOP_SET:
+ return 0x150f;
+ default:
+ return 0x1505;
+ }
+}
+
+static INLINE unsigned
+nvgl_comparison_op(unsigned op)
+{
+ switch (op) {
+ case PIPE_FUNC_NEVER:
+ return 0x0200;
+ case PIPE_FUNC_LESS:
+ return 0x0201;
+ case PIPE_FUNC_EQUAL:
+ return 0x0202;
+ case PIPE_FUNC_LEQUAL:
+ return 0x0203;
+ case PIPE_FUNC_GREATER:
+ return 0x0204;
+ case PIPE_FUNC_NOTEQUAL:
+ return 0x0205;
+ case PIPE_FUNC_GEQUAL:
+ return 0x0206;
+ case PIPE_FUNC_ALWAYS:
+ return 0x0207;
+ default:
+ return 0x0207;
+ }
+}
+
+static INLINE unsigned
+nvgl_polygon_mode(unsigned mode)
+{
+ switch (mode) {
+ case PIPE_POLYGON_MODE_POINT:
+ return 0x1b00;
+ case PIPE_POLYGON_MODE_LINE:
+ return 0x1b01;
+ case PIPE_POLYGON_MODE_FILL:
+ return 0x1b02;
+ default:
+ return 0x1b02;
+ }
+}
+
+static INLINE unsigned
+nvgl_stencil_op(unsigned op)
+{
+ switch (op) {
+ case PIPE_STENCIL_OP_ZERO:
+ return 0x0000;
+ case PIPE_STENCIL_OP_INVERT:
+ return 0x150a;
+ case PIPE_STENCIL_OP_KEEP:
+ return 0x1e00;
+ case PIPE_STENCIL_OP_REPLACE:
+ return 0x1e01;
+ case PIPE_STENCIL_OP_INCR:
+ return 0x1e02;
+ case PIPE_STENCIL_OP_DECR:
+ return 0x1e03;
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ return 0x8507;
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ return 0x8508;
+ default:
+ return 0x1e00;
+ }
+}
+
+static INLINE unsigned
+nvgl_primitive(unsigned prim) {
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ return 0x0001;
+ case PIPE_PRIM_LINES:
+ return 0x0002;
+ case PIPE_PRIM_LINE_LOOP:
+ return 0x0003;
+ case PIPE_PRIM_LINE_STRIP:
+ return 0x0004;
+ case PIPE_PRIM_TRIANGLES:
+ return 0x0005;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ return 0x0006;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ return 0x0007;
+ case PIPE_PRIM_QUADS:
+ return 0x0008;
+ case PIPE_PRIM_QUAD_STRIP:
+ return 0x0009;
+ case PIPE_PRIM_POLYGON:
+ return 0x000a;
+ default:
+ return 0;
+ }
+}
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_push.h b/src/gallium/drivers/nouveau/nouveau_push.h
new file mode 100644
index 0000000000..9c235080a5
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_push.h
@@ -0,0 +1,93 @@
+#ifndef __NOUVEAU_PUSH_H__
+#define __NOUVEAU_PUSH_H__
+
+#include "nouveau/nouveau_winsys.h"
+
+#ifndef NOUVEAU_PUSH_CONTEXT
+#error undefined push context
+#endif
+
+#define OUT_RING(data) do { \
+ NOUVEAU_PUSH_CONTEXT(pc); \
+ (*pc->base.channel->pushbuf->cur++) = (data); \
+} while(0)
+
+#define OUT_RINGp(src,size) do { \
+ NOUVEAU_PUSH_CONTEXT(pc); \
+ memcpy(pc->base.channel->pushbuf->cur, (src), (size) * 4); \
+ pc->base.channel->pushbuf->cur += (size); \
+} while(0)
+
+#define OUT_RINGf(data) do { \
+ union { float v; uint32_t u; } c; \
+ c.v = (data); \
+ OUT_RING(c.u); \
+} while(0)
+
+#define BEGIN_RING(obj,mthd,size) do { \
+ NOUVEAU_PUSH_CONTEXT(pc); \
+ struct nouveau_channel *chan = pc->base.channel; \
+ if (chan->pushbuf->remaining < ((size) + 1)) \
+ nouveau_pushbuf_flush(chan, ((size) + 1)); \
+ OUT_RING((pc->obj->subc << 13) | ((size) << 18) | (mthd)); \
+ chan->pushbuf->remaining -= ((size) + 1); \
+} while(0)
+
+#define BEGIN_RING_NI(obj,mthd,size) do { \
+ BEGIN_RING(obj, (mthd) | 0x40000000, (size)); \
+} while(0)
+
+static inline void
+DO_FIRE_RING(struct nouveau_channel *chan, struct pipe_fence_handle **fence)
+{
+ nouveau_pushbuf_flush(chan, 0);
+ if (fence)
+ *fence = NULL;
+}
+
+#define FIRE_RING(fence) do { \
+ NOUVEAU_PUSH_CONTEXT(pc); \
+ DO_FIRE_RING(pc->base.channel, fence); \
+} while(0)
+
+#define OUT_RELOC(bo,data,flags,vor,tor) do { \
+ NOUVEAU_PUSH_CONTEXT(pc); \
+ struct nouveau_channel *chan = pc->base.channel; \
+ nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, nouveau_bo(bo), \
+ (data), 0, (flags), (vor), (tor)); \
+} while(0)
+
+/* Raw data + flags depending on FB/TT buffer */
+#define OUT_RELOCd(bo,data,flags,vor,tor) do { \
+ OUT_RELOC((bo), (data), (flags) | NOUVEAU_BO_OR, (vor), (tor)); \
+} while(0)
+
+/* FB/TT object handle */
+#define OUT_RELOCo(bo,flags) do { \
+ OUT_RELOC((bo), 0, (flags) | NOUVEAU_BO_OR, \
+ pc->base.channel->vram->handle, \
+ pc->base.channel->gart->handle); \
+} while(0)
+
+/* Low 32-bits of offset */
+#define OUT_RELOCl(bo,delta,flags) do { \
+ OUT_RELOC((bo), (delta), (flags) | NOUVEAU_BO_LOW, 0, 0); \
+} while(0)
+
+/* High 32-bits of offset */
+#define OUT_RELOCh(bo,delta,flags) do { \
+ OUT_RELOC((bo), (delta), (flags) | NOUVEAU_BO_HIGH, 0, 0); \
+} while(0)
+
+/* A reloc which'll recombine into a NV_DMA_METHOD packet header */
+#define OUT_RELOCm(bo, flags, obj, mthd, size) do { \
+ NOUVEAU_PUSH_CONTEXT(pc); \
+ struct nouveau_channel *chan = pc->base.channel; \
+ if (chan->pushbuf->remaining < ((size) + 1)) \
+ nouveau_pushbuf_flush(chan, ((size) + 1)); \
+ OUT_RELOCd((bo), (pc->obj->subc << 13) | ((size) << 18) | (mthd), \
+ (flags), 0, 0); \
+ chan->pushbuf->remaining -= ((size) + 1); \
+} while(0)
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
new file mode 100644
index 0000000000..e4cf91c005
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -0,0 +1,243 @@
+#include <pipe/p_defines.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_state.h>
+
+#include <util/u_memory.h>
+
+#include <errno.h>
+
+#include "nouveau/nouveau_bo.h"
+#include "nouveau_winsys.h"
+#include "nouveau_screen.h"
+
+static const char *
+nouveau_screen_get_name(struct pipe_screen *pscreen)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ static char buffer[128];
+
+ snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
+ return buffer;
+}
+
+static const char *
+nouveau_screen_get_vendor(struct pipe_screen *pscreen)
+{
+ return "nouveau";
+}
+
+static struct pipe_buffer *
+nouveau_screen_bo_skel(struct pipe_screen *pscreen, struct nouveau_bo *bo,
+ unsigned alignment, unsigned usage, unsigned size)
+{
+ struct pipe_buffer *pb;
+
+ pb = CALLOC(1, sizeof(struct pipe_buffer)+sizeof(struct nouveau_bo *));
+ if (!pb) {
+ nouveau_bo_ref(NULL, &bo);
+ return NULL;
+ }
+
+ pipe_reference_init(&pb->reference, 1);
+ pb->screen = pscreen;
+ pb->alignment = alignment;
+ pb->usage = usage;
+ pb->size = size;
+ *(struct nouveau_bo **)(pb + 1) = bo;
+ return pb;
+}
+
+static struct pipe_buffer *
+nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment,
+ unsigned usage, unsigned size)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct nouveau_bo *bo = NULL;
+ uint32_t flags = NOUVEAU_BO_MAP;
+ int ret;
+
+ if (usage & NOUVEAU_BUFFER_USAGE_TRANSFER)
+ flags |= NOUVEAU_BO_GART;
+ else
+ if (usage & PIPE_BUFFER_USAGE_VERTEX) {
+ if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF))
+ flags |= NOUVEAU_BO_GART;
+ } else
+ if (usage & PIPE_BUFFER_USAGE_INDEX) {
+ if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF))
+ flags |= NOUVEAU_BO_GART;
+ }
+
+ if (usage & PIPE_BUFFER_USAGE_PIXEL) {
+ if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
+ flags |= NOUVEAU_BO_GART;
+ if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE))
+ flags |= NOUVEAU_BO_VRAM;
+
+ if (dev->chipset == 0x50 || dev->chipset >= 0x80) {
+ flags |= NOUVEAU_BO_TILED;
+ if (usage & NOUVEAU_BUFFER_USAGE_ZETA)
+ flags |= NOUVEAU_BO_ZTILE;
+ }
+ }
+
+ ret = nouveau_bo_new(dev, flags, alignment, size, &bo);
+ if (ret)
+ return NULL;
+
+ return nouveau_screen_bo_skel(pscreen, bo, alignment, usage, size);
+}
+
+static struct pipe_buffer *
+nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct nouveau_bo *bo = NULL;
+ int ret;
+
+ ret = nouveau_bo_user(dev, ptr, bytes, &bo);
+ if (ret)
+ return NULL;
+
+ return nouveau_screen_bo_skel(pscreen, bo, 0, 0, bytes);
+}
+
+static inline uint32_t
+nouveau_screen_map_flags(unsigned pipe)
+{
+ uint32_t flags = 0;
+
+ if (pipe & PIPE_BUFFER_USAGE_CPU_READ)
+ flags |= NOUVEAU_BO_RD;
+ if (pipe & PIPE_BUFFER_USAGE_CPU_WRITE)
+ flags |= NOUVEAU_BO_WR;
+ if (pipe & PIPE_BUFFER_USAGE_DISCARD)
+ flags |= NOUVEAU_BO_INVAL;
+ if (pipe & PIPE_BUFFER_USAGE_DONTBLOCK)
+ flags |= NOUVEAU_BO_NOWAIT;
+ else
+ if (pipe & 0 /*PIPE_BUFFER_USAGE_UNSYNCHRONIZED*/)
+ flags |= NOUVEAU_BO_NOSYNC;
+
+ return flags;
+}
+
+static void *
+nouveau_screen_bo_map(struct pipe_screen *pscreen, struct pipe_buffer *pb,
+ unsigned usage)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+ int ret;
+
+ ret = nouveau_bo_map(bo, nouveau_screen_map_flags(usage));
+ if (ret) {
+ debug_printf("map failed: %d\n", ret);
+ return NULL;
+ }
+
+ return bo->map;
+}
+
+static void *
+nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct pipe_buffer *pb,
+ unsigned offset, unsigned length, unsigned usage)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+ uint32_t flags = nouveau_screen_map_flags(usage);
+ int ret;
+
+ ret = nouveau_bo_map_range(bo, offset, length, flags);
+ if (ret) {
+ if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
+ debug_printf("map_range failed: %d\n", ret);
+ return NULL;
+ }
+
+ return (char *)bo->map - offset; /* why gallium? why? */
+}
+
+static void
+nouveau_screen_bo_map_flush(struct pipe_screen *pscreen, struct pipe_buffer *pb,
+ unsigned offset, unsigned length)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+
+ nouveau_bo_map_flush(bo, offset, length);
+}
+
+static void
+nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct pipe_buffer *pb)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+
+ nouveau_bo_unmap(bo);
+}
+
+static void
+nouveau_screen_bo_del(struct pipe_buffer *pb)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+
+ nouveau_bo_ref(NULL, &bo);
+ FREE(pb);
+}
+
+static void
+nouveau_screen_fence_ref(struct pipe_screen *pscreen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *pfence)
+{
+ *ptr = pfence;
+}
+
+static int
+nouveau_screen_fence_signalled(struct pipe_screen *screen,
+ struct pipe_fence_handle *pfence,
+ unsigned flags)
+{
+ return 0;
+}
+
+static int
+nouveau_screen_fence_finish(struct pipe_screen *screen,
+ struct pipe_fence_handle *pfence,
+ unsigned flags)
+{
+ return 0;
+}
+
+int
+nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
+{
+ struct pipe_screen *pscreen = &screen->base;
+ int ret;
+
+ ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202,
+ &screen->channel);
+ if (ret)
+ return ret;
+ screen->device = dev;
+
+ pscreen->get_name = nouveau_screen_get_name;
+ pscreen->get_vendor = nouveau_screen_get_vendor;
+
+ pscreen->buffer_create = nouveau_screen_bo_new;
+ pscreen->user_buffer_create = nouveau_screen_bo_user;
+ pscreen->buffer_map = nouveau_screen_bo_map;
+ pscreen->buffer_map_range = nouveau_screen_bo_map_range;
+ pscreen->buffer_flush_mapped_range = nouveau_screen_bo_map_flush;
+ pscreen->buffer_unmap = nouveau_screen_bo_unmap;
+ pscreen->buffer_destroy = nouveau_screen_bo_del;
+
+ pscreen->fence_reference = nouveau_screen_fence_ref;
+ pscreen->fence_signalled = nouveau_screen_fence_signalled;
+ pscreen->fence_finish = nouveau_screen_fence_finish;
+
+ return 0;
+}
+
+void
+nouveau_screen_fini(struct nouveau_screen *screen)
+{
+}
+
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h
new file mode 100644
index 0000000000..ebfc67ad1c
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -0,0 +1,36 @@
+#ifndef __NOUVEAU_SCREEN_H__
+#define __NOUVEAU_SCREEN_H__
+
+struct nouveau_screen {
+ struct pipe_screen base;
+ struct nouveau_device *device;
+ struct nouveau_channel *channel;
+};
+
+static inline struct nouveau_screen *
+nouveau_screen(struct pipe_screen *pscreen)
+{
+ return (struct nouveau_screen *)pscreen;
+}
+
+static inline struct nouveau_bo *
+nouveau_bo(struct pipe_buffer *pb)
+{
+ return pb ? *(struct nouveau_bo **)(pb + 1) : NULL;
+}
+
+int nouveau_screen_init(struct nouveau_screen *, struct nouveau_device *);
+void nouveau_screen_fini(struct nouveau_screen *);
+
+struct nouveau_miptree {
+ struct pipe_texture base;
+ struct nouveau_bo *bo;
+};
+
+static inline struct nouveau_miptree *
+nouveau_miptree(struct pipe_texture *pt)
+{
+ return (struct nouveau_miptree *)pt;
+}
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h b/src/gallium/drivers/nouveau/nouveau_stateobj.h
new file mode 100644
index 0000000000..b595405357
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h
@@ -0,0 +1,159 @@
+#ifndef __NOUVEAU_STATEOBJ_H__
+#define __NOUVEAU_STATEOBJ_H__
+
+#include "util/u_debug.h"
+
+struct nouveau_stateobj_reloc {
+ struct nouveau_bo *bo;
+
+ unsigned offset;
+ unsigned packet;
+
+ unsigned data;
+ unsigned flags;
+ unsigned vor;
+ unsigned tor;
+};
+
+struct nouveau_stateobj {
+ struct pipe_reference reference;
+
+ unsigned *push;
+ struct nouveau_stateobj_reloc *reloc;
+
+ unsigned *cur;
+ unsigned cur_packet;
+ unsigned cur_reloc;
+};
+
+static INLINE struct nouveau_stateobj *
+so_new(unsigned push, unsigned reloc)
+{
+ struct nouveau_stateobj *so;
+
+ so = MALLOC(sizeof(struct nouveau_stateobj));
+ pipe_reference_init(&so->reference, 1);
+ so->push = MALLOC(sizeof(unsigned) * push);
+ so->reloc = MALLOC(sizeof(struct nouveau_stateobj_reloc) * reloc);
+
+ so->cur = so->push;
+ so->cur_reloc = so->cur_packet = 0;
+
+ return so;
+}
+
+static INLINE void
+so_ref(struct nouveau_stateobj *ref, struct nouveau_stateobj **pso)
+{
+ struct nouveau_stateobj *so = *pso;
+ int i;
+
+ if (pipe_reference((struct pipe_reference**)pso, &ref->reference)) {
+ free(so->push);
+ for (i = 0; i < so->cur_reloc; i++)
+ nouveau_bo_ref(NULL, &so->reloc[i].bo);
+ free(so->reloc);
+ free(so);
+ }
+}
+
+static INLINE void
+so_data(struct nouveau_stateobj *so, unsigned data)
+{
+ (*so->cur++) = (data);
+ so->cur_packet += 4;
+}
+
+static INLINE void
+so_datap(struct nouveau_stateobj *so, unsigned *data, unsigned size)
+{
+ so->cur_packet += (4 * size);
+ while (size--)
+ (*so->cur++) = (*data++);
+}
+
+static INLINE void
+so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr,
+ unsigned mthd, unsigned size)
+{
+ so->cur_packet = (gr->subc << 13) | (1 << 18) | (mthd - 4);
+ so_data(so, (gr->subc << 13) | (size << 18) | mthd);
+}
+
+static INLINE void
+so_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo,
+ unsigned data, unsigned flags, unsigned vor, unsigned tor)
+{
+ struct nouveau_stateobj_reloc *r = &so->reloc[so->cur_reloc++];
+
+ r->bo = NULL;
+ nouveau_bo_ref(bo, &r->bo);
+ r->offset = so->cur - so->push;
+ r->packet = so->cur_packet;
+ r->data = data;
+ r->flags = flags;
+ r->vor = vor;
+ r->tor = tor;
+ so_data(so, data);
+}
+
+static INLINE void
+so_dump(struct nouveau_stateobj *so)
+{
+ unsigned i, nr = so->cur - so->push;
+
+ for (i = 0; i < nr; i++)
+ debug_printf("+0x%04x: 0x%08x\n", i, so->push[i]);
+}
+
+static INLINE void
+so_emit(struct nouveau_channel *chan, struct nouveau_stateobj *so)
+{
+ struct nouveau_pushbuf *pb = chan->pushbuf;
+ unsigned nr, i;
+
+ nr = so->cur - so->push;
+ if (pb->remaining < nr)
+ nouveau_pushbuf_flush(chan, nr);
+ pb->remaining -= nr;
+
+ memcpy(pb->cur, so->push, nr * 4);
+ for (i = 0; i < so->cur_reloc; i++) {
+ struct nouveau_stateobj_reloc *r = &so->reloc[i];
+
+ nouveau_pushbuf_emit_reloc(chan, pb->cur + r->offset,
+ r->bo, r->data, 0, r->flags,
+ r->vor, r->tor);
+ }
+ pb->cur += nr;
+}
+
+static INLINE void
+so_emit_reloc_markers(struct nouveau_channel *chan, struct nouveau_stateobj *so)
+{
+ struct nouveau_pushbuf *pb = chan->pushbuf;
+ unsigned i;
+
+ if (!so)
+ return;
+
+ i = so->cur_reloc << 1;
+ if (pb->remaining < i)
+ nouveau_pushbuf_flush(chan, i);
+ pb->remaining -= i;
+
+ for (i = 0; i < so->cur_reloc; i++) {
+ struct nouveau_stateobj_reloc *r = &so->reloc[i];
+
+ nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->packet, 0,
+ (r->flags & (NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_GART |
+ NOUVEAU_BO_RDWR)) |
+ NOUVEAU_BO_DUMMY, 0, 0);
+ nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->data, 0,
+ r->flags | NOUVEAU_BO_DUMMY,
+ r->vor, r->tor);
+ }
+}
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_util.h b/src/gallium/drivers/nouveau/nouveau_util.h
new file mode 100644
index 0000000000..a10114beab
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_util.h
@@ -0,0 +1,91 @@
+#ifndef __NOUVEAU_UTIL_H__
+#define __NOUVEAU_UTIL_H__
+
+/* Determine how many vertices can be pushed into the command stream.
+ * Where the remaining space isn't large enough to represent all verices,
+ * split the buffer at primitive boundaries.
+ *
+ * Returns a count of vertices that can be rendered, and an index to
+ * restart drawing at after a flush.
+ */
+static INLINE unsigned
+nouveau_vbuf_split(unsigned remaining, unsigned overhead, unsigned vpp,
+ unsigned mode, unsigned start, unsigned count,
+ unsigned *restart)
+{
+ int max, adj = 0;
+
+ max = remaining - overhead;
+ if (max < 0)
+ return 0;
+
+ max *= vpp;
+ if (max >= count)
+ return count;
+
+ switch (mode) {
+ case PIPE_PRIM_POINTS:
+ break;
+ case PIPE_PRIM_LINES:
+ max = max & 1;
+ break;
+ case PIPE_PRIM_TRIANGLES:
+ max = max - (max % 3);
+ break;
+ case PIPE_PRIM_QUADS:
+ max = max & 3;
+ break;
+ case PIPE_PRIM_LINE_LOOP:
+ case PIPE_PRIM_LINE_STRIP:
+ if (max < 2)
+ max = 0;
+ adj = 1;
+ break;
+ case PIPE_PRIM_POLYGON:
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ case PIPE_PRIM_TRIANGLE_FAN:
+ if (max < 3)
+ max = 0;
+ adj = 2;
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ if (max < 4)
+ max = 0;
+ adj = 3;
+ break;
+ default:
+ assert(0);
+ }
+
+ *restart = start + max - adj;
+ return max;
+}
+
+/* Integer base-2 logarithm, rounded towards zero. */
+static INLINE unsigned log2i(unsigned i)
+{
+ unsigned r = 0;
+
+ if (i & 0xffff0000) {
+ i >>= 16;
+ r += 16;
+ }
+ if (i & 0x0000ff00) {
+ i >>= 8;
+ r += 8;
+ }
+ if (i & 0x000000f0) {
+ i >>= 4;
+ r += 4;
+ }
+ if (i & 0x0000000c) {
+ i >>= 2;
+ r += 2;
+ }
+ if (i & 0x00000002) {
+ r += 1;
+ }
+ return r;
+}
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h
new file mode 100644
index 0000000000..42c77e5e77
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_winsys.h
@@ -0,0 +1,62 @@
+#ifndef NOUVEAU_WINSYS_H
+#define NOUVEAU_WINSYS_H
+
+#include <stdint.h>
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_defines.h"
+
+#include "nouveau/nouveau_bo.h"
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_class.h"
+#include "nouveau/nouveau_device.h"
+#include "nouveau/nouveau_grobj.h"
+#include "nouveau/nouveau_notifier.h"
+#include "nouveau/nouveau_resource.h"
+#include "nouveau/nouveau_pushbuf.h"
+
+#define NOUVEAU_CAP_HW_VTXBUF (0xbeef0000)
+#define NOUVEAU_CAP_HW_IDXBUF (0xbeef0001)
+
+#define NOUVEAU_TEXTURE_USAGE_LINEAR (1 << 16)
+
+#define NOUVEAU_BUFFER_USAGE_TEXTURE (1 << 16)
+#define NOUVEAU_BUFFER_USAGE_ZETA (1 << 17)
+#define NOUVEAU_BUFFER_USAGE_TRANSFER (1 << 18)
+
+extern struct pipe_screen *
+nv04_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
+
+extern struct pipe_context *
+nv04_create(struct pipe_screen *, unsigned pctx_id);
+
+extern struct pipe_screen *
+nv10_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
+
+extern struct pipe_context *
+nv10_create(struct pipe_screen *, unsigned pctx_id);
+
+extern struct pipe_screen *
+nv20_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
+
+extern struct pipe_context *
+nv20_create(struct pipe_screen *, unsigned pctx_id);
+
+extern struct pipe_screen *
+nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
+
+extern struct pipe_context *
+nv30_create(struct pipe_screen *, unsigned pctx_id);
+
+extern struct pipe_screen *
+nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
+
+extern struct pipe_context *
+nv40_create(struct pipe_screen *, unsigned pctx_id);
+
+extern struct pipe_screen *
+nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
+
+extern struct pipe_context *
+nv50_create(struct pipe_screen *, unsigned pctx_id);
+
+#endif
diff --git a/src/gallium/drivers/nv04/Makefile b/src/gallium/drivers/nv04/Makefile
new file mode 100644
index 0000000000..7c14bacb1d
--- /dev/null
+++ b/src/gallium/drivers/nv04/Makefile
@@ -0,0 +1,21 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv04
+
+C_SOURCES = \
+ nv04_surface_2d.c \
+ nv04_clear.c \
+ nv04_context.c \
+ nv04_fragprog.c \
+ nv04_fragtex.c \
+ nv04_miptree.c \
+ nv04_prim_vbuf.c \
+ nv04_screen.c \
+ nv04_state.c \
+ nv04_state_emit.c \
+ nv04_surface.c \
+ nv04_transfer.c \
+ nv04_vbo.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/nv04/nv04_clear.c b/src/gallium/drivers/nv04/nv04_clear.c
new file mode 100644
index 0000000000..01cacd36fe
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_clear.c
@@ -0,0 +1,12 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "nv04_context.h"
+
+void
+nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+ unsigned clearValue)
+{
+ pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue);
+}
diff --git a/src/gallium/drivers/nv04/nv04_context.c b/src/gallium/drivers/nv04/nv04_context.c
new file mode 100644
index 0000000000..17166c9f51
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_context.c
@@ -0,0 +1,134 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "nv04_context.h"
+#include "nv04_screen.h"
+
+static void
+nv04_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ draw_flush(nv04->draw);
+
+ FIRE_RING(fence);
+}
+
+static void
+nv04_destroy(struct pipe_context *pipe)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ if (nv04->draw)
+ draw_destroy(nv04->draw);
+
+ FREE(nv04);
+}
+
+static void
+nv04_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+}
+
+static boolean
+nv04_init_hwctx(struct nv04_context *nv04)
+{
+ // requires a valid handle
+// BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_NOTIFY, 1);
+// OUT_RING(0);
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_NOP, 1);
+ OUT_RING(0);
+
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1);
+ OUT_RING(0x40182800);
+// OUT_RING(1<<20/*no cull*/);
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_BLEND, 1);
+// OUT_RING(0x24|(1<<6)|(1<<8));
+ OUT_RING(0x120001a4);
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_FORMAT, 1);
+ OUT_RING(0x332213a1);
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_FILTER, 1);
+ OUT_RING(0x11001010);
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_COLORKEY, 1);
+ OUT_RING(0x0);
+// BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_OFFSET, 1);
+// OUT_RING(SCREEN_OFFSET);
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR, 1);
+ OUT_RING(0xff000000);
+
+
+
+ FIRE_RING (NULL);
+ return TRUE;
+}
+
+static unsigned int
+nv04_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static unsigned int
+nv04_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+
+struct pipe_context *
+nv04_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+ struct nv04_screen *screen = nv04_screen(pscreen);
+ struct pipe_winsys *ws = pscreen->winsys;
+ struct nv04_context *nv04;
+ struct nouveau_winsys *nvws = screen->nvws;
+
+ nv04 = CALLOC(1, sizeof(struct nv04_context));
+ if (!nv04)
+ return NULL;
+ nv04->screen = screen;
+ nv04->pctx_id = pctx_id;
+
+ nv04->nvws = nvws;
+
+ nv04->pipe.winsys = ws;
+ nv04->pipe.screen = pscreen;
+ nv04->pipe.destroy = nv04_destroy;
+ nv04->pipe.set_edgeflags = nv04_set_edgeflags;
+ nv04->pipe.draw_arrays = nv04_draw_arrays;
+ nv04->pipe.draw_elements = nv04_draw_elements;
+ nv04->pipe.clear = nv04_clear;
+ nv04->pipe.flush = nv04_flush;
+
+ nv04->pipe.is_texture_referenced = nv04_is_texture_referenced;
+ nv04->pipe.is_buffer_referenced = nv04_is_buffer_referenced;
+
+ nv04_init_surface_functions(nv04);
+ nv04_init_state_functions(nv04);
+
+ nv04->draw = draw_create();
+ assert(nv04->draw);
+ draw_wide_point_threshold(nv04->draw, 0.0);
+ draw_wide_line_threshold(nv04->draw, 0.0);
+ draw_enable_line_stipple(nv04->draw, FALSE);
+ draw_enable_point_sprites(nv04->draw, FALSE);
+ draw_set_rasterize_stage(nv04->draw, nv04_draw_vbuf_stage(nv04));
+
+ nv04_init_hwctx(nv04);
+
+ return &nv04->pipe;
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_context.h b/src/gallium/drivers/nv04/nv04_context.h
new file mode 100644
index 0000000000..2842b2c90d
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_context.h
@@ -0,0 +1,151 @@
+#ifndef __NV04_CONTEXT_H__
+#define __NV04_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx) \
+ struct nv04_screen *ctx = nv04->screen
+#include "nouveau/nouveau_push.h"
+
+#include "nv04_state.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+ fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+ fprintf(stderr, "nouveau: "fmt, ##args);
+
+#include "nv04_screen.h"
+
+#define NV04_NEW_VERTPROG (1 << 1)
+#define NV04_NEW_FRAGPROG (1 << 2)
+#define NV04_NEW_BLEND (1 << 3)
+#define NV04_NEW_RAST (1 << 4)
+#define NV04_NEW_CONTROL (1 << 5)
+#define NV04_NEW_VIEWPORT (1 << 6)
+#define NV04_NEW_SAMPLER (1 << 7)
+#define NV04_NEW_FRAMEBUFFER (1 << 8)
+#define NV04_NEW_VTXARRAYS (1 << 9)
+
+struct nv04_context {
+ struct pipe_context pipe;
+
+ struct nouveau_winsys *nvws;
+ struct nv04_screen *screen;
+ unsigned pctx_id;
+
+ struct draw_context *draw;
+
+ int chipset;
+ struct nouveau_notifier *sync;
+
+ uint32_t dirty;
+
+ struct nv04_blend_state *blend;
+ struct nv04_sampler_state *sampler[PIPE_MAX_SAMPLERS];
+ struct nv04_fragtex_state fragtex;
+ struct nv04_rasterizer_state *rast;
+ struct nv04_depth_stencil_alpha_state *dsa;
+
+ struct nv04_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
+ unsigned dirty_samplers;
+ unsigned fp_samplers;
+ unsigned vp_samplers;
+
+ uint32_t rt_enable;
+ struct pipe_framebuffer_state *framebuffer;
+ struct pipe_surface *rt;
+ struct pipe_surface *zeta;
+
+ struct {
+ struct pipe_buffer *buffer;
+ uint32_t format;
+ } tex[16];
+
+ unsigned vb_enable;
+ struct {
+ struct pipe_buffer *buffer;
+ unsigned delta;
+ } vb[16];
+
+ float *constbuf[PIPE_SHADER_TYPES][32][4];
+ unsigned constbuf_nr[PIPE_SHADER_TYPES];
+
+ struct vertex_info vertex_info;
+ struct {
+
+ struct nouveau_resource *exec_heap;
+ struct nouveau_resource *data_heap;
+
+ struct nv04_vertex_program *active;
+
+ struct nv04_vertex_program *current;
+ struct pipe_buffer *constant_buf;
+ } vertprog;
+
+ struct {
+ struct nv04_fragment_program *active;
+
+ struct nv04_fragment_program *current;
+ struct pipe_buffer *constant_buf;
+ } fragprog;
+
+ struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+ struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+
+ struct pipe_viewport_state viewport;
+};
+
+static INLINE struct nv04_context *
+nv04_context(struct pipe_context *pipe)
+{
+ return (struct nv04_context *)pipe;
+}
+
+extern void nv04_init_state_functions(struct nv04_context *nv04);
+extern void nv04_init_surface_functions(struct nv04_context *nv04);
+extern void nv04_screen_init_miptree_functions(struct pipe_screen *screen);
+
+/* nv04_clear.c */
+extern void nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+ unsigned clearValue);
+
+/* nv04_draw.c */
+extern struct draw_stage *nv04_draw_render_stage(struct nv04_context *nv04);
+
+/* nv04_fragprog.c */
+extern void nv04_fragprog_bind(struct nv04_context *,
+ struct nv04_fragment_program *);
+extern void nv04_fragprog_destroy(struct nv04_context *,
+ struct nv04_fragment_program *);
+
+/* nv04_fragtex.c */
+extern void nv04_fragtex_bind(struct nv04_context *);
+
+/* nv04_prim_vbuf.c */
+struct draw_stage *nv04_draw_vbuf_stage( struct nv04_context *nv04 );
+
+/* nv04_state.c and friends */
+extern void nv04_emit_hw_state(struct nv04_context *nv04);
+extern void nv04_state_tex_update(struct nv04_context *nv04);
+
+/* nv04_vbo.c */
+extern boolean nv04_draw_arrays(struct pipe_context *, unsigned mode,
+ unsigned start, unsigned count);
+extern boolean nv04_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count);
+
+
+#endif
diff --git a/src/gallium/drivers/nv04/nv04_fragprog.c b/src/gallium/drivers/nv04/nv04_fragprog.c
new file mode 100644
index 0000000000..8a2af41fe0
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_fragprog.c
@@ -0,0 +1,21 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+
+#include "nv04_context.h"
+
+void
+nv04_fragprog_bind(struct nv04_context *nv04, struct nv04_fragment_program *fp)
+{
+}
+
+void
+nv04_fragprog_destroy(struct nv04_context *nv04,
+ struct nv04_fragment_program *fp)
+{
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_fragtex.c b/src/gallium/drivers/nv04/nv04_fragtex.c
new file mode 100644
index 0000000000..21f990fd53
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_fragtex.c
@@ -0,0 +1,73 @@
+#include "nv04_context.h"
+#include "nouveau/nouveau_util.h"
+
+#define _(m,tf) \
+{ \
+ PIPE_FORMAT_##m, \
+ NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_##tf, \
+}
+
+struct nv04_texture_format {
+ uint pipe;
+ int format;
+};
+
+static struct nv04_texture_format
+nv04_texture_formats[] = {
+ _(A8R8G8B8_UNORM, A8R8G8B8),
+ _(X8R8G8B8_UNORM, X8R8G8B8),
+ _(A1R5G5B5_UNORM, A1R5G5B5),
+ _(A4R4G4B4_UNORM, A4R4G4B4),
+ _(L8_UNORM, Y8 ),
+ _(A8_UNORM, Y8 ),
+};
+
+static uint32_t
+nv04_fragtex_format(uint pipe_format)
+{
+ struct nv04_texture_format *tf = nv04_texture_formats;
+ int i;
+
+ for (i=0; i< sizeof(nv04_texture_formats)/sizeof(nv04_texture_formats[0]); i++) {
+ if (tf->pipe == pipe_format)
+ return tf->format;
+ tf++;
+ }
+
+ NOUVEAU_ERR("unknown texture format %s\n", pf_name(pipe_format));
+ return 0;
+}
+
+
+static void
+nv04_fragtex_build(struct nv04_context *nv04, int unit)
+{
+ struct nv04_miptree *nv04mt = nv04->tex_miptree[unit];
+ struct pipe_texture *pt = &nv04mt->base;
+
+ switch (pt->target) {
+ case PIPE_TEXTURE_2D:
+ break;
+ default:
+ NOUVEAU_ERR("Unknown target %d\n", pt->target);
+ return;
+ }
+
+ nv04->fragtex.format = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CORNER
+ | NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CORNER
+ | nv04_fragtex_format(pt->format)
+ | ( (pt->last_level + 1) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS_SHIFT )
+ | ( log2i(pt->width[0]) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U_SHIFT )
+ | ( log2i(pt->height[0]) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V_SHIFT )
+ | NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE
+ | NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_EDGE
+ ;
+}
+
+
+void
+nv04_fragtex_bind(struct nv04_context *nv04)
+{
+ nv04_fragtex_build(nv04, 0);
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_miptree.c b/src/gallium/drivers/nv04/nv04_miptree.c
new file mode 100644
index 0000000000..93f752faec
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_miptree.c
@@ -0,0 +1,153 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "nv04_context.h"
+#include "nv04_screen.h"
+
+static void
+nv04_miptree_layout(struct nv04_miptree *nv04mt)
+{
+ struct pipe_texture *pt = &nv04mt->base;
+ uint width = pt->width[0], height = pt->height[0];
+ uint offset = 0;
+ int nr_faces, l;
+
+ nr_faces = 1;
+
+ for (l = 0; l <= pt->last_level; l++) {
+ pt->width[l] = width;
+ pt->height[l] = height;
+
+ pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+ pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+
+ nv04mt->level[l].pitch = pt->width[0];
+ nv04mt->level[l].pitch = (nv04mt->level[l].pitch + 63) & ~63;
+
+ width = MAX2(1, width >> 1);
+ height = MAX2(1, height >> 1);
+ }
+
+ for (l = 0; l <= pt->last_level; l++) {
+
+ nv04mt->level[l].image_offset =
+ CALLOC(nr_faces, sizeof(unsigned));
+ offset += nv04mt->level[l].pitch * pt->height[l];
+ }
+
+ nv04mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv04_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
+{
+ struct nv04_miptree *mt;
+
+ mt = MALLOC(sizeof(struct nv04_miptree));
+ if (!mt)
+ return NULL;
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = pscreen;
+
+ //mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+
+ nv04_miptree_layout(mt);
+
+ mt->buffer = pscreen->buffer_create(pscreen, 256, PIPE_BUFFER_USAGE_PIXEL |
+ NOUVEAU_BUFFER_USAGE_TEXTURE,
+ mt->total_size);
+ if (!mt->buffer) {
+ printf("failed %d byte alloc\n",mt->total_size);
+ FREE(mt);
+ return NULL;
+ }
+
+ return &mt->base;
+}
+
+static struct pipe_texture *
+nv04_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt,
+ const unsigned *stride, struct pipe_buffer *pb)
+{
+ struct nv04_miptree *mt;
+
+ /* Only supports 2D, non-mipmapped textures for the moment */
+ if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 ||
+ pt->depth[0] != 1)
+ return NULL;
+
+ mt = CALLOC_STRUCT(nv04_miptree);
+ if (!mt)
+ return NULL;
+
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = pscreen;
+ mt->level[0].pitch = stride[0];
+ mt->level[0].image_offset = CALLOC(1, sizeof(unsigned));
+
+ pipe_buffer_reference(&mt->buffer, pb);
+ return &mt->base;
+}
+
+static void
+nv04_miptree_destroy(struct pipe_texture *pt)
+{
+ struct nv04_miptree *mt = (struct nv04_miptree *)pt;
+ int l;
+
+ pipe_buffer_reference(&mt->buffer, NULL);
+ for (l = 0; l <= pt->last_level; l++) {
+ if (mt->level[l].image_offset)
+ FREE(mt->level[l].image_offset);
+ }
+
+ FREE(mt);
+}
+
+static struct pipe_surface *
+nv04_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned flags)
+{
+ struct nv04_miptree *nv04mt = (struct nv04_miptree *)pt;
+ struct nv04_surface *ns;
+
+ ns = CALLOC_STRUCT(nv04_surface);
+ if (!ns)
+ return NULL;
+ pipe_texture_reference(&ns->base.texture, pt);
+ ns->base.format = pt->format;
+ ns->base.width = pt->width[level];
+ ns->base.height = pt->height[level];
+ ns->base.usage = flags;
+ pipe_reference_init(&ns->base.reference, 1);
+ ns->base.face = face;
+ ns->base.level = level;
+ ns->base.zslice = zslice;
+ ns->pitch = nv04mt->level[level].pitch;
+
+ ns->base.offset = nv04mt->level[level].image_offset;
+
+ return &ns->base;
+}
+
+static void
+nv04_miptree_surface_del(struct pipe_surface *ps)
+{
+ pipe_texture_reference(&ps->texture, NULL);
+ FREE(ps);
+}
+
+void
+nv04_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+ pscreen->texture_create = nv04_miptree_create;
+ pscreen->texture_blanket = nv04_miptree_blanket;
+ pscreen->texture_destroy = nv04_miptree_destroy;
+ pscreen->get_tex_surface = nv04_miptree_surface_new;
+ pscreen->tex_surface_destroy = nv04_miptree_surface_del;
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_prim_vbuf.c b/src/gallium/drivers/nv04/nv04_prim_vbuf.c
new file mode 100644
index 0000000000..f6458232ae
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_prim_vbuf.c
@@ -0,0 +1,321 @@
+
+#include "util/u_debug.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_compiler.h"
+
+#include "draw/draw_vbuf.h"
+
+#include "nv04_context.h"
+#include "nv04_state.h"
+
+#define VERTEX_SIZE 40
+#define VERTEX_BUFFER_SIZE (4096*VERTEX_SIZE) // 4096 vertices of 40 bytes each
+
+/**
+ * Primitive renderer for nv04.
+ */
+struct nv04_vbuf_render {
+ struct vbuf_render base;
+
+ struct nv04_context *nv04;
+
+ /** Vertex buffer */
+ unsigned char* buffer;
+
+ /** Vertex size in bytes */
+ unsigned vertex_size;
+
+ /** Current primitive */
+ unsigned prim;
+};
+
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct nv04_vbuf_render *
+nv04_vbuf_render( struct vbuf_render *render )
+{
+ assert(render);
+ return (struct nv04_vbuf_render *)render;
+}
+
+
+static const struct vertex_info *
+nv04_vbuf_render_get_vertex_info( struct vbuf_render *render )
+{
+ struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+ struct nv04_context *nv04 = nv04_render->nv04;
+ return &nv04->vertex_info;
+}
+
+
+static boolean
+nv04_vbuf_render_allocate_vertices( struct vbuf_render *render,
+ ushort vertex_size,
+ ushort nr_vertices )
+{
+ struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+
+ nv04_render->buffer = (unsigned char*) MALLOC(VERTEX_BUFFER_SIZE);
+ assert(!nv04_render->buffer);
+
+ return nv04_render->buffer ? TRUE : FALSE;
+}
+
+static void *
+nv04_vbuf_render_map_vertices( struct vbuf_render *render )
+{
+ struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+ return nv04_render->buffer;
+}
+
+static void
+nv04_vbuf_render_unmap_vertices( struct vbuf_render *render,
+ ushort min_index,
+ ushort max_index )
+{
+}
+
+static boolean
+nv04_vbuf_render_set_primitive( struct vbuf_render *render,
+ unsigned prim )
+{
+ struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+
+ if (prim <= PIPE_PRIM_LINE_STRIP)
+ return FALSE;
+
+ nv04_render->prim = prim;
+ return TRUE;
+}
+
+static INLINE void nv04_2triangles(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5)
+{
+ BEGIN_RING(fahrenheit,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49);
+ OUT_RINGp(buffer + VERTEX_SIZE * v0,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v1,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v2,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v3,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v4,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v5,8);
+ OUT_RING(0xFEDCBA);
+}
+
+static INLINE void nv04_1triangle(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2)
+{
+ BEGIN_RING(fahrenheit,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25);
+ OUT_RINGp(buffer + VERTEX_SIZE * v0,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v1,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v2,8);
+ OUT_RING(0xFED);
+}
+
+static INLINE void nv04_1quad(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2, ushort v3)
+{
+ BEGIN_RING(fahrenheit,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33);
+ OUT_RINGp(buffer + VERTEX_SIZE * v0,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v1,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v2,8);
+ OUT_RINGp(buffer + VERTEX_SIZE * v3,8);
+ OUT_RING(0xFECEDC);
+}
+
+static void nv04_vbuf_render_triangles_elts(struct nv04_vbuf_render * render, const ushort * indices, uint nr_indices)
+{
+ unsigned char* buffer = render->buffer;
+ struct nv04_context* nv04 = render->nv04;
+ int i;
+
+ for( i=0; i< nr_indices-5; i+=6)
+ nv04_2triangles(nv04,
+ buffer,
+ indices[i+0],
+ indices[i+1],
+ indices[i+2],
+ indices[i+3],
+ indices[i+4],
+ indices[i+5]
+ );
+ if (i != nr_indices)
+ {
+ nv04_1triangle(nv04,
+ buffer,
+ indices[i+0],
+ indices[i+1],
+ indices[i+2]
+ );
+ i+=3;
+ }
+ if (i != nr_indices)
+ NOUVEAU_ERR("Houston, we have lost some vertices\n");
+}
+
+static void nv04_vbuf_render_tri_strip_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices)
+{
+ const uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
+ unsigned char* buffer = render->buffer;
+ struct nv04_context* nv04 = render->nv04;
+ int i,j;
+
+ for(i = 0; i<nr_indices; i+=14)
+ {
+ int numvert = MIN2(16, nr_indices - i);
+ int numtri = numvert - 2;
+ if (numvert<3)
+ break;
+
+ BEGIN_RING( fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), numvert*8 );
+ for(j = 0; j<numvert; j++)
+ OUT_RINGp( buffer + VERTEX_SIZE * indices [i+j], 8 );
+
+ BEGIN_RING_NI( fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri+1)/2 );
+ for(j = 0; j<numtri/2; j++ )
+ OUT_RING(striptbl[j]);
+ if (numtri%2)
+ OUT_RING(striptbl[numtri/2]&0xFFF);
+ }
+}
+
+static void nv04_vbuf_render_tri_fan_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices)
+{
+ const uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
+ unsigned char* buffer = render->buffer;
+ struct nv04_context* nv04 = render->nv04;
+ int i,j;
+
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), 8);
+ OUT_RINGp(buffer + VERTEX_SIZE * indices[0], 8);
+
+ for(i = 1; i<nr_indices; i+=14)
+ {
+ int numvert=MIN2(15, nr_indices - i);
+ int numtri=numvert-2;
+ if (numvert < 3)
+ break;
+
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1), numvert*8);
+
+ for(j=0;j<numvert;j++)
+ OUT_RINGp( buffer + VERTEX_SIZE * indices[ i+j ], 8 );
+
+ BEGIN_RING_NI(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri+1)/2);
+ for(j = 0; j<numtri/2; j++)
+ OUT_RING(fantbl[j]);
+ if (numtri%2)
+ OUT_RING(fantbl[numtri/2]&0xFFF);
+ }
+}
+
+static void nv04_vbuf_render_quads_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices)
+{
+ unsigned char* buffer = render->buffer;
+ struct nv04_context* nv04 = render->nv04;
+ int i;
+
+ for(i = 0; i < nr_indices; i += 4)
+ nv04_1quad(nv04,
+ buffer,
+ indices[i+0],
+ indices[i+1],
+ indices[i+2],
+ indices[i+3]
+ );
+}
+
+
+static void
+nv04_vbuf_render_draw( struct vbuf_render *render,
+ const ushort *indices,
+ uint nr_indices)
+{
+ struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+
+ // emit the indices
+ switch( nv04_render->prim )
+ {
+ case PIPE_PRIM_TRIANGLES:
+ nv04_vbuf_render_triangles_elts(nv04_render, indices, nr_indices);
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ nv04_vbuf_render_tri_strip_elts(nv04_render, indices, nr_indices);
+ break;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ case PIPE_PRIM_POLYGON:
+ nv04_vbuf_render_tri_fan_elts(nv04_render, indices, nr_indices);
+ break;
+ case PIPE_PRIM_QUADS:
+ nv04_vbuf_render_quads_elts(nv04_render, indices, nr_indices);
+ break;
+ default:
+ NOUVEAU_ERR("You have to implement primitive %d, young padawan\n", nv04_render->prim);
+ break;
+ }
+}
+
+
+static void
+nv04_vbuf_render_release_vertices( struct vbuf_render *render )
+{
+ struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+
+ free(nv04_render->buffer);
+ nv04_render->buffer = NULL;
+}
+
+
+static void
+nv04_vbuf_render_destroy( struct vbuf_render *render )
+{
+ struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+ FREE(nv04_render);
+}
+
+
+/**
+ * Create a new primitive render.
+ */
+static struct vbuf_render *
+nv04_vbuf_render_create( struct nv04_context *nv04 )
+{
+ struct nv04_vbuf_render *nv04_render = CALLOC_STRUCT(nv04_vbuf_render);
+
+ nv04_render->nv04 = nv04;
+
+ nv04_render->base.max_vertex_buffer_bytes = VERTEX_BUFFER_SIZE;
+ nv04_render->base.max_indices = 65536;
+ nv04_render->base.get_vertex_info = nv04_vbuf_render_get_vertex_info;
+ nv04_render->base.allocate_vertices = nv04_vbuf_render_allocate_vertices;
+ nv04_render->base.map_vertices = nv04_vbuf_render_map_vertices;
+ nv04_render->base.unmap_vertices = nv04_vbuf_render_unmap_vertices;
+ nv04_render->base.set_primitive = nv04_vbuf_render_set_primitive;
+ nv04_render->base.draw = nv04_vbuf_render_draw;
+ nv04_render->base.release_vertices = nv04_vbuf_render_release_vertices;
+ nv04_render->base.destroy = nv04_vbuf_render_destroy;
+
+ return &nv04_render->base;
+}
+
+
+/**
+ * Create a new primitive vbuf/render stage.
+ */
+struct draw_stage *nv04_draw_vbuf_stage( struct nv04_context *nv04 )
+{
+ struct vbuf_render *render;
+ struct draw_stage *stage;
+
+ render = nv04_vbuf_render_create(nv04);
+ if(!render)
+ return NULL;
+
+ stage = draw_vbuf_stage( nv04->draw, render );
+ if(!stage) {
+ render->destroy(render);
+ return NULL;
+ }
+
+ return stage;
+}
diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c
new file mode 100644
index 0000000000..ff2febb668
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_screen.c
@@ -0,0 +1,212 @@
+#include "pipe/p_screen.h"
+#include "pipe/p_inlines.h"
+
+#include "nv04_context.h"
+#include "nv04_screen.h"
+
+static int
+nv04_screen_get_param(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return 1;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 0;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 0;
+ case PIPE_CAP_GLSL:
+ return 0;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 0;
+ case PIPE_CAP_POINT_SPRITE:
+ return 0;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 1;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 0;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 0;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 10;
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 0;
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 0;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ return 0;
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ return 0;
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ return 0;
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 0;
+ case NOUVEAU_CAP_HW_VTXBUF:
+ case NOUVEAU_CAP_HW_IDXBUF:
+ return 0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0;
+ }
+}
+
+static float
+nv04_screen_get_paramf(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 0.0;
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 0.0;
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 0.0;
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 0.0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0.0;
+ }
+}
+
+static boolean
+nv04_screen_is_format_supported(struct pipe_screen *screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else
+ if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) {
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_A8_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+nv04_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct nv04_screen *screen = nv04_screen(pscreen);
+
+ nouveau_notifier_free(&screen->sync);
+ nouveau_grobj_free(&screen->fahrenheit);
+ nv04_surface_2d_takedown(&screen->eng2d);
+
+ FREE(pscreen);
+}
+
+static struct pipe_buffer *
+nv04_surface_buffer(struct pipe_surface *surf)
+{
+ struct nv04_miptree *mt = (struct nv04_miptree *)surf->texture;
+
+ return mt->buffer;
+}
+
+struct pipe_screen *
+nv04_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
+{
+ struct nv04_screen *screen = CALLOC_STRUCT(nv04_screen);
+ struct nouveau_channel *chan;
+ struct pipe_screen *pscreen;
+ unsigned fahrenheit_class = 0, sub3d_class = 0;
+ int ret;
+
+ if (!screen)
+ return NULL;
+ pscreen = &screen->base.base;
+
+ ret = nouveau_screen_init(&screen->base, dev);
+ if (ret) {
+ nv04_screen_destroy(pscreen);
+ return NULL;
+ }
+ chan = screen->base.channel;
+
+ pscreen->winsys = ws;
+ pscreen->destroy = nv04_screen_destroy;
+ pscreen->get_param = nv04_screen_get_param;
+ pscreen->get_paramf = nv04_screen_get_paramf;
+ pscreen->is_format_supported = nv04_screen_is_format_supported;
+
+ nv04_screen_init_miptree_functions(pscreen);
+ nv04_screen_init_transfer_functions(pscreen);
+
+ if (dev->chipset >= 0x20) {
+ fahrenheit_class = 0;
+ sub3d_class = 0;
+ } else if (dev->chipset >= 0x10) {
+ fahrenheit_class = NV10_DX5_TEXTURED_TRIANGLE;
+ sub3d_class = NV10_CONTEXT_SURFACES_3D;
+ } else {
+ fahrenheit_class=NV04_DX5_TEXTURED_TRIANGLE;
+ sub3d_class = NV04_CONTEXT_SURFACES_3D;
+ }
+
+ if (!fahrenheit_class) {
+ NOUVEAU_ERR("Unknown nv04 chipset: nv%02x\n", dev->chipset);
+ return NULL;
+ }
+
+ /* 3D object */
+ ret = nouveau_grobj_alloc(chan, 0xbeef0001, fahrenheit_class,
+ &screen->fahrenheit);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+ return NULL;
+ }
+ BIND_RING(chan, screen->fahrenheit, 7);
+
+ /* 3D surface object */
+ ret = nouveau_grobj_alloc(chan, 0xbeef0002, sub3d_class,
+ &screen->context_surfaces_3d);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 3D surface object: %d\n", ret);
+ return NULL;
+ }
+ BIND_RING(chan, screen->context_surfaces_3d, 6);
+
+ /* 2D engine setup */
+ screen->eng2d = nv04_surface_2d_init(&screen->base);
+ screen->eng2d->buf = nv04_surface_buffer;
+
+ /* Notifier for sync purposes */
+ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
+ if (ret) {
+ NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+ nv04_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ return pscreen;
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_screen.h b/src/gallium/drivers/nv04/nv04_screen.h
new file mode 100644
index 0000000000..11466b9442
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_screen.h
@@ -0,0 +1,30 @@
+#ifndef __NV04_SCREEN_H__
+#define __NV04_SCREEN_H__
+
+#include "nouveau/nouveau_screen.h"
+#include "nv04_surface_2d.h"
+
+struct nv04_screen {
+ struct nouveau_screen base;
+
+ struct nouveau_winsys *nvws;
+ unsigned chipset;
+
+ /* HW graphics objects */
+ struct nv04_surface_2d *eng2d;
+ struct nouveau_grobj *fahrenheit;
+ struct nouveau_grobj *context_surfaces_3d;
+ struct nouveau_notifier *sync;
+
+};
+
+static INLINE struct nv04_screen *
+nv04_screen(struct pipe_screen *screen)
+{
+ return (struct nv04_screen *)screen;
+}
+
+void
+nv04_screen_init_transfer_functions(struct pipe_screen *pscreen);
+
+#endif
diff --git a/src/gallium/drivers/nv04/nv04_state.c b/src/gallium/drivers/nv04/nv04_state.c
new file mode 100644
index 0000000000..d356ebd8b3
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_state.c
@@ -0,0 +1,459 @@
+#include "draw/draw_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_inlines.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "nv04_context.h"
+#include "nv04_state.h"
+
+static void *
+nv04_blend_state_create(struct pipe_context *pipe,
+ const struct pipe_blend_state *cso)
+{
+ struct nv04_blend_state *cb;
+
+ cb = MALLOC(sizeof(struct nv04_blend_state));
+
+ cb->b_enable = cso->blend_enable ? 1 : 0;
+ cb->b_src = ((nvgl_blend_func(cso->alpha_src_factor)<<16) |
+ (nvgl_blend_func(cso->rgb_src_factor)));
+ cb->b_dst = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) |
+ (nvgl_blend_func(cso->rgb_dst_factor)));
+
+
+ return (void *)cb;
+}
+
+static void
+nv04_blend_state_bind(struct pipe_context *pipe, void *blend)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ nv04->blend = (struct nv04_blend_state*)blend;
+
+ nv04->dirty |= NV04_NEW_BLEND;
+}
+
+static void
+nv04_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ free(hwcso);
+}
+
+
+static INLINE unsigned
+wrap_mode(unsigned wrap) {
+ unsigned ret;
+
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MIRRORED_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_BORDER;
+ break;
+ case PIPE_TEX_WRAP_CLAMP:
+ ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ default:
+ NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+ ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP;
+ }
+ return ret >> NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT;
+}
+
+static void *
+nv04_sampler_state_create(struct pipe_context *pipe,
+ const struct pipe_sampler_state *cso)
+{
+
+ struct nv04_sampler_state *ss;
+ uint32_t filter = 0;
+
+ ss = MALLOC(sizeof(struct nv04_sampler_state));
+
+ ss->format = ((wrap_mode(cso->wrap_s) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT) |
+ (wrap_mode(cso->wrap_t) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_SHIFT));
+
+ if (cso->max_anisotropy > 1.0) {
+ filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE | NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE;
+ }
+
+ switch (cso->mag_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST;
+ break;
+ }
+
+ switch (cso->min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR;
+ break;
+ }
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST;
+ break;
+ }
+ break;
+ }
+
+ ss->filter = filter;
+
+ return (void *)ss;
+}
+
+static void
+nv04_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv04->sampler[unit] = sampler[unit];
+ nv04->dirty_samplers |= (1 << unit);
+ }
+}
+
+static void
+nv04_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ free(hwcso);
+}
+
+static void
+nv04_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+ struct pipe_texture **miptree)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv04->tex_miptree[unit] = (struct nv04_miptree *)miptree[unit];
+ nv04->dirty_samplers |= (1 << unit);
+ }
+}
+
+static void *
+nv04_rasterizer_state_create(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct nv04_rasterizer_state *rs;
+
+ /*XXX: ignored:
+ * scissor
+ * points/lines (no hw support, emulated with tris in gallium)
+ */
+ rs = MALLOC(sizeof(struct nv04_rasterizer_state));
+
+ rs->blend = cso->flatshade ? NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT : NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
+
+ return (void *)rs;
+}
+
+static void
+nv04_rasterizer_state_bind(struct pipe_context *pipe, void *rast)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ nv04->rast = (struct nv04_rasterizer_state*)rast;
+
+ draw_set_rasterizer_state(nv04->draw, (nv04->rast ? nv04->rast->templ : NULL));
+
+ nv04->dirty |= NV04_NEW_RAST | NV04_NEW_BLEND;
+}
+
+static void
+nv04_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ free(hwcso);
+}
+
+static INLINE uint32_t nv04_compare_func(uint32_t f)
+{
+ switch ( f ) {
+ case PIPE_FUNC_NEVER: return 1;
+ case PIPE_FUNC_LESS: return 2;
+ case PIPE_FUNC_EQUAL: return 3;
+ case PIPE_FUNC_LEQUAL: return 4;
+ case PIPE_FUNC_GREATER: return 5;
+ case PIPE_FUNC_NOTEQUAL: return 6;
+ case PIPE_FUNC_GEQUAL: return 7;
+ case PIPE_FUNC_ALWAYS: return 8;
+ }
+ NOUVEAU_MSG("Unable to find the function\n");
+ return 0;
+}
+
+static void *
+nv04_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct nv04_depth_stencil_alpha_state *hw;
+
+ hw = MALLOC(sizeof(struct nv04_depth_stencil_alpha_state));
+
+ hw->control = float_to_ubyte(cso->alpha.ref_value);
+ hw->control |= ( nv04_compare_func(cso->alpha.func) << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_SHIFT );
+ hw->control |= cso->alpha.enabled ? NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_TEST_ENABLE : 0;
+ hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ORIGIN;
+ hw->control |= cso->depth.enabled ? (1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE_SHIFT) : 0;
+ hw->control |= ( nv04_compare_func(cso->depth.func)<< NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_SHIFT );
+ hw->control |= 1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_SHIFT; // no culling, handled by the draw module
+ hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE;
+ hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_PERSPECTIVE_ENABLE;
+ hw->control |= cso->depth.writemask ? (1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_WRITE_ENABLE_SHIFT) : 0;
+ hw->control |= 1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_SHIFT; // integer zbuffer format
+
+ return (void *)hw;
+}
+
+static void
+nv04_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ nv04->dsa = hwcso;
+ nv04->dirty |= NV04_NEW_CONTROL;
+}
+
+static void
+nv04_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ free(hwcso);
+}
+
+static void *
+nv04_vp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ return draw_create_vertex_shader(nv04->draw, templ);
+}
+
+static void
+nv04_vp_state_bind(struct pipe_context *pipe, void *shader)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ draw_bind_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader);
+
+ nv04->dirty |= NV04_NEW_VERTPROG;
+}
+
+static void
+nv04_vp_state_delete(struct pipe_context *pipe, void *shader)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ draw_delete_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader);
+}
+
+static void *
+nv04_fp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv04_fragment_program *fp;
+
+ fp = CALLOC(1, sizeof(struct nv04_fragment_program));
+ fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+
+ return (void *)fp;
+}
+
+static void
+nv04_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+ struct nv04_fragment_program *fp = hwcso;
+
+ nv04->fragprog.current = fp;
+ nv04->dirty |= NV04_NEW_FRAGPROG;
+}
+
+static void
+nv04_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+ struct nv04_fragment_program *fp = hwcso;
+
+ nv04_fragprog_destroy(nv04, fp);
+ free((void*)fp->pipe.tokens);
+ free(fp);
+}
+
+static void
+nv04_set_blend_color(struct pipe_context *pipe,
+ const struct pipe_blend_color *bcol)
+{
+}
+
+static void
+nv04_set_clip_state(struct pipe_context *pipe,
+ const struct pipe_clip_state *clip)
+{
+}
+
+static void
+nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+ const struct pipe_constant_buffer *buf )
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+ struct pipe_screen *pscreen = pipe->screen;
+
+ assert(shader < PIPE_SHADER_TYPES);
+ assert(index == 0);
+
+ if (buf) {
+ void *mapped;
+ if (buf->buffer && buf->buffer->size &&
+ (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+ {
+ memcpy(nv04->constbuf[shader], mapped, buf->buffer->size);
+ nv04->constbuf_nr[shader] =
+ buf->buffer->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pscreen, buf->buffer);
+ }
+ }
+}
+
+static void
+nv04_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ nv04->framebuffer = (struct pipe_framebuffer_state*)fb;
+
+ nv04->dirty |= NV04_NEW_FRAMEBUFFER;
+}
+static void
+nv04_set_polygon_stipple(struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple)
+{
+ NOUVEAU_ERR("line stipple hahaha\n");
+}
+
+static void
+nv04_set_scissor_state(struct pipe_context *pipe,
+ const struct pipe_scissor_state *s)
+{
+/* struct nv04_context *nv04 = nv04_context(pipe);
+
+ // XXX
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_SCISSOR_HORIZ, 2);
+ OUT_RING (((s->maxx - s->minx) << 16) | s->minx);
+ OUT_RING (((s->maxy - s->miny) << 16) | s->miny);*/
+}
+
+static void
+nv04_set_viewport_state(struct pipe_context *pipe,
+ const struct pipe_viewport_state *viewport)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ nv04->viewport = *viewport;
+
+ draw_set_viewport_state(nv04->draw, &nv04->viewport);
+}
+
+static void
+nv04_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_buffer *buffers)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ memcpy(nv04->vtxbuf, buffers, count * sizeof(buffers[0]));
+ nv04->dirty |= NV04_NEW_VTXARRAYS;
+
+ draw_set_vertex_buffers(nv04->draw, count, buffers);
+}
+
+static void
+nv04_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_element *elements)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+
+ memcpy(nv04->vtxelt, elements, sizeof(*elements) * count);
+ nv04->dirty |= NV04_NEW_VTXARRAYS;
+
+ draw_set_vertex_elements(nv04->draw, count, elements);
+}
+
+void
+nv04_init_state_functions(struct nv04_context *nv04)
+{
+ nv04->pipe.create_blend_state = nv04_blend_state_create;
+ nv04->pipe.bind_blend_state = nv04_blend_state_bind;
+ nv04->pipe.delete_blend_state = nv04_blend_state_delete;
+
+ nv04->pipe.create_sampler_state = nv04_sampler_state_create;
+ nv04->pipe.bind_sampler_states = nv04_sampler_state_bind;
+ nv04->pipe.delete_sampler_state = nv04_sampler_state_delete;
+ nv04->pipe.set_sampler_textures = nv04_set_sampler_texture;
+
+ nv04->pipe.create_rasterizer_state = nv04_rasterizer_state_create;
+ nv04->pipe.bind_rasterizer_state = nv04_rasterizer_state_bind;
+ nv04->pipe.delete_rasterizer_state = nv04_rasterizer_state_delete;
+
+ nv04->pipe.create_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_create;
+ nv04->pipe.bind_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_bind;
+ nv04->pipe.delete_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_delete;
+
+ nv04->pipe.create_vs_state = nv04_vp_state_create;
+ nv04->pipe.bind_vs_state = nv04_vp_state_bind;
+ nv04->pipe.delete_vs_state = nv04_vp_state_delete;
+
+ nv04->pipe.create_fs_state = nv04_fp_state_create;
+ nv04->pipe.bind_fs_state = nv04_fp_state_bind;
+ nv04->pipe.delete_fs_state = nv04_fp_state_delete;
+
+ nv04->pipe.set_blend_color = nv04_set_blend_color;
+ nv04->pipe.set_clip_state = nv04_set_clip_state;
+ nv04->pipe.set_constant_buffer = nv04_set_constant_buffer;
+ nv04->pipe.set_framebuffer_state = nv04_set_framebuffer_state;
+ nv04->pipe.set_polygon_stipple = nv04_set_polygon_stipple;
+ nv04->pipe.set_scissor_state = nv04_set_scissor_state;
+ nv04->pipe.set_viewport_state = nv04_set_viewport_state;
+
+ nv04->pipe.set_vertex_buffers = nv04_set_vertex_buffers;
+ nv04->pipe.set_vertex_elements = nv04_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_state.h b/src/gallium/drivers/nv04/nv04_state.h
new file mode 100644
index 0000000000..399f750dbe
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_state.h
@@ -0,0 +1,71 @@
+#ifndef __NV04_STATE_H__
+#define __NV04_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+
+struct nv04_blend_state {
+ uint32_t b_enable;
+ uint32_t b_src;
+ uint32_t b_dst;
+};
+
+struct nv04_fragtex_state {
+ uint32_t format;
+};
+
+struct nv04_sampler_state {
+ uint32_t filter;
+ uint32_t format;
+};
+
+struct nv04_depth_stencil_alpha_state {
+ uint32_t control;
+};
+
+struct nv04_rasterizer_state {
+ uint32_t blend;
+
+ const struct pipe_rasterizer_state *templ;
+};
+
+struct nv04_miptree {
+ struct pipe_texture base;
+
+ struct pipe_buffer *buffer;
+ uint total_size;
+
+ struct {
+ uint pitch;
+ uint *image_offset;
+ } level[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+struct nv04_fragment_program_data {
+ unsigned offset;
+ unsigned index;
+};
+
+struct nv04_fragment_program {
+ struct pipe_shader_state pipe;
+ struct tgsi_shader_info info;
+
+ boolean translated;
+ boolean on_hw;
+ unsigned samplers;
+
+ uint32_t *insn;
+ int insn_len;
+
+ struct nv04_fragment_program_data *consts;
+ unsigned nr_consts;
+
+ struct pipe_buffer *buffer;
+
+ uint32_t fp_control;
+ uint32_t fp_reg_control;
+};
+
+
+
+#endif
diff --git a/src/gallium/drivers/nv04/nv04_state_emit.c b/src/gallium/drivers/nv04/nv04_state_emit.c
new file mode 100644
index 0000000000..eb2c1c57c6
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_state_emit.c
@@ -0,0 +1,226 @@
+#include "nv04_context.h"
+#include "nv04_state.h"
+
+static void nv04_vertex_layout(struct pipe_context* pipe)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+ struct nv04_fragment_program *fp = nv04->fragprog.current;
+ uint32_t src = 0;
+ int i;
+ struct vertex_info vinfo;
+
+ memset(&vinfo, 0, sizeof(vinfo));
+
+ for (i = 0; i < fp->info.num_inputs; i++) {
+ int isn = fp->info.input_semantic_name[i];
+ int isi = fp->info.input_semantic_index[i];
+ switch (isn) {
+ case TGSI_SEMANTIC_POSITION:
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
+ break;
+ default:
+ case TGSI_SEMANTIC_GENERIC:
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
+ break;
+ case TGSI_SEMANTIC_FOG:
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
+ break;
+ }
+ }
+
+ printf("%d vertex input\n",fp->info.num_inputs);
+ draw_compute_vertex_size(&vinfo);
+}
+
+static uint32_t nv04_blend_func(uint32_t f)
+{
+ switch ( f ) {
+ case PIPE_BLENDFACTOR_ZERO: return 0x1;
+ case PIPE_BLENDFACTOR_ONE: return 0x2;
+ case PIPE_BLENDFACTOR_SRC_COLOR: return 0x3;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR: return 0x4;
+ case PIPE_BLENDFACTOR_SRC_ALPHA: return 0x5;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return 0x6;
+ case PIPE_BLENDFACTOR_DST_ALPHA: return 0x7;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA: return 0x8;
+ case PIPE_BLENDFACTOR_DST_COLOR: return 0x9;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR: return 0xA;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return 0xB;
+ }
+ NOUVEAU_MSG("Unable to find the blend function 0x%x\n",f);
+ return 0;
+}
+
+static void nv04_emit_control(struct nv04_context* nv04)
+{
+ uint32_t control = nv04->dsa->control;
+
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1);
+ OUT_RING(control);
+}
+
+static void nv04_emit_blend(struct nv04_context* nv04)
+{
+ uint32_t blend;
+
+ blend=0x4; // texture MODULATE_ALPHA
+ blend|=0x20; // alpha is MSB
+ blend|=(2<<6); // flat shading
+ blend|=(1<<8); // persp correct
+ blend|=(0<<16); // no fog
+ blend|=(nv04->blend->b_enable<<20);
+ blend|=(nv04_blend_func(nv04->blend->b_src)<<24);
+ blend|=(nv04_blend_func(nv04->blend->b_dst)<<28);
+
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_BLEND, 1);
+ OUT_RING(blend);
+}
+
+static void nv04_emit_sampler(struct nv04_context *nv04, int unit)
+{
+ struct nv04_miptree *nv04mt = nv04->tex_miptree[unit];
+ struct pipe_texture *pt = &nv04mt->base;
+
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_OFFSET, 3);
+ OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ OUT_RELOCd(nv04mt->buffer, (nv04->fragtex.format | nv04->sampler[unit]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
+ OUT_RING(nv04->sampler[unit]->filter);
+}
+
+static void nv04_state_emit_framebuffer(struct nv04_context* nv04)
+{
+ struct pipe_framebuffer_state* fb = nv04->framebuffer;
+ struct nv04_surface *rt, *zeta;
+ uint32_t rt_format, w, h;
+ int colour_format = 0, zeta_format = 0;
+ struct nv04_miptree *nv04mt = 0;
+
+ w = fb->cbufs[0]->width;
+ h = fb->cbufs[0]->height;
+ colour_format = fb->cbufs[0]->format;
+ rt = (struct nv04_surface *)fb->cbufs[0];
+
+ if (fb->zsbuf) {
+ if (colour_format) {
+ assert(w == fb->zsbuf->width);
+ assert(h == fb->zsbuf->height);
+ } else {
+ w = fb->zsbuf->width;
+ h = fb->zsbuf->height;
+ }
+
+ zeta_format = fb->zsbuf->format;
+ zeta = (struct nv04_surface *)fb->zsbuf;
+ }
+
+ switch (colour_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case 0:
+ rt_format = 0x108;
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ rt_format = 0x103;
+ break;
+ default:
+ assert(0);
+ }
+
+ BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_FORMAT, 1);
+ OUT_RING(rt_format);
+
+ nv04mt = (struct nv04_miptree *)rt->base.texture;
+ /* FIXME pitches have to be aligned ! */
+ BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2);
+ OUT_RING(rt->pitch|(zeta->pitch<<16));
+ OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ if (fb->zsbuf) {
+ nv04mt = (struct nv04_miptree *)zeta->base.texture;
+ BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1);
+ OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ }
+}
+
+void
+nv04_emit_hw_state(struct nv04_context *nv04)
+{
+ int i;
+
+ if (nv04->dirty & NV04_NEW_VERTPROG) {
+ //nv04_vertprog_bind(nv04, nv04->vertprog.current);
+ nv04->dirty &= ~NV04_NEW_VERTPROG;
+ }
+
+ if (nv04->dirty & NV04_NEW_FRAGPROG) {
+ nv04_fragprog_bind(nv04, nv04->fragprog.current);
+ nv04->dirty &= ~NV04_NEW_FRAGPROG;
+ nv04->dirty_samplers |= (1<<10);
+ nv04->dirty_samplers = 0;
+ }
+
+ if (nv04->dirty & NV04_NEW_CONTROL) {
+ nv04->dirty &= ~NV04_NEW_CONTROL;
+
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1);
+ OUT_RING(nv04->dsa->control);
+ }
+
+ if (nv04->dirty & NV04_NEW_BLEND) {
+ nv04->dirty &= ~NV04_NEW_BLEND;
+
+ nv04_emit_blend(nv04);
+ }
+
+ if (nv04->dirty & NV04_NEW_VTXARRAYS) {
+ nv04->dirty &= ~NV04_NEW_VTXARRAYS;
+ nv04_vertex_layout(nv04);
+ }
+
+ if (nv04->dirty & NV04_NEW_SAMPLER) {
+ nv04->dirty &= ~NV04_NEW_SAMPLER;
+
+ nv04_emit_sampler(nv04, 0);
+ }
+
+ if (nv04->dirty & NV04_NEW_VIEWPORT) {
+ nv04->dirty &= ~NV04_NEW_VIEWPORT;
+// nv04_state_emit_viewport(nv04);
+ }
+
+ if (nv04->dirty & NV04_NEW_FRAMEBUFFER) {
+ nv04->dirty &= ~NV04_NEW_FRAMEBUFFER;
+ nv04_state_emit_framebuffer(nv04);
+ }
+
+ /* Emit relocs for every referenced buffer.
+ * This is to ensure the bufmgr has an accurate idea of how
+ * the buffer is used. This isn't very efficient, but we don't
+ * seem to take a significant performance hit. Will be improved
+ * at some point. Vertex arrays are emitted by nv04_vbo.c
+ */
+
+ /* Render target */
+ unsigned rt_pitch = ((struct nv04_surface *)nv04->rt)->pitch;
+ unsigned zeta_pitch = ((struct nv04_surface *)nv04->zeta)->pitch;
+
+ BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2);
+ OUT_RING(rt_pitch|(zeta_pitch<<16));
+ OUT_RELOCl(nv04->rt, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ if (nv04->zeta) {
+ BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1);
+ OUT_RELOCl(nv04->zeta, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ }
+
+ /* Texture images */
+ for (i = 0; i < 1; i++) {
+ if (!(nv04->fp_samplers & (1 << i)))
+ continue;
+ struct nv04_miptree *nv04mt = nv04->tex_miptree[i];
+ BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_OFFSET, 2);
+ OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ OUT_RELOCd(nv04mt->buffer, (nv04->fragtex.format | nv04->sampler[i]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
+ }
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_surface.c b/src/gallium/drivers/nv04/nv04_surface.c
new file mode 100644
index 0000000000..0387ff4e78
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_surface.c
@@ -0,0 +1,63 @@
+
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "nv04_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+
+static void
+nv04_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+ struct nv04_surface_2d *eng2d = nv04->screen->eng2d;
+
+ eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
+}
+
+static void
+nv04_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+ unsigned destx, unsigned desty, unsigned width,
+ unsigned height, unsigned value)
+{
+ struct nv04_context *nv04 = nv04_context(pipe);
+ struct nv04_surface_2d *eng2d = nv04->screen->eng2d;
+
+ eng2d->fill(eng2d, dest, destx, desty, width, height, value);
+}
+
+void
+nv04_init_surface_functions(struct nv04_context *nv04)
+{
+ nv04->pipe.surface_copy = nv04_surface_copy;
+ nv04->pipe.surface_fill = nv04_surface_fill;
+}
diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.c b/src/gallium/drivers/nv04/nv04_surface_2d.c
new file mode 100644
index 0000000000..f88e138c79
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_surface_2d.c
@@ -0,0 +1,558 @@
+#include "pipe/p_context.h"
+#include "pipe/p_format.h"
+#include "util/u_memory.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_util.h"
+#include "nouveau/nouveau_screen.h"
+#include "nv04_surface_2d.h"
+
+static INLINE int
+nv04_surface_format(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8_UNORM:
+ return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
+ case PIPE_FORMAT_R16_SNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
+ default:
+ return -1;
+ }
+}
+
+static INLINE int
+nv04_rect_format(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8_UNORM:
+ return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+ default:
+ return -1;
+ }
+}
+
+static INLINE int
+nv04_scaled_image_format(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5;
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_R16_SNORM:
+ return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
+ default:
+ return -1;
+ }
+}
+
+static INLINE unsigned
+nv04_swizzle_bits(unsigned x, unsigned y)
+{
+ unsigned u = (x & 0x001) << 0 |
+ (x & 0x002) << 1 |
+ (x & 0x004) << 2 |
+ (x & 0x008) << 3 |
+ (x & 0x010) << 4 |
+ (x & 0x020) << 5 |
+ (x & 0x040) << 6 |
+ (x & 0x080) << 7 |
+ (x & 0x100) << 8 |
+ (x & 0x200) << 9 |
+ (x & 0x400) << 10 |
+ (x & 0x800) << 11;
+
+ unsigned v = (y & 0x001) << 1 |
+ (y & 0x002) << 2 |
+ (y & 0x004) << 3 |
+ (y & 0x008) << 4 |
+ (y & 0x010) << 5 |
+ (y & 0x020) << 6 |
+ (y & 0x040) << 7 |
+ (y & 0x080) << 8 |
+ (y & 0x100) << 9 |
+ (y & 0x200) << 10 |
+ (y & 0x400) << 11 |
+ (y & 0x800) << 12;
+ return v | u;
+}
+
+static int
+nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx,
+ struct pipe_surface *dst, int dx, int dy,
+ struct pipe_surface *src, int sx, int sy,
+ int w, int h)
+{
+ struct nouveau_channel *chan = ctx->swzsurf->channel;
+ struct nouveau_grobj *swzsurf = ctx->swzsurf;
+ struct nouveau_grobj *sifm = ctx->sifm;
+ struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src));
+ struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst));
+ const unsigned src_pitch = ((struct nv04_surface *)src)->pitch;
+ const unsigned max_w = 1024;
+ const unsigned max_h = 1024;
+ const unsigned sub_w = w > max_w ? max_w : w;
+ const unsigned sub_h = h > max_h ? max_h : h;
+ unsigned cx;
+ unsigned cy;
+
+#if 0
+ /* That's the way she likes it */
+ assert(src_pitch == ((struct nv04_surface *)dst)->pitch);
+#endif
+
+ BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
+ OUT_RELOCo(chan, dst_bo,
+ NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1);
+ OUT_RING (chan, nv04_surface_format(dst->format) |
+ log2i(w) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT |
+ log2i(h) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT);
+
+ BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
+ OUT_RELOCo(chan, src_bo,
+ NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
+ OUT_RING (chan, swzsurf->handle);
+
+ for (cy = 0; cy < h; cy += sub_h) {
+ for (cx = 0; cx < w; cx += sub_w) {
+ BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1);
+ OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(cx+dx, cy+dy) *
+ dst->texture->block.size, NOUVEAU_BO_GART |
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
+ OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
+ OUT_RING (chan, nv04_scaled_image_format(src->format));
+ OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, sub_h << 16 | sub_w);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, sub_h << 16 | sub_w);
+ OUT_RING (chan, 1 << 20);
+ OUT_RING (chan, 1 << 20);
+
+ BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
+ OUT_RING (chan, sub_h << 16 | sub_w);
+ OUT_RING (chan, src_pitch |
+ NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
+ NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
+ OUT_RELOCl(chan, src_bo, src->offset + (cy+sy) * src_pitch +
+ (cx+sx) * src->texture->block.size, NOUVEAU_BO_GART |
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RING (chan, 0);
+ }
+ }
+
+ return 0;
+}
+
+static int
+nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx,
+ struct pipe_surface *dst, int dx, int dy,
+ struct pipe_surface *src, int sx, int sy, int w, int h)
+{
+ struct nouveau_channel *chan = ctx->m2mf->channel;
+ struct nouveau_grobj *m2mf = ctx->m2mf;
+ struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src));
+ struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst));
+ unsigned src_pitch = ((struct nv04_surface *)src)->pitch;
+ unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch;
+ unsigned dst_offset = dst->offset + dy * dst_pitch +
+ dx * dst->texture->block.size;
+ unsigned src_offset = src->offset + sy * src_pitch +
+ sx * src->texture->block.size;
+
+ WAIT_RING (chan, 3 + ((h / 2047) + 1) * 9);
+ BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
+ OUT_RELOCo(chan, src_bo,
+ NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RELOCo(chan, dst_bo,
+ NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ while (h) {
+ int count = (h > 2047) ? 2047 : h;
+
+ BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+ OUT_RELOCl(chan, src_bo, src_offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ OUT_RELOCl(chan, dst_bo, dst_offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
+ OUT_RING (chan, src_pitch);
+ OUT_RING (chan, dst_pitch);
+ OUT_RING (chan, w * src->texture->block.size);
+ OUT_RING (chan, count);
+ OUT_RING (chan, 0x0101);
+ OUT_RING (chan, 0);
+
+ h -= count;
+ src_offset += src_pitch * count;
+ dst_offset += dst_pitch * count;
+ }
+
+ return 0;
+}
+
+static int
+nv04_surface_copy_m2mf_swizzle(struct nv04_surface_2d *ctx,
+ struct pipe_surface *dst, int dx, int dy,
+ struct pipe_surface *src, int sx, int sy)
+{
+ struct nouveau_channel *chan = ctx->m2mf->channel;
+ struct nouveau_grobj *m2mf = ctx->m2mf;
+ struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src));
+ struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst));
+ unsigned src_pitch = ((struct nv04_surface *)src)->pitch;
+ unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch;
+ unsigned dst_offset = dst->offset + nv04_swizzle_bits(dx, dy) *
+ dst->texture->block.size;
+ unsigned src_offset = src->offset + sy * src_pitch +
+ sx * src->texture->block.size;
+
+ BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
+ OUT_RELOCo(chan, src_bo,
+ NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RELOCo(chan, dst_bo,
+ NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+ OUT_RELOCl(chan, src_bo, src_offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ OUT_RELOCl(chan, dst_bo, dst_offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
+ OUT_RING (chan, src_pitch);
+ OUT_RING (chan, dst_pitch);
+ OUT_RING (chan, 1 * src->texture->block.size);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, 0x0101);
+ OUT_RING (chan, 0);
+
+ return 0;
+}
+
+static int
+nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
+ int dx, int dy, struct pipe_surface *src, int sx, int sy,
+ int w, int h)
+{
+ struct nouveau_channel *chan = ctx->surf2d->channel;
+ struct nouveau_grobj *surf2d = ctx->surf2d;
+ struct nouveau_grobj *blit = ctx->blit;
+ struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src));
+ struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst));
+ unsigned src_pitch = ((struct nv04_surface *)src)->pitch;
+ unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch;
+ int format;
+
+ format = nv04_surface_format(dst->format);
+ if (format < 0)
+ return 1;
+
+ WAIT_RING (chan, 12);
+ BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+ OUT_RELOCo(chan, src_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
+ OUT_RING (chan, format);
+ OUT_RING (chan, (dst_pitch << 16) | src_pitch);
+ OUT_RELOCl(chan, src_bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ BEGIN_RING(chan, blit, 0x0300, 3);
+ OUT_RING (chan, (sy << 16) | sx);
+ OUT_RING (chan, (dy << 16) | dx);
+ OUT_RING (chan, ( h << 16) | w);
+
+ return 0;
+}
+
+static void
+nv04_surface_copy(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
+ int dx, int dy, struct pipe_surface *src, int sx, int sy,
+ int w, int h)
+{
+ unsigned src_pitch = ((struct nv04_surface *)src)->pitch;
+ unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch;
+ int src_linear = src->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR;
+ int dst_linear = dst->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR;
+
+ assert(src->format == dst->format);
+
+ /* Setup transfer to swizzle the texture to vram if needed */
+ if (src_linear && !dst_linear) {
+ int x,y;
+
+ if ((w>1) && (h>1)) {
+ int potWidth = 1<<log2i(w);
+ int potHeight = 1<<log2i(h);
+ int remainWidth = w-potWidth;
+ int remainHeight = h-potHeight;
+ int squareDim = (potWidth>potHeight ? potHeight : potWidth);
+
+ /* top left is always POT, but we can only swizzle squares */
+ for (y=0; y<potHeight; y+=squareDim) {
+ for (x=0; x<potWidth; x+= squareDim) {
+ nv04_surface_copy_swizzle(ctx, dst, dx+x, dy+y,
+ src, sx+x, sy+y,
+ squareDim, squareDim);
+ }
+ }
+
+ /* top right */
+ if (remainWidth>0) {
+ nv04_surface_copy(ctx, dst, dx+potWidth, dy,
+ src, sx+potWidth, sy,
+ remainWidth, potHeight);
+ }
+
+ /* bottom left */
+ if (remainHeight>0) {
+ nv04_surface_copy(ctx, dst, dx, dy+potHeight,
+ src, sx, sy+potHeight,
+ potWidth, remainHeight);
+ }
+
+ /* bottom right */
+ if ((remainWidth>0) && (remainHeight>0)) {
+ nv04_surface_copy(ctx, dst, dx+potWidth, dy+potHeight,
+ src, sx+potWidth, sy+potHeight,
+ remainWidth, remainHeight);
+ }
+ } else if (w==1) {
+ /* We have a column to copy to a swizzled texture */
+ for (y=0; y<h; y++) {
+ nv04_surface_copy_m2mf_swizzle(ctx, dst, dx, dy+y,
+ src, sx, sy+y);
+ }
+ } else if (h==1) {
+ /* We have a row to copy to a swizzled texture */
+ for (x=0; x<w; x++) {
+ nv04_surface_copy_m2mf_swizzle(ctx, dst, dx+x, dy,
+ src, sx+x, sy);
+ }
+ }
+
+ return;
+ }
+
+ /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
+ * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
+ */
+ if ((src->offset & 63) || (dst->offset & 63) ||
+ (src_pitch & 63) || (dst_pitch & 63)) {
+ nv04_surface_copy_m2mf(ctx, dst, dx, dy, src, sx, sy, w, h);
+ return;
+ }
+
+ nv04_surface_copy_blit(ctx, dst, dx, dy, src, sx, sy, w, h);
+}
+
+static void
+nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
+ int dx, int dy, int w, int h, unsigned value)
+{
+ struct nouveau_channel *chan = ctx->surf2d->channel;
+ struct nouveau_grobj *surf2d = ctx->surf2d;
+ struct nouveau_grobj *rect = ctx->rect;
+ struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst));
+ unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch;
+ int cs2d_format, gdirect_format;
+
+ cs2d_format = nv04_surface_format(dst->format);
+ assert(cs2d_format >= 0);
+
+ gdirect_format = nv04_rect_format(dst->format);
+ assert(gdirect_format >= 0);
+
+ WAIT_RING (chan, 16);
+ BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+ OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
+ OUT_RING (chan, cs2d_format);
+ OUT_RING (chan, (dst_pitch << 16) | dst_pitch);
+ OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
+ OUT_RING (chan, gdirect_format);
+ BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
+ OUT_RING (chan, value);
+ BEGIN_RING(chan, rect,
+ NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
+ OUT_RING (chan, (dx << 16) | dy);
+ OUT_RING (chan, ( w << 16) | h);
+}
+
+void
+nv04_surface_2d_takedown(struct nv04_surface_2d **pctx)
+{
+ struct nv04_surface_2d *ctx;
+
+ if (!pctx || !*pctx)
+ return;
+ ctx = *pctx;
+ *pctx = NULL;
+
+ nouveau_notifier_free(&ctx->ntfy);
+ nouveau_grobj_free(&ctx->m2mf);
+ nouveau_grobj_free(&ctx->surf2d);
+ nouveau_grobj_free(&ctx->swzsurf);
+ nouveau_grobj_free(&ctx->rect);
+ nouveau_grobj_free(&ctx->blit);
+ nouveau_grobj_free(&ctx->sifm);
+
+ FREE(ctx);
+}
+
+struct nv04_surface_2d *
+nv04_surface_2d_init(struct nouveau_screen *screen)
+{
+ struct nv04_surface_2d *ctx = CALLOC_STRUCT(nv04_surface_2d);
+ struct nouveau_channel *chan = screen->channel;
+ unsigned handle = 0x88000000, class;
+ int ret;
+
+ if (!ctx)
+ return NULL;
+
+ ret = nouveau_notifier_alloc(chan, handle++, 1, &ctx->ntfy);
+ if (ret) {
+ nv04_surface_2d_takedown(&ctx);
+ return NULL;
+ }
+
+ ret = nouveau_grobj_alloc(chan, handle++, 0x0039, &ctx->m2mf);
+ if (ret) {
+ nv04_surface_2d_takedown(&ctx);
+ return NULL;
+ }
+
+ BEGIN_RING(chan, ctx->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
+ OUT_RING (chan, ctx->ntfy->handle);
+
+ if (chan->device->chipset < 0x10)
+ class = NV04_CONTEXT_SURFACES_2D;
+ else
+ class = NV10_CONTEXT_SURFACES_2D;
+
+ ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->surf2d);
+ if (ret) {
+ nv04_surface_2d_takedown(&ctx);
+ return NULL;
+ }
+
+ BEGIN_RING(chan, ctx->surf2d,
+ NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+ OUT_RING (chan, chan->vram->handle);
+ OUT_RING (chan, chan->vram->handle);
+
+ if (chan->device->chipset < 0x10)
+ class = NV04_IMAGE_BLIT;
+ else
+ class = NV12_IMAGE_BLIT;
+
+ ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->blit);
+ if (ret) {
+ nv04_surface_2d_takedown(&ctx);
+ return NULL;
+ }
+
+ BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1);
+ OUT_RING (chan, ctx->ntfy->handle);
+ BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_SURFACE, 1);
+ OUT_RING (chan, ctx->surf2d->handle);
+ BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_OPERATION, 1);
+ OUT_RING (chan, NV04_IMAGE_BLIT_OPERATION_SRCCOPY);
+
+ ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT,
+ &ctx->rect);
+ if (ret) {
+ nv04_surface_2d_takedown(&ctx);
+ return NULL;
+ }
+
+ BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
+ OUT_RING (chan, ctx->ntfy->handle);
+ BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
+ OUT_RING (chan, ctx->surf2d->handle);
+ BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
+ OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
+ BEGIN_RING(chan, ctx->rect,
+ NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
+ OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
+
+ switch (chan->device->chipset & 0xf0) {
+ case 0x00:
+ case 0x10:
+ class = NV04_SWIZZLED_SURFACE;
+ break;
+ case 0x20:
+ class = NV20_SWIZZLED_SURFACE;
+ break;
+ case 0x30:
+ class = NV30_SWIZZLED_SURFACE;
+ break;
+ case 0x40:
+ case 0x60:
+ class = NV40_SWIZZLED_SURFACE;
+ break;
+ default:
+ /* Famous last words: this really can't happen.. */
+ assert(0);
+ break;
+ }
+
+ ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->swzsurf);
+ if (ret) {
+ nv04_surface_2d_takedown(&ctx);
+ return NULL;
+ }
+
+ switch (chan->device->chipset & 0xf0) {
+ case 0x10:
+ case 0x20:
+ class = NV10_SCALED_IMAGE_FROM_MEMORY;
+ break;
+ case 0x30:
+ class = NV30_SCALED_IMAGE_FROM_MEMORY;
+ break;
+ case 0x40:
+ case 0x60:
+ class = NV40_SCALED_IMAGE_FROM_MEMORY;
+ break;
+ default:
+ class = NV04_SCALED_IMAGE_FROM_MEMORY;
+ break;
+ }
+
+ ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->sifm);
+ if (ret) {
+ nv04_surface_2d_takedown(&ctx);
+ return NULL;
+ }
+
+ ctx->copy = nv04_surface_copy;
+ ctx->fill = nv04_surface_fill;
+ return ctx;
+}
diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.h b/src/gallium/drivers/nv04/nv04_surface_2d.h
new file mode 100644
index 0000000000..02b3f56ba8
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_surface_2d.h
@@ -0,0 +1,33 @@
+#ifndef __NV04_SURFACE_2D_H__
+#define __NV04_SURFACE_2D_H__
+
+struct nv04_surface {
+ struct pipe_surface base;
+ unsigned pitch;
+};
+
+struct nv04_surface_2d {
+ struct nouveau_notifier *ntfy;
+ struct nouveau_grobj *surf2d;
+ struct nouveau_grobj *swzsurf;
+ struct nouveau_grobj *m2mf;
+ struct nouveau_grobj *rect;
+ struct nouveau_grobj *blit;
+ struct nouveau_grobj *sifm;
+
+ struct pipe_buffer *(*buf)(struct pipe_surface *);
+
+ void (*copy)(struct nv04_surface_2d *, struct pipe_surface *dst,
+ int dx, int dy, struct pipe_surface *src, int sx, int sy,
+ int w, int h);
+ void (*fill)(struct nv04_surface_2d *, struct pipe_surface *dst,
+ int dx, int dy, int w, int h, unsigned value);
+};
+
+struct nv04_surface_2d *
+nv04_surface_2d_init(struct nouveau_screen *screen);
+
+void
+nv04_surface_2d_takedown(struct nv04_surface_2d **);
+
+#endif
diff --git a/src/gallium/drivers/nv04/nv04_transfer.c b/src/gallium/drivers/nv04/nv04_transfer.c
new file mode 100644
index 0000000000..854b855d64
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_transfer.c
@@ -0,0 +1,195 @@
+#include <pipe/p_state.h>
+#include <pipe/p_defines.h>
+#include <pipe/p_inlines.h>
+#include <util/u_memory.h>
+#include <nouveau/nouveau_winsys.h>
+#include "nv04_context.h"
+#include "nv04_screen.h"
+#include "nv04_state.h"
+
+struct nv04_transfer {
+ struct pipe_transfer base;
+ struct pipe_surface *surface;
+ bool direct;
+};
+
+static unsigned nv04_usage_tx_to_buf(unsigned tx_usage)
+{
+ switch (tx_usage) {
+ case PIPE_TRANSFER_READ:
+ return PIPE_BUFFER_USAGE_CPU_READ;
+ case PIPE_TRANSFER_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_WRITE;
+ case PIPE_TRANSFER_READ_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static void
+nv04_compatible_transfer_tex(struct pipe_texture *pt, unsigned level,
+ struct pipe_texture *template)
+{
+ memset(template, 0, sizeof(struct pipe_texture));
+ template->target = pt->target;
+ template->format = pt->format;
+ template->width[0] = pt->width[level];
+ template->height[0] = pt->height[level];
+ template->depth[0] = 1;
+ template->block = pt->block;
+ template->nblocksx[0] = pt->nblocksx[level];
+ template->nblocksy[0] = pt->nblocksx[level];
+ template->last_level = 0;
+ template->nr_samples = pt->nr_samples;
+
+ template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC |
+ NOUVEAU_TEXTURE_USAGE_LINEAR;
+}
+
+static struct pipe_transfer *
+nv04_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct nv04_miptree *mt = (struct nv04_miptree *)pt;
+ struct nv04_transfer *tx;
+ struct pipe_texture tx_tex_template, *tx_tex;
+
+ tx = CALLOC_STRUCT(nv04_transfer);
+ if (!tx)
+ return NULL;
+
+ pipe_texture_reference(&tx->base.texture, pt);
+ tx->base.format = pt->format;
+ tx->base.x = x;
+ tx->base.y = y;
+ tx->base.width = w;
+ tx->base.height = h;
+ tx->base.block = pt->block;
+ tx->base.nblocksx = pt->nblocksx[level];
+ tx->base.nblocksy = pt->nblocksy[level];
+ tx->base.stride = mt->level[level].pitch;
+ tx->base.usage = usage;
+ tx->base.face = face;
+ tx->base.level = level;
+ tx->base.zslice = zslice;
+
+ /* Direct access to texture */
+ if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC ||
+ debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) &&
+ pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)
+ {
+ tx->direct = true;
+ tx->surface = pscreen->get_tex_surface(pscreen, pt,
+ 0, 0, 0,
+ nv04_usage_tx_to_buf(usage));
+ return &tx->base;
+ }
+
+ tx->direct = false;
+
+ nv04_compatible_transfer_tex(pt, level, &tx_tex_template);
+
+ tx_tex = pscreen->texture_create(pscreen, &tx_tex_template);
+ if (!tx_tex)
+ {
+ FREE(tx);
+ return NULL;
+ }
+
+ tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
+ face, level, zslice,
+ nv04_usage_tx_to_buf(usage));
+
+ pipe_texture_reference(&tx_tex, NULL);
+
+ if (!tx->surface)
+ {
+ pipe_surface_reference(&tx->surface, NULL);
+ FREE(tx);
+ return NULL;
+ }
+
+ if (usage != PIPE_TRANSFER_WRITE) {
+ struct nv04_screen *nvscreen = nv04_screen(pscreen);
+ struct pipe_surface *src;
+
+ src = pscreen->get_tex_surface(pscreen, pt,
+ face, level, zslice,
+ PIPE_BUFFER_USAGE_GPU_READ);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ /* TODO: Check if SIFM can un-swizzle */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ tx->surface, 0, 0,
+ src, 0, 0,
+ src->width, src->height);
+
+ pipe_surface_reference(&src, NULL);
+ }
+
+ return &tx->base;
+}
+
+static void
+nv04_transfer_del(struct pipe_transfer *ptx)
+{
+ struct nv04_transfer *tx = (struct nv04_transfer *)ptx;
+
+ if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) {
+ struct pipe_screen *pscreen = ptx->texture->screen;
+ struct nv04_screen *nvscreen = nv04_screen(pscreen);
+ struct pipe_surface *dst;
+
+ dst = pscreen->get_tex_surface(pscreen, ptx->texture,
+ ptx->face, ptx->level, ptx->zslice,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ dst, 0, 0,
+ tx->surface, 0, 0,
+ dst->width, dst->height);
+
+ pipe_surface_reference(&dst, NULL);
+ }
+
+ pipe_surface_reference(&tx->surface, NULL);
+ pipe_texture_reference(&ptx->texture, NULL);
+ FREE(ptx);
+}
+
+static void *
+nv04_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv04_transfer *tx = (struct nv04_transfer *)ptx;
+ struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
+ struct nv04_miptree *mt = (struct nv04_miptree *)tx->surface->texture;
+ void *map = pipe_buffer_map(pscreen, mt->buffer,
+ nv04_usage_tx_to_buf(ptx->usage));
+
+ return map + ns->base.offset +
+ ptx->y * ns->pitch + ptx->x * ptx->block.size;
+}
+
+static void
+nv04_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv04_transfer *tx = (struct nv04_transfer *)ptx;
+ struct nv04_miptree *mt = (struct nv04_miptree *)tx->surface->texture;
+
+ pipe_buffer_unmap(pscreen, mt->buffer);
+}
+
+void
+nv04_screen_init_transfer_functions(struct pipe_screen *pscreen)
+{
+ pscreen->get_tex_transfer = nv04_transfer_new;
+ pscreen->tex_transfer_destroy = nv04_transfer_del;
+ pscreen->transfer_map = nv04_transfer_map;
+ pscreen->transfer_unmap = nv04_transfer_unmap;
+}
diff --git a/src/gallium/drivers/nv04/nv04_vbo.c b/src/gallium/drivers/nv04/nv04_vbo.c
new file mode 100644
index 0000000000..e3167814f2
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_vbo.c
@@ -0,0 +1,80 @@
+#include "draw/draw_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "nv04_context.h"
+#include "nv04_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+
+boolean nv04_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count)
+{
+ struct pipe_screen *pscreen = pipe->screen;
+ struct nv04_context *nv04 = nv04_context( pipe );
+ struct draw_context *draw = nv04->draw;
+ unsigned i;
+
+ nv04_emit_hw_state(nv04);
+
+ /*
+ * Map vertex buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (nv04->vtxbuf[i].buffer) {
+ void *buf
+ = pipe_buffer_map(pscreen,
+ nv04->vtxbuf[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_vertex_buffer(draw, i, buf);
+ }
+ }
+ /* Map index buffer, if present */
+ if (indexBuffer) {
+ void *mapped_indexes
+ = pipe_buffer_map(pscreen, indexBuffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes);
+ }
+ else {
+ /* no index/element buffer */
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+ draw_set_mapped_constant_buffer(draw,
+ nv04->constbuf[PIPE_SHADER_VERTEX],
+ nv04->constbuf_nr[PIPE_SHADER_VERTEX]);
+
+ /* draw! */
+ draw_arrays(nv04->draw, prim, start, count);
+
+ /*
+ * unmap vertex/index buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (nv04->vtxbuf[i].buffer) {
+ pipe_buffer_unmap(pscreen, nv04->vtxbuf[i].buffer);
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ }
+ }
+ if (indexBuffer) {
+ pipe_buffer_unmap(pscreen, indexBuffer);
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+ return TRUE;
+}
+
+boolean nv04_draw_arrays( struct pipe_context *pipe,
+ unsigned prim, unsigned start, unsigned count)
+{
+ printf("coucou in draw arrays\n");
+ return nv04_draw_elements(pipe, NULL, 0, prim, start, count);
+}
+
+
+
diff --git a/src/gallium/drivers/nv10/Makefile b/src/gallium/drivers/nv10/Makefile
new file mode 100644
index 0000000000..62677f5194
--- /dev/null
+++ b/src/gallium/drivers/nv10/Makefile
@@ -0,0 +1,20 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv10
+
+C_SOURCES = \
+ nv10_clear.c \
+ nv10_context.c \
+ nv10_fragprog.c \
+ nv10_fragtex.c \
+ nv10_miptree.c \
+ nv10_prim_vbuf.c \
+ nv10_screen.c \
+ nv10_state.c \
+ nv10_state_emit.c \
+ nv10_surface.c \
+ nv10_transfer.c \
+ nv10_vbo.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/nv10/nv10_clear.c b/src/gallium/drivers/nv10/nv10_clear.c
new file mode 100644
index 0000000000..a39a2b5f52
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_clear.c
@@ -0,0 +1,14 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "util/u_clear.h"
+
+#include "nv10_context.h"
+
+void
+nv10_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil)
+{
+ util_clear(pipe, nv10_context(pipe)->framebuffer, buffers, rgba, depth,
+ stencil);
+}
diff --git a/src/gallium/drivers/nv10/nv10_context.c b/src/gallium/drivers/nv10/nv10_context.c
new file mode 100644
index 0000000000..a127b134ec
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_context.c
@@ -0,0 +1,322 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "nv10_context.h"
+#include "nv10_screen.h"
+
+static void
+nv10_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ draw_flush(nv10->draw);
+
+ FIRE_RING(fence);
+}
+
+static void
+nv10_destroy(struct pipe_context *pipe)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ if (nv10->draw)
+ draw_destroy(nv10->draw);
+
+ FREE(nv10);
+}
+
+static void nv10_init_hwctx(struct nv10_context *nv10)
+{
+ struct nv10_screen *screen = nv10->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ int i;
+ float projectionmatrix[16];
+
+ BEGIN_RING(celsius, NV10TCL_DMA_NOTIFY, 1);
+ OUT_RING (screen->sync->handle);
+ BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY0, 2);
+ OUT_RING (chan->vram->handle);
+ OUT_RING (chan->gart->handle);
+ BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY2, 2);
+ OUT_RING (chan->vram->handle);
+ OUT_RING (chan->vram->handle);
+
+ BEGIN_RING(celsius, NV10TCL_NOP, 1);
+ OUT_RING (0);
+
+ BEGIN_RING(celsius, NV10TCL_RT_HORIZ, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+
+ BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
+ OUT_RING ((0x7ff<<16)|0x800);
+ BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
+ OUT_RING ((0x7ff<<16)|0x800);
+
+ for (i=1;i<8;i++) {
+ BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_VERT(i), 1);
+ OUT_RING (0);
+ }
+
+ BEGIN_RING(celsius, 0x290, 1);
+ OUT_RING ((0x10<<16)|1);
+ BEGIN_RING(celsius, 0x3f4, 1);
+ OUT_RING (0);
+
+ BEGIN_RING(celsius, NV10TCL_NOP, 1);
+ OUT_RING (0);
+
+ if (nv10->screen->celsius->grclass != NV10TCL) {
+ /* For nv11, nv17 */
+ BEGIN_RING(celsius, 0x120, 3);
+ OUT_RING (0);
+ OUT_RING (1);
+ OUT_RING (2);
+
+ BEGIN_RING(celsius, NV10TCL_NOP, 1);
+ OUT_RING (0);
+ }
+
+ BEGIN_RING(celsius, NV10TCL_NOP, 1);
+ OUT_RING (0);
+
+ /* Set state */
+ BEGIN_RING(celsius, NV10TCL_FOG_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_FUNC, 2);
+ OUT_RING (0x207);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_TX_ENABLE(0), 2);
+ OUT_RING (0);
+ OUT_RING (0);
+
+ BEGIN_RING(celsius, NV10TCL_RC_IN_ALPHA(0), 12);
+ OUT_RING (0x30141010);
+ OUT_RING (0);
+ OUT_RING (0x20040000);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0x00000c00);
+ OUT_RING (0);
+ OUT_RING (0x00000c00);
+ OUT_RING (0x18000000);
+ OUT_RING (0x300e0300);
+ OUT_RING (0x0c091c80);
+
+ BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_DITHER_ENABLE, 2);
+ OUT_RING (1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_VERTEX_WEIGHT_ENABLE, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_SRC, 4);
+ OUT_RING (1);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0x8006);
+ BEGIN_RING(celsius, NV10TCL_STENCIL_MASK, 8);
+ OUT_RING (0xff);
+ OUT_RING (0x207);
+ OUT_RING (0);
+ OUT_RING (0xff);
+ OUT_RING (0x1e00);
+ OUT_RING (0x1e00);
+ OUT_RING (0x1e00);
+ OUT_RING (0x1d01);
+ BEGIN_RING(celsius, NV10TCL_NORMALIZE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_FOG_ENABLE, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_LIGHT_MODEL, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_COLOR_CONTROL, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_ENABLED_LIGHTS, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_DEPTH_FUNC, 1);
+ OUT_RING (0x201);
+ BEGIN_RING(celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_DEPTH_TEST_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_POLYGON_OFFSET_FACTOR, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_POINT_SIZE, 1);
+ OUT_RING (8);
+ BEGIN_RING(celsius, NV10TCL_POINT_PARAMETERS_ENABLE, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_LINE_WIDTH, 1);
+ OUT_RING (8);
+ BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_POLYGON_MODE_FRONT, 2);
+ OUT_RING (0x1b02);
+ OUT_RING (0x1b02);
+ BEGIN_RING(celsius, NV10TCL_CULL_FACE, 2);
+ OUT_RING (0x405);
+ OUT_RING (0x901);
+ BEGIN_RING(celsius, NV10TCL_POLYGON_SMOOTH_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_CULL_FACE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_TX_GEN_S(0), 8);
+ for (i=0;i<8;i++) {
+ OUT_RING (0);
+ }
+ BEGIN_RING(celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3);
+ OUT_RING (0x3fc00000); /* -1.50 */
+ OUT_RING (0xbdb8aa0a); /* -0.09 */
+ OUT_RING (0); /* 0.00 */
+
+ BEGIN_RING(celsius, NV10TCL_NOP, 1);
+ OUT_RING (0);
+
+ BEGIN_RING(celsius, NV10TCL_FOG_MODE, 2);
+ OUT_RING (0x802);
+ OUT_RING (2);
+ /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when
+ * using texturing, except when using the texture matrix
+ */
+ BEGIN_RING(celsius, NV10TCL_VIEW_MATRIX_ENABLE, 1);
+ OUT_RING (6);
+ BEGIN_RING(celsius, NV10TCL_COLOR_MASK, 1);
+ OUT_RING (0x01010101);
+
+ /* Set vertex component */
+ BEGIN_RING(celsius, NV10TCL_VERTEX_COL_4F_R, 4);
+ OUT_RINGf (1.0);
+ OUT_RINGf (1.0);
+ OUT_RINGf (1.0);
+ OUT_RINGf (1.0);
+ BEGIN_RING(celsius, NV10TCL_VERTEX_COL2_3F_R, 3);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(celsius, NV10TCL_VERTEX_NOR_3F_X, 3);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RINGf (1.0);
+ BEGIN_RING(celsius, NV10TCL_VERTEX_TX0_4F_S, 4);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (1.0);
+ BEGIN_RING(celsius, NV10TCL_VERTEX_TX1_4F_S, 4);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (1.0);
+ BEGIN_RING(celsius, NV10TCL_VERTEX_FOG_1F, 1);
+ OUT_RINGf (0.0);
+ BEGIN_RING(celsius, NV10TCL_EDGEFLAG_ENABLE, 1);
+ OUT_RING (1);
+
+ memset(projectionmatrix, 0, sizeof(projectionmatrix));
+ BEGIN_RING(celsius, NV10TCL_PROJECTION_MATRIX(0), 16);
+ projectionmatrix[0*4+0] = 1.0;
+ projectionmatrix[1*4+1] = 1.0;
+ projectionmatrix[2*4+2] = 1.0;
+ projectionmatrix[3*4+3] = 1.0;
+ for (i=0;i<16;i++) {
+ OUT_RINGf (projectionmatrix[i]);
+ }
+
+ BEGIN_RING(celsius, NV10TCL_DEPTH_RANGE_NEAR, 2);
+ OUT_RING (0.0);
+ OUT_RINGf (16777216.0);
+
+ BEGIN_RING(celsius, NV10TCL_VIEWPORT_SCALE_X, 4);
+ OUT_RINGf (-2048.0);
+ OUT_RINGf (-2048.0);
+ OUT_RINGf (16777215.0 * 0.5);
+ OUT_RING (0);
+
+ FIRE_RING (NULL);
+}
+
+static void
+nv10_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+}
+
+static unsigned int
+nv10_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static unsigned int
+nv10_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+struct pipe_context *
+nv10_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+ struct nv10_screen *screen = nv10_screen(pscreen);
+ struct pipe_winsys *ws = pscreen->winsys;
+ struct nv10_context *nv10;
+ struct nouveau_winsys *nvws = screen->nvws;
+
+ nv10 = CALLOC(1, sizeof(struct nv10_context));
+ if (!nv10)
+ return NULL;
+ nv10->screen = screen;
+ nv10->pctx_id = pctx_id;
+
+ nv10->nvws = nvws;
+
+ nv10->pipe.winsys = ws;
+ nv10->pipe.screen = pscreen;
+ nv10->pipe.destroy = nv10_destroy;
+ nv10->pipe.set_edgeflags = nv10_set_edgeflags;
+ nv10->pipe.draw_arrays = nv10_draw_arrays;
+ nv10->pipe.draw_elements = nv10_draw_elements;
+ nv10->pipe.clear = nv10_clear;
+ nv10->pipe.flush = nv10_flush;
+
+ nv10->pipe.is_texture_referenced = nv10_is_texture_referenced;
+ nv10->pipe.is_buffer_referenced = nv10_is_buffer_referenced;
+
+ nv10_init_surface_functions(nv10);
+ nv10_init_state_functions(nv10);
+
+ nv10->draw = draw_create();
+ assert(nv10->draw);
+ draw_set_rasterize_stage(nv10->draw, nv10_draw_vbuf_stage(nv10));
+
+ nv10_init_hwctx(nv10);
+
+ return &nv10->pipe;
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_context.h b/src/gallium/drivers/nv10/nv10_context.h
new file mode 100644
index 0000000000..f1e003c953
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_context.h
@@ -0,0 +1,154 @@
+#ifndef __NV10_CONTEXT_H__
+#define __NV10_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx) \
+ struct nv10_screen *ctx = nv10->screen
+#include "nouveau/nouveau_push.h"
+
+#include "nv10_state.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+ fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+ fprintf(stderr, "nouveau: "fmt, ##args);
+
+#define NV10_NEW_VERTPROG (1 << 0)
+#define NV10_NEW_FRAGPROG (1 << 1)
+#define NV10_NEW_VTXARRAYS (1 << 2)
+#define NV10_NEW_BLEND (1 << 3)
+#define NV10_NEW_BLENDCOL (1 << 4)
+#define NV10_NEW_RAST (1 << 5)
+#define NV10_NEW_DSA (1 << 6)
+#define NV10_NEW_VIEWPORT (1 << 7)
+#define NV10_NEW_SCISSOR (1 << 8)
+#define NV10_NEW_FRAMEBUFFER (1 << 9)
+
+#include "nv10_screen.h"
+
+struct nv10_context {
+ struct pipe_context pipe;
+
+ struct nouveau_winsys *nvws;
+ struct nv10_screen *screen;
+ unsigned pctx_id;
+
+ struct draw_context *draw;
+
+ uint32_t dirty;
+
+ struct nv10_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
+ struct nv10_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
+ unsigned dirty_samplers;
+ unsigned fp_samplers;
+ unsigned vp_samplers;
+
+ uint32_t rt_enable;
+ struct pipe_buffer *rt[4];
+ struct pipe_buffer *zeta;
+ uint32_t lma_offset;
+
+ struct nv10_blend_state *blend;
+ struct pipe_blend_color *blend_color;
+ struct nv10_rasterizer_state *rast;
+ struct nv10_depth_stencil_alpha_state *dsa;
+ struct pipe_viewport_state *viewport;
+ struct pipe_scissor_state *scissor;
+ struct pipe_framebuffer_state *framebuffer;
+
+ //struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+ float *constbuf[PIPE_SHADER_TYPES][32][4];
+ unsigned constbuf_nr[PIPE_SHADER_TYPES];
+
+ struct vertex_info vertex_info;
+
+ struct {
+ struct pipe_buffer *buffer;
+ uint32_t format;
+ } tex[2];
+
+ unsigned vb_enable;
+ struct {
+ struct pipe_buffer *buffer;
+ unsigned delta;
+ } vb[16];
+
+/* struct {
+
+ struct nouveau_resource *exec_heap;
+ struct nouveau_resource *data_heap;
+
+ struct nv10_vertex_program *active;
+
+ struct nv10_vertex_program *current;
+ } vertprog;
+*/
+ struct {
+ struct nv10_fragment_program *active;
+
+ struct nv10_fragment_program *current;
+ struct pipe_buffer *constant_buf;
+ } fragprog;
+
+ struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+ struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+};
+
+static INLINE struct nv10_context *
+nv10_context(struct pipe_context *pipe)
+{
+ return (struct nv10_context *)pipe;
+}
+
+extern void nv10_init_state_functions(struct nv10_context *nv10);
+extern void nv10_init_surface_functions(struct nv10_context *nv10);
+
+extern void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+/* nv10_clear.c */
+extern void nv10_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil);
+
+
+/* nv10_draw.c */
+extern struct draw_stage *nv10_draw_render_stage(struct nv10_context *nv10);
+
+/* nv10_fragprog.c */
+extern void nv10_fragprog_bind(struct nv10_context *,
+ struct nv10_fragment_program *);
+extern void nv10_fragprog_destroy(struct nv10_context *,
+ struct nv10_fragment_program *);
+
+/* nv10_fragtex.c */
+extern void nv10_fragtex_bind(struct nv10_context *);
+
+/* nv10_prim_vbuf.c */
+struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 );
+extern void nv10_vtxbuf_bind(struct nv10_context* nv10);
+
+/* nv10_state.c and friends */
+extern void nv10_emit_hw_state(struct nv10_context *nv10);
+extern void nv10_state_tex_update(struct nv10_context *nv10);
+
+/* nv10_vbo.c */
+extern boolean nv10_draw_arrays(struct pipe_context *, unsigned mode,
+ unsigned start, unsigned count);
+extern boolean nv10_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count);
+
+
+#endif
diff --git a/src/gallium/drivers/nv10/nv10_fragprog.c b/src/gallium/drivers/nv10/nv10_fragprog.c
new file mode 100644
index 0000000000..698db5a16a
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_fragprog.c
@@ -0,0 +1,21 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+
+#include "nv10_context.h"
+
+void
+nv10_fragprog_bind(struct nv10_context *nv10, struct nv10_fragment_program *fp)
+{
+}
+
+void
+nv10_fragprog_destroy(struct nv10_context *nv10,
+ struct nv10_fragment_program *fp)
+{
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_fragtex.c b/src/gallium/drivers/nv10/nv10_fragtex.c
new file mode 100644
index 0000000000..27f2f87584
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_fragtex.c
@@ -0,0 +1,124 @@
+#include "nv10_context.h"
+#include "nouveau/nouveau_util.h"
+
+#define _(m,tf) \
+{ \
+ TRUE, \
+ PIPE_FORMAT_##m, \
+ NV10TCL_TX_FORMAT_FORMAT_##tf, \
+}
+
+struct nv10_texture_format {
+ boolean defined;
+ uint pipe;
+ int format;
+};
+
+static struct nv10_texture_format
+nv10_texture_formats[] = {
+ _(A8R8G8B8_UNORM, A8R8G8B8),
+ _(A1R5G5B5_UNORM, A1R5G5B5),
+ _(A4R4G4B4_UNORM, A4R4G4B4),
+ _(L8_UNORM , L8 ),
+ _(A8_UNORM , A8 ),
+ _(A8L8_UNORM , A8L8 ),
+// _(RGB_DXT1 , DXT1, ),
+// _(RGBA_DXT1 , DXT1, ),
+// _(RGBA_DXT3 , DXT3, ),
+// _(RGBA_DXT5 , DXT5, ),
+ {},
+};
+
+static struct nv10_texture_format *
+nv10_fragtex_format(uint pipe_format)
+{
+ struct nv10_texture_format *tf = nv10_texture_formats;
+
+ while (tf->defined) {
+ if (tf->pipe == pipe_format)
+ return tf;
+ tf++;
+ }
+
+ return NULL;
+}
+
+
+static void
+nv10_fragtex_build(struct nv10_context *nv10, int unit)
+{
+#if 0
+ struct nv10_sampler_state *ps = nv10->tex_sampler[unit];
+ struct nv10_miptree *nv10mt = nv10->tex_miptree[unit];
+ struct pipe_texture *pt = &nv10mt->base;
+ struct nv10_texture_format *tf;
+ uint32_t txf, txs, txp;
+
+ tf = nv10_fragtex_format(pt->format);
+ if (!tf || !tf->defined) {
+ NOUVEAU_ERR("Unsupported texture format: 0x%x\n", pt->format);
+ return;
+ }
+
+ txf = tf->format << 8;
+ txf |= (pt->last_level + 1) << 16;
+ txf |= log2i(pt->width[0]) << 20;
+ txf |= log2i(pt->height[0]) << 24;
+ txf |= log2i(pt->depth[0]) << 28;
+ txf |= 8;
+
+ switch (pt->target) {
+ case PIPE_TEXTURE_CUBE:
+ txf |= NV10TCL_TX_FORMAT_CUBE_MAP;
+ /* fall-through */
+ case PIPE_TEXTURE_2D:
+ txf |= (2<<4);
+ break;
+ case PIPE_TEXTURE_1D:
+ txf |= (1<<4);
+ break;
+ default:
+ NOUVEAU_ERR("Unknown target %d\n", pt->target);
+ return;
+ }
+
+ BEGIN_RING(celsius, NV10TCL_TX_OFFSET(unit), 8);
+ OUT_RELOCl(nv10mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ OUT_RELOCd(nv10mt->buffer,txf,NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
+ OUT_RING (ps->wrap);
+ OUT_RING (0x40000000); /* enable */
+ OUT_RING (txs);
+ OUT_RING (ps->filt | 0x2000 /* magic */);
+ OUT_RING ((pt->width[0] << 16) | pt->height[0]);
+ OUT_RING (ps->bcol);
+#endif
+}
+
+void
+nv10_fragtex_bind(struct nv10_context *nv10)
+{
+#if 0
+ struct nv10_fragment_program *fp = nv10->fragprog.active;
+ unsigned samplers, unit;
+
+ samplers = nv10->fp_samplers & ~fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ BEGIN_RING(celsius, NV10TCL_TX_ENABLE(unit), 1);
+ OUT_RING (0);
+ }
+
+ samplers = nv10->dirty_samplers & fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ nv10_fragtex_build(nv10, unit);
+ }
+
+ nv10->fp_samplers = fp->samplers;
+#endif
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_miptree.c b/src/gallium/drivers/nv10/nv10_miptree.c
new file mode 100644
index 0000000000..34e3c2ebd7
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_miptree.c
@@ -0,0 +1,167 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "nv10_context.h"
+#include "nv10_screen.h"
+
+static void
+nv10_miptree_layout(struct nv10_miptree *nv10mt)
+{
+ struct pipe_texture *pt = &nv10mt->base;
+ boolean swizzled = FALSE;
+ uint width = pt->width[0], height = pt->height[0];
+ uint offset = 0;
+ int nr_faces, l, f;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ nr_faces = 6;
+ } else {
+ nr_faces = 1;
+ }
+
+ for (l = 0; l <= pt->last_level; l++) {
+ pt->width[l] = width;
+ pt->height[l] = height;
+ pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+ pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+
+ if (swizzled)
+ nv10mt->level[l].pitch = pt->nblocksx[l] * pt->block.size;
+ else
+ nv10mt->level[l].pitch = pt->nblocksx[0] * pt->block.size;
+ nv10mt->level[l].pitch = (nv10mt->level[l].pitch + 63) & ~63;
+
+ nv10mt->level[l].image_offset =
+ CALLOC(nr_faces, sizeof(unsigned));
+
+ width = MAX2(1, width >> 1);
+ height = MAX2(1, height >> 1);
+
+ }
+
+ for (f = 0; f < nr_faces; f++) {
+ for (l = 0; l <= pt->last_level; l++) {
+ nv10mt->level[l].image_offset[f] = offset;
+ offset += nv10mt->level[l].pitch * pt->height[l];
+ }
+ }
+
+ nv10mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv10_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt,
+ const unsigned *stride, struct pipe_buffer *pb)
+{
+ struct nv10_miptree *mt;
+
+ /* Only supports 2D, non-mipmapped textures for the moment */
+ if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 ||
+ pt->depth[0] != 1)
+ return NULL;
+
+ mt = CALLOC_STRUCT(nv10_miptree);
+ if (!mt)
+ return NULL;
+
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = pscreen;
+ mt->level[0].pitch = stride[0];
+ mt->level[0].image_offset = CALLOC(1, sizeof(unsigned));
+
+ pipe_buffer_reference(&mt->buffer, pb);
+ return &mt->base;
+}
+
+static struct pipe_texture *
+nv10_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt)
+{
+ struct nv10_miptree *mt;
+
+ mt = MALLOC(sizeof(struct nv10_miptree));
+ if (!mt)
+ return NULL;
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = screen;
+
+ nv10_miptree_layout(mt);
+
+ mt->buffer = screen->buffer_create(screen, 256, PIPE_BUFFER_USAGE_PIXEL,
+ mt->total_size);
+ if (!mt->buffer) {
+ FREE(mt);
+ return NULL;
+ }
+
+ return &mt->base;
+}
+
+static void
+nv10_miptree_destroy(struct pipe_texture *pt)
+{
+ struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt;
+ int l;
+
+ pipe_buffer_reference(&nv10mt->buffer, NULL);
+ for (l = 0; l <= pt->last_level; l++) {
+ if (nv10mt->level[l].image_offset)
+ FREE(nv10mt->level[l].image_offset);
+ }
+ FREE(nv10mt);
+}
+
+static void
+nv10_miptree_update(struct pipe_context *pipe, struct pipe_texture *mt,
+ uint face, uint levels)
+{
+}
+
+
+static struct pipe_surface *
+nv10_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned flags)
+{
+ struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt;
+ struct nv04_surface *ns;
+
+ ns = CALLOC_STRUCT(nv04_surface);
+ if (!ns)
+ return NULL;
+ pipe_texture_reference(&ns->base.texture, pt);
+ ns->base.format = pt->format;
+ ns->base.width = pt->width[level];
+ ns->base.height = pt->height[level];
+ ns->base.usage = flags;
+ pipe_reference_init(&ns->base.reference, 1);
+ ns->base.face = face;
+ ns->base.level = level;
+ ns->base.zslice = zslice;
+ ns->pitch = nv10mt->level[level].pitch;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ns->base.offset = nv10mt->level[level].image_offset[face];
+ } else {
+ ns->base.offset = nv10mt->level[level].image_offset[0];
+ }
+
+ return &ns->base;
+}
+
+static void
+nv10_miptree_surface_destroy(struct pipe_surface *surface)
+{
+}
+
+void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+ pscreen->texture_create = nv10_miptree_create;
+ pscreen->texture_blanket = nv10_miptree_blanket;
+ pscreen->texture_destroy = nv10_miptree_destroy;
+ pscreen->get_tex_surface = nv10_miptree_surface_get;
+ pscreen->tex_surface_destroy = nv10_miptree_surface_destroy;
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_prim_vbuf.c b/src/gallium/drivers/nv10/nv10_prim_vbuf.c
new file mode 100644
index 0000000000..1806d5f8cc
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_prim_vbuf.c
@@ -0,0 +1,261 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Build post-transformation, post-clipping vertex buffers and element
+ * lists by hooking into the end of the primitive pipeline and
+ * manipulating the vertex_id field in the vertex headers.
+ *
+ * XXX: work in progress
+ *
+ * \author José Fonseca <jrfonseca@tungstengraphics.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "util/u_debug.h"
+#include "pipe/p_inlines.h"
+
+#include "nv10_context.h"
+#include "nv10_state.h"
+
+#include "draw/draw_vbuf.h"
+
+/**
+ * Primitive renderer for nv10.
+ */
+struct nv10_vbuf_render {
+ struct vbuf_render base;
+
+ struct nv10_context *nv10;
+
+ /** Vertex buffer */
+ struct pipe_buffer* buffer;
+
+ /** Vertex size in bytes */
+ unsigned vertex_size;
+
+ /** Hardware primitive */
+ unsigned hwprim;
+};
+
+
+void nv10_vtxbuf_bind( struct nv10_context* nv10 )
+{
+ int i;
+ for(i = 0; i < 8; i++) {
+ BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET(i), 1);
+ OUT_RING(0/*nv10->vtxbuf*/);
+ BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT(i) ,1);
+ OUT_RING(0/*XXX*/);
+ }
+}
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct nv10_vbuf_render *
+nv10_vbuf_render( struct vbuf_render *render )
+{
+ assert(render);
+ return (struct nv10_vbuf_render *)render;
+}
+
+
+static const struct vertex_info *
+nv10_vbuf_render_get_vertex_info( struct vbuf_render *render )
+{
+ struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+ struct nv10_context *nv10 = nv10_render->nv10;
+
+ nv10_emit_hw_state(nv10);
+
+ return &nv10->vertex_info;
+}
+
+static boolean
+nv10_vbuf_render_allocate_vertices( struct vbuf_render *render,
+ ushort vertex_size,
+ ushort nr_vertices )
+{
+ struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+ struct nv10_context *nv10 = nv10_render->nv10;
+ struct pipe_screen *screen = nv10->pipe.screen;
+ size_t size = (size_t)vertex_size * (size_t)nr_vertices;
+
+ assert(!nv10_render->buffer);
+ nv10_render->buffer = screen->buffer_create(screen, 64, PIPE_BUFFER_USAGE_VERTEX, size);
+
+ nv10->dirty |= NV10_NEW_VTXARRAYS;
+
+ if (nv10_render->buffer)
+ return FALSE;
+ return TRUE;
+}
+
+static void *
+nv10_vbuf_render_map_vertices( struct vbuf_render *render )
+{
+ struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+ struct nv10_context *nv10 = nv10_render->nv10;
+ struct pipe_screen *pscreen = nv10->pipe.screen;
+
+ return pipe_buffer_map(pscreen, nv10_render->buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+}
+
+static void
+nv10_vbuf_render_unmap_vertices( struct vbuf_render *render,
+ ushort min_index,
+ ushort max_index )
+{
+ struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+ struct nv10_context *nv10 = nv10_render->nv10;
+ struct pipe_screen *pscreen = nv10->pipe.screen;
+
+ assert(!nv10_render->buffer);
+ pipe_buffer_unmap(pscreen, nv10_render->buffer);
+}
+
+static boolean
+nv10_vbuf_render_set_primitive( struct vbuf_render *render,
+ unsigned prim )
+{
+ struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+ unsigned hwp = nvgl_primitive(prim);
+ if (hwp == 0)
+ return FALSE;
+
+ nv10_render->hwprim = hwp;
+ return TRUE;
+}
+
+
+static void
+nv10_vbuf_render_draw( struct vbuf_render *render,
+ const ushort *indices,
+ uint nr_indices)
+{
+ struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+ struct nv10_context *nv10 = nv10_render->nv10;
+ int push, i;
+
+ nv10_emit_hw_state(nv10);
+
+ BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_OFFSET_POS, 1);
+ OUT_RELOCl(nv10_render->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+
+ BEGIN_RING(celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);
+ OUT_RING(nv10_render->hwprim);
+
+ if (nr_indices & 1) {
+ BEGIN_RING(celsius, NV10TCL_VB_ELEMENT_U32, 1);
+ OUT_RING (indices[0]);
+ indices++; nr_indices--;
+ }
+
+ while (nr_indices) {
+ // XXX too big/small ? check the size
+ push = MIN2(nr_indices, 1200 * 2);
+
+ BEGIN_RING_NI(celsius, NV10TCL_VB_ELEMENT_U16, push >> 1);
+ for (i = 0; i < push; i+=2)
+ OUT_RING((indices[i+1] << 16) | indices[i]);
+
+ nr_indices -= push;
+ indices += push;
+ }
+
+ BEGIN_RING(celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);
+ OUT_RING (0);
+}
+
+
+static void
+nv10_vbuf_render_release_vertices( struct vbuf_render *render )
+{
+ struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+
+ assert(nv10_render->buffer);
+ pipe_buffer_reference(&nv10_render->buffer, NULL);
+}
+
+
+static void
+nv10_vbuf_render_destroy( struct vbuf_render *render )
+{
+ struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+ FREE(nv10_render);
+}
+
+
+/**
+ * Create a new primitive render.
+ */
+static struct vbuf_render *
+nv10_vbuf_render_create( struct nv10_context *nv10 )
+{
+ struct nv10_vbuf_render *nv10_render = CALLOC_STRUCT(nv10_vbuf_render);
+
+ nv10_render->nv10 = nv10;
+
+ nv10_render->base.max_vertex_buffer_bytes = 16*1024;
+ nv10_render->base.max_indices = 1024;
+ nv10_render->base.get_vertex_info = nv10_vbuf_render_get_vertex_info;
+ nv10_render->base.allocate_vertices = nv10_vbuf_render_allocate_vertices;
+ nv10_render->base.map_vertices = nv10_vbuf_render_map_vertices;
+ nv10_render->base.unmap_vertices = nv10_vbuf_render_unmap_vertices;
+ nv10_render->base.set_primitive = nv10_vbuf_render_set_primitive;
+ nv10_render->base.draw = nv10_vbuf_render_draw;
+ nv10_render->base.release_vertices = nv10_vbuf_render_release_vertices;
+ nv10_render->base.destroy = nv10_vbuf_render_destroy;
+
+ return &nv10_render->base;
+}
+
+
+/**
+ * Create a new primitive vbuf/render stage.
+ */
+struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 )
+{
+ struct vbuf_render *render;
+ struct draw_stage *stage;
+
+ render = nv10_vbuf_render_create(nv10);
+ if(!render)
+ return NULL;
+
+ stage = draw_vbuf_stage( nv10->draw, render );
+ if(!stage) {
+ render->destroy(render);
+ return NULL;
+ }
+
+ return stage;
+}
diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c
new file mode 100644
index 0000000000..4469b22d91
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_screen.c
@@ -0,0 +1,198 @@
+#include "pipe/p_screen.h"
+
+#include "nv10_context.h"
+#include "nv10_screen.h"
+
+static int
+nv10_screen_get_param(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return 2;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 0;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 0;
+ case PIPE_CAP_GLSL:
+ return 0;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 1;
+ case PIPE_CAP_POINT_SPRITE:
+ return 0;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 1;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 0;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 0;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 12;
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 0;
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 12;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ return 0;
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ return 0;
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 0;
+ case NOUVEAU_CAP_HW_VTXBUF:
+ case NOUVEAU_CAP_HW_IDXBUF:
+ return 0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0;
+ }
+}
+
+static float
+nv10_screen_get_paramf(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 10.0;
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 64.0;
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 2.0;
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 4.0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0.0;
+ }
+}
+
+static boolean
+nv10_screen_is_format_supported(struct pipe_screen *screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else
+ if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) {
+ switch (format) {
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+nv10_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct nv10_screen *screen = nv10_screen(pscreen);
+
+ nouveau_notifier_free(&screen->sync);
+ nouveau_grobj_free(&screen->celsius);
+
+ FREE(pscreen);
+}
+
+static struct pipe_buffer *
+nv10_surface_buffer(struct pipe_surface *surf)
+{
+ struct nv10_miptree *mt = (struct nv10_miptree *)surf->texture;
+
+ return mt->buffer;
+}
+
+struct pipe_screen *
+nv10_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
+{
+ struct nv10_screen *screen = CALLOC_STRUCT(nv10_screen);
+ struct nouveau_channel *chan;
+ struct pipe_screen *pscreen;
+ unsigned celsius_class;
+ int ret;
+
+ if (!screen)
+ return NULL;
+ pscreen = &screen->base.base;
+
+ ret = nouveau_screen_init(&screen->base, dev);
+ if (ret) {
+ nv10_screen_destroy(pscreen);
+ return NULL;
+ }
+ chan = screen->base.channel;
+
+ pscreen->winsys = ws;
+ pscreen->destroy = nv10_screen_destroy;
+ pscreen->get_param = nv10_screen_get_param;
+ pscreen->get_paramf = nv10_screen_get_paramf;
+ pscreen->is_format_supported = nv10_screen_is_format_supported;
+
+ nv10_screen_init_miptree_functions(pscreen);
+ nv10_screen_init_transfer_functions(pscreen);
+
+ /* 3D object */
+ if (dev->chipset >= 0x20)
+ celsius_class = NV11TCL;
+ else if (dev->chipset >= 0x17)
+ celsius_class = NV17TCL;
+ else if (dev->chipset >= 0x11)
+ celsius_class = NV11TCL;
+ else
+ celsius_class = NV10TCL;
+
+ if (!celsius_class) {
+ NOUVEAU_ERR("Unknown nv1x chipset: nv%02x\n", dev->chipset);
+ return NULL;
+ }
+
+ ret = nouveau_grobj_alloc(chan, 0xbeef0001, celsius_class,
+ &screen->celsius);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+ return FALSE;
+ }
+ BIND_RING(chan, screen->celsius, 7);
+
+ /* 2D engine setup */
+ screen->eng2d = nv04_surface_2d_init(&screen->base);
+ screen->eng2d->buf = nv10_surface_buffer;
+
+ /* Notifier for sync purposes */
+ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
+ if (ret) {
+ NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+ nv10_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ return pscreen;
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h
new file mode 100644
index 0000000000..86b6d8def5
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_screen.h
@@ -0,0 +1,28 @@
+#ifndef __NV10_SCREEN_H__
+#define __NV10_SCREEN_H__
+
+#include "nouveau/nouveau_screen.h"
+#include "nv04/nv04_surface_2d.h"
+
+struct nv10_screen {
+ struct nouveau_screen base;
+
+ struct nouveau_winsys *nvws;
+
+ /* HW graphics objects */
+ struct nv04_surface_2d *eng2d;
+ struct nouveau_grobj *celsius;
+ struct nouveau_notifier *sync;
+};
+
+static INLINE struct nv10_screen *
+nv10_screen(struct pipe_screen *screen)
+{
+ return (struct nv10_screen *)screen;
+}
+
+
+void
+nv10_screen_init_transfer_functions(struct pipe_screen *pscreen);
+
+#endif
diff --git a/src/gallium/drivers/nv10/nv10_state.c b/src/gallium/drivers/nv10/nv10_state.c
new file mode 100644
index 0000000000..9b38219b99
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_state.c
@@ -0,0 +1,590 @@
+#include "draw/draw_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_inlines.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "nv10_context.h"
+#include "nv10_state.h"
+
+static void *
+nv10_blend_state_create(struct pipe_context *pipe,
+ const struct pipe_blend_state *cso)
+{
+ struct nv10_blend_state *cb;
+
+ cb = MALLOC(sizeof(struct nv10_blend_state));
+
+ cb->b_enable = cso->blend_enable ? 1 : 0;
+ cb->b_srcfunc = ((nvgl_blend_func(cso->alpha_src_factor)<<16) |
+ (nvgl_blend_func(cso->rgb_src_factor)));
+ cb->b_dstfunc = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) |
+ (nvgl_blend_func(cso->rgb_dst_factor)));
+
+ cb->c_mask = (((cso->colormask & PIPE_MASK_A) ? (0x01<<24) : 0) |
+ ((cso->colormask & PIPE_MASK_R) ? (0x01<<16) : 0) |
+ ((cso->colormask & PIPE_MASK_G) ? (0x01<< 8) : 0) |
+ ((cso->colormask & PIPE_MASK_B) ? (0x01<< 0) : 0));
+
+ cb->d_enable = cso->dither ? 1 : 0;
+
+ return (void *)cb;
+}
+
+static void
+nv10_blend_state_bind(struct pipe_context *pipe, void *blend)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ nv10->blend = (struct nv10_blend_state*)blend;
+
+ nv10->dirty |= NV10_NEW_BLEND;
+}
+
+static void
+nv10_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+
+static INLINE unsigned
+wrap_mode(unsigned wrap) {
+ unsigned ret;
+
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ ret = NV10TCL_TX_FORMAT_WRAP_S_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ ret = NV10TCL_TX_FORMAT_WRAP_S_MIRRORED_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_BORDER;
+ break;
+ case PIPE_TEX_WRAP_CLAMP:
+ ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ default:
+ NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+ ret = NV10TCL_TX_FORMAT_WRAP_S_REPEAT;
+ break;
+ }
+
+ return ret >> NV10TCL_TX_FORMAT_WRAP_S_SHIFT;
+}
+
+static void *
+nv10_sampler_state_create(struct pipe_context *pipe,
+ const struct pipe_sampler_state *cso)
+{
+ struct nv10_sampler_state *ps;
+ uint32_t filter = 0;
+
+ ps = MALLOC(sizeof(struct nv10_sampler_state));
+
+ ps->wrap = ((wrap_mode(cso->wrap_s) << NV10TCL_TX_FORMAT_WRAP_S_SHIFT) |
+ (wrap_mode(cso->wrap_t) << NV10TCL_TX_FORMAT_WRAP_T_SHIFT));
+
+ ps->en = 0;
+ if (cso->max_anisotropy > 1.0) {
+ /* no idea, binary driver sets it, works without it.. meh.. */
+ ps->wrap |= (1 << 5);
+
+/* if (cso->max_anisotropy >= 16.0) {
+ ps->en |= NV10TCL_TX_ENABLE_ANISO_16X;
+ } else
+ if (cso->max_anisotropy >= 12.0) {
+ ps->en |= NV10TCL_TX_ENABLE_ANISO_12X;
+ } else
+ if (cso->max_anisotropy >= 10.0) {
+ ps->en |= NV10TCL_TX_ENABLE_ANISO_10X;
+ } else
+ if (cso->max_anisotropy >= 8.0) {
+ ps->en |= NV10TCL_TX_ENABLE_ANISO_8X;
+ } else
+ if (cso->max_anisotropy >= 6.0) {
+ ps->en |= NV10TCL_TX_ENABLE_ANISO_6X;
+ } else
+ if (cso->max_anisotropy >= 4.0) {
+ ps->en |= NV10TCL_TX_ENABLE_ANISO_4X;
+ } else {
+ ps->en |= NV10TCL_TX_ENABLE_ANISO_2X;
+ }*/
+ }
+
+ switch (cso->mag_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ filter |= NV10TCL_TX_FILTER_MAGNIFY_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ filter |= NV10TCL_TX_FILTER_MAGNIFY_NEAREST;
+ break;
+ }
+
+ switch (cso->min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR;
+ break;
+ }
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST;
+ break;
+ }
+ break;
+ }
+
+ ps->filt = filter;
+
+/* if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ switch (cso->compare_func) {
+ case PIPE_FUNC_NEVER:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NEVER;
+ break;
+ case PIPE_FUNC_GREATER:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GREATER;
+ break;
+ case PIPE_FUNC_EQUAL:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_EQUAL;
+ break;
+ case PIPE_FUNC_GEQUAL:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GEQUAL;
+ break;
+ case PIPE_FUNC_LESS:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LESS;
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NOTEQUAL;
+ break;
+ case PIPE_FUNC_LEQUAL:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LEQUAL;
+ break;
+ case PIPE_FUNC_ALWAYS:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_ALWAYS;
+ break;
+ default:
+ break;
+ }
+ }*/
+
+ ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) |
+ (float_to_ubyte(cso->border_color[0]) << 16) |
+ (float_to_ubyte(cso->border_color[1]) << 8) |
+ (float_to_ubyte(cso->border_color[2]) << 0));
+
+ return (void *)ps;
+}
+
+static void
+nv10_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv10->tex_sampler[unit] = sampler[unit];
+ nv10->dirty_samplers |= (1 << unit);
+ }
+}
+
+static void
+nv10_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void
+nv10_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+ struct pipe_texture **miptree)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv10->tex_miptree[unit] = (struct nv10_miptree *)miptree[unit];
+ nv10->dirty_samplers |= (1 << unit);
+ }
+}
+
+static void *
+nv10_rasterizer_state_create(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct nv10_rasterizer_state *rs;
+ int i;
+
+ /*XXX: ignored:
+ * light_twoside
+ * offset_cw/ccw -nohw
+ * scissor
+ * point_smooth -nohw
+ * multisample
+ * offset_units / offset_scale
+ */
+ rs = MALLOC(sizeof(struct nv10_rasterizer_state));
+
+ rs->templ = cso;
+
+ rs->shade_model = cso->flatshade ? 0x1d00 : 0x1d01;
+
+ rs->line_width = (unsigned char)(cso->line_width * 8.0) & 0xff;
+ rs->line_smooth_en = cso->line_smooth ? 1 : 0;
+
+ rs->point_size = *(uint32_t*)&cso->point_size;
+
+ rs->poly_smooth_en = cso->poly_smooth ? 1 : 0;
+
+ if (cso->front_winding == PIPE_WINDING_CCW) {
+ rs->front_face = NV10TCL_FRONT_FACE_CCW;
+ rs->poly_mode_front = nvgl_polygon_mode(cso->fill_ccw);
+ rs->poly_mode_back = nvgl_polygon_mode(cso->fill_cw);
+ } else {
+ rs->front_face = NV10TCL_FRONT_FACE_CW;
+ rs->poly_mode_front = nvgl_polygon_mode(cso->fill_cw);
+ rs->poly_mode_back = nvgl_polygon_mode(cso->fill_ccw);
+ }
+
+ switch (cso->cull_mode) {
+ case PIPE_WINDING_CCW:
+ rs->cull_face_en = 1;
+ if (cso->front_winding == PIPE_WINDING_CCW)
+ rs->cull_face = NV10TCL_CULL_FACE_FRONT;
+ else
+ rs->cull_face = NV10TCL_CULL_FACE_BACK;
+ break;
+ case PIPE_WINDING_CW:
+ rs->cull_face_en = 1;
+ if (cso->front_winding == PIPE_WINDING_CW)
+ rs->cull_face = NV10TCL_CULL_FACE_FRONT;
+ else
+ rs->cull_face = NV10TCL_CULL_FACE_BACK;
+ break;
+ case PIPE_WINDING_BOTH:
+ rs->cull_face_en = 1;
+ rs->cull_face = NV10TCL_CULL_FACE_FRONT_AND_BACK;
+ break;
+ case PIPE_WINDING_NONE:
+ default:
+ rs->cull_face_en = 0;
+ rs->cull_face = 0;
+ break;
+ }
+
+ if (cso->point_sprite) {
+ rs->point_sprite = (1 << 0);
+ for (i = 0; i < 8; i++) {
+ if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE)
+ rs->point_sprite |= (1 << (8 + i));
+ }
+ } else {
+ rs->point_sprite = 0;
+ }
+
+ return (void *)rs;
+}
+
+static void
+nv10_rasterizer_state_bind(struct pipe_context *pipe, void *rast)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ nv10->rast = (struct nv10_rasterizer_state*)rast;
+
+ draw_set_rasterizer_state(nv10->draw, (nv10->rast ? nv10->rast->templ : NULL));
+
+ nv10->dirty |= NV10_NEW_RAST;
+}
+
+static void
+nv10_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+nv10_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct nv10_depth_stencil_alpha_state *hw;
+
+ hw = MALLOC(sizeof(struct nv10_depth_stencil_alpha_state));
+
+ hw->depth.func = nvgl_comparison_op(cso->depth.func);
+ hw->depth.write_enable = cso->depth.writemask ? 1 : 0;
+ hw->depth.test_enable = cso->depth.enabled ? 1 : 0;
+
+ hw->stencil.enable = cso->stencil[0].enabled ? 1 : 0;
+ hw->stencil.wmask = cso->stencil[0].writemask;
+ hw->stencil.func = nvgl_comparison_op(cso->stencil[0].func);
+ hw->stencil.ref = cso->stencil[0].ref_value;
+ hw->stencil.vmask = cso->stencil[0].valuemask;
+ hw->stencil.fail = nvgl_stencil_op(cso->stencil[0].fail_op);
+ hw->stencil.zfail = nvgl_stencil_op(cso->stencil[0].zfail_op);
+ hw->stencil.zpass = nvgl_stencil_op(cso->stencil[0].zpass_op);
+
+ hw->alpha.enabled = cso->alpha.enabled ? 1 : 0;
+ hw->alpha.func = nvgl_comparison_op(cso->alpha.func);
+ hw->alpha.ref = float_to_ubyte(cso->alpha.ref_value);
+
+ return (void *)hw;
+}
+
+static void
+nv10_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *dsa)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ nv10->dsa = (struct nv10_depth_stencil_alpha_state*)dsa;
+
+ nv10->dirty |= NV10_NEW_DSA;
+}
+
+static void
+nv10_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+nv10_vp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ return draw_create_vertex_shader(nv10->draw, templ);
+}
+
+static void
+nv10_vp_state_bind(struct pipe_context *pipe, void *shader)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ draw_bind_vertex_shader(nv10->draw, (struct draw_vertex_shader *) shader);
+
+ nv10->dirty |= NV10_NEW_VERTPROG;
+}
+
+static void
+nv10_vp_state_delete(struct pipe_context *pipe, void *shader)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ draw_delete_vertex_shader(nv10->draw, (struct draw_vertex_shader *) shader);
+}
+
+static void *
+nv10_fp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv10_fragment_program *fp;
+
+ fp = CALLOC(1, sizeof(struct nv10_fragment_program));
+ fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+
+ tgsi_scan_shader(cso->tokens, &fp->info);
+
+ return (void *)fp;
+}
+
+static void
+nv10_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+ struct nv10_fragment_program *fp = hwcso;
+
+ nv10->fragprog.current = fp;
+ nv10->dirty |= NV10_NEW_FRAGPROG;
+}
+
+static void
+nv10_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+ struct nv10_fragment_program *fp = hwcso;
+
+ nv10_fragprog_destroy(nv10, fp);
+ FREE((void*)fp->pipe.tokens);
+ FREE(fp);
+}
+
+static void
+nv10_set_blend_color(struct pipe_context *pipe,
+ const struct pipe_blend_color *bcol)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ nv10->blend_color = (struct pipe_blend_color*)bcol;
+
+ nv10->dirty |= NV10_NEW_BLENDCOL;
+}
+
+static void
+nv10_set_clip_state(struct pipe_context *pipe,
+ const struct pipe_clip_state *clip)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ draw_set_clip_state(nv10->draw, clip);
+}
+
+static void
+nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+ const struct pipe_constant_buffer *buf )
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+ struct pipe_screen *pscreen = pipe->screen;
+
+ assert(shader < PIPE_SHADER_TYPES);
+ assert(index == 0);
+
+ if (buf) {
+ void *mapped;
+ if (buf->buffer && buf->buffer->size &&
+ (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+ {
+ memcpy(nv10->constbuf[shader], mapped, buf->buffer->size);
+ nv10->constbuf_nr[shader] =
+ buf->buffer->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pscreen, buf->buffer);
+ }
+ }
+}
+
+static void
+nv10_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ nv10->framebuffer = (struct pipe_framebuffer_state*)fb;
+
+ nv10->dirty |= NV10_NEW_FRAMEBUFFER;
+}
+
+static void
+nv10_set_polygon_stipple(struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple)
+{
+ NOUVEAU_ERR("line stipple hahaha\n");
+}
+
+static void
+nv10_set_scissor_state(struct pipe_context *pipe,
+ const struct pipe_scissor_state *s)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ nv10->scissor = (struct pipe_scissor_state*)s;
+
+ nv10->dirty |= NV10_NEW_SCISSOR;
+}
+
+static void
+nv10_set_viewport_state(struct pipe_context *pipe,
+ const struct pipe_viewport_state *vpt)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ nv10->viewport = (struct pipe_viewport_state*)vpt;
+
+ draw_set_viewport_state(nv10->draw, nv10->viewport);
+
+ nv10->dirty |= NV10_NEW_VIEWPORT;
+}
+
+static void
+nv10_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_buffer *vb)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ memcpy(nv10->vtxbuf, vb, sizeof(*vb) * count);
+ nv10->dirty |= NV10_NEW_VTXARRAYS;
+
+ draw_set_vertex_buffers(nv10->draw, count, vb);
+}
+
+static void
+nv10_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_element *ve)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+
+ memcpy(nv10->vtxelt, ve, sizeof(*ve) * count);
+ nv10->dirty |= NV10_NEW_VTXARRAYS;
+
+ draw_set_vertex_elements(nv10->draw, count, ve);
+}
+
+void
+nv10_init_state_functions(struct nv10_context *nv10)
+{
+ nv10->pipe.create_blend_state = nv10_blend_state_create;
+ nv10->pipe.bind_blend_state = nv10_blend_state_bind;
+ nv10->pipe.delete_blend_state = nv10_blend_state_delete;
+
+ nv10->pipe.create_sampler_state = nv10_sampler_state_create;
+ nv10->pipe.bind_sampler_states = nv10_sampler_state_bind;
+ nv10->pipe.delete_sampler_state = nv10_sampler_state_delete;
+ nv10->pipe.set_sampler_textures = nv10_set_sampler_texture;
+
+ nv10->pipe.create_rasterizer_state = nv10_rasterizer_state_create;
+ nv10->pipe.bind_rasterizer_state = nv10_rasterizer_state_bind;
+ nv10->pipe.delete_rasterizer_state = nv10_rasterizer_state_delete;
+
+ nv10->pipe.create_depth_stencil_alpha_state =
+ nv10_depth_stencil_alpha_state_create;
+ nv10->pipe.bind_depth_stencil_alpha_state =
+ nv10_depth_stencil_alpha_state_bind;
+ nv10->pipe.delete_depth_stencil_alpha_state =
+ nv10_depth_stencil_alpha_state_delete;
+
+ nv10->pipe.create_vs_state = nv10_vp_state_create;
+ nv10->pipe.bind_vs_state = nv10_vp_state_bind;
+ nv10->pipe.delete_vs_state = nv10_vp_state_delete;
+
+ nv10->pipe.create_fs_state = nv10_fp_state_create;
+ nv10->pipe.bind_fs_state = nv10_fp_state_bind;
+ nv10->pipe.delete_fs_state = nv10_fp_state_delete;
+
+ nv10->pipe.set_blend_color = nv10_set_blend_color;
+ nv10->pipe.set_clip_state = nv10_set_clip_state;
+ nv10->pipe.set_constant_buffer = nv10_set_constant_buffer;
+ nv10->pipe.set_framebuffer_state = nv10_set_framebuffer_state;
+ nv10->pipe.set_polygon_stipple = nv10_set_polygon_stipple;
+ nv10->pipe.set_scissor_state = nv10_set_scissor_state;
+ nv10->pipe.set_viewport_state = nv10_set_viewport_state;
+
+ nv10->pipe.set_vertex_buffers = nv10_set_vertex_buffers;
+ nv10->pipe.set_vertex_elements = nv10_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_state.h b/src/gallium/drivers/nv10/nv10_state.h
new file mode 100644
index 0000000000..3a3fd0d4f4
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_state.h
@@ -0,0 +1,139 @@
+#ifndef __NV10_STATE_H__
+#define __NV10_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+
+struct nv10_blend_state {
+ uint32_t b_enable;
+ uint32_t b_srcfunc;
+ uint32_t b_dstfunc;
+
+ uint32_t c_mask;
+
+ uint32_t d_enable;
+};
+
+struct nv10_sampler_state {
+ uint32_t wrap;
+ uint32_t en;
+ uint32_t filt;
+ uint32_t bcol;
+};
+
+struct nv10_rasterizer_state {
+ uint32_t shade_model;
+
+ uint32_t line_width;
+ uint32_t line_smooth_en;
+
+ uint32_t point_size;
+
+ uint32_t poly_smooth_en;
+
+ uint32_t poly_mode_front;
+ uint32_t poly_mode_back;
+
+ uint32_t front_face;
+ uint32_t cull_face;
+ uint32_t cull_face_en;
+
+ uint32_t point_sprite;
+
+ const struct pipe_rasterizer_state *templ;
+};
+
+struct nv10_vertex_program_exec {
+ uint32_t data[4];
+ boolean has_branch_offset;
+ int const_index;
+};
+
+struct nv10_vertex_program_data {
+ int index; /* immediates == -1 */
+ float value[4];
+};
+
+struct nv10_vertex_program {
+ const struct pipe_shader_state *pipe;
+
+ boolean translated;
+ struct nv10_vertex_program_exec *insns;
+ unsigned nr_insns;
+ struct nv10_vertex_program_data *consts;
+ unsigned nr_consts;
+
+ struct nouveau_resource *exec;
+ unsigned exec_start;
+ struct nouveau_resource *data;
+ unsigned data_start;
+ unsigned data_start_min;
+
+ uint32_t ir;
+ uint32_t or;
+};
+
+struct nv10_fragment_program_data {
+ unsigned offset;
+ unsigned index;
+};
+
+struct nv10_fragment_program {
+ struct pipe_shader_state pipe;
+ struct tgsi_shader_info info;
+
+ boolean translated;
+ boolean on_hw;
+ unsigned samplers;
+
+ uint32_t *insn;
+ int insn_len;
+
+ struct nv10_fragment_program_data *consts;
+ unsigned nr_consts;
+
+ struct pipe_buffer *buffer;
+
+ uint32_t fp_control;
+ uint32_t fp_reg_control;
+};
+
+
+struct nv10_depth_stencil_alpha_state {
+ struct {
+ uint32_t func;
+ uint32_t write_enable;
+ uint32_t test_enable;
+ } depth;
+
+ struct {
+ uint32_t enable;
+ uint32_t wmask;
+ uint32_t func;
+ uint32_t ref;
+ uint32_t vmask;
+ uint32_t fail;
+ uint32_t zfail;
+ uint32_t zpass;
+ } stencil;
+
+ struct {
+ uint32_t enabled;
+ uint32_t func;
+ uint32_t ref;
+ } alpha;
+};
+
+struct nv10_miptree {
+ struct pipe_texture base;
+
+ struct pipe_buffer *buffer;
+ uint total_size;
+
+ struct {
+ uint pitch;
+ uint *image_offset;
+ } level[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+#endif
diff --git a/src/gallium/drivers/nv10/nv10_state_emit.c b/src/gallium/drivers/nv10/nv10_state_emit.c
new file mode 100644
index 0000000000..d8691ef9c6
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_state_emit.c
@@ -0,0 +1,306 @@
+#include "nv10_context.h"
+#include "nv10_state.h"
+
+static void nv10_state_emit_blend(struct nv10_context* nv10)
+{
+ struct nv10_blend_state *b = nv10->blend;
+
+ BEGIN_RING(celsius, NV10TCL_DITHER_ENABLE, 1);
+ OUT_RING (b->d_enable);
+
+ BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_ENABLE, 3);
+ OUT_RING (b->b_enable);
+ OUT_RING (b->b_srcfunc);
+ OUT_RING (b->b_dstfunc);
+
+ BEGIN_RING(celsius, NV10TCL_COLOR_MASK, 1);
+ OUT_RING (b->c_mask);
+}
+
+static void nv10_state_emit_blend_color(struct nv10_context* nv10)
+{
+ struct pipe_blend_color *c = nv10->blend_color;
+
+ BEGIN_RING(celsius, NV10TCL_BLEND_COLOR, 1);
+ OUT_RING ((float_to_ubyte(c->color[3]) << 24)|
+ (float_to_ubyte(c->color[0]) << 16)|
+ (float_to_ubyte(c->color[1]) << 8) |
+ (float_to_ubyte(c->color[2]) << 0));
+}
+
+static void nv10_state_emit_rast(struct nv10_context* nv10)
+{
+ struct nv10_rasterizer_state *r = nv10->rast;
+
+ BEGIN_RING(celsius, NV10TCL_SHADE_MODEL, 2);
+ OUT_RING (r->shade_model);
+ OUT_RING (r->line_width);
+
+
+ BEGIN_RING(celsius, NV10TCL_POINT_SIZE, 1);
+ OUT_RING (r->point_size);
+
+ BEGIN_RING(celsius, NV10TCL_POLYGON_MODE_FRONT, 2);
+ OUT_RING (r->poly_mode_front);
+ OUT_RING (r->poly_mode_back);
+
+
+ BEGIN_RING(celsius, NV10TCL_CULL_FACE, 2);
+ OUT_RING (r->cull_face);
+ OUT_RING (r->front_face);
+
+ BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 2);
+ OUT_RING (r->line_smooth_en);
+ OUT_RING (r->poly_smooth_en);
+
+ BEGIN_RING(celsius, NV10TCL_CULL_FACE_ENABLE, 1);
+ OUT_RING (r->cull_face_en);
+}
+
+static void nv10_state_emit_dsa(struct nv10_context* nv10)
+{
+ struct nv10_depth_stencil_alpha_state *d = nv10->dsa;
+
+ BEGIN_RING(celsius, NV10TCL_DEPTH_FUNC, 1);
+ OUT_RING (d->depth.func);
+
+ BEGIN_RING(celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1);
+ OUT_RING (d->depth.write_enable);
+
+ BEGIN_RING(celsius, NV10TCL_DEPTH_TEST_ENABLE, 1);
+ OUT_RING (d->depth.test_enable);
+
+#if 0
+ BEGIN_RING(celsius, NV10TCL_STENCIL_ENABLE, 1);
+ OUT_RING (d->stencil.enable);
+ BEGIN_RING(celsius, NV10TCL_STENCIL_MASK, 7);
+ OUT_RINGp ((uint32_t *)&(d->stencil.wmask), 7);
+#endif
+
+ BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1);
+ OUT_RING (d->alpha.enabled);
+
+ BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_FUNC, 1);
+ OUT_RING (d->alpha.func);
+
+ BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_REF, 1);
+ OUT_RING (d->alpha.ref);
+}
+
+static void nv10_state_emit_viewport(struct nv10_context* nv10)
+{
+}
+
+static void nv10_state_emit_scissor(struct nv10_context* nv10)
+{
+ // XXX this is so not working
+/* struct pipe_scissor_state *s = nv10->scissor;
+ BEGIN_RING(celsius, NV10TCL_SCISSOR_HORIZ, 2);
+ OUT_RING (((s->maxx - s->minx) << 16) | s->minx);
+ OUT_RING (((s->maxy - s->miny) << 16) | s->miny);*/
+}
+
+static void nv10_state_emit_framebuffer(struct nv10_context* nv10)
+{
+ struct pipe_framebuffer_state* fb = nv10->framebuffer;
+ struct nv04_surface *rt, *zeta = NULL;
+ uint32_t rt_format, w, h;
+ int colour_format = 0, zeta_format = 0;
+ struct nv10_miptree *nv10mt = 0;
+
+ w = fb->cbufs[0]->width;
+ h = fb->cbufs[0]->height;
+ colour_format = fb->cbufs[0]->format;
+ rt = (struct nv04_surface *)fb->cbufs[0];
+
+ if (fb->zsbuf) {
+ if (colour_format) {
+ assert(w == fb->zsbuf->width);
+ assert(h == fb->zsbuf->height);
+ } else {
+ w = fb->zsbuf->width;
+ h = fb->zsbuf->height;
+ }
+
+ zeta_format = fb->zsbuf->format;
+ zeta = (struct nv04_surface *)fb->zsbuf;
+ }
+
+ rt_format = NV10TCL_RT_FORMAT_TYPE_LINEAR;
+
+ switch (colour_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case 0:
+ rt_format |= NV10TCL_RT_FORMAT_COLOR_A8R8G8B8;
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ rt_format |= NV10TCL_RT_FORMAT_COLOR_R5G6B5;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (zeta) {
+ BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1);
+ OUT_RING (rt->pitch | (zeta->pitch << 16));
+ } else {
+ BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1);
+ OUT_RING (rt->pitch | (rt->pitch << 16));
+ }
+
+ nv10mt = (struct nv10_miptree *)rt->base.texture;
+ nv10->rt[0] = nv10mt->buffer;
+
+ if (zeta_format)
+ {
+ nv10mt = (struct nv10_miptree *)zeta->base.texture;
+ nv10->zeta = nv10mt->buffer;
+ }
+
+ BEGIN_RING(celsius, NV10TCL_RT_HORIZ, 3);
+ OUT_RING ((w << 16) | 0);
+ OUT_RING ((h << 16) | 0);
+ OUT_RING (rt_format);
+ BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+ OUT_RING (((w - 1) << 16) | 0 | 0x08000800);
+ OUT_RING (((h - 1) << 16) | 0 | 0x08000800);
+}
+
+static void nv10_vertex_layout(struct nv10_context *nv10)
+{
+ struct nv10_fragment_program *fp = nv10->fragprog.current;
+ uint32_t src = 0;
+ int i;
+ struct vertex_info vinfo;
+
+ memset(&vinfo, 0, sizeof(vinfo));
+
+ for (i = 0; i < fp->info.num_inputs; i++) {
+ switch (fp->info.input_semantic_name[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
+ break;
+ default:
+ case TGSI_SEMANTIC_GENERIC:
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
+ break;
+ case TGSI_SEMANTIC_FOG:
+ draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
+ break;
+ }
+ }
+ draw_compute_vertex_size(&vinfo);
+}
+
+void
+nv10_emit_hw_state(struct nv10_context *nv10)
+{
+ int i;
+
+ if (nv10->dirty & NV10_NEW_VERTPROG) {
+ //nv10_vertprog_bind(nv10, nv10->vertprog.current);
+ nv10->dirty &= ~NV10_NEW_VERTPROG;
+ }
+
+ if (nv10->dirty & NV10_NEW_FRAGPROG) {
+ nv10_fragprog_bind(nv10, nv10->fragprog.current);
+ /*XXX: clear NV10_NEW_FRAGPROG if no new program uploaded */
+ nv10->dirty_samplers |= (1<<10);
+ nv10->dirty_samplers = 0;
+ }
+
+ if (nv10->dirty_samplers || (nv10->dirty & NV10_NEW_FRAGPROG)) {
+ nv10_fragtex_bind(nv10);
+ nv10->dirty &= ~NV10_NEW_FRAGPROG;
+ }
+
+ if (nv10->dirty & NV10_NEW_VTXARRAYS) {
+ nv10->dirty &= ~NV10_NEW_VTXARRAYS;
+ nv10_vertex_layout(nv10);
+ nv10_vtxbuf_bind(nv10);
+ }
+
+ if (nv10->dirty & NV10_NEW_BLEND) {
+ nv10->dirty &= ~NV10_NEW_BLEND;
+ nv10_state_emit_blend(nv10);
+ }
+
+ if (nv10->dirty & NV10_NEW_BLENDCOL) {
+ nv10->dirty &= ~NV10_NEW_BLENDCOL;
+ nv10_state_emit_blend_color(nv10);
+ }
+
+ if (nv10->dirty & NV10_NEW_RAST) {
+ nv10->dirty &= ~NV10_NEW_RAST;
+ nv10_state_emit_rast(nv10);
+ }
+
+ if (nv10->dirty & NV10_NEW_DSA) {
+ nv10->dirty &= ~NV10_NEW_DSA;
+ nv10_state_emit_dsa(nv10);
+ }
+
+ if (nv10->dirty & NV10_NEW_VIEWPORT) {
+ nv10->dirty &= ~NV10_NEW_VIEWPORT;
+ nv10_state_emit_viewport(nv10);
+ }
+
+ if (nv10->dirty & NV10_NEW_SCISSOR) {
+ nv10->dirty &= ~NV10_NEW_SCISSOR;
+ nv10_state_emit_scissor(nv10);
+ }
+
+ if (nv10->dirty & NV10_NEW_FRAMEBUFFER) {
+ nv10->dirty &= ~NV10_NEW_FRAMEBUFFER;
+ nv10_state_emit_framebuffer(nv10);
+ }
+
+ /* Emit relocs for every referenced buffer.
+ * This is to ensure the bufmgr has an accurate idea of how
+ * the buffer is used. This isn't very efficient, but we don't
+ * seem to take a significant performance hit. Will be improved
+ * at some point. Vertex arrays are emitted by nv10_vbo.c
+ */
+
+ /* Render target */
+// XXX figre out who's who for NV10TCL_DMA_* and fill accordingly
+// BEGIN_RING(celsius, NV10TCL_DMA_COLOR0, 1);
+// OUT_RELOCo(nv10->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(celsius, NV10TCL_COLOR_OFFSET, 1);
+ OUT_RELOCl(nv10->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ if (nv10->zeta) {
+// XXX
+// BEGIN_RING(celsius, NV10TCL_DMA_ZETA, 1);
+// OUT_RELOCo(nv10->zeta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(celsius, NV10TCL_ZETA_OFFSET, 1);
+ OUT_RELOCl(nv10->zeta, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ /* XXX for when we allocate LMA on nv17 */
+/* BEGIN_RING(celsius, NV10TCL_LMA_DEPTH_BUFFER_OFFSET, 1);
+ OUT_RELOCl(nv10->zeta + lma_offset);*/
+ }
+
+ /* Vertex buffer */
+ BEGIN_RING(celsius, NV10TCL_DMA_VTXBUF0, 1);
+ OUT_RELOCo(nv10->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(celsius, NV10TCL_COLOR_OFFSET, 1);
+ OUT_RELOCl(nv10->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ /* Texture images */
+ for (i = 0; i < 2; i++) {
+ if (!(nv10->fp_samplers & (1 << i)))
+ continue;
+ BEGIN_RING(celsius, NV10TCL_TX_OFFSET(i), 1);
+ OUT_RELOCl(nv10->tex[i].buffer, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ BEGIN_RING(celsius, NV10TCL_TX_FORMAT(i), 1);
+ OUT_RELOCd(nv10->tex[i].buffer, nv10->tex[i].format,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD |
+ NOUVEAU_BO_OR, NV10TCL_TX_FORMAT_DMA0,
+ NV10TCL_TX_FORMAT_DMA1);
+ }
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_surface.c b/src/gallium/drivers/nv10/nv10_surface.c
new file mode 100644
index 0000000000..5b52246a9c
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_surface.c
@@ -0,0 +1,63 @@
+
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "nv10_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+
+static void
+nv10_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+ struct nv04_surface_2d *eng2d = nv10->screen->eng2d;
+
+ eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
+}
+
+static void
+nv10_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+ unsigned destx, unsigned desty, unsigned width,
+ unsigned height, unsigned value)
+{
+ struct nv10_context *nv10 = nv10_context(pipe);
+ struct nv04_surface_2d *eng2d = nv10->screen->eng2d;
+
+ eng2d->fill(eng2d, dest, destx, desty, width, height, value);
+}
+
+void
+nv10_init_surface_functions(struct nv10_context *nv10)
+{
+ nv10->pipe.surface_copy = nv10_surface_copy;
+ nv10->pipe.surface_fill = nv10_surface_fill;
+}
diff --git a/src/gallium/drivers/nv10/nv10_transfer.c b/src/gallium/drivers/nv10/nv10_transfer.c
new file mode 100644
index 0000000000..c06b8d34c7
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_transfer.c
@@ -0,0 +1,195 @@
+#include <pipe/p_state.h>
+#include <pipe/p_defines.h>
+#include <pipe/p_inlines.h>
+#include <util/u_memory.h>
+#include <nouveau/nouveau_winsys.h>
+#include "nv10_context.h"
+#include "nv10_screen.h"
+#include "nv10_state.h"
+
+struct nv10_transfer {
+ struct pipe_transfer base;
+ struct pipe_surface *surface;
+ bool direct;
+};
+
+static unsigned nv10_usage_tx_to_buf(unsigned tx_usage)
+{
+ switch (tx_usage) {
+ case PIPE_TRANSFER_READ:
+ return PIPE_BUFFER_USAGE_CPU_READ;
+ case PIPE_TRANSFER_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_WRITE;
+ case PIPE_TRANSFER_READ_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static void
+nv10_compatible_transfer_tex(struct pipe_texture *pt, unsigned level,
+ struct pipe_texture *template)
+{
+ memset(template, 0, sizeof(struct pipe_texture));
+ template->target = pt->target;
+ template->format = pt->format;
+ template->width[0] = pt->width[level];
+ template->height[0] = pt->height[level];
+ template->depth[0] = 1;
+ template->block = pt->block;
+ template->nblocksx[0] = pt->nblocksx[level];
+ template->nblocksy[0] = pt->nblocksx[level];
+ template->last_level = 0;
+ template->nr_samples = pt->nr_samples;
+
+ template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC |
+ NOUVEAU_TEXTURE_USAGE_LINEAR;
+}
+
+static struct pipe_transfer *
+nv10_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct nv10_miptree *mt = (struct nv10_miptree *)pt;
+ struct nv10_transfer *tx;
+ struct pipe_texture tx_tex_template, *tx_tex;
+
+ tx = CALLOC_STRUCT(nv10_transfer);
+ if (!tx)
+ return NULL;
+
+ pipe_texture_reference(&tx->base.texture, pt);
+ tx->base.format = pt->format;
+ tx->base.x = x;
+ tx->base.y = y;
+ tx->base.width = w;
+ tx->base.height = h;
+ tx->base.block = pt->block;
+ tx->base.nblocksx = pt->nblocksx[level];
+ tx->base.nblocksy = pt->nblocksy[level];
+ tx->base.stride = mt->level[level].pitch;
+ tx->base.usage = usage;
+ tx->base.face = face;
+ tx->base.level = level;
+ tx->base.zslice = zslice;
+
+ /* Direct access to texture */
+ if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC ||
+ debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) &&
+ pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)
+ {
+ tx->direct = true;
+ tx->surface = pscreen->get_tex_surface(pscreen, pt,
+ 0, 0, 0,
+ nv10_usage_tx_to_buf(usage));
+ return &tx->base;
+ }
+
+ tx->direct = false;
+
+ nv10_compatible_transfer_tex(pt, level, &tx_tex_template);
+
+ tx_tex = pscreen->texture_create(pscreen, &tx_tex_template);
+ if (!tx_tex)
+ {
+ FREE(tx);
+ return NULL;
+ }
+
+ tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
+ face, level, zslice,
+ nv10_usage_tx_to_buf(usage));
+
+ pipe_texture_reference(&tx_tex, NULL);
+
+ if (!tx->surface)
+ {
+ pipe_surface_reference(&tx->surface, NULL);
+ FREE(tx);
+ return NULL;
+ }
+
+ if (usage != PIPE_TRANSFER_WRITE) {
+ struct nv10_screen *nvscreen = nv10_screen(pscreen);
+ struct pipe_surface *src;
+
+ src = pscreen->get_tex_surface(pscreen, pt,
+ face, level, zslice,
+ PIPE_BUFFER_USAGE_GPU_READ);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ /* TODO: Check if SIFM can un-swizzle */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ tx->surface, 0, 0,
+ src, 0, 0,
+ src->width, src->height);
+
+ pipe_surface_reference(&src, NULL);
+ }
+
+ return &tx->base;
+}
+
+static void
+nv10_transfer_del(struct pipe_transfer *ptx)
+{
+ struct nv10_transfer *tx = (struct nv10_transfer *)ptx;
+
+ if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) {
+ struct pipe_screen *pscreen = ptx->texture->screen;
+ struct nv10_screen *nvscreen = nv10_screen(pscreen);
+ struct pipe_surface *dst;
+
+ dst = pscreen->get_tex_surface(pscreen, ptx->texture,
+ ptx->face, ptx->level, ptx->zslice,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ dst, 0, 0,
+ tx->surface, 0, 0,
+ dst->width, dst->height);
+
+ pipe_surface_reference(&dst, NULL);
+ }
+
+ pipe_surface_reference(&tx->surface, NULL);
+ pipe_texture_reference(&ptx->texture, NULL);
+ FREE(ptx);
+}
+
+static void *
+nv10_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv10_transfer *tx = (struct nv10_transfer *)ptx;
+ struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
+ struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture;
+ void *map = pipe_buffer_map(pscreen, mt->buffer,
+ nv10_usage_tx_to_buf(ptx->usage));
+
+ return map + ns->base.offset +
+ ptx->y * ns->pitch + ptx->x * ptx->block.size;
+}
+
+static void
+nv10_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv10_transfer *tx = (struct nv10_transfer *)ptx;
+ struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture;
+
+ pipe_buffer_unmap(pscreen, mt->buffer);
+}
+
+void
+nv10_screen_init_transfer_functions(struct pipe_screen *pscreen)
+{
+ pscreen->get_tex_transfer = nv10_transfer_new;
+ pscreen->tex_transfer_destroy = nv10_transfer_del;
+ pscreen->transfer_map = nv10_transfer_map;
+ pscreen->transfer_unmap = nv10_transfer_unmap;
+}
diff --git a/src/gallium/drivers/nv10/nv10_vbo.c b/src/gallium/drivers/nv10/nv10_vbo.c
new file mode 100644
index 0000000000..441a4f75f3
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_vbo.c
@@ -0,0 +1,78 @@
+#include "draw/draw_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "nv10_context.h"
+#include "nv10_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+
+boolean nv10_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count)
+{
+ struct nv10_context *nv10 = nv10_context( pipe );
+ struct draw_context *draw = nv10->draw;
+ struct pipe_screen *pscreen = pipe->screen;
+ unsigned i;
+
+ nv10_emit_hw_state(nv10);
+
+ /*
+ * Map vertex buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (nv10->vtxbuf[i].buffer) {
+ void *buf =
+ pipe_buffer_map(pscreen, nv10->vtxbuf[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_vertex_buffer(draw, i, buf);
+ }
+ }
+ /* Map index buffer, if present */
+ if (indexBuffer) {
+ void *mapped_indexes
+ = pipe_buffer_map(pscreen, indexBuffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes);
+ }
+ else {
+ /* no index/element buffer */
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+ draw_set_mapped_constant_buffer(draw,
+ nv10->constbuf[PIPE_SHADER_VERTEX],
+ nv10->constbuf_nr[PIPE_SHADER_VERTEX]);
+
+ /* draw! */
+ draw_arrays(nv10->draw, prim, start, count);
+
+ /*
+ * unmap vertex/index buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (nv10->vtxbuf[i].buffer) {
+ pipe_buffer_unmap(pscreen, nv10->vtxbuf[i].buffer);
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ }
+ }
+ if (indexBuffer) {
+ pipe_buffer_unmap(pscreen, indexBuffer);
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+ return TRUE;
+}
+
+boolean nv10_draw_arrays( struct pipe_context *pipe,
+ unsigned prim, unsigned start, unsigned count)
+{
+ return nv10_draw_elements(pipe, NULL, 0, prim, start, count);
+}
+
+
+
diff --git a/src/gallium/drivers/nv20/Makefile b/src/gallium/drivers/nv20/Makefile
new file mode 100644
index 0000000000..1305f26c59
--- /dev/null
+++ b/src/gallium/drivers/nv20/Makefile
@@ -0,0 +1,21 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv20
+
+C_SOURCES = \
+ nv20_clear.c \
+ nv20_context.c \
+ nv20_fragprog.c \
+ nv20_fragtex.c \
+ nv20_miptree.c \
+ nv20_prim_vbuf.c \
+ nv20_screen.c \
+ nv20_state.c \
+ nv20_state_emit.c \
+ nv20_surface.c \
+ nv20_transfer.c \
+ nv20_vbo.c
+# nv20_vertprog.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/nv20/nv20_clear.c b/src/gallium/drivers/nv20/nv20_clear.c
new file mode 100644
index 0000000000..2b4490fa5e
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_clear.c
@@ -0,0 +1,14 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "util/u_clear.h"
+
+#include "nv20_context.h"
+
+void
+nv20_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil)
+{
+ util_clear(pipe, nv20_context(pipe)->framebuffer, buffers, rgba, depth,
+ stencil);
+}
diff --git a/src/gallium/drivers/nv20/nv20_context.c b/src/gallium/drivers/nv20/nv20_context.c
new file mode 100644
index 0000000000..b32d0d83ba
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_context.c
@@ -0,0 +1,446 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "nv20_context.h"
+#include "nv20_screen.h"
+
+static void
+nv20_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ draw_flush(nv20->draw);
+
+ FIRE_RING(fence);
+}
+
+static void
+nv20_destroy(struct pipe_context *pipe)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ if (nv20->draw)
+ draw_destroy(nv20->draw);
+
+ FREE(nv20);
+}
+
+static void nv20_init_hwctx(struct nv20_context *nv20)
+{
+ struct nv20_screen *screen = nv20->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ int i;
+ float projectionmatrix[16];
+ const boolean is_nv25tcl = (nv20->screen->kelvin->grclass == NV25TCL);
+
+ BEGIN_RING(kelvin, NV20TCL_DMA_NOTIFY, 1);
+ OUT_RING (screen->sync->handle);
+ BEGIN_RING(kelvin, NV20TCL_DMA_TEXTURE0, 2);
+ OUT_RING (chan->vram->handle);
+ OUT_RING (chan->gart->handle); /* TEXTURE1 */
+ BEGIN_RING(kelvin, NV20TCL_DMA_COLOR, 2);
+ OUT_RING (chan->vram->handle);
+ OUT_RING (chan->vram->handle); /* ZETA */
+
+ BEGIN_RING(kelvin, NV20TCL_DMA_QUERY, 1);
+ OUT_RING (0); /* renouveau: beef0351, unique */
+
+ BEGIN_RING(kelvin, NV20TCL_RT_HORIZ, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+
+ BEGIN_RING(kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(0), 1);
+ OUT_RING ((0xfff << 16) | 0x0);
+ BEGIN_RING(kelvin, NV20TCL_VIEWPORT_CLIP_VERT(0), 1);
+ OUT_RING ((0xfff << 16) | 0x0);
+
+ for (i = 1; i < NV20TCL_VIEWPORT_CLIP_HORIZ__SIZE; i++) {
+ BEGIN_RING(kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(i), 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_VIEWPORT_CLIP_VERT(i), 1);
+ OUT_RING (0);
+ }
+
+ BEGIN_RING(kelvin, NV20TCL_VIEWPORT_CLIP_MODE, 1);
+ OUT_RING (0);
+
+ BEGIN_RING(kelvin, 0x17e0, 3);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (1.0);
+
+ if (is_nv25tcl) {
+ BEGIN_RING(kelvin, NV20TCL_TX_RCOMP, 1);
+ OUT_RING (NV20TCL_TX_RCOMP_LEQUAL | 0xdb0);
+ } else {
+ BEGIN_RING(kelvin, 0x1e68, 1);
+ OUT_RING (0x4b800000); /* 16777216.000000 */
+ BEGIN_RING(kelvin, NV20TCL_TX_RCOMP, 1);
+ OUT_RING (NV20TCL_TX_RCOMP_LEQUAL);
+ }
+
+ BEGIN_RING(kelvin, 0x290, 1);
+ OUT_RING ((0x10 << 16) | 1);
+ BEGIN_RING(kelvin, 0x9fc, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, 0x1d80, 1);
+ OUT_RING (1);
+ BEGIN_RING(kelvin, 0x9f8, 1);
+ OUT_RING (4);
+ BEGIN_RING(kelvin, 0x17ec, 3);
+ OUT_RINGf (0.0);
+ OUT_RINGf (1.0);
+ OUT_RINGf (0.0);
+
+ if (is_nv25tcl) {
+ BEGIN_RING(kelvin, 0x1d88, 1);
+ OUT_RING (3);
+
+ BEGIN_RING(kelvin, NV25TCL_DMA_IN_MEMORY9, 1);
+ OUT_RING (chan->vram->handle);
+ BEGIN_RING(kelvin, NV25TCL_DMA_IN_MEMORY8, 1);
+ OUT_RING (chan->vram->handle);
+ }
+ BEGIN_RING(kelvin, NV20TCL_DMA_FENCE, 1);
+ OUT_RING (0); /* renouveau: beef1e10 */
+
+ BEGIN_RING(kelvin, 0x1e98, 1);
+ OUT_RING (0);
+#if 0
+ if (is_nv25tcl) {
+ BEGIN_RING(NvSub3D, NV25TCL_DMA_IN_MEMORY4, 2);
+ OUT_RING (NvDmaTT); /* renouveau: beef0202 */
+ OUT_RING (NvDmaFB); /* renouveau: beef0201 */
+
+ BEGIN_RING(NvSub3D, NV20TCL_DMA_TEXTURE1, 1);
+ OUT_RING (NvDmaTT); /* renouveau: beef0202 */
+ }
+#endif
+ BEGIN_RING(kelvin, NV20TCL_NOTIFY, 1);
+ OUT_RING (0);
+
+ BEGIN_RING(kelvin, 0x120, 3);
+ OUT_RING (0);
+ OUT_RING (1);
+ OUT_RING (2);
+
+/* error: ILLEGAL_MTHD, PROTECTION_FAULT
+ BEGIN_RING(kelvin, NV20TCL_VIEWPORT_TRANSLATE_X, 4);
+ OUT_RINGf (0.0);
+ OUT_RINGf (512.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+*/
+
+ if (is_nv25tcl) {
+ BEGIN_RING(kelvin, 0x022c, 2);
+ OUT_RING (0x280);
+ OUT_RING (0x07d28000);
+ }
+
+/* * illegal method, protection fault
+ BEGIN_RING(NvSub3D, 0x1c2c, 1);
+ OUT_RING (0); */
+
+ if (is_nv25tcl) {
+ BEGIN_RING(kelvin, 0x1da4, 1);
+ OUT_RING (0);
+ }
+
+/* * crashes with illegal method, protection fault
+ BEGIN_RING(NvSub3D, 0x1c18, 1);
+ OUT_RING (0x200); */
+
+ BEGIN_RING(kelvin, NV20TCL_RT_HORIZ, 2);
+ OUT_RING ((0 << 16) | 0);
+ OUT_RING ((0 << 16) | 0);
+
+ /* *** Set state *** */
+
+ BEGIN_RING(kelvin, NV20TCL_ALPHA_FUNC_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_ALPHA_FUNC_FUNC, 2);
+ OUT_RING (NV20TCL_ALPHA_FUNC_FUNC_ALWAYS);
+ OUT_RING (0); /* NV20TCL_ALPHA_FUNC_REF */
+
+ for (i = 0; i < NV20TCL_TX_ENABLE__SIZE; ++i) {
+ BEGIN_RING(kelvin, NV20TCL_TX_ENABLE(i), 1);
+ OUT_RING (0);
+ }
+ BEGIN_RING(kelvin, NV20TCL_TX_SHADER_OP, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_TX_SHADER_CULL_MODE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_RC_IN_ALPHA(0), 4);
+ OUT_RING (0x30d410d0);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_RC_OUT_RGB(0), 4);
+ OUT_RING (0x00000c00);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_RC_ENABLE, 1);
+ OUT_RING (0x00011101);
+ BEGIN_RING(kelvin, NV20TCL_RC_FINAL0, 2);
+ OUT_RING (0x130e0300);
+ OUT_RING (0x0c091c80);
+ BEGIN_RING(kelvin, NV20TCL_RC_OUT_ALPHA(0), 4);
+ OUT_RING (0x00000c00);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_RC_IN_RGB(0), 4);
+ OUT_RING (0x20c400c0);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_RC_COLOR0, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_RC_CONSTANT_COLOR0(0), 4);
+ OUT_RING (0x035125a0);
+ OUT_RING (0);
+ OUT_RING (0x40002000);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_MULTISAMPLE_CONTROL, 1);
+ OUT_RING (0xffff0000);
+
+ BEGIN_RING(kelvin, NV20TCL_BLEND_FUNC_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_DITHER_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_STENCIL_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_BLEND_FUNC_SRC, 4);
+ OUT_RING (NV20TCL_BLEND_FUNC_SRC_ONE);
+ OUT_RING (NV20TCL_BLEND_FUNC_DST_ZERO);
+ OUT_RING (0); /* NV20TCL_BLEND_COLOR */
+ OUT_RING (NV20TCL_BLEND_EQUATION_FUNC_ADD);
+ BEGIN_RING(kelvin, NV20TCL_STENCIL_MASK, 7);
+ OUT_RING (0xff);
+ OUT_RING (NV20TCL_STENCIL_FUNC_FUNC_ALWAYS);
+ OUT_RING (0); /* NV20TCL_STENCIL_FUNC_REF */
+ OUT_RING (0xff); /* NV20TCL_STENCIL_FUNC_MASK */
+ OUT_RING (NV20TCL_STENCIL_OP_FAIL_KEEP);
+ OUT_RING (NV20TCL_STENCIL_OP_ZFAIL_KEEP);
+ OUT_RING (NV20TCL_STENCIL_OP_ZPASS_KEEP);
+
+ BEGIN_RING(kelvin, NV20TCL_COLOR_LOGIC_OP_ENABLE, 2);
+ OUT_RING (0);
+ OUT_RING (NV20TCL_COLOR_LOGIC_OP_OP_COPY);
+ BEGIN_RING(kelvin, 0x17cc, 1);
+ OUT_RING (0);
+ if (is_nv25tcl) {
+ BEGIN_RING(kelvin, 0x1d84, 1);
+ OUT_RING (1);
+ }
+ BEGIN_RING(kelvin, NV20TCL_LIGHTING_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_LIGHT_CONTROL, 1);
+ OUT_RING (0x00020000);
+ BEGIN_RING(kelvin, NV20TCL_SEPARATE_SPECULAR_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_LIGHT_MODEL_TWO_SIDE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_ENABLED_LIGHTS, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_NORMALIZE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_POLYGON_STIPPLE_PATTERN(0),
+ NV20TCL_POLYGON_STIPPLE_PATTERN__SIZE);
+ for (i = 0; i < NV20TCL_POLYGON_STIPPLE_PATTERN__SIZE; ++i) {
+ OUT_RING(0xffffffff);
+ }
+
+ BEGIN_RING(kelvin, NV20TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+ OUT_RING (0);
+ OUT_RING (0); /* NV20TCL.POLYGON_OFFSET_LINE_ENABLE */
+ OUT_RING (0); /* NV20TCL.POLYGON_OFFSET_FILL_ENABLE */
+ BEGIN_RING(kelvin, NV20TCL_DEPTH_FUNC, 1);
+ OUT_RING (NV20TCL_DEPTH_FUNC_LESS);
+ BEGIN_RING(kelvin, NV20TCL_DEPTH_WRITE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_DEPTH_TEST_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_POLYGON_OFFSET_FACTOR, 2);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0); /* NV20TCL.POLYGON_OFFSET_UNITS */
+ BEGIN_RING(kelvin, NV20TCL_DEPTH_UNK17D8, 1);
+ OUT_RING (1);
+ if (!is_nv25tcl) {
+ BEGIN_RING(kelvin, 0x1d84, 1);
+ OUT_RING (3);
+ }
+ BEGIN_RING(kelvin, NV20TCL_POINT_SIZE, 1);
+ if (!is_nv25tcl) {
+ OUT_RING (8);
+ } else {
+ OUT_RINGf (1.0);
+ }
+ if (!is_nv25tcl) {
+ BEGIN_RING(kelvin, NV20TCL_POINT_PARAMETERS_ENABLE, 2);
+ OUT_RING (0);
+ OUT_RING (0); /* NV20TCL.POINT_SMOOTH_ENABLE */
+ } else {
+ BEGIN_RING(kelvin, NV20TCL_POINT_PARAMETERS_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, 0x0a1c, 1);
+ OUT_RING (0x800);
+ }
+ BEGIN_RING(kelvin, NV20TCL_LINE_WIDTH, 1);
+ OUT_RING (8);
+ BEGIN_RING(kelvin, NV20TCL_LINE_SMOOTH_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_POLYGON_MODE_FRONT, 2);
+ OUT_RING (NV20TCL_POLYGON_MODE_FRONT_FILL);
+ OUT_RING (NV20TCL_POLYGON_MODE_BACK_FILL);
+ BEGIN_RING(kelvin, NV20TCL_CULL_FACE, 2);
+ OUT_RING (NV20TCL_CULL_FACE_BACK);
+ OUT_RING (NV20TCL_FRONT_FACE_CCW);
+ BEGIN_RING(kelvin, NV20TCL_POLYGON_SMOOTH_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_CULL_FACE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_SHADE_MODEL, 1);
+ OUT_RING (NV20TCL_SHADE_MODEL_SMOOTH);
+ BEGIN_RING(kelvin, NV20TCL_POLYGON_STIPPLE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV20TCL_TX_GEN_S(0), 4 * NV20TCL_TX_GEN_S__SIZE);
+ for (i=0; i < 4 * NV20TCL_TX_GEN_S__SIZE; ++i) {
+ OUT_RING(0);
+ }
+ BEGIN_RING(kelvin, NV20TCL_FOG_EQUATION_CONSTANT, 3);
+ OUT_RINGf (1.5);
+ OUT_RINGf (-0.090168); /* NV20TCL.FOG_EQUATION_LINEAR */
+ OUT_RINGf (0.0); /* NV20TCL.FOG_EQUATION_QUADRATIC */
+ BEGIN_RING(kelvin, NV20TCL_FOG_MODE, 2);
+ OUT_RING (NV20TCL_FOG_MODE_EXP_2);
+ OUT_RING (NV20TCL_FOG_COORD_DIST_COORD_FOG);
+ BEGIN_RING(kelvin, NV20TCL_FOG_ENABLE, 2);
+ OUT_RING (0);
+ OUT_RING (0); /* NV20TCL.FOG_COLOR */
+ BEGIN_RING(kelvin, NV20TCL_ENGINE, 1);
+ OUT_RING (NV20TCL_ENGINE_FIXED);
+
+ for (i = 0; i < NV20TCL_TX_MATRIX_ENABLE__SIZE; ++i) {
+ BEGIN_RING(kelvin, NV20TCL_TX_MATRIX_ENABLE(i), 1);
+ OUT_RING (0);
+ }
+
+ BEGIN_RING(kelvin, NV20TCL_VTX_ATTR_4F_X(1), 4 * 15);
+ OUT_RINGf(1.0); OUT_RINGf(0.0); OUT_RINGf(0.0); OUT_RINGf(1.0);
+ OUT_RINGf(0.0); OUT_RINGf(0.0); OUT_RINGf(1.0); OUT_RINGf(1.0);
+ OUT_RINGf(1.0); OUT_RINGf(1.0); OUT_RINGf(1.0); OUT_RINGf(1.0);
+ for (i = 4; i < 16; ++i) {
+ OUT_RINGf(0.0); OUT_RINGf(0.0); OUT_RINGf(0.0); OUT_RINGf(1.0);
+ }
+
+ BEGIN_RING(kelvin, NV20TCL_EDGEFLAG_ENABLE, 1);
+ OUT_RING (1);
+ BEGIN_RING(kelvin, NV20TCL_COLOR_MASK, 1);
+ OUT_RING (0x00010101);
+ BEGIN_RING(kelvin, NV20TCL_CLEAR_VALUE, 1);
+ OUT_RING (0);
+
+ memset(projectionmatrix, 0, sizeof(projectionmatrix));
+ projectionmatrix[0*4+0] = 1.0;
+ projectionmatrix[1*4+1] = 1.0;
+ projectionmatrix[2*4+2] = 16777215.0;
+ projectionmatrix[3*4+3] = 1.0;
+ BEGIN_RING(kelvin, NV20TCL_PROJECTION_MATRIX(0), 16);
+ for (i = 0; i < 16; i++) {
+ OUT_RINGf (projectionmatrix[i]);
+ }
+
+ BEGIN_RING(kelvin, NV20TCL_DEPTH_RANGE_NEAR, 2);
+ OUT_RINGf (0.0);
+ OUT_RINGf (16777216.0); /* [0, 1] scaled approx to [0, 2^24] */
+
+ BEGIN_RING(kelvin, NV20TCL_VIEWPORT_SCALE0_X, 4);
+ OUT_RINGf (0.0); /* x-offset, w/2 + 1.031250 */
+ OUT_RINGf (0.0); /* y-offset, h/2 + 0.030762 */
+ OUT_RINGf (0.0);
+ OUT_RINGf (16777215.0);
+
+ BEGIN_RING(kelvin, NV20TCL_VIEWPORT_SCALE1_X, 4);
+ OUT_RINGf (0.0); /* no effect?, w/2 */
+ OUT_RINGf (0.0); /* no effect?, h/2 */
+ OUT_RINGf (16777215.0 * 0.5);
+ OUT_RINGf (65535.0);
+
+ FIRE_RING (NULL);
+}
+
+static void
+nv20_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+}
+
+
+static unsigned int
+nv20_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static unsigned int
+nv20_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+struct pipe_context *
+nv20_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+ struct nv20_screen *screen = nv20_screen(pscreen);
+ struct pipe_winsys *ws = pscreen->winsys;
+ struct nv20_context *nv20;
+ struct nouveau_winsys *nvws = screen->nvws;
+
+ nv20 = CALLOC(1, sizeof(struct nv20_context));
+ if (!nv20)
+ return NULL;
+ nv20->screen = screen;
+ nv20->pctx_id = pctx_id;
+
+ nv20->nvws = nvws;
+
+ nv20->pipe.winsys = ws;
+ nv20->pipe.screen = pscreen;
+ nv20->pipe.destroy = nv20_destroy;
+ nv20->pipe.set_edgeflags = nv20_set_edgeflags;
+ nv20->pipe.draw_arrays = nv20_draw_arrays;
+ nv20->pipe.draw_elements = nv20_draw_elements;
+ nv20->pipe.clear = nv20_clear;
+ nv20->pipe.flush = nv20_flush;
+
+ nv20->pipe.is_texture_referenced = nv20_is_texture_referenced;
+ nv20->pipe.is_buffer_referenced = nv20_is_buffer_referenced;
+
+ nv20_init_surface_functions(nv20);
+ nv20_init_state_functions(nv20);
+
+ nv20->draw = draw_create();
+ assert(nv20->draw);
+ draw_set_rasterize_stage(nv20->draw, nv20_draw_vbuf_stage(nv20));
+
+ nv20_init_hwctx(nv20);
+
+ return &nv20->pipe;
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_context.h b/src/gallium/drivers/nv20/nv20_context.h
new file mode 100644
index 0000000000..fc932f1f90
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_context.h
@@ -0,0 +1,153 @@
+#ifndef __NV20_CONTEXT_H__
+#define __NV20_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx) \
+ struct nv20_screen *ctx = nv20->screen
+#include "nouveau/nouveau_push.h"
+
+#include "nv20_state.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+ fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+ fprintf(stderr, "nouveau: "fmt, ##args);
+
+#define NV20_NEW_VERTPROG (1 << 0)
+#define NV20_NEW_FRAGPROG (1 << 1)
+#define NV20_NEW_VTXARRAYS (1 << 2)
+#define NV20_NEW_BLEND (1 << 3)
+#define NV20_NEW_BLENDCOL (1 << 4)
+#define NV20_NEW_RAST (1 << 5)
+#define NV20_NEW_DSA (1 << 6)
+#define NV20_NEW_VIEWPORT (1 << 7)
+#define NV20_NEW_SCISSOR (1 << 8)
+#define NV20_NEW_FRAMEBUFFER (1 << 9)
+
+#include "nv20_screen.h"
+
+struct nv20_context {
+ struct pipe_context pipe;
+
+ struct nouveau_winsys *nvws;
+ struct nv20_screen *screen;
+ unsigned pctx_id;
+
+ struct draw_context *draw;
+
+ uint32_t dirty;
+
+ struct nv20_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
+ struct nv20_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
+ unsigned dirty_samplers;
+ unsigned fp_samplers;
+ unsigned vp_samplers;
+
+ uint32_t rt_enable;
+ struct pipe_buffer *rt[4];
+ struct pipe_buffer *zeta;
+ uint32_t lma_offset;
+
+ struct nv20_blend_state *blend;
+ struct pipe_blend_color *blend_color;
+ struct nv20_rasterizer_state *rast;
+ struct nv20_depth_stencil_alpha_state *dsa;
+ struct pipe_viewport_state *viewport;
+ struct pipe_scissor_state *scissor;
+ struct pipe_framebuffer_state *framebuffer;
+
+ //struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+ float *constbuf[PIPE_SHADER_TYPES][32][4];
+ unsigned constbuf_nr[PIPE_SHADER_TYPES];
+
+ struct vertex_info vertex_info;
+
+ struct {
+ struct pipe_buffer *buffer;
+ uint32_t format;
+ } tex[2];
+
+ unsigned vb_enable;
+ struct {
+ struct pipe_buffer *buffer;
+ unsigned delta;
+ } vb[16];
+
+/* struct {
+
+ struct nouveau_resource *exec_heap;
+ struct nouveau_resource *data_heap;
+
+ struct nv20_vertex_program *active;
+
+ struct nv20_vertex_program *current;
+ } vertprog;
+*/
+ struct {
+ struct nv20_fragment_program *active;
+
+ struct nv20_fragment_program *current;
+ struct pipe_buffer *constant_buf;
+ } fragprog;
+
+ struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+ struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+};
+
+static INLINE struct nv20_context *
+nv20_context(struct pipe_context *pipe)
+{
+ return (struct nv20_context *)pipe;
+}
+
+extern void nv20_init_state_functions(struct nv20_context *nv20);
+extern void nv20_init_surface_functions(struct nv20_context *nv20);
+
+extern void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+/* nv20_clear.c */
+extern void nv20_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil);
+
+/* nv20_draw.c */
+extern struct draw_stage *nv20_draw_render_stage(struct nv20_context *nv20);
+
+/* nv20_fragprog.c */
+extern void nv20_fragprog_bind(struct nv20_context *,
+ struct nv20_fragment_program *);
+extern void nv20_fragprog_destroy(struct nv20_context *,
+ struct nv20_fragment_program *);
+
+/* nv20_fragtex.c */
+extern void nv20_fragtex_bind(struct nv20_context *);
+
+/* nv20_prim_vbuf.c */
+struct draw_stage *nv20_draw_vbuf_stage( struct nv20_context *nv20 );
+extern void nv20_vtxbuf_bind(struct nv20_context* nv20);
+
+/* nv20_state.c and friends */
+extern void nv20_emit_hw_state(struct nv20_context *nv20);
+extern void nv20_state_tex_update(struct nv20_context *nv20);
+
+/* nv20_vbo.c */
+extern boolean nv20_draw_arrays(struct pipe_context *, unsigned mode,
+ unsigned start, unsigned count);
+extern boolean nv20_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count);
+
+
+#endif
diff --git a/src/gallium/drivers/nv20/nv20_fragprog.c b/src/gallium/drivers/nv20/nv20_fragprog.c
new file mode 100644
index 0000000000..4f496369dd
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_fragprog.c
@@ -0,0 +1,21 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+
+#include "nv20_context.h"
+
+void
+nv20_fragprog_bind(struct nv20_context *nv20, struct nv20_fragment_program *fp)
+{
+}
+
+void
+nv20_fragprog_destroy(struct nv20_context *nv20,
+ struct nv20_fragment_program *fp)
+{
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_fragtex.c b/src/gallium/drivers/nv20/nv20_fragtex.c
new file mode 100644
index 0000000000..495a7be912
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_fragtex.c
@@ -0,0 +1,124 @@
+#include "nv20_context.h"
+#include "nouveau/nouveau_util.h"
+
+#define _(m,tf) \
+{ \
+ TRUE, \
+ PIPE_FORMAT_##m, \
+ NV20TCL_TX_FORMAT_FORMAT_##tf, \
+}
+
+struct nv20_texture_format {
+ boolean defined;
+ uint pipe;
+ int format;
+};
+
+static struct nv20_texture_format
+nv20_texture_formats[] = {
+ _(A8R8G8B8_UNORM, A8R8G8B8),
+ _(A1R5G5B5_UNORM, A1R5G5B5),
+ _(A4R4G4B4_UNORM, A4R4G4B4),
+ _(L8_UNORM , L8 ),
+ _(A8_UNORM , A8 ),
+ _(A8L8_UNORM , A8L8 ),
+/* _(RGB_DXT1 , DXT1, ), */
+/* _(RGBA_DXT1 , DXT1, ), */
+/* _(RGBA_DXT3 , DXT3, ), */
+/* _(RGBA_DXT5 , DXT5, ), */
+ {},
+};
+
+static struct nv20_texture_format *
+nv20_fragtex_format(uint pipe_format)
+{
+ struct nv20_texture_format *tf = nv20_texture_formats;
+
+ while (tf->defined) {
+ if (tf->pipe == pipe_format)
+ return tf;
+ tf++;
+ }
+
+ return NULL;
+}
+
+
+static void
+nv20_fragtex_build(struct nv20_context *nv20, int unit)
+{
+#if 0
+ struct nv20_sampler_state *ps = nv20->tex_sampler[unit];
+ struct nv20_miptree *nv20mt = nv20->tex_miptree[unit];
+ struct pipe_texture *pt = &nv20mt->base;
+ struct nv20_texture_format *tf;
+ uint32_t txf, txs, txp;
+
+ tf = nv20_fragtex_format(pt->format);
+ if (!tf || !tf->defined) {
+ NOUVEAU_ERR("Unsupported texture format: 0x%x\n", pt->format);
+ return;
+ }
+
+ txf = tf->format << 8;
+ txf |= (pt->last_level + 1) << 16;
+ txf |= log2i(pt->width[0]) << 20;
+ txf |= log2i(pt->height[0]) << 24;
+ txf |= log2i(pt->depth[0]) << 28;
+ txf |= 8;
+
+ switch (pt->target) {
+ case PIPE_TEXTURE_CUBE:
+ txf |= NV10TCL_TX_FORMAT_CUBE_MAP;
+ /* fall-through */
+ case PIPE_TEXTURE_2D:
+ txf |= (2<<4);
+ break;
+ case PIPE_TEXTURE_1D:
+ txf |= (1<<4);
+ break;
+ default:
+ NOUVEAU_ERR("Unknown target %d\n", pt->target);
+ return;
+ }
+
+ BEGIN_RING(kelvin, NV10TCL_TX_OFFSET(unit), 8);
+ OUT_RELOCl(nv20mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ OUT_RELOCd(nv20mt->buffer,txf,NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
+ OUT_RING (ps->wrap);
+ OUT_RING (0x40000000); /* enable */
+ OUT_RING (txs);
+ OUT_RING (ps->filt | 0x2000 /* magic */);
+ OUT_RING ((pt->width[0] << 16) | pt->height[0]);
+ OUT_RING (ps->bcol);
+#endif
+}
+
+void
+nv20_fragtex_bind(struct nv20_context *nv20)
+{
+#if 0
+ struct nv20_fragment_program *fp = nv20->fragprog.active;
+ unsigned samplers, unit;
+
+ samplers = nv20->fp_samplers & ~fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ BEGIN_RING(kelvin, NV10TCL_TX_ENABLE(unit), 1);
+ OUT_RING (0);
+ }
+
+ samplers = nv20->dirty_samplers & fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ nv20_fragtex_build(nv20, unit);
+ }
+
+ nv20->fp_samplers = fp->samplers;
+#endif
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_miptree.c b/src/gallium/drivers/nv20/nv20_miptree.c
new file mode 100644
index 0000000000..185fbf53e0
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_miptree.c
@@ -0,0 +1,206 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "nv20_context.h"
+#include "nv20_screen.h"
+
+static void
+nv20_miptree_layout(struct nv20_miptree *nv20mt)
+{
+ struct pipe_texture *pt = &nv20mt->base;
+ uint width = pt->width[0], height = pt->height[0];
+ uint offset = 0;
+ int nr_faces, l, f;
+ uint wide_pitch = pt->tex_usage & (PIPE_TEXTURE_USAGE_SAMPLER |
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL |
+ PIPE_TEXTURE_USAGE_RENDER_TARGET |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_PRIMARY);
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ nr_faces = 6;
+ } else {
+ nr_faces = 1;
+ }
+
+ for (l = 0; l <= pt->last_level; l++) {
+ pt->width[l] = width;
+ pt->height[l] = height;
+ pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+ pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+
+ if (wide_pitch && (pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR))
+ nv20mt->level[l].pitch = align(pt->width[0] * pt->block.size, 64);
+ else
+ nv20mt->level[l].pitch = pt->width[l] * pt->block.size;
+
+ nv20mt->level[l].image_offset =
+ CALLOC(nr_faces, sizeof(unsigned));
+
+ width = MAX2(1, width >> 1);
+ height = MAX2(1, height >> 1);
+ }
+
+ for (f = 0; f < nr_faces; f++) {
+ for (l = 0; l < pt->last_level; l++) {
+ nv20mt->level[l].image_offset[f] = offset;
+
+ if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) &&
+ pt->width[l + 1] > 1 && pt->height[l + 1] > 1)
+ offset += align(nv20mt->level[l].pitch * pt->height[l], 64);
+ else
+ offset += nv20mt->level[l].pitch * pt->height[l];
+ }
+
+ nv20mt->level[l].image_offset[f] = offset;
+ offset += nv20mt->level[l].pitch * pt->height[l];
+ }
+
+ nv20mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv20_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt,
+ const unsigned *stride, struct pipe_buffer *pb)
+{
+ struct nv20_miptree *mt;
+
+ /* Only supports 2D, non-mipmapped textures for the moment */
+ if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 ||
+ pt->depth[0] != 1)
+ return NULL;
+
+ mt = CALLOC_STRUCT(nv20_miptree);
+ if (!mt)
+ return NULL;
+
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = pscreen;
+ mt->level[0].pitch = stride[0];
+ mt->level[0].image_offset = CALLOC(1, sizeof(unsigned));
+
+ pipe_buffer_reference(&mt->buffer, pb);
+ return &mt->base;
+}
+
+static struct pipe_texture *
+nv20_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt)
+{
+ struct nv20_miptree *mt;
+ unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL |
+ NOUVEAU_BUFFER_USAGE_TEXTURE;
+
+ mt = MALLOC(sizeof(struct nv20_miptree));
+ if (!mt)
+ return NULL;
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = screen;
+
+ /* Swizzled textures must be POT */
+ if (pt->width[0] & (pt->width[0] - 1) ||
+ pt->height[0] & (pt->height[0] - 1))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else
+ if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else
+ if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC)
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else {
+ switch (pt->format) {
+ /* TODO: Figure out which formats can be swizzled */
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_R16_SNORM:
+ {
+ if (debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ break;
+ }
+ default:
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ }
+ }
+
+ if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC)
+ buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+
+ nv20_miptree_layout(mt);
+
+ mt->buffer = screen->buffer_create(screen, 256, buf_usage, mt->total_size);
+ if (!mt->buffer) {
+ FREE(mt);
+ return NULL;
+ }
+
+ return &mt->base;
+}
+
+static void
+nv20_miptree_destroy(struct pipe_texture *pt)
+{
+ struct nv20_miptree *nv20mt = (struct nv20_miptree *)pt;
+ int l;
+
+ pipe_buffer_reference(&nv20mt->buffer, NULL);
+ for (l = 0; l <= pt->last_level; l++) {
+ if (nv20mt->level[l].image_offset)
+ FREE(nv20mt->level[l].image_offset);
+ }
+}
+
+static struct pipe_surface *
+nv20_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned flags)
+{
+ struct nv20_miptree *nv20mt = (struct nv20_miptree *)pt;
+ struct nv04_surface *ns;
+
+ ns = CALLOC_STRUCT(nv04_surface);
+ if (!ns)
+ return NULL;
+ pipe_texture_reference(&ns->base.texture, pt);
+ ns->base.format = pt->format;
+ ns->base.width = pt->width[level];
+ ns->base.height = pt->height[level];
+ ns->base.usage = flags;
+ pipe_reference_init(&ns->base.reference, 1);
+ ns->base.face = face;
+ ns->base.level = level;
+ ns->base.zslice = zslice;
+ ns->pitch = nv20mt->level[level].pitch;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ns->base.offset = nv20mt->level[level].image_offset[face];
+ } else
+ if (pt->target == PIPE_TEXTURE_3D) {
+ ns->base.offset = nv20mt->level[level].image_offset[zslice];
+ } else {
+ ns->base.offset = nv20mt->level[level].image_offset[0];
+ }
+
+ return &ns->base;
+}
+
+static void
+nv20_miptree_surface_destroy(struct pipe_surface *ps)
+{
+ pipe_texture_reference(&ps->texture, NULL);
+ FREE(ps);
+}
+
+void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+ pscreen->texture_create = nv20_miptree_create;
+ pscreen->texture_blanket = nv20_miptree_blanket;
+ pscreen->texture_destroy = nv20_miptree_destroy;
+ pscreen->get_tex_surface = nv20_miptree_surface_get;
+ pscreen->tex_surface_destroy = nv20_miptree_surface_destroy;
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_prim_vbuf.c b/src/gallium/drivers/nv20/nv20_prim_vbuf.c
new file mode 100644
index 0000000000..ddfcdb8057
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_prim_vbuf.c
@@ -0,0 +1,428 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Build post-transformation, post-clipping vertex buffers and element
+ * lists by hooking into the end of the primitive pipeline and
+ * manipulating the vertex_id field in the vertex headers.
+ *
+ * XXX: work in progress
+ *
+ * \author José Fonseca <jrfonseca@tungstengraphics.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "util/u_debug.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "nv20_context.h"
+#include "nv20_state.h"
+
+#include "draw/draw_vbuf.h"
+
+/**
+ * Primitive renderer for nv20.
+ */
+struct nv20_vbuf_render {
+ struct vbuf_render base;
+
+ struct nv20_context *nv20;
+
+ /** Vertex buffer in VRAM */
+ struct pipe_buffer *pbuffer;
+
+ /** Vertex buffer in normal memory */
+ void *mbuffer;
+
+ /** Vertex size in bytes */
+ /*unsigned vertex_size;*/
+
+ /** Hardware primitive */
+ unsigned hwprim;
+};
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct nv20_vbuf_render *
+nv20_vbuf_render(struct vbuf_render *render)
+{
+ assert(render);
+ return (struct nv20_vbuf_render *)render;
+}
+
+void nv20_vtxbuf_bind( struct nv20_context* nv20 )
+{
+#if 0
+ int i;
+ for(i = 0; i < NV20TCL_VTXBUF_ADDRESS__SIZE; i++) {
+ BEGIN_RING(kelvin, NV20TCL_VTXBUF_ADDRESS(i), 1);
+ OUT_RING(0/*nv20->vtxbuf*/);
+ BEGIN_RING(kelvin, NV20TCL_VTXFMT(i) ,1);
+ OUT_RING(0/*XXX*/);
+ }
+#endif
+}
+
+static const struct vertex_info *
+nv20_vbuf_render_get_vertex_info( struct vbuf_render *render )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ struct nv20_context *nv20 = nv20_render->nv20;
+
+ nv20_emit_hw_state(nv20);
+
+ return &nv20->vertex_info;
+}
+
+static void *
+nv20__allocate_mbuffer(struct nv20_vbuf_render *nv20_render, size_t size)
+{
+ nv20_render->mbuffer = MALLOC(size);
+ return nv20_render->mbuffer;
+}
+
+static void
+nv20__allocate_pbuffer(struct nv20_vbuf_render *nv20_render, size_t size)
+{
+ struct pipe_screen *screen = nv20_render->nv20->pipe.screen;
+ nv20_render->pbuffer = screen->buffer_create(screen, 64,
+ PIPE_BUFFER_USAGE_VERTEX, size);
+}
+
+static boolean
+nv20_vbuf_render_allocate_vertices( struct vbuf_render *render,
+ ushort vertex_size,
+ ushort nr_vertices )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ size_t size = (size_t)vertex_size * (size_t)nr_vertices;
+ void *buf;
+
+ assert(!nv20_render->pbuffer);
+ assert(!nv20_render->mbuffer);
+
+ /*
+ * For small amount of vertices, don't bother with pipe vertex
+ * buffer, the data will be passed directly via the fifo.
+ */
+ /* XXX: Pipe vertex buffers don't work. */
+ if (0 && size > 16 * 1024) {
+ nv20__allocate_pbuffer(nv20_render, size);
+ /* umm yeah so this is ugly */
+ buf = nv20_render->pbuffer;
+ } else {
+ buf = nv20__allocate_mbuffer(nv20_render, size);
+ }
+
+ if (buf)
+ nv20_render->nv20->dirty |= NV20_NEW_VTXARRAYS;
+
+ return buf ? TRUE : FALSE;
+}
+
+static void *
+nv20_vbuf_render_map_vertices( struct vbuf_render *render )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ struct pipe_screen *pscreen = nv20_render->nv20->pipe.screen;
+
+ if (nv20_render->pbuffer) {
+ return pipe_buffer_map(pscreen, nv20_render->pbuffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ } else if (nv20_render->mbuffer) {
+ return nv20_render->mbuffer;
+ } else
+ assert(0);
+
+ /* warnings be gone */
+ return NULL;
+}
+
+static void
+nv20_vbuf_render_unmap_vertices( struct vbuf_render *render,
+ ushort min_index,
+ ushort max_index )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ struct pipe_screen *pscreen = nv20_render->nv20->pipe.screen;
+
+ if (nv20_render->pbuffer)
+ pipe_buffer_unmap(pscreen, nv20_render->pbuffer);
+}
+
+static boolean
+nv20_vbuf_render_set_primitive( struct vbuf_render *render,
+ unsigned prim )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ unsigned hwp = nvgl_primitive(prim);
+ if (hwp == 0)
+ return FALSE;
+
+ nv20_render->hwprim = hwp;
+ return TRUE;
+}
+
+static uint32_t
+nv20__vtxhwformat(unsigned stride, unsigned fields, unsigned type)
+{
+ return (stride << NV20TCL_VTXFMT_STRIDE_SHIFT) |
+ (fields << NV20TCL_VTXFMT_SIZE_SHIFT) |
+ (type << NV20TCL_VTXFMT_TYPE_SHIFT);
+}
+
+static unsigned
+nv20__emit_format(struct nv20_context *nv20, enum attrib_emit type, int hwattr)
+{
+ uint32_t hwfmt = 0;
+ unsigned fields;
+
+ switch (type) {
+ case EMIT_OMIT:
+ hwfmt = nv20__vtxhwformat(0, 0, 2);
+ fields = 0;
+ break;
+ case EMIT_1F:
+ hwfmt = nv20__vtxhwformat(4, 1, 2);
+ fields = 1;
+ break;
+ case EMIT_2F:
+ hwfmt = nv20__vtxhwformat(8, 2, 2);
+ fields = 2;
+ break;
+ case EMIT_3F:
+ hwfmt = nv20__vtxhwformat(12, 3, 2);
+ fields = 3;
+ break;
+ case EMIT_4F:
+ hwfmt = nv20__vtxhwformat(16, 4, 2);
+ fields = 4;
+ break;
+ default:
+ NOUVEAU_ERR("unhandled attrib_emit %d\n", type);
+ return 0;
+ }
+
+ BEGIN_RING(kelvin, NV20TCL_VTXFMT(hwattr), 1);
+ OUT_RING(hwfmt);
+ return fields;
+}
+
+static unsigned
+nv20__emit_vertex_array_format(struct nv20_context *nv20)
+{
+ struct vertex_info *vinfo = &nv20->vertex_info;
+ int hwattr = NV20TCL_VTXFMT__SIZE;
+ int attr = 0;
+ unsigned nr_fields = 0;
+
+ while (hwattr-- > 0) {
+ if (vinfo->hwfmt[0] & (1 << hwattr)) {
+ nr_fields += nv20__emit_format(nv20,
+ vinfo->attrib[attr].emit, hwattr);
+ attr++;
+ } else
+ nv20__emit_format(nv20, EMIT_OMIT, hwattr);
+ }
+
+ return nr_fields;
+}
+
+static void
+nv20__draw_mbuffer(struct nv20_vbuf_render *nv20_render,
+ const ushort *indices,
+ uint nr_indices)
+{
+ struct nv20_context *nv20 = nv20_render->nv20;
+ struct vertex_info *vinfo = &nv20->vertex_info;
+ unsigned nr_fields;
+ int max_push;
+ ubyte *data = nv20_render->mbuffer;
+ int vsz = 4 * vinfo->size;
+
+ nr_fields = nv20__emit_vertex_array_format(nv20);
+
+ BEGIN_RING(kelvin, NV20TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING(nv20_render->hwprim);
+
+ max_push = 1200 / nr_fields;
+ while (nr_indices) {
+ int i;
+ int push = MIN2(nr_indices, max_push);
+
+ BEGIN_RING_NI(kelvin, NV20TCL_VERTEX_DATA, push * nr_fields);
+ for (i = 0; i < push; i++) {
+ /* XXX: fixme to handle other than floats? */
+ int f = nr_fields;
+ float *attrv = (float*)&data[indices[i] * vsz];
+ while (f-- > 0)
+ OUT_RINGf(*attrv++);
+ }
+
+ nr_indices -= push;
+ indices += push;
+ }
+
+ BEGIN_RING(kelvin, NV20TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING(NV20TCL_VERTEX_BEGIN_END_STOP);
+}
+
+static void
+nv20__draw_pbuffer(struct nv20_vbuf_render *nv20_render,
+ const ushort *indices,
+ uint nr_indices)
+{
+ struct nv20_context *nv20 = nv20_render->nv20;
+ int push, i;
+
+ NOUVEAU_ERR("nv20__draw_pbuffer: this path is broken.\n");
+
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_ARRAY_OFFSET_POS, 1);
+ OUT_RELOCl(nv20_render->pbuffer, 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);
+ OUT_RING(nv20_render->hwprim);
+
+ if (nr_indices & 1) {
+ BEGIN_RING(kelvin, NV10TCL_VB_ELEMENT_U32, 1);
+ OUT_RING (indices[0]);
+ indices++; nr_indices--;
+ }
+
+ while (nr_indices) {
+ // XXX too big/small ? check the size
+ push = MIN2(nr_indices, 1200 * 2);
+
+ BEGIN_RING_NI(kelvin, NV10TCL_VB_ELEMENT_U16, push >> 1);
+ for (i = 0; i < push; i+=2)
+ OUT_RING((indices[i+1] << 16) | indices[i]);
+
+ nr_indices -= push;
+ indices += push;
+ }
+
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);
+ OUT_RING (0);
+}
+
+static void
+nv20_vbuf_render_draw( struct vbuf_render *render,
+ const ushort *indices,
+ uint nr_indices)
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+
+ nv20_emit_hw_state(nv20_render->nv20);
+
+ if (nv20_render->pbuffer)
+ nv20__draw_pbuffer(nv20_render, indices, nr_indices);
+ else if (nv20_render->mbuffer)
+ nv20__draw_mbuffer(nv20_render, indices, nr_indices);
+ else
+ assert(0);
+}
+
+
+static void
+nv20_vbuf_render_release_vertices( struct vbuf_render *render )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ struct nv20_context *nv20 = nv20_render->nv20;
+
+ if (nv20_render->pbuffer) {
+ pipe_buffer_reference(&nv20_render->pbuffer, NULL);
+ } else if (nv20_render->mbuffer) {
+ FREE(nv20_render->mbuffer);
+ nv20_render->mbuffer = NULL;
+ } else
+ assert(0);
+}
+
+
+static void
+nv20_vbuf_render_destroy( struct vbuf_render *render )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+
+ assert(!nv20_render->pbuffer);
+ assert(!nv20_render->mbuffer);
+
+ FREE(nv20_render);
+}
+
+
+/**
+ * Create a new primitive render.
+ */
+static struct vbuf_render *
+nv20_vbuf_render_create( struct nv20_context *nv20 )
+{
+ struct nv20_vbuf_render *nv20_render = CALLOC_STRUCT(nv20_vbuf_render);
+
+ nv20_render->nv20 = nv20;
+
+ nv20_render->base.max_vertex_buffer_bytes = 16*1024;
+ nv20_render->base.max_indices = 1024;
+ nv20_render->base.get_vertex_info = nv20_vbuf_render_get_vertex_info;
+ nv20_render->base.allocate_vertices =
+ nv20_vbuf_render_allocate_vertices;
+ nv20_render->base.map_vertices = nv20_vbuf_render_map_vertices;
+ nv20_render->base.unmap_vertices = nv20_vbuf_render_unmap_vertices;
+ nv20_render->base.set_primitive = nv20_vbuf_render_set_primitive;
+ nv20_render->base.draw = nv20_vbuf_render_draw;
+ nv20_render->base.release_vertices = nv20_vbuf_render_release_vertices;
+ nv20_render->base.destroy = nv20_vbuf_render_destroy;
+
+ return &nv20_render->base;
+}
+
+
+/**
+ * Create a new primitive vbuf/render stage.
+ */
+struct draw_stage *nv20_draw_vbuf_stage( struct nv20_context *nv20 )
+{
+ struct vbuf_render *render;
+ struct draw_stage *stage;
+
+ render = nv20_vbuf_render_create(nv20);
+ if(!render)
+ return NULL;
+
+ stage = draw_vbuf_stage( nv20->draw, render );
+ if(!stage) {
+ render->destroy(render);
+ return NULL;
+ }
+
+ return stage;
+}
diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c
new file mode 100644
index 0000000000..e6924ad71e
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_screen.c
@@ -0,0 +1,194 @@
+#include "pipe/p_screen.h"
+
+#include "nv20_context.h"
+#include "nv20_screen.h"
+
+static int
+nv20_screen_get_param(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return 2;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 0;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 0;
+ case PIPE_CAP_GLSL:
+ return 0;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 1;
+ case PIPE_CAP_POINT_SPRITE:
+ return 0;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 1;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 0;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 0;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 12;
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 0;
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 12;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ return 0;
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ return 0;
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 0;
+ case NOUVEAU_CAP_HW_VTXBUF:
+ case NOUVEAU_CAP_HW_IDXBUF:
+ return 0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0;
+ }
+}
+
+static float
+nv20_screen_get_paramf(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 10.0;
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 64.0;
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 2.0;
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 4.0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0.0;
+ }
+}
+
+static boolean
+nv20_screen_is_format_supported(struct pipe_screen *screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else
+ if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) {
+ switch (format) {
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+nv20_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct nv20_screen *screen = nv20_screen(pscreen);
+
+ nouveau_notifier_free(&screen->sync);
+ nouveau_grobj_free(&screen->kelvin);
+
+ FREE(pscreen);
+}
+
+static struct pipe_buffer *
+nv20_surface_buffer(struct pipe_surface *surf)
+{
+ struct nv20_miptree *mt = (struct nv20_miptree *)surf->texture;
+
+ return mt->buffer;
+}
+
+struct pipe_screen *
+nv20_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
+{
+ struct nv20_screen *screen = CALLOC_STRUCT(nv20_screen);
+ struct nouveau_channel *chan;
+ struct pipe_screen *pscreen;
+ unsigned kelvin_class = 0;
+ int ret;
+
+ if (!screen)
+ return NULL;
+ pscreen = &screen->base.base;
+
+ ret = nouveau_screen_init(&screen->base, dev);
+ if (ret) {
+ nv20_screen_destroy(pscreen);
+ return NULL;
+ }
+ chan = screen->base.channel;
+
+ pscreen->winsys = ws;
+ pscreen->destroy = nv20_screen_destroy;
+ pscreen->get_param = nv20_screen_get_param;
+ pscreen->get_paramf = nv20_screen_get_paramf;
+ pscreen->is_format_supported = nv20_screen_is_format_supported;
+
+ nv20_screen_init_miptree_functions(pscreen);
+ nv20_screen_init_transfer_functions(pscreen);
+
+ /* 3D object */
+ if (dev->chipset >= 0x25)
+ kelvin_class = NV25TCL;
+ else if (dev->chipset >= 0x20)
+ kelvin_class = NV20TCL;
+
+ if (!kelvin_class || dev->chipset >= 0x30) {
+ NOUVEAU_ERR("Unknown nv2x chipset: nv%02x\n", dev->chipset);
+ return NULL;
+ }
+
+ ret = nouveau_grobj_alloc(chan, 0xbeef0097, kelvin_class,
+ &screen->kelvin);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+ return FALSE;
+ }
+ BIND_RING(chan, screen->kelvin, 7);
+
+ /* 2D engine setup */
+ screen->eng2d = nv04_surface_2d_init(&screen->base);
+ screen->eng2d->buf = nv20_surface_buffer;
+
+ /* Notifier for sync purposes */
+ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
+ if (ret) {
+ NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+ nv20_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ return pscreen;
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_screen.h b/src/gallium/drivers/nv20/nv20_screen.h
new file mode 100644
index 0000000000..fc7bb05033
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_screen.h
@@ -0,0 +1,28 @@
+#ifndef __NV20_SCREEN_H__
+#define __NV20_SCREEN_H__
+
+#include "nouveau/nouveau_screen.h"
+#include "nv04/nv04_surface_2d.h"
+
+struct nv20_screen {
+ struct nouveau_screen base;
+
+ struct nouveau_winsys *nvws;
+
+ /* HW graphics objects */
+ struct nv04_surface_2d *eng2d;
+ struct nouveau_grobj *kelvin;
+ struct nouveau_notifier *sync;
+};
+
+static INLINE struct nv20_screen *
+nv20_screen(struct pipe_screen *screen)
+{
+ return (struct nv20_screen *)screen;
+}
+
+
+void
+nv20_screen_init_transfer_functions(struct pipe_screen *pscreen);
+
+#endif
diff --git a/src/gallium/drivers/nv20/nv20_state.c b/src/gallium/drivers/nv20/nv20_state.c
new file mode 100644
index 0000000000..ed4084980f
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_state.c
@@ -0,0 +1,583 @@
+#include "draw/draw_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_inlines.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "nv20_context.h"
+#include "nv20_state.h"
+
+static void *
+nv20_blend_state_create(struct pipe_context *pipe,
+ const struct pipe_blend_state *cso)
+{
+ struct nv20_blend_state *cb;
+
+ cb = MALLOC(sizeof(struct nv20_blend_state));
+
+ cb->b_enable = cso->blend_enable ? 1 : 0;
+ cb->b_srcfunc = ((nvgl_blend_func(cso->alpha_src_factor)<<16) |
+ (nvgl_blend_func(cso->rgb_src_factor)));
+ cb->b_dstfunc = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) |
+ (nvgl_blend_func(cso->rgb_dst_factor)));
+
+ cb->c_mask = (((cso->colormask & PIPE_MASK_A) ? (0x01<<24) : 0) |
+ ((cso->colormask & PIPE_MASK_R) ? (0x01<<16) : 0) |
+ ((cso->colormask & PIPE_MASK_G) ? (0x01<< 8) : 0) |
+ ((cso->colormask & PIPE_MASK_B) ? (0x01<< 0) : 0));
+
+ cb->d_enable = cso->dither ? 1 : 0;
+
+ return (void *)cb;
+}
+
+static void
+nv20_blend_state_bind(struct pipe_context *pipe, void *blend)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->blend = (struct nv20_blend_state*)blend;
+
+ nv20->dirty |= NV20_NEW_BLEND;
+}
+
+static void
+nv20_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+
+static INLINE unsigned
+wrap_mode(unsigned wrap) {
+ unsigned ret;
+
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ ret = NV20TCL_TX_WRAP_S_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ ret = NV20TCL_TX_WRAP_S_MIRRORED_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ ret = NV20TCL_TX_WRAP_S_CLAMP_TO_EDGE;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ ret = NV20TCL_TX_WRAP_S_CLAMP_TO_BORDER;
+ break;
+ case PIPE_TEX_WRAP_CLAMP:
+ ret = NV20TCL_TX_WRAP_S_CLAMP;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ default:
+ NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+ ret = NV20TCL_TX_WRAP_S_REPEAT;
+ break;
+ }
+
+ return (ret >> NV20TCL_TX_WRAP_S_SHIFT);
+}
+
+static void *
+nv20_sampler_state_create(struct pipe_context *pipe,
+ const struct pipe_sampler_state *cso)
+{
+ struct nv20_sampler_state *ps;
+ uint32_t filter = 0;
+
+ ps = MALLOC(sizeof(struct nv20_sampler_state));
+
+ ps->wrap = ((wrap_mode(cso->wrap_s) << NV20TCL_TX_WRAP_S_SHIFT) |
+ (wrap_mode(cso->wrap_t) << NV20TCL_TX_WRAP_T_SHIFT));
+
+ ps->en = 0;
+ if (cso->max_anisotropy > 1.0) {
+ /* no idea, binary driver sets it, works without it.. meh.. */
+ ps->wrap |= (1 << 5);
+
+/* if (cso->max_anisotropy >= 8.0) {
+ ps->en |= NV20TCL_TX_ENABLE_ANISO_8X;
+ } else
+ if (cso->max_anisotropy >= 4.0) {
+ ps->en |= NV20TCL_TX_ENABLE_ANISO_4X;
+ } else {
+ ps->en |= NV20TCL_TX_ENABLE_ANISO_2X;
+ }*/
+ }
+
+ switch (cso->mag_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ filter |= NV20TCL_TX_FILTER_MAGNIFY_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ filter |= NV20TCL_TX_FILTER_MAGNIFY_NEAREST;
+ break;
+ }
+
+ switch (cso->min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |=
+ NV20TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV20TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV20TCL_TX_FILTER_MINIFY_LINEAR;
+ break;
+ }
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |=
+ NV20TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |=
+ NV20TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV20TCL_TX_FILTER_MINIFY_NEAREST;
+ break;
+ }
+ break;
+ }
+
+ ps->filt = filter;
+
+/* if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ switch (cso->compare_func) {
+ case PIPE_FUNC_NEVER:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NEVER;
+ break;
+ case PIPE_FUNC_GREATER:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GREATER;
+ break;
+ case PIPE_FUNC_EQUAL:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_EQUAL;
+ break;
+ case PIPE_FUNC_GEQUAL:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GEQUAL;
+ break;
+ case PIPE_FUNC_LESS:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LESS;
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NOTEQUAL;
+ break;
+ case PIPE_FUNC_LEQUAL:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LEQUAL;
+ break;
+ case PIPE_FUNC_ALWAYS:
+ ps->wrap |= NV10TCL_TX_WRAP_RCOMP_ALWAYS;
+ break;
+ default:
+ break;
+ }
+ }*/
+
+ ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) |
+ (float_to_ubyte(cso->border_color[0]) << 16) |
+ (float_to_ubyte(cso->border_color[1]) << 8) |
+ (float_to_ubyte(cso->border_color[2]) << 0));
+
+ return (void *)ps;
+}
+
+static void
+nv20_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv20->tex_sampler[unit] = sampler[unit];
+ nv20->dirty_samplers |= (1 << unit);
+ }
+}
+
+static void
+nv20_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void
+nv20_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+ struct pipe_texture **miptree)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv20->tex_miptree[unit] = (struct nv20_miptree *)miptree[unit];
+ nv20->dirty_samplers |= (1 << unit);
+ }
+}
+
+static void *
+nv20_rasterizer_state_create(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct nv20_rasterizer_state *rs;
+ int i;
+
+ /*XXX: ignored:
+ * light_twoside
+ * offset_cw/ccw -nohw
+ * scissor
+ * point_smooth -nohw
+ * multisample
+ * offset_units / offset_scale
+ */
+ rs = MALLOC(sizeof(struct nv20_rasterizer_state));
+
+ rs->templ = cso;
+
+ rs->shade_model = cso->flatshade ? NV20TCL_SHADE_MODEL_FLAT :
+ NV20TCL_SHADE_MODEL_SMOOTH;
+
+ rs->line_width = (unsigned char)(cso->line_width * 8.0) & 0xff;
+ rs->line_smooth_en = cso->line_smooth ? 1 : 0;
+
+ /* XXX: nv20 and nv25 different! */
+ rs->point_size = *(uint32_t*)&cso->point_size;
+
+ rs->poly_smooth_en = cso->poly_smooth ? 1 : 0;
+
+ if (cso->front_winding == PIPE_WINDING_CCW) {
+ rs->front_face = NV20TCL_FRONT_FACE_CCW;
+ rs->poly_mode_front = nvgl_polygon_mode(cso->fill_ccw);
+ rs->poly_mode_back = nvgl_polygon_mode(cso->fill_cw);
+ } else {
+ rs->front_face = NV20TCL_FRONT_FACE_CW;
+ rs->poly_mode_front = nvgl_polygon_mode(cso->fill_cw);
+ rs->poly_mode_back = nvgl_polygon_mode(cso->fill_ccw);
+ }
+
+ switch (cso->cull_mode) {
+ case PIPE_WINDING_CCW:
+ rs->cull_face_en = 1;
+ if (cso->front_winding == PIPE_WINDING_CCW)
+ rs->cull_face = NV20TCL_CULL_FACE_FRONT;
+ else
+ rs->cull_face = NV20TCL_CULL_FACE_BACK;
+ break;
+ case PIPE_WINDING_CW:
+ rs->cull_face_en = 1;
+ if (cso->front_winding == PIPE_WINDING_CW)
+ rs->cull_face = NV20TCL_CULL_FACE_FRONT;
+ else
+ rs->cull_face = NV20TCL_CULL_FACE_BACK;
+ break;
+ case PIPE_WINDING_BOTH:
+ rs->cull_face_en = 1;
+ rs->cull_face = NV20TCL_CULL_FACE_FRONT_AND_BACK;
+ break;
+ case PIPE_WINDING_NONE:
+ default:
+ rs->cull_face_en = 0;
+ rs->cull_face = 0;
+ break;
+ }
+
+ if (cso->point_sprite) {
+ rs->point_sprite = (1 << 0);
+ for (i = 0; i < 8; i++) {
+ if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE)
+ rs->point_sprite |= (1 << (8 + i));
+ }
+ } else {
+ rs->point_sprite = 0;
+ }
+
+ return (void *)rs;
+}
+
+static void
+nv20_rasterizer_state_bind(struct pipe_context *pipe, void *rast)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->rast = (struct nv20_rasterizer_state*)rast;
+
+ draw_set_rasterizer_state(nv20->draw, (nv20->rast ? nv20->rast->templ : NULL));
+
+ nv20->dirty |= NV20_NEW_RAST;
+}
+
+static void
+nv20_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+nv20_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct nv20_depth_stencil_alpha_state *hw;
+
+ hw = MALLOC(sizeof(struct nv20_depth_stencil_alpha_state));
+
+ hw->depth.func = nvgl_comparison_op(cso->depth.func);
+ hw->depth.write_enable = cso->depth.writemask ? 1 : 0;
+ hw->depth.test_enable = cso->depth.enabled ? 1 : 0;
+
+ hw->stencil.enable = cso->stencil[0].enabled ? 1 : 0;
+ hw->stencil.wmask = cso->stencil[0].writemask;
+ hw->stencil.func = nvgl_comparison_op(cso->stencil[0].func);
+ hw->stencil.ref = cso->stencil[0].ref_value;
+ hw->stencil.vmask = cso->stencil[0].valuemask;
+ hw->stencil.fail = nvgl_stencil_op(cso->stencil[0].fail_op);
+ hw->stencil.zfail = nvgl_stencil_op(cso->stencil[0].zfail_op);
+ hw->stencil.zpass = nvgl_stencil_op(cso->stencil[0].zpass_op);
+
+ hw->alpha.enabled = cso->alpha.enabled ? 1 : 0;
+ hw->alpha.func = nvgl_comparison_op(cso->alpha.func);
+ hw->alpha.ref = float_to_ubyte(cso->alpha.ref_value);
+
+ return (void *)hw;
+}
+
+static void
+nv20_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *dsa)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->dsa = (struct nv20_depth_stencil_alpha_state*)dsa;
+
+ nv20->dirty |= NV20_NEW_DSA;
+}
+
+static void
+nv20_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+nv20_vp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ return draw_create_vertex_shader(nv20->draw, templ);
+}
+
+static void
+nv20_vp_state_bind(struct pipe_context *pipe, void *shader)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ draw_bind_vertex_shader(nv20->draw, (struct draw_vertex_shader *) shader);
+
+ nv20->dirty |= NV20_NEW_VERTPROG;
+}
+
+static void
+nv20_vp_state_delete(struct pipe_context *pipe, void *shader)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ draw_delete_vertex_shader(nv20->draw, (struct draw_vertex_shader *) shader);
+}
+
+static void *
+nv20_fp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv20_fragment_program *fp;
+
+ fp = CALLOC(1, sizeof(struct nv20_fragment_program));
+ fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+
+ tgsi_scan_shader(cso->tokens, &fp->info);
+
+ return (void *)fp;
+}
+
+static void
+nv20_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ struct nv20_fragment_program *fp = hwcso;
+
+ nv20->fragprog.current = fp;
+ nv20->dirty |= NV20_NEW_FRAGPROG;
+}
+
+static void
+nv20_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ struct nv20_fragment_program *fp = hwcso;
+
+ nv20_fragprog_destroy(nv20, fp);
+ FREE((void*)fp->pipe.tokens);
+ FREE(fp);
+}
+
+static void
+nv20_set_blend_color(struct pipe_context *pipe,
+ const struct pipe_blend_color *bcol)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->blend_color = (struct pipe_blend_color*)bcol;
+
+ nv20->dirty |= NV20_NEW_BLENDCOL;
+}
+
+static void
+nv20_set_clip_state(struct pipe_context *pipe,
+ const struct pipe_clip_state *clip)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ draw_set_clip_state(nv20->draw, clip);
+}
+
+static void
+nv20_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+ const struct pipe_constant_buffer *buf )
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ struct pipe_screen *pscreen = pipe->screen;
+
+ assert(shader < PIPE_SHADER_TYPES);
+ assert(index == 0);
+
+ if (buf) {
+ void *mapped;
+ if (buf->buffer && buf->buffer->size &&
+ (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+ {
+ memcpy(nv20->constbuf[shader], mapped, buf->buffer->size);
+ nv20->constbuf_nr[shader] =
+ buf->buffer->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pscreen, buf->buffer);
+ }
+ }
+}
+
+static void
+nv20_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->framebuffer = (struct pipe_framebuffer_state*)fb;
+
+ nv20->dirty |= NV20_NEW_FRAMEBUFFER;
+}
+
+static void
+nv20_set_polygon_stipple(struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple)
+{
+ NOUVEAU_ERR("line stipple hahaha\n");
+}
+
+static void
+nv20_set_scissor_state(struct pipe_context *pipe,
+ const struct pipe_scissor_state *s)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->scissor = (struct pipe_scissor_state*)s;
+
+ nv20->dirty |= NV20_NEW_SCISSOR;
+}
+
+static void
+nv20_set_viewport_state(struct pipe_context *pipe,
+ const struct pipe_viewport_state *vpt)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->viewport = (struct pipe_viewport_state*)vpt;
+
+ draw_set_viewport_state(nv20->draw, nv20->viewport);
+
+ nv20->dirty |= NV20_NEW_VIEWPORT;
+}
+
+static void
+nv20_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_buffer *vb)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ memcpy(nv20->vtxbuf, vb, sizeof(*vb) * count);
+ nv20->dirty |= NV20_NEW_VTXARRAYS;
+
+ draw_set_vertex_buffers(nv20->draw, count, vb);
+}
+
+static void
+nv20_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_element *ve)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ memcpy(nv20->vtxelt, ve, sizeof(*ve) * count);
+ nv20->dirty |= NV20_NEW_VTXARRAYS;
+
+ draw_set_vertex_elements(nv20->draw, count, ve);
+}
+
+void
+nv20_init_state_functions(struct nv20_context *nv20)
+{
+ nv20->pipe.create_blend_state = nv20_blend_state_create;
+ nv20->pipe.bind_blend_state = nv20_blend_state_bind;
+ nv20->pipe.delete_blend_state = nv20_blend_state_delete;
+
+ nv20->pipe.create_sampler_state = nv20_sampler_state_create;
+ nv20->pipe.bind_sampler_states = nv20_sampler_state_bind;
+ nv20->pipe.delete_sampler_state = nv20_sampler_state_delete;
+ nv20->pipe.set_sampler_textures = nv20_set_sampler_texture;
+
+ nv20->pipe.create_rasterizer_state = nv20_rasterizer_state_create;
+ nv20->pipe.bind_rasterizer_state = nv20_rasterizer_state_bind;
+ nv20->pipe.delete_rasterizer_state = nv20_rasterizer_state_delete;
+
+ nv20->pipe.create_depth_stencil_alpha_state =
+ nv20_depth_stencil_alpha_state_create;
+ nv20->pipe.bind_depth_stencil_alpha_state =
+ nv20_depth_stencil_alpha_state_bind;
+ nv20->pipe.delete_depth_stencil_alpha_state =
+ nv20_depth_stencil_alpha_state_delete;
+
+ nv20->pipe.create_vs_state = nv20_vp_state_create;
+ nv20->pipe.bind_vs_state = nv20_vp_state_bind;
+ nv20->pipe.delete_vs_state = nv20_vp_state_delete;
+
+ nv20->pipe.create_fs_state = nv20_fp_state_create;
+ nv20->pipe.bind_fs_state = nv20_fp_state_bind;
+ nv20->pipe.delete_fs_state = nv20_fp_state_delete;
+
+ nv20->pipe.set_blend_color = nv20_set_blend_color;
+ nv20->pipe.set_clip_state = nv20_set_clip_state;
+ nv20->pipe.set_constant_buffer = nv20_set_constant_buffer;
+ nv20->pipe.set_framebuffer_state = nv20_set_framebuffer_state;
+ nv20->pipe.set_polygon_stipple = nv20_set_polygon_stipple;
+ nv20->pipe.set_scissor_state = nv20_set_scissor_state;
+ nv20->pipe.set_viewport_state = nv20_set_viewport_state;
+
+ nv20->pipe.set_vertex_buffers = nv20_set_vertex_buffers;
+ nv20->pipe.set_vertex_elements = nv20_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_state.h b/src/gallium/drivers/nv20/nv20_state.h
new file mode 100644
index 0000000000..34f402fdcb
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_state.h
@@ -0,0 +1,139 @@
+#ifndef __NV20_STATE_H__
+#define __NV20_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+
+struct nv20_blend_state {
+ uint32_t b_enable;
+ uint32_t b_srcfunc;
+ uint32_t b_dstfunc;
+
+ uint32_t c_mask;
+
+ uint32_t d_enable;
+};
+
+struct nv20_sampler_state {
+ uint32_t wrap;
+ uint32_t en;
+ uint32_t filt;
+ uint32_t bcol;
+};
+
+struct nv20_rasterizer_state {
+ uint32_t shade_model;
+
+ uint32_t line_width;
+ uint32_t line_smooth_en;
+
+ uint32_t point_size;
+
+ uint32_t poly_smooth_en;
+
+ uint32_t poly_mode_front;
+ uint32_t poly_mode_back;
+
+ uint32_t front_face;
+ uint32_t cull_face;
+ uint32_t cull_face_en;
+
+ uint32_t point_sprite;
+
+ const struct pipe_rasterizer_state *templ;
+};
+
+struct nv20_vertex_program_exec {
+ uint32_t data[4];
+ boolean has_branch_offset;
+ int const_index;
+};
+
+struct nv20_vertex_program_data {
+ int index; /* immediates == -1 */
+ float value[4];
+};
+
+struct nv20_vertex_program {
+ const struct pipe_shader_state *pipe;
+
+ boolean translated;
+ struct nv20_vertex_program_exec *insns;
+ unsigned nr_insns;
+ struct nv20_vertex_program_data *consts;
+ unsigned nr_consts;
+
+ struct nouveau_resource *exec;
+ unsigned exec_start;
+ struct nouveau_resource *data;
+ unsigned data_start;
+ unsigned data_start_min;
+
+ uint32_t ir;
+ uint32_t or;
+};
+
+struct nv20_fragment_program_data {
+ unsigned offset;
+ unsigned index;
+};
+
+struct nv20_fragment_program {
+ struct pipe_shader_state pipe;
+ struct tgsi_shader_info info;
+
+ boolean translated;
+ boolean on_hw;
+ unsigned samplers;
+
+ uint32_t *insn;
+ int insn_len;
+
+ struct nv20_fragment_program_data *consts;
+ unsigned nr_consts;
+
+ struct pipe_buffer *buffer;
+
+ uint32_t fp_control;
+ uint32_t fp_reg_control;
+};
+
+
+struct nv20_depth_stencil_alpha_state {
+ struct {
+ uint32_t func;
+ uint32_t write_enable;
+ uint32_t test_enable;
+ } depth;
+
+ struct {
+ uint32_t enable;
+ uint32_t wmask;
+ uint32_t func;
+ uint32_t ref;
+ uint32_t vmask;
+ uint32_t fail;
+ uint32_t zfail;
+ uint32_t zpass;
+ } stencil;
+
+ struct {
+ uint32_t enabled;
+ uint32_t func;
+ uint32_t ref;
+ } alpha;
+};
+
+struct nv20_miptree {
+ struct pipe_texture base;
+
+ struct pipe_buffer *buffer;
+ uint total_size;
+
+ struct {
+ uint pitch;
+ uint *image_offset;
+ } level[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+#endif
diff --git a/src/gallium/drivers/nv20/nv20_state_emit.c b/src/gallium/drivers/nv20/nv20_state_emit.c
new file mode 100644
index 0000000000..4042f46d05
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_state_emit.c
@@ -0,0 +1,396 @@
+#include "nv20_context.h"
+#include "nv20_state.h"
+#include "draw/draw_context.h"
+
+static void nv20_state_emit_blend(struct nv20_context* nv20)
+{
+ struct nv20_blend_state *b = nv20->blend;
+
+ BEGIN_RING(kelvin, NV20TCL_DITHER_ENABLE, 1);
+ OUT_RING (b->d_enable);
+
+ BEGIN_RING(kelvin, NV20TCL_BLEND_FUNC_ENABLE, 1);
+ OUT_RING (b->b_enable);
+
+ BEGIN_RING(kelvin, NV20TCL_BLEND_FUNC_SRC, 2);
+ OUT_RING (b->b_srcfunc);
+ OUT_RING (b->b_dstfunc);
+
+ BEGIN_RING(kelvin, NV20TCL_COLOR_MASK, 1);
+ OUT_RING (b->c_mask);
+}
+
+static void nv20_state_emit_blend_color(struct nv20_context* nv20)
+{
+ struct pipe_blend_color *c = nv20->blend_color;
+
+ BEGIN_RING(kelvin, NV20TCL_BLEND_COLOR, 1);
+ OUT_RING ((float_to_ubyte(c->color[3]) << 24)|
+ (float_to_ubyte(c->color[0]) << 16)|
+ (float_to_ubyte(c->color[1]) << 8) |
+ (float_to_ubyte(c->color[2]) << 0));
+}
+
+static void nv20_state_emit_rast(struct nv20_context* nv20)
+{
+ struct nv20_rasterizer_state *r = nv20->rast;
+
+ BEGIN_RING(kelvin, NV20TCL_SHADE_MODEL, 2);
+ OUT_RING (r->shade_model);
+ OUT_RING (r->line_width);
+
+
+ BEGIN_RING(kelvin, NV20TCL_POINT_SIZE, 1);
+ OUT_RING (r->point_size);
+
+ BEGIN_RING(kelvin, NV20TCL_POLYGON_MODE_FRONT, 2);
+ OUT_RING (r->poly_mode_front);
+ OUT_RING (r->poly_mode_back);
+
+
+ BEGIN_RING(kelvin, NV20TCL_CULL_FACE, 2);
+ OUT_RING (r->cull_face);
+ OUT_RING (r->front_face);
+
+ BEGIN_RING(kelvin, NV20TCL_LINE_SMOOTH_ENABLE, 2);
+ OUT_RING (r->line_smooth_en);
+ OUT_RING (r->poly_smooth_en);
+
+ BEGIN_RING(kelvin, NV20TCL_CULL_FACE_ENABLE, 1);
+ OUT_RING (r->cull_face_en);
+}
+
+static void nv20_state_emit_dsa(struct nv20_context* nv20)
+{
+ struct nv20_depth_stencil_alpha_state *d = nv20->dsa;
+
+ BEGIN_RING(kelvin, NV20TCL_DEPTH_FUNC, 1);
+ OUT_RING (d->depth.func);
+
+ BEGIN_RING(kelvin, NV20TCL_DEPTH_WRITE_ENABLE, 1);
+ OUT_RING (d->depth.write_enable);
+
+ BEGIN_RING(kelvin, NV20TCL_DEPTH_TEST_ENABLE, 1);
+ OUT_RING (d->depth.test_enable);
+
+ BEGIN_RING(kelvin, NV20TCL_DEPTH_UNK17D8, 1);
+ OUT_RING (1);
+
+#if 0
+ BEGIN_RING(kelvin, NV20TCL_STENCIL_ENABLE, 1);
+ OUT_RING (d->stencil.enable);
+ BEGIN_RING(kelvin, NV20TCL_STENCIL_MASK, 7);
+ OUT_RINGp ((uint32_t *)&(d->stencil.wmask), 7);
+#endif
+
+ BEGIN_RING(kelvin, NV20TCL_ALPHA_FUNC_ENABLE, 1);
+ OUT_RING (d->alpha.enabled);
+
+ BEGIN_RING(kelvin, NV20TCL_ALPHA_FUNC_FUNC, 1);
+ OUT_RING (d->alpha.func);
+
+ BEGIN_RING(kelvin, NV20TCL_ALPHA_FUNC_REF, 1);
+ OUT_RING (d->alpha.ref);
+}
+
+static void nv20_state_emit_viewport(struct nv20_context* nv20)
+{
+}
+
+static void nv20_state_emit_scissor(struct nv20_context* nv20)
+{
+ /* NV20TCL_SCISSOR_* is probably a software method */
+/* struct pipe_scissor_state *s = nv20->scissor;
+ BEGIN_RING(kelvin, NV20TCL_SCISSOR_HORIZ, 2);
+ OUT_RING (((s->maxx - s->minx) << 16) | s->minx);
+ OUT_RING (((s->maxy - s->miny) << 16) | s->miny);*/
+}
+
+static void nv20_state_emit_framebuffer(struct nv20_context* nv20)
+{
+ struct pipe_framebuffer_state* fb = nv20->framebuffer;
+ struct nv04_surface *rt, *zeta = NULL;
+ uint32_t rt_format, w, h;
+ int colour_format = 0, zeta_format = 0;
+ struct nv20_miptree *nv20mt = 0;
+
+ w = fb->cbufs[0]->width;
+ h = fb->cbufs[0]->height;
+ colour_format = fb->cbufs[0]->format;
+ rt = (struct nv04_surface *)fb->cbufs[0];
+
+ if (fb->zsbuf) {
+ if (colour_format) {
+ assert(w == fb->zsbuf->width);
+ assert(h == fb->zsbuf->height);
+ } else {
+ w = fb->zsbuf->width;
+ h = fb->zsbuf->height;
+ }
+
+ zeta_format = fb->zsbuf->format;
+ zeta = (struct nv04_surface *)fb->zsbuf;
+ }
+
+ rt_format = NV20TCL_RT_FORMAT_TYPE_LINEAR | 0x20;
+
+ switch (colour_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case 0:
+ rt_format |= NV20TCL_RT_FORMAT_COLOR_A8R8G8B8;
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ rt_format |= NV20TCL_RT_FORMAT_COLOR_R5G6B5;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (zeta) {
+ BEGIN_RING(kelvin, NV20TCL_RT_PITCH, 1);
+ OUT_RING (rt->pitch | (zeta->pitch << 16));
+ } else {
+ BEGIN_RING(kelvin, NV20TCL_RT_PITCH, 1);
+ OUT_RING (rt->pitch | (rt->pitch << 16));
+ }
+
+ nv20mt = (struct nv20_miptree *)rt->base.texture;
+ nv20->rt[0] = nv20mt->buffer;
+
+ if (zeta_format)
+ {
+ nv20mt = (struct nv20_miptree *)zeta->base.texture;
+ nv20->zeta = nv20mt->buffer;
+ }
+
+ BEGIN_RING(kelvin, NV20TCL_RT_HORIZ, 3);
+ OUT_RING ((w << 16) | 0);
+ OUT_RING ((h << 16) | 0); /*NV20TCL_RT_VERT */
+ OUT_RING (rt_format); /* NV20TCL_RT_FORMAT */
+ BEGIN_RING(kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+ OUT_RING (((w - 1) << 16) | 0);
+ OUT_RING (((h - 1) << 16) | 0);
+}
+
+static void nv20_vertex_layout(struct nv20_context *nv20)
+{
+ struct nv20_fragment_program *fp = nv20->fragprog.current;
+ struct draw_context *dc = nv20->draw;
+ int src;
+ int i;
+ struct vertex_info *vinfo = &nv20->vertex_info;
+ const enum interp_mode colorInterp = INTERP_LINEAR;
+ boolean colors[2] = { FALSE };
+ boolean generics[12] = { FALSE };
+ boolean fog = FALSE;
+
+ memset(vinfo, 0, sizeof(*vinfo));
+
+ /*
+ * Assumed NV20 hardware vertex attribute order:
+ * 0 position, 1 ?, 2 ?, 3 col0,
+ * 4 col1?, 5 ?, 6 ?, 7 ?,
+ * 8 ?, 9 tex0, 10 tex1, 11 tex2,
+ * 12 tex3, 13 ?, 14 ?, 15 ?
+ * unaccounted: wgh, nor, fog
+ * There are total 16 attrs.
+ * vinfo->hwfmt[0] has a used-bit corresponding to each of these.
+ * relation to TGSI_SEMANTIC_*:
+ * - POSITION: position (always used)
+ * - COLOR: col1, col0
+ * - GENERIC: tex3, tex2, tex1, tex0, normal, weight
+ * - FOG: fog
+ */
+
+ for (i = 0; i < fp->info.num_inputs; i++) {
+ int isn = fp->info.input_semantic_name[i];
+ int isi = fp->info.input_semantic_index[i];
+ switch (isn) {
+ case TGSI_SEMANTIC_POSITION:
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ assert(isi < 2);
+ colors[isi] = TRUE;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ assert(isi < 12);
+ generics[isi] = TRUE;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ fog = TRUE;
+ break;
+ default:
+ assert(0 && "unknown input_semantic_name");
+ }
+ }
+
+ /* always do position */ {
+ src = draw_find_vs_output(dc, TGSI_SEMANTIC_POSITION, 0);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR, src);
+ vinfo->hwfmt[0] |= (1 << 0);
+ }
+
+ /* two unnamed generics */
+ for (i = 4; i < 6; i++) {
+ if (!generics[i])
+ continue;
+ src = draw_find_vs_output(dc, TGSI_SEMANTIC_GENERIC, i);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ vinfo->hwfmt[0] |= (1 << (i - 3));
+ }
+
+ if (colors[0]) {
+ src = draw_find_vs_output(dc, TGSI_SEMANTIC_COLOR, 0);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
+ vinfo->hwfmt[0] |= (1 << 3);
+ }
+
+ if (colors[1]) {
+ src = draw_find_vs_output(dc, TGSI_SEMANTIC_COLOR, 1);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
+ vinfo->hwfmt[0] |= (1 << 4);
+ }
+
+ /* four unnamed generics */
+ for (i = 6; i < 10; i++) {
+ if (!generics[i])
+ continue;
+ src = draw_find_vs_output(dc, TGSI_SEMANTIC_GENERIC, i);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ vinfo->hwfmt[0] |= (1 << (i - 1));
+ }
+
+ /* tex0, tex1, tex2, tex3 */
+ for (i = 0; i < 4; i++) {
+ if (!generics[i])
+ continue;
+ src = draw_find_vs_output(dc, TGSI_SEMANTIC_GENERIC, i);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ vinfo->hwfmt[0] |= (1 << (i + 9));
+ }
+
+ /* two unnamed generics */
+ for (i = 10; i < 12; i++) {
+ if (!generics[i])
+ continue;
+ src = draw_find_vs_output(dc, TGSI_SEMANTIC_GENERIC, i);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ vinfo->hwfmt[0] |= (1 << (i + 3));
+ }
+
+ if (fog) {
+ src = draw_find_vs_output(dc, TGSI_SEMANTIC_FOG, 0);
+ draw_emit_vertex_attr(vinfo, EMIT_1F, INTERP_PERSPECTIVE, src);
+ vinfo->hwfmt[0] |= (1 << 15);
+ }
+
+ draw_compute_vertex_size(vinfo);
+}
+
+void
+nv20_emit_hw_state(struct nv20_context *nv20)
+{
+ int i;
+
+ if (nv20->dirty & NV20_NEW_VERTPROG) {
+ //nv20_vertprog_bind(nv20, nv20->vertprog.current);
+ nv20->dirty &= ~NV20_NEW_VERTPROG;
+ }
+
+ if (nv20->dirty & NV20_NEW_FRAGPROG) {
+ nv20_fragprog_bind(nv20, nv20->fragprog.current);
+ /*XXX: clear NV20_NEW_FRAGPROG if no new program uploaded */
+ nv20->dirty_samplers |= (1<<10);
+ nv20->dirty_samplers = 0;
+ }
+
+ if (nv20->dirty_samplers || (nv20->dirty & NV20_NEW_FRAGPROG)) {
+ nv20_fragtex_bind(nv20);
+ nv20->dirty &= ~NV20_NEW_FRAGPROG;
+ }
+
+ if (nv20->dirty & NV20_NEW_VTXARRAYS) {
+ nv20->dirty &= ~NV20_NEW_VTXARRAYS;
+ nv20_vertex_layout(nv20);
+ nv20_vtxbuf_bind(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_BLEND) {
+ nv20->dirty &= ~NV20_NEW_BLEND;
+ nv20_state_emit_blend(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_BLENDCOL) {
+ nv20->dirty &= ~NV20_NEW_BLENDCOL;
+ nv20_state_emit_blend_color(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_RAST) {
+ nv20->dirty &= ~NV20_NEW_RAST;
+ nv20_state_emit_rast(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_DSA) {
+ nv20->dirty &= ~NV20_NEW_DSA;
+ nv20_state_emit_dsa(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_VIEWPORT) {
+ nv20->dirty &= ~NV20_NEW_VIEWPORT;
+ nv20_state_emit_viewport(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_SCISSOR) {
+ nv20->dirty &= ~NV20_NEW_SCISSOR;
+ nv20_state_emit_scissor(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_FRAMEBUFFER) {
+ nv20->dirty &= ~NV20_NEW_FRAMEBUFFER;
+ nv20_state_emit_framebuffer(nv20);
+ }
+
+ /* Emit relocs for every referenced buffer.
+ * This is to ensure the bufmgr has an accurate idea of how
+ * the buffer is used. This isn't very efficient, but we don't
+ * seem to take a significant performance hit. Will be improved
+ * at some point. Vertex arrays are emitted by nv20_vbo.c
+ */
+
+ /* Render target */
+ BEGIN_RING(kelvin, NV20TCL_DMA_COLOR, 1);
+ OUT_RELOCo(nv20->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(kelvin, NV20TCL_COLOR_OFFSET, 1);
+ OUT_RELOCl(nv20->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ if (nv20->zeta) {
+ BEGIN_RING(kelvin, NV20TCL_DMA_ZETA, 1);
+ OUT_RELOCo(nv20->zeta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(kelvin, NV20TCL_ZETA_OFFSET, 1);
+ OUT_RELOCl(nv20->zeta, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ /* XXX for when we allocate LMA on nv17 */
+/* BEGIN_RING(kelvin, NV10TCL_LMA_DEPTH_BUFFER_OFFSET, 1);
+ OUT_RELOCl(nv20->zeta + lma_offset);*/
+ }
+
+ /* Vertex buffer */
+ BEGIN_RING(kelvin, NV20TCL_DMA_VTXBUF0, 1);
+ OUT_RELOCo(nv20->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(kelvin, NV20TCL_COLOR_OFFSET, 1);
+ OUT_RELOCl(nv20->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ /* Texture images */
+ for (i = 0; i < 2; i++) {
+ if (!(nv20->fp_samplers & (1 << i)))
+ continue;
+ BEGIN_RING(kelvin, NV20TCL_TX_OFFSET(i), 1);
+ OUT_RELOCl(nv20->tex[i].buffer, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ BEGIN_RING(kelvin, NV20TCL_TX_FORMAT(i), 1);
+ OUT_RELOCd(nv20->tex[i].buffer, nv20->tex[i].format,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD |
+ NOUVEAU_BO_OR, NV20TCL_TX_FORMAT_DMA0,
+ NV20TCL_TX_FORMAT_DMA1);
+ }
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_surface.c b/src/gallium/drivers/nv20/nv20_surface.c
new file mode 100644
index 0000000000..4224bdd6af
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_surface.c
@@ -0,0 +1,63 @@
+
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "nv20_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+
+static void
+nv20_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ struct nv04_surface_2d *eng2d = nv20->screen->eng2d;
+
+ eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
+}
+
+static void
+nv20_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+ unsigned destx, unsigned desty, unsigned width,
+ unsigned height, unsigned value)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ struct nv04_surface_2d *eng2d = nv20->screen->eng2d;
+
+ eng2d->fill(eng2d, dest, destx, desty, width, height, value);
+}
+
+void
+nv20_init_surface_functions(struct nv20_context *nv20)
+{
+ nv20->pipe.surface_copy = nv20_surface_copy;
+ nv20->pipe.surface_fill = nv20_surface_fill;
+}
diff --git a/src/gallium/drivers/nv20/nv20_transfer.c b/src/gallium/drivers/nv20/nv20_transfer.c
new file mode 100644
index 0000000000..5018995596
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_transfer.c
@@ -0,0 +1,195 @@
+#include <pipe/p_state.h>
+#include <pipe/p_defines.h>
+#include <pipe/p_inlines.h>
+#include <util/u_memory.h>
+#include <nouveau/nouveau_winsys.h>
+#include "nv20_context.h"
+#include "nv20_screen.h"
+#include "nv20_state.h"
+
+struct nv20_transfer {
+ struct pipe_transfer base;
+ struct pipe_surface *surface;
+ bool direct;
+};
+
+static unsigned nv20_usage_tx_to_buf(unsigned tx_usage)
+{
+ switch (tx_usage) {
+ case PIPE_TRANSFER_READ:
+ return PIPE_BUFFER_USAGE_CPU_READ;
+ case PIPE_TRANSFER_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_WRITE;
+ case PIPE_TRANSFER_READ_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static void
+nv20_compatible_transfer_tex(struct pipe_texture *pt, unsigned level,
+ struct pipe_texture *template)
+{
+ memset(template, 0, sizeof(struct pipe_texture));
+ template->target = pt->target;
+ template->format = pt->format;
+ template->width[0] = pt->width[level];
+ template->height[0] = pt->height[level];
+ template->depth[0] = 1;
+ template->block = pt->block;
+ template->nblocksx[0] = pt->nblocksx[level];
+ template->nblocksy[0] = pt->nblocksx[level];
+ template->last_level = 0;
+ template->nr_samples = pt->nr_samples;
+
+ template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC |
+ NOUVEAU_TEXTURE_USAGE_LINEAR;
+}
+
+static struct pipe_transfer *
+nv20_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct nv20_miptree *mt = (struct nv20_miptree *)pt;
+ struct nv20_transfer *tx;
+ struct pipe_texture tx_tex_template, *tx_tex;
+
+ tx = CALLOC_STRUCT(nv20_transfer);
+ if (!tx)
+ return NULL;
+
+ pipe_texture_reference(&tx->base.texture, pt);
+ tx->base.format = pt->format;
+ tx->base.x = x;
+ tx->base.y = y;
+ tx->base.width = w;
+ tx->base.height = h;
+ tx->base.block = pt->block;
+ tx->base.nblocksx = pt->nblocksx[level];
+ tx->base.nblocksy = pt->nblocksy[level];
+ tx->base.stride = mt->level[level].pitch;
+ tx->base.usage = usage;
+ tx->base.face = face;
+ tx->base.level = level;
+ tx->base.zslice = zslice;
+
+ /* Direct access to texture */
+ if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC ||
+ debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) &&
+ pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)
+ {
+ tx->direct = true;
+ tx->surface = pscreen->get_tex_surface(pscreen, pt,
+ 0, 0, 0,
+ nv20_usage_tx_to_buf(usage));
+ return &tx->base;
+ }
+
+ tx->direct = false;
+
+ nv20_compatible_transfer_tex(pt, level, &tx_tex_template);
+
+ tx_tex = pscreen->texture_create(pscreen, &tx_tex_template);
+ if (!tx_tex)
+ {
+ FREE(tx);
+ return NULL;
+ }
+
+ tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
+ face, level, zslice,
+ nv20_usage_tx_to_buf(usage));
+
+ pipe_texture_reference(&tx_tex, NULL);
+
+ if (!tx->surface)
+ {
+ pipe_surface_reference(&tx->surface, NULL);
+ FREE(tx);
+ return NULL;
+ }
+
+ if (usage != PIPE_TRANSFER_WRITE) {
+ struct nv20_screen *nvscreen = nv20_screen(pscreen);
+ struct pipe_surface *src;
+
+ src = pscreen->get_tex_surface(pscreen, pt,
+ face, level, zslice,
+ PIPE_BUFFER_USAGE_GPU_READ);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ /* TODO: Check if SIFM can un-swizzle */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ tx->surface, 0, 0,
+ src, 0, 0,
+ src->width, src->height);
+
+ pipe_surface_reference(&src, NULL);
+ }
+
+ return &tx->base;
+}
+
+static void
+nv20_transfer_del(struct pipe_transfer *ptx)
+{
+ struct nv20_transfer *tx = (struct nv20_transfer *)ptx;
+
+ if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) {
+ struct pipe_screen *pscreen = ptx->texture->screen;
+ struct nv20_screen *nvscreen = nv20_screen(pscreen);
+ struct pipe_surface *dst;
+
+ dst = pscreen->get_tex_surface(pscreen, ptx->texture,
+ ptx->face, ptx->level, ptx->zslice,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ dst, 0, 0,
+ tx->surface, 0, 0,
+ dst->width, dst->height);
+
+ pipe_surface_reference(&dst, NULL);
+ }
+
+ pipe_surface_reference(&tx->surface, NULL);
+ pipe_texture_reference(&ptx->texture, NULL);
+ FREE(ptx);
+}
+
+static void *
+nv20_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv20_transfer *tx = (struct nv20_transfer *)ptx;
+ struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
+ struct nv20_miptree *mt = (struct nv20_miptree *)tx->surface->texture;
+ void *map = pipe_buffer_map(pscreen, mt->buffer,
+ nv20_usage_tx_to_buf(ptx->usage));
+
+ return map + ns->base.offset +
+ ptx->y * ns->pitch + ptx->x * ptx->block.size;
+}
+
+static void
+nv20_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv20_transfer *tx = (struct nv20_transfer *)ptx;
+ struct nv20_miptree *mt = (struct nv20_miptree *)tx->surface->texture;
+
+ pipe_buffer_unmap(pscreen, mt->buffer);
+}
+
+void
+nv20_screen_init_transfer_functions(struct pipe_screen *pscreen)
+{
+ pscreen->get_tex_transfer = nv20_transfer_new;
+ pscreen->tex_transfer_destroy = nv20_transfer_del;
+ pscreen->transfer_map = nv20_transfer_map;
+ pscreen->transfer_unmap = nv20_transfer_unmap;
+}
diff --git a/src/gallium/drivers/nv20/nv20_vbo.c b/src/gallium/drivers/nv20/nv20_vbo.c
new file mode 100644
index 0000000000..84d7db6c5e
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_vbo.c
@@ -0,0 +1,80 @@
+#include "draw/draw_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "nv20_context.h"
+#include "nv20_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+
+boolean nv20_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count)
+{
+ struct pipe_screen *pscreen = pipe->screen;
+ struct nv20_context *nv20 = nv20_context( pipe );
+ struct draw_context *draw = nv20->draw;
+ unsigned i;
+
+ nv20_emit_hw_state(nv20);
+
+ /*
+ * Map vertex buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (nv20->vtxbuf[i].buffer) {
+ void *buf
+ = pipe_buffer_map(pscreen,
+ nv20->vtxbuf[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_vertex_buffer(draw, i, buf);
+ }
+ }
+ /* Map index buffer, if present */
+ if (indexBuffer) {
+ void *mapped_indexes
+ = pipe_buffer_map(pscreen, indexBuffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes);
+ }
+ else {
+ /* no index/element buffer */
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+ draw_set_mapped_constant_buffer(draw,
+ nv20->constbuf[PIPE_SHADER_VERTEX],
+ nv20->constbuf_nr[PIPE_SHADER_VERTEX]);
+
+ /* draw! */
+ draw_arrays(nv20->draw, prim, start, count);
+
+ /*
+ * unmap vertex/index buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (nv20->vtxbuf[i].buffer) {
+ pipe_buffer_unmap(pscreen, nv20->vtxbuf[i].buffer);
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ }
+ }
+ if (indexBuffer) {
+ pipe_buffer_unmap(pscreen, indexBuffer);
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+ draw_flush(nv20->draw);
+ return TRUE;
+}
+
+boolean nv20_draw_arrays( struct pipe_context *pipe,
+ unsigned prim, unsigned start, unsigned count)
+{
+ return nv20_draw_elements(pipe, NULL, 0, prim, start, count);
+}
+
+
+
diff --git a/src/gallium/drivers/nv20/nv20_vertprog.c b/src/gallium/drivers/nv20/nv20_vertprog.c
new file mode 100644
index 0000000000..388245ecb0
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_vertprog.c
@@ -0,0 +1,838 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "nv20_context.h"
+#include "nv20_state.h"
+
+/* TODO (at least...):
+ * 1. Indexed consts + ARL
+ * 2. Arb. swz/negation
+ * 3. NV_vp11, NV_vp2, NV_vp3 features
+ * - extra arith opcodes
+ * - branching
+ * - texture sampling
+ * - indexed attribs
+ * - indexed results
+ * 4. bugs
+ */
+
+#define SWZ_X 0
+#define SWZ_Y 1
+#define SWZ_Z 2
+#define SWZ_W 3
+#define MASK_X 8
+#define MASK_Y 4
+#define MASK_Z 2
+#define MASK_W 1
+#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
+#define DEF_SCALE 0
+#define DEF_CTEST 0
+#include "nv20_shader.h"
+
+#define swz(s,x,y,z,w) nv20_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv20_sr_neg((s))
+#define abs(s) nv20_sr_abs((s))
+
+struct nv20_vpc {
+ struct nv20_vertex_program *vp;
+
+ struct nv20_vertex_program_exec *vpi;
+
+ unsigned output_map[PIPE_MAX_SHADER_OUTPUTS];
+
+ int high_temp;
+ int temp_temp_count;
+
+ struct nv20_sreg *imm;
+ unsigned nr_imm;
+};
+
+static struct nv20_sreg
+temp(struct nv20_vpc *vpc)
+{
+ int idx;
+
+ idx = vpc->temp_temp_count++;
+ idx += vpc->high_temp + 1;
+ return nv20_sr(NV30SR_TEMP, idx);
+}
+
+static struct nv20_sreg
+constant(struct nv20_vpc *vpc, int pipe, float x, float y, float z, float w)
+{
+ struct nv20_vertex_program *vp = vpc->vp;
+ struct nv20_vertex_program_data *vpd;
+ int idx;
+
+ if (pipe >= 0) {
+ for (idx = 0; idx < vp->nr_consts; idx++) {
+ if (vp->consts[idx].index == pipe)
+ return nv20_sr(NV30SR_CONST, idx);
+ }
+ }
+
+ idx = vp->nr_consts++;
+ vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts);
+ vpd = &vp->consts[idx];
+
+ vpd->index = pipe;
+ vpd->value[0] = x;
+ vpd->value[1] = y;
+ vpd->value[2] = z;
+ vpd->value[3] = w;
+ return nv20_sr(NV30SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+ nv20_vp_arith((cc), (s), NV30_VP_INST_##o, (d), (m), (s0), (s1), (s2))
+
+static void
+emit_src(struct nv20_vpc *vpc, uint32_t *hw, int pos, struct nv20_sreg src)
+{
+ struct nv20_vertex_program *vp = vpc->vp;
+ uint32_t sr = 0;
+
+ switch (src.type) {
+ case NV30SR_TEMP:
+ sr |= (NV30_VP_SRC_REG_TYPE_TEMP << NV30_VP_SRC_REG_TYPE_SHIFT);
+ sr |= (src.index << NV30_VP_SRC_TEMP_SRC_SHIFT);
+ break;
+ case NV30SR_INPUT:
+ sr |= (NV30_VP_SRC_REG_TYPE_INPUT <<
+ NV30_VP_SRC_REG_TYPE_SHIFT);
+ vp->ir |= (1 << src.index);
+ hw[1] |= (src.index << NV30_VP_INST_INPUT_SRC_SHIFT);
+ break;
+ case NV30SR_CONST:
+ sr |= (NV30_VP_SRC_REG_TYPE_CONST <<
+ NV30_VP_SRC_REG_TYPE_SHIFT);
+ assert(vpc->vpi->const_index == -1 ||
+ vpc->vpi->const_index == src.index);
+ vpc->vpi->const_index = src.index;
+ break;
+ case NV30SR_NONE:
+ sr |= (NV30_VP_SRC_REG_TYPE_INPUT <<
+ NV30_VP_SRC_REG_TYPE_SHIFT);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (src.negate)
+ sr |= NV30_VP_SRC_NEGATE;
+
+ if (src.abs)
+ hw[0] |= (1 << (21 + pos));
+
+ sr |= ((src.swz[0] << NV30_VP_SRC_SWZ_X_SHIFT) |
+ (src.swz[1] << NV30_VP_SRC_SWZ_Y_SHIFT) |
+ (src.swz[2] << NV30_VP_SRC_SWZ_Z_SHIFT) |
+ (src.swz[3] << NV30_VP_SRC_SWZ_W_SHIFT));
+
+/*
+ * |VVV|
+ * d�.�b
+ * \u/
+ *
+ */
+
+ switch (pos) {
+ case 0:
+ hw[1] |= ((sr & NV30_VP_SRC0_HIGH_MASK) >>
+ NV30_VP_SRC0_HIGH_SHIFT) << NV30_VP_INST_SRC0H_SHIFT;
+ hw[2] |= (sr & NV30_VP_SRC0_LOW_MASK) <<
+ NV30_VP_INST_SRC0L_SHIFT;
+ break;
+ case 1:
+ hw[2] |= sr << NV30_VP_INST_SRC1_SHIFT;
+ break;
+ case 2:
+ hw[2] |= ((sr & NV30_VP_SRC2_HIGH_MASK) >>
+ NV30_VP_SRC2_HIGH_SHIFT) << NV30_VP_INST_SRC2H_SHIFT;
+ hw[3] |= (sr & NV30_VP_SRC2_LOW_MASK) <<
+ NV30_VP_INST_SRC2L_SHIFT;
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+emit_dst(struct nv20_vpc *vpc, uint32_t *hw, int slot, struct nv20_sreg dst)
+{
+ struct nv20_vertex_program *vp = vpc->vp;
+
+ switch (dst.type) {
+ case NV30SR_TEMP:
+ hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT);
+ break;
+ case NV30SR_OUTPUT:
+ switch (dst.index) {
+ case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break;
+ case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break;
+ case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break;
+ case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break;
+ case NV30_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break;
+ case NV30_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break;
+ case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break;
+ case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break;
+ case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break;
+ case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break;
+ case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break;
+ case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break;
+ case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break;
+ case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break;
+ default:
+ break;
+ }
+
+ hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT);
+ hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20);
+
+ /*XXX: no way this is entirely correct, someone needs to
+ * figure out what exactly it is.
+ */
+ hw[3] |= 0x800;
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+nv20_vp_arith(struct nv20_vpc *vpc, int slot, int op,
+ struct nv20_sreg dst, int mask,
+ struct nv20_sreg s0, struct nv20_sreg s1,
+ struct nv20_sreg s2)
+{
+ struct nv20_vertex_program *vp = vpc->vp;
+ uint32_t *hw;
+
+ vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi));
+ vpc->vpi = &vp->insns[vp->nr_insns - 1];
+ memset(vpc->vpi, 0, sizeof(*vpc->vpi));
+ vpc->vpi->const_index = -1;
+
+ hw = vpc->vpi->data;
+
+ hw[0] |= (NV30_VP_INST_COND_TR << NV30_VP_INST_COND_SHIFT);
+ hw[0] |= ((0 << NV30_VP_INST_COND_SWZ_X_SHIFT) |
+ (1 << NV30_VP_INST_COND_SWZ_Y_SHIFT) |
+ (2 << NV30_VP_INST_COND_SWZ_Z_SHIFT) |
+ (3 << NV30_VP_INST_COND_SWZ_W_SHIFT));
+
+ hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT);
+// hw[3] |= NV30_VP_INST_SCA_DEST_TEMP_MASK;
+// hw[3] |= (mask << NV30_VP_INST_VEC_WRITEMASK_SHIFT);
+
+ if (dst.type == NV30SR_OUTPUT) {
+ if (slot)
+ hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT);
+ else
+ hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT);
+ } else {
+ if (slot)
+ hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT);
+ else
+ hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT);
+ }
+
+ emit_dst(vpc, hw, slot, dst);
+ emit_src(vpc, hw, 0, s0);
+ emit_src(vpc, hw, 1, s1);
+ emit_src(vpc, hw, 2, s2);
+}
+
+static INLINE struct nv20_sreg
+tgsi_src(struct nv20_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
+ struct nv20_sreg src;
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ src = nv20_sr(NV30SR_INPUT, fsrc->SrcRegister.Index);
+ break;
+ case TGSI_FILE_CONSTANT:
+ src = constant(vpc, fsrc->SrcRegister.Index, 0, 0, 0, 0);
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ src = vpc->imm[fsrc->SrcRegister.Index];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ if (vpc->high_temp < fsrc->SrcRegister.Index)
+ vpc->high_temp = fsrc->SrcRegister.Index;
+ src = nv20_sr(NV30SR_TEMP, fsrc->SrcRegister.Index);
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ break;
+ }
+
+ src.abs = fsrc->SrcRegisterExtMod.Absolute;
+ src.negate = fsrc->SrcRegister.Negate;
+ src.swz[0] = fsrc->SrcRegister.SwizzleX;
+ src.swz[1] = fsrc->SrcRegister.SwizzleY;
+ src.swz[2] = fsrc->SrcRegister.SwizzleZ;
+ src.swz[3] = fsrc->SrcRegister.SwizzleW;
+ return src;
+}
+
+static INLINE struct nv20_sreg
+tgsi_dst(struct nv20_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
+ struct nv20_sreg dst;
+
+ switch (fdst->DstRegister.File) {
+ case TGSI_FILE_OUTPUT:
+ dst = nv20_sr(NV30SR_OUTPUT,
+ vpc->output_map[fdst->DstRegister.Index]);
+
+ break;
+ case TGSI_FILE_TEMPORARY:
+ dst = nv20_sr(NV30SR_TEMP, fdst->DstRegister.Index);
+ if (vpc->high_temp < dst.index)
+ vpc->high_temp = dst.index;
+ break;
+ default:
+ NOUVEAU_ERR("bad dst file\n");
+ break;
+ }
+
+ return dst;
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+ int mask = 0;
+
+ if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
+ if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
+ if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
+ if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
+ return mask;
+}
+
+static boolean
+nv20_vertprog_parse_instruction(struct nv20_vpc *vpc,
+ const struct tgsi_full_instruction *finst)
+{
+ struct nv20_sreg src[3], dst, tmp;
+ struct nv20_sreg none = nv20_sr(NV30SR_NONE, 0);
+ int mask;
+ int ai = -1, ci = -1;
+ int i;
+
+ if (finst->Instruction.Opcode == TGSI_OPCODE_END)
+ return TRUE;
+
+ vpc->temp_temp_count = 0;
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+ if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) {
+ src[i] = tgsi_src(vpc, fsrc);
+ }
+ }
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ if (ai == -1 || ai == fsrc->SrcRegister.Index) {
+ ai = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = temp(vpc);
+ arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none);
+ }
+ break;
+ /*XXX: index comparison is broken now that consts come from
+ * two different register files.
+ */
+ case TGSI_FILE_CONSTANT:
+ case TGSI_FILE_IMMEDIATE:
+ if (ci == -1 || ci == fsrc->SrcRegister.Index) {
+ ci = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = temp(vpc);
+ arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_TEMPORARY:
+ /* handled above */
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ return FALSE;
+ }
+ }
+
+ dst = tgsi_dst(vpc, &finst->FullDstRegisters[0]);
+ mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+
+ switch (finst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none);
+ break;
+ case TGSI_OPCODE_ADD:
+ arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]);
+ break;
+ case TGSI_OPCODE_ARL:
+ arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_DP3:
+ arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DP4:
+ arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DPH:
+ arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DST:
+ arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_EX2:
+ arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_EXP:
+ arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_FLR:
+ arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_FRC:
+ arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_LG2:
+ arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_LIT:
+ arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_LOG:
+ arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_MAD:
+ arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]);
+ break;
+ case TGSI_OPCODE_MAX:
+ arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MIN:
+ arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MOV:
+ arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_MUL:
+ arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_POW:
+ tmp = temp(vpc);
+ arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none,
+ swz(src[0], X, X, X, X));
+ arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X),
+ swz(src[1], X, X, X, X), none);
+ arith(vpc, 1, OP_EX2, dst, mask, none, none,
+ swz(tmp, X, X, X, X));
+ break;
+ case TGSI_OPCODE_RCP:
+ arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_RET:
+ break;
+ case TGSI_OPCODE_RSQ:
+ arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_SGE:
+ arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SGT:
+ arith(vpc, 0, OP_SGT, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SLT:
+ arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SUB:
+ arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1]));
+ break;
+ case TGSI_OPCODE_XPD:
+ tmp = temp(vpc);
+ arith(vpc, 0, OP_MUL, tmp, mask,
+ swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
+ arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W),
+ swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
+ neg(tmp));
+ break;
+ default:
+ NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static boolean
+nv20_vertprog_parse_decl_output(struct nv20_vpc *vpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ int hw;
+
+ switch (fdec->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ hw = NV30_VP_INST_DEST_POS;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ if (fdec->Semantic.SemanticIndex == 0) {
+ hw = NV30_VP_INST_DEST_COL0;
+ } else
+ if (fdec->Semantic.SemanticIndex == 1) {
+ hw = NV30_VP_INST_DEST_COL1;
+ } else {
+ NOUVEAU_ERR("bad colour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_BCOLOR:
+ if (fdec->Semantic.SemanticIndex == 0) {
+ hw = NV30_VP_INST_DEST_BFC0;
+ } else
+ if (fdec->Semantic.SemanticIndex == 1) {
+ hw = NV30_VP_INST_DEST_BFC1;
+ } else {
+ NOUVEAU_ERR("bad bcolour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_FOG:
+ hw = NV30_VP_INST_DEST_FOGC;
+ break;
+ case TGSI_SEMANTIC_PSIZE:
+ hw = NV30_VP_INST_DEST_PSZ;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ if (fdec->Semantic.SemanticIndex <= 7) {
+ hw = NV30_VP_INST_DEST_TC(fdec->Semantic.SemanticIndex);
+ } else {
+ NOUVEAU_ERR("bad generic semantic index\n");
+ return FALSE;
+ }
+ break;
+ default:
+ NOUVEAU_ERR("bad output semantic\n");
+ return FALSE;
+ }
+
+ vpc->output_map[fdec->DeclarationRange.First] = hw;
+ return TRUE;
+}
+
+static boolean
+nv20_vertprog_prepare(struct nv20_vpc *vpc)
+{
+ struct tgsi_parse_context p;
+ int nr_imm = 0;
+
+ tgsi_parse_init(&p, vpc->vp->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&p)) {
+ const union tgsi_full_token *tok = &p.FullToken;
+
+ tgsi_parse_token(&p);
+ switch(tok->Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ nr_imm++;
+ break;
+ default:
+ break;
+ }
+ }
+ tgsi_parse_free(&p);
+
+ if (nr_imm) {
+ vpc->imm = CALLOC(nr_imm, sizeof(struct nv20_sreg));
+ assert(vpc->imm);
+ }
+
+ return TRUE;
+}
+
+static void
+nv20_vertprog_translate(struct nv20_context *nv20,
+ struct nv20_vertex_program *vp)
+{
+ struct tgsi_parse_context parse;
+ struct nv20_vpc *vpc = NULL;
+
+ tgsi_dump(vp->pipe.tokens,0);
+
+ vpc = CALLOC(1, sizeof(struct nv20_vpc));
+ if (!vpc)
+ return;
+ vpc->vp = vp;
+ vpc->high_temp = -1;
+
+ if (!nv20_vertprog_prepare(vpc)) {
+ FREE(vpc);
+ return;
+ }
+
+ tgsi_parse_init(&parse, vp->pipe.tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *fdec;
+ fdec = &parse.FullToken.FullDeclaration;
+ switch (fdec->Declaration.File) {
+ case TGSI_FILE_OUTPUT:
+ if (!nv20_vertprog_parse_decl_output(vpc, fdec))
+ goto out_err;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ const struct tgsi_full_immediate *imm;
+
+ imm = &parse.FullToken.FullImmediate;
+ assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
+ assert(imm->Immediate.NrTokens == 4 + 1);
+ vpc->imm[vpc->nr_imm++] =
+ constant(vpc, -1,
+ imm->u[0].Float,
+ imm->u[1].Float,
+ imm->u[2].Float,
+ imm->u[3].Float);
+ }
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ const struct tgsi_full_instruction *finst;
+ finst = &parse.FullToken.FullInstruction;
+ if (!nv20_vertprog_parse_instruction(vpc, finst))
+ goto out_err;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ vp->insns[vp->nr_insns - 1].data[3] |= NV30_VP_INST_LAST;
+ vp->translated = TRUE;
+out_err:
+ tgsi_parse_free(&parse);
+ FREE(vpc);
+}
+
+static boolean
+nv20_vertprog_validate(struct nv20_context *nv20)
+{
+ struct pipe_screen *pscreen = nv20->pipe.screen;
+ struct nouveau_winsys *nvws = nv20->nvws;
+ struct nouveau_grobj *rankine = nv20->screen->rankine;
+ struct nv20_vertex_program *vp;
+ struct pipe_buffer *constbuf;
+ boolean upload_code = FALSE, upload_data = FALSE;
+ int i;
+
+ vp = nv20->vertprog;
+ constbuf = nv20->constbuf[PIPE_SHADER_VERTEX];
+
+ /* Translate TGSI shader into hw bytecode */
+ if (!vp->translated) {
+ nv20_vertprog_translate(nv20, vp);
+ if (!vp->translated)
+ return FALSE;
+ }
+
+ /* Allocate hw vtxprog exec slots */
+ if (!vp->exec) {
+ struct nouveau_resource *heap = nv20->screen->vp_exec_heap;
+ struct nouveau_stateobj *so;
+ uint vplen = vp->nr_insns;
+
+ if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) {
+ while (heap->next && heap->size < vplen) {
+ struct nv20_vertex_program *evict;
+
+ evict = heap->next->priv;
+ nvws->res_free(&evict->exec);
+ }
+
+ if (nvws->res_alloc(heap, vplen, vp, &vp->exec))
+ assert(0);
+ }
+
+ so = so_new(2, 0);
+ so_method(so, rankine, NV34TCL_VP_START_FROM_ID, 1);
+ so_data (so, vp->exec->start);
+ so_ref(so, &vp->so);
+
+ upload_code = TRUE;
+ }
+
+ /* Allocate hw vtxprog const slots */
+ if (vp->nr_consts && !vp->data) {
+ struct nouveau_resource *heap = nv20->screen->vp_data_heap;
+
+ if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) {
+ while (heap->next && heap->size < vp->nr_consts) {
+ struct nv20_vertex_program *evict;
+
+ evict = heap->next->priv;
+ nvws->res_free(&evict->data);
+ }
+
+ if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data))
+ assert(0);
+ }
+
+ /*XXX: handle this some day */
+ assert(vp->data->start >= vp->data_start_min);
+
+ upload_data = TRUE;
+ if (vp->data_start != vp->data->start)
+ upload_code = TRUE;
+ }
+
+ /* If exec or data segments moved we need to patch the program to
+ * fixup offsets and register IDs.
+ */
+ if (vp->exec_start != vp->exec->start) {
+ for (i = 0; i < vp->nr_insns; i++) {
+ struct nv20_vertex_program_exec *vpi = &vp->insns[i];
+
+ if (vpi->has_branch_offset) {
+ assert(0);
+ }
+ }
+
+ vp->exec_start = vp->exec->start;
+ }
+
+ if (vp->nr_consts && vp->data_start != vp->data->start) {
+ for (i = 0; i < vp->nr_insns; i++) {
+ struct nv20_vertex_program_exec *vpi = &vp->insns[i];
+
+ if (vpi->const_index >= 0) {
+ vpi->data[1] &= ~NV30_VP_INST_CONST_SRC_MASK;
+ vpi->data[1] |=
+ (vpi->const_index + vp->data->start) <<
+ NV30_VP_INST_CONST_SRC_SHIFT;
+
+ }
+ }
+
+ vp->data_start = vp->data->start;
+ }
+
+ /* Update + Upload constant values */
+ if (vp->nr_consts) {
+ float *map = NULL;
+
+ if (constbuf) {
+ map = pipe_buffer_map(pscreen, constbuf,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ }
+
+ for (i = 0; i < vp->nr_consts; i++) {
+ struct nv20_vertex_program_data *vpd = &vp->consts[i];
+
+ if (vpd->index >= 0) {
+ if (!upload_data &&
+ !memcmp(vpd->value, &map[vpd->index * 4],
+ 4 * sizeof(float)))
+ continue;
+ memcpy(vpd->value, &map[vpd->index * 4],
+ 4 * sizeof(float));
+ }
+
+ BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5);
+ OUT_RING (i + vp->data->start);
+ OUT_RINGp ((uint32_t *)vpd->value, 4);
+ }
+
+ if (constbuf)
+ pipe_buffer_unmap(pscreen, constbuf);
+ }
+
+ /* Upload vtxprog */
+ if (upload_code) {
+#if 0
+ for (i = 0; i < vp->nr_insns; i++) {
+ NOUVEAU_MSG("VP inst %d: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ i, vp->insns[i].data[0], vp->insns[i].data[1],
+ vp->insns[i].data[2], vp->insns[i].data[3]);
+ }
+#endif
+ BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1);
+ OUT_RING (vp->exec->start);
+ for (i = 0; i < vp->nr_insns; i++) {
+ BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_INST(0), 4);
+ OUT_RINGp (vp->insns[i].data, 4);
+ }
+ }
+
+ if (vp->so != nv20->state.hw[NV30_STATE_VERTPROG]) {
+ so_ref(vp->so, &nv20->state.hw[NV30_STATE_VERTPROG]);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+nv20_vertprog_destroy(struct nv20_context *nv20, struct nv20_vertex_program *vp)
+{
+ struct nouveau_winsys *nvws = nv20->screen->nvws;
+
+ vp->translated = FALSE;
+
+ if (vp->nr_insns) {
+ FREE(vp->insns);
+ vp->insns = NULL;
+ vp->nr_insns = 0;
+ }
+
+ if (vp->nr_consts) {
+ FREE(vp->consts);
+ vp->consts = NULL;
+ vp->nr_consts = 0;
+ }
+
+ nvws->res_free(&vp->exec);
+ vp->exec_start = 0;
+ nvws->res_free(&vp->data);
+ vp->data_start = 0;
+ vp->data_start_min = 0;
+
+ vp->ir = vp->or = 0;
+ so_ref(NULL, &vp->so);
+}
+
+struct nv20_state_entry nv20_state_vertprog = {
+ .validate = nv20_vertprog_validate,
+ .dirty = {
+ .pipe = NV30_NEW_VERTPROG /*| NV30_NEW_UCP*/,
+ .hw = NV30_STATE_VERTPROG,
+ }
+};
diff --git a/src/gallium/drivers/nv30/Makefile b/src/gallium/drivers/nv30/Makefile
new file mode 100644
index 0000000000..364c80d8f3
--- /dev/null
+++ b/src/gallium/drivers/nv30/Makefile
@@ -0,0 +1,29 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv30
+
+C_SOURCES = \
+ nv30_clear.c \
+ nv30_context.c \
+ nv30_draw.c \
+ nv30_fragprog.c \
+ nv30_fragtex.c \
+ nv30_miptree.c \
+ nv30_query.c \
+ nv30_screen.c \
+ nv30_state.c \
+ nv30_state_blend.c \
+ nv30_state_emit.c \
+ nv30_state_fb.c \
+ nv30_state_rasterizer.c \
+ nv30_state_scissor.c \
+ nv30_state_stipple.c \
+ nv30_state_viewport.c \
+ nv30_state_zsa.c \
+ nv30_surface.c \
+ nv30_transfer.c \
+ nv30_vbo.c \
+ nv30_vertprog.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/nv30/nv30_clear.c b/src/gallium/drivers/nv30/nv30_clear.c
new file mode 100644
index 0000000000..c4ba926664
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_clear.c
@@ -0,0 +1,14 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "util/u_clear.h"
+
+#include "nv30_context.h"
+
+void
+nv30_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil)
+{
+ util_clear(pipe, &nv30_context(pipe)->framebuffer, buffers, rgba, depth,
+ stencil);
+}
diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c
new file mode 100644
index 0000000000..f827bdc78b
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_context.c
@@ -0,0 +1,98 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "nv30_context.h"
+#include "nv30_screen.h"
+
+static void
+nv30_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
+ BEGIN_RING(rankine, 0x1fd8, 1);
+ OUT_RING (2);
+ BEGIN_RING(rankine, 0x1fd8, 1);
+ OUT_RING (1);
+ }
+
+ FIRE_RING(fence);
+}
+
+static void
+nv30_destroy(struct pipe_context *pipe)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ if (nv30->draw)
+ draw_destroy(nv30->draw);
+ FREE(nv30);
+}
+
+static unsigned int
+nv30_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static unsigned int
+nv30_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+struct pipe_context *
+nv30_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+ struct nv30_screen *screen = nv30_screen(pscreen);
+ struct pipe_winsys *ws = pscreen->winsys;
+ struct nv30_context *nv30;
+ struct nouveau_winsys *nvws = screen->nvws;
+
+ nv30 = CALLOC(1, sizeof(struct nv30_context));
+ if (!nv30)
+ return NULL;
+ nv30->screen = screen;
+ nv30->pctx_id = pctx_id;
+
+ nv30->nvws = nvws;
+
+ nv30->pipe.winsys = ws;
+ nv30->pipe.screen = pscreen;
+ nv30->pipe.destroy = nv30_destroy;
+ nv30->pipe.draw_arrays = nv30_draw_arrays;
+ nv30->pipe.draw_elements = nv30_draw_elements;
+ nv30->pipe.clear = nv30_clear;
+ nv30->pipe.flush = nv30_flush;
+
+ nv30->pipe.is_texture_referenced = nv30_is_texture_referenced;
+ nv30->pipe.is_buffer_referenced = nv30_is_buffer_referenced;
+
+ nv30_init_query_functions(nv30);
+ nv30_init_surface_functions(nv30);
+ nv30_init_state_functions(nv30);
+
+ /* Create, configure, and install fallback swtnl path */
+ nv30->draw = draw_create();
+ draw_wide_point_threshold(nv30->draw, 9999999.0);
+ draw_wide_line_threshold(nv30->draw, 9999999.0);
+ draw_enable_line_stipple(nv30->draw, FALSE);
+ draw_enable_point_sprites(nv30->draw, FALSE);
+ draw_set_rasterize_stage(nv30->draw, nv30_draw_render_stage(nv30));
+
+ return &nv30->pipe;
+}
+
diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h
new file mode 100644
index 0000000000..4229c0a0e1
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_context.h
@@ -0,0 +1,212 @@
+#ifndef __NV30_CONTEXT_H__
+#define __NV30_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx) \
+ struct nv30_screen *ctx = nv30->screen
+#include "nouveau/nouveau_push.h"
+#include "nouveau/nouveau_stateobj.h"
+
+#include "nv30_state.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+ fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+ fprintf(stderr, "nouveau: "fmt, ##args);
+
+enum nv30_state_index {
+ NV30_STATE_FB = 0,
+ NV30_STATE_VIEWPORT = 1,
+ NV30_STATE_BLEND = 2,
+ NV30_STATE_RAST = 3,
+ NV30_STATE_ZSA = 4,
+ NV30_STATE_BCOL = 5,
+ NV30_STATE_CLIP = 6,
+ NV30_STATE_SCISSOR = 7,
+ NV30_STATE_STIPPLE = 8,
+ NV30_STATE_FRAGPROG = 9,
+ NV30_STATE_VERTPROG = 10,
+ NV30_STATE_FRAGTEX0 = 11,
+ NV30_STATE_FRAGTEX1 = 12,
+ NV30_STATE_FRAGTEX2 = 13,
+ NV30_STATE_FRAGTEX3 = 14,
+ NV30_STATE_FRAGTEX4 = 15,
+ NV30_STATE_FRAGTEX5 = 16,
+ NV30_STATE_FRAGTEX6 = 17,
+ NV30_STATE_FRAGTEX7 = 18,
+ NV30_STATE_FRAGTEX8 = 19,
+ NV30_STATE_FRAGTEX9 = 20,
+ NV30_STATE_FRAGTEX10 = 21,
+ NV30_STATE_FRAGTEX11 = 22,
+ NV30_STATE_FRAGTEX12 = 23,
+ NV30_STATE_FRAGTEX13 = 24,
+ NV30_STATE_FRAGTEX14 = 25,
+ NV30_STATE_FRAGTEX15 = 26,
+ NV30_STATE_VERTTEX0 = 27,
+ NV30_STATE_VERTTEX1 = 28,
+ NV30_STATE_VERTTEX2 = 29,
+ NV30_STATE_VERTTEX3 = 30,
+ NV30_STATE_VTXBUF = 31,
+ NV30_STATE_VTXFMT = 32,
+ NV30_STATE_VTXATTR = 33,
+ NV30_STATE_MAX = 34
+};
+
+#include "nv30_screen.h"
+
+#define NV30_NEW_BLEND (1 << 0)
+#define NV30_NEW_RAST (1 << 1)
+#define NV30_NEW_ZSA (1 << 2)
+#define NV30_NEW_SAMPLER (1 << 3)
+#define NV30_NEW_FB (1 << 4)
+#define NV30_NEW_STIPPLE (1 << 5)
+#define NV30_NEW_SCISSOR (1 << 6)
+#define NV30_NEW_VIEWPORT (1 << 7)
+#define NV30_NEW_BCOL (1 << 8)
+#define NV30_NEW_VERTPROG (1 << 9)
+#define NV30_NEW_FRAGPROG (1 << 10)
+#define NV30_NEW_ARRAYS (1 << 11)
+#define NV30_NEW_UCP (1 << 12)
+
+struct nv30_rasterizer_state {
+ struct pipe_rasterizer_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+struct nv30_zsa_state {
+ struct pipe_depth_stencil_alpha_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+struct nv30_blend_state {
+ struct pipe_blend_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+
+struct nv30_state {
+ unsigned scissor_enabled;
+ unsigned stipple_enabled;
+ unsigned viewport_bypass;
+ unsigned fp_samplers;
+
+ uint64_t dirty;
+ struct nouveau_stateobj *hw[NV30_STATE_MAX];
+};
+
+struct nv30_context {
+ struct pipe_context pipe;
+
+ struct nouveau_winsys *nvws;
+ struct nv30_screen *screen;
+ unsigned pctx_id;
+
+ struct draw_context *draw;
+
+ /* HW state derived from pipe states */
+ struct nv30_state state;
+
+ /* Context state */
+ unsigned dirty;
+ struct pipe_scissor_state scissor;
+ unsigned stipple[32];
+ struct nv30_vertex_program *vertprog;
+ struct nv30_fragment_program *fragprog;
+ struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+ unsigned constbuf_nr[PIPE_SHADER_TYPES];
+ struct nv30_rasterizer_state *rasterizer;
+ struct nv30_zsa_state *zsa;
+ struct nv30_blend_state *blend;
+ struct pipe_blend_color blend_colour;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_buffer *idxbuf;
+ unsigned idxbuf_format;
+ struct nv30_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
+ struct nv30_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
+ unsigned nr_samplers;
+ unsigned nr_textures;
+ unsigned dirty_samplers;
+ struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+ unsigned vtxbuf_nr;
+ struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+ unsigned vtxelt_nr;
+ const unsigned *edgeflags;
+};
+
+static INLINE struct nv30_context *
+nv30_context(struct pipe_context *pipe)
+{
+ return (struct nv30_context *)pipe;
+}
+
+struct nv30_state_entry {
+ boolean (*validate)(struct nv30_context *nv30);
+ struct {
+ unsigned pipe;
+ unsigned hw;
+ } dirty;
+};
+
+extern void nv30_init_state_functions(struct nv30_context *nv30);
+extern void nv30_init_surface_functions(struct nv30_context *nv30);
+extern void nv30_init_query_functions(struct nv30_context *nv30);
+
+extern void nv30_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+/* nv30_draw.c */
+extern struct draw_stage *nv30_draw_render_stage(struct nv30_context *nv30);
+
+/* nv30_vertprog.c */
+extern void nv30_vertprog_destroy(struct nv30_context *,
+ struct nv30_vertex_program *);
+
+/* nv30_fragprog.c */
+extern void nv30_fragprog_destroy(struct nv30_context *,
+ struct nv30_fragment_program *);
+
+/* nv30_fragtex.c */
+extern void nv30_fragtex_bind(struct nv30_context *);
+
+/* nv30_state.c and friends */
+extern boolean nv30_state_validate(struct nv30_context *nv30);
+extern void nv30_state_emit(struct nv30_context *nv30);
+extern struct nv30_state_entry nv30_state_rasterizer;
+extern struct nv30_state_entry nv30_state_scissor;
+extern struct nv30_state_entry nv30_state_stipple;
+extern struct nv30_state_entry nv30_state_fragprog;
+extern struct nv30_state_entry nv30_state_vertprog;
+extern struct nv30_state_entry nv30_state_blend;
+extern struct nv30_state_entry nv30_state_blend_colour;
+extern struct nv30_state_entry nv30_state_zsa;
+extern struct nv30_state_entry nv30_state_viewport;
+extern struct nv30_state_entry nv30_state_framebuffer;
+extern struct nv30_state_entry nv30_state_fragtex;
+extern struct nv30_state_entry nv30_state_vbo;
+
+/* nv30_vbo.c */
+extern boolean nv30_draw_arrays(struct pipe_context *, unsigned mode,
+ unsigned start, unsigned count);
+extern boolean nv30_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start,
+ unsigned count);
+
+/* nv30_clear.c */
+extern void nv30_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil);
+
+#endif
diff --git a/src/gallium/drivers/nv30/nv30_draw.c b/src/gallium/drivers/nv30/nv30_draw.c
new file mode 100644
index 0000000000..74fc138c05
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_draw.c
@@ -0,0 +1,61 @@
+#include "draw/draw_pipe.h"
+
+#include "nv30_context.h"
+
+struct nv30_draw_stage {
+ struct draw_stage draw;
+ struct nv30_context *nv30;
+};
+
+static void
+nv30_draw_point(struct draw_stage *draw, struct prim_header *prim)
+{
+ NOUVEAU_ERR("\n");
+}
+
+static void
+nv30_draw_line(struct draw_stage *draw, struct prim_header *prim)
+{
+ NOUVEAU_ERR("\n");
+}
+
+static void
+nv30_draw_tri(struct draw_stage *draw, struct prim_header *prim)
+{
+ NOUVEAU_ERR("\n");
+}
+
+static void
+nv30_draw_flush(struct draw_stage *draw, unsigned flags)
+{
+}
+
+static void
+nv30_draw_reset_stipple_counter(struct draw_stage *draw)
+{
+ NOUVEAU_ERR("\n");
+}
+
+static void
+nv30_draw_destroy(struct draw_stage *draw)
+{
+ FREE(draw);
+}
+
+struct draw_stage *
+nv30_draw_render_stage(struct nv30_context *nv30)
+{
+ struct nv30_draw_stage *nv30draw = CALLOC_STRUCT(nv30_draw_stage);
+
+ nv30draw->nv30 = nv30;
+ nv30draw->draw.draw = nv30->draw;
+ nv30draw->draw.point = nv30_draw_point;
+ nv30draw->draw.line = nv30_draw_line;
+ nv30draw->draw.tri = nv30_draw_tri;
+ nv30draw->draw.flush = nv30_draw_flush;
+ nv30draw->draw.reset_stipple_counter = nv30_draw_reset_stipple_counter;
+ nv30draw->draw.destroy = nv30_draw_destroy;
+
+ return &nv30draw->draw;
+}
+
diff --git a/src/gallium/drivers/nv30/nv30_fragprog.c b/src/gallium/drivers/nv30/nv30_fragprog.c
new file mode 100644
index 0000000000..a48ba9782b
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_fragprog.c
@@ -0,0 +1,915 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+
+#include "nv30_context.h"
+
+#define SWZ_X 0
+#define SWZ_Y 1
+#define SWZ_Z 2
+#define SWZ_W 3
+#define MASK_X 1
+#define MASK_Y 2
+#define MASK_Z 4
+#define MASK_W 8
+#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
+#define DEF_SCALE NV30_FP_OP_DST_SCALE_1X
+#define DEF_CTEST NV30_FP_OP_COND_TR
+#include "nv30_shader.h"
+
+#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv30_sr_neg((s))
+#define abs(s) nv30_sr_abs((s))
+#define scale(s,v) nv30_sr_scale((s), NV30_FP_OP_DST_SCALE_##v)
+
+#define MAX_CONSTS 128
+#define MAX_IMM 32
+struct nv30_fpc {
+ struct nv30_fragment_program *fp;
+
+ uint attrib_map[PIPE_MAX_SHADER_INPUTS];
+
+ int high_temp;
+ int temp_temp_count;
+ int num_regs;
+
+ uint depth_id;
+ uint colour_id;
+
+ unsigned inst_offset;
+
+ struct {
+ int pipe;
+ float vals[4];
+ } consts[MAX_CONSTS];
+ int nr_consts;
+
+ struct nv30_sreg imm[MAX_IMM];
+ unsigned nr_imm;
+};
+
+static INLINE struct nv30_sreg
+temp(struct nv30_fpc *fpc)
+{
+ int idx;
+
+ idx = fpc->temp_temp_count++;
+ idx += fpc->high_temp + 1;
+ return nv30_sr(NV30SR_TEMP, idx);
+}
+
+static INLINE struct nv30_sreg
+constant(struct nv30_fpc *fpc, int pipe, float vals[4])
+{
+ int idx;
+
+ if (fpc->nr_consts == MAX_CONSTS)
+ assert(0);
+ idx = fpc->nr_consts++;
+
+ fpc->consts[idx].pipe = pipe;
+ if (pipe == -1)
+ memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float));
+ return nv30_sr(NV30SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+ nv30_fp_arith((cc), (s), NV30_FP_OP_OPCODE_##o, \
+ (d), (m), (s0), (s1), (s2))
+#define tex(cc,s,o,u,d,m,s0,s1,s2) \
+ nv30_fp_tex((cc), (s), NV30_FP_OP_OPCODE_##o, (u), \
+ (d), (m), (s0), none, none)
+
+static void
+grow_insns(struct nv30_fpc *fpc, int size)
+{
+ struct nv30_fragment_program *fp = fpc->fp;
+
+ fp->insn_len += size;
+ fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len);
+}
+
+static void
+emit_src(struct nv30_fpc *fpc, int pos, struct nv30_sreg src)
+{
+ struct nv30_fragment_program *fp = fpc->fp;
+ uint32_t *hw = &fp->insn[fpc->inst_offset];
+ uint32_t sr = 0;
+
+ switch (src.type) {
+ case NV30SR_INPUT:
+ sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT);
+ hw[0] |= (src.index << NV30_FP_OP_INPUT_SRC_SHIFT);
+ break;
+ case NV30SR_OUTPUT:
+ sr |= NV30_FP_REG_SRC_HALF;
+ /* fall-through */
+ case NV30SR_TEMP:
+ sr |= (NV30_FP_REG_TYPE_TEMP << NV30_FP_REG_TYPE_SHIFT);
+ sr |= (src.index << NV30_FP_REG_SRC_SHIFT);
+ break;
+ case NV30SR_CONST:
+ grow_insns(fpc, 4);
+ hw = &fp->insn[fpc->inst_offset];
+ if (fpc->consts[src.index].pipe >= 0) {
+ struct nv30_fragment_program_data *fpd;
+
+ fp->consts = realloc(fp->consts, ++fp->nr_consts *
+ sizeof(*fpd));
+ fpd = &fp->consts[fp->nr_consts - 1];
+ fpd->offset = fpc->inst_offset + 4;
+ fpd->index = fpc->consts[src.index].pipe;
+ memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4);
+ } else {
+ memcpy(&fp->insn[fpc->inst_offset + 4],
+ fpc->consts[src.index].vals,
+ sizeof(uint32_t) * 4);
+ }
+
+ sr |= (NV30_FP_REG_TYPE_CONST << NV30_FP_REG_TYPE_SHIFT);
+ break;
+ case NV30SR_NONE:
+ sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (src.negate)
+ sr |= NV30_FP_REG_NEGATE;
+
+ if (src.abs)
+ hw[1] |= (1 << (29 + pos));
+
+ sr |= ((src.swz[0] << NV30_FP_REG_SWZ_X_SHIFT) |
+ (src.swz[1] << NV30_FP_REG_SWZ_Y_SHIFT) |
+ (src.swz[2] << NV30_FP_REG_SWZ_Z_SHIFT) |
+ (src.swz[3] << NV30_FP_REG_SWZ_W_SHIFT));
+
+ hw[pos + 1] |= sr;
+}
+
+static void
+emit_dst(struct nv30_fpc *fpc, struct nv30_sreg dst)
+{
+ struct nv30_fragment_program *fp = fpc->fp;
+ uint32_t *hw = &fp->insn[fpc->inst_offset];
+
+ switch (dst.type) {
+ case NV30SR_TEMP:
+ if (fpc->num_regs < (dst.index + 1))
+ fpc->num_regs = dst.index + 1;
+ break;
+ case NV30SR_OUTPUT:
+ if (dst.index == 1) {
+ fp->fp_control |= 0xe;
+ } else {
+ hw[0] |= NV30_FP_OP_OUT_REG_HALF;
+ }
+ break;
+ case NV30SR_NONE:
+ hw[0] |= (1 << 30);
+ break;
+ default:
+ assert(0);
+ }
+
+ hw[0] |= (dst.index << NV30_FP_OP_OUT_REG_SHIFT);
+}
+
+static void
+nv30_fp_arith(struct nv30_fpc *fpc, int sat, int op,
+ struct nv30_sreg dst, int mask,
+ struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2)
+{
+ struct nv30_fragment_program *fp = fpc->fp;
+ uint32_t *hw;
+
+ fpc->inst_offset = fp->insn_len;
+ grow_insns(fpc, 4);
+ hw = &fp->insn[fpc->inst_offset];
+ memset(hw, 0, sizeof(uint32_t) * 4);
+
+ if (op == NV30_FP_OP_OPCODE_KIL)
+ fp->fp_control |= NV34TCL_FP_CONTROL_USES_KIL;
+ hw[0] |= (op << NV30_FP_OP_OPCODE_SHIFT);
+ hw[0] |= (mask << NV30_FP_OP_OUTMASK_SHIFT);
+ hw[2] |= (dst.dst_scale << NV30_FP_OP_DST_SCALE_SHIFT);
+
+ if (sat)
+ hw[0] |= NV30_FP_OP_OUT_SAT;
+
+ if (dst.cc_update)
+ hw[0] |= NV30_FP_OP_COND_WRITE_ENABLE;
+ hw[1] |= (dst.cc_test << NV30_FP_OP_COND_SHIFT);
+ hw[1] |= ((dst.cc_swz[0] << NV30_FP_OP_COND_SWZ_X_SHIFT) |
+ (dst.cc_swz[1] << NV30_FP_OP_COND_SWZ_Y_SHIFT) |
+ (dst.cc_swz[2] << NV30_FP_OP_COND_SWZ_Z_SHIFT) |
+ (dst.cc_swz[3] << NV30_FP_OP_COND_SWZ_W_SHIFT));
+
+ emit_dst(fpc, dst);
+ emit_src(fpc, 0, s0);
+ emit_src(fpc, 1, s1);
+ emit_src(fpc, 2, s2);
+}
+
+static void
+nv30_fp_tex(struct nv30_fpc *fpc, int sat, int op, int unit,
+ struct nv30_sreg dst, int mask,
+ struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2)
+{
+ struct nv30_fragment_program *fp = fpc->fp;
+
+ nv30_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2);
+
+ fp->insn[fpc->inst_offset] |= (unit << NV30_FP_OP_TEX_UNIT_SHIFT);
+ fp->samplers |= (1 << unit);
+}
+
+static INLINE struct nv30_sreg
+tgsi_src(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc)
+{
+ struct nv30_sreg src;
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ src = nv30_sr(NV30SR_INPUT,
+ fpc->attrib_map[fsrc->SrcRegister.Index]);
+ break;
+ case TGSI_FILE_CONSTANT:
+ src = constant(fpc, fsrc->SrcRegister.Index, NULL);
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ assert(fsrc->SrcRegister.Index < fpc->nr_imm);
+ src = fpc->imm[fsrc->SrcRegister.Index];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ src = nv30_sr(NV30SR_TEMP, fsrc->SrcRegister.Index + 1);
+ if (fpc->high_temp < src.index)
+ fpc->high_temp = src.index;
+ break;
+ /* This is clearly insane, but gallium hands us shaders like this.
+ * Luckily fragprog results are just temp regs..
+ */
+ case TGSI_FILE_OUTPUT:
+ if (fsrc->SrcRegister.Index == fpc->colour_id)
+ return nv30_sr(NV30SR_OUTPUT, 0);
+ else
+ return nv30_sr(NV30SR_OUTPUT, 1);
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ break;
+ }
+
+ src.abs = fsrc->SrcRegisterExtMod.Absolute;
+ src.negate = fsrc->SrcRegister.Negate;
+ src.swz[0] = fsrc->SrcRegister.SwizzleX;
+ src.swz[1] = fsrc->SrcRegister.SwizzleY;
+ src.swz[2] = fsrc->SrcRegister.SwizzleZ;
+ src.swz[3] = fsrc->SrcRegister.SwizzleW;
+ return src;
+}
+
+static INLINE struct nv30_sreg
+tgsi_dst(struct nv30_fpc *fpc, const struct tgsi_full_dst_register *fdst) {
+ int idx;
+
+ switch (fdst->DstRegister.File) {
+ case TGSI_FILE_OUTPUT:
+ if (fdst->DstRegister.Index == fpc->colour_id)
+ return nv30_sr(NV30SR_OUTPUT, 0);
+ else
+ return nv30_sr(NV30SR_OUTPUT, 1);
+ break;
+ case TGSI_FILE_TEMPORARY:
+ idx = fdst->DstRegister.Index + 1;
+ if (fpc->high_temp < idx)
+ fpc->high_temp = idx;
+ return nv30_sr(NV30SR_TEMP, idx);
+ case TGSI_FILE_NULL:
+ return nv30_sr(NV30SR_NONE, 0);
+ default:
+ NOUVEAU_ERR("bad dst file %d\n", fdst->DstRegister.File);
+ return nv30_sr(NV30SR_NONE, 0);
+ }
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+ int mask = 0;
+
+ if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
+ if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
+ if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
+ if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
+ return mask;
+}
+
+static boolean
+src_native_swz(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc,
+ struct nv30_sreg *src)
+{
+ const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0);
+ struct nv30_sreg tgsi = tgsi_src(fpc, fsrc);
+ uint mask = 0, zero_mask = 0, one_mask = 0, neg_mask = 0;
+ uint neg[4] = { fsrc->SrcRegisterExtSwz.NegateX,
+ fsrc->SrcRegisterExtSwz.NegateY,
+ fsrc->SrcRegisterExtSwz.NegateZ,
+ fsrc->SrcRegisterExtSwz.NegateW };
+ uint c;
+
+ for (c = 0; c < 4; c++) {
+ switch (tgsi_util_get_full_src_register_extswizzle(fsrc, c)) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ mask |= (1 << c);
+ break;
+ case TGSI_EXTSWIZZLE_ZERO:
+ zero_mask |= (1 << c);
+ tgsi.swz[c] = SWZ_X;
+ break;
+ case TGSI_EXTSWIZZLE_ONE:
+ one_mask |= (1 << c);
+ tgsi.swz[c] = SWZ_X;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (!tgsi.negate && neg[c])
+ neg_mask |= (1 << c);
+ }
+
+ if (mask == MASK_ALL && !neg_mask)
+ return TRUE;
+
+ *src = temp(fpc);
+
+ if (mask)
+ arith(fpc, 0, MOV, *src, mask, tgsi, none, none);
+
+ if (zero_mask)
+ arith(fpc, 0, SFL, *src, zero_mask, *src, none, none);
+
+ if (one_mask)
+ arith(fpc, 0, STR, *src, one_mask, *src, none, none);
+
+ if (neg_mask) {
+ struct nv30_sreg one = temp(fpc);
+ arith(fpc, 0, STR, one, neg_mask, one, none, none);
+ arith(fpc, 0, MUL, *src, neg_mask, *src, neg(one), none);
+ }
+
+ return FALSE;
+}
+
+static boolean
+nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
+ const struct tgsi_full_instruction *finst)
+{
+ const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0);
+ struct nv30_sreg src[3], dst, tmp;
+ int mask, sat, unit = 0;
+ int ai = -1, ci = -1;
+ int i;
+
+ if (finst->Instruction.Opcode == TGSI_OPCODE_END)
+ return TRUE;
+
+ fpc->temp_temp_count = 0;
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+ if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) {
+ src[i] = tgsi_src(fpc, fsrc);
+ }
+ }
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ case TGSI_FILE_CONSTANT:
+ case TGSI_FILE_TEMPORARY:
+ if (!src_native_swz(fpc, fsrc, &src[i]))
+ continue;
+ break;
+ default:
+ break;
+ }
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ if (ai == -1 || ai == fsrc->SrcRegister.Index) {
+ ai = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(fpc, fsrc);
+ } else {
+ NOUVEAU_MSG("extra src attr %d\n",
+ fsrc->SrcRegister.Index);
+ src[i] = temp(fpc);
+ arith(fpc, 0, MOV, src[i], MASK_ALL,
+ tgsi_src(fpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ case TGSI_FILE_IMMEDIATE:
+ if (ci == -1 || ci == fsrc->SrcRegister.Index) {
+ ci = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(fpc, fsrc);
+ } else {
+ src[i] = temp(fpc);
+ arith(fpc, 0, MOV, src[i], MASK_ALL,
+ tgsi_src(fpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_TEMPORARY:
+ /* handled above */
+ break;
+ case TGSI_FILE_SAMPLER:
+ unit = fsrc->SrcRegister.Index;
+ break;
+ case TGSI_FILE_OUTPUT:
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ return FALSE;
+ }
+ }
+
+ dst = tgsi_dst(fpc, &finst->FullDstRegisters[0]);
+ mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+ sat = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE);
+
+ switch (finst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none);
+ break;
+ case TGSI_OPCODE_ADD:
+ arith(fpc, sat, ADD, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_CMP:
+ tmp = temp(fpc);
+ arith(fpc, sat, MOV, dst, mask, src[2], none, none);
+ tmp.cc_update = 1;
+ arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none);
+ dst.cc_test = NV30_VP_INST_COND_LT;
+ arith(fpc, sat, MOV, dst, mask, src[1], none, none);
+ break;
+ case TGSI_OPCODE_COS:
+ arith(fpc, sat, COS, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_DP3:
+ arith(fpc, sat, DP3, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DP4:
+ arith(fpc, sat, DP4, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DPH:
+ tmp = temp(fpc);
+ arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none);
+ arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X),
+ swz(src[1], W, W, W, W), none);
+ break;
+ case TGSI_OPCODE_DST:
+ arith(fpc, sat, DST, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_EX2:
+ arith(fpc, sat, EX2, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_FLR:
+ arith(fpc, sat, FLR, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_FRC:
+ arith(fpc, sat, FRC, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_KILP:
+ arith(fpc, 0, KIL, none, 0, none, none, none);
+ break;
+ case TGSI_OPCODE_KIL:
+ dst = nv30_sr(NV30SR_NONE, 0);
+ dst.cc_update = 1;
+ arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none);
+ dst.cc_update = 0; dst.cc_test = NV30_FP_OP_COND_LT;
+ arith(fpc, 0, KIL, dst, 0, none, none, none);
+ break;
+ case TGSI_OPCODE_LG2:
+ arith(fpc, sat, LG2, dst, mask, src[0], none, none);
+ break;
+// case TGSI_OPCODE_LIT:
+ case TGSI_OPCODE_LRP:
+ arith(fpc, sat, LRP, dst, mask, src[0], src[1], src[2]);
+ break;
+ case TGSI_OPCODE_MAD:
+ arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]);
+ break;
+ case TGSI_OPCODE_MAX:
+ arith(fpc, sat, MAX, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MIN:
+ arith(fpc, sat, MIN, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MOV:
+ arith(fpc, sat, MOV, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_MUL:
+ arith(fpc, sat, MUL, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_NOISE1:
+ case TGSI_OPCODE_NOISE2:
+ case TGSI_OPCODE_NOISE3:
+ case TGSI_OPCODE_NOISE4:
+ arith(fpc, sat, SFL, dst, mask, none, none, none);
+ break;
+ case TGSI_OPCODE_POW:
+ arith(fpc, sat, POW, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_RCP:
+ arith(fpc, sat, RCP, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_RET:
+ assert(0);
+ break;
+ case TGSI_OPCODE_RFL:
+ arith(fpc, 0, RFL, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_RSQ:
+ arith(fpc, sat, RSQ, dst, mask, abs(swz(src[0], X, X, X, X)), none, none);
+ break;
+ case TGSI_OPCODE_SCS:
+ if (mask & MASK_X) {
+ arith(fpc, sat, COS, dst, MASK_X,
+ swz(src[0], X, X, X, X), none, none);
+ }
+ if (mask & MASK_Y) {
+ arith(fpc, sat, SIN, dst, MASK_Y,
+ swz(src[0], X, X, X, X), none, none);
+ }
+ break;
+ case TGSI_OPCODE_SIN:
+ arith(fpc, sat, SIN, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_SGE:
+ arith(fpc, sat, SGE, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SGT:
+ arith(fpc, sat, SGT, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SLT:
+ arith(fpc, sat, SLT, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SUB:
+ arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none);
+ break;
+ case TGSI_OPCODE_TEX:
+ tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_TXB:
+ tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_TXP:
+ tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_XPD:
+ tmp = temp(fpc);
+ arith(fpc, 0, MUL, tmp, mask,
+ swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
+ arith(fpc, sat, MAD, dst, (mask & ~MASK_W),
+ swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
+ neg(tmp));
+ break;
+ default:
+ NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static boolean
+nv30_fragprog_parse_decl_attrib(struct nv30_fpc *fpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ int hw;
+
+ switch (fdec->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ hw = NV30_FP_OP_INPUT_SRC_POSITION;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ if (fdec->Semantic.SemanticIndex == 0) {
+ hw = NV30_FP_OP_INPUT_SRC_COL0;
+ } else
+ if (fdec->Semantic.SemanticIndex == 1) {
+ hw = NV30_FP_OP_INPUT_SRC_COL1;
+ } else {
+ NOUVEAU_ERR("bad colour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_FOG:
+ hw = NV30_FP_OP_INPUT_SRC_FOGC;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ if (fdec->Semantic.SemanticIndex <= 7) {
+ hw = NV30_FP_OP_INPUT_SRC_TC(fdec->Semantic.
+ SemanticIndex);
+ } else {
+ NOUVEAU_ERR("bad generic semantic index\n");
+ return FALSE;
+ }
+ break;
+ default:
+ NOUVEAU_ERR("bad input semantic\n");
+ return FALSE;
+ }
+
+ fpc->attrib_map[fdec->DeclarationRange.First] = hw;
+ return TRUE;
+}
+
+static boolean
+nv30_fragprog_parse_decl_output(struct nv30_fpc *fpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ switch (fdec->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ fpc->depth_id = fdec->DeclarationRange.First;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ fpc->colour_id = fdec->DeclarationRange.First;
+ break;
+ default:
+ NOUVEAU_ERR("bad output semantic\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static boolean
+nv30_fragprog_prepare(struct nv30_fpc *fpc)
+{
+ struct tgsi_parse_context p;
+ /*int high_temp = -1, i;*/
+
+ tgsi_parse_init(&p, fpc->fp->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&p)) {
+ const union tgsi_full_token *tok = &p.FullToken;
+
+ tgsi_parse_token(&p);
+ switch(tok->Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *fdec;
+ fdec = &p.FullToken.FullDeclaration;
+ switch (fdec->Declaration.File) {
+ case TGSI_FILE_INPUT:
+ if (!nv30_fragprog_parse_decl_attrib(fpc, fdec))
+ goto out_err;
+ break;
+ case TGSI_FILE_OUTPUT:
+ if (!nv30_fragprog_parse_decl_output(fpc, fdec))
+ goto out_err;
+ break;
+ /*case TGSI_FILE_TEMPORARY:
+ if (fdec->DeclarationRange.Last > high_temp) {
+ high_temp =
+ fdec->DeclarationRange.Last;
+ }
+ break;*/
+ default:
+ break;
+ }
+ }
+ break;
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ struct tgsi_full_immediate *imm;
+ float vals[4];
+
+ imm = &p.FullToken.FullImmediate;
+ assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
+ assert(fpc->nr_imm < MAX_IMM);
+
+ vals[0] = imm->u[0].Float;
+ vals[1] = imm->u[1].Float;
+ vals[2] = imm->u[2].Float;
+ vals[3] = imm->u[3].Float;
+ fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ tgsi_parse_free(&p);
+
+ /*if (++high_temp) {
+ fpc->r_temp = CALLOC(high_temp, sizeof(struct nv30_sreg));
+ for (i = 0; i < high_temp; i++)
+ fpc->r_temp[i] = temp(fpc);
+ fpc->r_temps_discard = 0;
+ }*/
+
+ return TRUE;
+
+out_err:
+ /*if (fpc->r_temp)
+ FREE(fpc->r_temp);*/
+ tgsi_parse_free(&p);
+ return FALSE;
+}
+
+static void
+nv30_fragprog_translate(struct nv30_context *nv30,
+ struct nv30_fragment_program *fp)
+{
+ struct tgsi_parse_context parse;
+ struct nv30_fpc *fpc = NULL;
+
+ tgsi_dump(fp->pipe.tokens,0);
+
+ fpc = CALLOC(1, sizeof(struct nv30_fpc));
+ if (!fpc)
+ return;
+ fpc->fp = fp;
+ fpc->high_temp = -1;
+ fpc->num_regs = 2;
+
+ if (!nv30_fragprog_prepare(fpc)) {
+ FREE(fpc);
+ return;
+ }
+
+ tgsi_parse_init(&parse, fp->pipe.tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ const struct tgsi_full_instruction *finst;
+
+ finst = &parse.FullToken.FullInstruction;
+ if (!nv30_fragprog_parse_instruction(fpc, finst))
+ goto out_err;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ fp->fp_control |= (fpc->num_regs-1)/2;
+ fp->fp_reg_control = (1<<16)|0x4;
+
+ /* Terminate final instruction */
+ fp->insn[fpc->inst_offset] |= 0x00000001;
+
+ /* Append NOP + END instruction, may or may not be necessary. */
+ fpc->inst_offset = fp->insn_len;
+ grow_insns(fpc, 4);
+ fp->insn[fpc->inst_offset + 0] = 0x00000001;
+ fp->insn[fpc->inst_offset + 1] = 0x00000000;
+ fp->insn[fpc->inst_offset + 2] = 0x00000000;
+ fp->insn[fpc->inst_offset + 3] = 0x00000000;
+
+ fp->translated = TRUE;
+ fp->on_hw = FALSE;
+out_err:
+ tgsi_parse_free(&parse);
+ FREE(fpc);
+}
+
+static void
+nv30_fragprog_upload(struct nv30_context *nv30,
+ struct nv30_fragment_program *fp)
+{
+ struct pipe_screen *pscreen = nv30->pipe.screen;
+ const uint32_t le = 1;
+ uint32_t *map;
+ int i;
+
+ map = pipe_buffer_map(pscreen, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+#if 0
+ for (i = 0; i < fp->insn_len; i++) {
+ fflush(stdout); fflush(stderr);
+ NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
+ fflush(stdout); fflush(stderr);
+ }
+#endif
+
+ if ((*(const uint8_t *)&le)) {
+ for (i = 0; i < fp->insn_len; i++) {
+ map[i] = fp->insn[i];
+ }
+ } else {
+ /* Weird swapping for big-endian chips */
+ for (i = 0; i < fp->insn_len; i++) {
+ map[i] = ((fp->insn[i] & 0xffff) << 16) |
+ ((fp->insn[i] >> 16) & 0xffff);
+ }
+ }
+
+ pipe_buffer_unmap(pscreen, fp->buffer);
+}
+
+static boolean
+nv30_fragprog_validate(struct nv30_context *nv30)
+{
+ struct nv30_fragment_program *fp = nv30->fragprog;
+ struct pipe_buffer *constbuf =
+ nv30->constbuf[PIPE_SHADER_FRAGMENT];
+ struct pipe_screen *pscreen = nv30->pipe.screen;
+ struct nouveau_stateobj *so;
+ boolean new_consts = FALSE;
+ int i;
+
+ if (fp->translated)
+ goto update_constants;
+
+ /*nv30->fallback_swrast &= ~NV30_NEW_FRAGPROG;*/
+ nv30_fragprog_translate(nv30, fp);
+ if (!fp->translated) {
+ /*nv30->fallback_swrast |= NV30_NEW_FRAGPROG;*/
+ return FALSE;
+ }
+
+ fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4);
+ nv30_fragprog_upload(nv30, fp);
+
+ so = so_new(8, 1);
+ so_method(so, nv30->screen->rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1);
+ so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW |
+ NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0,
+ NV34TCL_FP_ACTIVE_PROGRAM_DMA1);
+ so_method(so, nv30->screen->rankine, NV34TCL_FP_CONTROL, 1);
+ so_data (so, fp->fp_control);
+ so_method(so, nv30->screen->rankine, NV34TCL_FP_REG_CONTROL, 1);
+ so_data (so, fp->fp_reg_control);
+ so_method(so, nv30->screen->rankine, NV34TCL_TX_UNITS_ENABLE, 1);
+ so_data (so, fp->samplers);
+ so_ref(so, &fp->so);
+ so_ref(NULL, &so);
+
+update_constants:
+ if (fp->nr_consts) {
+ float *map;
+
+ map = pipe_buffer_map(pscreen, constbuf,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ for (i = 0; i < fp->nr_consts; i++) {
+ struct nv30_fragment_program_data *fpd = &fp->consts[i];
+ uint32_t *p = &fp->insn[fpd->offset];
+ uint32_t *cb = (uint32_t *)&map[fpd->index * 4];
+
+ if (!memcmp(p, cb, 4 * sizeof(float)))
+ continue;
+ memcpy(p, cb, 4 * sizeof(float));
+ new_consts = TRUE;
+ }
+ pipe_buffer_unmap(pscreen, constbuf);
+
+ if (new_consts)
+ nv30_fragprog_upload(nv30, fp);
+ }
+
+ if (new_consts || fp->so != nv30->state.hw[NV30_STATE_FRAGPROG]) {
+ so_ref(fp->so, &nv30->state.hw[NV30_STATE_FRAGPROG]);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+nv30_fragprog_destroy(struct nv30_context *nv30,
+ struct nv30_fragment_program *fp)
+{
+ if (fp->insn_len)
+ FREE(fp->insn);
+}
+
+struct nv30_state_entry nv30_state_fragprog = {
+ .validate = nv30_fragprog_validate,
+ .dirty = {
+ .pipe = NV30_NEW_FRAGPROG,
+ .hw = NV30_STATE_FRAGPROG
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nv30/nv30_fragtex.c
new file mode 100644
index 0000000000..822e1d8def
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_fragtex.c
@@ -0,0 +1,166 @@
+#include "nv30_context.h"
+#include "nouveau/nouveau_util.h"
+
+#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w) \
+{ \
+ TRUE, \
+ PIPE_FORMAT_##m, \
+ NV34TCL_TX_FORMAT_FORMAT_##tf, \
+ (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \
+ NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \
+ NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \
+ NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w) \
+}
+
+struct nv30_texture_format {
+ boolean defined;
+ uint pipe;
+ int format;
+ int swizzle;
+};
+
+static struct nv30_texture_format
+nv30_texture_formats[] = {
+ _(A8R8G8B8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W),
+ _(A1R5G5B5_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W),
+ _(A4R4G4B4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W),
+ _(R5G6B5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W),
+ _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X),
+ _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X),
+ _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X),
+ _(A8L8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y),
+// _(Z16_UNORM , Z16 , S1, S1, S1, ONE, X, X, X, X),
+// _(Z24S8_UNORM , Z24 , S1, S1, S1, ONE, X, X, X, X),
+ _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W),
+ _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W),
+ _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W),
+ _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W),
+ {},
+};
+
+static struct nv30_texture_format *
+nv30_fragtex_format(uint pipe_format)
+{
+ struct nv30_texture_format *tf = nv30_texture_formats;
+ char fs[128];
+
+ while (tf->defined) {
+ if (tf->pipe == pipe_format)
+ return tf;
+ tf++;
+ }
+
+ NOUVEAU_ERR("unknown texture format %s\n", pf_name(pipe_format));
+ return NULL;
+}
+
+
+static struct nouveau_stateobj *
+nv30_fragtex_build(struct nv30_context *nv30, int unit)
+{
+ struct nv30_sampler_state *ps = nv30->tex_sampler[unit];
+ struct nv30_miptree *nv30mt = nv30->tex_miptree[unit];
+ struct pipe_texture *pt = &nv30mt->base;
+ struct nouveau_bo *bo = nouveau_bo(nv30mt->buffer);
+ struct nv30_texture_format *tf;
+ struct nouveau_stateobj *so;
+ uint32_t txf, txs , txp;
+ unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+
+ tf = nv30_fragtex_format(pt->format);
+ if (!tf)
+ assert(0);
+
+ txf = tf->format;
+ txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0);
+ txf |= log2i(pt->width[0]) << 20;
+ txf |= log2i(pt->height[0]) << 24;
+ txf |= log2i(pt->depth[0]) << 28;
+ txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000;
+
+ switch (pt->target) {
+ case PIPE_TEXTURE_CUBE:
+ txf |= NV34TCL_TX_FORMAT_CUBIC;
+ /* fall-through */
+ case PIPE_TEXTURE_2D:
+ txf |= NV34TCL_TX_FORMAT_DIMS_2D;
+ break;
+ case PIPE_TEXTURE_3D:
+ txf |= NV34TCL_TX_FORMAT_DIMS_3D;
+ break;
+ case PIPE_TEXTURE_1D:
+ txf |= NV34TCL_TX_FORMAT_DIMS_1D;
+ break;
+ default:
+ NOUVEAU_ERR("Unknown target %d\n", pt->target);
+ return NULL;
+ }
+
+ if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+ txp = 0;
+ } else {
+ txp = nv30mt->level[0].pitch;
+ txf |= (1<<13) /*FIXME: NV34TCL_TX_FORMAT_LINEAR ? */;
+ }
+
+ txs = tf->swizzle;
+
+ so = so_new(16, 2);
+ so_method(so, nv30->screen->rankine, NV34TCL_TX_OFFSET(unit), 8);
+ so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
+ so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR,
+ NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
+ so_data (so, ps->wrap);
+ so_data (so, NV34TCL_TX_ENABLE_ENABLE | ps->en);
+ so_data (so, txs);
+ so_data (so, ps->filt | 0x2000 /*voodoo*/);
+ so_data (so, (pt->width[0] << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
+ pt->height[0]);
+ so_data (so, ps->bcol);
+
+ return so;
+}
+
+static boolean
+nv30_fragtex_validate(struct nv30_context *nv30)
+{
+ struct nv30_fragment_program *fp = nv30->fragprog;
+ struct nv30_state *state = &nv30->state;
+ struct nouveau_stateobj *so;
+ unsigned samplers, unit;
+
+ samplers = state->fp_samplers & ~fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ so = so_new(2, 0);
+ so_method(so, nv30->screen->rankine, NV34TCL_TX_ENABLE(unit), 1);
+ so_data (so, 0);
+ so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]);
+ so_ref(NULL, &so);
+ state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit));
+ }
+
+ samplers = nv30->dirty_samplers & fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ so = nv30_fragtex_build(nv30, unit);
+ so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]);
+ so_ref(NULL, &so);
+ state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit));
+ }
+
+ nv30->state.fp_samplers = fp->samplers;
+ return FALSE;
+}
+
+struct nv30_state_entry nv30_state_fragtex = {
+ .validate = nv30_fragtex_validate,
+ .dirty = {
+ .pipe = NV30_NEW_SAMPLER | NV30_NEW_FRAGPROG,
+ .hw = 0
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c
new file mode 100644
index 0000000000..7f8054de73
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_miptree.c
@@ -0,0 +1,213 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "nv30_context.h"
+
+static void
+nv30_miptree_layout(struct nv30_miptree *nv30mt)
+{
+ struct pipe_texture *pt = &nv30mt->base;
+ uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
+ uint offset = 0;
+ int nr_faces, l, f;
+ uint wide_pitch = pt->tex_usage & (PIPE_TEXTURE_USAGE_SAMPLER |
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL |
+ PIPE_TEXTURE_USAGE_RENDER_TARGET |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_PRIMARY);
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ nr_faces = 6;
+ } else
+ if (pt->target == PIPE_TEXTURE_3D) {
+ nr_faces = pt->depth[0];
+ } else {
+ nr_faces = 1;
+ }
+
+ for (l = 0; l <= pt->last_level; l++) {
+ pt->width[l] = width;
+ pt->height[l] = height;
+ pt->depth[l] = depth;
+ pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+ pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+
+ if (wide_pitch && (pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR))
+ nv30mt->level[l].pitch = align(pt->width[0] * pt->block.size, 64);
+ else
+ nv30mt->level[l].pitch = pt->width[l] * pt->block.size;
+
+ nv30mt->level[l].image_offset =
+ CALLOC(nr_faces, sizeof(unsigned));
+
+ width = MAX2(1, width >> 1);
+ height = MAX2(1, height >> 1);
+ depth = MAX2(1, depth >> 1);
+ }
+
+ for (f = 0; f < nr_faces; f++) {
+ for (l = 0; l < pt->last_level; l++) {
+ nv30mt->level[l].image_offset[f] = offset;
+
+ if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) &&
+ pt->width[l + 1] > 1 && pt->height[l + 1] > 1)
+ offset += align(nv30mt->level[l].pitch * pt->height[l], 64);
+ else
+ offset += nv30mt->level[l].pitch * pt->height[l];
+ }
+
+ nv30mt->level[l].image_offset[f] = offset;
+ offset += nv30mt->level[l].pitch * pt->height[l];
+ }
+
+ nv30mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
+{
+ struct nv30_miptree *mt;
+ unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL |
+ NOUVEAU_BUFFER_USAGE_TEXTURE;
+
+ mt = MALLOC(sizeof(struct nv30_miptree));
+ if (!mt)
+ return NULL;
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = pscreen;
+
+ /* Swizzled textures must be POT */
+ if (pt->width[0] & (pt->width[0] - 1) ||
+ pt->height[0] & (pt->height[0] - 1))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else
+ if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else
+ if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC)
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else {
+ switch (pt->format) {
+ /* TODO: Figure out which formats can be swizzled */
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_R16_SNORM:
+ {
+ if (debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ break;
+ }
+ default:
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ }
+ }
+
+ if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC)
+ buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+
+ nv30_miptree_layout(mt);
+
+ mt->buffer = pscreen->buffer_create(pscreen, 256, buf_usage,
+ mt->total_size);
+ if (!mt->buffer) {
+ FREE(mt);
+ return NULL;
+ }
+
+ return &mt->base;
+}
+
+static struct pipe_texture *
+nv30_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt,
+ const unsigned *stride, struct pipe_buffer *pb)
+{
+ struct nv30_miptree *mt;
+
+ /* Only supports 2D, non-mipmapped textures for the moment */
+ if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 ||
+ pt->depth[0] != 1)
+ return NULL;
+
+ mt = CALLOC_STRUCT(nv30_miptree);
+ if (!mt)
+ return NULL;
+
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = pscreen;
+ mt->level[0].pitch = stride[0];
+ mt->level[0].image_offset = CALLOC(1, sizeof(unsigned));
+
+ pipe_buffer_reference(&mt->buffer, pb);
+ return &mt->base;
+}
+
+static void
+nv30_miptree_destroy(struct pipe_texture *pt)
+{
+ struct nv30_miptree *mt = (struct nv30_miptree *)pt;
+ int l;
+
+ pipe_buffer_reference(&mt->buffer, NULL);
+ for (l = 0; l <= pt->last_level; l++) {
+ if (mt->level[l].image_offset)
+ FREE(mt->level[l].image_offset);
+ }
+
+ FREE(mt);
+}
+
+static struct pipe_surface *
+nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned flags)
+{
+ struct nv30_miptree *nv30mt = (struct nv30_miptree *)pt;
+ struct nv04_surface *ns;
+
+ ns = CALLOC_STRUCT(nv04_surface);
+ if (!ns)
+ return NULL;
+ pipe_texture_reference(&ns->base.texture, pt);
+ ns->base.format = pt->format;
+ ns->base.width = pt->width[level];
+ ns->base.height = pt->height[level];
+ ns->base.usage = flags;
+ pipe_reference_init(&ns->base.reference, 1);
+ ns->base.face = face;
+ ns->base.level = level;
+ ns->base.zslice = zslice;
+ ns->pitch = nv30mt->level[level].pitch;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ns->base.offset = nv30mt->level[level].image_offset[face];
+ } else
+ if (pt->target == PIPE_TEXTURE_3D) {
+ ns->base.offset = nv30mt->level[level].image_offset[zslice];
+ } else {
+ ns->base.offset = nv30mt->level[level].image_offset[0];
+ }
+
+ return &ns->base;
+}
+
+static void
+nv30_miptree_surface_del(struct pipe_surface *ps)
+{
+ pipe_texture_reference(&ps->texture, NULL);
+ FREE(ps);
+}
+
+void
+nv30_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+ pscreen->texture_create = nv30_miptree_create;
+ pscreen->texture_blanket = nv30_miptree_blanket;
+ pscreen->texture_destroy = nv30_miptree_destroy;
+ pscreen->get_tex_surface = nv30_miptree_surface_new;
+ pscreen->tex_surface_destroy = nv30_miptree_surface_del;
+}
diff --git a/src/gallium/drivers/nv30/nv30_query.c b/src/gallium/drivers/nv30/nv30_query.c
new file mode 100644
index 0000000000..1d1c8a484e
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_query.c
@@ -0,0 +1,121 @@
+#include "pipe/p_context.h"
+
+#include "nv30_context.h"
+
+struct nv30_query {
+ struct nouveau_resource *object;
+ unsigned type;
+ boolean ready;
+ uint64_t result;
+};
+
+static INLINE struct nv30_query *
+nv30_query(struct pipe_query *pipe)
+{
+ return (struct nv30_query *)pipe;
+}
+
+static struct pipe_query *
+nv30_query_create(struct pipe_context *pipe, unsigned query_type)
+{
+ struct nv30_query *q;
+
+ q = CALLOC(1, sizeof(struct nv30_query));
+ q->type = query_type;
+
+ return (struct pipe_query *)q;
+}
+
+static void
+nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv30_query *q = nv30_query(pq);
+
+ if (q->object)
+ nouveau_resource_free(&q->object);
+ FREE(q);
+}
+
+static void
+nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_query *q = nv30_query(pq);
+
+ assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+
+ /* Happens when end_query() is called, then another begin_query()
+ * without querying the result in-between. For now we'll wait for
+ * the existing query to notify completion, but it could be better.
+ */
+ if (q->object) {
+ uint64_t tmp;
+ pipe->get_query_result(pipe, pq, 1, &tmp);
+ }
+
+ if (nouveau_resource_alloc(nv30->screen->query_heap, 1, NULL, &q->object))
+ assert(0);
+ nouveau_notifier_reset(nv30->screen->query, q->object->start);
+
+ BEGIN_RING(rankine, NV34TCL_QUERY_RESET, 1);
+ OUT_RING (1);
+ BEGIN_RING(rankine, NV34TCL_QUERY_UNK17CC, 1);
+ OUT_RING (1);
+
+ q->ready = FALSE;
+}
+
+static void
+nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_query *q = nv30_query(pq);
+
+ BEGIN_RING(rankine, NV34TCL_QUERY_GET, 1);
+ OUT_RING ((0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) |
+ ((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT));
+ FIRE_RING(NULL);
+}
+
+static boolean
+nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
+ boolean wait, uint64_t *result)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_query *q = nv30_query(pq);
+
+ assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+
+ if (!q->ready) {
+ unsigned status;
+
+ status = nouveau_notifier_status(nv30->screen->query,
+ q->object->start);
+ if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) {
+ if (wait == FALSE)
+ return FALSE;
+
+ nouveau_notifier_wait_status(nv30->screen->query,
+ q->object->start,
+ NV_NOTIFY_STATE_STATUS_COMPLETED, 0);
+ }
+
+ q->result = nouveau_notifier_return_val(nv30->screen->query,
+ q->object->start);
+ q->ready = TRUE;
+ nouveau_resource_free(&q->object);
+ }
+
+ *result = q->result;
+ return TRUE;
+}
+
+void
+nv30_init_query_functions(struct nv30_context *nv30)
+{
+ nv30->pipe.create_query = nv30_query_create;
+ nv30->pipe.destroy_query = nv30_query_destroy;
+ nv30->pipe.begin_query = nv30_query_begin;
+ nv30->pipe.end_query = nv30_query_end;
+ nv30->pipe.get_query_result = nv30_query_result;
+}
diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c
new file mode 100644
index 0000000000..f8285e4455
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_screen.c
@@ -0,0 +1,324 @@
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+
+#include "nouveau/nouveau_screen.h"
+
+#include "nv30_context.h"
+#include "nv30_screen.h"
+
+#define NV30TCL_CHIPSET_3X_MASK 0x00000003
+#define NV34TCL_CHIPSET_3X_MASK 0x00000010
+#define NV35TCL_CHIPSET_3X_MASK 0x000001e0
+
+static int
+nv30_screen_get_param(struct pipe_screen *pscreen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return 16;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 0;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 1;
+ case PIPE_CAP_GLSL:
+ return 0;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 1;
+ case PIPE_CAP_POINT_SPRITE:
+ return 1;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 2;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 1;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 1;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 13;
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 10;
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 13;
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ return 0;
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ return 0;
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ return 0;
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 0;
+ case NOUVEAU_CAP_HW_VTXBUF:
+ case NOUVEAU_CAP_HW_IDXBUF:
+ return 1;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0;
+ }
+}
+
+static float
+nv30_screen_get_paramf(struct pipe_screen *pscreen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 10.0;
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 64.0;
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 8.0;
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 4.0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0.0;
+ }
+}
+
+static boolean
+nv30_screen_surface_format_supported(struct pipe_screen *pscreen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else
+ if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) {
+ switch (format) {
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_A8L8_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static struct pipe_buffer *
+nv30_surface_buffer(struct pipe_surface *surf)
+{
+ struct nv30_miptree *mt = (struct nv30_miptree *)surf->texture;
+
+ return mt->buffer;
+}
+
+static void
+nv30_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct nv30_screen *screen = nv30_screen(pscreen);
+
+ nouveau_resource_free(&screen->vp_exec_heap);
+ nouveau_resource_free(&screen->vp_data_heap);
+ nouveau_resource_free(&screen->query_heap);
+ nouveau_notifier_free(&screen->query);
+ nouveau_notifier_free(&screen->sync);
+ nouveau_grobj_free(&screen->rankine);
+
+ FREE(pscreen);
+}
+
+struct pipe_screen *
+nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
+{
+ struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
+ struct nouveau_channel *chan;
+ struct pipe_screen *pscreen;
+ struct nouveau_stateobj *so;
+ unsigned rankine_class = 0;
+ int ret, i;
+
+ if (!screen)
+ return NULL;
+ pscreen = &screen->base.base;
+
+ ret = nouveau_screen_init(&screen->base, dev);
+ if (ret) {
+ nv30_screen_destroy(pscreen);
+ return NULL;
+ }
+ chan = screen->base.channel;
+
+ pscreen->winsys = ws;
+ pscreen->destroy = nv30_screen_destroy;
+ pscreen->get_param = nv30_screen_get_param;
+ pscreen->get_paramf = nv30_screen_get_paramf;
+ pscreen->is_format_supported = nv30_screen_surface_format_supported;
+
+ nv30_screen_init_miptree_functions(pscreen);
+ nv30_screen_init_transfer_functions(pscreen);
+
+ /* 3D object */
+ switch (dev->chipset & 0xf0) {
+ case 0x30:
+ if (NV30TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f)))
+ rankine_class = 0x0397;
+ else
+ if (NV34TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f)))
+ rankine_class = 0x0697;
+ else
+ if (NV35TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f)))
+ rankine_class = 0x0497;
+ break;
+ default:
+ break;
+ }
+
+ if (!rankine_class) {
+ NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", dev->chipset);
+ return NULL;
+ }
+
+ ret = nouveau_grobj_alloc(chan, 0xbeef3097, rankine_class,
+ &screen->rankine);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+ return FALSE;
+ }
+ BIND_RING(chan, screen->rankine, 7);
+
+ /* 2D engine setup */
+ screen->eng2d = nv04_surface_2d_init(&screen->base);
+ screen->eng2d->buf = nv30_surface_buffer;
+
+ /* Notifier for sync purposes */
+ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
+ if (ret) {
+ NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+ nv30_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ /* Query objects */
+ ret = nouveau_notifier_alloc(chan, 0xbeef0302, 32, &screen->query);
+ if (ret) {
+ NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
+ nv30_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ ret = nouveau_resource_init(&screen->query_heap, 0, 32);
+ if (ret) {
+ NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
+ nv30_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ /* Vtxprog resources */
+ if (nouveau_resource_init(&screen->vp_exec_heap, 0, 256) ||
+ nouveau_resource_init(&screen->vp_data_heap, 0, 256)) {
+ nv30_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ /* Static rankine initialisation */
+ so = so_new(128, 0);
+ so_method(so, screen->rankine, NV34TCL_DMA_NOTIFY, 1);
+ so_data (so, screen->sync->handle);
+ so_method(so, screen->rankine, NV34TCL_DMA_TEXTURE0, 2);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->gart->handle);
+ so_method(so, screen->rankine, NV34TCL_DMA_COLOR1, 1);
+ so_data (so, chan->vram->handle);
+ so_method(so, screen->rankine, NV34TCL_DMA_COLOR0, 2);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->vram->handle);
+ so_method(so, screen->rankine, NV34TCL_DMA_VTXBUF0, 2);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->gart->handle);
+/* so_method(so, screen->rankine, NV34TCL_DMA_FENCE, 2);
+ so_data (so, 0);
+ so_data (so, screen->query->handle);*/
+ so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY7, 1);
+ so_data (so, chan->vram->handle);
+ so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY8, 1);
+ so_data (so, chan->vram->handle);
+
+ for (i=1; i<8; i++) {
+ so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1);
+ so_data (so, 0);
+ so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_VERT(i), 1);
+ so_data (so, 0);
+ }
+
+ so_method(so, screen->rankine, 0x220, 1);
+ so_data (so, 1);
+
+ so_method(so, screen->rankine, 0x03b0, 1);
+ so_data (so, 0x00100000);
+ so_method(so, screen->rankine, 0x1454, 1);
+ so_data (so, 0);
+ so_method(so, screen->rankine, 0x1d80, 1);
+ so_data (so, 3);
+ so_method(so, screen->rankine, 0x1450, 1);
+ so_data (so, 0x00030004);
+
+ /* NEW */
+ so_method(so, screen->rankine, 0x1e98, 1);
+ so_data (so, 0);
+ so_method(so, screen->rankine, 0x17e0, 3);
+ so_data (so, fui(0.0));
+ so_data (so, fui(0.0));
+ so_data (so, fui(1.0));
+ so_method(so, screen->rankine, 0x1f80, 16);
+ for (i=0; i<16; i++) {
+ so_data (so, (i==8) ? 0x0000ffff : 0);
+ }
+
+ so_method(so, screen->rankine, 0x120, 3);
+ so_data (so, 0);
+ so_data (so, 1);
+ so_data (so, 2);
+
+ so_method(so, screen->rankine, 0x1d88, 1);
+ so_data (so, 0x00001200);
+
+ so_method(so, screen->rankine, NV34TCL_RC_ENABLE, 1);
+ so_data (so, 0);
+
+ so_method(so, screen->rankine, NV34TCL_DEPTH_RANGE_NEAR, 2);
+ so_data (so, fui(0.0));
+ so_data (so, fui(1.0));
+
+ so_method(so, screen->rankine, NV34TCL_MULTISAMPLE_CONTROL, 1);
+ so_data (so, 0xffff0000);
+
+ /* enables use of vp rather than fixed-function somehow */
+ so_method(so, screen->rankine, 0x1e94, 1);
+ so_data (so, 0x13);
+
+ so_emit(chan, so);
+ so_ref(NULL, &so);
+ nouveau_pushbuf_flush(chan, 0);
+
+ return pscreen;
+}
diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h
new file mode 100644
index 0000000000..5fbd998b53
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_screen.h
@@ -0,0 +1,41 @@
+#ifndef __NV30_SCREEN_H__
+#define __NV30_SCREEN_H__
+
+#include "nouveau/nouveau_screen.h"
+
+#include "nv04/nv04_surface_2d.h"
+
+struct nv30_screen {
+ struct nouveau_screen base;
+
+ struct nouveau_winsys *nvws;
+
+ unsigned cur_pctx;
+
+ /* HW graphics objects */
+ struct nv04_surface_2d *eng2d;
+ struct nouveau_grobj *rankine;
+ struct nouveau_notifier *sync;
+
+ /* Query object resources */
+ struct nouveau_notifier *query;
+ struct nouveau_resource *query_heap;
+
+ /* Vtxprog resources */
+ struct nouveau_resource *vp_exec_heap;
+ struct nouveau_resource *vp_data_heap;
+
+ /* Current 3D state of channel */
+ struct nouveau_stateobj *state[NV30_STATE_MAX];
+};
+
+static INLINE struct nv30_screen *
+nv30_screen(struct pipe_screen *screen)
+{
+ return (struct nv30_screen *)screen;
+}
+
+void
+nv30_screen_init_transfer_functions(struct pipe_screen *pscreen);
+
+#endif
diff --git a/src/gallium/drivers/nv30/nv30_shader.h b/src/gallium/drivers/nv30/nv30_shader.h
new file mode 100644
index 0000000000..dd3a36f78f
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_shader.h
@@ -0,0 +1,490 @@
+#ifndef __NV30_SHADER_H__
+#define __NV30_SHADER_H__
+
+/* Vertex programs instruction set
+ *
+ * 128bit opcodes, split into 4 32-bit ones for ease of use.
+ *
+ * Non-native instructions
+ * ABS - MOV + NV40_VP_INST0_DEST_ABS
+ * POW - EX2 + MUL + LG2
+ * SUB - ADD, second source negated
+ * SWZ - MOV
+ * XPD -
+ *
+ * Register access
+ * - Only one INPUT can be accessed per-instruction (move extras into TEMPs)
+ * - Only one CONST can be accessed per-instruction (move extras into TEMPs)
+ *
+ * Relative Addressing
+ * According to the value returned for
+ * MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
+ *
+ * there are only two address registers available. The destination in the
+ * ARL instruction is set to TEMP <n> (The temp isn't actually written).
+ *
+ * When using vanilla ARB_v_p, the proprietary driver will squish both the
+ * available ADDRESS regs into the first hardware reg in the X and Y
+ * components.
+ *
+ * To use an address reg as an index into consts, the CONST_SRC is set to
+ * (const_base + offset) and INDEX_CONST is set.
+ *
+ * To access the second address reg use ADDR_REG_SELECT_1. A particular
+ * component of the address regs is selected with ADDR_SWZ.
+ *
+ * Only one address register can be accessed per instruction.
+ *
+ * Conditional execution (see NV_vertex_program{2,3} for details) Conditional
+ * execution of an instruction is enabled by setting COND_TEST_ENABLE, and
+ * selecting the condition which will allow the test to pass with
+ * COND_{FL,LT,...}. It is possible to swizzle the values in the condition
+ * register, which allows for testing against an individual component.
+ *
+ * Branching:
+ *
+ * The BRA/CAL instructions seem to follow a slightly different opcode
+ * layout. The destination instruction ID (IADDR) overlaps a source field.
+ * Instruction ID's seem to be numbered based on the UPLOAD_FROM_ID FIFO
+ * command, and is incremented automatically on each UPLOAD_INST FIFO
+ * command.
+ *
+ * Conditional branching is achieved by using the condition tests described
+ * above. There doesn't appear to be dedicated looping instructions, but
+ * this can be done using a temp reg + conditional branching.
+ *
+ * Subroutines may be uploaded before the main program itself, but the first
+ * executed instruction is determined by the PROGRAM_START_ID FIFO command.
+ *
+ */
+
+/* DWORD 0 */
+
+#define NV30_VP_INST_ADDR_REG_SELECT_1 (1 << 24)
+#define NV30_VP_INST_SRC2_ABS (1 << 23) /* guess */
+#define NV30_VP_INST_SRC1_ABS (1 << 22) /* guess */
+#define NV30_VP_INST_SRC0_ABS (1 << 21) /* guess */
+#define NV30_VP_INST_VEC_RESULT (1 << 20)
+#define NV30_VP_INST_DEST_TEMP_ID_SHIFT 16
+#define NV30_VP_INST_DEST_TEMP_ID_MASK (0x0F << 16)
+#define NV30_VP_INST_COND_UPDATE_ENABLE (1<<15)
+#define NV30_VP_INST_VEC_DEST_TEMP_MASK (0xF << 16)
+#define NV30_VP_INST_COND_TEST_ENABLE (1<<14)
+#define NV30_VP_INST_COND_SHIFT 11
+#define NV30_VP_INST_COND_MASK (0x07 << 11)
+# define NV30_VP_INST_COND_FL 0 /* guess */
+# define NV30_VP_INST_COND_LT 1
+# define NV30_VP_INST_COND_EQ 2
+# define NV30_VP_INST_COND_LE 3
+# define NV30_VP_INST_COND_GT 4
+# define NV30_VP_INST_COND_NE 5
+# define NV30_VP_INST_COND_GE 6
+# define NV30_VP_INST_COND_TR 7 /* guess */
+#define NV30_VP_INST_COND_SWZ_X_SHIFT 9
+#define NV30_VP_INST_COND_SWZ_X_MASK (0x03 << 9)
+#define NV30_VP_INST_COND_SWZ_Y_SHIFT 7
+#define NV30_VP_INST_COND_SWZ_Y_MASK (0x03 << 7)
+#define NV30_VP_INST_COND_SWZ_Z_SHIFT 5
+#define NV30_VP_INST_COND_SWZ_Z_MASK (0x03 << 5)
+#define NV30_VP_INST_COND_SWZ_W_SHIFT 3
+#define NV30_VP_INST_COND_SWZ_W_MASK (0x03 << 3)
+#define NV30_VP_INST_COND_SWZ_ALL_SHIFT 3
+#define NV30_VP_INST_COND_SWZ_ALL_MASK (0xFF << 3)
+#define NV30_VP_INST_ADDR_SWZ_SHIFT 1
+#define NV30_VP_INST_ADDR_SWZ_MASK (0x03 << 1)
+#define NV30_VP_INST_SCA_OPCODEH_SHIFT 0
+#define NV30_VP_INST_SCA_OPCODEH_MASK (0x01 << 0)
+
+/* DWORD 1 */
+#define NV30_VP_INST_SCA_OPCODEL_SHIFT 28
+#define NV30_VP_INST_SCA_OPCODEL_MASK (0x0F << 28)
+# define NV30_VP_INST_OP_NOP 0x00
+# define NV30_VP_INST_OP_RCP 0x02
+# define NV30_VP_INST_OP_RCC 0x03
+# define NV30_VP_INST_OP_RSQ 0x04
+# define NV30_VP_INST_OP_EXP 0x05
+# define NV30_VP_INST_OP_LOG 0x06
+# define NV30_VP_INST_OP_LIT 0x07
+# define NV30_VP_INST_OP_BRA 0x09
+# define NV30_VP_INST_OP_CAL 0x0B
+# define NV30_VP_INST_OP_RET 0x0C
+# define NV30_VP_INST_OP_LG2 0x0D
+# define NV30_VP_INST_OP_EX2 0x0E
+# define NV30_VP_INST_OP_SIN 0x0F
+# define NV30_VP_INST_OP_COS 0x10
+#define NV30_VP_INST_VEC_OPCODE_SHIFT 23
+#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23)
+# define NV30_VP_INST_OP_NOPV 0x00
+# define NV30_VP_INST_OP_MOV 0x01
+# define NV30_VP_INST_OP_MUL 0x02
+# define NV30_VP_INST_OP_ADD 0x03
+# define NV30_VP_INST_OP_MAD 0x04
+# define NV30_VP_INST_OP_DP3 0x05
+# define NV30_VP_INST_OP_DP4 0x07
+# define NV30_VP_INST_OP_DPH 0x06
+# define NV30_VP_INST_OP_DST 0x08
+# define NV30_VP_INST_OP_MIN 0x09
+# define NV30_VP_INST_OP_MAX 0x0A
+# define NV30_VP_INST_OP_SLT 0x0B
+# define NV30_VP_INST_OP_SGE 0x0C
+# define NV30_VP_INST_OP_ARL 0x0D
+# define NV30_VP_INST_OP_FRC 0x0E
+# define NV30_VP_INST_OP_FLR 0x0F
+# define NV30_VP_INST_OP_SEQ 0x10
+# define NV30_VP_INST_OP_SFL 0x11
+# define NV30_VP_INST_OP_SGT 0x12
+# define NV30_VP_INST_OP_SLE 0x13
+# define NV30_VP_INST_OP_SNE 0x14
+# define NV30_VP_INST_OP_STR 0x15
+# define NV30_VP_INST_OP_SSG 0x16
+# define NV30_VP_INST_OP_ARR 0x17
+# define NV30_VP_INST_OP_ARA 0x18
+#define NV30_VP_INST_CONST_SRC_SHIFT 14
+#define NV30_VP_INST_CONST_SRC_MASK (0xFF << 14)
+#define NV30_VP_INST_INPUT_SRC_SHIFT 9 /*NV20*/
+#define NV30_VP_INST_INPUT_SRC_MASK (0x0F << 9) /*NV20*/
+# define NV30_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */
+# define NV30_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */
+# define NV30_VP_INST_IN_NORMAL 2
+# define NV30_VP_INST_IN_COL0 3 /* Should probably confirm them all though */
+# define NV30_VP_INST_IN_COL1 4
+# define NV30_VP_INST_IN_FOGC 5
+# define NV30_VP_INST_IN_TC0 8
+# define NV30_VP_INST_IN_TC(n) (8+n)
+#define NV30_VP_INST_SRC0H_SHIFT 0 /*NV20*/
+#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/
+
+/* Please note: the IADDR fields overlap other fields because they are used
+ * only for branch instructions. See Branching: label above
+ *
+ * DWORD 2
+ */
+#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/
+#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /* NV30_VP_SRC0_LOW_MASK << 26 */
+#define NV30_VP_INST_SRC1_SHIFT 11 /*NV20*/
+#define NV30_VP_INST_SRC1_MASK (0x7FFF<<11) /*NV20*/
+#define NV30_VP_INST_SRC2H_SHIFT 0 /*NV20*/
+#define NV30_VP_INST_SRC2H_MASK (0x7FF << 0) /* NV30_VP_SRC2_HIGH_MASK >> 4*/
+#define NV30_VP_INST_IADDR_SHIFT 2
+#define NV30_VP_INST_IADDR_MASK (0xF << 28) /* NV30_VP_SRC2_LOW_MASK << 28 */
+
+/* DWORD 3 */
+#define NV30_VP_INST_SRC2L_SHIFT 28 /*NV20*/
+#define NV30_VP_INST_SRC2L_MASK (0x0F <<28) /*NV20*/
+#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT 24
+#define NV30_VP_INST_STEMP_WRITEMASK_MASK (0x0F << 24)
+#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT 20
+#define NV30_VP_INST_VTEMP_WRITEMASK_MASK (0x0F << 20)
+#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT 16
+#define NV30_VP_INST_SDEST_WRITEMASK_MASK (0x0F << 16)
+#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT 12 /*NV20*/
+#define NV30_VP_INST_VDEST_WRITEMASK_MASK (0x0F << 12) /*NV20*/
+#define NV30_VP_INST_DEST_SHIFT 2
+#define NV30_VP_INST_DEST_MASK (0x0F << 2)
+# define NV30_VP_INST_DEST_POS 0
+# define NV30_VP_INST_DEST_BFC0 1
+# define NV30_VP_INST_DEST_BFC1 2
+# define NV30_VP_INST_DEST_COL0 3
+# define NV30_VP_INST_DEST_COL1 4
+# define NV30_VP_INST_DEST_FOGC 5
+# define NV30_VP_INST_DEST_PSZ 6
+# define NV30_VP_INST_DEST_TC(n) (8+n)
+
+#define NV30_VP_INST_LAST (1 << 0)
+
+/* Useful to split the source selection regs into their pieces */
+#define NV30_VP_SRC0_HIGH_SHIFT 6
+#define NV30_VP_SRC0_HIGH_MASK 0x00007FC0
+#define NV30_VP_SRC0_LOW_MASK 0x0000003F
+#define NV30_VP_SRC2_HIGH_SHIFT 4
+#define NV30_VP_SRC2_HIGH_MASK 0x00007FF0
+#define NV30_VP_SRC2_LOW_MASK 0x0000000F
+
+
+/* Source-register definition - matches NV20 exactly */
+#define NV30_VP_SRC_NEGATE (1<<14)
+#define NV30_VP_SRC_SWZ_X_SHIFT 12
+#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12)
+#define NV30_VP_SRC_SWZ_Y_SHIFT 10
+#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10)
+#define NV30_VP_SRC_SWZ_Z_SHIFT 8
+#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8)
+#define NV30_VP_SRC_SWZ_W_SHIFT 6
+#define NV30_VP_SRC_REG_SWZ_W_MASK (0x03 << 6)
+#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT 6
+#define NV30_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6)
+#define NV30_VP_SRC_TEMP_SRC_SHIFT 2
+#define NV30_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0)
+#define NV30_VP_SRC_REG_TYPE_SHIFT 0
+#define NV30_VP_SRC_REG_TYPE_MASK (0x03 << 0)
+#define NV30_VP_SRC_REG_TYPE_TEMP 1
+#define NV30_VP_SRC_REG_TYPE_INPUT 2
+#define NV30_VP_SRC_REG_TYPE_CONST 3 /* guess */
+
+/*
+ * Each fragment program opcode appears to be comprised of 4 32-bit values.
+ *
+ * 0 - Opcode, output reg/mask, ATTRIB source
+ * 1 - Source 0
+ * 2 - Source 1
+ * 3 - Source 2
+ *
+ * There appears to be no special difference between result regs and temp regs.
+ * result.color == R0.xyzw
+ * result.depth == R1.z
+ * When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0
+ * otherwise it is set to 1.
+ *
+ * Constants are inserted directly after the instruction that uses them.
+ *
+ * It appears that it's not possible to use two input registers in one
+ * instruction as the input sourcing is done in the instruction dword
+ * and not the source selection dwords. As such instructions such as:
+ *
+ * ADD result.color, fragment.color, fragment.texcoord[0];
+ *
+ * must be split into two MOV's and then an ADD (nvidia does this) but
+ * I'm not sure why it's not just one MOV and then source the second input
+ * in the ADD instruction..
+ *
+ * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary
+ * negation requires multiplication with a const.
+ *
+ * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE
+ * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO
+ * is implemented simply by not writing to the relevant components of the destination.
+ *
+ * Conditional execution
+ * TODO
+ *
+ * Non-native instructions:
+ * LIT
+ * LRP - MAD+MAD
+ * SUB - ADD, negate second source
+ * RSQ - LG2 + EX2
+ * POW - LG2 + MUL + EX2
+ * SCS - COS + SIN
+ * XPD
+ */
+
+//== Opcode / Destination selection ==
+#define NV30_FP_OP_PROGRAM_END (1 << 0)
+#define NV30_FP_OP_OUT_REG_SHIFT 1
+#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */
+/* Needs to be set when writing outputs to get expected result.. */
+#define NV30_FP_OP_OUT_REG_HALF (1 << 7)
+#define NV30_FP_OP_COND_WRITE_ENABLE (1 << 8)
+#define NV30_FP_OP_OUTMASK_SHIFT 9
+#define NV30_FP_OP_OUTMASK_MASK (0xF << 9)
+# define NV30_FP_OP_OUT_X (1<<9)
+# define NV30_FP_OP_OUT_Y (1<<10)
+# define NV30_FP_OP_OUT_Z (1<<11)
+# define NV30_FP_OP_OUT_W (1<<12)
+/* Uncertain about these, especially the input_src values.. it's possible that
+ * they can be dynamically changed.
+ */
+#define NV30_FP_OP_INPUT_SRC_SHIFT 13
+#define NV30_FP_OP_INPUT_SRC_MASK (15 << 13)
+# define NV30_FP_OP_INPUT_SRC_POSITION 0x0
+# define NV30_FP_OP_INPUT_SRC_COL0 0x1
+# define NV30_FP_OP_INPUT_SRC_COL1 0x2
+# define NV30_FP_OP_INPUT_SRC_FOGC 0x3
+# define NV30_FP_OP_INPUT_SRC_TC0 0x4
+# define NV30_FP_OP_INPUT_SRC_TC(n) (0x4 + n)
+#define NV30_FP_OP_TEX_UNIT_SHIFT 17
+#define NV30_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */
+#define NV30_FP_OP_PRECISION_SHIFT 22
+#define NV30_FP_OP_PRECISION_MASK (3 << 22)
+# define NV30_FP_PRECISION_FP32 0
+# define NV30_FP_PRECISION_FP16 1
+# define NV30_FP_PRECISION_FX12 2
+#define NV30_FP_OP_OPCODE_SHIFT 24
+#define NV30_FP_OP_OPCODE_MASK (0x3F << 24)
+# define NV30_FP_OP_OPCODE_NOP 0x00
+# define NV30_FP_OP_OPCODE_MOV 0x01
+# define NV30_FP_OP_OPCODE_MUL 0x02
+# define NV30_FP_OP_OPCODE_ADD 0x03
+# define NV30_FP_OP_OPCODE_MAD 0x04
+# define NV30_FP_OP_OPCODE_DP3 0x05
+# define NV30_FP_OP_OPCODE_DP4 0x06
+# define NV30_FP_OP_OPCODE_DST 0x07
+# define NV30_FP_OP_OPCODE_MIN 0x08
+# define NV30_FP_OP_OPCODE_MAX 0x09
+# define NV30_FP_OP_OPCODE_SLT 0x0A
+# define NV30_FP_OP_OPCODE_SGE 0x0B
+# define NV30_FP_OP_OPCODE_SLE 0x0C
+# define NV30_FP_OP_OPCODE_SGT 0x0D
+# define NV30_FP_OP_OPCODE_SNE 0x0E
+# define NV30_FP_OP_OPCODE_SEQ 0x0F
+# define NV30_FP_OP_OPCODE_FRC 0x10
+# define NV30_FP_OP_OPCODE_FLR 0x11
+# define NV30_FP_OP_OPCODE_KIL 0x12
+# define NV30_FP_OP_OPCODE_PK4B 0x13
+# define NV30_FP_OP_OPCODE_UP4B 0x14
+# define NV30_FP_OP_OPCODE_DDX 0x15 /* can only write XY */
+# define NV30_FP_OP_OPCODE_DDY 0x16 /* can only write XY */
+# define NV30_FP_OP_OPCODE_TEX 0x17
+# define NV30_FP_OP_OPCODE_TXP 0x18
+# define NV30_FP_OP_OPCODE_TXD 0x19
+# define NV30_FP_OP_OPCODE_RCP 0x1A
+# define NV30_FP_OP_OPCODE_RSQ 0x1B
+# define NV30_FP_OP_OPCODE_EX2 0x1C
+# define NV30_FP_OP_OPCODE_LG2 0x1D
+# define NV30_FP_OP_OPCODE_LIT 0x1E
+# define NV30_FP_OP_OPCODE_LRP 0x1F
+# define NV30_FP_OP_OPCODE_STR 0x20
+# define NV30_FP_OP_OPCODE_SFL 0x21
+# define NV30_FP_OP_OPCODE_COS 0x22
+# define NV30_FP_OP_OPCODE_SIN 0x23
+# define NV30_FP_OP_OPCODE_PK2H 0x24
+# define NV30_FP_OP_OPCODE_UP2H 0x25
+# define NV30_FP_OP_OPCODE_POW 0x26
+# define NV30_FP_OP_OPCODE_PK4UB 0x27
+# define NV30_FP_OP_OPCODE_UP4UB 0x28
+# define NV30_FP_OP_OPCODE_PK2US 0x29
+# define NV30_FP_OP_OPCODE_UP2US 0x2A
+# define NV30_FP_OP_OPCODE_DP2A 0x2E
+# define NV30_FP_OP_OPCODE_TXB 0x31
+# define NV30_FP_OP_OPCODE_RFL 0x36
+# define NV30_FP_OP_OPCODE_DIV 0x3A
+#define NV30_FP_OP_OUT_SAT (1 << 31)
+
+/* high order bits of SRC0 */
+#define NV30_FP_OP_OUT_ABS (1 << 29)
+#define NV30_FP_OP_COND_SWZ_W_SHIFT 27
+#define NV30_FP_OP_COND_SWZ_W_MASK (3 << 27)
+#define NV30_FP_OP_COND_SWZ_Z_SHIFT 25
+#define NV30_FP_OP_COND_SWZ_Z_MASK (3 << 25)
+#define NV30_FP_OP_COND_SWZ_Y_SHIFT 23
+#define NV30_FP_OP_COND_SWZ_Y_MASK (3 << 23)
+#define NV30_FP_OP_COND_SWZ_X_SHIFT 21
+#define NV30_FP_OP_COND_SWZ_X_MASK (3 << 21)
+#define NV30_FP_OP_COND_SWZ_ALL_SHIFT 21
+#define NV30_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21)
+#define NV30_FP_OP_COND_SHIFT 18
+#define NV30_FP_OP_COND_MASK (0x07 << 18)
+# define NV30_FP_OP_COND_FL 0
+# define NV30_FP_OP_COND_LT 1
+# define NV30_FP_OP_COND_EQ 2
+# define NV30_FP_OP_COND_LE 3
+# define NV30_FP_OP_COND_GT 4
+# define NV30_FP_OP_COND_NE 5
+# define NV30_FP_OP_COND_GE 6
+# define NV30_FP_OP_COND_TR 7
+
+/* high order bits of SRC1 */
+#define NV30_FP_OP_DST_SCALE_SHIFT 28
+#define NV30_FP_OP_DST_SCALE_MASK (3 << 28)
+#define NV30_FP_OP_DST_SCALE_1X 0
+#define NV30_FP_OP_DST_SCALE_2X 1
+#define NV30_FP_OP_DST_SCALE_4X 2
+#define NV30_FP_OP_DST_SCALE_8X 3
+#define NV30_FP_OP_DST_SCALE_INV_2X 5
+#define NV30_FP_OP_DST_SCALE_INV_4X 6
+#define NV30_FP_OP_DST_SCALE_INV_8X 7
+
+
+/* high order bits of SRC2 */
+#define NV30_FP_OP_INDEX_INPUT (1 << 30)
+
+//== Register selection ==
+#define NV30_FP_REG_TYPE_SHIFT 0
+#define NV30_FP_REG_TYPE_MASK (3 << 0)
+# define NV30_FP_REG_TYPE_TEMP 0
+# define NV30_FP_REG_TYPE_INPUT 1
+# define NV30_FP_REG_TYPE_CONST 2
+#define NV30_FP_REG_SRC_SHIFT 2 /* uncertain */
+#define NV30_FP_REG_SRC_MASK (31 << 2)
+#define NV30_FP_REG_SRC_HALF (1 << 8)
+#define NV30_FP_REG_SWZ_ALL_SHIFT 9
+#define NV30_FP_REG_SWZ_ALL_MASK (255 << 9)
+#define NV30_FP_REG_SWZ_X_SHIFT 9
+#define NV30_FP_REG_SWZ_X_MASK (3 << 9)
+#define NV30_FP_REG_SWZ_Y_SHIFT 11
+#define NV30_FP_REG_SWZ_Y_MASK (3 << 11)
+#define NV30_FP_REG_SWZ_Z_SHIFT 13
+#define NV30_FP_REG_SWZ_Z_MASK (3 << 13)
+#define NV30_FP_REG_SWZ_W_SHIFT 15
+#define NV30_FP_REG_SWZ_W_MASK (3 << 15)
+# define NV30_FP_SWIZZLE_X 0
+# define NV30_FP_SWIZZLE_Y 1
+# define NV30_FP_SWIZZLE_Z 2
+# define NV30_FP_SWIZZLE_W 3
+#define NV30_FP_REG_NEGATE (1 << 17)
+
+#define NV30SR_NONE 0
+#define NV30SR_OUTPUT 1
+#define NV30SR_INPUT 2
+#define NV30SR_TEMP 3
+#define NV30SR_CONST 4
+
+struct nv30_sreg {
+ int type;
+ int index;
+
+ int dst_scale;
+
+ int negate;
+ int abs;
+ int swz[4];
+
+ int cc_update;
+ int cc_update_reg;
+ int cc_test;
+ int cc_test_reg;
+ int cc_swz[4];
+};
+
+static INLINE struct nv30_sreg
+nv30_sr(int type, int index)
+{
+ struct nv30_sreg temp = {
+ .type = type,
+ .index = index,
+ .dst_scale = DEF_SCALE,
+ .abs = 0,
+ .negate = 0,
+ .swz = { 0, 1, 2, 3 },
+ .cc_update = 0,
+ .cc_update_reg = 0,
+ .cc_test = DEF_CTEST,
+ .cc_test_reg = 0,
+ .cc_swz = { 0, 1, 2, 3 },
+ };
+ return temp;
+}
+
+static INLINE struct nv30_sreg
+nv30_sr_swz(struct nv30_sreg src, int x, int y, int z, int w)
+{
+ struct nv30_sreg dst = src;
+
+ dst.swz[SWZ_X] = src.swz[x];
+ dst.swz[SWZ_Y] = src.swz[y];
+ dst.swz[SWZ_Z] = src.swz[z];
+ dst.swz[SWZ_W] = src.swz[w];
+ return dst;
+}
+
+static INLINE struct nv30_sreg
+nv30_sr_neg(struct nv30_sreg src)
+{
+ src.negate = !src.negate;
+ return src;
+}
+
+static INLINE struct nv30_sreg
+nv30_sr_abs(struct nv30_sreg src)
+{
+ src.abs = 1;
+ return src;
+}
+
+static INLINE struct nv30_sreg
+nv30_sr_scale(struct nv30_sreg src, int scale)
+{
+ src.dst_scale = scale;
+ return src;
+}
+
+#endif
diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c
new file mode 100644
index 0000000000..b91e972c12
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state.c
@@ -0,0 +1,728 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "nv30_context.h"
+#include "nv30_state.h"
+
+static void *
+nv30_blend_state_create(struct pipe_context *pipe,
+ const struct pipe_blend_state *cso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nouveau_grobj *rankine = nv30->screen->rankine;
+ struct nv30_blend_state *bso = CALLOC(1, sizeof(*bso));
+ struct nouveau_stateobj *so = so_new(16, 0);
+
+ if (cso->blend_enable) {
+ so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 3);
+ so_data (so, 1);
+ so_data (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) |
+ nvgl_blend_func(cso->rgb_src_factor));
+ so_data (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 |
+ nvgl_blend_func(cso->rgb_dst_factor));
+ /* FIXME: Gallium assumes GL_EXT_blend_func_separate.
+ It is not the case for NV30 */
+ so_method(so, rankine, NV34TCL_BLEND_EQUATION, 1);
+ so_data (so, nvgl_blend_eqn(cso->rgb_func));
+ } else {
+ so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_method(so, rankine, NV34TCL_COLOR_MASK, 1);
+ so_data (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) |
+ ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) |
+ ((cso->colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) |
+ ((cso->colormask & PIPE_MASK_B) ? (0x01 << 0) : 0)));
+
+ if (cso->logicop_enable) {
+ so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2);
+ so_data (so, 1);
+ so_data (so, nvgl_logicop_func(cso->logicop_func));
+ } else {
+ so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_method(so, rankine, NV34TCL_DITHER_ENABLE, 1);
+ so_data (so, cso->dither ? 1 : 0);
+
+ so_ref(so, &bso->so);
+ so_ref(NULL, &so);
+ bso->pipe = *cso;
+ return (void *)bso;
+}
+
+static void
+nv30_blend_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->blend = hwcso;
+ nv30->dirty |= NV30_NEW_BLEND;
+}
+
+static void
+nv30_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_blend_state *bso = hwcso;
+
+ so_ref(NULL, &bso->so);
+ FREE(bso);
+}
+
+
+static INLINE unsigned
+wrap_mode(unsigned wrap) {
+ unsigned ret;
+
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ ret = NV34TCL_TX_WRAP_S_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ ret = NV34TCL_TX_WRAP_S_MIRRORED_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ ret = NV34TCL_TX_WRAP_S_CLAMP_TO_EDGE;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ ret = NV34TCL_TX_WRAP_S_CLAMP_TO_BORDER;
+ break;
+ case PIPE_TEX_WRAP_CLAMP:
+ ret = NV34TCL_TX_WRAP_S_CLAMP;
+ break;
+/* case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_EDGE;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_BORDER;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP;
+ break;*/
+ default:
+ NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+ ret = NV34TCL_TX_WRAP_S_REPEAT;
+ break;
+ }
+
+ return ret >> NV34TCL_TX_WRAP_S_SHIFT;
+}
+
+static void *
+nv30_sampler_state_create(struct pipe_context *pipe,
+ const struct pipe_sampler_state *cso)
+{
+ struct nv30_sampler_state *ps;
+ uint32_t filter = 0;
+
+ ps = MALLOC(sizeof(struct nv30_sampler_state));
+
+ ps->fmt = 0;
+ /* TODO: Not all RECTs formats have this bit set, bits 15-8 of format
+ are the tx format to use. We should store normalized coord flag
+ in sampler state structure, and set appropriate format in
+ nvxx_fragtex_build()
+ */
+ /*NV34TCL_TX_FORMAT_RECT*/
+ /*if (!cso->normalized_coords) {
+ ps->fmt |= (1<<14) ;
+ }*/
+
+ ps->wrap = ((wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) |
+ (wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) |
+ (wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT));
+
+ ps->en = 0;
+
+ if (cso->max_anisotropy >= 8.0) {
+ ps->en |= NV34TCL_TX_ENABLE_ANISO_8X;
+ } else
+ if (cso->max_anisotropy >= 4.0) {
+ ps->en |= NV34TCL_TX_ENABLE_ANISO_4X;
+ } else
+ if (cso->max_anisotropy >= 2.0) {
+ ps->en |= NV34TCL_TX_ENABLE_ANISO_2X;
+ }
+
+ switch (cso->mag_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ filter |= NV34TCL_TX_FILTER_MAGNIFY_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ filter |= NV34TCL_TX_FILTER_MAGNIFY_NEAREST;
+ break;
+ }
+
+ switch (cso->min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR;
+ break;
+ }
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST;
+ break;
+ }
+ break;
+ }
+
+ ps->filt = filter;
+
+ {
+ float limit;
+
+ limit = CLAMP(cso->lod_bias, -16.0, 15.0);
+ ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
+
+ limit = CLAMP(cso->max_lod, 0.0, 15.0);
+ ps->en |= (int)(limit) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/;
+
+ limit = CLAMP(cso->min_lod, 0.0, 15.0);
+ ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/;
+ }
+
+ if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ switch (cso->compare_func) {
+ case PIPE_FUNC_NEVER:
+ ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NEVER;
+ break;
+ case PIPE_FUNC_GREATER:
+ ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GREATER;
+ break;
+ case PIPE_FUNC_EQUAL:
+ ps->wrap |= NV34TCL_TX_WRAP_RCOMP_EQUAL;
+ break;
+ case PIPE_FUNC_GEQUAL:
+ ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GEQUAL;
+ break;
+ case PIPE_FUNC_LESS:
+ ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LESS;
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NOTEQUAL;
+ break;
+ case PIPE_FUNC_LEQUAL:
+ ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LEQUAL;
+ break;
+ case PIPE_FUNC_ALWAYS:
+ ps->wrap |= NV34TCL_TX_WRAP_RCOMP_ALWAYS;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) |
+ (float_to_ubyte(cso->border_color[0]) << 16) |
+ (float_to_ubyte(cso->border_color[1]) << 8) |
+ (float_to_ubyte(cso->border_color[2]) << 0));
+
+ return (void *)ps;
+}
+
+static void
+nv30_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv30->tex_sampler[unit] = sampler[unit];
+ nv30->dirty_samplers |= (1 << unit);
+ }
+
+ for (unit = nr; unit < nv30->nr_samplers; unit++) {
+ nv30->tex_sampler[unit] = NULL;
+ nv30->dirty_samplers |= (1 << unit);
+ }
+
+ nv30->nr_samplers = nr;
+ nv30->dirty |= NV30_NEW_SAMPLER;
+}
+
+static void
+nv30_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void
+nv30_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+ struct pipe_texture **miptree)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ pipe_texture_reference((struct pipe_texture **)
+ &nv30->tex_miptree[unit], miptree[unit]);
+ nv30->dirty_samplers |= (1 << unit);
+ }
+
+ for (unit = nr; unit < nv30->nr_textures; unit++) {
+ pipe_texture_reference((struct pipe_texture **)
+ &nv30->tex_miptree[unit], NULL);
+ nv30->dirty_samplers |= (1 << unit);
+ }
+
+ nv30->nr_textures = nr;
+ nv30->dirty |= NV30_NEW_SAMPLER;
+}
+
+static void *
+nv30_rasterizer_state_create(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso));
+ struct nouveau_stateobj *so = so_new(32, 0);
+ struct nouveau_grobj *rankine = nv30->screen->rankine;
+
+ /*XXX: ignored:
+ * light_twoside
+ * point_smooth -nohw
+ * multisample
+ */
+
+ so_method(so, rankine, NV34TCL_SHADE_MODEL, 1);
+ so_data (so, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT :
+ NV34TCL_SHADE_MODEL_SMOOTH);
+
+ so_method(so, rankine, NV34TCL_LINE_WIDTH, 2);
+ so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff);
+ so_data (so, cso->line_smooth ? 1 : 0);
+ so_method(so, rankine, NV34TCL_LINE_STIPPLE_ENABLE, 2);
+ so_data (so, cso->line_stipple_enable ? 1 : 0);
+ so_data (so, (cso->line_stipple_pattern << 16) |
+ cso->line_stipple_factor);
+
+ so_method(so, rankine, NV34TCL_POINT_SIZE, 1);
+ so_data (so, fui(cso->point_size));
+
+ so_method(so, rankine, NV34TCL_POLYGON_MODE_FRONT, 6);
+ if (cso->front_winding == PIPE_WINDING_CCW) {
+ so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+ so_data(so, nvgl_polygon_mode(cso->fill_cw));
+ switch (cso->cull_mode) {
+ case PIPE_WINDING_CCW:
+ so_data(so, NV34TCL_CULL_FACE_FRONT);
+ break;
+ case PIPE_WINDING_CW:
+ so_data(so, NV34TCL_CULL_FACE_BACK);
+ break;
+ case PIPE_WINDING_BOTH:
+ so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK);
+ break;
+ default:
+ so_data(so, NV34TCL_CULL_FACE_BACK);
+ break;
+ }
+ so_data(so, NV34TCL_FRONT_FACE_CCW);
+ } else {
+ so_data(so, nvgl_polygon_mode(cso->fill_cw));
+ so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+ switch (cso->cull_mode) {
+ case PIPE_WINDING_CCW:
+ so_data(so, NV34TCL_CULL_FACE_BACK);
+ break;
+ case PIPE_WINDING_CW:
+ so_data(so, NV34TCL_CULL_FACE_FRONT);
+ break;
+ case PIPE_WINDING_BOTH:
+ so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK);
+ break;
+ default:
+ so_data(so, NV34TCL_CULL_FACE_BACK);
+ break;
+ }
+ so_data(so, NV34TCL_FRONT_FACE_CW);
+ }
+ so_data(so, cso->poly_smooth ? 1 : 0);
+ so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0);
+
+ so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_data (so, cso->poly_stipple_enable ? 1 : 0);
+
+ so_method(so, rankine, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if (cso->offset_cw || cso->offset_ccw) {
+ so_method(so, rankine, NV34TCL_POLYGON_OFFSET_FACTOR, 2);
+ so_data (so, fui(cso->offset_scale));
+ so_data (so, fui(cso->offset_units * 2));
+ }
+
+ so_method(so, rankine, NV34TCL_POINT_SPRITE, 1);
+ if (cso->point_sprite) {
+ unsigned psctl = (1 << 0), i;
+
+ for (i = 0; i < 8; i++) {
+ if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE)
+ psctl |= (1 << (8 + i));
+ }
+
+ so_data(so, psctl);
+ } else {
+ so_data(so, 0);
+ }
+
+ so_ref(so, &rsso->so);
+ so_ref(NULL, &so);
+ rsso->pipe = *cso;
+ return (void *)rsso;
+}
+
+static void
+nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->rasterizer = hwcso;
+ nv30->dirty |= NV30_NEW_RAST;
+ /*nv30->draw_dirty |= NV30_NEW_RAST;*/
+}
+
+static void
+nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_rasterizer_state *rsso = hwcso;
+
+ so_ref(NULL, &rsso->so);
+ FREE(rsso);
+}
+
+static void *
+nv30_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
+ struct nouveau_stateobj *so = so_new(32, 0);
+ struct nouveau_grobj *rankine = nv30->screen->rankine;
+
+ so_method(so, rankine, NV34TCL_DEPTH_FUNC, 3);
+ so_data (so, nvgl_comparison_op(cso->depth.func));
+ so_data (so, cso->depth.writemask ? 1 : 0);
+ so_data (so, cso->depth.enabled ? 1 : 0);
+
+ so_method(so, rankine, NV34TCL_ALPHA_FUNC_ENABLE, 3);
+ so_data (so, cso->alpha.enabled ? 1 : 0);
+ so_data (so, nvgl_comparison_op(cso->alpha.func));
+ so_data (so, float_to_ubyte(cso->alpha.ref_value));
+
+ if (cso->stencil[0].enabled) {
+ so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 8);
+ so_data (so, cso->stencil[0].enabled ? 1 : 0);
+ so_data (so, cso->stencil[0].writemask);
+ so_data (so, nvgl_comparison_op(cso->stencil[0].func));
+ so_data (so, cso->stencil[0].ref_value);
+ so_data (so, cso->stencil[0].valuemask);
+ so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
+ } else {
+ so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ if (cso->stencil[1].enabled) {
+ so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 8);
+ so_data (so, cso->stencil[1].enabled ? 1 : 0);
+ so_data (so, cso->stencil[1].writemask);
+ so_data (so, nvgl_comparison_op(cso->stencil[1].func));
+ so_data (so, cso->stencil[1].ref_value);
+ so_data (so, cso->stencil[1].valuemask);
+ so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
+ } else {
+ so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_ref(so, &zsaso->so);
+ so_ref(NULL, &so);
+ zsaso->pipe = *cso;
+ return (void *)zsaso;
+}
+
+static void
+nv30_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->zsa = hwcso;
+ nv30->dirty |= NV30_NEW_ZSA;
+}
+
+static void
+nv30_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_zsa_state *zsaso = hwcso;
+
+ so_ref(NULL, &zsaso->so);
+ FREE(zsaso);
+}
+
+static void *
+nv30_vp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ /*struct nv30_context *nv30 = nv30_context(pipe);*/
+ struct nv30_vertex_program *vp;
+
+ vp = CALLOC(1, sizeof(struct nv30_vertex_program));
+ vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ /*vp->draw = draw_create_vertex_shader(nv30->draw, &vp->pipe);*/
+
+ return (void *)vp;
+}
+
+static void
+nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->vertprog = hwcso;
+ nv30->dirty |= NV30_NEW_VERTPROG;
+ /*nv30->draw_dirty |= NV30_NEW_VERTPROG;*/
+}
+
+static void
+nv30_vp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_vertex_program *vp = hwcso;
+
+ /*draw_delete_vertex_shader(nv30->draw, vp->draw);*/
+ nv30_vertprog_destroy(nv30, vp);
+ FREE((void*)vp->pipe.tokens);
+ FREE(vp);
+}
+
+static void *
+nv30_fp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv30_fragment_program *fp;
+
+ fp = CALLOC(1, sizeof(struct nv30_fragment_program));
+ fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+
+ tgsi_scan_shader(fp->pipe.tokens, &fp->info);
+
+ return (void *)fp;
+}
+
+static void
+nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->fragprog = hwcso;
+ nv30->dirty |= NV30_NEW_FRAGPROG;
+}
+
+static void
+nv30_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_fragment_program *fp = hwcso;
+
+ nv30_fragprog_destroy(nv30, fp);
+ FREE((void*)fp->pipe.tokens);
+ FREE(fp);
+}
+
+static void
+nv30_set_blend_color(struct pipe_context *pipe,
+ const struct pipe_blend_color *bcol)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->blend_colour = *bcol;
+ nv30->dirty |= NV30_NEW_BCOL;
+}
+
+static void
+nv30_set_clip_state(struct pipe_context *pipe,
+ const struct pipe_clip_state *clip)
+{
+}
+
+static void
+nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+ const struct pipe_constant_buffer *buf )
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->constbuf[shader] = buf->buffer;
+ nv30->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float));
+
+ if (shader == PIPE_SHADER_VERTEX) {
+ nv30->dirty |= NV30_NEW_VERTPROG;
+ } else
+ if (shader == PIPE_SHADER_FRAGMENT) {
+ nv30->dirty |= NV30_NEW_FRAGPROG;
+ }
+}
+
+static void
+nv30_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->framebuffer = *fb;
+ nv30->dirty |= NV30_NEW_FB;
+}
+
+static void
+nv30_set_polygon_stipple(struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ memcpy(nv30->stipple, stipple->stipple, 4 * 32);
+ nv30->dirty |= NV30_NEW_STIPPLE;
+}
+
+static void
+nv30_set_scissor_state(struct pipe_context *pipe,
+ const struct pipe_scissor_state *s)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->scissor = *s;
+ nv30->dirty |= NV30_NEW_SCISSOR;
+}
+
+static void
+nv30_set_viewport_state(struct pipe_context *pipe,
+ const struct pipe_viewport_state *vpt)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->viewport = *vpt;
+ nv30->dirty |= NV30_NEW_VIEWPORT;
+ /*nv30->draw_dirty |= NV30_NEW_VIEWPORT;*/
+}
+
+static void
+nv30_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_buffer *vb)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ memcpy(nv30->vtxbuf, vb, sizeof(*vb) * count);
+ nv30->vtxbuf_nr = count;
+
+ nv30->dirty |= NV30_NEW_ARRAYS;
+ /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
+}
+
+static void
+nv30_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_element *ve)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ memcpy(nv30->vtxelt, ve, sizeof(*ve) * count);
+ nv30->vtxelt_nr = count;
+
+ nv30->dirty |= NV30_NEW_ARRAYS;
+ /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
+}
+
+static void
+nv30_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->edgeflags = bitfield;
+ nv30->dirty |= NV30_NEW_ARRAYS;
+ /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
+}
+
+void
+nv30_init_state_functions(struct nv30_context *nv30)
+{
+ nv30->pipe.create_blend_state = nv30_blend_state_create;
+ nv30->pipe.bind_blend_state = nv30_blend_state_bind;
+ nv30->pipe.delete_blend_state = nv30_blend_state_delete;
+
+ nv30->pipe.create_sampler_state = nv30_sampler_state_create;
+ nv30->pipe.bind_sampler_states = nv30_sampler_state_bind;
+ nv30->pipe.delete_sampler_state = nv30_sampler_state_delete;
+ nv30->pipe.set_sampler_textures = nv30_set_sampler_texture;
+
+ nv30->pipe.create_rasterizer_state = nv30_rasterizer_state_create;
+ nv30->pipe.bind_rasterizer_state = nv30_rasterizer_state_bind;
+ nv30->pipe.delete_rasterizer_state = nv30_rasterizer_state_delete;
+
+ nv30->pipe.create_depth_stencil_alpha_state =
+ nv30_depth_stencil_alpha_state_create;
+ nv30->pipe.bind_depth_stencil_alpha_state =
+ nv30_depth_stencil_alpha_state_bind;
+ nv30->pipe.delete_depth_stencil_alpha_state =
+ nv30_depth_stencil_alpha_state_delete;
+
+ nv30->pipe.create_vs_state = nv30_vp_state_create;
+ nv30->pipe.bind_vs_state = nv30_vp_state_bind;
+ nv30->pipe.delete_vs_state = nv30_vp_state_delete;
+
+ nv30->pipe.create_fs_state = nv30_fp_state_create;
+ nv30->pipe.bind_fs_state = nv30_fp_state_bind;
+ nv30->pipe.delete_fs_state = nv30_fp_state_delete;
+
+ nv30->pipe.set_blend_color = nv30_set_blend_color;
+ nv30->pipe.set_clip_state = nv30_set_clip_state;
+ nv30->pipe.set_constant_buffer = nv30_set_constant_buffer;
+ nv30->pipe.set_framebuffer_state = nv30_set_framebuffer_state;
+ nv30->pipe.set_polygon_stipple = nv30_set_polygon_stipple;
+ nv30->pipe.set_scissor_state = nv30_set_scissor_state;
+ nv30->pipe.set_viewport_state = nv30_set_viewport_state;
+
+ nv30->pipe.set_edgeflags = nv30_set_edgeflags;
+ nv30->pipe.set_vertex_buffers = nv30_set_vertex_buffers;
+ nv30->pipe.set_vertex_elements = nv30_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv30/nv30_state.h b/src/gallium/drivers/nv30/nv30_state.h
new file mode 100644
index 0000000000..e6f23bf166
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state.h
@@ -0,0 +1,85 @@
+#ifndef __NV30_STATE_H__
+#define __NV30_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+
+struct nv30_sampler_state {
+ uint32_t fmt;
+ uint32_t wrap;
+ uint32_t en;
+ uint32_t filt;
+ uint32_t bcol;
+};
+
+struct nv30_vertex_program_exec {
+ uint32_t data[4];
+ boolean has_branch_offset;
+ int const_index;
+};
+
+struct nv30_vertex_program_data {
+ int index; /* immediates == -1 */
+ float value[4];
+};
+
+struct nv30_vertex_program {
+ struct pipe_shader_state pipe;
+
+ boolean translated;
+
+ struct nv30_vertex_program_exec *insns;
+ unsigned nr_insns;
+ struct nv30_vertex_program_data *consts;
+ unsigned nr_consts;
+
+ struct nouveau_resource *exec;
+ unsigned exec_start;
+ struct nouveau_resource *data;
+ unsigned data_start;
+ unsigned data_start_min;
+
+ uint32_t ir;
+ uint32_t or;
+ struct nouveau_stateobj *so;
+};
+
+struct nv30_fragment_program_data {
+ unsigned offset;
+ unsigned index;
+};
+
+struct nv30_fragment_program {
+ struct pipe_shader_state pipe;
+ struct tgsi_shader_info info;
+
+ boolean translated;
+ boolean on_hw;
+ unsigned samplers;
+
+ uint32_t *insn;
+ int insn_len;
+
+ struct nv30_fragment_program_data *consts;
+ unsigned nr_consts;
+
+ struct pipe_buffer *buffer;
+
+ uint32_t fp_control;
+ uint32_t fp_reg_control;
+ struct nouveau_stateobj *so;
+};
+
+struct nv30_miptree {
+ struct pipe_texture base;
+
+ struct pipe_buffer *buffer;
+ uint total_size;
+
+ struct {
+ uint pitch;
+ uint *image_offset;
+ } level[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+#endif
diff --git a/src/gallium/drivers/nv30/nv30_state_blend.c b/src/gallium/drivers/nv30/nv30_state_blend.c
new file mode 100644
index 0000000000..64cf9ae93a
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_blend.c
@@ -0,0 +1,41 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_blend_validate(struct nv30_context *nv30)
+{
+ so_ref(nv30->blend->so, &nv30->state.hw[NV30_STATE_BLEND]);
+ return TRUE;
+}
+
+struct nv30_state_entry nv30_state_blend = {
+ .validate = nv30_state_blend_validate,
+ .dirty = {
+ .pipe = NV30_NEW_BLEND,
+ .hw = NV30_STATE_BLEND
+ }
+};
+
+static boolean
+nv30_state_blend_colour_validate(struct nv30_context *nv30)
+{
+ struct nouveau_stateobj *so = so_new(2, 0);
+ struct pipe_blend_color *bcol = &nv30->blend_colour;
+
+ so_method(so, nv30->screen->rankine, NV34TCL_BLEND_COLOR, 1);
+ so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) |
+ (float_to_ubyte(bcol->color[0]) << 16) |
+ (float_to_ubyte(bcol->color[1]) << 8) |
+ (float_to_ubyte(bcol->color[2]) << 0)));
+
+ so_ref(so, &nv30->state.hw[NV30_STATE_BCOL]);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv30_state_entry nv30_state_blend_colour = {
+ .validate = nv30_state_blend_colour_validate,
+ .dirty = {
+ .pipe = NV30_NEW_BCOL,
+ .hw = NV30_STATE_BCOL
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c
new file mode 100644
index 0000000000..621b8846c8
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_emit.c
@@ -0,0 +1,111 @@
+#include "nv30_context.h"
+#include "nv30_state.h"
+
+static struct nv30_state_entry *render_states[] = {
+ &nv30_state_framebuffer,
+ &nv30_state_rasterizer,
+ &nv30_state_scissor,
+ &nv30_state_stipple,
+ &nv30_state_fragprog,
+ &nv30_state_fragtex,
+ &nv30_state_vertprog,
+ &nv30_state_blend,
+ &nv30_state_blend_colour,
+ &nv30_state_zsa,
+ &nv30_state_viewport,
+ &nv30_state_vbo,
+ NULL
+};
+
+static void
+nv30_state_do_validate(struct nv30_context *nv30,
+ struct nv30_state_entry **states)
+{
+ while (*states) {
+ struct nv30_state_entry *e = *states;
+
+ if (nv30->dirty & e->dirty.pipe) {
+ if (e->validate(nv30)) {
+ nv30->state.dirty |= (1ULL << e->dirty.hw);
+ }
+ }
+
+ states++;
+ }
+ nv30->dirty = 0;
+}
+
+void
+nv30_state_emit(struct nv30_context *nv30)
+{
+ struct nouveau_channel *chan = nv30->screen->base.channel;
+ struct nv30_state *state = &nv30->state;
+ struct nv30_screen *screen = nv30->screen;
+ unsigned i, samplers;
+ uint64_t states;
+
+ if (nv30->pctx_id != screen->cur_pctx) {
+ for (i = 0; i < NV30_STATE_MAX; i++) {
+ if (state->hw[i] && screen->state[i] != state->hw[i])
+ state->dirty |= (1ULL << i);
+ }
+
+ screen->cur_pctx = nv30->pctx_id;
+ }
+
+ for (i = 0, states = state->dirty; states; i++) {
+ if (!(states & (1ULL << i)))
+ continue;
+ so_ref (state->hw[i], &nv30->screen->state[i]);
+ if (state->hw[i])
+ so_emit(chan, nv30->screen->state[i]);
+ states &= ~(1ULL << i);
+ }
+
+ state->dirty = 0;
+
+ so_emit_reloc_markers(chan, state->hw[NV30_STATE_FB]);
+ for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
+ if (!(samplers & (1 << i)))
+ continue;
+ so_emit_reloc_markers(chan,
+ state->hw[NV30_STATE_FRAGTEX0+i]);
+ samplers &= ~(1ULL << i);
+ }
+ so_emit_reloc_markers(chan, state->hw[NV30_STATE_FRAGPROG]);
+ if (state->hw[NV30_STATE_VTXBUF] /*&& nv30->render_mode == HW*/)
+ so_emit_reloc_markers(chan, state->hw[NV30_STATE_VTXBUF]);
+}
+
+boolean
+nv30_state_validate(struct nv30_context *nv30)
+{
+#if 0
+ boolean was_sw = nv30->fallback_swtnl ? TRUE : FALSE;
+
+ if (nv30->render_mode != HW) {
+ /* Don't even bother trying to go back to hw if none
+ * of the states that caused swtnl previously have changed.
+ */
+ if ((nv30->fallback_swtnl & nv30->dirty)
+ != nv30->fallback_swtnl)
+ return FALSE;
+
+ /* Attempt to go to hwtnl again */
+ nv30->pipe.flush(&nv30->pipe, 0, NULL);
+ nv30->dirty |= (NV30_NEW_VIEWPORT |
+ NV30_NEW_VERTPROG |
+ NV30_NEW_ARRAYS);
+ nv30->render_mode = HW;
+ }
+#endif
+ nv30_state_do_validate(nv30, render_states);
+#if 0
+ if (nv30->fallback_swtnl || nv30->fallback_swrast)
+ return FALSE;
+
+ if (was_sw)
+ NOUVEAU_ERR("swtnl->hw\n");
+#endif
+ return TRUE;
+}
diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c
new file mode 100644
index 0000000000..44b6a74715
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_fb.c
@@ -0,0 +1,145 @@
+#include "nv30_context.h"
+#include "nouveau/nouveau_util.h"
+
+static boolean
+nv30_state_framebuffer_validate(struct nv30_context *nv30)
+{
+ struct pipe_framebuffer_state *fb = &nv30->framebuffer;
+ struct nouveau_channel *chan = nv30->screen->base.channel;
+ struct nouveau_grobj *rankine = nv30->screen->rankine;
+ struct nv04_surface *rt[2], *zeta = NULL;
+ uint32_t rt_enable, rt_format;
+ int i, colour_format = 0, zeta_format = 0;
+ struct nouveau_stateobj *so = so_new(64, 10);
+ unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
+ unsigned w = fb->width;
+ unsigned h = fb->height;
+ struct nv30_miptree *nv30mt;
+
+ rt_enable = 0;
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ if (colour_format) {
+ assert(colour_format == fb->cbufs[i]->format);
+ } else {
+ colour_format = fb->cbufs[i]->format;
+ rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i);
+ rt[i] = (struct nv04_surface *)fb->cbufs[i];
+ }
+ }
+
+ if (rt_enable & NV34TCL_RT_ENABLE_COLOR1)
+ rt_enable |= NV34TCL_RT_ENABLE_MRT;
+
+ if (fb->zsbuf) {
+ zeta_format = fb->zsbuf->format;
+ zeta = (struct nv04_surface *)fb->zsbuf;
+ }
+
+ if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+ assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1)));
+ for (i = 1; i < fb->nr_cbufs; i++)
+ assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR));
+
+ /* FIXME: NV34TCL_RT_FORMAT_LOG2_[WIDTH/HEIGHT] */
+ rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED |
+ log2i(fb->width) << 16 /*NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT*/ |
+ log2i(fb->height) << 24 /*NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT*/;
+ }
+ else
+ rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;
+
+ switch (colour_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case 0:
+ rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8;
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5;
+ break;
+ default:
+ assert(0);
+ }
+
+ switch (zeta_format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16;
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case 0:
+ rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (rt_enable & NV34TCL_RT_ENABLE_COLOR0) {
+ uint32_t pitch = rt[0]->pitch;
+ if (zeta) {
+ pitch |= (zeta->pitch << 16);
+ } else {
+ pitch |= (pitch << 16);
+ }
+
+ nv30mt = (struct nv30_miptree *)rt[0]->base.texture;
+ so_method(so, rankine, NV34TCL_DMA_COLOR0, 1);
+ so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR,
+ chan->vram->handle, chan->gart->handle);
+ so_method(so, rankine, NV34TCL_COLOR0_PITCH, 2);
+ so_data (so, pitch);
+ so_reloc (so, nouveau_bo(nv30mt->buffer), rt[0]->base.offset,
+ rt_flags | NOUVEAU_BO_LOW, 0, 0);
+ }
+
+ if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) {
+ nv30mt = (struct nv30_miptree *)rt[1]->base.texture;
+ so_method(so, rankine, NV34TCL_DMA_COLOR1, 1);
+ so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR,
+ chan->vram->handle, chan->gart->handle);
+ so_method(so, rankine, NV34TCL_COLOR1_OFFSET, 2);
+ so_reloc (so, nouveau_bo(nv30mt->buffer), rt[1]->base.offset,
+ rt_flags | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, rt[1]->pitch);
+ }
+
+ if (zeta_format) {
+ nv30mt = (struct nv30_miptree *)zeta->base.texture;
+ so_method(so, rankine, NV34TCL_DMA_ZETA, 1);
+ so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR,
+ chan->vram->handle, chan->gart->handle);
+ so_method(so, rankine, NV34TCL_ZETA_OFFSET, 1);
+ so_reloc (so, nouveau_bo(nv30mt->buffer), zeta->base.offset,
+ rt_flags | NOUVEAU_BO_LOW, 0, 0);
+ /* TODO: allocate LMA depth buffer */
+ }
+
+ so_method(so, rankine, NV34TCL_RT_ENABLE, 1);
+ so_data (so, rt_enable);
+ so_method(so, rankine, NV34TCL_RT_HORIZ, 3);
+ so_data (so, (w << 16) | 0);
+ so_data (so, (h << 16) | 0);
+ so_data (so, rt_format);
+ so_method(so, rankine, NV34TCL_VIEWPORT_HORIZ, 2);
+ so_data (so, (w << 16) | 0);
+ so_data (so, (h << 16) | 0);
+ so_method(so, rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+ so_data (so, ((w - 1) << 16) | 0);
+ so_data (so, ((h - 1) << 16) | 0);
+ so_method(so, rankine, 0x1d88, 1);
+ so_data (so, (1 << 12) | h);
+ /* Wonder why this is needed, context should all be set to zero on init */
+ so_method(so, rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1);
+ so_data (so, 0);
+
+ so_ref(so, &nv30->state.hw[NV30_STATE_FB]);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv30_state_entry nv30_state_framebuffer = {
+ .validate = nv30_state_framebuffer_validate,
+ .dirty = {
+ .pipe = NV30_NEW_FB,
+ .hw = NV30_STATE_FB
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_rasterizer.c b/src/gallium/drivers/nv30/nv30_state_rasterizer.c
new file mode 100644
index 0000000000..6d1b60e043
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_rasterizer.c
@@ -0,0 +1,17 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_rasterizer_validate(struct nv30_context *nv30)
+{
+ so_ref(nv30->rasterizer->so,
+ &nv30->state.hw[NV30_STATE_RAST]);
+ return TRUE;
+}
+
+struct nv30_state_entry nv30_state_rasterizer = {
+ .validate = nv30_state_rasterizer_validate,
+ .dirty = {
+ .pipe = NV30_NEW_RAST,
+ .hw = NV30_STATE_RAST
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_scissor.c b/src/gallium/drivers/nv30/nv30_state_scissor.c
new file mode 100644
index 0000000000..3ac7a8471e
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_scissor.c
@@ -0,0 +1,36 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_scissor_validate(struct nv30_context *nv30)
+{
+ struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe;
+ struct pipe_scissor_state *s = &nv30->scissor;
+ struct nouveau_stateobj *so;
+
+ if (nv30->state.hw[NV30_STATE_SCISSOR] &&
+ (rast->scissor == 0 && nv30->state.scissor_enabled == 0))
+ return FALSE;
+ nv30->state.scissor_enabled = rast->scissor;
+
+ so = so_new(3, 0);
+ so_method(so, nv30->screen->rankine, NV34TCL_SCISSOR_HORIZ, 2);
+ if (nv30->state.scissor_enabled) {
+ so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
+ so_data (so, ((s->maxy - s->miny) << 16) | s->miny);
+ } else {
+ so_data (so, 4096 << 16);
+ so_data (so, 4096 << 16);
+ }
+
+ so_ref(so, &nv30->state.hw[NV30_STATE_SCISSOR]);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv30_state_entry nv30_state_scissor = {
+ .validate = nv30_state_scissor_validate,
+ .dirty = {
+ .pipe = NV30_NEW_SCISSOR | NV30_NEW_RAST,
+ .hw = NV30_STATE_SCISSOR
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_stipple.c b/src/gallium/drivers/nv30/nv30_state_stipple.c
new file mode 100644
index 0000000000..d0c791ac08
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_stipple.c
@@ -0,0 +1,40 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_stipple_validate(struct nv30_context *nv30)
+{
+ struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe;
+ struct nouveau_grobj *rankine = nv30->screen->rankine;
+ struct nouveau_stateobj *so;
+
+ if (nv30->state.hw[NV30_STATE_STIPPLE] &&
+ (rast->poly_stipple_enable == 0 && nv30->state.stipple_enabled == 0))
+ return FALSE;
+
+ if (rast->poly_stipple_enable) {
+ unsigned i;
+
+ so = so_new(35, 0);
+ so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_data (so, 1);
+ so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32);
+ for (i = 0; i < 32; i++)
+ so_data(so, nv30->stipple[i]);
+ } else {
+ so = so_new(2, 0);
+ so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_ref(so, &nv30->state.hw[NV30_STATE_STIPPLE]);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv30_state_entry nv30_state_stipple = {
+ .validate = nv30_state_stipple_validate,
+ .dirty = {
+ .pipe = NV30_NEW_STIPPLE | NV30_NEW_RAST,
+ .hw = NV30_STATE_STIPPLE,
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_viewport.c b/src/gallium/drivers/nv30/nv30_state_viewport.c
new file mode 100644
index 0000000000..c3eb413dac
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_viewport.c
@@ -0,0 +1,72 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_viewport_validate(struct nv30_context *nv30)
+{
+ struct pipe_viewport_state *vpt = &nv30->viewport;
+ struct nouveau_stateobj *so;
+ unsigned bypass;
+
+ if (/*nv30->render_mode == HW &&*/
+ !nv30->rasterizer->pipe.bypass_vs_clip_and_viewport)
+ bypass = 0;
+ else
+ bypass = 1;
+
+ if (nv30->state.hw[NV30_STATE_VIEWPORT] &&
+ (bypass || !(nv30->dirty & NV30_NEW_VIEWPORT)) &&
+ nv30->state.viewport_bypass == bypass)
+ return FALSE;
+ nv30->state.viewport_bypass = bypass;
+
+ so = so_new(11, 0);
+ if (!bypass) {
+ so_method(so, nv30->screen->rankine,
+ NV34TCL_VIEWPORT_TRANSLATE_X, 8);
+ so_data (so, fui(vpt->translate[0]));
+ so_data (so, fui(vpt->translate[1]));
+ so_data (so, fui(vpt->translate[2]));
+ so_data (so, fui(vpt->translate[3]));
+ so_data (so, fui(vpt->scale[0]));
+ so_data (so, fui(vpt->scale[1]));
+ so_data (so, fui(vpt->scale[2]));
+ so_data (so, fui(vpt->scale[3]));
+/* so_method(so, nv30->screen->rankine, 0x1d78, 1);
+ so_data (so, 1);
+*/ } else {
+ so_method(so, nv30->screen->rankine,
+ NV34TCL_VIEWPORT_TRANSLATE_X, 8);
+ so_data (so, fui(0.0));
+ so_data (so, fui(0.0));
+ so_data (so, fui(0.0));
+ so_data (so, fui(0.0));
+ so_data (so, fui(1.0));
+ so_data (so, fui(1.0));
+ so_data (so, fui(1.0));
+ so_data (so, fui(0.0));
+ /* Not entirely certain what this is yet. The DDX uses this
+ * value also as it fixes rendering when you pass
+ * pre-transformed vertices to the GPU. My best gusss is that
+ * this bypasses some culling/clipping stage. Might be worth
+ * noting that points/lines are uneffected by whatever this
+ * value fixes, only filled polygons are effected.
+ */
+/* so_method(so, nv30->screen->rankine, 0x1d78, 1);
+ so_data (so, 0x110);
+*/ }
+ /* TODO/FIXME: never saw value 0x0110 in renouveau dumps, only 0x0001 */
+ so_method(so, nv30->screen->rankine, 0x1d78, 1);
+ so_data (so, 1);
+
+ so_ref(so, &nv30->state.hw[NV30_STATE_VIEWPORT]);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv30_state_entry nv30_state_viewport = {
+ .validate = nv30_state_viewport_validate,
+ .dirty = {
+ .pipe = NV30_NEW_VIEWPORT | NV30_NEW_RAST,
+ .hw = NV30_STATE_VIEWPORT
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_zsa.c b/src/gallium/drivers/nv30/nv30_state_zsa.c
new file mode 100644
index 0000000000..0940b7269b
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_zsa.c
@@ -0,0 +1,17 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_zsa_validate(struct nv30_context *nv30)
+{
+ so_ref(nv30->zsa->so,
+ &nv30->state.hw[NV30_STATE_ZSA]);
+ return TRUE;
+}
+
+struct nv30_state_entry nv30_state_zsa = {
+ .validate = nv30_state_zsa_validate,
+ .dirty = {
+ .pipe = NV30_NEW_ZSA,
+ .hw = NV30_STATE_ZSA
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_surface.c b/src/gallium/drivers/nv30/nv30_surface.c
new file mode 100644
index 0000000000..5e237e13eb
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_surface.c
@@ -0,0 +1,63 @@
+
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "nv30_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+
+static void
+nv30_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv04_surface_2d *eng2d = nv30->screen->eng2d;
+
+ eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
+}
+
+static void
+nv30_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+ unsigned destx, unsigned desty, unsigned width,
+ unsigned height, unsigned value)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv04_surface_2d *eng2d = nv30->screen->eng2d;
+
+ eng2d->fill(eng2d, dest, destx, desty, width, height, value);
+}
+
+void
+nv30_init_surface_functions(struct nv30_context *nv30)
+{
+ nv30->pipe.surface_copy = nv30_surface_copy;
+ nv30->pipe.surface_fill = nv30_surface_fill;
+}
diff --git a/src/gallium/drivers/nv30/nv30_transfer.c b/src/gallium/drivers/nv30/nv30_transfer.c
new file mode 100644
index 0000000000..2367571878
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_transfer.c
@@ -0,0 +1,195 @@
+#include <pipe/p_state.h>
+#include <pipe/p_defines.h>
+#include <pipe/p_inlines.h>
+#include <util/u_memory.h>
+#include <nouveau/nouveau_winsys.h>
+#include "nv30_context.h"
+#include "nv30_screen.h"
+#include "nv30_state.h"
+
+struct nv30_transfer {
+ struct pipe_transfer base;
+ struct pipe_surface *surface;
+ bool direct;
+};
+
+static unsigned nv30_usage_tx_to_buf(unsigned tx_usage)
+{
+ switch (tx_usage) {
+ case PIPE_TRANSFER_READ:
+ return PIPE_BUFFER_USAGE_CPU_READ;
+ case PIPE_TRANSFER_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_WRITE;
+ case PIPE_TRANSFER_READ_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static void
+nv30_compatible_transfer_tex(struct pipe_texture *pt, unsigned level,
+ struct pipe_texture *template)
+{
+ memset(template, 0, sizeof(struct pipe_texture));
+ template->target = pt->target;
+ template->format = pt->format;
+ template->width[0] = pt->width[level];
+ template->height[0] = pt->height[level];
+ template->depth[0] = 1;
+ template->block = pt->block;
+ template->nblocksx[0] = pt->nblocksx[level];
+ template->nblocksy[0] = pt->nblocksx[level];
+ template->last_level = 0;
+ template->nr_samples = pt->nr_samples;
+
+ template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC |
+ NOUVEAU_TEXTURE_USAGE_LINEAR;
+}
+
+static struct pipe_transfer *
+nv30_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct nv30_miptree *mt = (struct nv30_miptree *)pt;
+ struct nv30_transfer *tx;
+ struct pipe_texture tx_tex_template, *tx_tex;
+
+ tx = CALLOC_STRUCT(nv30_transfer);
+ if (!tx)
+ return NULL;
+
+ pipe_texture_reference(&tx->base.texture, pt);
+ tx->base.format = pt->format;
+ tx->base.x = x;
+ tx->base.y = y;
+ tx->base.width = w;
+ tx->base.height = h;
+ tx->base.block = pt->block;
+ tx->base.nblocksx = pt->nblocksx[level];
+ tx->base.nblocksy = pt->nblocksy[level];
+ tx->base.stride = mt->level[level].pitch;
+ tx->base.usage = usage;
+ tx->base.face = face;
+ tx->base.level = level;
+ tx->base.zslice = zslice;
+
+ /* Direct access to texture */
+ if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC ||
+ debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) &&
+ pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)
+ {
+ tx->direct = true;
+ tx->surface = pscreen->get_tex_surface(pscreen, pt,
+ face, level, zslice,
+ nv30_usage_tx_to_buf(usage));
+ return &tx->base;
+ }
+
+ tx->direct = false;
+
+ nv30_compatible_transfer_tex(pt, level, &tx_tex_template);
+
+ tx_tex = pscreen->texture_create(pscreen, &tx_tex_template);
+ if (!tx_tex)
+ {
+ FREE(tx);
+ return NULL;
+ }
+
+ tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
+ 0, 0, 0,
+ nv30_usage_tx_to_buf(usage));
+
+ pipe_texture_reference(&tx_tex, NULL);
+
+ if (!tx->surface)
+ {
+ pipe_surface_reference(&tx->surface, NULL);
+ FREE(tx);
+ return NULL;
+ }
+
+ if (usage != PIPE_TRANSFER_WRITE) {
+ struct nv30_screen *nvscreen = nv30_screen(pscreen);
+ struct pipe_surface *src;
+
+ src = pscreen->get_tex_surface(pscreen, pt,
+ face, level, zslice,
+ PIPE_BUFFER_USAGE_GPU_READ);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ /* TODO: Check if SIFM can un-swizzle */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ tx->surface, 0, 0,
+ src, 0, 0,
+ src->width, src->height);
+
+ pipe_surface_reference(&src, NULL);
+ }
+
+ return &tx->base;
+}
+
+static void
+nv30_transfer_del(struct pipe_transfer *ptx)
+{
+ struct nv30_transfer *tx = (struct nv30_transfer *)ptx;
+
+ if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) {
+ struct pipe_screen *pscreen = ptx->texture->screen;
+ struct nv30_screen *nvscreen = nv30_screen(pscreen);
+ struct pipe_surface *dst;
+
+ dst = pscreen->get_tex_surface(pscreen, ptx->texture,
+ ptx->face, ptx->level, ptx->zslice,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ dst, 0, 0,
+ tx->surface, 0, 0,
+ dst->width, dst->height);
+
+ pipe_surface_reference(&dst, NULL);
+ }
+
+ pipe_surface_reference(&tx->surface, NULL);
+ pipe_texture_reference(&ptx->texture, NULL);
+ FREE(ptx);
+}
+
+static void *
+nv30_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv30_transfer *tx = (struct nv30_transfer *)ptx;
+ struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
+ struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture;
+ void *map = pipe_buffer_map(pscreen, mt->buffer,
+ nv30_usage_tx_to_buf(ptx->usage));
+
+ return map + ns->base.offset +
+ ptx->y * ns->pitch + ptx->x * ptx->block.size;
+}
+
+static void
+nv30_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv30_transfer *tx = (struct nv30_transfer *)ptx;
+ struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture;
+
+ pipe_buffer_unmap(pscreen, mt->buffer);
+}
+
+void
+nv30_screen_init_transfer_functions(struct pipe_screen *pscreen)
+{
+ pscreen->get_tex_transfer = nv30_transfer_new;
+ pscreen->tex_transfer_destroy = nv30_transfer_del;
+ pscreen->transfer_map = nv30_transfer_map;
+ pscreen->transfer_unmap = nv30_transfer_unmap;
+}
diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nv30/nv30_vbo.c
new file mode 100644
index 0000000000..189656ec81
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_vbo.c
@@ -0,0 +1,561 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "nv30_context.h"
+#include "nv30_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+#include "nouveau/nouveau_util.h"
+
+#define FORCE_SWTNL 0
+
+static INLINE int
+nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp)
+{
+ switch (pipe) {
+ case PIPE_FORMAT_R32_FLOAT:
+ case PIPE_FORMAT_R32G32_FLOAT:
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ *fmt = NV34TCL_VTXFMT_TYPE_FLOAT;
+ break;
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R8G8_UNORM:
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ *fmt = NV34TCL_VTXFMT_TYPE_UBYTE;
+ break;
+ case PIPE_FORMAT_R16_SSCALED:
+ case PIPE_FORMAT_R16G16_SSCALED:
+ case PIPE_FORMAT_R16G16B16_SSCALED:
+ case PIPE_FORMAT_R16G16B16A16_SSCALED:
+ *fmt = NV34TCL_VTXFMT_TYPE_USHORT;
+ break;
+ default:
+ NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
+ return 1;
+ }
+
+ switch (pipe) {
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R32_FLOAT:
+ case PIPE_FORMAT_R16_SSCALED:
+ *ncomp = 1;
+ break;
+ case PIPE_FORMAT_R8G8_UNORM:
+ case PIPE_FORMAT_R32G32_FLOAT:
+ case PIPE_FORMAT_R16G16_SSCALED:
+ *ncomp = 2;
+ break;
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ case PIPE_FORMAT_R16G16B16_SSCALED:
+ *ncomp = 3;
+ break;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ case PIPE_FORMAT_R16G16B16A16_SSCALED:
+ *ncomp = 4;
+ break;
+ default:
+ NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
+ return 1;
+ }
+
+ return 0;
+}
+
+static boolean
+nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib,
+ unsigned ib_size)
+{
+ struct pipe_screen *pscreen = &nv30->screen->base.base;
+ unsigned type;
+
+ if (!ib) {
+ nv30->idxbuf = NULL;
+ nv30->idxbuf_format = 0xdeadbeef;
+ return FALSE;
+ }
+
+ if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1)
+ return FALSE;
+
+ switch (ib_size) {
+ case 2:
+ type = NV34TCL_IDXBUF_FORMAT_TYPE_U16;
+ break;
+ case 4:
+ type = NV34TCL_IDXBUF_FORMAT_TYPE_U32;
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (ib != nv30->idxbuf ||
+ type != nv30->idxbuf_format) {
+ nv30->dirty |= NV30_NEW_ARRAYS;
+ nv30->idxbuf = ib;
+ nv30->idxbuf_format = type;
+ }
+
+ return TRUE;
+}
+
+static boolean
+nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so,
+ int attrib, struct pipe_vertex_element *ve,
+ struct pipe_vertex_buffer *vb)
+{
+ struct pipe_screen *pscreen = nv30->pipe.screen;
+ struct nouveau_grobj *rankine = nv30->screen->rankine;
+ unsigned type, ncomp;
+ void *map;
+
+ if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp))
+ return FALSE;
+
+ map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+ map += vb->buffer_offset + ve->src_offset;
+
+ switch (type) {
+ case NV34TCL_VTXFMT_TYPE_FLOAT:
+ {
+ float *v = map;
+
+ switch (ncomp) {
+ case 4:
+ so_method(so, rankine, NV34TCL_VTX_ATTR_4F_X(attrib), 4);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ so_data (so, fui(v[2]));
+ so_data (so, fui(v[3]));
+ break;
+ case 3:
+ so_method(so, rankine, NV34TCL_VTX_ATTR_3F_X(attrib), 3);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ so_data (so, fui(v[2]));
+ break;
+ case 2:
+ so_method(so, rankine, NV34TCL_VTX_ATTR_2F_X(attrib), 2);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ break;
+ case 1:
+ so_method(so, rankine, NV34TCL_VTX_ATTR_1F(attrib), 1);
+ so_data (so, fui(v[0]));
+ break;
+ default:
+ pipe_buffer_unmap(pscreen, vb->buffer);
+ return FALSE;
+ }
+ }
+ break;
+ default:
+ pipe_buffer_unmap(pscreen, vb->buffer);
+ return FALSE;
+ }
+
+ pipe_buffer_unmap(pscreen, vb->buffer);
+ return TRUE;
+}
+
+boolean
+nv30_draw_arrays(struct pipe_context *pipe,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nouveau_channel *chan = nv30->screen->base.channel;
+ unsigned restart = 0;
+
+ nv30_vbo_set_idxbuf(nv30, NULL, 0);
+ if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
+ /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
+ mode, start, count);*/
+ return FALSE;
+ }
+
+ while (count) {
+ unsigned vc, nr;
+
+ nv30_state_emit(nv30);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
+ mode, start, count, &restart);
+ if (!vc) {
+ FIRE_RING(NULL);
+ continue;
+ }
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ nr = (vc & 0xff);
+ if (nr) {
+ BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1);
+ OUT_RING (((nr - 1) << 24) | start);
+ start += nr;
+ }
+
+ nr = vc >> 8;
+ while (nr) {
+ unsigned push = nr > 2047 ? 2047 : nr;
+
+ nr -= push;
+
+ BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push);
+ while (push--) {
+ OUT_RING(((0x100 - 1) << 24) | start);
+ start += 0x100;
+ }
+ }
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (0);
+
+ count -= vc;
+ start = restart;
+ }
+
+ pipe->flush(pipe, 0, NULL);
+ return TRUE;
+}
+
+static INLINE void
+nv30_draw_elements_u08(struct nv30_context *nv30, void *ib,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nouveau_channel *chan = nv30->screen->base.channel;
+
+ while (count) {
+ uint8_t *elts = (uint8_t *)ib + start;
+ unsigned vc, push, restart = 0;
+
+ nv30_state_emit(nv30);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
+ mode, start, count, &restart);
+ if (vc == 0) {
+ FIRE_RING(NULL);
+ continue;
+ }
+ count -= vc;
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ if (vc & 1) {
+ BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
+ OUT_RING (elts[0]);
+ elts++; vc--;
+ }
+
+ while (vc) {
+ unsigned i;
+
+ push = MIN2(vc, 2047 * 2);
+
+ BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
+ for (i = 0; i < push; i+=2)
+ OUT_RING((elts[i+1] << 16) | elts[i]);
+
+ vc -= push;
+ elts += push;
+ }
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (0);
+
+ start = restart;
+ }
+}
+
+static INLINE void
+nv30_draw_elements_u16(struct nv30_context *nv30, void *ib,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nouveau_channel *chan = nv30->screen->base.channel;
+
+ while (count) {
+ uint16_t *elts = (uint16_t *)ib + start;
+ unsigned vc, push, restart = 0;
+
+ nv30_state_emit(nv30);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
+ mode, start, count, &restart);
+ if (vc == 0) {
+ FIRE_RING(NULL);
+ continue;
+ }
+ count -= vc;
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ if (vc & 1) {
+ BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
+ OUT_RING (elts[0]);
+ elts++; vc--;
+ }
+
+ while (vc) {
+ unsigned i;
+
+ push = MIN2(vc, 2047 * 2);
+
+ BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
+ for (i = 0; i < push; i+=2)
+ OUT_RING((elts[i+1] << 16) | elts[i]);
+
+ vc -= push;
+ elts += push;
+ }
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (0);
+
+ start = restart;
+ }
+}
+
+static INLINE void
+nv30_draw_elements_u32(struct nv30_context *nv30, void *ib,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nouveau_channel *chan = nv30->screen->base.channel;
+
+ while (count) {
+ uint32_t *elts = (uint32_t *)ib + start;
+ unsigned vc, push, restart = 0;
+
+ nv30_state_emit(nv30);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1,
+ mode, start, count, &restart);
+ if (vc == 0) {
+ FIRE_RING(NULL);
+ continue;
+ }
+ count -= vc;
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ while (vc) {
+ push = MIN2(vc, 2047);
+
+ BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U32, push);
+ OUT_RINGp (elts, push);
+
+ vc -= push;
+ elts += push;
+ }
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (0);
+
+ start = restart;
+ }
+}
+
+static boolean
+nv30_draw_elements_inline(struct pipe_context *pipe,
+ struct pipe_buffer *ib, unsigned ib_size,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct pipe_screen *pscreen = pipe->screen;
+ void *map;
+
+ map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ);
+ if (!ib) {
+ NOUVEAU_ERR("failed mapping ib\n");
+ return FALSE;
+ }
+
+ switch (ib_size) {
+ case 1:
+ nv30_draw_elements_u08(nv30, map, mode, start, count);
+ break;
+ case 2:
+ nv30_draw_elements_u16(nv30, map, mode, start, count);
+ break;
+ case 4:
+ nv30_draw_elements_u32(nv30, map, mode, start, count);
+ break;
+ default:
+ NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
+ break;
+ }
+
+ pipe_buffer_unmap(pscreen, ib);
+ return TRUE;
+}
+
+static boolean
+nv30_draw_elements_vbo(struct pipe_context *pipe,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nouveau_channel *chan = nv30->screen->base.channel;
+ unsigned restart = 0;
+
+ while (count) {
+ unsigned nr, vc;
+
+ nv30_state_emit(nv30);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
+ mode, start, count, &restart);
+ if (!vc) {
+ FIRE_RING(NULL);
+ continue;
+ }
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ nr = (vc & 0xff);
+ if (nr) {
+ BEGIN_RING(rankine, NV34TCL_VB_INDEX_BATCH, 1);
+ OUT_RING (((nr - 1) << 24) | start);
+ start += nr;
+ }
+
+ nr = vc >> 8;
+ while (nr) {
+ unsigned push = nr > 2047 ? 2047 : nr;
+
+ nr -= push;
+
+ BEGIN_RING_NI(rankine, NV34TCL_VB_INDEX_BATCH, push);
+ while (push--) {
+ OUT_RING(((0x100 - 1) << 24) | start);
+ start += 0x100;
+ }
+ }
+
+ BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+ OUT_RING (0);
+
+ count -= vc;
+ start = restart;
+ }
+
+ return TRUE;
+}
+
+boolean
+nv30_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer, unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ boolean idxbuf;
+
+ idxbuf = nv30_vbo_set_idxbuf(nv30, indexBuffer, indexSize);
+ if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
+ /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
+ mode, start, count);*/
+ return FALSE;
+ }
+
+ if (idxbuf) {
+ nv30_draw_elements_vbo(pipe, mode, start, count);
+ } else {
+ nv30_draw_elements_inline(pipe, indexBuffer, indexSize,
+ mode, start, count);
+ }
+
+ pipe->flush(pipe, 0, NULL);
+ return TRUE;
+}
+
+static boolean
+nv30_vbo_validate(struct nv30_context *nv30)
+{
+ struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL;
+ struct nouveau_grobj *rankine = nv30->screen->rankine;
+ struct pipe_buffer *ib = nv30->idxbuf;
+ unsigned ib_format = nv30->idxbuf_format;
+ unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+ int hw;
+
+ if (nv30->edgeflags) {
+ /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
+ return FALSE;
+ }
+
+ vtxbuf = so_new(20, 18);
+ so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr);
+ vtxfmt = so_new(17, 0);
+ so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt_nr);
+
+ for (hw = 0; hw < nv30->vtxelt_nr; hw++) {
+ struct pipe_vertex_element *ve;
+ struct pipe_vertex_buffer *vb;
+ unsigned type, ncomp;
+
+ ve = &nv30->vtxelt[hw];
+ vb = &nv30->vtxbuf[ve->vertex_buffer_index];
+
+ if (!vb->stride) {
+ if (!sattr)
+ sattr = so_new(16 * 5, 0);
+
+ if (nv30_vbo_static_attrib(nv30, sattr, hw, ve, vb)) {
+ so_data(vtxbuf, 0);
+ so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT);
+ continue;
+ }
+ }
+
+ if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) {
+ /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
+ so_ref(NULL, &vtxbuf);
+ so_ref(NULL, &vtxfmt);
+ return FALSE;
+ }
+
+ so_reloc(vtxbuf, nouveau_bo(vb->buffer), vb->buffer_offset +
+ ve->src_offset, vb_flags | NOUVEAU_BO_LOW |
+ NOUVEAU_BO_OR, 0, NV34TCL_VTXBUF_ADDRESS_DMA1);
+ so_data (vtxfmt, ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) |
+ (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type));
+ }
+
+ if (ib) {
+ struct nouveau_bo *bo = nouveau_bo(ib);
+
+ so_method(vtxbuf, rankine, NV34TCL_IDXBUF_ADDRESS, 2);
+ so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
+ so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR,
+ 0, NV34TCL_IDXBUF_FORMAT_DMA1);
+ }
+
+ so_method(vtxbuf, rankine, 0x1710, 1);
+ so_data (vtxbuf, 0);
+
+ so_ref(vtxbuf, &nv30->state.hw[NV30_STATE_VTXBUF]);
+ so_ref(NULL, &vtxbuf);
+ nv30->state.dirty |= (1ULL << NV30_STATE_VTXBUF);
+ so_ref(vtxfmt, &nv30->state.hw[NV30_STATE_VTXFMT]);
+ so_ref(NULL, &vtxfmt);
+ nv30->state.dirty |= (1ULL << NV30_STATE_VTXFMT);
+ so_ref(sattr, &nv30->state.hw[NV30_STATE_VTXATTR]);
+ so_ref(NULL, &sattr);
+ nv30->state.dirty |= (1ULL << NV30_STATE_VTXATTR);
+ return FALSE;
+}
+
+struct nv30_state_entry nv30_state_vbo = {
+ .validate = nv30_vbo_validate,
+ .dirty = {
+ .pipe = NV30_NEW_ARRAYS,
+ .hw = 0,
+ }
+};
diff --git a/src/gallium/drivers/nv30/nv30_vertprog.c b/src/gallium/drivers/nv30/nv30_vertprog.c
new file mode 100644
index 0000000000..14a5c0260d
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_vertprog.c
@@ -0,0 +1,837 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "nv30_context.h"
+#include "nv30_state.h"
+
+/* TODO (at least...):
+ * 1. Indexed consts + ARL
+ * 2. Arb. swz/negation
+ * 3. NV_vp11, NV_vp2, NV_vp3 features
+ * - extra arith opcodes
+ * - branching
+ * - texture sampling
+ * - indexed attribs
+ * - indexed results
+ * 4. bugs
+ */
+
+#define SWZ_X 0
+#define SWZ_Y 1
+#define SWZ_Z 2
+#define SWZ_W 3
+#define MASK_X 8
+#define MASK_Y 4
+#define MASK_Z 2
+#define MASK_W 1
+#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
+#define DEF_SCALE 0
+#define DEF_CTEST 0
+#include "nv30_shader.h"
+
+#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv30_sr_neg((s))
+#define abs(s) nv30_sr_abs((s))
+
+struct nv30_vpc {
+ struct nv30_vertex_program *vp;
+
+ struct nv30_vertex_program_exec *vpi;
+
+ unsigned output_map[PIPE_MAX_SHADER_OUTPUTS];
+
+ int high_temp;
+ int temp_temp_count;
+
+ struct nv30_sreg *imm;
+ unsigned nr_imm;
+};
+
+static struct nv30_sreg
+temp(struct nv30_vpc *vpc)
+{
+ int idx;
+
+ idx = vpc->temp_temp_count++;
+ idx += vpc->high_temp + 1;
+ return nv30_sr(NV30SR_TEMP, idx);
+}
+
+static struct nv30_sreg
+constant(struct nv30_vpc *vpc, int pipe, float x, float y, float z, float w)
+{
+ struct nv30_vertex_program *vp = vpc->vp;
+ struct nv30_vertex_program_data *vpd;
+ int idx;
+
+ if (pipe >= 0) {
+ for (idx = 0; idx < vp->nr_consts; idx++) {
+ if (vp->consts[idx].index == pipe)
+ return nv30_sr(NV30SR_CONST, idx);
+ }
+ }
+
+ idx = vp->nr_consts++;
+ vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts);
+ vpd = &vp->consts[idx];
+
+ vpd->index = pipe;
+ vpd->value[0] = x;
+ vpd->value[1] = y;
+ vpd->value[2] = z;
+ vpd->value[3] = w;
+ return nv30_sr(NV30SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+ nv30_vp_arith((cc), (s), NV30_VP_INST_##o, (d), (m), (s0), (s1), (s2))
+
+static void
+emit_src(struct nv30_vpc *vpc, uint32_t *hw, int pos, struct nv30_sreg src)
+{
+ struct nv30_vertex_program *vp = vpc->vp;
+ uint32_t sr = 0;
+
+ switch (src.type) {
+ case NV30SR_TEMP:
+ sr |= (NV30_VP_SRC_REG_TYPE_TEMP << NV30_VP_SRC_REG_TYPE_SHIFT);
+ sr |= (src.index << NV30_VP_SRC_TEMP_SRC_SHIFT);
+ break;
+ case NV30SR_INPUT:
+ sr |= (NV30_VP_SRC_REG_TYPE_INPUT <<
+ NV30_VP_SRC_REG_TYPE_SHIFT);
+ vp->ir |= (1 << src.index);
+ hw[1] |= (src.index << NV30_VP_INST_INPUT_SRC_SHIFT);
+ break;
+ case NV30SR_CONST:
+ sr |= (NV30_VP_SRC_REG_TYPE_CONST <<
+ NV30_VP_SRC_REG_TYPE_SHIFT);
+ assert(vpc->vpi->const_index == -1 ||
+ vpc->vpi->const_index == src.index);
+ vpc->vpi->const_index = src.index;
+ break;
+ case NV30SR_NONE:
+ sr |= (NV30_VP_SRC_REG_TYPE_INPUT <<
+ NV30_VP_SRC_REG_TYPE_SHIFT);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (src.negate)
+ sr |= NV30_VP_SRC_NEGATE;
+
+ if (src.abs)
+ hw[0] |= (1 << (21 + pos));
+
+ sr |= ((src.swz[0] << NV30_VP_SRC_SWZ_X_SHIFT) |
+ (src.swz[1] << NV30_VP_SRC_SWZ_Y_SHIFT) |
+ (src.swz[2] << NV30_VP_SRC_SWZ_Z_SHIFT) |
+ (src.swz[3] << NV30_VP_SRC_SWZ_W_SHIFT));
+
+/*
+ * |VVV|
+ * d�.�b
+ * \u/
+ *
+ */
+
+ switch (pos) {
+ case 0:
+ hw[1] |= ((sr & NV30_VP_SRC0_HIGH_MASK) >>
+ NV30_VP_SRC0_HIGH_SHIFT) << NV30_VP_INST_SRC0H_SHIFT;
+ hw[2] |= (sr & NV30_VP_SRC0_LOW_MASK) <<
+ NV30_VP_INST_SRC0L_SHIFT;
+ break;
+ case 1:
+ hw[2] |= sr << NV30_VP_INST_SRC1_SHIFT;
+ break;
+ case 2:
+ hw[2] |= ((sr & NV30_VP_SRC2_HIGH_MASK) >>
+ NV30_VP_SRC2_HIGH_SHIFT) << NV30_VP_INST_SRC2H_SHIFT;
+ hw[3] |= (sr & NV30_VP_SRC2_LOW_MASK) <<
+ NV30_VP_INST_SRC2L_SHIFT;
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+emit_dst(struct nv30_vpc *vpc, uint32_t *hw, int slot, struct nv30_sreg dst)
+{
+ struct nv30_vertex_program *vp = vpc->vp;
+
+ switch (dst.type) {
+ case NV30SR_TEMP:
+ hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT);
+ break;
+ case NV30SR_OUTPUT:
+ switch (dst.index) {
+ case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break;
+ case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break;
+ case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break;
+ case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break;
+ case NV30_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break;
+ case NV30_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break;
+ case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break;
+ case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break;
+ case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break;
+ case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break;
+ case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break;
+ case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break;
+ case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break;
+ case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break;
+ default:
+ break;
+ }
+
+ hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT);
+ hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20);
+
+ /*XXX: no way this is entirely correct, someone needs to
+ * figure out what exactly it is.
+ */
+ hw[3] |= 0x800;
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+nv30_vp_arith(struct nv30_vpc *vpc, int slot, int op,
+ struct nv30_sreg dst, int mask,
+ struct nv30_sreg s0, struct nv30_sreg s1,
+ struct nv30_sreg s2)
+{
+ struct nv30_vertex_program *vp = vpc->vp;
+ uint32_t *hw;
+
+ vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi));
+ vpc->vpi = &vp->insns[vp->nr_insns - 1];
+ memset(vpc->vpi, 0, sizeof(*vpc->vpi));
+ vpc->vpi->const_index = -1;
+
+ hw = vpc->vpi->data;
+
+ hw[0] |= (NV30_VP_INST_COND_TR << NV30_VP_INST_COND_SHIFT);
+ hw[0] |= ((0 << NV30_VP_INST_COND_SWZ_X_SHIFT) |
+ (1 << NV30_VP_INST_COND_SWZ_Y_SHIFT) |
+ (2 << NV30_VP_INST_COND_SWZ_Z_SHIFT) |
+ (3 << NV30_VP_INST_COND_SWZ_W_SHIFT));
+
+ hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT);
+// hw[3] |= NV30_VP_INST_SCA_DEST_TEMP_MASK;
+// hw[3] |= (mask << NV30_VP_INST_VEC_WRITEMASK_SHIFT);
+
+ if (dst.type == NV30SR_OUTPUT) {
+ if (slot)
+ hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT);
+ else
+ hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT);
+ } else {
+ if (slot)
+ hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT);
+ else
+ hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT);
+ }
+
+ emit_dst(vpc, hw, slot, dst);
+ emit_src(vpc, hw, 0, s0);
+ emit_src(vpc, hw, 1, s1);
+ emit_src(vpc, hw, 2, s2);
+}
+
+static INLINE struct nv30_sreg
+tgsi_src(struct nv30_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
+ struct nv30_sreg src;
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ src = nv30_sr(NV30SR_INPUT, fsrc->SrcRegister.Index);
+ break;
+ case TGSI_FILE_CONSTANT:
+ src = constant(vpc, fsrc->SrcRegister.Index, 0, 0, 0, 0);
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ src = vpc->imm[fsrc->SrcRegister.Index];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ if (vpc->high_temp < fsrc->SrcRegister.Index)
+ vpc->high_temp = fsrc->SrcRegister.Index;
+ src = nv30_sr(NV30SR_TEMP, fsrc->SrcRegister.Index);
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ break;
+ }
+
+ src.abs = fsrc->SrcRegisterExtMod.Absolute;
+ src.negate = fsrc->SrcRegister.Negate;
+ src.swz[0] = fsrc->SrcRegister.SwizzleX;
+ src.swz[1] = fsrc->SrcRegister.SwizzleY;
+ src.swz[2] = fsrc->SrcRegister.SwizzleZ;
+ src.swz[3] = fsrc->SrcRegister.SwizzleW;
+ return src;
+}
+
+static INLINE struct nv30_sreg
+tgsi_dst(struct nv30_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
+ struct nv30_sreg dst;
+
+ switch (fdst->DstRegister.File) {
+ case TGSI_FILE_OUTPUT:
+ dst = nv30_sr(NV30SR_OUTPUT,
+ vpc->output_map[fdst->DstRegister.Index]);
+
+ break;
+ case TGSI_FILE_TEMPORARY:
+ dst = nv30_sr(NV30SR_TEMP, fdst->DstRegister.Index);
+ if (vpc->high_temp < dst.index)
+ vpc->high_temp = dst.index;
+ break;
+ default:
+ NOUVEAU_ERR("bad dst file\n");
+ break;
+ }
+
+ return dst;
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+ int mask = 0;
+
+ if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
+ if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
+ if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
+ if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
+ return mask;
+}
+
+static boolean
+nv30_vertprog_parse_instruction(struct nv30_vpc *vpc,
+ const struct tgsi_full_instruction *finst)
+{
+ struct nv30_sreg src[3], dst, tmp;
+ struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0);
+ int mask;
+ int ai = -1, ci = -1;
+ int i;
+
+ if (finst->Instruction.Opcode == TGSI_OPCODE_END)
+ return TRUE;
+
+ vpc->temp_temp_count = 0;
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+ if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) {
+ src[i] = tgsi_src(vpc, fsrc);
+ }
+ }
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ if (ai == -1 || ai == fsrc->SrcRegister.Index) {
+ ai = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = temp(vpc);
+ arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none);
+ }
+ break;
+ /*XXX: index comparison is broken now that consts come from
+ * two different register files.
+ */
+ case TGSI_FILE_CONSTANT:
+ case TGSI_FILE_IMMEDIATE:
+ if (ci == -1 || ci == fsrc->SrcRegister.Index) {
+ ci = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = temp(vpc);
+ arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_TEMPORARY:
+ /* handled above */
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ return FALSE;
+ }
+ }
+
+ dst = tgsi_dst(vpc, &finst->FullDstRegisters[0]);
+ mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+
+ switch (finst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none);
+ break;
+ case TGSI_OPCODE_ADD:
+ arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]);
+ break;
+ case TGSI_OPCODE_ARL:
+ arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_DP3:
+ arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DP4:
+ arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DPH:
+ arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DST:
+ arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_EX2:
+ arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_EXP:
+ arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_FLR:
+ arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_FRC:
+ arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_LG2:
+ arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_LIT:
+ arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_LOG:
+ arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_MAD:
+ arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]);
+ break;
+ case TGSI_OPCODE_MAX:
+ arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MIN:
+ arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MOV:
+ arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_MUL:
+ arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_POW:
+ tmp = temp(vpc);
+ arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none,
+ swz(src[0], X, X, X, X));
+ arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X),
+ swz(src[1], X, X, X, X), none);
+ arith(vpc, 1, OP_EX2, dst, mask, none, none,
+ swz(tmp, X, X, X, X));
+ break;
+ case TGSI_OPCODE_RCP:
+ arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_RET:
+ break;
+ case TGSI_OPCODE_RSQ:
+ arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_SGE:
+ arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SGT:
+ arith(vpc, 0, OP_SGT, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SLT:
+ arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SUB:
+ arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1]));
+ break;
+ case TGSI_OPCODE_XPD:
+ tmp = temp(vpc);
+ arith(vpc, 0, OP_MUL, tmp, mask,
+ swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
+ arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W),
+ swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
+ neg(tmp));
+ break;
+ default:
+ NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static boolean
+nv30_vertprog_parse_decl_output(struct nv30_vpc *vpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ int hw;
+
+ switch (fdec->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ hw = NV30_VP_INST_DEST_POS;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ if (fdec->Semantic.SemanticIndex == 0) {
+ hw = NV30_VP_INST_DEST_COL0;
+ } else
+ if (fdec->Semantic.SemanticIndex == 1) {
+ hw = NV30_VP_INST_DEST_COL1;
+ } else {
+ NOUVEAU_ERR("bad colour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_BCOLOR:
+ if (fdec->Semantic.SemanticIndex == 0) {
+ hw = NV30_VP_INST_DEST_BFC0;
+ } else
+ if (fdec->Semantic.SemanticIndex == 1) {
+ hw = NV30_VP_INST_DEST_BFC1;
+ } else {
+ NOUVEAU_ERR("bad bcolour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_FOG:
+ hw = NV30_VP_INST_DEST_FOGC;
+ break;
+ case TGSI_SEMANTIC_PSIZE:
+ hw = NV30_VP_INST_DEST_PSZ;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ if (fdec->Semantic.SemanticIndex <= 7) {
+ hw = NV30_VP_INST_DEST_TC(fdec->Semantic.SemanticIndex);
+ } else {
+ NOUVEAU_ERR("bad generic semantic index\n");
+ return FALSE;
+ }
+ break;
+ default:
+ NOUVEAU_ERR("bad output semantic\n");
+ return FALSE;
+ }
+
+ vpc->output_map[fdec->DeclarationRange.First] = hw;
+ return TRUE;
+}
+
+static boolean
+nv30_vertprog_prepare(struct nv30_vpc *vpc)
+{
+ struct tgsi_parse_context p;
+ int nr_imm = 0;
+
+ tgsi_parse_init(&p, vpc->vp->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&p)) {
+ const union tgsi_full_token *tok = &p.FullToken;
+
+ tgsi_parse_token(&p);
+ switch(tok->Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ nr_imm++;
+ break;
+ default:
+ break;
+ }
+ }
+ tgsi_parse_free(&p);
+
+ if (nr_imm) {
+ vpc->imm = CALLOC(nr_imm, sizeof(struct nv30_sreg));
+ assert(vpc->imm);
+ }
+
+ return TRUE;
+}
+
+static void
+nv30_vertprog_translate(struct nv30_context *nv30,
+ struct nv30_vertex_program *vp)
+{
+ struct tgsi_parse_context parse;
+ struct nv30_vpc *vpc = NULL;
+
+ tgsi_dump(vp->pipe.tokens,0);
+
+ vpc = CALLOC(1, sizeof(struct nv30_vpc));
+ if (!vpc)
+ return;
+ vpc->vp = vp;
+ vpc->high_temp = -1;
+
+ if (!nv30_vertprog_prepare(vpc)) {
+ FREE(vpc);
+ return;
+ }
+
+ tgsi_parse_init(&parse, vp->pipe.tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *fdec;
+ fdec = &parse.FullToken.FullDeclaration;
+ switch (fdec->Declaration.File) {
+ case TGSI_FILE_OUTPUT:
+ if (!nv30_vertprog_parse_decl_output(vpc, fdec))
+ goto out_err;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ const struct tgsi_full_immediate *imm;
+
+ imm = &parse.FullToken.FullImmediate;
+ assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
+ assert(imm->Immediate.NrTokens == 4 + 1);
+ vpc->imm[vpc->nr_imm++] =
+ constant(vpc, -1,
+ imm->u[0].Float,
+ imm->u[1].Float,
+ imm->u[2].Float,
+ imm->u[3].Float);
+ }
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ const struct tgsi_full_instruction *finst;
+ finst = &parse.FullToken.FullInstruction;
+ if (!nv30_vertprog_parse_instruction(vpc, finst))
+ goto out_err;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ vp->insns[vp->nr_insns - 1].data[3] |= NV30_VP_INST_LAST;
+ vp->translated = TRUE;
+out_err:
+ tgsi_parse_free(&parse);
+ FREE(vpc);
+}
+
+static boolean
+nv30_vertprog_validate(struct nv30_context *nv30)
+{
+ struct pipe_screen *pscreen = nv30->pipe.screen;
+ struct nouveau_grobj *rankine = nv30->screen->rankine;
+ struct nv30_vertex_program *vp;
+ struct pipe_buffer *constbuf;
+ boolean upload_code = FALSE, upload_data = FALSE;
+ int i;
+
+ vp = nv30->vertprog;
+ constbuf = nv30->constbuf[PIPE_SHADER_VERTEX];
+
+ /* Translate TGSI shader into hw bytecode */
+ if (!vp->translated) {
+ nv30_vertprog_translate(nv30, vp);
+ if (!vp->translated)
+ return FALSE;
+ }
+
+ /* Allocate hw vtxprog exec slots */
+ if (!vp->exec) {
+ struct nouveau_resource *heap = nv30->screen->vp_exec_heap;
+ struct nouveau_stateobj *so;
+ uint vplen = vp->nr_insns;
+
+ if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) {
+ while (heap->next && heap->size < vplen) {
+ struct nv30_vertex_program *evict;
+
+ evict = heap->next->priv;
+ nouveau_resource_free(&evict->exec);
+ }
+
+ if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec))
+ assert(0);
+ }
+
+ so = so_new(2, 0);
+ so_method(so, rankine, NV34TCL_VP_START_FROM_ID, 1);
+ so_data (so, vp->exec->start);
+ so_ref(so, &vp->so);
+ so_ref(NULL, &so);
+
+ upload_code = TRUE;
+ }
+
+ /* Allocate hw vtxprog const slots */
+ if (vp->nr_consts && !vp->data) {
+ struct nouveau_resource *heap = nv30->screen->vp_data_heap;
+
+ if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) {
+ while (heap->next && heap->size < vp->nr_consts) {
+ struct nv30_vertex_program *evict;
+
+ evict = heap->next->priv;
+ nouveau_resource_free(&evict->data);
+ }
+
+ if (nouveau_resource_alloc(heap, vp->nr_consts, vp,
+ &vp->data))
+ assert(0);
+ }
+
+ /*XXX: handle this some day */
+ assert(vp->data->start >= vp->data_start_min);
+
+ upload_data = TRUE;
+ if (vp->data_start != vp->data->start)
+ upload_code = TRUE;
+ }
+
+ /* If exec or data segments moved we need to patch the program to
+ * fixup offsets and register IDs.
+ */
+ if (vp->exec_start != vp->exec->start) {
+ for (i = 0; i < vp->nr_insns; i++) {
+ struct nv30_vertex_program_exec *vpi = &vp->insns[i];
+
+ if (vpi->has_branch_offset) {
+ assert(0);
+ }
+ }
+
+ vp->exec_start = vp->exec->start;
+ }
+
+ if (vp->nr_consts && vp->data_start != vp->data->start) {
+ for (i = 0; i < vp->nr_insns; i++) {
+ struct nv30_vertex_program_exec *vpi = &vp->insns[i];
+
+ if (vpi->const_index >= 0) {
+ vpi->data[1] &= ~NV30_VP_INST_CONST_SRC_MASK;
+ vpi->data[1] |=
+ (vpi->const_index + vp->data->start) <<
+ NV30_VP_INST_CONST_SRC_SHIFT;
+
+ }
+ }
+
+ vp->data_start = vp->data->start;
+ }
+
+ /* Update + Upload constant values */
+ if (vp->nr_consts) {
+ float *map = NULL;
+
+ if (constbuf) {
+ map = pipe_buffer_map(pscreen, constbuf,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ }
+
+ for (i = 0; i < vp->nr_consts; i++) {
+ struct nv30_vertex_program_data *vpd = &vp->consts[i];
+
+ if (vpd->index >= 0) {
+ if (!upload_data &&
+ !memcmp(vpd->value, &map[vpd->index * 4],
+ 4 * sizeof(float)))
+ continue;
+ memcpy(vpd->value, &map[vpd->index * 4],
+ 4 * sizeof(float));
+ }
+
+ BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5);
+ OUT_RING (i + vp->data->start);
+ OUT_RINGp ((uint32_t *)vpd->value, 4);
+ }
+
+ if (constbuf)
+ pipe_buffer_unmap(pscreen, constbuf);
+ }
+
+ /* Upload vtxprog */
+ if (upload_code) {
+#if 0
+ for (i = 0; i < vp->nr_insns; i++) {
+ NOUVEAU_MSG("VP inst %d: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ i, vp->insns[i].data[0], vp->insns[i].data[1],
+ vp->insns[i].data[2], vp->insns[i].data[3]);
+ }
+#endif
+ BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1);
+ OUT_RING (vp->exec->start);
+ for (i = 0; i < vp->nr_insns; i++) {
+ BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_INST(0), 4);
+ OUT_RINGp (vp->insns[i].data, 4);
+ }
+ }
+
+ if (vp->so != nv30->state.hw[NV30_STATE_VERTPROG]) {
+ so_ref(vp->so, &nv30->state.hw[NV30_STATE_VERTPROG]);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+nv30_vertprog_destroy(struct nv30_context *nv30, struct nv30_vertex_program *vp)
+{
+ vp->translated = FALSE;
+
+ if (vp->nr_insns) {
+ FREE(vp->insns);
+ vp->insns = NULL;
+ vp->nr_insns = 0;
+ }
+
+ if (vp->nr_consts) {
+ FREE(vp->consts);
+ vp->consts = NULL;
+ vp->nr_consts = 0;
+ }
+
+ nouveau_resource_free(&vp->exec);
+ vp->exec_start = 0;
+ nouveau_resource_free(&vp->data);
+ vp->data_start = 0;
+ vp->data_start_min = 0;
+
+ vp->ir = vp->or = 0;
+ so_ref(NULL, &vp->so);
+}
+
+struct nv30_state_entry nv30_state_vertprog = {
+ .validate = nv30_vertprog_validate,
+ .dirty = {
+ .pipe = NV30_NEW_VERTPROG /*| NV30_NEW_UCP*/,
+ .hw = NV30_STATE_VERTPROG,
+ }
+};
diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile
new file mode 100644
index 0000000000..0ecae2b491
--- /dev/null
+++ b/src/gallium/drivers/nv40/Makefile
@@ -0,0 +1,29 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv40
+
+C_SOURCES = \
+ nv40_clear.c \
+ nv40_context.c \
+ nv40_draw.c \
+ nv40_fragprog.c \
+ nv40_fragtex.c \
+ nv40_miptree.c \
+ nv40_query.c \
+ nv40_screen.c \
+ nv40_state.c \
+ nv40_state_blend.c \
+ nv40_state_emit.c \
+ nv40_state_fb.c \
+ nv40_state_rasterizer.c \
+ nv40_state_scissor.c \
+ nv40_state_stipple.c \
+ nv40_state_viewport.c \
+ nv40_state_zsa.c \
+ nv40_surface.c \
+ nv40_transfer.c \
+ nv40_vbo.c \
+ nv40_vertprog.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/nv40/nv40_clear.c b/src/gallium/drivers/nv40/nv40_clear.c
new file mode 100644
index 0000000000..ddf13addf3
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_clear.c
@@ -0,0 +1,14 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "util/u_clear.h"
+
+#include "nv40_context.h"
+
+void
+nv40_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil)
+{
+ util_clear(pipe, &nv40_context(pipe)->framebuffer, buffers, rgba, depth,
+ stencil);
+}
diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c
new file mode 100644
index 0000000000..8eba6a43ef
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_context.c
@@ -0,0 +1,98 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "nv40_context.h"
+#include "nv40_screen.h"
+
+static void
+nv40_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
+ BEGIN_RING(curie, 0x1fd8, 1);
+ OUT_RING (2);
+ BEGIN_RING(curie, 0x1fd8, 1);
+ OUT_RING (1);
+ }
+
+ FIRE_RING(fence);
+}
+
+static void
+nv40_destroy(struct pipe_context *pipe)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ if (nv40->draw)
+ draw_destroy(nv40->draw);
+ FREE(nv40);
+}
+
+static unsigned int
+nv40_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static unsigned int
+nv40_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+struct pipe_context *
+nv40_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+ struct nv40_screen *screen = nv40_screen(pscreen);
+ struct pipe_winsys *ws = pscreen->winsys;
+ struct nv40_context *nv40;
+ struct nouveau_winsys *nvws = screen->nvws;
+
+ nv40 = CALLOC(1, sizeof(struct nv40_context));
+ if (!nv40)
+ return NULL;
+ nv40->screen = screen;
+ nv40->pctx_id = pctx_id;
+
+ nv40->nvws = nvws;
+
+ nv40->pipe.winsys = ws;
+ nv40->pipe.screen = pscreen;
+ nv40->pipe.destroy = nv40_destroy;
+ nv40->pipe.draw_arrays = nv40_draw_arrays;
+ nv40->pipe.draw_elements = nv40_draw_elements;
+ nv40->pipe.clear = nv40_clear;
+ nv40->pipe.flush = nv40_flush;
+
+ nv40->pipe.is_texture_referenced = nv40_is_texture_referenced;
+ nv40->pipe.is_buffer_referenced = nv40_is_buffer_referenced;
+
+ nv40_init_query_functions(nv40);
+ nv40_init_surface_functions(nv40);
+ nv40_init_state_functions(nv40);
+
+ /* Create, configure, and install fallback swtnl path */
+ nv40->draw = draw_create();
+ draw_wide_point_threshold(nv40->draw, 9999999.0);
+ draw_wide_line_threshold(nv40->draw, 9999999.0);
+ draw_enable_line_stipple(nv40->draw, FALSE);
+ draw_enable_point_sprites(nv40->draw, FALSE);
+ draw_set_rasterize_stage(nv40->draw, nv40_draw_render_stage(nv40));
+
+ return &nv40->pipe;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h
new file mode 100644
index 0000000000..97bc83292d
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_context.h
@@ -0,0 +1,233 @@
+#ifndef __NV40_CONTEXT_H__
+#define __NV40_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx) \
+ struct nv40_screen *ctx = nv40->screen
+#include "nouveau/nouveau_push.h"
+#include "nouveau/nouveau_stateobj.h"
+
+#include "nv40_state.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+ fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+ fprintf(stderr, "nouveau: "fmt, ##args);
+
+enum nv40_state_index {
+ NV40_STATE_FB = 0,
+ NV40_STATE_VIEWPORT = 1,
+ NV40_STATE_BLEND = 2,
+ NV40_STATE_RAST = 3,
+ NV40_STATE_ZSA = 4,
+ NV40_STATE_BCOL = 5,
+ NV40_STATE_CLIP = 6,
+ NV40_STATE_SCISSOR = 7,
+ NV40_STATE_STIPPLE = 8,
+ NV40_STATE_FRAGPROG = 9,
+ NV40_STATE_VERTPROG = 10,
+ NV40_STATE_FRAGTEX0 = 11,
+ NV40_STATE_FRAGTEX1 = 12,
+ NV40_STATE_FRAGTEX2 = 13,
+ NV40_STATE_FRAGTEX3 = 14,
+ NV40_STATE_FRAGTEX4 = 15,
+ NV40_STATE_FRAGTEX5 = 16,
+ NV40_STATE_FRAGTEX6 = 17,
+ NV40_STATE_FRAGTEX7 = 18,
+ NV40_STATE_FRAGTEX8 = 19,
+ NV40_STATE_FRAGTEX9 = 20,
+ NV40_STATE_FRAGTEX10 = 21,
+ NV40_STATE_FRAGTEX11 = 22,
+ NV40_STATE_FRAGTEX12 = 23,
+ NV40_STATE_FRAGTEX13 = 24,
+ NV40_STATE_FRAGTEX14 = 25,
+ NV40_STATE_FRAGTEX15 = 26,
+ NV40_STATE_VERTTEX0 = 27,
+ NV40_STATE_VERTTEX1 = 28,
+ NV40_STATE_VERTTEX2 = 29,
+ NV40_STATE_VERTTEX3 = 30,
+ NV40_STATE_VTXBUF = 31,
+ NV40_STATE_VTXFMT = 32,
+ NV40_STATE_VTXATTR = 33,
+ NV40_STATE_MAX = 34
+};
+
+#include "nv40_screen.h"
+
+#define NV40_NEW_BLEND (1 << 0)
+#define NV40_NEW_RAST (1 << 1)
+#define NV40_NEW_ZSA (1 << 2)
+#define NV40_NEW_SAMPLER (1 << 3)
+#define NV40_NEW_FB (1 << 4)
+#define NV40_NEW_STIPPLE (1 << 5)
+#define NV40_NEW_SCISSOR (1 << 6)
+#define NV40_NEW_VIEWPORT (1 << 7)
+#define NV40_NEW_BCOL (1 << 8)
+#define NV40_NEW_VERTPROG (1 << 9)
+#define NV40_NEW_FRAGPROG (1 << 10)
+#define NV40_NEW_ARRAYS (1 << 11)
+#define NV40_NEW_UCP (1 << 12)
+
+struct nv40_rasterizer_state {
+ struct pipe_rasterizer_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+struct nv40_zsa_state {
+ struct pipe_depth_stencil_alpha_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+struct nv40_blend_state {
+ struct pipe_blend_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+
+struct nv40_state {
+ unsigned scissor_enabled;
+ unsigned stipple_enabled;
+ unsigned viewport_bypass;
+ unsigned fp_samplers;
+
+ uint64_t dirty;
+ struct nouveau_stateobj *hw[NV40_STATE_MAX];
+};
+
+struct nv40_context {
+ struct pipe_context pipe;
+
+ struct nouveau_winsys *nvws;
+ struct nv40_screen *screen;
+ unsigned pctx_id;
+
+ struct draw_context *draw;
+
+ /* HW state derived from pipe states */
+ struct nv40_state state;
+ struct {
+ struct nv40_vertex_program *vertprog;
+
+ unsigned nr_attribs;
+ unsigned hw[PIPE_MAX_SHADER_INPUTS];
+ unsigned draw[PIPE_MAX_SHADER_INPUTS];
+ unsigned emit[PIPE_MAX_SHADER_INPUTS];
+ } swtnl;
+
+ enum {
+ HW, SWTNL, SWRAST
+ } render_mode;
+ unsigned fallback_swtnl;
+ unsigned fallback_swrast;
+
+ /* Context state */
+ unsigned dirty, draw_dirty;
+ struct pipe_scissor_state scissor;
+ unsigned stipple[32];
+ struct pipe_clip_state clip;
+ struct nv40_vertex_program *vertprog;
+ struct nv40_fragment_program *fragprog;
+ struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+ unsigned constbuf_nr[PIPE_SHADER_TYPES];
+ struct nv40_rasterizer_state *rasterizer;
+ struct nv40_zsa_state *zsa;
+ struct nv40_blend_state *blend;
+ struct pipe_blend_color blend_colour;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_buffer *idxbuf;
+ unsigned idxbuf_format;
+ struct nv40_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
+ struct nv40_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
+ unsigned nr_samplers;
+ unsigned nr_textures;
+ unsigned dirty_samplers;
+ struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+ unsigned vtxbuf_nr;
+ struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+ unsigned vtxelt_nr;
+ const unsigned *edgeflags;
+};
+
+static INLINE struct nv40_context *
+nv40_context(struct pipe_context *pipe)
+{
+ return (struct nv40_context *)pipe;
+}
+
+struct nv40_state_entry {
+ boolean (*validate)(struct nv40_context *nv40);
+ struct {
+ unsigned pipe;
+ unsigned hw;
+ } dirty;
+};
+
+extern void nv40_init_state_functions(struct nv40_context *nv40);
+extern void nv40_init_surface_functions(struct nv40_context *nv40);
+extern void nv40_init_query_functions(struct nv40_context *nv40);
+
+extern void nv40_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+/* nv40_draw.c */
+extern struct draw_stage *nv40_draw_render_stage(struct nv40_context *nv40);
+extern boolean nv40_draw_elements_swtnl(struct pipe_context *pipe,
+ struct pipe_buffer *idxbuf,
+ unsigned ib_size, unsigned mode,
+ unsigned start, unsigned count);
+
+/* nv40_vertprog.c */
+extern void nv40_vertprog_destroy(struct nv40_context *,
+ struct nv40_vertex_program *);
+
+/* nv40_fragprog.c */
+extern void nv40_fragprog_destroy(struct nv40_context *,
+ struct nv40_fragment_program *);
+
+/* nv40_fragtex.c */
+extern void nv40_fragtex_bind(struct nv40_context *);
+
+/* nv40_state.c and friends */
+extern boolean nv40_state_validate(struct nv40_context *nv40);
+extern boolean nv40_state_validate_swtnl(struct nv40_context *nv40);
+extern void nv40_state_emit(struct nv40_context *nv40);
+extern struct nv40_state_entry nv40_state_rasterizer;
+extern struct nv40_state_entry nv40_state_scissor;
+extern struct nv40_state_entry nv40_state_stipple;
+extern struct nv40_state_entry nv40_state_fragprog;
+extern struct nv40_state_entry nv40_state_vertprog;
+extern struct nv40_state_entry nv40_state_blend;
+extern struct nv40_state_entry nv40_state_blend_colour;
+extern struct nv40_state_entry nv40_state_zsa;
+extern struct nv40_state_entry nv40_state_viewport;
+extern struct nv40_state_entry nv40_state_framebuffer;
+extern struct nv40_state_entry nv40_state_fragtex;
+extern struct nv40_state_entry nv40_state_vbo;
+extern struct nv40_state_entry nv40_state_vtxfmt;
+
+/* nv40_vbo.c */
+extern boolean nv40_draw_arrays(struct pipe_context *, unsigned mode,
+ unsigned start, unsigned count);
+extern boolean nv40_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start,
+ unsigned count);
+
+/* nv40_clear.c */
+extern void nv40_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil);
+
+#endif
diff --git a/src/gallium/drivers/nv40/nv40_draw.c b/src/gallium/drivers/nv40/nv40_draw.c
new file mode 100644
index 0000000000..b2f19ecb69
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_draw.c
@@ -0,0 +1,352 @@
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_pack_color.h"
+
+#include "draw/draw_context.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pipe.h"
+
+#include "nv40_context.h"
+#define NV40_SHADER_NO_FUCKEDNESS
+#include "nv40_shader.h"
+
+/* Simple, but crappy, swtnl path, hopefully we wont need to hit this very
+ * often at all. Uses "quadro style" vertex submission + a fixed vertex
+ * layout to avoid the need to generate a vertex program or vtxfmt.
+ */
+
+struct nv40_render_stage {
+ struct draw_stage stage;
+ struct nv40_context *nv40;
+ unsigned prim;
+};
+
+static INLINE struct nv40_render_stage *
+nv40_render_stage(struct draw_stage *stage)
+{
+ return (struct nv40_render_stage *)stage;
+}
+
+static INLINE void
+nv40_render_vertex(struct nv40_context *nv40, const struct vertex_header *v)
+{
+ unsigned i;
+
+ for (i = 0; i < nv40->swtnl.nr_attribs; i++) {
+ unsigned idx = nv40->swtnl.draw[i];
+ unsigned hw = nv40->swtnl.hw[i];
+
+ switch (nv40->swtnl.emit[i]) {
+ case EMIT_OMIT:
+ break;
+ case EMIT_1F:
+ BEGIN_RING(curie, NV40TCL_VTX_ATTR_1F(hw), 1);
+ OUT_RING (fui(v->data[idx][0]));
+ break;
+ case EMIT_2F:
+ BEGIN_RING(curie, NV40TCL_VTX_ATTR_2F_X(hw), 2);
+ OUT_RING (fui(v->data[idx][0]));
+ OUT_RING (fui(v->data[idx][1]));
+ break;
+ case EMIT_3F:
+ BEGIN_RING(curie, NV40TCL_VTX_ATTR_3F_X(hw), 3);
+ OUT_RING (fui(v->data[idx][0]));
+ OUT_RING (fui(v->data[idx][1]));
+ OUT_RING (fui(v->data[idx][2]));
+ break;
+ case EMIT_4F:
+ BEGIN_RING(curie, NV40TCL_VTX_ATTR_4F_X(hw), 4);
+ OUT_RING (fui(v->data[idx][0]));
+ OUT_RING (fui(v->data[idx][1]));
+ OUT_RING (fui(v->data[idx][2]));
+ OUT_RING (fui(v->data[idx][3]));
+ break;
+ case EMIT_4UB:
+ BEGIN_RING(curie, NV40TCL_VTX_ATTR_4UB(hw), 1);
+ OUT_RING (pack_ub4(float_to_ubyte(v->data[idx][0]),
+ float_to_ubyte(v->data[idx][1]),
+ float_to_ubyte(v->data[idx][2]),
+ float_to_ubyte(v->data[idx][3])));
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+}
+
+static INLINE void
+nv40_render_prim(struct draw_stage *stage, struct prim_header *prim,
+ unsigned mode, unsigned count)
+{
+ struct nv40_render_stage *rs = nv40_render_stage(stage);
+ struct nv40_context *nv40 = rs->nv40;
+ struct nouveau_pushbuf *pb = nv40->screen->base.channel->pushbuf;
+ unsigned i;
+
+ /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
+ if (pb->remaining < ((count * 20) + 6)) {
+ if (rs->prim != NV40TCL_BEGIN_END_STOP) {
+ NOUVEAU_ERR("AIII, missed flush\n");
+ assert(0);
+ }
+ FIRE_RING(NULL);
+ nv40_state_emit(nv40);
+ }
+
+ /* Switch primitive modes if necessary */
+ if (rs->prim != mode) {
+ if (rs->prim != NV40TCL_BEGIN_END_STOP) {
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (NV40TCL_BEGIN_END_STOP);
+ }
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (mode);
+ rs->prim = mode;
+ }
+
+ /* Emit vertex data */
+ for (i = 0; i < count; i++)
+ nv40_render_vertex(nv40, prim->v[i]);
+
+ /* If it's likely we'll need to empty the push buffer soon, finish
+ * off the primitive now.
+ */
+ if (pb->remaining < ((count * 20) + 6)) {
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (NV40TCL_BEGIN_END_STOP);
+ rs->prim = NV40TCL_BEGIN_END_STOP;
+ }
+}
+
+static void
+nv40_render_point(struct draw_stage *draw, struct prim_header *prim)
+{
+ nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_POINTS, 1);
+}
+
+static void
+nv40_render_line(struct draw_stage *draw, struct prim_header *prim)
+{
+ nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_LINES, 2);
+}
+
+static void
+nv40_render_tri(struct draw_stage *draw, struct prim_header *prim)
+{
+ nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_TRIANGLES, 3);
+}
+
+static void
+nv40_render_flush(struct draw_stage *draw, unsigned flags)
+{
+ struct nv40_render_stage *rs = nv40_render_stage(draw);
+ struct nv40_context *nv40 = rs->nv40;
+
+ if (rs->prim != NV40TCL_BEGIN_END_STOP) {
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (NV40TCL_BEGIN_END_STOP);
+ rs->prim = NV40TCL_BEGIN_END_STOP;
+ }
+}
+
+static void
+nv40_render_reset_stipple_counter(struct draw_stage *draw)
+{
+}
+
+static void
+nv40_render_destroy(struct draw_stage *draw)
+{
+ FREE(draw);
+}
+
+static INLINE void
+emit_mov(struct nv40_vertex_program *vp,
+ unsigned dst, unsigned src, unsigned vor, unsigned mask)
+{
+ struct nv40_vertex_program_exec *inst;
+
+ vp->insns = realloc(vp->insns,
+ sizeof(struct nv40_vertex_program_exec) *
+ ++vp->nr_insns);
+ inst = &vp->insns[vp->nr_insns - 1];
+
+ inst->data[0] = 0x401f9c6c;
+ inst->data[1] = 0x0040000d | (src << 8);
+ inst->data[2] = 0x8106c083;
+ inst->data[3] = 0x6041ff80 | (dst << 2) | (mask << 13);
+ inst->const_index = -1;
+ inst->has_branch_offset = FALSE;
+
+ vp->ir |= (1 << src);
+ if (vor != ~0)
+ vp->or |= (1 << vor);
+}
+
+static struct nv40_vertex_program *
+create_drawvp(struct nv40_context *nv40)
+{
+ struct nv40_vertex_program *vp = CALLOC_STRUCT(nv40_vertex_program);
+ unsigned i;
+
+ emit_mov(vp, NV40_VP_INST_DEST_POS, 0, ~0, 0xf);
+ emit_mov(vp, NV40_VP_INST_DEST_COL0, 3, 0, 0xf);
+ emit_mov(vp, NV40_VP_INST_DEST_COL1, 4, 1, 0xf);
+ emit_mov(vp, NV40_VP_INST_DEST_BFC0, 3, 2, 0xf);
+ emit_mov(vp, NV40_VP_INST_DEST_BFC1, 4, 3, 0xf);
+ emit_mov(vp, NV40_VP_INST_DEST_FOGC, 5, 4, 0x8);
+ for (i = 0; i < 8; i++)
+ emit_mov(vp, NV40_VP_INST_DEST_TC(i), 8 + i, 14 + i, 0xf);
+
+ vp->insns[vp->nr_insns - 1].data[3] |= 1;
+ vp->translated = TRUE;
+ return vp;
+}
+
+struct draw_stage *
+nv40_draw_render_stage(struct nv40_context *nv40)
+{
+ struct nv40_render_stage *render = CALLOC_STRUCT(nv40_render_stage);
+
+ if (!nv40->swtnl.vertprog)
+ nv40->swtnl.vertprog = create_drawvp(nv40);
+
+ render->nv40 = nv40;
+ render->stage.draw = nv40->draw;
+ render->stage.point = nv40_render_point;
+ render->stage.line = nv40_render_line;
+ render->stage.tri = nv40_render_tri;
+ render->stage.flush = nv40_render_flush;
+ render->stage.reset_stipple_counter = nv40_render_reset_stipple_counter;
+ render->stage.destroy = nv40_render_destroy;
+
+ return &render->stage;
+}
+
+boolean
+nv40_draw_elements_swtnl(struct pipe_context *pipe,
+ struct pipe_buffer *idxbuf, unsigned idxbuf_size,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct pipe_screen *pscreen = pipe->screen;
+ unsigned i;
+ void *map;
+
+ if (!nv40_state_validate_swtnl(nv40))
+ return FALSE;
+ nv40->state.dirty &= ~(1ULL << NV40_STATE_VTXBUF);
+ nv40_state_emit(nv40);
+
+ for (i = 0; i < nv40->vtxbuf_nr; i++) {
+ map = pipe_buffer_map(pscreen, nv40->vtxbuf[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_vertex_buffer(nv40->draw, i, map);
+ }
+
+ if (idxbuf) {
+ map = pipe_buffer_map(pscreen, idxbuf,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer(nv40->draw, idxbuf_size, map);
+ } else {
+ draw_set_mapped_element_buffer(nv40->draw, 0, NULL);
+ }
+
+ if (nv40->constbuf[PIPE_SHADER_VERTEX]) {
+ const unsigned nr = nv40->constbuf_nr[PIPE_SHADER_VERTEX];
+
+ map = pipe_buffer_map(pscreen,
+ nv40->constbuf[PIPE_SHADER_VERTEX],
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_constant_buffer(nv40->draw, map, nr);
+ }
+
+ draw_arrays(nv40->draw, mode, start, count);
+
+ for (i = 0; i < nv40->vtxbuf_nr; i++)
+ pipe_buffer_unmap(pscreen, nv40->vtxbuf[i].buffer);
+
+ if (idxbuf)
+ pipe_buffer_unmap(pscreen, idxbuf);
+
+ if (nv40->constbuf[PIPE_SHADER_VERTEX])
+ pipe_buffer_unmap(pscreen, nv40->constbuf[PIPE_SHADER_VERTEX]);
+
+ draw_flush(nv40->draw);
+ pipe->flush(pipe, 0, NULL);
+
+ return TRUE;
+}
+
+static INLINE void
+emit_attrib(struct nv40_context *nv40, unsigned hw, unsigned emit,
+ unsigned semantic, unsigned index)
+{
+ unsigned draw_out = draw_find_vs_output(nv40->draw, semantic, index);
+ unsigned a = nv40->swtnl.nr_attribs++;
+
+ nv40->swtnl.hw[a] = hw;
+ nv40->swtnl.emit[a] = emit;
+ nv40->swtnl.draw[a] = draw_out;
+}
+
+static boolean
+nv40_state_vtxfmt_validate(struct nv40_context *nv40)
+{
+ struct nv40_fragment_program *fp = nv40->fragprog;
+ unsigned colour = 0, texcoords = 0, fog = 0, i;
+
+ /* Determine needed fragprog inputs */
+ for (i = 0; i < fp->info.num_inputs; i++) {
+ switch (fp->info.input_semantic_name[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ colour |= (1 << fp->info.input_semantic_index[i]);
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ texcoords |= (1 << fp->info.input_semantic_index[i]);
+ break;
+ case TGSI_SEMANTIC_FOG:
+ fog = 1;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ nv40->swtnl.nr_attribs = 0;
+
+ /* Map draw vtxprog output to hw attribute IDs */
+ for (i = 0; i < 2; i++) {
+ if (!(colour & (1 << i)))
+ continue;
+ emit_attrib(nv40, 3 + i, EMIT_4UB, TGSI_SEMANTIC_COLOR, i);
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (!(texcoords & (1 << i)))
+ continue;
+ emit_attrib(nv40, 8 + i, EMIT_4F, TGSI_SEMANTIC_GENERIC, i);
+ }
+
+ if (fog) {
+ emit_attrib(nv40, 5, EMIT_1F, TGSI_SEMANTIC_FOG, 0);
+ }
+
+ emit_attrib(nv40, 0, EMIT_3F, TGSI_SEMANTIC_POSITION, 0);
+
+ return FALSE;
+}
+
+struct nv40_state_entry nv40_state_vtxfmt = {
+ .validate = nv40_state_vtxfmt_validate,
+ .dirty = {
+ .pipe = NV40_NEW_ARRAYS | NV40_NEW_FRAGPROG,
+ .hw = 0
+ }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nv40/nv40_fragprog.c
new file mode 100644
index 0000000000..32d9ed1a7f
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_fragprog.c
@@ -0,0 +1,995 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+
+#include "nv40_context.h"
+
+#define SWZ_X 0
+#define SWZ_Y 1
+#define SWZ_Z 2
+#define SWZ_W 3
+#define MASK_X 1
+#define MASK_Y 2
+#define MASK_Z 4
+#define MASK_W 8
+#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
+#define DEF_SCALE NV40_FP_OP_DST_SCALE_1X
+#define DEF_CTEST NV40_FP_OP_COND_TR
+#include "nv40_shader.h"
+
+#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv40_sr_neg((s))
+#define abs(s) nv40_sr_abs((s))
+#define scale(s,v) nv40_sr_scale((s), NV40_FP_OP_DST_SCALE_##v)
+
+#define MAX_CONSTS 128
+#define MAX_IMM 32
+struct nv40_fpc {
+ struct nv40_fragment_program *fp;
+
+ uint attrib_map[PIPE_MAX_SHADER_INPUTS];
+
+ unsigned r_temps;
+ unsigned r_temps_discard;
+ struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS];
+ struct nv40_sreg *r_temp;
+
+ int num_regs;
+
+ unsigned inst_offset;
+ unsigned have_const;
+
+ struct {
+ int pipe;
+ float vals[4];
+ } consts[MAX_CONSTS];
+ int nr_consts;
+
+ struct nv40_sreg imm[MAX_IMM];
+ unsigned nr_imm;
+};
+
+static INLINE struct nv40_sreg
+temp(struct nv40_fpc *fpc)
+{
+ int idx = ffs(~fpc->r_temps) - 1;
+
+ if (idx < 0) {
+ NOUVEAU_ERR("out of temps!!\n");
+ assert(0);
+ return nv40_sr(NV40SR_TEMP, 0);
+ }
+
+ fpc->r_temps |= (1 << idx);
+ fpc->r_temps_discard |= (1 << idx);
+ return nv40_sr(NV40SR_TEMP, idx);
+}
+
+static INLINE void
+release_temps(struct nv40_fpc *fpc)
+{
+ fpc->r_temps &= ~fpc->r_temps_discard;
+ fpc->r_temps_discard = 0;
+}
+
+static INLINE struct nv40_sreg
+constant(struct nv40_fpc *fpc, int pipe, float vals[4])
+{
+ int idx;
+
+ if (fpc->nr_consts == MAX_CONSTS)
+ assert(0);
+ idx = fpc->nr_consts++;
+
+ fpc->consts[idx].pipe = pipe;
+ if (pipe == -1)
+ memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float));
+ return nv40_sr(NV40SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+ nv40_fp_arith((cc), (s), NV40_FP_OP_OPCODE_##o, \
+ (d), (m), (s0), (s1), (s2))
+#define tex(cc,s,o,u,d,m,s0,s1,s2) \
+ nv40_fp_tex((cc), (s), NV40_FP_OP_OPCODE_##o, (u), \
+ (d), (m), (s0), none, none)
+
+static void
+grow_insns(struct nv40_fpc *fpc, int size)
+{
+ struct nv40_fragment_program *fp = fpc->fp;
+
+ fp->insn_len += size;
+ fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len);
+}
+
+static void
+emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src)
+{
+ struct nv40_fragment_program *fp = fpc->fp;
+ uint32_t *hw = &fp->insn[fpc->inst_offset];
+ uint32_t sr = 0;
+
+ switch (src.type) {
+ case NV40SR_INPUT:
+ sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT);
+ hw[0] |= (src.index << NV40_FP_OP_INPUT_SRC_SHIFT);
+ break;
+ case NV40SR_OUTPUT:
+ sr |= NV40_FP_REG_SRC_HALF;
+ /* fall-through */
+ case NV40SR_TEMP:
+ sr |= (NV40_FP_REG_TYPE_TEMP << NV40_FP_REG_TYPE_SHIFT);
+ sr |= (src.index << NV40_FP_REG_SRC_SHIFT);
+ break;
+ case NV40SR_CONST:
+ if (!fpc->have_const) {
+ grow_insns(fpc, 4);
+ fpc->have_const = 1;
+ }
+
+ hw = &fp->insn[fpc->inst_offset];
+ if (fpc->consts[src.index].pipe >= 0) {
+ struct nv40_fragment_program_data *fpd;
+
+ fp->consts = realloc(fp->consts, ++fp->nr_consts *
+ sizeof(*fpd));
+ fpd = &fp->consts[fp->nr_consts - 1];
+ fpd->offset = fpc->inst_offset + 4;
+ fpd->index = fpc->consts[src.index].pipe;
+ memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4);
+ } else {
+ memcpy(&fp->insn[fpc->inst_offset + 4],
+ fpc->consts[src.index].vals,
+ sizeof(uint32_t) * 4);
+ }
+
+ sr |= (NV40_FP_REG_TYPE_CONST << NV40_FP_REG_TYPE_SHIFT);
+ break;
+ case NV40SR_NONE:
+ sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (src.negate)
+ sr |= NV40_FP_REG_NEGATE;
+
+ if (src.abs)
+ hw[1] |= (1 << (29 + pos));
+
+ sr |= ((src.swz[0] << NV40_FP_REG_SWZ_X_SHIFT) |
+ (src.swz[1] << NV40_FP_REG_SWZ_Y_SHIFT) |
+ (src.swz[2] << NV40_FP_REG_SWZ_Z_SHIFT) |
+ (src.swz[3] << NV40_FP_REG_SWZ_W_SHIFT));
+
+ hw[pos + 1] |= sr;
+}
+
+static void
+emit_dst(struct nv40_fpc *fpc, struct nv40_sreg dst)
+{
+ struct nv40_fragment_program *fp = fpc->fp;
+ uint32_t *hw = &fp->insn[fpc->inst_offset];
+
+ switch (dst.type) {
+ case NV40SR_TEMP:
+ if (fpc->num_regs < (dst.index + 1))
+ fpc->num_regs = dst.index + 1;
+ break;
+ case NV40SR_OUTPUT:
+ if (dst.index == 1) {
+ fp->fp_control |= 0xe;
+ } else {
+ hw[0] |= NV40_FP_OP_OUT_REG_HALF;
+ }
+ break;
+ case NV40SR_NONE:
+ hw[0] |= (1 << 30);
+ break;
+ default:
+ assert(0);
+ }
+
+ hw[0] |= (dst.index << NV40_FP_OP_OUT_REG_SHIFT);
+}
+
+static void
+nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op,
+ struct nv40_sreg dst, int mask,
+ struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2)
+{
+ struct nv40_fragment_program *fp = fpc->fp;
+ uint32_t *hw;
+
+ fpc->inst_offset = fp->insn_len;
+ fpc->have_const = 0;
+ grow_insns(fpc, 4);
+ hw = &fp->insn[fpc->inst_offset];
+ memset(hw, 0, sizeof(uint32_t) * 4);
+
+ if (op == NV40_FP_OP_OPCODE_KIL)
+ fp->fp_control |= NV40TCL_FP_CONTROL_KIL;
+ hw[0] |= (op << NV40_FP_OP_OPCODE_SHIFT);
+ hw[0] |= (mask << NV40_FP_OP_OUTMASK_SHIFT);
+ hw[2] |= (dst.dst_scale << NV40_FP_OP_DST_SCALE_SHIFT);
+
+ if (sat)
+ hw[0] |= NV40_FP_OP_OUT_SAT;
+
+ if (dst.cc_update)
+ hw[0] |= NV40_FP_OP_COND_WRITE_ENABLE;
+ hw[1] |= (dst.cc_test << NV40_FP_OP_COND_SHIFT);
+ hw[1] |= ((dst.cc_swz[0] << NV40_FP_OP_COND_SWZ_X_SHIFT) |
+ (dst.cc_swz[1] << NV40_FP_OP_COND_SWZ_Y_SHIFT) |
+ (dst.cc_swz[2] << NV40_FP_OP_COND_SWZ_Z_SHIFT) |
+ (dst.cc_swz[3] << NV40_FP_OP_COND_SWZ_W_SHIFT));
+
+ emit_dst(fpc, dst);
+ emit_src(fpc, 0, s0);
+ emit_src(fpc, 1, s1);
+ emit_src(fpc, 2, s2);
+}
+
+static void
+nv40_fp_tex(struct nv40_fpc *fpc, int sat, int op, int unit,
+ struct nv40_sreg dst, int mask,
+ struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2)
+{
+ struct nv40_fragment_program *fp = fpc->fp;
+
+ nv40_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2);
+
+ fp->insn[fpc->inst_offset] |= (unit << NV40_FP_OP_TEX_UNIT_SHIFT);
+ fp->samplers |= (1 << unit);
+}
+
+static INLINE struct nv40_sreg
+tgsi_src(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc)
+{
+ struct nv40_sreg src;
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ src = nv40_sr(NV40SR_INPUT,
+ fpc->attrib_map[fsrc->SrcRegister.Index]);
+ break;
+ case TGSI_FILE_CONSTANT:
+ src = constant(fpc, fsrc->SrcRegister.Index, NULL);
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ assert(fsrc->SrcRegister.Index < fpc->nr_imm);
+ src = fpc->imm[fsrc->SrcRegister.Index];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ src = fpc->r_temp[fsrc->SrcRegister.Index];
+ break;
+ /* NV40 fragprog result regs are just temps, so this is simple */
+ case TGSI_FILE_OUTPUT:
+ src = fpc->r_result[fsrc->SrcRegister.Index];
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ break;
+ }
+
+ src.abs = fsrc->SrcRegisterExtMod.Absolute;
+ src.negate = fsrc->SrcRegister.Negate;
+ src.swz[0] = fsrc->SrcRegister.SwizzleX;
+ src.swz[1] = fsrc->SrcRegister.SwizzleY;
+ src.swz[2] = fsrc->SrcRegister.SwizzleZ;
+ src.swz[3] = fsrc->SrcRegister.SwizzleW;
+ return src;
+}
+
+static INLINE struct nv40_sreg
+tgsi_dst(struct nv40_fpc *fpc, const struct tgsi_full_dst_register *fdst) {
+ switch (fdst->DstRegister.File) {
+ case TGSI_FILE_OUTPUT:
+ return fpc->r_result[fdst->DstRegister.Index];
+ case TGSI_FILE_TEMPORARY:
+ return fpc->r_temp[fdst->DstRegister.Index];
+ case TGSI_FILE_NULL:
+ return nv40_sr(NV40SR_NONE, 0);
+ default:
+ NOUVEAU_ERR("bad dst file %d\n", fdst->DstRegister.File);
+ return nv40_sr(NV40SR_NONE, 0);
+ }
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+ int mask = 0;
+
+ if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
+ if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
+ if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
+ if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
+ return mask;
+}
+
+static boolean
+src_native_swz(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc,
+ struct nv40_sreg *src)
+{
+ const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+ struct nv40_sreg tgsi = tgsi_src(fpc, fsrc);
+ uint mask = 0, zero_mask = 0, one_mask = 0, neg_mask = 0;
+ uint neg[4] = { fsrc->SrcRegisterExtSwz.NegateX,
+ fsrc->SrcRegisterExtSwz.NegateY,
+ fsrc->SrcRegisterExtSwz.NegateZ,
+ fsrc->SrcRegisterExtSwz.NegateW };
+ uint c;
+
+ for (c = 0; c < 4; c++) {
+ switch (tgsi_util_get_full_src_register_extswizzle(fsrc, c)) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ mask |= (1 << c);
+ break;
+ case TGSI_EXTSWIZZLE_ZERO:
+ zero_mask |= (1 << c);
+ tgsi.swz[c] = SWZ_X;
+ break;
+ case TGSI_EXTSWIZZLE_ONE:
+ one_mask |= (1 << c);
+ tgsi.swz[c] = SWZ_X;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (!tgsi.negate && neg[c])
+ neg_mask |= (1 << c);
+ }
+
+ if (mask == MASK_ALL && !neg_mask)
+ return TRUE;
+
+ *src = temp(fpc);
+
+ if (mask)
+ arith(fpc, 0, MOV, *src, mask, tgsi, none, none);
+
+ if (zero_mask)
+ arith(fpc, 0, SFL, *src, zero_mask, *src, none, none);
+
+ if (one_mask)
+ arith(fpc, 0, STR, *src, one_mask, *src, none, none);
+
+ if (neg_mask) {
+ struct nv40_sreg one = temp(fpc);
+ arith(fpc, 0, STR, one, neg_mask, one, none, none);
+ arith(fpc, 0, MUL, *src, neg_mask, *src, neg(one), none);
+ }
+
+ return FALSE;
+}
+
+static boolean
+nv40_fragprog_parse_instruction(struct nv40_fpc *fpc,
+ const struct tgsi_full_instruction *finst)
+{
+ const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+ struct nv40_sreg src[3], dst, tmp;
+ int mask, sat, unit;
+ int ai = -1, ci = -1, ii = -1;
+ int i;
+
+ if (finst->Instruction.Opcode == TGSI_OPCODE_END)
+ return TRUE;
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+ if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) {
+ src[i] = tgsi_src(fpc, fsrc);
+ }
+ }
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ case TGSI_FILE_CONSTANT:
+ case TGSI_FILE_TEMPORARY:
+ if (!src_native_swz(fpc, fsrc, &src[i]))
+ continue;
+ break;
+ default:
+ break;
+ }
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ if (ai == -1 || ai == fsrc->SrcRegister.Index) {
+ ai = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(fpc, fsrc);
+ } else {
+ src[i] = temp(fpc);
+ arith(fpc, 0, MOV, src[i], MASK_ALL,
+ tgsi_src(fpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ if ((ci == -1 && ii == -1) ||
+ ci == fsrc->SrcRegister.Index) {
+ ci = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(fpc, fsrc);
+ } else {
+ src[i] = temp(fpc);
+ arith(fpc, 0, MOV, src[i], MASK_ALL,
+ tgsi_src(fpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ if ((ci == -1 && ii == -1) ||
+ ii == fsrc->SrcRegister.Index) {
+ ii = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(fpc, fsrc);
+ } else {
+ src[i] = temp(fpc);
+ arith(fpc, 0, MOV, src[i], MASK_ALL,
+ tgsi_src(fpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_TEMPORARY:
+ /* handled above */
+ break;
+ case TGSI_FILE_SAMPLER:
+ unit = fsrc->SrcRegister.Index;
+ break;
+ case TGSI_FILE_OUTPUT:
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ return FALSE;
+ }
+ }
+
+ dst = tgsi_dst(fpc, &finst->FullDstRegisters[0]);
+ mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+ sat = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE);
+
+ switch (finst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none);
+ break;
+ case TGSI_OPCODE_ADD:
+ arith(fpc, sat, ADD, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_CMP:
+ tmp = temp(fpc);
+ arith(fpc, sat, MOV, dst, mask, src[2], none, none);
+ tmp.cc_update = 1;
+ arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none);
+ dst.cc_test = NV40_VP_INST_COND_LT;
+ arith(fpc, sat, MOV, dst, mask, src[1], none, none);
+ break;
+ case TGSI_OPCODE_COS:
+ arith(fpc, sat, COS, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_DDX:
+ if (mask & (MASK_Z | MASK_W)) {
+ tmp = temp(fpc);
+ arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y,
+ swz(src[0], Z, W, Z, W), none, none);
+ arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W,
+ swz(tmp, X, Y, X, Y), none, none);
+ arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y, src[0],
+ none, none);
+ arith(fpc, 0, MOV, dst, mask, tmp, none, none);
+ } else {
+ arith(fpc, sat, DDX, dst, mask, src[0], none, none);
+ }
+ break;
+ case TGSI_OPCODE_DDY:
+ if (mask & (MASK_Z | MASK_W)) {
+ tmp = temp(fpc);
+ arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y,
+ swz(src[0], Z, W, Z, W), none, none);
+ arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W,
+ swz(tmp, X, Y, X, Y), none, none);
+ arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y, src[0],
+ none, none);
+ arith(fpc, 0, MOV, dst, mask, tmp, none, none);
+ } else {
+ arith(fpc, sat, DDY, dst, mask, src[0], none, none);
+ }
+ break;
+ case TGSI_OPCODE_DP3:
+ arith(fpc, sat, DP3, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DP4:
+ arith(fpc, sat, DP4, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DPH:
+ tmp = temp(fpc);
+ arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none);
+ arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X),
+ swz(src[1], W, W, W, W), none);
+ break;
+ case TGSI_OPCODE_DST:
+ arith(fpc, sat, DST, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_EX2:
+ arith(fpc, sat, EX2, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_FLR:
+ arith(fpc, sat, FLR, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_FRC:
+ arith(fpc, sat, FRC, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_KILP:
+ arith(fpc, 0, KIL, none, 0, none, none, none);
+ break;
+ case TGSI_OPCODE_KIL:
+ dst = nv40_sr(NV40SR_NONE, 0);
+ dst.cc_update = 1;
+ arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none);
+ dst.cc_update = 0; dst.cc_test = NV40_FP_OP_COND_LT;
+ arith(fpc, 0, KIL, dst, 0, none, none, none);
+ break;
+ case TGSI_OPCODE_LG2:
+ arith(fpc, sat, LG2, dst, mask, src[0], none, none);
+ break;
+// case TGSI_OPCODE_LIT:
+ case TGSI_OPCODE_LRP:
+ tmp = temp(fpc);
+ arith(fpc, 0, MAD, tmp, mask, neg(src[0]), src[2], src[2]);
+ arith(fpc, sat, MAD, dst, mask, src[0], src[1], tmp);
+ break;
+ case TGSI_OPCODE_MAD:
+ arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]);
+ break;
+ case TGSI_OPCODE_MAX:
+ arith(fpc, sat, MAX, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MIN:
+ arith(fpc, sat, MIN, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MOV:
+ arith(fpc, sat, MOV, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_MUL:
+ arith(fpc, sat, MUL, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_NOISE1:
+ case TGSI_OPCODE_NOISE2:
+ case TGSI_OPCODE_NOISE3:
+ case TGSI_OPCODE_NOISE4:
+ arith(fpc, sat, SFL, dst, mask, none, none, none);
+ break;
+ case TGSI_OPCODE_POW:
+ tmp = temp(fpc);
+ arith(fpc, 0, LG2, tmp, MASK_X,
+ swz(src[0], X, X, X, X), none, none);
+ arith(fpc, 0, MUL, tmp, MASK_X, swz(tmp, X, X, X, X),
+ swz(src[1], X, X, X, X), none);
+ arith(fpc, sat, EX2, dst, mask,
+ swz(tmp, X, X, X, X), none, none);
+ break;
+ case TGSI_OPCODE_RCP:
+ arith(fpc, sat, RCP, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_RET:
+ assert(0);
+ break;
+ case TGSI_OPCODE_RFL:
+ tmp = temp(fpc);
+ arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[0], none);
+ arith(fpc, 0, DP3, tmp, MASK_Y, src[0], src[1], none);
+ arith(fpc, 0, DIV, scale(tmp, 2X), MASK_Z,
+ swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none);
+ arith(fpc, sat, MAD, dst, mask,
+ swz(tmp, Z, Z, Z, Z), src[0], neg(src[1]));
+ break;
+ case TGSI_OPCODE_RSQ:
+ tmp = temp(fpc);
+ arith(fpc, 0, LG2, scale(tmp, INV_2X), MASK_X,
+ abs(swz(src[0], X, X, X, X)), none, none);
+ arith(fpc, sat, EX2, dst, mask,
+ neg(swz(tmp, X, X, X, X)), none, none);
+ break;
+ case TGSI_OPCODE_SCS:
+ if (mask & MASK_X) {
+ arith(fpc, sat, COS, dst, MASK_X,
+ swz(src[0], X, X, X, X), none, none);
+ }
+ if (mask & MASK_Y) {
+ arith(fpc, sat, SIN, dst, MASK_Y,
+ swz(src[0], X, X, X, X), none, none);
+ }
+ break;
+ case TGSI_OPCODE_SEQ:
+ arith(fpc, sat, SEQ, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SFL:
+ arith(fpc, sat, SFL, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SGE:
+ arith(fpc, sat, SGE, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SGT:
+ arith(fpc, sat, SGT, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SIN:
+ arith(fpc, sat, SIN, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_SLE:
+ arith(fpc, sat, SLE, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SLT:
+ arith(fpc, sat, SLT, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SNE:
+ arith(fpc, sat, SNE, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_STR:
+ arith(fpc, sat, STR, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SUB:
+ arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none);
+ break;
+ case TGSI_OPCODE_TEX:
+ tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_TXB:
+ tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_TXP:
+ tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_XPD:
+ tmp = temp(fpc);
+ arith(fpc, 0, MUL, tmp, mask,
+ swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
+ arith(fpc, sat, MAD, dst, (mask & ~MASK_W),
+ swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
+ neg(tmp));
+ break;
+ default:
+ NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+ return FALSE;
+ }
+
+ release_temps(fpc);
+ return TRUE;
+}
+
+static boolean
+nv40_fragprog_parse_decl_attrib(struct nv40_fpc *fpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ int hw;
+
+ switch (fdec->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ hw = NV40_FP_OP_INPUT_SRC_POSITION;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ if (fdec->Semantic.SemanticIndex == 0) {
+ hw = NV40_FP_OP_INPUT_SRC_COL0;
+ } else
+ if (fdec->Semantic.SemanticIndex == 1) {
+ hw = NV40_FP_OP_INPUT_SRC_COL1;
+ } else {
+ NOUVEAU_ERR("bad colour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_FOG:
+ hw = NV40_FP_OP_INPUT_SRC_FOGC;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ if (fdec->Semantic.SemanticIndex <= 7) {
+ hw = NV40_FP_OP_INPUT_SRC_TC(fdec->Semantic.
+ SemanticIndex);
+ } else {
+ NOUVEAU_ERR("bad generic semantic index\n");
+ return FALSE;
+ }
+ break;
+ default:
+ NOUVEAU_ERR("bad input semantic\n");
+ return FALSE;
+ }
+
+ fpc->attrib_map[fdec->DeclarationRange.First] = hw;
+ return TRUE;
+}
+
+static boolean
+nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ unsigned idx = fdec->DeclarationRange.First;
+ unsigned hw;
+
+ switch (fdec->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ hw = 1;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ switch (fdec->Semantic.SemanticIndex) {
+ case 0: hw = 0; break;
+ case 1: hw = 2; break;
+ case 2: hw = 3; break;
+ case 3: hw = 4; break;
+ default:
+ NOUVEAU_ERR("bad rcol index\n");
+ return FALSE;
+ }
+ break;
+ default:
+ NOUVEAU_ERR("bad output semantic\n");
+ return FALSE;
+ }
+
+ fpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw);
+ fpc->r_temps |= (1 << hw);
+ return TRUE;
+}
+
+static boolean
+nv40_fragprog_prepare(struct nv40_fpc *fpc)
+{
+ struct tgsi_parse_context p;
+ int high_temp = -1, i;
+
+ tgsi_parse_init(&p, fpc->fp->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&p)) {
+ const union tgsi_full_token *tok = &p.FullToken;
+
+ tgsi_parse_token(&p);
+ switch(tok->Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *fdec;
+ fdec = &p.FullToken.FullDeclaration;
+ switch (fdec->Declaration.File) {
+ case TGSI_FILE_INPUT:
+ if (!nv40_fragprog_parse_decl_attrib(fpc, fdec))
+ goto out_err;
+ break;
+ case TGSI_FILE_OUTPUT:
+ if (!nv40_fragprog_parse_decl_output(fpc, fdec))
+ goto out_err;
+ break;
+ case TGSI_FILE_TEMPORARY:
+ if (fdec->DeclarationRange.Last > high_temp) {
+ high_temp =
+ fdec->DeclarationRange.Last;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ struct tgsi_full_immediate *imm;
+ float vals[4];
+
+ imm = &p.FullToken.FullImmediate;
+ assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
+ assert(fpc->nr_imm < MAX_IMM);
+
+ vals[0] = imm->u[0].Float;
+ vals[1] = imm->u[1].Float;
+ vals[2] = imm->u[2].Float;
+ vals[3] = imm->u[3].Float;
+ fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ tgsi_parse_free(&p);
+
+ if (++high_temp) {
+ fpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg));
+ for (i = 0; i < high_temp; i++)
+ fpc->r_temp[i] = temp(fpc);
+ fpc->r_temps_discard = 0;
+ }
+
+ return TRUE;
+
+out_err:
+ if (fpc->r_temp)
+ FREE(fpc->r_temp);
+ tgsi_parse_free(&p);
+ return FALSE;
+}
+
+static void
+nv40_fragprog_translate(struct nv40_context *nv40,
+ struct nv40_fragment_program *fp)
+{
+ struct tgsi_parse_context parse;
+ struct nv40_fpc *fpc = NULL;
+
+ fpc = CALLOC(1, sizeof(struct nv40_fpc));
+ if (!fpc)
+ return;
+ fpc->fp = fp;
+ fpc->num_regs = 2;
+
+ if (!nv40_fragprog_prepare(fpc)) {
+ FREE(fpc);
+ return;
+ }
+
+ tgsi_parse_init(&parse, fp->pipe.tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ const struct tgsi_full_instruction *finst;
+
+ finst = &parse.FullToken.FullInstruction;
+ if (!nv40_fragprog_parse_instruction(fpc, finst))
+ goto out_err;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ fp->fp_control |= fpc->num_regs << NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT;
+
+ /* Terminate final instruction */
+ fp->insn[fpc->inst_offset] |= 0x00000001;
+
+ /* Append NOP + END instruction, may or may not be necessary. */
+ fpc->inst_offset = fp->insn_len;
+ grow_insns(fpc, 4);
+ fp->insn[fpc->inst_offset + 0] = 0x00000001;
+ fp->insn[fpc->inst_offset + 1] = 0x00000000;
+ fp->insn[fpc->inst_offset + 2] = 0x00000000;
+ fp->insn[fpc->inst_offset + 3] = 0x00000000;
+
+ fp->translated = TRUE;
+out_err:
+ tgsi_parse_free(&parse);
+ if (fpc->r_temp)
+ FREE(fpc->r_temp);
+ FREE(fpc);
+}
+
+static void
+nv40_fragprog_upload(struct nv40_context *nv40,
+ struct nv40_fragment_program *fp)
+{
+ struct pipe_screen *pscreen = nv40->pipe.screen;
+ const uint32_t le = 1;
+ uint32_t *map;
+ int i;
+
+ map = pipe_buffer_map(pscreen, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+#if 0
+ for (i = 0; i < fp->insn_len; i++) {
+ fflush(stdout); fflush(stderr);
+ NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
+ fflush(stdout); fflush(stderr);
+ }
+#endif
+
+ if ((*(const uint8_t *)&le)) {
+ for (i = 0; i < fp->insn_len; i++) {
+ map[i] = fp->insn[i];
+ }
+ } else {
+ /* Weird swapping for big-endian chips */
+ for (i = 0; i < fp->insn_len; i++) {
+ map[i] = ((fp->insn[i] & 0xffff) << 16) |
+ ((fp->insn[i] >> 16) & 0xffff);
+ }
+ }
+
+ pipe_buffer_unmap(pscreen, fp->buffer);
+}
+
+static boolean
+nv40_fragprog_validate(struct nv40_context *nv40)
+{
+ struct nv40_fragment_program *fp = nv40->fragprog;
+ struct pipe_buffer *constbuf =
+ nv40->constbuf[PIPE_SHADER_FRAGMENT];
+ struct pipe_screen *pscreen = nv40->pipe.screen;
+ struct nouveau_stateobj *so;
+ boolean new_consts = FALSE;
+ int i;
+
+ if (fp->translated)
+ goto update_constants;
+
+ nv40->fallback_swrast &= ~NV40_NEW_FRAGPROG;
+ nv40_fragprog_translate(nv40, fp);
+ if (!fp->translated) {
+ nv40->fallback_swrast |= NV40_NEW_FRAGPROG;
+ return FALSE;
+ }
+
+ fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4);
+ nv40_fragprog_upload(nv40, fp);
+
+ so = so_new(4, 1);
+ so_method(so, nv40->screen->curie, NV40TCL_FP_ADDRESS, 1);
+ so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW |
+ NOUVEAU_BO_OR, NV40TCL_FP_ADDRESS_DMA0,
+ NV40TCL_FP_ADDRESS_DMA1);
+ so_method(so, nv40->screen->curie, NV40TCL_FP_CONTROL, 1);
+ so_data (so, fp->fp_control);
+ so_ref(so, &fp->so);
+ so_ref(NULL, &so);
+
+update_constants:
+ if (fp->nr_consts) {
+ float *map;
+
+ map = pipe_buffer_map(pscreen, constbuf,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ for (i = 0; i < fp->nr_consts; i++) {
+ struct nv40_fragment_program_data *fpd = &fp->consts[i];
+ uint32_t *p = &fp->insn[fpd->offset];
+ uint32_t *cb = (uint32_t *)&map[fpd->index * 4];
+
+ if (!memcmp(p, cb, 4 * sizeof(float)))
+ continue;
+ memcpy(p, cb, 4 * sizeof(float));
+ new_consts = TRUE;
+ }
+ pipe_buffer_unmap(pscreen, constbuf);
+
+ if (new_consts)
+ nv40_fragprog_upload(nv40, fp);
+ }
+
+ if (new_consts || fp->so != nv40->state.hw[NV40_STATE_FRAGPROG]) {
+ so_ref(fp->so, &nv40->state.hw[NV40_STATE_FRAGPROG]);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+nv40_fragprog_destroy(struct nv40_context *nv40,
+ struct nv40_fragment_program *fp)
+{
+ if (fp->insn_len)
+ FREE(fp->insn);
+}
+
+struct nv40_state_entry nv40_state_fragprog = {
+ .validate = nv40_fragprog_validate,
+ .dirty = {
+ .pipe = NV40_NEW_FRAGPROG,
+ .hw = NV40_STATE_FRAGPROG
+ }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_fragtex.c b/src/gallium/drivers/nv40/nv40_fragtex.c
new file mode 100644
index 0000000000..f6cdf31dfe
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_fragtex.c
@@ -0,0 +1,170 @@
+#include "nv40_context.h"
+
+#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw) \
+{ \
+ TRUE, \
+ PIPE_FORMAT_##m, \
+ NV40TCL_TEX_FORMAT_FORMAT_##tf, \
+ (NV40TCL_TEX_SWIZZLE_S0_X_##ts0x | NV40TCL_TEX_SWIZZLE_S0_Y_##ts0y | \
+ NV40TCL_TEX_SWIZZLE_S0_Z_##ts0z | NV40TCL_TEX_SWIZZLE_S0_W_##ts0w | \
+ NV40TCL_TEX_SWIZZLE_S1_X_##ts1x | NV40TCL_TEX_SWIZZLE_S1_Y_##ts1y | \
+ NV40TCL_TEX_SWIZZLE_S1_Z_##ts1z | NV40TCL_TEX_SWIZZLE_S1_W_##ts1w), \
+ ((NV40TCL_TEX_FILTER_SIGNED_RED*sx) | (NV40TCL_TEX_FILTER_SIGNED_GREEN*sy) | \
+ (NV40TCL_TEX_FILTER_SIGNED_BLUE*sz) | (NV40TCL_TEX_FILTER_SIGNED_ALPHA*sw)) \
+}
+
+struct nv40_texture_format {
+ boolean defined;
+ uint pipe;
+ int format;
+ int swizzle;
+ int sign;
+};
+
+static struct nv40_texture_format
+nv40_texture_formats[] = {
+ _(A8R8G8B8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(A1R5G5B5_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(A4R4G4B4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(R5G6B5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
+ _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
+ _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X, 0, 0, 0, 0),
+ _(R16_SNORM , A16 , ZERO, ZERO, S1, ONE, X, X, X, Y, 1, 1, 1, 1),
+ _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X, 0, 0, 0, 0),
+ _(A8L8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y, 0, 0, 0, 0),
+ _(Z16_UNORM , Z16 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
+ _(Z24S8_UNORM , Z24 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
+ _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
+ _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ {},
+};
+
+static struct nv40_texture_format *
+nv40_fragtex_format(uint pipe_format)
+{
+ struct nv40_texture_format *tf = nv40_texture_formats;
+
+ while (tf->defined) {
+ if (tf->pipe == pipe_format)
+ return tf;
+ tf++;
+ }
+
+ NOUVEAU_ERR("unknown texture format %s\n", pf_name(pipe_format));
+ return NULL;
+}
+
+
+static struct nouveau_stateobj *
+nv40_fragtex_build(struct nv40_context *nv40, int unit)
+{
+ struct nv40_sampler_state *ps = nv40->tex_sampler[unit];
+ struct nv40_miptree *nv40mt = nv40->tex_miptree[unit];
+ struct nouveau_bo *bo = nouveau_bo(nv40mt->buffer);
+ struct pipe_texture *pt = &nv40mt->base;
+ struct nv40_texture_format *tf;
+ struct nouveau_stateobj *so;
+ uint32_t txf, txs, txp;
+ unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+
+ tf = nv40_fragtex_format(pt->format);
+ if (!tf)
+ assert(0);
+
+ txf = ps->fmt;
+ txf |= tf->format | 0x8000;
+ txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
+
+ if (1) /* XXX */
+ txf |= NV40TCL_TEX_FORMAT_NO_BORDER;
+
+ switch (pt->target) {
+ case PIPE_TEXTURE_CUBE:
+ txf |= NV40TCL_TEX_FORMAT_CUBIC;
+ /* fall-through */
+ case PIPE_TEXTURE_2D:
+ txf |= NV40TCL_TEX_FORMAT_DIMS_2D;
+ break;
+ case PIPE_TEXTURE_3D:
+ txf |= NV40TCL_TEX_FORMAT_DIMS_3D;
+ break;
+ case PIPE_TEXTURE_1D:
+ txf |= NV40TCL_TEX_FORMAT_DIMS_1D;
+ break;
+ default:
+ NOUVEAU_ERR("Unknown target %d\n", pt->target);
+ return NULL;
+ }
+
+ if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+ txp = 0;
+ } else {
+ txp = nv40mt->level[0].pitch;
+ txf |= NV40TCL_TEX_FORMAT_LINEAR;
+ }
+
+ txs = tf->swizzle;
+
+ so = so_new(16, 2);
+ so_method(so, nv40->screen->curie, NV40TCL_TEX_OFFSET(unit), 8);
+ so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
+ so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR,
+ NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1);
+ so_data (so, ps->wrap);
+ so_data (so, NV40TCL_TEX_ENABLE_ENABLE | ps->en);
+ so_data (so, txs);
+ so_data (so, ps->filt | tf->sign | 0x2000 /*voodoo*/);
+ so_data (so, (pt->width[0] << NV40TCL_TEX_SIZE0_W_SHIFT) |
+ pt->height[0]);
+ so_data (so, ps->bcol);
+ so_method(so, nv40->screen->curie, NV40TCL_TEX_SIZE1(unit), 1);
+ so_data (so, (pt->depth[0] << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp);
+
+ return so;
+}
+
+static boolean
+nv40_fragtex_validate(struct nv40_context *nv40)
+{
+ struct nv40_fragment_program *fp = nv40->fragprog;
+ struct nv40_state *state = &nv40->state;
+ struct nouveau_stateobj *so;
+ unsigned samplers, unit;
+
+ samplers = state->fp_samplers & ~fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ so = so_new(2, 0);
+ so_method(so, nv40->screen->curie, NV40TCL_TEX_ENABLE(unit), 1);
+ so_data (so, 0);
+ so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
+ state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
+ }
+
+ samplers = nv40->dirty_samplers & fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ so = nv40_fragtex_build(nv40, unit);
+ so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
+ so_ref(NULL, &so);
+ state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
+ }
+
+ nv40->state.fp_samplers = fp->samplers;
+ return FALSE;
+}
+
+struct nv40_state_entry nv40_state_fragtex = {
+ .validate = nv40_fragtex_validate,
+ .dirty = {
+ .pipe = NV40_NEW_SAMPLER | NV40_NEW_FRAGPROG,
+ .hw = 0
+ }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nv40/nv40_miptree.c
new file mode 100644
index 0000000000..5a201ccf45
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_miptree.c
@@ -0,0 +1,213 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "nv40_context.h"
+
+static void
+nv40_miptree_layout(struct nv40_miptree *mt)
+{
+ struct pipe_texture *pt = &mt->base;
+ uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
+ uint offset = 0;
+ int nr_faces, l, f;
+ uint wide_pitch = pt->tex_usage & (PIPE_TEXTURE_USAGE_SAMPLER |
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL |
+ PIPE_TEXTURE_USAGE_RENDER_TARGET |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_PRIMARY);
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ nr_faces = 6;
+ } else
+ if (pt->target == PIPE_TEXTURE_3D) {
+ nr_faces = pt->depth[0];
+ } else {
+ nr_faces = 1;
+ }
+
+ for (l = 0; l <= pt->last_level; l++) {
+ pt->width[l] = width;
+ pt->height[l] = height;
+ pt->depth[l] = depth;
+ pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+ pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+
+ if (wide_pitch && (pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR))
+ mt->level[l].pitch = align(pt->width[0] * pt->block.size, 64);
+ else
+ mt->level[l].pitch = pt->width[l] * pt->block.size;
+
+ mt->level[l].image_offset =
+ CALLOC(nr_faces, sizeof(unsigned));
+
+ width = MAX2(1, width >> 1);
+ height = MAX2(1, height >> 1);
+ depth = MAX2(1, depth >> 1);
+ }
+
+ for (f = 0; f < nr_faces; f++) {
+ for (l = 0; l < pt->last_level; l++) {
+ mt->level[l].image_offset[f] = offset;
+
+ if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) &&
+ pt->width[l + 1] > 1 && pt->height[l + 1] > 1)
+ offset += align(mt->level[l].pitch * pt->height[l], 64);
+ else
+ offset += mt->level[l].pitch * pt->height[l];
+ }
+
+ mt->level[l].image_offset[f] = offset;
+ offset += mt->level[l].pitch * pt->height[l];
+ }
+
+ mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
+{
+ struct nv40_miptree *mt;
+ unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL |
+ NOUVEAU_BUFFER_USAGE_TEXTURE;
+
+ mt = MALLOC(sizeof(struct nv40_miptree));
+ if (!mt)
+ return NULL;
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = pscreen;
+
+ /* Swizzled textures must be POT */
+ if (pt->width[0] & (pt->width[0] - 1) ||
+ pt->height[0] & (pt->height[0] - 1))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else
+ if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else
+ if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC)
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else {
+ switch (pt->format) {
+ /* TODO: Figure out which formats can be swizzled */
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_R16_SNORM:
+ {
+ if (debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ break;
+ }
+ default:
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ }
+ }
+
+ if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC)
+ buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+
+ nv40_miptree_layout(mt);
+
+ mt->buffer = pscreen->buffer_create(pscreen, 256, buf_usage, mt->total_size);
+ if (!mt->buffer) {
+ FREE(mt);
+ return NULL;
+ }
+
+ return &mt->base;
+}
+
+static struct pipe_texture *
+nv40_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt,
+ const unsigned *stride, struct pipe_buffer *pb)
+{
+ struct nv40_miptree *mt;
+
+ /* Only supports 2D, non-mipmapped textures for the moment */
+ if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 ||
+ pt->depth[0] != 1)
+ return NULL;
+
+ mt = CALLOC_STRUCT(nv40_miptree);
+ if (!mt)
+ return NULL;
+
+ mt->base = *pt;
+ pipe_reference_init(&mt->base.reference, 1);
+ mt->base.screen = pscreen;
+ mt->level[0].pitch = stride[0];
+ mt->level[0].image_offset = CALLOC(1, sizeof(unsigned));
+
+ pipe_buffer_reference(&mt->buffer, pb);
+ return &mt->base;
+}
+
+static void
+nv40_miptree_destroy(struct pipe_texture *pt)
+{
+ struct nv40_miptree *mt = (struct nv40_miptree *)pt;
+ int l;
+
+ pipe_buffer_reference(&mt->buffer, NULL);
+ for (l = 0; l <= pt->last_level; l++) {
+ if (mt->level[l].image_offset)
+ FREE(mt->level[l].image_offset);
+ }
+
+ FREE(mt);
+}
+
+static struct pipe_surface *
+nv40_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned flags)
+{
+ struct nv40_miptree *mt = (struct nv40_miptree *)pt;
+ struct nv04_surface *ns;
+
+ ns = CALLOC_STRUCT(nv04_surface);
+ if (!ns)
+ return NULL;
+ pipe_texture_reference(&ns->base.texture, pt);
+ ns->base.format = pt->format;
+ ns->base.width = pt->width[level];
+ ns->base.height = pt->height[level];
+ ns->base.usage = flags;
+ pipe_reference_init(&ns->base.reference, 1);
+ ns->base.face = face;
+ ns->base.level = level;
+ ns->base.zslice = zslice;
+ ns->pitch = mt->level[level].pitch;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ns->base.offset = mt->level[level].image_offset[face];
+ } else
+ if (pt->target == PIPE_TEXTURE_3D) {
+ ns->base.offset = mt->level[level].image_offset[zslice];
+ } else {
+ ns->base.offset = mt->level[level].image_offset[0];
+ }
+
+ return &ns->base;
+}
+
+static void
+nv40_miptree_surface_del(struct pipe_surface *ps)
+{
+ pipe_texture_reference(&ps->texture, NULL);
+ FREE(ps);
+}
+
+void
+nv40_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+ pscreen->texture_create = nv40_miptree_create;
+ pscreen->texture_blanket = nv40_miptree_blanket;
+ pscreen->texture_destroy = nv40_miptree_destroy;
+ pscreen->get_tex_surface = nv40_miptree_surface_new;
+ pscreen->tex_surface_destroy = nv40_miptree_surface_del;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_query.c b/src/gallium/drivers/nv40/nv40_query.c
new file mode 100644
index 0000000000..7874aedd42
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_query.c
@@ -0,0 +1,121 @@
+#include "pipe/p_context.h"
+
+#include "nv40_context.h"
+
+struct nv40_query {
+ struct nouveau_resource *object;
+ unsigned type;
+ boolean ready;
+ uint64_t result;
+};
+
+static INLINE struct nv40_query *
+nv40_query(struct pipe_query *pipe)
+{
+ return (struct nv40_query *)pipe;
+}
+
+static struct pipe_query *
+nv40_query_create(struct pipe_context *pipe, unsigned query_type)
+{
+ struct nv40_query *q;
+
+ q = CALLOC(1, sizeof(struct nv40_query));
+ q->type = query_type;
+
+ return (struct pipe_query *)q;
+}
+
+static void
+nv40_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv40_query *q = nv40_query(pq);
+
+ if (q->object)
+ nouveau_resource_free(&q->object);
+ FREE(q);
+}
+
+static void
+nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_query *q = nv40_query(pq);
+
+ assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+
+ /* Happens when end_query() is called, then another begin_query()
+ * without querying the result in-between. For now we'll wait for
+ * the existing query to notify completion, but it could be better.
+ */
+ if (q->object) {
+ uint64_t tmp;
+ pipe->get_query_result(pipe, pq, 1, &tmp);
+ }
+
+ if (nouveau_resource_alloc(nv40->screen->query_heap, 1, NULL, &q->object))
+ assert(0);
+ nouveau_notifier_reset(nv40->screen->query, q->object->start);
+
+ BEGIN_RING(curie, NV40TCL_QUERY_RESET, 1);
+ OUT_RING (1);
+ BEGIN_RING(curie, NV40TCL_QUERY_UNK17CC, 1);
+ OUT_RING (1);
+
+ q->ready = FALSE;
+}
+
+static void
+nv40_query_end(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_query *q = nv40_query(pq);
+
+ BEGIN_RING(curie, NV40TCL_QUERY_GET, 1);
+ OUT_RING ((0x01 << NV40TCL_QUERY_GET_UNK24_SHIFT) |
+ ((q->object->start * 32) << NV40TCL_QUERY_GET_OFFSET_SHIFT));
+ FIRE_RING(NULL);
+}
+
+static boolean
+nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq,
+ boolean wait, uint64_t *result)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_query *q = nv40_query(pq);
+
+ assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+
+ if (!q->ready) {
+ unsigned status;
+
+ status = nouveau_notifier_status(nv40->screen->query,
+ q->object->start);
+ if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) {
+ if (wait == FALSE)
+ return FALSE;
+ nouveau_notifier_wait_status(nv40->screen->query,
+ q->object->start,
+ NV_NOTIFY_STATE_STATUS_COMPLETED,
+ 0);
+ }
+
+ q->result = nouveau_notifier_return_val(nv40->screen->query,
+ q->object->start);
+ q->ready = TRUE;
+ nouveau_resource_free(&q->object);
+ }
+
+ *result = q->result;
+ return TRUE;
+}
+
+void
+nv40_init_query_functions(struct nv40_context *nv40)
+{
+ nv40->pipe.create_query = nv40_query_create;
+ nv40->pipe.destroy_query = nv40_query_destroy;
+ nv40->pipe.begin_query = nv40_query_begin;
+ nv40->pipe.end_query = nv40_query_end;
+ nv40->pipe.get_query_result = nv40_query_result;
+}
diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c
new file mode 100644
index 0000000000..5d2a4216c5
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_screen.c
@@ -0,0 +1,303 @@
+#include "pipe/p_screen.h"
+
+#include "nv40_context.h"
+#include "nv40_screen.h"
+
+#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf
+#define NV4X_GRCLASS4497_CHIPSETS 0x00005450
+#define NV6X_GRCLASS4497_CHIPSETS 0x00000088
+
+static int
+nv40_screen_get_param(struct pipe_screen *pscreen, int param)
+{
+ struct nv40_screen *screen = nv40_screen(pscreen);
+
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return 16;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 1;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 1;
+ case PIPE_CAP_GLSL:
+ return 0;
+ case PIPE_CAP_S3TC:
+ return 1;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 1;
+ case PIPE_CAP_POINT_SPRITE:
+ return 1;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 4;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 1;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 1;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 13;
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 10;
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 13;
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ return 0; /* We have 4 - but unsupported currently */
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ return 0;
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 1;
+ case NOUVEAU_CAP_HW_VTXBUF:
+ return 1;
+ case NOUVEAU_CAP_HW_IDXBUF:
+ if (screen->curie->grclass == NV40TCL)
+ return 1;
+ return 0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0;
+ }
+}
+
+static float
+nv40_screen_get_paramf(struct pipe_screen *pscreen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 10.0;
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 64.0;
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 16.0;
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 16.0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0.0;
+ }
+}
+
+static boolean
+nv40_screen_surface_format_supported(struct pipe_screen *pscreen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else
+ if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) {
+ switch (format) {
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_R16_SNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_A8L8_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT5_RGBA:
+ return TRUE;
+ default:
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static struct pipe_buffer *
+nv40_surface_buffer(struct pipe_surface *surf)
+{
+ struct nv40_miptree *mt = (struct nv40_miptree *)surf->texture;
+
+ return mt->buffer;
+}
+
+static void
+nv40_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct nv40_screen *screen = nv40_screen(pscreen);
+
+ nouveau_resource_free(&screen->vp_exec_heap);
+ nouveau_resource_free(&screen->vp_data_heap);
+ nouveau_resource_free(&screen->query_heap);
+ nouveau_notifier_free(&screen->query);
+ nouveau_notifier_free(&screen->sync);
+ nouveau_grobj_free(&screen->curie);
+
+ nouveau_screen_fini(&screen->base);
+
+ FREE(pscreen);
+}
+
+struct pipe_screen *
+nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
+{
+ struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen);
+ struct nouveau_channel *chan;
+ struct pipe_screen *pscreen;
+ struct nouveau_stateobj *so;
+ unsigned curie_class = 0;
+ int ret;
+
+ if (!screen)
+ return NULL;
+ pscreen = &screen->base.base;
+
+ ret = nouveau_screen_init(&screen->base, dev);
+ if (ret) {
+ nv40_screen_destroy(pscreen);
+ return NULL;
+ }
+ chan = screen->base.channel;
+
+ pscreen->winsys = ws;
+ pscreen->destroy = nv40_screen_destroy;
+ pscreen->get_param = nv40_screen_get_param;
+ pscreen->get_paramf = nv40_screen_get_paramf;
+ pscreen->is_format_supported = nv40_screen_surface_format_supported;
+
+ nv40_screen_init_miptree_functions(pscreen);
+ nv40_screen_init_transfer_functions(pscreen);
+
+ /* 3D object */
+ switch (dev->chipset & 0xf0) {
+ case 0x40:
+ if (NV4X_GRCLASS4097_CHIPSETS & (1 << (dev->chipset & 0x0f)))
+ curie_class = NV40TCL;
+ else
+ if (NV4X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f)))
+ curie_class = NV44TCL;
+ break;
+ case 0x60:
+ if (NV6X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f)))
+ curie_class = NV44TCL;
+ break;
+ }
+
+ if (!curie_class) {
+ NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", dev->chipset);
+ return NULL;
+ }
+
+ ret = nouveau_grobj_alloc(chan, 0xbeef3097, curie_class, &screen->curie);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+ return FALSE;
+ }
+ BIND_RING(chan, screen->curie, 7);
+
+ /* 2D engine setup */
+ screen->eng2d = nv04_surface_2d_init(&screen->base);
+ screen->eng2d->buf = nv40_surface_buffer;
+
+ /* Notifier for sync purposes */
+ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
+ if (ret) {
+ NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+ nv40_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ /* Query objects */
+ ret = nouveau_notifier_alloc(chan, 0xbeef0302, 32, &screen->query);
+ if (ret) {
+ NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
+ nv40_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ nouveau_resource_init(&screen->query_heap, 0, 32);
+ if (ret) {
+ NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
+ nv40_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ /* Vtxprog resources */
+ if (nouveau_resource_init(&screen->vp_exec_heap, 0, 512) ||
+ nouveau_resource_init(&screen->vp_data_heap, 0, 256)) {
+ nv40_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ /* Static curie initialisation */
+ so = so_new(128, 0);
+ so_method(so, screen->curie, NV40TCL_DMA_NOTIFY, 1);
+ so_data (so, screen->sync->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_TEXTURE0, 2);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->gart->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_COLOR1, 1);
+ so_data (so, chan->vram->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_COLOR0, 2);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->vram->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_VTXBUF0, 2);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->gart->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_FENCE, 2);
+ so_data (so, 0);
+ so_data (so, screen->query->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_UNK01AC, 2);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->vram->handle);
+ so_method(so, screen->curie, NV40TCL_DMA_COLOR2, 2);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->vram->handle);
+
+ so_method(so, screen->curie, 0x1ea4, 3);
+ so_data (so, 0x00000010);
+ so_data (so, 0x01000100);
+ so_data (so, 0xff800006);
+
+ /* vtxprog output routing */
+ so_method(so, screen->curie, 0x1fc4, 1);
+ so_data (so, 0x06144321);
+ so_method(so, screen->curie, 0x1fc8, 2);
+ so_data (so, 0xedcba987);
+ so_data (so, 0x00000021);
+ so_method(so, screen->curie, 0x1fd0, 1);
+ so_data (so, 0x00171615);
+ so_method(so, screen->curie, 0x1fd4, 1);
+ so_data (so, 0x001b1a19);
+
+ so_method(so, screen->curie, 0x1ef8, 1);
+ so_data (so, 0x0020ffff);
+ so_method(so, screen->curie, 0x1d64, 1);
+ so_data (so, 0x00d30000);
+ so_method(so, screen->curie, 0x1e94, 1);
+ so_data (so, 0x00000001);
+
+ so_emit(chan, so);
+ so_ref(NULL, &so);
+ nouveau_pushbuf_flush(chan, 0);
+
+ return pscreen;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h
new file mode 100644
index 0000000000..57b4c8fc46
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_screen.h
@@ -0,0 +1,40 @@
+#ifndef __NV40_SCREEN_H__
+#define __NV40_SCREEN_H__
+
+#include "nouveau/nouveau_screen.h"
+#include "nv04/nv04_surface_2d.h"
+
+struct nv40_screen {
+ struct nouveau_screen base;
+
+ struct nouveau_winsys *nvws;
+
+ unsigned cur_pctx;
+
+ /* HW graphics objects */
+ struct nv04_surface_2d *eng2d;
+ struct nouveau_grobj *curie;
+ struct nouveau_notifier *sync;
+
+ /* Query object resources */
+ struct nouveau_notifier *query;
+ struct nouveau_resource *query_heap;
+
+ /* Vtxprog resources */
+ struct nouveau_resource *vp_exec_heap;
+ struct nouveau_resource *vp_data_heap;
+
+ /* Current 3D state of channel */
+ struct nouveau_stateobj *state[NV40_STATE_MAX];
+};
+
+static INLINE struct nv40_screen *
+nv40_screen(struct pipe_screen *screen)
+{
+ return (struct nv40_screen *)screen;
+}
+
+void
+nv40_screen_init_transfer_functions(struct pipe_screen *pscreen);
+
+#endif
diff --git a/src/gallium/drivers/nv40/nv40_shader.h b/src/gallium/drivers/nv40/nv40_shader.h
new file mode 100644
index 0000000000..854dccf548
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_shader.h
@@ -0,0 +1,556 @@
+#ifndef __NV40_SHADER_H__
+#define __NV40_SHADER_H__
+
+/* Vertex programs instruction set
+ *
+ * The NV40 instruction set is very similar to NV30. Most fields are in
+ * a slightly different position in the instruction however.
+ *
+ * Merged instructions
+ * In some cases it is possible to put two instructions into one opcode
+ * slot. The rules for when this is OK is not entirely clear to me yet.
+ *
+ * There are separate writemasks and dest temp register fields for each
+ * grouping of instructions. There is however only one field with the
+ * ID of a result register. Writing to temp/result regs is selected by
+ * setting VEC_RESULT/SCA_RESULT.
+ *
+ * Temporary registers
+ * The source/dest temp register fields have been extended by 1 bit, to
+ * give a total of 32 temporary registers.
+ *
+ * Relative Addressing
+ * NV40 can use an address register to index into vertex attribute regs.
+ * This is done by putting the offset value into INPUT_SRC and setting
+ * the INDEX_INPUT flag.
+ *
+ * Conditional execution (see NV_vertex_program{2,3} for details)
+ * There is a second condition code register on NV40, it's use is enabled
+ * by setting the COND_REG_SELECT_1 flag.
+ *
+ * Texture lookup
+ * TODO
+ */
+
+/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */
+#define NV40_VP_INST_VEC_RESULT (1 << 30)
+/* uncertain.. */
+#define NV40_VP_INST_COND_UPDATE_ENABLE ((1 << 14)|1<<29)
+/* use address reg as index into attribs */
+#define NV40_VP_INST_INDEX_INPUT (1 << 27)
+#define NV40_VP_INST_COND_REG_SELECT_1 (1 << 25)
+#define NV40_VP_INST_ADDR_REG_SELECT_1 (1 << 24)
+#define NV40_VP_INST_SRC2_ABS (1 << 23)
+#define NV40_VP_INST_SRC1_ABS (1 << 22)
+#define NV40_VP_INST_SRC0_ABS (1 << 21)
+#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT 15
+#define NV40_VP_INST_VEC_DEST_TEMP_MASK (0x1F << 15)
+#define NV40_VP_INST_COND_TEST_ENABLE (1 << 13)
+#define NV40_VP_INST_COND_SHIFT 10
+#define NV40_VP_INST_COND_MASK (0x7 << 10)
+# define NV40_VP_INST_COND_FL 0
+# define NV40_VP_INST_COND_LT 1
+# define NV40_VP_INST_COND_EQ 2
+# define NV40_VP_INST_COND_LE 3
+# define NV40_VP_INST_COND_GT 4
+# define NV40_VP_INST_COND_NE 5
+# define NV40_VP_INST_COND_GE 6
+# define NV40_VP_INST_COND_TR 7
+#define NV40_VP_INST_COND_SWZ_X_SHIFT 8
+#define NV40_VP_INST_COND_SWZ_X_MASK (3 << 8)
+#define NV40_VP_INST_COND_SWZ_Y_SHIFT 6
+#define NV40_VP_INST_COND_SWZ_Y_MASK (3 << 6)
+#define NV40_VP_INST_COND_SWZ_Z_SHIFT 4
+#define NV40_VP_INST_COND_SWZ_Z_MASK (3 << 4)
+#define NV40_VP_INST_COND_SWZ_W_SHIFT 2
+#define NV40_VP_INST_COND_SWZ_W_MASK (3 << 2)
+#define NV40_VP_INST_COND_SWZ_ALL_SHIFT 2
+#define NV40_VP_INST_COND_SWZ_ALL_MASK (0xFF << 2)
+#define NV40_VP_INST_ADDR_SWZ_SHIFT 0
+#define NV40_VP_INST_ADDR_SWZ_MASK (0x03 << 0)
+#define NV40_VP_INST0_KNOWN ( \
+ NV40_VP_INST_INDEX_INPUT | \
+ NV40_VP_INST_COND_REG_SELECT_1 | \
+ NV40_VP_INST_ADDR_REG_SELECT_1 | \
+ NV40_VP_INST_SRC2_ABS | \
+ NV40_VP_INST_SRC1_ABS | \
+ NV40_VP_INST_SRC0_ABS | \
+ NV40_VP_INST_VEC_DEST_TEMP_MASK | \
+ NV40_VP_INST_COND_TEST_ENABLE | \
+ NV40_VP_INST_COND_MASK | \
+ NV40_VP_INST_COND_SWZ_ALL_MASK | \
+ NV40_VP_INST_ADDR_SWZ_MASK)
+
+/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */
+#define NV40_VP_INST_VEC_OPCODE_SHIFT 22
+#define NV40_VP_INST_VEC_OPCODE_MASK (0x1F << 22)
+# define NV40_VP_INST_OP_NOP 0x00
+# define NV40_VP_INST_OP_MOV 0x01
+# define NV40_VP_INST_OP_MUL 0x02
+# define NV40_VP_INST_OP_ADD 0x03
+# define NV40_VP_INST_OP_MAD 0x04
+# define NV40_VP_INST_OP_DP3 0x05
+# define NV40_VP_INST_OP_DPH 0x06
+# define NV40_VP_INST_OP_DP4 0x07
+# define NV40_VP_INST_OP_DST 0x08
+# define NV40_VP_INST_OP_MIN 0x09
+# define NV40_VP_INST_OP_MAX 0x0A
+# define NV40_VP_INST_OP_SLT 0x0B
+# define NV40_VP_INST_OP_SGE 0x0C
+# define NV40_VP_INST_OP_ARL 0x0D
+# define NV40_VP_INST_OP_FRC 0x0E
+# define NV40_VP_INST_OP_FLR 0x0F
+# define NV40_VP_INST_OP_SEQ 0x10
+# define NV40_VP_INST_OP_SFL 0x11
+# define NV40_VP_INST_OP_SGT 0x12
+# define NV40_VP_INST_OP_SLE 0x13
+# define NV40_VP_INST_OP_SNE 0x14
+# define NV40_VP_INST_OP_STR 0x15
+# define NV40_VP_INST_OP_SSG 0x16
+# define NV40_VP_INST_OP_ARR 0x17
+# define NV40_VP_INST_OP_ARA 0x18
+# define NV40_VP_INST_OP_TXL 0x19
+#define NV40_VP_INST_SCA_OPCODE_SHIFT 27
+#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27)
+# define NV40_VP_INST_OP_NOP 0x00
+# define NV40_VP_INST_OP_MOV 0x01
+# define NV40_VP_INST_OP_RCP 0x02
+# define NV40_VP_INST_OP_RCC 0x03
+# define NV40_VP_INST_OP_RSQ 0x04
+# define NV40_VP_INST_OP_EXP 0x05
+# define NV40_VP_INST_OP_LOG 0x06
+# define NV40_VP_INST_OP_LIT 0x07
+# define NV40_VP_INST_OP_BRA 0x09
+# define NV40_VP_INST_OP_CAL 0x0B
+# define NV40_VP_INST_OP_RET 0x0C
+# define NV40_VP_INST_OP_LG2 0x0D
+# define NV40_VP_INST_OP_EX2 0x0E
+# define NV40_VP_INST_OP_SIN 0x0F
+# define NV40_VP_INST_OP_COS 0x10
+# define NV40_VP_INST_OP_PUSHA 0x13
+# define NV40_VP_INST_OP_POPA 0x14
+#define NV40_VP_INST_CONST_SRC_SHIFT 12
+#define NV40_VP_INST_CONST_SRC_MASK (0xFF << 12)
+#define NV40_VP_INST_INPUT_SRC_SHIFT 8
+#define NV40_VP_INST_INPUT_SRC_MASK (0x0F << 8)
+# define NV40_VP_INST_IN_POS 0
+# define NV40_VP_INST_IN_WEIGHT 1
+# define NV40_VP_INST_IN_NORMAL 2
+# define NV40_VP_INST_IN_COL0 3
+# define NV40_VP_INST_IN_COL1 4
+# define NV40_VP_INST_IN_FOGC 5
+# define NV40_VP_INST_IN_TC0 8
+# define NV40_VP_INST_IN_TC(n) (8+n)
+#define NV40_VP_INST_SRC0H_SHIFT 0
+#define NV40_VP_INST_SRC0H_MASK (0xFF << 0)
+#define NV40_VP_INST1_KNOWN ( \
+ NV40_VP_INST_VEC_OPCODE_MASK | \
+ NV40_VP_INST_SCA_OPCODE_MASK | \
+ NV40_VP_INST_CONST_SRC_MASK | \
+ NV40_VP_INST_INPUT_SRC_MASK | \
+ NV40_VP_INST_SRC0H_MASK \
+ )
+
+/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */
+#define NV40_VP_INST_SRC0L_SHIFT 23
+#define NV40_VP_INST_SRC0L_MASK (0x1FF << 23)
+#define NV40_VP_INST_SRC1_SHIFT 6
+#define NV40_VP_INST_SRC1_MASK (0x1FFFF << 6)
+#define NV40_VP_INST_SRC2H_SHIFT 0
+#define NV40_VP_INST_SRC2H_MASK (0x3F << 0)
+#define NV40_VP_INST_IADDRH_SHIFT 0
+#define NV40_VP_INST_IADDRH_MASK (0x1F << 0)
+
+/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */
+#define NV40_VP_INST_IADDRL_SHIFT 29
+#define NV40_VP_INST_IADDRL_MASK (7 << 29)
+#define NV40_VP_INST_SRC2L_SHIFT 21
+#define NV40_VP_INST_SRC2L_MASK (0x7FF << 21)
+#define NV40_VP_INST_SCA_WRITEMASK_SHIFT 17
+#define NV40_VP_INST_SCA_WRITEMASK_MASK (0xF << 17)
+# define NV40_VP_INST_SCA_WRITEMASK_X (1 << 20)
+# define NV40_VP_INST_SCA_WRITEMASK_Y (1 << 19)
+# define NV40_VP_INST_SCA_WRITEMASK_Z (1 << 18)
+# define NV40_VP_INST_SCA_WRITEMASK_W (1 << 17)
+#define NV40_VP_INST_VEC_WRITEMASK_SHIFT 13
+#define NV40_VP_INST_VEC_WRITEMASK_MASK (0xF << 13)
+# define NV40_VP_INST_VEC_WRITEMASK_X (1 << 16)
+# define NV40_VP_INST_VEC_WRITEMASK_Y (1 << 15)
+# define NV40_VP_INST_VEC_WRITEMASK_Z (1 << 14)
+# define NV40_VP_INST_VEC_WRITEMASK_W (1 << 13)
+#define NV40_VP_INST_SCA_RESULT (1 << 12)
+#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT 7
+#define NV40_VP_INST_SCA_DEST_TEMP_MASK (0x1F << 7)
+#define NV40_VP_INST_DEST_SHIFT 2
+#define NV40_VP_INST_DEST_MASK (31 << 2)
+# define NV40_VP_INST_DEST_POS 0
+# define NV40_VP_INST_DEST_COL0 1
+# define NV40_VP_INST_DEST_COL1 2
+# define NV40_VP_INST_DEST_BFC0 3
+# define NV40_VP_INST_DEST_BFC1 4
+# define NV40_VP_INST_DEST_FOGC 5
+# define NV40_VP_INST_DEST_PSZ 6
+# define NV40_VP_INST_DEST_TC0 7
+# define NV40_VP_INST_DEST_TC(n) (7+n)
+# define NV40_VP_INST_DEST_TEMP 0x1F
+#define NV40_VP_INST_INDEX_CONST (1 << 1)
+#define NV40_VP_INST_LAST (1 << 0)
+#define NV40_VP_INST3_KNOWN ( \
+ NV40_VP_INST_SRC2L_MASK |\
+ NV40_VP_INST_SCA_WRITEMASK_MASK |\
+ NV40_VP_INST_VEC_WRITEMASK_MASK |\
+ NV40_VP_INST_SCA_DEST_TEMP_MASK |\
+ NV40_VP_INST_DEST_MASK |\
+ NV40_VP_INST_INDEX_CONST)
+
+/* Useful to split the source selection regs into their pieces */
+#define NV40_VP_SRC0_HIGH_SHIFT 9
+#define NV40_VP_SRC0_HIGH_MASK 0x0001FE00
+#define NV40_VP_SRC0_LOW_MASK 0x000001FF
+#define NV40_VP_SRC2_HIGH_SHIFT 11
+#define NV40_VP_SRC2_HIGH_MASK 0x0001F800
+#define NV40_VP_SRC2_LOW_MASK 0x000007FF
+
+/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */
+#define NV40_VP_SRC_NEGATE (1 << 16)
+#define NV40_VP_SRC_SWZ_X_SHIFT 14
+#define NV40_VP_SRC_SWZ_X_MASK (3 << 14)
+#define NV40_VP_SRC_SWZ_Y_SHIFT 12
+#define NV40_VP_SRC_SWZ_Y_MASK (3 << 12)
+#define NV40_VP_SRC_SWZ_Z_SHIFT 10
+#define NV40_VP_SRC_SWZ_Z_MASK (3 << 10)
+#define NV40_VP_SRC_SWZ_W_SHIFT 8
+#define NV40_VP_SRC_SWZ_W_MASK (3 << 8)
+#define NV40_VP_SRC_SWZ_ALL_SHIFT 8
+#define NV40_VP_SRC_SWZ_ALL_MASK (0xFF << 8)
+#define NV40_VP_SRC_TEMP_SRC_SHIFT 2
+#define NV40_VP_SRC_TEMP_SRC_MASK (0x1F << 2)
+#define NV40_VP_SRC_REG_TYPE_SHIFT 0
+#define NV40_VP_SRC_REG_TYPE_MASK (3 << 0)
+# define NV40_VP_SRC_REG_TYPE_UNK0 0
+# define NV40_VP_SRC_REG_TYPE_TEMP 1
+# define NV40_VP_SRC_REG_TYPE_INPUT 2
+# define NV40_VP_SRC_REG_TYPE_CONST 3
+
+
+/*
+ * Each fragment program opcode appears to be comprised of 4 32-bit values.
+ *
+ * 0 - Opcode, output reg/mask, ATTRIB source
+ * 1 - Source 0
+ * 2 - Source 1
+ * 3 - Source 2
+ *
+ * There appears to be no special difference between result regs and temp regs.
+ * result.color == R0.xyzw
+ * result.depth == R1.z
+ * When the fragprog contains instructions to write depth,
+ * NV30_TCL_PRIMITIVE_3D_UNK1D78=0 otherwise it is set to 1.
+ *
+ * Constants are inserted directly after the instruction that uses them.
+ *
+ * It appears that it's not possible to use two input registers in one
+ * instruction as the input sourcing is done in the instruction dword
+ * and not the source selection dwords. As such instructions such as:
+ *
+ * ADD result.color, fragment.color, fragment.texcoord[0];
+ *
+ * must be split into two MOV's and then an ADD (nvidia does this) but
+ * I'm not sure why it's not just one MOV and then source the second input
+ * in the ADD instruction..
+ *
+ * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary
+ * negation requires multiplication with a const.
+ *
+ * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO and
+ * SWIZZLE_ONE.
+ *
+ * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as
+ * SWIZZLE_ZERO is implemented simply by not writing to the relevant components
+ * of the destination.
+ *
+ * Looping
+ * Loops appear to be fairly expensive on NV40 at least, the proprietary
+ * driver goes to a lot of effort to avoid using the native looping
+ * instructions. If the total number of *executed* instructions between
+ * REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop.
+ * The maximum loop count is 255.
+ *
+ * Conditional execution
+ * TODO
+ *
+ * Non-native instructions:
+ * LIT
+ * LRP - MAD+MAD
+ * SUB - ADD, negate second source
+ * RSQ - LG2 + EX2
+ * POW - LG2 + MUL + EX2
+ * SCS - COS + SIN
+ * XPD
+ * DP2 - MUL + ADD
+ * NRM
+ */
+
+//== Opcode / Destination selection ==
+#define NV40_FP_OP_PROGRAM_END (1 << 0)
+#define NV40_FP_OP_OUT_REG_SHIFT 1
+#define NV40_FP_OP_OUT_REG_MASK (63 << 1)
+/* Needs to be set when writing outputs to get expected result.. */
+#define NV40_FP_OP_OUT_REG_HALF (1 << 7)
+#define NV40_FP_OP_COND_WRITE_ENABLE (1 << 8)
+#define NV40_FP_OP_OUTMASK_SHIFT 9
+#define NV40_FP_OP_OUTMASK_MASK (0xF << 9)
+# define NV40_FP_OP_OUT_X (1 << 9)
+# define NV40_FP_OP_OUT_Y (1 <<10)
+# define NV40_FP_OP_OUT_Z (1 <<11)
+# define NV40_FP_OP_OUT_W (1 <<12)
+/* Uncertain about these, especially the input_src values.. it's possible that
+ * they can be dynamically changed.
+ */
+#define NV40_FP_OP_INPUT_SRC_SHIFT 13
+#define NV40_FP_OP_INPUT_SRC_MASK (15 << 13)
+# define NV40_FP_OP_INPUT_SRC_POSITION 0x0
+# define NV40_FP_OP_INPUT_SRC_COL0 0x1
+# define NV40_FP_OP_INPUT_SRC_COL1 0x2
+# define NV40_FP_OP_INPUT_SRC_FOGC 0x3
+# define NV40_FP_OP_INPUT_SRC_TC0 0x4
+# define NV40_FP_OP_INPUT_SRC_TC(n) (0x4 + n)
+# define NV40_FP_OP_INPUT_SRC_FACING 0xE
+#define NV40_FP_OP_TEX_UNIT_SHIFT 17
+#define NV40_FP_OP_TEX_UNIT_MASK (0xF << 17)
+#define NV40_FP_OP_PRECISION_SHIFT 22
+#define NV40_FP_OP_PRECISION_MASK (3 << 22)
+# define NV40_FP_PRECISION_FP32 0
+# define NV40_FP_PRECISION_FP16 1
+# define NV40_FP_PRECISION_FX12 2
+#define NV40_FP_OP_OPCODE_SHIFT 24
+#define NV40_FP_OP_OPCODE_MASK (0x3F << 24)
+# define NV40_FP_OP_OPCODE_NOP 0x00
+# define NV40_FP_OP_OPCODE_MOV 0x01
+# define NV40_FP_OP_OPCODE_MUL 0x02
+# define NV40_FP_OP_OPCODE_ADD 0x03
+# define NV40_FP_OP_OPCODE_MAD 0x04
+# define NV40_FP_OP_OPCODE_DP3 0x05
+# define NV40_FP_OP_OPCODE_DP4 0x06
+# define NV40_FP_OP_OPCODE_DST 0x07
+# define NV40_FP_OP_OPCODE_MIN 0x08
+# define NV40_FP_OP_OPCODE_MAX 0x09
+# define NV40_FP_OP_OPCODE_SLT 0x0A
+# define NV40_FP_OP_OPCODE_SGE 0x0B
+# define NV40_FP_OP_OPCODE_SLE 0x0C
+# define NV40_FP_OP_OPCODE_SGT 0x0D
+# define NV40_FP_OP_OPCODE_SNE 0x0E
+# define NV40_FP_OP_OPCODE_SEQ 0x0F
+# define NV40_FP_OP_OPCODE_FRC 0x10
+# define NV40_FP_OP_OPCODE_FLR 0x11
+# define NV40_FP_OP_OPCODE_KIL 0x12
+# define NV40_FP_OP_OPCODE_PK4B 0x13
+# define NV40_FP_OP_OPCODE_UP4B 0x14
+/* DDX/DDY can only write to XY */
+# define NV40_FP_OP_OPCODE_DDX 0x15
+# define NV40_FP_OP_OPCODE_DDY 0x16
+# define NV40_FP_OP_OPCODE_TEX 0x17
+# define NV40_FP_OP_OPCODE_TXP 0x18
+# define NV40_FP_OP_OPCODE_TXD 0x19
+# define NV40_FP_OP_OPCODE_RCP 0x1A
+# define NV40_FP_OP_OPCODE_EX2 0x1C
+# define NV40_FP_OP_OPCODE_LG2 0x1D
+# define NV40_FP_OP_OPCODE_STR 0x20
+# define NV40_FP_OP_OPCODE_SFL 0x21
+# define NV40_FP_OP_OPCODE_COS 0x22
+# define NV40_FP_OP_OPCODE_SIN 0x23
+# define NV40_FP_OP_OPCODE_PK2H 0x24
+# define NV40_FP_OP_OPCODE_UP2H 0x25
+# define NV40_FP_OP_OPCODE_PK4UB 0x27
+# define NV40_FP_OP_OPCODE_UP4UB 0x28
+# define NV40_FP_OP_OPCODE_PK2US 0x29
+# define NV40_FP_OP_OPCODE_UP2US 0x2A
+# define NV40_FP_OP_OPCODE_DP2A 0x2E
+# define NV40_FP_OP_OPCODE_TXL 0x2F
+# define NV40_FP_OP_OPCODE_TXB 0x31
+# define NV40_FP_OP_OPCODE_DIV 0x3A
+# define NV40_FP_OP_OPCODE_UNK_LIT 0x3C
+/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/
+# define NV40_FP_OP_BRA_OPCODE_BRK 0x0
+# define NV40_FP_OP_BRA_OPCODE_CAL 0x1
+# define NV40_FP_OP_BRA_OPCODE_IF 0x2
+# define NV40_FP_OP_BRA_OPCODE_LOOP 0x3
+# define NV40_FP_OP_BRA_OPCODE_REP 0x4
+# define NV40_FP_OP_BRA_OPCODE_RET 0x5
+#define NV40_FP_OP_OUT_SAT (1 << 31)
+
+/* high order bits of SRC0 */
+#define NV40_FP_OP_OUT_ABS (1 << 29)
+#define NV40_FP_OP_COND_SWZ_W_SHIFT 27
+#define NV40_FP_OP_COND_SWZ_W_MASK (3 << 27)
+#define NV40_FP_OP_COND_SWZ_Z_SHIFT 25
+#define NV40_FP_OP_COND_SWZ_Z_MASK (3 << 25)
+#define NV40_FP_OP_COND_SWZ_Y_SHIFT 23
+#define NV40_FP_OP_COND_SWZ_Y_MASK (3 << 23)
+#define NV40_FP_OP_COND_SWZ_X_SHIFT 21
+#define NV40_FP_OP_COND_SWZ_X_MASK (3 << 21)
+#define NV40_FP_OP_COND_SWZ_ALL_SHIFT 21
+#define NV40_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21)
+#define NV40_FP_OP_COND_SHIFT 18
+#define NV40_FP_OP_COND_MASK (0x07 << 18)
+# define NV40_FP_OP_COND_FL 0
+# define NV40_FP_OP_COND_LT 1
+# define NV40_FP_OP_COND_EQ 2
+# define NV40_FP_OP_COND_LE 3
+# define NV40_FP_OP_COND_GT 4
+# define NV40_FP_OP_COND_NE 5
+# define NV40_FP_OP_COND_GE 6
+# define NV40_FP_OP_COND_TR 7
+
+/* high order bits of SRC1 */
+#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31)
+#define NV40_FP_OP_DST_SCALE_SHIFT 28
+#define NV40_FP_OP_DST_SCALE_MASK (3 << 28)
+#define NV40_FP_OP_DST_SCALE_1X 0
+#define NV40_FP_OP_DST_SCALE_2X 1
+#define NV40_FP_OP_DST_SCALE_4X 2
+#define NV40_FP_OP_DST_SCALE_8X 3
+#define NV40_FP_OP_DST_SCALE_INV_2X 5
+#define NV40_FP_OP_DST_SCALE_INV_4X 6
+#define NV40_FP_OP_DST_SCALE_INV_8X 7
+
+/* SRC1 LOOP */
+#define NV40_FP_OP_LOOP_INCR_SHIFT 19
+#define NV40_FP_OP_LOOP_INCR_MASK (0xFF << 19)
+#define NV40_FP_OP_LOOP_INDEX_SHIFT 10
+#define NV40_FP_OP_LOOP_INDEX_MASK (0xFF << 10)
+#define NV40_FP_OP_LOOP_COUNT_SHIFT 2
+#define NV40_FP_OP_LOOP_COUNT_MASK (0xFF << 2)
+
+/* SRC1 IF */
+#define NV40_FP_OP_ELSE_ID_SHIFT 2
+#define NV40_FP_OP_ELSE_ID_MASK (0xFF << 2)
+
+/* SRC1 CAL */
+#define NV40_FP_OP_IADDR_SHIFT 2
+#define NV40_FP_OP_IADDR_MASK (0xFF << 2)
+
+/* SRC1 REP
+ * I have no idea why there are 3 count values here.. but they
+ * have always been filled with the same value in my tests so
+ * far..
+ */
+#define NV40_FP_OP_REP_COUNT1_SHIFT 2
+#define NV40_FP_OP_REP_COUNT1_MASK (0xFF << 2)
+#define NV40_FP_OP_REP_COUNT2_SHIFT 10
+#define NV40_FP_OP_REP_COUNT2_MASK (0xFF << 10)
+#define NV40_FP_OP_REP_COUNT3_SHIFT 19
+#define NV40_FP_OP_REP_COUNT3_MASK (0xFF << 19)
+
+/* SRC2 REP/IF */
+#define NV40_FP_OP_END_ID_SHIFT 2
+#define NV40_FP_OP_END_ID_MASK (0xFF << 2)
+
+// SRC2 high-order
+#define NV40_FP_OP_INDEX_INPUT (1 << 30)
+#define NV40_FP_OP_ADDR_INDEX_SHIFT 19
+#define NV40_FP_OP_ADDR_INDEX_MASK (0xF << 19)
+
+//== Register selection ==
+#define NV40_FP_REG_TYPE_SHIFT 0
+#define NV40_FP_REG_TYPE_MASK (3 << 0)
+# define NV40_FP_REG_TYPE_TEMP 0
+# define NV40_FP_REG_TYPE_INPUT 1
+# define NV40_FP_REG_TYPE_CONST 2
+#define NV40_FP_REG_SRC_SHIFT 2
+#define NV40_FP_REG_SRC_MASK (63 << 2)
+#define NV40_FP_REG_SRC_HALF (1 << 8)
+#define NV40_FP_REG_SWZ_ALL_SHIFT 9
+#define NV40_FP_REG_SWZ_ALL_MASK (255 << 9)
+#define NV40_FP_REG_SWZ_X_SHIFT 9
+#define NV40_FP_REG_SWZ_X_MASK (3 << 9)
+#define NV40_FP_REG_SWZ_Y_SHIFT 11
+#define NV40_FP_REG_SWZ_Y_MASK (3 << 11)
+#define NV40_FP_REG_SWZ_Z_SHIFT 13
+#define NV40_FP_REG_SWZ_Z_MASK (3 << 13)
+#define NV40_FP_REG_SWZ_W_SHIFT 15
+#define NV40_FP_REG_SWZ_W_MASK (3 << 15)
+# define NV40_FP_SWIZZLE_X 0
+# define NV40_FP_SWIZZLE_Y 1
+# define NV40_FP_SWIZZLE_Z 2
+# define NV40_FP_SWIZZLE_W 3
+#define NV40_FP_REG_NEGATE (1 << 17)
+
+#ifndef NV40_SHADER_NO_FUCKEDNESS
+#define NV40SR_NONE 0
+#define NV40SR_OUTPUT 1
+#define NV40SR_INPUT 2
+#define NV40SR_TEMP 3
+#define NV40SR_CONST 4
+
+struct nv40_sreg {
+ int type;
+ int index;
+
+ int dst_scale;
+
+ int negate;
+ int abs;
+ int swz[4];
+
+ int cc_update;
+ int cc_update_reg;
+ int cc_test;
+ int cc_test_reg;
+ int cc_swz[4];
+};
+
+static INLINE struct nv40_sreg
+nv40_sr(int type, int index)
+{
+ struct nv40_sreg temp = {
+ .type = type,
+ .index = index,
+ .dst_scale = DEF_SCALE,
+ .abs = 0,
+ .negate = 0,
+ .swz = { 0, 1, 2, 3 },
+ .cc_update = 0,
+ .cc_update_reg = 0,
+ .cc_test = DEF_CTEST,
+ .cc_test_reg = 0,
+ .cc_swz = { 0, 1, 2, 3 },
+ };
+ return temp;
+}
+
+static INLINE struct nv40_sreg
+nv40_sr_swz(struct nv40_sreg src, int x, int y, int z, int w)
+{
+ struct nv40_sreg dst = src;
+
+ dst.swz[SWZ_X] = src.swz[x];
+ dst.swz[SWZ_Y] = src.swz[y];
+ dst.swz[SWZ_Z] = src.swz[z];
+ dst.swz[SWZ_W] = src.swz[w];
+ return dst;
+}
+
+static INLINE struct nv40_sreg
+nv40_sr_neg(struct nv40_sreg src)
+{
+ src.negate = !src.negate;
+ return src;
+}
+
+static INLINE struct nv40_sreg
+nv40_sr_abs(struct nv40_sreg src)
+{
+ src.abs = 1;
+ return src;
+}
+
+static INLINE struct nv40_sreg
+nv40_sr_scale(struct nv40_sreg src, int scale)
+{
+ src.dst_scale = scale;
+ return src;
+}
+#endif
+
+#endif
diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c
new file mode 100644
index 0000000000..c3ee4d2345
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state.c
@@ -0,0 +1,743 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "draw/draw_context.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "nv40_context.h"
+#include "nv40_state.h"
+
+static void *
+nv40_blend_state_create(struct pipe_context *pipe,
+ const struct pipe_blend_state *cso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nouveau_grobj *curie = nv40->screen->curie;
+ struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso));
+ struct nouveau_stateobj *so = so_new(16, 0);
+
+ if (cso->blend_enable) {
+ so_method(so, curie, NV40TCL_BLEND_ENABLE, 3);
+ so_data (so, 1);
+ so_data (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) |
+ nvgl_blend_func(cso->rgb_src_factor));
+ so_data (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 |
+ nvgl_blend_func(cso->rgb_dst_factor));
+ so_method(so, curie, NV40TCL_BLEND_EQUATION, 1);
+ so_data (so, nvgl_blend_eqn(cso->alpha_func) << 16 |
+ nvgl_blend_eqn(cso->rgb_func));
+ } else {
+ so_method(so, curie, NV40TCL_BLEND_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_method(so, curie, NV40TCL_COLOR_MASK, 1);
+ so_data (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) |
+ ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) |
+ ((cso->colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) |
+ ((cso->colormask & PIPE_MASK_B) ? (0x01 << 0) : 0)));
+
+ if (cso->logicop_enable) {
+ so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2);
+ so_data (so, 1);
+ so_data (so, nvgl_logicop_func(cso->logicop_func));
+ } else {
+ so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_method(so, curie, NV40TCL_DITHER_ENABLE, 1);
+ so_data (so, cso->dither ? 1 : 0);
+
+ so_ref(so, &bso->so);
+ so_ref(NULL, &so);
+ bso->pipe = *cso;
+ return (void *)bso;
+}
+
+static void
+nv40_blend_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->blend = hwcso;
+ nv40->dirty |= NV40_NEW_BLEND;
+}
+
+static void
+nv40_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_blend_state *bso = hwcso;
+
+ so_ref(NULL, &bso->so);
+ FREE(bso);
+}
+
+
+static INLINE unsigned
+wrap_mode(unsigned wrap) {
+ unsigned ret;
+
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ ret = NV40TCL_TEX_WRAP_S_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ ret = NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_EDGE;
+ break;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER;
+ break;
+ case PIPE_TEX_WRAP_CLAMP:
+ ret = NV40TCL_TEX_WRAP_S_CLAMP;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER;
+ break;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP;
+ break;
+ default:
+ NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+ ret = NV40TCL_TEX_WRAP_S_REPEAT;
+ break;
+ }
+
+ return ret >> NV40TCL_TEX_WRAP_S_SHIFT;
+}
+
+static void *
+nv40_sampler_state_create(struct pipe_context *pipe,
+ const struct pipe_sampler_state *cso)
+{
+ struct nv40_sampler_state *ps;
+ uint32_t filter = 0;
+
+ ps = MALLOC(sizeof(struct nv40_sampler_state));
+
+ ps->fmt = 0;
+ if (!cso->normalized_coords)
+ ps->fmt |= NV40TCL_TEX_FORMAT_RECT;
+
+ ps->wrap = ((wrap_mode(cso->wrap_s) << NV40TCL_TEX_WRAP_S_SHIFT) |
+ (wrap_mode(cso->wrap_t) << NV40TCL_TEX_WRAP_T_SHIFT) |
+ (wrap_mode(cso->wrap_r) << NV40TCL_TEX_WRAP_R_SHIFT));
+
+ ps->en = 0;
+ if (cso->max_anisotropy >= 2.0) {
+ /* no idea, binary driver sets it, works without it.. meh.. */
+ ps->wrap |= (1 << 5);
+
+ if (cso->max_anisotropy >= 16.0) {
+ ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X;
+ } else
+ if (cso->max_anisotropy >= 12.0) {
+ ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X;
+ } else
+ if (cso->max_anisotropy >= 10.0) {
+ ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X;
+ } else
+ if (cso->max_anisotropy >= 8.0) {
+ ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X;
+ } else
+ if (cso->max_anisotropy >= 6.0) {
+ ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X;
+ } else
+ if (cso->max_anisotropy >= 4.0) {
+ ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X;
+ } else {
+ ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X;
+ }
+ }
+
+ switch (cso->mag_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ filter |= NV40TCL_TEX_FILTER_MAG_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ filter |= NV40TCL_TEX_FILTER_MAG_NEAREST;
+ break;
+ }
+
+ switch (cso->min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV40TCL_TEX_FILTER_MIN_LINEAR;
+ break;
+ }
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ filter |= NV40TCL_TEX_FILTER_MIN_NEAREST;
+ break;
+ }
+ break;
+ }
+
+ ps->filt = filter;
+
+ {
+ float limit;
+
+ limit = CLAMP(cso->lod_bias, -16.0, 15.0);
+ ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
+
+ limit = CLAMP(cso->max_lod, 0.0, 15.0);
+ ps->en |= (int)(limit * 256.0) << 7;
+
+ limit = CLAMP(cso->min_lod, 0.0, 15.0);
+ ps->en |= (int)(limit * 256.0) << 19;
+ }
+
+
+ if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ switch (cso->compare_func) {
+ case PIPE_FUNC_NEVER:
+ ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NEVER;
+ break;
+ case PIPE_FUNC_GREATER:
+ ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GREATER;
+ break;
+ case PIPE_FUNC_EQUAL:
+ ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_EQUAL;
+ break;
+ case PIPE_FUNC_GEQUAL:
+ ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GEQUAL;
+ break;
+ case PIPE_FUNC_LESS:
+ ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LESS;
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NOTEQUAL;
+ break;
+ case PIPE_FUNC_LEQUAL:
+ ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LEQUAL;
+ break;
+ case PIPE_FUNC_ALWAYS:
+ ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_ALWAYS;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) |
+ (float_to_ubyte(cso->border_color[0]) << 16) |
+ (float_to_ubyte(cso->border_color[1]) << 8) |
+ (float_to_ubyte(cso->border_color[2]) << 0));
+
+ return (void *)ps;
+}
+
+static void
+nv40_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv40->tex_sampler[unit] = sampler[unit];
+ nv40->dirty_samplers |= (1 << unit);
+ }
+
+ for (unit = nr; unit < nv40->nr_samplers; unit++) {
+ nv40->tex_sampler[unit] = NULL;
+ nv40->dirty_samplers |= (1 << unit);
+ }
+
+ nv40->nr_samplers = nr;
+ nv40->dirty |= NV40_NEW_SAMPLER;
+}
+
+static void
+nv40_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void
+nv40_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+ struct pipe_texture **miptree)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ pipe_texture_reference((struct pipe_texture **)
+ &nv40->tex_miptree[unit], miptree[unit]);
+ nv40->dirty_samplers |= (1 << unit);
+ }
+
+ for (unit = nr; unit < nv40->nr_textures; unit++) {
+ pipe_texture_reference((struct pipe_texture **)
+ &nv40->tex_miptree[unit], NULL);
+ nv40->dirty_samplers |= (1 << unit);
+ }
+
+ nv40->nr_textures = nr;
+ nv40->dirty |= NV40_NEW_SAMPLER;
+}
+
+static void *
+nv40_rasterizer_state_create(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso));
+ struct nouveau_stateobj *so = so_new(32, 0);
+ struct nouveau_grobj *curie = nv40->screen->curie;
+
+ /*XXX: ignored:
+ * light_twoside
+ * point_smooth -nohw
+ * multisample
+ */
+
+ so_method(so, curie, NV40TCL_SHADE_MODEL, 1);
+ so_data (so, cso->flatshade ? NV40TCL_SHADE_MODEL_FLAT :
+ NV40TCL_SHADE_MODEL_SMOOTH);
+
+ so_method(so, curie, NV40TCL_LINE_WIDTH, 2);
+ so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff);
+ so_data (so, cso->line_smooth ? 1 : 0);
+ so_method(so, curie, NV40TCL_LINE_STIPPLE_ENABLE, 2);
+ so_data (so, cso->line_stipple_enable ? 1 : 0);
+ so_data (so, (cso->line_stipple_pattern << 16) |
+ cso->line_stipple_factor);
+
+ so_method(so, curie, NV40TCL_POINT_SIZE, 1);
+ so_data (so, fui(cso->point_size));
+
+ so_method(so, curie, NV40TCL_POLYGON_MODE_FRONT, 6);
+ if (cso->front_winding == PIPE_WINDING_CCW) {
+ so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+ so_data(so, nvgl_polygon_mode(cso->fill_cw));
+ switch (cso->cull_mode) {
+ case PIPE_WINDING_CCW:
+ so_data(so, NV40TCL_CULL_FACE_FRONT);
+ break;
+ case PIPE_WINDING_CW:
+ so_data(so, NV40TCL_CULL_FACE_BACK);
+ break;
+ case PIPE_WINDING_BOTH:
+ so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK);
+ break;
+ default:
+ so_data(so, NV40TCL_CULL_FACE_BACK);
+ break;
+ }
+ so_data(so, NV40TCL_FRONT_FACE_CCW);
+ } else {
+ so_data(so, nvgl_polygon_mode(cso->fill_cw));
+ so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+ switch (cso->cull_mode) {
+ case PIPE_WINDING_CCW:
+ so_data(so, NV40TCL_CULL_FACE_BACK);
+ break;
+ case PIPE_WINDING_CW:
+ so_data(so, NV40TCL_CULL_FACE_FRONT);
+ break;
+ case PIPE_WINDING_BOTH:
+ so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK);
+ break;
+ default:
+ so_data(so, NV40TCL_CULL_FACE_BACK);
+ break;
+ }
+ so_data(so, NV40TCL_FRONT_FACE_CW);
+ }
+ so_data(so, cso->poly_smooth ? 1 : 0);
+ so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0);
+
+ so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_data (so, cso->poly_stipple_enable ? 1 : 0);
+
+ so_method(so, curie, NV40TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if (cso->offset_cw || cso->offset_ccw) {
+ so_method(so, curie, NV40TCL_POLYGON_OFFSET_FACTOR, 2);
+ so_data (so, fui(cso->offset_scale));
+ so_data (so, fui(cso->offset_units * 2));
+ }
+
+ so_method(so, curie, NV40TCL_POINT_SPRITE, 1);
+ if (cso->point_sprite) {
+ unsigned psctl = (1 << 0), i;
+
+ for (i = 0; i < 8; i++) {
+ if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE)
+ psctl |= (1 << (8 + i));
+ }
+
+ so_data(so, psctl);
+ } else {
+ so_data(so, 0);
+ }
+
+ so_ref(so, &rsso->so);
+ so_ref(NULL, &so);
+ rsso->pipe = *cso;
+ return (void *)rsso;
+}
+
+static void
+nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->rasterizer = hwcso;
+ nv40->dirty |= NV40_NEW_RAST;
+ nv40->draw_dirty |= NV40_NEW_RAST;
+}
+
+static void
+nv40_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_rasterizer_state *rsso = hwcso;
+
+ so_ref(NULL, &rsso->so);
+ FREE(rsso);
+}
+
+static void *
+nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
+ struct nouveau_stateobj *so = so_new(32, 0);
+ struct nouveau_grobj *curie = nv40->screen->curie;
+
+ so_method(so, curie, NV40TCL_DEPTH_FUNC, 3);
+ so_data (so, nvgl_comparison_op(cso->depth.func));
+ so_data (so, cso->depth.writemask ? 1 : 0);
+ so_data (so, cso->depth.enabled ? 1 : 0);
+
+ so_method(so, curie, NV40TCL_ALPHA_TEST_ENABLE, 3);
+ so_data (so, cso->alpha.enabled ? 1 : 0);
+ so_data (so, nvgl_comparison_op(cso->alpha.func));
+ so_data (so, float_to_ubyte(cso->alpha.ref_value));
+
+ if (cso->stencil[0].enabled) {
+ so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 8);
+ so_data (so, cso->stencil[0].enabled ? 1 : 0);
+ so_data (so, cso->stencil[0].writemask);
+ so_data (so, nvgl_comparison_op(cso->stencil[0].func));
+ so_data (so, cso->stencil[0].ref_value);
+ so_data (so, cso->stencil[0].valuemask);
+ so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
+ } else {
+ so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ if (cso->stencil[1].enabled) {
+ so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 8);
+ so_data (so, cso->stencil[1].enabled ? 1 : 0);
+ so_data (so, cso->stencil[1].writemask);
+ so_data (so, nvgl_comparison_op(cso->stencil[1].func));
+ so_data (so, cso->stencil[1].ref_value);
+ so_data (so, cso->stencil[1].valuemask);
+ so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
+ } else {
+ so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_ref(so, &zsaso->so);
+ so_ref(NULL, &so);
+ zsaso->pipe = *cso;
+ return (void *)zsaso;
+}
+
+static void
+nv40_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->zsa = hwcso;
+ nv40->dirty |= NV40_NEW_ZSA;
+}
+
+static void
+nv40_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_zsa_state *zsaso = hwcso;
+
+ so_ref(NULL, &zsaso->so);
+ FREE(zsaso);
+}
+
+static void *
+nv40_vp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_vertex_program *vp;
+
+ vp = CALLOC(1, sizeof(struct nv40_vertex_program));
+ vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ vp->draw = draw_create_vertex_shader(nv40->draw, &vp->pipe);
+
+ return (void *)vp;
+}
+
+static void
+nv40_vp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->vertprog = hwcso;
+ nv40->dirty |= NV40_NEW_VERTPROG;
+ nv40->draw_dirty |= NV40_NEW_VERTPROG;
+}
+
+static void
+nv40_vp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_vertex_program *vp = hwcso;
+
+ draw_delete_vertex_shader(nv40->draw, vp->draw);
+ nv40_vertprog_destroy(nv40, vp);
+ FREE((void*)vp->pipe.tokens);
+ FREE(vp);
+}
+
+static void *
+nv40_fp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv40_fragment_program *fp;
+
+ fp = CALLOC(1, sizeof(struct nv40_fragment_program));
+ fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+
+ tgsi_scan_shader(fp->pipe.tokens, &fp->info);
+
+ return (void *)fp;
+}
+
+static void
+nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->fragprog = hwcso;
+ nv40->dirty |= NV40_NEW_FRAGPROG;
+}
+
+static void
+nv40_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_fragment_program *fp = hwcso;
+
+ nv40_fragprog_destroy(nv40, fp);
+ FREE((void*)fp->pipe.tokens);
+ FREE(fp);
+}
+
+static void
+nv40_set_blend_color(struct pipe_context *pipe,
+ const struct pipe_blend_color *bcol)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->blend_colour = *bcol;
+ nv40->dirty |= NV40_NEW_BCOL;
+}
+
+static void
+nv40_set_clip_state(struct pipe_context *pipe,
+ const struct pipe_clip_state *clip)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->clip = *clip;
+ nv40->dirty |= NV40_NEW_UCP;
+ nv40->draw_dirty |= NV40_NEW_UCP;
+}
+
+static void
+nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+ const struct pipe_constant_buffer *buf )
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->constbuf[shader] = buf->buffer;
+ nv40->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float));
+
+ if (shader == PIPE_SHADER_VERTEX) {
+ nv40->dirty |= NV40_NEW_VERTPROG;
+ } else
+ if (shader == PIPE_SHADER_FRAGMENT) {
+ nv40->dirty |= NV40_NEW_FRAGPROG;
+ }
+}
+
+static void
+nv40_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->framebuffer = *fb;
+ nv40->dirty |= NV40_NEW_FB;
+}
+
+static void
+nv40_set_polygon_stipple(struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ memcpy(nv40->stipple, stipple->stipple, 4 * 32);
+ nv40->dirty |= NV40_NEW_STIPPLE;
+}
+
+static void
+nv40_set_scissor_state(struct pipe_context *pipe,
+ const struct pipe_scissor_state *s)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->scissor = *s;
+ nv40->dirty |= NV40_NEW_SCISSOR;
+}
+
+static void
+nv40_set_viewport_state(struct pipe_context *pipe,
+ const struct pipe_viewport_state *vpt)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->viewport = *vpt;
+ nv40->dirty |= NV40_NEW_VIEWPORT;
+ nv40->draw_dirty |= NV40_NEW_VIEWPORT;
+}
+
+static void
+nv40_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_buffer *vb)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ memcpy(nv40->vtxbuf, vb, sizeof(*vb) * count);
+ nv40->vtxbuf_nr = count;
+
+ nv40->dirty |= NV40_NEW_ARRAYS;
+ nv40->draw_dirty |= NV40_NEW_ARRAYS;
+}
+
+static void
+nv40_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_element *ve)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ memcpy(nv40->vtxelt, ve, sizeof(*ve) * count);
+ nv40->vtxelt_nr = count;
+
+ nv40->dirty |= NV40_NEW_ARRAYS;
+ nv40->draw_dirty |= NV40_NEW_ARRAYS;
+}
+
+static void
+nv40_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+
+ nv40->edgeflags = bitfield;
+ nv40->dirty |= NV40_NEW_ARRAYS;
+ nv40->draw_dirty |= NV40_NEW_ARRAYS;
+}
+
+void
+nv40_init_state_functions(struct nv40_context *nv40)
+{
+ nv40->pipe.create_blend_state = nv40_blend_state_create;
+ nv40->pipe.bind_blend_state = nv40_blend_state_bind;
+ nv40->pipe.delete_blend_state = nv40_blend_state_delete;
+
+ nv40->pipe.create_sampler_state = nv40_sampler_state_create;
+ nv40->pipe.bind_sampler_states = nv40_sampler_state_bind;
+ nv40->pipe.delete_sampler_state = nv40_sampler_state_delete;
+ nv40->pipe.set_sampler_textures = nv40_set_sampler_texture;
+
+ nv40->pipe.create_rasterizer_state = nv40_rasterizer_state_create;
+ nv40->pipe.bind_rasterizer_state = nv40_rasterizer_state_bind;
+ nv40->pipe.delete_rasterizer_state = nv40_rasterizer_state_delete;
+
+ nv40->pipe.create_depth_stencil_alpha_state =
+ nv40_depth_stencil_alpha_state_create;
+ nv40->pipe.bind_depth_stencil_alpha_state =
+ nv40_depth_stencil_alpha_state_bind;
+ nv40->pipe.delete_depth_stencil_alpha_state =
+ nv40_depth_stencil_alpha_state_delete;
+
+ nv40->pipe.create_vs_state = nv40_vp_state_create;
+ nv40->pipe.bind_vs_state = nv40_vp_state_bind;
+ nv40->pipe.delete_vs_state = nv40_vp_state_delete;
+
+ nv40->pipe.create_fs_state = nv40_fp_state_create;
+ nv40->pipe.bind_fs_state = nv40_fp_state_bind;
+ nv40->pipe.delete_fs_state = nv40_fp_state_delete;
+
+ nv40->pipe.set_blend_color = nv40_set_blend_color;
+ nv40->pipe.set_clip_state = nv40_set_clip_state;
+ nv40->pipe.set_constant_buffer = nv40_set_constant_buffer;
+ nv40->pipe.set_framebuffer_state = nv40_set_framebuffer_state;
+ nv40->pipe.set_polygon_stipple = nv40_set_polygon_stipple;
+ nv40->pipe.set_scissor_state = nv40_set_scissor_state;
+ nv40->pipe.set_viewport_state = nv40_set_viewport_state;
+
+ nv40->pipe.set_edgeflags = nv40_set_edgeflags;
+ nv40->pipe.set_vertex_buffers = nv40_set_vertex_buffers;
+ nv40->pipe.set_vertex_elements = nv40_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nv40/nv40_state.h
new file mode 100644
index 0000000000..8a9d8c8fdf
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state.h
@@ -0,0 +1,88 @@
+#ifndef __NV40_STATE_H__
+#define __NV40_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+
+struct nv40_sampler_state {
+ uint32_t fmt;
+ uint32_t wrap;
+ uint32_t en;
+ uint32_t filt;
+ uint32_t bcol;
+};
+
+struct nv40_vertex_program_exec {
+ uint32_t data[4];
+ boolean has_branch_offset;
+ int const_index;
+};
+
+struct nv40_vertex_program_data {
+ int index; /* immediates == -1 */
+ float value[4];
+};
+
+struct nv40_vertex_program {
+ struct pipe_shader_state pipe;
+
+ struct draw_vertex_shader *draw;
+
+ boolean translated;
+
+ struct pipe_clip_state ucp;
+
+ struct nv40_vertex_program_exec *insns;
+ unsigned nr_insns;
+ struct nv40_vertex_program_data *consts;
+ unsigned nr_consts;
+
+ struct nouveau_resource *exec;
+ unsigned exec_start;
+ struct nouveau_resource *data;
+ unsigned data_start;
+ unsigned data_start_min;
+
+ uint32_t ir;
+ uint32_t or;
+ uint32_t clip_ctrl;
+ struct nouveau_stateobj *so;
+};
+
+struct nv40_fragment_program_data {
+ unsigned offset;
+ unsigned index;
+};
+
+struct nv40_fragment_program {
+ struct pipe_shader_state pipe;
+ struct tgsi_shader_info info;
+
+ boolean translated;
+ unsigned samplers;
+
+ uint32_t *insn;
+ int insn_len;
+
+ struct nv40_fragment_program_data *consts;
+ unsigned nr_consts;
+
+ struct pipe_buffer *buffer;
+
+ uint32_t fp_control;
+ struct nouveau_stateobj *so;
+};
+
+struct nv40_miptree {
+ struct pipe_texture base;
+
+ struct pipe_buffer *buffer;
+ uint total_size;
+
+ struct {
+ uint pitch;
+ uint *image_offset;
+ } level[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+#endif
diff --git a/src/gallium/drivers/nv40/nv40_state_blend.c b/src/gallium/drivers/nv40/nv40_state_blend.c
new file mode 100644
index 0000000000..8cd05ce66e
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_blend.c
@@ -0,0 +1,41 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_blend_validate(struct nv40_context *nv40)
+{
+ so_ref(nv40->blend->so, &nv40->state.hw[NV40_STATE_BLEND]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_blend = {
+ .validate = nv40_state_blend_validate,
+ .dirty = {
+ .pipe = NV40_NEW_BLEND,
+ .hw = NV40_STATE_BLEND
+ }
+};
+
+static boolean
+nv40_state_blend_colour_validate(struct nv40_context *nv40)
+{
+ struct nouveau_stateobj *so = so_new(2, 0);
+ struct pipe_blend_color *bcol = &nv40->blend_colour;
+
+ so_method(so, nv40->screen->curie, NV40TCL_BLEND_COLOR, 1);
+ so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) |
+ (float_to_ubyte(bcol->color[0]) << 16) |
+ (float_to_ubyte(bcol->color[1]) << 8) |
+ (float_to_ubyte(bcol->color[2]) << 0)));
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_BCOL]);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_blend_colour = {
+ .validate = nv40_state_blend_colour_validate,
+ .dirty = {
+ .pipe = NV40_NEW_BCOL,
+ .hw = NV40_STATE_BCOL
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
new file mode 100644
index 0000000000..198692965d
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_emit.c
@@ -0,0 +1,177 @@
+#include "nv40_context.h"
+#include "nv40_state.h"
+#include "draw/draw_context.h"
+
+static struct nv40_state_entry *render_states[] = {
+ &nv40_state_framebuffer,
+ &nv40_state_rasterizer,
+ &nv40_state_scissor,
+ &nv40_state_stipple,
+ &nv40_state_fragprog,
+ &nv40_state_fragtex,
+ &nv40_state_vertprog,
+ &nv40_state_blend,
+ &nv40_state_blend_colour,
+ &nv40_state_zsa,
+ &nv40_state_viewport,
+ &nv40_state_vbo,
+ NULL
+};
+
+static struct nv40_state_entry *swtnl_states[] = {
+ &nv40_state_framebuffer,
+ &nv40_state_rasterizer,
+ &nv40_state_scissor,
+ &nv40_state_stipple,
+ &nv40_state_fragprog,
+ &nv40_state_fragtex,
+ &nv40_state_vertprog,
+ &nv40_state_blend,
+ &nv40_state_blend_colour,
+ &nv40_state_zsa,
+ &nv40_state_viewport,
+ &nv40_state_vtxfmt,
+ NULL
+};
+
+static void
+nv40_state_do_validate(struct nv40_context *nv40,
+ struct nv40_state_entry **states)
+{
+ while (*states) {
+ struct nv40_state_entry *e = *states;
+
+ if (nv40->dirty & e->dirty.pipe) {
+ if (e->validate(nv40))
+ nv40->state.dirty |= (1ULL << e->dirty.hw);
+ }
+
+ states++;
+ }
+ nv40->dirty = 0;
+}
+
+void
+nv40_state_emit(struct nv40_context *nv40)
+{
+ struct nouveau_channel *chan = nv40->screen->base.channel;
+ struct nv40_state *state = &nv40->state;
+ struct nv40_screen *screen = nv40->screen;
+ unsigned i, samplers;
+ uint64_t states;
+
+ if (nv40->pctx_id != screen->cur_pctx) {
+ for (i = 0; i < NV40_STATE_MAX; i++) {
+ if (state->hw[i] && screen->state[i] != state->hw[i])
+ state->dirty |= (1ULL << i);
+ }
+
+ screen->cur_pctx = nv40->pctx_id;
+ }
+
+ for (i = 0, states = state->dirty; states; i++) {
+ if (!(states & (1ULL << i)))
+ continue;
+ so_ref (state->hw[i], &nv40->screen->state[i]);
+ if (state->hw[i])
+ so_emit(chan, nv40->screen->state[i]);
+ states &= ~(1ULL << i);
+ }
+
+ if (state->dirty & ((1ULL << NV40_STATE_FRAGPROG) |
+ (1ULL << NV40_STATE_FRAGTEX0))) {
+ BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
+ OUT_RING (2);
+ BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
+ OUT_RING (1);
+ }
+
+ state->dirty = 0;
+
+ so_emit_reloc_markers(chan, state->hw[NV40_STATE_FB]);
+ for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
+ if (!(samplers & (1 << i)))
+ continue;
+ so_emit_reloc_markers(chan,
+ state->hw[NV40_STATE_FRAGTEX0+i]);
+ samplers &= ~(1ULL << i);
+ }
+ so_emit_reloc_markers(chan, state->hw[NV40_STATE_FRAGPROG]);
+ if (state->hw[NV40_STATE_VTXBUF] && nv40->render_mode == HW)
+ so_emit_reloc_markers(chan, state->hw[NV40_STATE_VTXBUF]);
+}
+
+boolean
+nv40_state_validate(struct nv40_context *nv40)
+{
+ boolean was_sw = nv40->fallback_swtnl ? TRUE : FALSE;
+
+ if (nv40->render_mode != HW) {
+ /* Don't even bother trying to go back to hw if none
+ * of the states that caused swtnl previously have changed.
+ */
+ if ((nv40->fallback_swtnl & nv40->dirty)
+ != nv40->fallback_swtnl)
+ return FALSE;
+
+ /* Attempt to go to hwtnl again */
+ nv40->pipe.flush(&nv40->pipe, 0, NULL);
+ nv40->dirty |= (NV40_NEW_VIEWPORT |
+ NV40_NEW_VERTPROG |
+ NV40_NEW_ARRAYS);
+ nv40->render_mode = HW;
+ }
+
+ nv40_state_do_validate(nv40, render_states);
+ if (nv40->fallback_swtnl || nv40->fallback_swrast)
+ return FALSE;
+
+ if (was_sw)
+ NOUVEAU_ERR("swtnl->hw\n");
+
+ return TRUE;
+}
+
+boolean
+nv40_state_validate_swtnl(struct nv40_context *nv40)
+{
+ struct draw_context *draw = nv40->draw;
+
+ /* Setup for swtnl */
+ if (nv40->render_mode == HW) {
+ NOUVEAU_ERR("hw->swtnl 0x%08x\n", nv40->fallback_swtnl);
+ nv40->pipe.flush(&nv40->pipe, 0, NULL);
+ nv40->dirty |= (NV40_NEW_VIEWPORT |
+ NV40_NEW_VERTPROG |
+ NV40_NEW_ARRAYS);
+ nv40->render_mode = SWTNL;
+ }
+
+ if (nv40->draw_dirty & NV40_NEW_VERTPROG)
+ draw_bind_vertex_shader(draw, nv40->vertprog->draw);
+
+ if (nv40->draw_dirty & NV40_NEW_RAST)
+ draw_set_rasterizer_state(draw, &nv40->rasterizer->pipe);
+
+ if (nv40->draw_dirty & NV40_NEW_UCP)
+ draw_set_clip_state(draw, &nv40->clip);
+
+ if (nv40->draw_dirty & NV40_NEW_VIEWPORT)
+ draw_set_viewport_state(draw, &nv40->viewport);
+
+ if (nv40->draw_dirty & NV40_NEW_ARRAYS) {
+ draw_set_edgeflags(draw, nv40->edgeflags);
+ draw_set_vertex_buffers(draw, nv40->vtxbuf_nr, nv40->vtxbuf);
+ draw_set_vertex_elements(draw, nv40->vtxelt_nr, nv40->vtxelt);
+ }
+
+ nv40_state_do_validate(nv40, swtnl_states);
+ if (nv40->fallback_swrast) {
+ NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nv40->fallback_swrast);
+ return FALSE;
+ }
+
+ nv40->draw_dirty = 0;
+ return TRUE;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c
new file mode 100644
index 0000000000..c2f739157a
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_fb.c
@@ -0,0 +1,172 @@
+#include "nv40_context.h"
+#include "nouveau/nouveau_util.h"
+
+static struct pipe_buffer *
+nv40_do_surface_buffer(struct pipe_surface *surface)
+{
+ struct nv40_miptree *mt = (struct nv40_miptree *)surface->texture;
+ return mt->buffer;
+}
+
+#define nv40_surface_buffer(ps) nouveau_bo(nv40_do_surface_buffer(ps))
+
+static boolean
+nv40_state_framebuffer_validate(struct nv40_context *nv40)
+{
+ struct nouveau_channel *chan = nv40->screen->base.channel;
+ struct nouveau_grobj *curie = nv40->screen->curie;
+ struct pipe_framebuffer_state *fb = &nv40->framebuffer;
+ struct nv04_surface *rt[4], *zeta;
+ uint32_t rt_enable, rt_format;
+ int i, colour_format = 0, zeta_format = 0;
+ struct nouveau_stateobj *so = so_new(64, 10);
+ unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
+ unsigned w = fb->width;
+ unsigned h = fb->height;
+
+ rt_enable = 0;
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ if (colour_format) {
+ assert(colour_format == fb->cbufs[i]->format);
+ } else {
+ colour_format = fb->cbufs[i]->format;
+ rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i);
+ rt[i] = (struct nv04_surface *)fb->cbufs[i];
+ }
+ }
+
+ if (rt_enable & (NV40TCL_RT_ENABLE_COLOR1 | NV40TCL_RT_ENABLE_COLOR2 |
+ NV40TCL_RT_ENABLE_COLOR3))
+ rt_enable |= NV40TCL_RT_ENABLE_MRT;
+
+ if (fb->zsbuf) {
+ zeta_format = fb->zsbuf->format;
+ zeta = (struct nv04_surface *)fb->zsbuf;
+ }
+
+ if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+ assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1)));
+ for (i = 1; i < fb->nr_cbufs; i++)
+ assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR));
+
+ rt_format = NV40TCL_RT_FORMAT_TYPE_SWIZZLED |
+ log2i(fb->width) << NV40TCL_RT_FORMAT_LOG2_WIDTH_SHIFT |
+ log2i(fb->height) << NV40TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT;
+ }
+ else
+ rt_format = NV40TCL_RT_FORMAT_TYPE_LINEAR;
+
+ switch (colour_format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case 0:
+ rt_format |= NV40TCL_RT_FORMAT_COLOR_A8R8G8B8;
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ rt_format |= NV40TCL_RT_FORMAT_COLOR_R5G6B5;
+ break;
+ default:
+ assert(0);
+ }
+
+ switch (zeta_format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ rt_format |= NV40TCL_RT_FORMAT_ZETA_Z16;
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case 0:
+ rt_format |= NV40TCL_RT_FORMAT_ZETA_Z24S8;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) {
+ so_method(so, curie, NV40TCL_DMA_COLOR0, 1);
+ so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0,
+ rt_flags | NOUVEAU_BO_OR,
+ chan->vram->handle, chan->gart->handle);
+ so_method(so, curie, NV40TCL_COLOR0_PITCH, 2);
+ so_data (so, rt[0]->pitch);
+ so_reloc (so, nv40_surface_buffer(&rt[0]->base),
+ rt[0]->base.offset, rt_flags | NOUVEAU_BO_LOW,
+ 0, 0);
+ }
+
+ if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) {
+ so_method(so, curie, NV40TCL_DMA_COLOR1, 1);
+ so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0,
+ rt_flags | NOUVEAU_BO_OR,
+ chan->vram->handle, chan->gart->handle);
+ so_method(so, curie, NV40TCL_COLOR1_OFFSET, 2);
+ so_reloc (so, nv40_surface_buffer(&rt[1]->base),
+ rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW,
+ 0, 0);
+ so_data (so, rt[1]->pitch);
+ }
+
+ if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) {
+ so_method(so, curie, NV40TCL_DMA_COLOR2, 1);
+ so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0,
+ rt_flags | NOUVEAU_BO_OR,
+ chan->vram->handle, chan->gart->handle);
+ so_method(so, curie, NV40TCL_COLOR2_OFFSET, 1);
+ so_reloc (so, nv40_surface_buffer(&rt[2]->base),
+ rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW,
+ 0, 0);
+ so_method(so, curie, NV40TCL_COLOR2_PITCH, 1);
+ so_data (so, rt[2]->pitch);
+ }
+
+ if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) {
+ so_method(so, curie, NV40TCL_DMA_COLOR3, 1);
+ so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0,
+ rt_flags | NOUVEAU_BO_OR,
+ chan->vram->handle, chan->gart->handle);
+ so_method(so, curie, NV40TCL_COLOR3_OFFSET, 1);
+ so_reloc (so, nv40_surface_buffer(&rt[3]->base),
+ rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW,
+ 0, 0);
+ so_method(so, curie, NV40TCL_COLOR3_PITCH, 1);
+ so_data (so, rt[3]->pitch);
+ }
+
+ if (zeta_format) {
+ so_method(so, curie, NV40TCL_DMA_ZETA, 1);
+ so_reloc (so, nv40_surface_buffer(&zeta->base), 0,
+ rt_flags | NOUVEAU_BO_OR,
+ chan->vram->handle, chan->gart->handle);
+ so_method(so, curie, NV40TCL_ZETA_OFFSET, 1);
+ so_reloc (so, nv40_surface_buffer(&zeta->base),
+ zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0);
+ so_method(so, curie, NV40TCL_ZETA_PITCH, 1);
+ so_data (so, zeta->pitch);
+ }
+
+ so_method(so, curie, NV40TCL_RT_ENABLE, 1);
+ so_data (so, rt_enable);
+ so_method(so, curie, NV40TCL_RT_HORIZ, 3);
+ so_data (so, (w << 16) | 0);
+ so_data (so, (h << 16) | 0);
+ so_data (so, rt_format);
+ so_method(so, curie, NV40TCL_VIEWPORT_HORIZ, 2);
+ so_data (so, (w << 16) | 0);
+ so_data (so, (h << 16) | 0);
+ so_method(so, curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+ so_data (so, ((w - 1) << 16) | 0);
+ so_data (so, ((h - 1) << 16) | 0);
+ so_method(so, curie, 0x1d88, 1);
+ so_data (so, (1 << 12) | h);
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_FB]);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_framebuffer = {
+ .validate = nv40_state_framebuffer_validate,
+ .dirty = {
+ .pipe = NV40_NEW_FB,
+ .hw = NV40_STATE_FB
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_rasterizer.c b/src/gallium/drivers/nv40/nv40_state_rasterizer.c
new file mode 100644
index 0000000000..9ecda5990f
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_rasterizer.c
@@ -0,0 +1,17 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_rasterizer_validate(struct nv40_context *nv40)
+{
+ so_ref(nv40->rasterizer->so,
+ &nv40->state.hw[NV40_STATE_RAST]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_rasterizer = {
+ .validate = nv40_state_rasterizer_validate,
+ .dirty = {
+ .pipe = NV40_NEW_RAST,
+ .hw = NV40_STATE_RAST
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_scissor.c b/src/gallium/drivers/nv40/nv40_state_scissor.c
new file mode 100644
index 0000000000..cf58d33906
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_scissor.c
@@ -0,0 +1,36 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_scissor_validate(struct nv40_context *nv40)
+{
+ struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
+ struct pipe_scissor_state *s = &nv40->scissor;
+ struct nouveau_stateobj *so;
+
+ if (nv40->state.hw[NV40_STATE_SCISSOR] &&
+ (rast->scissor == 0 && nv40->state.scissor_enabled == 0))
+ return FALSE;
+ nv40->state.scissor_enabled = rast->scissor;
+
+ so = so_new(3, 0);
+ so_method(so, nv40->screen->curie, NV40TCL_SCISSOR_HORIZ, 2);
+ if (nv40->state.scissor_enabled) {
+ so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
+ so_data (so, ((s->maxy - s->miny) << 16) | s->miny);
+ } else {
+ so_data (so, 4096 << 16);
+ so_data (so, 4096 << 16);
+ }
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_SCISSOR]);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_scissor = {
+ .validate = nv40_state_scissor_validate,
+ .dirty = {
+ .pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST,
+ .hw = NV40_STATE_SCISSOR
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_stipple.c b/src/gallium/drivers/nv40/nv40_state_stipple.c
new file mode 100644
index 0000000000..b51024ad9b
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_stipple.c
@@ -0,0 +1,39 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_stipple_validate(struct nv40_context *nv40)
+{
+ struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
+ struct nouveau_grobj *curie = nv40->screen->curie;
+ struct nouveau_stateobj *so;
+
+ if (nv40->state.hw[NV40_STATE_STIPPLE] &&
+ (rast->poly_stipple_enable == 0 && nv40->state.stipple_enabled == 0))
+ return FALSE;
+
+ if (rast->poly_stipple_enable) {
+ unsigned i;
+
+ so = so_new(35, 0);
+ so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_data (so, 1);
+ so_method(so, curie, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 32);
+ for (i = 0; i < 32; i++)
+ so_data(so, nv40->stipple[i]);
+ } else {
+ so = so_new(2, 0);
+ so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_STIPPLE]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_stipple = {
+ .validate = nv40_state_stipple_validate,
+ .dirty = {
+ .pipe = NV40_NEW_STIPPLE | NV40_NEW_RAST,
+ .hw = NV40_STATE_STIPPLE,
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_viewport.c b/src/gallium/drivers/nv40/nv40_state_viewport.c
new file mode 100644
index 0000000000..665d2d5fca
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_viewport.c
@@ -0,0 +1,69 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_viewport_validate(struct nv40_context *nv40)
+{
+ struct pipe_viewport_state *vpt = &nv40->viewport;
+ struct nouveau_stateobj *so;
+ unsigned bypass;
+
+ if (nv40->render_mode == HW &&
+ !nv40->rasterizer->pipe.bypass_vs_clip_and_viewport)
+ bypass = 0;
+ else
+ bypass = 1;
+
+ if (nv40->state.hw[NV40_STATE_VIEWPORT] &&
+ (bypass || !(nv40->dirty & NV40_NEW_VIEWPORT)) &&
+ nv40->state.viewport_bypass == bypass)
+ return FALSE;
+ nv40->state.viewport_bypass = bypass;
+
+ so = so_new(11, 0);
+ if (!bypass) {
+ so_method(so, nv40->screen->curie,
+ NV40TCL_VIEWPORT_TRANSLATE_X, 8);
+ so_data (so, fui(vpt->translate[0]));
+ so_data (so, fui(vpt->translate[1]));
+ so_data (so, fui(vpt->translate[2]));
+ so_data (so, fui(vpt->translate[3]));
+ so_data (so, fui(vpt->scale[0]));
+ so_data (so, fui(vpt->scale[1]));
+ so_data (so, fui(vpt->scale[2]));
+ so_data (so, fui(vpt->scale[3]));
+ so_method(so, nv40->screen->curie, 0x1d78, 1);
+ so_data (so, 1);
+ } else {
+ so_method(so, nv40->screen->curie,
+ NV40TCL_VIEWPORT_TRANSLATE_X, 8);
+ so_data (so, fui(0.0));
+ so_data (so, fui(0.0));
+ so_data (so, fui(0.0));
+ so_data (so, fui(0.0));
+ so_data (so, fui(1.0));
+ so_data (so, fui(1.0));
+ so_data (so, fui(1.0));
+ so_data (so, fui(0.0));
+ /* Not entirely certain what this is yet. The DDX uses this
+ * value also as it fixes rendering when you pass
+ * pre-transformed vertices to the GPU. My best gusss is that
+ * this bypasses some culling/clipping stage. Might be worth
+ * noting that points/lines are uneffected by whatever this
+ * value fixes, only filled polygons are effected.
+ */
+ so_method(so, nv40->screen->curie, 0x1d78, 1);
+ so_data (so, 0x110);
+ }
+
+ so_ref(so, &nv40->state.hw[NV40_STATE_VIEWPORT]);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_viewport = {
+ .validate = nv40_state_viewport_validate,
+ .dirty = {
+ .pipe = NV40_NEW_VIEWPORT | NV40_NEW_RAST,
+ .hw = NV40_STATE_VIEWPORT
+ }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_zsa.c b/src/gallium/drivers/nv40/nv40_state_zsa.c
new file mode 100644
index 0000000000..fb760677c8
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_zsa.c
@@ -0,0 +1,17 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_zsa_validate(struct nv40_context *nv40)
+{
+ so_ref(nv40->zsa->so,
+ &nv40->state.hw[NV40_STATE_ZSA]);
+ return TRUE;
+}
+
+struct nv40_state_entry nv40_state_zsa = {
+ .validate = nv40_state_zsa_validate,
+ .dirty = {
+ .pipe = NV40_NEW_ZSA,
+ .hw = NV40_STATE_ZSA
+ }
+};
diff --git a/src/mesa/drivers/dri/i915/i915_tex.c b/src/gallium/drivers/nv40/nv40_surface.c
index e38d8fe79d..a596547974 100644
--- a/src/mesa/drivers/dri/i915/i915_tex.c
+++ b/src/gallium/drivers/nv40/nv40_surface.c
@@ -1,3 +1,4 @@
+
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
@@ -25,54 +26,39 @@
*
**************************************************************************/
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "main/imports.h"
-#include "main/simple_list.h"
-#include "main/enums.h"
-#include "main/image.h"
-#include "main/mm.h"
-#include "main/texstore.h"
-#include "main/texformat.h"
-#include "swrast/swrast.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
-#include "texmem.h"
+#include "util/u_tile.h"
-#include "i915_context.h"
-#include "i915_reg.h"
+#include "nv40_context.h"
+static void
+nv40_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv04_surface_2d *eng2d = nv40->screen->eng2d;
+ eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
+}
static void
-i915TexEnv(GLcontext * ctx, GLenum target,
- GLenum pname, const GLfloat * param)
+nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+ unsigned destx, unsigned desty, unsigned width,
+ unsigned height, unsigned value)
{
- struct i915_context *i915 = I915_CONTEXT(ctx);
-
- switch (pname) {
- case GL_TEXTURE_LOD_BIAS:{
- GLuint unit = ctx->Texture.CurrentUnit;
- GLint b = (int) ((*param) * 16.0);
- if (b > 255)
- b = 255;
- if (b < -256)
- b = -256;
- I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
- i915->lodbias_ss2[unit] =
- ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
- break;
- }
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv04_surface_2d *eng2d = nv40->screen->eng2d;
- default:
- break;
- }
+ eng2d->fill(eng2d, dest, destx, desty, width, height, value);
}
-
void
-i915InitTextureFuncs(struct dd_function_table *functions)
+nv40_init_surface_functions(struct nv40_context *nv40)
{
-/*
- functions->TexEnv = i915TexEnv;
-*/
+ nv40->pipe.surface_copy = nv40_surface_copy;
+ nv40->pipe.surface_fill = nv40_surface_fill;
}
diff --git a/src/gallium/drivers/nv40/nv40_transfer.c b/src/gallium/drivers/nv40/nv40_transfer.c
new file mode 100644
index 0000000000..6d92ac3db9
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_transfer.c
@@ -0,0 +1,195 @@
+#include <pipe/p_state.h>
+#include <pipe/p_defines.h>
+#include <pipe/p_inlines.h>
+#include <util/u_memory.h>
+#include <nouveau/nouveau_winsys.h>
+#include "nv40_context.h"
+#include "nv40_screen.h"
+#include "nv40_state.h"
+
+struct nv40_transfer {
+ struct pipe_transfer base;
+ struct pipe_surface *surface;
+ bool direct;
+};
+
+static unsigned nv40_usage_tx_to_buf(unsigned tx_usage)
+{
+ switch (tx_usage) {
+ case PIPE_TRANSFER_READ:
+ return PIPE_BUFFER_USAGE_CPU_READ;
+ case PIPE_TRANSFER_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_WRITE;
+ case PIPE_TRANSFER_READ_WRITE:
+ return PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static void
+nv40_compatible_transfer_tex(struct pipe_texture *pt, unsigned level,
+ struct pipe_texture *template)
+{
+ memset(template, 0, sizeof(struct pipe_texture));
+ template->target = pt->target;
+ template->format = pt->format;
+ template->width[0] = pt->width[level];
+ template->height[0] = pt->height[level];
+ template->depth[0] = 1;
+ template->block = pt->block;
+ template->nblocksx[0] = pt->nblocksx[level];
+ template->nblocksy[0] = pt->nblocksx[level];
+ template->last_level = 0;
+ template->nr_samples = pt->nr_samples;
+
+ template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC |
+ NOUVEAU_TEXTURE_USAGE_LINEAR;
+}
+
+static struct pipe_transfer *
+nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct nv40_miptree *mt = (struct nv40_miptree *)pt;
+ struct nv40_transfer *tx;
+ struct pipe_texture tx_tex_template, *tx_tex;
+
+ tx = CALLOC_STRUCT(nv40_transfer);
+ if (!tx)
+ return NULL;
+
+ pipe_texture_reference(&tx->base.texture, pt);
+ tx->base.format = pt->format;
+ tx->base.x = x;
+ tx->base.y = y;
+ tx->base.width = w;
+ tx->base.height = h;
+ tx->base.block = pt->block;
+ tx->base.nblocksx = pt->nblocksx[level];
+ tx->base.nblocksy = pt->nblocksy[level];
+ tx->base.stride = mt->level[level].pitch;
+ tx->base.usage = usage;
+ tx->base.face = face;
+ tx->base.level = level;
+ tx->base.zslice = zslice;
+
+ /* Direct access to texture */
+ if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC ||
+ debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) &&
+ pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)
+ {
+ tx->direct = true;
+ tx->surface = pscreen->get_tex_surface(pscreen, pt,
+ face, level, zslice,
+ nv40_usage_tx_to_buf(usage));
+ return &tx->base;
+ }
+
+ tx->direct = false;
+
+ nv40_compatible_transfer_tex(pt, level, &tx_tex_template);
+
+ tx_tex = pscreen->texture_create(pscreen, &tx_tex_template);
+ if (!tx_tex)
+ {
+ FREE(tx);
+ return NULL;
+ }
+
+ tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
+ 0, 0, 0,
+ nv40_usage_tx_to_buf(usage));
+
+ pipe_texture_reference(&tx_tex, NULL);
+
+ if (!tx->surface)
+ {
+ pipe_surface_reference(&tx->surface, NULL);
+ FREE(tx);
+ return NULL;
+ }
+
+ if (usage != PIPE_TRANSFER_WRITE) {
+ struct nv40_screen *nvscreen = nv40_screen(pscreen);
+ struct pipe_surface *src;
+
+ src = pscreen->get_tex_surface(pscreen, pt,
+ face, level, zslice,
+ PIPE_BUFFER_USAGE_GPU_READ);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ /* TODO: Check if SIFM can un-swizzle */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ tx->surface, 0, 0,
+ src, 0, 0,
+ src->width, src->height);
+
+ pipe_surface_reference(&src, NULL);
+ }
+
+ return &tx->base;
+}
+
+static void
+nv40_transfer_del(struct pipe_transfer *ptx)
+{
+ struct nv40_transfer *tx = (struct nv40_transfer *)ptx;
+
+ if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) {
+ struct pipe_screen *pscreen = ptx->texture->screen;
+ struct nv40_screen *nvscreen = nv40_screen(pscreen);
+ struct pipe_surface *dst;
+
+ dst = pscreen->get_tex_surface(pscreen, ptx->texture,
+ ptx->face, ptx->level, ptx->zslice,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
+ nvscreen->eng2d->copy(nvscreen->eng2d,
+ dst, 0, 0,
+ tx->surface, 0, 0,
+ dst->width, dst->height);
+
+ pipe_surface_reference(&dst, NULL);
+ }
+
+ pipe_surface_reference(&tx->surface, NULL);
+ pipe_texture_reference(&ptx->texture, NULL);
+ FREE(ptx);
+}
+
+static void *
+nv40_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv40_transfer *tx = (struct nv40_transfer *)ptx;
+ struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
+ struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture;
+ void *map = pipe_buffer_map(pscreen, mt->buffer,
+ nv40_usage_tx_to_buf(ptx->usage));
+
+ return map + ns->base.offset +
+ ptx->y * ns->pitch + ptx->x * ptx->block.size;
+}
+
+static void
+nv40_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv40_transfer *tx = (struct nv40_transfer *)ptx;
+ struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture;
+
+ pipe_buffer_unmap(pscreen, mt->buffer);
+}
+
+void
+nv40_screen_init_transfer_functions(struct pipe_screen *pscreen)
+{
+ pscreen->get_tex_transfer = nv40_transfer_new;
+ pscreen->tex_transfer_destroy = nv40_transfer_del;
+ pscreen->transfer_map = nv40_transfer_map;
+ pscreen->transfer_unmap = nv40_transfer_unmap;
+}
diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c
new file mode 100644
index 0000000000..b2753b8e2e
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_vbo.c
@@ -0,0 +1,562 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "nv40_context.h"
+#include "nv40_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+#include "nouveau/nouveau_util.h"
+
+#define FORCE_SWTNL 0
+
+static INLINE int
+nv40_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp)
+{
+ switch (pipe) {
+ case PIPE_FORMAT_R32_FLOAT:
+ case PIPE_FORMAT_R32G32_FLOAT:
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ *fmt = NV40TCL_VTXFMT_TYPE_FLOAT;
+ break;
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R8G8_UNORM:
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ *fmt = NV40TCL_VTXFMT_TYPE_UBYTE;
+ break;
+ case PIPE_FORMAT_R16_SSCALED:
+ case PIPE_FORMAT_R16G16_SSCALED:
+ case PIPE_FORMAT_R16G16B16_SSCALED:
+ case PIPE_FORMAT_R16G16B16A16_SSCALED:
+ *fmt = NV40TCL_VTXFMT_TYPE_USHORT;
+ break;
+ default:
+ NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
+ return 1;
+ }
+
+ switch (pipe) {
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R32_FLOAT:
+ case PIPE_FORMAT_R16_SSCALED:
+ *ncomp = 1;
+ break;
+ case PIPE_FORMAT_R8G8_UNORM:
+ case PIPE_FORMAT_R32G32_FLOAT:
+ case PIPE_FORMAT_R16G16_SSCALED:
+ *ncomp = 2;
+ break;
+ case PIPE_FORMAT_R8G8B8_UNORM:
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ case PIPE_FORMAT_R16G16B16_SSCALED:
+ *ncomp = 3;
+ break;
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ case PIPE_FORMAT_R16G16B16A16_SSCALED:
+ *ncomp = 4;
+ break;
+ default:
+ NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
+ return 1;
+ }
+
+ return 0;
+}
+
+static boolean
+nv40_vbo_set_idxbuf(struct nv40_context *nv40, struct pipe_buffer *ib,
+ unsigned ib_size)
+{
+ struct pipe_screen *pscreen = &nv40->screen->base.base;
+ unsigned type;
+
+ if (!ib) {
+ nv40->idxbuf = NULL;
+ nv40->idxbuf_format = 0xdeadbeef;
+ return FALSE;
+ }
+
+ if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1)
+ return FALSE;
+
+ switch (ib_size) {
+ case 2:
+ type = NV40TCL_IDXBUF_FORMAT_TYPE_U16;
+ break;
+ case 4:
+ type = NV40TCL_IDXBUF_FORMAT_TYPE_U32;
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (ib != nv40->idxbuf ||
+ type != nv40->idxbuf_format) {
+ nv40->dirty |= NV40_NEW_ARRAYS;
+ nv40->idxbuf = ib;
+ nv40->idxbuf_format = type;
+ }
+
+ return TRUE;
+}
+
+static boolean
+nv40_vbo_static_attrib(struct nv40_context *nv40, struct nouveau_stateobj *so,
+ int attrib, struct pipe_vertex_element *ve,
+ struct pipe_vertex_buffer *vb)
+{
+ struct pipe_screen *pscreen = nv40->pipe.screen;
+ struct nouveau_grobj *curie = nv40->screen->curie;
+ unsigned type, ncomp;
+ void *map;
+
+ if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp))
+ return FALSE;
+
+ map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+ map += vb->buffer_offset + ve->src_offset;
+
+ switch (type) {
+ case NV40TCL_VTXFMT_TYPE_FLOAT:
+ {
+ float *v = map;
+
+ switch (ncomp) {
+ case 4:
+ so_method(so, curie, NV40TCL_VTX_ATTR_4F_X(attrib), 4);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ so_data (so, fui(v[2]));
+ so_data (so, fui(v[3]));
+ break;
+ case 3:
+ so_method(so, curie, NV40TCL_VTX_ATTR_3F_X(attrib), 3);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ so_data (so, fui(v[2]));
+ break;
+ case 2:
+ so_method(so, curie, NV40TCL_VTX_ATTR_2F_X(attrib), 2);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ break;
+ case 1:
+ so_method(so, curie, NV40TCL_VTX_ATTR_1F(attrib), 1);
+ so_data (so, fui(v[0]));
+ break;
+ default:
+ pipe_buffer_unmap(pscreen, vb->buffer);
+ return FALSE;
+ }
+ }
+ break;
+ default:
+ pipe_buffer_unmap(pscreen, vb->buffer);
+ return FALSE;
+ }
+
+ pipe_buffer_unmap(pscreen, vb->buffer);
+
+ return TRUE;
+}
+
+boolean
+nv40_draw_arrays(struct pipe_context *pipe,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nouveau_channel *chan = nv40->screen->base.channel;
+ unsigned restart;
+
+ nv40_vbo_set_idxbuf(nv40, NULL, 0);
+ if (FORCE_SWTNL || !nv40_state_validate(nv40)) {
+ return nv40_draw_elements_swtnl(pipe, NULL, 0,
+ mode, start, count);
+ }
+
+ while (count) {
+ unsigned vc, nr;
+
+ nv40_state_emit(nv40);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
+ mode, start, count, &restart);
+ if (!vc) {
+ FIRE_RING(NULL);
+ continue;
+ }
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ nr = (vc & 0xff);
+ if (nr) {
+ BEGIN_RING(curie, NV40TCL_VB_VERTEX_BATCH, 1);
+ OUT_RING (((nr - 1) << 24) | start);
+ start += nr;
+ }
+
+ nr = vc >> 8;
+ while (nr) {
+ unsigned push = nr > 2047 ? 2047 : nr;
+
+ nr -= push;
+
+ BEGIN_RING_NI(curie, NV40TCL_VB_VERTEX_BATCH, push);
+ while (push--) {
+ OUT_RING(((0x100 - 1) << 24) | start);
+ start += 0x100;
+ }
+ }
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (0);
+
+ count -= vc;
+ start = restart;
+ }
+
+ pipe->flush(pipe, 0, NULL);
+ return TRUE;
+}
+
+static INLINE void
+nv40_draw_elements_u08(struct nv40_context *nv40, void *ib,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nouveau_channel *chan = nv40->screen->base.channel;
+
+ while (count) {
+ uint8_t *elts = (uint8_t *)ib + start;
+ unsigned vc, push, restart;
+
+ nv40_state_emit(nv40);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
+ mode, start, count, &restart);
+ if (vc == 0) {
+ FIRE_RING(NULL);
+ continue;
+ }
+ count -= vc;
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ if (vc & 1) {
+ BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
+ OUT_RING (elts[0]);
+ elts++; vc--;
+ }
+
+ while (vc) {
+ unsigned i;
+
+ push = MIN2(vc, 2047 * 2);
+
+ BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push >> 1);
+ for (i = 0; i < push; i+=2)
+ OUT_RING((elts[i+1] << 16) | elts[i]);
+
+ vc -= push;
+ elts += push;
+ }
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (0);
+
+ start = restart;
+ }
+}
+
+static INLINE void
+nv40_draw_elements_u16(struct nv40_context *nv40, void *ib,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nouveau_channel *chan = nv40->screen->base.channel;
+
+ while (count) {
+ uint16_t *elts = (uint16_t *)ib + start;
+ unsigned vc, push, restart;
+
+ nv40_state_emit(nv40);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
+ mode, start, count, &restart);
+ if (vc == 0) {
+ FIRE_RING(NULL);
+ continue;
+ }
+ count -= vc;
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ if (vc & 1) {
+ BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
+ OUT_RING (elts[0]);
+ elts++; vc--;
+ }
+
+ while (vc) {
+ unsigned i;
+
+ push = MIN2(vc, 2047 * 2);
+
+ BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push >> 1);
+ for (i = 0; i < push; i+=2)
+ OUT_RING((elts[i+1] << 16) | elts[i]);
+
+ vc -= push;
+ elts += push;
+ }
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (0);
+
+ start = restart;
+ }
+}
+
+static INLINE void
+nv40_draw_elements_u32(struct nv40_context *nv40, void *ib,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nouveau_channel *chan = nv40->screen->base.channel;
+
+ while (count) {
+ uint32_t *elts = (uint32_t *)ib + start;
+ unsigned vc, push, restart;
+
+ nv40_state_emit(nv40);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1,
+ mode, start, count, &restart);
+ if (vc == 0) {
+ FIRE_RING(NULL);
+ continue;
+ }
+ count -= vc;
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ while (vc) {
+ push = MIN2(vc, 2047);
+
+ BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U32, push);
+ OUT_RINGp (elts, push);
+
+ vc -= push;
+ elts += push;
+ }
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (0);
+
+ start = restart;
+ }
+}
+
+static boolean
+nv40_draw_elements_inline(struct pipe_context *pipe,
+ struct pipe_buffer *ib, unsigned ib_size,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct pipe_screen *pscreen = pipe->screen;
+ void *map;
+
+ map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ);
+ if (!ib) {
+ NOUVEAU_ERR("failed mapping ib\n");
+ return FALSE;
+ }
+
+ switch (ib_size) {
+ case 1:
+ nv40_draw_elements_u08(nv40, map, mode, start, count);
+ break;
+ case 2:
+ nv40_draw_elements_u16(nv40, map, mode, start, count);
+ break;
+ case 4:
+ nv40_draw_elements_u32(nv40, map, mode, start, count);
+ break;
+ default:
+ NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
+ break;
+ }
+
+ pipe_buffer_unmap(pscreen, ib);
+ return TRUE;
+}
+
+static boolean
+nv40_draw_elements_vbo(struct pipe_context *pipe,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ struct nouveau_channel *chan = nv40->screen->base.channel;
+ unsigned restart;
+
+ while (count) {
+ unsigned nr, vc;
+
+ nv40_state_emit(nv40);
+
+ vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
+ mode, start, count, &restart);
+ if (!vc) {
+ FIRE_RING(NULL);
+ continue;
+ }
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (nvgl_primitive(mode));
+
+ nr = (vc & 0xff);
+ if (nr) {
+ BEGIN_RING(curie, NV40TCL_VB_INDEX_BATCH, 1);
+ OUT_RING (((nr - 1) << 24) | start);
+ start += nr;
+ }
+
+ nr = vc >> 8;
+ while (nr) {
+ unsigned push = nr > 2047 ? 2047 : nr;
+
+ nr -= push;
+
+ BEGIN_RING_NI(curie, NV40TCL_VB_INDEX_BATCH, push);
+ while (push--) {
+ OUT_RING(((0x100 - 1) << 24) | start);
+ start += 0x100;
+ }
+ }
+
+ BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+ OUT_RING (0);
+
+ count -= vc;
+ start = restart;
+ }
+
+ return TRUE;
+}
+
+boolean
+nv40_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer, unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv40_context *nv40 = nv40_context(pipe);
+ boolean idxbuf;
+
+ idxbuf = nv40_vbo_set_idxbuf(nv40, indexBuffer, indexSize);
+ if (FORCE_SWTNL || !nv40_state_validate(nv40)) {
+ return nv40_draw_elements_swtnl(pipe, NULL, 0,
+ mode, start, count);
+ }
+
+ if (idxbuf) {
+ nv40_draw_elements_vbo(pipe, mode, start, count);
+ } else {
+ nv40_draw_elements_inline(pipe, indexBuffer, indexSize,
+ mode, start, count);
+ }
+
+ pipe->flush(pipe, 0, NULL);
+ return TRUE;
+}
+
+static boolean
+nv40_vbo_validate(struct nv40_context *nv40)
+{
+ struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL;
+ struct nouveau_grobj *curie = nv40->screen->curie;
+ struct pipe_buffer *ib = nv40->idxbuf;
+ unsigned ib_format = nv40->idxbuf_format;
+ unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+ int hw;
+
+ if (nv40->edgeflags) {
+ nv40->fallback_swtnl |= NV40_NEW_ARRAYS;
+ return FALSE;
+ }
+
+ vtxbuf = so_new(20, 18);
+ so_method(vtxbuf, curie, NV40TCL_VTXBUF_ADDRESS(0), nv40->vtxelt_nr);
+ vtxfmt = so_new(17, 0);
+ so_method(vtxfmt, curie, NV40TCL_VTXFMT(0), nv40->vtxelt_nr);
+
+ for (hw = 0; hw < nv40->vtxelt_nr; hw++) {
+ struct pipe_vertex_element *ve;
+ struct pipe_vertex_buffer *vb;
+ unsigned type, ncomp;
+
+ ve = &nv40->vtxelt[hw];
+ vb = &nv40->vtxbuf[ve->vertex_buffer_index];
+
+ if (!vb->stride) {
+ if (!sattr)
+ sattr = so_new(16 * 5, 0);
+
+ if (nv40_vbo_static_attrib(nv40, sattr, hw, ve, vb)) {
+ so_data(vtxbuf, 0);
+ so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
+ continue;
+ }
+ }
+
+ if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) {
+ nv40->fallback_swtnl |= NV40_NEW_ARRAYS;
+ so_ref(NULL, &vtxbuf);
+ so_ref(NULL, &vtxfmt);
+ return FALSE;
+ }
+
+ so_reloc(vtxbuf, nouveau_bo(vb->buffer),
+ vb->buffer_offset + ve->src_offset,
+ vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+ 0, NV40TCL_VTXBUF_ADDRESS_DMA1);
+ so_data (vtxfmt, ((vb->stride << NV40TCL_VTXFMT_STRIDE_SHIFT) |
+ (ncomp << NV40TCL_VTXFMT_SIZE_SHIFT) | type));
+ }
+
+ if (ib) {
+ struct nouveau_bo *bo = nouveau_bo(ib);
+
+ so_method(vtxbuf, curie, NV40TCL_IDXBUF_ADDRESS, 2);
+ so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
+ so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR,
+ 0, NV40TCL_IDXBUF_FORMAT_DMA1);
+ }
+
+ so_method(vtxbuf, curie, 0x1710, 1);
+ so_data (vtxbuf, 0);
+
+ so_ref(vtxbuf, &nv40->state.hw[NV40_STATE_VTXBUF]);
+ so_ref(NULL, &vtxbuf);
+ nv40->state.dirty |= (1ULL << NV40_STATE_VTXBUF);
+ so_ref(vtxfmt, &nv40->state.hw[NV40_STATE_VTXFMT]);
+ so_ref(NULL, &vtxfmt);
+ nv40->state.dirty |= (1ULL << NV40_STATE_VTXFMT);
+ so_ref(sattr, &nv40->state.hw[NV40_STATE_VTXATTR]);
+ so_ref(NULL, &sattr);
+ nv40->state.dirty |= (1ULL << NV40_STATE_VTXATTR);
+ return FALSE;
+}
+
+struct nv40_state_entry nv40_state_vbo = {
+ .validate = nv40_vbo_validate,
+ .dirty = {
+ .pipe = NV40_NEW_ARRAYS,
+ .hw = 0,
+ }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nv40/nv40_vertprog.c
new file mode 100644
index 0000000000..0382dbba8f
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_vertprog.c
@@ -0,0 +1,1069 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+
+#include "nv40_context.h"
+#include "nv40_state.h"
+
+/* TODO (at least...):
+ * 1. Indexed consts + ARL
+ * 3. NV_vp11, NV_vp2, NV_vp3 features
+ * - extra arith opcodes
+ * - branching
+ * - texture sampling
+ * - indexed attribs
+ * - indexed results
+ * 4. bugs
+ */
+
+#define SWZ_X 0
+#define SWZ_Y 1
+#define SWZ_Z 2
+#define SWZ_W 3
+#define MASK_X 8
+#define MASK_Y 4
+#define MASK_Z 2
+#define MASK_W 1
+#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
+#define DEF_SCALE 0
+#define DEF_CTEST 0
+#include "nv40_shader.h"
+
+#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv40_sr_neg((s))
+#define abs(s) nv40_sr_abs((s))
+
+#define NV40_VP_INST_DEST_CLIP(n) ((~0 - 6) + (n))
+
+struct nv40_vpc {
+ struct nv40_vertex_program *vp;
+
+ struct nv40_vertex_program_exec *vpi;
+
+ unsigned r_temps;
+ unsigned r_temps_discard;
+ struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS];
+ struct nv40_sreg *r_address;
+ struct nv40_sreg *r_temp;
+
+ struct nv40_sreg *imm;
+ unsigned nr_imm;
+
+ unsigned hpos_idx;
+};
+
+static struct nv40_sreg
+temp(struct nv40_vpc *vpc)
+{
+ int idx = ffs(~vpc->r_temps) - 1;
+
+ if (idx < 0) {
+ NOUVEAU_ERR("out of temps!!\n");
+ assert(0);
+ return nv40_sr(NV40SR_TEMP, 0);
+ }
+
+ vpc->r_temps |= (1 << idx);
+ vpc->r_temps_discard |= (1 << idx);
+ return nv40_sr(NV40SR_TEMP, idx);
+}
+
+static INLINE void
+release_temps(struct nv40_vpc *vpc)
+{
+ vpc->r_temps &= ~vpc->r_temps_discard;
+ vpc->r_temps_discard = 0;
+}
+
+static struct nv40_sreg
+constant(struct nv40_vpc *vpc, int pipe, float x, float y, float z, float w)
+{
+ struct nv40_vertex_program *vp = vpc->vp;
+ struct nv40_vertex_program_data *vpd;
+ int idx;
+
+ if (pipe >= 0) {
+ for (idx = 0; idx < vp->nr_consts; idx++) {
+ if (vp->consts[idx].index == pipe)
+ return nv40_sr(NV40SR_CONST, idx);
+ }
+ }
+
+ idx = vp->nr_consts++;
+ vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts);
+ vpd = &vp->consts[idx];
+
+ vpd->index = pipe;
+ vpd->value[0] = x;
+ vpd->value[1] = y;
+ vpd->value[2] = z;
+ vpd->value[3] = w;
+ return nv40_sr(NV40SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+ nv40_vp_arith((cc), (s), NV40_VP_INST_##o, (d), (m), (s0), (s1), (s2))
+
+static void
+emit_src(struct nv40_vpc *vpc, uint32_t *hw, int pos, struct nv40_sreg src)
+{
+ struct nv40_vertex_program *vp = vpc->vp;
+ uint32_t sr = 0;
+
+ switch (src.type) {
+ case NV40SR_TEMP:
+ sr |= (NV40_VP_SRC_REG_TYPE_TEMP << NV40_VP_SRC_REG_TYPE_SHIFT);
+ sr |= (src.index << NV40_VP_SRC_TEMP_SRC_SHIFT);
+ break;
+ case NV40SR_INPUT:
+ sr |= (NV40_VP_SRC_REG_TYPE_INPUT <<
+ NV40_VP_SRC_REG_TYPE_SHIFT);
+ vp->ir |= (1 << src.index);
+ hw[1] |= (src.index << NV40_VP_INST_INPUT_SRC_SHIFT);
+ break;
+ case NV40SR_CONST:
+ sr |= (NV40_VP_SRC_REG_TYPE_CONST <<
+ NV40_VP_SRC_REG_TYPE_SHIFT);
+ assert(vpc->vpi->const_index == -1 ||
+ vpc->vpi->const_index == src.index);
+ vpc->vpi->const_index = src.index;
+ break;
+ case NV40SR_NONE:
+ sr |= (NV40_VP_SRC_REG_TYPE_INPUT <<
+ NV40_VP_SRC_REG_TYPE_SHIFT);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (src.negate)
+ sr |= NV40_VP_SRC_NEGATE;
+
+ if (src.abs)
+ hw[0] |= (1 << (21 + pos));
+
+ sr |= ((src.swz[0] << NV40_VP_SRC_SWZ_X_SHIFT) |
+ (src.swz[1] << NV40_VP_SRC_SWZ_Y_SHIFT) |
+ (src.swz[2] << NV40_VP_SRC_SWZ_Z_SHIFT) |
+ (src.swz[3] << NV40_VP_SRC_SWZ_W_SHIFT));
+
+ switch (pos) {
+ case 0:
+ hw[1] |= ((sr & NV40_VP_SRC0_HIGH_MASK) >>
+ NV40_VP_SRC0_HIGH_SHIFT) << NV40_VP_INST_SRC0H_SHIFT;
+ hw[2] |= (sr & NV40_VP_SRC0_LOW_MASK) <<
+ NV40_VP_INST_SRC0L_SHIFT;
+ break;
+ case 1:
+ hw[2] |= sr << NV40_VP_INST_SRC1_SHIFT;
+ break;
+ case 2:
+ hw[2] |= ((sr & NV40_VP_SRC2_HIGH_MASK) >>
+ NV40_VP_SRC2_HIGH_SHIFT) << NV40_VP_INST_SRC2H_SHIFT;
+ hw[3] |= (sr & NV40_VP_SRC2_LOW_MASK) <<
+ NV40_VP_INST_SRC2L_SHIFT;
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+emit_dst(struct nv40_vpc *vpc, uint32_t *hw, int slot, struct nv40_sreg dst)
+{
+ struct nv40_vertex_program *vp = vpc->vp;
+
+ switch (dst.type) {
+ case NV40SR_TEMP:
+ hw[3] |= NV40_VP_INST_DEST_MASK;
+ if (slot == 0) {
+ hw[0] |= (dst.index <<
+ NV40_VP_INST_VEC_DEST_TEMP_SHIFT);
+ } else {
+ hw[3] |= (dst.index <<
+ NV40_VP_INST_SCA_DEST_TEMP_SHIFT);
+ }
+ break;
+ case NV40SR_OUTPUT:
+ switch (dst.index) {
+ case NV40_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break;
+ case NV40_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break;
+ case NV40_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break;
+ case NV40_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break;
+ case NV40_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break;
+ case NV40_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break;
+ case NV40_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break;
+ case NV40_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break;
+ case NV40_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break;
+ case NV40_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break;
+ case NV40_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break;
+ case NV40_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break;
+ case NV40_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break;
+ case NV40_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break;
+ case NV40_VP_INST_DEST_CLIP(0):
+ vp->or |= (1 << 6);
+ vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE0;
+ dst.index = NV40_VP_INST_DEST_FOGC;
+ break;
+ case NV40_VP_INST_DEST_CLIP(1):
+ vp->or |= (1 << 7);
+ vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE1;
+ dst.index = NV40_VP_INST_DEST_FOGC;
+ break;
+ case NV40_VP_INST_DEST_CLIP(2):
+ vp->or |= (1 << 8);
+ vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE2;
+ dst.index = NV40_VP_INST_DEST_FOGC;
+ break;
+ case NV40_VP_INST_DEST_CLIP(3):
+ vp->or |= (1 << 9);
+ vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE3;
+ dst.index = NV40_VP_INST_DEST_PSZ;
+ break;
+ case NV40_VP_INST_DEST_CLIP(4):
+ vp->or |= (1 << 10);
+ vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE4;
+ dst.index = NV40_VP_INST_DEST_PSZ;
+ break;
+ case NV40_VP_INST_DEST_CLIP(5):
+ vp->or |= (1 << 11);
+ vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE5;
+ dst.index = NV40_VP_INST_DEST_PSZ;
+ break;
+ default:
+ break;
+ }
+
+ hw[3] |= (dst.index << NV40_VP_INST_DEST_SHIFT);
+ if (slot == 0) {
+ hw[0] |= NV40_VP_INST_VEC_RESULT;
+ hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20);
+ } else {
+ hw[3] |= NV40_VP_INST_SCA_RESULT;
+ hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+nv40_vp_arith(struct nv40_vpc *vpc, int slot, int op,
+ struct nv40_sreg dst, int mask,
+ struct nv40_sreg s0, struct nv40_sreg s1,
+ struct nv40_sreg s2)
+{
+ struct nv40_vertex_program *vp = vpc->vp;
+ uint32_t *hw;
+
+ vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi));
+ vpc->vpi = &vp->insns[vp->nr_insns - 1];
+ memset(vpc->vpi, 0, sizeof(*vpc->vpi));
+ vpc->vpi->const_index = -1;
+
+ hw = vpc->vpi->data;
+
+ hw[0] |= (NV40_VP_INST_COND_TR << NV40_VP_INST_COND_SHIFT);
+ hw[0] |= ((0 << NV40_VP_INST_COND_SWZ_X_SHIFT) |
+ (1 << NV40_VP_INST_COND_SWZ_Y_SHIFT) |
+ (2 << NV40_VP_INST_COND_SWZ_Z_SHIFT) |
+ (3 << NV40_VP_INST_COND_SWZ_W_SHIFT));
+
+ if (slot == 0) {
+ hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT);
+ hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
+ hw[3] |= (mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT);
+ } else {
+ hw[1] |= (op << NV40_VP_INST_SCA_OPCODE_SHIFT);
+ hw[0] |= (NV40_VP_INST_VEC_DEST_TEMP_MASK | (1 << 20));
+ hw[3] |= (mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT);
+ }
+
+ emit_dst(vpc, hw, slot, dst);
+ emit_src(vpc, hw, 0, s0);
+ emit_src(vpc, hw, 1, s1);
+ emit_src(vpc, hw, 2, s2);
+}
+
+static INLINE struct nv40_sreg
+tgsi_src(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
+ struct nv40_sreg src;
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ src = nv40_sr(NV40SR_INPUT, fsrc->SrcRegister.Index);
+ break;
+ case TGSI_FILE_CONSTANT:
+ src = constant(vpc, fsrc->SrcRegister.Index, 0, 0, 0, 0);
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ src = vpc->imm[fsrc->SrcRegister.Index];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ src = vpc->r_temp[fsrc->SrcRegister.Index];
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ break;
+ }
+
+ src.abs = fsrc->SrcRegisterExtMod.Absolute;
+ src.negate = fsrc->SrcRegister.Negate;
+ src.swz[0] = fsrc->SrcRegister.SwizzleX;
+ src.swz[1] = fsrc->SrcRegister.SwizzleY;
+ src.swz[2] = fsrc->SrcRegister.SwizzleZ;
+ src.swz[3] = fsrc->SrcRegister.SwizzleW;
+ return src;
+}
+
+static INLINE struct nv40_sreg
+tgsi_dst(struct nv40_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
+ struct nv40_sreg dst;
+
+ switch (fdst->DstRegister.File) {
+ case TGSI_FILE_OUTPUT:
+ dst = vpc->r_result[fdst->DstRegister.Index];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ dst = vpc->r_temp[fdst->DstRegister.Index];
+ break;
+ case TGSI_FILE_ADDRESS:
+ dst = vpc->r_address[fdst->DstRegister.Index];
+ break;
+ default:
+ NOUVEAU_ERR("bad dst file\n");
+ break;
+ }
+
+ return dst;
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+ int mask = 0;
+
+ if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
+ if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
+ if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
+ if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
+ return mask;
+}
+
+static boolean
+src_native_swz(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc,
+ struct nv40_sreg *src)
+{
+ const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+ struct nv40_sreg tgsi = tgsi_src(vpc, fsrc);
+ uint mask = 0, zero_mask = 0, one_mask = 0, neg_mask = 0;
+ uint neg[4] = { fsrc->SrcRegisterExtSwz.NegateX,
+ fsrc->SrcRegisterExtSwz.NegateY,
+ fsrc->SrcRegisterExtSwz.NegateZ,
+ fsrc->SrcRegisterExtSwz.NegateW };
+ uint c;
+
+ for (c = 0; c < 4; c++) {
+ switch (tgsi_util_get_full_src_register_extswizzle(fsrc, c)) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ mask |= tgsi_mask(1 << c);
+ break;
+ case TGSI_EXTSWIZZLE_ZERO:
+ zero_mask |= tgsi_mask(1 << c);
+ tgsi.swz[c] = SWZ_X;
+ break;
+ case TGSI_EXTSWIZZLE_ONE:
+ one_mask |= tgsi_mask(1 << c);
+ tgsi.swz[c] = SWZ_X;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (!tgsi.negate && neg[c])
+ neg_mask |= tgsi_mask(1 << c);
+ }
+
+ if (mask == MASK_ALL && !neg_mask)
+ return TRUE;
+
+ *src = temp(vpc);
+
+ if (mask)
+ arith(vpc, 0, OP_MOV, *src, mask, tgsi, none, none);
+
+ if (zero_mask)
+ arith(vpc, 0, OP_SFL, *src, zero_mask, *src, none, none);
+
+ if (one_mask)
+ arith(vpc, 0, OP_STR, *src, one_mask, *src, none, none);
+
+ if (neg_mask) {
+ struct nv40_sreg one = temp(vpc);
+ arith(vpc, 0, OP_STR, one, neg_mask, one, none, none);
+ arith(vpc, 0, OP_MUL, *src, neg_mask, *src, neg(one), none);
+ }
+
+ return FALSE;
+}
+
+static boolean
+nv40_vertprog_parse_instruction(struct nv40_vpc *vpc,
+ const struct tgsi_full_instruction *finst)
+{
+ struct nv40_sreg src[3], dst, tmp;
+ struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+ int mask;
+ int ai = -1, ci = -1, ii = -1;
+ int i;
+
+ if (finst->Instruction.Opcode == TGSI_OPCODE_END)
+ return TRUE;
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+ if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) {
+ src[i] = tgsi_src(vpc, fsrc);
+ }
+ }
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->FullSrcRegisters[i];
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ case TGSI_FILE_CONSTANT:
+ case TGSI_FILE_TEMPORARY:
+ if (!src_native_swz(vpc, fsrc, &src[i]))
+ continue;
+ break;
+ default:
+ break;
+ }
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ if (ai == -1 || ai == fsrc->SrcRegister.Index) {
+ ai = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = temp(vpc);
+ arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ if ((ci == -1 && ii == -1) ||
+ ci == fsrc->SrcRegister.Index) {
+ ci = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = temp(vpc);
+ arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ if ((ci == -1 && ii == -1) ||
+ ii == fsrc->SrcRegister.Index) {
+ ii = fsrc->SrcRegister.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = temp(vpc);
+ arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none);
+ }
+ break;
+ case TGSI_FILE_TEMPORARY:
+ /* handled above */
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ return FALSE;
+ }
+ }
+
+ dst = tgsi_dst(vpc, &finst->FullDstRegisters[0]);
+ mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+
+ switch (finst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none);
+ break;
+ case TGSI_OPCODE_ADD:
+ arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]);
+ break;
+ case TGSI_OPCODE_ARL:
+ arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_DP3:
+ arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DP4:
+ arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DPH:
+ arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_DST:
+ arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_EX2:
+ arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_EXP:
+ arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_FLR:
+ arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_FRC:
+ arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_LG2:
+ arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_LIT:
+ arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_LOG:
+ arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_MAD:
+ arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]);
+ break;
+ case TGSI_OPCODE_MAX:
+ arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MIN:
+ arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_MOV:
+ arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none);
+ break;
+ case TGSI_OPCODE_MUL:
+ arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_POW:
+ tmp = temp(vpc);
+ arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none,
+ swz(src[0], X, X, X, X));
+ arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X),
+ swz(src[1], X, X, X, X), none);
+ arith(vpc, 1, OP_EX2, dst, mask, none, none,
+ swz(tmp, X, X, X, X));
+ break;
+ case TGSI_OPCODE_RCP:
+ arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]);
+ break;
+ case TGSI_OPCODE_RET:
+ break;
+ case TGSI_OPCODE_RSQ:
+ arith(vpc, 1, OP_RSQ, dst, mask, none, none, abs(src[0]));
+ break;
+ case TGSI_OPCODE_SGE:
+ arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SLT:
+ arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none);
+ break;
+ case TGSI_OPCODE_SUB:
+ arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1]));
+ break;
+ case TGSI_OPCODE_XPD:
+ tmp = temp(vpc);
+ arith(vpc, 0, OP_MUL, tmp, mask,
+ swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
+ arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W),
+ swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
+ neg(tmp));
+ break;
+ default:
+ NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+ return FALSE;
+ }
+
+ release_temps(vpc);
+ return TRUE;
+}
+
+static boolean
+nv40_vertprog_parse_decl_output(struct nv40_vpc *vpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ unsigned idx = fdec->DeclarationRange.First;
+ int hw;
+
+ switch (fdec->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ hw = NV40_VP_INST_DEST_POS;
+ vpc->hpos_idx = idx;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ if (fdec->Semantic.SemanticIndex == 0) {
+ hw = NV40_VP_INST_DEST_COL0;
+ } else
+ if (fdec->Semantic.SemanticIndex == 1) {
+ hw = NV40_VP_INST_DEST_COL1;
+ } else {
+ NOUVEAU_ERR("bad colour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_BCOLOR:
+ if (fdec->Semantic.SemanticIndex == 0) {
+ hw = NV40_VP_INST_DEST_BFC0;
+ } else
+ if (fdec->Semantic.SemanticIndex == 1) {
+ hw = NV40_VP_INST_DEST_BFC1;
+ } else {
+ NOUVEAU_ERR("bad bcolour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_FOG:
+ hw = NV40_VP_INST_DEST_FOGC;
+ break;
+ case TGSI_SEMANTIC_PSIZE:
+ hw = NV40_VP_INST_DEST_PSZ;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ if (fdec->Semantic.SemanticIndex <= 7) {
+ hw = NV40_VP_INST_DEST_TC(fdec->Semantic.SemanticIndex);
+ } else {
+ NOUVEAU_ERR("bad generic semantic index\n");
+ return FALSE;
+ }
+ break;
+ default:
+ NOUVEAU_ERR("bad output semantic\n");
+ return FALSE;
+ }
+
+ vpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw);
+ return TRUE;
+}
+
+static boolean
+nv40_vertprog_prepare(struct nv40_vpc *vpc)
+{
+ struct tgsi_parse_context p;
+ int high_temp = -1, high_addr = -1, nr_imm = 0, i;
+
+ tgsi_parse_init(&p, vpc->vp->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&p)) {
+ const union tgsi_full_token *tok = &p.FullToken;
+
+ tgsi_parse_token(&p);
+ switch(tok->Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ nr_imm++;
+ break;
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *fdec;
+
+ fdec = &p.FullToken.FullDeclaration;
+ switch (fdec->Declaration.File) {
+ case TGSI_FILE_TEMPORARY:
+ if (fdec->DeclarationRange.Last > high_temp) {
+ high_temp =
+ fdec->DeclarationRange.Last;
+ }
+ break;
+#if 0 /* this would be nice.. except gallium doesn't track it */
+ case TGSI_FILE_ADDRESS:
+ if (fdec->DeclarationRange.Last > high_addr) {
+ high_addr =
+ fdec->DeclarationRange.Last;
+ }
+ break;
+#endif
+ case TGSI_FILE_OUTPUT:
+ if (!nv40_vertprog_parse_decl_output(vpc, fdec))
+ return FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+#if 1 /* yay, parse instructions looking for address regs instead */
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ const struct tgsi_full_instruction *finst;
+ const struct tgsi_full_dst_register *fdst;
+
+ finst = &p.FullToken.FullInstruction;
+ fdst = &finst->FullDstRegisters[0];
+
+ if (fdst->DstRegister.File == TGSI_FILE_ADDRESS) {
+ if (fdst->DstRegister.Index > high_addr)
+ high_addr = fdst->DstRegister.Index;
+ }
+
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+ tgsi_parse_free(&p);
+
+ if (nr_imm) {
+ vpc->imm = CALLOC(nr_imm, sizeof(struct nv40_sreg));
+ assert(vpc->imm);
+ }
+
+ if (++high_temp) {
+ vpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg));
+ for (i = 0; i < high_temp; i++)
+ vpc->r_temp[i] = temp(vpc);
+ }
+
+ if (++high_addr) {
+ vpc->r_address = CALLOC(high_addr, sizeof(struct nv40_sreg));
+ for (i = 0; i < high_addr; i++)
+ vpc->r_address[i] = temp(vpc);
+ }
+
+ vpc->r_temps_discard = 0;
+ return TRUE;
+}
+
+static void
+nv40_vertprog_translate(struct nv40_context *nv40,
+ struct nv40_vertex_program *vp)
+{
+ struct tgsi_parse_context parse;
+ struct nv40_vpc *vpc = NULL;
+ struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+ int i;
+
+ vpc = CALLOC(1, sizeof(struct nv40_vpc));
+ if (!vpc)
+ return;
+ vpc->vp = vp;
+
+ if (!nv40_vertprog_prepare(vpc)) {
+ FREE(vpc);
+ return;
+ }
+
+ /* Redirect post-transform vertex position to a temp if user clip
+ * planes are enabled. We need to append code the the vtxprog
+ * to handle clip planes later.
+ */
+ if (vp->ucp.nr) {
+ vpc->r_result[vpc->hpos_idx] = temp(vpc);
+ vpc->r_temps_discard = 0;
+ }
+
+ tgsi_parse_init(&parse, vp->pipe.tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ const struct tgsi_full_immediate *imm;
+
+ imm = &parse.FullToken.FullImmediate;
+ assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
+ assert(imm->Immediate.NrTokens == 4 + 1);
+ vpc->imm[vpc->nr_imm++] =
+ constant(vpc, -1,
+ imm->u[0].Float,
+ imm->u[1].Float,
+ imm->u[2].Float,
+ imm->u[3].Float);
+ }
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ const struct tgsi_full_instruction *finst;
+ finst = &parse.FullToken.FullInstruction;
+ if (!nv40_vertprog_parse_instruction(vpc, finst))
+ goto out_err;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Write out HPOS if it was redirected to a temp earlier */
+ if (vpc->r_result[vpc->hpos_idx].type != NV40SR_OUTPUT) {
+ struct nv40_sreg hpos = nv40_sr(NV40SR_OUTPUT,
+ NV40_VP_INST_DEST_POS);
+ struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx];
+
+ arith(vpc, 0, OP_MOV, hpos, MASK_ALL, htmp, none, none);
+ }
+
+ /* Insert code to handle user clip planes */
+ for (i = 0; i < vp->ucp.nr; i++) {
+ struct nv40_sreg cdst = nv40_sr(NV40SR_OUTPUT,
+ NV40_VP_INST_DEST_CLIP(i));
+ struct nv40_sreg ceqn = constant(vpc, -1,
+ nv40->clip.ucp[i][0],
+ nv40->clip.ucp[i][1],
+ nv40->clip.ucp[i][2],
+ nv40->clip.ucp[i][3]);
+ struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx];
+ unsigned mask;
+
+ switch (i) {
+ case 0: case 3: mask = MASK_Y; break;
+ case 1: case 4: mask = MASK_Z; break;
+ case 2: case 5: mask = MASK_W; break;
+ default:
+ NOUVEAU_ERR("invalid clip dist #%d\n", i);
+ goto out_err;
+ }
+
+ arith(vpc, 0, OP_DP4, cdst, mask, htmp, ceqn, none);
+ }
+
+ vp->insns[vp->nr_insns - 1].data[3] |= NV40_VP_INST_LAST;
+ vp->translated = TRUE;
+out_err:
+ tgsi_parse_free(&parse);
+ if (vpc->r_temp)
+ FREE(vpc->r_temp);
+ if (vpc->r_address)
+ FREE(vpc->r_address);
+ if (vpc->imm)
+ FREE(vpc->imm);
+ FREE(vpc);
+}
+
+static boolean
+nv40_vertprog_validate(struct nv40_context *nv40)
+{
+ struct pipe_screen *pscreen = nv40->pipe.screen;
+ struct nouveau_grobj *curie = nv40->screen->curie;
+ struct nv40_vertex_program *vp;
+ struct pipe_buffer *constbuf;
+ boolean upload_code = FALSE, upload_data = FALSE;
+ int i;
+
+ if (nv40->render_mode == HW) {
+ vp = nv40->vertprog;
+ constbuf = nv40->constbuf[PIPE_SHADER_VERTEX];
+
+ if ((nv40->dirty & NV40_NEW_UCP) ||
+ memcmp(&nv40->clip, &vp->ucp, sizeof(vp->ucp))) {
+ nv40_vertprog_destroy(nv40, vp);
+ memcpy(&vp->ucp, &nv40->clip, sizeof(vp->ucp));
+ }
+ } else {
+ vp = nv40->swtnl.vertprog;
+ constbuf = NULL;
+ }
+
+ /* Translate TGSI shader into hw bytecode */
+ if (vp->translated)
+ goto check_gpu_resources;
+
+ nv40->fallback_swtnl &= ~NV40_NEW_VERTPROG;
+ nv40_vertprog_translate(nv40, vp);
+ if (!vp->translated) {
+ nv40->fallback_swtnl |= NV40_NEW_VERTPROG;
+ return FALSE;
+ }
+
+check_gpu_resources:
+ /* Allocate hw vtxprog exec slots */
+ if (!vp->exec) {
+ struct nouveau_resource *heap = nv40->screen->vp_exec_heap;
+ struct nouveau_stateobj *so;
+ uint vplen = vp->nr_insns;
+
+ if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) {
+ while (heap->next && heap->size < vplen) {
+ struct nv40_vertex_program *evict;
+
+ evict = heap->next->priv;
+ nouveau_resource_free(&evict->exec);
+ }
+
+ if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec))
+ assert(0);
+ }
+
+ so = so_new(7, 0);
+ so_method(so, curie, NV40TCL_VP_START_FROM_ID, 1);
+ so_data (so, vp->exec->start);
+ so_method(so, curie, NV40TCL_VP_ATTRIB_EN, 2);
+ so_data (so, vp->ir);
+ so_data (so, vp->or);
+ so_method(so, curie, NV40TCL_CLIP_PLANE_ENABLE, 1);
+ so_data (so, vp->clip_ctrl);
+ so_ref(so, &vp->so);
+ so_ref(NULL, &so);
+
+ upload_code = TRUE;
+ }
+
+ /* Allocate hw vtxprog const slots */
+ if (vp->nr_consts && !vp->data) {
+ struct nouveau_resource *heap = nv40->screen->vp_data_heap;
+
+ if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) {
+ while (heap->next && heap->size < vp->nr_consts) {
+ struct nv40_vertex_program *evict;
+
+ evict = heap->next->priv;
+ nouveau_resource_free(&evict->data);
+ }
+
+ if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data))
+ assert(0);
+ }
+
+ /*XXX: handle this some day */
+ assert(vp->data->start >= vp->data_start_min);
+
+ upload_data = TRUE;
+ if (vp->data_start != vp->data->start)
+ upload_code = TRUE;
+ }
+
+ /* If exec or data segments moved we need to patch the program to
+ * fixup offsets and register IDs.
+ */
+ if (vp->exec_start != vp->exec->start) {
+ for (i = 0; i < vp->nr_insns; i++) {
+ struct nv40_vertex_program_exec *vpi = &vp->insns[i];
+
+ if (vpi->has_branch_offset) {
+ assert(0);
+ }
+ }
+
+ vp->exec_start = vp->exec->start;
+ }
+
+ if (vp->nr_consts && vp->data_start != vp->data->start) {
+ for (i = 0; i < vp->nr_insns; i++) {
+ struct nv40_vertex_program_exec *vpi = &vp->insns[i];
+
+ if (vpi->const_index >= 0) {
+ vpi->data[1] &= ~NV40_VP_INST_CONST_SRC_MASK;
+ vpi->data[1] |=
+ (vpi->const_index + vp->data->start) <<
+ NV40_VP_INST_CONST_SRC_SHIFT;
+
+ }
+ }
+
+ vp->data_start = vp->data->start;
+ }
+
+ /* Update + Upload constant values */
+ if (vp->nr_consts) {
+ float *map = NULL;
+
+ if (constbuf) {
+ map = pipe_buffer_map(pscreen, constbuf,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ }
+
+ for (i = 0; i < vp->nr_consts; i++) {
+ struct nv40_vertex_program_data *vpd = &vp->consts[i];
+
+ if (vpd->index >= 0) {
+ if (!upload_data &&
+ !memcmp(vpd->value, &map[vpd->index * 4],
+ 4 * sizeof(float)))
+ continue;
+ memcpy(vpd->value, &map[vpd->index * 4],
+ 4 * sizeof(float));
+ }
+
+ BEGIN_RING(curie, NV40TCL_VP_UPLOAD_CONST_ID, 5);
+ OUT_RING (i + vp->data->start);
+ OUT_RINGp ((uint32_t *)vpd->value, 4);
+ }
+
+ if (constbuf)
+ pscreen->buffer_unmap(pscreen, constbuf);
+ }
+
+ /* Upload vtxprog */
+ if (upload_code) {
+#if 0
+ for (i = 0; i < vp->nr_insns; i++) {
+ NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[0]);
+ NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[1]);
+ NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[2]);
+ NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[3]);
+ }
+#endif
+ BEGIN_RING(curie, NV40TCL_VP_UPLOAD_FROM_ID, 1);
+ OUT_RING (vp->exec->start);
+ for (i = 0; i < vp->nr_insns; i++) {
+ BEGIN_RING(curie, NV40TCL_VP_UPLOAD_INST(0), 4);
+ OUT_RINGp (vp->insns[i].data, 4);
+ }
+ }
+
+ if (vp->so != nv40->state.hw[NV40_STATE_VERTPROG]) {
+ so_ref(vp->so, &nv40->state.hw[NV40_STATE_VERTPROG]);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp)
+{
+ vp->translated = FALSE;
+
+ if (vp->nr_insns) {
+ FREE(vp->insns);
+ vp->insns = NULL;
+ vp->nr_insns = 0;
+ }
+
+ if (vp->nr_consts) {
+ FREE(vp->consts);
+ vp->consts = NULL;
+ vp->nr_consts = 0;
+ }
+
+ nouveau_resource_free(&vp->exec);
+ vp->exec_start = 0;
+ nouveau_resource_free(&vp->data);
+ vp->data_start = 0;
+ vp->data_start_min = 0;
+
+ vp->ir = vp->or = vp->clip_ctrl = 0;
+ so_ref(NULL, &vp->so);
+}
+
+struct nv40_state_entry nv40_state_vertprog = {
+ .validate = nv40_vertprog_validate,
+ .dirty = {
+ .pipe = NV40_NEW_VERTPROG | NV40_NEW_UCP,
+ .hw = NV40_STATE_VERTPROG,
+ }
+};
+
diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile
new file mode 100644
index 0000000000..612aea28a3
--- /dev/null
+++ b/src/gallium/drivers/nv50/Makefile
@@ -0,0 +1,21 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv50
+
+C_SOURCES = \
+ nv50_clear.c \
+ nv50_context.c \
+ nv50_draw.c \
+ nv50_miptree.c \
+ nv50_query.c \
+ nv50_program.c \
+ nv50_screen.c \
+ nv50_state.c \
+ nv50_state_validate.c \
+ nv50_surface.c \
+ nv50_tex.c \
+ nv50_transfer.c \
+ nv50_vbo.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c
new file mode 100644
index 0000000000..e0b2d2880b
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_clear.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "nv50_context.h"
+
+void
+nv50_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nouveau_channel *chan = nv50->screen->base.channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct pipe_framebuffer_state *fb = &nv50->framebuffer;
+ unsigned mode = 0, i;
+
+ if (!nv50_state_validate(nv50))
+ return;
+
+ if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_COLOR(0), 4);
+ OUT_RING (chan, fui(rgba[0]));
+ OUT_RING (chan, fui(rgba[1]));
+ OUT_RING (chan, fui(rgba[2]));
+ OUT_RING (chan, fui(rgba[3]));
+ mode |= 0x3c;
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_DEPTH, 1);
+ OUT_RING (chan, fui(depth));
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_STENCIL, 1);
+ OUT_RING (chan, stencil & 0xff);
+
+ mode |= 0x03;
+ }
+
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
+ OUT_RING (chan, mode);
+
+ for (i = 1; i < fb->nr_cbufs; i++) {
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
+ OUT_RING (chan, (i << 6) | 0x3c);
+ }
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c
new file mode 100644
index 0000000000..6e8f4f9750
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_context.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION 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 "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "nv50_context.h"
+#include "nv50_screen.h"
+
+static void
+nv50_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nouveau_channel *chan = nv50->screen->base.channel;
+ struct nouveau_grobj *eng2d = nv50->screen->eng2d;
+
+ /* We need this in the ddx for reliable composite, not sure what we're
+ * actually flushing. We generate all our own flushes with flags = 0. */
+ WAIT_RING(chan, 3);
+ BEGIN_RING(chan, eng2d, 0x0110, 1);
+ OUT_RING (chan, 0);
+
+ FIRE_RING(chan);
+}
+
+static void
+nv50_destroy(struct pipe_context *pipe)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ draw_destroy(nv50->draw);
+ FREE(nv50);
+}
+
+
+static void
+nv50_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+}
+
+static unsigned int
+nv50_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static unsigned int
+nv50_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+struct pipe_context *
+nv50_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+ struct pipe_winsys *pipe_winsys = pscreen->winsys;
+ struct nv50_screen *screen = nv50_screen(pscreen);
+ struct nv50_context *nv50;
+
+ nv50 = CALLOC_STRUCT(nv50_context);
+ if (!nv50)
+ return NULL;
+ nv50->screen = screen;
+ nv50->pctx_id = pctx_id;
+
+ nv50->pipe.winsys = pipe_winsys;
+ nv50->pipe.screen = pscreen;
+
+ nv50->pipe.destroy = nv50_destroy;
+
+ nv50->pipe.set_edgeflags = nv50_set_edgeflags;
+ nv50->pipe.draw_arrays = nv50_draw_arrays;
+ nv50->pipe.draw_elements = nv50_draw_elements;
+ nv50->pipe.clear = nv50_clear;
+
+ nv50->pipe.flush = nv50_flush;
+
+ nv50->pipe.is_texture_referenced = nv50_is_texture_referenced;
+ nv50->pipe.is_buffer_referenced = nv50_is_buffer_referenced;
+
+ nv50_init_surface_functions(nv50);
+ nv50_init_state_functions(nv50);
+ nv50_init_query_functions(nv50);
+
+ nv50->draw = draw_create();
+ assert(nv50->draw);
+ draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));
+
+ return &nv50->pipe;
+}
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
new file mode 100644
index 0000000000..1e9e8e49bf
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -0,0 +1,201 @@
+#ifndef __NV50_CONTEXT_H__
+#define __NV50_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+#include "nouveau/nouveau_stateobj.h"
+
+#include "nv50_screen.h"
+#include "nv50_program.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+ fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+ fprintf(stderr, "nouveau: "fmt, ##args);
+
+/* Constant buffer assignment */
+#define NV50_CB_PMISC 0
+#define NV50_CB_PVP 1
+#define NV50_CB_PFP 2
+#define NV50_CB_PGP 3
+#define NV50_CB_TIC 4
+#define NV50_CB_TSC 5
+#define NV50_CB_PUPLOAD 6
+
+#define NV50_NEW_BLEND (1 << 0)
+#define NV50_NEW_ZSA (1 << 1)
+#define NV50_NEW_BLEND_COLOUR (1 << 2)
+#define NV50_NEW_STIPPLE (1 << 3)
+#define NV50_NEW_SCISSOR (1 << 4)
+#define NV50_NEW_VIEWPORT (1 << 5)
+#define NV50_NEW_RASTERIZER (1 << 6)
+#define NV50_NEW_FRAMEBUFFER (1 << 7)
+#define NV50_NEW_VERTPROG (1 << 8)
+#define NV50_NEW_VERTPROG_CB (1 << 9)
+#define NV50_NEW_FRAGPROG (1 << 10)
+#define NV50_NEW_FRAGPROG_CB (1 << 11)
+#define NV50_NEW_ARRAYS (1 << 12)
+#define NV50_NEW_SAMPLER (1 << 13)
+#define NV50_NEW_TEXTURE (1 << 14)
+
+struct nv50_blend_stateobj {
+ struct pipe_blend_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+struct nv50_zsa_stateobj {
+ struct pipe_depth_stencil_alpha_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+struct nv50_rasterizer_stateobj {
+ struct pipe_rasterizer_state pipe;
+ struct nouveau_stateobj *so;
+};
+
+struct nv50_sampler_stateobj {
+ bool normalized;
+ unsigned tsc[8];
+};
+
+struct nv50_miptree_level {
+ int *image_offset;
+ unsigned pitch;
+ unsigned tile_mode;
+};
+
+struct nv50_miptree {
+ struct nouveau_miptree base;
+
+ struct nv50_miptree_level level[PIPE_MAX_TEXTURE_LEVELS];
+ int image_nr;
+ int total_size;
+};
+
+static INLINE struct nv50_miptree *
+nv50_miptree(struct pipe_texture *pt)
+{
+ return (struct nv50_miptree *)pt;
+}
+
+struct nv50_surface {
+ struct pipe_surface base;
+};
+
+static INLINE struct nv50_surface *
+nv50_surface(struct pipe_surface *pt)
+{
+ return (struct nv50_surface *)pt;
+}
+
+struct nv50_state {
+ unsigned dirty;
+
+ struct nouveau_stateobj *fb;
+ struct nouveau_stateobj *blend;
+ struct nouveau_stateobj *blend_colour;
+ struct nouveau_stateobj *zsa;
+ struct nouveau_stateobj *rast;
+ struct nouveau_stateobj *stipple;
+ struct nouveau_stateobj *scissor;
+ unsigned scissor_enabled;
+ struct nouveau_stateobj *viewport;
+ unsigned viewport_bypass;
+ struct nouveau_stateobj *tsc_upload;
+ struct nouveau_stateobj *tic_upload;
+ unsigned miptree_nr;
+ struct nouveau_stateobj *vertprog;
+ struct nouveau_stateobj *fragprog;
+ struct nouveau_stateobj *vtxfmt;
+ struct nouveau_stateobj *vtxbuf;
+ struct nouveau_stateobj *vtxattr;
+};
+
+struct nv50_context {
+ struct pipe_context pipe;
+
+ struct nv50_screen *screen;
+ unsigned pctx_id;
+
+ struct draw_context *draw;
+
+ struct nv50_state state;
+
+ unsigned dirty;
+ struct nv50_blend_stateobj *blend;
+ struct nv50_zsa_stateobj *zsa;
+ struct nv50_rasterizer_stateobj *rasterizer;
+ struct pipe_blend_color blend_colour;
+ struct pipe_poly_stipple stipple;
+ struct pipe_scissor_state scissor;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state framebuffer;
+ struct nv50_program *vertprog;
+ struct nv50_program *fragprog;
+ struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+ struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+ unsigned vtxbuf_nr;
+ struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+ unsigned vtxelt_nr;
+ struct nv50_sampler_stateobj *sampler[PIPE_MAX_SAMPLERS];
+ unsigned sampler_nr;
+ struct nv50_miptree *miptree[PIPE_MAX_SAMPLERS];
+ unsigned miptree_nr;
+};
+
+static INLINE struct nv50_context *
+nv50_context(struct pipe_context *pipe)
+{
+ return (struct nv50_context *)pipe;
+}
+
+extern void nv50_init_surface_functions(struct nv50_context *nv50);
+extern void nv50_init_state_functions(struct nv50_context *nv50);
+extern void nv50_init_query_functions(struct nv50_context *nv50);
+
+extern void nv50_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+extern int
+nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst,
+ int dx, int dy, struct pipe_surface *src, int sx, int sy,
+ int w, int h);
+
+/* nv50_draw.c */
+extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *nv50);
+
+/* nv50_vbo.c */
+extern boolean nv50_draw_arrays(struct pipe_context *, unsigned mode,
+ unsigned start, unsigned count);
+extern boolean nv50_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start,
+ unsigned count);
+extern void nv50_vbo_validate(struct nv50_context *nv50);
+
+/* nv50_clear.c */
+extern void nv50_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil);
+
+/* nv50_program.c */
+extern void nv50_vertprog_validate(struct nv50_context *nv50);
+extern void nv50_fragprog_validate(struct nv50_context *nv50);
+extern void nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p);
+
+/* nv50_state_validate.c */
+extern boolean nv50_state_validate(struct nv50_context *nv50);
+
+/* nv50_tex.c */
+extern void nv50_tex_validate(struct nv50_context *);
+
+#endif
diff --git a/src/gallium/drivers/nv50/nv50_draw.c b/src/gallium/drivers/nv50/nv50_draw.c
new file mode 100644
index 0000000000..2f6f607261
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_draw.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION 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 "draw/draw_pipe.h"
+
+#include "nv50_context.h"
+
+struct nv50_render_stage {
+ struct draw_stage stage;
+ struct nv50_context *nv50;
+};
+
+static INLINE struct nv50_render_stage *
+nv50_render_stage(struct draw_stage *stage)
+{
+ return (struct nv50_render_stage *)stage;
+}
+
+static void
+nv50_render_point(struct draw_stage *stage, struct prim_header *prim)
+{
+ NOUVEAU_ERR("\n");
+}
+
+static void
+nv50_render_line(struct draw_stage *stage, struct prim_header *prim)
+{
+ NOUVEAU_ERR("\n");
+}
+
+static void
+nv50_render_tri(struct draw_stage *stage, struct prim_header *prim)
+{
+ NOUVEAU_ERR("\n");
+}
+
+static void
+nv50_render_flush(struct draw_stage *stage, unsigned flags)
+{
+}
+
+static void
+nv50_render_reset_stipple_counter(struct draw_stage *stage)
+{
+ NOUVEAU_ERR("\n");
+}
+
+static void
+nv50_render_destroy(struct draw_stage *stage)
+{
+ FREE(stage);
+}
+
+struct draw_stage *
+nv50_draw_render_stage(struct nv50_context *nv50)
+{
+ struct nv50_render_stage *rs = CALLOC_STRUCT(nv50_render_stage);
+
+ rs->nv50 = nv50;
+ rs->stage.draw = nv50->draw;
+ rs->stage.destroy = nv50_render_destroy;
+ rs->stage.point = nv50_render_point;
+ rs->stage.line = nv50_render_line;
+ rs->stage.tri = nv50_render_tri;
+ rs->stage.flush = nv50_render_flush;
+ rs->stage.reset_stipple_counter = nv50_render_reset_stipple_counter;
+
+ return &rs->stage;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
new file mode 100644
index 0000000000..93479a0314
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "nv50_context.h"
+
+static struct pipe_texture *
+nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
+ struct pipe_texture *pt = &mt->base.base;
+ unsigned width = tmp->width[0], height = tmp->height[0];
+ unsigned depth = tmp->depth[0];
+ uint32_t tile_mode, tile_flags, tile_h;
+ int ret, i, l;
+
+ *pt = *tmp;
+ pipe_reference_init(&pt->reference, 1);
+ pt->screen = pscreen;
+
+ switch (pt->format) {
+ case PIPE_FORMAT_Z32_FLOAT:
+ tile_flags = 0x4800;
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ tile_flags = 0x1800;
+ break;
+ case PIPE_FORMAT_X8Z24_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ tile_flags = 0x2800;
+ break;
+ default:
+ tile_flags = 0x7000;
+ break;
+ }
+
+ if (pt->height[0] > 32) tile_mode = 4;
+ else if (pt->height[0] > 16) tile_mode = 3;
+ else if (pt->height[0] > 8) tile_mode = 2;
+ else if (pt->height[0] > 4) tile_mode = 1;
+ else tile_mode = 0;
+ tile_h = 1 << (tile_mode + 2);
+
+ switch (pt->target) {
+ case PIPE_TEXTURE_3D:
+ mt->image_nr = pt->depth[0];
+ break;
+ case PIPE_TEXTURE_CUBE:
+ mt->image_nr = 6;
+ break;
+ default:
+ mt->image_nr = 1;
+ break;
+ }
+
+ for (l = 0; l <= pt->last_level; l++) {
+ struct nv50_miptree_level *lvl = &mt->level[l];
+
+ pt->width[l] = width;
+ pt->height[l] = height;
+ pt->depth[l] = depth;
+ pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+ pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+
+ lvl->image_offset = CALLOC(mt->image_nr, sizeof(int));
+ lvl->pitch = align(pt->width[l] * pt->block.size, 64);
+ lvl->tile_mode = tile_mode;
+
+ width = MAX2(1, width >> 1);
+ height = MAX2(1, height >> 1);
+ depth = MAX2(1, depth >> 1);
+
+ if (tile_mode && height <= (tile_h >> 1)) {
+ tile_mode--;
+ tile_h >>= 1;
+ }
+ }
+
+ for (i = 0; i < mt->image_nr; i++) {
+ for (l = 0; l <= pt->last_level; l++) {
+ struct nv50_miptree_level *lvl = &mt->level[l];
+ int size;
+ tile_h = 1 << (lvl->tile_mode + 2);
+
+ size = align(pt->width[l], 8) * pt->block.size;
+ size = align(size, 64);
+ size *= align(pt->height[l], tile_h);
+
+ lvl->image_offset[i] = mt->total_size;
+
+ mt->total_size += size;
+ }
+ }
+
+ ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size,
+ mt->level[0].tile_mode, tile_flags,
+ &mt->base.bo);
+ if (ret) {
+ FREE(mt);
+ return NULL;
+ }
+
+ return pt;
+}
+
+static struct pipe_texture *
+nv50_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt,
+ const unsigned *stride, struct pipe_buffer *pb)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+ struct nv50_miptree *mt;
+
+ /* Only supports 2D, non-mipmapped textures for the moment */
+ if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 ||
+ pt->depth[0] != 1)
+ return NULL;
+
+ mt = CALLOC_STRUCT(nv50_miptree);
+ if (!mt)
+ return NULL;
+
+ mt->base.base = *pt;
+ pipe_reference_init(&mt->base.base.reference, 1);
+ mt->base.base.screen = pscreen;
+ mt->image_nr = 1;
+ mt->level[0].pitch = *stride;
+ mt->level[0].image_offset = CALLOC(1, sizeof(unsigned));
+ mt->level[0].tile_mode = bo->tile_mode;
+
+ nouveau_bo_ref(bo, &mt->base.bo);
+ return &mt->base.base;
+}
+
+static void
+nv50_miptree_destroy(struct pipe_texture *pt)
+{
+ struct nv50_miptree *mt = nv50_miptree(pt);
+
+ nouveau_bo_ref(NULL, &mt->base.bo);
+ FREE(mt);
+}
+
+static struct pipe_surface *
+nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned flags)
+{
+ struct nv50_miptree *mt = nv50_miptree(pt);
+ struct nv50_miptree_level *lvl = &mt->level[level];
+ struct pipe_surface *ps;
+ int img;
+
+ if (pt->target == PIPE_TEXTURE_CUBE)
+ img = face;
+ else
+ if (pt->target == PIPE_TEXTURE_3D)
+ img = zslice;
+ else
+ img = 0;
+
+ ps = CALLOC_STRUCT(pipe_surface);
+ if (!ps)
+ return NULL;
+ pipe_texture_reference(&ps->texture, pt);
+ ps->format = pt->format;
+ ps->width = pt->width[level];
+ ps->height = pt->height[level];
+ ps->usage = flags;
+ pipe_reference_init(&ps->reference, 1);
+ ps->face = face;
+ ps->level = level;
+ ps->zslice = zslice;
+ ps->offset = lvl->image_offset[img];
+
+ return ps;
+}
+
+static void
+nv50_miptree_surface_del(struct pipe_surface *ps)
+{
+ struct nv50_surface *s = nv50_surface(ps);
+
+ pipe_texture_reference(&ps->texture, NULL);
+ FREE(s);
+}
+
+void
+nv50_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+ pscreen->texture_create = nv50_miptree_create;
+ pscreen->texture_blanket = nv50_miptree_blanket;
+ pscreen->texture_destroy = nv50_miptree_destroy;
+ pscreen->get_tex_surface = nv50_miptree_surface_new;
+ pscreen->tex_surface_destroy = nv50_miptree_surface_del;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
new file mode 100644
index 0000000000..4a838529de
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -0,0 +1,2482 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+
+#include "nv50_context.h"
+
+#define NV50_SU_MAX_TEMP 64
+//#define NV50_PROGRAM_DUMP
+
+/* ARL - gallium craps itself on progs/vp/arl.txt
+ *
+ * MSB - Like MAD, but MUL+SUB
+ * - Fuck it off, introduce a way to negate args for ops that
+ * support it.
+ *
+ * Look into inlining IMMD for ops other than MOV (make it general?)
+ * - Maybe even relax restrictions a bit, can't do P_RESULT + P_IMMD,
+ * but can emit to P_TEMP first - then MOV later. NVIDIA does this
+ *
+ * In ops such as ADD it's possible to construct a bad opcode in the !is_long()
+ * case, if the emit_src() causes the inst to suddenly become long.
+ *
+ * Verify half-insns work where expected - and force disable them where they
+ * don't work - MUL has it forcibly disabled atm as it fixes POW..
+ *
+ * FUCK! watch dst==src vectors, can overwrite components that are needed.
+ * ie. SUB R0, R0.yzxw, R0
+ *
+ * Things to check with renouveau:
+ * FP attr/result assignment - how?
+ * attrib
+ * - 0x16bc maps vp output onto fp hpos
+ * - 0x16c0 maps vp output onto fp col0
+ * result
+ * - colr always 0-3
+ * - depr always 4
+ * 0x16bc->0x16e8 --> some binding between vp/fp regs
+ * 0x16b8 --> VP output count
+ *
+ * 0x1298 --> "MOV rcol.x, fcol.y" "MOV depr, fcol.y" = 0x00000005
+ * "MOV rcol.x, fcol.y" = 0x00000004
+ * 0x19a8 --> as above but 0x00000100 and 0x00000000
+ * - 0x00100000 used when KIL used
+ * 0x196c --> as above but 0x00000011 and 0x00000000
+ *
+ * 0x1988 --> 0xXXNNNNNN
+ * - XX == FP high something
+ */
+struct nv50_reg {
+ enum {
+ P_TEMP,
+ P_ATTR,
+ P_RESULT,
+ P_CONST,
+ P_IMMD
+ } type;
+ int index;
+
+ int hw;
+ int neg;
+
+ int rhw; /* result hw for FP outputs, or interpolant index */
+ int acc; /* instruction where this reg is last read (first insn == 1) */
+};
+
+struct nv50_pc {
+ struct nv50_program *p;
+
+ /* hw resources */
+ struct nv50_reg *r_temp[NV50_SU_MAX_TEMP];
+
+ /* tgsi resources */
+ struct nv50_reg *temp;
+ int temp_nr;
+ struct nv50_reg *attr;
+ int attr_nr;
+ struct nv50_reg *result;
+ int result_nr;
+ struct nv50_reg *param;
+ int param_nr;
+ struct nv50_reg *immd;
+ float *immd_buf;
+ int immd_nr;
+
+ struct nv50_reg *temp_temp[16];
+ unsigned temp_temp_nr;
+
+ unsigned interp_mode[32];
+ /* perspective interpolation registers */
+ struct nv50_reg *iv_p;
+ struct nv50_reg *iv_c;
+
+ /* current instruction and total number of insns */
+ unsigned insn_cur;
+ unsigned insn_nr;
+
+ boolean allow32;
+};
+
+static void
+alloc_reg(struct nv50_pc *pc, struct nv50_reg *reg)
+{
+ int i = 0;
+
+ if (reg->type == P_RESULT) {
+ if (pc->p->cfg.high_result < (reg->hw + 1))
+ pc->p->cfg.high_result = reg->hw + 1;
+ }
+
+ if (reg->type != P_TEMP)
+ return;
+
+ if (reg->hw >= 0) {
+ /*XXX: do this here too to catch FP temp-as-attr usage..
+ * not clean, but works */
+ if (pc->p->cfg.high_temp < (reg->hw + 1))
+ pc->p->cfg.high_temp = reg->hw + 1;
+ return;
+ }
+
+ if (reg->rhw != -1) {
+ /* try to allocate temporary with index rhw first */
+ if (!(pc->r_temp[reg->rhw])) {
+ pc->r_temp[reg->rhw] = reg;
+ reg->hw = reg->rhw;
+ if (pc->p->cfg.high_temp < (reg->rhw + 1))
+ pc->p->cfg.high_temp = reg->rhw + 1;
+ return;
+ }
+ /* make sure we don't get things like $r0 needs to go
+ * in $r1 and $r1 in $r0
+ */
+ i = pc->result_nr * 4;
+ }
+
+ for (; i < NV50_SU_MAX_TEMP; i++) {
+ if (!(pc->r_temp[i])) {
+ pc->r_temp[i] = reg;
+ reg->hw = i;
+ if (pc->p->cfg.high_temp < (i + 1))
+ pc->p->cfg.high_temp = i + 1;
+ return;
+ }
+ }
+
+ assert(0);
+}
+
+static struct nv50_reg *
+alloc_temp(struct nv50_pc *pc, struct nv50_reg *dst)
+{
+ struct nv50_reg *r;
+ int i;
+
+ if (dst && dst->type == P_TEMP && dst->hw == -1)
+ return dst;
+
+ for (i = 0; i < NV50_SU_MAX_TEMP; i++) {
+ if (!pc->r_temp[i]) {
+ r = CALLOC_STRUCT(nv50_reg);
+ r->type = P_TEMP;
+ r->index = -1;
+ r->hw = i;
+ r->rhw = -1;
+ pc->r_temp[i] = r;
+ return r;
+ }
+ }
+
+ assert(0);
+ return NULL;
+}
+
+/* Assign the hw of the discarded temporary register src
+ * to the tgsi register dst and free src.
+ */
+static void
+assimilate_temp(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+ assert(src->index == -1 && src->hw != -1);
+
+ if (dst->hw != -1)
+ pc->r_temp[dst->hw] = NULL;
+ pc->r_temp[src->hw] = dst;
+ dst->hw = src->hw;
+
+ FREE(src);
+}
+
+/* release the hardware resource held by r */
+static void
+release_hw(struct nv50_pc *pc, struct nv50_reg *r)
+{
+ assert(r->type == P_TEMP);
+ if (r->hw == -1)
+ return;
+
+ assert(pc->r_temp[r->hw] == r);
+ pc->r_temp[r->hw] = NULL;
+
+ r->acc = 0;
+ if (r->index == -1)
+ FREE(r);
+}
+
+static void
+free_temp(struct nv50_pc *pc, struct nv50_reg *r)
+{
+ if (r->index == -1) {
+ unsigned hw = r->hw;
+
+ FREE(pc->r_temp[hw]);
+ pc->r_temp[hw] = NULL;
+ }
+}
+
+static int
+alloc_temp4(struct nv50_pc *pc, struct nv50_reg *dst[4], int idx)
+{
+ int i;
+
+ if ((idx + 4) >= NV50_SU_MAX_TEMP)
+ return 1;
+
+ if (pc->r_temp[idx] || pc->r_temp[idx + 1] ||
+ pc->r_temp[idx + 2] || pc->r_temp[idx + 3])
+ return alloc_temp4(pc, dst, idx + 4);
+
+ for (i = 0; i < 4; i++) {
+ dst[i] = CALLOC_STRUCT(nv50_reg);
+ dst[i]->type = P_TEMP;
+ dst[i]->index = -1;
+ dst[i]->hw = idx + i;
+ pc->r_temp[idx + i] = dst[i];
+ }
+
+ return 0;
+}
+
+static void
+free_temp4(struct nv50_pc *pc, struct nv50_reg *reg[4])
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ free_temp(pc, reg[i]);
+}
+
+static struct nv50_reg *
+temp_temp(struct nv50_pc *pc)
+{
+ if (pc->temp_temp_nr >= 16)
+ assert(0);
+
+ pc->temp_temp[pc->temp_temp_nr] = alloc_temp(pc, NULL);
+ return pc->temp_temp[pc->temp_temp_nr++];
+}
+
+static void
+kill_temp_temp(struct nv50_pc *pc)
+{
+ int i;
+
+ for (i = 0; i < pc->temp_temp_nr; i++)
+ free_temp(pc, pc->temp_temp[i]);
+ pc->temp_temp_nr = 0;
+}
+
+static int
+ctor_immd(struct nv50_pc *pc, float x, float y, float z, float w)
+{
+ pc->immd_buf = REALLOC(pc->immd_buf, (pc->immd_nr * 4 * sizeof(float)),
+ (pc->immd_nr + 1) * 4 * sizeof(float));
+ pc->immd_buf[(pc->immd_nr * 4) + 0] = x;
+ pc->immd_buf[(pc->immd_nr * 4) + 1] = y;
+ pc->immd_buf[(pc->immd_nr * 4) + 2] = z;
+ pc->immd_buf[(pc->immd_nr * 4) + 3] = w;
+
+ return pc->immd_nr++;
+}
+
+static struct nv50_reg *
+alloc_immd(struct nv50_pc *pc, float f)
+{
+ struct nv50_reg *r = CALLOC_STRUCT(nv50_reg);
+ unsigned hw;
+
+ for (hw = 0; hw < pc->immd_nr * 4; hw++)
+ if (pc->immd_buf[hw] == f)
+ break;
+
+ if (hw == pc->immd_nr * 4)
+ hw = ctor_immd(pc, f, -f, 0.5 * f, 0) * 4;
+
+ r->type = P_IMMD;
+ r->hw = hw;
+ r->index = -1;
+ return r;
+}
+
+static struct nv50_program_exec *
+exec(struct nv50_pc *pc)
+{
+ struct nv50_program_exec *e = CALLOC_STRUCT(nv50_program_exec);
+
+ e->param.index = -1;
+ return e;
+}
+
+static void
+emit(struct nv50_pc *pc, struct nv50_program_exec *e)
+{
+ struct nv50_program *p = pc->p;
+
+ if (p->exec_tail)
+ p->exec_tail->next = e;
+ if (!p->exec_head)
+ p->exec_head = e;
+ p->exec_tail = e;
+ p->exec_size += (e->inst[0] & 1) ? 2 : 1;
+}
+
+static INLINE void set_long(struct nv50_pc *, struct nv50_program_exec *);
+
+static boolean
+is_long(struct nv50_program_exec *e)
+{
+ if (e->inst[0] & 1)
+ return TRUE;
+ return FALSE;
+}
+
+static boolean
+is_immd(struct nv50_program_exec *e)
+{
+ if (is_long(e) && (e->inst[1] & 3) == 3)
+ return TRUE;
+ return FALSE;
+}
+
+static INLINE void
+set_pred(struct nv50_pc *pc, unsigned pred, unsigned idx,
+ struct nv50_program_exec *e)
+{
+ set_long(pc, e);
+ e->inst[1] &= ~((0x1f << 7) | (0x3 << 12));
+ e->inst[1] |= (pred << 7) | (idx << 12);
+}
+
+static INLINE void
+set_pred_wr(struct nv50_pc *pc, unsigned on, unsigned idx,
+ struct nv50_program_exec *e)
+{
+ set_long(pc, e);
+ e->inst[1] &= ~((0x3 << 4) | (1 << 6));
+ e->inst[1] |= (idx << 4) | (on << 6);
+}
+
+static INLINE void
+set_long(struct nv50_pc *pc, struct nv50_program_exec *e)
+{
+ if (is_long(e))
+ return;
+
+ e->inst[0] |= 1;
+ set_pred(pc, 0xf, 0, e);
+ set_pred_wr(pc, 0, 0, e);
+}
+
+static INLINE void
+set_dst(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_program_exec *e)
+{
+ if (dst->type == P_RESULT) {
+ set_long(pc, e);
+ e->inst[1] |= 0x00000008;
+ }
+
+ alloc_reg(pc, dst);
+ e->inst[0] |= (dst->hw << 2);
+}
+
+static INLINE void
+set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e)
+{
+ float f = pc->immd_buf[imm->hw];
+ unsigned val = fui(imm->neg ? -f : f);
+
+ set_long(pc, e);
+ /*XXX: can't be predicated - bits overlap.. catch cases where both
+ * are required and avoid them. */
+ set_pred(pc, 0, 0, e);
+ set_pred_wr(pc, 0, 0, e);
+
+ e->inst[1] |= 0x00000002 | 0x00000001;
+ e->inst[0] |= (val & 0x3f) << 16;
+ e->inst[1] |= (val >> 6) << 2;
+}
+
+
+#define INTERP_LINEAR 0
+#define INTERP_FLAT 1
+#define INTERP_PERSPECTIVE 2
+#define INTERP_CENTROID 4
+
+/* interpolant index has been stored in dst->rhw */
+static void
+emit_interp(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *iv,
+ unsigned mode)
+{
+ assert(dst->rhw != -1);
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] |= 0x80000000;
+ set_dst(pc, dst, e);
+ e->inst[0] |= (dst->rhw << 16);
+
+ if (mode & INTERP_FLAT) {
+ e->inst[0] |= (1 << 8);
+ } else {
+ if (mode & INTERP_PERSPECTIVE) {
+ e->inst[0] |= (1 << 25);
+ alloc_reg(pc, iv);
+ e->inst[0] |= (iv->hw << 9);
+ }
+
+ if (mode & INTERP_CENTROID)
+ e->inst[0] |= (1 << 24);
+ }
+
+ emit(pc, e);
+}
+
+static void
+set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s,
+ struct nv50_program_exec *e)
+{
+ set_long(pc, e);
+
+ e->param.index = src->hw;
+ e->param.shift = s;
+ e->param.mask = m << (s % 32);
+
+ e->inst[1] |= (((src->type == P_IMMD) ? 0 : 1) << 22);
+}
+
+static void
+emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] |= 0x10000000;
+
+ set_dst(pc, dst, e);
+
+ if (pc->allow32 && dst->type != P_RESULT && src->type == P_IMMD) {
+ set_immd(pc, src, e);
+ /*XXX: 32-bit, but steals part of "half" reg space - need to
+ * catch and handle this case if/when we do half-regs
+ */
+ } else
+ if (src->type == P_IMMD || src->type == P_CONST) {
+ set_long(pc, e);
+ set_data(pc, src, 0x7f, 9, e);
+ e->inst[1] |= 0x20000000; /* src0 const? */
+ } else {
+ if (src->type == P_ATTR) {
+ set_long(pc, e);
+ e->inst[1] |= 0x00200000;
+ }
+
+ alloc_reg(pc, src);
+ e->inst[0] |= (src->hw << 9);
+ }
+
+ if (is_long(e) && !is_immd(e)) {
+ e->inst[1] |= 0x04000000; /* 32-bit */
+ e->inst[1] |= 0x0000c000; /* "subsubop" 0x3 */
+ if (!(e->inst[1] & 0x20000000))
+ e->inst[1] |= 0x00030000; /* "subsubop" 0xf */
+ } else
+ e->inst[0] |= 0x00008000;
+
+ emit(pc, e);
+}
+
+static INLINE void
+emit_mov_immdval(struct nv50_pc *pc, struct nv50_reg *dst, float f)
+{
+ struct nv50_reg *imm = alloc_immd(pc, f);
+ emit_mov(pc, dst, imm);
+ FREE(imm);
+}
+
+static boolean
+check_swap_src_0_1(struct nv50_pc *pc,
+ struct nv50_reg **s0, struct nv50_reg **s1)
+{
+ struct nv50_reg *src0 = *s0, *src1 = *s1;
+
+ if (src0->type == P_CONST) {
+ if (src1->type != P_CONST) {
+ *s0 = src1;
+ *s1 = src0;
+ return TRUE;
+ }
+ } else
+ if (src1->type == P_ATTR) {
+ if (src0->type != P_ATTR) {
+ *s0 = src1;
+ *s1 = src0;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+set_src_0(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
+{
+ if (src->type == P_ATTR) {
+ set_long(pc, e);
+ e->inst[1] |= 0x00200000;
+ } else
+ if (src->type == P_CONST || src->type == P_IMMD) {
+ struct nv50_reg *temp = temp_temp(pc);
+
+ emit_mov(pc, temp, src);
+ src = temp;
+ }
+
+ alloc_reg(pc, src);
+ e->inst[0] |= (src->hw << 9);
+}
+
+static void
+set_src_1(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
+{
+ if (src->type == P_ATTR) {
+ struct nv50_reg *temp = temp_temp(pc);
+
+ emit_mov(pc, temp, src);
+ src = temp;
+ } else
+ if (src->type == P_CONST || src->type == P_IMMD) {
+ assert(!(e->inst[0] & 0x00800000));
+ if (e->inst[0] & 0x01000000) {
+ struct nv50_reg *temp = temp_temp(pc);
+
+ emit_mov(pc, temp, src);
+ src = temp;
+ } else {
+ set_data(pc, src, 0x7f, 16, e);
+ e->inst[0] |= 0x00800000;
+ }
+ }
+
+ alloc_reg(pc, src);
+ e->inst[0] |= (src->hw << 16);
+}
+
+static void
+set_src_2(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
+{
+ set_long(pc, e);
+
+ if (src->type == P_ATTR) {
+ struct nv50_reg *temp = temp_temp(pc);
+
+ emit_mov(pc, temp, src);
+ src = temp;
+ } else
+ if (src->type == P_CONST || src->type == P_IMMD) {
+ assert(!(e->inst[0] & 0x01000000));
+ if (e->inst[0] & 0x00800000) {
+ struct nv50_reg *temp = temp_temp(pc);
+
+ emit_mov(pc, temp, src);
+ src = temp;
+ } else {
+ set_data(pc, src, 0x7f, 32+14, e);
+ e->inst[0] |= 0x01000000;
+ }
+ }
+
+ alloc_reg(pc, src);
+ e->inst[1] |= (src->hw << 14);
+}
+
+static void
+emit_mul(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
+ struct nv50_reg *src1)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] |= 0xc0000000;
+
+ if (!pc->allow32)
+ set_long(pc, e);
+
+ check_swap_src_0_1(pc, &src0, &src1);
+ set_dst(pc, dst, e);
+ set_src_0(pc, src0, e);
+ if (src1->type == P_IMMD && !is_long(e)) {
+ if (src0->neg)
+ e->inst[0] |= 0x00008000;
+ set_immd(pc, src1, e);
+ } else {
+ set_src_1(pc, src1, e);
+ if (src0->neg ^ src1->neg) {
+ if (is_long(e))
+ e->inst[1] |= 0x08000000;
+ else
+ e->inst[0] |= 0x00008000;
+ }
+ }
+
+ emit(pc, e);
+}
+
+static void
+emit_add(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *src0, struct nv50_reg *src1)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] |= 0xb0000000;
+
+ check_swap_src_0_1(pc, &src0, &src1);
+
+ if (!pc->allow32 || src0->neg || src1->neg) {
+ set_long(pc, e);
+ e->inst[1] |= (src0->neg << 26) | (src1->neg << 27);
+ }
+
+ set_dst(pc, dst, e);
+ set_src_0(pc, src0, e);
+ if (src1->type == P_CONST || src1->type == P_ATTR || is_long(e))
+ set_src_2(pc, src1, e);
+ else
+ if (src1->type == P_IMMD)
+ set_immd(pc, src1, e);
+ else
+ set_src_1(pc, src1, e);
+
+ emit(pc, e);
+}
+
+static void
+emit_minmax(struct nv50_pc *pc, unsigned sub, struct nv50_reg *dst,
+ struct nv50_reg *src0, struct nv50_reg *src1)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ set_long(pc, e);
+ e->inst[0] |= 0xb0000000;
+ e->inst[1] |= (sub << 29);
+
+ check_swap_src_0_1(pc, &src0, &src1);
+ set_dst(pc, dst, e);
+ set_src_0(pc, src0, e);
+ set_src_1(pc, src1, e);
+
+ emit(pc, e);
+}
+
+static INLINE void
+emit_sub(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
+ struct nv50_reg *src1)
+{
+ src1->neg ^= 1;
+ emit_add(pc, dst, src0, src1);
+ src1->neg ^= 1;
+}
+
+static void
+emit_mad(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
+ struct nv50_reg *src1, struct nv50_reg *src2)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] |= 0xe0000000;
+
+ check_swap_src_0_1(pc, &src0, &src1);
+ set_dst(pc, dst, e);
+ set_src_0(pc, src0, e);
+ set_src_1(pc, src1, e);
+ set_src_2(pc, src2, e);
+
+ if (src0->neg ^ src1->neg)
+ e->inst[1] |= 0x04000000;
+ if (src2->neg)
+ e->inst[1] |= 0x08000000;
+
+ emit(pc, e);
+}
+
+static INLINE void
+emit_msb(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
+ struct nv50_reg *src1, struct nv50_reg *src2)
+{
+ src2->neg ^= 1;
+ emit_mad(pc, dst, src0, src1, src2);
+ src2->neg ^= 1;
+}
+
+static void
+emit_flop(struct nv50_pc *pc, unsigned sub,
+ struct nv50_reg *dst, struct nv50_reg *src)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] |= 0x90000000;
+ if (sub) {
+ set_long(pc, e);
+ e->inst[1] |= (sub << 29);
+ }
+
+ set_dst(pc, dst, e);
+ set_src_0(pc, src, e);
+
+ emit(pc, e);
+}
+
+static void
+emit_preex2(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] |= 0xb0000000;
+
+ set_dst(pc, dst, e);
+ set_src_0(pc, src, e);
+ set_long(pc, e);
+ e->inst[1] |= (6 << 29) | 0x00004000;
+
+ emit(pc, e);
+}
+
+static void
+emit_precossin(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] |= 0xb0000000;
+
+ set_dst(pc, dst, e);
+ set_src_0(pc, src, e);
+ set_long(pc, e);
+ e->inst[1] |= (6 << 29);
+
+ emit(pc, e);
+}
+
+#define CVTOP_RN 0x01
+#define CVTOP_FLOOR 0x03
+#define CVTOP_CEIL 0x05
+#define CVTOP_TRUNC 0x07
+#define CVTOP_SAT 0x08
+#define CVTOP_ABS 0x10
+
+#define CVT_F32_F32 0xc4
+#define CVT_F32_S32 0x44
+#define CVT_F32_U32 0x64
+#define CVT_S32_F32 0x8c
+#define CVT_S32_S32 0x0c
+#define CVT_F32_F32_ROP 0xcc
+
+static void
+emit_cvt(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src,
+ int wp, unsigned cop, unsigned fmt)
+{
+ struct nv50_program_exec *e;
+
+ e = exec(pc);
+ set_long(pc, e);
+
+ e->inst[0] |= 0xa0000000;
+ e->inst[1] |= 0x00004000;
+ e->inst[1] |= (cop << 16);
+ e->inst[1] |= (fmt << 24);
+ set_src_0(pc, src, e);
+
+ if (wp >= 0)
+ set_pred_wr(pc, 1, wp, e);
+
+ if (dst)
+ set_dst(pc, dst, e);
+ else {
+ e->inst[0] |= 0x000001fc;
+ e->inst[1] |= 0x00000008;
+ }
+
+ emit(pc, e);
+}
+
+static void
+emit_set(struct nv50_pc *pc, unsigned c_op, struct nv50_reg *dst,
+ struct nv50_reg *src0, struct nv50_reg *src1)
+{
+ struct nv50_program_exec *e = exec(pc);
+ unsigned inv_cop[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+ struct nv50_reg *rdst;
+
+ assert(c_op <= 7);
+ if (check_swap_src_0_1(pc, &src0, &src1))
+ c_op = inv_cop[c_op];
+
+ rdst = dst;
+ if (dst->type != P_TEMP)
+ dst = alloc_temp(pc, NULL);
+
+ /* set.u32 */
+ set_long(pc, e);
+ e->inst[0] |= 0xb0000000;
+ e->inst[1] |= (3 << 29);
+ e->inst[1] |= (c_op << 14);
+ /*XXX: breaks things, .u32 by default?
+ * decuda will disasm as .u16 and use .lo/.hi regs, but this
+ * doesn't seem to match what the hw actually does.
+ inst[1] |= 0x04000000; << breaks things.. .u32 by default?
+ */
+ set_dst(pc, dst, e);
+ set_src_0(pc, src0, e);
+ set_src_1(pc, src1, e);
+ emit(pc, e);
+
+ /* cvt.f32.u32 */
+ e = exec(pc);
+ e->inst[0] = 0xa0000001;
+ e->inst[1] = 0x64014780;
+ set_dst(pc, rdst, e);
+ set_src_0(pc, dst, e);
+ emit(pc, e);
+
+ if (dst != rdst)
+ free_temp(pc, dst);
+}
+
+static INLINE void
+emit_flr(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+ emit_cvt(pc, dst, src, -1, CVTOP_FLOOR, CVT_F32_F32_ROP);
+}
+
+static void
+emit_pow(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *v, struct nv50_reg *e)
+{
+ struct nv50_reg *temp = alloc_temp(pc, NULL);
+
+ emit_flop(pc, 3, temp, v);
+ emit_mul(pc, temp, temp, e);
+ emit_preex2(pc, temp, temp);
+ emit_flop(pc, 6, dst, temp);
+
+ free_temp(pc, temp);
+}
+
+static INLINE void
+emit_abs(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+ emit_cvt(pc, dst, src, -1, CVTOP_ABS, CVT_F32_F32);
+}
+
+static void
+emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask,
+ struct nv50_reg **src)
+{
+ struct nv50_reg *one = alloc_immd(pc, 1.0);
+ struct nv50_reg *zero = alloc_immd(pc, 0.0);
+ struct nv50_reg *neg128 = alloc_immd(pc, -127.999999);
+ struct nv50_reg *pos128 = alloc_immd(pc, 127.999999);
+ struct nv50_reg *tmp[4];
+ boolean allow32 = pc->allow32;
+
+ pc->allow32 = FALSE;
+
+ if (mask & (3 << 1)) {
+ tmp[0] = alloc_temp(pc, NULL);
+ emit_minmax(pc, 4, tmp[0], src[0], zero);
+ }
+
+ if (mask & (1 << 2)) {
+ set_pred_wr(pc, 1, 0, pc->p->exec_tail);
+
+ tmp[1] = temp_temp(pc);
+ emit_minmax(pc, 4, tmp[1], src[1], zero);
+
+ tmp[3] = temp_temp(pc);
+ emit_minmax(pc, 4, tmp[3], src[3], neg128);
+ emit_minmax(pc, 5, tmp[3], tmp[3], pos128);
+
+ emit_pow(pc, dst[2], tmp[1], tmp[3]);
+ emit_mov(pc, dst[2], zero);
+ set_pred(pc, 3, 0, pc->p->exec_tail);
+ }
+
+ if (mask & (1 << 1))
+ assimilate_temp(pc, dst[1], tmp[0]);
+ else
+ if (mask & (1 << 2))
+ free_temp(pc, tmp[0]);
+
+ pc->allow32 = allow32;
+
+ /* do this last, in case src[i,j] == dst[0,3] */
+ if (mask & (1 << 0))
+ emit_mov(pc, dst[0], one);
+
+ if (mask & (1 << 3))
+ emit_mov(pc, dst[3], one);
+
+ FREE(pos128);
+ FREE(neg128);
+ FREE(zero);
+ FREE(one);
+}
+
+static void
+emit_neg(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ set_long(pc, e);
+ e->inst[0] |= 0xa0000000; /* delta */
+ e->inst[1] |= (7 << 29); /* delta */
+ e->inst[1] |= 0x04000000; /* negate arg0? probably not */
+ e->inst[1] |= (1 << 14); /* src .f32 */
+ set_dst(pc, dst, e);
+ set_src_0(pc, src, e);
+
+ emit(pc, e);
+}
+
+static void
+emit_kil(struct nv50_pc *pc, struct nv50_reg *src)
+{
+ struct nv50_program_exec *e;
+ const int r_pred = 1;
+
+ /* Sets predicate reg ? */
+ e = exec(pc);
+ e->inst[0] = 0xa00001fd;
+ e->inst[1] = 0xc4014788;
+ set_src_0(pc, src, e);
+ set_pred_wr(pc, 1, r_pred, e);
+ if (src->neg)
+ e->inst[1] |= 0x20000000;
+ emit(pc, e);
+
+ /* This is probably KILP */
+ e = exec(pc);
+ e->inst[0] = 0x000001fe;
+ set_long(pc, e);
+ set_pred(pc, 1 /* LT? */, r_pred, e);
+ emit(pc, e);
+}
+
+static void
+emit_tex(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask,
+ struct nv50_reg **src, unsigned unit, unsigned type, boolean proj)
+{
+ struct nv50_reg *temp, *t[4];
+ struct nv50_program_exec *e;
+
+ unsigned c, mode, dim;
+
+ switch (type) {
+ case TGSI_TEXTURE_1D:
+ dim = 1;
+ break;
+ case TGSI_TEXTURE_UNKNOWN:
+ case TGSI_TEXTURE_2D:
+ case TGSI_TEXTURE_SHADOW1D: /* XXX: x, z */
+ case TGSI_TEXTURE_RECT:
+ dim = 2;
+ break;
+ case TGSI_TEXTURE_3D:
+ case TGSI_TEXTURE_CUBE:
+ case TGSI_TEXTURE_SHADOW2D:
+ case TGSI_TEXTURE_SHADOWRECT: /* XXX */
+ dim = 3;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* some cards need t[0]'s hw index to be a multiple of 4 */
+ alloc_temp4(pc, t, 0);
+
+ if (proj) {
+ if (src[0]->type == P_TEMP && src[0]->rhw != -1) {
+ mode = pc->interp_mode[src[0]->index];
+
+ t[3]->rhw = src[3]->rhw;
+ emit_interp(pc, t[3], NULL, (mode & INTERP_CENTROID));
+ emit_flop(pc, 0, t[3], t[3]);
+
+ for (c = 0; c < dim; c++) {
+ t[c]->rhw = src[c]->rhw;
+ emit_interp(pc, t[c], t[3],
+ (mode | INTERP_PERSPECTIVE));
+ }
+ } else {
+ emit_flop(pc, 0, t[3], src[3]);
+ for (c = 0; c < dim; c++)
+ emit_mul(pc, t[c], src[c], t[3]);
+
+ /* XXX: for some reason the blob sometimes uses MAD:
+ * emit_mad(pc, t[c], src[0][c], t[3], t[3])
+ * pc->p->exec_tail->inst[1] |= 0x080fc000;
+ */
+ }
+ } else {
+ if (type == TGSI_TEXTURE_CUBE) {
+ temp = temp_temp(pc);
+ emit_minmax(pc, 4, temp, src[0], src[1]);
+ emit_minmax(pc, 4, temp, temp, src[2]);
+ emit_flop(pc, 0, temp, temp);
+ for (c = 0; c < 3; c++)
+ emit_mul(pc, t[c], src[c], temp);
+ } else {
+ for (c = 0; c < dim; c++)
+ emit_mov(pc, t[c], src[c]);
+ }
+ }
+
+ e = exec(pc);
+ set_long(pc, e);
+ e->inst[0] |= 0xf0000000;
+ e->inst[1] |= 0x00000004;
+ set_dst(pc, t[0], e);
+ e->inst[0] |= (unit << 9);
+
+ if (dim == 2)
+ e->inst[0] |= 0x00400000;
+ else
+ if (dim == 3)
+ e->inst[0] |= 0x00800000;
+
+ e->inst[0] |= (mask & 0x3) << 25;
+ e->inst[1] |= (mask & 0xc) << 12;
+
+ emit(pc, e);
+
+#if 1
+ if (mask & 1) emit_mov(pc, dst[0], t[0]);
+ if (mask & 2) emit_mov(pc, dst[1], t[1]);
+ if (mask & 4) emit_mov(pc, dst[2], t[2]);
+ if (mask & 8) emit_mov(pc, dst[3], t[3]);
+
+ free_temp4(pc, t);
+#else
+ /* XXX: if p.e. MUL is used directly after TEX, it would still use
+ * the texture coordinates, not the fetched values: latency ? */
+
+ for (c = 0; c < 4; c++) {
+ if (mask & (1 << c))
+ assimilate_temp(pc, dst[c], t[c]);
+ else
+ free_temp(pc, t[c]);
+ }
+#endif
+}
+
+static void
+convert_to_long(struct nv50_pc *pc, struct nv50_program_exec *e)
+{
+ unsigned q = 0, m = ~0;
+
+ assert(!is_long(e));
+
+ switch (e->inst[0] >> 28) {
+ case 0x1:
+ /* MOV */
+ q = 0x0403c000;
+ m = 0xffff7fff;
+ break;
+ case 0x8:
+ /* INTERP (move centroid, perspective and flat bits) */
+ m = ~0x03000100;
+ q = (e->inst[0] & (3 << 24)) >> (24 - 16);
+ q |= (e->inst[0] & (1 << 8)) << (18 - 8);
+ break;
+ case 0x9:
+ /* RCP */
+ break;
+ case 0xB:
+ /* ADD */
+ m = ~(127 << 16);
+ q = ((e->inst[0] & (~m)) >> 2);
+ break;
+ case 0xC:
+ /* MUL */
+ m = ~0x00008000;
+ q = ((e->inst[0] & (~m)) << 12);
+ break;
+ case 0xE:
+ /* MAD (if src2 == dst) */
+ q = ((e->inst[0] & 0x1fc) << 12);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ set_long(pc, e);
+ pc->p->exec_size++;
+
+ e->inst[0] &= m;
+ e->inst[1] |= q;
+}
+
+static boolean
+negate_supported(const struct tgsi_full_instruction *insn, int i)
+{
+ switch (insn->Instruction.Opcode) {
+ case TGSI_OPCODE_DP3:
+ case TGSI_OPCODE_DP4:
+ case TGSI_OPCODE_MUL:
+ case TGSI_OPCODE_KIL:
+ case TGSI_OPCODE_ADD:
+ case TGSI_OPCODE_SUB:
+ case TGSI_OPCODE_MAD:
+ return TRUE;
+ case TGSI_OPCODE_POW:
+ return (i == 1) ? TRUE : FALSE;
+ default:
+ return FALSE;
+ }
+}
+
+static struct nv50_reg *
+tgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst)
+{
+ switch (dst->DstRegister.File) {
+ case TGSI_FILE_TEMPORARY:
+ return &pc->temp[dst->DstRegister.Index * 4 + c];
+ case TGSI_FILE_OUTPUT:
+ return &pc->result[dst->DstRegister.Index * 4 + c];
+ case TGSI_FILE_NULL:
+ return NULL;
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static struct nv50_reg *
+tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
+ boolean neg)
+{
+ struct nv50_reg *r = NULL;
+ struct nv50_reg *temp;
+ unsigned sgn, c;
+
+ sgn = tgsi_util_get_full_src_register_sign_mode(src, chan);
+
+ c = tgsi_util_get_full_src_register_extswizzle(src, chan);
+ switch (c) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ switch (src->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ r = &pc->attr[src->SrcRegister.Index * 4 + c];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ r = &pc->temp[src->SrcRegister.Index * 4 + c];
+ break;
+ case TGSI_FILE_CONSTANT:
+ r = &pc->param[src->SrcRegister.Index * 4 + c];
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ r = &pc->immd[src->SrcRegister.Index * 4 + c];
+ break;
+ case TGSI_FILE_SAMPLER:
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ break;
+ case TGSI_EXTSWIZZLE_ZERO:
+ r = alloc_immd(pc, 0.0);
+ return r;
+ case TGSI_EXTSWIZZLE_ONE:
+ if (sgn == TGSI_UTIL_SIGN_TOGGLE || sgn == TGSI_UTIL_SIGN_SET)
+ return alloc_immd(pc, -1.0);
+ return alloc_immd(pc, 1.0);
+ default:
+ assert(0);
+ break;
+ }
+
+ switch (sgn) {
+ case TGSI_UTIL_SIGN_KEEP:
+ break;
+ case TGSI_UTIL_SIGN_CLEAR:
+ temp = temp_temp(pc);
+ emit_abs(pc, temp, r);
+ r = temp;
+ break;
+ case TGSI_UTIL_SIGN_TOGGLE:
+ if (neg)
+ r->neg = 1;
+ else {
+ temp = temp_temp(pc);
+ emit_neg(pc, temp, r);
+ r = temp;
+ }
+ break;
+ case TGSI_UTIL_SIGN_SET:
+ temp = temp_temp(pc);
+ emit_abs(pc, temp, r);
+ if (neg)
+ temp->neg = 1;
+ else
+ emit_neg(pc, temp, temp);
+ r = temp;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return r;
+}
+
+/* returns TRUE if instruction can overwrite sources before they're read */
+static boolean
+direct2dest_op(const struct tgsi_full_instruction *insn)
+{
+ if (insn->Instruction.Saturate)
+ return FALSE;
+
+ switch (insn->Instruction.Opcode) {
+ case TGSI_OPCODE_COS:
+ case TGSI_OPCODE_DP3:
+ case TGSI_OPCODE_DP4:
+ case TGSI_OPCODE_DPH:
+ case TGSI_OPCODE_KIL:
+ case TGSI_OPCODE_LIT:
+ case TGSI_OPCODE_POW:
+ case TGSI_OPCODE_RCP:
+ case TGSI_OPCODE_RSQ:
+ case TGSI_OPCODE_SCS:
+ case TGSI_OPCODE_SIN:
+ case TGSI_OPCODE_TEX:
+ case TGSI_OPCODE_TXP:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+static boolean
+nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
+{
+ const struct tgsi_full_instruction *inst = &tok->FullInstruction;
+ struct nv50_reg *rdst[4], *dst[4], *src[3][4], *temp;
+ unsigned mask, sat, unit;
+ boolean assimilate = FALSE;
+ int i, c;
+
+ mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+ sat = inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE;
+
+ for (c = 0; c < 4; c++) {
+ if (mask & (1 << c))
+ dst[c] = tgsi_dst(pc, c, &inst->FullDstRegisters[0]);
+ else
+ dst[c] = NULL;
+ rdst[c] = NULL;
+ src[0][c] = NULL;
+ src[1][c] = NULL;
+ src[2][c] = NULL;
+ }
+
+ for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fs = &inst->FullSrcRegisters[i];
+
+ if (fs->SrcRegister.File == TGSI_FILE_SAMPLER)
+ unit = fs->SrcRegister.Index;
+
+ for (c = 0; c < 4; c++)
+ src[i][c] = tgsi_src(pc, c, fs,
+ negate_supported(inst, i));
+ }
+
+ if (sat) {
+ for (c = 0; c < 4; c++) {
+ rdst[c] = dst[c];
+ dst[c] = temp_temp(pc);
+ }
+ } else
+ if (direct2dest_op(inst)) {
+ for (c = 0; c < 4; c++) {
+ if (!dst[c] || dst[c]->type != P_TEMP)
+ continue;
+
+ for (i = c + 1; i < 4; i++) {
+ if (dst[c] == src[0][i] ||
+ dst[c] == src[1][i] ||
+ dst[c] == src[2][i])
+ break;
+ }
+ if (i == 4)
+ continue;
+
+ assimilate = TRUE;
+ rdst[c] = dst[c];
+ dst[c] = alloc_temp(pc, NULL);
+ }
+ }
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_abs(pc, dst[c], src[0][c]);
+ }
+ break;
+ case TGSI_OPCODE_ADD:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_add(pc, dst[c], src[0][c], src[1][c]);
+ }
+ break;
+ case TGSI_OPCODE_COS:
+ temp = temp_temp(pc);
+ emit_precossin(pc, temp, src[0][0]);
+ emit_flop(pc, 5, temp, temp);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], temp);
+ }
+ break;
+ case TGSI_OPCODE_DP3:
+ temp = temp_temp(pc);
+ emit_mul(pc, temp, src[0][0], src[1][0]);
+ emit_mad(pc, temp, src[0][1], src[1][1], temp);
+ emit_mad(pc, temp, src[0][2], src[1][2], temp);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], temp);
+ }
+ break;
+ case TGSI_OPCODE_DP4:
+ temp = temp_temp(pc);
+ emit_mul(pc, temp, src[0][0], src[1][0]);
+ emit_mad(pc, temp, src[0][1], src[1][1], temp);
+ emit_mad(pc, temp, src[0][2], src[1][2], temp);
+ emit_mad(pc, temp, src[0][3], src[1][3], temp);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], temp);
+ }
+ break;
+ case TGSI_OPCODE_DPH:
+ temp = temp_temp(pc);
+ emit_mul(pc, temp, src[0][0], src[1][0]);
+ emit_mad(pc, temp, src[0][1], src[1][1], temp);
+ emit_mad(pc, temp, src[0][2], src[1][2], temp);
+ emit_add(pc, temp, src[1][3], temp);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], temp);
+ }
+ break;
+ case TGSI_OPCODE_DST:
+ {
+ struct nv50_reg *one = alloc_immd(pc, 1.0);
+ if (mask & (1 << 0))
+ emit_mov(pc, dst[0], one);
+ if (mask & (1 << 1))
+ emit_mul(pc, dst[1], src[0][1], src[1][1]);
+ if (mask & (1 << 2))
+ emit_mov(pc, dst[2], src[0][2]);
+ if (mask & (1 << 3))
+ emit_mov(pc, dst[3], src[1][3]);
+ FREE(one);
+ }
+ break;
+ case TGSI_OPCODE_EX2:
+ temp = temp_temp(pc);
+ emit_preex2(pc, temp, src[0][0]);
+ emit_flop(pc, 6, temp, temp);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], temp);
+ }
+ break;
+ case TGSI_OPCODE_FLR:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_flr(pc, dst[c], src[0][c]);
+ }
+ break;
+ case TGSI_OPCODE_FRC:
+ temp = temp_temp(pc);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_flr(pc, temp, src[0][c]);
+ emit_sub(pc, dst[c], src[0][c], temp);
+ }
+ break;
+ case TGSI_OPCODE_KIL:
+ emit_kil(pc, src[0][0]);
+ emit_kil(pc, src[0][1]);
+ emit_kil(pc, src[0][2]);
+ emit_kil(pc, src[0][3]);
+ pc->p->cfg.fp.regs[2] |= 0x00100000;
+ break;
+ case TGSI_OPCODE_LIT:
+ emit_lit(pc, &dst[0], mask, &src[0][0]);
+ break;
+ case TGSI_OPCODE_LG2:
+ temp = temp_temp(pc);
+ emit_flop(pc, 3, temp, src[0][0]);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], temp);
+ }
+ break;
+ case TGSI_OPCODE_LRP:
+ temp = temp_temp(pc);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_sub(pc, temp, src[1][c], src[2][c]);
+ emit_mad(pc, dst[c], temp, src[0][c], src[2][c]);
+ }
+ break;
+ case TGSI_OPCODE_MAD:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mad(pc, dst[c], src[0][c], src[1][c], src[2][c]);
+ }
+ break;
+ case TGSI_OPCODE_MAX:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_minmax(pc, 4, dst[c], src[0][c], src[1][c]);
+ }
+ break;
+ case TGSI_OPCODE_MIN:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_minmax(pc, 5, dst[c], src[0][c], src[1][c]);
+ }
+ break;
+ case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_SWZ:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], src[0][c]);
+ }
+ break;
+ case TGSI_OPCODE_MUL:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mul(pc, dst[c], src[0][c], src[1][c]);
+ }
+ break;
+ case TGSI_OPCODE_POW:
+ temp = temp_temp(pc);
+ emit_pow(pc, temp, src[0][0], src[1][0]);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], temp);
+ }
+ break;
+ case TGSI_OPCODE_RCP:
+ for (c = 3; c >= 0; c--) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_flop(pc, 0, dst[c], src[0][0]);
+ }
+ break;
+ case TGSI_OPCODE_RSQ:
+ for (c = 3; c >= 0; c--) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_flop(pc, 2, dst[c], src[0][0]);
+ }
+ break;
+ case TGSI_OPCODE_SCS:
+ temp = temp_temp(pc);
+ emit_precossin(pc, temp, src[0][0]);
+ if (mask & (1 << 0))
+ emit_flop(pc, 5, dst[0], temp);
+ if (mask & (1 << 1))
+ emit_flop(pc, 4, dst[1], temp);
+ if (mask & (1 << 2))
+ emit_mov_immdval(pc, dst[2], 0.0);
+ if (mask & (1 << 3))
+ emit_mov_immdval(pc, dst[3], 1.0);
+ break;
+ case TGSI_OPCODE_SGE:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_set(pc, 6, dst[c], src[0][c], src[1][c]);
+ }
+ break;
+ case TGSI_OPCODE_SIN:
+ temp = temp_temp(pc);
+ emit_precossin(pc, temp, src[0][0]);
+ emit_flop(pc, 4, temp, temp);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], temp);
+ }
+ break;
+ case TGSI_OPCODE_SLT:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_set(pc, 1, dst[c], src[0][c], src[1][c]);
+ }
+ break;
+ case TGSI_OPCODE_SUB:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_sub(pc, dst[c], src[0][c], src[1][c]);
+ }
+ break;
+ case TGSI_OPCODE_TEX:
+ emit_tex(pc, dst, mask, src[0], unit,
+ inst->InstructionExtTexture.Texture, FALSE);
+ break;
+ case TGSI_OPCODE_TXP:
+ emit_tex(pc, dst, mask, src[0], unit,
+ inst->InstructionExtTexture.Texture, TRUE);
+ break;
+ case TGSI_OPCODE_XPD:
+ temp = temp_temp(pc);
+ if (mask & (1 << 0)) {
+ emit_mul(pc, temp, src[0][2], src[1][1]);
+ emit_msb(pc, dst[0], src[0][1], src[1][2], temp);
+ }
+ if (mask & (1 << 1)) {
+ emit_mul(pc, temp, src[0][0], src[1][2]);
+ emit_msb(pc, dst[1], src[0][2], src[1][0], temp);
+ }
+ if (mask & (1 << 2)) {
+ emit_mul(pc, temp, src[0][1], src[1][0]);
+ emit_msb(pc, dst[2], src[0][0], src[1][1], temp);
+ }
+ if (mask & (1 << 3))
+ emit_mov_immdval(pc, dst[3], 1.0);
+ break;
+ case TGSI_OPCODE_END:
+ break;
+ default:
+ NOUVEAU_ERR("invalid opcode %d\n", inst->Instruction.Opcode);
+ return FALSE;
+ }
+
+ if (sat) {
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_cvt(pc, rdst[c], dst[c], -1, CVTOP_SAT,
+ CVT_F32_F32);
+ }
+ } else if (assimilate) {
+ for (c = 0; c < 4; c++)
+ if (rdst[c])
+ assimilate_temp(pc, rdst[c], dst[c]);
+ }
+
+ for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+ for (c = 0; c < 4; c++) {
+ if (!src[i][c])
+ continue;
+ if (src[i][c]->index == -1 && src[i][c]->type == P_IMMD)
+ FREE(src[i][c]);
+ else
+ if (src[i][c]->acc == pc->insn_cur)
+ release_hw(pc, src[i][c]);
+ }
+ }
+
+ kill_temp_temp(pc);
+ return TRUE;
+}
+
+/* Adjust a bitmask that indicates what components of a source are used,
+ * we use this in tx_prep so we only load interpolants that are needed.
+ */
+static void
+insn_adjust_mask(const struct tgsi_full_instruction *insn, unsigned *mask)
+{
+ const struct tgsi_instruction_ext_texture *tex;
+
+ switch (insn->Instruction.Opcode) {
+ case TGSI_OPCODE_DP3:
+ *mask = 0x7;
+ break;
+ case TGSI_OPCODE_DP4:
+ case TGSI_OPCODE_DPH:
+ *mask = 0xF;
+ break;
+ case TGSI_OPCODE_LIT:
+ *mask = 0xB;
+ break;
+ case TGSI_OPCODE_RCP:
+ case TGSI_OPCODE_RSQ:
+ *mask = 0x1;
+ break;
+ case TGSI_OPCODE_TEX:
+ case TGSI_OPCODE_TXP:
+ assert(insn->Instruction.Extended);
+ tex = &insn->InstructionExtTexture;
+
+ *mask = 0x7;
+ if (tex->Texture == TGSI_TEXTURE_1D)
+ *mask = 0x1;
+ else
+ if (tex->Texture == TGSI_TEXTURE_2D)
+ *mask = 0x3;
+
+ if (insn->Instruction.Opcode == TGSI_OPCODE_TXP)
+ *mask |= 0x8;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+prep_inspect_insn(struct nv50_pc *pc, const union tgsi_full_token *tok,
+ unsigned *r_usage[2])
+{
+ const struct tgsi_full_instruction *insn;
+ const struct tgsi_full_src_register *src;
+ const struct tgsi_dst_register *dst;
+
+ unsigned i, c, k, n, mask, *acc_p;
+
+ insn = &tok->FullInstruction;
+ dst = &insn->FullDstRegisters[0].DstRegister;
+ mask = dst->WriteMask;
+
+ if (!r_usage[0])
+ r_usage[0] = CALLOC(pc->temp_nr * 4, sizeof(unsigned));
+ if (!r_usage[1])
+ r_usage[1] = CALLOC(pc->attr_nr * 4, sizeof(unsigned));
+
+ if (dst->File == TGSI_FILE_TEMPORARY) {
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ r_usage[0][dst->Index * 4 + c] = pc->insn_nr;
+ }
+ }
+
+ for (i = 0; i < insn->Instruction.NumSrcRegs; i++) {
+ src = &insn->FullSrcRegisters[i];
+
+ switch (src->SrcRegister.File) {
+ case TGSI_FILE_TEMPORARY:
+ acc_p = r_usage[0];
+ break;
+ case TGSI_FILE_INPUT:
+ acc_p = r_usage[1];
+ break;
+ default:
+ continue;
+ }
+
+ insn_adjust_mask(insn, &mask);
+
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+
+ k = tgsi_util_get_full_src_register_extswizzle(src, c);
+ switch (k) {
+ case TGSI_EXTSWIZZLE_X:
+ case TGSI_EXTSWIZZLE_Y:
+ case TGSI_EXTSWIZZLE_Z:
+ case TGSI_EXTSWIZZLE_W:
+ n = src->SrcRegister.Index * 4 + k;
+ acc_p[n] = pc->insn_nr;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+static unsigned
+load_fp_attrib(struct nv50_pc *pc, int i, unsigned *acc, int *mid,
+ int *aid, int *p_oid)
+{
+ struct nv50_reg *iv;
+ int oid, c, n;
+ unsigned mask = 0;
+
+ iv = (pc->interp_mode[i] & INTERP_CENTROID) ? pc->iv_c : pc->iv_p;
+
+ for (c = 0, n = i * 4; c < 4; c++, n++) {
+ oid = (*p_oid)++;
+ pc->attr[n].type = P_TEMP;
+ pc->attr[n].index = i;
+
+ if (pc->attr[n].acc == acc[n])
+ continue;
+ mask |= (1 << c);
+
+ pc->attr[n].acc = acc[n];
+ pc->attr[n].rhw = pc->attr[n].hw = -1;
+ alloc_reg(pc, &pc->attr[n]);
+
+ pc->attr[n].rhw = (*aid)++;
+ emit_interp(pc, &pc->attr[n], iv, pc->interp_mode[i]);
+
+ pc->p->cfg.fp.map[(*mid) / 4] |= oid << (8 * ((*mid) % 4));
+ (*mid)++;
+ pc->p->cfg.fp.regs[1] += 0x00010001;
+ }
+
+ return mask;
+}
+
+static boolean
+nv50_program_tx_prep(struct nv50_pc *pc)
+{
+ struct tgsi_parse_context p;
+ boolean ret = FALSE;
+ unsigned i, c;
+ unsigned fcol, bcol, fcrd, depr;
+
+ /* count (centroid) perspective interpolations */
+ unsigned centroid_loads = 0;
+ unsigned perspect_loads = 0;
+
+ /* track register access for temps and attrs */
+ unsigned *r_usage[2];
+ r_usage[0] = NULL;
+ r_usage[1] = NULL;
+
+ depr = fcol = bcol = fcrd = 0xffff;
+
+ if (pc->p->type == PIPE_SHADER_FRAGMENT) {
+ pc->p->cfg.fp.regs[0] = 0x01000404;
+ pc->p->cfg.fp.regs[1] = 0x00000400;
+ }
+
+ tgsi_parse_init(&p, pc->p->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&p)) {
+ const union tgsi_full_token *tok = &p.FullToken;
+
+ tgsi_parse_token(&p);
+ switch (tok->Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ const struct tgsi_full_immediate *imm =
+ &p.FullToken.FullImmediate;
+
+ ctor_immd(pc, imm->u[0].Float,
+ imm->u[1].Float,
+ imm->u[2].Float,
+ imm->u[3].Float);
+ }
+ break;
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *d;
+ unsigned last, first, mode;
+
+ d = &p.FullToken.FullDeclaration;
+ first = d->DeclarationRange.First;
+ last = d->DeclarationRange.Last;
+
+ switch (d->Declaration.File) {
+ case TGSI_FILE_TEMPORARY:
+ if (pc->temp_nr < (last + 1))
+ pc->temp_nr = last + 1;
+ break;
+ case TGSI_FILE_OUTPUT:
+ if (pc->result_nr < (last + 1))
+ pc->result_nr = last + 1;
+
+ if (!d->Declaration.Semantic)
+ break;
+
+ switch (d->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ depr = first;
+ pc->p->cfg.fp.regs[2] |= 0x00000100;
+ pc->p->cfg.fp.regs[3] |= 0x00000011;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case TGSI_FILE_INPUT:
+ {
+ if (pc->attr_nr < (last + 1))
+ pc->attr_nr = last + 1;
+
+ if (pc->p->type != PIPE_SHADER_FRAGMENT)
+ break;
+
+ switch (d->Declaration.Interpolate) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ mode = INTERP_FLAT;
+ break;
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ mode = INTERP_PERSPECTIVE;
+ break;
+ default:
+ mode = INTERP_LINEAR;
+ break;
+ }
+
+ if (d->Declaration.Semantic) {
+ switch (d->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ fcrd = first;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ fcol = first;
+ mode = INTERP_PERSPECTIVE;
+ break;
+ case TGSI_SEMANTIC_BCOLOR:
+ bcol = first;
+ mode = INTERP_PERSPECTIVE;
+ break;
+ }
+ }
+
+ if (d->Declaration.Centroid) {
+ mode |= INTERP_CENTROID;
+ if (mode & INTERP_PERSPECTIVE)
+ centroid_loads++;
+ } else
+ if (mode & INTERP_PERSPECTIVE)
+ perspect_loads++;
+
+ assert(last < 32);
+ for (i = first; i <= last; i++)
+ pc->interp_mode[i] = mode;
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ if (pc->param_nr < (last + 1))
+ pc->param_nr = last + 1;
+ break;
+ case TGSI_FILE_SAMPLER:
+ break;
+ default:
+ NOUVEAU_ERR("bad decl file %d\n",
+ d->Declaration.File);
+ goto out_err;
+ }
+ }
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ pc->insn_nr++;
+ prep_inspect_insn(pc, tok, r_usage);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (pc->temp_nr) {
+ pc->temp = CALLOC(pc->temp_nr * 4, sizeof(struct nv50_reg));
+ if (!pc->temp)
+ goto out_err;
+
+ for (i = 0; i < pc->temp_nr; i++) {
+ for (c = 0; c < 4; c++) {
+ pc->temp[i*4+c].type = P_TEMP;
+ pc->temp[i*4+c].hw = -1;
+ pc->temp[i*4+c].rhw = -1;
+ pc->temp[i*4+c].index = i;
+ pc->temp[i*4+c].acc = r_usage[0][i*4+c];
+ }
+ }
+ }
+
+ if (pc->attr_nr) {
+ int oid = 4, mid = 4, aid = 0;
+ /* oid = VP output id
+ * aid = FP attribute/interpolant id
+ * mid = VP output mapping field ID
+ */
+
+ pc->attr = CALLOC(pc->attr_nr * 4, sizeof(struct nv50_reg));
+ if (!pc->attr)
+ goto out_err;
+
+ if (pc->p->type == PIPE_SHADER_FRAGMENT) {
+ /* position should be loaded first */
+ if (fcrd != 0xffff) {
+ unsigned mask;
+ mid = 0;
+ mask = load_fp_attrib(pc, fcrd, r_usage[1],
+ &mid, &aid, &oid);
+ oid = 0;
+ pc->p->cfg.fp.regs[1] |= (mask << 24);
+ pc->p->cfg.fp.map[0] = 0x04040404 * fcrd;
+ }
+ pc->p->cfg.fp.map[0] += 0x03020100;
+
+ /* should do MAD fcrd.xy, fcrd, SOME_CONST, fcrd */
+
+ if (perspect_loads) {
+ pc->iv_p = alloc_temp(pc, NULL);
+
+ if (!(pc->p->cfg.fp.regs[1] & 0x08000000)) {
+ pc->p->cfg.fp.regs[1] |= 0x08000000;
+ pc->iv_p->rhw = aid++;
+ emit_interp(pc, pc->iv_p, NULL,
+ INTERP_LINEAR);
+ emit_flop(pc, 0, pc->iv_p, pc->iv_p);
+ } else {
+ pc->iv_p->rhw = aid - 1;
+ emit_flop(pc, 0, pc->iv_p,
+ &pc->attr[fcrd * 4 + 3]);
+ }
+ }
+
+ if (centroid_loads) {
+ pc->iv_c = alloc_temp(pc, NULL);
+ pc->iv_c->rhw = pc->iv_p ? aid - 1 : aid++;
+ emit_interp(pc, pc->iv_c, NULL,
+ INTERP_CENTROID);
+ emit_flop(pc, 0, pc->iv_c, pc->iv_c);
+ pc->p->cfg.fp.regs[1] |= 0x08000000;
+ }
+
+ for (c = 0; c < 4; c++) {
+ /* I don't know what these values do, but
+ * let's set them like the blob does:
+ */
+ if (fcol != 0xffff && r_usage[1][fcol * 4 + c])
+ pc->p->cfg.fp.regs[0] += 0x00010000;
+ if (bcol != 0xffff && r_usage[1][bcol * 4 + c])
+ pc->p->cfg.fp.regs[0] += 0x00010000;
+ }
+
+ for (i = 0; i < pc->attr_nr; i++)
+ load_fp_attrib(pc, i, r_usage[1],
+ &mid, &aid, &oid);
+
+ if (pc->iv_p)
+ free_temp(pc, pc->iv_p);
+ if (pc->iv_c)
+ free_temp(pc, pc->iv_c);
+
+ pc->p->cfg.fp.high_map = (mid / 4);
+ pc->p->cfg.fp.high_map += ((mid % 4) ? 1 : 0);
+ } else {
+ /* vertex program */
+ for (i = 0; i < pc->attr_nr * 4; i++) {
+ pc->p->cfg.vp.attr[aid / 32] |=
+ (1 << (aid % 32));
+ pc->attr[i].type = P_ATTR;
+ pc->attr[i].hw = aid++;
+ pc->attr[i].index = i / 4;
+ }
+ }
+ }
+
+ if (pc->result_nr) {
+ int rid = 0;
+
+ pc->result = CALLOC(pc->result_nr * 4, sizeof(struct nv50_reg));
+ if (!pc->result)
+ goto out_err;
+
+ for (i = 0; i < pc->result_nr; i++) {
+ for (c = 0; c < 4; c++) {
+ if (pc->p->type == PIPE_SHADER_FRAGMENT) {
+ pc->result[i*4+c].type = P_TEMP;
+ pc->result[i*4+c].hw = -1;
+ pc->result[i*4+c].rhw = (i == depr) ?
+ -1 : rid++;
+ } else {
+ pc->result[i*4+c].type = P_RESULT;
+ pc->result[i*4+c].hw = rid++;
+ }
+ pc->result[i*4+c].index = i;
+ }
+
+ if (pc->p->type == PIPE_SHADER_FRAGMENT &&
+ depr != 0xffff) {
+ pc->result[depr * 4 + 2].rhw =
+ (pc->result_nr - 1) * 4;
+ }
+ }
+ }
+
+ if (pc->param_nr) {
+ int rid = 0;
+
+ pc->param = CALLOC(pc->param_nr * 4, sizeof(struct nv50_reg));
+ if (!pc->param)
+ goto out_err;
+
+ for (i = 0; i < pc->param_nr; i++) {
+ for (c = 0; c < 4; c++) {
+ pc->param[i*4+c].type = P_CONST;
+ pc->param[i*4+c].hw = rid++;
+ pc->param[i*4+c].index = i;
+ }
+ }
+ }
+
+ if (pc->immd_nr) {
+ int rid = 0;
+
+ pc->immd = CALLOC(pc->immd_nr * 4, sizeof(struct nv50_reg));
+ if (!pc->immd)
+ goto out_err;
+
+ for (i = 0; i < pc->immd_nr; i++) {
+ for (c = 0; c < 4; c++) {
+ pc->immd[i*4+c].type = P_IMMD;
+ pc->immd[i*4+c].hw = rid++;
+ pc->immd[i*4+c].index = i;
+ }
+ }
+ }
+
+ ret = TRUE;
+out_err:
+ if (r_usage[0])
+ FREE(r_usage[0]);
+ if (r_usage[1])
+ FREE(r_usage[1]);
+
+ tgsi_parse_free(&p);
+ return ret;
+}
+
+static void
+free_nv50_pc(struct nv50_pc *pc)
+{
+ if (pc->immd)
+ FREE(pc->immd);
+ if (pc->param)
+ FREE(pc->param);
+ if (pc->result)
+ FREE(pc->result);
+ if (pc->attr)
+ FREE(pc->attr);
+ if (pc->temp)
+ FREE(pc->temp);
+
+ FREE(pc);
+}
+
+static boolean
+nv50_program_tx(struct nv50_program *p)
+{
+ struct tgsi_parse_context parse;
+ struct nv50_pc *pc;
+ unsigned k;
+ boolean ret;
+
+ pc = CALLOC_STRUCT(nv50_pc);
+ if (!pc)
+ return FALSE;
+ pc->p = p;
+ pc->p->cfg.high_temp = 4;
+
+ ret = nv50_program_tx_prep(pc);
+ if (ret == FALSE)
+ goto out_cleanup;
+
+ tgsi_parse_init(&parse, pc->p->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ const union tgsi_full_token *tok = &parse.FullToken;
+
+ /* don't allow half insn/immd on first and last instruction */
+ pc->allow32 = TRUE;
+ if (pc->insn_cur == 0 || pc->insn_cur + 2 == pc->insn_nr)
+ pc->allow32 = FALSE;
+
+ tgsi_parse_token(&parse);
+
+ switch (tok->Token.Type) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ ++pc->insn_cur;
+ ret = nv50_program_tx_insn(pc, tok);
+ if (ret == FALSE)
+ goto out_err;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (p->type == PIPE_SHADER_FRAGMENT) {
+ struct nv50_reg out;
+
+ out.type = P_TEMP;
+ for (k = 0; k < pc->result_nr * 4; k++) {
+ if (pc->result[k].rhw == -1)
+ continue;
+ if (pc->result[k].hw != pc->result[k].rhw) {
+ out.hw = pc->result[k].rhw;
+ emit_mov(pc, &out, &pc->result[k]);
+ }
+ if (pc->p->cfg.high_result < (pc->result[k].rhw + 1))
+ pc->p->cfg.high_result = pc->result[k].rhw + 1;
+ }
+ }
+
+ /* look for single half instructions and make them long */
+ struct nv50_program_exec *e, *e_prev;
+
+ for (k = 0, e = pc->p->exec_head, e_prev = NULL; e; e = e->next) {
+ if (!is_long(e))
+ k++;
+
+ if (!e->next || is_long(e->next)) {
+ if (k & 1)
+ convert_to_long(pc, e);
+ k = 0;
+ }
+
+ if (e->next)
+ e_prev = e;
+ }
+
+ if (!is_long(pc->p->exec_tail)) {
+ /* this may occur if moving FP results */
+ assert(e_prev && !is_long(e_prev));
+ convert_to_long(pc, e_prev);
+ convert_to_long(pc, pc->p->exec_tail);
+ }
+
+ assert(is_long(pc->p->exec_tail) && !is_immd(pc->p->exec_head));
+ pc->p->exec_tail->inst[1] |= 0x00000001;
+
+ p->param_nr = pc->param_nr * 4;
+ p->immd_nr = pc->immd_nr * 4;
+ p->immd = pc->immd_buf;
+
+out_err:
+ tgsi_parse_free(&parse);
+
+out_cleanup:
+ free_nv50_pc(pc);
+ return ret;
+}
+
+static void
+nv50_program_validate(struct nv50_context *nv50, struct nv50_program *p)
+{
+ if (nv50_program_tx(p) == FALSE)
+ assert(0);
+ p->translated = TRUE;
+}
+
+static void
+nv50_program_upload_data(struct nv50_context *nv50, float *map,
+ unsigned start, unsigned count, unsigned cbuf)
+{
+ struct nouveau_channel *chan = nv50->screen->base.channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+
+ while (count) {
+ unsigned nr = count > 2047 ? 2047 : count;
+
+ BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
+ OUT_RING (chan, (cbuf << 0) | (start << 8));
+ BEGIN_RING(chan, tesla, NV50TCL_CB_DATA(0) | 0x40000000, nr);
+ OUT_RINGp (chan, map, nr);
+
+ map += nr;
+ start += nr;
+ count -= nr;
+ }
+}
+
+static void
+nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p)
+{
+ struct pipe_screen *pscreen = nv50->pipe.screen;
+
+ if (!p->data[0] && p->immd_nr) {
+ struct nouveau_resource *heap = nv50->screen->immd_heap[0];
+
+ if (nouveau_resource_alloc(heap, p->immd_nr, p, &p->data[0])) {
+ while (heap->next && heap->size < p->immd_nr) {
+ struct nv50_program *evict = heap->next->priv;
+ nouveau_resource_free(&evict->data[0]);
+ }
+
+ if (nouveau_resource_alloc(heap, p->immd_nr, p,
+ &p->data[0]))
+ assert(0);
+ }
+
+ /* immediates only need to be uploaded again when freed */
+ nv50_program_upload_data(nv50, p->immd, p->data[0]->start,
+ p->immd_nr, NV50_CB_PMISC);
+ }
+
+ if (!p->data[1] && p->param_nr) {
+ struct nouveau_resource *heap =
+ nv50->screen->parm_heap[p->type];
+
+ if (nouveau_resource_alloc(heap, p->param_nr, p, &p->data[1])) {
+ while (heap->next && heap->size < p->param_nr) {
+ struct nv50_program *evict = heap->next->priv;
+ nouveau_resource_free(&evict->data[1]);
+ }
+
+ if (nouveau_resource_alloc(heap, p->param_nr, p,
+ &p->data[1]))
+ assert(0);
+ }
+ }
+
+ if (p->param_nr) {
+ unsigned cbuf = NV50_CB_PVP;
+ float *map = pipe_buffer_map(pscreen, nv50->constbuf[p->type],
+ PIPE_BUFFER_USAGE_CPU_READ);
+ if (p->type == PIPE_SHADER_FRAGMENT)
+ cbuf = NV50_CB_PFP;
+ nv50_program_upload_data(nv50, map, p->data[1]->start,
+ p->param_nr, cbuf);
+ pipe_buffer_unmap(pscreen, nv50->constbuf[p->type]);
+ }
+}
+
+static void
+nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p)
+{
+ struct nouveau_channel *chan = nv50->screen->base.channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nv50_program_exec *e;
+ struct nouveau_stateobj *so;
+ const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
+ unsigned start, count, *up, *ptr;
+ boolean upload = FALSE;
+
+ if (!p->bo) {
+ nouveau_bo_new(chan->device, NOUVEAU_BO_VRAM, 0x100,
+ p->exec_size * 4, &p->bo);
+ upload = TRUE;
+ }
+
+ if ((p->data[0] && p->data[0]->start != p->data_start[0]) ||
+ (p->data[1] && p->data[1]->start != p->data_start[1])) {
+ for (e = p->exec_head; e; e = e->next) {
+ unsigned ei, ci, bs;
+
+ if (e->param.index < 0)
+ continue;
+ bs = (e->inst[1] >> 22) & 0x07;
+ assert(bs < 2);
+ ei = e->param.shift >> 5;
+ ci = e->param.index + p->data[bs]->start;
+
+ e->inst[ei] &= ~e->param.mask;
+ e->inst[ei] |= (ci << e->param.shift);
+ }
+
+ if (p->data[0])
+ p->data_start[0] = p->data[0]->start;
+ if (p->data[1])
+ p->data_start[1] = p->data[1]->start;
+
+ upload = TRUE;
+ }
+
+ if (!upload)
+ return;
+
+#ifdef NV50_PROGRAM_DUMP
+ NOUVEAU_ERR("-------\n");
+ for (e = p->exec_head; e; e = e->next) {
+ NOUVEAU_ERR("0x%08x\n", e->inst[0]);
+ if (is_long(e))
+ NOUVEAU_ERR("0x%08x\n", e->inst[1]);
+ }
+#endif
+
+ up = ptr = MALLOC(p->exec_size * 4);
+ for (e = p->exec_head; e; e = e->next) {
+ *(ptr++) = e->inst[0];
+ if (is_long(e))
+ *(ptr++) = e->inst[1];
+ }
+
+ so = so_new(4,2);
+ so_method(so, nv50->screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ so_reloc (so, p->bo, 0, flags | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, p->bo, 0, flags | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, (NV50_CB_PUPLOAD << 16) | 0x0800); //(p->exec_size * 4));
+
+ start = 0; count = p->exec_size;
+ while (count) {
+ struct nouveau_channel *chan = nv50->screen->base.channel;
+ unsigned nr;
+
+ so_emit(chan, so);
+
+ nr = MIN2(count, 2047);
+ nr = MIN2(chan->pushbuf->remaining, nr);
+ if (chan->pushbuf->remaining < (nr + 3)) {
+ FIRE_RING(chan);
+ continue;
+ }
+
+ BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
+ OUT_RING (chan, (start << 8) | NV50_CB_PUPLOAD);
+ BEGIN_RING(chan, tesla, NV50TCL_CB_DATA(0) | 0x40000000, nr);
+ OUT_RINGp (chan, up + start, nr);
+
+ start += nr;
+ count -= nr;
+ }
+
+ FREE(up);
+ so_ref(NULL, &so);
+}
+
+void
+nv50_vertprog_validate(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nv50_program *p = nv50->vertprog;
+ struct nouveau_stateobj *so;
+
+ if (!p->translated) {
+ nv50_program_validate(nv50, p);
+ if (!p->translated)
+ assert(0);
+ }
+
+ nv50_program_validate_data(nv50, p);
+ nv50_program_validate_code(nv50, p);
+
+ so = so_new(13, 2);
+ so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2);
+ so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+ NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+ NOUVEAU_BO_LOW, 0, 0);
+ so_method(so, tesla, NV50TCL_VP_ATTR_EN_0, 2);
+ so_data (so, p->cfg.vp.attr[0]);
+ so_data (so, p->cfg.vp.attr[1]);
+ so_method(so, tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
+ so_data (so, p->cfg.high_result);
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 2);
+ so_data (so, p->cfg.high_result); //8);
+ so_data (so, p->cfg.high_temp);
+ so_method(so, tesla, NV50TCL_VP_START_ID, 1);
+ so_data (so, 0); /* program start offset */
+ so_ref(so, &nv50->state.vertprog);
+ so_ref(NULL, &so);
+}
+
+void
+nv50_fragprog_validate(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nv50_program *p = nv50->fragprog;
+ struct nouveau_stateobj *so;
+ unsigned i;
+
+ if (!p->translated) {
+ nv50_program_validate(nv50, p);
+ if (!p->translated)
+ assert(0);
+ }
+
+ nv50_program_validate_data(nv50, p);
+ nv50_program_validate_code(nv50, p);
+
+ so = so_new(64, 2);
+ so_method(so, tesla, NV50TCL_FP_ADDRESS_HIGH, 2);
+ so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+ NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+ NOUVEAU_BO_LOW, 0, 0);
+ so_method(so, tesla, NV50TCL_MAP_SEMANTIC_0, 4);
+ so_data (so, p->cfg.fp.regs[0]); /* 0x01000404 / 0x00040404 */
+ so_data (so, 0x00000004);
+ so_data (so, 0x00000000);
+ so_data (so, 0x00000000);
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), p->cfg.fp.high_map);
+ for (i = 0; i < p->cfg.fp.high_map; i++)
+ so_data(so, p->cfg.fp.map[i]);
+ so_method(so, tesla, NV50TCL_FP_INTERPOLANT_CTRL, 2);
+ so_data (so, p->cfg.fp.regs[1]); /* 0x08040404 / 0x0f000401 */
+ so_data (so, p->cfg.high_temp);
+ so_method(so, tesla, NV50TCL_FP_RESULT_COUNT, 1);
+ so_data (so, p->cfg.high_result);
+ so_method(so, tesla, NV50TCL_FP_CTRL_UNK19A8, 1);
+ so_data (so, p->cfg.fp.regs[2]);
+ so_method(so, tesla, NV50TCL_FP_CTRL_UNK196C, 1);
+ so_data (so, p->cfg.fp.regs[3]);
+ so_method(so, tesla, NV50TCL_FP_START_ID, 1);
+ so_data (so, 0); /* program start offset */
+ so_ref(so, &nv50->state.fragprog);
+ so_ref(NULL, &so);
+}
+
+void
+nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p)
+{
+ while (p->exec_head) {
+ struct nv50_program_exec *e = p->exec_head;
+
+ p->exec_head = e->next;
+ FREE(e);
+ }
+ p->exec_tail = NULL;
+ p->exec_size = 0;
+
+ nouveau_bo_ref(NULL, &p->bo);
+
+ nouveau_resource_free(&p->data[0]);
+ nouveau_resource_free(&p->data[1]);
+
+ p->translated = 0;
+}
diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h
new file mode 100644
index 0000000000..096e0476aa
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_program.h
@@ -0,0 +1,50 @@
+#ifndef __NV50_PROGRAM_H__
+#define __NV50_PROGRAM_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+
+struct nv50_program_exec {
+ struct nv50_program_exec *next;
+
+ unsigned inst[2];
+ struct {
+ int index;
+ unsigned mask;
+ unsigned shift;
+ } param;
+};
+
+struct nv50_program {
+ struct pipe_shader_state pipe;
+ struct tgsi_shader_info info;
+ boolean translated;
+
+ unsigned type;
+ struct nv50_program_exec *exec_head;
+ struct nv50_program_exec *exec_tail;
+ unsigned exec_size;
+ struct nouveau_resource *data[2];
+ unsigned data_start[2];
+
+ struct nouveau_bo *bo;
+
+ float *immd;
+ unsigned immd_nr;
+ unsigned param_nr;
+
+ struct {
+ unsigned high_temp;
+ unsigned high_result;
+ struct {
+ unsigned attr[2];
+ } vp;
+ struct {
+ unsigned regs[4];
+ unsigned map[5];
+ unsigned high_map;
+ } fp;
+ } cfg;
+};
+
+#endif
diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c
new file mode 100644
index 0000000000..5305c93d59
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_query.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+
+#include "nv50_context.h"
+
+struct nv50_query {
+ struct nouveau_bo *bo;
+ unsigned type;
+ boolean ready;
+ uint64_t result;
+};
+
+static INLINE struct nv50_query *
+nv50_query(struct pipe_query *pipe)
+{
+ return (struct nv50_query *)pipe;
+}
+
+static struct pipe_query *
+nv50_query_create(struct pipe_context *pipe, unsigned type)
+{
+ struct nouveau_device *dev = nouveau_screen(pipe->screen)->device;
+ struct nv50_query *q = CALLOC_STRUCT(nv50_query);
+ int ret;
+
+ assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+ q->type = type;
+
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 256,
+ 16, &q->bo);
+ if (ret) {
+ FREE(q);
+ return NULL;
+ }
+
+ return (struct pipe_query *)q;
+}
+
+static void
+nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv50_query *q = nv50_query(pq);
+
+ if (q) {
+ nouveau_bo_ref(NULL, &q->bo);
+ FREE(q);
+ }
+}
+
+static void
+nv50_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nouveau_channel *chan = nv50->screen->base.channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nv50_query *q = nv50_query(pq);
+
+ BEGIN_RING(chan, tesla, 0x1530, 1);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, tesla, 0x1514, 1);
+ OUT_RING (chan, 1);
+
+ q->ready = FALSE;
+}
+
+static void
+nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nouveau_channel *chan = nv50->screen->base.channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nv50_query *q = nv50_query(pq);
+
+ WAIT_RING (chan, 5);
+ BEGIN_RING(chan, tesla, NV50TCL_QUERY_ADDRESS_HIGH, 4);
+ OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RING (chan, 0x00000000);
+ OUT_RING (chan, 0x0100f002);
+ FIRE_RING (chan);
+}
+
+static boolean
+nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq,
+ boolean wait, uint64_t *result)
+{
+ struct nv50_query *q = nv50_query(pq);
+ int ret;
+
+ if (!q->ready) {
+ ret = nouveau_bo_map(q->bo, NOUVEAU_BO_RD |
+ wait ? 0 : NOUVEAU_BO_NOWAIT);
+ if (ret)
+ return false;
+ q->result = ((uint32_t *)q->bo->map)[1];
+ q->ready = TRUE;
+ nouveau_bo_unmap(q->bo);
+ }
+
+ *result = q->result;
+ return q->ready;
+}
+
+void
+nv50_init_query_functions(struct nv50_context *nv50)
+{
+ nv50->pipe.create_query = nv50_query_create;
+ nv50->pipe.destroy_query = nv50_query_destroy;
+ nv50->pipe.begin_query = nv50_query_begin;
+ nv50->pipe.end_query = nv50_query_end;
+ nv50->pipe.get_query_result = nv50_query_result;
+}
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
new file mode 100644
index 0000000000..c7f80a2203
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_screen.h"
+
+#include "nv50_context.h"
+#include "nv50_screen.h"
+
+#include "nouveau/nouveau_stateobj.h"
+
+static boolean
+nv50_screen_is_format_supported(struct pipe_screen *pscreen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else
+ if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) {
+ switch (format) {
+ case PIPE_FORMAT_Z32_FLOAT:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_A8L8_UNORM:
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT5_RGBA:
+ return TRUE;
+ default:
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static int
+nv50_screen_get_param(struct pipe_screen *pscreen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return 32;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 1;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 1;
+ case PIPE_CAP_GLSL:
+ return 0;
+ case PIPE_CAP_S3TC:
+ return 1;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 1;
+ case PIPE_CAP_POINT_SPRITE:
+ return 0;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 8;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 1;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 1;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 13;
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 10;
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 13;
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ return 0;
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ return 0;
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 1;
+ case NOUVEAU_CAP_HW_VTXBUF:
+ return 1;
+ case NOUVEAU_CAP_HW_IDXBUF:
+ return 0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0;
+ }
+}
+
+static float
+nv50_screen_get_paramf(struct pipe_screen *pscreen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 10.0;
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 64.0;
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 16.0;
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 4.0;
+ default:
+ NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+ return 0.0;
+ }
+}
+
+static void
+nv50_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct nv50_screen *screen = nv50_screen(pscreen);
+
+ nouveau_notifier_free(&screen->sync);
+ nouveau_grobj_free(&screen->tesla);
+ nouveau_grobj_free(&screen->eng2d);
+ nouveau_grobj_free(&screen->m2mf);
+ nouveau_screen_fini(&screen->base);
+ FREE(screen);
+}
+
+struct pipe_screen *
+nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
+{
+ struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen);
+ struct nouveau_channel *chan;
+ struct pipe_screen *pscreen;
+ struct nouveau_stateobj *so;
+ unsigned chipset = dev->chipset;
+ unsigned tesla_class = 0;
+ int ret, i;
+
+ if (!screen)
+ return NULL;
+ pscreen = &screen->base.base;
+
+ ret = nouveau_screen_init(&screen->base, dev);
+ if (ret) {
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+ chan = screen->base.channel;
+
+ pscreen->winsys = ws;
+ pscreen->destroy = nv50_screen_destroy;
+ pscreen->get_param = nv50_screen_get_param;
+ pscreen->get_paramf = nv50_screen_get_paramf;
+ pscreen->is_format_supported = nv50_screen_is_format_supported;
+
+ nv50_screen_init_miptree_functions(pscreen);
+ nv50_transfer_init_screen_functions(pscreen);
+
+ /* DMA engine object */
+ ret = nouveau_grobj_alloc(chan, 0xbeef5039,
+ NV50_MEMORY_TO_MEMORY_FORMAT, &screen->m2mf);
+ if (ret) {
+ NOUVEAU_ERR("Error creating M2MF object: %d\n", ret);
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+ BIND_RING(chan, screen->m2mf, 1);
+
+ /* 2D object */
+ ret = nouveau_grobj_alloc(chan, 0xbeef502d, NV50_2D, &screen->eng2d);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 2D object: %d\n", ret);
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+ BIND_RING(chan, screen->eng2d, 2);
+
+ /* 3D object */
+ switch (chipset & 0xf0) {
+ case 0x50:
+ tesla_class = NV50TCL;
+ break;
+ case 0x80:
+ case 0x90:
+ /* this stupid name should be corrected. */
+ tesla_class = NV54TCL;
+ break;
+ case 0xa0:
+ tesla_class = NVA0TCL;
+ break;
+ default:
+ NOUVEAU_ERR("Not a known NV50 chipset: NV%02x\n", chipset);
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ if (tesla_class == 0) {
+ NOUVEAU_ERR("Unknown G8x chipset: NV%02x\n", chipset);
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ ret = nouveau_grobj_alloc(chan, 0xbeef5097, tesla_class,
+ &screen->tesla);
+ if (ret) {
+ NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+ BIND_RING(chan, screen->tesla, 3);
+
+ /* Sync notifier */
+ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
+ if (ret) {
+ NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ /* Static M2MF init */
+ so = so_new(32, 0);
+ so_method(so, screen->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
+ so_data (so, screen->sync->handle);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->vram->handle);
+ so_emit(chan, so);
+ so_ref (NULL, &so);
+
+ /* Static 2D init */
+ so = so_new(64, 0);
+ so_method(so, screen->eng2d, NV50_2D_DMA_NOTIFY, 4);
+ so_data (so, screen->sync->handle);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->vram->handle);
+ so_data (so, chan->vram->handle);
+ so_method(so, screen->eng2d, NV50_2D_OPERATION, 1);
+ so_data (so, NV50_2D_OPERATION_SRCCOPY);
+ so_method(so, screen->eng2d, 0x0290, 1);
+ so_data (so, 0);
+ so_method(so, screen->eng2d, 0x0888, 1);
+ so_data (so, 1);
+ so_emit(chan, so);
+ so_ref(NULL, &so);
+
+ /* Static tesla init */
+ so = so_new(256, 20);
+
+ so_method(so, screen->tesla, 0x1558, 1);
+ so_data (so, 1);
+ so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1);
+ so_data (so, screen->sync->handle);
+ so_method(so, screen->tesla, NV50TCL_DMA_UNK0(0),
+ NV50TCL_DMA_UNK0__SIZE);
+ for (i = 0; i < NV50TCL_DMA_UNK0__SIZE; i++)
+ so_data(so, chan->vram->handle);
+ so_method(so, screen->tesla, NV50TCL_DMA_UNK1(0),
+ NV50TCL_DMA_UNK1__SIZE);
+ for (i = 0; i < NV50TCL_DMA_UNK1__SIZE; i++)
+ so_data(so, chan->vram->handle);
+ so_method(so, screen->tesla, 0x121c, 1);
+ so_data (so, 1);
+
+ so_method(so, screen->tesla, 0x13bc, 1);
+ so_data (so, 0x54);
+ /* origin is top left (set to 1 for bottom left) */
+ so_method(so, screen->tesla, 0x13ac, 1);
+ so_data (so, 0);
+ so_method(so, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
+ so_data (so, 8);
+
+ /* constant buffers for immediates and VP/FP parameters */
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 128*4*4,
+ &screen->constbuf_misc[0]);
+ if (ret) {
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ for (i = 0; i < 2; i++) {
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 128*4*4,
+ &screen->constbuf_parm[i]);
+ if (ret) {
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+ }
+
+ if (nouveau_resource_init(&screen->immd_heap[0], 0, 128) ||
+ nouveau_resource_init(&screen->parm_heap[0], 0, 128) ||
+ nouveau_resource_init(&screen->parm_heap[1], 0, 128))
+ {
+ NOUVEAU_ERR("Error initialising constant buffers.\n");
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ /*
+ // map constant buffers:
+ // B = buffer ID (maybe more than 1 byte)
+ // N = CB index used in shader instruction
+ // P = program type (0 = VP, 2 = GP, 3 = FP)
+ so_method(so, screen->tesla, 0x1694, 1);
+ so_data (so, 0x000BBNP1);
+ */
+
+ so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, (NV50_CB_PMISC << 16) | 0x00000800);
+ so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
+ so_data (so, 0x00000001 | (NV50_CB_PMISC << 12));
+ so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
+ so_data (so, 0x00000031 | (NV50_CB_PMISC << 12));
+
+ so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, (NV50_CB_PVP << 16) | 0x00000800);
+ so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
+ so_data (so, 0x00000101 | (NV50_CB_PVP << 12));
+
+ so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, (NV50_CB_PFP << 16) | 0x00000800);
+ so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
+ so_data (so, 0x00000131 | (NV50_CB_PFP << 12));
+
+ /* Texture sampler/image unit setup - we abuse the constant buffer
+ * upload mechanism for the moment to upload data to the tex config
+ * blocks. At some point we *may* want to go the NVIDIA way of doing
+ * things?
+ */
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 32*8*4, &screen->tic);
+ if (ret) {
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, (NV50_CB_TIC << 16) | 0x0800);
+ so_method(so, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3);
+ so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, 0x00000800);
+
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 32*8*4, &screen->tsc);
+ if (ret) {
+ nv50_screen_destroy(pscreen);
+ return NULL;
+ }
+
+ so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, (NV50_CB_TSC << 16) | 0x0800);
+ so_method(so, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3);
+ so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, 0x00000800);
+
+
+ /* Vertex array limits - max them out */
+ for (i = 0; i < 16; i++) {
+ so_method(so, screen->tesla, NV50TCL_UNK1080_OFFSET_HIGH(i), 2);
+ so_data (so, 0x000000ff);
+ so_data (so, 0xffffffff);
+ }
+
+ so_method(so, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR, 2);
+ so_data (so, fui(0.0));
+ so_data (so, fui(1.0));
+
+ so_method(so, screen->tesla, 0x1234, 1);
+ so_data (so, 1);
+
+ /* activate first scissor rectangle */
+ so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE, 1);
+ so_data (so, 1);
+
+ so_emit(chan, so);
+ so_ref (so, &screen->static_init);
+ so_ref (NULL, &so);
+ nouveau_pushbuf_flush(chan, 0);
+
+ return pscreen;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h
new file mode 100644
index 0000000000..61e24a5b57
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_screen.h
@@ -0,0 +1,38 @@
+#ifndef __NV50_SCREEN_H__
+#define __NV50_SCREEN_H__
+
+#include "nouveau/nouveau_screen.h"
+
+struct nv50_screen {
+ struct nouveau_screen base;
+
+ struct nouveau_winsys *nvws;
+
+ unsigned cur_pctx;
+
+ struct nouveau_grobj *tesla;
+ struct nouveau_grobj *eng2d;
+ struct nouveau_grobj *m2mf;
+ struct nouveau_notifier *sync;
+
+ struct nouveau_bo *constbuf_misc[1];
+ struct nouveau_bo *constbuf_parm[2];
+
+ struct nouveau_resource *immd_heap[1];
+ struct nouveau_resource *parm_heap[2];
+
+ struct nouveau_bo *tic;
+ struct nouveau_bo *tsc;
+
+ struct nouveau_stateobj *static_init;
+};
+
+static INLINE struct nv50_screen *
+nv50_screen(struct pipe_screen *screen)
+{
+ return (struct nv50_screen *)screen;
+}
+
+void nv50_transfer_init_screen_functions(struct pipe_screen *);
+
+#endif
diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c
new file mode 100644
index 0000000000..4283808ed9
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_state.c
@@ -0,0 +1,683 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "nv50_context.h"
+#include "nv50_texture.h"
+
+#include "nouveau/nouveau_stateobj.h"
+
+static void *
+nv50_blend_state_create(struct pipe_context *pipe,
+ const struct pipe_blend_state *cso)
+{
+ struct nouveau_stateobj *so = so_new(64, 0);
+ struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
+ struct nv50_blend_stateobj *bso = CALLOC_STRUCT(nv50_blend_stateobj);
+ unsigned cmask = 0, i;
+
+ /*XXX ignored:
+ * - dither
+ */
+
+ if (cso->blend_enable == 0) {
+ so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
+ for (i = 0; i < 8; i++)
+ so_data(so, 0);
+ } else {
+ so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
+ for (i = 0; i < 8; i++)
+ so_data(so, 1);
+ so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
+ so_data (so, nvgl_blend_eqn(cso->rgb_func));
+ so_data (so, 0x4000 | nvgl_blend_func(cso->rgb_src_factor));
+ so_data (so, 0x4000 | nvgl_blend_func(cso->rgb_dst_factor));
+ so_data (so, nvgl_blend_eqn(cso->alpha_func));
+ so_data (so, 0x4000 | nvgl_blend_func(cso->alpha_src_factor));
+ so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
+ so_data (so, 0x4000 | nvgl_blend_func(cso->alpha_dst_factor));
+ }
+
+ if (cso->logicop_enable == 0 ) {
+ so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 1);
+ so_data (so, 0);
+ } else {
+ so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 2);
+ so_data (so, 1);
+ so_data (so, nvgl_logicop_func(cso->logicop_func));
+ }
+
+ if (cso->colormask & PIPE_MASK_R)
+ cmask |= (1 << 0);
+ if (cso->colormask & PIPE_MASK_G)
+ cmask |= (1 << 4);
+ if (cso->colormask & PIPE_MASK_B)
+ cmask |= (1 << 8);
+ if (cso->colormask & PIPE_MASK_A)
+ cmask |= (1 << 12);
+ so_method(so, tesla, NV50TCL_COLOR_MASK(0), 8);
+ for (i = 0; i < 8; i++)
+ so_data(so, cmask);
+
+ bso->pipe = *cso;
+ so_ref(so, &bso->so);
+ so_ref(NULL, &so);
+ return (void *)bso;
+}
+
+static void
+nv50_blend_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->blend = hwcso;
+ nv50->dirty |= NV50_NEW_BLEND;
+}
+
+static void
+nv50_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_blend_stateobj *bso = hwcso;
+
+ so_ref(NULL, &bso->so);
+ FREE(bso);
+}
+
+static INLINE unsigned
+wrap_mode(unsigned wrap)
+{
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ return NV50TSC_1_0_WRAPS_REPEAT;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ return NV50TSC_1_0_WRAPS_MIRROR_REPEAT;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ return NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ return NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER;
+ case PIPE_TEX_WRAP_CLAMP:
+ return NV50TSC_1_0_WRAPS_CLAMP;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ return NV50TSC_1_0_WRAPS_MIRROR_CLAMP;
+ default:
+ NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+ return NV50TSC_1_0_WRAPS_REPEAT;
+ }
+}
+static void *
+nv50_sampler_state_create(struct pipe_context *pipe,
+ const struct pipe_sampler_state *cso)
+{
+ struct nv50_sampler_stateobj *sso = CALLOC(1, sizeof(*sso));
+ unsigned *tsc = sso->tsc;
+ float limit;
+
+ tsc[0] = (0x00026000 |
+ (wrap_mode(cso->wrap_s) << 0) |
+ (wrap_mode(cso->wrap_t) << 3) |
+ (wrap_mode(cso->wrap_r) << 6));
+
+ switch (cso->mag_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ tsc[1] |= NV50TSC_1_1_MAGF_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ tsc[1] |= NV50TSC_1_1_MAGF_NEAREST;
+ break;
+ }
+
+ switch (cso->min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ tsc[1] |= NV50TSC_1_1_MINF_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ tsc[1] |= NV50TSC_1_1_MINF_NEAREST;
+ break;
+ }
+
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ tsc[1] |= NV50TSC_1_1_MIPF_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ tsc[1] |= NV50TSC_1_1_MIPF_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ tsc[1] |= NV50TSC_1_1_MIPF_NONE;
+ break;
+ }
+
+ if (cso->max_anisotropy >= 16.0)
+ tsc[0] |= (7 << 20);
+ else
+ if (cso->max_anisotropy >= 12.0)
+ tsc[0] |= (6 << 20);
+ else
+ if (cso->max_anisotropy >= 10.0)
+ tsc[0] |= (5 << 20);
+ else
+ if (cso->max_anisotropy >= 8.0)
+ tsc[0] |= (4 << 20);
+ else
+ if (cso->max_anisotropy >= 6.0)
+ tsc[0] |= (3 << 20);
+ else
+ if (cso->max_anisotropy >= 4.0)
+ tsc[0] |= (2 << 20);
+ else
+ if (cso->max_anisotropy >= 2.0)
+ tsc[0] |= (1 << 20);
+
+ if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ tsc[0] |= (1 << 8);
+ tsc[0] |= (nvgl_comparison_op(cso->compare_func) & 0x7);
+ }
+
+ limit = CLAMP(cso->lod_bias, -16.0, 15.0);
+ tsc[1] |= ((int)(limit * 256.0) & 0x1fff) << 12;
+
+ tsc[2] |= ((int)CLAMP(cso->max_lod, 0.0, 15.0) << 20) |
+ ((int)CLAMP(cso->min_lod, 0.0, 15.0) << 8);
+
+ tsc[4] = fui(cso->border_color[0]);
+ tsc[5] = fui(cso->border_color[1]);
+ tsc[6] = fui(cso->border_color[2]);
+ tsc[7] = fui(cso->border_color[3]);
+
+ sso->normalized = cso->normalized_coords;
+ return (void *)sso;
+}
+
+static void
+nv50_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ int i;
+
+ nv50->sampler_nr = nr;
+ for (i = 0; i < nv50->sampler_nr; i++)
+ nv50->sampler[i] = sampler[i];
+
+ nv50->dirty |= NV50_NEW_SAMPLER;
+}
+
+static void
+nv50_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void
+nv50_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+ struct pipe_texture **pt)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ int i;
+
+ for (i = 0; i < nr; i++)
+ pipe_texture_reference((void *)&nv50->miptree[i], pt[i]);
+ for (i = nr; i < nv50->miptree_nr; i++)
+ pipe_texture_reference((void *)&nv50->miptree[i], NULL);
+
+ nv50->miptree_nr = nr;
+ nv50->dirty |= NV50_NEW_TEXTURE;
+}
+
+static void *
+nv50_rasterizer_state_create(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct nouveau_stateobj *so = so_new(64, 0);
+ struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
+ struct nv50_rasterizer_stateobj *rso =
+ CALLOC_STRUCT(nv50_rasterizer_stateobj);
+
+ /*XXX: ignored
+ * - light_twosize
+ * - point_smooth
+ * - multisample
+ * - point_sprite / sprite_coord_mode
+ */
+
+ so_method(so, tesla, NV50TCL_SHADE_MODEL, 1);
+ so_data (so, cso->flatshade ? NV50TCL_SHADE_MODEL_FLAT :
+ NV50TCL_SHADE_MODEL_SMOOTH);
+ so_method(so, tesla, 0x1684, 1);
+ so_data (so, cso->flatshade_first ? 0 : 1);
+
+ so_method(so, tesla, NV50TCL_LINE_WIDTH, 1);
+ so_data (so, fui(cso->line_width));
+ so_method(so, tesla, NV50TCL_LINE_SMOOTH_ENABLE, 1);
+ so_data (so, cso->line_smooth ? 1 : 0);
+ if (cso->line_stipple_enable) {
+ so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
+ so_data (so, 1);
+ so_method(so, tesla, NV50TCL_LINE_STIPPLE_PATTERN, 1);
+ so_data (so, (cso->line_stipple_pattern << 8) |
+ cso->line_stipple_factor);
+ } else {
+ so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ so_method(so, tesla, NV50TCL_POINT_SIZE, 1);
+ so_data (so, fui(cso->point_size));
+
+ so_method(so, tesla, NV50TCL_POLYGON_MODE_FRONT, 3);
+ if (cso->front_winding == PIPE_WINDING_CCW) {
+ so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+ so_data(so, nvgl_polygon_mode(cso->fill_cw));
+ } else {
+ so_data(so, nvgl_polygon_mode(cso->fill_cw));
+ so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+ }
+ so_data(so, cso->poly_smooth ? 1 : 0);
+
+ so_method(so, tesla, NV50TCL_CULL_FACE_ENABLE, 3);
+ so_data (so, cso->cull_mode != PIPE_WINDING_NONE);
+ if (cso->front_winding == PIPE_WINDING_CCW) {
+ so_data(so, NV50TCL_FRONT_FACE_CCW);
+ switch (cso->cull_mode) {
+ case PIPE_WINDING_CCW:
+ so_data(so, NV50TCL_CULL_FACE_FRONT);
+ break;
+ case PIPE_WINDING_CW:
+ so_data(so, NV50TCL_CULL_FACE_BACK);
+ break;
+ case PIPE_WINDING_BOTH:
+ so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK);
+ break;
+ default:
+ so_data(so, NV50TCL_CULL_FACE_BACK);
+ break;
+ }
+ } else {
+ so_data(so, NV50TCL_FRONT_FACE_CW);
+ switch (cso->cull_mode) {
+ case PIPE_WINDING_CCW:
+ so_data(so, NV50TCL_CULL_FACE_BACK);
+ break;
+ case PIPE_WINDING_CW:
+ so_data(so, NV50TCL_CULL_FACE_FRONT);
+ break;
+ case PIPE_WINDING_BOTH:
+ so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK);
+ break;
+ default:
+ so_data(so, NV50TCL_CULL_FACE_BACK);
+ break;
+ }
+ }
+
+ so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_ENABLE, 1);
+ so_data (so, cso->poly_stipple_enable ? 1 : 0);
+
+ so_method(so, tesla, NV50TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+ if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
+ (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
+ so_data(so, 1);
+ else
+ so_data(so, 0);
+
+ if (cso->offset_cw || cso->offset_ccw) {
+ so_method(so, tesla, NV50TCL_POLYGON_OFFSET_FACTOR, 1);
+ so_data (so, fui(cso->offset_scale));
+ so_method(so, tesla, NV50TCL_POLYGON_OFFSET_UNITS, 1);
+ so_data (so, fui(cso->offset_units));
+ }
+
+ rso->pipe = *cso;
+ so_ref(so, &rso->so);
+ so_ref(NULL, &so);
+ return (void *)rso;
+}
+
+static void
+nv50_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->rasterizer = hwcso;
+ nv50->dirty |= NV50_NEW_RASTERIZER;
+}
+
+static void
+nv50_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_rasterizer_stateobj *rso = hwcso;
+
+ so_ref(NULL, &rso->so);
+ FREE(rso);
+}
+
+static void *
+nv50_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
+ struct nv50_zsa_stateobj *zsa = CALLOC_STRUCT(nv50_zsa_stateobj);
+ struct nouveau_stateobj *so = so_new(64, 0);
+
+ so_method(so, tesla, NV50TCL_DEPTH_WRITE_ENABLE, 1);
+ so_data (so, cso->depth.writemask ? 1 : 0);
+ if (cso->depth.enabled) {
+ so_method(so, tesla, NV50TCL_DEPTH_TEST_ENABLE, 1);
+ so_data (so, 1);
+ so_method(so, tesla, NV50TCL_DEPTH_TEST_FUNC, 1);
+ so_data (so, nvgl_comparison_op(cso->depth.func));
+ } else {
+ so_method(so, tesla, NV50TCL_DEPTH_TEST_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ /* XXX: keep hex values until header is updated (names reversed) */
+ if (cso->stencil[0].enabled) {
+ so_method(so, tesla, 0x1380, 8);
+ so_data (so, 1);
+ so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
+ so_data (so, nvgl_comparison_op(cso->stencil[0].func));
+ so_data (so, cso->stencil[0].ref_value);
+ so_data (so, cso->stencil[0].writemask);
+ so_data (so, cso->stencil[0].valuemask);
+ } else {
+ so_method(so, tesla, 0x1380, 1);
+ so_data (so, 0);
+ }
+
+ if (cso->stencil[1].enabled) {
+ so_method(so, tesla, 0x1594, 5);
+ so_data (so, 1);
+ so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
+ so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
+ so_data (so, nvgl_comparison_op(cso->stencil[1].func));
+ so_method(so, tesla, 0x0f54, 3);
+ so_data (so, cso->stencil[1].ref_value);
+ so_data (so, cso->stencil[1].writemask);
+ so_data (so, cso->stencil[1].valuemask);
+ } else {
+ so_method(so, tesla, 0x1594, 1);
+ so_data (so, 0);
+ }
+
+ if (cso->alpha.enabled) {
+ so_method(so, tesla, NV50TCL_ALPHA_TEST_ENABLE, 1);
+ so_data (so, 1);
+ so_method(so, tesla, NV50TCL_ALPHA_TEST_REF, 2);
+ so_data (so, fui(cso->alpha.ref_value));
+ so_data (so, nvgl_comparison_op(cso->alpha.func));
+ } else {
+ so_method(so, tesla, NV50TCL_ALPHA_TEST_ENABLE, 1);
+ so_data (so, 0);
+ }
+
+ zsa->pipe = *cso;
+ so_ref(so, &zsa->so);
+ so_ref(NULL, &so);
+ return (void *)zsa;
+}
+
+static void
+nv50_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->zsa = hwcso;
+ nv50->dirty |= NV50_NEW_ZSA;
+}
+
+static void
+nv50_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_zsa_stateobj *zsa = hwcso;
+
+ so_ref(NULL, &zsa->so);
+ FREE(zsa);
+}
+
+static void *
+nv50_vp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+ p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ p->type = PIPE_SHADER_VERTEX;
+ tgsi_scan_shader(p->pipe.tokens, &p->info);
+ return (void *)p;
+}
+
+static void
+nv50_vp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->vertprog = hwcso;
+ nv50->dirty |= NV50_NEW_VERTPROG;
+}
+
+static void
+nv50_vp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_program *p = hwcso;
+
+ nv50_program_destroy(nv50, p);
+ FREE((void*)p->pipe.tokens);
+ FREE(p);
+}
+
+static void *
+nv50_fp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+ p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ p->type = PIPE_SHADER_FRAGMENT;
+ tgsi_scan_shader(p->pipe.tokens, &p->info);
+ return (void *)p;
+}
+
+static void
+nv50_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->fragprog = hwcso;
+ nv50->dirty |= NV50_NEW_FRAGPROG;
+}
+
+static void
+nv50_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_program *p = hwcso;
+
+ nv50_program_destroy(nv50, p);
+ FREE((void*)p->pipe.tokens);
+ FREE(p);
+}
+
+static void
+nv50_set_blend_color(struct pipe_context *pipe,
+ const struct pipe_blend_color *bcol)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->blend_colour = *bcol;
+ nv50->dirty |= NV50_NEW_BLEND_COLOUR;
+}
+
+static void
+nv50_set_clip_state(struct pipe_context *pipe,
+ const struct pipe_clip_state *clip)
+{
+}
+
+static void
+nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+ const struct pipe_constant_buffer *buf )
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ if (shader == PIPE_SHADER_VERTEX) {
+ nv50->constbuf[PIPE_SHADER_VERTEX] = buf->buffer;
+ nv50->dirty |= NV50_NEW_VERTPROG_CB;
+ } else
+ if (shader == PIPE_SHADER_FRAGMENT) {
+ nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
+ nv50->dirty |= NV50_NEW_FRAGPROG_CB;
+ }
+}
+
+static void
+nv50_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->framebuffer = *fb;
+ nv50->dirty |= NV50_NEW_FRAMEBUFFER;
+}
+
+static void
+nv50_set_polygon_stipple(struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->stipple = *stipple;
+ nv50->dirty |= NV50_NEW_STIPPLE;
+}
+
+static void
+nv50_set_scissor_state(struct pipe_context *pipe,
+ const struct pipe_scissor_state *s)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->scissor = *s;
+ nv50->dirty |= NV50_NEW_SCISSOR;
+}
+
+static void
+nv50_set_viewport_state(struct pipe_context *pipe,
+ const struct pipe_viewport_state *vpt)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->viewport = *vpt;
+ nv50->dirty |= NV50_NEW_VIEWPORT;
+}
+
+static void
+nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_buffer *vb)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ memcpy(nv50->vtxbuf, vb, sizeof(*vb) * count);
+ nv50->vtxbuf_nr = count;
+
+ nv50->dirty |= NV50_NEW_ARRAYS;
+}
+
+static void
+nv50_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_element *ve)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ memcpy(nv50->vtxelt, ve, sizeof(*ve) * count);
+ nv50->vtxelt_nr = count;
+
+ nv50->dirty |= NV50_NEW_ARRAYS;
+}
+
+void
+nv50_init_state_functions(struct nv50_context *nv50)
+{
+ nv50->pipe.create_blend_state = nv50_blend_state_create;
+ nv50->pipe.bind_blend_state = nv50_blend_state_bind;
+ nv50->pipe.delete_blend_state = nv50_blend_state_delete;
+
+ nv50->pipe.create_sampler_state = nv50_sampler_state_create;
+ nv50->pipe.bind_sampler_states = nv50_sampler_state_bind;
+ nv50->pipe.delete_sampler_state = nv50_sampler_state_delete;
+ nv50->pipe.set_sampler_textures = nv50_set_sampler_texture;
+
+ nv50->pipe.create_rasterizer_state = nv50_rasterizer_state_create;
+ nv50->pipe.bind_rasterizer_state = nv50_rasterizer_state_bind;
+ nv50->pipe.delete_rasterizer_state = nv50_rasterizer_state_delete;
+
+ nv50->pipe.create_depth_stencil_alpha_state =
+ nv50_depth_stencil_alpha_state_create;
+ nv50->pipe.bind_depth_stencil_alpha_state =
+ nv50_depth_stencil_alpha_state_bind;
+ nv50->pipe.delete_depth_stencil_alpha_state =
+ nv50_depth_stencil_alpha_state_delete;
+
+ nv50->pipe.create_vs_state = nv50_vp_state_create;
+ nv50->pipe.bind_vs_state = nv50_vp_state_bind;
+ nv50->pipe.delete_vs_state = nv50_vp_state_delete;
+
+ nv50->pipe.create_fs_state = nv50_fp_state_create;
+ nv50->pipe.bind_fs_state = nv50_fp_state_bind;
+ nv50->pipe.delete_fs_state = nv50_fp_state_delete;
+
+ nv50->pipe.set_blend_color = nv50_set_blend_color;
+ nv50->pipe.set_clip_state = nv50_set_clip_state;
+ nv50->pipe.set_constant_buffer = nv50_set_constant_buffer;
+ nv50->pipe.set_framebuffer_state = nv50_set_framebuffer_state;
+ nv50->pipe.set_polygon_stipple = nv50_set_polygon_stipple;
+ nv50->pipe.set_scissor_state = nv50_set_scissor_state;
+ nv50->pipe.set_viewport_state = nv50_set_viewport_state;
+
+ nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers;
+ nv50->pipe.set_vertex_elements = nv50_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
new file mode 100644
index 0000000000..d294356f75
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION 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 "nv50_context.h"
+#include "nouveau/nouveau_stateobj.h"
+
+static void
+nv50_state_validate_fb(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nouveau_stateobj *so = so_new(128, 18);
+ struct pipe_framebuffer_state *fb = &nv50->framebuffer;
+ unsigned i, w, h, gw = 0;
+
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ struct pipe_texture *pt = fb->cbufs[i]->texture;
+ struct nouveau_bo *bo = nv50_miptree(pt)->base.bo;
+
+ if (!gw) {
+ w = fb->cbufs[i]->width;
+ h = fb->cbufs[i]->height;
+ gw = 1;
+ } else {
+ assert(w == fb->cbufs[i]->width);
+ assert(h == fb->cbufs[i]->height);
+ }
+
+ so_method(so, tesla, NV50TCL_RT_HORIZ(i), 2);
+ so_data (so, fb->cbufs[i]->width);
+ so_data (so, fb->cbufs[i]->height);
+
+ so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5);
+ so_reloc (so, bo, fb->cbufs[i]->offset, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0);
+ so_reloc (so, bo, fb->cbufs[i]->offset, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0);
+ switch (fb->cbufs[i]->format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ so_data(so, NV50TCL_RT_FORMAT_A8R8G8B8_UNORM);
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ so_data(so, NV50TCL_RT_FORMAT_R5G6B5_UNORM);
+ break;
+ default:
+ NOUVEAU_ERR("AIIII unknown format %s\n",
+ pf_name(fb->cbufs[i]->format));
+ so_data(so, NV50TCL_RT_FORMAT_X8R8G8B8_UNORM);
+ break;
+ }
+ so_data(so, nv50_miptree(pt)->
+ level[fb->cbufs[i]->level].tile_mode << 4);
+ so_data(so, 0x00000000);
+
+ so_method(so, tesla, 0x1224, 1);
+ so_data (so, 1);
+ }
+
+ if (fb->zsbuf) {
+ struct pipe_texture *pt = fb->zsbuf->texture;
+ struct nouveau_bo *bo = nv50_miptree(pt)->base.bo;
+
+ if (!gw) {
+ w = fb->zsbuf->width;
+ h = fb->zsbuf->height;
+ gw = 1;
+ } else {
+ assert(w == fb->zsbuf->width);
+ assert(h == fb->zsbuf->height);
+ }
+
+ so_method(so, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
+ so_reloc (so, bo, fb->zsbuf->offset, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0);
+ so_reloc (so, bo, fb->zsbuf->offset, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0);
+ switch (fb->zsbuf->format) {
+ case PIPE_FORMAT_Z32_FLOAT:
+ so_data(so, NV50TCL_ZETA_FORMAT_Z32_FLOAT);
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ so_data(so, NV50TCL_ZETA_FORMAT_Z24S8_UNORM);
+ break;
+ case PIPE_FORMAT_X8Z24_UNORM:
+ so_data(so, NV50TCL_ZETA_FORMAT_X8Z24_UNORM);
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ so_data(so, NV50TCL_ZETA_FORMAT_S8Z24_UNORM);
+ break;
+ default:
+ NOUVEAU_ERR("AIIII unknown format %s\n",
+ pf_name(fb->zsbuf->format));
+ so_data(so, NV50TCL_ZETA_FORMAT_S8Z24_UNORM);
+ break;
+ }
+ so_data(so, nv50_miptree(pt)->
+ level[fb->zsbuf->level].tile_mode << 4);
+ so_data(so, 0x00000000);
+
+ so_method(so, tesla, 0x1538, 1);
+ so_data (so, 1);
+ so_method(so, tesla, NV50TCL_ZETA_HORIZ, 3);
+ so_data (so, fb->zsbuf->width);
+ so_data (so, fb->zsbuf->height);
+ so_data (so, 0x00010001);
+ }
+
+ so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ, 2);
+ so_data (so, w << 16);
+ so_data (so, h << 16);
+ /* set window lower left corner */
+ so_method(so, tesla, NV50TCL_WINDOW_LEFT, 2);
+ so_data (so, 0);
+ so_data (so, 0);
+ /* set screen scissor rectangle */
+ so_method(so, tesla, NV50TCL_SCREEN_SCISSOR_HORIZ, 2);
+ so_data (so, w << 16);
+ so_data (so, h << 16);
+
+ /* we set scissors to framebuffer size when they're 'turned off' */
+ nv50->dirty |= NV50_NEW_SCISSOR;
+ so_ref(NULL, &nv50->state.scissor);
+
+ so_ref(so, &nv50->state.fb);
+ so_ref(NULL, &so);
+}
+
+static void
+nv50_state_emit(struct nv50_context *nv50)
+{
+ struct nv50_screen *screen = nv50->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+
+ if (nv50->pctx_id != screen->cur_pctx) {
+ if (nv50->state.fb)
+ nv50->state.dirty |= NV50_NEW_FRAMEBUFFER;
+ if (nv50->state.blend)
+ nv50->state.dirty |= NV50_NEW_BLEND;
+ if (nv50->state.zsa)
+ nv50->state.dirty |= NV50_NEW_ZSA;
+ if (nv50->state.vertprog)
+ nv50->state.dirty |= NV50_NEW_VERTPROG;
+ if (nv50->state.fragprog)
+ nv50->state.dirty |= NV50_NEW_FRAGPROG;
+ if (nv50->state.rast)
+ nv50->state.dirty |= NV50_NEW_RASTERIZER;
+ if (nv50->state.blend_colour)
+ nv50->state.dirty |= NV50_NEW_BLEND_COLOUR;
+ if (nv50->state.stipple)
+ nv50->state.dirty |= NV50_NEW_STIPPLE;
+ if (nv50->state.scissor)
+ nv50->state.dirty |= NV50_NEW_SCISSOR;
+ if (nv50->state.viewport)
+ nv50->state.dirty |= NV50_NEW_VIEWPORT;
+ if (nv50->state.tsc_upload)
+ nv50->state.dirty |= NV50_NEW_SAMPLER;
+ if (nv50->state.tic_upload)
+ nv50->state.dirty |= NV50_NEW_TEXTURE;
+ if (nv50->state.vtxfmt && nv50->state.vtxbuf)
+ nv50->state.dirty |= NV50_NEW_ARRAYS;
+ screen->cur_pctx = nv50->pctx_id;
+ }
+
+ if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER)
+ so_emit(chan, nv50->state.fb);
+ if (nv50->state.dirty & NV50_NEW_BLEND)
+ so_emit(chan, nv50->state.blend);
+ if (nv50->state.dirty & NV50_NEW_ZSA)
+ so_emit(chan, nv50->state.zsa);
+ if (nv50->state.dirty & NV50_NEW_VERTPROG)
+ so_emit(chan, nv50->state.vertprog);
+ if (nv50->state.dirty & NV50_NEW_FRAGPROG)
+ so_emit(chan, nv50->state.fragprog);
+ if (nv50->state.dirty & NV50_NEW_RASTERIZER)
+ so_emit(chan, nv50->state.rast);
+ if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR)
+ so_emit(chan, nv50->state.blend_colour);
+ if (nv50->state.dirty & NV50_NEW_STIPPLE)
+ so_emit(chan, nv50->state.stipple);
+ if (nv50->state.dirty & NV50_NEW_SCISSOR)
+ so_emit(chan, nv50->state.scissor);
+ if (nv50->state.dirty & NV50_NEW_VIEWPORT)
+ so_emit(chan, nv50->state.viewport);
+ if (nv50->state.dirty & NV50_NEW_SAMPLER)
+ so_emit(chan, nv50->state.tsc_upload);
+ if (nv50->state.dirty & NV50_NEW_TEXTURE)
+ so_emit(chan, nv50->state.tic_upload);
+ if (nv50->state.dirty & NV50_NEW_ARRAYS) {
+ so_emit(chan, nv50->state.vtxfmt);
+ so_emit(chan, nv50->state.vtxbuf);
+ if (nv50->state.vtxattr)
+ so_emit(chan, nv50->state.vtxattr);
+ }
+ nv50->state.dirty = 0;
+
+ so_emit_reloc_markers(chan, nv50->state.fb);
+ so_emit_reloc_markers(chan, nv50->state.vertprog);
+ so_emit_reloc_markers(chan, nv50->state.fragprog);
+ so_emit_reloc_markers(chan, nv50->state.vtxbuf);
+ so_emit_reloc_markers(chan, nv50->screen->static_init);
+}
+
+boolean
+nv50_state_validate(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nouveau_stateobj *so;
+ unsigned i;
+
+ if (nv50->dirty & NV50_NEW_FRAMEBUFFER)
+ nv50_state_validate_fb(nv50);
+
+ if (nv50->dirty & NV50_NEW_BLEND)
+ so_ref(nv50->blend->so, &nv50->state.blend);
+
+ if (nv50->dirty & NV50_NEW_ZSA)
+ so_ref(nv50->zsa->so, &nv50->state.zsa);
+
+ if (nv50->dirty & (NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB))
+ nv50_vertprog_validate(nv50);
+
+ if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB))
+ nv50_fragprog_validate(nv50);
+
+ if (nv50->dirty & NV50_NEW_RASTERIZER)
+ so_ref(nv50->rasterizer->so, &nv50->state.rast);
+
+ if (nv50->dirty & NV50_NEW_BLEND_COLOUR) {
+ so = so_new(5, 0);
+ so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4);
+ so_data (so, fui(nv50->blend_colour.color[0]));
+ so_data (so, fui(nv50->blend_colour.color[1]));
+ so_data (so, fui(nv50->blend_colour.color[2]));
+ so_data (so, fui(nv50->blend_colour.color[3]));
+ so_ref(so, &nv50->state.blend_colour);
+ so_ref(NULL, &so);
+ }
+
+ if (nv50->dirty & NV50_NEW_STIPPLE) {
+ so = so_new(33, 0);
+ so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32);
+ for (i = 0; i < 32; i++)
+ so_data(so, nv50->stipple.stipple[i]);
+ so_ref(so, &nv50->state.stipple);
+ so_ref(NULL, &so);
+ }
+
+ if (nv50->dirty & (NV50_NEW_SCISSOR | NV50_NEW_RASTERIZER)) {
+ struct pipe_rasterizer_state *rast = &nv50->rasterizer->pipe;
+ struct pipe_scissor_state *s = &nv50->scissor;
+
+ if (nv50->state.scissor &&
+ (rast->scissor == 0 && nv50->state.scissor_enabled == 0))
+ goto scissor_uptodate;
+ nv50->state.scissor_enabled = rast->scissor;
+
+ so = so_new(3, 0);
+ so_method(so, tesla, NV50TCL_SCISSOR_HORIZ, 2);
+ if (nv50->state.scissor_enabled) {
+ so_data(so, (s->maxx << 16) | s->minx);
+ so_data(so, (s->maxy << 16) | s->miny);
+ } else {
+ so_data(so, (nv50->framebuffer.width << 16));
+ so_data(so, (nv50->framebuffer.height << 16));
+ }
+ so_ref(so, &nv50->state.scissor);
+ so_ref(NULL, &so);
+ nv50->state.dirty |= NV50_NEW_SCISSOR;
+ }
+scissor_uptodate:
+
+ if (nv50->dirty & (NV50_NEW_VIEWPORT | NV50_NEW_RASTERIZER)) {
+ unsigned bypass;
+
+ if (!nv50->rasterizer->pipe.bypass_vs_clip_and_viewport)
+ bypass = 0;
+ else
+ bypass = 1;
+
+ if (nv50->state.viewport &&
+ (bypass || !(nv50->dirty & NV50_NEW_VIEWPORT)) &&
+ nv50->state.viewport_bypass == bypass)
+ goto viewport_uptodate;
+ nv50->state.viewport_bypass = bypass;
+
+ so = so_new(12, 0);
+ if (!bypass) {
+ so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE(0), 3);
+ so_data (so, fui(nv50->viewport.translate[0]));
+ so_data (so, fui(nv50->viewport.translate[1]));
+ so_data (so, fui(nv50->viewport.translate[2]));
+ so_method(so, tesla, NV50TCL_VIEWPORT_SCALE(0), 3);
+ so_data (so, fui(nv50->viewport.scale[0]));
+ so_data (so, fui(nv50->viewport.scale[1]));
+ so_data (so, fui(nv50->viewport.scale[2]));
+
+ so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1);
+ so_data (so, 1);
+ /* no idea what 0f90 does */
+ so_method(so, tesla, 0x0f90, 1);
+ so_data (so, 0);
+ } else {
+ so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1);
+ so_data (so, 0);
+ so_method(so, tesla, 0x0f90, 1);
+ so_data (so, 1);
+ }
+
+ so_ref(so, &nv50->state.viewport);
+ so_ref(NULL, &so);
+ nv50->state.dirty |= NV50_NEW_VIEWPORT;
+ }
+viewport_uptodate:
+
+ if (nv50->dirty & NV50_NEW_SAMPLER) {
+ int i;
+
+ so = so_new(nv50->sampler_nr * 8 + 3, 0);
+ so_method(so, tesla, NV50TCL_CB_ADDR, 1);
+ so_data (so, NV50_CB_TSC);
+ so_method(so, tesla, NV50TCL_CB_DATA(0) | 0x40000000,
+ nv50->sampler_nr * 8);
+ for (i = 0; i < nv50->sampler_nr; i++)
+ so_datap (so, nv50->sampler[i]->tsc, 8);
+ so_ref(so, &nv50->state.tsc_upload);
+ so_ref(NULL, &so);
+ }
+
+ if (nv50->dirty & (NV50_NEW_TEXTURE | NV50_NEW_SAMPLER))
+ nv50_tex_validate(nv50);
+
+ if (nv50->dirty & NV50_NEW_ARRAYS)
+ nv50_vbo_validate(nv50);
+
+ nv50->state.dirty |= nv50->dirty;
+ nv50->dirty = 0;
+ nv50_state_emit(nv50);
+
+ return TRUE;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
new file mode 100644
index 0000000000..6bf6f773b0
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define __NOUVEAU_PUSH_H__
+#include <stdint.h>
+#include "nouveau/nouveau_pushbuf.h"
+#include "nv50_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_tile.h"
+
+static INLINE int
+nv50_format(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM;
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ return NV50_2D_DST_FORMAT_X8R8G8B8_UNORM;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return NV50_2D_DST_FORMAT_R5G6B5_UNORM;
+ case PIPE_FORMAT_A8_UNORM:
+ return NV50_2D_DST_FORMAT_R8_UNORM;
+ default:
+ return -1;
+ }
+}
+
+static int
+nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
+{
+ struct nv50_miptree *mt = nv50_miptree(ps->texture);
+ struct nouveau_channel *chan = screen->eng2d->channel;
+ struct nouveau_grobj *eng2d = screen->eng2d;
+ struct nouveau_bo *bo = nv50_miptree(ps->texture)->base.bo;
+ int format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
+ int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD);
+
+ format = nv50_format(ps->format);
+ if (format < 0)
+ return 1;
+
+ if (!bo->tile_flags) {
+ BEGIN_RING(chan, eng2d, mthd, 2);
+ OUT_RING (chan, format);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, eng2d, mthd + 0x14, 5);
+ OUT_RING (chan, mt->level[ps->level].pitch);
+ OUT_RING (chan, ps->width);
+ OUT_RING (chan, ps->height);
+ OUT_RELOCh(chan, bo, ps->offset, flags);
+ OUT_RELOCl(chan, bo, ps->offset, flags);
+ } else {
+ BEGIN_RING(chan, eng2d, mthd, 5);
+ OUT_RING (chan, format);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, mt->level[ps->level].tile_mode << 4);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
+ OUT_RING (chan, ps->width);
+ OUT_RING (chan, ps->height);
+ OUT_RELOCh(chan, bo, ps->offset, flags);
+ OUT_RELOCl(chan, bo, ps->offset, flags);
+ }
+
+#if 0
+ if (dst) {
+ BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, surf->width);
+ OUT_RING (chan, surf->height);
+ }
+#endif
+
+ return 0;
+}
+
+int
+nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst,
+ int dx, int dy, struct pipe_surface *src, int sx, int sy,
+ int w, int h)
+{
+ struct nouveau_channel *chan = screen->eng2d->channel;
+ struct nouveau_grobj *eng2d = screen->eng2d;
+ int ret;
+
+ WAIT_RING (chan, 32);
+
+ ret = nv50_surface_set(screen, dst, 1);
+ if (ret)
+ return ret;
+
+ ret = nv50_surface_set(screen, src, 0);
+ if (ret)
+ return ret;
+
+ BEGIN_RING(chan, eng2d, 0x088c, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 4);
+ OUT_RING (chan, dx);
+ OUT_RING (chan, dy);
+ OUT_RING (chan, w);
+ OUT_RING (chan, h);
+ BEGIN_RING(chan, eng2d, 0x08c0, 4);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, eng2d, 0x08d0, 4);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, sx);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, sy);
+
+ return 0;
+}
+
+static void
+nv50_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_screen *screen = nv50->screen;
+
+ assert(src->format == dest->format);
+
+ nv50_surface_do_copy(screen, dest, destx, desty, src, srcx,
+ srcy, width, height);
+}
+
+static void
+nv50_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+ unsigned destx, unsigned desty, unsigned width,
+ unsigned height, unsigned value)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_screen *screen = nv50->screen;
+ struct nouveau_channel *chan = screen->eng2d->channel;
+ struct nouveau_grobj *eng2d = screen->eng2d;
+ int format, ret;
+
+ format = nv50_format(dest->format);
+ if (format < 0)
+ return;
+
+ WAIT_RING (chan, 32);
+
+ ret = nv50_surface_set(screen, dest, 1);
+ if (ret)
+ return;
+
+ BEGIN_RING(chan, eng2d, 0x0580, 3);
+ OUT_RING (chan, 4);
+ OUT_RING (chan, format);
+ OUT_RING (chan, value);
+ BEGIN_RING(chan, eng2d, NV50_2D_RECT_X1, 4);
+ OUT_RING (chan, destx);
+ OUT_RING (chan, desty);
+ OUT_RING (chan, width);
+ OUT_RING (chan, height);
+}
+
+void
+nv50_init_surface_functions(struct nv50_context *nv50)
+{
+ nv50->pipe.surface_copy = nv50_surface_copy;
+ nv50->pipe.surface_fill = nv50_surface_fill;
+}
+
+
diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c
new file mode 100644
index 0000000000..033cb50c11
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_tex.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION 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 "nv50_context.h"
+#include "nv50_texture.h"
+
+#include "nouveau/nouveau_stateobj.h"
+
+static int
+nv50_tex_construct(struct nv50_context *nv50, struct nouveau_stateobj *so,
+ struct nv50_miptree *mt, int unit)
+{
+ switch (mt->base.base.format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_8_8_8_8);
+ break;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_1_5_5_5);
+ break;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_4_4_4_4);
+ break;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ so_data(so, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_5_6_5);
+ break;
+ case PIPE_FORMAT_L8_UNORM:
+ so_data(so, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C0 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_8);
+ break;
+ case PIPE_FORMAT_A8_UNORM:
+ so_data(so, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_8);
+ break;
+ case PIPE_FORMAT_I8_UNORM:
+ so_data(so, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C0 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_8);
+ break;
+ case PIPE_FORMAT_A8L8_UNORM:
+ so_data(so, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C0 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_8_8);
+ break;
+ case PIPE_FORMAT_DXT1_RGB:
+ so_data(so, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_DXT1);
+ break;
+ case PIPE_FORMAT_DXT1_RGBA:
+ so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_DXT1);
+ break;
+ case PIPE_FORMAT_DXT3_RGBA:
+ so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_DXT3);
+ break;
+ case PIPE_FORMAT_DXT5_RGBA:
+ so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
+ NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+ NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+ NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM |
+ NV50TIC_0_0_FMT_DXT5);
+ break;
+ default:
+ return 1;
+ }
+
+ so_reloc(so, mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW |
+ NOUVEAU_BO_RD, 0, 0);
+ if (nv50->sampler[unit]->normalized)
+ so_data (so, 0xd0005000 | mt->base.bo->tile_mode << 22);
+ else
+ so_data (so, 0x5001d000 | mt->base.bo->tile_mode << 22);
+ so_data (so, 0x00300000);
+ so_data (so, mt->base.base.width[0]);
+ so_data (so, (mt->base.base.last_level << 28) |
+ (mt->base.base.depth[0] << 16) | mt->base.base.height[0]);
+ so_data (so, 0x03000000);
+ so_data (so, mt->base.base.last_level << 4);
+
+ return 0;
+}
+
+void
+nv50_tex_validate(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nouveau_stateobj *so;
+ int unit, push;
+
+ push = nv50->miptree_nr * 9 + 2;
+ push += MAX2(nv50->miptree_nr, nv50->state.miptree_nr) * 2;
+
+ so = so_new(push, nv50->miptree_nr * 2);
+ so_method(so, tesla, NV50TCL_CB_ADDR, 1);
+ so_data (so, NV50_CB_TIC);
+ for (unit = 0; unit < nv50->miptree_nr; unit++) {
+ struct nv50_miptree *mt = nv50->miptree[unit];
+
+ so_method(so, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 8);
+ if (nv50_tex_construct(nv50, so, mt, unit)) {
+ NOUVEAU_ERR("failed tex validate\n");
+ so_ref(NULL, &so);
+ return;
+ }
+
+ so_method(so, tesla, NV50TCL_SET_SAMPLER_TEX, 1);
+ so_data (so, (unit << NV50TCL_SET_SAMPLER_TEX_TIC_SHIFT) |
+ (unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) |
+ NV50TCL_SET_SAMPLER_TEX_VALID);
+ }
+
+ for (; unit < nv50->state.miptree_nr; unit++) {
+ so_method(so, tesla, NV50TCL_SET_SAMPLER_TEX, 1);
+ so_data (so,
+ (unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) | 0);
+ }
+
+ so_ref(so, &nv50->state.tic_upload);
+ so_ref(NULL, &so);
+ nv50->state.miptree_nr = nv50->miptree_nr;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_texture.h b/src/gallium/drivers/nv50/nv50_texture.h
new file mode 100644
index 0000000000..207fb039f7
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_texture.h
@@ -0,0 +1,150 @@
+#ifndef __NV50_TEXTURE_H__
+#define __NV50_TEXTURE_H__
+
+/* It'd be really nice to have these in nouveau_class.h generated by
+ * renouveau like the rest of the object header - but not sure it can
+ * handle non-object stuff nicely - need to look into it.
+ */
+
+/* Texture image control block */
+#define NV50TIC_0_0_MAPA_MASK 0x38000000
+#define NV50TIC_0_0_MAPA_ZERO 0x00000000
+#define NV50TIC_0_0_MAPA_C0 0x10000000
+#define NV50TIC_0_0_MAPA_C1 0x18000000
+#define NV50TIC_0_0_MAPA_C2 0x20000000
+#define NV50TIC_0_0_MAPA_C3 0x28000000
+#define NV50TIC_0_0_MAPA_ONE 0x38000000
+#define NV50TIC_0_0_MAPB_MASK 0x07000000
+#define NV50TIC_0_0_MAPB_ZERO 0x00000000
+#define NV50TIC_0_0_MAPB_C0 0x02000000
+#define NV50TIC_0_0_MAPB_C1 0x03000000
+#define NV50TIC_0_0_MAPB_C2 0x04000000
+#define NV50TIC_0_0_MAPB_C3 0x05000000
+#define NV50TIC_0_0_MAPB_ONE 0x07000000
+#define NV50TIC_0_0_MAPG_MASK 0x00e00000
+#define NV50TIC_0_0_MAPG_ZERO 0x00000000
+#define NV50TIC_0_0_MAPG_C0 0x00400000
+#define NV50TIC_0_0_MAPG_C1 0x00600000
+#define NV50TIC_0_0_MAPG_C2 0x00800000
+#define NV50TIC_0_0_MAPG_C3 0x00a00000
+#define NV50TIC_0_0_MAPG_ONE 0x00e00000
+#define NV50TIC_0_0_MAPR_MASK 0x001c0000
+#define NV50TIC_0_0_MAPR_ZERO 0x00000000
+#define NV50TIC_0_0_MAPR_C0 0x00080000
+#define NV50TIC_0_0_MAPR_C1 0x000c0000
+#define NV50TIC_0_0_MAPR_C2 0x00100000
+#define NV50TIC_0_0_MAPR_C3 0x00140000
+#define NV50TIC_0_0_MAPR_ONE 0x001c0000
+#define NV50TIC_0_0_TYPEA_MASK 0x00038000
+#define NV50TIC_0_0_TYPEA_UNORM 0x00010000
+#define NV50TIC_0_0_TYPEA_SNORM 0x00008000
+#define NV50TIC_0_0_TYPEA_FLOAT 0x00038000
+#define NV50TIC_0_0_TYPEB_MASK 0x00007000
+#define NV50TIC_0_0_TYPEB_UNORM 0x00002000
+#define NV50TIC_0_0_TYPEB_SNORM 0x00001000
+#define NV50TIC_0_0_TYPEB_FLOAT 0x00007000
+#define NV50TIC_0_0_TYPEG_MASK 0x00000e00
+#define NV50TIC_0_0_TYPEG_UNORM 0x00000400
+#define NV50TIC_0_0_TYPEG_SNORM 0x00000200
+#define NV50TIC_0_0_TYPEG_FLOAT 0x00000e00
+#define NV50TIC_0_0_TYPER_MASK 0x000001c0
+#define NV50TIC_0_0_TYPER_UNORM 0x00000080
+#define NV50TIC_0_0_TYPER_SNORM 0x00000040
+#define NV50TIC_0_0_TYPER_FLOAT 0x000001c0
+#define NV50TIC_0_0_FMT_MASK 0x0000003f
+#define NV50TIC_0_0_FMT_32_32_32_32 0x00000001
+#define NV50TIC_0_0_FMT_16_16_16_16 0x00000003
+#define NV50TIC_0_0_FMT_32_32 0x00000004
+#define NV50TIC_0_0_FMT_8_8_8_8 0x00000008
+#define NV50TIC_0_0_FMT_2_10_10_10 0x00000009
+#define NV50TIC_0_0_FMT_32 0x0000000f
+#define NV50TIC_0_0_FMT_4_4_4_4 0x00000012
+/* #define NV50TIC_0_0_FMT_1_5_5_5 0x00000013 */
+#define NV50TIC_0_0_FMT_1_5_5_5 0x00000014
+#define NV50TIC_0_0_FMT_5_6_5 0x00000015
+#define NV50TIC_0_0_FMT_8_8 0x00000018
+#define NV50TIC_0_0_FMT_16 0x0000001b
+#define NV50TIC_0_0_FMT_8 0x0000001d
+#define NV50TIC_0_0_FMT_10_11_11 0x00000021
+#define NV50TIC_0_0_FMT_DXT1 0x00000024
+#define NV50TIC_0_0_FMT_DXT3 0x00000025
+#define NV50TIC_0_0_FMT_DXT5 0x00000026
+#define NV50TIC_0_0_FMT_RGTC1 0x00000027
+#define NV50TIC_0_0_FMT_RGTC2 0x00000028
+
+#define NV50TIC_0_1_OFFSET_LOW_MASK 0xffffffff
+#define NV50TIC_0_1_OFFSET_LOW_SHIFT 0
+
+#define NV50TIC_0_2_UNKNOWN_MASK 0xffffffff
+
+#define NV50TIC_0_3_UNKNOWN_MASK 0xffffffff
+
+#define NV50TIC_0_4_WIDTH_MASK 0x0000ffff
+#define NV50TIC_0_4_WIDTH_SHIFT 0
+
+#define NV50TIC_0_5_DEPTH_MASK 0xffff0000
+#define NV50TIC_0_5_DEPTH_SHIFT 16
+#define NV50TIC_0_5_HEIGHT_MASK 0x0000ffff
+#define NV50TIC_0_5_HEIGHT_SHIFT 0
+
+#define NV50TIC_0_6_UNKNOWN_MASK 0xffffffff
+
+#define NV50TIC_0_7_OFFSET_HIGH_MASK 0xffffffff
+#define NV50TIC_0_7_OFFSET_HIGH_SHIFT 0
+
+/* Texture sampler control block */
+#define NV50TSC_1_0_WRAPS_MASK 0x00000007
+#define NV50TSC_1_0_WRAPS_REPEAT 0x00000000
+#define NV50TSC_1_0_WRAPS_MIRROR_REPEAT 0x00000001
+#define NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE 0x00000002
+#define NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER 0x00000003
+#define NV50TSC_1_0_WRAPS_CLAMP 0x00000004
+#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE 0x00000005
+#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER 0x00000006
+#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP 0x00000007
+#define NV50TSC_1_0_WRAPT_MASK 0x00000038
+#define NV50TSC_1_0_WRAPT_REPEAT 0x00000000
+#define NV50TSC_1_0_WRAPT_MIRROR_REPEAT 0x00000008
+#define NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE 0x00000010
+#define NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER 0x00000018
+#define NV50TSC_1_0_WRAPT_CLAMP 0x00000020
+#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP_TO_EDGE 0x00000028
+#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP_TO_BORDER 0x00000030
+#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP 0x00000038
+#define NV50TSC_1_0_WRAPR_MASK 0x000001c0
+#define NV50TSC_1_0_WRAPR_REPEAT 0x00000000
+#define NV50TSC_1_0_WRAPR_MIRROR_REPEAT 0x00000040
+#define NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE 0x00000080
+#define NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER 0x000000c0
+#define NV50TSC_1_0_WRAPR_CLAMP 0x00000100
+#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_EDGE 0x00000140
+#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_BORDER 0x00000180
+#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP 0x000001c0
+#define NV50TSC_1_0_MAX_ANISOTROPY_MASK 0x00700000
+
+#define NV50TSC_1_1_MAGF_MASK 0x00000003
+#define NV50TSC_1_1_MAGF_NEAREST 0x00000001
+#define NV50TSC_1_1_MAGF_LINEAR 0x00000002
+#define NV50TSC_1_1_MINF_MASK 0x00000030
+#define NV50TSC_1_1_MINF_NEAREST 0x00000010
+#define NV50TSC_1_1_MINF_LINEAR 0x00000020
+#define NV50TSC_1_1_MIPF_MASK 0x000000c0
+#define NV50TSC_1_1_MIPF_NONE 0x00000040
+#define NV50TSC_1_1_MIPF_NEAREST 0x00000080
+#define NV50TSC_1_1_MIPF_LINEAR 0x000000c0
+#define NV50TSC_1_1_LOD_BIAS_MASK 0x01fff000
+
+#define NV50TSC_1_2_MIN_LOD_MASK 0x00000f00
+#define NV50TSC_1_2_MAX_LOD_MASK 0x00f00000
+
+#define NV50TSC_1_3_UNKNOWN_MASK 0xffffffff
+
+#define NV50TSC_1_4_BORDER_COLOR_RED_MASK 0xffffffff
+
+#define NV50TSC_1_5_BORDER_COLOR_GREEN_MASK 0xffffffff
+
+#define NV50TSC_1_6_BORDER_COLOR_BLUE_MASK 0xffffffff
+
+#define NV50TSC_1_7_BORDER_COLOR_ALPHA_MASK 0xffffffff
+
+#endif
diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c
new file mode 100644
index 0000000000..e9c3562194
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_transfer.c
@@ -0,0 +1,239 @@
+
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+
+#include "nv50_context.h"
+
+struct nv50_transfer {
+ struct pipe_transfer base;
+ struct nouveau_bo *bo;
+ unsigned level_offset;
+ unsigned level_tiling;
+ int level_pitch;
+ int level_width;
+ int level_height;
+ int level_x;
+ int level_y;
+};
+
+static void
+nv50_transfer_rect_m2mf(struct pipe_screen *pscreen,
+ struct nouveau_bo *src_bo, unsigned src_offset,
+ int src_pitch, unsigned src_tile_mode,
+ int sx, int sy, int sw, int sh,
+ struct nouveau_bo *dst_bo, unsigned dst_offset,
+ int dst_pitch, unsigned dst_tile_mode,
+ int dx, int dy, int dw, int dh,
+ int cpp, int width, int height,
+ unsigned src_reloc, unsigned dst_reloc)
+{
+ struct nv50_screen *screen = nv50_screen(pscreen);
+ struct nouveau_channel *chan = screen->m2mf->channel;
+ struct nouveau_grobj *m2mf = screen->m2mf;
+
+ src_reloc |= NOUVEAU_BO_RD;
+ dst_reloc |= NOUVEAU_BO_WR;
+
+ WAIT_RING (chan, 14);
+
+ if (!src_bo->tile_flags) {
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_PITCH_IN, 1);
+ OUT_RING (chan, src_pitch);
+ src_offset += (sy * src_pitch) + (sx * cpp);
+ } else {
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 6);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, src_tile_mode << 4);
+ OUT_RING (chan, sw * cpp);
+ OUT_RING (chan, sh);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, 0);
+ }
+
+ if (!dst_bo->tile_flags) {
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 1);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT, 1);
+ OUT_RING (chan, dst_pitch);
+ dst_offset += (dy * dst_pitch) + (dx * cpp);
+ } else {
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 6);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, dst_tile_mode << 4);
+ OUT_RING (chan, dw * cpp);
+ OUT_RING (chan, dh);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, 0);
+ }
+
+ while (height) {
+ int line_count = height > 2047 ? 2047 : height;
+
+ WAIT_RING (chan, 15);
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH, 2);
+ OUT_RELOCh(chan, src_bo, src_offset, src_reloc);
+ OUT_RELOCh(chan, dst_bo, dst_offset, dst_reloc);
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 2);
+ OUT_RELOCl(chan, src_bo, src_offset, src_reloc);
+ OUT_RELOCl(chan, dst_bo, dst_offset, dst_reloc);
+ if (src_bo->tile_flags) {
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_IN, 1);
+ OUT_RING (chan, (sy << 16) | sx);
+ } else {
+ src_offset += (line_count * src_pitch);
+ }
+ if (dst_bo->tile_flags) {
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_OUT, 1);
+ OUT_RING (chan, (dy << 16) | dx);
+ } else {
+ dst_offset += (line_count * dst_pitch);
+ }
+ BEGIN_RING(chan, m2mf,
+ NV50_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN, 4);
+ OUT_RING (chan, width * cpp);
+ OUT_RING (chan, line_count);
+ OUT_RING (chan, 0x00000101);
+ OUT_RING (chan, 0);
+ FIRE_RING (chan);
+
+ height -= line_count;
+ sy += line_count;
+ dy += line_count;
+ }
+}
+
+static struct pipe_transfer *
+nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct nv50_miptree *mt = nv50_miptree(pt);
+ struct nv50_miptree_level *lvl = &mt->level[level];
+ struct nv50_transfer *tx;
+ unsigned image = 0;
+ int ret;
+
+ if (pt->target == PIPE_TEXTURE_CUBE)
+ image = face;
+ else
+ if (pt->target == PIPE_TEXTURE_3D)
+ image = zslice;
+
+ tx = CALLOC_STRUCT(nv50_transfer);
+ if (!tx)
+ return NULL;
+
+ pipe_texture_reference(&tx->base.texture, pt);
+ tx->base.format = pt->format;
+ tx->base.width = w;
+ tx->base.height = h;
+ tx->base.block = pt->block;
+ tx->base.nblocksx = pt->nblocksx[level];
+ tx->base.nblocksy = pt->nblocksy[level];
+ tx->base.stride = (w * pt->block.size);
+ tx->base.usage = usage;
+
+ tx->level_pitch = lvl->pitch;
+ tx->level_width = mt->base.base.width[level];
+ tx->level_height = mt->base.base.height[level];
+ tx->level_offset = lvl->image_offset[image];
+ tx->level_tiling = lvl->tile_mode;
+ tx->level_x = x;
+ tx->level_y = y;
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
+ w * pt->block.size * h, &tx->bo);
+ if (ret) {
+ FREE(tx);
+ return NULL;
+ }
+
+ if (usage != PIPE_TRANSFER_WRITE) {
+ nv50_transfer_rect_m2mf(pscreen, mt->base.bo, tx->level_offset,
+ tx->level_pitch, tx->level_tiling,
+ x, y,
+ tx->level_width, tx->level_height,
+ tx->bo, 0, tx->base.stride,
+ tx->bo->tile_mode, 0, 0,
+ tx->base.width, tx->base.height,
+ tx->base.block.size, w, h,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
+ NOUVEAU_BO_GART);
+ }
+
+ return &tx->base;
+}
+
+static void
+nv50_transfer_del(struct pipe_transfer *ptx)
+{
+ struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
+ struct nv50_miptree *mt = nv50_miptree(ptx->texture);
+
+ if (ptx->usage != PIPE_TRANSFER_READ) {
+ struct pipe_screen *pscreen = ptx->texture->screen;
+ nv50_transfer_rect_m2mf(pscreen, tx->bo, 0, tx->base.stride,
+ tx->bo->tile_mode, 0, 0,
+ tx->base.width, tx->base.height,
+ mt->base.bo, tx->level_offset,
+ tx->level_pitch, tx->level_tiling,
+ tx->level_x, tx->level_y,
+ tx->level_width, tx->level_height,
+ tx->base.block.size, tx->base.width,
+ tx->base.height,
+ NOUVEAU_BO_GART, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_GART);
+ }
+
+ nouveau_bo_ref(NULL, &tx->bo);
+ pipe_texture_reference(&ptx->texture, NULL);
+ FREE(ptx);
+}
+
+static void *
+nv50_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
+ unsigned flags = 0;
+ int ret;
+
+ if (ptx->usage & PIPE_TRANSFER_WRITE)
+ flags |= NOUVEAU_BO_WR;
+ if (ptx->usage & PIPE_TRANSFER_READ)
+ flags |= NOUVEAU_BO_RD;
+
+ ret = nouveau_bo_map(tx->bo, flags);
+ if (ret)
+ return NULL;
+ return tx->bo->map;
+}
+
+static void
+nv50_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx)
+{
+ struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
+
+ nouveau_bo_unmap(tx->bo);
+}
+
+void
+nv50_transfer_init_screen_functions(struct pipe_screen *pscreen)
+{
+ pscreen->get_tex_transfer = nv50_transfer_new;
+ pscreen->tex_transfer_destroy = nv50_transfer_del;
+ pscreen->transfer_map = nv50_transfer_map;
+ pscreen->transfer_unmap = nv50_transfer_unmap;
+}
diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c
new file mode 100644
index 0000000000..eeed148c7b
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_vbo.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "nv50_context.h"
+
+static INLINE unsigned
+nv50_prim(unsigned mode)
+{
+ switch (mode) {
+ case PIPE_PRIM_POINTS: return NV50TCL_VERTEX_BEGIN_POINTS;
+ case PIPE_PRIM_LINES: return NV50TCL_VERTEX_BEGIN_LINES;
+ case PIPE_PRIM_LINE_LOOP: return NV50TCL_VERTEX_BEGIN_LINE_LOOP;
+ case PIPE_PRIM_LINE_STRIP: return NV50TCL_VERTEX_BEGIN_LINE_STRIP;
+ case PIPE_PRIM_TRIANGLES: return NV50TCL_VERTEX_BEGIN_TRIANGLES;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP;
+ case PIPE_PRIM_TRIANGLE_FAN: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN;
+ case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS;
+ case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP;
+ case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON;
+ default:
+ break;
+ }
+
+ NOUVEAU_ERR("invalid primitive type %d\n", mode);
+ return NV50TCL_VERTEX_BEGIN_POINTS;
+}
+
+static INLINE uint32_t
+nv50_vbo_type_to_hw(unsigned type)
+{
+ switch (type) {
+ case PIPE_FORMAT_TYPE_FLOAT:
+ return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT;
+ case PIPE_FORMAT_TYPE_UNORM:
+ return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UNORM;
+ case PIPE_FORMAT_TYPE_SNORM:
+ return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SNORM;
+ case PIPE_FORMAT_TYPE_USCALED:
+ return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_USCALED;
+ case PIPE_FORMAT_TYPE_SSCALED:
+ return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SSCALED;
+ /*
+ case PIPE_FORMAT_TYPE_UINT:
+ return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UINT;
+ case PIPE_FORMAT_TYPE_SINT:
+ return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SINT; */
+ default:
+ return 0;
+ }
+}
+
+static INLINE uint32_t
+nv50_vbo_size_to_hw(unsigned size, unsigned nr_c)
+{
+ static const uint32_t hw_values[] = {
+ 0, 0, 0, 0,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8_8,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8_8_8,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8_8_8_8,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16_16,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16_16_16,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16_16_16_16,
+ 0, 0, 0, 0,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32_32,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32_32_32,
+ NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32_32_32_32 };
+
+ /* we'd also have R11G11B10 and R10G10B10A2 */
+
+ assert(nr_c > 0 && nr_c <= 4);
+
+ if (size > 32)
+ return 0;
+ size >>= (3 - 2);
+
+ return hw_values[size + (nr_c - 1)];
+}
+
+static INLINE uint32_t
+nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve)
+{
+ uint32_t hw_type, hw_size;
+ enum pipe_format pf = ve->src_format;
+ unsigned size = pf_size_x(pf) << pf_exp2(pf);
+
+ hw_type = nv50_vbo_type_to_hw(pf_type(pf));
+ hw_size = nv50_vbo_size_to_hw(size, ve->nr_components);
+
+ if (!hw_type || !hw_size) {
+ NOUVEAU_ERR("unsupported vbo format: %s\n", pf_name(pf));
+ abort();
+ return 0x24e80000;
+ }
+
+ if (pf_swizzle_x(pf) == 2) /* BGRA */
+ hw_size |= (1 << 31); /* no real swizzle bits :-( */
+
+ return (hw_type | hw_size);
+}
+
+boolean
+nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
+ unsigned count)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nouveau_channel *chan = nv50->screen->tesla->channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+
+ nv50_state_validate(nv50);
+
+ BEGIN_RING(chan, tesla, 0x142c, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, tesla, 0x142c, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, tesla, 0x1440, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, tesla, 0x1334, 1);
+ OUT_RING (chan, 0);
+
+ BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
+ OUT_RING (chan, nv50_prim(mode));
+ BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2);
+ OUT_RING (chan, start);
+ OUT_RING (chan, count);
+ BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
+ OUT_RING (chan, 0);
+
+ pipe->flush(pipe, 0, NULL);
+ return TRUE;
+}
+
+static INLINE void
+nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map,
+ unsigned start, unsigned count)
+{
+ struct nouveau_channel *chan = nv50->screen->tesla->channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+
+ map += start;
+
+ if (count & 1) {
+ BEGIN_RING(chan, tesla, 0x15e8, 1);
+ OUT_RING (chan, map[0]);
+ map++;
+ count--;
+ }
+
+ while (count) {
+ unsigned nr = count > 2046 ? 2046 : count;
+ int i;
+
+ BEGIN_RING(chan, tesla, 0x400015f0, nr >> 1);
+ for (i = 0; i < nr; i += 2)
+ OUT_RING (chan, (map[i + 1] << 16) | map[i]);
+
+ count -= nr;
+ map += nr;
+ }
+}
+
+static INLINE void
+nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map,
+ unsigned start, unsigned count)
+{
+ struct nouveau_channel *chan = nv50->screen->tesla->channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+
+ map += start;
+
+ if (count & 1) {
+ BEGIN_RING(chan, tesla, 0x15e8, 1);
+ OUT_RING (chan, map[0]);
+ map++;
+ count--;
+ }
+
+ while (count) {
+ unsigned nr = count > 2046 ? 2046 : count;
+ int i;
+
+ BEGIN_RING(chan, tesla, 0x400015f0, nr >> 1);
+ for (i = 0; i < nr; i += 2)
+ OUT_RING (chan, (map[i + 1] << 16) | map[i]);
+
+ count -= nr;
+ map += nr;
+ }
+}
+
+static INLINE void
+nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint32_t *map,
+ unsigned start, unsigned count)
+{
+ struct nouveau_channel *chan = nv50->screen->tesla->channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+
+ map += start;
+
+ while (count) {
+ unsigned nr = count > 2047 ? 2047 : count;
+
+ BEGIN_RING(chan, tesla, 0x400015e8, nr);
+ OUT_RINGp (chan, map, nr);
+
+ count -= nr;
+ map += nr;
+ }
+}
+
+boolean
+nv50_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer, unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nouveau_channel *chan = nv50->screen->tesla->channel;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct pipe_screen *pscreen = pipe->screen;
+ void *map;
+
+ map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ);
+
+ nv50_state_validate(nv50);
+
+ BEGIN_RING(chan, tesla, 0x142c, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, tesla, 0x142c, 1);
+ OUT_RING (chan, 0);
+
+ BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
+ OUT_RING (chan, nv50_prim(mode));
+ switch (indexSize) {
+ case 1:
+ nv50_draw_elements_inline_u08(nv50, map, start, count);
+ break;
+ case 2:
+ nv50_draw_elements_inline_u16(nv50, map, start, count);
+ break;
+ case 4:
+ nv50_draw_elements_inline_u32(nv50, map, start, count);
+ break;
+ default:
+ assert(0);
+ }
+ BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
+ OUT_RING (chan, 0);
+
+ pipe_buffer_unmap(pscreen, indexBuffer);
+ pipe->flush(pipe, 0, NULL);
+ return TRUE;
+}
+
+static INLINE boolean
+nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib,
+ struct nouveau_stateobj **pso,
+ struct pipe_vertex_element *ve,
+ struct pipe_vertex_buffer *vb)
+
+{
+ struct nouveau_stateobj *so;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nouveau_bo *bo = nouveau_bo(vb->buffer);
+ float *v;
+ int ret;
+ enum pipe_format pf = ve->src_format;
+
+ if ((pf_type(pf) != PIPE_FORMAT_TYPE_FLOAT) ||
+ (pf_size_x(pf) << pf_exp2(pf)) != 32)
+ return FALSE;
+
+ ret = nouveau_bo_map(bo, NOUVEAU_BO_RD);
+ if (ret)
+ return FALSE;
+ v = (float *)(bo->map + (vb->buffer_offset + ve->src_offset));
+
+ so = *pso;
+ if (!so)
+ *pso = so = so_new(nv50->vtxelt_nr * 5, 0);
+
+ switch (ve->nr_components) {
+ case 4:
+ so_method(so, tesla, NV50TCL_VTX_ATTR_4F_X(attrib), 4);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ so_data (so, fui(v[2]));
+ so_data (so, fui(v[3]));
+ break;
+ case 3:
+ so_method(so, tesla, NV50TCL_VTX_ATTR_3F_X(attrib), 3);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ so_data (so, fui(v[2]));
+ break;
+ case 2:
+ so_method(so, tesla, NV50TCL_VTX_ATTR_2F_X(attrib), 2);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ break;
+ case 1:
+ so_method(so, tesla, NV50TCL_VTX_ATTR_1F(attrib), 1);
+ so_data (so, fui(v[0]));
+ break;
+ default:
+ nouveau_bo_unmap(bo);
+ return FALSE;
+ }
+
+ nouveau_bo_unmap(bo);
+ return TRUE;
+}
+
+void
+nv50_vbo_validate(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nouveau_stateobj *vtxbuf, *vtxfmt, *vtxattr;
+ unsigned i;
+
+ /* don't validate if Gallium took away our buffers */
+ if (nv50->vtxbuf_nr == 0)
+ return;
+
+ vtxattr = NULL;
+ vtxbuf = so_new(nv50->vtxelt_nr * 7, nv50->vtxelt_nr * 4);
+ vtxfmt = so_new(nv50->vtxelt_nr + 1, 0);
+ so_method(vtxfmt, tesla, NV50TCL_VERTEX_ARRAY_ATTRIB(0),
+ nv50->vtxelt_nr);
+
+ for (i = 0; i < nv50->vtxelt_nr; i++) {
+ struct pipe_vertex_element *ve = &nv50->vtxelt[i];
+ struct pipe_vertex_buffer *vb =
+ &nv50->vtxbuf[ve->vertex_buffer_index];
+ struct nouveau_bo *bo = nouveau_bo(vb->buffer);
+ uint32_t hw = nv50_vbo_vtxelt_to_hw(ve);
+
+ if (!vb->stride &&
+ nv50_vbo_static_attrib(nv50, i, &vtxattr, ve, vb)) {
+ so_data(vtxfmt, hw | (1 << 4));
+
+ so_method(vtxbuf, tesla,
+ NV50TCL_VERTEX_ARRAY_FORMAT(i), 1);
+ so_data (vtxbuf, 0);
+ continue;
+ }
+ so_data(vtxfmt, hw | i);
+
+ so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 3);
+ so_data (vtxbuf, 0x20000000 | vb->stride);
+ so_reloc (vtxbuf, bo, vb->buffer_offset +
+ ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
+ NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (vtxbuf, bo, vb->buffer_offset +
+ ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
+ NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+
+ /* vertex array limits */
+ so_method(vtxbuf, tesla, 0x1080 + (i * 8), 2);
+ so_reloc (vtxbuf, bo, vb->buffer->size - 1,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD |
+ NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (vtxbuf, bo, vb->buffer->size - 1,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD |
+ NOUVEAU_BO_LOW, 0, 0);
+ }
+
+ so_ref (vtxfmt, &nv50->state.vtxfmt);
+ so_ref (vtxbuf, &nv50->state.vtxbuf);
+ so_ref (vtxattr, &nv50->state.vtxattr);
+ so_ref (NULL, &vtxbuf);
+ so_ref (NULL, &vtxfmt);
+ so_ref (NULL, &vtxattr);
+}
+
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile
new file mode 100644
index 0000000000..93c2152edc
--- /dev/null
+++ b/src/gallium/drivers/r300/Makefile
@@ -0,0 +1,42 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = r300
+
+C_SOURCES = \
+ r3xx_fs.c \
+ r5xx_fs.c \
+ r300_chipset.c \
+ r300_clear.c \
+ r300_context.c \
+ r300_debug.c \
+ r300_emit.c \
+ r300_flush.c \
+ r300_fs.c \
+ r300_query.c \
+ r300_render.c \
+ r300_screen.c \
+ r300_state.c \
+ r300_state_derived.c \
+ r300_state_invariant.c \
+ r300_vs.c \
+ r300_surface.c \
+ r300_texture.c \
+ r300_tgsi_to_rc.c
+
+LIBRARY_INCLUDES = \
+ -I$(TOP)/src/mesa/drivers/dri/r300/compiler \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/include
+
+COMPILER_ARCHIVE = $(TOP)/src/mesa/drivers/dri/r300/compiler/libr300compiler.a
+
+EXTRA_OBJECTS = \
+ $(COMPILER_ARCHIVE)
+
+include ../../Makefile.template
+
+.PHONY : $(COMPILER_ARCHIVE)
+
+$(COMPILER_ARCHIVE):
+ cd $(TOP)/src/mesa/drivers/dri/r300/compiler; make
diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript
new file mode 100644
index 0000000000..493d7b28bc
--- /dev/null
+++ b/src/gallium/drivers/r300/SConscript
@@ -0,0 +1,29 @@
+Import('*')
+
+env = env.Clone()
+
+r300 = env.ConvenienceLibrary(
+ target = 'r300',
+ source = [
+ 'r3xx_fs.c',
+ 'r5xx_fs.c',
+ 'r300_chipset.c',
+ 'r300_clear.c',
+ 'r300_context.c',
+ 'r300_debug.c',
+ 'r300_emit.c',
+ 'r300_flush.c',
+ 'r300_fs.c',
+ 'r300_query.c',
+ 'r300_render.c',
+ 'r300_screen.c',
+ 'r300_state.c',
+ 'r300_state_derived.c',
+ 'r300_state_invariant.c',
+ 'r300_vs.c',
+ 'r300_surface.c',
+ 'r300_texture.c',
+ ])
+
+Export('r300')
+
diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c
new file mode 100644
index 0000000000..d138866d33
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_chipset.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_chipset.h"
+#include "util/u_debug.h"
+
+/* r300_chipset: A file all to itself for deducing the various properties of
+ * Radeons. */
+
+/* Parse a PCI ID and fill an r300_capabilities struct with information. */
+void r300_parse_chipset(struct r300_capabilities* caps)
+{
+ /* Reasonable defaults */
+ caps->num_vert_fpus = 4;
+ caps->has_tcl = getenv("RADEON_NO_TCL") ? FALSE : TRUE;
+ caps->is_r500 = FALSE;
+ caps->high_second_pipe = FALSE;
+
+
+ /* Note: These are not ordered by PCI ID. I leave that task to GCC,
+ * which will perform the ordering while collating jump tables. Instead,
+ * I've tried to group them according to capabilities and age. */
+ switch (caps->pci_id) {
+ case 0x4144:
+ caps->family = CHIP_FAMILY_R300;
+ caps->high_second_pipe = TRUE;
+ break;
+
+ case 0x4145:
+ case 0x4146:
+ case 0x4147:
+ case 0x4E44:
+ case 0x4E45:
+ case 0x4E46:
+ case 0x4E47:
+ caps->family = CHIP_FAMILY_R300;
+ caps->high_second_pipe = TRUE;
+ break;
+
+ case 0x4150:
+ case 0x4151:
+ case 0x4152:
+ case 0x4153:
+ case 0x4154:
+ case 0x4155:
+ case 0x4156:
+ case 0x4E50:
+ case 0x4E51:
+ case 0x4E52:
+ case 0x4E53:
+ case 0x4E54:
+ case 0x4E56:
+ caps->family = CHIP_FAMILY_RV350;
+ caps->high_second_pipe = TRUE;
+ break;
+
+ case 0x4148:
+ case 0x4149:
+ case 0x414A:
+ case 0x414B:
+ case 0x4E48:
+ case 0x4E49:
+ case 0x4E4B:
+ caps->family = CHIP_FAMILY_R350;
+ caps->high_second_pipe = TRUE;
+ break;
+
+ case 0x4E4A:
+ caps->family = CHIP_FAMILY_R360;
+ caps->high_second_pipe = TRUE;
+ break;
+
+ case 0x5460:
+ case 0x5462:
+ case 0x5464:
+ case 0x5B60:
+ case 0x5B62:
+ case 0x5B63:
+ case 0x5B64:
+ case 0x5B65:
+ caps->family = CHIP_FAMILY_RV370;
+ caps->high_second_pipe = TRUE;
+ break;
+
+ case 0x3150:
+ case 0x3152:
+ case 0x3154:
+ case 0x3E50:
+ case 0x3E54:
+ caps->family = CHIP_FAMILY_RV380;
+ caps->high_second_pipe = TRUE;
+ break;
+
+ case 0x4A48:
+ case 0x4A49:
+ case 0x4A4A:
+ case 0x4A4B:
+ case 0x4A4C:
+ case 0x4A4D:
+ case 0x4A4E:
+ case 0x4A4F:
+ case 0x4A50:
+ case 0x4A54:
+ caps->family = CHIP_FAMILY_R420;
+ caps->num_vert_fpus = 6;
+ break;
+
+ case 0x5548:
+ case 0x5549:
+ case 0x554A:
+ case 0x554B:
+ case 0x5550:
+ case 0x5551:
+ case 0x5552:
+ case 0x5554:
+ case 0x5D57:
+ caps->family = CHIP_FAMILY_R423;
+ caps->num_vert_fpus = 6;
+ break;
+
+ case 0x554C:
+ case 0x554D:
+ case 0x554E:
+ case 0x554F:
+ case 0x5D48:
+ case 0x5D49:
+ case 0x5D4A:
+ caps->family = CHIP_FAMILY_R430;
+ caps->num_vert_fpus = 6;
+ break;
+
+ case 0x5D4C:
+ case 0x5D4D:
+ case 0x5D4E:
+ case 0x5D4F:
+ case 0x5D50:
+ case 0x5D52:
+ caps->family = CHIP_FAMILY_R480;
+ caps->num_vert_fpus = 6;
+ break;
+
+ case 0x4B48:
+ case 0x4B49:
+ case 0x4B4A:
+ case 0x4B4B:
+ case 0x4B4C:
+ caps->family = CHIP_FAMILY_R481;
+ caps->num_vert_fpus = 6;
+ break;
+
+ case 0x5E4C:
+ case 0x5E4F:
+ case 0x564A:
+ case 0x564B:
+ case 0x564F:
+ case 0x5652:
+ case 0x5653:
+ case 0x5657:
+ case 0x5E48:
+ case 0x5E4A:
+ case 0x5E4B:
+ case 0x5E4D:
+ caps->family = CHIP_FAMILY_RV410;
+ caps->num_vert_fpus = 6;
+ break;
+
+ case 0x5954:
+ case 0x5955:
+ caps->family = CHIP_FAMILY_RS480;
+ caps->has_tcl = FALSE;
+ break;
+
+ case 0x5974:
+ case 0x5975:
+ caps->family = CHIP_FAMILY_RS482;
+ caps->has_tcl = FALSE;
+ break;
+
+ case 0x5A41:
+ case 0x5A42:
+ caps->family = CHIP_FAMILY_RS400;
+ caps->has_tcl = FALSE;
+ break;
+
+ case 0x5A61:
+ case 0x5A62:
+ caps->family = CHIP_FAMILY_RC410;
+ caps->has_tcl = FALSE;
+ break;
+
+ case 0x791E:
+ case 0x791F:
+ caps->family = CHIP_FAMILY_RS690;
+ caps->has_tcl = FALSE;
+ break;
+
+ case 0x793F:
+ case 0x7941:
+ case 0x7942:
+ caps->family = CHIP_FAMILY_RS600;
+ caps->has_tcl = FALSE;
+ break;
+
+ case 0x796C:
+ case 0x796D:
+ case 0x796E:
+ case 0x796F:
+ caps->family = CHIP_FAMILY_RS740;
+ caps->has_tcl = FALSE;
+ break;
+
+ case 0x7100:
+ case 0x7101:
+ case 0x7102:
+ case 0x7103:
+ case 0x7104:
+ case 0x7105:
+ case 0x7106:
+ case 0x7108:
+ case 0x7109:
+ case 0x710A:
+ case 0x710B:
+ case 0x710C:
+ case 0x710E:
+ case 0x710F:
+ caps->family = CHIP_FAMILY_R520;
+ caps->num_vert_fpus = 8;
+ caps->is_r500 = TRUE;
+ break;
+
+ case 0x7140:
+ case 0x7141:
+ case 0x7142:
+ case 0x7143:
+ case 0x7144:
+ case 0x7145:
+ case 0x7146:
+ case 0x7147:
+ case 0x7149:
+ case 0x714A:
+ case 0x714B:
+ case 0x714C:
+ case 0x714D:
+ case 0x714E:
+ case 0x714F:
+ case 0x7151:
+ case 0x7152:
+ case 0x7153:
+ case 0x715E:
+ case 0x715F:
+ case 0x7180:
+ case 0x7181:
+ case 0x7183:
+ case 0x7186:
+ case 0x7187:
+ case 0x7188:
+ case 0x718A:
+ case 0x718B:
+ case 0x718C:
+ case 0x718D:
+ case 0x718F:
+ case 0x7193:
+ case 0x7196:
+ case 0x719B:
+ case 0x719F:
+ case 0x7200:
+ case 0x7210:
+ case 0x7211:
+ caps->family = CHIP_FAMILY_RV515;
+ caps->num_vert_fpus = 2;
+ caps->is_r500 = TRUE;
+ break;
+
+ case 0x71C0:
+ case 0x71C1:
+ case 0x71C2:
+ case 0x71C3:
+ case 0x71C4:
+ case 0x71C5:
+ case 0x71C6:
+ case 0x71C7:
+ case 0x71CD:
+ case 0x71CE:
+ case 0x71D2:
+ case 0x71D4:
+ case 0x71D5:
+ case 0x71D6:
+ case 0x71DA:
+ case 0x71DE:
+ caps->family = CHIP_FAMILY_RV530;
+ caps->num_vert_fpus = 5;
+ caps->is_r500 = TRUE;
+ break;
+
+ case 0x7240:
+ case 0x7243:
+ case 0x7244:
+ case 0x7245:
+ case 0x7246:
+ case 0x7247:
+ case 0x7248:
+ case 0x7249:
+ case 0x724A:
+ case 0x724B:
+ case 0x724C:
+ case 0x724D:
+ case 0x724E:
+ case 0x724F:
+ case 0x7284:
+ caps->family = CHIP_FAMILY_R580;
+ caps->num_vert_fpus = 8;
+ caps->is_r500 = TRUE;
+ break;
+
+ case 0x7280:
+ caps->family = CHIP_FAMILY_RV570;
+ caps->num_vert_fpus = 5;
+ caps->is_r500 = TRUE;
+ break;
+
+ case 0x7281:
+ case 0x7283:
+ case 0x7287:
+ case 0x7288:
+ case 0x7289:
+ case 0x728B:
+ case 0x728C:
+ case 0x7290:
+ case 0x7291:
+ case 0x7293:
+ case 0x7297:
+ caps->family = CHIP_FAMILY_RV560;
+ caps->num_vert_fpus = 5;
+ caps->is_r500 = TRUE;
+ break;
+
+ default:
+ debug_printf("r300: Warning: Unknown chipset 0x%x\n",
+ caps->pci_id);
+ break;
+ }
+}
diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h
new file mode 100644
index 0000000000..322d4a57e4
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_chipset.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_CHIPSET_H
+#define R300_CHIPSET_H
+
+#include "pipe/p_compiler.h"
+
+/* Structure containing all the possible information about a specific Radeon
+ * in the R3xx, R4xx, and R5xx families. */
+struct r300_capabilities {
+ /* PCI ID */
+ uint32_t pci_id;
+ /* Chipset family */
+ int family;
+ /* The number of vertex floating-point units */
+ int num_vert_fpus;
+ /* The number of fragment pipes */
+ int num_frag_pipes;
+ /* Whether or not TCL is physically present */
+ boolean has_tcl;
+ /* Whether or not this is an RV515 or newer; R500s have many differences
+ * that require extra consideration, compared to their R3xx cousins:
+ * - Extra bit of width and height on texture sizes
+ * - Blend color is split across two registers
+ * - Universal Shader (US) block used for fragment shaders */
+ boolean is_r500;
+ /* Whether or not the second pixel pipe is accessed with the high bit */
+ boolean high_second_pipe;
+};
+
+/* Enumerations for legibility and telling which card we're running on. */
+enum {
+ CHIP_FAMILY_R300 = 0,
+ CHIP_FAMILY_R350,
+ CHIP_FAMILY_R360,
+ CHIP_FAMILY_RV350,
+ CHIP_FAMILY_RV370,
+ CHIP_FAMILY_RV380,
+ CHIP_FAMILY_R420,
+ CHIP_FAMILY_R423,
+ CHIP_FAMILY_R430,
+ CHIP_FAMILY_R480,
+ CHIP_FAMILY_R481,
+ CHIP_FAMILY_RV410,
+ CHIP_FAMILY_RS400,
+ CHIP_FAMILY_RC410,
+ CHIP_FAMILY_RS480,
+ CHIP_FAMILY_RS482,
+ CHIP_FAMILY_RS600,
+ CHIP_FAMILY_RS690,
+ CHIP_FAMILY_RS740,
+ CHIP_FAMILY_RV515,
+ CHIP_FAMILY_R520,
+ CHIP_FAMILY_RV530,
+ CHIP_FAMILY_R580,
+ CHIP_FAMILY_RV560,
+ CHIP_FAMILY_RV570
+};
+
+void r300_parse_chipset(struct r300_capabilities* caps);
+
+#endif /* R300_CHIPSET_H */
diff --git a/src/gallium/drivers/r300/r300_clear.c b/src/gallium/drivers/r300/r300_clear.c
new file mode 100644
index 0000000000..8b9cb819ae
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_clear.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_clear.h"
+
+/* Clears currently bound buffers. */
+void r300_clear(struct pipe_context* pipe,
+ unsigned buffers,
+ const float* rgba,
+ double depth,
+ unsigned stencil)
+{
+ /* XXX we can and should do one clear if both color and zs are set */
+ util_clear(pipe, &r300_context(pipe)->framebuffer_state,
+ buffers, rgba, depth, stencil);
+}
diff --git a/src/gallium/drivers/r300/r300_clear.h b/src/gallium/drivers/r300/r300_clear.h
new file mode 100644
index 0000000000..cd5900565e
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_clear.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_CLEAR_H
+#define R300_CLEAR_H
+
+#include "util/u_clear.h"
+
+#include "r300_context.h"
+
+void r300_clear(struct pipe_context* pipe,
+ unsigned buffers,
+ const float* rgba,
+ double depth,
+ unsigned stencil);
+
+#endif /* R300_CLEAR_H */
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
new file mode 100644
index 0000000000..9cc455135d
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_context.h"
+
+#include "r300_flush.h"
+#include "r300_state_invariant.h"
+
+static boolean r300_draw_range_elements(struct pipe_context* pipe,
+ struct pipe_buffer* indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ int i;
+
+ for (i = 0; i < r300->vertex_buffer_count; i++) {
+ void* buf = pipe_buffer_map(pipe->screen,
+ r300->vertex_buffers[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_vertex_buffer(r300->draw, i, buf);
+ }
+
+ if (indexBuffer) {
+ void* indices = pipe_buffer_map(pipe->screen, indexBuffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer_range(r300->draw, indexSize,
+ minIndex, maxIndex, indices);
+ } else {
+ draw_set_mapped_element_buffer(r300->draw, 0, NULL);
+ }
+
+ draw_set_mapped_constant_buffer(r300->draw,
+ r300->shader_constants[PIPE_SHADER_VERTEX].constants,
+ r300->shader_constants[PIPE_SHADER_VERTEX].count *
+ (sizeof(float) * 4));
+
+ draw_arrays(r300->draw, mode, start, count);
+
+ for (i = 0; i < r300->vertex_buffer_count; i++) {
+ pipe_buffer_unmap(pipe->screen, r300->vertex_buffers[i].buffer);
+ draw_set_mapped_vertex_buffer(r300->draw, i, NULL);
+ }
+
+ if (indexBuffer) {
+ pipe_buffer_unmap(pipe->screen, indexBuffer);
+ draw_set_mapped_element_buffer_range(r300->draw, 0, start,
+ start + count - 1, NULL);
+ }
+
+ return TRUE;
+}
+
+static boolean r300_draw_elements(struct pipe_context* pipe,
+ struct pipe_buffer* indexBuffer,
+ unsigned indexSize, unsigned mode,
+ unsigned start, unsigned count)
+{
+ return r300_draw_range_elements(pipe, indexBuffer, indexSize, 0, ~0,
+ mode, start, count);
+}
+
+static boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
+ unsigned start, unsigned count)
+{
+ return r300_draw_elements(pipe, NULL, 0, mode, start, count);
+}
+
+static void r300_destroy_context(struct pipe_context* context) {
+ struct r300_context* r300 = r300_context(context);
+ struct r300_query* query, * temp;
+
+ draw_destroy(r300->draw);
+
+ /* Free the OQ BO. */
+ context->screen->buffer_destroy(r300->oqbo);
+
+ /* If there are any queries pending or not destroyed, remove them now. */
+ if (r300->query_list) {
+ foreach_s(query, temp, r300->query_list) {
+ remove_from_list(query);
+ FREE(query);
+ }
+ }
+
+ FREE(r300->blend_color_state);
+ FREE(r300->rs_block);
+ FREE(r300->scissor_state);
+ FREE(r300->viewport_state);
+ FREE(r300);
+}
+
+static unsigned int
+r300_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static unsigned int
+r300_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ /**
+ * FIXME: Optimize.
+ */
+
+ return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+struct pipe_context* r300_create_context(struct pipe_screen* screen,
+ struct r300_winsys* r300_winsys)
+{
+ struct r300_context* r300 = CALLOC_STRUCT(r300_context);
+
+ if (!r300)
+ return NULL;
+
+ r300->winsys = r300_winsys;
+
+ r300->context.winsys = (struct pipe_winsys*)r300_winsys;
+ r300->context.screen = r300_screen(screen);
+
+ r300_init_debug(r300);
+
+ r300->context.destroy = r300_destroy_context;
+
+ r300->context.clear = r300_clear;
+
+ r300->context.draw_arrays = r300_draw_arrays;
+ r300->context.draw_elements = r300_draw_elements;
+ r300->context.draw_range_elements = r300_draw_range_elements;
+
+ r300->context.is_texture_referenced = r300_is_texture_referenced;
+ r300->context.is_buffer_referenced = r300_is_buffer_referenced;
+
+ r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state);
+ r300->rs_block = CALLOC_STRUCT(r300_rs_block);
+ r300->scissor_state = CALLOC_STRUCT(r300_scissor_state);
+ r300->viewport_state = CALLOC_STRUCT(r300_viewport_state);
+
+ /* Create a Draw. This is used for vert collation and SW TCL. */
+ r300->draw = draw_create();
+ /* Enable our renderer. */
+ draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300));
+ /* Disable Draw's clipping if TCL is present. */
+ draw_set_driver_clipping(r300->draw, r300_screen(screen)->caps->has_tcl);
+ /* Force Draw to never do viewport transform, since (again) we can do
+ * transform in hardware, always. */
+ draw_set_viewport_state(r300->draw, &r300_viewport_identity);
+
+ /* Open up the OQ BO. */
+ r300->oqbo = screen->buffer_create(screen, 4096,
+ PIPE_BUFFER_USAGE_VERTEX, 4096);
+
+ r300_init_flush_functions(r300);
+
+ r300_init_query_functions(r300);
+
+ r300_init_surface_functions(r300);
+
+ r300_init_state_functions(r300);
+
+ r300_emit_invariant_state(r300);
+ r300->dirty_state = R300_NEW_KITCHEN_SINK;
+ r300->dirty_hw++;
+
+ return &r300->context;
+}
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
new file mode 100644
index 0000000000..6c5914baa3
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_CONTEXT_H
+#define R300_CONTEXT_H
+
+#include "draw/draw_context.h"
+#include "draw/draw_vertex.h"
+
+#include "pipe/p_context.h"
+
+#include "tgsi/tgsi_scan.h"
+
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+
+#include "r300_clear.h"
+#include "r300_query.h"
+#include "r300_screen.h"
+#include "r300_winsys.h"
+
+struct r300_fragment_shader;
+struct r300_vertex_shader;
+
+struct r300_blend_state {
+ uint32_t blend_control; /* R300_RB3D_CBLEND: 0x4e04 */
+ uint32_t alpha_blend_control; /* R300_RB3D_ABLEND: 0x4e08 */
+ uint32_t rop; /* R300_RB3D_ROPCNTL: 0x4e18 */
+ uint32_t dither; /* R300_RB3D_DITHER_CTL: 0x4e50 */
+};
+
+struct r300_blend_color_state {
+ /* RV515 and earlier */
+ uint32_t blend_color; /* R300_RB3D_BLEND_COLOR: 0x4e10 */
+ /* R520 and newer */
+ uint32_t blend_color_red_alpha; /* R500_RB3D_CONSTANT_COLOR_AR: 0x4ef8 */
+ uint32_t blend_color_green_blue; /* R500_RB3D_CONSTANT_COLOR_GB: 0x4efc */
+};
+
+struct r300_dsa_state {
+ uint32_t alpha_function; /* R300_FG_ALPHA_FUNC: 0x4bd4 */
+ uint32_t alpha_reference; /* R500_FG_ALPHA_VALUE: 0x4be0 */
+ uint32_t z_buffer_control; /* R300_ZB_CNTL: 0x4f00 */
+ uint32_t z_stencil_control; /* R300_ZB_ZSTENCILCNTL: 0x4f04 */
+ uint32_t stencil_ref_mask; /* R300_ZB_STENCILREFMASK: 0x4f08 */
+ uint32_t z_buffer_top; /* R300_ZB_ZTOP: 0x4f14 */
+ uint32_t stencil_ref_bf; /* R500_ZB_STENCILREFMASK_BF: 0x4fd4 */
+};
+
+struct r300_rs_state {
+ /* Draw-specific rasterizer state */
+ struct pipe_rasterizer_state rs;
+
+ /* Whether or not to enable the VTE. This is referenced at the very
+ * last moment during emission of VTE state, to decide whether or not
+ * the VTE should be used for transformation. */
+ boolean enable_vte;
+
+ uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */
+ uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */
+ uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */
+ uint32_t line_control; /* R300_GA_LINE_CNTL: 0x4234 */
+ uint32_t depth_scale_front; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */
+ uint32_t depth_offset_front;/* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */
+ uint32_t depth_scale_back; /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */
+ uint32_t depth_offset_back; /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */
+ uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */
+ uint32_t cull_mode; /* R300_SU_CULL_MODE: 0x42b8 */
+ uint32_t line_stipple_config; /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */
+ uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */
+ uint32_t color_control; /* R300_GA_COLOR_CONTROL: 0x4278 */
+};
+
+struct r300_rs_block {
+ uint32_t ip[8]; /* R300_RS_IP_[0-7], R500_RS_IP_[0-7] */
+ uint32_t count; /* R300_RS_COUNT */
+ uint32_t inst_count; /* R300_RS_INST_COUNT */
+ uint32_t inst[8]; /* R300_RS_INST_[0-7] */
+};
+
+struct r300_sampler_state {
+ uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */
+ uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */
+ uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */
+};
+
+struct r300_scissor_state {
+ uint32_t scissor_top_left; /* R300_SC_SCISSORS_TL: 0x43e0 */
+ uint32_t scissor_bottom_right; /* R300_SC_SCISSORS_BR: 0x43e4 */
+};
+
+struct r300_texture_state {
+ uint32_t format0; /* R300_TX_FORMAT0: 0x4480 */
+ uint32_t format1; /* R300_TX_FORMAT1: 0x44c0 */
+ uint32_t format2; /* R300_TX_FORMAT2: 0x4500 */
+};
+
+struct r300_viewport_state {
+ float xscale; /* R300_VAP_VPORT_XSCALE: 0x2098 */
+ float xoffset; /* R300_VAP_VPORT_XOFFSET: 0x209c */
+ float yscale; /* R300_VAP_VPORT_YSCALE: 0x20a0 */
+ float yoffset; /* R300_VAP_VPORT_YOFFSET: 0x20a4 */
+ float zscale; /* R300_VAP_VPORT_ZSCALE: 0x20a8 */
+ float zoffset; /* R300_VAP_VPORT_ZOFFSET: 0x20ac */
+ uint32_t vte_control; /* R300_VAP_VTE_CNTL: 0x20b0 */
+};
+
+#define R300_NEW_BLEND 0x00000001
+#define R300_NEW_BLEND_COLOR 0x00000002
+#define R300_NEW_CLIP 0x00000004
+#define R300_NEW_CONSTANTS 0x00000008
+#define R300_NEW_DSA 0x00000010
+#define R300_NEW_FRAMEBUFFERS 0x00000020
+#define R300_NEW_FRAGMENT_SHADER 0x00000040
+#define R300_NEW_RASTERIZER 0x00000080
+#define R300_NEW_RS_BLOCK 0x00000100
+#define R300_NEW_SAMPLER 0x00000200
+#define R300_ANY_NEW_SAMPLERS 0x0001fe00
+#define R300_NEW_SCISSOR 0x00020000
+#define R300_NEW_TEXTURE 0x00040000
+#define R300_ANY_NEW_TEXTURES 0x03fc0000
+#define R300_NEW_VERTEX_FORMAT 0x04000000
+#define R300_NEW_VERTEX_SHADER 0x08000000
+#define R300_NEW_VIEWPORT 0x10000000
+#define R300_NEW_KITCHEN_SINK 0x1fffffff
+
+/* The next several objects are not pure Radeon state; they inherit from
+ * various Gallium classes. */
+
+struct r300_constant_buffer {
+ /* Buffer of constants */
+ /* XXX first number should be raised */
+ float constants[32][4];
+ /* Total number of constants */
+ unsigned count;
+};
+
+/* Query object.
+ *
+ * This is not a subclass of pipe_query because pipe_query is never
+ * actually fully defined. So, rather than have it as a member, and do
+ * subclass-style casting, we treat pipe_query as an opaque, and just
+ * trust that our state tracker does not ever mess up query objects.
+ */
+struct r300_query {
+ /* The kind of query. Currently only OQ is supported. */
+ unsigned type;
+ /* Whether this query is currently active. Only active queries will
+ * get emitted into the command stream, and only active queries get
+ * tallied. */
+ boolean active;
+ /* The current count of this query. Required to be at least 32 bits. */
+ unsigned int count;
+ /* The offset of this query into the query buffer, in bytes. */
+ unsigned offset;
+ /* Linked list members. */
+ struct r300_query* prev;
+ struct r300_query* next;
+};
+
+struct r300_texture {
+ /* Parent class */
+ struct pipe_texture tex;
+
+ /* Offsets into the buffer. */
+ unsigned offset[PIPE_MAX_TEXTURE_LEVELS];
+
+ /* Stride (pitch?) of this texture in bytes */
+ unsigned stride;
+
+ /* Total size of this texture, in bytes. */
+ unsigned size;
+
+ /* Pipe buffer backing this texture. */
+ struct pipe_buffer* buffer;
+
+ /* Registers carrying texture format data. */
+ struct r300_texture_state state;
+};
+
+struct r300_vertex_format {
+ /* Parent class */
+ struct vertex_info vinfo;
+ /* R300_VAP_PROG_STREAK_CNTL_[0-7] */
+ uint32_t vap_prog_stream_cntl[8];
+ /* R300_VAP_PROG_STREAK_CNTL_EXT_[0-7] */
+ uint32_t vap_prog_stream_cntl_ext[8];
+ /* Map of vertex attributes into PVS memory for HW TCL,
+ * or GA memory for SW TCL. */
+ int vs_tab[16];
+ /* Map of rasterizer attributes from GB through RS to US. */
+ int fs_tab[16];
+};
+
+extern struct pipe_viewport_state r300_viewport_identity;
+
+struct r300_context {
+ /* Parent class */
+ struct pipe_context context;
+
+ /* The interface to the windowing system, etc. */
+ struct r300_winsys* winsys;
+ /* Draw module. Used mostly for SW TCL. */
+ struct draw_context* draw;
+
+ /* Vertex buffer for rendering. */
+ struct pipe_buffer* vbo;
+ /* Offset into the VBO. */
+ size_t vbo_offset;
+
+ /* Occlusion query buffer. */
+ struct pipe_buffer* oqbo;
+ /* Query list. */
+ struct r300_query* query_list;
+
+ /* Various CSO state objects. */
+ /* Blend state. */
+ struct r300_blend_state* blend_state;
+ /* Blend color state. */
+ struct r300_blend_color_state* blend_color_state;
+ /* User clip planes. */
+ struct pipe_clip_state clip_state;
+ /* Shader constants. */
+ struct r300_constant_buffer shader_constants[PIPE_SHADER_TYPES];
+ /* Depth, stencil, and alpha state. */
+ struct r300_dsa_state* dsa_state;
+ /* Fragment shader. */
+ struct r300_fragment_shader* fs;
+ /* Framebuffer state. We currently don't need our own version of this. */
+ struct pipe_framebuffer_state framebuffer_state;
+ /* Rasterizer state. */
+ struct r300_rs_state* rs_state;
+ /* RS block state. */
+ struct r300_rs_block* rs_block;
+ /* Sampler states. */
+ struct r300_sampler_state* sampler_states[8];
+ int sampler_count;
+ /* Scissor state. */
+ struct r300_scissor_state* scissor_state;
+ /* Texture states. */
+ struct r300_texture* textures[8];
+ int texture_count;
+ /* Vertex buffers for Gallium. */
+ struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
+ int vertex_buffer_count;
+ /* Vertex information. */
+ struct r300_vertex_format vertex_info;
+ /* Vertex shader. */
+ struct r300_vertex_shader* vs;
+ /* Viewport state. */
+ struct r300_viewport_state* viewport_state;
+ /* Bitmask of dirty state objects. */
+ uint32_t dirty_state;
+ /* Flag indicating whether or not the HW is dirty. */
+ uint32_t dirty_hw;
+
+ /** Combination of DBG_xxx flags */
+ unsigned debug;
+};
+
+/* Convenience cast wrapper. */
+static INLINE struct r300_context* r300_context(struct pipe_context* context)
+{
+ return (struct r300_context*)context;
+}
+
+/* Context initialization. */
+struct draw_stage* r300_draw_stage(struct r300_context* r300);
+void r300_init_state_functions(struct r300_context* r300);
+void r300_init_surface_functions(struct r300_context* r300);
+
+/* Debug functionality. */
+
+/**
+ * Debug flags to disable/enable certain groups of debugging outputs.
+ *
+ * \note These may be rather coarse, and the grouping may be impractical.
+ * If you find, while debugging the driver, that a different grouping
+ * of these flags would be beneficial, just feel free to change them
+ * but make sure to update the documentation in r300_debug.c to reflect
+ * those changes.
+ */
+/*@{*/
+#define DBG_HELP 0x0000001
+#define DBG_FP 0x0000002
+#define DBG_VP 0x0000004
+#define DBG_CS 0x0000008
+#define DBG_DRAW 0x0000010
+/*@}*/
+
+static INLINE boolean DBG_ON(struct r300_context * ctx, unsigned flags)
+{
+ return (ctx->debug & flags) ? true : false;
+}
+
+static INLINE void DBG(struct r300_context * ctx, unsigned flags, const char * fmt, ...)
+{
+ if (DBG_ON(ctx, flags)) {
+ va_list va;
+ va_start(va, fmt);
+ debug_vprintf(fmt, va);
+ va_end(va);
+ }
+}
+
+void r300_init_debug(struct r300_context * ctx);
+
+#endif /* R300_CONTEXT_H */
diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h
new file mode 100644
index 0000000000..0a7e470363
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_cs.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_CS_H
+#define R300_CS_H
+
+#include "util/u_math.h"
+
+#include "r300_reg.h"
+#include "r300_winsys.h"
+
+/* Yes, I know macros are ugly. However, they are much prettier than the code
+ * that they neatly hide away, and don't have the cost of function setup,so
+ * we're going to use them. */
+
+#define MAX_CS_SIZE 64 * 1024 / 4
+
+#define VERY_VERBOSE_CS 0
+#define VERY_VERBOSE_REGISTERS 0
+
+/* XXX stolen from radeon_drm.h */
+#define RADEON_GEM_DOMAIN_CPU 0x1
+#define RADEON_GEM_DOMAIN_GTT 0x2
+#define RADEON_GEM_DOMAIN_VRAM 0x4
+
+/* XXX stolen from radeon_reg.h */
+#define RADEON_CP_PACKET0 0x0
+
+#define CP_PACKET0(register, count) \
+ (RADEON_CP_PACKET0 | ((count) << 16) | ((register) >> 2))
+
+#define CS_LOCALS(context) \
+ struct r300_context* const cs_context_copy = (context); \
+ struct r300_winsys* cs_winsys = cs_context_copy->winsys; \
+ int cs_count = 0;
+
+#define CHECK_CS(size) \
+ cs_winsys->check_cs(cs_winsys, (size))
+
+#define BEGIN_CS(size) do { \
+ CHECK_CS(size); \
+ if (VERY_VERBOSE_CS) { \
+ DBG(cs_context_copy, DBG_CS, "r300: BEGIN_CS, count %d, in %s (%s:%d)\n", \
+ size, __FUNCTION__, __FILE__, __LINE__); \
+ } \
+ cs_winsys->begin_cs(cs_winsys, (size), \
+ __FILE__, __FUNCTION__, __LINE__); \
+ cs_count = size; \
+} while (0)
+
+#define OUT_CS(value) do { \
+ cs_winsys->write_cs_dword(cs_winsys, (value)); \
+ cs_count--; \
+} while (0)
+
+#define OUT_CS_32F(value) do { \
+ cs_winsys->write_cs_dword(cs_winsys, fui(value)); \
+ cs_count--; \
+} while (0)
+
+#define OUT_CS_REG(register, value) do { \
+ if (VERY_VERBOSE_REGISTERS) \
+ DBG(cs_context_copy, DBG_CS, "r300: writing 0x%08X to register 0x%04X\n", \
+ value, register); \
+ assert(register); \
+ OUT_CS(CP_PACKET0(register, 0)); \
+ OUT_CS(value); \
+} while (0)
+
+/* Note: This expects count to be the number of registers,
+ * not the actual packet0 count! */
+#define OUT_CS_REG_SEQ(register, count) do { \
+ if (VERY_VERBOSE_REGISTERS) \
+ DBG(cs_context_copy, DBG_CS, "r300: writing register sequence of %d to 0x%04X\n", \
+ count, register); \
+ assert(register); \
+ OUT_CS(CP_PACKET0(register, ((count) - 1))); \
+} while (0)
+
+#define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \
+ DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, offset %d, " \
+ "domains (%d, %d, %d)\n", \
+ bo, offset, rd, wd, flags); \
+ assert(bo); \
+ OUT_CS(offset); \
+ cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \
+ cs_count -= 2; \
+} while (0)
+
+#define END_CS do { \
+ if (VERY_VERBOSE_CS) { \
+ DBG(cs_context_copy, DBG_CS, "r300: END_CS in %s (%s:%d)\n", __FUNCTION__, \
+ __FILE__, __LINE__); \
+ } \
+ if (cs_count != 0) \
+ debug_printf("r300: Warning: cs_count off by %d\n", cs_count); \
+ cs_winsys->end_cs(cs_winsys, __FILE__, __FUNCTION__, __LINE__); \
+} while (0)
+
+#define FLUSH_CS do { \
+ if (VERY_VERBOSE_CS) { \
+ DBG(cs_context_copy, DBG_CS, "r300: FLUSH_CS in %s (%s:%d)\n\n", __FUNCTION__, \
+ __FILE__, __LINE__); \
+ } \
+ cs_winsys->flush_cs(cs_winsys); \
+} while (0)
+
+#define RADEON_ONE_REG_WR (1 << 15)
+
+#define OUT_CS_ONE_REG(register, count) do { \
+ if (VERY_VERBOSE_REGISTERS) \
+ DBG(cs_context_copy, DBG_CS, "r300: writing data sequence of %d to 0x%04X\n", \
+ count, register); \
+ assert(register); \
+ OUT_CS(CP_PACKET0(register, ((count) - 1)) | RADEON_ONE_REG_WR); \
+} while (0)
+
+#define CP_PACKET3(op, count) \
+ (RADEON_CP_PACKET3 | (op) | ((count) << 16))
+
+#define OUT_CS_PKT3(op, count) do { \
+ OUT_CS(CP_PACKET3(op, count)); \
+} while (0)
+
+#define OUT_CS_INDEX_RELOC(bo, offset, count, rd, wd, flags) do { \
+ DBG(cs_context_copy, DBG_CS, "r300: writing relocation for index buffer %p," \
+ "offset %d\n", bo, offset); \
+ assert(bo); \
+ OUT_CS(offset); \
+ OUT_CS(count); \
+ cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \
+ cs_count -= 2; \
+} while (0)
+
+#endif /* R300_CS_H */
diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c
new file mode 100644
index 0000000000..15308dda1d
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_debug.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2009 Nicolai Haehnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_context.h"
+
+#include <ctype.h>
+
+
+struct debug_option {
+ const char * name;
+ unsigned flag;
+ const char * description;
+};
+
+static struct debug_option debug_options[] = {
+ { "help", DBG_HELP, "Helpful meta-information about the driver" },
+ { "fp", DBG_FP, "Fragment program handling" },
+ { "vp", DBG_VP, "Vertex program handling" },
+ { "cs", DBG_CS, "Command submissions" },
+ { "draw", DBG_DRAW, "Draw and emit" },
+
+ { "all", ~0, "Convenience option that enables all debug flags" },
+
+ /* must be last */
+ { 0, 0, 0 }
+};
+
+void r300_init_debug(struct r300_context * ctx)
+{
+ const char * options = debug_get_option("RADEON_DEBUG", 0);
+ boolean printhint = false;
+
+ if (options) {
+ while(*options) {
+ if (*options == ' ' || *options == ',') {
+ options++;
+ continue;
+ }
+
+ size_t length = strcspn(options, " ,");
+ struct debug_option * opt;
+
+ for(opt = debug_options; opt->name; ++opt) {
+ if (!strncmp(options, opt->name, length)) {
+ ctx->debug |= opt->flag;
+ break;
+ }
+ }
+
+ if (!opt->name) {
+ debug_printf("Unknown debug option: %s\n", options);
+ printhint = true;
+ }
+
+ options += length;
+ }
+
+ if (!ctx->debug)
+ printhint = true;
+ }
+
+ if (printhint || ctx->debug & DBG_HELP) {
+ debug_printf("You can enable debug output by setting the RADEON_DEBUG environment variable\n"
+ "to a comma-separated list of debug options. Available options are:\n");
+ for(struct debug_option * opt = debug_options; opt->name; ++opt) {
+ debug_printf(" %s: %s\n", opt->name, opt->description);
+ }
+ }
+}
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
new file mode 100644
index 0000000000..1bc35c2486
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -0,0 +1,813 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* r300_emit: Functions for emitting state. */
+
+#include "r300_emit.h"
+
+#include "r300_fs.h"
+#include "r300_state_derived.h"
+#include "r300_vs.h"
+
+void r300_emit_blend_state(struct r300_context* r300,
+ struct r300_blend_state* blend)
+{
+ CS_LOCALS(r300);
+ BEGIN_CS(7);
+ OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 2);
+ OUT_CS(blend->blend_control);
+ OUT_CS(blend->alpha_blend_control);
+ OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop);
+ OUT_CS_REG(R300_RB3D_DITHER_CTL, blend->dither);
+ END_CS;
+}
+
+void r300_emit_blend_color_state(struct r300_context* r300,
+ struct r300_blend_color_state* bc)
+{
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ CS_LOCALS(r300);
+
+ if (r300screen->caps->is_r500) {
+ BEGIN_CS(3);
+ OUT_CS_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2);
+ OUT_CS(bc->blend_color_red_alpha);
+ OUT_CS(bc->blend_color_green_blue);
+ END_CS;
+ } else {
+ BEGIN_CS(2);
+ OUT_CS_REG(R300_RB3D_BLEND_COLOR, bc->blend_color);
+ END_CS;
+ }
+}
+
+void r300_emit_clip_state(struct r300_context* r300,
+ struct pipe_clip_state* clip)
+{
+ int i;
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ CS_LOCALS(r300);
+
+ if (r300screen->caps->has_tcl) {
+ BEGIN_CS(5 + (6 * 4));
+ OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG,
+ (r300screen->caps->is_r500 ?
+ R500_PVS_UCP_START : R300_PVS_UCP_START));
+ OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, 6 * 4);
+ for (i = 0; i < 6; i++) {
+ OUT_CS_32F(clip->ucp[i][0]);
+ OUT_CS_32F(clip->ucp[i][1]);
+ OUT_CS_32F(clip->ucp[i][2]);
+ OUT_CS_32F(clip->ucp[i][3]);
+ }
+ OUT_CS_REG(R300_VAP_CLIP_CNTL, ((1 << clip->nr) - 1) |
+ R300_PS_UCP_MODE_CLIP_AS_TRIFAN);
+ END_CS;
+ } else {
+ BEGIN_CS(2);
+ OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
+ END_CS;
+ }
+
+}
+
+void r300_emit_dsa_state(struct r300_context* r300,
+ struct r300_dsa_state* dsa)
+{
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ CS_LOCALS(r300);
+
+ BEGIN_CS(r300screen->caps->is_r500 ? 8 : 8);
+ OUT_CS_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function);
+ /* XXX figure out the r300 counterpart for this */
+ if (r300screen->caps->is_r500) {
+ /* OUT_CS_REG(R500_FG_ALPHA_VALUE, dsa->alpha_reference); */
+ }
+ OUT_CS_REG_SEQ(R300_ZB_CNTL, 3);
+ OUT_CS(dsa->z_buffer_control);
+ OUT_CS(dsa->z_stencil_control);
+ OUT_CS(dsa->stencil_ref_mask);
+ OUT_CS_REG(R300_ZB_ZTOP, dsa->z_buffer_top);
+ if (r300screen->caps->is_r500) {
+ /* OUT_CS_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf); */
+ }
+ END_CS;
+}
+
+static const float * get_shader_constant(
+ struct r300_context * r300,
+ struct rc_constant * constant,
+ struct r300_constant_buffer * externals)
+{
+ static const float zero[4] = { 0.0, 0.0, 0.0, 0.0 };
+ switch(constant->Type) {
+ case RC_CONSTANT_EXTERNAL:
+ return externals->constants[constant->u.External];
+
+ case RC_CONSTANT_IMMEDIATE:
+ return constant->u.Immediate;
+
+ default:
+ debug_printf("r300: Implementation error: Unhandled constant type %i\n",
+ constant->Type);
+ return zero;
+ }
+}
+
+/* Convert a normal single-precision float into the 7.16 format
+ * used by the R300 fragment shader.
+ */
+static uint32_t pack_float24(float f)
+{
+ union {
+ float fl;
+ uint32_t u;
+ } u;
+ float mantissa;
+ int exponent;
+ uint32_t float24 = 0;
+
+ if (f == 0.0)
+ return 0;
+
+ u.fl = f;
+
+ mantissa = frexpf(f, &exponent);
+
+ /* Handle -ve */
+ if (mantissa < 0) {
+ float24 |= (1 << 23);
+ mantissa = mantissa * -1.0;
+ }
+ /* Handle exponent, bias of 63 */
+ exponent += 62;
+ float24 |= (exponent << 16);
+ /* Kill 7 LSB of mantissa */
+ float24 |= (u.u & 0x7FFFFF) >> 7;
+
+ return float24;
+}
+
+void r300_emit_fragment_program_code(struct r300_context* r300,
+ struct rX00_fragment_program_code* generic_code,
+ struct r300_constant_buffer* externals)
+{
+ struct r300_fragment_program_code * code = &generic_code->code.r300;
+ struct rc_constant_list * constants = &generic_code->constants;
+ int i;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(15 +
+ code->alu.length * 4 +
+ (code->tex.length ? (1 + code->tex.length) : 0) +
+ (constants->Count ? (1 + constants->Count * 4) : 0));
+
+ OUT_CS_REG(R300_US_CONFIG, code->config);
+ OUT_CS_REG(R300_US_PIXSIZE, code->pixsize);
+ OUT_CS_REG(R300_US_CODE_OFFSET, code->code_offset);
+
+ OUT_CS_REG_SEQ(R300_US_CODE_ADDR_0, 4);
+ for(i = 0; i < 4; ++i)
+ OUT_CS(code->code_addr[i]);
+
+ OUT_CS_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length);
+ for (i = 0; i < code->alu.length; i++)
+ OUT_CS(code->alu.inst[i].rgb_inst);
+
+ OUT_CS_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length);
+ for (i = 0; i < code->alu.length; i++)
+ OUT_CS(code->alu.inst[i].rgb_addr);
+
+ OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length);
+ for (i = 0; i < code->alu.length; i++)
+ OUT_CS(code->alu.inst[i].alpha_inst);
+
+ OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length);
+ for (i = 0; i < code->alu.length; i++)
+ OUT_CS(code->alu.inst[i].alpha_addr);
+
+ if (code->tex.length) {
+ OUT_CS_REG_SEQ(R300_US_TEX_INST_0, code->tex.length);
+ for(i = 0; i < code->tex.length; ++i)
+ OUT_CS(code->tex.inst[i]);
+ }
+
+ if (constants->Count) {
+ OUT_CS_ONE_REG(R300_PFS_PARAM_0_X, constants->Count * 4);
+ for(i = 0; i < constants->Count; ++i) {
+ const float * data = get_shader_constant(r300, &constants->Constants[i], externals);
+ OUT_CS(pack_float24(data[0]));
+ OUT_CS(pack_float24(data[1]));
+ OUT_CS(pack_float24(data[2]));
+ OUT_CS(pack_float24(data[3]));
+ }
+ }
+
+ END_CS;
+}
+
+void r500_emit_fragment_program_code(struct r300_context* r300,
+ struct rX00_fragment_program_code* generic_code,
+ struct r300_constant_buffer* externals)
+{
+ struct r500_fragment_program_code * code = &generic_code->code.r500;
+ struct rc_constant_list * constants = &generic_code->constants;
+ int i;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(13 +
+ ((code->inst_end + 1) * 6) +
+ (constants->Count ? (3 + (constants->Count * 4)) : 0));
+ OUT_CS_REG(R500_US_CONFIG, 0);
+ OUT_CS_REG(R500_US_PIXSIZE, code->max_temp_idx);
+ OUT_CS_REG(R500_US_CODE_RANGE,
+ R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end));
+ OUT_CS_REG(R500_US_CODE_OFFSET, 0);
+ OUT_CS_REG(R500_US_CODE_ADDR,
+ R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end));
+
+ OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_INSTR);
+ OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, (code->inst_end + 1) * 6);
+ for (i = 0; i <= code->inst_end; i++) {
+ OUT_CS(code->inst[i].inst0);
+ OUT_CS(code->inst[i].inst1);
+ OUT_CS(code->inst[i].inst2);
+ OUT_CS(code->inst[i].inst3);
+ OUT_CS(code->inst[i].inst4);
+ OUT_CS(code->inst[i].inst5);
+ }
+
+ if (constants->Count) {
+ OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST);
+ OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->Count * 4);
+ for (i = 0; i < constants->Count; i++) {
+ const float * data = get_shader_constant(r300, &constants->Constants[i], externals);
+ OUT_CS_32F(data[0]);
+ OUT_CS_32F(data[1]);
+ OUT_CS_32F(data[2]);
+ OUT_CS_32F(data[3]);
+ }
+ }
+
+ END_CS;
+}
+
+void r300_emit_fb_state(struct r300_context* r300,
+ struct pipe_framebuffer_state* fb)
+{
+ struct r300_texture* tex;
+ unsigned pixpitch;
+ int i;
+ CS_LOCALS(r300);
+
+ BEGIN_CS((10 * fb->nr_cbufs) + (fb->zsbuf ? 10 : 0) + 4);
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ tex = (struct r300_texture*)fb->cbufs[i]->texture;
+ assert(tex && tex->buffer && "cbuf is marked, but NULL!");
+ pixpitch = tex->stride / tex->tex.block.size;
+
+ OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1);
+ OUT_CS_RELOC(tex->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+ OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1);
+ OUT_CS_RELOC(tex->buffer, pixpitch |
+ r300_translate_colorformat(tex->tex.format), 0,
+ RADEON_GEM_DOMAIN_VRAM, 0);
+
+ OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i),
+ r300_translate_out_fmt(fb->cbufs[i]->format));
+ }
+
+ if (fb->zsbuf) {
+ tex = (struct r300_texture*)fb->zsbuf->texture;
+ assert(tex && tex->buffer && "zsbuf is marked, but NULL!");
+ pixpitch = tex->stride / tex->tex.block.size;
+
+ OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
+ OUT_CS_RELOC(tex->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+ OUT_CS_REG(R300_ZB_FORMAT, r300_translate_zsformat(tex->tex.format));
+
+ OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
+ OUT_CS_RELOC(tex->buffer, pixpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ }
+
+ OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT,
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
+ OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT,
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
+ END_CS;
+}
+
+void r300_emit_query_begin(struct r300_context* r300,
+ struct r300_query* query)
+{
+ CS_LOCALS(r300);
+
+ /* XXX This will almost certainly not return good results
+ * for overlapping queries. */
+ BEGIN_CS(2);
+ OUT_CS_REG(R300_ZB_ZPASS_DATA, 0);
+ END_CS;
+}
+
+void r300_emit_query_end(struct r300_context* r300,
+ struct r300_query* query)
+{
+ struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps;
+ CS_LOCALS(r300);
+
+ if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo,
+ 0, RADEON_GEM_DOMAIN_GTT)) {
+ debug_printf("r300: There wasn't room for the OQ buffer!?"
+ " Oh noes!\n");
+ }
+
+ assert(caps->num_frag_pipes);
+ BEGIN_CS(6 * caps->num_frag_pipes + 2);
+ /* I'm not so sure I like this switch, but it's hard to be elegant
+ * when there's so many special cases...
+ *
+ * So here's the basic idea. For each pipe, enable writes to it only,
+ * then put out the relocation for ZPASS_ADDR, taking into account a
+ * 4-byte offset for each pipe. RV380 and older are special; they have
+ * only two pipes, and the second pipe's enable is on bit 3, not bit 1,
+ * so there's a chipset cap for that. */
+ switch (caps->num_frag_pipes) {
+ 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(r300->oqbo, query->offset + (sizeof(uint32_t) * 3),
+ 0, RADEON_GEM_DOMAIN_GTT, 0);
+ 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(r300->oqbo, query->offset + (sizeof(uint32_t) * 2),
+ 0, RADEON_GEM_DOMAIN_GTT, 0);
+ 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(r300->oqbo, query->offset + (sizeof(uint32_t) * 1),
+ 0, RADEON_GEM_DOMAIN_GTT, 0);
+ 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(r300->oqbo, query->offset + (sizeof(uint32_t) * 0),
+ 0, RADEON_GEM_DOMAIN_GTT, 0);
+ default:
+ debug_printf("r300: Implementation error: Chipset reports %d"
+ " pixel pipes!\n", caps->num_frag_pipes);
+ assert(0);
+ }
+
+ /* And, finally, reset it to normal... */
+ OUT_CS_REG(R300_SU_REG_DEST, 0xF);
+ END_CS;
+
+}
+
+void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs)
+{
+ CS_LOCALS(r300);
+
+ BEGIN_CS(20);
+ OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status);
+ OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size);
+ OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2);
+ OUT_CS(rs->point_minmax);
+ OUT_CS(rs->line_control);
+ OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 6);
+ OUT_CS(rs->depth_scale_front);
+ OUT_CS(rs->depth_offset_front);
+ OUT_CS(rs->depth_scale_back);
+ OUT_CS(rs->depth_offset_back);
+ OUT_CS(rs->polygon_offset_enable);
+ OUT_CS(rs->cull_mode);
+ OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config);
+ OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value);
+ OUT_CS_REG(R300_GA_COLOR_CONTROL, rs->color_control);
+ END_CS;
+}
+
+void r300_emit_rs_block_state(struct r300_context* r300,
+ struct r300_rs_block* rs)
+{
+ int i;
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ CS_LOCALS(r300);
+
+ BEGIN_CS(21);
+ if (r300screen->caps->is_r500) {
+ OUT_CS_REG_SEQ(R500_RS_IP_0, 8);
+ } else {
+ OUT_CS_REG_SEQ(R300_RS_IP_0, 8);
+ }
+ for (i = 0; i < 8; i++) {
+ OUT_CS(rs->ip[i]);
+ /* debug_printf("ip %d: 0x%08x\n", i, rs->ip[i]); */
+ }
+
+ OUT_CS_REG_SEQ(R300_RS_COUNT, 2);
+ OUT_CS(rs->count);
+ OUT_CS(rs->inst_count);
+
+ if (r300screen->caps->is_r500) {
+ OUT_CS_REG_SEQ(R500_RS_INST_0, 8);
+ } else {
+ OUT_CS_REG_SEQ(R300_RS_INST_0, 8);
+ }
+ for (i = 0; i < 8; i++) {
+ OUT_CS(rs->inst[i]);
+ /* debug_printf("inst %d: 0x%08x\n", i, rs->inst[i]); */
+ }
+
+ /* debug_printf("count: 0x%08x inst_count: 0x%08x\n", rs->count,
+ * rs->inst_count); */
+
+ END_CS;
+}
+
+void r300_emit_scissor_state(struct r300_context* r300,
+ struct r300_scissor_state* scissor)
+{
+ CS_LOCALS(r300);
+
+ BEGIN_CS(3);
+ OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
+ OUT_CS(scissor->scissor_top_left);
+ OUT_CS(scissor->scissor_bottom_right);
+ END_CS;
+}
+
+void r300_emit_texture(struct r300_context* r300,
+ struct r300_sampler_state* sampler,
+ struct r300_texture* tex,
+ unsigned offset)
+{
+ CS_LOCALS(r300);
+
+ BEGIN_CS(16);
+ OUT_CS_REG(R300_TX_FILTER0_0 + (offset * 4), sampler->filter0);
+ OUT_CS_REG(R300_TX_FILTER1_0 + (offset * 4), sampler->filter1);
+ OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (offset * 4), sampler->border_color);
+
+ OUT_CS_REG(R300_TX_FORMAT0_0 + (offset * 4), tex->state.format0);
+ OUT_CS_REG(R300_TX_FORMAT1_0 + (offset * 4), tex->state.format1);
+ OUT_CS_REG(R300_TX_FORMAT2_0 + (offset * 4), tex->state.format2);
+ OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (offset * 4), 1);
+ OUT_CS_RELOC(tex->buffer, 0,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ END_CS;
+}
+
+void r300_emit_vertex_buffer(struct r300_context* r300)
+{
+ CS_LOCALS(r300);
+
+ DBG(r300, DBG_DRAW, "r300: Preparing vertex buffer %p for render, "
+ "vertex size %d\n", r300->vbo,
+ r300->vertex_info.vinfo.size);
+ /* Set the pointer to our vertex buffer. The emitted values are this:
+ * PACKET3 [3D_LOAD_VBPNTR]
+ * COUNT [1]
+ * FORMAT [size | stride << 8]
+ * OFFSET [offset into BO]
+ * VBPNTR [relocated BO]
+ */
+ BEGIN_CS(7);
+ OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3);
+ OUT_CS(1);
+ OUT_CS(r300->vertex_info.vinfo.size |
+ (r300->vertex_info.vinfo.size << 8));
+ OUT_CS(r300->vbo_offset);
+ OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ END_CS;
+}
+
+void r300_emit_vertex_format_state(struct r300_context* r300)
+{
+ int i;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(26);
+ OUT_CS_REG(R300_VAP_VTX_SIZE, r300->vertex_info.vinfo.size);
+
+ OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2);
+ OUT_CS(r300->vertex_info.vinfo.hwfmt[0]);
+ OUT_CS(r300->vertex_info.vinfo.hwfmt[1]);
+ OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+ OUT_CS(r300->vertex_info.vinfo.hwfmt[2]);
+ OUT_CS(r300->vertex_info.vinfo.hwfmt[3]);
+ /* for (i = 0; i < 4; i++) {
+ * debug_printf("hwfmt%d: 0x%08x\n", i,
+ * r300->vertex_info.vinfo.hwfmt[i]);
+ * } */
+
+ OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, 8);
+ for (i = 0; i < 8; i++) {
+ OUT_CS(r300->vertex_info.vap_prog_stream_cntl[i]);
+ /* debug_printf("prog_stream_cntl%d: 0x%08x\n", i,
+ * r300->vertex_info.vap_prog_stream_cntl[i]); */
+ }
+ OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, 8);
+ for (i = 0; i < 8; i++) {
+ OUT_CS(r300->vertex_info.vap_prog_stream_cntl_ext[i]);
+ /* debug_printf("prog_stream_cntl_ext%d: 0x%08x\n", i,
+ * r300->vertex_info.vap_prog_stream_cntl_ext[i]); */
+ }
+ END_CS;
+}
+
+void r300_emit_vertex_program_code(struct r300_context* r300,
+ struct r300_vertex_program_code* code,
+ struct r300_constant_buffer* constants)
+{
+ int i;
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ unsigned instruction_count = code->length / 4;
+ CS_LOCALS(r300);
+
+ if (!r300screen->caps->has_tcl) {
+ debug_printf("r300: Implementation error: emit_vertex_shader called,"
+ " but has_tcl is FALSE!\n");
+ return;
+ }
+
+ if (code->constants.Count) {
+ BEGIN_CS(14 + code->length + (code->constants.Count * 4));
+ } else {
+ BEGIN_CS(11 + code->length);
+ }
+
+ /* R300_VAP_PVS_CODE_CNTL_0
+ * R300_VAP_PVS_CONST_CNTL
+ * R300_VAP_PVS_CODE_CNTL_1
+ * See the r5xx docs for instructions on how to use these.
+ * XXX these could be optimized to select better values... */
+ OUT_CS_REG_SEQ(R300_VAP_PVS_CODE_CNTL_0, 3);
+ OUT_CS(R300_PVS_FIRST_INST(0) |
+ R300_PVS_XYZW_VALID_INST(instruction_count - 1) |
+ R300_PVS_LAST_INST(instruction_count - 1));
+ OUT_CS(R300_PVS_MAX_CONST_ADDR(code->constants.Count - 1));
+ OUT_CS(instruction_count - 1);
+
+ OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0);
+ OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->length);
+ for (i = 0; i < code->length; i++)
+ OUT_CS(code->body.d[i]);
+
+ if (code->constants.Count) {
+ OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG,
+ (r300screen->caps->is_r500 ?
+ R500_PVS_CONST_START : R300_PVS_CONST_START));
+ OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->constants.Count * 4);
+ for (i = 0; i < code->constants.Count; i++) {
+ const float * data = get_shader_constant(r300, &code->constants.Constants[i], constants);
+ OUT_CS_32F(data[0]);
+ OUT_CS_32F(data[1]);
+ OUT_CS_32F(data[2]);
+ OUT_CS_32F(data[3]);
+ }
+ }
+
+ OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(10) |
+ R300_PVS_NUM_CNTLRS(5) |
+ R300_PVS_NUM_FPUS(r300screen->caps->num_vert_fpus) |
+ R300_PVS_VF_MAX_VTX_NUM(12));
+ OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0);
+ END_CS;
+}
+
+void r300_emit_vertex_shader(struct r300_context* r300,
+ struct r300_vertex_shader* vs)
+{
+ r300_emit_vertex_program_code(r300, &vs->code, &r300->shader_constants[PIPE_SHADER_VERTEX]);
+}
+
+void r300_emit_viewport_state(struct r300_context* r300,
+ struct r300_viewport_state* viewport)
+{
+ CS_LOCALS(r300);
+
+ BEGIN_CS(9);
+ OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
+ OUT_CS_32F(viewport->xscale);
+ OUT_CS_32F(viewport->xoffset);
+ OUT_CS_32F(viewport->yscale);
+ OUT_CS_32F(viewport->yoffset);
+ OUT_CS_32F(viewport->zscale);
+ OUT_CS_32F(viewport->zoffset);
+
+ if (r300->rs_state->enable_vte) {
+ OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control);
+ } else {
+ OUT_CS_REG(R300_VAP_VTE_CNTL, 0);
+ }
+ END_CS;
+}
+
+void r300_flush_textures(struct r300_context* r300)
+{
+ CS_LOCALS(r300);
+
+ BEGIN_CS(4);
+ OUT_CS_REG(R300_TX_INVALTAGS, 0);
+ OUT_CS_REG(R300_TX_ENABLE, (1 << r300->texture_count) - 1);
+ END_CS;
+}
+
+/* Emit all dirty state. */
+void r300_emit_dirty_state(struct r300_context* r300)
+{
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct r300_texture* tex;
+ int i, dirty_tex = 0;
+ boolean invalid = FALSE;
+
+ if (!(r300->dirty_state)) {
+ return;
+ }
+
+ r300_update_derived_state(r300);
+
+ /* XXX check size */
+validate:
+ /* Color buffers... */
+ for (i = 0; i < r300->framebuffer_state.nr_cbufs; i++) {
+ tex = (struct r300_texture*)r300->framebuffer_state.cbufs[i]->texture;
+ assert(tex && tex->buffer && "cbuf is marked, but NULL!");
+ if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
+ 0, RADEON_GEM_DOMAIN_VRAM)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
+ }
+ /* ...depth buffer... */
+ if (r300->framebuffer_state.zsbuf) {
+ tex = (struct r300_texture*)r300->framebuffer_state.zsbuf->texture;
+ assert(tex && tex->buffer && "zsbuf is marked, but NULL!");
+ if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
+ 0, RADEON_GEM_DOMAIN_VRAM)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
+ }
+ /* ...textures... */
+ for (i = 0; i < r300->texture_count; i++) {
+ tex = r300->textures[i];
+ assert(tex && tex->buffer && "texture is marked, but NULL!");
+ if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
+ }
+ /* ...occlusion query buffer... */
+ if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo,
+ 0, RADEON_GEM_DOMAIN_GTT)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
+ /* ...and vertex buffer. */
+ if (r300->vbo) {
+ if (!r300->winsys->add_buffer(r300->winsys, r300->vbo,
+ RADEON_GEM_DOMAIN_GTT, 0)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
+ } else {
+ debug_printf("No VBO while emitting dirty state!\n");
+ }
+ if (!r300->winsys->validate(r300->winsys)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ if (invalid) {
+ /* Well, hell. */
+ debug_printf("r300: Stuck in validation loop, gonna quit now.");
+ exit(1);
+ }
+ invalid = TRUE;
+ goto validate;
+ }
+
+ if (r300->dirty_state & R300_NEW_BLEND) {
+ r300_emit_blend_state(r300, r300->blend_state);
+ r300->dirty_state &= ~R300_NEW_BLEND;
+ }
+
+ if (r300->dirty_state & R300_NEW_BLEND_COLOR) {
+ r300_emit_blend_color_state(r300, r300->blend_color_state);
+ r300->dirty_state &= ~R300_NEW_BLEND_COLOR;
+ }
+
+ if (r300->dirty_state & R300_NEW_CLIP) {
+ r300_emit_clip_state(r300, &r300->clip_state);
+ r300->dirty_state &= ~R300_NEW_CLIP;
+ }
+
+ if (r300->dirty_state & R300_NEW_DSA) {
+ r300_emit_dsa_state(r300, r300->dsa_state);
+ r300->dirty_state &= ~R300_NEW_DSA;
+ }
+
+ if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) {
+ if (r300screen->caps->is_r500) {
+ r500_emit_fragment_program_code(r300, &r300->fs->code, &r300->shader_constants[PIPE_SHADER_FRAGMENT]);
+ } else {
+ r300_emit_fragment_program_code(r300, &r300->fs->code, &r300->shader_constants[PIPE_SHADER_FRAGMENT]);
+ }
+ r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER;
+ }
+
+ if (r300->dirty_state & R300_NEW_FRAMEBUFFERS) {
+ r300_emit_fb_state(r300, &r300->framebuffer_state);
+ r300->dirty_state &= ~R300_NEW_FRAMEBUFFERS;
+ }
+
+ if (r300->dirty_state & R300_NEW_RASTERIZER) {
+ r300_emit_rs_state(r300, r300->rs_state);
+ r300->dirty_state &= ~R300_NEW_RASTERIZER;
+ }
+
+ if (r300->dirty_state & R300_NEW_RS_BLOCK) {
+ r300_emit_rs_block_state(r300, r300->rs_block);
+ r300->dirty_state &= ~R300_NEW_RS_BLOCK;
+ }
+
+ if (r300->dirty_state & R300_NEW_SCISSOR) {
+ r300_emit_scissor_state(r300, r300->scissor_state);
+ r300->dirty_state &= ~R300_NEW_SCISSOR;
+ }
+
+ /* Samplers and textures are tracked separately but emitted together. */
+ if (r300->dirty_state &
+ (R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES)) {
+ for (i = 0; i < MIN2(r300->sampler_count, r300->texture_count); i++) {
+ if (r300->dirty_state &
+ ((R300_NEW_SAMPLER << i) | (R300_NEW_TEXTURE << i))) {
+ r300_emit_texture(r300,
+ r300->sampler_states[i],
+ r300->textures[i],
+ i);
+ r300->dirty_state &=
+ ~((R300_NEW_SAMPLER << i) | (R300_NEW_TEXTURE << i));
+ dirty_tex++;
+ }
+ }
+ r300->dirty_state &= ~(R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES);
+ }
+
+ if (r300->dirty_state & R300_NEW_VIEWPORT) {
+ r300_emit_viewport_state(r300, r300->viewport_state);
+ r300->dirty_state &= ~R300_NEW_VIEWPORT;
+ }
+
+ if (dirty_tex) {
+ r300_flush_textures(r300);
+ }
+
+ if (r300->dirty_state & R300_NEW_VERTEX_FORMAT) {
+ r300_emit_vertex_format_state(r300);
+ r300->dirty_state &= ~R300_NEW_VERTEX_FORMAT;
+ }
+
+ if (r300->dirty_state & R300_NEW_VERTEX_SHADER) {
+ r300_emit_vertex_shader(r300, r300->vs);
+ r300->dirty_state &= ~R300_NEW_VERTEX_SHADER;
+ }
+
+ /* XXX
+ assert(r300->dirty_state == 0);
+ */
+
+ /* Finally, emit the VBO. */
+ r300_emit_vertex_buffer(r300);
+
+ r300->dirty_hw++;
+}
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
new file mode 100644
index 0000000000..c4002b8e5d
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_EMIT_H
+#define R300_EMIT_H
+
+#include "util/u_math.h"
+
+#include "r300_context.h"
+#include "r300_cs.h"
+#include "r300_screen.h"
+#include "r300_state_inlines.h"
+
+struct rX00_fragment_program_code;
+struct r300_vertex_program_code;
+
+void r300_emit_blend_state(struct r300_context* r300,
+ struct r300_blend_state* blend);
+
+void r300_emit_blend_color_state(struct r300_context* r300,
+ struct r300_blend_color_state* bc);
+
+void r300_emit_clip_state(struct r300_context* r300,
+ struct pipe_clip_state* clip);
+
+void r300_emit_dsa_state(struct r300_context* r300,
+ struct r300_dsa_state* dsa);
+
+void r300_emit_fragment_program_code(struct r300_context* r300,
+ struct rX00_fragment_program_code* generic_code,
+ struct r300_constant_buffer* externals);
+
+void r500_emit_fragment_program_code(struct r300_context* r300,
+ struct rX00_fragment_program_code* generic_code,
+ struct r300_constant_buffer* externals);
+
+void r300_emit_fb_state(struct r300_context* r300,
+ struct pipe_framebuffer_state* fb);
+
+void r300_emit_query_begin(struct r300_context* r300,
+ struct r300_query* query);
+void r300_emit_query_end(struct r300_context* r300,
+ struct r300_query* query);
+
+void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs);
+
+void r300_emit_rs_block_state(struct r300_context* r300,
+ struct r300_rs_block* rs);
+
+void r300_emit_scissor_state(struct r300_context* r300,
+ struct r300_scissor_state* scissor);
+
+void r300_emit_texture(struct r300_context* r300,
+ struct r300_sampler_state* sampler,
+ struct r300_texture* tex,
+ unsigned offset);
+
+void r300_emit_vertex_buffer(struct r300_context* r300);
+
+void r300_emit_vertex_format_state(struct r300_context* r300);
+
+void r300_emit_vertex_program_code(struct r300_context* r300,
+ struct r300_vertex_program_code* code,
+ struct r300_constant_buffer* constants);
+
+void r300_emit_vertex_shader(struct r300_context* r300,
+ struct r300_vertex_shader* vs);
+
+void r300_emit_viewport_state(struct r300_context* r300,
+ struct r300_viewport_state* viewport);
+
+void r300_flush_textures(struct r300_context* r300);
+
+/* Emit all dirty state. */
+void r300_emit_dirty_state(struct r300_context* r300);
+
+#endif /* R300_EMIT_H */
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
new file mode 100644
index 0000000000..0dff1c6f4f
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_flush.h"
+
+static void r300_flush(struct pipe_context* pipe,
+ unsigned flags,
+ struct pipe_fence_handle** fence)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ CS_LOCALS(r300);
+
+ /* We probably need to flush Draw, but we may have been called from
+ * within Draw. This feels kludgy, but it might be the best thing. */
+ if (!r300->draw->flushing) {
+ draw_flush(r300->draw);
+ }
+
+ if (r300->dirty_hw) {
+ FLUSH_CS;
+ r300_emit_invariant_state(r300);
+ r300->dirty_state = R300_NEW_KITCHEN_SINK;
+ r300->dirty_hw = 0;
+ }
+}
+
+void r300_init_flush_functions(struct r300_context* r300)
+{
+ r300->context.flush = r300_flush;
+}
diff --git a/src/gallium/drivers/r300/r300_flush.h b/src/gallium/drivers/r300/r300_flush.h
new file mode 100644
index 0000000000..9a83d89daa
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_flush.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_FLUSH_H
+#define R300_FLUSH_H
+
+#include "draw/draw_private.h"
+
+#include "pipe/p_context.h"
+
+#include "r300_context.h"
+#include "r300_cs.h"
+
+void r300_init_flush_functions(struct r300_context* r300);
+
+#endif /* R300_FLUSH_H */
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
new file mode 100644
index 0000000000..a0e848a59a
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_fs.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_fs.h"
+
+#include "r300_tgsi_to_rc.h"
+
+#include "radeon_compiler.h"
+
+static void find_output_registers(struct r300_fragment_program_compiler * compiler,
+ struct r300_fragment_shader * fs)
+{
+ unsigned i;
+
+ /* Mark the outputs as not present initially */
+ compiler->OutputColor = fs->info.num_outputs;
+ compiler->OutputDepth = fs->info.num_outputs;
+
+ /* Now see where they really are. */
+ for(i = 0; i < fs->info.num_outputs; ++i) {
+ switch(fs->info.output_semantic_name[i]) {
+ case TGSI_SEMANTIC_COLOR:
+ compiler->OutputColor = i;
+ break;
+ case TGSI_SEMANTIC_POSITION:
+ compiler->OutputDepth = i;
+ break;
+ }
+ }
+}
+
+static void allocate_hardware_inputs(
+ struct r300_fragment_program_compiler * c,
+ void (*allocate)(void * data, unsigned input, unsigned hwreg),
+ void * mydata)
+{
+ struct tgsi_shader_info* info = &((struct r300_fragment_shader*)c->UserData)->info;
+ int total_colors = 0;
+ int colors = 0;
+ int total_generic = 0;
+ int generic = 0;
+ int i;
+
+ for (i = 0; i < info->num_inputs; i++) {
+ switch (info->input_semantic_name[i]) {
+ case TGSI_SEMANTIC_COLOR:
+ total_colors++;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ case TGSI_SEMANTIC_GENERIC:
+ total_generic++;
+ break;
+ }
+ }
+
+ for(i = 0; i < info->num_inputs; i++) {
+ switch (info->input_semantic_name[i]) {
+ case TGSI_SEMANTIC_COLOR:
+ allocate(mydata, i, colors);
+ colors++;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ case TGSI_SEMANTIC_GENERIC:
+ allocate(mydata, i, total_colors + generic);
+ generic++;
+ break;
+ }
+ }
+}
+
+void r300_translate_fragment_shader(struct r300_context* r300,
+ struct r300_fragment_shader* fs)
+{
+ struct r300_fragment_program_compiler compiler;
+ struct tgsi_to_rc ttr;
+
+ memset(&compiler, 0, sizeof(compiler));
+ rc_init(&compiler.Base);
+ compiler.Base.Debug = DBG_ON(r300, DBG_FP);
+
+ compiler.code = &fs->code;
+ compiler.is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
+ compiler.AllocateHwInputs = &allocate_hardware_inputs;
+ compiler.UserData = fs;
+
+ /* TODO: Program compilation depends on texture compare modes,
+ * which are sampler state. Therefore, programs need to be recompiled
+ * depending on this state as in the classic Mesa driver.
+ *
+ * This is not yet handled correctly.
+ */
+
+ find_output_registers(&compiler, fs);
+
+ if (compiler.Base.Debug) {
+ debug_printf("r300: Initial fragment program\n");
+ tgsi_dump(fs->state.tokens, 0);
+ }
+
+ /* Translate TGSI to our internal representation */
+ ttr.compiler = &compiler.Base;
+ ttr.info = &fs->info;
+
+ r300_tgsi_to_rc(&ttr, fs->state.tokens);
+
+ /* Invoke the compiler */
+ r3xx_compile_fragment_program(&compiler);
+ if (compiler.Base.Error) {
+ /* Todo: Fail gracefully */
+ fprintf(stderr, "r300 FP: Compiler error\n");
+ abort();
+ }
+
+ /* And, finally... */
+ rc_destroy(&compiler.Base);
+ fs->translated = TRUE;
+}
diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h
new file mode 100644
index 0000000000..9fab789402
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_fs.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_FS_H
+#define R300_FS_H
+
+#include "tgsi/tgsi_dump.h"
+
+#include "r300_context.h"
+#include "r3xx_fs.h"
+#include "r5xx_fs.h"
+
+#include "radeon_code.h"
+
+struct r300_fragment_shader {
+ /* Parent class */
+ struct pipe_shader_state state;
+ struct tgsi_shader_info info;
+
+ /* Has this shader been translated yet? */
+ boolean translated;
+
+ /* Compiled code */
+ struct rX00_fragment_program_code code;
+};
+
+
+void r300_translate_fragment_shader(struct r300_context* r300,
+ struct r300_fragment_shader* fs);
+
+ #endif /* R300_FS_H */
diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c
new file mode 100644
index 0000000000..2880d34877
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_query.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_query.h"
+
+#include "r300_emit.h"
+
+static struct pipe_query* r300_create_query(struct pipe_context* pipe,
+ unsigned query_type)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ unsigned query_size = r300screen->caps->num_frag_pipes * 4;
+ struct r300_query* q, * qptr;
+
+ q = CALLOC_STRUCT(r300_query);
+
+ q->type = query_type;
+ assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+
+ q->active = FALSE;
+
+ if (!r300->query_list) {
+ r300->query_list = q;
+ } else if (!is_empty_list(r300->query_list)) {
+ qptr = last_elem(r300->query_list);
+ q->offset = qptr->offset + query_size;
+ insert_at_tail(r300->query_list, q);
+ }
+
+ /* XXX */
+ if (q->offset >= 4096) {
+ q->offset = 0;
+ }
+
+ return (struct pipe_query*)q;
+}
+
+static void r300_destroy_query(struct pipe_context* pipe,
+ struct pipe_query* query)
+{
+ struct r300_query* q = (struct r300_query*)query;
+
+ remove_from_list(q);
+ FREE(query);
+}
+
+static void r300_begin_query(struct pipe_context* pipe,
+ struct pipe_query* query)
+{
+ uint32_t* map;
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_query* q = (struct r300_query*)query;
+
+ map = pipe->screen->buffer_map(pipe->screen, r300->oqbo,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ map += q->offset / 4;
+ *map = ~0;
+ pipe->screen->buffer_unmap(pipe->screen, r300->oqbo);
+
+ r300_emit_dirty_state(r300);
+ r300_emit_query_begin(r300, q);
+}
+
+static void r300_end_query(struct pipe_context* pipe,
+ struct pipe_query* query)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_query* q = (struct r300_query*)query;
+
+ r300_emit_dirty_state(r300);
+ r300_emit_query_end(r300, q);
+}
+
+static boolean r300_get_query_result(struct pipe_context* pipe,
+ struct pipe_query* query,
+ boolean wait,
+ uint64_t* result)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct r300_query* q = (struct r300_query*)query;
+ unsigned flags = PIPE_BUFFER_USAGE_CPU_READ;
+ uint32_t* map;
+ uint32_t temp;
+ unsigned i;
+
+ if (wait) {
+ pipe->flush(pipe, 0, NULL);
+ } else {
+ flags |= PIPE_BUFFER_USAGE_DONTBLOCK;
+ }
+
+ map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, flags);
+ map += q->offset / 4;
+ for (i = 0; i < r300screen->caps->num_frag_pipes; i++) {
+ if (*map == ~0) {
+ /* Looks like our results aren't ready yet. */
+ if (wait) {
+ debug_printf("r300: Despite waiting, OQ results haven't"
+ " come in yet.\n");
+ }
+ temp = ~0;
+ break;
+ }
+ temp += *map;
+ map++;
+ }
+ pipe->screen->buffer_unmap(pipe->screen, r300->oqbo);
+
+ if (temp == ~0) {
+ /* Our results haven't been written yet... */
+ return FALSE;
+ }
+
+ *result = temp;
+ return TRUE;
+}
+
+void r300_init_query_functions(struct r300_context* r300) {
+ r300->context.create_query = r300_create_query;
+ r300->context.destroy_query = r300_destroy_query;
+ r300->context.begin_query = r300_begin_query;
+ r300->context.end_query = r300_end_query;
+ r300->context.get_query_result = r300_get_query_result;
+}
diff --git a/src/gallium/drivers/r300/r300_query.h b/src/gallium/drivers/r300/r300_query.h
new file mode 100644
index 0000000000..4f50e8f844
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_query.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_QUERY_H
+#define R300_QUERY_H
+
+#include "r300_context.h"
+#include "r300_cs.h"
+#include "r300_reg.h"
+
+struct r300_context;
+
+static INLINE struct r300_query* r300_query(struct pipe_query* q)
+{
+ return (struct r300_query*)q;
+}
+
+void r300_init_query_functions(struct r300_context* r300);
+
+#endif /* R300_QUERY_H */
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
new file mode 100644
index 0000000000..03cd219cde
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -0,0 +1,3323 @@
+/**************************************************************************
+
+Copyright (C) 2004-2005 Nicolai Haehnle et al.
+
+Permission is hereby granted, free of charge, to 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.
+
+**************************************************************************/
+
+/* *INDENT-OFF* */
+
+#ifndef _R300_REG_H
+#define _R300_REG_H
+
+#define R300_MC_INIT_MISC_LAT_TIMER 0x180
+# define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0
+# define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT 4
+# define R300_MC_MISC__MC_DISP0R_INIT_LAT_SHIFT 8
+# define R300_MC_MISC__MC_DISP1R_INIT_LAT_SHIFT 12
+# define R300_MC_MISC__MC_FIXED_INIT_LAT_SHIFT 16
+# define R300_MC_MISC__MC_E2R_INIT_LAT_SHIFT 20
+# define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT 24
+# define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT 28
+
+
+#define R300_MC_INIT_GFX_LAT_TIMER 0x154
+# define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT 0
+# define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT 4
+# define R300_MC_MISC__MC_G3D2R_INIT_LAT_SHIFT 8
+# define R300_MC_MISC__MC_G3D3R_INIT_LAT_SHIFT 12
+# define R300_MC_MISC__MC_TX0R_INIT_LAT_SHIFT 16
+# define R300_MC_MISC__MC_TX1R_INIT_LAT_SHIFT 20
+# define R300_MC_MISC__MC_GLOBR_INIT_LAT_SHIFT 24
+# define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT 28
+
+/*
+ * This file contains registers and constants for the R300. They have been
+ * found mostly by examining command buffers captured using glxtest, as well
+ * as by extrapolating some known registers and constants from the R200.
+ * I am fairly certain that they are correct unless stated otherwise
+ * in comments.
+ */
+
+#define R300_SE_VPORT_XSCALE 0x1D98
+#define R300_SE_VPORT_XOFFSET 0x1D9C
+#define R300_SE_VPORT_YSCALE 0x1DA0
+#define R300_SE_VPORT_YOFFSET 0x1DA4
+#define R300_SE_VPORT_ZSCALE 0x1DA8
+#define R300_SE_VPORT_ZOFFSET 0x1DAC
+
+#define R300_VAP_PORT_IDX0 0x2040
+/*
+ * Vertex Array Processing (VAP) Control
+ */
+#define R300_VAP_CNTL 0x2080
+# define R300_PVS_NUM_SLOTS_SHIFT 0
+# define R300_PVS_NUM_CNTLRS_SHIFT 4
+# define R300_PVS_NUM_FPUS_SHIFT 8
+# define R300_VF_MAX_VTX_NUM_SHIFT 18
+# define R300_PVS_NUM_SLOTS(x) ((x) << 0)
+# define R300_PVS_NUM_CNTLRS(x) ((x) << 4)
+# define R300_PVS_NUM_FPUS(x) ((x) << 8)
+# define R300_PVS_VF_MAX_VTX_NUM(x) ((x) << 18)
+# define R300_GL_CLIP_SPACE_DEF (0 << 22)
+# define R300_DX_CLIP_SPACE_DEF (1 << 22)
+# define R500_TCL_STATE_OPTIMIZATION (1 << 23)
+
+/* This register is written directly and also starts data section
+ * in many 3d CP_PACKET3's
+ */
+#define R300_VAP_VF_CNTL 0x2084
+# define R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT 0
+# define R300_VAP_VF_CNTL__PRIM_NONE (0<<0)
+# define R300_VAP_VF_CNTL__PRIM_POINTS (1<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINES (2<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINE_STRIP (3<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLES (4<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN (5<<0)
+# define R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP (6<<0)
+# define R300_VAP_VF_CNTL__PRIM_LINE_LOOP (12<<0)
+# define R300_VAP_VF_CNTL__PRIM_QUADS (13<<0)
+# define R300_VAP_VF_CNTL__PRIM_QUAD_STRIP (14<<0)
+# define R300_VAP_VF_CNTL__PRIM_POLYGON (15<<0)
+
+# define R300_VAP_VF_CNTL__PRIM_WALK__SHIFT 4
+ /* State based - direct writes to registers trigger vertex
+ generation */
+# define R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED (0<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_INDICES (1<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST (2<<4)
+# define R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED (3<<4)
+
+ /* I don't think I saw these three used.. */
+# define R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT 6
+# define R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT 9
+# define R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT 10
+
+ /* index size - when not set the indices are assumed to be 16 bit */
+# define R300_VAP_VF_CNTL__INDEX_SIZE_32bit (1<<11)
+ /* number of vertices */
+# define R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT 16
+
+#define R500_VAP_INDEX_OFFSET 0x208c
+
+#define R300_VAP_OUTPUT_VTX_FMT_0 0x2090
+# define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT (1<<0)
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT (1<<1)
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2)
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3)
+# define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4)
+# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16)
+
+#define R300_VAP_OUTPUT_VTX_FMT_1 0x2094
+ /* each of the following is 3 bits wide, specifies number
+ of components */
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
+# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
+# define R300_VAP_OUTPUT_VTX_FMT_1__NOT_PRESENT 0
+# define R300_VAP_OUTPUT_VTX_FMT_1__1_COMPONENT 1
+# define R300_VAP_OUTPUT_VTX_FMT_1__2_COMPONENTS 2
+# define R300_VAP_OUTPUT_VTX_FMT_1__3_COMPONENTS 3
+# define R300_VAP_OUTPUT_VTX_FMT_1__4_COMPONENTS 4
+
+#define R300_VAP_VPORT_XSCALE 0x2098
+#define R300_VAP_VPORT_XOFFSET 0x209c
+#define R300_VAP_VPORT_YSCALE 0x20a0
+#define R300_VAP_VPORT_YOFFSET 0x20a4
+#define R300_VAP_VPORT_ZSCALE 0x20a8
+#define R300_VAP_VPORT_ZOFFSET 0x20ac
+
+#define R300_VAP_VTE_CNTL 0x20b0
+#define R300_SE_VTE_CNTL R300_VAP_VTE_CNTL
+# define R300_VPORT_X_SCALE_ENA (1 << 0)
+# define R300_VPORT_X_OFFSET_ENA (1 << 1)
+# define R300_VPORT_Y_SCALE_ENA (1 << 2)
+# define R300_VPORT_Y_OFFSET_ENA (1 << 3)
+# define R300_VPORT_Z_SCALE_ENA (1 << 4)
+# define R300_VPORT_Z_OFFSET_ENA (1 << 5)
+# define R300_VTX_XY_FMT (1 << 8)
+# define R300_VTX_Z_FMT (1 << 9)
+# define R300_VTX_W0_FMT (1 << 10)
+# define R300_SERIAL_PROC_ENA (1 << 11)
+
+#define R300_VAP_VTX_SIZE 0x20b4
+
+/* BEGIN: Vertex data assembly - lots of uncertainties */
+
+/* gap */
+
+/* Maximum Vertex Indx Clamp */
+#define R300_VAP_VF_MAX_VTX_INDX 0x2134
+/* Minimum Vertex Indx Clamp */
+#define R300_VAP_VF_MIN_VTX_INDX 0x2138
+
+/** Vertex assembler/processor control status */
+#define R300_VAP_CNTL_STATUS 0x2140
+/* No swap at all (default) */
+# define R300_VC_NO_SWAP (0 << 0)
+/* 16-bit swap: 0xAABBCCDD becomes 0xBBAADDCC */
+# define R300_VC_16BIT_SWAP (1 << 0)
+/* 32-bit swap: 0xAABBCCDD becomes 0xDDCCBBAA */
+# define R300_VC_32BIT_SWAP (2 << 0)
+/* Half-dword swap: 0xAABBCCDD becomes 0xCCDDAABB */
+# define R300_VC_HALF_DWORD_SWAP (3 << 0)
+/* The TCL engine will not be used (as it is logically or even physically removed) */
+# define R300_VAP_TCL_BYPASS (1 << 8)
+/* Read only flag if TCL engine is busy. */
+# define R300_VAP_PVS_BUSY (1 << 11)
+/* TODO: gap for MAX_MPS */
+/* Read only flag if the vertex store is busy. */
+# define R300_VAP_VS_BUSY (1 << 24)
+/* Read only flag if the reciprocal engine is busy. */
+# define R300_VAP_RCP_BUSY (1 << 25)
+/* Read only flag if the viewport transform engine is busy. */
+# define R300_VAP_VTE_BUSY (1 << 26)
+/* Read only flag if the memory interface unit is busy. */
+# define R300_VAP_MUI_BUSY (1 << 27)
+/* Read only flag if the vertex cache is busy. */
+# define R300_VAP_VC_BUSY (1 << 28)
+/* Read only flag if the vertex fetcher is busy. */
+# define R300_VAP_VF_BUSY (1 << 29)
+/* Read only flag if the register pipeline is busy. */
+# define R300_VAP_REGPIPE_BUSY (1 << 30)
+/* Read only flag if the VAP engine is busy. */
+# define R300_VAP_VAP_BUSY (1 << 31)
+
+/* gap */
+
+/* Where do we get our vertex data?
+ *
+ * Vertex data either comes either from immediate mode registers or from
+ * vertex arrays.
+ * There appears to be no mixed mode (though we can force the pitch of
+ * vertex arrays to 0, effectively reusing the same element over and over
+ * again).
+ *
+ * Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
+ * if these registers influence vertex array processing.
+ *
+ * Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
+ *
+ * In both cases, vertex attributes are then passed through INPUT_ROUTE.
+ *
+ * Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
+ * into the vertex processor's input registers.
+ * The first word routes the first input, the second word the second, etc.
+ * The corresponding input is routed into the register with the given index.
+ * The list is ended by a word with INPUT_ROUTE_END set.
+ *
+ * Always set COMPONENTS_4 in immediate mode.
+ */
+
+#define R300_VAP_PROG_STREAM_CNTL_0 0x2150
+# define R300_DATA_TYPE_0_SHIFT 0
+# define R300_DATA_TYPE_FLOAT_1 0
+# define R300_DATA_TYPE_FLOAT_2 1
+# define R300_DATA_TYPE_FLOAT_3 2
+# define R300_DATA_TYPE_FLOAT_4 3
+# define R300_DATA_TYPE_BYTE 4
+# define R300_DATA_TYPE_D3DCOLOR 5
+# define R300_DATA_TYPE_SHORT_2 6
+# define R300_DATA_TYPE_SHORT_4 7
+# define R300_DATA_TYPE_VECTOR_3_TTT 8
+# define R300_DATA_TYPE_VECTOR_3_EET 9
+# define R300_SKIP_DWORDS_SHIFT 4
+# define R300_DST_VEC_LOC_SHIFT 8
+# define R300_LAST_VEC (1 << 13)
+# define R300_SIGNED (1 << 14)
+# define R300_NORMALIZE (1 << 15)
+# define R300_DATA_TYPE_1_SHIFT 16
+#define R300_VAP_PROG_STREAM_CNTL_1 0x2154
+#define R300_VAP_PROG_STREAM_CNTL_2 0x2158
+#define R300_VAP_PROG_STREAM_CNTL_3 0x215C
+#define R300_VAP_PROG_STREAM_CNTL_4 0x2160
+#define R300_VAP_PROG_STREAM_CNTL_5 0x2164
+#define R300_VAP_PROG_STREAM_CNTL_6 0x2168
+#define R300_VAP_PROG_STREAM_CNTL_7 0x216C
+/* gap */
+
+/* Notes:
+ * - always set up to produce at least two attributes:
+ * if vertex program uses only position, fglrx will set normal, too
+ * - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal.
+ */
+#define R300_VAP_VTX_STATE_CNTL 0x2180
+# define R300_COLOR_0_ASSEMBLY_SHIFT 0
+# define R300_SEL_COLOR 0
+# define R300_SEL_USER_COLOR_0 1
+# define R300_SEL_USER_COLOR_1 2
+# define R300_COLOR_1_ASSEMBLY_SHIFT 2
+# define R300_COLOR_2_ASSEMBLY_SHIFT 4
+# define R300_COLOR_3_ASSEMBLY_SHIFT 6
+# define R300_COLOR_4_ASSEMBLY_SHIFT 8
+# define R300_COLOR_5_ASSEMBLY_SHIFT 10
+# define R300_COLOR_6_ASSEMBLY_SHIFT 12
+# define R300_COLOR_7_ASSEMBLY_SHIFT 14
+# define R300_UPDATE_USER_COLOR_0_ENA (1 << 16)
+
+/*
+ * Each bit in this field applies to the corresponding vector in the VSM
+ * memory (i.e. Bit 0 applies to VECTOR_0 (POSITION), etc.). If the bit
+ * is set, then the corresponding 4-Dword Vector is output into the Vertex Stream.
+ */
+#define R300_VAP_VSM_VTX_ASSM 0x2184
+# define R300_INPUT_CNTL_POS 0x00000001
+# define R300_INPUT_CNTL_NORMAL 0x00000002
+# define R300_INPUT_CNTL_COLOR 0x00000004
+# define R300_INPUT_CNTL_TC0 0x00000400
+# define R300_INPUT_CNTL_TC1 0x00000800
+# define R300_INPUT_CNTL_TC2 0x00001000 /* GUESS */
+# define R300_INPUT_CNTL_TC3 0x00002000 /* GUESS */
+# define R300_INPUT_CNTL_TC4 0x00004000 /* GUESS */
+# define R300_INPUT_CNTL_TC5 0x00008000 /* GUESS */
+# define R300_INPUT_CNTL_TC6 0x00010000 /* GUESS */
+# define R300_INPUT_CNTL_TC7 0x00020000 /* GUESS */
+
+/* Programmable Stream Control Signed Normalize Control */
+#define R300_VAP_PSC_SGN_NORM_CNTL 0x21dc
+# define SGN_NORM_ZERO 0
+# define SGN_NORM_ZERO_CLAMP_MINUS_ONE 1
+# define SGN_NORM_NO_ZERO 2
+# define R300_SGN_NORM_NO_ZERO (SGN_NORM_NO_ZERO | \
+ (SGN_NORM_NO_ZERO << 2) | (SGN_NORM_NO_ZERO << 4) | \
+ (SGN_NORM_NO_ZERO << 6) | (SGN_NORM_NO_ZERO << 8) | \
+ (SGN_NORM_NO_ZERO << 10) | (SGN_NORM_NO_ZERO << 12) | \
+ (SGN_NORM_NO_ZERO << 14) | (SGN_NORM_NO_ZERO << 16) | \
+ (SGN_NORM_NO_ZERO << 18) | (SGN_NORM_NO_ZERO << 20) | \
+ (SGN_NORM_NO_ZERO << 22) | (SGN_NORM_NO_ZERO << 24) | \
+ (SGN_NORM_NO_ZERO << 26) | (SGN_NORM_NO_ZERO << 28) | \
+ (SGN_NORM_NO_ZERO << 30))
+
+/* gap */
+
+/* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0
+ * are set to a swizzling bit pattern, other words are 0.
+ *
+ * In immediate mode, the pattern is always set to xyzw. In vertex array
+ * mode, the swizzling pattern is e.g. used to set zw components in texture
+ * coordinates with only tweo components.
+ */
+#define R300_VAP_PROG_STREAM_CNTL_EXT_0 0x21e0
+# define R300_SWIZZLE0_SHIFT 0
+# define R300_SWIZZLE_SELECT_X_SHIFT 0
+# define R300_SWIZZLE_SELECT_Y_SHIFT 3
+# define R300_SWIZZLE_SELECT_Z_SHIFT 6
+# define R300_SWIZZLE_SELECT_W_SHIFT 9
+
+# define R300_SWIZZLE_SELECT_X 0
+# define R300_SWIZZLE_SELECT_Y 1
+# define R300_SWIZZLE_SELECT_Z 2
+# define R300_SWIZZLE_SELECT_W 3
+# define R300_SWIZZLE_SELECT_FP_ZERO 4
+# define R300_SWIZZLE_SELECT_FP_ONE 5
+/* alternate forms for r300_emit.c */
+# define R300_INPUT_ROUTE_SELECT_X 0
+# define R300_INPUT_ROUTE_SELECT_Y 1
+# define R300_INPUT_ROUTE_SELECT_Z 2
+# define R300_INPUT_ROUTE_SELECT_W 3
+# define R300_INPUT_ROUTE_SELECT_ZERO 4
+# define R300_INPUT_ROUTE_SELECT_ONE 5
+
+# define R300_WRITE_ENA_SHIFT 12
+# define R300_WRITE_ENA_X 1
+# define R300_WRITE_ENA_Y 2
+# define R300_WRITE_ENA_Z 4
+# define R300_WRITE_ENA_W 8
+# define R300_SWIZZLE1_SHIFT 16
+
+# define R300_VAP_SWIZZLE_XYZW \
+ ((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) | \
+ (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) | \
+ (R300_SWIZZLE_SELECT_Z << R300_SWIZZLE_SELECT_Z_SHIFT) | \
+ (R300_SWIZZLE_SELECT_W << R300_SWIZZLE_SELECT_W_SHIFT) | \
+ (0xf << R300_WRITE_ENA_SHIFT))
+
+#define R300_VAP_PROG_STREAM_CNTL_EXT_1 0x21e4
+#define R300_VAP_PROG_STREAM_CNTL_EXT_2 0x21e8
+#define R300_VAP_PROG_STREAM_CNTL_EXT_3 0x21ec
+#define R300_VAP_PROG_STREAM_CNTL_EXT_4 0x21f0
+#define R300_VAP_PROG_STREAM_CNTL_EXT_5 0x21f4
+#define R300_VAP_PROG_STREAM_CNTL_EXT_6 0x21f8
+#define R300_VAP_PROG_STREAM_CNTL_EXT_7 0x21fc
+
+/* END: Vertex data assembly */
+
+/* gap */
+
+/* BEGIN: Upload vertex program and data */
+
+/*
+ * The programmable vertex shader unit has a memory bank of unknown size
+ * that can be written to in 16 byte units by writing the address into
+ * UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
+ *
+ * Pointers into the memory bank are always in multiples of 16 bytes.
+ *
+ * The memory bank is divided into areas with fixed meaning.
+ *
+ * Starting at address UPLOAD_PROGRAM: Vertex program instructions.
+ * Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
+ * whereas the difference between known addresses suggests size 512.
+ *
+ * Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
+ * Native reported limits and the VPI layout suggest size 256, whereas
+ * difference between known addresses suggests size 512.
+ *
+ * At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
+ * floating point pointsize. The exact purpose of this state is uncertain,
+ * as there is also the R300_RE_POINTSIZE register.
+ *
+ * Multiple vertex programs and parameter sets can be loaded at once,
+ * which could explain the size discrepancy.
+ */
+#define R300_VAP_PVS_VECTOR_INDX_REG 0x2200
+# define R300_PVS_CODE_START 0
+# define R300_MAX_PVS_CODE_LINES 256
+# define R500_MAX_PVS_CODE_LINES 1024
+# define R300_PVS_CONST_START 512
+# define R500_PVS_CONST_START 1024
+# define R300_MAX_PVS_CONST_VECS 256
+# define R500_MAX_PVS_CONST_VECS 1024
+# define R300_PVS_UCP_START 1024
+# define R500_PVS_UCP_START 1536
+# define R300_POINT_VPORT_SCALE_OFFSET 1030
+# define R500_POINT_VPORT_SCALE_OFFSET 1542
+# define R300_POINT_GEN_TEX_OFFSET 1031
+# define R500_POINT_GEN_TEX_OFFSET 1543
+
+/*
+ * These are obsolete defines form r300_context.h, but they might give some
+ * clues when investigating the addresses further...
+ */
+#if 0
+#define VSF_DEST_PROGRAM 0x0
+#define VSF_DEST_MATRIX0 0x200
+#define VSF_DEST_MATRIX1 0x204
+#define VSF_DEST_MATRIX2 0x208
+#define VSF_DEST_VECTOR0 0x20c
+#define VSF_DEST_VECTOR1 0x20d
+#define VSF_DEST_UNKNOWN1 0x400
+#define VSF_DEST_UNKNOWN2 0x406
+#endif
+
+/* gap */
+
+#define R300_VAP_PVS_UPLOAD_DATA 0x2208
+
+/* END: Upload vertex program and data */
+
+/* gap */
+
+/* I do not know the purpose of this register. However, I do know that
+ * it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
+ * for normal rendering.
+ *
+ * 2007-11-05: This register is the user clip plane control register, but there
+ * also seems to be a rendering mode control; the NORMAL/CLEAR defines.
+ *
+ * See bug #9871. http://bugs.freedesktop.org/attachment.cgi?id=10672&action=view
+ */
+#define R300_VAP_CLIP_CNTL 0x221C
+# define R300_VAP_UCP_ENABLE_0 (1 << 0)
+# define R300_VAP_UCP_ENABLE_1 (1 << 1)
+# define R300_VAP_UCP_ENABLE_2 (1 << 2)
+# define R300_VAP_UCP_ENABLE_3 (1 << 3)
+# define R300_VAP_UCP_ENABLE_4 (1 << 4)
+# define R300_VAP_UCP_ENABLE_5 (1 << 5)
+# define R300_PS_UCP_MODE_DIST_COP (0 << 14)
+# define R300_PS_UCP_MODE_RADIUS_COP (1 << 14)
+# define R300_PS_UCP_MODE_RADIUS_COP_CLIP (2 << 14)
+# define R300_PS_UCP_MODE_CLIP_AS_TRIFAN (3 << 14)
+# define R300_CLIP_DISABLE (1 << 16)
+# define R300_UCP_CULL_ONLY_ENABLE (1 << 17)
+# define R300_BOUNDARY_EDGE_FLAG_ENABLE (1 << 18)
+# define R500_COLOR2_IS_TEXTURE (1 << 20)
+# define R500_COLOR3_IS_TEXTURE (1 << 21)
+
+/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first
+ * plane is per-pixel and the second plane is per-vertex.
+ *
+ * This was determined by experimentation alone but I believe it is correct.
+ *
+ * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest.
+ */
+#define R300_VAP_GB_VERT_CLIP_ADJ 0x2220
+#define R300_VAP_GB_VERT_DISC_ADJ 0x2224
+#define R300_VAP_GB_HORZ_CLIP_ADJ 0x2228
+#define R300_VAP_GB_HORZ_DISC_ADJ 0x222c
+
+/* gap */
+
+/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
+ * rendering commands and overwriting vertex program parameters.
+ * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
+ * avoids bugs caused by still running shaders reading bad data from memory.
+ */
+#define R300_VAP_PVS_STATE_FLUSH_REG 0x2284
+
+/* This register is used to define the number of core clocks to wait for a
+ * vertex to be received by the VAP input controller (while the primitive
+ * path is backed up) before forcing any accumulated vertices to be submitted
+ * to the vertex processing path.
+ */
+#define VAP_PVS_VTX_TIMEOUT_REG 0x2288
+# define R300_2288_R300 0x00750000 /* -- nh */
+# define R300_2288_RV350 0x0000FFFF /* -- Vladimir */
+
+/* gap */
+
+/* Addresses are relative to the vertex program instruction area of the
+ * memory bank. PROGRAM_END points to the last instruction of the active
+ * program
+ *
+ * The meaning of the two UNKNOWN fields is obviously not known. However,
+ * experiments so far have shown that both *must* point to an instruction
+ * inside the vertex program, otherwise the GPU locks up.
+ *
+ * fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
+ * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to
+ * position takes place.
+ *
+ * Most likely this is used to ignore rest of the program in cases
+ * where group of verts arent visible. For some reason this "section"
+ * is sometimes accepted other instruction that have no relationship with
+ * position calculations.
+ */
+#define R300_VAP_PVS_CODE_CNTL_0 0x22D0
+# define R300_PVS_FIRST_INST_SHIFT 0
+# define R300_PVS_XYZW_VALID_INST_SHIFT 10
+# define R300_PVS_LAST_INST_SHIFT 20
+# define R300_PVS_FIRST_INST(x) ((x) << 0)
+# define R300_PVS_XYZW_VALID_INST(x) ((x) << 10)
+# define R300_PVS_LAST_INST(x) ((x) << 20)
+/* Addresses are relative the the vertex program parameters area. */
+#define R300_VAP_PVS_CONST_CNTL 0x22D4
+# define R300_PVS_CONST_BASE_OFFSET_SHIFT 0
+# define R300_PVS_MAX_CONST_ADDR_SHIFT 16
+# define R300_PVS_MAX_CONST_ADDR(x) ((x) << 16)
+#define R300_VAP_PVS_CODE_CNTL_1 0x22D8
+# define R300_PVS_LAST_VTX_SRC_INST_SHIFT 0
+#define R300_VAP_PVS_FLOW_CNTL_OPC 0x22DC
+
+/* The entire range from 0x2300 to 0x2AC inclusive seems to be used for
+ * immediate vertices
+ */
+#define R300_VAP_VTX_COLOR_R 0x2464
+#define R300_VAP_VTX_COLOR_G 0x2468
+#define R300_VAP_VTX_COLOR_B 0x246C
+#define R300_VAP_VTX_POS_0_X_1 0x2490 /* used for glVertex2*() */
+#define R300_VAP_VTX_POS_0_Y_1 0x2494
+#define R300_VAP_VTX_COLOR_PKD 0x249C /* RGBA */
+#define R300_VAP_VTX_POS_0_X_2 0x24A0 /* used for glVertex3*() */
+#define R300_VAP_VTX_POS_0_Y_2 0x24A4
+#define R300_VAP_VTX_POS_0_Z_2 0x24A8
+/* write 0 to indicate end of packet? */
+#define R300_VAP_VTX_END_OF_PKT 0x24AC
+
+/* gap */
+
+/* These are values from r300_reg/r300_reg.h - they are known to be correct
+ * and are here so we can use one register file instead of several
+ * - Vladimir
+ */
+#define R300_GB_VAP_RASTER_VTX_FMT_0 0x4000
+# define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT (1<<0)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT (1<<1)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_1_PRESENT (1<<2)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_2_PRESENT (1<<3)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_3_PRESENT (1<<4)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_SPACE (0xf<<5)
+# define R300_GB_VAP_RASTER_VTX_FMT_0__PT_SIZE_PRESENT (0x1<<16)
+
+#define R300_GB_VAP_RASTER_VTX_FMT_1 0x4004
+ /* each of the following is 3 bits wide, specifies number
+ of components */
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
+# define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
+
+/* UNK30 seems to enables point to quad transformation on textures
+ * (or something closely related to that).
+ * This bit is rather fatal at the time being due to lackings at pixel
+ * shader side
+ * Specifies top of Raster pipe specific enable controls.
+ */
+#define R300_GB_ENABLE 0x4008
+# define R300_GB_POINT_STUFF_DISABLE (0 << 0)
+# define R300_GB_POINT_STUFF_ENABLE (1 << 0) /* Specifies if points will have stuffed texture coordinates. */
+# define R300_GB_LINE_STUFF_DISABLE (0 << 1)
+# define R300_GB_LINE_STUFF_ENABLE (1 << 1) /* Specifies if lines will have stuffed texture coordinates. */
+# define R300_GB_TRIANGLE_STUFF_DISABLE (0 << 2)
+# define R300_GB_TRIANGLE_STUFF_ENABLE (1 << 2) /* Specifies if triangles will have stuffed texture coordinates. */
+# define R300_GB_STENCIL_AUTO_DISABLE (0 << 4)
+# define R300_GB_STENCIL_AUTO_ENABLE (1 << 4) /* Enable stencil auto inc/dec based on triangle cw/ccw, force into dzy low bit. */
+# define R300_GB_STENCIL_AUTO_FORCE (2 << 4) /* Force 0 into dzy low bit. */
+
+ /* each of the following is 2 bits wide */
+#define R300_GB_TEX_REPLICATE 0 /* Replicate VAP source texture coordinates (S,T,[R,Q]). */
+#define R300_GB_TEX_ST 1 /* Stuff with source texture coordinates (S,T). */
+#define R300_GB_TEX_STR 2 /* Stuff with source texture coordinates (S,T,R). */
+# define R300_GB_TEX0_SOURCE_SHIFT 16
+# define R300_GB_TEX1_SOURCE_SHIFT 18
+# define R300_GB_TEX2_SOURCE_SHIFT 20
+# define R300_GB_TEX3_SOURCE_SHIFT 22
+# define R300_GB_TEX4_SOURCE_SHIFT 24
+# define R300_GB_TEX5_SOURCE_SHIFT 26
+# define R300_GB_TEX6_SOURCE_SHIFT 28
+# define R300_GB_TEX7_SOURCE_SHIFT 30
+
+/* MSPOS - positions for multisample antialiasing (?) */
+#define R300_GB_MSPOS0 0x4010
+ /* shifts - each of the fields is 4 bits */
+# define R300_GB_MSPOS0__MS_X0_SHIFT 0
+# define R300_GB_MSPOS0__MS_Y0_SHIFT 4
+# define R300_GB_MSPOS0__MS_X1_SHIFT 8
+# define R300_GB_MSPOS0__MS_Y1_SHIFT 12
+# define R300_GB_MSPOS0__MS_X2_SHIFT 16
+# define R300_GB_MSPOS0__MS_Y2_SHIFT 20
+# define R300_GB_MSPOS0__MSBD0_Y 24
+# define R300_GB_MSPOS0__MSBD0_X 28
+
+#define R300_GB_MSPOS1 0x4014
+# define R300_GB_MSPOS1__MS_X3_SHIFT 0
+# define R300_GB_MSPOS1__MS_Y3_SHIFT 4
+# define R300_GB_MSPOS1__MS_X4_SHIFT 8
+# define R300_GB_MSPOS1__MS_Y4_SHIFT 12
+# define R300_GB_MSPOS1__MS_X5_SHIFT 16
+# define R300_GB_MSPOS1__MS_Y5_SHIFT 20
+# define R300_GB_MSPOS1__MSBD1 24
+
+/* Specifies the graphics pipeline configuration for rasterization. */
+#define R300_GB_TILE_CONFIG 0x4018
+# define R300_GB_TILE_DISABLE (0 << 0)
+# define R300_GB_TILE_ENABLE (1 << 0)
+# define R300_GB_TILE_PIPE_COUNT_RV300 (0 << 1) /* RV350 (1 pipe, 1 ctx) */
+# define R300_GB_TILE_PIPE_COUNT_R300 (3 << 1) /* R300 (2 pipes, 1 ctx) */
+# define R300_GB_TILE_PIPE_COUNT_R420_3P (6 << 1) /* R420-3P (3 pipes, 1 ctx) */
+# define R300_GB_TILE_PIPE_COUNT_R420 (7 << 1) /* R420 (4 pipes, 1 ctx) */
+# define R300_GB_TILE_SIZE_8 (0 << 4)
+# define R300_GB_TILE_SIZE_16 (1 << 4)
+# define R300_GB_TILE_SIZE_32 (2 << 4)
+# define R300_GB_SUPER_SIZE_1 (0 << 6)
+# define R300_GB_SUPER_SIZE_2 (1 << 6)
+# define R300_GB_SUPER_SIZE_4 (2 << 6)
+# define R300_GB_SUPER_SIZE_8 (3 << 6)
+# define R300_GB_SUPER_SIZE_16 (4 << 6)
+# define R300_GB_SUPER_SIZE_32 (5 << 6)
+# define R300_GB_SUPER_SIZE_64 (6 << 6)
+# define R300_GB_SUPER_SIZE_128 (7 << 6)
+# define R300_GB_SUPER_X_SHIFT 9 /* 3 bits wide */
+# define R300_GB_SUPER_Y_SHIFT 12 /* 3 bits wide */
+# define R300_GB_SUPER_TILE_A (0 << 15)
+# define R300_GB_SUPER_TILE_B (1 << 15)
+# define R300_GB_SUBPIXEL_1_12 (0 << 16)
+# define R300_GB_SUBPIXEL_1_16 (1 << 16)
+# define GB_TILE_CONFIG_QUADS_PER_RAS_4 (0 << 17)
+# define GB_TILE_CONFIG_QUADS_PER_RAS_8 (1 << 17)
+# define GB_TILE_CONFIG_QUADS_PER_RAS_16 (2 << 17)
+# define GB_TILE_CONFIG_QUADS_PER_RAS_32 (3 << 17)
+# define GB_TILE_CONFIG_BB_SCAN_INTERCEPT (0 << 19)
+# define GB_TILE_CONFIG_BB_SCAN_BOUND_BOX (1 << 19)
+# define GB_TILE_CONFIG_ALT_SCAN_EN_LR (0 << 20)
+# define GB_TILE_CONFIG_ALT_SCAN_EN_LRL (1 << 20)
+# define GB_TILE_CONFIG_ALT_OFFSET (0 << 21)
+# define GB_TILE_CONFIG_SUBPRECISION (0 << 22)
+# define GB_TILE_CONFIG_ALT_TILING_DEF (0 << 23)
+# define GB_TILE_CONFIG_ALT_TILING_3_2 (1 << 23)
+# define GB_TILE_CONFIG_Z_EXTENDED_24_1 (0 << 24)
+# define GB_TILE_CONFIG_Z_EXTENDED_S25_1 (1 << 24)
+
+/* Specifies the sizes of the various FIFO`s in the sc/rs/us. This register must be the first one written */
+#define R300_GB_FIFO_SIZE 0x4024
+ /* each of the following is 2 bits wide */
+#define R300_GB_FIFO_SIZE_32 0
+#define R300_GB_FIFO_SIZE_64 1
+#define R300_GB_FIFO_SIZE_128 2
+#define R300_GB_FIFO_SIZE_256 3
+# define R300_SC_IFIFO_SIZE_SHIFT 0
+# define R300_SC_TZFIFO_SIZE_SHIFT 2
+# define R300_SC_BFIFO_SIZE_SHIFT 4
+
+# define R300_US_OFIFO_SIZE_SHIFT 12
+# define R300_US_WFIFO_SIZE_SHIFT 14
+ /* the following use the same constants as above, but meaning is
+ is times 2 (i.e. instead of 32 words it means 64 */
+# define R300_RS_TFIFO_SIZE_SHIFT 6
+# define R300_RS_CFIFO_SIZE_SHIFT 8
+# define R300_US_RAM_SIZE_SHIFT 10
+ /* watermarks, 3 bits wide */
+# define R300_RS_HIGHWATER_COL_SHIFT 16
+# define R300_RS_HIGHWATER_TEX_SHIFT 19
+# define R300_OFIFO_HIGHWATER_SHIFT 22 /* two bits only */
+# define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT 24
+
+#define GB_Z_PEQ_CONFIG 0x4028
+# define GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_4_4 (0 << 0)
+# define GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_8_8 (1 << 0)
+
+/* Specifies various polygon specific selects (fog, depth, perspective). */
+#define R300_GB_SELECT 0x401c
+# define R300_GB_FOG_SELECT_C0A (0 << 0)
+# define R300_GB_FOG_SELECT_C1A (1 << 0)
+# define R300_GB_FOG_SELECT_C2A (2 << 0)
+# define R300_GB_FOG_SELECT_C3A (3 << 0)
+# define R300_GB_FOG_SELECT_1_1_W (4 << 0)
+# define R300_GB_FOG_SELECT_Z (5 << 0)
+# define R300_GB_DEPTH_SELECT_Z (0 << 3)
+# define R300_GB_DEPTH_SELECT_1_1_W (1 << 3)
+# define R300_GB_W_SELECT_1_W (0 << 4)
+# define R300_GB_W_SELECT_1 (1 << 4)
+# define R300_GB_FOG_STUFF_DISABLE (0 << 5)
+# define R300_GB_FOG_STUFF_ENABLE (1 << 5)
+# define R300_GB_FOG_STUFF_TEX_SHIFT 6
+# define R300_GB_FOG_STUFF_TEX_MASK 0x000003c0
+# define R300_GB_FOG_STUFF_COMP_SHIFT 10
+# define R300_GB_FOG_STUFF_COMP_MASK 0x00000c00
+
+/* Specifies the graphics pipeline configuration for antialiasing. */
+#define R300_GB_AA_CONFIG 0x4020
+# define GB_AA_CONFIG_AA_DISABLE (0 << 0)
+# define GB_AA_CONFIG_AA_ENABLE (1 << 0)
+# define GB_AA_CONFIG_NUM_AA_SUBSAMPLES_2 (0 << 1)
+# define GB_AA_CONFIG_NUM_AA_SUBSAMPLES_3 (1 << 1)
+# define GB_AA_CONFIG_NUM_AA_SUBSAMPLES_4 (2 << 1)
+# define GB_AA_CONFIG_NUM_AA_SUBSAMPLES_6 (3 << 1)
+
+/* Selects which of 4 pipes are active. */
+#define GB_PIPE_SELECT 0x402c
+# define GB_PIPE_SELECT_PIPE0_ID_SHIFT 0
+# define GB_PIPE_SELECT_PIPE1_ID_SHIFT 2
+# define GB_PIPE_SELECT_PIPE2_ID_SHIFT 4
+# define GB_PIPE_SELECT_PIPE3_ID_SHIFT 6
+# define GB_PIPE_SELECT_PIPE_MASK_SHIFT 8
+# define GB_PIPE_SELECT_MAX_PIPE 12
+# define GB_PIPE_SELECT_BAD_PIPES 14
+# define GB_PIPE_SELECT_CONFIG_PIPES 18
+
+
+/* Specifies the sizes of the various FIFO`s in the sc/rs. */
+#define GB_FIFO_SIZE1 0x4070
+/* High water mark for SC input fifo */
+# define GB_FIFO_SIZE1_SC_HIGHWATER_IFIFO_SHIFT 0
+# define GB_FIFO_SIZE1_SC_HIGHWATER_IFIFO_MASK 0x0000003f
+/* High water mark for SC input fifo (B) */
+# define GB_FIFO_SIZE1_SC_HIGHWATER_BFIFO_SHIFT 6
+# define GB_FIFO_SIZE1_SC_HIGHWATER_BFIFO_MASK 0x00000fc0
+/* High water mark for RS colors' fifo */
+# define GB_FIFO_SIZE1_SC_HIGHWATER_COL_SHIFT 12
+# define GB_FIFO_SIZE1_SC_HIGHWATER_COL_MASK 0x0003f000
+/* High water mark for RS textures' fifo */
+# define GB_FIFO_SIZE1_SC_HIGHWATER_TEX_SHIFT 18
+# define GB_FIFO_SIZE1_SC_HIGHWATER_TEX_MASK 0x00fc0000
+
+/* This table specifies the source location and format for up to 16 texture
+ * addresses (i[0]:i[15]) and four colors (c[0]:c[3])
+ */
+#define R500_RS_IP_0 0x4074
+#define R500_RS_IP_1 0x4078
+#define R500_RS_IP_2 0x407C
+#define R500_RS_IP_3 0x4080
+#define R500_RS_IP_4 0x4084
+#define R500_RS_IP_5 0x4088
+#define R500_RS_IP_6 0x408C
+#define R500_RS_IP_7 0x4090
+#define R500_RS_IP_8 0x4094
+#define R500_RS_IP_9 0x4098
+#define R500_RS_IP_10 0x409C
+#define R500_RS_IP_11 0x40A0
+#define R500_RS_IP_12 0x40A4
+#define R500_RS_IP_13 0x40A8
+#define R500_RS_IP_14 0x40AC
+#define R500_RS_IP_15 0x40B0
+#define R500_RS_IP_PTR_K0 62
+#define R500_RS_IP_PTR_K1 63
+#define R500_RS_IP_TEX_PTR_S_SHIFT 0
+#define R500_RS_IP_TEX_PTR_T_SHIFT 6
+#define R500_RS_IP_TEX_PTR_R_SHIFT 12
+#define R500_RS_IP_TEX_PTR_Q_SHIFT 18
+#define R500_RS_IP_COL_PTR_SHIFT 24
+#define R500_RS_IP_COL_FMT_SHIFT 27
+# define R500_RS_SEL_S(x) ((x) << 0)
+# define R500_RS_SEL_T(x) ((x) << 6)
+# define R500_RS_SEL_R(x) ((x) << 12)
+# define R500_RS_SEL_Q(x) ((x) << 18)
+# define R500_RS_COL_PTR(x) ((x) << 24)
+# define R500_RS_COL_FMT(x) ((x) << 27)
+/* gap */
+#define R500_RS_IP_OFFSET_DIS (0 << 31)
+#define R500_RS_IP_OFFSET_EN (1 << 31)
+
+/* gap */
+
+/* Zero to flush caches. */
+#define R300_TX_INVALTAGS 0x4100
+#define R300_TX_FLUSH 0x0
+
+/* The upper enable bits are guessed, based on fglrx reported limits. */
+#define R300_TX_ENABLE 0x4104
+# define R300_TX_ENABLE_0 (1 << 0)
+# define R300_TX_ENABLE_1 (1 << 1)
+# define R300_TX_ENABLE_2 (1 << 2)
+# define R300_TX_ENABLE_3 (1 << 3)
+# define R300_TX_ENABLE_4 (1 << 4)
+# define R300_TX_ENABLE_5 (1 << 5)
+# define R300_TX_ENABLE_6 (1 << 6)
+# define R300_TX_ENABLE_7 (1 << 7)
+# define R300_TX_ENABLE_8 (1 << 8)
+# define R300_TX_ENABLE_9 (1 << 9)
+# define R300_TX_ENABLE_10 (1 << 10)
+# define R300_TX_ENABLE_11 (1 << 11)
+# define R300_TX_ENABLE_12 (1 << 12)
+# define R300_TX_ENABLE_13 (1 << 13)
+# define R300_TX_ENABLE_14 (1 << 14)
+# define R300_TX_ENABLE_15 (1 << 15)
+
+#define R500_TX_FILTER_4 0x4110
+# define R500_TX_WEIGHT_1_SHIFT (0)
+# define R500_TX_WEIGHT_0_SHIFT (11)
+# define R500_TX_WEIGHT_PAIR (1<<22)
+# define R500_TX_PHASE_SHIFT (23)
+# define R500_TX_DIRECTION_HORIZONTAL (0<<27)
+# define R500_TX_DIRECTION_VERITCAL (1<<27)
+
+/* S Texture Coordinate of Vertex 0 for Point texture stuffing (LLC) */
+#define R300_GA_POINT_S0 0x4200
+
+/* T Texture Coordinate of Vertex 0 for Point texture stuffing (LLC) */
+#define R300_GA_POINT_T0 0x4204
+
+/* S Texture Coordinate of Vertex 2 for Point texture stuffing (URC) */
+#define R300_GA_POINT_S1 0x4208
+
+/* T Texture Coordinate of Vertex 2 for Point texture stuffing (URC) */
+#define R300_GA_POINT_T1 0x420c
+
+/* Specifies amount to shift integer position of vertex (screen space) before
+ * converting to float for triangle stipple.
+ */
+#define R300_GA_TRIANGLE_STIPPLE 0x4214
+# define R300_GA_TRIANGLE_STIPPLE_X_SHIFT_SHIFT 0
+# define R300_GA_TRIANGLE_STIPPLE_X_SHIFT_MASK 0x0000000f
+# define R300_GA_TRIANGLE_STIPPLE_Y_SHIFT_SHIFT 16
+# define R300_GA_TRIANGLE_STIPPLE_Y_SHIFT_MASK 0x000f0000
+
+/* The pointsize is given in multiples of 6. The pointsize can be enormous:
+ * Clear() renders a single point that fills the entire framebuffer.
+ * 1/2 Height of point; fixed (16.0), subpixel format (1/12 or 1/16, even if in
+ * 8b precision).
+ */
+#define R300_GA_POINT_SIZE 0x421C
+# define R300_POINTSIZE_Y_SHIFT 0
+# define R300_POINTSIZE_Y_MASK 0x0000ffff
+# define R300_POINTSIZE_X_SHIFT 16
+# define R300_POINTSIZE_X_MASK 0xffff0000
+# define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6)
+
+/* Blue fill color */
+#define R500_GA_FILL_R 0x4220
+
+/* Blue fill color */
+#define R500_GA_FILL_G 0x4224
+
+/* Blue fill color */
+#define R500_GA_FILL_B 0x4228
+
+/* Alpha fill color */
+#define R500_GA_FILL_A 0x422c
+
+
+/* Specifies maximum and minimum point & sprite sizes for per vertex size
+ * specification. The lower part (15:0) is MIN and (31:16) is max.
+ */
+#define R300_GA_POINT_MINMAX 0x4230
+# define R300_GA_POINT_MINMAX_MIN_SHIFT 0
+# define R300_GA_POINT_MINMAX_MIN_MASK (0xFFFF << 0)
+# define R300_GA_POINT_MINMAX_MAX_SHIFT 16
+# define R300_GA_POINT_MINMAX_MAX_MASK (0xFFFF << 16)
+
+/* 1/2 width of line, in subpixels (1/12 or 1/16 only, even in 8b
+ * subprecision); (16.0) fixed format.
+ *
+ * The line width is given in multiples of 6.
+ * In default mode lines are classified as vertical lines.
+ * HO: horizontal
+ * VE: vertical or horizontal
+ * HO & VE: no classification
+ */
+#define R300_GA_LINE_CNTL 0x4234
+# define R300_GA_LINE_CNTL_WIDTH_SHIFT 0
+# define R300_GA_LINE_CNTL_WIDTH_MASK 0x0000ffff
+# define R300_GA_LINE_CNTL_END_TYPE_HOR (0 << 16)
+# define R300_GA_LINE_CNTL_END_TYPE_VER (1 << 16)
+# define R300_GA_LINE_CNTL_END_TYPE_SQR (2 << 16) /* horizontal or vertical depending upon slope */
+# define R300_GA_LINE_CNTL_END_TYPE_COMP (3 << 16) /* Computed (perpendicular to slope) */
+# define R500_GA_LINE_CNTL_SORT_NO (0 << 18)
+# define R500_GA_LINE_CNTL_SORT_MINX_MINY (1 << 18)
+/** TODO: looks wrong */
+# define R300_LINESIZE_MAX (R300_GA_LINE_CNTL_WIDTH_MASK / 6)
+/** TODO: looks wrong */
+# define R300_LINE_CNT_HO (1 << 16)
+/** TODO: looks wrong */
+# define R300_LINE_CNT_VE (1 << 17)
+
+/* Line Stipple configuration information. */
+#define R300_GA_LINE_STIPPLE_CONFIG 0x4238
+# define R300_GA_LINE_STIPPLE_CONFIG_LINE_RESET_NO (0 << 0)
+# define R300_GA_LINE_STIPPLE_CONFIG_LINE_RESET_LINE (1 << 0)
+# define R300_GA_LINE_STIPPLE_CONFIG_LINE_RESET_PACKET (2 << 0)
+# define R300_GA_LINE_STIPPLE_CONFIG_STIPPLE_SCALE_SHIFT 2
+# define R300_GA_LINE_STIPPLE_CONFIG_STIPPLE_SCALE_MASK 0xfffffffc
+
+/* Used to load US instructions and constants */
+#define R500_GA_US_VECTOR_INDEX 0x4250
+# define R500_GA_US_VECTOR_INDEX_SHIFT 0
+# define R500_GA_US_VECTOR_INDEX_MASK 0x000000ff
+# define R500_GA_US_VECTOR_INDEX_TYPE_INSTR (0 << 16)
+# define R500_GA_US_VECTOR_INDEX_TYPE_CONST (1 << 16)
+# define R500_GA_US_VECTOR_INDEX_CLAMP_NO (0 << 17)
+# define R500_GA_US_VECTOR_INDEX_CLAMP_CONST (1 << 17)
+
+/* Data register for loading US instructions and constants */
+#define R500_GA_US_VECTOR_DATA 0x4254
+
+/* Specifies color properties and mappings of textures. */
+#define R500_GA_COLOR_CONTROL_PS3 0x4258
+# define R500_TEX0_SHADING_PS3_SOLID (0 << 0)
+# define R500_TEX0_SHADING_PS3_FLAT (1 << 0)
+# define R500_TEX0_SHADING_PS3_GOURAUD (2 << 0)
+# define R500_TEX1_SHADING_PS3_SOLID (0 << 2)
+# define R500_TEX1_SHADING_PS3_FLAT (1 << 2)
+# define R500_TEX1_SHADING_PS3_GOURAUD (2 << 2)
+# define R500_TEX2_SHADING_PS3_SOLID (0 << 4)
+# define R500_TEX2_SHADING_PS3_FLAT (1 << 4)
+# define R500_TEX2_SHADING_PS3_GOURAUD (2 << 4)
+# define R500_TEX3_SHADING_PS3_SOLID (0 << 6)
+# define R500_TEX3_SHADING_PS3_FLAT (1 << 6)
+# define R500_TEX3_SHADING_PS3_GOURAUD (2 << 6)
+# define R500_TEX4_SHADING_PS3_SOLID (0 << 8)
+# define R500_TEX4_SHADING_PS3_FLAT (1 << 8)
+# define R500_TEX4_SHADING_PS3_GOURAUD (2 << 8)
+# define R500_TEX5_SHADING_PS3_SOLID (0 << 10)
+# define R500_TEX5_SHADING_PS3_FLAT (1 << 10)
+# define R500_TEX5_SHADING_PS3_GOURAUD (2 << 10)
+# define R500_TEX6_SHADING_PS3_SOLID (0 << 12)
+# define R500_TEX6_SHADING_PS3_FLAT (1 << 12)
+# define R500_TEX6_SHADING_PS3_GOURAUD (2 << 12)
+# define R500_TEX7_SHADING_PS3_SOLID (0 << 14)
+# define R500_TEX7_SHADING_PS3_FLAT (1 << 14)
+# define R500_TEX7_SHADING_PS3_GOURAUD (2 << 14)
+# define R500_TEX8_SHADING_PS3_SOLID (0 << 16)
+# define R500_TEX8_SHADING_PS3_FLAT (1 << 16)
+# define R500_TEX8_SHADING_PS3_GOURAUD (2 << 16)
+# define R500_TEX9_SHADING_PS3_SOLID (0 << 18)
+# define R500_TEX9_SHADING_PS3_FLAT (1 << 18)
+# define R500_TEX9_SHADING_PS3_GOURAUD (2 << 18)
+# define R500_TEX10_SHADING_PS3_SOLID (0 << 20)
+# define R500_TEX10_SHADING_PS3_FLAT (1 << 20)
+# define R500_TEX10_SHADING_PS3_GOURAUD (2 << 20)
+# define R500_COLOR0_TEX_OVERRIDE_NO (0 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_0 (1 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_1 (2 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_2 (3 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_3 (4 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_4 (5 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_5 (6 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_6 (7 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_7 (8 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_8_C2 (9 << 22)
+# define R500_COLOR0_TEX_OVERRIDE_TEX_9_C3 (10 << 22)
+# define R500_COLOR1_TEX_OVERRIDE_NO (0 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_0 (1 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_1 (2 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_2 (3 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_3 (4 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_4 (5 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_5 (6 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_6 (7 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_7 (8 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_8_C2 (9 << 26)
+# define R500_COLOR1_TEX_OVERRIDE_TEX_9_C3 (10 << 26)
+
+/* Returns idle status of various G3D block, captured when GA_IDLE written or
+ * when hard or soft reset asserted.
+ */
+#define R500_GA_IDLE 0x425c
+# define R500_GA_IDLE_PIPE3_Z_IDLE (0 << 0)
+# define R500_GA_IDLE_PIPE2_Z_IDLE (0 << 1)
+# define R500_GA_IDLE_PIPE3_CD_IDLE (0 << 2)
+# define R500_GA_IDLE_PIPE2_CD_IDLE (0 << 3)
+# define R500_GA_IDLE_PIPE3_FG_IDLE (0 << 4)
+# define R500_GA_IDLE_PIPE2_FG_IDLE (0 << 5)
+# define R500_GA_IDLE_PIPE3_US_IDLE (0 << 6)
+# define R500_GA_IDLE_PIPE2_US_IDLE (0 << 7)
+# define R500_GA_IDLE_PIPE3_SC_IDLE (0 << 8)
+# define R500_GA_IDLE_PIPE2_SC_IDLE (0 << 9)
+# define R500_GA_IDLE_PIPE3_RS_IDLE (0 << 10)
+# define R500_GA_IDLE_PIPE2_RS_IDLE (0 << 11)
+# define R500_GA_IDLE_PIPE1_Z_IDLE (0 << 12)
+# define R500_GA_IDLE_PIPE0_Z_IDLE (0 << 13)
+# define R500_GA_IDLE_PIPE1_CD_IDLE (0 << 14)
+# define R500_GA_IDLE_PIPE0_CD_IDLE (0 << 15)
+# define R500_GA_IDLE_PIPE1_FG_IDLE (0 << 16)
+# define R500_GA_IDLE_PIPE0_FG_IDLE (0 << 17)
+# define R500_GA_IDLE_PIPE1_US_IDLE (0 << 18)
+# define R500_GA_IDLE_PIPE0_US_IDLE (0 << 19)
+# define R500_GA_IDLE_PIPE1_SC_IDLE (0 << 20)
+# define R500_GA_IDLE_PIPE0_SC_IDLE (0 << 21)
+# define R500_GA_IDLE_PIPE1_RS_IDLE (0 << 22)
+# define R500_GA_IDLE_PIPE0_RS_IDLE (0 << 23)
+# define R500_GA_IDLE_SU_IDLE (0 << 24)
+# define R500_GA_IDLE_GA_IDLE (0 << 25)
+# define R500_GA_IDLE_GA_UNIT2_IDLE (0 << 26)
+
+/* Current value of stipple accumulator. */
+#define R300_GA_LINE_STIPPLE_VALUE 0x4260
+
+/* S Texture Coordinate Value for Vertex 0 of Line (stuff textures -- i.e. AA) */
+#define R300_GA_LINE_S0 0x4264
+/* S Texture Coordinate Value for Vertex 1 of Lines (V2 of parallelogram -- stuff textures -- i.e. AA) */
+#define R300_GA_LINE_S1 0x4268
+
+/* GA Input fifo high water marks */
+#define R500_GA_FIFO_CNTL 0x4270
+# define R500_GA_FIFO_CNTL_VERTEX_FIFO_MASK 0x00000007
+# define R500_GA_FIFO_CNTL_VERTEX_FIFO_SHIFT 0
+# define R500_GA_FIFO_CNTL_VERTEX_INDEX_MASK 0x00000038
+# define R500_GA_FIFO_CNTL_VERTEX_INDEX_SHIFT 3
+# define R500_GA_FIFO_CNTL_VERTEX_REG_MASK 0x00003fc0
+# define R500_GA_FIFO_CNTL_VERTEX_REG_SHIFT 6
+
+/* GA enhance/tweaks */
+#define R300_GA_ENHANCE 0x4274
+# define R300_GA_ENHANCE_DEADLOCK_CNTL_NO_EFFECT (0 << 0)
+# define R300_GA_ENHANCE_DEADLOCK_CNTL_PREVENT_TCL (1 << 0) /* Prevents TCL interface from deadlocking on GA side. */
+# define R300_GA_ENHANCE_FASTSYNC_CNTL_NO_EFFECT (0 << 1)
+# define R300_GA_ENHANCE_FASTSYNC_CNTL_ENABLE (1 << 1) /* Enables high-performance register/primitive switching. */
+# define R500_GA_ENHANCE_REG_READWRITE_NO_EFFECT (0 << 2) /* R520+ only */
+# define R500_GA_ENHANCE_REG_READWRITE_ENABLE (1 << 2) /* R520+ only, Enables GA support of simultaneous register reads and writes. */
+# define R500_GA_ENHANCE_REG_NOSTALL_NO_EFFECT (0 << 3)
+# define R500_GA_ENHANCE_REG_NOSTALL_ENABLE (1 << 3) /* Enables GA support of no-stall reads for register read back. */
+
+#define R300_GA_COLOR_CONTROL 0x4278
+# define R300_GA_COLOR_CONTROL_RGB0_SHADING_SOLID (0 << 0)
+# define R300_GA_COLOR_CONTROL_RGB0_SHADING_FLAT (1 << 0)
+# define R300_GA_COLOR_CONTROL_RGB0_SHADING_GOURAUD (2 << 0)
+# define R300_GA_COLOR_CONTROL_ALPHA0_SHADING_SOLID (0 << 2)
+# define R300_GA_COLOR_CONTROL_ALPHA0_SHADING_FLAT (1 << 2)
+# define R300_GA_COLOR_CONTROL_ALPHA0_SHADING_GOURAUD (2 << 2)
+# define R300_GA_COLOR_CONTROL_RGB1_SHADING_SOLID (0 << 4)
+# define R300_GA_COLOR_CONTROL_RGB1_SHADING_FLAT (1 << 4)
+# define R300_GA_COLOR_CONTROL_RGB1_SHADING_GOURAUD (2 << 4)
+# define R300_GA_COLOR_CONTROL_ALPHA1_SHADING_SOLID (0 << 6)
+# define R300_GA_COLOR_CONTROL_ALPHA1_SHADING_FLAT (1 << 6)
+# define R300_GA_COLOR_CONTROL_ALPHA1_SHADING_GOURAUD (2 << 6)
+# define R300_GA_COLOR_CONTROL_RGB2_SHADING_SOLID (0 << 8)
+# define R300_GA_COLOR_CONTROL_RGB2_SHADING_FLAT (1 << 8)
+# define R300_GA_COLOR_CONTROL_RGB2_SHADING_GOURAUD (2 << 8)
+# define R300_GA_COLOR_CONTROL_ALPHA2_SHADING_SOLID (0 << 10)
+# define R300_GA_COLOR_CONTROL_ALPHA2_SHADING_FLAT (1 << 10)
+# define R300_GA_COLOR_CONTROL_ALPHA2_SHADING_GOURAUD (2 << 10)
+# define R300_GA_COLOR_CONTROL_RGB3_SHADING_SOLID (0 << 12)
+# define R300_GA_COLOR_CONTROL_RGB3_SHADING_FLAT (1 << 12)
+# define R300_GA_COLOR_CONTROL_RGB3_SHADING_GOURAUD (2 << 12)
+# define R300_GA_COLOR_CONTROL_ALPHA3_SHADING_SOLID (0 << 14)
+# define R300_GA_COLOR_CONTROL_ALPHA3_SHADING_FLAT (1 << 14)
+# define R300_GA_COLOR_CONTROL_ALPHA3_SHADING_GOURAUD (2 << 14)
+# define R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_FIRST (0 << 16)
+# define R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_SECOND (1 << 16)
+# define R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_THIRD (2 << 16)
+# define R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST (3 << 16)
+
+# define R300_SHADE_MODEL_FLAT ( \
+ R300_GA_COLOR_CONTROL_RGB0_SHADING_FLAT | \
+ R300_GA_COLOR_CONTROL_ALPHA0_SHADING_FLAT | \
+ R300_GA_COLOR_CONTROL_RGB1_SHADING_FLAT | \
+ R300_GA_COLOR_CONTROL_ALPHA1_SHADING_FLAT | \
+ R300_GA_COLOR_CONTROL_RGB2_SHADING_FLAT | \
+ R300_GA_COLOR_CONTROL_ALPHA2_SHADING_FLAT | \
+ R300_GA_COLOR_CONTROL_RGB3_SHADING_FLAT | \
+ R300_GA_COLOR_CONTROL_ALPHA3_SHADING_FLAT )
+
+# define R300_SHADE_MODEL_SMOOTH ( \
+ R300_GA_COLOR_CONTROL_RGB0_SHADING_GOURAUD | \
+ R300_GA_COLOR_CONTROL_ALPHA0_SHADING_GOURAUD | \
+ R300_GA_COLOR_CONTROL_RGB1_SHADING_GOURAUD | \
+ R300_GA_COLOR_CONTROL_ALPHA1_SHADING_GOURAUD | \
+ R300_GA_COLOR_CONTROL_RGB2_SHADING_GOURAUD | \
+ R300_GA_COLOR_CONTROL_ALPHA2_SHADING_GOURAUD | \
+ R300_GA_COLOR_CONTROL_RGB3_SHADING_GOURAUD | \
+ R300_GA_COLOR_CONTROL_ALPHA3_SHADING_GOURAUD )
+
+/* Specifies red & green components of fill color -- S312 format -- Backwards comp. */
+#define R300_GA_SOLID_RG 0x427c
+# define GA_SOLID_RG_COLOR_GREEN_SHIFT 0
+# define GA_SOLID_RG_COLOR_GREEN_MASK 0x0000ffff
+# define GA_SOLID_RG_COLOR_RED_SHIFT 16
+# define GA_SOLID_RG_COLOR_RED_MASK 0xffff0000
+/* Specifies blue & alpha components of fill color -- S312 format -- Backwards comp. */
+#define R300_GA_SOLID_BA 0x4280
+# define GA_SOLID_BA_COLOR_ALPHA_SHIFT 0
+# define GA_SOLID_BA_COLOR_ALPHA_MASK 0x0000ffff
+# define GA_SOLID_BA_COLOR_BLUE_SHIFT 16
+# define GA_SOLID_BA_COLOR_BLUE_MASK 0xffff0000
+
+/* Polygon Mode
+ * Dangerous
+ */
+#define R300_GA_POLY_MODE 0x4288
+# define R300_GA_POLY_MODE_DISABLE (0 << 0)
+# define R300_GA_POLY_MODE_DUAL (1 << 0) /* send 2 sets of 3 polys with specified poly type */
+/* reserved */
+# define R300_GA_POLY_MODE_FRONT_PTYPE_POINT (0 << 4)
+# define R300_GA_POLY_MODE_FRONT_PTYPE_LINE (1 << 4)
+# define R300_GA_POLY_MODE_FRONT_PTYPE_TRI (2 << 4)
+/* reserved */
+# define R300_GA_POLY_MODE_BACK_PTYPE_POINT (0 << 7)
+# define R300_GA_POLY_MODE_BACK_PTYPE_LINE (1 << 7)
+# define R300_GA_POLY_MODE_BACK_PTYPE_TRI (2 << 7)
+/* reserved */
+
+/* Specifies the rouding mode for geometry & color SPFP to FP conversions. */
+#define R300_GA_ROUND_MODE 0x428c
+# define R300_GA_ROUND_MODE_GEOMETRY_ROUND_TRUNC (0 << 0)
+# define R300_GA_ROUND_MODE_GEOMETRY_ROUND_NEAREST (1 << 0)
+# define R300_GA_ROUND_MODE_COLOR_ROUND_TRUNC (0 << 2)
+# define R300_GA_ROUND_MODE_COLOR_ROUND_NEAREST (1 << 2)
+# define R300_GA_ROUND_MODE_RGB_CLAMP_RGB (0 << 4)
+# define R300_GA_ROUND_MODE_RGB_CLAMP_FP20 (1 << 4)
+# define R300_GA_ROUND_MODE_ALPHA_CLAMP_RGB (0 << 5)
+# define R300_GA_ROUND_MODE_ALPHA_CLAMP_FP20 (1 << 5)
+# define R500_GA_ROUND_MODE_GEOMETRY_MASK_SHIFT 6
+# define R500_GA_ROUND_MODE_GEOMETRY_MASK_MASK 0x000003c0
+
+/* Specifies x & y offsets for vertex data after conversion to FP.
+ * Offsets are in S15 format (subpixels -- 1/12 or 1/16, even in 8b
+ * subprecision).
+ */
+#define R300_GA_OFFSET 0x4290
+# define R300_GA_OFFSET_X_OFFSET_SHIFT 0
+# define R300_GA_OFFSET_X_OFFSET_MASK 0x0000ffff
+# define R300_GA_OFFSET_Y_OFFSET_SHIFT 16
+# define R300_GA_OFFSET_Y_OFFSET_MASK 0xffff0000
+
+/* Specifies the scale to apply to fog. */
+#define R300_GA_FOG_SCALE 0x4294
+/* Specifies the offset to apply to fog. */
+#define R300_GA_FOG_OFFSET 0x4298
+/* Specifies number of cycles to assert reset, and also causes RB3D soft reset to assert. */
+#define R300_GA_SOFT_RESET 0x429c
+
+/* Not sure why there are duplicate of factor and constant values.
+ * My best guess so far is that there are seperate zbiases for test and write.
+ * Ordering might be wrong.
+ * Some of the tests indicate that fgl has a fallback implementation of zbias
+ * via pixel shaders.
+ */
+#define R300_SU_TEX_WRAP 0x42A0
+#define R300_SU_POLY_OFFSET_FRONT_SCALE 0x42A4
+#define R300_SU_POLY_OFFSET_FRONT_OFFSET 0x42A8
+#define R300_SU_POLY_OFFSET_BACK_SCALE 0x42AC
+#define R300_SU_POLY_OFFSET_BACK_OFFSET 0x42B0
+
+/* This register needs to be set to (1<<1) for RV350 to correctly
+ * perform depth test (see --vb-triangles in r300_demo)
+ * Don't know about other chips. - Vladimir
+ * This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
+ * My guess is that there are two bits for each zbias primitive
+ * (FILL, LINE, POINT).
+ * One to enable depth test and one for depth write.
+ * Yet this doesnt explain why depth writes work ...
+ */
+#define R300_SU_POLY_OFFSET_ENABLE 0x42B4
+# define R300_FRONT_ENABLE (1 << 0)
+# define R300_BACK_ENABLE (1 << 1)
+# define R300_PARA_ENABLE (1 << 2)
+
+#define R300_SU_CULL_MODE 0x42B8
+# define R300_CULL_FRONT (1 << 0)
+# define R300_CULL_BACK (1 << 1)
+# define R300_FRONT_FACE_CCW (0 << 2)
+# define R300_FRONT_FACE_CW (1 << 2)
+
+/* SU Depth Scale value */
+#define R300_SU_DEPTH_SCALE 0x42c0
+/* SU Depth Offset value */
+#define R300_SU_DEPTH_OFFSET 0x42c4
+
+
+/* BEGIN: Rasterization / Interpolators - many guesses */
+
+/*
+ * TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
+ * on the vertex program, *not* the fragment program)
+ */
+#define R300_RS_COUNT 0x4300
+# define R300_IT_COUNT_SHIFT 0
+# define R300_IT_COUNT_MASK 0x0000007f
+# define R300_IC_COUNT_SHIFT 7
+# define R300_IC_COUNT_MASK 0x00000780
+# define R300_W_ADDR_SHIFT 12
+# define R300_W_ADDR_MASK 0x0003f000
+# define R300_HIRES_DIS (0 << 18)
+# define R300_HIRES_EN (1 << 18)
+# define R300_IT_COUNT(x) ((x) << 0)
+# define R300_IC_COUNT(x) ((x) << 7)
+# define R300_W_COUNT(x) ((x) << 12)
+
+#define R300_RS_INST_COUNT 0x4304
+# define R300_RS_INST_COUNT_SHIFT 0
+# define R300_RS_INST_COUNT_MASK 0x0000000f
+# define R300_RS_TX_OFFSET_SHIFT 5
+# define R300_RS_TX_OFFSET_MASK 0x000000e0
+# define R300_RS_TX_OFFSET(x) ((x) << 5)
+
+/* gap */
+
+/* Only used for texture coordinates.
+ * Use the source field to route texture coordinate input from the
+ * vertex program to the desired interpolator. Note that the source
+ * field is relative to the outputs the vertex program *actually*
+ * writes. If a vertex program only writes texcoord[1], this will
+ * be source index 0.
+ * Set INTERP_USED on all interpolators that produce data used by
+ * the fragment program. INTERP_USED looks like a swizzling mask,
+ * but I haven't seen it used that way.
+ *
+ * Note: The _UNKNOWN constants are always set in their respective
+ * register. I don't know if this is necessary.
+ */
+#define R300_RS_IP_0 0x4310
+#define R300_RS_IP_1 0x4314
+#define R300_RS_IP_2 0x4318
+#define R300_RS_IP_3 0x431C
+# define R300_RS_INTERP_SRC_SHIFT 2 /* TODO: check for removal */
+# define R300_RS_INTERP_SRC_MASK (7 << 2) /* TODO: check for removal */
+# define R300_RS_TEX_PTR(x) (x << 0)
+# define R300_RS_COL_PTR(x) ((x) << 6)
+# define R300_RS_COL_FMT(x) ((x) << 9)
+# define R300_RS_COL_FMT_RGBA 0
+# define R300_RS_COL_FMT_RGB0 1
+# define R300_RS_COL_FMT_RGB1 2
+# define R300_RS_COL_FMT_000A 4
+# define R300_RS_COL_FMT_0000 5
+# define R300_RS_COL_FMT_0001 6
+# define R300_RS_COL_FMT_111A 8
+# define R300_RS_COL_FMT_1110 9
+# define R300_RS_COL_FMT_1111 10
+# define R300_RS_SEL_S(x) ((x) << 13)
+# define R300_RS_SEL_T(x) ((x) << 16)
+# define R300_RS_SEL_R(x) ((x) << 19)
+# define R300_RS_SEL_Q(x) ((x) << 22)
+# define R300_RS_SEL_C0 0
+# define R300_RS_SEL_C1 1
+# define R300_RS_SEL_C2 2
+# define R300_RS_SEL_C3 3
+# define R300_RS_SEL_K0 4
+# define R300_RS_SEL_K1 5
+
+
+/* */
+#define R500_RS_INST_0 0x4320
+#define R500_RS_INST_1 0x4324
+#define R500_RS_INST_2 0x4328
+#define R500_RS_INST_3 0x432c
+#define R500_RS_INST_4 0x4330
+#define R500_RS_INST_5 0x4334
+#define R500_RS_INST_6 0x4338
+#define R500_RS_INST_7 0x433c
+#define R500_RS_INST_8 0x4340
+#define R500_RS_INST_9 0x4344
+#define R500_RS_INST_10 0x4348
+#define R500_RS_INST_11 0x434c
+#define R500_RS_INST_12 0x4350
+#define R500_RS_INST_13 0x4354
+#define R500_RS_INST_14 0x4358
+#define R500_RS_INST_15 0x435c
+#define R500_RS_INST_TEX_ID_SHIFT 0
+# define R500_RS_INST_TEX_ID(x) ((x) << 0)
+#define R500_RS_INST_TEX_CN_WRITE (1 << 4)
+#define R500_RS_INST_TEX_ADDR_SHIFT 5
+# define R500_RS_INST_TEX_ADDR(x) ((x) << 0)
+#define R500_RS_INST_COL_ID_SHIFT 12
+# define R500_RS_INST_COL_ID(x) ((x) << 12)
+#define R500_RS_INST_COL_CN_NO_WRITE (0 << 16)
+#define R500_RS_INST_COL_CN_WRITE (1 << 16)
+#define R500_RS_INST_COL_CN_WRITE_FBUFFER (2 << 16)
+#define R500_RS_INST_COL_CN_WRITE_BACKFACE (3 << 16)
+#define R500_RS_INST_COL_ADDR_SHIFT 18
+# define R500_RS_INST_COL_ADDR(x) ((x) << 18)
+#define R500_RS_INST_TEX_ADJ (1 << 25)
+#define R500_RS_INST_W_CN (1 << 26)
+
+/* These DWORDs control how vertex data is routed into fragment program
+ * registers, after interpolators.
+ */
+#define R300_RS_INST_0 0x4330
+#define R300_RS_INST_1 0x4334
+#define R300_RS_INST_2 0x4338
+#define R300_RS_INST_3 0x433C
+#define R300_RS_INST_4 0x4340
+#define R300_RS_INST_5 0x4344
+#define R300_RS_INST_6 0x4348
+#define R300_RS_INST_7 0x434C
+# define R300_RS_INST_TEX_ID(x) ((x) << 0)
+# define R300_RS_INST_TEX_CN_WRITE (1 << 3)
+# define R300_RS_INST_TEX_ADDR(x) ((x) << 6)
+# define R300_RS_INST_TEX_ADDR_SHIFT 6
+# define R300_RS_INST_COL_ID(x) ((x) << 11)
+# define R300_RS_INST_COL_CN_WRITE (1 << 14)
+# define R300_RS_INST_COL_ADDR(x) ((x) << 17)
+# define R300_RS_INST_COL_ADDR_SHIFT 17
+# define R300_RS_INST_TEX_ADJ (1 << 22)
+# define R300_RS_COL_BIAS_UNUSED_SHIFT 23
+
+/* END: Rasterization / Interpolators - many guesses */
+
+/* Hierarchical Z Enable */
+#define R300_SC_HYPERZ 0x43a4
+# define R300_SC_HYPERZ_DISABLE (0 << 0)
+# define R300_SC_HYPERZ_ENABLE (1 << 0)
+# define R300_SC_HYPERZ_MIN (0 << 1)
+# define R300_SC_HYPERZ_MAX (1 << 1)
+# define R300_SC_HYPERZ_ADJ_256 (0 << 2)
+# define R300_SC_HYPERZ_ADJ_128 (1 << 2)
+# define R300_SC_HYPERZ_ADJ_64 (2 << 2)
+# define R300_SC_HYPERZ_ADJ_32 (3 << 2)
+# define R300_SC_HYPERZ_ADJ_16 (4 << 2)
+# define R300_SC_HYPERZ_ADJ_8 (5 << 2)
+# define R300_SC_HYPERZ_ADJ_4 (6 << 2)
+# define R300_SC_HYPERZ_ADJ_2 (7 << 2)
+# define R300_SC_HYPERZ_HZ_Z0MIN_NO (0 << 5)
+# define R300_SC_HYPERZ_HZ_Z0MIN (1 << 5)
+# define R300_SC_HYPERZ_HZ_Z0MAX_NO (0 << 6)
+# define R300_SC_HYPERZ_HZ_Z0MAX (1 << 6)
+
+#define R300_SC_EDGERULE 0x43a8
+
+/* BEGIN: Scissors and cliprects */
+
+/* There are four clipping rectangles. Their corner coordinates are inclusive.
+ * Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
+ * on whether the pixel is inside cliprects 0-3, respectively. For example,
+ * if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
+ * the number 3 (binary 0011).
+ * Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
+ * the pixel is rasterized.
+ *
+ * In addition to this, there is a scissors rectangle. Only pixels inside the
+ * scissors rectangle are drawn. (coordinates are inclusive)
+ *
+ * For some reason, the top-left corner of the framebuffer is at (1440, 1440)
+ * for the purpose of clipping and scissors.
+ */
+#define R300_SC_CLIPRECT_TL_0 0x43B0
+#define R300_SC_CLIPRECT_BR_0 0x43B4
+#define R300_SC_CLIPRECT_TL_1 0x43B8
+#define R300_SC_CLIPRECT_BR_1 0x43BC
+#define R300_SC_CLIPRECT_TL_2 0x43C0
+#define R300_SC_CLIPRECT_BR_2 0x43C4
+#define R300_SC_CLIPRECT_TL_3 0x43C8
+#define R300_SC_CLIPRECT_BR_3 0x43CC
+# define R300_CLIPRECT_OFFSET 1440
+# define R300_CLIPRECT_MASK 0x1FFF
+# define R300_CLIPRECT_X_SHIFT 0
+# define R300_CLIPRECT_X_MASK (0x1FFF << 0)
+# define R300_CLIPRECT_Y_SHIFT 13
+# define R300_CLIPRECT_Y_MASK (0x1FFF << 13)
+#define R300_SC_CLIP_RULE 0x43D0
+# define R300_CLIP_OUT (1 << 0)
+# define R300_CLIP_0 (1 << 1)
+# define R300_CLIP_1 (1 << 2)
+# define R300_CLIP_10 (1 << 3)
+# define R300_CLIP_2 (1 << 4)
+# define R300_CLIP_20 (1 << 5)
+# define R300_CLIP_21 (1 << 6)
+# define R300_CLIP_210 (1 << 7)
+# define R300_CLIP_3 (1 << 8)
+# define R300_CLIP_30 (1 << 9)
+# define R300_CLIP_31 (1 << 10)
+# define R300_CLIP_310 (1 << 11)
+# define R300_CLIP_32 (1 << 12)
+# define R300_CLIP_320 (1 << 13)
+# define R300_CLIP_321 (1 << 14)
+# define R300_CLIP_3210 (1 << 15)
+
+/* gap */
+
+#define R300_SC_SCISSORS_TL 0x43E0
+#define R300_SC_SCISSORS_BR 0x43E4
+# define R300_SCISSORS_OFFSET 1440
+# define R300_SCISSORS_X_SHIFT 0
+# define R300_SCISSORS_X_MASK (0x1FFF << 0)
+# define R300_SCISSORS_Y_SHIFT 13
+# define R300_SCISSORS_Y_MASK (0x1FFF << 13)
+
+/* Screen door sample mask */
+#define R300_SC_SCREENDOOR 0x43e8
+
+/* END: Scissors and cliprects */
+
+/* BEGIN: Texture specification */
+
+/*
+ * The texture specification dwords are grouped by meaning and not by texture
+ * unit. This means that e.g. the offset for texture image unit N is found in
+ * register TX_OFFSET_0 + (4*N)
+ */
+#define R300_TX_FILTER0_0 0x4400
+#define R300_TX_FILTER0_1 0x4404
+#define R300_TX_FILTER0_2 0x4408
+#define R300_TX_FILTER0_3 0x440c
+#define R300_TX_FILTER0_4 0x4410
+#define R300_TX_FILTER0_5 0x4414
+#define R300_TX_FILTER0_6 0x4418
+#define R300_TX_FILTER0_7 0x441c
+#define R300_TX_FILTER0_8 0x4420
+#define R300_TX_FILTER0_9 0x4424
+#define R300_TX_FILTER0_10 0x4428
+#define R300_TX_FILTER0_11 0x442c
+#define R300_TX_FILTER0_12 0x4430
+#define R300_TX_FILTER0_13 0x4434
+#define R300_TX_FILTER0_14 0x4438
+#define R300_TX_FILTER0_15 0x443c
+# define R300_TX_REPEAT 0
+# define R300_TX_MIRRORED 1
+# define R300_TX_CLAMP_TO_EDGE 2
+# define R300_TX_MIRROR_ONCE_TO_EDGE 3
+# define R300_TX_CLAMP 4
+# define R300_TX_MIRROR_ONCE 5
+# define R300_TX_CLAMP_TO_BORDER 6
+# define R300_TX_MIRROR_ONCE_TO_BORDER 7
+# define R300_TX_WRAP_S_SHIFT 0
+# define R300_TX_WRAP_S_MASK (7 << 0)
+# define R300_TX_WRAP_T_SHIFT 3
+# define R300_TX_WRAP_T_MASK (7 << 3)
+# define R300_TX_WRAP_R_SHIFT 6
+# define R300_TX_WRAP_R_MASK (7 << 6)
+# define R300_TX_MAG_FILTER_4 (0 << 9)
+# define R300_TX_MAG_FILTER_NEAREST (1 << 9)
+# define R300_TX_MAG_FILTER_LINEAR (2 << 9)
+# define R300_TX_MAG_FILTER_ANISO (3 << 9)
+# define R300_TX_MAG_FILTER_MASK (3 << 9)
+# define R300_TX_MIN_FILTER_NEAREST (1 << 11)
+# define R300_TX_MIN_FILTER_LINEAR (2 << 11)
+# define R300_TX_MIN_FILTER_ANISO (3 << 11)
+# define R300_TX_MIN_FILTER_MASK (3 << 11)
+# define R300_TX_MIN_FILTER_MIP_NONE (0 << 13)
+# define R300_TX_MIN_FILTER_MIP_NEAREST (1 << 13)
+# define R300_TX_MIN_FILTER_MIP_LINEAR (2 << 13)
+# define R300_TX_MIN_FILTER_MIP_MASK (3 << 13)
+# define R300_TX_MAX_ANISO_1_TO_1 (0 << 21)
+# define R300_TX_MAX_ANISO_2_TO_1 (1 << 21)
+# define R300_TX_MAX_ANISO_4_TO_1 (2 << 21)
+# define R300_TX_MAX_ANISO_8_TO_1 (3 << 21)
+# define R300_TX_MAX_ANISO_16_TO_1 (4 << 21)
+# define R300_TX_MAX_ANISO_MASK (7 << 21)
+# define R300_TX_WRAP_S(x) ((x) << 0)
+# define R300_TX_WRAP_T(x) ((x) << 3)
+
+#define R300_TX_FILTER1_0 0x4440
+# define R300_CHROMA_KEY_MODE_DISABLE 0
+# define R300_CHROMA_KEY_FORCE 1
+# define R300_CHROMA_KEY_BLEND 2
+# define R300_MC_ROUND_NORMAL (0<<2)
+# define R300_MC_ROUND_MPEG4 (1<<2)
+# define R300_LOD_BIAS_SHIFT 3
+# define R300_LOD_BIAS_MASK 0x1ff8
+# define R300_EDGE_ANISO_EDGE_DIAG (0<<13)
+# define R300_EDGE_ANISO_EDGE_ONLY (1<<13)
+# define R300_MC_COORD_TRUNCATE_DISABLE (0<<14)
+# define R300_MC_COORD_TRUNCATE_MPEG (1<<14)
+# define R300_TX_TRI_PERF_0_8 (0<<15)
+# define R300_TX_TRI_PERF_1_8 (1<<15)
+# define R300_TX_TRI_PERF_1_4 (2<<15)
+# define R300_TX_TRI_PERF_3_8 (3<<15)
+# define R300_ANISO_THRESHOLD_MASK (7<<17)
+
+# define R500_MACRO_SWITCH (1<<22)
+# define R500_BORDER_FIX (1<<31)
+
+#define R300_TX_FORMAT0_0 0x4480
+# define R300_TX_WIDTHMASK_SHIFT 0
+# define R300_TX_WIDTHMASK_MASK (2047 << 0)
+# define R300_TX_HEIGHTMASK_SHIFT 11
+# define R300_TX_HEIGHTMASK_MASK (2047 << 11)
+# define R300_TX_DEPTHMASK_SHIFT 22
+# define R300_TX_DEPTHMASK_MASK (0xf << 22)
+# define R300_TX_MAX_MIP_LEVEL_SHIFT 26
+# define R300_TX_MAX_MIP_LEVEL_MASK (0xf << 26)
+# define R300_TX_SIZE_PROJECTED (1 << 30)
+# define R300_TX_PITCH_EN (1 << 31)
+# define R300_TX_WIDTH(x) ((x) << 0)
+# define R300_TX_HEIGHT(x) ((x) << 11)
+# define R300_TX_NUM_LEVELS(x) ((x) << 26)
+
+#define R300_TX_FORMAT1_0 0x44C0
+ /* The interpretation of the format word by Wladimir van der Laan */
+ /* The X, Y, Z and W refer to the layout of the components.
+ They are given meanings as R, G, B and Alpha by the swizzle
+ specification */
+# define R300_TX_FORMAT_X8 0x0
+# define R300_TX_FORMAT_X16 0x1
+# define R300_TX_FORMAT_Y4X4 0x2
+# define R300_TX_FORMAT_Y8X8 0x3
+# define R300_TX_FORMAT_Y16X16 0x4
+# define R300_TX_FORMAT_Z3Y3X2 0x5
+# define R300_TX_FORMAT_Z5Y6X5 0x6
+# define R300_TX_FORMAT_Z6Y5X5 0x7
+# define R300_TX_FORMAT_Z11Y11X10 0x8
+# define R300_TX_FORMAT_Z10Y11X11 0x9
+# define R300_TX_FORMAT_W4Z4Y4X4 0xA
+# define R300_TX_FORMAT_W1Z5Y5X5 0xB
+# define R300_TX_FORMAT_W8Z8Y8X8 0xC
+# define R300_TX_FORMAT_W2Z10Y10X10 0xD
+# define R300_TX_FORMAT_W16Z16Y16X16 0xE
+# define R300_TX_FORMAT_DXT1 0xF
+# define R300_TX_FORMAT_DXT3 0x10
+# define R300_TX_FORMAT_DXT5 0x11
+# define R300_TX_FORMAT_Y8 0x12
+# define R300_TX_FORMAT_AVYU444 0x13
+# define R300_TX_FORMAT_VYUY422 0x14
+# define R300_TX_FORMAT_YVYU422 0x15
+# define R300_TX_FORMAT_16_MPEG 0x16
+# define R300_TX_FORMAT_16_16_MPEG 0x17
+# define R300_TX_FORMAT_16F 0x18
+# define R300_TX_FORMAT_16F_16F 0x19
+# define R300_TX_FORMAT_16F_16F_16F_16F 0x1A
+# define R300_TX_FORMAT_32F 0x1B
+# define R300_TX_FORMAT_32F_32F 0x1C
+# define R300_TX_FORMAT_32F_32F_32F_32F 0x1D
+# define R300_TX_FORMAT_W24_FP 0x1E
+
+# define R300_TX_FORMAT_SIGNED_W (1 << 5)
+# define R300_TX_FORMAT_SIGNED_Z (1 << 6)
+# define R300_TX_FORMAT_SIGNED_Y (1 << 7)
+# define R300_TX_FORMAT_SIGNED_X (1 << 8)
+# define R300_TX_FORMAT_SIGNED (0xf << 5)
+
+# define R300_TX_FORMAT_3D (1 << 25)
+# define R300_TX_FORMAT_CUBIC_MAP (2 << 25)
+
+ /* alpha modes, convenience mostly */
+ /* if you have alpha, pick constant appropriate to the
+ number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */
+# define R300_TX_FORMAT_ALPHA_1CH 0x000
+# define R300_TX_FORMAT_ALPHA_2CH 0x200
+# define R300_TX_FORMAT_ALPHA_4CH 0x600
+# define R300_TX_FORMAT_ALPHA_NONE 0xA00
+ /* Swizzling */
+ /* constants */
+# define R300_TX_FORMAT_X 0
+# define R300_TX_FORMAT_Y 1
+# define R300_TX_FORMAT_Z 2
+# define R300_TX_FORMAT_W 3
+# define R300_TX_FORMAT_ZERO 4
+# define R300_TX_FORMAT_ONE 5
+ /* 2.0*Z, everything above 1.0 is set to 0.0 */
+# define R300_TX_FORMAT_CUT_Z 6
+ /* 2.0*W, everything above 1.0 is set to 0.0 */
+# define R300_TX_FORMAT_CUT_W 7
+
+# define R300_TX_FORMAT_B_SHIFT 18
+# define R300_TX_FORMAT_G_SHIFT 15
+# define R300_TX_FORMAT_R_SHIFT 12
+# define R300_TX_FORMAT_A_SHIFT 9
+ /* Convenience macro to take care of layout and swizzling */
+# define R300_EASY_TX_FORMAT(B, G, R, A, FMT) ( \
+ ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \
+ | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \
+ | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \
+ | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \
+ | (R300_TX_FORMAT_##FMT) \
+ )
+ /* These can be ORed with result of R300_EASY_TX_FORMAT()
+ We don't really know what they do. Take values from a
+ constant color ? */
+# define R300_TX_FORMAT_CONST_X (1<<5)
+# define R300_TX_FORMAT_CONST_Y (2<<5)
+# define R300_TX_FORMAT_CONST_Z (4<<5)
+# define R300_TX_FORMAT_CONST_W (8<<5)
+
+# define R300_TX_FORMAT_GAMMA (1 << 21)
+# define R300_TX_FORMAT_YUV_TO_RGB (1 << 22)
+
+#define R300_TX_FORMAT2_0 0x4500 /* obvious missing in gap */
+# define R300_TX_PITCHMASK_SHIFT 0
+# define R300_TX_PITCHMASK_MASK (2047 << 0)
+# define R500_TXFORMAT_MSB (1 << 14)
+# define R500_TXWIDTH_BIT11 (1 << 15)
+# define R500_TXHEIGHT_BIT11 (1 << 16)
+# define R500_POW2FIX2FLT (1 << 17)
+# define R500_SEL_FILTER4_TC0 (0 << 18)
+# define R500_SEL_FILTER4_TC1 (1 << 18)
+# define R500_SEL_FILTER4_TC2 (2 << 18)
+# define R500_SEL_FILTER4_TC3 (3 << 18)
+
+#define R300_TX_OFFSET_0 0x4540
+#define R300_TX_OFFSET_1 0x4544
+#define R300_TX_OFFSET_2 0x4548
+#define R300_TX_OFFSET_3 0x454C
+#define R300_TX_OFFSET_4 0x4550
+#define R300_TX_OFFSET_5 0x4554
+#define R300_TX_OFFSET_6 0x4558
+#define R300_TX_OFFSET_7 0x455C
+ /* BEGIN: Guess from R200 */
+# define R300_TXO_ENDIAN_NO_SWAP (0 << 0)
+# define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0)
+# define R300_TXO_ENDIAN_WORD_SWAP (2 << 0)
+# define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0)
+# define R300_TXO_MACRO_TILE (1 << 2)
+# define R300_TXO_MICRO_TILE_LINEAR (0 << 3)
+# define R300_TXO_MICRO_TILE (1 << 3)
+# define R300_TXO_MICRO_TILE_SQUARE (2 << 3)
+# define R300_TXO_OFFSET_MASK 0xffffffe0
+# define R300_TXO_OFFSET_SHIFT 5
+ /* END: Guess from R200 */
+
+/* 32 bit chroma key */
+#define R300_TX_CHROMA_KEY_0 0x4580
+#define R300_TX_CHROMA_KEY_1 0x4584
+#define R300_TX_CHROMA_KEY_2 0x4588
+#define R300_TX_CHROMA_KEY_3 0x458c
+#define R300_TX_CHROMA_KEY_4 0x4590
+#define R300_TX_CHROMA_KEY_5 0x4594
+#define R300_TX_CHROMA_KEY_6 0x4598
+#define R300_TX_CHROMA_KEY_7 0x459c
+#define R300_TX_CHROMA_KEY_8 0x45a0
+#define R300_TX_CHROMA_KEY_9 0x45a4
+#define R300_TX_CHROMA_KEY_10 0x45a8
+#define R300_TX_CHROMA_KEY_11 0x45ac
+#define R300_TX_CHROMA_KEY_12 0x45b0
+#define R300_TX_CHROMA_KEY_13 0x45b4
+#define R300_TX_CHROMA_KEY_14 0x45b8
+#define R300_TX_CHROMA_KEY_15 0x45bc
+/* ff00ff00 == { 0, 1.0, 0, 1.0 } */
+
+/* Border Color */
+#define R300_TX_BORDER_COLOR_0 0x45c0
+#define R300_TX_BORDER_COLOR_1 0x45c4
+#define R300_TX_BORDER_COLOR_2 0x45c8
+#define R300_TX_BORDER_COLOR_3 0x45cc
+#define R300_TX_BORDER_COLOR_4 0x45d0
+#define R300_TX_BORDER_COLOR_5 0x45d4
+#define R300_TX_BORDER_COLOR_6 0x45d8
+#define R300_TX_BORDER_COLOR_7 0x45dc
+#define R300_TX_BORDER_COLOR_8 0x45e0
+#define R300_TX_BORDER_COLOR_9 0x45e4
+#define R300_TX_BORDER_COLOR_10 0x45e8
+#define R300_TX_BORDER_COLOR_11 0x45ec
+#define R300_TX_BORDER_COLOR_12 0x45f0
+#define R300_TX_BORDER_COLOR_13 0x45f4
+#define R300_TX_BORDER_COLOR_14 0x45f8
+#define R300_TX_BORDER_COLOR_15 0x45fc
+
+
+/* END: Texture specification */
+
+/* BEGIN: Fragment program instruction set */
+
+/* Fragment programs are written directly into register space.
+ * There are separate instruction streams for texture instructions and ALU
+ * instructions.
+ * In order to synchronize these streams, the program is divided into up
+ * to 4 nodes. Each node begins with a number of TEX operations, followed
+ * by a number of ALU operations.
+ * The first node can have zero TEX ops, all subsequent nodes must have at
+ * least
+ * one TEX ops.
+ * All nodes must have at least one ALU op.
+ *
+ * The index of the last node is stored in PFS_CNTL_0: A value of 0 means
+ * 1 node, a value of 3 means 4 nodes.
+ * The total amount of instructions is defined in PFS_CNTL_2. The offsets are
+ * offsets into the respective instruction streams, while *_END points to the
+ * last instruction relative to this offset.
+ */
+#define R300_US_CONFIG 0x4600
+# define R300_PFS_CNTL_LAST_NODES_SHIFT 0
+# define R300_PFS_CNTL_LAST_NODES_MASK (3 << 0)
+# define R300_PFS_CNTL_FIRST_NODE_HAS_TEX (1 << 3)
+#define R300_US_PIXSIZE 0x4604
+/* There is an unshifted value here which has so far always been equal to the
+ * index of the highest used temporary register.
+ */
+#define R300_US_CODE_OFFSET 0x4608
+# define R300_PFS_CNTL_ALU_OFFSET_SHIFT 0
+# define R300_PFS_CNTL_ALU_OFFSET_MASK (63 << 0)
+# define R300_PFS_CNTL_ALU_END_SHIFT 6
+# define R300_PFS_CNTL_ALU_END_MASK (63 << 6)
+# define R300_PFS_CNTL_TEX_OFFSET_SHIFT 13
+# 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)
+
+/* gap */
+
+/* Nodes are stored backwards. The last active node is always stored in
+ * PFS_NODE_3.
+ * Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
+ * first node is stored in NODE_2, the second node is stored in NODE_3.
+ *
+ * Offsets are relative to the master offset from PFS_CNTL_2.
+ */
+#define R300_US_CODE_ADDR_0 0x4610
+#define R300_US_CODE_ADDR_1 0x4614
+#define R300_US_CODE_ADDR_2 0x4618
+#define R300_US_CODE_ADDR_3 0x461C
+# define R300_ALU_START_SHIFT 0
+# define R300_ALU_START_MASK (63 << 0)
+# define R300_ALU_SIZE_SHIFT 6
+# define R300_ALU_SIZE_MASK (63 << 6)
+# define R300_TEX_START_SHIFT 12
+# define R300_TEX_START_MASK (31 << 12)
+# define R300_TEX_SIZE_SHIFT 17
+# define R300_TEX_SIZE_MASK (31 << 17)
+# define R300_RGBA_OUT (1 << 22)
+# define R300_W_OUT (1 << 23)
+
+/* TEX
+ * As far as I can tell, texture instructions cannot write into output
+ * registers directly. A subsequent ALU instruction is always necessary,
+ * even if it's just MAD o0, r0, 1, 0
+ */
+#define R300_US_TEX_INST_0 0x4620
+# define R300_SRC_ADDR_SHIFT 0
+# define R300_SRC_ADDR_MASK (31 << 0)
+# define R300_DST_ADDR_SHIFT 6
+# define R300_DST_ADDR_MASK (31 << 6)
+# define R300_TEX_ID_SHIFT 11
+# define R300_TEX_ID_MASK (15 << 11)
+# define R300_TEX_INST_SHIFT 15
+# define R300_TEX_OP_NOP 0
+# define R300_TEX_OP_LD 1
+# define R300_TEX_OP_KIL 2
+# define R300_TEX_OP_TXP 3
+# define R300_TEX_OP_TXB 4
+# define R300_TEX_INST_MASK (7 << 15)
+
+/* Output format from the unfied shader */
+#define R300_US_OUT_FMT_0 0x46A4
+# define R300_US_OUT_FMT_C4_8 (0 << 0)
+# define R300_US_OUT_FMT_C4_10 (1 << 0)
+# define R300_US_OUT_FMT_C4_10_GAMMA (2 << 0)
+# define R300_US_OUT_FMT_C_16 (3 << 0)
+# define R300_US_OUT_FMT_C2_16 (4 << 0)
+# define R300_US_OUT_FMT_C4_16 (5 << 0)
+# define R300_US_OUT_FMT_C_16_MPEG (6 << 0)
+# define R300_US_OUT_FMT_C2_16_MPEG (7 << 0)
+# define R300_US_OUT_FMT_C2_4 (8 << 0)
+# define R300_US_OUT_FMT_C_3_3_2 (9 << 0)
+# define R300_US_OUT_FMT_C_6_5_6 (10 << 0)
+# define R300_US_OUT_FMT_C_11_11_10 (11 << 0)
+# define R300_US_OUT_FMT_C_10_11_11 (12 << 0)
+# define R300_US_OUT_FMT_C_2_10_10_10 (13 << 0)
+/* reserved */
+# define R300_US_OUT_FMT_UNUSED (15 << 0)
+# define R300_US_OUT_FMT_C_16_FP (16 << 0)
+# define R300_US_OUT_FMT_C2_16_FP (17 << 0)
+# define R300_US_OUT_FMT_C4_16_FP (18 << 0)
+# define R300_US_OUT_FMT_C_32_FP (19 << 0)
+# define R300_US_OUT_FMT_C2_32_FP (20 << 0)
+# define R300_US_OUT_FMT_C4_32_FP (21 << 0)
+# define R300_C0_SEL_A (0 << 8)
+# define R300_C0_SEL_R (1 << 8)
+# define R300_C0_SEL_G (2 << 8)
+# define R300_C0_SEL_B (3 << 8)
+# define R300_C1_SEL_A (0 << 10)
+# define R300_C1_SEL_R (1 << 10)
+# define R300_C1_SEL_G (2 << 10)
+# define R300_C1_SEL_B (3 << 10)
+# define R300_C2_SEL_A (0 << 12)
+# define R300_C2_SEL_R (1 << 12)
+# define R300_C2_SEL_G (2 << 12)
+# define R300_C2_SEL_B (3 << 12)
+# define R300_C3_SEL_A (0 << 14)
+# define R300_C3_SEL_R (1 << 14)
+# define R300_C3_SEL_G (2 << 14)
+# define R300_C3_SEL_B (3 << 14)
+# define R300_OUT_SIGN(x) ((x) << 16)
+# define R500_ROUND_ADJ (1 << 20)
+
+/* ALU
+ * The ALU instructions register blocks are enumerated according to the order
+ * in which fglrx. I assume there is space for 64 instructions, since
+ * each block has space for a maximum of 64 DWORDs, and this matches reported
+ * native limits.
+ *
+ * The basic functional block seems to be one MAD for each color and alpha,
+ * and an adder that adds all components after the MUL.
+ * - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
+ * - DP4: Use OUTC_DP4, OUTA_DP4
+ * - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
+ * - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
+ * - CMPH: If ARG2 > 0.5, return ARG0, else return ARG1
+ * - CMP: If ARG2 < 0, return ARG1, else return ARG0
+ * - FLR: use FRC+MAD
+ * - XPD: use MAD+MAD
+ * - SGE, SLT: use MAD+CMP
+ * - RSQ: use ABS modifier for argument
+ * - Use OUTC_REPL_ALPHA to write results of an alpha-only operation
+ * (e.g. RCP) into color register
+ * - apparently, there's no quick DST operation
+ * - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
+ * - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
+ * - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
+ *
+ * Operand selection
+ * First stage selects three sources from the available registers and
+ * constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
+ * fglrx sorts the three source fields: Registers before constants,
+ * lower indices before higher indices; I do not know whether this is
+ * necessary.
+ *
+ * fglrx fills unused sources with "read constant 0"
+ * According to specs, you cannot select more than two different constants.
+ *
+ * Second stage selects the operands from the sources. This is defined in
+ * INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
+ * zero and one.
+ * Swizzling and negation happens in this stage, as well.
+ *
+ * Important: Color and alpha seem to be mostly separate, i.e. their sources
+ * selection appears to be fully independent (the register storage is probably
+ * physically split into a color and an alpha section).
+ * However (because of the apparent physical split), there is some interaction
+ * WRT swizzling. If, for example, you want to load an R component into an
+ * Alpha operand, this R component is taken from a *color* source, not from
+ * an alpha source. The corresponding register doesn't even have to appear in
+ * the alpha sources list. (I hope this all makes sense to you)
+ *
+ * Destination selection
+ * The destination register index is in FPI1 (color) and FPI3 (alpha)
+ * together with enable bits.
+ * There are separate enable bits for writing into temporary registers
+ * (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_*
+ * /DSTA_OUTPUT). You can write to both at once, or not write at all (the
+ * same index must be used for both).
+ *
+ * Note: There is a special form for LRP
+ * - Argument order is the same as in ARB_fragment_program.
+ * - Operation is MAD
+ * - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
+ * - Set FPI0/FPI2_SPECIAL_LRP
+ * Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD
+ */
+#define R300_US_ALU_RGB_ADDR_0 0x46C0
+# define R300_ALU_SRC0C_SHIFT 0
+# define R300_ALU_SRC0C_MASK (31 << 0)
+# define R300_ALU_SRC0C_CONST (1 << 5)
+# define R300_ALU_SRC1C_SHIFT 6
+# define R300_ALU_SRC1C_MASK (31 << 6)
+# define R300_ALU_SRC1C_CONST (1 << 11)
+# define R300_ALU_SRC2C_SHIFT 12
+# define R300_ALU_SRC2C_MASK (31 << 12)
+# define R300_ALU_SRC2C_CONST (1 << 17)
+# define R300_ALU_SRC_MASK 0x0003ffff
+# define R300_ALU_DSTC_SHIFT 18
+# define R300_ALU_DSTC_MASK (31 << 18)
+# define R300_ALU_DSTC_REG_MASK_SHIFT 23
+# define R300_ALU_DSTC_REG_X (1 << 23)
+# define R300_ALU_DSTC_REG_Y (1 << 24)
+# define R300_ALU_DSTC_REG_Z (1 << 25)
+# define R300_ALU_DSTC_OUTPUT_MASK_SHIFT 26
+# define R300_ALU_DSTC_OUTPUT_X (1 << 26)
+# define R300_ALU_DSTC_OUTPUT_Y (1 << 27)
+# define R300_ALU_DSTC_OUTPUT_Z (1 << 28)
+# define R300_ALU_DSTC_OUTPUT_XYZ (7 << 26)
+# define R300_RGB_ADDR0(x) ((x) << 0)
+# define R300_RGB_ADDR1(x) ((x) << 6)
+# define R300_RGB_ADDR2(x) ((x) << 12)
+
+#define R300_US_ALU_ALPHA_ADDR_0 0x47C0
+# define R300_ALU_SRC0A_SHIFT 0
+# define R300_ALU_SRC0A_MASK (31 << 0)
+# define R300_ALU_SRC0A_CONST (1 << 5)
+# define R300_ALU_SRC1A_SHIFT 6
+# define R300_ALU_SRC1A_MASK (31 << 6)
+# define R300_ALU_SRC1A_CONST (1 << 11)
+# define R300_ALU_SRC2A_SHIFT 12
+# define R300_ALU_SRC2A_MASK (31 << 12)
+# define R300_ALU_SRC2A_CONST (1 << 17)
+# define R300_ALU_SRC_MASK 0x0003ffff
+# define R300_ALU_DSTA_SHIFT 18
+# define R300_ALU_DSTA_MASK (31 << 18)
+# define R300_ALU_DSTA_REG (1 << 23)
+# define R300_ALU_DSTA_OUTPUT (1 << 24)
+# define R300_ALU_DSTA_DEPTH (1 << 27)
+# define R300_ALPHA_ADDR0(x) ((x) << 0)
+# define R300_ALPHA_ADDR1(x) ((x) << 6)
+# define R300_ALPHA_ADDR2(x) ((x) << 12)
+
+#define R300_US_ALU_RGB_INST_0 0x48C0
+# define R300_ALU_ARGC_SRC0C_XYZ 0
+# define R300_ALU_ARGC_SRC0C_XXX 1
+# define R300_ALU_ARGC_SRC0C_YYY 2
+# define R300_ALU_ARGC_SRC0C_ZZZ 3
+# define R300_ALU_ARGC_SRC1C_XYZ 4
+# define R300_ALU_ARGC_SRC1C_XXX 5
+# define R300_ALU_ARGC_SRC1C_YYY 6
+# define R300_ALU_ARGC_SRC1C_ZZZ 7
+# define R300_ALU_ARGC_SRC2C_XYZ 8
+# define R300_ALU_ARGC_SRC2C_XXX 9
+# define R300_ALU_ARGC_SRC2C_YYY 10
+# define R300_ALU_ARGC_SRC2C_ZZZ 11
+# define R300_ALU_ARGC_SRC0A 12
+# define R300_ALU_ARGC_SRC1A 13
+# define R300_ALU_ARGC_SRC2A 14
+# define R300_ALU_ARGC_SRCP_XYZ 15
+# define R300_ALU_ARGC_SRCP_XXX 16
+# define R300_ALU_ARGC_SRCP_YYY 17
+# define R300_ALU_ARGC_SRCP_ZZZ 18
+# define R300_ALU_ARGC_SRCP_WWW 19
+# define R300_ALU_ARGC_ZERO 20
+# define R300_ALU_ARGC_ONE 21
+# define R300_ALU_ARGC_HALF 22
+# define R300_ALU_ARGC_SRC0C_YZX 23
+# define R300_ALU_ARGC_SRC1C_YZX 24
+# define R300_ALU_ARGC_SRC2C_YZX 25
+# define R300_ALU_ARGC_SRC0C_ZXY 26
+# define R300_ALU_ARGC_SRC1C_ZXY 27
+# define R300_ALU_ARGC_SRC2C_ZXY 28
+# define R300_ALU_ARGC_SRC0CA_WZY 29
+# define R300_ALU_ARGC_SRC1CA_WZY 30
+# define R300_ALU_ARGC_SRC2CA_WZY 31
+# define R300_RGB_SWIZA(x) ((x) << 0)
+# define R300_RGB_SWIZB(x) ((x) << 7)
+# define R300_RGB_SWIZC(x) ((x) << 14)
+
+# define R300_ALU_ARG0C_SHIFT 0
+# define R300_ALU_ARG0C_MASK (31 << 0)
+# define R300_ALU_ARG0C_NOP (0 << 5)
+# define R300_ALU_ARG0C_NEG (1 << 5)
+# define R300_ALU_ARG0C_ABS (2 << 5)
+# define R300_ALU_ARG0C_NAB (3 << 5)
+# define R300_ALU_ARG1C_SHIFT 7
+# define R300_ALU_ARG1C_MASK (31 << 7)
+# define R300_ALU_ARG1C_NOP (0 << 12)
+# define R300_ALU_ARG1C_NEG (1 << 12)
+# define R300_ALU_ARG1C_ABS (2 << 12)
+# define R300_ALU_ARG1C_NAB (3 << 12)
+# define R300_ALU_ARG2C_SHIFT 14
+# define R300_ALU_ARG2C_MASK (31 << 14)
+# define R300_ALU_ARG2C_NOP (0 << 19)
+# define R300_ALU_ARG2C_NEG (1 << 19)
+# define R300_ALU_ARG2C_ABS (2 << 19)
+# define R300_ALU_ARG2C_NAB (3 << 19)
+# define R300_ALU_SRCP_1_MINUS_2_SRC0 (0 << 21)
+# define R300_ALU_SRCP_SRC1_MINUS_SRC0 (1 << 21)
+# define R300_ALU_SRCP_SRC1_PLUS_SRC0 (2 << 21)
+# define R300_ALU_SRCP_1_MINUS_SRC0 (3 << 21)
+
+# define R300_ALU_OUTC_MAD (0 << 23)
+# define R300_ALU_OUTC_DP3 (1 << 23)
+# define R300_ALU_OUTC_DP4 (2 << 23)
+# define R300_ALU_OUTC_D2A (3 << 23)
+# define R300_ALU_OUTC_MIN (4 << 23)
+# define R300_ALU_OUTC_MAX (5 << 23)
+# define R300_ALU_OUTC_CMPH (7 << 23)
+# define R300_ALU_OUTC_CMP (8 << 23)
+# define R300_ALU_OUTC_FRC (9 << 23)
+# define R300_ALU_OUTC_REPL_ALPHA (10 << 23)
+
+# define R300_ALU_OUTC_MOD_NOP (0 << 27)
+# define R300_ALU_OUTC_MOD_MUL2 (1 << 27)
+# define R300_ALU_OUTC_MOD_MUL4 (2 << 27)
+# define R300_ALU_OUTC_MOD_MUL8 (3 << 27)
+# define R300_ALU_OUTC_MOD_DIV2 (4 << 27)
+# define R300_ALU_OUTC_MOD_DIV4 (5 << 27)
+# define R300_ALU_OUTC_MOD_DIV8 (6 << 27)
+
+# define R300_ALU_OUTC_CLAMP (1 << 30)
+# define R300_ALU_INSERT_NOP (1 << 31)
+
+#define R300_US_ALU_ALPHA_INST_0 0x49C0
+# define R300_ALU_ARGA_SRC0C_X 0
+# define R300_ALU_ARGA_SRC0C_Y 1
+# define R300_ALU_ARGA_SRC0C_Z 2
+# define R300_ALU_ARGA_SRC1C_X 3
+# define R300_ALU_ARGA_SRC1C_Y 4
+# define R300_ALU_ARGA_SRC1C_Z 5
+# define R300_ALU_ARGA_SRC2C_X 6
+# define R300_ALU_ARGA_SRC2C_Y 7
+# define R300_ALU_ARGA_SRC2C_Z 8
+# define R300_ALU_ARGA_SRC0A 9
+# define R300_ALU_ARGA_SRC1A 10
+# define R300_ALU_ARGA_SRC2A 11
+# define R300_ALU_ARGA_SRCP_X 12
+# define R300_ALU_ARGA_SRCP_Y 13
+# define R300_ALU_ARGA_SRCP_Z 14
+# define R300_ALU_ARGA_SRCP_W 15
+# define R300_ALU_ARGA_ZERO 16
+# define R300_ALU_ARGA_ONE 17
+# define R300_ALU_ARGA_HALF 18
+# define R300_ALPHA_SWIZA(x) ((x) << 0)
+# define R300_ALPHA_SWIZB(x) ((x) << 7)
+# define R300_ALPHA_SWIZC(x) ((x) << 14)
+
+# define R300_ALU_ARG0A_SHIFT 0
+# define R300_ALU_ARG0A_MASK (31 << 0)
+# define R300_ALU_ARG0A_NOP (0 << 5)
+# define R300_ALU_ARG0A_NEG (1 << 5)
+# define R300_ALU_ARG0A_ABS (2 << 5)
+# define R300_ALU_ARG0A_NAB (3 << 5)
+# define R300_ALU_ARG1A_SHIFT 7
+# define R300_ALU_ARG1A_MASK (31 << 7)
+# define R300_ALU_ARG1A_NOP (0 << 12)
+# define R300_ALU_ARG1A_NEG (1 << 12)
+# define R300_ALU_ARG1A_ABS (2 << 12)
+# define R300_ALU_ARG1A_NAB (3 << 12)
+# define R300_ALU_ARG2A_SHIFT 14
+# define R300_ALU_ARG2A_MASK (31 << 14)
+# define R300_ALU_ARG2A_NOP (0 << 19)
+# define R300_ALU_ARG2A_NEG (1 << 19)
+# define R300_ALU_ARG2A_ABS (2 << 19)
+# define R300_ALU_ARG2A_NAB (3 << 19)
+# define R300_ALU_SRCP_1_MINUS_2_SRC0 (0 << 21)
+# define R300_ALU_SRCP_SRC1_MINUS_SRC0 (1 << 21)
+# define R300_ALU_SRCP_SRC1_PLUS_SRC0 (2 << 21)
+# define R300_ALU_SRCP_1_MINUS_SRC0 (3 << 21)
+
+# define R300_ALU_OUTA_MAD (0 << 23)
+# define R300_ALU_OUTA_DP4 (1 << 23)
+# define R300_ALU_OUTA_MIN (2 << 23)
+# define R300_ALU_OUTA_MAX (3 << 23)
+# define R300_ALU_OUTA_CND (5 << 23)
+# define R300_ALU_OUTA_CMP (6 << 23)
+# define R300_ALU_OUTA_FRC (7 << 23)
+# define R300_ALU_OUTA_EX2 (8 << 23)
+# define R300_ALU_OUTA_LG2 (9 << 23)
+# define R300_ALU_OUTA_RCP (10 << 23)
+# define R300_ALU_OUTA_RSQ (11 << 23)
+
+# define R300_ALU_OUTA_MOD_NOP (0 << 27)
+# define R300_ALU_OUTA_MOD_MUL2 (1 << 27)
+# define R300_ALU_OUTA_MOD_MUL4 (2 << 27)
+# define R300_ALU_OUTA_MOD_MUL8 (3 << 27)
+# define R300_ALU_OUTA_MOD_DIV2 (4 << 27)
+# define R300_ALU_OUTA_MOD_DIV4 (5 << 27)
+# define R300_ALU_OUTA_MOD_DIV8 (6 << 27)
+
+# define R300_ALU_OUTA_CLAMP (1 << 30)
+/* END: Fragment program instruction set */
+
+/* Fog: Fog Blending Enable */
+#define R300_FG_FOG_BLEND 0x4bc0
+# define R300_FG_FOG_BLEND_DISABLE (0 << 0)
+# define R300_FG_FOG_BLEND_ENABLE (1 << 0)
+# define R300_FG_FOG_BLEND_FN_LINEAR (0 << 1)
+# define R300_FG_FOG_BLEND_FN_EXP (1 << 1)
+# define R300_FG_FOG_BLEND_FN_EXP2 (2 << 1)
+# define R300_FG_FOG_BLEND_FN_CONSTANT (3 << 1)
+# define R300_FG_FOG_BLEND_FN_MASK (3 << 1)
+
+/* Fog: Red Component of Fog Color */
+#define R300_FG_FOG_COLOR_R 0x4bc8
+/* Fog: Green Component of Fog Color */
+#define R300_FG_FOG_COLOR_G 0x4bcc
+/* Fog: Blue Component of Fog Color */
+#define R300_FG_FOG_COLOR_B 0x4bd0
+# define R300_FG_FOG_COLOR_MASK 0x000003ff
+
+/* Fog: Constant Factor for Fog Blending */
+#define R300_FG_FOG_FACTOR 0x4bc4
+# define FG_FOG_FACTOR_MASK 0x000003ff
+
+/* Fog: Alpha function */
+#define R300_FG_ALPHA_FUNC 0x4bd4
+# define R300_FG_ALPHA_FUNC_VAL_MASK 0x000000ff
+# define R300_FG_ALPHA_FUNC_NEVER (0 << 8)
+# define R300_FG_ALPHA_FUNC_LESS (1 << 8)
+# define R300_FG_ALPHA_FUNC_EQUAL (2 << 8)
+# define R300_FG_ALPHA_FUNC_LE (3 << 8)
+# define R300_FG_ALPHA_FUNC_GREATER (4 << 8)
+# define R300_FG_ALPHA_FUNC_NOTEQUAL (5 << 8)
+# define R300_FG_ALPHA_FUNC_GE (6 << 8)
+# define R300_FG_ALPHA_FUNC_ALWAYS (7 << 8)
+# define R300_ALPHA_TEST_OP_MASK (7 << 8)
+# define R300_FG_ALPHA_FUNC_DISABLE (0 << 11)
+# define R300_FG_ALPHA_FUNC_ENABLE (1 << 11)
+
+# define R500_FG_ALPHA_FUNC_10BIT (0 << 12)
+# define R500_FG_ALPHA_FUNC_8BIT (1 << 12)
+
+# define R300_FG_ALPHA_FUNC_MASK_DISABLE (0 << 16)
+# define R300_FG_ALPHA_FUNC_MASK_ENABLE (1 << 16)
+# define R300_FG_ALPHA_FUNC_CFG_2_OF_4 (0 << 17)
+# define R300_FG_ALPHA_FUNC_CFG_3_OF_6 (1 << 17)
+
+# define R300_FG_ALPHA_FUNC_DITH_DISABLE (0 << 20)
+# define R300_FG_ALPHA_FUNC_DITH_ENABLE (1 << 20)
+
+# define R500_FG_ALPHA_FUNC_OFFSET_DISABLE (0 << 24)
+# define R500_FG_ALPHA_FUNC_OFFSET_ENABLE (1 << 24) /* Not supported in R520 */
+# define R500_FG_ALPHA_FUNC_DISC_ZERO_MASK_DISABLE (0 << 25)
+# define R500_FG_ALPHA_FUNC_DISC_ZERO_MASK_ENABLE (1 << 25)
+
+# define R500_FG_ALPHA_FUNC_FP16_DISABLE (0 << 28)
+# define R500_FG_ALPHA_FUNC_FP16_ENABLE (1 << 28)
+
+
+/* Fog: Where does the depth come from? */
+#define R300_FG_DEPTH_SRC 0x4bd8
+# define R300_FG_DEPTH_SRC_SCAN (0 << 0)
+# define R300_FG_DEPTH_SRC_SHADER (1 << 0)
+
+/* Fog: Alpha Compare Value */
+#define R500_FG_ALPHA_VALUE 0x4be0
+# define R500_FG_ALPHA_VALUE_MASK 0x0000ffff
+
+/* gap */
+
+/* Fragment program parameters in 7.16 floating point */
+#define R300_PFS_PARAM_0_X 0x4C00
+#define R300_PFS_PARAM_0_Y 0x4C04
+#define R300_PFS_PARAM_0_Z 0x4C08
+#define R300_PFS_PARAM_0_W 0x4C0C
+/* last consts */
+#define R300_PFS_PARAM_31_X 0x4DF0
+#define R300_PFS_PARAM_31_Y 0x4DF4
+#define R300_PFS_PARAM_31_Z 0x4DF8
+#define R300_PFS_PARAM_31_W 0x4DFC
+
+/* Unpipelined. */
+#define R300_RB3D_CCTL 0x4e00
+# define R300_RB3D_CCTL_NUM_MULTIWRITES_1_BUFFER (0 << 5)
+# define R300_RB3D_CCTL_NUM_MULTIWRITES_2_BUFFERS (1 << 5)
+# define R300_RB3D_CCTL_NUM_MULTIWRITES_3_BUFFERS (2 << 5)
+# define R300_RB3D_CCTL_NUM_MULTIWRITES_4_BUFFERS (3 << 5)
+# define R300_RB3D_CCTL_CLRCMP_FLIPE_DISABLE (0 << 7)
+# define R300_RB3D_CCTL_CLRCMP_FLIPE_ENABLE (1 << 7)
+# define R300_RB3D_CCTL_AA_COMPRESSION_DISABLE (0 << 9)
+# define R300_RB3D_CCTL_AA_COMPRESSION_ENABLE (1 << 9)
+# define R300_RB3D_CCTL_CMASK_DISABLE (0 << 10)
+# define R300_RB3D_CCTL_CMASK_ENABLE (1 << 10)
+/* reserved */
+# define R300_RB3D_CCTL_INDEPENDENT_COLOR_CHANNEL_MASK_DISABLE (0 << 12)
+# define R300_RB3D_CCTL_INDEPENDENT_COLOR_CHANNEL_MASK_ENABLE (1 << 12)
+# define R300_RB3D_CCTL_WRITE_COMPRESSION_ENABLE (0 << 13)
+# define R300_RB3D_CCTL_WRITE_COMPRESSION_DISABLE (1 << 13)
+# define R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_DISABLE (0 << 14)
+# define R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE (1 << 14)
+
+
+/* Notes:
+ * - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in
+ * the application
+ * - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND
+ * are set to the same
+ * function (both registers are always set up completely in any case)
+ * - Most blend flags are simply copied from R200 and not tested yet
+ */
+#define R300_RB3D_CBLEND 0x4E04
+#define R300_RB3D_ABLEND 0x4E08
+/* the following only appear in CBLEND */
+# define R300_ALPHA_BLEND_ENABLE (1 << 0)
+# define R300_SEPARATE_ALPHA_ENABLE (1 << 1)
+# define R300_READ_ENABLE (1 << 2)
+# define R300_DISCARD_SRC_PIXELS_DIS (0 << 3)
+# define R300_DISCARD_SRC_PIXELS_SRC_ALPHA_0 (1 << 3)
+# define R300_DISCARD_SRC_PIXELS_SRC_COLOR_0 (2 << 3)
+# define R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_0 (3 << 3)
+# define R300_DISCARD_SRC_PIXELS_SRC_ALPHA_1 (4 << 3)
+# define R300_DISCARD_SRC_PIXELS_SRC_COLOR_1 (5 << 3)
+# define R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_1 (6 << 3)
+
+/* the following are shared between CBLEND and ABLEND */
+# define R300_FCN_MASK (3 << 12)
+# define R300_COMB_FCN_ADD_CLAMP (0 << 12)
+# define R300_COMB_FCN_ADD_NOCLAMP (1 << 12)
+# define R300_COMB_FCN_SUB_CLAMP (2 << 12)
+# define R300_COMB_FCN_SUB_NOCLAMP (3 << 12)
+# define R300_COMB_FCN_MIN (4 << 12)
+# define R300_COMB_FCN_MAX (5 << 12)
+# define R300_COMB_FCN_RSUB_CLAMP (6 << 12)
+# define R300_COMB_FCN_RSUB_NOCLAMP (7 << 12)
+# define R300_BLEND_GL_ZERO (32)
+# define R300_BLEND_GL_ONE (33)
+# define R300_BLEND_GL_SRC_COLOR (34)
+# define R300_BLEND_GL_ONE_MINUS_SRC_COLOR (35)
+# define R300_BLEND_GL_DST_COLOR (36)
+# define R300_BLEND_GL_ONE_MINUS_DST_COLOR (37)
+# define R300_BLEND_GL_SRC_ALPHA (38)
+# define R300_BLEND_GL_ONE_MINUS_SRC_ALPHA (39)
+# define R300_BLEND_GL_DST_ALPHA (40)
+# define R300_BLEND_GL_ONE_MINUS_DST_ALPHA (41)
+# define R300_BLEND_GL_SRC_ALPHA_SATURATE (42)
+# define R300_BLEND_GL_CONST_COLOR (43)
+# define R300_BLEND_GL_ONE_MINUS_CONST_COLOR (44)
+# define R300_BLEND_GL_CONST_ALPHA (45)
+# define R300_BLEND_GL_ONE_MINUS_CONST_ALPHA (46)
+# define R300_BLEND_MASK (63)
+# define R300_SRC_BLEND_SHIFT (16)
+# define R300_DST_BLEND_SHIFT (24)
+
+/* Constant color used by the blender. Pipelined through the blender.
+ * Note: For R520, this field is ignored, use RB3D_CONSTANT_COLOR_GB__BLUE,
+ * RB3D_CONSTANT_COLOR_GB__GREEN, etc. instead.
+ */
+#define R300_RB3D_BLEND_COLOR 0x4E10
+
+
+/* 3D Color Channel Mask. If all the channels used in the current color format
+ * are disabled, then the cb will discard all the incoming quads. Pipelined
+ * through the blender.
+ */
+#define RB3D_COLOR_CHANNEL_MASK 0x4E0C
+# define RB3D_COLOR_CHANNEL_MASK_BLUE_MASK0 (1 << 0)
+# define RB3D_COLOR_CHANNEL_MASK_GREEN_MASK0 (1 << 1)
+# define RB3D_COLOR_CHANNEL_MASK_RED_MASK0 (1 << 2)
+# define RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK0 (1 << 3)
+# define RB3D_COLOR_CHANNEL_MASK_BLUE_MASK1 (1 << 4)
+# define RB3D_COLOR_CHANNEL_MASK_GREEN_MASK1 (1 << 5)
+# define RB3D_COLOR_CHANNEL_MASK_RED_MASK1 (1 << 6)
+# define RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK1 (1 << 7)
+# define RB3D_COLOR_CHANNEL_MASK_BLUE_MASK2 (1 << 8)
+# define RB3D_COLOR_CHANNEL_MASK_GREEN_MASK2 (1 << 9)
+# define RB3D_COLOR_CHANNEL_MASK_RED_MASK2 (1 << 10)
+# define RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK2 (1 << 11)
+# define RB3D_COLOR_CHANNEL_MASK_BLUE_MASK3 (1 << 12)
+# define RB3D_COLOR_CHANNEL_MASK_GREEN_MASK3 (1 << 13)
+# define RB3D_COLOR_CHANNEL_MASK_RED_MASK3 (1 << 14)
+# define RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK3 (1 << 15)
+
+/* Clear color that is used when the color mask is set to 00. Unpipelined.
+ * Program this register with a 32-bit value in ARGB8888 or ARGB2101010
+ * formats, ignoring the fields.
+ */
+#define RB3D_COLOR_CLEAR_VALUE 0x4e14
+
+/* gap */
+
+/* Color Compare Color. Stalls the 2d/3d datapath until it is idle. */
+#define RB3D_CLRCMP_CLR 0x4e20
+
+/* Color Compare Mask. Stalls the 2d/3d datapath until it is idle. */
+#define RB3D_CLRCMP_MSK 0x4e24
+
+/* Color Buffer Address Offset of multibuffer 0. Unpipelined. */
+#define R300_RB3D_COLOROFFSET0 0x4E28
+# define R300_COLOROFFSET_MASK 0xFFFFFFE0
+/* Color Buffer Address Offset of multibuffer 1. Unpipelined. */
+#define R300_RB3D_COLOROFFSET1 0x4E2C
+/* Color Buffer Address Offset of multibuffer 2. Unpipelined. */
+#define R300_RB3D_COLOROFFSET2 0x4E30
+/* Color Buffer Address Offset of multibuffer 3. Unpipelined. */
+#define R300_RB3D_COLOROFFSET3 0x4E34
+
+/* Color buffer format and tiling control for all the multibuffers and the
+ * pitch of multibuffer 0 to 3. Unpipelined. The cache must be empty before any
+ * of the registers are changed.
+ *
+ * Bit 16: Larger tiles
+ * Bit 17: 4x2 tiles
+ * Bit 18: Extremely weird tile like, but some pixels duplicated?
+ */
+#define R300_RB3D_COLORPITCH0 0x4E38
+# define R300_COLORPITCH_MASK 0x00003FFE
+# define R300_COLOR_TILE_DISABLE (0 << 16)
+# define R300_COLOR_TILE_ENABLE (1 << 16)
+# define R300_COLOR_MICROTILE_DISABLE (0 << 17)
+# define R300_COLOR_MICROTILE_ENABLE (1 << 17)
+# define R300_COLOR_MICROTILE_ENABLE_SQUARE (2 << 17) /* Only available in 16-bit */
+# define R300_COLOR_ENDIAN_NO_SWAP (0 << 19)
+# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 19)
+# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 19)
+# define R300_COLOR_ENDIAN_HALF_DWORD_SWAP (3 << 19)
+# define R500_COLOR_FORMAT_ARGB10101010 (0 << 21)
+# define R500_COLOR_FORMAT_UV1010 (1 << 21)
+# define R500_COLOR_FORMAT_CI8 (2 << 21) /* 2D only */
+# define R300_COLOR_FORMAT_ARGB1555 (3 << 21)
+# define R300_COLOR_FORMAT_RGB565 (4 << 21)
+# define R500_COLOR_FORMAT_ARGB2101010 (5 << 21)
+# define R300_COLOR_FORMAT_ARGB8888 (6 << 21)
+# define R300_COLOR_FORMAT_ARGB32323232 (7 << 21)
+/* reserved */
+# define R300_COLOR_FORMAT_I8 (9 << 21)
+# define R300_COLOR_FORMAT_ARGB16161616 (10 << 21)
+# define R300_COLOR_FORMAT_VYUY (11 << 21)
+# define R300_COLOR_FORMAT_YVYU (12 << 21)
+# define R300_COLOR_FORMAT_UV88 (13 << 21)
+# define R500_COLOR_FORMAT_I10 (14 << 21)
+# define R300_COLOR_FORMAT_ARGB4444 (15 << 21)
+#define R300_RB3D_COLORPITCH1 0x4E3C
+#define R300_RB3D_COLORPITCH2 0x4E40
+#define R300_RB3D_COLORPITCH3 0x4E44
+
+/* gap */
+
+/* Destination Color Buffer Cache Control/Status. If the cb is in e2 mode, then
+ * a flush or free will not occur upon a write to this register, but a sync
+ * will be immediately sent if one is requested. If both DC_FLUSH and DC_FREE
+ * are zero but DC_FINISH is one, then a sync will be sent immediately -- the
+ * cb will not wait for all the previous operations to complete before sending
+ * the sync. Unpipelined except when DC_FINISH and DC_FREE are both set to
+ * zero.
+ *
+ * Set to 0A before 3D operations, set to 02 afterwards.
+ */
+#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_NO_EFFECT (0 << 0)
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_NO_EFFECT_1 (1 << 0)
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D (2 << 0)
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D_1 (3 << 0)
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_NO_EFFECT (0 << 2)
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_NO_EFFECT_1 (1 << 2)
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS (2 << 2)
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS_1 (3 << 2)
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FINISH_NO_SIGNAL (0 << 4)
+# define R300_RB3D_DSTCACHE_CTLSTAT_DC_FINISH_SIGNAL (1 << 4)
+
+#define R300_RB3D_DITHER_CTL 0x4E50
+# define R300_RB3D_DITHER_CTL_DITHER_MODE_TRUNCATE (0 << 0)
+# define R300_RB3D_DITHER_CTL_DITHER_MODE_ROUND (1 << 0)
+# define R300_RB3D_DITHER_CTL_DITHER_MODE_LUT (2 << 0)
+/* reserved */
+# define R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_TRUNCATE (0 << 2)
+# define R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_ROUND (1 << 2)
+# define R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT (2 << 2)
+/* reserved */
+
+/* Resolve buffer destination address. The cache must be empty before changing
+ * this register if the cb is in resolve mode. Unpipelined
+ */
+#define R300_RB3D_AARESOLVE_OFFSET 0x4e80
+# define R300_RB3D_AARESOLVE_OFFSET_SHIFT 5
+# define R300_RB3D_AARESOLVE_OFFSET_MASK 0xffffffe0 /* At least according to the calculations of Christoph Brill */
+
+/* Resolve Buffer Pitch and Tiling Control. The cache must be empty before
+ * changing this register if the cb is in resolve mode. Unpipelined
+ */
+#define R300_RB3D_AARESOLVE_PITCH 0x4e84
+# define R300_RB3D_AARESOLVE_PITCH_SHIFT 1
+# define R300_RB3D_AARESOLVE_PITCH_MASK 0x00003ffe /* At least according to the calculations of Christoph Brill */
+
+/* Resolve Buffer Control. Unpipelined */
+#define R300_RB3D_AARESOLVE_CTL 0x4e88
+# define R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_NORMAL (0 << 0)
+# define R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE (1 << 0)
+# define R300_RB3D_AARESOLVE_CTL_AARESOLVE_GAMMA_10 (0 << 1)
+# define R300_RB3D_AARESOLVE_CTL_AARESOLVE_GAMMA_22 (1 << 1)
+# define R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_SAMPLE0 (0 << 2)
+# define R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE (1 << 2)
+
+
+/* Discard src pixels less than or equal to threshold. */
+#define R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD 0x4ea0
+/* Discard src pixels greater than or equal to threshold. */
+#define R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD 0x4ea4
+# define R500_RB3D_DISCARD_SRC_PIXEL_THRESHOLD_BLUE_SHIFT 0
+# define R500_RB3D_DISCARD_SRC_PIXEL_THRESHOLD_BLUE_MASK 0x000000ff
+# define R500_RB3D_DISCARD_SRC_PIXEL_THRESHOLD_GREEN_SHIFT 8
+# define R500_RB3D_DISCARD_SRC_PIXEL_THRESHOLD_GREEN_MASK 0x0000ff00
+# define R500_RB3D_DISCARD_SRC_PIXEL_THRESHOLD_RED_SHIFT 16
+# define R500_RB3D_DISCARD_SRC_PIXEL_THRESHOLD_RED_MASK 0x00ff0000
+# define R500_RB3D_DISCARD_SRC_PIXEL_THRESHOLD_ALPHA_SHIFT 24
+# define R500_RB3D_DISCARD_SRC_PIXEL_THRESHOLD_ALPHA_MASK 0xff000000
+
+/* 3D ROP Control. Stalls the 2d/3d datapath until it is idle. */
+#define R300_RB3D_ROPCNTL 0x4e18
+# define R300_RB3D_ROPCNTL_ROP_ENABLE 0x00000004
+# define R300_RB3D_ROPCNTL_ROP_MASK (15 << 8)
+# define R300_RB3D_ROPCNTL_ROP_SHIFT 8
+
+/* Color Compare Flip. Stalls the 2d/3d datapath until it is idle. */
+#define R300_RB3D_CLRCMP_FLIPE 0x4e1c
+
+/* Sets the fifo sizes */
+#define R500_RB3D_FIFO_SIZE 0x4ef4
+# define R500_RB3D_FIFO_SIZE_OP_FIFO_SIZE_FULL (0 << 0)
+# define R500_RB3D_FIFO_SIZE_OP_FIFO_SIZE_HALF (1 << 0)
+# define R500_RB3D_FIFO_SIZE_OP_FIFO_SIZE_QUATER (2 << 0)
+# define R500_RB3D_FIFO_SIZE_OP_FIFO_SIZE_EIGTHS (3 << 0)
+
+/* Constant color used by the blender. Pipelined through the blender. */
+#define R500_RB3D_CONSTANT_COLOR_AR 0x4ef8
+# define R500_RB3D_CONSTANT_COLOR_AR_RED_MASK 0x0000ffff
+# define R500_RB3D_CONSTANT_COLOR_AR_RED_SHIFT 0
+# define R500_RB3D_CONSTANT_COLOR_AR_ALPHA_MASK 0xffff0000
+# define R500_RB3D_CONSTANT_COLOR_AR_ALPHA_SHIFT 16
+
+/* Constant color used by the blender. Pipelined through the blender. */
+#define R500_RB3D_CONSTANT_COLOR_GB 0x4efc
+# define R500_RB3D_CONSTANT_COLOR_AR_BLUE_MASK 0x0000ffff
+# define R500_RB3D_CONSTANT_COLOR_AR_BLUE_SHIFT 0
+# define R500_RB3D_CONSTANT_COLOR_AR_GREEN_MASK 0xffff0000
+# define R500_RB3D_CONSTANT_COLOR_AR_GREEN_SHIFT 16
+
+/* gap */
+/* There seems to be no "write only" setting, so use Z-test = ALWAYS
+ * for this.
+ * Bit (1<<8) is the "test" bit. so plain write is 6 - vd
+ */
+#define R300_ZB_CNTL 0x4F00
+# define R300_STENCIL_ENABLE (1 << 0)
+# define R300_Z_ENABLE (1 << 1)
+# define R300_Z_WRITE_ENABLE (1 << 2)
+# define R300_Z_SIGNED_COMPARE (1 << 3)
+# define R300_STENCIL_FRONT_BACK (1 << 4)
+
+#define R300_ZB_ZSTENCILCNTL 0x4f04
+ /* functions */
+# define R300_ZS_NEVER 0
+# define R300_ZS_LESS 1
+# define R300_ZS_LEQUAL 2
+# define R300_ZS_EQUAL 3
+# define R300_ZS_GEQUAL 4
+# define R300_ZS_GREATER 5
+# define R300_ZS_NOTEQUAL 6
+# define R300_ZS_ALWAYS 7
+# define R300_ZS_MASK 7
+ /* operations */
+# define R300_ZS_KEEP 0
+# define R300_ZS_ZERO 1
+# define R300_ZS_REPLACE 2
+# define R300_ZS_INCR 3
+# define R300_ZS_DECR 4
+# define R300_ZS_INVERT 5
+# define R300_ZS_INCR_WRAP 6
+# define R300_ZS_DECR_WRAP 7
+# define R300_Z_FUNC_SHIFT 0
+ /* front and back refer to operations done for front
+ and back faces, i.e. separate stencil function support */
+# define R300_S_FRONT_FUNC_SHIFT 3
+# define R300_S_FRONT_SFAIL_OP_SHIFT 6
+# define R300_S_FRONT_ZPASS_OP_SHIFT 9
+# define R300_S_FRONT_ZFAIL_OP_SHIFT 12
+# define R300_S_BACK_FUNC_SHIFT 15
+# define R300_S_BACK_SFAIL_OP_SHIFT 18
+# define R300_S_BACK_ZPASS_OP_SHIFT 21
+# define R300_S_BACK_ZFAIL_OP_SHIFT 24
+
+#define R300_ZB_STENCILREFMASK 0x4f08
+# define R300_STENCILREF_SHIFT 0
+# define R300_STENCILREF_MASK 0x000000ff
+# define R300_STENCILMASK_SHIFT 8
+# define R300_STENCILMASK_MASK 0x0000ff00
+# define R300_STENCILWRITEMASK_SHIFT 16
+# define R300_STENCILWRITEMASK_MASK 0x00ff0000
+
+/* gap */
+
+#define R300_ZB_FORMAT 0x4f10
+# define R300_DEPTHFORMAT_16BIT_INT_Z (0 << 0)
+# define R300_DEPTHFORMAT_16BIT_13E3 (1 << 0)
+# define R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL (2 << 0)
+/* reserved up to (15 << 0) */
+# define R300_INVERT_13E3_LEADING_ONES (0 << 4)
+# define R300_INVERT_13E3_LEADING_ZEROS (1 << 4)
+
+#define R300_ZB_ZTOP 0x4F14
+# define R300_ZTOP_DISABLE (0 << 0)
+# define R300_ZTOP_ENABLE (1 << 0)
+
+/* gap */
+
+#define R300_ZB_ZCACHE_CTLSTAT 0x4f18
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_NO_EFFECT (0 << 0)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE (1 << 0)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_NO_EFFECT (0 << 1)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE (1 << 1)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_IDLE (0 << 31)
+# define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_BUSY (1 << 31)
+
+#define R300_ZB_BW_CNTL 0x4f1c
+# define R300_HIZ_DISABLE (0 << 0)
+# define R300_HIZ_ENABLE (1 << 0)
+# define R300_HIZ_MIN (0 << 1)
+# define R300_HIZ_MAX (1 << 1)
+# define R300_FAST_FILL_DISABLE (0 << 2)
+# define R300_FAST_FILL_ENABLE (1 << 2)
+# define R300_RD_COMP_DISABLE (0 << 3)
+# define R300_RD_COMP_ENABLE (1 << 3)
+# define R300_WR_COMP_DISABLE (0 << 4)
+# define R300_WR_COMP_ENABLE (1 << 4)
+# define R300_ZB_CB_CLEAR_RMW (0 << 5)
+# define R300_ZB_CB_CLEAR_CACHE_LINEAR (1 << 5)
+# define R300_FORCE_COMPRESSED_STENCIL_VALUE_DISABLE (0 << 6)
+# define R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE (1 << 6)
+
+# define R500_ZEQUAL_OPTIMIZE_ENABLE (0 << 7)
+# define R500_ZEQUAL_OPTIMIZE_DISABLE (1 << 7)
+# define R500_SEQUAL_OPTIMIZE_ENABLE (0 << 8)
+# define R500_SEQUAL_OPTIMIZE_DISABLE (1 << 8)
+
+# define R500_BMASK_ENABLE (0 << 10)
+# define R500_BMASK_DISABLE (1 << 10)
+# define R500_HIZ_EQUAL_REJECT_DISABLE (0 << 11)
+# define R500_HIZ_EQUAL_REJECT_ENABLE (1 << 11)
+# define R500_HIZ_FP_EXP_BITS_DISABLE (0 << 12)
+# define R500_HIZ_FP_EXP_BITS_1 (1 << 12)
+# define R500_HIZ_FP_EXP_BITS_2 (2 << 12)
+# define R500_HIZ_FP_EXP_BITS_3 (3 << 12)
+# define R500_HIZ_FP_EXP_BITS_4 (4 << 12)
+# define R500_HIZ_FP_EXP_BITS_5 (5 << 12)
+# define R500_HIZ_FP_INVERT_LEADING_ONES (0 << 15)
+# define R500_HIZ_FP_INVERT_LEADING_ZEROS (1 << 15)
+# define R500_TILE_OVERWRITE_RECOMPRESSION_ENABLE (0 << 16)
+# define R500_TILE_OVERWRITE_RECOMPRESSION_DISABLE (1 << 16)
+# define R500_CONTIGUOUS_6XAA_SAMPLES_ENABLE (0 << 17)
+# define R500_CONTIGUOUS_6XAA_SAMPLES_DISABLE (1 << 17)
+# define R500_PEQ_PACKING_DISABLE (0 << 18)
+# define R500_PEQ_PACKING_ENABLE (1 << 18)
+# define R500_COVERED_PTR_MASKING_DISABLE (0 << 18)
+# define R500_COVERED_PTR_MASKING_ENABLE (1 << 18)
+
+
+/* gap */
+
+/* Z Buffer Address Offset.
+ * Bits 31 to 5 are used for aligned Z buffer address offset for macro tiles.
+ */
+#define R300_ZB_DEPTHOFFSET 0x4f20
+
+/* Z Buffer Pitch and Endian Control */
+#define R300_ZB_DEPTHPITCH 0x4f24
+# define R300_DEPTHPITCH_MASK 0x00003FFC
+# define R300_DEPTHMACROTILE_DISABLE (0 << 16)
+# define R300_DEPTHMACROTILE_ENABLE (1 << 16)
+# define R300_DEPTHMICROTILE_LINEAR (0 << 17)
+# define R300_DEPTHMICROTILE_TILED (1 << 17)
+# define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17)
+# define R300_DEPTHENDIAN_NO_SWAP (0 << 18)
+# define R300_DEPTHENDIAN_WORD_SWAP (1 << 18)
+# define R300_DEPTHENDIAN_DWORD_SWAP (2 << 18)
+# define R300_DEPTHENDIAN_HALF_DWORD_SWAP (3 << 18)
+
+/* Z Buffer Clear Value */
+#define R300_ZB_DEPTHCLEARVALUE 0x4f28
+
+/* Hierarchical Z Memory Offset */
+#define R300_ZB_HIZ_OFFSET 0x4f44
+
+/* Hierarchical Z Write Index */
+#define R300_ZB_HIZ_WRINDEX 0x4f48
+
+/* Hierarchical Z Data */
+#define R300_ZB_HIZ_DWORD 0x4f4c
+
+/* Hierarchical Z Read Index */
+#define R300_ZB_HIZ_RDINDEX 0x4f50
+
+/* Hierarchical Z Pitch */
+#define R300_ZB_HIZ_PITCH 0x4f54
+
+/* Z Buffer Z Pass Counter Data */
+#define R300_ZB_ZPASS_DATA 0x4f58
+
+/* Z Buffer Z Pass Counter Address */
+#define R300_ZB_ZPASS_ADDR 0x4f5c
+
+/* Depth buffer X and Y coordinate offset */
+#define R300_ZB_DEPTHXY_OFFSET 0x4f60
+# define R300_DEPTHX_OFFSET_SHIFT 1
+# define R300_DEPTHX_OFFSET_MASK 0x000007FE
+# define R300_DEPTHY_OFFSET_SHIFT 17
+# define R300_DEPTHY_OFFSET_MASK 0x07FE0000
+
+/* Sets the fifo sizes */
+#define R500_ZB_FIFO_SIZE 0x4fd0
+# define R500_OP_FIFO_SIZE_FULL (0 << 0)
+# define R500_OP_FIFO_SIZE_HALF (1 << 0)
+# define R500_OP_FIFO_SIZE_QUATER (2 << 0)
+# define R500_OP_FIFO_SIZE_EIGTHS (4 << 0)
+
+/* Stencil Reference Value and Mask for backfacing quads */
+/* R300_ZB_STENCILREFMASK handles front face */
+#define R500_ZB_STENCILREFMASK_BF 0x4fd4
+# define R500_STENCILREF_SHIFT 0
+# define R500_STENCILREF_MASK 0x000000ff
+# define R500_STENCILMASK_SHIFT 8
+# define R500_STENCILMASK_MASK 0x0000ff00
+# define R500_STENCILWRITEMASK_SHIFT 16
+# define R500_STENCILWRITEMASK_MASK 0x00ff0000
+
+/**
+ * \defgroup R3XX_R5XX_PROGRAMMABLE_VERTEX_SHADER_DESCRIPTION R3XX-R5XX PROGRAMMABLE VERTEX SHADER DESCRIPTION
+ *
+ * The PVS_DST_MATH_INST is used to identify whether the instruction is a Vector
+ * Engine instruction or a Math Engine instruction.
+ */
+
+/*\{*/
+
+enum {
+ /* R3XX */
+ VECTOR_NO_OP = 0,
+ VE_DOT_PRODUCT = 1,
+ VE_MULTIPLY = 2,
+ VE_ADD = 3,
+ VE_MULTIPLY_ADD = 4,
+ VE_DISTANCE_VECTOR = 5,
+ VE_FRACTION = 6,
+ VE_MAXIMUM = 7,
+ VE_MINIMUM = 8,
+ VE_SET_GREATER_THAN_EQUAL = 9,
+ VE_SET_LESS_THAN = 10,
+ VE_MULTIPLYX2_ADD = 11,
+ VE_MULTIPLY_CLAMP = 12,
+ VE_FLT2FIX_DX = 13,
+ VE_FLT2FIX_DX_RND = 14,
+ /* R5XX */
+ VE_PRED_SET_EQ_PUSH = 15,
+ VE_PRED_SET_GT_PUSH = 16,
+ VE_PRED_SET_GTE_PUSH = 17,
+ VE_PRED_SET_NEQ_PUSH = 18,
+ VE_COND_WRITE_EQ = 19,
+ VE_COND_WRITE_GT = 20,
+ VE_COND_WRITE_GTE = 21,
+ VE_COND_WRITE_NEQ = 22,
+ VE_COND_MUX_EQ = 23,
+ VE_COND_MUX_GT = 24,
+ VE_COND_MUX_GTE = 25,
+ VE_SET_GREATER_THAN = 26,
+ VE_SET_EQUAL = 27,
+ VE_SET_NOT_EQUAL = 28,
+};
+
+enum {
+ /* R3XX */
+ MATH_NO_OP = 0,
+ ME_EXP_BASE2_DX = 1,
+ ME_LOG_BASE2_DX = 2,
+ ME_EXP_BASEE_FF = 3,
+ ME_LIGHT_COEFF_DX = 4,
+ ME_POWER_FUNC_FF = 5,
+ ME_RECIP_DX = 6,
+ ME_RECIP_FF = 7,
+ ME_RECIP_SQRT_DX = 8,
+ ME_RECIP_SQRT_FF = 9,
+ ME_MULTIPLY = 10,
+ ME_EXP_BASE2_FULL_DX = 11,
+ ME_LOG_BASE2_FULL_DX = 12,
+ ME_POWER_FUNC_FF_CLAMP_B = 13,
+ ME_POWER_FUNC_FF_CLAMP_B1 = 14,
+ ME_POWER_FUNC_FF_CLAMP_01 = 15,
+ ME_SIN = 16,
+ ME_COS = 17,
+ /* R5XX */
+ ME_LOG_BASE2_IEEE = 18,
+ ME_RECIP_IEEE = 19,
+ ME_RECIP_SQRT_IEEE = 20,
+ ME_PRED_SET_EQ = 21,
+ ME_PRED_SET_GT = 22,
+ ME_PRED_SET_GTE = 23,
+ ME_PRED_SET_NEQ = 24,
+ ME_PRED_SET_CLR = 25,
+ ME_PRED_SET_INV = 26,
+ ME_PRED_SET_POP = 27,
+ ME_PRED_SET_RESTORE = 28,
+};
+
+enum {
+ /* R3XX */
+ PVS_MACRO_OP_2CLK_MADD = 0,
+ PVS_MACRO_OP_2CLK_M2X_ADD = 1,
+};
+
+enum {
+ PVS_SRC_REG_TEMPORARY = 0, /* Intermediate Storage */
+ PVS_SRC_REG_INPUT = 1, /* Input Vertex Storage */
+ PVS_SRC_REG_CONSTANT = 2, /* Constant State Storage */
+ PVS_SRC_REG_ALT_TEMPORARY = 3, /* Alternate Intermediate Storage */
+};
+
+enum {
+ PVS_DST_REG_TEMPORARY = 0, /* Intermediate Storage */
+ PVS_DST_REG_A0 = 1, /* Address Register Storage */
+ PVS_DST_REG_OUT = 2, /* Output Memory. Used for all outputs */
+ PVS_DST_REG_OUT_REPL_X = 3, /* Output Memory & Replicate X to all channels */
+ PVS_DST_REG_ALT_TEMPORARY = 4, /* Alternate Intermediate Storage */
+ PVS_DST_REG_INPUT = 5, /* Output Memory & Replicate X to all channels */
+};
+
+enum {
+ PVS_SRC_SELECT_X = 0, /* Select X Component */
+ PVS_SRC_SELECT_Y = 1, /* Select Y Component */
+ PVS_SRC_SELECT_Z = 2, /* Select Z Component */
+ PVS_SRC_SELECT_W = 3, /* Select W Component */
+ PVS_SRC_SELECT_FORCE_0 = 4, /* Force Component to 0.0 */
+ PVS_SRC_SELECT_FORCE_1 = 5, /* Force Component to 1.0 */
+};
+
+/* PVS Opcode & Destination Operand Description */
+
+enum {
+ PVS_DST_OPCODE_MASK = 0x3f,
+ PVS_DST_OPCODE_SHIFT = 0,
+ PVS_DST_MATH_INST_MASK = 0x1,
+ PVS_DST_MATH_INST_SHIFT = 6,
+ PVS_DST_MACRO_INST_MASK = 0x1,
+ PVS_DST_MACRO_INST_SHIFT = 7,
+ PVS_DST_REG_TYPE_MASK = 0xf,
+ PVS_DST_REG_TYPE_SHIFT = 8,
+ PVS_DST_ADDR_MODE_1_MASK = 0x1,
+ PVS_DST_ADDR_MODE_1_SHIFT = 12,
+ PVS_DST_OFFSET_MASK = 0x7f,
+ PVS_DST_OFFSET_SHIFT = 13,
+ PVS_DST_WE_X_MASK = 0x1,
+ PVS_DST_WE_X_SHIFT = 20,
+ PVS_DST_WE_Y_MASK = 0x1,
+ PVS_DST_WE_Y_SHIFT = 21,
+ PVS_DST_WE_Z_MASK = 0x1,
+ PVS_DST_WE_Z_SHIFT = 22,
+ PVS_DST_WE_W_MASK = 0x1,
+ PVS_DST_WE_W_SHIFT = 23,
+ PVS_DST_VE_SAT_MASK = 0x1,
+ PVS_DST_VE_SAT_SHIFT = 24,
+ PVS_DST_ME_SAT_MASK = 0x1,
+ PVS_DST_ME_SAT_SHIFT = 25,
+ PVS_DST_PRED_ENABLE_MASK = 0x1,
+ PVS_DST_PRED_ENABLE_SHIFT = 26,
+ PVS_DST_PRED_SENSE_MASK = 0x1,
+ PVS_DST_PRED_SENSE_SHIFT = 27,
+ PVS_DST_DUAL_MATH_OP_MASK = 0x3,
+ PVS_DST_DUAL_MATH_OP_SHIFT = 27,
+ PVS_DST_ADDR_SEL_MASK = 0x3,
+ PVS_DST_ADDR_SEL_SHIFT = 29,
+ PVS_DST_ADDR_MODE_0_MASK = 0x1,
+ PVS_DST_ADDR_MODE_0_SHIFT = 31,
+};
+
+/* PVS Source Operand Description */
+
+enum {
+ PVS_SRC_REG_TYPE_MASK = 0x3,
+ PVS_SRC_REG_TYPE_SHIFT = 0,
+ SPARE_0_MASK = 0x1,
+ SPARE_0_SHIFT = 2,
+ PVS_SRC_ABS_XYZW_MASK = 0x1,
+ PVS_SRC_ABS_XYZW_SHIFT = 3,
+ PVS_SRC_ADDR_MODE_0_MASK = 0x1,
+ PVS_SRC_ADDR_MODE_0_SHIFT = 4,
+ PVS_SRC_OFFSET_MASK = 0xff,
+ PVS_SRC_OFFSET_SHIFT = 5,
+ PVS_SRC_SWIZZLE_X_MASK = 0x7,
+ PVS_SRC_SWIZZLE_X_SHIFT = 13,
+ PVS_SRC_SWIZZLE_Y_MASK = 0x7,
+ PVS_SRC_SWIZZLE_Y_SHIFT = 16,
+ PVS_SRC_SWIZZLE_Z_MASK = 0x7,
+ PVS_SRC_SWIZZLE_Z_SHIFT = 19,
+ PVS_SRC_SWIZZLE_W_MASK = 0x7,
+ PVS_SRC_SWIZZLE_W_SHIFT = 22,
+ PVS_SRC_MODIFIER_X_MASK = 0x1,
+ PVS_SRC_MODIFIER_X_SHIFT = 25,
+ PVS_SRC_MODIFIER_Y_MASK = 0x1,
+ PVS_SRC_MODIFIER_Y_SHIFT = 26,
+ PVS_SRC_MODIFIER_Z_MASK = 0x1,
+ PVS_SRC_MODIFIER_Z_SHIFT = 27,
+ PVS_SRC_MODIFIER_W_MASK = 0x1,
+ PVS_SRC_MODIFIER_W_SHIFT = 28,
+ PVS_SRC_ADDR_SEL_MASK = 0x3,
+ PVS_SRC_ADDR_SEL_SHIFT = 29,
+ PVS_SRC_ADDR_MODE_1_MASK = 0x0,
+ PVS_SRC_ADDR_MODE_1_SHIFT = 32,
+};
+
+/*\}*/
+
+/* BEGIN: Packet 3 commands */
+
+/* A primitive emission dword. */
+#define R300_PRIM_TYPE_NONE (0 << 0)
+#define R300_PRIM_TYPE_POINT (1 << 0)
+#define R300_PRIM_TYPE_LINE (2 << 0)
+#define R300_PRIM_TYPE_LINE_STRIP (3 << 0)
+#define R300_PRIM_TYPE_TRI_LIST (4 << 0)
+#define R300_PRIM_TYPE_TRI_FAN (5 << 0)
+#define R300_PRIM_TYPE_TRI_STRIP (6 << 0)
+#define R300_PRIM_TYPE_TRI_TYPE2 (7 << 0)
+#define R300_PRIM_TYPE_RECT_LIST (8 << 0)
+#define R300_PRIM_TYPE_3VRT_POINT_LIST (9 << 0)
+#define R300_PRIM_TYPE_3VRT_LINE_LIST (10 << 0)
+ /* GUESS (based on r200) */
+#define R300_PRIM_TYPE_POINT_SPRITES (11 << 0)
+#define R300_PRIM_TYPE_LINE_LOOP (12 << 0)
+#define R300_PRIM_TYPE_QUADS (13 << 0)
+#define R300_PRIM_TYPE_QUAD_STRIP (14 << 0)
+#define R300_PRIM_TYPE_POLYGON (15 << 0)
+#define R300_PRIM_TYPE_MASK 0xF
+#define R300_PRIM_WALK_IND (1 << 4)
+#define R300_PRIM_WALK_LIST (2 << 4)
+#define R300_PRIM_WALK_RING (3 << 4)
+#define R300_PRIM_WALK_MASK (3 << 4)
+ /* GUESS (based on r200) */
+#define R300_PRIM_COLOR_ORDER_BGRA (0 << 6)
+#define R300_PRIM_COLOR_ORDER_RGBA (1 << 6)
+#define R300_PRIM_NUM_VERTICES_SHIFT 16
+#define R300_PRIM_NUM_VERTICES_MASK 0xffff
+
+
+
+/*
+ * The R500 unified shader (US) registers come in banks of 512 each, one
+ * for each instruction slot in the shader. You can't touch them directly.
+ * R500_US_VECTOR_INDEX() sets the base instruction to modify; successive
+ * writes to R500_GA_US_VECTOR_DATA autoincrement the index after the
+ * instruction is fully specified.
+ */
+#define R500_US_ALU_ALPHA_INST_0 0xa800
+# define R500_ALPHA_OP_MAD 0
+# define R500_ALPHA_OP_DP 1
+# define R500_ALPHA_OP_MIN 2
+# define R500_ALPHA_OP_MAX 3
+/* #define R500_ALPHA_OP_RESERVED 4 */
+# define R500_ALPHA_OP_CND 5
+# define R500_ALPHA_OP_CMP 6
+# define R500_ALPHA_OP_FRC 7
+# define R500_ALPHA_OP_EX2 8
+# define R500_ALPHA_OP_LN2 9
+# define R500_ALPHA_OP_RCP 10
+# define R500_ALPHA_OP_RSQ 11
+# define R500_ALPHA_OP_SIN 12
+# define R500_ALPHA_OP_COS 13
+# define R500_ALPHA_OP_MDH 14
+# define R500_ALPHA_OP_MDV 15
+# define R500_ALPHA_ADDRD(x) ((x) << 4)
+# define R500_ALPHA_ADDRD_REL (1 << 11)
+# define R500_ALPHA_SEL_A_SHIFT 12
+# define R500_ALPHA_SEL_A_SRC0 (0 << 12)
+# define R500_ALPHA_SEL_A_SRC1 (1 << 12)
+# define R500_ALPHA_SEL_A_SRC2 (2 << 12)
+# define R500_ALPHA_SEL_A_SRCP (3 << 12)
+# define R500_ALPHA_SWIZ_A_R (0 << 14)
+# define R500_ALPHA_SWIZ_A_G (1 << 14)
+# define R500_ALPHA_SWIZ_A_B (2 << 14)
+# define R500_ALPHA_SWIZ_A_A (3 << 14)
+# define R500_ALPHA_SWIZ_A_0 (4 << 14)
+# define R500_ALPHA_SWIZ_A_HALF (5 << 14)
+# define R500_ALPHA_SWIZ_A_1 (6 << 14)
+/* #define R500_ALPHA_SWIZ_A_UNUSED (7 << 14) */
+# define R500_ALPHA_MOD_A_NOP (0 << 17)
+# define R500_ALPHA_MOD_A_NEG (1 << 17)
+# define R500_ALPHA_MOD_A_ABS (2 << 17)
+# define R500_ALPHA_MOD_A_NAB (3 << 17)
+# define R500_ALPHA_SEL_B_SHIFT 19
+# define R500_ALPHA_SEL_B_SRC0 (0 << 19)
+# define R500_ALPHA_SEL_B_SRC1 (1 << 19)
+# define R500_ALPHA_SEL_B_SRC2 (2 << 19)
+# define R500_ALPHA_SEL_B_SRCP (3 << 19)
+# define R500_ALPHA_SWIZ_B_R (0 << 21)
+# define R500_ALPHA_SWIZ_B_G (1 << 21)
+# define R500_ALPHA_SWIZ_B_B (2 << 21)
+# define R500_ALPHA_SWIZ_B_A (3 << 21)
+# define R500_ALPHA_SWIZ_B_0 (4 << 21)
+# define R500_ALPHA_SWIZ_B_HALF (5 << 21)
+# define R500_ALPHA_SWIZ_B_1 (6 << 21)
+/* #define R500_ALPHA_SWIZ_B_UNUSED (7 << 21) */
+# define R500_ALPHA_MOD_B_NOP (0 << 24)
+# define R500_ALPHA_MOD_B_NEG (1 << 24)
+# define R500_ALPHA_MOD_B_ABS (2 << 24)
+# define R500_ALPHA_MOD_B_NAB (3 << 24)
+# define R500_ALPHA_OMOD_IDENTITY (0 << 26)
+# define R500_ALPHA_OMOD_MUL_2 (1 << 26)
+# define R500_ALPHA_OMOD_MUL_4 (2 << 26)
+# define R500_ALPHA_OMOD_MUL_8 (3 << 26)
+# define R500_ALPHA_OMOD_DIV_2 (4 << 26)
+# define R500_ALPHA_OMOD_DIV_4 (5 << 26)
+# define R500_ALPHA_OMOD_DIV_8 (6 << 26)
+# define R500_ALPHA_OMOD_DISABLE (7 << 26)
+# define R500_ALPHA_TARGET(x) ((x) << 29)
+# define R500_ALPHA_W_OMASK (1 << 31)
+#define R500_US_ALU_ALPHA_ADDR_0 0x9800
+# define R500_ALPHA_ADDR0(x) ((x) << 0)
+# define R500_ALPHA_ADDR0_CONST (1 << 8)
+# define R500_ALPHA_ADDR0_REL (1 << 9)
+# define R500_ALPHA_ADDR1(x) ((x) << 10)
+# define R500_ALPHA_ADDR1_CONST (1 << 18)
+# define R500_ALPHA_ADDR1_REL (1 << 19)
+# define R500_ALPHA_ADDR2(x) ((x) << 20)
+# define R500_ALPHA_ADDR2_CONST (1 << 28)
+# define R500_ALPHA_ADDR2_REL (1 << 29)
+# define R500_ALPHA_SRCP_OP_1_MINUS_2A0 (0 << 30)
+# define R500_ALPHA_SRCP_OP_A1_MINUS_A0 (1 << 30)
+# define R500_ALPHA_SRCP_OP_A1_PLUS_A0 (2 << 30)
+# define R500_ALPHA_SRCP_OP_1_MINUS_A0 (3 << 30)
+#define R500_US_ALU_RGBA_INST_0 0xb000
+# define R500_ALU_RGBA_OP_MAD (0 << 0)
+# define R500_ALU_RGBA_OP_DP3 (1 << 0)
+# define R500_ALU_RGBA_OP_DP4 (2 << 0)
+# define R500_ALU_RGBA_OP_D2A (3 << 0)
+# define R500_ALU_RGBA_OP_MIN (4 << 0)
+# define R500_ALU_RGBA_OP_MAX (5 << 0)
+/* #define R500_ALU_RGBA_OP_RESERVED (6 << 0) */
+# define R500_ALU_RGBA_OP_CND (7 << 0)
+# define R500_ALU_RGBA_OP_CMP (8 << 0)
+# define R500_ALU_RGBA_OP_FRC (9 << 0)
+# define R500_ALU_RGBA_OP_SOP (10 << 0)
+# define R500_ALU_RGBA_OP_MDH (11 << 0)
+# define R500_ALU_RGBA_OP_MDV (12 << 0)
+# define R500_ALU_RGBA_ADDRD(x) ((x) << 4)
+# define R500_ALU_RGBA_ADDRD_REL (1 << 11)
+# define R500_ALU_RGBA_SEL_C_SHIFT 12
+# define R500_ALU_RGBA_SEL_C_SRC0 (0 << 12)
+# define R500_ALU_RGBA_SEL_C_SRC1 (1 << 12)
+# define R500_ALU_RGBA_SEL_C_SRC2 (2 << 12)
+# define R500_ALU_RGBA_SEL_C_SRCP (3 << 12)
+# define R500_ALU_RGBA_R_SWIZ_R (0 << 14)
+# define R500_ALU_RGBA_R_SWIZ_G (1 << 14)
+# define R500_ALU_RGBA_R_SWIZ_B (2 << 14)
+# define R500_ALU_RGBA_R_SWIZ_A (3 << 14)
+# define R500_ALU_RGBA_R_SWIZ_0 (4 << 14)
+# define R500_ALU_RGBA_R_SWIZ_HALF (5 << 14)
+# define R500_ALU_RGBA_R_SWIZ_1 (6 << 14)
+/* #define R500_ALU_RGBA_R_SWIZ_UNUSED (7 << 14) */
+# define R500_ALU_RGBA_G_SWIZ_R (0 << 17)
+# define R500_ALU_RGBA_G_SWIZ_G (1 << 17)
+# define R500_ALU_RGBA_G_SWIZ_B (2 << 17)
+# define R500_ALU_RGBA_G_SWIZ_A (3 << 17)
+# define R500_ALU_RGBA_G_SWIZ_0 (4 << 17)
+# define R500_ALU_RGBA_G_SWIZ_HALF (5 << 17)
+# define R500_ALU_RGBA_G_SWIZ_1 (6 << 17)
+/* #define R500_ALU_RGBA_G_SWIZ_UNUSED (7 << 17) */
+# define R500_ALU_RGBA_B_SWIZ_R (0 << 20)
+# define R500_ALU_RGBA_B_SWIZ_G (1 << 20)
+# define R500_ALU_RGBA_B_SWIZ_B (2 << 20)
+# define R500_ALU_RGBA_B_SWIZ_A (3 << 20)
+# define R500_ALU_RGBA_B_SWIZ_0 (4 << 20)
+# define R500_ALU_RGBA_B_SWIZ_HALF (5 << 20)
+# define R500_ALU_RGBA_B_SWIZ_1 (6 << 20)
+/* #define R500_ALU_RGBA_B_SWIZ_UNUSED (7 << 20) */
+# define R500_ALU_RGBA_MOD_C_NOP (0 << 23)
+# define R500_ALU_RGBA_MOD_C_NEG (1 << 23)
+# define R500_ALU_RGBA_MOD_C_ABS (2 << 23)
+# define R500_ALU_RGBA_MOD_C_NAB (3 << 23)
+# define R500_ALU_RGBA_ALPHA_SEL_C_SHIFT 25
+# define R500_ALU_RGBA_ALPHA_SEL_C_SRC0 (0 << 25)
+# define R500_ALU_RGBA_ALPHA_SEL_C_SRC1 (1 << 25)
+# define R500_ALU_RGBA_ALPHA_SEL_C_SRC2 (2 << 25)
+# define R500_ALU_RGBA_ALPHA_SEL_C_SRCP (3 << 25)
+# define R500_ALU_RGBA_A_SWIZ_R (0 << 27)
+# define R500_ALU_RGBA_A_SWIZ_G (1 << 27)
+# define R500_ALU_RGBA_A_SWIZ_B (2 << 27)
+# define R500_ALU_RGBA_A_SWIZ_A (3 << 27)
+# define R500_ALU_RGBA_A_SWIZ_0 (4 << 27)
+# define R500_ALU_RGBA_A_SWIZ_HALF (5 << 27)
+# define R500_ALU_RGBA_A_SWIZ_1 (6 << 27)
+/* #define R500_ALU_RGBA_A_SWIZ_UNUSED (7 << 27) */
+# define R500_ALU_RGBA_ALPHA_MOD_C_NOP (0 << 30)
+# define R500_ALU_RGBA_ALPHA_MOD_C_NEG (1 << 30)
+# define R500_ALU_RGBA_ALPHA_MOD_C_ABS (2 << 30)
+# define R500_ALU_RGBA_ALPHA_MOD_C_NAB (3 << 30)
+#define R500_US_ALU_RGB_INST_0 0xa000
+# define R500_ALU_RGB_SEL_A_SHIFT 0
+# define R500_ALU_RGB_SEL_A_SRC0 (0 << 0)
+# define R500_ALU_RGB_SEL_A_SRC1 (1 << 0)
+# define R500_ALU_RGB_SEL_A_SRC2 (2 << 0)
+# define R500_ALU_RGB_SEL_A_SRCP (3 << 0)
+# define R500_ALU_RGB_R_SWIZ_A_R (0 << 2)
+# define R500_ALU_RGB_R_SWIZ_A_G (1 << 2)
+# define R500_ALU_RGB_R_SWIZ_A_B (2 << 2)
+# define R500_ALU_RGB_R_SWIZ_A_A (3 << 2)
+# define R500_ALU_RGB_R_SWIZ_A_0 (4 << 2)
+# define R500_ALU_RGB_R_SWIZ_A_HALF (5 << 2)
+# define R500_ALU_RGB_R_SWIZ_A_1 (6 << 2)
+/* #define R500_ALU_RGB_R_SWIZ_A_UNUSED (7 << 2) */
+# define R500_ALU_RGB_G_SWIZ_A_R (0 << 5)
+# define R500_ALU_RGB_G_SWIZ_A_G (1 << 5)
+# define R500_ALU_RGB_G_SWIZ_A_B (2 << 5)
+# define R500_ALU_RGB_G_SWIZ_A_A (3 << 5)
+# define R500_ALU_RGB_G_SWIZ_A_0 (4 << 5)
+# define R500_ALU_RGB_G_SWIZ_A_HALF (5 << 5)
+# define R500_ALU_RGB_G_SWIZ_A_1 (6 << 5)
+/* #define R500_ALU_RGB_G_SWIZ_A_UNUSED (7 << 5) */
+# define R500_ALU_RGB_B_SWIZ_A_R (0 << 8)
+# define R500_ALU_RGB_B_SWIZ_A_G (1 << 8)
+# define R500_ALU_RGB_B_SWIZ_A_B (2 << 8)
+# define R500_ALU_RGB_B_SWIZ_A_A (3 << 8)
+# define R500_ALU_RGB_B_SWIZ_A_0 (4 << 8)
+# define R500_ALU_RGB_B_SWIZ_A_HALF (5 << 8)
+# define R500_ALU_RGB_B_SWIZ_A_1 (6 << 8)
+/* #define R500_ALU_RGB_B_SWIZ_A_UNUSED (7 << 8) */
+# define R500_ALU_RGB_MOD_A_NOP (0 << 11)
+# define R500_ALU_RGB_MOD_A_NEG (1 << 11)
+# define R500_ALU_RGB_MOD_A_ABS (2 << 11)
+# define R500_ALU_RGB_MOD_A_NAB (3 << 11)
+# define R500_ALU_RGB_SEL_B_SHIFT 13
+# define R500_ALU_RGB_SEL_B_SRC0 (0 << 13)
+# define R500_ALU_RGB_SEL_B_SRC1 (1 << 13)
+# define R500_ALU_RGB_SEL_B_SRC2 (2 << 13)
+# define R500_ALU_RGB_SEL_B_SRCP (3 << 13)
+# define R500_ALU_RGB_R_SWIZ_B_R (0 << 15)
+# define R500_ALU_RGB_R_SWIZ_B_G (1 << 15)
+# define R500_ALU_RGB_R_SWIZ_B_B (2 << 15)
+# define R500_ALU_RGB_R_SWIZ_B_A (3 << 15)
+# define R500_ALU_RGB_R_SWIZ_B_0 (4 << 15)
+# define R500_ALU_RGB_R_SWIZ_B_HALF (5 << 15)
+# define R500_ALU_RGB_R_SWIZ_B_1 (6 << 15)
+/* #define R500_ALU_RGB_R_SWIZ_B_UNUSED (7 << 15) */
+# define R500_ALU_RGB_G_SWIZ_B_R (0 << 18)
+# define R500_ALU_RGB_G_SWIZ_B_G (1 << 18)
+# define R500_ALU_RGB_G_SWIZ_B_B (2 << 18)
+# define R500_ALU_RGB_G_SWIZ_B_A (3 << 18)
+# define R500_ALU_RGB_G_SWIZ_B_0 (4 << 18)
+# define R500_ALU_RGB_G_SWIZ_B_HALF (5 << 18)
+# define R500_ALU_RGB_G_SWIZ_B_1 (6 << 18)
+/* #define R500_ALU_RGB_G_SWIZ_B_UNUSED (7 << 18) */
+# define R500_ALU_RGB_B_SWIZ_B_R (0 << 21)
+# define R500_ALU_RGB_B_SWIZ_B_G (1 << 21)
+# define R500_ALU_RGB_B_SWIZ_B_B (2 << 21)
+# define R500_ALU_RGB_B_SWIZ_B_A (3 << 21)
+# define R500_ALU_RGB_B_SWIZ_B_0 (4 << 21)
+# define R500_ALU_RGB_B_SWIZ_B_HALF (5 << 21)
+# define R500_ALU_RGB_B_SWIZ_B_1 (6 << 21)
+/* #define R500_ALU_RGB_B_SWIZ_B_UNUSED (7 << 21) */
+# define R500_ALU_RGB_MOD_B_NOP (0 << 24)
+# define R500_ALU_RGB_MOD_B_NEG (1 << 24)
+# define R500_ALU_RGB_MOD_B_ABS (2 << 24)
+# define R500_ALU_RGB_MOD_B_NAB (3 << 24)
+# define R500_ALU_RGB_OMOD_IDENTITY (0 << 26)
+# define R500_ALU_RGB_OMOD_MUL_2 (1 << 26)
+# define R500_ALU_RGB_OMOD_MUL_4 (2 << 26)
+# define R500_ALU_RGB_OMOD_MUL_8 (3 << 26)
+# define R500_ALU_RGB_OMOD_DIV_2 (4 << 26)
+# define R500_ALU_RGB_OMOD_DIV_4 (5 << 26)
+# define R500_ALU_RGB_OMOD_DIV_8 (6 << 26)
+# define R500_ALU_RGB_OMOD_DISABLE (7 << 26)
+# define R500_ALU_RGB_TARGET(x) ((x) << 29)
+# define R500_ALU_RGB_WMASK (1 << 31)
+#define R500_US_ALU_RGB_ADDR_0 0x9000
+# define R500_RGB_ADDR0(x) ((x) << 0)
+# define R500_RGB_ADDR0_CONST (1 << 8)
+# define R500_RGB_ADDR0_REL (1 << 9)
+# define R500_RGB_ADDR1(x) ((x) << 10)
+# define R500_RGB_ADDR1_CONST (1 << 18)
+# define R500_RGB_ADDR1_REL (1 << 19)
+# define R500_RGB_ADDR2(x) ((x) << 20)
+# define R500_RGB_ADDR2_CONST (1 << 28)
+# define R500_RGB_ADDR2_REL (1 << 29)
+# define R500_RGB_SRCP_OP_1_MINUS_2RGB0 (0 << 30)
+# define R500_RGB_SRCP_OP_RGB1_MINUS_RGB0 (1 << 30)
+# define R500_RGB_SRCP_OP_RGB1_PLUS_RGB0 (2 << 30)
+# define R500_RGB_SRCP_OP_1_MINUS_RGB0 (3 << 30)
+#define R500_US_CMN_INST_0 0xb800
+# define R500_INST_TYPE_MASK (3 << 0)
+# define R500_INST_TYPE_ALU (0 << 0)
+# define R500_INST_TYPE_OUT (1 << 0)
+# define R500_INST_TYPE_FC (2 << 0)
+# define R500_INST_TYPE_TEX (3 << 0)
+# define R500_INST_TEX_SEM_WAIT (1 << 2)
+# define R500_INST_RGB_PRED_SEL_NONE (0 << 3)
+# define R500_INST_RGB_PRED_SEL_RGBA (1 << 3)
+# define R500_INST_RGB_PRED_SEL_RRRR (2 << 3)
+# define R500_INST_RGB_PRED_SEL_GGGG (3 << 3)
+# define R500_INST_RGB_PRED_SEL_BBBB (4 << 3)
+# define R500_INST_RGB_PRED_SEL_AAAA (5 << 3)
+# define R500_INST_RGB_PRED_INV (1 << 6)
+# define R500_INST_WRITE_INACTIVE (1 << 7)
+# define R500_INST_LAST (1 << 8)
+# define R500_INST_NOP (1 << 9)
+# define R500_INST_ALU_WAIT (1 << 10)
+# define R500_INST_RGB_WMASK_R (1 << 11)
+# define R500_INST_RGB_WMASK_G (1 << 12)
+# define R500_INST_RGB_WMASK_B (1 << 13)
+# define R500_INST_RGB_WMASK_RGB (7 << 11)
+# define R500_INST_ALPHA_WMASK (1 << 14)
+# define R500_INST_RGB_OMASK_R (1 << 15)
+# define R500_INST_RGB_OMASK_G (1 << 16)
+# define R500_INST_RGB_OMASK_B (1 << 17)
+# define R500_INST_RGB_OMASK_RGB (7 << 15)
+# define R500_INST_ALPHA_OMASK (1 << 18)
+# define R500_INST_RGB_CLAMP (1 << 19)
+# define R500_INST_ALPHA_CLAMP (1 << 20)
+# define R500_INST_ALU_RESULT_SEL (1 << 21)
+# define R500_INST_ALPHA_PRED_INV (1 << 22)
+# define R500_INST_ALU_RESULT_OP_EQ (0 << 23)
+# define R500_INST_ALU_RESULT_OP_LT (1 << 23)
+# define R500_INST_ALU_RESULT_OP_GE (2 << 23)
+# define R500_INST_ALU_RESULT_OP_NE (3 << 23)
+# define R500_INST_ALPHA_PRED_SEL_NONE (0 << 25)
+# define R500_INST_ALPHA_PRED_SEL_RGBA (1 << 25)
+# define R500_INST_ALPHA_PRED_SEL_RRRR (2 << 25)
+# define R500_INST_ALPHA_PRED_SEL_GGGG (3 << 25)
+# define R500_INST_ALPHA_PRED_SEL_BBBB (4 << 25)
+# define R500_INST_ALPHA_PRED_SEL_AAAA (5 << 25)
+/* XXX next four are kind of guessed */
+# define R500_INST_STAT_WE_R (1 << 28)
+# define R500_INST_STAT_WE_G (1 << 29)
+# define R500_INST_STAT_WE_B (1 << 30)
+# define R500_INST_STAT_WE_A (1 << 31)
+
+/* note that these are 8 bit lengths, despite the offsets, at least for R500 */
+#define R500_US_CODE_ADDR 0x4630
+# define R500_US_CODE_START_ADDR(x) ((x) << 0)
+# define R500_US_CODE_END_ADDR(x) ((x) << 16)
+#define R500_US_CODE_OFFSET 0x4638
+# define R500_US_CODE_OFFSET_ADDR(x) ((x) << 0)
+#define R500_US_CODE_RANGE 0x4634
+# define R500_US_CODE_RANGE_ADDR(x) ((x) << 0)
+# define R500_US_CODE_RANGE_SIZE(x) ((x) << 16)
+#define R500_US_CONFIG 0x4600
+# define R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO (1 << 1)
+#define R500_US_FC_ADDR_0 0xa000
+# define R500_FC_BOOL_ADDR(x) ((x) << 0)
+# define R500_FC_INT_ADDR(x) ((x) << 8)
+# define R500_FC_JUMP_ADDR(x) ((x) << 16)
+# define R500_FC_JUMP_GLOBAL (1 << 31)
+#define R500_US_FC_BOOL_CONST 0x4620
+# define R500_FC_KBOOL(x) (x)
+#define R500_US_FC_CTRL 0x4624
+# define R500_FC_TEST_EN (1 << 30)
+# define R500_FC_FULL_FC_EN (1 << 31)
+#define R500_US_FC_INST_0 0x9800
+# define R500_FC_OP_JUMP (0 << 0)
+# define R500_FC_OP_LOOP (1 << 0)
+# define R500_FC_OP_ENDLOOP (2 << 0)
+# define R500_FC_OP_REP (3 << 0)
+# define R500_FC_OP_ENDREP (4 << 0)
+# define R500_FC_OP_BREAKLOOP (5 << 0)
+# define R500_FC_OP_BREAKREP (6 << 0)
+# define R500_FC_OP_CONTINUE (7 << 0)
+# define R500_FC_B_ELSE (1 << 4)
+# define R500_FC_JUMP_ANY (1 << 5)
+# define R500_FC_A_OP_NONE (0 << 6)
+# define R500_FC_A_OP_POP (1 << 6)
+# define R500_FC_A_OP_PUSH (2 << 6)
+# define R500_FC_JUMP_FUNC(x) ((x) << 8)
+# define R500_FC_B_POP_CNT(x) ((x) << 16)
+# define R500_FC_B_OP0_NONE (0 << 24)
+# define R500_FC_B_OP0_DECR (1 << 24)
+# define R500_FC_B_OP0_INCR (2 << 24)
+# define R500_FC_B_OP1_DECR (0 << 26)
+# define R500_FC_B_OP1_NONE (1 << 26)
+# define R500_FC_B_OP1_INCR (2 << 26)
+# define R500_FC_IGNORE_UNCOVERED (1 << 28)
+#define R500_US_FC_INT_CONST_0 0x4c00
+# define R500_FC_INT_CONST_KR(x) ((x) << 0)
+# define R500_FC_INT_CONST_KG(x) ((x) << 8)
+# define R500_FC_INT_CONST_KB(x) ((x) << 16)
+/* _0 through _15 */
+#define R500_US_FORMAT0_0 0x4640
+# define R500_FORMAT_TXWIDTH(x) ((x) << 0)
+# define R500_FORMAT_TXHEIGHT(x) ((x) << 11)
+# define R500_FORMAT_TXDEPTH(x) ((x) << 22)
+#define R500_US_PIXSIZE 0x4604
+# define R500_PIX_SIZE(x) (x)
+#define R500_US_TEX_ADDR_0 0x9800
+# define R500_TEX_SRC_ADDR(x) ((x) << 0)
+# define R500_TEX_SRC_ADDR_REL (1 << 7)
+# define R500_TEX_SRC_S_SWIZ_R (0 << 8)
+# define R500_TEX_SRC_S_SWIZ_G (1 << 8)
+# define R500_TEX_SRC_S_SWIZ_B (2 << 8)
+# define R500_TEX_SRC_S_SWIZ_A (3 << 8)
+# define R500_TEX_SRC_T_SWIZ_R (0 << 10)
+# define R500_TEX_SRC_T_SWIZ_G (1 << 10)
+# define R500_TEX_SRC_T_SWIZ_B (2 << 10)
+# define R500_TEX_SRC_T_SWIZ_A (3 << 10)
+# define R500_TEX_SRC_R_SWIZ_R (0 << 12)
+# define R500_TEX_SRC_R_SWIZ_G (1 << 12)
+# define R500_TEX_SRC_R_SWIZ_B (2 << 12)
+# define R500_TEX_SRC_R_SWIZ_A (3 << 12)
+# define R500_TEX_SRC_Q_SWIZ_R (0 << 14)
+# define R500_TEX_SRC_Q_SWIZ_G (1 << 14)
+# define R500_TEX_SRC_Q_SWIZ_B (2 << 14)
+# define R500_TEX_SRC_Q_SWIZ_A (3 << 14)
+# define R500_TEX_DST_ADDR(x) ((x) << 16)
+# define R500_TEX_DST_ADDR_REL (1 << 23)
+# define R500_TEX_DST_R_SWIZ_R (0 << 24)
+# define R500_TEX_DST_R_SWIZ_G (1 << 24)
+# define R500_TEX_DST_R_SWIZ_B (2 << 24)
+# define R500_TEX_DST_R_SWIZ_A (3 << 24)
+# define R500_TEX_DST_G_SWIZ_R (0 << 26)
+# define R500_TEX_DST_G_SWIZ_G (1 << 26)
+# define R500_TEX_DST_G_SWIZ_B (2 << 26)
+# define R500_TEX_DST_G_SWIZ_A (3 << 26)
+# define R500_TEX_DST_B_SWIZ_R (0 << 28)
+# define R500_TEX_DST_B_SWIZ_G (1 << 28)
+# define R500_TEX_DST_B_SWIZ_B (2 << 28)
+# define R500_TEX_DST_B_SWIZ_A (3 << 28)
+# define R500_TEX_DST_A_SWIZ_R (0 << 30)
+# define R500_TEX_DST_A_SWIZ_G (1 << 30)
+# define R500_TEX_DST_A_SWIZ_B (2 << 30)
+# define R500_TEX_DST_A_SWIZ_A (3 << 30)
+#define R500_US_TEX_ADDR_DXDY_0 0xa000
+# define R500_DX_ADDR(x) ((x) << 0)
+# define R500_DX_ADDR_REL (1 << 7)
+# define R500_DX_S_SWIZ_R (0 << 8)
+# define R500_DX_S_SWIZ_G (1 << 8)
+# define R500_DX_S_SWIZ_B (2 << 8)
+# define R500_DX_S_SWIZ_A (3 << 8)
+# define R500_DX_T_SWIZ_R (0 << 10)
+# define R500_DX_T_SWIZ_G (1 << 10)
+# define R500_DX_T_SWIZ_B (2 << 10)
+# define R500_DX_T_SWIZ_A (3 << 10)
+# define R500_DX_R_SWIZ_R (0 << 12)
+# define R500_DX_R_SWIZ_G (1 << 12)
+# define R500_DX_R_SWIZ_B (2 << 12)
+# define R500_DX_R_SWIZ_A (3 << 12)
+# define R500_DX_Q_SWIZ_R (0 << 14)
+# define R500_DX_Q_SWIZ_G (1 << 14)
+# define R500_DX_Q_SWIZ_B (2 << 14)
+# define R500_DX_Q_SWIZ_A (3 << 14)
+# define R500_DY_ADDR(x) ((x) << 16)
+# define R500_DY_ADDR_REL (1 << 17)
+# define R500_DY_S_SWIZ_R (0 << 24)
+# define R500_DY_S_SWIZ_G (1 << 24)
+# define R500_DY_S_SWIZ_B (2 << 24)
+# define R500_DY_S_SWIZ_A (3 << 24)
+# define R500_DY_T_SWIZ_R (0 << 26)
+# define R500_DY_T_SWIZ_G (1 << 26)
+# define R500_DY_T_SWIZ_B (2 << 26)
+# define R500_DY_T_SWIZ_A (3 << 26)
+# define R500_DY_R_SWIZ_R (0 << 28)
+# define R500_DY_R_SWIZ_G (1 << 28)
+# define R500_DY_R_SWIZ_B (2 << 28)
+# define R500_DY_R_SWIZ_A (3 << 28)
+# define R500_DY_Q_SWIZ_R (0 << 30)
+# define R500_DY_Q_SWIZ_G (1 << 30)
+# define R500_DY_Q_SWIZ_B (2 << 30)
+# define R500_DY_Q_SWIZ_A (3 << 30)
+#define R500_US_TEX_INST_0 0x9000
+# define R500_TEX_ID(x) ((x) << 16)
+# define R500_TEX_INST_NOP (0 << 22)
+# define R500_TEX_INST_LD (1 << 22)
+# define R500_TEX_INST_TEXKILL (2 << 22)
+# define R500_TEX_INST_PROJ (3 << 22)
+# define R500_TEX_INST_LODBIAS (4 << 22)
+# define R500_TEX_INST_LOD (5 << 22)
+# define R500_TEX_INST_DXDY (6 << 22)
+# define R500_TEX_SEM_ACQUIRE (1 << 25)
+# define R500_TEX_IGNORE_UNCOVERED (1 << 26)
+# define R500_TEX_UNSCALED (1 << 27)
+#define R300_US_W_FMT 0x46b4
+# define R300_W_FMT_W0 (0 << 0)
+# define R300_W_FMT_W24 (1 << 0)
+# define R300_W_FMT_W24FP (2 << 0)
+# define R300_W_SRC_US (0 << 2)
+# define R300_W_SRC_RAS (1 << 2)
+
+
+/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
+ * Two parameter dwords:
+ * 0. VAP_VTX_FMT: The first parameter is not written to hardware
+ * 1. VAP_VF_CTL: The second parameter is a standard primitive emission dword.
+ */
+#define R300_PACKET3_3D_DRAW_VBUF 0x00002800
+
+/* Draw a primitive from immediate vertices in this packet
+ * Up to 16382 dwords:
+ * 0. VAP_VTX_FMT: The first parameter is not written to hardware
+ * 1. VAP_VF_CTL: The second parameter is a standard primitive emission dword.
+ * 2 to end: Up to 16380 dwords of vertex data.
+ */
+#define R300_PACKET3_3D_DRAW_IMMD 0x00002900
+
+/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR and
+ * immediate vertices in this packet
+ * Up to 16382 dwords:
+ * 0. VAP_VTX_FMT: The first parameter is not written to hardware
+ * 1. VAP_VF_CTL: The second parameter is a standard primitive emission dword.
+ * 2 to end: Up to 16380 dwords of vertex data.
+ */
+#define R300_PACKET3_3D_DRAW_INDX 0x00002A00
+
+
+/* Specify the full set of vertex arrays as (address, stride).
+ * The first parameter is the number of vertex arrays specified.
+ * The rest of the command is a variable length list of blocks, where
+ * each block is three dwords long and specifies two arrays.
+ * The first dword of a block is split into two words, the lower significant
+ * word refers to the first array, the more significant word to the second
+ * array in the block.
+ * The low byte of each word contains the size of an array entry in dwords,
+ * the high byte contains the stride of the array.
+ * The second dword of a block contains the pointer to the first array,
+ * the third dword of a block contains the pointer to the second array.
+ * Note that if the total number of arrays is odd, the third dword of
+ * the last block is omitted.
+ */
+#define R300_PACKET3_3D_LOAD_VBPNTR 0x00002F00
+
+#define R300_PACKET3_INDX_BUFFER 0x00003300
+# define R300_INDX_BUFFER_DST_SHIFT 0
+# define R300_INDX_BUFFER_SKIP_SHIFT 16
+# define R300_INDX_BUFFER_ONE_REG_WR (1<<31)
+
+/* Same as R300_PACKET3_3D_DRAW_VBUF but without VAP_VTX_FMT */
+#define R300_PACKET3_3D_DRAW_VBUF_2 0x00003400
+/* Same as R300_PACKET3_3D_DRAW_IMMD but without VAP_VTX_FMT */
+#define R300_PACKET3_3D_DRAW_IMMD_2 0x00003500
+/* Same as R300_PACKET3_3D_DRAW_INDX but without VAP_VTX_FMT */
+#define R300_PACKET3_3D_DRAW_INDX_2 0x00003600
+
+/* Clears a portion of hierachical Z RAM
+ * 3 dword parameters
+ * 0. START
+ * 1. COUNT: 13:0 (max is 0x3FFF)
+ * 2. CLEAR_VALUE: Value to write into HIZ RAM.
+ */
+#define R300_PACKET3_3D_CLEAR_HIZ 0x00003700
+
+/* Draws a set of primitives using vertex buffers pointed by the state data.
+ * At least 2 Parameters:
+ * 0. VAP_VF_CNTL: The first parameter is a standard primitive emission dword.
+ * 2 to end: Data or indices (see other 3D_DRAW_* packets for details)
+ */
+#define R300_PACKET3_3D_DRAW_128 0x00003900
+
+/* END: Packet 3 commands */
+
+
+/* Color formats for 2d packets
+ */
+#define R300_CP_COLOR_FORMAT_CI8 2
+#define R300_CP_COLOR_FORMAT_ARGB1555 3
+#define R300_CP_COLOR_FORMAT_RGB565 4
+#define R300_CP_COLOR_FORMAT_ARGB8888 6
+#define R300_CP_COLOR_FORMAT_RGB332 7
+#define R300_CP_COLOR_FORMAT_RGB8 9
+#define R300_CP_COLOR_FORMAT_ARGB4444 15
+
+/*
+ * CP type-3 packets
+ */
+#define R300_CP_CMD_BITBLT_MULTI 0xC0009B00
+
+/* XXX Corbin's stuff from radeon and r200 */
+
+#define RADEON_WAIT_UNTIL 0x1720
+# define RADEON_WAIT_CRTC_PFLIP (1 << 0)
+# define RADEON_WAIT_2D_IDLECLEAN (1 << 16)
+# define RADEON_WAIT_3D_IDLECLEAN (1 << 17)
+# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18)
+
+#define RADEON_CP_PACKET3 0xC0000000
+
+#define R200_3D_DRAW_IMMD_2 0xC0003500
+
+/* XXX Oh look, stuff not brought over from docs yet */
+
+#define R300_SU_REG_DEST 0x42C8
+
+#endif /* _R300_REG_H */
+
+/* *INDENT-ON* */
+
+/* vim: set foldenable foldmarker=\\{,\\} foldmethod=marker : */
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
new file mode 100644
index 0000000000..737396d8d9
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "draw/draw_pipe.h"
+#include "draw/draw_vbuf.h"
+#include "util/u_memory.h"
+
+#include "r300_cs.h"
+#include "r300_context.h"
+#include "r300_emit.h"
+#include "r300_reg.h"
+#include "r300_state_derived.h"
+
+/* r300_render: Vertex and index buffer primitive emission. */
+#define R300_MAX_VBO_SIZE (1024 * 1024)
+
+struct r300_render {
+ /* Parent class */
+ struct vbuf_render base;
+
+ /* Pipe context */
+ struct r300_context* r300;
+
+ /* Vertex information */
+ size_t vertex_size;
+ unsigned prim;
+ unsigned hwprim;
+
+ /* VBO */
+ struct pipe_buffer* vbo;
+ size_t vbo_size;
+ size_t vbo_offset;
+ size_t vbo_max_used;
+ void * vbo_ptr;
+};
+
+static INLINE struct r300_render*
+r300_render(struct vbuf_render* render)
+{
+ return (struct r300_render*)render;
+}
+
+static const struct vertex_info*
+r300_render_get_vertex_info(struct vbuf_render* render)
+{
+ struct r300_render* r300render = r300_render(render);
+ struct r300_context* r300 = r300render->r300;
+
+ r300_update_derived_state(r300);
+
+ return &r300->vertex_info.vinfo;
+}
+
+static boolean r300_render_allocate_vertices(struct vbuf_render* render,
+ ushort vertex_size,
+ ushort count)
+{
+ struct r300_render* r300render = r300_render(render);
+ struct r300_context* r300 = r300render->r300;
+ struct pipe_screen* screen = r300->context.screen;
+ size_t size = (size_t)vertex_size * (size_t)count;
+
+ if (size + r300render->vbo_offset > r300render->vbo_size)
+ {
+ r300render->vbo = pipe_buffer_create(screen,
+ 64,
+ PIPE_BUFFER_USAGE_VERTEX,
+ R300_MAX_VBO_SIZE);
+ r300render->vbo_size = R300_MAX_VBO_SIZE;
+ }
+
+ r300render->vertex_size = vertex_size;
+ r300->vbo = r300render->vbo;
+ r300->vbo_offset = r300render->vbo_offset;
+
+ return (r300render->vbo) ? TRUE : FALSE;
+}
+
+static void* r300_render_map_vertices(struct vbuf_render* render)
+{
+ struct r300_render* r300render = r300_render(render);
+ struct pipe_screen* screen = r300render->r300->context.screen;
+
+ r300render->vbo_ptr = pipe_buffer_map(screen, r300render->vbo,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ return (r300render->vbo_ptr + r300render->vbo_offset);
+}
+
+static void r300_render_unmap_vertices(struct vbuf_render* render,
+ ushort min,
+ ushort max)
+{
+ struct r300_render* r300render = r300_render(render);
+ struct pipe_screen* screen = r300render->r300->context.screen;
+ CS_LOCALS(r300render->r300);
+ BEGIN_CS(2);
+ OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max);
+ END_CS;
+
+ r300render->vbo_max_used = MAX2(r300render->vbo_max_used,
+ r300render->vertex_size * (max + 1));
+ pipe_buffer_unmap(screen, r300render->vbo);
+}
+
+static void r300_render_release_vertices(struct vbuf_render* render)
+{
+ struct r300_render* r300render = r300_render(render);
+ struct r300_context* r300 = r300render->r300;
+
+ r300render->vbo_offset += r300render->vbo_max_used;
+ r300render->vbo_max_used = 0;
+ r300->vbo = NULL;
+}
+
+static boolean r300_render_set_primitive(struct vbuf_render* render,
+ unsigned prim)
+{
+ struct r300_render* r300render = r300_render(render);
+ r300render->prim = prim;
+
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_POINTS;
+ break;
+ case PIPE_PRIM_LINES:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_LINES;
+ break;
+ case PIPE_PRIM_LINE_LOOP:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
+ break;
+ case PIPE_PRIM_LINE_STRIP:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
+ break;
+ case PIPE_PRIM_TRIANGLES:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_TRIANGLES;
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
+ break;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
+ break;
+ case PIPE_PRIM_QUADS:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_QUADS;
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
+ break;
+ case PIPE_PRIM_POLYGON:
+ r300render->hwprim = R300_VAP_VF_CNTL__PRIM_POLYGON;
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+}
+
+static void r300_prepare_render(struct r300_render* render, unsigned count)
+{
+ struct r300_context* r300 = render->r300;
+
+ CS_LOCALS(r300);
+
+ r300_emit_dirty_state(r300);
+}
+
+static void r300_render_draw_arrays(struct vbuf_render* render,
+ unsigned start,
+ unsigned count)
+{
+ struct r300_render* r300render = r300_render(render);
+ struct r300_context* r300 = r300render->r300;
+
+ CS_LOCALS(r300);
+
+ r300_prepare_render(r300render, count);
+
+ DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count);
+
+ BEGIN_CS(2);
+ OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
+ OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) |
+ r300render->hwprim);
+ END_CS;
+}
+
+static void r300_render_draw(struct vbuf_render* render,
+ const ushort* indices,
+ uint count)
+{
+ struct r300_render* r300render = r300_render(render);
+ struct r300_context* r300 = r300render->r300;
+ struct pipe_screen* screen = r300->context.screen;
+ struct pipe_buffer* index_buffer;
+ void* index_map;
+ int i;
+ uint32_t index;
+
+ CS_LOCALS(r300);
+
+ r300_prepare_render(r300render, count);
+
+ /* Send our indices into an index buffer. */
+ index_buffer = pipe_buffer_create(screen, 64, PIPE_BUFFER_USAGE_VERTEX,
+ count * 2);
+ if (!index_buffer) {
+ return;
+ }
+
+ BEGIN_CS(2 + (count+1)/2);
+ OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2);
+ OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
+ r300render->hwprim);
+ for (i = 0; i < count-1; i += 2) {
+ OUT_CS(indices[i+1] << 16 | indices[i]);
+ }
+ if (count % 2) {
+ OUT_CS(indices[count-1]);
+ }
+ END_CS;
+}
+
+static void r300_render_destroy(struct vbuf_render* render)
+{
+ FREE(render);
+}
+
+static struct vbuf_render* r300_render_create(struct r300_context* r300)
+{
+ struct r300_render* r300render = CALLOC_STRUCT(r300_render);
+
+ r300render->r300 = r300;
+
+ /* XXX find real numbers plz */
+ r300render->base.max_vertex_buffer_bytes = 128 * 1024;
+ r300render->base.max_indices = 16 * 1024;
+
+ r300render->base.get_vertex_info = r300_render_get_vertex_info;
+ r300render->base.allocate_vertices = r300_render_allocate_vertices;
+ r300render->base.map_vertices = r300_render_map_vertices;
+ r300render->base.unmap_vertices = r300_render_unmap_vertices;
+ r300render->base.set_primitive = r300_render_set_primitive;
+ r300render->base.draw = r300_render_draw;
+ r300render->base.draw_arrays = r300_render_draw_arrays;
+ r300render->base.release_vertices = r300_render_release_vertices;
+ r300render->base.destroy = r300_render_destroy;
+
+ r300render->vbo = NULL;
+ r300render->vbo_size = 0;
+ r300render->vbo_offset = 0;
+
+ return &r300render->base;
+}
+
+struct draw_stage* r300_draw_stage(struct r300_context* r300)
+{
+ struct vbuf_render* render;
+ struct draw_stage* stage;
+
+ render = r300_render_create(r300);
+
+ if (!render) {
+ return NULL;
+ }
+
+ stage = draw_vbuf_stage(r300->draw, render);
+
+ if (!stage) {
+ render->destroy(render);
+ return NULL;
+ }
+
+ draw_set_render(r300->draw, render);
+
+ return stage;
+}
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
new file mode 100644
index 0000000000..15740f6125
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_screen.h"
+
+/* Return the identifier behind whom the brave coders responsible for this
+ * amalgamation of code, sweat, and duct tape, routinely obscure their names.
+ *
+ * ...I should have just put "Corbin Simpson", but I'm not that cool.
+ *
+ * (Or egotistical. Yet.) */
+static const char* r300_get_vendor(struct pipe_screen* pscreen)
+{
+ return "X.Org R300 Project";
+}
+
+static const char* chip_families[] = {
+ "R300",
+ "R350",
+ "R360",
+ "RV350",
+ "RV370",
+ "RV380",
+ "R420",
+ "R423",
+ "R430",
+ "R480",
+ "R481",
+ "RV410",
+ "RS400",
+ "RC410",
+ "RS480",
+ "RS482",
+ "RS600",
+ "RS690",
+ "RS740",
+ "RV515",
+ "R520",
+ "RV530",
+ "R580",
+ "RV560",
+ "RV570"
+};
+
+static const char* r300_get_name(struct pipe_screen* pscreen)
+{
+ struct r300_screen* r300screen = r300_screen(pscreen);
+
+ return chip_families[r300screen->caps->family];
+}
+
+static int r300_get_param(struct pipe_screen* pscreen, int param)
+{
+ struct r300_screen* r300screen = r300_screen(pscreen);
+
+ switch (param) {
+ /* XXX cases marked "IN THEORY" are possible on the hardware,
+ * but haven't been implemented yet. */
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ /* XXX I'm told this goes up to 16 */
+ return 8;
+ case PIPE_CAP_NPOT_TEXTURES:
+ /* IN THEORY */
+ return 0;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ if (r300screen->caps->is_r500) {
+ return 1;
+ } else {
+ return 0;
+ }
+ case PIPE_CAP_GLSL:
+ if (r300screen->caps->is_r500) {
+ return 1;
+ } else {
+ return 0;
+ }
+ case PIPE_CAP_S3TC:
+ return 1;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 1;
+ case PIPE_CAP_POINT_SPRITE:
+ /* IN THEORY */
+ return 0;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return 4;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ /* IN THEORY */
+ return 0;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ /* IN THEORY */
+ return 0;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ if (r300screen->caps->is_r500) {
+ /* 13 == 4096x4096 */
+ return 13;
+ } else {
+ /* 12 == 2048x2048 */
+ return 12;
+ }
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ /* So, technically, the limit is the same as above, but some math
+ * shows why this is silly. Assuming RGBA, 4cpp, we can see that
+ * 4096*4096*4096 = 64.0 GiB exactly, so it's not exactly
+ * practical. However, if at some point a game really wants this,
+ * then we can remove or raise this limit. */
+ if (r300screen->caps->is_r500) {
+ /* 9 == 256x256x256 */
+ return 9;
+ } else {
+ /* 8 == 128*128*128 */
+ return 8;
+ }
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ if (r300screen->caps->is_r500) {
+ /* 13 == 4096x4096 */
+ return 13;
+ } else {
+ /* 12 == 2048x2048 */
+ return 12;
+ }
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ return 1;
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ /* XXX guessing (what a terrible guess) */
+ return 2;
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ /* XXX */
+ return 0;
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 1;
+ default:
+ debug_printf("r300: Implementation error: Bad param %d\n",
+ param);
+ return 0;
+ }
+}
+
+static float r300_get_paramf(struct pipe_screen* pscreen, int param)
+{
+ struct r300_screen* r300screen = r300_screen(pscreen);
+
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ /* The maximum dimensions of the colorbuffer are our practical
+ * rendering limits. 2048 pixels should be enough for anybody. */
+ if (r300screen->caps->is_r500) {
+ return 4096.0f;
+ } else {
+ return 2048.0f;
+ }
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 16.0f;
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 16.0f;
+ default:
+ debug_printf("r300: Implementation error: Bad paramf %d\n",
+ param);
+ return 0.0f;
+ }
+}
+
+static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage,
+ boolean is_r500)
+{
+ switch (format) {
+ /* Supported formats. */
+ /* Colorbuffer */
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ return usage &
+ (PIPE_TEXTURE_USAGE_RENDER_TARGET |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_PRIMARY);
+
+ /* Texture */
+ case PIPE_FORMAT_A8R8G8B8_SRGB:
+ case PIPE_FORMAT_R8G8B8A8_SRGB:
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT5_RGBA:
+ case PIPE_FORMAT_YCBCR:
+ return usage & PIPE_TEXTURE_USAGE_SAMPLER;
+
+ /* Colorbuffer or texture */
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ case PIPE_FORMAT_I8_UNORM:
+ return usage &
+ (PIPE_TEXTURE_USAGE_RENDER_TARGET |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_PRIMARY |
+ PIPE_TEXTURE_USAGE_SAMPLER);
+
+ /* Z buffer */
+ case PIPE_FORMAT_Z16_UNORM:
+ return usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+
+ /* Z buffer with stencil or texture */
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return usage &
+ (PIPE_TEXTURE_USAGE_DEPTH_STENCIL |
+ PIPE_TEXTURE_USAGE_SAMPLER);
+
+ /* Definitely unsupported formats. */
+ /* Non-usable Z buffer/stencil formats. */
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ debug_printf("r300: Note: Got unsupported format: %s in %s\n",
+ pf_name(format), __FUNCTION__);
+ return FALSE;
+
+ /* XXX These don't even exist
+ case PIPE_FORMAT_A32R32G32B32:
+ case PIPE_FORMAT_A16R16G16B16: */
+ /* XXX Insert YUV422 packed VYUY and YVYU here */
+ /* XXX What the deuce is UV88? (r3xx accel page 14)
+ debug_printf("r300: Warning: Got unimplemented format: %s in %s\n",
+ pf_name(format), __FUNCTION__);
+ return FALSE; */
+
+ /* XXX Supported yet unimplemented r5xx formats: */
+ /* XXX Again, what is UV1010 this time? (r5xx accel page 148) */
+ /* XXX Even more that don't exist
+ case PIPE_FORMAT_A10R10G10B10_UNORM:
+ case PIPE_FORMAT_A2R10G10B10_UNORM:
+ case PIPE_FORMAT_I10_UNORM:
+ debug_printf(
+ "r300: Warning: Got unimplemented r500 format: %s in %s\n",
+ pf_name(format), __FUNCTION__);
+ return FALSE; */
+
+ default:
+ /* Unknown format... */
+ debug_printf("r300: Warning: Got unknown format: %s in %s\n",
+ pf_name(format), __FUNCTION__);
+ break;
+ }
+
+ return FALSE;
+}
+
+/* XXX moar targets */
+static boolean r300_is_format_supported(struct pipe_screen* pscreen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ switch (target) {
+ case PIPE_TEXTURE_2D:
+ return check_tex_2d_format(format, tex_usage,
+ r300_screen(pscreen)->caps->is_r500);
+ case PIPE_TEXTURE_1D:
+ case PIPE_TEXTURE_3D:
+ case PIPE_TEXTURE_CUBE:
+ debug_printf("r300: Implementation error: Unsupported format "
+ "target: %d\n", target);
+ break;
+ default:
+ debug_printf("r300: Fatal: This is not a format target: %d\n",
+ target);
+ assert(0);
+ break;
+ }
+
+ return FALSE;
+}
+
+static struct pipe_transfer*
+r300_get_tex_transfer(struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage, unsigned x, unsigned y,
+ unsigned w, unsigned h)
+{
+ struct r300_texture *tex = (struct r300_texture *)texture;
+ struct r300_transfer *trans;
+ unsigned offset; /* in bytes */
+
+ /* XXX Add support for these things */
+ if (texture->target == PIPE_TEXTURE_CUBE) {
+ debug_printf("PIPE_TEXTURE_CUBE is not yet supported.\n");
+ /* offset = tex->image_offset[level][face]; */
+ }
+ else if (texture->target == PIPE_TEXTURE_3D) {
+ debug_printf("PIPE_TEXTURE_3D is not yet supported.\n");
+ /* offset = tex->image_offset[level][zslice]; */
+ }
+ else {
+ offset = tex->offset[level];
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+
+ trans = CALLOC_STRUCT(r300_transfer);
+ if (trans) {
+ pipe_texture_reference(&trans->transfer.texture, texture);
+ trans->transfer.format = texture->format;
+ trans->transfer.width = w;
+ trans->transfer.height = h;
+ trans->transfer.block = texture->block;
+ trans->transfer.nblocksx = texture->nblocksx[level];
+ trans->transfer.nblocksy = texture->nblocksy[level];
+ trans->transfer.stride = align(pf_get_stride(&trans->transfer.block,
+ texture->width[level]), 32);
+ trans->transfer.usage = usage;
+ trans->offset = offset;
+ }
+ return &trans->transfer;
+}
+
+static void
+r300_tex_transfer_destroy(struct pipe_transfer *trans)
+{
+ pipe_texture_reference(&trans->texture, NULL);
+ FREE(trans);
+}
+
+static void* r300_transfer_map(struct pipe_screen* screen,
+ struct pipe_transfer* transfer)
+{
+ struct r300_texture* tex = (struct r300_texture*)transfer->texture;
+ char* map;
+ unsigned flags = 0;
+
+ if (transfer->usage != PIPE_TRANSFER_WRITE) {
+ flags |= PIPE_BUFFER_USAGE_CPU_READ;
+ }
+ if (transfer->usage != PIPE_TRANSFER_READ) {
+ flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
+ }
+
+ map = pipe_buffer_map(screen, tex->buffer, flags);
+
+ if (!map) {
+ return NULL;
+ }
+
+ return map + r300_transfer(transfer)->offset +
+ transfer->y / transfer->block.height * transfer->stride +
+ transfer->x / transfer->block.width * transfer->block.size;
+}
+
+static void r300_transfer_unmap(struct pipe_screen* screen,
+ struct pipe_transfer* transfer)
+{
+ struct r300_texture* tex = (struct r300_texture*)transfer->texture;
+ pipe_buffer_unmap(screen, tex->buffer);
+}
+
+static void r300_destroy_screen(struct pipe_screen* pscreen)
+{
+ struct r300_screen* r300screen = r300_screen(pscreen);
+
+ FREE(r300screen->caps);
+ FREE(r300screen);
+}
+
+struct pipe_screen* r300_create_screen(struct r300_winsys* r300_winsys)
+{
+ struct r300_screen* r300screen = CALLOC_STRUCT(r300_screen);
+ struct r300_capabilities* caps = CALLOC_STRUCT(r300_capabilities);
+
+ if (!r300screen || !caps)
+ return NULL;
+
+ caps->pci_id = r300_winsys->pci_id;
+ caps->num_frag_pipes = r300_winsys->gb_pipes;
+
+ r300_parse_chipset(caps);
+
+ r300screen->caps = caps;
+ r300screen->screen.winsys = (struct pipe_winsys*)r300_winsys;
+ r300screen->screen.destroy = r300_destroy_screen;
+ r300screen->screen.get_name = r300_get_name;
+ r300screen->screen.get_vendor = r300_get_vendor;
+ r300screen->screen.get_param = r300_get_param;
+ r300screen->screen.get_paramf = r300_get_paramf;
+ r300screen->screen.is_format_supported = r300_is_format_supported;
+ r300screen->screen.get_tex_transfer = r300_get_tex_transfer;
+ r300screen->screen.tex_transfer_destroy = r300_tex_transfer_destroy;
+ r300screen->screen.transfer_map = r300_transfer_map;
+ r300screen->screen.transfer_unmap = r300_transfer_unmap;
+
+ r300_init_screen_texture_functions(&r300screen->screen);
+ u_simple_screen_init(&r300screen->screen);
+
+ return &r300screen->screen;
+}
diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h
new file mode 100644
index 0000000000..2a0e41fbc3
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_screen.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_SCREEN_H
+#define R300_SCREEN_H
+
+#include "pipe/p_inlines.h"
+#include "pipe/p_screen.h"
+#include "util/u_memory.h"
+#include "util/u_simple_screen.h"
+
+#include "r300_chipset.h"
+#include "r300_texture.h"
+#include "r300_winsys.h"
+
+struct r300_screen {
+ /* Parent class */
+ struct pipe_screen screen;
+
+ /* Chipset capabilities */
+ struct r300_capabilities* caps;
+};
+
+struct r300_transfer {
+ /* Parent class */
+ struct pipe_transfer transfer;
+
+ /* Offset from start of buffer. */
+ unsigned offset;
+};
+
+/* Convenience cast wrapper. */
+static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) {
+ return (struct r300_screen*)screen;
+}
+
+/* Convenience cast wrapper. */
+static INLINE struct r300_transfer*
+r300_transfer(struct pipe_transfer* transfer)
+{
+ return (struct r300_transfer*)transfer;
+}
+
+/* Creates a new r300 screen. */
+struct pipe_screen* r300_create_screen(struct r300_winsys* r300_winsys);
+
+#endif /* R300_SCREEN_H */
diff --git a/src/gallium/drivers/r300/r300_shader_inlines.h b/src/gallium/drivers/r300/r300_shader_inlines.h
new file mode 100644
index 0000000000..a04f45b03e
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_shader_inlines.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_SHADER_INLINES_H
+#define R300_SHADER_INLINES_H
+
+/* TGSI constants. TGSI is like XML: If it can't solve your problems, you're
+ * not using enough of it. */
+static const struct tgsi_full_src_register r300_constant_zero = {
+ .SrcRegister.Extended = TRUE,
+ .SrcRegister.File = TGSI_FILE_NULL,
+ .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO,
+ .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO,
+ .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO,
+ .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO,
+};
+
+static const struct tgsi_full_src_register r300_constant_one = {
+ .SrcRegister.Extended = TRUE,
+ .SrcRegister.File = TGSI_FILE_NULL,
+ .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ONE,
+ .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ONE,
+ .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ONE,
+ .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ONE,
+};
+
+#endif /* R300_SHADER_INLINES_H */
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
new file mode 100644
index 0000000000..88cb9af6fb
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -0,0 +1,734 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "util/u_debug.h"
+#include "util/u_math.h"
+#include "util/u_pack_color.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "pipe/p_config.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "r300_context.h"
+#include "r300_reg.h"
+#include "r300_state_inlines.h"
+#include "r300_fs.h"
+#include "r300_vs.h"
+
+/* r300_state: Functions used to intialize state context by translating
+ * Gallium state objects into semi-native r300 state objects. */
+
+/* Create a new blend state based on the CSO blend state.
+ *
+ * This encompasses alpha blending, logic/raster ops, and blend dithering. */
+static void* r300_create_blend_state(struct pipe_context* pipe,
+ const struct pipe_blend_state* state)
+{
+ struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state);
+
+ if (state->blend_enable) {
+ /* XXX for now, always do separate alpha...
+ * is it faster to do it with one reg? */
+ blend->blend_control = R300_ALPHA_BLEND_ENABLE |
+ R300_SEPARATE_ALPHA_ENABLE |
+ R300_READ_ENABLE |
+ r300_translate_blend_function(state->rgb_func) |
+ (r300_translate_blend_factor(state->rgb_src_factor) <<
+ R300_SRC_BLEND_SHIFT) |
+ (r300_translate_blend_factor(state->rgb_dst_factor) <<
+ R300_DST_BLEND_SHIFT);
+ blend->alpha_blend_control =
+ r300_translate_blend_function(state->alpha_func) |
+ (r300_translate_blend_factor(state->alpha_src_factor) <<
+ R300_SRC_BLEND_SHIFT) |
+ (r300_translate_blend_factor(state->alpha_dst_factor) <<
+ R300_DST_BLEND_SHIFT);
+ }
+
+ /* PIPE_LOGICOP_* don't need to be translated, fortunately. */
+ if (state->logicop_enable) {
+ blend->rop = R300_RB3D_ROPCNTL_ROP_ENABLE |
+ (state->logicop_func) << R300_RB3D_ROPCNTL_ROP_SHIFT;
+ }
+
+ if (state->dither) {
+ blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT |
+ R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT;
+ }
+
+ return (void*)blend;
+}
+
+/* Bind blend state. */
+static void r300_bind_blend_state(struct pipe_context* pipe,
+ void* state)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ r300->blend_state = (struct r300_blend_state*)state;
+ r300->dirty_state |= R300_NEW_BLEND;
+}
+
+/* Free blend state. */
+static void r300_delete_blend_state(struct pipe_context* pipe,
+ void* state)
+{
+ FREE(state);
+}
+
+/* Set blend color.
+ * Setup both R300 and R500 registers, figure out later which one to write. */
+static void r300_set_blend_color(struct pipe_context* pipe,
+ const struct pipe_blend_color* color)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ ubyte ur, ug, ub, ua;
+
+ ur = float_to_ubyte(color->color[0]);
+ ug = float_to_ubyte(color->color[1]);
+ ub = float_to_ubyte(color->color[2]);
+ ua = float_to_ubyte(color->color[3]);
+
+ util_pack_color(color->color, PIPE_FORMAT_A8R8G8B8_UNORM,
+ &r300->blend_color_state->blend_color);
+
+ /* XXX this is wrong */
+ r300->blend_color_state->blend_color_red_alpha = ur | (ua << 16);
+ r300->blend_color_state->blend_color_green_blue = ub | (ug << 16);
+
+ r300->dirty_state |= R300_NEW_BLEND_COLOR;
+}
+
+static void r300_set_clip_state(struct pipe_context* pipe,
+ const struct pipe_clip_state* state)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ if (r300_screen(pipe->screen)->caps->has_tcl) {
+ r300->clip_state = *state;
+ r300->dirty_state |= R300_NEW_CLIP;
+ } else {
+ draw_flush(r300->draw);
+ draw_set_clip_state(r300->draw, state);
+ }
+}
+
+static void
+ r300_set_constant_buffer(struct pipe_context* pipe,
+ uint shader, uint index,
+ const struct pipe_constant_buffer* buffer)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ /* This entire chunk of code seems ever-so-slightly baked.
+ * It's as if I've got pipe_buffer* matryoshkas... */
+ if (buffer && buffer->buffer && buffer->buffer->size) {
+ void* map = pipe->winsys->buffer_map(pipe->winsys, buffer->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ memcpy(r300->shader_constants[shader].constants,
+ map, buffer->buffer->size);
+ pipe->winsys->buffer_unmap(pipe->winsys, buffer->buffer);
+
+ r300->shader_constants[shader].count =
+ buffer->buffer->size / (sizeof(float) * 4);
+ } else {
+ r300->shader_constants[shader].count = 0;
+ }
+
+ r300->dirty_state |= R300_NEW_CONSTANTS;
+}
+
+/* Create a new depth, stencil, and alpha state based on the CSO dsa state.
+ *
+ * This contains the depth buffer, stencil buffer, alpha test, and such.
+ * On the Radeon, depth and stencil buffer setup are intertwined, which is
+ * the reason for some of the strange-looking assignments across registers. */
+static void*
+ r300_create_dsa_state(struct pipe_context* pipe,
+ const struct pipe_depth_stencil_alpha_state* state)
+{
+ struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state);
+
+ /* Depth test setup. */
+ if (state->depth.enabled) {
+ dsa->z_buffer_control |= R300_Z_ENABLE;
+
+ if (state->depth.writemask) {
+ dsa->z_buffer_control |= R300_Z_WRITE_ENABLE;
+ }
+
+ dsa->z_stencil_control |=
+ (r300_translate_depth_stencil_function(state->depth.func) <<
+ R300_Z_FUNC_SHIFT);
+ }
+
+ /* Stencil buffer setup. */
+ if (state->stencil[0].enabled) {
+ dsa->z_buffer_control |= R300_STENCIL_ENABLE;
+ dsa->z_stencil_control |=
+ (r300_translate_depth_stencil_function(state->stencil[0].func) <<
+ R300_S_FRONT_FUNC_SHIFT) |
+ (r300_translate_stencil_op(state->stencil[0].fail_op) <<
+ R300_S_FRONT_SFAIL_OP_SHIFT) |
+ (r300_translate_stencil_op(state->stencil[0].zpass_op) <<
+ R300_S_FRONT_ZPASS_OP_SHIFT) |
+ (r300_translate_stencil_op(state->stencil[0].zfail_op) <<
+ R300_S_FRONT_ZFAIL_OP_SHIFT);
+
+ dsa->stencil_ref_mask = (state->stencil[0].ref_value) |
+ (state->stencil[0].valuemask << R300_STENCILMASK_SHIFT) |
+ (state->stencil[0].writemask << R300_STENCILWRITEMASK_SHIFT);
+
+ if (state->stencil[1].enabled) {
+ dsa->z_buffer_control |= R300_STENCIL_FRONT_BACK;
+ dsa->z_stencil_control |=
+ (r300_translate_depth_stencil_function(state->stencil[1].func) <<
+ R300_S_BACK_FUNC_SHIFT) |
+ (r300_translate_stencil_op(state->stencil[1].fail_op) <<
+ R300_S_BACK_SFAIL_OP_SHIFT) |
+ (r300_translate_stencil_op(state->stencil[1].zpass_op) <<
+ R300_S_BACK_ZPASS_OP_SHIFT) |
+ (r300_translate_stencil_op(state->stencil[1].zfail_op) <<
+ R300_S_BACK_ZFAIL_OP_SHIFT);
+
+ dsa->stencil_ref_bf = (state->stencil[1].ref_value) |
+ (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) |
+ (state->stencil[1].writemask << R300_STENCILWRITEMASK_SHIFT);
+ }
+ }
+
+ /* Alpha test setup. */
+ if (state->alpha.enabled) {
+ dsa->alpha_function =
+ r300_translate_alpha_function(state->alpha.func) |
+ R300_FG_ALPHA_FUNC_ENABLE;
+ dsa->alpha_reference = CLAMP(state->alpha.ref_value * 1023.0f,
+ 0, 1023);
+ } else {
+ /* XXX need to fix this to be dynamically set
+ dsa->z_buffer_top = R300_ZTOP_ENABLE; */
+ }
+
+ return (void*)dsa;
+}
+
+/* Bind DSA state. */
+static void r300_bind_dsa_state(struct pipe_context* pipe,
+ void* state)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ r300->dsa_state = (struct r300_dsa_state*)state;
+ r300->dirty_state |= R300_NEW_DSA;
+}
+
+/* Free DSA state. */
+static void r300_delete_dsa_state(struct pipe_context* pipe,
+ void* state)
+{
+ FREE(state);
+}
+
+static void r300_set_edgeflags(struct pipe_context* pipe,
+ const unsigned* bitfield)
+{
+ /* XXX you know it's bad when i915 has this blank too */
+ /* XXX and even worse, I have no idea WTF the bitfield is */
+}
+
+static void
+ r300_set_framebuffer_state(struct pipe_context* pipe,
+ const struct pipe_framebuffer_state* state)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ draw_flush(r300->draw);
+
+ r300->framebuffer_state = *state;
+
+ r300->dirty_state |= R300_NEW_FRAMEBUFFERS;
+}
+
+/* Create fragment shader state. */
+static void* r300_create_fs_state(struct pipe_context* pipe,
+ const struct pipe_shader_state* shader)
+{
+ struct r300_fragment_shader* fs = NULL;
+
+ fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r300_fragment_shader);
+
+ /* Copy state directly into shader. */
+ fs->state = *shader;
+ fs->state.tokens = tgsi_dup_tokens(shader->tokens);
+
+ tgsi_scan_shader(shader->tokens, &fs->info);
+
+ return (void*)fs;
+}
+
+/* Bind fragment shader state. */
+static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader;
+
+ if (fs == NULL) {
+ r300->fs = NULL;
+ return;
+ } else if (!fs->translated) {
+ r300_translate_fragment_shader(r300, fs);
+ }
+
+ r300->fs = fs;
+
+ r300->dirty_state |= R300_NEW_FRAGMENT_SHADER;
+}
+
+/* Delete fragment shader state. */
+static void r300_delete_fs_state(struct pipe_context* pipe, void* shader)
+{
+ struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader;
+ rc_constants_destroy(&fs->code.constants);
+ FREE(fs->state.tokens);
+ FREE(shader);
+}
+
+static void r300_set_polygon_stipple(struct pipe_context* pipe,
+ const struct pipe_poly_stipple* state)
+{
+ /* XXX no idea how to set this up, but not terribly important */
+}
+
+/* Create a new rasterizer state based on the CSO rasterizer state.
+ *
+ * This is a very large chunk of state, and covers most of the graphics
+ * backend (GB), geometry assembly (GA), and setup unit (SU) blocks.
+ *
+ * In a not entirely unironic sidenote, this state has nearly nothing to do
+ * with the actual block on the Radeon called the rasterizer (RS). */
+static void* r300_create_rs_state(struct pipe_context* pipe,
+ const struct pipe_rasterizer_state* state)
+{
+ struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
+
+ /* Copy rasterizer state for Draw. */
+ rs->rs = *state;
+
+ rs->enable_vte = !state->bypass_vs_clip_and_viewport;
+
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
+ rs->vap_control_status = R300_VC_NO_SWAP;
+#else
+ rs->vap_control_status = R300_VC_32BIT_SWAP;
+#endif
+
+ /* If bypassing TCL, or if no TCL engine is present, turn off the HW TCL.
+ * Else, enable HW TCL and force Draw's TCL off. */
+ if (state->bypass_vs_clip_and_viewport ||
+ !r300_screen(pipe->screen)->caps->has_tcl) {
+ rs->vap_control_status |= R300_VAP_TCL_BYPASS;
+ } else {
+ rs->rs.bypass_vs_clip_and_viewport = TRUE;
+ }
+
+ rs->point_size = pack_float_16_6x(state->point_size) |
+ (pack_float_16_6x(state->point_size) << R300_POINTSIZE_X_SHIFT);
+
+ rs->point_minmax =
+ ((int)(state->point_size_min * 6.0) <<
+ R300_GA_POINT_MINMAX_MIN_SHIFT) |
+ ((int)(state->point_size_max * 6.0) <<
+ R300_GA_POINT_MINMAX_MAX_SHIFT);
+
+ rs->line_control = pack_float_16_6x(state->line_width) |
+ R300_GA_LINE_CNTL_END_TYPE_COMP;
+
+ /* Radeons don't think in "CW/CCW", they think in "front/back". */
+ if (state->front_winding == PIPE_WINDING_CW) {
+ rs->cull_mode = R300_FRONT_FACE_CW;
+
+ if (state->offset_cw) {
+ rs->polygon_offset_enable |= R300_FRONT_ENABLE;
+ }
+ if (state->offset_ccw) {
+ rs->polygon_offset_enable |= R300_BACK_ENABLE;
+ }
+ } else {
+ rs->cull_mode = R300_FRONT_FACE_CCW;
+
+ if (state->offset_ccw) {
+ rs->polygon_offset_enable |= R300_FRONT_ENABLE;
+ }
+ if (state->offset_cw) {
+ rs->polygon_offset_enable |= R300_BACK_ENABLE;
+ }
+ }
+ if (state->front_winding & state->cull_mode) {
+ rs->cull_mode |= R300_CULL_FRONT;
+ }
+ if (~(state->front_winding) & state->cull_mode) {
+ rs->cull_mode |= R300_CULL_BACK;
+ }
+
+ if (rs->polygon_offset_enable) {
+ rs->depth_offset_front = rs->depth_offset_back =
+ fui(state->offset_units);
+ rs->depth_scale_front = rs->depth_scale_back =
+ fui(state->offset_scale);
+ }
+
+ if (state->line_stipple_enable) {
+ rs->line_stipple_config =
+ R300_GA_LINE_STIPPLE_CONFIG_LINE_RESET_LINE |
+ (fui((float)state->line_stipple_factor) &
+ R300_GA_LINE_STIPPLE_CONFIG_STIPPLE_SCALE_MASK);
+ /* XXX this might need to be scaled up */
+ rs->line_stipple_value = state->line_stipple_pattern;
+ }
+
+ if (state->flatshade) {
+ rs->color_control = R300_SHADE_MODEL_FLAT;
+ } else {
+ rs->color_control = R300_SHADE_MODEL_SMOOTH;
+ }
+
+ if (!state->flatshade_first) {
+ rs->color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST;
+ }
+
+ return (void*)rs;
+}
+
+/* Bind rasterizer state. */
+static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_rs_state* rs = (struct r300_rs_state*)state;
+
+ draw_flush(r300->draw);
+ draw_set_rasterizer_state(r300->draw, &rs->rs);
+
+ r300->rs_state = rs;
+ r300->dirty_state |= R300_NEW_RASTERIZER;
+ r300->dirty_state |= R300_NEW_RS_BLOCK;
+ r300->dirty_state |= R300_NEW_SCISSOR;
+ r300->dirty_state |= R300_NEW_VIEWPORT;
+}
+
+/* Free rasterizer state. */
+static void r300_delete_rs_state(struct pipe_context* pipe, void* state)
+{
+ FREE(state);
+}
+
+static void*
+ r300_create_sampler_state(struct pipe_context* pipe,
+ const struct pipe_sampler_state* state)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_sampler_state* sampler = CALLOC_STRUCT(r300_sampler_state);
+ int lod_bias;
+
+ sampler->filter0 |=
+ (r300_translate_wrap(state->wrap_s) << R300_TX_WRAP_S_SHIFT) |
+ (r300_translate_wrap(state->wrap_t) << R300_TX_WRAP_T_SHIFT) |
+ (r300_translate_wrap(state->wrap_r) << R300_TX_WRAP_R_SHIFT);
+
+ sampler->filter0 |= r300_translate_tex_filters(state->min_img_filter,
+ state->mag_img_filter,
+ state->min_mip_filter);
+
+ lod_bias = CLAMP((int)(state->lod_bias * 32), -(1 << 9), (1 << 9) - 1);
+
+ sampler->filter1 |= lod_bias << R300_LOD_BIAS_SHIFT;
+
+ sampler->filter1 |= r300_anisotropy(state->max_anisotropy);
+
+ util_pack_color(state->border_color, PIPE_FORMAT_A8R8G8B8_UNORM,
+ &sampler->border_color);
+
+ /* R500-specific fixups and optimizations */
+ if (r300_screen(r300->context.screen)->caps->is_r500) {
+ sampler->filter1 |= R500_BORDER_FIX;
+ }
+
+ return (void*)sampler;
+}
+
+static void r300_bind_sampler_states(struct pipe_context* pipe,
+ unsigned count,
+ void** states)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ int i;
+
+ if (count > 8) {
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (r300->sampler_states[i] != states[i]) {
+ r300->sampler_states[i] = (struct r300_sampler_state*)states[i];
+ r300->dirty_state |= (R300_NEW_SAMPLER << i);
+ }
+ }
+
+ r300->sampler_count = count;
+}
+
+static void r300_delete_sampler_state(struct pipe_context* pipe, void* state)
+{
+ FREE(state);
+}
+
+static void r300_set_sampler_textures(struct pipe_context* pipe,
+ unsigned count,
+ struct pipe_texture** texture)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ int i;
+
+ /* XXX magic num */
+ if (count > 8) {
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (r300->textures[i] != (struct r300_texture*)texture[i]) {
+ pipe_texture_reference((struct pipe_texture**)&r300->textures[i],
+ texture[i]);
+ r300->dirty_state |= (R300_NEW_TEXTURE << i);
+ }
+ }
+
+ for (i = count; i < 8; i++) {
+ if (r300->textures[i]) {
+ pipe_texture_reference((struct pipe_texture**)&r300->textures[i],
+ NULL);
+ r300->dirty_state |= (R300_NEW_TEXTURE << i);
+ }
+ }
+
+ r300->texture_count = count;
+}
+
+static void r300_set_scissor_state(struct pipe_context* pipe,
+ const struct pipe_scissor_state* state)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ if (r300_screen(r300->context.screen)->caps->is_r500) {
+ r300->scissor_state->scissor_top_left =
+ (state->minx << R300_SCISSORS_X_SHIFT) |
+ (state->miny << R300_SCISSORS_Y_SHIFT);
+ r300->scissor_state->scissor_bottom_right =
+ ((state->maxx - 1) << R300_SCISSORS_X_SHIFT) |
+ ((state->maxy - 1) << R300_SCISSORS_Y_SHIFT);
+ } else {
+ /* Offset of 1440 in non-R500 chipsets. */
+ r300->scissor_state->scissor_top_left =
+ ((state->minx + 1440) << R300_SCISSORS_X_SHIFT) |
+ ((state->miny + 1440) << R300_SCISSORS_Y_SHIFT);
+ r300->scissor_state->scissor_bottom_right =
+ (((state->maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) |
+ (((state->maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT);
+ }
+
+ r300->dirty_state |= R300_NEW_SCISSOR;
+}
+
+static void r300_set_viewport_state(struct pipe_context* pipe,
+ const struct pipe_viewport_state* state)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ /* Do the transform in HW. */
+ r300->viewport_state->vte_control = R300_VTX_W0_FMT;
+
+ if (state->scale[0] != 1.0f) {
+ assert(state->scale[0] != 0.0f);
+ r300->viewport_state->xscale = state->scale[0];
+ r300->viewport_state->vte_control |= R300_VPORT_X_SCALE_ENA;
+ }
+ if (state->scale[1] != 1.0f) {
+ assert(state->scale[1] != 0.0f);
+ r300->viewport_state->yscale = state->scale[1];
+ r300->viewport_state->vte_control |= R300_VPORT_Y_SCALE_ENA;
+ }
+ if (state->scale[2] != 1.0f) {
+ assert(state->scale[2] != 0.0f);
+ r300->viewport_state->zscale = state->scale[2];
+ r300->viewport_state->vte_control |= R300_VPORT_Z_SCALE_ENA;
+ }
+ if (state->translate[0] != 0.0f) {
+ r300->viewport_state->xoffset = state->translate[0];
+ r300->viewport_state->vte_control |= R300_VPORT_X_OFFSET_ENA;
+ }
+ if (state->translate[1] != 0.0f) {
+ r300->viewport_state->yoffset = state->translate[1];
+ r300->viewport_state->vte_control |= R300_VPORT_Y_OFFSET_ENA;
+ }
+ if (state->translate[2] != 0.0f) {
+ r300->viewport_state->zoffset = state->translate[2];
+ r300->viewport_state->vte_control |= R300_VPORT_Z_OFFSET_ENA;
+ }
+
+ r300->dirty_state |= R300_NEW_VIEWPORT;
+}
+
+static void r300_set_vertex_buffers(struct pipe_context* pipe,
+ unsigned count,
+ const struct pipe_vertex_buffer* buffers)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ memcpy(r300->vertex_buffers, buffers,
+ sizeof(struct pipe_vertex_buffer) * count);
+
+ r300->vertex_buffer_count = count;
+
+ draw_flush(r300->draw);
+ draw_set_vertex_buffers(r300->draw, count, buffers);
+}
+
+static void r300_set_vertex_elements(struct pipe_context* pipe,
+ unsigned count,
+ const struct pipe_vertex_element* elements)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ draw_flush(r300->draw);
+ draw_set_vertex_elements(r300->draw, count, elements);
+}
+
+static void* r300_create_vs_state(struct pipe_context* pipe,
+ const struct pipe_shader_state* shader)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ if (r300_screen(pipe->screen)->caps->has_tcl) {
+ struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader);
+ /* Copy state directly into shader. */
+ vs->state = *shader;
+ vs->state.tokens = tgsi_dup_tokens(shader->tokens);
+
+ tgsi_scan_shader(shader->tokens, &vs->info);
+
+ /* Appease Draw. */
+ vs->draw = draw_create_vertex_shader(r300->draw, shader);
+
+ return (void*)vs;
+ } else {
+ return draw_create_vertex_shader(r300->draw, shader);
+ }
+}
+
+static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ draw_flush(r300->draw);
+
+ if (r300_screen(pipe->screen)->caps->has_tcl) {
+ struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
+
+ if (vs == NULL) {
+ r300->vs = NULL;
+ return;
+ } else if (!vs->translated) {
+ r300_translate_vertex_shader(r300, vs);
+ }
+
+ draw_bind_vertex_shader(r300->draw, vs->draw);
+ r300->vs = vs;
+ r300->dirty_state |= R300_NEW_VERTEX_SHADER;
+ } else {
+ draw_bind_vertex_shader(r300->draw,
+ (struct draw_vertex_shader*)shader);
+ }
+}
+
+static void r300_delete_vs_state(struct pipe_context* pipe, void* shader)
+{
+ struct r300_context* r300 = r300_context(pipe);
+
+ if (r300_screen(pipe->screen)->caps->has_tcl) {
+ struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
+
+ rc_constants_destroy(&vs->code.constants);
+ draw_delete_vertex_shader(r300->draw, vs->draw);
+ FREE(vs->state.tokens);
+ FREE(shader);
+ } else {
+ draw_delete_vertex_shader(r300->draw,
+ (struct draw_vertex_shader*)shader);
+ }
+}
+
+void r300_init_state_functions(struct r300_context* r300)
+{
+ r300->context.create_blend_state = r300_create_blend_state;
+ r300->context.bind_blend_state = r300_bind_blend_state;
+ r300->context.delete_blend_state = r300_delete_blend_state;
+
+ r300->context.set_blend_color = r300_set_blend_color;
+
+ r300->context.set_clip_state = r300_set_clip_state;
+
+ r300->context.set_constant_buffer = r300_set_constant_buffer;
+
+ r300->context.create_depth_stencil_alpha_state = r300_create_dsa_state;
+ r300->context.bind_depth_stencil_alpha_state = r300_bind_dsa_state;
+ r300->context.delete_depth_stencil_alpha_state = r300_delete_dsa_state;
+
+ r300->context.set_edgeflags = r300_set_edgeflags;
+
+ r300->context.set_framebuffer_state = r300_set_framebuffer_state;
+
+ r300->context.create_fs_state = r300_create_fs_state;
+ r300->context.bind_fs_state = r300_bind_fs_state;
+ r300->context.delete_fs_state = r300_delete_fs_state;
+
+ r300->context.set_polygon_stipple = r300_set_polygon_stipple;
+
+ r300->context.create_rasterizer_state = r300_create_rs_state;
+ r300->context.bind_rasterizer_state = r300_bind_rs_state;
+ r300->context.delete_rasterizer_state = r300_delete_rs_state;
+
+ r300->context.create_sampler_state = r300_create_sampler_state;
+ r300->context.bind_sampler_states = r300_bind_sampler_states;
+ r300->context.delete_sampler_state = r300_delete_sampler_state;
+
+ r300->context.set_sampler_textures = r300_set_sampler_textures;
+
+ r300->context.set_scissor_state = r300_set_scissor_state;
+
+ r300->context.set_viewport_state = r300_set_viewport_state;
+
+ r300->context.set_vertex_buffers = r300_set_vertex_buffers;
+ r300->context.set_vertex_elements = r300_set_vertex_elements;
+
+ r300->context.create_vs_state = r300_create_vs_state;
+ r300->context.bind_vs_state = r300_bind_vs_state;
+ r300->context.delete_vs_state = r300_delete_vs_state;
+}
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
new file mode 100644
index 0000000000..5f6b225d34
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_state_derived.h"
+
+#include "r300_fs.h"
+#include "r300_state_inlines.h"
+#include "r300_vs.h"
+
+/* r300_state_derived: Various bits of state which are dependent upon
+ * currently bound CSO data. */
+
+/* Set up the vs_tab and routes. */
+static void r300_vs_tab_routes(struct r300_context* r300,
+ struct r300_vertex_format* vformat)
+{
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct vertex_info* vinfo = &vformat->vinfo;
+ int* tab = vformat->vs_tab;
+ boolean pos = FALSE, psize = FALSE, fog = FALSE;
+ int i, texs = 0, cols = 0;
+ struct tgsi_shader_info* info;
+
+ if (r300screen->caps->has_tcl) {
+ /* Use vertex shader to determine required routes. */
+ info = &r300->vs->info;
+ } else {
+ /* Use fragment shader to determine required routes. */
+ info = &r300->fs->info;
+ }
+
+ assert(info->num_inputs <= 16);
+
+ if (!r300screen->caps->has_tcl || !r300->rs_state->enable_vte)
+ {
+ for (i = 0; i < info->num_inputs; i++) {
+ switch (info->input_semantic_name[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ pos = TRUE;
+ tab[i] = 0;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ tab[i] = 2 + cols;
+ cols++;
+ break;
+ case TGSI_SEMANTIC_PSIZE:
+ psize = TRUE;
+ tab[i] = 15;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ fog = TRUE;
+ /* Fall through */
+ case TGSI_SEMANTIC_GENERIC:
+ tab[i] = 6 + texs;
+ texs++;
+ break;
+ default:
+ debug_printf("r300: Unknown vertex input %d\n",
+ info->input_semantic_name[i]);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Just copy vert attribs over as-is. */
+ for (i = 0; i < info->num_inputs; i++) {
+ tab[i] = i;
+ }
+
+ for (i = 0; i < info->num_outputs; i++) {
+ switch (info->output_semantic_name[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ pos = TRUE;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ cols++;
+ break;
+ case TGSI_SEMANTIC_PSIZE:
+ psize = TRUE;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ fog = TRUE;
+ /* Fall through */
+ case TGSI_SEMANTIC_GENERIC:
+ texs++;
+ break;
+ default:
+ debug_printf("r300: Unknown vertex output %d\n",
+ info->output_semantic_name[i]);
+ break;
+ }
+ }
+ }
+
+ /* XXX magic */
+ assert(texs <= 8);
+
+ /* Do the actual vertex_info setup.
+ *
+ * vertex_info has four uints of hardware-specific data in it.
+ * vinfo.hwfmt[0] is R300_VAP_VTX_STATE_CNTL
+ * vinfo.hwfmt[1] is R300_VAP_VSM_VTX_ASSM
+ * vinfo.hwfmt[2] is R300_VAP_OUTPUT_VTX_FMT_0
+ * vinfo.hwfmt[3] is R300_VAP_OUTPUT_VTX_FMT_1 */
+
+ vinfo->hwfmt[0] = 0x5555; /* XXX this is classic Mesa bonghits */
+
+ if (!pos) {
+ debug_printf("r300: Forcing vertex position attribute emit...\n");
+ /* Make room for the position attribute
+ * at the beginning of the tab. */
+ for (i = 15; i > 0; i--) {
+ tab[i] = tab[i-1];
+ }
+ tab[0] = 0;
+ }
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE,
+ draw_find_vs_output(r300->draw, TGSI_SEMANTIC_POSITION, 0));
+ vinfo->hwfmt[1] |= R300_INPUT_CNTL_POS;
+ vinfo->hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
+
+ if (psize) {
+ draw_emit_vertex_attr(vinfo, EMIT_1F_PSIZE, INTERP_POS,
+ draw_find_vs_output(r300->draw, TGSI_SEMANTIC_PSIZE, 0));
+ vinfo->hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT;
+ }
+
+ for (i = 0; i < cols; i++) {
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR,
+ draw_find_vs_output(r300->draw, TGSI_SEMANTIC_COLOR, i));
+ vinfo->hwfmt[1] |= R300_INPUT_CNTL_COLOR;
+ vinfo->hwfmt[2] |= (R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i);
+ }
+
+ /* Init i right here, increment it if fog is enabled.
+ * This gets around a double-increment problem. */
+ i = 0;
+
+ if (fog) {
+ i++;
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE,
+ draw_find_vs_output(r300->draw, TGSI_SEMANTIC_FOG, 0));
+ vinfo->hwfmt[1] |= (R300_INPUT_CNTL_TC0 << i);
+ vinfo->hwfmt[3] |= (4 << (3 * i));
+ }
+
+ for (i; i < texs; i++) {
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE,
+ draw_find_vs_output(r300->draw, TGSI_SEMANTIC_GENERIC, i));
+ vinfo->hwfmt[1] |= (R300_INPUT_CNTL_TC0 << i);
+ vinfo->hwfmt[3] |= (4 << (3 * i));
+ }
+
+ /* Handle the case where the vertex shader will be generating some of
+ * the attribs based on its inputs. */
+ if (r300screen->caps->has_tcl &&
+ info->num_inputs < info->num_outputs) {
+ vinfo->num_attribs = info->num_inputs;
+ }
+
+ draw_compute_vertex_size(vinfo);
+}
+
+/* Update the PSC tables. */
+static void r300_vertex_psc(struct r300_context* r300,
+ struct r300_vertex_format* vformat)
+{
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct vertex_info* vinfo = &vformat->vinfo;
+ int* tab = vformat->vs_tab;
+ uint32_t temp;
+ int i, attrib_count;
+
+ /* Vertex shaders have no semantics on their inputs,
+ * so PSC should just route stuff based on their info,
+ * and not on attrib information. */
+ if (r300screen->caps->has_tcl) {
+ attrib_count = r300->vs->info.num_inputs;
+ DBG(r300, DBG_DRAW, "r300: routing %d attribs in psc for vs\n",
+ attrib_count);
+ } else {
+ attrib_count = vinfo->num_attribs;
+ DBG(r300, DBG_DRAW, "r300: attrib count: %d\n", attrib_count);
+ for (i = 0; i < attrib_count; i++) {
+ DBG(r300, DBG_DRAW, "r300: attrib: offset %d, interp %d, size %d,"
+ " tab %d\n", vinfo->attrib[i].src_index,
+ vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit,
+ tab[i]);
+ }
+ }
+
+ for (i = 0; i < attrib_count; i++) {
+ /* Make sure we have a proper destination for our attribute */
+ assert(tab[i] != -1);
+
+ /* Add the attribute to the PSC table. */
+ temp = r300screen->caps->has_tcl ?
+ R300_DATA_TYPE_FLOAT_4 :
+ translate_vertex_data_type(vinfo->attrib[i].emit);
+ temp |= tab[i] << R300_DST_VEC_LOC_SHIFT;
+
+ if (i & 1) {
+ vformat->vap_prog_stream_cntl[i >> 1] &= 0x0000ffff;
+ vformat->vap_prog_stream_cntl[i >> 1] |= temp << 16;
+
+ vformat->vap_prog_stream_cntl_ext[i >> 1] |=
+ (R300_VAP_SWIZZLE_XYZW << 16);
+ } else {
+ vformat->vap_prog_stream_cntl[i >> 1] &= 0xffff0000;
+ vformat->vap_prog_stream_cntl[i >> 1] |= temp << 0;
+
+ vformat->vap_prog_stream_cntl_ext[i >> 1] |=
+ (R300_VAP_SWIZZLE_XYZW << 0);
+ }
+ }
+
+ /* Set the last vector in the PSC. */
+ i--;
+ vformat->vap_prog_stream_cntl[i >> 1] |=
+ (R300_LAST_VEC << (i & 1 ? 16 : 0));
+}
+
+/* Update the vertex format. */
+static void r300_update_vertex_format(struct r300_context* r300)
+{
+ struct r300_vertex_format vformat;
+ int i;
+
+ memset(&vformat, 0, sizeof(struct r300_vertex_format));
+ for (i = 0; i < 16; i++) {
+ vformat.vs_tab[i] = -1;
+ vformat.fs_tab[i] = -1;
+ }
+
+ r300_vs_tab_routes(r300, &vformat);
+
+ r300_vertex_psc(r300, &vformat);
+
+ if (memcmp(&r300->vertex_info, &vformat,
+ sizeof(struct r300_vertex_format))) {
+ memcpy(&r300->vertex_info, &vformat,
+ sizeof(struct r300_vertex_format));
+ r300->dirty_state |= R300_NEW_VERTEX_FORMAT;
+ }
+}
+
+/* Set up the mappings from GB to US, for RS block. */
+static void r300_update_fs_tab(struct r300_context* r300)
+{
+ struct r300_vertex_format* vformat = &r300->vertex_info;
+ struct tgsi_shader_info* info = &r300->fs->info;
+ int i, cols = 0, texs = 0, cols_emitted = 0;
+ int* tab = vformat->fs_tab;
+
+ for (i = 0; i < 16; i++) {
+ tab[i] = -1;
+ }
+
+ assert(info->num_inputs <= 16);
+ for (i = 0; i < info->num_inputs; i++) {
+ switch (info->input_semantic_name[i]) {
+ case TGSI_SEMANTIC_COLOR:
+ tab[i] = INTERP_LINEAR;
+ cols++;
+ break;
+ case TGSI_SEMANTIC_POSITION:
+ case TGSI_SEMANTIC_PSIZE:
+ debug_printf("r300: Implementation error: Can't use "
+ "pos attribs in fragshader yet!\n");
+ /* Pass through for now */
+ case TGSI_SEMANTIC_FOG:
+ case TGSI_SEMANTIC_GENERIC:
+ tab[i] = INTERP_PERSPECTIVE;
+ break;
+ default:
+ debug_printf("r300: Unknown vertex input %d\n",
+ info->input_semantic_name[i]);
+ break;
+ }
+ }
+
+ /* Now that we know where everything is... */
+ DBG(r300, DBG_DRAW, "r300: fp input count: %d\n", info->num_inputs);
+ for (i = 0; i < info->num_inputs; i++) {
+ switch (tab[i]) {
+ case INTERP_LINEAR:
+ DBG(r300, DBG_DRAW, "r300: attrib: "
+ "stack offset %d, color, tab %d\n",
+ i, cols_emitted);
+ tab[i] = cols_emitted;
+ cols_emitted++;
+ break;
+ case INTERP_PERSPECTIVE:
+ DBG(r300, DBG_DRAW, "r300: attrib: "
+ "stack offset %d, texcoord, tab %d\n",
+ i, cols + texs);
+ tab[i] = cols + texs;
+ texs++;
+ break;
+ case -1:
+ debug_printf("r300: Implementation error: Bad fp interp!\n");
+ default:
+ break;
+ }
+ }
+
+}
+
+/* Set up the RS block. This is the part of the chipset that actually does
+ * the rasterization of vertices into fragments. This is also the part of the
+ * chipset that locks up if any part of it is even slightly wrong. */
+static void r300_update_rs_block(struct r300_context* r300)
+{
+ struct r300_rs_block* rs = r300->rs_block;
+ struct tgsi_shader_info* info = &r300->fs->info;
+ int* tab = r300->vertex_info.fs_tab;
+ int col_count = 0, fp_offset = 0, i, memory_pos, tex_count = 0;
+
+ memset(rs, 0, sizeof(struct r300_rs_block));
+
+ if (r300_screen(r300->context.screen)->caps->is_r500) {
+ for (i = 0; i < info->num_inputs; i++) {
+ assert(tab[i] != -1);
+ memory_pos = tab[i] * 4;
+ switch (info->input_semantic_name[i]) {
+ case TGSI_SEMANTIC_COLOR:
+ rs->ip[col_count] |=
+ R500_RS_COL_PTR(memory_pos) |
+ R500_RS_COL_FMT(R300_RS_COL_FMT_RGBA);
+ col_count++;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ rs->ip[tex_count] |=
+ R500_RS_SEL_S(memory_pos) |
+ R500_RS_SEL_T(memory_pos + 1) |
+ R500_RS_SEL_R(memory_pos + 2) |
+ R500_RS_SEL_Q(memory_pos + 3);
+ tex_count++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (col_count == 0) {
+ rs->ip[0] |= R500_RS_COL_FMT(R300_RS_COL_FMT_0001);
+ }
+
+ if (tex_count == 0) {
+ rs->ip[0] |=
+ R500_RS_SEL_S(R500_RS_IP_PTR_K0) |
+ R500_RS_SEL_T(R500_RS_IP_PTR_K0) |
+ R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
+ R500_RS_SEL_Q(R500_RS_IP_PTR_K1);
+ }
+
+ /* Rasterize at least one color, or bad things happen. */
+ if ((col_count == 0) && (tex_count == 0)) {
+ col_count++;
+ }
+
+ for (i = 0; i < tex_count; i++) {
+ rs->inst[i] |= R500_RS_INST_TEX_ID(i) |
+ R500_RS_INST_TEX_CN_WRITE | R500_RS_INST_TEX_ADDR(fp_offset);
+ fp_offset++;
+ }
+
+ for (i = 0; i < col_count; i++) {
+ rs->inst[i] |= R500_RS_INST_COL_ID(i) |
+ R500_RS_INST_COL_CN_WRITE | R500_RS_INST_COL_ADDR(fp_offset);
+ fp_offset++;
+ }
+ } else {
+ for (i = 0; i < info->num_inputs; i++) {
+ assert(tab[i] != -1);
+ memory_pos = tab[i] * 4;
+ switch (info->input_semantic_name[i]) {
+ case TGSI_SEMANTIC_COLOR:
+ rs->ip[col_count] |=
+ R300_RS_COL_PTR(memory_pos) |
+ R300_RS_COL_FMT(R300_RS_COL_FMT_RGBA);
+ col_count++;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ rs->ip[tex_count] |=
+ R300_RS_TEX_PTR(memory_pos) |
+ R300_RS_SEL_S(R300_RS_SEL_C0) |
+ R300_RS_SEL_T(R300_RS_SEL_C1) |
+ R300_RS_SEL_R(R300_RS_SEL_C2) |
+ R300_RS_SEL_Q(R300_RS_SEL_C3);
+ tex_count++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (col_count == 0) {
+ rs->ip[0] |= R300_RS_COL_FMT(R300_RS_COL_FMT_0001);
+ }
+
+ if (tex_count == 0) {
+ rs->ip[0] |=
+ R300_RS_SEL_S(R300_RS_SEL_K0) |
+ R300_RS_SEL_T(R300_RS_SEL_K0) |
+ R300_RS_SEL_R(R300_RS_SEL_K0) |
+ R300_RS_SEL_Q(R300_RS_SEL_K1);
+ }
+
+ /* Rasterize at least one color, or bad things happen. */
+ if ((col_count == 0) && (tex_count == 0)) {
+ col_count++;
+ }
+
+ for (i = 0; i < tex_count; i++) {
+ rs->inst[i] |= R300_RS_INST_TEX_ID(i) |
+ R300_RS_INST_TEX_CN_WRITE | R300_RS_INST_TEX_ADDR(fp_offset);
+ fp_offset++;
+ }
+
+ for (i = 0; i < col_count; i++) {
+ rs->inst[i] |= R300_RS_INST_COL_ID(i) |
+ R300_RS_INST_COL_CN_WRITE | R300_RS_INST_COL_ADDR(fp_offset);
+ fp_offset++;
+ }
+ }
+
+ rs->count = (tex_count * 4) | (col_count << R300_IC_COUNT_SHIFT) |
+ R300_HIRES_EN;
+
+ rs->inst_count = MAX2(MAX2(col_count - 1, tex_count - 1), 0);
+}
+
+void r300_update_derived_state(struct r300_context* r300)
+{
+ if (r300->dirty_state &
+ (R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER)) {
+ r300_update_vertex_format(r300);
+ }
+
+ if (r300->dirty_state & R300_NEW_VERTEX_FORMAT) {
+ r300_update_fs_tab(r300);
+ r300_update_rs_block(r300);
+ }
+}
diff --git a/src/gallium/drivers/r300/r300_state_derived.h b/src/gallium/drivers/r300/r300_state_derived.h
new file mode 100644
index 0000000000..71a4a47b00
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_state_derived.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_STATE_DERIVED_H
+#define R300_STATE_DERIVED_H
+
+struct r300_context;
+
+void r300_update_derived_state(struct r300_context* r300);
+
+#endif /* R300_STATE_DERIVED_H */
diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h
new file mode 100644
index 0000000000..91b93fc367
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_state_inlines.h
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2009 Joakim Sindholt <opensource@zhasha.com>
+ * Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_STATE_INLINES_H
+#define R300_STATE_INLINES_H
+
+#include "pipe/p_format.h"
+
+#include "r300_reg.h"
+
+/* Some maths. These should probably find their way to u_math, if needed. */
+
+static INLINE int pack_float_16_6x(float f) {
+ return ((int)(f * 6.0) & 0xffff);
+}
+
+/* Blend state. */
+
+static INLINE uint32_t r300_translate_blend_function(int blend_func)
+{
+ switch (blend_func) {
+ case PIPE_BLEND_ADD:
+ return R300_COMB_FCN_ADD_CLAMP;
+ case PIPE_BLEND_SUBTRACT:
+ return R300_COMB_FCN_SUB_CLAMP;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ return R300_COMB_FCN_RSUB_CLAMP;
+ case PIPE_BLEND_MIN:
+ return R300_COMB_FCN_MIN;
+ case PIPE_BLEND_MAX:
+ return R300_COMB_FCN_MAX;
+ default:
+ debug_printf("r300: Unknown blend function %d\n", blend_func);
+ break;
+ }
+ return 0;
+}
+
+/* XXX we can also offer the D3D versions of some of these... */
+static INLINE uint32_t r300_translate_blend_factor(int blend_fact)
+{
+ switch (blend_fact) {
+ case PIPE_BLENDFACTOR_ONE:
+ return R300_BLEND_GL_ONE;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ return R300_BLEND_GL_SRC_COLOR;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ return R300_BLEND_GL_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ return R300_BLEND_GL_DST_ALPHA;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ return R300_BLEND_GL_DST_COLOR;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ return R300_BLEND_GL_SRC_ALPHA_SATURATE;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ return R300_BLEND_GL_CONST_COLOR;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ return R300_BLEND_GL_CONST_ALPHA;
+ /* XXX WTF are these?
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_ALPHA: */
+ case PIPE_BLENDFACTOR_ZERO:
+ return R300_BLEND_GL_ZERO;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ return R300_BLEND_GL_ONE_MINUS_SRC_COLOR;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ return R300_BLEND_GL_ONE_MINUS_SRC_ALPHA;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ return R300_BLEND_GL_ONE_MINUS_DST_ALPHA;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ return R300_BLEND_GL_ONE_MINUS_DST_COLOR;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ return R300_BLEND_GL_ONE_MINUS_CONST_COLOR;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ return R300_BLEND_GL_ONE_MINUS_CONST_ALPHA;
+ /* XXX see above
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: */
+ default:
+ debug_printf("r300: Unknown blend factor %d\n", blend_fact);
+ break;
+ }
+ return 0;
+}
+
+/* DSA state. */
+
+static INLINE uint32_t r300_translate_depth_stencil_function(int zs_func)
+{
+ switch (zs_func) {
+ case PIPE_FUNC_NEVER:
+ return R300_ZS_NEVER;
+ case PIPE_FUNC_LESS:
+ return R300_ZS_LESS;
+ case PIPE_FUNC_EQUAL:
+ return R300_ZS_EQUAL;
+ case PIPE_FUNC_LEQUAL:
+ return R300_ZS_LEQUAL;
+ case PIPE_FUNC_GREATER:
+ return R300_ZS_GREATER;
+ case PIPE_FUNC_NOTEQUAL:
+ return R300_ZS_NOTEQUAL;
+ case PIPE_FUNC_GEQUAL:
+ return R300_ZS_GEQUAL;
+ case PIPE_FUNC_ALWAYS:
+ return R300_ZS_ALWAYS;
+ default:
+ debug_printf("r300: Unknown depth/stencil function %d\n",
+ zs_func);
+ break;
+ }
+ return 0;
+}
+
+static INLINE uint32_t r300_translate_stencil_op(int s_op)
+{
+ switch (s_op) {
+ case PIPE_STENCIL_OP_KEEP:
+ return R300_ZS_KEEP;
+ case PIPE_STENCIL_OP_ZERO:
+ return R300_ZS_ZERO;
+ case PIPE_STENCIL_OP_REPLACE:
+ return R300_ZS_REPLACE;
+ case PIPE_STENCIL_OP_INCR:
+ return R300_ZS_INCR;
+ case PIPE_STENCIL_OP_DECR:
+ return R300_ZS_DECR;
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ return R300_ZS_INCR_WRAP;
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ return R300_ZS_DECR_WRAP;
+ case PIPE_STENCIL_OP_INVERT:
+ return R300_ZS_INVERT;
+ default:
+ debug_printf("r300: Unknown stencil op %d", s_op);
+ break;
+ }
+ return 0;
+}
+
+static INLINE uint32_t r300_translate_alpha_function(int alpha_func)
+{
+ switch (alpha_func) {
+ case PIPE_FUNC_NEVER:
+ return R300_FG_ALPHA_FUNC_NEVER;
+ case PIPE_FUNC_LESS:
+ return R300_FG_ALPHA_FUNC_LESS;
+ case PIPE_FUNC_EQUAL:
+ return R300_FG_ALPHA_FUNC_EQUAL;
+ case PIPE_FUNC_LEQUAL:
+ return R300_FG_ALPHA_FUNC_LE;
+ case PIPE_FUNC_GREATER:
+ return R300_FG_ALPHA_FUNC_GREATER;
+ case PIPE_FUNC_NOTEQUAL:
+ return R300_FG_ALPHA_FUNC_NOTEQUAL;
+ case PIPE_FUNC_GEQUAL:
+ return R300_FG_ALPHA_FUNC_GE;
+ case PIPE_FUNC_ALWAYS:
+ return R300_FG_ALPHA_FUNC_ALWAYS;
+ default:
+ debug_printf("r300: Unknown alpha function %d", alpha_func);
+ break;
+ }
+ return 0;
+}
+
+/* Texture sampler state. */
+
+static INLINE uint32_t r300_translate_wrap(int wrap)
+{
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ return R300_TX_REPEAT;
+ case PIPE_TEX_WRAP_CLAMP:
+ return R300_TX_CLAMP;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ return R300_TX_CLAMP_TO_EDGE;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ return R300_TX_CLAMP_TO_BORDER;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ return R300_TX_REPEAT | R300_TX_MIRRORED;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ return R300_TX_CLAMP | R300_TX_MIRRORED;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED;
+ default:
+ debug_printf("r300: Unknown texture wrap %d", wrap);
+ return 0;
+ }
+}
+
+static INLINE uint32_t r300_translate_tex_filters(int min, int mag, int mip)
+{
+ uint32_t retval = 0;
+ switch (min) {
+ case PIPE_TEX_FILTER_NEAREST:
+ retval |= R300_TX_MIN_FILTER_NEAREST;
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ retval |= R300_TX_MIN_FILTER_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_ANISO:
+ retval |= R300_TX_MIN_FILTER_ANISO;
+ break;
+ default:
+ debug_printf("r300: Unknown texture filter %d\n", min);
+ break;
+ }
+ switch (mag) {
+ case PIPE_TEX_FILTER_NEAREST:
+ retval |= R300_TX_MAG_FILTER_NEAREST;
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ retval |= R300_TX_MAG_FILTER_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_ANISO:
+ retval |= R300_TX_MAG_FILTER_ANISO;
+ break;
+ default:
+ debug_printf("r300: Unknown texture filter %d\n", mag);
+ break;
+ }
+ switch (mip) {
+ case PIPE_TEX_MIPFILTER_NONE:
+ retval |= R300_TX_MIN_FILTER_MIP_NONE;
+ break;
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ retval |= R300_TX_MIN_FILTER_MIP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ retval |= R300_TX_MIN_FILTER_MIP_LINEAR;
+ break;
+ default:
+ debug_printf("r300: Unknown texture filter %d\n", mip);
+ break;
+ }
+
+ return retval;
+}
+
+static INLINE uint32_t r300_anisotropy(float max_aniso)
+{
+ if (max_aniso >= 16.0f) {
+ return R300_TX_MAX_ANISO_16_TO_1;
+ } else if (max_aniso >= 8.0f) {
+ return R300_TX_MAX_ANISO_8_TO_1;
+ } else if (max_aniso >= 4.0f) {
+ return R300_TX_MAX_ANISO_4_TO_1;
+ } else if (max_aniso >= 2.0f) {
+ return R300_TX_MAX_ANISO_2_TO_1;
+ } else {
+ return R300_TX_MAX_ANISO_1_TO_1;
+ }
+}
+
+/* Buffer formats. */
+
+static INLINE uint32_t r300_translate_colorformat(enum pipe_format format)
+{
+ switch (format) {
+ /* 8-bit buffers */
+ case PIPE_FORMAT_I8_UNORM:
+ return R300_COLOR_FORMAT_I8;
+ /* 16-bit buffers */
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return R300_COLOR_FORMAT_RGB565;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ return R300_COLOR_FORMAT_ARGB1555;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ return R300_COLOR_FORMAT_ARGB4444;
+ /* 32-bit buffers */
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return R300_COLOR_FORMAT_ARGB8888;
+ /* XXX Not in pipe_format
+ case PIPE_FORMAT_A32R32G32B32:
+ return R300_COLOR_FORMAT_ARGB32323232;
+ case PIPE_FORMAT_A16R16G16B16:
+ return R300_COLOR_FORMAT_ARGB16161616;
+ case PIPE_FORMAT_A10R10G10B10_UNORM:
+ return R500_COLOR_FORMAT_ARGB10101010;
+ case PIPE_FORMAT_A2R10G10B10_UNORM:
+ return R500_COLOR_FORMAT_ARGB2101010;
+ case PIPE_FORMAT_I10_UNORM:
+ return R500_COLOR_FORMAT_I10; */
+ default:
+ debug_printf("r300: Implementation error: "
+ "Got unsupported color format %s in %s\n",
+ pf_name(format), __FUNCTION__);
+ break;
+ }
+ return 0;
+}
+
+static INLINE uint32_t r300_translate_zsformat(enum pipe_format format)
+{
+ switch (format) {
+ /* 16-bit depth, no stencil */
+ case PIPE_FORMAT_Z16_UNORM:
+ return R300_DEPTHFORMAT_16BIT_INT_Z;
+ /* 24-bit depth, 8-bit stencil */
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
+ default:
+ debug_printf("r300: Implementation error: "
+ "Got unsupported ZS format %s in %s\n",
+ pf_name(format), __FUNCTION__);
+ break;
+ }
+ return 0;
+}
+
+/* Translate pipe_format into US_OUT_FMT.
+ * Note that formats are stored from C3 to C0. */
+static INLINE uint32_t r300_translate_out_fmt(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return R300_US_OUT_FMT_C4_8 |
+ R300_C0_SEL_B | R300_C1_SEL_G |
+ R300_C2_SEL_R | R300_C3_SEL_A;
+ default:
+ debug_printf("r300: Implementation error: "
+ "Got unsupported output format %s in %s\n",
+ pf_name(format), __FUNCTION__);
+ return R300_US_OUT_FMT_UNUSED;
+ }
+ return 0;
+}
+
+/* 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;
+ break;
+ case 2:
+ return R300_GB_TILE_PIPE_COUNT_R300;
+ break;
+ case 3:
+ return R300_GB_TILE_PIPE_COUNT_R420_3P;
+ break;
+ case 4:
+ return R300_GB_TILE_PIPE_COUNT_R420;
+ break;
+ }
+ return 0;
+}
+
+static INLINE uint32_t translate_vertex_data_type(int type) {
+ switch (type) {
+ case EMIT_1F:
+ case EMIT_1F_PSIZE:
+ return R300_DATA_TYPE_FLOAT_1;
+ break;
+ case EMIT_2F:
+ return R300_DATA_TYPE_FLOAT_2;
+ break;
+ case EMIT_3F:
+ return R300_DATA_TYPE_FLOAT_3;
+ break;
+ case EMIT_4F:
+ return R300_DATA_TYPE_FLOAT_4;
+ break;
+ case EMIT_4UB:
+ return R300_DATA_TYPE_BYTE;
+ break;
+ default:
+ debug_printf("r300: Implementation error: "
+ "Bad vertex data type!\n");
+ assert(0);
+ break;
+ }
+
+ return 0;
+}
+
+#endif /* R300_STATE_INLINES_H */
diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c
new file mode 100644
index 0000000000..3865730d63
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_state_invariant.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2009 Joakim Sindholt <opensource@zhasha.com>
+ * Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_state_invariant.h"
+
+
+struct pipe_viewport_state r300_viewport_identity = {
+ .scale = {1.0, 1.0, 1.0, 1.0},
+ .translate = {0.0, 0.0, 0.0, 0.0},
+};
+
+/* Calculate and emit invariant state. This is data that the 3D engine
+ * will probably want at the beginning of every CS, but it's not currently
+ * handled by any CSO setup, and in addition it doesn't really change much.
+ *
+ * Note that eventually this should be empty, but it's useful for development
+ * and general unduplication of code. */
+void r300_emit_invariant_state(struct r300_context* r300)
+{
+ struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(24 + (caps->has_tcl ? 2: 0));
+
+ /*** Graphics Backend (GB) ***/
+ /* Various GB enables */
+ OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
+ R300_GB_LINE_STUFF_ENABLE |
+ R300_GB_TRIANGLE_STUFF_ENABLE);
+ /* Subpixel multisampling for AA
+ * These are commented out because glisse's CS checker doesn't like them.
+ * I presume these will be re-enabled later.
+ * OUT_CS_REG(R300_GB_MSPOS0, 0x66666666);
+ * OUT_CS_REG(R300_GB_MSPOS1, 0x6666666);
+ */
+ /* Source of fog depth */
+ OUT_CS_REG(R300_GB_SELECT, R300_GB_FOG_SELECT_1_1_W);
+ /* AA enable */
+ OUT_CS_REG(R300_GB_AA_CONFIG, 0x0);
+
+ /*** Fog (FG) ***/
+ OUT_CS_REG(R300_FG_FOG_BLEND, 0x0);
+ OUT_CS_REG(R300_FG_FOG_COLOR_R, 0x0);
+ OUT_CS_REG(R300_FG_FOG_COLOR_G, 0x0);
+ OUT_CS_REG(R300_FG_FOG_COLOR_B, 0x0);
+ OUT_CS_REG(R300_FG_DEPTH_SRC, 0x0);
+ OUT_CS_REG(R300_US_W_FMT, 0x0);
+
+ /*** VAP ***/
+ /* Max and min vertex index clamp. */
+ OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0x0);
+ OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, 0xffffff);
+ /* Sign/normalize control */
+ OUT_CS_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO);
+ /* TCL-only stuff */
+ if (caps->has_tcl) {
+ /* Amount of time to wait for vertex fetches in PVS */
+ OUT_CS_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff);
+ }
+
+ END_CS;
+
+ /* XXX unsorted stuff from surface_fill */
+ BEGIN_CS(64 + (caps->has_tcl ? 5 : 0) + (caps->is_r500 ? 4 : 0));
+ /* Flush PVS. */
+ OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0);
+
+ OUT_CS_REG(R300_SE_VTE_CNTL, R300_VPORT_X_SCALE_ENA |
+ R300_VPORT_X_OFFSET_ENA | R300_VPORT_Y_SCALE_ENA |
+ R300_VPORT_Y_OFFSET_ENA | R300_VPORT_Z_SCALE_ENA |
+ R300_VPORT_Z_OFFSET_ENA | R300_VTX_W0_FMT);
+ if (caps->has_tcl) {
+ OUT_CS_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4);
+ OUT_CS_32F(1.0);
+ OUT_CS_32F(1.0);
+ OUT_CS_32F(1.0);
+ OUT_CS_32F(1.0);
+ }
+ /* XXX point tex stuffing */
+ OUT_CS_REG_SEQ(R300_GA_POINT_S0, 1);
+ OUT_CS_32F(0.0);
+ OUT_CS_REG_SEQ(R300_GA_POINT_S1, 1);
+ OUT_CS_32F(1.0);
+ /* XXX line tex stuffing */
+ OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1);
+ OUT_CS_32F(0.0);
+ OUT_CS_REG_SEQ(R300_GA_LINE_S1, 1);
+ OUT_CS_32F(1.0);
+ OUT_CS_REG(R300_GA_TRIANGLE_STIPPLE, 0x5 |
+ (0x5 << R300_GA_TRIANGLE_STIPPLE_Y_SHIFT_SHIFT));
+ /* XXX this big chunk should be refactored into rs_state */
+ OUT_CS_REG(R300_GA_SOLID_RG, 0x00000000);
+ OUT_CS_REG(R300_GA_SOLID_BA, 0x00000000);
+ OUT_CS_REG(R300_GA_POLY_MODE, 0x00000000);
+ OUT_CS_REG(R300_GA_ROUND_MODE, 0x00000001);
+ OUT_CS_REG(R300_GA_OFFSET, 0x00000000);
+ OUT_CS_REG(R300_GA_FOG_SCALE, 0x3DBF1412);
+ OUT_CS_REG(R300_GA_FOG_OFFSET, 0x00000000);
+ OUT_CS_REG(R300_SU_TEX_WRAP, 0x00000000);
+ OUT_CS_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF);
+ OUT_CS_REG(R300_SU_DEPTH_OFFSET, 0x00000000);
+ OUT_CS_REG(R300_SC_HYPERZ, 0x0000001C);
+ OUT_CS_REG(R300_SC_EDGERULE, 0x2DA49525);
+ OUT_CS_REG(R300_RB3D_CCTL, 0x00000000);
+ OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0x0000000F);
+ OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000);
+ if (caps->is_r500) {
+ OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x00000000);
+ OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFFFFFFFF);
+ }
+ OUT_CS_REG(R300_ZB_FORMAT, 0x00000002);
+ OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT, 0x00000003);
+ OUT_CS_REG(R300_ZB_BW_CNTL, 0x00000000);
+ OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000);
+ OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0x00000000);
+ OUT_CS_REG(R300_ZB_HIZ_PITCH, 0x00000000);
+ OUT_CS_REG(R300_VAP_VTX_STATE_CNTL, 0x1);
+ OUT_CS_REG(R300_VAP_VSM_VTX_ASSM, 0x405);
+ OUT_CS_REG(R300_SE_VTE_CNTL, 0x0000043F);
+
+ /* XXX */
+ OUT_CS_REG(R300_SC_CLIP_RULE, 0xaaaa);
+
+ END_CS;
+}
diff --git a/src/gallium/drivers/r300/r300_state_invariant.h b/src/gallium/drivers/r300/r300_state_invariant.h
new file mode 100644
index 0000000000..5bea6779fe
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_state_invariant.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_STATE_INVARIANT_H
+#define R300_STATE_INVARIANT_H
+
+#include "r300_chipset.h"
+#include "r300_context.h"
+#include "r300_cs.h"
+#include "r300_reg.h"
+#include "r300_state_inlines.h"
+
+void r300_emit_invariant_state(struct r300_context* r300);
+
+#endif /* R300_STATE_INVARIANT_H */
diff --git a/src/gallium/drivers/r300/r300_surface.c b/src/gallium/drivers/r300/r300_surface.c
new file mode 100644
index 0000000000..96e6e4a77d
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_surface.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_surface.h"
+
+static void r300_surface_setup(struct r300_context* r300,
+ struct r300_texture* dest,
+ unsigned x, unsigned y,
+ unsigned w, unsigned h)
+{
+ struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps;
+ unsigned pixpitch = dest->stride / dest->tex.block.size;
+ CS_LOCALS(r300);
+
+ r300_emit_blend_state(r300, &blend_clear_state);
+ r300_emit_blend_color_state(r300, &blend_color_clear_state);
+ r300_emit_dsa_state(r300, &dsa_clear_state);
+ r300_emit_rs_state(r300, &rs_clear_state);
+
+ BEGIN_CS(26);
+
+ /* Viewport setup */
+ OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
+ OUT_CS_32F((float)w);
+ OUT_CS_32F((float)x);
+ OUT_CS_32F((float)h);
+ OUT_CS_32F((float)y);
+ OUT_CS_32F(1.0);
+ OUT_CS_32F(0.0);
+
+ OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VPORT_X_SCALE_ENA |
+ R300_VPORT_X_OFFSET_ENA |
+ R300_VPORT_Y_SCALE_ENA |
+ R300_VPORT_Y_OFFSET_ENA |
+ R300_VTX_XY_FMT | R300_VTX_Z_FMT);
+
+ /* Pixel scissors. */
+ OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
+ if (caps->is_r500) {
+ OUT_CS((x << R300_SCISSORS_X_SHIFT) | (y << R300_SCISSORS_Y_SHIFT));
+ OUT_CS(((w - 1) << R300_SCISSORS_X_SHIFT) | ((h - 1) << R300_SCISSORS_Y_SHIFT));
+ } else {
+ /* Non-R500 chipsets have an offset of 1440 in their scissors. */
+ OUT_CS(((x + 1440) << R300_SCISSORS_X_SHIFT) |
+ ((y + 1440) << R300_SCISSORS_Y_SHIFT));
+ OUT_CS((((w - 1) + 1440) << R300_SCISSORS_X_SHIFT) |
+ (((h - 1) + 1440) << R300_SCISSORS_Y_SHIFT));
+ }
+
+ /* Flush colorbuffer and blend caches. */
+ OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT,
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D |
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FINISH_SIGNAL);
+ OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT,
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
+
+ /* Setup colorbuffer. */
+ OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0, 1);
+ OUT_CS_RELOC(dest->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0, 1);
+ OUT_CS_RELOC(dest->buffer, pixpitch |
+ r300_translate_colorformat(dest->tex.format), 0,
+ RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0xf);
+
+ END_CS;
+}
+
+/* Provides pipe_context's "surface_fill". Commonly used for clearing
+ * buffers. */
+static void r300_surface_fill(struct pipe_context* pipe,
+ struct pipe_surface* dest,
+ unsigned x, unsigned y,
+ unsigned w, unsigned h,
+ unsigned color)
+{
+ int i;
+ float r, g, b, a, depth;
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_capabilities* caps = r300_screen(pipe->screen)->caps;
+ struct r300_texture* tex = (struct r300_texture*)dest->texture;
+ unsigned pixpitch = tex->stride / tex->tex.block.size;
+ boolean invalid = FALSE;
+ CS_LOCALS(r300);
+
+ a = (float)((color >> 24) & 0xff) / 255.0f;
+ r = (float)((color >> 16) & 0xff) / 255.0f;
+ g = (float)((color >> 8) & 0xff) / 255.0f;
+ b = (float)((color >> 0) & 0xff) / 255.0f;
+ debug_printf("r300: Filling surface %p at (%d,%d),"
+ " dimensions %dx%d (pixel pitch %d), color 0x%x\n",
+ dest, x, y, w, h, pixpitch, color);
+
+ /* Fallback? */
+ if (FALSE) {
+fallback:
+ debug_printf("r300: Falling back on surface clear...");
+ util_surface_fill(pipe, dest, x, y, w, h, color);
+ return;
+ }
+
+ /* Make sure our target BO is okay. */
+validate:
+ if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
+ 0, RADEON_GEM_DOMAIN_VRAM)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
+ if (!r300->winsys->validate(r300->winsys)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ if (invalid) {
+ debug_printf("r300: Stuck in validation loop, gonna fallback.");
+ goto fallback;
+ }
+ invalid = TRUE;
+ goto validate;
+ }
+
+ r300_surface_setup(r300, tex, x, y, w, h);
+
+ /* Vertex shader setup */
+ if (caps->has_tcl) {
+ r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0);
+ } else {
+ BEGIN_CS(4);
+ OUT_CS_REG(R300_VAP_CNTL_STATUS,
+#ifdef PIPE_ARCH_BIG_ENDIAN
+ R300_VC_32BIT_SWAP |
+#endif
+ R300_VAP_TCL_BYPASS);
+ OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(5) |
+ R300_PVS_NUM_CNTLRS(5) |
+ R300_PVS_NUM_FPUS(caps->num_vert_fpus) |
+ R300_PVS_VF_MAX_VTX_NUM(12));
+ END_CS;
+ }
+
+ /* Fragment shader setup */
+ if (caps->is_r500) {
+ r500_emit_fragment_program_code(r300, &r5xx_passthrough_fragment_shader, 0);
+ r300_emit_rs_block_state(r300, &r5xx_rs_block_clear_state);
+ } else {
+ r300_emit_fragment_program_code(r300, &r3xx_passthrough_fragment_shader, 0);
+ r300_emit_rs_block_state(r300, &r3xx_rs_block_clear_state);
+ }
+
+ BEGIN_CS(26);
+
+ /* VAP stream control, mapping from input memory to PVS/RS memory */
+ if (caps->has_tcl) {
+ OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
+ (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) |
+ ((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) |
+ R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT));
+ } else {
+ OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
+ (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) |
+ ((R300_LAST_VEC | (2 << R300_DST_VEC_LOC_SHIFT) |
+ R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT));
+ }
+ OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0,
+ (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE0_SHIFT) |
+ (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE1_SHIFT));
+
+ /* VAP format controls */
+ OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_0,
+ R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
+ R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT);
+ OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x0);
+
+ /* Disable textures */
+ OUT_CS_REG(R300_TX_ENABLE, 0x0);
+
+ /* The size of the point we're about to draw, in sixths of pixels */
+ OUT_CS_REG(R300_GA_POINT_SIZE,
+ ((h * 6) & R300_POINTSIZE_Y_MASK) |
+ ((w * 6) << R300_POINTSIZE_X_SHIFT));
+
+ /* Vertex size. */
+ OUT_CS_REG(R300_VAP_VTX_SIZE, 0x8);
+
+ /* Packet3 with our point vertex */
+ OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 8);
+ OUT_CS(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
+ (1 << R300_PRIM_NUM_VERTICES_SHIFT));
+ /* Position */
+ OUT_CS_32F(0.5);
+ OUT_CS_32F(0.5);
+ OUT_CS_32F(1.0);
+ OUT_CS_32F(1.0);
+ /* Color */
+ OUT_CS_32F(r);
+ OUT_CS_32F(g);
+ OUT_CS_32F(b);
+ OUT_CS_32F(a);
+
+ OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA);
+
+ END_CS;
+
+ r300->dirty_hw++;
+}
+
+static void r300_surface_copy(struct pipe_context* pipe,
+ struct pipe_surface* dest,
+ unsigned destx, unsigned desty,
+ struct pipe_surface* src,
+ unsigned srcx, unsigned srcy,
+ unsigned w, unsigned h)
+{
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_capabilities* caps = r300_screen(pipe->screen)->caps;
+ struct r300_texture* srctex = (struct r300_texture*)src->texture;
+ struct r300_texture* desttex = (struct r300_texture*)dest->texture;
+ unsigned pixpitch = srctex->stride / srctex->tex.block.size;
+ boolean invalid = FALSE;
+ float fsrcx = srcx, fsrcy = srcy, fdestx = destx, fdesty = desty;
+ CS_LOCALS(r300);
+
+ debug_printf("r300: Copying surface %p at (%d,%d) to %p at (%d, %d),"
+ " dimensions %dx%d (pixel pitch %d)\n",
+ src, srcx, srcy, dest, destx, desty, w, h, pixpitch);
+
+ if ((srctex->buffer == desttex->buffer) &&
+ ((destx < srcx + w) || (srcx < destx + w)) &&
+ ((desty < srcy + h) || (srcy < desty + h))) {
+fallback:
+ debug_printf("r300: Falling back on surface_copy\n");
+ util_surface_copy(pipe, FALSE, dest, destx, desty, src,
+ srcx, srcy, w, h);
+ }
+
+ /* Add our target BOs to the list. */
+validate:
+ if (!r300->winsys->add_buffer(r300->winsys, srctex->buffer,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
+ if (!r300->winsys->add_buffer(r300->winsys, desttex->buffer,
+ 0, RADEON_GEM_DOMAIN_VRAM)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
+ if (!r300->winsys->validate(r300->winsys)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ if (invalid) {
+ debug_printf("r300: Stuck in validation loop, gonna fallback.");
+ goto fallback;
+ }
+ invalid = TRUE;
+ goto validate;
+ }
+
+ r300_surface_setup(r300, desttex, destx, desty, w, h);
+
+ /* Setup the texture. */
+ r300_emit_texture(r300, &r300_sampler_copy_state, srctex, 0);
+
+ /* Flush and enable. */
+ r300_flush_textures(r300);
+
+ /* Vertex shader setup */
+ if (caps->has_tcl) {
+ r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0);
+ } else {
+ BEGIN_CS(4);
+ OUT_CS_REG(R300_VAP_CNTL_STATUS,
+#ifdef PIPE_ARCH_BIG_ENDIAN
+ R300_VC_32BIT_SWAP |
+#endif
+ R300_VAP_TCL_BYPASS);
+ OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(5) |
+ R300_PVS_NUM_CNTLRS(5) |
+ R300_PVS_NUM_FPUS(caps->num_vert_fpus) |
+ R300_PVS_VF_MAX_VTX_NUM(12));
+ END_CS;
+ }
+
+ /* Fragment shader setup */
+ if (caps->is_r500) {
+ r500_emit_fragment_program_code(r300, &r5xx_texture_fragment_shader, 0);
+ r300_emit_rs_block_state(r300, &r5xx_rs_block_copy_state);
+ } else {
+ r300_emit_fragment_program_code(r300, &r3xx_texture_fragment_shader, 0);
+ r300_emit_rs_block_state(r300, &r3xx_rs_block_copy_state);
+ }
+
+ BEGIN_CS(30);
+ /* VAP stream control, mapping from input memory to PVS/RS memory */
+ if (caps->has_tcl) {
+ OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
+ (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
+ ((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) |
+ R300_DATA_TYPE_FLOAT_2) << R300_DATA_TYPE_1_SHIFT));
+ } else {
+ OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
+ (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
+ ((R300_LAST_VEC | (6 << R300_DST_VEC_LOC_SHIFT) |
+ R300_DATA_TYPE_FLOAT_2) << R300_DATA_TYPE_1_SHIFT));
+ }
+ OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0,
+ (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE0_SHIFT) |
+ (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE1_SHIFT));
+
+ /* VAP format controls */
+ OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_0,
+ R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT);
+ /* Two components of texture 0 */
+ OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x2);
+
+ /* Vertex size. */
+ OUT_CS_REG(R300_VAP_VTX_SIZE, 0x4);
+
+ /* Packet3 with our texcoords */
+ OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 16);
+ OUT_CS(R300_PRIM_TYPE_QUADS | R300_PRIM_WALK_RING |
+ (4 << R300_PRIM_NUM_VERTICES_SHIFT));
+ /* (x , y ) */
+ OUT_CS_32F(fdestx / dest->width);
+ OUT_CS_32F(fdesty / dest->height);
+ OUT_CS_32F(fsrcx / src->width);
+ OUT_CS_32F(fsrcy / src->height);
+ /* (x , y + h) */
+ OUT_CS_32F(fdestx / dest->width);
+ OUT_CS_32F((fdesty + h) / dest->height);
+ OUT_CS_32F(fsrcx / src->width);
+ OUT_CS_32F((fsrcy + h) / src->height);
+ /* (x + w, y + h) */
+ OUT_CS_32F((fdestx + w) / dest->width);
+ OUT_CS_32F((fdesty + h) / dest->height);
+ OUT_CS_32F((fsrcx + w) / src->width);
+ OUT_CS_32F((fsrcy + h) / src->height);
+ /* (x + w, y ) */
+ OUT_CS_32F((fdestx + w) / dest->width);
+ OUT_CS_32F(fdesty / dest->height);
+ OUT_CS_32F((fsrcx + w) / src->width);
+ OUT_CS_32F(fsrcy / src->height);
+
+ OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA);
+
+ END_CS;
+
+ r300->dirty_hw++;
+}
+
+void r300_init_surface_functions(struct r300_context* r300)
+{
+ r300->context.surface_fill = r300_surface_fill;
+ r300->context.surface_copy = r300_surface_copy;
+}
diff --git a/src/gallium/drivers/r300/r300_surface.h b/src/gallium/drivers/r300/r300_surface.h
new file mode 100644
index 0000000000..f9e98b2ec9
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_surface.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_SURFACE_H
+#define R300_SURFACE_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+
+#include "util/u_rect.h"
+
+#include "r300_context.h"
+#include "r300_cs.h"
+#include "r300_emit.h"
+#include "r300_fs.h"
+#include "r300_vs.h"
+#include "r300_state_inlines.h"
+
+static struct r300_blend_state blend_clear_state = {
+ .blend_control = 0x0,
+ .alpha_blend_control = 0x0,
+ .rop = 0x0,
+ .dither = 0x0,
+};
+
+static struct r300_blend_color_state blend_color_clear_state = {
+ .blend_color = 0x0,
+ .blend_color_red_alpha = 0x0,
+ .blend_color_green_blue = 0x0,
+};
+
+static struct r300_dsa_state dsa_clear_state = {
+ .alpha_function = 0x0,
+ .alpha_reference = 0x0,
+ .z_buffer_control = 0x0,
+ .z_stencil_control = 0x0,
+ .stencil_ref_mask = R300_STENCILWRITEMASK_MASK,
+ .z_buffer_top = R300_ZTOP_ENABLE,
+ .stencil_ref_bf = 0x0,
+};
+
+static struct r300_rs_state rs_clear_state = {
+ .point_minmax = 0x36000006,
+ .line_control = 0x00030006,
+ .depth_scale_front = 0x0,
+ .depth_offset_front = 0x0,
+ .depth_scale_back = 0x0,
+ .depth_offset_back = 0x0,
+ .polygon_offset_enable = 0x0,
+ .cull_mode = 0x0,
+ .line_stipple_config = 0x3BAAAAAB,
+ .line_stipple_value = 0x0,
+ .color_control = R300_SHADE_MODEL_FLAT,
+};
+
+static struct r300_rs_block r3xx_rs_block_clear_state = {
+ .ip[0] = R500_RS_SEL_S(R300_RS_SEL_C0) |
+ R500_RS_SEL_T(R300_RS_SEL_C0) |
+ R500_RS_SEL_R(R300_RS_SEL_C0) |
+ R500_RS_SEL_Q(R300_RS_SEL_K1),
+ .inst[0] = R300_RS_INST_COL_CN_WRITE,
+ .count = R300_IT_COUNT(0) | R300_IC_COUNT(1) | R300_HIRES_EN,
+ .inst_count = 0,
+};
+
+static struct r300_rs_block r5xx_rs_block_clear_state = {
+ .ip[0] = R500_RS_SEL_S(R500_RS_IP_PTR_K0) |
+ R500_RS_SEL_T(R500_RS_IP_PTR_K0) |
+ R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
+ R500_RS_SEL_Q(R500_RS_IP_PTR_K1),
+ .inst[0] = R500_RS_INST_COL_CN_WRITE,
+ .count = R300_IT_COUNT(0) | R300_IC_COUNT(1) | R300_HIRES_EN,
+ .inst_count = 0,
+};
+
+/* The following state is used for surface_copy only. */
+
+static struct r300_rs_block r3xx_rs_block_copy_state = {
+ .ip[0] = R500_RS_SEL_S(R300_RS_SEL_K0) |
+ R500_RS_SEL_T(R300_RS_SEL_K0) |
+ R500_RS_SEL_R(R300_RS_SEL_K0) |
+ R500_RS_SEL_Q(R300_RS_SEL_K1),
+ .inst[0] = R300_RS_INST_COL_CN_WRITE,
+ .count = R300_IT_COUNT(2) | R300_IC_COUNT(0) | R300_HIRES_EN,
+ .inst_count = R300_RS_TX_OFFSET(0),
+};
+
+static struct r300_rs_block r5xx_rs_block_copy_state = {
+ .ip[0] = R500_RS_SEL_S(0) |
+ R500_RS_SEL_T(1) |
+ R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
+ R500_RS_SEL_Q(R500_RS_IP_PTR_K1),
+ .inst[0] = R500_RS_INST_TEX_CN_WRITE,
+ .count = R300_IT_COUNT(2) | R300_IC_COUNT(0) | R300_HIRES_EN,
+ .inst_count = R300_RS_TX_OFFSET(0),
+};
+
+static struct r300_sampler_state r300_sampler_copy_state = {
+ .filter0 = R300_TX_WRAP_S(R300_TX_CLAMP) |
+ R300_TX_WRAP_T(R300_TX_CLAMP) |
+ R300_TX_MAG_FILTER_NEAREST |
+ R300_TX_MIN_FILTER_NEAREST,
+};
+
+#endif /* R300_SURFACE_H */
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
new file mode 100644
index 0000000000..590052509c
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_texture.h"
+
+static void r300_setup_texture_state(struct r300_texture* tex,
+ unsigned width,
+ unsigned height,
+ unsigned pitch,
+ unsigned levels)
+{
+ struct r300_texture_state* state = &tex->state;
+
+ state->format0 = R300_TX_WIDTH((width - 1) & 0x7ff) |
+ R300_TX_HEIGHT((height - 1) & 0x7ff) |
+ R300_TX_NUM_LEVELS(levels) |
+ R300_TX_PITCH_EN;
+
+ /* XXX */
+ state->format1 = r300_translate_texformat(tex->tex.format);
+
+ state->format2 = pitch - 1;
+
+ /* Assume (somewhat foolishly) that oversized textures will
+ * not be permitted by the state tracker. */
+ if (width > 2048) {
+ state->format2 |= R500_TXWIDTH_BIT11;
+ }
+ if (height > 2048) {
+ state->format2 |= R500_TXHEIGHT_BIT11;
+ }
+
+ debug_printf("r300: Set texture state (%dx%d, pitch %d, %d levels)\n",
+ width, height, pitch, levels);
+}
+
+static void r300_setup_miptree(struct r300_texture* tex)
+{
+ struct pipe_texture* base = &tex->tex;
+ int stride, size, offset;
+ int i;
+
+ for (i = 0; i <= base->last_level; i++) {
+ if (i > 0) {
+ base->width[i] = minify(base->width[i-1]);
+ base->height[i] = minify(base->height[i-1]);
+ base->depth[i] = minify(base->depth[i-1]);
+ }
+
+ base->nblocksx[i] = pf_get_nblocksx(&base->block, base->width[i]);
+ base->nblocksy[i] = pf_get_nblocksy(&base->block, base->height[i]);
+
+ /* Radeons enjoy things in multiples of 64.
+ *
+ * XXX
+ * POT, uncompressed, unmippmapped textures can be aligned to 32,
+ * instead of 64. */
+ stride = align(pf_get_stride(&base->block, base->width[i]), 32);
+ size = stride * base->nblocksy[i] * base->depth[i];
+
+ tex->offset[i] = align(tex->size, 32);
+ tex->size = tex->offset[i] + size;
+
+ debug_printf("r300: Texture miptree: Level %d "
+ "(%dx%dx%d px, pitch %d bytes)\n",
+ i, base->width[i], base->height[i], base->depth[i],
+ stride);
+ /* Save stride of first level to the texture. */
+ if (i == 0) {
+ tex->stride = stride;
+ }
+ }
+}
+
+/* Create a new texture. */
+static struct pipe_texture*
+ r300_texture_create(struct pipe_screen* screen,
+ const struct pipe_texture* template)
+{
+ struct r300_texture* tex = CALLOC_STRUCT(r300_texture);
+
+ if (!tex) {
+ return NULL;
+ }
+
+ tex->tex = *template;
+ pipe_reference_init(&tex->tex.reference, 1);
+ tex->tex.screen = screen;
+
+ r300_setup_miptree(tex);
+
+ r300_setup_texture_state(tex, template->width[0], template->height[0],
+ template->width[0], template->last_level);
+
+ tex->buffer = screen->buffer_create(screen, 1024,
+ PIPE_BUFFER_USAGE_PIXEL,
+ tex->size);
+
+ if (!tex->buffer) {
+ FREE(tex);
+ return NULL;
+ }
+
+ return (struct pipe_texture*)tex;
+}
+
+static void r300_texture_destroy(struct pipe_texture* texture)
+{
+ struct r300_texture* tex = (struct r300_texture*)texture;
+
+ pipe_buffer_reference(&tex->buffer, NULL);
+
+ FREE(tex);
+}
+
+static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
+ struct pipe_texture* texture,
+ unsigned face,
+ unsigned level,
+ unsigned zslice,
+ unsigned flags)
+{
+ struct r300_texture* tex = (struct r300_texture*)texture;
+ struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface);
+ unsigned offset;
+
+ /* XXX this is certainly dependent on tex target */
+ offset = tex->offset[level];
+
+ if (surface) {
+ pipe_reference_init(&surface->reference, 1);
+ pipe_texture_reference(&surface->texture, texture);
+ surface->format = texture->format;
+ surface->width = texture->width[level];
+ surface->height = texture->height[level];
+ surface->offset = offset;
+ surface->usage = flags;
+ }
+
+ return surface;
+}
+
+static void r300_tex_surface_destroy(struct pipe_surface* s)
+{
+ pipe_texture_reference(&s->texture, NULL);
+ FREE(s);
+}
+
+static struct pipe_texture*
+ r300_texture_blanket(struct pipe_screen* screen,
+ const struct pipe_texture* base,
+ const unsigned* stride,
+ struct pipe_buffer* buffer)
+{
+ struct r300_texture* tex;
+
+ /* XXX we should start doing mips now... */
+ if (base->target != PIPE_TEXTURE_2D ||
+ base->last_level != 0 ||
+ base->depth[0] != 1) {
+ return NULL;
+ }
+
+ tex = CALLOC_STRUCT(r300_texture);
+ if (!tex) {
+ return NULL;
+ }
+
+ tex->tex = *base;
+ pipe_reference_init(&tex->tex.reference, 1);
+ tex->tex.screen = screen;
+
+ tex->stride = *stride;
+
+ /* XXX */
+ r300_setup_texture_state(tex, tex->tex.width[0], tex->tex.height[0],
+ tex->stride, 0);
+
+ pipe_buffer_reference(&tex->buffer, buffer);
+
+ return (struct pipe_texture*)tex;
+}
+
+void r300_init_screen_texture_functions(struct pipe_screen* screen)
+{
+ screen->texture_create = r300_texture_create;
+ screen->texture_destroy = r300_texture_destroy;
+ screen->get_tex_surface = r300_get_tex_surface;
+ screen->tex_surface_destroy = r300_tex_surface_destroy;
+ screen->texture_blanket = r300_texture_blanket;
+}
+
+boolean r300_get_texture_buffer(struct pipe_texture* texture,
+ struct pipe_buffer** buffer,
+ unsigned* stride)
+{
+ struct r300_texture* tex = (struct r300_texture*)texture;
+ if (!tex) {
+ return FALSE;
+ }
+
+ pipe_buffer_reference(buffer, tex->buffer);
+
+ if (stride) {
+ *stride = tex->stride;
+ }
+
+ return TRUE;
+}
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
new file mode 100644
index 0000000000..3b56f0307c
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_TEXTURE_H
+#define R300_TEXTURE_H
+
+#include "pipe/p_screen.h"
+
+#include "util/u_math.h"
+
+#include "r300_context.h"
+#include "r300_reg.h"
+
+void r300_init_screen_texture_functions(struct pipe_screen* screen);
+
+/* Note the signature of R300_EASY_TX_FORMAT(A, R, G, B, FORMAT)... */
+static INLINE uint32_t r300_translate_texformat(enum pipe_format format)
+{
+ switch (format) {
+ /* X8 */
+ case PIPE_FORMAT_I8_UNORM:
+ return R300_EASY_TX_FORMAT(X, X, X, X, X8);
+ /* W8Z8Y8X8 */
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ return R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8);
+ case PIPE_FORMAT_A8R8G8B8_SRGB:
+ return R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8) |
+ R300_TX_FORMAT_GAMMA;
+ case PIPE_FORMAT_R8G8B8A8_SRGB:
+ return R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8) |
+ R300_TX_FORMAT_GAMMA;
+ /* DXT1 */
+ case PIPE_FORMAT_DXT1_RGB:
+ return R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1);
+ case PIPE_FORMAT_DXT1_RGBA:
+ return R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1);
+ /* DXT3 */
+ case PIPE_FORMAT_DXT3_RGBA:
+ return R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3);
+ /* DXT5 */
+ case PIPE_FORMAT_DXT5_RGBA:
+ return R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5);
+ /* YVYU422 */
+ case PIPE_FORMAT_YCBCR:
+ return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) |
+ R300_TX_FORMAT_YUV_TO_RGB;
+ /* W24_FP */
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP);
+ default:
+ debug_printf("r300: Implementation error: "
+ "Got unsupported texture format %s in %s\n",
+ pf_name(format), __FUNCTION__);
+ assert(0);
+ break;
+ }
+ return 0;
+}
+
+#ifndef R300_WINSYS_H
+
+boolean r300_get_texture_buffer(struct pipe_texture* texture,
+ struct pipe_buffer** buffer,
+ unsigned* stride);
+
+#endif /* R300_WINSYS_H */
+
+#endif /* R300_TEXTURE_H */
diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
new file mode 100644
index 0000000000..d68a104106
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_tgsi_to_rc.h"
+
+#include "radeon_compiler.h"
+#include "radeon_program.h"
+
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
+#include "tgsi/tgsi_util.h"
+
+
+static unsigned translate_opcode(unsigned opcode)
+{
+ switch(opcode) {
+ case TGSI_OPCODE_ARL: return OPCODE_ARL;
+ case TGSI_OPCODE_MOV: return OPCODE_MOV;
+ case TGSI_OPCODE_LIT: return OPCODE_LIT;
+ case TGSI_OPCODE_RCP: return OPCODE_RCP;
+ case TGSI_OPCODE_RSQ: return OPCODE_RSQ;
+ case TGSI_OPCODE_EXP: return OPCODE_EXP;
+ case TGSI_OPCODE_LOG: return OPCODE_LOG;
+ case TGSI_OPCODE_MUL: return OPCODE_MUL;
+ case TGSI_OPCODE_ADD: return OPCODE_ADD;
+ case TGSI_OPCODE_DP3: return OPCODE_DP3;
+ case TGSI_OPCODE_DP4: return OPCODE_DP4;
+ case TGSI_OPCODE_DST: return OPCODE_DST;
+ case TGSI_OPCODE_MIN: return OPCODE_MIN;
+ case TGSI_OPCODE_MAX: return OPCODE_MAX;
+ case TGSI_OPCODE_SLT: return OPCODE_SLT;
+ case TGSI_OPCODE_SGE: return OPCODE_SGE;
+ case TGSI_OPCODE_MAD: return OPCODE_MAD;
+ case TGSI_OPCODE_SUB: return OPCODE_SUB;
+ case TGSI_OPCODE_LRP: return OPCODE_LRP;
+ /* case TGSI_OPCODE_CND: return OPCODE_CND; */
+ case TGSI_OPCODE_DP2A: return OPCODE_DP2A;
+ /* gap */
+ case TGSI_OPCODE_FRC: return OPCODE_FRC;
+ /* case TGSI_OPCODE_CLAMP: return OPCODE_CLAMP; */
+ case TGSI_OPCODE_FLR: return OPCODE_FLR;
+ /* case TGSI_OPCODE_ROUND: return OPCODE_ROUND; */
+ case TGSI_OPCODE_EX2: return OPCODE_EX2;
+ case TGSI_OPCODE_LG2: return OPCODE_LG2;
+ case TGSI_OPCODE_POW: return OPCODE_POW;
+ case TGSI_OPCODE_XPD: return OPCODE_XPD;
+ /* gap */
+ case TGSI_OPCODE_ABS: return OPCODE_ABS;
+ case TGSI_OPCODE_RCC: return OPCODE_RCC;
+ case TGSI_OPCODE_DPH: return OPCODE_DPH;
+ case TGSI_OPCODE_COS: return OPCODE_COS;
+ case TGSI_OPCODE_DDX: return OPCODE_DDX;
+ case TGSI_OPCODE_DDY: return OPCODE_DDY;
+ /* case TGSI_OPCODE_KILP: return OPCODE_KILP; */
+ case TGSI_OPCODE_PK2H: return OPCODE_PK2H;
+ case TGSI_OPCODE_PK2US: return OPCODE_PK2US;
+ case TGSI_OPCODE_PK4B: return OPCODE_PK4B;
+ case TGSI_OPCODE_PK4UB: return OPCODE_PK4UB;
+ case TGSI_OPCODE_RFL: return OPCODE_RFL;
+ case TGSI_OPCODE_SEQ: return OPCODE_SEQ;
+ case TGSI_OPCODE_SFL: return OPCODE_SFL;
+ case TGSI_OPCODE_SGT: return OPCODE_SGT;
+ case TGSI_OPCODE_SIN: return OPCODE_SIN;
+ case TGSI_OPCODE_SLE: return OPCODE_SLE;
+ case TGSI_OPCODE_SNE: return OPCODE_SNE;
+ case TGSI_OPCODE_STR: return OPCODE_STR;
+ case TGSI_OPCODE_TEX: return OPCODE_TEX;
+ case TGSI_OPCODE_TXD: return OPCODE_TXD;
+ case TGSI_OPCODE_TXP: return OPCODE_TXP;
+ case TGSI_OPCODE_UP2H: return OPCODE_UP2H;
+ case TGSI_OPCODE_UP2US: return OPCODE_UP2US;
+ case TGSI_OPCODE_UP4B: return OPCODE_UP4B;
+ case TGSI_OPCODE_UP4UB: return OPCODE_UP4UB;
+ case TGSI_OPCODE_X2D: return OPCODE_X2D;
+ case TGSI_OPCODE_ARA: return OPCODE_ARA;
+ case TGSI_OPCODE_ARR: return OPCODE_ARR;
+ case TGSI_OPCODE_BRA: return OPCODE_BRA;
+ case TGSI_OPCODE_CAL: return OPCODE_CAL;
+ case TGSI_OPCODE_RET: return OPCODE_RET;
+ case TGSI_OPCODE_SSG: return OPCODE_SSG;
+ case TGSI_OPCODE_CMP: return OPCODE_CMP;
+ case TGSI_OPCODE_SCS: return OPCODE_SCS;
+ case TGSI_OPCODE_TXB: return OPCODE_TXB;
+ /* case TGSI_OPCODE_NRM: return OPCODE_NRM; */
+ /* case TGSI_OPCODE_DIV: return OPCODE_DIV; */
+ case TGSI_OPCODE_DP2: return OPCODE_DP2;
+ case TGSI_OPCODE_TXL: return OPCODE_TXL;
+ case TGSI_OPCODE_BRK: return OPCODE_BRK;
+ case TGSI_OPCODE_IF: return OPCODE_IF;
+ /* case TGSI_OPCODE_LOOP: return OPCODE_LOOP; */
+ /* case TGSI_OPCODE_REP: return OPCODE_REP; */
+ case TGSI_OPCODE_ELSE: return OPCODE_ELSE;
+ case TGSI_OPCODE_ENDIF: return OPCODE_ENDIF;
+ case TGSI_OPCODE_ENDLOOP: return OPCODE_ENDLOOP;
+ /* case TGSI_OPCODE_ENDREP: return OPCODE_ENDREP; */
+ case TGSI_OPCODE_PUSHA: return OPCODE_PUSHA;
+ case TGSI_OPCODE_POPA: return OPCODE_POPA;
+ /* case TGSI_OPCODE_CEIL: return OPCODE_CEIL; */
+ /* case TGSI_OPCODE_I2F: return OPCODE_I2F; */
+ case TGSI_OPCODE_NOT: return OPCODE_NOT;
+ case TGSI_OPCODE_TRUNC: return OPCODE_TRUNC;
+ /* case TGSI_OPCODE_SHL: return OPCODE_SHL; */
+ /* case TGSI_OPCODE_SHR: return OPCODE_SHR; */
+ case TGSI_OPCODE_AND: return OPCODE_AND;
+ case TGSI_OPCODE_OR: return OPCODE_OR;
+ /* case TGSI_OPCODE_MOD: return OPCODE_MOD; */
+ case TGSI_OPCODE_XOR: return OPCODE_XOR;
+ /* case TGSI_OPCODE_SAD: return OPCODE_SAD; */
+ /* case TGSI_OPCODE_TXF: return OPCODE_TXF; */
+ /* case TGSI_OPCODE_TXQ: return OPCODE_TXQ; */
+ case TGSI_OPCODE_CONT: return OPCODE_CONT;
+ /* case TGSI_OPCODE_EMIT: return OPCODE_EMIT; */
+ /* case TGSI_OPCODE_ENDPRIM: return OPCODE_ENDPRIM; */
+ /* case TGSI_OPCODE_BGNLOOP2: return OPCODE_BGNLOOP2; */
+ case TGSI_OPCODE_BGNSUB: return OPCODE_BGNSUB;
+ /* case TGSI_OPCODE_ENDLOOP2: return OPCODE_ENDLOOP2; */
+ case TGSI_OPCODE_ENDSUB: return OPCODE_ENDSUB;
+ case TGSI_OPCODE_NOISE1: return OPCODE_NOISE1;
+ case TGSI_OPCODE_NOISE2: return OPCODE_NOISE2;
+ case TGSI_OPCODE_NOISE3: return OPCODE_NOISE3;
+ case TGSI_OPCODE_NOISE4: return OPCODE_NOISE4;
+ case TGSI_OPCODE_NOP: return OPCODE_NOP;
+ /* gap */
+ case TGSI_OPCODE_NRM4: return OPCODE_NRM4;
+ /* case TGSI_OPCODE_CALLNZ: return OPCODE_CALLNZ; */
+ /* case TGSI_OPCODE_IFC: return OPCODE_IFC; */
+ /* case TGSI_OPCODE_BREAKC: return OPCODE_BREAKC; */
+ case TGSI_OPCODE_KIL: return OPCODE_KIL;
+ case TGSI_OPCODE_END: return OPCODE_END;
+ case TGSI_OPCODE_SWZ: return OPCODE_SWZ;
+ }
+
+ fprintf(stderr, "Unknown opcode: %i\n", opcode);
+ abort();
+}
+
+static unsigned translate_saturate(unsigned saturate)
+{
+ switch(saturate) {
+ case TGSI_SAT_NONE: return SATURATE_OFF;
+ case TGSI_SAT_ZERO_ONE: return SATURATE_ZERO_ONE;
+ case TGSI_SAT_MINUS_PLUS_ONE: return SATURATE_PLUS_MINUS_ONE;
+ }
+
+ fprintf(stderr, "Unknown saturate mode: %i\n", saturate);
+ abort();
+}
+
+static unsigned translate_register_file(unsigned file)
+{
+ switch(file) {
+ case TGSI_FILE_CONSTANT: return PROGRAM_CONSTANT;
+ case TGSI_FILE_IMMEDIATE: return PROGRAM_CONSTANT;
+ case TGSI_FILE_INPUT: return PROGRAM_INPUT;
+ case TGSI_FILE_OUTPUT: return PROGRAM_OUTPUT;
+ case TGSI_FILE_TEMPORARY: return PROGRAM_TEMPORARY;
+ case TGSI_FILE_ADDRESS: return PROGRAM_ADDRESS;
+ }
+
+ fprintf(stderr, "Unhandled register file: %i\n", file);
+ abort();
+}
+
+static int translate_register_index(
+ struct tgsi_to_rc * ttr,
+ unsigned file,
+ int index)
+{
+ if (file == TGSI_FILE_IMMEDIATE)
+ return ttr->immediate_offset + index;
+
+ return index;
+}
+
+static void transform_dstreg(
+ struct tgsi_to_rc * ttr,
+ struct prog_dst_register * dst,
+ struct tgsi_full_dst_register * src)
+{
+ dst->File = translate_register_file(src->DstRegister.File);
+ dst->Index = translate_register_index(ttr, src->DstRegister.File, src->DstRegister.Index);
+ dst->WriteMask = src->DstRegister.WriteMask;
+ dst->RelAddr = src->DstRegister.Indirect;
+}
+
+static void transform_srcreg(
+ struct tgsi_to_rc * ttr,
+ struct prog_src_register * dst,
+ struct tgsi_full_src_register * src)
+{
+ dst->File = translate_register_file(src->SrcRegister.File);
+ dst->Index = translate_register_index(ttr, src->SrcRegister.File, src->SrcRegister.Index);
+ dst->RelAddr = src->SrcRegister.Indirect;
+ dst->Swizzle = tgsi_util_get_full_src_register_extswizzle(src, 0);
+ dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 1) << 3;
+ dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 2) << 6;
+ dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 3) << 9;
+ dst->Abs = src->SrcRegisterExtMod.Absolute;
+ dst->Negate =
+ src->SrcRegisterExtSwz.NegateX |
+ (src->SrcRegisterExtSwz.NegateY << 1) |
+ (src->SrcRegisterExtSwz.NegateZ << 2) |
+ (src->SrcRegisterExtSwz.NegateW << 3);
+ dst->Negate ^= src->SrcRegister.Negate ? NEGATE_XYZW : 0;
+}
+
+static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_ext_texture src)
+{
+ switch(src.Texture) {
+ case TGSI_TEXTURE_1D:
+ dst->I.TexSrcTarget = TEXTURE_1D_INDEX;
+ break;
+ case TGSI_TEXTURE_2D:
+ dst->I.TexSrcTarget = TEXTURE_2D_INDEX;
+ break;
+ case TGSI_TEXTURE_3D:
+ dst->I.TexSrcTarget = TEXTURE_3D_INDEX;
+ break;
+ case TGSI_TEXTURE_CUBE:
+ dst->I.TexSrcTarget = TEXTURE_CUBE_INDEX;
+ break;
+ case TGSI_TEXTURE_RECT:
+ dst->I.TexSrcTarget = TEXTURE_RECT_INDEX;
+ break;
+ case TGSI_TEXTURE_SHADOW1D:
+ dst->I.TexSrcTarget = TEXTURE_1D_INDEX;
+ dst->I.TexShadow = 1;
+ break;
+ case TGSI_TEXTURE_SHADOW2D:
+ dst->I.TexSrcTarget = TEXTURE_2D_INDEX;
+ dst->I.TexShadow = 1;
+ break;
+ case TGSI_TEXTURE_SHADOWRECT:
+ dst->I.TexSrcTarget = TEXTURE_RECT_INDEX;
+ dst->I.TexShadow = 1;
+ break;
+ }
+}
+
+static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_instruction * src)
+{
+ if (src->Instruction.Opcode == TGSI_OPCODE_END)
+ return;
+
+ struct rc_instruction * dst = rc_insert_new_instruction(ttr->compiler, ttr->compiler->Program.Instructions.Prev);
+ int i;
+
+ dst->I.Opcode = translate_opcode(src->Instruction.Opcode);
+ dst->I.SaturateMode = translate_saturate(src->Instruction.Saturate);
+
+ if (src->Instruction.NumDstRegs)
+ transform_dstreg(ttr, &dst->I.DstReg, &src->FullDstRegisters[0]);
+
+ for(i = 0; i < src->Instruction.NumSrcRegs; ++i) {
+ if (src->FullSrcRegisters[i].SrcRegister.File == TGSI_FILE_SAMPLER)
+ dst->I.TexSrcUnit = src->FullSrcRegisters[i].SrcRegister.Index;
+ else
+ transform_srcreg(ttr, &dst->I.SrcReg[i], &src->FullSrcRegisters[i]);
+ }
+
+ /* Texturing. */
+ transform_texture(dst, src->InstructionExtTexture);
+}
+
+static void handle_immediate(struct tgsi_to_rc * ttr, struct tgsi_full_immediate * imm)
+{
+ struct rc_constant constant;
+ int i;
+
+ constant.Type = RC_CONSTANT_IMMEDIATE;
+ constant.Size = 4;
+ for(i = 0; i < 4; ++i)
+ constant.u.Immediate[i] = imm->u[i].Float;
+ rc_constants_add(&ttr->compiler->Program.Constants, &constant);
+}
+
+void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens)
+{
+ struct tgsi_parse_context parser;
+ int i;
+
+ /* Allocate constants placeholders.
+ *
+ * Note: What if declared constants are not contiguous? */
+ for(i = 0; i <= ttr->info->file_max[TGSI_FILE_CONSTANT]; ++i) {
+ struct rc_constant constant;
+ memset(&constant, 0, sizeof(constant));
+ constant.Type = RC_CONSTANT_EXTERNAL;
+ constant.Size = 4;
+ constant.u.External = i;
+ rc_constants_add(&ttr->compiler->Program.Constants, &constant);
+ }
+
+ ttr->immediate_offset = ttr->compiler->Program.Constants.Count;
+
+ tgsi_parse_init(&parser, tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parser)) {
+ tgsi_parse_token(&parser);
+
+ switch (parser.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ break;
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ handle_immediate(ttr, &parser.FullToken.FullImmediate);
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ transform_instruction(ttr, &parser.FullToken.FullInstruction);
+ break;
+ }
+ }
+
+ tgsi_parse_free(&parser);
+
+ rc_calculate_inputs_outputs(ttr->compiler);
+}
+
diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.h b/src/gallium/drivers/r300/r300_tgsi_to_rc.h
new file mode 100644
index 0000000000..93e90ec6d2
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_TGSI_TO_RC_H
+#define R300_TGSI_TO_RC_H
+
+struct radeon_compiler;
+
+struct tgsi_full_declaration;
+struct tgsi_shader_info;
+struct tgsi_token;
+
+struct tgsi_to_rc {
+ struct radeon_compiler * compiler;
+ const struct tgsi_shader_info * info;
+
+ int immediate_offset;
+};
+
+void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens);
+
+#endif /* R300_TGSI_TO_RC_H */
diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c
new file mode 100644
index 0000000000..12a6e37be6
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_vs.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r300_vs.h"
+
+#include "r300_context.h"
+#include "r300_tgsi_to_rc.h"
+
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_parse.h"
+
+#include "radeon_compiler.h"
+
+
+static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
+{
+ struct r300_vertex_shader * vs = c->UserData;
+ struct tgsi_shader_info* info = &vs->info;
+ boolean pointsize = false;
+ int out_colors = 0;
+ int colors = 0;
+ int out_generic = 0;
+ int generic = 0;
+ int i;
+
+ /* Fill in the input mapping */
+ for (i = 0; i < info->num_inputs; i++)
+ c->code->inputs[i] = i;
+
+ /* Fill in the output mapping */
+ for (i = 0; i < info->num_outputs; i++) {
+ switch (info->output_semantic_name[i]) {
+ case TGSI_SEMANTIC_PSIZE:
+ pointsize = true;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ out_colors++;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ case TGSI_SEMANTIC_GENERIC:
+ out_generic++;
+ break;
+ }
+ }
+
+ struct tgsi_parse_context parser;
+
+ tgsi_parse_init(&parser, vs->state.tokens);
+
+ while (!tgsi_parse_end_of_tokens(&parser)) {
+ tgsi_parse_token(&parser);
+
+ if (parser.FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION)
+ continue;
+
+ struct tgsi_full_declaration * decl = &parser.FullToken.FullDeclaration;
+
+ if (decl->Declaration.File != TGSI_FILE_OUTPUT)
+ continue;
+
+ switch (decl->Semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ c->code->outputs[decl->DeclarationRange.First] = 0;
+ break;
+ case TGSI_SEMANTIC_PSIZE:
+ c->code->outputs[decl->DeclarationRange.First] = 1;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ c->code->outputs[decl->DeclarationRange.First] = 1 +
+ (pointsize ? 1 : 0) +
+ colors++;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ case TGSI_SEMANTIC_GENERIC:
+ c->code->outputs[decl->DeclarationRange.First] = 1 +
+ (pointsize ? 1 : 0) +
+ out_colors +
+ generic++;
+ break;
+ default:
+ debug_printf("r300: vs: Bad semantic declaration %d\n",
+ decl->Semantic.SemanticName);
+ break;
+ }
+ }
+
+ tgsi_parse_free(&parser);
+}
+
+
+void r300_translate_vertex_shader(struct r300_context* r300,
+ struct r300_vertex_shader* vs)
+{
+ struct r300_vertex_program_compiler compiler;
+ struct tgsi_to_rc ttr;
+
+ /* Setup the compiler */
+ rc_init(&compiler.Base);
+
+ compiler.Base.Debug = DBG_ON(r300, DBG_VP);
+ compiler.code = &vs->code;
+ compiler.UserData = vs;
+
+ if (compiler.Base.Debug) {
+ debug_printf("r300: Initial vertex program\n");
+ tgsi_dump(vs->state.tokens, 0);
+ }
+
+ /* Translate TGSI to our internal representation */
+ ttr.compiler = &compiler.Base;
+ ttr.info = &vs->info;
+
+ r300_tgsi_to_rc(&ttr, vs->state.tokens);
+
+ compiler.RequiredOutputs = ~(~0 << vs->info.num_outputs);
+ compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
+
+ /* Invoke the compiler */
+ r3xx_compile_vertex_program(&compiler);
+ if (compiler.Base.Error) {
+ /* Todo: Fail gracefully */
+ fprintf(stderr, "r300 VP: Compiler error\n");
+ abort();
+ }
+
+ /* And, finally... */
+ rc_destroy(&compiler.Base);
+ vs->translated = TRUE;
+}
+
+
+/* XXX get these to r300_reg */
+#define R300_PVS_DST_OPCODE(x) ((x) << 0)
+# define R300_VE_DOT_PRODUCT 1
+# define R300_VE_MULTIPLY 2
+# define R300_VE_ADD 3
+# define R300_VE_MAXIMUM 7
+# define R300_VE_SET_LESS_THAN 10
+#define R300_PVS_DST_MATH_INST (1 << 6)
+# define R300_ME_RECIP_DX 6
+#define R300_PVS_DST_MACRO_INST (1 << 7)
+# define R300_PVS_MACRO_OP_2CLK_MADD 0
+#define R300_PVS_DST_REG_TYPE(x) ((x) << 8)
+# define R300_PVS_DST_REG_TEMPORARY 0
+# define R300_PVS_DST_REG_A0 1
+# define R300_PVS_DST_REG_OUT 2
+# define R300_PVS_DST_REG_OUT_REPL_X 3
+# define R300_PVS_DST_REG_ALT_TEMPORARY 4
+# define R300_PVS_DST_REG_INPUT 5
+#define R300_PVS_DST_OFFSET(x) ((x) << 13)
+#define R300_PVS_DST_WE(x) ((x) << 20)
+#define R300_PVS_DST_WE_XYZW (0xf << 20)
+
+#define R300_PVS_SRC_REG_TYPE(x) ((x) << 0)
+# define R300_PVS_SRC_REG_TEMPORARY 0
+# define R300_PVS_SRC_REG_INPUT 1
+# define R300_PVS_SRC_REG_CONSTANT 2
+# define R300_PVS_SRC_REG_ALT_TEMPORARY 3
+#define R300_PVS_SRC_OFFSET(x) ((x) << 5)
+#define R300_PVS_SRC_SWIZZLE(x) ((x) << 13)
+# define R300_PVS_SRC_SELECT_X 0
+# define R300_PVS_SRC_SELECT_Y 1
+# define R300_PVS_SRC_SELECT_Z 2
+# define R300_PVS_SRC_SELECT_W 3
+# define R300_PVS_SRC_SELECT_FORCE_0 4
+# define R300_PVS_SRC_SELECT_FORCE_1 5
+# define R300_PVS_SRC_SWIZZLE_XYZW \
+ ((R300_PVS_SRC_SELECT_X | (R300_PVS_SRC_SELECT_Y << 3) | \
+ (R300_PVS_SRC_SELECT_Z << 6) | (R300_PVS_SRC_SELECT_W << 9)) << 13)
+# define R300_PVS_SRC_SWIZZLE_ZERO \
+ ((R300_PVS_SRC_SELECT_FORCE_0 | (R300_PVS_SRC_SELECT_FORCE_0 << 3) | \
+ (R300_PVS_SRC_SELECT_FORCE_0 << 6) | \
+ (R300_PVS_SRC_SELECT_FORCE_0 << 9)) << 13)
+# define R300_PVS_SRC_SWIZZLE_ONE \
+ ((R300_PVS_SRC_SELECT_FORCE_1 | (R300_PVS_SRC_SELECT_FORCE_1 << 3) | \
+ (R300_PVS_SRC_SELECT_FORCE_1 << 6) | \
+ (R300_PVS_SRC_SELECT_FORCE_1 << 9)) << 13)
+#define R300_PVS_MODIFIER_X (1 << 25)
+#define R300_PVS_MODIFIER_Y (1 << 26)
+#define R300_PVS_MODIFIER_Z (1 << 27)
+#define R300_PVS_MODIFIER_W (1 << 28)
+#define R300_PVS_NEGATE_XYZW \
+ (R300_PVS_MODIFIER_X | R300_PVS_MODIFIER_Y | \
+ R300_PVS_MODIFIER_Z | R300_PVS_MODIFIER_W)
+
+struct r300_vertex_program_code r300_passthrough_vertex_shader = {
+ .length = 8, /* two instructions */
+
+ /* MOV out[0], in[0] */
+ .body.d[0] = R300_PVS_DST_OPCODE(R300_VE_ADD) |
+ R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
+ R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW,
+ .body.d[1] = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
+ R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW,
+ .body.d[2] = R300_PVS_SRC_SWIZZLE_ZERO,
+ .body.d[3] = 0x0,
+
+ /* MOV out[1], in[1] */
+ .body.d[4] = R300_PVS_DST_OPCODE(R300_VE_ADD) |
+ R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
+ R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW,
+ .body.d[5] = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
+ R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW,
+ .body.d[6] = R300_PVS_SRC_SWIZZLE_ZERO,
+ .body.d[7] = 0x0,
+
+ .inputs[0] = 0,
+ .inputs[1] = 1,
+ .outputs[0] = 0,
+ .outputs[1] = 1,
+
+ .InputsRead = 3,
+ .OutputsWritten = 3
+};
+
diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h
new file mode 100644
index 0000000000..2a4ce315e3
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_vs.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_VS_H
+#define R300_VS_H
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+
+#include "radeon_code.h"
+
+struct r300_context;
+
+struct r300_vertex_shader {
+ /* Parent class */
+ struct pipe_shader_state state;
+ struct tgsi_shader_info info;
+
+ /* Fallback shader, because Draw has issues */
+ struct draw_vertex_shader* draw;
+
+ /* Has this shader been translated yet? */
+ boolean translated;
+
+ /* Machine code (if translated) */
+ struct r300_vertex_program_code code;
+};
+
+
+extern struct r300_vertex_program_code r300_passthrough_vertex_shader;
+
+void r300_translate_vertex_shader(struct r300_context* r300,
+ struct r300_vertex_shader* vs);
+
+#endif /* R300_VS_H */
diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h
new file mode 100644
index 0000000000..f18ad75a47
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_winsys.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R300_WINSYS_H
+#define R300_WINSYS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The public interface header for the r300 pipe driver.
+ * Any winsys hosting this pipe needs to implement r300_winsys and then
+ * call r300_create_context to start things. */
+
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+struct r300_winsys {
+ /* Parent class */
+ struct pipe_winsys base;
+
+ /* Opaque Radeon-specific winsys object. */
+ void* radeon_winsys;
+
+ /* PCI ID */
+ uint32_t pci_id;
+
+ /* GB pipe count */
+ uint32_t gb_pipes;
+
+ /* GART size. */
+ uint32_t gart_size;
+
+ /* VRAM size. */
+ uint32_t vram_size;
+
+ /* Add a pipe_buffer to the list of buffer objects to validate. */
+ boolean (*add_buffer)(struct r300_winsys* winsys,
+ struct pipe_buffer* pbuffer,
+ uint32_t rd,
+ uint32_t wd);
+
+ /* Revalidate all currently setup pipe_buffers.
+ * Returns TRUE if a flush is required. */
+ boolean (*validate)(struct r300_winsys* winsys);
+
+ /* Check to see if there's room for commands. */
+ boolean (*check_cs)(struct r300_winsys* winsys, int size);
+
+ /* Start a command emit. */
+ void (*begin_cs)(struct r300_winsys* winsys,
+ int size,
+ const char* file,
+ const char* function,
+ int line);
+
+ /* Write a dword to the command buffer. */
+ void (*write_cs_dword)(struct r300_winsys* winsys, uint32_t dword);
+
+ /* Write a relocated dword to the command buffer. */
+ void (*write_cs_reloc)(struct r300_winsys* winsys,
+ struct pipe_buffer* bo,
+ uint32_t rd,
+ uint32_t wd,
+ uint32_t flags);
+
+ /* Finish a command emit. */
+ void (*end_cs)(struct r300_winsys* winsys,
+ const char* file,
+ const char* function,
+ int line);
+
+ /* Flush the CS. */
+ void (*flush_cs)(struct r300_winsys* winsys);
+};
+
+struct pipe_context* r300_create_context(struct pipe_screen* screen,
+ struct r300_winsys* r300_winsys);
+
+boolean r300_get_texture_buffer(struct pipe_texture* texture,
+ struct pipe_buffer** buffer,
+ unsigned* stride);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* R300_WINSYS_H */
diff --git a/src/gallium/drivers/r300/r3xx_fs.c b/src/gallium/drivers/r300/r3xx_fs.c
new file mode 100644
index 0000000000..c1c1194d58
--- /dev/null
+++ b/src/gallium/drivers/r300/r3xx_fs.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r3xx_fs.h"
+
+#include "r300_reg.h"
+
+struct rX00_fragment_program_code r3xx_passthrough_fragment_shader = {
+ .code.r300.alu.length = 1,
+ .code.r300.tex.length = 0,
+
+ .code.r300.config = 0,
+ .code.r300.pixsize = 0,
+ .code.r300.code_offset = 0,
+ .code.r300.code_addr[3] = R300_RGBA_OUT,
+
+ .code.r300.alu.inst[0].rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) |
+ R300_ALU_OUTC_CMP,
+ .code.r300.alu.inst[0].rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) |
+ R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ,
+ .code.r300.alu.inst[0].alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) |
+ R300_ALU_OUTA_CMP,
+ .code.r300.alu.inst[0].alpha_addr = R300_ALPHA_ADDR0(0) |
+ R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT,
+};
+
+struct rX00_fragment_program_code r3xx_texture_fragment_shader = {
+ .code.r300.alu.length = 1,
+ .code.r300.tex.length = 1,
+
+ .code.r300.config = R300_PFS_CNTL_FIRST_NODE_HAS_TEX,
+ .code.r300.pixsize = 0,
+ .code.r300.code_offset = 0,
+ .code.r300.code_addr[3] = R300_RGBA_OUT,
+
+ .code.r300.tex.inst[0] = R300_TEX_OP_LD << R300_TEX_INST_SHIFT,
+
+ .code.r300.alu.inst[0].rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) |
+ R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) |
+ R300_ALU_OUTC_CMP,
+ .code.r300.alu.inst[0].rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) |
+ R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ,
+ .code.r300.alu.inst[0].alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) |
+ R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) |
+ R300_ALU_OUTA_CMP,
+ .code.r300.alu.inst[0].alpha_addr = R300_ALPHA_ADDR0(0) |
+ R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT,
+};
diff --git a/src/gallium/drivers/r300/r3xx_fs.h b/src/gallium/drivers/r300/r3xx_fs.h
new file mode 100644
index 0000000000..51cd245724
--- /dev/null
+++ b/src/gallium/drivers/r300/r3xx_fs.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R3XX_FS_H
+#define R3XX_FS_H
+
+#include "radeon_code.h"
+
+struct rX00_fragment_program_code r3xx_passthrough_fragment_shader;
+struct rX00_fragment_program_code r3xx_texture_fragment_shader;
+
+#endif /* R3XX_FS_H */
diff --git a/src/gallium/drivers/r300/r5xx_fs.c b/src/gallium/drivers/r300/r5xx_fs.c
new file mode 100644
index 0000000000..f072deab0d
--- /dev/null
+++ b/src/gallium/drivers/r300/r5xx_fs.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "r5xx_fs.h"
+
+#include "r300_reg.h"
+
+/* XXX this all should find its way back to r300_reg */
+/* Swizzle tools */
+#define R500_SWIZZLE_ZERO 4
+#define R500_SWIZZLE_HALF 5
+#define R500_SWIZZLE_ONE 6
+#define R500_SWIZ_RGB_ZERO ((4 << 0) | (4 << 3) | (4 << 6))
+#define R500_SWIZ_RGB_ONE ((6 << 0) | (6 << 3) | (6 << 6))
+#define R500_SWIZ_RGB_RGB ((0 << 0) | (1 << 3) | (2 << 6))
+#define R500_SWIZ_MOD_NEG 1
+#define R500_SWIZ_MOD_ABS 2
+#define R500_SWIZ_MOD_NEG_ABS 3
+/* Swizzles for inst2 */
+#define R500_SWIZ_TEX_STRQ(x) ((x) << 8)
+#define R500_SWIZ_TEX_RGBA(x) ((x) << 24)
+/* Swizzles for inst3 */
+#define R500_SWIZ_RGB_A(x) ((x) << 2)
+#define R500_SWIZ_RGB_B(x) ((x) << 15)
+/* Swizzles for inst4 */
+#define R500_SWIZ_ALPHA_A(x) ((x) << 14)
+#define R500_SWIZ_ALPHA_B(x) ((x) << 21)
+/* Swizzle for inst5 */
+#define R500_SWIZ_RGBA_C(x) ((x) << 14)
+#define R500_SWIZ_ALPHA_C(x) ((x) << 27)
+/* Writemasks */
+#define R500_TEX_WMASK(x) ((x) << 11)
+#define R500_ALU_WMASK(x) ((x) << 11)
+#define R500_ALU_OMASK(x) ((x) << 15)
+#define R500_W_OMASK (1 << 31)
+
+struct rX00_fragment_program_code r5xx_passthrough_fragment_shader = {
+ .code.r500.max_temp_idx = 0,
+ .code.r500.inst_end = 0,
+
+ .code.r500.inst[0].inst0 = R500_INST_TYPE_OUT |
+ R500_INST_TEX_SEM_WAIT | R500_INST_LAST |
+ R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK |
+ R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
+ .code.r500.inst[0].inst1 =
+ R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST |
+ R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST,
+ .code.r500.inst[0].inst2 =
+ R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST |
+ R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST,
+ .code.r500.inst[0].inst3 =
+ R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R |
+ R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B |
+ R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R |
+ R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B,
+ .code.r500.inst[0].inst4 =
+ R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A,
+ .code.r500.inst[0].inst5 =
+ R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 |
+ R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 |
+ R500_ALU_RGBA_A_SWIZ_0,
+};
+
+struct rX00_fragment_program_code r5xx_texture_fragment_shader = {
+ .code.r500.max_temp_idx = 0,
+ .code.r500.inst_end = 1,
+
+ .code.r500.inst[0].inst0 = R500_INST_TYPE_TEX |
+ R500_INST_TEX_SEM_WAIT |
+ R500_INST_RGB_WMASK_RGB | R500_INST_ALPHA_WMASK |
+ R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
+ .code.r500.inst[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD |
+ R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED,
+ .code.r500.inst[0].inst2 = R500_TEX_SRC_ADDR(0) |
+ R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G |
+ R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A |
+ R500_TEX_DST_ADDR(0) |
+ R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G |
+ R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A,
+ .code.r500.inst[0].inst3 = 0x0,
+ .code.r500.inst[0].inst4 = 0x0,
+ .code.r500.inst[0].inst5 = 0x0,
+
+ .code.r500.inst[1].inst0 = R500_INST_TYPE_OUT |
+ R500_INST_TEX_SEM_WAIT | R500_INST_LAST |
+ R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK |
+ R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
+ .code.r500.inst[1].inst1 =
+ R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST |
+ R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST,
+ .code.r500.inst[1].inst2 =
+ R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST |
+ R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST,
+ .code.r500.inst[1].inst3 =
+ R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R |
+ R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B |
+ R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R |
+ R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B,
+ .code.r500.inst[1].inst4 =
+ R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A,
+ .code.r500.inst[1].inst5 =
+ R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 |
+ R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 |
+ R500_ALU_RGBA_A_SWIZ_0,
+};
diff --git a/src/gallium/drivers/r300/r5xx_fs.h b/src/gallium/drivers/r300/r5xx_fs.h
new file mode 100644
index 0000000000..a4addde32b
--- /dev/null
+++ b/src/gallium/drivers/r300/r5xx_fs.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef R5XX_FS_H
+#define R5XX_FS_H
+
+#include "radeon_code.h"
+
+struct rX00_fragment_program_code r5xx_passthrough_fragment_shader;
+struct rX00_fragment_program_code r5xx_texture_fragment_shader;
+
+#endif /* R5XX_FS_H */
diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile
new file mode 100644
index 0000000000..516e3992fd
--- /dev/null
+++ b/src/gallium/drivers/softpipe/Makefile
@@ -0,0 +1,44 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = softpipe
+
+C_SOURCES = \
+ sp_fs_exec.c \
+ sp_fs_sse.c \
+ sp_fs_llvm.c \
+ sp_clear.c \
+ sp_flush.c \
+ sp_query.c \
+ sp_context.c \
+ sp_draw_arrays.c \
+ sp_prim_setup.c \
+ sp_prim_vbuf.c \
+ sp_quad_pipe.c \
+ sp_quad_alpha_test.c \
+ sp_quad_blend.c \
+ sp_quad_colormask.c \
+ sp_quad_coverage.c \
+ sp_quad_depth_test.c \
+ sp_quad_earlyz.c \
+ sp_quad_fs.c \
+ sp_quad_occlusion.c \
+ sp_quad_output.c \
+ sp_quad_stencil.c \
+ sp_quad_stipple.c \
+ sp_screen.c \
+ sp_setup.c \
+ sp_state_blend.c \
+ sp_state_clip.c \
+ sp_state_derived.c \
+ sp_state_fs.c \
+ sp_state_sampler.c \
+ sp_state_rasterizer.c \
+ sp_state_surface.c \
+ sp_state_vertex.c \
+ sp_texture.c \
+ sp_tex_sample.c \
+ sp_tile_cache.c \
+ sp_surface.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript
new file mode 100644
index 0000000000..f8720638a7
--- /dev/null
+++ b/src/gallium/drivers/softpipe/SConscript
@@ -0,0 +1,46 @@
+Import('*')
+
+env = env.Clone()
+
+softpipe = env.ConvenienceLibrary(
+ target = 'softpipe',
+ source = [
+ 'sp_fs_exec.c',
+ 'sp_fs_sse.c',
+ 'sp_fs_llvm.c',
+ 'sp_clear.c',
+ 'sp_context.c',
+ 'sp_draw_arrays.c',
+ 'sp_flush.c',
+ 'sp_prim_setup.c',
+ 'sp_prim_vbuf.c',
+ 'sp_setup.c',
+ 'sp_quad_alpha_test.c',
+ 'sp_quad_blend.c',
+ 'sp_quad_pipe.c',
+ 'sp_quad_colormask.c',
+ 'sp_quad_coverage.c',
+ 'sp_quad_depth_test.c',
+ 'sp_quad_earlyz.c',
+ 'sp_quad_fs.c',
+ 'sp_quad_occlusion.c',
+ 'sp_quad_output.c',
+ 'sp_quad_stencil.c',
+ 'sp_quad_stipple.c',
+ 'sp_query.c',
+ 'sp_screen.c',
+ 'sp_state_blend.c',
+ 'sp_state_clip.c',
+ 'sp_state_derived.c',
+ 'sp_state_fs.c',
+ 'sp_state_rasterizer.c',
+ 'sp_state_sampler.c',
+ 'sp_state_surface.c',
+ 'sp_state_vertex.c',
+ 'sp_surface.c',
+ 'sp_tex_sample.c',
+ 'sp_texture.c',
+ 'sp_tile_cache.c',
+ ])
+
+Export('softpipe') \ No newline at end of file
diff --git a/src/gallium/drivers/softpipe/sp_clear.c b/src/gallium/drivers/softpipe/sp_clear.c
new file mode 100644
index 0000000000..8fac8e6e05
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_clear.c
@@ -0,0 +1,89 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Brian Paul
+ * Michel Dänzer
+ */
+
+
+#include "pipe/p_defines.h"
+#include "util/u_pack_color.h"
+#include "sp_clear.h"
+#include "sp_context.h"
+#include "sp_tile_cache.h"
+
+
+/**
+ * Clear the given buffers to the specified values.
+ * No masking, no scissor (clear entire buffer).
+ */
+void
+softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
+ double depth, unsigned stencil)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ unsigned cv;
+ uint i;
+
+ if (softpipe->no_rast)
+ return;
+
+#if 0
+ softpipe_update_derived(softpipe); /* not needed?? */
+#endif
+
+ if (buffers & PIPE_CLEAR_COLOR) {
+ for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
+ struct pipe_surface *ps = softpipe->framebuffer.cbufs[i];
+
+ util_pack_color(rgba, ps->format, &cv);
+ sp_tile_cache_clear(softpipe->cbuf_cache[i], rgba, cv);
+
+#if !TILE_CLEAR_OPTIMIZATION
+ /* non-cached surface */
+ pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv);
+#endif
+ }
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+ static const float zero[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
+ struct pipe_surface *ps = softpipe->framebuffer.zsbuf;
+
+ cv = util_pack_z_stencil(ps->format, depth, stencil);
+ sp_tile_cache_clear(softpipe->zsbuf_cache, zero, cv);
+
+#if !TILE_CLEAR_OPTIMIZATION
+ /* non-cached surface */
+ pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv);
+#endif
+ }
+
+ softpipe->dirty_render_cache = TRUE;
+}
diff --git a/src/gallium/drivers/softpipe/sp_clear.h b/src/gallium/drivers/softpipe/sp_clear.h
new file mode 100644
index 0000000000..9be3b86fe9
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_clear.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Brian Paul
+ */
+
+#ifndef SP_CLEAR_H
+#define SP_CLEAR_H
+
+struct pipe_context;
+
+extern void
+softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
+ double depth, unsigned stencil);
+
+
+#endif /* SP_CLEAR_H */
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
new file mode 100644
index 0000000000..c699c433e9
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -0,0 +1,330 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2008 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "sp_clear.h"
+#include "sp_context.h"
+#include "sp_flush.h"
+#include "sp_prim_setup.h"
+#include "sp_prim_vbuf.h"
+#include "sp_state.h"
+#include "sp_surface.h"
+#include "sp_tile_cache.h"
+#include "sp_texture.h"
+#include "sp_winsys.h"
+#include "sp_query.h"
+
+
+
+/**
+ * Map any drawing surfaces which aren't already mapped
+ */
+void
+softpipe_map_transfers(struct softpipe_context *sp)
+{
+ unsigned i;
+
+ for (i = 0; i < sp->framebuffer.nr_cbufs; i++) {
+ sp_tile_cache_map_transfers(sp->cbuf_cache[i]);
+ }
+
+ sp_tile_cache_map_transfers(sp->zsbuf_cache);
+}
+
+
+/**
+ * Unmap any mapped drawing surfaces
+ */
+void
+softpipe_unmap_transfers(struct softpipe_context *sp)
+{
+ uint i;
+
+ for (i = 0; i < sp->framebuffer.nr_cbufs; i++)
+ sp_flush_tile_cache(sp, sp->cbuf_cache[i]);
+ sp_flush_tile_cache(sp, sp->zsbuf_cache);
+
+ for (i = 0; i < sp->framebuffer.nr_cbufs; i++) {
+ sp_tile_cache_unmap_transfers(sp->cbuf_cache[i]);
+ }
+ sp_tile_cache_unmap_transfers(sp->zsbuf_cache);
+}
+
+
+static void
+softpipe_destroy( struct pipe_context *pipe )
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+ uint i;
+
+ if (softpipe->draw)
+ draw_destroy( softpipe->draw );
+
+ for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
+ softpipe->quad[i].polygon_stipple->destroy( softpipe->quad[i].polygon_stipple );
+ softpipe->quad[i].earlyz->destroy( softpipe->quad[i].earlyz );
+ softpipe->quad[i].shade->destroy( softpipe->quad[i].shade );
+ softpipe->quad[i].alpha_test->destroy( softpipe->quad[i].alpha_test );
+ softpipe->quad[i].depth_test->destroy( softpipe->quad[i].depth_test );
+ softpipe->quad[i].stencil_test->destroy( softpipe->quad[i].stencil_test );
+ softpipe->quad[i].occlusion->destroy( softpipe->quad[i].occlusion );
+ softpipe->quad[i].coverage->destroy( softpipe->quad[i].coverage );
+ softpipe->quad[i].blend->destroy( softpipe->quad[i].blend );
+ softpipe->quad[i].colormask->destroy( softpipe->quad[i].colormask );
+ softpipe->quad[i].output->destroy( softpipe->quad[i].output );
+ }
+
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
+ sp_destroy_tile_cache(softpipe->cbuf_cache[i]);
+ sp_destroy_tile_cache(softpipe->zsbuf_cache);
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ sp_destroy_tile_cache(softpipe->tex_cache[i]);
+
+ for (i = 0; i < Elements(softpipe->constants); i++) {
+ if (softpipe->constants[i].buffer) {
+ pipe_buffer_reference(&softpipe->constants[i].buffer, NULL);
+ }
+ }
+
+ FREE( softpipe );
+}
+
+
+/**
+ * if (the texture is being used as a framebuffer surface)
+ * return PIPE_REFERENCED_FOR_WRITE
+ * else if (the texture is a bound texture source)
+ * return PIPE_REFERENCED_FOR_READ XXX not done yet
+ * else
+ * return PIPE_UNREFERENCED
+ */
+static unsigned int
+softpipe_is_texture_referenced( struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level)
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+ unsigned i;
+
+ if (softpipe->dirty_render_cache) {
+ for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
+ if (softpipe->framebuffer.cbufs[i] &&
+ softpipe->framebuffer.cbufs[i]->texture == texture) {
+ return PIPE_REFERENCED_FOR_WRITE;
+ }
+ }
+ if (softpipe->framebuffer.zsbuf &&
+ softpipe->framebuffer.zsbuf->texture == texture) {
+ return PIPE_REFERENCED_FOR_WRITE;
+ }
+ }
+
+ /* FIXME: we also need to do the same for the texture cache */
+
+ return PIPE_UNREFERENCED;
+}
+
+
+static unsigned int
+softpipe_is_buffer_referenced( struct pipe_context *pipe,
+ struct pipe_buffer *buf)
+{
+ return PIPE_UNREFERENCED;
+}
+
+
+struct pipe_context *
+softpipe_create( struct pipe_screen *screen )
+{
+ struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context);
+ uint i;
+
+ util_init_math();
+
+#ifdef PIPE_ARCH_X86
+ softpipe->use_sse = !debug_get_bool_option( "GALLIUM_NOSSE", FALSE );
+#else
+ softpipe->use_sse = FALSE;
+#endif
+
+ softpipe->dump_fs = debug_get_bool_option( "GALLIUM_DUMP_FS", FALSE );
+
+ softpipe->pipe.winsys = screen->winsys;
+ softpipe->pipe.screen = screen;
+ softpipe->pipe.destroy = softpipe_destroy;
+
+ /* state setters */
+ softpipe->pipe.create_blend_state = softpipe_create_blend_state;
+ softpipe->pipe.bind_blend_state = softpipe_bind_blend_state;
+ softpipe->pipe.delete_blend_state = softpipe_delete_blend_state;
+
+ softpipe->pipe.create_sampler_state = softpipe_create_sampler_state;
+ softpipe->pipe.bind_sampler_states = softpipe_bind_sampler_states;
+ softpipe->pipe.delete_sampler_state = softpipe_delete_sampler_state;
+
+ softpipe->pipe.create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state;
+ softpipe->pipe.bind_depth_stencil_alpha_state = softpipe_bind_depth_stencil_state;
+ softpipe->pipe.delete_depth_stencil_alpha_state = softpipe_delete_depth_stencil_state;
+
+ softpipe->pipe.create_rasterizer_state = softpipe_create_rasterizer_state;
+ softpipe->pipe.bind_rasterizer_state = softpipe_bind_rasterizer_state;
+ softpipe->pipe.delete_rasterizer_state = softpipe_delete_rasterizer_state;
+
+ softpipe->pipe.create_fs_state = softpipe_create_fs_state;
+ softpipe->pipe.bind_fs_state = softpipe_bind_fs_state;
+ softpipe->pipe.delete_fs_state = softpipe_delete_fs_state;
+
+ softpipe->pipe.create_vs_state = softpipe_create_vs_state;
+ softpipe->pipe.bind_vs_state = softpipe_bind_vs_state;
+ softpipe->pipe.delete_vs_state = softpipe_delete_vs_state;
+
+ softpipe->pipe.set_blend_color = softpipe_set_blend_color;
+ softpipe->pipe.set_clip_state = softpipe_set_clip_state;
+ softpipe->pipe.set_constant_buffer = softpipe_set_constant_buffer;
+ softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;
+ softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple;
+ softpipe->pipe.set_scissor_state = softpipe_set_scissor_state;
+ softpipe->pipe.set_sampler_textures = softpipe_set_sampler_textures;
+ softpipe->pipe.set_viewport_state = softpipe_set_viewport_state;
+
+ softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers;
+ softpipe->pipe.set_vertex_elements = softpipe_set_vertex_elements;
+
+ softpipe->pipe.draw_arrays = softpipe_draw_arrays;
+ softpipe->pipe.draw_elements = softpipe_draw_elements;
+ softpipe->pipe.draw_range_elements = softpipe_draw_range_elements;
+ softpipe->pipe.set_edgeflags = softpipe_set_edgeflags;
+
+
+ softpipe->pipe.clear = softpipe_clear;
+ softpipe->pipe.flush = softpipe_flush;
+
+ softpipe->pipe.is_texture_referenced = softpipe_is_texture_referenced;
+ softpipe->pipe.is_buffer_referenced = softpipe_is_buffer_referenced;
+
+ softpipe_init_query_funcs( softpipe );
+
+ /*
+ * Alloc caches for accessing drawing surfaces and textures.
+ * Must be before quad stage setup!
+ */
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
+ softpipe->cbuf_cache[i] = sp_create_tile_cache( screen );
+ softpipe->zsbuf_cache = sp_create_tile_cache( screen );
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ softpipe->tex_cache[i] = sp_create_tile_cache( screen );
+
+
+ /* setup quad rendering stages */
+ for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
+ softpipe->quad[i].polygon_stipple = sp_quad_polygon_stipple_stage(softpipe);
+ softpipe->quad[i].earlyz = sp_quad_earlyz_stage(softpipe);
+ softpipe->quad[i].shade = sp_quad_shade_stage(softpipe);
+ softpipe->quad[i].alpha_test = sp_quad_alpha_test_stage(softpipe);
+ softpipe->quad[i].depth_test = sp_quad_depth_test_stage(softpipe);
+ softpipe->quad[i].stencil_test = sp_quad_stencil_test_stage(softpipe);
+ softpipe->quad[i].occlusion = sp_quad_occlusion_stage(softpipe);
+ softpipe->quad[i].coverage = sp_quad_coverage_stage(softpipe);
+ softpipe->quad[i].blend = sp_quad_blend_stage(softpipe);
+ softpipe->quad[i].colormask = sp_quad_colormask_stage(softpipe);
+ softpipe->quad[i].output = sp_quad_output_stage(softpipe);
+ }
+
+ /* vertex shader samplers */
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ softpipe->tgsi.vert_samplers[i].base.get_samples = sp_get_samples_vertex;
+ softpipe->tgsi.vert_samplers[i].unit = i;
+ softpipe->tgsi.vert_samplers[i].sp = softpipe;
+ softpipe->tgsi.vert_samplers[i].cache = softpipe->tex_cache[i];
+ softpipe->tgsi.vert_samplers_list[i] = &softpipe->tgsi.vert_samplers[i];
+ }
+
+ /* fragment shader samplers */
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ softpipe->tgsi.frag_samplers[i].base.get_samples = sp_get_samples_fragment;
+ softpipe->tgsi.frag_samplers[i].unit = i;
+ softpipe->tgsi.frag_samplers[i].sp = softpipe;
+ softpipe->tgsi.frag_samplers[i].cache = softpipe->tex_cache[i];
+ softpipe->tgsi.frag_samplers_list[i] = &softpipe->tgsi.frag_samplers[i];
+ }
+
+ /*
+ * Create drawing context and plug our rendering stage into it.
+ */
+ softpipe->draw = draw_create();
+ if (!softpipe->draw)
+ goto fail;
+
+ draw_texture_samplers(softpipe->draw,
+ PIPE_MAX_SAMPLERS,
+ (struct tgsi_sampler **)
+ softpipe->tgsi.vert_samplers_list);
+
+ softpipe->setup = sp_draw_render_stage(softpipe);
+ if (!softpipe->setup)
+ goto fail;
+
+ if (debug_get_bool_option( "SP_NO_RAST", FALSE ))
+ softpipe->no_rast = TRUE;
+
+ if (debug_get_bool_option( "SP_NO_VBUF", FALSE )) {
+ /* Deprecated path -- vbuf is the intended interface to the draw module:
+ */
+ draw_set_rasterize_stage(softpipe->draw, softpipe->setup);
+ }
+ else {
+ sp_init_vbuf(softpipe);
+ }
+
+ /* plug in AA line/point stages */
+ draw_install_aaline_stage(softpipe->draw, &softpipe->pipe);
+ draw_install_aapoint_stage(softpipe->draw, &softpipe->pipe);
+
+#if USE_DRAW_STAGE_PSTIPPLE
+ /* Do polygon stipple w/ texture map + frag prog? */
+ draw_install_pstipple_stage(softpipe->draw, &softpipe->pipe);
+#endif
+
+ sp_init_surface_functions(softpipe);
+
+ return &softpipe->pipe;
+
+ fail:
+ softpipe_destroy(&softpipe->pipe);
+ return NULL;
+}
+
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
new file mode 100644
index 0000000000..7888c2f644
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -0,0 +1,168 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_CONTEXT_H
+#define SP_CONTEXT_H
+
+#include "pipe/p_context.h"
+
+#include "draw/draw_vertex.h"
+
+#include "sp_quad_pipe.h"
+#include "sp_tex_sample.h"
+
+
+/**
+ * This is a temporary variable for testing draw-stage polygon stipple.
+ * If zero, do stipple in sp_quad_stipple.c
+ */
+#define USE_DRAW_STAGE_PSTIPPLE 1
+
+/* Number of threads working on individual quads.
+ * Setting to 1 disables this feature.
+ */
+#define SP_NUM_QUAD_THREADS 1
+
+struct softpipe_vbuf_render;
+struct draw_context;
+struct draw_stage;
+struct softpipe_tile_cache;
+struct sp_fragment_shader;
+struct sp_vertex_shader;
+
+
+struct softpipe_context {
+ struct pipe_context pipe; /**< base class */
+
+ /** Constant state objects */
+ const struct pipe_blend_state *blend;
+ const struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
+ const struct pipe_depth_stencil_alpha_state *depth_stencil;
+ const struct pipe_rasterizer_state *rasterizer;
+ const struct sp_fragment_shader *fs;
+ const struct sp_vertex_shader *vs;
+
+ /** Other rendering state */
+ struct pipe_blend_color blend_color;
+ struct pipe_clip_state clip;
+ struct pipe_constant_buffer constants[PIPE_SHADER_TYPES];
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_poly_stipple poly_stipple;
+ struct pipe_scissor_state scissor;
+ struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
+ struct pipe_viewport_state viewport;
+ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
+
+ unsigned num_samplers;
+ unsigned num_textures;
+ unsigned num_vertex_elements;
+ unsigned num_vertex_buffers;
+
+ unsigned dirty; /**< Mask of SP_NEW_x flags */
+
+ /* Counter for occlusion queries. Note this supports overlapping
+ * queries.
+ */
+ uint64_t occlusion_count;
+ unsigned active_query_count;
+
+ /** Mapped vertex buffers */
+ ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS];
+
+ /** Mapped constant buffers */
+ void *mapped_constants[PIPE_SHADER_TYPES];
+
+ /** Vertex format */
+ struct vertex_info vertex_info;
+ struct vertex_info vertex_info_vbuf;
+
+ /** Which vertex shader output slot contains point size */
+ int psize_slot;
+
+ unsigned reduced_api_prim; /**< PIPE_PRIM_POINTS, _LINES or _TRIANGLES */
+
+ /** Derived from scissor and surface bounds: */
+ struct pipe_scissor_state cliprect;
+
+ unsigned line_stipple_counter;
+
+ /** Software quad rendering pipeline */
+ struct {
+ struct quad_stage *polygon_stipple;
+ struct quad_stage *earlyz;
+ struct quad_stage *shade;
+ struct quad_stage *alpha_test;
+ struct quad_stage *stencil_test;
+ struct quad_stage *depth_test;
+ struct quad_stage *occlusion;
+ struct quad_stage *coverage;
+ struct quad_stage *blend;
+ struct quad_stage *colormask;
+ struct quad_stage *output;
+
+ struct quad_stage *first; /**< points to one of the above stages */
+ } quad[SP_NUM_QUAD_THREADS];
+
+ /** TGSI exec things */
+ struct {
+ struct sp_shader_sampler vert_samplers[PIPE_MAX_SAMPLERS];
+ struct sp_shader_sampler *vert_samplers_list[PIPE_MAX_SAMPLERS];
+ struct sp_shader_sampler frag_samplers[PIPE_MAX_SAMPLERS];
+ struct sp_shader_sampler *frag_samplers_list[PIPE_MAX_SAMPLERS];
+ } tgsi;
+
+ /** The primitive drawing context */
+ struct draw_context *draw;
+ struct draw_stage *setup;
+ struct draw_stage *vbuf;
+ struct softpipe_vbuf_render *vbuf_render;
+
+ boolean dirty_render_cache;
+
+ struct softpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS];
+ struct softpipe_tile_cache *zsbuf_cache;
+
+ struct softpipe_tile_cache *tex_cache[PIPE_MAX_SAMPLERS];
+
+ unsigned use_sse : 1;
+ unsigned dump_fs : 1;
+ unsigned no_rast : 1;
+};
+
+
+static INLINE struct softpipe_context *
+softpipe_context( struct pipe_context *pipe )
+{
+ return (struct softpipe_context *)pipe;
+}
+
+#endif /* SP_CONTEXT_H */
+
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
new file mode 100644
index 0000000000..d4045816d0
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -0,0 +1,194 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Brian Paul
+ * Keith Whitwell
+ */
+
+
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_prim.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+
+#include "draw/draw_context.h"
+
+
+
+static void
+softpipe_map_constant_buffers(struct softpipe_context *sp)
+{
+ struct pipe_winsys *ws = sp->pipe.winsys;
+ uint i, size;
+
+ for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+ if (sp->constants[i].buffer && sp->constants[i].buffer->size)
+ sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ }
+
+ if (sp->constants[PIPE_SHADER_VERTEX].buffer)
+ size = sp->constants[PIPE_SHADER_VERTEX].buffer->size;
+ else
+ size = 0;
+
+ draw_set_mapped_constant_buffer(sp->draw,
+ sp->mapped_constants[PIPE_SHADER_VERTEX],
+ size);
+}
+
+
+static void
+softpipe_unmap_constant_buffers(struct softpipe_context *sp)
+{
+ struct pipe_winsys *ws = sp->pipe.winsys;
+ uint i;
+
+ /* really need to flush all prims since the vert/frag shaders const buffers
+ * are going away now.
+ */
+ draw_flush(sp->draw);
+
+ draw_set_mapped_constant_buffer(sp->draw, NULL, 0);
+
+ for (i = 0; i < 2; i++) {
+ if (sp->constants[i].buffer && sp->constants[i].buffer->size)
+ ws->buffer_unmap(ws, sp->constants[i].buffer);
+ sp->mapped_constants[i] = NULL;
+ }
+}
+
+
+boolean
+softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
+ unsigned start, unsigned count)
+{
+ return softpipe_draw_elements(pipe, NULL, 0, mode, start, count);
+}
+
+
+/**
+ * Draw vertex arrays, with optional indexing.
+ * Basically, map the vertex buffers (and drawing surfaces), then hand off
+ * the drawing to the 'draw' module.
+ */
+boolean
+softpipe_draw_range_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned min_index,
+ unsigned max_index,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct softpipe_context *sp = softpipe_context(pipe);
+ struct draw_context *draw = sp->draw;
+ unsigned i;
+
+ sp->reduced_api_prim = u_reduced_prim(mode);
+
+ if (sp->dirty)
+ softpipe_update_derived( sp );
+
+ softpipe_map_transfers(sp);
+ softpipe_map_constant_buffers(sp);
+
+ /*
+ * Map vertex buffers
+ */
+ for (i = 0; i < sp->num_vertex_buffers; i++) {
+ void *buf
+ = pipe_buffer_map(pipe->screen,
+ sp->vertex_buffer[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_vertex_buffer(draw, i, buf);
+ }
+
+ /* Map index buffer, if present */
+ if (indexBuffer) {
+ void *mapped_indexes
+ = pipe_buffer_map(pipe->screen, indexBuffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer_range(draw, indexSize,
+ min_index,
+ max_index,
+ mapped_indexes);
+ }
+ else {
+ /* no index/element buffer */
+ draw_set_mapped_element_buffer_range(draw, 0, start,
+ start + count - 1, NULL);
+ }
+
+ /* draw! */
+ draw_arrays(draw, mode, start, count);
+
+ /*
+ * unmap vertex/index buffers - will cause draw module to flush
+ */
+ for (i = 0; i < sp->num_vertex_buffers; i++) {
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer);
+ }
+ if (indexBuffer) {
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ pipe_buffer_unmap(pipe->screen, indexBuffer);
+ }
+
+
+ /* Note: leave drawing surfaces mapped */
+ softpipe_unmap_constant_buffers(sp);
+
+ sp->dirty_render_cache = TRUE;
+
+ return TRUE;
+}
+
+
+boolean
+softpipe_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+{
+ return softpipe_draw_range_elements( pipe, indexBuffer,
+ indexSize,
+ 0, 0xffffffff,
+ mode, start, count );
+}
+
+
+void
+softpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags)
+{
+ struct softpipe_context *sp = softpipe_context(pipe);
+ draw_set_edgeflags(sp->draw, edgeflags);
+}
diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c
new file mode 100644
index 0000000000..4a14d49686
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_flush.c
@@ -0,0 +1,94 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "pipe/p_defines.h"
+#include "draw/draw_context.h"
+#include "sp_flush.h"
+#include "sp_context.h"
+#include "sp_surface.h"
+#include "sp_state.h"
+#include "sp_tile_cache.h"
+#include "sp_winsys.h"
+
+
+void
+softpipe_flush( struct pipe_context *pipe,
+ unsigned flags,
+ struct pipe_fence_handle **fence )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ uint i;
+
+ draw_flush(softpipe->draw);
+
+ if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
+ for (i = 0; i < softpipe->num_textures; i++) {
+ sp_flush_tile_cache(softpipe, softpipe->tex_cache[i]);
+ }
+ }
+
+ if (flags & PIPE_FLUSH_RENDER_CACHE) {
+ for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++)
+ if (softpipe->cbuf_cache[i])
+ sp_flush_tile_cache(softpipe, softpipe->cbuf_cache[i]);
+
+ if (softpipe->zsbuf_cache)
+ sp_flush_tile_cache(softpipe, softpipe->zsbuf_cache);
+
+ /* Need this call for hardware buffers before swapbuffers.
+ *
+ * there should probably be another/different flush-type function
+ * that's called before swapbuffers because we don't always want
+ * to unmap surfaces when flushing.
+ */
+ softpipe_unmap_transfers(softpipe);
+
+ softpipe->dirty_render_cache = FALSE;
+ }
+
+ /* Enable to dump BMPs of the color/depth buffers each frame */
+#if 0
+ if(flags & PIPE_FLUSH_FRAME) {
+ static unsigned frame_no = 1;
+ static char filename[256];
+ util_snprintf(filename, sizeof(filename), "cbuf_%u.bmp", frame_no);
+ debug_dump_surface_bmp(filename, softpipe->framebuffer.cbufs[0]);
+ util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no);
+ debug_dump_surface_bmp(filename, softpipe->framebuffer.zsbuf);
+ ++frame_no;
+ }
+#endif
+
+ if (fence)
+ *fence = NULL;
+}
+
diff --git a/src/gallium/drivers/softpipe/sp_flush.h b/src/gallium/drivers/softpipe/sp_flush.h
new file mode 100644
index 0000000000..68d9b5fa83
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_flush.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SP_FLUSH_H
+#define SP_FLUSH_H
+
+struct pipe_context;
+struct pipe_fence_handle;
+
+void softpipe_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence);
+
+#endif
diff --git a/src/gallium/drivers/softpipe/sp_fs.h b/src/gallium/drivers/softpipe/sp_fs.h
new file mode 100644
index 0000000000..4792ace3a3
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_fs.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_FS_H
+#define SP_FS_H
+
+struct sp_fragment_shader *
+softpipe_create_fs_exec(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ);
+
+struct sp_fragment_shader *
+softpipe_create_fs_sse(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ);
+
+struct sp_fragment_shader *
+softpipe_create_fs_llvm(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ);
+
+struct tgsi_interp_coef;
+struct tgsi_exec_vector;
+
+void sp_setup_pos_vector(const struct tgsi_interp_coef *coef,
+ float x, float y,
+ struct tgsi_exec_vector *quadpos);
+
+
+#endif
diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c
new file mode 100644
index 0000000000..9ee86fe787
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_fs_exec.c
@@ -0,0 +1,162 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Execute fragment shader using the TGSI interpreter.
+ */
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_fs.h"
+#include "sp_quad.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_exec.h"
+#include "tgsi/tgsi_parse.h"
+
+
+/**
+ * Subclass of sp_fragment_shader
+ */
+struct sp_exec_fragment_shader
+{
+ struct sp_fragment_shader base;
+ /* No other members for now */
+};
+
+
+/** cast wrapper */
+static INLINE struct sp_exec_fragment_shader *
+sp_exec_fragment_shader(const struct sp_fragment_shader *base)
+{
+ return (struct sp_exec_fragment_shader *) base;
+}
+
+
+/**
+ * Compute quad X,Y,Z,W for the four fragments in a quad.
+ *
+ * This should really be part of the compiled shader.
+ */
+void
+sp_setup_pos_vector(const struct tgsi_interp_coef *coef,
+ float x, float y,
+ struct tgsi_exec_vector *quadpos)
+{
+ uint chan;
+ /* do X */
+ quadpos->xyzw[0].f[0] = x;
+ quadpos->xyzw[0].f[1] = x + 1;
+ quadpos->xyzw[0].f[2] = x;
+ quadpos->xyzw[0].f[3] = x + 1;
+
+ /* do Y */
+ quadpos->xyzw[1].f[0] = y;
+ quadpos->xyzw[1].f[1] = y;
+ quadpos->xyzw[1].f[2] = y + 1;
+ quadpos->xyzw[1].f[3] = y + 1;
+
+ /* do Z and W for all fragments in the quad */
+ for (chan = 2; chan < 4; chan++) {
+ const float dadx = coef->dadx[chan];
+ const float dady = coef->dady[chan];
+ const float a0 = coef->a0[chan] + dadx * x + dady * y;
+ quadpos->xyzw[chan].f[0] = a0;
+ quadpos->xyzw[chan].f[1] = a0 + dadx;
+ quadpos->xyzw[chan].f[2] = a0 + dady;
+ quadpos->xyzw[chan].f[3] = a0 + dadx + dady;
+ }
+}
+
+
+static void
+exec_prepare( const struct sp_fragment_shader *base,
+ struct tgsi_exec_machine *machine,
+ struct tgsi_sampler **samplers )
+{
+ /*
+ * Bind tokens/shader to the interpreter's machine state.
+ * Avoid redundant binding.
+ */
+ if (machine->Tokens != base->shader.tokens) {
+ tgsi_exec_machine_bind_shader( machine,
+ base->shader.tokens,
+ PIPE_MAX_SAMPLERS,
+ samplers );
+ }
+}
+
+
+/* TODO: hide the machine struct in here somewhere, remove from this
+ * interface:
+ */
+static unsigned
+exec_run( const struct sp_fragment_shader *base,
+ struct tgsi_exec_machine *machine,
+ struct quad_header *quad )
+{
+ /* Compute X, Y, Z, W vals for this quad */
+ sp_setup_pos_vector(quad->posCoef,
+ (float)quad->input.x0, (float)quad->input.y0,
+ &machine->QuadPos);
+
+ return tgsi_exec_machine_run( machine );
+}
+
+
+static void
+exec_delete( struct sp_fragment_shader *base )
+{
+ FREE((void *) base->shader.tokens);
+ FREE(base);
+}
+
+
+struct sp_fragment_shader *
+softpipe_create_fs_exec(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ)
+{
+ struct sp_exec_fragment_shader *shader;
+
+ /* Decide whether we'll be codegenerating this shader and if so do
+ * that now.
+ */
+
+ shader = CALLOC_STRUCT(sp_exec_fragment_shader);
+ if (!shader)
+ return NULL;
+
+ /* we need to keep a local copy of the tokens */
+ shader->base.shader.tokens = tgsi_dup_tokens(templ->tokens);
+ shader->base.prepare = exec_prepare;
+ shader->base.run = exec_run;
+ shader->base.delete = exec_delete;
+
+ return &shader->base;
+}
diff --git a/src/gallium/drivers/softpipe/sp_fs_llvm.c b/src/gallium/drivers/softpipe/sp_fs_llvm.c
new file mode 100644
index 0000000000..95c0d982d1
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_fs_llvm.c
@@ -0,0 +1,205 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Execute fragment shader using LLVM code generation.
+ * Authors:
+ * Zack Rusin
+ */
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_fs.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_sse2.h"
+
+#if 0
+
+/**
+ * Subclass of sp_fragment_shader
+ */
+struct sp_llvm_fragment_shader
+{
+ struct sp_fragment_shader base;
+ struct gallivm_prog *llvm_prog;
+};
+
+
+static void
+shade_quad_llvm(struct quad_stage *qs,
+ struct quad_header *quad)
+{
+ struct quad_shade_stage *qss = quad_shade_stage(qs);
+ struct softpipe_context *softpipe = qs->softpipe;
+ float dests[4][16][4] ALIGN16_ATTRIB;
+ float inputs[4][16][4] ALIGN16_ATTRIB;
+ const float fx = (float) quad->x0;
+ const float fy = (float) quad->y0;
+ struct gallivm_prog *llvm = qss->llvm_prog;
+
+ inputs[0][0][0] = fx;
+ inputs[1][0][0] = fx + 1.0f;
+ inputs[2][0][0] = fx;
+ inputs[3][0][0] = fx + 1.0f;
+
+ inputs[0][0][1] = fy;
+ inputs[1][0][1] = fy;
+ inputs[2][0][1] = fy + 1.0f;
+ inputs[3][0][1] = fy + 1.0f;
+
+
+ gallivm_prog_inputs_interpolate(llvm, inputs, quad->coef);
+
+#if DLLVM
+ debug_printf("MASK = %d\n", quad->mask);
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ debug_printf("IN(%d,%d) [%f %f %f %f]\n", i, j,
+ inputs[i][j][0], inputs[i][j][1], inputs[i][j][2], inputs[i][j][3]);
+ }
+ }
+#endif
+
+ quad->mask &=
+ gallivm_fragment_shader_exec(llvm, fx, fy, dests, inputs,
+ softpipe->mapped_constants[PIPE_SHADER_FRAGMENT],
+ qss->samplers);
+#if DLLVM
+ debug_printf("OUT LLVM = 1[%f %f %f %f], 2[%f %f %f %f]\n",
+ dests[0][0][0], dests[0][0][1], dests[0][0][2], dests[0][0][3],
+ dests[0][1][0], dests[0][1][1], dests[0][1][2], dests[0][1][3]);
+#endif
+
+ /* store result color */
+ if (qss->colorOutSlot >= 0) {
+ unsigned i;
+ /* XXX need to handle multiple color outputs someday */
+ allvmrt(qss->stage.softpipe->fs->info.output_semantic_name[qss->colorOutSlot]
+ == TGSI_SEMANTIC_COLOR);
+ for (i = 0; i < QUAD_SIZE; ++i) {
+ quad->outputs.color[0][0][i] = dests[i][qss->colorOutSlot][0];
+ quad->outputs.color[0][1][i] = dests[i][qss->colorOutSlot][1];
+ quad->outputs.color[0][2][i] = dests[i][qss->colorOutSlot][2];
+ quad->outputs.color[0][3][i] = dests[i][qss->colorOutSlot][3];
+ }
+ }
+#if DLLVM
+ for (int i = 0; i < QUAD_SIZE; ++i) {
+ debug_printf("QLLVM%d(%d) [%f, %f, %f, %f]\n", i, qss->colorOutSlot,
+ quad->outputs.color[0][0][i],
+ quad->outputs.color[0][1][i],
+ quad->outputs.color[0][2][i],
+ quad->outputs.color[0][3][i]);
+ }
+#endif
+
+ /* store result Z */
+ if (qss->depthOutSlot >= 0) {
+ /* output[slot] is new Z */
+ uint i;
+ for (i = 0; i < 4; i++) {
+ quad->outputs.depth[i] = dests[i][0][2];
+ }
+ }
+ else {
+ /* copy input Z (which was interpolated by the executor) to output Z */
+ uint i;
+ for (i = 0; i < 4; i++) {
+ quad->outputs.depth[i] = inputs[i][0][2];
+ }
+ }
+#if DLLVM
+ debug_printf("D [%f, %f, %f, %f] mask = %d\n",
+ quad->outputs.depth[0],
+ quad->outputs.depth[1],
+ quad->outputs.depth[2],
+ quad->outputs.depth[3], quad->mask);
+#endif
+
+ /* shader may cull fragments */
+ if( quad->mask ) {
+ qs->next->run( qs->next, quad );
+ }
+}
+
+
+unsigned
+run_llvm_fs( const struct sp_fragment_shader *base,
+ struct foo *machine )
+{
+}
+
+
+void
+delete_llvm_fs( struct sp_fragment_shader *base )
+{
+ FREE(base);
+}
+
+
+struct sp_fragment_shader *
+softpipe_create_fs_llvm(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ)
+{
+ struct sp_llvm_fragment_shader *shader = NULL;
+
+ /* LLVM fragment shaders currently disabled:
+ */
+ state = CALLOC_STRUCT(sp_llvm_shader_state);
+ if (!state)
+ return NULL;
+
+ state->llvm_prog = 0;
+
+ if (!gallivm_global_cpu_engine()) {
+ gallivm_cpu_engine_create(state->llvm_prog);
+ }
+ else
+ gallivm_cpu_jit_compile(gallivm_global_cpu_engine(), state->llvm_prog);
+
+ if (shader) {
+ shader->base.run = run_llvm_fs;
+ shader->base.delete = delete_llvm_fs;
+ }
+
+ return shader;
+}
+
+
+#else
+
+struct sp_fragment_shader *
+softpipe_create_fs_llvm(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ)
+{
+ return NULL;
+}
+
+#endif
diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c
new file mode 100644
index 0000000000..f4fa0905d7
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_fs_sse.c
@@ -0,0 +1,169 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Execute fragment shader using runtime SSE code generation.
+ */
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_fs.h"
+#include "sp_quad.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_exec.h"
+#include "tgsi/tgsi_sse2.h"
+
+
+#if defined(PIPE_ARCH_X86)
+
+#include "rtasm/rtasm_x86sse.h"
+
+
+
+/**
+ * Subclass of sp_fragment_shader
+ */
+struct sp_sse_fragment_shader
+{
+ struct sp_fragment_shader base;
+ struct x86_function sse2_program;
+ tgsi_sse2_fs_function func;
+ float immediates[TGSI_EXEC_NUM_IMMEDIATES][4];
+};
+
+
+/** cast wrapper */
+static INLINE struct sp_sse_fragment_shader *
+sp_sse_fragment_shader(const struct sp_fragment_shader *base)
+{
+ return (struct sp_sse_fragment_shader *) base;
+}
+
+
+static void
+fs_sse_prepare( const struct sp_fragment_shader *base,
+ struct tgsi_exec_machine *machine,
+ struct tgsi_sampler **samplers )
+{
+ machine->Samplers = samplers;
+}
+
+
+/* TODO: codegenerate the whole run function, skip this wrapper.
+ * TODO: break dependency on tgsi_exec_machine struct
+ * TODO: push Position calculation into the generated shader
+ * TODO: process >1 quad at a time
+ */
+static unsigned
+fs_sse_run( const struct sp_fragment_shader *base,
+ struct tgsi_exec_machine *machine,
+ struct quad_header *quad )
+{
+ struct sp_sse_fragment_shader *shader = sp_sse_fragment_shader(base);
+
+ /* Compute X, Y, Z, W vals for this quad -- place in temp[0] for now */
+ sp_setup_pos_vector(quad->posCoef,
+ (float)quad->input.x0, (float)quad->input.y0,
+ machine->Temps);
+
+ /* init kill mask */
+ tgsi_set_kill_mask(machine, 0x0);
+ tgsi_set_exec_mask(machine, 1, 1, 1, 1);
+
+ shader->func( machine,
+ machine->Consts,
+ (const float (*)[4])shader->immediates,
+ machine->InterpCoefs
+ // , &machine->QuadPos
+ );
+
+ return ~(machine->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0]);
+}
+
+
+static void
+fs_sse_delete( struct sp_fragment_shader *base )
+{
+ struct sp_sse_fragment_shader *shader = sp_sse_fragment_shader(base);
+
+ x86_release_func( &shader->sse2_program );
+ FREE(shader);
+}
+
+
+struct sp_fragment_shader *
+softpipe_create_fs_sse(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ)
+{
+ struct sp_sse_fragment_shader *shader;
+
+ if (!softpipe->use_sse)
+ return NULL;
+
+ shader = CALLOC_STRUCT(sp_sse_fragment_shader);
+ if (!shader)
+ return NULL;
+
+ x86_init_func( &shader->sse2_program );
+
+ if (!tgsi_emit_sse2( templ->tokens, &shader->sse2_program,
+ shader->immediates, FALSE )) {
+ FREE(shader);
+ return NULL;
+ }
+
+ shader->func = (tgsi_sse2_fs_function) x86_get_func( &shader->sse2_program );
+ if (!shader->func) {
+ x86_release_func( &shader->sse2_program );
+ FREE(shader);
+ return NULL;
+ }
+
+ shader->base.shader.tokens = NULL; /* don't hold reference to templ->tokens */
+ shader->base.prepare = fs_sse_prepare;
+ shader->base.run = fs_sse_run;
+ shader->base.delete = fs_sse_delete;
+
+ return &shader->base;
+}
+
+
+#else
+
+/* Maybe put this variant in the header file.
+ */
+struct sp_fragment_shader *
+softpipe_create_fs_sse(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ)
+{
+ return NULL;
+}
+
+#endif
diff --git a/src/gallium/drivers/softpipe/sp_prim_setup.c b/src/gallium/drivers/softpipe/sp_prim_setup.c
new file mode 100644
index 0000000000..038ff04d4f
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_prim_setup.c
@@ -0,0 +1,190 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief A draw stage that drives our triangle setup routines from
+ * within the draw pipeline. One of two ways to drive setup, the
+ * other being in sp_prim_vbuf.c.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Brian Paul
+ */
+
+
+#include "sp_context.h"
+#include "sp_setup.h"
+#include "sp_state.h"
+#include "sp_prim_setup.h"
+#include "draw/draw_pipe.h"
+#include "draw/draw_vertex.h"
+#include "util/u_memory.h"
+
+/**
+ * Triangle setup info (derived from draw_stage).
+ * Also used for line drawing (taking some liberties).
+ */
+struct setup_stage {
+ struct draw_stage stage; /**< This must be first (base class) */
+
+ struct setup_context *setup;
+};
+
+
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct setup_stage *setup_stage( struct draw_stage *stage )
+{
+ return (struct setup_stage *)stage;
+}
+
+
+typedef const float (*cptrf4)[4];
+
+static void
+do_tri(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct setup_stage *setup = setup_stage( stage );
+
+ setup_tri( setup->setup,
+ (cptrf4)prim->v[0]->data,
+ (cptrf4)prim->v[1]->data,
+ (cptrf4)prim->v[2]->data );
+}
+
+static void
+do_line(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct setup_stage *setup = setup_stage( stage );
+
+ setup_line( setup->setup,
+ (cptrf4)prim->v[0]->data,
+ (cptrf4)prim->v[1]->data );
+}
+
+static void
+do_point(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct setup_stage *setup = setup_stage( stage );
+
+ setup_point( setup->setup,
+ (cptrf4)prim->v[0]->data );
+}
+
+
+
+
+static void setup_begin( struct draw_stage *stage )
+{
+ struct setup_stage *setup = setup_stage(stage);
+
+ setup_prepare( setup->setup );
+
+ stage->point = do_point;
+ stage->line = do_line;
+ stage->tri = do_tri;
+}
+
+
+static void setup_first_point( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ setup_begin(stage);
+ stage->point( stage, header );
+}
+
+static void setup_first_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ setup_begin(stage);
+ stage->line( stage, header );
+}
+
+
+static void setup_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ setup_begin(stage);
+ stage->tri( stage, header );
+}
+
+
+
+static void setup_flush( struct draw_stage *stage,
+ unsigned flags )
+{
+ stage->point = setup_first_point;
+ stage->line = setup_first_line;
+ stage->tri = setup_first_tri;
+}
+
+
+static void reset_stipple_counter( struct draw_stage *stage )
+{
+}
+
+
+static void render_destroy( struct draw_stage *stage )
+{
+ struct setup_stage *ssetup = setup_stage(stage);
+ setup_destroy_context(ssetup->setup);
+ FREE( stage );
+}
+
+
+/**
+ * Create a new primitive setup/render stage.
+ */
+struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe )
+{
+ struct setup_stage *sstage = CALLOC_STRUCT(setup_stage);
+
+ sstage->setup = setup_create_context(softpipe);
+ sstage->stage.draw = softpipe->draw;
+ sstage->stage.point = setup_first_point;
+ sstage->stage.line = setup_first_line;
+ sstage->stage.tri = setup_first_tri;
+ sstage->stage.flush = setup_flush;
+ sstage->stage.reset_stipple_counter = reset_stipple_counter;
+ sstage->stage.destroy = render_destroy;
+
+ return (struct draw_stage *)sstage;
+}
+
+struct setup_context *
+sp_draw_setup_context( struct draw_stage *stage )
+{
+ struct setup_stage *ssetup = setup_stage(stage);
+ return ssetup->setup;
+}
+
+void
+sp_draw_flush( struct draw_stage *stage )
+{
+ stage->flush( stage, 0 );
+}
diff --git a/src/gallium/drivers/softpipe/sp_prim_setup.h b/src/gallium/drivers/softpipe/sp_prim_setup.h
new file mode 100644
index 0000000000..49bdd98ed8
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_prim_setup.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef SP_PRIM_SETUP_H
+#define SP_PRIM_SETUP_H
+
+
+/**
+ * vbuf is a special stage to gather the stream of triangles, lines, points
+ * together and reconstruct vertex buffers for hardware upload.
+ *
+ * First attempt, work in progress.
+ *
+ * TODO:
+ * - separate out vertex buffer building and primitive emit, ie >1 draw per vb.
+ * - tell vbuf stage how to build hw vertices directly
+ * - pass vbuf stage a buffer pointer for direct emit to agp/vram.
+ *
+ *
+ *
+ * Vertices are just an array of floats, with all the attributes
+ * packed. We currently assume a layout like:
+ *
+ * attr[0][0..3] - window position
+ * attr[1..n][0..3] - remaining attributes.
+ *
+ * Attributes are assumed to be 4 floats wide but are packed so that
+ * all the enabled attributes run contiguously.
+ */
+
+
+struct draw_stage;
+struct softpipe_context;
+
+
+typedef void (*vbuf_draw_func)( struct pipe_context *pipe,
+ unsigned prim,
+ const ushort *elements,
+ unsigned nr_elements,
+ const void *vertex_buffer,
+ unsigned nr_vertices );
+
+
+extern struct draw_stage *
+sp_draw_render_stage( struct softpipe_context *softpipe );
+
+extern struct setup_context *
+sp_draw_setup_context( struct draw_stage * );
+
+extern void
+sp_draw_flush( struct draw_stage * );
+
+
+extern struct draw_stage *
+sp_draw_vbuf_stage( struct draw_context *draw_context,
+ struct pipe_context *pipe,
+ vbuf_draw_func draw );
+
+
+#endif /* SP_PRIM_SETUP_H */
diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
new file mode 100644
index 0000000000..42021789ea
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
@@ -0,0 +1,585 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Interface between 'draw' module's output and the softpipe rasterizer/setup
+ * code. When the 'draw' module has finished filling a vertex buffer, the
+ * draw_arrays() functions below will be called. Loop over the vertices and
+ * call the point/line/tri setup functions.
+ *
+ * Authors
+ * Brian Paul
+ */
+
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_prim_vbuf.h"
+#include "sp_prim_setup.h"
+#include "sp_setup.h"
+#include "draw/draw_context.h"
+#include "draw/draw_vbuf.h"
+#include "util/u_memory.h"
+
+
+#define SP_MAX_VBUF_INDEXES 1024
+#define SP_MAX_VBUF_SIZE 4096
+
+typedef const float (*cptrf4)[4];
+
+/**
+ * Subclass of vbuf_render.
+ */
+struct softpipe_vbuf_render
+{
+ struct vbuf_render base;
+ struct softpipe_context *softpipe;
+ uint prim;
+ uint vertex_size;
+ uint nr_vertices;
+ uint vertex_buffer_size;
+ void *vertex_buffer;
+};
+
+
+/** cast wrapper */
+static struct softpipe_vbuf_render *
+softpipe_vbuf_render(struct vbuf_render *vbr)
+{
+ return (struct softpipe_vbuf_render *) vbr;
+}
+
+
+static const struct vertex_info *
+sp_vbuf_get_vertex_info(struct vbuf_render *vbr)
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ return softpipe_get_vbuf_vertex_info(cvbr->softpipe);
+}
+
+
+static boolean
+sp_vbuf_allocate_vertices(struct vbuf_render *vbr,
+ ushort vertex_size, ushort nr_vertices)
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ unsigned size = vertex_size * nr_vertices;
+
+ if (cvbr->vertex_buffer_size < size) {
+ align_free(cvbr->vertex_buffer);
+ cvbr->vertex_buffer = align_malloc(size, 16);
+ cvbr->vertex_buffer_size = size;
+ }
+
+ cvbr->vertex_size = vertex_size;
+ cvbr->nr_vertices = nr_vertices;
+
+ return cvbr->vertex_buffer != NULL;
+}
+
+static void
+sp_vbuf_release_vertices(struct vbuf_render *vbr)
+{
+#if 0
+ {
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ const struct vertex_info *info =
+ softpipe_get_vbuf_vertex_info(cvbr->softpipe);
+ const float *vtx = (const float *) cvbr->vertex_buffer;
+ uint i, j;
+ debug_printf("%s (vtx_size = %u, vtx_used = %u)\n",
+ __FUNCTION__, cvbr->vertex_size, cvbr->nr_vertices);
+ for (i = 0; i < cvbr->nr_vertices; i++) {
+ for (j = 0; j < info->num_attribs; j++) {
+ uint k;
+ switch (info->attrib[j].emit) {
+ case EMIT_4F: k = 4; break;
+ case EMIT_3F: k = 3; break;
+ case EMIT_2F: k = 2; break;
+ case EMIT_1F: k = 1; break;
+ default: assert(0);
+ }
+ debug_printf("Vert %u attr %u: ", i, j);
+ while (k-- > 0) {
+ debug_printf("%g ", vtx[0]);
+ vtx++;
+ }
+ debug_printf("\n");
+ }
+ }
+ }
+#endif
+
+ /* keep the old allocation for next time */
+}
+
+static void *
+sp_vbuf_map_vertices(struct vbuf_render *vbr)
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ return cvbr->vertex_buffer;
+}
+
+static void
+sp_vbuf_unmap_vertices(struct vbuf_render *vbr,
+ ushort min_index,
+ ushort max_index )
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
+ /* do nothing */
+}
+
+
+static boolean
+sp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+
+ /* XXX: break this dependency - make setup_context live under
+ * softpipe, rename the old "setup" draw stage to something else.
+ */
+ struct setup_context *setup_ctx = sp_draw_setup_context(cvbr->softpipe->setup);
+
+ setup_prepare( setup_ctx );
+
+ cvbr->prim = prim;
+ return TRUE;
+
+}
+
+
+static INLINE cptrf4 get_vert( const void *vertex_buffer,
+ int index,
+ int stride )
+{
+ return (cptrf4)((char *)vertex_buffer + index * stride);
+}
+
+
+/**
+ * draw elements / indexed primitives
+ */
+static void
+sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ struct softpipe_context *softpipe = cvbr->softpipe;
+ const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
+ const void *vertex_buffer = cvbr->vertex_buffer;
+ unsigned i;
+
+ /* XXX: break this dependency - make setup_context live under
+ * softpipe, rename the old "setup" draw stage to something else.
+ */
+ struct draw_stage *setup = softpipe->setup;
+ struct setup_context *setup_ctx = sp_draw_setup_context(setup);
+
+ switch (cvbr->prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < nr; i++) {
+ setup_point( setup_ctx,
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 1; i < nr; i += 2) {
+ setup_line( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ for (i = 1; i < nr; i ++) {
+ setup_line( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ for (i = 1; i < nr; i ++) {
+ setup_line( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ if (nr) {
+ setup_line( setup_ctx,
+ get_vert(vertex_buffer, indices[nr-1], stride),
+ get_vert(vertex_buffer, indices[0], stride) );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 2; i < nr; i += 3) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-2], stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ for (i = 2; i < nr; i += 1) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
+ get_vert(vertex_buffer, indices[i-(i&1)], stride),
+ get_vert(vertex_buffer, indices[i-2], stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
+ get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ for (i = 2; i < nr; i += 1) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUADS:
+ for (i = 3; i < nr; i += 4) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-3], stride) );
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-3], stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = 3; i < nr; i += 2) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-3], stride));
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-3], stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-2], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[i-3], stride),
+ get_vert(vertex_buffer, indices[i-0], stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ /* Almost same as tri fan but the _first_ vertex specifies the flat
+ * shading color. Note that the first polygon vertex is passed as
+ * the last triangle vertex here.
+ * flatshade_first state makes no difference.
+ */
+ for (i = 2; i < nr; i += 1) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, indices[i-0], stride),
+ get_vert(vertex_buffer, indices[i-1], stride),
+ get_vert(vertex_buffer, indices[0], stride) );
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+
+ /* XXX: why are we calling this??? If we had to call something, it
+ * would be a function in sp_setup.c:
+ */
+ sp_draw_flush( setup );
+}
+
+
+/**
+ * This function is hit when the draw module is working in pass-through mode.
+ * It's up to us to convert the vertex array into point/line/tri prims.
+ */
+static void
+sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ struct softpipe_context *softpipe = cvbr->softpipe;
+ const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
+ const void *vertex_buffer =
+ (void *) get_vert(cvbr->vertex_buffer, start, stride);
+ unsigned i;
+
+ /* XXX: break this dependency - make setup_context live under
+ * softpipe, rename the old "setup" draw stage to something else.
+ */
+ struct draw_stage *setup = softpipe->setup;
+ struct setup_context *setup_ctx = sp_draw_setup_context(setup);
+
+ switch (cvbr->prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < nr; i++) {
+ setup_point( setup_ctx,
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 1; i < nr; i += 2) {
+ setup_line( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ for (i = 1; i < nr; i ++) {
+ setup_line( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ for (i = 1; i < nr; i ++) {
+ setup_line( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ if (nr) {
+ setup_line( setup_ctx,
+ get_vert(vertex_buffer, nr-1, stride),
+ get_vert(vertex_buffer, 0, stride) );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 2; i < nr; i += 3) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-2, stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ for (i = 2; i < nr; i++) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i+(i&1)-1, stride),
+ get_vert(vertex_buffer, i-(i&1), stride),
+ get_vert(vertex_buffer, i-2, stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i+(i&1)-2, stride),
+ get_vert(vertex_buffer, i-(i&1)-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ for (i = 2; i < nr; i += 1) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, 0, stride),
+ get_vert(vertex_buffer, i-1, stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, 0, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUADS:
+ for (i = 3; i < nr; i += 4) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-3, stride) );
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-3, stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = 3; i < nr; i += 2) {
+ if (softpipe->rasterizer->flatshade_first) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-3, stride) );
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, i-3, stride) );
+ }
+ else {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-2, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-3, stride),
+ get_vert(vertex_buffer, i-0, stride) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ /* Almost same as tri fan but the _first_ vertex specifies the flat
+ * shading color. Note that the first polygon vertex is passed as
+ * the last triangle vertex here.
+ * flatshade_first state makes no difference.
+ */
+ for (i = 2; i < nr; i += 1) {
+ setup_tri( setup_ctx,
+ get_vert(vertex_buffer, i-1, stride),
+ get_vert(vertex_buffer, i-0, stride),
+ get_vert(vertex_buffer, 0, stride) );
+ }
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+
+
+static void
+sp_vbuf_destroy(struct vbuf_render *vbr)
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ cvbr->softpipe->vbuf_render = NULL;
+ FREE(cvbr);
+}
+
+
+/**
+ * Initialize the post-transform vertex buffer information for the given
+ * context.
+ */
+void
+sp_init_vbuf(struct softpipe_context *sp)
+{
+ assert(sp->draw);
+
+ sp->vbuf_render = CALLOC_STRUCT(softpipe_vbuf_render);
+
+ sp->vbuf_render->base.max_indices = SP_MAX_VBUF_INDEXES;
+ sp->vbuf_render->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE;
+
+ sp->vbuf_render->base.get_vertex_info = sp_vbuf_get_vertex_info;
+ sp->vbuf_render->base.allocate_vertices = sp_vbuf_allocate_vertices;
+ sp->vbuf_render->base.map_vertices = sp_vbuf_map_vertices;
+ sp->vbuf_render->base.unmap_vertices = sp_vbuf_unmap_vertices;
+ sp->vbuf_render->base.set_primitive = sp_vbuf_set_primitive;
+ sp->vbuf_render->base.draw = sp_vbuf_draw;
+ sp->vbuf_render->base.draw_arrays = sp_vbuf_draw_arrays;
+ sp->vbuf_render->base.release_vertices = sp_vbuf_release_vertices;
+ sp->vbuf_render->base.destroy = sp_vbuf_destroy;
+
+ sp->vbuf_render->softpipe = sp;
+
+ sp->vbuf = draw_vbuf_stage(sp->draw, &sp->vbuf_render->base);
+
+ draw_set_rasterize_stage(sp->draw, sp->vbuf);
+
+ draw_set_render(sp->draw, &sp->vbuf_render->base);
+}
diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.h b/src/gallium/drivers/softpipe/sp_prim_vbuf.h
new file mode 100644
index 0000000000..1de9cc2a89
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SP_VBUF_H
+#define SP_VBUF_H
+
+
+struct softpipe_context;
+
+extern void
+sp_init_vbuf(struct softpipe_context *softpipe);
+
+
+#endif /* SP_VBUF_H */
diff --git a/src/gallium/drivers/softpipe/sp_quad.h b/src/gallium/drivers/softpipe/sp_quad.h
new file mode 100644
index 0000000000..bd6c6cb912
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad.h
@@ -0,0 +1,106 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_QUAD_H
+#define SP_QUAD_H
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_exec.h"
+
+
+#define QUAD_PRIM_POINT 1
+#define QUAD_PRIM_LINE 2
+#define QUAD_PRIM_TRI 3
+
+
+/* The rasterizer generates 2x2 quads of fragment and feeds them to
+ * the current fp_machine (see below).
+ * Remember that Y=0=top with Y increasing down the window.
+ */
+#define QUAD_TOP_LEFT 0
+#define QUAD_TOP_RIGHT 1
+#define QUAD_BOTTOM_LEFT 2
+#define QUAD_BOTTOM_RIGHT 3
+
+#define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT)
+#define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT)
+#define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT)
+#define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
+#define MASK_ALL 0xf
+
+
+/**
+ * Quad stage inputs (pos, coverage, front/back face, etc)
+ */
+struct quad_header_input
+{
+ int x0, y0; /**< quad window pos, always even */
+ float coverage[QUAD_SIZE]; /**< fragment coverage for antialiasing */
+ unsigned facing:1; /**< Front (0) or back (1) facing? */
+ unsigned prim:2; /**< QUAD_PRIM_POINT, LINE, TRI */
+};
+
+
+/**
+ * Quad stage inputs/outputs.
+ */
+struct quad_header_inout
+{
+ unsigned mask:4;
+};
+
+
+/**
+ * Quad stage outputs (color & depth).
+ */
+struct quad_header_output
+{
+ /** colors in SOA format (rrrr, gggg, bbbb, aaaa) */
+ float color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][QUAD_SIZE];
+ float depth[QUAD_SIZE];
+};
+
+
+/**
+ * Encodes everything we need to know about a 2x2 pixel block. Uses
+ * "Channel-Serial" or "SoA" layout.
+ */
+struct quad_header {
+ struct quad_header_input input;
+ struct quad_header_inout inout;
+ struct quad_header_output output;
+
+ const struct tgsi_interp_coef *coef;
+ const struct tgsi_interp_coef *posCoef;
+
+ unsigned nr_attrs;
+};
+
+#endif /* SP_QUAD_H */
diff --git a/src/gallium/drivers/softpipe/sp_quad_alpha_test.c b/src/gallium/drivers/softpipe/sp_quad_alpha_test.c
new file mode 100644
index 0000000000..0845bae0e6
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_alpha_test.c
@@ -0,0 +1,108 @@
+
+/**
+ * quad alpha test
+ */
+
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_quad_pipe.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+
+
+static void
+alpha_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ const float ref = softpipe->depth_stencil->alpha.ref_value;
+ unsigned passMask = 0x0, j;
+ const uint cbuf = 0; /* only output[0].alpha is tested */
+ const float *aaaa = quad->output.color[cbuf][3];
+
+ switch (softpipe->depth_stencil->alpha.func) {
+ case PIPE_FUNC_NEVER:
+ break;
+ case PIPE_FUNC_LESS:
+ /*
+ * If mask were an array [4] we could do this SIMD-style:
+ * passMask = (quad->outputs.color[0][3] <= vec4(ref));
+ */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (aaaa[j] < ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_EQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (aaaa[j] == ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_LEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (aaaa[j] <= ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_GREATER:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (aaaa[j] > ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (aaaa[j] != ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_GEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (aaaa[j] >= ref) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_ALWAYS:
+ passMask = MASK_ALL;
+ break;
+ default:
+ assert(0);
+ }
+
+ quad->inout.mask &= passMask;
+
+ if (quad->inout.mask)
+ qs->next->run(qs->next, quad);
+}
+
+
+static void alpha_test_begin(struct quad_stage *qs)
+{
+ qs->next->begin(qs->next);
+}
+
+
+static void alpha_test_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+struct quad_stage *
+sp_quad_alpha_test_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = alpha_test_begin;
+ stage->run = alpha_test_quad;
+ stage->destroy = alpha_test_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_blend.c b/src/gallium/drivers/softpipe/sp_quad_blend.c
new file mode 100644
index 0000000000..b1e18805c7
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_blend.c
@@ -0,0 +1,777 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * quad blending
+ * \author Brian Paul
+ */
+
+#include "pipe/p_defines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_surface.h"
+#include "sp_tile_cache.h"
+#include "sp_quad_pipe.h"
+
+
+#define VEC4_COPY(DST, SRC) \
+do { \
+ DST[0] = SRC[0]; \
+ DST[1] = SRC[1]; \
+ DST[2] = SRC[2]; \
+ DST[3] = SRC[3]; \
+} while(0)
+
+#define VEC4_SCALAR(DST, SRC) \
+do { \
+ DST[0] = SRC; \
+ DST[1] = SRC; \
+ DST[2] = SRC; \
+ DST[3] = SRC; \
+} while(0)
+
+#define VEC4_ADD(R, A, B) \
+do { \
+ R[0] = A[0] + B[0]; \
+ R[1] = A[1] + B[1]; \
+ R[2] = A[2] + B[2]; \
+ R[3] = A[3] + B[3]; \
+} while (0)
+
+#define VEC4_SUB(R, A, B) \
+do { \
+ R[0] = A[0] - B[0]; \
+ R[1] = A[1] - B[1]; \
+ R[2] = A[2] - B[2]; \
+ R[3] = A[3] - B[3]; \
+} while (0)
+
+/** Add and limit result to ceiling of 1.0 */
+#define VEC4_ADD_SAT(R, A, B) \
+do { \
+ R[0] = A[0] + B[0]; if (R[0] > 1.0f) R[0] = 1.0f; \
+ R[1] = A[1] + B[1]; if (R[1] > 1.0f) R[1] = 1.0f; \
+ R[2] = A[2] + B[2]; if (R[2] > 1.0f) R[2] = 1.0f; \
+ R[3] = A[3] + B[3]; if (R[3] > 1.0f) R[3] = 1.0f; \
+} while (0)
+
+/** Subtract and limit result to floor of 0.0 */
+#define VEC4_SUB_SAT(R, A, B) \
+do { \
+ R[0] = A[0] - B[0]; if (R[0] < 0.0f) R[0] = 0.0f; \
+ R[1] = A[1] - B[1]; if (R[1] < 0.0f) R[1] = 0.0f; \
+ R[2] = A[2] - B[2]; if (R[2] < 0.0f) R[2] = 0.0f; \
+ R[3] = A[3] - B[3]; if (R[3] < 0.0f) R[3] = 0.0f; \
+} while (0)
+
+#define VEC4_MUL(R, A, B) \
+do { \
+ R[0] = A[0] * B[0]; \
+ R[1] = A[1] * B[1]; \
+ R[2] = A[2] * B[2]; \
+ R[3] = A[3] * B[3]; \
+} while (0)
+
+#define VEC4_MIN(R, A, B) \
+do { \
+ R[0] = (A[0] < B[0]) ? A[0] : B[0]; \
+ R[1] = (A[1] < B[1]) ? A[1] : B[1]; \
+ R[2] = (A[2] < B[2]) ? A[2] : B[2]; \
+ R[3] = (A[3] < B[3]) ? A[3] : B[3]; \
+} while (0)
+
+#define VEC4_MAX(R, A, B) \
+do { \
+ R[0] = (A[0] > B[0]) ? A[0] : B[0]; \
+ R[1] = (A[1] > B[1]) ? A[1] : B[1]; \
+ R[2] = (A[2] > B[2]) ? A[2] : B[2]; \
+ R[3] = (A[3] > B[3]) ? A[3] : B[3]; \
+} while (0)
+
+
+
+static void
+logicop_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ uint cbuf;
+
+ /* loop over colorbuffer outputs */
+ for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
+ float dest[4][QUAD_SIZE];
+ ubyte src[4][4], dst[4][4], res[4][4];
+ uint *src4 = (uint *) src;
+ uint *dst4 = (uint *) dst;
+ uint *res4 = (uint *) res;
+ struct softpipe_cached_tile *
+ tile = sp_get_cached_tile(softpipe,
+ softpipe->cbuf_cache[cbuf],
+ quad->input.x0, quad->input.y0);
+ float (*quadColor)[4] = quad->output.color[cbuf];
+ uint i, j;
+
+ /* get/swizzle dest colors */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
+ int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
+ for (i = 0; i < 4; i++) {
+ dest[i][j] = tile->data.color[y][x][i];
+ }
+ }
+
+ /* convert to ubyte */
+ for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */
+ dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */
+ dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */
+ dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */
+ dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */
+
+ src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */
+ src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */
+ src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */
+ src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */
+ }
+
+ switch (softpipe->blend->logicop_func) {
+ case PIPE_LOGICOP_CLEAR:
+ for (j = 0; j < 4; j++)
+ res4[j] = 0;
+ break;
+ case PIPE_LOGICOP_NOR:
+ for (j = 0; j < 4; j++)
+ res4[j] = ~(src4[j] | dst4[j]);
+ break;
+ case PIPE_LOGICOP_AND_INVERTED:
+ for (j = 0; j < 4; j++)
+ res4[j] = ~src4[j] & dst4[j];
+ break;
+ case PIPE_LOGICOP_COPY_INVERTED:
+ for (j = 0; j < 4; j++)
+ res4[j] = ~src4[j];
+ break;
+ case PIPE_LOGICOP_AND_REVERSE:
+ for (j = 0; j < 4; j++)
+ res4[j] = src4[j] & ~dst4[j];
+ break;
+ case PIPE_LOGICOP_INVERT:
+ for (j = 0; j < 4; j++)
+ res4[j] = ~dst4[j];
+ break;
+ case PIPE_LOGICOP_XOR:
+ for (j = 0; j < 4; j++)
+ res4[j] = dst4[j] ^ src4[j];
+ break;
+ case PIPE_LOGICOP_NAND:
+ for (j = 0; j < 4; j++)
+ res4[j] = ~(src4[j] & dst4[j]);
+ break;
+ case PIPE_LOGICOP_AND:
+ for (j = 0; j < 4; j++)
+ res4[j] = src4[j] & dst4[j];
+ break;
+ case PIPE_LOGICOP_EQUIV:
+ for (j = 0; j < 4; j++)
+ res4[j] = ~(src4[j] ^ dst4[j]);
+ break;
+ case PIPE_LOGICOP_NOOP:
+ for (j = 0; j < 4; j++)
+ res4[j] = dst4[j];
+ break;
+ case PIPE_LOGICOP_OR_INVERTED:
+ for (j = 0; j < 4; j++)
+ res4[j] = ~src4[j] | dst4[j];
+ break;
+ case PIPE_LOGICOP_COPY:
+ for (j = 0; j < 4; j++)
+ res4[j] = src4[j];
+ break;
+ case PIPE_LOGICOP_OR_REVERSE:
+ for (j = 0; j < 4; j++)
+ res4[j] = src4[j] | ~dst4[j];
+ break;
+ case PIPE_LOGICOP_OR:
+ for (j = 0; j < 4; j++)
+ res4[j] = src4[j] | dst4[j];
+ break;
+ case PIPE_LOGICOP_SET:
+ for (j = 0; j < 4; j++)
+ res4[j] = ~0;
+ break;
+ default:
+ assert(0);
+ }
+
+ for (j = 0; j < 4; j++) {
+ quadColor[j][0] = ubyte_to_float(res[j][0]);
+ quadColor[j][1] = ubyte_to_float(res[j][1]);
+ quadColor[j][2] = ubyte_to_float(res[j][2]);
+ quadColor[j][3] = ubyte_to_float(res[j][3]);
+ }
+ }
+
+ /* pass quad to next stage */
+ qs->next->run(qs->next, quad);
+}
+
+
+
+
+static void
+blend_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ static const float zero[4] = { 0, 0, 0, 0 };
+ static const float one[4] = { 1, 1, 1, 1 };
+
+ struct softpipe_context *softpipe = qs->softpipe;
+ uint cbuf;
+
+ if (softpipe->blend->logicop_enable) {
+ logicop_quad(qs, quad);
+ return;
+ }
+
+ /* loop over colorbuffer outputs */
+ for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
+ float source[4][QUAD_SIZE], dest[4][QUAD_SIZE];
+ struct softpipe_cached_tile *tile
+ = sp_get_cached_tile(softpipe,
+ softpipe->cbuf_cache[cbuf],
+ quad->input.x0, quad->input.y0);
+ float (*quadColor)[4] = quad->output.color[cbuf];
+ uint i, j;
+
+ /* get/swizzle dest colors */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
+ int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
+ for (i = 0; i < 4; i++) {
+ dest[i][j] = tile->data.color[y][x][i];
+ }
+ }
+
+ /*
+ * Compute src/first term RGB
+ */
+ switch (softpipe->blend->rgb_src_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ VEC4_COPY(source[0], quadColor[0]); /* R */
+ VEC4_COPY(source[1], quadColor[1]); /* G */
+ VEC4_COPY(source[2], quadColor[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */
+ VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */
+ VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ {
+ const float *alpha = quadColor[3];
+ VEC4_MUL(source[0], quadColor[0], alpha); /* R */
+ VEC4_MUL(source[1], quadColor[1], alpha); /* G */
+ VEC4_MUL(source[2], quadColor[2], alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */
+ VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */
+ VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ {
+ const float *alpha = dest[3];
+ VEC4_MUL(source[0], quadColor[0], alpha); /* R */
+ VEC4_MUL(source[1], quadColor[1], alpha); /* G */
+ VEC4_MUL(source[2], quadColor[2], alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ {
+ const float *alpha = quadColor[3];
+ float diff[4], temp[4];
+ VEC4_SUB(diff, one, dest[3]);
+ VEC4_MIN(temp, alpha, diff);
+ VEC4_MUL(source[0], quadColor[0], temp); /* R */
+ VEC4_MUL(source[1], quadColor[1], temp); /* G */
+ VEC4_MUL(source[2], quadColor[2], temp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ {
+ float comp[4];
+ VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
+ VEC4_MUL(source[0], quadColor[0], comp); /* R */
+ VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */
+ VEC4_MUL(source[1], quadColor[1], comp); /* G */
+ VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */
+ VEC4_MUL(source[2], quadColor[2], comp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ {
+ float alpha[4];
+ VEC4_SCALAR(alpha, softpipe->blend_color.color[3]);
+ VEC4_MUL(source[0], quadColor[0], alpha); /* R */
+ VEC4_MUL(source[1], quadColor[1], alpha); /* G */
+ VEC4_MUL(source[2], quadColor[2], alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ VEC4_COPY(source[0], zero); /* R */
+ VEC4_COPY(source[1], zero); /* G */
+ VEC4_COPY(source[2], zero); /* B */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ {
+ float inv_comp[4];
+ VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
+ VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
+ VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
+ VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
+ VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
+ VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ {
+ float inv_alpha[4];
+ VEC4_SUB(inv_alpha, one, quadColor[3]);
+ VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
+ VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
+ VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ {
+ float inv_alpha[4];
+ VEC4_SUB(inv_alpha, one, dest[3]);
+ VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
+ VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
+ VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ {
+ float inv_comp[4];
+ VEC4_SUB(inv_comp, one, dest[0]); /* R */
+ VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
+ VEC4_SUB(inv_comp, one, dest[1]); /* G */
+ VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
+ VEC4_SUB(inv_comp, one, dest[2]); /* B */
+ VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ {
+ float inv_comp[4];
+ /* R */
+ VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]);
+ VEC4_MUL(source[0], quadColor[0], inv_comp);
+ /* G */
+ VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]);
+ VEC4_MUL(source[1], quadColor[1], inv_comp);
+ /* B */
+ VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]);
+ VEC4_MUL(source[2], quadColor[2], inv_comp);
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ {
+ float inv_alpha[4];
+ VEC4_SCALAR(inv_alpha, 1.0f - softpipe->blend_color.color[3]);
+ VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
+ VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
+ VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ assert(0); /* to do */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ assert(0); /* to do */
+ break;
+ default:
+ assert(0);
+ }
+
+ /*
+ * Compute src/first term A
+ */
+ switch (softpipe->blend->alpha_src_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ VEC4_COPY(source[3], quadColor[3]); /* A */
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ {
+ const float *alpha = quadColor[3];
+ VEC4_MUL(source[3], quadColor[3], alpha); /* A */
+ }
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ /* multiply alpha by 1.0 */
+ VEC4_COPY(source[3], quadColor[3]); /* A */
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ {
+ float comp[4];
+ VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
+ VEC4_MUL(source[3], quadColor[3], comp); /* A */
+ }
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ VEC4_COPY(source[3], zero); /* A */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ {
+ float inv_alpha[4];
+ VEC4_SUB(inv_alpha, one, quadColor[3]);
+ VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ {
+ float inv_alpha[4];
+ VEC4_SUB(inv_alpha, one, dest[3]);
+ VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ {
+ float inv_comp[4];
+ /* A */
+ VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
+ VEC4_MUL(source[3], quadColor[3], inv_comp);
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+
+ /*
+ * Compute dest/second term RGB
+ */
+ switch (softpipe->blend->rgb_dst_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ /* dest = dest * 1 NO-OP, leave dest as-is */
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ VEC4_MUL(dest[0], dest[0], quadColor[0]); /* R */
+ VEC4_MUL(dest[1], dest[1], quadColor[1]); /* G */
+ VEC4_MUL(dest[2], dest[2], quadColor[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ VEC4_MUL(dest[0], dest[0], quadColor[3]); /* R * A */
+ VEC4_MUL(dest[1], dest[1], quadColor[3]); /* G * A */
+ VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */
+ break;
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */
+ VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */
+ VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ VEC4_MUL(dest[0], dest[0], dest[0]); /* R */
+ VEC4_MUL(dest[1], dest[1], dest[1]); /* G */
+ VEC4_MUL(dest[2], dest[2], dest[2]); /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ assert(0); /* illegal */
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ {
+ float comp[4];
+ VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
+ VEC4_MUL(dest[0], dest[0], comp); /* R */
+ VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */
+ VEC4_MUL(dest[1], dest[1], comp); /* G */
+ VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */
+ VEC4_MUL(dest[2], dest[2], comp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ {
+ float comp[4];
+ VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
+ VEC4_MUL(dest[0], dest[0], comp); /* R */
+ VEC4_MUL(dest[1], dest[1], comp); /* G */
+ VEC4_MUL(dest[2], dest[2], comp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ VEC4_COPY(dest[0], zero); /* R */
+ VEC4_COPY(dest[1], zero); /* G */
+ VEC4_COPY(dest[2], zero); /* B */
+ break;
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_ALPHA:
+ /* XXX what are these? */
+ assert(0);
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ {
+ float inv_comp[4];
+ VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
+ VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
+ VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
+ VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
+ VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
+ VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ {
+ float one_minus_alpha[QUAD_SIZE];
+ VEC4_SUB(one_minus_alpha, one, quadColor[3]);
+ VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
+ VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
+ VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ {
+ float inv_comp[4];
+ VEC4_SUB(inv_comp, one, dest[3]); /* A */
+ VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
+ VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
+ VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ {
+ float inv_comp[4];
+ VEC4_SUB(inv_comp, one, dest[0]); /* R */
+ VEC4_MUL(dest[0], dest[0], inv_comp); /* R */
+ VEC4_SUB(inv_comp, one, dest[1]); /* G */
+ VEC4_MUL(dest[1], dest[1], inv_comp); /* G */
+ VEC4_SUB(inv_comp, one, dest[2]); /* B */
+ VEC4_MUL(dest[2], dest[2], inv_comp); /* B */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ {
+ float inv_comp[4];
+ /* R */
+ VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]);
+ VEC4_MUL(dest[0], dest[0], inv_comp);
+ /* G */
+ VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]);
+ VEC4_MUL(dest[1], dest[1], inv_comp);
+ /* B */
+ VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]);
+ VEC4_MUL(dest[2], dest[2], inv_comp);
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ {
+ float inv_comp[4];
+ VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
+ VEC4_MUL(dest[0], dest[0], inv_comp);
+ VEC4_MUL(dest[1], dest[1], inv_comp);
+ VEC4_MUL(dest[2], dest[2], inv_comp);
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+ case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+ /* XXX what are these? */
+ assert(0);
+ break;
+ default:
+ assert(0);
+ }
+
+ /*
+ * Compute dest/second term A
+ */
+ switch (softpipe->blend->alpha_dst_factor) {
+ case PIPE_BLENDFACTOR_ONE:
+ /* dest = dest * 1 NO-OP, leave dest as-is */
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_SRC_ALPHA:
+ VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */
+ break;
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_DST_ALPHA:
+ VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
+ break;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ assert(0); /* illegal */
+ break;
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_CONST_ALPHA:
+ {
+ float comp[4];
+ VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
+ VEC4_MUL(dest[3], dest[3], comp); /* A */
+ }
+ break;
+ case PIPE_BLENDFACTOR_ZERO:
+ VEC4_COPY(dest[3], zero); /* A */
+ break;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+ {
+ float one_minus_alpha[QUAD_SIZE];
+ VEC4_SUB(one_minus_alpha, one, quadColor[3]);
+ VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+ {
+ float inv_comp[4];
+ VEC4_SUB(inv_comp, one, dest[3]); /* A */
+ VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */
+ }
+ break;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+ /* fall-through */
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+ {
+ float inv_comp[4];
+ VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
+ VEC4_MUL(dest[3], dest[3], inv_comp);
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ /*
+ * Combine RGB terms
+ */
+ switch (softpipe->blend->rgb_func) {
+ case PIPE_BLEND_ADD:
+ VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */
+ VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */
+ VEC4_ADD_SAT(quadColor[2], source[2], dest[2]); /* B */
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ VEC4_SUB_SAT(quadColor[0], source[0], dest[0]); /* R */
+ VEC4_SUB_SAT(quadColor[1], source[1], dest[1]); /* G */
+ VEC4_SUB_SAT(quadColor[2], source[2], dest[2]); /* B */
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ VEC4_SUB_SAT(quadColor[0], dest[0], source[0]); /* R */
+ VEC4_SUB_SAT(quadColor[1], dest[1], source[1]); /* G */
+ VEC4_SUB_SAT(quadColor[2], dest[2], source[2]); /* B */
+ break;
+ case PIPE_BLEND_MIN:
+ VEC4_MIN(quadColor[0], source[0], dest[0]); /* R */
+ VEC4_MIN(quadColor[1], source[1], dest[1]); /* G */
+ VEC4_MIN(quadColor[2], source[2], dest[2]); /* B */
+ break;
+ case PIPE_BLEND_MAX:
+ VEC4_MAX(quadColor[0], source[0], dest[0]); /* R */
+ VEC4_MAX(quadColor[1], source[1], dest[1]); /* G */
+ VEC4_MAX(quadColor[2], source[2], dest[2]); /* B */
+ break;
+ default:
+ assert(0);
+ }
+
+ /*
+ * Combine A terms
+ */
+ switch (softpipe->blend->alpha_func) {
+ case PIPE_BLEND_ADD:
+ VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */
+ break;
+ case PIPE_BLEND_SUBTRACT:
+ VEC4_SUB_SAT(quadColor[3], source[3], dest[3]); /* A */
+ break;
+ case PIPE_BLEND_REVERSE_SUBTRACT:
+ VEC4_SUB_SAT(quadColor[3], dest[3], source[3]); /* A */
+ break;
+ case PIPE_BLEND_MIN:
+ VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */
+ break;
+ case PIPE_BLEND_MAX:
+ VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */
+ break;
+ default:
+ assert(0);
+ }
+
+ } /* cbuf loop */
+
+ /* pass blended quad to next stage */
+ qs->next->run(qs->next, quad);
+}
+
+
+static void blend_begin(struct quad_stage *qs)
+{
+ qs->next->begin(qs->next);
+}
+
+
+static void blend_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = blend_begin;
+ stage->run = blend_quad;
+ stage->destroy = blend_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_bufloop.c b/src/gallium/drivers/softpipe/sp_quad_bufloop.c
new file mode 100644
index 0000000000..953d8516b9
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_bufloop.c
@@ -0,0 +1,74 @@
+
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_surface.h"
+#include "sp_quad_pipe.h"
+
+
+/**
+ * Loop over colorbuffers, passing quad to next stage each time.
+ */
+static void
+cbuf_loop_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ float tmp[PIPE_MAX_COLOR_BUFS][4][QUAD_SIZE];
+ unsigned i;
+
+ assert(sizeof(quad->outputs.color) == sizeof(tmp));
+ assert(softpipe->framebuffer.nr_cbufs <= PIPE_MAX_COLOR_BUFS);
+
+ /* make copy of original colors since they can get modified
+ * by blending and masking.
+ * XXX we won't have to do this if the fragment program actually emits
+ * N separate colors and we're drawing to N color buffers (MRT).
+ * But if we emitted one color and glDrawBuffer(GL_FRONT_AND_BACK) is
+ * in effect, we need to save/restore colors like this.
+ */
+ memcpy(tmp, quad->outputs.color, sizeof(tmp));
+
+ for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
+ /* set current cbuffer */
+#if 0 /* obsolete & going away */
+ softpipe->current_cbuf = i;
+#endif
+
+ /* pass blended quad to next stage */
+ qs->next->run(qs->next, quad);
+
+ /* restore quad's colors for next buffer */
+ memcpy(quad->outputs.color, tmp, sizeof(tmp));
+ }
+}
+
+
+static void cbuf_loop_begin(struct quad_stage *qs)
+{
+ qs->next->begin(qs->next);
+}
+
+
+static void cbuf_loop_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+/**
+ * Create the colorbuffer loop stage.
+ * This is used to implement multiple render targets and GL_FRONT_AND_BACK
+ * rendering.
+ */
+struct quad_stage *sp_quad_bufloop_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = cbuf_loop_begin;
+ stage->run = cbuf_loop_quad;
+ stage->destroy = cbuf_loop_destroy;
+
+ return stage;
+}
+
diff --git a/src/gallium/drivers/softpipe/sp_quad_colormask.c b/src/gallium/drivers/softpipe/sp_quad_colormask.c
new file mode 100644
index 0000000000..dc90e5d5e9
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_colormask.c
@@ -0,0 +1,116 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief quad colormask stage
+ * \author Brian Paul
+ */
+
+#include "pipe/p_defines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_surface.h"
+#include "sp_quad_pipe.h"
+#include "sp_tile_cache.h"
+
+
+
+/**
+ * XXX colormask could be rolled into blending...
+ */
+static void
+colormask_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ uint cbuf;
+
+ /* loop over colorbuffer outputs */
+ for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
+ float dest[4][QUAD_SIZE];
+ struct softpipe_cached_tile *tile
+ = sp_get_cached_tile(softpipe,
+ softpipe->cbuf_cache[cbuf],
+ quad->input.x0, quad->input.y0);
+ float (*quadColor)[4] = quad->output.color[cbuf];
+ uint i, j;
+
+ /* get/swizzle dest colors */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
+ int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
+ for (i = 0; i < 4; i++) {
+ dest[i][j] = tile->data.color[y][x][i];
+ }
+ }
+
+ /* R */
+ if (!(softpipe->blend->colormask & PIPE_MASK_R))
+ COPY_4V(quadColor[0], dest[0]);
+
+ /* G */
+ if (!(softpipe->blend->colormask & PIPE_MASK_G))
+ COPY_4V(quadColor[1], dest[1]);
+
+ /* B */
+ if (!(softpipe->blend->colormask & PIPE_MASK_B))
+ COPY_4V(quadColor[2], dest[2]);
+
+ /* A */
+ if (!(softpipe->blend->colormask & PIPE_MASK_A))
+ COPY_4V(quadColor[3], dest[3]);
+ }
+
+ /* pass quad to next stage */
+ qs->next->run(qs->next, quad);
+}
+
+
+static void colormask_begin(struct quad_stage *qs)
+{
+ qs->next->begin(qs->next);
+}
+
+
+static void colormask_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = colormask_begin;
+ stage->run = colormask_quad;
+ stage->destroy = colormask_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_coverage.c b/src/gallium/drivers/softpipe/sp_quad_coverage.c
new file mode 100644
index 0000000000..4aeee85870
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_coverage.c
@@ -0,0 +1,94 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * \brief Apply AA coverage to quad alpha valus
+ * \author Brian Paul
+ */
+
+
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_quad_pipe.h"
+
+
+/**
+ * Multiply quad's alpha values by the fragment coverage.
+ */
+static void
+coverage_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ const uint prim = quad->input.prim;
+
+ if ((softpipe->rasterizer->poly_smooth && prim == QUAD_PRIM_TRI) ||
+ (softpipe->rasterizer->line_smooth && prim == QUAD_PRIM_LINE) ||
+ (softpipe->rasterizer->point_smooth && prim == QUAD_PRIM_POINT)) {
+ uint cbuf;
+
+ /* loop over colorbuffer outputs */
+ for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
+ float (*quadColor)[4] = quad->output.color[cbuf];
+ unsigned j;
+ for (j = 0; j < QUAD_SIZE; j++) {
+ assert(quad->input.coverage[j] >= 0.0);
+ assert(quad->input.coverage[j] <= 1.0);
+ quadColor[3][j] *= quad->input.coverage[j];
+ }
+ }
+ }
+
+ qs->next->run(qs->next, quad);
+}
+
+
+static void coverage_begin(struct quad_stage *qs)
+{
+ qs->next->begin(qs->next);
+}
+
+
+static void coverage_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = coverage_begin;
+ stage->run = coverage_quad;
+ stage->destroy = coverage_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c
new file mode 100644
index 0000000000..d463930bae
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c
@@ -0,0 +1,290 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Quad depth testing
+ */
+
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_surface.h"
+#include "sp_quad_pipe.h"
+#include "sp_tile_cache.h"
+
+
+/**
+ * Do depth testing for a quad.
+ * Not static since it's used by the stencil code.
+ */
+
+/*
+ * To increase efficiency, we should probably have multiple versions
+ * of this function that are specifically for Z16, Z32 and FP Z buffers.
+ * Try to effectively do that with codegen...
+ */
+
+void
+sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ struct pipe_surface *ps = softpipe->framebuffer.zsbuf;
+ const enum pipe_format format = ps->format;
+ unsigned bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */
+ unsigned qzzzz[QUAD_SIZE]; /**< Z values from the quad */
+ unsigned zmask = 0;
+ unsigned j;
+ struct softpipe_cached_tile *tile
+ = sp_get_cached_tile(softpipe, softpipe->zsbuf_cache, quad->input.x0, quad->input.y0);
+
+ assert(ps); /* shouldn't get here if there's no zbuffer */
+
+ /*
+ * Convert quad's float depth values to int depth values (qzzzz).
+ * If the Z buffer stores integer values, we _have_ to do the depth
+ * compares with integers (not floats). Otherwise, the float->int->float
+ * conversion of Z values (which isn't an identity function) will cause
+ * Z-fighting errors.
+ *
+ * Also, get the zbuffer values (bzzzz) from the cached tile.
+ */
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ {
+ float scale = 65535.0;
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
+ }
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ bzzzz[j] = tile->data.depth16[y][x];
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z32_UNORM:
+ {
+ double scale = (double) (uint) ~0UL;
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
+ }
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ bzzzz[j] = tile->data.depth32[y][x];
+ }
+ }
+ break;
+ case PIPE_FORMAT_X8Z24_UNORM:
+ /* fall-through */
+ case PIPE_FORMAT_S8Z24_UNORM:
+ {
+ float scale = (float) ((1 << 24) - 1);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
+ }
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z24X8_UNORM:
+ /* fall-through */
+ case PIPE_FORMAT_Z24S8_UNORM:
+ {
+ float scale = (float) ((1 << 24) - 1);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
+ }
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ bzzzz[j] = tile->data.depth32[y][x] >> 8;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ switch (softpipe->depth_stencil->depth.func) {
+ case PIPE_FUNC_NEVER:
+ /* zmask = 0 */
+ break;
+ case PIPE_FUNC_LESS:
+ /* Note this is pretty much a single sse or cell instruction.
+ * Like this: quad->mask &= (quad->outputs.depth < zzzz);
+ */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] < bzzzz[j])
+ zmask |= 1 << j;
+ }
+ break;
+ case PIPE_FUNC_EQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] == bzzzz[j])
+ zmask |= 1 << j;
+ }
+ break;
+ case PIPE_FUNC_LEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] <= bzzzz[j])
+ zmask |= (1 << j);
+ }
+ break;
+ case PIPE_FUNC_GREATER:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] > bzzzz[j])
+ zmask |= (1 << j);
+ }
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] != bzzzz[j])
+ zmask |= (1 << j);
+ }
+ break;
+ case PIPE_FUNC_GEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (qzzzz[j] >= bzzzz[j])
+ zmask |= (1 << j);
+ }
+ break;
+ case PIPE_FUNC_ALWAYS:
+ zmask = MASK_ALL;
+ break;
+ default:
+ assert(0);
+ }
+
+ quad->inout.mask &= zmask;
+
+ if (softpipe->depth_stencil->depth.writemask) {
+
+ /* This is also efficient with sse / spe instructions:
+ */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (quad->inout.mask & (1 << j)) {
+ bzzzz[j] = qzzzz[j];
+ }
+ }
+
+ /* put updated Z values back into cached tile */
+ switch (format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ tile->data.depth16[y][x] = (ushort) bzzzz[j];
+ }
+ break;
+ case PIPE_FORMAT_X8Z24_UNORM:
+ /* fall-through */
+ /* (yes, this falls through to a different case than above) */
+ case PIPE_FORMAT_Z32_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ tile->data.depth32[y][x] = bzzzz[j];
+ }
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ uint s8z24 = tile->data.depth32[y][x];
+ s8z24 = (s8z24 & 0xff000000) | bzzzz[j];
+ tile->data.depth32[y][x] = s8z24;
+ }
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ uint z24s8 = tile->data.depth32[y][x];
+ z24s8 = (z24s8 & 0xff) | (bzzzz[j] << 8);
+ tile->data.depth32[y][x] = z24s8;
+ }
+ break;
+ case PIPE_FORMAT_Z24X8_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ tile->data.depth32[y][x] = bzzzz[j] << 8;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+}
+
+
+static void
+depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ sp_depth_test_quad(qs, quad);
+
+ if (quad->inout.mask)
+ qs->next->run(qs->next, quad);
+}
+
+
+static void depth_test_begin(struct quad_stage *qs)
+{
+ qs->next->begin(qs->next);
+}
+
+
+static void depth_test_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = depth_test_begin;
+ stage->run = depth_test_quad;
+ stage->destroy = depth_test_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_earlyz.c b/src/gallium/drivers/softpipe/sp_quad_earlyz.c
new file mode 100644
index 0000000000..496fd39ed1
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_earlyz.c
@@ -0,0 +1,88 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Quad early-z testing
+ */
+
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "sp_quad.h"
+#include "sp_quad_pipe.h"
+
+
+/**
+ * All this stage does is compute the quad's Z values (which is normally
+ * done by the shading stage).
+ * The next stage will do the actual depth test.
+ */
+static void
+earlyz_quad(
+ struct quad_stage *qs,
+ struct quad_header *quad )
+{
+ const float fx = (float) quad->input.x0;
+ const float fy = (float) quad->input.y0;
+ const float dzdx = quad->posCoef->dadx[2];
+ const float dzdy = quad->posCoef->dady[2];
+ const float z0 = quad->posCoef->a0[2] + dzdx * fx + dzdy * fy;
+
+ quad->output.depth[0] = z0;
+ quad->output.depth[1] = z0 + dzdx;
+ quad->output.depth[2] = z0 + dzdy;
+ quad->output.depth[3] = z0 + dzdx + dzdy;
+
+ qs->next->run( qs->next, quad );
+}
+
+static void
+earlyz_begin(
+ struct quad_stage *qs )
+{
+ qs->next->begin( qs->next );
+}
+
+static void
+earlyz_destroy(
+ struct quad_stage *qs )
+{
+ FREE( qs );
+}
+
+struct quad_stage *
+sp_quad_earlyz_stage(
+ struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT( quad_stage );
+
+ stage->softpipe = softpipe;
+ stage->begin = earlyz_begin;
+ stage->run = earlyz_quad;
+ stage->destroy = earlyz_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c
new file mode 100644
index 0000000000..28f8d1a60e
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_fs.c
@@ -0,0 +1,192 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2008 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/* Vertices are just an array of floats, with all the attributes
+ * packed. We currently assume a layout like:
+ *
+ * attr[0][0..3] - window position
+ * attr[1..n][0..3] - remaining attributes.
+ *
+ * Attributes are assumed to be 4 floats wide but are packed so that
+ * all the enabled attributes run contiguously.
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_quad.h"
+#include "sp_quad_pipe.h"
+#include "sp_texture.h"
+#include "sp_tex_sample.h"
+
+
+struct quad_shade_stage
+{
+ struct quad_stage stage; /**< base class */
+ struct tgsi_exec_machine *machine;
+ struct tgsi_exec_vector *inputs, *outputs;
+};
+
+
+/** cast wrapper */
+static INLINE struct quad_shade_stage *
+quad_shade_stage(struct quad_stage *qs)
+{
+ return (struct quad_shade_stage *) qs;
+}
+
+
+/**
+ * Execute fragment shader for the four fragments in the quad.
+ */
+static void
+shade_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct quad_shade_stage *qss = quad_shade_stage( qs );
+ struct softpipe_context *softpipe = qs->softpipe;
+ struct tgsi_exec_machine *machine = qss->machine;
+ boolean z_written;
+
+ /* Consts do not require 16 byte alignment. */
+ machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT];
+
+ machine->InterpCoefs = quad->coef;
+
+ /* run shader */
+ quad->inout.mask &= softpipe->fs->run( softpipe->fs, machine, quad );
+
+ /* store outputs */
+ z_written = FALSE;
+ {
+ const ubyte *sem_name = softpipe->fs->info.output_semantic_name;
+ const ubyte *sem_index = softpipe->fs->info.output_semantic_index;
+ const uint n = qss->stage.softpipe->fs->info.num_outputs;
+ uint i;
+ for (i = 0; i < n; i++) {
+ switch (sem_name[i]) {
+ case TGSI_SEMANTIC_COLOR:
+ {
+ uint cbuf = sem_index[i];
+ memcpy(quad->output.color[cbuf],
+ &machine->Outputs[i].xyzw[0].f[0],
+ sizeof(quad->output.color[0]) );
+ }
+ break;
+ case TGSI_SEMANTIC_POSITION:
+ {
+ uint j;
+ for (j = 0; j < 4; j++) {
+ quad->output.depth[j] = machine->Outputs[0].xyzw[2].f[j];
+ }
+ z_written = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ if (!z_written) {
+ /* compute Z values now, as in the quad earlyz stage */
+ /* XXX we should really only do this if the earlyz stage is not used */
+ const float fx = (float) quad->input.x0;
+ const float fy = (float) quad->input.y0;
+ const float dzdx = quad->posCoef->dadx[2];
+ const float dzdy = quad->posCoef->dady[2];
+ const float z0 = quad->posCoef->a0[2] + dzdx * fx + dzdy * fy;
+
+ quad->output.depth[0] = z0;
+ quad->output.depth[1] = z0 + dzdx;
+ quad->output.depth[2] = z0 + dzdy;
+ quad->output.depth[3] = z0 + dzdx + dzdy;
+ }
+
+ /* shader may cull fragments */
+ if (quad->inout.mask) {
+ qs->next->run( qs->next, quad );
+ }
+}
+
+
+/**
+ * Per-primitive (or per-begin?) setup
+ */
+static void
+shade_begin(struct quad_stage *qs)
+{
+ struct quad_shade_stage *qss = quad_shade_stage(qs);
+ struct softpipe_context *softpipe = qs->softpipe;
+
+ softpipe->fs->prepare( softpipe->fs,
+ qss->machine,
+ (struct tgsi_sampler **)
+ softpipe->tgsi.frag_samplers_list );
+
+ qs->next->begin(qs->next);
+}
+
+
+static void
+shade_destroy(struct quad_stage *qs)
+{
+ struct quad_shade_stage *qss = (struct quad_shade_stage *) qs;
+
+ tgsi_exec_machine_destroy(qss->machine);
+
+ FREE( qs );
+}
+
+
+struct quad_stage *
+sp_quad_shade_stage( struct softpipe_context *softpipe )
+{
+ struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage);
+ if (!qss)
+ goto fail;
+
+ qss->stage.softpipe = softpipe;
+ qss->stage.begin = shade_begin;
+ qss->stage.run = shade_quad;
+ qss->stage.destroy = shade_destroy;
+
+ qss->machine = tgsi_exec_machine_create();
+ if (!qss->machine)
+ goto fail;
+
+ return &qss->stage;
+
+fail:
+ if (qss && qss->machine)
+ tgsi_exec_machine_destroy(qss->machine);
+
+ FREE(qss);
+ return NULL;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_occlusion.c b/src/gallium/drivers/softpipe/sp_quad_occlusion.c
new file mode 100644
index 0000000000..dfa7ff3b1d
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_occlusion.c
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * \brief Quad occlusion counter stage
+ * \author Brian Paul
+ */
+
+
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_surface.h"
+#include "sp_quad_pipe.h"
+
+static unsigned count_bits( unsigned val )
+{
+ unsigned i;
+
+ for (i = 0; val ; val >>= 1)
+ i += (val & 1);
+
+ return i;
+}
+
+static void
+occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+
+ softpipe->occlusion_count += count_bits(quad->inout.mask);
+
+ qs->next->run(qs->next, quad);
+}
+
+
+static void occlusion_begin(struct quad_stage *qs)
+{
+ qs->next->begin(qs->next);
+}
+
+
+static void occlusion_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = occlusion_begin;
+ stage->run = occlusion_count_quad;
+ stage->destroy = occlusion_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_output.c b/src/gallium/drivers/softpipe/sp_quad_output.c
new file mode 100644
index 0000000000..92d5f9f3c1
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_output.c
@@ -0,0 +1,103 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_surface.h"
+#include "sp_quad_pipe.h"
+#include "sp_tile_cache.h"
+
+
+/**
+ * Last step of quad processing: write quad colors to the framebuffer,
+ * taking mask into account.
+ */
+static void
+output_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ /* in-tile pos: */
+ const int itx = quad->input.x0 % TILE_SIZE;
+ const int ity = quad->input.y0 % TILE_SIZE;
+
+ struct softpipe_context *softpipe = qs->softpipe;
+ uint cbuf;
+
+ /* loop over colorbuffer outputs */
+ for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
+ struct softpipe_cached_tile *tile
+ = sp_get_cached_tile(softpipe,
+ softpipe->cbuf_cache[cbuf],
+ quad->input.x0, quad->input.y0);
+ float (*quadColor)[4] = quad->output.color[cbuf];
+ int i, j;
+
+ /* get/swizzle dest colors */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (quad->inout.mask & (1 << j)) {
+ int x = itx + (j & 1);
+ int y = ity + (j >> 1);
+ for (i = 0; i < 4; i++) { /* loop over color chans */
+ tile->data.color[y][x][i] = quadColor[i][j];
+ }
+ if (0) {
+ debug_printf("sp write pixel %d,%d: %g, %g, %g\n",
+ quad->input.x0 + x,
+ quad->input.y0 + y,
+ quadColor[0][j],
+ quadColor[1][j],
+ quadColor[2][j]);
+ }
+ }
+ }
+ }
+}
+
+
+static void output_begin(struct quad_stage *qs)
+{
+ assert(qs->next == NULL);
+}
+
+
+static void output_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = output_begin;
+ stage->run = output_quad;
+ stage->destroy = output_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_pipe.c b/src/gallium/drivers/softpipe/sp_quad_pipe.c
new file mode 100644
index 0000000000..b5f69b7426
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_pipe.c
@@ -0,0 +1,118 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "pipe/p_shader_tokens.h"
+
+static void
+sp_push_quad_first(
+ struct softpipe_context *sp,
+ struct quad_stage *quad,
+ uint i )
+{
+ quad->next = sp->quad[i].first;
+ sp->quad[i].first = quad;
+}
+
+static void
+sp_build_depth_stencil(
+ struct softpipe_context *sp,
+ uint i )
+{
+ if (sp->depth_stencil->stencil[0].enabled ||
+ sp->depth_stencil->stencil[1].enabled) {
+ sp_push_quad_first( sp, sp->quad[i].stencil_test, i );
+ }
+ else if (sp->depth_stencil->depth.enabled &&
+ sp->framebuffer.zsbuf) {
+ sp_push_quad_first( sp, sp->quad[i].depth_test, i );
+ }
+}
+
+void
+sp_build_quad_pipeline(struct softpipe_context *sp)
+{
+ uint i;
+
+ boolean early_depth_test =
+ sp->depth_stencil->depth.enabled &&
+ sp->framebuffer.zsbuf &&
+ !sp->depth_stencil->alpha.enabled &&
+ !sp->fs->info.uses_kill &&
+ !sp->fs->info.writes_z;
+
+ /* build up the pipeline in reverse order... */
+ for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
+ sp->quad[i].first = sp->quad[i].output;
+
+ if (sp->blend->colormask != 0xf) {
+ sp_push_quad_first( sp, sp->quad[i].colormask, i );
+ }
+
+ if (sp->blend->blend_enable ||
+ sp->blend->logicop_enable) {
+ sp_push_quad_first( sp, sp->quad[i].blend, i );
+ }
+
+ if (sp->active_query_count) {
+ sp_push_quad_first( sp, sp->quad[i].occlusion, i );
+ }
+
+ if (sp->rasterizer->poly_smooth ||
+ sp->rasterizer->line_smooth ||
+ sp->rasterizer->point_smooth) {
+ sp_push_quad_first( sp, sp->quad[i].coverage, i );
+ }
+
+ if (!early_depth_test) {
+ sp_build_depth_stencil( sp, i );
+ }
+
+ if (sp->depth_stencil->alpha.enabled) {
+ sp_push_quad_first( sp, sp->quad[i].alpha_test, i );
+ }
+
+ /* XXX always enable shader? */
+ if (1) {
+ sp_push_quad_first( sp, sp->quad[i].shade, i );
+ }
+
+ if (early_depth_test) {
+ sp_build_depth_stencil( sp, i );
+ sp_push_quad_first( sp, sp->quad[i].earlyz, i );
+ }
+
+#if !USE_DRAW_STAGE_PSTIPPLE
+ if (sp->rasterizer->poly_stipple_enable) {
+ sp_push_quad_first( sp, sp->quad[i].polygon_stipple, i );
+ }
+#endif
+ }
+}
+
diff --git a/src/gallium/drivers/softpipe/sp_quad_pipe.h b/src/gallium/drivers/softpipe/sp_quad_pipe.h
new file mode 100644
index 0000000000..0e40586ffc
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_pipe.h
@@ -0,0 +1,74 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_QUAD_PIPE_H
+#define SP_QUAD_PIPE_H
+
+
+struct softpipe_context;
+struct quad_header;
+
+
+/**
+ * Fragment processing is performed on 2x2 blocks of pixels called "quads".
+ * Quad processing is performed with a pipeline of stages represented by
+ * this type.
+ */
+struct quad_stage {
+ struct softpipe_context *softpipe;
+
+ struct quad_stage *next;
+
+ void (*begin)(struct quad_stage *qs);
+
+ /** the stage action */
+ void (*run)(struct quad_stage *qs, struct quad_header *quad);
+
+ void (*destroy)(struct quad_stage *qs);
+};
+
+
+struct quad_stage *sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_earlyz_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_alpha_test_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe );
+
+void sp_build_quad_pipeline(struct softpipe_context *sp);
+
+void sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad);
+
+#endif /* SP_QUAD_PIPE_H */
diff --git a/src/gallium/drivers/softpipe/sp_quad_stencil.c b/src/gallium/drivers/softpipe/sp_quad_stencil.c
new file mode 100644
index 0000000000..5e9d447737
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_stencil.c
@@ -0,0 +1,352 @@
+
+/**
+ * \brief Quad stencil testing
+ */
+
+
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_surface.h"
+#include "sp_tile_cache.h"
+#include "sp_quad_pipe.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+
+
+/** Only 8-bit stencil supported */
+#define STENCIL_MAX 0xff
+
+
+/**
+ * Do the basic stencil test (compare stencil buffer values against the
+ * reference value.
+ *
+ * \param stencilVals the stencil values from the stencil buffer
+ * \param func the stencil func (PIPE_FUNC_x)
+ * \param ref the stencil reference value
+ * \param valMask the stencil value mask indicating which bits of the stencil
+ * values and ref value are to be used.
+ * \return mask indicating which pixels passed the stencil test
+ */
+static unsigned
+do_stencil_test(const ubyte stencilVals[QUAD_SIZE], unsigned func,
+ unsigned ref, unsigned valMask)
+{
+ unsigned passMask = 0x0;
+ unsigned j;
+
+ ref &= valMask;
+
+ switch (func) {
+ case PIPE_FUNC_NEVER:
+ /* passMask = 0x0 */
+ break;
+ case PIPE_FUNC_LESS:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (ref < (stencilVals[j] & valMask)) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_EQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (ref == (stencilVals[j] & valMask)) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_LEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (ref <= (stencilVals[j] & valMask)) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_GREATER:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (ref > (stencilVals[j] & valMask)) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (ref != (stencilVals[j] & valMask)) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_GEQUAL:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (ref >= (stencilVals[j] & valMask)) {
+ passMask |= (1 << j);
+ }
+ }
+ break;
+ case PIPE_FUNC_ALWAYS:
+ passMask = MASK_ALL;
+ break;
+ default:
+ assert(0);
+ }
+
+ return passMask;
+}
+
+
+/**
+ * Apply the stencil operator to stencil values.
+ *
+ * \param stencilVals the stencil buffer values (read and written)
+ * \param mask indicates which pixels to update
+ * \param op the stencil operator (PIPE_STENCIL_OP_x)
+ * \param ref the stencil reference value
+ * \param wrtMask writemask controlling which bits are changed in the
+ * stencil values
+ */
+static void
+apply_stencil_op(ubyte stencilVals[QUAD_SIZE],
+ unsigned mask, unsigned op, ubyte ref, ubyte wrtMask)
+{
+ unsigned j;
+ ubyte newstencil[QUAD_SIZE];
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ newstencil[j] = stencilVals[j];
+ }
+
+ switch (op) {
+ case PIPE_STENCIL_OP_KEEP:
+ /* no-op */
+ break;
+ case PIPE_STENCIL_OP_ZERO:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = 0;
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_REPLACE:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = ref;
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_INCR:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ if (stencilVals[j] < STENCIL_MAX) {
+ newstencil[j] = stencilVals[j] + 1;
+ }
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_DECR:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ if (stencilVals[j] > 0) {
+ newstencil[j] = stencilVals[j] - 1;
+ }
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_INCR_WRAP:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = stencilVals[j] + 1;
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_DECR_WRAP:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = stencilVals[j] - 1;
+ }
+ }
+ break;
+ case PIPE_STENCIL_OP_INVERT:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ if (mask & (1 << j)) {
+ newstencil[j] = ~stencilVals[j];
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ /*
+ * update the stencil values
+ */
+ if (wrtMask != STENCIL_MAX) {
+ /* apply bit-wise stencil buffer writemask */
+ for (j = 0; j < QUAD_SIZE; j++) {
+ stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & stencilVals[j]);
+ }
+ }
+ else {
+ for (j = 0; j < QUAD_SIZE; j++) {
+ stencilVals[j] = newstencil[j];
+ }
+ }
+}
+
+
+/**
+ * Do stencil (and depth) testing. Stenciling depends on the outcome of
+ * depth testing.
+ */
+static void
+stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ struct softpipe_context *softpipe = qs->softpipe;
+ struct pipe_surface *ps = softpipe->framebuffer.zsbuf;
+ unsigned func, zFailOp, zPassOp, failOp;
+ ubyte ref, wrtMask, valMask;
+ ubyte stencilVals[QUAD_SIZE];
+ struct softpipe_cached_tile *tile
+ = sp_get_cached_tile(softpipe, softpipe->zsbuf_cache, quad->input.x0, quad->input.y0);
+ uint j;
+ uint face = quad->input.facing;
+
+ if (!softpipe->depth_stencil->stencil[1].enabled) {
+ /* single-sided stencil test, use front (face=0) state */
+ face = 0;
+ }
+
+ /* choose front or back face function, operator, etc */
+ /* XXX we could do these initializations once per primitive */
+ func = softpipe->depth_stencil->stencil[face].func;
+ failOp = softpipe->depth_stencil->stencil[face].fail_op;
+ zFailOp = softpipe->depth_stencil->stencil[face].zfail_op;
+ zPassOp = softpipe->depth_stencil->stencil[face].zpass_op;
+ ref = softpipe->depth_stencil->stencil[face].ref_value;
+ wrtMask = softpipe->depth_stencil->stencil[face].writemask;
+ valMask = softpipe->depth_stencil->stencil[face].valuemask;
+
+ assert(ps); /* shouldn't get here if there's no stencil buffer */
+
+ /* get stencil values from cached tile */
+ switch (ps->format) {
+ case PIPE_FORMAT_S8Z24_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ stencilVals[j] = tile->data.depth32[y][x] >> 24;
+ }
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ stencilVals[j] = tile->data.depth32[y][x] & 0xff;
+ }
+ break;
+ case PIPE_FORMAT_S8_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ stencilVals[j] = tile->data.stencil8[y][x];
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ /* do the stencil test first */
+ {
+ unsigned passMask, failMask;
+ passMask = do_stencil_test(stencilVals, func, ref, valMask);
+ failMask = quad->inout.mask & ~passMask;
+ quad->inout.mask &= passMask;
+
+ if (failOp != PIPE_STENCIL_OP_KEEP) {
+ apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask);
+ }
+ }
+
+ if (quad->inout.mask) {
+ /* now the pixels that passed the stencil test are depth tested */
+ if (softpipe->depth_stencil->depth.enabled) {
+ const unsigned origMask = quad->inout.mask;
+
+ sp_depth_test_quad(qs, quad); /* quad->mask is updated */
+
+ /* update stencil buffer values according to z pass/fail result */
+ if (zFailOp != PIPE_STENCIL_OP_KEEP) {
+ const unsigned failMask = origMask & ~quad->inout.mask;
+ apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask);
+ }
+
+ if (zPassOp != PIPE_STENCIL_OP_KEEP) {
+ const unsigned passMask = origMask & quad->inout.mask;
+ apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask);
+ }
+ }
+ else {
+ /* no depth test, apply Zpass operator to stencil buffer values */
+ apply_stencil_op(stencilVals, quad->inout.mask, zPassOp, ref, wrtMask);
+ }
+
+ }
+
+ /* put new stencil values into cached tile */
+ switch (ps->format) {
+ case PIPE_FORMAT_S8Z24_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ uint s8z24 = tile->data.depth32[y][x];
+ s8z24 = (stencilVals[j] << 24) | (s8z24 & 0xffffff);
+ tile->data.depth32[y][x] = s8z24;
+ }
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ uint z24s8 = tile->data.depth32[y][x];
+ z24s8 = (z24s8 & 0xffffff00) | stencilVals[j];
+ tile->data.depth32[y][x] = z24s8;
+ }
+ break;
+ case PIPE_FORMAT_S8_UNORM:
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int x = quad->input.x0 % TILE_SIZE + (j & 1);
+ int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+ tile->data.stencil8[y][x] = stencilVals[j];
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ if (quad->inout.mask)
+ qs->next->run(qs->next, quad);
+}
+
+
+static void stencil_begin(struct quad_stage *qs)
+{
+ qs->next->begin(qs->next);
+}
+
+
+static void stencil_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = stencil_begin;
+ stage->run = stencil_test_quad;
+ stage->destroy = stencil_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_quad_stipple.c b/src/gallium/drivers/softpipe/sp_quad_stipple.c
new file mode 100644
index 0000000000..07162db7b6
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_quad_stipple.c
@@ -0,0 +1,77 @@
+
+/**
+ * quad polygon stipple stage
+ */
+
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_quad_pipe.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+
+
+/**
+ * Apply polygon stipple to quads produced by triangle rasterization
+ */
+static void
+stipple_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+ static const uint bit31 = 1 << 31;
+ static const uint bit30 = 1 << 30;
+
+ if (quad->input.prim == QUAD_PRIM_TRI) {
+ struct softpipe_context *softpipe = qs->softpipe;
+ /* need to invert Y to index into OpenGL's stipple pattern */
+ const int col0 = quad->input.x0 % 32;
+ const int y0 = quad->input.y0;
+ const int y1 = y0 + 1;
+ const uint stipple0 = softpipe->poly_stipple.stipple[y0 % 32];
+ const uint stipple1 = softpipe->poly_stipple.stipple[y1 % 32];
+
+ /* turn off quad mask bits that fail the stipple test */
+ if ((stipple0 & (bit31 >> col0)) == 0)
+ quad->inout.mask &= ~MASK_TOP_LEFT;
+
+ if ((stipple0 & (bit30 >> col0)) == 0)
+ quad->inout.mask &= ~MASK_TOP_RIGHT;
+
+ if ((stipple1 & (bit31 >> col0)) == 0)
+ quad->inout.mask &= ~MASK_BOTTOM_LEFT;
+
+ if ((stipple1 & (bit30 >> col0)) == 0)
+ quad->inout.mask &= ~MASK_BOTTOM_RIGHT;
+
+ if (!quad->inout.mask) {
+ /* all fragments failed stipple test, end of quad pipeline */
+ return;
+ }
+ }
+
+ qs->next->run(qs->next, quad);
+}
+
+
+static void stipple_begin(struct quad_stage *qs)
+{
+ qs->next->begin(qs->next);
+}
+
+
+static void stipple_destroy(struct quad_stage *qs)
+{
+ FREE( qs );
+}
+
+
+struct quad_stage *
+sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe )
+{
+ struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+ stage->softpipe = softpipe;
+ stage->begin = stipple_begin;
+ stage->run = stipple_quad;
+ stage->destroy = stipple_destroy;
+
+ return stage;
+}
diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c
new file mode 100644
index 0000000000..379cf4ad06
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_query.c
@@ -0,0 +1,111 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_query.h"
+#include "sp_state.h"
+
+struct softpipe_query {
+ uint64_t start;
+ uint64_t end;
+};
+
+
+static struct softpipe_query *softpipe_query( struct pipe_query *p )
+{
+ return (struct softpipe_query *)p;
+}
+
+static struct pipe_query *
+softpipe_create_query(struct pipe_context *pipe,
+ unsigned type)
+{
+ assert(type == PIPE_QUERY_OCCLUSION_COUNTER);
+ return (struct pipe_query *)CALLOC_STRUCT( softpipe_query );
+}
+
+
+static void
+softpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+ FREE(q);
+}
+
+
+static void
+softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+ struct softpipe_query *sq = softpipe_query(q);
+
+ sq->start = softpipe->occlusion_count;
+ softpipe->active_query_count++;
+ softpipe->dirty |= SP_NEW_QUERY;
+}
+
+
+static void
+softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+ struct softpipe_query *sq = softpipe_query(q);
+
+ softpipe->active_query_count--;
+ sq->end = softpipe->occlusion_count;
+ softpipe->dirty |= SP_NEW_QUERY;
+}
+
+
+static boolean
+softpipe_get_query_result(struct pipe_context *pipe,
+ struct pipe_query *q,
+ boolean wait,
+ uint64_t *result )
+{
+ struct softpipe_query *sq = softpipe_query(q);
+ *result = sq->end - sq->start;
+ return TRUE;
+}
+
+
+void softpipe_init_query_funcs(struct softpipe_context *softpipe )
+{
+ softpipe->pipe.create_query = softpipe_create_query;
+ softpipe->pipe.destroy_query = softpipe_destroy_query;
+ softpipe->pipe.begin_query = softpipe_begin_query;
+ softpipe->pipe.end_query = softpipe_end_query;
+ softpipe->pipe.get_query_result = softpipe_get_query_result;
+}
+
+
diff --git a/src/gallium/drivers/softpipe/sp_query.h b/src/gallium/drivers/softpipe/sp_query.h
new file mode 100644
index 0000000000..05060a4575
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_query.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Author:
+ * Keith Whitwell
+ */
+
+#ifndef SP_QUERY_H
+#define SP_QUERY_H
+
+struct softpipe_context;
+extern void softpipe_init_query_funcs(struct softpipe_context * );
+
+
+#endif /* SP_QUERY_H */
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
new file mode 100644
index 0000000000..6178c4ac7e
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -0,0 +1,190 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "util/u_simple_screen.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+
+#include "sp_texture.h"
+#include "sp_winsys.h"
+#include "sp_screen.h"
+
+
+static const char *
+softpipe_get_vendor(struct pipe_screen *screen)
+{
+ return "Tungsten Graphics, Inc.";
+}
+
+
+static const char *
+softpipe_get_name(struct pipe_screen *screen)
+{
+ return "softpipe";
+}
+
+
+static int
+softpipe_get_param(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+ return PIPE_MAX_SAMPLERS;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ return PIPE_MAX_SAMPLERS;
+ case PIPE_CAP_NPOT_TEXTURES:
+ return 1;
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ return 1;
+ case PIPE_CAP_GLSL:
+ return 1;
+ case PIPE_CAP_S3TC:
+ return 0;
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ return 0;
+ case PIPE_CAP_POINT_SPRITE:
+ return 1;
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return PIPE_MAX_COLOR_BUFS;
+ case PIPE_CAP_OCCLUSION_QUERY:
+ return 1;
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ return 1;
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ return 1;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 13; /* max 4Kx4K */
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 8; /* max 128x128x128 */
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 13; /* max 4Kx4K */
+ case PIPE_CAP_TGSI_CONT_SUPPORTED:
+ return 1;
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+static float
+softpipe_get_paramf(struct pipe_screen *screen, int param)
+{
+ switch (param) {
+ case PIPE_CAP_MAX_LINE_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_LINE_WIDTH_AA:
+ return 255.0; /* arbitrary */
+ case PIPE_CAP_MAX_POINT_WIDTH:
+ /* fall-through */
+ case PIPE_CAP_MAX_POINT_WIDTH_AA:
+ return 255.0; /* arbitrary */
+ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+ return 16.0; /* not actually signficant at this time */
+ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+ return 16.0; /* arbitrary */
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ * Query format support for creating a texture, drawing surface, etc.
+ * \param format the format to test
+ * \param type one of PIPE_TEXTURE, PIPE_SURFACE
+ */
+static boolean
+softpipe_is_format_supported( struct pipe_screen *screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags )
+{
+ assert(target == PIPE_TEXTURE_1D ||
+ target == PIPE_TEXTURE_2D ||
+ target == PIPE_TEXTURE_3D ||
+ target == PIPE_TEXTURE_CUBE);
+
+ switch(format) {
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT5_RGBA:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+
+static void
+softpipe_destroy_screen( struct pipe_screen *screen )
+{
+ struct pipe_winsys *winsys = screen->winsys;
+
+ if(winsys->destroy)
+ winsys->destroy(winsys);
+
+ FREE(screen);
+}
+
+
+
+/**
+ * Create a new pipe_screen object
+ * Note: we're not presently subclassing pipe_screen (no softpipe_screen).
+ */
+struct pipe_screen *
+softpipe_create_screen(struct pipe_winsys *winsys)
+{
+ struct softpipe_screen *screen = CALLOC_STRUCT(softpipe_screen);
+
+ if (!screen)
+ return NULL;
+
+ screen->base.winsys = winsys;
+
+ screen->base.destroy = softpipe_destroy_screen;
+
+ screen->base.get_name = softpipe_get_name;
+ screen->base.get_vendor = softpipe_get_vendor;
+ screen->base.get_param = softpipe_get_param;
+ screen->base.get_paramf = softpipe_get_paramf;
+ screen->base.is_format_supported = softpipe_is_format_supported;
+
+ softpipe_init_screen_texture_funcs(&screen->base);
+ u_simple_screen_init(&screen->base);
+
+ return &screen->base;
+}
diff --git a/src/gallium/drivers/softpipe/sp_screen.h b/src/gallium/drivers/softpipe/sp_screen.h
new file mode 100644
index 0000000000..3d4bfd3e84
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_screen.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_SCREEN_H
+#define SP_SCREEN_H
+
+#include "pipe/p_screen.h"
+#include "pipe/p_defines.h"
+
+
+
+struct softpipe_screen {
+ struct pipe_screen base;
+
+ /* Increments whenever textures are modified. Contexts can track
+ * this.
+ */
+ unsigned timestamp;
+};
+
+
+
+
+static INLINE struct softpipe_screen *
+softpipe_screen( struct pipe_screen *pipe )
+{
+ return (struct softpipe_screen *)pipe;
+}
+
+
+#endif /* SP_SCREEN_H */
diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c
new file mode 100644
index 0000000000..de3ae3c369
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_setup.c
@@ -0,0 +1,1550 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \brief Primitive rasterization/rendering (points, lines, triangles)
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Brian Paul
+ */
+
+#include "sp_context.h"
+#include "sp_prim_setup.h"
+#include "sp_quad.h"
+#include "sp_quad_pipe.h"
+#include "sp_setup.h"
+#include "sp_state.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vertex.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_thread.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+
+#define DEBUG_VERTS 0
+#define DEBUG_FRAGS 0
+
+/**
+ * Triangle edge info
+ */
+struct edge {
+ float dx; /**< X(v1) - X(v0), used only during setup */
+ float dy; /**< Y(v1) - Y(v0), used only during setup */
+ float dxdy; /**< dx/dy */
+ float sx, sy; /**< first sample point coord */
+ int lines; /**< number of lines on this edge */
+};
+
+#if SP_NUM_QUAD_THREADS > 1
+
+/* Set to 1 if you want other threads to be instantly
+ * notified of pending jobs.
+ */
+#define INSTANT_NOTEMPTY_NOTIFY 0
+
+struct thread_info
+{
+ struct setup_context *setup;
+ uint id;
+ pipe_thread handle;
+};
+
+struct quad_job;
+
+typedef void (* quad_job_routine)( struct setup_context *setup, uint thread, struct quad_job *job );
+
+struct quad_job
+{
+ struct quad_header_input input;
+ struct quad_header_inout inout;
+ quad_job_routine routine;
+};
+
+#define NUM_QUAD_JOBS 64
+
+struct quad_job_que
+{
+ struct quad_job jobs[NUM_QUAD_JOBS];
+ uint first;
+ uint last;
+ pipe_mutex que_mutex;
+ pipe_condvar que_notfull_condvar;
+ pipe_condvar que_notempty_condvar;
+ uint jobs_added;
+ uint jobs_done;
+ pipe_condvar que_done_condvar;
+};
+
+static void
+add_quad_job( struct quad_job_que *que, struct quad_header *quad, quad_job_routine routine )
+{
+#if INSTANT_NOTEMPTY_NOTIFY
+ boolean empty;
+#endif
+
+ /* Wait for empty slot, see if the que is empty.
+ */
+ pipe_mutex_lock( que->que_mutex );
+ while ((que->last + 1) % NUM_QUAD_JOBS == que->first) {
+#if !INSTANT_NOTEMPTY_NOTIFY
+ pipe_condvar_broadcast( que->que_notempty_condvar );
+#endif
+ pipe_condvar_wait( que->que_notfull_condvar, que->que_mutex );
+ }
+#if INSTANT_NOTEMPTY_NOTIFY
+ empty = que->last == que->first;
+#endif
+ que->jobs_added++;
+ pipe_mutex_unlock( que->que_mutex );
+
+ /* Submit new job.
+ */
+ que->jobs[que->last].input = quad->input;
+ que->jobs[que->last].inout = quad->inout;
+ que->jobs[que->last].routine = routine;
+ que->last = (que->last + 1) % NUM_QUAD_JOBS;
+
+#if INSTANT_NOTEMPTY_NOTIFY
+ /* If the que was empty, notify consumers there's a job to be done.
+ */
+ if (empty) {
+ pipe_mutex_lock( que->que_mutex );
+ pipe_condvar_broadcast( que->que_notempty_condvar );
+ pipe_mutex_unlock( que->que_mutex );
+ }
+#endif
+}
+
+#endif
+
+/**
+ * Triangle setup info (derived from draw_stage).
+ * Also used for line drawing (taking some liberties).
+ */
+struct setup_context {
+ struct softpipe_context *softpipe;
+
+ /* Vertices are just an array of floats making up each attribute in
+ * turn. Currently fixed at 4 floats, but should change in time.
+ * Codegen will help cope with this.
+ */
+ const float (*vmax)[4];
+ const float (*vmid)[4];
+ const float (*vmin)[4];
+ const float (*vprovoke)[4];
+
+ struct edge ebot;
+ struct edge etop;
+ struct edge emaj;
+
+ float oneoverarea;
+
+ struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS];
+ struct tgsi_interp_coef posCoef; /* For Z, W */
+ struct quad_header quad;
+
+#if SP_NUM_QUAD_THREADS > 1
+ struct quad_job_que que;
+ struct thread_info threads[SP_NUM_QUAD_THREADS];
+#endif
+
+ struct {
+ int left[2]; /**< [0] = row0, [1] = row1 */
+ int right[2];
+ int y;
+ unsigned y_flags;
+ unsigned mask; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
+ } span;
+
+#if DEBUG_FRAGS
+ uint numFragsEmitted; /**< per primitive */
+ uint numFragsWritten; /**< per primitive */
+#endif
+
+ unsigned winding; /* which winding to cull */
+};
+
+#if SP_NUM_QUAD_THREADS > 1
+
+static PIPE_THREAD_ROUTINE( quad_thread, param )
+{
+ struct thread_info *info = (struct thread_info *) param;
+ struct quad_job_que *que = &info->setup->que;
+
+ for (;;) {
+ struct quad_job job;
+ boolean full;
+
+ /* Wait for an available job.
+ */
+ pipe_mutex_lock( que->que_mutex );
+ while (que->last == que->first)
+ pipe_condvar_wait( que->que_notempty_condvar, que->que_mutex );
+
+ /* See if the que is full.
+ */
+ full = (que->last + 1) % NUM_QUAD_JOBS == que->first;
+
+ /* Take a job and remove it from que.
+ */
+ job = que->jobs[que->first];
+ que->first = (que->first + 1) % NUM_QUAD_JOBS;
+
+ /* Notify the producer if the que is not full.
+ */
+ if (full)
+ pipe_condvar_signal( que->que_notfull_condvar );
+ pipe_mutex_unlock( que->que_mutex );
+
+ job.routine( info->setup, info->id, &job );
+
+ /* Notify the producer if that's the last finished job.
+ */
+ pipe_mutex_lock( que->que_mutex );
+ que->jobs_done++;
+ if (que->jobs_added == que->jobs_done)
+ pipe_condvar_signal( que->que_done_condvar );
+ pipe_mutex_unlock( que->que_mutex );
+ }
+
+ return NULL;
+}
+
+#define WAIT_FOR_COMPLETION(setup) \
+ do {\
+ pipe_mutex_lock( setup->que.que_mutex );\
+ if (!INSTANT_NOTEMPTY_NOTIFY)\
+ pipe_condvar_broadcast( setup->que.que_notempty_condvar );\
+ while (setup->que.jobs_added != setup->que.jobs_done)\
+ pipe_condvar_wait( setup->que.que_done_condvar, setup->que.que_mutex );\
+ pipe_mutex_unlock( setup->que.que_mutex );\
+ } while (0)
+
+#else
+
+#define WAIT_FOR_COMPLETION(setup) ((void) 0)
+
+#endif
+
+
+
+/**
+ * Do triangle cull test using tri determinant (sign indicates orientation)
+ * \return true if triangle is to be culled.
+ */
+static INLINE boolean
+cull_tri(const struct setup_context *setup, float det)
+{
+ if (det != 0) {
+ /* if (det < 0 then Z points toward camera and triangle is
+ * counter-clockwise winding.
+ */
+ unsigned winding = (det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW;
+
+ if ((winding & setup->winding) == 0)
+ return FALSE;
+ }
+
+ /* Culled:
+ */
+ return TRUE;
+}
+
+
+
+/**
+ * Clip setup->quad against the scissor/surface bounds.
+ */
+static INLINE void
+quad_clip( struct setup_context *setup, struct quad_header *quad )
+{
+ const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
+ const int minx = (int) cliprect->minx;
+ const int maxx = (int) cliprect->maxx;
+ const int miny = (int) cliprect->miny;
+ const int maxy = (int) cliprect->maxy;
+
+ if (quad->input.x0 >= maxx ||
+ quad->input.y0 >= maxy ||
+ quad->input.x0 + 1 < minx ||
+ quad->input.y0 + 1 < miny) {
+ /* totally clipped */
+ quad->inout.mask = 0x0;
+ return;
+ }
+ if (quad->input.x0 < minx)
+ quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
+ if (quad->input.y0 < miny)
+ quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
+ if (quad->input.x0 == maxx - 1)
+ quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
+ if (quad->input.y0 == maxy - 1)
+ quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
+}
+
+
+/**
+ * Emit a quad (pass to next stage) with clipping.
+ */
+static INLINE void
+clip_emit_quad( struct setup_context *setup, struct quad_header *quad, uint thread )
+{
+ quad_clip( setup, quad );
+ if (quad->inout.mask) {
+ struct softpipe_context *sp = setup->softpipe;
+
+ sp->quad[thread].first->run( sp->quad[thread].first, quad );
+ }
+}
+
+#if SP_NUM_QUAD_THREADS > 1
+
+static void
+clip_emit_quad_job( struct setup_context *setup, uint thread, struct quad_job *job )
+{
+ struct quad_header quad;
+
+ quad.input = job->input;
+ quad.inout = job->inout;
+ quad.coef = setup->quad.coef;
+ quad.posCoef = setup->quad.posCoef;
+ quad.nr_attrs = setup->quad.nr_attrs;
+ clip_emit_quad( setup, &quad, thread );
+}
+
+#define CLIP_EMIT_QUAD(setup) add_quad_job( &setup->que, &setup->quad, clip_emit_quad_job )
+
+#else
+
+#define CLIP_EMIT_QUAD(setup) clip_emit_quad( setup, &setup->quad, 0 )
+
+#endif
+
+/**
+ * Emit a quad (pass to next stage). No clipping is done.
+ */
+static INLINE void
+emit_quad( struct setup_context *setup, struct quad_header *quad, uint thread )
+{
+ struct softpipe_context *sp = setup->softpipe;
+#if DEBUG_FRAGS
+ uint mask = quad->inout.mask;
+#endif
+
+#if DEBUG_FRAGS
+ if (mask & 1) setup->numFragsEmitted++;
+ if (mask & 2) setup->numFragsEmitted++;
+ if (mask & 4) setup->numFragsEmitted++;
+ if (mask & 8) setup->numFragsEmitted++;
+#endif
+ sp->quad[thread].first->run( sp->quad[thread].first, quad );
+#if DEBUG_FRAGS
+ mask = quad->inout.mask;
+ if (mask & 1) setup->numFragsWritten++;
+ if (mask & 2) setup->numFragsWritten++;
+ if (mask & 4) setup->numFragsWritten++;
+ if (mask & 8) setup->numFragsWritten++;
+#endif
+}
+
+#if SP_NUM_QUAD_THREADS > 1
+
+static void
+emit_quad_job( struct setup_context *setup, uint thread, struct quad_job *job )
+{
+ struct quad_header quad;
+
+ quad.input = job->input;
+ quad.inout = job->inout;
+ quad.coef = setup->quad.coef;
+ quad.posCoef = setup->quad.posCoef;
+ quad.nr_attrs = setup->quad.nr_attrs;
+ emit_quad( setup, &quad, thread );
+}
+
+#define EMIT_QUAD(setup,x,y,mask) do {\
+ setup->quad.input.x0 = x;\
+ setup->quad.input.y0 = y;\
+ setup->quad.inout.mask = mask;\
+ add_quad_job( &setup->que, &setup->quad, emit_quad_job );\
+ } while (0)
+
+#else
+
+#define EMIT_QUAD(setup,x,y,mask) do {\
+ setup->quad.input.x0 = x;\
+ setup->quad.input.y0 = y;\
+ setup->quad.inout.mask = mask;\
+ emit_quad( setup, &setup->quad, 0 );\
+ } while (0)
+
+#endif
+
+/**
+ * Given an X or Y coordinate, return the block/quad coordinate that it
+ * belongs to.
+ */
+static INLINE int block( int x )
+{
+ return x & ~1;
+}
+
+
+/**
+ * Render a horizontal span of quads
+ */
+static void flush_spans( struct setup_context *setup )
+{
+ const int xleft0 = setup->span.left[0];
+ const int xleft1 = setup->span.left[1];
+ const int xright0 = setup->span.right[0];
+ const int xright1 = setup->span.right[1];
+ int minleft, maxright;
+ int x;
+
+ switch (setup->span.y_flags) {
+ case 0x3:
+ /* both odd and even lines written (both quad rows) */
+ minleft = block(MIN2(xleft0, xleft1));
+ maxright = block(MAX2(xright0, xright1));
+ for (x = minleft; x <= maxright; x += 2) {
+ /* determine which of the four pixels is inside the span bounds */
+ uint mask = 0x0;
+ if (x >= xleft0 && x < xright0)
+ mask |= MASK_TOP_LEFT;
+ if (x >= xleft1 && x < xright1)
+ mask |= MASK_BOTTOM_LEFT;
+ if (x+1 >= xleft0 && x+1 < xright0)
+ mask |= MASK_TOP_RIGHT;
+ if (x+1 >= xleft1 && x+1 < xright1)
+ mask |= MASK_BOTTOM_RIGHT;
+ if (mask)
+ EMIT_QUAD( setup, x, setup->span.y, mask );
+ }
+ break;
+
+ case 0x1:
+ /* only even line written (quad top row) */
+ minleft = block(xleft0);
+ maxright = block(xright0);
+ for (x = minleft; x <= maxright; x += 2) {
+ uint mask = 0x0;
+ if (x >= xleft0 && x < xright0)
+ mask |= MASK_TOP_LEFT;
+ if (x+1 >= xleft0 && x+1 < xright0)
+ mask |= MASK_TOP_RIGHT;
+ if (mask)
+ EMIT_QUAD( setup, x, setup->span.y, mask );
+ }
+ break;
+
+ case 0x2:
+ /* only odd line written (quad bottom row) */
+ minleft = block(xleft1);
+ maxright = block(xright1);
+ for (x = minleft; x <= maxright; x += 2) {
+ uint mask = 0x0;
+ if (x >= xleft1 && x < xright1)
+ mask |= MASK_BOTTOM_LEFT;
+ if (x+1 >= xleft1 && x+1 < xright1)
+ mask |= MASK_BOTTOM_RIGHT;
+ if (mask)
+ EMIT_QUAD( setup, x, setup->span.y, mask );
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ setup->span.y = 0;
+ setup->span.y_flags = 0;
+ setup->span.right[0] = 0;
+ setup->span.right[1] = 0;
+}
+
+
+#if DEBUG_VERTS
+static void print_vertex(const struct setup_context *setup,
+ const float (*v)[4])
+{
+ int i;
+ debug_printf(" Vertex: (%p)\n", v);
+ for (i = 0; i < setup->quad.nr_attrs; i++) {
+ debug_printf(" %d: %f %f %f %f\n", i,
+ v[i][0], v[i][1], v[i][2], v[i][3]);
+ if (util_is_inf_or_nan(v[i][0])) {
+ debug_printf(" NaN!\n");
+ }
+ }
+}
+#endif
+
+/**
+ * Sort the vertices from top to bottom order, setting up the triangle
+ * edge fields (ebot, emaj, etop).
+ * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
+ */
+static boolean setup_sort_vertices( struct setup_context *setup,
+ float det,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4] )
+{
+ setup->vprovoke = v2;
+
+ /* determine bottom to top order of vertices */
+ {
+ float y0 = v0[0][1];
+ float y1 = v1[0][1];
+ float y2 = v2[0][1];
+ if (y0 <= y1) {
+ if (y1 <= y2) {
+ /* y0<=y1<=y2 */
+ setup->vmin = v0;
+ setup->vmid = v1;
+ setup->vmax = v2;
+ }
+ else if (y2 <= y0) {
+ /* y2<=y0<=y1 */
+ setup->vmin = v2;
+ setup->vmid = v0;
+ setup->vmax = v1;
+ }
+ else {
+ /* y0<=y2<=y1 */
+ setup->vmin = v0;
+ setup->vmid = v2;
+ setup->vmax = v1;
+ }
+ }
+ else {
+ if (y0 <= y2) {
+ /* y1<=y0<=y2 */
+ setup->vmin = v1;
+ setup->vmid = v0;
+ setup->vmax = v2;
+ }
+ else if (y2 <= y1) {
+ /* y2<=y1<=y0 */
+ setup->vmin = v2;
+ setup->vmid = v1;
+ setup->vmax = v0;
+ }
+ else {
+ /* y1<=y2<=y0 */
+ setup->vmin = v1;
+ setup->vmid = v2;
+ setup->vmax = v0;
+ }
+ }
+ }
+
+ setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0];
+ setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1];
+ setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
+ setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
+ setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0];
+ setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1];
+
+ /*
+ * Compute triangle's area. Use 1/area to compute partial
+ * derivatives of attributes later.
+ *
+ * The area will be the same as prim->det, but the sign may be
+ * different depending on how the vertices get sorted above.
+ *
+ * To determine whether the primitive is front or back facing we
+ * use the prim->det value because its sign is correct.
+ */
+ {
+ const float area = (setup->emaj.dx * setup->ebot.dy -
+ setup->ebot.dx * setup->emaj.dy);
+
+ setup->oneoverarea = 1.0f / area;
+
+ /*
+ debug_printf("%s one-over-area %f area %f det %f\n",
+ __FUNCTION__, setup->oneoverarea, area, det );
+ */
+ if (util_is_inf_or_nan(setup->oneoverarea))
+ return FALSE;
+ }
+
+ /* We need to know if this is a front or back-facing triangle for:
+ * - the GLSL gl_FrontFacing fragment attribute (bool)
+ * - two-sided stencil test
+ */
+ setup->quad.input.facing = (det > 0.0) ^ (setup->softpipe->rasterizer->front_winding == PIPE_WINDING_CW);
+
+ return TRUE;
+}
+
+
+/**
+ * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
+ * The value value comes from vertex[slot][i].
+ * The result will be put into setup->coef[slot].a0[i].
+ * \param slot which attribute slot
+ * \param i which component of the slot (0..3)
+ */
+static void const_coeff( struct setup_context *setup,
+ struct tgsi_interp_coef *coef,
+ uint vertSlot, uint i)
+{
+ assert(i <= 3);
+
+ coef->dadx[i] = 0;
+ coef->dady[i] = 0;
+
+ /* need provoking vertex info!
+ */
+ coef->a0[i] = setup->vprovoke[vertSlot][i];
+}
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a triangle.
+ */
+static void tri_linear_coeff( struct setup_context *setup,
+ struct tgsi_interp_coef *coef,
+ uint vertSlot, uint i)
+{
+ float botda = setup->vmid[vertSlot][i] - setup->vmin[vertSlot][i];
+ float majda = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
+ float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+ float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+ float dadx = a * setup->oneoverarea;
+ float dady = b * setup->oneoverarea;
+
+ assert(i <= 3);
+
+ coef->dadx[i] = dadx;
+ coef->dady[i] = dady;
+
+ /* calculate a0 as the value which would be sampled for the
+ * fragment at (0,0), taking into account that we want to sample at
+ * pixel centers, in other words (0.5, 0.5).
+ *
+ * this is neat but unfortunately not a good way to do things for
+ * triangles with very large values of dadx or dady as it will
+ * result in the subtraction and re-addition from a0 of a very
+ * large number, which means we'll end up loosing a lot of the
+ * fractional bits and precision from a0. the way to fix this is
+ * to define a0 as the sample at a pixel center somewhere near vmin
+ * instead - i'll switch to this later.
+ */
+ coef->a0[i] = (setup->vmin[vertSlot][i] -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+
+ /*
+ debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
+ slot, "xyzw"[i],
+ setup->coef[slot].a0[i],
+ setup->coef[slot].dadx[i],
+ setup->coef[slot].dady[i]);
+ */
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a triangle.
+ * We basically multiply the vertex value by 1/w before computing
+ * the plane coefficients (a0, dadx, dady).
+ * Later, when we compute the value at a particular fragment position we'll
+ * divide the interpolated value by the interpolated W at that fragment.
+ */
+static void tri_persp_coeff( struct setup_context *setup,
+ struct tgsi_interp_coef *coef,
+ uint vertSlot, uint i)
+{
+ /* premultiply by 1/w (v[0][3] is always W):
+ */
+ float mina = setup->vmin[vertSlot][i] * setup->vmin[0][3];
+ float mida = setup->vmid[vertSlot][i] * setup->vmid[0][3];
+ float maxa = setup->vmax[vertSlot][i] * setup->vmax[0][3];
+ float botda = mida - mina;
+ float majda = maxa - mina;
+ float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+ float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+ float dadx = a * setup->oneoverarea;
+ float dady = b * setup->oneoverarea;
+
+ /*
+ debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
+ setup->vmin[vertSlot][i],
+ setup->vmid[vertSlot][i],
+ setup->vmax[vertSlot][i]
+ );
+ */
+ assert(i <= 3);
+
+ coef->dadx[i] = dadx;
+ coef->dady[i] = dady;
+ coef->a0[i] = (mina -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+}
+
+
+/**
+ * Special coefficient setup for gl_FragCoord.
+ * X and Y are trivial, though Y has to be inverted for OpenGL.
+ * Z and W are copied from posCoef which should have already been computed.
+ * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
+ */
+static void
+setup_fragcoord_coeff(struct setup_context *setup, uint slot)
+{
+ /*X*/
+ setup->coef[slot].a0[0] = 0;
+ setup->coef[slot].dadx[0] = 1.0;
+ setup->coef[slot].dady[0] = 0.0;
+ /*Y*/
+ setup->coef[slot].a0[1] = 0.0;
+ setup->coef[slot].dadx[1] = 0.0;
+ setup->coef[slot].dady[1] = 1.0;
+ /*Z*/
+ setup->coef[slot].a0[2] = setup->posCoef.a0[2];
+ setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
+ setup->coef[slot].dady[2] = setup->posCoef.dady[2];
+ /*W*/
+ setup->coef[slot].a0[3] = setup->posCoef.a0[3];
+ setup->coef[slot].dadx[3] = setup->posCoef.dadx[3];
+ setup->coef[slot].dady[3] = setup->posCoef.dady[3];
+}
+
+
+
+/**
+ * Compute the setup->coef[] array dadx, dady, a0 values.
+ * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
+ */
+static void setup_tri_coefficients( struct setup_context *setup )
+{
+ struct softpipe_context *softpipe = setup->softpipe;
+ const struct sp_fragment_shader *spfs = softpipe->fs;
+ const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
+ uint fragSlot;
+
+ /* z and w are done by linear interpolation:
+ */
+ tri_linear_coeff(setup, &setup->posCoef, 0, 2);
+ tri_linear_coeff(setup, &setup->posCoef, 0, 3);
+
+ /* setup interpolation for all the remaining attributes:
+ */
+ for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
+ const uint vertSlot = vinfo->attrib[fragSlot].src_index;
+ uint j;
+
+ switch (vinfo->attrib[fragSlot].interp_mode) {
+ case INTERP_CONSTANT:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ break;
+ case INTERP_LINEAR:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ break;
+ case INTERP_PERSPECTIVE:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ break;
+ case INTERP_POS:
+ setup_fragcoord_coeff(setup, fragSlot);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
+ setup->coef[fragSlot].a0[0] = 1.0f - setup->quad.input.facing;
+ setup->coef[fragSlot].dadx[0] = 0.0;
+ setup->coef[fragSlot].dady[0] = 0.0;
+ }
+ }
+}
+
+
+
+static void setup_tri_edges( struct setup_context *setup )
+{
+ float vmin_x = setup->vmin[0][0] + 0.5f;
+ float vmid_x = setup->vmid[0][0] + 0.5f;
+
+ float vmin_y = setup->vmin[0][1] - 0.5f;
+ float vmid_y = setup->vmid[0][1] - 0.5f;
+ float vmax_y = setup->vmax[0][1] - 0.5f;
+
+ setup->emaj.sy = ceilf(vmin_y);
+ setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
+ setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy;
+ setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
+
+ setup->etop.sy = ceilf(vmid_y);
+ setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
+ setup->etop.dxdy = setup->etop.dx / setup->etop.dy;
+ setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
+
+ setup->ebot.sy = ceilf(vmin_y);
+ setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
+ setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy;
+ setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
+}
+
+
+/**
+ * Render the upper or lower half of a triangle.
+ * Scissoring/cliprect is applied here too.
+ */
+static void subtriangle( struct setup_context *setup,
+ struct edge *eleft,
+ struct edge *eright,
+ unsigned lines )
+{
+ const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
+ const int minx = (int) cliprect->minx;
+ const int maxx = (int) cliprect->maxx;
+ const int miny = (int) cliprect->miny;
+ const int maxy = (int) cliprect->maxy;
+ int y, start_y, finish_y;
+ int sy = (int)eleft->sy;
+
+ assert((int)eleft->sy == (int) eright->sy);
+
+ /* clip top/bottom */
+ start_y = sy;
+ finish_y = sy + lines;
+
+ if (start_y < miny)
+ start_y = miny;
+
+ if (finish_y > maxy)
+ finish_y = maxy;
+
+ start_y -= sy;
+ finish_y -= sy;
+
+ /*
+ debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
+ */
+
+ for (y = start_y; y < finish_y; y++) {
+
+ /* avoid accumulating adds as floats don't have the precision to
+ * accurately iterate large triangle edges that way. luckily we
+ * can just multiply these days.
+ *
+ * this is all drowned out by the attribute interpolation anyway.
+ */
+ int left = (int)(eleft->sx + y * eleft->dxdy);
+ int right = (int)(eright->sx + y * eright->dxdy);
+
+ /* clip left/right */
+ if (left < minx)
+ left = minx;
+ if (right > maxx)
+ right = maxx;
+
+ if (left < right) {
+ int _y = sy + y;
+ if (block(_y) != setup->span.y) {
+ flush_spans(setup);
+ setup->span.y = block(_y);
+ }
+
+ setup->span.left[_y&1] = left;
+ setup->span.right[_y&1] = right;
+ setup->span.y_flags |= 1<<(_y&1);
+ }
+ }
+
+
+ /* save the values so that emaj can be restarted:
+ */
+ eleft->sx += lines * eleft->dxdy;
+ eright->sx += lines * eright->dxdy;
+ eleft->sy += lines;
+ eright->sy += lines;
+}
+
+
+/**
+ * Recalculate prim's determinant. This is needed as we don't have
+ * get this information through the vbuf_render interface & we must
+ * calculate it here.
+ */
+static float
+calc_det( const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4] )
+{
+ /* edge vectors e = v0 - v2, f = v1 - v2 */
+ const float ex = v0[0][0] - v2[0][0];
+ const float ey = v0[0][1] - v2[0][1];
+ const float fx = v1[0][0] - v2[0][0];
+ const float fy = v1[0][1] - v2[0][1];
+
+ /* det = cross(e,f).z */
+ return ex * fy - ey * fx;
+}
+
+
+/**
+ * Do setup for triangle rasterization, then render the triangle.
+ */
+void setup_tri( struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4] )
+{
+ float det;
+
+#if DEBUG_VERTS
+ debug_printf("Setup triangle:\n");
+ print_vertex(setup, v0);
+ print_vertex(setup, v1);
+ print_vertex(setup, v2);
+#endif
+
+ if (setup->softpipe->no_rast)
+ return;
+
+ det = calc_det(v0, v1, v2);
+ /*
+ debug_printf("%s\n", __FUNCTION__ );
+ */
+
+#if DEBUG_FRAGS
+ setup->numFragsEmitted = 0;
+ setup->numFragsWritten = 0;
+#endif
+
+ if (cull_tri( setup, det ))
+ return;
+
+ if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
+ return;
+ setup_tri_coefficients( setup );
+ setup_tri_edges( setup );
+
+ setup->quad.input.prim = QUAD_PRIM_TRI;
+
+ setup->span.y = 0;
+ setup->span.y_flags = 0;
+ setup->span.right[0] = 0;
+ setup->span.right[1] = 0;
+ /* setup->span.z_mode = tri_z_mode( setup->ctx ); */
+
+ /* init_constant_attribs( setup ); */
+
+ if (setup->oneoverarea < 0.0) {
+ /* emaj on left:
+ */
+ subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
+ subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
+ }
+ else {
+ /* emaj on right:
+ */
+ subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
+ subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
+ }
+
+ flush_spans( setup );
+
+ WAIT_FOR_COMPLETION(setup);
+
+#if DEBUG_FRAGS
+ printf("Tri: %u frags emitted, %u written\n",
+ setup->numFragsEmitted,
+ setup->numFragsWritten);
+#endif
+}
+
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a line.
+ */
+static void
+line_linear_coeff(const struct setup_context *setup,
+ struct tgsi_interp_coef *coef,
+ uint vertSlot, uint i)
+{
+ const float da = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
+ const float dadx = da * setup->emaj.dx * setup->oneoverarea;
+ const float dady = da * setup->emaj.dy * setup->oneoverarea;
+ coef->dadx[i] = dadx;
+ coef->dady[i] = dady;
+ coef->a0[i] = (setup->vmin[vertSlot][i] -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a line.
+ */
+static void
+line_persp_coeff(const struct setup_context *setup,
+ struct tgsi_interp_coef *coef,
+ uint vertSlot, uint i)
+{
+ /* XXX double-check/verify this arithmetic */
+ const float a0 = setup->vmin[vertSlot][i] * setup->vmin[0][3];
+ const float a1 = setup->vmax[vertSlot][i] * setup->vmax[0][3];
+ const float da = a1 - a0;
+ const float dadx = da * setup->emaj.dx * setup->oneoverarea;
+ const float dady = da * setup->emaj.dy * setup->oneoverarea;
+ coef->dadx[i] = dadx;
+ coef->dady[i] = dady;
+ coef->a0[i] = (setup->vmin[vertSlot][i] -
+ (dadx * (setup->vmin[0][0] - 0.5f) +
+ dady * (setup->vmin[0][1] - 0.5f)));
+}
+
+
+/**
+ * Compute the setup->coef[] array dadx, dady, a0 values.
+ * Must be called after setup->vmin,vmax are initialized.
+ */
+static INLINE boolean
+setup_line_coefficients(struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4])
+{
+ struct softpipe_context *softpipe = setup->softpipe;
+ const struct sp_fragment_shader *spfs = softpipe->fs;
+ const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
+ uint fragSlot;
+ float area;
+
+ /* use setup->vmin, vmax to point to vertices */
+ if (softpipe->rasterizer->flatshade_first)
+ setup->vprovoke = v0;
+ else
+ setup->vprovoke = v1;
+ setup->vmin = v0;
+ setup->vmax = v1;
+
+ setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
+ setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
+
+ /* NOTE: this is not really area but something proportional to it */
+ area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy;
+ if (area == 0.0f || util_is_inf_or_nan(area))
+ return FALSE;
+ setup->oneoverarea = 1.0f / area;
+
+ /* z and w are done by linear interpolation:
+ */
+ line_linear_coeff(setup, &setup->posCoef, 0, 2);
+ line_linear_coeff(setup, &setup->posCoef, 0, 3);
+
+ /* setup interpolation for all the remaining attributes:
+ */
+ for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
+ const uint vertSlot = vinfo->attrib[fragSlot].src_index;
+ uint j;
+
+ switch (vinfo->attrib[fragSlot].interp_mode) {
+ case INTERP_CONSTANT:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ break;
+ case INTERP_LINEAR:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ break;
+ case INTERP_PERSPECTIVE:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ break;
+ case INTERP_POS:
+ setup_fragcoord_coeff(setup, fragSlot);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
+ setup->coef[fragSlot].a0[0] = 1.0f - setup->quad.input.facing;
+ setup->coef[fragSlot].dadx[0] = 0.0;
+ setup->coef[fragSlot].dady[0] = 0.0;
+ }
+ }
+ return TRUE;
+}
+
+
+/**
+ * Plot a pixel in a line segment.
+ */
+static INLINE void
+plot(struct setup_context *setup, int x, int y)
+{
+ const int iy = y & 1;
+ const int ix = x & 1;
+ const int quadX = x - ix;
+ const int quadY = y - iy;
+ const int mask = (1 << ix) << (2 * iy);
+
+ if (quadX != setup->quad.input.x0 ||
+ quadY != setup->quad.input.y0)
+ {
+ /* flush prev quad, start new quad */
+
+ if (setup->quad.input.x0 != -1)
+ CLIP_EMIT_QUAD(setup);
+
+ setup->quad.input.x0 = quadX;
+ setup->quad.input.y0 = quadY;
+ setup->quad.inout.mask = 0x0;
+ }
+
+ setup->quad.inout.mask |= mask;
+}
+
+
+/**
+ * Do setup for line rasterization, then render the line.
+ * Single-pixel width, no stipple, etc. We rely on the 'draw' module
+ * to handle stippling and wide lines.
+ */
+void
+setup_line(struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4])
+{
+ int x0 = (int) v0[0][0];
+ int x1 = (int) v1[0][0];
+ int y0 = (int) v0[0][1];
+ int y1 = (int) v1[0][1];
+ int dx = x1 - x0;
+ int dy = y1 - y0;
+ int xstep, ystep;
+
+#if DEBUG_VERTS
+ debug_printf("Setup line:\n");
+ print_vertex(setup, v0);
+ print_vertex(setup, v1);
+#endif
+
+ if (setup->softpipe->no_rast)
+ return;
+
+ if (dx == 0 && dy == 0)
+ return;
+
+ if (!setup_line_coefficients(setup, v0, v1))
+ return;
+
+ assert(v0[0][0] < 1.0e9);
+ assert(v0[0][1] < 1.0e9);
+ assert(v1[0][0] < 1.0e9);
+ assert(v1[0][1] < 1.0e9);
+
+ if (dx < 0) {
+ dx = -dx; /* make positive */
+ xstep = -1;
+ }
+ else {
+ xstep = 1;
+ }
+
+ if (dy < 0) {
+ dy = -dy; /* make positive */
+ ystep = -1;
+ }
+ else {
+ ystep = 1;
+ }
+
+ assert(dx >= 0);
+ assert(dy >= 0);
+
+ setup->quad.input.x0 = setup->quad.input.y0 = -1;
+ setup->quad.inout.mask = 0x0;
+ setup->quad.input.prim = QUAD_PRIM_LINE;
+ /* XXX temporary: set coverage to 1.0 so the line appears
+ * if AA mode happens to be enabled.
+ */
+ setup->quad.input.coverage[0] =
+ setup->quad.input.coverage[1] =
+ setup->quad.input.coverage[2] =
+ setup->quad.input.coverage[3] = 1.0;
+
+ if (dx > dy) {
+ /*** X-major line ***/
+ int i;
+ const int errorInc = dy + dy;
+ int error = errorInc - dx;
+ const int errorDec = error - dx;
+
+ for (i = 0; i < dx; i++) {
+ plot(setup, x0, y0);
+
+ x0 += xstep;
+ if (error < 0) {
+ error += errorInc;
+ }
+ else {
+ error += errorDec;
+ y0 += ystep;
+ }
+ }
+ }
+ else {
+ /*** Y-major line ***/
+ int i;
+ const int errorInc = dx + dx;
+ int error = errorInc - dy;
+ const int errorDec = error - dy;
+
+ for (i = 0; i < dy; i++) {
+ plot(setup, x0, y0);
+
+ y0 += ystep;
+ if (error < 0) {
+ error += errorInc;
+ }
+ else {
+ error += errorDec;
+ x0 += xstep;
+ }
+ }
+ }
+
+ /* draw final quad */
+ if (setup->quad.inout.mask) {
+ CLIP_EMIT_QUAD(setup);
+ }
+
+ WAIT_FOR_COMPLETION(setup);
+}
+
+
+static void
+point_persp_coeff(const struct setup_context *setup,
+ const float (*vert)[4],
+ struct tgsi_interp_coef *coef,
+ uint vertSlot, uint i)
+{
+ assert(i <= 3);
+ coef->dadx[i] = 0.0F;
+ coef->dady[i] = 0.0F;
+ coef->a0[i] = vert[vertSlot][i] * vert[0][3];
+}
+
+
+/**
+ * Do setup for point rasterization, then render the point.
+ * Round or square points...
+ * XXX could optimize a lot for 1-pixel points.
+ */
+void
+setup_point( struct setup_context *setup,
+ const float (*v0)[4] )
+{
+ struct softpipe_context *softpipe = setup->softpipe;
+ const struct sp_fragment_shader *spfs = softpipe->fs;
+ const int sizeAttr = setup->softpipe->psize_slot;
+ const float size
+ = sizeAttr > 0 ? v0[sizeAttr][0]
+ : setup->softpipe->rasterizer->point_size;
+ const float halfSize = 0.5F * size;
+ const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth;
+ const float x = v0[0][0]; /* Note: data[0] is always position */
+ const float y = v0[0][1];
+ const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
+ uint fragSlot;
+
+#if DEBUG_VERTS
+ debug_printf("Setup point:\n");
+ print_vertex(setup, v0);
+#endif
+
+ if (softpipe->no_rast)
+ return;
+
+ /* For points, all interpolants are constant-valued.
+ * However, for point sprites, we'll need to setup texcoords appropriately.
+ * XXX: which coefficients are the texcoords???
+ * We may do point sprites as textured quads...
+ *
+ * KW: We don't know which coefficients are texcoords - ultimately
+ * the choice of what interpolation mode to use for each attribute
+ * should be determined by the fragment program, using
+ * per-attribute declaration statements that include interpolation
+ * mode as a parameter. So either the fragment program will have
+ * to be adjusted for pointsprite vs normal point behaviour, or
+ * otherwise a special interpolation mode will have to be defined
+ * which matches the required behaviour for point sprites. But -
+ * the latter is not a feature of normal hardware, and as such
+ * probably should be ruled out on that basis.
+ */
+ setup->vprovoke = v0;
+
+ /* setup Z, W */
+ const_coeff(setup, &setup->posCoef, 0, 2);
+ const_coeff(setup, &setup->posCoef, 0, 3);
+
+ for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
+ const uint vertSlot = vinfo->attrib[fragSlot].src_index;
+ uint j;
+
+ switch (vinfo->attrib[fragSlot].interp_mode) {
+ case INTERP_CONSTANT:
+ /* fall-through */
+ case INTERP_LINEAR:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+ break;
+ case INTERP_PERSPECTIVE:
+ for (j = 0; j < NUM_CHANNELS; j++)
+ point_persp_coeff(setup, setup->vprovoke,
+ &setup->coef[fragSlot], vertSlot, j);
+ break;
+ case INTERP_POS:
+ setup_fragcoord_coeff(setup, fragSlot);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
+ setup->coef[fragSlot].a0[0] = 1.0f - setup->quad.input.facing;
+ setup->coef[fragSlot].dadx[0] = 0.0;
+ setup->coef[fragSlot].dady[0] = 0.0;
+ }
+ }
+
+ setup->quad.input.prim = QUAD_PRIM_POINT;
+
+ if (halfSize <= 0.5 && !round) {
+ /* special case for 1-pixel points */
+ const int ix = ((int) x) & 1;
+ const int iy = ((int) y) & 1;
+ setup->quad.input.x0 = (int) x - ix;
+ setup->quad.input.y0 = (int) y - iy;
+ setup->quad.inout.mask = (1 << ix) << (2 * iy);
+ CLIP_EMIT_QUAD(setup);
+ }
+ else {
+ if (round) {
+ /* rounded points */
+ const int ixmin = block((int) (x - halfSize));
+ const int ixmax = block((int) (x + halfSize));
+ const int iymin = block((int) (y - halfSize));
+ const int iymax = block((int) (y + halfSize));
+ const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */
+ const float rmax = halfSize + 0.7071F;
+ const float rmin2 = MAX2(0.0F, rmin * rmin);
+ const float rmax2 = rmax * rmax;
+ const float cscale = 1.0F / (rmax2 - rmin2);
+ int ix, iy;
+
+ for (iy = iymin; iy <= iymax; iy += 2) {
+ for (ix = ixmin; ix <= ixmax; ix += 2) {
+ float dx, dy, dist2, cover;
+
+ setup->quad.inout.mask = 0x0;
+
+ dx = (ix + 0.5f) - x;
+ dy = (iy + 0.5f) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad.input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
+ setup->quad.inout.mask |= MASK_TOP_LEFT;
+ }
+
+ dx = (ix + 1.5f) - x;
+ dy = (iy + 0.5f) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad.input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
+ setup->quad.inout.mask |= MASK_TOP_RIGHT;
+ }
+
+ dx = (ix + 0.5f) - x;
+ dy = (iy + 1.5f) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad.input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
+ setup->quad.inout.mask |= MASK_BOTTOM_LEFT;
+ }
+
+ dx = (ix + 1.5f) - x;
+ dy = (iy + 1.5f) - y;
+ dist2 = dx * dx + dy * dy;
+ if (dist2 <= rmax2) {
+ cover = 1.0F - (dist2 - rmin2) * cscale;
+ setup->quad.input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
+ setup->quad.inout.mask |= MASK_BOTTOM_RIGHT;
+ }
+
+ if (setup->quad.inout.mask) {
+ setup->quad.input.x0 = ix;
+ setup->quad.input.y0 = iy;
+ CLIP_EMIT_QUAD(setup);
+ }
+ }
+ }
+ }
+ else {
+ /* square points */
+ const int xmin = (int) (x + 0.75 - halfSize);
+ const int ymin = (int) (y + 0.25 - halfSize);
+ const int xmax = xmin + (int) size;
+ const int ymax = ymin + (int) size;
+ /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
+ const int ixmin = block(xmin);
+ const int ixmax = block(xmax - 1);
+ const int iymin = block(ymin);
+ const int iymax = block(ymax - 1);
+ int ix, iy;
+
+ /*
+ debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
+ */
+ for (iy = iymin; iy <= iymax; iy += 2) {
+ uint rowMask = 0xf;
+ if (iy < ymin) {
+ /* above the top edge */
+ rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
+ }
+ if (iy + 1 >= ymax) {
+ /* below the bottom edge */
+ rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
+ }
+
+ for (ix = ixmin; ix <= ixmax; ix += 2) {
+ uint mask = rowMask;
+
+ if (ix < xmin) {
+ /* fragment is past left edge of point, turn off left bits */
+ mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
+ }
+ if (ix + 1 >= xmax) {
+ /* past the right edge */
+ mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
+ }
+
+ setup->quad.inout.mask = mask;
+ setup->quad.input.x0 = ix;
+ setup->quad.input.y0 = iy;
+ CLIP_EMIT_QUAD(setup);
+ }
+ }
+ }
+ }
+
+ WAIT_FOR_COMPLETION(setup);
+}
+
+void setup_prepare( struct setup_context *setup )
+{
+ struct softpipe_context *sp = setup->softpipe;
+ unsigned i;
+
+ if (sp->dirty) {
+ softpipe_update_derived(sp);
+ }
+
+ /* Note: nr_attrs is only used for debugging (vertex printing) */
+ setup->quad.nr_attrs = draw_num_vs_outputs(sp->draw);
+
+ for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
+ sp->quad[i].first->begin( sp->quad[i].first );
+ }
+
+ if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
+ sp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL &&
+ sp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) {
+ /* we'll do culling */
+ setup->winding = sp->rasterizer->cull_mode;
+ }
+ else {
+ /* 'draw' will do culling */
+ setup->winding = PIPE_WINDING_NONE;
+ }
+}
+
+
+
+void setup_destroy_context( struct setup_context *setup )
+{
+ FREE( setup );
+}
+
+
+/**
+ * Create a new primitive setup/render stage.
+ */
+struct setup_context *setup_create_context( struct softpipe_context *softpipe )
+{
+ struct setup_context *setup = CALLOC_STRUCT(setup_context);
+#if SP_NUM_QUAD_THREADS > 1
+ uint i;
+#endif
+
+ setup->softpipe = softpipe;
+
+ setup->quad.coef = setup->coef;
+ setup->quad.posCoef = &setup->posCoef;
+
+#if SP_NUM_QUAD_THREADS > 1
+ setup->que.first = 0;
+ setup->que.last = 0;
+ pipe_mutex_init( setup->que.que_mutex );
+ pipe_condvar_init( setup->que.que_notfull_condvar );
+ pipe_condvar_init( setup->que.que_notempty_condvar );
+ setup->que.jobs_added = 0;
+ setup->que.jobs_done = 0;
+ pipe_condvar_init( setup->que.que_done_condvar );
+ for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
+ setup->threads[i].setup = setup;
+ setup->threads[i].id = i;
+ setup->threads[i].handle = pipe_thread_create( quad_thread, &setup->threads[i] );
+ }
+#endif
+
+ return setup;
+}
+
diff --git a/src/gallium/drivers/softpipe/sp_setup.h b/src/gallium/drivers/softpipe/sp_setup.h
new file mode 100644
index 0000000000..d54f334428
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_setup.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+#ifndef SP_SETUP_H
+#define SP_SETUP_H
+
+struct setup_context;
+struct softpipe_context;
+
+void
+setup_tri( struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4] );
+
+void
+setup_line(struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4]);
+
+void
+setup_point( struct setup_context *setup,
+ const float (*v0)[4] );
+
+
+struct setup_context *setup_create_context( struct softpipe_context *softpipe );
+void setup_prepare( struct setup_context *setup );
+void setup_destroy_context( struct setup_context *setup );
+
+#endif
diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
new file mode 100644
index 0000000000..9776e978e3
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state.h
@@ -0,0 +1,206 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_STATE_H
+#define SP_STATE_H
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+
+
+#define SP_NEW_VIEWPORT 0x1
+#define SP_NEW_RASTERIZER 0x2
+#define SP_NEW_FS 0x4
+#define SP_NEW_BLEND 0x8
+#define SP_NEW_CLIP 0x10
+#define SP_NEW_SCISSOR 0x20
+#define SP_NEW_STIPPLE 0x40
+#define SP_NEW_FRAMEBUFFER 0x80
+#define SP_NEW_DEPTH_STENCIL_ALPHA 0x100
+#define SP_NEW_CONSTANTS 0x200
+#define SP_NEW_SAMPLER 0x400
+#define SP_NEW_TEXTURE 0x800
+#define SP_NEW_VERTEX 0x1000
+#define SP_NEW_VS 0x2000
+#define SP_NEW_QUERY 0x4000
+
+
+struct tgsi_sampler;
+struct tgsi_exec_machine;
+struct vertex_info;
+
+
+/**
+ * Subclass of pipe_shader_state (though it doesn't really need to be).
+ *
+ * This is starting to look an awful lot like a quad pipeline stage...
+ */
+struct sp_fragment_shader {
+ struct pipe_shader_state shader;
+
+ struct tgsi_shader_info info;
+
+ void (*prepare)( const struct sp_fragment_shader *shader,
+ struct tgsi_exec_machine *machine,
+ struct tgsi_sampler **samplers);
+
+ /* Run the shader - this interface will get cleaned up in the
+ * future:
+ */
+ unsigned (*run)( const struct sp_fragment_shader *shader,
+ struct tgsi_exec_machine *machine,
+ struct quad_header *quad );
+
+
+ void (*delete)( struct sp_fragment_shader * );
+};
+
+
+/** Subclass of pipe_shader_state */
+struct sp_vertex_shader {
+ struct pipe_shader_state shader;
+ struct draw_vertex_shader *draw_data;
+};
+
+
+
+void *
+softpipe_create_blend_state(struct pipe_context *,
+ const struct pipe_blend_state *);
+void softpipe_bind_blend_state(struct pipe_context *,
+ void *);
+void softpipe_delete_blend_state(struct pipe_context *,
+ void *);
+
+void *
+softpipe_create_sampler_state(struct pipe_context *,
+ const struct pipe_sampler_state *);
+void softpipe_bind_sampler_states(struct pipe_context *, unsigned, void **);
+void softpipe_delete_sampler_state(struct pipe_context *, void *);
+
+void *
+softpipe_create_depth_stencil_state(struct pipe_context *,
+ const struct pipe_depth_stencil_alpha_state *);
+void softpipe_bind_depth_stencil_state(struct pipe_context *, void *);
+void softpipe_delete_depth_stencil_state(struct pipe_context *, void *);
+
+void *
+softpipe_create_rasterizer_state(struct pipe_context *,
+ const struct pipe_rasterizer_state *);
+void softpipe_bind_rasterizer_state(struct pipe_context *, void *);
+void softpipe_delete_rasterizer_state(struct pipe_context *, void *);
+
+void softpipe_set_framebuffer_state( struct pipe_context *,
+ const struct pipe_framebuffer_state * );
+
+void softpipe_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color );
+
+void softpipe_set_clip_state( struct pipe_context *,
+ const struct pipe_clip_state * );
+
+void softpipe_set_constant_buffer(struct pipe_context *,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf);
+
+void *softpipe_create_fs_state(struct pipe_context *,
+ const struct pipe_shader_state *);
+void softpipe_bind_fs_state(struct pipe_context *, void *);
+void softpipe_delete_fs_state(struct pipe_context *, void *);
+void *softpipe_create_vs_state(struct pipe_context *,
+ const struct pipe_shader_state *);
+void softpipe_bind_vs_state(struct pipe_context *, void *);
+void softpipe_delete_vs_state(struct pipe_context *, void *);
+
+void softpipe_set_polygon_stipple( struct pipe_context *,
+ const struct pipe_poly_stipple * );
+
+void softpipe_set_scissor_state( struct pipe_context *,
+ const struct pipe_scissor_state * );
+
+void softpipe_set_sampler_textures( struct pipe_context *,
+ unsigned num,
+ struct pipe_texture ** );
+
+void softpipe_set_viewport_state( struct pipe_context *,
+ const struct pipe_viewport_state * );
+
+void softpipe_set_vertex_elements(struct pipe_context *,
+ unsigned count,
+ const struct pipe_vertex_element *);
+
+void softpipe_set_vertex_buffers(struct pipe_context *,
+ unsigned count,
+ const struct pipe_vertex_buffer *);
+
+
+void softpipe_update_derived( struct softpipe_context *softpipe );
+
+
+boolean softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
+ unsigned start, unsigned count);
+
+boolean softpipe_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count);
+boolean
+softpipe_draw_range_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned min_index,
+ unsigned max_index,
+ unsigned mode, unsigned start, unsigned count);
+
+void
+softpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags);
+
+
+void
+softpipe_map_transfers(struct softpipe_context *sp);
+
+void
+softpipe_unmap_transfers(struct softpipe_context *sp);
+
+void
+softpipe_map_texture_surfaces(struct softpipe_context *sp);
+
+void
+softpipe_unmap_texture_surfaces(struct softpipe_context *sp);
+
+
+struct vertex_info *
+softpipe_get_vertex_info(struct softpipe_context *softpipe);
+
+struct vertex_info *
+softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe);
+
+
+#endif
diff --git a/src/gallium/drivers/softpipe/sp_state_blend.c b/src/gallium/drivers/softpipe/sp_state_blend.c
new file mode 100644
index 0000000000..384fe559af
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state_blend.c
@@ -0,0 +1,98 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_state.h"
+
+
+void *
+softpipe_create_blend_state(struct pipe_context *pipe,
+ const struct pipe_blend_state *blend)
+{
+ return mem_dup(blend, sizeof(*blend));
+}
+
+void softpipe_bind_blend_state( struct pipe_context *pipe,
+ void *blend )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->blend = (const struct pipe_blend_state *)blend;
+
+ softpipe->dirty |= SP_NEW_BLEND;
+}
+
+void softpipe_delete_blend_state(struct pipe_context *pipe,
+ void *blend)
+{
+ FREE( blend );
+}
+
+
+void softpipe_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->blend_color = *blend_color;
+
+ softpipe->dirty |= SP_NEW_BLEND;
+}
+
+
+/** XXX move someday? Or consolidate all these simple state setters
+ * into one file.
+ */
+
+
+void *
+softpipe_create_depth_stencil_state(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *depth_stencil)
+{
+ return mem_dup(depth_stencil, sizeof(*depth_stencil));
+}
+
+void
+softpipe_bind_depth_stencil_state(struct pipe_context *pipe,
+ void *depth_stencil)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->depth_stencil = (const struct pipe_depth_stencil_alpha_state *)depth_stencil;
+
+ softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA;
+}
+
+void
+softpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth)
+{
+ FREE( depth );
+}
diff --git a/src/gallium/drivers/softpipe/sp_state_clip.c b/src/gallium/drivers/softpipe/sp_state_clip.c
new file mode 100644
index 0000000000..4946c776e3
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state_clip.c
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "sp_context.h"
+#include "sp_state.h"
+#include "draw/draw_context.h"
+
+
+void softpipe_set_clip_state( struct pipe_context *pipe,
+ const struct pipe_clip_state *clip )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ /* pass the clip state to the draw module */
+ draw_set_clip_state(softpipe->draw, clip);
+}
+
+
+void softpipe_set_viewport_state( struct pipe_context *pipe,
+ const struct pipe_viewport_state *viewport )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ /* pass the viewport info to the draw module */
+ draw_set_viewport_state(softpipe->draw, viewport);
+
+ softpipe->viewport = *viewport; /* struct copy */
+ softpipe->dirty |= SP_NEW_VIEWPORT;
+}
+
+
+void softpipe_set_scissor_state( struct pipe_context *pipe,
+ const struct pipe_scissor_state *scissor )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ draw_flush(softpipe->draw);
+
+ softpipe->scissor = *scissor; /* struct copy */
+ softpipe->dirty |= SP_NEW_SCISSOR;
+}
+
+
+void softpipe_set_polygon_stipple( struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple )
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ draw_flush(softpipe->draw);
+
+ softpipe->poly_stipple = *stipple; /* struct copy */
+ softpipe->dirty |= SP_NEW_STIPPLE;
+}
diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c
new file mode 100644
index 0000000000..75551000c9
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state_derived.c
@@ -0,0 +1,211 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_private.h"
+#include "sp_context.h"
+#include "sp_state.h"
+
+
+/**
+ * Mark the current vertex layout as "invalid".
+ * We'll validate the vertex layout later, when we start to actually
+ * render a point or line or tri.
+ */
+static void
+invalidate_vertex_layout(struct softpipe_context *softpipe)
+{
+ softpipe->vertex_info.num_attribs = 0;
+}
+
+
+/**
+ * The vertex info describes how to convert the post-transformed vertices
+ * (simple float[][4]) used by the 'draw' module into vertices for
+ * rasterization.
+ *
+ * This function validates the vertex layout and returns a pointer to a
+ * vertex_info object.
+ */
+struct vertex_info *
+softpipe_get_vertex_info(struct softpipe_context *softpipe)
+{
+ struct vertex_info *vinfo = &softpipe->vertex_info;
+
+ if (vinfo->num_attribs == 0) {
+ /* compute vertex layout now */
+ const struct sp_fragment_shader *spfs = softpipe->fs;
+ const enum interp_mode colorInterp
+ = softpipe->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
+ uint i;
+
+ if (softpipe->vbuf) {
+ /* if using the post-transform vertex buffer, tell draw_vbuf to
+ * simply emit the whole post-xform vertex as-is:
+ */
+ struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
+ const uint num = draw_num_vs_outputs(softpipe->draw);
+ uint i;
+
+ /* No longer any need to try and emit draw vertex_header info.
+ */
+ vinfo_vbuf->num_attribs = 0;
+ for (i = 0; i < num; i++) {
+ draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
+ }
+ draw_compute_vertex_size(vinfo_vbuf);
+ }
+
+ /*
+ * Loop over fragment shader inputs, searching for the matching output
+ * from the vertex shader.
+ */
+ vinfo->num_attribs = 0;
+ for (i = 0; i < spfs->info.num_inputs; i++) {
+ int src;
+ switch (spfs->info.input_semantic_name[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ src = draw_find_vs_output(softpipe->draw,
+ TGSI_SEMANTIC_POSITION, 0);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_POS, src);
+ break;
+
+ case TGSI_SEMANTIC_COLOR:
+ src = draw_find_vs_output(softpipe->draw, TGSI_SEMANTIC_COLOR,
+ spfs->info.input_semantic_index[i]);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
+ break;
+
+ case TGSI_SEMANTIC_FOG:
+ src = draw_find_vs_output(softpipe->draw, TGSI_SEMANTIC_FOG, 0);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ break;
+
+ case TGSI_SEMANTIC_GENERIC:
+ case TGSI_SEMANTIC_FACE:
+ /* this includes texcoords and varying vars */
+ src = draw_find_vs_output(softpipe->draw, TGSI_SEMANTIC_GENERIC,
+ spfs->info.input_semantic_index[i]);
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
+ break;
+
+ default:
+ assert(0);
+ }
+ }
+
+ softpipe->psize_slot = draw_find_vs_output(softpipe->draw,
+ TGSI_SEMANTIC_PSIZE, 0);
+ if (softpipe->psize_slot > 0) {
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
+ softpipe->psize_slot);
+ }
+
+ draw_compute_vertex_size(vinfo);
+ }
+
+ return vinfo;
+}
+
+
+/**
+ * Called from vbuf module.
+ *
+ * Note that there's actually two different vertex layouts in softpipe.
+ *
+ * The normal one is computed in softpipe_get_vertex_info() above and is
+ * used by the point/line/tri "setup" code.
+ *
+ * The other one (this one) is only used by the vbuf module (which is
+ * not normally used by default but used in testing). For the vbuf module,
+ * we basically want to pass-through the draw module's vertex layout as-is.
+ * When the softpipe vbuf code begins drawing, the normal vertex layout
+ * will come into play again.
+ */
+struct vertex_info *
+softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
+{
+ (void) softpipe_get_vertex_info(softpipe);
+ return &softpipe->vertex_info_vbuf;
+}
+
+
+/**
+ * Recompute cliprect from scissor bounds, scissor enable and surface size.
+ */
+static void
+compute_cliprect(struct softpipe_context *sp)
+{
+ uint surfWidth = sp->framebuffer.width;
+ uint surfHeight = sp->framebuffer.height;
+
+ if (sp->rasterizer->scissor) {
+ /* clip to scissor rect */
+ sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
+ sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
+ sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
+ sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
+ }
+ else {
+ /* clip to surface bounds */
+ sp->cliprect.minx = 0;
+ sp->cliprect.miny = 0;
+ sp->cliprect.maxx = surfWidth;
+ sp->cliprect.maxy = surfHeight;
+ }
+}
+
+
+/* Hopefully this will remain quite simple, otherwise need to pull in
+ * something like the state tracker mechanism.
+ */
+void softpipe_update_derived( struct softpipe_context *softpipe )
+{
+ if (softpipe->dirty & (SP_NEW_RASTERIZER |
+ SP_NEW_FS |
+ SP_NEW_VS))
+ invalidate_vertex_layout( softpipe );
+
+ if (softpipe->dirty & (SP_NEW_SCISSOR |
+ SP_NEW_DEPTH_STENCIL_ALPHA |
+ SP_NEW_FRAMEBUFFER))
+ compute_cliprect(softpipe);
+
+ if (softpipe->dirty & (SP_NEW_BLEND |
+ SP_NEW_DEPTH_STENCIL_ALPHA |
+ SP_NEW_FRAMEBUFFER |
+ SP_NEW_RASTERIZER |
+ SP_NEW_FS |
+ SP_NEW_QUERY))
+ sp_build_quad_pipeline(softpipe);
+
+ softpipe->dirty = 0;
+}
diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c
new file mode 100644
index 0000000000..4330c20393
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state_fs.c
@@ -0,0 +1,169 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_fs.h"
+
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_scan.h"
+#include "tgsi/tgsi_parse.h"
+
+
+void *
+softpipe_create_fs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ struct sp_fragment_shader *state;
+
+ /* debug */
+ if (softpipe->dump_fs)
+ tgsi_dump(templ->tokens, 0);
+
+ /* codegen */
+ state = softpipe_create_fs_llvm( softpipe, templ );
+ if (!state) {
+ state = softpipe_create_fs_sse( softpipe, templ );
+ if (!state) {
+ state = softpipe_create_fs_exec( softpipe, templ );
+ }
+ }
+
+ assert(state);
+
+ /* get/save the summary info for this shader */
+ tgsi_scan_shader(templ->tokens, &state->info);
+
+ return state;
+}
+
+
+void
+softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->fs = (struct sp_fragment_shader *) fs;
+
+ softpipe->dirty |= SP_NEW_FS;
+}
+
+
+void
+softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
+{
+ struct sp_fragment_shader *state = fs;
+
+ assert(fs != softpipe_context(pipe)->fs);
+
+ state->delete( state );
+}
+
+
+void *
+softpipe_create_vs_state(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ struct sp_vertex_shader *state;
+
+ state = CALLOC_STRUCT(sp_vertex_shader);
+ if (state == NULL )
+ goto fail;
+
+ /* copy shader tokens, the ones passed in will go away.
+ */
+ state->shader.tokens = tgsi_dup_tokens(templ->tokens);
+ if (state->shader.tokens == NULL)
+ goto fail;
+
+ state->draw_data = draw_create_vertex_shader(softpipe->draw, templ);
+ if (state->draw_data == NULL)
+ goto fail;
+
+ return state;
+
+fail:
+ if (state) {
+ FREE( (void *)state->shader.tokens );
+ FREE( state->draw_data );
+ FREE( state );
+ }
+ return NULL;
+}
+
+
+void
+softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ softpipe->vs = (const struct sp_vertex_shader *)vs;
+
+ draw_bind_vertex_shader(softpipe->draw,
+ (softpipe->vs ? softpipe->vs->draw_data : NULL));
+
+ softpipe->dirty |= SP_NEW_VS;
+}
+
+
+void
+softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ struct sp_vertex_shader *state =
+ (struct sp_vertex_shader *)vs;
+
+ draw_delete_vertex_shader(softpipe->draw, state->draw_data);
+ FREE( state );
+}
+
+
+
+void
+softpipe_set_constant_buffer(struct pipe_context *pipe,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ assert(shader < PIPE_SHADER_TYPES);
+ assert(index == 0);
+
+ /* note: reference counting */
+ pipe_buffer_reference(&softpipe->constants[shader].buffer,
+ buf ? buf->buffer : NULL);
+
+ softpipe->dirty |= SP_NEW_CONSTANTS;
+}
diff --git a/src/gallium/drivers/softpipe/sp_state_rasterizer.c b/src/gallium/drivers/softpipe/sp_state_rasterizer.c
new file mode 100644
index 0000000000..87b7219683
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state_rasterizer.c
@@ -0,0 +1,62 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "pipe/p_defines.h"
+#include "util/u_memory.h"
+#include "sp_context.h"
+#include "sp_state.h"
+#include "draw/draw_context.h"
+
+
+
+void *
+softpipe_create_rasterizer_state(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *rast)
+{
+ return mem_dup(rast, sizeof(*rast));
+}
+
+void softpipe_bind_rasterizer_state(struct pipe_context *pipe,
+ void *setup)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ /* pass-through to draw module */
+ draw_set_rasterizer_state(softpipe->draw, setup);
+
+ softpipe->rasterizer = (struct pipe_rasterizer_state *)setup;
+
+ softpipe->dirty |= SP_NEW_RASTERIZER;
+}
+
+void softpipe_delete_rasterizer_state(struct pipe_context *pipe,
+ void *rasterizer)
+{
+ FREE( rasterizer );
+}
+
+
diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c
new file mode 100644
index 0000000000..cb517b02e4
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state_sampler.c
@@ -0,0 +1,117 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors:
+ * Brian Paul
+ */
+
+#include "util/u_memory.h"
+
+#include "draw/draw_context.h"
+
+#include "sp_context.h"
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_texture.h"
+#include "sp_tile_cache.h"
+#include "draw/draw_context.h"
+
+
+
+void *
+softpipe_create_sampler_state(struct pipe_context *pipe,
+ const struct pipe_sampler_state *sampler)
+{
+ return mem_dup(sampler, sizeof(*sampler));
+}
+
+
+void
+softpipe_bind_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **sampler)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ unsigned i;
+
+ assert(num <= PIPE_MAX_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == softpipe->num_samplers &&
+ !memcmp(softpipe->sampler, sampler, num * sizeof(void *)))
+ return;
+
+ draw_flush(softpipe->draw);
+
+ for (i = 0; i < num; ++i)
+ softpipe->sampler[i] = sampler[i];
+ for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
+ softpipe->sampler[i] = NULL;
+
+ softpipe->num_samplers = num;
+
+ softpipe->dirty |= SP_NEW_SAMPLER;
+}
+
+
+void
+softpipe_set_sampler_textures(struct pipe_context *pipe,
+ unsigned num, struct pipe_texture **texture)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ uint i;
+
+ assert(num <= PIPE_MAX_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == softpipe->num_textures &&
+ !memcmp(softpipe->texture, texture, num * sizeof(struct pipe_texture *)))
+ return;
+
+ draw_flush(softpipe->draw);
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ struct pipe_texture *tex = i < num ? texture[i] : NULL;
+
+ pipe_texture_reference(&softpipe->texture[i], tex);
+ sp_tile_cache_set_texture(pipe, softpipe->tex_cache[i], tex);
+ }
+
+ softpipe->num_textures = num;
+
+ softpipe->dirty |= SP_NEW_TEXTURE;
+}
+
+
+void
+softpipe_delete_sampler_state(struct pipe_context *pipe,
+ void *sampler)
+{
+ FREE( sampler );
+}
+
+
+
diff --git a/src/gallium/drivers/softpipe/sp_state_surface.c b/src/gallium/drivers/softpipe/sp_state_surface.c
new file mode 100644
index 0000000000..7c06d864a7
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state_surface.c
@@ -0,0 +1,129 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_surface.h"
+#include "sp_tile_cache.h"
+
+#include "draw/draw_context.h"
+
+
+/**
+ * XXX this might get moved someday
+ * Set the framebuffer surface info: color buffers, zbuffer, stencil buffer.
+ * Here, we flush the old surfaces and update the tile cache to point to the new
+ * surfaces.
+ */
+void
+softpipe_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct softpipe_context *sp = softpipe_context(pipe);
+ uint i;
+
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ /* check if changing cbuf */
+ if (sp->framebuffer.cbufs[i] != fb->cbufs[i]) {
+ /* flush old */
+ sp_flush_tile_cache(sp, sp->cbuf_cache[i]);
+
+ /* assign new */
+ sp->framebuffer.cbufs[i] = fb->cbufs[i];
+
+ /* update cache */
+ sp_tile_cache_set_surface(sp->cbuf_cache[i], fb->cbufs[i]);
+ }
+ }
+
+ sp->framebuffer.nr_cbufs = fb->nr_cbufs;
+
+ /* zbuf changing? */
+ if (sp->framebuffer.zsbuf != fb->zsbuf) {
+ /* flush old */
+ sp_flush_tile_cache(sp, sp->zsbuf_cache);
+
+ /* assign new */
+ sp->framebuffer.zsbuf = fb->zsbuf;
+
+ /* update cache */
+ sp_tile_cache_set_surface(sp->zsbuf_cache, fb->zsbuf);
+ }
+
+#if 0
+ /* XXX combined depth/stencil here */
+
+ /* sbuf changing? */
+ if (sp->framebuffer.sbuf != fb->sbuf) {
+ /* flush old */
+ sp_flush_tile_cache(sp, sp->sbuf_cache_sep);
+
+ /* assign new */
+ sp->framebuffer.sbuf = fb->sbuf;
+
+ /* update cache */
+ if (fb->sbuf != fb->zbuf) {
+ /* separate stencil buf */
+ sp->sbuf_cache = sp->sbuf_cache_sep;
+ sp_tile_cache_set_surface(sp->sbuf_cache, fb->sbuf);
+ }
+ else {
+ /* combined depth/stencil */
+ sp->sbuf_cache = sp->zbuf_cache;
+ sp_tile_cache_set_surface(sp->sbuf_cache, fb->sbuf);
+ }
+ }
+#endif
+
+ /* Tell draw module how deep the Z/depth buffer is */
+ {
+ int depth_bits;
+ double mrd;
+ if (sp->framebuffer.zsbuf) {
+ depth_bits = pf_get_component_bits(sp->framebuffer.zsbuf->format,
+ PIPE_FORMAT_COMP_Z);
+ }
+ else {
+ depth_bits = 0;
+ }
+ if (depth_bits > 16) {
+ mrd = 0.0000001;
+ }
+ else {
+ mrd = 0.00002;
+ }
+ draw_set_mrd(sp->draw, mrd);
+ }
+
+ sp->framebuffer.width = fb->width;
+ sp->framebuffer.height = fb->height;
+
+ sp->dirty |= SP_NEW_FRAMEBUFFER;
+}
diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c
new file mode 100644
index 0000000000..46b6991195
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state_vertex.c
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_surface.h"
+
+#include "draw/draw_context.h"
+
+
+void
+softpipe_set_vertex_elements(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_element *attribs)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ assert(count <= PIPE_MAX_ATTRIBS);
+
+ memcpy(softpipe->vertex_element, attribs,
+ count * sizeof(struct pipe_vertex_element));
+ softpipe->num_vertex_elements = count;
+
+ softpipe->dirty |= SP_NEW_VERTEX;
+
+ draw_set_vertex_elements(softpipe->draw, count, attribs);
+}
+
+
+void
+softpipe_set_vertex_buffers(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_buffer *buffers)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+
+ assert(count <= PIPE_MAX_ATTRIBS);
+
+ memcpy(softpipe->vertex_buffer, buffers, count * sizeof(buffers[0]));
+ softpipe->num_vertex_buffers = count;
+
+ softpipe->dirty |= SP_NEW_VERTEX;
+
+ draw_set_vertex_buffers(softpipe->draw, count, buffers);
+}
diff --git a/src/gallium/drivers/softpipe/sp_surface.c b/src/gallium/drivers/softpipe/sp_surface.c
new file mode 100644
index 0000000000..b04c2a63ad
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_surface.c
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_rect.h"
+#include "sp_context.h"
+#include "sp_surface.h"
+
+
+static void
+sp_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ util_surface_copy(pipe, FALSE,
+ dest, destx, desty,
+ src, srcx, srcy,
+ width, height);
+}
+
+void
+sp_init_surface_functions(struct softpipe_context *sp)
+{
+ sp->pipe.surface_copy = sp_surface_copy;
+ sp->pipe.surface_fill = util_surface_fill;
+}
diff --git a/src/gallium/drivers/softpipe/sp_surface.h b/src/gallium/drivers/softpipe/sp_surface.h
new file mode 100644
index 0000000000..22de3ba43f
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_surface.h
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_SURFACE_H
+#define SP_SURFACE_H
+
+
+struct softpipe_context;
+
+
+extern void
+sp_init_surface_functions(struct softpipe_context *sp);
+
+
+#endif /* SP_SURFACE_H */
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
new file mode 100644
index 0000000000..a1d3bade27
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -0,0 +1,1295 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2008 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/**
+ * Texture sampling
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+#include "sp_context.h"
+#include "sp_quad.h"
+#include "sp_surface.h"
+#include "sp_texture.h"
+#include "sp_tex_sample.h"
+#include "sp_tile_cache.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+
+
+/*
+ * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
+ * see 1-pixel bands of improperly weighted linear-filtered textures.
+ * The tests/texwrap.c demo is a good test.
+ * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
+ * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
+ */
+#define FRAC(f) ((f) - util_ifloor(f))
+
+
+/**
+ * Linear interpolation macro
+ */
+static INLINE float
+lerp(float a, float v0, float v1)
+{
+ return v0 + a * (v1 - v0);
+}
+
+
+/**
+ * Do 2D/biliner interpolation of float values.
+ * v00, v10, v01 and v11 are typically four texture samples in a square/box.
+ * a and b are the horizontal and vertical interpolants.
+ * It's important that this function is inlined when compiled with
+ * optimization! If we find that's not true on some systems, convert
+ * to a macro.
+ */
+static INLINE float
+lerp_2d(float a, float b,
+ float v00, float v10, float v01, float v11)
+{
+ const float temp0 = lerp(a, v00, v10);
+ const float temp1 = lerp(a, v01, v11);
+ return lerp(b, temp0, temp1);
+}
+
+
+/**
+ * As above, but 3D interpolation of 8 values.
+ */
+static INLINE float
+lerp_3d(float a, float b, float c,
+ float v000, float v100, float v010, float v110,
+ float v001, float v101, float v011, float v111)
+{
+ const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
+ const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
+ return lerp(c, temp0, temp1);
+}
+
+
+
+/**
+ * If A is a signed integer, A % B doesn't give the right value for A < 0
+ * (in terms of texture repeat). Just casting to unsigned fixes that.
+ */
+#define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))
+
+
+/**
+ * Apply texture coord wrapping mode and return integer texture indexes
+ * for a vector of four texcoords (S or T or P).
+ * \param wrapMode PIPE_TEX_WRAP_x
+ * \param s the incoming texcoords
+ * \param size the texture image size
+ * \param icoord returns the integer texcoords
+ * \return integer texture index
+ */
+static INLINE void
+nearest_texcoord_4(unsigned wrapMode, const float s[4], unsigned size,
+ int icoord[4])
+{
+ uint ch;
+ switch (wrapMode) {
+ case PIPE_TEX_WRAP_REPEAT:
+ /* s limited to [0,1) */
+ /* i limited to [0,size-1] */
+ for (ch = 0; ch < 4; ch++) {
+ int i = util_ifloor(s[ch] * size);
+ icoord[ch] = REMAINDER(i, size);
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP:
+ /* s limited to [0,1] */
+ /* i limited to [0,size-1] */
+ for (ch = 0; ch < 4; ch++) {
+ if (s[ch] <= 0.0F)
+ icoord[ch] = 0;
+ else if (s[ch] >= 1.0F)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(s[ch] * size);
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [0, size-1] */
+ const float min = 1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ if (s[ch] < min)
+ icoord[ch] = 0;
+ else if (s[ch] > max)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(s[ch] * size);
+ }
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [-1, size] */
+ const float min = -1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ if (s[ch] <= min)
+ icoord[ch] = -1;
+ else if (s[ch] >= max)
+ icoord[ch] = size;
+ else
+ icoord[ch] = util_ifloor(s[ch] * size);
+ }
+ }
+ return;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ {
+ const float min = 1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ const int flr = util_ifloor(s[ch]);
+ float u;
+ if (flr & 1)
+ u = 1.0F - (s[ch] - (float) flr);
+ else
+ u = s[ch] - (float) flr;
+ if (u < min)
+ icoord[ch] = 0;
+ else if (u > max)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(u * size);
+ }
+ }
+ return;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ /* s limited to [0,1] */
+ /* i limited to [0,size-1] */
+ const float u = fabsf(s[ch]);
+ if (u <= 0.0F)
+ icoord[ch] = 0;
+ else if (u >= 1.0F)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(u * size);
+ }
+ return;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [0, size-1] */
+ const float min = 1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ const float u = fabsf(s[ch]);
+ if (u < min)
+ icoord[ch] = 0;
+ else if (u > max)
+ icoord[ch] = size - 1;
+ else
+ icoord[ch] = util_ifloor(u * size);
+ }
+ }
+ return;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [0, size-1] */
+ const float min = -1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ const float u = fabsf(s[ch]);
+ if (u < min)
+ icoord[ch] = -1;
+ else if (u > max)
+ icoord[ch] = size;
+ else
+ icoord[ch] = util_ifloor(u * size);
+ }
+ }
+ return;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Used to compute texel locations for linear sampling for four texcoords.
+ * \param wrapMode PIPE_TEX_WRAP_x
+ * \param s the texcoords
+ * \param size the texture image size
+ * \param icoord0 returns first texture indexes
+ * \param icoord1 returns second texture indexes (usually icoord0 + 1)
+ * \param w returns blend factor/weight between texture indexes
+ * \param icoord returns the computed integer texture coords
+ */
+static INLINE void
+linear_texcoord_4(unsigned wrapMode, const float s[4], unsigned size,
+ int icoord0[4], int icoord1[4], float w[4])
+{
+ uint ch;
+
+ switch (wrapMode) {
+ case PIPE_TEX_WRAP_REPEAT:
+ for (ch = 0; ch < 4; ch++) {
+ float u = s[ch] * size - 0.5F;
+ icoord0[ch] = REMAINDER(util_ifloor(u), size);
+ icoord1[ch] = REMAINDER(icoord0[ch] + 1, size);
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ float u = CLAMP(s[ch], 0.0F, 1.0F);
+ u = u * size - 0.5f;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ for (ch = 0; ch < 4; ch++) {
+ float u = CLAMP(s[ch], 0.0F, 1.0F);
+ u = u * size - 0.5f;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ if (icoord0[ch] < 0)
+ icoord0[ch] = 0;
+ if (icoord1[ch] >= (int) size)
+ icoord1[ch] = size - 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ {
+ const float min = -1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ float u = CLAMP(s[ch], min, max);
+ u = u * size - 0.5f;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ }
+ break;;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ for (ch = 0; ch < 4; ch++) {
+ const int flr = util_ifloor(s[ch]);
+ float u;
+ if (flr & 1)
+ u = 1.0F - (s[ch] - (float) flr);
+ else
+ u = s[ch] - (float) flr;
+ u = u * size - 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ if (icoord0[ch] < 0)
+ icoord0[ch] = 0;
+ if (icoord1[ch] >= (int) size)
+ icoord1[ch] = size - 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ float u = fabsf(s[ch]);
+ if (u >= 1.0F)
+ u = (float) size;
+ else
+ u *= size;
+ u -= 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ for (ch = 0; ch < 4; ch++) {
+ float u = fabsf(s[ch]);
+ if (u >= 1.0F)
+ u = (float) size;
+ else
+ u *= size;
+ u -= 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ if (icoord0[ch] < 0)
+ icoord0[ch] = 0;
+ if (icoord1[ch] >= (int) size)
+ icoord1[ch] = size - 1;
+ w[ch] = FRAC(u);
+ }
+ break;;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ {
+ const float min = -1.0F / (2.0F * size);
+ const float max = 1.0F - min;
+ for (ch = 0; ch < 4; ch++) {
+ float u = fabsf(s[ch]);
+ if (u <= min)
+ u = min * size;
+ else if (u >= max)
+ u = max * size;
+ else
+ u *= size;
+ u -= 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ }
+ break;;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * For RECT textures / unnormalized texcoords
+ * Only a subset of wrap modes supported.
+ */
+static INLINE void
+nearest_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size,
+ int icoord[4])
+{
+ uint ch;
+ switch (wrapMode) {
+ case PIPE_TEX_WRAP_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ int i = util_ifloor(s[ch]);
+ icoord[ch]= CLAMP(i, 0, (int) size-1);
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ /* fall-through */
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ for (ch = 0; ch < 4; ch++) {
+ icoord[ch]= util_ifloor( CLAMP(s[ch], 0.5F, (float) size - 0.5F) );
+ }
+ return;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * For RECT textures / unnormalized texcoords.
+ * Only a subset of wrap modes supported.
+ */
+static INLINE void
+linear_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size,
+ int icoord0[4], int icoord1[4], float w[4])
+{
+ uint ch;
+ switch (wrapMode) {
+ case PIPE_TEX_WRAP_CLAMP:
+ for (ch = 0; ch < 4; ch++) {
+ /* Not exactly what the spec says, but it matches NVIDIA output */
+ float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f);
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ w[ch] = FRAC(u);
+ }
+ return;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ /* fall-through */
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ for (ch = 0; ch < 4; ch++) {
+ float u = CLAMP(s[ch], 0.5F, (float) size - 0.5F);
+ u -= 0.5F;
+ icoord0[ch] = util_ifloor(u);
+ icoord1[ch] = icoord0[ch] + 1;
+ if (icoord1[ch] > (int) size - 1)
+ icoord1[ch] = size - 1;
+ w[ch] = FRAC(u);
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+static unsigned
+choose_cube_face(float rx, float ry, float rz, float *newS, float *newT)
+{
+ /*
+ major axis
+ direction target sc tc ma
+ ---------- ------------------------------- --- --- ---
+ +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
+ -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
+ +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
+ -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
+ +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
+ -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
+ */
+ const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
+ unsigned face;
+ float sc, tc, ma;
+
+ if (arx > ary && arx > arz) {
+ if (rx >= 0.0F) {
+ face = PIPE_TEX_FACE_POS_X;
+ sc = -rz;
+ tc = -ry;
+ ma = arx;
+ }
+ else {
+ face = PIPE_TEX_FACE_NEG_X;
+ sc = rz;
+ tc = -ry;
+ ma = arx;
+ }
+ }
+ else if (ary > arx && ary > arz) {
+ if (ry >= 0.0F) {
+ face = PIPE_TEX_FACE_POS_Y;
+ sc = rx;
+ tc = rz;
+ ma = ary;
+ }
+ else {
+ face = PIPE_TEX_FACE_NEG_Y;
+ sc = rx;
+ tc = -rz;
+ ma = ary;
+ }
+ }
+ else {
+ if (rz > 0.0F) {
+ face = PIPE_TEX_FACE_POS_Z;
+ sc = rx;
+ tc = -ry;
+ ma = arz;
+ }
+ else {
+ face = PIPE_TEX_FACE_NEG_Z;
+ sc = -rx;
+ tc = -ry;
+ ma = arz;
+ }
+ }
+
+ *newS = ( sc / ma + 1.0F ) * 0.5F;
+ *newT = ( tc / ma + 1.0F ) * 0.5F;
+
+ return face;
+}
+
+
+/**
+ * Examine the quad's texture coordinates to compute the partial
+ * derivatives w.r.t X and Y, then compute lambda (level of detail).
+ *
+ * This is only done for fragment shaders, not vertex shaders.
+ */
+static float
+compute_lambda(const struct pipe_texture *tex,
+ const struct pipe_sampler_state *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias)
+{
+ float rho, lambda;
+
+ assert(sampler->normalized_coords);
+
+ assert(s);
+ {
+ float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT];
+ float dsdy = s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT];
+ dsdx = fabsf(dsdx);
+ dsdy = fabsf(dsdy);
+ rho = MAX2(dsdx, dsdy) * tex->width[0];
+ }
+ if (t) {
+ float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT];
+ float dtdy = t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT];
+ float max;
+ dtdx = fabsf(dtdx);
+ dtdy = fabsf(dtdy);
+ max = MAX2(dtdx, dtdy) * tex->height[0];
+ rho = MAX2(rho, max);
+ }
+ if (p) {
+ float dpdx = p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT];
+ float dpdy = p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT];
+ float max;
+ dpdx = fabsf(dpdx);
+ dpdy = fabsf(dpdy);
+ max = MAX2(dpdx, dpdy) * tex->depth[0];
+ rho = MAX2(rho, max);
+ }
+
+ lambda = util_fast_log2(rho);
+ lambda += lodbias + sampler->lod_bias;
+ lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod);
+
+ return lambda;
+}
+
+
+/**
+ * Do several things here:
+ * 1. Compute lambda from the texcoords, if needed
+ * 2. Determine if we're minifying or magnifying
+ * 3. If minifying, choose mipmap levels
+ * 4. Return image filter to use within mipmap images
+ * \param level0 Returns first mipmap level to sample from
+ * \param level1 Returns second mipmap level to sample from
+ * \param levelBlend Returns blend factor between levels, in [0,1]
+ * \param imgFilter Returns either the min or mag filter, depending on lambda
+ */
+static void
+choose_mipmap_levels(const struct pipe_texture *texture,
+ const struct pipe_sampler_state *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ boolean computeLambda,
+ float lodbias,
+ unsigned *level0, unsigned *level1, float *levelBlend,
+ unsigned *imgFilter)
+{
+ if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
+ /* no mipmap selection needed */
+ *level0 = *level1 = CLAMP((int) sampler->min_lod,
+ 0, (int) texture->last_level);
+
+ if (sampler->min_img_filter != sampler->mag_img_filter) {
+ /* non-mipmapped texture, but still need to determine if doing
+ * minification or magnification.
+ */
+ float lambda = compute_lambda(texture, sampler, s, t, p, lodbias);
+ if (lambda <= 0.0) {
+ *imgFilter = sampler->mag_img_filter;
+ }
+ else {
+ *imgFilter = sampler->min_img_filter;
+ }
+ }
+ else {
+ *imgFilter = sampler->mag_img_filter;
+ }
+ }
+ else {
+ float lambda;
+
+ if (computeLambda)
+ /* fragment shader */
+ lambda = compute_lambda(texture, sampler, s, t, p, lodbias);
+ else
+ /* vertex shader */
+ lambda = lodbias; /* not really a bias, but absolute LOD */
+
+ if (lambda <= 0.0) { /* XXX threshold depends on the filter */
+ /* magnifying */
+ *imgFilter = sampler->mag_img_filter;
+ *level0 = *level1 = 0;
+ }
+ else {
+ /* minifying */
+ *imgFilter = sampler->min_img_filter;
+
+ /* choose mipmap level(s) and compute the blend factor between them */
+ if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
+ /* Nearest mipmap level */
+ const int lvl = (int) (lambda + 0.5);
+ *level0 =
+ *level1 = CLAMP(lvl, 0, (int) texture->last_level);
+ }
+ else {
+ /* Linear interpolation between mipmap levels */
+ const int lvl = (int) lambda;
+ *level0 = CLAMP(lvl, 0, (int) texture->last_level);
+ *level1 = CLAMP(lvl + 1, 0, (int) texture->last_level);
+ *levelBlend = FRAC(lambda); /* blending weight between levels */
+ }
+ }
+ }
+}
+
+
+/**
+ * Get a texel from a texture, using the texture tile cache.
+ *
+ * \param face the cube face in 0..5
+ * \param level the mipmap level
+ * \param x the x coord of texel within 2D image
+ * \param y the y coord of texel within 2D image
+ * \param z which slice of a 3D texture
+ * \param rgba the quad to put the texel/color into
+ * \param j which element of the rgba quad to write to
+ *
+ * XXX maybe move this into sp_tile_cache.c and merge with the
+ * sp_get_cached_tile_tex() function. Also, get 4 texels instead of 1...
+ */
+static void
+get_texel(const struct tgsi_sampler *tgsi_sampler,
+ unsigned face, unsigned level, int x, int y, int z,
+ float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j)
+{
+ const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler);
+ struct softpipe_context *sp = samp->sp;
+ const uint unit = samp->unit;
+ const struct pipe_texture *texture = sp->texture[unit];
+ const struct pipe_sampler_state *sampler = sp->sampler[unit];
+
+ if (x < 0 || x >= (int) texture->width[level] ||
+ y < 0 || y >= (int) texture->height[level] ||
+ z < 0 || z >= (int) texture->depth[level]) {
+ rgba[0][j] = sampler->border_color[0];
+ rgba[1][j] = sampler->border_color[1];
+ rgba[2][j] = sampler->border_color[2];
+ rgba[3][j] = sampler->border_color[3];
+ }
+ else {
+ const int tx = x % TILE_SIZE;
+ const int ty = y % TILE_SIZE;
+ const struct softpipe_cached_tile *tile
+ = sp_get_cached_tile_tex(sp, samp->cache,
+ x, y, z, face, level);
+ rgba[0][j] = tile->data.color[ty][tx][0];
+ rgba[1][j] = tile->data.color[ty][tx][1];
+ rgba[2][j] = tile->data.color[ty][tx][2];
+ rgba[3][j] = tile->data.color[ty][tx][3];
+ if (0)
+ {
+ debug_printf("Get texel %f %f %f %f from %s\n",
+ rgba[0][j], rgba[1][j], rgba[2][j], rgba[3][j],
+ pf_name(texture->format));
+ }
+ }
+}
+
+
+/**
+ * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
+ * When we sampled the depth texture, the depth value was put into all
+ * RGBA channels. We look at the red channel here.
+ * \param rgba quad of (depth) texel values
+ * \param p texture 'P' components for four pixels in quad
+ * \param j which pixel in the quad to test [0..3]
+ */
+static INLINE void
+shadow_compare(const struct pipe_sampler_state *sampler,
+ float rgba[NUM_CHANNELS][QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ uint j)
+{
+ int k;
+ switch (sampler->compare_func) {
+ case PIPE_FUNC_LESS:
+ k = p[j] < rgba[0][j];
+ break;
+ case PIPE_FUNC_LEQUAL:
+ k = p[j] <= rgba[0][j];
+ break;
+ case PIPE_FUNC_GREATER:
+ k = p[j] > rgba[0][j];
+ break;
+ case PIPE_FUNC_GEQUAL:
+ k = p[j] >= rgba[0][j];
+ break;
+ case PIPE_FUNC_EQUAL:
+ k = p[j] == rgba[0][j];
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ k = p[j] != rgba[0][j];
+ break;
+ case PIPE_FUNC_ALWAYS:
+ k = 1;
+ break;
+ case PIPE_FUNC_NEVER:
+ k = 0;
+ break;
+ default:
+ k = 0;
+ assert(0);
+ break;
+ }
+
+ /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
+ rgba[0][j] = rgba[1][j] = rgba[2][j] = (float) k;
+ rgba[3][j] = 1.0F;
+}
+
+
+/**
+ * As above, but do four z/texture comparisons.
+ */
+static INLINE void
+shadow_compare4(const struct pipe_sampler_state *sampler,
+ float rgba[NUM_CHANNELS][QUAD_SIZE],
+ const float p[QUAD_SIZE])
+{
+ int j, k0, k1, k2, k3;
+ float val;
+
+ /* compare four texcoords vs. four texture samples */
+ switch (sampler->compare_func) {
+ case PIPE_FUNC_LESS:
+ k0 = p[0] < rgba[0][0];
+ k1 = p[1] < rgba[0][1];
+ k2 = p[2] < rgba[0][2];
+ k3 = p[3] < rgba[0][3];
+ break;
+ case PIPE_FUNC_LEQUAL:
+ k0 = p[0] <= rgba[0][0];
+ k1 = p[1] <= rgba[0][1];
+ k2 = p[2] <= rgba[0][2];
+ k3 = p[3] <= rgba[0][3];
+ break;
+ case PIPE_FUNC_GREATER:
+ k0 = p[0] > rgba[0][0];
+ k1 = p[1] > rgba[0][1];
+ k2 = p[2] > rgba[0][2];
+ k3 = p[3] > rgba[0][3];
+ break;
+ case PIPE_FUNC_GEQUAL:
+ k0 = p[0] >= rgba[0][0];
+ k1 = p[1] >= rgba[0][1];
+ k2 = p[2] >= rgba[0][2];
+ k3 = p[3] >= rgba[0][3];
+ break;
+ case PIPE_FUNC_EQUAL:
+ k0 = p[0] == rgba[0][0];
+ k1 = p[1] == rgba[0][1];
+ k2 = p[2] == rgba[0][2];
+ k3 = p[3] == rgba[0][3];
+ break;
+ case PIPE_FUNC_NOTEQUAL:
+ k0 = p[0] != rgba[0][0];
+ k1 = p[1] != rgba[0][1];
+ k2 = p[2] != rgba[0][2];
+ k3 = p[3] != rgba[0][3];
+ break;
+ case PIPE_FUNC_ALWAYS:
+ k0 = k1 = k2 = k3 = 1;
+ break;
+ case PIPE_FUNC_NEVER:
+ k0 = k1 = k2 = k3 = 0;
+ break;
+ default:
+ k0 = k1 = k2 = k3 = 0;
+ assert(0);
+ break;
+ }
+
+ /* convert four pass/fail values to an intensity in [0,1] */
+ val = 0.25F * (k0 + k1 + k2 + k3);
+
+ /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
+ for (j = 0; j < 4; j++) {
+ rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
+ rgba[3][j] = 1.0F;
+ }
+}
+
+
+/**
+ * Common code for sampling 1D/2D/cube textures.
+ * Could probably extend for 3D...
+ */
+static void
+sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ boolean computeLambda,
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE],
+ const unsigned faces[4])
+{
+ const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler);
+ const struct softpipe_context *sp = samp->sp;
+ const uint unit = samp->unit;
+ const struct pipe_texture *texture = sp->texture[unit];
+ const struct pipe_sampler_state *sampler = sp->sampler[unit];
+ unsigned level0, level1, j, imgFilter;
+ int width, height;
+ float levelBlend;
+
+ choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias,
+ &level0, &level1, &levelBlend, &imgFilter);
+
+ assert(sampler->normalized_coords);
+
+ width = texture->width[level0];
+ height = texture->height[level0];
+
+ assert(width > 0);
+
+ switch (imgFilter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ {
+ int x[4], y[4];
+ nearest_texcoord_4(sampler->wrap_s, s, width, x);
+ nearest_texcoord_4(sampler->wrap_t, t, height, y);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ shadow_compare(sampler, rgba, p, j);
+ }
+
+ if (level0 != level1) {
+ /* get texels from second mipmap level and blend */
+ float rgba2[4][4];
+ unsigned c;
+ x[j] /= 2;
+ y[j] /= 2;
+ get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0,
+ rgba2, j);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
+ shadow_compare(sampler, rgba2, p, j);
+ }
+
+ for (c = 0; c < NUM_CHANNELS; c++) {
+ rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
+ }
+ }
+ }
+ }
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ case PIPE_TEX_FILTER_ANISO:
+ {
+ int x0[4], y0[4], x1[4], y1[4];
+ float xw[4], yw[4]; /* weights */
+
+ linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw);
+ linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ float tx[4][4]; /* texels */
+ int c;
+ get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0);
+ get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1);
+ get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2);
+ get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ shadow_compare4(sampler, tx, p);
+ }
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp_2d(xw[j], yw[j],
+ tx[c][0], tx[c][1],
+ tx[c][2], tx[c][3]);
+ }
+
+ if (level0 != level1) {
+ /* get texels from second mipmap level and blend */
+ float rgba2[4][4];
+ x0[j] /= 2;
+ y0[j] /= 2;
+ x1[j] /= 2;
+ y1[j] /= 2;
+ get_texel(tgsi_sampler, faces[j], level1, x0[j], y0[j], 0, tx, 0);
+ get_texel(tgsi_sampler, faces[j], level1, x1[j], y0[j], 0, tx, 1);
+ get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2);
+ get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
+ shadow_compare4(sampler, tx, p);
+ }
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba2[c][j] = lerp_2d(xw[j], yw[j],
+ tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
+ }
+
+ for (c = 0; c < NUM_CHANNELS; c++) {
+ rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+static INLINE void
+sp_get_samples_1d(const struct tgsi_sampler *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ boolean computeLambda,
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ static const unsigned faces[4] = {0, 0, 0, 0};
+ static const float tzero[4] = {0, 0, 0, 0};
+ sp_get_samples_2d_common(sampler, s, tzero, NULL,
+ computeLambda, lodbias, rgba, faces);
+}
+
+
+static INLINE void
+sp_get_samples_2d(const struct tgsi_sampler *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ boolean computeLambda,
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ static const unsigned faces[4] = {0, 0, 0, 0};
+ sp_get_samples_2d_common(sampler, s, t, p,
+ computeLambda, lodbias, rgba, faces);
+}
+
+
+static INLINE void
+sp_get_samples_3d(const struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ boolean computeLambda,
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler);
+ const struct softpipe_context *sp = samp->sp;
+ const uint unit = samp->unit;
+ const struct pipe_texture *texture = sp->texture[unit];
+ const struct pipe_sampler_state *sampler = sp->sampler[unit];
+ /* get/map pipe_surfaces corresponding to 3D tex slices */
+ unsigned level0, level1, j, imgFilter;
+ int width, height, depth;
+ float levelBlend;
+ const uint face = 0;
+
+ choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias,
+ &level0, &level1, &levelBlend, &imgFilter);
+
+ assert(sampler->normalized_coords);
+
+ width = texture->width[level0];
+ height = texture->height[level0];
+ depth = texture->depth[level0];
+
+ assert(width > 0);
+ assert(height > 0);
+ assert(depth > 0);
+
+ switch (imgFilter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ {
+ int x[4], y[4], z[4];
+ nearest_texcoord_4(sampler->wrap_s, s, width, x);
+ nearest_texcoord_4(sampler->wrap_t, t, height, y);
+ nearest_texcoord_4(sampler->wrap_r, p, depth, z);
+ for (j = 0; j < QUAD_SIZE; j++) {
+ get_texel(tgsi_sampler, face, level0, x[j], y[j], z[j], rgba, j);
+ if (level0 != level1) {
+ /* get texels from second mipmap level and blend */
+ float rgba2[4][4];
+ unsigned c;
+ x[j] /= 2;
+ y[j] /= 2;
+ z[j] /= 2;
+ get_texel(tgsi_sampler, face, level1, x[j], y[j], z[j], rgba2, j);
+ for (c = 0; c < NUM_CHANNELS; c++) {
+ rgba[c][j] = lerp(levelBlend, rgba2[c][j], rgba[c][j]);
+ }
+ }
+ }
+ }
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ case PIPE_TEX_FILTER_ANISO:
+ {
+ int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4];
+ float xw[4], yw[4], zw[4]; /* interpolation weights */
+ linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw);
+ linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw);
+ linear_texcoord_4(sampler->wrap_r, p, depth, z0, z1, zw);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ int c;
+ float tx0[4][4], tx1[4][4];
+ get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z0[j], tx0, 0);
+ get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z0[j], tx0, 1);
+ get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z0[j], tx0, 2);
+ get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z0[j], tx0, 3);
+ get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z1[j], tx1, 0);
+ get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z1[j], tx1, 1);
+ get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z1[j], tx1, 2);
+ get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z1[j], tx1, 3);
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j],
+ tx0[c][0], tx0[c][1],
+ tx0[c][2], tx0[c][3],
+ tx1[c][0], tx1[c][1],
+ tx1[c][2], tx1[c][3]);
+ }
+
+ if (level0 != level1) {
+ /* get texels from second mipmap level and blend */
+ float rgba2[4][4];
+ x0[j] /= 2;
+ y0[j] /= 2;
+ z0[j] /= 2;
+ x1[j] /= 2;
+ y1[j] /= 2;
+ z1[j] /= 2;
+ get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z0[j], tx0, 0);
+ get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z0[j], tx0, 1);
+ get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z0[j], tx0, 2);
+ get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z0[j], tx0, 3);
+ get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z1[j], tx1, 0);
+ get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z1[j], tx1, 1);
+ get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z1[j], tx1, 2);
+ get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z1[j], tx1, 3);
+
+ /* interpolate R, G, B, A */
+ for (c = 0; c < 4; c++) {
+ rgba2[c][j] = lerp_3d(xw[j], yw[j], zw[j],
+ tx0[c][0], tx0[c][1],
+ tx0[c][2], tx0[c][3],
+ tx1[c][0], tx1[c][1],
+ tx1[c][2], tx1[c][3]);
+ }
+
+ /* blend mipmap levels */
+ for (c = 0; c < NUM_CHANNELS; c++) {
+ rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+static void
+sp_get_samples_cube(const struct tgsi_sampler *sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ boolean computeLambda,
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ unsigned faces[QUAD_SIZE], j;
+ float ssss[4], tttt[4];
+ for (j = 0; j < QUAD_SIZE; j++) {
+ faces[j] = choose_cube_face(s[j], t[j], p[j], ssss + j, tttt + j);
+ }
+ sp_get_samples_2d_common(sampler, ssss, tttt, NULL,
+ computeLambda, lodbias, rgba, faces);
+}
+
+
+static void
+sp_get_samples_rect(const struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ boolean computeLambda,
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler);
+ const struct softpipe_context *sp = samp->sp;
+ const uint unit = samp->unit;
+ const struct pipe_texture *texture = sp->texture[unit];
+ const struct pipe_sampler_state *sampler = sp->sampler[unit];
+ const uint face = 0;
+ unsigned level0, level1, j, imgFilter;
+ int width, height;
+ float levelBlend;
+
+ choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias,
+ &level0, &level1, &levelBlend, &imgFilter);
+
+ /* texture RECTS cannot be mipmapped */
+ assert(level0 == level1);
+
+ width = texture->width[level0];
+ height = texture->height[level0];
+
+ assert(width > 0);
+
+ switch (imgFilter) {
+ case PIPE_TEX_FILTER_NEAREST:
+ {
+ int x[4], y[4];
+ nearest_texcoord_unnorm_4(sampler->wrap_s, s, width, x);
+ nearest_texcoord_unnorm_4(sampler->wrap_t, t, height, y);
+ for (j = 0; j < QUAD_SIZE; j++) {
+ get_texel(tgsi_sampler, face, level0, x[j], y[j], 0, rgba, j);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ shadow_compare(sampler, rgba, p, j);
+ }
+ }
+ }
+ break;
+ case PIPE_TEX_FILTER_LINEAR:
+ case PIPE_TEX_FILTER_ANISO:
+ {
+ int x0[4], y0[4], x1[4], y1[4];
+ float xw[4], yw[4]; /* weights */
+ linear_texcoord_unnorm_4(sampler->wrap_s, s, width, x0, x1, xw);
+ linear_texcoord_unnorm_4(sampler->wrap_t, t, height, y0, y1, yw);
+ for (j = 0; j < QUAD_SIZE; j++) {
+ float tx[4][4]; /* texels */
+ int c;
+ get_texel(tgsi_sampler, face, level0, x0[j], y0[j], 0, tx, 0);
+ get_texel(tgsi_sampler, face, level0, x1[j], y0[j], 0, tx, 1);
+ get_texel(tgsi_sampler, face, level0, x0[j], y1[j], 0, tx, 2);
+ get_texel(tgsi_sampler, face, level0, x1[j], y1[j], 0, tx, 3);
+ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ shadow_compare4(sampler, tx, p);
+ }
+ for (c = 0; c < 4; c++) {
+ rgba[c][j] = lerp_2d(xw[j], yw[j],
+ tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
+ }
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Common code for vertex/fragment program texture sampling.
+ */
+static INLINE void
+sp_get_samples(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ boolean computeLambda,
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler);
+ const struct softpipe_context *sp = samp->sp;
+ const uint unit = samp->unit;
+ const struct pipe_texture *texture = sp->texture[unit];
+ const struct pipe_sampler_state *sampler = sp->sampler[unit];
+
+ if (!texture)
+ return;
+
+ switch (texture->target) {
+ case PIPE_TEXTURE_1D:
+ assert(sampler->normalized_coords);
+ sp_get_samples_1d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);
+ break;
+ case PIPE_TEXTURE_2D:
+ if (sampler->normalized_coords)
+ sp_get_samples_2d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);
+ else
+ sp_get_samples_rect(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);
+ break;
+ case PIPE_TEXTURE_3D:
+ assert(sampler->normalized_coords);
+ sp_get_samples_3d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);
+ break;
+ case PIPE_TEXTURE_CUBE:
+ assert(sampler->normalized_coords);
+ sp_get_samples_cube(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);
+ break;
+ default:
+ assert(0);
+ }
+
+#if 0 /* DEBUG */
+ {
+ int i;
+ printf("Sampled at %f, %f, %f:\n", s[0], t[0], p[0]);
+ for (i = 0; i < 4; i++) {
+ printf("Frag %d: %f %f %f %f\n", i,
+ rgba[0][i],
+ rgba[1][i],
+ rgba[2][i],
+ rgba[3][i]);
+ }
+ }
+#endif
+}
+
+
+/**
+ * Called via tgsi_sampler::get_samples() when running a fragment shader.
+ * Get four filtered RGBA values from the sampler's texture.
+ */
+void
+sp_get_samples_fragment(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ sp_get_samples(tgsi_sampler, s, t, p, TRUE, lodbias, rgba);
+}
+
+
+/**
+ * Called via tgsi_sampler::get_samples() when running a vertex shader.
+ * Get four filtered RGBA values from the sampler's texture.
+ */
+void
+sp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+ sp_get_samples(tgsi_sampler, s, t, p, FALSE, lodbias, rgba);
+}
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.h b/src/gallium/drivers/softpipe/sp_tex_sample.h
new file mode 100644
index 0000000000..40d8eb2c2a
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SP_TEX_SAMPLE_H
+#define SP_TEX_SAMPLE_H
+
+
+#include "tgsi/tgsi_exec.h"
+
+
+/**
+ * Subclass of tgsi_sampler
+ */
+struct sp_shader_sampler
+{
+ struct tgsi_sampler base; /**< base class */
+
+ uint unit;
+ struct softpipe_context *sp;
+ struct softpipe_tile_cache *cache;
+};
+
+
+
+static INLINE const struct sp_shader_sampler *
+sp_shader_sampler(const struct tgsi_sampler *sampler)
+{
+ return (const struct sp_shader_sampler *) sampler;
+}
+
+
+extern void
+sp_get_samples_fragment(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE]);
+
+extern void
+sp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler,
+ const float s[QUAD_SIZE],
+ const float t[QUAD_SIZE],
+ const float p[QUAD_SIZE],
+ float lodbias,
+ float rgba[NUM_CHANNELS][QUAD_SIZE]);
+
+
+#endif /* SP_TEX_SAMPLE_H */
diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c
new file mode 100644
index 0000000000..548e40c4a8
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_texture.c
@@ -0,0 +1,407 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Michel Dänzer <michel@tungstengraphics.com>
+ */
+
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_texture.h"
+#include "sp_screen.h"
+#include "sp_winsys.h"
+
+
+/**
+ * Conventional allocation path for non-display textures:
+ * Use a simple, maximally packed layout.
+ */
+static boolean
+softpipe_texture_layout(struct pipe_screen *screen,
+ struct softpipe_texture * spt)
+{
+ struct pipe_texture *pt = &spt->base;
+ unsigned level;
+ unsigned width = pt->width[0];
+ unsigned height = pt->height[0];
+ unsigned depth = pt->depth[0];
+
+ unsigned buffer_size = 0;
+
+ for (level = 0; level <= pt->last_level; level++) {
+ pt->width[level] = width;
+ pt->height[level] = height;
+ pt->depth[level] = depth;
+ pt->nblocksx[level] = pf_get_nblocksx(&pt->block, width);
+ pt->nblocksy[level] = pf_get_nblocksy(&pt->block, height);
+ spt->stride[level] = pt->nblocksx[level]*pt->block.size;
+
+ spt->level_offset[level] = buffer_size;
+
+ buffer_size += (pt->nblocksy[level] *
+ ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
+ spt->stride[level]);
+
+ width = minify(width);
+ height = minify(height);
+ depth = minify(depth);
+ }
+
+ spt->buffer = screen->buffer_create(screen, 32,
+ PIPE_BUFFER_USAGE_PIXEL,
+ buffer_size);
+
+ return spt->buffer != NULL;
+}
+
+
+/**
+ * Texture layout for simple color buffers.
+ */
+static boolean
+softpipe_displaytarget_layout(struct pipe_screen *screen,
+ struct softpipe_texture * spt)
+{
+ unsigned usage = (PIPE_BUFFER_USAGE_CPU_READ_WRITE |
+ PIPE_BUFFER_USAGE_GPU_READ_WRITE);
+ unsigned tex_usage = spt->base.tex_usage;
+
+ spt->base.nblocksx[0] = pf_get_nblocksx(&spt->base.block, spt->base.width[0]);
+ spt->base.nblocksy[0] = pf_get_nblocksy(&spt->base.block, spt->base.height[0]);
+
+ spt->buffer = screen->surface_buffer_create( screen,
+ spt->base.width[0],
+ spt->base.height[0],
+ spt->base.format,
+ usage,
+ tex_usage,
+ &spt->stride[0]);
+
+ return spt->buffer != NULL;
+}
+
+
+static struct pipe_texture *
+softpipe_texture_create(struct pipe_screen *screen,
+ const struct pipe_texture *templat)
+{
+ struct softpipe_texture *spt = CALLOC_STRUCT(softpipe_texture);
+ if (!spt)
+ return NULL;
+
+ spt->base = *templat;
+ pipe_reference_init(&spt->base.reference, 1);
+ spt->base.screen = screen;
+
+ if (spt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_PRIMARY)) {
+ if (!softpipe_displaytarget_layout(screen, spt))
+ goto fail;
+ }
+ else {
+ if (!softpipe_texture_layout(screen, spt))
+ goto fail;
+ }
+
+ return &spt->base;
+
+ fail:
+ FREE(spt);
+ return NULL;
+}
+
+
+static struct pipe_texture *
+softpipe_texture_blanket(struct pipe_screen * screen,
+ const struct pipe_texture *base,
+ const unsigned *stride,
+ struct pipe_buffer *buffer)
+{
+ struct softpipe_texture *spt;
+ assert(screen);
+
+ /* Only supports one type */
+ if (base->target != PIPE_TEXTURE_2D ||
+ base->last_level != 0 ||
+ base->depth[0] != 1) {
+ return NULL;
+ }
+
+ spt = CALLOC_STRUCT(softpipe_texture);
+ if (!spt)
+ return NULL;
+
+ spt->base = *base;
+ pipe_reference_init(&spt->base.reference, 1);
+ spt->base.screen = screen;
+ spt->base.nblocksx[0] = pf_get_nblocksx(&spt->base.block, spt->base.width[0]);
+ spt->base.nblocksy[0] = pf_get_nblocksy(&spt->base.block, spt->base.height[0]);
+ spt->stride[0] = stride[0];
+
+ pipe_buffer_reference(&spt->buffer, buffer);
+
+ return &spt->base;
+}
+
+
+static void
+softpipe_texture_destroy(struct pipe_texture *pt)
+{
+ struct softpipe_texture *spt = softpipe_texture(pt);
+
+ pipe_buffer_reference(&spt->buffer, NULL);
+ FREE(spt);
+}
+
+
+static struct pipe_surface *
+softpipe_get_tex_surface(struct pipe_screen *screen,
+ struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned usage)
+{
+ struct softpipe_texture *spt = softpipe_texture(pt);
+ struct pipe_surface *ps;
+
+ assert(level <= pt->last_level);
+
+ ps = CALLOC_STRUCT(pipe_surface);
+ if (ps) {
+ pipe_reference_init(&ps->reference, 1);
+ pipe_texture_reference(&ps->texture, pt);
+ ps->format = pt->format;
+ ps->width = pt->width[level];
+ ps->height = pt->height[level];
+ ps->offset = spt->level_offset[level];
+ ps->usage = usage;
+
+ /* Because we are softpipe, anything that the state tracker
+ * thought was going to be done with the GPU will actually get
+ * done with the CPU. Let's adjust the flags to take that into
+ * account.
+ */
+ if (ps->usage & PIPE_BUFFER_USAGE_GPU_WRITE) {
+ /* GPU_WRITE means "render" and that can involve reads (blending) */
+ ps->usage |= PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_CPU_READ;
+ }
+
+ if (ps->usage & PIPE_BUFFER_USAGE_GPU_READ)
+ ps->usage |= PIPE_BUFFER_USAGE_CPU_READ;
+
+ ps->face = face;
+ ps->level = level;
+ ps->zslice = zslice;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ps->offset += face * pt->nblocksy[level] * spt->stride[level];
+ }
+ else if (pt->target == PIPE_TEXTURE_3D) {
+ ps->offset += zslice * pt->nblocksy[level] * spt->stride[level];
+ }
+ else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+ }
+ return ps;
+}
+
+
+static void
+softpipe_tex_surface_destroy(struct pipe_surface *surf)
+{
+ /* Effectively do the texture_update work here - if texture images
+ * needed post-processing to put them into hardware layout, this is
+ * where it would happen. For softpipe, nothing to do.
+ */
+ assert(surf->texture);
+ pipe_texture_reference(&surf->texture, NULL);
+ FREE(surf);
+}
+
+
+static struct pipe_transfer *
+softpipe_get_tex_transfer(struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct softpipe_texture *sptex = softpipe_texture(texture);
+ struct softpipe_transfer *spt;
+
+ assert(texture);
+ assert(level <= texture->last_level);
+
+ spt = CALLOC_STRUCT(softpipe_transfer);
+ if (spt) {
+ struct pipe_transfer *pt = &spt->base;
+ pipe_texture_reference(&pt->texture, texture);
+ pt->format = texture->format;
+ pt->block = texture->block;
+ pt->x = x;
+ pt->y = y;
+ pt->width = w;
+ pt->height = h;
+ pt->nblocksx = texture->nblocksx[level];
+ pt->nblocksy = texture->nblocksy[level];
+ pt->stride = sptex->stride[level];
+ pt->usage = usage;
+ pt->face = face;
+ pt->level = level;
+ pt->zslice = zslice;
+
+ spt->offset = sptex->level_offset[level];
+
+ if (texture->target == PIPE_TEXTURE_CUBE) {
+ spt->offset += face * pt->nblocksy * pt->stride;
+ }
+ else if (texture->target == PIPE_TEXTURE_3D) {
+ spt->offset += zslice * pt->nblocksy * pt->stride;
+ }
+ else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+ return pt;
+ }
+ return NULL;
+}
+
+
+static void
+softpipe_tex_transfer_destroy(struct pipe_transfer *transfer)
+{
+ /* Effectively do the texture_update work here - if texture images
+ * needed post-processing to put them into hardware layout, this is
+ * where it would happen. For softpipe, nothing to do.
+ */
+ assert (transfer->texture);
+ pipe_texture_reference(&transfer->texture, NULL);
+ FREE(transfer);
+}
+
+
+static void *
+softpipe_transfer_map( struct pipe_screen *screen,
+ struct pipe_transfer *transfer )
+{
+ ubyte *map, *xfer_map;
+ struct softpipe_texture *spt;
+ unsigned flags = 0;
+
+ assert(transfer->texture);
+ spt = softpipe_texture(transfer->texture);
+
+ if (transfer->usage != PIPE_TRANSFER_READ) {
+ flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
+ }
+
+ if (transfer->usage != PIPE_TRANSFER_WRITE) {
+ flags |= PIPE_BUFFER_USAGE_CPU_READ;
+ }
+
+ map = pipe_buffer_map(screen, spt->buffer, flags);
+ if (map == NULL)
+ return NULL;
+
+ /* May want to different things here depending on read/write nature
+ * of the map:
+ */
+ if (transfer->texture && transfer->usage != PIPE_TRANSFER_READ) {
+ /* Do something to notify sharing contexts of a texture change.
+ * In softpipe, that would mean flushing the texture cache.
+ */
+ softpipe_screen(screen)->timestamp++;
+ }
+
+ xfer_map = map + softpipe_transfer(transfer)->offset +
+ transfer->y / transfer->block.height * transfer->stride +
+ transfer->x / transfer->block.width * transfer->block.size;
+ /*printf("map = %p xfer map = %p\n", map, xfer_map);*/
+ return xfer_map;
+}
+
+
+static void
+softpipe_transfer_unmap(struct pipe_screen *screen,
+ struct pipe_transfer *transfer)
+{
+ struct softpipe_texture *spt;
+
+ assert(transfer->texture);
+ spt = softpipe_texture(transfer->texture);
+
+ pipe_buffer_unmap( screen, spt->buffer );
+
+ if (transfer->usage != PIPE_TRANSFER_READ) {
+ /* Mark the texture as dirty to expire the tile caches. */
+ spt->modified = TRUE;
+ }
+}
+
+
+void
+softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
+{
+ screen->texture_create = softpipe_texture_create;
+ screen->texture_blanket = softpipe_texture_blanket;
+ screen->texture_destroy = softpipe_texture_destroy;
+
+ screen->get_tex_surface = softpipe_get_tex_surface;
+ screen->tex_surface_destroy = softpipe_tex_surface_destroy;
+
+ screen->get_tex_transfer = softpipe_get_tex_transfer;
+ screen->tex_transfer_destroy = softpipe_tex_transfer_destroy;
+ screen->transfer_map = softpipe_transfer_map;
+ screen->transfer_unmap = softpipe_transfer_unmap;
+}
+
+
+boolean
+softpipe_get_texture_buffer( struct pipe_texture *texture,
+ struct pipe_buffer **buf,
+ unsigned *stride )
+{
+ struct softpipe_texture *tex = (struct softpipe_texture *) texture;
+
+ if (!tex)
+ return FALSE;
+
+ pipe_buffer_reference(buf, tex->buffer);
+
+ if (stride)
+ *stride = tex->stride[0];
+
+ return TRUE;
+}
diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h
new file mode 100644
index 0000000000..b1b6130b22
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_texture.h
@@ -0,0 +1,80 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SP_TEXTURE_H
+#define SP_TEXTURE_H
+
+
+#include "pipe/p_state.h"
+
+
+struct pipe_context;
+struct pipe_screen;
+struct softpipe_context;
+
+
+struct softpipe_texture
+{
+ struct pipe_texture base;
+
+ unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned stride[PIPE_MAX_TEXTURE_LEVELS];
+
+ /* The data is held here:
+ */
+ struct pipe_buffer *buffer;
+
+ boolean modified;
+};
+
+struct softpipe_transfer
+{
+ struct pipe_transfer base;
+
+ unsigned long offset;
+};
+
+
+/** cast wrappers */
+static INLINE struct softpipe_texture *
+softpipe_texture(struct pipe_texture *pt)
+{
+ return (struct softpipe_texture *) pt;
+}
+
+static INLINE struct softpipe_transfer *
+softpipe_transfer(struct pipe_transfer *pt)
+{
+ return (struct softpipe_transfer *) pt;
+}
+
+
+extern void
+softpipe_init_screen_texture_funcs(struct pipe_screen *screen);
+
+
+#endif /* SP_TEXTURE */
diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c
new file mode 100644
index 0000000000..1f9b8f1f4f
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_tile_cache.c
@@ -0,0 +1,626 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Texture tile caching.
+ *
+ * Author:
+ * Brian Paul
+ */
+
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_tile.h"
+#include "sp_context.h"
+#include "sp_surface.h"
+#include "sp_texture.h"
+#include "sp_tile_cache.h"
+
+#define NUM_ENTRIES 50
+
+
+/** XXX move these */
+#define MAX_WIDTH 2048
+#define MAX_HEIGHT 2048
+
+
+struct softpipe_tile_cache
+{
+ struct pipe_screen *screen;
+ struct pipe_surface *surface; /**< the surface we're caching */
+ struct pipe_transfer *transfer;
+ void *transfer_map;
+ struct pipe_texture *texture; /**< if caching a texture */
+ struct softpipe_cached_tile entries[NUM_ENTRIES];
+ uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32];
+ float clear_color[4]; /**< for color bufs */
+ uint clear_val; /**< for z+stencil, or packed color clear value */
+ boolean depth_stencil; /**< Is the surface a depth/stencil format? */
+
+ struct pipe_transfer *tex_trans;
+ void *tex_trans_map;
+ int tex_face, tex_level, tex_z;
+
+ struct softpipe_cached_tile tile; /**< scratch tile for clears */
+};
+
+
+/**
+ * Return the position in the cache for the tile that contains win pos (x,y).
+ * We currently use a direct mapped cache so this is like a hack key.
+ * At some point we should investige something more sophisticated, like
+ * a LRU replacement policy.
+ */
+#define CACHE_POS(x, y) \
+ (((x) / TILE_SIZE + ((y) / TILE_SIZE) * 5) % NUM_ENTRIES)
+
+
+
+/**
+ * Is the tile at (x,y) in cleared state?
+ */
+static INLINE uint
+is_clear_flag_set(const uint *bitvec, int x, int y)
+{
+ int pos, bit;
+ x /= TILE_SIZE;
+ y /= TILE_SIZE;
+ pos = y * (MAX_WIDTH / TILE_SIZE) + x;
+ assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
+ bit = bitvec[pos / 32] & (1 << (pos & 31));
+ return bit;
+}
+
+
+/**
+ * Mark the tile at (x,y) as not cleared.
+ */
+static INLINE void
+clear_clear_flag(uint *bitvec, int x, int y)
+{
+ int pos;
+ x /= TILE_SIZE;
+ y /= TILE_SIZE;
+ pos = y * (MAX_WIDTH / TILE_SIZE) + x;
+ assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
+ bitvec[pos / 32] &= ~(1 << (pos & 31));
+}
+
+
+struct softpipe_tile_cache *
+sp_create_tile_cache( struct pipe_screen *screen )
+{
+ struct softpipe_tile_cache *tc;
+ uint pos;
+
+ tc = CALLOC_STRUCT( softpipe_tile_cache );
+ if (tc) {
+ tc->screen = screen;
+ for (pos = 0; pos < NUM_ENTRIES; pos++) {
+ tc->entries[pos].x =
+ tc->entries[pos].y = -1;
+ }
+ }
+ return tc;
+}
+
+
+void
+sp_destroy_tile_cache(struct softpipe_tile_cache *tc)
+{
+ struct pipe_screen *screen;
+ uint pos;
+
+ for (pos = 0; pos < NUM_ENTRIES; pos++) {
+ /*assert(tc->entries[pos].x < 0);*/
+ }
+ if (tc->transfer) {
+ screen = tc->transfer->texture->screen;
+ screen->tex_transfer_destroy(tc->transfer);
+ }
+ if (tc->tex_trans) {
+ screen = tc->tex_trans->texture->screen;
+ screen->tex_transfer_destroy(tc->tex_trans);
+ }
+
+ FREE( tc );
+}
+
+
+/**
+ * Specify the surface to cache.
+ */
+void
+sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
+ struct pipe_surface *ps)
+{
+ assert(!tc->texture);
+
+ if (tc->transfer) {
+ struct pipe_screen *screen = tc->transfer->texture->screen;
+
+ if (ps == tc->surface)
+ return;
+
+ if (tc->transfer_map) {
+ screen->transfer_unmap(screen, tc->transfer);
+ tc->transfer_map = NULL;
+ }
+
+ screen->tex_transfer_destroy(tc->transfer);
+ tc->transfer = NULL;
+ }
+
+ tc->surface = ps;
+
+ if (ps) {
+ struct pipe_screen *screen = ps->texture->screen;
+
+ tc->transfer = screen->get_tex_transfer(screen, ps->texture, ps->face,
+ ps->level, ps->zslice,
+ PIPE_TRANSFER_READ_WRITE,
+ 0, 0, ps->width, ps->height);
+
+ tc->depth_stencil = (ps->format == PIPE_FORMAT_S8Z24_UNORM ||
+ ps->format == PIPE_FORMAT_X8Z24_UNORM ||
+ ps->format == PIPE_FORMAT_Z24S8_UNORM ||
+ ps->format == PIPE_FORMAT_Z24X8_UNORM ||
+ ps->format == PIPE_FORMAT_Z16_UNORM ||
+ ps->format == PIPE_FORMAT_Z32_UNORM ||
+ ps->format == PIPE_FORMAT_S8_UNORM);
+ }
+}
+
+
+/**
+ * Return the transfer being cached.
+ */
+struct pipe_surface *
+sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
+{
+ return tc->surface;
+}
+
+
+void
+sp_tile_cache_map_transfers(struct softpipe_tile_cache *tc)
+{
+ if (tc->transfer && !tc->transfer_map)
+ tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer);
+
+ if (tc->tex_trans && !tc->tex_trans_map)
+ tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans);
+}
+
+
+void
+sp_tile_cache_unmap_transfers(struct softpipe_tile_cache *tc)
+{
+ if (tc->transfer_map) {
+ tc->screen->transfer_unmap(tc->screen, tc->transfer);
+ tc->transfer_map = NULL;
+ }
+
+ if (tc->tex_trans_map) {
+ tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
+ tc->tex_trans_map = NULL;
+ }
+}
+
+
+/**
+ * Specify the texture to cache.
+ */
+void
+sp_tile_cache_set_texture(struct pipe_context *pipe,
+ struct softpipe_tile_cache *tc,
+ struct pipe_texture *texture)
+{
+ uint i;
+
+ assert(!tc->transfer);
+
+ pipe_texture_reference(&tc->texture, texture);
+
+ if (tc->tex_trans) {
+ struct pipe_screen *screen = tc->tex_trans->texture->screen;
+
+ if (tc->tex_trans_map) {
+ screen->transfer_unmap(screen, tc->tex_trans);
+ tc->tex_trans_map = NULL;
+ }
+
+ screen->tex_transfer_destroy(tc->tex_trans);
+ tc->tex_trans = NULL;
+ }
+
+ /* mark as entries as invalid/empty */
+ /* XXX we should try to avoid this when the teximage hasn't changed */
+ for (i = 0; i < NUM_ENTRIES; i++) {
+ tc->entries[i].x = -1;
+ }
+
+ tc->tex_face = -1; /* any invalid value here */
+}
+
+
+/**
+ * Set pixels in a tile to the given clear color/value, float.
+ */
+static void
+clear_tile_rgba(struct softpipe_cached_tile *tile,
+ enum pipe_format format,
+ const float clear_value[4])
+{
+ if (clear_value[0] == 0.0 &&
+ clear_value[1] == 0.0 &&
+ clear_value[2] == 0.0 &&
+ clear_value[3] == 0.0) {
+ memset(tile->data.color, 0, sizeof(tile->data.color));
+ }
+ else {
+ uint i, j;
+ for (i = 0; i < TILE_SIZE; i++) {
+ for (j = 0; j < TILE_SIZE; j++) {
+ tile->data.color[i][j][0] = clear_value[0];
+ tile->data.color[i][j][1] = clear_value[1];
+ tile->data.color[i][j][2] = clear_value[2];
+ tile->data.color[i][j][3] = clear_value[3];
+ }
+ }
+ }
+}
+
+
+/**
+ * Set a tile to a solid value/color.
+ */
+static void
+clear_tile(struct softpipe_cached_tile *tile,
+ enum pipe_format format,
+ uint clear_value)
+{
+ uint i, j;
+
+ switch (pf_get_size(format)) {
+ case 1:
+ memset(tile->data.any, 0, TILE_SIZE * TILE_SIZE);
+ break;
+ case 2:
+ if (clear_value == 0) {
+ memset(tile->data.any, 0, 2 * TILE_SIZE * TILE_SIZE);
+ }
+ else {
+ for (i = 0; i < TILE_SIZE; i++) {
+ for (j = 0; j < TILE_SIZE; j++) {
+ tile->data.depth16[i][j] = (ushort) clear_value;
+ }
+ }
+ }
+ break;
+ case 4:
+ if (clear_value == 0) {
+ memset(tile->data.any, 0, 4 * TILE_SIZE * TILE_SIZE);
+ }
+ else {
+ for (i = 0; i < TILE_SIZE; i++) {
+ for (j = 0; j < TILE_SIZE; j++) {
+ tile->data.color32[i][j] = clear_value;
+ }
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Actually clear the tiles which were flagged as being in a clear state.
+ */
+static void
+sp_tile_cache_flush_clear(struct pipe_context *pipe,
+ struct softpipe_tile_cache *tc)
+{
+ struct pipe_transfer *pt = tc->transfer;
+ const uint w = tc->transfer->width;
+ const uint h = tc->transfer->height;
+ uint x, y;
+ uint numCleared = 0;
+
+ /* clear the scratch tile to the clear value */
+ clear_tile(&tc->tile, pt->format, tc->clear_val);
+
+ /* push the tile to all positions marked as clear */
+ for (y = 0; y < h; y += TILE_SIZE) {
+ for (x = 0; x < w; x += TILE_SIZE) {
+ if (is_clear_flag_set(tc->clear_flags, x, y)) {
+ pipe_put_tile_raw(pt,
+ x, y, TILE_SIZE, TILE_SIZE,
+ tc->tile.data.color32, 0/*STRIDE*/);
+
+ /* do this? */
+ clear_clear_flag(tc->clear_flags, x, y);
+
+ numCleared++;
+ }
+ }
+ }
+#if 0
+ debug_printf("num cleared: %u\n", numCleared);
+#endif
+}
+
+
+/**
+ * Flush the tile cache: write all dirty tiles back to the transfer.
+ * any tiles "flagged" as cleared will be "really" cleared.
+ */
+void
+sp_flush_tile_cache(struct softpipe_context *softpipe,
+ struct softpipe_tile_cache *tc)
+{
+ struct pipe_transfer *pt = tc->transfer;
+ int inuse = 0, pos;
+
+ if (pt) {
+ /* caching a drawing transfer */
+ for (pos = 0; pos < NUM_ENTRIES; pos++) {
+ struct softpipe_cached_tile *tile = tc->entries + pos;
+ if (tile->x >= 0) {
+ if (tc->depth_stencil) {
+ pipe_put_tile_raw(pt,
+ tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+ tile->data.depth32, 0/*STRIDE*/);
+ }
+ else {
+ pipe_put_tile_rgba(pt,
+ tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+ (float *) tile->data.color);
+ }
+ tile->x = tile->y = -1; /* mark as empty */
+ inuse++;
+ }
+ }
+
+#if TILE_CLEAR_OPTIMIZATION
+ sp_tile_cache_flush_clear(&softpipe->pipe, tc);
+#endif
+ }
+ else if (tc->texture) {
+ /* caching a texture, mark all entries as empty */
+ for (pos = 0; pos < NUM_ENTRIES; pos++) {
+ tc->entries[pos].x = -1;
+ }
+ tc->tex_face = -1;
+ }
+
+#if 0
+ debug_printf("flushed tiles in use: %d\n", inuse);
+#endif
+}
+
+
+/**
+ * Get a tile from the cache.
+ * \param x, y position of tile, in pixels
+ */
+struct softpipe_cached_tile *
+sp_get_cached_tile(struct softpipe_context *softpipe,
+ struct softpipe_tile_cache *tc, int x, int y)
+{
+ struct pipe_transfer *pt = tc->transfer;
+
+ /* tile pos in framebuffer: */
+ const int tile_x = x & ~(TILE_SIZE - 1);
+ const int tile_y = y & ~(TILE_SIZE - 1);
+
+ /* cache pos/entry: */
+ const int pos = CACHE_POS(x, y);
+ struct softpipe_cached_tile *tile = tc->entries + pos;
+
+ if (tile_x != tile->x ||
+ tile_y != tile->y) {
+
+ if (tile->x != -1) {
+ /* put dirty tile back in framebuffer */
+ if (tc->depth_stencil) {
+ pipe_put_tile_raw(pt,
+ tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+ tile->data.depth32, 0/*STRIDE*/);
+ }
+ else {
+ pipe_put_tile_rgba(pt,
+ tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+ (float *) tile->data.color);
+ }
+ }
+
+ tile->x = tile_x;
+ tile->y = tile_y;
+
+ if (is_clear_flag_set(tc->clear_flags, x, y)) {
+ /* don't get tile from framebuffer, just clear it */
+ if (tc->depth_stencil) {
+ clear_tile(tile, pt->format, tc->clear_val);
+ }
+ else {
+ clear_tile_rgba(tile, pt->format, tc->clear_color);
+ }
+ clear_clear_flag(tc->clear_flags, x, y);
+ }
+ else {
+ /* get new tile data from transfer */
+ if (tc->depth_stencil) {
+ pipe_get_tile_raw(pt,
+ tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+ tile->data.depth32, 0/*STRIDE*/);
+ }
+ else {
+ pipe_get_tile_rgba(pt,
+ tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+ (float *) tile->data.color);
+ }
+ }
+ }
+
+ return tile;
+}
+
+
+/**
+ * Given the texture face, level, zslice, x and y values, compute
+ * the cache entry position/index where we'd hope to find the
+ * cached texture tile.
+ * This is basically a direct-map cache.
+ * XXX There's probably lots of ways in which we can improve this.
+ */
+static INLINE uint
+tex_cache_pos(int x, int y, int z, int face, int level)
+{
+ uint entry = x + y * 9 + z * 3 + face + level * 7;
+ return entry % NUM_ENTRIES;
+}
+
+
+/**
+ * Similar to sp_get_cached_tile() but for textures.
+ * Tiles are read-only and indexed with more params.
+ */
+const struct softpipe_cached_tile *
+sp_get_cached_tile_tex(struct softpipe_context *sp,
+ struct softpipe_tile_cache *tc, int x, int y, int z,
+ int face, int level)
+{
+ struct pipe_screen *screen = sp->pipe.screen;
+ /* tile pos in framebuffer: */
+ const int tile_x = x & ~(TILE_SIZE - 1);
+ const int tile_y = y & ~(TILE_SIZE - 1);
+ /* cache pos/entry: */
+ const uint pos = tex_cache_pos(x / TILE_SIZE, y / TILE_SIZE, z,
+ face, level);
+ struct softpipe_cached_tile *tile = tc->entries + pos;
+
+ if (tc->texture) {
+ struct softpipe_texture *spt = softpipe_texture(tc->texture);
+ if (spt->modified) {
+ /* texture was modified, invalidate all cached tiles */
+ uint p;
+ for (p = 0; p < NUM_ENTRIES; p++) {
+ tile = tc->entries + p;
+ tile->x = -1;
+ }
+ spt->modified = FALSE;
+ }
+ }
+
+ if (tile_x != tile->x ||
+ tile_y != tile->y ||
+ z != tile->z ||
+ face != tile->face ||
+ level != tile->level) {
+ /* cache miss */
+
+#if 0
+ printf("miss at %u x=%d y=%d z=%d face=%d level=%d\n", pos,
+ x/TILE_SIZE, y/TILE_SIZE, z, face, level);
+#endif
+ /* check if we need to get a new transfer */
+ if (!tc->tex_trans ||
+ tc->tex_face != face ||
+ tc->tex_level != level ||
+ tc->tex_z != z) {
+ /* get new transfer (view into texture) */
+
+ if (tc->tex_trans) {
+ if (tc->tex_trans_map) {
+ tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
+ tc->tex_trans_map = NULL;
+ }
+
+ screen->tex_transfer_destroy(tc->tex_trans);
+ tc->tex_trans = NULL;
+ }
+
+ tc->tex_trans = screen->get_tex_transfer(screen, tc->texture, face, level, z,
+ PIPE_TRANSFER_READ, 0, 0,
+ tc->texture->width[level],
+ tc->texture->height[level]);
+ tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans);
+
+ tc->tex_face = face;
+ tc->tex_level = level;
+ tc->tex_z = z;
+ }
+
+ /* get tile from the transfer (view into texture) */
+ pipe_get_tile_rgba(tc->tex_trans,
+ tile_x, tile_y, TILE_SIZE, TILE_SIZE,
+ (float *) tile->data.color);
+ tile->x = tile_x;
+ tile->y = tile_y;
+ tile->z = z;
+ tile->face = face;
+ tile->level = level;
+ }
+
+ return tile;
+}
+
+
+/**
+ * When a whole surface is being cleared to a value we can avoid
+ * fetching tiles above.
+ * Save the color and set a 'clearflag' for each tile of the screen.
+ */
+void
+sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float *rgba,
+ uint clearValue)
+{
+ uint pos;
+
+ tc->clear_color[0] = rgba[0];
+ tc->clear_color[1] = rgba[1];
+ tc->clear_color[2] = rgba[2];
+ tc->clear_color[3] = rgba[3];
+
+ tc->clear_val = clearValue;
+
+#if TILE_CLEAR_OPTIMIZATION
+ /* set flags to indicate all the tiles are cleared */
+ memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
+#else
+ /* disable the optimization */
+ memset(tc->clear_flags, 0, sizeof(tc->clear_flags));
+#endif
+
+ for (pos = 0; pos < NUM_ENTRIES; pos++) {
+ struct softpipe_cached_tile *tile = tc->entries + pos;
+ tile->x = tile->y = -1;
+ }
+}
diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h
new file mode 100644
index 0000000000..8f247d0e58
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_tile_cache.h
@@ -0,0 +1,106 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SP_TILE_CACHE_H
+#define SP_TILE_CACHE_H
+
+#define TILE_CLEAR_OPTIMIZATION 1
+
+
+#include "pipe/p_compiler.h"
+
+
+struct softpipe_context;
+struct softpipe_tile_cache;
+
+
+/**
+ * Cache tile size (width and height). This needs to be a power of two.
+ */
+#define TILE_SIZE 64
+
+
+
+struct softpipe_cached_tile
+{
+ int x, y; /**< pos of tile in window coords */
+ int z, face, level; /**< Extra texture indexes */
+ union {
+ float color[TILE_SIZE][TILE_SIZE][4];
+ uint color32[TILE_SIZE][TILE_SIZE];
+ uint depth32[TILE_SIZE][TILE_SIZE];
+ ushort depth16[TILE_SIZE][TILE_SIZE];
+ ubyte stencil8[TILE_SIZE][TILE_SIZE];
+ ubyte any[1];
+ } data;
+};
+
+
+extern struct softpipe_tile_cache *
+sp_create_tile_cache( struct pipe_screen *screen );
+
+extern void
+sp_destroy_tile_cache(struct softpipe_tile_cache *tc);
+
+extern void
+sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
+ struct pipe_surface *sps);
+
+extern struct pipe_surface *
+sp_tile_cache_get_surface(struct softpipe_tile_cache *tc);
+
+extern void
+sp_tile_cache_map_transfers(struct softpipe_tile_cache *tc);
+
+extern void
+sp_tile_cache_unmap_transfers(struct softpipe_tile_cache *tc);
+
+extern void
+sp_tile_cache_set_texture(struct pipe_context *pipe,
+ struct softpipe_tile_cache *tc,
+ struct pipe_texture *texture);
+
+extern void
+sp_flush_tile_cache(struct softpipe_context *softpipe,
+ struct softpipe_tile_cache *tc);
+
+extern void
+sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float *rgba,
+ uint clearValue);
+
+extern struct softpipe_cached_tile *
+sp_get_cached_tile(struct softpipe_context *softpipe,
+ struct softpipe_tile_cache *tc, int x, int y);
+
+extern const struct softpipe_cached_tile *
+sp_get_cached_tile_tex(struct softpipe_context *softpipe,
+ struct softpipe_tile_cache *tc, int x, int y, int z,
+ int face, int level);
+
+
+#endif /* SP_TILE_CACHE_H */
+
diff --git a/src/gallium/drivers/softpipe/sp_winsys.h b/src/gallium/drivers/softpipe/sp_winsys.h
new file mode 100644
index 0000000000..9e571862b7
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_winsys.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* This is the interface that softpipe requires any window system
+ * hosting it to implement. This is the only include file in softpipe
+ * which is public.
+ */
+
+
+#ifndef SP_WINSYS_H
+#define SP_WINSYS_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_screen;
+struct pipe_winsys;
+struct pipe_context;
+
+
+struct pipe_context *softpipe_create( struct pipe_screen * );
+
+
+struct pipe_screen *
+softpipe_create_screen(struct pipe_winsys *);
+
+
+boolean
+softpipe_get_texture_buffer( struct pipe_texture *texture,
+ struct pipe_buffer **buf,
+ unsigned *stride );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SP_WINSYS_H */
diff --git a/src/gallium/drivers/trace/Makefile b/src/gallium/drivers/trace/Makefile
new file mode 100644
index 0000000000..dd6831c70a
--- /dev/null
+++ b/src/gallium/drivers/trace/Makefile
@@ -0,0 +1,17 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = trace
+
+C_SOURCES = \
+ tr_buffer.c \
+ tr_context.c \
+ tr_dump.c \
+ tr_dump_state.c \
+ tr_screen.c \
+ tr_state.c \
+ tr_rbug.c \
+ tr_drm.c \
+ tr_texture.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/trace/README b/src/gallium/drivers/trace/README
new file mode 100644
index 0000000000..1000c31e49
--- /dev/null
+++ b/src/gallium/drivers/trace/README
@@ -0,0 +1,78 @@
+ TRACE PIPE DRIVER
+
+
+= About =
+
+This directory contains a Gallium3D debugger pipe driver.
+It can traces all incoming calls and/or provide remote debugging functionality.
+
+
+= Build Instructions =
+
+To build, invoke scons on the top dir as
+
+ scons dri=no statetrackers=mesa drivers=softpipe,i965simple,trace winsys=xlib
+
+
+= Usage =
+
+To use do
+
+ export LD_LIBRARY_PATH=$PWD/build/linux-x86-debug/lib
+
+ensure the right libGL.so is being picked by doing
+
+ ldd progs/trivial/tri
+
+== Traceing ==
+
+For traceing then do
+
+ export XMESA_TRACE=y
+ GALLIUM_TRACE=tri.trace progs/trivial/tri
+
+which should create a tri.trace file, which is an XML file. You can view copying
+trace.xsl to the same directory, and opening with a XSLT capable browser such as
+Firefox or Internet Explorer.
+
+== Remote debugging ==
+
+For remote debugging
+
+ export XMESA_TRACE=y
+ GALLIUM_RBUG=true progs/trivial/tri
+
+which should open gallium remote debugging session. While the program is running
+you can launch the small remote debugging application from progs/rbug. More
+information is in that directory.
+
+= Integrating =
+
+You can integrate the trace pipe driver either inside the state tracker or the
+winsys. The procedure on both cases is the same. Let's assume you have a
+pipe_screen and a pipe_context pair obtained by the usual means (variable and
+function names are just for illustration purposes):
+
+ real_screen = real_screen_create(...);
+
+ real_context = real_context_create(...);
+
+The trace screen and pipe_context is then created by doing
+
+ trace_screen = trace_screen_create(real_screen);
+
+ trace_context = trace_context_create(trace_screen, real_context);
+
+You can then simply use trace_screen and trace_context instead of real_screen
+and real_context.
+
+Do not call trace_winsys_create. Simply pass trace_screen->winsys or
+trace_context->winsys in places you would pass winsys.
+
+You can create as many contexts you wish. Just ensure that you don't mistake
+trace_screen with real_screen when creating them.
+
+
+--
+Jose Fonseca <jrfonseca@tungstengraphics.com>
+Jakob Bornecrantz <jakob@vmware.com>
diff --git a/src/gallium/drivers/trace/SConscript b/src/gallium/drivers/trace/SConscript
new file mode 100644
index 0000000000..c1675d1c16
--- /dev/null
+++ b/src/gallium/drivers/trace/SConscript
@@ -0,0 +1,19 @@
+Import('*')
+
+env = env.Clone()
+
+trace = env.ConvenienceLibrary(
+ target = 'trace',
+ source = [
+ 'tr_buffer.c',
+ 'tr_context.c',
+ 'tr_drm.c',
+ 'tr_dump.c',
+ 'tr_dump_state.c',
+ 'tr_screen.c',
+ 'tr_state.c',
+ 'tr_rbug.c',
+ 'tr_texture.c',
+ ])
+
+Export('trace')
diff --git a/src/gallium/drivers/trace/tr_buffer.c b/src/gallium/drivers/trace/tr_buffer.c
new file mode 100644
index 0000000000..4f0eff6a5a
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_buffer.c
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+
+#include "tr_buffer.h"
+
+struct pipe_buffer *
+trace_buffer_create(struct trace_screen *tr_scr,
+ struct pipe_buffer *buffer)
+{
+ struct trace_buffer *tr_buf;
+
+ if(!buffer)
+ goto error;
+
+ assert(buffer->screen == tr_scr->screen);
+
+ tr_buf = CALLOC_STRUCT(trace_buffer);
+ if(!tr_buf)
+ goto error;
+
+ memcpy(&tr_buf->base, buffer, sizeof(struct pipe_buffer));
+
+ pipe_reference_init(&tr_buf->base.reference, 1);
+ tr_buf->base.screen = &tr_scr->base;
+ tr_buf->buffer = buffer;
+
+ trace_screen_add_to_list(tr_scr, buffers, tr_buf);
+
+ return &tr_buf->base;
+
+error:
+ pipe_buffer_reference(&buffer, NULL);
+ return NULL;
+}
+
+
+void
+trace_buffer_destroy(struct trace_screen *tr_scr,
+ struct pipe_buffer *buffer)
+{
+ struct trace_buffer *tr_buf = trace_buffer(buffer);
+
+ trace_screen_remove_from_list(tr_scr, buffers, tr_buf);
+
+ pipe_buffer_reference(&tr_buf->buffer, NULL);
+ FREE(tr_buf);
+}
diff --git a/src/gallium/drivers/trace/tr_buffer.h b/src/gallium/drivers/trace/tr_buffer.h
new file mode 100644
index 0000000000..1a2d0b9aea
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_buffer.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TR_BUFFER_H_
+#define TR_BUFFER_H_
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+
+#include "tr_screen.h"
+
+
+struct trace_buffer
+{
+ struct pipe_buffer base;
+
+ struct pipe_buffer *buffer;
+
+ struct tr_list list;
+
+ void *map;
+ boolean range_flushed;
+};
+
+
+static INLINE struct trace_buffer *
+trace_buffer(struct pipe_buffer *buffer)
+{
+ if(!buffer)
+ return NULL;
+ (void)trace_screen(buffer->screen);
+ return (struct trace_buffer *)buffer;
+}
+
+
+struct pipe_buffer *
+trace_buffer_create(struct trace_screen *tr_scr,
+ struct pipe_buffer *buffer);
+
+void
+trace_buffer_destroy(struct trace_screen *tr_scr,
+ struct pipe_buffer *buffer);
+
+
+#endif
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
new file mode 100644
index 0000000000..ae0af4d055
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -0,0 +1,1302 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+
+#include "pipe/p_screen.h"
+
+#include "tr_dump.h"
+#include "tr_dump_state.h"
+#include "tr_state.h"
+#include "tr_buffer.h"
+#include "tr_screen.h"
+#include "tr_texture.h"
+
+
+static INLINE struct pipe_buffer *
+trace_buffer_unwrap(struct trace_context *tr_ctx,
+ struct pipe_buffer *buffer)
+{
+ struct trace_screen *tr_scr = trace_screen(tr_ctx->base.screen);
+ struct trace_buffer *tr_buf;
+
+ if(!buffer)
+ return NULL;
+
+ tr_buf = trace_buffer(buffer);
+
+ assert(tr_buf->buffer);
+ assert(tr_buf->buffer->screen == tr_scr->screen);
+ return tr_buf->buffer;
+}
+
+
+static INLINE struct pipe_texture *
+trace_texture_unwrap(struct trace_context *tr_ctx,
+ struct pipe_texture *texture)
+{
+ struct trace_texture *tr_tex;
+
+ if(!texture)
+ return NULL;
+
+ tr_tex = trace_texture(texture);
+
+ assert(tr_tex->texture);
+ return tr_tex->texture;
+}
+
+
+static INLINE struct pipe_surface *
+trace_surface_unwrap(struct trace_context *tr_ctx,
+ struct pipe_surface *surface)
+{
+ struct trace_screen *tr_scr = trace_screen(tr_ctx->base.screen);
+ struct trace_surface *tr_surf;
+
+ if(!surface)
+ return NULL;
+
+ assert(surface->texture);
+ if(!surface->texture)
+ return surface;
+
+ tr_surf = trace_surface(surface);
+
+ assert(tr_surf->surface);
+ assert(tr_surf->surface->texture->screen == tr_scr->screen);
+ return tr_surf->surface;
+}
+
+
+static INLINE void
+trace_context_set_edgeflags(struct pipe_context *_pipe,
+ const unsigned *bitfield)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "set_edgeflags");
+
+ trace_dump_arg(ptr, pipe);
+ /* FIXME: we don't know how big this array is */
+ trace_dump_arg(ptr, bitfield);
+
+ pipe->set_edgeflags(pipe, bitfield);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_draw_block(struct trace_context *tr_ctx, int flag)
+{
+ int k;
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+
+ if (tr_ctx->draw_blocker & flag) {
+ tr_ctx->draw_blocked |= flag;
+ } else if ((tr_ctx->draw_rule.blocker & flag) &&
+ (tr_ctx->draw_blocker & 4)) {
+ boolean block = FALSE;
+ debug_printf("%s (%lu %lu) (%lu %lu) (%lu %u) (%lu %u)\n", __FUNCTION__,
+ tr_ctx->draw_rule.fs, tr_ctx->curr.fs,
+ tr_ctx->draw_rule.vs, tr_ctx->curr.vs,
+ tr_ctx->draw_rule.surf, 0,
+ tr_ctx->draw_rule.tex, 0);
+ if (tr_ctx->draw_rule.fs &&
+ tr_ctx->draw_rule.fs == tr_ctx->curr.fs)
+ block = TRUE;
+ if (tr_ctx->draw_rule.vs &&
+ tr_ctx->draw_rule.vs == tr_ctx->curr.vs)
+ block = TRUE;
+ if (tr_ctx->draw_rule.surf &&
+ tr_ctx->draw_rule.surf == tr_ctx->curr.zsbuf)
+ block = TRUE;
+ if (tr_ctx->draw_rule.surf)
+ for (k = 0; k < tr_ctx->curr.nr_cbufs; k++)
+ if (tr_ctx->draw_rule.surf == tr_ctx->curr.cbufs[k])
+ block = TRUE;
+ if (tr_ctx->draw_rule.tex)
+ for (k = 0; k < tr_ctx->curr.num_texs; k++)
+ if (tr_ctx->draw_rule.tex == tr_ctx->curr.tex[k])
+ block = TRUE;
+
+ if (block)
+ tr_ctx->draw_blocked |= (flag | 4);
+ }
+
+ if (tr_ctx->draw_blocked)
+ trace_rbug_notify_draw_blocked(tr_ctx);
+
+ /* wait for rbug to clear the blocked flag */
+ while (tr_ctx->draw_blocked & flag) {
+ tr_ctx->draw_blocked |= flag;
+#ifdef PIPE_THREAD_HAVE_CONDVAR
+ pipe_condvar_wait(tr_ctx->draw_cond, tr_ctx->draw_mutex);
+#else
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+#ifdef PIPE_SUBSYSTEM_WINDOWS_USER
+ Sleep(1);
+#endif
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+#endif
+ }
+
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+}
+
+static INLINE boolean
+trace_context_draw_arrays(struct pipe_context *_pipe,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ boolean result;
+
+ if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled)
+ return 0;
+
+ trace_context_draw_block(tr_ctx, 1);
+
+ trace_dump_call_begin("pipe_context", "draw_arrays");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, mode);
+ trace_dump_arg(uint, start);
+ trace_dump_arg(uint, count);
+
+ result = pipe->draw_arrays(pipe, mode, start, count);;
+
+ trace_dump_ret(bool, result);
+
+ trace_dump_call_end();
+
+ trace_context_draw_block(tr_ctx, 2);
+
+ return result;
+}
+
+
+static INLINE boolean
+trace_context_draw_elements(struct pipe_context *_pipe,
+ struct pipe_buffer *_indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_buffer *tr_buf = trace_buffer(_indexBuffer);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ struct pipe_buffer *indexBuffer = tr_buf->buffer;
+ boolean result;
+
+ if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled)
+ return 0;
+
+ trace_context_draw_block(tr_ctx, 1);
+
+ trace_screen_user_buffer_update(_pipe->screen, indexBuffer);
+
+ trace_dump_call_begin("pipe_context", "draw_elements");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, indexBuffer);
+ trace_dump_arg(uint, indexSize);
+ trace_dump_arg(uint, mode);
+ trace_dump_arg(uint, start);
+ trace_dump_arg(uint, count);
+
+ result = pipe->draw_elements(pipe, indexBuffer, indexSize, mode, start, count);;
+
+ trace_dump_ret(bool, result);
+
+ trace_dump_call_end();
+
+ trace_context_draw_block(tr_ctx, 2);
+
+ return result;
+}
+
+
+static INLINE boolean
+trace_context_draw_range_elements(struct pipe_context *_pipe,
+ struct pipe_buffer *_indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_buffer *tr_buf = trace_buffer(_indexBuffer);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ struct pipe_buffer *indexBuffer = tr_buf->buffer;
+ boolean result;
+
+ if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled)
+ return 0;
+
+ trace_context_draw_block(tr_ctx, 1);
+
+ trace_screen_user_buffer_update(_pipe->screen, indexBuffer);
+
+ trace_dump_call_begin("pipe_context", "draw_range_elements");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, indexBuffer);
+ trace_dump_arg(uint, indexSize);
+ trace_dump_arg(uint, minIndex);
+ trace_dump_arg(uint, maxIndex);
+ trace_dump_arg(uint, mode);
+ trace_dump_arg(uint, start);
+ trace_dump_arg(uint, count);
+
+ result = pipe->draw_range_elements(pipe,
+ indexBuffer,
+ indexSize, minIndex, maxIndex,
+ mode, start, count);
+
+ trace_dump_ret(bool, result);
+
+ trace_dump_call_end();
+
+ trace_context_draw_block(tr_ctx, 2);
+
+ return result;
+}
+
+
+static INLINE struct pipe_query *
+trace_context_create_query(struct pipe_context *_pipe,
+ unsigned query_type)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ struct pipe_query *result;
+
+ trace_dump_call_begin("pipe_context", "create_query");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, query_type);
+
+ result = pipe->create_query(pipe, query_type);;
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static INLINE void
+trace_context_destroy_query(struct pipe_context *_pipe,
+ struct pipe_query *query)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "destroy_query");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, query);
+
+ pipe->destroy_query(pipe, query);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_begin_query(struct pipe_context *_pipe,
+ struct pipe_query *query)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "begin_query");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, query);
+
+ pipe->begin_query(pipe, query);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_end_query(struct pipe_context *_pipe,
+ struct pipe_query *query)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "end_query");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, query);
+
+ pipe->end_query(pipe, query);
+
+ trace_dump_call_end();
+}
+
+
+static INLINE boolean
+trace_context_get_query_result(struct pipe_context *_pipe,
+ struct pipe_query *query,
+ boolean wait,
+ uint64_t *presult)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ uint64_t result;
+ boolean _result;
+
+ trace_dump_call_begin("pipe_context", "get_query_result");
+
+ trace_dump_arg(ptr, pipe);
+
+ _result = pipe->get_query_result(pipe, query, wait, presult);;
+ result = *presult;
+
+ trace_dump_arg(uint, result);
+ trace_dump_ret(bool, _result);
+
+ trace_dump_call_end();
+
+ return _result;
+}
+
+
+static INLINE void *
+trace_context_create_blend_state(struct pipe_context *_pipe,
+ const struct pipe_blend_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void * result;
+
+ trace_dump_call_begin("pipe_context", "create_blend_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(blend_state, state);
+
+ result = pipe->create_blend_state(pipe, state);;
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static INLINE void
+trace_context_bind_blend_state(struct pipe_context *_pipe,
+ void *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "bind_blend_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ pipe->bind_blend_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_delete_blend_state(struct pipe_context *_pipe,
+ void *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "delete_blend_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ pipe->delete_blend_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void *
+trace_context_create_sampler_state(struct pipe_context *_pipe,
+ const struct pipe_sampler_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void * result;
+
+ trace_dump_call_begin("pipe_context", "create_sampler_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(sampler_state, state);
+
+ result = pipe->create_sampler_state(pipe, state);;
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static INLINE void
+trace_context_bind_sampler_states(struct pipe_context *_pipe,
+ unsigned num_states, void **states)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "bind_sampler_states");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, num_states);
+ trace_dump_arg_array(ptr, states, num_states);
+
+ pipe->bind_sampler_states(pipe, num_states, states);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_delete_sampler_state(struct pipe_context *_pipe,
+ void *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "delete_sampler_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ pipe->delete_sampler_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void *
+trace_context_create_rasterizer_state(struct pipe_context *_pipe,
+ const struct pipe_rasterizer_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void * result;
+
+ trace_dump_call_begin("pipe_context", "create_rasterizer_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(rasterizer_state, state);
+
+ result = pipe->create_rasterizer_state(pipe, state);;
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static INLINE void
+trace_context_bind_rasterizer_state(struct pipe_context *_pipe,
+ void *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "bind_rasterizer_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ pipe->bind_rasterizer_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_delete_rasterizer_state(struct pipe_context *_pipe,
+ void *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "delete_rasterizer_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ pipe->delete_rasterizer_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void *
+trace_context_create_depth_stencil_alpha_state(struct pipe_context *_pipe,
+ const struct pipe_depth_stencil_alpha_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void * result;
+
+ trace_dump_call_begin("pipe_context", "create_depth_stencil_alpha_state");
+
+ result = pipe->create_depth_stencil_alpha_state(pipe, state);;
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(depth_stencil_alpha_state, state);
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static INLINE void
+trace_context_bind_depth_stencil_alpha_state(struct pipe_context *_pipe,
+ void *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "bind_depth_stencil_alpha_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ pipe->bind_depth_stencil_alpha_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_delete_depth_stencil_alpha_state(struct pipe_context *_pipe,
+ void *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "delete_depth_stencil_alpha_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ pipe->delete_depth_stencil_alpha_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void *
+trace_context_create_fs_state(struct pipe_context *_pipe,
+ const struct pipe_shader_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void * result;
+
+ trace_dump_call_begin("pipe_context", "create_fs_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(shader_state, state);
+
+ result = pipe->create_fs_state(pipe, state);;
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ result = trace_shader_create(tr_ctx, state, result, TRACE_SHADER_FRAGMENT);
+
+ return result;
+}
+
+
+static INLINE void
+trace_context_bind_fs_state(struct pipe_context *_pipe,
+ void *_state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_shader *tr_shdr = trace_shader(_state);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void *state = tr_shdr ? tr_shdr->state : NULL;
+
+ trace_dump_call_begin("pipe_context", "bind_fs_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ tr_ctx->curr.fs = tr_shdr;
+
+ if (tr_shdr && tr_shdr->replaced)
+ state = tr_shdr->replaced;
+
+ pipe->bind_fs_state(pipe, state);
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_delete_fs_state(struct pipe_context *_pipe,
+ void *_state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_shader *tr_shdr = trace_shader(_state);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void *state = tr_shdr->state;
+
+ trace_dump_call_begin("pipe_context", "delete_fs_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ pipe->delete_fs_state(pipe, state);
+
+ trace_dump_call_end();
+
+ trace_shader_destroy(tr_ctx, tr_shdr);
+}
+
+
+static INLINE void *
+trace_context_create_vs_state(struct pipe_context *_pipe,
+ const struct pipe_shader_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void * result;
+
+ trace_dump_call_begin("pipe_context", "create_vs_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(shader_state, state);
+
+ result = pipe->create_vs_state(pipe, state);
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ result = trace_shader_create(tr_ctx, state, result, TRACE_SHADER_VERTEX);
+
+ return result;
+}
+
+
+static INLINE void
+trace_context_bind_vs_state(struct pipe_context *_pipe,
+ void *_state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_shader *tr_shdr = trace_shader(_state);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void *state = tr_shdr ? tr_shdr->state : NULL;
+
+ trace_dump_call_begin("pipe_context", "bind_vs_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ tr_ctx->curr.vs = tr_shdr;
+
+ if (tr_shdr && tr_shdr->replaced)
+ state = tr_shdr->replaced;
+
+ pipe->bind_vs_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_delete_vs_state(struct pipe_context *_pipe,
+ void *_state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_shader *tr_shdr = trace_shader(_state);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ void *state = tr_shdr->state;
+
+ trace_dump_call_begin("pipe_context", "delete_vs_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, state);
+
+ pipe->delete_vs_state(pipe, state);;
+
+ trace_dump_call_end();
+
+ trace_shader_destroy(tr_ctx, tr_shdr);
+}
+
+
+static INLINE void
+trace_context_set_blend_color(struct pipe_context *_pipe,
+ const struct pipe_blend_color *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "set_blend_color");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(blend_color, state);
+
+ pipe->set_blend_color(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_set_clip_state(struct pipe_context *_pipe,
+ const struct pipe_clip_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "set_clip_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(clip_state, state);
+
+ pipe->set_clip_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_set_constant_buffer(struct pipe_context *_pipe,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buffer)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ if (buffer)
+ trace_screen_user_buffer_update(_pipe->screen, buffer->buffer);
+
+ trace_dump_call_begin("pipe_context", "set_constant_buffer");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, shader);
+ trace_dump_arg(uint, index);
+ trace_dump_arg(constant_buffer, buffer);
+
+ if (buffer) {
+ struct pipe_constant_buffer _buffer;
+ _buffer.buffer = trace_buffer_unwrap(tr_ctx, buffer->buffer);
+ pipe->set_constant_buffer(pipe, shader, index, &_buffer);
+ } else {
+ pipe->set_constant_buffer(pipe, shader, index, buffer);
+ }
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_set_framebuffer_state(struct pipe_context *_pipe,
+ const struct pipe_framebuffer_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ struct pipe_framebuffer_state unwrapped_state;
+ unsigned i;
+
+ {
+ tr_ctx->curr.nr_cbufs = state->nr_cbufs;
+ for (i = 0; i < state->nr_cbufs; i++)
+ if (state->cbufs[i])
+ tr_ctx->curr.cbufs[i] = trace_texture(state->cbufs[i]->texture);
+ else
+ tr_ctx->curr.cbufs[i] = NULL;
+ if (state->zsbuf)
+ tr_ctx->curr.zsbuf = trace_texture(state->zsbuf->texture);
+ else
+ tr_ctx->curr.zsbuf = NULL;
+ }
+
+ /* Unwrap the input state */
+ memcpy(&unwrapped_state, state, sizeof(unwrapped_state));
+ for(i = 0; i < state->nr_cbufs; ++i)
+ unwrapped_state.cbufs[i] = trace_surface_unwrap(tr_ctx, state->cbufs[i]);
+ for(i = state->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; ++i)
+ unwrapped_state.cbufs[i] = NULL;
+ unwrapped_state.zsbuf = trace_surface_unwrap(tr_ctx, state->zsbuf);
+ state = &unwrapped_state;
+
+ trace_dump_call_begin("pipe_context", "set_framebuffer_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(framebuffer_state, state);
+
+ pipe->set_framebuffer_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_set_polygon_stipple(struct pipe_context *_pipe,
+ const struct pipe_poly_stipple *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "set_polygon_stipple");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(poly_stipple, state);
+
+ pipe->set_polygon_stipple(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_set_scissor_state(struct pipe_context *_pipe,
+ const struct pipe_scissor_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "set_scissor_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(scissor_state, state);
+
+ pipe->set_scissor_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_set_viewport_state(struct pipe_context *_pipe,
+ const struct pipe_viewport_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "set_viewport_state");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(viewport_state, state);
+
+ pipe->set_viewport_state(pipe, state);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_set_sampler_textures(struct pipe_context *_pipe,
+ unsigned num_textures,
+ struct pipe_texture **textures)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_texture *tr_tex;
+ struct pipe_context *pipe = tr_ctx->pipe;
+ struct pipe_texture *unwrapped_textures[PIPE_MAX_SAMPLERS];
+ unsigned i;
+
+ tr_ctx->curr.num_texs = num_textures;
+ for(i = 0; i < num_textures; ++i) {
+ tr_tex = trace_texture(textures[i]);
+ tr_ctx->curr.tex[i] = tr_tex;
+ unwrapped_textures[i] = tr_tex ? tr_tex->texture : NULL;
+ }
+ textures = unwrapped_textures;
+
+ trace_dump_call_begin("pipe_context", "set_sampler_textures");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, num_textures);
+ trace_dump_arg_array(ptr, textures, num_textures);
+
+ pipe->set_sampler_textures(pipe, num_textures, textures);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_set_vertex_buffers(struct pipe_context *_pipe,
+ unsigned num_buffers,
+ const struct pipe_vertex_buffer *buffers)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ unsigned i;
+
+ for(i = 0; i < num_buffers; ++i)
+ trace_screen_user_buffer_update(_pipe->screen, buffers[i].buffer);
+
+ trace_dump_call_begin("pipe_context", "set_vertex_buffers");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, num_buffers);
+
+ trace_dump_arg_begin("buffers");
+ trace_dump_struct_array(vertex_buffer, buffers, num_buffers);
+ trace_dump_arg_end();
+
+ if (num_buffers) {
+ struct pipe_vertex_buffer *_buffers = malloc(num_buffers * sizeof(*_buffers));
+ memcpy(_buffers, buffers, num_buffers * sizeof(*_buffers));
+ for (i = 0; i < num_buffers; i++)
+ _buffers[i].buffer = trace_buffer_unwrap(tr_ctx, buffers[i].buffer);
+ pipe->set_vertex_buffers(pipe, num_buffers, _buffers);
+ free(_buffers);
+ } else {
+ pipe->set_vertex_buffers(pipe, num_buffers, NULL);
+ }
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_set_vertex_elements(struct pipe_context *_pipe,
+ unsigned num_elements,
+ const struct pipe_vertex_element *elements)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "set_vertex_elements");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, num_elements);
+
+ trace_dump_arg_begin("elements");
+ trace_dump_struct_array(vertex_element, elements, num_elements);
+ trace_dump_arg_end();
+
+ pipe->set_vertex_elements(pipe, num_elements, elements);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_surface_copy(struct pipe_context *_pipe,
+ struct pipe_surface *dest,
+ unsigned destx, unsigned desty,
+ struct pipe_surface *src,
+ unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ dest = trace_surface_unwrap(tr_ctx, dest);
+ src = trace_surface_unwrap(tr_ctx, src);
+
+ trace_dump_call_begin("pipe_context", "surface_copy");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, dest);
+ trace_dump_arg(uint, destx);
+ trace_dump_arg(uint, desty);
+ trace_dump_arg(ptr, src);
+ trace_dump_arg(uint, srcx);
+ trace_dump_arg(uint, srcy);
+ trace_dump_arg(uint, width);
+ trace_dump_arg(uint, height);
+
+ pipe->surface_copy(pipe,
+ dest, destx, desty,
+ src, srcx, srcy, width, height);
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_surface_fill(struct pipe_context *_pipe,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height,
+ unsigned value)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ dst = trace_surface_unwrap(tr_ctx, dst);
+
+ trace_dump_call_begin("pipe_context", "surface_fill");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, dst);
+ trace_dump_arg(uint, dstx);
+ trace_dump_arg(uint, dsty);
+ trace_dump_arg(uint, width);
+ trace_dump_arg(uint, height);
+
+ pipe->surface_fill(pipe, dst, dstx, dsty, width, height, value);;
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_clear(struct pipe_context *_pipe,
+ unsigned buffers,
+ const float *rgba,
+ double depth,
+ unsigned stencil)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "clear");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, buffers);
+ trace_dump_arg_array(float, rgba, 4);
+ trace_dump_arg(float, depth);
+ trace_dump_arg(uint, stencil);
+
+ pipe->clear(pipe, buffers, rgba, depth, stencil);
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_flush(struct pipe_context *_pipe,
+ unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "flush");
+
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, flags);
+
+ pipe->flush(pipe, flags, fence);;
+
+ if(fence)
+ trace_dump_ret(ptr, *fence);
+
+ trace_dump_call_end();
+}
+
+
+static INLINE void
+trace_context_destroy(struct pipe_context *_pipe)
+{
+ struct trace_screen *tr_scr = trace_screen(_pipe->screen);
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "destroy");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_call_end();
+
+ trace_screen_remove_from_list(tr_scr, contexts, tr_ctx);
+
+ pipe->destroy(pipe);
+
+ FREE(tr_ctx);
+}
+
+static unsigned int
+trace_is_texture_referenced( struct pipe_context *_pipe,
+ struct pipe_texture *_texture,
+ unsigned face, unsigned level)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_texture *tr_tex = trace_texture(_texture);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ struct pipe_texture *texture = tr_tex->texture;
+ unsigned int referenced;
+
+ trace_dump_call_begin("pipe_context", "is_texture_referenced");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, texture);
+ trace_dump_arg(uint, face);
+ trace_dump_arg(uint, level);
+
+ referenced = pipe->is_texture_referenced(pipe, texture, face, level);
+
+ trace_dump_ret(uint, referenced);
+ trace_dump_call_end();
+
+ return referenced;
+}
+
+static unsigned int
+trace_is_buffer_referenced( struct pipe_context *_pipe,
+ struct pipe_buffer *_buf)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_buffer *tr_buf = trace_buffer(_buf);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ struct pipe_buffer *buf = tr_buf->buffer;
+ unsigned int referenced;
+
+ trace_dump_call_begin("pipe_context", "is_buffer_referenced");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, buf);
+
+ referenced = pipe->is_buffer_referenced(pipe, buf);
+
+ trace_dump_ret(uint, referenced);
+ trace_dump_call_end();
+
+ return referenced;
+}
+
+static const struct debug_named_value rbug_blocker_flags[] = {
+ {"before", 1},
+ {"after", 2},
+ {NULL, 0},
+};
+
+struct pipe_context *
+trace_context_create(struct pipe_screen *_screen,
+ struct pipe_context *pipe)
+{
+ struct trace_screen *tr_scr;
+ struct trace_context *tr_ctx;
+ struct pipe_screen *screen;
+
+ if(!pipe)
+ goto error1;
+
+ if(!trace_enabled())
+ goto error1;
+
+ tr_scr = trace_screen(_screen);
+ screen = tr_scr->screen;
+
+ tr_ctx = CALLOC_STRUCT(trace_context);
+ if(!tr_ctx)
+ goto error1;
+
+ tr_ctx->draw_blocker = debug_get_flags_option("RBUG_BLOCK",
+ rbug_blocker_flags,
+ 0);
+ pipe_mutex_init(tr_ctx->draw_mutex);
+ pipe_condvar_init(tr_ctx->draw_cond);
+ pipe_mutex_init(tr_ctx->list_mutex);
+ make_empty_list(&tr_ctx->shaders);
+
+ tr_ctx->base.winsys = _screen->winsys;
+ tr_ctx->base.screen = _screen;
+ tr_ctx->base.destroy = trace_context_destroy;
+ tr_ctx->base.set_edgeflags = trace_context_set_edgeflags;
+ tr_ctx->base.draw_arrays = trace_context_draw_arrays;
+ tr_ctx->base.draw_elements = trace_context_draw_elements;
+ tr_ctx->base.draw_range_elements = trace_context_draw_range_elements;
+ tr_ctx->base.create_query = trace_context_create_query;
+ tr_ctx->base.destroy_query = trace_context_destroy_query;
+ tr_ctx->base.begin_query = trace_context_begin_query;
+ tr_ctx->base.end_query = trace_context_end_query;
+ tr_ctx->base.get_query_result = trace_context_get_query_result;
+ tr_ctx->base.create_blend_state = trace_context_create_blend_state;
+ tr_ctx->base.bind_blend_state = trace_context_bind_blend_state;
+ tr_ctx->base.delete_blend_state = trace_context_delete_blend_state;
+ tr_ctx->base.create_sampler_state = trace_context_create_sampler_state;
+ tr_ctx->base.bind_sampler_states = trace_context_bind_sampler_states;
+ tr_ctx->base.delete_sampler_state = trace_context_delete_sampler_state;
+ tr_ctx->base.create_rasterizer_state = trace_context_create_rasterizer_state;
+ tr_ctx->base.bind_rasterizer_state = trace_context_bind_rasterizer_state;
+ tr_ctx->base.delete_rasterizer_state = trace_context_delete_rasterizer_state;
+ tr_ctx->base.create_depth_stencil_alpha_state = trace_context_create_depth_stencil_alpha_state;
+ tr_ctx->base.bind_depth_stencil_alpha_state = trace_context_bind_depth_stencil_alpha_state;
+ tr_ctx->base.delete_depth_stencil_alpha_state = trace_context_delete_depth_stencil_alpha_state;
+ tr_ctx->base.create_fs_state = trace_context_create_fs_state;
+ tr_ctx->base.bind_fs_state = trace_context_bind_fs_state;
+ tr_ctx->base.delete_fs_state = trace_context_delete_fs_state;
+ tr_ctx->base.create_vs_state = trace_context_create_vs_state;
+ tr_ctx->base.bind_vs_state = trace_context_bind_vs_state;
+ tr_ctx->base.delete_vs_state = trace_context_delete_vs_state;
+ tr_ctx->base.set_blend_color = trace_context_set_blend_color;
+ tr_ctx->base.set_clip_state = trace_context_set_clip_state;
+ tr_ctx->base.set_constant_buffer = trace_context_set_constant_buffer;
+ tr_ctx->base.set_framebuffer_state = trace_context_set_framebuffer_state;
+ tr_ctx->base.set_polygon_stipple = trace_context_set_polygon_stipple;
+ tr_ctx->base.set_scissor_state = trace_context_set_scissor_state;
+ tr_ctx->base.set_viewport_state = trace_context_set_viewport_state;
+ tr_ctx->base.set_sampler_textures = trace_context_set_sampler_textures;
+ tr_ctx->base.set_vertex_buffers = trace_context_set_vertex_buffers;
+ tr_ctx->base.set_vertex_elements = trace_context_set_vertex_elements;
+ if (pipe->surface_copy)
+ tr_ctx->base.surface_copy = trace_context_surface_copy;
+ if (pipe->surface_fill)
+ tr_ctx->base.surface_fill = trace_context_surface_fill;
+ tr_ctx->base.clear = trace_context_clear;
+ tr_ctx->base.flush = trace_context_flush;
+ tr_ctx->base.is_texture_referenced = trace_is_texture_referenced;
+ tr_ctx->base.is_buffer_referenced = trace_is_buffer_referenced;
+
+ tr_ctx->pipe = pipe;
+
+ trace_dump_call_begin("", "pipe_context_create");
+ trace_dump_arg(ptr, screen);
+ trace_dump_ret(ptr, pipe);
+ trace_dump_call_end();
+
+ trace_screen_add_to_list(tr_scr, contexts, tr_ctx);
+
+ return &tr_ctx->base;
+
+error1:
+ return pipe;
+}
diff --git a/src/gallium/drivers/trace/tr_context.h b/src/gallium/drivers/trace/tr_context.h
new file mode 100644
index 0000000000..6febe4b411
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_context.h
@@ -0,0 +1,108 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TR_CONTEXT_H_
+#define TR_CONTEXT_H_
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "pipe/p_context.h"
+
+#include "tr_screen.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct trace_context
+{
+ struct pipe_context base;
+
+ struct pipe_context *pipe;
+
+ /* current state */
+ struct {
+ struct trace_shader *fs;
+ struct trace_shader *vs;
+
+ struct trace_texture *tex[PIPE_MAX_SAMPLERS];
+ unsigned num_texs;
+
+ unsigned nr_cbufs;
+ struct trace_texture *cbufs[PIPE_MAX_COLOR_BUFS];
+ struct trace_texture *zsbuf;
+ } curr;
+
+ struct {
+ struct trace_shader *fs;
+ struct trace_shader *vs;
+
+ struct trace_texture *tex;
+ struct trace_texture *surf;
+
+ int blocker;
+ } draw_rule;
+ unsigned draw_num_rules;
+ pipe_condvar draw_cond;
+ pipe_mutex draw_mutex;
+ int draw_blocker;
+ int draw_blocked;
+
+ /* for list on screen */
+ struct tr_list list;
+
+ /* list of state objects */
+ pipe_mutex list_mutex;
+ unsigned num_shaders;
+ struct tr_list shaders;
+};
+
+
+static INLINE struct trace_context *
+trace_context(struct pipe_context *pipe)
+{
+ assert(pipe);
+ return (struct trace_context *)pipe;
+}
+
+
+
+struct pipe_context *
+trace_context_create(struct pipe_screen *screen,
+ struct pipe_context *pipe);
+
+void
+trace_rbug_notify_draw_blocked(struct trace_context *tr_ctx);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TR_CONTEXT_H_ */
diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c
new file mode 100644
index 0000000000..781ca5d3bc
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_drm.c
@@ -0,0 +1,186 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "state_tracker/drm_api.h"
+
+#include "util/u_memory.h"
+#include "trace/tr_drm.h"
+#include "trace/tr_screen.h"
+#include "trace/tr_context.h"
+#include "trace/tr_buffer.h"
+#include "trace/tr_texture.h"
+
+struct trace_drm_api
+{
+ struct drm_api base;
+
+ struct drm_api *api;
+};
+
+static INLINE struct trace_drm_api *
+trace_drm_api(struct drm_api *_api)
+{
+ return (struct trace_drm_api *)_api;
+}
+
+static struct pipe_screen *
+trace_drm_create_screen(struct drm_api *_api, int fd,
+ struct drm_create_screen_arg *arg)
+{
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct drm_api *api = tr_api->api;
+ struct pipe_screen *screen;
+
+ /* TODO trace call */
+
+ if (arg && arg->mode != DRM_CREATE_NORMAL)
+ return NULL;
+
+ screen = api->create_screen(api, fd, arg);
+
+ return trace_screen_create(screen);
+}
+
+static struct pipe_context *
+trace_drm_create_context(struct drm_api *_api,
+ struct pipe_screen *_screen)
+{
+ struct trace_screen *tr_screen = trace_screen(_screen);
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct pipe_screen *screen = tr_screen->screen;
+ struct drm_api *api = tr_api->api;
+ struct pipe_context *pipe;
+
+ /* TODO trace call */
+
+ pipe = api->create_context(api, screen);
+
+ pipe = trace_context_create(_screen, pipe);
+
+ return pipe;
+}
+
+static struct pipe_texture *
+trace_drm_texture_from_shared_handle(struct drm_api *_api,
+ struct pipe_screen *_screen,
+ struct pipe_texture *templ,
+ const char *name,
+ unsigned stride,
+ unsigned handle)
+{
+ struct trace_screen *tr_screen = trace_screen(_screen);
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct pipe_screen *screen = tr_screen->screen;
+ struct drm_api *api = tr_api->api;
+ struct pipe_texture *result;
+
+ /* TODO trace call */
+
+ result = api->texture_from_shared_handle(api, screen, templ, name, stride, handle);
+
+ result = trace_texture_create(trace_screen(_screen), result);
+
+ return result;
+}
+
+static boolean
+trace_drm_shared_handle_from_texture(struct drm_api *_api,
+ struct pipe_screen *_screen,
+ struct pipe_texture *_texture,
+ unsigned *stride,
+ unsigned *handle)
+{
+ struct trace_screen *tr_screen = trace_screen(_screen);
+ struct trace_texture *tr_texture = trace_texture(_texture);
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct pipe_screen *screen = tr_screen->screen;
+ struct pipe_texture *texture = tr_texture->texture;
+ struct drm_api *api = tr_api->api;
+
+ /* TODO trace call */
+
+ return api->shared_handle_from_texture(api, screen, texture, stride, handle);
+}
+
+static boolean
+trace_drm_local_handle_from_texture(struct drm_api *_api,
+ struct pipe_screen *_screen,
+ struct pipe_texture *_texture,
+ unsigned *stride,
+ unsigned *handle)
+{
+ struct trace_screen *tr_screen = trace_screen(_screen);
+ struct trace_texture *tr_texture = trace_texture(_texture);
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct pipe_screen *screen = tr_screen->screen;
+ struct pipe_texture *texture = tr_texture->texture;
+ struct drm_api *api = tr_api->api;
+
+ /* TODO trace call */
+
+ return api->local_handle_from_texture(api, screen, texture, stride, handle);
+}
+
+static void
+trace_drm_destroy(struct drm_api *_api)
+{
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct drm_api *api = tr_api->api;
+ api->destroy(api);
+
+ free(tr_api);
+}
+
+struct drm_api *
+trace_drm_create(struct drm_api *api)
+{
+ struct trace_drm_api *tr_api;
+
+ if (!api)
+ goto error;
+
+ if (!trace_enabled())
+ goto error;
+
+ tr_api = CALLOC_STRUCT(trace_drm_api);
+
+ if (!tr_api)
+ goto error;
+
+ tr_api->base.create_screen = trace_drm_create_screen;
+ tr_api->base.create_context = trace_drm_create_context;
+ tr_api->base.texture_from_shared_handle = trace_drm_texture_from_shared_handle;
+ tr_api->base.shared_handle_from_texture = trace_drm_shared_handle_from_texture;
+ tr_api->base.local_handle_from_texture = trace_drm_local_handle_from_texture;
+ tr_api->base.destroy = trace_drm_destroy;
+ tr_api->api = api;
+
+ return &tr_api->base;
+
+error:
+ return api;
+}
diff --git a/src/gallium/drivers/trace/tr_drm.h b/src/gallium/drivers/trace/tr_drm.h
new file mode 100644
index 0000000000..845c66a32a
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_drm.h
@@ -0,0 +1,35 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TR_DRM_H
+#define TR_DRM_H
+
+struct drm_api;
+
+struct drm_api* trace_drm_create(struct drm_api *api);
+
+#endif /* ID_DRM_H */
diff --git a/src/gallium/drivers/trace/tr_dump.c b/src/gallium/drivers/trace/tr_dump.c
new file mode 100644
index 0000000000..7e2ccbcfdc
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_dump.c
@@ -0,0 +1,627 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * Trace dumping functions.
+ *
+ * For now we just use standard XML for dumping the trace calls, as this is
+ * simple to write, parse, and visually inspect, but the actual representation
+ * is abstracted out of this file, so that we can switch to a binary
+ * representation if/when it becomes justified.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#include "pipe/p_config.h"
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)
+#include <stdlib.h>
+#endif
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_thread.h"
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "util/u_string.h"
+#include "util/u_stream.h"
+
+#include "tr_dump.h"
+#include "tr_screen.h"
+#include "tr_texture.h"
+#include "tr_buffer.h"
+
+
+static struct util_stream *stream = NULL;
+static unsigned refcount = 0;
+static pipe_mutex call_mutex;
+static long unsigned call_no = 0;
+static boolean dumping = FALSE;
+static boolean initialized = FALSE;
+
+
+static INLINE void
+trace_dump_write(const char *buf, size_t size)
+{
+ if(stream)
+ util_stream_write(stream, buf, size);
+}
+
+
+static INLINE void
+trace_dump_writes(const char *s)
+{
+ trace_dump_write(s, strlen(s));
+}
+
+
+static INLINE void
+trace_dump_writef(const char *format, ...)
+{
+ static char buf[1024];
+ unsigned len;
+ va_list ap;
+ va_start(ap, format);
+ len = util_vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+ trace_dump_write(buf, len);
+}
+
+
+static INLINE void
+trace_dump_escape(const char *str)
+{
+ const unsigned char *p = (const unsigned char *)str;
+ unsigned char c;
+ while((c = *p++) != 0) {
+ if(c == '<')
+ trace_dump_writes("&lt;");
+ else if(c == '>')
+ trace_dump_writes("&gt;");
+ else if(c == '&')
+ trace_dump_writes("&amp;");
+ else if(c == '\'')
+ trace_dump_writes("&apos;");
+ else if(c == '\"')
+ trace_dump_writes("&quot;");
+ else if(c >= 0x20 && c <= 0x7e)
+ trace_dump_writef("%c", c);
+ else
+ trace_dump_writef("&#%u;", c);
+ }
+}
+
+
+static INLINE void
+trace_dump_indent(unsigned level)
+{
+ unsigned i;
+ for(i = 0; i < level; ++i)
+ trace_dump_writes("\t");
+}
+
+
+static INLINE void
+trace_dump_newline(void)
+{
+ trace_dump_writes("\n");
+}
+
+
+static INLINE void
+trace_dump_tag(const char *name)
+{
+ trace_dump_writes("<");
+ trace_dump_writes(name);
+ trace_dump_writes("/>");
+}
+
+
+static INLINE void
+trace_dump_tag_begin(const char *name)
+{
+ trace_dump_writes("<");
+ trace_dump_writes(name);
+ trace_dump_writes(">");
+}
+
+static INLINE void
+trace_dump_tag_begin1(const char *name,
+ const char *attr1, const char *value1)
+{
+ trace_dump_writes("<");
+ trace_dump_writes(name);
+ trace_dump_writes(" ");
+ trace_dump_writes(attr1);
+ trace_dump_writes("='");
+ trace_dump_escape(value1);
+ trace_dump_writes("'>");
+}
+
+
+static INLINE void
+trace_dump_tag_begin2(const char *name,
+ const char *attr1, const char *value1,
+ const char *attr2, const char *value2)
+{
+ trace_dump_writes("<");
+ trace_dump_writes(name);
+ trace_dump_writes(" ");
+ trace_dump_writes(attr1);
+ trace_dump_writes("=\'");
+ trace_dump_escape(value1);
+ trace_dump_writes("\' ");
+ trace_dump_writes(attr2);
+ trace_dump_writes("=\'");
+ trace_dump_escape(value2);
+ trace_dump_writes("\'>");
+}
+
+
+static INLINE void
+trace_dump_tag_begin3(const char *name,
+ const char *attr1, const char *value1,
+ const char *attr2, const char *value2,
+ const char *attr3, const char *value3)
+{
+ trace_dump_writes("<");
+ trace_dump_writes(name);
+ trace_dump_writes(" ");
+ trace_dump_writes(attr1);
+ trace_dump_writes("=\'");
+ trace_dump_escape(value1);
+ trace_dump_writes("\' ");
+ trace_dump_writes(attr2);
+ trace_dump_writes("=\'");
+ trace_dump_escape(value2);
+ trace_dump_writes("\' ");
+ trace_dump_writes(attr3);
+ trace_dump_writes("=\'");
+ trace_dump_escape(value3);
+ trace_dump_writes("\'>");
+}
+
+
+static INLINE void
+trace_dump_tag_end(const char *name)
+{
+ trace_dump_writes("</");
+ trace_dump_writes(name);
+ trace_dump_writes(">");
+}
+
+static void
+trace_dump_trace_close(void)
+{
+ if(stream) {
+ trace_dump_writes("</trace>\n");
+ util_stream_close(stream);
+ stream = NULL;
+ refcount = 0;
+ call_no = 0;
+ pipe_mutex_destroy(call_mutex);
+ }
+}
+
+void trace_dump_init()
+{
+ if (initialized)
+ return;
+
+ pipe_mutex_init(call_mutex);
+ dumping = FALSE;
+ initialized = TRUE;
+}
+
+boolean trace_dump_trace_begin()
+{
+ const char *filename;
+
+ assert(initialized);
+
+ filename = debug_get_option("GALLIUM_TRACE", NULL);
+ if(!filename)
+ return FALSE;
+
+ if(!stream) {
+
+ stream = util_stream_create(filename, 0);
+ if(!stream)
+ return FALSE;
+
+ trace_dump_writes("<?xml version='1.0' encoding='UTF-8'?>\n");
+ trace_dump_writes("<?xml-stylesheet type='text/xsl' href='trace.xsl'?>\n");
+ trace_dump_writes("<trace version='0.1'>\n");
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)
+ /* Linux applications rarely cleanup GL / Gallium resources so catch
+ * application exit here */
+ atexit(trace_dump_trace_close);
+#endif
+ }
+
+ ++refcount;
+
+ return TRUE;
+}
+
+boolean trace_dump_trace_enabled(void)
+{
+ return stream ? TRUE : FALSE;
+}
+
+void trace_dump_trace_end(void)
+{
+ if(stream)
+ if(!--refcount)
+ trace_dump_trace_close();
+}
+
+/*
+ * Call lock
+ */
+
+void trace_dump_call_lock(void)
+{
+ pipe_mutex_lock(call_mutex);
+}
+
+void trace_dump_call_unlock(void)
+{
+ pipe_mutex_unlock(call_mutex);
+}
+
+/*
+ * Dumping control
+ */
+
+void trace_dumping_start_locked(void)
+{
+ dumping = TRUE;
+}
+
+void trace_dumping_stop_locked(void)
+{
+ dumping = FALSE;
+}
+
+boolean trace_dumping_enabled_locked(void)
+{
+ return dumping;
+}
+
+void trace_dumping_start(void)
+{
+ pipe_mutex_lock(call_mutex);
+ trace_dumping_start_locked();
+ pipe_mutex_unlock(call_mutex);
+}
+
+void trace_dumping_stop(void)
+{
+ pipe_mutex_lock(call_mutex);
+ trace_dumping_stop_locked();
+ pipe_mutex_unlock(call_mutex);
+}
+
+boolean trace_dumping_enabled(void)
+{
+ boolean ret;
+ pipe_mutex_lock(call_mutex);
+ ret = trace_dumping_enabled_locked();
+ pipe_mutex_unlock(call_mutex);
+ return ret;
+}
+
+/*
+ * Dump functions
+ */
+
+void trace_dump_call_begin_locked(const char *klass, const char *method)
+{
+ if (!dumping)
+ return;
+
+ ++call_no;
+ trace_dump_indent(1);
+ trace_dump_writes("<call no=\'");
+ trace_dump_writef("%lu", call_no);
+ trace_dump_writes("\' class=\'");
+ trace_dump_escape(klass);
+ trace_dump_writes("\' method=\'");
+ trace_dump_escape(method);
+ trace_dump_writes("\'>");
+ trace_dump_newline();
+}
+
+void trace_dump_call_end_locked(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_indent(1);
+ trace_dump_tag_end("call");
+ trace_dump_newline();
+ util_stream_flush(stream);
+}
+
+void trace_dump_call_begin(const char *klass, const char *method)
+{
+ pipe_mutex_lock(call_mutex);
+ trace_dump_call_begin_locked(klass, method);
+}
+
+void trace_dump_call_end(void)
+{
+ trace_dump_call_end_locked();
+ pipe_mutex_unlock(call_mutex);
+}
+
+void trace_dump_arg_begin(const char *name)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_indent(2);
+ trace_dump_tag_begin1("arg", "name", name);
+}
+
+void trace_dump_arg_end(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_tag_end("arg");
+ trace_dump_newline();
+}
+
+void trace_dump_ret_begin(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_indent(2);
+ trace_dump_tag_begin("ret");
+}
+
+void trace_dump_ret_end(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_tag_end("ret");
+ trace_dump_newline();
+}
+
+void trace_dump_bool(int value)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writef("<bool>%c</bool>", value ? '1' : '0');
+}
+
+void trace_dump_int(long long int value)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writef("<int>%lli</int>", value);
+}
+
+void trace_dump_uint(long long unsigned value)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writef("<uint>%llu</uint>", value);
+}
+
+void trace_dump_float(double value)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writef("<float>%g</float>", value);
+}
+
+void trace_dump_bytes(const void *data,
+ size_t size)
+{
+ static const char hex_table[16] = "0123456789ABCDEF";
+ const uint8_t *p = data;
+ size_t i;
+
+ if (!dumping)
+ return;
+
+ trace_dump_writes("<bytes>");
+ for(i = 0; i < size; ++i) {
+ uint8_t byte = *p++;
+ char hex[2];
+ hex[0] = hex_table[byte >> 4];
+ hex[1] = hex_table[byte & 0xf];
+ trace_dump_write(hex, 2);
+ }
+ trace_dump_writes("</bytes>");
+}
+
+void trace_dump_string(const char *str)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writes("<string>");
+ trace_dump_escape(str);
+ trace_dump_writes("</string>");
+}
+
+void trace_dump_enum(const char *value)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writes("<enum>");
+ trace_dump_escape(value);
+ trace_dump_writes("</enum>");
+}
+
+void trace_dump_array_begin(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writes("<array>");
+}
+
+void trace_dump_array_end(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writes("</array>");
+}
+
+void trace_dump_elem_begin(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writes("<elem>");
+}
+
+void trace_dump_elem_end(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writes("</elem>");
+}
+
+void trace_dump_struct_begin(const char *name)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writef("<struct name='%s'>", name);
+}
+
+void trace_dump_struct_end(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writes("</struct>");
+}
+
+void trace_dump_member_begin(const char *name)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writef("<member name='%s'>", name);
+}
+
+void trace_dump_member_end(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writes("</member>");
+}
+
+void trace_dump_null(void)
+{
+ if (!dumping)
+ return;
+
+ trace_dump_writes("<null/>");
+}
+
+void trace_dump_ptr(const void *value)
+{
+ if (!dumping)
+ return;
+
+ if(value)
+ trace_dump_writef("<ptr>0x%08lx</ptr>", (unsigned long)(uintptr_t)value);
+ else
+ trace_dump_null();
+}
+
+void trace_dump_buffer_ptr(struct pipe_buffer *_buffer)
+{
+ if (!dumping)
+ return;
+
+ if (_buffer) {
+ struct trace_buffer *tr_buf = trace_buffer(_buffer);
+ trace_dump_ptr(tr_buf->buffer);
+ } else {
+ trace_dump_null();
+ }
+}
+
+void trace_dump_texture_ptr(struct pipe_texture *_texture)
+{
+ if (!dumping)
+ return;
+
+ if (_texture) {
+ struct trace_texture *tr_tex = trace_texture(_texture);
+ trace_dump_ptr(tr_tex->texture);
+ } else {
+ trace_dump_null();
+ }
+}
+
+void trace_dump_surface_ptr(struct pipe_surface *_surface)
+{
+ if (!dumping)
+ return;
+
+ if (_surface) {
+ struct trace_surface *tr_surf = trace_surface(_surface);
+ trace_dump_ptr(tr_surf->surface);
+ } else {
+ trace_dump_null();
+ }
+}
+
+void trace_dump_transfer_ptr(struct pipe_transfer *_transfer)
+{
+ if (!dumping)
+ return;
+
+ if (_transfer) {
+ struct trace_transfer *tr_tran = trace_transfer(_transfer);
+ trace_dump_ptr(tr_tran->transfer);
+ } else {
+ trace_dump_null();
+ }
+}
diff --git a/src/gallium/drivers/trace/tr_dump.h b/src/gallium/drivers/trace/tr_dump.h
new file mode 100644
index 0000000000..32592bab12
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_dump.h
@@ -0,0 +1,177 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Trace data dumping primitives.
+ */
+
+#ifndef TR_DUMP_H
+#define TR_DUMP_H
+
+
+#include "pipe/p_compiler.h"
+
+
+struct pipe_buffer;
+struct pipe_texture;
+struct pipe_surface;
+struct pipe_transfer;
+
+/*
+ * Call before use.
+ */
+void trace_dump_init(void);
+
+/*
+ * Low level dumping controls.
+ *
+ * Opening the trace file and checking if that is opened.
+ */
+boolean trace_dump_trace_begin(void);
+boolean trace_dump_trace_enabled(void);
+void trace_dump_trace_end(void);
+
+/*
+ * Lock and unlock the call mutex.
+ *
+ * It used by the none locked version of dumping control
+ * and begin/end call dump functions.
+ *
+ * Begin takes the lock while end unlocks it. Use the _locked
+ * version to avoid locking/unlocking it.
+ */
+void trace_dump_call_lock(void);
+void trace_dump_call_unlock(void);
+
+/*
+ * High level dumping control.
+ */
+void trace_dumping_start_locked(void);
+void trace_dumping_stop_locked(void);
+boolean trace_dumping_enabled_locked(void);
+void trace_dumping_start(void);
+void trace_dumping_stop(void);
+boolean trace_dumping_enabled(void);
+
+void trace_dump_call_begin_locked(const char *klass, const char *method);
+void trace_dump_call_end_locked(void);
+void trace_dump_call_begin(const char *klass, const char *method);
+void trace_dump_call_end(void);
+
+void trace_dump_arg_begin(const char *name);
+void trace_dump_arg_end(void);
+void trace_dump_ret_begin(void);
+void trace_dump_ret_end(void);
+void trace_dump_bool(int value);
+void trace_dump_int(long long int value);
+void trace_dump_uint(long long unsigned value);
+void trace_dump_float(double value);
+void trace_dump_bytes(const void *data, size_t size);
+void trace_dump_string(const char *str);
+void trace_dump_enum(const char *value);
+void trace_dump_array_begin(void);
+void trace_dump_array_end(void);
+void trace_dump_elem_begin(void);
+void trace_dump_elem_end(void);
+void trace_dump_struct_begin(const char *name);
+void trace_dump_struct_end(void);
+void trace_dump_member_begin(const char *name);
+void trace_dump_member_end(void);
+void trace_dump_null(void);
+void trace_dump_ptr(const void *value);
+/* will turn a wrapped object into the real one and dump ptr */
+void trace_dump_buffer_ptr(struct pipe_buffer *_buffer);
+void trace_dump_texture_ptr(struct pipe_texture *_texture);
+void trace_dump_surface_ptr(struct pipe_surface *_surface);
+void trace_dump_transfer_ptr(struct pipe_transfer *_transfer);
+
+/*
+ * Code saving macros.
+ */
+
+#define trace_dump_arg(_type, _arg) \
+ do { \
+ trace_dump_arg_begin(#_arg); \
+ trace_dump_##_type(_arg); \
+ trace_dump_arg_end(); \
+ } while(0)
+
+#define trace_dump_ret(_type, _arg) \
+ do { \
+ trace_dump_ret_begin(); \
+ trace_dump_##_type(_arg); \
+ trace_dump_ret_end(); \
+ } while(0)
+
+#define trace_dump_array(_type, _obj, _size) \
+ do { \
+ size_t idx; \
+ trace_dump_array_begin(); \
+ for(idx = 0; idx < (_size); ++idx) { \
+ trace_dump_elem_begin(); \
+ trace_dump_##_type((_obj)[idx]); \
+ trace_dump_elem_end(); \
+ } \
+ trace_dump_array_end(); \
+ } while(0)
+
+#define trace_dump_struct_array(_type, _obj, _size) \
+ do { \
+ size_t idx; \
+ trace_dump_array_begin(); \
+ for(idx = 0; idx < (_size); ++idx) { \
+ trace_dump_elem_begin(); \
+ trace_dump_##_type(&(_obj)[idx]); \
+ trace_dump_elem_end(); \
+ } \
+ trace_dump_array_end(); \
+ } while(0)
+
+#define trace_dump_member(_type, _obj, _member) \
+ do { \
+ trace_dump_member_begin(#_member); \
+ trace_dump_##_type((_obj)->_member); \
+ trace_dump_member_end(); \
+ } while(0)
+
+#define trace_dump_arg_array(_type, _arg, _size) \
+ do { \
+ trace_dump_arg_begin(#_arg); \
+ trace_dump_array(_type, _arg, _size); \
+ trace_dump_arg_end(); \
+ } while(0)
+
+#define trace_dump_member_array(_type, _obj, _member) \
+ do { \
+ trace_dump_member_begin(#_member); \
+ trace_dump_array(_type, (_obj)->_member, sizeof((_obj)->_member)/sizeof((_obj)->_member[0])); \
+ trace_dump_member_end(); \
+ } while(0)
+
+
+#endif /* TR_DUMP_H */
diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
new file mode 100644
index 0000000000..bcf6751af4
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -0,0 +1,549 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "tr_dump.h"
+#include "tr_dump_state.h"
+
+
+void trace_dump_format(enum pipe_format format)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ trace_dump_enum(pf_name(format) );
+}
+
+
+void trace_dump_block(const struct pipe_format_block *block)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ trace_dump_struct_begin("pipe_format_block");
+ trace_dump_member(uint, block, size);
+ trace_dump_member(uint, block, width);
+ trace_dump_member(uint, block, height);
+ trace_dump_struct_end();
+}
+
+
+static void trace_dump_reference(const struct pipe_reference *reference)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ trace_dump_struct_begin("pipe_reference");
+ trace_dump_member(int, &reference->count, count);
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_template(const struct pipe_texture *templat)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!templat) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_texture");
+
+ trace_dump_member(int, templat, target);
+ trace_dump_member(format, templat, format);
+
+ trace_dump_member_begin("width");
+ trace_dump_array(uint, templat->width, 1);
+ trace_dump_member_end();
+
+ trace_dump_member_begin("height");
+ trace_dump_array(uint, templat->height, 1);
+ trace_dump_member_end();
+
+ trace_dump_member_begin("depth");
+ trace_dump_array(uint, templat->depth, 1);
+ trace_dump_member_end();
+
+ trace_dump_member_begin("block");
+ trace_dump_block(&templat->block);
+ trace_dump_member_end();
+
+ trace_dump_member(uint, templat, last_level);
+ trace_dump_member(uint, templat, tex_usage);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_rasterizer_state");
+
+ trace_dump_member(bool, state, flatshade);
+ trace_dump_member(bool, state, light_twoside);
+ trace_dump_member(uint, state, front_winding);
+ trace_dump_member(uint, state, cull_mode);
+ trace_dump_member(uint, state, fill_cw);
+ trace_dump_member(uint, state, fill_ccw);
+ trace_dump_member(bool, state, offset_cw);
+ trace_dump_member(bool, state, offset_ccw);
+ trace_dump_member(bool, state, scissor);
+ trace_dump_member(bool, state, poly_smooth);
+ trace_dump_member(bool, state, poly_stipple_enable);
+ trace_dump_member(bool, state, point_smooth);
+ trace_dump_member(bool, state, point_sprite);
+ trace_dump_member(bool, state, point_size_per_vertex);
+ trace_dump_member(bool, state, multisample);
+ trace_dump_member(bool, state, line_smooth);
+ trace_dump_member(bool, state, line_stipple_enable);
+ trace_dump_member(uint, state, line_stipple_factor);
+ trace_dump_member(uint, state, line_stipple_pattern);
+ trace_dump_member(bool, state, line_last_pixel);
+ trace_dump_member(bool, state, bypass_vs_clip_and_viewport);
+ trace_dump_member(bool, state, flatshade_first);
+ trace_dump_member(bool, state, gl_rasterization_rules);
+
+ trace_dump_member(float, state, line_width);
+ trace_dump_member(float, state, point_size);
+ trace_dump_member(float, state, point_size_min);
+ trace_dump_member(float, state, point_size_max);
+ trace_dump_member(float, state, offset_units);
+ trace_dump_member(float, state, offset_scale);
+
+ trace_dump_member_array(uint, state, sprite_coord_mode);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_poly_stipple(const struct pipe_poly_stipple *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_poly_stipple");
+
+ trace_dump_member_begin("stipple");
+ trace_dump_array(uint,
+ state->stipple,
+ Elements(state->stipple));
+ trace_dump_member_end();
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_viewport_state(const struct pipe_viewport_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_viewport_state");
+
+ trace_dump_member_array(float, state, scale);
+ trace_dump_member_array(float, state, translate);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_scissor_state(const struct pipe_scissor_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_scissor_state");
+
+ trace_dump_member(uint, state, minx);
+ trace_dump_member(uint, state, miny);
+ trace_dump_member(uint, state, maxx);
+ trace_dump_member(uint, state, maxy);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_clip_state(const struct pipe_clip_state *state)
+{
+ unsigned i;
+
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_clip_state");
+
+ trace_dump_member_begin("ucp");
+ trace_dump_array_begin();
+ for(i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) {
+ trace_dump_elem_begin();
+ trace_dump_array(float, state->ucp[i], 4);
+ trace_dump_elem_end();
+ }
+ trace_dump_array_end();
+ trace_dump_member_end();
+
+ trace_dump_member(uint, state, nr);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_constant_buffer(const struct pipe_constant_buffer *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_constant_buffer");
+
+ trace_dump_member(buffer_ptr, state, buffer);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_shader_state(const struct pipe_shader_state *state)
+{
+ static char str[8192];
+
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ tgsi_dump_str(state->tokens, 0, str, sizeof(str));
+
+ trace_dump_struct_begin("pipe_shader_state");
+
+ trace_dump_member_begin("tokens");
+ trace_dump_string(str);
+ trace_dump_member_end();
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state)
+{
+ unsigned i;
+
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_depth_stencil_alpha_state");
+
+ trace_dump_member_begin("depth");
+ trace_dump_struct_begin("pipe_depth_state");
+ trace_dump_member(bool, &state->depth, enabled);
+ trace_dump_member(bool, &state->depth, writemask);
+ trace_dump_member(uint, &state->depth, func);
+ trace_dump_struct_end();
+ trace_dump_member_end();
+
+ trace_dump_member_begin("stencil");
+ trace_dump_array_begin();
+ for(i = 0; i < Elements(state->stencil); ++i) {
+ trace_dump_elem_begin();
+ trace_dump_struct_begin("pipe_stencil_state");
+ trace_dump_member(bool, &state->stencil[i], enabled);
+ trace_dump_member(uint, &state->stencil[i], func);
+ trace_dump_member(uint, &state->stencil[i], fail_op);
+ trace_dump_member(uint, &state->stencil[i], zpass_op);
+ trace_dump_member(uint, &state->stencil[i], zfail_op);
+ trace_dump_member(uint, &state->stencil[i], ref_value);
+ trace_dump_member(uint, &state->stencil[i], valuemask);
+ trace_dump_member(uint, &state->stencil[i], writemask);
+ trace_dump_struct_end();
+ trace_dump_elem_end();
+ }
+ trace_dump_array_end();
+ trace_dump_member_end();
+
+ trace_dump_member_begin("alpha");
+ trace_dump_struct_begin("pipe_alpha_state");
+ trace_dump_member(bool, &state->alpha, enabled);
+ trace_dump_member(uint, &state->alpha, func);
+ trace_dump_member(float, &state->alpha, ref_value);
+ trace_dump_struct_end();
+ trace_dump_member_end();
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_blend_state(const struct pipe_blend_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_blend_state");
+
+ trace_dump_member(bool, state, blend_enable);
+
+ trace_dump_member(uint, state, rgb_func);
+ trace_dump_member(uint, state, rgb_src_factor);
+ trace_dump_member(uint, state, rgb_dst_factor);
+
+ trace_dump_member(uint, state, alpha_func);
+ trace_dump_member(uint, state, alpha_src_factor);
+ trace_dump_member(uint, state, alpha_dst_factor);
+
+ trace_dump_member(bool, state, logicop_enable);
+ trace_dump_member(uint, state, logicop_func);
+
+ trace_dump_member(uint, state, colormask);
+ trace_dump_member(bool, state, dither);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_blend_color(const struct pipe_blend_color *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_blend_color");
+
+ trace_dump_member_array(float, state, color);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ trace_dump_struct_begin("pipe_framebuffer_state");
+
+ trace_dump_member(uint, state, width);
+ trace_dump_member(uint, state, height);
+ trace_dump_member(uint, state, nr_cbufs);
+ trace_dump_member_array(ptr, state, cbufs);
+ trace_dump_member(ptr, state, zsbuf);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_sampler_state(const struct pipe_sampler_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_sampler_state");
+
+ trace_dump_member(uint, state, wrap_s);
+ trace_dump_member(uint, state, wrap_t);
+ trace_dump_member(uint, state, wrap_r);
+ trace_dump_member(uint, state, min_img_filter);
+ trace_dump_member(uint, state, min_mip_filter);
+ trace_dump_member(uint, state, mag_img_filter);
+ trace_dump_member(bool, state, compare_mode);
+ trace_dump_member(uint, state, compare_func);
+ trace_dump_member(bool, state, normalized_coords);
+ trace_dump_member(uint, state, prefilter);
+ trace_dump_member(float, state, lod_bias);
+ trace_dump_member(float, state, min_lod);
+ trace_dump_member(float, state, max_lod);
+ trace_dump_member_array(float, state, border_color);
+ trace_dump_member(float, state, max_anisotropy);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_surface(const struct pipe_surface *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_surface");
+
+ trace_dump_reference(&state->reference);
+
+ trace_dump_member(format, state, format);
+ trace_dump_member(uint, state, width);
+ trace_dump_member(uint, state, height);
+
+ trace_dump_member(uint, state, layout);
+ trace_dump_member(uint, state, offset);
+ trace_dump_member(uint, state, usage);
+
+ trace_dump_member(ptr, state, texture);
+ trace_dump_member(uint, state, face);
+ trace_dump_member(uint, state, level);
+ trace_dump_member(uint, state, zslice);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_transfer(const struct pipe_transfer *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_transfer");
+
+ trace_dump_member(format, state, format);
+ trace_dump_member(uint, state, width);
+ trace_dump_member(uint, state, height);
+
+ trace_dump_member_begin("block");
+ trace_dump_block(&state->block);
+ trace_dump_member_end();
+
+ trace_dump_member(uint, state, nblocksx);
+ trace_dump_member(uint, state, nblocksy);
+ trace_dump_member(uint, state, stride);
+ trace_dump_member(uint, state, usage);
+
+ trace_dump_member(ptr, state, texture);
+ trace_dump_member(uint, state, face);
+ trace_dump_member(uint, state, level);
+ trace_dump_member(uint, state, zslice);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ 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(buffer_ptr, state, buffer);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_vertex_element(const struct pipe_vertex_element *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_vertex_element");
+
+ trace_dump_member(uint, state, src_offset);
+
+ trace_dump_member(uint, state, vertex_buffer_index);
+ trace_dump_member(uint, state, nr_components);
+
+ trace_dump_member(format, state, src_format);
+
+ trace_dump_struct_end();
+}
diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h
new file mode 100644
index 0000000000..05b821adb6
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_dump_state.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TR_DUMP_STATE_H_
+#define TR_DUMP_STATE_H_
+
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+
+
+void trace_dump_format(enum pipe_format format);
+
+void trace_dump_block(const struct pipe_format_block *block);
+
+void trace_dump_template(const struct pipe_texture *templat);
+
+
+void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state);
+
+void trace_dump_poly_stipple(const struct pipe_poly_stipple *state);
+
+void trace_dump_viewport_state(const struct pipe_viewport_state *state);
+
+void trace_dump_scissor_state(const struct pipe_scissor_state *state);
+
+void trace_dump_clip_state(const struct pipe_clip_state *state);
+
+void trace_dump_constant_buffer(const struct pipe_constant_buffer *state);
+
+void trace_dump_token(const struct tgsi_token *token);
+
+void trace_dump_shader_state(const struct pipe_shader_state *state);
+
+void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state);
+
+void trace_dump_blend_state(const struct pipe_blend_state *state);
+
+void trace_dump_blend_color(const struct pipe_blend_color *state);
+
+void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state);
+
+void trace_dump_sampler_state(const struct pipe_sampler_state *state);
+
+void trace_dump_surface(const struct pipe_surface *state);
+
+void trace_dump_transfer(const struct pipe_transfer *state);
+
+void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state);
+
+void trace_dump_vertex_element(const struct pipe_vertex_element *state);
+
+
+#endif /* TR_STATE_H */
diff --git a/src/gallium/drivers/trace/tr_rbug.c b/src/gallium/drivers/trace/tr_rbug.c
new file mode 100644
index 0000000000..e85ac15edc
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_rbug.c
@@ -0,0 +1,864 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_string.h"
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+#include "util/u_network.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "tr_dump.h"
+#include "tr_state.h"
+#include "tr_buffer.h"
+#include "tr_texture.h"
+
+#include "rbug/rbug.h"
+
+#include <errno.h>
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+# define sleep Sleep
+#elif defined(PIPE_OS_LINUX)
+void usleep(int);
+# define sleep usleep
+#else
+# warning "No socket implementation"
+#endif
+
+#define U642VOID(x) ((void *)(unsigned long)(x))
+#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
+
+struct trace_rbug
+{
+ struct trace_screen *tr_scr;
+ struct rbug_connection *con;
+ pipe_thread thread;
+ boolean running;
+};
+
+PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug);
+
+
+/**********************************************************
+ * Helper functions
+ */
+
+
+static struct trace_context *
+trace_rbug_get_context_locked(struct trace_screen *tr_scr, rbug_context_t ctx)
+{
+ struct trace_context *tr_ctx = NULL;
+ struct tr_list *ptr;
+
+ foreach(ptr, &tr_scr->contexts) {
+ tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list));
+ if (ctx == VOID2U64(tr_ctx))
+ break;
+ tr_ctx = NULL;
+ }
+
+ return tr_ctx;
+}
+
+static struct trace_shader *
+trace_rbug_get_shader_locked(struct trace_context *tr_ctx, rbug_shader_t shdr)
+{
+ struct trace_shader *tr_shdr = NULL;
+ struct tr_list *ptr;
+
+ foreach(ptr, &tr_ctx->shaders) {
+ tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list));
+ if (shdr == VOID2U64(tr_shdr))
+ break;
+ tr_shdr = NULL;
+ }
+
+ return tr_shdr;
+}
+
+static void *
+trace_shader_create_locked(struct pipe_context *pipe,
+ struct trace_shader *tr_shdr,
+ struct tgsi_token *tokens)
+{
+ void *state = NULL;
+ struct pipe_shader_state pss = { 0 };
+ pss.tokens = tokens;
+
+ if (tr_shdr->type == TRACE_SHADER_FRAGMENT) {
+ state = pipe->create_fs_state(pipe, &pss);
+ } else if (tr_shdr->type == TRACE_SHADER_VERTEX) {
+ state = pipe->create_vs_state(pipe, &pss);
+ } else
+ assert(0);
+
+ return state;
+}
+
+static void
+trace_shader_bind_locked(struct pipe_context *pipe,
+ struct trace_shader *tr_shdr,
+ void *state)
+{
+ if (tr_shdr->type == TRACE_SHADER_FRAGMENT) {
+ pipe->bind_fs_state(pipe, state);
+ } else if (tr_shdr->type == TRACE_SHADER_VERTEX) {
+ pipe->bind_vs_state(pipe, state);
+ } else
+ assert(0);
+}
+
+static void
+trace_shader_delete_locked(struct pipe_context *pipe,
+ struct trace_shader *tr_shdr,
+ void *state)
+{
+ if (tr_shdr->type == TRACE_SHADER_FRAGMENT) {
+ pipe->delete_fs_state(pipe, state);
+ } else if (tr_shdr->type == TRACE_SHADER_VERTEX) {
+ pipe->delete_vs_state(pipe, state);
+ } else
+ assert(0);
+}
+
+/************************************************
+ * Request handler functions
+ */
+
+
+static int
+trace_rbug_texture_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_texture *tr_tex = NULL;
+ struct tr_list *ptr;
+ rbug_texture_t *texs;
+ int i = 0;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ texs = MALLOC(tr_scr->num_textures * sizeof(rbug_texture_t));
+ foreach(ptr, &tr_scr->textures) {
+ tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list));
+ texs[i++] = VOID2U64(tr_tex);
+ }
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL);
+ FREE(texs);
+
+ return 0;
+}
+
+static int
+trace_rbug_texture_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_texture *tr_tex;
+ struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header;
+ struct tr_list *ptr;
+ struct pipe_texture *t;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ foreach(ptr, &tr_scr->textures) {
+ tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list));
+ if (gpti->texture == VOID2U64(tr_tex))
+ break;
+ tr_tex = NULL;
+ }
+
+ if (!tr_tex) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ t = tr_tex->texture;
+ rbug_send_texture_info_reply(tr_rbug->con, serial,
+ t->target, t->format,
+ t->width, t->last_level + 1,
+ t->height, t->last_level + 1,
+ t->depth, t->last_level + 1,
+ t->block.width, t->block.height, t->block.size,
+ t->last_level,
+ t->nr_samples,
+ t->tex_usage,
+ NULL);
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_texture *tr_tex;
+ struct tr_list *ptr;
+
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_texture *tex;
+ struct pipe_transfer *t;
+
+ void *map;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ foreach(ptr, &tr_scr->textures) {
+ tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list));
+ if (gptr->texture == VOID2U64(tr_tex))
+ break;
+ tr_tex = NULL;
+ }
+
+ if (!tr_tex) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ tex = tr_tex->texture;
+ t = screen->get_tex_transfer(tr_scr->screen, tex,
+ gptr->face, gptr->level, gptr->zslice,
+ PIPE_TRANSFER_READ,
+ gptr->x, gptr->y, gptr->w, gptr->h);
+
+ map = screen->transfer_map(screen, t);
+
+ rbug_send_texture_read_reply(tr_rbug->con, serial,
+ t->format,
+ t->block.width, t->block.height, t->block.size,
+ (uint8_t*)map, t->stride * t->nblocksy,
+ t->stride,
+ NULL);
+
+ screen->transfer_unmap(screen, t);
+ screen->tex_transfer_destroy(t);
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct tr_list *ptr;
+ struct trace_context *tr_ctx = NULL;
+ rbug_context_t *ctxs;
+ int i = 0;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ ctxs = MALLOC(tr_scr->num_contexts * sizeof(rbug_context_t));
+ foreach(ptr, &tr_scr->contexts) {
+ tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list));
+ ctxs[i++] = VOID2U64(tr_ctx);
+ }
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL);
+ FREE(ctxs);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+ rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS];
+ rbug_texture_t texs[PIPE_MAX_SAMPLERS];
+ int i;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, info->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ /* protect the pipe context */
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ trace_dump_call_lock();
+
+ for (i = 0; i < tr_ctx->curr.nr_cbufs; i++)
+ cbufs[i] = VOID2U64(tr_ctx->curr.cbufs[i]);
+
+ for (i = 0; i < tr_ctx->curr.num_texs; i++)
+ texs[i] = VOID2U64(tr_ctx->curr.tex[i]);
+
+ rbug_send_context_info_reply(tr_rbug->con, serial,
+ VOID2U64(tr_ctx->curr.vs), VOID2U64(tr_ctx->curr.fs),
+ texs, tr_ctx->curr.num_texs,
+ cbufs, tr_ctx->curr.nr_cbufs,
+ VOID2U64(tr_ctx->curr.zsbuf),
+ tr_ctx->draw_blocker, tr_ctx->draw_blocked, NULL);
+
+ trace_dump_call_unlock();
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_draw_block(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, block->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ tr_ctx->draw_blocker |= block->block;
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_draw_step(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, step->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) {
+ if (step->step & RBUG_BLOCK_RULE)
+ tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK;
+ } else {
+ tr_ctx->draw_blocked &= ~step->step;
+ }
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+#ifdef PIPE_THREAD_HAVE_CONDVAR
+ pipe_condvar_broadcast(tr_ctx->draw_cond);
+#endif
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_draw_unblock(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, unblock->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) {
+ if (unblock->unblock & RBUG_BLOCK_RULE)
+ tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK;
+ } else {
+ tr_ctx->draw_blocked &= ~unblock->unblock;
+ }
+ tr_ctx->draw_blocker &= ~unblock->unblock;
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+#ifdef PIPE_THREAD_HAVE_CONDVAR
+ pipe_condvar_broadcast(tr_ctx->draw_cond);
+#endif
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_draw_rule(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, rule->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ tr_ctx->draw_rule.vs = U642VOID(rule->vertex);
+ tr_ctx->draw_rule.fs = U642VOID(rule->fragment);
+ tr_ctx->draw_rule.tex = U642VOID(rule->texture);
+ tr_ctx->draw_rule.surf = U642VOID(rule->surface);
+ tr_ctx->draw_rule.blocker = rule->block;
+ tr_ctx->draw_blocker |= RBUG_BLOCK_RULE;
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+#ifdef PIPE_THREAD_HAVE_CONDVAR
+ pipe_condvar_broadcast(tr_ctx->draw_cond);
+#endif
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_flush(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_flush *flush = (struct rbug_proto_context_flush *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, flush->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ /* protect the pipe context */
+ trace_dump_call_lock();
+
+ tr_ctx->pipe->flush(tr_ctx->pipe, flush->flags, NULL);
+
+ trace_dump_call_unlock();
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_shader_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_shader_list *list = (struct rbug_proto_shader_list *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+ struct trace_shader *tr_shdr = NULL;
+ struct tr_list *ptr;
+ rbug_shader_t *shdrs;
+ int i = 0;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, list->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->list_mutex);
+ shdrs = MALLOC(tr_ctx->num_shaders * sizeof(rbug_shader_t));
+ foreach(ptr, &tr_ctx->shaders) {
+ tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list));
+ shdrs[i++] = VOID2U64(tr_shdr);
+ }
+
+ pipe_mutex_unlock(tr_ctx->list_mutex);
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ rbug_send_shader_list_reply(tr_rbug->con, serial, shdrs, i, NULL);
+ FREE(shdrs);
+
+ return 0;
+}
+
+static int
+trace_rbug_shader_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_shader_info *info = (struct rbug_proto_shader_info *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+ struct trace_shader *tr_shdr = NULL;
+ unsigned original_len;
+ unsigned replaced_len;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, info->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->list_mutex);
+
+ tr_shdr = trace_rbug_get_shader_locked(tr_ctx, info->shader);
+
+ if (!tr_shdr) {
+ pipe_mutex_unlock(tr_ctx->list_mutex);
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ /* just in case */
+ assert(sizeof(struct tgsi_token) == 4);
+
+ original_len = tgsi_num_tokens(tr_shdr->tokens);
+ if (tr_shdr->replaced_tokens)
+ replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens);
+ else
+ replaced_len = 0;
+
+ rbug_send_shader_info_reply(tr_rbug->con, serial,
+ (uint32_t*)tr_shdr->tokens, original_len,
+ (uint32_t*)tr_shdr->replaced_tokens, replaced_len,
+ tr_shdr->disabled,
+ NULL);
+
+ pipe_mutex_unlock(tr_ctx->list_mutex);
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_shader_disable(struct trace_rbug *tr_rbug, struct rbug_header *header)
+{
+ struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+ struct trace_shader *tr_shdr = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, dis->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->list_mutex);
+
+ tr_shdr = trace_rbug_get_shader_locked(tr_ctx, dis->shader);
+
+ if (!tr_shdr) {
+ pipe_mutex_unlock(tr_ctx->list_mutex);
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ tr_shdr->disabled = dis->disable;
+
+ pipe_mutex_unlock(tr_ctx->list_mutex);
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_shader_replace(struct trace_rbug *tr_rbug, struct rbug_header *header)
+{
+ struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+ struct trace_shader *tr_shdr = NULL;
+ struct pipe_context *pipe = NULL;
+ void *state;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, rep->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->list_mutex);
+
+ tr_shdr = trace_rbug_get_shader_locked(tr_ctx, rep->shader);
+
+ if (!tr_shdr) {
+ pipe_mutex_unlock(tr_ctx->list_mutex);
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ /* protect the pipe context */
+ trace_dump_call_lock();
+
+ pipe = tr_ctx->pipe;
+
+ /* remove old replaced shader */
+ if (tr_shdr->replaced) {
+ if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr)
+ trace_shader_bind_locked(pipe, tr_shdr, tr_shdr->state);
+
+ FREE(tr_shdr->replaced_tokens);
+ trace_shader_delete_locked(pipe, tr_shdr, tr_shdr->replaced);
+ tr_shdr->replaced = NULL;
+ tr_shdr->replaced_tokens = NULL;
+ }
+
+ /* empty inputs means restore old which we did above */
+ if (rep->tokens_len == 0)
+ goto out;
+
+ tr_shdr->replaced_tokens = tgsi_dup_tokens((struct tgsi_token *)rep->tokens);
+ if (!tr_shdr->replaced_tokens)
+ goto err;
+
+ state = trace_shader_create_locked(pipe, tr_shdr, tr_shdr->replaced_tokens);
+ if (!state)
+ goto err;
+
+ /* bind new shader if the shader is currently a bound */
+ if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr)
+ trace_shader_bind_locked(pipe, tr_shdr, state);
+
+ /* save state */
+ tr_shdr->replaced = state;
+
+out:
+ trace_dump_call_unlock();
+ pipe_mutex_unlock(tr_ctx->list_mutex);
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+
+err:
+ FREE(tr_shdr->replaced_tokens);
+ tr_shdr->replaced = NULL;
+ tr_shdr->replaced_tokens = NULL;
+
+ trace_dump_call_unlock();
+ pipe_mutex_unlock(tr_ctx->list_mutex);
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -EINVAL;
+}
+
+static boolean
+trace_rbug_header(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ int ret = 0;
+
+ switch(header->opcode) {
+ case RBUG_OP_PING:
+ rbug_send_ping_reply(tr_rbug->con, serial, NULL);
+ break;
+ case RBUG_OP_TEXTURE_LIST:
+ ret = trace_rbug_texture_list(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_TEXTURE_INFO:
+ ret = trace_rbug_texture_info(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_TEXTURE_READ:
+ ret = trace_rbug_texture_read(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_LIST:
+ ret = trace_rbug_context_list(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_INFO:
+ ret = trace_rbug_context_info(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_DRAW_BLOCK:
+ ret = trace_rbug_context_draw_block(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_DRAW_STEP:
+ ret = trace_rbug_context_draw_step(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_DRAW_UNBLOCK:
+ ret = trace_rbug_context_draw_unblock(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_DRAW_RULE:
+ ret = trace_rbug_context_draw_rule(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_FLUSH:
+ ret = trace_rbug_context_flush(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_SHADER_LIST:
+ ret = trace_rbug_shader_list(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_SHADER_INFO:
+ ret = trace_rbug_shader_info(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_SHADER_DISABLE:
+ ret = trace_rbug_shader_disable(tr_rbug, header);
+ break;
+ case RBUG_OP_SHADER_REPLACE:
+ ret = trace_rbug_shader_replace(tr_rbug, header);
+ break;
+ default:
+ debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode);
+ ret = -ENOSYS;
+ break;
+ }
+ rbug_free_header(header);
+
+ if (ret)
+ rbug_send_error_reply(tr_rbug->con, serial, ret, NULL);
+
+ return TRUE;
+}
+
+static void
+trace_rbug_con(struct trace_rbug *tr_rbug)
+{
+ struct rbug_header *header;
+ uint32_t serial;
+
+ debug_printf("%s - connection received\n", __FUNCTION__);
+
+ while(tr_rbug->running) {
+ header = rbug_get_message(tr_rbug->con, &serial);
+ if (!header)
+ break;
+
+ if (!trace_rbug_header(tr_rbug, header, serial))
+ break;
+ }
+
+ debug_printf("%s - connection closed\n", __FUNCTION__);
+
+ rbug_disconnect(tr_rbug->con);
+ tr_rbug->con = NULL;
+}
+
+PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug)
+{
+ struct trace_rbug *tr_rbug = void_tr_rbug;
+ uint16_t port = 13370;
+ int s = -1;
+ int c;
+
+ u_socket_init();
+
+ for (;port <= 13379 && s < 0; port++)
+ s = u_socket_listen_on_port(port);
+
+ if (s < 0) {
+ debug_printf("trace_rbug - failed to listen\n");
+ return NULL;
+ }
+
+ u_socket_block(s, false);
+
+ debug_printf("trace_rbug - remote debugging listening on port %u\n", --port);
+
+ while(tr_rbug->running) {
+ sleep(1);
+
+ c = u_socket_accept(s);
+ if (c < 0)
+ continue;
+
+ u_socket_block(c, true);
+ tr_rbug->con = rbug_from_socket(c);
+
+ trace_rbug_con(tr_rbug);
+
+ u_socket_close(c);
+ }
+
+ u_socket_close(s);
+
+ u_socket_stop();
+
+ return NULL;
+}
+
+/**********************************************************
+ *
+ */
+
+struct trace_rbug *
+trace_rbug_start(struct trace_screen *tr_scr)
+{
+ struct trace_rbug *tr_rbug = CALLOC_STRUCT(trace_rbug);
+ if (!tr_rbug)
+ return NULL;
+
+ tr_rbug->tr_scr = tr_scr;
+ tr_rbug->running = TRUE;
+ tr_rbug->thread = pipe_thread_create(trace_rbug_thread, tr_rbug);
+
+ return tr_rbug;
+}
+
+void
+trace_rbug_stop(struct trace_rbug *tr_rbug)
+{
+ if (!tr_rbug)
+ return;
+
+ tr_rbug->running = false;
+ pipe_thread_wait(tr_rbug->thread);
+
+ FREE(tr_rbug);
+
+ return;
+}
+
+void
+trace_rbug_notify_draw_blocked(struct trace_context *tr_ctx)
+{
+ struct trace_screen *tr_scr = trace_screen(tr_ctx->base.screen);
+ struct trace_rbug *tr_rbug = tr_scr->rbug;
+
+ if (tr_rbug && tr_rbug->con)
+ rbug_send_context_draw_blocked(tr_rbug->con,
+ VOID2U64(tr_ctx), tr_ctx->draw_blocked, NULL);
+}
diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c
new file mode 100644
index 0000000000..26f1c04594
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_screen.c
@@ -0,0 +1,958 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+
+#include "tr_buffer.h"
+#include "tr_dump.h"
+#include "tr_dump_state.h"
+#include "tr_texture.h"
+#include "tr_screen.h"
+
+#include "pipe/p_inlines.h"
+
+
+static boolean trace = FALSE;
+static boolean rbug = FALSE;
+
+static const char *
+trace_screen_get_name(struct pipe_screen *_screen)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ const char *result;
+
+ trace_dump_call_begin("pipe_screen", "get_name");
+
+ trace_dump_arg(ptr, screen);
+
+ result = screen->get_name(screen);
+
+ trace_dump_ret(string, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static const char *
+trace_screen_get_vendor(struct pipe_screen *_screen)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ const char *result;
+
+ trace_dump_call_begin("pipe_screen", "get_vendor");
+
+ trace_dump_arg(ptr, screen);
+
+ result = screen->get_vendor(screen);
+
+ trace_dump_ret(string, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static int
+trace_screen_get_param(struct pipe_screen *_screen,
+ int param)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ int result;
+
+ trace_dump_call_begin("pipe_screen", "get_param");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(int, param);
+
+ result = screen->get_param(screen, param);
+
+ trace_dump_ret(int, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static float
+trace_screen_get_paramf(struct pipe_screen *_screen,
+ int param)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ float result;
+
+ trace_dump_call_begin("pipe_screen", "get_paramf");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(int, param);
+
+ result = screen->get_paramf(screen, param);
+
+ trace_dump_ret(float, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static boolean
+trace_screen_is_format_supported(struct pipe_screen *_screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ boolean result;
+
+ trace_dump_call_begin("pipe_screen", "is_format_supported");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(format, format);
+ trace_dump_arg(int, target);
+ trace_dump_arg(uint, tex_usage);
+ trace_dump_arg(uint, geom_flags);
+
+ result = screen->is_format_supported(screen, format, target, tex_usage, geom_flags);
+
+ trace_dump_ret(bool, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static void
+trace_screen_flush_frontbuffer(struct pipe_screen *_screen,
+ struct pipe_surface *_surface,
+ void *context_private)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_surface *tr_surf = trace_surface(_surface);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_surface *surface = tr_surf->surface;
+
+ trace_dump_call_begin("pipe_screen", "flush_frontbuffer");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, surface);
+ /* XXX: hide, as there is nothing we can do with this
+ trace_dump_arg(ptr, context_private);
+ */
+
+ screen->flush_frontbuffer(screen, surface, context_private);
+
+ trace_dump_call_end();
+}
+
+
+/********************************************************************
+ * texture
+ */
+
+
+static struct pipe_texture *
+trace_screen_texture_create(struct pipe_screen *_screen,
+ const struct pipe_texture *templat)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_texture *result;
+
+ trace_dump_call_begin("pipe_screen", "texture_create");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(template, templat);
+
+ result = screen->texture_create(screen, templat);
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ result = trace_texture_create(tr_scr, result);
+
+ return result;
+}
+
+
+static struct pipe_texture *
+trace_screen_texture_blanket(struct pipe_screen *_screen,
+ const struct pipe_texture *templat,
+ const unsigned *ppitch,
+ struct pipe_buffer *_buffer)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_buffer *tr_buf = trace_buffer(_buffer);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_buffer *buffer = tr_buf->buffer;
+ unsigned pitch = *ppitch;
+ struct pipe_texture *result;
+
+ trace_dump_call_begin("pipe_screen", "texture_blanket");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(template, templat);
+ trace_dump_arg(uint, pitch);
+ trace_dump_arg(ptr, buffer);
+
+ result = screen->texture_blanket(screen, templat, ppitch, buffer);
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ result = trace_texture_create(tr_scr, result);
+
+ return result;
+}
+
+
+static void
+trace_screen_texture_destroy(struct pipe_texture *_texture)
+{
+ struct trace_screen *tr_scr = trace_screen(_texture->screen);
+ struct trace_texture *tr_tex = trace_texture(_texture);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_texture *texture = tr_tex->texture;
+
+ assert(texture->screen == screen);
+
+ trace_dump_call_begin("pipe_screen", "texture_destroy");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, texture);
+
+ trace_dump_call_end();
+
+ trace_texture_destroy(tr_tex);
+}
+
+
+/********************************************************************
+ * surface
+ */
+
+
+static struct pipe_surface *
+trace_screen_get_tex_surface(struct pipe_screen *_screen,
+ struct pipe_texture *_texture,
+ unsigned face, unsigned level,
+ unsigned zslice,
+ unsigned usage)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_texture *tr_tex = trace_texture(_texture);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_texture *texture = tr_tex->texture;
+ struct pipe_surface *result = NULL;
+
+ assert(texture->screen == screen);
+
+ trace_dump_call_begin("pipe_screen", "get_tex_surface");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, texture);
+ trace_dump_arg(uint, face);
+ trace_dump_arg(uint, level);
+ trace_dump_arg(uint, zslice);
+ trace_dump_arg(uint, usage);
+
+ result = screen->get_tex_surface(screen, texture, face, level, zslice, usage);
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ result = trace_surface_create(tr_tex, result);
+
+ return result;
+}
+
+
+static void
+trace_screen_tex_surface_destroy(struct pipe_surface *_surface)
+{
+ struct trace_screen *tr_scr = trace_screen(_surface->texture->screen);
+ struct trace_surface *tr_surf = trace_surface(_surface);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_surface *surface = tr_surf->surface;
+
+ trace_dump_call_begin("pipe_screen", "tex_surface_destroy");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, surface);
+
+ trace_dump_call_end();
+
+ trace_surface_destroy(tr_surf);
+}
+
+
+/********************************************************************
+ * transfer
+ */
+
+
+static struct pipe_transfer *
+trace_screen_get_tex_transfer(struct pipe_screen *_screen,
+ struct pipe_texture *_texture,
+ unsigned face, unsigned level,
+ unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_texture *tr_tex = trace_texture(_texture);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_texture *texture = tr_tex->texture;
+ struct pipe_transfer *result = NULL;
+
+ assert(texture->screen == screen);
+
+ trace_dump_call_begin("pipe_screen", "get_tex_transfer");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, texture);
+ trace_dump_arg(uint, face);
+ trace_dump_arg(uint, level);
+ trace_dump_arg(uint, zslice);
+ trace_dump_arg(uint, usage);
+
+ trace_dump_arg(uint, x);
+ trace_dump_arg(uint, y);
+ trace_dump_arg(uint, w);
+ trace_dump_arg(uint, h);
+
+ result = screen->get_tex_transfer(screen, texture, face, level, zslice, usage,
+ x, y, w, h);
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ result = trace_transfer_create(tr_tex, result);
+
+ return result;
+}
+
+
+static void
+trace_screen_tex_transfer_destroy(struct pipe_transfer *_transfer)
+{
+ struct trace_screen *tr_scr = trace_screen(_transfer->texture->screen);
+ struct trace_transfer *tr_trans = trace_transfer(_transfer);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_transfer *transfer = tr_trans->transfer;
+
+ trace_dump_call_begin("pipe_screen", "tex_transfer_destroy");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, transfer);
+
+ trace_dump_call_end();
+
+ trace_transfer_destroy(tr_trans);
+}
+
+
+static void *
+trace_screen_transfer_map(struct pipe_screen *_screen,
+ struct pipe_transfer *_transfer)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_transfer *tr_trans = trace_transfer(_transfer);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_transfer *transfer = tr_trans->transfer;
+ void *map;
+
+ map = screen->transfer_map(screen, transfer);
+ if(map) {
+ if(transfer->usage != PIPE_TRANSFER_READ) {
+ assert(!tr_trans->map);
+ tr_trans->map = map;
+ }
+ }
+
+ return map;
+}
+
+
+static void
+trace_screen_transfer_unmap(struct pipe_screen *_screen,
+ struct pipe_transfer *_transfer)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_transfer *tr_trans = trace_transfer(_transfer);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_transfer *transfer = tr_trans->transfer;
+
+ if(tr_trans->map) {
+ size_t size = transfer->nblocksy * transfer->stride;
+
+ trace_dump_call_begin("pipe_screen", "transfer_write");
+
+ trace_dump_arg(ptr, screen);
+
+ trace_dump_arg(ptr, transfer);
+
+ trace_dump_arg_begin("stride");
+ trace_dump_uint(transfer->stride);
+ trace_dump_arg_end();
+
+ trace_dump_arg_begin("data");
+ trace_dump_bytes(tr_trans->map, size);
+ trace_dump_arg_end();
+
+ trace_dump_arg_begin("size");
+ trace_dump_uint(size);
+ trace_dump_arg_end();
+
+ trace_dump_call_end();
+
+ tr_trans->map = NULL;
+ }
+
+ screen->transfer_unmap(screen, transfer);
+}
+
+
+/********************************************************************
+ * buffer
+ */
+
+
+static struct pipe_buffer *
+trace_screen_surface_buffer_create(struct pipe_screen *_screen,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *pstride)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ unsigned stride;
+ struct pipe_buffer *result;
+
+ trace_dump_call_begin("pipe_screen", "surface_buffer_create");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(uint, width);
+ trace_dump_arg(uint, height);
+ trace_dump_arg(format, format);
+ trace_dump_arg(uint, usage);
+ trace_dump_arg(uint, tex_usage);
+
+ result = screen->surface_buffer_create(screen,
+ width, height,
+ format,
+ usage,
+ tex_usage,
+ pstride);
+
+ stride = *pstride;
+
+ trace_dump_arg(uint, stride);
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ return trace_buffer_create(tr_scr, result);
+}
+
+
+static struct pipe_buffer *
+trace_screen_buffer_create(struct pipe_screen *_screen,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_buffer *result;
+
+ trace_dump_call_begin("pipe_screen", "buffer_create");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(uint, alignment);
+ trace_dump_arg(uint, usage);
+ trace_dump_arg(uint, size);
+
+ result = screen->buffer_create(screen, alignment, usage, size);
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ /* Zero the buffer to avoid dumping uninitialized memory */
+ if(result->usage & PIPE_BUFFER_USAGE_CPU_WRITE) {
+ void *map;
+ map = pipe_buffer_map(screen, result, PIPE_BUFFER_USAGE_CPU_WRITE);
+ if(map) {
+ memset(map, 0, result->size);
+ screen->buffer_unmap(screen, result);
+ }
+ }
+
+ return trace_buffer_create(tr_scr, result);
+}
+
+
+static struct pipe_buffer *
+trace_screen_user_buffer_create(struct pipe_screen *_screen,
+ void *data,
+ unsigned size)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_buffer *result;
+
+ trace_dump_call_begin("pipe_screen", "user_buffer_create");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg_begin("data");
+ trace_dump_bytes(data, size);
+ trace_dump_arg_end();
+ trace_dump_arg(uint, size);
+
+ result = screen->user_buffer_create(screen, data, size);
+
+ trace_dump_ret(ptr, result);
+
+ trace_dump_call_end();
+
+ if(result) {
+ assert(!(result->usage & TRACE_BUFFER_USAGE_USER));
+ result->usage |= TRACE_BUFFER_USAGE_USER;
+ }
+
+ return trace_buffer_create(tr_scr, result);
+}
+
+
+/**
+ * This function is used to track if data has been changed on a user buffer
+ * without map/unmap being called.
+ */
+void
+trace_screen_user_buffer_update(struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer)
+{
+#if 0
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ const void *map;
+
+ if(buffer && buffer->usage & TRACE_BUFFER_USAGE_USER) {
+ map = screen->buffer_map(screen, buffer, PIPE_BUFFER_USAGE_CPU_READ);
+ if(map) {
+ trace_dump_call_begin("pipe_winsys", "buffer_write");
+
+ trace_dump_arg(ptr, screen);
+
+ trace_dump_arg(ptr, buffer);
+
+ trace_dump_arg_begin("data");
+ trace_dump_bytes(map, buffer->size);
+ trace_dump_arg_end();
+
+ trace_dump_arg_begin("size");
+ trace_dump_uint(buffer->size);
+ trace_dump_arg_end();
+
+ trace_dump_call_end();
+
+ screen->buffer_unmap(screen, buffer);
+ }
+ }
+#endif
+}
+
+
+static void *
+trace_screen_buffer_map(struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer,
+ unsigned usage)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_buffer *tr_buf = trace_buffer(_buffer);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_buffer *buffer = tr_buf->buffer;
+ void *map;
+
+ assert(screen->buffer_map);
+ map = screen->buffer_map(screen, buffer, usage);
+ if(map) {
+ if(usage & PIPE_BUFFER_USAGE_CPU_WRITE) {
+ tr_buf->map = map;
+ }
+ }
+
+ return map;
+}
+
+
+static void *
+trace_screen_buffer_map_range(struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer,
+ unsigned offset,
+ unsigned length,
+ unsigned usage)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_buffer *tr_buf = trace_buffer(_buffer);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_buffer *buffer = tr_buf->buffer;
+ void *map;
+
+ assert(screen->buffer_map_range);
+ map = screen->buffer_map_range(screen, buffer, offset, length, usage);
+ if(map) {
+ if(usage & PIPE_BUFFER_USAGE_CPU_WRITE) {
+ tr_buf->map = map;
+ }
+ }
+
+ return map;
+}
+
+
+static void
+buffer_write(struct pipe_screen *screen,
+ struct pipe_buffer *buffer,
+ unsigned offset,
+ const char *map,
+ unsigned size)
+{
+ assert(map);
+
+ trace_dump_call_begin("pipe_screen", "buffer_write");
+
+ trace_dump_arg(ptr, screen);
+
+ trace_dump_arg(ptr, buffer);
+
+ trace_dump_arg(uint, offset);
+
+ trace_dump_arg_begin("data");
+ trace_dump_bytes(map + offset, size);
+ trace_dump_arg_end();
+
+ trace_dump_arg(uint, size);
+
+ trace_dump_call_end();
+
+}
+
+
+static void
+trace_screen_buffer_flush_mapped_range(struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer,
+ unsigned offset,
+ unsigned length)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_buffer *tr_buf = trace_buffer(_buffer);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_buffer *buffer = tr_buf->buffer;
+
+ assert(tr_buf->map);
+ buffer_write(screen, buffer, offset, tr_buf->map, length);
+ tr_buf->range_flushed = TRUE;
+ screen->buffer_flush_mapped_range(screen, buffer, offset, length);
+}
+
+
+static void
+trace_screen_buffer_unmap(struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_buffer *tr_buf = trace_buffer(_buffer);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_buffer *buffer = tr_buf->buffer;
+
+ if (tr_buf->map && !tr_buf->range_flushed)
+ buffer_write(screen, buffer, 0, tr_buf->map, buffer->size);
+ tr_buf->map = NULL;
+ tr_buf->range_flushed = FALSE;
+ screen->buffer_unmap(screen, buffer);
+}
+
+
+static void
+trace_screen_buffer_destroy(struct pipe_buffer *_buffer)
+{
+ struct trace_screen *tr_scr = trace_screen(_buffer->screen);
+ struct trace_buffer *tr_buf = trace_buffer(_buffer);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_buffer *buffer = tr_buf->buffer;
+
+ trace_dump_call_begin("pipe_screen", "buffer_destroy");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, buffer);
+
+ trace_dump_call_end();
+
+ trace_buffer_destroy(tr_scr, _buffer);
+}
+
+
+/********************************************************************
+ * fence
+ */
+
+
+static void
+trace_screen_fence_reference(struct pipe_screen *_screen,
+ struct pipe_fence_handle **pdst,
+ struct pipe_fence_handle *src)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_fence_handle *dst;
+
+ assert(pdst);
+ dst = *pdst;
+
+ trace_dump_call_begin("pipe_screen", "fence_reference");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, dst);
+ trace_dump_arg(ptr, src);
+
+ screen->fence_reference(screen, pdst, src);
+
+ trace_dump_call_end();
+}
+
+
+static int
+trace_screen_fence_signalled(struct pipe_screen *_screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ int result;
+
+ trace_dump_call_begin("pipe_screen", "fence_signalled");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, fence);
+ trace_dump_arg(uint, flags);
+
+ result = screen->fence_signalled(screen, fence, flags);
+
+ trace_dump_ret(int, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+static int
+trace_screen_fence_finish(struct pipe_screen *_screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+ int result;
+
+ trace_dump_call_begin("pipe_screen", "fence_finish");
+
+ trace_dump_arg(ptr, screen);
+ trace_dump_arg(ptr, fence);
+ trace_dump_arg(uint, flags);
+
+ result = screen->fence_finish(screen, fence, flags);
+
+ trace_dump_ret(int, result);
+
+ trace_dump_call_end();
+
+ return result;
+}
+
+
+/********************************************************************
+ * screen
+ */
+
+static void
+trace_screen_destroy(struct pipe_screen *_screen)
+{
+ struct trace_screen *tr_scr = trace_screen(_screen);
+ struct pipe_screen *screen = tr_scr->screen;
+
+ trace_dump_call_begin("pipe_screen", "destroy");
+ trace_dump_arg(ptr, screen);
+ trace_dump_call_end();
+ trace_dump_trace_end();
+
+ if (tr_scr->rbug)
+ trace_rbug_stop(tr_scr->rbug);
+
+ screen->destroy(screen);
+
+ FREE(tr_scr);
+}
+
+boolean
+trace_enabled(void)
+{
+ static boolean firstrun = TRUE;
+
+ if (!firstrun)
+ return trace;
+ firstrun = FALSE;
+
+ trace_dump_init();
+
+ if(trace_dump_trace_begin()) {
+ trace_dumping_start();
+ trace = TRUE;
+ }
+
+ if (debug_get_bool_option("GALLIUM_RBUG", FALSE)) {
+ trace = TRUE;
+ rbug = TRUE;
+ }
+
+ return trace;
+}
+
+struct pipe_screen *
+trace_screen_create(struct pipe_screen *screen)
+{
+ struct trace_screen *tr_scr;
+ struct pipe_winsys *winsys;
+
+ if(!screen)
+ goto error1;
+
+ if (!trace_enabled())
+ goto error1;
+
+ trace_dump_call_begin("", "pipe_screen_create");
+
+ tr_scr = CALLOC_STRUCT(trace_screen);
+ if(!tr_scr)
+ goto error2;
+
+#if 0
+ winsys = trace_winsys_create(screen->winsys);
+ if(!winsys)
+ goto error3;
+#else
+ winsys = screen->winsys;
+#endif
+ pipe_mutex_init(tr_scr->list_mutex);
+ make_empty_list(&tr_scr->buffers);
+ make_empty_list(&tr_scr->contexts);
+ make_empty_list(&tr_scr->textures);
+ make_empty_list(&tr_scr->surfaces);
+ make_empty_list(&tr_scr->transfers);
+
+ tr_scr->base.winsys = winsys;
+ tr_scr->base.destroy = trace_screen_destroy;
+ tr_scr->base.get_name = trace_screen_get_name;
+ tr_scr->base.get_vendor = trace_screen_get_vendor;
+ tr_scr->base.get_param = trace_screen_get_param;
+ tr_scr->base.get_paramf = trace_screen_get_paramf;
+ tr_scr->base.is_format_supported = trace_screen_is_format_supported;
+ tr_scr->base.texture_create = trace_screen_texture_create;
+ tr_scr->base.texture_blanket = trace_screen_texture_blanket;
+ tr_scr->base.texture_destroy = trace_screen_texture_destroy;
+ tr_scr->base.get_tex_surface = trace_screen_get_tex_surface;
+ tr_scr->base.tex_surface_destroy = trace_screen_tex_surface_destroy;
+ tr_scr->base.get_tex_transfer = trace_screen_get_tex_transfer;
+ tr_scr->base.tex_transfer_destroy = trace_screen_tex_transfer_destroy;
+ tr_scr->base.transfer_map = trace_screen_transfer_map;
+ tr_scr->base.transfer_unmap = trace_screen_transfer_unmap;
+ tr_scr->base.buffer_create = trace_screen_buffer_create;
+ tr_scr->base.user_buffer_create = trace_screen_user_buffer_create;
+ tr_scr->base.surface_buffer_create = trace_screen_surface_buffer_create;
+ if (screen->buffer_map)
+ tr_scr->base.buffer_map = trace_screen_buffer_map;
+ if (screen->buffer_map_range)
+ tr_scr->base.buffer_map_range = trace_screen_buffer_map_range;
+ if (screen->buffer_flush_mapped_range)
+ tr_scr->base.buffer_flush_mapped_range = trace_screen_buffer_flush_mapped_range;
+ if (screen->buffer_unmap)
+ tr_scr->base.buffer_unmap = trace_screen_buffer_unmap;
+ tr_scr->base.buffer_destroy = trace_screen_buffer_destroy;
+ tr_scr->base.fence_reference = trace_screen_fence_reference;
+ tr_scr->base.fence_signalled = trace_screen_fence_signalled;
+ tr_scr->base.fence_finish = trace_screen_fence_finish;
+ tr_scr->base.flush_frontbuffer = trace_screen_flush_frontbuffer;
+ tr_scr->screen = screen;
+
+ trace_dump_ret(ptr, screen);
+ trace_dump_call_end();
+
+ if (rbug)
+ tr_scr->rbug = trace_rbug_start(tr_scr);
+
+ return &tr_scr->base;
+
+#if 0
+error3:
+ FREE(tr_scr);
+#endif
+error2:
+ trace_dump_ret(ptr, screen);
+ trace_dump_call_end();
+ trace_dump_trace_end();
+error1:
+ return screen;
+}
+
+
+struct trace_screen *
+trace_screen(struct pipe_screen *screen)
+{
+ assert(screen);
+ assert(screen->destroy == trace_screen_destroy);
+ return (struct trace_screen *)screen;
+}
diff --git a/src/gallium/drivers/trace/tr_screen.h b/src/gallium/drivers/trace/tr_screen.h
new file mode 100644
index 0000000000..dba8cd7c65
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_screen.h
@@ -0,0 +1,130 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TR_SCREEN_H_
+#define TR_SCREEN_H_
+
+
+#include "pipe/p_screen.h"
+#include "pipe/p_thread.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct tr_list {
+ struct tr_list *next;
+ struct tr_list *prev;
+};
+
+/**
+ * It often happens that new data is written directly to the user buffers
+ * without mapping/unmapping. This flag marks user buffers, so that their
+ * contents can be dumpped before being used by the pipe context.
+ */
+#define TRACE_BUFFER_USAGE_USER (1 << 31)
+
+
+struct trace_screen
+{
+ struct pipe_screen base;
+
+ struct pipe_screen *screen;
+
+ /* remote debugger */
+ struct trace_rbug *rbug;
+
+ pipe_mutex list_mutex;
+ int num_buffers;
+ int num_contexts;
+ int num_textures;
+ int num_surfaces;
+ int num_transfers;
+ struct tr_list buffers;
+ struct tr_list contexts;
+ struct tr_list textures;
+ struct tr_list surfaces;
+ struct tr_list transfers;
+};
+
+
+/*
+ * tr_rbug.c
+ */
+
+
+struct trace_rbug;
+
+struct trace_rbug *
+trace_rbug_start(struct trace_screen *tr_scr);
+
+void
+trace_rbug_stop(struct trace_rbug *tr_rbug);
+
+
+/*
+ * tr_screen.c
+ */
+
+
+boolean
+trace_enabled(void);
+
+struct trace_screen *
+trace_screen(struct pipe_screen *screen);
+
+struct pipe_screen *
+trace_screen_create(struct pipe_screen *screen);
+
+void
+trace_screen_user_buffer_update(struct pipe_screen *screen,
+ struct pipe_buffer *buffer);
+
+#define trace_screen_add_to_list(tr_scr, name, obj) \
+ do { \
+ pipe_mutex_lock(tr_scr->list_mutex); \
+ insert_at_head(&tr_scr->name, &obj->list); \
+ tr_scr->num_##name++; \
+ pipe_mutex_unlock(tr_scr->list_mutex); \
+ } while (0)
+
+#define trace_screen_remove_from_list(tr_scr, name, obj) \
+ do { \
+ pipe_mutex_lock(tr_scr->list_mutex); \
+ remove_from_list(&obj->list); \
+ tr_scr->num_##name--; \
+ pipe_mutex_unlock(tr_scr->list_mutex); \
+ } while (0)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TR_SCREEN_H_ */
diff --git a/src/gallium/drivers/trace/tr_state.c b/src/gallium/drivers/trace/tr_state.c
new file mode 100644
index 0000000000..d8c11640bf
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_state.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE 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 "tr_state.h"
+
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+
+#include "tgsi/tgsi_parse.h"
+
+struct trace_shader * trace_shader_create(struct trace_context *tr_ctx,
+ const struct pipe_shader_state *state,
+ void *result,
+ enum trace_shader_type type)
+{
+ struct trace_shader *tr_shdr = CALLOC_STRUCT(trace_shader);
+
+ tr_shdr->state = result;
+ tr_shdr->type = type;
+ tr_shdr->tokens = tgsi_dup_tokens(state->tokens);
+
+ /* works on context as well */
+ trace_screen_add_to_list(tr_ctx, shaders, tr_shdr);
+
+ return tr_shdr;
+}
+
+void trace_shader_destroy(struct trace_context *tr_ctx,
+ struct trace_shader *tr_shdr)
+{
+ trace_screen_remove_from_list(tr_ctx, shaders, tr_shdr);
+
+ if (tr_shdr->replaced) {
+ if (tr_shdr->type == TRACE_SHADER_FRAGMENT)
+ tr_ctx->pipe->delete_fs_state(tr_ctx->pipe, tr_shdr->replaced);
+ else if (tr_shdr->type == TRACE_SHADER_VERTEX)
+ tr_ctx->pipe->delete_vs_state(tr_ctx->pipe, tr_shdr->replaced);
+ else
+ assert(0);
+ }
+
+ FREE(tr_shdr->replaced_tokens);
+ FREE(tr_shdr->tokens);
+ FREE(tr_shdr);
+}
diff --git a/src/gallium/drivers/trace/tr_state.h b/src/gallium/drivers/trace/tr_state.h
new file mode 100644
index 0000000000..1c16042ee5
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_state.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef TR_STATE_H_
+#define TR_STATE_H_
+
+#include "tr_context.h"
+
+struct tgsi_token;
+
+enum trace_shader_type {
+ TRACE_SHADER_FRAGMENT = 0,
+ TRACE_SHADER_VERTEX = 1,
+ TRACE_SHADER_GEOMETRY = 2,
+};
+
+struct trace_shader
+{
+ struct tr_list list;
+
+ enum trace_shader_type type;
+
+ void *state;
+ void *replaced;
+
+ struct tgsi_token *tokens;
+ struct tgsi_token *replaced_tokens;
+
+ boolean disabled;
+};
+
+
+static INLINE struct trace_shader *
+trace_shader(void *state)
+{
+ return (struct trace_shader *)state;
+}
+
+struct trace_shader * trace_shader_create(struct trace_context *tr_ctx,
+ const struct pipe_shader_state *state,
+ void *result,
+ enum trace_shader_type type);
+
+void trace_shader_destroy(struct trace_context *tr_ctx,
+ struct trace_shader *tr_shdr);
+
+#endif
diff --git a/src/gallium/drivers/trace/tr_texture.c b/src/gallium/drivers/trace/tr_texture.c
new file mode 100644
index 0000000000..1f25fe38d4
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_texture.c
@@ -0,0 +1,170 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_hash_table.h"
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+
+#include "tr_screen.h"
+#include "tr_texture.h"
+
+
+struct pipe_texture *
+trace_texture_create(struct trace_screen *tr_scr,
+ struct pipe_texture *texture)
+{
+ struct trace_texture *tr_tex;
+
+ if(!texture)
+ goto error;
+
+ assert(texture->screen == tr_scr->screen);
+
+ tr_tex = CALLOC_STRUCT(trace_texture);
+ if(!tr_tex)
+ goto error;
+
+ memcpy(&tr_tex->base, texture, sizeof(struct pipe_texture));
+
+ pipe_reference_init(&tr_tex->base.reference, 1);
+ tr_tex->base.screen = &tr_scr->base;
+ tr_tex->texture = texture;
+
+ trace_screen_add_to_list(tr_scr, textures, tr_tex);
+
+ return &tr_tex->base;
+
+error:
+ pipe_texture_reference(&texture, NULL);
+ return NULL;
+}
+
+
+void
+trace_texture_destroy(struct trace_texture *tr_tex)
+{
+ struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen);
+
+ trace_screen_remove_from_list(tr_scr, textures, tr_tex);
+
+ pipe_texture_reference(&tr_tex->texture, NULL);
+ FREE(tr_tex);
+}
+
+
+struct pipe_surface *
+trace_surface_create(struct trace_texture *tr_tex,
+ struct pipe_surface *surface)
+{
+ struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen);
+ struct trace_surface *tr_surf;
+
+ if(!surface)
+ goto error;
+
+ assert(surface->texture == tr_tex->texture);
+
+ tr_surf = CALLOC_STRUCT(trace_surface);
+ if(!tr_surf)
+ goto error;
+
+ memcpy(&tr_surf->base, surface, sizeof(struct pipe_surface));
+
+ pipe_reference_init(&tr_surf->base.reference, 1);
+ tr_surf->base.texture = NULL;
+ pipe_texture_reference(&tr_surf->base.texture, &tr_tex->base);
+ tr_surf->surface = surface;
+
+ trace_screen_add_to_list(tr_scr, surfaces, tr_surf);
+
+ return &tr_surf->base;
+
+error:
+ pipe_surface_reference(&surface, NULL);
+ return NULL;
+}
+
+
+void
+trace_surface_destroy(struct trace_surface *tr_surf)
+{
+ struct trace_screen *tr_scr = trace_screen(tr_surf->base.texture->screen);
+
+ trace_screen_remove_from_list(tr_scr, surfaces, tr_surf);
+
+ pipe_texture_reference(&tr_surf->base.texture, NULL);
+ pipe_surface_reference(&tr_surf->surface, NULL);
+ FREE(tr_surf);
+}
+
+
+struct pipe_transfer *
+trace_transfer_create(struct trace_texture *tr_tex,
+ struct pipe_transfer *transfer)
+{
+ struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen);
+ struct trace_transfer *tr_trans;
+
+ if(!transfer)
+ goto error;
+
+ assert(transfer->texture == tr_tex->texture);
+
+ tr_trans = CALLOC_STRUCT(trace_transfer);
+ if(!tr_trans)
+ goto error;
+
+ memcpy(&tr_trans->base, transfer, sizeof(struct pipe_transfer));
+
+ tr_trans->base.texture = NULL;
+ pipe_texture_reference(&tr_trans->base.texture, &tr_tex->base);
+ tr_trans->transfer = transfer;
+ assert(tr_trans->base.texture == &tr_tex->base);
+
+ trace_screen_add_to_list(tr_scr, transfers, tr_trans);
+
+ return &tr_trans->base;
+
+error:
+ transfer->texture->screen->tex_transfer_destroy(transfer);
+ return NULL;
+}
+
+
+void
+trace_transfer_destroy(struct trace_transfer *tr_trans)
+{
+ struct trace_screen *tr_scr = trace_screen(tr_trans->base.texture->screen);
+ struct pipe_screen *screen = tr_trans->transfer->texture->screen;
+
+ trace_screen_remove_from_list(tr_scr, transfers, tr_trans);
+
+ pipe_texture_reference(&tr_trans->base.texture, NULL);
+ screen->tex_transfer_destroy(tr_trans->transfer);
+ FREE(tr_trans);
+}
+
diff --git a/src/gallium/drivers/trace/tr_texture.h b/src/gallium/drivers/trace/tr_texture.h
new file mode 100644
index 0000000000..395e523e73
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_texture.h
@@ -0,0 +1,122 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TR_TEXTURE_H_
+#define TR_TEXTURE_H_
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+
+#include "tr_screen.h"
+
+
+struct trace_texture
+{
+ struct pipe_texture base;
+
+ struct pipe_texture *texture;
+
+ struct tr_list list;
+};
+
+
+struct trace_surface
+{
+ struct pipe_surface base;
+
+ struct pipe_surface *surface;
+
+ struct tr_list list;
+};
+
+
+struct trace_transfer
+{
+ struct pipe_transfer base;
+
+ struct pipe_transfer *transfer;
+
+ struct tr_list list;
+
+ void *map;
+};
+
+
+static INLINE struct trace_texture *
+trace_texture(struct pipe_texture *texture)
+{
+ if(!texture)
+ return NULL;
+ (void)trace_screen(texture->screen);
+ return (struct trace_texture *)texture;
+}
+
+
+static INLINE struct trace_surface *
+trace_surface(struct pipe_surface *surface)
+{
+ if(!surface)
+ return NULL;
+ (void)trace_texture(surface->texture);
+ return (struct trace_surface *)surface;
+}
+
+
+static INLINE struct trace_transfer *
+trace_transfer(struct pipe_transfer *transfer)
+{
+ if(!transfer)
+ return NULL;
+ (void)trace_texture(transfer->texture);
+ return (struct trace_transfer *)transfer;
+}
+
+
+struct pipe_texture *
+trace_texture_create(struct trace_screen *tr_scr,
+ struct pipe_texture *texture);
+
+void
+trace_texture_destroy(struct trace_texture *tr_tex);
+
+struct pipe_surface *
+trace_surface_create(struct trace_texture *tr_tex,
+ struct pipe_surface *surface);
+
+void
+trace_surface_destroy(struct trace_surface *tr_surf);
+
+struct pipe_transfer *
+trace_transfer_create(struct trace_texture *tr_tex,
+ struct pipe_transfer *transfer);
+
+void
+trace_transfer_destroy(struct trace_transfer *tr_trans);
+
+
+#endif /* TR_TEXTURE_H_ */
diff --git a/src/gallium/drivers/trace/trace.xsl b/src/gallium/drivers/trace/trace.xsl
new file mode 100644
index 0000000000..7be95e0e75
--- /dev/null
+++ b/src/gallium/drivers/trace/trace.xsl
@@ -0,0 +1,188 @@
+<?xml version="1.0"?>
+
+<!--
+
+Copyright 2008 Tungsten Graphics, Inc.
+
+This program 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 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+!-->
+
+<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <xsl:output method="html" />
+
+ <xsl:strip-space elements="*" />
+
+ <xsl:template match="/trace">
+ <html>
+ <head>
+ <title>Gallium Trace</title>
+ </head>
+ <style>
+ body {
+ font-family: verdana, sans-serif;
+ font-size: 11px;
+ font-weight: normal;
+ text-align : left;
+ }
+
+ .fun {
+ font-weight: bold;
+ }
+
+ .var {
+ font-style: italic;
+ }
+
+ .typ {
+ display: none;
+ }
+
+ .lit {
+ color: #0000ff;
+ }
+
+ .ptr {
+ color: #008000;
+ }
+ </style>
+ <body>
+ <ol class="calls">
+ <xsl:apply-templates/>
+ </ol>
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template match="call">
+ <li>
+ <xsl:attribute name="value">
+ <xsl:apply-templates select="@no"/>
+ </xsl:attribute>
+ <span class="fun">
+ <xsl:value-of select="@class"/>
+ <xsl:text>::</xsl:text>
+ <xsl:value-of select="@method"/>
+ </span>
+ <xsl:text>(</xsl:text>
+ <xsl:apply-templates select="arg"/>
+ <xsl:text>)</xsl:text>
+ <xsl:apply-templates select="ret"/>
+ </li>
+ </xsl:template>
+
+ <xsl:template match="arg|member">
+ <xsl:apply-templates select="@name"/>
+ <xsl:text> = </xsl:text>
+ <xsl:apply-templates />
+ <xsl:if test="position() != last()">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="ret">
+ <xsl:text> = </xsl:text>
+ <xsl:apply-templates />
+ </xsl:template>
+
+ <xsl:template match="bool|int|uint|float|enum">
+ <span class="lit">
+ <xsl:value-of select="text()"/>
+ </span>
+ </xsl:template>
+
+ <xsl:template match="bytes">
+ <span class="lit">
+ <xsl:text>...</xsl:text>
+ </span>
+ </xsl:template>
+
+ <xsl:template match="string">
+ <span class="lit">
+ <xsl:text>"</xsl:text>
+ <xsl:call-template name="break">
+ <xsl:with-param name="text" select="text()"/>
+ </xsl:call-template>
+ <xsl:text>"</xsl:text>
+ </span>
+ </xsl:template>
+
+ <xsl:template match="array|struct">
+ <xsl:text>{</xsl:text>
+ <xsl:apply-templates />
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="elem">
+ <xsl:apply-templates />
+ <xsl:if test="position() != last()">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="null">
+ <span class="ptr">
+ <xsl:text>NULL</xsl:text>
+ </span>
+ </xsl:template>
+
+ <xsl:template match="ptr">
+ <span class="ptr">
+ <xsl:value-of select="text()"/>
+ </span>
+ </xsl:template>
+
+ <xsl:template match="@name">
+ <span class="var">
+ <xsl:value-of select="."/>
+ </span>
+ </xsl:template>
+
+ <xsl:template name="break">
+ <xsl:param name="text" select="."/>
+ <xsl:choose>
+ <xsl:when test="contains($text, '&#xa;')">
+ <xsl:value-of select="substring-before($text, '&#xa;')"/>
+ <br/>
+ <xsl:call-template name="break">
+ <xsl:with-param name="text" select="substring-after($text, '&#xa;')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="replace">
+ <xsl:param name="text"/>
+ <xsl:param name="from"/>
+ <xsl:param name="to"/>
+ <xsl:choose>
+ <xsl:when test="contains($text,$from)">
+ <xsl:value-of select="concat(substring-before($text,$from),$to)"/>
+ <xsl:call-template name="replace">
+ <xsl:with-param name="text" select="substring-after($text,$from)"/>
+ <xsl:with-param name="from" select="$from"/>
+ <xsl:with-param name="to" select="$to"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$text"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:transform>
diff --git a/src/gallium/include/pipe/internal/p_winsys_screen.h b/src/gallium/include/pipe/internal/p_winsys_screen.h
new file mode 100644
index 0000000000..a1542dada7
--- /dev/null
+++ b/src/gallium/include/pipe/internal/p_winsys_screen.h
@@ -0,0 +1,190 @@
+ /**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * This is the interface that Gallium3D requires any window system
+ * hosting it to implement. This is the only include file in Gallium3D
+ * which is public.
+ */
+
+#ifndef P_WINSYS_H
+#define P_WINSYS_H
+
+
+#include "pipe/p_format.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** Opaque type */
+struct pipe_fence_handle;
+
+struct pipe_surface;
+
+
+/**
+ * Gallium3D drivers are (meant to be!) independent of both GL and the
+ * window system. The window system provides a buffer manager and a
+ * set of additional hooks for things like command buffer submission,
+ * etc.
+ *
+ * There clearly has to be some agreement between the window system
+ * driver and the hardware driver about the format of command buffers,
+ * etc.
+ */
+struct pipe_winsys
+{
+ void (*destroy)( struct pipe_winsys *ws );
+
+ /** Returns name of this winsys interface */
+ const char *(*get_name)( struct pipe_winsys *ws );
+
+ /**
+ * Do any special operations to ensure buffer size is correct
+ */
+ void (*update_buffer)( struct pipe_winsys *ws,
+ void *context_private );
+ /**
+ * Do any special operations to ensure frontbuffer contents are
+ * displayed, eg copy fake frontbuffer.
+ */
+ void (*flush_frontbuffer)( struct pipe_winsys *ws,
+ struct pipe_surface *surf,
+ void *context_private );
+
+
+ /**
+ * Buffer management. Buffer attributes are mostly fixed over its lifetime.
+ *
+ * Remember that gallium gets to choose the interface it needs, and the
+ * window systems must then implement that interface (rather than the
+ * other way around...).
+ *
+ * usage is a bitmask of PIPE_BUFFER_USAGE_PIXEL/VERTEX/INDEX/CONSTANT. This
+ * usage argument is only an optimization hint, not a guarantee, therefore
+ * proper behavior must be observed in all circumstances.
+ *
+ * alignment indicates the client's alignment requirements, eg for
+ * SSE instructions.
+ */
+ struct pipe_buffer *(*buffer_create)( struct pipe_winsys *ws,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size );
+
+ /**
+ * Create a buffer that wraps user-space data.
+ *
+ * Effectively this schedules a delayed call to buffer_create
+ * followed by an upload of the data at *some point in the future*,
+ * or perhaps never. Basically the allocate/upload is delayed
+ * until the buffer is actually passed to hardware.
+ *
+ * The intention is to provide a quick way to turn regular data
+ * into a buffer, and secondly to avoid a copy operation if that
+ * data subsequently turns out to be only accessed by the CPU.
+ *
+ * Common example is OpenGL vertex buffers that are subsequently
+ * processed either by software TNL in the driver or by passing to
+ * hardware.
+ *
+ * XXX: What happens if the delayed call to buffer_create() fails?
+ *
+ * Note that ptr may be accessed at any time upto the time when the
+ * buffer is destroyed, so the data must not be freed before then.
+ */
+ struct pipe_buffer *(*user_buffer_create)(struct pipe_winsys *ws,
+ void *ptr,
+ unsigned bytes);
+
+ /**
+ * Allocate storage for a display target surface.
+ *
+ * Often surfaces which are meant to be blitted to the front screen (i.e.,
+ * display targets) must be allocated with special characteristics, memory
+ * pools, or obtained directly from the windowing system.
+ *
+ * This callback is invoked by the pipe_screenwhen creating a texture marked
+ * with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET flag to get the underlying
+ * buffer storage.
+ */
+ struct pipe_buffer *(*surface_buffer_create)(struct pipe_winsys *ws,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride);
+
+
+ /**
+ * Map the entire data store of a buffer object into the client's address.
+ * flags is bitmask of PIPE_BUFFER_USAGE_CPU_READ/WRITE flags.
+ */
+ void *(*buffer_map)( struct pipe_winsys *ws,
+ struct pipe_buffer *buf,
+ unsigned usage );
+
+ void (*buffer_unmap)( struct pipe_winsys *ws,
+ struct pipe_buffer *buf );
+
+ void (*buffer_destroy)( struct pipe_buffer *buf );
+
+
+ /** Set ptr = fence, with reference counting */
+ void (*fence_reference)( struct pipe_winsys *ws,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence );
+
+ /**
+ * Checks whether the fence has been signalled.
+ * \param flags driver-specific meaning
+ * \return zero on success.
+ */
+ int (*fence_signalled)( struct pipe_winsys *ws,
+ struct pipe_fence_handle *fence,
+ unsigned flag );
+
+ /**
+ * Wait for the fence to finish.
+ * \param flags driver-specific meaning
+ * \return zero on success.
+ */
+ int (*fence_finish)( struct pipe_winsys *ws,
+ struct pipe_fence_handle *fence,
+ unsigned flag );
+
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* P_WINSYS_H */
diff --git a/src/gallium/include/pipe/p_atomic.h b/src/gallium/include/pipe/p_atomic.h
new file mode 100644
index 0000000000..0c3fbae428
--- /dev/null
+++ b/src/gallium/include/pipe/p_atomic.h
@@ -0,0 +1,353 @@
+/**
+ * Many similar implementations exist. See for example libwsbm
+ * or the linux kernel include/atomic.h
+ *
+ * No copyright claimed on this file.
+ *
+ */
+
+#ifndef P_ATOMIC_H
+#define P_ATOMIC_H
+
+#include "p_compiler.h"
+#include "p_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Favor OS-provided implementations.
+ *
+ * Where no OS-provided implementation is available, fall back to
+ * locally coded assembly, compiler intrinsic or ultimately a
+ * mutex-based implementation.
+ */
+#if (defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || \
+ defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT))
+#define PIPE_ATOMIC_OS_UNLOCKED
+#elif (defined(PIPE_CC_MSVC) && defined(PIPE_SUBSYSTEM_WINDOWS_USER))
+#define PIPE_ATOMIC_OS_MS_INTERLOCK
+#elif (defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86))
+#define PIPE_ATOMIC_ASM_MSVC_X86
+#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86))
+#define PIPE_ATOMIC_ASM_GCC_X86
+#elif defined(PIPE_CC_GCC)
+#define PIPE_ATOMIC_GCC_INTRINSIC
+#else
+#define PIPE_ATOMIC_MUTEX
+#endif
+
+
+
+#if defined(PIPE_ATOMIC_ASM_GCC_X86)
+
+#define PIPE_ATOMIC "GCC x86 assembly"
+
+struct pipe_atomic {
+ int32_t count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__("lock; decl %0; sete %1":"+m"(v->count), "=qm"(c)
+ ::"memory");
+
+ return c != 0;
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ __asm__ __volatile__("lock; incl %0":"+m"(v->count));
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ __asm__ __volatile__("lock; decl %0":"+m"(v->count));
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ return __sync_val_compare_and_swap(&v->count, old, _new);
+}
+#endif
+
+
+
+/* Implementation using GCC-provided synchronization intrinsics
+ */
+#if defined(PIPE_ATOMIC_GCC_INTRINSIC)
+
+#define PIPE_ATOMIC "GCC Sync Intrinsics"
+
+struct pipe_atomic {
+ int32_t count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ return (__sync_sub_and_fetch(&v->count, 1) == 0);
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ (void) __sync_add_and_fetch(&v->count, 1);
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ (void) __sync_sub_and_fetch(&v->count, 1);
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ return __sync_val_compare_and_swap(&v->count, old, _new);
+}
+#endif
+
+
+
+/* Unlocked version for single threaded environments, such as some
+ * windows kernel modules.
+ */
+#if defined(PIPE_ATOMIC_OS_UNLOCKED)
+
+#define PIPE_ATOMIC "Unlocked"
+
+struct pipe_atomic
+{
+ int32_t count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+#define p_atomic_dec_zero(_v) ((boolean) --(_v)->count)
+#define p_atomic_inc(_v) ((void) (_v)->count++)
+#define p_atomic_dec(_v) ((void) (_v)->count--)
+#define p_atomic_cmpxchg(_v, old, _new) ((_v)->count == old ? (_v)->count = (_new) : (_v)->count)
+
+#endif
+
+
+/* Locally coded assembly for MSVC on x86:
+ */
+#if defined(PIPE_ATOMIC_ASM_MSVC_X86)
+
+#define PIPE_ATOMIC "MSVC x86 assembly"
+
+struct pipe_atomic
+{
+ int32_t count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ int32_t *pcount = &v->count;
+ unsigned char c;
+
+ __asm {
+ mov eax, [pcount]
+ lock dec dword ptr [eax]
+ sete byte ptr [c]
+ }
+
+ return c != 0;
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ int32_t *pcount = &v->count;
+
+ __asm {
+ mov eax, [pcount]
+ lock inc dword ptr [eax]
+ }
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ int32_t *pcount = &v->count;
+
+ __asm {
+ mov eax, [pcount]
+ lock dec dword ptr [eax]
+ }
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ int32_t *pcount = &v->count;
+ int32_t orig;
+
+ __asm {
+ mov ecx, [pcount]
+ mov eax, [old]
+ mov edx, [_new]
+ lock cmpxchg [ecx], edx
+ mov [orig], eax
+ }
+
+ return orig;
+}
+#endif
+
+
+#if defined(PIPE_ATOMIC_OS_MS_INTERLOCK)
+
+#define PIPE_ATOMIC "MS userspace interlocks"
+
+#include <windows.h>
+
+struct pipe_atomic
+{
+ volatile long count;
+};
+
+#define p_atomic_set(_v, _i) ((_v)->count = (_i))
+#define p_atomic_read(_v) ((_v)->count)
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ return InterlockedDecrement(&v->count) == 0;
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ InterlockedIncrement(&v->count);
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ InterlockedDecrement(&v->count);
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ return InterlockedCompareExchange(&v->count, _new, old);
+}
+
+#endif
+
+
+
+#if defined(PIPE_ATOMIC_MUTEX)
+
+#define PIPE_ATOMIC "mutex-based fallback"
+
+#include "pipe/p_thread.h"
+
+/**
+ * This implementation should really not be used.
+ * Add an assembly port instead. It may abort and
+ * doesn't destroy used mutexes.
+ */
+
+struct pipe_atomic {
+ pipe_mutex mutex;
+ int32_t count;
+};
+
+static INLINE void
+p_atomic_set(struct pipe_atomic *v, int32_t i)
+{
+ pipe_mutex_init(v->mutex);
+ pipe_mutex_lock(v->mutex);
+ v->count = i;
+ pipe_mutex_unlock(v->mutex);
+}
+
+static INLINE int32_t
+p_atomic_read(struct pipe_atomic *v)
+{
+ int32_t ret;
+
+ pipe_mutex_lock(v->mutex);
+ ret = v->count;
+ pipe_mutex_unlock(v->mutex);
+ return ret;
+}
+
+static INLINE void
+p_atomic_inc(struct pipe_atomic *v)
+{
+ pipe_mutex_lock(v->mutex);
+ ++v->count;
+ pipe_mutex_unlock(v->mutex);
+}
+
+static INLINE void
+p_atomic_dec(struct pipe_atomic *v)
+{
+ pipe_mutex_lock(v->mutex);
+ --v->count;
+ pipe_mutex_unlock(v->mutex);
+}
+
+static INLINE boolean
+p_atomic_dec_zero(struct pipe_atomic *v)
+{
+ boolean ret;
+
+ pipe_mutex_lock(v->mutex);
+ ret = (--v->count == 0);
+ pipe_mutex_unlock(v->mutex);
+ return ret;
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
+{
+ int32_t ret;
+
+ pipe_mutex_lock(v->mutex);
+ ret = v->count;
+ if (ret == old)
+ v->count = _new;
+ pipe_mutex_unlock(v->mutex);
+
+ return ret;
+}
+
+#endif
+
+
+#ifndef PIPE_ATOMIC
+#error "No pipe_atomic implementation selected"
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* P_ATOMIC_H */
diff --git a/src/gallium/include/pipe/p_compiler.h b/src/gallium/include/pipe/p_compiler.h
new file mode 100644
index 0000000000..c13cffceb0
--- /dev/null
+++ b/src/gallium/include/pipe/p_compiler.h
@@ -0,0 +1,179 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef P_COMPILER_H
+#define P_COMPILER_H
+
+
+#include "p_config.h"
+
+#ifndef XFree86Server
+#include <stdlib.h>
+#include <string.h>
+#else
+#include "xf86_ansic.h"
+#include "xf86_libc.h"
+#endif
+
+
+#if defined(_WIN32) && !defined(__WIN32__)
+#define __WIN32__
+#endif
+
+#if defined(_MSC_VER)
+
+/* Avoid 'expression is always true' warning */
+#pragma warning(disable: 4296)
+
+#endif /* _MSC_VER */
+
+
+#if defined(_MSC_VER)
+
+typedef __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+#ifndef __eglplatform_h_
+typedef __int32 int32_t;
+#endif
+typedef unsigned __int32 uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+#if defined(_WIN64)
+typedef __int64 intptr_t;
+typedef unsigned __int64 uintptr_t;
+#else
+typedef __int32 intptr_t;
+typedef unsigned __int32 uintptr_t;
+#endif
+
+#define INT64_C(__val) __val##i64
+#define UINT64_C(__val) __val##ui64
+
+#ifndef __cplusplus
+#define false 0
+#define true 1
+#define bool _Bool
+typedef int _Bool;
+#define __bool_true_false_are_defined 1
+#endif /* !__cplusplus */
+
+#else
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+#include <stdint.h>
+#include <stdbool.h>
+#endif
+
+
+#ifndef __HAIKU__
+typedef unsigned int uint;
+typedef unsigned short ushort;
+#endif
+typedef unsigned char ubyte;
+
+#if 0
+#define boolean bool
+#else
+typedef unsigned char boolean;
+#endif
+#ifndef TRUE
+#define TRUE true
+#endif
+#ifndef FALSE
+#define FALSE false
+#endif
+
+
+/* Function inlining */
+#ifndef INLINE
+# ifdef __cplusplus
+# define INLINE inline
+# elif defined(__GNUC__)
+# define INLINE __inline__
+# elif defined(_MSC_VER)
+# define INLINE __inline
+# elif defined(__ICL)
+# define INLINE __inline
+# elif defined(__INTEL_COMPILER)
+# define INLINE inline
+# elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100)
+# define INLINE __inline
+# elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
+# define INLINE inline
+# elif (__STDC_VERSION__ >= 199901L) /* C99 */
+# define INLINE inline
+# else
+# define INLINE
+# endif
+#endif
+
+/* The __FUNCTION__ gcc variable is generally only used for debugging.
+ * If we're not using gcc, define __FUNCTION__ as a cpp symbol here.
+ */
+#ifndef __FUNCTION__
+# if (!defined(__GNUC__) || (__GNUC__ < 2))
+# if (__STDC_VERSION__ >= 199901L) /* C99 */ || \
+ (defined(__SUNPRO_C) && defined(__C99FEATURES__))
+# define __FUNCTION__ __func__
+# else
+# define __FUNCTION__ "<unknown>"
+# endif
+# endif
+#endif
+
+
+
+/* This should match linux gcc cdecl semantics everywhere, so that we
+ * just codegen one calling convention on all platforms.
+ */
+#ifdef _MSC_VER
+#define PIPE_CDECL __cdecl
+#else
+#define PIPE_CDECL
+#endif
+
+
+
+#if defined(__GNUC__)
+#define ALIGN16_DECL(TYPE, NAME, SIZE) TYPE NAME##___aligned[SIZE] __attribute__(( aligned( 16 ) ))
+#define ALIGN16_ASSIGN(NAME) NAME##___aligned
+#define ALIGN16_ATTRIB __attribute__(( aligned( 16 ) ))
+#define ALIGN8_ATTRIB __attribute__(( aligned( 8 ) ))
+#else
+#define ALIGN16_DECL(TYPE, NAME, SIZE) TYPE NAME##___unaligned[SIZE + 1]
+#define ALIGN16_ASSIGN(NAME) align16(NAME##___unaligned)
+#define ALIGN16_ATTRIB
+#define ALIGN8_ATTRIB
+#endif
+
+
+
+#endif /* P_COMPILER_H */
diff --git a/src/gallium/include/pipe/p_config.h b/src/gallium/include/pipe/p_config.h
new file mode 100644
index 0000000000..de99957d9d
--- /dev/null
+++ b/src/gallium/include/pipe/p_config.h
@@ -0,0 +1,176 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Gallium configuration defines.
+ *
+ * This header file sets several defines based on the compiler, processor
+ * architecture, and operating system being used. These defines should be used
+ * throughout the code to facilitate porting to new platforms. It is likely that
+ * this file is auto-generated by an autoconf-like tool at some point, as some
+ * things cannot be determined by pre-defined environment alone.
+ *
+ * See also:
+ * - http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
+ * - echo | gcc -dM -E - | sort
+ * - http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+ *
+ * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef P_CONFIG_H_
+#define P_CONFIG_H_
+
+
+/*
+ * Compiler
+ */
+
+#if defined(__GNUC__)
+#define PIPE_CC_GCC
+#endif
+
+/*
+ * Meaning of _MSC_VER value:
+ * - 1400: Visual C++ 2005
+ * - 1310: Visual C++ .NET 2003
+ * - 1300: Visual C++ .NET 2002
+ *
+ * __MSC__ seems to be an old macro -- it is not pre-defined on recent MSVC
+ * versions.
+ */
+#if defined(_MSC_VER) || defined(__MSC__)
+#define PIPE_CC_MSVC
+#endif
+
+#if defined(__ICL)
+#define PIPE_CC_ICL
+#endif
+
+
+/*
+ * Processor architecture
+ */
+
+#if defined(__i386__) /* gcc */ || defined(_M_IX86) /* msvc */ || defined(_X86_) || defined(__386__) || defined(i386) || defined(__i386) /* Sun cc */
+#define PIPE_ARCH_X86
+#endif
+
+#if defined(__x86_64__) /* gcc */ || defined(_M_X64) /* msvc */ || defined(_M_AMD64) /* msvc */ || defined(__x86_64) /* Sun cc */
+#define PIPE_ARCH_X86_64
+#endif
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+#if defined(PIPE_CC_GCC) && !defined(__SSE2__)
+/* #warning SSE2 support requires -msse -msse2 compiler options */
+#else
+#define PIPE_ARCH_SSE
+#endif
+#endif
+
+#if defined(__PPC__)
+#define PIPE_ARCH_PPC
+#if defined(__PPC64__)
+#define PIPE_ARCH_PPC_64
+#endif
+#endif
+
+
+/*
+ * Endian detection.
+ */
+
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
+#define PIPE_ARCH_LITTLE_ENDIAN
+#elif defined(PIPE_ARCH_PPC) || defined(PIPE_ARCH_PPC_64)
+#define PIPE_ARCH_BIG_ENDIAN
+#else
+#define PIPE_ARCH_UNKNOWN_ENDIAN
+#endif
+
+
+/*
+ * Operating system family.
+ *
+ * See subsystem below for a more fine-grained distinction.
+ */
+
+#if defined(__linux__)
+#define PIPE_OS_LINUX
+#endif
+
+#if defined(__FreeBSD__)
+#define PIPE_OS_BSD
+#endif
+
+#if defined(__sun)
+#define PIPE_OS_SOLARIS
+#endif
+
+#if defined(__APPLE__)
+#define PIPE_OS_APPLE
+#endif
+
+#if defined(_WIN32) || defined(WIN32)
+#define PIPE_OS_WINDOWS
+#endif
+
+#if defined(__HAIKU__)
+#define PIPE_OS_HAIKU
+#endif
+
+/*
+ * Subsystem.
+ *
+ * NOTE: There is no way to auto-detect most of these.
+ */
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)
+#define PIPE_SUBSYSTEM_DRI
+#endif /* PIPE_OS_LINUX || PIPE_OS_BSD || PIPE_OS_SOLARIS */
+
+#if defined(PIPE_OS_WINDOWS)
+#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+/* Windows 2000/XP Display Driver */
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+/* Windows 2000/XP Miniport Driver */
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+/* Windows User-space Library */
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+/* Windows CE 5.0/6.0 */
+#else
+#ifdef _WIN32_WCE
+#define PIPE_SUBSYSTEM_WINDOWS_CE
+#else /* !_WIN32_WCE */
+#error No PIPE_SUBSYSTEM_WINDOWS_xxx subsystem defined.
+#endif /* !_WIN32_WCE */
+#endif
+#endif /* PIPE_OS_WINDOWS */
+
+
+#endif /* P_CONFIG_H_ */
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
new file mode 100644
index 0000000000..39620a7198
--- /dev/null
+++ b/src/gallium/include/pipe/p_context.h
@@ -0,0 +1,271 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PIPE_CONTEXT_H
+#define PIPE_CONTEXT_H
+
+#include "p_state.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_screen;
+struct pipe_fence_handle;
+struct pipe_state_cache;
+struct pipe_query;
+struct pipe_winsys;
+
+/**
+ * Gallium rendering context. Basically:
+ * - state setting functions
+ * - VBO drawing functions
+ * - surface functions
+ */
+struct pipe_context {
+ struct pipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ void *priv; /**< context private data (for DRI for example) */
+ void *draw; /**< private, for draw module (temporary?) */
+
+ void (*destroy)( struct pipe_context * );
+
+
+ /* Possible interface for setting edgeflags. These aren't really
+ * vertex elements, so don't fit there.
+ */
+ void (*set_edgeflags)( struct pipe_context *,
+ const unsigned *bitfield );
+
+
+ /**
+ * VBO drawing (return false on fallbacks (temporary??))
+ */
+ /*@{*/
+ boolean (*draw_arrays)( struct pipe_context *pipe,
+ unsigned mode, unsigned start, unsigned count);
+
+ boolean (*draw_elements)( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count);
+
+ /* XXX: this is (probably) a temporary entrypoint, as the range
+ * information should be available from the vertex_buffer state.
+ * Using this to quickly evaluate a specialized path in the draw
+ * module.
+ */
+ boolean (*draw_range_elements)( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count);
+ /*@}*/
+
+
+ /**
+ * Query objects
+ */
+ /*@{*/
+ struct pipe_query *(*create_query)( struct pipe_context *pipe,
+ unsigned query_type );
+
+ void (*destroy_query)(struct pipe_context *pipe,
+ struct pipe_query *q);
+
+ void (*begin_query)(struct pipe_context *pipe, struct pipe_query *q);
+ void (*end_query)(struct pipe_context *pipe, struct pipe_query *q);
+
+ boolean (*get_query_result)(struct pipe_context *pipe,
+ struct pipe_query *q,
+ boolean wait,
+ uint64_t *result);
+ /*@}*/
+
+ /**
+ * State functions (create/bind/destroy state objects)
+ */
+ /*@{*/
+ void * (*create_blend_state)(struct pipe_context *,
+ const struct pipe_blend_state *);
+ void (*bind_blend_state)(struct pipe_context *, void *);
+ void (*delete_blend_state)(struct pipe_context *, void *);
+
+ void * (*create_sampler_state)(struct pipe_context *,
+ const struct pipe_sampler_state *);
+ void (*bind_sampler_states)(struct pipe_context *, unsigned num, void **);
+ void (*delete_sampler_state)(struct pipe_context *, void *);
+
+ void * (*create_rasterizer_state)(struct pipe_context *,
+ const struct pipe_rasterizer_state *);
+ void (*bind_rasterizer_state)(struct pipe_context *, void *);
+ void (*delete_rasterizer_state)(struct pipe_context *, void *);
+
+ void * (*create_depth_stencil_alpha_state)(struct pipe_context *,
+ const struct pipe_depth_stencil_alpha_state *);
+ void (*bind_depth_stencil_alpha_state)(struct pipe_context *, void *);
+ void (*delete_depth_stencil_alpha_state)(struct pipe_context *, void *);
+
+ void * (*create_fs_state)(struct pipe_context *,
+ const struct pipe_shader_state *);
+ void (*bind_fs_state)(struct pipe_context *, void *);
+ void (*delete_fs_state)(struct pipe_context *, void *);
+
+ void * (*create_vs_state)(struct pipe_context *,
+ const struct pipe_shader_state *);
+ void (*bind_vs_state)(struct pipe_context *, void *);
+ void (*delete_vs_state)(struct pipe_context *, void *);
+ /*@}*/
+
+ /**
+ * Parameter-like state (or properties)
+ */
+ /*@{*/
+ void (*set_blend_color)( struct pipe_context *,
+ const struct pipe_blend_color * );
+
+ void (*set_clip_state)( struct pipe_context *,
+ const struct pipe_clip_state * );
+
+ void (*set_constant_buffer)( struct pipe_context *,
+ uint shader, uint index,
+ const struct pipe_constant_buffer *buf );
+
+ void (*set_framebuffer_state)( struct pipe_context *,
+ const struct pipe_framebuffer_state * );
+
+ void (*set_polygon_stipple)( struct pipe_context *,
+ const struct pipe_poly_stipple * );
+
+ void (*set_scissor_state)( struct pipe_context *,
+ const struct pipe_scissor_state * );
+
+ void (*set_viewport_state)( struct pipe_context *,
+ const struct pipe_viewport_state * );
+
+ void (*set_sampler_textures)( struct pipe_context *,
+ unsigned num_textures,
+ struct pipe_texture ** );
+
+ void (*set_vertex_buffers)( struct pipe_context *,
+ unsigned num_buffers,
+ const struct pipe_vertex_buffer * );
+
+ void (*set_vertex_elements)( struct pipe_context *,
+ unsigned num_elements,
+ const struct pipe_vertex_element * );
+ /*@}*/
+
+
+ /**
+ * Surface functions
+ */
+ /*@{*/
+
+ /**
+ * Copy a block of pixels from one surface to another.
+ * The surfaces must be of the same format.
+ */
+ void (*surface_copy)(struct pipe_context *pipe,
+ struct pipe_surface *dest,
+ unsigned destx, unsigned desty,
+ struct pipe_surface *src,
+ unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height);
+
+ /**
+ * Fill a region of a surface with a constant value.
+ */
+ void (*surface_fill)(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height,
+ unsigned value);
+ /*@}*/
+
+ /**
+ * Clear the specified set of currently bound buffers to specified values.
+ * The entire buffers are cleared (no scissor, no colormask, etc).
+ *
+ * \param buffers bitfield of PIPE_CLEAR_* values.
+ * \param rgba pointer to an array of one float for each of r, g, b, a.
+ * \param depth depth clear value in [0,1].
+ * \param stencil stencil clear value
+ */
+ void (*clear)(struct pipe_context *pipe,
+ unsigned buffers,
+ const float *rgba,
+ double depth,
+ unsigned stencil);
+
+ /** Flush rendering
+ * \param flags bitmask of PIPE_FLUSH_x tokens)
+ */
+ void (*flush)( struct pipe_context *pipe,
+ unsigned flags,
+ struct pipe_fence_handle **fence );
+
+ /**
+ * Check whether a texture is referenced by an unflushed hw command.
+ * The state-tracker uses this function to optimize away unnecessary
+ * flushes. It is safe (but wasteful) to always return.
+ * PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE.
+ * \param pipe The pipe context whose unflushed hw commands will be
+ * checked.
+ * \param level mipmap level.
+ * \param texture texture to check.
+ * \param face cubemap face. Use 0 for non-cubemap texture.
+ */
+ unsigned int (*is_texture_referenced) (struct pipe_context *pipe,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level);
+
+ /**
+ * Check whether a buffer is referenced by an unflushed hw command.
+ * The state-tracker uses this function to optimize away unnecessary
+ * flushes. It is safe (but wasteful) to always return
+ * PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE.
+ * \param pipe The pipe context whose unflushed hw commands will be
+ * checked.
+ * \param buf Buffer to check.
+ */
+ unsigned int (*is_buffer_referenced) (struct pipe_context *pipe,
+ struct pipe_buffer *buf);
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PIPE_CONTEXT_H */
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
new file mode 100644
index 0000000000..b01ab6d137
--- /dev/null
+++ b/src/gallium/include/pipe/p_defines.h
@@ -0,0 +1,322 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PIPE_DEFINES_H
+#define PIPE_DEFINES_H
+
+#include "p_format.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PIPE_BLENDFACTOR_ONE 0x1
+#define PIPE_BLENDFACTOR_SRC_COLOR 0x2
+#define PIPE_BLENDFACTOR_SRC_ALPHA 0x3
+#define PIPE_BLENDFACTOR_DST_ALPHA 0x4
+#define PIPE_BLENDFACTOR_DST_COLOR 0x5
+#define PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE 0x6
+#define PIPE_BLENDFACTOR_CONST_COLOR 0x7
+#define PIPE_BLENDFACTOR_CONST_ALPHA 0x8
+#define PIPE_BLENDFACTOR_SRC1_COLOR 0x9
+#define PIPE_BLENDFACTOR_SRC1_ALPHA 0x0A
+#define PIPE_BLENDFACTOR_ZERO 0x11
+#define PIPE_BLENDFACTOR_INV_SRC_COLOR 0x12
+#define PIPE_BLENDFACTOR_INV_SRC_ALPHA 0x13
+#define PIPE_BLENDFACTOR_INV_DST_ALPHA 0x14
+#define PIPE_BLENDFACTOR_INV_DST_COLOR 0x15
+#define PIPE_BLENDFACTOR_INV_CONST_COLOR 0x17
+#define PIPE_BLENDFACTOR_INV_CONST_ALPHA 0x18
+#define PIPE_BLENDFACTOR_INV_SRC1_COLOR 0x19
+#define PIPE_BLENDFACTOR_INV_SRC1_ALPHA 0x1A
+
+#define PIPE_BLEND_ADD 0
+#define PIPE_BLEND_SUBTRACT 1
+#define PIPE_BLEND_REVERSE_SUBTRACT 2
+#define PIPE_BLEND_MIN 3
+#define PIPE_BLEND_MAX 4
+
+#define PIPE_LOGICOP_CLEAR 0
+#define PIPE_LOGICOP_NOR 1
+#define PIPE_LOGICOP_AND_INVERTED 2
+#define PIPE_LOGICOP_COPY_INVERTED 3
+#define PIPE_LOGICOP_AND_REVERSE 4
+#define PIPE_LOGICOP_INVERT 5
+#define PIPE_LOGICOP_XOR 6
+#define PIPE_LOGICOP_NAND 7
+#define PIPE_LOGICOP_AND 8
+#define PIPE_LOGICOP_EQUIV 9
+#define PIPE_LOGICOP_NOOP 10
+#define PIPE_LOGICOP_OR_INVERTED 11
+#define PIPE_LOGICOP_COPY 12
+#define PIPE_LOGICOP_OR_REVERSE 13
+#define PIPE_LOGICOP_OR 14
+#define PIPE_LOGICOP_SET 15
+
+#define PIPE_MASK_R 0x1
+#define PIPE_MASK_G 0x2
+#define PIPE_MASK_B 0x4
+#define PIPE_MASK_A 0x8
+#define PIPE_MASK_RGBA 0xf
+
+
+/**
+ * Inequality functions. Used for depth test, stencil compare, alpha
+ * test, shadow compare, etc.
+ */
+#define PIPE_FUNC_NEVER 0
+#define PIPE_FUNC_LESS 1
+#define PIPE_FUNC_EQUAL 2
+#define PIPE_FUNC_LEQUAL 3
+#define PIPE_FUNC_GREATER 4
+#define PIPE_FUNC_NOTEQUAL 5
+#define PIPE_FUNC_GEQUAL 6
+#define PIPE_FUNC_ALWAYS 7
+
+/** Polygon fill mode */
+#define PIPE_POLYGON_MODE_FILL 0
+#define PIPE_POLYGON_MODE_LINE 1
+#define PIPE_POLYGON_MODE_POINT 2
+
+/** Polygon front/back window, also for culling */
+#define PIPE_WINDING_NONE 0
+#define PIPE_WINDING_CW 1
+#define PIPE_WINDING_CCW 2
+#define PIPE_WINDING_BOTH (PIPE_WINDING_CW | PIPE_WINDING_CCW)
+
+/** Stencil ops */
+#define PIPE_STENCIL_OP_KEEP 0
+#define PIPE_STENCIL_OP_ZERO 1
+#define PIPE_STENCIL_OP_REPLACE 2
+#define PIPE_STENCIL_OP_INCR 3
+#define PIPE_STENCIL_OP_DECR 4
+#define PIPE_STENCIL_OP_INCR_WRAP 5
+#define PIPE_STENCIL_OP_DECR_WRAP 6
+#define PIPE_STENCIL_OP_INVERT 7
+
+/** Texture types */
+enum pipe_texture_target {
+ PIPE_TEXTURE_1D = 0,
+ PIPE_TEXTURE_2D = 1,
+ PIPE_TEXTURE_3D = 2,
+ PIPE_TEXTURE_CUBE = 3
+};
+
+#define PIPE_TEX_FACE_POS_X 0
+#define PIPE_TEX_FACE_NEG_X 1
+#define PIPE_TEX_FACE_POS_Y 2
+#define PIPE_TEX_FACE_NEG_Y 3
+#define PIPE_TEX_FACE_POS_Z 4
+#define PIPE_TEX_FACE_NEG_Z 5
+#define PIPE_TEX_FACE_MAX 6
+
+#define PIPE_TEX_WRAP_REPEAT 0
+#define PIPE_TEX_WRAP_CLAMP 1
+#define PIPE_TEX_WRAP_CLAMP_TO_EDGE 2
+#define PIPE_TEX_WRAP_CLAMP_TO_BORDER 3
+#define PIPE_TEX_WRAP_MIRROR_REPEAT 4
+#define PIPE_TEX_WRAP_MIRROR_CLAMP 5
+#define PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE 6
+#define PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER 7
+
+/* Between mipmaps, ie mipfilter
+ */
+#define PIPE_TEX_MIPFILTER_NEAREST 0
+#define PIPE_TEX_MIPFILTER_LINEAR 1
+#define PIPE_TEX_MIPFILTER_NONE 2
+
+/* Within a mipmap, ie min/mag filter
+ */
+#define PIPE_TEX_FILTER_NEAREST 0
+#define PIPE_TEX_FILTER_LINEAR 1
+#define PIPE_TEX_FILTER_ANISO 2
+
+
+#define PIPE_TEX_COMPARE_NONE 0
+#define PIPE_TEX_COMPARE_R_TO_TEXTURE 1
+
+#define PIPE_TEXTURE_USAGE_RENDER_TARGET 0x1
+#define PIPE_TEXTURE_USAGE_DISPLAY_TARGET 0x2 /* ie a backbuffer */
+#define PIPE_TEXTURE_USAGE_PRIMARY 0x4 /* ie a frontbuffer */
+#define PIPE_TEXTURE_USAGE_DEPTH_STENCIL 0x8
+#define PIPE_TEXTURE_USAGE_SAMPLER 0x10
+#define PIPE_TEXTURE_USAGE_DYNAMIC 0x20
+/** Pipe driver custom usage flags should be greater or equal to this value */
+#define PIPE_TEXTURE_USAGE_CUSTOM (1 << 16)
+
+#define PIPE_TEXTURE_GEOM_NON_SQUARE 0x1
+#define PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO 0x2
+
+
+/**
+ * Surface layout
+ */
+#define PIPE_SURFACE_LAYOUT_LINEAR 0
+
+
+/**
+ * Clear buffer bits
+ */
+/** All color buffers currently bound */
+#define PIPE_CLEAR_COLOR (1 << 0)
+/** Depth/stencil combined */
+#define PIPE_CLEAR_DEPTHSTENCIL (1 << 1)
+
+
+/**
+ * Transfer object usage flags
+ */
+enum pipe_transfer_usage {
+ PIPE_TRANSFER_READ = (1 << 0),
+ PIPE_TRANSFER_WRITE = (1 << 1),
+ PIPE_TRANSFER_READ_WRITE = PIPE_TRANSFER_READ | PIPE_TRANSFER_WRITE /**< Read/modify/write */
+};
+
+
+/**
+ * Buffer usage flags
+ */
+#define PIPE_BUFFER_USAGE_CPU_READ (1 << 0)
+#define PIPE_BUFFER_USAGE_CPU_WRITE (1 << 1)
+#define PIPE_BUFFER_USAGE_GPU_READ (1 << 2)
+#define PIPE_BUFFER_USAGE_GPU_WRITE (1 << 3)
+#define PIPE_BUFFER_USAGE_PIXEL (1 << 4)
+#define PIPE_BUFFER_USAGE_VERTEX (1 << 5)
+#define PIPE_BUFFER_USAGE_INDEX (1 << 6)
+#define PIPE_BUFFER_USAGE_CONSTANT (1 << 7)
+#define PIPE_BUFFER_USAGE_DISCARD (1 << 8)
+#define PIPE_BUFFER_USAGE_DONTBLOCK (1 << 9)
+#define PIPE_BUFFER_USAGE_FLUSH_EXPLICIT (1 << 10) /**< See pipe_screen::buffer_flush_mapped_range */
+/** Pipe driver custom usage flags should be greater or equal to this value */
+#define PIPE_BUFFER_USAGE_CUSTOM (1 << 16)
+
+/* Convenient shortcuts */
+#define PIPE_BUFFER_USAGE_CPU_READ_WRITE \
+ ( PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE )
+#define PIPE_BUFFER_USAGE_GPU_READ_WRITE \
+ ( PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE )
+#define PIPE_BUFFER_USAGE_WRITE \
+ ( PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_GPU_WRITE )
+
+
+/**
+ * Flush types:
+ */
+#define PIPE_FLUSH_RENDER_CACHE 0x1
+#define PIPE_FLUSH_TEXTURE_CACHE 0x2
+#define PIPE_FLUSH_SWAPBUFFERS 0x4
+#define PIPE_FLUSH_FRAME 0x8 /**< Mark the end of a frame */
+
+
+/**
+ * Shaders
+ */
+#define PIPE_SHADER_VERTEX 0
+#define PIPE_SHADER_FRAGMENT 1
+#define PIPE_SHADER_TYPES 2
+
+
+/**
+ * Primitive types:
+ */
+#define PIPE_PRIM_POINTS 0
+#define PIPE_PRIM_LINES 1
+#define PIPE_PRIM_LINE_LOOP 2
+#define PIPE_PRIM_LINE_STRIP 3
+#define PIPE_PRIM_TRIANGLES 4
+#define PIPE_PRIM_TRIANGLE_STRIP 5
+#define PIPE_PRIM_TRIANGLE_FAN 6
+#define PIPE_PRIM_QUADS 7
+#define PIPE_PRIM_QUAD_STRIP 8
+#define PIPE_PRIM_POLYGON 9
+#define PIPE_PRIM_MAX 10
+
+
+/**
+ * Query object types
+ */
+#define PIPE_QUERY_OCCLUSION_COUNTER 0
+#define PIPE_QUERY_PRIMITIVES_GENERATED 1
+#define PIPE_QUERY_PRIMITIVES_EMITTED 2
+#define PIPE_QUERY_TYPES 3
+
+
+/**
+ * Point sprite coord modes
+ */
+#define PIPE_SPRITE_COORD_NONE 0
+#define PIPE_SPRITE_COORD_UPPER_LEFT 1
+#define PIPE_SPRITE_COORD_LOWER_LEFT 2
+
+
+/**
+ * Implementation capabilities/limits which are queried through
+ * pipe_screen::get_param() and pipe_screen::get_paramf().
+ */
+#define PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS 1
+#define PIPE_CAP_NPOT_TEXTURES 2
+#define PIPE_CAP_TWO_SIDED_STENCIL 3
+#define PIPE_CAP_GLSL 4 /* XXX need something better */
+#define PIPE_CAP_S3TC 5
+#define PIPE_CAP_ANISOTROPIC_FILTER 6
+#define PIPE_CAP_POINT_SPRITE 7
+#define PIPE_CAP_MAX_RENDER_TARGETS 8
+#define PIPE_CAP_OCCLUSION_QUERY 9
+#define PIPE_CAP_TEXTURE_SHADOW_MAP 10
+#define PIPE_CAP_MAX_TEXTURE_2D_LEVELS 11
+#define PIPE_CAP_MAX_TEXTURE_3D_LEVELS 12
+#define PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS 13
+#define PIPE_CAP_MAX_LINE_WIDTH 14
+#define PIPE_CAP_MAX_LINE_WIDTH_AA 15
+#define PIPE_CAP_MAX_POINT_WIDTH 16
+#define PIPE_CAP_MAX_POINT_WIDTH_AA 17
+#define PIPE_CAP_MAX_TEXTURE_ANISOTROPY 18
+#define PIPE_CAP_MAX_TEXTURE_LOD_BIAS 19
+#define PIPE_CAP_GUARD_BAND_LEFT 20 /*< float */
+#define PIPE_CAP_GUARD_BAND_TOP 21 /*< float */
+#define PIPE_CAP_GUARD_BAND_RIGHT 22 /*< float */
+#define PIPE_CAP_GUARD_BAND_BOTTOM 23 /*< float */
+#define PIPE_CAP_TEXTURE_MIRROR_CLAMP 24
+#define PIPE_CAP_TEXTURE_MIRROR_REPEAT 25
+#define PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS 26
+#define PIPE_CAP_TGSI_CONT_SUPPORTED 27
+#define PIPE_CAP_BLEND_EQUATION_SEPARATE 28
+
+
+/**
+ * Referenced query flags.
+ */
+
+#define PIPE_UNREFERENCED 0
+#define PIPE_REFERENCED_FOR_READ (1 << 0)
+#define PIPE_REFERENCED_FOR_WRITE (1 << 1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/include/pipe/p_error.h b/src/gallium/include/pipe/p_error.h
new file mode 100644
index 0000000000..b865b22635
--- /dev/null
+++ b/src/gallium/include/pipe/p_error.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Gallium error codes.
+ *
+ * @author José Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef P_ERROR_H_
+#define P_ERROR_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Gallium error codes.
+ *
+ * - A zero value always means success.
+ * - A negative value always means failure.
+ * - The meaning of a positive value is function dependent.
+ */
+enum pipe_error {
+ PIPE_OK = 0,
+ PIPE_ERROR = -1, /**< Generic error */
+ PIPE_ERROR_BAD_INPUT = -2,
+ PIPE_ERROR_OUT_OF_MEMORY = -3,
+ PIPE_ERROR_RETRY = -4
+ /* TODO */
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* P_ERROR_H_ */
diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h
new file mode 100644
index 0000000000..c4469d4a9e
--- /dev/null
+++ b/src/gallium/include/pipe/p_format.h
@@ -0,0 +1,620 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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 PIPE_FORMAT_H
+#define PIPE_FORMAT_H
+
+#include "p_compiler.h"
+
+/* FIXME: remove these header dependencies */
+#include "util/u_debug.h"
+#include "util/u_string.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The pipe_format enum is a 32-bit wide bitfield that encodes all the
+ * information needed to uniquely describe a pixel format.
+ */
+
+/**
+ * Possible format layouts are encoded in the first 2 bits.
+ * The interpretation of the remaining 30 bits depends on a particular
+ * format layout.
+ */
+#define PIPE_FORMAT_LAYOUT_RGBAZS 0
+#define PIPE_FORMAT_LAYOUT_YCBCR 1
+#define PIPE_FORMAT_LAYOUT_DXT 2 /**< XXX temporary? */
+#define PIPE_FORMAT_LAYOUT_MIXED 3
+
+static INLINE uint pf_layout(uint f) /**< PIPE_FORMAT_LAYOUT_ */
+{
+ return f & 0x3;
+}
+
+/**
+ * RGBAZS Format Layout.
+ */
+
+/**
+ * Format component selectors for RGBAZS & MIXED layout.
+ */
+#define PIPE_FORMAT_COMP_R 0
+#define PIPE_FORMAT_COMP_G 1
+#define PIPE_FORMAT_COMP_B 2
+#define PIPE_FORMAT_COMP_A 3
+#define PIPE_FORMAT_COMP_0 4
+#define PIPE_FORMAT_COMP_1 5
+#define PIPE_FORMAT_COMP_Z 6
+#define PIPE_FORMAT_COMP_S 7
+
+/**
+ * Format types for RGBAZS layout.
+ */
+#define PIPE_FORMAT_TYPE_UNKNOWN 0
+#define PIPE_FORMAT_TYPE_FLOAT 1 /**< 16/32/64-bit/channel formats */
+#define PIPE_FORMAT_TYPE_UNORM 2 /**< uints, normalized to [0,1] */
+#define PIPE_FORMAT_TYPE_SNORM 3 /**< ints, normalized to [-1,1] */
+#define PIPE_FORMAT_TYPE_USCALED 4 /**< uints, not normalized */
+#define PIPE_FORMAT_TYPE_SSCALED 5 /**< ints, not normalized */
+#define PIPE_FORMAT_TYPE_SRGB 6 /**< sRGB colorspace */
+#define PIPE_FORMAT_TYPE_FIXED 7 /**< 16.16 fixed point */
+
+
+/**
+ * Because the destination vector is assumed to be RGBA FLOAT, we
+ * need to know how to swizzle and expand components from the source
+ * vector.
+ * Let's take U_A1_R5_G5_B5 as an example. X swizzle is A, X size
+ * is 1 bit and type is UNORM. So we take the most significant bit
+ * from source vector, convert 0 to 0.0 and 1 to 1.0 and save it
+ * in the last component of the destination RGBA component.
+ * Next, Y swizzle is R, Y size is 5 and type is UNORM. We normalize
+ * those 5 bits into [0.0; 1.0] range and put it into second
+ * component of the destination vector. Rinse and repeat for
+ * components Z and W.
+ * If any of size fields is zero, it means the source format contains
+ * less than four components.
+ * If any swizzle is 0 or 1, the corresponding destination component
+ * should be filled with 0.0 and 1.0, respectively.
+ */
+typedef uint pipe_format_rgbazs_t;
+
+static INLINE uint pf_get(pipe_format_rgbazs_t f, uint shift, uint mask)
+{
+ return (f >> shift) & mask;
+}
+
+#define pf_swizzle_x(f) pf_get(f, 2, 0x7) /**< PIPE_FORMAT_COMP_ */
+#define pf_swizzle_y(f) pf_get(f, 5, 0x7) /**< PIPE_FORMAT_COMP_ */
+#define pf_swizzle_z(f) pf_get(f, 8, 0x7) /**< PIPE_FORMAT_COMP_ */
+#define pf_swizzle_w(f) pf_get(f, 11, 0x7) /**< PIPE_FORMAT_COMP_ */
+#define pf_swizzle_xyzw(f,i) pf_get(f, 2+((i)*3), 0x7)
+#define pf_size_x(f) pf_get(f, 14, 0x7) /**< Size of X */
+#define pf_size_y(f) pf_get(f, 17, 0x7) /**< Size of Y */
+#define pf_size_z(f) pf_get(f, 20, 0x7) /**< Size of Z */
+#define pf_size_w(f) pf_get(f, 23, 0x7) /**< Size of W */
+#define pf_size_xyzw(f,i) pf_get(f, 14+((i)*3), 0x7)
+#define pf_exp2(f) pf_get(f, 26, 0x7) /**< Scale size by 2 ^ exp2 */
+#define pf_type(f) pf_get(f, 29, 0x7) /**< PIPE_FORMAT_TYPE_ */
+
+/**
+ * Helper macro to encode the above structure into a 32-bit value.
+ */
+#define _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, EXP2, TYPE ) (\
+ (PIPE_FORMAT_LAYOUT_RGBAZS << 0) |\
+ ((SWZ) << 2) |\
+ ((SIZEX) << 14) |\
+ ((SIZEY) << 17) |\
+ ((SIZEZ) << 20) |\
+ ((SIZEW) << 23) |\
+ ((EXP2) << 26) |\
+ ((TYPE) << 29) )
+
+/**
+ * Helper macro to encode the swizzle part of the structure above.
+ */
+#define _PIPE_FORMAT_SWZ( SWZX, SWZY, SWZZ, SWZW ) (((SWZX) << 0) | ((SWZY) << 3) | ((SWZZ) << 6) | ((SWZW) << 9))
+
+/**
+ * Shorthand macro for RGBAZS layout with component sizes in 1-bit units.
+ */
+#define _PIPE_FORMAT_RGBAZS_1( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, TYPE )\
+ _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 0, TYPE )
+
+/**
+ * Shorthand macro for RGBAZS layout with component sizes in 2-bit units.
+ */
+#define _PIPE_FORMAT_RGBAZS_2( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, TYPE )\
+ _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 1, TYPE )
+
+/**
+ * Shorthand macro for RGBAZS layout with component sizes in 8-bit units.
+ */
+#define _PIPE_FORMAT_RGBAZS_8( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, TYPE )\
+ _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 3, TYPE )
+
+/**
+ * Shorthand macro for RGBAZS layout with component sizes in 64-bit units.
+ */
+#define _PIPE_FORMAT_RGBAZS_64( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, TYPE )\
+ _PIPE_FORMAT_RGBAZS( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, 6, TYPE )
+
+typedef uint pipe_format_mixed_t;
+
+/* NOTE: Use pf_swizzle_* and pf_size_* macros for swizzles and sizes.
+ */
+
+#define pf_mixed_sign_x(f) pf_get( f, 26, 0x1 ) /*< Sign of X */
+#define pf_mixed_sign_y(f) pf_get( f, 27, 0x1 ) /*< Sign of Y */
+#define pf_mixed_sign_z(f) pf_get( f, 28, 0x1 ) /*< Sign of Z */
+#define pf_mixed_sign_w(f) pf_get( f, 29, 0x1 ) /*< Sign of W */
+#define pf_mixed_sign_xyzw(f, i) pf_get( f, 26 + (i), 0x1 )
+#define pf_mixed_normalized(f) pf_get( f, 30, 0x1 ) /*< Type is NORM (1) or SCALED (0) */
+#define pf_mixed_scale8(f) pf_get( f, 31, 0x1 ) /*< Scale size by either one (0) or eight (1) */
+
+/**
+ * Helper macro to encode the above structure into a 32-bit value.
+ */
+#define _PIPE_FORMAT_MIXED( SWZ, SIZEX, SIZEY, SIZEZ, SIZEW, SIGNX, SIGNY, SIGNZ, SIGNW, NORMALIZED, SCALE8 ) (\
+ (PIPE_FORMAT_LAYOUT_MIXED << 0) |\
+ ((SWZ) << 2) |\
+ ((SIZEX) << 14) |\
+ ((SIZEY) << 17) |\
+ ((SIZEZ) << 20) |\
+ ((SIZEW) << 23) |\
+ ((SIGNX) << 26) |\
+ ((SIGNY) << 27) |\
+ ((SIGNZ) << 28) |\
+ ((SIGNW) << 29) |\
+ ((NORMALIZED) << 30) |\
+ ((SCALE8) << 31) )
+
+/**
+ * Shorthand macro for common format swizzles.
+ */
+#define _PIPE_FORMAT_R001 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_1 )
+#define _PIPE_FORMAT_RG01 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_1 )
+#define _PIPE_FORMAT_RGB1 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_1 )
+#define _PIPE_FORMAT_RGBA _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_A )
+#define _PIPE_FORMAT_ARGB _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_A, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_B )
+#define _PIPE_FORMAT_ABGR _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_A, PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_R )
+#define _PIPE_FORMAT_BGRA _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_A )
+#define _PIPE_FORMAT_1RGB _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_1, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_B )
+#define _PIPE_FORMAT_1BGR _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_1, PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_R )
+#define _PIPE_FORMAT_BGR1 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_B, PIPE_FORMAT_COMP_G, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_1 )
+#define _PIPE_FORMAT_0000 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0 )
+#define _PIPE_FORMAT_000R _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_R )
+#define _PIPE_FORMAT_RRR1 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_1 )
+#define _PIPE_FORMAT_RRRR _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_R )
+#define _PIPE_FORMAT_RRRG _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_R, PIPE_FORMAT_COMP_G )
+#define _PIPE_FORMAT_Z000 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_Z, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0 )
+#define _PIPE_FORMAT_0Z00 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_Z, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0 )
+#define _PIPE_FORMAT_SZ00 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_S, PIPE_FORMAT_COMP_Z, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0 )
+#define _PIPE_FORMAT_ZS00 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_Z, PIPE_FORMAT_COMP_S, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0 )
+#define _PIPE_FORMAT_S000 _PIPE_FORMAT_SWZ( PIPE_FORMAT_COMP_S, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0, PIPE_FORMAT_COMP_0 )
+
+/**
+ * YCBCR Format Layout.
+ */
+
+/**
+ * This only contains a flag that indicates whether the format is reversed or
+ * not.
+ */
+typedef uint pipe_format_ycbcr_t;
+
+/**
+ * Helper macro to encode the above structure into a 32-bit value.
+ */
+#define _PIPE_FORMAT_YCBCR( REV ) (\
+ (PIPE_FORMAT_LAYOUT_YCBCR << 0) |\
+ ((REV) << 2) )
+
+static INLINE uint pf_rev(pipe_format_ycbcr_t f)
+{
+ return (f >> 2) & 0x1;
+}
+
+
+/**
+ * Compresssed format layouts (this will probably change)
+ */
+#define _PIPE_FORMAT_DXT( LEVEL, RSIZE, GSIZE, BSIZE, ASIZE, TYPE ) \
+ ((PIPE_FORMAT_LAYOUT_DXT << 0) | \
+ ((LEVEL) << 2) | \
+ ((RSIZE) << 5) | \
+ ((GSIZE) << 8) | \
+ ((BSIZE) << 11) | \
+ ((ASIZE) << 14) | \
+ ((TYPE) << 29))
+
+
+
+/**
+ * Texture/surface image formats (preliminary)
+ */
+
+/* KW: Added lots of surface formats to support vertex element layout
+ * definitions, and eventually render-to-vertex-buffer. Could
+ * consider making float/int/uint/scaled/normalized a separate
+ * parameter, but on the other hand there are special cases like
+ * z24s8, compressed textures, ycbcr, etc that won't fit that model.
+ */
+
+enum pipe_format {
+ PIPE_FORMAT_NONE = _PIPE_FORMAT_RGBAZS_1 ( _PIPE_FORMAT_0000, 0, 0, 0, 0, PIPE_FORMAT_TYPE_UNKNOWN ),
+ PIPE_FORMAT_A8R8G8B8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_ARGB, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_X8R8G8B8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_1RGB, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_B8G8R8A8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_BGRA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_B8G8R8X8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_BGR1, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_A1R5G5B5_UNORM = _PIPE_FORMAT_RGBAZS_1 ( _PIPE_FORMAT_ARGB, 1, 5, 5, 5, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_A4R4G4B4_UNORM = _PIPE_FORMAT_RGBAZS_1 ( _PIPE_FORMAT_ARGB, 4, 4, 4, 4, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R5G6B5_UNORM = _PIPE_FORMAT_RGBAZS_1 ( _PIPE_FORMAT_RGB1, 5, 6, 5, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_A2B10G10R10_UNORM = _PIPE_FORMAT_RGBAZS_2 ( _PIPE_FORMAT_ABGR, 1, 5, 5, 5, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_L8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRR1, 1, 1, 1, 0, PIPE_FORMAT_TYPE_UNORM ), /**< ubyte luminance */
+ PIPE_FORMAT_A8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_000R, 0, 0, 0, 1, PIPE_FORMAT_TYPE_UNORM ), /**< ubyte alpha */
+ PIPE_FORMAT_I8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRRR, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ), /**< ubyte intensity */
+ PIPE_FORMAT_A8L8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRRG, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ), /**< ubyte alpha, luminance */
+ PIPE_FORMAT_L16_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRR1, 2, 2, 2, 0, PIPE_FORMAT_TYPE_UNORM ), /**< ushort luminance */
+ PIPE_FORMAT_YCBCR = _PIPE_FORMAT_YCBCR( 0 ),
+ PIPE_FORMAT_YCBCR_REV = _PIPE_FORMAT_YCBCR( 1 ),
+ PIPE_FORMAT_Z16_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_Z000, 2, 0, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_Z32_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_Z000, 4, 0, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_Z32_FLOAT = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_Z000, 4, 0, 0, 0, PIPE_FORMAT_TYPE_FLOAT ),
+ PIPE_FORMAT_S8Z24_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_SZ00, 1, 3, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_Z24S8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_ZS00, 3, 1, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_X8Z24_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_0Z00, 1, 3, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_Z24X8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_Z000, 3, 1, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_S8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_S000, 1, 0, 0, 0, PIPE_FORMAT_TYPE_UNORM ), /**< ubyte stencil */
+ PIPE_FORMAT_R64_FLOAT = _PIPE_FORMAT_RGBAZS_64( _PIPE_FORMAT_R001, 1, 0, 0, 0, PIPE_FORMAT_TYPE_FLOAT ),
+ PIPE_FORMAT_R64G64_FLOAT = _PIPE_FORMAT_RGBAZS_64( _PIPE_FORMAT_RG01, 1, 1, 0, 0, PIPE_FORMAT_TYPE_FLOAT ),
+ PIPE_FORMAT_R64G64B64_FLOAT = _PIPE_FORMAT_RGBAZS_64( _PIPE_FORMAT_RGB1, 1, 1, 1, 0, PIPE_FORMAT_TYPE_FLOAT ),
+ PIPE_FORMAT_R64G64B64A64_FLOAT = _PIPE_FORMAT_RGBAZS_64( _PIPE_FORMAT_RGBA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_FLOAT ),
+ PIPE_FORMAT_R32_FLOAT = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 4, 0, 0, 0, PIPE_FORMAT_TYPE_FLOAT ),
+ PIPE_FORMAT_R32G32_FLOAT = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 4, 4, 0, 0, PIPE_FORMAT_TYPE_FLOAT ),
+ PIPE_FORMAT_R32G32B32_FLOAT = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 4, 4, 4, 0, PIPE_FORMAT_TYPE_FLOAT ),
+ PIPE_FORMAT_R32G32B32A32_FLOAT = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 4, 4, 4, 4, PIPE_FORMAT_TYPE_FLOAT ),
+ PIPE_FORMAT_R32_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 4, 0, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R32G32_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 4, 4, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R32G32B32_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 4, 4, 4, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R32G32B32A32_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 4, 4, 4, 4, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R32_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 4, 0, 0, 0, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R32G32_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 4, 4, 0, 0, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R32G32B32_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 4, 4, 4, 0, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R32G32B32A32_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 4, 4, 4, 4, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R32_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 4, 0, 0, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R32G32_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 4, 4, 0, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R32G32B32_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 4, 4, 4, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R32G32B32A32_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 4, 4, 4, 4, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R32_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 4, 0, 0, 0, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R32G32_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 4, 4, 0, 0, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R32G32B32_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 4, 4, 4, 0, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R32G32B32A32_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 4, 4, 4, 4, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R16_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 2, 0, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R16G16_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 2, 2, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R16G16B16_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 2, 2, 2, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R16G16B16A16_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 2, 2, 2, 2, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R16_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 2, 0, 0, 0, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R16G16_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 2, 2, 0, 0, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R16G16B16_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 2, 2, 2, 0, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R16G16B16A16_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 2, 2, 2, 2, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R16_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 2, 0, 0, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R16G16_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 2, 2, 0, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R16G16B16_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 2, 2, 2, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R16G16B16A16_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 2, 2, 2, 2, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R16_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 2, 0, 0, 0, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R16G16_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 2, 2, 0, 0, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R16G16B16_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 2, 2, 2, 0, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R16G16B16A16_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 2, 2, 2, 2, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 1, 0, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R8G8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 1, 1, 0, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R8G8B8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R8G8B8A8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R8G8B8X8_UNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 1, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_R8_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 1, 0, 0, 0, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R8G8_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 1, 1, 0, 0, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R8G8B8_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 0, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R8G8B8A8_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R8G8B8X8_USCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 1, PIPE_FORMAT_TYPE_USCALED ),
+ PIPE_FORMAT_R8_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 1, 0, 0, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R8G8_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 1, 1, 0, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R8G8B8_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R8G8B8A8_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R8G8B8X8_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_B6G5R5_SNORM = _PIPE_FORMAT_RGBAZS_1 ( _PIPE_FORMAT_BGR1, 6, 5, 5, 0, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_A8B8G8R8_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_BGRA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_X8B8G8R8_SNORM = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_BGR1, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SNORM ),
+ PIPE_FORMAT_R8_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 1, 0, 0, 0, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R8G8_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 1, 1, 0, 0, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R8G8B8_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 0, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R8G8B8A8_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R8G8B8X8_SSCALED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SSCALED ),
+ PIPE_FORMAT_R32_FIXED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_R001, 4, 0, 0, 0, PIPE_FORMAT_TYPE_FIXED ),
+ PIPE_FORMAT_R32G32_FIXED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RG01, 4, 4, 0, 0, PIPE_FORMAT_TYPE_FIXED ),
+ PIPE_FORMAT_R32G32B32_FIXED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 4, 4, 4, 0, PIPE_FORMAT_TYPE_FIXED ),
+ PIPE_FORMAT_R32G32B32A32_FIXED = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 4, 4, 4, 4, PIPE_FORMAT_TYPE_FIXED ),
+ /* sRGB formats */
+ PIPE_FORMAT_L8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRR1, 1, 1, 1, 0, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_A8L8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RRRG, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_R8G8B8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 0, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_R8G8B8A8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGBA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_R8G8B8X8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_RGB1, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_A8R8G8B8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_ARGB, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_X8R8G8B8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_1RGB, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_B8G8R8A8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_BGRA, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_B8G8R8X8_SRGB = _PIPE_FORMAT_RGBAZS_8 ( _PIPE_FORMAT_BGR1, 1, 1, 1, 1, PIPE_FORMAT_TYPE_SRGB ),
+
+ /* mixed formats */
+ PIPE_FORMAT_X8UB8UG8SR8S_NORM = _PIPE_FORMAT_MIXED( _PIPE_FORMAT_1BGR, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 ),
+ PIPE_FORMAT_B6UG5SR5S_NORM = _PIPE_FORMAT_MIXED( _PIPE_FORMAT_BGR1, 6, 5, 5, 0, 0, 1, 1, 0, 1, 0 ),
+
+ /* compressed formats */
+ PIPE_FORMAT_DXT1_RGB = _PIPE_FORMAT_DXT( 1, 8, 8, 8, 0, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_DXT1_RGBA = _PIPE_FORMAT_DXT( 1, 8, 8, 8, 8, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_DXT3_RGBA = _PIPE_FORMAT_DXT( 3, 8, 8, 8, 8, PIPE_FORMAT_TYPE_UNORM ),
+ PIPE_FORMAT_DXT5_RGBA = _PIPE_FORMAT_DXT( 5, 8, 8, 8, 8, PIPE_FORMAT_TYPE_UNORM ),
+
+ /* sRGB, compressed */
+ PIPE_FORMAT_DXT1_SRGB = _PIPE_FORMAT_DXT( 1, 8, 8, 8, 0, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_DXT1_SRGBA = _PIPE_FORMAT_DXT( 1, 8, 8, 8, 8, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_DXT3_SRGBA = _PIPE_FORMAT_DXT( 3, 8, 8, 8, 8, PIPE_FORMAT_TYPE_SRGB ),
+ PIPE_FORMAT_DXT5_SRGBA = _PIPE_FORMAT_DXT( 5, 8, 8, 8, 8, PIPE_FORMAT_TYPE_SRGB )
+};
+
+/**
+ * Builds pipe format name from format token.
+ */
+extern const char *pf_name( enum pipe_format format );
+
+/**
+ * Return bits for a particular component.
+ * \param comp component index, starting at 0
+ */
+static INLINE uint pf_get_component_bits( enum pipe_format format, uint comp )
+{
+ uint size;
+
+ if (pf_swizzle_x(format) == comp) {
+ size = pf_size_x(format);
+ }
+ else if (pf_swizzle_y(format) == comp) {
+ size = pf_size_y(format);
+ }
+ else if (pf_swizzle_z(format) == comp) {
+ size = pf_size_z(format);
+ }
+ else if (pf_swizzle_w(format) == comp) {
+ size = pf_size_w(format);
+ }
+ else {
+ size = 0;
+ }
+ if (pf_layout( format ) == PIPE_FORMAT_LAYOUT_RGBAZS)
+ return size << pf_exp2( format );
+ return size << (pf_mixed_scale8( format ) * 3);
+}
+
+/**
+ * Return total bits needed for the pixel format.
+ */
+static INLINE uint pf_get_bits( enum pipe_format format )
+{
+ switch (pf_layout(format)) {
+ case PIPE_FORMAT_LAYOUT_RGBAZS:
+ case PIPE_FORMAT_LAYOUT_MIXED:
+ return
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_0 ) +
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_1 ) +
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_R ) +
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_G ) +
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_B ) +
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_A ) +
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_Z ) +
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_S );
+ case PIPE_FORMAT_LAYOUT_YCBCR:
+ assert( format == PIPE_FORMAT_YCBCR || format == PIPE_FORMAT_YCBCR_REV );
+ /* return effective bits per pixel */
+ return 16;
+ default:
+ assert( 0 );
+ return 0;
+ }
+}
+
+/**
+ * Return bytes per pixel for the given format.
+ */
+static INLINE uint pf_get_size( enum pipe_format format )
+{
+ assert(pf_get_bits(format) % 8 == 0);
+ return pf_get_bits(format) / 8;
+}
+
+/**
+ * Describe accurately the pixel format.
+ *
+ * The chars-per-pixel concept falls apart with compressed and yuv images, where
+ * more than one pixel are coded in a single data block. This structure
+ * describes that block.
+ *
+ * Simple pixel formats are effectively a 1x1xcpp block.
+ */
+struct pipe_format_block
+{
+ /** Block size in bytes */
+ unsigned size;
+
+ /** Block width in pixels */
+ unsigned width;
+
+ /** Block height in pixels */
+ unsigned height;
+};
+
+/**
+ * Describe pixel format's block.
+ *
+ * @sa http://msdn2.microsoft.com/en-us/library/ms796147.aspx
+ */
+static INLINE void
+pf_get_block(enum pipe_format format, struct pipe_format_block *block)
+{
+ switch(format) {
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_SRGBA:
+ case PIPE_FORMAT_DXT1_SRGB:
+ block->size = 8;
+ block->width = 4;
+ block->height = 4;
+ break;
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT5_RGBA:
+ case PIPE_FORMAT_DXT3_SRGBA:
+ case PIPE_FORMAT_DXT5_SRGBA:
+ block->size = 16;
+ block->width = 4;
+ block->height = 4;
+ break;
+ case PIPE_FORMAT_YCBCR:
+ case PIPE_FORMAT_YCBCR_REV:
+ block->size = 4; /* 2*cpp */
+ block->width = 2;
+ block->height = 1;
+ break;
+ default:
+ block->size = pf_get_size(format);
+ block->width = 1;
+ block->height = 1;
+ break;
+ }
+}
+
+static INLINE unsigned
+pf_get_nblocksx(const struct pipe_format_block *block, unsigned x)
+{
+ return (x + block->width - 1)/block->width;
+}
+
+static INLINE unsigned
+pf_get_nblocksy(const struct pipe_format_block *block, unsigned y)
+{
+ return (y + block->height - 1)/block->height;
+}
+
+static INLINE unsigned
+pf_get_nblocks(const struct pipe_format_block *block, unsigned width, unsigned height)
+{
+ return pf_get_nblocksx(block, width)*pf_get_nblocksy(block, height);
+}
+
+static INLINE size_t
+pf_get_stride(const struct pipe_format_block *block, unsigned width)
+{
+ return pf_get_nblocksx(block, width)*block->size;
+}
+
+static INLINE size_t
+pf_get_2d_size(const struct pipe_format_block *block, size_t stride, unsigned height)
+{
+ return pf_get_nblocksy(block, height)*stride;
+}
+
+static INLINE boolean
+pf_is_depth_or_stencil( enum pipe_format format )
+{
+ return (pf_get_component_bits( format, PIPE_FORMAT_COMP_Z ) +
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_S )) != 0;
+}
+
+static INLINE boolean
+pf_is_depth_and_stencil( enum pipe_format format )
+{
+ return (pf_get_component_bits( format, PIPE_FORMAT_COMP_Z ) != 0 &&
+ pf_get_component_bits( format, PIPE_FORMAT_COMP_S ) != 0);
+}
+
+/** DEPRECATED: For backwards compatibility */
+static INLINE boolean
+pf_is_depth_stencil( enum pipe_format format )
+{
+ return pf_is_depth_or_stencil( format );
+}
+
+static INLINE boolean
+pf_is_compressed( enum pipe_format format )
+{
+ return pf_layout(format) == PIPE_FORMAT_LAYOUT_DXT ? TRUE : FALSE;
+}
+
+static INLINE boolean
+pf_is_ycbcr( enum pipe_format format )
+{
+ return pf_layout(format) == PIPE_FORMAT_LAYOUT_YCBCR ? TRUE : FALSE;
+}
+
+static INLINE boolean
+pf_has_alpha( enum pipe_format format )
+{
+ switch (pf_layout(format)) {
+ case PIPE_FORMAT_LAYOUT_RGBAZS:
+ case PIPE_FORMAT_LAYOUT_MIXED:
+ /* FIXME: pf_get_component_bits( PIPE_FORMAT_A8L8_UNORM, PIPE_FORMAT_COMP_A ) should not return 0 right? */
+ if(format == PIPE_FORMAT_A8_UNORM ||
+ format == PIPE_FORMAT_A8L8_UNORM ||
+ format == PIPE_FORMAT_A8L8_SRGB)
+ return TRUE;
+ return pf_get_component_bits( format, PIPE_FORMAT_COMP_A ) ? TRUE : FALSE;
+ case PIPE_FORMAT_LAYOUT_YCBCR:
+ return FALSE;
+ case PIPE_FORMAT_LAYOUT_DXT:
+ switch (format) {
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT5_RGBA:
+ case PIPE_FORMAT_DXT1_SRGBA:
+ case PIPE_FORMAT_DXT3_SRGBA:
+ case PIPE_FORMAT_DXT5_SRGBA:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ default:
+ assert( 0 );
+ return FALSE;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/include/pipe/p_inlines.h b/src/gallium/include/pipe/p_inlines.h
new file mode 100644
index 0000000000..a5c1e8270a
--- /dev/null
+++ b/src/gallium/include/pipe/p_inlines.h
@@ -0,0 +1,163 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef P_INLINES_H
+#define P_INLINES_H
+
+#include "p_context.h"
+#include "p_defines.h"
+#include "p_screen.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Convenience wrappers for screen buffer functions.
+ */
+
+static INLINE struct pipe_buffer *
+pipe_buffer_create( struct pipe_screen *screen,
+ unsigned alignment, unsigned usage, unsigned size )
+{
+ return screen->buffer_create(screen, alignment, usage, size);
+}
+
+static INLINE struct pipe_buffer *
+pipe_user_buffer_create( struct pipe_screen *screen, void *ptr, unsigned size )
+{
+ return screen->user_buffer_create(screen, ptr, size);
+}
+
+static INLINE void *
+pipe_buffer_map(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned usage)
+{
+ if(screen->buffer_map_range) {
+ unsigned offset = 0;
+ unsigned length = buf->size;
+
+ /* XXX: Actually we should be using/detecting DISCARD
+ * instead of assuming that WRITE implies discard */
+ if((usage & PIPE_BUFFER_USAGE_CPU_WRITE) &&
+ !(usage & PIPE_BUFFER_USAGE_DISCARD))
+ usage |= PIPE_BUFFER_USAGE_CPU_READ;
+
+ return screen->buffer_map_range(screen, buf, offset, length, usage);
+ }
+ else
+ return screen->buffer_map(screen, buf, usage);
+}
+
+static INLINE void
+pipe_buffer_unmap(struct pipe_screen *screen,
+ struct pipe_buffer *buf)
+{
+ screen->buffer_unmap(screen, buf);
+}
+
+static INLINE void *
+pipe_buffer_map_range(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset,
+ unsigned length,
+ unsigned usage)
+{
+ assert(offset < buf->size);
+ assert(offset + length <= buf->size);
+ assert(length);
+ if(screen->buffer_map_range)
+ return screen->buffer_map_range(screen, buf, offset, length, usage);
+ else
+ return screen->buffer_map(screen, buf, usage);
+}
+
+static INLINE void
+pipe_buffer_flush_mapped_range(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset,
+ unsigned length)
+{
+ assert(offset < buf->size);
+ assert(offset + length <= buf->size);
+ assert(length);
+ if(screen->buffer_flush_mapped_range)
+ screen->buffer_flush_mapped_range(screen, buf, offset, length);
+}
+
+static INLINE void
+pipe_buffer_write(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset, unsigned size,
+ const void *data)
+{
+ uint8_t *map;
+
+ assert(offset < buf->size);
+ assert(offset + size <= buf->size);
+ assert(size);
+
+ map = pipe_buffer_map_range(screen, buf, offset, size,
+ PIPE_BUFFER_USAGE_CPU_WRITE |
+ PIPE_BUFFER_USAGE_FLUSH_EXPLICIT);
+ assert(map);
+ if(map) {
+ memcpy(map + offset, data, size);
+ pipe_buffer_flush_mapped_range(screen, buf, offset, size);
+ pipe_buffer_unmap(screen, buf);
+ }
+}
+
+static INLINE void
+pipe_buffer_read(struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset, unsigned size,
+ void *data)
+{
+ uint8_t *map;
+
+ assert(offset < buf->size);
+ assert(offset + size <= buf->size);
+ assert(size);
+
+ map = pipe_buffer_map_range(screen, buf, offset, size, PIPE_BUFFER_USAGE_CPU_READ);
+ assert(map);
+ if(map) {
+ memcpy(data, map + offset, size);
+ pipe_buffer_unmap(screen, buf);
+ }
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* P_INLINES_H */
diff --git a/src/gallium/include/pipe/p_refcnt.h b/src/gallium/include/pipe/p_refcnt.h
new file mode 100644
index 0000000000..1f9088b3e9
--- /dev/null
+++ b/src/gallium/include/pipe/p_refcnt.h
@@ -0,0 +1,96 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef P_REFCNT_H
+#define P_REFCNT_H
+
+
+#include "p_defines.h"
+#include "p_atomic.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct pipe_reference
+{
+ struct pipe_atomic count;
+};
+
+
+static INLINE void
+pipe_reference_init(struct pipe_reference *reference, unsigned count)
+{
+ p_atomic_set(&reference->count, count);
+}
+
+
+static INLINE bool
+pipe_is_referenced(struct pipe_reference *reference)
+{
+ return p_atomic_read(&reference->count) != 0;
+}
+
+
+/**
+ * Set 'ptr' to point to 'reference' and update reference counting.
+ * The old thing pointed to, if any, will be unreferenced first.
+ * 'reference' may be NULL.
+ */
+static INLINE bool
+pipe_reference(struct pipe_reference **ptr, struct pipe_reference *reference)
+{
+ bool destroy = FALSE;
+
+ if(*ptr != reference) {
+ /* bump the reference.count first */
+ if (reference) {
+ assert(pipe_is_referenced(reference));
+ p_atomic_inc(&reference->count);
+ }
+
+ if (*ptr) {
+ assert(pipe_is_referenced(*ptr));
+ if (p_atomic_dec_zero(&(*ptr)->count)) {
+ destroy = TRUE;
+ }
+ }
+
+ *ptr = reference;
+ }
+
+ return destroy;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* P_REFCNT_H */
diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h
new file mode 100644
index 0000000000..3f30c52a16
--- /dev/null
+++ b/src/gallium/include/pipe/p_screen.h
@@ -0,0 +1,296 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ *
+ * Screen, Adapter or GPU
+ *
+ * These are driver functions/facilities that are context independent.
+ */
+
+
+#ifndef P_SCREEN_H
+#define P_SCREEN_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_defines.h"
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** Opaque type */
+struct pipe_fence_handle;
+struct pipe_winsys;
+struct pipe_buffer;
+
+
+
+/**
+ * Gallium screen/adapter context. Basically everything
+ * hardware-specific that doesn't actually require a rendering
+ * context.
+ */
+struct pipe_screen {
+ struct pipe_winsys *winsys;
+
+ void (*destroy)( struct pipe_screen * );
+
+
+ const char *(*get_name)( struct pipe_screen * );
+
+ const char *(*get_vendor)( struct pipe_screen * );
+
+ /**
+ * Query an integer-valued capability/parameter/limit
+ * \param param one of PIPE_CAP_x
+ */
+ int (*get_param)( struct pipe_screen *, int param );
+
+ /**
+ * Query a float-valued capability/parameter/limit
+ * \param param one of PIPE_CAP_x
+ */
+ float (*get_paramf)( struct pipe_screen *, int param );
+
+ /**
+ * Check if the given pipe_format is supported as a texture or
+ * drawing surface.
+ * \param tex_usage bitmask of PIPE_TEXTURE_USAGE_*
+ * \param geom_flags bitmask of PIPE_TEXTURE_GEOM_*
+ */
+ boolean (*is_format_supported)( struct pipe_screen *,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags );
+
+ /**
+ * Create a new texture object, using the given template info.
+ */
+ struct pipe_texture * (*texture_create)(struct pipe_screen *,
+ const struct pipe_texture *templat);
+
+ /**
+ * Create a new texture object, using the given template info, but on top of
+ * existing memory.
+ *
+ * It is assumed that the buffer data is layed out according to the expected
+ * by the hardware. NULL will be returned if any inconsistency is found.
+ */
+ struct pipe_texture * (*texture_blanket)(struct pipe_screen *,
+ const struct pipe_texture *templat,
+ const unsigned *stride,
+ struct pipe_buffer *buffer);
+
+ void (*texture_destroy)(struct pipe_texture *pt);
+
+ /** Get a surface which is a "view" into a texture */
+ struct pipe_surface *(*get_tex_surface)(struct pipe_screen *,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level,
+ unsigned zslice,
+ unsigned usage );
+
+ void (*tex_surface_destroy)(struct pipe_surface *);
+
+
+ /** Get a transfer object for transferring data to/from a texture */
+ struct pipe_transfer *(*get_tex_transfer)(struct pipe_screen *,
+ struct pipe_texture *texture,
+ unsigned face, unsigned level,
+ unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y,
+ unsigned w, unsigned h);
+
+ void (*tex_transfer_destroy)(struct pipe_transfer *);
+
+ void *(*transfer_map)( struct pipe_screen *,
+ struct pipe_transfer *transfer );
+
+ void (*transfer_unmap)( struct pipe_screen *,
+ struct pipe_transfer *transfer );
+
+
+ /**
+ * Create a new buffer.
+ * \param alignment buffer start address alignment in bytes
+ * \param usage bitmask of PIPE_BUFFER_USAGE_x
+ * \param size size in bytes
+ */
+ struct pipe_buffer *(*buffer_create)( struct pipe_screen *screen,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size );
+
+ /**
+ * Create a buffer that wraps user-space data.
+ *
+ * Effectively this schedules a delayed call to buffer_create
+ * followed by an upload of the data at *some point in the future*,
+ * or perhaps never. Basically the allocate/upload is delayed
+ * until the buffer is actually passed to hardware.
+ *
+ * The intention is to provide a quick way to turn regular data
+ * into a buffer, and secondly to avoid a copy operation if that
+ * data subsequently turns out to be only accessed by the CPU.
+ *
+ * Common example is OpenGL vertex buffers that are subsequently
+ * processed either by software TNL in the driver or by passing to
+ * hardware.
+ *
+ * XXX: What happens if the delayed call to buffer_create() fails?
+ *
+ * Note that ptr may be accessed at any time upto the time when the
+ * buffer is destroyed, so the data must not be freed before then.
+ */
+ struct pipe_buffer *(*user_buffer_create)(struct pipe_screen *screen,
+ void *ptr,
+ unsigned bytes);
+
+ /**
+ * Allocate storage for a display target surface.
+ *
+ * Often surfaces which are meant to be blitted to the front screen (i.e.,
+ * display targets) must be allocated with special characteristics, memory
+ * pools, or obtained directly from the windowing system.
+ *
+ * This callback is invoked by the pipe_screenwhen creating a texture marked
+ * with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET flag to get the underlying
+ * buffer storage.
+ */
+ struct pipe_buffer *(*surface_buffer_create)(struct pipe_screen *screen,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride);
+
+
+ /**
+ * Map the entire data store of a buffer object into the client's address.
+ * flags is bitmask of PIPE_BUFFER_USAGE_CPU_READ/WRITE flags.
+ */
+ void *(*buffer_map)( struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned usage );
+ /**
+ * Map a subrange of the buffer data store into the client's address space.
+ *
+ * The returned pointer is always relative to buffer start, regardless of
+ * the specified range. This is different from the ARB_map_buffer_range
+ * semantics because we don't forbid multiple mappings of the same buffer
+ * (yet).
+ */
+ void *(*buffer_map_range)( struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset,
+ unsigned length,
+ unsigned usage);
+
+ /**
+ * Notify a range that was actually written into.
+ *
+ * Can only be used if the buffer was mapped with the
+ * PIPE_BUFFER_USAGE_CPU_WRITE and PIPE_BUFFER_USAGE_FLUSH_EXPLICIT flags
+ * set.
+ *
+ * The range is relative to the buffer start, regardless of the range
+ * specified to buffer_map_range. This is different from the
+ * ARB_map_buffer_range semantics because we don't forbid multiple mappings
+ * of the same buffer (yet).
+ *
+ */
+ void (*buffer_flush_mapped_range)( struct pipe_screen *screen,
+ struct pipe_buffer *buf,
+ unsigned offset,
+ unsigned length);
+
+ /**
+ * Unmap buffer.
+ *
+ * If the buffer was mapped with PIPE_BUFFER_USAGE_CPU_WRITE flag but not
+ * PIPE_BUFFER_USAGE_FLUSH_EXPLICIT then the pipe driver will
+ * assume that the whole buffer was written. This is mostly for backward
+ * compatibility purposes and may affect performance -- the state tracker
+ * should always specify exactly what got written while the buffer was
+ * mapped.
+ */
+ void (*buffer_unmap)( struct pipe_screen *screen,
+ struct pipe_buffer *buf );
+
+ void (*buffer_destroy)( struct pipe_buffer *buf );
+
+
+ /**
+ * Do any special operations to ensure frontbuffer contents are
+ * displayed, eg copy fake frontbuffer.
+ */
+ void (*flush_frontbuffer)( struct pipe_screen *screen,
+ struct pipe_surface *surf,
+ void *context_private );
+
+
+
+ /** Set ptr = fence, with reference counting */
+ void (*fence_reference)( struct pipe_screen *screen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence );
+
+ /**
+ * Checks whether the fence has been signalled.
+ * \param flags driver-specific meaning
+ * \return zero on success.
+ */
+ int (*fence_signalled)( struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags );
+
+ /**
+ * Wait for the fence to finish.
+ * \param flags driver-specific meaning
+ * \return zero on success.
+ */
+ int (*fence_finish)( struct pipe_screen *screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags );
+
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* P_SCREEN_H */
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
new file mode 100644
index 0000000000..5fa6c9af30
--- /dev/null
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -0,0 +1,671 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_TOKEN_H
+#define TGSI_TOKEN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "p_compiler.h"
+
+struct tgsi_version
+{
+ unsigned MajorVersion : 8;
+ unsigned MinorVersion : 8;
+ unsigned Padding : 16;
+};
+
+struct tgsi_header
+{
+ unsigned HeaderSize : 8;
+ unsigned BodySize : 24;
+};
+
+#define TGSI_PROCESSOR_FRAGMENT 0
+#define TGSI_PROCESSOR_VERTEX 1
+#define TGSI_PROCESSOR_GEOMETRY 2
+
+struct tgsi_processor
+{
+ unsigned Processor : 4; /* TGSI_PROCESSOR_ */
+ unsigned Padding : 28;
+};
+
+#define TGSI_TOKEN_TYPE_DECLARATION 0
+#define TGSI_TOKEN_TYPE_IMMEDIATE 1
+#define TGSI_TOKEN_TYPE_INSTRUCTION 2
+
+struct tgsi_token
+{
+ unsigned Type : 4; /**< TGSI_TOKEN_TYPE_x */
+ unsigned NrTokens : 8; /**< UINT */
+ unsigned Padding : 19;
+ unsigned Extended : 1; /**< BOOL */
+};
+
+enum tgsi_file_type {
+ TGSI_FILE_NULL =0,
+ TGSI_FILE_CONSTANT =1,
+ TGSI_FILE_INPUT =2,
+ TGSI_FILE_OUTPUT =3,
+ TGSI_FILE_TEMPORARY =4,
+ TGSI_FILE_SAMPLER =5,
+ TGSI_FILE_ADDRESS =6,
+ TGSI_FILE_IMMEDIATE =7,
+ TGSI_FILE_LOOP =8,
+ TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */
+};
+
+
+#define TGSI_WRITEMASK_NONE 0x00
+#define TGSI_WRITEMASK_X 0x01
+#define TGSI_WRITEMASK_Y 0x02
+#define TGSI_WRITEMASK_XY 0x03
+#define TGSI_WRITEMASK_Z 0x04
+#define TGSI_WRITEMASK_XZ 0x05
+#define TGSI_WRITEMASK_YZ 0x06
+#define TGSI_WRITEMASK_XYZ 0x07
+#define TGSI_WRITEMASK_W 0x08
+#define TGSI_WRITEMASK_XW 0x09
+#define TGSI_WRITEMASK_YW 0x0A
+#define TGSI_WRITEMASK_XYW 0x0B
+#define TGSI_WRITEMASK_ZW 0x0C
+#define TGSI_WRITEMASK_XZW 0x0D
+#define TGSI_WRITEMASK_YZW 0x0E
+#define TGSI_WRITEMASK_XYZW 0x0F
+
+#define TGSI_INTERPOLATE_CONSTANT 0
+#define TGSI_INTERPOLATE_LINEAR 1
+#define TGSI_INTERPOLATE_PERSPECTIVE 2
+#define TGSI_INTERPOLATE_COUNT 3
+
+struct tgsi_declaration
+{
+ unsigned Type : 4; /**< TGSI_TOKEN_TYPE_DECLARATION */
+ unsigned NrTokens : 8; /**< UINT */
+ unsigned File : 4; /**< one of TGSI_FILE_x */
+ unsigned UsageMask : 4; /**< bitmask of TGSI_WRITEMASK_x flags */
+ unsigned Interpolate : 4; /**< one of TGSI_INTERPOLATE_x */
+ unsigned Semantic : 1; /**< BOOL, any semantic info? */
+ unsigned Centroid : 1; /**< centroid sampling? */
+ unsigned Invariant : 1; /**< invariant optimization? */
+ unsigned Padding : 4;
+ unsigned Extended : 1; /**< BOOL */
+};
+
+struct tgsi_declaration_range
+{
+ unsigned First : 16; /**< UINT */
+ unsigned Last : 16; /**< UINT */
+};
+
+#define TGSI_SEMANTIC_POSITION 0
+#define TGSI_SEMANTIC_COLOR 1
+#define TGSI_SEMANTIC_BCOLOR 2 /**< back-face color */
+#define TGSI_SEMANTIC_FOG 3
+#define TGSI_SEMANTIC_PSIZE 4
+#define TGSI_SEMANTIC_GENERIC 5
+#define TGSI_SEMANTIC_NORMAL 6
+#define TGSI_SEMANTIC_FACE 7
+#define TGSI_SEMANTIC_COUNT 8 /**< number of semantic values */
+
+struct tgsi_declaration_semantic
+{
+ unsigned SemanticName : 8; /**< one of TGSI_SEMANTIC_x */
+ unsigned SemanticIndex : 16; /**< UINT */
+ unsigned Padding : 8;
+};
+
+#define TGSI_IMM_FLOAT32 0
+
+struct tgsi_immediate
+{
+ unsigned Type : 4; /**< TGSI_TOKEN_TYPE_IMMEDIATE */
+ unsigned NrTokens : 8; /**< UINT */
+ unsigned DataType : 4; /**< one of TGSI_IMM_x */
+ unsigned Padding : 15;
+ unsigned Extended : 1; /**< BOOL */
+};
+
+union tgsi_immediate_data
+{
+ float Float;
+};
+
+/* TGSI opcodes.
+ *
+ * For more information on semantics of opcodes and
+ * which APIs are known to use which opcodes, see
+ * auxiliary/tgsi/tgsi-instruction-set.txt
+ */
+#define TGSI_OPCODE_ARL 0
+#define TGSI_OPCODE_MOV 1
+#define TGSI_OPCODE_LIT 2
+#define TGSI_OPCODE_RCP 3
+#define TGSI_OPCODE_RSQ 4
+#define TGSI_OPCODE_EXP 5
+#define TGSI_OPCODE_LOG 6
+#define TGSI_OPCODE_MUL 7
+#define TGSI_OPCODE_ADD 8
+#define TGSI_OPCODE_DP3 9
+#define TGSI_OPCODE_DP4 10
+#define TGSI_OPCODE_DST 11
+#define TGSI_OPCODE_MIN 12
+#define TGSI_OPCODE_MAX 13
+#define TGSI_OPCODE_SLT 14
+#define TGSI_OPCODE_SGE 15
+#define TGSI_OPCODE_MAD 16
+#define TGSI_OPCODE_SUB 17
+#define TGSI_OPCODE_LRP 18
+#define TGSI_OPCODE_CND 19
+ /* gap */
+#define TGSI_OPCODE_DP2A 21
+ /* gap */
+#define TGSI_OPCODE_FRC 24
+#define TGSI_OPCODE_CLAMP 25
+#define TGSI_OPCODE_FLR 26
+#define TGSI_OPCODE_ROUND 27
+#define TGSI_OPCODE_EX2 28
+#define TGSI_OPCODE_LG2 29
+#define TGSI_OPCODE_POW 30
+#define TGSI_OPCODE_XPD 31
+ /* gap */
+#define TGSI_OPCODE_ABS 33
+#define TGSI_OPCODE_RCC 34
+#define TGSI_OPCODE_DPH 35
+#define TGSI_OPCODE_COS 36
+#define TGSI_OPCODE_DDX 37
+#define TGSI_OPCODE_DDY 38
+#define TGSI_OPCODE_KILP 39 /* predicated kill */
+#define TGSI_OPCODE_PK2H 40
+#define TGSI_OPCODE_PK2US 41
+#define TGSI_OPCODE_PK4B 42
+#define TGSI_OPCODE_PK4UB 43
+#define TGSI_OPCODE_RFL 44
+#define TGSI_OPCODE_SEQ 45
+#define TGSI_OPCODE_SFL 46
+#define TGSI_OPCODE_SGT 47
+#define TGSI_OPCODE_SIN 48
+#define TGSI_OPCODE_SLE 49
+#define TGSI_OPCODE_SNE 50
+#define TGSI_OPCODE_STR 51
+#define TGSI_OPCODE_TEX 52
+#define TGSI_OPCODE_TXD 53
+#define TGSI_OPCODE_TXP 54
+#define TGSI_OPCODE_UP2H 55
+#define TGSI_OPCODE_UP2US 56
+#define TGSI_OPCODE_UP4B 57
+#define TGSI_OPCODE_UP4UB 58
+#define TGSI_OPCODE_X2D 59
+#define TGSI_OPCODE_ARA 60
+#define TGSI_OPCODE_ARR 61
+#define TGSI_OPCODE_BRA 62
+#define TGSI_OPCODE_CAL 63
+#define TGSI_OPCODE_RET 64
+#define TGSI_OPCODE_SSG 65 /* SGN */
+#define TGSI_OPCODE_CMP 66
+#define TGSI_OPCODE_SCS 67
+#define TGSI_OPCODE_TXB 68
+#define TGSI_OPCODE_NRM 69
+#define TGSI_OPCODE_DIV 70
+#define TGSI_OPCODE_DP2 71
+#define TGSI_OPCODE_TXL 72
+#define TGSI_OPCODE_BRK 73
+#define TGSI_OPCODE_IF 74
+#define TGSI_OPCODE_BGNFOR 75
+#define TGSI_OPCODE_REP 76
+#define TGSI_OPCODE_ELSE 77
+#define TGSI_OPCODE_ENDIF 78
+#define TGSI_OPCODE_ENDFOR 79
+#define TGSI_OPCODE_ENDREP 80
+#define TGSI_OPCODE_PUSHA 81
+#define TGSI_OPCODE_POPA 82
+#define TGSI_OPCODE_CEIL 83
+#define TGSI_OPCODE_I2F 84
+#define TGSI_OPCODE_NOT 85
+#define TGSI_OPCODE_TRUNC 86
+#define TGSI_OPCODE_SHL 87
+#define TGSI_OPCODE_SHR 88
+#define TGSI_OPCODE_AND 89
+#define TGSI_OPCODE_OR 90
+#define TGSI_OPCODE_MOD 91
+#define TGSI_OPCODE_XOR 92
+#define TGSI_OPCODE_SAD 93
+#define TGSI_OPCODE_TXF 94
+#define TGSI_OPCODE_TXQ 95
+#define TGSI_OPCODE_CONT 96
+#define TGSI_OPCODE_EMIT 97
+#define TGSI_OPCODE_ENDPRIM 98
+#define TGSI_OPCODE_BGNLOOP 99
+#define TGSI_OPCODE_BGNSUB 100
+#define TGSI_OPCODE_ENDLOOP 101
+#define TGSI_OPCODE_ENDSUB 102
+#define TGSI_OPCODE_NOISE1 103
+#define TGSI_OPCODE_NOISE2 104
+#define TGSI_OPCODE_NOISE3 105
+#define TGSI_OPCODE_NOISE4 106
+#define TGSI_OPCODE_NOP 107
+ /* gap */
+#define TGSI_OPCODE_NRM4 112
+#define TGSI_OPCODE_CALLNZ 113
+#define TGSI_OPCODE_IFC 114
+#define TGSI_OPCODE_BREAKC 115
+#define TGSI_OPCODE_KIL 116 /* conditional kill */
+#define TGSI_OPCODE_END 117 /* aka HALT */
+#define TGSI_OPCODE_SWZ 118
+#define TGSI_OPCODE_LAST 119
+
+#define TGSI_SAT_NONE 0 /* do not saturate */
+#define TGSI_SAT_ZERO_ONE 1 /* clamp to [0,1] */
+#define TGSI_SAT_MINUS_PLUS_ONE 2 /* clamp to [-1,1] */
+
+/**
+ * Opcode is the operation code to execute. A given operation defines the
+ * semantics how the source registers (if any) are interpreted and what is
+ * written to the destination registers (if any) as a result of execution.
+ *
+ * NumDstRegs and NumSrcRegs is the number of destination and source registers,
+ * respectively. For a given operation code, those numbers are fixed and are
+ * present here only for convenience.
+ *
+ * If Extended is TRUE, it is now executed.
+ *
+ * Saturate controls how are final results in destination registers modified.
+ */
+
+struct tgsi_instruction
+{
+ unsigned Type : 4; /* TGSI_TOKEN_TYPE_INSTRUCTION */
+ unsigned NrTokens : 8; /* UINT */
+ unsigned Opcode : 8; /* TGSI_OPCODE_ */
+ unsigned Saturate : 2; /* TGSI_SAT_ */
+ unsigned NumDstRegs : 2; /* UINT */
+ unsigned NumSrcRegs : 4; /* UINT */
+ unsigned Padding : 3;
+ unsigned Extended : 1; /* BOOL */
+};
+
+/*
+ * If tgsi_instruction::Extended is TRUE, tgsi_instruction_ext follows.
+ *
+ * Then, tgsi_instruction::NumDstRegs of tgsi_dst_register follow.
+ *
+ * Then, tgsi_instruction::NumSrcRegs of tgsi_src_register follow.
+ *
+ * tgsi_instruction::NrTokens contains the total number of words that make the
+ * instruction, including the instruction word.
+ */
+
+#define TGSI_INSTRUCTION_EXT_TYPE_NV 0
+#define TGSI_INSTRUCTION_EXT_TYPE_LABEL 1
+#define TGSI_INSTRUCTION_EXT_TYPE_TEXTURE 2
+#define TGSI_INSTRUCTION_EXT_TYPE_PREDICATE 3
+
+struct tgsi_instruction_ext
+{
+ unsigned Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_ */
+ unsigned Padding : 27;
+ unsigned Extended : 1; /* BOOL */
+};
+
+/*
+ * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_NV, it should
+ * be cast to tgsi_instruction_ext_nv.
+ *
+ * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_LABEL, it
+ * should be cast to tgsi_instruction_ext_label.
+ *
+ * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_TEXTURE, it
+ * should be cast to tgsi_instruction_ext_texture.
+ *
+ * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_PREDICATE, it
+ * should be cast to tgsi_instruction_ext_predicate.
+ *
+ * If tgsi_instruction_ext::Extended is TRUE, another tgsi_instruction_ext
+ * follows.
+ */
+
+#define TGSI_PRECISION_DEFAULT 0
+#define TGSI_PRECISION_FLOAT32 1
+#define TGSI_PRECISION_FLOAT16 2
+#define TGSI_PRECISION_FIXED12 3
+
+#define TGSI_CC_GT 0
+#define TGSI_CC_EQ 1
+#define TGSI_CC_LT 2
+#define TGSI_CC_GE 3
+#define TGSI_CC_LE 4
+#define TGSI_CC_NE 5
+#define TGSI_CC_TR 6
+#define TGSI_CC_FL 7
+
+#define TGSI_SWIZZLE_X 0
+#define TGSI_SWIZZLE_Y 1
+#define TGSI_SWIZZLE_Z 2
+#define TGSI_SWIZZLE_W 3
+
+/**
+ * Precision controls the precision at which the operation should be executed.
+ *
+ * CondDstUpdate enables condition code register writes. When this field is
+ * TRUE, CondDstIndex specifies the index of the condition code register to
+ * update.
+ *
+ * CondFlowEnable enables conditional execution of the operation. When this
+ * field is TRUE, CondFlowIndex specifies the index of the condition code
+ * register to test against CondMask with component swizzle controled by
+ * CondSwizzleX, CondSwizzleY, CondSwizzleZ and CondSwizzleW. If the test fails,
+ * the operation is not executed.
+ */
+
+struct tgsi_instruction_ext_nv
+{
+ unsigned Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_NV */
+ unsigned Precision : 4; /* TGSI_PRECISION_ */
+ unsigned CondDstIndex : 4; /* UINT */
+ unsigned CondFlowIndex : 4; /* UINT */
+ unsigned CondMask : 4; /* TGSI_CC_ */
+ unsigned CondSwizzleX : 2; /* TGSI_SWIZZLE_ */
+ unsigned CondSwizzleY : 2; /* TGSI_SWIZZLE_ */
+ unsigned CondSwizzleZ : 2; /* TGSI_SWIZZLE_ */
+ unsigned CondSwizzleW : 2; /* TGSI_SWIZZLE_ */
+ unsigned CondDstUpdate : 1; /* BOOL */
+ unsigned CondFlowEnable : 1; /* BOOL */
+ unsigned Padding : 1;
+ unsigned Extended : 1; /* BOOL */
+};
+
+struct tgsi_instruction_ext_label
+{
+ unsigned Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_LABEL */
+ unsigned Label : 24; /* UINT */
+ unsigned Padding : 3;
+ unsigned Extended : 1; /* BOOL */
+};
+
+#define TGSI_TEXTURE_UNKNOWN 0
+#define TGSI_TEXTURE_1D 1
+#define TGSI_TEXTURE_2D 2
+#define TGSI_TEXTURE_3D 3
+#define TGSI_TEXTURE_CUBE 4
+#define TGSI_TEXTURE_RECT 5
+#define TGSI_TEXTURE_SHADOW1D 6
+#define TGSI_TEXTURE_SHADOW2D 7
+#define TGSI_TEXTURE_SHADOWRECT 8
+#define TGSI_TEXTURE_COUNT 9
+
+struct tgsi_instruction_ext_texture
+{
+ unsigned Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_TEXTURE */
+ unsigned Texture : 8; /* TGSI_TEXTURE_ */
+ unsigned Padding : 19;
+ unsigned Extended : 1; /* BOOL */
+};
+
+struct tgsi_instruction_ext_predicate
+{
+ unsigned Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_PREDICATE */
+ unsigned PredDstIndex : 4; /* UINT */
+ unsigned PredWriteMask : 4; /* TGSI_WRITEMASK_ */
+ unsigned Padding : 19;
+ unsigned Extended : 1; /* BOOL */
+};
+
+/**
+ * File specifies the register array to access.
+ *
+ * Index specifies the element number of a register in the register file.
+ *
+ * If Indirect is TRUE, Index should be offset by the X component of a source
+ * register that follows. The register can be now fetched into local storage
+ * for further processing.
+ *
+ * If Negate is TRUE, all components of the fetched register are negated.
+ *
+ * The fetched register components are swizzled according to SwizzleX, SwizzleY,
+ * SwizzleZ and SwizzleW.
+ *
+ * If Extended is TRUE, any further modifications to the source register are
+ * made to this temporary storage.
+ */
+
+struct tgsi_src_register
+{
+ unsigned File : 4; /* TGSI_FILE_ */
+ unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
+ unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
+ unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
+ unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
+ unsigned Negate : 1; /* BOOL */
+ unsigned Indirect : 1; /* BOOL */
+ unsigned Dimension : 1; /* BOOL */
+ int Index : 16; /* SINT */
+ unsigned Extended : 1; /* BOOL */
+};
+
+/**
+ * If tgsi_src_register::Extended is TRUE, tgsi_src_register_ext follows.
+ *
+ * Then, if tgsi_src_register::Indirect is TRUE, another tgsi_src_register
+ * follows.
+ *
+ * Then, if tgsi_src_register::Dimension is TRUE, tgsi_dimension follows.
+ */
+
+#define TGSI_SRC_REGISTER_EXT_TYPE_SWZ 0
+#define TGSI_SRC_REGISTER_EXT_TYPE_MOD 1
+
+struct tgsi_src_register_ext
+{
+ unsigned Type : 4; /* TGSI_SRC_REGISTER_EXT_TYPE_ */
+ unsigned Padding : 27;
+ unsigned Extended : 1; /* BOOL */
+};
+
+/**
+ * If tgsi_src_register_ext::Type is TGSI_SRC_REGISTER_EXT_TYPE_SWZ,
+ * it should be cast to tgsi_src_register_ext_swz.
+ *
+ * If tgsi_src_register_ext::Type is TGSI_SRC_REGISTER_EXT_TYPE_MOD,
+ * it should be cast to tgsi_src_register_ext_mod.
+ *
+ * If tgsi_dst_register_ext::Extended is TRUE, another tgsi_dst_register_ext
+ * follows.
+ */
+
+#define TGSI_EXTSWIZZLE_X TGSI_SWIZZLE_X
+#define TGSI_EXTSWIZZLE_Y TGSI_SWIZZLE_Y
+#define TGSI_EXTSWIZZLE_Z TGSI_SWIZZLE_Z
+#define TGSI_EXTSWIZZLE_W TGSI_SWIZZLE_W
+#define TGSI_EXTSWIZZLE_ZERO 4
+#define TGSI_EXTSWIZZLE_ONE 5
+
+/**
+ * ExtSwizzleX, ExtSwizzleY, ExtSwizzleZ and ExtSwizzleW swizzle the source
+ * register in an extended manner.
+ *
+ * NegateX, NegateY, NegateZ and NegateW negate individual components of the
+ * source register.
+ *
+ * NOTE: To simplify matter, if this token is present, the corresponding Swizzle
+ * and Negate fields in tgsi_src_register should be set to X,Y,Z,W
+ * and FALSE, respectively.
+ */
+
+struct tgsi_src_register_ext_swz
+{
+ unsigned Type : 4; /* TGSI_SRC_REGISTER_EXT_TYPE_SWZ */
+ unsigned ExtSwizzleX : 4; /* TGSI_EXTSWIZZLE_ */
+ unsigned ExtSwizzleY : 4; /* TGSI_EXTSWIZZLE_ */
+ unsigned ExtSwizzleZ : 4; /* TGSI_EXTSWIZZLE_ */
+ unsigned ExtSwizzleW : 4; /* TGSI_EXTSWIZZLE_ */
+ unsigned NegateX : 1; /* BOOL */
+ unsigned NegateY : 1; /* BOOL */
+ unsigned NegateZ : 1; /* BOOL */
+ unsigned NegateW : 1; /* BOOL */
+ unsigned Padding : 7;
+ unsigned Extended : 1; /* BOOL */
+};
+
+/**
+ * Extra src register modifiers
+ *
+ * If Complement is TRUE, the source register is modified by subtracting it
+ * from 1.0.
+ *
+ * If Bias is TRUE, the source register is modified by subtracting 0.5 from it.
+ *
+ * If Scale2X is TRUE, the source register is modified by multiplying it by 2.0.
+ *
+ * If Absolute is TRUE, the source register is modified by removing the sign.
+ *
+ * If Negate is TRUE, the source register is modified by negating it.
+ */
+
+struct tgsi_src_register_ext_mod
+{
+ unsigned Type : 4; /* TGSI_SRC_REGISTER_EXT_TYPE_MOD */
+ unsigned Complement : 1; /* BOOL */
+ unsigned Bias : 1; /* BOOL */
+ unsigned Scale2X : 1; /* BOOL */
+ unsigned Absolute : 1; /* BOOL */
+ unsigned Negate : 1; /* BOOL */
+ unsigned Padding : 22;
+ unsigned Extended : 1; /* BOOL */
+};
+
+struct tgsi_dimension
+{
+ unsigned Indirect : 1; /* BOOL */
+ unsigned Dimension : 1; /* BOOL */
+ unsigned Padding : 13;
+ int Index : 16; /* SINT */
+ unsigned Extended : 1; /* BOOL */
+};
+
+struct tgsi_dst_register
+{
+ unsigned File : 4; /* TGSI_FILE_ */
+ unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
+ unsigned Indirect : 1; /* BOOL */
+ unsigned Dimension : 1; /* BOOL */
+ int Index : 16; /* SINT */
+ unsigned Padding : 5;
+ unsigned Extended : 1; /* BOOL */
+};
+
+/*
+ * If tgsi_dst_register::Extended is TRUE, tgsi_dst_register_ext follows.
+ *
+ * Then, if tgsi_dst_register::Indirect is TRUE, tgsi_src_register follows.
+ */
+
+#define TGSI_DST_REGISTER_EXT_TYPE_CONDCODE 0
+#define TGSI_DST_REGISTER_EXT_TYPE_MODULATE 1
+#define TGSI_DST_REGISTER_EXT_TYPE_PREDICATE 2
+
+struct tgsi_dst_register_ext
+{
+ unsigned Type : 4; /* TGSI_DST_REGISTER_EXT_TYPE_ */
+ unsigned Padding : 27;
+ unsigned Extended : 1; /* BOOL */
+};
+
+/**
+ * Extra destination register modifiers
+ *
+ * If tgsi_dst_register_ext::Type is TGSI_DST_REGISTER_EXT_TYPE_CONDCODE,
+ * it should be cast to tgsi_dst_register_ext_condcode.
+ *
+ * If tgsi_dst_register_ext::Type is TGSI_DST_REGISTER_EXT_TYPE_MODULATE,
+ * it should be cast to tgsi_dst_register_ext_modulate.
+ *
+ * If tgsi_dst_register_ext::Type is TGSI_DST_REGISTER_EXT_TYPE_PREDICATE,
+ * it should be cast to tgsi_dst_register_ext_predicate.
+ *
+ * If tgsi_dst_register_ext::Extended is TRUE, another tgsi_dst_register_ext
+ * follows.
+ */
+struct tgsi_dst_register_ext_concode
+{
+ unsigned Type : 4; /* TGSI_DST_REGISTER_EXT_TYPE_CONDCODE */
+ unsigned CondMask : 4; /* TGSI_CC_ */
+ unsigned CondSwizzleX : 2; /* TGSI_SWIZZLE_ */
+ unsigned CondSwizzleY : 2; /* TGSI_SWIZZLE_ */
+ unsigned CondSwizzleZ : 2; /* TGSI_SWIZZLE_ */
+ unsigned CondSwizzleW : 2; /* TGSI_SWIZZLE_ */
+ unsigned CondSrcIndex : 4; /* UINT */
+ unsigned Padding : 11;
+ unsigned Extended : 1; /* BOOL */
+};
+
+#define TGSI_MODULATE_1X 0
+#define TGSI_MODULATE_2X 1
+#define TGSI_MODULATE_4X 2
+#define TGSI_MODULATE_8X 3
+#define TGSI_MODULATE_HALF 4
+#define TGSI_MODULATE_QUARTER 5
+#define TGSI_MODULATE_EIGHTH 6
+#define TGSI_MODULATE_COUNT 7
+
+struct tgsi_dst_register_ext_modulate
+{
+ unsigned Type : 4; /* TGSI_DST_REGISTER_EXT_TYPE_MODULATE */
+ unsigned Modulate : 4; /* TGSI_MODULATE_ */
+ unsigned Padding : 23;
+ unsigned Extended : 1; /* BOOL */
+};
+
+/*
+ * Currently, the following constraints apply.
+ *
+ * - PredSwizzleXYZW is either set to identity or replicate.
+ * - PredSrcIndex is 0.
+ */
+
+struct tgsi_dst_register_ext_predicate
+{
+ unsigned Type : 4; /* TGSI_DST_REGISTER_EXT_TYPE_PREDICATE */
+ unsigned PredSwizzleX : 2; /* TGSI_SWIZZLE_ */
+ unsigned PredSwizzleY : 2; /* TGSI_SWIZZLE_ */
+ unsigned PredSwizzleZ : 2; /* TGSI_SWIZZLE_ */
+ unsigned PredSwizzleW : 2; /* TGSI_SWIZZLE_ */
+ unsigned PredSrcIndex : 4; /* UINT */
+ unsigned Negate : 1; /* BOOL */
+ unsigned Padding : 14;
+ unsigned Extended : 1; /* BOOL */
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TGSI_TOKEN_H */
+
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
new file mode 100644
index 0000000000..626bedb35a
--- /dev/null
+++ b/src/gallium/include/pipe/p_state.h
@@ -0,0 +1,412 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ *
+ * Abstract graphics pipe state objects.
+ *
+ * Basic notes:
+ * 1. Want compact representations, so we use bitfields.
+ * 2. Put bitfields before other (GLfloat) fields.
+ */
+
+
+#ifndef PIPE_STATE_H
+#define PIPE_STATE_H
+
+#include "p_compiler.h"
+#include "p_defines.h"
+#include "p_format.h"
+#include "p_refcnt.h"
+#include "p_screen.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Implementation limits
+ */
+#define PIPE_MAX_ATTRIBS 32
+#define PIPE_MAX_CLIP_PLANES 6
+#define PIPE_MAX_COLOR_BUFS 8
+#define PIPE_MAX_CONSTANT 32
+#define PIPE_MAX_SAMPLERS 16
+#define PIPE_MAX_SHADER_INPUTS 16
+#define PIPE_MAX_SHADER_OUTPUTS 16
+#define PIPE_MAX_TEXTURE_LEVELS 16
+
+
+/* fwd decls */
+struct pipe_surface;
+
+
+/**
+ * The driver will certainly subclass this to include actual memory
+ * management information.
+ */
+struct pipe_buffer
+{
+ struct pipe_reference reference;
+ unsigned size;
+ struct pipe_screen *screen;
+ unsigned alignment;
+ unsigned usage;
+};
+
+
+/**
+ * Primitive (point/line/tri) rasterization info
+ */
+struct pipe_rasterizer_state
+{
+ unsigned flatshade:1;
+ unsigned light_twoside:1;
+ unsigned front_winding:2; /**< PIPE_WINDING_x */
+ unsigned cull_mode:2; /**< PIPE_WINDING_x */
+ unsigned fill_cw:2; /**< PIPE_POLYGON_MODE_x */
+ unsigned fill_ccw:2; /**< PIPE_POLYGON_MODE_x */
+ unsigned offset_cw:1;
+ unsigned offset_ccw:1;
+ unsigned scissor:1;
+ unsigned poly_smooth:1;
+ unsigned poly_stipple_enable:1;
+ unsigned point_smooth:1;
+ unsigned point_sprite:1;
+ unsigned point_size_per_vertex:1; /**< size computed in vertex shader */
+ unsigned multisample:1; /* XXX maybe more ms state in future */
+ unsigned line_smooth:1;
+ unsigned line_stipple_enable:1;
+ unsigned line_stipple_factor:8; /**< [1..256] actually */
+ unsigned line_stipple_pattern:16;
+ unsigned line_last_pixel:1;
+
+ /**
+ * Vertex coordinates are pre-transformed to screen space. Skip
+ * the vertex shader, clipping and viewport processing. Note that
+ * a vertex shader is still needed though, to indicate the mapping
+ * from vertex elements to fragment shader input semantics.
+ */
+ unsigned bypass_vs_clip_and_viewport:1;
+
+ unsigned flatshade_first:1; /**< take color attribute from the first vertex of a primitive */
+ unsigned gl_rasterization_rules:1; /**< enable tweaks for GL rasterization? */
+
+ float line_width;
+ float point_size; /**< used when no per-vertex size */
+ float point_size_min; /* XXX - temporary, will go away */
+ float point_size_max; /* XXX - temporary, will go away */
+ float offset_units;
+ float offset_scale;
+ ubyte sprite_coord_mode[PIPE_MAX_SHADER_OUTPUTS]; /**< PIPE_SPRITE_COORD_ */
+};
+
+
+struct pipe_poly_stipple
+{
+ unsigned stipple[32];
+};
+
+
+struct pipe_viewport_state
+{
+ float scale[4];
+ float translate[4];
+};
+
+
+struct pipe_scissor_state
+{
+ unsigned minx:16;
+ unsigned miny:16;
+ unsigned maxx:16;
+ unsigned maxy:16;
+};
+
+
+struct pipe_clip_state
+{
+ float ucp[PIPE_MAX_CLIP_PLANES][4];
+ unsigned nr;
+};
+
+
+/**
+ * Constants for vertex/fragment shaders
+ */
+struct pipe_constant_buffer
+{
+ struct pipe_buffer *buffer;
+};
+
+
+struct pipe_shader_state
+{
+ const struct tgsi_token *tokens;
+};
+
+
+struct pipe_depth_state
+{
+ unsigned enabled:1; /**< depth test enabled? */
+ unsigned writemask:1; /**< allow depth buffer writes? */
+ unsigned func:3; /**< depth test func (PIPE_FUNC_x) */
+ unsigned occlusion_count:1; /**< do occlusion counting? */
+};
+
+
+struct pipe_stencil_state
+{
+ unsigned enabled:1; /**< stencil[0]: stencil enabled, stencil[1]: two-side enabled */
+ unsigned func:3; /**< PIPE_FUNC_x */
+ unsigned fail_op:3; /**< PIPE_STENCIL_OP_x */
+ unsigned zpass_op:3; /**< PIPE_STENCIL_OP_x */
+ unsigned zfail_op:3; /**< PIPE_STENCIL_OP_x */
+ ubyte ref_value;
+ ubyte valuemask;
+ ubyte writemask;
+};
+
+
+struct pipe_alpha_state
+{
+ unsigned enabled:1;
+ unsigned func:3; /**< PIPE_FUNC_x */
+ float ref_value; /**< reference value */
+};
+
+
+struct pipe_depth_stencil_alpha_state
+{
+ struct pipe_depth_state depth;
+ struct pipe_stencil_state stencil[2]; /**< [0] = front, [1] = back */
+ struct pipe_alpha_state alpha;
+};
+
+
+struct pipe_blend_state
+{
+ unsigned blend_enable:1;
+
+ unsigned rgb_func:3; /**< PIPE_BLEND_x */
+ unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */
+ unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
+
+ unsigned alpha_func:3; /**< PIPE_BLEND_x */
+ unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */
+ unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
+
+ unsigned logicop_enable:1;
+ unsigned logicop_func:4; /**< PIPE_LOGICOP_x */
+
+ unsigned colormask:4; /**< bitmask of PIPE_MASK_R/G/B/A */
+ unsigned dither:1;
+};
+
+
+struct pipe_blend_color
+{
+ float color[4];
+};
+
+
+struct pipe_framebuffer_state
+{
+ unsigned width, height;
+
+ /** multiple colorbuffers for multiple render targets */
+ unsigned nr_cbufs;
+ struct pipe_surface *cbufs[PIPE_MAX_COLOR_BUFS];
+
+ struct pipe_surface *zsbuf; /**< Z/stencil buffer */
+};
+
+
+/**
+ * Texture sampler state.
+ */
+struct pipe_sampler_state
+{
+ unsigned wrap_s:3; /**< PIPE_TEX_WRAP_x */
+ unsigned wrap_t:3; /**< PIPE_TEX_WRAP_x */
+ unsigned wrap_r:3; /**< PIPE_TEX_WRAP_x */
+ unsigned min_img_filter:2; /**< PIPE_TEX_FILTER_x */
+ unsigned min_mip_filter:2; /**< PIPE_TEX_MIPFILTER_x */
+ unsigned mag_img_filter:2; /**< PIPE_TEX_FILTER_x */
+ unsigned compare_mode:1; /**< PIPE_TEX_COMPARE_x */
+ unsigned compare_func:3; /**< PIPE_FUNC_x */
+ unsigned normalized_coords:1; /**< Are coords normalized to [0,1]? */
+ unsigned prefilter:4; /**< Wierd sampling state exposed by some api's */
+ float lod_bias; /**< LOD/lambda bias */
+ float min_lod, max_lod; /**< LOD clamp range, after bias */
+ float border_color[4];
+ float max_anisotropy;
+};
+
+
+/**
+ * 2D surface. This is basically a view into a memory buffer.
+ * May be a renderbuffer, texture mipmap level, etc.
+ */
+struct pipe_surface
+{
+ struct pipe_reference reference;
+ enum pipe_format format; /**< PIPE_FORMAT_x */
+ unsigned width; /**< logical width in pixels */
+ unsigned height; /**< logical height in pixels */
+ unsigned layout; /**< PIPE_SURFACE_LAYOUT_x */
+ unsigned offset; /**< offset from start of buffer, in bytes */
+ unsigned usage; /**< PIPE_BUFFER_USAGE_* */
+
+ unsigned zslice;
+ struct pipe_texture *texture; /**< texture into which this is a view */
+ unsigned face;
+ unsigned level;
+};
+
+
+/**
+ * Transfer object. For data transfer to/from a texture.
+ */
+struct pipe_transfer
+{
+ enum pipe_format format; /**< PIPE_FORMAT_x */
+ unsigned x; /**< x offset from start of texture image */
+ unsigned y; /**< y offset from start of texture image */
+ unsigned width; /**< logical width in pixels */
+ unsigned height; /**< logical height in pixels */
+ struct pipe_format_block block;
+ unsigned nblocksx; /**< allocated width in blocks */
+ unsigned nblocksy; /**< allocated height in blocks */
+ unsigned stride; /**< stride in bytes between rows of blocks */
+ unsigned usage; /**< PIPE_TRANSFER_* */
+
+ struct pipe_texture *texture; /**< texture to transfer to/from */
+ unsigned face;
+ unsigned level;
+ unsigned zslice;
+};
+
+
+/**
+ * Texture object.
+ */
+struct pipe_texture
+{
+ struct pipe_reference reference;
+
+ enum pipe_texture_target target; /**< PIPE_TEXTURE_x */
+ enum pipe_format format; /**< PIPE_FORMAT_x */
+
+ unsigned width[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned height[PIPE_MAX_TEXTURE_LEVELS];
+ unsigned depth[PIPE_MAX_TEXTURE_LEVELS];
+
+ struct pipe_format_block block;
+ unsigned nblocksx[PIPE_MAX_TEXTURE_LEVELS]; /**< allocated width in blocks */
+ unsigned nblocksy[PIPE_MAX_TEXTURE_LEVELS]; /**< allocated height in blocks */
+
+ unsigned last_level:8; /**< Index of last mipmap level present/defined */
+
+ unsigned nr_samples:8; /**< for multisampled surfaces, nr of samples */
+
+ unsigned tex_usage; /* PIPE_TEXTURE_USAGE_* */
+
+ struct pipe_screen *screen; /**< screen that this texture belongs to */
+};
+
+
+/**
+ * A vertex buffer. Typically, all the vertex data/attributes for
+ * drawing something will be in one buffer. But it's also possible, for
+ * example, to put colors in one buffer and texcoords in another.
+ */
+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_buffer *buffer; /**< the actual buffer */
+};
+
+
+/**
+ * Information to describe a vertex attribute (position, color, etc)
+ */
+struct pipe_vertex_element
+{
+ /** Offset of this attribute, in bytes, from the start of the vertex */
+ unsigned src_offset;
+
+ /** Which vertex_buffer (as given to pipe->set_vertex_buffer()) does
+ * this attribute live in?
+ */
+ unsigned vertex_buffer_index:8;
+ unsigned nr_components:8;
+
+ enum pipe_format src_format; /**< PIPE_FORMAT_* */
+};
+
+
+/* Reference counting helper functions */
+static INLINE void
+pipe_buffer_reference(struct pipe_buffer **ptr, struct pipe_buffer *buf)
+{
+ struct pipe_buffer *old_buf = *ptr;
+
+ if (pipe_reference((struct pipe_reference **)ptr, &buf->reference))
+ old_buf->screen->buffer_destroy(old_buf);
+}
+
+static INLINE void
+pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
+{
+ struct pipe_surface *old_surf = *ptr;
+
+ if (pipe_reference((struct pipe_reference **)ptr, &surf->reference))
+ old_surf->texture->screen->tex_surface_destroy(old_surf);
+}
+
+static INLINE void
+pipe_texture_reference(struct pipe_texture **ptr, struct pipe_texture *tex)
+{
+ struct pipe_texture *old_tex = *ptr;
+
+ if (pipe_reference((struct pipe_reference **)ptr, &tex->reference))
+ old_tex->screen->texture_destroy(old_tex);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/include/pipe/p_thread.h b/src/gallium/include/pipe/p_thread.h
new file mode 100644
index 0000000000..b1606dc652
--- /dev/null
+++ b/src/gallium/include/pipe/p_thread.h
@@ -0,0 +1,279 @@
+/**************************************************************************
+ *
+ * Copyright 1999-2006 Brian Paul
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ *
+ * Thread, mutex, condition var and thread-specific data functions.
+ */
+
+
+#ifndef _P_THREAD2_H_
+#define _P_THREAD2_H_
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h" /* for assert */
+
+
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU)
+
+#include <pthread.h> /* POSIX threads headers */
+#include <stdio.h> /* for perror() */
+
+#define PIPE_THREAD_HAVE_CONDVAR
+
+typedef pthread_t pipe_thread;
+
+#define PIPE_THREAD_ROUTINE( name, param ) \
+ void *name( void *param )
+
+static INLINE pipe_thread pipe_thread_create( void *(* routine)( void *), void *param )
+{
+ pipe_thread thread;
+ if (pthread_create( &thread, NULL, routine, param ))
+ return 0;
+ return thread;
+}
+
+static INLINE int pipe_thread_wait( pipe_thread thread )
+{
+ return pthread_join( thread, NULL );
+}
+
+static INLINE int pipe_thread_destroy( pipe_thread thread )
+{
+ return pthread_detach( thread );
+}
+
+typedef pthread_mutex_t pipe_mutex;
+typedef pthread_cond_t pipe_condvar;
+
+#define pipe_static_mutex(mutex) \
+ static pipe_mutex mutex = PTHREAD_MUTEX_INITIALIZER
+
+#define pipe_mutex_init(mutex) \
+ (void) pthread_mutex_init(&(mutex), NULL)
+
+#define pipe_mutex_destroy(mutex) \
+ pthread_mutex_destroy(&(mutex))
+
+#define pipe_mutex_lock(mutex) \
+ (void) pthread_mutex_lock(&(mutex))
+
+#define pipe_mutex_unlock(mutex) \
+ (void) pthread_mutex_unlock(&(mutex))
+
+#define pipe_static_condvar(mutex) \
+ static pipe_condvar mutex = PTHREAD_COND_INITIALIZER
+
+#define pipe_condvar_init(cond) \
+ pthread_cond_init(&(cond), NULL)
+
+#define pipe_condvar_destroy(cond) \
+ pthread_cond_destroy(&(cond))
+
+#define pipe_condvar_wait(cond, mutex) \
+ pthread_cond_wait(&(cond), &(mutex))
+
+#define pipe_condvar_signal(cond) \
+ pthread_cond_signal(&(cond))
+
+#define pipe_condvar_broadcast(cond) \
+ pthread_cond_broadcast(&(cond))
+
+
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+
+#include <windows.h>
+
+typedef HANDLE pipe_thread;
+
+#define PIPE_THREAD_ROUTINE( name, param ) \
+ void * WINAPI name( void *param )
+
+static INLINE pipe_thread pipe_thread_create( void *(WINAPI * routine)( void *), void *param )
+{
+ DWORD id;
+ return CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) routine, param, 0, &id );
+}
+
+static INLINE int pipe_thread_wait( pipe_thread thread )
+{
+ if (WaitForSingleObject( thread, INFINITE ) == WAIT_OBJECT_0)
+ return 0;
+ return -1;
+}
+
+static INLINE int pipe_thread_destroy( pipe_thread thread )
+{
+ if (CloseHandle( thread ))
+ return 0;
+ return -1;
+}
+
+typedef CRITICAL_SECTION pipe_mutex;
+
+#define pipe_static_mutex(mutex) \
+ /*static*/ pipe_mutex mutex = {0,0,0,0,0,0}
+
+#define pipe_mutex_init(mutex) \
+ InitializeCriticalSection(&mutex)
+
+#define pipe_mutex_destroy(mutex) \
+ DeleteCriticalSection(&mutex)
+
+#define pipe_mutex_lock(mutex) \
+ EnterCriticalSection(&mutex)
+
+#define pipe_mutex_unlock(mutex) \
+ LeaveCriticalSection(&mutex)
+
+/* XXX: dummy definitions, make it compile */
+
+typedef unsigned pipe_condvar;
+
+#define pipe_condvar_init(condvar) \
+ (void) condvar
+
+#define pipe_condvar_broadcast(condvar) \
+ (void) condvar
+
+#else
+
+/** Dummy definitions */
+
+typedef unsigned pipe_thread;
+typedef unsigned pipe_mutex;
+typedef unsigned pipe_condvar;
+
+#define pipe_static_mutex(mutex) \
+ static pipe_mutex mutex = 0
+
+#define pipe_mutex_init(mutex) \
+ (void) mutex
+
+#define pipe_mutex_destroy(mutex) \
+ (void) mutex
+
+#define pipe_mutex_lock(mutex) \
+ (void) mutex
+
+#define pipe_mutex_unlock(mutex) \
+ (void) mutex
+
+#define pipe_static_condvar(condvar) \
+ static unsigned condvar = 0
+
+#define pipe_condvar_init(condvar) \
+ (void) condvar
+
+#define pipe_condvar_destroy(condvar) \
+ (void) condvar
+
+#define pipe_condvar_wait(condvar, mutex) \
+ (void) condvar
+
+#define pipe_condvar_signal(condvar) \
+ (void) condvar
+
+#define pipe_condvar_broadcast(condvar) \
+ (void) condvar
+
+
+#endif /* PIPE_OS_? */
+
+
+
+/*
+ * Thread-specific data.
+ */
+
+typedef struct {
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU)
+ pthread_key_t key;
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ DWORD key;
+#endif
+ int initMagic;
+} pipe_tsd;
+
+
+#define PIPE_TSD_INIT_MAGIC 0xff8adc98
+
+
+static INLINE void
+pipe_tsd_init(pipe_tsd *tsd)
+{
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU)
+ if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) {
+ perror("pthread_key_create(): failed to allocate key for thread specific data");
+ exit(-1);
+ }
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ assert(0);
+#endif
+ tsd->initMagic = PIPE_TSD_INIT_MAGIC;
+}
+
+static INLINE void *
+pipe_tsd_get(pipe_tsd *tsd)
+{
+ if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
+ pipe_tsd_init(tsd);
+ }
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU)
+ return pthread_getspecific(tsd->key);
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ assert(0);
+ return NULL;
+#else
+ assert(0);
+ return NULL;
+#endif
+}
+
+static INLINE void
+pipe_tsd_set(pipe_tsd *tsd, void *value)
+{
+ if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
+ pipe_tsd_init(tsd);
+ }
+#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU)
+ if (pthread_setspecific(tsd->key, value) != 0) {
+ perror("pthread_set_specific() failed");
+ exit(-1);
+ }
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+ assert(0);
+#else
+ assert(0);
+#endif
+}
+
+
+
+#endif /* _P_THREAD2_H_ */
diff --git a/src/gallium/include/state_tracker/dri1_api.h b/src/gallium/include/state_tracker/dri1_api.h
new file mode 100644
index 0000000000..b173ba3683
--- /dev/null
+++ b/src/gallium/include/state_tracker/dri1_api.h
@@ -0,0 +1,82 @@
+#ifndef _DRI1_API_H_
+#define _DRI1_API_H_
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_format.h"
+
+#include "state_tracker/drm_api.h"
+
+#include <drm.h>
+
+struct pipe_screen;
+struct pipe_winsys;
+struct pipe_buffer;
+struct pipe_context;
+struct pipe_texture;
+
+struct dri1_api_version
+{
+ int major;
+ int minor;
+ int patch_level;
+};
+
+/**
+ * This callback struct is intended for drivers that need to take
+ * the hardware lock on command submission.
+ */
+
+struct dri1_api_lock_funcs
+{
+ void (*lock) (struct pipe_context * pipe);
+ void (*unlock) (struct pipe_context * locked_pipe);
+ boolean(*is_locked) (struct pipe_context * locked_pipe);
+ boolean(*is_lock_lost) (struct pipe_context * locked_pipe);
+ void (*clear_lost_lock) (struct pipe_context * locked_pipe);
+};
+
+struct dri1_api
+{
+ /**
+ * For flushing to the front buffer. A driver should implement one and only
+ * one of the functions below. The present_locked functions allows a dri1
+ * driver to pageflip.
+ */
+
+ /*@{ */
+
+ struct pipe_surface *(*front_srf_locked) (struct pipe_context *
+ locked_pipe);
+
+ void (*present_locked) (struct pipe_context * locked_pipe,
+ struct pipe_surface * surf,
+ const struct drm_clip_rect * rect,
+ unsigned int num_clip,
+ int x_draw, int y_draw,
+ const struct drm_clip_rect * src_bbox,
+ struct pipe_fence_handle ** fence);
+ /*@} */
+};
+
+struct dri1_create_screen_arg
+{
+ struct drm_create_screen_arg base;
+
+ struct dri1_api_lock_funcs *lf;
+ void *ddx_info;
+ int ddx_info_size;
+ void *sarea;
+
+ struct dri1_api_version ddx_version;
+ struct dri1_api_version dri_version;
+ struct dri1_api_version drm_version;
+
+ /*
+ * out parameters;
+ */
+
+ struct dri1_api *api;
+};
+
+#endif
diff --git a/src/gallium/include/state_tracker/drm_api.h b/src/gallium/include/state_tracker/drm_api.h
new file mode 100644
index 0000000000..4d1259e1ee
--- /dev/null
+++ b/src/gallium/include/state_tracker/drm_api.h
@@ -0,0 +1,69 @@
+
+#ifndef _DRM_API_H_
+#define _DRM_API_H_
+
+#include "pipe/p_compiler.h"
+
+struct pipe_screen;
+struct pipe_winsys;
+struct pipe_buffer;
+struct pipe_context;
+struct pipe_texture;
+
+enum drm_create_screen_mode {
+ DRM_CREATE_NORMAL = 0,
+ DRM_CREATE_DRI1,
+ DRM_CREATE_DRIVER = 1024,
+ DRM_CREATE_MAX
+};
+
+/**
+ * Modes other than DRM_CREATE_NORMAL derive from this struct.
+ */
+/*@{*/
+struct drm_create_screen_arg {
+ enum drm_create_screen_mode mode;
+};
+/*@}*/
+
+struct drm_api
+{
+ /**
+ * Special buffer functions
+ */
+ /*@{*/
+ struct pipe_screen* (*create_screen)(struct drm_api *api, int drm_fd,
+ struct drm_create_screen_arg *arg);
+ struct pipe_context* (*create_context)(struct drm_api *api,
+ struct pipe_screen *screen);
+ /*@}*/
+
+ /**
+ * Special buffer functions
+ */
+ /*@{*/
+ struct pipe_texture*
+ (*texture_from_shared_handle)(struct drm_api *api,
+ struct pipe_screen *screen,
+ struct pipe_texture *templ,
+ const char *name,
+ unsigned stride,
+ unsigned handle);
+ boolean (*shared_handle_from_texture)(struct drm_api *api,
+ struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned *stride,
+ unsigned *handle);
+ boolean (*local_handle_from_texture)(struct drm_api *api,
+ struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned *stride,
+ unsigned *handle);
+ /*@}*/
+
+ void (*destroy)(struct drm_api *api);
+};
+
+extern struct drm_api * drm_api_create(void);
+
+#endif
diff --git a/src/gallium/state_trackers/Makefile b/src/gallium/state_trackers/Makefile
new file mode 100644
index 0000000000..265ca468c2
--- /dev/null
+++ b/src/gallium/state_trackers/Makefile
@@ -0,0 +1,25 @@
+TOP = ../../..
+include $(TOP)/configs/current
+
+
+SUBDIRS = $(GALLIUM_STATE_TRACKERS_DIRS)
+
+
+default: subdirs
+
+
+subdirs:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE)) || exit 1 ; \
+ fi \
+ done
+
+
+clean:
+ rm -f `find . -name \*.[oa]`
+ rm -f `find . -name depend`
+
+
+# Dummy install target
+install:
diff --git a/src/gallium/state_trackers/README b/src/gallium/state_trackers/README
new file mode 100644
index 0000000000..28dd27bbd5
--- /dev/null
+++ b/src/gallium/state_trackers/README
@@ -0,0 +1,2 @@
+This directory is a placeholder for incubating state-trackers. Mesa's
+state-tracker is in src/mesa.
diff --git a/src/gallium/state_trackers/dri/Makefile b/src/gallium/state_trackers/dri/Makefile
new file mode 100644
index 0000000000..ef8f19709a
--- /dev/null
+++ b/src/gallium/state_trackers/dri/Makefile
@@ -0,0 +1,28 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = dridrm
+
+LIBRARY_INCLUDES = \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -I$(TOP)/src/mesa/main \
+ $(shell pkg-config --cflags-only-I libdrm)
+
+
+C_SOURCES = \
+ dri_context.c \
+ dri_screen.c \
+ dri_drawable.c \
+ dri_extensions.c
+
+# $(TOP)/src/mesa/drivers/dri/common/utils.c \
+ $(TOP)/src/mesa/drivers/dri/common/vblank.c \
+ $(TOP)/src/mesa/drivers/dri/common/dri_util.c \
+ $(TOP)/src/mesa/drivers/dri/common/xmlconfig.c \
+ $(TOP)/src/mesa/drivers/common/driverfuncs.c \
+ $(TOP)/src/mesa/drivers/dri/common/texmem.c \
+ $(TOP)/src/mesa/drivers/dri/common/drirenderbuffer.c
+
+include ../../Makefile.template
diff --git a/src/gallium/state_trackers/dri/SConscript b/src/gallium/state_trackers/dri/SConscript
new file mode 100644
index 0000000000..ce2c273597
--- /dev/null
+++ b/src/gallium/state_trackers/dri/SConscript
@@ -0,0 +1,23 @@
+#######################################################################
+# SConscript for dri state_tracker
+
+Import('*')
+
+if env['dri']:
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#/src/mesa',
+ '#/src/mesa/drivers/dri/common',
+ ])
+
+ st_dri = env.ConvenienceLibrary(
+ target = 'st_dri',
+ source = [ 'dri_context.c',
+ 'dri_drawable.c',
+ 'dri_extensions.c',
+ 'dri_screen.c',
+ ]
+ )
+ Export('st_dri')
diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c
new file mode 100644
index 0000000000..8819936fca
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri_context.c
@@ -0,0 +1,215 @@
+/**************************************************************************
+ *
+ * Copyright 2009, VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Author: Keith Whitwell <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#include "dri_screen.h"
+
+#include "dri_drawable.h"
+#include "state_tracker/drm_api.h"
+#include "state_tracker/dri1_api.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
+#include "pipe/p_context.h"
+
+#include "dri_context.h"
+
+#include "util/u_memory.h"
+
+GLboolean
+dri_create_context(const __GLcontextModes * visual,
+ __DRIcontextPrivate * cPriv, void *sharedContextPrivate)
+{
+ __DRIscreenPrivate *sPriv = cPriv->driScreenPriv;
+ struct dri_screen *screen = dri_screen(sPriv);
+ struct dri_context *ctx = NULL;
+ struct st_context *st_share = NULL;
+
+ if (sharedContextPrivate) {
+ st_share = ((struct dri_context *)sharedContextPrivate)->st;
+ }
+
+ ctx = CALLOC_STRUCT(dri_context);
+ if (ctx == NULL)
+ goto fail;
+
+ cPriv->driverPrivate = ctx;
+ ctx->cPriv = cPriv;
+ ctx->sPriv = sPriv;
+ ctx->lock = screen->drmLock;
+ ctx->d_stamp = -1;
+ ctx->r_stamp = -1;
+
+ driParseConfigFiles(&ctx->optionCache,
+ &screen->optionCache, sPriv->myNum, "dri");
+
+ ctx->pipe = screen->api->create_context(screen->api, screen->pipe_screen);
+
+ if (ctx->pipe == NULL)
+ goto fail;
+
+ /* used in dri_flush_frontbuffer */
+ ctx->pipe->priv = ctx;
+
+ ctx->st = st_create_context(ctx->pipe, visual, st_share);
+ if (ctx->st == NULL)
+ goto fail;
+
+ dri_init_extensions(ctx);
+
+ return GL_TRUE;
+
+ fail:
+ if (ctx && ctx->st)
+ st_destroy_context(ctx->st);
+
+ if (ctx && ctx->pipe)
+ ctx->pipe->destroy(ctx->pipe);
+
+ FREE(ctx);
+ return FALSE;
+}
+
+void
+dri_destroy_context(__DRIcontextPrivate * cPriv)
+{
+ struct dri_context *ctx = dri_context(cPriv);
+
+ /* No particular reason to wait for command completion before
+ * destroying a context, but it is probably worthwhile flushing it
+ * to avoid having to add code elsewhere to cope with flushing a
+ * partially destroyed context.
+ */
+ st_flush(ctx->st, 0, NULL);
+
+ /* Also frees ctx->pipe?
+ */
+ st_destroy_context(ctx->st);
+
+ FREE(ctx);
+}
+
+GLboolean
+dri_unbind_context(__DRIcontextPrivate * cPriv)
+{
+ if (cPriv) {
+ struct dri_context *ctx = dri_context(cPriv);
+
+ if (--ctx->bind_count == 0) {
+ if (ctx->st && ctx->st == st_get_current()) {
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ st_make_current(NULL, NULL, NULL);
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean
+dri_make_current(__DRIcontextPrivate * cPriv,
+ __DRIdrawablePrivate * driDrawPriv,
+ __DRIdrawablePrivate * driReadPriv)
+{
+ if (cPriv) {
+ struct dri_context *ctx = dri_context(cPriv);
+ struct dri_drawable *draw = dri_drawable(driDrawPriv);
+ struct dri_drawable *read = dri_drawable(driReadPriv);
+ struct st_context *old_st = st_get_current();
+
+ if (old_st && old_st != ctx->st)
+ st_flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ ++ctx->bind_count;
+
+ if (ctx->dPriv != driDrawPriv) {
+ ctx->dPriv = driDrawPriv;
+ ctx->d_stamp = driDrawPriv->lastStamp - 1;
+ }
+ if (ctx->rPriv != driReadPriv) {
+ ctx->rPriv = driReadPriv;
+ ctx->r_stamp = driReadPriv->lastStamp - 1;
+ }
+
+ st_make_current(ctx->st, draw->stfb, read->stfb);
+
+ if (__dri1_api_hooks) {
+ dri1_update_drawables(ctx, draw, read);
+ } else {
+ if (driDrawPriv)
+ dri_get_buffers(driDrawPriv);
+ if (driDrawPriv != driReadPriv && driReadPriv)
+ dri_get_buffers(driReadPriv);
+ }
+ } else {
+ st_make_current(NULL, NULL, NULL);
+ }
+
+ return GL_TRUE;
+}
+
+static void
+st_dri_lock(struct pipe_context *pipe)
+{
+ dri_lock((struct dri_context *)pipe->priv);
+}
+
+static void
+st_dri_unlock(struct pipe_context *pipe)
+{
+ dri_unlock((struct dri_context *)pipe->priv);
+}
+
+static boolean
+st_dri_is_locked(struct pipe_context *pipe)
+{
+ return ((struct dri_context *)pipe->priv)->isLocked;
+}
+
+static boolean
+st_dri_lost_lock(struct pipe_context *pipe)
+{
+ return ((struct dri_context *)pipe->priv)->wsLostLock;
+}
+
+static void
+st_dri_clear_lost_lock(struct pipe_context *pipe)
+{
+ ((struct dri_context *)pipe->priv)->wsLostLock = FALSE;
+}
+
+struct dri1_api_lock_funcs dri1_lf = {
+ .lock = st_dri_lock,
+ .unlock = st_dri_unlock,
+ .is_locked = st_dri_is_locked,
+ .is_lock_lost = st_dri_lost_lock,
+ .clear_lost_lock = st_dri_clear_lost_lock
+};
+
+/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_context.h b/src/gallium/state_trackers/dri/dri_context.h
new file mode 100644
index 0000000000..4650178734
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri_context.h
@@ -0,0 +1,123 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Author: Keith Whitwell <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#ifndef DRI_CONTEXT_H
+#define DRI_CONTEXT_H
+
+#include "pipe/p_compiler.h"
+#include "drm.h"
+#include "dri_util.h"
+
+struct pipe_context;
+struct pipe_fence;
+struct st_context;
+struct dri_drawable;
+
+struct dri_context
+{
+ /* dri */
+ __DRIscreenPrivate *sPriv;
+ __DRIcontextPrivate *cPriv;
+ __DRIdrawablePrivate *dPriv;
+ __DRIdrawablePrivate *rPriv;
+
+ driOptionCache optionCache;
+
+ unsigned int d_stamp;
+ unsigned int r_stamp;
+
+ drmLock *lock;
+ boolean isLocked;
+ boolean stLostLock;
+ boolean wsLostLock;
+
+ unsigned int bind_count;
+
+ /* gallium */
+ struct st_context *st;
+ struct pipe_context *pipe;
+};
+
+static INLINE struct dri_context *
+dri_context(__DRIcontextPrivate * driContextPriv)
+{
+ return (struct dri_context *)driContextPriv->driverPrivate;
+}
+
+static INLINE void
+dri_lock(struct dri_context *ctx)
+{
+ drm_context_t hw_context = ctx->cPriv->hHWContext;
+ char ret = 0;
+
+ DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret);
+ if (ret) {
+ drmGetLock(ctx->sPriv->fd, hw_context, 0);
+ ctx->stLostLock = TRUE;
+ ctx->wsLostLock = TRUE;
+ }
+ ctx->isLocked = TRUE;
+}
+
+static INLINE void
+dri_unlock(struct dri_context *ctx)
+{
+ ctx->isLocked = FALSE;
+ DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext);
+}
+
+/***********************************************************************
+ * dri_context.c
+ */
+extern struct dri1_api_lock_funcs dri1_lf;
+
+void dri_destroy_context(__DRIcontextPrivate * driContextPriv);
+
+boolean dri_unbind_context(__DRIcontextPrivate * driContextPriv);
+
+boolean
+dri_make_current(__DRIcontextPrivate * driContextPriv,
+ __DRIdrawablePrivate * driDrawPriv,
+ __DRIdrawablePrivate * driReadPriv);
+
+boolean
+dri_create_context(const __GLcontextModes * visual,
+ __DRIcontextPrivate * driContextPriv,
+ void *sharedContextPrivate);
+
+/***********************************************************************
+ * dri_extensions.c
+ */
+void dri_init_extensions(struct dri_context *ctx);
+
+#endif
+
+/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c
new file mode 100644
index 0000000000..5cec9e329d
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri_drawable.c
@@ -0,0 +1,687 @@
+/**************************************************************************
+ *
+ * Copyright 2009, VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Author: Keith Whitwell <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#include "dri_screen.h"
+#include "dri_context.h"
+#include "dri_drawable.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_inlines.h"
+#include "main/mtypes.h"
+#include "main/renderbuffer.h"
+#include "state_tracker/drm_api.h"
+#include "state_tracker/dri1_api.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_cb_fbo.h"
+
+#include "util/u_memory.h"
+
+static struct pipe_surface *
+dri_surface_from_handle(struct drm_api *api,
+ struct pipe_screen *screen,
+ unsigned handle,
+ enum pipe_format format,
+ unsigned width, unsigned height, unsigned pitch)
+{
+ struct pipe_surface *surface = NULL;
+ struct pipe_texture *texture = NULL;
+ struct pipe_texture templat;
+
+ memset(&templat, 0, sizeof(templat));
+ templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ templat.target = PIPE_TEXTURE_2D;
+ templat.last_level = 0;
+ templat.depth[0] = 1;
+ templat.format = format;
+ templat.width[0] = width;
+ templat.height[0] = height;
+ pf_get_block(templat.format, &templat.block);
+
+ texture = api->texture_from_shared_handle(api, screen, &templat,
+ "dri2 buffer", pitch, handle);
+
+ if (!texture) {
+ debug_printf("%s: Failed to blanket the buffer with a texture\n", __func__);
+ return NULL;
+ }
+
+ surface = screen->get_tex_surface(screen, texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* we don't need the texture from this point on */
+ pipe_texture_reference(&texture, NULL);
+ return surface;
+}
+
+/**
+ * Pixmaps have will have the same name of fake front and front.
+ */
+static boolean
+dri2_check_if_pixmap(__DRIbuffer *buffers, int count)
+{
+ boolean found = FALSE;
+ boolean is_pixmap = FALSE;
+ unsigned name;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ switch (buffers[i].attachment) {
+ case __DRI_BUFFER_FRONT_LEFT:
+ case __DRI_BUFFER_FAKE_FRONT_LEFT:
+ if (found) {
+ is_pixmap = buffers[i].name == name;
+ } else {
+ name = buffers[i].name;
+ found = TRUE;
+ }
+ default:
+ continue;
+ }
+ }
+
+ return is_pixmap;
+}
+
+/**
+ * This will be called a drawable is known to have been resized.
+ */
+void
+dri_get_buffers(__DRIdrawablePrivate * dPriv)
+{
+
+ struct dri_drawable *drawable = dri_drawable(dPriv);
+ struct pipe_surface *surface = NULL;
+ struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen;
+ __DRIbuffer *buffers = NULL;
+ __DRIscreen *dri_screen = drawable->sPriv;
+ __DRIdrawable *dri_drawable = drawable->dPriv;
+ struct drm_api *api = ((struct dri_screen*)(dri_screen->private))->api;
+ boolean have_depth = FALSE;
+ int i, count;
+
+ buffers = (*dri_screen->dri2.loader->getBuffers) (dri_drawable,
+ &dri_drawable->w,
+ &dri_drawable->h,
+ drawable->attachments,
+ drawable->
+ num_attachments, &count,
+ dri_drawable->
+ loaderPrivate);
+
+ if (buffers == NULL) {
+ return;
+ }
+
+ /* set one cliprect to cover the whole dri_drawable */
+ dri_drawable->x = 0;
+ dri_drawable->y = 0;
+ dri_drawable->backX = 0;
+ dri_drawable->backY = 0;
+ dri_drawable->numClipRects = 1;
+ dri_drawable->pClipRects[0].x1 = 0;
+ dri_drawable->pClipRects[0].y1 = 0;
+ dri_drawable->pClipRects[0].x2 = dri_drawable->w;
+ dri_drawable->pClipRects[0].y2 = dri_drawable->h;
+ dri_drawable->numBackClipRects = 1;
+ dri_drawable->pBackClipRects[0].x1 = 0;
+ dri_drawable->pBackClipRects[0].y1 = 0;
+ dri_drawable->pBackClipRects[0].x2 = dri_drawable->w;
+ dri_drawable->pBackClipRects[0].y2 = dri_drawable->h;
+
+ if (drawable->old_num == count &&
+ drawable->old_w == dri_drawable->w &&
+ drawable->old_h == dri_drawable->h &&
+ memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) {
+ return;
+ } else {
+ drawable->old_num = count;
+ drawable->old_w = dri_drawable->w;
+ drawable->old_h = dri_drawable->h;
+ memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
+ }
+
+ drawable->is_pixmap = dri2_check_if_pixmap(buffers, count);
+
+ for (i = 0; i < count; i++) {
+ enum pipe_format format = 0;
+ int index = 0;
+
+ switch (buffers[i].attachment) {
+ case __DRI_BUFFER_FRONT_LEFT:
+ continue;
+ case __DRI_BUFFER_FAKE_FRONT_LEFT:
+ index = ST_SURFACE_FRONT_LEFT;
+ format = drawable->color_format;
+ break;
+ case __DRI_BUFFER_BACK_LEFT:
+ index = ST_SURFACE_BACK_LEFT;
+ format = drawable->color_format;
+ break;
+ case __DRI_BUFFER_DEPTH:
+ case __DRI_BUFFER_DEPTH_STENCIL:
+ case __DRI_BUFFER_STENCIL:
+ index = ST_SURFACE_DEPTH;
+ format = drawable->depth_stencil_format;
+ break;
+ case __DRI_BUFFER_ACCUM:
+ default:
+ assert(0);
+ }
+
+ if (index == ST_SURFACE_DEPTH) {
+ if (have_depth)
+ continue;
+ else
+ have_depth = TRUE;
+ }
+
+ surface = dri_surface_from_handle(api,
+ screen,
+ buffers[i].name,
+ format,
+ dri_drawable->w,
+ dri_drawable->h, buffers[i].pitch);
+
+ switch (buffers[i].attachment) {
+ case __DRI_BUFFER_FAKE_FRONT_LEFT:
+ case __DRI_BUFFER_BACK_LEFT:
+ drawable->color_format = surface->format;
+ break;
+ case __DRI_BUFFER_DEPTH:
+ case __DRI_BUFFER_DEPTH_STENCIL:
+ case __DRI_BUFFER_STENCIL:
+ drawable->depth_stencil_format = surface->format;
+ break;
+ }
+
+ st_set_framebuffer_surface(drawable->stfb, index, surface);
+ pipe_surface_reference(&surface, NULL);
+ }
+ /* this needed, or else the state tracker fails to pick the new buffers */
+ st_resize_framebuffer(drawable->stfb, dri_drawable->w, dri_drawable->h);
+}
+
+/**
+ * These are used for GLX_EXT_texture_from_pixmap
+ */
+void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
+ GLint format, __DRIdrawable *dPriv)
+{
+ struct dri_drawable *drawable = dri_drawable(dPriv);
+ struct pipe_surface *ps;
+
+ if (!drawable->stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer) {
+ struct gl_renderbuffer *rb =
+ st_new_renderbuffer_fb(drawable->color_format, 0 /*XXX*/, FALSE);
+ _mesa_add_renderbuffer(&drawable->stfb->Base, BUFFER_FRONT_LEFT, rb);
+ }
+
+ dri_get_buffers(drawable->dPriv);
+ st_get_framebuffer_surface(drawable->stfb, ST_SURFACE_FRONT_LEFT, &ps);
+
+ st_bind_texture_surface(ps, target == GL_TEXTURE_2D ? ST_TEXTURE_2D :
+ ST_TEXTURE_RECT, 0, drawable->color_format);
+}
+
+void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
+ __DRIdrawable *dPriv)
+{
+ dri2_set_tex_buffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
+}
+
+void
+dri_flush_frontbuffer(struct pipe_screen *screen,
+ struct pipe_surface *surf, void *context_private)
+{
+ struct dri_context *ctx = (struct dri_context *)context_private;
+ struct dri_drawable *drawable = dri_drawable(ctx->dPriv);
+ __DRIdrawable *dri_drawable = ctx->dPriv;
+ __DRIscreen *dri_screen = ctx->sPriv;
+
+ /* XXX Does this function get called with DRI1? */
+
+ if (ctx->dPriv == NULL) {
+ debug_printf("%s: no drawable bound to context\n", __func__);
+ return;
+ }
+
+#if 0
+ /* TODO if rendering to pixmaps is slow enable this code. */
+ if (drawable->is_pixmap)
+ return;
+#else
+ (void)drawable;
+#endif
+
+ (*dri_screen->dri2.loader->flushFrontBuffer)(dri_drawable,
+ dri_drawable->loaderPrivate);
+}
+
+/**
+ * This is called when we need to set up GL rendering to a new X window.
+ */
+boolean
+dri_create_buffer(__DRIscreenPrivate * sPriv,
+ __DRIdrawablePrivate * dPriv,
+ const __GLcontextModes * visual, boolean isPixmap)
+{
+ struct dri_screen *screen = sPriv->private;
+ struct dri_drawable *drawable = NULL;
+ int i;
+
+ if (isPixmap)
+ goto fail; /* not implemented */
+
+ drawable = CALLOC_STRUCT(dri_drawable);
+ if (drawable == NULL)
+ goto fail;
+
+ if (visual->redBits == 8) {
+ if (visual->alphaBits == 8)
+ drawable->color_format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ else
+ drawable->color_format = PIPE_FORMAT_X8R8G8B8_UNORM;
+ } else {
+ drawable->color_format = PIPE_FORMAT_R5G6B5_UNORM;
+ }
+
+ switch(visual->depthBits) {
+ default:
+ case 0:
+ drawable->depth_stencil_format = PIPE_FORMAT_NONE;
+ break;
+ case 16:
+ drawable->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
+ break;
+ case 24:
+ if (visual->stencilBits == 0) {
+ drawable->depth_stencil_format = (screen->d_depth_bits_last) ?
+ PIPE_FORMAT_X8Z24_UNORM:
+ PIPE_FORMAT_Z24X8_UNORM;
+ } else {
+ drawable->depth_stencil_format = (screen->sd_depth_bits_last) ?
+ PIPE_FORMAT_S8Z24_UNORM:
+ PIPE_FORMAT_Z24S8_UNORM;
+ }
+ break;
+ case 32:
+ drawable->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
+ break;
+ }
+
+ drawable->stfb = st_create_framebuffer(visual,
+ drawable->color_format,
+ drawable->depth_stencil_format,
+ drawable->depth_stencil_format,
+ dPriv->w,
+ dPriv->h, (void *)drawable);
+ if (drawable->stfb == NULL)
+ goto fail;
+
+ drawable->sPriv = sPriv;
+ drawable->dPriv = dPriv;
+ dPriv->driverPrivate = (void *)drawable;
+
+ /* setup dri2 buffers information */
+ /* TODO incase of double buffer visual, delay fake creation */
+ i = 0;
+ drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+
+ if (visual->doubleBufferMode)
+ drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+ else
+ drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT;
+ if (visual->depthBits && visual->stencilBits)
+ drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
+ else if (visual->depthBits)
+ drawable->attachments[i++] = __DRI_BUFFER_DEPTH;
+ else if (visual->stencilBits)
+ drawable->attachments[i++] = __DRI_BUFFER_STENCIL;
+ drawable->num_attachments = i;
+
+ drawable->desired_fences = 2;
+
+ return GL_TRUE;
+ fail:
+ FREE(drawable);
+ return GL_FALSE;
+}
+
+static struct pipe_fence_handle *
+dri_swap_fences_pop_front(struct dri_drawable *draw)
+{
+ struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
+ struct pipe_fence_handle *fence = NULL;
+
+ if (draw->cur_fences >= draw->desired_fences) {
+ screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]);
+ screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL);
+ --draw->cur_fences;
+ draw->tail &= DRI_SWAP_FENCES_MASK;
+ }
+ return fence;
+}
+
+static void
+dri_swap_fences_push_back(struct dri_drawable *draw,
+ struct pipe_fence_handle *fence)
+{
+ struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
+
+ if (!fence)
+ return;
+
+ if (draw->cur_fences < DRI_SWAP_FENCES_MAX) {
+ draw->cur_fences++;
+ screen->fence_reference(screen, &draw->swap_fences[draw->head++],
+ fence);
+ draw->head &= DRI_SWAP_FENCES_MASK;
+ }
+}
+
+void
+dri_destroy_buffer(__DRIdrawablePrivate * dPriv)
+{
+ struct dri_drawable *drawable = dri_drawable(dPriv);
+ struct pipe_fence_handle *fence;
+ struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen;
+
+ st_unreference_framebuffer(drawable->stfb);
+ drawable->desired_fences = 0;
+ while (drawable->cur_fences) {
+ fence = dri_swap_fences_pop_front(drawable);
+ screen->fence_reference(screen, &fence, NULL);
+ }
+
+ FREE(drawable);
+}
+
+static void
+dri1_update_drawables_locked(struct dri_context *ctx,
+ __DRIdrawablePrivate * driDrawPriv,
+ __DRIdrawablePrivate * driReadPriv)
+{
+ if (ctx->stLostLock) {
+ ctx->stLostLock = FALSE;
+ if (driDrawPriv == driReadPriv)
+ DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv);
+ else
+ DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv,
+ driReadPriv);
+ }
+}
+
+/**
+ * This ensures all contexts which bind to a drawable pick up the
+ * drawable change and signal new buffer state.
+ * Calling st_resize_framebuffer for each context may seem like overkill,
+ * but no new buffers will actually be allocated if the dimensions don't
+ * change.
+ */
+
+static void
+dri1_propagate_drawable_change(struct dri_context *ctx)
+{
+ __DRIdrawablePrivate *dPriv = ctx->dPriv;
+ __DRIdrawablePrivate *rPriv = ctx->rPriv;
+ boolean flushed = FALSE;
+
+ if (dPriv && ctx->d_stamp != dPriv->lastStamp) {
+
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ flushed = TRUE;
+ ctx->d_stamp = dPriv->lastStamp;
+ st_resize_framebuffer(dri_drawable(dPriv)->stfb, dPriv->w, dPriv->h);
+
+ }
+
+ if (rPriv && dPriv != rPriv && ctx->r_stamp != rPriv->lastStamp) {
+
+ if (!flushed)
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ ctx->r_stamp = rPriv->lastStamp;
+ st_resize_framebuffer(dri_drawable(rPriv)->stfb, rPriv->w, rPriv->h);
+
+ } else if (rPriv && dPriv == rPriv) {
+
+ ctx->r_stamp = ctx->d_stamp;
+
+ }
+}
+
+void
+dri1_update_drawables(struct dri_context *ctx,
+ struct dri_drawable *draw, struct dri_drawable *read)
+{
+ dri_lock(ctx);
+ dri1_update_drawables_locked(ctx, draw->dPriv, read->dPriv);
+ dri_unlock(ctx);
+
+ dri1_propagate_drawable_change(ctx);
+}
+
+static INLINE boolean
+dri1_intersect_src_bbox(struct drm_clip_rect *dst,
+ int dst_x,
+ int dst_y,
+ const struct drm_clip_rect *src,
+ const struct drm_clip_rect *bbox)
+{
+ int xy1;
+ int xy2;
+
+ xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 :
+ (int)bbox->x1 + dst_x;
+ xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 :
+ (int)bbox->x2 + dst_x;
+ if (xy1 >= xy2 || xy1 < 0)
+ return FALSE;
+
+ dst->x1 = xy1;
+ dst->x2 = xy2;
+
+ xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 :
+ (int)bbox->y1 + dst_y;
+ xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 :
+ (int)bbox->y2 + dst_y;
+ if (xy1 >= xy2 || xy1 < 0)
+ return FALSE;
+
+ dst->y1 = xy1;
+ dst->y2 = xy2;
+ return TRUE;
+}
+
+static void
+dri1_swap_copy(struct dri_context *ctx,
+ struct pipe_surface *dst,
+ struct pipe_surface *src,
+ __DRIdrawablePrivate * dPriv, const struct drm_clip_rect *bbox)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct drm_clip_rect clip;
+ struct drm_clip_rect *cur;
+ int i;
+
+ cur = dPriv->pClipRects;
+
+ for (i = 0; i < dPriv->numClipRects; ++i) {
+ if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox))
+ pipe->surface_copy(pipe, dst, clip.x1, clip.y1,
+ src,
+ (int)clip.x1 - dPriv->x,
+ (int)clip.y1 - dPriv->y,
+ clip.x2 - clip.x1, clip.y2 - clip.y1);
+ }
+}
+
+static void
+dri1_copy_to_front(struct dri_context *ctx,
+ struct pipe_surface *surf,
+ __DRIdrawablePrivate * dPriv,
+ const struct drm_clip_rect *sub_box,
+ struct pipe_fence_handle **fence)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ boolean save_lost_lock;
+ uint cur_w;
+ uint cur_h;
+ struct drm_clip_rect bbox;
+ boolean visible = TRUE;
+
+ *fence = NULL;
+
+ dri_lock(ctx);
+ save_lost_lock = ctx->stLostLock;
+ dri1_update_drawables_locked(ctx, dPriv, dPriv);
+ st_get_framebuffer_dimensions(dri_drawable(dPriv)->stfb, &cur_w, &cur_h);
+
+ bbox.x1 = 0;
+ bbox.x2 = cur_w;
+ bbox.y1 = 0;
+ bbox.y2 = cur_h;
+
+ if (sub_box)
+ visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box);
+
+ if (visible && __dri1_api_hooks->present_locked) {
+
+ __dri1_api_hooks->present_locked(pipe,
+ surf,
+ dPriv->pClipRects,
+ dPriv->numClipRects,
+ dPriv->x, dPriv->y, &bbox, fence);
+
+ } else if (visible && __dri1_api_hooks->front_srf_locked) {
+
+ struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe);
+
+ if (front)
+ dri1_swap_copy(ctx, front, surf, dPriv, &bbox);
+
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence);
+ }
+
+ ctx->stLostLock = save_lost_lock;
+
+ /**
+ * FIXME: Revisit this: Update drawables on copy_sub_buffer ?
+ */
+
+ if (!sub_box)
+ dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv);
+
+ dri_unlock(ctx);
+ dri1_propagate_drawable_change(ctx);
+}
+
+void
+dri1_flush_frontbuffer(struct pipe_screen *screen,
+ struct pipe_surface *surf, void *context_private)
+{
+ struct dri_context *ctx = (struct dri_context *)context_private;
+ struct pipe_fence_handle *dummy_fence;
+
+ dri1_copy_to_front(ctx, surf, ctx->dPriv, NULL, &dummy_fence);
+ screen->fence_reference(screen, &dummy_fence, NULL);
+
+ /**
+ * FIXME: Do we need swap throttling here?
+ */
+}
+
+void
+dri_swap_buffers(__DRIdrawablePrivate * dPriv)
+{
+ struct dri_context *ctx;
+ struct pipe_surface *back_surf;
+ struct dri_drawable *draw = dri_drawable(dPriv);
+ struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
+ struct pipe_fence_handle *fence;
+ struct st_context *st = st_get_current();
+
+ assert(__dri1_api_hooks != NULL);
+
+ if (!st)
+ return; /* For now */
+
+ ctx = (struct dri_context *)st->pipe->priv;
+
+ st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
+ if (back_surf) {
+ st_notify_swapbuffers(draw->stfb);
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ fence = dri_swap_fences_pop_front(draw);
+ if (fence) {
+ (void)screen->fence_finish(screen, fence, 0);
+ screen->fence_reference(screen, &fence, NULL);
+ }
+ dri1_copy_to_front(ctx, back_surf, dPriv, NULL, &fence);
+ dri_swap_fences_push_back(draw, fence);
+ screen->fence_reference(screen, &fence, NULL);
+ }
+}
+
+void
+dri_copy_sub_buffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
+{
+ struct pipe_screen *screen = dri_screen(dPriv->driScreenPriv)->pipe_screen;
+ struct drm_clip_rect sub_bbox;
+ struct dri_context *ctx;
+ struct pipe_surface *back_surf;
+ struct dri_drawable *draw = dri_drawable(dPriv);
+ struct pipe_fence_handle *dummy_fence;
+ struct st_context *st = st_get_current();
+
+ assert(__dri1_api_hooks != NULL);
+
+ if (!st)
+ return;
+
+ ctx = (struct dri_context *)st->pipe->priv;
+
+ sub_bbox.x1 = x;
+ sub_bbox.x2 = x + w;
+ sub_bbox.y1 = y;
+ sub_bbox.y2 = y + h;
+
+ st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
+ if (back_surf) {
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+ dri1_copy_to_front(ctx, back_surf, dPriv, &sub_bbox, &dummy_fence);
+ screen->fence_reference(screen, &dummy_fence, NULL);
+ }
+}
+
+/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h
new file mode 100644
index 0000000000..b910930db4
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri_drawable.h
@@ -0,0 +1,111 @@
+/**************************************************************************
+ *
+ * Copyright 2009, VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef DRI_DRAWABLE_H
+#define DRI_DRAWABLE_H
+
+#include "pipe/p_compiler.h"
+
+struct pipe_surface;
+struct pipe_fence_handle;
+struct st_framebuffer;
+struct dri_context;
+
+#define DRI_SWAP_FENCES_MAX 8
+#define DRI_SWAP_FENCES_MASK 7
+
+struct dri_drawable
+{
+ /* dri */
+ __DRIdrawablePrivate *dPriv;
+ __DRIscreenPrivate *sPriv;
+
+ unsigned attachments[8];
+ unsigned num_attachments;
+
+ boolean is_pixmap;
+
+ __DRIbuffer old[8];
+ unsigned old_num;
+ unsigned old_w;
+ unsigned old_h;
+
+ /* gallium */
+ struct st_framebuffer *stfb;
+ struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX];
+ unsigned int head;
+ unsigned int tail;
+ unsigned int desired_fences;
+ unsigned int cur_fences;
+
+ enum pipe_format color_format;
+ enum pipe_format depth_stencil_format;
+};
+
+static INLINE struct dri_drawable *
+dri_drawable(__DRIdrawablePrivate * driDrawPriv)
+{
+ return (struct dri_drawable *)driDrawPriv->driverPrivate;
+}
+
+/***********************************************************************
+ * dri_drawable.c
+ */
+boolean
+dri_create_buffer(__DRIscreenPrivate * sPriv,
+ __DRIdrawablePrivate * dPriv,
+ const __GLcontextModes * visual, boolean isPixmap);
+
+void
+dri_flush_frontbuffer(struct pipe_screen *screen,
+ struct pipe_surface *surf, void *context_private);
+
+void dri_swap_buffers(__DRIdrawablePrivate * dPriv);
+
+void
+dri_copy_sub_buffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h);
+
+void dri_get_buffers(__DRIdrawablePrivate * dPriv);
+
+void dri_destroy_buffer(__DRIdrawablePrivate * dPriv);
+
+void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
+ GLint glx_texture_format, __DRIdrawable *dPriv);
+
+void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
+ __DRIdrawable *dPriv);
+
+void
+dri1_update_drawables(struct dri_context *ctx,
+ struct dri_drawable *draw, struct dri_drawable *read);
+
+void
+dri1_flush_frontbuffer(struct pipe_screen *screen,
+ struct pipe_surface *surf, void *context_private);
+#endif
+
+/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c
new file mode 100644
index 0000000000..4349a4d1d2
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri_extensions.c
@@ -0,0 +1,128 @@
+/**************************************************************************
+ *
+ * Copyright 2009, VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Author: Keith Whitwell <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#include "dri_screen.h"
+#include "dri_context.h"
+#include "state_tracker/st_context.h"
+
+#define need_GL_ARB_map_buffer_range
+#define need_GL_ARB_multisample
+#define need_GL_ARB_occlusion_query
+#define need_GL_ARB_point_parameters
+#define need_GL_ARB_shader_objects
+#define need_GL_ARB_texture_compression
+#define need_GL_ARB_vertex_buffer_object
+#define need_GL_ARB_vertex_program
+#define need_GL_ARB_vertex_shader
+#define need_GL_ARB_window_pos
+#define need_GL_EXT_blend_color
+#define need_GL_EXT_blend_equation_separate
+#define need_GL_EXT_blend_func_separate
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_cull_vertex
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_multi_draw_arrays
+#define need_GL_EXT_secondary_color
+#define need_GL_NV_vertex_program
+#define need_GL_VERSION_2_0
+#define need_GL_VERSION_2_1
+#include "extension_helper.h"
+
+/**
+ * Extension strings exported by the driver.
+ */
+const struct dri_extension card_extensions[] = {
+ {"GL_ARB_fragment_shader", NULL},
+ {"GL_ARB_map_buffer_range", GL_ARB_map_buffer_range_functions},
+ {"GL_ARB_multisample", GL_ARB_multisample_functions},
+ {"GL_ARB_multitexture", NULL},
+ {"GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions},
+ {"GL_ARB_pixel_buffer_object", NULL},
+ {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions},
+ {"GL_ARB_shading_language_100", GL_VERSION_2_0_functions },
+ {"GL_ARB_shading_language_120", GL_VERSION_2_1_functions },
+ {"GL_ARB_shader_objects", GL_ARB_shader_objects_functions},
+ {"GL_ARB_texture_border_clamp", NULL},
+ {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions},
+ {"GL_ARB_texture_cube_map", NULL},
+ {"GL_ARB_texture_env_add", NULL},
+ {"GL_ARB_texture_env_combine", NULL},
+ {"GL_ARB_texture_env_dot3", NULL},
+ {"GL_ARB_texture_mirrored_repeat", NULL},
+ {"GL_ARB_texture_rectangle", NULL},
+ {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
+ {"GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions},
+ {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
+ {"GL_ARB_window_pos", GL_ARB_window_pos_functions},
+ {"GL_EXT_blend_color", GL_EXT_blend_color_functions},
+ {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions},
+ {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions},
+ {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
+ {"GL_EXT_blend_subtract", NULL},
+ {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions},
+ {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions},
+ {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions},
+ {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
+ {"GL_EXT_packed_depth_stencil", NULL},
+ {"GL_EXT_pixel_buffer_object", NULL},
+ {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
+ {"GL_EXT_stencil_wrap", NULL},
+ {"GL_EXT_texture_edge_clamp", NULL},
+ {"GL_EXT_texture_env_combine", NULL},
+ {"GL_EXT_texture_env_dot3", NULL},
+ {"GL_EXT_texture_filter_anisotropic", NULL},
+ {"GL_EXT_texture_lod_bias", NULL},
+ {"GL_3DFX_texture_compression_FXT1", NULL},
+ {"GL_APPLE_client_storage", NULL},
+ {"GL_MESA_pack_invert", NULL},
+ {"GL_MESA_ycbcr_texture", NULL},
+ {"GL_NV_blend_square", NULL},
+ {"GL_NV_vertex_program", GL_NV_vertex_program_functions},
+ {"GL_NV_vertex_program1_1", NULL},
+ {"GL_SGIS_generate_mipmap", NULL},
+ {NULL, NULL}
+};
+
+void
+dri_init_extensions(struct dri_context *ctx)
+{
+ /* The card_extensions list should be pruned according to the
+ * capabilities of the pipe_screen. This is actually something
+ * that can/should be done inside st_create_context().
+ */
+ if (ctx)
+ driInitExtensions(ctx->st->ctx, card_extensions, GL_TRUE);
+ else
+ driInitExtensions(NULL, card_extensions, GL_FALSE);
+}
+
+/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c
new file mode 100644
index 0000000000..884b6d5011
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri_screen.c
@@ -0,0 +1,354 @@
+/**************************************************************************
+ *
+ * Copyright 2009, VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Author: Keith Whitwell <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#include "utils.h"
+#include "vblank.h"
+#include "xmlpool.h"
+
+#include "dri_screen.h"
+#include "dri_context.h"
+#include "dri_drawable.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_format.h"
+#include "state_tracker/drm_api.h"
+#include "state_tracker/dri1_api.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_cb_fbo.h"
+
+PUBLIC const char __driConfigOptions[] =
+ DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
+ DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
+ DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
+ DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
+ /*DRI_CONF_FORCE_S3TC_ENABLE(false) */
+ DRI_CONF_ALLOW_LARGE_TEXTURES(1)
+ DRI_CONF_SECTION_END DRI_CONF_END;
+
+ const uint __driNConfigOptions = 3;
+
+static const __DRItexBufferExtension dri2TexBufferExtension = {
+ { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
+ dri2_set_tex_buffer,
+ dri2_set_tex_buffer2,
+};
+
+ static const __DRIextension *dri_screen_extensions[] = {
+ &driReadDrawableExtension,
+ &driCopySubBufferExtension.base,
+ &driSwapControlExtension.base,
+ &driFrameTrackingExtension.base,
+ &driMediaStreamCounterExtension.base,
+ &dri2TexBufferExtension.base,
+ NULL
+ };
+
+struct dri1_api *__dri1_api_hooks = NULL;
+
+static const __DRIconfig **
+dri_fill_in_modes(struct dri_screen *screen,
+ unsigned pixel_bits)
+{
+ __DRIconfig **configs = NULL;
+ unsigned num_modes;
+ uint8_t depth_bits_array[5];
+ uint8_t stencil_bits_array[5];
+ uint8_t msaa_samples_array[1];
+ unsigned depth_buffer_factor;
+ unsigned back_buffer_factor;
+ unsigned msaa_samples_factor;
+ struct pipe_screen *p_screen = screen->pipe_screen;
+ boolean pf_r5g6b5, pf_a8r8g8b8, pf_x8r8g8b8;
+ boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32;
+
+ static const GLenum back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+ };
+
+ depth_bits_array[0] = 0;
+ stencil_bits_array[0] = 0;
+ depth_buffer_factor = 1;
+
+ pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+ pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+ pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+ pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+ pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+ pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+ pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0);
+ pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0);
+ pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8R8G8B8_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0);
+
+ if (pf_z16) {
+ depth_bits_array[depth_buffer_factor] = 16;
+ stencil_bits_array[depth_buffer_factor++] = 0;
+ }
+ if (pf_x8z24 || pf_z24x8) {
+ depth_bits_array[depth_buffer_factor] = 24;
+ stencil_bits_array[depth_buffer_factor++] = 0;
+ screen->d_depth_bits_last = pf_x8z24;
+ }
+ if (pf_s8z24 || pf_z24s8) {
+ depth_bits_array[depth_buffer_factor] = 24;
+ stencil_bits_array[depth_buffer_factor++] = 8;
+ screen->sd_depth_bits_last = pf_s8z24;
+ }
+ if (pf_z32) {
+ depth_bits_array[depth_buffer_factor] = 32;
+ stencil_bits_array[depth_buffer_factor++] = 0;
+ }
+
+ msaa_samples_array[0] = 0;
+ back_buffer_factor = 3;
+ msaa_samples_factor = 1;
+
+ num_modes =
+ depth_buffer_factor * back_buffer_factor * msaa_samples_factor * 4;
+
+ if (pixel_bits == 16 && pf_r5g6b5) {
+ configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+ depth_bits_array, stencil_bits_array,
+ depth_buffer_factor, back_buffer_modes,
+ back_buffer_factor,
+ msaa_samples_array, 1);
+ } else {
+ __DRIconfig **configs_a8r8g8b8 = NULL;
+ __DRIconfig **configs_x8r8g8b8 = NULL;
+
+ if (pf_a8r8g8b8)
+ configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ depth_bits_array,
+ stencil_bits_array,
+ depth_buffer_factor,
+ back_buffer_modes,
+ back_buffer_factor,
+ msaa_samples_array, 1);
+ if (pf_x8r8g8b8)
+ configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV,
+ depth_bits_array,
+ stencil_bits_array,
+ depth_buffer_factor,
+ back_buffer_modes,
+ back_buffer_factor,
+ msaa_samples_array, 1);
+
+ if (configs_a8r8g8b8 && configs_x8r8g8b8)
+ configs = driConcatConfigs(configs_x8r8g8b8, configs_a8r8g8b8);
+ else if (configs_a8r8g8b8)
+ configs = configs_a8r8g8b8;
+ else if (configs_x8r8g8b8)
+ configs = configs_x8r8g8b8;
+ else
+ configs = NULL;
+ }
+
+ if (configs == NULL) {
+ debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__);
+ return NULL;
+ }
+
+ return (const const __DRIconfig **)configs;
+}
+
+/**
+ * Get information about previous buffer swaps.
+ */
+static int
+dri_get_swap_info(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
+{
+ if (dPriv == NULL || dPriv->driverPrivate == NULL || sInfo == NULL)
+ return -1;
+ else
+ return 0;
+}
+
+static INLINE void
+dri_copy_version(struct dri1_api_version *dst,
+ const struct __DRIversionRec *src)
+{
+ dst->major = src->major;
+ dst->minor = src->minor;
+ dst->patch_level = src->patch;
+}
+
+static const __DRIconfig **
+dri_init_screen(__DRIscreenPrivate * sPriv)
+{
+ struct dri_screen *screen;
+ const __DRIconfig **configs;
+ struct dri1_create_screen_arg arg;
+
+ dri_init_extensions(NULL);
+
+ screen = CALLOC_STRUCT(dri_screen);
+ if (!screen)
+ return NULL;
+
+ screen->api = drm_api_create();
+ screen->sPriv = sPriv;
+ screen->fd = sPriv->fd;
+ screen->drmLock = (drmLock *) & sPriv->pSAREA->lock;
+
+ sPriv->private = (void *)screen;
+ sPriv->extensions = dri_screen_extensions;
+
+ arg.base.mode = DRM_CREATE_DRI1;
+ arg.lf = &dri1_lf;
+ arg.ddx_info = sPriv->pDevPriv;
+ arg.ddx_info_size = sPriv->devPrivSize;
+ arg.sarea = sPriv->pSAREA;
+ dri_copy_version(&arg.ddx_version, &sPriv->ddx_version);
+ dri_copy_version(&arg.dri_version, &sPriv->dri_version);
+ dri_copy_version(&arg.drm_version, &sPriv->drm_version);
+ arg.api = NULL;
+
+ screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base);
+
+ if (!screen->pipe_screen || !arg.api) {
+ debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__);
+ goto out_no_screen;
+ }
+
+ __dri1_api_hooks = arg.api;
+
+ screen->pipe_screen->flush_frontbuffer = dri1_flush_frontbuffer;
+ driParseOptionInfo(&screen->optionCache,
+ __driConfigOptions, __driNConfigOptions);
+
+ /**
+ * FIXME: If the driver supports format conversion swapbuffer blits, we might
+ * want to support other color bit depths than the server is currently
+ * using.
+ */
+
+ configs = dri_fill_in_modes(screen, sPriv->fbBPP);
+ if (!configs)
+ goto out_no_configs;
+
+ return configs;
+ out_no_configs:
+ screen->pipe_screen->destroy(screen->pipe_screen);
+ out_no_screen:
+ FREE(screen);
+ return NULL;
+}
+
+/**
+ * This is the driver specific part of the createNewScreen entry point.
+ *
+ * Returns the __GLcontextModes supported by this driver.
+ */
+static const __DRIconfig **
+dri_init_screen2(__DRIscreenPrivate * sPriv)
+{
+ struct dri_screen *screen;
+ struct drm_create_screen_arg arg;
+
+ /* Set up dispatch table to cope with all known extensions */
+ dri_init_extensions(NULL);
+
+ screen = CALLOC_STRUCT(dri_screen);
+ if (!screen)
+ goto fail;
+
+ screen->api = drm_api_create();
+ screen->sPriv = sPriv;
+ screen->fd = sPriv->fd;
+ sPriv->private = (void *)screen;
+ sPriv->extensions = dri_screen_extensions;
+ arg.mode = DRM_CREATE_NORMAL;
+
+ screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg);
+ if (!screen->pipe_screen) {
+ debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__);
+ goto fail;
+ }
+
+ /* We need to hook in here */
+ screen->pipe_screen->flush_frontbuffer = dri_flush_frontbuffer;
+
+ driParseOptionInfo(&screen->optionCache,
+ __driConfigOptions, __driNConfigOptions);
+
+ return dri_fill_in_modes(screen, 32);
+ fail:
+ return NULL;
+}
+
+static void
+dri_destroy_screen(__DRIscreenPrivate * sPriv)
+{
+ struct dri_screen *screen = dri_screen(sPriv);
+
+ screen->pipe_screen->destroy(screen->pipe_screen);
+ FREE(screen);
+ sPriv->private = NULL;
+}
+
+PUBLIC const struct __DriverAPIRec driDriverAPI = {
+ .InitScreen = dri_init_screen,
+ .DestroyScreen = dri_destroy_screen,
+ .CreateContext = dri_create_context,
+ .DestroyContext = dri_destroy_context,
+ .CreateBuffer = dri_create_buffer,
+ .DestroyBuffer = dri_destroy_buffer,
+ .SwapBuffers = dri_swap_buffers,
+ .MakeCurrent = dri_make_current,
+ .UnbindContext = dri_unbind_context,
+ .GetSwapInfo = dri_get_swap_info,
+ .GetDrawableMSC = driDrawableGetMSC32,
+ .WaitForMSC = driWaitForMSC32,
+ .CopySubBuffer = dri_copy_sub_buffer,
+ .InitScreen = dri_init_screen,
+ .InitScreen2 = dri_init_screen2,
+};
+
+/* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h
new file mode 100644
index 0000000000..f6c56d0f0c
--- /dev/null
+++ b/src/gallium/state_trackers/dri/dri_screen.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * Copyright 2009, VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Author: Keith Whitwell <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#ifndef DRI_SCREEN_H
+#define DRI_SCREEN_H
+
+#include "dri_util.h"
+#include "xmlconfig.h"
+
+#include "pipe/p_compiler.h"
+
+#include "state_tracker/dri1_api.h"
+
+struct dri_screen
+{
+ /* dri */
+ __DRIscreenPrivate *sPriv;
+
+ /**
+ * Configuration cache with default values for all contexts
+ */
+ driOptionCache optionCache;
+
+ /* drm */
+ int fd;
+ drmLock *drmLock;
+
+ /* gallium */
+ struct drm_api *api;
+ struct pipe_winsys *pipe_winsys;
+ struct pipe_screen *pipe_screen;
+ boolean d_depth_bits_last;
+ boolean sd_depth_bits_last;
+};
+
+/** cast wrapper */
+static INLINE struct dri_screen *
+dri_screen(__DRIscreenPrivate * sPriv)
+{
+ return (struct dri_screen *)sPriv->private;
+}
+
+/***********************************************************************
+ * dri_screen.c
+ */
+
+extern struct dri1_api *__dri1_api_hooks;
+
+#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
new file mode 100644
index 0000000000..e825aa718b
--- /dev/null
+++ b/src/gallium/state_trackers/egl/Makefile
@@ -0,0 +1,19 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = egldrm
+
+LIBRARY_INCLUDES = \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/include \
+ -I$(TOP)/src/egl/main \
+ $(shell pkg-config --cflags-only-I libdrm)
+
+
+C_SOURCES = $(wildcard ./*.c)
+
+
+include ../../Makefile.template
diff --git a/src/gallium/state_trackers/egl/egl_context.c b/src/gallium/state_trackers/egl/egl_context.c
new file mode 100644
index 0000000000..c4f7361ca0
--- /dev/null
+++ b/src/gallium/state_trackers/egl/egl_context.c
@@ -0,0 +1,179 @@
+
+#include "utils.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "egl_tracker.h"
+
+#include "egllog.h"
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+
+#include "state_tracker/st_public.h"
+#include "state_tracker/drm_api.h"
+
+#include "GL/internal/glcore.h"
+
+#define need_GL_ARB_multisample
+#define need_GL_ARB_point_parameters
+#define need_GL_ARB_texture_compression
+#define need_GL_ARB_vertex_buffer_object
+#define need_GL_ARB_vertex_program
+#define need_GL_ARB_window_pos
+#define need_GL_EXT_blend_color
+#define need_GL_EXT_blend_equation_separate
+#define need_GL_EXT_blend_func_separate
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_cull_vertex
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_multi_draw_arrays
+#define need_GL_EXT_secondary_color
+#define need_GL_NV_vertex_program
+#include "extension_helper.h"
+
+/**
+ * TODO HACK! FUGLY!
+ * Copied for intel extentions.
+ */
+const struct dri_extension card_extensions[] = {
+ {"GL_ARB_multisample", GL_ARB_multisample_functions},
+ {"GL_ARB_multitexture", NULL},
+ {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions},
+ {"GL_ARB_texture_border_clamp", NULL},
+ {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions},
+ {"GL_ARB_texture_cube_map", NULL},
+ {"GL_ARB_texture_env_add", NULL},
+ {"GL_ARB_texture_env_combine", NULL},
+ {"GL_ARB_texture_env_dot3", NULL},
+ {"GL_ARB_texture_mirrored_repeat", NULL},
+ {"GL_ARB_texture_rectangle", NULL},
+ {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
+ {"GL_ARB_pixel_buffer_object", NULL},
+ {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
+ {"GL_ARB_window_pos", GL_ARB_window_pos_functions},
+ {"GL_EXT_blend_color", GL_EXT_blend_color_functions},
+ {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions},
+ {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions},
+ {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
+ {"GL_EXT_blend_subtract", NULL},
+ {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions},
+ {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions},
+ {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions},
+ {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
+ {"GL_EXT_packed_depth_stencil", NULL},
+ {"GL_EXT_pixel_buffer_object", NULL},
+ {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
+ {"GL_EXT_stencil_wrap", NULL},
+ {"GL_EXT_texture_edge_clamp", NULL},
+ {"GL_EXT_texture_env_combine", NULL},
+ {"GL_EXT_texture_env_dot3", NULL},
+ {"GL_EXT_texture_filter_anisotropic", NULL},
+ {"GL_EXT_texture_lod_bias", NULL},
+ {"GL_3DFX_texture_compression_FXT1", NULL},
+ {"GL_APPLE_client_storage", NULL},
+ {"GL_MESA_pack_invert", NULL},
+ {"GL_MESA_ycbcr_texture", NULL},
+ {"GL_NV_blend_square", NULL},
+ {"GL_NV_vertex_program", GL_NV_vertex_program_functions},
+ {"GL_NV_vertex_program1_1", NULL},
+ {"GL_SGIS_generate_mipmap", NULL },
+ {NULL, NULL}
+};
+
+_EGLContext *
+drm_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list)
+{
+ struct drm_device *dev = lookup_drm_device(dpy);
+ struct drm_context *ctx;
+ struct drm_context *share = NULL;
+ struct st_context *st_share = NULL;
+ int i;
+ __GLcontextModes *visual;
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ /* no attribs defined for now */
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
+ return EGL_NO_CONTEXT;
+ }
+ }
+
+ ctx = (struct drm_context *) calloc(1, sizeof(struct drm_context));
+ if (!ctx)
+ goto err_c;
+
+ _eglInitContext(drv, &ctx->base, conf, attrib_list);
+
+ ctx->pipe = dev->api->create_context(dev->api, dev->screen);
+ if (!ctx->pipe)
+ goto err_pipe;
+
+ if (share)
+ st_share = share->st;
+
+ visual = drm_visual_from_config(conf);
+ ctx->st = st_create_context(ctx->pipe, visual, st_share);
+ drm_visual_modes_destroy(visual);
+
+ if (!ctx->st)
+ goto err_gl;
+
+ return &ctx->base;
+
+err_gl:
+ ctx->pipe->destroy(ctx->pipe);
+err_pipe:
+ free(ctx);
+err_c:
+ return NULL;
+}
+
+EGLBoolean
+drm_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *context)
+{
+ struct drm_context *c = lookup_drm_context(context);
+ if (!_eglIsContextBound(&c->base)) {
+ st_destroy_context(c->st);
+ c->pipe->destroy(c->pipe);
+ free(c);
+ }
+ return EGL_TRUE;
+}
+
+EGLBoolean
+drm_make_current(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *context)
+{
+ struct drm_surface *readSurf = lookup_drm_surface(read);
+ struct drm_surface *drawSurf = lookup_drm_surface(draw);
+ struct drm_context *ctx = lookup_drm_context(context);
+ EGLBoolean b;
+
+ b = _eglMakeCurrent(drv, dpy, draw, read, context);
+ if (!b)
+ return EGL_FALSE;
+
+ if (ctx) {
+ if (!drawSurf || !readSurf)
+ return EGL_FALSE;
+
+ drawSurf->user = ctx;
+ readSurf->user = ctx;
+
+ st_make_current(ctx->st, drawSurf->stfb, readSurf->stfb);
+
+ /* st_resize_framebuffer needs a bound context to work */
+ st_resize_framebuffer(drawSurf->stfb, drawSurf->w, drawSurf->h);
+ st_resize_framebuffer(readSurf->stfb, readSurf->w, readSurf->h);
+ } else {
+ drawSurf->user = NULL;
+ readSurf->user = NULL;
+
+ st_make_current(NULL, NULL, NULL);
+ }
+
+ return EGL_TRUE;
+}
diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c
new file mode 100644
index 0000000000..69e2d6b708
--- /dev/null
+++ b/src/gallium/state_trackers/egl/egl_surface.c
@@ -0,0 +1,387 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "egl_tracker.h"
+
+#include "egllog.h"
+
+#include "pipe/p_inlines.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+
+#include "state_tracker/drm_api.h"
+
+/*
+ * Util functions
+ */
+
+static drmModeModeInfoPtr
+drm_find_mode(drmModeConnectorPtr connector, _EGLMode *mode)
+{
+ int i;
+ drmModeModeInfoPtr m = NULL;
+
+ for (i = 0; i < connector->count_modes; i++) {
+ m = &connector->modes[i];
+ if (m->hdisplay == mode->Width && m->vdisplay == mode->Height && m->vrefresh == mode->RefreshRate)
+ break;
+ m = &connector->modes[0]; /* if we can't find one, return first */
+ }
+
+ return m;
+}
+
+static struct st_framebuffer *
+drm_create_framebuffer(const __GLcontextModes *visual,
+ unsigned width,
+ unsigned height,
+ void *priv)
+{
+ enum pipe_format colorFormat, depthFormat, stencilFormat;
+
+ if (visual->redBits == 5)
+ colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
+ else
+ colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
+
+ if (visual->depthBits == 16)
+ depthFormat = PIPE_FORMAT_Z16_UNORM;
+ else if (visual->depthBits == 24)
+ depthFormat = PIPE_FORMAT_S8Z24_UNORM;
+ else
+ depthFormat = PIPE_FORMAT_NONE;
+
+ if (visual->stencilBits == 8)
+ stencilFormat = PIPE_FORMAT_S8Z24_UNORM;
+ else
+ stencilFormat = PIPE_FORMAT_NONE;
+
+ return st_create_framebuffer(visual,
+ colorFormat,
+ depthFormat,
+ stencilFormat,
+ width,
+ height,
+ priv);
+}
+
+static void
+drm_create_texture(_EGLDisplay *dpy,
+ struct drm_screen *scrn,
+ unsigned w, unsigned h)
+{
+ struct drm_device *dev = lookup_drm_device(dpy);
+ struct pipe_screen *screen = dev->screen;
+ struct pipe_surface *surface;
+ struct pipe_texture *texture;
+ struct pipe_texture templat;
+ struct pipe_buffer *buf = NULL;
+ unsigned pitch = 0;
+
+ memset(&templat, 0, sizeof(templat));
+ templat.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
+ templat.target = PIPE_TEXTURE_2D;
+ templat.last_level = 0;
+ templat.depth[0] = 1;
+ templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ templat.width[0] = w;
+ templat.height[0] = h;
+ pf_get_block(templat.format, &templat.block);
+
+ texture = screen->texture_create(dev->screen,
+ &templat);
+
+ if (!texture)
+ goto err_tex;
+
+ surface = screen->get_tex_surface(screen,
+ texture,
+ 0,
+ 0,
+ 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ if (!surface)
+ goto err_surf;
+
+ scrn->tex = texture;
+ scrn->surface = surface;
+ scrn->front.width = w;
+ scrn->front.height = h;
+ scrn->front.pitch = pitch;
+ dev->api->local_handle_from_texture(dev->api, screen, texture,
+ &scrn->front.pitch, &scrn->front.handle);
+ if (0)
+ goto err_handle;
+
+ return;
+
+err_handle:
+ pipe_surface_reference(&surface, NULL);
+err_surf:
+ pipe_texture_reference(&texture, NULL);
+err_tex:
+ pipe_buffer_reference(&buf, NULL);
+ return;
+}
+
+/*
+ * Exported functions
+ */
+
+void
+drm_takedown_shown_screen(_EGLDisplay *dpy, struct drm_screen *screen)
+{
+ struct drm_device *dev = lookup_drm_device(dpy);
+
+ screen->surf = NULL;
+
+ drmModeSetCrtc(
+ dev->drmFD,
+ screen->crtcID,
+ 0, // FD
+ 0, 0,
+ NULL, 0, // List of output ids
+ NULL);
+
+ drmModeRmFB(dev->drmFD, screen->fbID);
+ drmModeFreeFB(screen->fb);
+ screen->fb = NULL;
+
+ pipe_surface_reference(&screen->surface, NULL);
+ pipe_texture_reference(&screen->tex, NULL);
+ pipe_buffer_reference(&screen->buffer, NULL);
+
+ screen->shown = 0;
+}
+
+_EGLSurface *
+drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list)
+{
+ return NULL;
+}
+
+
+_EGLSurface *
+drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list)
+{
+ return NULL;
+}
+
+
+_EGLSurface *
+drm_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+ const EGLint *attrib_list)
+{
+ int i;
+ int width = -1;
+ int height = -1;
+ struct drm_surface *surf = NULL;
+ __GLcontextModes *visual;
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ case EGL_WIDTH:
+ width = attrib_list[++i];
+ break;
+ case EGL_HEIGHT:
+ height = attrib_list[++i];
+ break;
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface");
+ return EGL_NO_SURFACE;
+ }
+ }
+
+ if (width < 1 || height < 1) {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface");
+ return NULL;
+ }
+
+ surf = (struct drm_surface *) calloc(1, sizeof(struct drm_surface));
+ if (!surf)
+ goto err;
+
+ if (!_eglInitSurface(drv, &surf->base, EGL_PBUFFER_BIT, conf, attrib_list))
+ goto err_surf;
+
+ surf->w = width;
+ surf->h = height;
+
+ visual = drm_visual_from_config(conf);
+ surf->stfb = drm_create_framebuffer(visual,
+ width,
+ height,
+ (void*)surf);
+ drm_visual_modes_destroy(visual);
+
+ return &surf->base;
+
+err_surf:
+ free(surf);
+err:
+ return NULL;
+}
+
+_EGLSurface *
+drm_create_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *cfg,
+ const EGLint *attrib_list)
+{
+ EGLSurface surf = drm_create_pbuffer_surface(drv, dpy, cfg, attrib_list);
+
+ return surf;
+}
+
+EGLBoolean
+drm_show_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLScreen *screen,
+ _EGLSurface *surface, _EGLMode *mode)
+{
+ struct drm_device *dev = lookup_drm_device(dpy);
+ struct drm_surface *surf = lookup_drm_surface(surface);
+ struct drm_screen *scrn = lookup_drm_screen(screen);
+ int ret;
+ unsigned int i, k;
+
+ if (scrn->shown)
+ drm_takedown_shown_screen(dpy, scrn);
+
+
+ drm_create_texture(dpy, scrn, mode->Width, mode->Height);
+ if (!scrn->buffer)
+ return EGL_FALSE;
+
+ ret = drmModeAddFB(dev->drmFD,
+ scrn->front.width, scrn->front.height,
+ 32, 32, scrn->front.pitch,
+ scrn->front.handle,
+ &scrn->fbID);
+
+ if (ret)
+ goto err_bo;
+
+ scrn->fb = drmModeGetFB(dev->drmFD, scrn->fbID);
+ if (!scrn->fb)
+ goto err_bo;
+
+ /* find a fitting crtc */
+ {
+ drmModeConnector *con = scrn->connector;
+
+ scrn->mode = drm_find_mode(con, mode);
+ if (!scrn->mode)
+ goto err_fb;
+
+ for (k = 0; k < con->count_encoders; k++) {
+ drmModeEncoder *enc = drmModeGetEncoder(dev->drmFD, con->encoders[k]);
+ for (i = 0; i < dev->res->count_crtcs; i++) {
+ if (enc->possible_crtcs & (1<<i)) {
+ /* save the ID */
+ scrn->crtcID = dev->res->crtcs[i];
+
+ /* skip the rest */
+ i = dev->res->count_crtcs;
+ k = dev->res->count_encoders;
+ }
+ }
+ drmModeFreeEncoder(enc);
+ }
+ }
+
+ ret = drmModeSetCrtc(dev->drmFD,
+ scrn->crtcID,
+ scrn->fbID,
+ 0, 0,
+ &scrn->connectorID, 1,
+ scrn->mode);
+
+ if (ret)
+ goto err_crtc;
+
+
+ if (scrn->dpms)
+ drmModeConnectorSetProperty(dev->drmFD,
+ scrn->connectorID,
+ scrn->dpms->prop_id,
+ DRM_MODE_DPMS_ON);
+
+ surf->screen = scrn;
+
+ scrn->surf = surf;
+ scrn->shown = 1;
+
+ return EGL_TRUE;
+
+err_crtc:
+ scrn->crtcID = 0;
+
+err_fb:
+ drmModeRmFB(dev->drmFD, scrn->fbID);
+ drmModeFreeFB(scrn->fb);
+ scrn->fb = NULL;
+
+err_bo:
+ pipe_surface_reference(&scrn->surface, NULL);
+ pipe_texture_reference(&scrn->tex, NULL);
+ pipe_buffer_reference(&scrn->buffer, NULL);
+
+ return EGL_FALSE;
+}
+
+EGLBoolean
+drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
+{
+ struct drm_surface *surf = lookup_drm_surface(surface);
+ if (!_eglIsSurfaceBound(&surf->base)) {
+ if (surf->screen)
+ drm_takedown_shown_screen(dpy, surf->screen);
+ st_unreference_framebuffer(surf->stfb);
+ free(surf);
+ }
+ return EGL_TRUE;
+}
+
+EGLBoolean
+drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
+{
+ struct drm_device *dev = lookup_drm_device(dpy);
+ struct drm_surface *surf = lookup_drm_surface(draw);
+ struct pipe_surface *back_surf;
+
+ if (!surf)
+ return EGL_FALSE;
+
+ /* error checking */
+ if (!_eglSwapBuffers(drv, dpy, draw))
+ return EGL_FALSE;
+
+ st_get_framebuffer_surface(surf->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
+
+ if (back_surf) {
+
+ st_notify_swapbuffers(surf->stfb);
+
+ if (surf->screen) {
+ surf->user->pipe->surface_copy(surf->user->pipe,
+ surf->screen->surface,
+ 0, 0,
+ back_surf,
+ 0, 0,
+ surf->w, surf->h);
+ surf->user->pipe->flush(surf->user->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL);
+
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ /* TODO query connector property to see if this is needed */
+ drmModeDirtyFB(dev->drmFD, surf->screen->fbID, NULL, 0);
+#else
+ (void)dev;
+#endif
+
+ /* TODO more stuff here */
+ }
+ }
+
+ return EGL_TRUE;
+}
diff --git a/src/gallium/state_trackers/egl/egl_tracker.c b/src/gallium/state_trackers/egl/egl_tracker.c
new file mode 100644
index 0000000000..5140755001
--- /dev/null
+++ b/src/gallium/state_trackers/egl/egl_tracker.c
@@ -0,0 +1,271 @@
+
+#include "utils.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "egl_tracker.h"
+
+#include <fcntl.h>
+
+#include "egllog.h"
+#include "state_tracker/drm_api.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+/** HACK */
+void* driDriverAPI;
+extern const struct dri_extension card_extensions[];
+
+
+/*
+ * Exported functions
+ */
+
+static void
+drm_unload(_EGLDriver *drv)
+{
+ free(drv);
+}
+
+/**
+ * The bootstrap function. Return a new drm_driver object and
+ * plug in API functions.
+ */
+_EGLDriver *
+_eglMain(const char *args)
+{
+ _EGLDriver *drv;
+
+ drv = (_EGLDriver *) calloc(1, sizeof(_EGLDriver));
+ if (!drv) {
+ return NULL;
+ }
+
+ /* First fill in the dispatch table with defaults */
+ _eglInitDriverFallbacks(drv);
+ /* then plug in our Drm-specific functions */
+ drv->API.Initialize = drm_initialize;
+ drv->API.Terminate = drm_terminate;
+ drv->API.CreateContext = drm_create_context;
+ drv->API.MakeCurrent = drm_make_current;
+ drv->API.CreateWindowSurface = drm_create_window_surface;
+ drv->API.CreatePixmapSurface = drm_create_pixmap_surface;
+ drv->API.CreatePbufferSurface = drm_create_pbuffer_surface;
+ drv->API.DestroySurface = drm_destroy_surface;
+ drv->API.DestroyContext = drm_destroy_context;
+ drv->API.CreateScreenSurfaceMESA = drm_create_screen_surface_mesa;
+ drv->API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa;
+ drv->API.SwapBuffers = drm_swap_buffers;
+
+ drv->Name = "DRM/Gallium/Win";
+ drv->Unload = drm_unload;
+
+ return drv;
+}
+
+static void
+drm_get_device_id(struct drm_device *device)
+{
+ char path[512];
+ FILE *file;
+ char *ret;
+
+ /* TODO get the real minor */
+ int minor = 0;
+
+ device->deviceID = 0;
+
+ snprintf(path, sizeof(path), "/sys/class/drm/card%d/device/device", minor);
+ file = fopen(path, "r");
+ if (!file) {
+ _eglLog(_EGL_WARNING, "Could not retrive device ID\n");
+ return;
+ }
+
+ ret = fgets(path, sizeof( path ), file);
+ if (!ret)
+ return;
+
+ sscanf(path, "%x", &device->deviceID);
+ fclose(file);
+}
+
+static void
+drm_update_res(struct drm_device *dev)
+{
+ drmModeFreeResources(dev->res);
+ dev->res = drmModeGetResources(dev->drmFD);
+}
+
+static void
+drm_add_modes_from_connector(_EGLScreen *screen, drmModeConnectorPtr connector)
+{
+ drmModeModeInfoPtr m = NULL;
+ int i;
+
+ for (i = 0; i < connector->count_modes; i++) {
+ m = &connector->modes[i];
+ _eglAddNewMode(screen, m->hdisplay, m->vdisplay, m->vrefresh, m->name);
+ }
+}
+
+static void
+drm_find_dpms(struct drm_device *dev, struct drm_screen *screen)
+{
+ drmModeConnectorPtr c = screen->connector;
+ drmModePropertyPtr p;
+ int i;
+
+ for (i = 0; i < c->count_props; i++) {
+ p = drmModeGetProperty(dev->drmFD, c->props[i]);
+ if (!strcmp(p->name, "DPMS"))
+ break;
+
+ drmModeFreeProperty(p);
+ p = NULL;
+ }
+
+ screen->dpms = p;
+}
+
+static int drm_open_minor(int minor)
+{
+ char buf[64];
+
+ sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ return open(buf, O_RDWR, 0);
+}
+
+EGLBoolean
+drm_initialize(_EGLDriver *drv, _EGLDisplay *disp, EGLint *major, EGLint *minor)
+{
+ struct drm_device *dev;
+ struct drm_screen *screen = NULL;
+ drmModeConnectorPtr connector = NULL;
+ drmModeResPtr res = NULL;
+ unsigned count_connectors = 0;
+ int num_screens = 0;
+ EGLint i;
+ int fd;
+
+ dev = (struct drm_device *) calloc(1, sizeof(struct drm_device));
+ if (!dev)
+ return EGL_FALSE;
+ dev->api = drm_api_create();
+
+ /* try the first node */
+ fd = drm_open_minor(0);
+ if (fd < 0)
+ goto err_fd;
+
+ dev->drmFD = fd;
+ drm_get_device_id(dev);
+
+ dev->screen = dev->api->create_screen(dev->api, dev->drmFD, NULL);
+ if (!dev->screen)
+ goto err_screen;
+ dev->winsys = dev->screen->winsys;
+
+ /* TODO HACK */
+ driInitExtensions(NULL, card_extensions, GL_FALSE);
+
+ drm_update_res(dev);
+ res = dev->res;
+ if (res)
+ count_connectors = res->count_connectors;
+ else
+ _eglLog(_EGL_WARNING, "Could not retrive kms information\n");
+
+ for(i = 0; i < count_connectors && i < MAX_SCREENS; i++) {
+ connector = drmModeGetConnector(fd, res->connectors[i]);
+
+ if (!connector)
+ continue;
+
+ if (connector->connection != DRM_MODE_CONNECTED) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ screen = malloc(sizeof(struct drm_screen));
+ memset(screen, 0, sizeof(*screen));
+ screen->connector = connector;
+ screen->connectorID = connector->connector_id;
+ _eglInitScreen(&screen->base);
+ _eglAddScreen(disp, &screen->base);
+ drm_add_modes_from_connector(&screen->base, connector);
+ drm_find_dpms(dev, screen);
+ dev->screens[num_screens++] = screen;
+ }
+ dev->count_screens = num_screens;
+
+ disp->DriverData = dev;
+
+ /* for now we only have one config */
+ _EGLConfig *config = calloc(1, sizeof(*config));
+ memset(config, 1, sizeof(*config));
+ _eglInitConfig(config, 1);
+ _eglSetConfigAttrib(config, EGL_RED_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32);
+ _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 24);
+ _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
+ _eglAddConfig(disp, config);
+
+ disp->ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/;
+ /* enable supported extensions */
+ disp->Extensions.MESA_screen_surface = EGL_TRUE;
+ disp->Extensions.MESA_copy_context = EGL_TRUE;
+
+ *major = 1;
+ *minor = 4;
+
+ return EGL_TRUE;
+
+err_screen:
+ drmClose(fd);
+err_fd:
+ free(dev);
+ return EGL_FALSE;
+}
+
+EGLBoolean
+drm_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct drm_device *dev = lookup_drm_device(dpy);
+ struct drm_screen *screen;
+ int i = 0;
+
+ _eglReleaseDisplayResources(drv, dpy);
+ _eglCleanupDisplay(dpy);
+
+ drmFreeVersion(dev->version);
+
+ for (i = 0; i < dev->count_screens; i++) {
+ screen = dev->screens[i];
+
+ if (screen->shown)
+ drm_takedown_shown_screen(dpy, screen);
+
+ drmModeFreeProperty(screen->dpms);
+ drmModeFreeConnector(screen->connector);
+ _eglDestroyScreen(&screen->base);
+ dev->screens[i] = NULL;
+ }
+
+ dev->screen->destroy(dev->screen);
+ dev->winsys = NULL;
+
+ drmClose(dev->drmFD);
+
+ dev->api->destroy(dev->api);
+ free(dev);
+ dpy->DriverData = NULL;
+
+ return EGL_TRUE;
+}
diff --git a/src/gallium/state_trackers/egl/egl_tracker.h b/src/gallium/state_trackers/egl/egl_tracker.h
new file mode 100644
index 0000000000..dd4730f957
--- /dev/null
+++ b/src/gallium/state_trackers/egl/egl_tracker.h
@@ -0,0 +1,197 @@
+
+#ifndef _EGL_TRACKER_H_
+#define _EGL_TRACKER_H_
+
+#include <stdint.h>
+
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "eglmode.h"
+#include "eglscreen.h"
+#include "eglsurface.h"
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#include "pipe/p_compiler.h"
+
+#include "state_tracker/st_public.h"
+
+#define MAX_SCREENS 16
+
+struct pipe_winsys;
+struct pipe_screen;
+struct pipe_context;
+struct state_tracker;
+
+struct drm_screen;
+struct drm_context;
+
+struct drm_device
+{
+ /*
+ * pipe
+ */
+
+ struct drm_api *api;
+ struct pipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ /*
+ * drm
+ */
+
+ int drmFD;
+ drmVersionPtr version;
+ int deviceID;
+
+ drmModeResPtr res;
+
+ struct drm_screen *screens[MAX_SCREENS];
+ size_t count_screens;
+};
+
+struct drm_surface
+{
+ _EGLSurface base; /* base class/object */
+
+ /*
+ * pipe
+ */
+
+
+ struct st_framebuffer *stfb;
+
+ /*
+ * drm
+ */
+
+ struct drm_context *user;
+ struct drm_screen *screen;
+
+ int w;
+ int h;
+};
+
+struct drm_context
+{
+ _EGLContext base; /* base class/object */
+
+ /* pipe */
+
+ struct pipe_context *pipe;
+ struct st_context *st;
+};
+
+struct drm_screen
+{
+ _EGLScreen base;
+
+ /*
+ * pipe
+ */
+
+ struct pipe_buffer *buffer;
+ struct pipe_texture *tex;
+ struct pipe_surface *surface;
+
+ /*
+ * drm
+ */
+
+ struct {
+ unsigned height;
+ unsigned width;
+ unsigned pitch;
+ unsigned handle;
+ } front;
+
+ /* currently only support one connector */
+ drmModeConnectorPtr connector;
+ uint32_t connectorID;
+
+ /* dpms property */
+ drmModePropertyPtr dpms;
+
+ /* Has this screen been shown */
+ int shown;
+
+ /* Surface that is currently attached to this screen */
+ struct drm_surface *surf;
+
+ /* framebuffer */
+ drmModeFBPtr fb;
+ uint32_t fbID;
+
+ /* crtc and mode used */
+ /*drmModeCrtcPtr crtc;*/
+ uint32_t crtcID;
+
+ drmModeModeInfoPtr mode;
+};
+
+
+static INLINE struct drm_device *
+lookup_drm_device(_EGLDisplay *d)
+{
+ return (struct drm_device *) d->DriverData;
+}
+
+
+static INLINE struct drm_context *
+lookup_drm_context(_EGLContext *c)
+{
+ return (struct drm_context *) c;
+}
+
+
+static INLINE struct drm_surface *
+lookup_drm_surface(_EGLSurface *s)
+{
+ return (struct drm_surface *) s;
+}
+
+static INLINE struct drm_screen *
+lookup_drm_screen(_EGLScreen *s)
+{
+ return (struct drm_screen *) s;
+}
+
+/**
+ * egl_visual.h
+ */
+/*@{*/
+void drm_visual_modes_destroy(__GLcontextModes *modes);
+__GLcontextModes* drm_visual_modes_create(unsigned count, size_t minimum_size);
+__GLcontextModes* drm_visual_from_config(_EGLConfig *conf);
+/*@}*/
+
+/**
+ * egl_surface.h
+ */
+/*@{*/
+void drm_takedown_shown_screen(_EGLDisplay *dpy, struct drm_screen *screen);
+/*@}*/
+
+/**
+ * All function exported to the egl side.
+ */
+/*@{*/
+EGLBoolean drm_initialize(_EGLDriver *drv, _EGLDisplay *dpy, EGLint *major, EGLint *minor);
+EGLBoolean drm_terminate(_EGLDriver *drv, _EGLDisplay *dpy);
+_EGLContext *drm_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list);
+EGLBoolean drm_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *context);
+_EGLSurface *drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list);
+_EGLSurface *drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list);
+_EGLSurface *drm_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list);
+_EGLSurface *drm_create_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list);
+EGLBoolean drm_show_screen_surface_mesa(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, _EGLSurface *surface, _EGLMode *mode);
+EGLBoolean drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface);
+EGLBoolean drm_make_current(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *context);
+EGLBoolean drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw);
+/*@}*/
+
+#endif
diff --git a/src/gallium/state_trackers/egl/egl_visual.c b/src/gallium/state_trackers/egl/egl_visual.c
new file mode 100644
index 0000000000..e59f893851
--- /dev/null
+++ b/src/gallium/state_trackers/egl/egl_visual.c
@@ -0,0 +1,85 @@
+
+#include "egl_tracker.h"
+
+#include "egllog.h"
+
+void
+drm_visual_modes_destroy(__GLcontextModes *modes)
+{
+ _eglLog(_EGL_DEBUG, "%s", __FUNCTION__);
+
+ while (modes) {
+ __GLcontextModes * const next = modes->next;
+ free(modes);
+ modes = next;
+ }
+}
+
+__GLcontextModes *
+drm_visual_modes_create(unsigned count, size_t minimum_size)
+{
+ /* This code copied from libGLX, and modified */
+ const size_t size = (minimum_size > sizeof(__GLcontextModes))
+ ? minimum_size : sizeof(__GLcontextModes);
+ __GLcontextModes * head = NULL;
+ __GLcontextModes ** next;
+ unsigned i;
+
+ _eglLog(_EGL_DEBUG, "%s %d %d", __FUNCTION__, count, minimum_size);
+
+ next = & head;
+ for (i = 0 ; i < count ; i++) {
+ *next = (__GLcontextModes *) calloc(1, size);
+ if (*next == NULL) {
+ drm_visual_modes_destroy(head);
+ head = NULL;
+ break;
+ }
+
+ (*next)->doubleBufferMode = 1;
+ (*next)->visualID = GLX_DONT_CARE;
+ (*next)->visualType = GLX_DONT_CARE;
+ (*next)->visualRating = GLX_NONE;
+ (*next)->transparentPixel = GLX_NONE;
+ (*next)->transparentRed = GLX_DONT_CARE;
+ (*next)->transparentGreen = GLX_DONT_CARE;
+ (*next)->transparentBlue = GLX_DONT_CARE;
+ (*next)->transparentAlpha = GLX_DONT_CARE;
+ (*next)->transparentIndex = GLX_DONT_CARE;
+ (*next)->xRenderable = GLX_DONT_CARE;
+ (*next)->fbconfigID = GLX_DONT_CARE;
+ (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
+ (*next)->bindToTextureRgb = GLX_DONT_CARE;
+ (*next)->bindToTextureRgba = GLX_DONT_CARE;
+ (*next)->bindToMipmapTexture = GLX_DONT_CARE;
+ (*next)->bindToTextureTargets = 0;
+ (*next)->yInverted = GLX_DONT_CARE;
+
+ next = & ((*next)->next);
+ }
+
+ return head;
+}
+
+__GLcontextModes *
+drm_visual_from_config(_EGLConfig *conf)
+{
+ __GLcontextModes *visual;
+ (void)conf;
+
+ visual = drm_visual_modes_create(1, sizeof(*visual));
+ visual->redBits = 8;
+ visual->greenBits = 8;
+ visual->blueBits = 8;
+ visual->alphaBits = 8;
+
+ visual->rgbBits = 32;
+ visual->doubleBufferMode = 1;
+
+ visual->depthBits = 24;
+ visual->haveDepthBuffer = visual->depthBits > 0;
+ visual->stencilBits = 8;
+ visual->haveStencilBuffer = visual->stencilBits > 0;
+
+ return visual;
+}
diff --git a/src/gallium/state_trackers/es/Makefile b/src/gallium/state_trackers/es/Makefile
new file mode 100644
index 0000000000..1ffabf339a
--- /dev/null
+++ b/src/gallium/state_trackers/es/Makefile
@@ -0,0 +1,100 @@
+# src/gallium/state_trackers/es/Makefile
+
+# Build the ES 1/2 state tracker libraries
+# This consists of core Mesa ES, plus GL/gallium state tracker.
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+GLES_1_VERSION_MAJOR = 1
+GLES_1_VERSION_MINOR = 1
+GLES_1_VERSION_PATCH = 0
+
+GLES_2_VERSION_MAJOR = 2
+GLES_2_VERSION_MINOR = 0
+GLES_2_VERSION_PATCH = 0
+
+
+# Maybe move these into configs/default:
+GLES_1_LIB = GLESv1_CM
+GLES_1_LIB_NAME = lib$(GLES_1_LIB).so
+GLES_2_LIB = GLESv2
+GLES_2_LIB_NAME = lib$(GLES_2_LIB).so
+
+
+INCLUDE_DIRS = \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/include
+
+ES1_SOURCES = \
+ st_es1.c \
+
+ES1_OBJECTS = $(ES1_SOURCES:.c=.o)
+
+ES2_SOURCES = \
+ st_es2.c \
+
+ES2_OBJECTS = $(ES2_SOURCES:.c=.o)
+
+
+# we only need the gallium libs that the state trackers directly use:
+GALLIUM_LIBS = \
+ $(TOP)/src/gallium/auxiliary/cso_cache/libcso_cache.a \
+ $(TOP)/src/gallium/auxiliary/rtasm/librtasm.a \
+ $(TOP)/src/gallium/auxiliary/tgsi/libtgsi.a \
+ $(TOP)/src/gallium/auxiliary/util/libutil.a
+
+ES1_LIBS = \
+ $(TOP)/src/mesa/es/libes1gallium.a \
+ $(TOP)/src/mesa/es/libes1api.a
+
+ES2_LIBS = \
+ $(TOP)/src/mesa/es/libes2gallium.a \
+ $(TOP)/src/mesa/es/libes2api.a
+
+SYS_LIBS = -lm -pthread
+
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+# Default: make both GL ES 1.1 and GL ES 2.0 libraries
+default: $(TOP)/$(LIB_DIR)/$(GLES_1_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLES_2_LIB_NAME)
+
+# Make the shared libs
+$(TOP)/$(LIB_DIR)/$(GLES_1_LIB_NAME): $(ES1_OBJECTS) $(ES1_LIBS)
+ $(TOP)/bin/mklib -o $(GLES_1_LIB) \
+ -major $(GLES_1_VERSION_MAJOR) \
+ -minor $(GLES_1_VERSION_MINOR) \
+ -patch $(GLES_1_VERSION_PATCH) \
+ -install $(TOP)/$(LIB_DIR) \
+ $(ES1_OBJECTS) \
+ -Wl,--whole-archive $(ES1_LIBS) -Wl,--no-whole-archive \
+ -Wl,--start-group $(GALLIUM_LIBS) -Wl,--end-group \
+ $(SYS_LIBS)
+
+$(TOP)/$(LIB_DIR)/$(GLES_2_LIB_NAME): $(ES2_OBJECTS) $(ES1_LIBS)
+ $(TOP)/bin/mklib -o $(GLES_2_LIB) \
+ -major $(GLES_2_VERSION_MAJOR) \
+ -minor $(GLES_2_VERSION_MINOR) \
+ -patch $(GLES_2_VERSION_PATCH) \
+ -install $(TOP)/$(LIB_DIR) \
+ $(ES2_OBJECTS) \
+ -Wl,--whole-archive $(ES2_LIBS) -Wl,--no-whole-archive \
+ -Wl,--start-group $(GALLIUM_LIBS) -Wl,--end-group \
+ $(SYS_LIBS)
+
+install: default
+ $(INSTALL) -d $(INSTALL_DIR)/include/GLES
+ $(INSTALL) -m 644 $(TOP)/include/GLES/*.h $(INSTALL_DIR)/include/GLES
+ $(INSTALL) -d $(INSTALL_DIR)/include/GLES2
+ $(INSTALL) -m 644 $(TOP)/include/GLES2/*.h $(INSTALL_DIR)/include/GLES2
+ $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR)
+ $(INSTALL) $(TOP)/$(LIB_DIR)/libGLESv1* $(INSTALL_DIR)/$(LIB_DIR)
+ $(INSTALL) $(TOP)/$(LIB_DIR)/libGLESv2* $(INSTALL_DIR)/$(LIB_DIR)
+
+clean:
+ -rm -f *.o *~
+ -rm -f $(TOP)/$(LIB_DIR)/$(GLES_1_LIB_NAME)* $(TOP)/$(LIB_DIR)/$(GLES_2_LIB_NAME)*
+ -rm -f *.pyc
diff --git a/src/gallium/state_trackers/es/st_es1.c b/src/gallium/state_trackers/es/st_es1.c
new file mode 100644
index 0000000000..7f0c038957
--- /dev/null
+++ b/src/gallium/state_trackers/es/st_es1.c
@@ -0,0 +1 @@
+const int st_api_OpenGL_ES1 = 1;
diff --git a/src/gallium/state_trackers/es/st_es2.c b/src/gallium/state_trackers/es/st_es2.c
new file mode 100644
index 0000000000..78e3791fbe
--- /dev/null
+++ b/src/gallium/state_trackers/es/st_es2.c
@@ -0,0 +1 @@
+const int st_api_OpenGL_ES2 = 1;
diff --git a/src/gallium/state_trackers/g3dvl/Makefile b/src/gallium/state_trackers/g3dvl/Makefile
new file mode 100644
index 0000000000..f9f4d6be3c
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/Makefile
@@ -0,0 +1,21 @@
+TARGET = libg3dvl.a
+OBJECTS = vl_display.o vl_screen.o vl_context.o vl_surface.o vl_shader_build.o vl_util.o vl_basic_csc.o \
+ vl_r16snorm_mc_buf.o
+GALLIUMDIR = ../..
+
+CFLAGS += -g -Wall -Werror-implicit-function-declaration -fPIC \
+ -I${GALLIUMDIR}/include \
+ -I${GALLIUMDIR}/auxiliary \
+ -I${GALLIUMDIR}/winsys/g3dvl \
+
+#############################################
+
+.PHONY = all clean
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS}
+ ar rcs $@ $^
+
+clean:
+ rm -rf ${OBJECTS} ${TARGET}
diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c
new file mode 100644
index 0000000000..20d682de3f
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c
@@ -0,0 +1,714 @@
+#define VL_INTERNAL
+#include "vl_basic_csc.h"
+#include <assert.h>
+#include <pipe/p_context.h>
+#include <pipe/p_state.h>
+#include <pipe/p_inlines.h>
+#include <tgsi/tgsi_parse.h>
+#include <tgsi/tgsi_build.h>
+#include <util/u_memory.h>
+#include "vl_csc.h"
+#include "vl_surface.h"
+#include "vl_shader_build.h"
+#include "vl_types.h"
+
+struct vlVertexShaderConsts
+{
+ struct vlVertex4f dst_scale;
+ struct vlVertex4f dst_trans;
+ struct vlVertex4f src_scale;
+ struct vlVertex4f src_trans;
+};
+
+struct vlFragmentShaderConsts
+{
+ struct vlVertex4f bias;
+ float matrix[16];
+};
+
+struct vlBasicCSC
+{
+ struct vlCSC base;
+
+ struct pipe_context *pipe;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_texture *framebuffer_tex;
+ void *sampler;
+ void *vertex_shader, *fragment_shader;
+ struct pipe_vertex_buffer vertex_bufs[2];
+ struct pipe_vertex_element vertex_elems[2];
+ struct pipe_constant_buffer vs_const_buf, fs_const_buf;
+};
+
+static int vlResizeFrameBuffer
+(
+ struct vlCSC *csc,
+ unsigned int width,
+ unsigned int height
+)
+{
+ struct vlBasicCSC *basic_csc;
+ struct pipe_context *pipe;
+ struct pipe_texture template;
+
+ assert(csc);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+ pipe = basic_csc->pipe;
+
+ if (basic_csc->framebuffer.width == width && basic_csc->framebuffer.height == height)
+ return 0;
+
+ basic_csc->viewport.scale[0] = width;
+ basic_csc->viewport.scale[1] = height;
+ basic_csc->viewport.scale[2] = 1;
+ basic_csc->viewport.scale[3] = 1;
+ basic_csc->viewport.translate[0] = 0;
+ basic_csc->viewport.translate[1] = 0;
+ basic_csc->viewport.translate[2] = 0;
+ basic_csc->viewport.translate[3] = 0;
+
+ if (basic_csc->framebuffer_tex)
+ {
+ pipe_surface_reference(&basic_csc->framebuffer.cbufs[0], NULL);
+ pipe_texture_reference(&basic_csc->framebuffer_tex, NULL);
+ }
+
+ memset(&template, 0, sizeof(struct pipe_texture));
+ template.target = PIPE_TEXTURE_2D;
+ template.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ template.last_level = 0;
+ template.width[0] = width;
+ template.height[0] = height;
+ template.depth[0] = 1;
+ pf_get_block(template.format, &template.block);
+ template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
+ basic_csc->framebuffer_tex = pipe->screen->texture_create(pipe->screen, &template);
+
+ basic_csc->framebuffer.width = width;
+ basic_csc->framebuffer.height = height;
+ basic_csc->framebuffer.cbufs[0] = pipe->screen->get_tex_surface
+ (
+ pipe->screen,
+ basic_csc->framebuffer_tex,
+ 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
+ );
+
+ /* Clear to black, in case video doesn't fill the entire window */
+ pipe->set_framebuffer_state(pipe, &basic_csc->framebuffer);
+ pipe->clear(pipe, PIPE_CLEAR_COLOR, 0, 0.0f, 0);
+
+ return 0;
+}
+
+static int vlBegin
+(
+ struct vlCSC *csc
+)
+{
+ struct vlBasicCSC *basic_csc;
+ struct pipe_context *pipe;
+
+ assert(csc);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+ pipe = basic_csc->pipe;
+
+ pipe->set_framebuffer_state(pipe, &basic_csc->framebuffer);
+ pipe->set_viewport_state(pipe, &basic_csc->viewport);
+ pipe->bind_sampler_states(pipe, 1, (void**)&basic_csc->sampler);
+ /* Source texture set in vlPutPictureCSC() */
+ pipe->bind_vs_state(pipe, basic_csc->vertex_shader);
+ pipe->bind_fs_state(pipe, basic_csc->fragment_shader);
+ pipe->set_vertex_buffers(pipe, 2, basic_csc->vertex_bufs);
+ pipe->set_vertex_elements(pipe, 2, basic_csc->vertex_elems);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &basic_csc->vs_const_buf);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &basic_csc->fs_const_buf);
+
+ return 0;
+}
+
+static int vlPutPictureCSC
+(
+ struct vlCSC *csc,
+ struct vlSurface *surface,
+ int srcx,
+ int srcy,
+ int srcw,
+ int srch,
+ int destx,
+ int desty,
+ int destw,
+ int desth,
+ enum vlPictureType picture_type
+)
+{
+ struct vlBasicCSC *basic_csc;
+ struct pipe_context *pipe;
+ struct vlVertexShaderConsts *vs_consts;
+
+ assert(csc);
+ assert(surface);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+ pipe = basic_csc->pipe;
+
+ vs_consts = pipe_buffer_map
+ (
+ pipe->screen,
+ basic_csc->vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
+ );
+
+ vs_consts->dst_scale.x = destw / (float)basic_csc->framebuffer.cbufs[0]->width;
+ vs_consts->dst_scale.y = desth / (float)basic_csc->framebuffer.cbufs[0]->height;
+ vs_consts->dst_scale.z = 1;
+ vs_consts->dst_scale.w = 1;
+ vs_consts->dst_trans.x = destx / (float)basic_csc->framebuffer.cbufs[0]->width;
+ vs_consts->dst_trans.y = desty / (float)basic_csc->framebuffer.cbufs[0]->height;
+ vs_consts->dst_trans.z = 0;
+ vs_consts->dst_trans.w = 0;
+
+ vs_consts->src_scale.x = srcw / (float)surface->texture->width[0];
+ vs_consts->src_scale.y = srch / (float)surface->texture->height[0];
+ vs_consts->src_scale.z = 1;
+ vs_consts->src_scale.w = 1;
+ vs_consts->src_trans.x = srcx / (float)surface->texture->width[0];
+ vs_consts->src_trans.y = srcy / (float)surface->texture->height[0];
+ vs_consts->src_trans.z = 0;
+ vs_consts->src_trans.w = 0;
+
+ pipe_buffer_unmap(pipe->screen, basic_csc->vs_const_buf.buffer);
+
+ pipe->set_sampler_textures(pipe, 1, &surface->texture);
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
+
+ return 0;
+}
+
+static int vlEnd
+(
+ struct vlCSC *csc
+)
+{
+ assert(csc);
+
+ return 0;
+}
+
+static struct pipe_surface* vlGetFrameBuffer
+(
+ struct vlCSC *csc
+)
+{
+ struct vlBasicCSC *basic_csc;
+
+ assert(csc);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+
+ return basic_csc->framebuffer.cbufs[0];
+}
+
+static int vlDestroy
+(
+ struct vlCSC *csc
+)
+{
+ struct vlBasicCSC *basic_csc;
+ struct pipe_context *pipe;
+ unsigned int i;
+
+ assert(csc);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+ pipe = basic_csc->pipe;
+
+ if (basic_csc->framebuffer_tex)
+ {
+ pipe_surface_reference(&basic_csc->framebuffer.cbufs[0], NULL);
+ pipe_texture_reference(&basic_csc->framebuffer_tex, NULL);
+ }
+
+ pipe->delete_sampler_state(pipe, basic_csc->sampler);
+ pipe->delete_vs_state(pipe, basic_csc->vertex_shader);
+ pipe->delete_fs_state(pipe, basic_csc->fragment_shader);
+
+ for (i = 0; i < 2; ++i)
+ pipe_buffer_reference(&basic_csc->vertex_bufs[i].buffer, NULL);
+
+ pipe_buffer_reference(&basic_csc->vs_const_buf.buffer, NULL);
+ pipe_buffer_reference(&basic_csc->fs_const_buf.buffer, NULL);
+
+ FREE(basic_csc);
+
+ return 0;
+}
+
+/*
+ * Represents 2 triangles in a strip in normalized coords.
+ * Used to render the surface onto the frame buffer.
+ */
+static const struct vlVertex2f surface_verts[4] =
+{
+ {0.0f, 0.0f},
+ {0.0f, 1.0f},
+ {1.0f, 0.0f},
+ {1.0f, 1.0f}
+};
+
+/*
+ * Represents texcoords for the above. We can use the position values directly.
+ * TODO: Duplicate these in the shader, no need to create a buffer.
+ */
+static const struct vlVertex2f *surface_texcoords = surface_verts;
+
+/*
+ * Identity color conversion constants, for debugging
+ */
+static const struct vlFragmentShaderConsts identity =
+{
+ {
+ 0.0f, 0.0f, 0.0f, 0.0f
+ },
+ {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ }
+};
+
+/*
+ * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [16,235]
+ */
+static const struct vlFragmentShaderConsts bt_601 =
+{
+ {
+ 0.0f, 0.501960784f, 0.501960784f, 0.0f
+ },
+ {
+ 1.0f, 0.0f, 1.371f, 0.0f,
+ 1.0f, -0.336f, -0.698f, 0.0f,
+ 1.0f, 1.732f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ }
+};
+
+/*
+ * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [0,255]
+ */
+static const struct vlFragmentShaderConsts bt_601_full =
+{
+ {
+ 0.062745098f, 0.501960784f, 0.501960784f, 0.0f
+ },
+ {
+ 1.164f, 0.0f, 1.596f, 0.0f,
+ 1.164f, -0.391f, -0.813f, 0.0f,
+ 1.164f, 2.018f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ }
+};
+
+/*
+ * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [16,235]
+ */
+static const struct vlFragmentShaderConsts bt_709 =
+{
+ {
+ 0.0f, 0.501960784f, 0.501960784f, 0.0f
+ },
+ {
+ 1.0f, 0.0f, 1.540f, 0.0f,
+ 1.0f, -0.183f, -0.459f, 0.0f,
+ 1.0f, 1.816f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ }
+};
+
+/*
+ * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [0,255]
+ */
+const struct vlFragmentShaderConsts bt_709_full =
+{
+ {
+ 0.062745098f, 0.501960784f, 0.501960784f, 0.0f
+ },
+ {
+ 1.164f, 0.0f, 1.793f, 0.0f,
+ 1.164f, -0.213f, -0.534f, 0.0f,
+ 1.164f, 2.115f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ }
+};
+
+static int vlCreateVertexShader
+(
+ struct vlBasicCSC *csc
+)
+{
+ const unsigned int max_tokens = 50;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state vs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(csc);
+
+ pipe = csc->pipe;
+ tokens = (struct tgsi_token*)MALLOC(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Vertex pos
+ * decl i1 ; Vertex texcoords
+ */
+ for (i = 0; i < 2; i++)
+ {
+ decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * decl c0 ; Scaling vector to scale vertex pos rect to destination size
+ * decl c1 ; Translation vector to move vertex pos rect into position
+ * decl c2 ; Scaling vector to scale texcoord rect to source size
+ * decl c3 ; Translation vector to move texcoord rect into position
+ */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 3);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl o0 ; Vertex pos
+ * decl o1 ; Vertex texcoords
+ */
+ for (i = 0; i < 2; i++)
+ {
+ decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* decl t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * madd o0, i0, c0, c1 ; Scale and translate unit output rect to destination size and pos
+ * madd o1, i1, c2, c3 ; Scale and translate unit texcoord rect to source size and pos
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_inst4(TGSI_OPCODE_MADD, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i, TGSI_FILE_CONSTANT, i * 2, TGSI_FILE_CONSTANT, i * 2 + 1);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ vs.tokens = tokens;
+ csc->vertex_shader = pipe->create_vs_state(pipe, &vs);
+ FREE(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShader
+(
+ struct vlBasicCSC *csc
+)
+{
+ const unsigned int max_tokens = 50;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state fs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(csc);
+
+ pipe = csc->pipe;
+ tokens = (struct tgsi_token*)MALLOC(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+ ti = 3;
+
+ /* decl i0 ; Texcoords for s0 */
+ decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, 1, 0, 0, TGSI_INTERPOLATE_LINEAR);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl c0 ; Bias vector for CSC
+ * decl c1-c4 ; CSC matrix c1-c4
+ */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 4);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl o0 ; Fragment color */
+ decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl t0 */
+ decl = vl_decl_temps(0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl s0 ; Sampler for tex containing picture to display */
+ decl = vl_decl_samplers(0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* tex2d t0, i0, s0 ; Read src pixel */
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_SAMPLER, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* sub t0, t0, c0 ; Subtract bias vector from pixel */
+ inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * dp4 o0.x, t0, c1 ; Multiply pixel by the color conversion matrix
+ * dp4 o0.y, t0, c2
+ * dp4 o0.z, t0, c3
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 1);
+ inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ fs.tokens = tokens;
+ csc->fragment_shader = pipe->create_fs_state(pipe, &fs);
+ FREE(tokens);
+
+ return 0;
+}
+
+static int vlCreateDataBufs
+(
+ struct vlBasicCSC *csc
+)
+{
+ struct pipe_context *pipe;
+
+ assert(csc);
+
+ pipe = csc->pipe;
+
+ /*
+ * Create our vertex buffer and vertex buffer element
+ * VB contains 4 vertices that render a quad covering the entire window
+ * to display a rendered surface
+ * Quad is rendered as a tri strip
+ */
+ csc->vertex_bufs[0].stride = sizeof(struct vlVertex2f);
+ csc->vertex_bufs[0].max_index = 3;
+ csc->vertex_bufs[0].buffer_offset = 0;
+ csc->vertex_bufs[0].buffer = pipe_buffer_create
+ (
+ pipe->screen,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 4
+ );
+
+ memcpy
+ (
+ pipe_buffer_map(pipe->screen, csc->vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ surface_verts,
+ sizeof(struct vlVertex2f) * 4
+ );
+
+ pipe_buffer_unmap(pipe->screen, csc->vertex_bufs[0].buffer);
+
+ csc->vertex_elems[0].src_offset = 0;
+ csc->vertex_elems[0].vertex_buffer_index = 0;
+ csc->vertex_elems[0].nr_components = 2;
+ csc->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /*
+ * Create our texcoord buffer and texcoord buffer element
+ * Texcoord buffer contains the TCs for mapping the rendered surface to the 4 vertices
+ */
+ csc->vertex_bufs[1].stride = sizeof(struct vlVertex2f);
+ csc->vertex_bufs[1].max_index = 3;
+ csc->vertex_bufs[1].buffer_offset = 0;
+ csc->vertex_bufs[1].buffer = pipe_buffer_create
+ (
+ pipe->screen,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 4
+ );
+
+ memcpy
+ (
+ pipe_buffer_map(pipe->screen, csc->vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ surface_texcoords,
+ sizeof(struct vlVertex2f) * 4
+ );
+
+ pipe_buffer_unmap(pipe->screen, csc->vertex_bufs[1].buffer);
+
+ csc->vertex_elems[1].src_offset = 0;
+ csc->vertex_elems[1].vertex_buffer_index = 1;
+ csc->vertex_elems[1].nr_components = 2;
+ csc->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /*
+ * Create our vertex shader's constant buffer
+ * Const buffer contains scaling and translation vectors
+ */
+ csc->vs_const_buf.buffer = pipe_buffer_create
+ (
+ pipe->screen,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT | PIPE_BUFFER_USAGE_DISCARD,
+ sizeof(struct vlVertexShaderConsts)
+ );
+
+ /*
+ * Create our fragment shader's constant buffer
+ * Const buffer contains the color conversion matrix and bias vectors
+ */
+ csc->fs_const_buf.buffer = pipe_buffer_create
+ (
+ pipe->screen,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ sizeof(struct vlFragmentShaderConsts)
+ );
+
+ /*
+ * TODO: Refactor this into a seperate function,
+ * allow changing the CSC matrix at runtime to switch between regular & full versions
+ */
+ memcpy
+ (
+ pipe_buffer_map(pipe->screen, csc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ &bt_601_full,
+ sizeof(struct vlFragmentShaderConsts)
+ );
+
+ pipe_buffer_unmap(pipe->screen, csc->fs_const_buf.buffer);
+
+ return 0;
+}
+
+static int vlInit
+(
+ struct vlBasicCSC *csc
+)
+{
+ struct pipe_context *pipe;
+ struct pipe_sampler_state sampler;
+
+ assert(csc);
+
+ pipe = csc->pipe;
+
+ /* Delay creating the FB until vlPutPictureCSC() so we know window size */
+ csc->framebuffer_tex = NULL;
+ csc->framebuffer.width = 0;
+ csc->framebuffer.height = 0;
+ csc->framebuffer.nr_cbufs = 1;
+ csc->framebuffer.cbufs[0] = NULL;
+ csc->framebuffer.zsbuf = NULL;
+
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
+ sampler.compare_func = PIPE_FUNC_ALWAYS;
+ sampler.normalized_coords = 1;
+ /*sampler.prefilter = ;*/
+ /*sampler.lod_bias = ;*/
+ /*sampler.min_lod = ;*/
+ /*sampler.max_lod = ;*/
+ /*sampler.border_color[i] = ;*/
+ /*sampler.max_anisotropy = ;*/
+ csc->sampler = pipe->create_sampler_state(pipe, &sampler);
+
+ vlCreateVertexShader(csc);
+ vlCreateFragmentShader(csc);
+ vlCreateDataBufs(csc);
+
+ return 0;
+}
+
+int vlCreateBasicCSC
+(
+ struct pipe_context *pipe,
+ struct vlCSC **csc
+)
+{
+ struct vlBasicCSC *basic_csc;
+
+ assert(pipe);
+ assert(csc);
+
+ basic_csc = CALLOC_STRUCT(vlBasicCSC);
+
+ if (!basic_csc)
+ return 1;
+
+ basic_csc->base.vlResizeFrameBuffer = &vlResizeFrameBuffer;
+ basic_csc->base.vlBegin = &vlBegin;
+ basic_csc->base.vlPutPicture = &vlPutPictureCSC;
+ basic_csc->base.vlEnd = &vlEnd;
+ basic_csc->base.vlGetFrameBuffer = &vlGetFrameBuffer;
+ basic_csc->base.vlDestroy = &vlDestroy;
+ basic_csc->pipe = pipe;
+
+ vlInit(basic_csc);
+
+ *csc = &basic_csc->base;
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.h b/src/gallium/state_trackers/g3dvl/vl_basic_csc.h
new file mode 100644
index 0000000000..2e17f1d814
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.h
@@ -0,0 +1,13 @@
+#ifndef vl_basic_csc_h
+#define vl_basic_csc_h
+
+struct pipe_context;
+struct vlCSC;
+
+int vlCreateBasicCSC
+(
+ struct pipe_context *pipe,
+ struct vlCSC **csc
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_context.c b/src/gallium/state_trackers/g3dvl/vl_context.c
new file mode 100644
index 0000000000..5cfd233c4c
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_context.c
@@ -0,0 +1,205 @@
+#define VL_INTERNAL
+#include "vl_context.h"
+#include <assert.h>
+#include <pipe/p_context.h>
+#include <pipe/p_state.h>
+#include <util/u_memory.h>
+#include "vl_render.h"
+#include "vl_r16snorm_mc_buf.h"
+#include "vl_csc.h"
+#include "vl_basic_csc.h"
+
+static int vlInitCommon(struct vlContext *context)
+{
+ struct pipe_context *pipe;
+ struct pipe_rasterizer_state rast;
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state dsa;
+ unsigned int i;
+
+ assert(context);
+
+ pipe = context->pipe;
+
+ rast.flatshade = 1;
+ rast.flatshade_first = 0;
+ rast.light_twoside = 0;
+ rast.front_winding = PIPE_WINDING_CCW;
+ rast.cull_mode = PIPE_WINDING_CW;
+ rast.fill_cw = PIPE_POLYGON_MODE_FILL;
+ rast.fill_ccw = PIPE_POLYGON_MODE_FILL;
+ rast.offset_cw = 0;
+ rast.offset_ccw = 0;
+ rast.scissor = 0;
+ rast.poly_smooth = 0;
+ rast.poly_stipple_enable = 0;
+ rast.point_sprite = 0;
+ rast.point_size_per_vertex = 0;
+ rast.multisample = 0;
+ rast.line_smooth = 0;
+ rast.line_stipple_enable = 0;
+ rast.line_stipple_factor = 0;
+ rast.line_stipple_pattern = 0;
+ rast.line_last_pixel = 0;
+ rast.bypass_vs_clip_and_viewport = 0;
+ rast.line_width = 1;
+ rast.point_smooth = 0;
+ rast.point_size = 1;
+ rast.offset_units = 1;
+ rast.offset_scale = 1;
+ /*rast.sprite_coord_mode[i] = ;*/
+ context->raster = pipe->create_rasterizer_state(pipe, &rast);
+ pipe->bind_rasterizer_state(pipe, context->raster);
+
+ blend.blend_enable = 0;
+ blend.rgb_func = PIPE_BLEND_ADD;
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_func = PIPE_BLEND_ADD;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+ blend.logicop_enable = 0;
+ blend.logicop_func = PIPE_LOGICOP_CLEAR;
+ /* Needed to allow color writes to FB, even if blending disabled */
+ blend.colormask = PIPE_MASK_RGBA;
+ blend.dither = 0;
+ context->blend = pipe->create_blend_state(pipe, &blend);
+ pipe->bind_blend_state(pipe, context->blend);
+
+ dsa.depth.enabled = 0;
+ dsa.depth.writemask = 0;
+ dsa.depth.func = PIPE_FUNC_ALWAYS;
+ dsa.depth.occlusion_count = 0;
+ for (i = 0; i < 2; ++i)
+ {
+ dsa.stencil[i].enabled = 0;
+ dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[i].ref_value = 0;
+ dsa.stencil[i].valuemask = 0;
+ dsa.stencil[i].writemask = 0;
+ }
+ dsa.alpha.enabled = 0;
+ dsa.alpha.func = PIPE_FUNC_ALWAYS;
+ dsa.alpha.ref_value = 0;
+ context->dsa = pipe->create_depth_stencil_alpha_state(pipe, &dsa);
+ pipe->bind_depth_stencil_alpha_state(pipe, context->dsa);
+
+ return 0;
+}
+
+int vlCreateContext
+(
+ struct vlScreen *screen,
+ struct pipe_context *pipe,
+ unsigned int picture_width,
+ unsigned int picture_height,
+ enum vlFormat picture_format,
+ enum vlProfile profile,
+ enum vlEntryPoint entry_point,
+ struct vlContext **context
+)
+{
+ struct vlContext *ctx;
+
+ assert(screen);
+ assert(context);
+ assert(pipe);
+
+ ctx = CALLOC_STRUCT(vlContext);
+
+ if (!ctx)
+ return 1;
+
+ ctx->screen = screen;
+ ctx->pipe = pipe;
+ ctx->picture_width = picture_width;
+ ctx->picture_height = picture_height;
+ ctx->picture_format = picture_format;
+ ctx->profile = profile;
+ ctx->entry_point = entry_point;
+
+ vlInitCommon(ctx);
+
+ vlCreateR16SNormBufferedMC(pipe, picture_width, picture_height, picture_format, &ctx->render);
+ vlCreateBasicCSC(pipe, &ctx->csc);
+
+ *context = ctx;
+
+ return 0;
+}
+
+int vlDestroyContext
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ /* XXX: Must unbind shaders before we can delete them for some reason */
+ context->pipe->bind_vs_state(context->pipe, NULL);
+ context->pipe->bind_fs_state(context->pipe, NULL);
+
+ context->render->vlDestroy(context->render);
+ context->csc->vlDestroy(context->csc);
+
+ context->pipe->delete_blend_state(context->pipe, context->blend);
+ context->pipe->delete_rasterizer_state(context->pipe, context->raster);
+ context->pipe->delete_depth_stencil_alpha_state(context->pipe, context->dsa);
+
+ FREE(context);
+
+ return 0;
+}
+
+struct vlScreen* vlContextGetScreen
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->screen;
+}
+
+struct pipe_context* vlGetPipeContext
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->pipe;
+}
+
+unsigned int vlGetPictureWidth
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->picture_width;
+}
+
+unsigned int vlGetPictureHeight
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->picture_height;
+}
+
+enum vlFormat vlGetPictureFormat
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->picture_format;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_context.h b/src/gallium/state_trackers/g3dvl/vl_context.h
new file mode 100644
index 0000000000..3d14634c44
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_context.h
@@ -0,0 +1,73 @@
+#ifndef vl_context_h
+#define vl_context_h
+
+#include "vl_types.h"
+
+struct pipe_context;
+
+#ifdef VL_INTERNAL
+struct vlRender;
+struct vlCSC;
+
+struct vlContext
+{
+ struct vlScreen *screen;
+ struct pipe_context *pipe;
+ unsigned int picture_width;
+ unsigned int picture_height;
+ enum vlFormat picture_format;
+ enum vlProfile profile;
+ enum vlEntryPoint entry_point;
+
+ void *raster;
+ void *dsa;
+ void *blend;
+
+ struct vlRender *render;
+ struct vlCSC *csc;
+};
+#endif
+
+int vlCreateContext
+(
+ struct vlScreen *screen,
+ struct pipe_context *pipe,
+ unsigned int picture_width,
+ unsigned int picture_height,
+ enum vlFormat picture_format,
+ enum vlProfile profile,
+ enum vlEntryPoint entry_point,
+ struct vlContext **context
+);
+
+int vlDestroyContext
+(
+ struct vlContext *context
+);
+
+struct vlScreen* vlContextGetScreen
+(
+ struct vlContext *context
+);
+
+struct pipe_context* vlGetPipeContext
+(
+ struct vlContext *context
+);
+
+unsigned int vlGetPictureWidth
+(
+ struct vlContext *context
+);
+
+unsigned int vlGetPictureHeight
+(
+ struct vlContext *context
+);
+
+enum vlFormat vlGetPictureFormat
+(
+ struct vlContext *context
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_csc.h b/src/gallium/state_trackers/g3dvl/vl_csc.h
new file mode 100644
index 0000000000..36417a2792
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_csc.h
@@ -0,0 +1,53 @@
+#ifndef vl_csc_h
+#define vl_csc_h
+
+#include "vl_types.h"
+
+struct pipe_surface;
+
+struct vlCSC
+{
+ int (*vlResizeFrameBuffer)
+ (
+ struct vlCSC *csc,
+ unsigned int width,
+ unsigned int height
+ );
+
+ int (*vlBegin)
+ (
+ struct vlCSC *csc
+ );
+
+ int (*vlPutPicture)
+ (
+ struct vlCSC *csc,
+ struct vlSurface *surface,
+ int srcx,
+ int srcy,
+ int srcw,
+ int srch,
+ int destx,
+ int desty,
+ int destw,
+ int desth,
+ enum vlPictureType picture_type
+ );
+
+ int (*vlEnd)
+ (
+ struct vlCSC *csc
+ );
+
+ struct pipe_surface* (*vlGetFrameBuffer)
+ (
+ struct vlCSC *csc
+ );
+
+ int (*vlDestroy)
+ (
+ struct vlCSC *csc
+ );
+};
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_defs.h b/src/gallium/state_trackers/g3dvl/vl_defs.h
new file mode 100644
index 0000000000..d612d02502
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_defs.h
@@ -0,0 +1,11 @@
+#ifndef vl_defs_h
+#define vl_defs_h
+
+#define VL_BLOCK_WIDTH 8
+#define VL_BLOCK_HEIGHT 8
+#define VL_BLOCK_SIZE (VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT)
+#define VL_MACROBLOCK_WIDTH 16
+#define VL_MACROBLOCK_HEIGHT 16
+#define VL_MACROBLOCK_SIZE (VL_MACROBLOCK_WIDTH * VL_MACROBLOCK_HEIGHT)
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_display.c b/src/gallium/state_trackers/g3dvl/vl_display.c
new file mode 100644
index 0000000000..dce06de758
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_display.c
@@ -0,0 +1,48 @@
+#define VL_INTERNAL
+#include "vl_display.h"
+#include <assert.h>
+#include <util/u_memory.h>
+
+int vlCreateDisplay
+(
+ vlNativeDisplay native_display,
+ struct vlDisplay **display
+)
+{
+ struct vlDisplay *dpy;
+
+ assert(native_display);
+ assert(display);
+
+ dpy = CALLOC_STRUCT(vlDisplay);
+
+ if (!dpy)
+ return 1;
+
+ dpy->native = native_display;
+ *display = dpy;
+
+ return 0;
+}
+
+int vlDestroyDisplay
+(
+ struct vlDisplay *display
+)
+{
+ assert(display);
+
+ FREE(display);
+
+ return 0;
+}
+
+vlNativeDisplay vlGetNativeDisplay
+(
+ struct vlDisplay *display
+)
+{
+ assert(display);
+
+ return display->native;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_display.h b/src/gallium/state_trackers/g3dvl/vl_display.h
new file mode 100644
index 0000000000..e11fd40799
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_display.h
@@ -0,0 +1,29 @@
+#ifndef vl_display_h
+#define vl_display_h
+
+#include "vl_types.h"
+
+#ifdef VL_INTERNAL
+struct vlDisplay
+{
+ vlNativeDisplay native;
+};
+#endif
+
+int vlCreateDisplay
+(
+ vlNativeDisplay native_display,
+ struct vlDisplay **display
+);
+
+int vlDestroyDisplay
+(
+ struct vlDisplay *display
+);
+
+vlNativeDisplay vlGetNativeDisplay
+(
+ struct vlDisplay *display
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
new file mode 100644
index 0000000000..23631adb69
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
@@ -0,0 +1,1155 @@
+#define VL_INTERNAL
+#include "vl_r16snorm_mc_buf.h"
+#include <assert.h>
+#include <pipe/p_context.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_state.h>
+#include <pipe/p_inlines.h>
+#include <tgsi/tgsi_parse.h>
+#include <tgsi/tgsi_build.h>
+#include <util/u_math.h>
+#include <util/u_memory.h>
+#include "vl_render.h"
+#include "vl_shader_build.h"
+#include "vl_surface.h"
+#include "vl_util.h"
+#include "vl_types.h"
+#include "vl_defs.h"
+
+const unsigned int DEFAULT_BUF_ALIGNMENT = 1;
+
+enum vlMacroBlockTypeEx
+{
+ vlMacroBlockExTypeIntra,
+ vlMacroBlockExTypeFwdPredictedFrame,
+ vlMacroBlockExTypeFwdPredictedField,
+ vlMacroBlockExTypeBkwdPredictedFrame,
+ vlMacroBlockExTypeBkwdPredictedField,
+ vlMacroBlockExTypeBiPredictedFrame,
+ vlMacroBlockExTypeBiPredictedField,
+
+ vlNumMacroBlockExTypes
+};
+
+struct vlVertexShaderConsts
+{
+ struct vlVertex4f denorm;
+};
+
+struct vlFragmentShaderConsts
+{
+ struct vlVertex4f multiplier;
+ struct vlVertex4f div;
+};
+
+struct vlMacroBlockVertexStream0
+{
+ struct vlVertex2f pos;
+ struct vlVertex2f luma_tc;
+ struct vlVertex2f cb_tc;
+ struct vlVertex2f cr_tc;
+};
+
+struct vlR16SnormBufferedMC
+{
+ struct vlRender base;
+
+ unsigned int picture_width;
+ unsigned int picture_height;
+ enum vlFormat picture_format;
+ unsigned int macroblocks_per_picture;
+
+ struct vlSurface *buffered_surface;
+ struct vlSurface *past_surface;
+ struct vlSurface *future_surface;
+ struct vlVertex2f surface_tex_inv_size;
+ struct vlVertex2f zero_block[3];
+ unsigned int num_macroblocks;
+ struct vlMpeg2MacroBlock *macroblocks;
+ struct pipe_transfer *tex_transfer[3];
+ short *texels[3];
+
+ struct pipe_context *pipe;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state render_target;
+
+ union
+ {
+ void *all[5];
+ struct
+ {
+ void *y;
+ void *cb;
+ void *cr;
+ void *ref[2];
+ };
+ } samplers;
+
+ union
+ {
+ struct pipe_texture *all[5];
+ struct
+ {
+ struct pipe_texture *y;
+ struct pipe_texture *cb;
+ struct pipe_texture *cr;
+ struct pipe_texture *ref[2];
+ };
+ } textures;
+
+ union
+ {
+ struct pipe_vertex_buffer all[3];
+ struct
+ {
+ struct pipe_vertex_buffer ycbcr;
+ struct pipe_vertex_buffer ref[2];
+ };
+ } vertex_bufs;
+
+ void *i_vs, *p_vs[2], *b_vs[2];
+ void *i_fs, *p_fs[2], *b_fs[2];
+ struct pipe_vertex_element vertex_elems[8];
+ struct pipe_constant_buffer vs_const_buf;
+ struct pipe_constant_buffer fs_const_buf;
+};
+
+static inline int vlBegin
+(
+ struct vlRender *render
+)
+{
+ assert(render);
+
+ return 0;
+}
+
+static inline int vlGrabFrameCodedBlock(short *src, short *dst, unsigned int dst_pitch)
+{
+ unsigned int y;
+
+ for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+ memcpy
+ (
+ dst + y * dst_pitch,
+ src + y * VL_BLOCK_WIDTH,
+ VL_BLOCK_WIDTH * 2
+ );
+
+ return 0;
+}
+
+static inline int vlGrabFieldCodedBlock(short *src, short *dst, unsigned int dst_pitch)
+{
+ unsigned int y;
+
+ for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+ memcpy
+ (
+ dst + y * dst_pitch * 2,
+ src + y * VL_BLOCK_WIDTH,
+ VL_BLOCK_WIDTH * 2
+ );
+
+ return 0;
+}
+
+static inline int vlGrabNoBlock(short *dst, unsigned int dst_pitch)
+{
+ unsigned int y;
+
+ for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+ memset
+ (
+ dst + y * dst_pitch,
+ 0,
+ VL_BLOCK_WIDTH * 2
+ );
+
+ return 0;
+}
+
+static inline int vlGrabBlocks
+(
+ struct vlR16SnormBufferedMC *mc,
+ unsigned int mbx,
+ unsigned int mby,
+ enum vlDCTType dct_type,
+ unsigned int coded_block_pattern,
+ short *blocks
+)
+{
+ short *texels;
+ unsigned int tex_pitch;
+ unsigned int x, y, tb = 0, sb = 0;
+ unsigned int mbpx = mbx * VL_MACROBLOCK_WIDTH, mbpy = mby * VL_MACROBLOCK_HEIGHT;
+
+ assert(mc);
+ assert(blocks);
+
+ tex_pitch = mc->tex_transfer[0]->stride / mc->tex_transfer[0]->block.size;
+ texels = mc->texels[0] + mbpy * tex_pitch + mbpx;
+
+ for (y = 0; y < 2; ++y)
+ {
+ for (x = 0; x < 2; ++x, ++tb)
+ {
+ if ((coded_block_pattern >> (5 - tb)) & 1)
+ {
+ short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
+
+ if (dct_type == vlDCTTypeFrameCoded)
+ {
+ vlGrabFrameCodedBlock
+ (
+ cur_block,
+ texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH,
+ tex_pitch
+ );
+ }
+ else
+ {
+ vlGrabFieldCodedBlock
+ (
+ cur_block,
+ texels + y * tex_pitch + x * VL_BLOCK_WIDTH,
+ tex_pitch
+ );
+ }
+
+ ++sb;
+ }
+ else if (mc->zero_block[0].x < 0.0f)
+ {
+ vlGrabNoBlock(texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH, tex_pitch);
+
+ mc->zero_block[0].x = (mbpx + x * 8) * mc->surface_tex_inv_size.x;
+ mc->zero_block[0].y = (mbpy + y * 8) * mc->surface_tex_inv_size.y;
+ }
+ }
+ }
+
+ /* TODO: Implement 422, 444 */
+ mbpx >>= 1;
+ mbpy >>= 1;
+
+ for (tb = 0; tb < 2; ++tb)
+ {
+ tex_pitch = mc->tex_transfer[tb + 1]->stride / mc->tex_transfer[tb + 1]->block.size;
+ texels = mc->texels[tb + 1] + mbpy * tex_pitch + mbpx;
+
+ if ((coded_block_pattern >> (1 - tb)) & 1)
+ {
+ short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
+
+ vlGrabFrameCodedBlock
+ (
+ cur_block,
+ texels,
+ tex_pitch
+ );
+
+ ++sb;
+ }
+ else if (mc->zero_block[tb + 1].x < 0.0f)
+ {
+ vlGrabNoBlock(texels, tex_pitch);
+
+ mc->zero_block[tb + 1].x = (mbpx << 1) * mc->surface_tex_inv_size.x;
+ mc->zero_block[tb + 1].y = (mbpy << 1) * mc->surface_tex_inv_size.y;
+ }
+ }
+
+ return 0;
+}
+
+static inline enum vlMacroBlockTypeEx vlGetMacroBlockTypeEx(struct vlMpeg2MacroBlock *mb)
+{
+ assert(mb);
+
+ switch (mb->mb_type)
+ {
+ case vlMacroBlockTypeIntra:
+ return vlMacroBlockExTypeIntra;
+ case vlMacroBlockTypeFwdPredicted:
+ return mb->mo_type == vlMotionTypeFrame ?
+ vlMacroBlockExTypeFwdPredictedFrame : vlMacroBlockExTypeFwdPredictedField;
+ case vlMacroBlockTypeBkwdPredicted:
+ return mb->mo_type == vlMotionTypeFrame ?
+ vlMacroBlockExTypeBkwdPredictedFrame : vlMacroBlockExTypeBkwdPredictedField;
+ case vlMacroBlockTypeBiPredicted:
+ return mb->mo_type == vlMotionTypeFrame ?
+ vlMacroBlockExTypeBiPredictedFrame : vlMacroBlockExTypeBiPredictedField;
+ default:
+ assert(0);
+ }
+
+ /* Unreachable */
+ return -1;
+}
+
+static inline int vlGrabMacroBlock
+(
+ struct vlR16SnormBufferedMC *mc,
+ struct vlMpeg2MacroBlock *macroblock
+)
+{
+ assert(mc);
+ assert(macroblock);
+ assert(mc->num_macroblocks < mc->macroblocks_per_picture);
+
+ mc->macroblocks[mc->num_macroblocks].mbx = macroblock->mbx;
+ mc->macroblocks[mc->num_macroblocks].mby = macroblock->mby;
+ mc->macroblocks[mc->num_macroblocks].mb_type = macroblock->mb_type;
+ mc->macroblocks[mc->num_macroblocks].mo_type = macroblock->mo_type;
+ mc->macroblocks[mc->num_macroblocks].dct_type = macroblock->dct_type;
+ mc->macroblocks[mc->num_macroblocks].PMV[0][0][0] = macroblock->PMV[0][0][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[0][0][1] = macroblock->PMV[0][0][1];
+ mc->macroblocks[mc->num_macroblocks].PMV[0][1][0] = macroblock->PMV[0][1][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[0][1][1] = macroblock->PMV[0][1][1];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][0][0] = macroblock->PMV[1][0][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][0][1] = macroblock->PMV[1][0][1];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][1][0] = macroblock->PMV[1][1][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][1][1] = macroblock->PMV[1][1][1];
+ mc->macroblocks[mc->num_macroblocks].cbp = macroblock->cbp;
+ mc->macroblocks[mc->num_macroblocks].blocks = macroblock->blocks;
+
+ vlGrabBlocks
+ (
+ mc,
+ macroblock->mbx,
+ macroblock->mby,
+ macroblock->dct_type,
+ macroblock->cbp,
+ macroblock->blocks
+ );
+
+ mc->num_macroblocks++;
+
+ return 0;
+}
+
+#define SET_BLOCK(vb, cbp, mbx, mby, unitx, unity, ofsx, ofsy, hx, hy, lm, cbm, crm, zb) \
+ do { \
+ (vb)[0].pos.x = (mbx) * (unitx) + (ofsx); (vb)[0].pos.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].pos.x = (mbx) * (unitx) + (ofsx); (vb)[1].pos.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].pos.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].pos.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].pos.x = (mbx) * (unitx) + (ofsx); (vb)[4].pos.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].pos.y = (mby) * (unity) + (ofsy) + (hy); \
+ \
+ if ((cbp) & (lm)) \
+ { \
+ (vb)[0].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].luma_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].luma_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].luma_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ } \
+ else \
+ { \
+ (vb)[0].luma_tc.x = (zb)[0].x; (vb)[0].luma_tc.y = (zb)[0].y; \
+ (vb)[1].luma_tc.x = (zb)[0].x; (vb)[1].luma_tc.y = (zb)[0].y + (hy); \
+ (vb)[2].luma_tc.x = (zb)[0].x + (hx); (vb)[2].luma_tc.y = (zb)[0].y; \
+ (vb)[3].luma_tc.x = (zb)[0].x + (hx); (vb)[3].luma_tc.y = (zb)[0].y; \
+ (vb)[4].luma_tc.x = (zb)[0].x; (vb)[4].luma_tc.y = (zb)[0].y + (hy); \
+ (vb)[5].luma_tc.x = (zb)[0].x + (hx); (vb)[5].luma_tc.y = (zb)[0].y + (hy); \
+ } \
+ \
+ if ((cbp) & (cbm)) \
+ { \
+ (vb)[0].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cb_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cb_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cb_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ } \
+ else \
+ { \
+ (vb)[0].cb_tc.x = (zb)[1].x; (vb)[0].cb_tc.y = (zb)[1].y; \
+ (vb)[1].cb_tc.x = (zb)[1].x; (vb)[1].cb_tc.y = (zb)[1].y + (hy); \
+ (vb)[2].cb_tc.x = (zb)[1].x + (hx); (vb)[2].cb_tc.y = (zb)[1].y; \
+ (vb)[3].cb_tc.x = (zb)[1].x + (hx); (vb)[3].cb_tc.y = (zb)[1].y; \
+ (vb)[4].cb_tc.x = (zb)[1].x; (vb)[4].cb_tc.y = (zb)[1].y + (hy); \
+ (vb)[5].cb_tc.x = (zb)[1].x + (hx); (vb)[5].cb_tc.y = (zb)[1].y + (hy); \
+ } \
+ \
+ if ((cbp) & (crm)) \
+ { \
+ (vb)[0].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cr_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cr_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cr_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ } \
+ else \
+ { \
+ (vb)[0].cr_tc.x = (zb)[2].x; (vb)[0].cr_tc.y = (zb)[2].y; \
+ (vb)[1].cr_tc.x = (zb)[2].x; (vb)[1].cr_tc.y = (zb)[2].y + (hy); \
+ (vb)[2].cr_tc.x = (zb)[2].x + (hx); (vb)[2].cr_tc.y = (zb)[2].y; \
+ (vb)[3].cr_tc.x = (zb)[2].x + (hx); (vb)[3].cr_tc.y = (zb)[2].y; \
+ (vb)[4].cr_tc.x = (zb)[2].x; (vb)[4].cr_tc.y = (zb)[2].y + (hy); \
+ (vb)[5].cr_tc.x = (zb)[2].x + (hx); (vb)[5].cr_tc.y = (zb)[2].y + (hy); \
+ } \
+ } while (0)
+
+static inline int vlGenMacroblockVerts
+(
+ struct vlR16SnormBufferedMC *mc,
+ struct vlMpeg2MacroBlock *macroblock,
+ unsigned int pos,
+ struct vlMacroBlockVertexStream0 *ycbcr_vb,
+ struct vlVertex2f **ref_vb
+)
+{
+ struct vlVertex2f mo_vec[2];
+ unsigned int i;
+
+ assert(mc);
+ assert(macroblock);
+ assert(ycbcr_vb);
+ assert(pos < mc->macroblocks_per_picture);
+
+ switch (macroblock->mb_type)
+ {
+ case vlMacroBlockTypeBiPredicted:
+ {
+ struct vlVertex2f *vb;
+
+ assert(ref_vb && ref_vb[1]);
+
+ vb = ref_vb[1] + pos * 2 * 24;
+
+ mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ if (macroblock->mo_type == vlMotionTypeFrame)
+ {
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ }
+ }
+ else
+ {
+ mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ vb[i + 1].x = mo_vec[1].x;
+ vb[i + 1].y = mo_vec[1].y;
+ }
+ }
+
+ /* fall-through */
+ }
+ case vlMacroBlockTypeFwdPredicted:
+ case vlMacroBlockTypeBkwdPredicted:
+ {
+ struct vlVertex2f *vb;
+
+ assert(ref_vb && ref_vb[0]);
+
+ vb = ref_vb[0] + pos * 2 * 24;
+
+ if (macroblock->mb_type == vlMacroBlockTypeBkwdPredicted)
+ {
+ mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ if (macroblock->mo_type == vlMotionTypeField)
+ {
+ mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+ }
+ }
+ else
+ {
+ mo_vec[0].x = macroblock->PMV[0][0][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[0].y = macroblock->PMV[0][0][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ if (macroblock->mo_type == vlMotionTypeField)
+ {
+ mo_vec[1].x = macroblock->PMV[1][0][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[1].y = macroblock->PMV[1][0][1] * 0.5f * mc->surface_tex_inv_size.y;
+ }
+ }
+
+ if (macroblock->mo_type == vlMotionTypeFrame)
+ {
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ }
+ }
+ else
+ {
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ vb[i + 1].x = mo_vec[1].x;
+ vb[i + 1].y = mo_vec[1].y;
+ }
+ }
+
+ /* fall-through */
+ }
+ case vlMacroBlockTypeIntra:
+ {
+ const struct vlVertex2f unit =
+ {
+ mc->surface_tex_inv_size.x * VL_MACROBLOCK_WIDTH,
+ mc->surface_tex_inv_size.y * VL_MACROBLOCK_HEIGHT
+ };
+ const struct vlVertex2f half =
+ {
+ mc->surface_tex_inv_size.x * (VL_MACROBLOCK_WIDTH / 2),
+ mc->surface_tex_inv_size.y * (VL_MACROBLOCK_HEIGHT / 2)
+ };
+
+ struct vlMacroBlockVertexStream0 *vb;
+
+ vb = ycbcr_vb + pos * 24;
+
+ SET_BLOCK
+ (
+ vb,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, 0, 0, half.x, half.y,
+ 32, 2, 1, mc->zero_block
+ );
+
+ SET_BLOCK
+ (
+ vb + 6,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, half.x, 0, half.x, half.y,
+ 16, 2, 1, mc->zero_block
+ );
+
+ SET_BLOCK
+ (
+ vb + 12,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, 0, half.y, half.x, half.y,
+ 8, 2, 1, mc->zero_block
+ );
+
+ SET_BLOCK
+ (
+ vb + 18,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, half.x, half.y, half.x, half.y,
+ 4, 2, 1, mc->zero_block
+ );
+
+ break;
+ }
+ default:
+ assert(0);
+ }
+
+ return 0;
+}
+
+static int vlFlush
+(
+ struct vlRender *render
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ struct pipe_context *pipe;
+ struct vlVertexShaderConsts *vs_consts;
+ unsigned int num_macroblocks[vlNumMacroBlockExTypes] = {0};
+ unsigned int offset[vlNumMacroBlockExTypes];
+ unsigned int vb_start = 0;
+ unsigned int i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormBufferedMC*)render;
+
+ if (!mc->buffered_surface)
+ return 0;
+
+ if (mc->num_macroblocks < mc->macroblocks_per_picture)
+ return 0;
+
+ assert(mc->num_macroblocks <= mc->macroblocks_per_picture);
+
+ pipe = mc->pipe;
+
+ for (i = 0; i < mc->num_macroblocks; ++i)
+ {
+ enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
+
+ num_macroblocks[mb_type_ex]++;
+ }
+
+ offset[0] = 0;
+
+ for (i = 1; i < vlNumMacroBlockExTypes; ++i)
+ offset[i] = offset[i - 1] + num_macroblocks[i - 1];
+
+ {
+ struct vlMacroBlockVertexStream0 *ycbcr_vb;
+ struct vlVertex2f *ref_vb[2];
+
+ ycbcr_vb = (struct vlMacroBlockVertexStream0*)pipe_buffer_map
+ (
+ pipe->screen,
+ mc->vertex_bufs.ycbcr.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
+ );
+
+ for (i = 0; i < 2; ++i)
+ ref_vb[i] = (struct vlVertex2f*)pipe_buffer_map
+ (
+ pipe->screen,
+ mc->vertex_bufs.ref[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
+ );
+
+ for (i = 0; i < mc->num_macroblocks; ++i)
+ {
+ enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
+
+ vlGenMacroblockVerts(mc, &mc->macroblocks[i], offset[mb_type_ex], ycbcr_vb, ref_vb);
+
+ offset[mb_type_ex]++;
+ }
+
+ pipe_buffer_unmap(pipe->screen, mc->vertex_bufs.ycbcr.buffer);
+ for (i = 0; i < 2; ++i)
+ pipe_buffer_unmap(pipe->screen, mc->vertex_bufs.ref[i].buffer);
+ }
+
+ for (i = 0; i < 3; ++i)
+ {
+ pipe->screen->transfer_unmap(pipe->screen, mc->tex_transfer[i]);
+ pipe->screen->tex_transfer_destroy(mc->tex_transfer[i]);
+ }
+
+ mc->render_target.cbufs[0] = pipe->screen->get_tex_surface
+ (
+ pipe->screen,
+ mc->buffered_surface->texture,
+ 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
+ );
+
+ pipe->set_framebuffer_state(pipe, &mc->render_target);
+ pipe->set_viewport_state(pipe, &mc->viewport);
+ vs_consts = pipe_buffer_map
+ (
+ pipe->screen,
+ mc->vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
+ );
+
+ vs_consts->denorm.x = mc->buffered_surface->texture->width[0];
+ vs_consts->denorm.y = mc->buffered_surface->texture->height[0];
+
+ pipe_buffer_unmap(pipe->screen, mc->vs_const_buf.buffer);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &mc->vs_const_buf);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &mc->fs_const_buf);
+
+ if (num_macroblocks[vlMacroBlockExTypeIntra] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 1, mc->vertex_bufs.all);
+ pipe->set_vertex_elements(pipe, 4, mc->vertex_elems);
+ pipe->set_sampler_textures(pipe, 3, mc->textures.all);
+ pipe->bind_sampler_states(pipe, 3, mc->samplers.all);
+ pipe->bind_vs_state(pipe, mc->i_vs);
+ pipe->bind_fs_state(pipe, mc->i_fs);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeIntra] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeIntra] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures.ref[0] = mc->past_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures.all);
+ pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
+ pipe->bind_vs_state(pipe, mc->p_vs[0]);
+ pipe->bind_fs_state(pipe, mc->p_fs[0]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeFwdPredictedField] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures.ref[0] = mc->past_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures.all);
+ pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
+ pipe->bind_vs_state(pipe, mc->p_vs[1]);
+ pipe->bind_fs_state(pipe, mc->p_fs[1]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures.ref[0] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures.all);
+ pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
+ pipe->bind_vs_state(pipe, mc->p_vs[0]);
+ pipe->bind_fs_state(pipe, mc->p_fs[0]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures.ref[0] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures.all);
+ pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
+ pipe->bind_vs_state(pipe, mc->p_vs[1]);
+ pipe->bind_fs_state(pipe, mc->p_fs[1]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs.all);
+ pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
+ mc->textures.ref[0] = mc->past_surface->texture;
+ mc->textures.ref[1] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 5, mc->textures.all);
+ pipe->bind_sampler_states(pipe, 5, mc->samplers.all);
+ pipe->bind_vs_state(pipe, mc->b_vs[0]);
+ pipe->bind_fs_state(pipe, mc->b_fs[0]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBiPredictedField] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs.all);
+ pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
+ mc->textures.ref[0] = mc->past_surface->texture;
+ mc->textures.ref[1] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 5, mc->textures.all);
+ pipe->bind_sampler_states(pipe, 5, mc->samplers.all);
+ pipe->bind_vs_state(pipe, mc->b_vs[1]);
+ pipe->bind_fs_state(pipe, mc->b_fs[1]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24;
+ }
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &mc->buffered_surface->render_fence);
+ pipe_surface_reference(&mc->render_target.cbufs[0], NULL);
+
+ for (i = 0; i < 3; ++i)
+ mc->zero_block[i].x = -1.0f;
+
+ mc->buffered_surface = NULL;
+ mc->num_macroblocks = 0;
+
+ return 0;
+}
+
+static int vlRenderMacroBlocksMpeg2R16SnormBuffered
+(
+ struct vlRender *render,
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ bool new_surface = false;
+ unsigned int i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormBufferedMC*)render;
+
+ if (mc->buffered_surface)
+ {
+ if (mc->buffered_surface != surface)
+ {
+ vlFlush(&mc->base);
+ new_surface = true;
+ }
+ }
+ else
+ new_surface = true;
+
+ if (new_surface)
+ {
+ mc->buffered_surface = surface;
+ mc->past_surface = batch->past_surface;
+ mc->future_surface = batch->future_surface;
+ mc->surface_tex_inv_size.x = 1.0f / surface->texture->width[0];
+ mc->surface_tex_inv_size.y = 1.0f / surface->texture->height[0];
+
+ for (i = 0; i < 3; ++i)
+ {
+ mc->tex_transfer[i] = mc->pipe->screen->get_tex_transfer
+ (
+ mc->pipe->screen,
+ mc->textures.all[i],
+ 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0,
+ surface->texture->width[0],
+ surface->texture->height[0]
+ );
+
+ mc->texels[i] = mc->pipe->screen->transfer_map(mc->pipe->screen, mc->tex_transfer[i]);
+ }
+ }
+
+ for (i = 0; i < batch->num_macroblocks; ++i)
+ vlGrabMacroBlock(mc, &batch->macroblocks[i]);
+
+ return 0;
+}
+
+static inline int vlEnd
+(
+ struct vlRender *render
+)
+{
+ assert(render);
+
+ return 0;
+}
+
+static int vlDestroy
+(
+ struct vlRender *render
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ struct pipe_context *pipe;
+ unsigned int i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormBufferedMC*)render;
+ pipe = mc->pipe;
+
+ for (i = 0; i < 5; ++i)
+ pipe->delete_sampler_state(pipe, mc->samplers.all[i]);
+
+ for (i = 0; i < 3; ++i)
+ pipe_buffer_reference(&mc->vertex_bufs.all[i].buffer, NULL);
+
+ /* Textures 3 & 4 are not created directly, no need to release them here */
+ for (i = 0; i < 3; ++i)
+ pipe_texture_reference(&mc->textures.all[i], NULL);
+
+ pipe->delete_vs_state(pipe, mc->i_vs);
+ pipe->delete_fs_state(pipe, mc->i_fs);
+
+ for (i = 0; i < 2; ++i)
+ {
+ pipe->delete_vs_state(pipe, mc->p_vs[i]);
+ pipe->delete_fs_state(pipe, mc->p_fs[i]);
+ pipe->delete_vs_state(pipe, mc->b_vs[i]);
+ pipe->delete_fs_state(pipe, mc->b_fs[i]);
+ }
+
+ pipe_buffer_reference(&mc->vs_const_buf.buffer, NULL);
+ pipe_buffer_reference(&mc->fs_const_buf.buffer, NULL);
+
+ FREE(mc->macroblocks);
+ FREE(mc);
+
+ return 0;
+}
+
+/*
+ * Muliplier renormalizes block samples from 16 bits to 12 bits.
+ * Divider is used when calculating Y % 2 for choosing top or bottom
+ * field for P or B macroblocks.
+ * TODO: Use immediates.
+ */
+static const struct vlFragmentShaderConsts fs_consts =
+{
+ {32767.0f / 255.0f, 32767.0f / 255.0f, 32767.0f / 255.0f, 0.0f},
+ {0.5f, 2.0f, 0.0f, 0.0f}
+};
+
+#include "vl_r16snorm_mc_buf_shaders.inc"
+
+static int vlCreateDataBufs
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int mbw = align(mc->picture_width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH;
+ const unsigned int mbh = align(mc->picture_height, VL_MACROBLOCK_HEIGHT) / VL_MACROBLOCK_HEIGHT;
+
+ struct pipe_context *pipe;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ mc->macroblocks_per_picture = mbw * mbh;
+
+ /* Create our vertex buffers */
+ mc->vertex_bufs.ycbcr.stride = sizeof(struct vlVertex2f) * 4;
+ mc->vertex_bufs.ycbcr.max_index = 24 * mc->macroblocks_per_picture - 1;
+ mc->vertex_bufs.ycbcr.buffer_offset = 0;
+ mc->vertex_bufs.ycbcr.buffer = pipe_buffer_create
+ (
+ pipe->screen,
+ DEFAULT_BUF_ALIGNMENT,
+ PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_DISCARD,
+ sizeof(struct vlVertex2f) * 4 * 24 * mc->macroblocks_per_picture
+ );
+
+ for (i = 1; i < 3; ++i)
+ {
+ mc->vertex_bufs.all[i].stride = sizeof(struct vlVertex2f) * 2;
+ mc->vertex_bufs.all[i].max_index = 24 * mc->macroblocks_per_picture - 1;
+ mc->vertex_bufs.all[i].buffer_offset = 0;
+ mc->vertex_bufs.all[i].buffer = pipe_buffer_create
+ (
+ pipe->screen,
+ DEFAULT_BUF_ALIGNMENT,
+ PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_DISCARD,
+ sizeof(struct vlVertex2f) * 2 * 24 * mc->macroblocks_per_picture
+ );
+ }
+
+ /* Position element */
+ mc->vertex_elems[0].src_offset = 0;
+ mc->vertex_elems[0].vertex_buffer_index = 0;
+ mc->vertex_elems[0].nr_components = 2;
+ mc->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Luma, texcoord element */
+ mc->vertex_elems[1].src_offset = sizeof(struct vlVertex2f);
+ mc->vertex_elems[1].vertex_buffer_index = 0;
+ mc->vertex_elems[1].nr_components = 2;
+ mc->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Chroma Cr texcoord element */
+ mc->vertex_elems[2].src_offset = sizeof(struct vlVertex2f) * 2;
+ mc->vertex_elems[2].vertex_buffer_index = 0;
+ mc->vertex_elems[2].nr_components = 2;
+ mc->vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Chroma Cb texcoord element */
+ mc->vertex_elems[3].src_offset = sizeof(struct vlVertex2f) * 3;
+ mc->vertex_elems[3].vertex_buffer_index = 0;
+ mc->vertex_elems[3].nr_components = 2;
+ mc->vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* First ref surface top field texcoord element */
+ mc->vertex_elems[4].src_offset = 0;
+ mc->vertex_elems[4].vertex_buffer_index = 1;
+ mc->vertex_elems[4].nr_components = 2;
+ mc->vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* First ref surface bottom field texcoord element */
+ mc->vertex_elems[5].src_offset = sizeof(struct vlVertex2f);
+ mc->vertex_elems[5].vertex_buffer_index = 1;
+ mc->vertex_elems[5].nr_components = 2;
+ mc->vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Second ref surface top field texcoord element */
+ mc->vertex_elems[6].src_offset = 0;
+ mc->vertex_elems[6].vertex_buffer_index = 2;
+ mc->vertex_elems[6].nr_components = 2;
+ mc->vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Second ref surface bottom field texcoord element */
+ mc->vertex_elems[7].src_offset = sizeof(struct vlVertex2f);
+ mc->vertex_elems[7].vertex_buffer_index = 2;
+ mc->vertex_elems[7].nr_components = 2;
+ mc->vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Create our constant buffer */
+ mc->vs_const_buf.buffer = pipe_buffer_create
+ (
+ pipe->screen,
+ DEFAULT_BUF_ALIGNMENT,
+ PIPE_BUFFER_USAGE_CONSTANT | PIPE_BUFFER_USAGE_DISCARD,
+ sizeof(struct vlVertexShaderConsts)
+ );
+
+ mc->fs_const_buf.buffer = pipe_buffer_create
+ (
+ pipe->screen,
+ DEFAULT_BUF_ALIGNMENT,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ sizeof(struct vlFragmentShaderConsts)
+ );
+
+ memcpy
+ (
+ pipe_buffer_map(pipe->screen, mc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ &fs_consts,
+ sizeof(struct vlFragmentShaderConsts)
+ );
+
+ pipe_buffer_unmap(pipe->screen, mc->fs_const_buf.buffer);
+
+ mc->macroblocks = MALLOC(sizeof(struct vlMpeg2MacroBlock) * mc->macroblocks_per_picture);
+
+ return 0;
+}
+
+static int vlInit
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ struct pipe_context *pipe;
+ struct pipe_sampler_state sampler;
+ struct pipe_texture template;
+ unsigned int filters[5];
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+
+ mc->buffered_surface = NULL;
+ mc->past_surface = NULL;
+ mc->future_surface = NULL;
+ for (i = 0; i < 3; ++i)
+ mc->zero_block[i].x = -1.0f;
+ mc->num_macroblocks = 0;
+
+ /* For MC we render to textures, which are rounded up to nearest POT */
+ mc->viewport.scale[0] = vlRoundUpPOT(mc->picture_width);
+ mc->viewport.scale[1] = vlRoundUpPOT(mc->picture_height);
+ mc->viewport.scale[2] = 1;
+ mc->viewport.scale[3] = 1;
+ mc->viewport.translate[0] = 0;
+ mc->viewport.translate[1] = 0;
+ mc->viewport.translate[2] = 0;
+ mc->viewport.translate[3] = 0;
+
+ mc->render_target.width = vlRoundUpPOT(mc->picture_width);
+ mc->render_target.height = vlRoundUpPOT(mc->picture_height);
+ mc->render_target.nr_cbufs = 1;
+ /* FB for MC stage is a vlSurface created by the user, set at render time */
+ mc->render_target.zsbuf = NULL;
+
+ filters[0] = PIPE_TEX_FILTER_NEAREST;
+ /* FIXME: Linear causes discoloration around block edges */
+ filters[1] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST /*: PIPE_TEX_FILTER_LINEAR*/;
+ filters[2] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST /*: PIPE_TEX_FILTER_LINEAR*/;
+ filters[3] = PIPE_TEX_FILTER_LINEAR;
+ filters[4] = PIPE_TEX_FILTER_LINEAR;
+
+ for (i = 0; i < 5; ++i)
+ {
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_img_filter = filters[i];
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.mag_img_filter = filters[i];
+ sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
+ sampler.compare_func = PIPE_FUNC_ALWAYS;
+ sampler.normalized_coords = 1;
+ /*sampler.prefilter = ;*/
+ /*sampler.lod_bias = ;*/
+ sampler.min_lod = 0;
+ /*sampler.max_lod = ;*/
+ /*sampler.border_color[i] = ;*/
+ /*sampler.max_anisotropy = ;*/
+ mc->samplers.all[i] = pipe->create_sampler_state(pipe, &sampler);
+ }
+
+ memset(&template, 0, sizeof(struct pipe_texture));
+ template.target = PIPE_TEXTURE_2D;
+ template.format = PIPE_FORMAT_R16_SNORM;
+ template.last_level = 0;
+ template.width[0] = vlRoundUpPOT(mc->picture_width);
+ template.height[0] = vlRoundUpPOT(mc->picture_height);
+ template.depth[0] = 1;
+ pf_get_block(template.format, &template.block);
+ template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_DYNAMIC;
+
+ mc->textures.y = pipe->screen->texture_create(pipe->screen, &template);
+
+ if (mc->picture_format == vlFormatYCbCr420)
+ {
+ template.width[0] = vlRoundUpPOT(mc->picture_width / 2);
+ template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
+ }
+ else if (mc->picture_format == vlFormatYCbCr422)
+ template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
+
+ mc->textures.cb = pipe->screen->texture_create(pipe->screen, &template);
+ mc->textures.cr = pipe->screen->texture_create(pipe->screen, &template);
+
+ /* textures.all[3] & textures.all[4] are assigned from vlSurfaces for P and B macroblocks at render time */
+
+ vlCreateVertexShaderIMB(mc);
+ vlCreateFragmentShaderIMB(mc);
+ vlCreateVertexShaderFramePMB(mc);
+ vlCreateVertexShaderFieldPMB(mc);
+ vlCreateFragmentShaderFramePMB(mc);
+ vlCreateFragmentShaderFieldPMB(mc);
+ vlCreateVertexShaderFrameBMB(mc);
+ vlCreateVertexShaderFieldBMB(mc);
+ vlCreateFragmentShaderFrameBMB(mc);
+ vlCreateFragmentShaderFieldBMB(mc);
+ vlCreateDataBufs(mc);
+
+ return 0;
+}
+
+int vlCreateR16SNormBufferedMC
+(
+ struct pipe_context *pipe,
+ unsigned int picture_width,
+ unsigned int picture_height,
+ enum vlFormat picture_format,
+ struct vlRender **render
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+
+ assert(pipe);
+ assert(render);
+
+ mc = CALLOC_STRUCT(vlR16SnormBufferedMC);
+
+ mc->base.vlBegin = &vlBegin;
+ mc->base.vlRenderMacroBlocksMpeg2 = &vlRenderMacroBlocksMpeg2R16SnormBuffered;
+ mc->base.vlEnd = &vlEnd;
+ mc->base.vlFlush = &vlFlush;
+ mc->base.vlDestroy = &vlDestroy;
+ mc->pipe = pipe;
+ mc->picture_width = picture_width;
+ mc->picture_height = picture_height;
+
+ vlInit(mc);
+
+ *render = &mc->base;
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h
new file mode 100644
index 0000000000..27177d64ca
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h
@@ -0,0 +1,18 @@
+#ifndef vl_r16snorm_mc_buf_h
+#define vl_r16snorm_mc_buf_h
+
+#include "vl_types.h"
+
+struct pipe_context;
+struct vlRender;
+
+int vlCreateR16SNormBufferedMC
+(
+ struct pipe_context *pipe,
+ unsigned int picture_width,
+ unsigned int picture_height,
+ enum vlFormat picture_format,
+ struct vlRender **render
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc
new file mode 100644
index 0000000000..ef4a4b2add
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc
@@ -0,0 +1,1185 @@
+static int vlCreateVertexShaderIMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 50;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state vs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Vertex pos
+ * decl i1 ; Luma texcoords
+ * decl i2 ; Chroma Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ */
+ for (i = 0; i < 4; i++)
+ {
+ decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * decl o0 ; Vertex pos
+ * decl o1 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr texcoords
+ */
+ for (i = 0; i < 4; i++)
+ {
+ decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * mov o0, i0 ; Move input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ vs.tokens = tokens;
+ mc->i_vs = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderIMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 100;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state fs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl o0 ; Fragment color */
+ decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl s0 ; Sampler for luma texture
+ * decl s1 ; Sampler for chroma Cb texture
+ * decl s2 ; Sampler for chroma Cr texture
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ decl = vl_decl_samplers(i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header,max_tokens - ti);
+ }
+
+ /*
+ * tex2d t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul o0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ fs.tokens = tokens;
+ mc->i_fs = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFramePMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 100;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state vs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Vertex pos
+ * decl i1 ; Luma texcoords
+ * decl i2 ; Chroma Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ * decl i4 ; Ref surface top field texcoords
+ * decl i5 ; Ref surface bottom field texcoords (unused, packed in the same stream)
+ */
+ for (i = 0; i < 6; i++)
+ {
+ decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * decl o0 ; Vertex pos
+ * decl o1 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr texcoords
+ * decl o4 ; Ref macroblock texcoords
+ */
+ for (i = 0; i < 5; i++)
+ {
+ decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * mov o0, i0 ; Move input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* add o4, i0, i4 ; Translate vertex pos by motion vec to form ref macroblock texcoords */
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, 4);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ vs.tokens = tokens;
+ mc->p_vs[0] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFieldPMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 100;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state vs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Vertex pos
+ * decl i1 ; Luma texcoords
+ * decl i2 ; Chroma Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ * decl i4 ; Ref macroblock top field texcoords
+ * decl i5 ; Ref macroblock bottom field texcoords
+ */
+ for (i = 0; i < 6; i++)
+ {
+ decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* decl c0 ; Render target dimensions */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl o0 ; Vertex pos
+ * decl o1 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr texcoords
+ * decl o4 ; Ref macroblock top field texcoords
+ * decl o5 ; Ref macroblock bottom field texcoords
+ * decl o6 ; Denormalized vertex pos
+ */
+ for (i = 0; i < 7; i++)
+ {
+ decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * mov o0, i0 ; Move input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * add o4, i0, i4 ; Translate vertex pos by motion vec to form top field macroblock texcoords
+ * add o5, i0, i5 ; Translate vertex pos by motion vec to form bottom field macroblock texcoords
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, i + 4);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul o6, i0, c0 ; Denorm vertex pos */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 6, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ vs.tokens = tokens;
+ mc->p_vs[1] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFramePMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 100;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state fs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ * decl i3 ; Ref macroblock texcoords
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl o0 ; Fragment color */
+ decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl s0 ; Sampler for luma texture
+ * decl s1 ; Sampler for chroma Cb texture
+ * decl s2 ; Sampler for chroma Cr texture
+ * decl s3 ; Sampler for ref surface texture
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ decl = vl_decl_samplers(i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * tex2d t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* tex2d t1, i3, s3 ; Read texel from ref macroblock */
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, 3, TGSI_FILE_SAMPLER, 3);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* add o0, t0, t1 ; Add ref and differential to form final output */
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ fs.tokens = tokens;
+ mc->p_fs[0] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFieldPMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 200;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state fs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ * decl i3 ; Ref macroblock top field texcoords
+ * decl i4 ; Ref macroblock bottom field texcoords
+ * decl i5 ; Denormalized vertex pos
+ */
+ for (i = 0; i < 6; ++i)
+ {
+ decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
+ * decl c1 ; Constants 1/2 & 2 in .x, .y channels for Y-mod-2 top/bottom field selection
+ */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl o0 ; Fragment color */
+ decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl t0-t4 */
+ decl = vl_decl_temps(0, 4);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl s0 ; Sampler for luma texture
+ * decl s1 ; Sampler for chroma Cb texture
+ * decl s2 ; Sampler for chroma Cr texture
+ * decl s3 ; Sampler for ref surface texture
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ decl = vl_decl_samplers(i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * tex2d t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * tex2d t1, i3, s3 ; Read texel from ref macroblock top field
+ * tex2d t2, i4, s3 ; Read texel from ref macroblock bottom field
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 3, TGSI_FILE_SAMPLER, 3);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* XXX: Pos values off by 0.5? */
+ /* sub t4, i5.y, c1.x ; Sub 0.5 from denormalized pos */
+ inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 5, TGSI_FILE_CONSTANT, 1);
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* mul t3, t4, c1.x ; Multiply pos Y-coord by 1/2 */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_CONSTANT, 1);
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* floor t3, t3 ; Get rid of fractional part */
+ inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* mul t3, t3, c1.y ; Multiply by 2 */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1);
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* sub t3, t4, t3 ; Subtract from original Y to get Y % 2 */
+ inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 3);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* TODO: Move to conditional tex fetch on t3 instead of lerp */
+ /* lerp t1, t3, t1, t2 ; Choose between top and bottom fields based on Y % 2 */
+ inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* add o0, t0, t1 ; Add ref and differential to form final output */
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ fs.tokens = tokens;
+ mc->p_fs[1] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFrameBMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 100;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state vs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Vertex pos
+ * decl i1 ; Luma texcoords
+ * decl i2 ; Chroma Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ * decl i4 ; First ref macroblock top field texcoords
+ * decl i5 ; First ref macroblock bottom field texcoords (unused, packed in the same stream)
+ * decl i6 ; Second ref macroblock top field texcoords
+ * decl i7 ; Second ref macroblock bottom field texcoords (unused, packed in the same stream)
+ */
+ for (i = 0; i < 8; i++)
+ {
+ decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * decl o0 ; Vertex pos
+ * decl o1 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr texcoords
+ * decl o4 ; First ref macroblock texcoords
+ * decl o5 ; Second ref macroblock texcoords
+ */
+ for (i = 0; i < 6; i++)
+ {
+ decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * mov o0, i0 ; Move input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * add o4, i0, i4 ; Translate vertex pos by motion vec to form first ref macroblock texcoords
+ * add o5, i0, i6 ; Translate vertex pos by motion vec to form second ref macroblock texcoords
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, (i + 2) * 2);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ vs.tokens = tokens;
+ mc->b_vs[0] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFieldBMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 100;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state vs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Vertex pos
+ * decl i1 ; Luma texcoords
+ * decl i2 ; Chroma Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ * decl i4 ; First ref macroblock top field texcoords
+ * decl i5 ; First ref macroblock bottom field texcoords
+ * decl i6 ; Second ref macroblock top field texcoords
+ * decl i7 ; Second ref macroblock bottom field texcoords
+ */
+ for (i = 0; i < 8; i++)
+ {
+ decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* decl c0 ; Render target dimensions */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl o0 ; Vertex pos
+ * decl o1 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr texcoords
+ * decl o4 ; First ref macroblock top field texcoords
+ * decl o5 ; First ref macroblock Bottom field texcoords
+ * decl o6 ; Second ref macroblock top field texcoords
+ * decl o7 ; Second ref macroblock Bottom field texcoords
+ * decl o8 ; Denormalized vertex pos
+ */
+ for (i = 0; i < 9; i++)
+ {
+ decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* decl t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * mov o0, i0 ; Move input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * add o4, i0, i4 ; Translate vertex pos by motion vec to form first top field macroblock texcoords
+ * add o5, i0, i5 ; Translate vertex pos by motion vec to form first bottom field macroblock texcoords
+ * add o6, i0, i6 ; Translate vertex pos by motion vec to form second top field macroblock texcoords
+ * add o7, i0, i7 ; Translate vertex pos by motion vec to form second bottom field macroblock texcoords
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, i + 4);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul o8, i0, c0 ; Denorm vertex pos */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 8, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ vs.tokens = tokens;
+ mc->b_vs[1] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFrameBMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 100;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state fs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ * decl i3 ; First ref macroblock texcoords
+ * decl i4 ; Second ref macroblock texcoords
+ */
+ for (i = 0; i < 5; ++i)
+ {
+ decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
+ * decl c1 ; Constant 1/2 in .x channel to use as weight to blend past and future texels
+ */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl o0 ; Fragment color */
+ decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl t0-t2 */
+ decl = vl_decl_temps(0, 2);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl s0 ; Sampler for luma texture
+ * decl s1 ; Sampler for chroma Cb texture
+ * decl s2 ; Sampler for chroma Cr texture
+ * decl s3 ; Sampler for first ref surface texture
+ * decl s4 ; Sampler for second ref surface texture
+ */
+ for (i = 0; i < 5; ++i)
+ {
+ decl = vl_decl_samplers(i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * tex2d t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * tex2d t1, i3, s3 ; Read texel from first ref macroblock
+ * tex2d t2, i4, s4 ; Read texel from second ref macroblock
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 3, TGSI_FILE_SAMPLER, i + 3);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* lerp t1, c1.x, t1, t2 ; Blend past and future texels */
+ inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* add o0, t0, t1 ; Add past/future ref and differential to form final output */
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ fs.tokens = tokens;
+ mc->b_fs[0] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFieldBMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int max_tokens = 200;
+
+ struct pipe_context *pipe;
+ struct pipe_shader_state fs;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+
+ unsigned int ti;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+ tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+ /* Version */
+ *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+ /* Header */
+ header = (struct tgsi_header*)&tokens[1];
+ *header = tgsi_build_header();
+ /* Processor */
+ *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+ ti = 3;
+
+ /*
+ * decl i0 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ * decl i3 ; First ref macroblock top field texcoords
+ * decl i4 ; First ref macroblock bottom field texcoords
+ * decl i5 ; Second ref macroblock top field texcoords
+ * decl i6 ; Second ref macroblock bottom field texcoords
+ * decl i7 ; Denormalized vertex pos
+ */
+ for (i = 0; i < 8; ++i)
+ {
+ decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
+ * decl c1 ; Constants 1/2 & 2 in .x, .y channels to use as weight to blend past and future texels
+ * ; and for Y-mod-2 top/bottom field selection
+ */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl o0 ; Fragment color */
+ decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /* decl t0-t5 */
+ decl = vl_decl_temps(0, 5);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl s0 ; Sampler for luma texture
+ * decl s1 ; Sampler for chroma Cb texture
+ * decl s2 ; Sampler for chroma Cr texture
+ * decl s3 ; Sampler for first ref surface texture
+ * decl s4 ; Sampler for second ref surface texture
+ */
+ for (i = 0; i < 5; ++i)
+ {
+ decl = vl_decl_samplers(i, i);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /*
+ * tex2d t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* XXX: Pos values off by 0.5? */
+ /* sub t4, i7.y, c1.x ; Sub 0.5 from denormalized pos */
+ inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 7, TGSI_FILE_CONSTANT, 1);
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* mul t3, t4, c1.x ; Multiply pos Y-coord by 1/2 */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_CONSTANT, 1);
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* floor t3, t3 ; Get rid of fractional part */
+ inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* mul t3, t3, c1.y ; Multiply by 2 */
+ inst = vl_inst3( TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1);
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+ inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* sub t3, t4, t3 ; Subtract from original Y to get Y % 2 */
+ inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 3);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * tex2d t1, i3, s3 ; Read texel from past ref macroblock top field
+ * tex2d t2, i4, s3 ; Read texel from past ref macroblock bottom field
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 3, TGSI_FILE_SAMPLER, 3);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* TODO: Move to conditional tex fetch on t3 instead of lerp */
+ /* lerp t1, t3, t1, t2 ; Choose between top and bottom fields based on Y % 2 */
+ inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * tex2d t4, i5, s4 ; Read texel from future ref macroblock top field
+ * tex2d t5, i6, s4 ; Read texel from future ref macroblock bottom field
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 4, TGSI_FILE_INPUT, i + 5, TGSI_FILE_SAMPLER, 4);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* TODO: Move to conditional tex fetch on t3 instead of lerp */
+ /* lerp t2, t3, t4, t5 ; Choose between top and bottom fields based on Y % 2 */
+ inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 2, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 5);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* lerp t1, c1.x, t1, t2 ; Blend past and future texels */
+ inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+ inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* add o0, t0, t1 ; Add past/future ref and differential to form final output */
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* end */
+ inst = vl_end();
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ fs.tokens = tokens;
+ mc->b_fs[1] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_render.h b/src/gallium/state_trackers/g3dvl/vl_render.h
new file mode 100644
index 0000000000..166030b498
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_render.h
@@ -0,0 +1,38 @@
+#ifndef vl_render_h
+#define vl_render_h
+
+#include "vl_types.h"
+
+struct pipe_surface;
+
+struct vlRender
+{
+ int (*vlBegin)
+ (
+ struct vlRender *render
+ );
+
+ int (*vlRenderMacroBlocksMpeg2)
+ (
+ struct vlRender *render,
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+ );
+
+ int (*vlEnd)
+ (
+ struct vlRender *render
+ );
+
+ int (*vlFlush)
+ (
+ struct vlRender *render
+ );
+
+ int (*vlDestroy)
+ (
+ struct vlRender *render
+ );
+};
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_screen.c b/src/gallium/state_trackers/g3dvl/vl_screen.c
new file mode 100644
index 0000000000..ade8643a66
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_screen.c
@@ -0,0 +1,115 @@
+#define VL_INTERNAL
+#include "vl_screen.h"
+#include <assert.h>
+#include <util/u_memory.h>
+
+int vlCreateScreen
+(
+ struct vlDisplay *display,
+ int screen,
+ struct pipe_screen *pscreen,
+ struct vlScreen **vl_screen
+)
+{
+ struct vlScreen *scrn;
+
+ assert(display);
+ assert(pscreen);
+ assert(vl_screen);
+
+ scrn = CALLOC_STRUCT(vlScreen);
+
+ if (!scrn)
+ return 1;
+
+ scrn->display = display;
+ scrn->ordinal = screen;
+ scrn->pscreen = pscreen;
+ *vl_screen = scrn;
+
+ return 0;
+}
+
+int vlDestroyScreen
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ FREE(screen);
+
+ return 0;
+}
+
+struct vlDisplay* vlGetDisplay
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ return screen->display;
+}
+
+struct pipe_screen* vlGetPipeScreen
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ return screen->pscreen;
+}
+
+unsigned int vlGetMaxProfiles
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ return vlProfileCount;
+}
+
+int vlQueryProfiles
+(
+ struct vlScreen *screen,
+ enum vlProfile *profiles
+)
+{
+ assert(screen);
+ assert(profiles);
+
+ profiles[0] = vlProfileMpeg2Simple;
+ profiles[1] = vlProfileMpeg2Main;
+
+ return 0;
+}
+
+unsigned int vlGetMaxEntryPoints
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ return vlEntryPointCount;
+}
+
+int vlQueryEntryPoints
+(
+ struct vlScreen *screen,
+ enum vlProfile profile,
+ enum vlEntryPoint *entry_points
+)
+{
+ assert(screen);
+ assert(entry_points);
+
+ entry_points[0] = vlEntryPointIDCT;
+ entry_points[1] = vlEntryPointMC;
+ entry_points[2] = vlEntryPointCSC;
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_screen.h b/src/gallium/state_trackers/g3dvl/vl_screen.h
new file mode 100644
index 0000000000..98f3d429b6
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_screen.h
@@ -0,0 +1,63 @@
+#ifndef vl_screen_h
+#define vl_screen_h
+
+#include "vl_types.h"
+
+struct pipe_screen;
+
+#ifdef VL_INTERNAL
+struct vlScreen
+{
+ struct vlDisplay *display;
+ unsigned int ordinal;
+ struct pipe_screen *pscreen;
+};
+#endif
+
+int vlCreateScreen
+(
+ struct vlDisplay *display,
+ int screen,
+ struct pipe_screen *pscreen,
+ struct vlScreen **vl_screen
+);
+
+int vlDestroyScreen
+(
+ struct vlScreen *screen
+);
+
+struct vlDisplay* vlGetDisplay
+(
+ struct vlScreen *screen
+);
+
+struct pipe_screen* vlGetPipeScreen
+(
+ struct vlScreen *screen
+);
+
+unsigned int vlGetMaxProfiles
+(
+ struct vlScreen *screen
+);
+
+int vlQueryProfiles
+(
+ struct vlScreen *screen,
+ enum vlProfile *profiles
+);
+
+unsigned int vlGetMaxEntryPoints
+(
+ struct vlScreen *screen
+);
+
+int vlQueryEntryPoints
+(
+ struct vlScreen *screen,
+ enum vlProfile profile,
+ enum vlEntryPoint *entry_points
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_shader_build.c b/src/gallium/state_trackers/g3dvl/vl_shader_build.c
new file mode 100644
index 0000000000..51f1721a33
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_shader_build.c
@@ -0,0 +1,215 @@
+#include "vl_shader_build.h"
+#include <assert.h>
+#include <tgsi/tgsi_parse.h>
+#include <tgsi/tgsi_build.h>
+
+struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last)
+{
+ struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = name;
+ decl.Semantic.SemanticIndex = index;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
+
+ return decl;
+}
+
+struct tgsi_full_declaration vl_decl_interpolated_input
+(
+ unsigned int name,
+ unsigned int index,
+ unsigned int first,
+ unsigned int last,
+ int interpolation
+)
+{
+ struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+
+ assert
+ (
+ interpolation == TGSI_INTERPOLATE_CONSTANT ||
+ interpolation == TGSI_INTERPOLATE_LINEAR ||
+ interpolation == TGSI_INTERPOLATE_PERSPECTIVE
+ );
+
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = name;
+ decl.Semantic.SemanticIndex = index;
+ decl.Declaration.Interpolate = interpolation;;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
+
+ return decl;
+}
+
+struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last)
+{
+ struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+
+ decl.Declaration.File = TGSI_FILE_CONSTANT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = name;
+ decl.Semantic.SemanticIndex = index;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
+
+ return decl;
+}
+
+struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last)
+{
+ struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+
+ decl.Declaration.File = TGSI_FILE_OUTPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = name;
+ decl.Semantic.SemanticIndex = index;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
+
+ return decl;
+}
+
+struct tgsi_full_declaration vl_decl_temps(unsigned int first, unsigned int last)
+{
+ struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
+
+ return decl;
+}
+
+struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last)
+{
+ struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
+
+ return decl;
+}
+
+struct tgsi_full_instruction vl_inst2
+(
+ int opcode,
+ enum tgsi_file_type dst_file,
+ unsigned int dst_index,
+ enum tgsi_file_type src_file,
+ unsigned int src_index
+)
+{
+ struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+
+ inst.Instruction.Opcode = opcode;
+ inst.Instruction.NumDstRegs = 1;
+ inst.FullDstRegisters[0].DstRegister.File = dst_file;
+ inst.FullDstRegisters[0].DstRegister.Index = dst_index;
+ inst.Instruction.NumSrcRegs = 1;
+ inst.FullSrcRegisters[0].SrcRegister.File = src_file;
+ inst.FullSrcRegisters[0].SrcRegister.Index = src_index;
+
+ return inst;
+}
+
+struct tgsi_full_instruction vl_inst3
+(
+ int opcode,
+ enum tgsi_file_type dst_file,
+ unsigned int dst_index,
+ enum tgsi_file_type src1_file,
+ unsigned int src1_index,
+ enum tgsi_file_type src2_file,
+ unsigned int src2_index
+)
+{
+ struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+
+ inst.Instruction.Opcode = opcode;
+ inst.Instruction.NumDstRegs = 1;
+ inst.FullDstRegisters[0].DstRegister.File = dst_file;
+ inst.FullDstRegisters[0].DstRegister.Index = dst_index;
+ inst.Instruction.NumSrcRegs = 2;
+ inst.FullSrcRegisters[0].SrcRegister.File = src1_file;
+ inst.FullSrcRegisters[0].SrcRegister.Index = src1_index;
+ inst.FullSrcRegisters[1].SrcRegister.File = src2_file;
+ inst.FullSrcRegisters[1].SrcRegister.Index = src2_index;
+
+ return inst;
+}
+
+struct tgsi_full_instruction vl_tex
+(
+ int tex,
+ enum tgsi_file_type dst_file,
+ unsigned int dst_index,
+ enum tgsi_file_type src1_file,
+ unsigned int src1_index,
+ enum tgsi_file_type src2_file,
+ unsigned int src2_index
+)
+{
+ struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+
+ inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+ inst.Instruction.NumDstRegs = 1;
+ inst.FullDstRegisters[0].DstRegister.File = dst_file;
+ inst.FullDstRegisters[0].DstRegister.Index = dst_index;
+ inst.Instruction.NumSrcRegs = 2;
+ inst.InstructionExtTexture.Texture = tex;
+ inst.FullSrcRegisters[0].SrcRegister.File = src1_file;
+ inst.FullSrcRegisters[0].SrcRegister.Index = src1_index;
+ inst.FullSrcRegisters[1].SrcRegister.File = src2_file;
+ inst.FullSrcRegisters[1].SrcRegister.Index = src2_index;
+
+ return inst;
+}
+
+struct tgsi_full_instruction vl_inst4
+(
+ int opcode,
+ enum tgsi_file_type dst_file,
+ unsigned int dst_index,
+ enum tgsi_file_type src1_file,
+ unsigned int src1_index,
+ enum tgsi_file_type src2_file,
+ unsigned int src2_index,
+ enum tgsi_file_type src3_file,
+ unsigned int src3_index
+)
+{
+ struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+
+ inst.Instruction.Opcode = opcode;
+ inst.Instruction.NumDstRegs = 1;
+ inst.FullDstRegisters[0].DstRegister.File = dst_file;
+ inst.FullDstRegisters[0].DstRegister.Index = dst_index;
+ inst.Instruction.NumSrcRegs = 3;
+ inst.FullSrcRegisters[0].SrcRegister.File = src1_file;
+ inst.FullSrcRegisters[0].SrcRegister.Index = src1_index;
+ inst.FullSrcRegisters[1].SrcRegister.File = src2_file;
+ inst.FullSrcRegisters[1].SrcRegister.Index = src2_index;
+ inst.FullSrcRegisters[2].SrcRegister.File = src3_file;
+ inst.FullSrcRegisters[2].SrcRegister.Index = src3_index;
+
+ return inst;
+}
+
+struct tgsi_full_instruction vl_end(void)
+{
+ struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+
+ inst.Instruction.Opcode = TGSI_OPCODE_END;
+ inst.Instruction.NumDstRegs = 0;
+ inst.Instruction.NumSrcRegs = 0;
+
+ return inst;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_shader_build.h b/src/gallium/state_trackers/g3dvl/vl_shader_build.h
new file mode 100644
index 0000000000..dc615cb156
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_shader_build.h
@@ -0,0 +1,61 @@
+#ifndef vl_shader_build_h
+#define vl_shader_build_h
+
+#include <pipe/p_shader_tokens.h>
+
+struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last);
+struct tgsi_full_declaration vl_decl_interpolated_input
+(
+ unsigned int name,
+ unsigned int index,
+ unsigned int first,
+ unsigned int last,
+ int interpolation
+);
+struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last);
+struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last);
+struct tgsi_full_declaration vl_decl_temps(unsigned int first, unsigned int last);
+struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last);
+struct tgsi_full_instruction vl_inst2
+(
+ int opcode,
+ enum tgsi_file_type dst_file,
+ unsigned int dst_index,
+ enum tgsi_file_type src_file,
+ unsigned int src_index
+);
+struct tgsi_full_instruction vl_inst3
+(
+ int opcode,
+ enum tgsi_file_type dst_file,
+ unsigned int dst_index,
+ enum tgsi_file_type src1_file,
+ unsigned int src1_index,
+ enum tgsi_file_type src2_file,
+ unsigned int src2_index
+);
+struct tgsi_full_instruction vl_tex
+(
+ int tex,
+ enum tgsi_file_type dst_file,
+ unsigned int dst_index,
+ enum tgsi_file_type src1_file,
+ unsigned int src1_index,
+ enum tgsi_file_type src2_file,
+ unsigned int src2_index
+);
+struct tgsi_full_instruction vl_inst4
+(
+ int opcode,
+ enum tgsi_file_type dst_file,
+ unsigned int dst_index,
+ enum tgsi_file_type src1_file,
+ unsigned int src1_index,
+ enum tgsi_file_type src2_file,
+ unsigned int src2_index,
+ enum tgsi_file_type src3_file,
+ unsigned int src3_index
+);
+struct tgsi_full_instruction vl_end(void);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.c b/src/gallium/state_trackers/g3dvl/vl_surface.c
new file mode 100644
index 0000000000..7f60852cae
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_surface.c
@@ -0,0 +1,242 @@
+#define VL_INTERNAL
+#include "vl_surface.h"
+#include <assert.h>
+#include <string.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_state.h>
+#include <pipe/p_inlines.h>
+#include <util/u_memory.h>
+#include <vl_winsys.h>
+#include "vl_screen.h"
+#include "vl_context.h"
+#include "vl_render.h"
+#include "vl_csc.h"
+#include "vl_util.h"
+
+int vlCreateSurface
+(
+ struct vlScreen *screen,
+ unsigned int width,
+ unsigned int height,
+ enum vlFormat format,
+ struct vlSurface **surface
+)
+{
+ struct vlSurface *sfc;
+ struct pipe_texture template;
+
+ assert(screen);
+ assert(surface);
+
+ sfc = CALLOC_STRUCT(vlSurface);
+
+ if (!sfc)
+ return 1;
+
+ sfc->screen = screen;
+ sfc->width = width;
+ sfc->height = height;
+ sfc->format = format;
+
+ memset(&template, 0, sizeof(struct pipe_texture));
+ template.target = PIPE_TEXTURE_2D;
+ template.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ template.last_level = 0;
+ template.width[0] = vlRoundUpPOT(sfc->width);
+ template.height[0] = vlRoundUpPOT(sfc->height);
+ template.depth[0] = 1;
+ pf_get_block(template.format, &template.block);
+ template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET;
+
+ sfc->texture = vlGetPipeScreen(screen)->texture_create(vlGetPipeScreen(screen), &template);
+
+ if (!sfc->texture)
+ {
+ FREE(sfc);
+ return 1;
+ }
+
+ *surface = sfc;
+
+ return 0;
+}
+
+int vlDestroySurface
+(
+ struct vlSurface *surface
+)
+{
+ assert(surface);
+
+ pipe_texture_reference(&surface->texture, NULL);
+ FREE(surface);
+
+ return 0;
+}
+
+int vlRenderMacroBlocksMpeg2
+(
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+)
+{
+ assert(batch);
+ assert(surface);
+ assert(surface->context);
+
+ surface->context->render->vlBegin(surface->context->render);
+
+ surface->context->render->vlRenderMacroBlocksMpeg2
+ (
+ surface->context->render,
+ batch,
+ surface
+ );
+
+ surface->context->render->vlEnd(surface->context->render);
+
+ return 0;
+}
+
+int vlPutPicture
+(
+ struct vlSurface *surface,
+ vlNativeDrawable drawable,
+ int srcx,
+ int srcy,
+ int srcw,
+ int srch,
+ int destx,
+ int desty,
+ int destw,
+ int desth,
+ int drawable_w,
+ int drawable_h,
+ enum vlPictureType picture_type
+)
+{
+ struct vlCSC *csc;
+ struct pipe_context *pipe;
+
+ assert(surface);
+ assert(surface->context);
+
+ surface->context->render->vlFlush(surface->context->render);
+
+ csc = surface->context->csc;
+ pipe = surface->context->pipe;
+
+ csc->vlResizeFrameBuffer(csc, drawable_w, drawable_h);
+
+ csc->vlBegin(csc);
+
+ csc->vlPutPicture
+ (
+ csc,
+ surface,
+ srcx,
+ srcy,
+ srcw,
+ srch,
+ destx,
+ desty,
+ destw,
+ desth,
+ picture_type
+ );
+
+ csc->vlEnd(csc);
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &surface->disp_fence);
+
+ bind_pipe_drawable(pipe, drawable);
+
+ pipe->screen->flush_frontbuffer
+ (
+ pipe->screen,
+ csc->vlGetFrameBuffer(csc),
+ pipe->priv
+ );
+
+ return 0;
+}
+
+int vlSurfaceGetStatus
+(
+ struct vlSurface *surface,
+ enum vlResourceStatus *status
+)
+{
+ assert(surface);
+ assert(surface->context);
+ assert(status);
+
+ if (surface->render_fence && !surface->context->pipe->screen->fence_signalled(surface->context->pipe->screen, surface->render_fence, 0))
+ {
+ *status = vlResourceStatusRendering;
+ return 0;
+ }
+
+ if (surface->disp_fence && !surface->context->pipe->screen->fence_signalled(surface->context->pipe->screen, surface->disp_fence, 0))
+ {
+ *status = vlResourceStatusDisplaying;
+ return 0;
+ }
+
+ *status = vlResourceStatusFree;
+
+ return 0;
+}
+
+int vlSurfaceFlush
+(
+ struct vlSurface *surface
+)
+{
+ assert(surface);
+ assert(surface->context);
+
+ surface->context->render->vlFlush(surface->context->render);
+
+ return 0;
+}
+
+int vlSurfaceSync
+(
+ struct vlSurface *surface
+)
+{
+ assert(surface);
+ assert(surface->context);
+ assert(surface->render_fence);
+
+ surface->context->pipe->screen->fence_finish(surface->context->pipe->screen, surface->render_fence, 0);
+
+ return 0;
+}
+
+struct vlScreen* vlSurfaceGetScreen
+(
+ struct vlSurface *surface
+)
+{
+ assert(surface);
+
+ return surface->screen;
+}
+
+struct vlContext* vlBindToContext
+(
+ struct vlSurface *surface,
+ struct vlContext *context
+)
+{
+ struct vlContext *old;
+
+ assert(surface);
+
+ old = surface->context;
+ surface->context = context;
+
+ return old;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.h b/src/gallium/state_trackers/g3dvl/vl_surface.h
new file mode 100644
index 0000000000..133e1515ef
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_surface.h
@@ -0,0 +1,86 @@
+#ifndef vl_surface_h
+#define vl_surface_h
+
+#include "vl_types.h"
+
+#ifdef VL_INTERNAL
+struct pipe_texture;
+
+struct vlSurface
+{
+ struct vlScreen *screen;
+ struct vlContext *context;
+ unsigned int width;
+ unsigned int height;
+ enum vlFormat format;
+ struct pipe_texture *texture;
+ struct pipe_fence_handle *render_fence;
+ struct pipe_fence_handle *disp_fence;
+};
+#endif
+
+int vlCreateSurface
+(
+ struct vlScreen *screen,
+ unsigned int width,
+ unsigned int height,
+ enum vlFormat format,
+ struct vlSurface **surface
+);
+
+int vlDestroySurface
+(
+ struct vlSurface *surface
+);
+
+int vlRenderMacroBlocksMpeg2
+(
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+);
+
+int vlPutPicture
+(
+ struct vlSurface *surface,
+ vlNativeDrawable drawable,
+ int srcx,
+ int srcy,
+ int srcw,
+ int srch,
+ int destx,
+ int desty,
+ int destw,
+ int desth,
+ int drawable_w,
+ int drawable_h,
+ enum vlPictureType picture_type
+);
+
+int vlSurfaceGetStatus
+(
+ struct vlSurface *surface,
+ enum vlResourceStatus *status
+);
+
+int vlSurfaceFlush
+(
+ struct vlSurface *surface
+);
+
+int vlSurfaceSync
+(
+ struct vlSurface *surface
+);
+
+struct vlScreen* vlSurfaceGetScreen
+(
+ struct vlSurface *surface
+);
+
+struct vlContext* vlBindToContext
+(
+ struct vlSurface *surface,
+ struct vlContext *context
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_types.h b/src/gallium/state_trackers/g3dvl/vl_types.h
new file mode 100644
index 0000000000..274e1f7437
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_types.h
@@ -0,0 +1,115 @@
+#ifndef vl_types_h
+#define vl_types_h
+
+#if 1 /*#ifdef X11*/
+#include <X11/Xlib.h>
+
+typedef Display* vlNativeDisplay;
+typedef Drawable vlNativeDrawable;
+#endif
+
+struct vlDisplay;
+struct vlScreen;
+struct vlContext;
+struct vlSurface;
+
+enum vlResourceStatus
+{
+ vlResourceStatusFree,
+ vlResourceStatusRendering,
+ vlResourceStatusDisplaying
+};
+
+enum vlProfile
+{
+ vlProfileMpeg2Simple,
+ vlProfileMpeg2Main,
+
+ vlProfileCount
+};
+
+enum vlEntryPoint
+{
+ vlEntryPointIDCT,
+ vlEntryPointMC,
+ vlEntryPointCSC,
+
+ vlEntryPointCount
+};
+
+enum vlFormat
+{
+ vlFormatYCbCr420,
+ vlFormatYCbCr422,
+ vlFormatYCbCr444
+};
+
+enum vlPictureType
+{
+ vlPictureTypeTopField,
+ vlPictureTypeBottomField,
+ vlPictureTypeFrame
+};
+
+enum vlMotionType
+{
+ vlMotionTypeField,
+ vlMotionTypeFrame,
+ vlMotionTypeDualPrime,
+ vlMotionType16x8
+};
+
+enum vlFieldOrder
+{
+ vlFieldOrderFirst,
+ vlFieldOrderSecond
+};
+
+enum vlDCTType
+{
+ vlDCTTypeFrameCoded,
+ vlDCTTypeFieldCoded
+};
+
+struct vlVertex2f
+{
+ float x, y;
+};
+
+struct vlVertex4f
+{
+ float x, y, z, w;
+};
+
+enum vlMacroBlockType
+{
+ vlMacroBlockTypeIntra,
+ vlMacroBlockTypeFwdPredicted,
+ vlMacroBlockTypeBkwdPredicted,
+ vlMacroBlockTypeBiPredicted,
+
+ vlNumMacroBlockTypes
+};
+
+struct vlMpeg2MacroBlock
+{
+ unsigned int mbx, mby;
+ enum vlMacroBlockType mb_type;
+ enum vlMotionType mo_type;
+ enum vlDCTType dct_type;
+ int PMV[2][2][2];
+ unsigned int cbp;
+ short *blocks;
+};
+
+struct vlMpeg2MacroBlockBatch
+{
+ struct vlSurface *past_surface;
+ struct vlSurface *future_surface;
+ enum vlPictureType picture_type;
+ enum vlFieldOrder field_order;
+ unsigned int num_macroblocks;
+ struct vlMpeg2MacroBlock *macroblocks;
+};
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_util.c b/src/gallium/state_trackers/g3dvl/vl_util.c
new file mode 100644
index 0000000000..50aa9af66f
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_util.c
@@ -0,0 +1,16 @@
+#include "vl_util.h"
+#include <assert.h>
+
+unsigned int vlRoundUpPOT(unsigned int x)
+{
+ unsigned int i;
+
+ assert(x > 0);
+
+ --x;
+
+ for (i = 1; i < sizeof(unsigned int) * 8; i <<= 1)
+ x |= x >> i;
+
+ return x + 1;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_util.h b/src/gallium/state_trackers/g3dvl/vl_util.h
new file mode 100644
index 0000000000..bc98e79df4
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_util.h
@@ -0,0 +1,6 @@
+#ifndef vl_util_h
+#define vl_util_h
+
+unsigned int vlRoundUpPOT(unsigned int x);
+
+#endif
diff --git a/src/gallium/state_trackers/glx/Makefile b/src/gallium/state_trackers/glx/Makefile
new file mode 100644
index 0000000000..f779035763
--- /dev/null
+++ b/src/gallium/state_trackers/glx/Makefile
@@ -0,0 +1,25 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+SUBDIRS = xlib
+
+
+default: subdirs
+
+
+subdirs:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE)) || exit 1 ; \
+ fi \
+ done
+
+
+clean:
+ rm -f `find . -name \*.[oa]`
+ rm -f `find . -name depend`
+
+
+# Dummy install target
+install:
diff --git a/src/gallium/state_trackers/glx/xlib/Makefile b/src/gallium/state_trackers/glx/xlib/Makefile
new file mode 100644
index 0000000000..7b2adc62c3
--- /dev/null
+++ b/src/gallium/state_trackers/glx/xlib/Makefile
@@ -0,0 +1,16 @@
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = xlib
+
+LIBRARY_INCLUDES = \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa
+
+C_SOURCES = \
+ glx_api.c \
+ glx_getproc.c \
+ glx_usefont.c \
+ xm_api.c
+
+include ../../../Makefile.template
diff --git a/src/gallium/state_trackers/glx/xlib/SConscript b/src/gallium/state_trackers/glx/xlib/SConscript
new file mode 100644
index 0000000000..fa96df357d
--- /dev/null
+++ b/src/gallium/state_trackers/glx/xlib/SConscript
@@ -0,0 +1,27 @@
+#######################################################################
+# SConscript for xlib state_tracker
+
+Import('*')
+
+if env['platform'] == 'linux' \
+ and 'mesa' in env['statetrackers']:
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#/src/mesa',
+ '#/src/mesa/main',
+ ])
+
+ env.Append(CPPDEFINES = ['USE_XSHM'])
+
+ st_xlib = env.ConvenienceLibrary(
+ target = 'st_xlib',
+ source = [
+ 'glx_api.c',
+ 'glx_getproc.c',
+ 'glx_usefont.c',
+ 'xm_api.c',
+ ]
+ )
+ Export('st_xlib')
diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c
new file mode 100644
index 0000000000..d1a98f8991
--- /dev/null
+++ b/src/gallium/state_trackers/glx/xlib/glx_api.c
@@ -0,0 +1,2629 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * "Fake" GLX API implemented in terms of the XMesa*() functions.
+ */
+
+
+
+#define GLX_GLXEXT_PROTOTYPES
+#include "GL/glx.h"
+
+#include "xm_api.h"
+#include "main/context.h"
+#include "main/config.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/version.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_public.h"
+
+
+/* This indicates the client-side GLX API and GLX encoder version. */
+#define CLIENT_MAJOR_VERSION 1
+#define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */
+
+/* This indicates the server-side GLX decoder version.
+ * GLX 1.4 indicates OpenGL 1.3 support
+ */
+#define SERVER_MAJOR_VERSION 1
+#define SERVER_MINOR_VERSION 4
+
+/* This is appended onto the glXGetClient/ServerString version strings. */
+#define MESA_GLX_VERSION "Mesa " MESA_VERSION_STRING
+
+/* Who implemented this GLX? */
+#define VENDOR "Brian Paul"
+
+#define EXTENSIONS \
+ "GLX_MESA_copy_sub_buffer " \
+ "GLX_MESA_pixmap_colormap " \
+ "GLX_MESA_release_buffers " \
+ "GLX_ARB_get_proc_address " \
+ "GLX_EXT_texture_from_pixmap " \
+ "GLX_EXT_visual_info " \
+ "GLX_EXT_visual_rating " \
+ /*"GLX_SGI_video_sync "*/ \
+ "GLX_SGIX_fbconfig " \
+ "GLX_SGIX_pbuffer "
+
+#define DEFAULT_DIRECT GL_TRUE
+
+
+
+/**
+ * The GLXContext typedef is defined as a pointer to this structure.
+ */
+struct __GLXcontextRec
+{
+ Display *currentDpy;
+ GLboolean isDirect;
+ GLXDrawable currentDrawable;
+ GLXDrawable currentReadable;
+ XID xid;
+
+ XMesaContext xmesaContext;
+};
+
+
+
+static pipe_tsd ContextTSD;
+
+/** Set current context for calling thread */
+static void
+SetCurrentContext(GLXContext c)
+{
+ pipe_tsd_set(&ContextTSD, c);
+}
+
+/** Get current context for calling thread */
+static GLXContext
+GetCurrentContext(void)
+{
+ return pipe_tsd_get(&ContextTSD);
+}
+
+
+
+/**********************************************************************/
+/*** GLX Visual Code ***/
+/**********************************************************************/
+
+#define DONT_CARE -1
+
+
+static XMesaVisual *VisualTable = NULL;
+static int NumVisuals = 0;
+
+
+
+/* Macro to handle c_class vs class field name in XVisualInfo struct */
+#if defined(__cplusplus) || defined(c_plusplus)
+#define CLASS c_class
+#else
+#define CLASS class
+#endif
+
+
+
+/*
+ * Test if the given XVisualInfo is usable for Mesa rendering.
+ */
+static GLboolean
+is_usable_visual( XVisualInfo *vinfo )
+{
+ switch (vinfo->CLASS) {
+ case StaticGray:
+ case GrayScale:
+ /* Any StaticGray/GrayScale visual works in RGB or CI mode */
+ return GL_TRUE;
+ case StaticColor:
+ case PseudoColor:
+ /* Any StaticColor/PseudoColor visual of at least 4 bits */
+ if (vinfo->depth>=4) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+ case TrueColor:
+ case DirectColor:
+ /* Any depth of TrueColor or DirectColor works in RGB mode */
+ return GL_TRUE;
+ default:
+ /* This should never happen */
+ return GL_FALSE;
+ }
+}
+
+
+/*
+ * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
+ * configuration in our list of GLX visuals.
+ */
+static XMesaVisual
+save_glx_visual( Display *dpy, XVisualInfo *vinfo,
+ GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
+ GLboolean stereoFlag,
+ GLint depth_size, GLint stencil_size,
+ GLint accumRedSize, GLint accumGreenSize,
+ GLint accumBlueSize, GLint accumAlphaSize,
+ GLint level, GLint numAuxBuffers )
+{
+ GLboolean ximageFlag = GL_TRUE;
+ XMesaVisual xmvis;
+ GLint i;
+ GLboolean comparePointers;
+
+ if (dbFlag) {
+ /* Check if the MESA_BACK_BUFFER env var is set */
+ char *backbuffer = _mesa_getenv("MESA_BACK_BUFFER");
+ if (backbuffer) {
+ if (backbuffer[0]=='p' || backbuffer[0]=='P') {
+ ximageFlag = GL_FALSE;
+ }
+ else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
+ ximageFlag = GL_TRUE;
+ }
+ else {
+ _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage.");
+ }
+ }
+ }
+
+ if (stereoFlag) {
+ /* stereo not supported */
+ return NULL;
+ }
+
+ if (stencil_size > 0 && depth_size > 0)
+ depth_size = 24;
+
+ /* Comparing IDs uses less memory but sometimes fails. */
+ /* XXX revisit this after 3.0 is finished. */
+ if (_mesa_getenv("MESA_GLX_VISUAL_HACK"))
+ comparePointers = GL_TRUE;
+ else
+ comparePointers = GL_FALSE;
+
+ /* Force the visual to have an alpha channel */
+ if (rgbFlag && _mesa_getenv("MESA_GLX_FORCE_ALPHA"))
+ alphaFlag = GL_TRUE;
+
+ /* First check if a matching visual is already in the list */
+ for (i=0; i<NumVisuals; i++) {
+ XMesaVisual v = VisualTable[i];
+ if (v->display == dpy
+ && v->mesa_visual.level == level
+ && v->mesa_visual.numAuxBuffers == numAuxBuffers
+ && v->ximage_flag == ximageFlag
+ && v->mesa_visual.rgbMode == rgbFlag
+ && v->mesa_visual.doubleBufferMode == dbFlag
+ && v->mesa_visual.stereoMode == stereoFlag
+ && (v->mesa_visual.alphaBits > 0) == alphaFlag
+ && (v->mesa_visual.depthBits >= depth_size || depth_size == 0)
+ && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0)
+ && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0)
+ && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0)
+ && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0)
+ && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) {
+ /* now either compare XVisualInfo pointers or visual IDs */
+ if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)
+ || (comparePointers && v->vishandle == vinfo)) {
+ return v;
+ }
+ }
+ }
+
+ /* Create a new visual and add it to the list. */
+
+ xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
+ stereoFlag, ximageFlag,
+ depth_size, stencil_size,
+ accumRedSize, accumBlueSize,
+ accumBlueSize, accumAlphaSize, 0, level,
+ GLX_NONE_EXT );
+ if (xmvis) {
+ /* Save a copy of the pointer now so we can find this visual again
+ * if we need to search for it in find_glx_visual().
+ */
+ xmvis->vishandle = vinfo;
+ /* Allocate more space for additional visual */
+ VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable,
+ sizeof(XMesaVisual) * NumVisuals,
+ sizeof(XMesaVisual) * (NumVisuals + 1));
+ /* add xmvis to the list */
+ VisualTable[NumVisuals] = xmvis;
+ NumVisuals++;
+ /* XXX minor hack, because XMesaCreateVisual doesn't support an
+ * aux buffers parameter.
+ */
+ xmvis->mesa_visual.numAuxBuffers = numAuxBuffers;
+ }
+ return xmvis;
+}
+
+
+/**
+ * Return the default number of bits for the Z buffer.
+ * If defined, use the MESA_GLX_DEPTH_BITS env var value.
+ * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant.
+ * XXX probably do the same thing for stencil, accum, etc.
+ */
+static GLint
+default_depth_bits(void)
+{
+ int zBits;
+ const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS");
+ if (zEnv)
+ zBits = _mesa_atoi(zEnv);
+ else
+ zBits = DEFAULT_SOFTWARE_DEPTH_BITS;
+ return zBits;
+}
+
+static GLint
+default_alpha_bits(void)
+{
+ int aBits;
+ const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS");
+ if (aEnv)
+ aBits = _mesa_atoi(aEnv);
+ else
+ aBits = 0;
+ return aBits;
+}
+
+static GLint
+default_accum_bits(void)
+{
+ return 16;
+}
+
+
+
+/*
+ * Create a GLX visual from a regular XVisualInfo.
+ * This is called when Fake GLX is given an XVisualInfo which wasn't
+ * returned by glXChooseVisual. Since this is the first time we're
+ * considering this visual we'll take a guess at reasonable values
+ * for depth buffer size, stencil size, accum size, etc.
+ * This is the best we can do with a client-side emulation of GLX.
+ */
+static XMesaVisual
+create_glx_visual( Display *dpy, XVisualInfo *visinfo )
+{
+ GLint zBits = default_depth_bits();
+ GLint accBits = default_accum_bits();
+ GLboolean alphaFlag = default_alpha_bits() > 0;
+
+ if (is_usable_visual( visinfo )) {
+ /* Configure this visual as RGB, double-buffered, depth-buffered. */
+ /* This is surely wrong for some people's needs but what else */
+ /* can be done? They should use glXChooseVisual(). */
+ return save_glx_visual( dpy, visinfo,
+ GL_TRUE, /* rgb */
+ alphaFlag, /* alpha */
+ GL_TRUE, /* double */
+ GL_FALSE, /* stereo */
+ zBits,
+ STENCIL_BITS,
+ accBits, /* r */
+ accBits, /* g */
+ accBits, /* b */
+ accBits, /* a */
+ 0, /* level */
+ 0 /* numAux */
+ );
+ }
+ else {
+ _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n");
+ return NULL;
+ }
+}
+
+
+
+/*
+ * Find the GLX visual associated with an XVisualInfo.
+ */
+static XMesaVisual
+find_glx_visual( Display *dpy, XVisualInfo *vinfo )
+{
+ int i;
+
+ /* try to match visual id */
+ for (i=0;i<NumVisuals;i++) {
+ if (VisualTable[i]->display==dpy
+ && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
+ return VisualTable[i];
+ }
+ }
+
+ /* if that fails, try to match pointers */
+ for (i=0;i<NumVisuals;i++) {
+ if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
+ return VisualTable[i];
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Try to get an X visual which matches the given arguments.
+ */
+static XVisualInfo *
+get_visual( Display *dpy, int scr, unsigned int depth, int xclass )
+{
+ XVisualInfo temp, *vis;
+ long mask;
+ int n;
+ unsigned int default_depth;
+ int default_class;
+
+ mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
+ temp.screen = scr;
+ temp.depth = depth;
+ temp.CLASS = xclass;
+
+ default_depth = DefaultDepth(dpy,scr);
+ default_class = DefaultVisual(dpy,scr)->CLASS;
+
+ if (depth==default_depth && xclass==default_class) {
+ /* try to get root window's visual */
+ temp.visualid = DefaultVisual(dpy,scr)->visualid;
+ mask |= VisualIDMask;
+ }
+
+ vis = XGetVisualInfo( dpy, mask, &temp, &n );
+
+ /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
+ * An SGI Infinite Reality system, for example, can have 30bpp pixels:
+ * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.
+ */
+ if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
+ if (_mesa_bitcount((GLuint) vis->red_mask ) <= 8 &&
+ _mesa_bitcount((GLuint) vis->green_mask) <= 8 &&
+ _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) {
+ return vis;
+ }
+ else {
+ XFree((void *) vis);
+ return NULL;
+ }
+ }
+
+ return vis;
+}
+
+
+/*
+ * Retrieve the value of the given environment variable and find
+ * the X visual which matches it.
+ * Input: dpy - the display
+ * screen - the screen number
+ * varname - the name of the environment variable
+ * Return: an XVisualInfo pointer to NULL if error.
+ */
+static XVisualInfo *
+get_env_visual(Display *dpy, int scr, const char *varname)
+{
+ char value[100], type[100];
+ int depth, xclass = -1;
+ XVisualInfo *vis;
+
+ if (!_mesa_getenv( varname )) {
+ return NULL;
+ }
+
+ _mesa_strncpy( value, _mesa_getenv(varname), 100 );
+ value[99] = 0;
+
+ sscanf( value, "%s %d", type, &depth );
+
+ if (_mesa_strcmp(type,"TrueColor")==0) xclass = TrueColor;
+ else if (_mesa_strcmp(type,"DirectColor")==0) xclass = DirectColor;
+ else if (_mesa_strcmp(type,"PseudoColor")==0) xclass = PseudoColor;
+ else if (_mesa_strcmp(type,"StaticColor")==0) xclass = StaticColor;
+ else if (_mesa_strcmp(type,"GrayScale")==0) xclass = GrayScale;
+ else if (_mesa_strcmp(type,"StaticGray")==0) xclass = StaticGray;
+
+ if (xclass>-1 && depth>0) {
+ vis = get_visual( dpy, scr, depth, xclass );
+ if (vis) {
+ return vis;
+ }
+ }
+
+ _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.",
+ type, depth);
+
+ return NULL;
+}
+
+
+
+/*
+ * Select an X visual which satisfies the RGBA flag and minimum depth.
+ * Input: dpy,
+ * screen - X display and screen number
+ * min_depth - minimum visual depth
+ * preferred_class - preferred GLX visual class or DONT_CARE
+ * Return: pointer to an XVisualInfo or NULL.
+ */
+static XVisualInfo *
+choose_x_visual( Display *dpy, int screen, int min_depth,
+ int preferred_class )
+{
+ XVisualInfo *vis;
+ int xclass, visclass = 0;
+ int depth;
+
+ /* First see if the MESA_RGB_VISUAL env var is defined */
+ vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
+ if (vis) {
+ return vis;
+ }
+ /* Otherwise, search for a suitable visual */
+ if (preferred_class==DONT_CARE) {
+ for (xclass=0;xclass<6;xclass++) {
+ switch (xclass) {
+ case 0: visclass = TrueColor; break;
+ case 1: visclass = DirectColor; break;
+ case 2: visclass = PseudoColor; break;
+ case 3: visclass = StaticColor; break;
+ case 4: visclass = GrayScale; break;
+ case 5: visclass = StaticGray; break;
+ }
+ if (min_depth==0) {
+ /* start with shallowest */
+ for (depth=0;depth<=32;depth++) {
+ if (visclass==TrueColor && depth==8) {
+ /* Special case: try to get 8-bit PseudoColor before */
+ /* 8-bit TrueColor */
+ vis = get_visual( dpy, screen, 8, PseudoColor );
+ if (vis) {
+ return vis;
+ }
+ }
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ else {
+ /* start with deepest */
+ for (depth=32;depth>=min_depth;depth--) {
+ if (visclass==TrueColor && depth==8) {
+ /* Special case: try to get 8-bit PseudoColor before */
+ /* 8-bit TrueColor */
+ vis = get_visual( dpy, screen, 8, PseudoColor );
+ if (vis) {
+ return vis;
+ }
+ }
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* search for a specific visual class */
+ switch (preferred_class) {
+ case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
+ case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
+ case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
+ case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
+ case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
+ case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
+ default: return NULL;
+ }
+ if (min_depth==0) {
+ /* start with shallowest */
+ for (depth=0;depth<=32;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ else {
+ /* start with deepest */
+ for (depth=32;depth>=min_depth;depth--) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+
+ /* didn't find a visual */
+ return NULL;
+}
+
+
+
+
+/**********************************************************************/
+/*** Display-related functions ***/
+/**********************************************************************/
+
+
+/**
+ * Free all XMesaVisuals which are associated with the given display.
+ */
+static void
+destroy_visuals_on_display(Display *dpy)
+{
+ int i;
+ for (i = 0; i < NumVisuals; i++) {
+ if (VisualTable[i]->display == dpy) {
+ /* remove this visual */
+ int j;
+ free(VisualTable[i]);
+ for (j = i; j < NumVisuals - 1; j++)
+ VisualTable[j] = VisualTable[j + 1];
+ NumVisuals--;
+ }
+ }
+}
+
+
+/**
+ * Called from XCloseDisplay() to let us free our display-related data.
+ */
+static int
+close_display_callback(Display *dpy, XExtCodes *codes)
+{
+ destroy_visuals_on_display(dpy);
+ xmesa_destroy_buffers_on_display(dpy);
+ return 0;
+}
+
+
+/**
+ * Look for the named extension on given display and return a pointer
+ * to the _XExtension data, or NULL if extension not found.
+ */
+static _XExtension *
+lookup_extension(Display *dpy, const char *extName)
+{
+ _XExtension *ext;
+ for (ext = dpy->ext_procs; ext; ext = ext->next) {
+ if (ext->name && strcmp(ext->name, extName) == 0) {
+ return ext;
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * Whenever we're given a new Display pointer, call this function to
+ * register our close_display_callback function.
+ */
+static void
+register_with_display(Display *dpy)
+{
+ const char *extName = "MesaGLX";
+ _XExtension *ext;
+
+ ext = lookup_extension(dpy, extName);
+ if (!ext) {
+ XExtCodes *c = XAddExtension(dpy);
+ ext = dpy->ext_procs; /* new extension is at head of list */
+ assert(c->extension == ext->codes.extension);
+ ext->name = _mesa_strdup(extName);
+ ext->close_display = close_display_callback;
+ }
+}
+
+
+/**********************************************************************/
+/*** Begin Fake GLX API Functions ***/
+/**********************************************************************/
+
+
+/**
+ * Helper used by glXChooseVisual and glXChooseFBConfig.
+ * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for
+ * the later.
+ * In either case, the attribute list is terminated with the value 'None'.
+ */
+static XMesaVisual
+choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
+{
+ const GLboolean rgbModeDefault = fbConfig;
+ const int *parselist;
+ XVisualInfo *vis;
+ int min_ci = 0;
+ int min_red=0, min_green=0, min_blue=0;
+ GLboolean rgb_flag = rgbModeDefault;
+ GLboolean alpha_flag = GL_FALSE;
+ GLboolean double_flag = GL_FALSE;
+ GLboolean stereo_flag = GL_FALSE;
+ GLint depth_size = 0;
+ GLint stencil_size = 0;
+ GLint accumRedSize = 0;
+ GLint accumGreenSize = 0;
+ GLint accumBlueSize = 0;
+ GLint accumAlphaSize = 0;
+ int level = 0;
+ int visual_type = DONT_CARE;
+ int trans_type = DONT_CARE;
+ int trans_value = DONT_CARE;
+ GLint caveat = DONT_CARE;
+ XMesaVisual xmvis = NULL;
+ int desiredVisualID = -1;
+ int numAux = 0;
+
+ parselist = list;
+
+ while (*parselist) {
+
+ switch (*parselist) {
+ case GLX_USE_GL:
+ if (fbConfig) {
+ /* invalid token */
+ return NULL;
+ }
+ else {
+ /* skip */
+ parselist++;
+ }
+ break;
+ case GLX_BUFFER_SIZE:
+ parselist++;
+ min_ci = *parselist++;
+ break;
+ case GLX_LEVEL:
+ parselist++;
+ level = *parselist++;
+ break;
+ case GLX_RGBA:
+ if (fbConfig) {
+ /* invalid token */
+ return NULL;
+ }
+ else {
+ rgb_flag = GL_TRUE;
+ parselist++;
+ }
+ break;
+ case GLX_DOUBLEBUFFER:
+ parselist++;
+ if (fbConfig) {
+ double_flag = *parselist++;
+ }
+ else {
+ double_flag = GL_TRUE;
+ }
+ break;
+ case GLX_STEREO:
+ parselist++;
+ if (fbConfig) {
+ stereo_flag = *parselist++;
+ }
+ else {
+ stereo_flag = GL_TRUE;
+ }
+ break;
+ case GLX_AUX_BUFFERS:
+ parselist++;
+ numAux = *parselist++;
+ if (numAux > MAX_AUX_BUFFERS)
+ return NULL;
+ break;
+ case GLX_RED_SIZE:
+ parselist++;
+ min_red = *parselist++;
+ break;
+ case GLX_GREEN_SIZE:
+ parselist++;
+ min_green = *parselist++;
+ break;
+ case GLX_BLUE_SIZE:
+ parselist++;
+ min_blue = *parselist++;
+ break;
+ case GLX_ALPHA_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ alpha_flag = size ? GL_TRUE : GL_FALSE;
+ }
+ break;
+ case GLX_DEPTH_SIZE:
+ parselist++;
+ depth_size = *parselist++;
+ break;
+ case GLX_STENCIL_SIZE:
+ parselist++;
+ stencil_size = *parselist++;
+ break;
+ case GLX_ACCUM_RED_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ accumRedSize = MAX2( accumRedSize, size );
+ }
+ break;
+ case GLX_ACCUM_GREEN_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ accumGreenSize = MAX2( accumGreenSize, size );
+ }
+ break;
+ case GLX_ACCUM_BLUE_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ accumBlueSize = MAX2( accumBlueSize, size );
+ }
+ break;
+ case GLX_ACCUM_ALPHA_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ accumAlphaSize = MAX2( accumAlphaSize, size );
+ }
+ break;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_X_VISUAL_TYPE_EXT:
+ parselist++;
+ visual_type = *parselist++;
+ break;
+ case GLX_TRANSPARENT_TYPE_EXT:
+ parselist++;
+ trans_type = *parselist++;
+ break;
+ case GLX_TRANSPARENT_INDEX_VALUE_EXT:
+ parselist++;
+ trans_value = *parselist++;
+ break;
+ case GLX_TRANSPARENT_RED_VALUE_EXT:
+ case GLX_TRANSPARENT_GREEN_VALUE_EXT:
+ case GLX_TRANSPARENT_BLUE_VALUE_EXT:
+ case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
+ /* ignore */
+ parselist++;
+ parselist++;
+ break;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_VISUAL_CAVEAT_EXT:
+ parselist++;
+ caveat = *parselist++; /* ignored for now */
+ break;
+
+ /*
+ * GLX_ARB_multisample
+ */
+ case GLX_SAMPLE_BUFFERS_ARB:
+ /* ms not supported */
+ return NULL;
+ case GLX_SAMPLES_ARB:
+ /* ms not supported */
+ return NULL;
+
+ /*
+ * FBConfig attribs.
+ */
+ case GLX_RENDER_TYPE:
+ if (!fbConfig)
+ return NULL;
+ parselist++;
+ if (*parselist == GLX_RGBA_BIT) {
+ rgb_flag = GL_TRUE;
+ }
+ else if (*parselist == GLX_COLOR_INDEX_BIT) {
+ rgb_flag = GL_FALSE;
+ }
+ else if (*parselist == 0) {
+ rgb_flag = GL_TRUE;
+ }
+ parselist++;
+ break;
+ case GLX_DRAWABLE_TYPE:
+ if (!fbConfig)
+ return NULL;
+ parselist++;
+ if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {
+ return NULL; /* bad bit */
+ }
+ parselist++;
+ break;
+ case GLX_FBCONFIG_ID:
+ if (!fbConfig)
+ return NULL;
+ parselist++;
+ desiredVisualID = *parselist++;
+ break;
+ case GLX_X_RENDERABLE:
+ if (!fbConfig)
+ return NULL;
+ parselist += 2;
+ /* ignore */
+ break;
+
+#ifdef GLX_EXT_texture_from_pixmap
+ case GLX_BIND_TO_TEXTURE_RGB_EXT:
+ parselist++; /*skip*/
+ break;
+ case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+ parselist++; /*skip*/
+ break;
+ case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+ parselist++; /*skip*/
+ break;
+ case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+ parselist++;
+ if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT |
+ GLX_TEXTURE_2D_BIT_EXT |
+ GLX_TEXTURE_RECTANGLE_BIT_EXT)) {
+ /* invalid bit */
+ return NULL;
+ }
+ break;
+ case GLX_Y_INVERTED_EXT:
+ parselist++; /*skip*/
+ break;
+#endif
+
+ case None:
+ /* end of list */
+ break;
+
+ default:
+ /* undefined attribute */
+ _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()",
+ *parselist);
+ return NULL;
+ }
+ }
+
+ (void) caveat;
+
+
+ /*
+ * Since we're only simulating the GLX extension this function will never
+ * find any real GL visuals. Instead, all we can do is try to find an RGB
+ * or CI visual of appropriate depth. Other requested attributes such as
+ * double buffering, depth buffer, etc. will be associated with the X
+ * visual and stored in the VisualTable[].
+ */
+ if (desiredVisualID != -1) {
+ /* try to get a specific visual, by visualID */
+ XVisualInfo temp;
+ int n;
+ temp.visualid = desiredVisualID;
+ temp.screen = screen;
+ vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n);
+ if (vis) {
+ /* give the visual some useful GLX attributes */
+ double_flag = GL_TRUE;
+ rgb_flag = GL_TRUE;
+ depth_size = default_depth_bits();
+ stencil_size = STENCIL_BITS;
+ /* XXX accum??? */
+ }
+ }
+ else if (level==0) {
+ /* normal color planes */
+ /* Get an RGB visual */
+ int min_rgb = min_red + min_green + min_blue;
+ if (min_rgb>1 && min_rgb<8) {
+ /* a special case to be sure we can get a monochrome visual */
+ min_rgb = 1;
+ }
+ vis = choose_x_visual( dpy, screen, min_rgb, visual_type );
+ }
+ else {
+ _mesa_warning(NULL, "overlay not supported");
+ return NULL;
+ }
+
+ if (vis) {
+ /* Note: we're not exactly obeying the glXChooseVisual rules here.
+ * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the
+ * largest depth buffer size, which is 32bits/value. Instead, we
+ * return 16 to maintain performance with earlier versions of Mesa.
+ */
+ if (stencil_size > 0)
+ depth_size = 24; /* if Z and stencil, always use 24+8 format */
+ else if (depth_size > 24)
+ depth_size = 32;
+ else if (depth_size > 16)
+ depth_size = 24;
+ else if (depth_size > 0) {
+ depth_size = default_depth_bits();
+ }
+
+ if (!alpha_flag) {
+ alpha_flag = default_alpha_bits() > 0;
+ }
+
+ /* we only support one size of stencil and accum buffers. */
+ if (stencil_size > 0)
+ stencil_size = STENCIL_BITS;
+
+ if (accumRedSize > 0 ||
+ accumGreenSize > 0 ||
+ accumBlueSize > 0 ||
+ accumAlphaSize > 0) {
+
+ accumRedSize =
+ accumGreenSize =
+ accumBlueSize = default_accum_bits();
+
+ accumAlphaSize = alpha_flag ? accumRedSize : 0;
+ }
+
+ xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
+ stereo_flag, depth_size, stencil_size,
+ accumRedSize, accumGreenSize,
+ accumBlueSize, accumAlphaSize, level, numAux );
+ }
+
+ return xmvis;
+}
+
+
+XVisualInfo *
+glXChooseVisual( Display *dpy, int screen, int *list )
+{
+ XMesaVisual xmvis;
+
+ /* register ourselves as an extension on this display */
+ register_with_display(dpy);
+
+ xmvis = choose_visual(dpy, screen, list, GL_FALSE);
+ if (xmvis) {
+ /* create a new vishandle - the cached one may be stale */
+ xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo));
+ if (xmvis->vishandle) {
+ _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
+ }
+ return xmvis->vishandle;
+ }
+ else
+ return NULL;
+}
+
+
+GLXContext
+glXCreateContext( Display *dpy, XVisualInfo *visinfo,
+ GLXContext share_list, Bool direct )
+{
+ XMesaVisual xmvis;
+ GLXContext glxCtx;
+ GLXContext shareCtx = share_list;
+
+ if (!dpy || !visinfo)
+ return 0;
+
+ glxCtx = CALLOC_STRUCT(__GLXcontextRec);
+ if (!glxCtx)
+ return 0;
+
+ /* deallocate unused windows/buffers */
+#if 0
+ XMesaGarbageCollect();
+#endif
+
+ xmvis = find_glx_visual( dpy, visinfo );
+ if (!xmvis) {
+ /* This visual wasn't found with glXChooseVisual() */
+ xmvis = create_glx_visual( dpy, visinfo );
+ if (!xmvis) {
+ /* unusable visual */
+ _mesa_free(glxCtx);
+ return NULL;
+ }
+ }
+
+ glxCtx->xmesaContext = XMesaCreateContext(xmvis,
+ shareCtx ? shareCtx->xmesaContext : NULL);
+ if (!glxCtx->xmesaContext) {
+ _mesa_free(glxCtx);
+ return NULL;
+ }
+
+ glxCtx->isDirect = DEFAULT_DIRECT;
+ glxCtx->currentDpy = dpy;
+ glxCtx->xid = (XID) glxCtx; /* self pointer */
+
+ return glxCtx;
+}
+
+
+/* XXX these may have to be removed due to thread-safety issues. */
+static GLXContext MakeCurrent_PrevContext = 0;
+static GLXDrawable MakeCurrent_PrevDrawable = 0;
+static GLXDrawable MakeCurrent_PrevReadable = 0;
+static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
+static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
+
+
+/* GLX 1.3 and later */
+Bool
+glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
+ GLXDrawable read, GLXContext ctx )
+{
+ GLXContext glxCtx = ctx;
+ static boolean firsttime = 1, no_rast = 0;
+
+ if (firsttime) {
+ no_rast = getenv("SP_NO_RAST") != NULL;
+ firsttime = 0;
+ }
+
+ if (ctx && draw && read) {
+ XMesaBuffer drawBuffer, readBuffer;
+ XMesaContext xmctx = glxCtx->xmesaContext;
+
+ /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
+ if (ctx == MakeCurrent_PrevContext
+ && draw == MakeCurrent_PrevDrawable) {
+ drawBuffer = MakeCurrent_PrevDrawBuffer;
+ }
+ else {
+ drawBuffer = XMesaFindBuffer( dpy, draw );
+ }
+ if (!drawBuffer) {
+ /* drawable must be a new window! */
+ drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw );
+ if (!drawBuffer) {
+ /* Out of memory, or context/drawable depth mismatch */
+ return False;
+ }
+ }
+
+ /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
+ if (ctx == MakeCurrent_PrevContext
+ && read == MakeCurrent_PrevReadable) {
+ readBuffer = MakeCurrent_PrevReadBuffer;
+ }
+ else {
+ readBuffer = XMesaFindBuffer( dpy, read );
+ }
+ if (!readBuffer) {
+ /* drawable must be a new window! */
+ readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read );
+ if (!readBuffer) {
+ /* Out of memory, or context/drawable depth mismatch */
+ return False;
+ }
+ }
+
+ if (no_rast &&
+ MakeCurrent_PrevContext == ctx &&
+ MakeCurrent_PrevDrawable == draw &&
+ MakeCurrent_PrevReadable == read &&
+ MakeCurrent_PrevDrawBuffer == drawBuffer &&
+ MakeCurrent_PrevReadBuffer == readBuffer)
+ return True;
+
+ MakeCurrent_PrevContext = ctx;
+ MakeCurrent_PrevDrawable = draw;
+ MakeCurrent_PrevReadable = read;
+ MakeCurrent_PrevDrawBuffer = drawBuffer;
+ MakeCurrent_PrevReadBuffer = readBuffer;
+
+ /* Now make current! */
+ if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
+ ctx->currentDpy = dpy;
+ ctx->currentDrawable = draw;
+ ctx->currentReadable = read;
+ SetCurrentContext(ctx);
+ return True;
+ }
+ else {
+ return False;
+ }
+ }
+ else if (!ctx && !draw && !read) {
+ /* release current context w/out assigning new one. */
+ XMesaMakeCurrent2( NULL, NULL, NULL );
+ MakeCurrent_PrevContext = 0;
+ MakeCurrent_PrevDrawable = 0;
+ MakeCurrent_PrevReadable = 0;
+ MakeCurrent_PrevDrawBuffer = 0;
+ MakeCurrent_PrevReadBuffer = 0;
+ SetCurrentContext(NULL);
+ return True;
+ }
+ else {
+ /* The args must either all be non-zero or all zero.
+ * This is an error.
+ */
+ return False;
+ }
+}
+
+
+Bool
+glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
+{
+ return glXMakeContextCurrent( dpy, drawable, drawable, ctx );
+}
+
+
+GLXContext
+glXGetCurrentContext(void)
+{
+ return GetCurrentContext();
+}
+
+
+Display *
+glXGetCurrentDisplay(void)
+{
+ GLXContext glxCtx = glXGetCurrentContext();
+
+ return glxCtx ? glxCtx->currentDpy : NULL;
+}
+
+
+Display *
+glXGetCurrentDisplayEXT(void)
+{
+ return glXGetCurrentDisplay();
+}
+
+
+GLXDrawable
+glXGetCurrentDrawable(void)
+{
+ GLXContext gc = glXGetCurrentContext();
+ return gc ? gc->currentDrawable : 0;
+}
+
+
+GLXDrawable
+glXGetCurrentReadDrawable(void)
+{
+ GLXContext gc = glXGetCurrentContext();
+ return gc ? gc->currentReadable : 0;
+}
+
+
+GLXDrawable
+glXGetCurrentReadDrawableSGI(void)
+{
+ return glXGetCurrentReadDrawable();
+}
+
+
+GLXPixmap
+glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
+{
+ XMesaVisual v;
+ XMesaBuffer b;
+
+ v = find_glx_visual( dpy, visinfo );
+ if (!v) {
+ v = create_glx_visual( dpy, visinfo );
+ if (!v) {
+ /* unusable visual */
+ return 0;
+ }
+ }
+
+ b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+ if (!b) {
+ return 0;
+ }
+ return b->drawable;
+}
+
+
+/*** GLX_MESA_pixmap_colormap ***/
+
+GLXPixmap
+glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
+ Pixmap pixmap, Colormap cmap )
+{
+ XMesaVisual v;
+ XMesaBuffer b;
+
+ v = find_glx_visual( dpy, visinfo );
+ if (!v) {
+ v = create_glx_visual( dpy, visinfo );
+ if (!v) {
+ /* unusable visual */
+ return 0;
+ }
+ }
+
+ b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
+ if (!b) {
+ return 0;
+ }
+ return b->drawable;
+}
+
+
+void
+glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
+ if (b) {
+ XMesaDestroyBuffer(b);
+ }
+ else if (_mesa_getenv("MESA_DEBUG")) {
+ _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
+ }
+}
+
+
+void
+glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
+ unsigned long mask )
+{
+ XMesaContext xm_src = src->xmesaContext;
+ XMesaContext xm_dst = dst->xmesaContext;
+ (void) dpy;
+ if (MakeCurrent_PrevContext == src) {
+ _mesa_Flush();
+ }
+ st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask );
+}
+
+
+Bool
+glXQueryExtension( Display *dpy, int *errorb, int *event )
+{
+ /* Mesa's GLX isn't really an X extension but we try to act like one. */
+ (void) dpy;
+ (void) errorb;
+ (void) event;
+ return True;
+}
+
+
+void
+glXDestroyContext( Display *dpy, GLXContext ctx )
+{
+ GLXContext glxCtx = ctx;
+ (void) dpy;
+ MakeCurrent_PrevContext = 0;
+ MakeCurrent_PrevDrawable = 0;
+ MakeCurrent_PrevReadable = 0;
+ MakeCurrent_PrevDrawBuffer = 0;
+ MakeCurrent_PrevReadBuffer = 0;
+ XMesaDestroyContext( glxCtx->xmesaContext );
+ XMesaGarbageCollect();
+ _mesa_free(glxCtx);
+}
+
+
+Bool
+glXIsDirect( Display *dpy, GLXContext ctx )
+{
+ GLXContext glxCtx = ctx;
+ (void) ctx;
+ return glxCtx->isDirect;
+}
+
+
+
+void
+glXSwapBuffers( Display *dpy, GLXDrawable drawable )
+{
+ XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
+ static boolean firsttime = 1, no_rast = 0;
+
+ if (firsttime) {
+ no_rast = getenv("SP_NO_RAST") != NULL;
+ firsttime = 0;
+ }
+
+ if (no_rast)
+ return;
+
+ if (buffer) {
+ XMesaSwapBuffers(buffer);
+ }
+ else if (_mesa_getenv("MESA_DEBUG")) {
+ _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",
+ (int) drawable);
+ }
+}
+
+
+
+/*** GLX_MESA_copy_sub_buffer ***/
+
+void
+glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
+ int x, int y, int width, int height )
+{
+ XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
+ if (buffer) {
+ XMesaCopySubBuffer(buffer, x, y, width, height);
+ }
+ else if (_mesa_getenv("MESA_DEBUG")) {
+ _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
+ }
+}
+
+
+Bool
+glXQueryVersion( Display *dpy, int *maj, int *min )
+{
+ (void) dpy;
+ /* Return GLX version, not Mesa version */
+ assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
+ *maj = CLIENT_MAJOR_VERSION;
+ *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
+ return True;
+}
+
+
+/*
+ * Query the GLX attributes of the given XVisualInfo.
+ */
+static int
+get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
+{
+ ASSERT(xmvis);
+ switch(attrib) {
+ case GLX_USE_GL:
+ if (fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = (int) True;
+ return 0;
+ case GLX_BUFFER_SIZE:
+ *value = xmvis->visinfo->depth;
+ return 0;
+ case GLX_LEVEL:
+ *value = xmvis->mesa_visual.level;
+ return 0;
+ case GLX_RGBA:
+ if (fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ if (xmvis->mesa_visual.rgbMode) {
+ *value = True;
+ }
+ else {
+ *value = False;
+ }
+ return 0;
+ case GLX_DOUBLEBUFFER:
+ *value = (int) xmvis->mesa_visual.doubleBufferMode;
+ return 0;
+ case GLX_STEREO:
+ *value = (int) xmvis->mesa_visual.stereoMode;
+ return 0;
+ case GLX_AUX_BUFFERS:
+ *value = xmvis->mesa_visual.numAuxBuffers;
+ return 0;
+ case GLX_RED_SIZE:
+ *value = xmvis->mesa_visual.redBits;
+ return 0;
+ case GLX_GREEN_SIZE:
+ *value = xmvis->mesa_visual.greenBits;
+ return 0;
+ case GLX_BLUE_SIZE:
+ *value = xmvis->mesa_visual.blueBits;
+ return 0;
+ case GLX_ALPHA_SIZE:
+ *value = xmvis->mesa_visual.alphaBits;
+ return 0;
+ case GLX_DEPTH_SIZE:
+ *value = xmvis->mesa_visual.depthBits;
+ return 0;
+ case GLX_STENCIL_SIZE:
+ *value = xmvis->mesa_visual.stencilBits;
+ return 0;
+ case GLX_ACCUM_RED_SIZE:
+ *value = xmvis->mesa_visual.accumRedBits;
+ return 0;
+ case GLX_ACCUM_GREEN_SIZE:
+ *value = xmvis->mesa_visual.accumGreenBits;
+ return 0;
+ case GLX_ACCUM_BLUE_SIZE:
+ *value = xmvis->mesa_visual.accumBlueBits;
+ return 0;
+ case GLX_ACCUM_ALPHA_SIZE:
+ *value = xmvis->mesa_visual.accumAlphaBits;
+ return 0;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_X_VISUAL_TYPE_EXT:
+ switch (xmvis->visinfo->CLASS) {
+ case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0;
+ case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0;
+ case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0;
+ case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0;
+ case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0;
+ case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0;
+ }
+ return 0;
+ case GLX_TRANSPARENT_TYPE_EXT:
+ /* normal planes */
+ *value = GLX_NONE_EXT;
+ return 0;
+ case GLX_TRANSPARENT_INDEX_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_RED_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_GREEN_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_BLUE_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
+ /* undefined */
+ return 0;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_VISUAL_CAVEAT_EXT:
+ /* test for zero, just in case */
+ if (xmvis->mesa_visual.visualRating > 0)
+ *value = xmvis->mesa_visual.visualRating;
+ else
+ *value = GLX_NONE_EXT;
+ return 0;
+
+ /*
+ * GLX_ARB_multisample
+ */
+ case GLX_SAMPLE_BUFFERS_ARB:
+ *value = 0;
+ return 0;
+ case GLX_SAMPLES_ARB:
+ *value = 0;
+ return 0;
+
+ /*
+ * For FBConfigs:
+ */
+ case GLX_SCREEN_EXT:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = xmvis->visinfo->screen;
+ break;
+ case GLX_DRAWABLE_TYPE: /*SGIX too */
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
+ break;
+ case GLX_RENDER_TYPE_SGIX:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ if (xmvis->mesa_visual.rgbMode)
+ *value = GLX_RGBA_BIT;
+ else
+ *value = GLX_COLOR_INDEX_BIT;
+ break;
+ case GLX_X_RENDERABLE_SGIX:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = True; /* XXX really? */
+ break;
+ case GLX_FBCONFIG_ID_SGIX:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = xmvis->visinfo->visualid;
+ break;
+ case GLX_MAX_PBUFFER_WIDTH:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ /* XXX or MAX_WIDTH? */
+ *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);
+ break;
+ case GLX_MAX_PBUFFER_HEIGHT:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen);
+ break;
+ case GLX_MAX_PBUFFER_PIXELS:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) *
+ DisplayHeight(xmvis->display, xmvis->visinfo->screen);
+ break;
+ case GLX_VISUAL_ID:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = xmvis->visinfo->visualid;
+ break;
+
+#ifdef GLX_EXT_texture_from_pixmap
+ case GLX_BIND_TO_TEXTURE_RGB_EXT:
+ *value = True; /*XXX*/
+ break;
+ case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+ /* XXX review */
+ *value = xmvis->mesa_visual.alphaBits > 0 ? True : False;
+ break;
+ case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+ *value = True; /*XXX*/
+ break;
+ case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+ *value = (GLX_TEXTURE_1D_BIT_EXT |
+ GLX_TEXTURE_2D_BIT_EXT |
+ GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/
+ break;
+ case GLX_Y_INVERTED_EXT:
+ *value = True; /*XXX*/
+ break;
+#endif
+
+ default:
+ return GLX_BAD_ATTRIBUTE;
+ }
+ return Success;
+}
+
+
+int
+glXGetConfig( Display *dpy, XVisualInfo *visinfo,
+ int attrib, int *value )
+{
+ XMesaVisual xmvis;
+ int k;
+ if (!dpy || !visinfo)
+ return GLX_BAD_ATTRIBUTE;
+
+ xmvis = find_glx_visual( dpy, visinfo );
+ if (!xmvis) {
+ /* this visual wasn't obtained with glXChooseVisual */
+ xmvis = create_glx_visual( dpy, visinfo );
+ if (!xmvis) {
+ /* this visual can't be used for GL rendering */
+ if (attrib==GLX_USE_GL) {
+ *value = (int) False;
+ return 0;
+ }
+ else {
+ return GLX_BAD_VISUAL;
+ }
+ }
+ }
+
+ k = get_config(xmvis, attrib, value, GL_FALSE);
+ return k;
+}
+
+
+void
+glXWaitGL( void )
+{
+ XMesaContext xmesa = XMesaGetCurrentContext();
+ XMesaFlush( xmesa );
+}
+
+
+
+void
+glXWaitX( void )
+{
+ XMesaContext xmesa = XMesaGetCurrentContext();
+ XMesaFlush( xmesa );
+}
+
+
+static const char *
+get_extensions( void )
+{
+ return EXTENSIONS;
+}
+
+
+
+/* GLX 1.1 and later */
+const char *
+glXQueryExtensionsString( Display *dpy, int screen )
+{
+ (void) dpy;
+ (void) screen;
+ return get_extensions();
+}
+
+
+
+/* GLX 1.1 and later */
+const char *
+glXQueryServerString( Display *dpy, int screen, int name )
+{
+ static char version[1000];
+ _mesa_sprintf(version, "%d.%d %s",
+ SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION);
+
+ (void) dpy;
+ (void) screen;
+
+ switch (name) {
+ case GLX_EXTENSIONS:
+ return get_extensions();
+ case GLX_VENDOR:
+ return VENDOR;
+ case GLX_VERSION:
+ return version;
+ default:
+ return NULL;
+ }
+}
+
+
+
+/* GLX 1.1 and later */
+const char *
+glXGetClientString( Display *dpy, int name )
+{
+ static char version[1000];
+ _mesa_sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION,
+ CLIENT_MINOR_VERSION, MESA_GLX_VERSION);
+
+ (void) dpy;
+
+ switch (name) {
+ case GLX_EXTENSIONS:
+ return get_extensions();
+ case GLX_VENDOR:
+ return VENDOR;
+ case GLX_VERSION:
+ return version;
+ default:
+ return NULL;
+ }
+}
+
+
+
+/*
+ * GLX 1.3 and later
+ */
+
+
+int
+glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
+ int attribute, int *value )
+{
+ XMesaVisual v = (XMesaVisual) config;
+ (void) dpy;
+ (void) config;
+
+ if (!dpy || !config || !value)
+ return -1;
+
+ return get_config(v, attribute, value, GL_TRUE);
+}
+
+
+GLXFBConfig *
+glXGetFBConfigs( Display *dpy, int screen, int *nelements )
+{
+ XVisualInfo *visuals, visTemplate;
+ const long visMask = VisualScreenMask;
+ int i;
+
+ /* Get list of all X visuals */
+ visTemplate.screen = screen;
+ visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);
+ if (*nelements > 0) {
+ XMesaVisual *results;
+ results = (XMesaVisual *) _mesa_malloc(*nelements * sizeof(XMesaVisual));
+ if (!results) {
+ *nelements = 0;
+ return NULL;
+ }
+ for (i = 0; i < *nelements; i++) {
+ results[i] = create_glx_visual(dpy, visuals + i);
+ }
+ return (GLXFBConfig *) results;
+ }
+ return NULL;
+}
+
+
+GLXFBConfig *
+glXChooseFBConfig( Display *dpy, int screen,
+ const int *attribList, int *nitems )
+{
+ XMesaVisual xmvis;
+
+ if (!attribList || !attribList[0]) {
+ /* return list of all configs (per GLX_SGIX_fbconfig spec) */
+ return glXGetFBConfigs(dpy, screen, nitems);
+ }
+
+ xmvis = choose_visual(dpy, screen, attribList, GL_TRUE);
+ if (xmvis) {
+ GLXFBConfig *config = (GLXFBConfig *) _mesa_malloc(sizeof(XMesaVisual));
+ if (!config) {
+ *nitems = 0;
+ return NULL;
+ }
+ *nitems = 1;
+ config[0] = (GLXFBConfig) xmvis;
+ return (GLXFBConfig *) config;
+ }
+ else {
+ *nitems = 0;
+ return NULL;
+ }
+}
+
+
+XVisualInfo *
+glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
+{
+ if (dpy && config) {
+ XMesaVisual xmvis = (XMesaVisual) config;
+#if 0
+ return xmvis->vishandle;
+#else
+ /* create a new vishandle - the cached one may be stale */
+ xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo));
+ if (xmvis->vishandle) {
+ _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
+ }
+ return xmvis->vishandle;
+#endif
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+GLXWindow
+glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
+ const int *attribList )
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ XMesaBuffer xmbuf;
+ if (!xmvis)
+ return 0;
+
+ xmbuf = XMesaCreateWindowBuffer(xmvis, win);
+ if (!xmbuf)
+ return 0;
+
+ (void) dpy;
+ (void) attribList; /* Ignored in GLX 1.3 */
+
+ return win; /* A hack for now */
+}
+
+
+void
+glXDestroyWindow( Display *dpy, GLXWindow window )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window);
+ if (b)
+ XMesaDestroyBuffer(b);
+ /* don't destroy X window */
+}
+
+
+/* XXX untested */
+GLXPixmap
+glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
+ const int *attribList )
+{
+ XMesaVisual v = (XMesaVisual) config;
+ XMesaBuffer b;
+ const int *attr;
+ int target = 0, format = 0, mipmap = 0;
+ int value;
+
+ if (!dpy || !config || !pixmap)
+ return 0;
+
+ for (attr = attribList; attr && *attr; attr++) {
+ switch (*attr) {
+ case GLX_TEXTURE_FORMAT_EXT:
+ attr++;
+ switch (*attr) {
+ case GLX_TEXTURE_FORMAT_NONE_EXT:
+ case GLX_TEXTURE_FORMAT_RGB_EXT:
+ case GLX_TEXTURE_FORMAT_RGBA_EXT:
+ format = *attr;
+ break;
+ default:
+ /* error */
+ return 0;
+ }
+ break;
+ case GLX_TEXTURE_TARGET_EXT:
+ attr++;
+ switch (*attr) {
+ case GLX_TEXTURE_1D_EXT:
+ case GLX_TEXTURE_2D_EXT:
+ case GLX_TEXTURE_RECTANGLE_EXT:
+ target = *attr;
+ break;
+ default:
+ /* error */
+ return 0;
+ }
+ break;
+ case GLX_MIPMAP_TEXTURE_EXT:
+ attr++;
+ if (*attr)
+ mipmap = 1;
+ break;
+ default:
+ /* error */
+ return 0;
+ }
+ }
+
+ if (format == GLX_TEXTURE_FORMAT_RGB_EXT) {
+ if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT,
+ &value, GL_TRUE) != Success
+ || !value) {
+ return 0; /* error! */
+ }
+ }
+ else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) {
+ if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT,
+ &value, GL_TRUE) != Success
+ || !value) {
+ return 0; /* error! */
+ }
+ }
+ if (mipmap) {
+ if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
+ &value, GL_TRUE) != Success
+ || !value) {
+ return 0; /* error! */
+ }
+ }
+ if (target == GLX_TEXTURE_1D_EXT) {
+ if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+ &value, GL_TRUE) != Success
+ || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) {
+ return 0; /* error! */
+ }
+ }
+ else if (target == GLX_TEXTURE_2D_EXT) {
+ if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+ &value, GL_TRUE) != Success
+ || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) {
+ return 0; /* error! */
+ }
+ }
+ if (target == GLX_TEXTURE_RECTANGLE_EXT) {
+ if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+ &value, GL_TRUE) != Success
+ || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) {
+ return 0; /* error! */
+ }
+ }
+
+ if (format || target || mipmap) {
+ /* texture from pixmap */
+ b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap);
+ }
+ else {
+ b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+ }
+ if (!b) {
+ return 0;
+ }
+
+ return pixmap;
+}
+
+
+void
+glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap);
+ if (b)
+ XMesaDestroyBuffer(b);
+ /* don't destroy X pixmap */
+}
+
+
+GLXPbuffer
+glXCreatePbuffer( Display *dpy, GLXFBConfig config,
+ const int *attribList )
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ XMesaBuffer xmbuf;
+ const int *attrib;
+ int width = 0, height = 0;
+ GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
+
+ (void) dpy;
+
+ for (attrib = attribList; *attrib; attrib++) {
+ switch (*attrib) {
+ case GLX_PBUFFER_WIDTH:
+ attrib++;
+ width = *attrib;
+ break;
+ case GLX_PBUFFER_HEIGHT:
+ attrib++;
+ height = *attrib;
+ break;
+ case GLX_PRESERVED_CONTENTS:
+ attrib++;
+ preserveContents = *attrib; /* ignored */
+ break;
+ case GLX_LARGEST_PBUFFER:
+ attrib++;
+ useLargest = *attrib; /* ignored */
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ /* not used at this time */
+ (void) useLargest;
+ (void) preserveContents;
+
+ if (width == 0 || height == 0)
+ return 0;
+
+ xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
+ /* A GLXPbuffer handle must be an X Drawable because that's what
+ * glXMakeCurrent takes.
+ */
+ if (xmbuf)
+ return (GLXPbuffer) xmbuf->drawable;
+ else
+ return 0;
+}
+
+
+void
+glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
+ if (b) {
+ XMesaDestroyBuffer(b);
+ }
+}
+
+
+void
+glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
+ unsigned int *value )
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw);
+ if (!xmbuf)
+ return;
+
+ switch (attribute) {
+ case GLX_WIDTH:
+ *value = xmesa_buffer_width(xmbuf);
+ break;
+ case GLX_HEIGHT:
+ *value = xmesa_buffer_width(xmbuf);
+ break;
+ case GLX_PRESERVED_CONTENTS:
+ *value = True;
+ break;
+ case GLX_LARGEST_PBUFFER:
+ *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf);
+ break;
+ case GLX_FBCONFIG_ID:
+ *value = xmbuf->xm_visual->visinfo->visualid;
+ return;
+#ifdef GLX_EXT_texture_from_pixmap
+ case GLX_TEXTURE_FORMAT_EXT:
+ *value = xmbuf->TextureFormat;
+ break;
+ case GLX_TEXTURE_TARGET_EXT:
+ *value = xmbuf->TextureTarget;
+ break;
+ case GLX_MIPMAP_TEXTURE_EXT:
+ *value = xmbuf->TextureMipmap;
+ break;
+#endif
+
+ default:
+ return; /* raise BadValue error */
+ }
+}
+
+
+GLXContext
+glXCreateNewContext( Display *dpy, GLXFBConfig config,
+ int renderType, GLXContext shareList, Bool direct )
+{
+ GLXContext glxCtx;
+ GLXContext shareCtx = shareList;
+ XMesaVisual xmvis = (XMesaVisual) config;
+
+ if (!dpy || !config ||
+ (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
+ return 0;
+
+ glxCtx = CALLOC_STRUCT(__GLXcontextRec);
+ if (!glxCtx)
+ return 0;
+
+ /* deallocate unused windows/buffers */
+ XMesaGarbageCollect();
+
+ glxCtx->xmesaContext = XMesaCreateContext(xmvis,
+ shareCtx ? shareCtx->xmesaContext : NULL);
+ if (!glxCtx->xmesaContext) {
+ _mesa_free(glxCtx);
+ return NULL;
+ }
+
+ glxCtx->isDirect = DEFAULT_DIRECT;
+ glxCtx->currentDpy = dpy;
+ glxCtx->xid = (XID) glxCtx; /* self pointer */
+
+ return glxCtx;
+}
+
+
+int
+glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
+{
+ GLXContext glxCtx = ctx;
+ XMesaContext xmctx = glxCtx->xmesaContext;
+
+ (void) dpy;
+ (void) ctx;
+
+ switch (attribute) {
+ case GLX_FBCONFIG_ID:
+ *value = xmctx->xm_visual->visinfo->visualid;
+ break;
+ case GLX_RENDER_TYPE:
+ if (xmctx->xm_visual->mesa_visual.rgbMode)
+ *value = GLX_RGBA_BIT;
+ else
+ *value = GLX_COLOR_INDEX_BIT;
+ break;
+ case GLX_SCREEN:
+ *value = 0;
+ return Success;
+ default:
+ return GLX_BAD_ATTRIBUTE;
+ }
+ return 0;
+}
+
+
+void
+glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+ if (xmbuf)
+ xmbuf->selectedEvents = mask;
+}
+
+
+void
+glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
+ unsigned long *mask )
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+ if (xmbuf)
+ *mask = xmbuf->selectedEvents;
+ else
+ *mask = 0;
+}
+
+
+
+/*** GLX_SGI_swap_control ***/
+
+int
+glXSwapIntervalSGI(int interval)
+{
+ (void) interval;
+ return 0;
+}
+
+
+
+/*** GLX_SGI_video_sync ***/
+
+static unsigned int FrameCounter = 0;
+
+int
+glXGetVideoSyncSGI(unsigned int *count)
+{
+ /* this is a bogus implementation */
+ *count = FrameCounter++;
+ return 0;
+}
+
+int
+glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
+{
+ if (divisor <= 0 || remainder < 0)
+ return GLX_BAD_VALUE;
+ /* this is a bogus implementation */
+ FrameCounter++;
+ while (FrameCounter % divisor != remainder)
+ FrameCounter++;
+ *count = FrameCounter;
+ return 0;
+}
+
+
+
+/*** GLX_SGI_make_current_read ***/
+
+Bool
+glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
+{
+ return glXMakeContextCurrent( dpy, draw, read, ctx );
+}
+
+/* not used
+static GLXDrawable
+glXGetCurrentReadDrawableSGI(void)
+{
+ return 0;
+}
+*/
+
+
+/*** GLX_SGIX_video_source ***/
+#if defined(_VL_H)
+
+GLXVideoSourceSGIX
+glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode)
+{
+ (void) dpy;
+ (void) screen;
+ (void) server;
+ (void) path;
+ (void) nodeClass;
+ (void) drainNode;
+ return 0;
+}
+
+void
+glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
+{
+ (void) dpy;
+ (void) src;
+}
+
+#endif
+
+
+/*** GLX_EXT_import_context ***/
+
+void
+glXFreeContextEXT(Display *dpy, GLXContext context)
+{
+ (void) dpy;
+ (void) context;
+}
+
+GLXContextID
+glXGetContextIDEXT(const GLXContext context)
+{
+ (void) context;
+ return 0;
+}
+
+GLXContext
+glXImportContextEXT(Display *dpy, GLXContextID contextID)
+{
+ (void) dpy;
+ (void) contextID;
+ return 0;
+}
+
+int
+glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value)
+{
+ (void) dpy;
+ (void) context;
+ (void) attribute;
+ (void) value;
+ return 0;
+}
+
+
+
+/*** GLX_SGIX_fbconfig ***/
+
+int
+glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value)
+{
+ return glXGetFBConfigAttrib(dpy, config, attribute, value);
+}
+
+GLXFBConfigSGIX *
+glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements)
+{
+ return (GLXFBConfig *) glXChooseFBConfig(dpy, screen, attrib_list, nelements);
+}
+
+
+GLXPixmap
+glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap)
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
+ return xmbuf->drawable; /* need to return an X ID */
+}
+
+
+GLXContext
+glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct)
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ GLXContext glxCtx;
+ GLXContext shareCtx = share_list;
+
+ glxCtx = CALLOC_STRUCT(__GLXcontextRec);
+ if (!glxCtx)
+ return 0;
+
+ /* deallocate unused windows/buffers */
+ XMesaGarbageCollect();
+
+ glxCtx->xmesaContext = XMesaCreateContext(xmvis,
+ shareCtx ? shareCtx->xmesaContext : NULL);
+ if (!glxCtx->xmesaContext) {
+ _mesa_free(glxCtx);
+ return NULL;
+ }
+
+ glxCtx->isDirect = DEFAULT_DIRECT;
+ glxCtx->currentDpy = dpy;
+ glxCtx->xid = (XID) glxCtx; /* self pointer */
+
+ return glxCtx;
+}
+
+
+XVisualInfo *
+glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
+{
+ return glXGetVisualFromFBConfig(dpy, config);
+}
+
+
+GLXFBConfigSGIX
+glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
+{
+ XMesaVisual xmvis = find_glx_visual(dpy, vis);
+ if (!xmvis) {
+ /* This visual wasn't found with glXChooseVisual() */
+ xmvis = create_glx_visual(dpy, vis);
+ }
+
+ return (GLXFBConfigSGIX) xmvis;
+}
+
+
+
+/*** GLX_SGIX_pbuffer ***/
+
+GLXPbufferSGIX
+glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
+ unsigned int width, unsigned int height,
+ int *attribList)
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ XMesaBuffer xmbuf;
+ const int *attrib;
+ GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
+
+ (void) dpy;
+
+ for (attrib = attribList; attrib && *attrib; attrib++) {
+ switch (*attrib) {
+ case GLX_PRESERVED_CONTENTS_SGIX:
+ attrib++;
+ preserveContents = *attrib; /* ignored */
+ break;
+ case GLX_LARGEST_PBUFFER_SGIX:
+ attrib++;
+ useLargest = *attrib; /* ignored */
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ /* not used at this time */
+ (void) useLargest;
+ (void) preserveContents;
+
+ xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
+ /* A GLXPbuffer handle must be an X Drawable because that's what
+ * glXMakeCurrent takes.
+ */
+ return (GLXPbuffer) xmbuf->drawable;
+}
+
+
+void
+glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
+ if (xmbuf) {
+ XMesaDestroyBuffer(xmbuf);
+ }
+}
+
+
+int
+glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value)
+{
+ const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
+
+ if (!xmbuf) {
+ /* Generate GLXBadPbufferSGIX for bad pbuffer */
+ return 0;
+ }
+
+ switch (attribute) {
+ case GLX_PRESERVED_CONTENTS_SGIX:
+ *value = True;
+ break;
+ case GLX_LARGEST_PBUFFER_SGIX:
+ *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf);
+ break;
+ case GLX_WIDTH_SGIX:
+ *value = xmesa_buffer_width(xmbuf);
+ break;
+ case GLX_HEIGHT_SGIX:
+ *value = xmesa_buffer_height(xmbuf);
+ break;
+ case GLX_EVENT_MASK_SGIX:
+ *value = 0; /* XXX might be wrong */
+ break;
+ default:
+ *value = 0;
+ }
+ return 0;
+}
+
+
+void
+glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+ if (xmbuf) {
+ /* Note: we'll never generate clobber events */
+ xmbuf->selectedEvents = mask;
+ }
+}
+
+
+void
+glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask)
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+ if (xmbuf) {
+ *mask = xmbuf->selectedEvents;
+ }
+ else {
+ *mask = 0;
+ }
+}
+
+
+
+/*** GLX_SGI_cushion ***/
+
+void
+glXCushionSGI(Display *dpy, Window win, float cushion)
+{
+ (void) dpy;
+ (void) win;
+ (void) cushion;
+}
+
+
+
+/*** GLX_SGIX_video_resize ***/
+
+int
+glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) window;
+ return 0;
+}
+
+int
+glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) x;
+ (void) y;
+ (void) w;
+ (void) h;
+ return 0;
+}
+
+int
+glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) x;
+ (void) y;
+ (void) w;
+ (void) h;
+ return 0;
+}
+
+int
+glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) dx;
+ (void) dy;
+ (void) dw;
+ (void) dh;
+ return 0;
+}
+
+int
+glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) synctype;
+ return 0;
+}
+
+
+
+/*** GLX_SGIX_dmbuffer **/
+
+#if defined(_DM_BUFFER_H_)
+Bool
+glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer)
+{
+ (void) dpy;
+ (void) pbuffer;
+ (void) params;
+ (void) dmbuffer;
+ return False;
+}
+#endif
+
+
+/*** GLX_SGIX_swap_group ***/
+
+void
+glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
+{
+ (void) dpy;
+ (void) drawable;
+ (void) member;
+}
+
+
+
+/*** GLX_SGIX_swap_barrier ***/
+
+void
+glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
+{
+ (void) dpy;
+ (void) drawable;
+ (void) barrier;
+}
+
+Bool
+glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
+{
+ (void) dpy;
+ (void) screen;
+ (void) max;
+ return False;
+}
+
+
+
+/*** GLX_SUN_get_transparent_index ***/
+
+Status
+glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent)
+{
+ (void) dpy;
+ (void) overlay;
+ (void) underlay;
+ (void) pTransparent;
+ return 0;
+}
+
+
+
+/*** GLX_MESA_release_buffers ***/
+
+/*
+ * Release the depth, stencil, accum buffers attached to a GLXDrawable
+ * (a window or pixmap) prior to destroying the GLXDrawable.
+ */
+Bool
+glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, d);
+ if (b) {
+ XMesaDestroyBuffer(b);
+ return True;
+ }
+ return False;
+}
+
+/*** GLX_EXT_texture_from_pixmap ***/
+
+void
+glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
+ const int *attrib_list)
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
+ if (b)
+ XMesaBindTexImage(dpy, b, buffer, attrib_list);
+}
+
+void
+glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
+ if (b)
+ XMesaReleaseTexImage(dpy, b, buffer);
+}
diff --git a/src/gallium/state_trackers/glx/xlib/glx_getproc.c b/src/gallium/state_trackers/glx/xlib/glx_getproc.c
new file mode 100644
index 0000000000..ca7d88c922
--- /dev/null
+++ b/src/gallium/state_trackers/glx/xlib/glx_getproc.c
@@ -0,0 +1,214 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * glXGetProcAddress()
+ */
+
+
+#define GLX_GLXEXT_PROTOTYPES
+
+#include <string.h>
+#include "GL/glx.h"
+#include "glapi/glapi.h"
+
+
+struct name_address_pair {
+ const char *Name;
+ __GLXextFuncPtr Address;
+};
+
+
+static struct name_address_pair GLX_functions[] = {
+ /*** GLX_VERSION_1_0 ***/
+ { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual },
+ { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext },
+ { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext },
+ { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap },
+ { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext },
+ { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap },
+ { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig },
+ { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext },
+ { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable },
+ { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect },
+ { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent },
+ { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension },
+ { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion },
+ { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers },
+ { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont },
+ { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL },
+ { "glXWaitX", (__GLXextFuncPtr) glXWaitX },
+
+ /*** GLX_VERSION_1_1 ***/
+ { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString },
+ { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString },
+ { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString },
+
+ /*** GLX_VERSION_1_2 ***/
+ { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay },
+
+ /*** GLX_VERSION_1_3 ***/
+ { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig },
+ { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext },
+ { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer },
+ { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap },
+ { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow },
+ { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer },
+ { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap },
+ { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow },
+ { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable },
+ { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib },
+ { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs },
+ { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent },
+ { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig },
+ { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent },
+ { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext },
+ { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable },
+ { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent },
+
+ /*** GLX_VERSION_1_4 ***/
+ { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress },
+
+ /*** GLX_SGI_swap_control ***/
+ { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI },
+
+ /*** GLX_SGI_video_sync ***/
+ { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI },
+ { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI },
+
+ /*** GLX_SGI_make_current_read ***/
+ { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI },
+ { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI },
+
+ /*** GLX_SGIX_video_source ***/
+#if defined(_VL_H)
+ { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX },
+ { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX },
+#endif
+
+ /*** GLX_EXT_import_context ***/
+ { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT },
+ { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT },
+ { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT },
+ { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT },
+ { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT },
+
+ /*** GLX_SGIX_fbconfig ***/
+ { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX },
+ { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX },
+ { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX },
+ { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX },
+ { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX },
+ { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX },
+
+ /*** GLX_SGIX_pbuffer ***/
+ { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX },
+ { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX },
+ { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX },
+ { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX },
+ { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX },
+
+ /*** GLX_SGI_cushion ***/
+ { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI },
+
+ /*** GLX_SGIX_video_resize ***/
+ { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX },
+ { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX },
+ { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX },
+ { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX },
+ { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX },
+
+ /*** GLX_SGIX_dmbuffer **/
+#if defined(_DM_BUFFER_H_)
+ { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX },
+#endif
+
+ /*** GLX_SGIX_swap_group ***/
+ { "glXJoinSwapGroupSGIX", (__GLXextFuncPtr) glXJoinSwapGroupSGIX },
+
+ /*** GLX_SGIX_swap_barrier ***/
+ { "glXBindSwapBarrierSGIX", (__GLXextFuncPtr) glXBindSwapBarrierSGIX },
+ { "glXQueryMaxSwapBarriersSGIX", (__GLXextFuncPtr) glXQueryMaxSwapBarriersSGIX },
+
+ /*** GLX_SUN_get_transparent_index ***/
+ { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN },
+
+ /*** GLX_MESA_copy_sub_buffer ***/
+ { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA },
+
+ /*** GLX_MESA_pixmap_colormap ***/
+ { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA },
+
+ /*** GLX_MESA_release_buffers ***/
+ { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA },
+
+ /*** GLX_ARB_get_proc_address ***/
+ { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB },
+
+ /*** GLX_EXT_texture_from_pixmap ***/
+ { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT },
+ { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT },
+
+ { NULL, NULL } /* end of list */
+};
+
+
+
+/**
+ * Return address of named glX function, or NULL if not found.
+ */
+static __GLXextFuncPtr
+_glxapi_get_proc_address(const char *funcName)
+{
+ GLuint i;
+ for (i = 0; GLX_functions[i].Name; i++) {
+ if (strcmp(GLX_functions[i].Name, funcName) == 0)
+ return GLX_functions[i].Address;
+ }
+ return NULL;
+}
+
+
+__GLXextFuncPtr
+glXGetProcAddressARB(const GLubyte *procName)
+{
+ __GLXextFuncPtr f;
+
+ f = _glxapi_get_proc_address((const char *) procName);
+ if (f) {
+ return f;
+ }
+
+ f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName);
+ return f;
+}
+
+
+/* GLX 1.4 */
+void (*glXGetProcAddress(const GLubyte *procName))()
+{
+ return glXGetProcAddressARB(procName);
+}
diff --git a/src/gallium/state_trackers/glx/xlib/glx_usefont.c b/src/gallium/state_trackers/glx/xlib/glx_usefont.c
new file mode 100644
index 0000000000..acc64df62b
--- /dev/null
+++ b/src/gallium/state_trackers/glx/xlib/glx_usefont.c
@@ -0,0 +1,375 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Fake implementation of glXUseXFont().
+ */
+
+
+#include "main/context.h"
+#include "main/imports.h"
+#include <GL/glx.h>
+
+
+/* Some debugging info. */
+
+#ifdef DEBUG
+#undef _R
+#undef _G
+#undef _B
+#include <ctype.h>
+
+int debug_xfonts = 0;
+
+static void
+dump_char_struct(XCharStruct * ch, char *prefix)
+{
+ printf("%slbearing = %d, rbearing = %d, width = %d\n",
+ prefix, ch->lbearing, ch->rbearing, ch->width);
+ printf("%sascent = %d, descent = %d, attributes = %u\n",
+ prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes);
+}
+
+static void
+dump_font_struct(XFontStruct * font)
+{
+ printf("ascent = %d, descent = %d\n", font->ascent, font->descent);
+ printf("char_or_byte2 = (%u,%u)\n",
+ font->min_char_or_byte2, font->max_char_or_byte2);
+ printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1);
+ printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False");
+ printf("default_char = %c (\\%03o)\n",
+ (char) (isprint(font->default_char) ? font->default_char : ' '),
+ font->default_char);
+ dump_char_struct(&font->min_bounds, "min> ");
+ dump_char_struct(&font->max_bounds, "max> ");
+#if 0
+ for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) {
+ char prefix[8];
+ sprintf(prefix, "%d> ", c);
+ dump_char_struct(&font->per_char[c], prefix);
+ }
+#endif
+}
+
+static void
+dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap)
+{
+ unsigned int x, y;
+
+ printf(" ");
+ for (x = 0; x < 8 * width; x++)
+ printf("%o", 7 - (x % 8));
+ putchar('\n');
+ for (y = 0; y < height; y++) {
+ printf("%3o:", y);
+ for (x = 0; x < 8 * width; x++)
+ putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x %
+ 8))))
+ ? '*' : '.');
+ printf(" ");
+ for (x = 0; x < width; x++)
+ printf("0x%02x, ", bitmap[width * (height - y - 1) + x]);
+ putchar('\n');
+ }
+}
+#endif /* DEBUG */
+
+
+/* Implementation. */
+
+/* Fill a BITMAP with a character C from thew current font
+ in the graphics context GC. WIDTH is the width in bytes
+ and HEIGHT is the height in bits.
+
+ Note that the generated bitmaps must be used with
+
+ glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
+ glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+
+ Possible optimizations:
+
+ * use only one reusable pixmap with the maximum dimensions.
+ * draw the entire font into a single pixmap (careful with
+ proportional fonts!).
+*/
+
+
+/*
+ * Generate OpenGL-compatible bitmap.
+ */
+static void
+fill_bitmap(Display * dpy, Window win, GC gc,
+ unsigned int width, unsigned int height,
+ int x0, int y0, unsigned int c, GLubyte * bitmap)
+{
+ XImage *image;
+ unsigned int x, y;
+ Pixmap pixmap;
+ XChar2b char2b;
+
+ pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1);
+ XSetForeground(dpy, gc, 0);
+ XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height);
+ XSetForeground(dpy, gc, 1);
+
+ char2b.byte1 = (c >> 8) & 0xff;
+ char2b.byte2 = (c & 0xff);
+
+ XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);
+
+ image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap);
+ if (image) {
+ /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */
+ for (y = 0; y < height; y++)
+ for (x = 0; x < 8 * width; x++)
+ if (XGetPixel(image, x, y))
+ bitmap[width * (height - y - 1) + x / 8] |=
+ (1 << (7 - (x % 8)));
+ XDestroyImage(image);
+ }
+
+ XFreePixmap(dpy, pixmap);
+}
+
+/*
+ * determine if a given glyph is valid and return the
+ * corresponding XCharStruct.
+ */
+static XCharStruct *
+isvalid(XFontStruct * fs, unsigned int which)
+{
+ unsigned int rows, pages;
+ unsigned int byte1 = 0, byte2 = 0;
+ int i, valid = 1;
+
+ rows = fs->max_byte1 - fs->min_byte1 + 1;
+ pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
+
+ if (rows == 1) {
+ /* "linear" fonts */
+ if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))
+ valid = 0;
+ }
+ else {
+ /* "matrix" fonts */
+ byte2 = which & 0xff;
+ byte1 = which >> 8;
+ if ((fs->min_char_or_byte2 > byte2) ||
+ (fs->max_char_or_byte2 < byte2) ||
+ (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))
+ valid = 0;
+ }
+
+ if (valid) {
+ if (fs->per_char) {
+ if (rows == 1) {
+ /* "linear" fonts */
+ return (fs->per_char + (which - fs->min_char_or_byte2));
+ }
+ else {
+ /* "matrix" fonts */
+ i = ((byte1 - fs->min_byte1) * pages) +
+ (byte2 - fs->min_char_or_byte2);
+ return (fs->per_char + i);
+ }
+ }
+ else {
+ return (&fs->min_bounds);
+ }
+ }
+ return (NULL);
+}
+
+
+void
+glXUseXFont(Font font, int first, int count, int listbase)
+{
+ Display *dpy;
+ Window win;
+ Pixmap pixmap;
+ GC gc;
+ XGCValues values;
+ unsigned long valuemask;
+ XFontStruct *fs;
+ GLint swapbytes, lsbfirst, rowlength;
+ GLint skiprows, skippixels, alignment;
+ unsigned int max_width, max_height, max_bm_width, max_bm_height;
+ GLubyte *bm;
+ int i;
+
+ dpy = glXGetCurrentDisplay();
+ if (!dpy)
+ return; /* I guess glXMakeCurrent wasn't called */
+ i = DefaultScreen(dpy);
+ win = RootWindow(dpy, i);
+
+ fs = XQueryFont(dpy, font);
+ if (!fs) {
+ _mesa_error(NULL, GL_INVALID_VALUE,
+ "Couldn't get font structure information");
+ return;
+ }
+
+ /* Allocate a bitmap that can fit all characters. */
+ max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
+ max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
+ max_bm_width = (max_width + 7) / 8;
+ max_bm_height = max_height;
+
+ bm = (GLubyte *) MALLOC((max_bm_width * max_bm_height) * sizeof(GLubyte));
+ if (!bm) {
+ XFreeFontInfo(NULL, fs, 1);
+ _mesa_error(NULL, GL_OUT_OF_MEMORY,
+ "Couldn't allocate bitmap in glXUseXFont()");
+ return;
+ }
+
+#if 0
+ /* get the page info */
+ pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
+ firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
+ lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
+ rows = fs->max_byte1 - fs->min_byte1 + 1;
+ unsigned int first_char, last_char, pages, rows;
+#endif
+
+ /* Save the current packing mode for bitmaps. */
+ glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
+ glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
+ glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
+ glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
+
+ /* Enforce a standard packing mode which is compatible with
+ fill_bitmap() from above. This is actually the default mode,
+ except for the (non)alignment. */
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
+ glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ pixmap = XCreatePixmap(dpy, win, 10, 10, 1);
+ values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
+ values.background = WhitePixel(dpy, DefaultScreen(dpy));
+ values.font = fs->fid;
+ valuemask = GCForeground | GCBackground | GCFont;
+ gc = XCreateGC(dpy, pixmap, valuemask, &values);
+ XFreePixmap(dpy, pixmap);
+
+#ifdef DEBUG
+ if (debug_xfonts)
+ dump_font_struct(fs);
+#endif
+
+ for (i = 0; i < count; i++) {
+ unsigned int width, height, bm_width, bm_height;
+ GLfloat x0, y0, dx, dy;
+ XCharStruct *ch;
+ int x, y;
+ unsigned int c = first + i;
+ int list = listbase + i;
+ int valid;
+
+ /* check on index validity and get the bounds */
+ ch = isvalid(fs, c);
+ if (!ch) {
+ ch = &fs->max_bounds;
+ valid = 0;
+ }
+ else {
+ valid = 1;
+ }
+
+#ifdef DEBUG
+ if (debug_xfonts) {
+ char s[7];
+ sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
+ dump_char_struct(ch, s);
+ }
+#endif
+
+ /* glBitmap()' parameters:
+ straight from the glXUseXFont(3) manpage. */
+ width = ch->rbearing - ch->lbearing;
+ height = ch->ascent + ch->descent;
+ x0 = -ch->lbearing;
+ y0 = ch->descent - 0; /* XXX used to subtract 1 here */
+ /* but that caused a conformace failure */
+ dx = ch->width;
+ dy = 0;
+
+ /* X11's starting point. */
+ x = -ch->lbearing;
+ y = ch->ascent;
+
+ /* Round the width to a multiple of eight. We will use this also
+ for the pixmap for capturing the X11 font. This is slightly
+ inefficient, but it makes the OpenGL part real easy. */
+ bm_width = (width + 7) / 8;
+ bm_height = height;
+
+ glNewList(list, GL_COMPILE);
+ if (valid && (bm_width > 0) && (bm_height > 0)) {
+
+ MEMSET(bm, '\0', bm_width * bm_height);
+ fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);
+
+ glBitmap(width, height, x0, y0, dx, dy, bm);
+#ifdef DEBUG
+ if (debug_xfonts) {
+ printf("width/height = %u/%u\n", width, height);
+ printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height);
+ dump_bitmap(bm_width, bm_height, bm);
+ }
+#endif
+ }
+ else {
+ glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);
+ }
+ glEndList();
+ }
+
+ FREE(bm);
+ XFreeFontInfo(NULL, fs, 1);
+ XFreeGC(dpy, gc);
+
+ /* Restore saved packing modes. */
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
+ glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+}
diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c
new file mode 100644
index 0000000000..957002ddd5
--- /dev/null
+++ b/src/gallium/state_trackers/glx/xlib/xm_api.c
@@ -0,0 +1,1220 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file xm_api.c
+ *
+ * All the XMesa* API functions.
+ *
+ *
+ * NOTES:
+ *
+ * The window coordinate system origin (0,0) is in the lower-left corner
+ * of the window. X11's window coordinate origin is in the upper-left
+ * corner of the window. Therefore, most drawing functions in this
+ * file have to flip Y coordinates.
+ *
+ * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
+ * in support for the MIT Shared Memory extension. If enabled, when you
+ * use an Ximage for the back buffer in double buffered mode, the "swap"
+ * operation will be faster. You must also link with -lXext.
+ *
+ * Byte swapping: If the Mesa host and the X display use a different
+ * byte order then there's some trickiness to be aware of when using
+ * XImages. The byte ordering used for the XImage is that of the X
+ * display, not the Mesa host.
+ * The color-to-pixel encoding for True/DirectColor must be done
+ * according to the display's visual red_mask, green_mask, and blue_mask.
+ * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
+ * do byte swapping if needed. If one wants to directly "poke" the pixel
+ * into the XImage's buffer then the pixel must be byte swapped first.
+ *
+ */
+
+#ifdef __CYGWIN__
+#undef WIN32
+#undef __WIN32__
+#endif
+
+#include "xm_api.h"
+#include "main/context.h"
+#include "main/framebuffer.h"
+
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+
+#include "xm_winsys.h"
+#include <GL/glx.h>
+
+
+/* Driver interface routines, set up by xlib backend on library
+ * _init(). These are global in the same way that function names are
+ * global.
+ */
+static struct xm_driver driver;
+
+void xmesa_set_driver( const struct xm_driver *templ )
+{
+ driver = *templ;
+}
+
+/**
+ * Global X driver lock
+ */
+pipe_mutex _xmesa_lock;
+
+
+
+/**********************************************************************/
+/***** X Utility Functions *****/
+/**********************************************************************/
+
+
+/**
+ * Return the host's byte order as LSBFirst or MSBFirst ala X.
+ */
+static int host_byte_order( void )
+{
+ int i = 1;
+ char *cptr = (char *) &i;
+ return (*cptr==1) ? LSBFirst : MSBFirst;
+}
+
+
+/**
+ * Check if the X Shared Memory extension is available.
+ * Return: 0 = not available
+ * 1 = shared XImage support available
+ * 2 = shared Pixmap support available also
+ */
+int xmesa_check_for_xshm( Display *display )
+{
+#if defined(USE_XSHM)
+ int major, minor, ignore;
+ Bool pixmaps;
+
+ if (getenv("SP_NO_RAST"))
+ return 0;
+
+ if (getenv("MESA_NOSHM")) {
+ return 0;
+ }
+
+ if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
+ if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
+ return (pixmaps==True) ? 2 : 1;
+ }
+ else {
+ return 0;
+ }
+ }
+ else {
+ return 0;
+ }
+#else
+ /* No XSHM support */
+ return 0;
+#endif
+}
+
+
+/**
+ * Return the true number of bits per pixel for XImages.
+ * For example, if we request a 24-bit deep visual we may actually need/get
+ * 32bpp XImages. This function returns the appropriate bpp.
+ * Input: dpy - the X display
+ * visinfo - desribes the visual to be used for XImages
+ * Return: true number of bits per pixel for XImages
+ */
+static int
+bits_per_pixel( XMesaVisual xmv )
+{
+ Display *dpy = xmv->display;
+ XVisualInfo * visinfo = xmv->visinfo;
+ XImage *img;
+ int bitsPerPixel;
+ /* Create a temporary XImage */
+ img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
+ ZPixmap, 0, /*format, offset*/
+ (char*) MALLOC(8), /*data*/
+ 1, 1, /*width, height*/
+ 32, /*bitmap_pad*/
+ 0 /*bytes_per_line*/
+ );
+ assert(img);
+ /* grab the bits/pixel value */
+ bitsPerPixel = img->bits_per_pixel;
+ /* free the XImage */
+ _mesa_free( img->data );
+ img->data = NULL;
+ XDestroyImage( img );
+ return bitsPerPixel;
+}
+
+
+
+/*
+ * Determine if a given X window ID is valid (window exists).
+ * Do this by calling XGetWindowAttributes() for the window and
+ * checking if we catch an X error.
+ * Input: dpy - the display
+ * win - the window to check for existance
+ * Return: GL_TRUE - window exists
+ * GL_FALSE - window doesn't exist
+ */
+static GLboolean WindowExistsFlag;
+
+static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr )
+{
+ (void) dpy;
+ if (xerr->error_code == BadWindow) {
+ WindowExistsFlag = GL_FALSE;
+ }
+ return 0;
+}
+
+static GLboolean window_exists( Display *dpy, Window win )
+{
+ XWindowAttributes wa;
+ int (*old_handler)( Display*, XErrorEvent* );
+ WindowExistsFlag = GL_TRUE;
+ old_handler = XSetErrorHandler(window_exists_err_handler);
+ XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
+ XSetErrorHandler(old_handler);
+ return WindowExistsFlag;
+}
+
+static Status
+get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height )
+{
+ Window root;
+ Status stat;
+ int xpos, ypos;
+ unsigned int w, h, bw, depth;
+ stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+ *width = w;
+ *height = h;
+ return stat;
+}
+
+
+/**
+ * Return the size of the window (or pixmap) that corresponds to the
+ * given XMesaBuffer.
+ * \param width returns width in pixels
+ * \param height returns height in pixels
+ */
+static void
+xmesa_get_window_size(Display *dpy, XMesaBuffer b,
+ GLuint *width, GLuint *height)
+{
+ Status stat;
+
+ pipe_mutex_lock(_xmesa_lock);
+ XSync(b->xm_visual->display, 0); /* added for Chromium */
+ stat = get_drawable_size(dpy, b->drawable, width, height);
+ pipe_mutex_unlock(_xmesa_lock);
+
+ if (!stat) {
+ /* probably querying a window that's recently been destroyed */
+ _mesa_warning(NULL, "XGetGeometry failed!\n");
+ *width = *height = 1;
+ }
+}
+
+#define GET_REDMASK(__v) __v->mesa_visual.redMask
+#define GET_GREENMASK(__v) __v->mesa_visual.greenMask
+#define GET_BLUEMASK(__v) __v->mesa_visual.blueMask
+
+
+/**
+ * Choose the pixel format for the given visual.
+ * This will tell the gallium driver how to pack pixel data into
+ * drawing surfaces.
+ */
+static GLuint
+choose_pixel_format(XMesaVisual v)
+{
+ boolean native_byte_order = (host_byte_order() ==
+ ImageByteOrder(v->display));
+
+ if ( GET_REDMASK(v) == 0x0000ff
+ && GET_GREENMASK(v) == 0x00ff00
+ && GET_BLUEMASK(v) == 0xff0000
+ && v->BitsPerPixel == 32) {
+ if (native_byte_order) {
+ /* no byteswapping needed */
+ return 0 /* PIXEL_FORMAT_U_A8_B8_G8_R8 */;
+ }
+ else {
+ return PIPE_FORMAT_R8G8B8A8_UNORM;
+ }
+ }
+ else if ( GET_REDMASK(v) == 0xff0000
+ && GET_GREENMASK(v) == 0x00ff00
+ && GET_BLUEMASK(v) == 0x0000ff
+ && v->BitsPerPixel == 32) {
+ if (native_byte_order) {
+ /* no byteswapping needed */
+ return PIPE_FORMAT_A8R8G8B8_UNORM;
+ }
+ else {
+ return PIPE_FORMAT_B8G8R8A8_UNORM;
+ }
+ }
+ else if ( GET_REDMASK(v) == 0x0000ff00
+ && GET_GREENMASK(v) == 0x00ff0000
+ && GET_BLUEMASK(v) == 0xff000000
+ && v->BitsPerPixel == 32) {
+ if (native_byte_order) {
+ /* no byteswapping needed */
+ return PIPE_FORMAT_B8G8R8A8_UNORM;
+ }
+ else {
+ return PIPE_FORMAT_A8R8G8B8_UNORM;
+ }
+ }
+ else if ( GET_REDMASK(v) == 0xf800
+ && GET_GREENMASK(v) == 0x07e0
+ && GET_BLUEMASK(v) == 0x001f
+ && native_byte_order
+ && v->BitsPerPixel == 16) {
+ /* 5-6-5 RGB */
+ return PIPE_FORMAT_R5G6B5_UNORM;
+ }
+
+ assert(0);
+ return 0;
+}
+
+
+
+/**********************************************************************/
+/***** Linked list of XMesaBuffers *****/
+/**********************************************************************/
+
+XMesaBuffer XMesaBufferList = NULL;
+
+
+/**
+ * Allocate a new XMesaBuffer object which corresponds to the given drawable.
+ * Note that XMesaBuffer is derived from GLframebuffer.
+ * The new XMesaBuffer will not have any size (Width=Height=0).
+ *
+ * \param d the corresponding X drawable (window or pixmap)
+ * \param type either WINDOW, PIXMAP or PBUFFER, describing d
+ * \param vis the buffer's visual
+ * \param cmap the window's colormap, if known.
+ * \return new XMesaBuffer or NULL if any problem
+ */
+static XMesaBuffer
+create_xmesa_buffer(Drawable d, BufferType type,
+ XMesaVisual vis, Colormap cmap)
+{
+ XMesaBuffer b;
+ GLframebuffer *fb;
+ enum pipe_format colorFormat, depthFormat, stencilFormat;
+ uint width, height;
+
+ ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
+
+ b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
+ if (!b)
+ return NULL;
+
+ b->drawable = d;
+
+ b->xm_visual = vis;
+ b->type = type;
+ b->cmap = cmap;
+
+ /* determine PIPE_FORMATs for buffers */
+ colorFormat = choose_pixel_format(vis);
+
+ if (vis->mesa_visual.depthBits == 0)
+ depthFormat = PIPE_FORMAT_NONE;
+#ifdef GALLIUM_CELL /* XXX temporary for Cell! */
+ else
+ depthFormat = PIPE_FORMAT_S8Z24_UNORM;
+#else
+ else if (vis->mesa_visual.depthBits <= 16)
+ depthFormat = PIPE_FORMAT_Z16_UNORM;
+ else if (vis->mesa_visual.depthBits <= 24)
+ depthFormat = PIPE_FORMAT_S8Z24_UNORM;
+ else
+ depthFormat = PIPE_FORMAT_Z32_UNORM;
+#endif
+
+ if (vis->mesa_visual.stencilBits == 8) {
+ if (depthFormat == PIPE_FORMAT_S8Z24_UNORM)
+ stencilFormat = depthFormat;
+ else
+ stencilFormat = PIPE_FORMAT_S8_UNORM;
+ }
+ else {
+ /* no stencil */
+ stencilFormat = PIPE_FORMAT_NONE;
+ if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) {
+ /* use 24-bit Z, undefined stencil channel */
+ depthFormat = PIPE_FORMAT_X8Z24_UNORM;
+ }
+ }
+
+
+ get_drawable_size(vis->display, d, &width, &height);
+
+ /*
+ * Create framebuffer, but we'll plug in our own renderbuffers below.
+ */
+ b->stfb = st_create_framebuffer(&vis->mesa_visual,
+ colorFormat, depthFormat, stencilFormat,
+ width, height,
+ (void *) b);
+ fb = &b->stfb->Base;
+
+ /*
+ * Create scratch XImage for xmesa_display_surface()
+ */
+ b->tempImage = XCreateImage(vis->display,
+ vis->visinfo->visual,
+ vis->visinfo->depth,
+ ZPixmap, 0, /* format, offset */
+ NULL, /* data */
+ 0, 0, /* size */
+ 32, /* bitmap_pad */
+ 0); /* bytes_per_line */
+
+ /* GLX_EXT_texture_from_pixmap */
+ b->TextureTarget = 0;
+ b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
+ b->TextureMipmap = 0;
+
+ /* insert buffer into linked list */
+ b->Next = XMesaBufferList;
+ XMesaBufferList = b;
+
+ return b;
+}
+
+
+/**
+ * Find an XMesaBuffer by matching X display and colormap but NOT matching
+ * the notThis buffer.
+ */
+XMesaBuffer
+xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis)
+{
+ XMesaBuffer b;
+ for (b = XMesaBufferList; b; b = b->Next) {
+ if (b->xm_visual->display == dpy &&
+ b->cmap == cmap &&
+ b != notThis) {
+ return b;
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * Remove buffer from linked list, delete if no longer referenced.
+ */
+static void
+xmesa_free_buffer(XMesaBuffer buffer)
+{
+ XMesaBuffer prev = NULL, b;
+
+ for (b = XMesaBufferList; b; b = b->Next) {
+ if (b == buffer) {
+ struct gl_framebuffer *fb = &buffer->stfb->Base;
+
+ /* unlink buffer from list */
+ if (prev)
+ prev->Next = buffer->Next;
+ else
+ XMesaBufferList = buffer->Next;
+
+ /* mark as delete pending */
+ fb->DeletePending = GL_TRUE;
+
+ /* Since the X window for the XMesaBuffer is going away, we don't
+ * want to dereference this pointer in the future.
+ */
+ b->drawable = 0;
+
+ buffer->tempImage->data = NULL;
+ XDestroyImage(buffer->tempImage);
+
+ /* Unreference. If count = zero we'll really delete the buffer */
+ _mesa_reference_framebuffer(&fb, NULL);
+
+ XFreeGC(b->xm_visual->display, b->gc);
+
+ free(buffer);
+
+ return;
+ }
+ /* continue search */
+ prev = b;
+ }
+ /* buffer not found in XMesaBufferList */
+ _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
+}
+
+
+
+/**********************************************************************/
+/***** Misc Private Functions *****/
+/**********************************************************************/
+
+
+/**
+ * When a context is bound for the first time, we can finally finish
+ * initializing the context's visual and buffer information.
+ * \param v the XMesaVisual to initialize
+ * \param b the XMesaBuffer to initialize (may be NULL)
+ * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode
+ * \param window the window/pixmap we're rendering into
+ * \param cmap the colormap associated with the window/pixmap
+ * \return GL_TRUE=success, GL_FALSE=failure
+ */
+static GLboolean
+initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
+ GLboolean rgb_flag, Drawable window,
+ Colormap cmap)
+{
+ ASSERT(!b || b->xm_visual == v);
+
+ /* Save true bits/pixel */
+ v->BitsPerPixel = bits_per_pixel(v);
+ assert(v->BitsPerPixel > 0);
+
+ if (rgb_flag == GL_FALSE) {
+ /* COLOR-INDEXED WINDOW: not supported*/
+ return GL_FALSE;
+ }
+ else {
+ /* RGB WINDOW:
+ * We support RGB rendering into almost any kind of visual.
+ */
+ const int xclass = v->mesa_visual.visualType;
+ if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
+ _mesa_warning(NULL,
+ "XMesa: RGB mode rendering not supported in given visual.\n");
+ return GL_FALSE;
+ }
+ v->mesa_visual.indexBits = 0;
+
+ if (v->BitsPerPixel == 32) {
+ /* We use XImages for all front/back buffers. If an X Window or
+ * X Pixmap is 32bpp, there's no guarantee that the alpha channel
+ * will be preserved. For XImages we're in luck.
+ */
+ v->mesa_visual.alphaBits = 8;
+ }
+ }
+
+ /*
+ * If MESA_INFO env var is set print out some debugging info
+ * which can help Brian figure out what's going on when a user
+ * reports bugs.
+ */
+ if (_mesa_getenv("MESA_INFO")) {
+ _mesa_printf("X/Mesa visual = %p\n", (void *) v);
+ _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
+ _mesa_printf("X/Mesa depth = %d\n", v->visinfo->depth);
+ _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
+ }
+
+ if (b && window) {
+ /* these should have been set in create_xmesa_buffer */
+ ASSERT(b->drawable == window);
+
+ /* Setup for single/double buffering */
+ if (v->mesa_visual.doubleBufferMode) {
+ /* Double buffered */
+ b->shm = xmesa_check_for_xshm( v->display );
+ }
+
+ /* X11 graphics context */
+ b->gc = XCreateGC( v->display, window, 0, NULL );
+ XSetFunction( v->display, b->gc, GXcopy );
+ }
+
+ return GL_TRUE;
+}
+
+
+
+#define NUM_VISUAL_TYPES 6
+
+/**
+ * Convert an X visual type to a GLX visual type.
+ *
+ * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
+ * to be converted.
+ * \return If \c visualType is a valid X visual type, a GLX visual type will
+ * be returned. Otherwise \c GLX_NONE will be returned.
+ *
+ * \note
+ * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
+ * DRI CVS tree.
+ */
+static GLint
+xmesa_convert_from_x_visual_type( int visualType )
+{
+ static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
+ GLX_STATIC_GRAY, GLX_GRAY_SCALE,
+ GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
+ GLX_TRUE_COLOR, GLX_DIRECT_COLOR
+ };
+
+ return ( (unsigned) visualType < NUM_VISUAL_TYPES )
+ ? glx_visual_types[ visualType ] : GLX_NONE;
+}
+
+
+/**********************************************************************/
+/***** Public Functions *****/
+/**********************************************************************/
+
+
+/*
+ * Create a new X/Mesa visual.
+ * Input: display - X11 display
+ * visinfo - an XVisualInfo pointer
+ * rgb_flag - GL_TRUE = RGB mode,
+ * GL_FALSE = color index mode
+ * alpha_flag - alpha buffer requested?
+ * db_flag - GL_TRUE = double-buffered,
+ * GL_FALSE = single buffered
+ * stereo_flag - stereo visual?
+ * ximage_flag - GL_TRUE = use an XImage for back buffer,
+ * GL_FALSE = use an off-screen pixmap for back buffer
+ * depth_size - requested bits/depth values, or zero
+ * stencil_size - requested bits/stencil values, or zero
+ * accum_red_size - requested bits/red accum values, or zero
+ * accum_green_size - requested bits/green accum values, or zero
+ * accum_blue_size - requested bits/blue accum values, or zero
+ * accum_alpha_size - requested bits/alpha accum values, or zero
+ * num_samples - number of samples/pixel if multisampling, or zero
+ * level - visual level, usually 0
+ * visualCaveat - ala the GLX extension, usually GLX_NONE
+ * Return; a new XMesaVisual or 0 if error.
+ */
+PUBLIC
+XMesaVisual XMesaCreateVisual( Display *display,
+ XVisualInfo * visinfo,
+ GLboolean rgb_flag,
+ GLboolean alpha_flag,
+ GLboolean db_flag,
+ GLboolean stereo_flag,
+ GLboolean ximage_flag,
+ GLint depth_size,
+ GLint stencil_size,
+ GLint accum_red_size,
+ GLint accum_green_size,
+ GLint accum_blue_size,
+ GLint accum_alpha_size,
+ GLint num_samples,
+ GLint level,
+ GLint visualCaveat )
+{
+ XMesaVisual v;
+ GLint red_bits, green_bits, blue_bits, alpha_bits;
+
+ /* For debugging only */
+ if (_mesa_getenv("MESA_XSYNC")) {
+ /* This makes debugging X easier.
+ * In your debugger, set a breakpoint on _XError to stop when an
+ * X protocol error is generated.
+ */
+ XSynchronize( display, 1 );
+ }
+
+ v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
+ if (!v) {
+ return NULL;
+ }
+
+ v->display = display;
+
+ /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
+ * the struct but we may need some of the information contained in it
+ * at a later time.
+ */
+ v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
+ if (!v->visinfo) {
+ _mesa_free(v);
+ return NULL;
+ }
+ MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
+
+ v->ximage_flag = ximage_flag;
+
+ v->mesa_visual.redMask = visinfo->red_mask;
+ v->mesa_visual.greenMask = visinfo->green_mask;
+ v->mesa_visual.blueMask = visinfo->blue_mask;
+ v->mesa_visual.visualID = visinfo->visualid;
+ v->mesa_visual.screen = visinfo->screen;
+
+#if !(defined(__cplusplus) || defined(c_plusplus))
+ v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
+#else
+ v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
+#endif
+
+ v->mesa_visual.visualRating = visualCaveat;
+
+ if (alpha_flag)
+ v->mesa_visual.alphaBits = 8;
+
+ (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
+
+ {
+ const int xclass = v->mesa_visual.visualType;
+ if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
+ red_bits = _mesa_bitcount(GET_REDMASK(v));
+ green_bits = _mesa_bitcount(GET_GREENMASK(v));
+ blue_bits = _mesa_bitcount(GET_BLUEMASK(v));
+ }
+ else {
+ /* this is an approximation */
+ int depth;
+ depth = v->visinfo->depth;
+ red_bits = depth / 3;
+ depth -= red_bits;
+ green_bits = depth / 2;
+ depth -= green_bits;
+ blue_bits = depth;
+ alpha_bits = 0;
+ assert( red_bits + green_bits + blue_bits == v->visinfo->depth );
+ }
+ alpha_bits = v->mesa_visual.alphaBits;
+ }
+
+ _mesa_initialize_visual( &v->mesa_visual,
+ rgb_flag, db_flag, stereo_flag,
+ red_bits, green_bits,
+ blue_bits, alpha_bits,
+ v->mesa_visual.indexBits,
+ depth_size,
+ stencil_size,
+ accum_red_size, accum_green_size,
+ accum_blue_size, accum_alpha_size,
+ 0 );
+
+ /* XXX minor hack */
+ v->mesa_visual.level = level;
+ return v;
+}
+
+
+PUBLIC
+void XMesaDestroyVisual( XMesaVisual v )
+{
+ _mesa_free(v->visinfo);
+ _mesa_free(v);
+}
+
+
+
+/**
+ * Create a new XMesaContext.
+ * \param v the XMesaVisual
+ * \param share_list another XMesaContext with which to share display
+ * lists or NULL if no sharing is wanted.
+ * \return an XMesaContext or NULL if error.
+ */
+PUBLIC
+XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
+{
+ static GLboolean firstTime = GL_TRUE;
+ static struct pipe_screen *screen = NULL;
+ struct pipe_context *pipe = NULL;
+ XMesaContext c;
+ GLcontext *mesaCtx;
+ uint pf;
+
+ if (firstTime) {
+ pipe_mutex_init(_xmesa_lock);
+ screen = driver.create_pipe_screen();
+ firstTime = GL_FALSE;
+ }
+
+ /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
+ c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
+ if (!c)
+ return NULL;
+
+ pf = choose_pixel_format(v);
+ assert(pf);
+
+ c->xm_visual = v;
+ c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
+ c->xm_read_buffer = NULL;
+
+ if (screen == NULL)
+ goto fail;
+
+ pipe = driver.create_pipe_context(screen, (void *) c);
+ if (pipe == NULL)
+ goto fail;
+
+ c->st = st_create_context(pipe,
+ &v->mesa_visual,
+ share_list ? share_list->st : NULL);
+ if (c->st == NULL)
+ goto fail;
+
+ mesaCtx = c->st->ctx;
+ c->st->ctx->DriverCtx = c;
+
+ return c;
+
+fail:
+ if (c->st)
+ st_destroy_context(c->st);
+ else if (pipe)
+ pipe->destroy(pipe);
+
+ _mesa_free(c);
+ return NULL;
+}
+
+
+
+PUBLIC
+void XMesaDestroyContext( XMesaContext c )
+{
+ st_destroy_context(c->st);
+
+ /* FIXME: We should destroy the screen here, but if we do so, surfaces may
+ * outlive it, causing segfaults
+ struct pipe_screen *screen = c->st->pipe->screen;
+ screen->destroy(screen);
+ */
+
+ _mesa_free(c);
+}
+
+
+
+/**
+ * Private function for creating an XMesaBuffer which corresponds to an
+ * X window or pixmap.
+ * \param v the window's XMesaVisual
+ * \param w the window we're wrapping
+ * \return new XMesaBuffer or NULL if error
+ */
+PUBLIC XMesaBuffer
+XMesaCreateWindowBuffer(XMesaVisual v, Window w)
+{
+ XWindowAttributes attr;
+ XMesaBuffer b;
+ Colormap cmap;
+ int depth;
+
+ assert(v);
+ assert(w);
+
+ /* Check that window depth matches visual depth */
+ XGetWindowAttributes( v->display, w, &attr );
+ depth = attr.depth;
+ if (v->visinfo->depth != depth) {
+ _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
+ v->visinfo->depth, depth);
+ return NULL;
+ }
+
+ /* Find colormap */
+ if (attr.colormap) {
+ cmap = attr.colormap;
+ }
+ else {
+ _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
+ /* this is weird, a window w/out a colormap!? */
+ /* OK, let's just allocate a new one and hope for the best */
+ cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
+ }
+
+ b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap);
+ if (!b)
+ return NULL;
+
+ if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
+ (Drawable) w, cmap )) {
+ xmesa_free_buffer(b);
+ return NULL;
+ }
+
+ return b;
+}
+
+
+
+/**
+ * Create a new XMesaBuffer from an X pixmap.
+ *
+ * \param v the XMesaVisual
+ * \param p the pixmap
+ * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
+ * \c GLX_DIRECT_COLOR visual for the pixmap
+ * \returns new XMesaBuffer or NULL if error
+ */
+PUBLIC XMesaBuffer
+XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap)
+{
+ XMesaBuffer b;
+
+ assert(v);
+
+ b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
+ if (!b)
+ return NULL;
+
+ if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
+ (Drawable) p, cmap)) {
+ xmesa_free_buffer(b);
+ return NULL;
+ }
+
+ return b;
+}
+
+
+/**
+ * For GLX_EXT_texture_from_pixmap
+ */
+XMesaBuffer
+XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
+ Colormap cmap,
+ int format, int target, int mipmap)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ XMesaBuffer b;
+ GLuint width, height;
+
+ assert(v);
+
+ b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
+ if (!b)
+ return NULL;
+
+ /* get pixmap size, update framebuffer/renderbuffer dims */
+ xmesa_get_window_size(v->display, b, &width, &height);
+ _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
+
+ if (target == 0) {
+ /* examine dims */
+ if (ctx->Extensions.ARB_texture_non_power_of_two) {
+ target = GLX_TEXTURE_2D_EXT;
+ }
+ else if ( _mesa_bitcount(width) == 1
+ && _mesa_bitcount(height) == 1) {
+ /* power of two size */
+ if (height == 1) {
+ target = GLX_TEXTURE_1D_EXT;
+ }
+ else {
+ target = GLX_TEXTURE_2D_EXT;
+ }
+ }
+ else if (ctx->Extensions.NV_texture_rectangle) {
+ target = GLX_TEXTURE_RECTANGLE_EXT;
+ }
+ else {
+ /* non power of two textures not supported */
+ XMesaDestroyBuffer(b);
+ return 0;
+ }
+ }
+
+ b->TextureTarget = target;
+ b->TextureFormat = format;
+ b->TextureMipmap = mipmap;
+
+ if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
+ (Drawable) p, cmap)) {
+ xmesa_free_buffer(b);
+ return NULL;
+ }
+
+ return b;
+}
+
+
+
+XMesaBuffer
+XMesaCreatePBuffer(XMesaVisual v, Colormap cmap,
+ unsigned int width, unsigned int height)
+{
+ Window root;
+ Drawable drawable; /* X Pixmap Drawable */
+ XMesaBuffer b;
+
+ /* allocate pixmap for front buffer */
+ root = RootWindow( v->display, v->visinfo->screen );
+ drawable = XCreatePixmap(v->display, root, width, height,
+ v->visinfo->depth);
+ if (!drawable)
+ return NULL;
+
+ b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
+ if (!b)
+ return NULL;
+
+ if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
+ drawable, cmap)) {
+ xmesa_free_buffer(b);
+ return NULL;
+ }
+
+ return b;
+}
+
+
+
+/*
+ * Deallocate an XMesaBuffer structure and all related info.
+ */
+PUBLIC void
+XMesaDestroyBuffer(XMesaBuffer b)
+{
+ xmesa_free_buffer(b);
+}
+
+
+/**
+ * Query the current window size and update the corresponding GLframebuffer
+ * and all attached renderbuffers.
+ * Called when:
+ * 1. the first time a buffer is bound to a context.
+ * 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too...
+ * Note: it's possible (and legal) for xmctx to be NULL. That can happen
+ * when resizing a buffer when no rendering context is bound.
+ */
+void
+xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
+{
+ GLuint width, height;
+ xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
+ st_resize_framebuffer(drawBuffer->stfb, width, height);
+}
+
+
+
+
+/*
+ * Bind buffer b to context c and make c the current rendering context.
+ */
+PUBLIC
+GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
+ XMesaBuffer readBuffer )
+{
+ XMesaContext old_ctx = XMesaGetCurrentContext();
+
+ if (old_ctx && old_ctx != c) {
+ XMesaFlush(old_ctx);
+ old_ctx->xm_buffer = NULL;
+ old_ctx->xm_read_buffer = NULL;
+ }
+
+ if (c) {
+ if (!drawBuffer || !readBuffer)
+ return GL_FALSE; /* must specify buffers! */
+
+ if (c == old_ctx &&
+ c->xm_buffer == drawBuffer &&
+ c->xm_read_buffer == readBuffer)
+ return GL_TRUE;
+
+ c->xm_buffer = drawBuffer;
+ c->xm_read_buffer = readBuffer;
+
+ st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb);
+
+ xmesa_check_and_update_buffer_size(c, drawBuffer);
+ if (readBuffer != drawBuffer)
+ xmesa_check_and_update_buffer_size(c, readBuffer);
+
+ /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
+ drawBuffer->wasCurrent = GL_TRUE;
+ }
+ else {
+ /* Detach */
+ st_make_current( NULL, NULL, NULL );
+
+ }
+ return GL_TRUE;
+}
+
+
+/*
+ * Unbind the context c from its buffer.
+ */
+GLboolean XMesaUnbindContext( XMesaContext c )
+{
+ /* A no-op for XFree86 integration purposes */
+ return GL_TRUE;
+}
+
+
+XMesaContext XMesaGetCurrentContext( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx) {
+ XMesaContext xmesa = xmesa_context(ctx);
+ return xmesa;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+
+/**
+ * Swap front and back color buffers and have winsys display front buffer.
+ * If there's no front color buffer no swap actually occurs.
+ */
+PUBLIC
+void XMesaSwapBuffers( XMesaBuffer b )
+{
+ struct pipe_surface *frontLeftSurf;
+
+ st_swapbuffers(b->stfb, &frontLeftSurf, NULL);
+
+ if (frontLeftSurf) {
+ driver.display_surface(b, frontLeftSurf);
+ }
+
+ xmesa_check_and_update_buffer_size(NULL, b);
+}
+
+
+
+/*
+ * Copy sub-region of back buffer to front buffer
+ */
+void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
+{
+ struct pipe_surface *surf_front;
+ struct pipe_surface *surf_back;
+ struct pipe_context *pipe = NULL; /* XXX fix */
+
+ st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front);
+ st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back);
+
+ if (!surf_front || !surf_back)
+ return;
+
+ pipe->surface_copy(pipe,
+ surf_front, x, y, /* dest */
+ surf_back, x, y, /* src */
+ width, height);
+}
+
+
+
+void XMesaFlush( XMesaContext c )
+{
+ if (c && c->xm_visual->display) {
+ st_finish(c->st);
+ XSync( c->xm_visual->display, False );
+ }
+}
+
+
+
+
+
+XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d )
+{
+ XMesaBuffer b;
+ for (b = XMesaBufferList; b; b = b->Next) {
+ if (b->drawable == d && b->xm_visual->display == dpy) {
+ return b;
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * Free/destroy all XMesaBuffers associated with given display.
+ */
+void xmesa_destroy_buffers_on_display(Display *dpy)
+{
+ XMesaBuffer b, next;
+ for (b = XMesaBufferList; b; b = next) {
+ next = b->Next;
+ if (b->xm_visual->display == dpy) {
+ xmesa_free_buffer(b);
+ }
+ }
+}
+
+
+/*
+ * Look for XMesaBuffers whose X window has been destroyed.
+ * Deallocate any such XMesaBuffers.
+ */
+void XMesaGarbageCollect( void )
+{
+ XMesaBuffer b, next;
+ for (b=XMesaBufferList; b; b=next) {
+ next = b->Next;
+ if (b->xm_visual &&
+ b->xm_visual->display &&
+ b->drawable &&
+ b->type == WINDOW) {
+ XSync(b->xm_visual->display, False);
+ if (!window_exists( b->xm_visual->display, b->drawable )) {
+ /* found a dead window, free the ancillary info */
+ XMesaDestroyBuffer( b );
+ }
+ }
+ }
+}
+
+
+
+
+PUBLIC void
+XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
+ const int *attrib_list)
+{
+}
+
+
+
+PUBLIC void
+XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer)
+{
+}
+
diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h
new file mode 100644
index 0000000000..ce97a3ec76
--- /dev/null
+++ b/src/gallium/state_trackers/glx/xlib/xm_api.h
@@ -0,0 +1,394 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+/* Sample Usage:
+
+In addition to the usual X calls to select a visual, create a colormap
+and create a window, you must do the following to use the X/Mesa interface:
+
+1. Call XMesaCreateVisual() to make an XMesaVisual from an XVisualInfo.
+
+2. Call XMesaCreateContext() to create an X/Mesa rendering context, given
+ the XMesaVisual.
+
+3. Call XMesaCreateWindowBuffer() to create an XMesaBuffer from an X window
+ and XMesaVisual.
+
+4. Call XMesaMakeCurrent() to bind the XMesaBuffer to an XMesaContext and
+ to make the context the current one.
+
+5. Make gl* calls to render your graphics.
+
+6. Use XMesaSwapBuffers() when double buffering to swap front/back buffers.
+
+7. Before the X window is destroyed, call XMesaDestroyBuffer().
+
+8. Before exiting, call XMesaDestroyVisual and XMesaDestroyContext.
+
+*/
+
+
+
+
+#ifndef XMESA_H
+#define XMESA_H
+
+
+#include "main/mtypes.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_public.h"
+#include "pipe/p_thread.h"
+
+
+# include <X11/Xlib.h>
+# include <X11/Xlibint.h>
+# include <X11/Xutil.h>
+# ifdef USE_XSHM /* was SHM */
+# include <sys/ipc.h>
+# include <sys/shm.h>
+# include <X11/extensions/XShm.h>
+# endif
+
+typedef struct xmesa_buffer *XMesaBuffer;
+typedef struct xmesa_context *XMesaContext;
+typedef struct xmesa_visual *XMesaVisual;
+
+
+
+/*
+ * Create a new X/Mesa visual.
+ * Input: display - X11 display
+ * visinfo - an XVisualInfo pointer
+ * rgb_flag - GL_TRUE = RGB mode,
+ * GL_FALSE = color index mode
+ * alpha_flag - alpha buffer requested?
+ * db_flag - GL_TRUE = double-buffered,
+ * GL_FALSE = single buffered
+ * stereo_flag - stereo visual?
+ * ximage_flag - GL_TRUE = use an XImage for back buffer,
+ * GL_FALSE = use an off-screen pixmap for back buffer
+ * depth_size - requested bits/depth values, or zero
+ * stencil_size - requested bits/stencil values, or zero
+ * accum_red_size - requested bits/red accum values, or zero
+ * accum_green_size - requested bits/green accum values, or zero
+ * accum_blue_size - requested bits/blue accum values, or zero
+ * accum_alpha_size - requested bits/alpha accum values, or zero
+ * num_samples - number of samples/pixel if multisampling, or zero
+ * level - visual level, usually 0
+ * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT
+ * Return; a new XMesaVisual or 0 if error.
+ */
+extern XMesaVisual XMesaCreateVisual( Display *display,
+ XVisualInfo * visinfo,
+ GLboolean rgb_flag,
+ GLboolean alpha_flag,
+ GLboolean db_flag,
+ GLboolean stereo_flag,
+ GLboolean ximage_flag,
+ GLint depth_size,
+ GLint stencil_size,
+ GLint accum_red_size,
+ GLint accum_green_size,
+ GLint accum_blue_size,
+ GLint accum_alpha_size,
+ GLint num_samples,
+ GLint level,
+ GLint visualCaveat );
+
+/*
+ * Destroy an XMesaVisual, but not the associated XVisualInfo.
+ */
+extern void XMesaDestroyVisual( XMesaVisual v );
+
+
+
+/*
+ * Create a new XMesaContext for rendering into an X11 window.
+ *
+ * Input: visual - an XMesaVisual
+ * share_list - another XMesaContext with which to share display
+ * lists or NULL if no sharing is wanted.
+ * Return: an XMesaContext or NULL if error.
+ */
+extern XMesaContext XMesaCreateContext( XMesaVisual v,
+ XMesaContext share_list );
+
+
+/*
+ * Destroy a rendering context as returned by XMesaCreateContext()
+ */
+extern void XMesaDestroyContext( XMesaContext c );
+
+
+
+/*
+ * Create an XMesaBuffer from an X window.
+ */
+extern XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, Window w );
+
+
+/*
+ * Create an XMesaBuffer from an X pixmap.
+ */
+extern XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v,
+ Pixmap p,
+ Colormap cmap );
+
+
+/*
+ * Destroy an XMesaBuffer, but not the corresponding window or pixmap.
+ */
+extern void XMesaDestroyBuffer( XMesaBuffer b );
+
+
+/*
+ * Return the XMesaBuffer handle which corresponds to an X drawable, if any.
+ *
+ * New in Mesa 2.3.
+ */
+extern XMesaBuffer XMesaFindBuffer( Display *dpy,
+ Drawable d );
+
+
+
+/*
+ * Bind two buffers (read and draw) to a context and make the
+ * context the current one.
+ * New in Mesa 3.3
+ */
+extern GLboolean XMesaMakeCurrent2( XMesaContext c,
+ XMesaBuffer drawBuffer,
+ XMesaBuffer readBuffer );
+
+
+/*
+ * Unbind the current context from its buffer.
+ */
+extern GLboolean XMesaUnbindContext( XMesaContext c );
+
+
+/*
+ * Return a handle to the current context.
+ */
+extern XMesaContext XMesaGetCurrentContext( void );
+
+
+/*
+ * Swap the front and back buffers for the given buffer. No action is
+ * taken if the buffer is not double buffered.
+ */
+extern void XMesaSwapBuffers( XMesaBuffer b );
+
+
+/*
+ * Copy a sub-region of the back buffer to the front buffer.
+ *
+ * New in Mesa 2.6
+ */
+extern void XMesaCopySubBuffer( XMesaBuffer b,
+ int x,
+ int y,
+ int width,
+ int height );
+
+
+
+
+
+/*
+ * Flush/sync a context
+ */
+extern void XMesaFlush( XMesaContext c );
+
+
+
+/*
+ * Scan for XMesaBuffers whose window/pixmap has been destroyed, then free
+ * any memory used by that buffer.
+ *
+ * New in Mesa 2.3.
+ */
+extern void XMesaGarbageCollect( void );
+
+
+
+/*
+ * Create a pbuffer.
+ * New in Mesa 4.1
+ */
+extern XMesaBuffer XMesaCreatePBuffer(XMesaVisual v, Colormap cmap,
+ unsigned int width, unsigned int height);
+
+
+
+/*
+ * Texture from Pixmap
+ * New in Mesa 7.1
+ */
+extern void
+XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
+ const int *attrib_list);
+
+extern void
+XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer);
+
+
+extern XMesaBuffer
+XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
+ Colormap cmap,
+ int format, int target, int mipmap);
+
+
+
+
+/***********************************************************************
+ */
+
+extern pipe_mutex _xmesa_lock;
+
+extern struct xmesa_buffer *XMesaBufferList;
+
+
+/**
+ * Visual inforation, derived from GLvisual.
+ * Basically corresponds to an XVisualInfo.
+ */
+struct xmesa_visual {
+ GLvisual mesa_visual; /* Device independent visual parameters */
+ Display *display; /* The X11 display */
+ XVisualInfo * visinfo; /* X's visual info (pointer to private copy) */
+ XVisualInfo *vishandle; /* Only used in fakeglx.c */
+ GLint BitsPerPixel; /* True bits per pixel for XImages */
+
+ GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */
+};
+
+
+/**
+ * Context info, derived from st_context.
+ * Basically corresponds to a GLXContext.
+ */
+struct xmesa_context {
+ struct st_context *st;
+ XMesaVisual xm_visual; /** pixel format info */
+ XMesaBuffer xm_buffer; /** current drawbuffer */
+ XMesaBuffer xm_read_buffer; /** current readbuffer */
+};
+
+
+/**
+ * Types of X/GLX drawables we might render into.
+ */
+typedef enum {
+ WINDOW, /* An X window */
+ GLXWINDOW, /* GLX window */
+ PIXMAP, /* GLX pixmap */
+ PBUFFER /* GLX Pbuffer */
+} BufferType;
+
+
+/**
+ * Framebuffer information, derived from.
+ * Basically corresponds to a GLXDrawable.
+ */
+struct xmesa_buffer {
+ struct st_framebuffer *stfb;
+
+ GLboolean wasCurrent; /* was ever the current buffer? */
+ XMesaVisual xm_visual; /* the X/Mesa visual */
+ Drawable drawable; /* Usually the X window ID */
+ Colormap cmap; /* the X colormap */
+ BufferType type; /* window, pixmap, pbuffer or glxwindow */
+
+ XImage *tempImage;
+ unsigned long selectedEvents;/* for pbuffers only */
+
+ GLuint shm; /* X Shared Memory extension status: */
+ /* 0 = not available */
+ /* 1 = XImage support available */
+ /* 2 = Pixmap support available too */
+#if defined(USE_XSHM)
+ XShmSegmentInfo shminfo;
+#endif
+
+ GC gc; /* scratch GC for span, line, tri drawing */
+
+ /* GLX_EXT_texture_from_pixmap */
+ GLint TextureTarget; /** GLX_TEXTURE_1D_EXT, for example */
+ GLint TextureFormat; /** GLX_TEXTURE_FORMAT_RGB_EXT, for example */
+ GLint TextureMipmap; /** 0 or 1 */
+
+ struct xmesa_buffer *Next; /* Linked list pointer: */
+};
+
+
+
+/** cast wrapper */
+static INLINE XMesaContext
+xmesa_context(GLcontext *ctx)
+{
+ return (XMesaContext) ctx->DriverCtx;
+}
+
+
+/** cast wrapper */
+static INLINE XMesaBuffer
+xmesa_buffer(GLframebuffer *fb)
+{
+ struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
+ return (XMesaBuffer) st_framebuffer_private(stfb);
+}
+
+
+extern void
+xmesa_delete_framebuffer(struct gl_framebuffer *fb);
+
+extern XMesaBuffer
+xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis);
+
+extern void
+xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer);
+
+extern void
+xmesa_destroy_buffers_on_display(Display *dpy);
+
+static INLINE GLuint
+xmesa_buffer_width(XMesaBuffer b)
+{
+ return b->stfb->Base.Width;
+}
+
+static INLINE GLuint
+xmesa_buffer_height(XMesaBuffer b)
+{
+ return b->stfb->Base.Height;
+}
+
+extern int
+xmesa_check_for_xshm(Display *display);
+
+
+#endif
diff --git a/src/gallium/state_trackers/glx/xlib/xm_winsys.h b/src/gallium/state_trackers/glx/xlib/xm_winsys.h
new file mode 100644
index 0000000000..0e57605c34
--- /dev/null
+++ b/src/gallium/state_trackers/glx/xlib/xm_winsys.h
@@ -0,0 +1,59 @@
+
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef XM_WINSYS_H
+#define XM_WINSYS_H
+
+struct pipe_context;
+struct pipe_screen;
+struct pipe_surface;
+struct xmesa_buffer;
+
+
+struct xm_driver {
+
+ struct pipe_screen *(*create_pipe_screen)( void );
+
+ /* The context_private argument needs to go away. Is currently used
+ * in a round-about way to associate a display-target surface with its
+ * Xlib window.
+ */
+ struct pipe_context *(*create_pipe_context)( struct pipe_screen *,
+ void *context_private );
+
+ void (*display_surface)( struct xmesa_buffer *,
+ struct pipe_surface * );
+
+};
+
+
+extern void
+xmesa_set_driver( const struct xm_driver *driver );
+
+
+#endif
diff --git a/src/gallium/state_trackers/python/README b/src/gallium/state_trackers/python/README
new file mode 100644
index 0000000000..e03d546830
--- /dev/null
+++ b/src/gallium/state_trackers/python/README
@@ -0,0 +1,43 @@
+This directory contains Python bindings to Gallium3D. It looks like a state
+tracker from the pipe driver perspective, and it looks like a pipe driver from
+the python script perspective.
+
+
+To build you'll need:
+* Python (with development packages)
+* SCons
+* SWIG, http://www.swig.org/download.html
+* Python Imaging Library with TK support, http://www.pythonware.com/products/pil/,
+ for the samples
+
+On a debian-based distro you can simply do:
+
+ aptitude install python-dev scons swig python-imaging python-imaging-tk
+
+On a Windows machine ensure the swig command is in your PATH.
+
+Invoke scons on the top dir as
+
+ scons debug=yes statetrackers=python drivers=softpipe,trace winsys=none
+
+To use it set PYTHONPATH appropriately, e.g, in Linux do:
+
+ export PYTHONPATH=$PWD/build/linux-x86-debug/gallium/state_trackers/python
+
+or (in Windows)
+
+ set PYTHONPATH=%CD%\build\windows-x86-debug\gallium\state_trackers\python
+
+and then try running
+
+ python src/gallium/state_trackers/python/samples/tri.py
+
+which should show a triangle.
+
+
+This is still work in progress:
+- errors are not handled properly and almost always result in crash
+- state atoms with array members are awkward to set
+
+--
+Jose Fonseca <jfonseca@vmware.com>
diff --git a/src/gallium/state_trackers/python/SConscript b/src/gallium/state_trackers/python/SConscript
new file mode 100644
index 0000000000..ec385e7c44
--- /dev/null
+++ b/src/gallium/state_trackers/python/SConscript
@@ -0,0 +1,47 @@
+import sys
+import os.path
+
+Import('*')
+
+if 'python' in env['statetrackers']:
+
+ env = env.Clone()
+
+ env.Tool('python')
+
+ env.Tool('swig')
+ env.Append(SWIGPATH = ['#src/gallium/include', '#src/gallium/include/pipe'])
+ env.Append(SWIGFLAGS = ['-python', '-keyword'])
+
+ env.Append(CPPPATH = '.')
+
+ if env['platform'] == 'windows':
+ env.Append(LIBS = [
+ 'opengl32',
+ 'gdi32',
+ 'user32',
+ 'kernel32',
+ ])
+ else:
+ env.Append(LIBS = [
+ 'GL',
+ 'X11',
+ ])
+
+ pyst = env.ConvenienceLibrary(
+ target = 'pyst',
+ source = [
+ 'gallium.i',
+ 'st_device.c',
+ 'st_sample.c',
+ 'st_softpipe_winsys.c',
+ ],
+ )
+
+ env.SharedLibrary(
+ target = '_gallium',
+ source = [
+ 'st_hardpipe_winsys.c',
+ ],
+ LIBS = [pyst, softpipe, trace] + auxiliaries + env['LIBS'],
+ )
diff --git a/src/gallium/state_trackers/python/gallium.i b/src/gallium/state_trackers/python/gallium.i
new file mode 100644
index 0000000000..3f79cc1a3d
--- /dev/null
+++ b/src/gallium/state_trackers/python/gallium.i
@@ -0,0 +1,103 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+%module gallium;
+
+%{
+
+#include <stdio.h>
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+#include "cso_cache/cso_context.h"
+#include "util/u_draw_quad.h"
+#include "util/u_tile.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_text.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "st_device.h"
+#include "st_sample.h"
+
+%}
+
+%include "typemaps.i"
+%include "exception.i"
+%include "cstring.i"
+
+%include "carrays.i"
+%array_class(unsigned char, ByteArray);
+%array_class(int, IntArray);
+%array_class(unsigned, UnsignedArray);
+%array_class(float, FloatArray);
+
+
+%rename(Device) st_device;
+%rename(Context) st_context;
+%rename(Texture) pipe_texture;
+%rename(Surface) st_surface;
+%rename(Buffer) pipe_buffer;
+
+%rename(BlendColor) pipe_blend_color;
+%rename(Blend) pipe_blend_state;
+%rename(Clip) pipe_clip_state;
+%rename(ConstantBuffer) pipe_constant_buffer;
+%rename(Depth) pipe_depth_state;
+%rename(Stencil) pipe_stencil_state;
+%rename(Alpha) pipe_alpha_state;
+%rename(DepthStencilAlpha) pipe_depth_stencil_alpha_state;
+%rename(FormatBlock) pipe_format_block;
+%rename(Framebuffer) pipe_framebuffer_state;
+%rename(PolyStipple) pipe_poly_stipple;
+%rename(Rasterizer) pipe_rasterizer_state;
+%rename(Sampler) pipe_sampler_state;
+%rename(Scissor) pipe_scissor_state;
+%rename(Shader) pipe_shader_state;
+%rename(VertexBuffer) pipe_vertex_buffer;
+%rename(VertexElement) pipe_vertex_element;
+%rename(Viewport) pipe_viewport_state;
+
+
+%include "p_compiler.i"
+%include "p_defines.h";
+%include "p_format.i"
+
+%include "p_device.i"
+%include "p_context.i"
+%include "p_texture.i"
+%include "p_state.i"
+
diff --git a/src/gallium/state_trackers/python/p_compiler.i b/src/gallium/state_trackers/python/p_compiler.i
new file mode 100644
index 0000000000..15f6ba5b9d
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_compiler.i
@@ -0,0 +1,29 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+typedef unsigned char ubyte;
diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i
new file mode 100644
index 0000000000..a40aa1e518
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_context.i
@@ -0,0 +1,319 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+%nodefaultctor st_context;
+%nodefaultdtor st_context;
+
+struct st_context {
+};
+
+%extend st_context {
+
+ ~st_context() {
+ st_context_destroy($self);
+ }
+
+ /*
+ * State functions (create/bind/destroy state objects)
+ */
+
+ void set_blend( const struct pipe_blend_state *state ) {
+ cso_set_blend($self->cso, state);
+ }
+
+ void set_sampler( unsigned index, const struct pipe_sampler_state *state ) {
+ cso_single_sampler($self->cso, index, state);
+ cso_single_sampler_done($self->cso);
+ }
+
+ void set_rasterizer( const struct pipe_rasterizer_state *state ) {
+ cso_set_rasterizer($self->cso, state);
+ }
+
+ void set_depth_stencil_alpha(const struct pipe_depth_stencil_alpha_state *state) {
+ cso_set_depth_stencil_alpha($self->cso, state);
+ }
+
+ void set_fragment_shader( const struct pipe_shader_state *state ) {
+ void *fs;
+
+ if(!state) {
+ cso_set_fragment_shader_handle($self->cso, NULL);
+ return;
+ }
+
+ fs = $self->pipe->create_fs_state($self->pipe, state);
+ if(!fs)
+ return;
+
+ if(cso_set_fragment_shader_handle($self->cso, fs) != PIPE_OK)
+ return;
+
+ cso_delete_fragment_shader($self->cso, $self->fs);
+ $self->fs = fs;
+ }
+
+ void set_vertex_shader( const struct pipe_shader_state *state ) {
+ void *vs;
+
+ if(!state) {
+ cso_set_vertex_shader_handle($self->cso, NULL);
+ return;
+ }
+
+ vs = $self->pipe->create_vs_state($self->pipe, state);
+ if(!vs)
+ return;
+
+ if(cso_set_vertex_shader_handle($self->cso, vs) != PIPE_OK)
+ return;
+
+ cso_delete_vertex_shader($self->cso, $self->vs);
+ $self->vs = vs;
+ }
+
+ /*
+ * Parameter-like state (or properties)
+ */
+
+ void set_blend_color(const struct pipe_blend_color *state ) {
+ cso_set_blend_color($self->cso, state);
+ }
+
+ void set_clip(const struct pipe_clip_state *state ) {
+ $self->pipe->set_clip_state($self->pipe, state);
+ }
+
+ void set_constant_buffer(unsigned shader, unsigned index,
+ struct pipe_buffer *buffer )
+ {
+ struct pipe_constant_buffer state;
+ memset(&state, 0, sizeof(state));
+ state.buffer = buffer;
+ $self->pipe->set_constant_buffer($self->pipe, shader, index, &state);
+ }
+
+ void set_framebuffer(const struct pipe_framebuffer_state *state )
+ {
+ memcpy(&$self->framebuffer, state, sizeof *state);
+ cso_set_framebuffer($self->cso, state);
+ }
+
+ void set_polygon_stipple(const struct pipe_poly_stipple *state ) {
+ $self->pipe->set_polygon_stipple($self->pipe, state);
+ }
+
+ void set_scissor(const struct pipe_scissor_state *state ) {
+ $self->pipe->set_scissor_state($self->pipe, state);
+ }
+
+ void set_viewport(const struct pipe_viewport_state *state) {
+ cso_set_viewport($self->cso, state);
+ }
+
+ void set_sampler_texture(unsigned index,
+ struct pipe_texture *texture) {
+ if(!texture)
+ texture = $self->default_texture;
+ pipe_texture_reference(&$self->sampler_textures[index], texture);
+ $self->pipe->set_sampler_textures($self->pipe,
+ PIPE_MAX_SAMPLERS,
+ $self->sampler_textures);
+ }
+
+ void set_vertex_buffer(unsigned index,
+ unsigned stride,
+ unsigned max_index,
+ unsigned buffer_offset,
+ struct pipe_buffer *buffer)
+ {
+ unsigned i;
+ struct pipe_vertex_buffer state;
+
+ memset(&state, 0, sizeof(state));
+ state.stride = stride;
+ state.max_index = max_index;
+ state.buffer_offset = buffer_offset;
+ state.buffer = buffer;
+
+ memcpy(&$self->vertex_buffers[index], &state, sizeof(state));
+
+ for(i = 0; i < PIPE_MAX_ATTRIBS; ++i)
+ if(self->vertex_buffers[i].buffer)
+ $self->num_vertex_buffers = i + 1;
+
+ $self->pipe->set_vertex_buffers($self->pipe,
+ $self->num_vertex_buffers,
+ $self->vertex_buffers);
+ }
+
+ void set_vertex_element(unsigned index,
+ const struct pipe_vertex_element *element)
+ {
+ memcpy(&$self->vertex_elements[index], element, sizeof(*element));
+ }
+
+ void set_vertex_elements(unsigned num)
+ {
+ $self->num_vertex_elements = num;
+ $self->pipe->set_vertex_elements($self->pipe,
+ $self->num_vertex_elements,
+ $self->vertex_elements);
+ }
+
+ /*
+ * Draw functions
+ */
+
+ void draw_arrays(unsigned mode, unsigned start, unsigned count) {
+ $self->pipe->draw_arrays($self->pipe, mode, start, count);
+ }
+
+ void draw_elements( struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+ {
+ $self->pipe->draw_elements($self->pipe,
+ indexBuffer,
+ indexSize,
+ mode, start, count);
+ }
+
+ void draw_range_elements( struct pipe_buffer *indexBuffer,
+ unsigned indexSize, unsigned minIndex, unsigned maxIndex,
+ unsigned mode, unsigned start, unsigned count)
+ {
+ $self->pipe->draw_range_elements($self->pipe,
+ indexBuffer,
+ indexSize, minIndex, maxIndex,
+ mode, start, count);
+ }
+
+ void draw_vertices(unsigned prim,
+ unsigned num_verts,
+ unsigned num_attribs,
+ const float *vertices)
+ {
+ struct pipe_context *pipe = $self->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_buffer *vbuf;
+ float *map;
+ unsigned size;
+
+ size = num_verts * num_attribs * 4 * sizeof(float);
+
+ vbuf = pipe_buffer_create(screen,
+ 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ size);
+ if(!vbuf)
+ goto error1;
+
+ map = pipe_buffer_map(screen, vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
+ if (!map)
+ goto error2;
+ memcpy(map, vertices, size);
+ pipe_buffer_unmap(screen, vbuf);
+
+ util_draw_vertex_buffer(pipe, vbuf, 0, prim, num_verts, num_attribs);
+
+error2:
+ pipe_buffer_reference(&vbuf, NULL);
+error1:
+ ;
+ }
+
+ void
+ flush(unsigned flags = 0) {
+ struct pipe_fence_handle *fence = NULL;
+ $self->pipe->flush($self->pipe, flags | PIPE_FLUSH_RENDER_CACHE, &fence);
+ if(fence) {
+ /* TODO: allow asynchronous operation */
+ $self->pipe->screen->fence_finish( $self->pipe->screen, fence, 0 );
+ $self->pipe->screen->fence_reference( $self->pipe->screen, &fence, NULL );
+ }
+ }
+
+ /*
+ * Surface functions
+ */
+
+ void surface_copy(struct st_surface *dst,
+ unsigned destx, unsigned desty,
+ struct st_surface *src,
+ unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+ {
+ struct pipe_surface *_dst = NULL;
+ struct pipe_surface *_src = NULL;
+
+ _dst = st_pipe_surface(dst, PIPE_BUFFER_USAGE_GPU_WRITE);
+ if(!_dst)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
+
+ _src = st_pipe_surface(src, PIPE_BUFFER_USAGE_GPU_READ);
+ if(!_src)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire source surface for reading");
+
+ $self->pipe->surface_copy($self->pipe, _dst, destx, desty, _src, srcx, srcy, width, height);
+
+ fail:
+ pipe_surface_reference(&_src, NULL);
+ pipe_surface_reference(&_dst, NULL);
+ }
+
+ void surface_fill(struct st_surface *dst,
+ unsigned x, unsigned y,
+ unsigned width, unsigned height,
+ unsigned value)
+ {
+ struct pipe_surface *_dst = NULL;
+
+ _dst = st_pipe_surface(dst, PIPE_BUFFER_USAGE_GPU_WRITE);
+ if(!_dst)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
+
+ $self->pipe->surface_fill($self->pipe, _dst, x, y, width, height, value);
+
+ fail:
+ pipe_surface_reference(&_dst, NULL);
+ }
+
+ void clear(unsigned buffers, const float *rgba, double depth = 0.0f,
+ unsigned stencil = 0)
+ {
+ $self->pipe->clear($self->pipe, buffers, rgba, depth, stencil);
+ }
+
+};
diff --git a/src/gallium/state_trackers/python/p_device.i b/src/gallium/state_trackers/python/p_device.i
new file mode 100644
index 0000000000..f16fe5b0ff
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_device.i
@@ -0,0 +1,130 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+%nodefaultctor st_device;
+%nodefaultdtor st_device;
+
+
+struct st_device {
+};
+
+%newobject st_device::texture_create;
+%newobject st_device::context_create;
+%newobject st_device::buffer_create;
+
+%extend st_device {
+
+ st_device(int hardware = 1) {
+ return st_device_create(hardware ? TRUE : FALSE);
+ }
+
+ ~st_device() {
+ st_device_destroy($self);
+ }
+
+ const char * get_name( void ) {
+ return $self->screen->get_name($self->screen);
+ }
+
+ const char * get_vendor( void ) {
+ return $self->screen->get_vendor($self->screen);
+ }
+
+ /**
+ * Query an integer-valued capability/parameter/limit
+ * \param param one of PIPE_CAP_x
+ */
+ int get_param( int param ) {
+ return $self->screen->get_param($self->screen, param);
+ }
+
+ /**
+ * Query a float-valued capability/parameter/limit
+ * \param param one of PIPE_CAP_x
+ */
+ float get_paramf( int param ) {
+ return $self->screen->get_paramf($self->screen, param);
+ }
+
+ /**
+ * Check if the given pipe_format is supported as a texture or
+ * drawing surface.
+ * \param type one of PIPE_TEXTURE, PIPE_SURFACE
+ */
+ int is_format_supported( enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags ) {
+ return $self->screen->is_format_supported( $self->screen,
+ format,
+ target,
+ tex_usage,
+ geom_flags );
+ }
+
+ struct st_context *
+ context_create(void) {
+ return st_context_create($self);
+ }
+
+ struct pipe_texture *
+ texture_create(
+ enum pipe_format format,
+ unsigned width,
+ unsigned height,
+ unsigned depth = 1,
+ unsigned last_level = 0,
+ enum pipe_texture_target target = PIPE_TEXTURE_2D,
+ unsigned tex_usage = 0
+ ) {
+ struct pipe_texture templat;
+ memset(&templat, 0, sizeof(templat));
+ templat.format = format;
+ pf_get_block(templat.format, &templat.block);
+ templat.width[0] = width;
+ templat.height[0] = height;
+ templat.depth[0] = depth;
+ templat.last_level = last_level;
+ templat.target = target;
+ templat.tex_usage = tex_usage;
+ return $self->screen->texture_create($self->screen, &templat);
+ }
+
+ struct pipe_buffer *
+ buffer_create(unsigned size, unsigned alignment = 0, unsigned usage = 0) {
+ return pipe_buffer_create($self->screen, alignment, usage, size);
+ }
+
+};
diff --git a/src/gallium/state_trackers/python/p_format.i b/src/gallium/state_trackers/python/p_format.i
new file mode 100644
index 0000000000..26fb12b387
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_format.i
@@ -0,0 +1,162 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+/*
+ * XXX: SWIG can't parse p_format.h, so we need to duplicate the relevant
+ * declarations here
+ */
+
+%{
+#include "pipe/p_format.h"
+%}
+
+enum pipe_format {
+ PIPE_FORMAT_NONE,
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_B8G8R8X8_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A2B10G10R10_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_I8_UNORM,
+ PIPE_FORMAT_A8L8_UNORM,
+ PIPE_FORMAT_L16_UNORM,
+ PIPE_FORMAT_YCBCR,
+ PIPE_FORMAT_YCBCR_REV,
+ PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z32_FLOAT,
+ PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_X8Z24_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_S8_UNORM,
+ PIPE_FORMAT_R64_FLOAT,
+ PIPE_FORMAT_R64G64_FLOAT,
+ PIPE_FORMAT_R64G64B64_FLOAT,
+ PIPE_FORMAT_R64G64B64A64_FLOAT,
+ PIPE_FORMAT_R32_FLOAT,
+ PIPE_FORMAT_R32G32_FLOAT,
+ PIPE_FORMAT_R32G32B32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_FORMAT_R32_UNORM,
+ PIPE_FORMAT_R32G32_UNORM,
+ PIPE_FORMAT_R32G32B32_UNORM,
+ PIPE_FORMAT_R32G32B32A32_UNORM,
+ PIPE_FORMAT_R32_USCALED,
+ PIPE_FORMAT_R32G32_USCALED,
+ PIPE_FORMAT_R32G32B32_USCALED,
+ PIPE_FORMAT_R32G32B32A32_USCALED,
+ PIPE_FORMAT_R32_SNORM,
+ PIPE_FORMAT_R32G32_SNORM,
+ PIPE_FORMAT_R32G32B32_SNORM,
+ PIPE_FORMAT_R32G32B32A32_SNORM,
+ PIPE_FORMAT_R32_SSCALED,
+ PIPE_FORMAT_R32G32_SSCALED,
+ PIPE_FORMAT_R32G32B32_SSCALED,
+ PIPE_FORMAT_R32G32B32A32_SSCALED,
+ PIPE_FORMAT_R16_UNORM,
+ PIPE_FORMAT_R16G16_UNORM,
+ PIPE_FORMAT_R16G16B16_UNORM,
+ PIPE_FORMAT_R16G16B16A16_UNORM,
+ PIPE_FORMAT_R16_USCALED,
+ PIPE_FORMAT_R16G16_USCALED,
+ PIPE_FORMAT_R16G16B16_USCALED,
+ PIPE_FORMAT_R16G16B16A16_USCALED,
+ PIPE_FORMAT_R16_SNORM,
+ PIPE_FORMAT_R16G16_SNORM,
+ PIPE_FORMAT_R16G16B16_SNORM,
+ PIPE_FORMAT_R16G16B16A16_SNORM,
+ PIPE_FORMAT_R16_SSCALED,
+ PIPE_FORMAT_R16G16_SSCALED,
+ PIPE_FORMAT_R16G16B16_SSCALED,
+ PIPE_FORMAT_R16G16B16A16_SSCALED,
+ PIPE_FORMAT_R8_UNORM,
+ PIPE_FORMAT_R8G8_UNORM,
+ PIPE_FORMAT_R8G8B8_UNORM,
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_R8G8B8X8_UNORM,
+ PIPE_FORMAT_R8_USCALED,
+ PIPE_FORMAT_R8G8_USCALED,
+ PIPE_FORMAT_R8G8B8_USCALED,
+ PIPE_FORMAT_R8G8B8A8_USCALED,
+ PIPE_FORMAT_R8G8B8X8_USCALED,
+ PIPE_FORMAT_R8_SNORM,
+ PIPE_FORMAT_R8G8_SNORM,
+ PIPE_FORMAT_R8G8B8_SNORM,
+ PIPE_FORMAT_R8G8B8A8_SNORM,
+ PIPE_FORMAT_R8G8B8X8_SNORM,
+ PIPE_FORMAT_B6G5R5_SNORM,
+ PIPE_FORMAT_A8B8G8R8_SNORM,
+ PIPE_FORMAT_X8B8G8R8_SNORM,
+ PIPE_FORMAT_R8_SSCALED,
+ PIPE_FORMAT_R8G8_SSCALED,
+ PIPE_FORMAT_R8G8B8_SSCALED,
+ PIPE_FORMAT_R8G8B8A8_SSCALED,
+ PIPE_FORMAT_R8G8B8X8_SSCALED,
+ PIPE_FORMAT_R32_FIXED,
+ PIPE_FORMAT_R32G32_FIXED,
+ PIPE_FORMAT_R32G32B32_FIXED,
+ PIPE_FORMAT_R32G32B32A32_FIXED,
+
+ PIPE_FORMAT_L8_SRGB,
+ PIPE_FORMAT_A8L8_SRGB,
+ PIPE_FORMAT_R8G8B8_SRGB,
+ PIPE_FORMAT_R8G8B8A8_SRGB,
+ PIPE_FORMAT_R8G8B8X8_SRGB,
+ PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_X8R8G8B8_SRGB,
+ PIPE_FORMAT_B8G8R8A8_SRGB,
+ PIPE_FORMAT_B8G8R8X8_SRGB,
+
+ PIPE_FORMAT_X8UB8UG8SR8S_NORM,
+ PIPE_FORMAT_B6UG5SR5S_NORM,
+
+ PIPE_FORMAT_DXT1_RGB,
+ PIPE_FORMAT_DXT1_RGBA,
+ PIPE_FORMAT_DXT3_RGBA,
+ PIPE_FORMAT_DXT5_RGBA,
+
+ PIPE_FORMAT_DXT1_SRGB,
+ PIPE_FORMAT_DXT1_SRGBA,
+ PIPE_FORMAT_DXT3_SRGBA,
+ PIPE_FORMAT_DXT5_SRGBA,
+};
+
+
+struct pipe_format_block
+{
+ unsigned size;
+ unsigned width;
+ unsigned height;
+};
+
diff --git a/src/gallium/state_trackers/python/p_state.i b/src/gallium/state_trackers/python/p_state.i
new file mode 100644
index 0000000000..90f157e0ab
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_state.i
@@ -0,0 +1,137 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+%module gallium;
+
+%ignore winsys;
+%ignore pipe_vertex_buffer::buffer;
+
+%include "pipe/p_compiler.h";
+%include "pipe/p_state.h";
+
+
+%array_class(struct pipe_stencil_state, StencilArray);
+
+
+%extend pipe_framebuffer_state {
+
+ pipe_framebuffer_state(void) {
+ return CALLOC_STRUCT(pipe_framebuffer_state);
+ }
+
+ ~pipe_framebuffer_state() {
+ unsigned index;
+ for(index = 0; index < PIPE_MAX_COLOR_BUFS; ++index)
+ pipe_surface_reference(&$self->cbufs[index], NULL);
+ pipe_surface_reference(&$self->zsbuf, NULL);
+ FREE($self);
+ }
+
+ void
+ set_cbuf(unsigned index, struct st_surface *surface)
+ {
+ struct pipe_surface *_surface = NULL;
+
+ if(index >= PIPE_MAX_COLOR_BUFS)
+ SWIG_exception(SWIG_ValueError, "index out of bounds");
+
+ if(surface) {
+ _surface = st_pipe_surface(surface, PIPE_BUFFER_USAGE_GPU_WRITE);
+ if(!_surface)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire surface for writing");
+ }
+
+ pipe_surface_reference(&$self->cbufs[index], _surface);
+
+ fail:
+ return;
+ }
+
+ void
+ set_zsbuf(struct st_surface *surface)
+ {
+ struct pipe_surface *_surface = NULL;
+
+ if(surface) {
+ _surface = st_pipe_surface(surface, PIPE_BUFFER_USAGE_GPU_WRITE);
+ if(!_surface)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire surface for writing");
+ }
+
+ pipe_surface_reference(&$self->zsbuf, _surface);
+
+ fail:
+ return;
+ }
+
+};
+
+
+%extend pipe_shader_state {
+
+ pipe_shader_state(const char *text, unsigned num_tokens = 1024) {
+ struct tgsi_token *tokens;
+ struct pipe_shader_state *shader;
+
+ tokens = MALLOC(num_tokens * sizeof(struct tgsi_token));
+ if(!tokens)
+ goto error1;
+
+ if(tgsi_text_translate(text, tokens, num_tokens ) != TRUE)
+ goto error2;
+
+ shader = CALLOC_STRUCT(pipe_shader_state);
+ if(!shader)
+ goto error3;
+
+ shader->tokens = tokens;
+
+ return shader;
+
+error3:
+error2:
+ FREE(tokens);
+error1:
+ return NULL;
+ }
+
+ ~pipe_shader_state() {
+ FREE((void*)$self->tokens);
+ FREE($self);
+ }
+
+ void dump(unsigned flags = 0) {
+ tgsi_dump($self->tokens, flags);
+ }
+}
diff --git a/src/gallium/state_trackers/python/p_texture.i b/src/gallium/state_trackers/python/p_texture.i
new file mode 100644
index 0000000000..1d513abf3c
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_texture.i
@@ -0,0 +1,450 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+%nodefaultctor pipe_texture;
+%nodefaultctor st_surface;
+%nodefaultctor pipe_buffer;
+
+%nodefaultdtor pipe_texture;
+%nodefaultdtor st_surface;
+%nodefaultdtor pipe_buffer;
+
+%ignore pipe_texture::screen;
+
+%immutable st_surface::texture;
+%immutable st_surface::face;
+%immutable st_surface::level;
+%immutable st_surface::zslice;
+
+%newobject pipe_texture::get_surface;
+
+
+%extend pipe_texture {
+
+ ~pipe_texture() {
+ struct pipe_texture *ptr = $self;
+ pipe_texture_reference(&ptr, NULL);
+ }
+
+ unsigned get_width(unsigned level=0) {
+ return $self->width[level];
+ }
+
+ unsigned get_height(unsigned level=0) {
+ return $self->height[level];
+ }
+
+ unsigned get_depth(unsigned level=0) {
+ return $self->depth[level];
+ }
+
+ unsigned get_nblocksx(unsigned level=0) {
+ return $self->nblocksx[level];
+ }
+
+ unsigned get_nblocksy(unsigned level=0) {
+ return $self->nblocksy[level];
+ }
+
+ /** Get a surface which is a "view" into a texture */
+ struct st_surface *
+ get_surface(unsigned face=0, unsigned level=0, unsigned zslice=0)
+ {
+ struct st_surface *surface;
+
+ if(face >= ($self->target == PIPE_TEXTURE_CUBE ? 6U : 1U))
+ SWIG_exception(SWIG_ValueError, "face out of bounds");
+ if(level > $self->last_level)
+ SWIG_exception(SWIG_ValueError, "level out of bounds");
+ if(zslice >= $self->depth[level])
+ SWIG_exception(SWIG_ValueError, "zslice out of bounds");
+
+ surface = CALLOC_STRUCT(st_surface);
+ if(!surface)
+ return NULL;
+
+ pipe_texture_reference(&surface->texture, $self);
+ surface->face = face;
+ surface->level = level;
+ surface->zslice = zslice;
+
+ return surface;
+
+ fail:
+ return NULL;
+ }
+
+};
+
+struct st_surface
+{
+ %immutable;
+
+ struct pipe_texture *texture;
+ unsigned face;
+ unsigned level;
+ unsigned zslice;
+
+};
+
+%extend st_surface {
+
+ %immutable;
+
+ unsigned format;
+ unsigned width;
+ unsigned height;
+ unsigned nblocksx;
+ unsigned nblocksy;
+
+ ~st_surface() {
+ pipe_texture_reference(&$self->texture, NULL);
+ FREE($self);
+ }
+
+ %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
+ void get_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, char **STRING, int *LENGTH)
+ {
+ struct pipe_texture *texture = $self->texture;
+ struct pipe_screen *screen = texture->screen;
+ struct pipe_transfer *transfer;
+ unsigned stride;
+
+ stride = pf_get_nblocksx(&texture->block, w) * texture->block.size;
+ *LENGTH = pf_get_nblocksy(&texture->block, h) * stride;
+ *STRING = (char *) malloc(*LENGTH);
+ if(!*STRING)
+ return;
+
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y, w, h);
+ if(transfer) {
+ pipe_get_tile_raw(transfer, 0, 0, w, h, *STRING, stride);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ %cstring_input_binary(const char *STRING, unsigned LENGTH);
+ void put_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, const char *STRING, unsigned LENGTH, unsigned stride = 0)
+ {
+ struct pipe_texture *texture = $self->texture;
+ struct pipe_screen *screen = texture->screen;
+ struct pipe_transfer *transfer;
+
+ if(stride == 0)
+ stride = pf_get_nblocksx(&texture->block, w) * texture->block.size;
+
+ if(LENGTH < pf_get_nblocksy(&texture->block, h) * stride)
+ SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size");
+
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_WRITE,
+ x, y, w, h);
+ if(!transfer)
+ SWIG_exception(SWIG_MemoryError, "couldn't initiate transfer");
+
+ pipe_put_tile_raw(transfer, 0, 0, w, h, STRING, stride);
+ screen->tex_transfer_destroy(transfer);
+
+ fail:
+ return;
+ }
+
+ void
+ get_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, float *rgba)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y, w, h);
+ if(transfer) {
+ pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ void
+ put_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_WRITE,
+ x, y, w, h);
+ if(transfer) {
+ pipe_put_tile_rgba(transfer, 0, 0, w, h, rgba);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
+ void
+ get_tile_rgba8(unsigned x, unsigned y, unsigned w, unsigned h, char **STRING, int *LENGTH)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ float *rgba;
+ unsigned char *rgba8;
+ unsigned i, j, k;
+
+ *LENGTH = 0;
+ *STRING = NULL;
+
+ if (!$self)
+ return;
+
+ *LENGTH = h*w*4;
+ *STRING = (char *) malloc(*LENGTH);
+ if(!*STRING)
+ return;
+
+ rgba = malloc(h*w*4*sizeof(float));
+ if(!rgba)
+ return;
+
+ rgba8 = (unsigned char *) *STRING;
+
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y,
+ w, h);
+ if(transfer) {
+ pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba);
+ for(j = 0; j < h; ++j) {
+ for(i = 0; i < w; ++i)
+ for(k = 0; k <4; ++k)
+ rgba8[j*w*4 + i*4 + k] = float_to_ubyte(rgba[j*w*4 + i*4 + k]);
+ }
+ screen->tex_transfer_destroy(transfer);
+ }
+
+ free(rgba);
+ }
+
+ void
+ get_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, unsigned *z)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y, w, h);
+ if(transfer) {
+ pipe_get_tile_z(transfer, 0, 0, w, h, z);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ void
+ put_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, const unsigned *z)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_WRITE,
+ x, y, w, h);
+ if(transfer) {
+ pipe_put_tile_z(transfer, 0, 0, w, h, z);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ void
+ sample_rgba(float *rgba) {
+ st_sample_surface($self, rgba);
+ }
+
+ unsigned
+ compare_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba, float tol = 0.0)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ float *rgba2;
+ const float *p1;
+ const float *p2;
+ unsigned i, j, n;
+
+ rgba2 = MALLOC(h*w*4*sizeof(float));
+ if(!rgba2)
+ return ~0;
+
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y, w, h);
+ if(!transfer) {
+ FREE(rgba2);
+ return ~0;
+ }
+
+ pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba2);
+ screen->tex_transfer_destroy(transfer);
+
+ p1 = rgba;
+ p2 = rgba2;
+ n = 0;
+ for(i = h*w; i; --i) {
+ unsigned differs = 0;
+ for(j = 4; j; --j) {
+ float delta = *p2++ - *p1++;
+ if (delta < -tol || delta > tol)
+ differs = 1;
+ }
+ n += differs;
+ }
+
+ FREE(rgba2);
+
+ return n;
+ }
+
+};
+
+%{
+ static enum pipe_format
+ st_surface_format_get(struct st_surface *surface)
+ {
+ return surface->texture->format;
+ }
+
+ static unsigned
+ st_surface_width_get(struct st_surface *surface)
+ {
+ return surface->texture->width[surface->level];
+ }
+
+ static unsigned
+ st_surface_height_get(struct st_surface *surface)
+ {
+ return surface->texture->height[surface->level];
+ }
+
+ static unsigned
+ st_surface_nblocksx_get(struct st_surface *surface)
+ {
+ return surface->texture->nblocksx[surface->level];
+ }
+
+ static unsigned
+ st_surface_nblocksy_get(struct st_surface *surface)
+ {
+ return surface->texture->nblocksy[surface->level];
+ }
+%}
+
+/* Avoid naming conflict with p_inlines.h's pipe_buffer_read/write */
+%rename(read) read_;
+%rename(write) write_;
+
+%extend pipe_buffer {
+
+ ~pipe_buffer() {
+ struct pipe_buffer *ptr = $self;
+ pipe_buffer_reference(&ptr, NULL);
+ }
+
+ unsigned __len__(void)
+ {
+ assert(p_atomic_read(&$self->reference.count) > 0);
+ return $self->size;
+ }
+
+ %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
+ void read_(char **STRING, int *LENGTH)
+ {
+ struct pipe_screen *screen = $self->screen;
+
+ assert(p_atomic_read(&$self->reference.count) > 0);
+
+ *LENGTH = $self->size;
+ *STRING = (char *) malloc($self->size);
+ if(!*STRING)
+ return;
+
+ pipe_buffer_read(screen, $self, 0, $self->size, *STRING);
+ }
+
+ %cstring_input_binary(const char *STRING, unsigned LENGTH);
+ void write_(const char *STRING, unsigned LENGTH, unsigned offset = 0)
+ {
+ struct pipe_screen *screen = $self->screen;
+
+ assert(p_atomic_read(&$self->reference.count) > 0);
+
+ if(offset > $self->size)
+ SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size");
+
+ if(offset + LENGTH > $self->size)
+ SWIG_exception(SWIG_ValueError, "data length must fit inside the buffer");
+
+ pipe_buffer_write(screen, $self, offset, LENGTH, STRING);
+
+fail:
+ return;
+ }
+};
diff --git a/src/gallium/state_trackers/python/retrace/README b/src/gallium/state_trackers/python/retrace/README
new file mode 100644
index 0000000000..822cd11404
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/README
@@ -0,0 +1,17 @@
+This is an application written in python to replay the traces captured by the
+ trace pipe driver.
+
+
+To use it follow the instructions in src/gallium/drivers/trace/README and
+src/gallium/state_trackers/python/README, and then do
+
+ python src/gallium/state_trackers/python/samples/retrace/interpreter.py filename.trace
+
+
+This is still work in progress:
+- not everything is captured/replayed
+ - surface/textures contents
+- any tiny error will result in a crash
+
+--
+Jose Fonseca <jrfonseca@tungstengraphics.com>
diff --git a/src/gallium/state_trackers/python/retrace/format.py b/src/gallium/state_trackers/python/retrace/format.py
new file mode 100755
index 0000000000..a4285bfe07
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/format.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+import sys
+
+
+class Formatter:
+ '''Plain formatter'''
+
+ def __init__(self, stream):
+ self.stream = stream
+
+ def text(self, text):
+ self.stream.write(text)
+
+ def newline(self):
+ self.text('\n')
+
+ def function(self, name):
+ self.text(name)
+
+ def variable(self, name):
+ self.text(name)
+
+ def literal(self, value):
+ self.text(str(value))
+
+ def address(self, addr):
+ self.text(str(addr))
+
+
+class AnsiFormatter(Formatter):
+ '''Formatter for plain-text files which outputs ANSI escape codes. See
+ http://en.wikipedia.org/wiki/ANSI_escape_code for more information
+ concerning ANSI escape codes.
+ '''
+
+ _csi = '\33['
+
+ _normal = '0m'
+ _bold = '1m'
+ _italic = '3m'
+ _red = '31m'
+ _green = '32m'
+ _blue = '34m'
+
+ def _escape(self, code):
+ self.text(self._csi + code)
+
+ def function(self, name):
+ self._escape(self._bold)
+ Formatter.function(self, name)
+ self._escape(self._normal)
+
+ def variable(self, name):
+ self._escape(self._italic)
+ Formatter.variable(self, name)
+ self._escape(self._normal)
+
+ def literal(self, value):
+ self._escape(self._blue)
+ Formatter.literal(self, value)
+ self._escape(self._normal)
+
+ def address(self, value):
+ self._escape(self._green)
+ Formatter.address(self, value)
+ self._escape(self._normal)
+
+
+class WindowsConsoleFormatter(Formatter):
+ '''Formatter for the Windows Console. See
+ http://code.activestate.com/recipes/496901/ for more information.
+ '''
+
+ STD_INPUT_HANDLE = -10
+ STD_OUTPUT_HANDLE = -11
+ STD_ERROR_HANDLE = -12
+
+ FOREGROUND_BLUE = 0x01
+ FOREGROUND_GREEN = 0x02
+ FOREGROUND_RED = 0x04
+ FOREGROUND_INTENSITY = 0x08
+ BACKGROUND_BLUE = 0x10
+ BACKGROUND_GREEN = 0x20
+ BACKGROUND_RED = 0x40
+ BACKGROUND_INTENSITY = 0x80
+
+ _normal = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
+ _bold = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
+ _italic = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
+ _red = FOREGROUND_RED | FOREGROUND_INTENSITY
+ _green = FOREGROUND_GREEN | FOREGROUND_INTENSITY
+ _blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY
+
+ def __init__(self, stream):
+ Formatter.__init__(self, stream)
+
+ if stream is sys.stdin:
+ nStdHandle = self.STD_INPUT_HANDLE
+ elif stream is sys.stdout:
+ nStdHandle = self.STD_OUTPUT_HANDLE
+ elif stream is sys.stderr:
+ nStdHandle = self.STD_ERROR_HANDLE
+ else:
+ nStdHandle = None
+
+ if nStdHandle:
+ import ctypes
+ self.handle = ctypes.windll.kernel32.GetStdHandle(nStdHandle)
+ else:
+ self.handle = None
+
+ def _attribute(self, attr):
+ if self.handle:
+ import ctypes
+ ctypes.windll.kernel32.SetConsoleTextAttribute(self.handle, attr)
+
+ def function(self, name):
+ self._attribute(self._bold)
+ Formatter.function(self, name)
+ self._attribute(self._normal)
+
+ def variable(self, name):
+ self._attribute(self._italic)
+ Formatter.variable(self, name)
+ self._attribute(self._normal)
+
+ def literal(self, value):
+ self._attribute(self._blue)
+ Formatter.literal(self, value)
+ self._attribute(self._normal)
+
+ def address(self, value):
+ self._attribute(self._green)
+ Formatter.address(self, value)
+ self._attribute(self._normal)
+
+
+def DefaultFormatter(stream):
+ if sys.platform in ('linux2', 'cygwin'):
+ return AnsiFormatter(stream)
+ elif sys.platform in ('win32',):
+ return WindowsConsoleFormatter(stream)
+ else:
+ return Formatter(stream)
+
diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py
new file mode 100755
index 0000000000..6f0bd6ae52
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/interpreter.py
@@ -0,0 +1,748 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+import sys
+import struct
+
+import gallium
+import model
+import parse as parser
+
+
+try:
+ from struct import unpack_from
+except ImportError:
+ def unpack_from(fmt, buf, offset=0):
+ size = struct.calcsize(fmt)
+ return struct.unpack(fmt, buf[offset:offset + size])
+
+
+def make_image(surface, x=None, y=None, w=None, h=None):
+ if x is None:
+ x = 0
+ if y is None:
+ y = 0
+ if w is None:
+ w = surface.width - x
+ if h is None:
+ h = surface.height - y
+ data = surface.get_tile_rgba8(0, 0, surface.width, surface.height)
+
+ import Image
+ outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1)
+ return outimage
+
+def save_image(filename, surface, x=None, y=None, w=None, h=None):
+ outimage = make_image(surface, x, y, w, h)
+ outimage.save(filename, "PNG")
+
+def show_image(surface, title, x=None, y=None, w=None, h=None):
+ outimage = make_image(surface, x, y, w, h)
+
+ import Tkinter as tk
+ from PIL import Image, ImageTk
+ root = tk.Tk()
+
+ root.title(title)
+
+ image1 = ImageTk.PhotoImage(outimage)
+ w = image1.width()
+ h = image1.height()
+ x = 100
+ y = 100
+ root.geometry("%dx%d+%d+%d" % (w, h, x, y))
+ panel1 = tk.Label(root, image=image1)
+ panel1.pack(side='top', fill='both', expand='yes')
+ panel1.image = image1
+ root.mainloop()
+
+
+class Struct:
+ """C-like struct"""
+
+ # A basic Python class can pass as a C-like structure
+ pass
+
+
+struct_factories = {
+ "pipe_blend_color": gallium.BlendColor,
+ "pipe_blend_state": gallium.Blend,
+ #"pipe_clip_state": gallium.Clip,
+ #"pipe_constant_buffer": gallium.ConstantBuffer,
+ "pipe_depth_state": gallium.Depth,
+ "pipe_stencil_state": gallium.Stencil,
+ "pipe_alpha_state": gallium.Alpha,
+ "pipe_depth_stencil_alpha_state": gallium.DepthStencilAlpha,
+ "pipe_format_block": gallium.FormatBlock,
+ #"pipe_framebuffer_state": gallium.Framebuffer,
+ "pipe_poly_stipple": gallium.PolyStipple,
+ "pipe_rasterizer_state": gallium.Rasterizer,
+ "pipe_sampler_state": gallium.Sampler,
+ "pipe_scissor_state": gallium.Scissor,
+ #"pipe_shader_state": gallium.Shader,
+ #"pipe_vertex_buffer": gallium.VertexBuffer,
+ "pipe_vertex_element": gallium.VertexElement,
+ "pipe_viewport_state": gallium.Viewport,
+ #"pipe_texture": gallium.Texture,
+}
+
+
+member_array_factories = {
+ "pipe_rasterizer_state": {"sprite_coord_mode": gallium.ByteArray},
+ "pipe_poly_stipple": {"stipple": gallium.UnsignedArray},
+ "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray},
+ #"pipe_clip_state": {"ucp": gallium.FloatArray},
+ "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray},
+ "pipe_blend_color": {"color": gallium.FloatArray},
+ "pipe_sampler_state": {"border_color": gallium.FloatArray},
+}
+
+
+class Translator(model.Visitor):
+ """Translate model arguments into regular Python objects"""
+
+ def __init__(self, interpreter):
+ self.interpreter = interpreter
+ self.result = None
+
+ def visit(self, node):
+ self.result = None
+ node.visit(self)
+ return self.result
+
+ def visit_literal(self, node):
+ self.result = node.value
+
+ def visit_named_constant(self, node):
+ # lookup the named constant in the gallium module
+ self.result = getattr(gallium, node.name)
+
+ def visit_array(self, node):
+ array = []
+ for element in node.elements:
+ array.append(self.visit(element))
+ self.result = array
+
+ def visit_struct(self, node):
+ struct_factory = struct_factories.get(node.name, Struct)
+ struct = struct_factory()
+ for member_name, member_node in node.members:
+ member_value = self.visit(member_node)
+ try:
+ array_factory = member_array_factories[node.name][member_name]
+ except KeyError:
+ pass
+ else:
+ assert isinstance(member_value, list)
+ array = array_factory(len(member_value))
+ for i in range(len(member_value)):
+ array[i] = member_value[i]
+ member_value = array
+ #print node.name, member_name, member_value
+ assert isinstance(struct, Struct) or hasattr(struct, member_name)
+ setattr(struct, member_name, member_value)
+ self.result = struct
+
+ def visit_pointer(self, node):
+ self.result = self.interpreter.lookup_object(node.address)
+
+
+class Object:
+
+ def __init__(self, interpreter, real):
+ self.interpreter = interpreter
+ self.real = real
+
+
+class Global(Object):
+
+ def __init__(self, interpreter, real):
+ self.interpreter = interpreter
+ self.real = real
+
+ def pipe_winsys_create(self):
+ return Winsys(self.interpreter, gallium.Device())
+
+ def pipe_screen_create(self, winsys=None):
+ if winsys is None:
+ real = gallium.Device()
+ else:
+ real = winsys.real
+ return Screen(self.interpreter, real)
+
+ def pipe_context_create(self, screen):
+ context = screen.real.context_create()
+ return Context(self.interpreter, context)
+
+
+class Winsys(Object):
+
+ def __init__(self, interpreter, real):
+ self.interpreter = interpreter
+ self.real = real
+
+ def get_name(self):
+ pass
+
+ def user_buffer_create(self, data, size):
+ # We don't really care to distinguish between user and regular buffers
+ buffer = self.real.buffer_create(size,
+ 4,
+ gallium.PIPE_BUFFER_USAGE_CPU_READ |
+ gallium.PIPE_BUFFER_USAGE_CPU_WRITE )
+ assert size == len(data)
+ buffer.write(data)
+ return buffer
+
+ def buffer_create(self, alignment, usage, size):
+ return self.real.buffer_create(size, alignment, usage)
+
+ def buffer_destroy(self, buffer):
+ pass
+
+ def buffer_write(self, buffer, data, size):
+ assert size == len(data)
+ buffer.write(data)
+
+ def fence_finish(self, fence, flags):
+ pass
+
+ def fence_reference(self, dst, src):
+ pass
+
+ def flush_frontbuffer(self, surface):
+ pass
+
+ def surface_alloc(self):
+ return None
+
+ def surface_release(self, surface):
+ pass
+
+
+class Transfer:
+
+ def __init__(self, surface, x, y, w, h):
+ self.surface = surface
+ self.x = x
+ self.y = y
+ self.w = w
+ self.h = h
+
+
+class Screen(Object):
+
+ def destroy(self):
+ pass
+
+ def get_name(self):
+ pass
+
+ def get_vendor(self):
+ pass
+
+ def get_param(self, param):
+ pass
+
+ def get_paramf(self, param):
+ pass
+
+ def is_format_supported(self, format, target, tex_usage, geom_flags):
+ return self.real.is_format_supported(format, target, tex_usage, geom_flags)
+
+ def texture_create(self, templat):
+ return self.real.texture_create(
+ format = templat.format,
+ width = templat.width[0],
+ height = templat.height[0],
+ depth = templat.depth[0],
+ last_level = templat.last_level,
+ target = templat.target,
+ tex_usage = templat.tex_usage,
+ )
+
+ def texture_destroy(self, texture):
+ self.interpreter.unregister_object(texture)
+
+ def texture_release(self, surface):
+ pass
+
+ def get_tex_surface(self, texture, face, level, zslice, usage):
+ if texture is None:
+ return None
+ return texture.get_surface(face, level, zslice)
+
+ def tex_surface_destroy(self, surface):
+ self.interpreter.unregister_object(surface)
+
+ def tex_surface_release(self, surface):
+ pass
+
+ def surface_write(self, surface, data, stride, size):
+ if surface is None:
+ return
+ assert surface.nblocksy * stride == size
+ surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride)
+
+ def get_tex_transfer(self, texture, face, level, zslice, usage, x, y, w, h):
+ if texture is None:
+ return None
+ transfer = Transfer(texture.get_surface(face, level, zslice), x, y, w, h)
+ if transfer and usage != gallium.PIPE_TRANSFER_WRITE:
+ if self.interpreter.options.all:
+ self.interpreter.present(transfer.surface, 'transf_read', x, y, w, h)
+ return transfer
+
+ def tex_transfer_destroy(self, transfer):
+ self.interpreter.unregister_object(transfer)
+
+ def transfer_write(self, transfer, stride, data, size):
+ if transfer is None:
+ return
+ transfer.surface.put_tile_raw(transfer.x, transfer.y, transfer.w, transfer.h, data, stride)
+ if self.interpreter.options.all:
+ self.interpreter.present(transfer.surface, 'transf_write', transfer.x, transfer.y, transfer.w, transfer.h)
+
+ def user_buffer_create(self, data, size):
+ # We don't really care to distinguish between user and regular buffers
+ buffer = self.real.buffer_create(size,
+ 4,
+ gallium.PIPE_BUFFER_USAGE_CPU_READ |
+ gallium.PIPE_BUFFER_USAGE_CPU_WRITE )
+ assert size == len(data)
+ buffer.write(data)
+ return buffer
+
+ def buffer_create(self, alignment, usage, size):
+ return self.real.buffer_create(size, alignment, usage)
+
+ def buffer_destroy(self, buffer):
+ pass
+
+ def buffer_write(self, buffer, data, size, offset=0):
+ assert size == len(data)
+ buffer.write(data)
+
+ def fence_finish(self, fence, flags):
+ pass
+
+ def fence_reference(self, dst, src):
+ pass
+
+ def flush_frontbuffer(self, surface):
+ pass
+
+
+class Context(Object):
+
+ def __init__(self, interpreter, real):
+ Object.__init__(self, interpreter, real)
+ self.cbufs = []
+ self.zsbuf = None
+ self.vbufs = []
+ self.velems = []
+ self.dirty = False
+
+ def destroy(self):
+ pass
+
+ def create_blend_state(self, state):
+ return state
+
+ def bind_blend_state(self, state):
+ if state is not None:
+ self.real.set_blend(state)
+
+ def delete_blend_state(self, state):
+ pass
+
+ def create_sampler_state(self, state):
+ return state
+
+ def delete_sampler_state(self, state):
+ pass
+
+ def bind_sampler_states(self, num_states, states):
+ for i in range(num_states):
+ self.real.set_sampler(i, states[i])
+
+ def create_rasterizer_state(self, state):
+ return state
+
+ def bind_rasterizer_state(self, state):
+ if state is not None:
+ self.real.set_rasterizer(state)
+
+ def delete_rasterizer_state(self, state):
+ pass
+
+ def create_depth_stencil_alpha_state(self, state):
+ return state
+
+ def bind_depth_stencil_alpha_state(self, state):
+ if state is not None:
+ self.real.set_depth_stencil_alpha(state)
+
+ def delete_depth_stencil_alpha_state(self, state):
+ pass
+
+ def create_fs_state(self, state):
+ tokens = str(state.tokens)
+ shader = gallium.Shader(tokens)
+ return shader
+
+ create_vs_state = create_fs_state
+
+ def bind_fs_state(self, state):
+ self.real.set_fragment_shader(state)
+
+ def bind_vs_state(self, state):
+ self.real.set_vertex_shader(state)
+
+ def delete_fs_state(self, state):
+ pass
+
+ delete_vs_state = delete_fs_state
+
+ def set_blend_color(self, state):
+ self.real.set_blend_color(state)
+
+ def set_clip_state(self, state):
+ _state = gallium.Clip()
+ _state.nr = state.nr
+ if state.nr:
+ # FIXME
+ ucp = gallium.FloatArray(gallium.PIPE_MAX_CLIP_PLANES*4)
+ for i in range(len(state.ucp)):
+ for j in range(len(state.ucp[i])):
+ ucp[i*4 + j] = state.ucp[i][j]
+ _state.ucp = ucp
+ self.real.set_clip(_state)
+
+ def dump_constant_buffer(self, buffer):
+ if not self.interpreter.verbosity(2):
+ return
+
+ data = buffer.read()
+ format = '4f'
+ index = 0
+ for offset in range(0, len(data), struct.calcsize(format)):
+ x, y, z, w = unpack_from(format, data, offset)
+ sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w))
+ index += 1
+ sys.stdout.flush()
+
+ def set_constant_buffer(self, shader, index, buffer):
+ if buffer is not None:
+ self.real.set_constant_buffer(shader, index, buffer.buffer)
+
+ self.dump_constant_buffer(buffer.buffer)
+
+ def set_framebuffer_state(self, state):
+ _state = gallium.Framebuffer()
+ _state.width = state.width
+ _state.height = state.height
+ _state.nr_cbufs = state.nr_cbufs
+ for i in range(len(state.cbufs)):
+ _state.set_cbuf(i, state.cbufs[i])
+ _state.set_zsbuf(state.zsbuf)
+ self.real.set_framebuffer(_state)
+
+ self.cbufs = state.cbufs
+ self.zsbuf = state.zsbuf
+
+ def set_polygon_stipple(self, state):
+ self.real.set_polygon_stipple(state)
+
+ def set_scissor_state(self, state):
+ self.real.set_scissor(state)
+
+ def set_viewport_state(self, state):
+ self.real.set_viewport(state)
+
+ def set_sampler_textures(self, num_textures, textures):
+ for i in range(num_textures):
+ self.real.set_sampler_texture(i, textures[i])
+
+ def set_vertex_buffers(self, num_buffers, buffers):
+ self.vbufs = buffers[0:num_buffers]
+ for i in range(num_buffers):
+ vbuf = buffers[i]
+ self.real.set_vertex_buffer(
+ i,
+ stride = vbuf.stride,
+ max_index = vbuf.max_index,
+ buffer_offset = vbuf.buffer_offset,
+ buffer = vbuf.buffer,
+ )
+
+ def set_vertex_elements(self, num_elements, elements):
+ self.velems = elements[0:num_elements]
+ for i in range(num_elements):
+ self.real.set_vertex_element(i, elements[i])
+ self.real.set_vertex_elements(num_elements)
+
+ def set_edgeflags(self, bitfield):
+ # FIXME
+ pass
+
+ def dump_vertices(self, start, count):
+ if not self.interpreter.verbosity(2):
+ return
+
+ for index in range(start, start + count):
+ if index >= start + 16:
+ sys.stdout.write('\t...\n')
+ break
+ sys.stdout.write('\t{\n')
+ for velem in self.velems:
+ vbuf = self.vbufs[velem.vertex_buffer_index]
+
+ offset = vbuf.buffer_offset + velem.src_offset + vbuf.stride*index
+ format = {
+ gallium.PIPE_FORMAT_R32_FLOAT: 'f',
+ gallium.PIPE_FORMAT_R32G32_FLOAT: '2f',
+ gallium.PIPE_FORMAT_R32G32B32_FLOAT: '3f',
+ gallium.PIPE_FORMAT_R32G32B32A32_FLOAT: '4f',
+ gallium.PIPE_FORMAT_B8G8R8A8_UNORM: '4B',
+ }[velem.src_format]
+
+ data = vbuf.buffer.read()
+ values = unpack_from(format, data, offset)
+ sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n')
+ assert len(values) == velem.nr_components
+ sys.stdout.write('\t},\n')
+ sys.stdout.flush()
+
+ def dump_indices(self, ibuf, isize, start, count):
+ if not self.interpreter.verbosity(2):
+ return
+
+ format = {
+ 1: 'B',
+ 2: 'H',
+ 4: 'I',
+ }[isize]
+
+ assert struct.calcsize(format) == isize
+
+ data = ibuf.read()
+ maxindex, minindex = 0, 0xffffffff
+
+ sys.stdout.write('\t{\n')
+ for i in range(start, start + count):
+ if i >= start + 16:
+ sys.stdout.write('\t...\n')
+ break
+ offset = i*isize
+ index, = unpack_from(format, data, offset)
+ sys.stdout.write('\t\t%u,\n' % index)
+ minindex = min(minindex, index)
+ maxindex = max(maxindex, index)
+ sys.stdout.write('\t},\n')
+ sys.stdout.flush()
+
+ return minindex, maxindex
+
+ def draw_arrays(self, mode, start, count):
+ self.dump_vertices(start, count)
+
+ self.real.draw_arrays(mode, start, count)
+ self._set_dirty()
+
+ def draw_elements(self, indexBuffer, indexSize, mode, start, count):
+ if self.interpreter.verbosity(2):
+ minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count)
+ self.dump_vertices(minindex, maxindex - minindex)
+
+ self.real.draw_elements(indexBuffer, indexSize, mode, start, count)
+ self._set_dirty()
+
+ def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count):
+ if self.interpreter.verbosity(2):
+ minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count)
+ minindex = min(minindex, minIndex)
+ maxindex = min(maxindex, maxIndex)
+ self.dump_vertices(minindex, maxindex - minindex)
+
+ self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count)
+ self._set_dirty()
+
+ def surface_copy(self, dest, destx, desty, src, srcx, srcy, width, height):
+ if dest is not None and src is not None:
+ if self.interpreter.options.all:
+ self.interpreter.present(src, 'surface_copy_src', srcx, srcy, width, height)
+ self.real.surface_copy(dest, destx, desty, src, srcx, srcy, width, height)
+ if dest in self.cbufs:
+ self._set_dirty()
+ flags = gallium.PIPE_FLUSH_FRAME
+ else:
+ flags = 0
+ self.flush(flags)
+ if self.interpreter.options.all:
+ self.interpreter.present(dest, 'surface_copy_dest', destx, desty, width, height)
+
+ def is_texture_referenced(self, texture, face, level):
+ #return self.real.is_texture_referenced(format, texture, face, level)
+ pass
+
+ def is_buffer_referenced(self, buf):
+ #return self.real.is_buffer_referenced(format, buf)
+ pass
+
+ def _set_dirty(self):
+ if self.interpreter.options.step:
+ self._present()
+ else:
+ self.dirty = True
+
+ def flush(self, flags):
+ self.real.flush(flags)
+ if self.dirty:
+ if flags & gallium.PIPE_FLUSH_FRAME:
+ self._present()
+ self.dirty = False
+ return None
+
+ def clear(self, buffers, rgba, depth, stencil):
+ _rgba = gallium.FloatArray(4)
+ for i in range(4):
+ _rgba[i] = rgba[i]
+ self.real.clear(buffers, _rgba, depth, stencil)
+
+ def _present(self):
+ self.real.flush()
+
+ if self.cbufs and self.cbufs[0]:
+ self.interpreter.present(self.cbufs[0], "cbuf")
+ if self.zsbuf:
+ if self.interpreter.options.all:
+ self.interpreter.present(self.zsbuf, "zsbuf")
+
+
+class Interpreter(parser.TraceDumper):
+
+ ignore_calls = set((
+ ('pipe_screen', 'is_format_supported'),
+ ('pipe_screen', 'get_param'),
+ ('pipe_screen', 'get_paramf'),
+ ))
+
+ def __init__(self, stream, options):
+ parser.TraceDumper.__init__(self, stream)
+ self.options = options
+ self.objects = {}
+ self.result = None
+ self.globl = Global(self, None)
+ self.call_no = None
+
+ def register_object(self, address, object):
+ self.objects[address] = object
+
+ def unregister_object(self, object):
+ # FIXME:
+ pass
+
+ def lookup_object(self, address):
+ return self.objects[address]
+
+ def interpret(self, trace):
+ for call in trace.calls:
+ self.interpret_call(call)
+
+ def handle_call(self, call):
+ if self.options.stop and call.no > self.options.stop:
+ sys.exit(0)
+
+ if (call.klass, call.method) in self.ignore_calls:
+ return
+
+ self.call_no = call.no
+
+ if self.verbosity(1):
+ parser.TraceDumper.handle_call(self, call)
+ sys.stdout.flush()
+
+ args = [(str(name), self.interpret_arg(arg)) for name, arg in call.args]
+
+ if call.klass:
+ name, obj = args[0]
+ args = args[1:]
+ else:
+ obj = self.globl
+
+ method = getattr(obj, call.method)
+ ret = method(**dict(args))
+
+ if call.ret and isinstance(call.ret, model.Pointer):
+ if ret is None:
+ sys.stderr.write('warning: NULL returned\n')
+ self.register_object(call.ret.address, ret)
+
+ self.call_no = None
+
+ def interpret_arg(self, node):
+ translator = Translator(self)
+ return translator.visit(node)
+
+ def verbosity(self, level):
+ return self.options.verbosity >= level
+
+ def present(self, surface, description, x=None, y=None, w=None, h=None):
+ if self.call_no < self.options.start:
+ return
+
+ if self.options.images:
+ filename = '%04u_%s.png' % (self.call_no, description)
+ save_image(filename, surface, x, y, w, h)
+ else:
+ title = '%u. %s' % (self.call_no, description)
+ show_image(surface, title, x, y, w, h)
+
+
+class Main(parser.Main):
+
+ def get_optparser(self):
+ optparser = parser.Main.get_optparser(self)
+ optparser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages")
+ optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=1, help="increase verbosity level")
+ optparser.add_option("-i", "--images", action="store_true", dest="images", default=False, help="save images instead of showing them")
+ optparser.add_option("-a", "--all", action="store_true", dest="all", default=False, help="show depth, stencil, and transfers")
+ optparser.add_option("-s", "--step", action="store_true", dest="step", default=False, help="step trhough every draw")
+ optparser.add_option("-f", "--from", action="store", type="int", dest="start", default=0, help="from call no")
+ optparser.add_option("-t", "--to", action="store", type="int", dest="stop", default=0, help="until call no")
+ return optparser
+
+ def process_arg(self, stream, options):
+ parser = Interpreter(stream, options)
+ parser.parse()
+
+
+if __name__ == '__main__':
+ Main().main()
diff --git a/src/gallium/state_trackers/python/retrace/model.py b/src/gallium/state_trackers/python/retrace/model.py
new file mode 100755
index 0000000000..d4a079fb1e
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/model.py
@@ -0,0 +1,213 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+'''Trace data model.'''
+
+
+import sys
+import string
+import format
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+
+class Node:
+
+ def visit(self, visitor):
+ raise NotImplementedError
+
+ def __str__(self):
+ stream = StringIO()
+ formatter = format.DefaultFormatter(stream)
+ pretty_printer = PrettyPrinter(formatter)
+ self.visit(pretty_printer)
+ return stream.getvalue()
+
+
+class Literal(Node):
+
+ def __init__(self, value):
+ self.value = value
+
+ def visit(self, visitor):
+ visitor.visit_literal(self)
+
+
+class NamedConstant(Node):
+
+ def __init__(self, name):
+ self.name = name
+
+ def visit(self, visitor):
+ visitor.visit_named_constant(self)
+
+
+class Array(Node):
+
+ def __init__(self, elements):
+ self.elements = elements
+
+ def visit(self, visitor):
+ visitor.visit_array(self)
+
+
+class Struct(Node):
+
+ def __init__(self, name, members):
+ self.name = name
+ self.members = members
+
+ def visit(self, visitor):
+ visitor.visit_struct(self)
+
+
+class Pointer(Node):
+
+ def __init__(self, address):
+ self.address = address
+
+ def visit(self, visitor):
+ visitor.visit_pointer(self)
+
+
+class Call:
+
+ def __init__(self, no, klass, method, args, ret):
+ self.no = no
+ self.klass = klass
+ self.method = method
+ self.args = args
+ self.ret = ret
+
+ def visit(self, visitor):
+ visitor.visit_call(self)
+
+
+class Trace:
+
+ def __init__(self, calls):
+ self.calls = calls
+
+ def visit(self, visitor):
+ visitor.visit_trace(self)
+
+
+class Visitor:
+
+ def visit_literal(self, node):
+ raise NotImplementedError
+
+ def visit_named_constant(self, node):
+ raise NotImplementedError
+
+ def visit_array(self, node):
+ raise NotImplementedError
+
+ def visit_struct(self, node):
+ raise NotImplementedError
+
+ def visit_pointer(self, node):
+ raise NotImplementedError
+
+ def visit_call(self, node):
+ raise NotImplementedError
+
+ def visit_trace(self, node):
+ raise NotImplementedError
+
+
+class PrettyPrinter:
+
+ def __init__(self, formatter):
+ self.formatter = formatter
+
+ def visit_literal(self, node):
+ if isinstance(node.value, basestring):
+ if len(node.value) >= 4096 or node.value.strip(string.printable):
+ self.formatter.text('...')
+ return
+
+ self.formatter.literal('"' + node.value + '"')
+ return
+
+ self.formatter.literal(repr(node.value))
+
+ def visit_named_constant(self, node):
+ self.formatter.literal(node.name)
+
+ def visit_array(self, node):
+ self.formatter.text('{')
+ sep = ''
+ for value in node.elements:
+ self.formatter.text(sep)
+ value.visit(self)
+ sep = ', '
+ self.formatter.text('}')
+
+ def visit_struct(self, node):
+ self.formatter.text('{')
+ sep = ''
+ for name, value in node.members:
+ self.formatter.text(sep)
+ self.formatter.variable(name)
+ self.formatter.text(' = ')
+ value.visit(self)
+ sep = ', '
+ self.formatter.text('}')
+
+ def visit_pointer(self, node):
+ self.formatter.address(node.address)
+
+ def visit_call(self, node):
+ self.formatter.text('%s ' % node.no)
+ if node.klass is not None:
+ self.formatter.function(node.klass + '::' + node.method)
+ else:
+ self.formatter.function(node.method)
+ self.formatter.text('(')
+ sep = ''
+ for name, value in node.args:
+ self.formatter.text(sep)
+ self.formatter.variable(name)
+ self.formatter.text(' = ')
+ value.visit(self)
+ sep = ', '
+ self.formatter.text(')')
+ if node.ret is not None:
+ self.formatter.text(' = ')
+ node.ret.visit(self)
+
+ def visit_trace(self, node):
+ for call in node.calls:
+ call.visit(self)
+ self.formatter.newline()
+
diff --git a/src/gallium/state_trackers/python/retrace/parse.py b/src/gallium/state_trackers/python/retrace/parse.py
new file mode 100755
index 0000000000..b08d368671
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/parse.py
@@ -0,0 +1,392 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+import sys
+import xml.parsers.expat
+import binascii
+import optparse
+
+from model import *
+
+
+ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4)
+
+
+class XmlToken:
+
+ def __init__(self, type, name_or_data, attrs = None, line = None, column = None):
+ assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF)
+ self.type = type
+ self.name_or_data = name_or_data
+ self.attrs = attrs
+ self.line = line
+ self.column = column
+
+ def __str__(self):
+ if self.type == ELEMENT_START:
+ return '<' + self.name_or_data + ' ...>'
+ if self.type == ELEMENT_END:
+ return '</' + self.name_or_data + '>'
+ if self.type == CHARACTER_DATA:
+ return self.name_or_data
+ if self.type == EOF:
+ return 'end of file'
+ assert 0
+
+
+class XmlTokenizer:
+ """Expat based XML tokenizer."""
+
+ def __init__(self, fp, skip_ws = True):
+ self.fp = fp
+ self.tokens = []
+ self.index = 0
+ self.final = False
+ self.skip_ws = skip_ws
+
+ self.character_pos = 0, 0
+ self.character_data = ''
+
+ self.parser = xml.parsers.expat.ParserCreate()
+ self.parser.StartElementHandler = self.handle_element_start
+ self.parser.EndElementHandler = self.handle_element_end
+ self.parser.CharacterDataHandler = self.handle_character_data
+
+ def handle_element_start(self, name, attributes):
+ self.finish_character_data()
+ line, column = self.pos()
+ token = XmlToken(ELEMENT_START, name, attributes, line, column)
+ self.tokens.append(token)
+
+ def handle_element_end(self, name):
+ self.finish_character_data()
+ line, column = self.pos()
+ token = XmlToken(ELEMENT_END, name, None, line, column)
+ self.tokens.append(token)
+
+ def handle_character_data(self, data):
+ if not self.character_data:
+ self.character_pos = self.pos()
+ self.character_data += data
+
+ def finish_character_data(self):
+ if self.character_data:
+ if not self.skip_ws or not self.character_data.isspace():
+ line, column = self.character_pos
+ token = XmlToken(CHARACTER_DATA, self.character_data, None, line, column)
+ self.tokens.append(token)
+ self.character_data = ''
+
+ def next(self):
+ size = 16*1024
+ while self.index >= len(self.tokens) and not self.final:
+ self.tokens = []
+ self.index = 0
+ data = self.fp.read(size)
+ self.final = len(data) < size
+ data = data.rstrip('\0')
+ try:
+ self.parser.Parse(data, self.final)
+ except xml.parsers.expat.ExpatError, e:
+ #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS:
+ if e.code == 3:
+ pass
+ else:
+ raise e
+ if self.index >= len(self.tokens):
+ line, column = self.pos()
+ token = XmlToken(EOF, None, None, line, column)
+ else:
+ token = self.tokens[self.index]
+ self.index += 1
+ return token
+
+ def pos(self):
+ return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber
+
+
+class TokenMismatch(Exception):
+
+ def __init__(self, expected, found):
+ self.expected = expected
+ self.found = found
+
+ def __str__(self):
+ return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found))
+
+
+
+class XmlParser:
+ """Base XML document parser."""
+
+ def __init__(self, fp):
+ self.tokenizer = XmlTokenizer(fp)
+ self.consume()
+
+ def consume(self):
+ self.token = self.tokenizer.next()
+
+ def match_element_start(self, name):
+ return self.token.type == ELEMENT_START and self.token.name_or_data == name
+
+ def match_element_end(self, name):
+ return self.token.type == ELEMENT_END and self.token.name_or_data == name
+
+ def element_start(self, name):
+ while self.token.type == CHARACTER_DATA:
+ self.consume()
+ if self.token.type != ELEMENT_START:
+ raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token)
+ if self.token.name_or_data != name:
+ raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token)
+ attrs = self.token.attrs
+ self.consume()
+ return attrs
+
+ def element_end(self, name):
+ while self.token.type == CHARACTER_DATA:
+ self.consume()
+ if self.token.type != ELEMENT_END:
+ raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token)
+ if self.token.name_or_data != name:
+ raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token)
+ self.consume()
+
+ def character_data(self, strip = True):
+ data = ''
+ while self.token.type == CHARACTER_DATA:
+ data += self.token.name_or_data
+ self.consume()
+ if strip:
+ data = data.strip()
+ return data
+
+
+class TraceParser(XmlParser):
+
+ def __init__(self, fp):
+ XmlParser.__init__(self, fp)
+ self.last_call_no = 0
+
+ def parse(self):
+ self.element_start('trace')
+ while self.token.type not in (ELEMENT_END, EOF):
+ call = self.parse_call()
+ self.handle_call(call)
+ if self.token.type != EOF:
+ self.element_end('trace')
+
+ def parse_call(self):
+ attrs = self.element_start('call')
+ try:
+ no = int(attrs['no'])
+ except KeyError:
+ self.last_call_no += 1
+ no = self.last_call_no
+ else:
+ self.last_call_no = no
+ klass = attrs['class']
+ method = attrs['method']
+ args = []
+ ret = None
+ while self.token.type == ELEMENT_START:
+ if self.token.name_or_data == 'arg':
+ arg = self.parse_arg()
+ args.append(arg)
+ elif self.token.name_or_data == 'ret':
+ ret = self.parse_ret()
+ elif self.token.name_or_data == 'call':
+ # ignore nested function calls
+ self.parse_call()
+ else:
+ raise TokenMismatch("<arg ...> or <ret ...>", self.token)
+ self.element_end('call')
+
+ return Call(no, klass, method, args, ret)
+
+ def parse_arg(self):
+ attrs = self.element_start('arg')
+ name = attrs['name']
+ value = self.parse_value()
+ self.element_end('arg')
+
+ return name, value
+
+ def parse_ret(self):
+ attrs = self.element_start('ret')
+ value = self.parse_value()
+ self.element_end('ret')
+
+ return value
+
+ def parse_value(self):
+ expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes')
+ if self.token.type == ELEMENT_START:
+ if self.token.name_or_data in expected_tokens:
+ method = getattr(self, 'parse_' + self.token.name_or_data)
+ return method()
+ raise TokenMismatch(" or " .join(expected_tokens), self.token)
+
+ def parse_null(self):
+ self.element_start('null')
+ self.element_end('null')
+ return Literal(None)
+
+ def parse_bool(self):
+ self.element_start('bool')
+ value = int(self.character_data())
+ self.element_end('bool')
+ return Literal(value)
+
+ def parse_int(self):
+ self.element_start('int')
+ value = int(self.character_data())
+ self.element_end('int')
+ return Literal(value)
+
+ def parse_uint(self):
+ self.element_start('uint')
+ value = int(self.character_data())
+ self.element_end('uint')
+ return Literal(value)
+
+ def parse_float(self):
+ self.element_start('float')
+ value = float(self.character_data())
+ self.element_end('float')
+ return Literal(value)
+
+ def parse_enum(self):
+ self.element_start('enum')
+ name = self.character_data()
+ self.element_end('enum')
+ return NamedConstant(name)
+
+ def parse_string(self):
+ self.element_start('string')
+ value = self.character_data()
+ self.element_end('string')
+ return Literal(value)
+
+ def parse_bytes(self):
+ self.element_start('bytes')
+ value = binascii.a2b_hex(self.character_data())
+ self.element_end('bytes')
+ return Literal(value)
+
+ def parse_array(self):
+ self.element_start('array')
+ elems = []
+ while self.token.type != ELEMENT_END:
+ elems.append(self.parse_elem())
+ self.element_end('array')
+ return Array(elems)
+
+ def parse_elem(self):
+ self.element_start('elem')
+ value = self.parse_value()
+ self.element_end('elem')
+ return value
+
+ def parse_struct(self):
+ attrs = self.element_start('struct')
+ name = attrs['name']
+ members = []
+ while self.token.type != ELEMENT_END:
+ members.append(self.parse_member())
+ self.element_end('struct')
+ return Struct(name, members)
+
+ def parse_member(self):
+ attrs = self.element_start('member')
+ name = attrs['name']
+ value = self.parse_value()
+ self.element_end('member')
+
+ return name, value
+
+ def parse_ptr(self):
+ self.element_start('ptr')
+ address = self.character_data()
+ self.element_end('ptr')
+
+ return Pointer(address)
+
+ def handle_call(self, call):
+ pass
+
+
+class TraceDumper(TraceParser):
+
+ def __init__(self, fp):
+ TraceParser.__init__(self, fp)
+ self.formatter = format.DefaultFormatter(sys.stdout)
+ self.pretty_printer = PrettyPrinter(self.formatter)
+
+ def handle_call(self, call):
+ call.visit(self.pretty_printer)
+ self.formatter.newline()
+
+
+class Main:
+ '''Common main class for all retrace command line utilities.'''
+
+ def __init__(self):
+ pass
+
+ def main(self):
+ optparser = self.get_optparser()
+ (options, args) = optparser.parse_args(sys.argv[1:])
+
+ if args:
+ for arg in args:
+ if arg.endswith('.gz'):
+ from gzip import GzipFile
+ stream = GzipFile(arg, 'rt')
+ elif arg.endswith('.bz2'):
+ from bz2 import BZ2File
+ stream = BZ2File(arg, 'rU')
+ else:
+ stream = open(arg, 'rt')
+ self.process_arg(stream, options)
+ else:
+ self.process_arg(stream, options)
+
+ def get_optparser(self):
+ optparser = optparse.OptionParser(
+ usage="\n\t%prog [options] [traces] ...")
+ return optparser
+
+ def process_arg(self, stream, options):
+ parser = TraceDumper(stream)
+ parser.parse()
+
+
+if __name__ == '__main__':
+ Main().main()
diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py
new file mode 100755
index 0000000000..bd47c9a6b0
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/parser.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+from parse import *
+
+
+if __name__ == '__main__':
+ Main().main()
diff --git a/src/gallium/state_trackers/python/samples/tri.py b/src/gallium/state_trackers/python/samples/tri.py
new file mode 100644
index 0000000000..b721e0b575
--- /dev/null
+++ b/src/gallium/state_trackers/python/samples/tri.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+from gallium import *
+
+
+def make_image(surface):
+ data = surface.get_tile_rgba8(0, 0, surface.width, surface.height)
+
+ import Image
+ outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1)
+ return outimage
+
+def save_image(filename, surface):
+ outimage = make_image(surface)
+ outimage.save(filename, "PNG")
+
+def show_image(surface):
+ outimage = make_image(surface)
+
+ import Tkinter as tk
+ from PIL import Image, ImageTk
+ root = tk.Tk()
+
+ root.title('background image')
+
+ image1 = ImageTk.PhotoImage(outimage)
+ w = image1.width()
+ h = image1.height()
+ x = 100
+ y = 100
+ root.geometry("%dx%d+%d+%d" % (w, h, x, y))
+ panel1 = tk.Label(root, image=image1)
+ panel1.pack(side='top', fill='both', expand='yes')
+ panel1.image = image1
+ root.mainloop()
+
+
+def test(dev):
+ ctx = dev.context_create()
+
+ width = 255
+ height = 255
+ minz = 0.0
+ maxz = 1.0
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ depth_stencil_alpha.depth.enabled = 1
+ depth_stencil_alpha.depth.writemask = 1
+ depth_stencil_alpha.depth.func = PIPE_FUNC_LESS
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.scissor = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # viewport
+ viewport = Viewport()
+ scale = FloatArray(4)
+ scale[0] = width / 2.0
+ scale[1] = -height / 2.0
+ scale[2] = (maxz - minz) / 2.0
+ scale[3] = 1.0
+ viewport.scale = scale
+ translate = FloatArray(4)
+ translate[0] = width / 2.0
+ translate[1] = height / 2.0
+ translate[2] = (maxz - minz) / 2.0
+ translate[3] = 0.0
+ viewport.translate = translate
+ ctx.set_viewport(viewport)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ ctx.set_sampler(0, sampler)
+
+ # scissor
+ scissor = Scissor()
+ scissor.minx = 0
+ scissor.miny = 0
+ scissor.maxx = width
+ scissor.maxy = height
+ ctx.set_scissor(scissor)
+
+ clip = Clip()
+ clip.nr = 0
+ ctx.set_clip(clip)
+
+ # framebuffer
+ cbuf = dev.texture_create(
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ width, height,
+ tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ ).get_surface()
+ zbuf = dev.texture_create(
+ PIPE_FORMAT_Z16_UNORM,
+ width, height,
+ tex_usage=PIPE_TEXTURE_USAGE_DEPTH_STENCIL,
+ ).get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ fb.set_zsbuf(zbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.0
+ rgba[1] = 0.0
+ rgba[2] = 0.0
+ rgba[3] = 0.0
+ ctx.clear(PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, rgba, 1.0, 0xff)
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION, CONSTANT
+ DCL IN[1], COLOR, CONSTANT
+ DCL OUT[0], POSITION, CONSTANT
+ DCL OUT[1], COLOR, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:MOV OUT[1], IN[1]
+ 2:END
+ ''')
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], COLOR, LINEAR
+ DCL OUT[0], COLOR, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:END
+ ''')
+ ctx.set_fragment_shader(fs)
+
+ nverts = 3
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ verts[ 0] = 0.0 # x1
+ verts[ 1] = 0.8 # y1
+ verts[ 2] = 0.2 # z1
+ verts[ 3] = 1.0 # w1
+ verts[ 4] = 1.0 # r1
+ verts[ 5] = 0.0 # g1
+ verts[ 6] = 0.0 # b1
+ verts[ 7] = 1.0 # a1
+ verts[ 8] = -0.8 # x2
+ verts[ 9] = -0.8 # y2
+ verts[10] = 0.5 # z2
+ verts[11] = 1.0 # w2
+ verts[12] = 0.0 # r2
+ verts[13] = 1.0 # g2
+ verts[14] = 0.0 # b2
+ verts[15] = 1.0 # a2
+ verts[16] = 0.8 # x3
+ verts[17] = -0.8 # y3
+ verts[18] = 0.8 # z3
+ verts[19] = 1.0 # w3
+ verts[20] = 0.0 # r3
+ verts[21] = 0.0 # g3
+ verts[22] = 1.0 # b3
+ verts[23] = 1.0 # a3
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLES,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ show_image(cbuf)
+ #show_image(zbuf)
+ #save_image('cbuf.png', cbuf)
+ #save_image('zbuf.png', zbuf)
+
+
+
+def main():
+ dev = Device()
+ test(dev)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/st_device.c b/src/gallium/state_trackers/python/st_device.c
new file mode 100644
index 0000000000..ea7d18738f
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_device.c
@@ -0,0 +1,305 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_inlines.h"
+#include "cso_cache/cso_context.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_simple_shaders.h"
+#include "trace/tr_screen.h"
+#include "trace/tr_context.h"
+
+#include "st_device.h"
+#include "st_winsys.h"
+
+
+static void
+st_device_really_destroy(struct st_device *st_dev)
+{
+ if(st_dev->screen) {
+ /* FIXME: Don't really destroy until we keep track of every single
+ * reference or we end up causing a segmentation fault every time
+ * python exits. */
+#if 0
+ st_dev->screen->destroy(st_dev->screen);
+#endif
+ }
+
+ FREE(st_dev);
+}
+
+
+static void
+st_device_reference(struct st_device **ptr, struct st_device *st_dev)
+{
+ struct st_device *old_dev = *ptr;
+
+ if (pipe_reference((struct pipe_reference **)ptr, &st_dev->reference))
+ st_device_really_destroy(old_dev);
+}
+
+
+void
+st_device_destroy(struct st_device *st_dev)
+{
+ st_device_reference(&st_dev, NULL);
+}
+
+
+static struct st_device *
+st_device_create_from_st_winsys(const struct st_winsys *st_ws)
+{
+ struct st_device *st_dev;
+
+ if(!st_ws->screen_create ||
+ !st_ws->context_create)
+ return NULL;
+
+ st_dev = CALLOC_STRUCT(st_device);
+ if(!st_dev)
+ return NULL;
+
+ pipe_reference_init(&st_dev->reference, 1);
+ st_dev->st_ws = st_ws;
+
+ st_dev->real_screen = st_ws->screen_create();
+ if(!st_dev->real_screen) {
+ st_device_destroy(st_dev);
+ return NULL;
+ }
+
+ st_dev->screen = trace_screen_create(st_dev->real_screen);
+ if(!st_dev->screen) {
+ st_device_destroy(st_dev);
+ return NULL;
+ }
+
+ return st_dev;
+}
+
+
+struct st_device *
+st_device_create(boolean hardware) {
+ if(hardware)
+ return st_device_create_from_st_winsys(&st_hardpipe_winsys);
+ else
+ return st_device_create_from_st_winsys(&st_softpipe_winsys);
+}
+
+
+void
+st_context_destroy(struct st_context *st_ctx)
+{
+ unsigned i;
+
+ if(st_ctx) {
+ struct st_device *st_dev = st_ctx->st_dev;
+
+ if(st_ctx->cso) {
+ cso_delete_vertex_shader(st_ctx->cso, st_ctx->vs);
+ cso_delete_fragment_shader(st_ctx->cso, st_ctx->fs);
+
+ cso_destroy_context(st_ctx->cso);
+ }
+
+ if(st_ctx->pipe)
+ st_ctx->pipe->destroy(st_ctx->pipe);
+
+ for(i = 0; i < PIPE_MAX_SAMPLERS; ++i)
+ pipe_texture_reference(&st_ctx->sampler_textures[i], NULL);
+ pipe_texture_reference(&st_ctx->default_texture, NULL);
+
+ FREE(st_ctx);
+
+ st_device_reference(&st_dev, NULL);
+ }
+}
+
+
+struct st_context *
+st_context_create(struct st_device *st_dev)
+{
+ struct st_context *st_ctx;
+
+ st_ctx = CALLOC_STRUCT(st_context);
+ if(!st_ctx)
+ return NULL;
+
+ st_device_reference(&st_ctx->st_dev, st_dev);
+
+ st_ctx->real_pipe = st_dev->st_ws->context_create(st_dev->real_screen);
+ if(!st_ctx->real_pipe) {
+ st_context_destroy(st_ctx);
+ return NULL;
+ }
+
+ st_ctx->pipe = trace_context_create(st_dev->screen, st_ctx->real_pipe);
+ if(!st_ctx->pipe) {
+ st_context_destroy(st_ctx);
+ return NULL;
+ }
+
+ st_ctx->cso = cso_create_context(st_ctx->pipe);
+ if(!st_ctx->cso) {
+ st_context_destroy(st_ctx);
+ return NULL;
+ }
+
+ /* disabled blending/masking */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask = PIPE_MASK_RGBA;
+ cso_set_blend(st_ctx->cso, &blend);
+ }
+
+ /* no-op depth/stencil/alpha */
+ {
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ memset(&depthstencil, 0, sizeof(depthstencil));
+ cso_set_depth_stencil_alpha(st_ctx->cso, &depthstencil);
+ }
+
+ /* rasterizer */
+ {
+ struct pipe_rasterizer_state rasterizer;
+ memset(&rasterizer, 0, sizeof(rasterizer));
+ rasterizer.front_winding = PIPE_WINDING_CW;
+ rasterizer.cull_mode = PIPE_WINDING_NONE;
+ cso_set_rasterizer(st_ctx->cso, &rasterizer);
+ }
+
+ /* clip */
+ {
+ struct pipe_clip_state clip;
+ memset(&clip, 0, sizeof(clip));
+ st_ctx->pipe->set_clip_state(st_ctx->pipe, &clip);
+ }
+
+ /* identity viewport */
+ {
+ struct pipe_viewport_state viewport;
+ viewport.scale[0] = 1.0;
+ viewport.scale[1] = 1.0;
+ viewport.scale[2] = 1.0;
+ viewport.scale[3] = 1.0;
+ viewport.translate[0] = 0.0;
+ viewport.translate[1] = 0.0;
+ viewport.translate[2] = 0.0;
+ viewport.translate[3] = 0.0;
+ cso_set_viewport(st_ctx->cso, &viewport);
+ }
+
+ /* samplers */
+ {
+ struct pipe_sampler_state sampler;
+ unsigned i;
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.normalized_coords = 1;
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ cso_single_sampler(st_ctx->cso, i, &sampler);
+ cso_single_sampler_done(st_ctx->cso);
+ }
+
+ /* default textures */
+ {
+ struct pipe_screen *screen = st_dev->screen;
+ struct pipe_texture templat;
+ struct pipe_transfer *transfer;
+ unsigned i;
+
+ memset( &templat, 0, sizeof( templat ) );
+ templat.target = PIPE_TEXTURE_2D;
+ templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ templat.block.size = 4;
+ templat.block.width = 1;
+ templat.block.height = 1;
+ templat.width[0] = 1;
+ templat.height[0] = 1;
+ templat.depth[0] = 1;
+ templat.last_level = 0;
+
+ st_ctx->default_texture = screen->texture_create( screen, &templat );
+ if(st_ctx->default_texture) {
+ transfer = screen->get_tex_transfer(screen,
+ st_ctx->default_texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ 0, 0,
+ st_ctx->default_texture->width[0],
+ st_ctx->default_texture->height[0]);
+ if (transfer) {
+ uint32_t *map;
+ map = (uint32_t *) screen->transfer_map(screen, transfer);
+ if(map) {
+ *map = 0x00000000;
+ screen->transfer_unmap(screen, transfer);
+ }
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ pipe_texture_reference(&st_ctx->sampler_textures[i], st_ctx->default_texture);
+
+ cso_set_sampler_textures(st_ctx->cso, PIPE_MAX_SAMPLERS, st_ctx->sampler_textures);
+ }
+
+ /* vertex shader */
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0 };
+ st_ctx->vs = util_make_vertex_passthrough_shader(st_ctx->pipe,
+ 2,
+ semantic_names,
+ semantic_indexes);
+ cso_set_vertex_shader_handle(st_ctx->cso, st_ctx->vs);
+ }
+
+ /* fragment shader */
+ {
+ st_ctx->fs = util_make_fragment_passthrough_shader(st_ctx->pipe);
+ cso_set_fragment_shader_handle(st_ctx->cso, st_ctx->fs);
+ }
+
+ return st_ctx;
+}
diff --git a/src/gallium/state_trackers/python/st_device.h b/src/gallium/state_trackers/python/st_device.h
new file mode 100644
index 0000000000..a246b6a1f2
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_device.h
@@ -0,0 +1,106 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_DEVICE_H_
+#define ST_DEVICE_H_
+
+
+#include "pipe/p_state.h"
+
+struct cso_context;
+struct pipe_screen;
+struct pipe_context;
+struct st_winsys;
+
+
+struct st_surface
+{
+ struct pipe_texture *texture;
+ unsigned face;
+ unsigned level;
+ unsigned zslice;
+};
+
+
+struct st_context {
+ struct st_device *st_dev;
+
+ struct pipe_context *real_pipe;
+ struct pipe_context *pipe;
+
+ struct cso_context *cso;
+
+ void *vs;
+ void *fs;
+
+ struct pipe_texture *default_texture;
+ struct pipe_texture *sampler_textures[PIPE_MAX_SAMPLERS];
+
+ unsigned num_vertex_buffers;
+ struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
+
+ unsigned num_vertex_elements;
+ struct pipe_vertex_element vertex_elements[PIPE_MAX_ATTRIBS];
+
+ struct pipe_framebuffer_state framebuffer;
+};
+
+
+struct st_device {
+ /* FIXME: we also need to refcount for textures and surfaces... */
+ struct pipe_reference reference;
+
+ const struct st_winsys *st_ws;
+
+ struct pipe_screen *real_screen;
+ struct pipe_screen *screen;
+};
+
+
+static INLINE struct pipe_surface *
+st_pipe_surface(struct st_surface *surface, unsigned usage)
+{
+ struct pipe_texture *texture = surface->texture;
+ struct pipe_screen *screen = texture->screen;
+ return screen->get_tex_surface(screen, texture, surface->face, surface->level, surface->zslice, usage);
+}
+
+struct st_context *
+st_context_create(struct st_device *st_dev);
+
+void
+st_context_destroy(struct st_context *st_ctx);
+
+struct st_device *
+st_device_create(boolean hardware);
+
+void
+st_device_destroy(struct st_device *st_dev);
+
+
+#endif /* ST_DEVICE_H_ */
diff --git a/src/gallium/state_trackers/python/st_hardpipe_winsys.c b/src/gallium/state_trackers/python/st_hardpipe_winsys.c
new file mode 100644
index 0000000000..43aaaabf2a
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_hardpipe_winsys.c
@@ -0,0 +1,237 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * 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.
+ *
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Get a hardware accelerated Gallium screen/context from the OpenGL driver.
+ */
+
+
+#include "pipe/p_compiler.h"
+
+#ifdef PIPE_OS_WINDOWS
+#include <windows.h>
+#include <GL/gl.h>
+#else
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#endif
+
+#include "st_winsys.h"
+
+
+typedef struct pipe_screen * (GLAPIENTRY *PFNGETGALLIUMSCREENMESAPROC) (void);
+typedef struct pipe_context * (GLAPIENTRY* PFNCREATEGALLIUMCONTEXTMESAPROC) (void);
+
+static PFNGETGALLIUMSCREENMESAPROC pfnGetGalliumScreenMESA = NULL;
+static PFNCREATEGALLIUMCONTEXTMESAPROC pfnCreateGalliumContextMESA = NULL;
+
+
+/* XXX: Force init_gallium symbol to be linked */
+extern void init_gallium(void);
+void (*force_init_gallium_linkage)(void) = &init_gallium;
+
+
+#ifdef PIPE_OS_WINDOWS
+
+static INLINE boolean
+st_hardpipe_load(void)
+{
+ WNDCLASS wc;
+ HWND hwnd;
+ HGLRC hglrc;
+ HDC hdc;
+ PIXELFORMATDESCRIPTOR pfd;
+ int iPixelFormat;
+
+ if(pfnGetGalliumScreenMESA && pfnCreateGalliumContextMESA)
+ return TRUE;
+
+ memset(&wc, 0, sizeof wc);
+ wc.lpfnWndProc = DefWindowProc;
+ wc.lpszClassName = "gallium";
+ wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+ RegisterClass(&wc);
+
+ hwnd = CreateWindow(wc.lpszClassName, "gallium", 0, 0, 0, 0, 0, NULL, 0, wc.hInstance, NULL);
+ if (!hwnd)
+ return FALSE;
+
+ hdc = GetDC(hwnd);
+ if (!hdc)
+ return FALSE;
+
+ pfd.cColorBits = 3;
+ pfd.cRedBits = 1;
+ pfd.cGreenBits = 1;
+ pfd.cBlueBits = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+
+ iPixelFormat = ChoosePixelFormat(hdc, &pfd);
+ if (!iPixelFormat) {
+ pfd.dwFlags |= PFD_DOUBLEBUFFER;
+ iPixelFormat = ChoosePixelFormat(hdc, &pfd);
+ }
+ if (!iPixelFormat)
+ return FALSE;
+
+ SetPixelFormat(hdc, iPixelFormat, &pfd);
+ hglrc = wglCreateContext(hdc);
+ if (!hglrc)
+ return FALSE;
+
+ if (!wglMakeCurrent(hdc, hglrc))
+ return FALSE;
+
+ pfnGetGalliumScreenMESA = (PFNGETGALLIUMSCREENMESAPROC)wglGetProcAddress("wglGetGalliumScreenMESA");
+ if(!pfnGetGalliumScreenMESA)
+ return FALSE;
+
+ pfnCreateGalliumContextMESA = (PFNCREATEGALLIUMCONTEXTMESAPROC)wglGetProcAddress("wglCreateGalliumContextMESA");
+ if(!pfnCreateGalliumContextMESA)
+ return FALSE;
+
+ DestroyWindow(hwnd);
+
+ return TRUE;
+}
+
+#else
+
+static INLINE boolean
+st_hardpipe_load(void)
+{
+ Display *dpy;
+ int scrnum;
+ Window root;
+ int attribSingle[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ None };
+ int attribDouble[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None };
+ XVisualInfo *visinfo;
+ GLXContext ctx = NULL;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ int width = 100, height = 100;
+ Window win;
+
+ dpy = XOpenDisplay(NULL);
+ if (!dpy)
+ return FALSE;
+
+ scrnum = 0;
+
+ root = RootWindow(dpy, scrnum);
+
+ visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
+ if (!visinfo)
+ visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
+ if (!visinfo)
+ return FALSE;
+
+ ctx = glXCreateContext( dpy, visinfo, NULL, True );
+
+ if (!ctx)
+ return FALSE;
+
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask;
+
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ win = XCreateWindow(dpy, root, 0, 0, width, height,
+ 0, visinfo->depth, InputOutput,
+ visinfo->visual, mask, &attr);
+
+ if (!glXMakeCurrent(dpy, win, ctx))
+ return FALSE;
+
+ pfnGetGalliumScreenMESA = (PFNGETGALLIUMSCREENMESAPROC)glXGetProcAddressARB((const GLubyte *)"glXGetGalliumScreenMESA");
+ if(!pfnGetGalliumScreenMESA)
+ return FALSE;
+
+ pfnCreateGalliumContextMESA = (PFNCREATEGALLIUMCONTEXTMESAPROC)glXGetProcAddressARB((const GLubyte *)"glXCreateGalliumContextMESA");
+ if(!pfnCreateGalliumContextMESA)
+ return FALSE;
+
+ glXDestroyContext(dpy, ctx);
+ XFree(visinfo);
+ XDestroyWindow(dpy, win);
+ XCloseDisplay(dpy);
+
+ return TRUE;
+}
+
+#endif
+
+
+static struct pipe_screen *
+st_hardpipe_screen_create(void)
+{
+ if(st_hardpipe_load())
+ return pfnGetGalliumScreenMESA();
+ else
+ return st_softpipe_winsys.screen_create();
+}
+
+
+static struct pipe_context *
+st_hardpipe_context_create(struct pipe_screen *screen)
+{
+ if(st_hardpipe_load()) {
+ if(screen == pfnGetGalliumScreenMESA())
+ return pfnCreateGalliumContextMESA();
+ else
+ return NULL;
+ }
+ else
+ return st_softpipe_winsys.context_create(screen);
+}
+
+
+const struct st_winsys st_hardpipe_winsys = {
+ &st_hardpipe_screen_create,
+ &st_hardpipe_context_create
+};
diff --git a/src/gallium/state_trackers/python/st_sample.c b/src/gallium/state_trackers/python/st_sample.c
new file mode 100644
index 0000000000..53a01891e1
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_sample.c
@@ -0,0 +1,570 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "st_device.h"
+#include "st_sample.h"
+
+
+/**
+ * Use our own pseudo random generator to ensure consistent runs among
+ * multiple runs and platforms.
+ *
+ * @sa http://en.wikipedia.org/wiki/Linear_congruential_generator
+ */
+static uint32_t st_random(void) {
+ static uint64_t seed = UINT64_C(0xbb9a063afb0a739d);
+
+ seed = UINT64_C(134775813) * seed + UINT64_C(1);
+
+ return (uint16_t)(seed >> 32);
+}
+
+
+/**
+ * We don't want to include the patent-encumbered DXT code here, so instead
+ * we store several uncompressed/compressed data pairs for hardware testing
+ * purposes.
+ */
+struct dxt_data
+{
+ uint8_t rgba[16*4];
+ uint8_t raw[16];
+};
+
+
+static const struct dxt_data
+dxt1_rgb_data[] = {
+ {
+ {
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0xd6, 0xff, 0x94, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0xd6, 0xff, 0x94, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0x21, 0x14, 0x84, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x21, 0x14, 0x84, 0xff,
+ 0x21, 0x14, 0x84, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff
+ },
+ {0xf2, 0xd7, 0xb0, 0x20, 0xae, 0x2c, 0x6f, 0x97}
+ },
+ {
+ {
+ 0xb5, 0xcf, 0x9c, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x21, 0x08, 0x6b, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x52, 0x4a, 0x7b, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0xb5, 0xcf, 0x9c, 0xff,
+ 0x21, 0x08, 0x6b, 0xff,
+ 0xb5, 0xcf, 0x9c, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x52, 0x4a, 0x7b, 0xff,
+ 0xb5, 0xcf, 0x9c, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x52, 0x4a, 0x7b, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff
+ },
+ {0x73, 0xb6, 0x4d, 0x20, 0x98, 0x2b, 0xe1, 0xb8}
+ },
+ {
+ {
+ 0x00, 0x2c, 0xff, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0x4a, 0x5c, 0xbd, 0xff,
+ 0x4a, 0x5c, 0xbd, 0xff,
+ 0x4a, 0x5c, 0xbd, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff
+ },
+ {0xe7, 0xdd, 0x7f, 0x01, 0xf9, 0xab, 0x08, 0x80}
+ },
+ {
+ {
+ 0x6b, 0x24, 0x21, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x8b, 0x7a, 0x99, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x6b, 0x24, 0x21, 0xff,
+ 0x8b, 0x7a, 0x99, 0xff,
+ 0x9c, 0xa6, 0xd6, 0xff,
+ 0x6b, 0x24, 0x21, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x8b, 0x7a, 0x99, 0xff,
+ 0x6b, 0x24, 0x21, 0xff,
+ 0x8b, 0x7a, 0x99, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x9c, 0xa6, 0xd6, 0xff
+ },
+ {0x3a, 0x9d, 0x24, 0x69, 0xbd, 0x9f, 0xb4, 0x39}
+ }
+};
+
+
+static const struct dxt_data
+dxt1_rgba_data[] = {
+ {
+ {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x29, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x73, 0x55, 0x21, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff
+ },
+ {0xff, 0x2f, 0xa4, 0x72, 0xeb, 0xb2, 0xbd, 0xbe}
+ },
+ {
+ {
+ 0xb5, 0xe3, 0x63, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x6b, 0x24, 0x84, 0xff,
+ 0xb5, 0xe3, 0x63, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xb5, 0xe3, 0x63, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x6b, 0x24, 0x84, 0xff,
+ 0x6b, 0x24, 0x84, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xb5, 0xe3, 0x63, 0xff,
+ 0x90, 0x83, 0x73, 0xff,
+ 0xb5, 0xe3, 0x63, 0xff
+ },
+ {0x30, 0x69, 0x0c, 0xb7, 0x4d, 0xf7, 0x0f, 0x67}
+ },
+ {
+ {
+ 0x00, 0x00, 0x00, 0x00,
+ 0xc6, 0x86, 0x8c, 0xff,
+ 0xc6, 0x86, 0x8c, 0xff,
+ 0x21, 0x65, 0x42, 0xff,
+ 0x21, 0x65, 0x42, 0xff,
+ 0x21, 0x65, 0x42, 0xff,
+ 0x21, 0x65, 0x42, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x21, 0x65, 0x42, 0xff,
+ 0xc6, 0x86, 0x8c, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xc6, 0x86, 0x8c, 0xff
+ },
+ {0x28, 0x23, 0x31, 0xc4, 0x17, 0xc0, 0xd3, 0x7f}
+ },
+ {
+ {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xc6, 0xe3, 0x9c, 0xff,
+ 0x7b, 0x1c, 0x52, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x7b, 0x1c, 0x52, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x7b, 0x1c, 0x52, 0xff,
+ 0xa0, 0x7f, 0x77, 0xff,
+ 0xc6, 0xe3, 0x9c, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x7f, 0x77, 0xff
+ },
+ {0xea, 0x78, 0x13, 0xc7, 0x7f, 0xfc, 0x33, 0xb6}
+ },
+};
+
+
+static const struct dxt_data
+dxt3_rgba_data[] = {
+ {
+ {
+ 0x6d, 0xc6, 0x96, 0x77,
+ 0x6d, 0xc6, 0x96, 0xee,
+ 0x6d, 0xc6, 0x96, 0xaa,
+ 0x8c, 0xff, 0xb5, 0x44,
+ 0x6d, 0xc6, 0x96, 0xff,
+ 0x6d, 0xc6, 0x96, 0x88,
+ 0x31, 0x55, 0x5a, 0x66,
+ 0x6d, 0xc6, 0x96, 0x99,
+ 0x31, 0x55, 0x5a, 0xbb,
+ 0x31, 0x55, 0x5a, 0x55,
+ 0x31, 0x55, 0x5a, 0x11,
+ 0x6d, 0xc6, 0x96, 0xcc,
+ 0x6d, 0xc6, 0x96, 0xcc,
+ 0x6d, 0xc6, 0x96, 0x11,
+ 0x31, 0x55, 0x5a, 0x44,
+ 0x31, 0x55, 0x5a, 0x88
+ },
+ {0xe7, 0x4a, 0x8f, 0x96, 0x5b, 0xc1, 0x1c, 0x84, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a}
+ },
+ {
+ {
+ 0xad, 0xeb, 0x73, 0x99,
+ 0x97, 0xaa, 0x86, 0x66,
+ 0x6b, 0x28, 0xad, 0x99,
+ 0xad, 0xeb, 0x73, 0x99,
+ 0x6b, 0x28, 0xad, 0x22,
+ 0xad, 0xeb, 0x73, 0xff,
+ 0x97, 0xaa, 0x86, 0x55,
+ 0x6b, 0x28, 0xad, 0x55,
+ 0x6b, 0x28, 0xad, 0x44,
+ 0xad, 0xeb, 0x73, 0x33,
+ 0x6b, 0x28, 0xad, 0xee,
+ 0x6b, 0x28, 0xad, 0x99,
+ 0x97, 0xaa, 0x86, 0x66,
+ 0xad, 0xeb, 0x73, 0xbb,
+ 0x97, 0xaa, 0x86, 0x99,
+ 0xad, 0xeb, 0x73, 0xbb
+ },
+ {0x69, 0x99, 0xf2, 0x55, 0x34, 0x9e, 0xb6, 0xb9, 0x4e, 0xaf, 0x55, 0x69, 0x18, 0x61, 0x51, 0x22}
+ },
+ {
+ {
+ 0x63, 0xd7, 0xd6, 0x00,
+ 0x57, 0x62, 0x5d, 0xdd,
+ 0x57, 0x62, 0x5d, 0xcc,
+ 0x57, 0x62, 0x5d, 0xbb,
+ 0x52, 0x28, 0x21, 0xaa,
+ 0x57, 0x62, 0x5d, 0xcc,
+ 0x57, 0x62, 0x5d, 0xcc,
+ 0x57, 0x62, 0x5d, 0x66,
+ 0x57, 0x62, 0x5d, 0x22,
+ 0x57, 0x62, 0x5d, 0xdd,
+ 0x63, 0xd7, 0xd6, 0xee,
+ 0x57, 0x62, 0x5d, 0x33,
+ 0x63, 0xd7, 0xd6, 0x55,
+ 0x52, 0x28, 0x21, 0x55,
+ 0x57, 0x62, 0x5d, 0x11,
+ 0x5d, 0x9c, 0x99, 0xee
+ },
+ {0xd0, 0xbc, 0xca, 0x6c, 0xd2, 0x3e, 0x55, 0xe1, 0xba, 0x66, 0x44, 0x51, 0xfc, 0xfd, 0xcf, 0xb4}
+ },
+ {
+ {
+ 0x94, 0x6f, 0x60, 0x22,
+ 0x94, 0x6f, 0x60, 0x22,
+ 0xc5, 0xab, 0x76, 0x11,
+ 0xc5, 0xab, 0x76, 0xee,
+ 0x63, 0x34, 0x4a, 0xdd,
+ 0x63, 0x34, 0x4a, 0x33,
+ 0x94, 0x6f, 0x60, 0x77,
+ 0xf7, 0xe7, 0x8c, 0x00,
+ 0x94, 0x6f, 0x60, 0x33,
+ 0x63, 0x34, 0x4a, 0xaa,
+ 0x94, 0x6f, 0x60, 0x77,
+ 0x63, 0x34, 0x4a, 0xcc,
+ 0x94, 0x6f, 0x60, 0xaa,
+ 0xf7, 0xe7, 0x8c, 0x99,
+ 0x63, 0x34, 0x4a, 0x44,
+ 0xc5, 0xab, 0x76, 0xaa
+ },
+ {0x22, 0xe1, 0x3d, 0x07, 0xa3, 0xc7, 0x9a, 0xa4, 0x31, 0xf7, 0xa9, 0x61, 0xaf, 0x35, 0x77, 0x93}
+ },
+};
+
+
+static const struct dxt_data
+dxt5_rgba_data[] = {
+ {
+ {
+ 0x6d, 0xc6, 0x96, 0x74,
+ 0x6d, 0xc6, 0x96, 0xf8,
+ 0x6d, 0xc6, 0x96, 0xb6,
+ 0x8c, 0xff, 0xb5, 0x53,
+ 0x6d, 0xc6, 0x96, 0xf8,
+ 0x6d, 0xc6, 0x96, 0x95,
+ 0x31, 0x55, 0x5a, 0x53,
+ 0x6d, 0xc6, 0x96, 0x95,
+ 0x31, 0x55, 0x5a, 0xb6,
+ 0x31, 0x55, 0x5a, 0x53,
+ 0x31, 0x55, 0x5a, 0x11,
+ 0x6d, 0xc6, 0x96, 0xd7,
+ 0x6d, 0xc6, 0x96, 0xb6,
+ 0x6d, 0xc6, 0x96, 0x11,
+ 0x31, 0x55, 0x5a, 0x32,
+ 0x31, 0x55, 0x5a, 0x95
+ },
+ {0xf8, 0x11, 0xc5, 0x0c, 0x9a, 0x73, 0xb4, 0x9c, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a}
+ },
+ {
+ {
+ 0xad, 0xeb, 0x73, 0xa1,
+ 0x97, 0xaa, 0x86, 0x65,
+ 0x6b, 0x28, 0xad, 0xa1,
+ 0xad, 0xeb, 0x73, 0xa1,
+ 0x6b, 0x28, 0xad, 0x2a,
+ 0xad, 0xeb, 0x73, 0xfb,
+ 0x97, 0xaa, 0x86, 0x47,
+ 0x6b, 0x28, 0xad, 0x65,
+ 0x6b, 0x28, 0xad, 0x47,
+ 0xad, 0xeb, 0x73, 0x47,
+ 0x6b, 0x28, 0xad, 0xdd,
+ 0x6b, 0x28, 0xad, 0xa1,
+ 0x97, 0xaa, 0x86, 0x65,
+ 0xad, 0xeb, 0x73, 0xbf,
+ 0x97, 0xaa, 0x86, 0xa1,
+ 0xad, 0xeb, 0x73, 0xbf
+ },
+ {0xfb, 0x2a, 0x34, 0x19, 0xdc, 0xbf, 0xe8, 0x71, 0x4e, 0xaf, 0x55, 0x69, 0x18, 0x61, 0x51, 0x22}
+ },
+ {
+ {
+ 0x63, 0xd7, 0xd6, 0x00,
+ 0x57, 0x62, 0x5d, 0xf5,
+ 0x57, 0x62, 0x5d, 0xd2,
+ 0x57, 0x62, 0x5d, 0xaf,
+ 0x52, 0x28, 0x21, 0xaf,
+ 0x57, 0x62, 0x5d, 0xd2,
+ 0x57, 0x62, 0x5d, 0xd2,
+ 0x57, 0x62, 0x5d, 0x69,
+ 0x57, 0x62, 0x5d, 0x23,
+ 0x57, 0x62, 0x5d, 0xd2,
+ 0x63, 0xd7, 0xd6, 0xf5,
+ 0x57, 0x62, 0x5d, 0x46,
+ 0x63, 0xd7, 0xd6, 0x46,
+ 0x52, 0x28, 0x21, 0x69,
+ 0x57, 0x62, 0x5d, 0x23,
+ 0x5d, 0x9c, 0x99, 0xf5
+ },
+ {0xf5, 0x00, 0x81, 0x36, 0xa9, 0x17, 0xec, 0x1e, 0xba, 0x66, 0x44, 0x51, 0xfc, 0xfd, 0xcf, 0xb4}
+ },
+ {
+ {
+ 0x94, 0x6f, 0x60, 0x25,
+ 0x94, 0x6f, 0x60, 0x25,
+ 0xc5, 0xab, 0x76, 0x05,
+ 0xc5, 0xab, 0x76, 0xe8,
+ 0x63, 0x34, 0x4a, 0xe8,
+ 0x63, 0x34, 0x4a, 0x25,
+ 0x94, 0x6f, 0x60, 0x86,
+ 0xf7, 0xe7, 0x8c, 0x05,
+ 0x94, 0x6f, 0x60, 0x25,
+ 0x63, 0x34, 0x4a, 0xa7,
+ 0x94, 0x6f, 0x60, 0x66,
+ 0x63, 0x34, 0x4a, 0xc7,
+ 0x94, 0x6f, 0x60, 0xa7,
+ 0xf7, 0xe7, 0x8c, 0xa7,
+ 0x63, 0x34, 0x4a, 0x45,
+ 0xc5, 0xab, 0x76, 0xa7
+ },
+ {0xe8, 0x05, 0x7f, 0x80, 0x33, 0x5f, 0xb5, 0x79, 0x31, 0xf7, 0xa9, 0x61, 0xaf, 0x35, 0x77, 0x93}
+ },
+};
+
+
+static INLINE void
+st_sample_dxt_pixel_block(enum pipe_format format,
+ const struct pipe_format_block *block,
+ uint8_t *raw,
+ float *rgba, unsigned rgba_stride,
+ unsigned w, unsigned h)
+{
+ const struct dxt_data *data;
+ unsigned n;
+ unsigned i;
+ unsigned x, y, ch;
+
+ switch(format) {
+ case PIPE_FORMAT_DXT1_RGB:
+ data = dxt1_rgb_data;
+ n = sizeof(dxt1_rgb_data)/sizeof(dxt1_rgb_data[0]);
+ break;
+ case PIPE_FORMAT_DXT1_RGBA:
+ data = dxt1_rgba_data;
+ n = sizeof(dxt1_rgba_data)/sizeof(dxt1_rgba_data[0]);
+ break;
+ case PIPE_FORMAT_DXT3_RGBA:
+ data = dxt3_rgba_data;
+ n = sizeof(dxt3_rgba_data)/sizeof(dxt3_rgba_data[0]);
+ break;
+ case PIPE_FORMAT_DXT5_RGBA:
+ data = dxt5_rgba_data;
+ n = sizeof(dxt5_rgba_data)/sizeof(dxt5_rgba_data[0]);
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ i = st_random() % n;
+
+ for(y = 0; y < h; ++y)
+ for(x = 0; x < w; ++x)
+ for(ch = 0; ch < 4; ++ch)
+ rgba[y*rgba_stride + x*4 + ch] = (float)(data[i].rgba[y*4*4 + x*4 + ch])/255.0f;
+
+ memcpy(raw, data[i].raw, block->size);
+}
+
+
+static INLINE void
+st_sample_generic_pixel_block(enum pipe_format format,
+ const struct pipe_format_block *block,
+ uint8_t *raw,
+ float *rgba, unsigned rgba_stride,
+ unsigned w, unsigned h)
+{
+ unsigned i;
+ unsigned x, y, ch;
+
+ for(i = 0; i < block->size; ++i)
+ raw[i] = (uint8_t)st_random();
+
+
+ pipe_tile_raw_to_rgba(format,
+ raw,
+ w, h,
+ rgba, rgba_stride);
+
+ if(format == PIPE_FORMAT_YCBCR || format == PIPE_FORMAT_YCBCR_REV) {
+ for(y = 0; y < h; ++y) {
+ for(x = 0; x < w; ++x) {
+ for(ch = 0; ch < 4; ++ch) {
+ unsigned offset = y*rgba_stride + x*4 + ch;
+ rgba[offset] = CLAMP(rgba[offset], 0.0f, 1.0f);
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Randomly sample pixels.
+ */
+void
+st_sample_pixel_block(enum pipe_format format,
+ const struct pipe_format_block *block,
+ void *raw,
+ float *rgba, unsigned rgba_stride,
+ unsigned w, unsigned h)
+{
+ switch(format) {
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT5_RGBA:
+ st_sample_dxt_pixel_block(format, block, raw, rgba, rgba_stride, w, h);
+ break;
+
+ default:
+ st_sample_generic_pixel_block(format, block, raw, rgba, rgba_stride, w, h);
+ break;
+ }
+}
+
+
+void
+st_sample_surface(struct st_surface *surface, float *rgba)
+{
+ struct pipe_texture *texture = surface->texture;
+ struct pipe_screen *screen = texture->screen;
+ unsigned width = texture->width[surface->level];
+ unsigned height = texture->height[surface->level];
+ uint rgba_stride = width * 4;
+ struct pipe_transfer *transfer;
+ void *raw;
+
+ transfer = screen->get_tex_transfer(screen,
+ surface->texture,
+ surface->face,
+ surface->level,
+ surface->zslice,
+ PIPE_TRANSFER_WRITE,
+ 0, 0,
+ width,
+ height);
+ if (!transfer)
+ return;
+
+ raw = screen->transfer_map(screen, transfer);
+ if (raw) {
+ const struct pipe_format_block *block = &texture->block;
+ uint x, y;
+
+ for (y = 0; y < transfer->nblocksy; ++y) {
+ for (x = 0; x < transfer->nblocksx; ++x) {
+ st_sample_pixel_block(texture->format,
+ block,
+ (uint8_t *) raw + y * transfer->stride + x * block->size,
+ rgba + y * block->height * rgba_stride + x * block->width * 4,
+ rgba_stride,
+ MIN2(block->width, width - x*block->width),
+ MIN2(block->height, height - y*block->height));
+ }
+ }
+
+ screen->transfer_unmap(screen, transfer);
+ }
+
+ screen->tex_transfer_destroy(transfer);
+}
diff --git a/src/gallium/state_trackers/python/st_sample.h b/src/gallium/state_trackers/python/st_sample.h
new file mode 100644
index 0000000000..0a27083549
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_sample.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_SAMPLE_H_
+#define ST_SAMPLE_H_
+
+
+#include "pipe/p_format.h"
+
+
+void
+st_sample_pixel_block(enum pipe_format format,
+ const struct pipe_format_block *block,
+ void *raw,
+ float *rgba, unsigned rgba_stride,
+ unsigned w, unsigned h);
+
+void
+st_sample_surface(struct st_surface *surface, float *rgba);
+
+
+#endif /* ST_SAMPLE_H_ */
diff --git a/src/gallium/state_trackers/python/st_softpipe_winsys.c b/src/gallium/state_trackers/python/st_softpipe_winsys.c
new file mode 100644
index 0000000000..f0a4826a00
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_softpipe_winsys.c
@@ -0,0 +1,270 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * 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.
+ *
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Softpipe support.
+ *
+ * @author Keith Whitwell
+ * @author Brian Paul
+ * @author Jose Fonseca
+ */
+
+
+#include "pipe/internal/p_winsys_screen.h"/* port to just p_screen */
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "softpipe/sp_winsys.h"
+#include "st_winsys.h"
+
+
+struct st_softpipe_buffer
+{
+ struct pipe_buffer base;
+ boolean userBuffer; /** Is this a user-space buffer? */
+ void *data;
+ void *mapped;
+};
+
+
+/** Cast wrapper */
+static INLINE struct st_softpipe_buffer *
+st_softpipe_buffer( struct pipe_buffer *buf )
+{
+ return (struct st_softpipe_buffer *)buf;
+}
+
+
+static void *
+st_softpipe_buffer_map(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf,
+ unsigned flags)
+{
+ struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf);
+ st_softpipe_buf->mapped = st_softpipe_buf->data;
+ return st_softpipe_buf->mapped;
+}
+
+
+static void
+st_softpipe_buffer_unmap(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf)
+{
+ struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf);
+ st_softpipe_buf->mapped = NULL;
+}
+
+
+static void
+st_softpipe_buffer_destroy(struct pipe_buffer *buf)
+{
+ struct st_softpipe_buffer *oldBuf = st_softpipe_buffer(buf);
+
+ if (oldBuf->data) {
+ if (!oldBuf->userBuffer)
+ align_free(oldBuf->data);
+
+ oldBuf->data = NULL;
+ }
+
+ FREE(oldBuf);
+}
+
+
+static void
+st_softpipe_flush_frontbuffer(struct pipe_winsys *winsys,
+ struct pipe_surface *surf,
+ void *context_private)
+{
+}
+
+
+
+static const char *
+st_softpipe_get_name(struct pipe_winsys *winsys)
+{
+ return "softpipe";
+}
+
+
+static struct pipe_buffer *
+st_softpipe_buffer_create(struct pipe_winsys *winsys,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct st_softpipe_buffer *buffer = CALLOC_STRUCT(st_softpipe_buffer);
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.alignment = alignment;
+ buffer->base.usage = usage;
+ buffer->base.size = size;
+
+ buffer->data = align_malloc(size, alignment);
+
+ return &buffer->base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+st_softpipe_user_buffer_create(struct pipe_winsys *winsys,
+ void *ptr,
+ unsigned bytes)
+{
+ struct st_softpipe_buffer *buffer;
+
+ buffer = CALLOC_STRUCT(st_softpipe_buffer);
+ if(!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.size = bytes;
+ buffer->userBuffer = TRUE;
+ buffer->data = ptr;
+
+ return &buffer->base;
+}
+
+
+/**
+ * Round n up to next multiple.
+ */
+static INLINE unsigned
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+
+static struct pipe_buffer *
+st_softpipe_surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned *stride)
+{
+ const unsigned alignment = 64;
+ struct pipe_format_block block;
+ unsigned nblocksx, nblocksy;
+
+ pf_get_block(format, &block);
+ nblocksx = pf_get_nblocksx(&block, width);
+ nblocksy = pf_get_nblocksy(&block, height);
+ *stride = round_up(nblocksx * block.size, alignment);
+
+ return winsys->buffer_create(winsys, alignment,
+ usage,
+ *stride * nblocksy);
+}
+
+
+static void
+st_softpipe_fence_reference(struct pipe_winsys *winsys,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+}
+
+
+static int
+st_softpipe_fence_signalled(struct pipe_winsys *winsys,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+static int
+st_softpipe_fence_finish(struct pipe_winsys *winsys,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+static void
+st_softpipe_destroy(struct pipe_winsys *winsys)
+{
+ FREE(winsys);
+}
+
+
+static struct pipe_screen *
+st_softpipe_screen_create(void)
+{
+ static struct pipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ winsys = CALLOC_STRUCT(pipe_winsys);
+ if(!winsys)
+ return NULL;
+
+ winsys->destroy = st_softpipe_destroy;
+
+ winsys->buffer_create = st_softpipe_buffer_create;
+ winsys->user_buffer_create = st_softpipe_user_buffer_create;
+ winsys->buffer_map = st_softpipe_buffer_map;
+ winsys->buffer_unmap = st_softpipe_buffer_unmap;
+ winsys->buffer_destroy = st_softpipe_buffer_destroy;
+
+ winsys->surface_buffer_create = st_softpipe_surface_buffer_create;
+
+ winsys->fence_reference = st_softpipe_fence_reference;
+ winsys->fence_signalled = st_softpipe_fence_signalled;
+ winsys->fence_finish = st_softpipe_fence_finish;
+
+ winsys->flush_frontbuffer = st_softpipe_flush_frontbuffer;
+ winsys->get_name = st_softpipe_get_name;
+
+ screen = softpipe_create_screen(winsys);
+ if(!screen)
+ st_softpipe_destroy(winsys);
+
+ return screen;
+}
+
+
+static struct pipe_context *
+st_softpipe_context_create(struct pipe_screen *screen)
+{
+ return softpipe_create(screen);
+}
+
+
+const struct st_winsys st_softpipe_winsys = {
+ &st_softpipe_screen_create,
+ &st_softpipe_context_create,
+};
diff --git a/src/gallium/state_trackers/python/st_winsys.h b/src/gallium/state_trackers/python/st_winsys.h
new file mode 100644
index 0000000000..b8cb612d86
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_winsys.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_WINSYS_H_
+#define ST_WINSYS_H_
+
+
+struct pipe_screen;
+struct pipe_context;
+
+
+struct st_winsys
+{
+ struct pipe_screen *
+ (*screen_create)(void);
+
+ struct pipe_context *
+ (*context_create)(struct pipe_screen *screen);
+};
+
+
+extern const struct st_winsys st_softpipe_winsys;
+
+extern const struct st_winsys st_hardpipe_winsys;
+
+
+#endif /* ST_WINSYS_H_ */
diff --git a/src/gallium/state_trackers/python/tests/.gitignore b/src/gallium/state_trackers/python/tests/.gitignore
new file mode 100644
index 0000000000..0dbbaeea16
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/.gitignore
@@ -0,0 +1,3 @@
+*.txt
+*.tsv
+*.dot
diff --git a/src/gallium/state_trackers/python/tests/base.py b/src/gallium/state_trackers/python/tests/base.py
new file mode 100755
index 0000000000..202ccfc350
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/base.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL 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.
+#
+##########################################################################
+
+
+"""Base classes for tests.
+
+Loosely inspired on Python's unittest module.
+"""
+
+
+import os.path
+import sys
+
+from gallium import *
+
+
+# Enumerate all pixel formats
+formats = {}
+for name, value in globals().items():
+ if name.startswith("PIPE_FORMAT_") and isinstance(value, int):
+ formats[value] = name
+
+def is_depth_stencil_format(format):
+ # FIXME: make and use binding to pf_is_depth_stencil
+ return format in (
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_Z16_UNORM,
+ )
+
+def make_image(width, height, rgba):
+ import Image
+ outimage = Image.new(
+ mode='RGB',
+ size=(width, height),
+ color=(0,0,0))
+ outpixels = outimage.load()
+ for y in range(0, height):
+ for x in range(0, width):
+ offset = (y*width + x)*4
+ r, g, b, a = [int(min(max(rgba[offset + ch], 0.0), 1.0)*255) for ch in range(4)]
+ outpixels[x, y] = r, g, b
+ return outimage
+
+def save_image(width, height, rgba, filename):
+ outimage = make_image(width, height, rgba)
+ outimage.save(filename, "PNG")
+
+def show_image(width, height, **rgbas):
+ import Tkinter as tk
+ from PIL import Image, ImageTk
+
+ root = tk.Tk()
+
+ x = 64
+ y = 64
+
+ labels = rgbas.keys()
+ labels.sort()
+ for i in range(len(labels)):
+ label = labels[i]
+ outimage = make_image(width, height, rgbas[label])
+
+ if i:
+ window = tk.Toplevel(root)
+ else:
+ window = root
+ window.title(label)
+ image1 = ImageTk.PhotoImage(outimage)
+ w = image1.width()
+ h = image1.height()
+ window.geometry("%dx%d+%d+%d" % (w, h, x, y))
+ panel1 = tk.Label(window, image=image1)
+ panel1.pack(side='top', fill='both', expand='yes')
+ panel1.image = image1
+ x += w + 2
+
+ root.mainloop()
+
+
+class TestFailure(Exception):
+
+ pass
+
+class TestSkip(Exception):
+
+ pass
+
+
+class Test:
+
+ def __init__(self):
+ pass
+
+ def _run(self, result):
+ raise NotImplementedError
+
+ def run(self):
+ result = TestResult()
+ self._run(result)
+ result.summary()
+
+ def assert_rgba(self, surface, x, y, w, h, expected_rgba, pixel_tol=4.0/256, surface_tol=0.85):
+ total = h*w
+ different = surface.compare_tile_rgba(x, y, w, h, expected_rgba, tol=pixel_tol)
+ if different:
+ sys.stderr.write("%u out of %u pixels differ\n" % (different, total))
+
+ if float(total - different)/float(total) < surface_tol:
+ if 0:
+ rgba = FloatArray(h*w*4)
+ surface.get_tile_rgba(x, y, w, h, rgba)
+ show_image(w, h, Result=rgba, Expected=expected_rgba)
+ save_image(w, h, rgba, "result.png")
+ save_image(w, h, expected_rgba, "expected.png")
+ #sys.exit(0)
+
+ raise TestFailure
+
+
+class TestCase(Test):
+
+ tags = ()
+
+ def __init__(self, dev, **kargs):
+ Test.__init__(self)
+ self.dev = dev
+ self.__dict__.update(kargs)
+
+ def description(self):
+ descriptions = []
+ for tag in self.tags:
+ value = self.get(tag)
+ if value is not None and value != '':
+ descriptions.append(tag + '=' + str(value))
+ return ' '.join(descriptions)
+
+ def get(self, tag):
+ try:
+ method = getattr(self, '_get_' + tag)
+ except AttributeError:
+ return getattr(self, tag, None)
+ else:
+ return method()
+
+ def _get_target(self):
+ return {
+ PIPE_TEXTURE_1D: "1d",
+ PIPE_TEXTURE_2D: "2d",
+ PIPE_TEXTURE_3D: "3d",
+ PIPE_TEXTURE_CUBE: "cube",
+ }[self.target]
+
+ def _get_format(self):
+ name = formats[self.format]
+ if name.startswith('PIPE_FORMAT_'):
+ name = name[12:]
+ name = name.lower()
+ return name
+
+ def _get_face(self):
+ if self.target == PIPE_TEXTURE_CUBE:
+ return {
+ PIPE_TEX_FACE_POS_X: "+x",
+ PIPE_TEX_FACE_NEG_X: "-x",
+ PIPE_TEX_FACE_POS_Y: "+y",
+ PIPE_TEX_FACE_NEG_Y: "-y",
+ PIPE_TEX_FACE_POS_Z: "+z",
+ PIPE_TEX_FACE_NEG_Z: "-z",
+ }[self.face]
+ else:
+ return ''
+
+ def test(self):
+ raise NotImplementedError
+
+ def _run(self, result):
+ result.test_start(self)
+ try:
+ self.test()
+ except KeyboardInterrupt:
+ raise
+ except TestSkip:
+ result.test_skipped(self)
+ except TestFailure:
+ result.test_failed(self)
+ else:
+ result.test_passed(self)
+
+
+class TestSuite(Test):
+
+ def __init__(self, tests = None):
+ Test.__init__(self)
+ if tests is None:
+ self.tests = []
+ else:
+ self.tests = tests
+
+ def add_test(self, test):
+ self.tests.append(test)
+
+ def _run(self, result):
+ for test in self.tests:
+ test._run(result)
+
+
+class TestResult:
+
+ def __init__(self):
+ self.tests = 0
+ self.passed = 0
+ self.skipped = 0
+ self.failed = 0
+
+ self.names = ['result']
+ self.types = ['pass skip fail']
+ self.rows = []
+
+ def test_start(self, test):
+ sys.stdout.write("Running %s...\n" % test.description())
+ sys.stdout.flush()
+ self.tests += 1
+
+ def test_passed(self, test):
+ sys.stdout.write("PASS\n")
+ sys.stdout.flush()
+ self.passed += 1
+ self.log_result(test, 'pass')
+
+ def test_skipped(self, test):
+ sys.stdout.write("SKIP\n")
+ sys.stdout.flush()
+ self.skipped += 1
+ #self.log_result(test, 'skip')
+
+ def test_failed(self, test):
+ sys.stdout.write("FAIL\n")
+ sys.stdout.flush()
+ self.failed += 1
+ self.log_result(test, 'fail')
+
+ def log_result(self, test, result):
+ row = ['']*len(self.names)
+
+ # add result
+ assert self.names[0] == 'result'
+ assert result in ('pass', 'skip', 'fail')
+ row[0] = result
+
+ # add tags
+ for tag in test.tags:
+ value = test.get(tag)
+
+ # infer type
+ if value is None:
+ continue
+ elif isinstance(value, (int, float)):
+ value = str(value)
+ type = 'c' # continous
+ elif isinstance(value, basestring):
+ type = 'd' # discrete
+ else:
+ assert False
+ value = str(value)
+ type = 'd' # discrete
+
+ # insert value
+ try:
+ col = self.names.index(tag, 1)
+ except ValueError:
+ self.names.append(tag)
+ self.types.append(type)
+ row.append(value)
+ else:
+ row[col] = value
+ assert self.types[col] == type
+
+ self.rows.append(row)
+
+ def summary(self):
+ sys.stdout.write("%u tests, %u passed, %u skipped, %u failed\n\n" % (self.tests, self.passed, self.skipped, self.failed))
+ sys.stdout.flush()
+
+ name, ext = os.path.splitext(os.path.basename(sys.argv[0]))
+ filename = name + '.tsv'
+ stream = file(filename, 'wt')
+
+ # header
+ stream.write('\t'.join(self.names) + '\n')
+ stream.write('\t'.join(self.types) + '\n')
+ stream.write('class\n')
+
+ # rows
+ for row in self.rows:
+ row += ['']*(len(self.names) - len(row))
+ stream.write('\t'.join(row) + '\n')
+
+ stream.close()
+
+ # See http://www.ailab.si/orange/doc/ofb/c_otherclass.htm
+ try:
+ import orange
+ import orngTree
+ except ImportError:
+ sys.stderr.write('Install Orange from http://www.ailab.si/orange/ for a classification tree.\n')
+ return
+
+ data = orange.ExampleTable(filename)
+
+ tree = orngTree.TreeLearner(data, sameMajorityPruning=1, mForPruning=2)
+
+ orngTree.printTxt(tree, maxDepth=4)
+
+ file(name+'.txt', 'wt').write(orngTree.dumpTree(tree))
+
+ orngTree.printDot(tree, fileName=name+'.dot', nodeShape='ellipse', leafShape='box')
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.sh
new file mode 100644
index 0000000000..7a0006bf66
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { -0.5, -0.4, -0.6, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+ABS OUT[0], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-add.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-add.sh
new file mode 100644
index 0000000000..f7836c85dd
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-add.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+ADD OUT[0], IN[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp3.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp3.sh
new file mode 100644
index 0000000000..c89cd748a8
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp3.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DP3 OUT[0], IN[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp4.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp4.sh
new file mode 100644
index 0000000000..6517e3c494
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp4.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DP4 OUT[0], IN[0].xyzx, IN[0].xyzx
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dst.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dst.sh
new file mode 100644
index 0000000000..464880ba68
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dst.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DST OUT[0], IN[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-ex2.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-ex2.sh
new file mode 100644
index 0000000000..2684076f1d
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-ex2.sh
@@ -0,0 +1,11 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+EX2 TEMP[0], IN[0].xxxx
+MUL OUT[0], TEMP[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-flr.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-flr.sh
new file mode 100644
index 0000000000..ad11e28918
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-flr.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 2.5, 4.0, 2.0, 1.0 }
+IMM FLT32 { 0.4, 0.25, 0.5, 1.0 }
+
+MUL TEMP[0], IN[0], IMM[0]
+FLR TEMP[0], TEMP[0]
+MUL OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-frc.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-frc.sh
new file mode 100644
index 0000000000..4f3aa30d66
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-frc.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 2.7, 3.1, 4.5, 1.0 }
+
+MUL TEMP[0], IN[0], IMM[0]
+FRC OUT[0], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lg2.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lg2.sh
new file mode 100644
index 0000000000..54c7c64459
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lg2.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 0.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+LG2 TEMP[0].x, TEMP[0].xxxx
+ADD OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lit.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lit.sh
new file mode 100644
index 0000000000..0e78ef86b5
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lit.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+LIT OUT[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lrp.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lrp.sh
new file mode 100644
index 0000000000..e9ee0f8147
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lrp.sh
@@ -0,0 +1,11 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+ABS TEMP[0], IN[0]
+LRP OUT[0], TEMP[0], IN[0].xxxx, IN[0].yyyy
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mad.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mad.sh
new file mode 100644
index 0000000000..439acd5bbd
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mad.sh
@@ -0,0 +1,11 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+IMM FLT32 { 0.5, 0.4, 0.6, 1.0 }
+IMM FLT32 { 0.5, 0.4, 0.6, 0.0 }
+
+MAD OUT[0], IN[0], IMM[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-max.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-max.sh
new file mode 100644
index 0000000000..ab21b245dd
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-max.sh
@@ -0,0 +1,10 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+IMM FLT32 { 0.4, 0.4, 0.4, 0.0 }
+
+MAX OUT[0], IN[0], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-min.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-min.sh
new file mode 100644
index 0000000000..969ae73d98
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-min.sh
@@ -0,0 +1,10 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+IMM FLT32 { 0.6, 0.6, 0.6, 1.0 }
+
+MIN OUT[0], IN[0], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mov.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mov.sh
new file mode 100644
index 0000000000..612975e057
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mov.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+MOV OUT[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mul.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mul.sh
new file mode 100644
index 0000000000..ed158b0fc6
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mul.sh
@@ -0,0 +1,10 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+IMM FLT32 { 0.5, 0.6, 0.7, 1.0 }
+
+MUL OUT[0], IN[0], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rcp.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rcp.sh
new file mode 100644
index 0000000000..cc9feef07e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rcp.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 1.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+RCP TEMP[0].x, TEMP[0].xxxx
+SUB OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rsq.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rsq.sh
new file mode 100644
index 0000000000..695621fdc9
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rsq.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 1.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+RSQ TEMP[0].x, TEMP[0].xxxx
+SUB OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sge.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sge.sh
new file mode 100644
index 0000000000..9505bc3c3e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sge.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 0.6, 0.6, 0.6, 0.0 }
+
+SGE TEMP[0], IN[0], IMM[0]
+MUL OUT[0], IN[0], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh
new file mode 100644
index 0000000000..f2a1521cbf
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 0.6, 0.6, 0.6, 0.0 }
+
+SLT TEMP[0], IN[0], IMM[0]
+MUL OUT[0], IN[0], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-abs.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-abs.sh
new file mode 100644
index 0000000000..9cd4b68295
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-abs.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { -0.3, -0.5, -0.4, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+MOV OUT[0], |TEMP[0]|
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh
new file mode 100644
index 0000000000..acd6aa750d
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { -0.2, -0.3, -0.4, 0.0 }
+IMM FLT32 { -1.0, -1.0, -1.0, -1.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+MOV TEMP[0], -|TEMP[0]|
+MUL OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-neg.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-neg.sh
new file mode 100644
index 0000000000..ba1b61503b
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-neg.sh
@@ -0,0 +1,11 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+SUB TEMP[0], IN[0], IN[0].yzxw
+MOV OUT[0], -TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-swz.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-swz.sh
new file mode 100644
index 0000000000..192aa7bb26
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-swz.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+MOV OUT[0], IN[0].yxzw
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sub.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sub.sh
new file mode 100644
index 0000000000..83441fa820
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sub.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+SUB OUT[0], IN[0], IN[0].yzxw
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-xpd.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-xpd.sh
new file mode 100644
index 0000000000..d6f66c4927
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-xpd.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+XPD OUT[0], IN[0], IN[0].yzxw
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py b/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py
new file mode 100644
index 0000000000..d60fb38d1a
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py
@@ -0,0 +1,218 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+from gallium import *
+
+def make_image(surface):
+ data = surface.get_tile_rgba8(0, 0, surface.width, surface.height)
+
+ import Image
+ outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1)
+ return outimage
+
+def save_image(filename, surface):
+ outimage = make_image(surface)
+ outimage.save(filename, "PNG")
+
+def test(dev, name):
+ ctx = dev.context_create()
+
+ width = 320
+ height = 320
+ minz = 0.0
+ maxz = 1.0
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ depth_stencil_alpha.depth.enabled = 0
+ depth_stencil_alpha.depth.writemask = 1
+ depth_stencil_alpha.depth.func = PIPE_FUNC_LESS
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.scissor = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # viewport
+ viewport = Viewport()
+ scale = FloatArray(4)
+ scale[0] = width / 2.0
+ scale[1] = -height / 2.0
+ scale[2] = (maxz - minz) / 2.0
+ scale[3] = 1.0
+ viewport.scale = scale
+ translate = FloatArray(4)
+ translate[0] = width / 2.0
+ translate[1] = height / 2.0
+ translate[2] = (maxz - minz) / 2.0
+ translate[3] = 0.0
+ viewport.translate = translate
+ ctx.set_viewport(viewport)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ ctx.set_sampler(0, sampler)
+
+ # scissor
+ scissor = Scissor()
+ scissor.minx = 0
+ scissor.miny = 0
+ scissor.maxx = width
+ scissor.maxy = height
+ ctx.set_scissor(scissor)
+
+ clip = Clip()
+ clip.nr = 0
+ ctx.set_clip(clip)
+
+ # framebuffer
+ cbuf = dev.texture_create(
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ width, height,
+ tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ ).get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.5
+ rgba[1] = 0.5
+ rgba[2] = 0.5
+ rgba[3] = 0.5
+ ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION
+ DCL IN[1], COLOR
+ DCL OUT[0], POSITION
+ DCL OUT[1], COLOR
+ MOV OUT[0], IN[0]
+ MOV OUT[1], IN[1]
+ END
+ ''')
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ fs = Shader(file('frag-' + name + '.sh', 'rt').read())
+ ctx.set_fragment_shader(fs)
+
+ xy = [
+ -0.8, -0.8,
+ 0.8, -0.8,
+ 0.0, 0.8,
+ ]
+ color = [
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0,
+ ]
+
+ nverts = 3
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ for i in range(0, nverts):
+ verts[i * nattrs * 4 + 0] = xy[i * 2 + 0] # x
+ verts[i * nattrs * 4 + 1] = xy[i * 2 + 1] # y
+ verts[i * nattrs * 4 + 2] = 0.5 # z
+ verts[i * nattrs * 4 + 3] = 1.0 # w
+ verts[i * nattrs * 4 + 4] = color[i * 3 + 0] # r
+ verts[i * nattrs * 4 + 5] = color[i * 3 + 1] # g
+ verts[i * nattrs * 4 + 6] = color[i * 3 + 2] # b
+ verts[i * nattrs * 4 + 7] = 1.0 # a
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLES,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ save_image('frag-' + name + '.png', cbuf)
+
+def main():
+ tests = [
+ 'abs',
+ 'add',
+ 'dp3',
+ 'dp4',
+ 'dst',
+ 'ex2',
+ 'flr',
+ 'frc',
+ 'lg2',
+ 'lit',
+ 'lrp',
+ 'mad',
+ 'max',
+ 'min',
+ 'mov',
+ 'mul',
+ 'rcp',
+ 'rsq',
+ 'sge',
+ 'slt',
+ 'srcmod-abs',
+ 'srcmod-absneg',
+ 'srcmod-neg',
+ 'srcmod-swz',
+ 'sub',
+ 'xpd',
+ ]
+
+ dev = Device()
+ for t in tests:
+ test(dev, t)
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-abs.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-abs.sh
new file mode 100644
index 0000000000..f0d0d5de17
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-abs.sh
@@ -0,0 +1,15 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { 0.2, 0.2, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+ABS OUT[0], TEMP[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-add.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-add.sh
new file mode 100644
index 0000000000..936c851c9d
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-add.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.2, -0.1, 0.0, 0.0 }
+
+ADD OUT[0], IN[0], IMM[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arl.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arl.sh
new file mode 100644
index 0000000000..7638e96346
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arl.sh
@@ -0,0 +1,23 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+DCL ADDR[0]
+
+IMM FLT32 { 3.0, 1.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 0.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 1.0, 1.0 }
+
+MOV OUT[0], IN[0]
+MUL TEMP[0], IN[0], IMM[0]
+ARL ADDR[0].x, TEMP[0]
+MOV OUT[1], IMM[ADDR[0].x + 3]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arr.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arr.sh
new file mode 100644
index 0000000000..28ce6f9a0c
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arr.sh
@@ -0,0 +1,23 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+DCL ADDR[0]
+
+IMM FLT32 { 3.0, 1.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 0.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 1.0, 1.0 }
+
+MOV OUT[0], IN[0]
+MUL TEMP[0], IN[0], IMM[0]
+ARR ADDR[0].x, TEMP[0]
+MOV OUT[1], IMM[ADDR[0].x + 3]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp3.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp3.sh
new file mode 100644
index 0000000000..b57d68520f
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp3.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+
+DP3 TEMP[0].xy, IN[0], IN[0]
+MOV TEMP[0].zw, IMM[0]
+MUL OUT[0], IN[0], TEMP[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp4.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp4.sh
new file mode 100644
index 0000000000..0eb31719c5
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp4.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+
+DP4 TEMP[0].xy, IN[0], IN[0]
+MOV TEMP[0].zw, IMM[0]
+MUL OUT[0], IN[0], TEMP[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dst.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dst.sh
new file mode 100644
index 0000000000..dc5e0eb92e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dst.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0]
+DST OUT[1], IN[1], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-ex2.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-ex2.sh
new file mode 100644
index 0000000000..34057af4e6
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-ex2.sh
@@ -0,0 +1,18 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0..1]
+
+IMM FLT32 { 0.3, 0.3, 0.3, 1.0 }
+
+EX2 TEMP[0], IN[0]
+EX2 TEMP[1], IN[1].yyyy
+MUL TEMP[0], TEMP[0], IMM[0]
+MOV OUT[0], IN[0]
+MUL OUT[1], TEMP[0], TEMP[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-flr.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-flr.sh
new file mode 100644
index 0000000000..44ad708119
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-flr.sh
@@ -0,0 +1,23 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+DCL ADDR[0]
+
+IMM FLT32 { 3.0, 1.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 0.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 1.0, 1.0 }
+
+MOV OUT[0], IN[0]
+MUL TEMP[0], IN[0], IMM[0]
+FLR ADDR[0].x, TEMP[0]
+MOV OUT[1], IMM[ADDR[0].x + 3]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-frc.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-frc.sh
new file mode 100644
index 0000000000..d179749de8
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-frc.sh
@@ -0,0 +1,15 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 2.7, 3.1, 4.5, 1.0 }
+
+MUL TEMP[0], IN[0].xyxw, IMM[0]
+MOV OUT[0], IN[0]
+FRC OUT[1], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lg2.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lg2.sh
new file mode 100644
index 0000000000..f6e08d087c
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lg2.sh
@@ -0,0 +1,18 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 0.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+LG2 TEMP[0].x, TEMP[0].xxxx
+ADD OUT[0], TEMP[0], IMM[1]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lit.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lit.sh
new file mode 100644
index 0000000000..da98f30928
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lit.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0]
+LIT OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lrp.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lrp.sh
new file mode 100644
index 0000000000..8c262580e2
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lrp.sh
@@ -0,0 +1,14 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+ABS TEMP[0], IN[0]
+MOV OUT[0], IN[0]
+LRP OUT[1], TEMP[0], IN[1].xxxx, IN[1].yyyy
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mad.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mad.sh
new file mode 100644
index 0000000000..eb07a3bd56
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mad.sh
@@ -0,0 +1,14 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.5, 1.0, 1.0, 1.0 }
+IMM FLT32 { 0.5, 0.0, 0.0, 0.0 }
+
+MAD OUT[0], IN[0], IMM[0], IMM[1]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-max.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-max.sh
new file mode 100644
index 0000000000..2d8b1fe3bf
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-max.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.5, 0.5, 0.5, 0.0 }
+
+MOV OUT[0], IN[0]
+MAX OUT[1], IN[1], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-min.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-min.sh
new file mode 100644
index 0000000000..84af0e2905
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-min.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.5, 0.5, 0.5, 0.0 }
+
+MOV OUT[0], IN[0]
+MIN OUT[1], IN[1], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mov.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mov.sh
new file mode 100644
index 0000000000..bcdec07c20
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mov.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mul.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mul.sh
new file mode 100644
index 0000000000..f3b57c3038
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mul.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.6, 0.6, 1.0, 1.0 }
+
+MUL OUT[0], IN[0], IMM[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rcp.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rcp.sh
new file mode 100644
index 0000000000..78af589b5c
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rcp.sh
@@ -0,0 +1,18 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 1.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+RCP TEMP[0].x, TEMP[0].xxxx
+SUB OUT[0], TEMP[0], IMM[1]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rsq.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rsq.sh
new file mode 100644
index 0000000000..1675c7d5ff
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rsq.sh
@@ -0,0 +1,18 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 1.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+RSQ TEMP[0].x, TEMP[0].xxxx
+SUB OUT[0], TEMP[0], IMM[1]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sge.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sge.sh
new file mode 100644
index 0000000000..3d92cd5aae
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sge.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { -0.1, -0.1, 1.0, 0.0 }
+
+SGE TEMP[0], IN[0], IMM[0]
+MOV OUT[0], IN[0]
+MUL OUT[1], IN[1], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-slt.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-slt.sh
new file mode 100644
index 0000000000..85c60ff4ec
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-slt.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 0.6, 0.6, 0.0, 0.0 }
+
+SLT TEMP[0], IN[0], IMM[0]
+MOV OUT[0], IN[0]
+MUL OUT[1], IN[1], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-abs.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-abs.sh
new file mode 100644
index 0000000000..6db417a62e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-abs.sh
@@ -0,0 +1,15 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { 0.1, 0.1, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+MOV OUT[0], |TEMP[0]|
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh
new file mode 100644
index 0000000000..fc83238052
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { -0.2, -0.2, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+MOV OUT[0].xy, -|TEMP[0]|
+MOV OUT[0].zw, IN[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-neg.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-neg.sh
new file mode 100644
index 0000000000..ce4e90b5e1
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-neg.sh
@@ -0,0 +1,12 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0].xy, -IN[0]
+MOV OUT[0].zw, IN[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-swz.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-swz.sh
new file mode 100644
index 0000000000..c03de4c674
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-swz.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0].yxzw
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sub.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sub.sh
new file mode 100644
index 0000000000..a583b95828
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sub.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.1, 0.1, 0.0, 0.0 }
+
+SUB OUT[0], IN[0], IMM[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-xpd.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-xpd.sh
new file mode 100644
index 0000000000..8def8943b0
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-xpd.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0]
+XPD OUT[1], IN[0], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py
new file mode 100644
index 0000000000..472769f259
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py
@@ -0,0 +1,247 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+from gallium import *
+
+def make_image(surface):
+ data = surface.get_tile_rgba8(0, 0, surface.width, surface.height)
+
+ import Image
+ outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1)
+ return outimage
+
+def save_image(filename, surface):
+ outimage = make_image(surface)
+ outimage.save(filename, "PNG")
+
+def test(dev, name):
+ ctx = dev.context_create()
+
+ width = 320
+ height = 320
+ minz = 0.0
+ maxz = 1.0
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ depth_stencil_alpha.depth.enabled = 0
+ depth_stencil_alpha.depth.writemask = 1
+ depth_stencil_alpha.depth.func = PIPE_FUNC_LESS
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.scissor = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # viewport
+ viewport = Viewport()
+ scale = FloatArray(4)
+ scale[0] = width / 2.0
+ scale[1] = -height / 2.0
+ scale[2] = (maxz - minz) / 2.0
+ scale[3] = 1.0
+ viewport.scale = scale
+ translate = FloatArray(4)
+ translate[0] = width / 2.0
+ translate[1] = height / 2.0
+ translate[2] = (maxz - minz) / 2.0
+ translate[3] = 0.0
+ viewport.translate = translate
+ ctx.set_viewport(viewport)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ ctx.set_sampler(0, sampler)
+
+ # scissor
+ scissor = Scissor()
+ scissor.minx = 0
+ scissor.miny = 0
+ scissor.maxx = width
+ scissor.maxy = height
+ ctx.set_scissor(scissor)
+
+ clip = Clip()
+ clip.nr = 0
+ ctx.set_clip(clip)
+
+ # framebuffer
+ cbuf = dev.texture_create(
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ width, height,
+ tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ ).get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.5
+ rgba[1] = 0.5
+ rgba[2] = 0.5
+ rgba[3] = 0.5
+ ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
+
+ # vertex shader
+ vs = Shader(file('vert-' + name + '.sh', 'rt').read())
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], COLOR, LINEAR
+ DCL OUT[0], COLOR, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:END
+ ''')
+ ctx.set_fragment_shader(fs)
+
+ xy = [
+ 0.0, 0.8,
+ -0.2, 0.4,
+ 0.2, 0.4,
+ -0.4, 0.0,
+ 0.0, 0.0,
+ 0.4, 0.0,
+ -0.6, -0.4,
+ -0.2, -0.4,
+ 0.2, -0.4,
+ 0.6, -0.4,
+ -0.8, -0.8,
+ -0.4, -0.8,
+ 0.0, -0.8,
+ 0.4, -0.8,
+ 0.8, -0.8,
+ ]
+ color = [
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0,
+ ]
+ tri = [
+ 1, 2, 0,
+ 3, 4, 1,
+ 4, 2, 1,
+ 4, 5, 2,
+ 6, 7, 3,
+ 7, 4, 3,
+ 7, 8, 4,
+ 8, 5, 4,
+ 8, 9, 5,
+ 10, 11, 6,
+ 11, 7, 6,
+ 11, 12, 7,
+ 12, 8, 7,
+ 12, 13, 8,
+ 13, 9, 8,
+ 13, 14, 9,
+ ]
+
+ nverts = 16 * 3
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ for i in range(0, nverts):
+ verts[i * nattrs * 4 + 0] = xy[tri[i] * 2 + 0] # x
+ verts[i * nattrs * 4 + 1] = xy[tri[i] * 2 + 1] # y
+ verts[i * nattrs * 4 + 2] = 0.5 # z
+ verts[i * nattrs * 4 + 3] = 1.0 # w
+ verts[i * nattrs * 4 + 4] = color[(i % 3) * 3 + 0] # r
+ verts[i * nattrs * 4 + 5] = color[(i % 3) * 3 + 1] # g
+ verts[i * nattrs * 4 + 6] = color[(i % 3) * 3 + 2] # b
+ verts[i * nattrs * 4 + 7] = 1.0 # a
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLES,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ save_image('vert-' + name + '.png', cbuf)
+
+def main():
+ tests = [
+ 'abs',
+ 'add',
+ 'arl',
+ 'arr',
+ 'dp3',
+ 'dp4',
+ 'dst',
+ 'ex2',
+ 'flr',
+ 'frc',
+ 'lg2',
+ 'lit',
+ 'lrp',
+ 'mad',
+ 'max',
+ 'min',
+ 'mov',
+ 'mul',
+ 'rcp',
+ 'rsq',
+ 'sge',
+ 'slt',
+ 'srcmod-abs',
+ 'srcmod-absneg',
+ 'srcmod-neg',
+ 'srcmod-swz',
+ 'sub',
+ 'xpd',
+ ]
+
+ dev = Device()
+ for t in tests:
+ test(dev, t)
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/surface_copy.py b/src/gallium/state_trackers/python/tests/surface_copy.py
new file mode 100755
index 0000000000..3ceecbbd3a
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/surface_copy.py
@@ -0,0 +1,199 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+from gallium import *
+from base import *
+
+
+def lods(*dims):
+ size = max(dims)
+ lods = 0
+ while size:
+ lods += 1
+ size >>= 1
+ return lods
+
+
+class TextureTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ # textures
+ dst_texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+ if dst_texture is None:
+ raise TestSkip
+
+ dst_surface = dst_texture.get_surface(face = face, level = level, zslice = zslice)
+
+ src_texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = dst_surface.width,
+ height = dst_surface.height,
+ depth = 1,
+ last_level = 0,
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER,
+ )
+
+ src_surface = src_texture.get_surface()
+
+ x = 0
+ y = 0
+ w = dst_surface.width
+ h = dst_surface.height
+
+ stride = dst_surface.nblocksx * dst_texture.block.size
+ size = dst_surface.nblocksy * stride
+ src_raw = os.urandom(size)
+
+ src_surface.put_tile_raw(0, 0, w, h, src_raw, stride)
+
+ ctx = self.dev.context_create()
+
+ ctx.surface_copy(dst_surface, 0, 0,
+ src_surface, 0, 0, w, h)
+
+ ctx.flush()
+
+ dst_raw = dst_surface.get_tile_raw(0, 0, w, h)
+
+ if dst_raw != src_raw:
+ raise TestFailure
+
+
+
+def main():
+ dev = Device()
+ suite = TestSuite()
+
+ targets = [
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_CUBE,
+ #PIPE_TEXTURE_3D,
+ ]
+
+ formats = [
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_S8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_DXT1_RGB,
+ PIPE_FORMAT_DXT1_RGBA,
+ PIPE_FORMAT_DXT3_RGBA,
+ PIPE_FORMAT_DXT5_RGBA,
+ ]
+
+ sizes = [64, 32, 16, 8, 4, 2, 1]
+ #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
+ #sizes = [64]
+ #sizes = [63]
+
+ faces = [
+ PIPE_TEX_FACE_POS_X,
+ PIPE_TEX_FACE_NEG_X,
+ PIPE_TEX_FACE_POS_Y,
+ PIPE_TEX_FACE_NEG_Y,
+ PIPE_TEX_FACE_POS_Z,
+ PIPE_TEX_FACE_NEG_Z,
+ ]
+
+ for target in targets:
+ for format in formats:
+ for size in sizes:
+ if target == PIPE_TEXTURE_3D:
+ depth = size
+ else:
+ depth = 1
+ for face in faces:
+ if target != PIPE_TEXTURE_CUBE and face:
+ continue
+ levels = lods(size)
+ for last_level in range(levels):
+ for level in range(0, last_level + 1):
+ zslice = 0
+ while zslice < depth >> level:
+ test = TextureTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ zslice = (zslice + 1)*2 - 1
+ suite.run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/texture_render.py b/src/gallium/state_trackers/python/tests/texture_render.py
new file mode 100755
index 0000000000..0b76932b6e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/texture_render.py
@@ -0,0 +1,320 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##########################################################################
+
+
+from gallium import *
+from base import *
+
+
+def lods(*dims):
+ size = max(dims)
+ lods = 0
+ while size:
+ lods += 1
+ size >>= 1
+ return lods
+
+
+class TextureTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ # textures
+ dst_texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+ if dst_texture is None:
+ raise TestSkip
+
+ dst_surface = dst_texture.get_surface(face = face, level = level, zslice = zslice)
+
+ ref_texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = dst_surface.width,
+ height = dst_surface.height,
+ depth = 1,
+ last_level = 0,
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER,
+ )
+
+ ref_surface = ref_texture.get_surface()
+
+ src_texture = dev.texture_create(
+ target = target,
+ format = PIPE_FORMAT_A8R8G8B8_UNORM,
+ width = dst_surface.width,
+ height = dst_surface.height,
+ depth = 1,
+ last_level = 0,
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER,
+ )
+
+ src_surface = src_texture.get_surface()
+
+ expected_rgba = FloatArray(height*width*4)
+ ref_surface.sample_rgba(expected_rgba)
+
+ src_surface.put_tile_rgba(0, 0, src_surface.width, src_surface.height, expected_rgba)
+
+ ctx = self.dev.context_create()
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # no-op depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.bypass_vs_clip_and_viewport = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ sampler.min_lod = 0
+ sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1
+ ctx.set_sampler(0, sampler)
+ ctx.set_sampler_texture(0, src_texture)
+
+ # framebuffer
+ cbuf_tex = dev.texture_create(
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ width,
+ height,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+
+ fb = Framebuffer()
+ fb.width = dst_surface.width
+ fb.height = dst_surface.height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, dst_surface)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.0
+ rgba[1] = 0.0
+ rgba[2] = 0.0
+ rgba[3] = 0.0
+ ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
+ del fb
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION, CONSTANT
+ DCL IN[1], GENERIC, CONSTANT
+ DCL OUT[0], POSITION, CONSTANT
+ DCL OUT[1], GENERIC, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:MOV OUT[1], IN[1]
+ 2:END
+ ''')
+ #vs.dump()
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], GENERIC[0], LINEAR
+ DCL OUT[0], COLOR, CONSTANT
+ DCL SAMP[0], CONSTANT
+ 0:TEX OUT[0], IN[0], SAMP[0], 2D
+ 1:END
+ ''')
+ #fs.dump()
+ ctx.set_fragment_shader(fs)
+
+ nverts = 4
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ x = 0
+ y = 0
+ w = dst_surface.width
+ h = dst_surface.height
+
+ pos = [
+ [x, y],
+ [x+w, y],
+ [x+w, y+h],
+ [x, y+h],
+ ]
+
+ tex = [
+ [0.0, 0.0],
+ [1.0, 0.0],
+ [1.0, 1.0],
+ [0.0, 1.0],
+ ]
+
+ for i in range(0, 4):
+ j = 8*i
+ verts[j + 0] = pos[i][0] # x
+ verts[j + 1] = pos[i][1] # y
+ verts[j + 2] = 0.0 # z
+ verts[j + 3] = 1.0 # w
+ verts[j + 4] = tex[i][0] # s
+ verts[j + 5] = tex[i][1] # r
+ verts[j + 6] = 0.0
+ verts[j + 7] = 1.0
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ self.assert_rgba(dst_surface, x, y, w, h, expected_rgba, 4.0/256, 0.85)
+
+
+
+def main():
+ dev = Device()
+ suite = TestSuite()
+
+ targets = [
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_CUBE,
+ #PIPE_TEXTURE_3D,
+ ]
+
+ formats = [
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ #PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ #PIPE_FORMAT_Z32_UNORM,
+ #PIPE_FORMAT_Z24S8_UNORM,
+ #PIPE_FORMAT_Z24X8_UNORM,
+ #PIPE_FORMAT_Z16_UNORM,
+ #PIPE_FORMAT_S8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ #PIPE_FORMAT_DXT1_RGB,
+ #PIPE_FORMAT_DXT1_RGBA,
+ #PIPE_FORMAT_DXT3_RGBA,
+ #PIPE_FORMAT_DXT5_RGBA,
+ ]
+
+ sizes = [64, 32, 16, 8, 4, 2, 1]
+ #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
+ #sizes = [64]
+ #sizes = [63]
+
+ faces = [
+ PIPE_TEX_FACE_POS_X,
+ PIPE_TEX_FACE_NEG_X,
+ PIPE_TEX_FACE_POS_Y,
+ PIPE_TEX_FACE_NEG_Y,
+ PIPE_TEX_FACE_POS_Z,
+ PIPE_TEX_FACE_NEG_Z,
+ ]
+
+ for target in targets:
+ for format in formats:
+ for size in sizes:
+ if target == PIPE_TEXTURE_3D:
+ depth = size
+ else:
+ depth = 1
+ for face in faces:
+ if target != PIPE_TEXTURE_CUBE and face:
+ continue
+ levels = lods(size)
+ for last_level in range(levels):
+ for level in range(0, last_level + 1):
+ zslice = 0
+ while zslice < depth >> level:
+ test = TextureTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ zslice = (zslice + 1)*2 - 1
+ suite.run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/texture_sample.py b/src/gallium/state_trackers/python/tests/texture_sample.py
new file mode 100755
index 0000000000..c7b78abbbe
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/texture_sample.py
@@ -0,0 +1,591 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL 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.
+#
+##########################################################################
+
+
+from gallium import *
+from base import *
+
+
+def lods(*dims):
+ size = max(dims)
+ lods = 0
+ while size:
+ lods += 1
+ size >>= 1
+ return lods
+
+
+def minify(dims, level = 1):
+ return [max(dim>>level, 1) for dim in dims]
+
+
+def tex_coords(texture, face, level, zslice):
+ st = [
+ [0.0, 0.0],
+ [1.0, 0.0],
+ [1.0, 1.0],
+ [0.0, 1.0],
+ ]
+
+ if texture.target == PIPE_TEXTURE_2D:
+ return [[s, t, 0.0] for s, t in st]
+ elif texture.target == PIPE_TEXTURE_3D:
+ depth = texture.get_depth(level)
+ if depth > 1:
+ r = float(zslice)/float(depth - 1)
+ else:
+ r = 0.0
+ return [[s, t, r] for s, t in st]
+ elif texture.target == PIPE_TEXTURE_CUBE:
+ result = []
+ for s, t in st:
+ # See http://developer.nvidia.com/object/cube_map_ogl_tutorial.html
+ sc = 2.0*s - 1.0
+ tc = 2.0*t - 1.0
+ if face == PIPE_TEX_FACE_POS_X:
+ rx = 1.0
+ ry = -tc
+ rz = -sc
+ if face == PIPE_TEX_FACE_NEG_X:
+ rx = -1.0
+ ry = -tc
+ rz = sc
+ if face == PIPE_TEX_FACE_POS_Y:
+ rx = sc
+ ry = 1.0
+ rz = tc
+ if face == PIPE_TEX_FACE_NEG_Y:
+ rx = sc
+ ry = -1.0
+ rz = -tc
+ if face == PIPE_TEX_FACE_POS_Z:
+ rx = sc
+ ry = -tc
+ rz = 1.0
+ if face == PIPE_TEX_FACE_NEG_Z:
+ rx = -sc
+ ry = -tc
+ rz = -1.0
+ result.append([rx, ry, rz])
+ return result
+
+def is_pot(n):
+ return n & (n - 1) == 0
+
+
+class TextureColorSampleTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER
+ geom_flags = 0
+ if width != height:
+ geom_flags |= PIPE_TEXTURE_GEOM_NON_SQUARE
+ if not is_pot(width) or not is_pot(height) or not is_pot(depth):
+ geom_flags |= PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
+
+ if not dev.is_format_supported(format, target, tex_usage, geom_flags):
+ raise TestSkip
+
+ ctx = self.dev.context_create()
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # no-op depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.bypass_vs_clip_and_viewport = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ sampler.min_lod = 0
+ sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1
+ ctx.set_sampler(0, sampler)
+
+ # texture
+ texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = tex_usage,
+ )
+
+ expected_rgba = FloatArray(height*width*4)
+ texture.get_surface(
+ face = face,
+ level = level,
+ zslice = zslice,
+ ).sample_rgba(expected_rgba)
+
+ ctx.set_sampler_texture(0, texture)
+
+ # framebuffer
+ cbuf_tex = dev.texture_create(
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ width,
+ height,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+
+ cbuf = cbuf_tex.get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.5
+ rgba[1] = 0.5
+ rgba[2] = 0.5
+ rgba[3] = 0.5
+ ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
+ del fb
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION, CONSTANT
+ DCL IN[1], GENERIC, CONSTANT
+ DCL OUT[0], POSITION, CONSTANT
+ DCL OUT[1], GENERIC, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:MOV OUT[1], IN[1]
+ 2:END
+ ''')
+ #vs.dump()
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ op = {
+ PIPE_TEXTURE_1D: "1D",
+ PIPE_TEXTURE_2D: "2D",
+ PIPE_TEXTURE_3D: "3D",
+ PIPE_TEXTURE_CUBE: "CUBE",
+ }[target]
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], GENERIC[0], LINEAR
+ DCL OUT[0], COLOR, CONSTANT
+ DCL SAMP[0], CONSTANT
+ 0:TEX OUT[0], IN[0], SAMP[0], %s
+ 1:END
+ ''' % op)
+ #fs.dump()
+ ctx.set_fragment_shader(fs)
+
+ nverts = 4
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ x = 0
+ y = 0
+ w, h = minify((width, height), level)
+
+ pos = [
+ [x, y],
+ [x+w, y],
+ [x+w, y+h],
+ [x, y+h],
+ ]
+
+ tex = tex_coords(texture, face, level, zslice)
+
+ for i in range(0, 4):
+ j = 8*i
+ verts[j + 0] = pos[i][0] # x
+ verts[j + 1] = pos[i][1] # y
+ verts[j + 2] = 0.0 # z
+ verts[j + 3] = 1.0 # w
+ verts[j + 4] = tex[i][0] # s
+ verts[j + 5] = tex[i][1] # r
+ verts[j + 6] = tex[i][2] # q
+ verts[j + 7] = 1.0
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ cbuf = cbuf_tex.get_surface()
+
+ self.assert_rgba(cbuf, x, y, w, h, expected_rgba, 4.0/256, 0.85)
+
+
+class TextureDepthSampleTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER
+ geom_flags = 0
+ if width != height:
+ geom_flags |= PIPE_TEXTURE_GEOM_NON_SQUARE
+ if not is_pot(width) or not is_pot(height) or not is_pot(depth):
+ geom_flags |= PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
+
+ if not dev.is_format_supported(format, target, tex_usage, geom_flags):
+ raise TestSkip
+
+ ctx = self.dev.context_create()
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ depth_stencil_alpha.depth.enabled = 1
+ depth_stencil_alpha.depth.writemask = 1
+ depth_stencil_alpha.depth.func = PIPE_FUNC_LESS
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.bypass_vs_clip_and_viewport = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ sampler.min_lod = 0
+ sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1
+ ctx.set_sampler(0, sampler)
+
+ # texture
+ texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = tex_usage,
+ )
+
+ expected_rgba = FloatArray(height*width*4)
+ texture.get_surface(
+ face = face,
+ level = level,
+ zslice = zslice,
+ ).sample_rgba(expected_rgba)
+
+ ctx.set_sampler_texture(0, texture)
+
+ # framebuffer
+ cbuf_tex = dev.texture_create(
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ width,
+ height,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+
+ zsbuf_tex = dev.texture_create(
+ PIPE_FORMAT_Z24X8_UNORM,
+ width,
+ height,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+
+ cbuf = cbuf_tex.get_surface()
+ zsbuf = zsbuf_tex.get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ fb.set_zsbuf(zsbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.5
+ rgba[1] = 0.5
+ rgba[2] = 0.5
+ rgba[3] = 0.5
+ ctx.clear(PIPE_CLEAR_DEPTHSTENCIL, rgba, 1.0, 0)
+ del fb
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION, CONSTANT
+ DCL IN[1], GENERIC, CONSTANT
+ DCL OUT[0], POSITION, CONSTANT
+ DCL OUT[1], GENERIC, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:MOV OUT[1], IN[1]
+ 2:END
+ ''')
+ #vs.dump()
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ op = {
+ PIPE_TEXTURE_1D: "1D",
+ PIPE_TEXTURE_2D: "2D",
+ PIPE_TEXTURE_3D: "3D",
+ PIPE_TEXTURE_CUBE: "CUBE",
+ }[target]
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], GENERIC[0], LINEAR
+ DCL SAMP[0], CONSTANT
+ DCL OUT[0].z, POSITION
+ 0:TEX OUT[0].z, IN[0], SAMP[0], %s
+ 1:END
+ ''' % op)
+ #fs.dump()
+ ctx.set_fragment_shader(fs)
+
+ nverts = 4
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ x = 0
+ y = 0
+ w, h = minify((width, height), level)
+
+ pos = [
+ [x, y],
+ [x+w, y],
+ [x+w, y+h],
+ [x, y+h],
+ ]
+
+ tex = tex_coords(texture, face, level, zslice)
+
+ for i in range(0, 4):
+ j = 8*i
+ verts[j + 0] = pos[i][0] # x
+ verts[j + 1] = pos[i][1] # y
+ verts[j + 2] = 0.0 # z
+ verts[j + 3] = 1.0 # w
+ verts[j + 4] = tex[i][0] # s
+ verts[j + 5] = tex[i][1] # r
+ verts[j + 6] = tex[i][2] # q
+ verts[j + 7] = 1.0
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ zsbuf = zsbuf_tex.get_surface()
+
+ self.assert_rgba(zsbuf, x, y, w, h, expected_rgba, 4.0/256, 0.85)
+
+
+
+
+def main():
+ dev = Device()
+ suite = TestSuite()
+
+ targets = [
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_CUBE,
+ PIPE_TEXTURE_3D,
+ ]
+
+ color_formats = [
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ #PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_YCBCR,
+ PIPE_FORMAT_DXT1_RGB,
+ #PIPE_FORMAT_DXT1_RGBA,
+ #PIPE_FORMAT_DXT3_RGBA,
+ #PIPE_FORMAT_DXT5_RGBA,
+ ]
+
+ depth_formats = [
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_Z16_UNORM,
+ ]
+
+ sizes = [64, 32, 16, 8, 4, 2, 1]
+ #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
+ #sizes = [64]
+ #sizes = [63]
+
+ faces = [
+ PIPE_TEX_FACE_POS_X,
+ PIPE_TEX_FACE_NEG_X,
+ PIPE_TEX_FACE_POS_Y,
+ PIPE_TEX_FACE_NEG_Y,
+ PIPE_TEX_FACE_POS_Z,
+ PIPE_TEX_FACE_NEG_Z,
+ ]
+
+ for format in color_formats:
+ for target in targets:
+ for size in sizes:
+ if target == PIPE_TEXTURE_3D:
+ depth = size
+ else:
+ depth = 1
+ for face in faces:
+ if target != PIPE_TEXTURE_CUBE and face:
+ continue
+ levels = lods(size)
+ for last_level in range(levels):
+ for level in range(0, last_level + 1):
+ zslice = 0
+ while zslice < depth >> level:
+ test = TextureColorSampleTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ zslice = (zslice + 1)*2 - 1
+ for format in depth_formats:
+ target = PIPE_TEXTURE_2D
+ depth = 1
+ face = 0
+ last_level = 0
+ level = 0
+ zslice = 0
+ for size in sizes:
+ test = TextureDepthSampleTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ suite.run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/texture_transfer.py b/src/gallium/state_trackers/python/tests/texture_transfer.py
new file mode 100755
index 0000000000..e65b425adf
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/texture_transfer.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL 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.
+#
+##########################################################################
+
+
+import os
+
+from gallium import *
+from base import *
+
+
+def lods(*dims):
+ size = max(dims)
+ lods = 0
+ while size:
+ lods += 1
+ size >>= 1
+ return lods
+
+
+class TextureTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ tex_usage = 0
+
+ texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = tex_usage,
+ )
+ if texture is None:
+ raise TestSkip
+
+ surface = texture.get_surface(face, level, zslice)
+
+ stride = surface.nblocksx * texture.block.size
+ size = surface.nblocksy * stride
+
+ in_raw = os.urandom(size)
+
+ surface.put_tile_raw(0, 0, surface.width, surface.height, in_raw, stride)
+
+ out_raw = surface.get_tile_raw(0, 0, surface.width, surface.height)
+
+ if in_raw != out_raw:
+ raise TestFailure
+
+
+def main():
+ dev = Device()
+ suite = TestSuite()
+
+ targets = [
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_CUBE,
+ PIPE_TEXTURE_3D,
+ ]
+
+ formats = [
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_S8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_DXT1_RGB,
+ PIPE_FORMAT_DXT1_RGBA,
+ PIPE_FORMAT_DXT3_RGBA,
+ PIPE_FORMAT_DXT5_RGBA,
+ ]
+
+ sizes = [64, 32, 16, 8, 4, 2, 1]
+ #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
+ #sizes = [64]
+ #sizes = [63]
+
+ faces = [
+ PIPE_TEX_FACE_POS_X,
+ PIPE_TEX_FACE_NEG_X,
+ PIPE_TEX_FACE_POS_Y,
+ PIPE_TEX_FACE_NEG_Y,
+ PIPE_TEX_FACE_POS_Z,
+ PIPE_TEX_FACE_NEG_Z,
+ ]
+
+ for target in targets:
+ for format in formats:
+ for size in sizes:
+ if target == PIPE_TEXTURE_3D:
+ depth = size
+ else:
+ depth = 1
+ for face in faces:
+ if target != PIPE_TEXTURE_CUBE and face:
+ continue
+ levels = lods(size)
+ for last_level in range(levels):
+ for level in range(0, last_level + 1):
+ zslice = 0
+ while zslice < depth >> level:
+ test = TextureTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ zslice = (zslice + 1)*2 - 1
+ suite.run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/tree.py b/src/gallium/state_trackers/python/tests/tree.py
new file mode 100755
index 0000000000..0c1bcda4cf
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/tree.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+#
+# See also:
+# http://www.ailab.si/orange/doc/ofb/c_otherclass.htm
+
+import os.path
+import sys
+
+import orange
+import orngTree
+
+for arg in sys.argv[1:]:
+ name, ext = os.path.splitext(arg)
+
+ data = orange.ExampleTable(arg)
+
+ tree = orngTree.TreeLearner(data, sameMajorityPruning=1, mForPruning=2)
+
+ orngTree.printTxt(tree)
+
+ file(name+'.txt', 'wt').write(orngTree.dumpTree(tree) + '\n')
+
+ orngTree.printDot(tree, fileName=name+'.dot', nodeShape='ellipse', leafShape='box')
diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile
new file mode 100644
index 0000000000..b8c805b06c
--- /dev/null
+++ b/src/gallium/state_trackers/vega/Makefile
@@ -0,0 +1,128 @@
+# src/mesa/Makefile
+
+TOP = ../../../..
+include $(TOP)/configs/current
+GALLIUM = $(TOP)
+
+### Lists of source files, included by Makefiles
+
+VG_SOURCES = \
+ api_context.c \
+ api_filters.c \
+ api_images.c \
+ api_masks.c \
+ api_misc.c \
+ api_paint.c \
+ api_params.c \
+ api_path.c \
+ api_text.c \
+ api_transform.c \
+ vgu.c \
+ vg_context.c \
+ vg_state.c \
+ vg_tracker.c \
+ vg_translate.c \
+ polygon.c \
+ bezier.c \
+ path.c \
+ paint.c \
+ arc.c \
+ image.c \
+ renderer.c \
+ stroker.c \
+ mask.c \
+ shader.c \
+ shaders_cache.c
+
+
+### All the core C sources
+
+ALL_SOURCES = \
+ $(VG_SOURCES)
+
+
+### Object files
+VG_OBJECTS = \
+ $(VG_SOURCES:.c=.o)
+
+### Include directories
+
+INCLUDE_DIRS = \
+ -I$(TOP)/include \
+ -I$(GALLIUM)/include \
+ -I$(GALLIUM)/src/gallium/include \
+ -I$(GALLIUM)/src/gallium/auxiliary
+
+VG_LIB = OpenVG
+VG_LIB_NAME = lib$(VG_LIB).so
+
+VG_MAJOR = 1
+VG_MINOR = 0
+VG_TINY = 0
+
+GALLIUM_LIBS = \
+ $(GALLIUM)/src/gallium/auxiliary/pipebuffer/libpipebuffer.a \
+ $(GALLIUM)/src/gallium/auxiliary/sct/libsct.a \
+ $(GALLIUM)/src/gallium/auxiliary/draw/libdraw.a \
+ $(GALLIUM)/src/gallium/auxiliary/rtasm/librtasm.a \
+ $(GALLIUM)/src/gallium/auxiliary/translate/libtranslate.a \
+ $(GALLIUM)/src/gallium/auxiliary/cso_cache/libcso_cache.a \
+ $(GALLIUM)/src/gallium/auxiliary/util/libutil.a \
+ $(GALLIUM)/src/gallium/auxiliary/tgsi/libtgsi.a
+
+.SUFFIXES : .cpp
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+.cpp.o:
+ $(CXX) -c $(INCLUDE_DIRS) $(CXXFLAGS) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+default: depend subdirs $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME)
+
+# Make the OpenVG library
+$(TOP)/$(LIB_DIR)/$(VG_LIB_NAME): $(VG_OBJECTS) $(GALLIUM_LIBS)
+ $(TOP)/bin/mklib -o $(VG_LIB) \
+ -major $(VG_MAJOR) \
+ -minor $(VG_MINOR) \
+ -patch $(VG_TINY) \
+ -install $(TOP)/$(LIB_DIR) \
+ $(VG_OBJECTS) $(GALLIUM_LIBS) \
+ -Wl,--whole-archive $(LIBS) -Wl,--no-whole-archive $(SYS_LIBS)
+
+######################################################################
+# Generic stuff
+
+depend: $(ALL_SOURCES)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend # workaround oops on gutsy?!?
+ @ touch depend
+ @ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \
+ > /dev/null 2>/dev/null
+
+
+subdirs:
+
+install: default
+ $(INSTALL) -d $(INSTALL_DIR)/include/VG
+ $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR)
+ $(INSTALL) -m 644 $(TOP)/include/VG/*.h $(INSTALL_DIR)/include/VG
+ @if [ -e $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) ]; then \
+ $(INSTALL) $(TOP)/$(LIB_DIR)/libOpenVG* $(INSTALL_DIR)/$(LIB_DIR); \
+ fi
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` $(TOP)/include/VG/*.h
+
+clean:
+ -rm -f *.o
+ -rm -f */*.o
+ -rm -f */*/*.o
+ -rm -f depend depend.bak
+
+include depend
diff --git a/src/gallium/state_trackers/vega/api_consts.h b/src/gallium/state_trackers/vega/api_consts.h
new file mode 100644
index 0000000000..e1b48d4a46
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_consts.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef API_CONSTS_H
+#define API_CONSTS_H
+
+/*must be at least 32*/
+#define VEGA_MAX_SCISSOR_RECTS 32
+
+/*must be at least 16*/
+#define VEGA_MAX_DASH_COUNT 32
+
+/*must be at least 7*/
+#define VEGA_MAX_KERNEL_SIZE 7
+
+/*must be at least 15*/
+#define VEGA_MAX_SEPARABLE_KERNEL_SIZE 15
+
+/*must be at least 32*/
+#define VEGA_MAX_COLOR_RAMP_STOPS 256
+
+#define VEGA_MAX_IMAGE_WIDTH 2048
+
+#define VEGA_MAX_IMAGE_HEIGHT 2048
+
+#define VEGA_MAX_IMAGE_PIXELS (2048*2048)
+
+#define VEGA_MAX_IMAGE_BYTES (2048*2048 * 4)
+
+/*must be at least 128*/
+#define VEGA_MAX_GAUSSIAN_STD_DEVIATION 128
+
+#endif
diff --git a/src/gallium/state_trackers/vega/api_context.c b/src/gallium/state_trackers/vega/api_context.c
new file mode 100644
index 0000000000..47db102dd2
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_context.c
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+
+#include "vg_context.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+
+VGErrorCode vgGetError(void)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGErrorCode error = VG_NO_CONTEXT_ERROR;
+
+ if (!ctx)
+ return error;
+
+ error = ctx->_error;
+ ctx->_error = VG_NO_ERROR;
+
+ return error;
+}
+
+void vgFlush(void)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_context *pipe;
+
+ if (!ctx)
+ return;
+
+ pipe = ctx->pipe;
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+}
+
+void vgFinish(void)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_fence_handle *fence = NULL;
+ struct pipe_context *pipe;
+
+ if (!ctx)
+ return;
+
+ pipe = ctx->pipe;
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
+
+ pipe->screen->fence_finish(pipe->screen, fence, 0);
+ pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+}
diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c
new file mode 100644
index 0000000000..862cbb03c4
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_filters.c
@@ -0,0 +1,805 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+
+#include "vg_context.h"
+#include "image.h"
+#include "renderer.h"
+#include "shaders_cache.h"
+#include "st_inlines.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_memory.h"
+
+
+#include "asm_filters.h"
+
+
+struct filter_info {
+ struct vg_image *dst;
+ struct vg_image *src;
+ struct vg_shader * (*setup_shader)(struct vg_context *, void *);
+ void *user_data;
+ const void *const_buffer;
+ VGint const_buffer_len;
+ VGTilingMode tiling_mode;
+ struct pipe_texture *extra_texture;
+};
+
+static INLINE struct pipe_texture *create_texture_1d(struct vg_context *ctx,
+ const VGuint *color_data,
+ const VGint color_data_len)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture *tex = 0;
+ struct pipe_texture templ;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_1D;
+ templ.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ templ.last_level = 0;
+ templ.width[0] = color_data_len;
+ templ.height[0] = 1;
+ templ.depth[0] = 1;
+ pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &templ.block);
+ templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+
+ tex = screen->texture_create(screen, &templ);
+
+ { /* upload color_data */
+ struct pipe_transfer *transfer =
+ screen->get_tex_transfer(screen, tex,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ_WRITE ,
+ 0, 0, tex->width[0], tex->height[0]);
+ void *map = screen->transfer_map(screen, transfer);
+ memcpy(map, color_data, sizeof(VGint)*color_data_len);
+ screen->transfer_unmap(screen, transfer);
+ screen->tex_transfer_destroy(transfer);
+ }
+
+ return tex;
+}
+
+static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_framebuffer_state fb;
+ struct pipe_surface *dst_surf = pipe->screen->get_tex_surface(
+ pipe->screen, dst->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* drawing dest */
+ memset(&fb, 0, sizeof(fb));
+ fb.width = dst->x + dst_surf->width;
+ fb.height = dst->y + dst_surf->height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = dst_surf;
+ {
+ VGint i;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ fb.cbufs[i] = 0;
+ }
+ cso_set_framebuffer(ctx->cso_context, &fb);
+
+ return dst_surf;
+}
+
+static void setup_viewport(struct vg_image *dst)
+{
+ struct vg_context *ctx = vg_current_context();
+ vg_set_viewport(ctx, VEGA_Y0_TOP);
+}
+
+static void setup_blend()
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ if (ctx->state.vg.filter_channel_mask & VG_RED)
+ blend.colormask |= PIPE_MASK_R;
+ if (ctx->state.vg.filter_channel_mask & VG_GREEN)
+ blend.colormask |= PIPE_MASK_G;
+ if (ctx->state.vg.filter_channel_mask & VG_BLUE)
+ blend.colormask |= PIPE_MASK_B;
+ if (ctx->state.vg.filter_channel_mask & VG_ALPHA)
+ blend.colormask |= PIPE_MASK_A;
+ blend.blend_enable = 1;
+ cso_set_blend(ctx->cso_context, &blend);
+}
+
+static void setup_constant_buffer(struct vg_context *ctx, const void *buffer,
+ VGint param_bytes)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_constant_buffer *cbuf = &ctx->filter.buffer;
+
+ /* We always need to get a new buffer, to keep the drivers simple and
+ * avoid gratuitous rendering synchronization. */
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+
+ cbuf->buffer = pipe_buffer_create(pipe->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+
+ if (cbuf->buffer) {
+ st_no_flush_pipe_buffer_write(ctx, cbuf->buffer,
+ 0, param_bytes, buffer);
+ }
+
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+}
+
+static void setup_samplers(struct vg_context *ctx, struct filter_info *info)
+{
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_state sampler[3];
+ int num_samplers = 0;
+ int num_textures = 0;
+
+ samplers[0] = NULL;
+ samplers[1] = NULL;
+ samplers[2] = NULL;
+ samplers[3] = NULL;
+ textures[0] = NULL;
+ textures[1] = NULL;
+ textures[2] = NULL;
+ textures[3] = NULL;
+
+ memset(&sampler[0], 0, sizeof(struct pipe_sampler_state));
+ sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler[0].wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler[0].min_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
+ sampler[0].mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
+ sampler[0].normalized_coords = 1;
+
+ switch(info->tiling_mode) {
+ case VG_TILE_FILL:
+ sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ memcpy(sampler[0].border_color,
+ ctx->state.vg.tile_fill_color,
+ sizeof(VGfloat) * 4);
+ break;
+ case VG_TILE_PAD:
+ sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ break;
+ case VG_TILE_REPEAT:
+ sampler[0].wrap_s = PIPE_TEX_WRAP_REPEAT;
+ sampler[0].wrap_t = PIPE_TEX_WRAP_REPEAT;
+ break;
+ case VG_TILE_REFLECT:
+ sampler[0].wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
+ sampler[0].wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT;
+ break;
+ default:
+ debug_assert(!"Unknown tiling mode");
+ }
+
+ samplers[0] = &sampler[0];
+ textures[0] = info->src->texture;
+ ++num_samplers;
+ ++num_textures;
+
+ if (info->extra_texture) {
+ memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state));
+ samplers[1] = &sampler[1];
+ textures[1] = info->extra_texture;
+ ++num_samplers;
+ ++num_textures;
+ }
+
+
+ cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers);
+ cso_set_sampler_textures(ctx->cso_context, num_textures, textures);
+}
+
+static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data)
+{
+ struct vg_shader *shader =
+ shader_create_from_text(ctx->pipe, color_matrix_asm, 200,
+ PIPE_SHADER_FRAGMENT);
+ cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
+ return shader;
+}
+
+static struct vg_shader * setup_convolution(struct vg_context *ctx, void *user_data)
+{
+ char buffer[1024];
+ VGint num_consts = (VGint)(long)(user_data);
+ struct vg_shader *shader;
+
+ snprintf(buffer, 1023, convolution_asm, num_consts, num_consts / 2 + 1);
+
+ shader = shader_create_from_text(ctx->pipe, buffer, 200,
+ PIPE_SHADER_FRAGMENT);
+
+ cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
+ return shader;
+}
+
+static struct vg_shader * setup_lookup(struct vg_context *ctx, void *user_data)
+{
+ struct vg_shader *shader =
+ shader_create_from_text(ctx->pipe, lookup_asm,
+ 200, PIPE_SHADER_FRAGMENT);
+
+ cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
+ return shader;
+}
+
+
+static struct vg_shader * setup_lookup_single(struct vg_context *ctx, void *user_data)
+{
+ char buffer[1024];
+ VGImageChannel channel = (VGImageChannel)(user_data);
+ struct vg_shader *shader;
+
+ switch(channel) {
+ case VG_RED:
+ snprintf(buffer, 1023, lookup_single_asm, "xxxx");
+ break;
+ case VG_GREEN:
+ snprintf(buffer, 1023, lookup_single_asm, "yyyy");
+ break;
+ case VG_BLUE:
+ snprintf(buffer, 1023, lookup_single_asm, "zzzz");
+ break;
+ case VG_ALPHA:
+ snprintf(buffer, 1023, lookup_single_asm, "wwww");
+ break;
+ default:
+ debug_assert(!"Unknown color channel");
+ }
+
+ shader = shader_create_from_text(ctx->pipe, buffer, 200,
+ PIPE_SHADER_FRAGMENT);
+
+ cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
+ return shader;
+}
+
+static void execute_filter(struct vg_context *ctx,
+ struct filter_info *info)
+{
+ struct pipe_surface *dst_surf;
+ struct vg_shader *shader;
+
+ cso_save_framebuffer(ctx->cso_context);
+ cso_save_fragment_shader(ctx->cso_context);
+ cso_save_viewport(ctx->cso_context);
+ cso_save_blend(ctx->cso_context);
+ cso_save_samplers(ctx->cso_context);
+ cso_save_sampler_textures(ctx->cso_context);
+
+ dst_surf = setup_framebuffer(info->dst);
+ setup_viewport(info->dst);
+ setup_blend();
+ setup_constant_buffer(ctx, info->const_buffer, info->const_buffer_len);
+ shader = info->setup_shader(ctx, info->user_data);
+ setup_samplers(ctx, info);
+
+ renderer_draw_texture(ctx->renderer,
+ info->src->texture,
+ info->dst->x, info->dst->y,
+ info->dst->x + info->dst->width,
+ info->dst->y + info->dst->height,
+ info->dst->x, info->dst->y,
+ info->dst->x + info->dst->width,
+ info->dst->y + info->dst->height);
+
+ cso_restore_framebuffer(ctx->cso_context);
+ cso_restore_fragment_shader(ctx->cso_context);
+ cso_restore_viewport(ctx->cso_context);
+ cso_restore_blend(ctx->cso_context);
+ cso_restore_samplers(ctx->cso_context);
+ cso_restore_sampler_textures(ctx->cso_context);
+
+ vg_shader_destroy(ctx, shader);
+
+ pipe_surface_reference(&dst_surf, NULL);
+}
+
+void vgColorMatrix(VGImage dst, VGImage src,
+ const VGfloat * matrix)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *d, *s;
+ struct filter_info info;
+
+ if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (!matrix || !is_aligned(matrix)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ d = (struct vg_image*)dst;
+ s = (struct vg_image*)src;
+
+ if (vg_image_overlaps(d, s)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ info.dst = d;
+ info.src = s;
+ info.setup_shader = &setup_color_matrix;
+ info.user_data = NULL;
+ info.const_buffer = matrix;
+ info.const_buffer_len = 20 * sizeof(VGfloat);
+ info.tiling_mode = VG_TILE_PAD;
+ info.extra_texture = 0;
+ execute_filter(ctx, &info);
+}
+
+static VGfloat texture_offset(VGfloat width, VGint kernelSize, VGint current, VGint shift)
+{
+ VGfloat diff = current - shift;
+
+ return diff / width;
+}
+
+void vgConvolve(VGImage dst, VGImage src,
+ VGint kernelWidth, VGint kernelHeight,
+ VGint shiftX, VGint shiftY,
+ const VGshort * kernel,
+ VGfloat scale,
+ VGfloat bias,
+ VGTilingMode tilingMode)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGfloat *buffer;
+ VGint buffer_len;
+ VGint i, j;
+ VGint idx = 0;
+ struct vg_image *d, *s;
+ VGint kernel_size = kernelWidth * kernelHeight;
+ struct filter_info info;
+ const VGint max_kernel_size = vgGeti(VG_MAX_KERNEL_SIZE);
+
+ if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (kernelWidth <= 0 || kernelHeight <= 0 ||
+ kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (!kernel || !is_aligned_to(kernel, 2)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (tilingMode < VG_TILE_FILL ||
+ tilingMode > VG_TILE_REFLECT) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ d = (struct vg_image*)dst;
+ s = (struct vg_image*)src;
+
+ if (vg_image_overlaps(d, s)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ vg_validate_state(ctx);
+
+ buffer_len = 8 + 2 * 4 * kernel_size;
+ buffer = (VGfloat*)malloc(buffer_len * sizeof(VGfloat));
+
+ buffer[0] = 0.f;
+ buffer[1] = 1.f;
+ buffer[2] = 2.f; /*unused*/
+ buffer[3] = 4.f; /*unused*/
+
+ buffer[4] = kernelWidth * kernelHeight;
+ buffer[5] = scale;
+ buffer[6] = bias;
+ buffer[7] = 0.f;
+
+ idx = 8;
+ for (j = 0; j < kernelHeight; ++j) {
+ for (i = 0; i < kernelWidth; ++i) {
+ VGint index = j * kernelWidth + i;
+ VGfloat x, y;
+
+ x = texture_offset(s->width, kernelWidth, i, shiftX);
+ y = texture_offset(s->height, kernelHeight, j, shiftY);
+
+ buffer[idx + index*4 + 0] = x;
+ buffer[idx + index*4 + 1] = y;
+ buffer[idx + index*4 + 2] = 0.f;
+ buffer[idx + index*4 + 3] = 0.f;
+ }
+ }
+ idx += kernel_size * 4;
+
+ for (j = 0; j < kernelHeight; ++j) {
+ for (i = 0; i < kernelWidth; ++i) {
+ /* transpose the kernel */
+ VGint index = j * kernelWidth + i;
+ VGint kindex = (kernelWidth - i - 1) * kernelHeight + (kernelHeight - j - 1);
+ buffer[idx + index*4 + 0] = kernel[kindex];
+ buffer[idx + index*4 + 1] = kernel[kindex];
+ buffer[idx + index*4 + 2] = kernel[kindex];
+ buffer[idx + index*4 + 3] = kernel[kindex];
+ }
+ }
+
+ info.dst = d;
+ info.src = s;
+ info.setup_shader = &setup_convolution;
+ info.user_data = (void*)(long)(buffer_len/4);
+ info.const_buffer = buffer;
+ info.const_buffer_len = buffer_len * sizeof(VGfloat);
+ info.tiling_mode = tilingMode;
+ info.extra_texture = 0;
+ execute_filter(ctx, &info);
+
+ free(buffer);
+}
+
+void vgSeparableConvolve(VGImage dst, VGImage src,
+ VGint kernelWidth,
+ VGint kernelHeight,
+ VGint shiftX, VGint shiftY,
+ const VGshort * kernelX,
+ const VGshort * kernelY,
+ VGfloat scale,
+ VGfloat bias,
+ VGTilingMode tilingMode)
+{
+ 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);
+
+ if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (kernelWidth <= 0 || kernelHeight <= 0 ||
+ kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (!kernelX || !kernelY ||
+ !is_aligned_to(kernelX, 2) || !is_aligned_to(kernelY, 2)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (tilingMode < VG_TILE_FILL ||
+ tilingMode > VG_TILE_REFLECT) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ kernel = malloc(sizeof(VGshort)*kernelWidth*kernelHeight);
+ for (i = 0; i < kernelWidth; ++i) {
+ for (j = 0; j < kernelHeight; ++j) {
+ kernel[idx] = kernelX[i] * kernelY[j];
+ ++idx;
+ }
+ }
+ vgConvolve(dst, src, kernelWidth, kernelHeight, shiftX, shiftY,
+ kernel, scale, bias, tilingMode);
+ free(kernel);
+}
+
+static INLINE VGfloat compute_gaussian_componenet(VGfloat x, VGfloat y,
+ VGfloat stdDeviationX,
+ VGfloat stdDeviationY)
+{
+ VGfloat mult = 1 / ( 2 * M_PI * stdDeviationX * stdDeviationY);
+ VGfloat e = exp( - ( pow(x, 2)/(2*pow(stdDeviationX, 2)) +
+ pow(y, 2)/(2*pow(stdDeviationY, 2)) ) );
+ return mult * e;
+}
+
+static INLINE VGint compute_kernel_size(VGfloat deviation)
+{
+ VGint size = ceil(2.146 * deviation);
+ if (size > 11)
+ return 11;
+ return size;
+}
+
+static void compute_gaussian_kernel(VGfloat *kernel,
+ VGint width, VGint height,
+ VGfloat stdDeviationX,
+ VGfloat stdDeviationY)
+{
+ VGint i, j;
+ VGfloat scale = 0.0f;
+
+ for (j = 0; j < height; ++j) {
+ for (i = 0; i < width; ++i) {
+ VGint idx = (height - j -1) * width + (width - i -1);
+ kernel[idx] = compute_gaussian_componenet(i-(ceil(width/2))-1,
+ j-ceil(height/2)-1,
+ stdDeviationX, stdDeviationY);
+ scale += kernel[idx];
+ }
+ }
+
+ for (j = 0; j < height; ++j) {
+ for (i = 0; i < width; ++i) {
+ VGint idx = j * width + i;
+ kernel[idx] /= scale;
+ }
+ }
+}
+
+void vgGaussianBlur(VGImage dst, VGImage src,
+ VGfloat stdDeviationX,
+ VGfloat stdDeviationY,
+ VGTilingMode tilingMode)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *d, *s;
+ VGfloat *buffer, *kernel;
+ VGint kernel_width, kernel_height, kernel_size;
+ VGint buffer_len;
+ VGint idx, i, j;
+ struct filter_info info;
+
+ if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (stdDeviationX <= 0 || stdDeviationY <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (tilingMode < VG_TILE_FILL ||
+ tilingMode > VG_TILE_REFLECT) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ d = (struct vg_image*)dst;
+ s = (struct vg_image*)src;
+
+ if (vg_image_overlaps(d, s)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ kernel_width = compute_kernel_size(stdDeviationX);
+ kernel_height = compute_kernel_size(stdDeviationY);
+ kernel_size = kernel_width * kernel_height;
+ kernel = malloc(sizeof(VGfloat)*kernel_size);
+ compute_gaussian_kernel(kernel, kernel_width, kernel_height,
+ stdDeviationX, stdDeviationY);
+
+ buffer_len = 8 + 2 * 4 * kernel_size;
+ buffer = (VGfloat*)malloc(buffer_len * sizeof(VGfloat));
+
+ buffer[0] = 0.f;
+ buffer[1] = 1.f;
+ buffer[2] = 2.f; /*unused*/
+ buffer[3] = 4.f; /*unused*/
+
+ buffer[4] = kernel_width * kernel_height;
+ buffer[5] = 1.f;/*scale*/
+ buffer[6] = 0.f;/*bias*/
+ buffer[7] = 0.f;
+
+ idx = 8;
+ for (j = 0; j < kernel_height; ++j) {
+ for (i = 0; i < kernel_width; ++i) {
+ VGint index = j * kernel_width + i;
+ VGfloat x, y;
+
+ x = texture_offset(s->width, kernel_width, i, kernel_width/2);
+ y = texture_offset(s->height, kernel_height, j, kernel_height/2);
+
+ buffer[idx + index*4 + 0] = x;
+ buffer[idx + index*4 + 1] = y;
+ buffer[idx + index*4 + 2] = 0.f;
+ buffer[idx + index*4 + 3] = 0.f;
+ }
+ }
+ idx += kernel_size * 4;
+
+ for (j = 0; j < kernel_height; ++j) {
+ for (i = 0; i < kernel_width; ++i) {
+ /* transpose the kernel */
+ VGint index = j * kernel_width + i;
+ VGint kindex = (kernel_width - i - 1) * kernel_height + (kernel_height - j - 1);
+ buffer[idx + index*4 + 0] = kernel[kindex];
+ buffer[idx + index*4 + 1] = kernel[kindex];
+ buffer[idx + index*4 + 2] = kernel[kindex];
+ buffer[idx + index*4 + 3] = kernel[kindex];
+ }
+ }
+
+ info.dst = d;
+ info.src = s;
+ info.setup_shader = &setup_convolution;
+ info.user_data = (void*)(long)(buffer_len/4);
+ info.const_buffer = buffer;
+ info.const_buffer_len = buffer_len * sizeof(VGfloat);
+ info.tiling_mode = tilingMode;
+ info.extra_texture = 0;
+ execute_filter(ctx, &info);
+
+ free(buffer);
+ free(kernel);
+}
+
+void vgLookup(VGImage dst, VGImage src,
+ const VGubyte * redLUT,
+ const VGubyte * greenLUT,
+ const VGubyte * blueLUT,
+ const VGubyte * alphaLUT,
+ VGboolean outputLinear,
+ VGboolean outputPremultiplied)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *d, *s;
+ VGuint color_data[256];
+ VGint i;
+ struct pipe_texture *lut_texture;
+ VGfloat buffer[4];
+ struct filter_info info;
+
+ if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (!redLUT || !greenLUT || !blueLUT || !alphaLUT) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ d = (struct vg_image*)dst;
+ s = (struct vg_image*)src;
+
+ if (vg_image_overlaps(d, s)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ for (i = 0; i < 256; ++i) {
+ color_data[i] = blueLUT[i] << 24 | greenLUT[i] << 16 |
+ redLUT[i] << 8 | alphaLUT[i];
+ }
+ lut_texture = create_texture_1d(ctx, color_data, 255);
+
+ buffer[0] = 0.f;
+ buffer[1] = 0.f;
+ buffer[2] = 1.f;
+ buffer[3] = 1.f;
+
+ info.dst = d;
+ info.src = s;
+ info.setup_shader = &setup_lookup;
+ info.user_data = NULL;
+ info.const_buffer = buffer;
+ info.const_buffer_len = 4 * sizeof(VGfloat);
+ info.tiling_mode = VG_TILE_PAD;
+ info.extra_texture = lut_texture;
+
+ execute_filter(ctx, &info);
+
+ pipe_texture_reference(&lut_texture, NULL);
+}
+
+void vgLookupSingle(VGImage dst, VGImage src,
+ const VGuint * lookupTable,
+ VGImageChannel sourceChannel,
+ VGboolean outputLinear,
+ VGboolean outputPremultiplied)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *d, *s;
+ struct pipe_texture *lut_texture;
+ VGfloat buffer[4];
+ struct filter_info info;
+ VGuint color_data[256];
+ VGint i;
+
+ if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (!lookupTable || !is_aligned(lookupTable)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (sourceChannel != VG_RED && sourceChannel != VG_GREEN &&
+ sourceChannel != VG_BLUE && sourceChannel != VG_ALPHA) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ d = (struct vg_image*)dst;
+ s = (struct vg_image*)src;
+
+ if (vg_image_overlaps(d, s)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ for (i = 0; i < 256; ++i) {
+ VGuint rgba = lookupTable[i];
+ VGubyte blue, green, red, alpha;
+ red = (rgba & 0xff000000)>>24;
+ green = (rgba & 0x00ff0000)>>16;
+ blue = (rgba & 0x0000ff00)>> 8;
+ alpha = (rgba & 0x000000ff)>> 0;
+ color_data[i] = blue << 24 | green << 16 |
+ red << 8 | alpha;
+ }
+ lut_texture = create_texture_1d(ctx, color_data, 256);
+
+ buffer[0] = 0.f;
+ buffer[1] = 0.f;
+ buffer[2] = 1.f;
+ buffer[3] = 1.f;
+
+ info.dst = d;
+ info.src = s;
+ info.setup_shader = &setup_lookup_single;
+ info.user_data = (void*)sourceChannel;
+ info.const_buffer = buffer;
+ info.const_buffer_len = 4 * sizeof(VGfloat);
+ info.tiling_mode = VG_TILE_PAD;
+ info.extra_texture = lut_texture;
+
+ execute_filter(ctx, &info);
+
+ pipe_texture_reference(&lut_texture, NULL);
+}
diff --git a/src/gallium/state_trackers/vega/api_images.c b/src/gallium/state_trackers/vega/api_images.c
new file mode 100644
index 0000000000..c437553bc2
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_images.c
@@ -0,0 +1,489 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "image.h"
+
+#include "VG/openvg.h"
+
+#include "vg_context.h"
+#include "vg_translate.h"
+#include "api_consts.h"
+#include "image.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_blit.h"
+#include "util/u_tile.h"
+#include "util/u_memory.h"
+
+static INLINE VGboolean supported_image_format(VGImageFormat format)
+{
+ switch(format) {
+ case VG_sRGBX_8888:
+ case VG_sRGBA_8888:
+ case VG_sRGBA_8888_PRE:
+ case VG_sRGB_565:
+ case VG_sRGBA_5551:
+ case VG_sRGBA_4444:
+ case VG_sL_8:
+ case VG_lRGBX_8888:
+ case VG_lRGBA_8888:
+ case VG_lRGBA_8888_PRE:
+ case VG_lL_8:
+ case VG_A_8:
+ case VG_BW_1:
+#ifdef OPENVG_VERSION_1_1
+ case VG_A_1:
+ case VG_A_4:
+#endif
+ case VG_sXRGB_8888:
+ case VG_sARGB_8888:
+ case VG_sARGB_8888_PRE:
+ case VG_sARGB_1555:
+ case VG_sARGB_4444:
+ case VG_lXRGB_8888:
+ case VG_lARGB_8888:
+ case VG_lARGB_8888_PRE:
+ case VG_sBGRX_8888:
+ case VG_sBGRA_8888:
+ case VG_sBGRA_8888_PRE:
+ case VG_sBGR_565:
+ case VG_sBGRA_5551:
+ case VG_sBGRA_4444:
+ case VG_lBGRX_8888:
+ case VG_lBGRA_8888:
+ case VG_lBGRA_8888_PRE:
+ case VG_sXBGR_8888:
+ case VG_sABGR_8888:
+ case VG_sABGR_8888_PRE:
+ case VG_sABGR_1555:
+ case VG_sABGR_4444:
+ case VG_lXBGR_8888:
+ case VG_lABGR_8888:
+ case VG_lABGR_8888_PRE:
+ return VG_TRUE;
+ default:
+ return VG_FALSE;
+ }
+ return VG_FALSE;
+}
+
+VGImage vgCreateImage(VGImageFormat format,
+ VGint width, VGint height,
+ VGbitfield allowedQuality)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (!supported_image_format(format)) {
+ vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+ if (width <= 0 || height <= 0) {
+ 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)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+ if (width * height > vgGeti(VG_MAX_IMAGE_PIXELS)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+
+ if (!(allowedQuality & ((VG_IMAGE_QUALITY_NONANTIALIASED |
+ VG_IMAGE_QUALITY_FASTER |
+ VG_IMAGE_QUALITY_BETTER)))) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+
+ return (VGImage)image_create(format, width, height);
+}
+
+void vgDestroyImage(VGImage image)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *img = (struct vg_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)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ image_destroy(img);
+}
+
+void vgClearImage(VGImage image,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *img;
+
+ if (image == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ img = (struct vg_image*)image;
+
+ if (x + width < 0 || y + height < 0)
+ return;
+
+ image_clear(img, x, y, width, height);
+
+}
+
+void vgImageSubData(VGImage image,
+ const void * data,
+ VGint dataStride,
+ VGImageFormat dataFormat,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *img;
+
+ if (image == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (!supported_image_format(dataFormat)) {
+ vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
+ return;
+ }
+ if (width <= 0 || height <= 0 || !data || !is_aligned(data)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ img = (struct vg_image*)(image);
+ image_sub_data(img, data, dataStride, dataFormat,
+ x, y, width, height);
+}
+
+void vgGetImageSubData(VGImage image,
+ void * data,
+ VGint dataStride,
+ VGImageFormat dataFormat,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *img;
+
+ if (image == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (!supported_image_format(dataFormat)) {
+ vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
+ return;
+ }
+ if (width <= 0 || height <= 0 || !data || !is_aligned(data)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ img = (struct vg_image*)image;
+ image_get_sub_data(img, data, dataStride, dataFormat,
+ x, y, width, height);
+}
+
+VGImage vgChildImage(VGImage parent,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ 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_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+ if (width <= 0 || height <= 0 || x < 0 || y < 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+ p = (struct vg_image *)parent;
+ if (x > p->width || y > p->height) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+ if (x + width > p->width || y + height > p->height) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+
+ return (VGImage)image_child_image(p, x, y, width, height);
+}
+
+VGImage vgGetParent(VGImage image)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *img;
+
+ if (image == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+
+ img = (struct vg_image*)image;
+ if (img->parent)
+ return (VGImage)img->parent;
+ else
+ return image;
+}
+
+void vgCopyImage(VGImage dst, VGint dx, VGint dy,
+ VGImage src, VGint sx, VGint sy,
+ VGint width, VGint height,
+ VGboolean dither)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (src == VG_INVALID_HANDLE || dst == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ vg_validate_state(ctx);
+ image_copy((struct vg_image*)dst, dx, dy,
+ (struct vg_image*)src, sx, sy,
+ width, height, dither);
+}
+
+void vgDrawImage(VGImage image)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (!ctx)
+ return;
+
+ if (image == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ vg_validate_state(ctx);
+ image_draw((struct vg_image*)image);
+}
+
+void vgSetPixels(VGint dx, VGint dy,
+ VGImage src, VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ vg_validate_state(ctx);
+
+ if (src == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ image_set_pixels(dx, dy, (struct vg_image*)src, sx, sy, width,
+ height);
+}
+
+void vgGetPixels(VGImage dst, VGint dx, VGint dy,
+ VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *img;
+
+ if (dst == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ img = (struct vg_image*)dst;
+
+ image_get_pixels(img, dx, dy,
+ sx, sy, width, height);
+}
+
+void vgWritePixels(const void * data, VGint dataStride,
+ VGImageFormat dataFormat,
+ VGint dx, VGint dy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_context *pipe = ctx->pipe;
+
+ if (!supported_image_format(dataFormat)) {
+ vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
+ return;
+ }
+ if (!data || !is_aligned(data)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ vg_validate_state(ctx);
+ {
+ struct vg_image *img = image_create(dataFormat, width, height);
+ image_sub_data(img, data, dataStride, dataFormat, 0, 0,
+ width, height);
+#if 0
+ struct matrix *matrix = &ctx->state.vg.image_user_to_surface_matrix;
+ matrix_translate(matrix, dx, dy);
+ image_draw(img);
+ matrix_translate(matrix, -dx, -dy);
+#else
+ /* this looks like a better approach */
+ image_set_pixels(dx, dy, img, 0, 0, width, height);
+#endif
+ image_destroy(img);
+ }
+ /* make sure rendering has completed */
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+}
+
+void vgReadPixels(void * data, VGint dataStride,
+ VGImageFormat dataFormat,
+ VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+ struct st_renderbuffer *strb = stfb->strb;
+ struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
+
+ VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
+ VGfloat *df = (VGfloat*)temp;
+ VGint y = (fb->height - sy) - 1, yStep = -1;
+ VGint i;
+ VGubyte *dst = (VGubyte *)data;
+ VGint xoffset = 0, yoffset = 0;
+
+ if (!supported_image_format(dataFormat)) {
+ vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
+ return;
+ }
+ if (!data || !is_aligned(data)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ /* make sure rendering has completed */
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+ if (sx < 0) {
+ xoffset = -sx;
+ xoffset *= _vega_size_for_format(dataFormat);
+ width += sx;
+ sx = 0;
+ }
+ if (sy < 0) {
+ yoffset = -sy;
+ height += sy;
+ sy = 0;
+ y = (fb->height - sy) - 1;
+ yoffset *= dataStride;
+ }
+
+ {
+ struct pipe_transfer *transfer;
+
+ transfer = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0,
+ PIPE_TRANSFER_READ,
+ 0, 0, width, height);
+
+ /* Do a row at a time to flip image data vertically */
+ for (i = 0; i < height; i++) {
+#if 0
+ debug_printf("%d-%d == %d\n", sy, height, y);
+#endif
+ pipe_get_tile_rgba(transfer, sx, y, width, 1, df);
+ y += yStep;
+ _vega_pack_rgba_span_float(ctx, width, temp, dataFormat,
+ dst + yoffset + xoffset);
+ dst += dataStride;
+ }
+
+ screen->tex_transfer_destroy(transfer);
+ }
+}
+
+void vgCopyPixels(VGint dx, VGint dy,
+ VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
+ struct st_renderbuffer *strb = ctx->draw_buffer->strb;
+
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ /* do nothing if we copy from outside the fb */
+ if (dx >= (VGint)fb->width || dy >= (VGint)fb->height ||
+ sx >= (VGint)fb->width || sy >= (VGint)fb->height)
+ return;
+
+ vg_validate_state(ctx);
+ /* make sure rendering has completed */
+ vgFinish();
+
+ 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
new file mode 100644
index 0000000000..4f9f3dae17
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_masks.c
@@ -0,0 +1,373 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+
+#include "mask.h"
+#include "renderer.h"
+
+#include "vg_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "pipe/internal/p_winsys_screen.h" /* for winsys->update_buffer */
+
+#include "util/u_pack_color.h"
+#include "util/u_draw_quad.h"
+#include "util/u_memory.h"
+
+
+#define DISABLE_1_1_MASKING 1
+
+/**
+ * Draw a screen-aligned quadrilateral.
+ * Coords are window coords with y=0=bottom. These coords will be transformed
+ * by the vertex shader and viewport transform.
+ */
+static void
+draw_clear_quad(struct vg_context *st,
+ float x0, float y0, float x1, float y1, float z,
+ const VGfloat color[4])
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_buffer *buf;
+ VGuint i;
+
+ /* positions */
+ st->clear.vertices[0][0][0] = x0;
+ st->clear.vertices[0][0][1] = y0;
+
+ st->clear.vertices[1][0][0] = x1;
+ st->clear.vertices[1][0][1] = y0;
+
+ st->clear.vertices[2][0][0] = x1;
+ st->clear.vertices[2][0][1] = y1;
+
+ st->clear.vertices[3][0][0] = x0;
+ st->clear.vertices[3][0][1] = y1;
+
+ /* same for all verts: */
+ for (i = 0; i < 4; i++) {
+ st->clear.vertices[i][0][2] = z;
+ st->clear.vertices[i][0][3] = 1.0;
+ st->clear.vertices[i][1][0] = color[0];
+ st->clear.vertices[i][1][1] = color[1];
+ st->clear.vertices[i][1][2] = color[2];
+ st->clear.vertices[i][1][3] = color[3];
+ }
+
+
+ /* put vertex data into vbuf */
+ buf = pipe_user_buffer_create(pipe->screen,
+ st->clear.vertices,
+ sizeof(st->clear.vertices));
+
+
+ /* draw */
+ if (buf) {
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+}
+
+/**
+ * Do vgClear by drawing a quadrilateral.
+ */
+static void
+clear_with_quad(struct vg_context *st, float x0, float y0,
+ float width, float height, const VGfloat clear_color[4])
+{
+ VGfloat x1, y1;
+
+ vg_validate_state(st);
+
+ x1 = x0 + width;
+ y1 = y0 + height;
+
+ /*
+ printf("%s %f,%f %f,%f\n", __FUNCTION__,
+ x0, y0,
+ x1, y1);
+ */
+
+ if (st->pipe->winsys && st->pipe->winsys->update_buffer)
+ st->pipe->winsys->update_buffer( st->pipe->winsys,
+ st->pipe->priv );
+
+ cso_save_blend(st->cso_context);
+ cso_save_rasterizer(st->cso_context);
+ cso_save_fragment_shader(st->cso_context);
+ cso_save_vertex_shader(st->cso_context);
+
+ /* blend state: RGBA masking */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask |= PIPE_MASK_R;
+ blend.colormask |= PIPE_MASK_G;
+ blend.colormask |= PIPE_MASK_B;
+ blend.colormask |= PIPE_MASK_A;
+ cso_set_blend(st->cso_context, &blend);
+ }
+
+ cso_set_rasterizer(st->cso_context, &st->clear.raster);
+
+ cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
+ cso_set_vertex_shader_handle(st->cso_context, vg_clear_vs(st));
+
+ /* draw quad matching scissor rect (XXX verify coord round-off) */
+ draw_clear_quad(st, x0, y0, x1, y1, 0, clear_color);
+
+ /* Restore pipe state */
+ cso_restore_blend(st->cso_context);
+ cso_restore_rasterizer(st->cso_context);
+ cso_restore_fragment_shader(st->cso_context);
+ cso_restore_vertex_shader(st->cso_context);
+}
+
+
+void vgMask(VGHandle mask, VGMaskOperation operation,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (width <=0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (operation < VG_CLEAR_MASK || operation > VG_SUBTRACT_MASK) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+
+ vg_validate_state(ctx);
+
+ if (operation == VG_CLEAR_MASK) {
+ 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;
+ mask_using_image(image, operation, x, y, width, height);
+ } else if (vg_object_is_valid((void*)mask, VG_OBJECT_MASK)) {
+#if DISABLE_1_1_MASKING
+ return;
+#else
+ struct vg_mask_layer *layer = (struct vg_mask_layer *)mask;
+ mask_using_layer(layer, operation, x, y, width, height);
+#endif
+ } else {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ }
+}
+
+void vgClear(VGint x, VGint y,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_framebuffer_state *fb;
+
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ vg_validate_state(ctx);
+#if 0
+ debug_printf("Clear [%d, %d, %d, %d] with [%f, %f, %f, %f]\n",
+ x, y, width, height,
+ ctx->state.vg.clear_color[0],
+ ctx->state.vg.clear_color[1],
+ ctx->state.vg.clear_color[2],
+ ctx->state.vg.clear_color[3]);
+#endif
+
+ fb = &ctx->state.g3d.fb;
+ /* check for a whole surface clear */
+ if (!ctx->state.vg.scissoring &&
+ (x == 0 && y == 0 && width == fb->width && height == fb->height)) {
+ ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
+ ctx->state.vg.clear_color, 1., 0);
+ } else {
+ clear_with_quad(ctx, x, y, width, height, ctx->state.vg.clear_color);
+ }
+}
+
+
+#ifdef OPENVG_VERSION_1_1
+
+
+void vgRenderToMask(VGPath path,
+ VGbitfield paintModes,
+ VGMaskOperation operation)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (path == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (!paintModes || (paintModes&(~(VG_STROKE_PATH|VG_FILL_PATH)))) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (operation < VG_CLEAR_MASK ||
+ operation > VG_SUBTRACT_MASK) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (!vg_object_is_valid((void*)path, VG_OBJECT_PATH)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+#if DISABLE_1_1_MASKING
+ return;
+#endif
+
+ vg_validate_state(ctx);
+
+ mask_render_to((struct path *)path, paintModes, operation);
+}
+
+VGMaskLayer vgCreateMaskLayer(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)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+
+ return (VGMaskLayer)mask_layer_create(width, height);
+}
+
+void vgDestroyMaskLayer(VGMaskLayer maskLayer)
+{
+ struct vg_mask_layer *mask = 0;
+ struct vg_context *ctx = vg_current_context();
+
+ if (maskLayer == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ mask = (struct vg_mask_layer *)maskLayer;
+ mask_layer_destroy(mask);
+}
+
+void vgFillMaskLayer(VGMaskLayer maskLayer,
+ VGint x, VGint y,
+ VGint width, VGint height,
+ VGfloat value)
+{
+ struct vg_mask_layer *mask = 0;
+ struct vg_context *ctx = vg_current_context();
+
+ if (maskLayer == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (value < 0 || value > 1) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (x < 0 || y < 0 || (x + width) < 0 || (y + height) < 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ mask = (struct vg_mask_layer*)maskLayer;
+
+ if (x + width > mask_layer_width(mask) ||
+ y + height > mask_layer_height(mask)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+#if DISABLE_1_1_MASKING
+ return;
+#endif
+ mask_layer_fill(mask, x, y, width, height, value);
+}
+
+void vgCopyMask(VGMaskLayer maskLayer,
+ VGint sx, VGint sy,
+ VGint dx, VGint dy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_mask_layer *mask = 0;
+
+ if (maskLayer == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+#if DISABLE_1_1_MASKING
+ return;
+#endif
+
+ mask = (struct vg_mask_layer*)maskLayer;
+ mask_copy(mask, sx, sy, dx, dy, width, height);
+}
+
+#endif
diff --git a/src/gallium/state_trackers/vega/api_misc.c b/src/gallium/state_trackers/vega/api_misc.c
new file mode 100644
index 0000000000..78ba0bc110
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_misc.c
@@ -0,0 +1,83 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+
+#include "vg_context.h"
+
+/* Hardware Queries */
+VGHardwareQueryResult vgHardwareQuery(VGHardwareQueryType key,
+ VGint setting)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (key < VG_IMAGE_FORMAT_QUERY ||
+ key > VG_PATH_DATATYPE_QUERY) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_HARDWARE_UNACCELERATED;
+ }
+
+ if (key == VG_IMAGE_FORMAT_QUERY) {
+ if (setting < VG_sRGBX_8888 ||
+ setting > VG_lABGR_8888_PRE) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_HARDWARE_UNACCELERATED;
+ }
+ } else if (key == VG_PATH_DATATYPE_QUERY) {
+ if (setting < VG_PATH_DATATYPE_S_8 ||
+ setting > VG_PATH_DATATYPE_F) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_HARDWARE_UNACCELERATED;
+ }
+ }
+ /* we're supposed to accelerate everything */
+ return VG_HARDWARE_ACCELERATED;
+}
+
+/* Renderer and Extension Information */
+const VGubyte *vgGetString(VGStringID name)
+{
+ struct vg_context *ctx = vg_current_context();
+ static const VGubyte *vendor = (VGubyte *)"Tungsten Graphics, Inc";
+ static const VGubyte *renderer = (VGubyte *)"Vega OpenVG 1.0";
+ static const VGubyte *version = (VGubyte *)"1.0";
+
+ if (!ctx)
+ return NULL;
+
+ switch(name) {
+ case VG_VENDOR:
+ return vendor;
+ case VG_RENDERER:
+ return renderer;
+ case VG_VERSION:
+ return version;
+ case VG_EXTENSIONS:
+ return NULL;
+ default:
+ return NULL;
+ }
+}
diff --git a/src/gallium/state_trackers/vega/api_paint.c b/src/gallium/state_trackers/vega/api_paint.c
new file mode 100644
index 0000000000..dd3ac5bdb0
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_paint.c
@@ -0,0 +1,166 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+
+#include "vg_context.h"
+#include "paint.h"
+#include "image.h"
+
+VGPaint vgCreatePaint(void)
+{
+ return (VGPaint) paint_create(vg_current_context());
+}
+
+void vgDestroyPaint(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);
+}
+
+void vgSetPaint(VGPaint paint, VGbitfield paintModes)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (paint == VG_INVALID_HANDLE) {
+ /* restore the default */
+ paint = (VGPaint)ctx->default_paint;
+ } else if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (!(paintModes & ((VG_FILL_PATH|VG_STROKE_PATH)))) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (paintModes & VG_FILL_PATH) {
+ ctx->state.vg.fill_paint = (struct vg_paint *)paint;
+ }
+ if (paintModes & VG_STROKE_PATH) {
+ ctx->state.vg.stroke_paint = (struct vg_paint *)paint;
+ }
+}
+
+VGPaint vgGetPaint(VGPaintMode paintMode)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGPaint paint = VG_INVALID_HANDLE;
+
+ if (paintMode < VG_STROKE_PATH || paintMode > VG_FILL_PATH) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+
+ if (paintMode == VG_FILL_PATH)
+ paint = (VGPaint)ctx->state.vg.fill_paint;
+ else if (paintMode == VG_STROKE_PATH)
+ paint = (VGPaint)ctx->state.vg.stroke_paint;
+
+ if (paint == (VGPaint)ctx->default_paint)
+ paint = VG_INVALID_HANDLE;
+
+ return paint;
+}
+
+void vgSetColor(VGPaint paint, VGuint rgba)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (paint == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (!vg_object_is_valid((void*)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);
+ }
+}
+
+VGuint vgGetColor(VGPaint paint)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_paint *p;
+ VGuint rgba = 0;
+
+ if (paint == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return rgba;
+ }
+
+ if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return rgba;
+ }
+ p = (struct vg_paint *)paint;
+
+ return paint_colori(p);
+}
+
+void vgPaintPattern(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_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (pattern == VG_INVALID_HANDLE) {
+ paint_set_type((struct vg_paint*)paint, VG_PAINT_TYPE_COLOR);
+ return;
+ }
+
+ if (!vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)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)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ paint_set_pattern((struct vg_paint*)paint,
+ (struct vg_image*)pattern);
+}
+
diff --git a/src/gallium/state_trackers/vega/api_params.c b/src/gallium/state_trackers/vega/api_params.c
new file mode 100644
index 0000000000..db77fd9cb0
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_params.c
@@ -0,0 +1,1673 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+
+#include "vg_context.h"
+#include "paint.h"
+#include "path.h"
+#include "image.h"
+#include "matrix.h"
+#include "api_consts.h"
+
+#include "pipe/p_compiler.h"
+#include "util/u_pointer.h"
+#include "util/u_math.h"
+
+#include <math.h>
+
+static INLINE struct vg_state *current_state()
+{
+ struct vg_context *ctx = vg_current_context();
+ if (!ctx)
+ return 0;
+ else
+ return &ctx->state.vg;
+}
+
+static INLINE VGboolean count_in_bounds(VGParamType type, VGint count)
+{
+ if (count < 0)
+ return VG_FALSE;
+
+ if (type == VG_SCISSOR_RECTS)
+ return (!(count % 4) && (count >= 0 || count <= VEGA_MAX_SCISSOR_RECTS * 4));
+ else if (type == VG_STROKE_DASH_PATTERN) {
+ return count <= VEGA_MAX_DASH_COUNT;
+ } else {
+ VGint real_count = vgGetVectorSize(type);
+ return count == real_count;
+ }
+}
+
+void vgSetf (VGParamType type, VGfloat value)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_state *state = current_state();
+ VGErrorCode error = VG_NO_ERROR;
+
+ switch(type) {
+ case VG_MATRIX_MODE:
+ case VG_FILL_RULE:
+ case VG_IMAGE_QUALITY:
+ case VG_RENDERING_QUALITY:
+ case VG_BLEND_MODE:
+ case VG_IMAGE_MODE:
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM:
+#endif
+ case VG_STROKE_CAP_STYLE:
+ case VG_STROKE_JOIN_STYLE:
+ case VG_STROKE_DASH_PHASE_RESET:
+ case VG_MASKING:
+ case VG_SCISSORING:
+ case VG_PIXEL_LAYOUT:
+ case VG_SCREEN_LAYOUT:
+ case VG_FILTER_FORMAT_LINEAR:
+ case VG_FILTER_FORMAT_PREMULTIPLIED:
+ case VG_FILTER_CHANNEL_MASK:
+
+ case VG_MAX_SCISSOR_RECTS:
+ case VG_MAX_DASH_COUNT:
+ case VG_MAX_KERNEL_SIZE:
+ case VG_MAX_SEPARABLE_KERNEL_SIZE:
+ case VG_MAX_COLOR_RAMP_STOPS:
+ case VG_MAX_IMAGE_WIDTH:
+ case VG_MAX_IMAGE_HEIGHT:
+ case VG_MAX_IMAGE_PIXELS:
+ case VG_MAX_IMAGE_BYTES:
+ case VG_MAX_GAUSSIAN_STD_DEVIATION:
+ case VG_MAX_FLOAT:
+ vgSeti(type, floor(value));
+ return;
+ break;
+ case VG_STROKE_LINE_WIDTH:
+ state->stroke.line_width.f = value;
+ state->stroke.line_width.i = float_to_int_floor(*((VGuint*)(&value)));
+ break;
+ case VG_STROKE_MITER_LIMIT:
+ state->stroke.miter_limit.f = value;
+ state->stroke.miter_limit.i = float_to_int_floor(*((VGuint*)(&value)));
+ break;
+ case VG_STROKE_DASH_PHASE:
+ state->stroke.dash_phase.f = value;
+ state->stroke.dash_phase.i = float_to_int_floor(*((VGuint*)(&value)));
+ break;
+ default:
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ break;
+ }
+ vg_set_error(ctx, error);
+}
+
+void vgSeti (VGParamType type, VGint value)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_state *state = current_state();
+ VGErrorCode error = VG_NO_ERROR;
+
+ switch(type) {
+ case VG_MATRIX_MODE:
+ if (value < VG_MATRIX_PATH_USER_TO_SURFACE ||
+#ifdef OPENVG_VERSION_1_1
+ value > VG_MATRIX_GLYPH_USER_TO_SURFACE)
+#else
+ value > VG_MATRIX_STROKE_PAINT_TO_USER)
+#endif
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ else
+ state->matrix_mode = value;
+ break;
+ case VG_FILL_RULE:
+ if (value < VG_EVEN_ODD ||
+ value > VG_NON_ZERO)
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ else
+ state->fill_rule = value;
+ break;
+ case VG_IMAGE_QUALITY:
+ state->image_quality = value;
+ break;
+ case VG_RENDERING_QUALITY:
+ if (value < VG_RENDERING_QUALITY_NONANTIALIASED ||
+ value > VG_RENDERING_QUALITY_BETTER)
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ else
+ state->rendering_quality = value;
+ break;
+ case VG_BLEND_MODE:
+ if (value < VG_BLEND_SRC ||
+ value > VG_BLEND_ADDITIVE)
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ else {
+ ctx->state.dirty |= BLEND_DIRTY;
+ state->blend_mode = value;
+ }
+ break;
+ case VG_IMAGE_MODE:
+ if (value < VG_DRAW_IMAGE_NORMAL ||
+ value > VG_DRAW_IMAGE_STENCIL)
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ else
+ state->image_mode = value;
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM:
+ state->color_transform = value;
+#endif
+ break;
+ case VG_STROKE_LINE_WIDTH:
+ state->stroke.line_width.f = value;
+ state->stroke.line_width.i = value;
+ break;
+ case VG_STROKE_CAP_STYLE:
+ if (value < VG_CAP_BUTT ||
+ value > VG_CAP_SQUARE)
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ else
+ state->stroke.cap_style = value;
+ break;
+ case VG_STROKE_JOIN_STYLE:
+ if (value < VG_JOIN_MITER ||
+ value > VG_JOIN_BEVEL)
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ else
+ state->stroke.join_style = value;
+ break;
+ case VG_STROKE_MITER_LIMIT:
+ state->stroke.miter_limit.f = value;
+ state->stroke.miter_limit.i = value;
+ break;
+ case VG_STROKE_DASH_PHASE:
+ state->stroke.dash_phase.f = value;
+ state->stroke.dash_phase.i = value;
+ break;
+ case VG_STROKE_DASH_PHASE_RESET:
+ state->stroke.dash_phase_reset = value;
+ break;
+ case VG_MASKING:
+ state->masking = value;
+ break;
+ case VG_SCISSORING:
+ state->scissoring = value;
+ ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
+ break;
+ case VG_PIXEL_LAYOUT:
+ if (value < VG_PIXEL_LAYOUT_UNKNOWN ||
+ value > VG_PIXEL_LAYOUT_BGR_HORIZONTAL)
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ else
+ state->pixel_layout = value;
+ break;
+ case VG_SCREEN_LAYOUT:
+ /* read only ignore */
+ break;
+ case VG_FILTER_FORMAT_LINEAR:
+ state->filter_format_linear = value;
+ break;
+ case VG_FILTER_FORMAT_PREMULTIPLIED:
+ state->filter_format_premultiplied = value;
+ break;
+ case VG_FILTER_CHANNEL_MASK:
+ state->filter_channel_mask = value;
+ break;
+
+ case VG_MAX_SCISSOR_RECTS:
+ case VG_MAX_DASH_COUNT:
+ case VG_MAX_KERNEL_SIZE:
+ case VG_MAX_SEPARABLE_KERNEL_SIZE:
+ case VG_MAX_COLOR_RAMP_STOPS:
+ case VG_MAX_IMAGE_WIDTH:
+ case VG_MAX_IMAGE_HEIGHT:
+ case VG_MAX_IMAGE_PIXELS:
+ case VG_MAX_IMAGE_BYTES:
+ case VG_MAX_GAUSSIAN_STD_DEVIATION:
+ case VG_MAX_FLOAT:
+ /* read only ignore */
+ break;
+ default:
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ break;
+ }
+ vg_set_error(ctx, error);
+}
+
+void vgSetfv(VGParamType type, VGint count,
+ const VGfloat * values)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_state *state = current_state();
+ VGErrorCode error = VG_NO_ERROR;
+
+ if ((count && !values) || !count_in_bounds(type, count) || !is_aligned(values)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ switch(type) {
+ case VG_MATRIX_MODE:
+ case VG_FILL_RULE:
+ case VG_IMAGE_QUALITY:
+ case VG_RENDERING_QUALITY:
+ case VG_BLEND_MODE:
+ case VG_IMAGE_MODE:
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM:
+#endif
+ case VG_STROKE_CAP_STYLE:
+ case VG_STROKE_JOIN_STYLE:
+ case VG_STROKE_DASH_PHASE_RESET:
+ case VG_MASKING:
+ case VG_SCISSORING:
+ case VG_PIXEL_LAYOUT:
+ case VG_SCREEN_LAYOUT:
+ case VG_FILTER_FORMAT_LINEAR:
+ case VG_FILTER_FORMAT_PREMULTIPLIED:
+ case VG_FILTER_CHANNEL_MASK:
+ vgSeti(type, floor(values[0]));
+ return;
+ break;
+ case VG_SCISSOR_RECTS: {
+ VGint i;
+ VGuint *x = (VGuint*)values;
+ for (i = 0; i < count; ++i) {
+ state->scissor_rects[i].f = values[i];
+ state->scissor_rects[i].i = float_to_int_floor(x[i]);
+ }
+ state->scissor_rects_num = count / 4;
+ ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
+ }
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM_VALUES: {
+ VGint i;
+ for (i = 0; i < count; ++i) {
+ state->color_transform_values[i] = values[i];
+ }
+ }
+ break;
+#endif
+ case VG_STROKE_LINE_WIDTH:
+ state->stroke.line_width.f = values[0];
+ state->stroke.line_width.i = float_to_int_floor(*((VGuint*)(values)));
+ break;
+ case VG_STROKE_MITER_LIMIT:
+ state->stroke.miter_limit.f = values[0];
+ state->stroke.miter_limit.i = float_to_int_floor(*((VGuint*)(values)));
+ break;
+ case VG_STROKE_DASH_PATTERN: {
+ int i;
+ for (i = 0; i < count; ++i) {
+ state->stroke.dash_pattern[i].f = values[i];
+ state->stroke.dash_pattern[i].i =
+ float_to_int_floor(*((VGuint*)(values + i)));
+ }
+ state->stroke.dash_pattern_num = count;
+ }
+ break;
+ case VG_STROKE_DASH_PHASE:
+ state->stroke.dash_phase.f = values[0];
+ state->stroke.dash_phase.i = float_to_int_floor(*((VGuint*)(values)));
+ break;
+ case VG_TILE_FILL_COLOR:
+ state->tile_fill_color[0] = values[0];
+ state->tile_fill_color[1] = values[1];
+ state->tile_fill_color[2] = values[2];
+ state->tile_fill_color[3] = values[3];
+
+ state->tile_fill_colori[0] = float_to_int_floor(*((VGuint*)(values + 0)));
+ state->tile_fill_colori[1] = float_to_int_floor(*((VGuint*)(values + 1)));
+ state->tile_fill_colori[2] = float_to_int_floor(*((VGuint*)(values + 2)));
+ state->tile_fill_colori[3] = float_to_int_floor(*((VGuint*)(values + 3)));
+ break;
+ case VG_CLEAR_COLOR:
+ state->clear_color[0] = values[0];
+ state->clear_color[1] = values[1];
+ state->clear_color[2] = values[2];
+ state->clear_color[3] = values[3];
+
+ state->clear_colori[0] = float_to_int_floor(*((VGuint*)(values + 0)));
+ state->clear_colori[1] = float_to_int_floor(*((VGuint*)(values + 1)));
+ state->clear_colori[2] = float_to_int_floor(*((VGuint*)(values + 2)));
+ state->clear_colori[3] = float_to_int_floor(*((VGuint*)(values + 3)));
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_GLYPH_ORIGIN:
+ state->glyph_origin[0].f = values[0];
+ state->glyph_origin[1].f = values[1];
+
+ state->glyph_origin[0].i = float_to_int_floor(*((VGuint*)(values + 0)));
+ state->glyph_origin[1].i = float_to_int_floor(*((VGuint*)(values + 1)));
+ break;
+#endif
+
+ case VG_MAX_SCISSOR_RECTS:
+ case VG_MAX_DASH_COUNT:
+ case VG_MAX_KERNEL_SIZE:
+ case VG_MAX_SEPARABLE_KERNEL_SIZE:
+ case VG_MAX_COLOR_RAMP_STOPS:
+ case VG_MAX_IMAGE_WIDTH:
+ case VG_MAX_IMAGE_HEIGHT:
+ case VG_MAX_IMAGE_PIXELS:
+ case VG_MAX_IMAGE_BYTES:
+ case VG_MAX_GAUSSIAN_STD_DEVIATION:
+ case VG_MAX_FLOAT:
+ break;
+ default:
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ break;
+ }
+ vg_set_error(ctx, error);
+}
+
+void vgSetiv(VGParamType type, VGint count,
+ const VGint * values)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_state *state = current_state();
+
+ if ((count && !values) || !count_in_bounds(type, count) || !is_aligned(values)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ switch(type) {
+ case VG_MATRIX_MODE:
+ case VG_FILL_RULE:
+ case VG_IMAGE_QUALITY:
+ case VG_RENDERING_QUALITY:
+ case VG_BLEND_MODE:
+ case VG_IMAGE_MODE:
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM:
+#endif
+ case VG_STROKE_CAP_STYLE:
+ case VG_STROKE_JOIN_STYLE:
+ case VG_STROKE_DASH_PHASE_RESET:
+ case VG_MASKING:
+ case VG_SCISSORING:
+ case VG_PIXEL_LAYOUT:
+ case VG_SCREEN_LAYOUT:
+ case VG_FILTER_FORMAT_LINEAR:
+ case VG_FILTER_FORMAT_PREMULTIPLIED:
+ case VG_FILTER_CHANNEL_MASK:
+ vgSeti(type, values[0]);
+ return;
+ break;
+ case VG_SCISSOR_RECTS: {
+ VGint i;
+ for (i = 0; i < count; ++i) {
+ state->scissor_rects[i].i = values[i];
+ state->scissor_rects[i].f = values[i];
+ }
+ state->scissor_rects_num = count / 4;
+ ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
+ }
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM_VALUES: {
+ VGint i;
+ for (i = 0; i < count; ++i) {
+ state->color_transform_values[i] = values[i];
+ }
+ }
+ break;
+#endif
+ case VG_STROKE_LINE_WIDTH:
+ state->stroke.line_width.f = values[0];
+ state->stroke.line_width.i = values[0];
+ break;
+ case VG_STROKE_MITER_LIMIT:
+ state->stroke.miter_limit.f = values[0];
+ state->stroke.miter_limit.i = values[0];
+ break;
+ case VG_STROKE_DASH_PATTERN: {
+ int i;
+ for (i = 0; i < count; ++i) {
+ state->stroke.dash_pattern[i].f = values[i];
+ state->stroke.dash_pattern[i].i = values[i];
+ }
+ state->stroke.dash_pattern_num = count;
+ }
+ break;
+ case VG_STROKE_DASH_PHASE:
+ state->stroke.dash_phase.f = values[0];
+ state->stroke.dash_phase.i = values[0];
+ break;
+ case VG_TILE_FILL_COLOR:
+ state->tile_fill_color[0] = values[0];
+ state->tile_fill_color[1] = values[1];
+ state->tile_fill_color[2] = values[2];
+ state->tile_fill_color[3] = values[3];
+
+ state->tile_fill_colori[0] = values[0];
+ state->tile_fill_colori[1] = values[1];
+ state->tile_fill_colori[2] = values[2];
+ state->tile_fill_colori[3] = values[3];
+ break;
+ case VG_CLEAR_COLOR:
+ state->clear_color[0] = values[0];
+ state->clear_color[1] = values[1];
+ state->clear_color[2] = values[2];
+ state->clear_color[3] = values[3];
+
+ state->clear_colori[0] = values[0];
+ state->clear_colori[1] = values[1];
+ state->clear_colori[2] = values[2];
+ state->clear_colori[3] = values[3];
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_GLYPH_ORIGIN:
+ state->glyph_origin[0].f = values[0];
+ state->glyph_origin[1].f = values[1];
+ state->glyph_origin[0].i = values[0];
+ state->glyph_origin[1].i = values[1];
+ break;
+#endif
+
+ case VG_MAX_SCISSOR_RECTS:
+ case VG_MAX_DASH_COUNT:
+ case VG_MAX_KERNEL_SIZE:
+ case VG_MAX_SEPARABLE_KERNEL_SIZE:
+ case VG_MAX_COLOR_RAMP_STOPS:
+ case VG_MAX_IMAGE_WIDTH:
+ case VG_MAX_IMAGE_HEIGHT:
+ case VG_MAX_IMAGE_PIXELS:
+ case VG_MAX_IMAGE_BYTES:
+ case VG_MAX_GAUSSIAN_STD_DEVIATION:
+ case VG_MAX_FLOAT:
+ break;
+
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ }
+}
+
+VGfloat vgGetf(VGParamType type)
+{
+ struct vg_context *ctx = vg_current_context();
+ const struct vg_state *state = current_state();
+ VGErrorCode error = VG_NO_ERROR;
+ VGfloat value = 0.0f;
+
+ switch(type) {
+ case VG_MATRIX_MODE:
+ case VG_FILL_RULE:
+ case VG_IMAGE_QUALITY:
+ case VG_RENDERING_QUALITY:
+ case VG_BLEND_MODE:
+ case VG_IMAGE_MODE:
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM:
+#endif
+ case VG_STROKE_CAP_STYLE:
+ case VG_STROKE_JOIN_STYLE:
+ case VG_STROKE_DASH_PHASE_RESET:
+ case VG_MASKING:
+ case VG_SCISSORING:
+ case VG_PIXEL_LAYOUT:
+ case VG_SCREEN_LAYOUT:
+ case VG_FILTER_FORMAT_LINEAR:
+ case VG_FILTER_FORMAT_PREMULTIPLIED:
+ case VG_FILTER_CHANNEL_MASK:
+ return vgGeti(type);
+ break;
+ case VG_STROKE_LINE_WIDTH:
+ value = state->stroke.line_width.f;
+ break;
+ case VG_STROKE_MITER_LIMIT:
+ value = state->stroke.miter_limit.f;
+ break;
+ case VG_STROKE_DASH_PHASE:
+ value = state->stroke.dash_phase.f;
+ break;
+
+ case VG_MAX_SCISSOR_RECTS:
+ case VG_MAX_DASH_COUNT:
+ case VG_MAX_KERNEL_SIZE:
+ case VG_MAX_SEPARABLE_KERNEL_SIZE:
+ case VG_MAX_COLOR_RAMP_STOPS:
+ case VG_MAX_IMAGE_WIDTH:
+ case VG_MAX_IMAGE_HEIGHT:
+ case VG_MAX_IMAGE_PIXELS:
+ case VG_MAX_IMAGE_BYTES:
+ case VG_MAX_GAUSSIAN_STD_DEVIATION:
+ return vgGeti(type);
+ break;
+ case VG_MAX_FLOAT:
+ value = 1e+10;/*must be at least 1e+10*/
+ break;
+ default:
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ break;
+ }
+ vg_set_error(ctx, error);
+ return value;
+}
+
+VGint vgGeti(VGParamType type)
+{
+ const struct vg_state *state = current_state();
+ struct vg_context *ctx = vg_current_context();
+ VGErrorCode error = VG_NO_ERROR;
+ VGint value = 0;
+
+ switch(type) {
+ case VG_MATRIX_MODE:
+ value = state->matrix_mode;
+ break;
+ case VG_FILL_RULE:
+ value = state->fill_rule;
+ break;
+ case VG_IMAGE_QUALITY:
+ value = state->image_quality;
+ break;
+ case VG_RENDERING_QUALITY:
+ value = state->rendering_quality;
+ break;
+ case VG_BLEND_MODE:
+ value = state->blend_mode;
+ break;
+ case VG_IMAGE_MODE:
+ value = state->image_mode;
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM:
+ value = state->color_transform;
+ break;
+#endif
+ case VG_STROKE_LINE_WIDTH:
+ value = state->stroke.line_width.i;
+ break;
+ case VG_STROKE_CAP_STYLE:
+ value = state->stroke.cap_style;
+ break;
+ case VG_STROKE_JOIN_STYLE:
+ value = state->stroke.join_style;
+ break;
+ case VG_STROKE_MITER_LIMIT:
+ value = state->stroke.miter_limit.i;
+ break;
+ case VG_STROKE_DASH_PHASE:
+ value = state->stroke.dash_phase.i;
+ break;
+ case VG_STROKE_DASH_PHASE_RESET:
+ value = state->stroke.dash_phase_reset;
+ break;
+ case VG_MASKING:
+ value = state->masking;
+ break;
+ case VG_SCISSORING:
+ value = state->scissoring;
+ break;
+ case VG_PIXEL_LAYOUT:
+ value = state->pixel_layout;
+ break;
+ case VG_SCREEN_LAYOUT:
+ value = state->screen_layout;
+ break;
+ case VG_FILTER_FORMAT_LINEAR:
+ value = state->filter_format_linear;
+ break;
+ case VG_FILTER_FORMAT_PREMULTIPLIED:
+ value = state->filter_format_premultiplied;
+ break;
+ case VG_FILTER_CHANNEL_MASK:
+ value = state->filter_channel_mask;
+ break;
+
+ case VG_MAX_SCISSOR_RECTS:
+ value = 32; /*must be at least 32*/
+ break;
+ case VG_MAX_DASH_COUNT:
+ value = 16; /*must be at least 16*/
+ break;
+ case VG_MAX_KERNEL_SIZE:
+ value = 7; /*must be at least 7*/
+ break;
+ case VG_MAX_SEPARABLE_KERNEL_SIZE:
+ value = 15; /*must be at least 15*/
+ break;
+ case VG_MAX_COLOR_RAMP_STOPS:
+ value = 256; /*must be at least 32*/
+ break;
+ case VG_MAX_IMAGE_WIDTH:
+ value = 2048;
+ break;
+ case VG_MAX_IMAGE_HEIGHT:
+ value = 2048;
+ break;
+ case VG_MAX_IMAGE_PIXELS:
+ value = 2048*2048;
+ break;
+ case VG_MAX_IMAGE_BYTES:
+ value = 2048*2048 * 4;
+ break;
+ case VG_MAX_GAUSSIAN_STD_DEVIATION:
+ value = 128; /*must be at least 128*/
+ break;
+
+ case VG_MAX_FLOAT: {
+ VGfloat val = vgGetf(type);
+ value = float_to_int_floor(*((VGuint*)&val));
+ }
+ break;
+ default:
+ error = VG_ILLEGAL_ARGUMENT_ERROR;
+ break;
+ }
+ vg_set_error(ctx, error);
+ return value;
+}
+
+VGint vgGetVectorSize(VGParamType type)
+{
+ struct vg_context *ctx = vg_current_context();
+ const struct vg_state *state = current_state();
+ switch(type) {
+ case VG_MATRIX_MODE:
+ case VG_FILL_RULE:
+ case VG_IMAGE_QUALITY:
+ case VG_RENDERING_QUALITY:
+ case VG_BLEND_MODE:
+ case VG_IMAGE_MODE:
+ return 1;
+ case VG_SCISSOR_RECTS:
+ return state->scissor_rects_num * 4;
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM:
+ return 1;
+ case VG_COLOR_TRANSFORM_VALUES:
+ return 8;
+#endif
+ case VG_STROKE_LINE_WIDTH:
+ case VG_STROKE_CAP_STYLE:
+ case VG_STROKE_JOIN_STYLE:
+ case VG_STROKE_MITER_LIMIT:
+ return 1;
+ case VG_STROKE_DASH_PATTERN:
+ return state->stroke.dash_pattern_num;
+ case VG_STROKE_DASH_PHASE:
+ return 1;
+ case VG_STROKE_DASH_PHASE_RESET:
+ return 1;
+ case VG_TILE_FILL_COLOR:
+ return 4;
+ case VG_CLEAR_COLOR:
+ return 4;
+#ifdef OPENVG_VERSION_1_1
+ case VG_GLYPH_ORIGIN:
+ return 2;
+#endif
+ case VG_MASKING:
+ return 1;
+ case VG_SCISSORING:
+ return 1;
+ case VG_PIXEL_LAYOUT:
+ return 1;
+ case VG_SCREEN_LAYOUT:
+ return 1;
+ case VG_FILTER_FORMAT_LINEAR:
+ return 1;
+ case VG_FILTER_FORMAT_PREMULTIPLIED:
+ return 1;
+ case VG_FILTER_CHANNEL_MASK:
+ return 1;
+
+ case VG_MAX_COLOR_RAMP_STOPS:
+ return 1;
+ case VG_MAX_SCISSOR_RECTS:
+ case VG_MAX_DASH_COUNT:
+ case VG_MAX_KERNEL_SIZE:
+ case VG_MAX_SEPARABLE_KERNEL_SIZE:
+ case VG_MAX_IMAGE_WIDTH:
+ case VG_MAX_IMAGE_HEIGHT:
+ case VG_MAX_IMAGE_PIXELS:
+ case VG_MAX_IMAGE_BYTES:
+ case VG_MAX_FLOAT:
+ case VG_MAX_GAUSSIAN_STD_DEVIATION:
+ return 1;
+ default:
+ if (ctx)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return 0;
+ }
+}
+
+void vgGetfv(VGParamType type, VGint count,
+ VGfloat * values)
+{
+ const struct vg_state *state = current_state();
+ struct vg_context *ctx = vg_current_context();
+ VGint real_count = vgGetVectorSize(type);
+
+ if (!values || count <= 0 || count > real_count || !is_aligned(values)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ switch(type) {
+ case VG_MATRIX_MODE:
+ case VG_FILL_RULE:
+ case VG_IMAGE_QUALITY:
+ case VG_RENDERING_QUALITY:
+ case VG_BLEND_MODE:
+ case VG_IMAGE_MODE:
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM:
+#endif
+ case VG_STROKE_CAP_STYLE:
+ case VG_STROKE_JOIN_STYLE:
+ case VG_STROKE_DASH_PHASE_RESET:
+ case VG_MASKING:
+ case VG_SCISSORING:
+ case VG_PIXEL_LAYOUT:
+ case VG_SCREEN_LAYOUT:
+ case VG_FILTER_FORMAT_LINEAR:
+ case VG_FILTER_FORMAT_PREMULTIPLIED:
+ case VG_FILTER_CHANNEL_MASK:
+ case VG_MAX_SCISSOR_RECTS:
+ case VG_MAX_DASH_COUNT:
+ case VG_MAX_KERNEL_SIZE:
+ case VG_MAX_SEPARABLE_KERNEL_SIZE:
+ case VG_MAX_COLOR_RAMP_STOPS:
+ case VG_MAX_IMAGE_WIDTH:
+ case VG_MAX_IMAGE_HEIGHT:
+ case VG_MAX_IMAGE_PIXELS:
+ case VG_MAX_IMAGE_BYTES:
+ case VG_MAX_GAUSSIAN_STD_DEVIATION:
+ values[0] = vgGeti(type);
+ break;
+ case VG_MAX_FLOAT:
+ values[0] = vgGetf(type);
+ break;
+ case VG_SCISSOR_RECTS: {
+ VGint i;
+ for (i = 0; i < count; ++i) {
+ values[i] = state->scissor_rects[i].f;
+ }
+ }
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM_VALUES: {
+ memcpy(values, state->color_transform_values,
+ sizeof(VGfloat) * count);
+ }
+ break;
+#endif
+ case VG_STROKE_LINE_WIDTH:
+ values[0] = state->stroke.line_width.f;
+ break;
+ case VG_STROKE_MITER_LIMIT:
+ values[0] = state->stroke.miter_limit.f;
+ break;
+ case VG_STROKE_DASH_PATTERN: {
+ VGint i;
+ for (i = 0; i < count; ++i) {
+ values[i] = state->stroke.dash_pattern[i].f;
+ }
+ }
+ break;
+ case VG_STROKE_DASH_PHASE:
+ values[0] = state->stroke.dash_phase.f;
+ break;
+ case VG_TILE_FILL_COLOR:
+ values[0] = state->tile_fill_color[0];
+ values[1] = state->tile_fill_color[1];
+ values[2] = state->tile_fill_color[2];
+ values[3] = state->tile_fill_color[3];
+ break;
+ case VG_CLEAR_COLOR:
+ values[0] = state->clear_color[0];
+ values[1] = state->clear_color[1];
+ values[2] = state->clear_color[2];
+ values[3] = state->clear_color[3];
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_GLYPH_ORIGIN:
+ values[0] = state->glyph_origin[0].f;
+ values[1] = state->glyph_origin[1].f;
+ break;
+#endif
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ }
+}
+
+void vgGetiv(VGParamType type, VGint count,
+ VGint * values)
+{
+ const struct vg_state *state = current_state();
+ struct vg_context *ctx = vg_current_context();
+ VGint real_count = vgGetVectorSize(type);
+
+ if (!values || count <= 0 || count > real_count || !is_aligned(values)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ switch(type) {
+ case VG_MATRIX_MODE:
+ case VG_FILL_RULE:
+ case VG_IMAGE_QUALITY:
+ case VG_RENDERING_QUALITY:
+ case VG_BLEND_MODE:
+ case VG_IMAGE_MODE:
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM:
+#endif
+ case VG_STROKE_CAP_STYLE:
+ case VG_STROKE_JOIN_STYLE:
+ case VG_STROKE_DASH_PHASE_RESET:
+ case VG_MASKING:
+ case VG_SCISSORING:
+ case VG_PIXEL_LAYOUT:
+ case VG_SCREEN_LAYOUT:
+ case VG_FILTER_FORMAT_LINEAR:
+ case VG_FILTER_FORMAT_PREMULTIPLIED:
+ case VG_FILTER_CHANNEL_MASK:
+ case VG_MAX_SCISSOR_RECTS:
+ case VG_MAX_DASH_COUNT:
+ case VG_MAX_KERNEL_SIZE:
+ case VG_MAX_SEPARABLE_KERNEL_SIZE:
+ case VG_MAX_COLOR_RAMP_STOPS:
+ case VG_MAX_IMAGE_WIDTH:
+ case VG_MAX_IMAGE_HEIGHT:
+ case VG_MAX_IMAGE_PIXELS:
+ case VG_MAX_IMAGE_BYTES:
+ case VG_MAX_GAUSSIAN_STD_DEVIATION:
+ values[0] = vgGeti(type);
+ break;
+ case VG_MAX_FLOAT: {
+ VGfloat val = vgGetf(type);
+ values[0] = float_to_int_floor(*((VGuint*)&val));
+ }
+ break;
+ case VG_SCISSOR_RECTS: {
+ VGint i;
+ for (i = 0; i < count; ++i) {
+ values[i] = state->scissor_rects[i].i;
+ }
+ }
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_COLOR_TRANSFORM_VALUES: {
+ VGint i;
+ VGuint *x = (VGuint*)state->color_transform_values;
+ for (i = 0; i < count; ++i) {
+ values[i] = float_to_int_floor(x[i]);
+ }
+ }
+ break;
+#endif
+ case VG_STROKE_LINE_WIDTH:
+ values[0] = state->stroke.line_width.i;
+ break;
+ case VG_STROKE_MITER_LIMIT:
+ values[0] = state->stroke.miter_limit.i;
+ break;
+ case VG_STROKE_DASH_PATTERN: {
+ VGint i;
+ for (i = 0; i < count; ++i) {
+ values[i] = state->stroke.dash_pattern[i].i;
+ }
+ }
+ break;
+ case VG_STROKE_DASH_PHASE:
+ values[0] = state->stroke.dash_phase.i;
+ break;
+ case VG_TILE_FILL_COLOR:
+ values[0] = state->tile_fill_colori[0];
+ values[1] = state->tile_fill_colori[1];
+ values[2] = state->tile_fill_colori[2];
+ values[3] = state->tile_fill_colori[3];
+ break;
+ case VG_CLEAR_COLOR:
+ values[0] = state->clear_colori[0];
+ values[1] = state->clear_colori[1];
+ values[2] = state->clear_colori[2];
+ values[3] = state->clear_colori[3];
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_GLYPH_ORIGIN:
+ values[0] = state->glyph_origin[0].i;
+ values[1] = state->glyph_origin[1].i;
+ break;
+#endif
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ }
+}
+
+void vgSetParameterf(VGHandle object,
+ VGint paramType,
+ VGfloat value)
+{
+ struct vg_context *ctx = vg_current_context();
+ void *ptr = (void*)object;
+
+ if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ switch(paramType) {
+ case VG_PAINT_TYPE:
+ case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
+ case VG_PAINT_PATTERN_TILING_MODE:
+ vgSetParameteri(object, paramType, floor(value));
+ return;
+ break;
+ case VG_PAINT_COLOR:
+ case VG_PAINT_COLOR_RAMP_STOPS:
+ case VG_PAINT_LINEAR_GRADIENT:
+ case VG_PAINT_RADIAL_GRADIENT:
+ /* it's an error if paramType refers to a vector parameter */
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
+ struct vg_paint *p = (struct vg_paint *)object;
+ paint_set_color_ramp_premultiplied(p, value);
+ }
+ break;
+
+ case VG_PATH_DATATYPE:
+ case VG_PATH_FORMAT:
+ case VG_PATH_SCALE:
+ case VG_PATH_BIAS:
+ case VG_PATH_NUM_SEGMENTS:
+ case VG_PATH_NUM_COORDS:
+
+ case VG_IMAGE_FORMAT:
+ case VG_IMAGE_WIDTH:
+ case VG_IMAGE_HEIGHT:
+
+#ifdef OPENVG_VERSION_1_1
+ case VG_FONT_NUM_GLYPHS:
+ /* read only don't produce an error */
+ break;
+#endif
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ }
+}
+
+void vgSetParameteri(VGHandle object,
+ VGint paramType,
+ VGint value)
+{
+ struct vg_context *ctx = vg_current_context();
+ void *ptr = (void*)object;
+
+ if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ switch(paramType) {
+ case VG_PAINT_TYPE:
+ if (value < VG_PAINT_TYPE_COLOR ||
+ value > VG_PAINT_TYPE_PATTERN)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else {
+ struct vg_paint *paint = (struct vg_paint *)ptr;
+ paint_set_type(paint, value);
+ }
+ break;
+ case VG_PAINT_COLOR:
+ case VG_PAINT_COLOR_RAMP_STOPS:
+ case VG_PAINT_LINEAR_GRADIENT:
+ case VG_PAINT_RADIAL_GRADIENT:
+ /* it's an error if paramType refers to a vector parameter */
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
+ if (value < VG_COLOR_RAMP_SPREAD_PAD ||
+ value > VG_COLOR_RAMP_SPREAD_REFLECT)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else {
+ struct vg_paint *paint = (struct vg_paint *)ptr;
+ paint_set_spread_mode(paint, value);
+ }
+ break;
+ case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
+ struct vg_paint *p = (struct vg_paint *)object;
+ paint_set_color_ramp_premultiplied(p, value);
+ }
+ break;
+ case VG_PAINT_PATTERN_TILING_MODE:
+ if (value < VG_TILE_FILL ||
+ value > VG_TILE_REFLECT)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else {
+ struct vg_paint *paint = (struct vg_paint *)ptr;
+ paint_set_pattern_tiling(paint, value);
+ }
+ break;
+
+ case VG_PATH_DATATYPE:
+ case VG_PATH_FORMAT:
+ case VG_PATH_SCALE:
+ case VG_PATH_BIAS:
+ case VG_PATH_NUM_SEGMENTS:
+ case VG_PATH_NUM_COORDS:
+
+ case VG_IMAGE_FORMAT:
+ case VG_IMAGE_WIDTH:
+ case VG_IMAGE_HEIGHT:
+
+#ifdef OPENVG_VERSION_1_1
+ case VG_FONT_NUM_GLYPHS:
+ /* read only don't produce an error */
+ break;
+#endif
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+}
+
+void vgSetParameterfv(VGHandle object,
+ VGint paramType,
+ VGint count,
+ const VGfloat * values)
+{
+ struct vg_context *ctx = vg_current_context();
+ void *ptr = (void*)object;
+ VGint real_count = vgGetParameterVectorSize(object, paramType);
+
+ if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (count < 0 || count < real_count ||
+ (values == NULL && count != 0) ||
+ !is_aligned(values)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ switch(paramType) {
+ case VG_PAINT_TYPE:
+ case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
+ case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
+ case VG_PAINT_PATTERN_TILING_MODE:
+ if (count != 1)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else
+ vgSetParameterf(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;
+ paint_set_color(paint, values);
+ }
+ }
+ break;
+ case VG_PAINT_COLOR_RAMP_STOPS: {
+ if (count && count < 4)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ count = MIN2(count, VEGA_MAX_COLOR_RAMP_STOPS);
+ paint_set_ramp_stops(paint, values, count);
+ {
+ VGint stopsi[VEGA_MAX_COLOR_RAMP_STOPS];
+ int i = 0;
+ for (i = 0; i < count; ++i) {
+ stopsi[i] = float_to_int_floor(*((VGuint*)(values + i)));
+ }
+ paint_set_ramp_stopsi(paint, stopsi, count);
+ }
+ }
+ }
+ break;
+ case VG_PAINT_LINEAR_GRADIENT: {
+ if (count != 4)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_set_linear_gradient(paint, values);
+ {
+ VGint vals[4];
+ vals[0] = FLT_TO_INT(values[0]);
+ vals[1] = FLT_TO_INT(values[1]);
+ vals[2] = FLT_TO_INT(values[2]);
+ vals[3] = FLT_TO_INT(values[3]);
+ paint_set_linear_gradienti(paint, vals);
+ }
+ }
+ }
+ break;
+ case VG_PAINT_RADIAL_GRADIENT: {
+ if (count != 5)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_set_radial_gradient(paint, values);
+ {
+ VGint vals[5];
+ vals[0] = FLT_TO_INT(values[0]);
+ vals[1] = FLT_TO_INT(values[1]);
+ vals[2] = FLT_TO_INT(values[2]);
+ vals[3] = FLT_TO_INT(values[3]);
+ vals[4] = FLT_TO_INT(values[4]);
+ paint_set_radial_gradienti(paint, vals);
+ }
+ }
+ }
+ break;
+
+ case VG_PATH_DATATYPE:
+ case VG_PATH_FORMAT:
+ case VG_PATH_SCALE:
+ case VG_PATH_BIAS:
+ case VG_PATH_NUM_SEGMENTS:
+ case VG_PATH_NUM_COORDS:
+
+#ifdef OPENVG_VERSION_1_1
+ case VG_FONT_NUM_GLYPHS:
+ /* read only don't produce an error */
+ break;
+#endif
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+}
+
+void vgSetParameteriv(VGHandle object,
+ VGint paramType,
+ VGint count,
+ const VGint * values)
+{
+ struct vg_context *ctx = vg_current_context();
+ void *ptr = (void*)object;
+ VGint real_count = vgGetParameterVectorSize(object, paramType);
+
+ if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (count < 0 || count < real_count ||
+ (values == NULL && count != 0) ||
+ !is_aligned(values)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ switch(paramType) {
+ case VG_PAINT_TYPE:
+ case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
+ case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
+ case VG_PAINT_PATTERN_TILING_MODE:
+ if (count != 1)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else
+ vgSetParameteri(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;
+ paint_set_coloriv(paint, values);
+ }
+ }
+ break;
+ case VG_PAINT_COLOR_RAMP_STOPS: {
+ if ((count % 5))
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else {
+ VGfloat *vals = 0;
+ int i;
+ struct vg_paint *paint = (struct vg_paint *)object;
+ if (count) {
+ vals = malloc(sizeof(VGfloat)*count);
+ for (i = 0; i < count; ++i)
+ vals[i] = values[i];
+ }
+
+ paint_set_ramp_stopsi(paint, values, count);
+ paint_set_ramp_stops(paint, vals, count);
+ free(vals);
+ }
+ }
+ break;
+ case VG_PAINT_LINEAR_GRADIENT: {
+ if (count != 4)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else {
+ VGfloat vals[4];
+ struct vg_paint *paint = (struct vg_paint *)object;
+ vals[0] = values[0];
+ vals[1] = values[1];
+ vals[2] = values[2];
+ vals[3] = values[3];
+ paint_set_linear_gradient(paint, vals);
+ paint_set_linear_gradienti(paint, values);
+ }
+ }
+ break;
+ case VG_PAINT_RADIAL_GRADIENT: {
+ if (count != 5)
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ else {
+ VGfloat vals[5];
+ struct vg_paint *paint = (struct vg_paint *)object;
+ vals[0] = values[0];
+ vals[1] = values[1];
+ vals[2] = values[2];
+ vals[3] = values[3];
+ vals[4] = values[4];
+ paint_set_radial_gradient(paint, vals);
+ paint_set_radial_gradienti(paint, values);
+ }
+ }
+ break;
+ case VG_PATH_DATATYPE:
+ case VG_PATH_FORMAT:
+ case VG_PATH_SCALE:
+ case VG_PATH_BIAS:
+ case VG_PATH_NUM_SEGMENTS:
+ case VG_PATH_NUM_COORDS:
+ /* read only don't produce an error */
+ break;
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+}
+
+VGint vgGetParameterVectorSize(VGHandle object,
+ VGint paramType)
+{
+ struct vg_context *ctx = vg_current_context();
+ void *ptr = (void*)object;
+
+ if (!ptr || object == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return 0;
+ }
+
+ switch(paramType) {
+ case VG_PAINT_TYPE:
+ case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
+ case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
+ case VG_PAINT_PATTERN_TILING_MODE:
+ return 1;
+ case VG_PAINT_COLOR:
+ return 4;
+ case VG_PAINT_COLOR_RAMP_STOPS: {
+ struct vg_paint *p = (struct vg_paint *)object;
+ return paint_num_ramp_stops(p);
+ }
+ break;
+ case VG_PAINT_LINEAR_GRADIENT:
+ return 4;
+ case VG_PAINT_RADIAL_GRADIENT:
+ return 5;
+
+
+ case VG_PATH_FORMAT:
+ case VG_PATH_DATATYPE:
+ case VG_PATH_SCALE:
+ case VG_PATH_BIAS:
+ case VG_PATH_NUM_SEGMENTS:
+ case VG_PATH_NUM_COORDS:
+ return 1;
+
+ case VG_IMAGE_FORMAT:
+ case VG_IMAGE_WIDTH:
+ case VG_IMAGE_HEIGHT:
+ return 1;
+
+#ifdef OPENVG_VERSION_1_1
+ case VG_FONT_NUM_GLYPHS:
+ return 1;
+#endif
+
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ }
+ return 0;
+}
+
+
+VGfloat vgGetParameterf(VGHandle object,
+ VGint paramType)
+{
+ struct vg_context *ctx = vg_current_context();
+ void *ptr = (void*)object;
+
+ if (!ptr || object == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return 0;
+ }
+
+ switch(paramType) {
+ case VG_PAINT_TYPE:
+ case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
+ case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
+ case VG_PAINT_PATTERN_TILING_MODE:
+ return vgGetParameteri(object, paramType);
+ break;
+ case VG_PAINT_COLOR:
+ case VG_PAINT_COLOR_RAMP_STOPS:
+ case VG_PAINT_LINEAR_GRADIENT:
+ case VG_PAINT_RADIAL_GRADIENT:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+
+ case VG_PATH_FORMAT:
+ return VG_PATH_FORMAT_STANDARD;
+ case VG_PATH_SCALE: {
+ struct path *p = (struct path*)object;
+ return path_scale(p);
+ }
+ case VG_PATH_BIAS: {
+ struct path *p = (struct path*)object;
+ return path_bias(p);
+ }
+ case VG_PATH_DATATYPE:
+ case VG_PATH_NUM_SEGMENTS:
+ case VG_PATH_NUM_COORDS:
+ return vgGetParameteri(object, paramType);
+ break;
+
+ case VG_IMAGE_FORMAT:
+ case VG_IMAGE_WIDTH:
+ case VG_IMAGE_HEIGHT:
+#ifdef OPENVG_VERSION_1_1
+ case VG_FONT_NUM_GLYPHS:
+ return vgGetParameteri(object, paramType);
+ break;
+#endif
+
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ }
+ return 0;
+}
+
+VGint vgGetParameteri(VGHandle object,
+ VGint paramType)
+{
+ struct vg_context *ctx = vg_current_context();
+ void *ptr = (void*)object;
+
+ if (!ptr || 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;
+ return paint_type(paint);
+ }
+ break;
+ case VG_PAINT_COLOR_RAMP_SPREAD_MODE: {
+ struct vg_paint *p = (struct vg_paint *)object;
+ return paint_spread_mode(p);
+ }
+ case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
+ struct vg_paint *p = (struct vg_paint *)object;
+ return paint_color_ramp_premultiplied(p);
+ }
+ break;
+ case VG_PAINT_PATTERN_TILING_MODE: {
+ struct vg_paint *p = (struct vg_paint *)object;
+ return paint_pattern_tiling(p);
+ }
+ break;
+ case VG_PAINT_COLOR:
+ case VG_PAINT_COLOR_RAMP_STOPS:
+ case VG_PAINT_LINEAR_GRADIENT:
+ case VG_PAINT_RADIAL_GRADIENT:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+
+ case VG_PATH_FORMAT:
+ return VG_PATH_FORMAT_STANDARD;
+ case VG_PATH_SCALE:
+ case VG_PATH_BIAS:
+ return vgGetParameterf(object, paramType);
+ case VG_PATH_DATATYPE: {
+ struct path *p = (struct path*)object;
+ return path_datatype(p);
+ }
+ case VG_PATH_NUM_SEGMENTS: {
+ struct path *p = (struct path*)object;
+ return path_num_segments(p);
+ }
+ case VG_PATH_NUM_COORDS: {
+ struct path *p = (struct path*)object;
+ return path_num_coords(p);
+ }
+ break;
+
+ case VG_IMAGE_FORMAT: {
+ struct vg_image *img = (struct vg_image*)object;
+ return img->format;
+ }
+ break;
+ case VG_IMAGE_WIDTH: {
+ struct vg_image *img = (struct vg_image*)object;
+ return img->width;
+ }
+ break;
+ case VG_IMAGE_HEIGHT: {
+ struct vg_image *img = (struct vg_image*)object;
+ return img->height;
+ }
+ break;
+
+#ifdef OPENVG_VERSION_1_1
+ case VG_FONT_NUM_GLYPHS: {
+ return 1;
+ }
+ break;
+#endif
+
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ }
+ return 0;
+}
+
+void vgGetParameterfv(VGHandle object,
+ VGint paramType,
+ VGint count,
+ VGfloat * values)
+{
+ struct vg_context *ctx = vg_current_context();
+ void *ptr = (void*)object;
+ VGint real_count = vgGetParameterVectorSize(object, paramType);
+
+ if (!ptr || object == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (!values || count <= 0 || count > real_count ||
+ !is_aligned(values)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ switch(paramType) {
+ case VG_PAINT_TYPE: {
+ struct vg_paint *p = (struct vg_paint *)object;
+ values[0] = paint_type(p);
+ }
+ break;
+ case VG_PAINT_COLOR_RAMP_SPREAD_MODE: {
+ struct vg_paint *p = (struct vg_paint *)object;
+ values[0] = paint_spread_mode(p);
+ }
+ break;
+ case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
+ struct vg_paint *p = (struct vg_paint *)object;
+ values[0] = paint_color_ramp_premultiplied(p);
+ }
+ break;
+ case VG_PAINT_PATTERN_TILING_MODE: {
+ values[0] = vgGetParameterf(object, paramType);
+ }
+ break;
+ case VG_PAINT_COLOR: {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_get_color(paint, values);
+ }
+ break;
+ case VG_PAINT_COLOR_RAMP_STOPS: {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_ramp_stops(paint, values, count);
+ }
+ break;
+ case VG_PAINT_LINEAR_GRADIENT: {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_linear_gradient(paint, values);
+ }
+ break;
+ case VG_PAINT_RADIAL_GRADIENT: {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_radial_gradient(paint, values);
+ }
+ break;
+
+ case VG_PATH_FORMAT:
+ case VG_PATH_DATATYPE:
+ case VG_PATH_NUM_SEGMENTS:
+ case VG_PATH_NUM_COORDS:
+ values[0] = vgGetParameteri(object, paramType);
+ break;
+ case VG_PATH_SCALE:
+ case VG_PATH_BIAS:
+ values[0] = vgGetParameterf(object, paramType);
+ break;
+
+ case VG_IMAGE_FORMAT:
+ case VG_IMAGE_WIDTH:
+ case VG_IMAGE_HEIGHT:
+#ifdef OPENVG_VERSION_1_1
+ case VG_FONT_NUM_GLYPHS:
+ values[0] = vgGetParameteri(object, paramType);
+ break;
+#endif
+
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ }
+}
+
+void vgGetParameteriv(VGHandle object,
+ VGint paramType,
+ VGint count,
+ VGint * values)
+{
+ struct vg_context *ctx = vg_current_context();
+ void *ptr = (void*)object;
+ VGint real_count = vgGetParameterVectorSize(object, paramType);
+
+ if (!ptr || object == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (!values || count <= 0 || count > real_count ||
+ !is_aligned(values)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ switch(paramType) {
+ case VG_PAINT_TYPE:
+ case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
+ case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
+ case VG_PAINT_PATTERN_TILING_MODE:
+#ifdef OPENVG_VERSION_1_1
+ case VG_FONT_NUM_GLYPHS:
+ values[0] = vgGetParameteri(object, paramType);
+ break;
+#endif
+ case VG_PAINT_COLOR: {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_get_coloriv(paint, values);
+ }
+ break;
+ case VG_PAINT_COLOR_RAMP_STOPS: {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_ramp_stopsi(paint, values, count);
+ }
+ break;
+ case VG_PAINT_LINEAR_GRADIENT: {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_linear_gradienti(paint, values);
+ }
+ break;
+ case VG_PAINT_RADIAL_GRADIENT: {
+ struct vg_paint *paint = (struct vg_paint *)object;
+ paint_radial_gradienti(paint, values);
+ }
+ break;
+
+ case VG_PATH_SCALE:
+ case VG_PATH_BIAS:
+ values[0] = vgGetParameterf(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);
+ break;
+
+ case VG_IMAGE_FORMAT:
+ case VG_IMAGE_WIDTH:
+ case VG_IMAGE_HEIGHT:
+ values[0] = vgGetParameteri(object, paramType);
+ break;
+
+ default:
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ break;
+ }
+}
diff --git a/src/gallium/state_trackers/vega/api_path.c b/src/gallium/state_trackers/vega/api_path.c
new file mode 100644
index 0000000000..a6b7a2bb93
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_path.c
@@ -0,0 +1,488 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+
+#include "vg_context.h"
+#include "path.h"
+#include "polygon.h"
+#include "paint.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_draw_quad.h"
+
+VGPath vgCreatePath(VGint pathFormat,
+ VGPathDatatype datatype,
+ VGfloat scale, VGfloat bias,
+ VGint segmentCapacityHint,
+ VGint coordCapacityHint,
+ VGbitfield capabilities)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (pathFormat != VG_PATH_FORMAT_STANDARD) {
+ vg_set_error(ctx, VG_UNSUPPORTED_PATH_FORMAT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+ if (datatype < VG_PATH_DATATYPE_S_8 ||
+ datatype > VG_PATH_DATATYPE_F) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+ if (!scale) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+
+ return (VGPath)path_create(datatype, scale, bias,
+ segmentCapacityHint, coordCapacityHint,
+ capabilities);
+}
+
+void vgClearPath(VGPath path, VGbitfield capabilities)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *p = 0;
+
+ if (path == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ p = (struct path *)path;
+ path_clear(p, capabilities);
+}
+
+void vgDestroyPath(VGPath p)
+{
+ struct path *path = 0;
+ struct vg_context *ctx = vg_current_context();
+
+ if (p == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ path = (struct path *)p;
+ path_destroy(path);
+}
+
+void vgRemovePathCapabilities(VGPath path,
+ VGbitfield capabilities)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGbitfield current;
+ struct path *p;
+
+ if (path == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ p = (struct path*)path;
+ current = path_capabilities(p);
+ path_set_capabilities(p, (current &
+ (~(capabilities & VG_PATH_CAPABILITY_ALL))));
+}
+
+VGbitfield vgGetPathCapabilities(VGPath path)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *p = 0;
+
+ if (path == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return 0;
+ }
+ p = (struct path*)path;
+ return path_capabilities(p);
+}
+
+void vgAppendPath(VGPath dstPath, VGPath srcPath)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *src, *dst;
+
+ if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ src = (struct path *)srcPath;
+ dst = (struct path *)dstPath;
+
+ if (!(path_capabilities(src) & VG_PATH_CAPABILITY_APPEND_FROM) ||
+ !(path_capabilities(dst) & VG_PATH_CAPABILITY_APPEND_TO)) {
+ vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
+ return;
+ }
+ path_append_path(dst, src);
+}
+
+void vgAppendPathData(VGPath dstPath,
+ VGint numSegments,
+ const VGubyte * pathSegments,
+ const void * pathData)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *p = 0;
+ VGint i;
+
+ if (dstPath == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (!pathSegments) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (numSegments <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ for (i = 0; i < numSegments; ++i) {
+ if (pathSegments[i] < VG_CLOSE_PATH ||
+ pathSegments[i] > VG_LCWARC_TO_REL) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ }
+
+ p = (struct path*)dstPath;
+
+ if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (!(path_capabilities(p)&VG_PATH_CAPABILITY_APPEND_TO)) {
+ vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
+ return;
+ }
+
+ path_append_data(p, numSegments, pathSegments, pathData);
+}
+
+void vgModifyPathCoords(VGPath dstPath,
+ VGint startIndex,
+ VGint numSegments,
+ const void * pathData)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *p = 0;
+
+ if (dstPath == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (startIndex < 0 || numSegments <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ p = (struct path *)dstPath;
+
+ if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (startIndex + numSegments > path_num_segments(p)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (!(path_capabilities(p)&VG_PATH_CAPABILITY_MODIFY)) {
+ vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
+ return;
+ }
+ path_modify_coords(p, startIndex, numSegments, pathData);
+}
+
+void vgTransformPath(VGPath dstPath, VGPath srcPath)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *src = 0, *dst = 0;
+
+ if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ src = (struct path *)srcPath;
+ dst = (struct path *)dstPath;
+
+ if (!(path_capabilities(src) & VG_PATH_CAPABILITY_TRANSFORM_FROM) ||
+ !(path_capabilities(dst) & VG_PATH_CAPABILITY_TRANSFORM_TO)) {
+ vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
+ return;
+ }
+ path_transform(dst, src);
+}
+
+VGboolean vgInterpolatePath(VGPath dstPath,
+ VGPath startPath,
+ VGPath endPath,
+ VGfloat amount)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *start = 0, *dst = 0, *end = 0;
+
+ if (dstPath == VG_INVALID_HANDLE ||
+ startPath == VG_INVALID_HANDLE ||
+ endPath == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return VG_FALSE;
+ }
+ dst = (struct path *)dstPath;
+ start = (struct path *)startPath;
+ end = (struct path *)endPath;
+
+ if (!(path_capabilities(dst) & VG_PATH_CAPABILITY_INTERPOLATE_TO) ||
+ !(path_capabilities(start) & VG_PATH_CAPABILITY_INTERPOLATE_FROM) ||
+ !(path_capabilities(end) & VG_PATH_CAPABILITY_INTERPOLATE_FROM)) {
+ vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
+ return VG_FALSE;
+ }
+
+ return path_interpolate(dst,
+ start, end, amount);
+}
+
+VGfloat vgPathLength(VGPath path,
+ VGint startSegment,
+ VGint numSegments)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *p = 0;
+
+ if (path == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return -1;
+ }
+ if (startSegment < 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return -1;
+ }
+ if (numSegments <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return -1;
+ }
+ p = (struct path*)path;
+
+ if (!(path_capabilities(p) & VG_PATH_CAPABILITY_PATH_LENGTH)) {
+ vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
+ return -1;
+ }
+ if (startSegment + numSegments > path_num_segments(p)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return -1;
+ }
+
+ return path_length(p, startSegment, numSegments);
+}
+
+void vgPointAlongPath(VGPath path,
+ VGint startSegment,
+ VGint numSegments,
+ VGfloat distance,
+ VGfloat * x, VGfloat * y,
+ VGfloat * tangentX,
+ VGfloat * tangentY)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *p = 0;
+ VGbitfield caps;
+
+ if (path == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (startSegment < 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (numSegments <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (!is_aligned(x) || !is_aligned(y) ||
+ !is_aligned(tangentX) || !is_aligned(tangentY)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ p = (struct path*)path;
+
+ caps = path_capabilities(p);
+ if (!(caps & VG_PATH_CAPABILITY_POINT_ALONG_PATH) ||
+ !(caps & VG_PATH_CAPABILITY_TANGENT_ALONG_PATH)) {
+ vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
+ return;
+ }
+
+ if (startSegment + numSegments > path_num_segments(p)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ {
+ VGfloat point[2], normal[2];
+ path_point(p, startSegment, numSegments, distance,
+ point, normal);
+ if (x)
+ *x = point[0];
+ if (y)
+ *y = point[1];
+ if (tangentX)
+ *tangentX = -normal[1];
+ if (tangentY)
+ *tangentY = normal[0];
+ }
+}
+
+void vgPathBounds(VGPath path,
+ VGfloat * minX,
+ VGfloat * minY,
+ VGfloat * width,
+ VGfloat * height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *p = 0;
+ VGbitfield caps;
+
+ if (path == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (!minX || !minY || !width || !height) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (!is_aligned(minX) || !is_aligned(minY) ||
+ !is_aligned(width) || !is_aligned(height)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ p = (struct path*)path;
+
+ caps = path_capabilities(p);
+ if (!(caps & VG_PATH_CAPABILITY_PATH_BOUNDS)) {
+ vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
+ return;
+ }
+
+ path_bounding_rect(p, minX, minY, width, height);
+}
+
+void vgPathTransformedBounds(VGPath path,
+ VGfloat * minX,
+ VGfloat * minY,
+ VGfloat * width,
+ VGfloat * height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct path *p = 0;
+ VGbitfield caps;
+
+ if (path == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (!minX || !minY || !width || !height) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (!is_aligned(minX) || !is_aligned(minY) ||
+ !is_aligned(width) || !is_aligned(height)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ p = (struct path*)path;
+
+ caps = path_capabilities(p);
+ if (!(caps & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS)) {
+ vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
+ return;
+ }
+
+#if 0
+ /* faster, but seems to have precision problems... */
+ path_bounding_rect(p, minX, minY, width, height);
+ if (*width > 0 && *height > 0) {
+ VGfloat pts[] = {*minX, *minY,
+ *minX + *width, *minY,
+ *minX + *width, *minY + *height,
+ *minX, *minY + *height};
+ struct matrix *matrix = &ctx->state.vg.path_user_to_surface_matrix;
+ VGfloat maxX, maxY;
+ matrix_map_point(matrix, pts[0], pts[1], pts + 0, pts + 1);
+ matrix_map_point(matrix, pts[2], pts[3], pts + 2, pts + 3);
+ matrix_map_point(matrix, pts[4], pts[5], pts + 4, pts + 5);
+ matrix_map_point(matrix, pts[6], pts[7], pts + 6, pts + 7);
+ *minX = MIN2(pts[0], MIN2(pts[2], MIN2(pts[4], pts[6])));
+ *minY = MIN2(pts[1], MIN2(pts[3], MIN2(pts[5], pts[7])));
+ maxX = MAX2(pts[0], MAX2(pts[2], MAX2(pts[4], pts[6])));
+ maxY = MAX2(pts[1], MAX2(pts[3], MAX2(pts[5], pts[7])));
+ *width = maxX - *minX;
+ *height = maxY - *minY;
+ }
+#else
+ {
+ struct path *dst = path_create(VG_PATH_DATATYPE_F, 1.0, 0,
+ 0, 0, VG_PATH_CAPABILITY_ALL);
+ path_transform(dst, p);
+ path_bounding_rect(dst, minX, minY, width, height);
+ path_destroy(dst);
+ }
+#endif
+}
+
+
+void vgDrawPath(VGPath path, VGbitfield paintModes)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (path == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ if (!(paintModes & (VG_STROKE_PATH | VG_FILL_PATH))) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (path_is_empty((struct path*)path))
+ return;
+ path_render((struct path*)path, paintModes);
+}
+
diff --git a/src/gallium/state_trackers/vega/api_text.c b/src/gallium/state_trackers/vega/api_text.c
new file mode 100644
index 0000000000..d8411cf3e8
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_text.c
@@ -0,0 +1,258 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+
+#include "vg_context.h"
+
+#include "util/u_memory.h"
+
+#ifdef OPENVG_VERSION_1_1
+
+struct vg_font {
+ struct vg_object base;
+
+ VGint glyph_indices[200];
+ VGint num_glyphs;
+};
+
+VGFont vgCreateFont(VGint glyphCapacityHint)
+{
+ struct vg_font *font = 0;
+ struct vg_context *ctx = vg_current_context();
+
+ if (glyphCapacityHint < 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return VG_INVALID_HANDLE;
+ }
+
+ font = CALLOC_STRUCT(vg_font);
+ vg_init_object(&font->base, ctx, VG_OBJECT_FONT);
+ vg_context_add_object(ctx, VG_OBJECT_FONT, font);
+ return (VGFont)font;
+}
+
+void vgDestroyFont(VGFont f)
+{
+ struct vg_font *font = (struct vg_font *)f;
+ struct vg_context *ctx = vg_current_context();
+
+ if (f == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ vg_context_remove_object(ctx, VG_OBJECT_FONT, font);
+ /*free(font);*/
+}
+
+void vgSetGlyphToPath(VGFont font,
+ VGuint glyphIndex,
+ VGPath path,
+ VGboolean isHinted,
+ VGfloat glyphOrigin [2],
+ VGfloat escapement[2])
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_object *pathObj;
+ struct vg_font *f;
+
+ if (font == VG_INVALID_HANDLE ||
+ !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (!glyphOrigin || !escapement ||
+ !is_aligned(glyphOrigin) || !is_aligned(escapement)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (path != VG_INVALID_HANDLE &&
+ !vg_context_is_object_valid(ctx, VG_OBJECT_PATH, (void *)path)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ pathObj = (struct vg_object*)path;
+ if (pathObj && pathObj->type != VG_OBJECT_PATH) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+
+ f = (struct vg_font*)font;
+ f->glyph_indices[f->num_glyphs] = glyphIndex;
+ ++f->num_glyphs;
+}
+
+void vgSetGlyphToImage(VGFont font,
+ VGuint glyphIndex,
+ VGImage image,
+ VGfloat glyphOrigin [2],
+ VGfloat escapement[2])
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_object *img_obj;
+ struct vg_font *f;
+
+ if (font == VG_INVALID_HANDLE ||
+ !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (!glyphOrigin || !escapement ||
+ !is_aligned(glyphOrigin) || !is_aligned(escapement)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (image != VG_INVALID_HANDLE &&
+ !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)image)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ img_obj = (struct vg_object*)image;
+ if (img_obj && img_obj->type != VG_OBJECT_IMAGE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ f = (struct vg_font*)font;
+ f->glyph_indices[f->num_glyphs] = glyphIndex;
+ ++f->num_glyphs;
+}
+
+static INLINE VGboolean font_contains_glyph(struct vg_font *font,
+ VGuint glyph_index)
+{
+ VGint i;
+ for (i = 0; i < font->num_glyphs; ++i) {
+ if (font->glyph_indices[i] == glyph_index) {
+ return VG_TRUE;
+ }
+ }
+ return VG_FALSE;
+}
+
+void vgClearGlyph(VGFont font,
+ VGuint glyphIndex)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_font *f;
+ VGint i;
+
+ if (font == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (glyphIndex <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ f = (struct vg_font*)font;
+ if (!font_contains_glyph(f, glyphIndex)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ for (i = 0; i < f->num_glyphs; ++i) {
+ if (f->glyph_indices[i] == glyphIndex) {
+ /*FIXME*/
+ f->glyph_indices[f->num_glyphs] = 0;
+ --f->num_glyphs;
+ return;
+ }
+ }
+}
+
+void vgDrawGlyph(VGFont font,
+ VGuint glyphIndex,
+ VGbitfield paintModes,
+ VGboolean allowAutoHinting)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_font *f;
+
+ if (font == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (glyphIndex <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (paintModes & (~(VG_STROKE_PATH|VG_FILL_PATH))) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ f = (struct vg_font*)font;
+ if (!font_contains_glyph(f, glyphIndex)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+}
+
+void vgDrawGlyphs(VGFont font,
+ VGint glyphCount,
+ VGuint *glyphIndices,
+ VGfloat *adjustments_x,
+ VGfloat *adjustments_y,
+ VGbitfield paintModes,
+ VGboolean allowAutoHinting)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGint i;
+ struct vg_font *f;
+
+ if (font == VG_INVALID_HANDLE) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
+ if (glyphCount <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (!glyphIndices || !is_aligned(glyphIndices)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (!adjustments_x || !is_aligned(adjustments_x) ||
+ !adjustments_y || !is_aligned(adjustments_y)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ if (paintModes & (~(VG_STROKE_PATH|VG_FILL_PATH))) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ f = (struct vg_font*)font;
+ for (i = 0; i < glyphCount; ++i) {
+ VGuint glyph_index = glyphIndices[i];
+ if (!font_contains_glyph(f, glyph_index)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ }
+}
+
+#endif
diff --git a/src/gallium/state_trackers/vega/api_transform.c b/src/gallium/state_trackers/vega/api_transform.c
new file mode 100644
index 0000000000..763a5ec415
--- /dev/null
+++ b/src/gallium/state_trackers/vega/api_transform.c
@@ -0,0 +1,128 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+
+#include "vg_context.h"
+
+#include "matrix.h"
+
+void vgLoadIdentity(void)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *mat = vg_state_matrix(&ctx->state.vg);
+ matrix_load_identity(mat);
+}
+
+void vgLoadMatrix(const VGfloat * m)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *mat;
+
+ if (!ctx)
+ return;
+
+ if (!m || !is_aligned(m)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ mat = vg_state_matrix(&ctx->state.vg);
+ matrix_init(mat, m);
+ if (!matrix_is_affine(mat)) {
+ if (ctx->state.vg.matrix_mode != VG_MATRIX_IMAGE_USER_TO_SURFACE) {
+ matrix_make_affine(mat);
+ }
+ }
+}
+
+void vgGetMatrix(VGfloat * m)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *mat;
+
+ if (!ctx)
+ return;
+
+ if (!m || !is_aligned(m)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ mat = vg_state_matrix(&ctx->state.vg);
+ memcpy(m, mat->m, sizeof(VGfloat)*9);
+}
+
+void vgMultMatrix(const VGfloat * m)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *dst, src;
+
+ if (!ctx)
+ return;
+
+ if (!m || !is_aligned(m)) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ matrix_init(&src, m);
+ dst = vg_state_matrix(&ctx->state.vg);
+ if (!matrix_is_affine(&src)) {
+ if (ctx->state.vg.matrix_mode != VG_MATRIX_IMAGE_USER_TO_SURFACE) {
+ matrix_make_affine(&src);
+ }
+ }
+ matrix_mult(dst, &src);
+
+}
+
+void vgTranslate(VGfloat tx, VGfloat ty)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *dst = vg_state_matrix(&ctx->state.vg);
+ matrix_translate(dst, tx, ty);
+}
+
+void vgScale(VGfloat sx, VGfloat sy)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *dst = vg_state_matrix(&ctx->state.vg);
+ matrix_scale(dst, sx, sy);
+}
+
+void vgShear(VGfloat shx, VGfloat shy)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *dst = vg_state_matrix(&ctx->state.vg);
+ matrix_shear(dst, shx, shy);
+}
+
+void vgRotate(VGfloat angle)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *dst = vg_state_matrix(&ctx->state.vg);
+ matrix_rotate(dst, angle);
+}
diff --git a/src/gallium/state_trackers/vega/arc.c b/src/gallium/state_trackers/vega/arc.c
new file mode 100644
index 0000000000..e74c7f0334
--- /dev/null
+++ b/src/gallium/state_trackers/vega/arc.c
@@ -0,0 +1,708 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "arc.h"
+
+#include "matrix.h"
+#include "bezier.h"
+#include "polygon.h"
+#include "stroker.h"
+#include "path.h"
+
+#include "util/u_debug.h"
+
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#define DEBUG_ARCS 0
+
+static const VGfloat two_pi = M_PI * 2;
+
+
+static const double coeffs3Low[2][4][4] = {
+ {
+ { 3.85268, -21.229, -0.330434, 0.0127842 },
+ { -1.61486, 0.706564, 0.225945, 0.263682 },
+ { -0.910164, 0.388383, 0.00551445, 0.00671814 },
+ { -0.630184, 0.192402, 0.0098871, 0.0102527 }
+ },
+ {
+ { -0.162211, 9.94329, 0.13723, 0.0124084 },
+ { -0.253135, 0.00187735, 0.0230286, 0.01264 },
+ { -0.0695069, -0.0437594, 0.0120636, 0.0163087 },
+ { -0.0328856, -0.00926032, -0.00173573, 0.00527385 }
+ }
+};
+
+/* coefficients for error estimation
+ while using cubic Bézier curves for approximation
+ 1/4 <= b/a <= 1 */
+static const double coeffs3High[2][4][4] = {
+ {
+ { 0.0899116, -19.2349, -4.11711, 0.183362 },
+ { 0.138148, -1.45804, 1.32044, 1.38474 },
+ { 0.230903, -0.450262, 0.219963, 0.414038 },
+ { 0.0590565, -0.101062, 0.0430592, 0.0204699 }
+ },
+ {
+ { 0.0164649, 9.89394, 0.0919496, 0.00760802 },
+ { 0.0191603, -0.0322058, 0.0134667, -0.0825018 },
+ { 0.0156192, -0.017535, 0.00326508, -0.228157 },
+ { -0.0236752, 0.0405821, -0.0173086, 0.176187 }
+ }
+};
+
+/* safety factor to convert the "best" error approximation
+ into a "max bound" error */
+static const double safety3[] = {
+ 0.001, 4.98, 0.207, 0.0067
+};
+
+/* The code below is from the OpenVG 1.1 Spec
+ * Section 18.4 */
+
+/* Given: Points (x0, y0) and (x1, y1)
+ * Return: TRUE if a solution exists, FALSE otherwise
+ * Circle centers are written to (cx0, cy0) and (cx1, cy1)
+ */
+static VGboolean
+find_unit_circles(double x0, double y0, double x1, double y1,
+ double *cx0, double *cy0,
+ double *cx1, double *cy1)
+{
+ /* Compute differences and averages */
+ double dx = x0 - x1;
+ double dy = y0 - y1;
+ double xm = (x0 + x1)/2;
+ double ym = (y0 + y1)/2;
+ double dsq, disc, s, sdx, sdy;
+
+ /* Solve for intersecting unit circles */
+ dsq = dx*dx + dy*dy;
+ if (dsq == 0.0) return VG_FALSE; /* Points are coincident */
+ disc = 1.0/dsq - 1.0/4.0;
+
+ /* the precision we care about here is around float so if we're
+ * around the float defined zero then make it official to avoid
+ * precision problems later on */
+ if (floatIsZero(disc))
+ disc = 0.0;
+
+ if (disc < 0.0) return VG_FALSE; /* Points are too far apart */
+ s = sqrt(disc);
+ sdx = s*dx;
+ sdy = s*dy;
+ *cx0 = xm + sdy;
+ *cy0 = ym - sdx;
+ *cx1 = xm - sdy;
+ *cy1 = ym + sdx;
+ return VG_TRUE;
+}
+
+
+/* Given: Ellipse parameters rh, rv, rot (in degrees),
+ * endpoints (x0, y0) and (x1, y1)
+ * Return: TRUE if a solution exists, FALSE otherwise
+ * Ellipse centers are written to (cx0, cy0) and (cx1, cy1)
+ */
+static VGboolean
+find_ellipses(double rh, double rv, double rot,
+ double x0, double y0, double x1, double y1,
+ double *cx0, double *cy0, double *cx1, double *cy1)
+{
+ double COS, SIN, x0p, y0p, x1p, y1p, pcx0, pcy0, pcx1, pcy1;
+ /* Convert rotation angle from degrees to radians */
+ rot *= M_PI/180.0;
+ /* Pre-compute rotation matrix entries */
+ COS = cos(rot); SIN = sin(rot);
+ /* Transform (x0, y0) and (x1, y1) into unit space */
+ /* using (inverse) rotate, followed by (inverse) scale */
+ x0p = (x0*COS + y0*SIN)/rh;
+ y0p = (-x0*SIN + y0*COS)/rv;
+ x1p = (x1*COS + y1*SIN)/rh;
+ y1p = (-x1*SIN + y1*COS)/rv;
+ if (!find_unit_circles(x0p, y0p, x1p, y1p,
+ &pcx0, &pcy0, &pcx1, &pcy1)) {
+ return VG_FALSE;
+ }
+ /* Transform back to original coordinate space */
+ /* using (forward) scale followed by (forward) rotate */
+ pcx0 *= rh; pcy0 *= rv;
+ pcx1 *= rh; pcy1 *= rv;
+ *cx0 = pcx0*COS - pcy0*SIN;
+ *cy0 = pcx0*SIN + pcy0*COS;
+ *cx1 = pcx1*COS - pcy1*SIN;
+ *cy1 = pcx1*SIN + pcy1*COS;
+ return VG_TRUE;
+}
+
+static INLINE VGboolean
+try_to_fix_radii(struct arc *arc)
+{
+ double COS, SIN, rot, x0p, y0p, x1p, y1p;
+ double dx, dy, dsq, scale;
+
+ /* Convert rotation angle from degrees to radians */
+ rot = DEGREES_TO_RADIANS(arc->theta);
+
+ /* Pre-compute rotation matrix entries */
+ COS = cos(rot); SIN = sin(rot);
+
+ /* Transform (x0, y0) and (x1, y1) into unit space */
+ /* using (inverse) rotate, followed by (inverse) scale */
+ x0p = (arc->x1*COS + arc->y1*SIN)/arc->a;
+ y0p = (-arc->x1*SIN + arc->y1*COS)/arc->b;
+ x1p = (arc->x2*COS + arc->y2*SIN)/arc->a;
+ y1p = (-arc->x2*SIN + arc->y2*COS)/arc->b;
+ /* Compute differences and averages */
+ dx = x0p - x1p;
+ dy = y0p - y1p;
+
+ dsq = dx*dx + dy*dy;
+#if 0
+ if (dsq <= 0.001) {
+ debug_printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaaa\n");
+ }
+#endif
+ scale = 1/(2/sqrt(dsq));
+ arc->a *= scale;
+ arc->b *= scale;
+ return VG_TRUE;
+}
+
+static INLINE double vector_normalize(double *v)
+{
+ double sq = v[0] * v[0] + v[1] * v[1];
+ return sqrt(sq);
+}
+static INLINE double vector_orientation(double *v)
+{
+ double norm = vector_normalize(v);
+ double cosa = v[0] / norm;
+ double sina = v[1] / norm;
+ return (sina>=0 ? acos(cosa) : 2*M_PI - acos(cosa));
+}
+static INLINE double vector_dot(double *v0,
+ double *v1)
+{
+ return v0[0] * v1[0] + v0[1] * v1[1];
+}
+
+static INLINE double vector_angles(double *v0,
+ double *v1)
+{
+ double dot = vector_dot(v0, v1);
+ double norm0 = vector_normalize(v0);
+ double norm1 = vector_normalize(v1);
+
+ return acos(dot / (norm0 * norm1));
+}
+
+static VGboolean find_angles(struct arc *arc)
+{
+ double vec0[2], vec1[2];
+ double lambda1, lambda2;
+ double angle;
+ struct matrix matrix;
+
+ if (floatIsZero(arc->a) || floatIsZero(arc->b)) {
+ return VG_FALSE;
+ }
+ /* map the points to an identity circle */
+ matrix_load_identity(&matrix);
+ matrix_scale(&matrix, 1.f, arc->a/arc->b);
+ matrix_rotate(&matrix, -arc->theta);
+ matrix_map_point(&matrix,
+ arc->x1, arc->y1,
+ &arc->x1, &arc->y1);
+ matrix_map_point(&matrix,
+ arc->x2, arc->y2,
+ &arc->x2, &arc->y2);
+ matrix_map_point(&matrix,
+ arc->cx, arc->cy,
+ &arc->cx, &arc->cy);
+
+#if DEBUG_ARCS
+ debug_printf("Matrix 3 [%f, %f, %f| %f, %f, %f| %f, %f, %f]\n",
+ matrix.m[0], matrix.m[1], matrix.m[2],
+ matrix.m[3], matrix.m[4], matrix.m[5],
+ matrix.m[6], matrix.m[7], matrix.m[8]);
+ debug_printf("Endpoints [%f, %f], [%f, %f]\n",
+ arc->x1, arc->y1, arc->x2, arc->y2);
+#endif
+
+ vec0[0] = arc->x1 - arc->cx;
+ vec0[1] = arc->y1 - arc->cy;
+ vec1[0] = arc->x2 - arc->cx;
+ vec1[1] = arc->y2 - arc->cy;
+
+#if DEBUG_ARCS
+ debug_printf("Vec is [%f, %f], [%f, %f], [%f, %f]\n",
+ vec0[0], vec0[1], vec1[0], vec1[1], arc->cx, arc->cy);
+#endif
+
+ lambda1 = vector_orientation(vec0);
+
+ if (isnan(lambda1))
+ lambda1 = 0.f;
+
+ if (arc->type == VG_SCWARC_TO ||
+ arc->type == VG_SCCWARC_TO)
+ angle = vector_angles(vec0, vec1);
+ else if (arc->type == VG_LCWARC_TO ||
+ arc->type == VG_LCCWARC_TO) {
+ angle = 2*M_PI - vector_angles(vec0, vec1);
+ } else
+ abort();
+
+ if (isnan(angle))
+ angle = M_PI;
+
+
+ if (arc->type == VG_SCWARC_TO ||
+ arc->type == VG_LCWARC_TO)
+ lambda2 = lambda1 - angle;
+ else
+ lambda2 = lambda1 + angle;
+
+#if DEBUG_ARCS
+ debug_printf("Angle is %f and (%f, %f)\n", angle, lambda1, lambda2);
+#endif
+
+#if 0
+ arc->eta1 = atan2(sin(lambda1) / arc->b,
+ cos(lambda1) / arc->a);
+ arc->eta2 = atan2(sin(lambda2) / arc->b,
+ cos(lambda2) / arc->a);
+
+ /* make sure we have eta1 <= eta2 <= eta1 + 2 PI */
+ arc->eta2 -= two_pi * floor((arc->eta2 - arc->eta1) / two_pi);
+
+ /* the preceding correction fails if we have exactly et2 - eta1 = 2 PI
+ it reduces the interval to zero length */
+ if ((lambda2 - lambda1 > M_PI) && (arc->eta2 - arc->eta1 < M_PI)) {
+ arc->eta2 += 2 * M_PI;
+ }
+#else
+ arc->eta1 = lambda1;
+ arc->eta2 = lambda2;
+#endif
+
+ return VG_TRUE;
+}
+
+#if DEBUG_ARCS
+static void check_endpoints(struct arc *arc)
+{
+ double x1, y1, x2, y2;
+
+ double a_cos_eta1 = arc->a * cos(arc->eta1);
+ double b_sin_eta1 = arc->b * sin(arc->eta1);
+ x1 = arc->cx + a_cos_eta1 * arc->cos_theta -
+ b_sin_eta1 * arc->sin_theta;
+ y1 = arc->cy + a_cos_eta1 * arc->sin_theta +
+ b_sin_eta1 * arc->cos_theta;
+
+ double a_cos_eta2 = arc->a * cos(arc->eta2);
+ double b_sin_eta2 = arc->b * sin(arc->eta2);
+ x2 = arc->cx + a_cos_eta2 * arc->cos_theta -
+ b_sin_eta2 * arc->sin_theta;
+ y2 = arc->cy + a_cos_eta2 * arc->sin_theta +
+ b_sin_eta2 * arc->cos_theta;
+
+ debug_printf("Computed (%f, %f), (%f, %f)\n",
+ x1, y1, x2, y2);
+ debug_printf("Real (%f, %f), (%f, %f)\n",
+ arc->x1, arc->y1,
+ arc->x2, arc->y2);
+}
+#endif
+
+void arc_init(struct arc *arc,
+ VGPathSegment type,
+ VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2,
+ VGfloat rh, VGfloat rv,
+ VGfloat rot)
+{
+ assert(type == VG_SCCWARC_TO ||
+ type == VG_SCWARC_TO ||
+ type == VG_LCCWARC_TO ||
+ type == VG_LCWARC_TO);
+ arc->type = type;
+ arc->x1 = x1;
+ arc->y1 = y1;
+ arc->x2 = x2;
+ arc->y2 = y2;
+ arc->a = rh;
+ arc->b = rv;
+ arc->theta = rot;
+ arc->cos_theta = cos(arc->theta);
+ arc->sin_theta = sin(arc->theta);
+ {
+ double cx0, cy0, cx1, cy1;
+ double cx, cy;
+ arc->is_valid = find_ellipses(rh, rv, rot, x1, y1, x2, y2,
+ &cx0, &cy0, &cx1, &cy1);
+
+ if (!arc->is_valid && try_to_fix_radii(arc)) {
+ rh = arc->a;
+ rv = arc->b;
+ arc->is_valid =
+ find_ellipses(rh, rv, rot, x1, y1, x2, y2,
+ &cx0, &cy0, &cx1, &cy1);
+ }
+
+ if (type == VG_SCWARC_TO ||
+ type == VG_LCCWARC_TO) {
+ cx = cx1;
+ cy = cy1;
+ } else {
+ cx = cx0;
+ cy = cy0;
+ }
+#if DEBUG_ARCS
+ debug_printf("Centers are : (%f, %f) , (%f, %f). Real (%f, %f)\n",
+ cx0, cy0, cx1, cy1, cx, cy);
+#endif
+ arc->cx = cx;
+ arc->cy = cy;
+ if (arc->is_valid) {
+ arc->is_valid = find_angles(arc);
+#if DEBUG_ARCS
+ check_endpoints(arc);
+#endif
+ /* remap a few points. find_angles requires
+ * rot in angles, the rest of the code
+ * will need them in radians. and find_angles
+ * modifies the center to match an identity
+ * circle so lets reset it */
+ arc->theta = DEGREES_TO_RADIANS(rot);
+ arc->cos_theta = cos(arc->theta);
+ arc->sin_theta = sin(arc->theta);
+ arc->cx = cx;
+ arc->cy = cy;
+ }
+ }
+}
+
+static INLINE double rational_function(double x, const double *c)
+{
+ return (x * (x * c[0] + c[1]) + c[2]) / (x + c[3]);
+}
+
+static double estimate_error(struct arc *arc,
+ double etaA, double etaB)
+{
+ double eta = 0.5 * (etaA + etaB);
+
+ double x = arc->b / arc->a;
+ double dEta = etaB - etaA;
+ double cos2 = cos(2 * eta);
+ double cos4 = cos(4 * eta);
+ double cos6 = cos(6 * eta);
+ double c0, c1;
+
+ /* select the right coeficients set according to degree and b/a */
+ const double (*coeffs)[4][4];
+ const double *safety;
+ coeffs = (x < 0.25) ? coeffs3Low : coeffs3High;
+ safety = safety3;
+
+ c0 = rational_function(x, coeffs[0][0])
+ + cos2 * rational_function(x, coeffs[0][1])
+ + cos4 * rational_function(x, coeffs[0][2])
+ + cos6 * rational_function(x, coeffs[0][3]);
+
+ c1 = rational_function(x, coeffs[1][0])
+ + cos2 * rational_function(x, coeffs[1][1])
+ + cos4 * rational_function(x, coeffs[1][2])
+ + cos6 * rational_function(x, coeffs[1][3]);
+
+ return rational_function(x, safety) * arc->a * exp(c0 + c1 * dEta);
+}
+
+struct arc_cb {
+ void (*move)(struct arc_cb *cb, VGfloat x, VGfloat y);
+ void (*point)(struct arc_cb *cb, VGfloat x, VGfloat y);
+ void (*bezier)(struct arc_cb *cb, struct bezier *bezier);
+
+ void *user_data;
+};
+
+static void cb_null_move(struct arc_cb *cb, VGfloat x, VGfloat y)
+{
+}
+
+static void polygon_point(struct arc_cb *cb, VGfloat x, VGfloat y)
+{
+ struct polygon *poly = (struct polygon*)cb->user_data;
+ polygon_vertex_append(poly, x, y);
+}
+
+static void polygon_bezier(struct arc_cb *cb, struct bezier *bezier)
+{
+ struct polygon *poly = (struct polygon*)cb->user_data;
+ bezier_add_to_polygon(bezier, poly);
+}
+
+static void stroke_point(struct arc_cb *cb, VGfloat x, VGfloat y)
+{
+ struct stroker *stroker = (struct stroker*)cb->user_data;
+ stroker_line_to(stroker, x, y);
+}
+
+static void stroke_curve(struct arc_cb *cb, struct bezier *bezier)
+{
+ struct stroker *stroker = (struct stroker*)cb->user_data;
+ stroker_curve_to(stroker,
+ bezier->x2, bezier->y2,
+ bezier->x3, bezier->y3,
+ bezier->x4, bezier->y4);
+}
+
+static void stroke_emit_point(struct arc_cb *cb, VGfloat x, VGfloat y)
+{
+ struct stroker *stroker = (struct stroker*)cb->user_data;
+ stroker_emit_line_to(stroker, x, y);
+}
+
+static void stroke_emit_curve(struct arc_cb *cb, struct bezier *bezier)
+{
+ struct stroker *stroker = (struct stroker*)cb->user_data;
+ stroker_emit_curve_to(stroker,
+ bezier->x2, bezier->y2,
+ bezier->x3, bezier->y3,
+ bezier->x4, bezier->y4);
+}
+
+static void arc_path_move(struct arc_cb *cb, VGfloat x, VGfloat y)
+{
+ struct path *path = (struct path*)cb->user_data;
+ path_move_to(path, x, y);
+}
+
+static void arc_path_point(struct arc_cb *cb, VGfloat x, VGfloat y)
+{
+ struct path *path = (struct path*)cb->user_data;
+ path_line_to(path, x, y);
+}
+
+static void arc_path_bezier(struct arc_cb *cb, struct bezier *bezier)
+{
+ struct path *path = (struct path*)cb->user_data;
+ path_cubic_to(path,
+ bezier->x2, bezier->y2,
+ bezier->x3, bezier->y3,
+ bezier->x4, bezier->y4);
+}
+
+static INLINE int num_beziers_needed(struct arc *arc)
+{
+ double threshold = 0.05;
+ VGboolean found = VG_FALSE;
+ int n = 1;
+ double min_eta, max_eta;
+
+ min_eta = MIN2(arc->eta1, arc->eta2);
+ max_eta = MAX2(arc->eta1, arc->eta2);
+
+ while ((! found) && (n < 1024)) {
+ double d_eta = (max_eta - min_eta) / n;
+ if (d_eta <= 0.5 * M_PI) {
+ double eta_b = min_eta;
+ found = VG_TRUE;
+ for (int i = 0; found && (i < n); ++i) {
+ double etaA = eta_b;
+ eta_b += d_eta;
+ found = (estimate_error(arc, etaA, eta_b) <= threshold);
+ }
+ }
+ n = n << 1;
+ }
+
+ return n;
+}
+
+static void arc_to_beziers(struct arc *arc,
+ struct arc_cb cb,
+ struct matrix *matrix)
+{
+ int n = 1;
+ double d_eta, eta_b, cos_eta_b,
+ sin_eta_b, a_cos_eta_b, b_sin_eta_b, a_sin_eta_b,
+ b_cos_eta_b, x_b, y_b, x_b_dot, y_b_dot, lx, ly;
+ double t, alpha;
+
+ { /* always move to the start of the arc */
+ VGfloat x = arc->x1;
+ VGfloat y = arc->y1;
+ matrix_map_point(matrix, x, y, &x, &y);
+ cb.move(&cb, x, y);
+ }
+
+ if (!arc->is_valid) {
+ VGfloat x = arc->x2;
+ VGfloat y = arc->y2;
+ matrix_map_point(matrix, x, y, &x, &y);
+ cb.point(&cb, x, y);
+ return;
+ }
+
+ /* find the number of Bézier curves needed */
+ n = num_beziers_needed(arc);
+
+ d_eta = (arc->eta2 - arc->eta1) / n;
+ eta_b = arc->eta1;
+
+ cos_eta_b = cos(eta_b);
+ sin_eta_b = sin(eta_b);
+ a_cos_eta_b = arc->a * cos_eta_b;
+ b_sin_eta_b = arc->b * sin_eta_b;
+ a_sin_eta_b = arc->a * sin_eta_b;
+ b_cos_eta_b = arc->b * cos_eta_b;
+ x_b = arc->cx + a_cos_eta_b * arc->cos_theta -
+ b_sin_eta_b * arc->sin_theta;
+ y_b = arc->cy + a_cos_eta_b * arc->sin_theta +
+ b_sin_eta_b * arc->cos_theta;
+ x_b_dot = -a_sin_eta_b * arc->cos_theta -
+ b_cos_eta_b * arc->sin_theta;
+ y_b_dot = -a_sin_eta_b * arc->sin_theta +
+ b_cos_eta_b * arc->cos_theta;
+
+ {
+ VGfloat x = x_b, y = y_b;
+ matrix_map_point(matrix, x, y, &x, &y);
+ cb.point(&cb, x, y);
+ }
+ lx = x_b;
+ ly = y_b;
+
+ t = tan(0.5 * d_eta);
+ alpha = sin(d_eta) * (sqrt(4 + 3 * t * t) - 1) / 3;
+
+ for (int i = 0; i < n; ++i) {
+ struct bezier bezier;
+ double xA = x_b;
+ double yA = y_b;
+ double xADot = x_b_dot;
+ double yADot = y_b_dot;
+
+ eta_b += d_eta;
+ cos_eta_b = cos(eta_b);
+ sin_eta_b = sin(eta_b);
+ a_cos_eta_b = arc->a * cos_eta_b;
+ b_sin_eta_b = arc->b * sin_eta_b;
+ a_sin_eta_b = arc->a * sin_eta_b;
+ b_cos_eta_b = arc->b * cos_eta_b;
+ x_b = arc->cx + a_cos_eta_b * arc->cos_theta -
+ b_sin_eta_b * arc->sin_theta;
+ y_b = arc->cy + a_cos_eta_b * arc->sin_theta +
+ b_sin_eta_b * arc->cos_theta;
+ x_b_dot = -a_sin_eta_b * arc->cos_theta -
+ b_cos_eta_b * arc->sin_theta;
+ y_b_dot = -a_sin_eta_b * arc->sin_theta +
+ b_cos_eta_b * arc->cos_theta;
+
+ bezier_init(&bezier,
+ lx, ly,
+ (float) (xA + alpha * xADot), (float) (yA + alpha * yADot),
+ (float) (x_b - alpha * x_b_dot), (float) (y_b - alpha * y_b_dot),
+ (float) x_b, (float) y_b);
+#if 0
+ debug_printf("%d) Bezier (%f, %f), (%f, %f), (%f, %f), (%f, %f)\n",
+ i,
+ bezier.x1, bezier.y1,
+ bezier.x2, bezier.y2,
+ bezier.x3, bezier.y3,
+ bezier.x4, bezier.y4);
+#endif
+ bezier_transform(&bezier, matrix);
+ cb.bezier(&cb, &bezier);
+ lx = x_b;
+ ly = y_b;
+ }
+}
+
+
+void arc_add_to_polygon(struct arc *arc,
+ struct polygon *poly,
+ struct matrix *matrix)
+{
+ struct arc_cb cb;
+
+ cb.move = cb_null_move;
+ cb.point = polygon_point;
+ cb.bezier = polygon_bezier;
+ cb.user_data = poly;
+
+ arc_to_beziers(arc, cb, matrix);
+}
+
+void arc_stroke_cb(struct arc *arc,
+ struct stroker *stroke,
+ struct matrix *matrix)
+{
+ struct arc_cb cb;
+
+ cb.move = cb_null_move;
+ cb.point = stroke_point;
+ cb.bezier = stroke_curve;
+ cb.user_data = stroke;
+
+ arc_to_beziers(arc, cb, matrix);
+}
+
+void arc_stroker_emit(struct arc *arc,
+ struct stroker *stroker,
+ struct matrix *matrix)
+{
+ struct arc_cb cb;
+
+ cb.move = cb_null_move;
+ cb.point = stroke_emit_point;
+ cb.bezier = stroke_emit_curve;
+ cb.user_data = stroker;
+
+ arc_to_beziers(arc, cb, matrix);
+}
+
+void arc_to_path(struct arc *arc,
+ struct path *path,
+ struct matrix *matrix)
+{
+ struct arc_cb cb;
+
+ cb.move = arc_path_move;
+ cb.point = arc_path_point;
+ cb.bezier = arc_path_bezier;
+ cb.user_data = path;
+
+ arc_to_beziers(arc, cb, matrix);
+}
diff --git a/src/gallium/state_trackers/vega/arc.h b/src/gallium/state_trackers/vega/arc.h
new file mode 100644
index 0000000000..3205cd5021
--- /dev/null
+++ b/src/gallium/state_trackers/vega/arc.h
@@ -0,0 +1,80 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ARC_H
+#define ARC_H
+
+#include "VG/openvg.h"
+
+struct polygon;
+struct matrix;
+struct stroker;
+struct path;
+
+struct arc {
+ VGPathSegment type;
+
+ VGfloat cx, cy;
+
+ VGfloat a, b;
+
+ VGfloat theta;
+ VGfloat cos_theta, sin_theta;
+
+ VGfloat eta1;
+ VGfloat eta2;
+
+ VGfloat x1, y1, x2, y2;
+
+ VGboolean is_valid;
+};
+
+void arc_init(struct arc *arc,
+ VGPathSegment type,
+ VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2,
+ VGfloat rh, VGfloat rv,
+ VGfloat rot);
+
+void arc_add_to_polygon(struct arc *arc,
+ struct polygon *poly,
+ struct matrix *matrix);
+
+
+void arc_to_path(struct arc *arc,
+ struct path *p,
+ struct matrix *matrix);
+
+void arc_stroke_cb(struct arc *arc,
+ struct stroker *stroke,
+ struct matrix *matrix);
+
+void arc_stroker_emit(struct arc *arc,
+ struct stroker *stroke,
+ struct matrix *matrix);
+
+
+#endif
diff --git a/src/gallium/state_trackers/vega/asm_fill.h b/src/gallium/state_trackers/vega/asm_fill.h
new file mode 100644
index 0000000000..2f394ad6c5
--- /dev/null
+++ b/src/gallium/state_trackers/vega/asm_fill.h
@@ -0,0 +1,246 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ASM_FILL_H
+#define ASM_FILL_H
+
+static const char solid_fill_asm[] =
+ "MOV %s, CONST[0]\n";
+
+
+static const char linear_grad_asm[] =
+ "MOV TEMP[0].xy, IN[0]\n"
+ "MOV TEMP[0].z, CONST[1].yyyy\n"
+ "DP3 TEMP[1], CONST[2], TEMP[0]\n"
+ "DP3 TEMP[2], CONST[3], TEMP[0]\n"
+ "DP3 TEMP[3], CONST[4], TEMP[0]\n"
+ "RCP TEMP[3], TEMP[3]\n"
+ "MUL TEMP[1], TEMP[1], TEMP[3]\n"
+ "MUL TEMP[2], TEMP[2], TEMP[3]\n"
+ "MOV TEMP[4].x, TEMP[1]\n"
+ "MOV TEMP[4].y, TEMP[2]\n"
+ "MUL TEMP[0], CONST[0].yyyy, TEMP[4].yyyy\n"
+ "MAD TEMP[1], CONST[0].xxxx, TEMP[4].xxxx, TEMP[0]\n"
+ "MUL TEMP[2], TEMP[1], CONST[0].zzzz\n"
+ "TEX %s, TEMP[2], SAMP[0], 1D\n";
+
+static const char radial_grad_asm[] =
+ "MOV TEMP[0].xy, IN[0]\n"
+ "MOV TEMP[0].z, CONST[1].yyyy\n"
+ "DP3 TEMP[1], CONST[2], TEMP[0]\n"
+ "DP3 TEMP[2], CONST[3], TEMP[0]\n"
+ "DP3 TEMP[3], CONST[4], TEMP[0]\n"
+ "RCP TEMP[3], TEMP[3]\n"
+ "MUL TEMP[1], TEMP[1], TEMP[3]\n"
+ "MUL TEMP[2], TEMP[2], TEMP[3]\n"
+ "MOV TEMP[5].x, TEMP[1]\n"
+ "MOV TEMP[5].y, TEMP[2]\n"
+ "MUL TEMP[0], CONST[0].yyyy, TEMP[5].yyyy\n"
+ "MAD TEMP[1], CONST[0].xxxx, TEMP[5].xxxx, TEMP[0]\n"
+ "ADD TEMP[1], TEMP[1], TEMP[1]\n"
+ "MUL TEMP[3], TEMP[5].yyyy, TEMP[5].yyyy\n"
+ "MAD TEMP[4], TEMP[5].xxxx, TEMP[5].xxxx, TEMP[3]\n"
+ "MOV TEMP[4], -TEMP[4]\n"
+ "MUL TEMP[2], CONST[0].zzzz, TEMP[4]\n"
+ "MUL TEMP[0], CONST[1].wwww, TEMP[2]\n"
+ "MUL TEMP[3], TEMP[1], TEMP[1]\n"
+ "SUB TEMP[2], TEMP[3], TEMP[0]\n"
+ "RSQ TEMP[2], |TEMP[2]|\n"
+ "RCP TEMP[2], TEMP[2]\n"
+ "SUB TEMP[1], TEMP[2], TEMP[1]\n"
+ "ADD TEMP[0], CONST[0].zzzz, CONST[0].zzzz\n"
+ "RCP TEMP[0], TEMP[0]\n"
+ "MUL TEMP[2], TEMP[1], TEMP[0]\n"
+ "TEX %s, TEMP[2], SAMP[0], 1D\n";
+
+static const char pattern_asm[] =
+ "MOV TEMP[0].xy, IN[0]\n"
+ "MOV TEMP[0].z, CONST[1].yyyy\n"
+ "DP3 TEMP[1], CONST[2], TEMP[0]\n"
+ "DP3 TEMP[2], CONST[3], TEMP[0]\n"
+ "DP3 TEMP[3], CONST[4], TEMP[0]\n"
+ "RCP TEMP[3], TEMP[3]\n"
+ "MUL TEMP[1], TEMP[1], TEMP[3]\n"
+ "MUL TEMP[2], TEMP[2], TEMP[3]\n"
+ "MOV TEMP[4].x, TEMP[1]\n"
+ "MOV TEMP[4].y, TEMP[2]\n"
+ "RCP TEMP[0], CONST[1].zwzw\n"
+ "MOV TEMP[1], TEMP[4]\n"
+ "MUL TEMP[1].x, TEMP[1], TEMP[0]\n"
+ "MUL TEMP[1].y, TEMP[1], TEMP[0]\n"
+ "TEX %s, TEMP[1], SAMP[0], 2D\n";
+
+
+static const char mask_asm[] =
+ "TEX TEMP[1], IN[0], SAMP[1], 2D\n"
+ "MUL TEMP[0].w, TEMP[0].wwww, TEMP[1].wwww\n"
+ "MOV %s, TEMP[0]\n";
+
+
+static const char image_normal_asm[] =
+ "TEX %s, IN[1], SAMP[3], 2D\n";
+
+static const char image_multiply_asm[] =
+ "TEX TEMP[1], IN[1], SAMP[3], 2D\n"
+ "MUL %s, TEMP[0], TEMP[1]\n";
+
+static const char image_stencil_asm[] =
+ "TEX TEMP[1], IN[1], SAMP[3], 2D\n"
+ "MUL %s, TEMP[0], TEMP[1]\n";
+
+
+#define EXTENDED_BLEND_OVER \
+ "SUB TEMP[3], CONST[1].yyyy, TEMP[1].wwww\n" \
+ "SUB TEMP[4], CONST[1].yyyy, TEMP[0].wwww\n" \
+ "MUL TEMP[3], TEMP[0], TEMP[3]\n" \
+ "MUL TEMP[4], TEMP[1], TEMP[4]\n" \
+ "ADD TEMP[3], TEMP[3], TEMP[4]\n"
+
+static const char blend_multiply_asm[] =
+ "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
+ EXTENDED_BLEND_OVER
+ "MUL TEMP[4], TEMP[0], TEMP[1]\n"
+ "ADD TEMP[1], TEMP[4], TEMP[3]\n"/*result.rgb*/
+ "MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n"
+ "ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n"
+ "SUB TEMP[1].w, TEMP[3], TEMP[2]\n"
+ "MOV %s, TEMP[1]\n";
+#if 1
+static const char blend_screen_asm[] =
+ "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
+ "ADD TEMP[3], TEMP[0], TEMP[1]\n"
+ "MUL TEMP[2], TEMP[0], TEMP[1]\n"
+ "SUB %s, TEMP[3], TEMP[2]\n";
+#else
+static const char blend_screen_asm[] =
+ "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
+ "MOV %s, TEMP[1]\n";
+#endif
+
+static const char blend_darken_asm[] =
+ "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
+ EXTENDED_BLEND_OVER
+ "MUL TEMP[4], TEMP[0], TEMP[1].wwww\n"
+ "MUL TEMP[5], TEMP[1], TEMP[0].wwww\n"
+ "MIN TEMP[4], TEMP[4], TEMP[5]\n"
+ "ADD TEMP[1], TEMP[3], TEMP[4]\n"
+ "MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n"
+ "ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n"
+ "SUB TEMP[1].w, TEMP[3], TEMP[2]\n"
+ "MOV %s, TEMP[1]\n";
+
+static const char blend_lighten_asm[] =
+ "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
+ EXTENDED_BLEND_OVER
+ "MUL TEMP[4], TEMP[0], TEMP[1].wwww\n"
+ "MUL TEMP[5], TEMP[1], TEMP[0].wwww\n"
+ "MAX TEMP[4], TEMP[4], TEMP[5]\n"
+ "ADD TEMP[1], TEMP[3], TEMP[4]\n"
+ "MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n"
+ "ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n"
+ "SUB TEMP[1].w, TEMP[3], TEMP[2]\n"
+ "MOV %s, TEMP[1]\n";
+
+
+static const char premultiply_asm[] =
+ "MUL TEMP[0].xyz, TEMP[0], TEMP[0].wwww\n";
+
+static const char unpremultiply_asm[] =
+ "TEX TEMP[0], IN[0], SAMP[1], 2D\n";
+
+
+static const char color_bw_asm[] =
+ "ADD TEMP[1], CONST[1].yyyy, CONST[1].yyyy\n"
+ "RCP TEMP[2], TEMP[1]\n"
+ "ADD TEMP[1], CONST[1].yyyy, TEMP[2]\n"
+ "ADD TEMP[2].x, TEMP[0].xxxx, TEMP[0].yyyy\n"
+ "ADD TEMP[2].x, TEMP[0].zzzz, TEMP[0].xxxx\n"
+ "SGE TEMP[0].xyz, TEMP[2].xxxx, TEMP[1]\n"
+ "SGE TEMP[0].w, TEMP[0].wwww, TEMP[2].yyyy\n"
+ "MOV %s, TEMP[0]\n";
+
+
+struct shader_asm_info {
+ VGint id;
+ VGint num_tokens;
+ const char * txt;
+
+ VGboolean needs_position;
+
+ VGint start_const;
+ VGint num_consts;
+
+ VGint start_sampler;
+ VGint num_samplers;
+
+ VGint start_temp;
+ VGint num_temps;
+};
+
+
+static const struct shader_asm_info shaders_asm[] = {
+ /* fills */
+ {VEGA_SOLID_FILL_SHADER, 40, solid_fill_asm,
+ VG_FALSE, 0, 1, 0, 0, 0, 0},
+ {VEGA_LINEAR_GRADIENT_SHADER, 200, linear_grad_asm,
+ VG_TRUE, 0, 5, 0, 1, 0, 5},
+ {VEGA_RADIAL_GRADIENT_SHADER, 200, radial_grad_asm,
+ VG_TRUE, 0, 5, 0, 1, 0, 6},
+ {VEGA_PATTERN_SHADER, 100, pattern_asm,
+ VG_TRUE, 1, 4, 0, 1, 0, 5},
+
+ /* image draw modes */
+ {VEGA_IMAGE_NORMAL_SHADER, 200, image_normal_asm,
+ VG_TRUE, 0, 0, 3, 1, 0, 0},
+ {VEGA_IMAGE_MULTIPLY_SHADER, 200, image_multiply_asm,
+ VG_TRUE, 0, 0, 3, 1, 0, 2},
+ {VEGA_IMAGE_STENCIL_SHADER, 200, image_stencil_asm,
+ VG_TRUE, 0, 0, 3, 1, 0, 2},
+
+ {VEGA_MASK_SHADER, 100, mask_asm,
+ VG_TRUE, 0, 0, 1, 1, 0, 2},
+
+ /* extra blend modes */
+ {VEGA_BLEND_MULTIPLY_SHADER, 200, blend_multiply_asm,
+ VG_TRUE, 1, 1, 2, 1, 0, 5},
+ {VEGA_BLEND_SCREEN_SHADER, 200, blend_screen_asm,
+ VG_TRUE, 0, 0, 2, 1, 0, 4},
+ {VEGA_BLEND_DARKEN_SHADER, 200, blend_darken_asm,
+ VG_TRUE, 1, 1, 2, 1, 0, 6},
+ {VEGA_BLEND_LIGHTEN_SHADER, 200, blend_lighten_asm,
+ VG_TRUE, 1, 1, 2, 1, 0, 6},
+
+ /* premultiply */
+ {VEGA_PREMULTIPLY_SHADER, 100, premultiply_asm,
+ VG_FALSE, 0, 0, 0, 0, 0, 1},
+ {VEGA_UNPREMULTIPLY_SHADER, 100, unpremultiply_asm,
+ VG_FALSE, 0, 0, 0, 0, 0, 1},
+
+ /* color transform to black and white */
+ {VEGA_BW_SHADER, 150, color_bw_asm,
+ VG_FALSE, 1, 1, 0, 0, 0, 3},
+};
+#endif
diff --git a/src/gallium/state_trackers/vega/asm_filters.h b/src/gallium/state_trackers/vega/asm_filters.h
new file mode 100644
index 0000000000..9a49f2e12d
--- /dev/null
+++ b/src/gallium/state_trackers/vega/asm_filters.h
@@ -0,0 +1,117 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ASM_FILTERS_H
+#define ASM_FILTERS_H
+
+static const char color_matrix_asm[] =
+ "FRAG1.1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR, CONSTANT\n"
+ "DCL CONST[0..4], CONSTANT\n"
+ "DCL TEMP[0..4], CONSTANT\n"
+ "DCL SAMP[0], CONSTANT\n"
+ "TEX TEMP[0], IN[0], SAMP[0], 2D\n"
+ "MOV TEMP[1], TEMP[0].xxxx\n"
+ "MOV TEMP[2], TEMP[0].yyyy\n"
+ "MOV TEMP[3], TEMP[0].zzzz\n"
+ "MOV TEMP[4], TEMP[0].wwww\n"
+ "MUL TEMP[1], TEMP[1], CONST[0]\n"
+ "MUL TEMP[2], TEMP[2], CONST[1]\n"
+ "MUL TEMP[3], TEMP[3], CONST[2]\n"
+ "MUL TEMP[4], TEMP[4], CONST[3]\n"
+ "ADD TEMP[0], TEMP[1], CONST[4]\n"
+ "ADD TEMP[0], TEMP[0], TEMP[2]\n"
+ "ADD TEMP[0], TEMP[0], TEMP[3]\n"
+ "ADD TEMP[0], TEMP[0], TEMP[4]\n"
+ "MOV OUT[0], TEMP[0]\n"
+ "END\n";
+
+static const char convolution_asm[] =
+ "FRAG1.1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR, CONSTANT\n"
+ "DCL TEMP[0..4], CONSTANT\n"
+ "DCL ADDR[0], CONSTANT\n"
+ "DCL CONST[0..%d], CONSTANT\n"
+ "DCL SAMP[0], CONSTANT\n"
+ "0: MOV TEMP[0], CONST[0].xxxx\n"
+ "1: MOV TEMP[1], CONST[0].xxxx\n"
+ "2: BGNLOOP :14\n"
+ "3: SGE TEMP[0].z, TEMP[0].yyyy, CONST[1].xxxx\n"
+ "4: IF TEMP[0].zzzz :7\n"
+ "5: BRK\n"
+ "6: ENDIF\n"
+ "7: ARL ADDR[0].x, TEMP[0].yyyy\n"
+ "8: MOV TEMP[3], CONST[ADDR[0]+2]\n"
+ "9: ADD TEMP[4].xy, IN[0], TEMP[3]\n"
+ "10: TEX TEMP[2], TEMP[4], SAMP[0], 2D\n"
+ "11: MOV TEMP[3], CONST[ADDR[0]+%d]\n"
+ "12: MAD TEMP[1], TEMP[2], TEMP[3], TEMP[1]\n"
+ "13: ADD TEMP[0].y, TEMP[0].yyyy, CONST[0].yyyy\n"
+ "14: ENDLOOP :2\n"
+ "15: MAD OUT[0], TEMP[1], CONST[1].yyyy, CONST[1].zzzz\n"
+ "16: END\n";
+
+
+static const char lookup_asm[] =
+ "FRAG1.1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR, CONSTANT\n"
+ "DCL TEMP[0..2], CONSTANT\n"
+ "DCL CONST[0], CONSTANT\n"
+ "DCL SAMP[0..1], CONSTANT\n"
+ "TEX TEMP[0], IN[0], SAMP[0], 2D\n"
+ "MOV TEMP[1], TEMP[0]\n"
+ /* do red */
+ "TEX TEMP[2], TEMP[1].xxxx, SAMP[1], 1D\n"
+ "MOV TEMP[0].x, TEMP[2].xxxx\n"
+ /* do blue */
+ "TEX TEMP[2], TEMP[1].yyyy, SAMP[1], 1D\n"
+ "MOV TEMP[0].y, TEMP[2].yyyy\n"
+ /* do green */
+ "TEX TEMP[2], TEMP[1].zzzz, SAMP[1], 1D\n"
+ "MOV TEMP[0].z, TEMP[2].zzzz\n"
+ /* do alpha */
+ "TEX TEMP[2], TEMP[1].wwww, SAMP[1], 1D\n"
+ "MOV TEMP[0].w, TEMP[2].wwww\n"
+ "MOV OUT[0], TEMP[0]\n"
+ "END\n";
+
+
+static const char lookup_single_asm[] =
+ "FRAG1.1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR, CONSTANT\n"
+ "DCL TEMP[0..2], CONSTANT\n"
+ "DCL CONST[0], CONSTANT\n"
+ "DCL SAMP[0..1], CONSTANT\n"
+ "TEX TEMP[0], IN[0], SAMP[0], 2D\n"
+ "TEX TEMP[1], TEMP[0].%s, SAMP[1], 1D\n"
+ "MOV OUT[0], TEMP[1]\n"
+ "END\n";
+
+#endif
diff --git a/src/gallium/state_trackers/vega/asm_util.h b/src/gallium/state_trackers/vega/asm_util.h
new file mode 100644
index 0000000000..218e1d166d
--- /dev/null
+++ b/src/gallium/state_trackers/vega/asm_util.h
@@ -0,0 +1,136 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ASM_UTIL_H
+#define ASM_UTIL_H
+
+
+static const char pass_through_depth_asm[] =
+ "FRAG1.1\n"
+ "DCL IN[0], POSITION, LINEAR\n"
+ "DCL OUT[0].z, POSITION, CONSTANT\n"
+ "0: MOV OUT[0].z, IN[0].zzzz\n"
+ "1: END\n";
+
+
+
+/* μnew = μmask */
+static const char set_mask_asm[] =
+ "FRAG1.1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL SAMP[0], CONSTANT\n"
+ "DCL OUT[0], COLOR, CONSTANT\n"
+ "0: TEX OUT[0], IN[0], SAMP[0], 2D\n"/*umask*/
+ "1: END\n";
+
+/* μnew = 1 – (1 – μmask)*(1 – μprev) */
+static const char union_mask_asm[] =
+ "FRAG1.1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL IN[1], POSITION, LINEAR\n"
+ "DCL CONST[0], CONSTANT\n"
+ "DCL SAMP[0..1], CONSTANT\n"
+ "DCL TEMP[0..3], CONSTANT\n"
+ "DCL OUT[0], COLOR, CONSTANT\n"
+ "0: TEX TEMP[1], IN[0], SAMP[0], 2D\n"/*umask*/
+ "1: TEX TEMP[0], IN[1], SAMP[1], 2D\n"/*uprev*/
+ "2: SUB TEMP[2], CONST[0], TEMP[0]\n"
+ "3: SUB TEMP[3], CONST[0], TEMP[1]\n"
+ "4: MUL TEMP[0].w, TEMP[2].wwww, TEMP[3].wwww\n"
+ "5: SUB OUT[0], CONST[0], TEMP[0]\n"
+ "6: END\n";
+
+/* μnew = μmask *μprev */
+static const char intersect_mask_asm[] =
+ "FRAG1.1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL IN[1], POSITION, LINEAR\n"
+ "DCL CONST[0], CONSTANT\n"
+ "DCL SAMP[0..1], CONSTANT\n"
+ "DCL TEMP[0..1], CONSTANT\n"
+ "DCL OUT[0], COLOR, CONSTANT\n"
+ "0: TEX TEMP[0], IN[1], SAMP[1], 2D\n"/*uprev*/
+ "1: TEX TEMP[1], IN[0], SAMP[0], 2D\n"/*umask*/
+ "2: MUL OUT[0], TEMP[0].wwww, TEMP[1].wwww\n"
+ "3: END\n";
+
+/* μnew = μprev*(1 – μmask) */
+static const char subtract_mask_asm[] =
+ "FRAG1.1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL IN[1], POSITION, LINEAR\n"
+ "DCL CONST[0], CONSTANT\n"
+ "DCL SAMP[0..1], CONSTANT\n"
+ "DCL TEMP[0..2], CONSTANT\n"
+ "DCL OUT[0], COLOR, CONSTANT\n"
+ "0: TEX TEMP[1], IN[0], SAMP[0], 2D\n"/*umask*/
+ "1: TEX TEMP[0], IN[1], SAMP[1], 2D\n"/*uprev*/
+ "2: SUB TEMP[2], CONST[0], TEMP[1]\n"
+ "3: MUL OUT[0], TEMP[2].wwww, TEMP[0].wwww\n"
+ "4: END\n";
+
+
+static const char vs_plain_asm[] =
+ "VERT1.1\n"
+ "DCL IN[0]\n"
+ "DCL OUT[0], POSITION\n"
+ "DCL TEMP[0]\n"
+ "DCL CONST[0..1]\n"
+ "0: MUL TEMP[0], IN[0], CONST[0]\n"
+ "1: ADD TEMP[0], TEMP[0], CONST[1]\n"
+ "2: MOV OUT[0], TEMP[0]\n"
+ "3: END\n";
+
+static const char vs_clear_asm[] =
+ "VERT1.1\n"
+ "DCL IN[0]\n"
+ "DCL IN[1]\n"
+ "DCL OUT[0], POSITION\n"
+ "DCL OUT[1], COLOR\n"
+ "DCL TEMP[0]\n"
+ "DCL CONST[0..1]\n"
+ "0: MUL TEMP[0], IN[0], CONST[0]\n"
+ "1: ADD TEMP[0], TEMP[0], CONST[1]\n"
+ "2: MOV OUT[0], TEMP[0]\n"
+ "3: MOV OUT[1], IN[1]\n"
+ "4: END\n";
+
+
+static const char vs_texture_asm[] =
+ "VERT1.1\n"
+ "DCL IN[0]\n"
+ "DCL IN[1]\n"
+ "DCL OUT[0], POSITION\n"
+ "DCL OUT[1], GENERIC\n"
+ "DCL TEMP[0]\n"
+ "DCL CONST[0..1]\n"
+ "0: MUL TEMP[0], IN[0], CONST[0]\n"
+ "1: ADD TEMP[0], TEMP[0], CONST[1]\n"
+ "2: MOV OUT[0], TEMP[0]\n"
+ "3: MOV OUT[1], IN[1]\n"
+ "4: END\n";
+
+#endif
diff --git a/src/gallium/state_trackers/vega/bezier.c b/src/gallium/state_trackers/vega/bezier.c
new file mode 100644
index 0000000000..39a7ade016
--- /dev/null
+++ b/src/gallium/state_trackers/vega/bezier.c
@@ -0,0 +1,704 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "bezier.h"
+
+#include "matrix.h"
+#include "polygon.h"
+
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <math.h>
+
+static const float flatness = 0.5;
+
+
+static INLINE void split_left(struct bezier *bez, VGfloat t, struct bezier* left)
+{
+ left->x1 = bez->x1;
+ left->y1 = bez->y1;
+
+ left->x2 = bez->x1 + t * (bez->x2 - bez->x1);
+ left->y2 = bez->y1 + t * (bez->y2 - bez->y1);
+
+ left->x3 = bez->x2 + t * (bez->x3 - bez->x2);
+ left->y3 = bez->y2 + t * (bez->y3 - bez->y2);
+
+ bez->x3 = bez->x3 + t * (bez->x4 - bez->x3);
+ bez->y3 = bez->y3 + t * (bez->y4 - bez->y3);
+
+ bez->x2 = left->x3 + t * (bez->x3 - left->x3);
+ bez->y2 = left->y3 + t * (bez->y3 - left->y3);
+
+ left->x3 = left->x2 + t * (left->x3 - left->x2);
+ left->y3 = left->y2 + t * (left->y3 - left->y2);
+
+ left->x4 = bez->x1 = left->x3 + t * (bez->x2 - left->x3);
+ left->y4 = bez->y1 = left->y3 + t * (bez->y2 - left->y3);
+}
+
+static INLINE void split(struct bezier *bez,
+ struct bezier *first_half,
+ struct bezier *second_half)
+{
+ double c = (bez->x2 + bez->x3) * 0.5;
+ first_half->x2 = (bez->x1 + bez->x2) * 0.5;
+ second_half->x3 = (bez->x3 + bez->x4) * 0.5;
+ first_half->x1 = bez->x1;
+ second_half->x4 = bez->x4;
+ first_half->x3 = (first_half->x2 + c) * 0.5;
+ second_half->x2 = (second_half->x3 + c) * 0.5;
+ first_half->x4 = second_half->x1 =
+ (first_half->x3 + second_half->x2) * 0.5;
+
+ c = (bez->y2 + bez->y3) / 2;
+ first_half->y2 = (bez->y1 + bez->y2) * 0.5;
+ second_half->y3 = (bez->y3 + bez->y4) * 0.5;
+ first_half->y1 = bez->y1;
+ second_half->y4 = bez->y4;
+ first_half->y3 = (first_half->y2 + c) * 0.5;
+ second_half->y2 = (second_half->y3 + c) * 0.5;
+ first_half->y4 = second_half->y1 =
+ (first_half->y3 + second_half->y2) * 0.5;
+}
+
+struct polygon * bezier_to_polygon(struct bezier *bez)
+{
+ struct polygon *poly = polygon_create(64);
+ polygon_vertex_append(poly, bez->x1, bez->y1);
+ bezier_add_to_polygon(bez, poly);
+ return poly;
+}
+
+void bezier_add_to_polygon(const struct bezier *bez,
+ struct polygon *poly)
+{
+ struct bezier beziers[32];
+ struct bezier *b;
+
+ beziers[0] = *bez;
+ b = beziers;
+
+ while (b >= beziers) {
+ double y4y1 = b->y4 - b->y1;
+ double x4x1 = b->x4 - b->x1;
+ double l = ABS(x4x1) + ABS(y4y1);
+ double d;
+ if (l > 1.f) {
+ d = ABS((x4x1)*(b->y1 - b->y2) - (y4y1)*(b->x1 - b->x2))
+ + ABS((x4x1)*(b->y1 - b->y3) - (y4y1)*(b->x1 - b->x3));
+ } else {
+ d = ABS(b->x1 - b->x2) + ABS(b->y1 - b->y2) +
+ ABS(b->x1 - b->x3) + ABS(b->y1 - b->y3);
+ l = 1.;
+ }
+ if (d < flatness*l || b == beziers + 31) {
+ /* good enough, we pop it off and add the endpoint */
+ polygon_vertex_append(poly, b->x4, b->y4);
+ --b;
+ } else {
+ /* split, second half of the bezier goes lower into the stack */
+ split(b, b+1, b);
+ ++b;
+ }
+ }
+}
+
+static void add_if_close(struct bezier *bez, VGfloat *length, VGfloat error)
+{
+ struct bezier left, right; /* bez poly splits */
+ VGfloat len = 0.0; /* arc length */
+ VGfloat chord; /* chord length */
+
+ len = len + line_length(bez->x1, bez->y1, bez->x2, bez->y2);
+ len = len + line_length(bez->x2, bez->y2, bez->x3, bez->y3);
+ len = len + line_length(bez->x3, bez->y3, bez->x4, bez->y4);
+
+ chord = line_length(bez->x1, bez->y1, bez->x4, bez->y4);
+
+ if ((len-chord) > error) {
+ split(bez, &left, &right); /* split in two */
+ add_if_close(&left, length, error); /* try left side */
+ add_if_close(&right, length, error); /* try right side */
+ return;
+ }
+
+ *length = *length + len;
+
+ return;
+}
+
+float bezier_length(struct bezier *bez, float error)
+{
+ VGfloat length = 0.f;
+
+ add_if_close(bez, &length, error);
+ return length;
+}
+
+void bezier_init(struct bezier *bez,
+ float x1, float y1,
+ float x2, float y2,
+ float x3, float y3,
+ float x4, float y4)
+{
+ bez->x1 = x1;
+ bez->y1 = y1;
+ bez->x2 = x2;
+ bez->y2 = y2;
+ bez->x3 = x3;
+ bez->y3 = y3;
+ bez->x4 = x4;
+ bez->y4 = y4;
+#if 0
+ debug_printf("bezier in [%f, %f, %f, %f, %f, %f]\n",
+ x1, y1, x2, y2, x3, y3, x4, y4);
+#endif
+}
+
+
+static INLINE void bezier_init2v(struct bezier *bez,
+ float *pt1,
+ float *pt2,
+ float *pt3,
+ float *pt4)
+{
+ bez->x1 = pt1[0];
+ bez->y1 = pt1[1];
+
+ bez->x2 = pt2[0];
+ bez->y2 = pt2[1];
+
+ bez->x3 = pt3[0];
+ bez->y3 = pt3[1];
+
+ bez->x4 = pt4[0];
+ bez->y4 = pt4[1];
+}
+
+
+void bezier_transform(struct bezier *bez,
+ struct matrix *matrix)
+{
+ assert(matrix_is_affine(matrix));
+ matrix_map_point(matrix, bez->x1, bez->y1, &bez->x1, &bez->y1);
+ matrix_map_point(matrix, bez->x2, bez->y2, &bez->x2, &bez->y2);
+ matrix_map_point(matrix, bez->x3, bez->y3, &bez->x3, &bez->y3);
+ matrix_map_point(matrix, bez->x4, bez->y4, &bez->x4, &bez->y4);
+}
+
+static INLINE void bezier_point_at(const struct bezier *bez, float t, float *pt)
+{
+ float a, b, c, d;
+ float m_t;
+ m_t = 1. - t;
+ b = m_t * m_t;
+ c = t * t;
+ d = c * t;
+ a = b * m_t;
+ b *= 3. * t;
+ c *= 3. * m_t;
+ pt[0] = a*bez->x1 + b*bez->x2 + c*bez->x3 + d*bez->x4;
+ pt[1] = a*bez->y1 + b*bez->y2 + c*bez->y3 + d*bez->y4;
+}
+
+static INLINE void bezier_normal_at(const struct bezier *bez, float t, float *norm)
+{
+ float m_t = 1. - t;
+ float a = m_t * m_t;
+ float b = t * m_t;
+ float c = t * t;
+
+ norm[0] = (bez->y2-bez->y1) * a + (bez->y3-bez->y2) * b + (bez->y4-bez->y3) * c;
+ norm[1] = -(bez->x2-bez->x1) * a - (bez->x3-bez->x2) * b - (bez->x4-bez->x3) * c;
+}
+
+enum shift_result {
+ Ok,
+ Discard,
+ Split,
+ Circle
+};
+
+static enum shift_result good_offset(const struct bezier *b1,
+ const struct bezier *b2,
+ float offset, float threshold)
+{
+ const float o2 = offset*offset;
+ const float max_dist_line = threshold*offset*offset;
+ const float max_dist_normal = threshold*offset;
+ const float spacing = 0.25;
+ for (float i = spacing; i < 0.99; i += spacing) {
+ float p1[2],p2[2], d, l;
+ float normal[2];
+ bezier_point_at(b1, i, p1);
+ bezier_point_at(b2, i, p2);
+ d = (p1[0] - p2[0])*(p1[0] - p2[0]) + (p1[1] - p2[1])*(p1[1] - p2[1]);
+ if (ABS(d - o2) > max_dist_line)
+ return Split;
+
+ bezier_normal_at(b1, i, normal);
+ l = ABS(normal[0]) + ABS(normal[1]);
+ if (l != 0.) {
+ d = ABS(normal[0]*(p1[1] - p2[1]) - normal[1]*(p1[0] - p2[0]) ) / l;
+ if (d > max_dist_normal)
+ return Split;
+ }
+ }
+ return Ok;
+}
+
+static INLINE void shift_line_by_normal(float *l, float offset)
+{
+ float norm[4];
+ float tx, ty;
+
+ line_normal(l, norm);
+ line_normalize(norm);
+
+ tx = (norm[2] - norm[0]) * offset;
+ ty = (norm[3] - norm[1]) * offset;
+ l[0] += tx; l[1] += ty;
+ l[2] += tx; l[3] += ty;
+}
+
+static INLINE VGboolean is_bezier_line(float (*points)[2], int count)
+{
+ float dx13 = points[2][0] - points[0][0];
+ float dy13 = points[2][1] - points[0][1];
+
+ float dx12 = points[1][0] - points[0][0];
+ float dy12 = points[1][1] - points[0][1];
+
+ debug_assert(count > 2);
+
+ if (count == 3) {
+ return floatsEqual(dx12 * dy13, dx13 * dy12);
+ } else if (count == 4) {
+ float dx14 = points[3][0] - points[0][0];
+ float dy14 = points[3][1] - points[0][1];
+
+ return (floatsEqual(dx12 * dy13, dx13 * dy12) &&
+ floatsEqual(dx12 * dy14, dx14 * dy12));
+ }
+
+ return VG_FALSE;
+}
+
+static INLINE void compute_pt_normal(float *pt1, float *pt2, float *res)
+{
+ float line[4];
+ float normal[4];
+ line[0] = 0.f; line[1] = 0.f;
+ line[2] = pt2[0] - pt1[0];
+ line[3] = pt2[1] - pt1[1];
+ line_normal(line, normal);
+ line_normalize(normal);
+
+ res[0] = normal[2];
+ res[1] = normal[3];
+}
+
+static enum shift_result shift(const struct bezier *orig,
+ struct bezier *shifted,
+ float offset, float threshold)
+{
+ int map[4];
+ VGboolean p1_p2_equal = (orig->x1 == orig->x2 && orig->y1 == orig->y2);
+ VGboolean p2_p3_equal = (orig->x2 == orig->x3 && orig->y2 == orig->y3);
+ VGboolean p3_p4_equal = (orig->x3 == orig->x4 && orig->y3 == orig->y4);
+
+ float points[4][2];
+ int np = 0;
+ float bounds[4];
+ float points_shifted[4][2];
+ float prev_normal[2];
+
+ points[np][0] = orig->x1;
+ points[np][1] = orig->y1;
+ map[0] = 0;
+ ++np;
+ if (!p1_p2_equal) {
+ points[np][0] = orig->x2;
+ points[np][1] = orig->y2;
+ ++np;
+ }
+ map[1] = np - 1;
+ if (!p2_p3_equal) {
+ points[np][0] = orig->x3;
+ points[np][1] = orig->y3;
+ ++np;
+ }
+ map[2] = np - 1;
+ if (!p3_p4_equal) {
+ points[np][0] = orig->x4;
+ points[np][1] = orig->y4;
+ ++np;
+ }
+ map[3] = np - 1;
+ if (np == 1)
+ return Discard;
+
+ /* We need to specialcase lines of 3 or 4 points due to numerical
+ instability in intersection code below */
+ if (np > 2 && is_bezier_line(points, np)) {
+ float l[4] = { points[0][0], points[0][1],
+ points[np-1][0], points[np-1][1] };
+ float ctrl1[2], ctrl2[2];
+ if (floatsEqual(points[0][0], points[np-1][0]) &&
+ floatsEqual(points[0][1], points[np-1][1]))
+ return Discard;
+
+ shift_line_by_normal(l, offset);
+ line_point_at(l, 0.33, ctrl1);
+ line_point_at(l, 0.66, ctrl2);
+ bezier_init(shifted, l[0], l[1],
+ ctrl1[0], ctrl1[1], ctrl2[0], ctrl2[1],
+ l[2], l[3]);
+ return Ok;
+ }
+
+ bezier_bounds(orig, bounds);
+ if (np == 4 && bounds[2] < .1*offset && bounds[3] < .1*offset) {
+ float l = (orig->x1 - orig->x2)*(orig->x1 - orig->x2) +
+ (orig->y1 - orig->y2)*(orig->y1 - orig->y1) *
+ (orig->x3 - orig->x4)*(orig->x3 - orig->x4) +
+ (orig->y3 - orig->y4)*(orig->y3 - orig->y4);
+ float dot = (orig->x1 - orig->x2)*(orig->x3 - orig->x4) +
+ (orig->y1 - orig->y2)*(orig->y3 - orig->y4);
+ if (dot < 0 && dot*dot < 0.8*l)
+ /* the points are close and reverse dirction. Approximate the whole
+ thing by a semi circle */
+ return Circle;
+ }
+
+ compute_pt_normal(points[0], points[1], prev_normal);
+
+ points_shifted[0][0] = points[0][0] + offset * prev_normal[0];
+ points_shifted[0][1] = points[0][1] + offset * prev_normal[1];
+
+ for (int i = 1; i < np - 1; ++i) {
+ float normal_sum[2], r;
+ float next_normal[2];
+ compute_pt_normal(points[i], points[i + 1], next_normal);
+
+ normal_sum[0] = prev_normal[0] + next_normal[0];
+ normal_sum[1] = prev_normal[1] + next_normal[1];
+
+ r = 1.0 + prev_normal[0] * next_normal[0]
+ + prev_normal[1] * next_normal[1];
+
+ if (floatsEqual(r + 1, 1)) {
+ points_shifted[i][0] = points[i][0] + offset * prev_normal[0];
+ points_shifted[i][1] = points[i][1] + offset * prev_normal[1];
+ } else {
+ float k = offset / r;
+ points_shifted[i][0] = points[i][0] + k * normal_sum[0];
+ points_shifted[i][1] = points[i][1] + k * normal_sum[1];
+ }
+
+ prev_normal[0] = next_normal[0];
+ prev_normal[1] = next_normal[1];
+ }
+
+ points_shifted[np - 1][0] = points[np - 1][0] + offset * prev_normal[0];
+ points_shifted[np - 1][1] = points[np - 1][1] + offset * prev_normal[1];
+
+ bezier_init2v(shifted,
+ points_shifted[map[0]], points_shifted[map[1]],
+ points_shifted[map[2]], points_shifted[map[3]]);
+
+ return good_offset(orig, shifted, offset, threshold);
+}
+
+static VGboolean make_circle(const struct bezier *b, float offset, struct bezier *o)
+{
+ float normals[3][2];
+ float dist;
+ float angles[2];
+ float sign = 1.f;
+ int i;
+ float circle[3][2];
+
+ normals[0][0] = b->y2 - b->y1;
+ normals[0][1] = b->x1 - b->x2;
+ dist = sqrt(normals[0][0]*normals[0][0] + normals[0][1]*normals[0][1]);
+ if (floatsEqual(dist + 1, 1.f))
+ return VG_FALSE;
+ normals[0][0] /= dist;
+ normals[0][1] /= dist;
+
+ normals[2][0] = b->y4 - b->y3;
+ normals[2][1] = b->x3 - b->x4;
+ dist = sqrt(normals[2][0]*normals[2][0] + normals[2][1]*normals[2][1]);
+ if (floatsEqual(dist + 1, 1.f))
+ return VG_FALSE;
+ normals[2][0] /= dist;
+ normals[2][1] /= dist;
+
+ normals[1][0] = b->x1 - b->x2 - b->x3 + b->x4;
+ normals[1][1] = b->y1 - b->y2 - b->y3 + b->y4;
+ dist = -1*sqrt(normals[1][0]*normals[1][0] + normals[1][1]*normals[1][1]);
+ normals[1][0] /= dist;
+ normals[1][1] /= dist;
+
+ for (i = 0; i < 2; ++i) {
+ float cos_a = normals[i][0]*normals[i+1][0] + normals[i][1]*normals[i+1][1];
+ if (cos_a > 1.)
+ cos_a = 1.;
+ if (cos_a < -1.)
+ cos_a = -1;
+ angles[i] = acos(cos_a)/M_PI;
+ }
+
+ if (angles[0] + angles[1] > 1.) {
+ /* more than 180 degrees */
+ normals[1][0] = -normals[1][0];
+ normals[1][1] = -normals[1][1];
+ angles[0] = 1. - angles[0];
+ angles[1] = 1. - angles[1];
+ sign = -1.;
+ }
+
+ circle[0][0] = b->x1 + normals[0][0]*offset;
+ circle[0][1] = b->y1 + normals[0][1]*offset;
+
+ circle[1][0] = 0.5*(b->x1 + b->x4) + normals[1][0]*offset;
+ circle[1][1] = 0.5*(b->y1 + b->y4) + normals[1][1]*offset;
+
+ circle[2][0] = b->x4 + normals[2][0]*offset;
+ circle[2][1] = b->y4 + normals[2][1]*offset;
+
+ for (i = 0; i < 2; ++i) {
+ float kappa = 2.*KAPPA * sign * offset * angles[i];
+
+ o->x1 = circle[i][0];
+ o->y1 = circle[i][1];
+ o->x2 = circle[i][0] - normals[i][1]*kappa;
+ o->y2 = circle[i][1] + normals[i][0]*kappa;
+ o->x3 = circle[i+1][0] + normals[i+1][1]*kappa;
+ o->y3 = circle[i+1][1] - normals[i+1][0]*kappa;
+ o->x4 = circle[i+1][0];
+ o->y4 = circle[i+1][1];
+
+ ++o;
+ }
+ return VG_TRUE;
+}
+
+int bezier_translate_by_normal(struct bezier *bez,
+ struct bezier *curves,
+ int max_curves,
+ float normal_len,
+ float threshold)
+{
+ struct bezier beziers[10];
+ struct bezier *b, *o;
+
+ /* fixme: this should really be floatsEqual */
+ if (bez->x1 == bez->x2 && bez->x1 == bez->x3 && bez->x1 == bez->x4 &&
+ bez->y1 == bez->y2 && bez->y1 == bez->y3 && bez->y1 == bez->y4)
+ return 0;
+
+ --max_curves;
+redo:
+ beziers[0] = *bez;
+ b = beziers;
+ o = curves;
+
+ while (b >= beziers) {
+ int stack_segments = b - beziers + 1;
+ enum shift_result res;
+ if ((stack_segments == 10) || (o - curves == max_curves - stack_segments)) {
+ threshold *= 1.5;
+ if (threshold > 2.)
+ goto give_up;
+ goto redo;
+ }
+ res = shift(b, o, normal_len, threshold);
+ if (res == Discard) {
+ --b;
+ } else if (res == Ok) {
+ ++o;
+ --b;
+ continue;
+ } else if (res == Circle && max_curves - (o - curves) >= 2) {
+ /* add semi circle */
+ if (make_circle(b, normal_len, o))
+ o += 2;
+ --b;
+ } else {
+ split(b, b+1, b);
+ ++b;
+ }
+ }
+
+give_up:
+ while (b >= beziers) {
+ enum shift_result res = shift(b, o, normal_len, threshold);
+
+ /* if res isn't Ok or Split then *o is undefined */
+ if (res == Ok || res == Split)
+ ++o;
+
+ --b;
+ }
+
+ debug_assert(o - curves <= max_curves);
+ return o - curves;
+}
+
+void bezier_bounds(const struct bezier *bez,
+ float *bounds/*x/y/width/height*/)
+{
+ float xmin = bez->x1;
+ float xmax = bez->x1;
+ float ymin = bez->y1;
+ float ymax = bez->y1;
+
+ if (bez->x2 < xmin)
+ xmin = bez->x2;
+ else if (bez->x2 > xmax)
+ xmax = bez->x2;
+ if (bez->x3 < xmin)
+ xmin = bez->x3;
+ else if (bez->x3 > xmax)
+ xmax = bez->x3;
+ if (bez->x4 < xmin)
+ xmin = bez->x4;
+ else if (bez->x4 > xmax)
+ xmax = bez->x4;
+
+ if (bez->y2 < ymin)
+ ymin = bez->y2;
+ else if (bez->y2 > ymax)
+ ymax = bez->y2;
+ if (bez->y3 < ymin)
+ ymin = bez->y3;
+ else if (bez->y3 > ymax)
+ ymax = bez->y3;
+ if (bez->y4 < ymin)
+ ymin = bez->y4;
+ else if (bez->y4 > ymax)
+ ymax = bez->y4;
+
+ bounds[0] = xmin; /* x */
+ bounds[1] = ymin; /* y */
+ bounds[2] = xmax - xmin; /* width */
+ bounds[3] = ymax - ymin; /* height */
+}
+
+void bezier_start_tangent(const struct bezier *bez,
+ float *tangent)
+{
+ tangent[0] = bez->x1;
+ tangent[1] = bez->y1;
+ tangent[2] = bez->x2;
+ tangent[3] = bez->y2;
+
+ if (null_line(tangent)) {
+ tangent[0] = bez->x1;
+ tangent[1] = bez->y1;
+ tangent[2] = bez->x3;
+ tangent[3] = bez->y3;
+ }
+ if (null_line(tangent)) {
+ tangent[0] = bez->x1;
+ tangent[1] = bez->y1;
+ tangent[2] = bez->x4;
+ tangent[3] = bez->y4;
+ }
+}
+
+
+static INLINE VGfloat bezier_t_at_length(struct bezier *bez,
+ VGfloat at_length,
+ VGfloat error)
+{
+ VGfloat len = bezier_length(bez, error);
+ VGfloat t = 1.0;
+ VGfloat last_bigger = 1.;
+
+ if (at_length > len || floatsEqual(at_length, len))
+ return t;
+
+ if (floatIsZero(at_length))
+ return 0.f;
+
+ t *= 0.5;
+ while (1) {
+ struct bezier right = *bez;
+ struct bezier left;
+ VGfloat tmp_len;
+ split_left(&right, t, &left);
+ tmp_len = bezier_length(&left, error);
+ if (ABS(tmp_len - at_length) < error)
+ break;
+
+ if (tmp_len < at_length) {
+ t += (last_bigger - t)*.5;
+ } else {
+ last_bigger = t;
+ t -= t*.5;
+ }
+ }
+ return t;
+}
+
+void bezier_point_at_length(struct bezier *bez,
+ float length,
+ float *point,
+ float *normal)
+{
+ /* ~0.000001 seems to be required to pass G2080x tests */
+ VGfloat t = bezier_t_at_length(bez, length, 0.000001);
+ bezier_point_at(bez, t, point);
+ bezier_normal_at(bez, t, normal);
+ vector_unit(normal);
+}
+
+void bezier_point_at_t(struct bezier *bez, float t,
+ float *point, float *normal)
+{
+ bezier_point_at(bez, t, point);
+ bezier_normal_at(bez, t, normal);
+ vector_unit(normal);
+}
+
+void bezier_exact_bounds(const struct bezier *bez,
+ float *bounds/*x/y/width/height*/)
+{
+ struct polygon *poly = polygon_create(64);
+ polygon_vertex_append(poly, bez->x1, bez->y1);
+ bezier_add_to_polygon(bez, poly);
+ polygon_bounding_rect(poly, bounds);
+ polygon_destroy(poly);
+}
+
diff --git a/src/gallium/state_trackers/vega/bezier.h b/src/gallium/state_trackers/vega/bezier.h
new file mode 100644
index 0000000000..e06666051c
--- /dev/null
+++ b/src/gallium/state_trackers/vega/bezier.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef BEZIER_H
+#define BEZIER_H
+
+struct polygon;
+struct matrix;
+
+struct bezier {
+ float x1, y1;
+ float x2, y2;
+ float x3, y3;
+ float x4, y4;
+};
+
+
+#define BEZIER_DEFAULT_ERROR 0.01
+
+/* kappa as being l of a circle with r = 1, we can emulate any
+ * circle of radius r by using the formula
+ * l = r . kappa
+ * More at:
+ * http://www.whizkidtech.redprince.net/bezier/circle/ */
+#define KAPPA 0.5522847498
+
+void bezier_init(struct bezier *bez,
+ float x1, float y1,
+ float x2, float y2,
+ float x3, float y3,
+ float x4, float y4);
+
+struct polygon *bezier_to_polygon(struct bezier *bez);
+void bezier_add_to_polygon(const struct bezier *bez,
+ struct polygon *poly);
+float bezier_length(struct bezier *bez, float error);
+void bezier_transform(struct bezier *bez,
+ struct matrix *mat);
+
+int bezier_translate_by_normal(struct bezier *b,
+ struct bezier *curves,
+ int max_curves,
+ float normal_len,
+ float threshold);
+void bezier_bounds(const struct bezier *bez,
+ float *bounds/*x/y/width/height*/);
+void bezier_exact_bounds(const struct bezier *bez,
+ float *bounds/*x/y/width/height*/);
+
+void bezier_start_tangent(const struct bezier *bez,
+ float *tangent);
+
+void bezier_point_at_length(struct bezier *bez, float length,
+ float *point, float *normal);
+void bezier_point_at_t(struct bezier *bez, float t,
+ float *point, float *normal);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c
new file mode 100644
index 0000000000..9a722980d5
--- /dev/null
+++ b/src/gallium/state_trackers/vega/image.c
@@ -0,0 +1,654 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "image.h"
+
+#include "vg_translate.h"
+#include "vg_context.h"
+#include "matrix.h"
+#include "renderer.h"
+#include "util_array.h"
+#include "api_consts.h"
+#include "shaders_cache.h"
+#include "shader.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_blit.h"
+#include "util/u_tile.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+static enum pipe_format vg_format_to_pipe(VGImageFormat format)
+{
+ switch(format) {
+ case VG_sRGB_565:
+ return PIPE_FORMAT_R5G6B5_UNORM;
+ case VG_sRGBA_5551:
+ return PIPE_FORMAT_A1R5G5B5_UNORM;
+ case VG_sRGBA_4444:
+ return PIPE_FORMAT_A4R4G4B4_UNORM;
+ case VG_sL_8:
+ case VG_lL_8:
+ return PIPE_FORMAT_L8_UNORM;
+ case VG_BW_1:
+ return PIPE_FORMAT_A8R8G8B8_UNORM;
+ case VG_A_8:
+ return PIPE_FORMAT_A8_UNORM;
+#ifdef OPENVG_VERSION_1_1
+ case VG_A_1:
+ case VG_A_4:
+ return PIPE_FORMAT_A8_UNORM;
+#endif
+ default:
+ return PIPE_FORMAT_A8R8G8B8_UNORM;
+ }
+}
+
+static INLINE void vg_sync_size(VGfloat *src_loc, VGfloat *dst_loc)
+{
+ src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
+ src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
+ dst_loc[2] = src_loc[2];
+ dst_loc[3] = src_loc[3];
+}
+
+
+static void vg_copy_texture(struct vg_context *ctx,
+ struct pipe_texture *dst, VGint dx, VGint dy,
+ struct pipe_texture *src, VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ VGfloat dst_loc[4], src_loc[4];
+ VGfloat dst_bounds[4], src_bounds[4];
+ VGfloat src_shift[4], dst_shift[4], shift[4];
+
+ dst_loc[0] = dx;
+ dst_loc[1] = dy;
+ dst_loc[2] = width;
+ dst_loc[3] = height;
+ dst_bounds[0] = 0.f;
+ dst_bounds[1] = 0.f;
+ dst_bounds[2] = dst->width[0];
+ dst_bounds[3] = dst->height[0];
+
+ src_loc[0] = sx;
+ src_loc[1] = sy;
+ src_loc[2] = width;
+ src_loc[3] = height;
+ src_bounds[0] = 0.f;
+ src_bounds[1] = 0.f;
+ src_bounds[2] = src->width[0];
+ src_bounds[3] = src->height[0];
+
+ vg_bound_rect(src_loc, src_bounds, src_shift);
+ vg_bound_rect(dst_loc, dst_bounds, dst_shift);
+ shift[0] = src_shift[0] - dst_shift[0];
+ shift[1] = src_shift[1] - dst_shift[1];
+
+ if (shift[0] < 0)
+ vg_shift_rectx(src_loc, src_bounds, -shift[0]);
+ else
+ vg_shift_rectx(dst_loc, dst_bounds, shift[0]);
+
+ if (shift[1] < 0)
+ vg_shift_recty(src_loc, src_bounds, -shift[1]);
+ else
+ vg_shift_recty(dst_loc, dst_bounds, shift[1]);
+
+ vg_sync_size(src_loc, dst_loc);
+
+ if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
+ dst_loc[2] >= 0 && dst_loc[3] >= 0) {
+ renderer_copy_texture(ctx->renderer,
+ src,
+ src_loc[0],
+ src_loc[1] + src_loc[3],
+ src_loc[0] + src_loc[2],
+ src_loc[1],
+ dst,
+ dst_loc[0],
+ dst_loc[1] + dst_loc[3],
+ dst_loc[0] + dst_loc[2],
+ dst_loc[1]);
+ }
+
+}
+
+void vg_copy_surface(struct vg_context *ctx,
+ struct pipe_surface *dst, VGint dx, VGint dy,
+ struct pipe_surface *src, VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ VGfloat dst_loc[4], src_loc[4];
+ VGfloat dst_bounds[4], src_bounds[4];
+ VGfloat src_shift[4], dst_shift[4], shift[4];
+
+ dst_loc[0] = dx;
+ dst_loc[1] = dy;
+ dst_loc[2] = width;
+ dst_loc[3] = height;
+ dst_bounds[0] = 0.f;
+ dst_bounds[1] = 0.f;
+ dst_bounds[2] = dst->width;
+ dst_bounds[3] = dst->height;
+
+ src_loc[0] = sx;
+ src_loc[1] = sy;
+ src_loc[2] = width;
+ src_loc[3] = height;
+ src_bounds[0] = 0.f;
+ src_bounds[1] = 0.f;
+ src_bounds[2] = src->width;
+ src_bounds[3] = src->height;
+
+ vg_bound_rect(src_loc, src_bounds, src_shift);
+ vg_bound_rect(dst_loc, dst_bounds, dst_shift);
+ shift[0] = src_shift[0] - dst_shift[0];
+ shift[1] = src_shift[1] - dst_shift[1];
+
+ if (shift[0] < 0)
+ vg_shift_rectx(src_loc, src_bounds, -shift[0]);
+ else
+ vg_shift_rectx(dst_loc, dst_bounds, shift[0]);
+
+ if (shift[1] < 0)
+ vg_shift_recty(src_loc, src_bounds, -shift[1]);
+ else
+ vg_shift_recty(dst_loc, dst_bounds, shift[1]);
+
+ vg_sync_size(src_loc, dst_loc);
+
+ if (src_loc[2] > 0 && src_loc[3] > 0 &&
+ dst_loc[2] > 0 && dst_loc[3] > 0) {
+ if (src == dst)
+ renderer_copy_surface(ctx->renderer,
+ src,
+ src_loc[0],
+ src->height - (src_loc[1] + src_loc[3]),
+ src_loc[0] + src_loc[2],
+ src->height - src_loc[1],
+ dst,
+ dst_loc[0],
+ dst->height - (dst_loc[1] + dst_loc[3]),
+ dst_loc[0] + dst_loc[2],
+ dst->height - dst_loc[1],
+ 0, 0);
+ else
+ renderer_copy_surface(ctx->renderer,
+ src,
+ src_loc[0],
+ src->height - src_loc[1],
+ src_loc[0] + src_loc[2],
+ src->height - (src_loc[1] + src_loc[3]),
+ dst,
+ dst_loc[0],
+ dst->height - (dst_loc[1] + dst_loc[3]),
+ dst_loc[0] + dst_loc[2],
+ dst->height - dst_loc[1],
+ 0, 0);
+ }
+
+}
+
+static struct pipe_texture *image_texture(struct vg_image *img)
+{
+ struct pipe_texture *tex = img->texture;
+ return tex;
+}
+
+
+static void image_cleari(struct vg_image *img, VGint clear_colori,
+ VGint x, VGint y, VGint width, VGint height)
+{
+ VGint *clearbuf;
+ VGint i;
+ VGfloat dwidth, dheight;
+
+ clearbuf = malloc(sizeof(VGint)*width*height);
+ for (i = 0; i < width*height; ++i)
+ clearbuf[i] = clear_colori;
+
+ dwidth = MIN2(width, img->width);
+ dheight = MIN2(height, img->height);
+
+ image_sub_data(img, clearbuf, width * sizeof(VGint),
+ VG_sRGBA_8888,
+ x, y, dwidth, dheight);
+ free(clearbuf);
+}
+
+struct vg_image * image_create(VGImageFormat format,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *image = CALLOC_STRUCT(vg_image);
+ enum pipe_format pformat = vg_format_to_pipe(format);
+ struct pipe_texture pt, *newtex;
+ struct pipe_screen *screen = ctx->pipe->screen;
+
+ vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
+
+ image->format = format;
+ image->width = width;
+ image->height = height;
+
+ image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ image->sampler.normalized_coords = 1;
+
+ assert(screen->is_format_supported(screen, pformat, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0));
+
+ memset(&pt, 0, sizeof(pt));
+ pt.target = PIPE_TEXTURE_2D;
+ pt.format = pformat;
+ pf_get_block(pformat, &pt.block);
+ pt.last_level = 0;
+ pt.width[0] = width;
+ pt.height[0] = height;
+ pt.depth[0] = 1;
+ pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+
+ newtex = screen->texture_create(screen, &pt);
+
+ debug_assert(newtex);
+
+ image->texture = newtex;
+
+ vg_context_add_object(ctx, VG_OBJECT_IMAGE, image);
+
+ image_cleari(image, 0, 0, 0, image->width, image->height);
+ return image;
+}
+
+void image_destroy(struct vg_image *img)
+{
+ struct vg_context *ctx = vg_current_context();
+ vg_context_remove_object(ctx, VG_OBJECT_IMAGE, img);
+
+
+ if (img->parent) {
+ /* remove img from the parent child array */
+ int idx;
+ struct vg_image **array =
+ (struct vg_image **)img->parent->children_array->data;
+
+ for (idx = 0; idx < img->parent->children_array->num_elements; ++idx) {
+ struct vg_image *child = array[idx];
+ if (child == img) {
+ break;
+ }
+ }
+ debug_assert(idx < img->parent->children_array->num_elements);
+ array_remove_element(img->parent->children_array, idx);
+ }
+
+ if (img->children_array && img->children_array->num_elements) {
+ /* reparent the children */
+ VGint i;
+ struct vg_image *parent = img->parent;
+ struct vg_image **children =
+ (struct vg_image **)img->children_array->data;
+ if (!parent) {
+ VGint min_x = children[0]->x;
+ parent = children[0];
+
+ for (i = 1; i < img->children_array->num_elements; ++i) {
+ struct vg_image *child = children[i];
+ if (child->x < min_x) {
+ parent = child;
+ }
+ }
+ }
+
+ for (i = 0; i < img->children_array->num_elements; ++i) {
+ struct vg_image *child = children[i];
+ if (child != parent) {
+ child->parent = parent;
+ if (!parent->children_array) {
+ parent->children_array = array_create(
+ sizeof(struct vg_image*));
+ }
+ array_append_data(parent->children_array,
+ &child, 1);
+ } else
+ child->parent = NULL;
+ }
+ array_destroy(img->children_array);
+ }
+
+ pipe_texture_reference(&img->texture, NULL);
+ free(img);
+}
+
+void image_clear(struct vg_image *img,
+ VGint x, VGint y, VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGfloat *clear_colorf = ctx->state.vg.clear_color;
+ VGubyte r, g, b ,a;
+ VGint clear_colori;
+ /* FIXME: this is very nasty */
+ r = float_to_ubyte(clear_colorf[0]);
+ g = float_to_ubyte(clear_colorf[1]);
+ b = float_to_ubyte(clear_colorf[2]);
+ a = float_to_ubyte(clear_colorf[3]);
+ clear_colori = r << 24 | g << 16 | b << 8 | a;
+ image_cleari(img, clear_colori, x, y, width, height);
+}
+
+void image_sub_data(struct vg_image *image,
+ const void * data,
+ VGint dataStride,
+ VGImageFormat dataFormat,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ const VGint yStep = 1;
+ VGubyte *src = (VGubyte *)data;
+ VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
+ VGfloat *df = (VGfloat*)temp;
+ VGint i;
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_screen *screen = ctx->pipe->screen;
+ struct pipe_texture *texture = image_texture(image);
+ VGint xoffset = 0, yoffset = 0;
+
+ if (x < 0) {
+ xoffset -= x;
+ width += x;
+ x = 0;
+ }
+ if (y < 0) {
+ yoffset -= y;
+ height += y;
+ y = 0;
+ }
+
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (x > image->width || y > image->width) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ if (x + width > image->width) {
+ width = image->width - x;
+ }
+
+ if (y + height > image->height) {
+ height = image->height - y;
+ }
+
+ { /* upload color_data */
+ struct pipe_transfer *transfer = screen->get_tex_transfer(
+ screen, texture, 0, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0, texture->width[0], texture->height[0]);
+ src += (dataStride * yoffset);
+ for (i = 0; i < height; i++) {
+ _vega_unpack_float_span_rgba(ctx, width, xoffset, src, dataFormat, temp);
+ pipe_put_tile_rgba(transfer, x+image->x, y+image->y, width, 1, df);
+ y += yStep;
+ src += dataStride;
+ }
+ screen->tex_transfer_destroy(transfer);
+ }
+}
+
+void image_get_sub_data(struct vg_image * image,
+ void * data,
+ VGint dataStride,
+ VGImageFormat dataFormat,
+ VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
+ VGfloat *df = (VGfloat*)temp;
+ VGint y = 0, yStep = 1;
+ VGint i;
+ VGubyte *dst = (VGubyte *)data;
+
+ {
+ struct pipe_transfer *transfer =
+ screen->get_tex_transfer(screen,
+ image->texture, 0, 0, 0,
+ PIPE_TRANSFER_READ,
+ 0, 0,
+ image->x + image->width,
+ image->y + image->height);
+ /* Do a row at a time to flip image data vertically */
+ for (i = 0; i < height; i++) {
+#if 0
+ debug_printf("%d-%d == %d\n", sy, height, y);
+#endif
+ pipe_get_tile_rgba(transfer, sx+image->x, y, width, 1, df);
+ y += yStep;
+ _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst);
+ dst += dataStride;
+ }
+
+ screen->tex_transfer_destroy(transfer);
+ }
+}
+
+struct vg_image * image_child_image(struct vg_image *parent,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_image *image = CALLOC_STRUCT(vg_image);
+
+ vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
+
+ image->x = parent->x + x;
+ image->y = parent->y + y;
+ image->width = width;
+ image->height = height;
+ image->parent = parent;
+ image->texture = 0;
+ pipe_texture_reference(&image->texture,
+ parent->texture);
+
+ image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ image->sampler.normalized_coords = 1;
+
+ if (!parent->children_array)
+ parent->children_array = array_create(
+ sizeof(struct vg_image*));
+
+ array_append_data(parent->children_array,
+ &image, 1);
+
+ vg_context_add_object(ctx, VG_OBJECT_IMAGE, image);
+
+ return image;
+}
+
+void image_copy(struct vg_image *dst, VGint dx, VGint dy,
+ struct vg_image *src, VGint sx, VGint sy,
+ VGint width, VGint height,
+ VGboolean dither)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (width <= 0 || height <= 0) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ /* make sure rendering has completed */
+ ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+ vg_copy_texture(ctx, dst->texture, dst->x + dx, dst->y + dy,
+ src->texture, src->x + sx, src->y + sy, width, height);
+}
+
+void image_draw(struct vg_image *img)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGfloat x1, y1;
+ VGfloat x2, y2;
+ VGfloat x3, y3;
+ VGfloat x4, y4;
+ struct matrix *matrix;
+
+ x1 = 0;
+ y1 = 0;
+ x2 = img->width;
+ y2 = 0;
+ x3 = img->width;
+ y3 = img->height;
+ x4 = 0;
+ y4 = img->height;
+
+ matrix = &ctx->state.vg.image_user_to_surface_matrix;
+
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ matrix_map_point(matrix, x2, y2, &x2, &y2);
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ matrix_map_point(matrix, x4, y4, &x4, &y4);
+
+ shader_set_drawing_image(ctx->shader, VG_TRUE);
+ shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
+ shader_set_image(ctx->shader, img);
+ shader_bind(ctx->shader);
+
+ renderer_texture_quad(ctx->renderer, image_texture(img),
+ img->x, img->y, img->x + img->width, img->y + img->height,
+ x1, y1, x2, y2, x3, y3, x4, y4);
+}
+
+void image_set_pixels(VGint dx, VGint dy,
+ struct vg_image *src, VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *surf;
+ struct st_renderbuffer *strb = ctx->draw_buffer->strb;
+
+ /* make sure rendering has completed */
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ surf = screen->get_tex_surface(screen, image_texture(src), 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ);
+
+ vg_copy_surface(ctx, strb->surface, dx, dy,
+ surf, sx+src->x, sy+src->y, width, height);
+
+ screen->tex_surface_destroy(surf);
+}
+
+void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
+ VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *surf;
+ struct st_renderbuffer *strb = ctx->draw_buffer->strb;
+
+ /* flip the y coordinates */
+ /*dy = dst->height - dy - height;*/
+
+ /* make sure rendering has completed */
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ surf = screen->get_tex_surface(screen, image_texture(dst), 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE |
+ PIPE_BUFFER_USAGE_GPU_READ);
+ vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy,
+ strb->surface, sx, sy, width, height);
+
+ pipe_surface_reference(&surf, NULL);
+}
+
+
+VGboolean vg_image_overlaps(struct vg_image *dst,
+ struct vg_image *src)
+{
+ if (dst == src || dst->parent == src ||
+ dst == src->parent)
+ return VG_TRUE;
+ if (dst->parent && dst->parent == src->parent) {
+ VGfloat left1 = dst->x;
+ VGfloat left2 = src->x;
+ VGfloat right1 = dst->x + dst->width;
+ VGfloat right2 = src->x + src->width;
+ VGfloat bottom1 = dst->y;
+ VGfloat bottom2 = src->y;
+ VGfloat top1 = dst->y + dst->height;
+ VGfloat top2 = src->y + src->height;
+
+ return !(left2 > right1 || right2 < left1 ||
+ top2 > bottom1 || bottom2 < top1);
+ }
+ return VG_FALSE;
+}
+
+VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers,
+ struct pipe_texture **textures)
+{
+ img->sampler.min_img_filter = image_sampler_filter(img->base.ctx);
+ img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx);
+ samplers[3] = &img->sampler;
+ textures[3] = img->texture;
+ return 1;
+}
+
+VGint image_sampler_filter(struct vg_context *ctx)
+{
+ switch(ctx->state.vg.image_quality) {
+ case VG_IMAGE_QUALITY_NONANTIALIASED:
+ return PIPE_TEX_FILTER_NEAREST;
+ break;
+ case VG_IMAGE_QUALITY_FASTER:
+ return PIPE_TEX_FILTER_NEAREST;
+ break;
+ case VG_IMAGE_QUALITY_BETTER:
+ /*return PIPE_TEX_FILTER_ANISO;*/
+ return PIPE_TEX_FILTER_LINEAR;
+ break;
+ default:
+ debug_printf("Unknown image quality");
+ }
+ return PIPE_TEX_FILTER_NEAREST;
+}
diff --git a/src/gallium/state_trackers/vega/image.h b/src/gallium/state_trackers/vega/image.h
new file mode 100644
index 0000000000..78e17cffa6
--- /dev/null
+++ b/src/gallium/state_trackers/vega/image.h
@@ -0,0 +1,104 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef IMAGES_H
+#define IMAGES_H
+
+#include "vg_context.h"
+#include "pipe/p_state.h"
+
+struct pipe_texture;
+struct array;
+struct vg_context;
+struct pipe_surface;
+
+struct vg_image {
+ struct vg_object base;
+ VGImageFormat format;
+ VGint x, y;
+ VGint width, height;
+
+ struct vg_image *parent;
+
+ struct pipe_texture *texture;
+ struct pipe_sampler_state sampler;
+
+ struct array *children_array;
+};
+
+struct vg_image *image_create(VGImageFormat format,
+ VGint width, VGint height);
+void image_destroy(struct vg_image *img);
+
+void image_clear(struct vg_image *img,
+ VGint x, VGint y, VGint width, VGint height);
+
+void image_sub_data(struct vg_image *image,
+ const void * data,
+ VGint dataStride,
+ VGImageFormat dataFormat,
+ VGint x, VGint y,
+ VGint width, VGint height);
+
+void image_get_sub_data(struct vg_image * image,
+ void * data,
+ VGint dataStride,
+ VGImageFormat dataFormat,
+ VGint x, VGint y,
+ VGint width, VGint height);
+
+struct vg_image *image_child_image(struct vg_image *parent,
+ VGint x, VGint y,
+ VGint width, VGint height);
+
+void image_copy(struct vg_image *dst, VGint dx, VGint dy,
+ struct vg_image *src, VGint sx, VGint sy,
+ VGint width, VGint height,
+ VGboolean dither);
+
+void image_draw(struct vg_image *img);
+
+void image_set_pixels(VGint dx, VGint dy,
+ struct vg_image *src, VGint sx, VGint sy,
+ VGint width, VGint height);
+void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
+ VGint sx, VGint sy,
+ VGint width, VGint height);
+
+VGint image_bind_samplers(struct vg_image *dst, struct pipe_sampler_state **samplers,
+ struct pipe_texture **textures);
+
+VGboolean vg_image_overlaps(struct vg_image *dst,
+ struct vg_image *src);
+
+VGint image_sampler_filter(struct vg_context *ctx);
+
+void vg_copy_surface(struct vg_context *ctx,
+ struct pipe_surface *dst, VGint dx, VGint dy,
+ struct pipe_surface *src, VGint sx, VGint sy,
+ VGint width, VGint height);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c
new file mode 100644
index 0000000000..24650a37d5
--- /dev/null
+++ b/src/gallium/state_trackers/vega/mask.c
@@ -0,0 +1,690 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "mask.h"
+
+#include "path.h"
+#include "image.h"
+#include "shaders_cache.h"
+#include "renderer.h"
+#include "asm_util.h"
+#include "st_inlines.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+
+struct vg_mask_layer {
+ struct vg_object base;
+
+ VGint width;
+ VGint height;
+
+ struct pipe_texture *texture;
+};
+
+static INLINE struct pipe_surface *
+alpha_mask_surface(struct vg_context *ctx, int usage)
+{
+ struct pipe_screen *screen = ctx->pipe->screen;
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+ return screen->get_tex_surface(screen,
+ stfb->alpha_mask,
+ 0, 0, 0,
+ usage);
+}
+
+static INLINE VGboolean
+intersect_rectangles(VGint dwidth, VGint dheight,
+ VGint swidth, VGint sheight,
+ VGint tx, VGint ty,
+ VGint twidth, VGint theight,
+ VGint *offsets,
+ VGint *location)
+{
+ if (tx + twidth <= 0 || tx >= dwidth)
+ return VG_FALSE;
+ if (ty + theight <= 0 || ty >= dheight)
+ return VG_FALSE;
+
+ offsets[0] = 0;
+ offsets[1] = 0;
+ location[0] = tx;
+ location[1] = ty;
+
+ if (tx < 0) {
+ offsets[0] -= tx;
+ location[0] = 0;
+
+ location[2] = MIN2(tx + swidth, MIN2(dwidth, tx + twidth));
+ offsets[2] = location[2];
+ } else {
+ offsets[2] = MIN2(twidth, MIN2(dwidth - tx, swidth ));
+ location[2] = offsets[2];
+ }
+
+ if (ty < 0) {
+ offsets[1] -= ty;
+ location[1] = 0;
+
+ location[3] = MIN2(ty + sheight, MIN2(dheight, ty + theight));
+ offsets[3] = location[3];
+ } else {
+ offsets[3] = MIN2(theight, MIN2(dheight - ty, sheight));
+ location[3] = offsets[3];
+ }
+
+ return VG_TRUE;
+}
+
+#if DEBUG_MASKS
+static void read_alpha_mask(void * data, VGint dataStride,
+ VGImageFormat dataFormat,
+ VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+ struct st_renderbuffer *strb = stfb->alpha_mask;
+ struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
+
+ VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
+ VGfloat *df = (VGfloat*)temp;
+ VGint y = (fb->height - sy) - 1, yStep = -1;
+ VGint i;
+ VGubyte *dst = (VGubyte *)data;
+ VGint xoffset = 0, yoffset = 0;
+
+ /* make sure rendering has completed */
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+ if (sx < 0) {
+ xoffset = -sx;
+ xoffset *= _vega_size_for_format(dataFormat);
+ width += sx;
+ sx = 0;
+ }
+ if (sy < 0) {
+ yoffset = -sy;
+ height += sy;
+ sy = 0;
+ y = (fb->height - sy) - 1;
+ yoffset *= dataStride;
+ }
+
+ {
+ struct pipe_surface *surf;
+
+ surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ /* Do a row at a time to flip image data vertically */
+ for (i = 0; i < height; i++) {
+#if 0
+ debug_printf("%d-%d == %d\n", sy, height, y);
+#endif
+ pipe_get_tile_rgba(surf, sx, y, width, 1, df);
+ y += yStep;
+ _vega_pack_rgba_span_float(ctx, width, temp, dataFormat,
+ dst + yoffset + xoffset);
+ dst += dataStride;
+ }
+
+ pipe_surface_reference(&surf, NULL);
+ }
+}
+
+void save_alpha_to_file(const char *filename)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
+ VGint *data;
+ int i, j;
+
+ data = malloc(sizeof(int) * fb->width * fb->height);
+ read_alpha_mask(data, fb->width * sizeof(int),
+ VG_sRGBA_8888,
+ 0, 0, fb->width, fb->height);
+ fprintf(stderr, "/*---------- start */\n");
+ fprintf(stderr, "const int image_width = %d;\n",
+ fb->width);
+ fprintf(stderr, "const int image_height = %d;\n",
+ fb->height);
+ fprintf(stderr, "const int image_data = {\n");
+ for (i = 0; i < fb->height; ++i) {
+ for (j = 0; j < fb->width; ++j) {
+ int rgba = data[i * fb->height + j];
+ int argb = 0;
+ argb = (rgba >> 8);
+ argb |= ((rgba & 0xff) << 24);
+ fprintf(stderr, "0x%x, ", argb);
+ }
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, "};\n");
+ fprintf(stderr, "/*---------- end */\n");
+}
+#endif
+
+static void setup_mask_framebuffer(struct pipe_surface *surf,
+ VGint surf_width, VGint surf_height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_framebuffer_state fb;
+
+ memset(&fb, 0, sizeof(fb));
+ fb.width = surf_width;
+ fb.height = surf_height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = surf;
+ {
+ VGint i;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ fb.cbufs[i] = 0;
+ }
+ cso_set_framebuffer(ctx->cso_context, &fb);
+}
+
+
+/* setup shader constants */
+static void setup_mask_operation(VGMaskOperation operation)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf;
+ const VGint param_bytes = 4 * sizeof(VGfloat);
+ const VGfloat ones[4] = {1.f, 1.f, 1.f, 1.f};
+ void *shader = 0;
+
+ /* We always need to get a new buffer, to keep the drivers simple and
+ * avoid gratuitous rendering synchronization.
+ */
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+
+ cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+ if (cbuf->buffer) {
+ st_no_flush_pipe_buffer_write(ctx, cbuf->buffer,
+ 0, param_bytes, ones);
+ }
+
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+ switch (operation) {
+ case VG_UNION_MASK: {
+ if (!ctx->mask.union_fs) {
+ ctx->mask.union_fs = shader_create_from_text(ctx->pipe,
+ union_mask_asm,
+ 200,
+ PIPE_SHADER_FRAGMENT);
+ }
+ shader = ctx->mask.union_fs->driver;
+ }
+ break;
+ case VG_INTERSECT_MASK: {
+ if (!ctx->mask.intersect_fs) {
+ ctx->mask.intersect_fs = shader_create_from_text(ctx->pipe,
+ intersect_mask_asm,
+ 200,
+ PIPE_SHADER_FRAGMENT);
+ }
+ shader = ctx->mask.intersect_fs->driver;
+ }
+ break;
+ case VG_SUBTRACT_MASK: {
+ if (!ctx->mask.subtract_fs) {
+ ctx->mask.subtract_fs = shader_create_from_text(ctx->pipe,
+ subtract_mask_asm,
+ 200,
+ PIPE_SHADER_FRAGMENT);
+ }
+ shader = ctx->mask.subtract_fs->driver;
+ }
+ break;
+ case VG_SET_MASK: {
+ if (!ctx->mask.set_fs) {
+ ctx->mask.set_fs = shader_create_from_text(ctx->pipe,
+ set_mask_asm,
+ 200,
+ PIPE_SHADER_FRAGMENT);
+ }
+ shader = ctx->mask.set_fs->driver;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ cso_set_fragment_shader_handle(ctx->cso_context, shader);
+}
+
+static void setup_mask_samplers(struct pipe_texture *umask)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ struct st_framebuffer *fb_buffers = ctx->draw_buffer;
+ struct pipe_texture *uprev = NULL;
+ struct pipe_sampler_state sampler;
+
+ uprev = fb_buffers->blend_texture;
+ sampler = ctx->mask.sampler;
+ sampler.normalized_coords = 1;
+
+ samplers[0] = NULL;
+ samplers[1] = NULL;
+ samplers[2] = NULL;
+ textures[0] = NULL;
+ textures[1] = NULL;
+ textures[2] = NULL;
+
+ samplers[0] = &sampler;
+ samplers[1] = &ctx->mask.sampler;
+
+ textures[0] = umask;
+ textures[1] = uprev;
+
+ cso_set_samplers(ctx->cso_context, 2,
+ (const struct pipe_sampler_state **)samplers);
+ cso_set_sampler_textures(ctx->cso_context, 2, textures);
+}
+
+
+/* setup shader constants */
+static void setup_mask_fill(const VGfloat color[4])
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf;
+ const VGint param_bytes = 4 * sizeof(VGfloat);
+
+ /* We always need to get a new buffer, to keep the drivers simple and
+ * avoid gratuitous rendering synchronization.
+ */
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+
+ cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+ if (cbuf->buffer) {
+ st_no_flush_pipe_buffer_write(ctx, cbuf->buffer, 0, param_bytes, color);
+ }
+
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+ cso_set_fragment_shader_handle(ctx->cso_context,
+ shaders_cache_fill(ctx->sc,
+ VEGA_SOLID_FILL_SHADER));
+}
+
+static void setup_mask_viewport()
+{
+ struct vg_context *ctx = vg_current_context();
+ vg_set_viewport(ctx, VEGA_Y0_TOP);
+}
+
+static void setup_mask_blend()
+{
+ struct vg_context *ctx = vg_current_context();
+
+ struct pipe_blend_state blend;
+
+ memset(&blend, 0, sizeof(struct pipe_blend_state));
+ blend.blend_enable = 1;
+ blend.colormask |= PIPE_MASK_R;
+ blend.colormask |= PIPE_MASK_G;
+ blend.colormask |= PIPE_MASK_B;
+ blend.colormask |= PIPE_MASK_A;
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+
+ cso_set_blend(ctx->cso_context, &blend);
+}
+
+
+static void surface_fill(struct pipe_surface *surf,
+ int surf_width, int surf_height,
+ int x, int y, int width, int height,
+ const VGfloat color[4])
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (x < 0) {
+ width += x;
+ x = 0;
+ }
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+
+ cso_save_framebuffer(ctx->cso_context);
+ cso_save_blend(ctx->cso_context);
+ cso_save_fragment_shader(ctx->cso_context);
+ cso_save_viewport(ctx->cso_context);
+
+ setup_mask_blend();
+ setup_mask_fill(color);
+ setup_mask_framebuffer(surf, surf_width, surf_height);
+ setup_mask_viewport();
+
+ renderer_draw_quad(ctx->renderer, x, y,
+ x + width, y + height, 0.0f/*depth should be disabled*/);
+
+
+ /* make sure rendering has completed */
+ ctx->pipe->flush(ctx->pipe,
+ PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME,
+ NULL);
+
+#if DEBUG_MASKS
+ save_alpha_to_file(0);
+#endif
+
+ cso_restore_blend(ctx->cso_context);
+ cso_restore_framebuffer(ctx->cso_context);
+ cso_restore_fragment_shader(ctx->cso_context);
+ cso_restore_viewport(ctx->cso_context);
+}
+
+
+static void mask_using_texture(struct pipe_texture *texture,
+ VGMaskOperation operation,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_surface *surface =
+ alpha_mask_surface(ctx, PIPE_BUFFER_USAGE_GPU_WRITE);
+ VGint offsets[4], loc[4];
+
+ if (!surface)
+ return;
+ if (!intersect_rectangles(surface->width, surface->height,
+ texture->width[0], texture->height[0],
+ x, y, width, height,
+ offsets, loc))
+ return;
+#if 0
+ debug_printf("Offset = [%d, %d, %d, %d]\n", offsets[0],
+ offsets[1], offsets[2], offsets[3]);
+ debug_printf("Locati = [%d, %d, %d, %d]\n", loc[0],
+ loc[1], loc[2], loc[3]);
+#endif
+
+ /* prepare our blend surface */
+ vg_prepare_blend_surface_from_mask(ctx);
+
+ cso_save_samplers(ctx->cso_context);
+ cso_save_sampler_textures(ctx->cso_context);
+ cso_save_framebuffer(ctx->cso_context);
+ cso_save_blend(ctx->cso_context);
+ cso_save_fragment_shader(ctx->cso_context);
+ cso_save_viewport(ctx->cso_context);
+
+ setup_mask_samplers(texture);
+ setup_mask_blend();
+ setup_mask_operation(operation);
+ setup_mask_framebuffer(surface, surface->width, surface->height);
+ setup_mask_viewport();
+
+ /* render the quad to propagate the rendering from stencil */
+ renderer_draw_texture(ctx->renderer, texture,
+ offsets[0], offsets[1],
+ offsets[0] + offsets[2], offsets[1] + offsets[3],
+ loc[0], loc[1], loc[0] + loc[2], loc[1] + loc[3]);
+
+ /* make sure rendering has completed */
+ ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+ cso_restore_blend(ctx->cso_context);
+ cso_restore_framebuffer(ctx->cso_context);
+ cso_restore_fragment_shader(ctx->cso_context);
+ cso_restore_samplers(ctx->cso_context);
+ cso_restore_sampler_textures(ctx->cso_context);
+ cso_restore_viewport(ctx->cso_context);
+
+ pipe_surface_reference(&surface, NULL);
+}
+
+
+#ifdef OPENVG_VERSION_1_1
+
+struct vg_mask_layer * mask_layer_create(VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_mask_layer *mask = 0;
+
+ mask = CALLOC_STRUCT(vg_mask_layer);
+ vg_init_object(&mask->base, ctx, VG_OBJECT_MASK);
+ mask->width = width;
+ mask->height = height;
+
+ {
+ struct pipe_texture pt;
+ struct pipe_screen *screen = ctx->pipe->screen;
+
+ memset(&pt, 0, sizeof(pt));
+ pt.target = PIPE_TEXTURE_2D;
+ pt.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &pt.block);
+ pt.last_level = 0;
+ pt.width[0] = width;
+ pt.height[0] = height;
+ pt.depth[0] = 1;
+ pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+ pt.compressed = 0;
+
+ mask->texture = screen->texture_create(screen, &pt);
+ }
+
+ vg_context_add_object(ctx, VG_OBJECT_MASK, mask);
+
+ return mask;
+}
+
+void mask_layer_destroy(struct vg_mask_layer *layer)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ vg_context_remove_object(ctx, VG_OBJECT_MASK, layer);
+ pipe_texture_release(&layer->texture);
+ free(layer);
+}
+
+void mask_layer_fill(struct vg_mask_layer *layer,
+ VGint x, VGint y,
+ VGint width, VGint height,
+ VGfloat value)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGfloat alpha_color[4] = {0, 0, 0, 0};
+ struct pipe_surface *surface;
+
+ alpha_color[3] = value;
+
+ surface = ctx->pipe->screen->get_tex_surface(
+ ctx->pipe->screen, layer->texture,
+ 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ surface_fill(surface,
+ layer->width, layer->height,
+ x, y, width, height, alpha_color);
+
+ ctx->pipe->screen->tex_surface_release(ctx->pipe->screen, &surface);
+}
+
+void mask_copy(struct vg_mask_layer *layer,
+ VGint sx, VGint sy,
+ VGint dx, VGint dy,
+ VGint width, VGint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct st_framebuffer *fb_buffers = ctx->draw_buffer;
+
+ renderer_copy_texture(ctx->renderer,
+ layer->texture,
+ sx, sy,
+ sx + width, sy + height,
+ fb_buffers->alpha_mask,
+ dx, dy,
+ dx + width, dy + height);
+}
+
+static void mask_layer_render_to(struct vg_mask_layer *layer,
+ struct path *path,
+ VGbitfield paint_modes)
+{
+ struct vg_context *ctx = vg_current_context();
+ const VGfloat fill_color[4] = {1.f, 1.f, 1.f, 1.f};
+ struct pipe_screen *screen = ctx->pipe->screen;
+ struct pipe_surface *surface;
+
+ surface = screen->get_tex_surface(screen, layer->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ cso_save_framebuffer(ctx->cso_context);
+ cso_save_fragment_shader(ctx->cso_context);
+ cso_save_viewport(ctx->cso_context);
+
+ setup_mask_blend();
+ setup_mask_fill(fill_color);
+ setup_mask_framebuffer(surface, layer->width, layer->height);
+ setup_mask_viewport();
+
+ if (paint_modes & VG_FILL_PATH) {
+ struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
+ path_fill(path, mat);
+ }
+
+ if (paint_modes & VG_STROKE_PATH){
+ path_stroke(path);
+ }
+
+
+ /* make sure rendering has completed */
+ ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ cso_restore_framebuffer(ctx->cso_context);
+ cso_restore_fragment_shader(ctx->cso_context);
+ cso_restore_viewport(ctx->cso_context);
+ ctx->state.dirty |= BLEND_DIRTY;
+
+ screen->tex_surface_release(ctx->pipe->screen, &surface);
+}
+
+void mask_render_to(struct path *path,
+ VGbitfield paint_modes,
+ VGMaskOperation operation)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct st_framebuffer *fb_buffers = ctx->draw_buffer;
+ struct vg_mask_layer *temp_layer;
+ VGint width, height;
+
+ width = fb_buffers->alpha_mask->width[0];
+ height = fb_buffers->alpha_mask->width[0];
+
+ temp_layer = mask_layer_create(width, height);
+
+ mask_layer_render_to(temp_layer, path, paint_modes);
+
+ mask_using_layer(temp_layer, 0, 0, width, height,
+ operation);
+
+ mask_layer_destroy(temp_layer);
+}
+
+void mask_using_layer(struct vg_mask_layer *layer,
+ VGMaskOperation operation,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ mask_using_texture(layer->texture, operation,
+ x, y, width, height);
+}
+
+VGint mask_layer_width(struct vg_mask_layer *layer)
+{
+ return layer->width;
+}
+
+VGint mask_layer_height(struct vg_mask_layer *layer)
+{
+ return layer->height;
+}
+
+
+#endif
+
+void mask_using_image(struct vg_image *image,
+ VGMaskOperation operation,
+ VGint x, VGint y,
+ VGint width, VGint height)
+{
+ mask_using_texture(image->texture, operation,
+ x, y, width, height);
+}
+
+void mask_fill(VGint x, VGint y, VGint width, VGint height,
+ VGfloat value)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGfloat alpha_color[4] = {.0f, .0f, .0f, value};
+ struct pipe_surface *surf = alpha_mask_surface(
+ ctx, PIPE_BUFFER_USAGE_GPU_WRITE);
+
+#if DEBUG_MASKS
+ debug_printf("mask_fill(%d, %d, %d, %d) with rgba(%f, %f, %f, %f)\n",
+ x, y, width, height,
+ alpha_color[0], alpha_color[1],
+ alpha_color[2], alpha_color[3]);
+ debug_printf("XXX %f === %f \n",
+ alpha_color[3], value);
+#endif
+
+ surface_fill(surf, surf->width, surf->height,
+ x, y, width, height, alpha_color);
+
+ pipe_surface_reference(&surf, NULL);
+}
+
+VGint mask_bind_samplers(struct pipe_sampler_state **samplers,
+ struct pipe_texture **textures)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ if (ctx->state.vg.masking) {
+ struct st_framebuffer *fb_buffers = ctx->draw_buffer;
+
+ samplers[1] = &ctx->mask.sampler;
+ textures[1] = fb_buffers->alpha_mask;
+ return 1;
+ } else
+ return 0;
+}
diff --git a/src/gallium/state_trackers/vega/mask.h b/src/gallium/state_trackers/vega/mask.h
new file mode 100644
index 0000000000..5eaaede0e3
--- /dev/null
+++ b/src/gallium/state_trackers/vega/mask.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef MASK_H
+#define MASK_H
+
+#include "vg_context.h"
+
+struct path;
+struct vg_image;
+struct pipe_texture;
+
+struct vg_mask_layer *mask_layer_create(VGint width, VGint height);
+void mask_layer_destroy(struct vg_mask_layer *layer);
+void mask_layer_fill(struct vg_mask_layer *layer,
+ VGint x, VGint y,
+ VGint width, VGint height,
+ VGfloat value);
+VGint mask_layer_width(struct vg_mask_layer *layer);
+VGint mask_layer_height(struct vg_mask_layer *layer);
+void mask_copy(struct vg_mask_layer *layer,
+ VGint sx, VGint sy,
+ VGint dx, VGint dy,
+ VGint width, VGint height);
+
+void mask_render_to(struct path *path,
+ VGbitfield paint_modes,
+ VGMaskOperation operation);
+
+void mask_using_layer(struct vg_mask_layer *layer,
+ VGMaskOperation operation,
+ VGint x, VGint y,
+ VGint width, VGint height);
+void mask_using_image(struct vg_image *image,
+ VGMaskOperation operation,
+ VGint x, VGint y,
+ VGint width, VGint height);
+void mask_fill(VGint x, VGint y,
+ VGint width, VGint height,
+ VGfloat value);
+
+VGint mask_bind_samplers(struct pipe_sampler_state **samplers,
+ struct pipe_texture **textures);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/matrix.h b/src/gallium/state_trackers/vega/matrix.h
new file mode 100644
index 0000000000..4c207f912a
--- /dev/null
+++ b/src/gallium/state_trackers/vega/matrix.h
@@ -0,0 +1,462 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef MATRIX_H
+#define MATRIX_H
+
+#include "VG/openvg.h"
+
+#include "pipe/p_compiler.h"
+#include "util/u_math.h"
+
+#include <stdio.h>
+#include <math.h>
+
+#define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
+#define floatIsZero(x) (floatsEqual((x) + 1, 1))
+#define ABS(x) (fabsf(x))
+
+#define DEGREES_TO_RADIANS(d) (0.0174532925199 * (d))
+#define FLT_TO_INT(flt) float_to_int_floor(((VGuint*)&(flt))[0])
+
+static INLINE VGint float_to_int_floor(VGuint bits)
+{
+ int sign = (bits >> 31) ? -1 : 1;
+ int exp = ((bits >> 23) & 255) - 127;
+ int mant = bits & 0x007fffff;
+ int sh = 23 - exp;
+
+ /* abs(value) >= 2^31 -> clamp. */
+
+ if (exp >= 31)
+ return (VGint)((sign < 0) ? 0x80000000u : 0x7fffffffu);
+
+ /* abs(value) < 1 -> return -1 or 0. */
+
+ if (exp < 0)
+ return (sign < 0 && (exp > -127 || mant != 0)) ? -1 : 0;
+
+ /* abs(value) >= 2^23 -> shift left. */
+
+ mant |= 0x00800000;
+ if (sh <= 0)
+ return sign * (mant << -sh);
+
+ /* Negative -> add a rounding term. */
+
+ if (sign < 0)
+ mant += (1 << sh) - 1;
+
+ /* Shift right to obtain the result. */
+
+ return sign * (mant >> sh);
+}
+
+
+struct matrix {
+ VGfloat m[9];
+};
+
+static INLINE void matrix_init(struct matrix *mat,
+ const VGfloat *val)
+{
+ memcpy(mat->m, val, sizeof(VGfloat) * 9);
+}
+
+static INLINE void matrix_inits(struct matrix *mat,
+ VGfloat m11, VGfloat m12, VGfloat m13,
+ VGfloat m21, VGfloat m22, VGfloat m23,
+ VGfloat m31, VGfloat m32, VGfloat m33)
+{
+ mat->m[0] = m11; mat->m[1] = m12; mat->m[2] = m13;
+ mat->m[3] = m21; mat->m[4] = m22; mat->m[5] = m23;
+ mat->m[6] = m31; mat->m[7] = m32; mat->m[8] = m33;
+}
+
+static INLINE void matrix_load_identity(struct matrix *matrix)
+{
+ static const VGfloat identity[9] = {1.f, 0.f, 0.f,
+ 0.f, 1.f, 0.f,
+ 0.f, 0.f, 1.f};
+ memcpy(matrix->m, identity, sizeof(identity));
+}
+
+static INLINE VGboolean matrix_is_identity(struct matrix *matrix)
+{
+ return floatsEqual(matrix->m[0], 1) && floatIsZero(matrix->m[1]) &&
+ floatIsZero(matrix->m[2]) &&
+ floatIsZero(matrix->m[3]) && floatsEqual(matrix->m[4], 1) &&
+ floatIsZero(matrix->m[5]) &&
+ floatIsZero(matrix->m[6]) && floatIsZero(matrix->m[7]) &&
+ floatIsZero(matrix->m[8]);
+}
+
+static INLINE VGboolean matrix_is_affine(struct matrix *matrix)
+{
+ return floatIsZero(matrix->m[2]) && floatIsZero(matrix->m[5])
+ && floatsEqual(matrix->m[8], 1);
+}
+
+
+static INLINE void matrix_make_affine(struct matrix *matrix)
+{
+ matrix->m[2] = 0.f;
+ matrix->m[5] = 0.f;
+ matrix->m[8] = 1.f;
+}
+
+static INLINE void matrix_mult(struct matrix *dst,
+ struct matrix *src)
+{
+ VGfloat m11 = dst->m[0]*src->m[0] + dst->m[3]*src->m[1] + dst->m[6]*src->m[2];
+ VGfloat m12 = dst->m[0]*src->m[3] + dst->m[3]*src->m[4] + dst->m[6]*src->m[5];
+ VGfloat m13 = dst->m[0]*src->m[6] + dst->m[3]*src->m[7] + dst->m[6]*src->m[8];
+
+ VGfloat m21 = dst->m[1]*src->m[0] + dst->m[4]*src->m[1] + dst->m[7]*src->m[2];
+ VGfloat m22 = dst->m[1]*src->m[3] + dst->m[4]*src->m[4] + dst->m[7]*src->m[5];
+ VGfloat m23 = dst->m[1]*src->m[6] + dst->m[4]*src->m[7] + dst->m[7]*src->m[8];
+
+ VGfloat m31 = dst->m[2]*src->m[0] + dst->m[5]*src->m[1] + dst->m[8]*src->m[2];
+ VGfloat m32 = dst->m[2]*src->m[3] + dst->m[5]*src->m[4] + dst->m[8]*src->m[5];
+ VGfloat m33 = dst->m[2]*src->m[6] + dst->m[5]*src->m[7] + dst->m[8]*src->m[8];
+
+ dst->m[0] = m11; dst->m[1] = m21; dst->m[2] = m31;
+ dst->m[3] = m12; dst->m[4] = m22; dst->m[5] = m32;
+ dst->m[6] = m13; dst->m[7] = m23; dst->m[8] = m33;
+}
+
+
+static INLINE void matrix_map_point(struct matrix *mat,
+ VGfloat x, VGfloat y,
+ VGfloat *out_x, VGfloat *out_y)
+{
+ /* to be able to do matrix_map_point(m, x, y, &x, &y) use
+ * temporaries */
+ VGfloat tmp_x = x, tmp_y = y;
+
+ *out_x = mat->m[0]*tmp_x + mat->m[3]*tmp_y + mat->m[6];
+ *out_y = mat->m[1]*tmp_x + mat->m[4]*tmp_y + mat->m[7];
+ if (!matrix_is_affine(mat)) {
+ VGfloat w = 1/(mat->m[2]*tmp_x + mat->m[5]*tmp_y + mat->m[8]);
+ *out_x *= w;
+ *out_y *= w;
+ }
+}
+
+static INLINE void matrix_translate(struct matrix *dst,
+ VGfloat tx, VGfloat ty)
+{
+ if (!matrix_is_affine(dst)) {
+ struct matrix trans_matrix;
+ matrix_load_identity(&trans_matrix);
+ trans_matrix.m[6] = tx;
+ trans_matrix.m[7] = ty;
+ matrix_mult(dst, &trans_matrix);
+ } else {
+ dst->m[6] += tx*dst->m[0] + ty*dst->m[3];
+ dst->m[7] += ty*dst->m[4] + tx*dst->m[1];
+ }
+}
+
+static INLINE void matrix_scale(struct matrix *dst,
+ VGfloat sx, VGfloat sy)
+{
+ if (!matrix_is_affine(dst)) {
+ struct matrix scale_matrix;
+ matrix_load_identity(&scale_matrix);
+ scale_matrix.m[0] = sx;
+ scale_matrix.m[4] = sy;
+ matrix_mult(dst, &scale_matrix);
+ } else {
+ dst->m[0] *= sx; dst->m[1] *= sx;
+ dst->m[3] *= sy; dst->m[4] *= sy;
+ }
+}
+
+static INLINE void matrix_shear(struct matrix *dst,
+ VGfloat shx, VGfloat shy)
+{
+ struct matrix shear_matrix;
+ matrix_load_identity(&shear_matrix);
+ shear_matrix.m[1] = shy;
+ shear_matrix.m[3] = shx;
+ matrix_mult(dst, &shear_matrix);
+}
+
+static INLINE void matrix_rotate(struct matrix *dst,
+ VGfloat angle)
+{
+ struct matrix mat;
+ float sin_val = 0;
+ float cos_val = 0;
+
+
+ if (floatsEqual(angle, 90) || floatsEqual(angle, -270))
+ sin_val = 1.f;
+ else if (floatsEqual(angle, 270) || floatsEqual(angle, -90))
+ sin_val = -1.f;
+ else if (floatsEqual(angle, 180))
+ cos_val = -1.f;
+ else {
+ float radians = DEGREES_TO_RADIANS(angle);
+ sin_val = sin(radians);
+ cos_val = cos(radians);
+ }
+
+ if (!matrix_is_affine(dst)) {
+ matrix_load_identity(&mat);
+ mat.m[0] = cos_val; mat.m[1] = sin_val;
+ mat.m[3] = -sin_val; mat.m[4] = cos_val;
+
+ matrix_mult(dst, &mat);
+ } else {
+ VGfloat m11 = cos_val*dst->m[0] + sin_val*dst->m[3];
+ VGfloat m12 = cos_val*dst->m[1] + sin_val*dst->m[4];
+ VGfloat m21 = -sin_val*dst->m[0] + cos_val*dst->m[3];
+ VGfloat m22 = -sin_val*dst->m[1] + cos_val*dst->m[4];
+ dst->m[0] = m11; dst->m[1] = m12;
+ dst->m[3] = m21; dst->m[4] = m22;
+ }
+}
+
+
+static INLINE VGfloat matrix_determinant(struct matrix *mat)
+{
+ return mat->m[0]*(mat->m[8]*mat->m[4]-mat->m[7]*mat->m[5]) -
+ mat->m[3]*(mat->m[8]*mat->m[1]-mat->m[7]*mat->m[2])+
+ mat->m[6]*(mat->m[5]*mat->m[1]-mat->m[4]*mat->m[2]);
+}
+
+
+static INLINE void matrix_adjoint(struct matrix *mat)
+{
+ VGfloat h[9];
+ h[0] = mat->m[4]*mat->m[8] - mat->m[5]*mat->m[7];
+ h[3] = mat->m[5]*mat->m[6] - mat->m[3]*mat->m[8];
+ h[6] = mat->m[3]*mat->m[7] - mat->m[4]*mat->m[6];
+ h[1] = mat->m[2]*mat->m[7] - mat->m[1]*mat->m[8];
+ h[4] = mat->m[0]*mat->m[8] - mat->m[2]*mat->m[6];
+ h[7] = mat->m[1]*mat->m[6] - mat->m[0]*mat->m[7];
+ h[2] = mat->m[1]*mat->m[5] - mat->m[2]*mat->m[4];
+ h[5] = mat->m[2]*mat->m[3] - mat->m[0]*mat->m[5];
+ h[8] = mat->m[0]*mat->m[4] - mat->m[1]*mat->m[3];
+
+
+ memcpy(mat->m, h, sizeof(VGfloat) * 9);
+}
+
+static INLINE void matrix_divs(struct matrix *mat,
+ VGfloat s)
+{
+ mat->m[0] /= s;
+ mat->m[1] /= s;
+ mat->m[2] /= s;
+ mat->m[3] /= s;
+ mat->m[4] /= s;
+ mat->m[5] /= s;
+ mat->m[6] /= s;
+ mat->m[7] /= s;
+ mat->m[8] /= s;
+}
+
+static INLINE VGboolean matrix_invert(struct matrix *mat)
+{
+ VGfloat det = matrix_determinant(mat);
+
+ if (floatIsZero(det))
+ return VG_FALSE;
+
+ matrix_adjoint(mat);
+ matrix_divs(mat, det);
+ return VG_TRUE;
+}
+
+static INLINE VGboolean matrix_is_invertible(struct matrix *mat)
+{
+ return !floatIsZero(matrix_determinant(mat));
+}
+
+
+static INLINE VGboolean matrix_square_to_quad(VGfloat dx0, VGfloat dy0,
+ VGfloat dx1, VGfloat dy1,
+ VGfloat dx3, VGfloat dy3,
+ VGfloat dx2, VGfloat dy2,
+ struct matrix *mat)
+{
+ VGfloat ax = dx0 - dx1 + dx2 - dx3;
+ VGfloat ay = dy0 - dy1 + dy2 - dy3;
+
+ if (floatIsZero(ax) && floatIsZero(ay)) {
+ /* affine case */
+ matrix_inits(mat,
+ dx1 - dx0, dy1 - dy0, 0,
+ dx2 - dx1, dy2 - dy1, 0,
+ dx0, dy0, 1);
+ } else {
+ VGfloat a, b, c, d, e, f, g, h;
+ VGfloat ax1 = dx1 - dx2;
+ VGfloat ax2 = dx3 - dx2;
+ VGfloat ay1 = dy1 - dy2;
+ VGfloat ay2 = dy3 - dy2;
+
+ /* determinants */
+ VGfloat gtop = ax * ay2 - ax2 * ay;
+ VGfloat htop = ax1 * ay - ax * ay1;
+ VGfloat bottom = ax1 * ay2 - ax2 * ay1;
+
+ if (!bottom)
+ return VG_FALSE;
+
+ g = gtop / bottom;
+ h = htop / bottom;
+
+ a = dx1 - dx0 + g * dx1;
+ b = dx3 - dx0 + h * dx3;
+ c = dx0;
+ d = dy1 - dy0 + g * dy1;
+ e = dy3 - dy0 + h * dy3;
+ f = dy0;
+
+ matrix_inits(mat,
+ a, d, g,
+ b, e, h,
+ c, f, 1.f);
+ }
+
+ return VG_TRUE;
+}
+
+static INLINE VGboolean matrix_quad_to_square(VGfloat sx0, VGfloat sy0,
+ VGfloat sx1, VGfloat sy1,
+ VGfloat sx2, VGfloat sy2,
+ VGfloat sx3, VGfloat sy3,
+ struct matrix *mat)
+{
+ if (!matrix_square_to_quad(sx0, sy0, sx1, sy1,
+ sx2, sy2, sx3, sy3,
+ mat))
+ return VG_FALSE;
+
+ return matrix_invert(mat);
+}
+
+
+static INLINE VGboolean matrix_quad_to_quad(VGfloat dx0, VGfloat dy0,
+ VGfloat dx1, VGfloat dy1,
+ VGfloat dx2, VGfloat dy2,
+ VGfloat dx3, VGfloat dy3,
+ VGfloat sx0, VGfloat sy0,
+ VGfloat sx1, VGfloat sy1,
+ VGfloat sx2, VGfloat sy2,
+ VGfloat sx3, VGfloat sy3,
+ struct matrix *mat)
+{
+ struct matrix sqr_to_qd;
+
+ if (!matrix_square_to_quad(dx0, dy0, dx1, dy1,
+ dx2, dy2, dx3, dy3,
+ mat))
+ return VG_FALSE;
+
+ if (!matrix_quad_to_square(sx0, sy0, sx1, sy1,
+ sx2, sy2, sx3, sy3,
+ &sqr_to_qd))
+ return VG_FALSE;
+
+ matrix_mult(mat, &sqr_to_qd);
+
+ return VG_TRUE;
+}
+
+
+static INLINE VGboolean null_line(const VGfloat *l)
+{
+ return floatsEqual(l[0], l[2]) && floatsEqual(l[1], l[3]);
+}
+
+static INLINE void line_normal(float *l, float *norm)
+{
+ norm[0] = l[0];
+ norm[1] = l[1];
+
+ norm[2] = l[0] + (l[3] - l[1]);
+ norm[3] = l[1] - (l[2] - l[0]);
+}
+
+static INLINE void line_normalize(float *l)
+{
+ float x = l[2] - l[0];
+ float y = l[3] - l[1];
+ float len = sqrt(x*x + y*y);
+ l[2] = l[0] + x/len;
+ l[3] = l[1] + y/len;
+}
+
+static INLINE VGfloat line_length(VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2)
+{
+ VGfloat x = x2 - x1;
+ VGfloat y = y2 - y1;
+ return sqrt(x*x + y*y);
+}
+
+static INLINE VGfloat line_lengthv(const VGfloat *l)
+{
+ VGfloat x = l[2] - l[0];
+ VGfloat y = l[3] - l[1];
+ return sqrt(x*x + y*y);
+}
+
+
+static INLINE void line_point_at(float *l, float t, float *pt)
+{
+ float dx = l[2] - l[0];
+ float dy = l[3] - l[1];
+
+ pt[0] = l[0] + dx * t;
+ pt[1] = l[1] + dy * t;
+}
+
+static INLINE void vector_unit(float *vec)
+{
+ float len = sqrt(vec[0] * vec[0] + vec[1] * vec[1]);
+ vec[0] /= len;
+ vec[1] /= len;
+}
+
+static INLINE void line_normal_vector(float *line, float *vec)
+{
+ VGfloat normal[4];
+
+ line_normal(line, normal);
+
+ vec[0] = normal[2] - normal[0];
+ vec[1] = normal[3] - normal[1];
+
+ vector_unit(vec);
+}
+
+#endif
diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c
new file mode 100644
index 0000000000..04a6ba9cdc
--- /dev/null
+++ b/src/gallium/state_trackers/vega/paint.c
@@ -0,0 +1,699 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "paint.h"
+
+#include "shaders_cache.h"
+#include "matrix.h"
+#include "image.h"
+#include "st_inlines.h"
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "cso_cache/cso_context.h"
+
+struct vg_paint {
+ struct vg_object base;
+
+ VGPaintType type;
+
+ struct {
+ VGfloat color[4];
+ VGint colori[4];
+ } solid;
+
+ struct {
+ VGColorRampSpreadMode spread;
+ VGuint color_data[1024];
+ struct {
+ VGfloat coords[4];
+ VGint coordsi[4];
+ } linear;
+ struct {
+ VGfloat vals[5];
+ VGint valsi[5];
+ } radial;
+ struct pipe_texture *texture;
+ struct pipe_sampler_state sampler;
+
+ VGfloat *ramp_stops;
+ VGint *ramp_stopsi;
+ VGint num_stops;
+
+ VGboolean color_ramps_premultiplied;
+ } gradient;
+
+ struct {
+ struct pipe_texture *texture;
+ VGTilingMode tiling_mode;
+ struct pipe_sampler_state sampler;
+ } pattern;
+
+ struct pipe_constant_buffer cbuf;
+ struct pipe_shader_state fs_state;
+ void *fs;
+};
+
+static INLINE VGuint mix_pixels(VGuint p1, VGuint a, VGuint p2, VGuint b)
+{
+ VGuint t = (p1 & 0xff00ff) * a + (p2 & 0xff00ff) * b;
+ t >>= 8; t &= 0xff00ff;
+
+ p1 = ((p1 >> 8) & 0xff00ff) * a + ((p2 >> 8) & 0xff00ff) * b;
+ p1 &= 0xff00ff00; p1 |= t;
+
+ return p1;
+}
+
+static INLINE VGuint float4_to_argb(const VGfloat *clr)
+{
+ return float_to_ubyte(clr[3]) << 24 |
+ float_to_ubyte(clr[0]) << 16 |
+ float_to_ubyte(clr[1]) << 8 |
+ float_to_ubyte(clr[2]) << 0;
+}
+
+static INLINE void create_gradient_data(const VGfloat *ramp_stops,
+ VGint num,
+ VGuint *data,
+ VGint size)
+{
+ VGint i;
+ VGint pos = 0;
+ VGfloat fpos = 0, incr = 1.f / size;
+ VGuint last_color;
+
+ while (fpos < ramp_stops[0]) {
+ data[pos] = float4_to_argb(ramp_stops + 1);
+ fpos += incr;
+ ++pos;
+ }
+
+ for (i = 0; i < num - 1; ++i) {
+ VGint rcur = 5 * i;
+ VGint rnext = 5 * (i + 1);
+ VGfloat delta = 1.f/(ramp_stops[rnext] - ramp_stops[rcur]);
+ while (fpos < ramp_stops[rnext] && pos < size) {
+ VGint dist = 256 * ((fpos - ramp_stops[rcur]) * delta);
+ VGint idist = 256 - dist;
+ VGuint current_color = float4_to_argb(ramp_stops + rcur + 1);
+ VGuint next_color = float4_to_argb(ramp_stops + rnext + 1);
+ data[pos] = mix_pixels(current_color, idist,
+ next_color, dist);
+ fpos += incr;
+ ++pos;
+ }
+ }
+
+ last_color = float4_to_argb(ramp_stops + ((num - 1) * 5 + 1));
+ while (pos < size) {
+ data[pos] = last_color;
+ ++pos;
+ }
+ data[size-1] = last_color;
+}
+
+static INLINE struct pipe_texture *create_gradient_texture(struct vg_paint *p)
+{
+ struct pipe_context *pipe = p->base.ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture *tex = 0;
+ struct pipe_texture templ;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_1D;
+ templ.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ templ.last_level = 0;
+ templ.width[0] = 1024;
+ templ.height[0] = 1;
+ templ.depth[0] = 1;
+ pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &templ.block);
+ templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+
+ tex = screen->texture_create(screen, &templ);
+
+ { /* upload color_data */
+ struct pipe_transfer *transfer =
+ st_no_flush_get_tex_transfer(p->base.ctx, tex, 0, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0, 1024, 1);
+ void *map = screen->transfer_map(screen, transfer);
+ memcpy(map, p->gradient.color_data, sizeof(VGint)*1024);
+ screen->transfer_unmap(screen, transfer);
+ screen->tex_transfer_destroy(transfer);
+ }
+
+ return tex;
+}
+
+struct vg_paint * paint_create(struct vg_context *ctx)
+{
+ struct vg_paint *paint = CALLOC_STRUCT(vg_paint);
+ const VGfloat default_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
+ const VGfloat def_ling[] = {0.0f, 0.0f, 1.0f, 0.0f};
+ const VGfloat def_radg[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+ vg_init_object(&paint->base, ctx, VG_OBJECT_PAINT);
+ vg_context_add_object(ctx, VG_OBJECT_PAINT, paint);
+
+ paint->type = VG_PAINT_TYPE_COLOR;
+ memcpy(paint->solid.color, default_color,
+ 4 * sizeof(VGfloat));
+ paint->gradient.spread = VG_COLOR_RAMP_SPREAD_PAD;
+ memcpy(paint->gradient.linear.coords, def_ling,
+ 4 * sizeof(VGfloat));
+ memcpy(paint->gradient.radial.vals, def_radg,
+ 5 * sizeof(VGfloat));
+
+ paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ paint->gradient.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ paint->gradient.sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ paint->gradient.sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ paint->gradient.sampler.normalized_coords = 1;
+
+ memcpy(&paint->pattern.sampler,
+ &paint->gradient.sampler,
+ sizeof(struct pipe_sampler_state));
+
+ return paint;
+}
+
+void paint_destroy(struct vg_paint *paint)
+{
+ struct vg_context *ctx = paint->base.ctx;
+ if (paint->pattern.texture)
+ pipe_texture_reference(&paint->pattern.texture, NULL);
+ if (ctx)
+ vg_context_remove_object(ctx, VG_OBJECT_PAINT, paint);
+
+ free(paint->gradient.ramp_stopsi);
+ free(paint->gradient.ramp_stops);
+ free(paint);
+}
+
+void paint_set_color(struct vg_paint *paint,
+ const VGfloat *color)
+{
+ paint->solid.color[0] = color[0];
+ paint->solid.color[1] = color[1];
+ paint->solid.color[2] = color[2];
+ paint->solid.color[3] = color[3];
+
+ paint->solid.colori[0] = FLT_TO_INT(color[0]);
+ paint->solid.colori[1] = FLT_TO_INT(color[1]);
+ paint->solid.colori[2] = FLT_TO_INT(color[2]);
+ paint->solid.colori[3] = FLT_TO_INT(color[3]);
+}
+
+static INLINE void paint_color_buffer(struct vg_paint *paint, void *buffer)
+{
+ VGfloat *map = (VGfloat*)buffer;
+ memcpy(buffer, paint->solid.color, 4 * sizeof(VGfloat));
+ map[4] = 0.f;
+ map[5] = 1.f;
+ map[6] = 2.f;
+ map[7] = 4.f;
+}
+
+static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *buffer)
+{
+ struct vg_context *ctx = paint->base.ctx;
+ VGfloat *map = (VGfloat*)buffer;
+
+ map[0] = paint->gradient.linear.coords[2] - paint->gradient.linear.coords[0];
+ map[1] = paint->gradient.linear.coords[3] - paint->gradient.linear.coords[1];
+ map[2] = 1.f / (map[0] * map[0] + map[1] * map[1]);
+ map[3] = 1.f;
+
+ map[4] = 0.f;
+ map[5] = 1.f;
+ map[6] = 2.f;
+ map[7] = 4.f;
+ {
+ struct matrix mat;
+ struct matrix inv;
+ matrix_load_identity(&mat);
+ matrix_translate(&mat, -paint->gradient.linear.coords[0], -paint->gradient.linear.coords[1]);
+ memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
+ sizeof(struct matrix));
+ matrix_invert(&inv);
+ matrix_mult(&inv, &mat);
+ memcpy(&mat, &inv,
+ sizeof(struct matrix));
+
+ map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
+ map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
+ map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
+ }
+#if 0
+ debug_printf("Coords (%f, %f, %f, %f)\n",
+ map[0], map[1], map[2], map[3]);
+#endif
+}
+
+
+static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *buffer)
+{
+ VGfloat *radialCoords = paint->gradient.radial.vals;
+ struct vg_context *ctx = paint->base.ctx;
+
+ VGfloat *map = (VGfloat*)buffer;
+
+ map[0] = radialCoords[0] - radialCoords[2];
+ map[1] = radialCoords[1] - radialCoords[3];
+ map[2] = -map[0] * map[0] - map[1] * map[1] +
+ radialCoords[4] * radialCoords[4];
+ map[3] = 1.f;
+
+ map[4] = 0.f;
+ map[5] = 1.f;
+ map[6] = 2.f;
+ map[7] = 4.f;
+
+ {
+ struct matrix mat;
+ struct matrix inv;
+ matrix_load_identity(&mat);
+ matrix_translate(&mat, -radialCoords[2], -radialCoords[3]);
+ memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
+ sizeof(struct matrix));
+ matrix_invert(&inv);
+ matrix_mult(&inv, &mat);
+ memcpy(&mat, &inv,
+ sizeof(struct matrix));
+
+ map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
+ map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
+ map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
+ }
+
+#if 0
+ debug_printf("Coords (%f, %f, %f, %f)\n",
+ map[0], map[1], map[2], map[3]);
+#endif
+}
+
+
+static INLINE void paint_pattern_buffer(struct vg_paint *paint, void *buffer)
+{
+ struct vg_context *ctx = paint->base.ctx;
+
+ VGfloat *map = (VGfloat *)buffer;
+ memcpy(map, paint->solid.color, 4 * sizeof(VGfloat));
+
+ map[4] = 0.f;
+ map[5] = 1.f;
+ map[6] = paint->pattern.texture->width[0];
+ map[7] = paint->pattern.texture->height[0];
+ {
+ struct matrix mat;
+ memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix,
+ sizeof(struct matrix));
+ matrix_invert(&mat);
+ {
+ struct matrix pm;
+ memcpy(&pm, &ctx->state.vg.path_user_to_surface_matrix,
+ sizeof(struct matrix));
+ matrix_invert(&pm);
+ matrix_mult(&pm, &mat);
+ memcpy(&mat, &pm, sizeof(struct matrix));
+ }
+
+ map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
+ map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
+ map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
+ }
+}
+
+void paint_set_type(struct vg_paint *paint, VGPaintType type)
+{
+ paint->type = type;
+}
+
+void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops,
+ int num)
+{
+ const VGfloat default_stops[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+ VGint i;
+ const VGint num_stops = num / 5;
+ VGfloat last_coord;
+
+ paint->gradient.num_stops = num;
+ if (num) {
+ free(paint->gradient.ramp_stops);
+ paint->gradient.ramp_stops = malloc(sizeof(VGfloat)*num);
+ memcpy(paint->gradient.ramp_stops, stops, sizeof(VGfloat)*num);
+ } else
+ return;
+
+ /* stops must be in increasing order. the last stop is 1.0. if the
+ * first one is bigger than 1 then the whole sequence is invalid*/
+ if (stops[0] > 1) {
+ stops = default_stops;
+ num = 10;
+ }
+ last_coord = stops[0];
+ for (i = 1; i < num_stops; ++i) {
+ VGint idx = 5 * i;
+ VGfloat coord = stops[idx];
+ if (!floatsEqual(last_coord, coord) && coord < last_coord) {
+ stops = default_stops;
+ num = 10;
+ break;
+ }
+ last_coord = coord;
+ }
+
+ create_gradient_data(stops, num / 5, paint->gradient.color_data,
+ 1024);
+
+ if (paint->gradient.texture) {
+ pipe_texture_reference(&paint->gradient.texture, NULL);
+ paint->gradient.texture = 0;
+ }
+
+ paint->gradient.texture = create_gradient_texture(paint);
+}
+
+void paint_set_colori(struct vg_paint *p,
+ VGuint rgba)
+{
+ p->solid.color[0] = ((rgba >> 24) & 0xff) / 255.f;
+ p->solid.color[1] = ((rgba >> 16) & 0xff) / 255.f;
+ p->solid.color[2] = ((rgba >> 8) & 0xff) / 255.f;
+ p->solid.color[3] = ((rgba >> 0) & 0xff) / 255.f;
+}
+
+VGuint paint_colori(struct vg_paint *p)
+{
+#define F2B(f) (float_to_ubyte(f))
+
+ return ((F2B(p->solid.color[0]) << 24) |
+ (F2B(p->solid.color[1]) << 16) |
+ (F2B(p->solid.color[2]) << 8) |
+ (F2B(p->solid.color[3]) << 0));
+#undef F2B
+}
+
+void paint_set_linear_gradient(struct vg_paint *paint,
+ const VGfloat *coords)
+{
+ memcpy(paint->gradient.linear.coords, coords, sizeof(VGfloat) * 4);
+}
+
+void paint_set_spread_mode(struct vg_paint *paint,
+ VGint mode)
+{
+ paint->gradient.spread = mode;
+ switch(mode) {
+ case VG_COLOR_RAMP_SPREAD_PAD:
+ paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ break;
+ case VG_COLOR_RAMP_SPREAD_REPEAT:
+ paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
+ break;
+ case VG_COLOR_RAMP_SPREAD_REFLECT:
+ paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
+ break;
+ }
+}
+
+VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint)
+{
+ return paint->gradient.spread;
+}
+
+void paint_set_radial_gradient(struct vg_paint *paint,
+ const VGfloat *values)
+{
+ memcpy(paint->gradient.radial.vals, values, sizeof(VGfloat) * 5);
+}
+
+void paint_set_pattern(struct vg_paint *paint,
+ struct vg_image *img)
+{
+ if (paint->pattern.texture)
+ pipe_texture_reference(&paint->pattern.texture, NULL);
+
+ paint->pattern.texture = 0;
+ pipe_texture_reference(&paint->pattern.texture,
+ img->texture);
+}
+
+void paint_set_pattern_tiling(struct vg_paint *paint,
+ VGTilingMode mode)
+{
+ paint->pattern.tiling_mode = mode;
+
+ switch(mode) {
+ case VG_TILE_FILL:
+ paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ break;
+ case VG_TILE_PAD:
+ paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ break;
+ case VG_TILE_REPEAT:
+ paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
+ paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
+ break;
+ case VG_TILE_REFLECT:
+ paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
+ paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT;
+ break;
+ default:
+ debug_assert("!Unknown tiling mode");
+ }
+}
+
+void paint_get_color(struct vg_paint *paint,
+ VGfloat *color)
+{
+ color[0] = paint->solid.color[0];
+ color[1] = paint->solid.color[1];
+ color[2] = paint->solid.color[2];
+ color[3] = paint->solid.color[3];
+}
+
+void paint_ramp_stops(struct vg_paint *paint, VGfloat *stops,
+ int num)
+{
+ memcpy(stops, paint->gradient.ramp_stops, sizeof(VGfloat)*num);
+}
+
+void paint_linear_gradient(struct vg_paint *paint,
+ VGfloat *coords)
+{
+ memcpy(coords, paint->gradient.linear.coords, sizeof(VGfloat)*4);
+}
+
+void paint_radial_gradient(struct vg_paint *paint,
+ VGfloat *coords)
+{
+ memcpy(coords, paint->gradient.radial.vals, sizeof(VGfloat)*5);
+}
+
+int paint_num_ramp_stops(struct vg_paint *paint)
+{
+ return paint->gradient.num_stops;
+}
+
+VGPaintType paint_type(struct vg_paint *paint)
+{
+ return paint->type;
+}
+
+void paint_set_coloriv(struct vg_paint *paint,
+ const VGint *color)
+{
+ paint->solid.color[0] = color[0];
+ paint->solid.color[1] = color[1];
+ paint->solid.color[2] = color[2];
+ paint->solid.color[3] = color[3];
+
+ paint->solid.colori[0] = color[0];
+ paint->solid.colori[1] = color[1];
+ paint->solid.colori[2] = color[2];
+ paint->solid.colori[3] = color[3];
+}
+
+void paint_get_coloriv(struct vg_paint *paint,
+ VGint *color)
+{
+ color[0] = paint->solid.colori[0];
+ color[1] = paint->solid.colori[1];
+ color[2] = paint->solid.colori[2];
+ color[3] = paint->solid.colori[3];
+}
+
+void paint_set_color_ramp_premultiplied(struct vg_paint *paint,
+ VGboolean set)
+{
+ paint->gradient.color_ramps_premultiplied = set;
+}
+
+VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint)
+{
+ return paint->gradient.color_ramps_premultiplied;
+}
+
+void paint_set_ramp_stopsi(struct vg_paint *paint, const VGint *stops,
+ int num)
+{
+ if (num) {
+ free(paint->gradient.ramp_stopsi);
+ paint->gradient.ramp_stopsi = malloc(sizeof(VGint)*num);
+ memcpy(paint->gradient.ramp_stopsi, stops, sizeof(VGint)*num);
+ }
+}
+
+void paint_ramp_stopsi(struct vg_paint *paint, VGint *stops,
+ int num)
+{
+ memcpy(stops, paint->gradient.ramp_stopsi, sizeof(VGint)*num);
+}
+
+void paint_set_linear_gradienti(struct vg_paint *paint,
+ const VGint *coords)
+{
+ memcpy(paint->gradient.linear.coordsi, coords, sizeof(VGint) * 4);
+}
+
+void paint_linear_gradienti(struct vg_paint *paint,
+ VGint *coords)
+{
+ memcpy(coords, paint->gradient.linear.coordsi, sizeof(VGint)*4);
+}
+
+void paint_set_radial_gradienti(struct vg_paint *paint,
+ const VGint *values)
+{
+ memcpy(paint->gradient.radial.valsi, values, sizeof(VGint) * 5);
+}
+
+void paint_radial_gradienti(struct vg_paint *paint,
+ VGint *coords)
+{
+ memcpy(coords, paint->gradient.radial.valsi, sizeof(VGint)*5);
+}
+
+VGTilingMode paint_pattern_tiling(struct vg_paint *paint)
+{
+ return paint->pattern.tiling_mode;
+}
+
+VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers,
+ struct pipe_texture **textures)
+{
+ struct vg_context *ctx = vg_current_context();
+
+ switch(paint->type) {
+ case VG_PAINT_TYPE_LINEAR_GRADIENT:
+ case VG_PAINT_TYPE_RADIAL_GRADIENT: {
+ if (paint->gradient.texture) {
+ paint->gradient.sampler.min_img_filter = image_sampler_filter(ctx);
+ paint->gradient.sampler.mag_img_filter = image_sampler_filter(ctx);
+ samplers[0] = &paint->gradient.sampler;
+ textures[0] = paint->gradient.texture;
+ return 1;
+ }
+ }
+ break;
+ case VG_PAINT_TYPE_PATTERN: {
+ memcpy(paint->pattern.sampler.border_color,
+ ctx->state.vg.tile_fill_color,
+ sizeof(VGfloat) * 4);
+ paint->pattern.sampler.min_img_filter = image_sampler_filter(ctx);
+ paint->pattern.sampler.mag_img_filter = image_sampler_filter(ctx);
+ samplers[0] = &paint->pattern.sampler;
+ textures[0] = paint->pattern.texture;
+ return 1;
+ }
+ break;
+ default:
+ samplers[0] = &paint->pattern.sampler; /* dummy */
+ textures[0] = 0;
+ return 0;
+ break;
+ }
+ return 0;
+}
+
+void paint_resolve_type(struct vg_paint *paint)
+{
+ if (paint->type == VG_PAINT_TYPE_PATTERN &&
+ !paint->pattern.texture) {
+ paint->type = VG_PAINT_TYPE_COLOR;
+ }
+}
+
+VGint paint_constant_buffer_size(struct vg_paint *paint)
+{
+ switch(paint->type) {
+ case VG_PAINT_TYPE_COLOR:
+ return 8 * sizeof(VGfloat);/*4 color + 4 constants (0.f,1.f,2.f,4.f)*/
+ break;
+ case VG_PAINT_TYPE_LINEAR_GRADIENT:
+ return 20 * sizeof(VGfloat);
+ break;
+ case VG_PAINT_TYPE_RADIAL_GRADIENT:
+ return 20 * sizeof(VGfloat);
+ break;
+ case VG_PAINT_TYPE_PATTERN:
+ return 20 * sizeof(VGfloat);
+ break;
+ default:
+ debug_printf("Uknown paint type: %d\n", paint->type);
+ }
+
+ return 0;
+}
+
+void paint_fill_constant_buffer(struct vg_paint *paint,
+ void *buffer)
+{
+ switch(paint->type) {
+ case VG_PAINT_TYPE_COLOR:
+ paint_color_buffer(paint, buffer);
+ break;
+ case VG_PAINT_TYPE_LINEAR_GRADIENT:
+ paint_linear_gradient_buffer(paint, buffer);
+ break;
+ case VG_PAINT_TYPE_RADIAL_GRADIENT:
+ paint_radial_gradient_buffer(paint, buffer);
+ break;
+ case VG_PAINT_TYPE_PATTERN:
+ paint_pattern_buffer(paint, buffer);
+ break;
+
+ default:
+ abort();
+ }
+}
diff --git a/src/gallium/state_trackers/vega/paint.h b/src/gallium/state_trackers/vega/paint.h
new file mode 100644
index 0000000000..999b5c167c
--- /dev/null
+++ b/src/gallium/state_trackers/vega/paint.h
@@ -0,0 +1,118 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PAINT_H
+#define PAINT_H
+
+#include "vg_context.h"
+
+#include "VG/openvg.h"
+#include "pipe/p_state.h"
+
+struct vg_paint;
+struct vg_image;
+struct pipe_sampler_state;
+struct pipe_texture;
+
+struct vg_paint *paint_create(struct vg_context *ctx);
+void paint_destroy(struct vg_paint *paint);
+
+void paint_set_color(struct vg_paint *paint,
+ const VGfloat *color);
+void paint_get_color(struct vg_paint *paint,
+ VGfloat *color);
+
+void paint_set_coloriv(struct vg_paint *paint,
+ const VGint *color);
+void paint_get_coloriv(struct vg_paint *paint,
+ VGint *color);
+
+void paint_set_colori(struct vg_paint *paint,
+ VGuint rgba);
+
+VGuint paint_colori(struct vg_paint *paint);
+
+void paint_set_type(struct vg_paint *paint, VGPaintType type);
+VGPaintType paint_type(struct vg_paint *paint);
+void paint_resolve_type(struct vg_paint *paint);
+
+void paint_set_linear_gradient(struct vg_paint *paint,
+ const VGfloat *coords);
+void paint_linear_gradient(struct vg_paint *paint,
+ VGfloat *coords);
+void paint_set_linear_gradienti(struct vg_paint *paint,
+ const VGint *coords);
+void paint_linear_gradienti(struct vg_paint *paint,
+ VGint *coords);
+
+
+void paint_set_radial_gradient(struct vg_paint *paint,
+ const VGfloat *values);
+void paint_radial_gradient(struct vg_paint *paint,
+ VGfloat *coords);
+void paint_set_radial_gradienti(struct vg_paint *paint,
+ const VGint *values);
+void paint_radial_gradienti(struct vg_paint *paint,
+ VGint *coords);
+
+
+void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops,
+ int num);
+void paint_ramp_stops(struct vg_paint *paint, VGfloat *stops,
+ int num);
+
+void paint_set_ramp_stopsi(struct vg_paint *paint, const VGint *stops,
+ int num);
+void paint_ramp_stopsi(struct vg_paint *paint, VGint *stops,
+ int num);
+
+int paint_num_ramp_stops(struct vg_paint *paint);
+
+void paint_set_spread_mode(struct vg_paint *paint,
+ VGint mode);
+VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint);
+
+
+void paint_set_pattern(struct vg_paint *paint,
+ struct vg_image *img);
+void paint_set_pattern_tiling(struct vg_paint *paint,
+ VGTilingMode mode);
+VGTilingMode paint_pattern_tiling(struct vg_paint *paint);
+
+void paint_set_color_ramp_premultiplied(struct vg_paint *paint,
+ VGboolean set);
+VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint);
+
+
+VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers,
+ struct pipe_texture **textures);
+
+VGint paint_constant_buffer_size(struct vg_paint *paint);
+void paint_fill_constant_buffer(struct vg_paint *paint,
+ void *buffer);
+
+
+#endif
diff --git a/src/gallium/state_trackers/vega/path.c b/src/gallium/state_trackers/vega/path.c
new file mode 100644
index 0000000000..4fc23a7a27
--- /dev/null
+++ b/src/gallium/state_trackers/vega/path.c
@@ -0,0 +1,2034 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "path.h"
+
+#include "stroker.h"
+#include "polygon.h"
+#include "bezier.h"
+#include "matrix.h"
+#include "vg_context.h"
+#include "util_array.h"
+#include "arc.h"
+#include "path_utils.h"
+#include "paint.h"
+#include "shader.h"
+
+#include "util/u_memory.h"
+
+#include <assert.h>
+
+#define DEBUG_PATH 0
+
+struct path {
+ struct vg_object base;
+ VGbitfield caps;
+ VGboolean dirty;
+ VGboolean dirty_stroke;
+
+ VGPathDatatype datatype;
+
+ VGfloat scale;
+ VGfloat bias;
+
+ VGint num_segments;
+
+ struct array * segments;
+ struct array * control_points;
+
+ struct {
+ struct polygon_array polygon_array;
+ struct matrix matrix;
+ } fill_polys;
+
+ struct {
+ struct path *path;
+ struct matrix matrix;
+ VGfloat stroke_width;
+ VGfloat miter_limit;
+ VGCapStyle cap_style;
+ VGJoinStyle join_style;
+ } stroked;
+};
+
+
+static INLINE void data_at(void **data,
+ struct path *p,
+ VGint start, VGint count,
+ VGfloat *out)
+{
+ VGPathDatatype dt = p->datatype;
+ VGint i;
+ VGint end = start + count;
+ VGfloat *itr = out;
+
+ switch(dt) {
+ case VG_PATH_DATATYPE_S_8: {
+ VGbyte **bdata = (VGbyte **)data;
+ for (i = start; i < end; ++i) {
+ *itr = (*bdata)[i];
+ ++itr;
+ }
+ *bdata += count;
+ }
+ break;
+ case VG_PATH_DATATYPE_S_16: {
+ VGshort **bdata = (VGshort **)data;
+ for (i = start; i < end; ++i) {
+ *itr = (*bdata)[i];
+ ++itr;
+ }
+ *bdata += count;
+ }
+ break;
+ case VG_PATH_DATATYPE_S_32: {
+ VGint **bdata = (VGint **)data;
+ for (i = start; i < end; ++i) {
+ *itr = (*bdata)[i];
+ ++itr;
+ }
+ *bdata += count;
+ }
+ break;
+ case VG_PATH_DATATYPE_F: {
+ VGfloat **fdata = (VGfloat **)data;
+ for (i = start; i < end; ++i) {
+ *itr = (*fdata)[i];
+ ++itr;
+ }
+ *fdata += count;
+ }
+ break;
+ default:
+ debug_assert(!"Unknown path datatype!");
+ }
+}
+
+
+void vg_float_to_datatype(VGPathDatatype datatype,
+ VGubyte *common_data,
+ const VGfloat *data,
+ VGint num_coords)
+{
+ VGint i;
+ switch(datatype) {
+ case VG_PATH_DATATYPE_S_8: {
+ for (i = 0; i < num_coords; ++i) {
+ common_data[i] = (VGubyte)data[i];
+ }
+ }
+ break;
+ case VG_PATH_DATATYPE_S_16: {
+ VGshort *buf = (VGshort*)common_data;
+ for (i = 0; i < num_coords; ++i) {
+ buf[i] = (VGshort)data[i];
+ }
+ }
+ break;
+ case VG_PATH_DATATYPE_S_32: {
+ VGint *buf = (VGint*)common_data;
+ for (i = 0; i < num_coords; ++i) {
+ buf[i] = (VGint)data[i];
+ }
+ }
+ break;
+ case VG_PATH_DATATYPE_F: {
+ memcpy(common_data, data, sizeof(VGfloat) * num_coords);
+ }
+ break;
+ default:
+ debug_assert(!"Unknown path datatype!");
+ }
+}
+
+static void coords_adjust_by_scale_bias(struct path *p,
+ void *pdata, VGint num_coords,
+ VGfloat scale, VGfloat bias,
+ VGPathDatatype datatype)
+{
+ VGfloat data[8];
+ void *coords = (VGfloat *)pdata;
+ VGubyte *common_data = (VGubyte *)pdata;
+ VGint size_dst = size_for_datatype(datatype);
+ VGint i;
+
+ for (i = 0; i < num_coords; ++i) {
+ data_at(&coords, p, 0, 1, data);
+ data[0] = data[0] * scale + bias;
+ vg_float_to_datatype(datatype, common_data, data, 1);
+ common_data += size_dst;
+ }
+}
+
+struct path * path_create(VGPathDatatype dt, VGfloat scale, VGfloat bias,
+ VGint segmentCapacityHint,
+ VGint coordCapacityHint,
+ VGbitfield capabilities)
+{
+ struct path *path = CALLOC_STRUCT(path);
+
+ vg_init_object(&path->base, vg_current_context(), VG_OBJECT_PATH);
+ path->caps = capabilities & VG_PATH_CAPABILITY_ALL;
+ vg_context_add_object(vg_current_context(), VG_OBJECT_PATH, path);
+
+ path->datatype = dt;
+ path->scale = scale;
+ path->bias = bias;
+
+ path->segments = array_create(size_for_datatype(VG_PATH_DATATYPE_S_8));
+ path->control_points = array_create(size_for_datatype(dt));
+
+ path->dirty = VG_TRUE;
+ path->dirty_stroke = VG_TRUE;
+
+ return path;
+}
+
+void path_destroy(struct path *p)
+{
+ vg_context_remove_object(vg_current_context(), VG_OBJECT_PATH, p);
+
+ array_destroy(p->segments);
+ array_destroy(p->control_points);
+ array_destroy(p->fill_polys.polygon_array.array);
+
+ if (p->stroked.path)
+ path_destroy(p->stroked.path);
+
+ free(p);
+}
+
+VGbitfield path_capabilities(struct path *p)
+{
+ return p->caps;
+}
+
+void path_set_capabilities(struct path *p, VGbitfield bf)
+{
+ p->caps = (bf & VG_PATH_CAPABILITY_ALL);
+}
+
+void path_append_data(struct path *p,
+ VGint numSegments,
+ const VGubyte * pathSegments,
+ const void * pathData)
+{
+ VGint old_segments = p->num_segments;
+ VGint num_new_coords = num_elements_for_segments(pathSegments, numSegments);
+ array_append_data(p->segments, pathSegments, numSegments);
+ array_append_data(p->control_points, pathData, num_new_coords);
+
+ p->num_segments += numSegments;
+ if (!floatsEqual(p->scale, 1.f) || !floatsEqual(p->bias, 0.f)) {
+ VGubyte *coords = (VGubyte*)p->control_points->data;
+ coords_adjust_by_scale_bias(p,
+ coords + old_segments * p->control_points->datatype_size,
+ num_new_coords,
+ p->scale, p->bias, p->datatype);
+ }
+ p->dirty = VG_TRUE;
+ p->dirty_stroke = VG_TRUE;
+}
+
+VGint path_num_segments(struct path *p)
+{
+ return p->num_segments;
+}
+
+static INLINE void map_if_relative(VGfloat ox, VGfloat oy,
+ VGboolean relative,
+ VGfloat *x, VGfloat *y)
+{
+ if (relative) {
+ if (x)
+ *x += ox;
+ if (y)
+ *y += oy;
+ }
+}
+
+static INLINE void close_polygon(struct polygon *current,
+ VGfloat sx, VGfloat sy,
+ VGfloat ox, VGfloat oy,
+ struct matrix *matrix)
+{
+ if (!floatsEqual(sx, ox) ||
+ !floatsEqual(sy, oy)) {
+ VGfloat x0 = sx;
+ VGfloat y0 = sy;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ polygon_vertex_append(current, x0, y0);
+ }
+}
+
+static void convert_path(struct path *p,
+ VGPathDatatype to,
+ void *dst,
+ VGint num_coords)
+{
+ VGfloat data[8];
+ void *coords = (VGfloat *)p->control_points->data;
+ VGubyte *common_data = (VGubyte *)dst;
+ VGint size_dst = size_for_datatype(to);
+ VGint i;
+
+ for (i = 0; i < num_coords; ++i) {
+ data_at(&coords, p, 0, 1, data);
+ vg_float_to_datatype(to, common_data, data, 1);
+ common_data += size_dst;
+ }
+}
+
+
+static void polygon_array_calculate_bounds( struct polygon_array *polyarray )
+{
+ struct array *polys = polyarray->array;
+ VGfloat min_x, max_x;
+ VGfloat min_y, max_y;
+ VGfloat bounds[4];
+ unsigned i;
+
+ assert(polys);
+ assert(polys->num_elements);
+ polygon_bounding_rect((((struct polygon**)polys->data)[0]), bounds);
+ min_x = bounds[0];
+ min_y = bounds[1];
+ max_x = bounds[0] + bounds[2];
+ max_y = bounds[1] + bounds[3];
+ for (i = 1; i < polys->num_elements; ++i) {
+ struct polygon *p = (((struct polygon**)polys->data)[i]);
+ polygon_bounding_rect(p, bounds);
+ min_x = MIN2(min_x, bounds[0]);
+ min_y = MIN2(min_y, bounds[1]);
+ max_x = MAX2(max_x, bounds[0] + bounds[2]);
+ max_y = MAX2(max_y, bounds[1] + bounds[3]);
+ }
+
+ polyarray->min_x = min_x;
+ polyarray->min_y = min_y;
+ polyarray->max_x = max_x;
+ polyarray->max_y = max_y;
+}
+
+
+static struct polygon_array * path_get_fill_polygons(struct path *p, struct matrix *matrix)
+{
+ VGint i;
+ struct polygon *current = 0;
+ VGfloat sx, sy, px, py, ox, oy;
+ VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
+ VGfloat data[8];
+ void *coords = (VGfloat *)p->control_points->data;
+ struct array *array;
+
+ if (p->fill_polys.polygon_array.array)
+ {
+ if (memcmp( &p->fill_polys.matrix,
+ matrix,
+ sizeof *matrix ) == 0 && p->dirty == VG_FALSE)
+ {
+ return &p->fill_polys.polygon_array;
+ }
+ else {
+ array_destroy( p->fill_polys.polygon_array.array );
+ p->fill_polys.polygon_array.array = NULL;
+ }
+ }
+
+ array = array_create(sizeof(struct array*));
+
+ sx = sy = px = py = ox = oy = 0.f;
+
+ current = polygon_create(32);
+
+ for (i = 0; i < p->num_segments; ++i) {
+ VGubyte segment = ((VGubyte*)(p->segments->data))[i];
+ VGint command = SEGMENT_COMMAND(segment);
+ VGboolean relative = SEGMENT_ABS_REL(segment);
+
+ switch(command) {
+ case VG_CLOSE_PATH:
+ close_polygon(current, sx, sy, ox, oy, matrix);
+ ox = sx;
+ oy = sy;
+ break;
+ case VG_MOVE_TO:
+ if (current && polygon_vertex_count(current) > 0) {
+ /* add polygon */
+ close_polygon(current, sx, sy, ox, oy, matrix);
+ array_append_data(array, &current, 1);
+ current = polygon_create(32);
+ }
+ data_at(&coords, p, 0, 2, data);
+ x0 = data[0];
+ y0 = data[1];
+ map_if_relative(ox, oy, relative, &x0, &y0);
+ sx = x0;
+ sy = y0;
+ ox = x0;
+ oy = y0;
+ px = x0;
+ py = y0;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ polygon_vertex_append(current, x0, y0);
+ break;
+ case VG_LINE_TO:
+ data_at(&coords, p, 0, 2, data);
+ x0 = data[0];
+ y0 = data[1];
+ map_if_relative(ox, oy, relative, &x0, &y0);
+ ox = x0;
+ oy = y0;
+ px = x0;
+ py = y0;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ polygon_vertex_append(current, x0, y0);
+ break;
+ case VG_HLINE_TO:
+ data_at(&coords, p, 0, 1, data);
+ x0 = data[0];
+ y0 = oy;
+ map_if_relative(ox, oy, relative, &x0, 0);
+ ox = x0;
+ px = x0;
+ py = y0;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ polygon_vertex_append(current, x0, y0);
+ break;
+ case VG_VLINE_TO:
+ data_at(&coords, p, 0, 1, data);
+ x0 = ox;
+ y0 = data[0];
+ map_if_relative(ox, oy, relative, 0, &y0);
+ oy = y0;
+ px = x0;
+ py = y0;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ polygon_vertex_append(current, x0, y0);
+ break;
+ case VG_CUBIC_TO: {
+ struct bezier bezier;
+ data_at(&coords, p, 0, 6, data);
+ x0 = ox;
+ y0 = oy;
+ x1 = data[0];
+ y1 = data[1];
+ x2 = data[2];
+ y2 = data[3];
+ x3 = data[4];
+ y3 = data[5];
+ map_if_relative(ox, oy, relative, &x1, &y1);
+ map_if_relative(ox, oy, relative, &x2, &y2);
+ map_if_relative(ox, oy, relative, &x3, &y3);
+ ox = x3;
+ oy = y3;
+ px = x2;
+ py = y2;
+ assert(matrix_is_affine(matrix));
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ matrix_map_point(matrix, x2, y2, &x2, &y2);
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ bezier_init(&bezier, x0, y0, x1, y1,
+ x2, y2, x3, y3);
+ bezier_add_to_polygon(&bezier, current);
+ }
+ break;
+ case VG_QUAD_TO: {
+ struct bezier bezier;
+ data_at(&coords, p, 0, 4, data);
+ x0 = ox;
+ y0 = oy;
+ x1 = data[0];
+ y1 = data[1];
+ x3 = data[2];
+ y3 = data[3];
+ map_if_relative(ox, oy, relative, &x1, &y1);
+ map_if_relative(ox, oy, relative, &x3, &y3);
+ px = x1;
+ py = y1;
+ { /* form a cubic out of it */
+ x2 = (x3 + 2*x1) / 3.f;
+ y2 = (y3 + 2*y1) / 3.f;
+ x1 = (x0 + 2*x1) / 3.f;
+ y1 = (y0 + 2*y1) / 3.f;
+ }
+ ox = x3;
+ oy = y3;
+ assert(matrix_is_affine(matrix));
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ matrix_map_point(matrix, x2, y2, &x2, &y2);
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ bezier_init(&bezier, x0, y0, x1, y1,
+ x2, y2, x3, y3);
+ bezier_add_to_polygon(&bezier, current);
+ }
+ break;
+ case VG_SQUAD_TO: {
+ struct bezier bezier;
+ data_at(&coords, p, 0, 2, data);
+ x0 = ox;
+ y0 = oy;
+ x1 = 2*ox-px;
+ y1 = 2*oy-py;
+ x3 = data[0];
+ y3 = data[1];
+ map_if_relative(ox, oy, relative, &x3, &y3);
+ px = x1;
+ py = y1;
+ { /* form a cubic out of it */
+ x2 = (x3 + 2*x1) / 3.f;
+ y2 = (y3 + 2*y1) / 3.f;
+ x1 = (x0 + 2*x1) / 3.f;
+ y1 = (y0 + 2*y1) / 3.f;
+ }
+ ox = x3;
+ oy = y3;
+ assert(matrix_is_affine(matrix));
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ matrix_map_point(matrix, x2, y2, &x2, &y2);
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ bezier_init(&bezier, x0, y0, x1, y1,
+ x2, y2, x3, y3);
+ bezier_add_to_polygon(&bezier, current);
+ }
+ break;
+ case VG_SCUBIC_TO: {
+ struct bezier bezier;
+ data_at(&coords, p, 0, 4, data);
+ x0 = ox;
+ y0 = oy;
+ x1 = 2*ox-px;
+ y1 = 2*oy-py;
+ x2 = data[0];
+ y2 = data[1];
+ x3 = data[2];
+ y3 = data[3];
+ map_if_relative(ox, oy, relative, &x2, &y2);
+ map_if_relative(ox, oy, relative, &x3, &y3);
+ ox = x3;
+ oy = y3;
+ px = x2;
+ py = y2;
+ assert(matrix_is_affine(matrix));
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ matrix_map_point(matrix, x2, y2, &x2, &y2);
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ bezier_init(&bezier, x0, y0, x1, y1,
+ x2, y2, x3, y3);
+ bezier_add_to_polygon(&bezier, current);
+ }
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO: {
+ VGfloat rh, rv, rot;
+ struct arc arc;
+
+ data_at(&coords, p, 0, 5, data);
+ x0 = ox;
+ y0 = oy;
+ rh = data[0];
+ rv = data[1];
+ rot = data[2];
+ x1 = data[3];
+ y1 = data[4];
+ map_if_relative(ox, oy, relative, &x1, &y1);
+#if 0
+ debug_printf("------- ARC (%f, %f), (%f, %f) %f, %f, %f\n",
+ x0, y0, x1, y1, rh, rv, rot);
+#endif
+ arc_init(&arc, command, x0, y0, x1, y1,
+ rh, rv, rot);
+ arc_add_to_polygon(&arc, current,
+ matrix);
+ ox = x1;
+ oy = y1;
+ px = x1;
+ py = y1;
+ }
+ break;
+ default:
+ abort();
+ assert(!"Unknown segment!");
+ }
+ }
+ if (current) {
+ if (polygon_vertex_count(current) > 0) {
+ close_polygon(current, sx, sy, ox, oy, matrix);
+ array_append_data(array, &current, 1);
+ } else
+ polygon_destroy(current);
+ }
+
+ p->fill_polys.polygon_array.array = array;
+ p->fill_polys.matrix = *matrix;
+
+ polygon_array_calculate_bounds( &p->fill_polys.polygon_array );
+
+ p->dirty = VG_FALSE;
+
+ return &p->fill_polys.polygon_array;
+}
+
+VGbyte path_datatype_size(struct path *p)
+{
+ return size_for_datatype(p->datatype);
+}
+
+VGPathDatatype path_datatype(struct path *p)
+{
+ return p->datatype;
+}
+
+VGfloat path_scale(struct path *p)
+{
+ return p->scale;
+}
+
+VGfloat path_bias(struct path *p)
+{
+ return p->bias;
+}
+
+VGint path_num_coords(struct path *p)
+{
+ return num_elements_for_segments((VGubyte*)p->segments->data,
+ p->num_segments);
+}
+
+void path_modify_coords(struct path *p,
+ VGint startIndex,
+ VGint numSegments,
+ const void * pathData)
+{
+ VGubyte *segments = (VGubyte*)(p->segments->data);
+ VGint count = num_elements_for_segments(&segments[startIndex], numSegments);
+ VGint start_cp = num_elements_for_segments(segments, startIndex);
+
+ array_change_data(p->control_points, pathData, start_cp, count);
+ coords_adjust_by_scale_bias(p,
+ ((VGubyte*)p->control_points->data) +
+ (startIndex * p->control_points->datatype_size),
+ path_num_coords(p),
+ p->scale, p->bias, p->datatype);
+ p->dirty = VG_TRUE;
+ p->dirty_stroke = VG_TRUE;
+}
+
+void path_for_each_segment(struct path *path,
+ path_for_each_cb cb,
+ void *user_data)
+{
+ VGint i;
+ struct path_for_each_data p;
+ VGfloat data[8];
+ void *coords = (VGfloat *)path->control_points->data;
+
+ p.coords = data;
+ p.sx = p.sy = p.px = p.py = p.ox = p.oy = 0.f;
+ p.user_data = user_data;
+
+ for (i = 0; i < path->num_segments; ++i) {
+ VGint command;
+ VGboolean relative;
+
+ p.segment = ((VGubyte*)(path->segments->data))[i];
+ command = SEGMENT_COMMAND(p.segment);
+ relative = SEGMENT_ABS_REL(p.segment);
+
+ switch(command) {
+ case VG_CLOSE_PATH:
+ cb(path, &p);
+ break;
+ case VG_MOVE_TO:
+ data_at(&coords, path, 0, 2, data);
+ map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
+ cb(path, &p);
+ p.sx = data[0];
+ p.sy = data[1];
+ p.ox = data[0];
+ p.oy = data[1];
+ p.px = data[0];
+ p.py = data[1];
+ break;
+ case VG_LINE_TO:
+ data_at(&coords, path, 0, 2, data);
+ map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
+ cb(path, &p);
+ p.ox = data[0];
+ p.oy = data[1];
+ p.px = data[0];
+ p.py = data[1];
+ break;
+ case VG_HLINE_TO:
+ data_at(&coords, path, 0, 1, data);
+ map_if_relative(p.ox, p.oy, relative, &data[0], 0);
+ p.segment = VG_LINE_TO;
+ data[1] = p.oy;
+ cb(path, &p);
+ p.ox = data[0];
+ p.oy = data[1];
+ p.px = data[0];
+ p.py = data[1];
+ break;
+ case VG_VLINE_TO:
+ data_at(&coords, path, 0, 1, data);
+ map_if_relative(p.ox, p.oy, relative, 0, &data[0]);
+ p.segment = VG_LINE_TO;
+ data[1] = data[0];
+ data[0] = p.ox;
+ cb(path, &p);
+ p.ox = data[0];
+ p.oy = data[1];
+ p.px = data[0];
+ p.py = data[1];
+ break;
+ case VG_CUBIC_TO: {
+ data_at(&coords, path, 0, 6, data);
+ map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
+ map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]);
+ map_if_relative(p.ox, p.oy, relative, &data[4], &data[5]);
+ cb(path, &p);
+ p.px = data[2];
+ p.py = data[3];
+ p.ox = data[4];
+ p.oy = data[5];
+ }
+ break;
+ case VG_QUAD_TO: {
+ data_at(&coords, path, 0, 4, data);
+ map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
+ map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]);
+ cb(path, &p);
+ p.px = data[0];
+ p.py = data[1];
+ p.ox = data[2];
+ p.oy = data[3];
+ }
+ break;
+ case VG_SQUAD_TO: {
+ data_at(&coords, path, 0, 2, data);
+ map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
+ cb(path, &p);
+ p.px = 2*p.ox-p.px;
+ p.py = 2*p.oy-p.py;
+ p.ox = data[2];
+ p.oy = data[3];
+ }
+ break;
+ case VG_SCUBIC_TO: {
+ data_at(&coords, path, 0, 4, data);
+ map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
+ map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]);
+ cb(path, &p);
+ p.px = data[0];
+ p.py = data[1];
+ p.ox = data[2];
+ p.oy = data[3];
+ }
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO: {
+ data_at(&coords, path, 0, 5, data);
+ map_if_relative(p.ox, p.oy, relative, &data[3], &data[4]);
+#if 0
+ debug_printf("------- ARC (%f, %f), (%f, %f) %f, %f, %f\n",
+ p.ox, p.oy, data[3], data[4], data[0], data[1], data[2]);
+#endif
+ cb(path, &p);
+ p.ox = data[3];
+ p.oy = data[4];
+ p.px = data[3];
+ p.py = data[4];
+ }
+ break;
+ default:
+ abort();
+ assert(!"Unknown segment!");
+ }
+ }
+}
+
+struct transform_data {
+ struct array *segments;
+ struct array *coords;
+
+ struct matrix *matrix;
+
+ VGPathDatatype datatype;
+};
+
+static VGboolean transform_cb(struct path *p,
+ struct path_for_each_data *pd)
+{
+ struct transform_data *td = (struct transform_data *)pd->user_data;
+ VGint num_coords = num_elements_for_segments(&pd->segment, 1);
+ VGubyte segment = SEGMENT_COMMAND(pd->segment);/* abs bit is 0 */
+ VGfloat data[8];
+ VGubyte common_data[sizeof(VGfloat)*8];
+
+ memcpy(data, pd->coords, sizeof(VGfloat) * num_coords);
+
+ switch(segment) {
+ case VG_CLOSE_PATH:
+ break;
+ case VG_MOVE_TO:
+ matrix_map_point(td->matrix,
+ data[0], data[1], &data[0], &data[1]);
+ break;
+ case VG_LINE_TO:
+ matrix_map_point(td->matrix,
+ data[0], data[1], &data[0], &data[1]);
+ break;
+ case VG_HLINE_TO:
+ case VG_VLINE_TO:
+ assert(0);
+ break;
+ case VG_QUAD_TO:
+ matrix_map_point(td->matrix,
+ data[0], data[1], &data[0], &data[1]);
+ matrix_map_point(td->matrix,
+ data[2], data[3], &data[2], &data[3]);
+ break;
+ case VG_CUBIC_TO:
+ matrix_map_point(td->matrix,
+ data[0], data[1], &data[0], &data[1]);
+ matrix_map_point(td->matrix,
+ data[2], data[3], &data[2], &data[3]);
+ matrix_map_point(td->matrix,
+ data[4], data[5], &data[4], &data[5]);
+ break;
+ case VG_SQUAD_TO:
+ matrix_map_point(td->matrix,
+ data[0], data[1], &data[0], &data[1]);
+ break;
+ case VG_SCUBIC_TO:
+ matrix_map_point(td->matrix,
+ data[0], data[1], &data[0], &data[1]);
+ matrix_map_point(td->matrix,
+ data[2], data[3], &data[2], &data[3]);
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO: {
+ struct arc arc;
+ struct path *path = path_create(td->datatype,
+ 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
+ arc_init(&arc, segment,
+ pd->ox, pd->oy, data[3], data[4],
+ data[0], data[1], data[2]);
+
+ arc_to_path(&arc, path, td->matrix);
+
+ num_coords = path_num_coords(path);
+
+ array_append_data(td->segments, path->segments->data,
+ path->num_segments);
+ array_append_data(td->coords, path->control_points->data,
+ num_coords);
+ path_destroy(path);
+
+ return VG_TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ vg_float_to_datatype(td->datatype, common_data, data, num_coords);
+
+ array_append_data(td->segments, &pd->segment, 1);
+ array_append_data(td->coords, common_data, num_coords);
+ return VG_TRUE;
+}
+
+void path_transform(struct path *dst, struct path *src)
+{
+ struct transform_data data;
+ struct vg_context *ctx = dst->base.ctx;
+
+ data.segments = dst->segments;
+ data.coords = dst->control_points;
+ data.matrix = &ctx->state.vg.path_user_to_surface_matrix;
+ data.datatype = dst->datatype;
+
+ path_for_each_segment(src, transform_cb, (void*)&data);
+
+ dst->num_segments = dst->segments->num_elements;
+ dst->dirty = VG_TRUE;
+ dst->dirty_stroke = VG_TRUE;
+}
+
+void path_append_path(struct path *dst,
+ struct path *src)
+{
+ VGint num_coords = path_num_coords(src);
+ void *dst_data = malloc(size_for_datatype(dst->datatype) * num_coords);
+ array_append_data(dst->segments,
+ src->segments->data,
+ src->num_segments);
+ convert_path(src, dst->datatype,
+ dst_data, num_coords);
+ array_append_data(dst->control_points,
+ dst_data,
+ num_coords);
+ free(dst_data);
+
+ dst->num_segments += src->num_segments;
+ dst->dirty = VG_TRUE;
+ dst->dirty_stroke = VG_TRUE;
+}
+
+static INLINE VGboolean is_segment_arc(VGubyte segment)
+{
+ VGubyte scommand = SEGMENT_COMMAND(segment);
+ return (scommand == VG_SCCWARC_TO ||
+ scommand == VG_SCWARC_TO ||
+ scommand == VG_LCCWARC_TO ||
+ scommand == VG_LCWARC_TO);
+}
+
+struct path_iter_data {
+ struct path *path;
+ VGubyte segment;
+ void *coords;
+ VGfloat px, py, ox, oy, sx, sy;
+};
+static INLINE VGubyte normalize_coords(struct path_iter_data *pd,
+ VGint *num_coords,
+ VGfloat *data)
+{
+ VGint command = SEGMENT_COMMAND(pd->segment);
+ VGboolean relative = SEGMENT_ABS_REL(pd->segment);
+
+ switch(command) {
+ case VG_CLOSE_PATH:
+ *num_coords = 0;
+ pd->ox = pd->sx;
+ pd->oy = pd->sy;
+ return VG_CLOSE_PATH;
+ break;
+ case VG_MOVE_TO:
+ data_at(&pd->coords, pd->path, 0, 2, data);
+ map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]);
+ pd->sx = data[0];
+ pd->sy = data[1];
+ pd->ox = data[0];
+ pd->oy = data[1];
+ pd->px = data[0];
+ pd->py = data[1];
+ *num_coords = 2;
+ return VG_MOVE_TO_ABS;
+ break;
+ case VG_LINE_TO:
+ data_at(&pd->coords, pd->path, 0, 2, data);
+ map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]);
+ pd->ox = data[0];
+ pd->oy = data[1];
+ pd->px = data[0];
+ pd->py = data[1];
+ *num_coords = 2;
+ return VG_LINE_TO_ABS;
+ break;
+ case VG_HLINE_TO:
+ data_at(&pd->coords, pd->path, 0, 1, data);
+ map_if_relative(pd->ox, pd->oy, relative, &data[0], 0);
+ data[1] = pd->oy;
+ pd->ox = data[0];
+ pd->oy = data[1];
+ pd->px = data[0];
+ pd->py = data[1];
+ *num_coords = 2;
+ return VG_LINE_TO_ABS;
+ break;
+ case VG_VLINE_TO:
+ data_at(&pd->coords, pd->path, 0, 1, data);
+ map_if_relative(pd->ox, pd->oy, relative, 0, &data[0]);
+ data[1] = data[0];
+ data[0] = pd->ox;
+ pd->ox = data[0];
+ pd->oy = data[1];
+ pd->px = data[0];
+ pd->py = data[1];
+ *num_coords = 2;
+ return VG_LINE_TO_ABS;
+ break;
+ case VG_CUBIC_TO: {
+ data_at(&pd->coords, pd->path, 0, 6, data);
+ map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]);
+ map_if_relative(pd->ox, pd->oy, relative, &data[2], &data[3]);
+ map_if_relative(pd->ox, pd->oy, relative, &data[4], &data[5]);
+ pd->px = data[2];
+ pd->py = data[3];
+ pd->ox = data[4];
+ pd->oy = data[5];
+ *num_coords = 6;
+ return VG_CUBIC_TO_ABS;
+ }
+ break;
+ case VG_QUAD_TO: {
+ VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
+ data_at(&pd->coords, pd->path, 0, 4, data);
+ x0 = pd->ox;
+ y0 = pd->oy;
+ x1 = data[0];
+ y1 = data[1];
+ x3 = data[2];
+ y3 = data[3];
+ map_if_relative(pd->ox, pd->oy, relative, &x1, &y1);
+ map_if_relative(pd->ox, pd->oy, relative, &x3, &y3);
+ pd->px = x1;
+ pd->py = y1;
+ { /* form a cubic out of it */
+ x2 = (x3 + 2*x1) / 3.f;
+ y2 = (y3 + 2*y1) / 3.f;
+ x1 = (x0 + 2*x1) / 3.f;
+ y1 = (y0 + 2*y1) / 3.f;
+ }
+ pd->ox = x3;
+ pd->oy = y3;
+ data[0] = x1;
+ data[1] = y1;
+ data[2] = x2;
+ data[3] = y2;
+ data[4] = x3;
+ data[5] = y3;
+ *num_coords = 6;
+ return VG_CUBIC_TO_ABS;
+ }
+ break;
+ case VG_SQUAD_TO: {
+ VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
+ data_at(&pd->coords, pd->path, 0, 2, data);
+ x0 = pd->ox;
+ y0 = pd->oy;
+ x1 = 2 * pd->ox - pd->px;
+ y1 = 2 * pd->oy - pd->py;
+ x3 = data[0];
+ y3 = data[1];
+ map_if_relative(pd->ox, pd->oy, relative, &x3, &y3);
+ pd->px = x1;
+ pd->py = y1;
+ { /* form a cubic out of it */
+ x2 = (x3 + 2*x1) / 3.f;
+ y2 = (y3 + 2*y1) / 3.f;
+ x1 = (x0 + 2*x1) / 3.f;
+ y1 = (y0 + 2*y1) / 3.f;
+ }
+ pd->ox = x3;
+ pd->oy = y3;
+ data[0] = x1;
+ data[1] = y1;
+ data[2] = x2;
+ data[3] = y2;
+ data[4] = x3;
+ data[5] = y3;
+ *num_coords = 6;
+ return VG_CUBIC_TO_ABS;
+ }
+ break;
+ case VG_SCUBIC_TO: {
+ VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
+ data_at(&pd->coords, pd->path, 0, 4, data);
+ x0 = pd->ox;
+ y0 = pd->oy;
+ x1 = 2*pd->ox-pd->px;
+ y1 = 2*pd->oy-pd->py;
+ x2 = data[0];
+ y2 = data[1];
+ x3 = data[2];
+ y3 = data[3];
+ map_if_relative(pd->ox, pd->oy, relative, &x2, &y2);
+ map_if_relative(pd->ox, pd->oy, relative, &x3, &y3);
+ pd->ox = x3;
+ pd->oy = y3;
+ pd->px = x2;
+ pd->py = y2;
+ data[0] = x1;
+ data[1] = y1;
+ data[2] = x2;
+ data[3] = y2;
+ data[4] = x3;
+ data[5] = y3;
+ *num_coords = 6;
+ return VG_CUBIC_TO_ABS;
+ }
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO: {
+ data_at(&pd->coords, pd->path, 0, 5, data);
+ map_if_relative(pd->ox, pd->oy, relative, &data[3], &data[4]);
+ pd->ox = data[3];
+ pd->oy = data[4];
+ pd->px = data[3];
+ pd->py = data[4];
+ *num_coords = 5;
+ return command | VG_ABSOLUTE;
+ }
+ break;
+ default:
+ abort();
+ assert(!"Unknown segment!");
+ }
+}
+
+static void linearly_interpolate(VGfloat *result,
+ const VGfloat *start,
+ const VGfloat *end,
+ VGfloat amount,
+ VGint number)
+{
+ VGint i;
+ for (i = 0; i < number; ++i) {
+ result[i] = start[i] + (end[i] - start[i]) * amount;
+ }
+}
+
+VGboolean path_interpolate(struct path *dst,
+ struct path *start, struct path *end,
+ VGfloat amount)
+{
+ /* temporary path that we can discard if it will turn
+ * out that start is not compatible with end */
+ struct path *res_path = path_create(dst->datatype,
+ 1.0, 0.0,
+ 0, 0, dst->caps);
+ VGint i;
+ VGfloat start_coords[8];
+ VGfloat end_coords[8];
+ VGfloat results[8];
+ VGubyte common_data[sizeof(VGfloat)*8];
+ struct path_iter_data start_iter, end_iter;
+
+ memset(&start_iter, 0, sizeof(struct path_iter_data));
+ memset(&end_iter, 0, sizeof(struct path_iter_data));
+
+ start_iter.path = start;
+ start_iter.coords = start->control_points->data;
+ end_iter.path = end;
+ end_iter.coords = end->control_points->data;
+
+ for (i = 0; i < start->num_segments; ++i) {
+ VGubyte segment;
+ VGubyte ssegment, esegment;
+ VGint snum_coords, enum_coords;
+ start_iter.segment = ((VGubyte*)(start->segments->data))[i];
+ end_iter.segment = ((VGubyte*)(end->segments->data))[i];
+
+ ssegment = normalize_coords(&start_iter, &snum_coords,
+ start_coords);
+ esegment = normalize_coords(&end_iter, &enum_coords,
+ end_coords);
+
+ if (is_segment_arc(ssegment)) {
+ if (!is_segment_arc(esegment)) {
+ path_destroy(res_path);
+ return VG_FALSE;
+ }
+ if (amount > 0.5)
+ segment = esegment;
+ else
+ segment = ssegment;
+ } else if (is_segment_arc(esegment)) {
+ path_destroy(res_path);
+ return VG_FALSE;
+ }
+ else if (ssegment != esegment) {
+ path_destroy(res_path);
+ return VG_FALSE;
+ }
+ else
+ segment = ssegment;
+
+ linearly_interpolate(results, start_coords, end_coords,
+ amount, snum_coords);
+ vg_float_to_datatype(dst->datatype, common_data, results, snum_coords);
+ path_append_data(res_path, 1, &segment, common_data);
+ }
+
+ path_append_path(dst, res_path);
+ path_destroy(res_path);
+
+ dst->dirty = VG_TRUE;
+ dst->dirty_stroke = VG_TRUE;
+
+ return VG_TRUE;
+}
+
+void path_clear(struct path *p, VGbitfield capabilities)
+{
+ path_set_capabilities(p, capabilities);
+ array_destroy(p->segments);
+ array_destroy(p->control_points);
+ p->segments = array_create(size_for_datatype(VG_PATH_DATATYPE_S_8));
+ p->control_points = array_create(size_for_datatype(p->datatype));
+ p->num_segments = 0;
+ p->dirty = VG_TRUE;
+ p->dirty_stroke = VG_TRUE;
+}
+
+struct path * path_create_stroke(struct path *p,
+ struct matrix *matrix)
+{
+ VGint i;
+ VGfloat sx, sy, px, py, ox, oy;
+ VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
+ VGfloat data[8];
+ void *coords = (VGfloat *)p->control_points->data;
+ int dashed = (p->base.ctx->state.vg.stroke.dash_pattern_num ? 1 : 0);
+ struct dash_stroker stroker;
+ struct vg_state *vg_state = &p->base.ctx->state.vg;
+
+ if (p->stroked.path)
+ {
+ /* ### compare the dash patterns to see if we can cache them.
+ * for now we simply always bail out if the path is dashed.
+ */
+ if (memcmp( &p->stroked.matrix,
+ matrix,
+ sizeof *matrix ) == 0 &&
+ !dashed && !p->dirty_stroke &&
+ floatsEqual(p->stroked.stroke_width, vg_state->stroke.line_width.f) &&
+ floatsEqual(p->stroked.miter_limit, vg_state->stroke.miter_limit.f) &&
+ p->stroked.cap_style == vg_state->stroke.cap_style &&
+ p->stroked.join_style == vg_state->stroke.join_style)
+ {
+ return p->stroked.path;
+ }
+ else {
+ path_destroy( p->stroked.path );
+ p->stroked.path = NULL;
+ }
+ }
+
+
+ sx = sy = px = py = ox = oy = 0.f;
+
+ if (dashed)
+ dash_stroker_init((struct stroker *)&stroker, vg_state);
+ else
+ stroker_init((struct stroker *)&stroker, vg_state);
+
+ stroker_begin((struct stroker *)&stroker);
+
+ for (i = 0; i < p->num_segments; ++i) {
+ VGubyte segment = ((VGubyte*)(p->segments->data))[i];
+ VGint command = SEGMENT_COMMAND(segment);
+ VGboolean relative = SEGMENT_ABS_REL(segment);
+
+ switch(command) {
+ case VG_CLOSE_PATH: {
+ VGfloat x0 = sx;
+ VGfloat y0 = sy;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ stroker_line_to((struct stroker *)&stroker, x0, y0);
+ }
+ break;
+ case VG_MOVE_TO:
+ data_at(&coords, p, 0, 2, data);
+ x0 = data[0];
+ y0 = data[1];
+ map_if_relative(ox, oy, relative, &x0, &y0);
+ sx = x0;
+ sy = y0;
+ ox = x0;
+ oy = y0;
+ px = x0;
+ py = y0;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ stroker_move_to((struct stroker *)&stroker, x0, y0);
+ break;
+ case VG_LINE_TO:
+ data_at(&coords, p, 0, 2, data);
+ x0 = data[0];
+ y0 = data[1];
+ map_if_relative(ox, oy, relative, &x0, &y0);
+ ox = x0;
+ oy = y0;
+ px = x0;
+ py = y0;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ stroker_line_to((struct stroker *)&stroker, x0, y0);
+ break;
+ case VG_HLINE_TO:
+ data_at(&coords, p, 0, 1, data);
+ x0 = data[0];
+ y0 = oy;
+ map_if_relative(ox, oy, relative, &x0, 0);
+ ox = x0;
+ px = x0;
+ py = y0;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ stroker_line_to((struct stroker *)&stroker, x0, y0);
+ break;
+ case VG_VLINE_TO:
+ data_at(&coords, p, 0, 1, data);
+ x0 = ox;
+ y0 = data[0];
+ map_if_relative(ox, oy, relative, 0, &y0);
+ oy = y0;
+ px = x0;
+ py = y0;
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ stroker_line_to((struct stroker *)&stroker, x0, y0);
+ break;
+ case VG_CUBIC_TO: {
+ data_at(&coords, p, 0, 6, data);
+ x0 = ox;
+ y0 = oy;
+ x1 = data[0];
+ y1 = data[1];
+ x2 = data[2];
+ y2 = data[3];
+ x3 = data[4];
+ y3 = data[5];
+ map_if_relative(ox, oy, relative, &x1, &y1);
+ map_if_relative(ox, oy, relative, &x2, &y2);
+ map_if_relative(ox, oy, relative, &x3, &y3);
+ if (floatsEqual(x1, ox) && floatsEqual(y1, oy) &&
+ floatsEqual(x1, x2) && floatsEqual(y1, y2) &&
+ floatsEqual(x2, x3) && floatsEqual(y2, y3)) {
+ /*ignore the empty segment */
+ continue;
+ } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) {
+ /* if dup vertex, emit a line */
+ ox = x3;
+ oy = y3;
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ stroker_line_to((struct stroker *)&stroker, x3, y3);
+ continue;
+ }
+ ox = x3;
+ oy = y3;
+ px = x2;
+ py = y2;
+ assert(matrix_is_affine(matrix));
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ matrix_map_point(matrix, x2, y2, &x2, &y2);
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3);
+ }
+ break;
+ case VG_QUAD_TO: {
+ data_at(&coords, p, 0, 4, data);
+ x0 = ox;
+ y0 = oy;
+ x1 = data[0];
+ y1 = data[1];
+ x3 = data[2];
+ y3 = data[3];
+ map_if_relative(ox, oy, relative, &x1, &y1);
+ map_if_relative(ox, oy, relative, &x3, &y3);
+ px = x1;
+ py = y1;
+ { /* form a cubic out of it */
+ x2 = (x3 + 2*x1) / 3.f;
+ y2 = (y3 + 2*y1) / 3.f;
+ x1 = (x0 + 2*x1) / 3.f;
+ y1 = (y0 + 2*y1) / 3.f;
+ }
+ if (floatsEqual(x1, ox) && floatsEqual(y1, oy) &&
+ floatsEqual(x1, x2) && floatsEqual(y1, y2) &&
+ floatsEqual(x2, x3) && floatsEqual(y2, y3)) {
+ /*ignore the empty segment */
+ continue;
+ } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) {
+ /* if dup vertex, emit a line */
+ ox = x3;
+ oy = y3;
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ stroker_line_to((struct stroker *)&stroker, x3, y3);
+ continue;
+ }
+ ox = x3;
+ oy = y3;
+ assert(matrix_is_affine(matrix));
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ matrix_map_point(matrix, x2, y2, &x2, &y2);
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3);
+ }
+ break;
+ case VG_SQUAD_TO: {
+ data_at(&coords, p, 0, 2, data);
+ x0 = ox;
+ y0 = oy;
+ x1 = 2*ox-px;
+ y1 = 2*oy-py;
+ x3 = data[0];
+ y3 = data[1];
+ map_if_relative(ox, oy, relative, &x3, &y3);
+ px = x1;
+ py = y1;
+ { /* form a cubic out of it */
+ x2 = (x3 + 2*x1) / 3.f;
+ y2 = (y3 + 2*y1) / 3.f;
+ x1 = (x0 + 2*x1) / 3.f;
+ y1 = (y0 + 2*y1) / 3.f;
+ }
+ if (floatsEqual(x1, ox) && floatsEqual(y1, oy) &&
+ floatsEqual(x1, x2) && floatsEqual(y1, y2) &&
+ floatsEqual(x2, x3) && floatsEqual(y2, y3)) {
+ /*ignore the empty segment */
+ continue;
+ } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) {
+ /* if dup vertex, emit a line */
+ ox = x3;
+ oy = y3;
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ stroker_line_to((struct stroker *)&stroker, x3, y3);
+ continue;
+ }
+ ox = x3;
+ oy = y3;
+ assert(matrix_is_affine(matrix));
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ matrix_map_point(matrix, x2, y2, &x2, &y2);
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3);
+ }
+ break;
+ case VG_SCUBIC_TO: {
+ data_at(&coords, p, 0, 4, data);
+ x0 = ox;
+ y0 = oy;
+ x1 = 2*ox-px;
+ y1 = 2*oy-py;
+ x2 = data[0];
+ y2 = data[1];
+ x3 = data[2];
+ y3 = data[3];
+ map_if_relative(ox, oy, relative, &x2, &y2);
+ map_if_relative(ox, oy, relative, &x3, &y3);
+ if (floatsEqual(x1, ox) && floatsEqual(y1, oy) &&
+ floatsEqual(x1, x2) && floatsEqual(y1, y2) &&
+ floatsEqual(x2, x3) && floatsEqual(y2, y3)) {
+ /*ignore the empty segment */
+ continue;
+ } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) {
+ /* if dup vertex, emit a line */
+ ox = x3;
+ oy = y3;
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ stroker_line_to((struct stroker *)&stroker, x3, y3);
+ continue;
+ }
+ ox = x3;
+ oy = y3;
+ px = x2;
+ py = y2;
+ assert(matrix_is_affine(matrix));
+ matrix_map_point(matrix, x0, y0, &x0, &y0);
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ matrix_map_point(matrix, x2, y2, &x2, &y2);
+ matrix_map_point(matrix, x3, y3, &x3, &y3);
+ stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3);
+ }
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO: {
+ VGfloat rh, rv, rot;
+ struct arc arc;
+
+ data_at(&coords, p, 0, 5, data);
+ x0 = ox;
+ y0 = oy;
+ rh = data[0];
+ rv = data[1];
+ rot = data[2];
+ x1 = data[3];
+ y1 = data[4];
+ map_if_relative(ox, oy, relative, &x1, &y1);
+ if (floatsEqual(x1, ox) && floatsEqual(y1, oy)) {
+ /* if dup vertex, emit a line */
+ ox = x1;
+ oy = y1;
+ matrix_map_point(matrix, x1, y1, &x1, &y1);
+ stroker_line_to((struct stroker *)&stroker, x1, y1);
+ continue;
+ }
+ arc_init(&arc, command, x0, y0, x1, y1,
+ rh, rv, rot);
+ arc_stroke_cb(&arc, (struct stroker *)&stroker,
+ matrix);
+ ox = x1;
+ oy = y1;
+ px = x1;
+ py = y1;
+ }
+ break;
+ default:
+ abort();
+ assert(!"Unknown segment!");
+ }
+ }
+
+ stroker_end((struct stroker *)&stroker);
+
+ if (dashed)
+ dash_stroker_cleanup((struct dash_stroker *)&stroker);
+ else
+ stroker_cleanup((struct stroker *)&stroker);
+
+ p->stroked.path = stroker.base.path;
+ p->stroked.matrix = *matrix;
+ p->dirty_stroke = VG_FALSE;
+ p->stroked.stroke_width = vg_state->stroke.line_width.f;
+ p->stroked.miter_limit = vg_state->stroke.miter_limit.f;
+ p->stroked.cap_style = vg_state->stroke.cap_style;
+ p->stroked.join_style = vg_state->stroke.join_style;
+
+ return stroker.base.path;
+}
+
+void path_render(struct path *p, VGbitfield paintModes)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
+
+ vg_validate_state(ctx);
+
+ shader_set_drawing_image(ctx->shader, VG_FALSE);
+ shader_set_image(ctx->shader, 0);
+#if 0
+ fprintf(stderr, "Matrix(11=%f 12=%f 13=%f 21=%f 22=%f 23=%f 31=%f 32=%f 33=%f)\n",
+ mat->m[0], mat->m[1], mat->m[2],
+ mat->m[3], mat->m[4], mat->m[5],
+ mat->m[6], mat->m[7], mat->m[8]);
+#endif
+ if (paintModes & VG_FILL_PATH) {
+ /* First the fill */
+ shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
+ shader_bind(ctx->shader);
+ path_fill(p, mat);
+ }
+
+ if (paintModes & VG_STROKE_PATH){
+ /* 8.7.5: "line width less than or equal to 0 prevents stroking from
+ * taking place."*/
+ if (ctx->state.vg.stroke.line_width.f <= 0)
+ return;
+ shader_set_paint(ctx->shader, ctx->state.vg.stroke_paint);
+ shader_bind(ctx->shader);
+ path_stroke(p);
+ }
+}
+
+void path_fill(struct path *p, struct matrix *mat)
+{
+ struct vg_context *ctx = vg_current_context();
+ {
+ struct polygon_array *polygon_array = path_get_fill_polygons(p, mat);
+ struct array *polys = polygon_array->array;
+
+ if (!polygon_array || !polys || !polys->num_elements) {
+ return;
+ }
+ polygon_array_fill(polygon_array, ctx);
+ }
+}
+
+void path_stroke(struct path *p)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
+ VGFillRule old_fill = ctx->state.vg.fill_rule;
+ struct matrix identity;
+ struct path *stroke;
+
+ matrix_load_identity(&identity);
+ stroke = path_create_stroke(p, &identity);
+ if (stroke && !path_is_empty(stroke)) {
+ ctx->state.vg.fill_rule = VG_NON_ZERO;
+
+ path_fill(stroke, mat);
+
+ ctx->state.vg.fill_rule = old_fill;
+ }
+}
+
+void path_move_to(struct path *p, float x, float y)
+{
+ VGubyte segment = VG_MOVE_TO_ABS;
+ VGubyte common_data[sizeof(VGfloat) * 2];
+ VGfloat data[2] = {x, y};
+
+ vg_float_to_datatype(p->datatype, common_data, data, 2);
+ path_append_data(p, 1, &segment, common_data);
+}
+
+void path_line_to(struct path *p, float x, float y)
+{
+ VGubyte segment = VG_LINE_TO_ABS;
+ VGubyte common_data[sizeof(VGfloat) * 2];
+ VGfloat data[2] = {x, y};
+
+ vg_float_to_datatype(p->datatype, common_data, data, 2);
+
+ path_append_data(p, 1, &segment, common_data);
+}
+
+void path_cubic_to(struct path *p, float px1, float py1,
+ float px2, float py2,
+ float x, float y)
+{
+ VGubyte segment = VG_CUBIC_TO_ABS;
+ VGubyte common_data[sizeof(VGfloat) * 6];
+ VGfloat data[6];
+
+ data[0] = px1; data[1] = py1;
+ data[2] = px2; data[3] = py2;
+ data[4] = x; data[5] = y;
+
+ vg_float_to_datatype(p->datatype, common_data, data, 6);
+
+ path_append_data(p, 1, &segment, common_data);
+}
+
+static INLINE void line_bounds(VGfloat *line /*x1,y1,x2,y2*/,
+ VGfloat *bounds)
+{
+ bounds[0] = MIN2(line[0], line[2]);
+ bounds[1] = MIN2(line[1], line[3]);
+ bounds[2] = MAX2(line[0], line[2]) - bounds[0];
+ bounds[3] = MAX2(line[1], line[3]) - bounds[1];
+}
+
+static INLINE void unite_bounds(VGfloat *bounds,
+ VGfloat *el)
+{
+ VGfloat cx1, cy1, cx2, cy2;
+ VGfloat nx1, ny1, nx2, ny2;
+
+ cx1 = bounds[0];
+ cy1 = bounds[1];
+ cx2 = bounds[0] + bounds[2];
+ cy2 = bounds[1] + bounds[3];
+
+ nx1 = el[0];
+ ny1 = el[1];
+ nx2 = el[0] + el[2];
+ ny2 = el[1] + el[3];
+
+ bounds[0] = MIN2(cx1, nx1);
+ bounds[1] = MIN2(cy1, ny1);
+ bounds[2] = MAX2(cx2, nx2) - bounds[0];
+ bounds[3] = MAX2(cy2, ny2) - bounds[1];
+}
+
+static INLINE void set_bounds(VGfloat *bounds,
+ VGfloat *element_bounds,
+ VGboolean *initialized)
+{
+ if (!(*initialized)) {
+ memcpy(bounds, element_bounds, 4 * sizeof(VGfloat));
+ *initialized = VG_TRUE;
+ } else
+ unite_bounds(bounds, element_bounds);
+}
+
+void path_bounding_rect(struct path *p, float *x, float *y,
+ float *w, float *h)
+{
+ VGint i;
+ VGfloat coords[8];
+ struct path_iter_data iter;
+ VGint num_coords;
+ VGfloat bounds[4];
+ VGfloat element_bounds[4];
+ VGfloat ox, oy;
+ VGboolean bounds_inited = VG_FALSE;
+
+ memset(&iter, 0, sizeof(struct path_iter_data));
+ memset(&bounds, 0, sizeof(bounds));
+
+ if (!p->num_segments) {
+ bounds[2] = -1;
+ bounds[3] = -1;
+ }
+
+
+ iter.path = p;
+ iter.coords = p->control_points->data;
+
+ for (i = 0; i < p->num_segments; ++i) {
+ VGubyte segment;
+ iter.segment = ((VGubyte*)(p->segments->data))[i];
+
+ ox = iter.ox;
+ oy = iter.oy;
+
+ segment = normalize_coords(&iter, &num_coords, coords);
+
+ switch(segment) {
+ case VG_CLOSE_PATH:
+ case VG_MOVE_TO_ABS:
+ break;
+ case VG_LINE_TO_ABS: {
+ VGfloat line[4] = {ox, oy, coords[0], coords[1]};
+ line_bounds(line, element_bounds);
+ set_bounds(bounds, element_bounds, &bounds_inited);
+ }
+ break;
+ case VG_CUBIC_TO_ABS: {
+ struct bezier bezier;
+ bezier_init(&bezier, ox, oy,
+ coords[0], coords[1],
+ coords[2], coords[3],
+ coords[4], coords[5]);
+ bezier_exact_bounds(&bezier, element_bounds);
+ set_bounds(bounds, element_bounds, &bounds_inited);
+ }
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO: {
+ struct arc arc;
+ struct matrix identity;
+ struct path *path = path_create(VG_PATH_DATATYPE_F,
+ 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
+
+ matrix_load_identity(&identity);
+ arc_init(&arc, segment,
+ ox, oy, coords[3], coords[4],
+ coords[0], coords[1], coords[2]);
+
+ arc_to_path(&arc, path, &identity);
+
+ path_bounding_rect(path, element_bounds + 0, element_bounds + 1,
+ element_bounds + 2, element_bounds + 3);
+ set_bounds(bounds, element_bounds, &bounds_inited);
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ *x = bounds[0];
+ *y = bounds[1];
+ *w = bounds[2];
+ *h = bounds[3];
+}
+
+float path_length(struct path *p, int start_segment, int num_segments)
+{
+ VGint i;
+ VGfloat coords[8];
+ struct path_iter_data iter;
+ VGint num_coords;
+ VGfloat length = 0;
+ VGfloat ox, oy;
+ VGboolean in_range = VG_FALSE;
+
+ memset(&iter, 0, sizeof(struct path_iter_data));
+
+ iter.path = p;
+ iter.coords = p->control_points->data;
+
+ for (i = 0; i < (start_segment + num_segments); ++i) {
+ VGubyte segment;
+
+ iter.segment = ((VGubyte*)(p->segments->data))[i];
+
+ ox = iter.ox;
+ oy = iter.oy;
+
+ segment = normalize_coords(&iter, &num_coords, coords);
+
+ in_range = (i >= start_segment) && i <= (start_segment + num_segments);
+ if (!in_range)
+ continue;
+
+ switch(segment) {
+ case VG_MOVE_TO_ABS:
+ break;
+ case VG_CLOSE_PATH: {
+ VGfloat line[4] = {ox, oy, iter.sx, iter.sy};
+ length += line_lengthv(line);
+ }
+ break;
+ case VG_LINE_TO_ABS: {
+ VGfloat line[4] = {ox, oy, coords[0], coords[1]};
+ length += line_lengthv(line);
+ }
+ break;
+ case VG_CUBIC_TO_ABS: {
+ struct bezier bezier;
+ bezier_init(&bezier, ox, oy,
+ coords[0], coords[1],
+ coords[2], coords[3],
+ coords[4], coords[5]);
+ length += bezier_length(&bezier, BEZIER_DEFAULT_ERROR);
+ }
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO: {
+ struct arc arc;
+ struct matrix identity;
+ struct path *path = path_create(VG_PATH_DATATYPE_F,
+ 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
+
+ matrix_load_identity(&identity);
+ arc_init(&arc, segment,
+ ox, oy, coords[3], coords[4],
+ coords[0], coords[1], coords[2]);
+
+ arc_to_path(&arc, path, &identity);
+
+ length += path_length(path, 0, path_num_segments(path));
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ return length;
+}
+
+static INLINE VGboolean point_on_current_segment(VGfloat distance,
+ VGfloat length,
+ VGfloat segment_length)
+{
+ return
+ (((floatIsZero(distance) || distance < 0) && floatIsZero(length)) ||
+ ((distance > length || floatsEqual(distance, length)) &&
+ (floatsEqual(distance, length + segment_length) ||
+ distance < (length + segment_length))));
+}
+
+static VGboolean path_point_segment(struct path_iter_data iter,
+ struct path_iter_data prev_iter,
+ VGfloat coords[8],
+ VGfloat distance,
+ VGfloat length, VGfloat *current_length,
+ VGfloat *point, VGfloat *normal)
+{
+ switch (iter.segment) {
+ case VG_MOVE_TO_ABS:
+ break;
+ case VG_CLOSE_PATH: {
+ VGfloat line[4] = {prev_iter.ox, prev_iter.oy, iter.sx, iter.sy};
+ VGboolean on_current_segment = VG_FALSE;
+ *current_length = line_lengthv(line);
+ on_current_segment = point_on_current_segment(distance,
+ length,
+ *current_length);
+ if (on_current_segment) {
+ VGfloat at = (distance - length) / line_lengthv(line);
+ line_normal_vector(line, normal);
+ line_point_at(line, at, point);
+ return VG_TRUE;
+ }
+ }
+ break;
+ case VG_LINE_TO_ABS: {
+ VGfloat line[4] = {prev_iter.ox, prev_iter.oy, coords[0], coords[1]};
+ VGboolean on_current_segment = VG_FALSE;
+ *current_length = line_lengthv(line);
+ on_current_segment = point_on_current_segment(distance,
+ length,
+ *current_length);
+ if (on_current_segment) {
+ VGfloat at = (distance - length) / line_lengthv(line);
+ line_normal_vector(line, normal);
+ line_point_at(line, at, point);
+ return VG_TRUE;
+ }
+ }
+ break;
+ case VG_CUBIC_TO_ABS: {
+ struct bezier bezier;
+ bezier_init(&bezier, prev_iter.ox, prev_iter.oy,
+ coords[0], coords[1],
+ coords[2], coords[3],
+ coords[4], coords[5]);
+ *current_length = bezier_length(&bezier, BEZIER_DEFAULT_ERROR);
+ if (point_on_current_segment(distance, length, *current_length)) {
+ bezier_point_at_length(&bezier, distance - length,
+ point, normal);
+ return VG_TRUE;
+ }
+ }
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO: {
+ struct arc arc;
+ struct matrix identity;
+ struct path *path = path_create(VG_PATH_DATATYPE_F,
+ 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
+
+ matrix_load_identity(&identity);
+ arc_init(&arc, iter.segment,
+ prev_iter.ox, prev_iter.oy, coords[3], coords[4],
+ coords[0], coords[1], coords[2]);
+
+ arc_to_path(&arc, path, &identity);
+
+ *current_length = path_length(path, 0, path_num_segments(path));
+ if (point_on_current_segment(distance, length, *current_length)) {
+ path_point(path, 0, path_num_segments(path),
+ distance - length, point, normal);
+ return VG_TRUE;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+ return VG_FALSE;
+}
+
+void path_point(struct path *p, VGint start_segment, VGint num_segments,
+ VGfloat distance, VGfloat *point, VGfloat *normal)
+{
+ VGint i;
+ VGfloat coords[8];
+ struct path_iter_data iter, prev_iter;
+ VGint num_coords;
+ VGfloat length = 0;
+ VGfloat current_length = 0;
+
+ memset(&iter, 0, sizeof(struct path_iter_data));
+ memset(&prev_iter, 0, sizeof(struct path_iter_data));
+
+ point[0] = 0;
+ point[1] = 0;
+
+ normal[0] = 0;
+ normal[1] = -1;
+
+ iter.path = p;
+ iter.coords = p->control_points->data;
+ if (distance < 0)
+ distance = 0;
+
+ for (i = 0; i < (start_segment + num_segments); ++i) {
+ VGboolean outside_range = (i < start_segment ||
+ i >= (start_segment + num_segments));
+
+ prev_iter = iter;
+
+ iter.segment = ((VGubyte*)(p->segments->data))[i];
+ iter.segment = normalize_coords(&iter, &num_coords, coords);
+
+ if (outside_range)
+ continue;
+
+ if (path_point_segment(iter, prev_iter, coords,
+ distance, length, &current_length,
+ point, normal))
+ return;
+
+ length += current_length;
+ }
+
+ /*
+ *OpenVG 1.0 - 8.6.11 vgPointAlongPath
+ *
+ * If distance is greater than or equal to the path length
+ *(i.e., the value returned by vgPathLength when called with the same
+ *startSegment and numSegments parameters), the visual ending point of
+ *the path is used.
+ */
+ {
+ switch (iter.segment) {
+ case VG_MOVE_TO_ABS:
+ break;
+ case VG_CLOSE_PATH: {
+ VGfloat line[4] = {prev_iter.ox, prev_iter.oy, iter.sx, iter.sy};
+ line_normal_vector(line, normal);
+ line_point_at(line, 1.f, point);
+ }
+ break;
+ case VG_LINE_TO_ABS: {
+ VGfloat line[4] = {prev_iter.ox, prev_iter.oy, coords[0], coords[1]};
+ line_normal_vector(line, normal);
+ line_point_at(line, 1.f, point);
+ }
+ break;
+ case VG_CUBIC_TO_ABS: {
+ struct bezier bezier;
+ bezier_init(&bezier, prev_iter.ox, prev_iter.oy,
+ coords[0], coords[1],
+ coords[2], coords[3],
+ coords[4], coords[5]);
+ bezier_point_at_t(&bezier, 1.f, point, normal);
+ }
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO: {
+ struct arc arc;
+ struct matrix identity;
+ struct path *path = path_create(VG_PATH_DATATYPE_F,
+ 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
+
+ matrix_load_identity(&identity);
+ arc_init(&arc, iter.segment,
+ prev_iter.ox, prev_iter.oy, coords[3], coords[4],
+ coords[0], coords[1], coords[2]);
+
+ arc_to_path(&arc, path, &identity);
+
+ path_point(path, 0, path_num_segments(path),
+ /* to make sure we're bigger than len * 2 it */
+ 2 * path_length(path, 0, path_num_segments(path)),
+ point, normal);
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+}
+
+VGboolean path_is_empty(struct path *p)
+{
+ return p->segments->num_elements == 0;
+}
diff --git a/src/gallium/state_trackers/vega/path.h b/src/gallium/state_trackers/vega/path.h
new file mode 100644
index 0000000000..e34538b736
--- /dev/null
+++ b/src/gallium/state_trackers/vega/path.h
@@ -0,0 +1,126 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _PATH_H
+#define _PATH_H
+
+#include "VG/openvg.h"
+
+struct path;
+struct polygon;
+struct matrix;
+
+enum fill_rule {
+ ODD_EVEN_FILL,
+ WINDING_FILL
+};
+
+
+struct path_for_each_data {
+ VGubyte segment;
+ /* all coords are absolute, even if segment is relative */
+ const VGfloat *coords;
+ VGfloat sx, sy, ox, oy, px, py;
+ void *user_data;
+};
+
+typedef VGboolean (*path_for_each_cb)(struct path *p,
+ struct path_for_each_data *data);
+
+
+struct path *path_create(VGPathDatatype dt, VGfloat scale, VGfloat bias,
+ VGint segmentCapacityHint,
+ VGint coordCapacityHint,
+ VGbitfield capabilities);
+void path_destroy(struct path *p);
+
+VGbitfield path_capabilities(struct path *p);
+void path_set_capabilities(struct path *p, VGbitfield bf);
+
+void path_append_data(struct path *p,
+ VGint numSegments,
+ const VGubyte * pathSegments,
+ const void * pathData);
+
+void path_append_path(struct path *dst,
+ struct path *src);
+
+VGint path_num_segments(struct path *p);
+
+void path_bounding_rect(struct path *p, float *x, float *y,
+ float *w, float *h);
+float path_length(struct path *p, int start_segment, int num_segments);
+
+void path_set_fill_rule(enum fill_rule fill);
+enum fill_rule path_fill_rule(enum fill_rule fill);
+
+VGboolean path_is_empty(struct path *p);
+
+VGbyte path_datatype_size(struct path *p);
+
+VGPathDatatype path_datatype(struct path *p);
+VGfloat path_scale(struct path *p);
+VGfloat path_bias(struct path *p);
+VGint path_num_coords(struct path *p);
+
+void path_modify_coords(struct path *p,
+ VGint startIndex,
+ VGint numSegments,
+ const void * pathData);
+
+struct path *path_create_stroke(struct path *p,
+ struct matrix *m);
+
+void path_for_each_segment(struct path *path,
+ path_for_each_cb cb,
+ void *user_data);
+
+void path_transform(struct path *dst, struct path *src);
+VGboolean path_interpolate(struct path *dst,
+ struct path *start, struct path *end,
+ VGfloat amount);
+
+void path_clear(struct path *p, VGbitfield capabilities);
+void path_render(struct path *p, VGbitfield paintModes);
+void path_fill(struct path *p, struct matrix *mat);
+void path_stroke(struct path *p);
+
+void path_move_to(struct path *p, float x, float y);
+void path_line_to(struct path *p, float x, float y);
+void path_cubic_to(struct path *p, float px1, float py1,
+ float px2, float py2,
+ float x, float y);
+
+void path_point(struct path *p, VGint startSegment, VGint numSegments,
+ VGfloat distance, VGfloat *point, VGfloat *normal);
+
+
+
+void vg_float_to_datatype(VGPathDatatype datatype,
+ VGubyte *common_data,
+ const VGfloat *data,
+ VGint num_coords);
+#endif
diff --git a/src/gallium/state_trackers/vega/path_utils.h b/src/gallium/state_trackers/vega/path_utils.h
new file mode 100644
index 0000000000..c2b3221dc5
--- /dev/null
+++ b/src/gallium/state_trackers/vega/path_utils.h
@@ -0,0 +1,109 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PATH_UTILS_H
+#define PATH_UTILS_H
+
+#include "VG/openvg.h"
+
+#define SEGMENT_COMMAND(command) /* Extract segment type */ \
+ ((command) & 0x1e)
+#define SEGMENT_ABS_REL(command) /* Extract absolute/relative bit */ \
+ ((command) & 0x1)
+
+static INLINE VGint size_for_datatype(VGPathDatatype datatype)
+{
+ switch(datatype) {
+ case VG_PATH_DATATYPE_S_8:
+ return 1;
+ case VG_PATH_DATATYPE_S_16:
+ return 2;
+ case VG_PATH_DATATYPE_S_32:
+ return 4;
+ case VG_PATH_DATATYPE_F:
+ return 4;
+ default:
+ assert(!"unknown datatype");
+ }
+ return 0;
+}
+
+static INLINE VGint num_elements_for_segments(const VGubyte *segments,
+ VGint num_segments)
+{
+ VGint i;
+ VGint count = 0;
+
+ for (i = 0; i < num_segments; ++i) {
+ VGubyte segment = segments[i];
+ VGint command = SEGMENT_COMMAND(segment);
+ switch(command) {
+ case VG_CLOSE_PATH:
+ break;
+ case VG_MOVE_TO:
+ count += 2;
+ break;
+ case VG_LINE_TO:
+ count += 2;
+ break;
+ case VG_HLINE_TO:
+ count += 1;
+ break;
+ case VG_VLINE_TO:
+ count += 1;
+ break;
+ case VG_QUAD_TO:
+ count += 4;
+ break;
+ case VG_CUBIC_TO:
+ count += 6;
+ break;
+ case VG_SQUAD_TO:
+ count += 2;
+ break;
+ case VG_SCUBIC_TO:
+ count += 4;
+ break;
+ case VG_SCCWARC_TO:
+ count += 5;
+ break;
+ case VG_SCWARC_TO:
+ count += 5;
+ break;
+ case VG_LCCWARC_TO:
+ count += 5;
+ break;
+ case VG_LCWARC_TO:
+ count += 5;
+ break;
+ default:
+ assert(!"Unknown segment!");
+ }
+ }
+ return count;
+}
+
+#endif
diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c
new file mode 100644
index 0000000000..b6d282d803
--- /dev/null
+++ b/src/gallium/state_trackers/vega/polygon.c
@@ -0,0 +1,550 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "polygon.h"
+
+#include "matrix.h" /*for floatsEqual*/
+#include "vg_context.h"
+#include "vg_state.h"
+#include "paint.h"
+#include "renderer.h"
+#include "util_array.h"
+#include "VG/openvg.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_screen.h"
+
+#include "util/u_draw_quad.h"
+#include "util/u_math.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#define DEBUG_POLYGON 0
+
+#define COMPONENTS 2
+
+struct polygon
+{
+ VGfloat *data;
+ VGint size;
+
+ VGint num_verts;
+
+ VGboolean dirty;
+ struct pipe_buffer *vbuf;
+ struct pipe_screen *screen;
+};
+
+static float *ptr_to_vertex(float *data, int idx)
+{
+ return data + (idx * COMPONENTS);
+}
+
+#if 0
+static void polygon_print(struct polygon *poly)
+{
+ int i;
+ float *vert;
+ debug_printf("Polygon %p, size = %d\n", poly, poly->num_verts);
+ for (i = 0; i < poly->num_verts; ++i) {
+ vert = ptr_to_vertex(poly->data, i);
+ debug_printf("%f, %f, ", vert[0], vert[1]);
+ }
+ debug_printf("\nend\n");
+}
+#endif
+
+
+struct polygon * polygon_create(int size)
+{
+ struct polygon *poly = (struct polygon*)malloc(sizeof(struct polygon));
+
+ poly->data = malloc(sizeof(float) * COMPONENTS * size);
+ poly->size = size;
+ poly->num_verts = 0;
+ poly->dirty = VG_TRUE;
+ poly->vbuf = NULL;
+
+ return poly;
+}
+
+struct polygon * polygon_create_from_data(float *data, int size)
+{
+ struct polygon *poly = polygon_create(size);
+
+ memcpy(poly->data, data, sizeof(float) * COMPONENTS * size);
+ poly->num_verts = size;
+ poly->dirty = VG_TRUE;
+ poly->vbuf = NULL;
+
+ return poly;
+}
+
+void polygon_destroy(struct polygon *poly)
+{
+ if (poly->vbuf)
+ pipe_buffer_reference(&poly->vbuf, NULL);
+
+ free(poly->data);
+ free(poly);
+}
+
+void polygon_resize(struct polygon *poly, int new_size)
+{
+ float *data = (float*)malloc(sizeof(float) * COMPONENTS * new_size);
+ int size = MIN2(sizeof(float) * COMPONENTS * new_size,
+ sizeof(float) * COMPONENTS * poly->size);
+ memcpy(data, poly->data, size);
+ free(poly->data);
+ poly->data = data;
+ poly->size = new_size;
+ poly->dirty = VG_TRUE;
+}
+
+int polygon_size(struct polygon *poly)
+{
+ return poly->size;
+}
+
+int polygon_vertex_count(struct polygon *poly)
+{
+ return poly->num_verts;
+}
+
+float * polygon_data(struct polygon *poly)
+{
+ return poly->data;
+}
+
+void polygon_vertex_append(struct polygon *p,
+ float x, float y)
+{
+ float *vert;
+#if DEBUG_POLYGON
+ debug_printf("Append vertex [%f, %f]\n", x, y);
+#endif
+ if (p->num_verts >= p->size) {
+ polygon_resize(p, p->size * 2);
+ }
+
+ vert = ptr_to_vertex(p->data, p->num_verts);
+ vert[0] = x;
+ vert[1] = y;
+ ++p->num_verts;
+ p->dirty = VG_TRUE;
+}
+
+void polygon_set_vertex(struct polygon *p, int idx,
+ float x, float y)
+{
+ float *vert;
+ if (idx >= p->num_verts) {
+ /*fixme: error reporting*/
+ abort();
+ return;
+ }
+
+ vert = ptr_to_vertex(p->data, idx);
+ vert[0] = x;
+ vert[1] = y;
+ p->dirty = VG_TRUE;
+}
+
+void polygon_vertex(struct polygon *p, int idx,
+ float *vertex)
+{
+ float *vert;
+ if (idx >= p->num_verts) {
+ /*fixme: error reporting*/
+ abort();
+ return;
+ }
+
+ vert = ptr_to_vertex(p->data, idx);
+ vertex[0] = vert[0];
+ vertex[1] = vert[1];
+}
+
+void polygon_bounding_rect(struct polygon *p,
+ float *rect)
+{
+ int i;
+ float minx, miny, maxx, maxy;
+ float *vert = ptr_to_vertex(p->data, 0);
+ minx = vert[0];
+ maxx = vert[0];
+ miny = vert[1];
+ maxy = vert[1];
+
+ for (i = 1; i < p->num_verts; ++i) {
+ vert = ptr_to_vertex(p->data, i);
+ minx = MIN2(vert[0], minx);
+ miny = MIN2(vert[1], miny);
+
+ maxx = MAX2(vert[0], maxx);
+ maxy = MAX2(vert[1], maxy);
+ }
+
+ rect[0] = minx;
+ rect[1] = miny;
+ rect[2] = maxx - minx;
+ rect[3] = maxy - miny;
+}
+
+int polygon_contains_point(struct polygon *p,
+ float x, float y)
+{
+ return 0;
+}
+
+void polygon_append_polygon(struct polygon *dst,
+ struct polygon *src)
+{
+ if (dst->num_verts + src->num_verts >= dst->size) {
+ polygon_resize(dst, dst->num_verts + src->num_verts * 1.5);
+ }
+ memcpy(ptr_to_vertex(dst->data, dst->num_verts),
+ src->data, src->num_verts * COMPONENTS * sizeof(VGfloat));
+ dst->num_verts += src->num_verts;
+}
+
+VGboolean polygon_is_closed(struct polygon *p)
+{
+ VGfloat start[2], end[2];
+
+ polygon_vertex(p, 0, start);
+ polygon_vertex(p, p->num_verts - 1, end);
+
+ return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]);
+}
+
+static void set_blend_for_fill(struct pipe_blend_state *blend)
+{
+ memset(blend, 0, sizeof(struct pipe_blend_state));
+ blend->colormask = 0; /*disable colorwrites*/
+
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+}
+
+static void draw_polygon(struct vg_context *ctx,
+ struct polygon *poly)
+{
+ int vert_size;
+ struct pipe_context *pipe;
+ struct pipe_vertex_buffer vbuffer;
+ struct pipe_vertex_element velement;
+
+ vert_size = poly->num_verts * COMPONENTS * sizeof(float);
+
+ /*polygon_print(poly);*/
+
+ pipe = ctx->pipe;
+
+ if (poly->vbuf == NULL || poly->dirty) {
+ if (poly->vbuf) {
+ pipe_buffer_reference(&poly->vbuf,
+ NULL);
+ }
+ poly->screen = pipe->screen;
+ poly->vbuf= pipe_user_buffer_create(poly->screen,
+ poly->data,
+ vert_size);
+ poly->dirty = VG_FALSE;
+ }
+
+
+ /* tell pipe about the vertex buffer */
+ memset(&vbuffer, 0, sizeof(vbuffer));
+ vbuffer.buffer = poly->vbuf;
+ vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
+ vbuffer.buffer_offset = 0;
+ vbuffer.max_index = poly->num_verts - 1;
+ pipe->set_vertex_buffers(pipe, 1, &vbuffer);
+
+ /* tell pipe about the vertex attributes */
+ velement.src_offset = 0;
+ velement.vertex_buffer_index = 0;
+ velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
+ velement.nr_components = COMPONENTS;
+ pipe->set_vertex_elements(pipe, 1, &velement);
+
+ /* draw */
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN,
+ 0, poly->num_verts);
+}
+
+void polygon_fill(struct polygon *poly, struct vg_context *ctx)
+{
+ struct pipe_depth_stencil_alpha_state dsa;
+ struct pipe_blend_state blend;
+ VGfloat bounds[4];
+ VGfloat min_x, min_y, max_x, max_y;
+ assert(poly);
+ polygon_bounding_rect(poly, bounds);
+ min_x = bounds[0];
+ min_y = bounds[1];
+ max_x = bounds[0] + bounds[2];
+ max_y = bounds[1] + bounds[3];
+
+#if DEBUG_POLYGON
+ debug_printf("Poly bounds are [%f, %f], [%f, %f]\n",
+ min_x, min_y, max_x, max_y);
+#endif
+
+ set_blend_for_fill(&blend);
+
+ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
+
+ cso_save_blend(ctx->cso_context);
+ cso_save_depth_stencil_alpha(ctx->cso_context);
+
+ dsa.stencil[0].enabled = 1;
+ if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
+ dsa.stencil[0].writemask = 1;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
+ dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[0].ref_value = 0;
+ dsa.stencil[0].valuemask = ~0;
+
+ cso_set_blend(ctx->cso_context, &blend);
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+ draw_polygon(ctx, poly);
+ } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
+ struct pipe_screen *screen = ctx->pipe->screen;
+
+ if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
+ /* front */
+ dsa.stencil[0].writemask = ~0;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
+ dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[0].ref_value = 0;
+ dsa.stencil[0].valuemask = ~0;
+
+ /* back */
+ dsa.stencil[1].enabled = 1;
+ dsa.stencil[1].writemask = ~0;
+ dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
+ dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[1].ref_value = 0;
+ dsa.stencil[1].valuemask = ~0;
+
+ cso_set_blend(ctx->cso_context, &blend);
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+ draw_polygon(ctx, poly);
+ } else {
+ struct pipe_rasterizer_state raster;
+
+ memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
+
+ cso_save_rasterizer(ctx->cso_context);
+ dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[0].ref_value = 0;
+ dsa.stencil[0].valuemask = ~0;
+
+ raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
+
+ cso_set_blend(ctx->cso_context, &blend);
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+ cso_set_rasterizer(ctx->cso_context, &raster);
+ draw_polygon(ctx, poly);
+
+ raster.cull_mode = raster.front_winding;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+ cso_set_rasterizer(ctx->cso_context, &raster);
+ draw_polygon(ctx, poly);
+
+ cso_restore_rasterizer(ctx->cso_context);
+ }
+ }
+
+ /* restore color writes */
+ cso_restore_blend(ctx->cso_context);
+ /* setup stencil ops */
+ dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+ dsa.stencil[0].ref_value = 0;
+ dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
+ dsa.stencil[1].enabled = 0;
+ memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
+ sizeof(struct pipe_depth_state));
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+
+ /* render the quad to propagate the rendering from stencil */
+ renderer_draw_quad(ctx->renderer, min_x, min_y,
+ max_x, max_y, 0.0f/*depth should be disabled*/);
+
+ cso_restore_depth_stencil_alpha(ctx->cso_context);
+}
+
+void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
+{
+ struct array *polys = polyarray->array;
+ struct pipe_depth_stencil_alpha_state dsa;
+ struct pipe_blend_state blend;
+ VGfloat min_x = polyarray->min_x;
+ VGfloat min_y = polyarray->min_y;
+ VGfloat max_x = polyarray->max_x;
+ VGfloat max_y = polyarray->max_y;
+ VGint i;
+
+
+#if DEBUG_POLYGON
+ debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
+ __FUNCTION__,
+ min_x, min_y, max_x, max_y);
+#endif
+
+ set_blend_for_fill(&blend);
+
+ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
+
+ cso_save_blend(ctx->cso_context);
+ cso_save_depth_stencil_alpha(ctx->cso_context);
+
+ dsa.stencil[0].enabled = 1;
+ if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
+ dsa.stencil[0].writemask = 1;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
+ dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[0].ref_value = 0;
+ dsa.stencil[0].valuemask = ~0;
+
+ cso_set_blend(ctx->cso_context, &blend);
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+ for (i = 0; i < polys->num_elements; ++i) {
+ struct polygon *poly = (((struct polygon**)polys->data)[i]);
+ draw_polygon(ctx, poly);
+ }
+ } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
+ struct pipe_screen *screen = ctx->pipe->screen;
+
+ if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
+ /* front */
+ dsa.stencil[0].writemask = ~0;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
+ dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[0].ref_value = 0;
+ dsa.stencil[0].valuemask = ~0;
+
+ /* back */
+ dsa.stencil[1].enabled = 1;
+ dsa.stencil[1].writemask = ~0;
+ dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
+ dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[1].ref_value = 0;
+ dsa.stencil[1].valuemask = ~0;
+
+ cso_set_blend(ctx->cso_context, &blend);
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+ for (i = 0; i < polys->num_elements; ++i) {
+ struct polygon *poly = (((struct polygon**)polys->data)[i]);
+ draw_polygon(ctx, poly);
+ }
+ } else {
+ struct pipe_rasterizer_state raster;
+
+ memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
+
+ cso_save_rasterizer(ctx->cso_context);
+ dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[0].ref_value = 0;
+ dsa.stencil[0].valuemask = ~0;
+
+ raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
+
+ cso_set_blend(ctx->cso_context, &blend);
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+ cso_set_rasterizer(ctx->cso_context, &raster);
+ for (i = 0; i < polys->num_elements; ++i) {
+ struct polygon *poly = (((struct polygon**)polys->data)[i]);
+ draw_polygon(ctx, poly);
+ }
+
+ raster.cull_mode = raster.front_winding;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+ cso_set_rasterizer(ctx->cso_context, &raster);
+ for (i = 0; i < polys->num_elements; ++i) {
+ struct polygon *poly = (((struct polygon**)polys->data)[i]);
+ draw_polygon(ctx, poly);
+ }
+
+ cso_restore_rasterizer(ctx->cso_context);
+ }
+ }
+
+ /* restore color writes */
+ cso_restore_blend(ctx->cso_context);
+ /* setup stencil ops */
+ dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+ dsa.stencil[0].ref_value = 0;
+ dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
+ dsa.stencil[1].enabled = 0;
+ memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
+ sizeof(struct pipe_depth_state));
+ cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
+
+ /* render the quad to propagate the rendering from stencil */
+ renderer_draw_quad(ctx->renderer, min_x, min_y,
+ max_x, max_y, 0.0f/*depth should be disabled*/);
+
+ cso_restore_depth_stencil_alpha(ctx->cso_context);
+}
diff --git a/src/gallium/state_trackers/vega/polygon.h b/src/gallium/state_trackers/vega/polygon.h
new file mode 100644
index 0000000000..22672b728e
--- /dev/null
+++ b/src/gallium/state_trackers/vega/polygon.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef POLYGON_H
+#define POLYGON_H
+
+#include "VG/openvg.h"
+
+struct polygon;
+struct vg_context;
+struct vg_paint;
+struct array;
+
+struct polygon *polygon_create(int size);
+struct polygon *polygon_create_from_data(float *data, int size);
+void polygon_destroy(struct polygon *poly);
+
+void polygon_resize(struct polygon *poly, int new_size);
+int polygon_size(struct polygon *poly);
+
+int polygon_vertex_count(struct polygon *poly);
+float * polygon_data(struct polygon *poly);
+
+void polygon_vertex_append(struct polygon *p,
+ float x, float y);
+void polygon_append_polygon(struct polygon *dst,
+ struct polygon *src);
+void polygon_set_vertex(struct polygon *p, int idx,
+ float x, float y);
+void polygon_vertex(struct polygon *p, int idx,
+ float *vertex);
+
+void polygon_bounding_rect(struct polygon *p,
+ float *rect);
+int polygon_contains_point(struct polygon *p,
+ float x, float y);
+
+VGboolean polygon_is_closed(struct polygon *p);
+
+void polygon_fill(struct polygon *p, struct vg_context *pipe);
+
+/* TODO: make a file/module around this struct
+ */
+struct polygon_array {
+ struct array *array;
+ VGfloat min_x, max_x;
+ VGfloat min_y, max_y;
+};
+
+void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c
new file mode 100644
index 0000000000..f7c5f2f0cd
--- /dev/null
+++ b/src/gallium/state_trackers/vega/renderer.c
@@ -0,0 +1,592 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "renderer.h"
+
+#include "vg_context.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_draw_quad.h"
+#include "util/u_simple_shaders.h"
+#include "util/u_memory.h"
+
+#include "cso_cache/cso_context.h"
+
+struct renderer {
+ struct pipe_context *pipe;
+ struct vg_context *owner;
+
+ struct cso_context *cso;
+
+ void *fs;
+
+ VGfloat vertices[4][2][4];
+};
+
+static void setup_shaders(struct renderer *ctx)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ /* fragment shader */
+ ctx->fs = util_make_fragment_tex_shader(pipe);
+}
+
+static struct pipe_buffer *
+setup_vertex_data(struct renderer *ctx,
+ float x0, float y0, float x1, float y1, float z)
+{
+ ctx->vertices[0][0][0] = x0;
+ ctx->vertices[0][0][1] = y0;
+ ctx->vertices[0][0][2] = z;
+ ctx->vertices[0][1][0] = 0.0f; /*s*/
+ ctx->vertices[0][1][1] = 0.0f; /*t*/
+
+ ctx->vertices[1][0][0] = x1;
+ ctx->vertices[1][0][1] = y0;
+ ctx->vertices[1][0][2] = z;
+ ctx->vertices[1][1][0] = 1.0f; /*s*/
+ ctx->vertices[1][1][1] = 0.0f; /*t*/
+
+ ctx->vertices[2][0][0] = x1;
+ ctx->vertices[2][0][1] = y1;
+ ctx->vertices[2][0][2] = z;
+ ctx->vertices[2][1][0] = 1.0f;
+ ctx->vertices[2][1][1] = 1.0f;
+
+ ctx->vertices[3][0][0] = x0;
+ ctx->vertices[3][0][1] = y1;
+ ctx->vertices[3][0][2] = z;
+ ctx->vertices[3][1][0] = 0.0f;
+ ctx->vertices[3][1][1] = 1.0f;
+
+ return pipe_user_buffer_create( ctx->pipe->screen,
+ ctx->vertices,
+ sizeof(ctx->vertices) );
+}
+
+static struct pipe_buffer *
+setup_vertex_data_tex(struct renderer *ctx,
+ float x0, float y0, float x1, float y1,
+ float s0, float t0, float s1, float t1,
+ float z)
+{
+ ctx->vertices[0][0][0] = x0;
+ ctx->vertices[0][0][1] = y0;
+ ctx->vertices[0][0][2] = z;
+ ctx->vertices[0][1][0] = s0; /*s*/
+ ctx->vertices[0][1][1] = t0; /*t*/
+
+ ctx->vertices[1][0][0] = x1;
+ ctx->vertices[1][0][1] = y0;
+ ctx->vertices[1][0][2] = z;
+ ctx->vertices[1][1][0] = s1; /*s*/
+ ctx->vertices[1][1][1] = t0; /*t*/
+
+ ctx->vertices[2][0][0] = x1;
+ ctx->vertices[2][0][1] = y1;
+ ctx->vertices[2][0][2] = z;
+ ctx->vertices[2][1][0] = s1;
+ ctx->vertices[2][1][1] = t1;
+
+ ctx->vertices[3][0][0] = x0;
+ ctx->vertices[3][0][1] = y1;
+ ctx->vertices[3][0][2] = z;
+ ctx->vertices[3][1][0] = s0;
+ ctx->vertices[3][1][1] = t1;
+
+ return pipe_user_buffer_create( ctx->pipe->screen,
+ ctx->vertices,
+ sizeof(ctx->vertices) );
+}
+
+
+static struct pipe_buffer *
+setup_vertex_data_qtex(struct renderer *ctx,
+ float x0, float y0, float x1, float y1,
+ float x2, float y2, float x3, float y3,
+ float s0, float t0, float s1, float t1,
+ float z)
+{
+ ctx->vertices[0][0][0] = x0;
+ ctx->vertices[0][0][1] = y0;
+ ctx->vertices[0][0][2] = z;
+ ctx->vertices[0][1][0] = s0; /*s*/
+ ctx->vertices[0][1][1] = t0; /*t*/
+
+ ctx->vertices[1][0][0] = x1;
+ ctx->vertices[1][0][1] = y1;
+ ctx->vertices[1][0][2] = z;
+ ctx->vertices[1][1][0] = s1; /*s*/
+ ctx->vertices[1][1][1] = t0; /*t*/
+
+ ctx->vertices[2][0][0] = x2;
+ ctx->vertices[2][0][1] = y2;
+ ctx->vertices[2][0][2] = z;
+ ctx->vertices[2][1][0] = s1;
+ ctx->vertices[2][1][1] = t1;
+
+ ctx->vertices[3][0][0] = x3;
+ ctx->vertices[3][0][1] = y3;
+ ctx->vertices[3][0][2] = z;
+ ctx->vertices[3][1][0] = s0;
+ ctx->vertices[3][1][1] = t1;
+
+ return pipe_user_buffer_create( ctx->pipe->screen,
+ ctx->vertices,
+ sizeof(ctx->vertices) );
+}
+
+struct renderer * renderer_create(struct vg_context *owner)
+{
+ VGint i;
+ struct renderer *renderer = CALLOC_STRUCT(renderer);
+
+ if (!renderer)
+ return NULL;
+
+ renderer->owner = owner;
+ renderer->pipe = owner->pipe;
+ renderer->cso = owner->cso_context;
+
+ setup_shaders(renderer);
+
+ /* init vertex data that doesn't change */
+ for (i = 0; i < 4; i++) {
+ renderer->vertices[i][0][3] = 1.0f; /* w */
+ renderer->vertices[i][1][2] = 0.0f; /* r */
+ renderer->vertices[i][1][3] = 1.0f; /* q */
+ }
+
+ return renderer;
+}
+
+void renderer_destroy(struct renderer *ctx)
+{
+#if 0
+ if (ctx->fs) {
+ cso_delete_fragment_shader(ctx->cso, ctx->fs);
+ ctx->fs = NULL;
+ }
+#endif
+ free(ctx);
+}
+
+void renderer_draw_quad(struct renderer *r,
+ VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2,
+ VGfloat depth)
+{
+ struct pipe_buffer *buf;
+
+ buf = setup_vertex_data(r, x1, y1, x2, y2, depth);
+
+ if (buf) {
+ util_draw_vertex_buffer(r->pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference( &buf,
+ NULL );
+ }
+}
+
+void renderer_draw_texture(struct renderer *r,
+ struct pipe_texture *tex,
+ VGfloat x1offset, VGfloat y1offset,
+ VGfloat x2offset, VGfloat y2offset,
+ VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2)
+{
+ struct pipe_context *pipe = r->pipe;
+ struct pipe_buffer *buf;
+ VGfloat s0, t0, s1, t1;
+
+ assert(tex->width[0] != 0);
+ assert(tex->height[0] != 0);
+
+ s0 = x1offset / tex->width[0];
+ s1 = x2offset / tex->width[0];
+ t0 = y1offset / tex->height[0];
+ t1 = y2offset / tex->height[0];
+
+ cso_save_vertex_shader(r->cso);
+ /* shaders */
+ cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
+
+ /* draw quad */
+ buf = setup_vertex_data_tex(r, x1, y1, x2, y2,
+ s0, t0, s1, t1, 0.0f);
+
+ if (buf) {
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference( &buf,
+ NULL );
+ }
+
+ cso_restore_vertex_shader(r->cso);
+}
+
+void renderer_copy_texture(struct renderer *ctx,
+ struct pipe_texture *src,
+ VGfloat sx1, VGfloat sy1,
+ VGfloat sx2, VGfloat sy2,
+ struct pipe_texture *dst,
+ VGfloat dx1, VGfloat dy1,
+ VGfloat dx2, VGfloat dy2)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_buffer *buf;
+ struct pipe_surface *dst_surf = screen->get_tex_surface(
+ screen, dst, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ struct pipe_framebuffer_state fb;
+ float s0, t0, s1, t1;
+
+ assert(src->width[0] != 0);
+ assert(src->height[0] != 0);
+ assert(dst->width[0] != 0);
+ assert(dst->height[0] != 0);
+
+#if 0
+ debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
+ sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
+#endif
+
+#if 1
+ s0 = sx1 / src->width[0];
+ s1 = sx2 / src->width[0];
+ t0 = sy1 / src->height[0];
+ t1 = sy2 / src->height[0];
+#else
+ s0 = 0;
+ s1 = 1;
+ t0 = 0;
+ t1 = 1;
+#endif
+
+ assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
+
+ /* save state (restored below) */
+ cso_save_blend(ctx->cso);
+ cso_save_samplers(ctx->cso);
+ cso_save_sampler_textures(ctx->cso);
+ cso_save_framebuffer(ctx->cso);
+ cso_save_fragment_shader(ctx->cso);
+ cso_save_vertex_shader(ctx->cso);
+
+ cso_save_viewport(ctx->cso);
+
+
+ /* set misc state we care about */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask = PIPE_MASK_RGBA;
+ cso_set_blend(ctx->cso, &blend);
+ }
+
+ /* sampler */
+ {
+ struct pipe_sampler_state sampler;
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.normalized_coords = 1;
+ cso_single_sampler(ctx->cso, 0, &sampler);
+ cso_single_sampler_done(ctx->cso);
+ }
+
+ vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
+
+ /* texture */
+ cso_set_sampler_textures(ctx->cso, 1, &src);
+
+ /* shaders */
+ cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
+
+ /* drawing dest */
+ memset(&fb, 0, sizeof(fb));
+ fb.width = dst_surf->width;
+ fb.height = dst_surf->height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = dst_surf;
+ {
+ VGint i;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ fb.cbufs[i] = 0;
+ }
+ cso_set_framebuffer(ctx->cso, &fb);
+
+ /* draw quad */
+ buf = setup_vertex_data_tex(ctx,
+ dx1, dy1,
+ dx2, dy2,
+ s0, t0, s1, t1,
+ 0.0f);
+
+ if (buf) {
+ util_draw_vertex_buffer(ctx->pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference( &buf,
+ NULL );
+ }
+
+ /* restore state we changed */
+ cso_restore_blend(ctx->cso);
+ cso_restore_samplers(ctx->cso);
+ cso_restore_sampler_textures(ctx->cso);
+ cso_restore_framebuffer(ctx->cso);
+ cso_restore_vertex_shader(ctx->cso);
+ cso_restore_fragment_shader(ctx->cso);
+ cso_restore_viewport(ctx->cso);
+
+ pipe_surface_reference(&dst_surf, NULL);
+}
+
+void renderer_copy_surface(struct renderer *ctx,
+ struct pipe_surface *src,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, unsigned filter)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_buffer *buf;
+ struct pipe_texture texTemp, *tex;
+ struct pipe_surface *texSurf;
+ struct pipe_framebuffer_state fb;
+ struct st_framebuffer *stfb = ctx->owner->draw_buffer;
+ const int srcW = abs(srcX1 - srcX0);
+ const int srcH = abs(srcY1 - srcY0);
+ const int srcLeft = MIN2(srcX0, srcX1);
+ const int srcTop = MIN2(srcY0, srcY1);
+
+ assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
+ filter == PIPE_TEX_MIPFILTER_LINEAR);
+
+ if (srcLeft != srcX0) {
+ /* left-right flip */
+ int tmp = dstX0;
+ dstX0 = dstX1;
+ dstX1 = tmp;
+ }
+
+ if (srcTop != srcY0) {
+ /* up-down flip */
+ int tmp = dstY0;
+ dstY0 = dstY1;
+ dstY1 = tmp;
+ }
+
+ assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0));
+ assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0));
+ assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
+
+ /*
+ * XXX for now we're always creating a temporary texture.
+ * Strictly speaking that's not always needed.
+ */
+
+ /* create temp texture */
+ memset(&texTemp, 0, sizeof(texTemp));
+ texTemp.target = PIPE_TEXTURE_2D;
+ texTemp.format = src->format;
+ texTemp.last_level = 0;
+ texTemp.width[0] = srcW;
+ texTemp.height[0] = srcH;
+ texTemp.depth[0] = 1;
+ pf_get_block(src->format, &texTemp.block);
+
+ tex = screen->texture_create(screen, &texTemp);
+ if (!tex)
+ return;
+
+ texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* load temp texture */
+ pipe->surface_copy(pipe,
+ texSurf, 0, 0, /* dest */
+ src, srcLeft, srcTop, /* src */
+ srcW, srcH); /* size */
+
+ /* free the surface, update the texture if necessary.*/
+ screen->tex_surface_destroy(texSurf);
+
+ /* save state (restored below) */
+ cso_save_blend(ctx->cso);
+ cso_save_samplers(ctx->cso);
+ cso_save_sampler_textures(ctx->cso);
+ cso_save_framebuffer(ctx->cso);
+ cso_save_fragment_shader(ctx->cso);
+ cso_save_vertex_shader(ctx->cso);
+ cso_save_viewport(ctx->cso);
+
+ /* set misc state we care about */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask = PIPE_MASK_RGBA;
+ cso_set_blend(ctx->cso, &blend);
+ }
+
+ vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
+
+ /* sampler */
+ {
+ struct pipe_sampler_state sampler;
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.normalized_coords = 1;
+ cso_single_sampler(ctx->cso, 0, &sampler);
+ cso_single_sampler_done(ctx->cso);
+ }
+
+ /* texture */
+ cso_set_sampler_textures(ctx->cso, 1, &tex);
+
+ /* shaders */
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
+ cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
+
+ /* drawing dest */
+ if (stfb->strb->surface != dst) {
+ memset(&fb, 0, sizeof(fb));
+ fb.width = dst->width;
+ fb.height = dst->height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = dst;
+ fb.zsbuf = stfb->dsrb->surface;
+ cso_set_framebuffer(ctx->cso, &fb);
+ }
+
+ /* draw quad */
+ buf = setup_vertex_data(ctx,
+ (float) dstX0, (float) dstY0,
+ (float) dstX1, (float) dstY1, z);
+
+ if (buf) {
+ util_draw_vertex_buffer(ctx->pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference( &buf,
+ NULL );
+ }
+
+
+ /* restore state we changed */
+ cso_restore_blend(ctx->cso);
+ cso_restore_samplers(ctx->cso);
+ cso_restore_sampler_textures(ctx->cso);
+ cso_restore_framebuffer(ctx->cso);
+ cso_restore_fragment_shader(ctx->cso);
+ cso_restore_vertex_shader(ctx->cso);
+ cso_restore_viewport(ctx->cso);
+
+ pipe_texture_reference(&tex, NULL);
+}
+
+void renderer_texture_quad(struct renderer *r,
+ struct pipe_texture *tex,
+ VGfloat x1offset, VGfloat y1offset,
+ VGfloat x2offset, VGfloat y2offset,
+ VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2,
+ VGfloat x3, VGfloat y3,
+ VGfloat x4, VGfloat y4)
+{
+ struct pipe_context *pipe = r->pipe;
+ struct pipe_buffer *buf;
+ VGfloat s0, t0, s1, t1;
+
+ assert(tex->width[0] != 0);
+ assert(tex->height[0] != 0);
+
+ s0 = x1offset / tex->width[0];
+ s1 = x2offset / tex->width[0];
+ t0 = y1offset / tex->height[0];
+ t1 = y2offset / tex->height[0];
+
+ cso_save_vertex_shader(r->cso);
+ /* shaders */
+ cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
+
+ /* draw quad */
+ buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4,
+ s0, t0, s1, t1, 0.0f);
+
+ if (buf) {
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference(&buf,
+ NULL);
+ }
+
+ cso_restore_vertex_shader(r->cso);
+}
diff --git a/src/gallium/state_trackers/vega/renderer.h b/src/gallium/state_trackers/vega/renderer.h
new file mode 100644
index 0000000000..990cd32c31
--- /dev/null
+++ b/src/gallium/state_trackers/vega/renderer.h
@@ -0,0 +1,76 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef RENDERER_H
+#define RENDERER_H
+
+#include "VG/openvg.h"
+
+struct renderer;
+
+struct vg_context;
+struct pipe_texture;
+struct pipe_surface;
+
+struct renderer *renderer_create(struct vg_context *owner);
+void renderer_destroy(struct renderer *);
+
+void renderer_draw_quad(struct renderer *,
+ VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2,
+ VGfloat depth);
+void renderer_draw_texture(struct renderer *,
+ struct pipe_texture *texture,
+ VGfloat x1offset, VGfloat y1offset,
+ VGfloat x2offset, VGfloat y2offset,
+ VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2);
+void renderer_texture_quad(struct renderer *,
+ struct pipe_texture *texture,
+ VGfloat x1offset, VGfloat y1offset,
+ VGfloat x2offset, VGfloat y2offset,
+ VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2,
+ VGfloat x3, VGfloat y3,
+ VGfloat x4, VGfloat y4);
+void renderer_copy_texture(struct renderer *r,
+ struct pipe_texture *src,
+ VGfloat sx1, VGfloat sy1,
+ VGfloat sx2, VGfloat sy2,
+ struct pipe_texture *dst,
+ VGfloat dx1, VGfloat dy1,
+ VGfloat dx2, VGfloat dy2);
+void renderer_copy_surface(struct renderer *r,
+ struct pipe_surface *src,
+ int sx1, int sy1,
+ int sx2, int sy2,
+ struct pipe_surface *dst,
+ int dx1, int dy1,
+ int dx2, int dy2,
+ float z, unsigned filter);
+
+
+#endif
diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c
new file mode 100644
index 0000000000..d9074a377b
--- /dev/null
+++ b/src/gallium/state_trackers/vega/shader.c
@@ -0,0 +1,310 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "shader.h"
+
+#include "vg_context.h"
+#include "shaders_cache.h"
+#include "paint.h"
+#include "mask.h"
+#include "image.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "util/u_memory.h"
+
+#define MAX_CONSTANTS 20
+
+struct shader {
+ struct vg_context *context;
+
+ VGboolean masking;
+ struct vg_paint *paint;
+ struct vg_image *image;
+
+ VGboolean drawing_image;
+ VGImageMode image_mode;
+
+ float constants[MAX_CONSTANTS];
+ struct pipe_constant_buffer cbuf;
+ struct pipe_shader_state fs_state;
+ void *fs;
+};
+
+struct shader * shader_create(struct vg_context *ctx)
+{
+ struct shader *shader = 0;
+
+ shader = CALLOC_STRUCT(shader);
+ shader->context = ctx;
+
+ return shader;
+}
+
+void shader_destroy(struct shader *shader)
+{
+ free(shader);
+}
+
+void shader_set_masking(struct shader *shader, VGboolean set)
+{
+ shader->masking = set;
+}
+
+VGboolean shader_is_masking(struct shader *shader)
+{
+ return shader->masking;
+}
+
+void shader_set_paint(struct shader *shader, struct vg_paint *paint)
+{
+ shader->paint = paint;
+}
+
+struct vg_paint * shader_paint(struct shader *shader)
+{
+ return shader->paint;
+}
+
+
+static void setup_constant_buffer(struct shader *shader)
+{
+ struct vg_context *ctx = shader->context;
+ struct pipe_context *pipe = shader->context->pipe;
+ struct pipe_constant_buffer *cbuf = &shader->cbuf;
+ VGint param_bytes = paint_constant_buffer_size(shader->paint);
+ float temp_buf[MAX_CONSTANTS];
+
+ assert(param_bytes <= sizeof(temp_buf));
+ paint_fill_constant_buffer(shader->paint, temp_buf);
+
+ if (cbuf->buffer == NULL ||
+ memcmp(temp_buf, shader->constants, param_bytes) != 0)
+ {
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+
+ memcpy(shader->constants, temp_buf, param_bytes);
+ cbuf->buffer = pipe_user_buffer_create(pipe->screen,
+ &shader->constants,
+ sizeof(shader->constants));
+ }
+
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+}
+
+static VGint blend_bind_samplers(struct vg_context *ctx,
+ struct pipe_sampler_state **samplers,
+ struct pipe_texture **textures)
+{
+ VGBlendMode bmode = ctx->state.vg.blend_mode;
+
+ if (bmode == VG_BLEND_MULTIPLY ||
+ bmode == VG_BLEND_SCREEN ||
+ bmode == VG_BLEND_DARKEN ||
+ bmode == VG_BLEND_LIGHTEN) {
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+
+ vg_prepare_blend_surface(ctx);
+
+ samplers[2] = &ctx->blend_sampler;
+ textures[2] = stfb->blend_texture;
+
+ if (!samplers[0] || !textures[0]) {
+ samplers[1] = samplers[2];
+ textures[1] = textures[2];
+ }
+ if (!samplers[1] || !textures[1]) {
+ samplers[1] = samplers[0];
+ textures[1] = textures[0];
+ }
+
+ return 1;
+ }
+ return 0;
+}
+
+static void setup_samplers(struct shader *shader)
+{
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ struct vg_context *ctx = shader->context;
+ /* a little wonky: we use the num as a boolean that just says
+ * whether any sampler/textures have been set. the actual numbering
+ * for samplers is always the same:
+ * 0 - paint sampler/texture for gradient/pattern
+ * 1 - mask sampler/texture
+ * 2 - blend sampler/texture
+ * 3 - image sampler/texture
+ * */
+ VGint num = 0;
+
+ samplers[0] = NULL;
+ samplers[1] = NULL;
+ samplers[2] = NULL;
+ samplers[3] = NULL;
+ textures[0] = NULL;
+ textures[1] = NULL;
+ textures[2] = NULL;
+ textures[3] = NULL;
+
+ num += paint_bind_samplers(shader->paint, samplers, textures);
+ num += mask_bind_samplers(samplers, textures);
+ num += blend_bind_samplers(ctx, samplers, textures);
+ if (shader->drawing_image && shader->image)
+ num += image_bind_samplers(shader->image, samplers, textures);
+
+ if (num) {
+ cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers);
+ cso_set_sampler_textures(ctx->cso_context, 4, textures);
+ }
+}
+
+static INLINE VGboolean is_format_bw(struct shader *shader)
+{
+#if 0
+ struct vg_context *ctx = shader->context;
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+#endif
+
+ if (shader->drawing_image && shader->image) {
+ if (shader->image->format == VG_BW_1)
+ return VG_TRUE;
+ }
+
+ return VG_FALSE;
+}
+
+static void setup_shader_program(struct shader *shader)
+{
+ struct vg_context *ctx = shader->context;
+ VGint shader_id = 0;
+ VGBlendMode blend_mode = ctx->state.vg.blend_mode;
+ VGboolean black_white = is_format_bw(shader);
+
+ /* 1st stage: fill */
+ if (!shader->drawing_image ||
+ (shader->image_mode == VG_DRAW_IMAGE_MULTIPLY || shader->image_mode == VG_DRAW_IMAGE_STENCIL)) {
+ switch(paint_type(shader->paint)) {
+ case VG_PAINT_TYPE_COLOR:
+ shader_id |= VEGA_SOLID_FILL_SHADER;
+ break;
+ case VG_PAINT_TYPE_LINEAR_GRADIENT:
+ shader_id |= VEGA_LINEAR_GRADIENT_SHADER;
+ break;
+ case VG_PAINT_TYPE_RADIAL_GRADIENT:
+ shader_id |= VEGA_RADIAL_GRADIENT_SHADER;
+ break;
+ case VG_PAINT_TYPE_PATTERN:
+ shader_id |= VEGA_PATTERN_SHADER;
+ break;
+
+ default:
+ abort();
+ }
+ }
+
+ /* second stage image */
+ if (shader->drawing_image) {
+ switch(shader->image_mode) {
+ case VG_DRAW_IMAGE_NORMAL:
+ shader_id |= VEGA_IMAGE_NORMAL_SHADER;
+ break;
+ case VG_DRAW_IMAGE_MULTIPLY:
+ shader_id |= VEGA_IMAGE_MULTIPLY_SHADER;
+ break;
+ case VG_DRAW_IMAGE_STENCIL:
+ shader_id |= VEGA_IMAGE_STENCIL_SHADER;
+ break;
+ default:
+ debug_printf("Unknown image mode!");
+ }
+ }
+
+ if (shader->masking)
+ shader_id |= VEGA_MASK_SHADER;
+
+ switch(blend_mode) {
+ case VG_BLEND_MULTIPLY:
+ shader_id |= VEGA_BLEND_MULTIPLY_SHADER;
+ break;
+ case VG_BLEND_SCREEN:
+ shader_id |= VEGA_BLEND_SCREEN_SHADER;
+ break;
+ case VG_BLEND_DARKEN:
+ shader_id |= VEGA_BLEND_DARKEN_SHADER;
+ break;
+ case VG_BLEND_LIGHTEN:
+ shader_id |= VEGA_BLEND_LIGHTEN_SHADER;
+ break;
+ default:
+ /* handled by pipe_blend_state */
+ break;
+ }
+
+ if (black_white)
+ shader_id |= VEGA_BW_SHADER;
+
+ shader->fs = shaders_cache_fill(ctx->sc, shader_id);
+ cso_set_fragment_shader_handle(ctx->cso_context, shader->fs);
+}
+
+
+void shader_bind(struct shader *shader)
+{
+ /* first resolve the real paint type */
+ paint_resolve_type(shader->paint);
+
+ setup_constant_buffer(shader);
+ setup_samplers(shader);
+ setup_shader_program(shader);
+}
+
+void shader_set_image_mode(struct shader *shader, VGImageMode image_mode)
+{
+ shader->image_mode = image_mode;
+}
+
+VGImageMode shader_image_mode(struct shader *shader)
+{
+ return shader->image_mode;
+}
+
+void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image)
+{
+ shader->drawing_image = drawing_image;
+}
+
+VGboolean shader_drawing_image(struct shader *shader)
+{
+ return shader->drawing_image;
+}
+
+void shader_set_image(struct shader *shader, struct vg_image *img)
+{
+ shader->image = img;
+}
diff --git a/src/gallium/state_trackers/vega/shader.h b/src/gallium/state_trackers/vega/shader.h
new file mode 100644
index 0000000000..847eee6a31
--- /dev/null
+++ b/src/gallium/state_trackers/vega/shader.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SHADER_H
+#define SHADER_H
+
+#include "VG/openvg.h"
+
+struct shader;
+struct vg_paint;
+struct vg_context;
+struct vg_image;
+
+struct shader *shader_create(struct vg_context *context);
+void shader_destroy(struct shader *shader);
+
+void shader_set_masking(struct shader *shader, VGboolean set);
+VGboolean shader_is_masking(struct shader *shader);
+
+void shader_set_paint(struct shader *shader, struct vg_paint *paint);
+struct vg_paint *shader_paint(struct shader *shader);
+
+void shader_set_image_mode(struct shader *shader, VGImageMode image_mode);
+VGImageMode shader_image_mode(struct shader *shader);
+
+void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image);
+VGboolean shader_drawing_image(struct shader *shader);
+
+void shader_set_image(struct shader *shader, struct vg_image *img);
+
+void shader_bind(struct shader *shader);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/shaders_cache.c b/src/gallium/state_trackers/vega/shaders_cache.c
new file mode 100644
index 0000000000..fd0831fab1
--- /dev/null
+++ b/src/gallium/state_trackers/vega/shaders_cache.c
@@ -0,0 +1,439 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "shaders_cache.h"
+
+#include "vg_context.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "tgsi/tgsi_build.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_text.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_debug.h"
+#include "cso_cache/cso_hash.h"
+#include "cso_cache/cso_context.h"
+
+#include "VG/openvg.h"
+
+#include "asm_fill.h"
+
+/* Essentially we construct an ubber-shader based on the state
+ * of the pipeline. The stages are:
+ * 1) Fill (mandatory, solid color/gradient/pattern/image draw)
+ * 2) Image composition (image mode multiply and stencil)
+ * 3) Mask
+ * 4) Extended blend (multiply/screen/darken/lighten)
+ * 5) Premultiply/Unpremultiply
+ * 6) Color transform (to black and white)
+ */
+#define SHADER_STAGES 6
+
+struct cached_shader {
+ void *driver_shader;
+ struct pipe_shader_state state;
+};
+
+struct shaders_cache {
+ struct vg_context *pipe;
+
+ struct cso_hash *hash;
+};
+
+
+static INLINE struct tgsi_token *tokens_from_assembly(const char *txt, int num_tokens)
+{
+ struct tgsi_token *tokens;
+
+ tokens = (struct tgsi_token *) MALLOC(num_tokens * sizeof(tokens[0]));
+
+ tgsi_text_translate(txt, tokens, num_tokens);
+
+#if DEBUG_SHADERS
+ tgsi_dump(tokens, 0);
+#endif
+
+ return tokens;
+}
+
+#define ALL_FILLS (VEGA_SOLID_FILL_SHADER | \
+ VEGA_LINEAR_GRADIENT_SHADER | \
+ VEGA_RADIAL_GRADIENT_SHADER | \
+ VEGA_PATTERN_SHADER | \
+ VEGA_IMAGE_NORMAL_SHADER)
+
+
+/*
+static const char max_shader_preamble[] =
+ "FRAG1.1\n"
+ "DCL IN[0], POSITION, LINEAR\n"
+ "DCL IN[1], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR, CONSTANT\n"
+ "DCL CONST[0..9], CONSTANT\n"
+ "DCL TEMP[0..9], CONSTANT\n"
+ "DCL SAMP[0..9], CONSTANT\n";
+
+ max_shader_preamble strlen == 175
+*/
+#define MAX_PREAMBLE 175
+
+static INLINE VGint range_min(VGint min, VGint current)
+{
+ if (min < 0)
+ min = current;
+ else
+ min = MIN2(min, current);
+ return min;
+}
+
+static INLINE VGint range_max(VGint max, VGint current)
+{
+ return MAX2(max, current);
+}
+
+static void
+create_preamble(char *txt,
+ const struct shader_asm_info *shaders[SHADER_STAGES],
+ int num_shaders)
+{
+ VGboolean declare_input = VG_FALSE;
+ VGint start_const = -1, end_const = 0;
+ VGint start_temp = -1, end_temp = 0;
+ VGint start_sampler = -1, end_sampler = 0;
+ VGint i;
+ VGint num_consts, num_temps, num_samplers;
+
+ for (i = 0; i < num_shaders; ++i) {
+ if (shaders[i]->num_consts)
+ start_const = range_min(start_const, shaders[i]->start_const);
+ if (shaders[i]->num_temps)
+ start_temp = range_min(start_temp, shaders[i]->start_temp);
+ if (shaders[i]->num_samplers)
+ start_sampler = range_min(start_sampler, shaders[i]->start_sampler);
+
+ end_const = range_max(end_const, shaders[i]->start_const +
+ shaders[i]->num_consts);
+ end_temp = range_max(end_temp, shaders[i]->start_temp +
+ shaders[i]->num_temps);
+ end_sampler = range_max(end_sampler, shaders[i]->start_sampler +
+ shaders[i]->num_samplers);
+ if (shaders[i]->needs_position)
+ declare_input = VG_TRUE;
+ }
+ /* if they're still unitialized, initialize them */
+ if (start_const < 0)
+ start_const = 0;
+ if (start_temp < 0)
+ start_temp = 0;
+ if (start_sampler < 0)
+ start_sampler = 0;
+
+ num_consts = end_const - start_const;
+ num_temps = end_temp - start_temp;
+ num_samplers = end_sampler - start_sampler;
+ /* end exclusive */
+ --end_const;
+ --end_temp;
+ --end_sampler;
+
+ sprintf(txt, "FRAG1.1\n");
+
+ if (declare_input) {
+ sprintf(txt + strlen(txt), "DCL IN[0], POSITION, LINEAR\n");
+ sprintf(txt + strlen(txt), "DCL IN[1], GENERIC[0], PERSPECTIVE\n");
+ }
+
+ /* we always have a color output */
+ sprintf(txt + strlen(txt), "DCL OUT[0], COLOR, CONSTANT\n");
+
+ if (num_consts > 1)
+ sprintf(txt + strlen(txt), "DCL CONST[%d..%d], CONSTANT\n", start_const, end_const);
+ else if (num_consts == 1)
+ sprintf(txt + strlen(txt), "DCL CONST[%d], CONSTANT\n", start_const);
+
+ if (num_temps > 1)
+ sprintf(txt + strlen(txt), "DCL TEMP[%d..%d], CONSTANT\n", start_temp, end_temp);
+ else if (num_temps > 1)
+ sprintf(txt + strlen(txt), "DCL TEMP[%d], CONSTANT\n", start_temp);
+
+ if (num_samplers > 1)
+ sprintf(txt + strlen(txt), "DCL SAMP[%d..%d], CONSTANT\n", start_sampler, end_sampler);
+ else if (num_samplers == 1)
+ sprintf(txt + strlen(txt), "DCL SAMP[%d], CONSTANT\n", start_sampler);
+}
+
+static void *
+combine_shaders(const struct shader_asm_info *shaders[SHADER_STAGES], int num_shaders,
+ struct pipe_context *pipe,
+ struct pipe_shader_state *shader)
+{
+ char *combined_txt;
+ int combined_len = MAX_PREAMBLE;
+ int combined_tokens = 0;
+ int i = 0;
+ int current_shader = 0;
+ int current_len;
+
+ for (i = 0; i < num_shaders; ++i) {
+ combined_len += strlen(shaders[i]->txt);
+ combined_tokens += shaders[i]->num_tokens;
+ }
+ /* add for the %s->TEMP[0] substitutions */
+ combined_len += num_shaders * 7 /*TEMP[0]*/ + 4 /*"END\n"*/;
+
+ combined_txt = (char*)malloc(combined_len);
+ combined_txt[0] = '\0';
+
+ create_preamble(combined_txt, shaders, num_shaders);
+
+ while (current_shader < num_shaders) {
+ const char temp[] = "TEMP[0]";
+ const char out[] = "OUT[0]";
+ const char *subst = temp;
+
+ current_len = strlen(combined_txt);
+
+ /* if the last shader then output */
+ if (current_shader + 1 == num_shaders)
+ subst = out;
+
+ snprintf(combined_txt + current_len,
+ combined_len - current_len,
+ shaders[current_shader]->txt,
+ subst);
+ ++current_shader;
+ }
+
+
+ current_len = strlen(combined_txt);
+ snprintf(combined_txt + current_len,
+ combined_len - current_len,
+ "END\n");
+
+ debug_printf("Combined shader is : \n%s\n",
+ combined_txt);
+
+ shader->tokens = tokens_from_assembly(
+ combined_txt, combined_tokens);
+
+ free(combined_txt);
+
+ return pipe->create_fs_state(pipe, shader);
+}
+
+static void *
+create_shader(struct pipe_context *pipe,
+ int id,
+ struct pipe_shader_state *shader)
+{
+ int idx = 0;
+ const struct shader_asm_info * shaders[SHADER_STAGES];
+
+ /* the shader has to have a fill */
+ debug_assert(id & ALL_FILLS);
+
+ /* first stage */
+ if (id & VEGA_SOLID_FILL_SHADER) {
+ debug_assert(idx == 0);
+ shaders[idx] = &shaders_asm[0];
+ debug_assert(shaders_asm[0].id == VEGA_SOLID_FILL_SHADER);
+ ++idx;
+ }
+ if ((id & VEGA_LINEAR_GRADIENT_SHADER)) {
+ debug_assert(idx == 0);
+ shaders[idx] = &shaders_asm[1];
+ debug_assert(shaders_asm[1].id == VEGA_LINEAR_GRADIENT_SHADER);
+ ++idx;
+ }
+ if ((id & VEGA_RADIAL_GRADIENT_SHADER)) {
+ debug_assert(idx == 0);
+ shaders[idx] = &shaders_asm[2];
+ debug_assert(shaders_asm[2].id == VEGA_RADIAL_GRADIENT_SHADER);
+ ++idx;
+ }
+ if ((id & VEGA_PATTERN_SHADER)) {
+ debug_assert(idx == 0);
+ debug_assert(shaders_asm[3].id == VEGA_PATTERN_SHADER);
+ shaders[idx] = &shaders_asm[3];
+ ++idx;
+ }
+ if ((id & VEGA_IMAGE_NORMAL_SHADER)) {
+ debug_assert(idx == 0);
+ debug_assert(shaders_asm[4].id == VEGA_IMAGE_NORMAL_SHADER);
+ shaders[idx] = &shaders_asm[4];
+ ++idx;
+ }
+
+ /* second stage */
+ if ((id & VEGA_IMAGE_MULTIPLY_SHADER)) {
+ debug_assert(shaders_asm[5].id == VEGA_IMAGE_MULTIPLY_SHADER);
+ shaders[idx] = &shaders_asm[5];
+ ++idx;
+ } else if ((id & VEGA_IMAGE_STENCIL_SHADER)) {
+ debug_assert(shaders_asm[6].id == VEGA_IMAGE_STENCIL_SHADER);
+ shaders[idx] = &shaders_asm[6];
+ ++idx;
+ }
+
+ /* third stage */
+ if ((id & VEGA_MASK_SHADER)) {
+ debug_assert(idx == 1);
+ debug_assert(shaders_asm[7].id == VEGA_MASK_SHADER);
+ shaders[idx] = &shaders_asm[7];
+ ++idx;
+ }
+
+ /* fourth stage */
+ if ((id & VEGA_BLEND_MULTIPLY_SHADER)) {
+ debug_assert(shaders_asm[8].id == VEGA_BLEND_MULTIPLY_SHADER);
+ shaders[idx] = &shaders_asm[8];
+ ++idx;
+ } else if ((id & VEGA_BLEND_SCREEN_SHADER)) {
+ debug_assert(shaders_asm[9].id == VEGA_BLEND_SCREEN_SHADER);
+ shaders[idx] = &shaders_asm[9];
+ ++idx;
+ } else if ((id & VEGA_BLEND_DARKEN_SHADER)) {
+ debug_assert(shaders_asm[10].id == VEGA_BLEND_DARKEN_SHADER);
+ shaders[idx] = &shaders_asm[10];
+ ++idx;
+ } else if ((id & VEGA_BLEND_LIGHTEN_SHADER)) {
+ debug_assert(shaders_asm[11].id == VEGA_BLEND_LIGHTEN_SHADER);
+ shaders[idx] = &shaders_asm[11];
+ ++idx;
+ }
+
+ /* fifth stage */
+ if ((id & VEGA_PREMULTIPLY_SHADER)) {
+ debug_assert(shaders_asm[12].id == VEGA_PREMULTIPLY_SHADER);
+ shaders[idx] = &shaders_asm[12];
+ ++idx;
+ } else if ((id & VEGA_UNPREMULTIPLY_SHADER)) {
+ debug_assert(shaders_asm[13].id == VEGA_UNPREMULTIPLY_SHADER);
+ shaders[idx] = &shaders_asm[13];
+ ++idx;
+ }
+
+ /* sixth stage */
+ if ((id & VEGA_BW_SHADER)) {
+ debug_assert(shaders_asm[14].id == VEGA_BW_SHADER);
+ shaders[idx] = &shaders_asm[14];
+ ++idx;
+ }
+
+ return combine_shaders(shaders, idx, pipe, shader);
+}
+
+/*************************************************/
+
+struct shaders_cache * shaders_cache_create(struct vg_context *vg)
+{
+ struct shaders_cache *sc = CALLOC_STRUCT(shaders_cache);
+
+ sc->pipe = vg;
+ sc->hash = cso_hash_create();
+
+ return sc;
+}
+
+void shaders_cache_destroy(struct shaders_cache *sc)
+{
+ struct cso_hash_iter iter = cso_hash_first_node(sc->hash);
+
+ while (!cso_hash_iter_is_null(iter)) {
+ struct cached_shader *cached =
+ (struct cached_shader *)cso_hash_iter_data(iter);
+ cso_delete_fragment_shader(sc->pipe->cso_context,
+ cached->driver_shader);
+ iter = cso_hash_erase(sc->hash, iter);
+ }
+
+ cso_hash_delete(sc->hash);
+ free(sc);
+}
+
+void * shaders_cache_fill(struct shaders_cache *sc,
+ int shader_key)
+{
+ VGint key = shader_key;
+ struct cached_shader *cached;
+ struct cso_hash_iter iter = cso_hash_find(sc->hash, key);
+
+ if (cso_hash_iter_is_null(iter)) {
+ cached = CALLOC_STRUCT(cached_shader);
+ cached->driver_shader = create_shader(sc->pipe->pipe, key, &cached->state);
+
+ cso_hash_insert(sc->hash, key, cached);
+
+ return cached->driver_shader;
+ }
+
+ cached = (struct cached_shader *)cso_hash_iter_data(iter);
+
+ assert(cached->driver_shader);
+ return cached->driver_shader;
+}
+
+struct vg_shader * shader_create_from_text(struct pipe_context *pipe,
+ const char *txt, int num_tokens,
+ int type)
+{
+ struct vg_shader *shader = (struct vg_shader *)malloc(
+ sizeof(struct vg_shader));
+ struct tgsi_token *tokens = tokens_from_assembly(txt, num_tokens);
+ struct pipe_shader_state state;
+
+ debug_assert(type == PIPE_SHADER_VERTEX ||
+ type == PIPE_SHADER_FRAGMENT);
+
+ state.tokens = tokens;
+ shader->type = type;
+ shader->tokens = tokens;
+
+ if (type == PIPE_SHADER_FRAGMENT)
+ shader->driver = pipe->create_fs_state(pipe, &state);
+ else
+ shader->driver = pipe->create_vs_state(pipe, &state);
+ return shader;
+}
+
+void vg_shader_destroy(struct vg_context *ctx, struct vg_shader *shader)
+{
+ if (shader->type == PIPE_SHADER_FRAGMENT)
+ cso_delete_fragment_shader(ctx->cso_context, shader->driver);
+ else
+ cso_delete_vertex_shader(ctx->cso_context, shader->driver);
+ free(shader->tokens);
+ free(shader);
+}
diff --git a/src/gallium/state_trackers/vega/shaders_cache.h b/src/gallium/state_trackers/vega/shaders_cache.h
new file mode 100644
index 0000000000..feca58b61a
--- /dev/null
+++ b/src/gallium/state_trackers/vega/shaders_cache.h
@@ -0,0 +1,77 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef SHADERS_CACHE_H
+#define SHADERS_CACHE_H
+
+
+struct vg_context;
+struct pipe_context;
+struct tgsi_token;
+struct shaders_cache;
+
+enum VegaShaderType {
+ VEGA_SOLID_FILL_SHADER = 1 << 0,
+ VEGA_LINEAR_GRADIENT_SHADER = 1 << 1,
+ VEGA_RADIAL_GRADIENT_SHADER = 1 << 2,
+ VEGA_PATTERN_SHADER = 1 << 3,
+ VEGA_IMAGE_NORMAL_SHADER = 1 << 4,
+ VEGA_IMAGE_MULTIPLY_SHADER = 1 << 5,
+ VEGA_IMAGE_STENCIL_SHADER = 1 << 6,
+
+ VEGA_MASK_SHADER = 1 << 7,
+
+ VEGA_BLEND_MULTIPLY_SHADER = 1 << 8,
+ VEGA_BLEND_SCREEN_SHADER = 1 << 9,
+ VEGA_BLEND_DARKEN_SHADER = 1 << 10,
+ VEGA_BLEND_LIGHTEN_SHADER = 1 << 11,
+
+ VEGA_PREMULTIPLY_SHADER = 1 << 12,
+ VEGA_UNPREMULTIPLY_SHADER = 1 << 13,
+
+ VEGA_BW_SHADER = 1 << 14
+};
+
+struct vg_shader {
+ void *driver;
+ struct tgsi_token *tokens;
+ int type;/* PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT */
+};
+
+struct shaders_cache *shaders_cache_create(struct vg_context *pipe);
+void shaders_cache_destroy(struct shaders_cache *sc);
+void *shaders_cache_fill(struct shaders_cache *sc,
+ int shader_key);
+
+struct vg_shader *shader_create_from_text(struct pipe_context *pipe,
+ const char *txt, int num_tokens,
+ int type);
+
+void vg_shader_destroy(struct vg_context *ctx, struct vg_shader *shader);
+
+
+
+#endif
diff --git a/src/gallium/state_trackers/vega/st_inlines.h b/src/gallium/state_trackers/vega/st_inlines.h
new file mode 100644
index 0000000000..1f331dfcdb
--- /dev/null
+++ b/src/gallium/state_trackers/vega/st_inlines.h
@@ -0,0 +1,159 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Functions for checking if buffers/textures are referenced when we need
+ * to read/write from/to them. Flush when needed.
+ */
+
+#ifndef ST_INLINES_H
+#define ST_INLINES_H
+
+#include "vg_context.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_state.h"
+
+static INLINE struct pipe_transfer *
+st_cond_flush_get_tex_transfer(struct vg_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ unsigned int zslice,
+ enum pipe_transfer_usage usage,
+ unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+ struct pipe_context *pipe = st->pipe;
+ unsigned referenced =
+ pipe->is_texture_referenced(pipe, pt, face, level);
+
+ if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
+ usage == PIPE_TRANSFER_WRITE ||
+ usage == PIPE_TRANSFER_READ_WRITE))
+ vgFlush();
+
+ return screen->get_tex_transfer(screen, pt, face, level, zslice, usage,
+ x, y, w, h);
+}
+
+static INLINE struct pipe_transfer *
+st_no_flush_get_tex_transfer(struct vg_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ unsigned int zslice,
+ enum pipe_transfer_usage usage,
+ unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+
+ return screen->get_tex_transfer(screen, pt, face, level,
+ zslice, usage, x, y, w, h);
+}
+
+static INLINE void *
+st_cond_flush_pipe_buffer_map(struct vg_context *st,
+ struct pipe_buffer *buf,
+ unsigned int map_flags)
+{
+ struct pipe_context *pipe = st->pipe;
+ unsigned int referenced = pipe->is_buffer_referenced(pipe, buf);
+
+ if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
+ (map_flags & PIPE_BUFFER_USAGE_CPU_WRITE)))
+ vgFlush();
+
+ return pipe_buffer_map(pipe->screen, buf, map_flags);
+}
+
+static INLINE void *
+st_no_flush_pipe_buffer_map(struct vg_context *st,
+ struct pipe_buffer *buf,
+ unsigned int map_flags)
+{
+ return pipe_buffer_map(st->pipe->screen, buf, map_flags);
+}
+
+
+static INLINE void
+st_cond_flush_pipe_buffer_write(struct vg_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ const void * data)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ if (pipe->is_buffer_referenced(pipe, buf))
+ vgFlush();
+
+ pipe_buffer_write(pipe->screen, buf, offset, size, data);
+}
+
+static INLINE void
+st_no_flush_pipe_buffer_write(struct vg_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ const void * data)
+{
+ pipe_buffer_write(st->pipe->screen, buf, offset, size, data);
+}
+
+static INLINE void
+st_cond_flush_pipe_buffer_read(struct vg_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ void * data)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ if (pipe->is_buffer_referenced(pipe, buf) & PIPE_REFERENCED_FOR_WRITE)
+ vgFlush();
+
+ pipe_buffer_read(pipe->screen, buf, offset, size, data);
+}
+
+static INLINE void
+st_no_flush_pipe_buffer_read(struct vg_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ void * data)
+{
+ pipe_buffer_read(st->pipe->screen, buf, offset, size, data);
+}
+
+#endif
+
diff --git a/src/gallium/state_trackers/vega/stroker.c b/src/gallium/state_trackers/vega/stroker.c
new file mode 100644
index 0000000000..1b92d2b5c6
--- /dev/null
+++ b/src/gallium/state_trackers/vega/stroker.c
@@ -0,0 +1,1349 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "stroker.h"
+
+#include "path.h"
+#include "vg_state.h"
+#include "util_array.h"
+#include "arc.h"
+#include "bezier.h"
+#include "matrix.h"
+#include "path_utils.h"
+#include "polygon.h"
+
+#include "math.h"
+
+#ifndef M_2PI
+#define M_2PI 6.28318530717958647692528676655900576
+#endif
+
+#define STROKE_SEGMENTS 0
+#define STROKE_DEBUG 0
+#define DEBUG_EMITS 0
+
+static const VGfloat curve_threshold = 0.25f;
+
+static const VGfloat zero_coords[] = {0.f, 0.f};
+
+enum intersection_type {
+ NoIntersections,
+ BoundedIntersection,
+ UnboundedIntersection,
+};
+
+enum line_join_mode {
+ FlatJoin,
+ SquareJoin,
+ MiterJoin,
+ RoundJoin,
+ RoundCap
+};
+
+struct stroke_iterator {
+ void (*next)(struct stroke_iterator *);
+ VGboolean (*has_next)(struct stroke_iterator *);
+
+ VGPathCommand (*current_command)(struct stroke_iterator *it);
+ void (*current_coords)(struct stroke_iterator *it, VGfloat *coords);
+
+ VGint position;
+ VGint coord_position;
+
+ const VGubyte *cmds;
+ const VGfloat *coords;
+ VGint num_commands;
+ VGint num_coords;
+
+ struct polygon *curve_poly;
+ VGint curve_index;
+};
+
+static VGPathCommand stroke_itr_command(struct stroke_iterator *itr)
+{
+ return itr->current_command(itr);
+}
+
+static void stroke_itr_coords(struct stroke_iterator *itr, VGfloat *coords)
+{
+ itr->current_coords(itr, coords);
+}
+
+static void stroke_fw_itr_coords(struct stroke_iterator *itr, VGfloat *coords)
+{
+ if (itr->position >= itr->num_commands)
+ return;
+ switch (stroke_itr_command(itr)) {
+ case VG_MOVE_TO_ABS:
+ coords[0] = itr->coords[itr->coord_position];
+ coords[1] = itr->coords[itr->coord_position + 1];
+ break;
+ case VG_LINE_TO_ABS:
+ coords[0] = itr->coords[itr->coord_position];
+ coords[1] = itr->coords[itr->coord_position + 1];
+ break;
+ case VG_CUBIC_TO_ABS:
+ coords[0] = itr->coords[itr->coord_position];
+ coords[1] = itr->coords[itr->coord_position + 1];
+ coords[2] = itr->coords[itr->coord_position + 2];
+ coords[3] = itr->coords[itr->coord_position + 3];
+ coords[4] = itr->coords[itr->coord_position + 4];
+ coords[5] = itr->coords[itr->coord_position + 5];
+ break;
+ default:
+ debug_assert(!"invalid command!\n");
+ }
+}
+
+
+static void stroke_bw_itr_coords(struct stroke_iterator *itr, VGfloat *coords)
+{
+ if (itr->position >= itr->num_commands)
+ return;
+ switch (stroke_itr_command(itr)) {
+ case VG_MOVE_TO_ABS:
+ coords[0] = itr->coords[itr->coord_position];
+ coords[1] = itr->coords[itr->coord_position + 1];
+ break;
+ case VG_LINE_TO_ABS:
+ coords[0] = itr->coords[itr->coord_position];
+ coords[1] = itr->coords[itr->coord_position + 1];
+ break;
+ case VG_CUBIC_TO_ABS:
+ coords[0] = itr->coords[itr->coord_position + 4];
+ coords[1] = itr->coords[itr->coord_position + 5];
+ coords[2] = itr->coords[itr->coord_position + 2];
+ coords[3] = itr->coords[itr->coord_position + 3];
+ coords[4] = itr->coords[itr->coord_position + 0];
+ coords[5] = itr->coords[itr->coord_position + 1];
+ break;
+ default:
+ debug_assert(!"invalid command!\n");
+ }
+}
+
+
+static VGPathCommand stroke_fw_current_command(struct stroke_iterator *it)
+{
+ return it->cmds[it->position];
+}
+
+static VGPathCommand stroke_bw_current_command(struct stroke_iterator *it)
+{
+ VGPathCommand prev_cmd;
+ if (it->position == it->num_commands -1)
+ return VG_MOVE_TO_ABS;
+
+ prev_cmd = it->cmds[it->position + 1];
+ return prev_cmd;
+}
+
+static VGboolean stroke_fw_has_next(struct stroke_iterator *itr)
+{
+ return itr->position < (itr->num_commands - 1);
+}
+
+static VGboolean stroke_bw_has_next(struct stroke_iterator *itr)
+{
+ return itr->position > 0;
+}
+
+static void stroke_fw_next(struct stroke_iterator *itr)
+{
+ VGubyte cmd;
+ debug_assert(stroke_fw_has_next(itr));
+
+ cmd = stroke_itr_command(itr);
+
+ itr->coord_position += num_elements_for_segments(&cmd, 1);
+ ++itr->position;
+}
+
+static void stroke_bw_next(struct stroke_iterator *itr)
+{
+ VGubyte cmd;
+ debug_assert(stroke_bw_has_next(itr));
+
+ --itr->position;
+ cmd = stroke_itr_command(itr);
+
+ itr->coord_position -= num_elements_for_segments(&cmd, 1);
+}
+
+static void stroke_itr_common_init(struct stroke_iterator *itr,
+ struct array *cmds,
+ struct array *coords)
+{
+ itr->cmds = (VGubyte*)cmds->data;
+ itr->num_commands = cmds->num_elements;
+
+ itr->coords = (VGfloat*)coords->data;
+ itr->num_coords = coords->num_elements;
+}
+
+static void stroke_forward_iterator(struct stroke_iterator *itr,
+ struct array *cmds,
+ struct array *coords)
+{
+ stroke_itr_common_init(itr, cmds, coords);
+ itr->position = 0;
+ itr->coord_position = 0;
+
+ itr->next = stroke_fw_next;
+ itr->has_next = stroke_fw_has_next;
+ itr->current_command = stroke_fw_current_command;
+ itr->current_coords = stroke_fw_itr_coords;
+}
+
+static void stroke_backward_iterator(struct stroke_iterator *itr,
+ struct array *cmds,
+ struct array *coords)
+{
+ VGubyte cmd;
+ stroke_itr_common_init(itr, cmds, coords);
+ itr->position = itr->num_commands - 1;
+
+ cmd = stroke_bw_current_command(itr);
+ itr->coord_position = itr->num_coords -
+ num_elements_for_segments(&cmd, 1);
+
+ itr->next = stroke_bw_next;
+ itr->has_next = stroke_bw_has_next;
+ itr->current_command = stroke_bw_current_command;
+ itr->current_coords = stroke_bw_itr_coords;
+}
+
+
+
+static void stroke_flat_next(struct stroke_iterator *itr)
+{
+ VGubyte cmd;
+
+ if (itr->curve_index >= 0) {
+ ++itr->curve_index;
+ if (itr->curve_index >= polygon_vertex_count(itr->curve_poly)) {
+ itr->curve_index = -1;
+ polygon_destroy(itr->curve_poly);
+ itr->curve_poly = 0;
+ } else
+ return;
+ }
+ debug_assert(stroke_fw_has_next(itr));
+
+ cmd = itr->cmds[itr->position];
+ itr->coord_position += num_elements_for_segments(&cmd, 1);
+ ++itr->position;
+
+ cmd = itr->cmds[itr->position];
+
+ if (cmd == VG_CUBIC_TO_ABS) {
+ struct bezier bezier;
+ VGfloat bez[8];
+
+ bez[0] = itr->coords[itr->coord_position - 2];
+ bez[1] = itr->coords[itr->coord_position - 1];
+ bez[2] = itr->coords[itr->coord_position];
+ bez[3] = itr->coords[itr->coord_position + 1];
+ bez[4] = itr->coords[itr->coord_position + 2];
+ bez[5] = itr->coords[itr->coord_position + 3];
+ bez[6] = itr->coords[itr->coord_position + 4];
+ bez[7] = itr->coords[itr->coord_position + 5];
+
+ bezier_init(&bezier,
+ bez[0], bez[1],
+ bez[2], bez[3],
+ bez[4], bez[5],
+ bez[6], bez[7]);
+ /* skip the first one, it's the same as the prev point */
+ itr->curve_index = 1;
+ if (itr->curve_poly) {
+ polygon_destroy(itr->curve_poly);
+ itr->curve_poly = 0;
+ }
+ itr->curve_poly = bezier_to_polygon(&bezier);
+ }
+}
+
+static VGboolean stroke_flat_has_next(struct stroke_iterator *itr)
+{
+ return (itr->curve_index >= 0 &&
+ itr->curve_index < (polygon_vertex_count(itr->curve_poly)-1))
+ || itr->position < (itr->num_commands - 1);
+}
+
+static VGPathCommand stroke_flat_current_command(struct stroke_iterator *it)
+{
+ if (it->cmds[it->position] == VG_CUBIC_TO_ABS) {
+ return VG_LINE_TO_ABS;
+ }
+ return it->cmds[it->position];
+}
+
+static void stroke_flat_itr_coords(struct stroke_iterator *itr, VGfloat *coords)
+{
+ if (itr->curve_index <= -1 && itr->position >= itr->num_commands)
+ return;
+
+ if (itr->curve_index >= 0) {
+ polygon_vertex(itr->curve_poly, itr->curve_index,
+ coords);
+ return;
+ }
+
+ switch (stroke_itr_command(itr)) {
+ case VG_MOVE_TO_ABS:
+ coords[0] = itr->coords[itr->coord_position];
+ coords[1] = itr->coords[itr->coord_position + 1];
+ break;
+ case VG_LINE_TO_ABS:
+ coords[0] = itr->coords[itr->coord_position];
+ coords[1] = itr->coords[itr->coord_position + 1];
+ break;
+ case VG_CUBIC_TO_ABS:
+ default:
+ debug_assert(!"invalid command!\n");
+ }
+}
+
+static void stroke_flat_iterator(struct stroke_iterator *itr,
+ struct array *cmds,
+ struct array *coords)
+{
+ stroke_itr_common_init(itr, cmds, coords);
+ itr->position = 0;
+ itr->coord_position = 0;
+
+ itr->next = stroke_flat_next;
+ itr->has_next = stroke_flat_has_next;
+ itr->current_command = stroke_flat_current_command;
+ itr->current_coords = stroke_flat_itr_coords;
+ itr->curve_index = -1;
+ itr->curve_poly = 0;
+}
+
+
+static INLINE VGboolean finite_coords4(const VGfloat *c)
+{
+ return
+ isfinite(c[0]) && isfinite(c[1]) &&
+ isfinite(c[2]) && isfinite(c[3]);
+}
+
+/* from Graphics Gems II */
+#define SAME_SIGNS(a, b) ((a) * (b) >= 0)
+static VGboolean do_lines_intersect(VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2,
+ VGfloat x3, VGfloat y3, VGfloat x4, VGfloat y4)
+{
+ VGfloat a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns */
+ VGfloat r1, r2, r3, r4; /* 'sign' values */
+
+ a1 = y2 - y1;
+ b1 = x1 - x2;
+ c1 = x2 * y1 - x1 * y2;
+
+ r3 = a1 * x3 + b1 * y3 + c1;
+ r4 = a1 * x4 + b1 * y4 + c1;
+
+ if (r3 != 0 && r4 != 0 && SAME_SIGNS(r3, r4))
+ return VG_FALSE;
+
+ a2 = y4 - y3;
+ b2 = x3 - x4;
+ c2 = x4 * y3 - x3 * y4;
+
+ r1 = a2 * x1 + b2 * y1 + c2;
+ r2 = a2 * x2 + b2 * y2 + c2;
+
+ if (r1 != 0 && r2 != 0 && SAME_SIGNS(r1, r2))
+ return VG_FALSE;
+
+ return VG_TRUE;
+}
+
+static INLINE VGfloat line_dx(const VGfloat *l)
+{
+ return l[2] - l[0];
+}
+
+static INLINE VGfloat line_dy(const VGfloat *l)
+{
+ return l[3] - l[1];
+}
+
+static INLINE VGfloat line_angle(const VGfloat *l)
+{
+ const VGfloat dx = line_dx(l);
+ const VGfloat dy = line_dy(l);
+
+ const VGfloat theta = atan2(-dy, dx) * 360.0 / M_2PI;
+
+ const VGfloat theta_normalized = theta < 0 ? theta + 360 : theta;
+
+ if (floatsEqual(theta_normalized, 360.f))
+ return 0;
+ else
+ return theta_normalized;
+}
+
+static INLINE void line_set_length(VGfloat *l, VGfloat len)
+{
+ VGfloat uv[] = {l[0], l[1], l[2], l[3]};
+ if (null_line(l))
+ return;
+ line_normalize(uv);
+ l[2] = l[0] + line_dx(uv) * len;
+ l[3] = l[1] + line_dy(uv) * len;
+}
+
+static INLINE void line_translate(VGfloat *l, VGfloat x, VGfloat y)
+{
+ l[0] += x;
+ l[1] += y;
+ l[2] += x;
+ l[3] += y;
+}
+
+static INLINE VGfloat line_angle_to(const VGfloat *l1,
+ const VGfloat *l2)
+{
+ VGfloat a1, a2, delta, delta_normalized;
+ if (null_line(l1) || null_line(l1))
+ return 0;
+
+ a1 = line_angle(l1);
+ a2 = line_angle(l2);
+
+ delta = a2 - a1;
+ delta_normalized = delta < 0 ? delta + 360 : delta;
+
+ if (floatsEqual(delta, 360.f))
+ return 0;
+ else
+ return delta_normalized;
+}
+
+static INLINE VGfloat line_angles(const VGfloat *l1,
+ const VGfloat *l2)
+{
+ VGfloat cos_line, rad = 0;
+
+ if (null_line(l1) || null_line(l2))
+ return 0;
+
+ cos_line = (line_dx(l1)*line_dx(l2) + line_dy(l1)*line_dy(l2)) /
+ (line_lengthv(l1)*line_lengthv(l2));
+ rad = 0;
+
+ if (cos_line >= -1.0 && cos_line <= 1.0)
+ rad = acos(cos_line);
+ return rad * 360 / M_2PI;
+}
+
+
+static INLINE VGfloat adapted_angle_on_x(const VGfloat *line)
+{
+ const VGfloat identity[] = {0, 0, 1, 0};
+ VGfloat angle = line_angles(line, identity);
+ if (line_dy(line) > 0)
+ angle = 360 - angle;
+ return angle;
+}
+
+static enum intersection_type line_intersect(const VGfloat *l1,
+ const VGfloat *l2,
+ float *intersection_point)
+{
+ VGfloat isect[2];
+ enum intersection_type type;
+ VGboolean dx_zero, ldx_zero;
+
+ if (null_line(l1) || null_line(l2) ||
+ !finite_coords4(l1) || !finite_coords4(l2))
+ return NoIntersections;
+
+ type = do_lines_intersect(l1[0], l1[1], l1[2], l1[3], l2[0], l2[1], l2[2], l2[3])
+ ? BoundedIntersection : UnboundedIntersection;
+
+ dx_zero = floatsEqual(line_dx(l1) + 1, 1);
+ ldx_zero = floatsEqual(line_dx(l2) + 1, 1);
+
+ /* one of the lines is vertical */
+ if (dx_zero && ldx_zero) {
+ type = NoIntersections;
+ } else if (dx_zero) {
+ VGfloat la = line_dy(l2) / line_dx(l2);
+ isect[0] = l1[0];
+ isect[1] = la * l1[0] + l2[1] - la * l2[0];
+ } else if (ldx_zero) {
+ VGfloat ta = line_dy(l1) / line_dx(l1);
+ isect[0] = l2[0];
+ isect[1] = ta * l2[0] + l1[1] - ta*l1[0];
+ } else {
+ VGfloat x;
+ VGfloat ta = line_dy(l1) / line_dx(l1);
+ VGfloat la = line_dy(l2) / line_dx(l2);
+ if (ta == la)
+ return NoIntersections;
+
+ x = ( - l2[1] + la * l2[0] + l1[1] - ta * l1[0] ) / (la - ta);
+ isect[0] = x;
+ isect[1] = ta*(x - l1[0]) + l1[1];
+ }
+ if (intersection_point) {
+ intersection_point[0] = isect[0];
+ intersection_point[1] = isect[1];
+ }
+ return type;
+}
+
+static INLINE enum line_join_mode stroker_join_mode(struct stroker *s)
+{
+ switch(s->join_style) {
+ case VG_JOIN_MITER:
+ return MiterJoin;
+ case VG_JOIN_ROUND:
+ return RoundJoin;
+ case VG_JOIN_BEVEL:
+ return FlatJoin;
+ default:
+ return FlatJoin;
+ }
+}
+
+static INLINE enum line_join_mode stroker_cap_mode(struct stroker *s)
+{
+ switch(s->cap_style) {
+ case VG_CAP_BUTT:
+ return FlatJoin;
+ case VG_CAP_ROUND:
+ return RoundCap;
+ case VG_CAP_SQUARE:
+ return SquareJoin;
+ default:
+ return FlatJoin;
+ }
+}
+
+void stroker_emit_move_to(struct stroker *stroker, VGfloat x, VGfloat y)
+{
+ VGubyte cmds = VG_MOVE_TO_ABS;
+ VGfloat coords[2] = {x, y};
+#if DEBUG_EMITS
+ debug_printf("emit move %f, %f\n", x, y);
+#endif
+ stroker->back2_x = stroker->back1_x;
+ stroker->back2_y = stroker->back1_y;
+ stroker->back1_x = x;
+ stroker->back1_y = y;
+
+ path_append_data(stroker->path,
+ 1,
+ &cmds, &coords);
+}
+
+void stroker_emit_line_to(struct stroker *stroker, VGfloat x, VGfloat y)
+{
+ VGubyte cmds = VG_LINE_TO_ABS;
+ VGfloat coords[2] = {x, y};
+#if DEBUG_EMITS
+ debug_printf("emit line %f, %f\n", x, y);
+#endif
+ stroker->back2_x = stroker->back1_x;
+ stroker->back2_y = stroker->back1_y;
+ stroker->back1_x = x;
+ stroker->back1_y = y;
+ path_append_data(stroker->path,
+ 1,
+ &cmds, &coords);
+}
+
+void stroker_emit_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1,
+ VGfloat px2, VGfloat py2,
+ VGfloat x, VGfloat y)
+{
+ VGubyte cmds = VG_CUBIC_TO_ABS;
+ VGfloat coords[6] = {px1, py1, px2, py2, x, y};
+#if DEBUG_EMITS
+ debug_printf("emit curve %f, %f, %f, %f, %f, %f\n", px1, py1,
+ px2, py2, x, y);
+#endif
+
+ if (px2 == x && py2 == y) {
+ if (px1 == x && py1 == y) {
+ stroker->back2_x = stroker->back1_x;
+ stroker->back2_y = stroker->back1_y;
+ } else {
+ stroker->back2_x = px1;
+ stroker->back2_y = py1;
+ }
+ } else {
+ stroker->back2_x = px2;
+ stroker->back2_y = py2;
+ }
+ stroker->back1_x = x;
+ stroker->back1_y = y;
+
+ path_append_data(stroker->path,
+ 1,
+ &cmds, &coords);
+}
+
+static INLINE void create_round_join(struct stroker *stroker,
+ VGfloat x1, VGfloat y1,
+ VGfloat x2, VGfloat y2,
+ VGfloat width, VGfloat height)
+{
+ struct arc arc;
+ struct matrix matrix;
+
+ matrix_load_identity(&matrix);
+
+ /*stroker_emit_line_to(stroker, nx, ny);*/
+
+ arc_init(&arc, VG_SCCWARC_TO_ABS,
+ x1, y1, x2, y2, width/2, height/2, 0);
+ arc_stroker_emit(&arc, stroker, &matrix);
+}
+
+
+static void create_joins(struct stroker *stroker,
+ VGfloat focal_x, VGfloat focal_y,
+ const VGfloat *next_line, enum line_join_mode join)
+{
+#if DEBUG_EMITS
+ debug_printf("create_joins: focal=[%f, %f], next_line=[%f, %f,%f, %f]\n",
+ focal_x, focal_y,
+ next_line[0], next_line[1], next_line[2], next_line[3]);
+#endif
+ /* if we're alredy connected do nothing */
+ if (floatsEqual(stroker->back1_x, next_line[0]) &&
+ floatsEqual(stroker->back1_y, next_line[1]))
+ return;
+
+ if (join == FlatJoin) {
+ stroker_emit_line_to(stroker, next_line[0], next_line[1]);
+ } else {
+ VGfloat prev_line[] = {stroker->back2_x, stroker->back2_y,
+ stroker->back1_x, stroker->back1_y};
+
+ VGfloat isect[2];
+ enum intersection_type type = line_intersect(prev_line, next_line, isect);
+
+ if (join == SquareJoin) {
+ VGfloat offset = stroker->stroke_width / 2;
+ VGfloat l1[4] = {prev_line[0],
+ prev_line[1],
+ prev_line[2],
+ prev_line[3]};
+ VGfloat l2[4] = {next_line[2],
+ next_line[3],
+ next_line[0],
+ next_line[1]};
+
+ line_translate(l1, line_dx(l1), line_dy(l1));
+ line_set_length(l1, offset);
+
+ line_translate(l2, line_dx(l2), line_dy(l2));
+ line_set_length(l2, offset);
+
+ stroker_emit_line_to(stroker, l1[2], l1[3]);
+ stroker_emit_line_to(stroker, l2[2], l2[3]);
+ stroker_emit_line_to(stroker, l2[0], l2[1]);
+ } else if (join == RoundJoin) {
+ VGfloat offset = stroker->stroke_width / 2;
+ VGfloat short_cut[4] = {prev_line[2], prev_line[3],
+ next_line[0], next_line[1]};
+ VGfloat angle = line_angles(prev_line, short_cut);
+
+ if (type == BoundedIntersection ||
+ (angle > 90 && !floatsEqual(angle, 90.f))) {
+ stroker_emit_line_to(stroker, next_line[0], next_line[1]);
+ return;
+ }
+ create_round_join(stroker, prev_line[2], prev_line[3],
+ next_line[0], next_line[1],
+ offset * 2, offset * 2);
+
+ stroker_emit_line_to(stroker, next_line[0], next_line[1]);
+ } else if (join == RoundCap) {
+ VGfloat offset = stroker->stroke_width / 2;
+ VGfloat l1[4] = { prev_line[0], prev_line[1],
+ prev_line[2], prev_line[3] };
+ VGfloat l2[4] = {focal_x, focal_y,
+ prev_line[2], prev_line[3]};
+
+ line_translate(l1, line_dx(l1), line_dy(l1));
+ line_set_length(l1, KAPPA * offset);
+
+ /* normal between prev_line and focal */
+ line_translate(l2, -line_dy(l2), line_dx(l2));
+ line_set_length(l2, KAPPA * offset);
+
+ stroker_emit_curve_to(stroker, l1[2], l1[3],
+ l2[2], l2[3],
+ l2[0], l2[1]);
+
+ l2[0] = l2[0];
+ l2[1] = l2[1];
+ l2[2] = l2[0] - line_dx(l2);
+ l2[3] = l2[1] - line_dy(l2);
+
+ line_translate(l1, next_line[0] - l1[0], next_line[1] - l1[1]);
+
+ stroker_emit_curve_to(stroker,
+ l2[2], l2[3],
+ l1[2], l1[3],
+ l1[0], l1[1]);
+ } else if (join == MiterJoin) {
+ VGfloat miter_line[4] = {stroker->back1_x, stroker->back1_y,
+ isect[0], isect[1]};
+ VGfloat sl = (stroker->stroke_width * stroker->miter_limit);
+ VGfloat inside_line[4] = {prev_line[2], prev_line[3],
+ next_line[0], next_line[1]};
+ VGfloat angle = line_angle_to(inside_line, prev_line);
+
+ if (type == BoundedIntersection ||
+ (angle > 90 && !floatsEqual(angle, 90.f))) {
+ /*
+ debug_printf("f = %f, nl = %f, pl = %f, is = %f\n",
+ focal_x, next_line[0],
+ prev_line[2], isect[0]);*/
+ stroker_emit_line_to(stroker, next_line[0], next_line[1]);
+ return;
+ }
+
+ if (type == NoIntersections || line_lengthv(miter_line) > sl) {
+ stroker_emit_line_to(stroker, next_line[0], next_line[1]);
+ } else {
+ stroker_emit_line_to(stroker, isect[0], isect[1]);
+ stroker_emit_line_to(stroker, next_line[0], next_line[1]);
+ }
+ } else {
+ debug_assert(!"create_joins bad join style");
+ }
+ }
+}
+
+static void stroker_add_segment(struct stroker *stroker,
+ VGPathCommand cmd,
+ const VGfloat *coords,
+ VGint num_coords)
+{
+ /* skip duplicated points */
+ if (stroker->segments->num_elements &&
+ stroker->last_cmd == cmd) {
+ VGfloat *data = stroker->control_points->data;
+ data += stroker->control_points->num_elements;
+ data -= num_coords;
+ switch (cmd) {
+ case VG_MOVE_TO_ABS:
+ if (floatsEqual(coords[0], data[0]) &&
+ floatsEqual(coords[1], data[1]))
+ return;
+ break;
+ case VG_LINE_TO_ABS:
+ if (floatsEqual(coords[0], data[0]) &&
+ floatsEqual(coords[1], data[1]))
+ return;
+ break;
+ case VG_CUBIC_TO_ABS:
+ if (floatsEqual(coords[0], data[0]) &&
+ floatsEqual(coords[1], data[1]) &&
+ floatsEqual(coords[2], data[2]) &&
+ floatsEqual(coords[3], data[3]) &&
+ floatsEqual(coords[4], data[4]) &&
+ floatsEqual(coords[5], data[5]))
+ return;
+ break;
+ default:
+ debug_assert(!"Invalid stroke segment");
+ }
+ } else if (stroker->last_cmd == VG_CUBIC_TO_ABS &&
+ cmd == VG_LINE_TO_ABS) {
+ VGfloat *data = stroker->control_points->data;
+ data += stroker->control_points->num_elements;
+ data -= 2;
+ if (floatsEqual(coords[0], data[0]) &&
+ floatsEqual(coords[1], data[1]))
+ return;
+ }
+ stroker->last_cmd = cmd;
+ array_append_data(stroker->segments, &cmd, 1);
+ array_append_data(stroker->control_points, coords, num_coords);
+}
+
+void stroker_move_to(struct stroker *stroker, VGfloat x, VGfloat y)
+{
+ VGfloat coords[2] = {x, y};
+#if STROKE_SEGMENTS
+ debug_printf("stroker_move_to(%f, %f)\n", x, y);
+#endif
+
+ if (stroker->segments->num_elements > 0)
+ stroker->process_subpath(stroker);
+
+ array_reset(stroker->segments);
+ array_reset(stroker->control_points);
+
+ stroker_add_segment(stroker, VG_MOVE_TO_ABS, coords, 2);
+}
+
+void stroker_line_to(struct stroker *stroker, VGfloat x, VGfloat y)
+{
+ VGfloat coords[] = {x, y};
+
+#if STROKE_SEGMENTS
+ debug_printf("stroker_line_to(%f, %f)\n", x, y);
+#endif
+ if (!stroker->segments->num_elements)
+ stroker_add_segment(stroker, VG_MOVE_TO_ABS, zero_coords, 2);
+
+ stroker_add_segment(stroker, VG_LINE_TO_ABS, coords, 2);
+}
+
+void stroker_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1,
+ VGfloat px2, VGfloat py2,
+ VGfloat x, VGfloat y)
+{
+ VGfloat coords[] = {px1, py1,
+ px2, py2,
+ x, y};
+#if STROKE_SEGMENTS
+ debug_printf("stroker_curve_to(%f, %f, %f, %f, %f, %f)\n",
+ px1, py1, px2, py2, x, y);
+#endif
+ if (!stroker->segments->num_elements)
+ stroker_add_segment(stroker, VG_MOVE_TO_ABS, zero_coords, 2);
+
+ stroker_add_segment(stroker, VG_CUBIC_TO_ABS, coords, 6);
+}
+
+static INLINE VGboolean is_segment_null(VGPathCommand cmd,
+ VGfloat *coords,
+ VGfloat *res)
+{
+ switch(cmd) {
+ case VG_MOVE_TO_ABS:
+ case VG_LINE_TO_ABS:
+ return floatsEqual(coords[0], res[0]) &&
+ floatsEqual(coords[1], res[1]);
+ break;
+ case VG_CUBIC_TO_ABS:
+ return floatsEqual(coords[0], res[0]) &&
+ floatsEqual(coords[1], res[1]) &&
+ floatsEqual(coords[2], res[0]) &&
+ floatsEqual(coords[3], res[1]) &&
+ floatsEqual(coords[4], res[0]) &&
+ floatsEqual(coords[5], res[1]);
+ break;
+ default:
+ assert(0);
+ }
+ return VG_FALSE;
+}
+
+static VGboolean vg_stroke_outline(struct stroke_iterator *it,
+ struct stroker *stroker,
+ VGboolean cap_first,
+ VGfloat *start_tangent)
+{
+ const int MAX_OFFSET = 16;
+ struct bezier offset_curves[MAX_OFFSET];
+ VGPathCommand first_element;
+ VGfloat start[2], prev[2];
+ VGboolean first = VG_TRUE;
+ VGfloat offset;
+
+ first_element = stroke_itr_command(it);
+ if (first_element != VG_MOVE_TO_ABS) {
+ stroker_emit_move_to(stroker, 0.f, 0.f);
+ prev[0] = 0.f;
+ prev[1] = 0.f;
+ }
+ stroke_itr_coords(it, start);
+#if STROKE_DEBUG
+ debug_printf(" -> (side) [%.2f, %.2f]\n",
+ start[0],
+ start[1]);
+#endif
+
+ prev[0] = start[0];
+ prev[1] = start[1];
+
+ offset = stroker->stroke_width / 2;
+
+ if (!it->has_next(it)) {
+ /* single point */
+
+ return VG_TRUE;
+ }
+
+ while (it->has_next(it)) {
+ VGPathCommand cmd;
+ VGfloat coords[8];
+
+ it->next(it);
+ cmd = stroke_itr_command(it);
+ stroke_itr_coords(it, coords);
+
+ if (cmd == VG_LINE_TO_ABS) {
+ VGfloat line[4] = {prev[0], prev[1], coords[0], coords[1]};
+ VGfloat normal[4];
+ line_normal(line, normal);
+
+#if STROKE_DEBUG
+ debug_printf("\n ---> (side) lineto [%.2f, %.2f]\n", coords[0], coords[1]);
+#endif
+ line_set_length(normal, offset);
+ line_translate(line, line_dx(normal), line_dy(normal));
+
+ /* if we are starting a new subpath, move to correct starting point */
+ if (first) {
+ if (cap_first)
+ create_joins(stroker, prev[0], prev[1], line,
+ stroker_cap_mode(stroker));
+ else
+ stroker_emit_move_to(stroker, line[0], line[1]);
+ memcpy(start_tangent, line,
+ sizeof(VGfloat) * 4);
+ first = VG_FALSE;
+ } else {
+ create_joins(stroker, prev[0], prev[1], line,
+ stroker_join_mode(stroker));
+ }
+
+ /* add the stroke for this line */
+ stroker_emit_line_to(stroker, line[2], line[3]);
+ prev[0] = coords[0];
+ prev[1] = coords[1];
+ } else if (cmd == VG_CUBIC_TO_ABS) {
+#if STROKE_DEBUG
+ debug_printf("\n ---> (side) cubicTo [%.2f, %.2f]\n",
+ coords[4],
+ coords[5]);
+#endif
+ struct bezier bezier;
+ int count;
+
+ bezier_init(&bezier,
+ prev[0], prev[1], coords[0], coords[1],
+ coords[2], coords[3], coords[4], coords[5]);
+
+ count = bezier_translate_by_normal(&bezier,
+ offset_curves,
+ MAX_OFFSET,
+ offset,
+ curve_threshold);
+
+ if (count) {
+ /* if we are starting a new subpath, move to correct starting point */
+ VGfloat tangent[4];
+ VGint i;
+
+ bezier_start_tangent(&bezier, tangent);
+ line_translate(tangent,
+ offset_curves[0].x1 - bezier.x1,
+ offset_curves[0].y1 - bezier.y1);
+ if (first) {
+ VGfloat pt[2] = {offset_curves[0].x1,
+ offset_curves[0].y1};
+
+ if (cap_first) {
+ create_joins(stroker, prev[0], prev[1], tangent,
+ stroker_cap_mode(stroker));
+ } else {
+ stroker_emit_move_to(stroker, pt[0], pt[1]);
+ }
+ start_tangent[0] = tangent[0];
+ start_tangent[1] = tangent[1];
+ start_tangent[2] = tangent[2];
+ start_tangent[3] = tangent[3];
+ first = VG_FALSE;
+ } else {
+ create_joins(stroker, prev[0], prev[1], tangent,
+ stroker_join_mode(stroker));
+ }
+
+ /* add these beziers */
+ for (i = 0; i < count; ++i) {
+ struct bezier *bez = &offset_curves[i];
+ stroker_emit_curve_to(stroker,
+ bez->x2, bez->y2,
+ bez->x3, bez->y3,
+ bez->x4, bez->y4);
+ }
+ }
+
+ prev[0] = coords[4];
+ prev[1] = coords[5];
+ }
+ }
+
+ if (floatsEqual(start[0], prev[0]) &&
+ floatsEqual(start[1], prev[1])) {
+ /* closed subpath, join first and last point */
+#if STROKE_DEBUG
+ debug_printf("\n stroker: closed subpath\n");
+#endif
+ create_joins(stroker, prev[0], prev[1], start_tangent,
+ stroker_join_mode(stroker));
+ return VG_TRUE;
+ } else {
+#if STROKE_DEBUG
+ debug_printf("\n stroker: open subpath\n");
+#endif
+ return VG_FALSE;
+ }
+}
+
+static void stroker_process_subpath(struct stroker *stroker)
+{
+ VGboolean fwclosed, bwclosed;
+ VGfloat fw_start_tangent[4], bw_start_tangent[4];
+ struct stroke_iterator fwit;
+ struct stroke_iterator bwit;
+ debug_assert(stroker->segments->num_elements > 0);
+
+ memset(fw_start_tangent, 0,
+ sizeof(VGfloat)*4);
+ memset(bw_start_tangent, 0,
+ sizeof(VGfloat)*4);
+
+ stroke_forward_iterator(&fwit, stroker->segments,
+ stroker->control_points);
+ stroke_backward_iterator(&bwit, stroker->segments,
+ stroker->control_points);
+
+ debug_assert(fwit.cmds[0] == VG_MOVE_TO_ABS);
+
+ fwclosed = vg_stroke_outline(&fwit, stroker, VG_FALSE, fw_start_tangent);
+ bwclosed = vg_stroke_outline(&bwit, stroker, !fwclosed, bw_start_tangent);
+
+ if (!bwclosed)
+ create_joins(stroker,
+ fwit.coords[0], fwit.coords[1], fw_start_tangent,
+ stroker_cap_mode(stroker));
+ else {
+ /* hack to handle the requirement of the VG spec that says that strokes
+ * of len==0 that have butt cap or round cap still need
+ * to be rendered. (8.7.4 Stroke Generation) */
+ if (stroker->segments->num_elements <= 3) {
+ VGPathCommand cmd;
+ VGfloat data[8], coords[8];
+ struct stroke_iterator *it = &fwit;
+
+ stroke_forward_iterator(it, stroker->segments,
+ stroker->control_points);
+ cmd = stroke_itr_command(it);
+ stroke_itr_coords(it, coords);
+ if (cmd != VG_MOVE_TO_ABS) {
+ memset(data, 0, sizeof(VGfloat) * 8);
+ if (!is_segment_null(cmd, coords, data))
+ return;
+ } else {
+ data[0] = coords[0];
+ data[1] = coords[1];
+ }
+ while (it->has_next(it)) {
+ it->next(it);
+ cmd = stroke_itr_command(it);
+ stroke_itr_coords(it, coords);
+ if (!is_segment_null(cmd, coords, data))
+ return;
+ }
+ /* generate the square/round cap */
+ if (stroker->cap_style == VG_CAP_SQUARE) {
+ VGfloat offset = stroker->stroke_width / 2;
+ stroker_emit_move_to(stroker, data[0] - offset,
+ data[1] - offset);
+ stroker_emit_line_to(stroker, data[0] + offset,
+ data[1] - offset);
+ stroker_emit_line_to(stroker, data[0] + offset,
+ data[1] + offset);
+ stroker_emit_line_to(stroker, data[0] - offset,
+ data[1] + offset);
+ stroker_emit_line_to(stroker, data[0] - offset,
+ data[1] - offset);
+ } else if (stroker->cap_style == VG_CAP_ROUND) {
+ VGfloat offset = stroker->stroke_width / 2;
+ VGfloat cx = data[0], cy = data[1];
+ { /*circle */
+ struct arc arc;
+ struct matrix matrix;
+ matrix_load_identity(&matrix);
+
+ stroker_emit_move_to(stroker, cx + offset, cy);
+ arc_init(&arc, VG_SCCWARC_TO_ABS,
+ cx + offset, cy,
+ cx - offset, cy,
+ offset, offset, 0);
+ arc_stroker_emit(&arc, stroker, &matrix);
+ arc_init(&arc, VG_SCCWARC_TO_ABS,
+ cx - offset, cy,
+ cx + offset, cy,
+ offset, offset, 0);
+ arc_stroker_emit(&arc, stroker, &matrix);
+ }
+ }
+ }
+ }
+}
+
+static INLINE VGfloat dash_pattern(struct dash_stroker *stroker,
+ VGint idx)
+{
+ if (stroker->dash_pattern[idx] < 0)
+ return 0.f;
+ return stroker->dash_pattern[idx];
+}
+
+static void dash_stroker_process_subpath(struct stroker *str)
+{
+ struct dash_stroker *stroker = (struct dash_stroker *)str;
+ VGfloat sum_length = 0;
+ VGint i;
+ VGint idash = 0;
+ VGfloat pos = 0;
+ VGfloat elen = 0;
+ VGfloat doffset = stroker->dash_phase;
+ VGfloat estart = 0;
+ VGfloat estop = 0;
+ VGfloat cline[4];
+ struct stroke_iterator it;
+ VGfloat prev[2];
+ VGfloat move_to_pos[2];
+ VGfloat line_to_pos[2];
+
+ VGboolean has_move_to = VG_FALSE;
+
+ stroke_flat_iterator(&it, stroker->base.segments,
+ stroker->base.control_points);
+
+ stroke_itr_coords(&it, prev);
+ move_to_pos[0] = prev[0];
+ move_to_pos[1] = prev[1];
+
+ debug_assert(stroker->dash_pattern_num > 0);
+
+ for (i = 0; i < stroker->dash_pattern_num; ++i) {
+ sum_length += dash_pattern(stroker, i);
+ }
+
+ if (floatIsZero(sum_length)) {
+ return;
+ }
+
+ doffset -= floorf(doffset / sum_length) * sum_length;
+
+ while (!floatIsZero(doffset) && doffset >= dash_pattern(stroker, idash)) {
+ doffset -= dash_pattern(stroker, idash);
+ idash = (idash + 1) % stroker->dash_pattern_num;
+ }
+
+ while (it.has_next(&it)) {
+ VGPathCommand cmd;
+ VGfloat coords[8];
+ VGboolean done;
+
+ it.next(&it);
+ cmd = stroke_itr_command(&it);
+ stroke_itr_coords(&it, coords);
+
+ debug_assert(cmd == VG_LINE_TO_ABS);
+ cline[0] = prev[0];
+ cline[1] = prev[1];
+ cline[2] = coords[0];
+ cline[3] = coords[1];
+
+ elen = line_lengthv(cline);
+
+ estop = estart + elen;
+
+ done = pos >= estop;
+ while (!done) {
+ VGfloat p2[2];
+
+ VGint idash_incr = 0;
+ VGboolean has_offset = doffset > 0;
+ VGfloat dpos = pos + dash_pattern(stroker, idash) - doffset - estart;
+
+ debug_assert(dpos >= 0);
+
+ if (dpos > elen) { /* dash extends this line */
+ doffset = dash_pattern(stroker, idash) - (dpos - elen);
+ pos = estop;
+ done = VG_TRUE;
+ p2[0] = cline[2];
+ p2[1] = cline[3];
+ } else { /* Dash is on this line */
+ line_point_at(cline, dpos/elen, p2);
+ pos = dpos + estart;
+ done = pos >= estop;
+ idash_incr = 1;
+ doffset = 0;
+ }
+
+ if (idash % 2 == 0) {
+ line_to_pos[0] = p2[0];
+ line_to_pos[1] = p2[1];
+
+ if (!has_offset || !has_move_to) {
+ stroker_move_to(&stroker->stroker, move_to_pos[0], move_to_pos[1]);
+ has_move_to = VG_TRUE;
+ }
+ stroker_line_to(&stroker->stroker, line_to_pos[0], line_to_pos[1]);
+ } else {
+ move_to_pos[0] = p2[0];
+ move_to_pos[1] = p2[1];
+ }
+
+ idash = (idash + idash_incr) % stroker->dash_pattern_num;
+ }
+
+ estart = estop;
+ prev[0] = coords[0];
+ prev[1] = coords[1];
+ }
+
+ if (it.curve_poly) {
+ polygon_destroy(it.curve_poly);
+ it.curve_poly = 0;
+ }
+
+ stroker->base.path = stroker->stroker.path;
+}
+
+static void default_begin(struct stroker *stroker)
+{
+ array_reset(stroker->segments);
+ array_reset(stroker->control_points);
+}
+
+static void default_end(struct stroker *stroker)
+{
+ if (stroker->segments->num_elements > 0)
+ stroker->process_subpath(stroker);
+}
+
+
+static void dash_stroker_begin(struct stroker *stroker)
+{
+ struct dash_stroker *dasher =
+ (struct dash_stroker *)stroker;
+
+ default_begin(&dasher->stroker);
+ default_begin(stroker);
+}
+
+static void dash_stroker_end(struct stroker *stroker)
+{
+ struct dash_stroker *dasher =
+ (struct dash_stroker *)stroker;
+
+ default_end(stroker);
+ default_end(&dasher->stroker);
+}
+
+void stroker_init(struct stroker *stroker,
+ struct vg_state *state)
+{
+ stroker->stroke_width = state->stroke.line_width.f;
+ stroker->miter_limit = state->stroke.miter_limit.f;
+ stroker->cap_style = state->stroke.cap_style;
+ stroker->join_style = state->stroke.join_style;
+
+ stroker->begin = default_begin;
+ stroker->process_subpath = stroker_process_subpath;
+ stroker->end = default_end;
+
+ stroker->segments = array_create(sizeof(VGubyte));
+ stroker->control_points = array_create(sizeof(VGfloat));
+
+ stroker->back1_x = 0;
+ stroker->back1_y = 0;
+ stroker->back2_x = 0;
+ stroker->back2_y = 0;
+
+ stroker->path = path_create(VG_PATH_DATATYPE_F, 1.0f, 0.0f,
+ 0, 0, VG_PATH_CAPABILITY_ALL);
+
+ stroker->last_cmd = VG_CLOSE_PATH;
+}
+
+void dash_stroker_init(struct stroker *str,
+ struct vg_state *state)
+{
+ struct dash_stroker *stroker = (struct dash_stroker *)str;
+ int i;
+
+ stroker_init(str, state);
+ stroker_init(&stroker->stroker, state);
+
+ {
+ int real_num = state->stroke.dash_pattern_num;
+ if (real_num % 2)/* if odd, ignore the last one */
+ --real_num;
+ for (i = 0; i < real_num; ++i)
+ stroker->dash_pattern[i] = state->stroke.dash_pattern[i].f;
+ stroker->dash_pattern_num = real_num;
+ }
+
+ stroker->dash_phase = state->stroke.dash_phase.f;
+ stroker->dash_phase_reset = state->stroke.dash_phase_reset;
+
+ stroker->base.begin = dash_stroker_begin;
+ stroker->base.process_subpath = dash_stroker_process_subpath;
+ stroker->base.end = dash_stroker_end;
+ path_destroy(stroker->base.path);
+ stroker->base.path = NULL;
+}
+
+void stroker_begin(struct stroker *stroker)
+{
+ stroker->begin(stroker);
+}
+
+void stroker_end(struct stroker *stroker)
+{
+ stroker->end(stroker);
+}
+
+void stroker_cleanup(struct stroker *stroker)
+{
+ array_destroy(stroker->segments);
+ array_destroy(stroker->control_points);
+}
+
+void dash_stroker_cleanup(struct dash_stroker *stroker)
+{
+ /* if stroker->base.path is null means we never
+ * processed a valid path so delete the temp one
+ * we already created */
+ if (!stroker->base.path)
+ path_destroy(stroker->stroker.path);
+ stroker_cleanup(&stroker->stroker);
+ stroker_cleanup((struct stroker*)stroker);
+}
diff --git a/src/gallium/state_trackers/vega/stroker.h b/src/gallium/state_trackers/vega/stroker.h
new file mode 100644
index 0000000000..36543cd923
--- /dev/null
+++ b/src/gallium/state_trackers/vega/stroker.h
@@ -0,0 +1,89 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STROKER_H
+#define STROKER_H
+
+#include "VG/openvg.h"
+#include "api_consts.h"
+
+struct path;
+struct vg_state;
+struct array;
+
+struct stroker {
+ void (*begin)(struct stroker *stroker);
+ void (*process_subpath)(struct stroker *stroker);
+ void (*end)(struct stroker *stroker);
+
+ struct array *segments;
+ struct array *control_points;
+ struct path *path;
+
+ VGfloat back1_x, back1_y;
+ VGfloat back2_x, back2_y;
+
+ VGfloat stroke_width;
+ VGfloat miter_limit;
+ VGCapStyle cap_style;
+ VGJoinStyle join_style;
+
+ VGPathCommand last_cmd;
+};
+
+struct dash_stroker {
+ struct stroker base;
+
+ struct stroker stroker;
+
+ VGfloat dash_pattern[VEGA_MAX_DASH_COUNT];
+ VGint dash_pattern_num;
+ VGfloat dash_phase;
+ VGboolean dash_phase_reset;
+};
+
+void stroker_init(struct stroker *stroker,
+ struct vg_state *state);
+void dash_stroker_init(struct stroker *stroker,
+ struct vg_state *state);
+void dash_stroker_cleanup(struct dash_stroker *stroker);
+void stroker_cleanup(struct stroker *stroker);
+
+void stroker_begin(struct stroker *stroker);
+void stroker_move_to(struct stroker *stroker, VGfloat x, VGfloat y);
+void stroker_line_to(struct stroker *stroker, VGfloat x, VGfloat y);
+void stroker_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1,
+ VGfloat px2, VGfloat py2,
+ VGfloat x, VGfloat y);
+void stroker_end(struct stroker *stroker);
+
+void stroker_emit_move_to(struct stroker *stroker, VGfloat x, VGfloat y);
+void stroker_emit_line_to(struct stroker *stroker, VGfloat x, VGfloat y);
+void stroker_emit_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1,
+ VGfloat px2, VGfloat py2,
+ VGfloat x, VGfloat y);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/util_array.h b/src/gallium/state_trackers/vega/util_array.h
new file mode 100644
index 0000000000..4343dfe36e
--- /dev/null
+++ b/src/gallium/state_trackers/vega/util_array.h
@@ -0,0 +1,122 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef UTIL_ARRAY_H
+#define UTIL_ARRAY_H
+
+#include "util/u_memory.h"
+
+#define DEFAULT_ARRAY_SIZE 256
+
+struct array {
+ VGint datatype_size;
+ void *data;
+ VGint size;
+ VGint num_elements;
+};
+
+static INLINE struct array *array_create(VGint datatype_size)
+{
+ struct array *array = CALLOC_STRUCT(array);
+ array->datatype_size = datatype_size;
+
+ array->size = DEFAULT_ARRAY_SIZE;
+ array->data = malloc(array->size * array->datatype_size);
+
+ return array;
+}
+
+
+static INLINE struct array *array_create_size(VGint datatype_size, VGint size)
+{
+ struct array *array = CALLOC_STRUCT(array);
+ array->datatype_size = datatype_size;
+
+ array->size = size;
+ array->data = malloc(array->size * array->datatype_size);
+
+ return array;
+}
+
+static INLINE void array_destroy(struct array *array)
+{
+ if (array)
+ free(array->data);
+ free(array);
+}
+
+static INLINE void array_resize(struct array *array, int num)
+{
+ VGint size = array->datatype_size * num;
+ void *data = malloc(size);
+ memcpy(data, array->data, array->size * array->datatype_size);
+ free(array->data);
+ array->data = data;
+ array->size = num;
+ array->num_elements = (array->num_elements > num) ? num :
+ array->num_elements;
+}
+
+static INLINE void array_append_data(struct array *array,
+ const void *data, int num_elements)
+{
+ VGbyte *adata;
+
+ while (array->num_elements + num_elements > array->size) {
+ array_resize(array, (array->num_elements + num_elements) * 1.5);
+ }
+ adata = (VGbyte *)array->data;
+ memcpy(adata + (array->num_elements * array->datatype_size), data,
+ num_elements * array->datatype_size);
+ array->num_elements += num_elements;
+}
+
+static INLINE void array_change_data(struct array *array,
+ const void *data,
+ int start_idx,
+ int num_elements)
+{
+ VGbyte *adata = (VGbyte *)array->data;
+ memcpy(adata + (start_idx * array->datatype_size), data,
+ num_elements * array->datatype_size);
+}
+
+static INLINE void array_remove_element(struct array *array,
+ int idx)
+{
+ VGbyte *adata = (VGbyte *)array->data;
+ memmove(adata + (idx * array->datatype_size),
+ adata + ((idx + 1) * array->datatype_size),
+ (array->num_elements - idx - 1) * array->datatype_size);
+ --array->num_elements;
+}
+
+static INLINE void array_reset(struct array *array)
+{
+ array->num_elements = 0;
+}
+
+#endif
diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c
new file mode 100644
index 0000000000..e0ff02f3a9
--- /dev/null
+++ b/src/gallium/state_trackers/vega/vg_context.c
@@ -0,0 +1,543 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vg_context.h"
+
+#include "paint.h"
+#include "renderer.h"
+#include "shaders_cache.h"
+#include "shader.h"
+#include "asm_util.h"
+#include "st_inlines.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "cso_cache/cso_context.h"
+
+#include "util/u_simple_shaders.h"
+#include "util/u_memory.h"
+#include "util/u_blit.h"
+
+struct vg_context *_vg_context = 0;
+
+struct vg_context * vg_current_context(void)
+{
+ return _vg_context;
+}
+
+static void init_clear(struct vg_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ /* rasterizer state: bypass clipping */
+ memset(&st->clear.raster, 0, sizeof(st->clear.raster));
+ st->clear.raster.gl_rasterization_rules = 1;
+
+ /* fragment shader state: color pass-through program */
+ st->clear.fs =
+ util_make_fragment_passthrough_shader(pipe);
+}
+void vg_set_current_context(struct vg_context *ctx)
+{
+ _vg_context = ctx;
+}
+
+struct vg_context * vg_create_context(struct pipe_context *pipe,
+ const void *visual,
+ struct vg_context *share)
+{
+ struct vg_context *ctx;
+
+ ctx = CALLOC_STRUCT(vg_context);
+
+ ctx->pipe = pipe;
+
+ vg_init_state(&ctx->state.vg);
+ ctx->state.dirty = ALL_DIRTY;
+
+ ctx->cso_context = cso_create_context(pipe);
+
+ init_clear(ctx);
+
+ ctx->default_paint = paint_create(ctx);
+ ctx->state.vg.stroke_paint = ctx->default_paint;
+ ctx->state.vg.fill_paint = ctx->default_paint;
+
+
+ ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ ctx->mask.sampler.normalized_coords = 0;
+
+ ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ ctx->blend_sampler.normalized_coords = 0;
+
+ vg_set_error(ctx, VG_NO_ERROR);
+
+ ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create();
+ ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create();
+ ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create();
+ ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create();
+ ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create();
+
+ ctx->renderer = renderer_create(ctx);
+ ctx->sc = shaders_cache_create(ctx);
+ ctx->shader = shader_create(ctx);
+
+ ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context);
+
+ return ctx;
+}
+
+void vg_destroy_context(struct vg_context *ctx)
+{
+ struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf;
+ struct pipe_constant_buffer *vsbuf = &ctx->vs_const_buffer;
+
+ util_destroy_blit(ctx->blit);
+ renderer_destroy(ctx->renderer);
+ shaders_cache_destroy(ctx->sc);
+ shader_destroy(ctx->shader);
+ paint_destroy(ctx->default_paint);
+
+ if (cbuf && cbuf->buffer)
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+
+ if (vsbuf && vsbuf->buffer)
+ pipe_buffer_reference(&vsbuf->buffer, NULL);
+
+ if (ctx->clear.fs) {
+ cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs);
+ ctx->clear.fs = NULL;
+ }
+
+ if (ctx->plain_vs) {
+ vg_shader_destroy(ctx, ctx->plain_vs);
+ ctx->plain_vs = NULL;
+ }
+ if (ctx->clear_vs) {
+ vg_shader_destroy(ctx, ctx->clear_vs);
+ ctx->clear_vs = NULL;
+ }
+ if (ctx->texture_vs) {
+ vg_shader_destroy(ctx, ctx->texture_vs);
+ ctx->texture_vs = NULL;
+ }
+
+ if (ctx->pass_through_depth_fs)
+ vg_shader_destroy(ctx, ctx->pass_through_depth_fs);
+ if (ctx->mask.union_fs)
+ vg_shader_destroy(ctx, ctx->mask.union_fs);
+ if (ctx->mask.intersect_fs)
+ vg_shader_destroy(ctx, ctx->mask.intersect_fs);
+ if (ctx->mask.subtract_fs)
+ vg_shader_destroy(ctx, ctx->mask.subtract_fs);
+ if (ctx->mask.set_fs)
+ vg_shader_destroy(ctx, ctx->mask.set_fs);
+
+ cso_release_all(ctx->cso_context);
+ cso_destroy_context(ctx->cso_context);
+
+ cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]);
+ cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]);
+ cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]);
+ cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]);
+ cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]);
+
+ free(ctx);
+}
+
+void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type)
+{
+ obj->type = type;
+ obj->ctx = ctx;
+}
+
+VGboolean vg_context_is_object_valid(struct vg_context *ctx,
+ enum vg_object_type type,
+ void *ptr)
+{
+ if (ctx) {
+ struct cso_hash *hash = ctx->owned_objects[type];
+ if (!hash)
+ return VG_FALSE;
+ return cso_hash_contains(hash, (unsigned)(long)ptr);
+ }
+ return VG_FALSE;
+}
+
+void vg_context_add_object(struct vg_context *ctx,
+ enum vg_object_type type,
+ void *ptr)
+{
+ if (ctx) {
+ struct cso_hash *hash = ctx->owned_objects[type];
+ if (!hash)
+ return;
+ cso_hash_insert(hash, (unsigned)(long)ptr, ptr);
+ }
+}
+
+void vg_context_remove_object(struct vg_context *ctx,
+ enum vg_object_type type,
+ void *ptr)
+{
+ if (ctx) {
+ struct cso_hash *hash = ctx->owned_objects[type];
+ if (!hash)
+ return;
+ cso_hash_take(hash, (unsigned)(long)ptr);
+ }
+}
+
+static void update_clip_state(struct vg_context *ctx)
+{
+ struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa;
+ struct vg_state *state = &ctx->state.vg;
+
+ memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
+
+ if (state->scissoring) {
+ struct pipe_blend_state *blend = &ctx->state.g3d.blend;
+ struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
+ dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/
+ dsa->depth.func = PIPE_FUNC_ALWAYS;
+ dsa->depth.enabled = 1;
+
+ cso_save_blend(ctx->cso_context);
+ cso_save_fragment_shader(ctx->cso_context);
+ /* set a passthrough shader */
+ if (!ctx->pass_through_depth_fs)
+ ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe,
+ pass_through_depth_asm,
+ 40,
+ PIPE_SHADER_FRAGMENT);
+ cso_set_fragment_shader_handle(ctx->cso_context,
+ ctx->pass_through_depth_fs->driver);
+ cso_set_depth_stencil_alpha(ctx->cso_context, dsa);
+
+ ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0);
+
+ /* disable color writes */
+ blend->colormask = 0; /*disable colorwrites*/
+ cso_set_blend(ctx->cso_context, blend);
+
+ /* enable scissoring */
+ for (int i = 0; i < state->scissor_rects_num; ++i) {
+ const float x = state->scissor_rects[i * 4 + 0].f;
+ const float y = state->scissor_rects[i * 4 + 1].f;
+ const float width = state->scissor_rects[i * 4 + 2].f;
+ const float height = state->scissor_rects[i * 4 + 3].f;
+ VGfloat minx, miny, maxx, maxy;
+
+ minx = 0;
+ miny = 0;
+ maxx = fb->width;
+ maxy = fb->height;
+
+ if (x > minx)
+ minx = x;
+ if (y > miny)
+ miny = y;
+
+ if (x + width < maxx)
+ maxx = x + width;
+ if (y + height < maxy)
+ maxy = y + height;
+
+ /* check for null space */
+ if (minx >= maxx || miny >= maxy)
+ minx = miny = maxx = maxy = 0;
+
+ /*glClear(GL_DEPTH_BUFFER_BIT);*/
+ renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f);
+ }
+
+ blend->colormask = 1; /*enable colorwrites*/
+ cso_restore_blend(ctx->cso_context);
+ cso_restore_fragment_shader(ctx->cso_context);
+
+ dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
+ dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
+ dsa->depth.func = PIPE_FUNC_GEQUAL;
+ }
+}
+
+void vg_validate_state(struct vg_context *ctx)
+{
+ if ((ctx->state.dirty & BLEND_DIRTY)) {
+ struct pipe_blend_state *blend = &ctx->state.g3d.blend;
+ memset(blend, 0, sizeof(struct pipe_blend_state));
+ blend->blend_enable = 1;
+ blend->colormask |= PIPE_MASK_R;
+ blend->colormask |= PIPE_MASK_G;
+ blend->colormask |= PIPE_MASK_B;
+ blend->colormask |= PIPE_MASK_A;
+
+ switch (ctx->state.vg.blend_mode) {
+ case VG_BLEND_SRC:
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ break;
+ case VG_BLEND_SRC_OVER:
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ break;
+ case VG_BLEND_DST_OVER:
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
+ break;
+ case VG_BLEND_SRC_IN:
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ break;
+ case VG_BLEND_DST_IN:
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
+ break;
+ case VG_BLEND_MULTIPLY:
+ case VG_BLEND_SCREEN:
+ case VG_BLEND_DARKEN:
+ case VG_BLEND_LIGHTEN:
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ break;
+ case VG_BLEND_ADDITIVE:
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+ break;
+ default:
+ assert(!"not implemented blend mode");
+ }
+ cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend);
+ }
+ if ((ctx->state.dirty & RASTERIZER_DIRTY)) {
+ struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer;
+ memset(raster, 0, sizeof(struct pipe_rasterizer_state));
+ raster->gl_rasterization_rules = 1;
+ cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer);
+ }
+ if ((ctx->state.dirty & VIEWPORT_DIRTY)) {
+ struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
+ const VGint param_bytes = 8 * sizeof(VGfloat);
+ VGfloat vs_consts[8] = {
+ 2.f/fb->width, 2.f/fb->height, 1, 1,
+ -1, -1, 0, 0
+ };
+ struct pipe_constant_buffer *cbuf = &ctx->vs_const_buffer;
+
+ vg_set_viewport(ctx, VEGA_Y0_BOTTOM);
+
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+ cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+
+ if (cbuf->buffer) {
+ st_no_flush_pipe_buffer_write(ctx, cbuf->buffer,
+ 0, param_bytes, vs_consts);
+ }
+ ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, cbuf);
+ }
+ if ((ctx->state.dirty & VS_DIRTY)) {
+ cso_set_vertex_shader_handle(ctx->cso_context,
+ vg_plain_vs(ctx));
+ }
+
+ /* must be last because it renders to the depth buffer*/
+ if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) {
+ update_clip_state(ctx);
+ cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa);
+ }
+
+ shader_set_masking(ctx->shader, ctx->state.vg.masking);
+ shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
+
+ ctx->state.dirty = NONE_DIRTY;
+}
+
+VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)
+{
+ struct vg_object *obj = ptr;
+ if (ptr && is_aligned(obj) && obj->type == type)
+ return VG_TRUE;
+ else
+ return VG_FALSE;
+}
+
+void vg_set_error(struct vg_context *ctx,
+ VGErrorCode code)
+{
+ /*vgGetError returns the oldest error code provided by
+ * an API call on the current context since the previous
+ * call to vgGetError on that context (or since the creation
+ of the context).*/
+ if (ctx->_error == VG_NO_ERROR)
+ ctx->_error = code;
+}
+
+void vg_prepare_blend_surface(struct vg_context *ctx)
+{
+ struct pipe_surface *dest_surface = NULL;
+ struct pipe_context *pipe = ctx->pipe;
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+ struct st_renderbuffer *strb = stfb->strb;
+
+ /* first finish all pending rendering */
+ vgFinish();
+
+ dest_surface = pipe->screen->get_tex_surface(pipe->screen,
+ stfb->blend_texture,
+ 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ /* flip it, because we want to use it as a sampler */
+ util_blit_pixels_tex(ctx->blit,
+ strb->texture,
+ 0, strb->height,
+ strb->width, 0,
+ dest_surface,
+ 0, 0,
+ strb->width, strb->height,
+ 0.0, PIPE_TEX_MIPFILTER_NEAREST);
+
+ if (dest_surface)
+ pipe_surface_reference(&dest_surface, NULL);
+
+ /* make sure it's complete */
+ vgFinish();
+}
+
+
+void vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
+{
+ struct pipe_surface *dest_surface = NULL;
+ struct pipe_context *pipe = ctx->pipe;
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+ struct st_renderbuffer *strb = stfb->strb;
+
+ vg_validate_state(ctx);
+
+ /* first finish all pending rendering */
+ vgFinish();
+
+ dest_surface = pipe->screen->get_tex_surface(pipe->screen,
+ stfb->blend_texture,
+ 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* flip it, because we want to use it as a sampler */
+ util_blit_pixels_tex(ctx->blit,
+ stfb->alpha_mask,
+ 0, strb->height,
+ strb->width, 0,
+ dest_surface,
+ 0, 0,
+ strb->width, strb->height,
+ 0.0, PIPE_TEX_MIPFILTER_NEAREST);
+
+ /* make sure it's complete */
+ vgFinish();
+
+ if (dest_surface)
+ pipe_surface_reference(&dest_surface, NULL);
+}
+
+void * vg_plain_vs(struct vg_context *ctx)
+{
+ if (!ctx->plain_vs) {
+ ctx->plain_vs = shader_create_from_text(ctx->pipe,
+ vs_plain_asm,
+ 200,
+ PIPE_SHADER_VERTEX);
+ }
+
+ return ctx->plain_vs->driver;
+}
+
+
+void * vg_clear_vs(struct vg_context *ctx)
+{
+ if (!ctx->clear_vs) {
+ ctx->clear_vs = shader_create_from_text(ctx->pipe,
+ vs_clear_asm,
+ 200,
+ PIPE_SHADER_VERTEX);
+ }
+
+ return ctx->clear_vs->driver;
+}
+
+void * vg_texture_vs(struct vg_context *ctx)
+{
+ if (!ctx->texture_vs) {
+ ctx->texture_vs = shader_create_from_text(ctx->pipe,
+ vs_texture_asm,
+ 200,
+ PIPE_SHADER_VERTEX);
+ }
+
+ return ctx->texture_vs->driver;
+}
+
+void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation)
+{
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
+ VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
+
+ viewport.scale[0] = fb->width / 2.f;
+ viewport.scale[1] = fb->height / y_scale;
+ viewport.scale[2] = 1.0;
+ viewport.scale[3] = 1.0;
+ viewport.translate[0] = fb->width / 2.f;
+ viewport.translate[1] = fb->height / 2.f;
+ viewport.translate[2] = 0.0;
+ viewport.translate[3] = 0.0;
+
+ cso_set_viewport(ctx->cso_context, &viewport);
+}
diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h
new file mode 100644
index 0000000000..ccc8889c8c
--- /dev/null
+++ b/src/gallium/state_trackers/vega/vg_context.h
@@ -0,0 +1,292 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef VG_CONTEXT_H
+#define VG_CONTEXT_H
+
+#include "vg_state.h"
+
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+#include "util/u_pointer.h"
+#include "util/u_math.h"
+
+#include "cso_cache/cso_hash.h"
+#include "cso_cache/cso_context.h"
+
+struct renderer;
+struct shaders_cache;
+struct shader;
+struct vg_shader;
+
+struct st_renderbuffer {
+ enum pipe_format format;
+ struct pipe_surface *surface;
+ struct pipe_texture *texture;
+ VGint width, height;
+};
+
+struct st_framebuffer {
+ VGint init_width, init_height;
+ struct st_renderbuffer *strb;
+ struct st_renderbuffer *dsrb;
+
+ struct pipe_texture *alpha_mask;
+
+ struct pipe_texture *blend_texture;
+
+ void *privateData;
+};
+
+enum vg_object_type {
+ VG_OBJECT_UNKNOWN = 0,
+ VG_OBJECT_PAINT,
+ VG_OBJECT_IMAGE,
+ VG_OBJECT_MASK,
+ VG_OBJECT_FONT,
+ VG_OBJECT_PATH,
+
+ VG_OBJECT_LAST
+};
+enum dirty_state {
+ NONE_DIRTY = 0<<0,
+ BLEND_DIRTY = 1<<1,
+ RASTERIZER_DIRTY = 1<<2,
+ VIEWPORT_DIRTY = 1<<3,
+ VS_DIRTY = 1<<4,
+ DEPTH_STENCIL_DIRTY = 1<<5,
+ ALL_DIRTY = BLEND_DIRTY | RASTERIZER_DIRTY |
+ VIEWPORT_DIRTY | VS_DIRTY | DEPTH_STENCIL_DIRTY
+};
+
+struct vg_context
+{
+ struct pipe_context *pipe;
+
+ struct {
+ struct vg_state vg;
+ struct {
+ struct pipe_blend_state blend;
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_shader_state vs_state;
+ struct pipe_depth_stencil_alpha_state dsa;
+ struct pipe_framebuffer_state fb;
+ } g3d;
+ VGbitfield dirty;
+ } state;
+
+ VGErrorCode _error;
+
+ struct st_framebuffer *draw_buffer;
+
+ struct cso_hash *owned_objects[VG_OBJECT_LAST];
+
+ struct {
+ struct pipe_shader_state vert_shader;
+ struct pipe_shader_state frag_shader;
+ struct pipe_rasterizer_state raster;
+ void *fs;
+ float vertices[4][2][4]; /**< vertex pos + color */
+ } clear;
+
+ struct {
+ struct pipe_constant_buffer cbuf;
+ struct pipe_sampler_state sampler;
+
+ struct vg_shader *union_fs;
+ struct vg_shader *intersect_fs;
+ struct vg_shader *subtract_fs;
+ struct vg_shader *set_fs;
+ } mask;
+
+ struct vg_shader *pass_through_depth_fs;
+
+ struct cso_context *cso_context;
+
+ struct pipe_buffer *stencil_quad;
+ VGfloat stencil_vertices[4][2][4];
+
+ struct renderer *renderer;
+ struct shaders_cache *sc;
+ struct shader *shader;
+
+ struct pipe_sampler_state blend_sampler;
+ struct {
+ struct pipe_constant_buffer buffer;
+ void *color_matrix_fs;
+ } filter;
+ struct vg_paint *default_paint;
+
+ struct blit_state *blit;
+
+ struct vg_shader *plain_vs;
+ struct vg_shader *clear_vs;
+ struct vg_shader *texture_vs;
+ struct pipe_constant_buffer vs_const_buffer;
+};
+
+struct vg_object {
+ enum vg_object_type type;
+ 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);
+
+struct vg_context *vg_create_context(struct pipe_context *pipe,
+ const void *visual,
+ struct vg_context *share);
+void vg_destroy_context(struct vg_context *ctx);
+struct vg_context *vg_current_context(void);
+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);
+void vg_context_add_object(struct vg_context *ctx,
+ enum vg_object_type type,
+ void *ptr);
+void vg_context_remove_object(struct vg_context *ctx,
+ enum vg_object_type type,
+ void *ptr);
+
+void vg_validate_state(struct vg_context *ctx);
+
+void vg_set_error(struct vg_context *ctx,
+ VGErrorCode code);
+
+void vg_prepare_blend_surface(struct vg_context *ctx);
+void vg_prepare_blend_surface_from_mask(struct vg_context *ctx);
+
+
+static INLINE VGboolean is_aligned_to(const void *ptr, VGbyte alignment)
+{
+ void *aligned = align_pointer(ptr, alignment);
+ return (ptr == aligned) ? VG_TRUE : VG_FALSE;
+}
+
+static INLINE VGboolean is_aligned(const void *ptr)
+{
+ return is_aligned_to(ptr, 4);
+}
+
+static INLINE void vg_shift_rectx(VGfloat coords[4],
+ const VGfloat *bounds,
+ const VGfloat shift)
+{
+ coords[0] += shift;
+ coords[2] -= shift;
+ if (bounds) {
+ coords[2] = MIN2(coords[2], bounds[2]);
+ /* bound x/y + width/height */
+ if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
+ coords[2] = (bounds[0] + bounds[2]) - coords[0];
+ }
+ }
+}
+
+static INLINE void vg_shift_recty(VGfloat coords[4],
+ const VGfloat *bounds,
+ const VGfloat shift)
+{
+ coords[1] += shift;
+ coords[3] -= shift;
+ if (bounds) {
+ coords[3] = MIN2(coords[3], bounds[3]);
+ if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
+ coords[3] = (bounds[1] + bounds[3]) - coords[1];
+ }
+ }
+}
+
+static INLINE void vg_bound_rect(VGfloat coords[4],
+ const VGfloat bounds[4],
+ VGfloat shift[4])
+{
+ /* if outside the bounds */
+ if (coords[0] > (bounds[0] + bounds[2]) ||
+ coords[1] > (bounds[1] + bounds[3]) ||
+ (coords[0] + coords[2]) < bounds[0] ||
+ (coords[1] + coords[3]) < bounds[1]) {
+ coords[0] = 0.f;
+ coords[1] = 0.f;
+ coords[2] = 0.f;
+ coords[3] = 0.f;
+ shift[0] = 0.f;
+ shift[1] = 0.f;
+ return;
+ }
+
+ /* bound x */
+ if (coords[0] < bounds[0]) {
+ shift[0] = bounds[0] - coords[0];
+ coords[2] -= shift[0];
+ coords[0] = bounds[0];
+ } else
+ shift[0] = 0.f;
+
+ /* bound y */
+ if (coords[1] < bounds[1]) {
+ shift[1] = bounds[1] - coords[1];
+ coords[3] -= shift[1];
+ coords[1] = bounds[1];
+ } else
+ shift[1] = 0.f;
+
+ shift[2] = bounds[2] - coords[2];
+ shift[3] = bounds[3] - coords[3];
+ /* bound width/height */
+ coords[2] = MIN2(coords[2], bounds[2]);
+ coords[3] = MIN2(coords[3], bounds[3]);
+
+ /* bound x/y + width/height */
+ if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
+ coords[2] = (bounds[0] + bounds[2]) - coords[0];
+ }
+ if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
+ coords[3] = (bounds[1] + bounds[3]) - coords[1];
+ }
+
+ /* if outside the bounds */
+ if ((coords[0] + coords[2]) < bounds[0] ||
+ (coords[1] + coords[3]) < bounds[1]) {
+ coords[0] = 0.f;
+ coords[1] = 0.f;
+ coords[2] = 0.f;
+ coords[3] = 0.f;
+ return;
+ }
+}
+
+void *vg_plain_vs(struct vg_context *ctx);
+void *vg_clear_vs(struct vg_context *ctx);
+void *vg_texture_vs(struct vg_context *ctx);
+typedef enum {
+ VEGA_Y0_TOP,
+ VEGA_Y0_BOTTOM
+} VegaOrientation;
+void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/vg_state.c b/src/gallium/state_trackers/vega/vg_state.c
new file mode 100644
index 0000000000..6f6bfdaf7a
--- /dev/null
+++ b/src/gallium/state_trackers/vega/vg_state.c
@@ -0,0 +1,124 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vg_state.h"
+
+#include <string.h>
+
+void vg_init_state(struct vg_state *state)
+{
+ state->matrix_mode = VG_MATRIX_PATH_USER_TO_SURFACE;
+ state->fill_rule = VG_EVEN_ODD;
+ state->image_quality = VG_IMAGE_QUALITY_FASTER;
+ state->rendering_quality = VG_RENDERING_QUALITY_BETTER;
+ state->blend_mode = VG_BLEND_SRC_OVER;
+ state->image_mode = VG_DRAW_IMAGE_NORMAL;
+
+ memset(state->scissor_rects, 0, sizeof(state->scissor_rects));
+ state->scissor_rects_num = 0;
+
+ state->color_transform = VG_FALSE;
+ state->color_transform_values[0] = 1.0f;
+ state->color_transform_values[1] = 1.0f;
+ state->color_transform_values[2] = 1.0f;
+ state->color_transform_values[3] = 1.0f;
+ state->color_transform_values[4] = 0.0f;
+ state->color_transform_values[5] = 0.0f;
+ state->color_transform_values[6] = 0.0f;
+ state->color_transform_values[7] = 0.0f;
+
+ /* Stroke parameters */
+ state->stroke.line_width.f = 1.0f;
+ state->stroke.line_width.i = 1;
+ state->stroke.cap_style = VG_CAP_BUTT;
+ state->stroke.join_style = VG_JOIN_MITER;
+ state->stroke.miter_limit.f = 4.0f;
+ state->stroke.miter_limit.i = 4;
+ state->stroke.dash_pattern_num = 0;
+ state->stroke.dash_phase.f = 0.0f;
+ state->stroke.dash_phase.i = 0;
+ state->stroke.dash_phase_reset = VG_FALSE;
+
+ /* Edge fill color for VG_TILE_FILL tiling mode */
+ state->tile_fill_color[0] = 0.0f;
+ state->tile_fill_color[1] = 0.0f;
+ state->tile_fill_color[2] = 0.0f;
+ state->tile_fill_color[3] = 0.0f;
+
+ /* Color for vgClear */
+ state->clear_color[0] = 0.0f;
+ state->clear_color[1] = 0.0f;
+ state->clear_color[2] = 0.0f;
+ state->clear_color[3] = 0.0f;
+
+ /* Glyph origin */
+ state->glyph_origin[0].f = 0.0f;
+ state->glyph_origin[1].f = 0.0f;
+ state->glyph_origin[0].i = 0;
+ state->glyph_origin[1].i = 0;
+
+ /* Enable/disable alpha masking and scissoring */
+ state->masking = VG_FALSE;
+ state->scissoring = VG_FALSE;
+
+ /* Pixel layout information */
+ state->pixel_layout = VG_PIXEL_LAYOUT_UNKNOWN;
+ state->screen_layout = VG_PIXEL_LAYOUT_UNKNOWN;
+
+ /* Source format selection for image filters */
+ state->filter_format_linear = VG_FALSE;
+ state->filter_format_premultiplied = VG_FALSE;
+
+ /* Destination write enable mask for image filters */
+ state->filter_channel_mask = (VG_RED | VG_GREEN | VG_BLUE | VG_ALPHA);
+
+ matrix_load_identity(&state->path_user_to_surface_matrix);
+ matrix_load_identity(&state->image_user_to_surface_matrix);
+ matrix_load_identity(&state->fill_paint_to_user_matrix);
+ matrix_load_identity(&state->stroke_paint_to_user_matrix);
+ matrix_load_identity(&state->glyph_user_to_surface_matrix);
+}
+
+struct matrix *vg_state_matrix(struct vg_state *state)
+{
+ switch(state->matrix_mode) {
+ case VG_MATRIX_PATH_USER_TO_SURFACE:
+ return &state->path_user_to_surface_matrix;
+ case VG_MATRIX_IMAGE_USER_TO_SURFACE:
+ return &state->image_user_to_surface_matrix;
+ case VG_MATRIX_FILL_PAINT_TO_USER:
+ return &state->fill_paint_to_user_matrix;
+ case VG_MATRIX_STROKE_PAINT_TO_USER:
+ return &state->stroke_paint_to_user_matrix;
+#ifdef OPENVG_VERSION_1_1
+ case VG_MATRIX_GLYPH_USER_TO_SURFACE:
+ return &state->glyph_user_to_surface_matrix;
+#endif
+ default:
+ break;
+ }
+ return NULL;
+}
diff --git a/src/gallium/state_trackers/vega/vg_state.h b/src/gallium/state_trackers/vega/vg_state.h
new file mode 100644
index 0000000000..ed90689f91
--- /dev/null
+++ b/src/gallium/state_trackers/vega/vg_state.h
@@ -0,0 +1,109 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef VG_STATE_H
+#define VG_STATE_H
+
+#include "VG/openvg.h"
+
+#include "api_consts.h"
+#include "matrix.h"
+
+struct vg_value
+{
+ VGfloat f;
+ VGint i;
+};
+
+struct vg_state {
+ /* Mode settings */
+ VGMatrixMode matrix_mode;
+ VGFillRule fill_rule;
+ VGImageQuality image_quality;
+ VGRenderingQuality rendering_quality;
+ VGBlendMode blend_mode;
+ VGImageMode image_mode;
+
+ /* Scissoring rectangles */
+ struct vg_value scissor_rects[32*4];
+ VGint scissor_rects_num;
+
+ /* Color Transformation */
+ VGboolean color_transform;
+ VGfloat color_transform_values[8];
+
+ /* Stroke parameters */
+ struct {
+ struct vg_value line_width;
+ VGCapStyle cap_style;
+ VGJoinStyle join_style;
+ struct vg_value miter_limit;
+ struct vg_value dash_pattern[VEGA_MAX_DASH_COUNT];
+ VGint dash_pattern_num;
+ struct vg_value dash_phase;
+ VGboolean dash_phase_reset;
+ } stroke;
+
+ /* Edge fill color for VG_TILE_FILL tiling mode */
+ VGfloat tile_fill_color[4];
+ VGint tile_fill_colori[4];
+
+ /* Color for vgClear */
+ VGfloat clear_color[4];
+ VGint clear_colori[4];
+
+ /* Glyph origin */
+ struct vg_value glyph_origin[2];
+
+ /* Enable/disable alpha masking and scissoring */
+ VGboolean masking;
+ VGboolean scissoring;
+
+ /* Pixel layout information */
+ VGPixelLayout pixel_layout;
+ VGPixelLayout screen_layout;
+
+ /* Source format selection for image filters */
+ VGboolean filter_format_linear;
+ VGboolean filter_format_premultiplied;
+
+ /* Destination write enable mask for image filters */
+ VGbitfield filter_channel_mask;
+
+ struct matrix path_user_to_surface_matrix;
+ struct matrix image_user_to_surface_matrix;
+ struct matrix fill_paint_to_user_matrix;
+ struct matrix stroke_paint_to_user_matrix;
+ struct matrix glyph_user_to_surface_matrix;
+
+ struct vg_paint *stroke_paint;
+ struct vg_paint *fill_paint;
+};
+
+void vg_init_state(struct vg_state *state);
+struct matrix * vg_state_matrix(struct vg_state *state);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c
new file mode 100644
index 0000000000..56cc60aebe
--- /dev/null
+++ b/src/gallium/state_trackers/vega/vg_tracker.c
@@ -0,0 +1,416 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vg_context.h"
+#include "vg_tracker.h"
+#include "mask.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_screen.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+static struct pipe_texture *
+create_texture(struct pipe_context *pipe, enum pipe_format format,
+ VGint width, VGint height)
+{
+ struct pipe_texture templ;
+
+ memset(&templ, 0, sizeof(templ));
+
+ if (format != PIPE_FORMAT_NONE) {
+ templ.format = format;
+ }
+ else {
+ templ.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ }
+
+ templ.target = PIPE_TEXTURE_2D;
+ pf_get_block(templ.format, &templ.block);
+ templ.width[0] = width;
+ templ.height[0] = height;
+ templ.depth[0] = 1;
+ templ.last_level = 0;
+
+ if (pf_get_component_bits(format, PIPE_FORMAT_COMP_S)) {
+ templ.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ } else {
+ templ.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_RENDER_TARGET |
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ }
+
+ return pipe->screen->texture_create(pipe->screen, &templ);
+}
+
+/**
+ * Allocate a renderbuffer for a an on-screen window (not a user-created
+ * renderbuffer). The window system code determines the format.
+ */
+static struct st_renderbuffer *
+st_new_renderbuffer_fb(enum pipe_format format)
+{
+ struct st_renderbuffer *strb;
+
+ strb = CALLOC_STRUCT(st_renderbuffer);
+ if (!strb) {
+ /*_vega_error(NULL, VG_OUT_OF_MEMORY, "creating renderbuffer");*/
+ return NULL;
+ }
+
+ strb->format = format;
+
+ return strb;
+}
+
+
+/**
+ * This is called to allocate the original drawing surface, and
+ * during window resize.
+ */
+static VGboolean
+st_renderbuffer_alloc_storage(struct vg_context * ctx,
+ struct st_renderbuffer *strb,
+ VGuint width, VGuint height)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ unsigned surface_usage;
+
+ /* Free the old surface and texture
+ */
+ pipe_surface_reference(&strb->surface, NULL);
+ pipe_texture_reference(&strb->texture, NULL);
+
+
+ /* Probably need dedicated flags for surface usage too:
+ */
+ surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ strb->texture = create_texture(pipe, strb->format,
+ width, height);
+
+ if (!strb->texture)
+ return FALSE;
+
+ strb->surface = pipe->screen->get_tex_surface(pipe->screen,
+ strb->texture,
+ 0, 0, 0,
+ surface_usage);
+ strb->width = width;
+ strb->height = height;
+
+ assert(strb->surface->width == width);
+ assert(strb->surface->height == height);
+
+ return strb->surface != NULL;
+}
+
+struct vg_context * st_create_context(struct pipe_context *pipe,
+ const void *visual,
+ struct vg_context *share)
+{
+ struct vg_context *ctx = vg_create_context(pipe, visual, share);
+ /*debug_printf("--------- CREATE CONTEXT %p\n", ctx);*/
+ return ctx;
+}
+
+void st_destroy_context(struct vg_context *st)
+{
+ /*debug_printf("--------- DESTROY CONTEXT %p\n", st);*/
+ vg_destroy_context(st);
+}
+
+void st_copy_context_state(struct vg_context *dst, struct vg_context *src,
+ uint mask)
+{
+ fprintf(stderr, "FIXME: %s\n", __FUNCTION__);
+}
+
+void st_get_framebuffer_dimensions(struct st_framebuffer *stfb,
+ uint *width,
+ uint *height)
+{
+ *width = stfb->strb->width;
+ *height = stfb->strb->height;
+}
+
+struct st_framebuffer * st_create_framebuffer(const void *visual,
+ enum pipe_format colorFormat,
+ enum pipe_format depthFormat,
+ enum pipe_format stencilFormat,
+ uint width, uint height,
+ void *privateData)
+{
+ struct st_framebuffer *stfb = CALLOC_STRUCT(st_framebuffer);
+ if (stfb) {
+ struct st_renderbuffer *rb =
+ st_new_renderbuffer_fb(colorFormat);
+ stfb->strb = rb;
+#if 0
+ if (doubleBuffer) {
+ struct st_renderbuffer *rb =
+ st_new_renderbuffer_fb(colorFormat);
+ }
+#endif
+
+ /* we want to combine the depth/stencil */
+ if (stencilFormat == depthFormat)
+ stfb->dsrb = st_new_renderbuffer_fb(stencilFormat);
+ else
+ stfb->dsrb = st_new_renderbuffer_fb(PIPE_FORMAT_S8Z24_UNORM);
+
+ /*### currently we always allocate it but it's possible it's
+ not necessary if EGL_ALPHA_MASK_SIZE was 0
+ */
+ stfb->alpha_mask = 0;
+
+ stfb->init_width = width;
+ stfb->init_height = height;
+ stfb->privateData = privateData;
+ }
+
+ return stfb;
+}
+
+static void setup_new_alpha_mask(struct vg_context *ctx,
+ struct st_framebuffer *stfb,
+ uint width, uint height)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_texture *old_texture = stfb->alpha_mask;
+
+ /*
+ we use PIPE_FORMAT_A8R8G8B8_UNORM because we want to render to
+ this texture and use it as a sampler, so while this wastes some
+ space it makes both of those a lot simpler
+ */
+ stfb->alpha_mask =
+ create_texture(pipe, PIPE_FORMAT_A8R8G8B8_UNORM, width, height);
+
+ if (!stfb->alpha_mask) {
+ if (old_texture)
+ pipe_texture_reference(&old_texture, NULL);
+ return;
+ }
+
+ vg_validate_state(ctx);
+
+ /* alpha mask starts with 1.f alpha */
+ mask_fill(0, 0, width, height, 1.f);
+
+ /* if we had an old surface copy it over */
+ if (old_texture) {
+ struct pipe_surface *surface = pipe->screen->get_tex_surface(
+ pipe->screen,
+ stfb->alpha_mask,
+ 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ struct pipe_surface *old_surface = pipe->screen->get_tex_surface(
+ pipe->screen,
+ old_texture,
+ 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ);
+ pipe->surface_copy(pipe,
+ surface,
+ 0, 0,
+ old_surface,
+ 0, 0,
+ MIN2(old_surface->width, width),
+ MIN2(old_surface->height, height));
+ if (surface)
+ pipe_surface_reference(&surface, NULL);
+ if (old_surface)
+ pipe_surface_reference(&old_surface, NULL);
+ }
+
+ /* Free the old texture
+ */
+ if (old_texture)
+ pipe_texture_reference(&old_texture, NULL);
+}
+
+void st_resize_framebuffer(struct st_framebuffer *stfb,
+ uint width, uint height)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct st_renderbuffer *strb = stfb->strb;
+ struct pipe_framebuffer_state *state;
+
+ if (!ctx)
+ return;
+
+ state = &ctx->state.g3d.fb;
+
+ /* If this is a noop, exit early and don't do the clear, etc below.
+ */
+ if (strb->width == width &&
+ strb->height == height &&
+ state->zsbuf)
+ return;
+
+ if (strb->width != width || strb->height != height)
+ st_renderbuffer_alloc_storage(ctx, strb,
+ width, height);
+
+ if (stfb->dsrb->width != width || stfb->dsrb->height != height)
+ st_renderbuffer_alloc_storage(ctx, stfb->dsrb,
+ width, height);
+
+ {
+ VGuint i;
+
+ memset(state, 0, sizeof(struct pipe_framebuffer_state));
+
+ state->width = width;
+ state->height = height;
+
+ state->nr_cbufs = 1;
+ state->cbufs[0] = strb->surface;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ state->cbufs[i] = 0;
+
+ state->zsbuf = stfb->dsrb->surface;
+
+ cso_set_framebuffer(ctx->cso_context, state);
+ }
+
+ ctx->state.dirty |= VIEWPORT_DIRTY;
+ ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/
+
+ ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL,
+ NULL, 0.0, 0);
+
+ /* we need all the other state already set */
+
+ setup_new_alpha_mask(ctx, stfb, width, height);
+
+ pipe_texture_reference( &stfb->blend_texture, NULL );
+ stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_A8R8G8B8_UNORM,
+ width, height);
+}
+
+void st_set_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface *surf)
+{
+ struct st_renderbuffer *rb = stfb->strb;
+
+ /* unreference existing surfaces */
+ pipe_surface_reference( &rb->surface, NULL );
+ pipe_texture_reference( &rb->texture, NULL );
+
+ /* reference new ones */
+ pipe_surface_reference( &rb->surface, surf );
+ pipe_texture_reference( &rb->texture, surf->texture );
+
+ rb->width = surf->width;
+ rb->height = surf->height;
+}
+
+int st_get_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface **surf)
+{
+ struct st_renderbuffer *rb = stfb->strb;
+ *surf = rb->surface;
+ return VG_TRUE;
+}
+
+int st_get_framebuffer_texture(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_texture **tex)
+{
+ struct st_renderbuffer *rb = stfb->strb;
+ *tex = rb->texture;
+ return VG_TRUE;
+}
+
+void * st_framebuffer_private(struct st_framebuffer *stfb)
+{
+ return stfb->privateData;
+}
+
+void st_unreference_framebuffer(struct st_framebuffer *stfb)
+{
+ /* FIXME */
+}
+
+void st_make_current(struct vg_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read)
+{
+ vg_set_current_context(st);
+ if (st) {
+ st->draw_buffer = draw;
+ }
+}
+
+struct vg_context *st_get_current(void)
+{
+ return vg_current_context();
+}
+
+void st_flush(struct vg_context *st, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence)
+{
+ st->pipe->flush(st->pipe, pipeFlushFlags, fence);
+}
+
+void st_finish(struct vg_context *st)
+{
+ struct pipe_fence_handle *fence = NULL;
+
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, &fence);
+
+ st->pipe->screen->fence_finish(st->pipe->screen, fence, 0);
+ st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
+}
+
+void st_notify_swapbuffers(struct st_framebuffer *stfb)
+{
+ struct vg_context *ctx = vg_current_context();
+ if (ctx && ctx->draw_buffer == stfb) {
+ st_flush(ctx,
+ PIPE_FLUSH_RENDER_CACHE |
+ PIPE_FLUSH_SWAPBUFFERS |
+ PIPE_FLUSH_FRAME,
+ NULL);
+ }
+}
+
+void st_notify_swapbuffers_complete(struct st_framebuffer *stfb)
+{
+}
+
+int st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
+ enum pipe_format format)
+{
+ return 0;
+}
+
+int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level)
+{
+ return 0;
+}
diff --git a/src/gallium/state_trackers/vega/vg_tracker.h b/src/gallium/state_trackers/vega/vg_tracker.h
new file mode 100644
index 0000000000..5457631106
--- /dev/null
+++ b/src/gallium/state_trackers/vega/vg_tracker.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef VG_TRACKER_H
+#define VG_TRACKER_H
+
+#include "VG/openvg.h"
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+
+#define ST_SURFACE_FRONT_LEFT 0
+#define ST_SURFACE_BACK_LEFT 1
+#define ST_SURFACE_FRONT_RIGHT 2
+#define ST_SURFACE_BACK_RIGHT 3
+#define ST_SURFACE_DEPTH 8
+
+struct vg_context;
+struct st_framebuffer;
+struct pipe_context;
+struct pipe_fence_handle;
+struct pipe_surface;
+
+
+struct vg_context *st_create_context(struct pipe_context *pipe,
+ const void *visual,
+ struct vg_context *share);
+
+void st_destroy_context( struct vg_context *st );
+
+void st_copy_context_state(struct vg_context *dst, struct vg_context *src,
+ uint mask);
+
+struct st_framebuffer *st_create_framebuffer(const void *visual,
+ enum pipe_format colorFormat,
+ enum pipe_format depthFormat,
+ enum pipe_format stencilFormat,
+ uint width, uint height,
+ void *privateData);
+
+void st_resize_framebuffer(struct st_framebuffer *stfb,
+ uint width, uint height);
+
+void st_set_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface *surf);
+
+void st_get_framebuffer_dimensions( struct st_framebuffer *stfb,
+ uint *width, uint *height);
+
+int st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
+ enum pipe_format format);
+
+int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level);
+
+int st_get_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface **surf);
+
+int st_get_framebuffer_texture(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_texture **tex);
+
+void *st_framebuffer_private(struct st_framebuffer *stfb);
+
+void st_unreference_framebuffer(struct st_framebuffer *stfb);
+
+void st_make_current(struct vg_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read);
+
+struct vg_context *st_get_current(void);
+
+void st_flush(struct vg_context *st, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence);
+void st_finish(struct vg_context *st);
+
+void st_notify_swapbuffers(struct st_framebuffer *stfb);
+void st_notify_swapbuffers_complete(struct st_framebuffer *stfb);
+
+
+/** Generic function type */
+typedef void (*st_proc)();
+
+st_proc st_get_proc_address(const char *procname);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/vg_translate.c b/src/gallium/state_trackers/vega/vg_translate.c
new file mode 100644
index 0000000000..00e0764706
--- /dev/null
+++ b/src/gallium/state_trackers/vega/vg_translate.c
@@ -0,0 +1,1030 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vg_translate.h"
+
+#include "pipe/p_format.h"
+#include "util/u_pack_color.h"
+
+void _vega_pack_rgba_span_float(struct vg_context *ctx,
+ VGuint n, VGfloat rgba[][4],
+ VGImageFormat dstFormat,
+ void *dstAddr)
+{
+ VGint i;
+
+ switch (dstFormat) {
+ case VG_sRGBX_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = 255;
+ dst[i] = r << 24 | g << 16 | b << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_sRGBA_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = r << 24 | g << 16 | b << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_sRGBA_8888_PRE: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = r << 24 | g << 16 | b << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_sRGB_565: {
+ VGshort *dst = (VGshort *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ r = (r / 255.0) * 32;
+ g = (g / 255.0) * 32;
+ b = (b / 255.0) * 32;
+
+ dst[i] = b | g << 5 | r << 11;
+ }
+ return;
+ }
+ break;
+ case VG_sRGBA_5551: {
+ VGshort *dst = (VGshort *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b, a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ r = (r / 255.0) * 32;
+ g = (g / 255.0) * 32;
+ b = (b / 255.0) * 32;
+ a = (a / 255.0);
+
+ dst[i] = a | b << 1 | g << 6 | r << 11;
+ }
+ return;
+ }
+ break;
+ case VG_sRGBA_4444: {
+ VGshort *dst = (VGshort *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b, a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ r = (r / 255.0) * 16;
+ g = (g / 255.0) * 16;
+ b = (b / 255.0) * 16;
+ a = (a / 255.0) * 16;
+
+ dst[i] = a | b << 4 | g << 8 | r << 12;
+ }
+ return;
+ }
+ break;
+ case VG_sL_8: {
+ VGubyte *dst = (VGubyte *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b, a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+
+ dst[i] = a;
+ }
+ return;
+ }
+ break;
+ case VG_lRGBX_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = 255;
+ dst[i] = r << 24 | g << 16 | b << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_lRGBA_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = r << 24 | g << 16 | b << 8 | a;
+ }
+ return;
+ }
+ case VG_lRGBA_8888_PRE: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = r << 24 | g << 16 | b << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_lL_8: {
+ VGubyte *dst = (VGubyte *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = a;
+ }
+ return;
+ }
+ break;
+ case VG_A_8: {
+ VGubyte *dst = (VGubyte *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b, a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+
+ dst[i] = a;
+ }
+ return;
+ }
+ break;
+ case VG_BW_1: {
+ VGshort *dst = (VGshort *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b, a;
+ VGubyte res;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+
+ res = (r + g + b + a)/4;
+ dst[i] = (res & (128));
+ }
+ return;
+ }
+ break;
+#ifdef OPENVG_VERSION_1_1
+ case VG_A_1: {
+ VGshort *dst = (VGshort *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b, a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+
+ dst[i] = (a & (128));
+ }
+ return;
+ }
+ break;
+ case VG_A_4: {
+ VGshort *dst = (VGshort *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b, a;
+ VGubyte res;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+
+ res = a/4;
+ dst[i] = (res & (128));
+ }
+ return;
+ }
+ break;
+#endif
+ case VG_sXRGB_8888:
+ break;
+ case VG_sARGB_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = a << 24 | r << 16 | g << 8 | b;
+ }
+ return;
+ }
+ break;
+ case VG_sARGB_8888_PRE: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = a << 24 | r << 16 | g << 8 | b;
+ }
+ return;
+ }
+ break;
+ case VG_sARGB_1555:
+ break;
+ case VG_sARGB_4444:
+ break;
+ case VG_lXRGB_8888:
+ break;
+ case VG_lARGB_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = a << 24 | r << 16 | g << 8 | b;
+ }
+ return;
+ }
+ break;
+ case VG_lARGB_8888_PRE: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = a << 24 | r << 16 | g << 8 | b;
+ }
+ return;
+ }
+ break;
+ case VG_sBGRX_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = 0xff;
+ dst[i] = b << 24 | g << 16 | r << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_sBGRA_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = b << 24 | g << 16 | r << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_sBGRA_8888_PRE: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = b << 24 | g << 16 | r << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_sBGR_565:
+ break;
+ case VG_sBGRA_5551:
+ break;
+ case VG_sBGRA_4444:
+ break;
+ case VG_lBGRX_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = 0xff;
+ dst[i] = b << 24 | g << 16 | r << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_lBGRA_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = b << 24 | g << 16 | r << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_lBGRA_8888_PRE: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = b << 24 | g << 16 | r << 8 | a;
+ }
+ return;
+ }
+ break;
+ case VG_sXBGR_8888:
+ break;
+ case VG_sABGR_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = a << 24 | b << 16 | g << 8 | r;
+ }
+ return;
+ }
+ break;
+ case VG_sABGR_8888_PRE: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = a << 24 | b << 16 | g << 8 | r;
+ }
+ return;
+ }
+ break;
+ case VG_sABGR_1555:
+ break;
+ case VG_sABGR_4444:
+ break;
+ case VG_lXBGR_8888:
+ break;
+ case VG_lABGR_8888: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = a << 24 | b << 16 | g << 8 | r;
+ }
+ return;
+ }
+ break;
+ case VG_lABGR_8888_PRE: {
+ VGint *dst = (VGint *)dstAddr;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = float_to_ubyte(rgba[i][0]);
+ g = float_to_ubyte(rgba[i][1]);
+ b = float_to_ubyte(rgba[i][2]);
+ a = float_to_ubyte(rgba[i][3]);
+ dst[i] = a << 24 | b << 16 | g << 8 | r;
+ }
+ return;
+ }
+ break;
+ default:
+ assert(!"Unknown ReadPixels format");
+ break;
+ }
+ assert(!"Not implemented ReadPixels format");
+}
+
+void _vega_unpack_float_span_rgba(struct vg_context *ctx,
+ VGuint n,
+ VGuint offset,
+ const void * data,
+ VGImageFormat dataFormat,
+ VGfloat rgba[][4])
+{
+ VGint i;
+
+ switch (dataFormat) {
+ case VG_sRGBX_8888: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ b = (*src >> 8) & 0xff;
+ a = 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ }
+ return;
+ case VG_sRGBA_8888: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ b = (*src >> 8) & 0xff;
+ a = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sRGBA_8888_PRE: {
+ VGint *src = (VGint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ b = (*src >> 8) & 0xff;
+ a = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sRGB_565: {
+ VGshort *src = (VGshort *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGfloat clr[4];
+ clr[0] = ((*src >> 10) & 31)/31.;
+ clr[1] = ((*src >> 5) & 95)/95.;
+ clr[2] = ((*src >> 0) & 31)/31.;
+ clr[3] = 1.f;
+
+ util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ }
+ return;
+ case VG_sRGBA_5551: {
+ VGshort *src = (VGshort *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGfloat clr[4];
+ clr[0] = ((*src >> 10) & 31)/31.;
+ clr[1] = ((*src >> 5) & 31)/31.;
+ clr[2] = ((*src >> 1) & 31)/31.;
+ clr[3] = ((*src >> 0) & 1)/1.;
+
+ util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ }
+ return;
+ case VG_sRGBA_4444: {
+ VGshort *src = (VGshort *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGfloat clr[4];
+ clr[0] = ((*src >> 12) & 15)/15.;
+ clr[1] = ((*src >> 8) & 15)/15.;
+ clr[2] = ((*src >> 4) & 15)/15.;
+ clr[3] = ((*src >> 0) & 15)/15.;
+
+ util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ }
+ return;
+ case VG_sL_8: {
+ VGubyte *src = (VGubyte *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ util_pack_color_ub(0xff, 0xff, 0xff, *src, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ }
+ return;
+ case VG_lRGBX_8888: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ b = (*src >> 8) & 0xff;
+ a = 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ }
+ return;
+ case VG_lRGBA_8888: {
+ VGint *src = (VGint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ b = (*src >> 8) & 0xff;
+ a = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_lRGBA_8888_PRE: {
+ VGint *src = (VGint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ r = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ b = (*src >> 8) & 0xff;
+ a = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_lL_8: {
+ VGubyte *src = (VGubyte *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ util_pack_color_ub(0xff, 0xff, 0xff, *src, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ }
+ return;
+ case VG_A_8: {
+ VGubyte *src = (VGubyte *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ util_pack_color_ub(0xff, 0xff, 0xff, *src, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ }
+ return;
+ case VG_BW_1: {
+ VGubyte *src = (VGubyte *)data;
+ src += offset;
+ for (i = 0; i < n; i += 8) {
+ VGfloat clr[4];
+ VGint j;
+ for (j = 0; j < 8 && j < n ; ++j) {
+ VGint shift = j;
+ clr[0] = (((*src) & (1<<shift)) >> shift);
+ clr[1] = clr[0];
+ clr[2] = clr[0];
+ clr[3] = 1.f;
+
+ util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i+j]);
+ }
+ ++src;
+ }
+ }
+ return;
+#ifdef OPENVG_VERSION_1_1
+ case VG_A_1: {
+ VGubyte *src = (VGubyte *)data;
+ src += offset;
+ for (i = 0; i < n; i += 8) {
+ VGfloat clr[4];
+ VGint j;
+ for (j = 0; j < 8 && j < n ; ++j) {
+ VGint shift = j;
+ clr[0] = 0.f;
+ clr[1] = 0.f;
+ clr[2] = 0.f;
+ clr[3] = (((*src) & (1<<shift)) >> shift);
+
+ util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i+j]);
+ }
+ ++src;
+ }
+ }
+ return;
+ case VG_A_4: {
+ VGubyte *src = (VGubyte *)data;
+ src += offset/2;
+ for (i = 0; i < n; i += 2) {
+ VGfloat clr[4];
+ VGint j;
+ for (j = 0; j < n && j < 2; ++j) {
+ VGint bitter, shift;
+ if (j == 0) {
+ bitter = 0x0f;
+ shift = 0;
+ } else {
+ bitter = 0xf0;
+ shift = 4;
+ }
+ clr[0] = 0.f;
+ clr[1] = 0.f;
+ clr[2] = 0.f;
+ clr[3] = ((*src) & (bitter)) >> shift;
+
+ util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i +j]);
+ }
+ ++src;
+ }
+ }
+ return;
+#endif
+ case VG_sXRGB_8888:
+ break;
+ case VG_sARGB_8888: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ a = (*src >> 24) & 0xff;
+ r = (*src >> 16) & 0xff;
+ g = (*src >> 8) & 0xff;
+ b = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sARGB_8888_PRE: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ a = (*src >> 24) & 0xff;
+ r = (*src >> 16) & 0xff;
+ g = (*src >> 8) & 0xff;
+ b = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sARGB_1555:
+ break;
+ case VG_sARGB_4444:
+ break;
+ case VG_lXRGB_8888:
+ break;
+ case VG_lARGB_8888: {
+ VGint *src = (VGint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ a = (*src >> 24) & 0xff;
+ r = (*src >> 16) & 0xff;
+ g = (*src >> 8) & 0xff;
+ b = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_lARGB_8888_PRE: {
+ VGint *src = (VGint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ a = (*src >> 24) & 0xff;
+ r = (*src >> 16) & 0xff;
+ g = (*src >> 8) & 0xff;
+ b = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sBGRX_8888:
+ break;
+ case VG_sBGRA_8888: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ b = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ r = (*src >> 8) & 0xff;
+ a = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sBGRA_8888_PRE: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ b = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ r = (*src >> 8) & 0xff;
+ a = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sBGR_565:
+ break;
+ case VG_sBGRA_5551:
+ break;
+ case VG_sBGRA_4444:
+ break;
+ case VG_lBGRX_8888:
+ break;
+ case VG_lBGRA_8888: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ b = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ r = (*src >> 8) & 0xff;
+ a = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_lBGRA_8888_PRE: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ b = (*src >> 24) & 0xff;
+ g = (*src >> 16) & 0xff;
+ r = (*src >> 8) & 0xff;
+ a = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sXBGR_8888:
+ break;
+ case VG_sABGR_8888: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ a = (*src >> 24) & 0xff;
+ b = (*src >> 16) & 0xff;
+ g = (*src >> 8) & 0xff;
+ r = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sABGR_8888_PRE: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ a = (*src >> 24) & 0xff;
+ b = (*src >> 16) & 0xff;
+ g = (*src >> 8) & 0xff;
+ r = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_sABGR_1555:
+ break;
+ case VG_sABGR_4444:
+ break;
+ case VG_lXBGR_8888:
+ break;
+ case VG_lABGR_8888: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ a = (*src >> 24) & 0xff;
+ b = (*src >> 16) & 0xff;
+ g = (*src >> 8) & 0xff;
+ r = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ case VG_lABGR_8888_PRE: {
+ VGuint *src = (VGuint *)data;
+ src += offset;
+ for (i = 0; i < n; ++i) {
+ VGubyte r, g, b ,a;
+ a = (*src >> 24) & 0xff;
+ b = (*src >> 16) & 0xff;
+ g = (*src >> 8) & 0xff;
+ r = (*src >> 0) & 0xff;
+
+ util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT,
+ rgba[i]);
+ ++src;
+ }
+ return;
+ }
+ break;
+ default:
+ assert(!"Unknown ReadPixels format");
+ break;
+ }
+ assert(!"Not implemented ReadPixels format");
+}
+
+VGint _vega_size_for_format(VGImageFormat dataFormat)
+{
+ switch (dataFormat) {
+ case VG_sRGBX_8888:
+ case VG_sRGBA_8888:
+ case VG_sRGBA_8888_PRE:
+ return 4;
+ case VG_sRGB_565:
+ case VG_sRGBA_5551:
+ case VG_sRGBA_4444:
+ return 2;
+ case VG_sL_8:
+ return 1;
+ case VG_lRGBX_8888:
+ case VG_lRGBA_8888:
+ case VG_lRGBA_8888_PRE:
+ return 4;
+ case VG_lL_8:
+ return 1;
+ case VG_A_8:
+ return 1;
+ case VG_BW_1:
+ return 1;
+#ifdef OPENVG_VERSION_1_1
+ case VG_A_1:
+ break;
+ case VG_A_4:
+ break;
+#endif
+ case VG_sXRGB_8888:
+ case VG_sARGB_8888:
+ case VG_sARGB_8888_PRE:
+ return 4;
+ case VG_sARGB_1555:
+ case VG_sARGB_4444:
+ return 2;
+ case VG_lXRGB_8888:
+ case VG_lARGB_8888:
+ case VG_lARGB_8888_PRE:
+ case VG_sBGRX_8888:
+ case VG_sBGRA_8888:
+ case VG_sBGRA_8888_PRE:
+ return 4;
+ case VG_sBGR_565:
+ case VG_sBGRA_5551:
+ case VG_sBGRA_4444:
+ return 2;
+ case VG_lBGRX_8888:
+ case VG_lBGRA_8888:
+ case VG_lBGRA_8888_PRE:
+ case VG_sXBGR_8888:
+ case VG_sABGR_8888:
+ case VG_sABGR_8888_PRE:
+ return 4;
+ case VG_sABGR_1555:
+ case VG_sABGR_4444:
+ return 2;
+ case VG_lXBGR_8888:
+ case VG_lABGR_8888:
+ case VG_lABGR_8888_PRE:
+ return 4;
+ default:
+ assert(!"Unknown ReadPixels format");
+ break;
+ }
+ assert(!"Not implemented ReadPixels format");
+ return 0;
+}
diff --git a/src/gallium/state_trackers/vega/vg_translate.h b/src/gallium/state_trackers/vega/vg_translate.h
new file mode 100644
index 0000000000..70815bacbc
--- /dev/null
+++ b/src/gallium/state_trackers/vega/vg_translate.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef VG_TRANSLATE_H
+#define VG_TRANSLATE_H
+
+#include "VG/openvg.h"
+#include "vg_context.h"
+
+/*FIXME: we really should be using translate module
+ * but pipe_format can't express some of the VG formats
+ * (the premultiplied ones) so currently it won't work */
+
+void _vega_pack_rgba_span_float(struct vg_context *ctx,
+ VGuint n, VGfloat rgba[][4],
+ VGImageFormat dstFormat,
+ void *dstAddr);
+void _vega_unpack_float_span_rgba(struct vg_context *ctx,
+ VGuint n,
+ VGuint offset,
+ const void * data,
+ VGImageFormat dataFormat,
+ VGfloat rgba[][4]);
+VGint _vega_size_for_format(VGImageFormat format);
+
+#endif
diff --git a/src/gallium/state_trackers/vega/vgu.c b/src/gallium/state_trackers/vega/vgu.c
new file mode 100644
index 0000000000..7dc51c5599
--- /dev/null
+++ b/src/gallium/state_trackers/vega/vgu.c
@@ -0,0 +1,450 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "VG/openvg.h"
+#include "VG/vgu.h"
+
+#include "matrix.h"
+#include "path.h"
+
+#include "util/u_debug.h"
+#include "util/u_pointer.h"
+
+#include <math.h>
+#include <assert.h>
+
+static VGboolean is_aligned_to(const void *ptr, VGbyte alignment)
+{
+ void *aligned = align_pointer(ptr, alignment);
+ return (ptr == aligned) ? VG_TRUE : VG_FALSE;
+}
+
+static VGboolean is_aligned(const void *ptr)
+{
+ return is_aligned_to(ptr, 4);
+}
+
+static void vgu_append_float_coords(VGPath path,
+ const VGubyte *cmds,
+ VGint num_cmds,
+ const VGfloat *coords,
+ VGint num_coords)
+{
+ VGubyte common_data[40 * sizeof(VGfloat)];
+ struct path *p = (struct path *)path;
+
+ vg_float_to_datatype(path_datatype(p), common_data, coords, num_coords);
+ vgAppendPathData(path, num_cmds, cmds, common_data);
+}
+
+VGUErrorCode vguLine(VGPath path,
+ VGfloat x0, VGfloat y0,
+ VGfloat x1, VGfloat y1)
+{
+ static const VGubyte cmds[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS};
+ VGfloat coords[4];
+ VGbitfield caps;
+
+ if (path == VG_INVALID_HANDLE) {
+ return VGU_BAD_HANDLE_ERROR;
+ }
+ caps = vgGetPathCapabilities(path);
+ if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
+ return VGU_PATH_CAPABILITY_ERROR;
+ }
+
+ coords[0] = x0;
+ coords[1] = y0;
+ coords[2] = x1;
+ coords[3] = y1;
+
+ vgu_append_float_coords(path, cmds, 2, coords, 4);
+
+ return VGU_NO_ERROR;
+}
+
+VGUErrorCode vguPolygon(VGPath path,
+ const VGfloat * points,
+ VGint count,
+ VGboolean closed)
+{
+ VGubyte *cmds;
+ VGfloat *coords;
+ VGbitfield caps;
+ VGint i;
+
+ if (path == VG_INVALID_HANDLE) {
+ return VGU_BAD_HANDLE_ERROR;
+ }
+
+ if (!points || count <= 0 || !is_aligned(points)) {
+ return VGU_ILLEGAL_ARGUMENT_ERROR;
+ }
+
+ caps = vgGetPathCapabilities(path);
+ if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
+ return VGU_PATH_CAPABILITY_ERROR;
+ }
+
+ cmds = malloc(sizeof(VGubyte) * count + 1);
+ coords = malloc(sizeof(VGfloat) * count * 2);
+
+ cmds[0] = VG_MOVE_TO_ABS;
+ coords[0] = points[0];
+ coords[1] = points[1];
+ for (i = 1; i < count; ++i) {
+ cmds[i] = VG_LINE_TO_ABS;
+ coords[2*i + 0] = points[2*i + 0];
+ coords[2*i + 1] = points[2*i + 1];
+ }
+
+ if (closed) {
+ cmds[i] = VG_CLOSE_PATH;
+ ++i;
+ }
+
+ vgu_append_float_coords(path, cmds, i, coords, 2*i);
+
+ free(cmds);
+ free(coords);
+
+ return VGU_NO_ERROR;
+}
+
+VGUErrorCode vguRect(VGPath path,
+ VGfloat x, VGfloat y,
+ VGfloat width, VGfloat height)
+{
+ static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
+ VG_HLINE_TO_REL,
+ VG_VLINE_TO_REL,
+ VG_HLINE_TO_REL,
+ VG_CLOSE_PATH
+ };
+ VGfloat coords[5];
+ VGbitfield caps;
+
+ if (path == VG_INVALID_HANDLE) {
+ return VGU_BAD_HANDLE_ERROR;
+ }
+ caps = vgGetPathCapabilities(path);
+ if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
+ return VGU_PATH_CAPABILITY_ERROR;
+ }
+ if (width <= 0 || height <= 0) {
+ return VGU_ILLEGAL_ARGUMENT_ERROR;
+ }
+
+ coords[0] = x;
+ coords[1] = y;
+ coords[2] = width;
+ coords[3] = height;
+ coords[4] = -width;
+
+ vgu_append_float_coords(path, cmds, 5, coords, 5);
+
+ return VGU_NO_ERROR;
+}
+
+VGUErrorCode vguRoundRect(VGPath path,
+ VGfloat x, VGfloat y,
+ VGfloat width,
+ VGfloat height,
+ VGfloat arcWidth,
+ VGfloat arcHeight)
+{
+ static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
+ VG_HLINE_TO_REL,
+ VG_SCCWARC_TO_REL,
+ VG_VLINE_TO_REL,
+ VG_SCCWARC_TO_REL,
+ VG_HLINE_TO_REL,
+ VG_SCCWARC_TO_REL,
+ VG_VLINE_TO_REL,
+ VG_SCCWARC_TO_REL,
+ VG_CLOSE_PATH
+ };
+ VGfloat c[26];
+ VGbitfield caps;
+
+ if (path == VG_INVALID_HANDLE) {
+ return VGU_BAD_HANDLE_ERROR;
+ }
+ caps = vgGetPathCapabilities(path);
+ if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
+ return VGU_PATH_CAPABILITY_ERROR;
+ }
+ if (width <= 0 || height <= 0) {
+ return VGU_ILLEGAL_ARGUMENT_ERROR;
+ }
+
+ c[0] = x + arcWidth/2; c[1] = y;
+
+ c[2] = width - arcWidth;
+
+ c[3] = arcWidth/2; c[4] = arcHeight/2; c[5] = 0;
+ c[6] = arcWidth/2; c[7] = arcHeight/2;
+
+ c[8] = height - arcHeight;
+
+ c[9] = arcWidth/2; c[10] = arcHeight/2; c[11] = 0;
+ c[12] = -arcWidth/2; c[13] = arcHeight/2;
+
+ c[14] = -(width - arcWidth);
+
+ c[15] = arcWidth/2; c[16] = arcHeight/2; c[17] = 0;
+ c[18] = -arcWidth/2; c[19] = -arcHeight/2;
+
+ c[20] = -(height - arcHeight);
+
+ c[21] = arcWidth/2; c[22] = arcHeight/2; c[23] = 0;
+ c[24] = arcWidth/2; c[25] = -arcHeight/2;
+
+ vgu_append_float_coords(path, cmds, 10, c, 26);
+
+ return VGU_NO_ERROR;
+}
+
+VGUErrorCode vguEllipse(VGPath path,
+ VGfloat cx, VGfloat cy,
+ VGfloat width,
+ VGfloat height)
+{
+ static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
+ VG_SCCWARC_TO_REL,
+ VG_SCCWARC_TO_REL,
+ VG_CLOSE_PATH
+ };
+ VGfloat coords[12];
+ VGbitfield caps;
+
+ if (path == VG_INVALID_HANDLE) {
+ return VGU_BAD_HANDLE_ERROR;
+ }
+ caps = vgGetPathCapabilities(path);
+ if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
+ return VGU_PATH_CAPABILITY_ERROR;
+ }
+ if (width <= 0 || height <= 0) {
+ return VGU_ILLEGAL_ARGUMENT_ERROR;
+ }
+
+ coords[0] = cx + width/2; coords[1] = cy;
+
+ coords[2] = width/2; coords[3] = height/2; coords[4] = 0;
+ coords[5] = -width; coords[6] = 0;
+
+ coords[7] = width/2; coords[8] = height/2; coords[9] = 0;
+ coords[10] = width; coords[11] = 0;
+
+ vgu_append_float_coords(path, cmds, 4, coords, 11);
+
+ return VGU_NO_ERROR;
+}
+
+VGUErrorCode vguArc(VGPath path,
+ VGfloat x, VGfloat y,
+ VGfloat width, VGfloat height,
+ VGfloat startAngle,
+ VGfloat angleExtent,
+ VGUArcType arcType)
+{
+ VGubyte cmds[11];
+ VGfloat coords[40];
+ VGbitfield caps;
+ VGfloat last = startAngle + angleExtent;
+ VGint i, c = 0;
+
+ if (path == VG_INVALID_HANDLE) {
+ return VGU_BAD_HANDLE_ERROR;
+ }
+ caps = vgGetPathCapabilities(path);
+ if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
+ return VGU_PATH_CAPABILITY_ERROR;
+ }
+ if (width <= 0 || height <= 0) {
+ return VGU_ILLEGAL_ARGUMENT_ERROR;
+ }
+ if (arcType != VGU_ARC_OPEN &&
+ arcType != VGU_ARC_CHORD &&
+ arcType != VGU_ARC_PIE) {
+ return VGU_ILLEGAL_ARGUMENT_ERROR;
+ }
+
+ cmds[c] = VG_MOVE_TO_ABS; ++c;
+ coords[0] = x+cos(DEGREES_TO_RADIANS(startAngle))*width/2;
+ coords[1] = y+sin(DEGREES_TO_RADIANS(startAngle))*height/2;
+#ifdef DEBUG_VGUARC
+ debug_printf("start [%f, %f]\n", coords[0], coords[1]);
+#endif
+ i = 2;
+ if (angleExtent > 0) {
+ VGfloat angle = startAngle + 180;
+ while (angle < last) {
+ cmds[c] = VG_SCCWARC_TO_ABS; ++c;
+ coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
+ coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle))*width/2;
+ coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle))*height/2;
+#ifdef DEBUG_VGUARC
+ debug_printf("1 [%f, %f]\n", coords[i+3],
+ coords[i+4]);
+#endif
+ i += 5;
+ angle += 180;
+ }
+ cmds[c] = VG_SCCWARC_TO_ABS; ++c;
+ coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
+ coords[i+3] = x+cos(DEGREES_TO_RADIANS(last))*width/2;
+ coords[i+4] = y+sin(DEGREES_TO_RADIANS(last))*height/2;
+#ifdef DEBUG_VGUARC
+ debug_printf("2 [%f, %f]\n", coords[i+3],
+ coords[i+4]);
+#endif
+ i += 5;
+ } else {
+ VGfloat angle = startAngle - 180;
+ while (angle > last) {
+ cmds[c] = VG_SCWARC_TO_ABS; ++c;
+ coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
+ coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle)) * width/2;
+ coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle)) * height/2;
+#ifdef DEBUG_VGUARC
+ debug_printf("3 [%f, %f]\n", coords[i+3],
+ coords[i+4]);
+#endif
+ angle -= 180;
+ i += 5;
+ }
+ cmds[c] = VG_SCWARC_TO_ABS; ++c;
+ coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
+ coords[i+3] = x + cos(DEGREES_TO_RADIANS(last)) * width/2;
+ coords[i+4] = y + sin(DEGREES_TO_RADIANS(last)) * height/2;
+#ifdef DEBUG_VGUARC
+ debug_printf("4 [%f, %f]\n", coords[i+3],
+ coords[i+4]);
+#endif
+ i += 5;
+ }
+
+ if (arcType == VGU_ARC_PIE) {
+ cmds[c] = VG_LINE_TO_ABS; ++c;
+ coords[i] = x; coords[i + 1] = y;
+ i += 2;
+ }
+ if (arcType == VGU_ARC_PIE || arcType == VGU_ARC_CHORD) {
+ cmds[c] = VG_CLOSE_PATH;
+ ++c;
+ }
+
+ assert(c < 11);
+
+ vgu_append_float_coords(path, cmds, c, coords, i);
+
+ return VGU_NO_ERROR;
+}
+
+VGUErrorCode vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0,
+ VGfloat sx1, VGfloat sy1,
+ VGfloat sx2, VGfloat sy2,
+ VGfloat sx3, VGfloat sy3,
+ VGfloat * matrix)
+{
+ struct matrix mat;
+
+ if (!matrix || !is_aligned(matrix))
+ return VGU_ILLEGAL_ARGUMENT_ERROR;
+
+ if (!matrix_quad_to_square(sx0, sy0,
+ sx1, sy1,
+ sx2, sy2,
+ sx3, sy3,
+ &mat))
+ return VGU_BAD_WARP_ERROR;
+
+ if (!matrix_is_invertible(&mat))
+ return VGU_BAD_WARP_ERROR;
+
+ memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
+
+ return VGU_NO_ERROR;
+}
+
+VGUErrorCode vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0,
+ VGfloat dx1, VGfloat dy1,
+ VGfloat dx2, VGfloat dy2,
+ VGfloat dx3, VGfloat dy3,
+ VGfloat * matrix)
+{
+ struct matrix mat;
+
+ if (!matrix || !is_aligned(matrix))
+ return VGU_ILLEGAL_ARGUMENT_ERROR;
+
+ if (!matrix_square_to_quad(dx0, dy0,
+ dx1, dy1,
+ dx2, dy2,
+ dx3, dy3,
+ &mat))
+ return VGU_BAD_WARP_ERROR;
+
+ if (!matrix_is_invertible(&mat))
+ return VGU_BAD_WARP_ERROR;
+
+ memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
+
+ return VGU_NO_ERROR;
+}
+
+VGUErrorCode vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0,
+ VGfloat dx1, VGfloat dy1,
+ VGfloat dx2, VGfloat dy2,
+ VGfloat dx3, VGfloat dy3,
+ VGfloat sx0, VGfloat sy0,
+ VGfloat sx1, VGfloat sy1,
+ VGfloat sx2, VGfloat sy2,
+ VGfloat sx3, VGfloat sy3,
+ VGfloat * matrix)
+{
+ struct matrix mat;
+
+ if (!matrix || !is_aligned(matrix))
+ return VGU_ILLEGAL_ARGUMENT_ERROR;
+
+ if (!matrix_quad_to_quad(dx0, dy0,
+ dx1, dy1,
+ dx2, dy2,
+ dx3, dy3,
+ sx0, sy0,
+ sx1, sy1,
+ sx2, sy2,
+ sx3, sy3,
+ &mat))
+ return VGU_BAD_WARP_ERROR;
+
+ memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
+
+ return VGU_NO_ERROR;
+}
diff --git a/src/gallium/state_trackers/wgl/SConscript b/src/gallium/state_trackers/wgl/SConscript
new file mode 100644
index 0000000000..69b88618ec
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/SConscript
@@ -0,0 +1,42 @@
+import os
+
+Import('*')
+
+if env['platform'] in ['windows']:
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#src/mesa',
+ '.',
+ ])
+
+ env.Append(CPPDEFINES = [
+ '_GDI32_', # prevent wgl* being declared __declspec(dllimport)
+ 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers
+ 'WIN32_THREADS', # use Win32 thread API
+ ])
+
+ sources = [
+ 'icd/stw_icd.c',
+
+ 'wgl/stw_wgl.c',
+
+ 'shared/stw_context.c',
+ 'shared/stw_device.c',
+ 'shared/stw_framebuffer.c',
+ 'shared/stw_pixelformat.c',
+ 'shared/stw_extensionsstring.c',
+ 'shared/stw_extswapinterval.c',
+ 'shared/stw_getprocaddress.c',
+ 'shared/stw_extgallium.c',
+ 'shared/stw_arbpixelformat.c',
+ 'shared/stw_tls.c',
+ ]
+
+ wgl = env.ConvenienceLibrary(
+ target ='wgl',
+ source = sources,
+ )
+
+ Export('wgl')
diff --git a/src/gallium/state_trackers/wgl/icd/stw_icd.c b/src/gallium/state_trackers/wgl/icd/stw_icd.c
new file mode 100644
index 0000000000..347f40aa06
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/icd/stw_icd.c
@@ -0,0 +1,617 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+#include <stdio.h>
+
+#include "GL/gl.h"
+
+#include "util/u_debug.h"
+#include "pipe/p_thread.h"
+
+#include "shared/stw_public.h"
+#include "icd/stw_icd.h"
+
+#define DBG 0
+
+
+BOOL APIENTRY
+DrvCopyContext(
+ DHGLRC dhrcSource,
+ DHGLRC dhrcDest,
+ UINT fuMask )
+{
+ return stw_copy_context(dhrcSource, dhrcDest, fuMask);
+}
+
+
+DHGLRC APIENTRY
+DrvCreateLayerContext(
+ HDC hdc,
+ INT iLayerPlane )
+{
+ DHGLRC r;
+
+ r = stw_create_layer_context( hdc, iLayerPlane );
+
+ if (DBG)
+ debug_printf( "%s( %p, %i ) = %u\n",
+ __FUNCTION__, hdc, iLayerPlane, r );
+
+ return r;
+}
+
+DHGLRC APIENTRY
+DrvCreateContext(
+ HDC hdc )
+{
+ return DrvCreateLayerContext( hdc, 0 );
+}
+
+BOOL APIENTRY
+DrvDeleteContext(
+ DHGLRC dhglrc )
+{
+ BOOL r;
+
+ r = stw_delete_context( dhglrc );
+
+ if (DBG)
+ debug_printf( "%s( %u ) = %u\n",
+ __FUNCTION__, dhglrc, r );
+
+ return r;
+}
+
+BOOL APIENTRY
+DrvDescribeLayerPlane(
+ HDC hdc,
+ INT iPixelFormat,
+ INT iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd )
+{
+ if (DBG)
+ debug_printf( "%s\n", __FUNCTION__ );
+
+ return FALSE;
+}
+
+LONG APIENTRY
+DrvDescribePixelFormat(
+ HDC hdc,
+ INT iPixelFormat,
+ ULONG cjpfd,
+ PIXELFORMATDESCRIPTOR *ppfd )
+{
+ LONG r;
+
+ r = stw_pixelformat_describe( hdc, iPixelFormat, cjpfd, ppfd );
+
+ if (DBG)
+ debug_printf( "%s( %p, %d, %u, %p ) = %d\n",
+ __FUNCTION__, hdc, iPixelFormat, cjpfd, ppfd, r );
+
+ return r;
+}
+
+int APIENTRY
+DrvGetLayerPaletteEntries(
+ HDC hdc,
+ INT iLayerPlane,
+ INT iStart,
+ INT cEntries,
+ COLORREF *pcr )
+{
+ if (DBG)
+ debug_printf( "%s\n", __FUNCTION__ );
+
+ return 0;
+}
+
+PROC APIENTRY
+DrvGetProcAddress(
+ LPCSTR lpszProc )
+{
+ PROC r;
+
+ r = stw_get_proc_address( lpszProc );
+
+ if (DBG)
+ debug_printf( "%s( \"%s\" ) = %p\n", __FUNCTION__, lpszProc, r );
+
+ return r;
+}
+
+BOOL APIENTRY
+DrvRealizeLayerPalette(
+ HDC hdc,
+ INT iLayerPlane,
+ BOOL bRealize )
+{
+ if (DBG)
+ debug_printf( "%s\n", __FUNCTION__ );
+
+ return FALSE;
+}
+
+BOOL APIENTRY
+DrvReleaseContext(
+ DHGLRC dhglrc )
+{
+ return stw_release_context(dhglrc);
+}
+
+void APIENTRY
+DrvSetCallbackProcs(
+ INT nProcs,
+ PROC *pProcs )
+{
+ if (DBG)
+ debug_printf( "%s( %d, %p )\n", __FUNCTION__, nProcs, pProcs );
+
+ return;
+}
+
+
+/**
+ * Although WGL allows different dispatch entrypoints per context
+ */
+static const GLCLTPROCTABLE cpt =
+{
+ OPENGL_VERSION_110_ENTRIES,
+ {
+ &glNewList,
+ &glEndList,
+ &glCallList,
+ &glCallLists,
+ &glDeleteLists,
+ &glGenLists,
+ &glListBase,
+ &glBegin,
+ &glBitmap,
+ &glColor3b,
+ &glColor3bv,
+ &glColor3d,
+ &glColor3dv,
+ &glColor3f,
+ &glColor3fv,
+ &glColor3i,
+ &glColor3iv,
+ &glColor3s,
+ &glColor3sv,
+ &glColor3ub,
+ &glColor3ubv,
+ &glColor3ui,
+ &glColor3uiv,
+ &glColor3us,
+ &glColor3usv,
+ &glColor4b,
+ &glColor4bv,
+ &glColor4d,
+ &glColor4dv,
+ &glColor4f,
+ &glColor4fv,
+ &glColor4i,
+ &glColor4iv,
+ &glColor4s,
+ &glColor4sv,
+ &glColor4ub,
+ &glColor4ubv,
+ &glColor4ui,
+ &glColor4uiv,
+ &glColor4us,
+ &glColor4usv,
+ &glEdgeFlag,
+ &glEdgeFlagv,
+ &glEnd,
+ &glIndexd,
+ &glIndexdv,
+ &glIndexf,
+ &glIndexfv,
+ &glIndexi,
+ &glIndexiv,
+ &glIndexs,
+ &glIndexsv,
+ &glNormal3b,
+ &glNormal3bv,
+ &glNormal3d,
+ &glNormal3dv,
+ &glNormal3f,
+ &glNormal3fv,
+ &glNormal3i,
+ &glNormal3iv,
+ &glNormal3s,
+ &glNormal3sv,
+ &glRasterPos2d,
+ &glRasterPos2dv,
+ &glRasterPos2f,
+ &glRasterPos2fv,
+ &glRasterPos2i,
+ &glRasterPos2iv,
+ &glRasterPos2s,
+ &glRasterPos2sv,
+ &glRasterPos3d,
+ &glRasterPos3dv,
+ &glRasterPos3f,
+ &glRasterPos3fv,
+ &glRasterPos3i,
+ &glRasterPos3iv,
+ &glRasterPos3s,
+ &glRasterPos3sv,
+ &glRasterPos4d,
+ &glRasterPos4dv,
+ &glRasterPos4f,
+ &glRasterPos4fv,
+ &glRasterPos4i,
+ &glRasterPos4iv,
+ &glRasterPos4s,
+ &glRasterPos4sv,
+ &glRectd,
+ &glRectdv,
+ &glRectf,
+ &glRectfv,
+ &glRecti,
+ &glRectiv,
+ &glRects,
+ &glRectsv,
+ &glTexCoord1d,
+ &glTexCoord1dv,
+ &glTexCoord1f,
+ &glTexCoord1fv,
+ &glTexCoord1i,
+ &glTexCoord1iv,
+ &glTexCoord1s,
+ &glTexCoord1sv,
+ &glTexCoord2d,
+ &glTexCoord2dv,
+ &glTexCoord2f,
+ &glTexCoord2fv,
+ &glTexCoord2i,
+ &glTexCoord2iv,
+ &glTexCoord2s,
+ &glTexCoord2sv,
+ &glTexCoord3d,
+ &glTexCoord3dv,
+ &glTexCoord3f,
+ &glTexCoord3fv,
+ &glTexCoord3i,
+ &glTexCoord3iv,
+ &glTexCoord3s,
+ &glTexCoord3sv,
+ &glTexCoord4d,
+ &glTexCoord4dv,
+ &glTexCoord4f,
+ &glTexCoord4fv,
+ &glTexCoord4i,
+ &glTexCoord4iv,
+ &glTexCoord4s,
+ &glTexCoord4sv,
+ &glVertex2d,
+ &glVertex2dv,
+ &glVertex2f,
+ &glVertex2fv,
+ &glVertex2i,
+ &glVertex2iv,
+ &glVertex2s,
+ &glVertex2sv,
+ &glVertex3d,
+ &glVertex3dv,
+ &glVertex3f,
+ &glVertex3fv,
+ &glVertex3i,
+ &glVertex3iv,
+ &glVertex3s,
+ &glVertex3sv,
+ &glVertex4d,
+ &glVertex4dv,
+ &glVertex4f,
+ &glVertex4fv,
+ &glVertex4i,
+ &glVertex4iv,
+ &glVertex4s,
+ &glVertex4sv,
+ &glClipPlane,
+ &glColorMaterial,
+ &glCullFace,
+ &glFogf,
+ &glFogfv,
+ &glFogi,
+ &glFogiv,
+ &glFrontFace,
+ &glHint,
+ &glLightf,
+ &glLightfv,
+ &glLighti,
+ &glLightiv,
+ &glLightModelf,
+ &glLightModelfv,
+ &glLightModeli,
+ &glLightModeliv,
+ &glLineStipple,
+ &glLineWidth,
+ &glMaterialf,
+ &glMaterialfv,
+ &glMateriali,
+ &glMaterialiv,
+ &glPointSize,
+ &glPolygonMode,
+ &glPolygonStipple,
+ &glScissor,
+ &glShadeModel,
+ &glTexParameterf,
+ &glTexParameterfv,
+ &glTexParameteri,
+ &glTexParameteriv,
+ &glTexImage1D,
+ &glTexImage2D,
+ &glTexEnvf,
+ &glTexEnvfv,
+ &glTexEnvi,
+ &glTexEnviv,
+ &glTexGend,
+ &glTexGendv,
+ &glTexGenf,
+ &glTexGenfv,
+ &glTexGeni,
+ &glTexGeniv,
+ &glFeedbackBuffer,
+ &glSelectBuffer,
+ &glRenderMode,
+ &glInitNames,
+ &glLoadName,
+ &glPassThrough,
+ &glPopName,
+ &glPushName,
+ &glDrawBuffer,
+ &glClear,
+ &glClearAccum,
+ &glClearIndex,
+ &glClearColor,
+ &glClearStencil,
+ &glClearDepth,
+ &glStencilMask,
+ &glColorMask,
+ &glDepthMask,
+ &glIndexMask,
+ &glAccum,
+ &glDisable,
+ &glEnable,
+ &glFinish,
+ &glFlush,
+ &glPopAttrib,
+ &glPushAttrib,
+ &glMap1d,
+ &glMap1f,
+ &glMap2d,
+ &glMap2f,
+ &glMapGrid1d,
+ &glMapGrid1f,
+ &glMapGrid2d,
+ &glMapGrid2f,
+ &glEvalCoord1d,
+ &glEvalCoord1dv,
+ &glEvalCoord1f,
+ &glEvalCoord1fv,
+ &glEvalCoord2d,
+ &glEvalCoord2dv,
+ &glEvalCoord2f,
+ &glEvalCoord2fv,
+ &glEvalMesh1,
+ &glEvalPoint1,
+ &glEvalMesh2,
+ &glEvalPoint2,
+ &glAlphaFunc,
+ &glBlendFunc,
+ &glLogicOp,
+ &glStencilFunc,
+ &glStencilOp,
+ &glDepthFunc,
+ &glPixelZoom,
+ &glPixelTransferf,
+ &glPixelTransferi,
+ &glPixelStoref,
+ &glPixelStorei,
+ &glPixelMapfv,
+ &glPixelMapuiv,
+ &glPixelMapusv,
+ &glReadBuffer,
+ &glCopyPixels,
+ &glReadPixels,
+ &glDrawPixels,
+ &glGetBooleanv,
+ &glGetClipPlane,
+ &glGetDoublev,
+ &glGetError,
+ &glGetFloatv,
+ &glGetIntegerv,
+ &glGetLightfv,
+ &glGetLightiv,
+ &glGetMapdv,
+ &glGetMapfv,
+ &glGetMapiv,
+ &glGetMaterialfv,
+ &glGetMaterialiv,
+ &glGetPixelMapfv,
+ &glGetPixelMapuiv,
+ &glGetPixelMapusv,
+ &glGetPolygonStipple,
+ &glGetString,
+ &glGetTexEnvfv,
+ &glGetTexEnviv,
+ &glGetTexGendv,
+ &glGetTexGenfv,
+ &glGetTexGeniv,
+ &glGetTexImage,
+ &glGetTexParameterfv,
+ &glGetTexParameteriv,
+ &glGetTexLevelParameterfv,
+ &glGetTexLevelParameteriv,
+ &glIsEnabled,
+ &glIsList,
+ &glDepthRange,
+ &glFrustum,
+ &glLoadIdentity,
+ &glLoadMatrixf,
+ &glLoadMatrixd,
+ &glMatrixMode,
+ &glMultMatrixf,
+ &glMultMatrixd,
+ &glOrtho,
+ &glPopMatrix,
+ &glPushMatrix,
+ &glRotated,
+ &glRotatef,
+ &glScaled,
+ &glScalef,
+ &glTranslated,
+ &glTranslatef,
+ &glViewport,
+ &glArrayElement,
+ &glBindTexture,
+ &glColorPointer,
+ &glDisableClientState,
+ &glDrawArrays,
+ &glDrawElements,
+ &glEdgeFlagPointer,
+ &glEnableClientState,
+ &glIndexPointer,
+ &glIndexub,
+ &glIndexubv,
+ &glInterleavedArrays,
+ &glNormalPointer,
+ &glPolygonOffset,
+ &glTexCoordPointer,
+ &glVertexPointer,
+ &glAreTexturesResident,
+ &glCopyTexImage1D,
+ &glCopyTexImage2D,
+ &glCopyTexSubImage1D,
+ &glCopyTexSubImage2D,
+ &glDeleteTextures,
+ &glGenTextures,
+ &glGetPointerv,
+ &glIsTexture,
+ &glPrioritizeTextures,
+ &glTexSubImage1D,
+ &glTexSubImage2D,
+ &glPopClientAttrib,
+ &glPushClientAttrib
+ }
+};
+
+
+PGLCLTPROCTABLE APIENTRY
+DrvSetContext(
+ HDC hdc,
+ DHGLRC dhglrc,
+ PFN_SETPROCTABLE pfnSetProcTable )
+{
+ PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt;
+
+ if (!stw_make_current( hdc, dhglrc ))
+ r = NULL;
+
+ if (DBG)
+ debug_printf( "%s( 0x%p, %u, 0x%p ) = %p\n",
+ __FUNCTION__, hdc, dhglrc, pfnSetProcTable, r );
+
+ return r;
+}
+
+int APIENTRY
+DrvSetLayerPaletteEntries(
+ HDC hdc,
+ INT iLayerPlane,
+ INT iStart,
+ INT cEntries,
+ CONST COLORREF *pcr )
+{
+ if (DBG)
+ debug_printf( "%s\n", __FUNCTION__ );
+
+ return 0;
+}
+
+BOOL APIENTRY
+DrvSetPixelFormat(
+ HDC hdc,
+ LONG iPixelFormat )
+{
+ BOOL r;
+
+ r = stw_pixelformat_set( hdc, iPixelFormat );
+
+ if (DBG)
+ debug_printf( "%s( %p, %d ) = %s\n", __FUNCTION__, hdc, iPixelFormat, r ? "TRUE" : "FALSE" );
+
+ return r;
+}
+
+BOOL APIENTRY
+DrvShareLists(
+ DHGLRC dhglrc1,
+ DHGLRC dhglrc2 )
+{
+ if (DBG)
+ debug_printf( "%s\n", __FUNCTION__ );
+
+ return stw_share_lists(dhglrc1, dhglrc2);
+}
+
+BOOL APIENTRY
+DrvSwapBuffers(
+ HDC hdc )
+{
+ if (DBG)
+ debug_printf( "%s( %p )\n", __FUNCTION__, hdc );
+
+ return stw_swap_buffers( hdc );
+}
+
+BOOL APIENTRY
+DrvSwapLayerBuffers(
+ HDC hdc,
+ UINT fuPlanes )
+{
+ if (DBG)
+ debug_printf( "%s\n", __FUNCTION__ );
+
+ return stw_swap_layer_buffers( hdc, fuPlanes );
+}
+
+BOOL APIENTRY
+DrvValidateVersion(
+ ULONG ulVersion )
+{
+ if (DBG)
+ debug_printf( "%s( %u )\n", __FUNCTION__, ulVersion );
+
+ /* TODO: get the expected version from the winsys */
+
+ return ulVersion == 1;
+}
diff --git a/src/gallium/state_trackers/wgl/icd/stw_icd.h b/src/gallium/state_trackers/wgl/icd/stw_icd.h
new file mode 100644
index 0000000000..cbc1a66548
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/icd/stw_icd.h
@@ -0,0 +1,489 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_ICD_H
+#define STW_ICD_H
+
+
+#include <windows.h>
+
+#include "GL/gl.h"
+
+
+typedef ULONG DHGLRC;
+
+#define OPENGL_VERSION_110_ENTRIES 336
+
+struct __GLdispatchTableRec
+{
+ void (GLAPIENTRY * NewList)(GLuint, GLenum);
+ void (GLAPIENTRY * EndList)(void);
+ void (GLAPIENTRY * CallList)(GLuint);
+ void (GLAPIENTRY * CallLists)(GLsizei, GLenum, const GLvoid *);
+ void (GLAPIENTRY * DeleteLists)(GLuint, GLsizei);
+ GLuint (GLAPIENTRY * GenLists)(GLsizei);
+ void (GLAPIENTRY * ListBase)(GLuint);
+ void (GLAPIENTRY * Begin)(GLenum);
+ void (GLAPIENTRY * Bitmap)(GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, const GLubyte *);
+ void (GLAPIENTRY * Color3b)(GLbyte, GLbyte, GLbyte);
+ void (GLAPIENTRY * Color3bv)(const GLbyte *);
+ void (GLAPIENTRY * Color3d)(GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * Color3dv)(const GLdouble *);
+ void (GLAPIENTRY * Color3f)(GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * Color3fv)(const GLfloat *);
+ void (GLAPIENTRY * Color3i)(GLint, GLint, GLint);
+ void (GLAPIENTRY * Color3iv)(const GLint *);
+ void (GLAPIENTRY * Color3s)(GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * Color3sv)(const GLshort *);
+ void (GLAPIENTRY * Color3ub)(GLubyte, GLubyte, GLubyte);
+ void (GLAPIENTRY * Color3ubv)(const GLubyte *);
+ void (GLAPIENTRY * Color3ui)(GLuint, GLuint, GLuint);
+ void (GLAPIENTRY * Color3uiv)(const GLuint *);
+ void (GLAPIENTRY * Color3us)(GLushort, GLushort, GLushort);
+ void (GLAPIENTRY * Color3usv)(const GLushort *);
+ void (GLAPIENTRY * Color4b)(GLbyte, GLbyte, GLbyte, GLbyte);
+ void (GLAPIENTRY * Color4bv)(const GLbyte *);
+ void (GLAPIENTRY * Color4d)(GLdouble, GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * Color4dv)(const GLdouble *);
+ void (GLAPIENTRY * Color4f)(GLfloat, GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * Color4fv)(const GLfloat *);
+ void (GLAPIENTRY * Color4i)(GLint, GLint, GLint, GLint);
+ void (GLAPIENTRY * Color4iv)(const GLint *);
+ void (GLAPIENTRY * Color4s)(GLshort, GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * Color4sv)(const GLshort *);
+ void (GLAPIENTRY * Color4ub)(GLubyte, GLubyte, GLubyte, GLubyte);
+ void (GLAPIENTRY * Color4ubv)(const GLubyte *);
+ void (GLAPIENTRY * Color4ui)(GLuint, GLuint, GLuint, GLuint);
+ void (GLAPIENTRY * Color4uiv)(const GLuint *);
+ void (GLAPIENTRY * Color4us)(GLushort, GLushort, GLushort, GLushort);
+ void (GLAPIENTRY * Color4usv)(const GLushort *);
+ void (GLAPIENTRY * EdgeFlag)(GLboolean);
+ void (GLAPIENTRY * EdgeFlagv)(const GLboolean *);
+ void (GLAPIENTRY * End)(void);
+ void (GLAPIENTRY * Indexd)(GLdouble);
+ void (GLAPIENTRY * Indexdv)(const GLdouble *);
+ void (GLAPIENTRY * Indexf)(GLfloat);
+ void (GLAPIENTRY * Indexfv)(const GLfloat *);
+ void (GLAPIENTRY * Indexi)(GLint);
+ void (GLAPIENTRY * Indexiv)(const GLint *);
+ void (GLAPIENTRY * Indexs)(GLshort);
+ void (GLAPIENTRY * Indexsv)(const GLshort *);
+ void (GLAPIENTRY * Normal3b)(GLbyte, GLbyte, GLbyte);
+ void (GLAPIENTRY * Normal3bv)(const GLbyte *);
+ void (GLAPIENTRY * Normal3d)(GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * Normal3dv)(const GLdouble *);
+ void (GLAPIENTRY * Normal3f)(GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * Normal3fv)(const GLfloat *);
+ void (GLAPIENTRY * Normal3i)(GLint, GLint, GLint);
+ void (GLAPIENTRY * Normal3iv)(const GLint *);
+ void (GLAPIENTRY * Normal3s)(GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * Normal3sv)(const GLshort *);
+ void (GLAPIENTRY * RasterPos2d)(GLdouble, GLdouble);
+ void (GLAPIENTRY * RasterPos2dv)(const GLdouble *);
+ void (GLAPIENTRY * RasterPos2f)(GLfloat, GLfloat);
+ void (GLAPIENTRY * RasterPos2fv)(const GLfloat *);
+ void (GLAPIENTRY * RasterPos2i)(GLint, GLint);
+ void (GLAPIENTRY * RasterPos2iv)(const GLint *);
+ void (GLAPIENTRY * RasterPos2s)(GLshort, GLshort);
+ void (GLAPIENTRY * RasterPos2sv)(const GLshort *);
+ void (GLAPIENTRY * RasterPos3d)(GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * RasterPos3dv)(const GLdouble *);
+ void (GLAPIENTRY * RasterPos3f)(GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * RasterPos3fv)(const GLfloat *);
+ void (GLAPIENTRY * RasterPos3i)(GLint, GLint, GLint);
+ void (GLAPIENTRY * RasterPos3iv)(const GLint *);
+ void (GLAPIENTRY * RasterPos3s)(GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * RasterPos3sv)(const GLshort *);
+ void (GLAPIENTRY * RasterPos4d)(GLdouble, GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * RasterPos4dv)(const GLdouble *);
+ void (GLAPIENTRY * RasterPos4f)(GLfloat, GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * RasterPos4fv)(const GLfloat *);
+ void (GLAPIENTRY * RasterPos4i)(GLint, GLint, GLint, GLint);
+ void (GLAPIENTRY * RasterPos4iv)(const GLint *);
+ void (GLAPIENTRY * RasterPos4s)(GLshort, GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * RasterPos4sv)(const GLshort *);
+ void (GLAPIENTRY * Rectd)(GLdouble, GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * Rectdv)(const GLdouble *, const GLdouble *);
+ void (GLAPIENTRY * Rectf)(GLfloat, GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * Rectfv)(const GLfloat *, const GLfloat *);
+ void (GLAPIENTRY * Recti)(GLint, GLint, GLint, GLint);
+ void (GLAPIENTRY * Rectiv)(const GLint *, const GLint *);
+ void (GLAPIENTRY * Rects)(GLshort, GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * Rectsv)(const GLshort *, const GLshort *);
+ void (GLAPIENTRY * TexCoord1d)(GLdouble);
+ void (GLAPIENTRY * TexCoord1dv)(const GLdouble *);
+ void (GLAPIENTRY * TexCoord1f)(GLfloat);
+ void (GLAPIENTRY * TexCoord1fv)(const GLfloat *);
+ void (GLAPIENTRY * TexCoord1i)(GLint);
+ void (GLAPIENTRY * TexCoord1iv)(const GLint *);
+ void (GLAPIENTRY * TexCoord1s)(GLshort);
+ void (GLAPIENTRY * TexCoord1sv)(const GLshort *);
+ void (GLAPIENTRY * TexCoord2d)(GLdouble, GLdouble);
+ void (GLAPIENTRY * TexCoord2dv)(const GLdouble *);
+ void (GLAPIENTRY * TexCoord2f)(GLfloat, GLfloat);
+ void (GLAPIENTRY * TexCoord2fv)(const GLfloat *);
+ void (GLAPIENTRY * TexCoord2i)(GLint, GLint);
+ void (GLAPIENTRY * TexCoord2iv)(const GLint *);
+ void (GLAPIENTRY * TexCoord2s)(GLshort, GLshort);
+ void (GLAPIENTRY * TexCoord2sv)(const GLshort *);
+ void (GLAPIENTRY * TexCoord3d)(GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * TexCoord3dv)(const GLdouble *);
+ void (GLAPIENTRY * TexCoord3f)(GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * TexCoord3fv)(const GLfloat *);
+ void (GLAPIENTRY * TexCoord3i)(GLint, GLint, GLint);
+ void (GLAPIENTRY * TexCoord3iv)(const GLint *);
+ void (GLAPIENTRY * TexCoord3s)(GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * TexCoord3sv)(const GLshort *);
+ void (GLAPIENTRY * TexCoord4d)(GLdouble, GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * TexCoord4dv)(const GLdouble *);
+ void (GLAPIENTRY * TexCoord4f)(GLfloat, GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * TexCoord4fv)(const GLfloat *);
+ void (GLAPIENTRY * TexCoord4i)(GLint, GLint, GLint, GLint);
+ void (GLAPIENTRY * TexCoord4iv)(const GLint *);
+ void (GLAPIENTRY * TexCoord4s)(GLshort, GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * TexCoord4sv)(const GLshort *);
+ void (GLAPIENTRY * Vertex2d)(GLdouble, GLdouble);
+ void (GLAPIENTRY * Vertex2dv)(const GLdouble *);
+ void (GLAPIENTRY * Vertex2f)(GLfloat, GLfloat);
+ void (GLAPIENTRY * Vertex2fv)(const GLfloat *);
+ void (GLAPIENTRY * Vertex2i)(GLint, GLint);
+ void (GLAPIENTRY * Vertex2iv)(const GLint *);
+ void (GLAPIENTRY * Vertex2s)(GLshort, GLshort);
+ void (GLAPIENTRY * Vertex2sv)(const GLshort *);
+ void (GLAPIENTRY * Vertex3d)(GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * Vertex3dv)(const GLdouble *);
+ void (GLAPIENTRY * Vertex3f)(GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * Vertex3fv)(const GLfloat *);
+ void (GLAPIENTRY * Vertex3i)(GLint, GLint, GLint);
+ void (GLAPIENTRY * Vertex3iv)(const GLint *);
+ void (GLAPIENTRY * Vertex3s)(GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * Vertex3sv)(const GLshort *);
+ void (GLAPIENTRY * Vertex4d)(GLdouble, GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * Vertex4dv)(const GLdouble *);
+ void (GLAPIENTRY * Vertex4f)(GLfloat, GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * Vertex4fv)(const GLfloat *);
+ void (GLAPIENTRY * Vertex4i)(GLint, GLint, GLint, GLint);
+ void (GLAPIENTRY * Vertex4iv)(const GLint *);
+ void (GLAPIENTRY * Vertex4s)(GLshort, GLshort, GLshort, GLshort);
+ void (GLAPIENTRY * Vertex4sv)(const GLshort *);
+ void (GLAPIENTRY * ClipPlane)(GLenum, const GLdouble *);
+ void (GLAPIENTRY * ColorMaterial)(GLenum, GLenum);
+ void (GLAPIENTRY * CullFace)(GLenum);
+ void (GLAPIENTRY * Fogf)(GLenum, GLfloat);
+ void (GLAPIENTRY * Fogfv)(GLenum, const GLfloat *);
+ void (GLAPIENTRY * Fogi)(GLenum, GLint);
+ void (GLAPIENTRY * Fogiv)(GLenum, const GLint *);
+ void (GLAPIENTRY * FrontFace)(GLenum);
+ void (GLAPIENTRY * Hint)(GLenum, GLenum);
+ void (GLAPIENTRY * Lightf)(GLenum, GLenum, GLfloat);
+ void (GLAPIENTRY * Lightfv)(GLenum, GLenum, const GLfloat *);
+ void (GLAPIENTRY * Lighti)(GLenum, GLenum, GLint);
+ void (GLAPIENTRY * Lightiv)(GLenum, GLenum, const GLint *);
+ void (GLAPIENTRY * LightModelf)(GLenum, GLfloat);
+ void (GLAPIENTRY * LightModelfv)(GLenum, const GLfloat *);
+ void (GLAPIENTRY * LightModeli)(GLenum, GLint);
+ void (GLAPIENTRY * LightModeliv)(GLenum, const GLint *);
+ void (GLAPIENTRY * LineStipple)(GLint, GLushort);
+ void (GLAPIENTRY * LineWidth)(GLfloat);
+ void (GLAPIENTRY * Materialf)(GLenum, GLenum, GLfloat);
+ void (GLAPIENTRY * Materialfv)(GLenum, GLenum, const GLfloat *);
+ void (GLAPIENTRY * Materiali)(GLenum, GLenum, GLint);
+ void (GLAPIENTRY * Materialiv)(GLenum, GLenum, const GLint *);
+ void (GLAPIENTRY * PointSize)(GLfloat);
+ void (GLAPIENTRY * PolygonMode)(GLenum, GLenum);
+ void (GLAPIENTRY * PolygonStipple)(const GLubyte *);
+ void (GLAPIENTRY * Scissor)(GLint, GLint, GLsizei, GLsizei);
+ void (GLAPIENTRY * ShadeModel)(GLenum);
+ void (GLAPIENTRY * TexParameterf)(GLenum, GLenum, GLfloat);
+ void (GLAPIENTRY * TexParameterfv)(GLenum, GLenum, const GLfloat *);
+ void (GLAPIENTRY * TexParameteri)(GLenum, GLenum, GLint);
+ void (GLAPIENTRY * TexParameteriv)(GLenum, GLenum, const GLint *);
+ void (GLAPIENTRY * TexImage1D)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+ void (GLAPIENTRY * TexImage2D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+ void (GLAPIENTRY * TexEnvf)(GLenum, GLenum, GLfloat);
+ void (GLAPIENTRY * TexEnvfv)(GLenum, GLenum, const GLfloat *);
+ void (GLAPIENTRY * TexEnvi)(GLenum, GLenum, GLint);
+ void (GLAPIENTRY * TexEnviv)(GLenum, GLenum, const GLint *);
+ void (GLAPIENTRY * TexGend)(GLenum, GLenum, GLdouble);
+ void (GLAPIENTRY * TexGendv)(GLenum, GLenum, const GLdouble *);
+ void (GLAPIENTRY * TexGenf)(GLenum, GLenum, GLfloat);
+ void (GLAPIENTRY * TexGenfv)(GLenum, GLenum, const GLfloat *);
+ void (GLAPIENTRY * TexGeni)(GLenum, GLenum, GLint);
+ void (GLAPIENTRY * TexGeniv)(GLenum, GLenum, const GLint *);
+ void (GLAPIENTRY * FeedbackBuffer)(GLsizei, GLenum, GLfloat *);
+ void (GLAPIENTRY * SelectBuffer)(GLsizei, GLuint *);
+ GLint (GLAPIENTRY * RenderMode)(GLenum);
+ void (GLAPIENTRY * InitNames)(void);
+ void (GLAPIENTRY * LoadName)(GLuint);
+ void (GLAPIENTRY * PassThrough)(GLfloat);
+ void (GLAPIENTRY * PopName)(void);
+ void (GLAPIENTRY * PushName)(GLuint);
+ void (GLAPIENTRY * DrawBuffer)(GLenum);
+ void (GLAPIENTRY * Clear)(GLbitfield);
+ void (GLAPIENTRY * ClearAccum)(GLfloat, GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * ClearIndex)(GLfloat);
+ void (GLAPIENTRY * ClearColor)(GLclampf, GLclampf, GLclampf, GLclampf);
+ void (GLAPIENTRY * ClearStencil)(GLint);
+ void (GLAPIENTRY * ClearDepth)(GLclampd);
+ void (GLAPIENTRY * StencilMask)(GLuint);
+ void (GLAPIENTRY * ColorMask)(GLboolean, GLboolean, GLboolean, GLboolean);
+ void (GLAPIENTRY * DepthMask)(GLboolean);
+ void (GLAPIENTRY * IndexMask)(GLuint);
+ void (GLAPIENTRY * Accum)(GLenum, GLfloat);
+ void (GLAPIENTRY * Disable)(GLenum);
+ void (GLAPIENTRY * Enable)(GLenum);
+ void (GLAPIENTRY * Finish)(void);
+ void (GLAPIENTRY * Flush)(void);
+ void (GLAPIENTRY * PopAttrib)(void);
+ void (GLAPIENTRY * PushAttrib)(GLbitfield);
+ void (GLAPIENTRY * Map1d)(GLenum, GLdouble, GLdouble, GLint, GLint, const GLdouble *);
+ void (GLAPIENTRY * Map1f)(GLenum, GLfloat, GLfloat, GLint, GLint, const GLfloat *);
+ void (GLAPIENTRY * Map2d)(GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *);
+ void (GLAPIENTRY * Map2f)(GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *);
+ void (GLAPIENTRY * MapGrid1d)(GLint, GLdouble, GLdouble);
+ void (GLAPIENTRY * MapGrid1f)(GLint, GLfloat, GLfloat);
+ void (GLAPIENTRY * MapGrid2d)(GLint, GLdouble, GLdouble, GLint, GLdouble, GLdouble);
+ void (GLAPIENTRY * MapGrid2f)(GLint, GLfloat, GLfloat, GLint, GLfloat, GLfloat);
+ void (GLAPIENTRY * EvalCoord1d)(GLdouble);
+ void (GLAPIENTRY * EvalCoord1dv)(const GLdouble *);
+ void (GLAPIENTRY * EvalCoord1f)(GLfloat);
+ void (GLAPIENTRY * EvalCoord1fv)(const GLfloat *);
+ void (GLAPIENTRY * EvalCoord2d)(GLdouble, GLdouble);
+ void (GLAPIENTRY * EvalCoord2dv)(const GLdouble *);
+ void (GLAPIENTRY * EvalCoord2f)(GLfloat, GLfloat);
+ void (GLAPIENTRY * EvalCoord2fv)(const GLfloat *);
+ void (GLAPIENTRY * EvalMesh1)(GLenum, GLint, GLint);
+ void (GLAPIENTRY * EvalPoint1)(GLint);
+ void (GLAPIENTRY * EvalMesh2)(GLenum, GLint, GLint, GLint, GLint);
+ void (GLAPIENTRY * EvalPoint2)(GLint, GLint);
+ void (GLAPIENTRY * AlphaFunc)(GLenum, GLclampf);
+ void (GLAPIENTRY * BlendFunc)(GLenum, GLenum);
+ void (GLAPIENTRY * LogicOp)(GLenum);
+ void (GLAPIENTRY * StencilFunc)(GLenum, GLint, GLuint);
+ void (GLAPIENTRY * StencilOp)(GLenum, GLenum, GLenum);
+ void (GLAPIENTRY * DepthFunc)(GLenum);
+ void (GLAPIENTRY * PixelZoom)(GLfloat, GLfloat);
+ void (GLAPIENTRY * PixelTransferf)(GLenum, GLfloat);
+ void (GLAPIENTRY * PixelTransferi)(GLenum, GLint);
+ void (GLAPIENTRY * PixelStoref)(GLenum, GLfloat);
+ void (GLAPIENTRY * PixelStorei)(GLenum, GLint);
+ void (GLAPIENTRY * PixelMapfv)(GLenum, GLint, const GLfloat *);
+ void (GLAPIENTRY * PixelMapuiv)(GLenum, GLint, const GLuint *);
+ void (GLAPIENTRY * PixelMapusv)(GLenum, GLint, const GLushort *);
+ void (GLAPIENTRY * ReadBuffer)(GLenum);
+ void (GLAPIENTRY * CopyPixels)(GLint, GLint, GLsizei, GLsizei, GLenum);
+ void (GLAPIENTRY * ReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *);
+ void (GLAPIENTRY * DrawPixels)(GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+ void (GLAPIENTRY * GetBooleanv)(GLenum, GLboolean *);
+ void (GLAPIENTRY * GetClipPlane)(GLenum, GLdouble *);
+ void (GLAPIENTRY * GetDoublev)(GLenum, GLdouble *);
+ GLenum (GLAPIENTRY * GetError)(void);
+ void (GLAPIENTRY * GetFloatv)(GLenum, GLfloat *);
+ void (GLAPIENTRY * GetIntegerv)(GLenum, GLint *);
+ void (GLAPIENTRY * GetLightfv)(GLenum, GLenum, GLfloat *);
+ void (GLAPIENTRY * GetLightiv)(GLenum, GLenum, GLint *);
+ void (GLAPIENTRY * GetMapdv)(GLenum, GLenum, GLdouble *);
+ void (GLAPIENTRY * GetMapfv)(GLenum, GLenum, GLfloat *);
+ void (GLAPIENTRY * GetMapiv)(GLenum, GLenum, GLint *);
+ void (GLAPIENTRY * GetMaterialfv)(GLenum, GLenum, GLfloat *);
+ void (GLAPIENTRY * GetMaterialiv)(GLenum, GLenum, GLint *);
+ void (GLAPIENTRY * GetPixelMapfv)(GLenum, GLfloat *);
+ void (GLAPIENTRY * GetPixelMapuiv)(GLenum, GLuint *);
+ void (GLAPIENTRY * GetPixelMapusv)(GLenum, GLushort *);
+ void (GLAPIENTRY * GetPolygonStipple)(GLubyte *);
+ const GLubyte * (GLAPIENTRY * GetString)(GLenum);
+ void (GLAPIENTRY * GetTexEnvfv)(GLenum, GLenum, GLfloat *);
+ void (GLAPIENTRY * GetTexEnviv)(GLenum, GLenum, GLint *);
+ void (GLAPIENTRY * GetTexGendv)(GLenum, GLenum, GLdouble *);
+ void (GLAPIENTRY * GetTexGenfv)(GLenum, GLenum, GLfloat *);
+ void (GLAPIENTRY * GetTexGeniv)(GLenum, GLenum, GLint *);
+ void (GLAPIENTRY * GetTexImage)(GLenum, GLint, GLenum, GLenum, GLvoid *);
+ void (GLAPIENTRY * GetTexParameterfv)(GLenum, GLenum, GLfloat *);
+ void (GLAPIENTRY * GetTexParameteriv)(GLenum, GLenum, GLint *);
+ void (GLAPIENTRY * GetTexLevelParameterfv)(GLenum, GLint, GLenum, GLfloat *);
+ void (GLAPIENTRY * GetTexLevelParameteriv)(GLenum, GLint, GLenum, GLint *);
+ GLboolean (GLAPIENTRY * IsEnabled)(GLenum);
+ GLboolean (GLAPIENTRY * IsList)(GLuint);
+ void (GLAPIENTRY * DepthRange)(GLclampd, GLclampd);
+ void (GLAPIENTRY * Frustum)(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * LoadIdentity)(void);
+ void (GLAPIENTRY * LoadMatrixf)(const GLfloat *);
+ void (GLAPIENTRY * LoadMatrixd)(const GLdouble *);
+ void (GLAPIENTRY * MatrixMode)(GLenum);
+ void (GLAPIENTRY * MultMatrixf)(const GLfloat *);
+ void (GLAPIENTRY * MultMatrixd)(const GLdouble *);
+ void (GLAPIENTRY * Ortho)(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * PopMatrix)(void);
+ void (GLAPIENTRY * PushMatrix)(void);
+ void (GLAPIENTRY * Rotated)(GLdouble, GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * Rotatef)(GLfloat, GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * Scaled)(GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * Scalef)(GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * Translated)(GLdouble, GLdouble, GLdouble);
+ void (GLAPIENTRY * Translatef)(GLfloat, GLfloat, GLfloat);
+ void (GLAPIENTRY * Viewport)(GLint, GLint, GLsizei, GLsizei);
+ void (GLAPIENTRY * ArrayElement)(GLint);
+ void (GLAPIENTRY * BindTexture)(GLenum, GLuint);
+ void (GLAPIENTRY * ColorPointer)(GLint, GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY * DisableClientState)(GLenum);
+ void (GLAPIENTRY * DrawArrays)(GLenum, GLint, GLsizei);
+ void (GLAPIENTRY * DrawElements)(GLenum, GLsizei, GLenum, const GLvoid *);
+ void (GLAPIENTRY * EdgeFlagPointer)(GLsizei, const GLvoid *);
+ void (GLAPIENTRY * EnableClientState)(GLenum);
+ void (GLAPIENTRY * IndexPointer)(GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY * Indexub)(GLubyte);
+ void (GLAPIENTRY * Indexubv)(const GLubyte *);
+ void (GLAPIENTRY * InterleavedArrays)(GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY * NormalPointer)(GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY * PolygonOffset)(GLfloat, GLfloat);
+ void (GLAPIENTRY * TexCoordPointer)(GLint, GLenum, GLsizei, const GLvoid *);
+ void (GLAPIENTRY * VertexPointer)(GLint, GLenum, GLsizei, const GLvoid *);
+ GLboolean (GLAPIENTRY * AreTexturesResident)(GLsizei, const GLuint *, GLboolean *);
+ void (GLAPIENTRY * CopyTexImage1D)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint);
+ void (GLAPIENTRY * CopyTexImage2D)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint);
+ void (GLAPIENTRY * CopyTexSubImage1D)(GLenum, GLint, GLint, GLint, GLint, GLsizei);
+ void (GLAPIENTRY * CopyTexSubImage2D)(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei);
+ void (GLAPIENTRY * DeleteTextures)(GLsizei, const GLuint *);
+ void (GLAPIENTRY * GenTextures)(GLsizei, GLuint *);
+ void (GLAPIENTRY * GetPointerv)(GLenum, GLvoid **);
+ GLboolean (GLAPIENTRY * IsTexture)(GLuint);
+ void (GLAPIENTRY * PrioritizeTextures)(GLsizei, const GLuint *, const GLclampf *);
+ void (GLAPIENTRY * TexSubImage1D)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *);
+ void (GLAPIENTRY * TexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
+ void (GLAPIENTRY * PopClientAttrib)(void);
+ void (GLAPIENTRY * PushClientAttrib)(GLbitfield);
+};
+
+typedef struct __GLdispatchTableRec GLDISPATCHTABLE;
+
+typedef struct _GLCLTPROCTABLE
+{
+ int cEntries;
+ GLDISPATCHTABLE glDispatchTable;
+} GLCLTPROCTABLE, * PGLCLTPROCTABLE;
+
+typedef VOID (APIENTRY * PFN_SETPROCTABLE)(PGLCLTPROCTABLE);
+
+BOOL APIENTRY
+DrvCopyContext(
+ DHGLRC dhrcSource,
+ DHGLRC dhrcDest,
+ UINT fuMask );
+
+DHGLRC APIENTRY
+DrvCreateLayerContext(
+ HDC hdc,
+ INT iLayerPlane );
+
+DHGLRC APIENTRY
+DrvCreateContext(
+ HDC hdc );
+
+BOOL APIENTRY
+DrvDeleteContext(
+ DHGLRC dhglrc );
+
+BOOL APIENTRY
+DrvDescribeLayerPlane(
+ HDC hdc,
+ INT iPixelFormat,
+ INT iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd );
+
+LONG APIENTRY
+DrvDescribePixelFormat(
+ HDC hdc,
+ INT iPixelFormat,
+ ULONG cjpfd,
+ PIXELFORMATDESCRIPTOR *ppfd );
+
+int APIENTRY
+DrvGetLayerPaletteEntries(
+ HDC hdc,
+ INT iLayerPlane,
+ INT iStart,
+ INT cEntries,
+ COLORREF *pcr );
+
+PROC APIENTRY
+DrvGetProcAddress(
+ LPCSTR lpszProc );
+
+BOOL APIENTRY
+DrvRealizeLayerPalette(
+ HDC hdc,
+ INT iLayerPlane,
+ BOOL bRealize );
+
+BOOL APIENTRY
+DrvReleaseContext(
+ DHGLRC dhglrc );
+
+void APIENTRY
+DrvSetCallbackProcs(
+ INT nProcs,
+ PROC *pProcs );
+
+PGLCLTPROCTABLE APIENTRY
+DrvSetContext(
+ HDC hdc,
+ DHGLRC dhglrc,
+ PFN_SETPROCTABLE pfnSetProcTable );
+
+int APIENTRY
+DrvSetLayerPaletteEntries(
+ HDC hdc,
+ INT iLayerPlane,
+ INT iStart,
+ INT cEntries,
+ CONST COLORREF *pcr );
+
+BOOL APIENTRY
+DrvSetPixelFormat(
+ HDC hdc,
+ LONG iPixelFormat );
+
+BOOL APIENTRY
+DrvShareLists(
+ DHGLRC dhglrc1,
+ DHGLRC dhglrc2 );
+
+BOOL APIENTRY
+DrvSwapBuffers(
+ HDC hdc );
+
+BOOL APIENTRY
+DrvSwapLayerBuffers(
+ HDC hdc,
+ UINT fuPlanes );
+
+BOOL APIENTRY
+DrvValidateVersion(
+ ULONG ulVersion );
+
+#endif /* STW_ICD_H */
diff --git a/src/gallium/state_trackers/wgl/opengl32.def b/src/gallium/state_trackers/wgl/opengl32.def
new file mode 100644
index 0000000000..596417ed84
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/opengl32.def
@@ -0,0 +1,388 @@
+EXPORTS
+; GlmfBeginGlsBlock
+; GlmfCloseMetaFile
+; GlmfEndGlsBlock
+; GlmfEndPlayback
+; GlmfInitPlayback
+; GlmfPlayGlsRecord
+ glAccum
+ glAlphaFunc
+ glAreTexturesResident
+ glArrayElement
+ glBegin
+ glBindTexture
+ glBitmap
+ glBlendFunc
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearColor
+ glClearDepth
+ glClearIndex
+ glClearStencil
+ glClipPlane
+ glColor3b
+ glColor3bv
+ glColor3d
+ glColor3dv
+ glColor3f
+ glColor3fv
+ glColor3i
+ glColor3iv
+ glColor3s
+ glColor3sv
+ glColor3ub
+ glColor3ubv
+ glColor3ui
+ glColor3uiv
+ glColor3us
+ glColor3usv
+ glColor4b
+ glColor4bv
+ glColor4d
+ glColor4dv
+ glColor4f
+ glColor4fv
+ glColor4i
+ glColor4iv
+ glColor4s
+ glColor4sv
+ glColor4ub
+ glColor4ubv
+ glColor4ui
+ glColor4uiv
+ glColor4us
+ glColor4usv
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glCullFace
+; glDebugEntry
+ glDeleteLists
+ glDeleteTextures
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDisable
+ glDisableClientState
+ glDrawArrays
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glEdgeFlag
+ glEdgeFlagPointer
+ glEdgeFlagv
+ glEnable
+ glEnableClientState
+ glEnd
+ glEndList
+ glEvalCoord1d
+ glEvalCoord1dv
+ glEvalCoord1f
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2dv
+ glEvalCoord2f
+ glEvalCoord2fv
+ glEvalMesh1
+ glEvalMesh2
+ glEvalPoint1
+ glEvalPoint2
+ glFeedbackBuffer
+ glFinish
+ glFlush
+ glFogf
+ glFogfv
+ glFogi
+ glFogiv
+ glFrontFace
+ glFrustum
+ glGenLists
+ glGenTextures
+ glGetBooleanv
+ glGetClipPlane
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPointerv
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexGeniv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glHint
+ glIndexMask
+ glIndexPointer
+ glIndexd
+ glIndexdv
+ glIndexf
+ glIndexfv
+ glIndexi
+ glIndexiv
+ glIndexs
+ glIndexsv
+ glIndexub
+ glIndexubv
+ glInitNames
+ glInterleavedArrays
+ glIsEnabled
+ glIsList
+ glIsTexture
+ glLightModelf
+ glLightModelfv
+ glLightModeli
+ glLightModeliv
+ glLightf
+ glLightfv
+ glLighti
+ glLightiv
+ glLineStipple
+ glLineWidth
+ glListBase
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLogicOp
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMaterialf
+ glMaterialfv
+ glMateriali
+ glMaterialiv
+ glMatrixMode
+ glMultMatrixd
+ glMultMatrixf
+ glNewList
+ glNormal3b
+ glNormal3bv
+ glNormal3d
+ glNormal3dv
+ glNormal3f
+ glNormal3fv
+ glNormal3i
+ glNormal3iv
+ glNormal3s
+ glNormal3sv
+ glNormalPointer
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointSize
+ glPolygonMode
+ glPolygonOffset
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPushAttrib
+ glPushClientAttrib
+ glPushMatrix
+ glPushName
+ glRasterPos2d
+ glRasterPos2dv
+ glRasterPos2f
+ glRasterPos2fv
+ glRasterPos2i
+ glRasterPos2iv
+ glRasterPos2s
+ glRasterPos2sv
+ glRasterPos3d
+ glRasterPos3dv
+ glRasterPos3f
+ glRasterPos3fv
+ glRasterPos3i
+ glRasterPos3iv
+ glRasterPos3s
+ glRasterPos3sv
+ glRasterPos4d
+ glRasterPos4dv
+ glRasterPos4f
+ glRasterPos4fv
+ glRasterPos4i
+ glRasterPos4iv
+ glRasterPos4s
+ glRasterPos4sv
+ glReadBuffer
+ glReadPixels
+ glRectd
+ glRectdv
+ glRectf
+ glRectfv
+ glRecti
+ glRectiv
+ glRects
+ glRectsv
+ glRenderMode
+ glRotated
+ glRotatef
+ glScaled
+ glScalef
+ glScissor
+ glSelectBuffer
+ glShadeModel
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glTexCoord1d
+ glTexCoord1dv
+ glTexCoord1f
+ glTexCoord1fv
+ glTexCoord1i
+ glTexCoord1iv
+ glTexCoord1s
+ glTexCoord1sv
+ glTexCoord2d
+ glTexCoord2dv
+ glTexCoord2f
+ glTexCoord2fv
+ glTexCoord2i
+ glTexCoord2iv
+ glTexCoord2s
+ glTexCoord2sv
+ glTexCoord3d
+ glTexCoord3dv
+ glTexCoord3f
+ glTexCoord3fv
+ glTexCoord3i
+ glTexCoord3iv
+ glTexCoord3s
+ glTexCoord3sv
+ glTexCoord4d
+ glTexCoord4dv
+ glTexCoord4f
+ glTexCoord4fv
+ glTexCoord4i
+ glTexCoord4iv
+ glTexCoord4s
+ glTexCoord4sv
+ glTexCoordPointer
+ glTexEnvf
+ glTexEnvfv
+ glTexEnvi
+ glTexEnviv
+ glTexGend
+ glTexGendv
+ glTexGenf
+ glTexGenfv
+ glTexGeni
+ glTexGeniv
+ glTexImage1D
+ glTexImage2D
+ glTexParameterf
+ glTexParameterfv
+ glTexParameteri
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage2D
+ glTranslated
+ glTranslatef
+ glVertex2d
+ glVertex2dv
+ glVertex2f
+ glVertex2fv
+ glVertex2i
+ glVertex2iv
+ glVertex2s
+ glVertex2sv
+ glVertex3d
+ glVertex3dv
+ glVertex3f
+ glVertex3fv
+ glVertex3i
+ glVertex3iv
+ glVertex3s
+ glVertex3sv
+ glVertex4d
+ glVertex4dv
+ glVertex4f
+ glVertex4fv
+ glVertex4i
+ glVertex4iv
+ glVertex4s
+ glVertex4sv
+ glVertexPointer
+ glViewport
+ wglChoosePixelFormat
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+ wglDescribeLayerPlane
+ wglDescribePixelFormat
+ wglGetCurrentContext
+ wglGetCurrentDC
+; wglGetDefaultProcAddress
+ wglGetLayerPaletteEntries
+ wglGetPixelFormat
+ wglGetProcAddress
+ wglMakeCurrent
+ wglRealizeLayerPalette
+ wglSetLayerPaletteEntries
+ wglSetPixelFormat
+ wglShareLists
+ wglSwapBuffers
+ wglSwapLayerBuffers
+; wglSwapMultipleBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ wglGetExtensionsStringARB
+ DrvCopyContext
+ DrvCreateContext
+ DrvCreateLayerContext
+ DrvDeleteContext
+ DrvDescribeLayerPlane
+ DrvDescribePixelFormat
+ DrvGetLayerPaletteEntries
+ DrvGetProcAddress
+ DrvRealizeLayerPalette
+ DrvReleaseContext
+ DrvSetCallbackProcs
+ DrvSetContext
+ DrvSetLayerPaletteEntries
+ DrvSetPixelFormat
+ DrvShareLists
+ DrvSwapBuffers
+ DrvSwapLayerBuffers
+ DrvValidateVersion
diff --git a/src/gallium/state_trackers/wgl/opengl32.mingw.def b/src/gallium/state_trackers/wgl/opengl32.mingw.def
new file mode 100644
index 0000000000..1f03ea3b37
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/opengl32.mingw.def
@@ -0,0 +1,387 @@
+EXPORTS
+; GlmfBeginGlsBlock = GlmfBeginGlsBlock@4
+; GlmfCloseMetaFile = GlmfCloseMetaFile@4
+; GlmfEndGlsBlock = GlmfEndGlsBlock@4
+; GlmfEndPlayback = GlmfEndPlayback@4
+; GlmfInitPlayback = GlmfInitPlayback@12
+; GlmfPlayGlsRecord = GlmfPlayGlsRecord@16
+ glAccum = glAccum@8
+ glAlphaFunc = glAlphaFunc@8
+ glAreTexturesResident = glAreTexturesResident@12
+ glArrayElement = glArrayElement@4
+ glBegin = glBegin@4
+ glBindTexture = glBindTexture@8
+ glBitmap = glBitmap@28
+ glBlendFunc = glBlendFunc@8
+ glCallList = glCallList@4
+ glCallLists = glCallLists@12
+ glClear = glClear@4
+ glClearAccum = glClearAccum@16
+ glClearColor = glClearColor@16
+ glClearDepth = glClearDepth@8
+ glClearIndex = glClearIndex@4
+ glClearStencil = glClearStencil@4
+ glClipPlane = glClipPlane@8
+ glColor3b = glColor3b@12
+ glColor3bv = glColor3bv@4
+ glColor3d = glColor3d@24
+ glColor3dv = glColor3dv@4
+ glColor3f = glColor3f@12
+ glColor3fv = glColor3fv@4
+ glColor3i = glColor3i@12
+ glColor3iv = glColor3iv@4
+ glColor3s = glColor3s@12
+ glColor3sv = glColor3sv@4
+ glColor3ub = glColor3ub@12
+ glColor3ubv = glColor3ubv@4
+ glColor3ui = glColor3ui@12
+ glColor3uiv = glColor3uiv@4
+ glColor3us = glColor3us@12
+ glColor3usv = glColor3usv@4
+ glColor4b = glColor4b@16
+ glColor4bv = glColor4bv@4
+ glColor4d = glColor4d@32
+ glColor4dv = glColor4dv@4
+ glColor4f = glColor4f@16
+ glColor4fv = glColor4fv@4
+ glColor4i = glColor4i@16
+ glColor4iv = glColor4iv@4
+ glColor4s = glColor4s@16
+ glColor4sv = glColor4sv@4
+ glColor4ub = glColor4ub@16
+ glColor4ubv = glColor4ubv@4
+ glColor4ui = glColor4ui@16
+ glColor4uiv = glColor4uiv@4
+ glColor4us = glColor4us@16
+ glColor4usv = glColor4usv@4
+ glColorMask = glColorMask@16
+ glColorMaterial = glColorMaterial@8
+ glColorPointer = glColorPointer@16
+ glCopyPixels = glCopyPixels@20
+ glCopyTexImage1D = glCopyTexImage1D@28
+ glCopyTexImage2D = glCopyTexImage2D@32
+ glCopyTexSubImage1D = glCopyTexSubImage1D@24
+ glCopyTexSubImage2D = glCopyTexSubImage2D@32
+ glCullFace = glCullFace@4
+; glDebugEntry = glDebugEntry@8
+ glDeleteLists = glDeleteLists@8
+ glDeleteTextures = glDeleteTextures@8
+ glDepthFunc = glDepthFunc@4
+ glDepthMask = glDepthMask@4
+ glDepthRange = glDepthRange@16
+ glDisable = glDisable@4
+ glDisableClientState = glDisableClientState@4
+ glDrawArrays = glDrawArrays@12
+ glDrawBuffer = glDrawBuffer@4
+ glDrawElements = glDrawElements@16
+ glDrawPixels = glDrawPixels@20
+ glEdgeFlag = glEdgeFlag@4
+ glEdgeFlagPointer = glEdgeFlagPointer@8
+ glEdgeFlagv = glEdgeFlagv@4
+ glEnable = glEnable@4
+ glEnableClientState = glEnableClientState@4
+ glEnd = glEnd@0
+ glEndList = glEndList@0
+ glEvalCoord1d = glEvalCoord1d@8
+ glEvalCoord1dv = glEvalCoord1dv@4
+ glEvalCoord1f = glEvalCoord1f@4
+ glEvalCoord1fv = glEvalCoord1fv@4
+ glEvalCoord2d = glEvalCoord2d@16
+ glEvalCoord2dv = glEvalCoord2dv@4
+ glEvalCoord2f = glEvalCoord2f@8
+ glEvalCoord2fv = glEvalCoord2fv@4
+ glEvalMesh1 = glEvalMesh1@12
+ glEvalMesh2 = glEvalMesh2@20
+ glEvalPoint1 = glEvalPoint1@4
+ glEvalPoint2 = glEvalPoint2@8
+ glFeedbackBuffer = glFeedbackBuffer@12
+ glFinish = glFinish@0
+ glFlush = glFlush@0
+ glFogf = glFogf@8
+ glFogfv = glFogfv@8
+ glFogi = glFogi@8
+ glFogiv = glFogiv@8
+ glFrontFace = glFrontFace@4
+ glFrustum = glFrustum@48
+ glGenLists = glGenLists@4
+ glGenTextures = glGenTextures@8
+ glGetBooleanv = glGetBooleanv@8
+ glGetClipPlane = glGetClipPlane@8
+ glGetDoublev = glGetDoublev@8
+ glGetError = glGetError@0
+ glGetFloatv = glGetFloatv@8
+ glGetIntegerv = glGetIntegerv@8
+ glGetLightfv = glGetLightfv@12
+ glGetLightiv = glGetLightiv@12
+ glGetMapdv = glGetMapdv@12
+ glGetMapfv = glGetMapfv@12
+ glGetMapiv = glGetMapiv@12
+ glGetMaterialfv = glGetMaterialfv@12
+ glGetMaterialiv = glGetMaterialiv@12
+ glGetPixelMapfv = glGetPixelMapfv@8
+ glGetPixelMapuiv = glGetPixelMapuiv@8
+ glGetPixelMapusv = glGetPixelMapusv@8
+ glGetPointerv = glGetPointerv@8
+ glGetPolygonStipple = glGetPolygonStipple@4
+ glGetString = glGetString@4
+ glGetTexEnvfv = glGetTexEnvfv@12
+ glGetTexEnviv = glGetTexEnviv@12
+ glGetTexGendv = glGetTexGendv@12
+ glGetTexGenfv = glGetTexGenfv@12
+ glGetTexGeniv = glGetTexGeniv@12
+ glGetTexImage = glGetTexImage@20
+ glGetTexLevelParameterfv = glGetTexLevelParameterfv@16
+ glGetTexLevelParameteriv = glGetTexLevelParameteriv@16
+ glGetTexParameterfv = glGetTexParameterfv@12
+ glGetTexParameteriv = glGetTexParameteriv@12
+ glHint = glHint@8
+ glIndexMask = glIndexMask@4
+ glIndexPointer = glIndexPointer@12
+ glIndexd = glIndexd@8
+ glIndexdv = glIndexdv@4
+ glIndexf = glIndexf@4
+ glIndexfv = glIndexfv@4
+ glIndexi = glIndexi@4
+ glIndexiv = glIndexiv@4
+ glIndexs = glIndexs@4
+ glIndexsv = glIndexsv@4
+ glIndexub = glIndexub@4
+ glIndexubv = glIndexubv@4
+ glInitNames = glInitNames@0
+ glInterleavedArrays = glInterleavedArrays@12
+ glIsEnabled = glIsEnabled@4
+ glIsList = glIsList@4
+ glIsTexture = glIsTexture@4
+ glLightModelf = glLightModelf@8
+ glLightModelfv = glLightModelfv@8
+ glLightModeli = glLightModeli@8
+ glLightModeliv = glLightModeliv@8
+ glLightf = glLightf@12
+ glLightfv = glLightfv@12
+ glLighti = glLighti@12
+ glLightiv = glLightiv@12
+ glLineStipple = glLineStipple@8
+ glLineWidth = glLineWidth@4
+ glListBase = glListBase@4
+ glLoadIdentity = glLoadIdentity@0
+ glLoadMatrixd = glLoadMatrixd@4
+ glLoadMatrixf = glLoadMatrixf@4
+ glLoadName = glLoadName@4
+ glLogicOp = glLogicOp@4
+ glMap1d = glMap1d@32
+ glMap1f = glMap1f@24
+ glMap2d = glMap2d@56
+ glMap2f = glMap2f@40
+ glMapGrid1d = glMapGrid1d@20
+ glMapGrid1f = glMapGrid1f@12
+ glMapGrid2d = glMapGrid2d@40
+ glMapGrid2f = glMapGrid2f@24
+ glMaterialf = glMaterialf@12
+ glMaterialfv = glMaterialfv@12
+ glMateriali = glMateriali@12
+ glMaterialiv = glMaterialiv@12
+ glMatrixMode = glMatrixMode@4
+ glMultMatrixd = glMultMatrixd@4
+ glMultMatrixf = glMultMatrixf@4
+ glNewList = glNewList@8
+ glNormal3b = glNormal3b@12
+ glNormal3bv = glNormal3bv@4
+ glNormal3d = glNormal3d@24
+ glNormal3dv = glNormal3dv@4
+ glNormal3f = glNormal3f@12
+ glNormal3fv = glNormal3fv@4
+ glNormal3i = glNormal3i@12
+ glNormal3iv = glNormal3iv@4
+ glNormal3s = glNormal3s@12
+ glNormal3sv = glNormal3sv@4
+ glNormalPointer = glNormalPointer@12
+ glOrtho = glOrtho@48
+ glPassThrough = glPassThrough@4
+ glPixelMapfv = glPixelMapfv@12
+ glPixelMapuiv = glPixelMapuiv@12
+ glPixelMapusv = glPixelMapusv@12
+ glPixelStoref = glPixelStoref@8
+ glPixelStorei = glPixelStorei@8
+ glPixelTransferf = glPixelTransferf@8
+ glPixelTransferi = glPixelTransferi@8
+ glPixelZoom = glPixelZoom@8
+ glPointSize = glPointSize@4
+ glPolygonMode = glPolygonMode@8
+ glPolygonOffset = glPolygonOffset@8
+ glPolygonStipple = glPolygonStipple@4
+ glPopAttrib = glPopAttrib@0
+ glPopClientAttrib = glPopClientAttrib@0
+ glPopMatrix = glPopMatrix@0
+ glPopName = glPopName@0
+ glPrioritizeTextures = glPrioritizeTextures@12
+ glPushAttrib = glPushAttrib@4
+ glPushClientAttrib = glPushClientAttrib@4
+ glPushMatrix = glPushMatrix@0
+ glPushName = glPushName@4
+ glRasterPos2d = glRasterPos2d@16
+ glRasterPos2dv = glRasterPos2dv@4
+ glRasterPos2f = glRasterPos2f@8
+ glRasterPos2fv = glRasterPos2fv@4
+ glRasterPos2i = glRasterPos2i@8
+ glRasterPos2iv = glRasterPos2iv@4
+ glRasterPos2s = glRasterPos2s@8
+ glRasterPos2sv = glRasterPos2sv@4
+ glRasterPos3d = glRasterPos3d@24
+ glRasterPos3dv = glRasterPos3dv@4
+ glRasterPos3f = glRasterPos3f@12
+ glRasterPos3fv = glRasterPos3fv@4
+ glRasterPos3i = glRasterPos3i@12
+ glRasterPos3iv = glRasterPos3iv@4
+ glRasterPos3s = glRasterPos3s@12
+ glRasterPos3sv = glRasterPos3sv@4
+ glRasterPos4d = glRasterPos4d@32
+ glRasterPos4dv = glRasterPos4dv@4
+ glRasterPos4f = glRasterPos4f@16
+ glRasterPos4fv = glRasterPos4fv@4
+ glRasterPos4i = glRasterPos4i@16
+ glRasterPos4iv = glRasterPos4iv@4
+ glRasterPos4s = glRasterPos4s@16
+ glRasterPos4sv = glRasterPos4sv@4
+ glReadBuffer = glReadBuffer@4
+ glReadPixels = glReadPixels@28
+ glRectd = glRectd@32
+ glRectdv = glRectdv@8
+ glRectf = glRectf@16
+ glRectfv = glRectfv@8
+ glRecti = glRecti@16
+ glRectiv = glRectiv@8
+ glRects = glRects@16
+ glRectsv = glRectsv@8
+ glRenderMode = glRenderMode@4
+ glRotated = glRotated@32
+ glRotatef = glRotatef@16
+ glScaled = glScaled@24
+ glScalef = glScalef@12
+ glScissor = glScissor@16
+ glSelectBuffer = glSelectBuffer@8
+ glShadeModel = glShadeModel@4
+ glStencilFunc = glStencilFunc@12
+ glStencilMask = glStencilMask@4
+ glStencilOp = glStencilOp@12
+ glTexCoord1d = glTexCoord1d@8
+ glTexCoord1dv = glTexCoord1dv@4
+ glTexCoord1f = glTexCoord1f@4
+ glTexCoord1fv = glTexCoord1fv@4
+ glTexCoord1i = glTexCoord1i@4
+ glTexCoord1iv = glTexCoord1iv@4
+ glTexCoord1s = glTexCoord1s@4
+ glTexCoord1sv = glTexCoord1sv@4
+ glTexCoord2d = glTexCoord2d@16
+ glTexCoord2dv = glTexCoord2dv@4
+ glTexCoord2f = glTexCoord2f@8
+ glTexCoord2fv = glTexCoord2fv@4
+ glTexCoord2i = glTexCoord2i@8
+ glTexCoord2iv = glTexCoord2iv@4
+ glTexCoord2s = glTexCoord2s@8
+ glTexCoord2sv = glTexCoord2sv@4
+ glTexCoord3d = glTexCoord3d@24
+ glTexCoord3dv = glTexCoord3dv@4
+ glTexCoord3f = glTexCoord3f@12
+ glTexCoord3fv = glTexCoord3fv@4
+ glTexCoord3i = glTexCoord3i@12
+ glTexCoord3iv = glTexCoord3iv@4
+ glTexCoord3s = glTexCoord3s@12
+ glTexCoord3sv = glTexCoord3sv@4
+ glTexCoord4d = glTexCoord4d@32
+ glTexCoord4dv = glTexCoord4dv@4
+ glTexCoord4f = glTexCoord4f@16
+ glTexCoord4fv = glTexCoord4fv@4
+ glTexCoord4i = glTexCoord4i@16
+ glTexCoord4iv = glTexCoord4iv@4
+ glTexCoord4s = glTexCoord4s@16
+ glTexCoord4sv = glTexCoord4sv@4
+ glTexCoordPointer = glTexCoordPointer@16
+ glTexEnvf = glTexEnvf@12
+ glTexEnvfv = glTexEnvfv@12
+ glTexEnvi = glTexEnvi@12
+ glTexEnviv = glTexEnviv@12
+ glTexGend = glTexGend@16
+ glTexGendv = glTexGendv@12
+ glTexGenf = glTexGenf@12
+ glTexGenfv = glTexGenfv@12
+ glTexGeni = glTexGeni@12
+ glTexGeniv = glTexGeniv@12
+ glTexImage1D = glTexImage1D@32
+ glTexImage2D = glTexImage2D@36
+ glTexParameterf = glTexParameterf@12
+ glTexParameterfv = glTexParameterfv@12
+ glTexParameteri = glTexParameteri@12
+ glTexParameteriv = glTexParameteriv@12
+ glTexSubImage1D = glTexSubImage1D@28
+ glTexSubImage2D = glTexSubImage2D@36
+ glTranslated = glTranslated@24
+ glTranslatef = glTranslatef@12
+ glVertex2d = glVertex2d@16
+ glVertex2dv = glVertex2dv@4
+ glVertex2f = glVertex2f@8
+ glVertex2fv = glVertex2fv@4
+ glVertex2i = glVertex2i@8
+ glVertex2iv = glVertex2iv@4
+ glVertex2s = glVertex2s@8
+ glVertex2sv = glVertex2sv@4
+ glVertex3d = glVertex3d@24
+ glVertex3dv = glVertex3dv@4
+ glVertex3f = glVertex3f@12
+ glVertex3fv = glVertex3fv@4
+ glVertex3i = glVertex3i@12
+ glVertex3iv = glVertex3iv@4
+ glVertex3s = glVertex3s@12
+ glVertex3sv = glVertex3sv@4
+ glVertex4d = glVertex4d@32
+ glVertex4dv = glVertex4dv@4
+ glVertex4f = glVertex4f@16
+ glVertex4fv = glVertex4fv@4
+ glVertex4i = glVertex4i@16
+ glVertex4iv = glVertex4iv@4
+ glVertex4s = glVertex4s@16
+ glVertex4sv = glVertex4sv@4
+ glVertexPointer = glVertexPointer@16
+ glViewport = glViewport@16
+ wglChoosePixelFormat = wglChoosePixelFormat@8
+ wglCopyContext = wglCopyContext@12
+ wglCreateContext = wglCreateContext@4
+ wglCreateLayerContext = wglCreateLayerContext@8
+ wglDeleteContext = wglDeleteContext@4
+ wglDescribeLayerPlane = wglDescribeLayerPlane@20
+ wglDescribePixelFormat = wglDescribePixelFormat@16
+ wglGetCurrentContext = wglGetCurrentContext@0
+ wglGetCurrentDC = wglGetCurrentDC@0
+; wglGetDefaultProcAddress = wglGetDefaultProcAddress@4
+ wglGetLayerPaletteEntries = wglGetLayerPaletteEntries@20
+ wglGetPixelFormat = wglGetPixelFormat@4
+ wglGetProcAddress = wglGetProcAddress@4
+ wglMakeCurrent = wglMakeCurrent@8
+ wglRealizeLayerPalette = wglRealizeLayerPalette@12
+ wglSetLayerPaletteEntries = wglSetLayerPaletteEntries@20
+ wglSetPixelFormat = wglSetPixelFormat@12
+ wglShareLists = wglShareLists@8
+ wglSwapBuffers = wglSwapBuffers@4
+ wglSwapLayerBuffers = wglSwapLayerBuffers@8
+; wglSwapMultipleBuffers = wglSwapMultipleBuffers@8
+ wglUseFontBitmapsA = wglUseFontBitmapsA@16
+ wglUseFontBitmapsW = wglUseFontBitmapsW@16
+ wglUseFontOutlinesA = wglUseFontOutlinesA@32
+ wglUseFontOutlinesW = wglUseFontOutlinesW@32
+ DrvCopyContext = DrvCopyContext@12
+ DrvCreateContext = DrvCreateContext@4
+ DrvCreateLayerContext = DrvCreateLayerContext@8
+ DrvDeleteContext = DrvDeleteContext@4
+ DrvDescribeLayerPlane = DrvDescribeLayerPlane@20
+ DrvDescribePixelFormat = DrvDescribePixelFormat@16
+ DrvGetLayerPaletteEntries = DrvGetLayerPaletteEntries@20
+ DrvGetProcAddress = DrvGetProcAddress@4
+ DrvRealizeLayerPalette = DrvRealizeLayerPalette@12
+ DrvReleaseContext = DrvReleaseContext@4
+ DrvSetCallbackProcs = DrvSetCallbackProcs@8
+ DrvSetContext = DrvSetContext@12
+ DrvSetLayerPaletteEntries = DrvSetLayerPaletteEntries@20
+ DrvSetPixelFormat = DrvSetPixelFormat@8
+ DrvShareLists = DrvShareLists@8
+ DrvSwapBuffers = DrvSwapBuffers@4
+ DrvSwapLayerBuffers = DrvSwapLayerBuffers@8
+ DrvValidateVersion = DrvValidateVersion@4
diff --git a/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c b/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c
new file mode 100644
index 0000000000..0e2d407699
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c
@@ -0,0 +1,483 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ *
+ * WGL_ARB_pixel_format extension implementation.
+ *
+ * @sa http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
+ */
+
+
+#include <windows.h>
+
+#define WGL_WGLEXT_PROTOTYPES
+
+#include <GL/gl.h>
+#include <GL/wglext.h>
+
+#include "pipe/p_compiler.h"
+#include "util/u_memory.h"
+#include "stw_public.h"
+#include "stw_pixelformat.h"
+
+
+static boolean
+stw_query_attrib(
+ int iPixelFormat,
+ int iLayerPlane,
+ int attrib,
+ int *pvalue )
+{
+ uint count;
+ uint index;
+ const struct stw_pixelformat_info *pfi;
+
+ count = stw_pixelformat_get_extended_count();
+
+ if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB) {
+ *pvalue = (int) count;
+ return TRUE;
+ }
+
+ index = (uint) iPixelFormat - 1;
+ if (index >= count)
+ return FALSE;
+
+ pfi = stw_pixelformat_get_info( index );
+
+ switch (attrib) {
+ case WGL_DRAW_TO_WINDOW_ARB:
+ *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? TRUE : FALSE;
+ return TRUE;
+
+ case WGL_DRAW_TO_BITMAP_ARB:
+ *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_BITMAP ? TRUE : FALSE;
+ return TRUE;
+
+ case WGL_NEED_PALETTE_ARB:
+ *pvalue = pfi->pfd.dwFlags & PFD_NEED_PALETTE ? TRUE : FALSE;
+ return TRUE;
+
+ case WGL_NEED_SYSTEM_PALETTE_ARB:
+ *pvalue = pfi->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE;
+ return TRUE;
+
+ case WGL_SWAP_METHOD_ARB:
+ *pvalue = pfi->pfd.dwFlags & PFD_SWAP_COPY ? WGL_SWAP_COPY_ARB : WGL_SWAP_UNDEFINED_ARB;
+ return TRUE;
+
+ case WGL_SWAP_LAYER_BUFFERS_ARB:
+ *pvalue = FALSE;
+ return TRUE;
+
+ case WGL_NUMBER_OVERLAYS_ARB:
+ *pvalue = 0;
+ return TRUE;
+
+ case WGL_NUMBER_UNDERLAYS_ARB:
+ *pvalue = 0;
+ return TRUE;
+ }
+
+ if (iLayerPlane != 0)
+ return FALSE;
+
+ switch (attrib) {
+ case WGL_ACCELERATION_ARB:
+ *pvalue = WGL_FULL_ACCELERATION_ARB;
+ break;
+
+ case WGL_TRANSPARENT_ARB:
+ *pvalue = FALSE;
+ break;
+
+ case WGL_TRANSPARENT_RED_VALUE_ARB:
+ case WGL_TRANSPARENT_GREEN_VALUE_ARB:
+ case WGL_TRANSPARENT_BLUE_VALUE_ARB:
+ case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
+ case WGL_TRANSPARENT_INDEX_VALUE_ARB:
+ break;
+
+ case WGL_SHARE_DEPTH_ARB:
+ case WGL_SHARE_STENCIL_ARB:
+ case WGL_SHARE_ACCUM_ARB:
+ *pvalue = TRUE;
+ break;
+
+ case WGL_SUPPORT_GDI_ARB:
+ *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_GDI ? TRUE : FALSE;
+ break;
+
+ case WGL_SUPPORT_OPENGL_ARB:
+ *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_OPENGL ? TRUE : FALSE;
+ break;
+
+ case WGL_DOUBLE_BUFFER_ARB:
+ *pvalue = pfi->pfd.dwFlags & PFD_DOUBLEBUFFER ? TRUE : FALSE;
+ break;
+
+ case WGL_STEREO_ARB:
+ *pvalue = pfi->pfd.dwFlags & PFD_STEREO ? TRUE : FALSE;
+ break;
+
+ case WGL_PIXEL_TYPE_ARB:
+ switch (pfi->pfd.iPixelType) {
+ case PFD_TYPE_RGBA:
+ *pvalue = WGL_TYPE_RGBA_ARB;
+ break;
+ case PFD_TYPE_COLORINDEX:
+ *pvalue = WGL_TYPE_COLORINDEX_ARB;
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+
+ case WGL_COLOR_BITS_ARB:
+ *pvalue = pfi->pfd.cColorBits;
+ break;
+
+ case WGL_RED_BITS_ARB:
+ *pvalue = pfi->pfd.cRedBits;
+ break;
+
+ case WGL_RED_SHIFT_ARB:
+ *pvalue = pfi->pfd.cRedShift;
+ break;
+
+ case WGL_GREEN_BITS_ARB:
+ *pvalue = pfi->pfd.cGreenBits;
+ break;
+
+ case WGL_GREEN_SHIFT_ARB:
+ *pvalue = pfi->pfd.cGreenShift;
+ break;
+
+ case WGL_BLUE_BITS_ARB:
+ *pvalue = pfi->pfd.cBlueBits;
+ break;
+
+ case WGL_BLUE_SHIFT_ARB:
+ *pvalue = pfi->pfd.cBlueShift;
+ break;
+
+ case WGL_ALPHA_BITS_ARB:
+ *pvalue = pfi->pfd.cAlphaBits;
+ break;
+
+ case WGL_ALPHA_SHIFT_ARB:
+ *pvalue = pfi->pfd.cAlphaShift;
+ break;
+
+ case WGL_ACCUM_BITS_ARB:
+ *pvalue = pfi->pfd.cAccumBits;
+ break;
+
+ case WGL_ACCUM_RED_BITS_ARB:
+ *pvalue = pfi->pfd.cAccumRedBits;
+ break;
+
+ case WGL_ACCUM_GREEN_BITS_ARB:
+ *pvalue = pfi->pfd.cAccumGreenBits;
+ break;
+
+ case WGL_ACCUM_BLUE_BITS_ARB:
+ *pvalue = pfi->pfd.cAccumBlueBits;
+ break;
+
+ case WGL_ACCUM_ALPHA_BITS_ARB:
+ *pvalue = pfi->pfd.cAccumAlphaBits;
+ break;
+
+ case WGL_DEPTH_BITS_ARB:
+ *pvalue = pfi->pfd.cDepthBits;
+ break;
+
+ case WGL_STENCIL_BITS_ARB:
+ *pvalue = pfi->pfd.cStencilBits;
+ break;
+
+ case WGL_AUX_BUFFERS_ARB:
+ *pvalue = pfi->pfd.cAuxBuffers;
+ break;
+
+ case WGL_SAMPLE_BUFFERS_ARB:
+ *pvalue = pfi->numSampleBuffers;
+ break;
+
+ case WGL_SAMPLES_ARB:
+ *pvalue = pfi->numSamples;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+struct attrib_match_info
+{
+ int attribute;
+ int weight;
+ BOOL exact;
+};
+
+static const struct attrib_match_info attrib_match[] = {
+
+ /* WGL_ARB_pixel_format */
+ { WGL_DRAW_TO_WINDOW_ARB, 0, TRUE },
+ { WGL_DRAW_TO_BITMAP_ARB, 0, TRUE },
+ { WGL_ACCELERATION_ARB, 0, TRUE },
+ { WGL_NEED_PALETTE_ARB, 0, TRUE },
+ { WGL_NEED_SYSTEM_PALETTE_ARB, 0, TRUE },
+ { WGL_SWAP_LAYER_BUFFERS_ARB, 0, TRUE },
+ { WGL_SWAP_METHOD_ARB, 0, TRUE },
+ { WGL_NUMBER_OVERLAYS_ARB, 4, FALSE },
+ { WGL_NUMBER_UNDERLAYS_ARB, 4, FALSE },
+ /*{ WGL_SHARE_DEPTH_ARB, 0, TRUE },*/ /* no overlays -- ignore */
+ /*{ WGL_SHARE_STENCIL_ARB, 0, TRUE },*/ /* no overlays -- ignore */
+ /*{ WGL_SHARE_ACCUM_ARB, 0, TRUE },*/ /* no overlays -- ignore */
+ { WGL_SUPPORT_GDI_ARB, 0, TRUE },
+ { WGL_SUPPORT_OPENGL_ARB, 0, TRUE },
+ { WGL_DOUBLE_BUFFER_ARB, 0, TRUE },
+ { WGL_STEREO_ARB, 0, TRUE },
+ { WGL_PIXEL_TYPE_ARB, 0, TRUE },
+ { WGL_COLOR_BITS_ARB, 1, FALSE },
+ { WGL_RED_BITS_ARB, 1, FALSE },
+ { WGL_GREEN_BITS_ARB, 1, FALSE },
+ { WGL_BLUE_BITS_ARB, 1, FALSE },
+ { WGL_ALPHA_BITS_ARB, 1, FALSE },
+ { WGL_ACCUM_BITS_ARB, 1, FALSE },
+ { WGL_ACCUM_RED_BITS_ARB, 1, FALSE },
+ { WGL_ACCUM_GREEN_BITS_ARB, 1, FALSE },
+ { WGL_ACCUM_BLUE_BITS_ARB, 1, FALSE },
+ { WGL_ACCUM_ALPHA_BITS_ARB, 1, FALSE },
+ { WGL_DEPTH_BITS_ARB, 1, FALSE },
+ { WGL_STENCIL_BITS_ARB, 1, FALSE },
+ { WGL_AUX_BUFFERS_ARB, 2, FALSE },
+
+ /* WGL_ARB_multisample */
+ { WGL_SAMPLE_BUFFERS_ARB, 2, FALSE },
+ { WGL_SAMPLES_ARB, 2, FALSE }
+};
+
+struct stw_pixelformat_score
+{
+ int points;
+ uint index;
+};
+
+static BOOL
+score_pixelformats(
+ struct stw_pixelformat_score *scores,
+ uint count,
+ int attribute,
+ int expected_value )
+{
+ uint i;
+ const struct attrib_match_info *ami = NULL;
+ uint index;
+
+ /* Find out if a given attribute should be considered for score calculation.
+ */
+ for (i = 0; i < sizeof( attrib_match ) / sizeof( attrib_match[0] ); i++) {
+ if (attrib_match[i].attribute == attribute) {
+ ami = &attrib_match[i];
+ break;
+ }
+ }
+ if (ami == NULL)
+ return TRUE;
+
+ /* Iterate all pixelformats, query the requested attribute and calculate
+ * score points.
+ */
+ for (index = 0; index < count; index++) {
+ int actual_value;
+
+ if (!stw_query_attrib( index + 1, 0, attribute, &actual_value ))
+ return FALSE;
+
+ if (ami->exact) {
+ /* For an exact match criteria, if the actual and expected values differ,
+ * the score is set to 0 points, effectively removing the pixelformat
+ * from a list of matching pixelformats.
+ */
+ if (actual_value != expected_value)
+ scores[index].points = 0;
+ }
+ else {
+ /* For a minimum match criteria, if the actual value is smaller than the expected
+ * value, the pixelformat is rejected (score set to 0). However, if the actual
+ * value is bigger, the pixelformat is given a penalty to favour pixelformats that
+ * more closely match the expected values.
+ */
+ if (actual_value < expected_value)
+ scores[index].points = 0;
+ else if (actual_value > expected_value)
+ scores[index].points -= (actual_value - expected_value) * ami->weight;
+ }
+ }
+
+ return TRUE;
+}
+
+WINGDIAPI BOOL APIENTRY
+wglChoosePixelFormatARB(
+ HDC hdc,
+ const int *piAttribIList,
+ const FLOAT *pfAttribFList,
+ UINT nMaxFormats,
+ int *piFormats,
+ UINT *nNumFormats )
+{
+ uint count;
+ struct stw_pixelformat_score *scores;
+ uint i;
+
+ *nNumFormats = 0;
+
+ /* Allocate and initialize pixelformat score table -- better matches
+ * have higher scores. Start with a high score and take out penalty
+ * points for a mismatch when the match does not have to be exact.
+ * Set a score to 0 if there is a mismatch for an exact match criteria.
+ */
+ count = stw_pixelformat_get_extended_count();
+ scores = (struct stw_pixelformat_score *) MALLOC( count * sizeof( struct stw_pixelformat_score ) );
+ if (scores == NULL)
+ return FALSE;
+ for (i = 0; i < count; i++) {
+ scores[i].points = 0x7fffffff;
+ scores[i].index = i;
+ }
+
+ /* Given the attribute list calculate a score for each pixelformat.
+ */
+ if (piAttribIList != NULL) {
+ while (*piAttribIList != 0) {
+ if (!score_pixelformats( scores, count, piAttribIList[0], piAttribIList[1] )) {
+ FREE( scores );
+ return FALSE;
+ }
+ piAttribIList += 2;
+ }
+ }
+ if (pfAttribFList != NULL) {
+ while (*pfAttribFList != 0) {
+ if (!score_pixelformats( scores, count, (int) pfAttribFList[0], (int) pfAttribFList[1] )) {
+ FREE( scores );
+ return FALSE;
+ }
+ pfAttribFList += 2;
+ }
+ }
+
+ /* Bubble-sort the resulting scores. Pixelformats with higher scores go first.
+ * TODO: Find out if there are any patent issues with it.
+ */
+ if (count > 1) {
+ uint n = count;
+ boolean swapped;
+
+ do {
+ swapped = FALSE;
+ for (i = 1; i < n; i++) {
+ if (scores[i - 1].points < scores[i].points) {
+ struct stw_pixelformat_score score = scores[i - 1];
+
+ scores[i - 1] = scores[i];
+ scores[i] = score;
+ swapped = TRUE;
+ }
+ }
+ n--;
+ }
+ while (swapped);
+ }
+
+ /* Return a list of pixelformats that are the best match.
+ * Reject pixelformats with non-positive scores.
+ */
+ for (i = 0; i < count; i++) {
+ if (scores[i].points > 0) {
+ if (*nNumFormats < nMaxFormats)
+ piFormats[*nNumFormats] = scores[i].index + 1;
+ (*nNumFormats)++;
+ }
+ }
+
+ FREE( scores );
+ return TRUE;
+}
+
+WINGDIAPI BOOL APIENTRY
+wglGetPixelFormatAttribfvARB(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int *piAttributes,
+ FLOAT *pfValues )
+{
+ UINT i;
+
+ (void) hdc;
+
+ for (i = 0; i < nAttributes; i++) {
+ int value;
+
+ if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &value ))
+ return FALSE;
+ pfValues[i] = (FLOAT) value;
+ }
+
+ return TRUE;
+}
+
+WINGDIAPI BOOL APIENTRY
+wglGetPixelFormatAttribivARB(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int *piAttributes,
+ int *piValues )
+{
+ UINT i;
+
+ (void) hdc;
+
+ for (i = 0; i < nAttributes; i++) {
+ if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &piValues[i] ))
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_context.c b/src/gallium/state_trackers/wgl/shared/stw_context.c
new file mode 100644
index 0000000000..4968ecc692
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_context.c
@@ -0,0 +1,382 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+
+#include "main/mtypes.h"
+#include "main/context.h"
+#include "pipe/p_compiler.h"
+#include "pipe/p_context.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_public.h"
+
+#ifdef DEBUG
+#include "trace/tr_screen.h"
+#include "trace/tr_context.h"
+#endif
+
+#include "shared/stw_device.h"
+#include "shared/stw_winsys.h"
+#include "shared/stw_framebuffer.h"
+#include "shared/stw_pixelformat.h"
+#include "stw_public.h"
+#include "stw_context.h"
+#include "stw_tls.h"
+
+
+static INLINE struct stw_context *
+stw_context(GLcontext *glctx)
+{
+ if(!glctx)
+ return NULL;
+ assert(glctx->DriverCtx);
+ return (struct stw_context *)glctx->DriverCtx;
+}
+
+static INLINE struct stw_context *
+stw_current_context(void)
+{
+ /* We must check if multiple threads are being used or GET_CURRENT_CONTEXT
+ * might return the current context of the thread first seen. */
+ _glapi_check_multithread();
+
+ {
+ GET_CURRENT_CONTEXT( glctx );
+ return stw_context(glctx);
+ }
+}
+
+BOOL
+stw_copy_context(
+ UINT_PTR hglrcSrc,
+ UINT_PTR hglrcDst,
+ UINT mask )
+{
+ struct stw_context *src;
+ struct stw_context *dst;
+ BOOL ret = FALSE;
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+
+ src = stw_lookup_context_locked( hglrcSrc );
+ dst = stw_lookup_context_locked( hglrcDst );
+
+ if (src && dst) {
+ /* FIXME */
+ assert(0);
+ (void) src;
+ (void) dst;
+ (void) mask;
+ }
+
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+
+ return ret;
+}
+
+BOOL
+stw_share_lists(
+ UINT_PTR hglrc1,
+ UINT_PTR hglrc2 )
+{
+ struct stw_context *ctx1;
+ struct stw_context *ctx2;
+ BOOL ret = FALSE;
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+
+ ctx1 = stw_lookup_context_locked( hglrc1 );
+ ctx2 = stw_lookup_context_locked( hglrc2 );
+
+ if (ctx1 && ctx2 &&
+ ctx1->iPixelFormat == ctx2->iPixelFormat) {
+ ret = _mesa_share_state(ctx2->st->ctx, ctx1->st->ctx);
+ }
+
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+
+ return ret;
+}
+
+static void
+stw_viewport(GLcontext * glctx, GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ struct stw_context *ctx = (struct stw_context *)glctx->DriverCtx;
+ struct stw_framebuffer *fb;
+
+ fb = stw_framebuffer_from_hdc( ctx->hdc );
+ if(fb) {
+ stw_framebuffer_update(fb);
+ stw_framebuffer_release(fb);
+ }
+}
+
+UINT_PTR
+stw_create_layer_context(
+ HDC hdc,
+ int iLayerPlane )
+{
+ int iPixelFormat;
+ const struct stw_pixelformat_info *pfi;
+ GLvisual visual;
+ struct stw_context *ctx = NULL;
+ struct pipe_screen *screen = NULL;
+ struct pipe_context *pipe = NULL;
+
+ if(!stw_dev)
+ return 0;
+
+ if (iLayerPlane != 0)
+ return 0;
+
+ iPixelFormat = GetPixelFormat(hdc);
+ if(!iPixelFormat)
+ return 0;
+
+ pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
+ stw_pixelformat_visual(&visual, pfi);
+
+ ctx = CALLOC_STRUCT( stw_context );
+ if (ctx == NULL)
+ goto no_ctx;
+
+ ctx->hdc = hdc;
+ ctx->iPixelFormat = iPixelFormat;
+
+ screen = stw_dev->screen;
+
+#ifdef DEBUG
+ /* Unwrap screen */
+ if(stw_dev->trace_running)
+ screen = trace_screen(screen)->screen;
+#endif
+
+ pipe = stw_dev->stw_winsys->create_context( screen );
+ if (pipe == NULL)
+ goto no_pipe;
+
+#ifdef DEBUG
+ /* Wrap context */
+ if(stw_dev->trace_running)
+ pipe = trace_context_create(stw_dev->screen, pipe);
+#endif
+
+ /* pass to stw_flush_frontbuffer as context_private */
+ assert(!pipe->priv);
+ pipe->priv = hdc;
+
+ ctx->st = st_create_context( pipe, &visual, NULL );
+ if (ctx->st == NULL)
+ goto no_st_ctx;
+
+ ctx->st->ctx->DriverCtx = ctx;
+ ctx->st->ctx->Driver.Viewport = stw_viewport;
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+ ctx->hglrc = handle_table_add(stw_dev->ctx_table, ctx);
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+ if (!ctx->hglrc)
+ goto no_hglrc;
+
+ return ctx->hglrc;
+
+no_hglrc:
+ st_destroy_context(ctx->st);
+ goto no_pipe; /* st_context_destroy already destroys pipe */
+no_st_ctx:
+ pipe->destroy( pipe );
+no_pipe:
+ FREE(ctx);
+no_ctx:
+ return 0;
+}
+
+BOOL
+stw_delete_context(
+ UINT_PTR hglrc )
+{
+ struct stw_context *ctx ;
+ BOOL ret = FALSE;
+
+ if (!stw_dev)
+ return FALSE;
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+ ctx = stw_lookup_context_locked(hglrc);
+ handle_table_remove(stw_dev->ctx_table, hglrc);
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+
+ if (ctx) {
+ struct stw_context *curctx = stw_current_context();
+
+ /* Unbind current if deleting current context. */
+ if (curctx == ctx)
+ st_make_current( NULL, NULL, NULL );
+
+ st_destroy_context(ctx->st);
+ FREE(ctx);
+
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+BOOL
+stw_release_context(
+ UINT_PTR hglrc )
+{
+ struct stw_context *ctx;
+
+ if (!stw_dev)
+ return FALSE;
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+ ctx = stw_lookup_context_locked( hglrc );
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+
+ if (!ctx)
+ return FALSE;
+
+ /* The expectation is that ctx is the same context which is
+ * current for this thread. We should check that and return False
+ * if not the case.
+ */
+ if (ctx != stw_current_context())
+ return FALSE;
+
+ if (stw_make_current( NULL, 0 ) == FALSE)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+UINT_PTR
+stw_get_current_context( void )
+{
+ struct stw_context *ctx;
+
+ ctx = stw_current_context();
+ if(!ctx)
+ return 0;
+
+ return ctx->hglrc;
+}
+
+HDC
+stw_get_current_dc( void )
+{
+ struct stw_context *ctx;
+
+ ctx = stw_current_context();
+ if(!ctx)
+ return NULL;
+
+ return ctx->hdc;
+}
+
+BOOL
+stw_make_current(
+ HDC hdc,
+ UINT_PTR hglrc )
+{
+ struct stw_context *curctx = NULL;
+ struct stw_context *ctx = NULL;
+ struct stw_framebuffer *fb = NULL;
+
+ if (!stw_dev)
+ goto fail;
+
+ curctx = stw_current_context();
+ if (curctx != NULL) {
+ if (curctx->hglrc != hglrc)
+ st_flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* Return if already current. */
+ if (curctx->hglrc == hglrc && curctx->hdc == hdc) {
+ ctx = curctx;
+ fb = stw_framebuffer_from_hdc( hdc );
+ goto success;
+ }
+ }
+
+ if (hdc == NULL || hglrc == 0) {
+ return st_make_current( NULL, NULL, NULL );
+ }
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+ ctx = stw_lookup_context_locked( hglrc );
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+ if(!ctx)
+ goto fail;
+
+ fb = stw_framebuffer_from_hdc( hdc );
+ if(!fb) {
+ /* Applications should call SetPixelFormat before creating a context,
+ * but not all do, and the opengl32 runtime seems to use a default pixel
+ * format in some cases, so we must create a framebuffer for those here
+ */
+ int iPixelFormat = GetPixelFormat(hdc);
+ if(iPixelFormat)
+ fb = stw_framebuffer_create( hdc, iPixelFormat );
+ if(!fb)
+ goto fail;
+ }
+
+ if(fb->iPixelFormat != ctx->iPixelFormat)
+ goto fail;
+
+ /* Lazy allocation of the frame buffer */
+ if(!stw_framebuffer_allocate(fb))
+ goto fail;
+
+ /* Bind the new framebuffer */
+ ctx->hdc = hdc;
+
+ /* pass to stw_flush_frontbuffer as context_private */
+ ctx->st->pipe->priv = hdc;
+
+ if(!st_make_current( ctx->st, fb->stfb, fb->stfb ))
+ goto fail;
+
+success:
+ assert(fb);
+ if(fb) {
+ stw_framebuffer_update(fb);
+ stw_framebuffer_release(fb);
+ }
+
+ return TRUE;
+
+fail:
+ if(fb)
+ stw_framebuffer_release(fb);
+ st_make_current( NULL, NULL, NULL );
+ return FALSE;
+}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_context.h b/src/gallium/state_trackers/wgl/shared/stw_context.h
new file mode 100644
index 0000000000..166471de5e
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_context.h
@@ -0,0 +1,43 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_CONTEXT_H
+#define STW_CONTEXT_H
+
+#include <windows.h>
+
+struct st_context;
+
+struct stw_context
+{
+ struct st_context *st;
+ UINT_PTR hglrc;
+ int iPixelFormat;
+ HDC hdc;
+};
+
+#endif /* STW_CONTEXT_H */
diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.c b/src/gallium/state_trackers/wgl/shared/stw_device.c
new file mode 100644
index 0000000000..0b6954915a
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_device.c
@@ -0,0 +1,225 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+
+#include "glapi/glthread.h"
+#include "util/u_debug.h"
+#include "pipe/p_screen.h"
+#include "state_tracker/st_public.h"
+
+#ifdef DEBUG
+#include "trace/tr_screen.h"
+#include "trace/tr_texture.h"
+#endif
+
+#include "shared/stw_device.h"
+#include "shared/stw_winsys.h"
+#include "shared/stw_pixelformat.h"
+#include "shared/stw_public.h"
+#include "shared/stw_tls.h"
+#include "shared/stw_framebuffer.h"
+
+#ifdef WIN32_THREADS
+extern _glthread_Mutex OneTimeLock;
+extern void FreeAllTSD(void);
+#endif
+
+
+struct stw_device *stw_dev = NULL;
+
+
+/**
+ * XXX: Dispatch pipe_screen::flush_front_buffer to our
+ * stw_winsys::flush_front_buffer.
+ */
+static void
+stw_flush_frontbuffer(struct pipe_screen *screen,
+ struct pipe_surface *surface,
+ void *context_private )
+{
+ const struct stw_winsys *stw_winsys = stw_dev->stw_winsys;
+ HDC hdc = (HDC)context_private;
+ struct stw_framebuffer *fb;
+
+ fb = stw_framebuffer_from_hdc( hdc );
+ /* fb can be NULL if window was destroyed already */
+ if (fb) {
+#if DEBUG
+ {
+ struct pipe_surface *surface2;
+
+ if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_FRONT_LEFT, &surface2 ))
+ assert(0);
+ else
+ assert(surface2 == surface);
+ }
+#endif
+
+#ifdef DEBUG
+ if(stw_dev->trace_running) {
+ screen = trace_screen(screen)->screen;
+ surface = trace_surface(surface)->surface;
+ }
+#endif
+ }
+
+ stw_winsys->flush_frontbuffer(screen, surface, hdc);
+
+ if(fb) {
+ stw_framebuffer_update(fb);
+ stw_framebuffer_release(fb);
+ }
+}
+
+
+boolean
+stw_init(const struct stw_winsys *stw_winsys)
+{
+ static struct stw_device stw_dev_storage;
+ struct pipe_screen *screen;
+
+ debug_printf("%s\n", __FUNCTION__);
+
+ assert(!stw_dev);
+
+ stw_tls_init();
+
+ stw_dev = &stw_dev_storage;
+ memset(stw_dev, 0, sizeof(*stw_dev));
+
+#ifdef DEBUG
+ stw_dev->memdbg_no = debug_memory_begin();
+#endif
+
+ stw_dev->stw_winsys = stw_winsys;
+
+#ifdef WIN32_THREADS
+ _glthread_INIT_MUTEX(OneTimeLock);
+#endif
+
+ screen = stw_winsys->create_screen();
+ if(!screen)
+ goto error1;
+
+#ifdef DEBUG
+ stw_dev->screen = trace_screen_create(screen);
+ stw_dev->trace_running = stw_dev->screen != screen ? TRUE : FALSE;
+#else
+ stw_dev->screen = screen;
+#endif
+
+ stw_dev->screen->flush_frontbuffer = &stw_flush_frontbuffer;
+
+ pipe_mutex_init( stw_dev->ctx_mutex );
+ pipe_mutex_init( stw_dev->fb_mutex );
+
+ stw_dev->ctx_table = handle_table_create();
+ if (!stw_dev->ctx_table) {
+ goto error1;
+ }
+
+ stw_pixelformat_init();
+
+ return TRUE;
+
+error1:
+ stw_dev = NULL;
+ return FALSE;
+}
+
+
+boolean
+stw_init_thread(void)
+{
+ return stw_tls_init_thread();
+}
+
+
+void
+stw_cleanup_thread(void)
+{
+ stw_tls_cleanup_thread();
+}
+
+
+void
+stw_cleanup(void)
+{
+ unsigned i;
+
+ debug_printf("%s\n", __FUNCTION__);
+
+ if (!stw_dev)
+ return;
+
+ pipe_mutex_lock( stw_dev->ctx_mutex );
+ {
+ /* Ensure all contexts are destroyed */
+ i = handle_table_get_first_handle(stw_dev->ctx_table);
+ while (i) {
+ stw_delete_context(i);
+ i = handle_table_get_next_handle(stw_dev->ctx_table, i);
+ }
+ handle_table_destroy(stw_dev->ctx_table);
+ }
+ pipe_mutex_unlock( stw_dev->ctx_mutex );
+
+ stw_framebuffer_cleanup();
+
+ pipe_mutex_destroy( stw_dev->fb_mutex );
+ pipe_mutex_destroy( stw_dev->ctx_mutex );
+
+ stw_dev->screen->destroy(stw_dev->screen);
+
+#ifdef WIN32_THREADS
+ _glthread_DESTROY_MUTEX(OneTimeLock);
+ FreeAllTSD();
+#endif
+
+#ifdef DEBUG
+ debug_memory_end(stw_dev->memdbg_no);
+#endif
+
+ stw_tls_cleanup();
+
+ stw_dev = NULL;
+}
+
+
+struct stw_context *
+stw_lookup_context_locked( UINT_PTR dhglrc )
+{
+ if (dhglrc == 0)
+ return NULL;
+
+ if (stw_dev == NULL)
+ return NULL;
+
+ return (struct stw_context *) handle_table_get(stw_dev->ctx_table, dhglrc);
+}
+
diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.h b/src/gallium/state_trackers/wgl/shared/stw_device.h
new file mode 100644
index 0000000000..e1bb9518dd
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_device.h
@@ -0,0 +1,77 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_DEVICE_H_
+#define STW_DEVICE_H_
+
+
+#include <windows.h>
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_thread.h"
+#include "util/u_handle_table.h"
+#include "stw_pixelformat.h"
+
+
+#define STW_MAX_PIXELFORMATS 256
+
+
+struct pipe_screen;
+struct stw_framebuffer;
+
+struct stw_device
+{
+ const struct stw_winsys *stw_winsys;
+
+ struct pipe_screen *screen;
+
+#ifdef DEBUG
+ boolean trace_running;
+#endif
+
+ struct stw_pixelformat_info pixelformats[STW_MAX_PIXELFORMATS];
+ unsigned pixelformat_count;
+ unsigned pixelformat_extended_count;
+
+ pipe_mutex ctx_mutex;
+ struct handle_table *ctx_table;
+
+ pipe_mutex fb_mutex;
+ struct stw_framebuffer *fb_head;
+
+#ifdef DEBUG
+ unsigned long memdbg_no;
+#endif
+};
+
+struct stw_context *
+stw_lookup_context_locked( UINT_PTR hglrc );
+
+extern struct stw_device *stw_dev;
+
+
+#endif /* STW_DEVICE_H_ */
diff --git a/src/gallium/state_trackers/wgl/shared/stw_extensionsstring.c b/src/gallium/state_trackers/wgl/shared/stw_extensionsstring.c
new file mode 100644
index 0000000000..62c859e1f9
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_extensionsstring.c
@@ -0,0 +1,59 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+
+#define WGL_WGLEXT_PROTOTYPES
+
+#include <GL/gl.h>
+#include <GL/wglext.h>
+
+
+static const char *stw_extension_string =
+ "WGL_ARB_extensions_string "
+ "WGL_ARB_multisample "
+ "WGL_ARB_pixel_format "
+/* "WGL_EXT_swap_interval " */
+ "WGL_EXT_extensions_string";
+
+
+WINGDIAPI const char * APIENTRY
+wglGetExtensionsStringARB(
+ HDC hdc )
+{
+ (void) hdc;
+
+ return stw_extension_string;
+}
+
+
+WINGDIAPI const char * APIENTRY
+wglGetExtensionsStringEXT( void )
+{
+ return stw_extension_string;
+}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_extgallium.c b/src/gallium/state_trackers/wgl/shared/stw_extgallium.c
new file mode 100644
index 0000000000..fc22737d7e
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_extgallium.c
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_screen.h"
+#include "stw_public.h"
+#include "stw_device.h"
+#include "stw_winsys.h"
+
+#ifdef DEBUG
+#include "trace/tr_screen.h"
+#include "trace/tr_context.h"
+#endif
+
+
+struct pipe_screen * APIENTRY
+wglGetGalliumScreenMESA(void)
+{
+ return stw_dev ? stw_dev->screen : NULL;
+}
+
+
+/* XXX: Unify with stw_create_layer_context */
+struct pipe_context * APIENTRY
+wglCreateGalliumContextMESA(void)
+{
+ struct pipe_screen *screen = NULL;
+ struct pipe_context *pipe = NULL;
+
+ if(!stw_dev)
+ return NULL;
+
+ screen = stw_dev->screen;
+
+#ifdef DEBUG
+ /* Unwrap screen */
+ if(stw_dev->trace_running)
+ screen = trace_screen(screen)->screen;
+#endif
+
+ pipe = stw_dev->stw_winsys->create_context( screen );
+ if (pipe == NULL)
+ goto no_pipe;
+
+#ifdef DEBUG
+ /* Wrap context */
+ if(stw_dev->trace_running)
+ pipe = trace_context_create(stw_dev->screen, pipe);
+#endif
+
+ return pipe;
+
+no_pipe:
+ return NULL;
+}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_extgallium.h b/src/gallium/state_trackers/wgl/shared/stw_extgallium.h
new file mode 100644
index 0000000000..cc35f2bb7f
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_extgallium.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_EXTGALLIUM_H_
+#define STW_EXTGALLIUM_H_
+
+
+#include <windows.h>
+
+
+struct pipe_screen;
+struct pipe_context;
+
+
+struct pipe_screen * APIENTRY
+wglGetGalliumScreenMESA(void);
+
+
+struct pipe_context * APIENTRY
+wglCreateGalliumContextMESA(void);
+
+
+#endif /* STW_EXTGALLIUM_H_ */
diff --git a/src/gallium/state_trackers/wgl/shared/stw_extswapinterval.c b/src/gallium/state_trackers/wgl/shared/stw_extswapinterval.c
new file mode 100644
index 0000000000..9eac6a1d09
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_extswapinterval.c
@@ -0,0 +1,57 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+
+#define WGL_WGLEXT_PROTOTYPES
+
+#include <GL/gl.h>
+#include <GL/wglext.h>
+#include "util/u_debug.h"
+
+/* A dummy implementation of this extension.
+ *
+ * Required as some applications retrieve and call these functions
+ * regardless of the fact that we don't advertise the extension and
+ * further more the results of wglGetProcAddress are NULL.
+ */
+WINGDIAPI BOOL APIENTRY
+wglSwapIntervalEXT(int interval)
+{
+ (void) interval;
+ debug_printf("%s: %d\n", __FUNCTION__, interval);
+ return TRUE;
+}
+
+WINGDIAPI int APIENTRY
+wglGetSwapIntervalEXT(void)
+{
+ return 0;
+}
+
+
diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c
new file mode 100644
index 0000000000..b8956bb550
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c
@@ -0,0 +1,493 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+
+#include "main/context.h"
+#include "pipe/p_format.h"
+#include "pipe/p_screen.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_public.h"
+
+#ifdef DEBUG
+#include "trace/tr_screen.h"
+#include "trace/tr_texture.h"
+#endif
+
+#include "stw_framebuffer.h"
+#include "stw_device.h"
+#include "stw_public.h"
+#include "stw_winsys.h"
+#include "stw_tls.h"
+
+
+/**
+ * Search the framebuffer with the matching HWND while holding the
+ * stw_dev::fb_mutex global lock.
+ */
+static INLINE struct stw_framebuffer *
+stw_framebuffer_from_hwnd_locked(
+ HWND hwnd )
+{
+ struct stw_framebuffer *fb;
+
+ for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next)
+ if (fb->hWnd == hwnd) {
+ pipe_mutex_lock(fb->mutex);
+ break;
+ }
+
+ return fb;
+}
+
+
+/**
+ * Destroy this framebuffer. Both stw_dev::fb_mutex and stw_framebuffer::mutex
+ * must be held, by this order. Obviously no further access to fb can be done
+ * after this.
+ */
+static INLINE void
+stw_framebuffer_destroy_locked(
+ struct stw_framebuffer *fb )
+{
+ struct stw_framebuffer **link;
+
+ link = &stw_dev->fb_head;
+ while (*link != fb)
+ link = &(*link)->next;
+ assert(*link);
+ *link = fb->next;
+ fb->next = NULL;
+
+ st_unreference_framebuffer(fb->stfb);
+
+ pipe_mutex_unlock( fb->mutex );
+
+ pipe_mutex_destroy( fb->mutex );
+
+ FREE( fb );
+}
+
+
+void
+stw_framebuffer_release(
+ struct stw_framebuffer *fb)
+{
+ assert(fb);
+ pipe_mutex_unlock( fb->mutex );
+}
+
+
+static INLINE void
+stw_framebuffer_get_size( struct stw_framebuffer *fb )
+{
+ unsigned width, height;
+ RECT rect;
+
+ assert(fb->hWnd);
+
+ GetClientRect( fb->hWnd, &rect );
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+
+ if(width < 1)
+ width = 1;
+ if(height < 1)
+ height = 1;
+
+ if(width != fb->width || height != fb->height) {
+ fb->must_resize = TRUE;
+ fb->width = width;
+ fb->height = height;
+ }
+}
+
+
+/**
+ * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx
+ * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
+ */
+LRESULT CALLBACK
+stw_call_window_proc(
+ int nCode,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ struct stw_tls_data *tls_data;
+ PCWPSTRUCT pParams = (PCWPSTRUCT)lParam;
+ struct stw_framebuffer *fb;
+
+ tls_data = stw_tls_get_data();
+ if(!tls_data)
+ return 0;
+
+ if (nCode < 0)
+ return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
+
+ if (pParams->message == WM_WINDOWPOSCHANGED) {
+ /* We handle WM_WINDOWPOSCHANGED instead of WM_SIZE because according to
+ * http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx
+ * WM_SIZE is generated from WM_WINDOWPOSCHANGED by DefWindowProc so it
+ * can be masked out by the application. */
+ LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam;
+ if((lpWindowPos->flags & SWP_SHOWWINDOW) ||
+ !(lpWindowPos->flags & SWP_NOSIZE)) {
+ fb = stw_framebuffer_from_hwnd( pParams->hwnd );
+ if(fb) {
+ /* Size in WINDOWPOS includes the window frame, so get the size
+ * of the client area via GetClientRect. */
+ stw_framebuffer_get_size(fb);
+ stw_framebuffer_release(fb);
+ }
+ }
+ }
+ else if (pParams->message == WM_DESTROY) {
+ pipe_mutex_lock( stw_dev->fb_mutex );
+ fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
+ if(fb)
+ stw_framebuffer_destroy_locked(fb);
+ pipe_mutex_unlock( stw_dev->fb_mutex );
+ }
+
+ return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
+}
+
+
+struct stw_framebuffer *
+stw_framebuffer_create(
+ HDC hdc,
+ int iPixelFormat )
+{
+ HWND hWnd;
+ struct stw_framebuffer *fb;
+ const struct stw_pixelformat_info *pfi;
+
+ /* We only support drawing to a window. */
+ hWnd = WindowFromDC( hdc );
+ if(!hWnd)
+ return NULL;
+
+ fb = CALLOC_STRUCT( stw_framebuffer );
+ if (fb == NULL)
+ return NULL;
+
+ fb->hDC = hdc;
+ fb->hWnd = hWnd;
+ fb->iPixelFormat = iPixelFormat;
+
+ fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
+
+ stw_pixelformat_visual(&fb->visual, pfi);
+
+ stw_framebuffer_get_size(fb);
+
+ pipe_mutex_init( fb->mutex );
+
+ /* This is the only case where we lock the stw_framebuffer::mutex before
+ * stw_dev::fb_mutex, since no other thread can know about this framebuffer
+ * and we must prevent any other thread from destroying it before we return.
+ */
+ pipe_mutex_lock( fb->mutex );
+
+ pipe_mutex_lock( stw_dev->fb_mutex );
+ fb->next = stw_dev->fb_head;
+ stw_dev->fb_head = fb;
+ pipe_mutex_unlock( stw_dev->fb_mutex );
+
+ return fb;
+}
+
+
+BOOL
+stw_framebuffer_allocate(
+ struct stw_framebuffer *fb)
+{
+ assert(fb);
+
+ if(!fb->stfb) {
+ const struct stw_pixelformat_info *pfi = fb->pfi;
+ enum pipe_format colorFormat, depthFormat, stencilFormat;
+
+ colorFormat = pfi->color_format;
+
+ assert(pf_layout( pfi->depth_stencil_format ) == PIPE_FORMAT_LAYOUT_RGBAZS );
+
+ if(pf_get_component_bits( pfi->depth_stencil_format, PIPE_FORMAT_COMP_Z ))
+ depthFormat = pfi->depth_stencil_format;
+ else
+ depthFormat = PIPE_FORMAT_NONE;
+
+ if(pf_get_component_bits( pfi->depth_stencil_format, PIPE_FORMAT_COMP_S ))
+ stencilFormat = pfi->depth_stencil_format;
+ else
+ stencilFormat = PIPE_FORMAT_NONE;
+
+ assert(fb->must_resize);
+ assert(fb->width);
+ assert(fb->height);
+
+ fb->stfb = st_create_framebuffer(
+ &fb->visual,
+ colorFormat,
+ depthFormat,
+ stencilFormat,
+ fb->width,
+ fb->height,
+ (void *) fb );
+
+ // to notify the context
+ fb->must_resize = TRUE;
+ }
+
+ return fb->stfb ? TRUE : FALSE;
+}
+
+
+/**
+ * Update the framebuffer's size if necessary.
+ */
+void
+stw_framebuffer_update(
+ struct stw_framebuffer *fb)
+{
+ assert(fb->stfb);
+ assert(fb->height);
+ assert(fb->width);
+
+ /* XXX: It would be nice to avoid checking the size again -- in theory
+ * stw_call_window_proc would have cought the resize and stored the right
+ * size already, but unfortunately threads created before the DllMain is
+ * called don't get a DLL_THREAD_ATTACH notification, and there is no way
+ * to know of their existing without using the not very portable PSAPI.
+ */
+ stw_framebuffer_get_size(fb);
+
+ if(fb->must_resize) {
+ st_resize_framebuffer(fb->stfb, fb->width, fb->height);
+ fb->must_resize = FALSE;
+ }
+}
+
+
+void
+stw_framebuffer_cleanup( void )
+{
+ struct stw_framebuffer *fb;
+ struct stw_framebuffer *next;
+
+ pipe_mutex_lock( stw_dev->fb_mutex );
+
+ fb = stw_dev->fb_head;
+ while (fb) {
+ next = fb->next;
+
+ pipe_mutex_lock(fb->mutex);
+ stw_framebuffer_destroy_locked(fb);
+
+ fb = next;
+ }
+ stw_dev->fb_head = NULL;
+
+ pipe_mutex_unlock( stw_dev->fb_mutex );
+}
+
+
+/**
+ * Given an hdc, return the corresponding stw_framebuffer.
+ */
+static INLINE struct stw_framebuffer *
+stw_framebuffer_from_hdc_locked(
+ HDC hdc )
+{
+ HWND hwnd;
+ struct stw_framebuffer *fb;
+
+ /*
+ * Some applications create and use several HDCs for the same window, so
+ * looking up the framebuffer by the HDC is not reliable. Use HWND whenever
+ * possible.
+ */
+ hwnd = WindowFromDC(hdc);
+ if(hwnd)
+ return stw_framebuffer_from_hwnd_locked(hwnd);
+
+ for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next)
+ if (fb->hDC == hdc) {
+ pipe_mutex_lock(fb->mutex);
+ break;
+ }
+
+ return fb;
+}
+
+
+/**
+ * Given an hdc, return the corresponding stw_framebuffer.
+ */
+struct stw_framebuffer *
+stw_framebuffer_from_hdc(
+ HDC hdc )
+{
+ struct stw_framebuffer *fb;
+
+ pipe_mutex_lock( stw_dev->fb_mutex );
+ fb = stw_framebuffer_from_hdc_locked(hdc);
+ pipe_mutex_unlock( stw_dev->fb_mutex );
+
+ return fb;
+}
+
+
+/**
+ * Given an hdc, return the corresponding stw_framebuffer.
+ */
+struct stw_framebuffer *
+stw_framebuffer_from_hwnd(
+ HWND hwnd )
+{
+ struct stw_framebuffer *fb;
+
+ pipe_mutex_lock( stw_dev->fb_mutex );
+ fb = stw_framebuffer_from_hwnd_locked(hwnd);
+ pipe_mutex_unlock( stw_dev->fb_mutex );
+
+ return fb;
+}
+
+
+BOOL
+stw_pixelformat_set(
+ HDC hdc,
+ int iPixelFormat )
+{
+ uint count;
+ uint index;
+ struct stw_framebuffer *fb;
+
+ index = (uint) iPixelFormat - 1;
+ count = stw_pixelformat_get_extended_count();
+ if (index >= count)
+ return FALSE;
+
+ fb = stw_framebuffer_from_hdc_locked(hdc);
+ if(fb) {
+ /* SetPixelFormat must be called only once */
+ stw_framebuffer_release( fb );
+ return FALSE;
+ }
+
+ fb = stw_framebuffer_create(hdc, iPixelFormat);
+ if(!fb) {
+ return FALSE;
+ }
+
+ stw_framebuffer_release( fb );
+
+ /* Some applications mistakenly use the undocumented wglSetPixelFormat
+ * function instead of SetPixelFormat, so we call SetPixelFormat here to
+ * avoid opengl32.dll's wglCreateContext to fail */
+ if (GetPixelFormat(hdc) == 0) {
+ SetPixelFormat(hdc, iPixelFormat, NULL);
+ }
+
+ return TRUE;
+}
+
+
+int
+stw_pixelformat_get(
+ HDC hdc )
+{
+ int iPixelFormat = 0;
+ struct stw_framebuffer *fb;
+
+ fb = stw_framebuffer_from_hdc(hdc);
+ if(fb) {
+ iPixelFormat = fb->iPixelFormat;
+ stw_framebuffer_release(fb);
+ }
+
+ return iPixelFormat;
+}
+
+
+BOOL
+stw_swap_buffers(
+ HDC hdc )
+{
+ struct stw_framebuffer *fb;
+ struct pipe_screen *screen;
+ struct pipe_surface *surface;
+
+ fb = stw_framebuffer_from_hdc( hdc );
+ if (fb == NULL)
+ return FALSE;
+
+ if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) {
+ stw_framebuffer_release(fb);
+ return TRUE;
+ }
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+ st_notify_swapbuffers( fb->stfb );
+
+ screen = stw_dev->screen;
+
+ if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_BACK_LEFT, &surface )) {
+ /* FIXME: this shouldn't happen, but does on glean */
+ stw_framebuffer_release(fb);
+ return FALSE;
+ }
+
+#ifdef DEBUG
+ if(stw_dev->trace_running) {
+ screen = trace_screen(screen)->screen;
+ surface = trace_surface(surface)->surface;
+ }
+#endif
+
+ stw_dev->stw_winsys->flush_frontbuffer( screen, surface, hdc );
+
+ stw_framebuffer_update(fb);
+ stw_framebuffer_release(fb);
+
+ return TRUE;
+}
+
+
+BOOL
+stw_swap_layer_buffers(
+ HDC hdc,
+ UINT fuPlanes )
+{
+ if(fuPlanes & WGL_SWAP_MAIN_PLANE)
+ return stw_swap_buffers(hdc);
+
+ return FALSE;
+}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h
new file mode 100644
index 0000000000..13d29f37e4
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h
@@ -0,0 +1,148 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_FRAMEBUFFER_H
+#define STW_FRAMEBUFFER_H
+
+#include <windows.h>
+
+#include "main/mtypes.h"
+
+#include "pipe/p_thread.h"
+
+struct stw_pixelformat_info;
+
+/**
+ * Windows framebuffer, derived from gl_framebuffer.
+ */
+struct stw_framebuffer
+{
+ /**
+ * This mutex has two purposes:
+ * - protect the access to the mutable data members below
+ * - prevent the the framebuffer from being deleted while being accessed.
+ *
+ * It is OK to lock this mutex while holding the stw_device::fb_mutex lock,
+ * but the opposite must never happen.
+ */
+ pipe_mutex mutex;
+
+ /*
+ * Immutable members.
+ *
+ * Note that even access to immutable members implies acquiring the mutex
+ * above, to prevent the framebuffer from being destroyed.
+ */
+
+ HDC hDC;
+ HWND hWnd;
+
+ int iPixelFormat;
+ const struct stw_pixelformat_info *pfi;
+ GLvisual visual;
+
+ /*
+ * Mutable members.
+ */
+
+ struct st_framebuffer *stfb;
+
+ /* FIXME: Make this work for multiple contexts bound to the same framebuffer */
+ boolean must_resize;
+ unsigned width;
+ unsigned height;
+
+ /**
+ * This is protected by stw_device::fb_mutex, not the mutex above.
+ *
+ * Deletions must be done by first acquiring stw_device::fb_mutex, and then
+ * acquiring the stw_framebuffer::mutex of the framebuffer to be deleted.
+ * This ensures that nobody else is reading/writing to the.
+ *
+ * It is not necessary to aquire the mutex above to navigate the linked list
+ * given that deletions are done with stw_device::fb_mutex held, so no other
+ * thread can delete.
+ */
+ struct stw_framebuffer *next;
+};
+
+
+/**
+ * Create a new framebuffer object which will correspond to the given HDC.
+ *
+ * This function will acquire stw_framebuffer::mutex. stw_framebuffer_release
+ * must be called when done
+ */
+struct stw_framebuffer *
+stw_framebuffer_create(
+ HDC hdc,
+ int iPixelFormat );
+
+/**
+ * Search a framebuffer with a matching HWND.
+ *
+ * This function will acquire stw_framebuffer::mutex. stw_framebuffer_release
+ * must be called when done
+ */
+struct stw_framebuffer *
+stw_framebuffer_from_hwnd(
+ HWND hwnd );
+
+/**
+ * Search a framebuffer with a matching HDC.
+ *
+ * This function will acquire stw_framebuffer::mutex. stw_framebuffer_release
+ * must be called when done
+ */
+struct stw_framebuffer *
+stw_framebuffer_from_hdc(
+ HDC hdc );
+
+BOOL
+stw_framebuffer_allocate(
+ struct stw_framebuffer *fb );
+
+void
+stw_framebuffer_update(
+ struct stw_framebuffer *fb);
+
+/**
+ * Release stw_framebuffer::mutex lock. This framebuffer must not be accessed
+ * after calling this function, as it may have been deleted by another thread
+ * in the meanwhile.
+ */
+void
+stw_framebuffer_release(
+ struct stw_framebuffer *fb);
+
+/**
+ * Cleanup any existing framebuffers when exiting application.
+ */
+void
+stw_framebuffer_cleanup(void);
+
+#endif /* STW_FRAMEBUFFER_H */
diff --git a/src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c b/src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c
new file mode 100644
index 0000000000..879ced925a
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c
@@ -0,0 +1,86 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+
+#define WGL_WGLEXT_PROTOTYPES
+
+#include <GL/gl.h>
+#include <GL/wglext.h>
+
+#include "glapi/glapi.h"
+#include "stw_public.h"
+#include "stw_extgallium.h"
+
+struct stw_extension_entry
+{
+ const char *name;
+ PROC proc;
+};
+
+#define STW_EXTENSION_ENTRY(P) { #P, (PROC) P }
+
+static const struct stw_extension_entry stw_extension_entries[] = {
+
+ /* WGL_ARB_extensions_string */
+ STW_EXTENSION_ENTRY( wglGetExtensionsStringARB ),
+
+ /* WGL_ARB_pixel_format */
+ STW_EXTENSION_ENTRY( wglChoosePixelFormatARB ),
+ STW_EXTENSION_ENTRY( wglGetPixelFormatAttribfvARB ),
+ STW_EXTENSION_ENTRY( wglGetPixelFormatAttribivARB ),
+
+ /* WGL_EXT_extensions_string */
+ STW_EXTENSION_ENTRY( wglGetExtensionsStringEXT ),
+
+ /* WGL_EXT_swap_interval */
+ STW_EXTENSION_ENTRY( wglGetSwapIntervalEXT ),
+ STW_EXTENSION_ENTRY( wglSwapIntervalEXT ),
+
+ /* WGL_EXT_gallium ? */
+ STW_EXTENSION_ENTRY( wglGetGalliumScreenMESA ),
+ STW_EXTENSION_ENTRY( wglCreateGalliumContextMESA ),
+
+ { NULL, NULL }
+};
+
+PROC
+stw_get_proc_address(
+ LPCSTR lpszProc )
+{
+ const struct stw_extension_entry *entry;
+
+ if (lpszProc[0] == 'w' && lpszProc[1] == 'g' && lpszProc[2] == 'l')
+ for (entry = stw_extension_entries; entry->name; entry++)
+ if (strcmp( lpszProc, entry->name ) == 0)
+ return entry->proc;
+
+ if (lpszProc[0] == 'g' && lpszProc[1] == 'l')
+ return (PROC) _glapi_get_proc_address( lpszProc );
+
+ return NULL;
+}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c
new file mode 100644
index 0000000000..c296744838
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c
@@ -0,0 +1,370 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/mtypes.h"
+#include "main/context.h"
+
+#include "pipe/p_format.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+
+#include "util/u_debug.h"
+
+#include "stw_device.h"
+#include "stw_pixelformat.h"
+#include "stw_public.h"
+#include "stw_tls.h"
+
+
+struct stw_pf_color_info
+{
+ enum pipe_format format;
+ struct {
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ unsigned char alpha;
+ } bits;
+ struct {
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ unsigned char alpha;
+ } shift;
+};
+
+struct stw_pf_depth_info
+{
+ enum pipe_format format;
+ struct {
+ unsigned char depth;
+ unsigned char stencil;
+ } bits;
+};
+
+
+/* NOTE: order matters, since in otherwise equal circumstances the first
+ * format listed will get chosen */
+
+static const struct stw_pf_color_info
+stw_pf_color[] = {
+ /* no-alpha */
+ { PIPE_FORMAT_X8R8G8B8_UNORM, { 8, 8, 8, 0}, {16, 8, 0, 0} },
+ { PIPE_FORMAT_B8G8R8X8_UNORM, { 8, 8, 8, 0}, { 8, 16, 24, 0} },
+ { PIPE_FORMAT_R5G6B5_UNORM, { 5, 6, 5, 0}, {11, 5, 0, 0} },
+ /* alpha */
+ { PIPE_FORMAT_A8R8G8B8_UNORM, { 8, 8, 8, 8}, {16, 8, 0, 24} },
+ { PIPE_FORMAT_B8G8R8A8_UNORM, { 8, 8, 8, 8}, { 8, 16, 24, 0} },
+#if 0
+ { PIPE_FORMAT_A2B10G10R10_UNORM, {10, 10, 10, 2}, { 0, 10, 20, 30} },
+#endif
+ { PIPE_FORMAT_A1R5G5B5_UNORM, { 5, 5, 5, 1}, {10, 5, 0, 15} },
+ { PIPE_FORMAT_A4R4G4B4_UNORM, { 4, 4, 4, 4}, {16, 4, 0, 12} }
+};
+
+
+static const struct stw_pf_depth_info
+stw_pf_depth_stencil[] = {
+ /* pure depth */
+ { PIPE_FORMAT_Z32_UNORM, {32, 0} },
+ { PIPE_FORMAT_Z24X8_UNORM, {24, 0} },
+ { PIPE_FORMAT_X8Z24_UNORM, {24, 0} },
+ { PIPE_FORMAT_Z16_UNORM, {16, 0} },
+ /* pure stencil */
+ { PIPE_FORMAT_S8_UNORM, { 0, 8} },
+ /* combined depth-stencil */
+ { PIPE_FORMAT_S8Z24_UNORM, {24, 8} },
+ { PIPE_FORMAT_Z24S8_UNORM, {24, 8} }
+};
+
+
+static const boolean
+stw_pf_doublebuffer[] = {
+ FALSE,
+ TRUE,
+};
+
+
+const unsigned
+stw_pf_multisample[] = {
+ 0,
+ 4
+};
+
+
+static void
+stw_pixelformat_add(
+ struct stw_device *stw_dev,
+ const struct stw_pf_color_info *color,
+ const struct stw_pf_depth_info *depth,
+ unsigned accum,
+ boolean doublebuffer,
+ unsigned samples )
+{
+ boolean extended = FALSE;
+ struct stw_pixelformat_info *pfi;
+
+ assert(stw_dev->pixelformat_extended_count < STW_MAX_PIXELFORMATS);
+ if(stw_dev->pixelformat_extended_count >= STW_MAX_PIXELFORMATS)
+ return;
+
+ assert(pf_layout( color->format ) == PIPE_FORMAT_LAYOUT_RGBAZS );
+ assert(pf_get_component_bits( color->format, PIPE_FORMAT_COMP_R ) == color->bits.red );
+ assert(pf_get_component_bits( color->format, PIPE_FORMAT_COMP_G ) == color->bits.green );
+ assert(pf_get_component_bits( color->format, PIPE_FORMAT_COMP_B ) == color->bits.blue );
+ assert(pf_get_component_bits( color->format, PIPE_FORMAT_COMP_A ) == color->bits.alpha );
+ assert(pf_layout( depth->format ) == PIPE_FORMAT_LAYOUT_RGBAZS );
+ assert(pf_get_component_bits( depth->format, PIPE_FORMAT_COMP_Z ) == depth->bits.depth );
+ assert(pf_get_component_bits( depth->format, PIPE_FORMAT_COMP_S ) == depth->bits.stencil );
+
+ pfi = &stw_dev->pixelformats[stw_dev->pixelformat_extended_count];
+
+ memset(pfi, 0, sizeof *pfi);
+
+ pfi->color_format = color->format;
+ pfi->depth_stencil_format = depth->format;
+
+ pfi->pfd.nSize = sizeof pfi->pfd;
+ pfi->pfd.nVersion = 1;
+
+ pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL;
+
+ /* TODO: also support non-native pixel formats */
+ pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW ;
+
+ if (doublebuffer)
+ pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY;
+
+ pfi->pfd.iPixelType = PFD_TYPE_RGBA;
+
+ pfi->pfd.cColorBits = color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha;
+ pfi->pfd.cRedBits = color->bits.red;
+ pfi->pfd.cRedShift = color->shift.red;
+ pfi->pfd.cGreenBits = color->bits.green;
+ pfi->pfd.cGreenShift = color->shift.green;
+ pfi->pfd.cBlueBits = color->bits.blue;
+ pfi->pfd.cBlueShift = color->shift.blue;
+ pfi->pfd.cAlphaBits = color->bits.alpha;
+ pfi->pfd.cAlphaShift = color->shift.alpha;
+ pfi->pfd.cAccumBits = 4*accum;
+ pfi->pfd.cAccumRedBits = accum;
+ pfi->pfd.cAccumGreenBits = accum;
+ pfi->pfd.cAccumBlueBits = accum;
+ pfi->pfd.cAccumAlphaBits = accum;
+ pfi->pfd.cDepthBits = depth->bits.depth;
+ pfi->pfd.cStencilBits = depth->bits.stencil;
+ pfi->pfd.cAuxBuffers = 0;
+ pfi->pfd.iLayerType = 0;
+ pfi->pfd.bReserved = 0;
+ pfi->pfd.dwLayerMask = 0;
+ pfi->pfd.dwVisibleMask = 0;
+ pfi->pfd.dwDamageMask = 0;
+
+ if(samples) {
+ pfi->numSampleBuffers = 1;
+ pfi->numSamples = samples;
+ extended = TRUE;
+ }
+
+ ++stw_dev->pixelformat_extended_count;
+
+ if(!extended) {
+ ++stw_dev->pixelformat_count;
+ assert(stw_dev->pixelformat_count == stw_dev->pixelformat_extended_count);
+ }
+}
+
+void
+stw_pixelformat_init( void )
+{
+ struct pipe_screen *screen = stw_dev->screen;
+ unsigned i, j, k, l;
+
+ assert( !stw_dev->pixelformat_count );
+ assert( !stw_dev->pixelformat_extended_count );
+
+ for(i = 0; i < Elements(stw_pf_multisample); ++i) {
+ unsigned samples = stw_pf_multisample[i];
+
+ /* FIXME: re-enabled MSAA when we can query it */
+ if(samples)
+ continue;
+
+ for(j = 0; j < Elements(stw_pf_color); ++j) {
+ const struct stw_pf_color_info *color = &stw_pf_color[j];
+
+ if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0))
+ continue;
+
+ for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) {
+ unsigned doublebuffer = stw_pf_doublebuffer[k];
+
+ for(l = 0; l < Elements(stw_pf_depth_stencil); ++l) {
+ const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[l];
+
+ if(!screen->is_format_supported(screen, depth->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0))
+ continue;
+
+ stw_pixelformat_add( stw_dev, color, depth, 0, doublebuffer, samples );
+ stw_pixelformat_add( stw_dev, color, depth, 16, doublebuffer, samples );
+ }
+ }
+ }
+ }
+
+ assert( stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count );
+ assert( stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS );
+}
+
+uint
+stw_pixelformat_get_count( void )
+{
+ return stw_dev->pixelformat_count;
+}
+
+uint
+stw_pixelformat_get_extended_count( void )
+{
+ return stw_dev->pixelformat_extended_count;
+}
+
+const struct stw_pixelformat_info *
+stw_pixelformat_get_info( uint index )
+{
+ assert( index < stw_dev->pixelformat_extended_count );
+
+ return &stw_dev->pixelformats[index];
+}
+
+
+void
+stw_pixelformat_visual(GLvisual *visual,
+ const struct stw_pixelformat_info *pfi )
+{
+ memset(visual, 0, sizeof *visual);
+ _mesa_initialize_visual(
+ visual,
+ (pfi->pfd.iPixelType == PFD_TYPE_RGBA) ? GL_TRUE : GL_FALSE,
+ (pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE,
+ (pfi->pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE,
+ pfi->pfd.cRedBits,
+ pfi->pfd.cGreenBits,
+ pfi->pfd.cBlueBits,
+ pfi->pfd.cAlphaBits,
+ (pfi->pfd.iPixelType == PFD_TYPE_COLORINDEX) ? pfi->pfd.cColorBits : 0,
+ pfi->pfd.cDepthBits,
+ pfi->pfd.cStencilBits,
+ pfi->pfd.cAccumRedBits,
+ pfi->pfd.cAccumGreenBits,
+ pfi->pfd.cAccumBlueBits,
+ pfi->pfd.cAccumAlphaBits,
+ pfi->numSamples );
+}
+
+
+int
+stw_pixelformat_describe(
+ HDC hdc,
+ int iPixelFormat,
+ UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd )
+{
+ uint count;
+ uint index;
+ const struct stw_pixelformat_info *pfi;
+
+ (void) hdc;
+
+ count = stw_pixelformat_get_extended_count();
+ index = (uint) iPixelFormat - 1;
+
+ if (ppfd == NULL)
+ return count;
+ if (index >= count || nBytes != sizeof( PIXELFORMATDESCRIPTOR ))
+ return 0;
+
+ pfi = stw_pixelformat_get_info( index );
+
+ memcpy(ppfd, &pfi->pfd, sizeof( PIXELFORMATDESCRIPTOR ));
+
+ return count;
+}
+
+/* Only used by the wgl code, but have it here to avoid exporting the
+ * pixelformat.h functionality.
+ */
+int stw_pixelformat_choose( HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ uint count;
+ uint index;
+ uint bestindex;
+ uint bestdelta;
+
+ (void) hdc;
+
+ count = stw_pixelformat_get_count();
+ bestindex = count;
+ bestdelta = ~0U;
+
+ for (index = 0; index < count; index++) {
+ uint delta = 0;
+ const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info( index );
+
+ if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
+ !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
+ !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
+ continue;
+
+ /* FIXME: Take in account individual channel bits */
+ if (ppfd->cColorBits != pfi->pfd.cColorBits)
+ delta += 8;
+
+ if (ppfd->cDepthBits != pfi->pfd.cDepthBits)
+ delta += 4;
+
+ if (ppfd->cStencilBits != pfi->pfd.cStencilBits)
+ delta += 2;
+
+ if (ppfd->cAlphaBits != pfi->pfd.cAlphaBits)
+ delta++;
+
+ if (delta < bestdelta) {
+ bestindex = index;
+ bestdelta = delta;
+ if (bestdelta == 0)
+ break;
+ }
+ }
+
+ if (bestindex == count)
+ return 0;
+
+ return bestindex + 1;
+}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.h b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.h
new file mode 100644
index 0000000000..bec429231b
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_PIXELFORMAT_H
+#define STW_PIXELFORMAT_H
+
+#include <windows.h>
+
+#include "main/mtypes.h"
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+
+struct stw_pixelformat_info
+{
+ enum pipe_format color_format;
+ enum pipe_format depth_stencil_format;
+
+ PIXELFORMATDESCRIPTOR pfd;
+
+ unsigned numSampleBuffers;
+ unsigned numSamples;
+};
+
+void
+stw_pixelformat_init( void );
+
+uint
+stw_pixelformat_get_count( void );
+
+uint
+stw_pixelformat_get_extended_count( void );
+
+const struct stw_pixelformat_info *
+stw_pixelformat_get_info( uint index );
+
+void
+stw_pixelformat_visual(GLvisual *visual,
+ const struct stw_pixelformat_info *pfi );
+
+#endif /* STW_PIXELFORMAT_H */
diff --git a/src/gallium/state_trackers/wgl/shared/stw_public.h b/src/gallium/state_trackers/wgl/shared/stw_public.h
new file mode 100644
index 0000000000..7fe9cfb356
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_public.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_PUBLIC_H
+#define STW_PUBLIC_H
+
+#include <windows.h>
+
+BOOL stw_copy_context( UINT_PTR hglrcSrc,
+ UINT_PTR hglrcDst,
+ UINT mask );
+
+UINT_PTR stw_create_layer_context( HDC hdc,
+ int iLayerPlane );
+
+BOOL stw_share_lists( UINT_PTR hglrc1, UINT_PTR hglrc2 );
+
+BOOL stw_delete_context( UINT_PTR hglrc );
+
+BOOL
+stw_release_context( UINT_PTR dhglrc );
+
+UINT_PTR stw_get_current_context( void );
+
+HDC stw_get_current_dc( void );
+
+BOOL stw_make_current( HDC hdc, UINT_PTR hglrc );
+
+BOOL stw_swap_buffers( HDC hdc );
+
+BOOL
+stw_swap_layer_buffers( HDC hdc, UINT fuPlanes );
+
+PROC stw_get_proc_address( LPCSTR lpszProc );
+
+int stw_pixelformat_describe( HDC hdc,
+ int iPixelFormat,
+ UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd );
+
+int stw_pixelformat_get( HDC hdc );
+
+BOOL stw_pixelformat_set( HDC hdc,
+ int iPixelFormat );
+
+int stw_pixelformat_choose( HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd );
+
+#endif
diff --git a/src/gallium/state_trackers/wgl/shared/stw_tls.c b/src/gallium/state_trackers/wgl/shared/stw_tls.c
new file mode 100644
index 0000000000..4bd6a9289c
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_tls.c
@@ -0,0 +1,139 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+
+#include "pipe/p_compiler.h"
+#include "util/u_memory.h"
+#include "stw_tls.h"
+
+static DWORD tlsIndex = TLS_OUT_OF_INDEXES;
+
+boolean
+stw_tls_init(void)
+{
+ tlsIndex = TlsAlloc();
+ if (tlsIndex == TLS_OUT_OF_INDEXES) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static INLINE struct stw_tls_data *
+stw_tls_data_create()
+{
+ struct stw_tls_data *data;
+
+ data = CALLOC_STRUCT(stw_tls_data);
+ if (!data)
+ goto no_data;
+
+ data->hCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC,
+ stw_call_window_proc,
+ NULL,
+ GetCurrentThreadId());
+ if(data->hCallWndProcHook == NULL)
+ goto no_hook;
+
+ TlsSetValue(tlsIndex, data);
+
+ return data;
+
+no_hook:
+ FREE(data);
+no_data:
+ return NULL;
+}
+
+boolean
+stw_tls_init_thread(void)
+{
+ struct stw_tls_data *data;
+
+ if (tlsIndex == TLS_OUT_OF_INDEXES) {
+ return FALSE;
+ }
+
+ data = stw_tls_data_create();
+ if(!data)
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+stw_tls_cleanup_thread(void)
+{
+ struct stw_tls_data *data;
+
+ if (tlsIndex == TLS_OUT_OF_INDEXES) {
+ return;
+ }
+
+ data = (struct stw_tls_data *) TlsGetValue(tlsIndex);
+ if(data) {
+ TlsSetValue(tlsIndex, NULL);
+
+ if(data->hCallWndProcHook) {
+ UnhookWindowsHookEx(data->hCallWndProcHook);
+ data->hCallWndProcHook = NULL;
+ }
+
+ FREE(data);
+ }
+}
+
+void
+stw_tls_cleanup(void)
+{
+ if (tlsIndex != TLS_OUT_OF_INDEXES) {
+ TlsFree(tlsIndex);
+ tlsIndex = TLS_OUT_OF_INDEXES;
+ }
+}
+
+struct stw_tls_data *
+stw_tls_get_data(void)
+{
+ struct stw_tls_data *data;
+
+ if (tlsIndex == TLS_OUT_OF_INDEXES) {
+ return NULL;
+ }
+
+ data = (struct stw_tls_data *) TlsGetValue(tlsIndex);
+ if(!data) {
+ /* DllMain is called with DLL_THREAD_ATTACH only by threads created after
+ * the DLL is loaded by the process */
+ data = stw_tls_data_create();
+ if(!data)
+ return NULL;
+ }
+
+ return data;
+}
diff --git a/src/gallium/state_trackers/wgl/shared/stw_tls.h b/src/gallium/state_trackers/wgl/shared/stw_tls.h
new file mode 100644
index 0000000000..fbf8b1cbee
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_tls.h
@@ -0,0 +1,59 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_TLS_H
+#define STW_TLS_H
+
+#include <windows.h>
+
+struct stw_tls_data
+{
+ HHOOK hCallWndProcHook;
+};
+
+boolean
+stw_tls_init(void);
+
+boolean
+stw_tls_init_thread(void);
+
+void
+stw_tls_cleanup_thread(void);
+
+void
+stw_tls_cleanup(void);
+
+struct stw_tls_data *
+stw_tls_get_data(void);
+
+LRESULT CALLBACK
+stw_call_window_proc(
+ int nCode,
+ WPARAM wParam,
+ LPARAM lParam );
+
+#endif /* STW_TLS_H */
diff --git a/src/gallium/state_trackers/wgl/shared/stw_winsys.h b/src/gallium/state_trackers/wgl/shared/stw_winsys.h
new file mode 100644
index 0000000000..c0bf82c9ed
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/shared/stw_winsys.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_WINSYS_H
+#define STW_WINSYS_H
+
+#include <windows.h> /* for HDC */
+
+#include "pipe/p_compiler.h"
+
+struct pipe_screen;
+struct pipe_context;
+struct pipe_surface;
+
+struct stw_winsys
+{
+ struct pipe_screen *
+ (*create_screen)( void );
+
+ struct pipe_context *
+ (*create_context)( struct pipe_screen *screen );
+
+ void
+ (*flush_frontbuffer)( struct pipe_screen *screen,
+ struct pipe_surface *surf,
+ HDC hDC );
+};
+
+boolean
+stw_init(const struct stw_winsys *stw_winsys);
+
+boolean
+stw_init_thread(void);
+
+void
+stw_cleanup_thread(void);
+
+void
+stw_cleanup(void);
+
+#endif /* STW_WINSYS_H */
diff --git a/src/gallium/state_trackers/wgl/wgl/stw_wgl.c b/src/gallium/state_trackers/wgl/wgl/stw_wgl.c
new file mode 100644
index 0000000000..a131292f7a
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/wgl/stw_wgl.c
@@ -0,0 +1,329 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <windows.h>
+
+#include "util/u_debug.h"
+#include "shared/stw_public.h"
+#include "stw_wgl.h"
+
+
+WINGDIAPI BOOL APIENTRY
+wglCopyContext(
+ HGLRC hglrcSrc,
+ HGLRC hglrcDst,
+ UINT mask )
+{
+ return stw_copy_context( (UINT_PTR)hglrcSrc,
+ (UINT_PTR)hglrcDst,
+ mask );
+}
+
+WINGDIAPI HGLRC APIENTRY
+wglCreateContext(
+ HDC hdc )
+{
+ return wglCreateLayerContext(hdc, 0);
+}
+
+WINGDIAPI HGLRC APIENTRY
+wglCreateLayerContext(
+ HDC hdc,
+ int iLayerPlane )
+{
+ return (HGLRC) stw_create_layer_context( hdc, iLayerPlane );
+}
+
+WINGDIAPI BOOL APIENTRY
+wglDeleteContext(
+ HGLRC hglrc )
+{
+ return stw_delete_context( (UINT_PTR)hglrc );
+}
+
+
+WINGDIAPI HGLRC APIENTRY
+wglGetCurrentContext( VOID )
+{
+ return (HGLRC)stw_get_current_context();
+}
+
+WINGDIAPI HDC APIENTRY
+wglGetCurrentDC( VOID )
+{
+ return stw_get_current_dc();
+}
+
+WINGDIAPI BOOL APIENTRY
+wglMakeCurrent(
+ HDC hdc,
+ HGLRC hglrc )
+{
+ return stw_make_current( hdc, (UINT_PTR)hglrc );
+}
+
+
+WINGDIAPI BOOL APIENTRY
+wglSwapBuffers(
+ HDC hdc )
+{
+ return stw_swap_buffers( hdc );
+}
+
+
+WINGDIAPI BOOL APIENTRY
+wglSwapLayerBuffers(
+ HDC hdc,
+ UINT fuPlanes )
+{
+ return stw_swap_layer_buffers( hdc, fuPlanes );
+}
+
+WINGDIAPI PROC APIENTRY
+wglGetProcAddress(
+ LPCSTR lpszProc )
+{
+ return stw_get_proc_address( lpszProc );
+}
+
+
+WINGDIAPI int APIENTRY
+wglChoosePixelFormat(
+ HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ if (ppfd->nSize != sizeof( PIXELFORMATDESCRIPTOR ) || ppfd->nVersion != 1)
+ return 0;
+ if (ppfd->iPixelType != PFD_TYPE_RGBA)
+ return 0;
+ if (!(ppfd->dwFlags & PFD_DRAW_TO_WINDOW))
+ return 0;
+ if (!(ppfd->dwFlags & PFD_SUPPORT_OPENGL))
+ return 0;
+ if (ppfd->dwFlags & PFD_DRAW_TO_BITMAP)
+ return 0;
+ if (ppfd->dwFlags & PFD_SUPPORT_GDI)
+ return 0;
+ if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE) && (ppfd->dwFlags & PFD_STEREO))
+ return 0;
+
+ return stw_pixelformat_choose( hdc, ppfd );
+}
+
+WINGDIAPI int APIENTRY
+wglDescribePixelFormat(
+ HDC hdc,
+ int iPixelFormat,
+ UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd )
+{
+ return stw_pixelformat_describe( hdc, iPixelFormat, nBytes, ppfd );
+}
+
+WINGDIAPI int APIENTRY
+wglGetPixelFormat(
+ HDC hdc )
+{
+ return stw_pixelformat_get( hdc );
+}
+
+WINGDIAPI BOOL APIENTRY
+wglSetPixelFormat(
+ HDC hdc,
+ int iPixelFormat,
+ const PIXELFORMATDESCRIPTOR *ppfd )
+{
+ if (ppfd->nSize != sizeof( PIXELFORMATDESCRIPTOR ))
+ return FALSE;
+
+ return stw_pixelformat_set( hdc, iPixelFormat );
+}
+
+
+WINGDIAPI BOOL APIENTRY
+wglUseFontBitmapsA(
+ HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase )
+{
+ (void) hdc;
+ (void) first;
+ (void) count;
+ (void) listBase;
+
+ assert( 0 );
+
+ return FALSE;
+}
+
+WINGDIAPI BOOL APIENTRY
+wglShareLists(
+ HGLRC hglrc1,
+ HGLRC hglrc2 )
+{
+ return stw_share_lists( (UINT_PTR)hglrc1, (UINT_PTR)hglrc2);;
+}
+
+WINGDIAPI BOOL APIENTRY
+wglUseFontBitmapsW(
+ HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase )
+{
+ (void) hdc;
+ (void) first;
+ (void) count;
+ (void) listBase;
+
+ assert( 0 );
+
+ return FALSE;
+}
+
+WINGDIAPI BOOL APIENTRY
+wglUseFontOutlinesA(
+ HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase,
+ FLOAT deviation,
+ FLOAT extrusion,
+ int format,
+ LPGLYPHMETRICSFLOAT lpgmf )
+{
+ (void) hdc;
+ (void) first;
+ (void) count;
+ (void) listBase;
+ (void) deviation;
+ (void) extrusion;
+ (void) format;
+ (void) lpgmf;
+
+ assert( 0 );
+
+ return FALSE;
+}
+
+WINGDIAPI BOOL APIENTRY
+wglUseFontOutlinesW(
+ HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase,
+ FLOAT deviation,
+ FLOAT extrusion,
+ int format,
+ LPGLYPHMETRICSFLOAT lpgmf )
+{
+ (void) hdc;
+ (void) first;
+ (void) count;
+ (void) listBase;
+ (void) deviation;
+ (void) extrusion;
+ (void) format;
+ (void) lpgmf;
+
+ assert( 0 );
+
+ return FALSE;
+}
+
+WINGDIAPI BOOL APIENTRY
+wglDescribeLayerPlane(
+ HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd )
+{
+ (void) hdc;
+ (void) iPixelFormat;
+ (void) iLayerPlane;
+ (void) nBytes;
+ (void) plpd;
+
+ assert( 0 );
+
+ return FALSE;
+}
+
+WINGDIAPI int APIENTRY
+wglSetLayerPaletteEntries(
+ HDC hdc,
+ int iLayerPlane,
+ int iStart,
+ int cEntries,
+ CONST COLORREF *pcr )
+{
+ (void) hdc;
+ (void) iLayerPlane;
+ (void) iStart;
+ (void) cEntries;
+ (void) pcr;
+
+ assert( 0 );
+
+ return 0;
+}
+
+WINGDIAPI int APIENTRY
+wglGetLayerPaletteEntries(
+ HDC hdc,
+ int iLayerPlane,
+ int iStart,
+ int cEntries,
+ COLORREF *pcr )
+{
+ (void) hdc;
+ (void) iLayerPlane;
+ (void) iStart;
+ (void) cEntries;
+ (void) pcr;
+
+ assert( 0 );
+
+ return 0;
+}
+
+WINGDIAPI BOOL APIENTRY
+wglRealizeLayerPalette(
+ HDC hdc,
+ int iLayerPlane,
+ BOOL bRealize )
+{
+ (void) hdc;
+ (void) iLayerPlane;
+ (void) bRealize;
+
+ assert( 0 );
+
+ return FALSE;
+}
diff --git a/src/gallium/state_trackers/wgl/wgl/stw_wgl.h b/src/gallium/state_trackers/wgl/wgl/stw_wgl.h
new file mode 100644
index 0000000000..a98179944a
--- /dev/null
+++ b/src/gallium/state_trackers/wgl/wgl/stw_wgl.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef STW_WGL_H_
+#define STW_WGL_H_
+
+
+#include <windows.h>
+
+#include <GL/gl.h>
+
+
+/*
+ * Undeclared APIs exported by opengl32.dll
+ */
+
+WINGDIAPI BOOL WINAPI
+wglSwapBuffers(HDC hdc);
+
+WINGDIAPI int WINAPI
+wglChoosePixelFormat(HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd);
+
+WINGDIAPI int WINAPI
+wglDescribePixelFormat(HDC hdc,
+ int iPixelFormat,
+ UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd);
+
+WINGDIAPI int WINAPI
+wglGetPixelFormat(HDC hdc);
+
+WINGDIAPI BOOL WINAPI
+wglSetPixelFormat(HDC hdc,
+ int iPixelFormat,
+ CONST PIXELFORMATDESCRIPTOR *ppfd);
+
+
+#endif /* STW_WGL_H_ */
diff --git a/src/gallium/state_trackers/xorg/Makefile b/src/gallium/state_trackers/xorg/Makefile
new file mode 100644
index 0000000000..27a1990724
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/Makefile
@@ -0,0 +1,18 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = xorgtracker
+
+LIBRARY_INCLUDES = \
+ -DHAVE_CONFIG_H \
+ $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -I$(TOP)/src/mesa/main
+
+C_SOURCES = $(wildcard ./*.c)
+
+include ../../Makefile.template
diff --git a/src/gallium/state_trackers/xorg/SConscript b/src/gallium/state_trackers/xorg/SConscript
new file mode 100644
index 0000000000..65f55ea378
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/SConscript
@@ -0,0 +1,27 @@
+#######################################################################
+# SConscript for xorg state_tracker
+
+Import('*')
+
+if 'xorg' in env['statetrackers']:
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#/src/mesa',
+ ])
+
+ env.ParseConfig('pkg-config --cflags --libs xorg-server')
+
+ st_xorg = env.ConvenienceLibrary(
+ target = 'st_xorg',
+ source = [ 'xorg_composite.c',
+ 'xorg_crtc.c',
+ 'xorg_dri2.c',
+ 'xorg_driver.c',
+ 'xorg_exa.c',
+ 'xorg_exa_tgsi.c',
+ 'xorg_output.c',
+ ]
+ )
+ Export('st_xorg')
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c
new file mode 100644
index 0000000000..15c955450d
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_composite.c
@@ -0,0 +1,1019 @@
+#include "xorg_composite.h"
+
+#include "xorg_exa_tgsi.h"
+
+#include "cso_cache/cso_context.h"
+#include "util/u_draw_quad.h"
+#include "util/u_math.h"
+
+#include "pipe/p_inlines.h"
+
+struct xorg_composite_blend {
+ int op:8;
+
+ unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */
+ unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
+
+ unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */
+ unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
+};
+
+#define BLEND_OP_OVER 3
+static const struct xorg_composite_blend xorg_blends[] = {
+ { PictOpClear,
+ PIPE_BLENDFACTOR_CONST_COLOR, PIPE_BLENDFACTOR_CONST_ALPHA,
+ PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
+
+ { PictOpSrc,
+ PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE,
+ PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
+
+ { PictOpDst,
+ PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO,
+ PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE },
+
+ { PictOpOver,
+ PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
+ PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
+
+ { PictOpOverReverse,
+ PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
+ PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
+};
+
+
+static INLINE void
+pixel_to_float4(Pixel pixel, float *color)
+{
+ CARD32 r, g, b, a;
+
+ a = (pixel >> 24) & 0xff;
+ r = (pixel >> 16) & 0xff;
+ g = (pixel >> 8) & 0xff;
+ b = (pixel >> 0) & 0xff;
+ color[0] = ((float)r) / 255.;
+ color[1] = ((float)g) / 255.;
+ color[2] = ((float)b) / 255.;
+ color[3] = ((float)a) / 255.;
+}
+
+static INLINE void
+render_pixel_to_float4(PictFormatPtr format,
+ CARD32 pixel, float *color)
+{
+ CARD32 r, g, b, a;
+
+ debug_assert(format->type == PictTypeDirect);
+
+ r = (pixel >> format->direct.red) & format->direct.redMask;
+ g = (pixel >> format->direct.green) & format->direct.greenMask;
+ b = (pixel >> format->direct.blue) & format->direct.blueMask;
+ a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
+ color[0] = ((float)r) / ((float)format->direct.redMask);
+ color[1] = ((float)g) / ((float)format->direct.greenMask);
+ color[2] = ((float)b) / ((float)format->direct.blueMask);
+ color[3] = ((float)a) / ((float)format->direct.alphaMask);
+}
+
+struct acceleration_info {
+ int op : 16;
+ int with_mask : 1;
+ int component_alpha : 1;
+};
+static const struct acceleration_info accelerated_ops[] = {
+ {PictOpClear, 1, 0},
+ {PictOpSrc, 1, 0},
+ {PictOpDst, 1, 0},
+ {PictOpOver, 1, 0},
+ {PictOpOverReverse, 1, 0},
+ {PictOpIn, 1, 0},
+ {PictOpInReverse, 1, 0},
+ {PictOpOut, 1, 0},
+ {PictOpOutReverse, 1, 0},
+ {PictOpAtop, 1, 0},
+ {PictOpAtopReverse, 1, 0},
+ {PictOpXor, 1, 0},
+ {PictOpAdd, 1, 0},
+ {PictOpSaturate, 1, 0},
+};
+
+static struct xorg_composite_blend
+blend_for_op(int op)
+{
+ const int num_blends =
+ sizeof(xorg_blends)/sizeof(struct xorg_composite_blend);
+ int i;
+
+ for (i = 0; i < num_blends; ++i) {
+ if (xorg_blends[i].op == op)
+ return xorg_blends[i];
+ }
+ return xorg_blends[BLEND_OP_OVER];
+}
+
+static INLINE int
+render_repeat_to_gallium(int mode)
+{
+ switch(mode) {
+ case RepeatNone:
+ return PIPE_TEX_WRAP_CLAMP;
+ case RepeatNormal:
+ return PIPE_TEX_WRAP_REPEAT;
+ case RepeatReflect:
+ return PIPE_TEX_WRAP_MIRROR_REPEAT;
+ case RepeatPad:
+ return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ default:
+ debug_printf("Unsupported repeat mode\n");
+ }
+ return PIPE_TEX_WRAP_REPEAT;
+}
+
+
+static INLINE void
+setup_vertex0(float vertex[2][4], float x, float y,
+ float color[4])
+{
+ vertex[0][0] = x;
+ vertex[0][1] = y;
+ vertex[0][2] = 0.f; /*z*/
+ vertex[0][3] = 1.f; /*w*/
+
+ vertex[1][0] = color[0]; /*r*/
+ vertex[1][1] = color[1]; /*g*/
+ vertex[1][2] = color[2]; /*b*/
+ vertex[1][3] = color[3]; /*a*/
+}
+
+static struct pipe_buffer *
+setup_vertex_data0(struct exa_context *ctx,
+ int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height)
+{
+ float vertices[4][2][4];
+
+ /* 1st vertex */
+ setup_vertex0(vertices[0], dstX, dstY,
+ ctx->solid_color);
+ /* 2nd vertex */
+ setup_vertex0(vertices[1], dstX + width, dstY,
+ ctx->solid_color);
+ /* 3rd vertex */
+ setup_vertex0(vertices[2], dstX + width, dstY + height,
+ ctx->solid_color);
+ /* 4th vertex */
+ setup_vertex0(vertices[3], dstX, dstY + height,
+ ctx->solid_color);
+
+ return pipe_user_buffer_create(ctx->pipe->screen,
+ vertices,
+ sizeof(vertices));
+}
+
+static INLINE void
+setup_vertex1(float vertex[2][4], float x, float y, float s, float t)
+{
+ vertex[0][0] = x;
+ vertex[0][1] = y;
+ vertex[0][2] = 0.f; /*z*/
+ vertex[0][3] = 1.f; /*w*/
+
+ vertex[1][0] = s; /*s*/
+ vertex[1][1] = t; /*t*/
+ vertex[1][2] = 0.f; /*r*/
+ vertex[1][3] = 1.f; /*q*/
+}
+
+static struct pipe_buffer *
+setup_vertex_data1(struct exa_context *ctx,
+ int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height)
+{
+ float vertices[4][2][4];
+ float s0, t0, s1, t1;
+ struct pipe_texture *src = ctx->bound_textures[0];
+
+ s0 = srcX / src->width[0];
+ s1 = srcX + width / src->width[0];
+ t0 = srcY / src->height[0];
+ t1 = srcY + height / src->height[0];
+
+ /* 1st vertex */
+ setup_vertex1(vertices[0], dstX, dstY,
+ s0, t0);
+ /* 2nd vertex */
+ setup_vertex1(vertices[1], dstX + width, dstY,
+ s1, t0);
+ /* 3rd vertex */
+ setup_vertex1(vertices[2], dstX + width, dstY + height,
+ s1, t1);
+ /* 4th vertex */
+ setup_vertex1(vertices[3], dstX, dstY + height,
+ s0, t1);
+
+ return pipe_user_buffer_create(ctx->pipe->screen,
+ vertices,
+ sizeof(vertices));
+}
+
+static struct pipe_buffer *
+setup_vertex_data_tex(struct exa_context *ctx,
+ float x0, float y0, float x1, float y1,
+ float s0, float t0, float s1, float t1,
+ float z)
+{
+ float vertices[4][2][4];
+
+ /* 1st vertex */
+ setup_vertex1(vertices[0], x0, y0,
+ s0, t0);
+ /* 2nd vertex */
+ setup_vertex1(vertices[1], x1, y0,
+ s1, t0);
+ /* 3rd vertex */
+ setup_vertex1(vertices[2], x1, y1,
+ s1, t1);
+ /* 4th vertex */
+ setup_vertex1(vertices[3], x0, y1,
+ s0, t1);
+
+ return pipe_user_buffer_create(ctx->pipe->screen,
+ vertices,
+ sizeof(vertices));
+}
+
+
+
+static INLINE void
+setup_vertex2(float vertex[3][4], float x, float y,
+ float s0, float t0, float s1, float t1)
+{
+ vertex[0][0] = x;
+ vertex[0][1] = y;
+ vertex[0][2] = 0.f; /*z*/
+ vertex[0][3] = 1.f; /*w*/
+
+ vertex[1][0] = s0; /*s*/
+ vertex[1][1] = t0; /*t*/
+ vertex[1][2] = 0.f; /*r*/
+ vertex[1][3] = 1.f; /*q*/
+
+ vertex[2][0] = s1; /*s*/
+ vertex[2][1] = t1; /*t*/
+ vertex[2][2] = 0.f; /*r*/
+ vertex[2][3] = 1.f; /*q*/
+}
+
+static struct pipe_buffer *
+setup_vertex_data2(struct exa_context *ctx,
+ int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height)
+{
+ float vertices[4][3][4];
+ float st0[4], st1[4];
+ struct pipe_texture *src = ctx->bound_textures[0];
+ struct pipe_texture *mask = ctx->bound_textures[0];
+
+ st0[0] = srcX / src->width[0];
+ st0[1] = srcY / src->height[0];
+ st0[2] = srcX + width / src->width[0];
+ st0[3] = srcY + height / src->height[0];
+
+ st1[0] = maskX / mask->width[0];
+ st1[1] = maskY / mask->height[0];
+ st1[2] = maskX + width / mask->width[0];
+ st1[3] = maskY + height / mask->height[0];
+
+ /* 1st vertex */
+ setup_vertex2(vertices[0], dstX, dstY,
+ st0[0], st0[1], st1[0], st1[1]);
+ /* 2nd vertex */
+ setup_vertex2(vertices[1], dstX + width, dstY,
+ st0[2], st0[1], st1[2], st1[1]);
+ /* 3rd vertex */
+ setup_vertex2(vertices[2], dstX + width, dstY + height,
+ st0[2], st0[3], st1[2], st1[3]);
+ /* 4th vertex */
+ setup_vertex2(vertices[3], dstX, dstY + height,
+ st0[0], st0[3], st1[0], st1[3]);
+
+ return pipe_user_buffer_create(ctx->pipe->screen,
+ vertices,
+ sizeof(vertices));
+}
+
+boolean xorg_composite_accelerated(int op,
+ PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ unsigned i;
+ unsigned accel_ops_count =
+ sizeof(accelerated_ops)/sizeof(struct acceleration_info);
+
+
+ /*FIXME: currently accel is disabled */
+ return FALSE;
+
+ if (pSrcPicture) {
+ /* component alpha not supported */
+ if (pSrcPicture->componentAlpha)
+ return FALSE;
+ /* fills not supported */
+ if (pSrcPicture->pSourcePict)
+ return FALSE;
+ }
+
+ for (i = 0; i < accel_ops_count; ++i) {
+ if (op == accelerated_ops[i].op) {
+ if (pMaskPicture && !accelerated_ops[i].with_mask)
+ return FALSE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+bind_clip_state(struct exa_context *exa)
+{
+}
+
+static void
+bind_framebuffer_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
+{
+ unsigned i;
+ struct pipe_framebuffer_state state;
+ struct pipe_surface *surface = exa_gpu_surface(exa, pDst);
+ memset(&state, 0, sizeof(struct pipe_framebuffer_state));
+
+ state.width = pDst->tex->width[0];
+ state.height = pDst->tex->height[0];
+
+ state.nr_cbufs = 1;
+ state.cbufs[0] = surface;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ state.cbufs[i] = 0;
+
+ /* currently we don't use depth/stencil */
+ state.zsbuf = 0;
+
+ cso_set_framebuffer(exa->cso, &state);
+}
+
+enum AxisOrientation {
+ Y0_BOTTOM,
+ Y0_TOP
+};
+
+static void
+set_viewport(struct exa_context *exa, int width, int height,
+ enum AxisOrientation orientation)
+{
+ struct pipe_viewport_state viewport;
+ float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f;
+
+ viewport.scale[0] = width / 2.f;
+ viewport.scale[1] = height / y_scale;
+ viewport.scale[2] = 1.0;
+ viewport.scale[3] = 1.0;
+ viewport.translate[0] = width / 2.f;
+ viewport.translate[1] = height / 2.f;
+ viewport.translate[2] = 0.0;
+ viewport.translate[3] = 0.0;
+
+ cso_set_viewport(exa->cso, &viewport);
+}
+
+static void
+bind_viewport_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
+{
+ int width = pDst->tex->width[0];
+ int height = pDst->tex->height[0];
+
+ debug_printf("Bind viewport (%d, %d)\n", width, height);
+
+ set_viewport(exa, width, height, Y0_TOP);
+}
+
+static void
+bind_blend_state(struct exa_context *exa, int op,
+ PicturePtr pSrcPicture, PicturePtr pMaskPicture)
+{
+ boolean component_alpha = (pSrcPicture) ?
+ pSrcPicture->componentAlpha : FALSE;
+ struct xorg_composite_blend blend_opt;
+ struct pipe_blend_state blend;
+
+ if (component_alpha) {
+ op = PictOpOver;
+ }
+ blend_opt = blend_for_op(op);
+
+ memset(&blend, 0, sizeof(struct pipe_blend_state));
+ blend.blend_enable = 1;
+ blend.colormask |= PIPE_MASK_R;
+ blend.colormask |= PIPE_MASK_G;
+ blend.colormask |= PIPE_MASK_B;
+ blend.colormask |= PIPE_MASK_A;
+
+ blend.rgb_src_factor = blend_opt.rgb_src_factor;
+ blend.alpha_src_factor = blend_opt.alpha_src_factor;
+ blend.rgb_dst_factor = blend_opt.rgb_dst_factor;
+ blend.alpha_dst_factor = blend_opt.alpha_dst_factor;
+
+ cso_set_blend(exa->cso, &blend);
+}
+
+static void
+bind_rasterizer_state(struct exa_context *exa)
+{
+ struct pipe_rasterizer_state raster;
+ memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
+ raster.gl_rasterization_rules = 1;
+ cso_set_rasterizer(exa->cso, &raster);
+}
+
+static void
+bind_shaders(struct exa_context *exa, int op,
+ PicturePtr pSrcPicture, PicturePtr pMaskPicture)
+{
+ unsigned vs_traits = 0, fs_traits = 0;
+ struct xorg_shader shader;
+
+ exa->has_solid_color = FALSE;
+
+ if (pSrcPicture) {
+ if (pSrcPicture->pSourcePict) {
+ if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
+ fs_traits |= FS_SOLID_FILL;
+ vs_traits |= VS_SOLID_FILL;
+ render_pixel_to_float4(pSrcPicture->pFormat,
+ pSrcPicture->pSourcePict->solidFill.color,
+ exa->solid_color);
+ exa->has_solid_color = TRUE;
+ } else {
+ debug_assert("!gradients not supported");
+ }
+ } else {
+ fs_traits |= FS_COMPOSITE;
+ vs_traits |= VS_COMPOSITE;
+ }
+ }
+
+ if (pMaskPicture) {
+ vs_traits |= VS_MASK;
+ fs_traits |= FS_MASK;
+ }
+
+ shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(exa->cso, shader.vs);
+ cso_set_fragment_shader_handle(exa->cso, shader.fs);
+}
+
+
+static void
+bind_samplers(struct exa_context *exa, int op,
+ PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture,
+ struct exa_pixmap_priv *pSrc,
+ struct exa_pixmap_priv *pMask,
+ struct exa_pixmap_priv *pDst)
+{
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_state src_sampler, mask_sampler;
+
+ exa->num_bound_samplers = 0;
+
+ memset(&src_sampler, 0, sizeof(struct pipe_sampler_state));
+ memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
+
+ if (pSrcPicture && pSrc) {
+ unsigned src_wrap = render_repeat_to_gallium(
+ pSrcPicture->repeatType);
+ src_sampler.wrap_s = src_wrap;
+ src_sampler.wrap_t = src_wrap;
+ src_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ src_sampler.normalized_coords = 1;
+ samplers[0] = &src_sampler;
+ exa->bound_textures[0] = pSrc->tex;
+ ++exa->num_bound_samplers;
+ }
+
+ if (pMaskPicture && pMask) {
+ unsigned mask_wrap = render_repeat_to_gallium(
+ pMaskPicture->repeatType);
+ mask_sampler.wrap_s = mask_wrap;
+ mask_sampler.wrap_t = mask_wrap;
+ mask_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ mask_sampler.normalized_coords = 1;
+ samplers[1] = &mask_sampler;
+ exa->bound_textures[1] = pMask->tex;
+ ++exa->num_bound_samplers;
+ }
+
+ cso_set_samplers(exa->cso, exa->num_bound_samplers,
+ (const struct pipe_sampler_state **)samplers);
+ cso_set_sampler_textures(exa->cso, exa->num_bound_samplers,
+ exa->bound_textures);
+}
+
+static void
+setup_vs_constant_buffer(struct exa_context *exa,
+ int width, int height)
+{
+ const int param_bytes = 8 * sizeof(float);
+ float vs_consts[8] = {
+ 2.f/width, 2.f/height, 1, 1,
+ -1, -1, 0, 0
+ };
+ struct pipe_constant_buffer *cbuf = &exa->vs_const_buffer;
+
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+ cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+
+ if (cbuf->buffer) {
+ pipe_buffer_write(exa->pipe->screen, cbuf->buffer,
+ 0, param_bytes, vs_consts);
+ }
+ exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_VERTEX, 0, cbuf);
+}
+
+
+static void
+setup_fs_constant_buffer(struct exa_context *exa)
+{
+ const int param_bytes = 4 * sizeof(float);
+ float fs_consts[8] = {
+ 0, 0, 0, 1,
+ };
+ struct pipe_constant_buffer *cbuf = &exa->fs_const_buffer;
+
+ pipe_buffer_reference(&cbuf->buffer, NULL);
+ cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ param_bytes);
+
+ if (cbuf->buffer) {
+ pipe_buffer_write(exa->pipe->screen, cbuf->buffer,
+ 0, param_bytes, fs_consts);
+ }
+ exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
+}
+
+static void
+setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst)
+{
+ int width = pDst->tex->width[0];
+ int height = pDst->tex->height[0];
+
+ setup_vs_constant_buffer(exa, width, height);
+ setup_fs_constant_buffer(exa);
+}
+
+boolean xorg_composite_bind_state(struct exa_context *exa,
+ int op,
+ PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture,
+ PicturePtr pDstPicture,
+ struct exa_pixmap_priv *pSrc,
+ struct exa_pixmap_priv *pMask,
+ struct exa_pixmap_priv *pDst)
+{
+ bind_framebuffer_state(exa, pDst);
+ bind_viewport_state(exa, pDst);
+ bind_blend_state(exa, op, pSrcPicture, pMaskPicture);
+ bind_rasterizer_state(exa);
+ bind_shaders(exa, op, pSrcPicture, pMaskPicture);
+ bind_samplers(exa, op, pSrcPicture, pMaskPicture,
+ pDstPicture, pSrc, pMask, pDst);
+ bind_clip_state(exa);
+ setup_constant_buffers(exa, pDst);
+
+ return FALSE;
+}
+
+void xorg_composite(struct exa_context *exa,
+ struct exa_pixmap_priv *dst,
+ int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height)
+{
+ struct pipe_context *pipe = exa->pipe;
+ struct pipe_buffer *buf = 0;
+
+ if (exa->num_bound_samplers == 0 ) { /* solid fill */
+ buf = setup_vertex_data0(exa,
+ srcX, srcY, maskX, maskY,
+ dstX, dstY, width, height);
+ } else if (exa->num_bound_samplers == 1 ) /* src */
+ buf = setup_vertex_data1(exa,
+ srcX, srcY, maskX, maskY,
+ dstX, dstY, width, height);
+ else if (exa->num_bound_samplers == 2) /* src + mask */
+ buf = setup_vertex_data2(exa,
+ srcX, srcY, maskX, maskY,
+ dstX, dstY, width, height);
+ else if (exa->num_bound_samplers == 3) { /* src + mask + dst */
+ debug_assert(!"src/mask/dst not handled right now");
+#if 0
+ buf = setup_vertex_data2(exa,
+ srcX, srcY, maskX, maskY,
+ dstX, dstY, width, height);
+#endif
+ }
+
+ if (buf) {
+ int num_attribs = 1; /*pos*/
+ num_attribs += exa->num_bound_samplers;
+ if (exa->has_solid_color)
+ ++num_attribs;
+
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ num_attribs); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+}
+
+boolean xorg_solid_bind_state(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ Pixel fg)
+{
+ unsigned vs_traits, fs_traits;
+ struct xorg_shader shader;
+
+ pixel_to_float4(fg, exa->solid_color);
+ exa->has_solid_color = TRUE;
+
+ exa->solid_color[3] = 1.f;
+
+ debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
+ (fg >> 24) & 0xff, (fg >> 16) & 0xff,
+ (fg >> 8) & 0xff, (fg >> 0) & 0xff,
+ exa->solid_color[0], exa->solid_color[1],
+ exa->solid_color[2], exa->solid_color[3]);
+
+#if 0
+ exa->solid_color[0] = 1.f;
+ exa->solid_color[1] = 0.f;
+ exa->solid_color[2] = 0.f;
+ exa->solid_color[3] = 1.f;
+#endif
+
+ vs_traits = VS_SOLID_FILL;
+ fs_traits = FS_SOLID_FILL;
+
+ bind_framebuffer_state(exa, pixmap);
+ bind_viewport_state(exa, pixmap);
+ bind_rasterizer_state(exa);
+ bind_blend_state(exa, PictOpSrc, NULL, NULL);
+ setup_constant_buffers(exa, pixmap);
+ bind_clip_state(exa);
+
+ shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
+ cso_set_vertex_shader_handle(exa->cso, shader.vs);
+ cso_set_fragment_shader_handle(exa->cso, shader.fs);
+
+ return FALSE;
+}
+
+void xorg_solid(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ int x0, int y0, int x1, int y1)
+{
+ struct pipe_context *pipe = exa->pipe;
+ struct pipe_buffer *buf = 0;
+ float vertices[4][2][4];
+
+ x0 = 10; y0 = 10;
+ x1 = 300; y1 = 300;
+
+ /* 1st vertex */
+ setup_vertex0(vertices[0], x0, y0,
+ exa->solid_color);
+ /* 2nd vertex */
+ setup_vertex0(vertices[1], x1, y0,
+ exa->solid_color);
+ /* 3rd vertex */
+ setup_vertex0(vertices[2], x1, y1,
+ exa->solid_color);
+ /* 4th vertex */
+ setup_vertex0(vertices[3], x0, y1,
+ exa->solid_color);
+
+ buf = pipe_user_buffer_create(exa->pipe->screen,
+ vertices,
+ sizeof(vertices));
+
+
+ if (buf) {
+ debug_printf("Drawing buf is %p\n", buf);
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+}
+
+
+static INLINE void shift_rectx(float coords[4],
+ const float *bounds,
+ const float shift)
+{
+ coords[0] += shift;
+ coords[2] -= shift;
+ if (bounds) {
+ coords[2] = MIN2(coords[2], bounds[2]);
+ /* bound x/y + width/height */
+ if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
+ coords[2] = (bounds[0] + bounds[2]) - coords[0];
+ }
+ }
+}
+
+static INLINE void shift_recty(float coords[4],
+ const float *bounds,
+ const float shift)
+{
+ coords[1] += shift;
+ coords[3] -= shift;
+ if (bounds) {
+ coords[3] = MIN2(coords[3], bounds[3]);
+ if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
+ coords[3] = (bounds[1] + bounds[3]) - coords[1];
+ }
+ }
+}
+
+static INLINE void bound_rect(float coords[4],
+ const float bounds[4],
+ float shift[4])
+{
+ /* if outside the bounds */
+ if (coords[0] > (bounds[0] + bounds[2]) ||
+ coords[1] > (bounds[1] + bounds[3]) ||
+ (coords[0] + coords[2]) < bounds[0] ||
+ (coords[1] + coords[3]) < bounds[1]) {
+ coords[0] = 0.f;
+ coords[1] = 0.f;
+ coords[2] = 0.f;
+ coords[3] = 0.f;
+ shift[0] = 0.f;
+ shift[1] = 0.f;
+ return;
+ }
+
+ /* bound x */
+ if (coords[0] < bounds[0]) {
+ shift[0] = bounds[0] - coords[0];
+ coords[2] -= shift[0];
+ coords[0] = bounds[0];
+ } else
+ shift[0] = 0.f;
+
+ /* bound y */
+ if (coords[1] < bounds[1]) {
+ shift[1] = bounds[1] - coords[1];
+ coords[3] -= shift[1];
+ coords[1] = bounds[1];
+ } else
+ shift[1] = 0.f;
+
+ shift[2] = bounds[2] - coords[2];
+ shift[3] = bounds[3] - coords[3];
+ /* bound width/height */
+ coords[2] = MIN2(coords[2], bounds[2]);
+ coords[3] = MIN2(coords[3], bounds[3]);
+
+ /* bound x/y + width/height */
+ if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
+ coords[2] = (bounds[0] + bounds[2]) - coords[0];
+ }
+ if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
+ coords[3] = (bounds[1] + bounds[3]) - coords[1];
+ }
+
+ /* if outside the bounds */
+ if ((coords[0] + coords[2]) < bounds[0] ||
+ (coords[1] + coords[3]) < bounds[1]) {
+ coords[0] = 0.f;
+ coords[1] = 0.f;
+ coords[2] = 0.f;
+ coords[3] = 0.f;
+ return;
+ }
+}
+
+static INLINE void sync_size(float *src_loc, float *dst_loc)
+{
+ src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
+ src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
+ dst_loc[2] = src_loc[2];
+ dst_loc[3] = src_loc[3];
+}
+
+
+static void renderer_copy_texture(struct exa_context *exa,
+ struct pipe_texture *src,
+ float sx1, float sy1,
+ float sx2, float sy2,
+ struct pipe_texture *dst,
+ float dx1, float dy1,
+ float dx2, float dy2)
+{
+ struct pipe_context *pipe = exa->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_buffer *buf;
+ struct pipe_surface *dst_surf = screen->get_tex_surface(
+ screen, dst, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ struct pipe_framebuffer_state fb;
+ float s0, t0, s1, t1;
+ struct xorg_shader shader;
+
+ assert(src->width[0] != 0);
+ assert(src->height[0] != 0);
+ assert(dst->width[0] != 0);
+ assert(dst->height[0] != 0);
+
+#if 0
+ debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
+ sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
+#endif
+
+#if 1
+ s0 = sx1 / src->width[0];
+ s1 = sx2 / src->width[0];
+ t0 = sy1 / src->height[0];
+ t1 = sy2 / src->height[0];
+#else
+ s0 = 0;
+ s1 = 1;
+ t0 = 0;
+ t1 = 1;
+#endif
+
+ assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
+
+ /* save state (restored below) */
+ cso_save_blend(exa->cso);
+ cso_save_samplers(exa->cso);
+ cso_save_sampler_textures(exa->cso);
+ cso_save_framebuffer(exa->cso);
+ cso_save_fragment_shader(exa->cso);
+ cso_save_vertex_shader(exa->cso);
+
+ cso_save_viewport(exa->cso);
+
+
+ /* set misc state we care about */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask = PIPE_MASK_RGBA;
+ cso_set_blend(exa->cso, &blend);
+ }
+
+ /* sampler */
+ {
+ struct pipe_sampler_state sampler;
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.normalized_coords = 1;
+ cso_single_sampler(exa->cso, 0, &sampler);
+ cso_single_sampler_done(exa->cso);
+ }
+
+ set_viewport(exa, dst_surf->width, dst_surf->height, Y0_TOP);
+
+ /* texture */
+ cso_set_sampler_textures(exa->cso, 1, &src);
+
+ /* shaders */
+ shader = xorg_shaders_get(exa->shaders,
+ VS_COMPOSITE,
+ FS_COMPOSITE);
+ cso_set_vertex_shader_handle(exa->cso, shader.vs);
+ cso_set_fragment_shader_handle(exa->cso, shader.fs);
+
+ /* drawing dest */
+ memset(&fb, 0, sizeof(fb));
+ fb.width = dst_surf->width;
+ fb.height = dst_surf->height;
+ fb.nr_cbufs = 1;
+ fb.cbufs[0] = dst_surf;
+ {
+ int i;
+ for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
+ fb.cbufs[i] = 0;
+ }
+ cso_set_framebuffer(exa->cso, &fb);
+
+ /* draw quad */
+ buf = setup_vertex_data_tex(exa,
+ dx1, dy1,
+ dx2, dy2,
+ s0, t0, s1, t1,
+ 0.0f);
+
+ if (buf) {
+ util_draw_vertex_buffer(exa->pipe, buf, 0,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ pipe_buffer_reference(&buf, NULL);
+ }
+
+ /* restore state we changed */
+ cso_restore_blend(exa->cso);
+ cso_restore_samplers(exa->cso);
+ cso_restore_sampler_textures(exa->cso);
+ cso_restore_framebuffer(exa->cso);
+ cso_restore_vertex_shader(exa->cso);
+ cso_restore_fragment_shader(exa->cso);
+ cso_restore_viewport(exa->cso);
+
+ pipe_surface_reference(&dst_surf, NULL);
+}
+
+void xorg_copy_pixmap(struct exa_context *ctx,
+ struct exa_pixmap_priv *dst_priv, int dx, int dy,
+ struct exa_pixmap_priv *src_priv, int sx, int sy,
+ int width, int height)
+{
+ float dst_loc[4], src_loc[4];
+ float dst_bounds[4], src_bounds[4];
+ float src_shift[4], dst_shift[4], shift[4];
+ struct pipe_texture *dst = dst_priv->tex;
+ struct pipe_texture *src = src_priv->tex;
+
+ dst_loc[0] = dx;
+ dst_loc[1] = dy;
+ dst_loc[2] = width;
+ dst_loc[3] = height;
+ dst_bounds[0] = 0.f;
+ dst_bounds[1] = 0.f;
+ dst_bounds[2] = dst->width[0];
+ dst_bounds[3] = dst->height[0];
+
+ src_loc[0] = sx;
+ src_loc[1] = sy;
+ src_loc[2] = width;
+ src_loc[3] = height;
+ src_bounds[0] = 0.f;
+ src_bounds[1] = 0.f;
+ src_bounds[2] = src->width[0];
+ src_bounds[3] = src->height[0];
+
+ bound_rect(src_loc, src_bounds, src_shift);
+ bound_rect(dst_loc, dst_bounds, dst_shift);
+ shift[0] = src_shift[0] - dst_shift[0];
+ shift[1] = src_shift[1] - dst_shift[1];
+
+ if (shift[0] < 0)
+ shift_rectx(src_loc, src_bounds, -shift[0]);
+ else
+ shift_rectx(dst_loc, dst_bounds, shift[0]);
+
+ if (shift[1] < 0)
+ shift_recty(src_loc, src_bounds, -shift[1]);
+ else
+ shift_recty(dst_loc, dst_bounds, shift[1]);
+
+ sync_size(src_loc, dst_loc);
+
+ if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
+ dst_loc[2] >= 0 && dst_loc[3] >= 0) {
+ renderer_copy_texture(ctx,
+ src,
+ src_loc[0],
+ src_loc[1] + src_loc[3],
+ src_loc[0] + src_loc[2],
+ src_loc[1],
+ dst,
+ dst_loc[0],
+ dst_loc[1] + dst_loc[3],
+ dst_loc[0] + dst_loc[2],
+ dst_loc[1]);
+ }
+}
+
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.h b/src/gallium/state_trackers/xorg/xorg_composite.h
new file mode 100644
index 0000000000..e73f1c704a
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_composite.h
@@ -0,0 +1,37 @@
+#ifndef XORG_COMPOSITE_H
+#define XORG_COMPOSITE_H
+
+#include "xorg_exa.h"
+
+boolean xorg_composite_accelerated(int op,
+ PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture,
+ PicturePtr pDstPicture);
+
+boolean xorg_composite_bind_state(struct exa_context *exa,
+ int op,
+ PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture,
+ PicturePtr pDstPicture,
+ struct exa_pixmap_priv *pSrc,
+ struct exa_pixmap_priv *pMask,
+ struct exa_pixmap_priv *pDst);
+
+void xorg_composite(struct exa_context *exa,
+ struct exa_pixmap_priv *dst,
+ int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height);
+
+boolean xorg_solid_bind_state(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ Pixel fg);
+void xorg_solid(struct exa_context *exa,
+ struct exa_pixmap_priv *pixmap,
+ int x0, int y0, int x1, int y1);
+
+void xorg_copy_pixmap(struct exa_context *ctx,
+ struct exa_pixmap_priv *dst, int dx, int dy,
+ struct exa_pixmap_priv *src, int sx, int sy,
+ int width, int height);
+
+#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c
new file mode 100644
index 0000000000..fe08bde9ef
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_crtc.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Author: Alan Hourihane <alanh@tungstengraphics.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "xorg-server.h"
+#include <xf86.h>
+#include <xf86i2c.h>
+#include <xf86Crtc.h>
+#include "xorg_tracker.h"
+#include "xf86Modes.h"
+
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "pipe/p_inlines.h"
+#include "util/u_rect.h"
+
+struct crtc_private
+{
+ drmModeCrtcPtr drm_crtc;
+
+ /* hwcursor */
+ struct pipe_texture *cursor_tex;
+ unsigned cursor_handle;
+};
+
+static void
+crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+ //ScrnInfoPtr pScrn = crtc->scrn;
+
+ switch (mode) {
+ case DPMSModeOn:
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ break;
+ case DPMSModeOff:
+ break;
+ }
+}
+
+static Bool
+crtc_lock(xf86CrtcPtr crtc)
+{
+ return FALSE;
+}
+
+static void
+crtc_unlock(xf86CrtcPtr crtc)
+{
+}
+
+static void
+crtc_prepare(xf86CrtcPtr crtc)
+{
+}
+
+static void
+crtc_commit(xf86CrtcPtr crtc)
+{
+}
+
+static Bool
+crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ return TRUE;
+}
+
+static void
+crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode, int x, int y)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ modesettingPtr ms = modesettingPTR(crtc->scrn);
+ xf86OutputPtr output = config->output[config->compat_output];
+ drmModeConnectorPtr drm_connector = output->driver_private;
+ struct crtc_private *crtcp = crtc->driver_private;
+ drmModeCrtcPtr drm_crtc = crtcp->drm_crtc;
+ drmModeModeInfo drm_mode;
+
+ drm_mode.clock = mode->Clock;
+ drm_mode.hdisplay = mode->HDisplay;
+ drm_mode.hsync_start = mode->HSyncStart;
+ drm_mode.hsync_end = mode->HSyncEnd;
+ drm_mode.htotal = mode->HTotal;
+ drm_mode.vdisplay = mode->VDisplay;
+ drm_mode.vsync_start = mode->VSyncStart;
+ drm_mode.vsync_end = mode->VSyncEnd;
+ drm_mode.vtotal = mode->VTotal;
+ drm_mode.flags = mode->Flags;
+ drm_mode.hskew = mode->HSkew;
+ drm_mode.vscan = mode->VScan;
+ drm_mode.vrefresh = mode->VRefresh;
+ if (!mode->name)
+ xf86SetModeDefaultName(mode);
+ strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN);
+
+ drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, ms->fb_id, x, y,
+ &drm_connector->connector_id, 1, &drm_mode);
+}
+
+#if 0
+static void
+crtc_load_lut(xf86CrtcPtr crtc)
+{
+ //ScrnInfoPtr pScrn = crtc->scrn;
+}
+#endif
+
+static void
+crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue,
+ int size)
+{
+}
+
+static void *
+crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
+{
+ //ScrnInfoPtr pScrn = crtc->scrn;
+
+ return NULL;
+}
+
+static PixmapPtr
+crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
+{
+ //ScrnInfoPtr pScrn = crtc->scrn;
+
+ return NULL;
+}
+
+static void
+crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
+{
+ //ScrnInfoPtr pScrn = crtc->scrn;
+}
+
+static void
+crtc_destroy(xf86CrtcPtr crtc)
+{
+ struct crtc_private *crtcp = crtc->driver_private;
+
+ if (crtcp->cursor_tex)
+ pipe_texture_reference(&crtcp->cursor_tex, NULL);
+
+ drmModeFreeCrtc(crtcp->drm_crtc);
+ xfree(crtcp);
+}
+
+static void
+crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
+{
+ unsigned char *ptr;
+ modesettingPtr ms = modesettingPTR(crtc->scrn);
+ struct crtc_private *crtcp = crtc->driver_private;
+ struct pipe_transfer *transfer;
+
+ if (!crtcp->cursor_tex) {
+ struct pipe_texture templat;
+ unsigned pitch;
+
+ memset(&templat, 0, sizeof(templat));
+ templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
+ templat.target = PIPE_TEXTURE_2D;
+ templat.last_level = 0;
+ templat.depth[0] = 1;
+ templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ templat.width[0] = 64;
+ templat.height[0] = 64;
+ pf_get_block(templat.format, &templat.block);
+
+ crtcp->cursor_tex = ms->screen->texture_create(ms->screen,
+ &templat);
+ ms->api->local_handle_from_texture(ms->api,
+ ms->screen,
+ crtcp->cursor_tex,
+ &pitch,
+ &crtcp->cursor_handle);
+ }
+
+ transfer = ms->screen->get_tex_transfer(ms->screen, crtcp->cursor_tex,
+ 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ 0, 0, 64, 64);
+ ptr = ms->screen->transfer_map(ms->screen, transfer);
+ util_copy_rect(ptr, &crtcp->cursor_tex->block,
+ transfer->stride, 0, 0,
+ 64, 64, (void*)image, 64 * 4, 0, 0);
+ ms->screen->transfer_unmap(ms->screen, transfer);
+ ms->screen->tex_transfer_destroy(transfer);
+}
+
+static void
+crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
+{
+ modesettingPtr ms = modesettingPTR(crtc->scrn);
+ struct crtc_private *crtcp = crtc->driver_private;
+
+ drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y);
+}
+
+static void
+crtc_show_cursor(xf86CrtcPtr crtc)
+{
+ modesettingPtr ms = modesettingPTR(crtc->scrn);
+ struct crtc_private *crtcp = crtc->driver_private;
+
+ if (crtcp->cursor_tex)
+ drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
+ crtcp->cursor_handle, 64, 64);
+}
+
+static void
+crtc_hide_cursor(xf86CrtcPtr crtc)
+{
+ modesettingPtr ms = modesettingPTR(crtc->scrn);
+ struct crtc_private *crtcp = crtc->driver_private;
+
+ drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0);
+}
+
+static const xf86CrtcFuncsRec crtc_funcs = {
+ .dpms = crtc_dpms,
+ .save = NULL,
+ .restore = NULL,
+ .lock = crtc_lock,
+ .unlock = crtc_unlock,
+ .mode_fixup = crtc_mode_fixup,
+ .prepare = crtc_prepare,
+ .mode_set = crtc_mode_set,
+ .commit = crtc_commit,
+ .gamma_set = crtc_gamma_set,
+ .shadow_create = crtc_shadow_create,
+ .shadow_allocate = crtc_shadow_allocate,
+ .shadow_destroy = crtc_shadow_destroy,
+ .set_cursor_position = crtc_set_cursor_position,
+ .show_cursor = crtc_show_cursor,
+ .hide_cursor = crtc_hide_cursor,
+ .load_cursor_image = NULL, /* lets convert to argb only */
+ .set_cursor_colors = NULL, /* using argb only */
+ .load_cursor_argb = crtc_load_cursor_argb,
+ .destroy = crtc_destroy,
+};
+
+void
+crtc_cursor_destroy(xf86CrtcPtr crtc)
+{
+ struct crtc_private *crtcp = crtc->driver_private;
+
+ if (crtcp->cursor_tex) {
+ pipe_texture_reference(&crtcp->cursor_tex, NULL);
+ }
+}
+
+void
+crtc_init(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ xf86CrtcPtr crtc;
+ drmModeResPtr res;
+ drmModeCrtcPtr drm_crtc = NULL;
+ struct crtc_private *crtcp;
+ int c;
+
+ res = drmModeGetResources(ms->fd);
+ if (res == 0) {
+ ErrorF("Failed drmModeGetResources %d\n", errno);
+ return;
+ }
+
+ for (c = 0; c < res->count_crtcs; c++) {
+ drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]);
+ if (!drm_crtc)
+ continue;
+
+ crtc = xf86CrtcCreate(pScrn, &crtc_funcs);
+ if (crtc == NULL)
+ goto out;
+
+ crtcp = xcalloc(1, sizeof(struct crtc_private));
+ if (!crtcp) {
+ xf86CrtcDestroy(crtc);
+ goto out;
+ }
+
+ crtcp->drm_crtc = drm_crtc;
+
+ crtc->driver_private = crtcp;
+
+ }
+
+ out:
+ drmModeFreeResources(res);
+}
+
+/* vim: set sw=4 ts=8 sts=4: */
diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c
new file mode 100644
index 0000000000..8a362596c7
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_dri2.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Author: Alan Hourihane <alanh@tungstengraphics.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ */
+
+#include "xorg-server.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "xorg_tracker.h"
+#include "xorg_exa.h"
+
+#include "dri2.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_rect.h"
+
+typedef struct {
+ PixmapPtr pPixmap;
+ struct pipe_texture *tex;
+ struct pipe_fence_handle *fence;
+} *BufferPrivatePtr;
+
+static Bool
+driDoCreateBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int format)
+{
+ struct pipe_texture *tex = NULL;
+ ScreenPtr pScreen = pDraw->pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_pixmap_priv *exa_priv;
+ BufferPrivatePtr private = buffer->driverPrivate;
+ PixmapPtr pPixmap;
+ unsigned stride, handle;
+
+ if (pDraw->type == DRAWABLE_PIXMAP)
+ pPixmap = (PixmapPtr) pDraw;
+ else
+ pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr) pDraw);
+ exa_priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ switch (buffer->attachment) {
+ default:
+ if (buffer->attachment != DRI2BufferFakeFrontLeft ||
+ pDraw->type != DRAWABLE_PIXMAP) {
+ private->pPixmap = (*pScreen->CreatePixmap)(pScreen, pDraw->width,
+ pDraw->height,
+ pDraw->depth,
+ 0);
+ }
+ break;
+ case DRI2BufferFrontLeft:
+ break;
+ case DRI2BufferStencil:
+#if defined(DRI2INFOREC_VERSION) && DRI2INFOREC_VERSION > 2
+ case DRI2BufferDepthStencil:
+ if (exa_priv->depth_stencil_tex &&
+ !pf_is_depth_stencil(exa_priv->depth_stencil_tex->format))
+ exa_priv->depth_stencil_tex = NULL;
+ /* Fall through */
+#endif
+ case DRI2BufferDepth:
+ if (exa_priv->depth_stencil_tex)
+ pipe_texture_reference(&tex, exa_priv->depth_stencil_tex);
+ else {
+ struct pipe_texture template;
+ memset(&template, 0, sizeof(template));
+ template.target = PIPE_TEXTURE_2D;
+ if (buffer->attachment == DRI2BufferDepth)
+ template.format = ms->ds_depth_bits_last ?
+ PIPE_FORMAT_X8Z24_UNORM : PIPE_FORMAT_Z24X8_UNORM;
+ else
+ template.format = ms->ds_depth_bits_last ?
+ PIPE_FORMAT_S8Z24_UNORM : PIPE_FORMAT_Z24S8_UNORM;
+ pf_get_block(template.format, &template.block);
+ template.width[0] = pDraw->width;
+ template.height[0] = pDraw->height;
+ template.depth[0] = 1;
+ template.last_level = 0;
+ template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+ tex = ms->screen->texture_create(ms->screen, &template);
+ pipe_texture_reference(&exa_priv->depth_stencil_tex, tex);
+ }
+ break;
+ }
+
+ if (!private->pPixmap) {
+ private->pPixmap = pPixmap;
+ pPixmap->refcnt++;
+ }
+
+ if (!tex) {
+ exaMoveInPixmap(private->pPixmap);
+ xorg_exa_set_shared_usage(private->pPixmap);
+ pScreen->ModifyPixmapHeader(private->pPixmap, 0, 0, 0, 0, 0, NULL);
+ tex = xorg_exa_get_texture(private->pPixmap);
+ }
+
+ if (!tex)
+ FatalError("NO TEXTURE IN DRI2\n");
+
+ ms->api->shared_handle_from_texture(ms->api, ms->screen, tex, &stride, &handle);
+
+ buffer->name = handle;
+ buffer->pitch = stride;
+ buffer->cpp = 4;
+ buffer->driverPrivate = private;
+ buffer->flags = 0; /* not tiled */
+ private->tex = tex;
+
+ return TRUE;
+}
+
+static void
+driDoDestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ BufferPrivatePtr private = buffer->driverPrivate;
+ struct exa_pixmap_priv *exa_priv = exaGetPixmapDriverPrivate(private->pPixmap);
+
+ pipe_texture_reference(&private->tex, NULL);
+ ms->screen->fence_reference(ms->screen, &private->fence, NULL);
+ pipe_texture_reference(&exa_priv->depth_stencil_tex, NULL);
+ (*pScreen->DestroyPixmap)(private->pPixmap);
+}
+
+#if defined(DRI2INFOREC_VERSION) && DRI2INFOREC_VERSION > 2
+
+static DRI2BufferPtr
+driCreateBuffer(DrawablePtr pDraw, unsigned int attachment, unsigned int format)
+{
+ DRI2BufferPtr buffer;
+ BufferPrivatePtr private;
+
+ buffer = xcalloc(1, sizeof *buffer);
+ if (!buffer)
+ return NULL;
+
+ private = xcalloc(1, sizeof *private);
+ if (!private) {
+ goto fail;
+ }
+
+ buffer->attachment = attachment;
+ buffer->driverPrivate = private;
+
+ if (driDoCreateBuffer(pDraw, buffer, format))
+ return buffer;
+
+ xfree(private);
+fail:
+ xfree(buffer);
+ return NULL;
+}
+
+static void
+driDestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
+{
+ driDoDestroyBuffer(pDraw, buffer);
+
+ xfree(buffer->driverPrivate);
+ xfree(buffer);
+}
+
+#else /* DRI2INFOREC_VERSION <= 2 */
+
+static DRI2BufferPtr
+driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
+{
+ BufferPrivatePtr privates;
+ DRI2BufferPtr buffers;
+ int i;
+
+ buffers = xcalloc(count, sizeof *buffers);
+ if (!buffers)
+ goto fail_buffers;
+
+ privates = xcalloc(count, sizeof *privates);
+ if (!privates)
+ goto fail_privates;
+
+ for (i = 0; i < count; i++) {
+ buffers[i].attachment = attachments[i];
+ buffers[i].driverPrivate = &privates[i];
+
+ if (!driDoCreateBuffer(pDraw, &buffers[i], 0))
+ goto fail;
+ }
+
+ return buffers;
+
+fail:
+ xfree(privates);
+fail_privates:
+ xfree(buffers);
+fail_buffers:
+ return NULL;
+}
+
+static void
+driDestroyBuffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ driDoDestroyBuffer(pDraw, &buffers[i]);
+ }
+
+ if (buffers) {
+ xfree(buffers[0].driverPrivate);
+ xfree(buffers);
+ }
+}
+
+#endif /* DRI2INFOREC_VERSION */
+
+static void
+driCopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
+ DRI2BufferPtr pDestBuffer, DRI2BufferPtr pSrcBuffer)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ BufferPrivatePtr dst_priv = pDestBuffer->driverPrivate;
+ BufferPrivatePtr src_priv = pSrcBuffer->driverPrivate;
+ PixmapPtr src_pixmap;
+ PixmapPtr dst_pixmap;
+ GCPtr gc;
+ RegionPtr copy_clip;
+
+ /*
+ * In driCreateBuffers we dewrap windows into the
+ * backing pixmaps in order to get to the texture.
+ * We need to use the real drawable in CopyArea
+ * so that cliprects and offsets are correct.
+ */
+ src_pixmap = src_priv->pPixmap;
+ dst_pixmap = dst_priv->pPixmap;
+ if (pSrcBuffer->attachment == DRI2BufferFrontLeft)
+ src_pixmap = (PixmapPtr)pDraw;
+ if (pDestBuffer->attachment == DRI2BufferFrontLeft)
+ dst_pixmap = (PixmapPtr)pDraw;
+
+ /*
+ * The clients implements glXWaitX with a copy front to fake and then
+ * waiting on the server to signal its completion of it. While
+ * glXWaitGL is a client side flush and a copy from fake to front.
+ * This is how it is done in the DRI2 protocol, how ever depending
+ * which type of drawables the server does things a bit differently
+ * then what the protocol says as the fake and front are the same.
+ *
+ * for pixmaps glXWaitX is a server flush.
+ * for pixmaps glXWaitGL is a client flush.
+ * for windows glXWaitX is a copy from front to fake then a server flush.
+ * for windows glXWaitGL is a client flush then a copy from fake to front.
+ *
+ * XXX in the windows case this code always flushes but that isn't a
+ * must in the glXWaitGL case but we don't know if this is a glXWaitGL
+ * or a glFlush/glFinish call.
+ */
+ if (dst_pixmap == src_pixmap) {
+ /* pixmap glXWaitX */
+ if (pSrcBuffer->attachment == DRI2BufferFrontLeft &&
+ pDestBuffer->attachment == DRI2BufferFakeFrontLeft) {
+ ms->ctx->flush(ms->ctx, PIPE_FLUSH_SWAPBUFFERS, NULL);
+ return;
+ }
+ /* pixmap glXWaitGL */
+ if (pDestBuffer->attachment == DRI2BufferFrontLeft &&
+ pSrcBuffer->attachment == DRI2BufferFakeFrontLeft) {
+ return;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "copying between the same pixmap\n");
+ }
+ }
+
+ gc = GetScratchGC(pDraw->depth, pScreen);
+ copy_clip = REGION_CREATE(pScreen, NULL, 0);
+ REGION_COPY(pScreen, copy_clip, pRegion);
+ (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
+ ValidateGC(&dst_pixmap->drawable, gc);
+
+ /* If this is a full buffer swap, throttle on the previous one */
+ if (dst_priv->fence && REGION_NUM_RECTS(pRegion) == 1) {
+ BoxPtr extents = REGION_EXTENTS(pScreen, pRegion);
+
+ if (extents->x1 == 0 && extents->y1 == 0 &&
+ extents->x2 == pDraw->width && extents->y2 == pDraw->height) {
+ ms->screen->fence_finish(ms->screen, dst_priv->fence, 0);
+ ms->screen->fence_reference(ms->screen, &dst_priv->fence, NULL);
+ }
+ }
+
+ (*gc->ops->CopyArea)(&src_pixmap->drawable, &dst_pixmap->drawable, gc,
+ 0, 0, pDraw->width, pDraw->height, 0, 0);
+
+ FreeScratchGC(gc);
+
+ ms->ctx->flush(ms->ctx, PIPE_FLUSH_SWAPBUFFERS,
+ pDestBuffer->attachment == DRI2BufferFrontLeft ?
+ &dst_priv->fence : NULL);
+}
+
+Bool
+driScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ DRI2InfoRec dri2info;
+
+#if defined(DRI2INFOREC_VERSION)
+ dri2info.version = DRI2INFOREC_VERSION;
+#else
+ dri2info.version = 1;
+#endif
+ dri2info.fd = ms->fd;
+
+ dri2info.driverName = pScrn->driverName;
+ dri2info.deviceName = "/dev/dri/card0"; /* FIXME */
+
+#if defined(DRI2INFOREC_VERSION) && DRI2INFOREC_VERSION > 2
+ dri2info.CreateBuffer = driCreateBuffer;
+ dri2info.DestroyBuffer = driDestroyBuffer;
+#else
+ dri2info.CreateBuffers = driCreateBuffers;
+ dri2info.DestroyBuffers = driDestroyBuffers;
+#endif
+ dri2info.CopyRegion = driCopyRegion;
+ dri2info.Wait = NULL;
+
+ ms->d_depth_bits_last =
+ ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_X8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+ ms->ds_depth_bits_last =
+ ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
+
+ return DRI2ScreenInit(pScreen, &dri2info);
+}
+
+void
+driCloseScreen(ScreenPtr pScreen)
+{
+ DRI2CloseScreen(pScreen);
+}
+
+/* vim: set sw=4 ts=8 sts=4: */
diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c
new file mode 100644
index 0000000000..643b6b3b9e
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_driver.c
@@ -0,0 +1,744 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Author: Alan Hourihane <alanh@tungstengraphics.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ */
+
+
+#include "xorg-server.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "mipointer.h"
+#include "micmap.h"
+#include <X11/extensions/randr.h>
+#include "fb.h"
+#include "edid.h"
+#include "xf86i2c.h"
+#include "xf86Crtc.h"
+#include "miscstruct.h"
+#include "dixstruct.h"
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+#ifndef XSERVER_LIBPCIACCESS
+#error "libpciaccess needed"
+#endif
+
+#include <pciaccess.h>
+
+#include "pipe/p_context.h"
+#include "xorg_tracker.h"
+#include "xorg_winsys.h"
+
+static void AdjustFrame(int scrnIndex, int x, int y, int flags);
+static Bool CloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool EnterVT(int scrnIndex, int flags);
+static Bool SaveHWState(ScrnInfoPtr pScrn);
+static Bool RestoreHWState(ScrnInfoPtr pScrn);
+
+
+static ModeStatus ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose,
+ int flags);
+static void FreeScreen(int scrnIndex, int flags);
+static void LeaveVT(int scrnIndex, int flags);
+static Bool SwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+static Bool ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
+ char **argv);
+static Bool PreInit(ScrnInfoPtr pScrn, int flags);
+
+typedef enum
+{
+ OPTION_SW_CURSOR,
+} modesettingOpts;
+
+static const OptionInfoRec Options[] = {
+ {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
+ {-1, NULL, OPTV_NONE, {0}, FALSE}
+};
+
+/*
+ * Exported Xorg driver functions to winsys
+ */
+
+const OptionInfoRec *
+xorg_tracker_available_options(int chipid, int busid)
+{
+ return Options;
+}
+
+void
+xorg_tracker_set_functions(ScrnInfoPtr scrn)
+{
+ scrn->PreInit = PreInit;
+ scrn->ScreenInit = ScreenInit;
+ scrn->SwitchMode = SwitchMode;
+ scrn->AdjustFrame = AdjustFrame;
+ scrn->EnterVT = EnterVT;
+ scrn->LeaveVT = LeaveVT;
+ scrn->FreeScreen = FreeScreen;
+ scrn->ValidMode = ValidMode;
+}
+
+/*
+ * Static Xorg funtctions
+ */
+
+static Bool
+GetRec(ScrnInfoPtr pScrn)
+{
+ if (pScrn->driverPrivate)
+ return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1);
+
+ return TRUE;
+}
+
+static void
+FreeRec(ScrnInfoPtr pScrn)
+{
+ if (!pScrn)
+ return;
+
+ if (!pScrn->driverPrivate)
+ return;
+
+ xfree(pScrn->driverPrivate);
+
+ pScrn->driverPrivate = NULL;
+}
+
+static void
+ProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ ConfiguredMonitor = NULL;
+}
+
+static Bool
+CreateFrontBuffer(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ ScreenPtr pScreen = pScrn->pScreen;
+ PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ unsigned handle, stride;
+
+ ms->noEvict = TRUE;
+ xorg_exa_set_displayed_usage(rootPixmap);
+ pScreen->ModifyPixmapHeader(rootPixmap,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->depth, pScrn->bitsPerPixel,
+ pScrn->displayWidth * pScrn->bitsPerPixel / 8,
+ NULL);
+ ms->noEvict = FALSE;
+
+ handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
+
+ drmModeAddFB(ms->fd,
+ pScrn->virtualX,
+ pScrn->virtualY,
+ pScrn->depth,
+ pScrn->bitsPerPixel,
+ stride,
+ handle,
+ &ms->fb_id);
+
+ pScrn->frameX0 = 0;
+ pScrn->frameY0 = 0;
+ AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ return TRUE;
+}
+
+static Bool
+crtc_resize(ScrnInfoPtr pScrn, int width, int height)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ //ScreenPtr pScreen = pScrn->pScreen;
+ //PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ //Bool fbAccessDisabled;
+ //CARD8 *fbstart;
+
+ if (width == pScrn->virtualX && height == pScrn->virtualY)
+ return TRUE;
+
+ ErrorF("RESIZING TO %dx%d\n", width, height);
+
+ pScrn->virtualX = width;
+ pScrn->virtualY = height;
+
+ /* HW dependent - FIXME */
+ pScrn->displayWidth = pScrn->virtualX;
+
+ drmModeRmFB(ms->fd, ms->fb_id);
+
+ /* now create new frontbuffer */
+ return CreateFrontBuffer(pScrn);
+}
+
+static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
+ crtc_resize
+};
+
+static Bool
+PreInit(ScrnInfoPtr pScrn, int flags)
+{
+ xf86CrtcConfigPtr xf86_config;
+ modesettingPtr ms;
+ rgb defaultWeight = { 0, 0, 0 };
+ EntityInfoPtr pEnt;
+ EntPtr msEnt = NULL;
+ char *BusID;
+ int max_width, max_height;
+
+ if (pScrn->numEntities != 1)
+ return FALSE;
+
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+
+ if (flags & PROBE_DETECT) {
+ ProbeDDC(pScrn, pEnt->index);
+ return TRUE;
+ }
+
+ /* Allocate driverPrivate */
+ if (!GetRec(pScrn))
+ return FALSE;
+
+ ms = modesettingPTR(pScrn);
+ ms->SaveGeneration = -1;
+ ms->pEnt = pEnt;
+
+ pScrn->displayWidth = 640; /* default it */
+
+ if (ms->pEnt->location.type != BUS_PCI)
+ return FALSE;
+
+ ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
+
+ /* Allocate an entity private if necessary */
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ FatalError("Entity");
+#if 0
+ msEnt = xf86GetEntityPrivate(pScrn->entityList[0],
+ modesettingEntityIndex)->ptr;
+ ms->entityPrivate = msEnt;
+#else
+ (void)msEnt;
+#endif
+ } else
+ ms->entityPrivate = NULL;
+
+ if (xf86IsEntityShared(pScrn->entityList[0])) {
+ if (xf86IsPrimInitDone(pScrn->entityList[0])) {
+ /* do something */
+ } else {
+ xf86SetPrimInitDone(pScrn->entityList[0]);
+ }
+ }
+
+ BusID = xalloc(64);
+ sprintf(BusID, "PCI:%d:%d:%d",
+ ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
+ ms->PciInfo->dev, ms->PciInfo->func
+ );
+
+ ms->api = drm_api_create();
+ ms->fd = drmOpen(NULL, BusID);
+
+ if (ms->fd < 0)
+ return FALSE;
+
+ pScrn->monitor = pScrn->confScreen->monitor;
+ pScrn->progClock = TRUE;
+ pScrn->rgbBits = 8;
+
+ if (!xf86SetDepthBpp
+ (pScrn, 0, 0, 0,
+ PreferConvert24to32 | SupportConvert24to32 | Support32bppFb))
+ return FALSE;
+
+ switch (pScrn->depth) {
+ case 15:
+ case 16:
+ case 24:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by the driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ xf86PrintDepthBpp(pScrn);
+
+ if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
+ return FALSE;
+ if (!xf86SetDefaultVisual(pScrn, -1))
+ return FALSE;
+
+ /* Process the options */
+ xf86CollectOptions(pScrn, NULL);
+ if (!(ms->Options = xalloc(sizeof(Options))))
+ return FALSE;
+ memcpy(ms->Options, Options, sizeof(Options));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);
+
+ /* Allocate an xf86CrtcConfig */
+ xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
+ xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+ max_width = 8192;
+ max_height = 8192;
+ xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height);
+
+ if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) {
+ ms->SWCursor = TRUE;
+ }
+
+ SaveHWState(pScrn);
+
+ crtc_init(pScrn);
+ output_init(pScrn);
+
+ if (!xf86InitialConfiguration(pScrn, TRUE)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
+ RestoreHWState(pScrn);
+ return FALSE;
+ }
+
+ RestoreHWState(pScrn);
+
+ /*
+ * If the driver can do gamma correction, it should call xf86SetGamma() here.
+ */
+ {
+ Gamma zeros = { 0.0, 0.0, 0.0 };
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ return FALSE;
+ }
+ }
+
+ if (pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
+ return FALSE;
+ }
+
+ pScrn->currentMode = pScrn->modes;
+
+ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+ /* Load the required sub modules */
+ if (!xf86LoadSubModule(pScrn, "fb")) {
+ return FALSE;
+ }
+
+ xf86LoadSubModule(pScrn, "exa");
+
+#ifdef DRI2
+ xf86LoadSubModule(pScrn, "dri2");
+#endif
+
+ return TRUE;
+}
+
+static Bool
+SaveHWState(ScrnInfoPtr pScrn)
+{
+ /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/
+
+ return TRUE;
+}
+
+static Bool
+RestoreHWState(ScrnInfoPtr pScrn)
+{
+ /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/
+
+ return TRUE;
+}
+
+static void xorgBlockHandler(int i, pointer blockData, pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]);
+
+ pScreen->BlockHandler = ms->blockHandler;
+ pScreen->BlockHandler(i, blockData, pTimeout, pReadmask);
+ pScreen->BlockHandler = xorgBlockHandler;
+
+ ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ {
+ RegionPtr dirty = DamageRegion(ms->damage);
+ unsigned num_cliprects = REGION_NUM_RECTS(dirty);
+
+ if (num_cliprects) {
+ drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip));
+ BoxPtr rect = REGION_RECTS(dirty);
+ int i;
+
+ for (i = 0; i < num_cliprects; i++, rect++) {
+ clip[i].x = rect->x1;
+ clip[i].y = rect->y1;
+ clip[i].width = rect->x2 - rect->x1;
+ clip[i].height = rect->y2 - rect->y1;
+ }
+
+ /* TODO query connector property to see if this is needed */
+ drmModeDirtyFB(ms->fd, ms->fb_id, clip, num_cliprects);
+
+ DamageEmpty(ms->damage);
+ }
+ }
+#endif
+}
+
+static Bool
+CreateScreenResources(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ PixmapPtr rootPixmap;
+ Bool ret;
+ unsigned handle, stride;
+
+ ms->noEvict = TRUE;
+
+ pScreen->CreateScreenResources = ms->createScreenResources;
+ ret = pScreen->CreateScreenResources(pScreen);
+ pScreen->CreateScreenResources = CreateScreenResources;
+
+ rootPixmap = pScreen->GetScreenPixmap(pScreen);
+
+ xorg_exa_set_displayed_usage(rootPixmap);
+ xorg_exa_set_shared_usage(rootPixmap);
+ if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL))
+ FatalError("Couldn't adjust screen pixmap\n");
+
+ ms->noEvict = FALSE;
+
+ handle = xorg_exa_get_pixmap_handle(rootPixmap, &stride);
+
+ drmModeAddFB(ms->fd,
+ pScrn->virtualX,
+ pScrn->virtualY,
+ pScrn->depth,
+ pScrn->bitsPerPixel,
+ stride,
+ handle,
+ &ms->fb_id);
+
+ AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
+ pScreen, rootPixmap);
+
+ if (ms->damage) {
+ DamageRegister(&rootPixmap->drawable, ms->damage);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to create screen damage record\n");
+ return FALSE;
+ }
+#endif
+
+ return ret;
+}
+
+static Bool
+ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ VisualPtr visual;
+
+ /* deal with server regeneration */
+ if (ms->fd < 0) {
+ char *BusID;
+
+ BusID = xalloc(64);
+ sprintf(BusID, "PCI:%d:%d:%d",
+ ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
+ ms->PciInfo->dev, ms->PciInfo->func
+ );
+
+ ms->fd = drmOpen(NULL, BusID);
+
+ if (ms->fd < 0)
+ return FALSE;
+ }
+
+ if (!ms->screen) {
+ ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL);
+
+ if (!ms->screen) {
+ FatalError("Could not init pipe_screen\n");
+ return FALSE;
+ }
+ }
+
+ pScrn->pScreen = pScreen;
+
+ /* HW dependent - FIXME */
+ pScrn->displayWidth = pScrn->virtualX;
+
+ miClearVisualTypes();
+
+ if (!miSetVisualTypes(pScrn->depth,
+ miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+
+ if (!miSetPixmapDepths())
+ return FALSE;
+
+ pScrn->memPhysBase = 0;
+ pScrn->fbOffset = 0;
+
+ if (!fbScreenInit(pScreen, NULL,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth, pScrn->bitsPerPixel))
+ return FALSE;
+
+ if (pScrn->bitsPerPixel > 8) {
+ /* Fixup RGB ordering */
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+ fbPictureInit(pScreen, NULL, 0);
+
+ ms->blockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = xorgBlockHandler;
+ ms->createScreenResources = pScreen->CreateScreenResources;
+ pScreen->CreateScreenResources = CreateScreenResources;
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ ms->exa = xorg_exa_init(pScrn);
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ /* Need to extend HWcursor support to handle mask interleave */
+ if (!ms->SWCursor)
+ xf86_cursors_init(pScreen, 64, 64,
+ HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
+ HARDWARE_CURSOR_ARGB);
+
+ /* Must force it before EnterVT, so we are in control of VT and
+ * later memory should be bound when allocating, e.g rotate_mem */
+ pScrn->vtSema = TRUE;
+
+ pScreen->SaveScreen = xf86SaveScreen;
+ ms->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = CloseScreen;
+
+ if (!xf86CrtcScreenInit(pScreen))
+ return FALSE;
+
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+
+ xf86DPMSInit(pScreen, xf86DPMSSet, 0);
+
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+#if 1
+#ifdef DRI2
+ driScreenInit(pScreen);
+#endif
+#endif
+
+ return EnterVT(scrnIndex, 1);
+}
+
+static void
+AdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86OutputPtr output = config->output[config->compat_output];
+ xf86CrtcPtr crtc = output->crtc;
+
+ if (crtc && crtc->enabled) {
+ crtc->funcs->mode_set(crtc, pScrn->currentMode, pScrn->currentMode, x,
+ y);
+ crtc->x = output->initial_x + x;
+ crtc->y = output->initial_y + y;
+ }
+}
+
+static void
+FreeScreen(int scrnIndex, int flags)
+{
+ FreeRec(xf86Screens[scrnIndex]);
+}
+
+static void
+LeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int o;
+
+ for (o = 0; o < config->num_crtc; o++) {
+ xf86CrtcPtr crtc = config->crtc[o];
+
+ crtc_cursor_destroy(crtc);
+
+ if (crtc->rotatedPixmap || crtc->rotatedData) {
+ crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
+ crtc->rotatedData);
+ crtc->rotatedPixmap = NULL;
+ crtc->rotatedData = NULL;
+ }
+ }
+
+ drmModeRmFB(ms->fd, ms->fb_id);
+
+ RestoreHWState(pScrn);
+
+ if (drmDropMaster(ms->fd))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "drmDropMaster failed: %s\n", strerror(errno));
+
+ pScrn->vtSema = FALSE;
+}
+
+/*
+ * This gets called when gaining control of the VT, and from ScreenInit().
+ */
+static Bool
+EnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ if (drmSetMaster(ms->fd)) {
+ if (errno == EINVAL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "drmSetMaster failed: 2.6.29 or newer kernel required for "
+ "multi-server DRI\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "drmSetMaster failed: %s\n", strerror(errno));
+ }
+ }
+
+ /*
+ * Only save state once per server generation since that's what most
+ * drivers do. Could change this to save state at each VT enter.
+ */
+ if (ms->SaveGeneration != serverGeneration) {
+ ms->SaveGeneration = serverGeneration;
+ SaveHWState(pScrn);
+ }
+
+ if (!flags) /* signals startup as we'll do this in CreateScreenResources */
+ CreateFrontBuffer(pScrn);
+
+ if (!xf86SetDesiredModes(pScrn))
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+ return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
+}
+
+static Bool
+CloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ if (pScrn->vtSema) {
+ LeaveVT(scrnIndex, 0);
+ }
+#ifdef DRI2
+ driCloseScreen(pScreen);
+#endif
+
+ pScreen->BlockHandler = ms->blockHandler;
+ pScreen->CreateScreenResources = ms->createScreenResources;
+
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ if (ms->damage) {
+ DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage);
+ DamageDestroy(ms->damage);
+ ms->damage = NULL;
+ }
+#endif
+
+ if (ms->exa)
+ xorg_exa_close(pScrn);
+
+ ms->api->destroy(ms->api);
+ ms->api = NULL;
+ drmClose(ms->fd);
+ ms->fd = -1;
+
+ pScrn->vtSema = FALSE;
+ pScreen->CloseScreen = ms->CloseScreen;
+ return (*pScreen->CloseScreen) (scrnIndex, pScreen);
+}
+
+static ModeStatus
+ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
+{
+ return MODE_OK;
+}
+
+/* vim: set sw=4 ts=8 sts=4: */
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
new file mode 100644
index 0000000000..312dab1544
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Author: Alan Hourihane <alanh@tungstengraphics.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ */
+
+#include "xorg_exa.h"
+#include "xorg_tracker.h"
+#include "xorg_composite.h"
+#include "xorg_exa_tgsi.h"
+
+#include <xorg-server.h>
+#include <xf86.h>
+#include <picturestr.h>
+#include <picture.h>
+
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "cso_cache/cso_context.h"
+
+#include "util/u_rect.h"
+
+/*
+ * Helper functions
+ */
+
+static void
+exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp)
+{
+ switch (depth) {
+ case 32:
+ *format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ assert(*bbp == 32);
+ break;
+ case 24:
+ *format = PIPE_FORMAT_X8R8G8B8_UNORM;
+ assert(*bbp == 32);
+ break;
+ case 16:
+ *format = PIPE_FORMAT_R5G6B5_UNORM;
+ assert(*bbp == 16);
+ break;
+ case 15:
+ *format = PIPE_FORMAT_A1R5G5B5_UNORM;
+ assert(*bbp == 16);
+ break;
+ case 8:
+ case 4:
+ case 1:
+ *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static void
+xorg_exa_init_state(struct exa_context *exa)
+{
+ struct pipe_depth_stencil_alpha_state dsa;
+
+ /* set common initial clip state */
+ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
+ cso_set_depth_stencil_alpha(exa->cso, &dsa);
+}
+
+static void
+xorg_exa_common_done(struct exa_context *exa)
+{
+ exa->copy.src = NULL;
+ exa->copy.dst = NULL;
+ exa->has_solid_color = FALSE;
+ exa->num_bound_samplers = 0;
+}
+
+/*
+ * Static exported EXA functions
+ */
+
+static void
+ExaWaitMarker(ScreenPtr pScreen, int marker)
+{
+}
+
+static int
+ExaMarkSync(ScreenPtr pScreen)
+{
+ return 1;
+}
+
+static Bool
+ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst,
+ int dst_pitch)
+{
+ ScreenPtr pScreen = pPix->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
+ struct pipe_transfer *transfer;
+
+ if (!priv || !priv->tex)
+ return FALSE;
+
+ if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
+ PIPE_REFERENCED_FOR_WRITE)
+ exa->pipe->flush(exa->pipe, 0, NULL);
+
+ transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
+ PIPE_TRANSFER_READ, x, y, w, h);
+ if (!transfer)
+ return FALSE;
+
+ util_copy_rect((unsigned char*)dst, &priv->tex->block, dst_pitch, 0, 0,
+ w, h, exa->scrn->transfer_map(exa->scrn, transfer),
+ transfer->stride, 0, 0);
+
+ exa->scrn->transfer_unmap(exa->scrn, transfer);
+ exa->scrn->tex_transfer_destroy(transfer);
+
+ return TRUE;
+}
+
+static Bool
+ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src,
+ int src_pitch)
+{
+ ScreenPtr pScreen = pPix->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPix);
+ struct pipe_transfer *transfer;
+
+ if (!priv || !priv->tex)
+ return FALSE;
+
+ transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
+ PIPE_TRANSFER_WRITE, x, y, w, h);
+ if (!transfer)
+ return FALSE;
+
+ util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
+ &priv->tex->block, transfer->stride, 0, 0, w, h,
+ (unsigned char*)src, src_pitch, 0, 0);
+
+ exa->scrn->transfer_unmap(exa->scrn, transfer);
+ exa->scrn->tex_transfer_destroy(transfer);
+
+ return TRUE;
+}
+
+static Bool
+ExaPrepareAccess(PixmapPtr pPix, int index)
+{
+ ScreenPtr pScreen = pPix->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv;
+
+ priv = exaGetPixmapDriverPrivate(pPix);
+
+ if (!priv)
+ return FALSE;
+
+ if (!priv->tex)
+ return FALSE;
+
+ if (priv->map_count++ == 0)
+ {
+ if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) &
+ PIPE_REFERENCED_FOR_WRITE)
+ exa->pipe->flush(exa->pipe, 0, NULL);
+
+ priv->map_transfer =
+ exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0,
+ PIPE_TRANSFER_READ_WRITE,
+ 0, 0, priv->tex->width[0], priv->tex->height[0]);
+
+ pPix->devPrivate.ptr =
+ exa->scrn->transfer_map(exa->scrn, priv->map_transfer);
+ pPix->devKind = priv->map_transfer->stride;
+ }
+
+ return TRUE;
+}
+
+static void
+ExaFinishAccess(PixmapPtr pPix, int index)
+{
+ ScreenPtr pScreen = pPix->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv;
+ priv = exaGetPixmapDriverPrivate(pPix);
+
+ if (!priv)
+ return;
+
+ if (!priv->map_transfer)
+ return;
+
+ if (--priv->map_count == 0) {
+ assert(priv->map_transfer);
+ exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer);
+ exa->scrn->tex_transfer_destroy(priv->map_transfer);
+ priv->map_transfer = NULL;
+ pPix->devPrivate.ptr = NULL;
+ }
+}
+
+static void
+ExaDone(PixmapPtr pPixmap)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+ struct exa_context *exa = ms->exa;
+
+ if (!priv)
+ return;
+
+#if 1
+ xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL);
+#else
+ xorg_finish(exa);
+#endif
+ xorg_exa_common_done(exa);
+}
+
+static void
+ExaDoneComposite(PixmapPtr pPixmap)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+
+ xorg_exa_common_done(exa);
+}
+
+static Bool
+ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+ struct exa_context *exa = ms->exa;
+
+ debug_printf("ExaPrepareSolid - test\n");
+ if (pPixmap->drawable.depth < 15)
+ return FALSE;
+
+ if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
+ return FALSE;
+
+ if (!priv || !priv->tex)
+ return FALSE;
+
+ if (alu != GXcopy)
+ return FALSE;
+
+ if (!exa->pipe)
+ return FALSE;
+
+ debug_printf(" ExaPrepareSolid(0x%x)\n", fg);
+ return xorg_solid_bind_state(exa, priv, fg);
+}
+
+static void
+ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ debug_printf("\tExaSolid(%d, %d, %d, %d)\n", x0, y0, x1, y1);
+
+#if 0
+ if (x0 == 0 && y0 == 0 &&
+ x1 == priv->tex->width[0] &&
+ y1 == priv->tex->height[0]) {
+ exa->ctx->clear(exa->ctx, PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
+ exa->solid_color, 1., 0);
+ } else
+#endif
+ xorg_solid(exa, priv, x0, y0, x1, y1) ;
+}
+
+static Bool
+ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
+ int ydir, int alu, Pixel planeMask)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+ struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
+
+ debug_printf("ExaPrepareCopy\n");
+
+ if (alu != GXcopy)
+ return FALSE;
+
+ if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15)
+ return FALSE;
+
+ if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
+ return FALSE;
+
+ if (!priv || !src_priv)
+ return FALSE;
+
+ if (!priv->tex || !src_priv->tex)
+ return FALSE;
+
+ if (!exa->pipe)
+ return FALSE;
+
+ exa->copy.src = src_priv;
+ exa->copy.dst = priv;
+
+ /*XXX disabled until some issues with syncing are fixed */
+ return FALSE;
+}
+
+static void
+ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
+ int width, int height)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+
+ debug_printf("\tExaCopy(srcx=%d, srcy=%d, dstX=%d, dstY=%d, w=%d, h=%d)\n",
+ srcX, srcY, dstX, dstY, width, height);
+
+ debug_assert(priv == exa->copy.dst);
+
+ xorg_copy_pixmap(exa, exa->copy.dst, dstX, dstY,
+ exa->copy.src, srcX, srcY,
+ width, height);
+}
+
+static Bool
+ExaPrepareComposite(int op, PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture, PicturePtr pDstPicture,
+ PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+
+ debug_printf("ExaPrepareComposite\n");
+
+ return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture,
+ pDstPicture,
+ exaGetPixmapDriverPrivate(pSrc),
+ exaGetPixmapDriverPrivate(pMask),
+ exaGetPixmapDriverPrivate(pDst));
+}
+
+static void
+ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst);
+
+ debug_printf("\tExaComposite\n");
+
+ xorg_composite(exa, priv, srcX, srcY, maskX, maskY,
+ dstX, dstY, width, height);
+}
+
+static Bool
+ExaCheckComposite(int op,
+ PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ return xorg_composite_accelerated(op,
+ pSrcPicture,
+ pMaskPicture,
+ pDstPicture);
+}
+
+static void *
+ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
+{
+ struct exa_pixmap_priv *priv;
+
+ priv = xcalloc(1, sizeof(struct exa_pixmap_priv));
+ if (!priv)
+ return NULL;
+
+ return priv;
+}
+
+static void
+ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
+{
+ struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+
+ if (!priv)
+ return;
+
+ if (priv->tex)
+ ms->screen->texture_destroy(priv->tex);
+
+ xfree(priv);
+}
+
+static Bool
+ExaPixmapIsOffscreen(PixmapPtr pPixmap)
+{
+ struct exa_pixmap_priv *priv;
+
+ priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ if (!priv)
+ return FALSE;
+
+ if (priv->tex)
+ return TRUE;
+
+ return FALSE;
+}
+
+int
+xorg_exa_set_displayed_usage(PixmapPtr pPixmap)
+{
+ struct exa_pixmap_priv *priv;
+ priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ if (!priv) {
+ FatalError("NO PIXMAP PRIVATE\n");
+ return 0;
+ }
+
+ priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY;
+
+ return 0;
+}
+
+int
+xorg_exa_set_shared_usage(PixmapPtr pPixmap)
+{
+ struct exa_pixmap_priv *priv;
+ priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ if (!priv) {
+ FatalError("NO PIXMAP PRIVATE\n");
+ return 0;
+ }
+
+ priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+
+ return 0;
+}
+
+unsigned
+xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride_out)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_pixmap_priv *priv;
+ unsigned handle;
+ unsigned stride;
+
+ if (!ms->exa) {
+ FatalError("NO MS->EXA\n");
+ return 0;
+ }
+
+ priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ if (!priv) {
+ FatalError("NO PIXMAP PRIVATE\n");
+ return 0;
+ }
+
+ ms->api->local_handle_from_texture(ms->api, ms->screen, priv->tex, &stride, &handle);
+ if (stride_out)
+ *stride_out = stride;
+
+ return handle;
+}
+
+static Bool
+ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
+ int depth, int bitsPerPixel, int devKind,
+ pointer pPixData)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+
+ if (!priv || pPixData)
+ return FALSE;
+
+ if (depth <= 0)
+ depth = pPixmap->drawable.depth;
+
+ if (bitsPerPixel <= 0)
+ bitsPerPixel = pPixmap->drawable.bitsPerPixel;
+
+ if (width <= 0)
+ width = pPixmap->drawable.width;
+
+ if (height <= 0)
+ height = pPixmap->drawable.height;
+
+ if (width <= 0 || height <= 0 || depth <= 0)
+ return FALSE;
+
+ miModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, NULL);
+
+ /* Deal with screen resize */
+ if (!priv->tex ||
+ (priv->tex->width[0] != width ||
+ priv->tex->height[0] != height ||
+ priv->tex_flags != priv->flags)) {
+ struct pipe_texture *texture = NULL;
+
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ if (priv->flags)
+#endif
+ {
+ struct pipe_texture template;
+
+ memset(&template, 0, sizeof(template));
+ template.target = PIPE_TEXTURE_2D;
+ exa_get_pipe_format(depth, &template.format, &bitsPerPixel);
+ pf_get_block(template.format, &template.block);
+ template.width[0] = width;
+ template.height[0] = height;
+ template.depth[0] = 1;
+ template.last_level = 0;
+ template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags;
+ priv->tex_flags = priv->flags;
+ texture = exa->scrn->texture_create(exa->scrn, &template);
+
+ if (priv->tex) {
+ struct pipe_surface *dst_surf;
+ struct pipe_surface *src_surf;
+
+ dst_surf = exa->scrn->get_tex_surface(exa->scrn, texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ src_surf = exa_gpu_surface(exa, priv);
+ exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf,
+ 0, 0, min(width, texture->width[0]),
+ min(height, texture->height[0]));
+ exa->scrn->tex_surface_destroy(dst_surf);
+ exa->scrn->tex_surface_destroy(src_surf);
+ } else if (pPixmap->devPrivate.ptr) {
+ struct pipe_transfer *transfer;
+
+ if (priv->map_count != 0)
+ FatalError("doing ExaModifyPixmapHeader on mapped buffer\n");
+
+ transfer =
+ exa->scrn->get_tex_transfer(exa->scrn, texture, 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ 0, 0, width, height);
+ util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer),
+ &texture->block, transfer->stride, 0, 0,
+ width, height, pPixmap->devPrivate.ptr,
+ pPixmap->devKind, 0, 0);
+ exa->scrn->transfer_unmap(exa->scrn, transfer);
+ exa->scrn->tex_transfer_destroy(transfer);
+
+ xfree(pPixmap->devPrivate.ptr);
+ pPixmap->devPrivate.ptr = NULL;
+ }
+ }
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ else {
+ xfree(pPixmap->devPrivate.ptr);
+ pPixmap->devPrivate.ptr = xalloc(pPixmap->drawable.height *
+ pPixmap->devKind);
+ }
+#endif
+
+ pipe_texture_reference(&priv->tex, texture);
+ }
+
+ return TRUE;
+}
+
+struct pipe_texture *
+xorg_exa_get_texture(PixmapPtr pPixmap)
+{
+ struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap);
+ struct pipe_texture *tex = NULL;
+ pipe_texture_reference(&tex, priv->tex);
+ return tex;
+}
+
+void
+xorg_exa_close(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa = ms->exa;
+ struct pipe_constant_buffer *vsbuf = &exa->vs_const_buffer;
+ struct pipe_constant_buffer *fsbuf = &exa->fs_const_buffer;
+
+ if (exa->shaders) {
+ xorg_shaders_destroy(exa->shaders);
+ }
+
+ if (vsbuf && vsbuf->buffer)
+ pipe_buffer_reference(&vsbuf->buffer, NULL);
+
+ if (fsbuf && fsbuf->buffer)
+ pipe_buffer_reference(&fsbuf->buffer, NULL);
+
+ if (exa->cso) {
+ cso_release_all(exa->cso);
+ cso_destroy_context(exa->cso);
+ }
+
+ if (exa->pipe)
+ exa->pipe->destroy(exa->pipe);
+
+ exaDriverFini(pScrn->pScreen);
+ xfree(exa);
+ ms->exa = NULL;
+}
+
+void *
+xorg_exa_init(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ struct exa_context *exa;
+ ExaDriverPtr pExa;
+
+ exa = xcalloc(1, sizeof(struct exa_context));
+ if (!exa)
+ return NULL;
+
+ pExa = exaDriverAlloc();
+ if (!pExa) {
+ goto out_err;
+ }
+
+ memset(pExa, 0, sizeof(*pExa));
+
+ pExa->exa_major = 2;
+ pExa->exa_minor = 2;
+ pExa->memoryBase = 0;
+ pExa->memorySize = 0;
+ pExa->offScreenBase = 0;
+ pExa->pixmapOffsetAlign = 0;
+ pExa->pixmapPitchAlign = 1;
+ pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
+#ifdef EXA_SUPPORTS_PREPARE_AUX
+ pExa->flags |= EXA_SUPPORTS_PREPARE_AUX;
+#endif
+#ifdef EXA_MIXED_PIXMAPS
+ pExa->flags |= EXA_MIXED_PIXMAPS;
+#endif
+ pExa->maxX = 8191; /* FIXME */
+ pExa->maxY = 8191; /* FIXME */
+
+ pExa->WaitMarker = ExaWaitMarker;
+ pExa->MarkSync = ExaMarkSync;
+ pExa->PrepareSolid = ExaPrepareSolid;
+ pExa->Solid = ExaSolid;
+ pExa->DoneSolid = ExaDone;
+ pExa->PrepareCopy = ExaPrepareCopy;
+ pExa->Copy = ExaCopy;
+ pExa->DoneCopy = ExaDone;
+ pExa->CheckComposite = ExaCheckComposite;
+ pExa->PrepareComposite = ExaPrepareComposite;
+ pExa->Composite = ExaComposite;
+ pExa->DoneComposite = ExaDoneComposite;
+ pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
+ pExa->DownloadFromScreen = ExaDownloadFromScreen;
+ pExa->UploadToScreen = ExaUploadToScreen;
+ pExa->PrepareAccess = ExaPrepareAccess;
+ pExa->FinishAccess = ExaFinishAccess;
+ pExa->CreatePixmap = ExaCreatePixmap;
+ pExa->DestroyPixmap = ExaDestroyPixmap;
+ pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
+
+ if (!exaDriverInit(pScrn->pScreen, pExa)) {
+ goto out_err;
+ }
+
+ exa->scrn = ms->screen;
+ exa->pipe = ms->api->create_context(ms->api, exa->scrn);
+ /* Share context with DRI */
+ ms->ctx = exa->pipe;
+
+ exa->cso = cso_create_context(exa->pipe);
+ exa->shaders = xorg_shaders_create(exa);
+
+ xorg_exa_init_state(exa);
+
+ return (void *)exa;
+
+out_err:
+ xorg_exa_close(pScrn);
+
+ return NULL;
+}
+
+struct pipe_surface *
+exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv)
+{
+ return exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+}
+
+void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence)
+{
+ exa->pipe->flush(exa->pipe, pipeFlushFlags, fence);
+}
+
+void xorg_exa_finish(struct exa_context *exa)
+{
+ struct pipe_fence_handle *fence = NULL;
+
+ xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, &fence);
+
+ exa->pipe->screen->fence_finish(exa->pipe->screen, fence, 0);
+ exa->pipe->screen->fence_reference(exa->pipe->screen, &fence, NULL);
+}
+
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h
new file mode 100644
index 0000000000..43949b04a4
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_exa.h
@@ -0,0 +1,57 @@
+#ifndef XORG_EXA_H
+#define XORG_EXA_H
+
+#include "xorg_tracker.h"
+
+#include <pipe/p_state.h>
+
+struct cso_context;
+struct xorg_shaders;
+
+/* src + mask + dst */
+#define MAX_EXA_SAMPLERS 3
+
+struct exa_context
+{
+ ExaDriverPtr pExa;
+ struct pipe_context *pipe;
+ struct pipe_screen *scrn;
+ struct cso_context *cso;
+ struct xorg_shaders *shaders;
+
+ struct pipe_constant_buffer vs_const_buffer;
+ struct pipe_constant_buffer fs_const_buffer;
+
+ struct pipe_texture *bound_textures[MAX_EXA_SAMPLERS];
+ int num_bound_samplers;
+
+ float solid_color[4];
+ boolean has_solid_color;
+
+ struct {
+ struct exa_pixmap_priv *src;
+ struct exa_pixmap_priv *dst;
+ } copy;
+};
+
+
+struct exa_pixmap_priv
+{
+ int flags;
+ int tex_flags;
+
+ struct pipe_texture *tex;
+ struct pipe_texture *depth_stencil_tex;
+
+ struct pipe_transfer *map_transfer;
+ unsigned map_count;
+};
+
+struct pipe_surface *
+exa_gpu_surface(struct exa_context *exa, struct exa_pixmap_priv *priv);
+
+void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence);
+void xorg_exa_finish(struct exa_context *exa);
+
+#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
new file mode 100644
index 0000000000..694eded09a
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c
@@ -0,0 +1,489 @@
+#include "xorg_exa_tgsi.h"
+
+/*### stupidity defined in X11/extensions/XI.h */
+#undef Absolute
+
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_memory.h"
+#include "util/u_simple_shaders.h"
+
+#include "tgsi/tgsi_ureg.h"
+
+#include "cso_cache/cso_context.h"
+#include "cso_cache/cso_hash.h"
+
+/* Vertex shader:
+ * IN[0] = vertex pos
+ * IN[1] = src tex coord | solid fill color
+ * IN[2] = mask tex coord
+ * IN[3] = dst tex coord
+ * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
+ * CONST[1] = (-1, -1, 0, 0)
+ *
+ * OUT[0] = vertex pos
+ * OUT[1] = src tex coord | solid fill color
+ * OUT[2] = mask tex coord
+ * OUT[3] = dst tex coord
+ */
+
+/* Fragment shader:
+ * SAMP[0] = src
+ * SAMP[1] = mask
+ * SAMP[2] = dst
+ * IN[0] = pos src | solid fill color
+ * IN[1] = pos mask
+ * IN[2] = pos dst
+ * CONST[0] = (0, 0, 0, 1)
+ *
+ * OUT[0] = color
+ */
+
+struct xorg_shaders {
+ struct exa_context *exa;
+
+ struct cso_hash *vs_hash;
+ struct cso_hash *fs_hash;
+};
+
+static const char over_op[] =
+ "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n"
+ "MUL TEMP[3], TEMP[0], TEMP[3]\n"
+ "ADD TEMP[0], TEMP[3], TEMP[0]\n";
+
+
+static INLINE void
+create_preamble(struct ureg_program *ureg)
+{
+}
+
+
+static INLINE void
+src_in_mask(struct ureg_program *ureg,
+ struct ureg_dst dst,
+ struct ureg_src src,
+ struct ureg_src mask)
+{
+ /* MUL dst, src, mask.wwww */
+ ureg_MUL(ureg, dst, src,
+ ureg_scalar(mask, TGSI_SWIZZLE_W));
+}
+
+static struct ureg_src
+vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords,
+ struct ureg_src const0, struct ureg_src const1)
+{
+ struct ureg_dst tmp = ureg_DECL_temporary(ureg);
+ struct ureg_src ret;
+ ureg_MUL(ureg, tmp, coords, const0);
+ ureg_ADD(ureg, tmp, ureg_src(tmp), const1);
+ ret = ureg_src(tmp);
+ ureg_release_temporary(ureg, tmp);
+ return ret;
+}
+
+static void
+linear_gradient(struct ureg_program *ureg,
+ struct ureg_dst out,
+ struct ureg_src pos,
+ struct ureg_src sampler,
+ struct ureg_src coords,
+ struct ureg_src const0124,
+ struct ureg_src matrow0,
+ struct ureg_src matrow1,
+ struct ureg_src matrow2)
+{
+ struct ureg_dst temp0 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp1 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp2 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp3 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp4 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp5 = ureg_DECL_temporary(ureg);
+
+ ureg_MOV(ureg,
+ ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos);
+ ureg_MOV(ureg,
+ ureg_writemask(temp0, TGSI_WRITEMASK_Z),
+ ureg_scalar(const0124, TGSI_SWIZZLE_Y));
+
+ ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0));
+ ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0));
+ ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0));
+ ureg_RCP(ureg, temp3, ureg_src(temp3));
+ ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3));
+ ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3));
+
+ ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_X),
+ ureg_src(temp1));
+ ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_Y),
+ ureg_src(temp2));
+
+ ureg_MUL(ureg, temp0,
+ ureg_scalar(coords, TGSI_SWIZZLE_Y),
+ ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_Y));
+ ureg_MAD(ureg, temp1,
+ ureg_scalar(coords, TGSI_SWIZZLE_X),
+ ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_X),
+ ureg_src(temp0));
+
+ ureg_MUL(ureg, temp2,
+ ureg_src(temp1),
+ ureg_scalar(coords, TGSI_SWIZZLE_Z));
+
+ ureg_TEX(ureg, out,
+ TGSI_TEXTURE_1D, ureg_src(temp2), sampler);
+
+ ureg_release_temporary(ureg, temp0);
+ ureg_release_temporary(ureg, temp1);
+ ureg_release_temporary(ureg, temp2);
+ ureg_release_temporary(ureg, temp3);
+ ureg_release_temporary(ureg, temp4);
+ ureg_release_temporary(ureg, temp5);
+}
+
+
+static void
+radial_gradient(struct ureg_program *ureg,
+ struct ureg_dst out,
+ struct ureg_src pos,
+ struct ureg_src sampler,
+ struct ureg_src coords,
+ struct ureg_src const0124,
+ struct ureg_src matrow0,
+ struct ureg_src matrow1,
+ struct ureg_src matrow2)
+{
+ struct ureg_dst temp0 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp1 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp2 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp3 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp4 = ureg_DECL_temporary(ureg);
+ struct ureg_dst temp5 = ureg_DECL_temporary(ureg);
+
+ ureg_MOV(ureg,
+ ureg_writemask(temp0, TGSI_WRITEMASK_XY),
+ pos);
+ ureg_MOV(ureg,
+ ureg_writemask(temp0, TGSI_WRITEMASK_Z),
+ ureg_scalar(const0124, TGSI_SWIZZLE_Y));
+
+ ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0));
+ ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0));
+ ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0));
+ ureg_RCP(ureg, temp3, ureg_src(temp3));
+ ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3));
+ ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3));
+
+ ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_X),
+ ureg_src(temp1));
+ ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_Y),
+ ureg_src(temp2));
+
+ ureg_MUL(ureg, temp0, ureg_scalar(coords, TGSI_SWIZZLE_Y),
+ ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y));
+ ureg_MAD(ureg, temp1,
+ ureg_scalar(coords, TGSI_SWIZZLE_X),
+ ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X),
+ ureg_src(temp0));
+ ureg_ADD(ureg, temp1,
+ ureg_src(temp1), ureg_src(temp1));
+ ureg_MUL(ureg, temp3,
+ ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y),
+ ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y));
+ ureg_MAD(ureg, temp4,
+ ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X),
+ ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X),
+ ureg_src(temp3));
+ ureg_MOV(ureg, temp4, ureg_negate(ureg_src(temp4)));
+ ureg_MUL(ureg, temp2,
+ ureg_scalar(coords, TGSI_SWIZZLE_Z),
+ ureg_src(temp4));
+ ureg_MUL(ureg, temp0,
+ ureg_scalar(const0124, TGSI_SWIZZLE_W),
+ ureg_src(temp2));
+ ureg_MUL(ureg, temp3,
+ ureg_src(temp1), ureg_src(temp1));
+ ureg_SUB(ureg, temp2,
+ ureg_src(temp3), ureg_src(temp0));
+ ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2)));
+ ureg_RCP(ureg, temp2, ureg_src(temp2));
+ ureg_SUB(ureg, temp1,
+ ureg_src(temp2), ureg_src(temp1));
+ ureg_ADD(ureg, temp0,
+ ureg_scalar(coords, TGSI_SWIZZLE_Z),
+ ureg_scalar(coords, TGSI_SWIZZLE_Z));
+ ureg_RCP(ureg, temp0, ureg_src(temp0));
+ ureg_MUL(ureg, temp2,
+ ureg_src(temp1), ureg_src(temp0));
+ ureg_TEX(ureg, out, TGSI_TEXTURE_1D,
+ ureg_src(temp2), sampler);
+
+ ureg_release_temporary(ureg, temp0);
+ ureg_release_temporary(ureg, temp1);
+ ureg_release_temporary(ureg, temp2);
+ ureg_release_temporary(ureg, temp3);
+ ureg_release_temporary(ureg, temp4);
+ ureg_release_temporary(ureg, temp5);
+}
+
+static void *
+create_vs(struct pipe_context *pipe,
+ unsigned vs_traits)
+{
+ struct ureg_program *ureg;
+ struct ureg_src src;
+ struct ureg_dst dst;
+ struct ureg_src const0, const1;
+ boolean is_fill = vs_traits & VS_FILL;
+ boolean is_composite = vs_traits & VS_COMPOSITE;
+ boolean has_mask = vs_traits & VS_MASK;
+
+ ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
+ if (ureg == NULL)
+ return 0;
+
+ const0 = ureg_DECL_constant(ureg);
+ const1 = ureg_DECL_constant(ureg);
+
+ /* it has to be either a fill or a composite op */
+ debug_assert(is_fill ^ is_composite);
+
+ src = ureg_DECL_vs_input(ureg,
+ TGSI_SEMANTIC_POSITION, 0);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+ src = vs_normalize_coords(ureg, src,
+ const0, const1);
+ ureg_MOV(ureg, dst, src);
+
+
+ if (is_composite) {
+ src = ureg_DECL_vs_input(ureg,
+ TGSI_SEMANTIC_GENERIC, 1);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
+ ureg_MOV(ureg, dst, src);
+ }
+ if (is_fill) {
+ src = ureg_DECL_vs_input(ureg,
+ TGSI_SEMANTIC_COLOR, 0);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+ ureg_MOV(ureg, dst, src);
+ }
+
+ if (has_mask) {
+ src = ureg_DECL_vs_input(ureg,
+ TGSI_SEMANTIC_GENERIC, 2);
+ dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 2);
+ ureg_MOV(ureg, dst, src);
+ }
+
+ ureg_END(ureg);
+
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+static void *
+create_fs(struct pipe_context *pipe,
+ unsigned fs_traits)
+{
+ struct ureg_program *ureg;
+ struct ureg_src /*dst_sampler,*/ src_sampler, mask_sampler;
+ struct ureg_src /*dst_pos,*/ src_input, mask_pos;
+ struct ureg_dst src, mask;
+ struct ureg_dst out;
+ boolean has_mask = fs_traits & FS_MASK;
+ boolean is_fill = fs_traits & FS_FILL;
+ boolean is_composite = fs_traits & FS_COMPOSITE;
+ boolean is_solid = fs_traits & FS_SOLID_FILL;
+ boolean is_lingrad = fs_traits & FS_LINGRAD_FILL;
+ boolean is_radgrad = fs_traits & FS_RADGRAD_FILL;
+
+ ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+ if (ureg == NULL)
+ return 0;
+
+ /* it has to be either a fill or a composite op */
+ debug_assert(is_fill ^ is_composite);
+
+ out = ureg_DECL_output(ureg,
+ TGSI_SEMANTIC_COLOR,
+ 0);
+
+ if (is_composite) {
+ src_sampler = ureg_DECL_sampler(ureg, 0);
+ src_input = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_POSITION,
+ 0,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+ } else {
+ debug_assert(is_fill);
+ if (is_solid)
+ src_input = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_COLOR,
+ 0,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+ else
+ src_input = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_POSITION,
+ 0,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+ }
+
+ if (has_mask) {
+ mask_sampler = ureg_DECL_sampler(ureg, 1);
+ mask_pos = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_POSITION,
+ 1,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+ }
+
+#if 0 /* unused right now */
+ dst_sampler = ureg_DECL_sampler(ureg, 2);
+ dst_pos = ureg_DECL_fs_input(ureg,
+ TGSI_SEMANTIC_POSITION,
+ 2,
+ TGSI_INTERPOLATE_PERSPECTIVE);
+#endif
+
+ if (is_composite) {
+ if (has_mask)
+ src = ureg_DECL_temporary(ureg);
+ else
+ src = out;
+ ureg_TEX(ureg, src,
+ TGSI_TEXTURE_2D, src_input, src_sampler);
+ } else if (is_fill) {
+ if (is_solid) {
+ if (has_mask)
+ src = ureg_dst(src_input);
+ else
+ ureg_MOV(ureg, out, src_input);
+ } else if (is_lingrad || is_radgrad) {
+ struct ureg_src coords, const0124,
+ matrow0, matrow1, matrow2;
+
+ if (has_mask)
+ src = ureg_DECL_temporary(ureg);
+ else
+ src = out;
+
+ coords = ureg_DECL_constant(ureg);
+ const0124 = ureg_DECL_constant(ureg);
+ matrow0 = ureg_DECL_constant(ureg);
+ matrow1 = ureg_DECL_constant(ureg);
+ matrow2 = ureg_DECL_constant(ureg);
+
+ if (is_lingrad) {
+ linear_gradient(ureg, src,
+ src_input, src_sampler,
+ coords, const0124,
+ matrow0, matrow1, matrow2);
+ } else if (is_radgrad) {
+ radial_gradient(ureg, src,
+ src_input, src_sampler,
+ coords, const0124,
+ matrow0, matrow1, matrow2);
+ }
+ } else
+ debug_assert(!"Unknown fill type!");
+ }
+
+ if (has_mask) {
+ mask = ureg_DECL_temporary(ureg);
+ ureg_TEX(ureg, mask,
+ TGSI_TEXTURE_2D, mask_pos, mask_sampler);
+ /* src IN mask */
+ src_in_mask(ureg, out, ureg_src(src), ureg_src(mask));
+ ureg_release_temporary(ureg, mask);
+ }
+
+ ureg_END(ureg);
+
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+struct xorg_shaders * xorg_shaders_create(struct exa_context *exa)
+{
+ struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders);
+
+ sc->exa = exa;
+ sc->vs_hash = cso_hash_create();
+ sc->fs_hash = cso_hash_create();
+
+ return sc;
+}
+
+static void
+cache_destroy(struct cso_context *cso,
+ struct cso_hash *hash,
+ unsigned processor)
+{
+ struct cso_hash_iter iter = cso_hash_first_node(hash);
+ while (!cso_hash_iter_is_null(iter)) {
+ void *shader = (void *)cso_hash_iter_data(iter);
+ if (processor == PIPE_SHADER_FRAGMENT) {
+ cso_delete_fragment_shader(cso, shader);
+ } else if (processor == PIPE_SHADER_VERTEX) {
+ cso_delete_vertex_shader(cso, shader);
+ }
+ iter = cso_hash_erase(hash, iter);
+ }
+ cso_hash_delete(hash);
+}
+
+void xorg_shaders_destroy(struct xorg_shaders *sc)
+{
+ cache_destroy(sc->exa->cso, sc->vs_hash,
+ PIPE_SHADER_VERTEX);
+ cache_destroy(sc->exa->cso, sc->fs_hash,
+ PIPE_SHADER_FRAGMENT);
+
+ free(sc);
+}
+
+static INLINE void *
+shader_from_cache(struct pipe_context *pipe,
+ unsigned type,
+ struct cso_hash *hash,
+ unsigned key)
+{
+ void *shader = 0;
+
+ struct cso_hash_iter iter = cso_hash_find(hash, key);
+
+ if (cso_hash_iter_is_null(iter)) {
+ if (type == PIPE_SHADER_VERTEX)
+ shader = create_vs(pipe, key);
+ else
+ shader = create_fs(pipe, key);
+ cso_hash_insert(hash, key, shader);
+ } else
+ shader = (void *)cso_hash_iter_data(iter);
+
+ return shader;
+}
+
+struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc,
+ unsigned vs_traits,
+ unsigned fs_traits)
+{
+ struct xorg_shader shader = {0};
+ void *vs, *fs;
+
+ vs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_VERTEX,
+ sc->vs_hash, vs_traits);
+ fs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_FRAGMENT,
+ sc->fs_hash, fs_traits);
+
+ debug_assert(vs && fs);
+ if (!vs || !fs)
+ return shader;
+
+ shader.vs = vs;
+ shader.fs = fs;
+
+ return shader;
+}
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
new file mode 100644
index 0000000000..1535a0c8c3
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h
@@ -0,0 +1,43 @@
+#ifndef XORG_EXA_TGSI_H
+#define XORG_EXA_TGSI_H
+
+#include "xorg_exa.h"
+
+enum xorg_vs_traits {
+ VS_COMPOSITE = 1 << 0,
+ VS_MASK = 1 << 1,
+ VS_SOLID_FILL = 1 << 2,
+ VS_LINGRAD_FILL = 1 << 3,
+ VS_RADGRAD_FILL = 1 << 4,
+ VS_FILL = (VS_SOLID_FILL |
+ VS_LINGRAD_FILL |
+ VS_RADGRAD_FILL)
+ /*VS_TRANSFORM = 1 << 5*/
+};
+
+enum xorg_fs_traits {
+ FS_COMPOSITE = 1 << 0,
+ FS_MASK = 1 << 1,
+ FS_SOLID_FILL = 1 << 2,
+ FS_LINGRAD_FILL = 1 << 3,
+ FS_RADGRAD_FILL = 1 << 4,
+ FS_FILL = (FS_SOLID_FILL |
+ FS_LINGRAD_FILL |
+ FS_RADGRAD_FILL)
+};
+
+struct xorg_shader {
+ void *fs;
+ void *vs;
+};
+
+struct xorg_shaders;
+
+struct xorg_shaders *xorg_shaders_create(struct exa_context *exa);
+void xorg_shaders_destroy(struct xorg_shaders *shaders);
+
+struct xorg_shader xorg_shaders_get(struct xorg_shaders *shaders,
+ unsigned vs_traits,
+ unsigned fs_traits);
+
+#endif
diff --git a/src/gallium/state_trackers/xorg/xorg_output.c b/src/gallium/state_trackers/xorg/xorg_output.c
new file mode 100644
index 0000000000..950af942f5
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_output.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Author: Alan Hourihane <alanh@tungstengraphics.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ */
+
+#include "xorg-server.h"
+#include <xf86.h>
+#include <xf86i2c.h>
+#include <xf86Crtc.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "X11/Xatom.h"
+
+#include "xorg_tracker.h"
+
+static char *connector_enum_list[] = {
+ "Unknown",
+ "VGA",
+ "DVI-I",
+ "DVI-D",
+ "DVI-A",
+ "Composite",
+ "SVIDEO",
+ "LVDS",
+ "Component",
+ "9-pin DIN",
+ "DisplayPort",
+ "HDMI Type A",
+ "HDMI Type B",
+};
+
+static void
+dpms(xf86OutputPtr output, int mode)
+{
+}
+
+static void
+save(xf86OutputPtr output)
+{
+}
+
+static void
+restore(xf86OutputPtr output)
+{
+}
+
+static int
+mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
+{
+ return MODE_OK;
+}
+
+static Bool
+mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ return TRUE;
+}
+
+static void
+prepare(xf86OutputPtr output)
+{
+ dpms(output, DPMSModeOff);
+}
+
+static void
+mode_set(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+}
+
+static void
+commit(xf86OutputPtr output)
+{
+ dpms(output, DPMSModeOn);
+
+ if (output->scrn->pScreen != NULL)
+ xf86_reload_cursors(output->scrn->pScreen);
+}
+
+static xf86OutputStatus
+detect(xf86OutputPtr output)
+{
+ drmModeConnectorPtr drm_connector = output->driver_private;
+
+ switch (drm_connector->connection) {
+ case DRM_MODE_CONNECTED:
+ return XF86OutputStatusConnected;
+ case DRM_MODE_DISCONNECTED:
+ return XF86OutputStatusDisconnected;
+ default:
+ return XF86OutputStatusUnknown;
+ }
+}
+
+static DisplayModePtr
+get_modes(xf86OutputPtr output)
+{
+ drmModeConnectorPtr drm_connector = output->driver_private;
+ drmModeModeInfoPtr drm_mode = NULL;
+ DisplayModePtr modes = NULL, mode = NULL;
+ int i;
+
+ for (i = 0; i < drm_connector->count_modes; i++) {
+ drm_mode = &drm_connector->modes[i];
+ if (drm_mode) {
+ mode = xcalloc(1, sizeof(DisplayModeRec));
+ if (!mode)
+ continue;
+ mode->type = 0;
+ mode->Clock = drm_mode->clock;
+ mode->HDisplay = drm_mode->hdisplay;
+ mode->HSyncStart = drm_mode->hsync_start;
+ mode->HSyncEnd = drm_mode->hsync_end;
+ mode->HTotal = drm_mode->htotal;
+ mode->VDisplay = drm_mode->vdisplay;
+ mode->VSyncStart = drm_mode->vsync_start;
+ mode->VSyncEnd = drm_mode->vsync_end;
+ mode->VTotal = drm_mode->vtotal;
+ mode->Flags = drm_mode->flags;
+ mode->HSkew = drm_mode->hskew;
+ mode->VScan = drm_mode->vscan;
+ mode->VRefresh = xf86ModeVRefresh(mode);
+ mode->Private = (void *)drm_mode;
+ xf86SetModeDefaultName(mode);
+ modes = xf86ModesAdd(modes, mode);
+ xf86PrintModeline(0, mode);
+ }
+ }
+
+ return modes;
+}
+
+static void
+destroy(xf86OutputPtr output)
+{
+ drmModeFreeConnector(output->driver_private);
+}
+
+static void
+create_resources(xf86OutputPtr output)
+{
+#ifdef RANDR_12_INTERFACE
+#endif /* RANDR_12_INTERFACE */
+}
+
+#ifdef RANDR_12_INTERFACE
+static Bool
+set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value)
+{
+ return TRUE;
+}
+#endif /* RANDR_12_INTERFACE */
+
+#ifdef RANDR_13_INTERFACE
+static Bool
+get_property(xf86OutputPtr output, Atom property)
+{
+ return TRUE;
+}
+#endif /* RANDR_13_INTERFACE */
+
+#ifdef RANDR_GET_CRTC_INTERFACE
+static xf86CrtcPtr
+get_crtc(xf86OutputPtr output)
+{
+ return NULL;
+}
+#endif
+
+static const xf86OutputFuncsRec output_funcs = {
+ .create_resources = create_resources,
+ .dpms = dpms,
+ .save = save,
+ .restore = restore,
+ .mode_valid = mode_valid,
+ .mode_fixup = mode_fixup,
+ .prepare = prepare,
+ .mode_set = mode_set,
+ .commit = commit,
+ .detect = detect,
+ .get_modes = get_modes,
+#ifdef RANDR_12_INTERFACE
+ .set_property = set_property,
+#endif
+#ifdef RANDR_13_INTERFACE
+ .get_property = get_property,
+#endif
+ .destroy = destroy,
+#ifdef RANDR_GET_CRTC_INTERFACE
+ .get_crtc = get_crtc,
+#endif
+};
+
+void
+output_init(ScrnInfoPtr pScrn)
+{
+ modesettingPtr ms = modesettingPTR(pScrn);
+ xf86OutputPtr output;
+ drmModeResPtr res;
+ drmModeConnectorPtr drm_connector = NULL;
+ drmModeEncoderPtr drm_encoder = NULL;
+ char *name;
+ int c, v, p;
+
+ res = drmModeGetResources(ms->fd);
+ if (res == 0) {
+ DRV_ERROR("Failed drmModeGetResources\n");
+ return;
+ }
+
+ for (c = 0; c < res->count_connectors; c++) {
+ drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]);
+ if (!drm_connector)
+ goto out;
+
+#if 0
+ for (p = 0; p < drm_connector->count_props; p++) {
+ drmModePropertyPtr prop;
+
+ prop = drmModeGetProperty(ms->fd, drm_connector->props[p]);
+
+ name = NULL;
+ if (prop) {
+ ErrorF("VALUES %d\n", prop->count_values);
+
+ for (v = 0; v < prop->count_values; v++)
+ ErrorF("%s %lld\n", prop->name, prop->values[v]);
+ }
+ }
+#else
+ (void)p;
+ (void)v;
+#endif
+
+ name = connector_enum_list[drm_connector->connector_type];
+
+ output = xf86OutputCreate(pScrn, &output_funcs, name);
+ if (!output)
+ continue;
+
+ drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]);
+ if (drm_encoder) {
+ output->possible_crtcs = drm_encoder->possible_crtcs;
+ output->possible_clones = drm_encoder->possible_clones;
+ } else {
+ output->possible_crtcs = 0;
+ output->possible_clones = 0;
+ }
+ output->driver_private = drm_connector;
+ output->subpixel_order = SubPixelHorizontalRGB;
+ output->interlaceAllowed = FALSE;
+ output->doubleScanAllowed = FALSE;
+ }
+
+ out:
+ drmModeFreeResources(res);
+}
+
+/* vim: set sw=4 ts=8 sts=4: */
diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h
new file mode 100644
index 0000000000..b1ab783a15
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_tracker.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Author: Alan Hourihane <alanh@tungstengraphics.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ */
+
+#ifndef _XORG_TRACKER_H_
+#define _XORG_TRACKER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <errno.h>
+#include <drm.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <xorg-server.h>
+#include <xf86.h>
+#include "xf86Crtc.h"
+#include <exa.h>
+
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+#include <damage.h>
+#endif
+
+#include "pipe/p_screen.h"
+#include "state_tracker/drm_api.h"
+
+#define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
+
+typedef struct
+{
+ int lastInstance;
+ int refCount;
+ ScrnInfoPtr pScrn_1;
+ ScrnInfoPtr pScrn_2;
+} EntRec, *EntPtr;
+
+typedef struct _modesettingRec
+{
+ /* drm */
+ int fd;
+ unsigned fb_id;
+
+ /* X */
+ EntPtr entityPrivate;
+
+ int Chipset;
+ EntityInfoPtr pEnt;
+ struct pci_device *PciInfo;
+
+ Bool noAccel;
+ Bool SWCursor;
+ CloseScreenProcPtr CloseScreen;
+
+ /* Broken-out options. */
+ OptionInfoPtr Options;
+
+ unsigned int SaveGeneration;
+
+ void (*blockHandler)(int, pointer, pointer, pointer);
+ CreateScreenResourcesProcPtr createScreenResources;
+
+ /* gallium */
+ struct drm_api *api;
+ struct pipe_screen *screen;
+ struct pipe_context *ctx;
+ boolean d_depth_bits_last;
+ boolean ds_depth_bits_last;
+
+ /* exa */
+ void *exa;
+ Bool noEvict;
+
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+ DamagePtr damage;
+#endif
+} modesettingRec, *modesettingPtr;
+
+#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))
+
+
+/***********************************************************************
+ * xorg_exa.c
+ */
+struct pipe_texture *
+xorg_exa_get_texture(PixmapPtr pPixmap);
+
+unsigned
+xorg_exa_get_pixmap_handle(PixmapPtr pPixmap, unsigned *stride);
+
+int
+xorg_exa_set_displayed_usage(PixmapPtr pPixmap);
+
+int
+xorg_exa_set_shared_usage(PixmapPtr pPixmap);
+
+void *
+xorg_exa_init(ScrnInfoPtr pScrn);
+
+void
+xorg_exa_close(ScrnInfoPtr pScrn);
+
+
+/***********************************************************************
+ * xorg_dri2.c
+ */
+Bool
+driScreenInit(ScreenPtr pScreen);
+
+void
+driCloseScreen(ScreenPtr pScreen);
+
+
+/***********************************************************************
+ * xorg_crtc.c
+ */
+void
+crtc_init(ScrnInfoPtr pScrn);
+
+void
+crtc_cursor_destroy(xf86CrtcPtr crtc);
+
+
+/***********************************************************************
+ * xorg_output.c
+ */
+void
+output_init(ScrnInfoPtr pScrn);
+
+
+#endif /* _XORG_TRACKER_H_ */
diff --git a/src/gallium/state_trackers/xorg/xorg_winsys.h b/src/gallium/state_trackers/xorg/xorg_winsys.h
new file mode 100644
index 0000000000..47ee4b9ffd
--- /dev/null
+++ b/src/gallium/state_trackers/xorg/xorg_winsys.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Author: Alan Hourihane <alanh@tungstengraphics.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ */
+
+/*
+ * File with all the junk needed to personalize the a xorg driver.
+ */
+
+#ifndef _XORG_WINSYS_H_
+#define _XORG_WINSYS_H_
+
+#include "xorg-server.h"
+#include "xf86.h"
+#include "pciaccess.h"
+
+#ifndef XSERVER_LIBPCIACCESS
+#error "libpciaccess needed"
+#endif
+
+void xorg_tracker_set_functions(ScrnInfoPtr scrn);
+const OptionInfoRec * xorg_tracker_available_options(int chipid, int busid);
+
+#endif
diff --git a/src/gallium/winsys/Makefile b/src/gallium/winsys/Makefile
new file mode 100644
index 0000000000..bce5b3f9e0
--- /dev/null
+++ b/src/gallium/winsys/Makefile
@@ -0,0 +1,12 @@
+# src/gallium/winsys/Makefile
+TOP = ../../..
+include $(TOP)/configs/current
+
+SUBDIRS = $(GALLIUM_WINSYS_DIRS)
+
+default install clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) $@) || exit 1; \
+ fi \
+ done
diff --git a/src/gallium/winsys/SConscript b/src/gallium/winsys/SConscript
new file mode 100644
index 0000000000..30c3378dff
--- /dev/null
+++ b/src/gallium/winsys/SConscript
@@ -0,0 +1,16 @@
+Import('*')
+
+if env['dri']:
+ SConscript([
+ 'drm/SConscript',
+ ])
+
+if 'xlib' in env['winsys']:
+ SConscript([
+ 'xlib/SConscript',
+ ])
+
+if 'gdi' in env['winsys']:
+ SConscript([
+ 'gdi/SConscript',
+ ])
diff --git a/src/gallium/winsys/drm/Makefile b/src/gallium/winsys/drm/Makefile
new file mode 100644
index 0000000000..fee0191643
--- /dev/null
+++ b/src/gallium/winsys/drm/Makefile
@@ -0,0 +1,12 @@
+# src/gallium/winsys/Makefile
+TOP = ../../../..
+include $(TOP)/configs/current
+
+SUBDIRS = $(GALLIUM_WINSYS_DRM_DIRS)
+
+default install clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) $@) || exit 1; \
+ fi \
+ done
diff --git a/src/gallium/winsys/drm/Makefile.template b/src/gallium/winsys/drm/Makefile.template
new file mode 100644
index 0000000000..9635c3c50e
--- /dev/null
+++ b/src/gallium/winsys/drm/Makefile.template
@@ -0,0 +1,126 @@
+# -*-makefile-*-
+
+MESA_MODULES = \
+ $(TOP)/src/mesa/libmesagallium.a \
+ $(GALLIUM_AUXILIARIES)
+
+COMMON_GALLIUM_SOURCES = \
+ $(TOP)/src/mesa/drivers/dri/common/utils.c \
+ $(TOP)/src/mesa/drivers/dri/common/vblank.c \
+ $(TOP)/src/mesa/drivers/dri/common/dri_util.c \
+ $(TOP)/src/mesa/drivers/dri/common/xmlconfig.c
+
+COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
+ $(TOP)/src/mesa/drivers/common/driverfuncs.c \
+ $(TOP)/src/mesa/drivers/dri/common/texmem.c \
+ $(TOP)/src/mesa/drivers/dri/common/drirenderbuffer.c
+
+COMMON_BM_SOURCES = \
+ $(TOP)/src/mesa/drivers/dri/common/dri_bufmgr.c \
+ $(TOP)/src/mesa/drivers/dri/common/dri_drmpool.c
+
+
+ifeq ($(WINDOW_SYSTEM),dri)
+WINOBJ=
+WINLIB=
+INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES)
+
+OBJECTS = \
+ $(C_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+else
+# miniglx
+WINOBJ=
+WINLIB=-L$(MESA)/src/glx/mini
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
+INCLUDES = $(MINIGLX_INCLUDES) \
+ $(SHARED_INCLUDES) \
+ $(PCIACCESS_CFLAGS)
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(MINIGLX_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+endif
+
+
+### Include directories
+SHARED_INCLUDES = \
+ -I. \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -Iserver \
+ -I$(TOP)/include \
+ -I$(TOP)/include/GL/internal \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/src/gallium/drivers \
+ -I$(TOP)/src/gallium/winsys/common \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/mesa/math \
+ -I$(TOP)/src/mesa/transform \
+ -I$(TOP)/src/mesa/shader \
+ -I$(TOP)/src/mesa/swrast \
+ -I$(TOP)/src/mesa/swrast_setup \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/src/egl/drivers/dri \
+ $(LIBDRM_CFLAGS)
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+default: depend symlinks $(TOP)/$(LIB_DIR)/gallium/$(LIBNAME)
+
+$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template
+ $(MKLIB) -noprefix -o $@ \
+ $(OBJECTS) $(PIPE_DRIVERS) \
+ -Wl,--start-group $(MESA_MODULES) -Wl,--end-group \
+ $(WINOBJ) $(DRI_LIB_DEPS) $(DRIVER_EXTRAS)
+
+$(LIBNAME_EGL): $(WINSYS_OBJECTS) $(LIBS)
+ $(MKLIB) -o $(LIBNAME_EGL) \
+ -linker "$(CC)" \
+ -noprefix \
+ $(OBJECTS) $(MKLIB_OPTIONS) $(WINSYS_OBJECTS) $(PIPE_DRIVERS) $(WINOBJ) $(DRI_LIB_DEPS) \
+ --whole-archive $(LIBS) $(GALLIUM_AUXILIARIES) --no-whole-archive $(DRIVER_EXTRAS)
+
+$(TOP)/$(LIB_DIR)/gallium:
+ mkdir -p $@
+
+$(TOP)/$(LIB_DIR)/gallium/$(LIBNAME): $(LIBNAME) $(TOP)/$(LIB_DIR)/gallium
+ $(INSTALL) $(LIBNAME) $(TOP)/$(LIB_DIR)/gallium
+
+depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
+ $(ASM_SOURCES) 2> /dev/null
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+ -rm -f *.o */*.o *~ *.so *~ server/*.o $(SYMLINKS)
+ -rm -f depend depend.bak
+
+
+install: $(LIBNAME)
+ $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+ $(MINSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+
+
+include depend
diff --git a/src/gallium/winsys/drm/SConscript b/src/gallium/winsys/drm/SConscript
new file mode 100644
index 0000000000..a9e9f2682a
--- /dev/null
+++ b/src/gallium/winsys/drm/SConscript
@@ -0,0 +1,59 @@
+Import('*')
+
+if env['dri']:
+
+ drienv = env.Clone()
+
+ drienv.Replace(CPPPATH = [
+ '#src/mesa/drivers/dri/common',
+ '#include',
+ '#include/GL/internal',
+ '#src/gallium/include',
+ '#src/gallium/auxiliary',
+ '#src/gallium/drivers',
+ '#src/mesa',
+ '#src/mesa/main',
+ '#src/mesa/glapi',
+ '#src/mesa/math',
+ '#src/mesa/transform',
+ '#src/mesa/shader',
+ '#src/mesa/swrast',
+ '#src/mesa/swrast_setup',
+ '#src/egl/main',
+ '#src/egl/drivers/dri',
+ ])
+
+ drienv.ParseConfig('pkg-config --cflags --libs libdrm')
+
+ COMMON_GALLIUM_SOURCES = [
+ '#src/mesa/drivers/dri/common/utils.c',
+ '#src/mesa/drivers/dri/common/vblank.c',
+ '#src/mesa/drivers/dri/common/dri_util.c',
+ '#src/mesa/drivers/dri/common/xmlconfig.c',
+ ]
+
+ COMMON_BM_SOURCES = [
+ '#src/mesa/drivers/dri/common/dri_bufmgr.c',
+ '#src/mesa/drivers/dri/common/dri_drmpool.c',
+ ]
+
+ Export([
+ 'drienv',
+ 'COMMON_GALLIUM_SOURCES',
+ 'COMMON_BM_SOURCES',
+ ])
+
+ # TODO: Installation
+ #install: $(LIBNAME)
+ # $(INSTALL) -d $(DRI_DRIVER_INSTALL_DIR)
+ # $(INSTALL) -m 755 $(LIBNAME) $(DRI_DRIVER_INSTALL_DIR)
+
+ if 'intel' in env['winsys']:
+ SConscript([
+ 'intel/SConscript',
+ ])
+
+ if 'radeon' in env['winsys']:
+ SConscript([
+ 'radeon/SConscript',
+ ])
diff --git a/src/gallium/winsys/drm/intel/Makefile b/src/gallium/winsys/drm/intel/Makefile
new file mode 100644
index 0000000000..d8feef6824
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/Makefile
@@ -0,0 +1,12 @@
+# src/gallium/winsys/drm/intel/Makefile
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+SUBDIRS = gem $(GALLIUM_STATE_TRACKERS_DIRS)
+
+default install clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) $@) || exit 1; \
+ fi \
+ done
diff --git a/src/gallium/winsys/drm/intel/SConscript b/src/gallium/winsys/drm/intel/SConscript
new file mode 100644
index 0000000000..50d7b75ed6
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/SConscript
@@ -0,0 +1,7 @@
+Import('*')
+
+SConscript(['gem/SConscript',])
+
+if 'mesa' in env['statetrackers']:
+
+ SConscript(['dri/SConscript'])
diff --git a/src/gallium/winsys/drm/intel/dri/Makefile b/src/gallium/winsys/drm/intel/dri/Makefile
new file mode 100644
index 0000000000..5e212b62a4
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/dri/Makefile
@@ -0,0 +1,27 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = i915_dri.so
+
+PIPE_DRIVERS = \
+ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \
+ $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(TOP)/src/gallium/drivers/identity/libidentity.a \
+ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a
+
+
+DRIVER_SOURCES =
+
+C_SOURCES = \
+ $(COMMON_GALLIUM_SOURCES) \
+ $(DRIVER_SOURCES)
+
+include ../../Makefile.template
+
+DRI_LIB_DEPS += -ldrm_intel
+
+symlinks: $(TOP)/$(LIB_DIR)/gallium
+ @rm -f $(TOP)/$(LIB_DIR)/gallium/i965_dri.so
+ ln -s i915_dri.so $(TOP)/$(LIB_DIR)/gallium/i965_dri.so
diff --git a/src/gallium/winsys/drm/intel/dri/SConscript b/src/gallium/winsys/drm/intel/dri/SConscript
new file mode 100644
index 0000000000..f973811072
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/dri/SConscript
@@ -0,0 +1,20 @@
+Import('*')
+
+env = drienv.Clone()
+
+env.ParseConfig('pkg-config --cflags --libs libdrm_intel')
+
+drivers = [
+ st_dri,
+ inteldrm,
+ softpipe,
+ i915simple,
+ trace,
+]
+
+env.LoadableModule(
+ target ='i915_dri.so',
+ source = COMMON_GALLIUM_SOURCES,
+ LIBS = drivers + mesa + auxiliaries + env['LIBS'],
+ SHLIBPREFIX = '',
+)
diff --git a/src/gallium/winsys/drm/intel/egl/Makefile b/src/gallium/winsys/drm/intel/egl/Makefile
new file mode 100644
index 0000000000..490baded66
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/egl/Makefile
@@ -0,0 +1,29 @@
+TOP = ../../../../../..
+GALLIUMDIR = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = EGL_i915.so
+
+PIPE_DRIVERS = \
+ $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \
+ $(GALLIUMDIR)/winsys/drm/intel/gem/libinteldrm.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a
+
+DRIVER_SOURCES =
+
+C_SOURCES = \
+ $(COMMON_GALLIUM_SOURCES) \
+ $(DRIVER_SOURCES)
+
+DRIVER_EXTRAS = -ldrm_intel
+
+ASM_SOURCES =
+
+DRIVER_DEFINES = -I../gem $(shell pkg-config libdrm --atleast-version=2.3.1 \
+ && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP")
+
+include ../../Makefile.template
+
+symlinks:
diff --git a/src/gallium/winsys/drm/intel/gem/Makefile b/src/gallium/winsys/drm/intel/gem/Makefile
new file mode 100644
index 0000000000..0d6d4e37db
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/gem/Makefile
@@ -0,0 +1,16 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = inteldrm
+
+C_SOURCES = \
+ intel_drm_batchbuffer.c \
+ intel_drm_buffer.c \
+ intel_drm_fence.c \
+ intel_drm_api.c
+
+LIBRARY_INCLUDES = $(shell pkg-config libdrm --cflags-only-I)
+
+LIBRARY_DEFINES = $(shell pkg-config libdrm --cflags-only-other)
+
+include ../../../../Makefile.template
diff --git a/src/gallium/winsys/drm/intel/gem/SConscript b/src/gallium/winsys/drm/intel/gem/SConscript
new file mode 100644
index 0000000000..26717f391f
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/gem/SConscript
@@ -0,0 +1,17 @@
+Import('*')
+
+env = drienv.Clone()
+
+inteldrm_sources = [
+ 'intel_drm_api.c',
+ 'intel_drm_batchbuffer.c',
+ 'intel_drm_buffer.c',
+ 'intel_drm_fence.c',
+]
+
+inteldrm = env.ConvenienceLibrary(
+ target ='inteldrm',
+ source = inteldrm_sources,
+)
+
+Export('inteldrm')
diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_api.c b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c
new file mode 100644
index 0000000000..4c5a1d2ea8
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/gem/intel_drm_api.c
@@ -0,0 +1,202 @@
+
+#include "state_tracker/drm_api.h"
+
+#include "intel_drm_winsys.h"
+#include "util/u_memory.h"
+
+#include "i915simple/i915_context.h"
+#include "i915simple/i915_screen.h"
+
+
+/*
+ * Helper functions
+ */
+
+
+static void
+intel_drm_get_device_id(unsigned int *device_id)
+{
+ char path[512];
+ FILE *file;
+ void *shutup_gcc;
+
+ /*
+ * FIXME: Fix this up to use a drm ioctl or whatever.
+ */
+
+ snprintf(path, sizeof(path), "/sys/class/drm/card0/device/device");
+ file = fopen(path, "r");
+ if (!file) {
+ return;
+ }
+
+ shutup_gcc = fgets(path, sizeof(path), file);
+ sscanf(path, "%x", device_id);
+ fclose(file);
+}
+
+static struct intel_buffer *
+intel_drm_buffer_from_handle(struct intel_drm_winsys *idws,
+ const char* name, unsigned handle)
+{
+ struct intel_drm_buffer *buf = CALLOC_STRUCT(intel_drm_buffer);
+
+ if (!buf)
+ return NULL;
+
+ buf->magic = 0xDEAD1337;
+ buf->bo = drm_intel_bo_gem_create_from_name(idws->pools.gem, name, handle);
+ buf->flinked = TRUE;
+ buf->flink = handle;
+
+ if (!buf->bo)
+ goto err;
+
+ return (struct intel_buffer *)buf;
+
+err:
+ FREE(buf);
+ return NULL;
+}
+
+
+/*
+ * Exported functions
+ */
+
+
+static struct pipe_texture *
+intel_drm_texture_from_shared_handle(struct drm_api *api,
+ struct pipe_screen *screen,
+ struct pipe_texture *templ,
+ const char* name,
+ unsigned pitch,
+ unsigned handle)
+{
+ struct intel_drm_winsys *idws = intel_drm_winsys(i915_screen(screen)->iws);
+ struct intel_buffer *buffer;
+
+ buffer = intel_drm_buffer_from_handle(idws, name, handle);
+ if (!buffer)
+ return NULL;
+
+ return i915_texture_blanket_intel(screen, templ, pitch, buffer);
+}
+
+static boolean
+intel_drm_shared_handle_from_texture(struct drm_api *api,
+ struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned *pitch,
+ unsigned *handle)
+{
+ struct intel_drm_buffer *buf = NULL;
+ struct intel_buffer *buffer = NULL;
+ if (!i915_get_texture_buffer_intel(texture, &buffer, pitch))
+ return FALSE;
+
+ buf = intel_drm_buffer(buffer);
+ if (!buf->flinked) {
+ if (drm_intel_bo_flink(buf->bo, &buf->flink))
+ return FALSE;
+ buf->flinked = TRUE;
+ }
+
+ *handle = buf->flink;
+
+ return TRUE;
+}
+
+static boolean
+intel_drm_local_handle_from_texture(struct drm_api *api,
+ struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned *pitch,
+ unsigned *handle)
+{
+ struct intel_buffer *buffer = NULL;
+ if (!i915_get_texture_buffer_intel(texture, &buffer, pitch))
+ return FALSE;
+
+ *handle = intel_drm_buffer(buffer)->bo->handle;
+
+ return TRUE;
+}
+
+static void
+intel_drm_winsys_destroy(struct intel_winsys *iws)
+{
+ struct intel_drm_winsys *idws = intel_drm_winsys(iws);
+
+ drm_intel_bufmgr_destroy(idws->pools.gem);
+
+ FREE(idws);
+}
+
+static struct pipe_screen *
+intel_drm_create_screen(struct drm_api *api, int drmFD,
+ struct drm_create_screen_arg *arg)
+{
+ struct intel_drm_winsys *idws;
+ unsigned int deviceID;
+
+ if (arg != NULL) {
+ switch(arg->mode) {
+ case DRM_CREATE_NORMAL:
+ break;
+ default:
+ return NULL;
+ }
+ }
+
+ idws = CALLOC_STRUCT(intel_drm_winsys);
+ if (!idws)
+ return NULL;
+
+ intel_drm_get_device_id(&deviceID);
+
+ intel_drm_winsys_init_batchbuffer_functions(idws);
+ intel_drm_winsys_init_buffer_functions(idws);
+ intel_drm_winsys_init_fence_functions(idws);
+
+ idws->fd = drmFD;
+ idws->id = deviceID;
+ idws->max_batch_size = 16 * 4096;
+
+ idws->base.destroy = intel_drm_winsys_destroy;
+
+ idws->pools.gem = drm_intel_bufmgr_gem_init(idws->fd, idws->max_batch_size);
+
+ idws->softpipe = FALSE;
+ idws->dump_cmd = debug_get_bool_option("INTEL_DUMP_CMD", FALSE);
+
+ return i915_create_screen(&idws->base, deviceID);
+}
+
+static struct pipe_context *
+intel_drm_create_context(struct drm_api *api, struct pipe_screen *screen)
+{
+ return i915_create_context(screen);
+}
+
+static void
+destroy(struct drm_api *api)
+{
+
+}
+
+struct drm_api intel_drm_api =
+{
+ .create_context = intel_drm_create_context,
+ .create_screen = intel_drm_create_screen,
+ .texture_from_shared_handle = intel_drm_texture_from_shared_handle,
+ .shared_handle_from_texture = intel_drm_shared_handle_from_texture,
+ .local_handle_from_texture = intel_drm_local_handle_from_texture,
+ .destroy = destroy,
+};
+
+struct drm_api *
+drm_api_create()
+{
+ return &intel_drm_api;
+}
diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_batchbuffer.c b/src/gallium/winsys/drm/intel/gem/intel_drm_batchbuffer.c
new file mode 100644
index 0000000000..ebd1b607b7
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/gem/intel_drm_batchbuffer.c
@@ -0,0 +1,229 @@
+
+#include "intel_drm_winsys.h"
+#include "util/u_memory.h"
+
+#include "i915_drm.h"
+
+#define BATCH_RESERVED 16
+
+#define INTEL_DEFAULT_RELOCS 100
+#define INTEL_MAX_RELOCS 400
+
+#define INTEL_BATCH_NO_CLIPRECTS 0x1
+#define INTEL_BATCH_CLIPRECTS 0x2
+
+#undef INTEL_RUN_SYNC
+#undef INTEL_MAP_BATCHBUFFER
+
+struct intel_drm_batchbuffer
+{
+ struct intel_batchbuffer base;
+
+ size_t actual_size;
+
+ drm_intel_bo *bo;
+};
+
+static INLINE struct intel_drm_batchbuffer *
+intel_drm_batchbuffer(struct intel_batchbuffer *batch)
+{
+ return (struct intel_drm_batchbuffer *)batch;
+}
+
+static void
+intel_drm_batchbuffer_reset(struct intel_drm_batchbuffer *batch)
+{
+ struct intel_drm_winsys *idws = intel_drm_winsys(batch->base.iws);
+
+ if (batch->bo)
+ drm_intel_bo_unreference(batch->bo);
+ batch->bo = drm_intel_bo_alloc(idws->pools.gem,
+ "gallium3d_batchbuffer",
+ batch->actual_size,
+ 4096);
+
+#ifdef INTEL_MAP_BATCHBUFFER
+ drm_intel_bo_map(batch->bo, TRUE);
+ batch->base.map = batch->bo->virtual;
+#endif
+
+ memset(batch->base.map, 0, batch->actual_size);
+ batch->base.ptr = batch->base.map;
+ batch->base.size = batch->actual_size - BATCH_RESERVED;
+ batch->base.relocs = 0;
+}
+
+static struct intel_batchbuffer *
+intel_drm_batchbuffer_create(struct intel_winsys *iws)
+{
+ struct intel_drm_winsys *idws = intel_drm_winsys(iws);
+ struct intel_drm_batchbuffer *batch = CALLOC_STRUCT(intel_drm_batchbuffer);
+
+ batch->actual_size = idws->max_batch_size;
+
+#ifdef INTEL_MAP_BATCHBUFFER
+ batch->base.map = NULL;
+#else
+ batch->base.map = MALLOC(batch->actual_size);
+#endif
+ batch->base.ptr = NULL;
+ batch->base.size = 0;
+
+ batch->base.relocs = 0;
+ batch->base.max_relocs = 300;/*INTEL_DEFAULT_RELOCS;*/
+
+ batch->base.iws = iws;
+
+ intel_drm_batchbuffer_reset(batch);
+
+ return &batch->base;
+}
+
+static int
+intel_drm_batchbuffer_reloc(struct intel_batchbuffer *ibatch,
+ struct intel_buffer *buffer,
+ enum intel_buffer_usage usage,
+ unsigned pre_add)
+{
+ struct intel_drm_batchbuffer *batch = intel_drm_batchbuffer(ibatch);
+ unsigned write_domain = 0;
+ unsigned read_domain = 0;
+ unsigned offset;
+ int ret = 0;
+
+ assert(batch->base.relocs < batch->base.max_relocs);
+
+ if (usage == INTEL_USAGE_SAMPLER) {
+ write_domain = 0;
+ read_domain = I915_GEM_DOMAIN_SAMPLER;
+
+ } else if (usage == INTEL_USAGE_RENDER) {
+ write_domain = I915_GEM_DOMAIN_RENDER;
+ read_domain = I915_GEM_DOMAIN_RENDER;
+
+ } else if (usage == INTEL_USAGE_2D_TARGET) {
+ write_domain = I915_GEM_DOMAIN_RENDER;
+ read_domain = I915_GEM_DOMAIN_RENDER;
+
+ } else if (usage == INTEL_USAGE_2D_SOURCE) {
+ write_domain = 0;
+ read_domain = I915_GEM_DOMAIN_RENDER;
+
+ } else if (usage == INTEL_USAGE_VERTEX) {
+ write_domain = 0;
+ read_domain = I915_GEM_DOMAIN_VERTEX;
+
+ } else {
+ assert(0);
+ return -1;
+ }
+
+ offset = (unsigned)(batch->base.ptr - batch->base.map);
+
+ ret = drm_intel_bo_emit_reloc(batch->bo, offset,
+ intel_bo(buffer), pre_add,
+ read_domain,
+ write_domain);
+
+ ((uint32_t*)batch->base.ptr)[0] = intel_bo(buffer)->offset + pre_add;
+ batch->base.ptr += 4;
+
+ if (!ret)
+ batch->base.relocs++;
+
+ return ret;
+}
+
+static void
+intel_drm_batchbuffer_flush(struct intel_batchbuffer *ibatch,
+ struct pipe_fence_handle **fence)
+{
+ struct intel_drm_batchbuffer *batch = intel_drm_batchbuffer(ibatch);
+ unsigned used = 0;
+ int ret = 0;
+ int i;
+
+ assert(intel_batchbuffer_space(ibatch) >= 0);
+
+ used = batch->base.ptr - batch->base.map;
+ assert((used & 3) == 0);
+
+ if (used & 4) {
+ // MI_FLUSH | FLUSH_MAP_CACHE;
+ intel_batchbuffer_dword(ibatch, (0x0<<29)|(0x4<<23)|(1<<0));
+ // MI_NOOP
+ intel_batchbuffer_dword(ibatch, (0x0<<29)|(0x0<<23));
+ // MI_BATCH_BUFFER_END;
+ intel_batchbuffer_dword(ibatch, (0x0<<29)|(0xA<<23));
+ } else {
+ //MI_FLUSH | FLUSH_MAP_CACHE;
+ intel_batchbuffer_dword(ibatch, (0x0<<29)|(0x4<<23)|(1<<0));
+ // MI_BATCH_BUFFER_END;
+ intel_batchbuffer_dword(ibatch, (0x0<<29)|(0xA<<23));
+ }
+
+ used = batch->base.ptr - batch->base.map;
+
+#ifdef INTEL_MAP_BATCHBUFFER
+ drm_intel_bo_unmap(batch->bo);
+#else
+ drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map);
+#endif
+
+ /* Do the sending to HW */
+ ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0);
+ assert(ret == 0);
+
+ if (intel_drm_winsys(ibatch->iws)->dump_cmd) {
+ unsigned *ptr;
+ drm_intel_bo_map(batch->bo, FALSE);
+ ptr = (unsigned*)batch->bo->virtual;
+
+ debug_printf("%s:\n", __func__);
+ for (i = 0; i < used / 4; i++, ptr++) {
+ debug_printf("\t%08x: %08x\n", i*4, *ptr);
+ }
+
+ drm_intel_bo_unmap(batch->bo);
+ } else {
+#ifdef INTEL_RUN_SYNC
+ drm_intel_bo_map(batch->bo, FALSE);
+ drm_intel_bo_unmap(batch->bo);
+#endif
+ }
+
+ if (fence) {
+ ibatch->iws->fence_reference(ibatch->iws, fence, NULL);
+
+#ifdef INTEL_RUN_SYNC
+ /* we run synced to GPU so just pass null */
+ (*fence) = intel_drm_fence_create(NULL);
+#else
+ (*fence) = intel_drm_fence_create(batch->bo);
+#endif
+ }
+
+ intel_drm_batchbuffer_reset(batch);
+}
+
+static void
+intel_drm_batchbuffer_destroy(struct intel_batchbuffer *ibatch)
+{
+ struct intel_drm_batchbuffer *batch = intel_drm_batchbuffer(ibatch);
+
+ if (batch->bo)
+ drm_intel_bo_unreference(batch->bo);
+
+#ifndef INTEL_MAP_BATCHBUFFER
+ FREE(batch->base.map);
+#endif
+ FREE(batch);
+}
+
+void intel_drm_winsys_init_batchbuffer_functions(struct intel_drm_winsys *idws)
+{
+ idws->base.batchbuffer_create = intel_drm_batchbuffer_create;
+ idws->base.batchbuffer_reloc = intel_drm_batchbuffer_reloc;
+ idws->base.batchbuffer_flush = intel_drm_batchbuffer_flush;
+ idws->base.batchbuffer_destroy = intel_drm_batchbuffer_destroy;
+}
diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c b/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c
new file mode 100644
index 0000000000..0030f915a3
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/gem/intel_drm_buffer.c
@@ -0,0 +1,148 @@
+
+#include "intel_drm_winsys.h"
+#include "util/u_memory.h"
+
+#include "i915_drm.h"
+
+static struct intel_buffer *
+intel_drm_buffer_create(struct intel_winsys *iws,
+ unsigned size, unsigned alignment,
+ enum intel_buffer_type type)
+{
+ struct intel_drm_buffer *buf = CALLOC_STRUCT(intel_drm_buffer);
+ struct intel_drm_winsys *idws = intel_drm_winsys(iws);
+ drm_intel_bufmgr *pool;
+ char *name;
+
+ if (!buf)
+ return NULL;
+
+ buf->magic = 0xDEAD1337;
+ buf->flinked = FALSE;
+ buf->flink = 0;
+ buf->map_gtt = FALSE;
+
+ if (type == INTEL_NEW_TEXTURE) {
+ name = "gallium3d_texture";
+ pool = idws->pools.gem;
+ } else if (type == INTEL_NEW_VERTEX) {
+ name = "gallium3d_vertex";
+ pool = idws->pools.gem;
+ buf->map_gtt = TRUE;
+ } else if (type == INTEL_NEW_SCANOUT) {
+ name = "gallium3d_scanout";
+ pool = idws->pools.gem;
+ buf->map_gtt = TRUE;
+ } else {
+ assert(0);
+ name = "gallium3d_unknown";
+ pool = idws->pools.gem;
+ }
+
+ buf->bo = drm_intel_bo_alloc(pool, name, size, alignment);
+
+ if (!buf->bo)
+ goto err;
+
+ return (struct intel_buffer *)buf;
+
+err:
+ assert(0);
+ FREE(buf);
+ return NULL;
+}
+
+static int
+intel_drm_buffer_set_fence_reg(struct intel_winsys *iws,
+ struct intel_buffer *buffer,
+ unsigned stride,
+ enum intel_buffer_tile tile)
+{
+ assert(I915_TILING_NONE == INTEL_TILE_NONE);
+ assert(I915_TILING_X == INTEL_TILE_X);
+ assert(I915_TILING_Y == INTEL_TILE_Y);
+
+ return drm_intel_bo_set_tiling(intel_bo(buffer), &tile, stride);
+}
+
+static void *
+intel_drm_buffer_map(struct intel_winsys *iws,
+ struct intel_buffer *buffer,
+ boolean write)
+{
+ struct intel_drm_buffer *buf = intel_drm_buffer(buffer);
+ drm_intel_bo *bo = intel_bo(buffer);
+ int ret = 0;
+
+ assert(bo);
+
+ if (buf->map_count)
+ goto out;
+
+ if (buf->map_gtt)
+ ret = drm_intel_gem_bo_map_gtt(bo);
+ else
+ ret = drm_intel_bo_map(bo, write);
+
+ buf->ptr = bo->virtual;
+
+ assert(ret == 0);
+out:
+ if (ret)
+ return NULL;
+
+ buf->map_count++;
+ return buf->ptr;
+}
+
+static void
+intel_drm_buffer_unmap(struct intel_winsys *iws,
+ struct intel_buffer *buffer)
+{
+ struct intel_drm_buffer *buf = intel_drm_buffer(buffer);
+
+ if (--buf->map_count)
+ return;
+
+ if (buf->map_gtt)
+ drm_intel_gem_bo_unmap_gtt(intel_bo(buffer));
+ else
+ drm_intel_bo_unmap(intel_bo(buffer));
+}
+
+static int
+intel_drm_buffer_write(struct intel_winsys *iws,
+ struct intel_buffer *buffer,
+ const void *data,
+ size_t size,
+ size_t offset)
+{
+ struct intel_drm_buffer *buf = intel_drm_buffer(buffer);
+
+ return drm_intel_bo_subdata(buf->bo, offset, size, (void*)data);
+}
+
+static void
+intel_drm_buffer_destroy(struct intel_winsys *iws,
+ struct intel_buffer *buffer)
+{
+ drm_intel_bo_unreference(intel_bo(buffer));
+
+#ifdef DEBUG
+ intel_drm_buffer(buffer)->magic = 0;
+ intel_drm_buffer(buffer)->bo = NULL;
+#endif
+
+ FREE(buffer);
+}
+
+void
+intel_drm_winsys_init_buffer_functions(struct intel_drm_winsys *idws)
+{
+ idws->base.buffer_create = intel_drm_buffer_create;
+ idws->base.buffer_set_fence_reg = intel_drm_buffer_set_fence_reg;
+ idws->base.buffer_map = intel_drm_buffer_map;
+ idws->base.buffer_unmap = intel_drm_buffer_unmap;
+ idws->base.buffer_write = intel_drm_buffer_write;
+ idws->base.buffer_destroy = intel_drm_buffer_destroy;
+}
diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c b/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c
new file mode 100644
index 0000000000..e70bfe7b44
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/gem/intel_drm_fence.c
@@ -0,0 +1,81 @@
+
+#include "intel_drm_winsys.h"
+#include "util/u_memory.h"
+#include "pipe/p_refcnt.h"
+
+/**
+ * Because gem does not have fence's we have to create our own fences.
+ *
+ * They work by keeping the batchbuffer around and checking if that has
+ * been idled. If bo is NULL fence has expired.
+ */
+struct intel_drm_fence
+{
+ struct pipe_reference reference;
+ drm_intel_bo *bo;
+};
+
+
+struct pipe_fence_handle *
+intel_drm_fence_create(drm_intel_bo *bo)
+{
+ struct intel_drm_fence *fence = CALLOC_STRUCT(intel_drm_fence);
+
+ pipe_reference_init(&fence->reference, 1);
+ /* bo is null if fence already expired */
+ if (bo) {
+ drm_intel_bo_reference(bo);
+ fence->bo = bo;
+ }
+
+ return (struct pipe_fence_handle *)fence;
+}
+
+static void
+intel_drm_fence_reference(struct intel_winsys *iws,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ struct intel_drm_fence *old = (struct intel_drm_fence *)*ptr;
+ struct intel_drm_fence *f = (struct intel_drm_fence *)fence;
+
+ if (pipe_reference((struct pipe_reference**)ptr, &f->reference)) {
+ if (old->bo)
+ drm_intel_bo_unreference(old->bo);
+ FREE(old);
+ }
+}
+
+static int
+intel_drm_fence_signalled(struct intel_winsys *iws,
+ struct pipe_fence_handle *fence)
+{
+ assert(0);
+
+ return 0;
+}
+
+static int
+intel_drm_fence_finish(struct intel_winsys *iws,
+ struct pipe_fence_handle *fence)
+{
+ struct intel_drm_fence *f = (struct intel_drm_fence *)fence;
+
+ /* fence already expired */
+ if (!f->bo)
+ return 0;
+
+ drm_intel_bo_wait_rendering(f->bo);
+ drm_intel_bo_unreference(f->bo);
+ f->bo = NULL;
+
+ return 0;
+}
+
+void
+intel_drm_winsys_init_fence_functions(struct intel_drm_winsys *idws)
+{
+ idws->base.fence_reference = intel_drm_fence_reference;
+ idws->base.fence_signalled = intel_drm_fence_signalled;
+ idws->base.fence_finish = intel_drm_fence_finish;
+}
diff --git a/src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h b/src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h
new file mode 100644
index 0000000000..415c45feea
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/gem/intel_drm_winsys.h
@@ -0,0 +1,78 @@
+
+#ifndef INTEL_DRM_WINSYS_H
+#define INTEL_DRM_WINSYS_H
+
+#include "i915simple/intel_batchbuffer.h"
+
+#include "drm.h"
+#include "intel_bufmgr.h"
+
+
+/*
+ * Winsys
+ */
+
+
+struct intel_drm_winsys
+{
+ struct intel_winsys base;
+
+ boolean softpipe;
+ boolean dump_cmd;
+
+ int fd; /**< Drm file discriptor */
+
+ unsigned id;
+
+ size_t max_batch_size;
+
+ struct {
+ drm_intel_bufmgr *gem;
+ } pools;
+};
+
+static INLINE struct intel_drm_winsys *
+intel_drm_winsys(struct intel_winsys *iws)
+{
+ return (struct intel_drm_winsys *)iws;
+}
+
+struct intel_drm_winsys * intel_drm_winsys_create(int fd, unsigned pci_id);
+struct pipe_fence_handle * intel_drm_fence_create(drm_intel_bo *bo);
+
+void intel_drm_winsys_init_batchbuffer_functions(struct intel_drm_winsys *idws);
+void intel_drm_winsys_init_buffer_functions(struct intel_drm_winsys *idws);
+void intel_drm_winsys_init_fence_functions(struct intel_drm_winsys *idws);
+
+
+/*
+ * Buffer
+ */
+
+
+struct intel_drm_buffer {
+ unsigned magic;
+
+ drm_intel_bo *bo;
+
+ void *ptr;
+ unsigned map_count;
+ boolean map_gtt;
+
+ boolean flinked;
+ unsigned flink;
+};
+
+static INLINE struct intel_drm_buffer *
+intel_drm_buffer(struct intel_buffer *buffer)
+{
+ return (struct intel_drm_buffer *)buffer;
+}
+
+static INLINE drm_intel_bo *
+intel_bo(struct intel_buffer *buffer)
+{
+ return intel_drm_buffer(buffer)->bo;
+}
+
+#endif
diff --git a/src/gallium/winsys/drm/intel/xorg/Makefile b/src/gallium/winsys/drm/intel/xorg/Makefile
new file mode 100644
index 0000000000..9e56853b02
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/xorg/Makefile
@@ -0,0 +1,57 @@
+TARGET = modesetting_drv.so
+CFILES = $(wildcard ./*.c)
+OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES))
+TOP = ../../../../../..
+
+include $(TOP)/configs/current
+
+INCLUDES = \
+ $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \
+ -I../gem \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/drivers \
+ -I$(TOP)/src/gallium/auxiliary \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/include \
+ -I$(TOP)/src/egl/main
+
+LIBS = \
+ $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \
+ $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \
+ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(GALLIUM_AUXILIARIES)
+
+DRIVER_DEFINES = \
+ -DHAVE_CONFIG_H
+
+
+#############################################
+
+
+
+all default: $(TARGET)
+
+$(TARGET): $(OBJECTS) Makefile $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a $(LIBS)
+ $(TOP)/bin/mklib -noprefix -o $@ \
+ $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_intel
+
+clean:
+ rm -rf $(OBJECTS) $(TARGET)
+
+install:
+ $(INSTALL) -d $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR)
+ $(MINSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR)
+
+
+##############################################
+
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCLUDES) $(DRIVER_DEFINES) $< -o $@
+
+
+##############################################
+
+.PHONY = all clean install
diff --git a/src/gallium/winsys/drm/intel/xorg/intel_xorg.c b/src/gallium/winsys/drm/intel/xorg/intel_xorg.c
new file mode 100644
index 0000000000..369dc356cf
--- /dev/null
+++ b/src/gallium/winsys/drm/intel/xorg/intel_xorg.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Author: Alan Hourihane <alanh@tungstengraphics.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ */
+
+#include "../../../../state_trackers/xorg/xorg_winsys.h"
+
+static void intel_xorg_identify(int flags);
+static Bool intel_xorg_pci_probe(DriverPtr driver,
+ int entity_num,
+ struct pci_device *device,
+ intptr_t match_data);
+
+static const struct pci_id_match intel_xorg_device_match[] = {
+ {0x8086, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0},
+ {0, 0, 0},
+};
+
+static SymTabRec intel_xorg_chipsets[] = {
+ {PCI_MATCH_ANY, "Intel Graphics Device"},
+ {-1, NULL}
+};
+
+static PciChipsets intel_xorg_pci_devices[] = {
+ {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL},
+ {-1, -1, NULL}
+};
+
+static XF86ModuleVersionInfo intel_xorg_version = {
+ "modesetting",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 0, 1, 0, /* major, minor, patch */
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+/*
+ * Xorg driver exported structures
+ */
+
+_X_EXPORT DriverRec modesetting = {
+ 1,
+ "modesetting",
+ intel_xorg_identify,
+ NULL,
+ xorg_tracker_available_options,
+ NULL,
+ 0,
+ NULL,
+ intel_xorg_device_match,
+ intel_xorg_pci_probe
+};
+
+static MODULESETUPPROTO(intel_xorg_setup);
+
+_X_EXPORT XF86ModuleData modesettingModuleData = {
+ &intel_xorg_version,
+ intel_xorg_setup,
+ NULL
+};
+
+/*
+ * Xorg driver functions
+ */
+
+static pointer
+intel_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = 0;
+
+ /* This module should be loaded only once, but check to be sure.
+ */
+ if (!setupDone) {
+ setupDone = 1;
+ xf86AddDriver(&modesetting, module, HaveDriverFuncs);
+
+ /*
+ * The return value must be non-NULL on success even though there
+ * is no TearDownProc.
+ */
+ return (pointer) 1;
+ } else {
+ if (errmaj)
+ *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+
+static void
+intel_xorg_identify(int flags)
+{
+ xf86PrintChipsets("modesetting", "Driver for Modesetting Kernel Drivers",
+ intel_xorg_chipsets);
+}
+
+static Bool
+intel_xorg_pci_probe(DriverPtr driver,
+ int entity_num, struct pci_device *device, intptr_t match_data)
+{
+ ScrnInfoPtr scrn = NULL;
+ EntityInfoPtr entity;
+
+ scrn = xf86ConfigPciEntity(scrn, 0, entity_num, intel_xorg_pci_devices,
+ NULL, NULL, NULL, NULL, NULL);
+ if (scrn != NULL) {
+ scrn->driverVersion = 1;
+ scrn->driverName = "i915";
+ scrn->name = "modesetting";
+ scrn->Probe = NULL;
+
+ entity = xf86GetEntityInfo(entity_num);
+
+ /* Use all the functions from the xorg tracker */
+ xorg_tracker_set_functions(scrn);
+ }
+ return scrn != NULL;
+}
diff --git a/src/gallium/winsys/drm/nouveau/Makefile b/src/gallium/winsys/drm/nouveau/Makefile
new file mode 100644
index 0000000000..6c9cbef26d
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/Makefile
@@ -0,0 +1,12 @@
+# src/gallium/winsys/drm/nouveau/Makefile
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+SUBDIRS = drm $(GALLIUM_STATE_TRACKERS_DIRS)
+
+default install clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) $@) || exit 1; \
+ fi \
+ done
diff --git a/src/gallium/winsys/drm/nouveau/dri/Makefile b/src/gallium/winsys/drm/nouveau/dri/Makefile
new file mode 100644
index 0000000000..0937f68c34
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/dri/Makefile
@@ -0,0 +1,27 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nouveau_dri.so
+
+PIPE_DRIVERS = \
+ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \
+ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \
+ $(TOP)/src/gallium/drivers/nv04/libnv04.a \
+ $(TOP)/src/gallium/drivers/nv10/libnv10.a \
+ $(TOP)/src/gallium/drivers/nv20/libnv20.a \
+ $(TOP)/src/gallium/drivers/nv30/libnv30.a \
+ $(TOP)/src/gallium/drivers/nv40/libnv40.a \
+ $(TOP)/src/gallium/drivers/nv50/libnv50.a \
+ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a
+
+DRIVER_SOURCES =
+
+C_SOURCES = \
+ $(COMMON_GALLIUM_SOURCES) \
+ $(DRIVER_SOURCES)
+
+include ../../Makefile.template
+
+DRI_LIB_DEPS += $(shell pkg-config libdrm_nouveau --libs)
+
+symlinks:
diff --git a/src/gallium/winsys/drm/nouveau/drm/Makefile b/src/gallium/winsys/drm/nouveau/drm/Makefile
new file mode 100644
index 0000000000..54c3b26c75
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/drm/Makefile
@@ -0,0 +1,11 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nouveaudrm
+
+C_SOURCES = nouveau_drm_api.c
+
+LIBRARY_INCLUDES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-I)
+LIBRARY_DEFINES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-other)
+
+include ../../../../Makefile.template
diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h b/src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h
new file mode 100644
index 0000000000..1207c2d609
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h
@@ -0,0 +1,28 @@
+#ifndef _NOUVEAU_DRI_
+#define _NOUVEAU_DRI_
+
+#include "xf86drm.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+
+struct nouveau_dri {
+ uint32_t device_id; /**< \brief PCI device ID */
+ uint32_t width; /**< \brief width in pixels of display */
+ uint32_t height; /**< \brief height in scanlines of display */
+ uint32_t depth; /**< \brief depth of display (8, 15, 16, 24) */
+ uint32_t bpp; /**< \brief bit depth of display (8, 16, 24, 32) */
+
+ uint32_t bus_type; /**< \brief ths bus type */
+ uint32_t bus_mode; /**< \brief bus mode (used for AGP, maybe also for PCI-E ?) */
+
+ uint32_t front_offset; /**< \brief front buffer offset */
+ uint32_t front_pitch; /**< \brief front buffer pitch */
+ uint32_t back_offset; /**< \brief private back buffer offset */
+ uint32_t back_pitch; /**< \brief private back buffer pitch */
+ uint32_t depth_offset; /**< \brief private depth buffer offset */
+ uint32_t depth_pitch; /**< \brief private depth buffer pitch */
+
+};
+
+#endif
+
diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
new file mode 100644
index 0000000000..091cbbcfed
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
@@ -0,0 +1,263 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "util/u_memory.h"
+
+#include "nouveau_drm_api.h"
+
+#include "nouveau_drmif.h"
+#include "nouveau_channel.h"
+#include "nouveau_bo.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_screen.h"
+
+static struct pipe_surface *
+dri_surface_from_handle(struct drm_api *api, struct pipe_screen *pscreen,
+ unsigned handle, enum pipe_format format,
+ unsigned width, unsigned height, unsigned pitch)
+{
+ struct pipe_surface *ps = NULL;
+ struct pipe_texture *pt = NULL;
+ struct pipe_texture tmpl;
+
+ memset(&tmpl, 0, sizeof(tmpl));
+ tmpl.tex_usage = PIPE_TEXTURE_USAGE_PRIMARY |
+ NOUVEAU_TEXTURE_USAGE_LINEAR;
+ tmpl.target = PIPE_TEXTURE_2D;
+ tmpl.last_level = 0;
+ tmpl.depth[0] = 1;
+ tmpl.format = format;
+ tmpl.width[0] = width;
+ tmpl.height[0] = height;
+ pf_get_block(tmpl.format, &tmpl.block);
+
+ pt = api->texture_from_shared_handle(api, pscreen, &tmpl,
+ "front buffer", pitch, handle);
+ if (!pt)
+ return NULL;
+
+ ps = pscreen->get_tex_surface(pscreen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* we don't need the texture from this point on */
+ pipe_texture_reference(&pt, NULL);
+ return ps;
+}
+
+static struct pipe_surface *
+nouveau_dri1_front_surface(struct pipe_context *pipe)
+{
+ return nouveau_winsys_screen(pipe->screen)->front;
+}
+
+static struct dri1_api nouveau_dri1_api = {
+ nouveau_dri1_front_surface,
+};
+
+static struct pipe_screen *
+nouveau_drm_create_screen(struct drm_api *api, int fd,
+ struct drm_create_screen_arg *arg)
+{
+ struct dri1_create_screen_arg *dri1 = (void *)arg;
+ struct nouveau_winsys *nvws;
+ struct pipe_winsys *ws;
+ struct nouveau_device *dev = NULL;
+ struct pipe_screen *(*init)(struct pipe_winsys *,
+ struct nouveau_device *);
+ int ret;
+
+ ret = nouveau_device_open_existing(&dev, 0, fd, 0);
+ if (ret)
+ return NULL;
+
+ switch (dev->chipset & 0xf0) {
+ case 0x00:
+ init = nv04_screen_create;
+ break;
+ case 0x10:
+ init = nv10_screen_create;
+ break;
+ case 0x20:
+ init = nv20_screen_create;
+ break;
+ case 0x30:
+ init = nv30_screen_create;
+ break;
+ case 0x40:
+ case 0x60:
+ init = nv40_screen_create;
+ break;
+ case 0x80:
+ case 0x90:
+ case 0xa0:
+ init = nv50_screen_create;
+ break;
+ default:
+ debug_printf("%s: unknown chipset nv%02x\n", __func__,
+ dev->chipset);
+ return NULL;
+ }
+
+ nvws = CALLOC_STRUCT(nouveau_winsys);
+ if (!nvws) {
+ nouveau_device_close(&dev);
+ return NULL;
+ }
+ ws = &nvws->base;
+
+ nvws->pscreen = init(ws, dev);
+ if (!nvws->pscreen) {
+ ws->destroy(ws);
+ return NULL;
+ }
+
+ if (arg->mode == DRM_CREATE_DRI1) {
+ struct nouveau_dri *nvdri = dri1->ddx_info;
+ enum pipe_format format;
+
+ if (nvdri->bpp == 16)
+ format = PIPE_FORMAT_R5G6B5_UNORM;
+ else
+ format = PIPE_FORMAT_A8R8G8B8_UNORM;
+
+ nvws->front = dri_surface_from_handle(api, nvws->pscreen,
+ nvdri->front_offset,
+ format, nvdri->width,
+ nvdri->height,
+ nvdri->front_pitch *
+ (nvdri->bpp / 8));
+ if (!nvws->front) {
+ debug_printf("%s: error referencing front buffer\n",
+ __func__);
+ ws->destroy(ws);
+ return NULL;
+ }
+
+ dri1->api = &nouveau_dri1_api;
+ }
+
+ return nvws->pscreen;
+}
+
+static struct pipe_context *
+nouveau_drm_create_context(struct drm_api *api, struct pipe_screen *pscreen)
+{
+ struct nouveau_winsys *nvws = nouveau_winsys_screen(pscreen);
+ struct pipe_context *(*init)(struct pipe_screen *, unsigned);
+ unsigned chipset = nouveau_screen(pscreen)->device->chipset;
+ int i;
+
+ switch (chipset & 0xf0) {
+ case 0x00:
+ init = nv04_create;
+ break;
+ case 0x10:
+ init = nv10_create;
+ break;
+ case 0x20:
+ init = nv20_create;
+ break;
+ case 0x30:
+ init = nv30_create;
+ break;
+ case 0x40:
+ case 0x60:
+ init = nv40_create;
+ break;
+ case 0x80:
+ case 0x90:
+ case 0xa0:
+ init = nv50_create;
+ break;
+ default:
+ debug_printf("%s: unknown chipset nv%02x\n", __func__, chipset);
+ return NULL;
+ }
+
+ /* Find a free slot for a pipe context, allocate a new one if needed */
+ for (i = 0; i < nvws->nr_pctx; i++) {
+ if (nvws->pctx[i] == NULL)
+ break;
+ }
+
+ if (i == nvws->nr_pctx) {
+ nvws->nr_pctx++;
+ nvws->pctx = realloc(nvws->pctx,
+ sizeof(*nvws->pctx) * nvws->nr_pctx);
+ }
+
+ nvws->pctx[i] = init(pscreen, i);
+ return nvws->pctx[i];
+}
+
+static struct pipe_texture *
+nouveau_drm_pt_from_name(struct drm_api *api, struct pipe_screen *pscreen,
+ struct pipe_texture *templ, const char *name,
+ unsigned stride, unsigned handle)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct pipe_buffer *pb;
+ int ret;
+
+ pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*));
+ if (!pb)
+ return NULL;
+
+ ret = nouveau_bo_handle_ref(dev, handle, (struct nouveau_bo**)(pb+1));
+ if (ret) {
+ debug_printf("%s: ref name 0x%08x failed with %d\n",
+ __func__, handle, ret);
+ FREE(pb);
+ return NULL;
+ }
+
+ pipe_reference_init(&pb->reference, 1);
+ pb->screen = pscreen;
+ pb->alignment = 0;
+ pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE |
+ PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ pb->size = nouveau_bo(pb)->size;
+ return pscreen->texture_blanket(pscreen, templ, &stride, pb);
+}
+
+static boolean
+nouveau_drm_name_from_pt(struct drm_api *api, struct pipe_screen *pscreen,
+ struct pipe_texture *pt, unsigned *stride,
+ unsigned *handle)
+{
+ struct nouveau_miptree *mt = nouveau_miptree(pt);
+
+ if (!mt || !mt->bo)
+ return false;
+
+ return nouveau_bo_handle_get(mt->bo, handle) == 0;
+}
+
+static boolean
+nouveau_drm_handle_from_pt(struct drm_api *api, struct pipe_screen *pscreen,
+ struct pipe_texture *pt, unsigned *stride,
+ unsigned *handle)
+{
+ struct nouveau_miptree *mt = nouveau_miptree(pt);
+
+ if (!mt || !mt->bo)
+ return false;
+
+ *handle = mt->bo->handle;
+ return true;
+}
+
+struct drm_api drm_api_hooks = {
+ .create_screen = nouveau_drm_create_screen,
+ .create_context = nouveau_drm_create_context,
+ .texture_from_shared_handle = nouveau_drm_pt_from_name,
+ .shared_handle_from_texture = nouveau_drm_name_from_pt,
+ .local_handle_from_texture = nouveau_drm_handle_from_pt,
+};
+
+struct drm_api *
+drm_api_create() {
+ return &drm_api_hooks;
+}
+
diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h
new file mode 100644
index 0000000000..e61e0e0957
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h
@@ -0,0 +1,34 @@
+#ifndef __NOUVEAU_DRM_API_H__
+#define __NOUVEAU_DRM_API_H__
+
+#include "state_tracker/drm_api.h"
+#include "state_tracker/dri1_api.h"
+
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "nouveau_dri.h"
+
+struct nouveau_winsys {
+ struct pipe_winsys base;
+
+ struct pipe_screen *pscreen;
+
+ unsigned nr_pctx;
+ struct pipe_context **pctx;
+
+ struct pipe_surface *front;
+};
+
+static INLINE struct nouveau_winsys *
+nouveau_winsys(struct pipe_winsys *ws)
+{
+ return (struct nouveau_winsys *)ws;
+}
+
+static INLINE struct nouveau_winsys *
+nouveau_winsys_screen(struct pipe_screen *pscreen)
+{
+ return nouveau_winsys(pscreen->winsys);
+}
+
+#endif
diff --git a/src/gallium/winsys/drm/radeon/Makefile b/src/gallium/winsys/drm/radeon/Makefile
new file mode 100644
index 0000000000..bacdf3de28
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/Makefile
@@ -0,0 +1,12 @@
+# src/gallium/winsys/drm/radeon/Makefile
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+SUBDIRS = core $(GALLIUM_STATE_TRACKERS_DIRS)
+
+default install clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) $@) || exit 1; \
+ fi \
+ done
diff --git a/src/gallium/winsys/drm/radeon/SConscript b/src/gallium/winsys/drm/radeon/SConscript
new file mode 100644
index 0000000000..b2dfd504d4
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/SConscript
@@ -0,0 +1,7 @@
+Import('*')
+
+SConscript(['core/SConscript',])
+
+if 'mesa' in env['statetrackers']:
+
+ SConscript(['dri/SConscript'])
diff --git a/src/gallium/winsys/drm/radeon/core/Makefile b/src/gallium/winsys/drm/radeon/core/Makefile
new file mode 100644
index 0000000000..42a6f4abc2
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/Makefile
@@ -0,0 +1,18 @@
+
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = radeonwinsys
+
+C_SOURCES = \
+ radeon_buffer.c \
+ radeon_drm.c \
+ radeon_r300.c \
+ radeon_winsys_softpipe.c
+
+LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/r300 \
+ $(shell pkg-config libdrm --cflags-only-I)
+
+include ../../../../Makefile.template
+
+symlinks:
diff --git a/src/gallium/winsys/drm/radeon/core/SConscript b/src/gallium/winsys/drm/radeon/core/SConscript
new file mode 100644
index 0000000000..2ad68e403f
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/SConscript
@@ -0,0 +1,19 @@
+Import('*')
+
+env = drienv.Clone()
+
+radeon_sources = [
+ 'radeon_buffer.c',
+ 'radeon_drm.c',
+ 'radeon_r300.c',
+ 'radeon_winsys_softpipe.c',
+]
+
+env.Append(CPPPATH = '#/src/gallium/drivers/r300')
+
+radeonwinsys = env.ConvenienceLibrary(
+ target ='radeonwinsys',
+ source = radeon_sources,
+)
+
+Export('radeonwinsys')
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c
new file mode 100644
index 0000000000..7bf23cba23
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright © 2008 Jérôme Glisse
+ * 2009 Corbin Simpson
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Jérôme Glisse <glisse@freedesktop.org>
+ * Corbin Simpson <MostAwesomeDude@gmail.com>
+ */
+
+#include "radeon_buffer.h"
+
+#include "radeon_bo_gem.h"
+
+static const char *radeon_get_name(struct pipe_winsys *ws)
+{
+ return "Radeon/GEM+KMS";
+}
+
+static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct radeon_winsys *radeon_ws = (struct radeon_winsys *)ws;
+ struct radeon_pipe_buffer *radeon_buffer;
+ uint32_t domain;
+
+ radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer);
+ if (radeon_buffer == NULL) {
+ return NULL;
+ }
+
+ pipe_reference_init(&radeon_buffer->base.reference, 1);
+ radeon_buffer->base.alignment = alignment;
+ radeon_buffer->base.usage = usage;
+ radeon_buffer->base.size = size;
+
+ domain = 0;
+
+ if (usage & PIPE_BUFFER_USAGE_PIXEL) {
+ domain |= RADEON_GEM_DOMAIN_VRAM;
+ }
+ if (usage & PIPE_BUFFER_USAGE_VERTEX) {
+ domain |= RADEON_GEM_DOMAIN_GTT;
+ }
+ if (usage & PIPE_BUFFER_USAGE_INDEX) {
+ domain |= RADEON_GEM_DOMAIN_GTT;
+ }
+
+ radeon_buffer->bo = radeon_bo_open(radeon_ws->priv->bom, 0, size,
+ alignment, domain, 0);
+ if (radeon_buffer->bo == NULL) {
+ FREE(radeon_buffer);
+ return NULL;
+ }
+ return &radeon_buffer->base;
+}
+
+static struct pipe_buffer *radeon_buffer_user_create(struct pipe_winsys *ws,
+ void *ptr,
+ unsigned bytes)
+{
+ struct radeon_pipe_buffer *radeon_buffer;
+
+ radeon_buffer =
+ (struct radeon_pipe_buffer*)radeon_buffer_create(ws, 0, 0, bytes);
+ if (radeon_buffer == NULL) {
+ return NULL;
+ }
+ radeon_bo_map(radeon_buffer->bo, 1);
+ memcpy(radeon_buffer->bo->ptr, ptr, bytes);
+ radeon_bo_unmap(radeon_buffer->bo);
+ return &radeon_buffer->base;
+}
+
+static struct pipe_buffer *radeon_surface_buffer_create(struct pipe_winsys *ws,
+ unsigned width,
+ unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ struct pipe_format_block block;
+ unsigned nblocksx, nblocksy, size;
+
+ pf_get_block(format, &block);
+
+ nblocksx = pf_get_nblocksx(&block, width);
+ nblocksy = pf_get_nblocksy(&block, height);
+
+ /* Radeons enjoy things in multiples of 32. */
+ /* XXX this can be 32 when POT */
+ *stride = (nblocksx * block.size + 63) & ~63;
+ size = *stride * nblocksy;
+
+ return radeon_buffer_create(ws, 64, usage, size);
+}
+
+static void radeon_buffer_del(struct pipe_buffer *buffer)
+{
+ struct radeon_pipe_buffer *radeon_buffer =
+ (struct radeon_pipe_buffer*)buffer;
+
+ radeon_bo_unref(radeon_buffer->bo);
+ free(radeon_buffer);
+}
+
+static void *radeon_buffer_map(struct pipe_winsys *ws,
+ struct pipe_buffer *buffer,
+ unsigned flags)
+{
+ struct radeon_pipe_buffer *radeon_buffer =
+ (struct radeon_pipe_buffer*)buffer;
+ int write = 0;
+
+ if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) {
+ uint32_t domain;
+
+ if (radeon_bo_is_busy(radeon_buffer->bo, &domain))
+ return NULL;
+ }
+ if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) {
+ write = 1;
+ }
+
+ if (radeon_bo_map(radeon_buffer->bo, write)) {
+ return NULL;
+ }
+
+ return radeon_buffer->bo->ptr;
+}
+
+static void radeon_buffer_unmap(struct pipe_winsys *ws,
+ struct pipe_buffer *buffer)
+{
+ struct radeon_pipe_buffer *radeon_buffer =
+ (struct radeon_pipe_buffer*)buffer;
+
+ radeon_bo_unmap(radeon_buffer->bo);
+}
+
+static void radeon_fence_reference(struct pipe_winsys *ws,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *pfence)
+{
+}
+
+static int radeon_fence_signalled(struct pipe_winsys *ws,
+ struct pipe_fence_handle *pfence,
+ unsigned flag)
+{
+ return 1;
+}
+
+static int radeon_fence_finish(struct pipe_winsys *ws,
+ struct pipe_fence_handle *pfence,
+ unsigned flag)
+{
+ return 0;
+}
+
+static void radeon_flush_frontbuffer(struct pipe_winsys *pipe_winsys,
+ struct pipe_surface *pipe_surface,
+ void *context_private)
+{
+ /* XXX TODO: call dri2CopyRegion */
+}
+
+struct radeon_winsys* radeon_pipe_winsys(int fd)
+{
+ struct radeon_winsys* radeon_ws;
+
+ radeon_ws = CALLOC_STRUCT(radeon_winsys);
+ if (radeon_ws == NULL) {
+ return NULL;
+ }
+
+ radeon_ws->priv = CALLOC_STRUCT(radeon_winsys_priv);
+ if (radeon_ws->priv == NULL) {
+ FREE(radeon_ws);
+ return NULL;
+ }
+
+ radeon_ws->priv->fd = fd;
+ radeon_ws->priv->bom = radeon_bo_manager_gem_ctor(fd);
+
+ radeon_ws->base.flush_frontbuffer = radeon_flush_frontbuffer;
+
+ radeon_ws->base.buffer_create = radeon_buffer_create;
+ radeon_ws->base.user_buffer_create = radeon_buffer_user_create;
+ radeon_ws->base.surface_buffer_create = radeon_surface_buffer_create;
+ radeon_ws->base.buffer_map = radeon_buffer_map;
+ radeon_ws->base.buffer_unmap = radeon_buffer_unmap;
+ radeon_ws->base.buffer_destroy = radeon_buffer_del;
+
+ radeon_ws->base.fence_reference = radeon_fence_reference;
+ radeon_ws->base.fence_signalled = radeon_fence_signalled;
+ radeon_ws->base.fence_finish = radeon_fence_finish;
+
+ radeon_ws->base.get_name = radeon_get_name;
+
+ return radeon_ws;
+}
+#if 0
+static struct pipe_buffer *radeon_buffer_from_handle(struct radeon_screen *radeon_screen,
+ uint32_t handle)
+{
+ struct radeon_pipe_buffer *radeon_buffer;
+ struct radeon_bo *bo = NULL;
+
+ bo = radeon_bo_open(radeon_screen->bom, handle, 0, 0, 0, 0);
+ if (bo == NULL) {
+ return NULL;
+ }
+ radeon_buffer = calloc(1, sizeof(struct radeon_pipe_buffer));
+ if (radeon_buffer == NULL) {
+ radeon_bo_unref(bo);
+ return NULL;
+ }
+ pipe_reference_init(&radeon_buffer->base.reference, 1);
+ radeon_buffer->base.usage = PIPE_BUFFER_USAGE_PIXEL;
+ radeon_buffer->bo = bo;
+ return &radeon_buffer->base;
+}
+
+struct pipe_surface *radeon_surface_from_handle(struct radeon_context *radeon_context,
+ uint32_t handle,
+ enum pipe_format format,
+ int w, int h, int pitch)
+{
+ struct pipe_screen *pipe_screen = radeon_context->pipe_screen;
+ struct pipe_winsys *pipe_winsys = radeon_context->pipe_winsys;
+ struct pipe_texture tmpl;
+ struct pipe_surface *ps;
+ struct pipe_texture *pt;
+ struct pipe_buffer *pb;
+
+ pb = radeon_buffer_from_handle(radeon_context->radeon_screen, handle);
+ if (pb == NULL) {
+ return NULL;
+ }
+ memset(&tmpl, 0, sizeof(tmpl));
+ tmpl.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
+ tmpl.target = PIPE_TEXTURE_2D;
+ tmpl.width[0] = w;
+ tmpl.height[0] = h;
+ tmpl.depth[0] = 1;
+ tmpl.format = format;
+ pf_get_block(tmpl.format, &tmpl.block);
+ tmpl.nblocksx[0] = pf_get_nblocksx(&tmpl.block, w);
+ tmpl.nblocksy[0] = pf_get_nblocksy(&tmpl.block, h);
+
+ pt = pipe_screen->texture_blanket(pipe_screen, &tmpl, &pitch, pb);
+ if (pt == NULL) {
+ pipe_buffer_reference(&pb, NULL);
+ }
+ ps = pipe_screen->get_tex_surface(pipe_screen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ return ps;
+}
+#endif
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h
new file mode 100644
index 0000000000..f5153b06af
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Jérôme Glisse <glisse@freedesktop.org>
+ */
+#ifndef RADEON_BUFFER_H
+#define RADEON_BUFFER_H
+
+#include <stdio.h>
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+//#include "state_tracker/st_public.h"
+
+#include "util/u_memory.h"
+
+#include "radeon_bo.h"
+#include "radeon_cs.h"
+
+#include "radeon_drm.h"
+
+struct radeon_pipe_buffer {
+ struct pipe_buffer base;
+ struct radeon_bo *bo;
+ boolean flinked;
+ uint32_t flink;
+};
+
+#define RADEON_MAX_BOS 24
+
+struct radeon_winsys_priv {
+ /* DRM FD */
+ int fd;
+
+ /* Radeon BO manager. */
+ struct radeon_bo_manager* bom;
+
+ /* Radeon CS manager. */
+ struct radeon_cs_manager* csm;
+
+ /* Current CS. */
+ struct radeon_cs* cs;
+};
+
+struct radeon_winsys {
+ /* Parent class. */
+ struct pipe_winsys base;
+
+ /* This corresponds to void* radeon_winsys in r300_winsys. */
+ struct radeon_winsys_priv* priv;
+};
+
+struct radeon_winsys* radeon_pipe_winsys(int fb);
+#if 0
+struct pipe_surface *radeon_surface_from_handle(struct radeon_context *radeon_context,
+ uint32_t handle,
+ enum pipe_format format,
+ int w, int h, int pitch);
+#endif
+#endif
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.c b/src/gallium/winsys/drm/radeon/core/radeon_drm.c
new file mode 100644
index 0000000000..a4011db0b8
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright © 2009 Corbin Simpson
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Joakim Sindholt <opensource@zhasha.com>
+ */
+
+#include "radeon_drm.h"
+
+/* Create a pipe_screen. */
+struct pipe_screen* radeon_create_screen(struct drm_api* api,
+ int drmFB,
+ struct drm_create_screen_arg *arg)
+{
+ struct radeon_winsys* winsys = radeon_pipe_winsys(drmFB);
+
+ if (getenv("RADEON_SOFTPIPE")) {
+ return softpipe_create_screen((struct pipe_winsys*)winsys);
+ } else {
+ struct r300_winsys* r300 = radeon_create_r300_winsys(drmFB, winsys);
+ FREE(winsys);
+ return r300_create_screen(r300);
+ }
+}
+
+/* Create a pipe_context. */
+struct pipe_context* radeon_create_context(struct drm_api* api,
+ struct pipe_screen* screen)
+{
+ if (getenv("RADEON_SOFTPIPE")) {
+ return radeon_create_softpipe(screen->winsys);
+ } else {
+ return r300_create_context(screen,
+ (struct r300_winsys*)screen->winsys);
+ }
+}
+
+boolean radeon_buffer_from_texture(struct drm_api* api,
+ struct pipe_texture* texture,
+ struct pipe_buffer** buffer,
+ unsigned* stride)
+{
+ /* XXX fix this */
+ return r300_get_texture_buffer(texture, buffer, stride);
+}
+
+/* Create a buffer from a handle. */
+/* XXX what's up with name? */
+struct pipe_buffer* radeon_buffer_from_handle(struct drm_api* api,
+ struct pipe_screen* screen,
+ const char* name,
+ unsigned handle)
+{
+ struct radeon_bo_manager* bom =
+ ((struct radeon_winsys*)screen->winsys)->priv->bom;
+ struct radeon_pipe_buffer* radeon_buffer;
+ struct radeon_bo* bo = NULL;
+
+ bo = radeon_bo_open(bom, handle, 0, 0, 0, 0);
+ if (bo == NULL) {
+ return NULL;
+ }
+
+ radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer);
+ if (radeon_buffer == NULL) {
+ radeon_bo_unref(bo);
+ return NULL;
+ }
+
+ pipe_reference_init(&radeon_buffer->base.reference, 1);
+ radeon_buffer->base.screen = screen;
+ radeon_buffer->base.usage = PIPE_BUFFER_USAGE_PIXEL;
+ radeon_buffer->bo = bo;
+ return &radeon_buffer->base;
+}
+
+static struct pipe_texture*
+radeon_texture_from_shared_handle(struct drm_api *api,
+ struct pipe_screen *screen,
+ struct pipe_texture *templ,
+ const char *name,
+ unsigned stride,
+ unsigned handle)
+{
+ struct pipe_buffer *buffer;
+
+ buffer = radeon_buffer_from_handle(api, screen, name, handle);
+ if (!buffer) {
+ return NULL;
+ }
+
+ return screen->texture_blanket(screen, templ, &stride, buffer);
+}
+
+static boolean radeon_shared_handle_from_texture(struct drm_api *api,
+ struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned *stride,
+ unsigned *handle)
+{
+ int retval, fd;
+ struct drm_gem_flink flink;
+ struct radeon_pipe_buffer* radeon_buffer;
+ struct pipe_buffer *buffer;
+
+ if (!radeon_buffer_from_texture(api, texture, &buffer, stride)) {
+ return FALSE;
+ }
+
+ radeon_buffer = (struct radeon_pipe_buffer*)buffer;
+ if (!radeon_buffer->flinked) {
+ fd = ((struct radeon_winsys*)screen->winsys)->priv->fd;
+
+ flink.handle = radeon_buffer->bo->handle;
+
+ retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
+ if (retval) {
+ debug_printf("radeon: DRM_IOCTL_GEM_FLINK failed, error %d\n",
+ retval);
+ return FALSE;
+ }
+
+ radeon_buffer->flink = flink.name;
+ radeon_buffer->flinked = TRUE;
+ }
+
+ *handle = radeon_buffer->flink;
+ return TRUE;
+}
+
+static boolean radeon_local_handle_from_texture(struct drm_api *api,
+ struct pipe_screen *screen,
+ struct pipe_texture *texture,
+ unsigned *stride,
+ unsigned *handle)
+{
+ struct pipe_buffer *buffer;
+ if (!radeon_buffer_from_texture(api, texture, &buffer, stride)) {
+ return FALSE;
+ }
+
+ *handle = ((struct radeon_pipe_buffer*)buffer)->bo->handle;
+
+ pipe_buffer_reference(&buffer, NULL);
+
+ return TRUE;
+}
+
+struct drm_api drm_api_hooks = {
+ .create_screen = radeon_create_screen,
+ .create_context = radeon_create_context,
+ .texture_from_shared_handle = radeon_texture_from_shared_handle,
+ .shared_handle_from_texture = radeon_shared_handle_from_texture,
+ .local_handle_from_texture = radeon_local_handle_from_texture,
+};
+
+struct drm_api* drm_api_create()
+{
+#ifdef DEBUG
+ return trace_drm_create(&drm_api_hooks);
+#else
+ return &drm_api_hooks;
+#endif
+}
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.h b/src/gallium/winsys/drm/radeon/core/radeon_drm.h
new file mode 100644
index 0000000000..88a5c82b28
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2009 Corbin Simpson
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Corbin Simpson <MostAwesomeDude@gmail.com>
+ */
+#ifndef RADEON_DRM_H
+#define RADEON_DRM_H
+
+#include <sys/ioctl.h>
+
+#include "xf86drm.h"
+
+#include "pipe/p_screen.h"
+
+#include "trace/tr_drm.h"
+#include "util/u_memory.h"
+
+#include "state_tracker/drm_api.h"
+
+#include "radeon_buffer.h"
+#include "radeon_r300.h"
+#include "radeon_winsys_softpipe.h"
+
+/* XXX */
+#include "r300_screen.h"
+
+struct pipe_screen* radeon_create_screen(struct drm_api* api,
+ int drmFB,
+ struct drm_create_screen_arg *arg);
+
+struct pipe_context* radeon_create_context(struct drm_api* api,
+ struct pipe_screen* screen);
+
+boolean radeon_buffer_from_texture(struct drm_api* api,
+ struct pipe_texture* texture,
+ struct pipe_buffer** buffer,
+ unsigned* stride);
+
+struct pipe_buffer* radeon_buffer_from_handle(struct drm_api* api,
+ struct pipe_screen* screen,
+ const char* name,
+ unsigned handle);
+
+boolean radeon_handle_from_buffer(struct drm_api* api,
+ struct pipe_screen* screen,
+ struct pipe_buffer* buffer,
+ unsigned* handle);
+
+boolean radeon_global_handle_from_buffer(struct drm_api* api,
+ struct pipe_screen* screen,
+ struct pipe_buffer* buffer,
+ unsigned* handle);
+
+void radeon_destroy_drm_api(struct drm_api* api);
+#endif
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c
new file mode 100644
index 0000000000..d2d84f1a8f
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "radeon_r300.h"
+
+static boolean radeon_r300_add_buffer(struct r300_winsys* winsys,
+ struct pipe_buffer* pbuffer,
+ uint32_t rd,
+ uint32_t wd)
+{
+ struct radeon_winsys_priv* priv =
+ (struct radeon_winsys_priv*)winsys->radeon_winsys;
+ struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo;
+
+ radeon_cs_space_add_persistent_bo(priv->cs, bo, rd, wd);
+ return TRUE;
+}
+
+static boolean radeon_r300_validate(struct r300_winsys* winsys)
+{
+ struct radeon_winsys_priv* priv =
+ (struct radeon_winsys_priv*)winsys->radeon_winsys;
+
+ if (radeon_cs_space_check(priv->cs) < 0) {
+ return FALSE;
+ }
+
+ /* Things are fine, we can proceed as normal. */
+ return TRUE;
+}
+
+static boolean radeon_r300_check_cs(struct r300_winsys* winsys, int size)
+{
+ /* XXX check size here, lazy ass! */
+ /* XXX also validate buffers */
+ return TRUE;
+}
+
+static void radeon_r300_begin_cs(struct r300_winsys* winsys,
+ int size,
+ const char* file,
+ const char* function,
+ int line)
+{
+ struct radeon_winsys_priv* priv =
+ (struct radeon_winsys_priv*)winsys->radeon_winsys;
+
+ radeon_cs_begin(priv->cs, size, file, function, line);
+}
+
+static void radeon_r300_write_cs_dword(struct r300_winsys* winsys,
+ uint32_t dword)
+{
+ struct radeon_winsys_priv* priv =
+ (struct radeon_winsys_priv*)winsys->radeon_winsys;
+
+ radeon_cs_write_dword(priv->cs, dword);
+}
+
+static void radeon_r300_write_cs_reloc(struct r300_winsys* winsys,
+ struct pipe_buffer* pbuffer,
+ uint32_t rd,
+ uint32_t wd,
+ uint32_t flags)
+{
+ struct radeon_winsys_priv* priv =
+ (struct radeon_winsys_priv*)winsys->radeon_winsys;
+ int retval = 0;
+
+ retval = radeon_cs_write_reloc(priv->cs,
+ ((struct radeon_pipe_buffer*)pbuffer)->bo, rd, wd, flags);
+
+ if (retval) {
+ debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n",
+ pbuffer, rd, wd, flags);
+ }
+}
+
+static void radeon_r300_end_cs(struct r300_winsys* winsys,
+ const char* file,
+ const char* function,
+ int line)
+{
+ struct radeon_winsys_priv* priv =
+ (struct radeon_winsys_priv*)winsys->radeon_winsys;
+
+ radeon_cs_end(priv->cs, file, function, line);
+}
+
+static void radeon_r300_flush_cs(struct r300_winsys* winsys)
+{
+ struct radeon_winsys_priv* priv =
+ (struct radeon_winsys_priv*)winsys->radeon_winsys;
+ int retval;
+
+ /* Emit the CS. */
+ retval = radeon_cs_emit(priv->cs);
+ if (retval) {
+ debug_printf("radeon: Bad CS, dumping...\n");
+ radeon_cs_print(priv->cs, stderr);
+ }
+
+ /* Clean out BOs. */
+ radeon_cs_space_reset_bos(priv->cs);
+
+ /* Reset CS.
+ * Someday, when we care about performance, we should really find a way
+ * to rotate between two or three CS objects so that the GPU can be
+ * spinning through one CS while another one is being filled. */
+ radeon_cs_erase(priv->cs);
+}
+
+/* Helper function to do the ioctls needed for setup and init. */
+static void do_ioctls(struct r300_winsys* winsys, int fd)
+{
+ struct drm_radeon_gem_info gem_info = {0};
+ struct drm_radeon_info info = {0};
+ int target = 0;
+ int retval;
+
+ info.value = (unsigned long)&target;
+
+ /* First, get the number of pixel pipes */
+ info.request = RADEON_INFO_NUM_GB_PIPES;
+ retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
+ if (retval) {
+ fprintf(stderr, "%s: Failed to get GB pipe count, "
+ "error number %d\n", __FUNCTION__, retval);
+ exit(1);
+ }
+ winsys->gb_pipes = target;
+
+ /* Then, get PCI ID */
+ info.request = RADEON_INFO_DEVICE_ID;
+ retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
+ if (retval) {
+ fprintf(stderr, "%s: Failed to get PCI ID, "
+ "error number %d\n", __FUNCTION__, retval);
+ exit(1);
+ }
+ winsys->pci_id = target;
+
+ /* Finally, retrieve MM info */
+ retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO,
+ &gem_info, sizeof(gem_info));
+ if (retval) {
+ fprintf(stderr, "%s: Failed to get MM info, error number %d\n",
+ __FUNCTION__, retval);
+ exit(1);
+ }
+ winsys->gart_size = gem_info.gart_size;
+ /* XXX */
+ winsys->vram_size = gem_info.vram_visible;
+}
+
+struct r300_winsys*
+radeon_create_r300_winsys(int fd, struct radeon_winsys* old_winsys)
+{
+ struct r300_winsys* winsys = CALLOC_STRUCT(r300_winsys);
+ struct radeon_winsys_priv* priv;
+
+ if (winsys == NULL) {
+ return NULL;
+ }
+
+ priv = old_winsys->priv;
+
+ do_ioctls(winsys, fd);
+
+ priv->csm = radeon_cs_manager_gem_ctor(fd);
+
+ priv->cs = radeon_cs_create(priv->csm, 1024 * 64 / 4);
+ radeon_cs_set_limit(priv->cs,
+ RADEON_GEM_DOMAIN_GTT, winsys->gart_size);
+ radeon_cs_set_limit(priv->cs,
+ RADEON_GEM_DOMAIN_VRAM, winsys->vram_size);
+
+ winsys->add_buffer = radeon_r300_add_buffer;
+ winsys->validate = radeon_r300_validate;
+
+ winsys->check_cs = radeon_r300_check_cs;
+ winsys->begin_cs = radeon_r300_begin_cs;
+ winsys->write_cs_dword = radeon_r300_write_cs_dword;
+ winsys->write_cs_reloc = radeon_r300_write_cs_reloc;
+ winsys->end_cs = radeon_r300_end_cs;
+ winsys->flush_cs = radeon_r300_flush_cs;
+
+ memcpy(winsys, old_winsys, sizeof(struct radeon_winsys));
+
+ return winsys;
+}
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.h b/src/gallium/winsys/drm/radeon/core/radeon_r300.h
new file mode 100644
index 0000000000..775d7937fd
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef RADEON_R300_H
+#define RADEON_R300_H
+
+/* XXX WTF is this! I shouldn't have to include those first three! FUCK! */
+#include <stdint.h>
+#include <stdlib.h>
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_cs_gem.h"
+
+#include "r300_winsys.h"
+
+#include "radeon_buffer.h"
+
+struct radeon_winsys;
+
+struct r300_winsys*
+radeon_create_r300_winsys(int fd, struct radeon_winsys* old_winsys);
+
+#endif /* RADEON_R300_H */
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.c b/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.c
new file mode 100644
index 0000000000..f038bfa40e
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.c
@@ -0,0 +1,41 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+/*
+ * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ */
+
+#include "radeon_winsys_softpipe.h"
+
+struct pipe_context *radeon_create_softpipe(struct pipe_winsys* winsys)
+{
+ struct pipe_screen *pipe_screen;
+
+ pipe_screen = softpipe_create_screen(winsys);
+
+ return softpipe_create(pipe_screen);
+}
diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.h b/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.h
new file mode 100644
index 0000000000..04740e41a5
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/core/radeon_winsys_softpipe.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Jérôme Glisse <glisse@freedesktop.org>
+ */
+#ifndef RADEON_WINSYS_SOFTPIPE_H
+#define RADEON_WINSYS_SOFTPIPE_H
+
+#include <stdio.h>
+
+#include "pipe/p_defines.h"
+#include "pipe/p_format.h"
+
+#include "softpipe/sp_winsys.h"
+
+#include "util/u_memory.h"
+
+struct pipe_context *radeon_create_softpipe(struct pipe_winsys* winsys);
+
+#endif
diff --git a/src/gallium/winsys/drm/radeon/dri/Makefile b/src/gallium/winsys/drm/radeon/dri/Makefile
new file mode 100644
index 0000000000..a9889444de
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/dri/Makefile
@@ -0,0 +1,26 @@
+
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = radeon_dri.so
+
+MINIGLX_SOURCES =
+
+PIPE_DRIVERS = \
+ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \
+ $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/r300/libr300.a
+
+C_SOURCES = \
+ $(COMMON_GALLIUM_SOURCES) \
+ $(DRIVER_SOURCES)
+
+ASM_SOURCES =
+
+include ../../Makefile.template
+
+DRI_LIB_DEPS += -ldrm_radeon
+
+symlinks:
diff --git a/src/gallium/winsys/drm/radeon/dri/SConscript b/src/gallium/winsys/drm/radeon/dri/SConscript
new file mode 100644
index 0000000000..aea987a3ac
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/dri/SConscript
@@ -0,0 +1,17 @@
+Import('*')
+
+env = drienv.Clone()
+
+env.ParseConfig('pkg-config --cflags --libs libdrm_radeon')
+
+drivers = [
+ trace,
+ softpipe,
+ r300
+]
+
+env.SharedLibrary(
+ target ='radeon_dri.so',
+ source = COMMON_GALLIUM_SOURCES,
+ LIBS = st_dri + radeonwinsys + mesa + drivers + auxiliaries + env['LIBS'],
+)
diff --git a/src/gallium/winsys/drm/radeon/egl/Makefile b/src/gallium/winsys/drm/radeon/egl/Makefile
new file mode 100644
index 0000000000..6a1448d1b9
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/egl/Makefile
@@ -0,0 +1,26 @@
+TOP = ../../../../../..
+GALLIUMDIR = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = EGL_r300.so
+
+PIPE_DRIVERS = \
+ $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \
+ $(GALLIUMDIR)/winsys/drm/radeon/core/libradeonwinsys.a \
+ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+ $(TOP)/src/gallium/drivers/trace/libtrace.a \
+ $(TOP)/src/gallium/drivers/r300/libr300.a
+
+DRIVER_SOURCES =
+
+C_SOURCES = \
+ $(COMMON_GALLIUM_SOURCES) \
+ $(DRIVER_SOURCES)
+
+DRIVER_EXTRAS = -ldrm_radeon
+
+ASM_SOURCES =
+
+include ../../Makefile.template
+
+symlinks:
diff --git a/src/gallium/winsys/drm/radeon/python/README b/src/gallium/winsys/drm/radeon/python/README
new file mode 100644
index 0000000000..d9e49bce67
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/python/README
@@ -0,0 +1,15 @@
+Python bindings for the radeon gallium driver.
+
+
+See gallium/src/gallium/state_trackers/python/README for more information.
+
+
+Build as:
+
+ scons debug=1 statetrackers=python winsys=drm/radeon/python
+
+Run as:
+
+ export PYTHONPATH=$PWD/build/linux-x86-debug/gallium/winsys/drm/radeon/python:$PWD/build/linux-x86-debug/gallium/state_trackers/python
+
+ python src/gallium/state_trackers/python/samples/tri.py
diff --git a/src/gallium/winsys/drm/radeon/python/SConscript b/src/gallium/winsys/drm/radeon/python/SConscript
new file mode 100644
index 0000000000..3200fd8d1b
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/python/SConscript
@@ -0,0 +1,33 @@
+import os.path
+
+Import('*')
+
+if env['platform'] == 'linux':
+
+ env = env.Clone()
+
+ env.Tool('python')
+
+ env.ParseConfig('pkg-config --cflags --libs libdrm')
+
+ env.Prepend(CPPPATH = [
+ '#src/gallium/state_trackers/python',
+ '../core',
+ ])
+
+ drivers = [
+ softpipe,
+ radeon,
+ trace,
+ ]
+
+ sources = [
+ 'radeon_hardpipe_winsys.c',
+ 'xf86dri.c',
+ ]
+
+ env.SharedLibrary(
+ target ='_gallium',
+ source = sources,
+ LIBS = [pyst] + drivers + auxiliaries + env['LIBS'],
+ )
diff --git a/src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c b/src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c
new file mode 100644
index 0000000000..c3ec24aaf7
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/python/radeon_hardpipe_winsys.c
@@ -0,0 +1,140 @@
+ /**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <drm/drm.h>
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+
+#include "st_winsys.h"
+
+#include "radeon_winsys.h"
+
+#include "xf86dri.h"
+
+
+/* XXX: Force init_gallium symbol to be linked */
+extern void init_gallium(void);
+void (*force_init_gallium_linkage)(void) = &init_gallium;
+
+
+static struct pipe_screen *
+radeon_hardpipe_screen_create(void)
+{
+ Display *dpy;
+ Window rootWin;
+ XWindowAttributes winAttr;
+ int isCapable;
+ int screen;
+ char *driverName;
+ char *curBusID;
+ unsigned magic;
+ int ddxDriverMajor;
+ int ddxDriverMinor;
+ int ddxDriverPatch;
+ drm_handle_t sAreaOffset;
+ int ret;
+ int drmFD;
+ drm_context_t hHWContext;
+ XID id;
+
+ dpy = XOpenDisplay(":0");
+ if (!dpy) {
+ fprintf(stderr, "Open Display Failed\n");
+ return NULL;
+ }
+
+ screen = DefaultScreen(dpy);
+ rootWin = RootWindow(dpy, screen);
+ XGetWindowAttributes(dpy, rootWin, &winAttr);
+
+ ret = uniDRIQueryDirectRenderingCapable(dpy, screen, &isCapable);
+ if (!ret || !isCapable) {
+ fprintf(stderr, "No DRI on this display:sceen\n");
+ goto error;
+ }
+
+ if (!uniDRIOpenConnection(dpy, screen, &sAreaOffset,
+ &curBusID)) {
+ fprintf(stderr, "Could not open DRI connection.\n");
+ goto error;
+ }
+
+ if (!uniDRIGetClientDriverName(dpy, screen, &ddxDriverMajor,
+ &ddxDriverMinor, &ddxDriverPatch,
+ &driverName)) {
+ fprintf(stderr, "Could not get DRI driver name.\n");
+ goto error;
+ }
+
+ if ((drmFD = drmOpen(NULL, curBusID)) < 0) {
+ perror("DRM Device could not be opened");
+ goto error;
+ }
+
+ drmGetMagic(drmFD, &magic);
+ if (!uniDRIAuthConnection(dpy, screen, magic)) {
+ fprintf(stderr, "Could not get X server to authenticate us.\n");
+ goto error;
+ }
+
+ if (!uniDRICreateContext(dpy, screen, winAttr.visual,
+ &id, &hHWContext)) {
+ fprintf(stderr, "Could not create DRI context.\n");
+ goto error;
+ }
+
+ /* FIXME: create a radeon pipe_screen from drmFD and hHWContext */
+
+ return NULL;
+
+error:
+ return NULL;
+}
+
+
+static struct pipe_context *
+radeon_hardpipe_context_create(struct pipe_screen *screen)
+{
+ /* FIXME: create a radon pipe_context from screen */
+
+ return NULL;
+}
+
+
+const struct st_winsys st_hardpipe_winsys = {
+ &radeon_hardpipe_screen_create,
+ &radeon_hardpipe_context_create,
+};
+
diff --git a/src/gallium/winsys/drm/radeon/python/xf86dri.c b/src/gallium/winsys/drm/radeon/python/xf86dri.c
new file mode 100644
index 0000000000..1736f1e54f
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/python/xf86dri.c
@@ -0,0 +1,605 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, 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 PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include "xf86dristr.h"
+
+static XExtensionInfo _xf86dri_info_data;
+static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
+static char xf86dri_extension_name[] = XF86DRINAME;
+
+#define uniDRICheckExtension(dpy,i,val) \
+ XextCheckExtension (dpy, i, xf86dri_extension_name, val)
+
+/*****************************************************************************
+ * *
+ * private utility routines *
+ * *
+ *****************************************************************************/
+
+static int close_display(Display * dpy, XExtCodes * extCodes);
+static /* const */ XExtensionHooks xf86dri_extension_hooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ close_display, /* close_display */
+ NULL, /* wire_to_event */
+ NULL, /* event_to_wire */
+ NULL, /* error */
+ NULL, /* error_string */
+};
+
+static
+XEXT_GENERATE_FIND_DISPLAY(find_display, xf86dri_info,
+ xf86dri_extension_name, &xf86dri_extension_hooks,
+ 0, NULL)
+
+ static XEXT_GENERATE_CLOSE_DISPLAY(close_display, xf86dri_info)
+
+/*****************************************************************************
+ * *
+ * public XFree86-DRI Extension routines *
+ * *
+ *****************************************************************************/
+#if 0
+#include <stdio.h>
+#define TRACE(msg) fprintf(stderr,"uniDRI%s\n", msg);
+#else
+#define TRACE(msg)
+#endif
+ Bool uniDRIQueryExtension(dpy, event_basep, error_basep)
+ Display *dpy;
+ int *event_basep, *error_basep;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+
+ TRACE("QueryExtension...");
+ if (XextHasExtension(info)) {
+ *event_basep = info->codes->first_event;
+ *error_basep = info->codes->first_error;
+ TRACE("QueryExtension... return True");
+ return True;
+ } else {
+ TRACE("QueryExtension... return False");
+ return False;
+ }
+}
+
+Bool
+uniDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
+ Display *dpy;
+ int *majorVersion;
+ int *minorVersion;
+ int *patchVersion;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIQueryVersionReply rep;
+ xXF86DRIQueryVersionReq *req;
+
+ TRACE("QueryVersion...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryVersion, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryVersion;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return False");
+ return False;
+ }
+ *majorVersion = rep.majorVersion;
+ *minorVersion = rep.minorVersion;
+ *patchVersion = rep.patchVersion;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return True");
+ return True;
+}
+
+Bool
+uniDRIQueryDirectRenderingCapable(dpy, screen, isCapable)
+ Display *dpy;
+ int screen;
+ Bool *isCapable;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIQueryDirectRenderingCapableReply rep;
+ xXF86DRIQueryDirectRenderingCapableReq *req;
+
+ TRACE("QueryDirectRenderingCapable...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryDirectRenderingCapable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return False");
+ return False;
+ }
+ *isCapable = rep.isCapable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return True");
+ return True;
+}
+
+Bool
+uniDRIOpenConnection(dpy, screen, hSAREA, busIdString)
+ Display *dpy;
+ int screen;
+ drm_handle_t *hSAREA;
+ char **busIdString;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIOpenConnectionReply rep;
+ xXF86DRIOpenConnectionReq *req;
+
+ TRACE("OpenConnection...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIOpenConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIOpenConnection;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+
+ *hSAREA = rep.hSAREALow;
+#ifdef LONG64
+ if (sizeof(drm_handle_t) == 8) {
+ *hSAREA |= ((unsigned long)rep.hSAREAHigh) << 32;
+ }
+#endif
+ if (rep.length) {
+ if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
+ _XEatData(dpy, ((rep.busIdStringLength + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+ _XReadPad(dpy, *busIdString, rep.busIdStringLength);
+ } else {
+ *busIdString = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return True");
+ return True;
+}
+
+Bool
+uniDRIAuthConnection(dpy, screen, magic)
+ Display *dpy;
+ int screen;
+ drm_magic_t magic;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIAuthConnectionReq *req;
+ xXF86DRIAuthConnectionReply rep;
+
+ TRACE("AuthConnection...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIAuthConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIAuthConnection;
+ req->screen = screen;
+ req->magic = magic;
+ rep.authenticated = 0;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.authenticated) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return False");
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return True");
+ return True;
+}
+
+Bool
+uniDRICloseConnection(dpy, screen)
+ Display *dpy;
+ int screen;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRICloseConnectionReq *req;
+
+ TRACE("CloseConnection...");
+
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICloseConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICloseConnection;
+ req->screen = screen;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CloseConnection... return True");
+ return True;
+}
+
+Bool
+uniDRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion,
+ ddxDriverMinorVersion, ddxDriverPatchVersion,
+ clientDriverName)
+ Display *dpy;
+ int screen;
+ int *ddxDriverMajorVersion;
+ int *ddxDriverMinorVersion;
+ int *ddxDriverPatchVersion;
+ char **clientDriverName;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIGetClientDriverNameReply rep;
+ xXF86DRIGetClientDriverNameReq *req;
+
+ TRACE("GetClientDriverName...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetClientDriverName, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetClientDriverName;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+
+ *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
+ *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
+ *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
+
+ if (rep.length) {
+ if (!(*clientDriverName =
+ (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
+ _XEatData(dpy, ((rep.clientDriverNameLength + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+ _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
+ } else {
+ *clientDriverName = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return True");
+ return True;
+}
+
+Bool
+uniDRICreateContextWithConfig(dpy, screen, configID, context, hHWContext)
+ Display *dpy;
+ int screen;
+ int configID;
+ XID *context;
+ drm_context_t *hHWContext;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRICreateContextReply rep;
+ xXF86DRICreateContextReq *req;
+
+ TRACE("CreateContext...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateContext;
+ req->visual = configID;
+ req->screen = screen;
+ *context = XAllocID(dpy);
+ req->context = *context;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return False");
+ return False;
+ }
+ *hHWContext = rep.hHWContext;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return True");
+ return True;
+}
+
+Bool
+uniDRICreateContext(dpy, screen, visual, context, hHWContext)
+ Display *dpy;
+ int screen;
+ Visual *visual;
+ XID *context;
+ drm_context_t *hHWContext;
+{
+ return uniDRICreateContextWithConfig(dpy, screen, visual->visualid,
+ context, hHWContext);
+}
+
+Bool
+uniDRIDestroyContext(Display * ndpy, int screen, XID context)
+{
+ Display *const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIDestroyContextReq *req;
+
+ TRACE("DestroyContext...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyContext;
+ req->screen = screen;
+ req->context = context;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyContext... return True");
+ return True;
+}
+
+Bool
+uniDRICreateDrawable(Display * ndpy, int screen,
+ Drawable drawable, drm_drawable_t * hHWDrawable)
+{
+ Display *const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRICreateDrawableReply rep;
+ xXF86DRICreateDrawableReq *req;
+
+ TRACE("CreateDrawable...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return False");
+ return False;
+ }
+ *hHWDrawable = rep.hHWDrawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return True");
+ return True;
+}
+
+Bool
+uniDRIDestroyDrawable(Display * ndpy, int screen, Drawable drawable)
+{
+ Display *const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIDestroyDrawableReq *req;
+
+ TRACE("DestroyDrawable...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyDrawable... return True");
+ return True;
+}
+
+Bool
+uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable,
+ unsigned int *index, unsigned int *stamp,
+ int *X, int *Y, int *W, int *H,
+ int *numClipRects, drm_clip_rect_t ** pClipRects,
+ int *backX, int *backY,
+ int *numBackClipRects,
+ drm_clip_rect_t ** pBackClipRects)
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIGetDrawableInfoReply rep;
+ xXF86DRIGetDrawableInfoReq *req;
+ int total_rects;
+
+ TRACE("GetDrawableInfo...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDrawableInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDrawableInfo;
+ req->screen = screen;
+ req->drawable = drawable;
+
+ if (!_XReply(dpy, (xReply *) & rep, 1, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+ *index = rep.drawableTableIndex;
+ *stamp = rep.drawableTableStamp;
+ *X = (int)rep.drawableX;
+ *Y = (int)rep.drawableY;
+ *W = (int)rep.drawableWidth;
+ *H = (int)rep.drawableHeight;
+ *numClipRects = rep.numClipRects;
+ total_rects = *numClipRects;
+
+ *backX = rep.backX;
+ *backY = rep.backY;
+ *numBackClipRects = rep.numBackClipRects;
+ total_rects += *numBackClipRects;
+
+#if 0
+ /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
+ * backwards compatibility (Because of the >> 2 shift) but the fix
+ * enables multi-threaded apps to work.
+ */
+ if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
+ SIZEOF(xGenericReply) +
+ total_rects * sizeof(drm_clip_rect_t)) +
+ 3) & ~3) >> 2)) {
+ _XEatData(dpy, rep.length);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+#endif
+
+ if (*numClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numClipRects);
+
+ *pClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
+ if (*pClipRects)
+ _XRead(dpy, (char *)*pClipRects, len);
+ } else {
+ *pClipRects = NULL;
+ }
+
+ if (*numBackClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
+
+ *pBackClipRects = (drm_clip_rect_t *) Xcalloc(len, 1);
+ if (*pBackClipRects)
+ _XRead(dpy, (char *)*pBackClipRects, len);
+ } else {
+ *pBackClipRects = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return True");
+ return True;
+}
+
+Bool
+uniDRIGetDeviceInfo(dpy, screen, hFrameBuffer,
+ fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
+ Display *dpy;
+ int screen;
+ drm_handle_t *hFrameBuffer;
+ int *fbOrigin;
+ int *fbSize;
+ int *fbStride;
+ int *devPrivateSize;
+ void **pDevPrivate;
+{
+ XExtDisplayInfo *info = find_display(dpy);
+ xXF86DRIGetDeviceInfoReply rep;
+ xXF86DRIGetDeviceInfoReq *req;
+
+ TRACE("GetDeviceInfo...");
+ uniDRICheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDeviceInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDeviceInfo;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+
+ *hFrameBuffer = rep.hFrameBufferLow;
+#ifdef LONG64
+ if (sizeof(drm_handle_t) == 8) {
+ *hFrameBuffer |= ((unsigned long)rep.hFrameBufferHigh) << 32;
+ }
+#endif
+
+ *fbOrigin = rep.framebufferOrigin;
+ *fbSize = rep.framebufferSize;
+ *fbStride = rep.framebufferStride;
+ *devPrivateSize = rep.devPrivateSize;
+
+ if (rep.length) {
+ if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
+ _XEatData(dpy, ((rep.devPrivateSize + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+ _XRead(dpy, (char *)*pDevPrivate, rep.devPrivateSize);
+ } else {
+ *pDevPrivate = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return True");
+ return True;
+}
diff --git a/src/gallium/winsys/drm/radeon/python/xf86dri.h b/src/gallium/winsys/drm/radeon/python/xf86dri.h
new file mode 100644
index 0000000000..bf6de37d9d
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/python/xf86dri.h
@@ -0,0 +1,123 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, 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 PRECISION INSIGHT 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.
+
+**************************************************************************/
+
+/**
+ * \file xf86dri.h
+ * Protocol numbers and function prototypes for DRI X protocol.
+ *
+ * \author Kevin E. Martin <martin@valinux.com>
+ * \author Jens Owen <jens@tungstengraphics.com>
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+#ifndef _XF86DRI_H_
+#define _XF86DRI_H_
+
+#include <stdint.h>
+#include <X11/Xfuncproto.h>
+#include <drm/drm.h>
+
+#define X_XF86DRIQueryVersion 0
+#define X_XF86DRIQueryDirectRenderingCapable 1
+#define X_XF86DRIOpenConnection 2
+#define X_XF86DRICloseConnection 3
+#define X_XF86DRIGetClientDriverName 4
+#define X_XF86DRICreateContext 5
+#define X_XF86DRIDestroyContext 6
+#define X_XF86DRICreateDrawable 7
+#define X_XF86DRIDestroyDrawable 8
+#define X_XF86DRIGetDrawableInfo 9
+#define X_XF86DRIGetDeviceInfo 10
+#define X_XF86DRIAuthConnection 11
+#define X_XF86DRIOpenFullScreen 12 /* Deprecated */
+#define X_XF86DRICloseFullScreen 13 /* Deprecated */
+
+#define XF86DRINumberEvents 0
+
+#define XF86DRIClientNotLocal 0
+#define XF86DRIOperationNotSupported 1
+#define XF86DRINumberErrors (XF86DRIOperationNotSupported + 1)
+
+#ifndef _XF86DRI_SERVER_
+
+_XFUNCPROTOBEGIN
+ Bool uniDRIQueryExtension(Display * dpy, int *event_base,
+ int *error_base);
+
+Bool uniDRIQueryVersion(Display * dpy, int *majorVersion, int *minorVersion,
+ int *patchVersion);
+
+Bool uniDRIQueryDirectRenderingCapable(Display * dpy, int screen,
+ Bool * isCapable);
+
+Bool uniDRIOpenConnection(Display * dpy, int screen, drm_handle_t * hSAREA,
+ char **busIDString);
+
+Bool uniDRIAuthConnection(Display * dpy, int screen, drm_magic_t magic);
+
+Bool uniDRICloseConnection(Display * dpy, int screen);
+
+Bool uniDRIGetClientDriverName(Display * dpy, int screen,
+ int *ddxDriverMajorVersion,
+ int *ddxDriverMinorVersion,
+ int *ddxDriverPatchVersion,
+ char **clientDriverName);
+
+Bool uniDRICreateContext(Display * dpy, int screen, Visual * visual,
+ XID * ptr_to_returned_context_id,
+ drm_context_t * hHWContext);
+
+Bool uniDRICreateContextWithConfig(Display * dpy, int screen, int configID,
+ XID * ptr_to_returned_context_id,
+ drm_context_t * hHWContext);
+
+extern Bool uniDRIDestroyContext(Display * dpy, int screen, XID context_id);
+
+extern Bool uniDRICreateDrawable(Display * dpy, int screen,
+ Drawable drawable,
+ drm_drawable_t * hHWDrawable);
+
+extern Bool uniDRIDestroyDrawable(Display * dpy, int screen,
+ Drawable drawable);
+
+Bool uniDRIGetDrawableInfo(Display * dpy, int screen, Drawable drawable,
+ unsigned int *index, unsigned int *stamp,
+ int *X, int *Y, int *W, int *H,
+ int *numClipRects, drm_clip_rect_t ** pClipRects,
+ int *backX, int *backY,
+ int *numBackClipRects,
+ drm_clip_rect_t ** pBackClipRects);
+
+Bool uniDRIGetDeviceInfo(Display * dpy, int screen,
+ drm_handle_t * hFrameBuffer, int *fbOrigin,
+ int *fbSize, int *fbStride, int *devPrivateSize,
+ void **pDevPrivate);
+
+_XFUNCPROTOEND
+#endif /* _XF86DRI_SERVER_ */
+#endif /* _XF86DRI_H_ */
diff --git a/src/gallium/winsys/drm/radeon/python/xf86dristr.h b/src/gallium/winsys/drm/radeon/python/xf86dristr.h
new file mode 100644
index 0000000000..d898996360
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/python/xf86dristr.h
@@ -0,0 +1,389 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, 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 PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Fiath <faith@valinux.com>
+ *
+ */
+
+#ifndef _XF86DRISTR_H_
+#define _XF86DRISTR_H_
+
+#include "xf86dri.h"
+
+#define XF86DRINAME "XFree86-DRI"
+
+/* The DRI version number. This was originally set to be the same of the
+ * XFree86 version number. However, this version is really indepedent of
+ * the XFree86 version.
+ *
+ * Version History:
+ * 4.0.0: Original
+ * 4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02
+ * 4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02
+ */
+#define XF86DRI_MAJOR_VERSION 4
+#define XF86DRI_MINOR_VERSION 1
+#define XF86DRI_PATCH_VERSION 0
+
+typedef struct _XF86DRIQueryVersion
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIQueryVersion */
+ CARD16 length B16;
+} xXF86DRIQueryVersionReq;
+
+#define sz_xXF86DRIQueryVersionReq 4
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 majorVersion B16; /* major version of DRI protocol */
+ CARD16 minorVersion B16; /* minor version of DRI protocol */
+ CARD32 patchVersion B32; /* patch version of DRI protocol */
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIQueryVersionReply;
+
+#define sz_xXF86DRIQueryVersionReply 32
+
+typedef struct _XF86DRIQueryDirectRenderingCapable
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIQueryDirectRenderingCapableReq;
+
+#define sz_xXF86DRIQueryDirectRenderingCapableReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ BOOL isCapable;
+ BOOL pad2;
+ BOOL pad3;
+ BOOL pad4;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+ CARD32 pad9 B32;
+} xXF86DRIQueryDirectRenderingCapableReply;
+
+#define sz_xXF86DRIQueryDirectRenderingCapableReply 32
+
+typedef struct _XF86DRIOpenConnection
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIOpenConnectionReq;
+
+#define sz_xXF86DRIOpenConnectionReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hSAREALow B32;
+ CARD32 hSAREAHigh B32;
+ CARD32 busIdStringLength B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+} xXF86DRIOpenConnectionReply;
+
+#define sz_xXF86DRIOpenConnectionReply 32
+
+typedef struct _XF86DRIAuthConnection
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 magic B32;
+} xXF86DRIAuthConnectionReq;
+
+#define sz_xXF86DRIAuthConnectionReq 12
+
+typedef struct
+{
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 authenticated B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIAuthConnectionReply;
+
+#define zx_xXF86DRIAuthConnectionReply 32
+
+typedef struct _XF86DRICloseConnection
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRICloseConnectionReq;
+
+#define sz_xXF86DRICloseConnectionReq 8
+
+typedef struct _XF86DRIGetClientDriverName
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetClientDriverName */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetClientDriverNameReq;
+
+#define sz_xXF86DRIGetClientDriverNameReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 ddxDriverMajorVersion B32;
+ CARD32 ddxDriverMinorVersion B32;
+ CARD32 ddxDriverPatchVersion B32;
+ CARD32 clientDriverNameLength B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIGetClientDriverNameReply;
+
+#define sz_xXF86DRIGetClientDriverNameReply 32
+
+typedef struct _XF86DRICreateContext
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 visual B32;
+ CARD32 context B32;
+} xXF86DRICreateContextReq;
+
+#define sz_xXF86DRICreateContextReq 16
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWContext B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateContextReply;
+
+#define sz_xXF86DRICreateContextReply 32
+
+typedef struct _XF86DRIDestroyContext
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 context B32;
+} xXF86DRIDestroyContextReq;
+
+#define sz_xXF86DRIDestroyContextReq 12
+
+typedef struct _XF86DRICreateDrawable
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICreateDrawableReq;
+
+#define sz_xXF86DRICreateDrawableReq 12
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWDrawable B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateDrawableReply;
+
+#define sz_xXF86DRICreateDrawableReply 32
+
+typedef struct _XF86DRIDestroyDrawable
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIDestroyDrawableReq;
+
+#define sz_xXF86DRIDestroyDrawableReq 12
+
+typedef struct _XF86DRIGetDrawableInfo
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDrawableInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIGetDrawableInfoReq;
+
+#define sz_xXF86DRIGetDrawableInfoReq 12
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 drawableTableIndex B32;
+ CARD32 drawableTableStamp B32;
+ INT16 drawableX B16;
+ INT16 drawableY B16;
+ INT16 drawableWidth B16;
+ INT16 drawableHeight B16;
+ CARD32 numClipRects B32;
+ INT16 backX B16;
+ INT16 backY B16;
+ CARD32 numBackClipRects B32;
+} xXF86DRIGetDrawableInfoReply;
+
+#define sz_xXF86DRIGetDrawableInfoReply 36
+
+typedef struct _XF86DRIGetDeviceInfo
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDeviceInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetDeviceInfoReq;
+
+#define sz_xXF86DRIGetDeviceInfoReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hFrameBufferLow B32;
+ CARD32 hFrameBufferHigh B32;
+ CARD32 framebufferOrigin B32;
+ CARD32 framebufferSize B32;
+ CARD32 framebufferStride B32;
+ CARD32 devPrivateSize B32;
+} xXF86DRIGetDeviceInfoReply;
+
+#define sz_xXF86DRIGetDeviceInfoReply 32
+
+typedef struct _XF86DRIOpenFullScreen
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIOpenFullScreenReq;
+
+#define sz_xXF86DRIOpenFullScreenReq 12
+
+typedef struct
+{
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 isFullScreen B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIOpenFullScreenReply;
+
+#define sz_xXF86DRIOpenFullScreenReply 32
+
+typedef struct _XF86DRICloseFullScreen
+{
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICloseFullScreenReq;
+
+#define sz_xXF86DRICloseFullScreenReq 12
+
+typedef struct
+{
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xXF86DRICloseFullScreenReply;
+
+#define sz_xXF86DRICloseFullScreenReply 32
+
+#endif /* _XF86DRISTR_H_ */
diff --git a/src/gallium/winsys/drm/radeon/xorg/Makefile b/src/gallium/winsys/drm/radeon/xorg/Makefile
new file mode 100644
index 0000000000..0241625f69
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/xorg/Makefile
@@ -0,0 +1,42 @@
+TARGET = modesetting_drv.so
+CFILES = $(wildcard ./*.c)
+OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES))
+GALLIUMDIR = ../../../..
+TOP = ../../../../../..
+
+include ${TOP}/configs/current
+
+CFLAGS = -DHAVE_CONFIG_H \
+ -g -Wall -Wimplicit-function-declaration -fPIC \
+ $(shell pkg-config --cflags pixman-1 xorg-server libdrm xproto) \
+ -I${GALLIUMDIR}/include \
+ -I${GALLIUMDIR}/drivers \
+ -I${GALLIUMDIR}/auxiliary \
+ -I${TOP}/src/mesa \
+ -I$(TOP)/include \
+ -I$(TOP)/src/egl/main
+
+LIBS = \
+ $(GALLIUMDIR)/state_trackers/xorg/libxorgtracker.a \
+ $(GALLIUMDIR)/winsys/drm/radeon/core/libradeonwinsys.a \
+ $(TOP)/src/gallium/drivers/r300/libr300.a \
+ $(GALLIUM_AUXILIARIES)
+
+#############################################
+
+
+
+all default: $(TARGET)
+
+$(TARGET): $(OBJECTS) Makefile $(GALLIUMDIR)/state_trackers/xorg/libxorgtracker.a
+ $(TOP)/bin/mklib -noprefix -o $@ \
+ $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_radeon
+
+clean:
+ rm -rf $(OBJECTS) $(TARGET)
+
+install:
+ $(INSTALL) -d $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR)
+ $(MINSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR)
+
+.PHONY = all clean install
diff --git a/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c b/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c
new file mode 100644
index 0000000000..837f2aa8fe
--- /dev/null
+++ b/src/gallium/winsys/drm/radeon/xorg/radeon_xorg.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Author: Alan Hourihane <alanh@tungstengraphics.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ * Author: Corbin Simpson <MostAwesomedude@gmail.com>
+ *
+ */
+
+#include "../../../../state_trackers/xorg/xorg_winsys.h"
+
+static void radeon_xorg_identify(int flags);
+static Bool radeon_xorg_pci_probe(DriverPtr driver,
+ int entity_num,
+ struct pci_device *device,
+ intptr_t match_data);
+
+static const struct pci_id_match radeon_xorg_device_match[] = {
+ {0x1002, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0},
+ {0, 0, 0},
+};
+
+static SymTabRec radeon_xorg_chipsets[] = {
+ {PCI_MATCH_ANY, "ATI/AMD Radeon Graphics Chipset"},
+ {-1, NULL}
+};
+
+static PciChipsets radeon_xorg_pci_devices[] = {
+ {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL},
+ {-1, -1, NULL}
+};
+
+static XF86ModuleVersionInfo radeon_xorg_version = {
+ "modesetting",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 0, 1, 0, /* major, minor, patch */
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+/*
+ * Xorg driver exported structures
+ */
+
+_X_EXPORT DriverRec modesetting = {
+ 1,
+ "modesetting",
+ radeon_xorg_identify,
+ NULL,
+ xorg_tracker_available_options,
+ NULL,
+ 0,
+ NULL,
+ radeon_xorg_device_match,
+ radeon_xorg_pci_probe
+};
+
+static MODULESETUPPROTO(radeon_xorg_setup);
+
+_X_EXPORT XF86ModuleData modesettingModuleData = {
+ &radeon_xorg_version,
+ radeon_xorg_setup,
+ NULL
+};
+
+/*
+ * Xorg driver functions
+ */
+
+static pointer
+radeon_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = 0;
+
+ /* This module should be loaded only once, but check to be sure.
+ */
+ if (!setupDone) {
+ setupDone = 1;
+ xf86AddDriver(&modesetting, module, HaveDriverFuncs);
+
+ /*
+ * The return value must be non-NULL on success even though there
+ * is no TearDownProc.
+ */
+ return (pointer) 1;
+ } else {
+ if (errmaj)
+ *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+
+static void
+radeon_xorg_identify(int flags)
+{
+ xf86PrintChipsets("modesetting", "Driver for Modesetting Kernel Drivers",
+ radeon_xorg_chipsets);
+}
+
+static Bool
+radeon_xorg_pci_probe(DriverPtr driver,
+ int entity_num, struct pci_device *device, intptr_t match_data)
+{
+ ScrnInfoPtr scrn = NULL;
+ EntityInfoPtr entity;
+
+ scrn = xf86ConfigPciEntity(scrn, 0, entity_num, radeon_xorg_pci_devices,
+ NULL, NULL, NULL, NULL, NULL);
+ if (scrn != NULL) {
+ scrn->driverVersion = 1;
+ scrn->driverName = "radeon";
+ scrn->name = "modesetting";
+ scrn->Probe = NULL;
+
+ entity = xf86GetEntityInfo(entity_num);
+
+ /* Use all the functions from the xorg tracker */
+ xorg_tracker_set_functions(scrn);
+ }
+ return scrn != NULL;
+}
diff --git a/src/gallium/winsys/egl_xlib/Makefile b/src/gallium/winsys/egl_xlib/Makefile
new file mode 100644
index 0000000000..3efb7ed4af
--- /dev/null
+++ b/src/gallium/winsys/egl_xlib/Makefile
@@ -0,0 +1,89 @@
+# src/gallium/winsys/egl_xlib/Makefile
+
+# Build softpipe/xlib/EGL driver library/object: "egl_softpipe.so"
+
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+DRIVER_NAME = egl_softpipe.so
+
+
+INCLUDE_DIRS = \
+ -I$(TOP)/include \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/drivers \
+ -I$(TOP)/src/gallium/auxiliary
+
+WINSYS_SOURCES = \
+ egl_xlib.c \
+ sw_winsys.c
+
+WINSYS_OBJECTS = $(WINSYS_SOURCES:.c=.o)
+
+
+LIBS = \
+ $(GALLIUM_DRIVERS) \
+ $(GALLIUM_AUXILIARIES)
+
+# XXX temporary (should create a separate lib with the GL API funcs and
+# mesa code, as done for ES 1.x, 2.x, OpenVG, etc)
+UNUSED_LIBS = \
+ $(TOP)/src/mesa/libglapi.a \
+ $(TOP)/src/mesa/libmesagallium.a \
+
+
+LOCAL_CFLAGS =
+
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@
+
+
+.PHONY: library
+
+
+default: depend library Makefile
+
+
+library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME)
+
+
+# Make the egl_softpipe.so library
+$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(WINSYS_OBJECTS) $(LIBS)
+ $(TOP)/bin/mklib -o $(DRIVER_NAME) \
+ -linker "$(CC)" \
+ -noprefix \
+ -install $(TOP)/$(LIB_DIR) \
+ $(MKLIB_OPTIONS) $(WINSYS_OBJECTS) \
+ -Wl,--whole-archive $(LIBS) -Wl,--no-whole-archive
+
+
+depend: $(ALL_SOURCES)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend # workaround oops on gutsy?!?
+ @ touch depend
+ @ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \
+ > /dev/null 2>/dev/null
+
+
+install: default
+ $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR)
+ @if [ -e $(TOP)/$(LIB_DIR) ]; then \
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(INSTALL_DIR)/$(LIB_DIR); \
+ fi
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h
+
+clean:
+ -rm -f *.o *~ *.bak
+
+
+include depend
diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c
new file mode 100644
index 0000000000..d02f825047
--- /dev/null
+++ b/src/gallium/winsys/egl_xlib/egl_xlib.c
@@ -0,0 +1,869 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * EGL / softpipe / xlib winsys module
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include <dlfcn.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_memory.h"
+#include "softpipe/sp_winsys.h"
+#include "softpipe/sp_texture.h"
+
+#include "eglconfig.h"
+#include "eglconfigutil.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "egllog.h"
+#include "eglsurface.h"
+
+#include "state_tracker/st_public.h"
+
+#include "sw_winsys.h"
+
+
+/** subclass of _EGLDriver */
+struct xlib_egl_driver
+{
+ _EGLDriver Base; /**< base class */
+ EGLint apis;
+};
+
+
+/** driver data of _EGLDisplay */
+struct xlib_egl_display
+{
+ Display *Dpy;
+
+ struct pipe_winsys *winsys;
+ struct pipe_screen *screen;
+};
+
+
+/** subclass of _EGLContext */
+struct xlib_egl_context
+{
+ _EGLContext Base; /**< base class */
+
+ struct pipe_context *pipe; /**< Gallium driver context */
+ struct st_context *Context; /**< Mesa/gallium state tracker context */
+};
+
+
+/** subclass of _EGLSurface */
+struct xlib_egl_surface
+{
+ _EGLSurface Base; /**< base class */
+
+ /* These are set for window surface */
+ Display *Dpy; /**< The X Display of the window */
+ Window Win; /**< The user-created window ID */
+ GC Gc;
+ XVisualInfo VisInfo;
+
+ struct pipe_winsys *winsys;
+
+ struct st_framebuffer *Framebuffer;
+};
+
+
+static void
+flush_frontbuffer(struct pipe_winsys *pws,
+ struct pipe_surface *psurf,
+ void *context_private);
+
+
+/** cast wrapper */
+static INLINE struct xlib_egl_driver *
+xlib_egl_driver(_EGLDriver *drv)
+{
+ return (struct xlib_egl_driver *) drv;
+}
+
+
+static INLINE struct xlib_egl_display *
+xlib_egl_display(_EGLDisplay *dpy)
+{
+ return (struct xlib_egl_display *) dpy->DriverData;
+}
+
+
+static INLINE struct xlib_egl_surface *
+lookup_surface(_EGLSurface *surf)
+{
+ return (struct xlib_egl_surface *) surf;
+}
+
+
+static INLINE struct xlib_egl_context *
+lookup_context(_EGLContext *ctx)
+{
+ return (struct xlib_egl_context *) ctx;
+}
+
+
+static unsigned int
+bitcount(unsigned int n)
+{
+ unsigned int bits;
+ for (bits = 0; n > 0; n = n >> 1) {
+ bits += (n & 1);
+ }
+ return bits;
+}
+
+
+/**
+ * Create the EGLConfigs. (one per X visual)
+ */
+static void
+create_configs(struct xlib_egl_display *xdpy, _EGLDisplay *disp)
+{
+ static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
+ EGL_OPENGL_ES2_BIT |
+ EGL_OPENVG_BIT |
+ EGL_OPENGL_BIT);
+ XVisualInfo *visInfo, visTemplate;
+ int num_visuals, i;
+
+ /* get list of all X visuals, create an EGL config for each */
+ visTemplate.screen = DefaultScreen(xdpy->Dpy);
+ visInfo = XGetVisualInfo(xdpy->Dpy, VisualScreenMask,
+ &visTemplate, &num_visuals);
+ if (!visInfo) {
+ printf("egl_xlib.c: couldn't get any X visuals\n");
+ abort();
+ }
+
+ for (i = 0; i < num_visuals; i++) {
+ _EGLConfig *config = calloc(1, sizeof(_EGLConfig));
+ int id = i + 1;
+ int rbits = bitcount(visInfo[i].red_mask);
+ int gbits = bitcount(visInfo[i].green_mask);
+ int bbits = bitcount(visInfo[i].blue_mask);
+ int abits = bbits == 8 ? 8 : 0;
+ int zbits = 24;
+ int sbits = 8;
+ int visid = visInfo[i].visualid;
+#if defined(__cplusplus) || defined(c_plusplus)
+ int vistype = visInfo[i].c_class;
+#else
+ int vistype = visInfo[i].class;
+#endif
+
+ _eglInitConfig(config, id);
+ SET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE, rbits + gbits + bbits + abits);
+ SET_CONFIG_ATTRIB(config, EGL_RED_SIZE, rbits);
+ SET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE, gbits);
+ SET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE, bbits);
+ SET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE, abits);
+ SET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE, zbits);
+ SET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE, sbits);
+ SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_ID, visid);
+ SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, vistype);
+ SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_FALSE);
+ SET_CONFIG_ATTRIB(config, EGL_CONFORMANT, all_apis);
+ SET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE, all_apis);
+ SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
+ SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
+ SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
+
+ _eglAddConfig(disp, config);
+ }
+
+ XFree(visInfo);
+}
+
+
+/**
+ * Called via eglInitialize(), drv->API.Initialize().
+ */
+static EGLBoolean
+xlib_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
+ EGLint *major, EGLint *minor)
+{
+ struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
+ struct xlib_egl_display *xdpy;
+
+ xdpy = CALLOC_STRUCT(xlib_egl_display);
+ if (!xdpy)
+ return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+ xdpy->Dpy = (Display *) dpy->NativeDisplay;
+ if (!xdpy->Dpy) {
+ xdpy->Dpy = XOpenDisplay(NULL);
+ if (!xdpy->Dpy) {
+ free(xdpy);
+ return EGL_FALSE;
+ }
+ }
+
+ /* create winsys and pipe screen */
+ xdpy->winsys = create_sw_winsys();
+ if (!xdpy->winsys) {
+ free(xdpy);
+ return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+ }
+ xdpy->winsys->flush_frontbuffer = flush_frontbuffer;
+ xdpy->screen = softpipe_create_screen(xdpy->winsys);
+ if (!xdpy->screen) {
+ free(xdpy->winsys);
+ free(xdpy);
+ return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+ }
+
+ dpy->DriverData = (void *) xdpy;
+ dpy->ClientAPIsMask = xdrv->apis;
+
+ create_configs(xdpy, dpy);
+
+ /* we're supporting EGL 1.4 */
+ *major = 1;
+ *minor = 4;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglTerminate(), drv->API.Terminate().
+ */
+static EGLBoolean
+xlib_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct xlib_egl_display *xdpy = xlib_egl_display(dpy);
+
+ _eglReleaseDisplayResources(drv, dpy);
+ _eglCleanupDisplay(dpy);
+
+ xdpy->screen->destroy(xdpy->screen);
+ free(xdpy->winsys);
+
+ if (!dpy->NativeDisplay)
+ XCloseDisplay(xdpy->Dpy);
+ free(xdpy);
+
+ return EGL_TRUE;
+}
+
+
+static _EGLProc
+xlib_eglGetProcAddress(const char *procname)
+{
+ return (_EGLProc) st_get_proc_address(procname);
+}
+
+
+static void
+get_drawable_visual_info(Display *dpy, Drawable d, XVisualInfo *visInfo)
+{
+ XWindowAttributes attr;
+ XVisualInfo visTemp, *vis;
+ int num_visuals;
+
+ XGetWindowAttributes(dpy, d, &attr);
+
+ visTemp.screen = DefaultScreen(dpy);
+ visTemp.visualid = attr.visual->visualid;
+ vis = XGetVisualInfo(dpy,
+ (VisualScreenMask | VisualIDMask),
+ &visTemp, &num_visuals);
+ if (vis)
+ *visInfo = *vis;
+
+ XFree(vis);
+}
+
+
+
+/** Get size of given window */
+static Status
+get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
+{
+ Window root;
+ Status stat;
+ int xpos, ypos;
+ unsigned int w, h, bw, depth;
+ stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+ *width = w;
+ *height = h;
+ return stat;
+}
+
+
+static void
+check_and_update_buffer_size(struct xlib_egl_surface *surface)
+{
+ uint width, height;
+ if (surface->Base.Type == EGL_PBUFFER_BIT) {
+ width = surface->Base.Width;
+ height = surface->Base.Height;
+ }
+ else {
+ get_drawable_size(surface->Dpy, surface->Win, &width, &height);
+ }
+ st_resize_framebuffer(surface->Framebuffer, width, height);
+ surface->Base.Width = width;
+ surface->Base.Height = height;
+}
+
+
+
+static void
+display_surface(struct pipe_winsys *pws,
+ struct pipe_surface *psurf,
+ struct xlib_egl_surface *xsurf)
+{
+ struct softpipe_texture *spt = softpipe_texture(psurf->texture);
+ XImage *ximage;
+ void *data;
+
+ if (xsurf->Base.Type == EGL_PBUFFER_BIT)
+ return;
+
+ ximage = XCreateImage(xsurf->Dpy,
+ xsurf->VisInfo.visual,
+ xsurf->VisInfo.depth,
+ ZPixmap, 0, /* format, offset */
+ NULL, /* data */
+ 0, 0, /* size */
+ 32, /* bitmap_pad */
+ 0); /* bytes_per_line */
+
+
+ assert(ximage->format);
+ assert(ximage->bitmap_unit);
+
+ data = pws->buffer_map(pws, spt->buffer, 0);
+
+ /* update XImage's fields */
+ ximage->data = data;
+ ximage->width = psurf->width;
+ ximage->height = psurf->height;
+ ximage->bytes_per_line = spt->stride[psurf->level];
+
+ XPutImage(xsurf->Dpy, xsurf->Win, xsurf->Gc,
+ ximage, 0, 0, 0, 0, psurf->width, psurf->height);
+
+ XSync(xsurf->Dpy, 0);
+
+ ximage->data = NULL;
+ XDestroyImage(ximage);
+
+ pws->buffer_unmap(pws, spt->buffer);
+}
+
+
+
+/** Display gallium surface in X window */
+static void
+flush_frontbuffer(struct pipe_winsys *pws,
+ struct pipe_surface *psurf,
+ void *context_private)
+{
+ struct xlib_egl_surface *xsurf = (struct xlib_egl_surface *) context_private;
+ display_surface(pws, psurf, xsurf);
+}
+
+
+
+/**
+ * Called via eglCreateContext(), drv->API.CreateContext().
+ */
+static _EGLContext *
+xlib_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
+ _EGLContext *share_list, const EGLint *attrib_list)
+{
+ struct xlib_egl_display *xdpy = xlib_egl_display(dpy);
+ struct xlib_egl_context *ctx;
+ struct st_context *share_ctx = NULL; /* XXX fix */
+ __GLcontextModes visual;
+
+ ctx = CALLOC_STRUCT(xlib_egl_context);
+ if (!ctx)
+ return NULL;
+
+ /* let EGL lib init the common stuff */
+ if (!_eglInitContext(drv, &ctx->Base, conf, attrib_list)) {
+ free(ctx);
+ return NULL;
+ }
+
+ /* API-dependent context creation */
+ switch (ctx->Base.ClientAPI) {
+ case EGL_OPENVG_API:
+ case EGL_OPENGL_ES_API:
+ _eglLog(_EGL_DEBUG, "Create Context for ES version %d\n",
+ ctx->Base.ClientVersion);
+ /* fall-through */
+ case EGL_OPENGL_API:
+ /* create a softpipe context */
+ ctx->pipe = softpipe_create(xdpy->screen);
+ /* Now do xlib / state tracker inits here */
+ _eglConfigToContextModesRec(conf, &visual);
+ ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx);
+ break;
+ default:
+ _eglError(EGL_BAD_MATCH, "eglCreateContext(unsupported API)");
+ free(ctx);
+ return NULL;
+ }
+
+ return &ctx->Base;
+}
+
+
+static EGLBoolean
+xlib_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+{
+ struct xlib_egl_context *context = lookup_context(ctx);
+
+ if (!_eglIsContextBound(&context->Base)) {
+ /* API-dependent clean-up */
+ switch (context->Base.ClientAPI) {
+ case EGL_OPENGL_ES_API:
+ case EGL_OPENVG_API:
+ /* fall-through */
+ case EGL_OPENGL_API:
+ st_destroy_context(context->Context);
+ break;
+ default:
+ assert(0);
+ }
+ free(context);
+ }
+ return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglMakeCurrent(), drv->API.MakeCurrent().
+ */
+static EGLBoolean
+xlib_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
+{
+ struct xlib_egl_context *context = lookup_context(ctx);
+ struct xlib_egl_surface *draw_surf = lookup_surface(draw);
+ struct xlib_egl_surface *read_surf = lookup_surface(read);
+ struct st_context *oldcontext = NULL;
+ _EGLContext *oldctx;
+
+ oldctx = _eglGetCurrentContext();
+ if (oldctx && _eglIsContextLinked(oldctx))
+ oldcontext = st_get_current();
+
+ if (!_eglMakeCurrent(drv, dpy, draw, read, ctx))
+ return EGL_FALSE;
+
+ /* Flush before switching context. Check client API? */
+ if (oldcontext)
+ st_flush(oldcontext, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+ st_make_current((context ? context->Context : NULL),
+ (draw_surf ? draw_surf->Framebuffer : NULL),
+ (read_surf ? read_surf->Framebuffer : NULL));
+
+ if (draw_surf)
+ check_and_update_buffer_size(draw_surf);
+ if (read_surf && read_surf != draw_surf)
+ check_and_update_buffer_size(draw_surf);
+
+ return EGL_TRUE;
+}
+
+
+static enum pipe_format
+choose_color_format(const __GLcontextModes *visual)
+{
+ if (visual->redBits == 8 &&
+ visual->greenBits == 8 &&
+ visual->blueBits == 8 &&
+ visual->alphaBits == 8) {
+ /* XXX this really also depends on the ordering of R,G,B,A */
+ return PIPE_FORMAT_A8R8G8B8_UNORM;
+ }
+ else {
+ assert(0);
+ return PIPE_FORMAT_NONE;
+ }
+}
+
+
+static enum pipe_format
+choose_depth_format(const __GLcontextModes *visual)
+{
+ if (visual->depthBits > 0)
+ return PIPE_FORMAT_S8Z24_UNORM;
+ else
+ return PIPE_FORMAT_NONE;
+}
+
+
+static enum pipe_format
+choose_stencil_format(const __GLcontextModes *visual)
+{
+ if (visual->stencilBits > 0)
+ return PIPE_FORMAT_S8Z24_UNORM;
+ else
+ return PIPE_FORMAT_NONE;
+}
+
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static _EGLSurface *
+xlib_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
+ NativeWindowType window, const EGLint *attrib_list)
+{
+ struct xlib_egl_display *xdpy = xlib_egl_display(disp);
+ struct xlib_egl_surface *surf;
+ __GLcontextModes visual;
+ uint width, height;
+
+ surf = CALLOC_STRUCT(xlib_egl_surface);
+ if (!surf)
+ return NULL;
+
+ /* Let EGL lib init the common stuff */
+ if (!_eglInitSurface(drv, &surf->Base, EGL_WINDOW_BIT,
+ conf, attrib_list)) {
+ free(surf);
+ return NULL;
+ }
+
+ /*
+ * Now init the Xlib and gallium stuff
+ */
+ surf->Win = (Window) window; /* The X window ID */
+ surf->Dpy = xdpy->Dpy; /* The X display */
+ surf->Gc = XCreateGC(surf->Dpy, surf->Win, 0, NULL);
+
+ surf->winsys = xdpy->winsys;
+
+ _eglConfigToContextModesRec(conf, &visual);
+ get_drawable_size(surf->Dpy, surf->Win, &width, &height);
+ get_drawable_visual_info(surf->Dpy, surf->Win, &surf->VisInfo);
+
+ surf->Base.Width = width;
+ surf->Base.Height = height;
+
+ /* Create GL statetracker framebuffer */
+ surf->Framebuffer = st_create_framebuffer(&visual,
+ choose_color_format(&visual),
+ choose_depth_format(&visual),
+ choose_stencil_format(&visual),
+ width, height,
+ (void *) surf);
+
+ st_resize_framebuffer(surf->Framebuffer, width, height);
+
+ return &surf->Base;
+}
+
+
+static _EGLSurface *
+xlib_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
+ const EGLint *attrib_list)
+{
+ struct xlib_egl_display *xdpy = xlib_egl_display(disp);
+ struct xlib_egl_surface *surf;
+ __GLcontextModes visual;
+ uint width, height;
+ EGLBoolean bind_texture;
+
+ surf = CALLOC_STRUCT(xlib_egl_surface);
+ if (!surf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT,
+ conf, attrib_list)) {
+ free(surf);
+ return NULL;
+ }
+ if (surf->Base.Width < 0 || surf->Base.Height < 0) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferSurface");
+ free(surf);
+ return NULL;
+ }
+
+ bind_texture = (surf->Base.TextureFormat != EGL_NO_TEXTURE);
+ width = (uint) surf->Base.Width;
+ height = (uint) surf->Base.Height;
+ if ((surf->Base.TextureTarget == EGL_NO_TEXTURE && bind_texture) ||
+ (surf->Base.TextureTarget != EGL_NO_TEXTURE && !bind_texture)) {
+ _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface");
+ free(surf);
+ return NULL;
+ }
+ /* a framebuffer of zero width or height confuses st */
+ if (width == 0 || height == 0) {
+ _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface");
+ free(surf);
+ return NULL;
+ }
+ /* no mipmap generation */
+ if (surf->Base.MipmapTexture) {
+ _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface");
+ free(surf);
+ return NULL;
+ }
+
+ surf->winsys = xdpy->winsys;
+
+ _eglConfigToContextModesRec(conf, &visual);
+
+ /* Create GL statetracker framebuffer */
+ surf->Framebuffer = st_create_framebuffer(&visual,
+ choose_color_format(&visual),
+ choose_depth_format(&visual),
+ choose_stencil_format(&visual),
+ width, height,
+ (void *) surf);
+ st_resize_framebuffer(surf->Framebuffer, width, height);
+
+ return &surf->Base;
+}
+
+
+static EGLBoolean
+xlib_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
+{
+ struct xlib_egl_surface *surf = lookup_surface(surface);
+ if (!_eglIsSurfaceBound(&surf->Base)) {
+ if (surf->Base.Type != EGL_PBUFFER_BIT)
+ XFreeGC(surf->Dpy, surf->Gc);
+ st_unreference_framebuffer(surf->Framebuffer);
+ free(surf);
+ }
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+xlib_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLSurface *surface, EGLint buffer)
+{
+ struct xlib_egl_surface *xsurf = lookup_surface(surface);
+ struct xlib_egl_context *xctx;
+ struct pipe_surface *psurf;
+ enum pipe_format format;
+ int target;
+
+ if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT)
+ return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
+ if (buffer != EGL_BACK_BUFFER)
+ return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
+ if (xsurf->Base.BoundToTexture)
+ return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
+
+ /* this should be updated when choose_color_format is */
+ switch (xsurf->Base.TextureFormat) {
+ case EGL_TEXTURE_RGB:
+ format = PIPE_FORMAT_R8G8B8_UNORM;
+ break;
+ case EGL_TEXTURE_RGBA:
+ format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ break;
+ default:
+ return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ }
+
+ switch (xsurf->Base.TextureTarget) {
+ case EGL_TEXTURE_2D:
+ target = ST_TEXTURE_2D;
+ break;
+ default:
+ return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ }
+
+ /* flush properly */
+ if (eglGetCurrentSurface(EGL_DRAW) == surface) {
+ xctx = lookup_context(_eglGetCurrentContext());
+ st_flush(xctx->Context, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME,
+ NULL);
+ }
+ else if (_eglIsSurfaceBound(&xsurf->Base)) {
+ xctx = lookup_context(xsurf->Base.Binding);
+ if (xctx)
+ st_finish(xctx->Context);
+ }
+
+ st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
+ &psurf);
+ st_bind_texture_surface(psurf, target, xsurf->Base.MipmapLevel, format);
+ xsurf->Base.BoundToTexture = EGL_TRUE;
+
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+xlib_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
+ EGLint buffer)
+{
+ struct xlib_egl_surface *xsurf = lookup_surface(surface);
+ struct pipe_surface *psurf;
+
+ if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT ||
+ !xsurf->Base.BoundToTexture)
+ return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
+ if (buffer != EGL_BACK_BUFFER)
+ return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
+
+ st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
+ &psurf);
+ st_unbind_texture_surface(psurf, ST_TEXTURE_2D, xsurf->Base.MipmapLevel);
+ xsurf->Base.BoundToTexture = EGL_FALSE;
+
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+xlib_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
+{
+ /* error checking step: */
+ if (!_eglSwapBuffers(drv, dpy, draw))
+ return EGL_FALSE;
+
+ {
+ struct xlib_egl_surface *xsurf = lookup_surface(draw);
+ struct pipe_winsys *pws = xsurf->winsys;
+ struct pipe_surface *psurf;
+
+ st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
+ &psurf);
+
+ st_notify_swapbuffers(xsurf->Framebuffer);
+
+ display_surface(pws, psurf, xsurf);
+
+ check_and_update_buffer_size(xsurf);
+ }
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Determine which API(s) is(are) present by looking for some specific
+ * global symbols.
+ */
+static EGLint
+find_supported_apis(void)
+{
+ EGLint mask = 0;
+ void *handle;
+
+ handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
+ if(!handle)
+ return mask;
+
+ if (dlsym(handle, "st_api_OpenGL_ES1"))
+ mask |= EGL_OPENGL_ES_BIT;
+
+ if (dlsym(handle, "st_api_OpenGL_ES2"))
+ mask |= EGL_OPENGL_ES2_BIT;
+
+ if (dlsym(handle, "st_api_OpenGL"))
+ mask |= EGL_OPENGL_BIT;
+
+ if (dlsym(handle, "st_api_OpenVG"))
+ mask |= EGL_OPENVG_BIT;
+
+ dlclose(handle);
+
+ return mask;
+}
+
+
+static void
+xlib_Unload(_EGLDriver *drv)
+{
+ struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
+ free(xdrv);
+}
+
+
+/**
+ * This is the main entrypoint into the driver.
+ * Called by libEGL to instantiate an _EGLDriver object.
+ */
+_EGLDriver *
+_eglMain(const char *args)
+{
+ struct xlib_egl_driver *xdrv;
+
+ _eglLog(_EGL_INFO, "Entering EGL/Xlib _eglMain(%s)", args);
+
+ xdrv = CALLOC_STRUCT(xlib_egl_driver);
+ if (!xdrv)
+ return NULL;
+
+ _eglInitDriverFallbacks(&xdrv->Base);
+ xdrv->Base.API.Initialize = xlib_eglInitialize;
+ xdrv->Base.API.Terminate = xlib_eglTerminate;
+ xdrv->Base.API.GetProcAddress = xlib_eglGetProcAddress;
+ xdrv->Base.API.CreateContext = xlib_eglCreateContext;
+ xdrv->Base.API.DestroyContext = xlib_eglDestroyContext;
+ xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface;
+ xdrv->Base.API.CreatePbufferSurface = xlib_eglCreatePbufferSurface;
+ xdrv->Base.API.DestroySurface = xlib_eglDestroySurface;
+ xdrv->Base.API.BindTexImage = xlib_eglBindTexImage;
+ xdrv->Base.API.ReleaseTexImage = xlib_eglReleaseTexImage;
+ xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent;
+ xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers;
+
+ xdrv->apis = find_supported_apis();
+ if (xdrv->apis == 0x0) {
+ /* the app isn't directly linked with any EGL-supprted APIs
+ * (such as libGLESv2.so) so use an EGL utility to see what
+ * APIs might be loaded dynamically on this system.
+ */
+ xdrv->apis = _eglFindAPIs();
+ }
+
+ xdrv->Base.Name = "Xlib/softpipe";
+ xdrv->Base.Unload = xlib_Unload;
+
+ return &xdrv->Base;
+}
diff --git a/src/gallium/winsys/egl_xlib/sw_winsys.c b/src/gallium/winsys/egl_xlib/sw_winsys.c
new file mode 100644
index 0000000000..79ff2cc985
--- /dev/null
+++ b/src/gallium/winsys/egl_xlib/sw_winsys.c
@@ -0,0 +1,243 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Totally software-based winsys layer.
+ * Note that the one winsys function that we can't implement here
+ * is flush_frontbuffer().
+ * Whoever uses this code will have to provide that.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "sw_winsys.h"
+
+
+
+/** Subclass of pipe_winsys */
+struct sw_pipe_winsys
+{
+ struct pipe_winsys Base;
+ /* no extra fields for now */
+};
+
+
+/** subclass of pipe_buffer */
+struct sw_pipe_buffer
+{
+ struct pipe_buffer Base;
+ boolean UserBuffer; /** Is this a user-space buffer? */
+ void *Data;
+ void *Mapped;
+};
+
+
+/** cast wrapper */
+static INLINE struct sw_pipe_buffer *
+sw_pipe_buffer(struct pipe_buffer *b)
+{
+ return (struct sw_pipe_buffer *) b;
+}
+
+
+/**
+ * Round n up to next multiple.
+ */
+static INLINE unsigned
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+
+static const char *
+get_name(struct pipe_winsys *pws)
+{
+ return "software";
+}
+
+
+/** Create new pipe_buffer and allocate storage of given size */
+static struct pipe_buffer *
+buffer_create(struct pipe_winsys *pws,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
+ if (!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->Base.reference, 1);
+ buffer->Base.alignment = alignment;
+ buffer->Base.usage = usage;
+ buffer->Base.size = size;
+
+ /* align to 16-byte multiple for Cell */
+ buffer->Data = align_malloc(size, MAX2(alignment, 16));
+
+ return &buffer->Base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
+{
+ struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
+ if (!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->Base.reference, 1);
+ buffer->Base.size = bytes;
+ buffer->UserBuffer = TRUE;
+ buffer->Data = ptr;
+
+ return &buffer->Base;
+}
+
+
+static void *
+buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags)
+{
+ struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+ buffer->Mapped = buffer->Data;
+ return buffer->Mapped;
+}
+
+
+static void
+buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+ struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+ buffer->Mapped = NULL;
+}
+
+
+static void
+buffer_destroy(struct pipe_buffer *buf)
+{
+ struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
+
+ if (buffer->Data && !buffer->UserBuffer) {
+ align_free(buffer->Data);
+ buffer->Data = NULL;
+ }
+
+ free(buffer);
+}
+
+
+static struct pipe_buffer *
+surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ const unsigned alignment = 64;
+ struct pipe_format_block block;
+ unsigned nblocksx, nblocksy;
+
+ pf_get_block(format, &block);
+ nblocksx = pf_get_nblocksx(&block, width);
+ nblocksy = pf_get_nblocksy(&block, height);
+ *stride = round_up(nblocksx * block.size, alignment);
+
+ return winsys->buffer_create(winsys, alignment,
+ usage,
+ *stride * nblocksy);
+}
+
+
+static void
+fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ /* no-op */
+}
+
+
+static int
+fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ /* no-op */
+ return 0;
+}
+
+
+static int
+fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ /* no-op */
+ return 0;
+}
+
+
+/**
+ * Create/return a new pipe_winsys object.
+ */
+struct pipe_winsys *
+create_sw_winsys(void)
+{
+ struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys);
+ if (!ws)
+ return NULL;
+
+ /* Fill in this struct with callbacks that pipe will need to
+ * communicate with the window system, buffer manager, etc.
+ */
+ ws->Base.buffer_create = buffer_create;
+ ws->Base.user_buffer_create = user_buffer_create;
+ ws->Base.buffer_map = buffer_map;
+ ws->Base.buffer_unmap = buffer_unmap;
+ ws->Base.buffer_destroy = buffer_destroy;
+
+ ws->Base.surface_buffer_create = surface_buffer_create;
+
+ ws->Base.fence_reference = fence_reference;
+ ws->Base.fence_signalled = fence_signalled;
+ ws->Base.fence_finish = fence_finish;
+
+ ws->Base.flush_frontbuffer = NULL; /* not implemented here! */
+
+ ws->Base.get_name = get_name;
+
+ return &ws->Base;
+}
diff --git a/src/gallium/winsys/egl_xlib/sw_winsys.h b/src/gallium/winsys/egl_xlib/sw_winsys.h
new file mode 100644
index 0000000000..f96c5a14b0
--- /dev/null
+++ b/src/gallium/winsys/egl_xlib/sw_winsys.h
@@ -0,0 +1,40 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef SW_WINSYS_H
+#define SW_WINSYS_H
+
+
+struct pipe_winsys;
+
+
+extern struct pipe_winsys *
+create_sw_winsys(void);
+
+
+#endif /* SW_WINSYS_H */
diff --git a/src/gallium/winsys/g3dvl/nouveau/Makefile b/src/gallium/winsys/g3dvl/nouveau/Makefile
new file mode 100644
index 0000000000..2997f6b79c
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/Makefile
@@ -0,0 +1,50 @@
+TARGET = libnouveau_dri.so
+GALLIUMDIR = ../../..
+DRMDIR ?= /usr
+DRIDIR = ../../../../driclient
+
+OBJECTS = nouveau_screen_vl.o nouveau_context_vl.o nouveau_swapbuffers.o
+
+CFLAGS += -g -Wall -Werror=implicit-function-declaration -fPIC \
+ -I${GALLIUMDIR}/include \
+ -I${GALLIUMDIR}/winsys/g3dvl \
+ -I${GALLIUMDIR}/winsys/drm/nouveau \
+ -I${DRMDIR}/include \
+ -I${DRMDIR}/include/drm \
+ -I${DRMDIR}/include/nouveau \
+ -I${GALLIUMDIR}/drivers \
+ -I${GALLIUMDIR}/auxiliary \
+ -I${DRIDIR}/include
+
+LDFLAGS += -L${DRMDIR}/lib \
+ -L${DRIDIR}/lib \
+ -L${GALLIUMDIR}/winsys/drm/nouveau/common \
+ -L${GALLIUMDIR}/auxiliary/draw \
+ -L${GALLIUMDIR}/auxiliary/tgsi \
+ -L${GALLIUMDIR}/auxiliary/translate \
+ -L${GALLIUMDIR}/auxiliary/rtasm \
+ -L${GALLIUMDIR}/auxiliary/cso_cache \
+ -L${GALLIUMDIR}/drivers/nv04 \
+ -L${GALLIUMDIR}/drivers/nv10 \
+ -L${GALLIUMDIR}/drivers/nv20 \
+ -L${GALLIUMDIR}/drivers/nv30 \
+ -L${GALLIUMDIR}/drivers/nv40 \
+ -L${GALLIUMDIR}/drivers/nv50
+
+LIBS += -lnouveaudrm -ldriclient -ldrm_nouveau -ldrm -lnv04 -lnv10 -lnv20 -lnv30 -lnv40 -lnv50 -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lm
+
+#############################################
+
+.PHONY = all clean libdriclient
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS} libdriclient
+ $(CC) ${LDFLAGS} -shared -o $@ ${OBJECTS} ${LIBS}
+
+libdriclient:
+ cd ${DRIDIR}/src; ${MAKE}
+
+clean:
+ cd ${DRIDIR}/src; ${MAKE} clean
+ rm -rf ${OBJECTS} ${TARGET}
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_context_vl.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_context_vl.c
new file mode 100644
index 0000000000..dfc4905bc0
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_context_vl.c
@@ -0,0 +1,172 @@
+#include "nouveau_context_vl.h"
+#include <pipe/p_defines.h>
+#include <pipe/p_context.h>
+#include <pipe/p_screen.h>
+#include <util/u_memory.h>
+#include <common/nouveau_dri.h>
+#include <common/nouveau_local.h>
+#include <common/nouveau_winsys_pipe.h>
+#include "nouveau_screen_vl.h"
+
+/*
+#ifdef DEBUG
+static const struct dri_debug_control debug_control[] = {
+ { "bo", DEBUG_BO },
+ { NULL, 0 }
+};
+int __nouveau_debug = 0;
+#endif
+*/
+
+int
+nouveau_context_create(dri_context_t *dri_context)
+{
+ dri_screen_t *dri_screen;
+ struct nouveau_screen_vl *nv_screen;
+ struct nouveau_context_vl *nv;
+
+ assert (dri_context);
+
+ dri_screen = dri_context->dri_screen;
+ nv_screen = dri_screen->private;
+ nv = CALLOC_STRUCT(nouveau_context_vl);
+
+ if (!nv)
+ return 1;
+
+ if (nouveau_context_init(&nv_screen->base, dri_context->drm_context,
+ (drmLock*)&dri_screen->sarea->lock, NULL, &nv->base))
+ {
+ FREE(nv);
+ return 1;
+ }
+
+ dri_context->private = (void*)nv;
+ nv->dri_context = dri_context;
+ nv->nv_screen = nv_screen;
+
+ /*
+ driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache,
+ nv->dri_screen->myNum, "nouveau");
+#ifdef DEBUG
+ __nouveau_debug = driParseDebugString(getenv("NOUVEAU_DEBUG"),
+ debug_control);
+#endif
+ */
+
+ nv->base.nvc->pctx[nv->base.pctx_id]->priv = nv;
+
+ return 0;
+}
+
+void
+nouveau_context_destroy(dri_context_t *dri_context)
+{
+ struct nouveau_context_vl *nv = dri_context->private;
+
+ assert(dri_context);
+
+ nouveau_context_cleanup(&nv->base);
+
+ FREE(nv);
+}
+
+int
+nouveau_context_bind(struct nouveau_context_vl *nv, dri_drawable_t *dri_drawable)
+{
+ assert(nv);
+ assert(dri_drawable);
+
+ if (nv->dri_drawable != dri_drawable)
+ {
+ nv->dri_drawable = dri_drawable;
+ dri_drawable->private = nv;
+ }
+
+ return 0;
+}
+
+int
+nouveau_context_unbind(struct nouveau_context_vl *nv)
+{
+ assert(nv);
+
+ nv->dri_drawable = NULL;
+
+ return 0;
+}
+
+/* Show starts here */
+
+int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable)
+{
+ struct nouveau_context_vl *nv;
+ dri_drawable_t *dri_drawable;
+
+ assert(pipe);
+
+ nv = pipe->priv;
+
+ driCreateDrawable(nv->nv_screen->dri_screen, drawable, &dri_drawable);
+
+ nouveau_context_bind(nv, dri_drawable);
+
+ return 0;
+}
+
+int unbind_pipe_drawable(struct pipe_context *pipe)
+{
+ assert (pipe);
+
+ nouveau_context_unbind(pipe->priv);
+
+ return 0;
+}
+
+struct pipe_context* create_pipe_context(Display *display, int screen)
+{
+ dri_screen_t *dri_screen;
+ dri_framebuffer_t dri_framebuf;
+ dri_context_t *dri_context;
+ struct nouveau_context_vl *nv;
+
+ assert(display);
+
+ driCreateScreen(display, screen, &dri_screen, &dri_framebuf);
+ driCreateContext(dri_screen, XDefaultVisual(display, screen), &dri_context);
+
+ nouveau_screen_create(dri_screen, &dri_framebuf);
+ nouveau_context_create(dri_context);
+
+ nv = dri_context->private;
+
+ return nv->base.nvc->pctx[nv->base.pctx_id];
+}
+
+int destroy_pipe_context(struct pipe_context *pipe)
+{
+ struct pipe_screen *screen;
+ struct pipe_winsys *winsys;
+ struct nouveau_context_vl *nv;
+ dri_screen_t *dri_screen;
+ dri_context_t *dri_context;
+
+ assert(pipe);
+
+ screen = pipe->screen;
+ winsys = pipe->winsys;
+ nv = pipe->priv;
+ dri_context = nv->dri_context;
+ dri_screen = dri_context->dri_screen;
+
+ pipe->destroy(pipe);
+ screen->destroy(screen);
+ FREE(winsys);
+
+ nouveau_context_destroy(dri_context);
+ nouveau_screen_destroy(dri_screen);
+ driDestroyContext(dri_context);
+ driDestroyScreen(dri_screen);
+
+ return 0;
+}
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_context_vl.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_context_vl.h
new file mode 100644
index 0000000000..1115c3130c
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_context_vl.h
@@ -0,0 +1,39 @@
+#ifndef __NOUVEAU_CONTEXT_VL_H__
+#define __NOUVEAU_CONTEXT_VL_H__
+
+#include <driclient.h>
+#include <nouveau/nouveau_winsys.h>
+#include <common/nouveau_context.h>
+
+/*#include "xmlconfig.h"*/
+
+struct nouveau_context_vl {
+ struct nouveau_context base;
+ struct nouveau_screen_vl *nv_screen;
+ dri_context_t *dri_context;
+ dri_drawable_t *dri_drawable;
+ unsigned int last_stamp;
+ /*driOptionCache dri_option_cache;*/
+ drm_context_t drm_context;
+ drmLock drm_lock;
+};
+
+extern int nouveau_context_create(dri_context_t *);
+extern void nouveau_context_destroy(dri_context_t *);
+extern int nouveau_context_bind(struct nouveau_context_vl *, dri_drawable_t *);
+extern int nouveau_context_unbind(struct nouveau_context_vl *);
+
+#ifdef DEBUG
+extern int __nouveau_debug;
+
+#define DEBUG_BO (1 << 0)
+
+#define DBG(flag, ...) do { \
+ if (__nouveau_debug & (DEBUG_##flag)) \
+ NOUVEAU_ERR(__VA_ARGS__); \
+} while(0)
+#else
+#define DBG(flag, ...)
+#endif
+
+#endif
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_screen_vl.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen_vl.c
new file mode 100644
index 0000000000..b7c74f8299
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen_vl.c
@@ -0,0 +1,88 @@
+#include "nouveau_screen_vl.h"
+#include <util/u_memory.h>
+#include <nouveau_drm.h>
+#include <common/nouveau_dri.h>
+#include <common/nouveau_local.h>
+
+#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 12
+#error nouveau_drm.h version does not match expected version
+#endif
+
+/*
+PUBLIC const char __driConfigOptions[] =
+DRI_CONF_BEGIN
+DRI_CONF_END;
+static const GLuint __driNConfigOptions = 0;
+*/
+
+int nouveau_check_dri_drm_ddx(dri_version_t *dri, dri_version_t *drm, dri_version_t *ddx)
+{
+ static const dri_version_t ddx_expected = {0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL};
+ static const dri_version_t dri_expected = {4, 0, 0};
+ static const dri_version_t drm_expected = {0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL};
+
+ assert(dri);
+ assert(drm);
+ assert(ddx);
+
+ if (dri->major != dri_expected.major || dri->minor < dri_expected.minor)
+ {
+ NOUVEAU_ERR("Unexpected DRI version.\n");
+ return 1;
+ }
+ if (drm->major != drm_expected.major || drm->minor < drm_expected.minor)
+ {
+ NOUVEAU_ERR("Unexpected DRM version.\n");
+ return 1;
+ }
+ if (ddx->major != ddx_expected.major || ddx->minor < ddx_expected.minor)
+ {
+ NOUVEAU_ERR("Unexpected DDX version.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+nouveau_screen_create(dri_screen_t *dri_screen, dri_framebuffer_t *dri_framebuf)
+{
+ struct nouveau_dri *nv_dri = dri_framebuf->private;
+ struct nouveau_screen_vl *nv_screen;
+
+ assert(dri_screen);
+ assert(dri_framebuf);
+
+ if (nouveau_check_dri_drm_ddx(&dri_screen->dri, &dri_screen->drm, &dri_screen->ddx))
+ return 1;
+
+ nv_screen = CALLOC_STRUCT(nouveau_screen_vl);
+
+ if (!nv_screen)
+ return 1;
+
+ if (nouveau_screen_init(nv_dri, dri_screen->fd, &nv_screen->base))
+ {
+ FREE(nv_screen);
+ return 1;
+ }
+
+ /*
+ driParseOptionInfo(&nv_screen->option_cache,
+ __driConfigOptions, __driNConfigOptions);
+ */
+
+ nv_screen->dri_screen = dri_screen;
+ dri_screen->private = (void*)nv_screen;
+
+ return 0;
+}
+
+void
+nouveau_screen_destroy(dri_screen_t *dri_screen)
+{
+ struct nouveau_screen_vl *nv_screen = dri_screen->private;
+
+ nouveau_screen_cleanup(&nv_screen->base);
+ FREE(nv_screen);
+}
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_screen_vl.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen_vl.h
new file mode 100644
index 0000000000..0c1ceca6de
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen_vl.h
@@ -0,0 +1,20 @@
+#ifndef __NOUVEAU_SCREEN_VL_H__
+#define __NOUVEAU_SCREEN_VL_H__
+
+#include <driclient.h>
+#include <common/nouveau_screen.h>
+
+/* TODO: Investigate using DRI options for interesting things */
+/*#include "xmlconfig.h"*/
+
+struct nouveau_screen_vl
+{
+ struct nouveau_screen base;
+ dri_screen_t *dri_screen;
+ /*driOptionCache option_cache;*/
+};
+
+int nouveau_screen_create(dri_screen_t *dri_screen, dri_framebuffer_t *dri_framebuf);
+void nouveau_screen_destroy(dri_screen_t *dri_screen);
+
+#endif
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c
new file mode 100644
index 0000000000..77e46a2054
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c
@@ -0,0 +1,94 @@
+#include <driclient.h>
+#include <common/nouveau_local.h>
+#include <common/nouveau_screen.h>
+#include "nouveau_context_vl.h"
+#include "nouveau_swapbuffers.h"
+
+void
+nouveau_copy_buffer(dri_drawable_t *dri_drawable, struct pipe_surface *surf,
+ const drm_clip_rect_t *rect)
+{
+ struct nouveau_context_vl *nv = dri_drawable->private;
+ struct pipe_context *pipe = nv->base.nvc->pctx[nv->base.pctx_id];
+ drm_clip_rect_t *pbox;
+ int nbox, i;
+
+ LOCK_HARDWARE(&nv->base);
+ if (!dri_drawable->num_cliprects) {
+ UNLOCK_HARDWARE(&nv->base);
+ return;
+ }
+ pbox = dri_drawable->cliprects;
+ nbox = dri_drawable->num_cliprects;
+
+ for (i = 0; i < nbox; i++, pbox++) {
+ int sx, sy, dx, dy, w, h;
+
+ sx = pbox->x1 - dri_drawable->x;
+ sy = pbox->y1 - dri_drawable->y;
+ dx = pbox->x1;
+ dy = pbox->y1;
+ w = pbox->x2 - pbox->x1;
+ h = pbox->y2 - pbox->y1;
+
+ pipe->surface_copy(pipe, nv->base.frontbuffer,
+ dx, dy, surf, sx, sy, w, h);
+ }
+
+ FIRE_RING(nv->base.nvc->channel);
+ UNLOCK_HARDWARE(&nv->base);
+}
+
+void
+nouveau_copy_sub_buffer(dri_drawable_t *dri_drawable, struct pipe_surface *surf, int x, int y, int w, int h)
+{
+ if (surf) {
+ drm_clip_rect_t rect;
+ rect.x1 = x;
+ rect.y1 = y;
+ rect.x2 = x + w;
+ rect.y2 = y + h;
+
+ nouveau_copy_buffer(dri_drawable, surf, &rect);
+ }
+}
+
+void
+nouveau_swap_buffers(dri_drawable_t *dri_drawable, struct pipe_surface *surf)
+{
+ if (surf)
+ nouveau_copy_buffer(dri_drawable, surf, NULL);
+}
+
+void
+nouveau_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surf,
+ void *context_private)
+{
+ struct nouveau_context_vl *nv;
+ dri_drawable_t *dri_drawable;
+
+ assert(pws);
+ assert(surf);
+ assert(context_private);
+
+ nv = context_private;
+ dri_drawable = nv->dri_drawable;
+
+ nouveau_copy_buffer(dri_drawable, surf, NULL);
+}
+
+void
+nouveau_contended_lock(struct nouveau_context *nv)
+{
+ struct nouveau_context_vl *nv_vl = (struct nouveau_context_vl*)nv;
+ dri_drawable_t *dri_drawable = nv_vl->dri_drawable;
+ dri_screen_t *dri_screen = nv_vl->dri_context->dri_screen;
+
+ /* If the window moved, may need to set a new cliprect now.
+ *
+ * NOTE: This releases and regains the hw lock, so all state
+ * checking must be done *after* this call:
+ */
+ if (dri_drawable)
+ DRI_VALIDATE_DRAWABLE_INFO(dri_screen, dri_drawable);
+}
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h
new file mode 100644
index 0000000000..35e934adba
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h
@@ -0,0 +1,10 @@
+#ifndef __NOUVEAU_SWAPBUFFERS_H__
+#define __NOUVEAU_SWAPBUFFERS_H__
+
+extern void nouveau_copy_buffer(dri_drawable_t *, struct pipe_surface *,
+ const drm_clip_rect_t *);
+extern void nouveau_copy_sub_buffer(dri_drawable_t *, struct pipe_surface *,
+ int x, int y, int w, int h);
+extern void nouveau_swap_buffers(dri_drawable_t *, struct pipe_surface *);
+
+#endif
diff --git a/src/gallium/winsys/g3dvl/vl_winsys.h b/src/gallium/winsys/g3dvl/vl_winsys.h
new file mode 100644
index 0000000000..c83db28dd9
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/vl_winsys.h
@@ -0,0 +1,14 @@
+#ifndef vl_winsys_h
+#define vl_winsys_h
+
+#include <X11/Xlib.h>
+
+struct pipe_context;
+
+struct pipe_context* create_pipe_context(Display *display, int screen);
+int destroy_pipe_context(struct pipe_context *pipe);
+int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable);
+int unbind_pipe_drawable(struct pipe_context *pipe);
+
+#endif
+
diff --git a/src/gallium/winsys/g3dvl/xsp_winsys.c b/src/gallium/winsys/g3dvl/xsp_winsys.c
new file mode 100644
index 0000000000..698c2856a4
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/xsp_winsys.c
@@ -0,0 +1,290 @@
+#include "vl_winsys.h"
+#include <X11/Xutil.h>
+#include <pipe/internal/p_winsys_screen.h>
+#include <pipe/p_state.h>
+#include <pipe/p_inlines.h>
+#include <util/u_memory.h>
+#include <util/u_math.h>
+#include <softpipe/sp_winsys.h>
+#include <softpipe/sp_texture.h>
+
+/* pipe_winsys implementation */
+
+struct xsp_pipe_winsys
+{
+ struct pipe_winsys base;
+ XImage fbimage;
+};
+
+struct xsp_context
+{
+ Display *display;
+ int screen;
+ Drawable drawable;
+ int drawable_bound;
+};
+
+struct xsp_buffer
+{
+ struct pipe_buffer base;
+ boolean is_user_buffer;
+ void *data;
+ void *mapped_data;
+};
+
+static struct pipe_buffer* xsp_buffer_create(struct pipe_winsys *pws, unsigned alignment, unsigned usage, unsigned size)
+{
+ struct xsp_buffer *buffer;
+
+ assert(pws);
+
+ buffer = calloc(1, sizeof(struct xsp_buffer));
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.alignment = alignment;
+ buffer->base.usage = usage;
+ buffer->base.size = size;
+ buffer->data = align_malloc(size, alignment);
+
+ return (struct pipe_buffer*)buffer;
+}
+
+static struct pipe_buffer* xsp_user_buffer_create(struct pipe_winsys *pws, void *data, unsigned size)
+{
+ struct xsp_buffer *buffer;
+
+ assert(pws);
+
+ buffer = calloc(1, sizeof(struct xsp_buffer));
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.size = size;
+ buffer->is_user_buffer = TRUE;
+ buffer->data = data;
+
+ return (struct pipe_buffer*)buffer;
+}
+
+static void* xsp_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buffer, unsigned flags)
+{
+ struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
+
+ assert(pws);
+ assert(buffer);
+
+ xsp_buf->mapped_data = xsp_buf->data;
+
+ return xsp_buf->mapped_data;
+}
+
+static void xsp_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buffer)
+{
+ struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
+
+ assert(pws);
+ assert(buffer);
+
+ xsp_buf->mapped_data = NULL;
+}
+
+static void xsp_buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buffer)
+{
+ struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
+
+ assert(pws);
+ assert(buffer);
+
+ if (!xsp_buf->is_user_buffer)
+ align_free(xsp_buf->data);
+
+ free(xsp_buf);
+}
+
+static struct pipe_buffer* xsp_surface_buffer_create
+(
+ struct pipe_winsys *pws,
+ unsigned width,
+ unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned *stride
+)
+{
+ const unsigned int ALIGNMENT = 1;
+ struct pipe_format_block block;
+ unsigned nblocksx, nblocksy;
+
+ pf_get_block(format, &block);
+ nblocksx = pf_get_nblocksx(&block, width);
+ nblocksy = pf_get_nblocksy(&block, height);
+ *stride = align(nblocksx * block.size, ALIGNMENT);
+
+ return pws->buffer_create(pws, ALIGNMENT,
+ usage,
+ *stride * nblocksy);
+}
+
+static void xsp_fence_reference(struct pipe_winsys *pws, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence)
+{
+ assert(pws);
+ assert(ptr);
+ assert(fence);
+}
+
+static int xsp_fence_signalled(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
+{
+ assert(pws);
+ assert(fence);
+
+ return 0;
+}
+
+static int xsp_fence_finish(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
+{
+ assert(pws);
+ assert(fence);
+
+ return 0;
+}
+
+static void xsp_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surface, void *context_private)
+{
+ struct xsp_pipe_winsys *xsp_winsys;
+ struct xsp_context *xsp_context;
+
+ assert(pws);
+ assert(surface);
+ assert(context_private);
+
+ xsp_winsys = (struct xsp_pipe_winsys*)pws;
+ xsp_context = (struct xsp_context*)context_private;
+
+ if (!xsp_context->drawable_bound)
+ return;
+
+ xsp_winsys->fbimage.width = surface->width;
+ xsp_winsys->fbimage.height = surface->height;
+ xsp_winsys->fbimage.bytes_per_line = surface->width * (xsp_winsys->fbimage.bits_per_pixel >> 3);
+ xsp_winsys->fbimage.data = ((struct xsp_buffer *)softpipe_texture(surface->texture)->buffer)->data + surface->offset;
+
+ XPutImage
+ (
+ xsp_context->display,
+ xsp_context->drawable,
+ XDefaultGC(xsp_context->display, xsp_context->screen),
+ &xsp_winsys->fbimage,
+ 0,
+ 0,
+ 0,
+ 0,
+ surface->width,
+ surface->height
+ );
+ XFlush(xsp_context->display);
+}
+
+static const char* xsp_get_name(struct pipe_winsys *pws)
+{
+ assert(pws);
+ return "X11 SoftPipe";
+}
+
+/* Show starts here */
+
+int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable)
+{
+ struct xsp_context *xsp_context;
+
+ assert(pipe);
+
+ xsp_context = pipe->priv;
+ xsp_context->drawable = drawable;
+ xsp_context->drawable_bound = 1;
+
+ return 0;
+}
+
+int unbind_pipe_drawable(struct pipe_context *pipe)
+{
+ struct xsp_context *xsp_context;
+
+ assert(pipe);
+
+ xsp_context = pipe->priv;
+ xsp_context->drawable_bound = 0;
+
+ return 0;
+}
+
+struct pipe_context* create_pipe_context(Display *display, int screen)
+{
+ struct xsp_pipe_winsys *xsp_winsys;
+ struct xsp_context *xsp_context;
+ struct pipe_screen *sp_screen;
+ struct pipe_context *sp_pipe;
+
+ assert(display);
+
+ xsp_winsys = calloc(1, sizeof(struct xsp_pipe_winsys));
+ xsp_winsys->base.buffer_create = xsp_buffer_create;
+ xsp_winsys->base.user_buffer_create = xsp_user_buffer_create;
+ xsp_winsys->base.buffer_map = xsp_buffer_map;
+ xsp_winsys->base.buffer_unmap = xsp_buffer_unmap;
+ xsp_winsys->base.buffer_destroy = xsp_buffer_destroy;
+ xsp_winsys->base.surface_buffer_create = xsp_surface_buffer_create;
+ xsp_winsys->base.fence_reference = xsp_fence_reference;
+ xsp_winsys->base.fence_signalled = xsp_fence_signalled;
+ xsp_winsys->base.fence_finish = xsp_fence_finish;
+ xsp_winsys->base.flush_frontbuffer = xsp_flush_frontbuffer;
+ xsp_winsys->base.get_name = xsp_get_name;
+
+ {
+ /* XXX: Can't use the returned XImage* directly,
+ since we don't have control over winsys destruction
+ and we wouldn't be able to free it */
+ XImage *template = XCreateImage
+ (
+ display,
+ XDefaultVisual(display, XDefaultScreen(display)),
+ XDefaultDepth(display, XDefaultScreen(display)),
+ ZPixmap,
+ 0,
+ NULL,
+ 0, /* Don't know the width and height until flush_frontbuffer */
+ 0,
+ 32,
+ 0
+ );
+
+ memcpy(&xsp_winsys->fbimage, template, sizeof(XImage));
+ XInitImage(&xsp_winsys->fbimage);
+
+ XDestroyImage(template);
+ }
+
+ sp_screen = softpipe_create_screen((struct pipe_winsys*)xsp_winsys);
+ sp_pipe = softpipe_create(sp_screen);
+
+ xsp_context = calloc(1, sizeof(struct xsp_context));
+ xsp_context->display = display;
+ xsp_context->screen = screen;
+
+ sp_pipe->priv = xsp_context;
+
+ return sp_pipe;
+}
+
+int destroy_pipe_context(struct pipe_context *pipe)
+{
+ struct pipe_screen *screen;
+ struct pipe_winsys *winsys;
+
+ assert(pipe);
+
+ screen = pipe->screen;
+ winsys = pipe->winsys;
+ free(pipe->priv);
+ pipe->destroy(pipe);
+ screen->destroy(screen);
+ free(winsys);
+
+ return 0;
+}
diff --git a/src/gallium/winsys/gdi/SConscript b/src/gallium/winsys/gdi/SConscript
new file mode 100644
index 0000000000..86eb9ef55e
--- /dev/null
+++ b/src/gallium/winsys/gdi/SConscript
@@ -0,0 +1,39 @@
+#######################################################################
+# SConscript for gdi winsys
+
+Import('*')
+
+if env['platform'] == 'windows':
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#src/gallium/state_trackers/wgl',
+ ])
+
+ env.Append(LIBS = [
+ 'gdi32',
+ 'user32',
+ 'kernel32',
+ 'ws2_32',
+ ])
+
+ sources = [
+ 'gdi_softpipe_winsys.c',
+ ]
+
+ if env['gcc']:
+ sources += ['#src/gallium/state_trackers/wgl/opengl32.mingw.def']
+ else:
+ sources += ['#src/gallium/state_trackers/wgl/opengl32.def']
+
+ drivers = [
+ trace,
+ softpipe,
+ ]
+
+ env.SharedLibrary(
+ target ='opengl32',
+ source = sources,
+ LIBS = wgl + glapi + mesa + drivers + auxiliaries + env['LIBS'],
+ )
diff --git a/src/gallium/winsys/gdi/gdi_softpipe_winsys.c b/src/gallium/winsys/gdi/gdi_softpipe_winsys.c
new file mode 100644
index 0000000000..66120a6a98
--- /dev/null
+++ b/src/gallium/winsys/gdi/gdi_softpipe_winsys.c
@@ -0,0 +1,334 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * 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.
+ *
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Softpipe support.
+ *
+ * @author Keith Whitwell
+ * @author Brian Paul
+ * @author Jose Fonseca
+ */
+
+
+#include <windows.h>
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "softpipe/sp_winsys.h"
+#include "softpipe/sp_texture.h"
+#include "shared/stw_winsys.h"
+
+
+struct gdi_softpipe_buffer
+{
+ struct pipe_buffer base;
+ boolean userBuffer; /** Is this a user-space buffer? */
+ void *data;
+ void *mapped;
+};
+
+
+/** Cast wrapper */
+static INLINE struct gdi_softpipe_buffer *
+gdi_softpipe_buffer( struct pipe_buffer *buf )
+{
+ return (struct gdi_softpipe_buffer *)buf;
+}
+
+
+static void *
+gdi_softpipe_buffer_map(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf,
+ unsigned flags)
+{
+ struct gdi_softpipe_buffer *gdi_softpipe_buf = gdi_softpipe_buffer(buf);
+ gdi_softpipe_buf->mapped = gdi_softpipe_buf->data;
+ return gdi_softpipe_buf->mapped;
+}
+
+
+static void
+gdi_softpipe_buffer_unmap(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf)
+{
+ struct gdi_softpipe_buffer *gdi_softpipe_buf = gdi_softpipe_buffer(buf);
+ gdi_softpipe_buf->mapped = NULL;
+}
+
+
+static void
+gdi_softpipe_buffer_destroy(struct pipe_buffer *buf)
+{
+ struct gdi_softpipe_buffer *oldBuf = gdi_softpipe_buffer(buf);
+
+ if (oldBuf->data) {
+ if (!oldBuf->userBuffer)
+ align_free(oldBuf->data);
+
+ oldBuf->data = NULL;
+ }
+
+ FREE(oldBuf);
+}
+
+
+static const char *
+gdi_softpipe_get_name(struct pipe_winsys *winsys)
+{
+ return "softpipe";
+}
+
+
+static struct pipe_buffer *
+gdi_softpipe_buffer_create(struct pipe_winsys *winsys,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct gdi_softpipe_buffer *buffer = CALLOC_STRUCT(gdi_softpipe_buffer);
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.alignment = alignment;
+ buffer->base.usage = usage;
+ buffer->base.size = size;
+
+ buffer->data = align_malloc(size, alignment);
+
+ return &buffer->base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+gdi_softpipe_user_buffer_create(struct pipe_winsys *winsys,
+ void *ptr,
+ unsigned bytes)
+{
+ struct gdi_softpipe_buffer *buffer;
+
+ buffer = CALLOC_STRUCT(gdi_softpipe_buffer);
+ if(!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.size = bytes;
+ buffer->userBuffer = TRUE;
+ buffer->data = ptr;
+
+ return &buffer->base;
+}
+
+
+/**
+ * Round n up to next multiple.
+ */
+static INLINE unsigned
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+
+static struct pipe_buffer *
+gdi_softpipe_surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ const unsigned alignment = 64;
+ struct pipe_format_block block;
+ unsigned nblocksx, nblocksy;
+
+ pf_get_block(format, &block);
+ nblocksx = pf_get_nblocksx(&block, width);
+ nblocksy = pf_get_nblocksy(&block, height);
+ *stride = round_up(nblocksx * block.size, alignment);
+
+ return winsys->buffer_create(winsys, alignment,
+ usage,
+ *stride * nblocksy);
+}
+
+
+static void
+gdi_softpipe_dummy_flush_frontbuffer(struct pipe_winsys *winsys,
+ struct pipe_surface *surface,
+ void *context_private)
+{
+ assert(0);
+}
+
+
+static void
+gdi_softpipe_fence_reference(struct pipe_winsys *winsys,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+}
+
+
+static int
+gdi_softpipe_fence_signalled(struct pipe_winsys *winsys,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+static int
+gdi_softpipe_fence_finish(struct pipe_winsys *winsys,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+static void
+gdi_softpipe_destroy(struct pipe_winsys *winsys)
+{
+ FREE(winsys);
+}
+
+
+static struct pipe_screen *
+gdi_softpipe_screen_create(void)
+{
+ static struct pipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ winsys = CALLOC_STRUCT(pipe_winsys);
+ if(!winsys)
+ return NULL;
+
+ winsys->destroy = gdi_softpipe_destroy;
+
+ winsys->buffer_create = gdi_softpipe_buffer_create;
+ winsys->user_buffer_create = gdi_softpipe_user_buffer_create;
+ winsys->buffer_map = gdi_softpipe_buffer_map;
+ winsys->buffer_unmap = gdi_softpipe_buffer_unmap;
+ winsys->buffer_destroy = gdi_softpipe_buffer_destroy;
+
+ winsys->surface_buffer_create = gdi_softpipe_surface_buffer_create;
+
+ winsys->fence_reference = gdi_softpipe_fence_reference;
+ winsys->fence_signalled = gdi_softpipe_fence_signalled;
+ winsys->fence_finish = gdi_softpipe_fence_finish;
+
+ winsys->flush_frontbuffer = gdi_softpipe_dummy_flush_frontbuffer;
+ winsys->get_name = gdi_softpipe_get_name;
+
+ screen = softpipe_create_screen(winsys);
+ if(!screen)
+ gdi_softpipe_destroy(winsys);
+
+ return screen;
+}
+
+
+static struct pipe_context *
+gdi_softpipe_context_create(struct pipe_screen *screen)
+{
+ return softpipe_create(screen);
+}
+
+
+static void
+gdi_softpipe_flush_frontbuffer(struct pipe_screen *screen,
+ struct pipe_surface *surface,
+ HDC hDC)
+{
+ struct softpipe_texture *texture;
+ struct gdi_softpipe_buffer *buffer;
+ BITMAPINFO bmi;
+
+ texture = softpipe_texture(surface->texture);
+
+ buffer = gdi_softpipe_buffer(texture->buffer);
+
+ memset(&bmi, 0, sizeof(BITMAPINFO));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = texture->stride[surface->level] / pf_get_size(surface->format);
+ bmi.bmiHeader.biHeight= -(long)surface->height;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = pf_get_bits(surface->format);
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biSizeImage = 0;
+ bmi.bmiHeader.biXPelsPerMeter = 0;
+ bmi.bmiHeader.biYPelsPerMeter = 0;
+ bmi.bmiHeader.biClrUsed = 0;
+ bmi.bmiHeader.biClrImportant = 0;
+
+ StretchDIBits(hDC,
+ 0, 0, surface->width, surface->height,
+ 0, 0, surface->width, surface->height,
+ buffer->data, &bmi, 0, SRCCOPY);
+}
+
+
+static const struct stw_winsys stw_winsys = {
+ &gdi_softpipe_screen_create,
+ &gdi_softpipe_context_create,
+ &gdi_softpipe_flush_frontbuffer
+};
+
+
+BOOL WINAPI
+DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
+{
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ if (!stw_init(&stw_winsys)) {
+ return FALSE;
+ }
+ return stw_init_thread();
+
+ case DLL_THREAD_ATTACH:
+ return stw_init_thread();
+
+ case DLL_THREAD_DETACH:
+ stw_cleanup_thread();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ stw_cleanup_thread();
+ stw_cleanup();
+ break;
+ }
+ return TRUE;
+}
diff --git a/src/gallium/winsys/xlib/Makefile b/src/gallium/winsys/xlib/Makefile
new file mode 100644
index 0000000000..522f6dc5ae
--- /dev/null
+++ b/src/gallium/winsys/xlib/Makefile
@@ -0,0 +1,105 @@
+# src/gallium/winsys/xlib/Makefile
+
+# This makefile produces a "stand-alone" libGL.so which is based on
+# Xlib (no DRI HW acceleration)
+
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+GL_MAJOR = 1
+GL_MINOR = 5
+GL_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY)
+
+
+INCLUDE_DIRS = \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/drivers \
+ -I$(TOP)/src/gallium/state_trackers/glx/xlib \
+ -I$(TOP)/src/gallium/auxiliary
+
+DEFINES += \
+ -DGALLIUM_SOFTPIPE \
+ -DGALLIUM_TRACE \
+ -DGALLIUM_BRW
+#-DGALLIUM_CELL will be defined by the config */
+
+XLIB_WINSYS_SOURCES = \
+ xlib.c \
+ xlib_cell.c \
+ xlib_brw_aub.c \
+ xlib_brw_context.c \
+ xlib_brw_screen.c \
+ xlib_softpipe.c \
+ xlib_trace.c
+
+
+XLIB_WINSYS_OBJECTS = $(XLIB_WINSYS_SOURCES:.c=.o)
+
+
+# Note: CELL_SPU_LIB is only defined for cell configs
+
+LIBS = \
+ $(GALLIUM_DRIVERS) \
+ $(TOP)/src/gallium/state_trackers/glx/xlib/libxlib.a \
+ $(TOP)/src/mesa/libglapi.a \
+ $(TOP)/src/mesa/libmesagallium.a \
+ $(GALLIUM_AUXILIARIES) \
+ $(CELL_SPU_LIB) \
+
+
+.SUFFIXES : .cpp
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) $< -o $@
+
+.cpp.o:
+ $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CXXFLAGS) $< -o $@
+
+
+
+default: $(TOP)/$(LIB_DIR)/gallium $(TOP)/$(LIB_DIR)/gallium/$(GL_LIB_NAME)
+
+$(TOP)/$(LIB_DIR)/gallium:
+ @ mkdir -p $(TOP)/$(LIB_DIR)/gallium
+
+# Make the libGL.so library
+$(TOP)/$(LIB_DIR)/gallium/$(GL_LIB_NAME): $(XLIB_WINSYS_OBJECTS) $(LIBS) Makefile
+ $(TOP)/bin/mklib -o $(GL_LIB) \
+ -linker "$(CC)" \
+ -major $(GL_MAJOR) -minor $(GL_MINOR) -patch $(GL_TINY) \
+ -install $(TOP)/$(LIB_DIR)/gallium \
+ $(MKLIB_OPTIONS) $(XLIB_WINSYS_OBJECTS) \
+ -Wl,--start-group $(LIBS) -Wl,--end-group $(GL_LIB_DEPS)
+
+
+depend: $(XLIB_WINSYS_SOURCES)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend # workaround oops on gutsy?!?
+ @ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(XLIB_WINSYS_SOURCES) \
+ > /dev/null 2>/dev/null
+
+
+install: default
+ $(INSTALL) -d $(INSTALL_DIR)/include/GL
+ $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR)
+ $(INSTALL) -m 644 $(TOP)/include/GL/*.h $(INSTALL_DIR)/include/GL
+ @if [ -e $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ]; then \
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/libGL* $(INSTALL_DIR)/$(LIB_DIR); \
+ fi
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h
+
+clean:
+ -rm -f *.o
+
+
+include depend
diff --git a/src/gallium/winsys/xlib/SConscript b/src/gallium/winsys/xlib/SConscript
new file mode 100644
index 0000000000..467d595d33
--- /dev/null
+++ b/src/gallium/winsys/xlib/SConscript
@@ -0,0 +1,66 @@
+#######################################################################
+# SConscript for xlib winsys
+
+Import('*')
+
+if env['platform'] == 'linux' \
+ and 'mesa' in env['statetrackers'] \
+ and set(('softpipe', 'llvmpipe', 'i915simple', 'trace')).intersection(env['drivers']) \
+ and not env['dri']:
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#/src/mesa',
+ '#/src/mesa/main',
+ '#src/gallium/state_trackers/glx/xlib',
+ ])
+
+ env.Append(CPPDEFINES = ['USE_XSHM'])
+
+ sources = [
+ 'xlib.c',
+ ]
+
+ drivers = []
+
+ if 'softpipe' in env['drivers']:
+ env.Append(CPPDEFINES = 'GALLIUM_SOFTPIPE')
+ sources += ['xlib_softpipe.c']
+ drivers += [softpipe]
+
+ if 'llvmpipe' in env['drivers']:
+ env.Tool('llvm')
+ if 'LLVM_VERSION' in env:
+ env.Append(CPPDEFINES = 'GALLIUM_LLVMPIPE')
+ env.Tool('udis86')
+ sources += ['xlib_llvmpipe.c']
+ drivers += [llvmpipe]
+
+ if 'i965simple' in env['drivers']:
+ env.Append(CPPDEFINES = 'GALLIUM_I965SIMPLE')
+ sources += [
+ 'xlib_brw_aub.c',
+ 'xlib_brw_context.c',
+ 'xlib_brw_screen.c',
+ ]
+ drivers += [i965simple]
+
+ if 'cell' in env['drivers']:
+ env.Append(CPPDEFINES = 'GALLIUM_CELL')
+ sources += ['xlib_cell.c']
+ drivers += [cell]
+
+ if 'trace' in env['drivers']:
+ env.Append(CPPDEFINES = 'GALLIUM_TRACE')
+ sources += ['xlib_trace.c']
+ drivers += [trace]
+
+ # TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions
+ libgl = env.SharedLibrary(
+ target ='GL',
+ source = sources,
+ LIBS = st_xlib + glapi + mesa + drivers + auxiliaries + env['LIBS'],
+ )
+
+ env.InstallSharedLibrary(libgl, version=(1, 5))
diff --git a/src/gallium/winsys/xlib/xlib.c b/src/gallium/winsys/xlib/xlib.c
new file mode 100644
index 0000000000..4b71cf7ec3
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib.c
@@ -0,0 +1,123 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell
+ */
+
+#include "xlib.h"
+#include "xm_winsys.h"
+
+#include <stdlib.h>
+#include <assert.h>
+
+/* Todo, replace all this with callback-structs provided by the
+ * individual implementations.
+ */
+
+enum mode {
+ MODE_TRACE,
+ MODE_BRW,
+ MODE_CELL,
+ MODE_LLVMPIPE,
+ MODE_SOFTPIPE
+};
+
+
+static enum mode get_mode()
+{
+ if (getenv("XMESA_TRACE"))
+ return MODE_TRACE;
+
+ if (getenv("XMESA_BRW"))
+ return MODE_BRW;
+
+#ifdef GALLIUM_CELL
+ if (!getenv("GALLIUM_NOCELL"))
+ return MODE_CELL;
+#endif
+
+#if defined(GALLIUM_LLVMPIPE)
+ return MODE_LLVMPIPE;
+#else
+ return MODE_SOFTPIPE;
+#endif
+}
+
+static void _init( void ) __attribute__((constructor));
+
+static void _init( void )
+{
+ enum mode xlib_mode = get_mode();
+
+ switch (xlib_mode) {
+ case MODE_TRACE:
+#if defined(GALLIUM_TRACE) && defined(GALLIUM_SOFTPIPE)
+ xmesa_set_driver( &xlib_trace_driver );
+#endif
+ break;
+ case MODE_BRW:
+#if defined(GALLIUM_BRW)
+ xmesa_set_driver( &xlib_brw_driver );
+#endif
+ break;
+ case MODE_CELL:
+#if defined(GALLIUM_CELL)
+ xmesa_set_driver( &xlib_cell_driver );
+#endif
+ break;
+ case MODE_LLVMPIPE:
+#if defined(GALLIUM_LLVMPIPE)
+ xmesa_set_driver( &xlib_llvmpipe_driver );
+#endif
+ break;
+ case MODE_SOFTPIPE:
+#if defined(GALLIUM_SOFTPIPE)
+ xmesa_set_driver( &xlib_softpipe_driver );
+#endif
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * Butt-ugly hack to convince the linker not to throw away public GL
+ * symbols (they are all referenced from getprocaddress, I guess).
+ */
+extern void (*linker_foo(const unsigned char *procName))();
+extern void (*glXGetProcAddress(const unsigned char *procName))();
+
+extern void (*linker_foo(const unsigned char *procName))()
+{
+ return glXGetProcAddress(procName);
+}
diff --git a/src/gallium/winsys/xlib/xlib.h b/src/gallium/winsys/xlib/xlib.h
new file mode 100644
index 0000000000..347d45f4d6
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib.h
@@ -0,0 +1,15 @@
+
+#ifndef XLIB_H
+#define XLIB_H
+
+#include "pipe/p_compiler.h"
+#include "xm_winsys.h"
+
+extern struct xm_driver xlib_trace_driver;
+extern struct xm_driver xlib_softpipe_driver;
+extern struct xm_driver xlib_llvmpipe_driver;
+extern struct xm_driver xlib_cell_driver;
+extern struct xm_driver xlib_brw_driver;
+
+
+#endif
diff --git a/src/gallium/winsys/xlib/xlib_brw.h b/src/gallium/winsys/xlib/xlib_brw.h
new file mode 100644
index 0000000000..be2dd147db
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib_brw.h
@@ -0,0 +1,30 @@
+#ifndef XLIB_BRW_H
+#define XLIB_BRW_H
+
+struct pipe_winsys;
+struct pipe_buffer;
+struct pipe_surface;
+struct xmesa_buffer;
+
+unsigned xlib_brw_get_buffer_offset( struct pipe_winsys *pws,
+ struct pipe_buffer *buf,
+ unsigned access_flags );
+
+void xlib_brw_buffer_subdata_typed( struct pipe_winsys *pws,
+ struct pipe_buffer *buf,
+ unsigned long offset,
+ unsigned long size,
+ const void *data,
+ unsigned data_type );
+
+
+
+void xlib_brw_commands_aub(struct pipe_winsys *winsys,
+ unsigned *cmds,
+ unsigned nr_dwords);
+
+struct pipe_context *
+xlib_create_brw_context( struct pipe_screen *screen,
+ void *unused );
+
+#endif
diff --git a/src/gallium/winsys/xlib/xlib_brw_aub.c b/src/gallium/winsys/xlib/xlib_brw_aub.c
new file mode 100644
index 0000000000..b6bd849ef2
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib_brw_aub.c
@@ -0,0 +1,399 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "xlib_brw_aub.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "util/u_debug.h"
+#include "util/u_memory.h"
+#include "softpipe/sp_texture.h"
+
+
+struct brw_aubfile {
+ FILE *file;
+ unsigned next_free_page;
+};
+
+
+extern char *__progname;
+
+
+struct aub_file_header {
+ unsigned int instruction_type;
+ unsigned int pad0:16;
+ unsigned int minor:8;
+ unsigned int major:8;
+ unsigned char application[8*4];
+ unsigned int day:8;
+ unsigned int month:8;
+ unsigned int year:16;
+ unsigned int timezone:8;
+ unsigned int second:8;
+ unsigned int minute:8;
+ unsigned int hour:8;
+ unsigned int comment_length:16;
+ unsigned int pad1:16;
+};
+
+struct aub_block_header {
+ unsigned int instruction_type;
+ unsigned int operation:8;
+ unsigned int type:8;
+ unsigned int address_space:8;
+ unsigned int pad0:8;
+ unsigned int general_state_type:8;
+ unsigned int surface_state_type:8;
+ unsigned int pad1:16;
+ unsigned int address;
+ unsigned int length;
+};
+
+struct aub_dump_bmp {
+ unsigned int instruction_type;
+ unsigned int xmin:16;
+ unsigned int ymin:16;
+ unsigned int pitch:16;
+ unsigned int bpp:8;
+ unsigned int format:8;
+ unsigned int xsize:16;
+ unsigned int ysize:16;
+ unsigned int addr;
+ unsigned int unknown;
+};
+
+enum bh_operation {
+ BH_COMMENT,
+ BH_DATA_WRITE,
+ BH_COMMAND_WRITE,
+ BH_MMI0_WRITE32,
+ BH_END_SCENE,
+ BH_CONFIG_MEMORY_MAP,
+ BH_MAX_OPERATION
+};
+
+enum command_write_type {
+ CW_HWB_RING = 1,
+ CW_PRIMARY_RING_A,
+ CW_PRIMARY_RING_B, /* XXX - disagreement with listaub! */
+ CW_PRIMARY_RING_C,
+ CW_MAX_TYPE
+};
+
+enum memory_map_type {
+ MM_DEFAULT,
+ MM_DYNAMIC,
+ MM_MAX_TYPE
+};
+
+enum address_space {
+ ADDR_GTT,
+ ADDR_LOCAL,
+ ADDR_MAIN,
+ ADDR_MAX
+};
+
+
+#define AUB_FILE_HEADER 0xe085000b
+#define AUB_BLOCK_HEADER 0xe0c10003
+#define AUB_DUMP_BMP 0xe09e0004
+
+/* Registers to control page table
+ */
+#define PGETBL_CTL 0x2020
+#define PGETBL_ENABLED 0x1
+
+#define NR_GTT_ENTRIES 65536 /* 256 mb */
+
+#define FAIL \
+do { \
+ fprintf(stderr, "failed to write aub data at %s/%d\n", __FUNCTION__, __LINE__); \
+ exit(1); \
+} while (0)
+
+
+/* Emit the headers at the top of each aubfile. Initialize the GTT.
+ */
+static void init_aubfile( FILE *aub_file )
+{
+ struct aub_file_header fh;
+ struct aub_block_header bh;
+ unsigned int data;
+
+ static int nr;
+
+ nr++;
+
+ /* Emit the aub header:
+ */
+ memset(&fh, 0, sizeof(fh));
+
+ fh.instruction_type = AUB_FILE_HEADER;
+ fh.minor = 0x0;
+ fh.major = 0x7;
+ memcpy(fh.application, __progname, sizeof(fh.application));
+ fh.day = (nr>>24) & 0xff;
+ fh.month = 0x0;
+ fh.year = 0x0;
+ fh.timezone = 0x0;
+ fh.second = nr & 0xff;
+ fh.minute = (nr>>8) & 0xff;
+ fh.hour = (nr>>16) & 0xff;
+ fh.comment_length = 0x0;
+
+ if (fwrite(&fh, sizeof(fh), 1, aub_file) < 0)
+ FAIL;
+
+ /* Setup the GTT starting at main memory address zero (!):
+ */
+ memset(&bh, 0, sizeof(bh));
+
+ bh.instruction_type = AUB_BLOCK_HEADER;
+ bh.operation = BH_MMI0_WRITE32;
+ bh.type = 0x0;
+ bh.address_space = ADDR_GTT; /* ??? */
+ bh.general_state_type = 0x0;
+ bh.surface_state_type = 0x0;
+ bh.address = PGETBL_CTL;
+ bh.length = 0x4;
+
+ if (fwrite(&bh, sizeof(bh), 1, aub_file) < 0)
+ FAIL;
+
+ data = 0x0 | PGETBL_ENABLED;
+
+ if (fwrite(&data, sizeof(data), 1, aub_file) < 0)
+ FAIL;
+}
+
+
+static void init_aub_gtt( struct brw_aubfile *aubfile,
+ unsigned start_offset,
+ unsigned size )
+{
+ FILE *aub_file = aubfile->file;
+ struct aub_block_header bh;
+ unsigned int i;
+
+ assert(start_offset + size < NR_GTT_ENTRIES * 4096);
+
+
+ memset(&bh, 0, sizeof(bh));
+
+ bh.instruction_type = AUB_BLOCK_HEADER;
+ bh.operation = BH_DATA_WRITE;
+ bh.type = 0x0;
+ bh.address_space = ADDR_MAIN;
+ bh.general_state_type = 0x0;
+ bh.surface_state_type = 0x0;
+ bh.address = start_offset / 4096 * 4;
+ bh.length = size / 4096 * 4;
+
+ if (fwrite(&bh, sizeof(bh), 1, aub_file) < 0)
+ FAIL;
+
+ for (i = 0; i < size / 4096; i++) {
+ unsigned data = aubfile->next_free_page | 1;
+
+ aubfile->next_free_page += 4096;
+
+ if (fwrite(&data, sizeof(data), 1, aub_file) < 0)
+ FAIL;
+ }
+
+}
+
+static void write_block_header( FILE *aub_file,
+ struct aub_block_header *bh,
+ const unsigned *data,
+ unsigned sz )
+{
+ sz = (sz + 3) & ~3;
+
+ if (fwrite(bh, sizeof(*bh), 1, aub_file) < 0)
+ FAIL;
+
+ if (fwrite(data, sz, 1, aub_file) < 0)
+ FAIL;
+
+ fflush(aub_file);
+}
+
+
+static void write_dump_bmp( FILE *aub_file,
+ struct aub_dump_bmp *db )
+{
+ if (fwrite(db, sizeof(*db), 1, aub_file) < 0)
+ FAIL;
+
+ fflush(aub_file);
+}
+
+
+
+void brw_aub_gtt_data( struct brw_aubfile *aubfile,
+ unsigned offset,
+ const void *data,
+ unsigned sz,
+ unsigned type,
+ unsigned state_type )
+{
+ struct aub_block_header bh;
+
+ bh.instruction_type = AUB_BLOCK_HEADER;
+ bh.operation = BH_DATA_WRITE;
+ bh.type = type;
+ bh.address_space = ADDR_GTT;
+ bh.pad0 = 0;
+
+ if (type == DW_GENERAL_STATE) {
+ bh.general_state_type = state_type;
+ bh.surface_state_type = 0;
+ }
+ else {
+ bh.general_state_type = 0;
+ bh.surface_state_type = state_type;
+ }
+
+ bh.pad1 = 0;
+ bh.address = offset;
+ bh.length = sz;
+
+ write_block_header(aubfile->file, &bh, data, sz);
+}
+
+
+
+void brw_aub_gtt_cmds( struct brw_aubfile *aubfile,
+ unsigned offset,
+ const void *data,
+ unsigned sz )
+{
+ struct aub_block_header bh;
+ unsigned type = CW_PRIMARY_RING_A;
+
+
+ bh.instruction_type = AUB_BLOCK_HEADER;
+ bh.operation = BH_COMMAND_WRITE;
+ bh.type = type;
+ bh.address_space = ADDR_GTT;
+ bh.pad0 = 0;
+ bh.general_state_type = 0;
+ bh.surface_state_type = 0;
+ bh.pad1 = 0;
+ bh.address = offset;
+ bh.length = sz;
+
+ write_block_header(aubfile->file, &bh, data, sz);
+}
+
+void brw_aub_dump_bmp( struct brw_aubfile *aubfile,
+ struct pipe_surface *surface,
+ unsigned gtt_offset )
+{
+ struct aub_dump_bmp db;
+ unsigned format;
+
+ assert(surface->texture->block.width == 1);
+ assert(surface->texture->block.height == 1);
+
+ if (surface->texture->block.size == 4)
+ format = 0x7;
+ else
+ format = 0x3;
+
+ db.instruction_type = AUB_DUMP_BMP;
+ db.xmin = 0;
+ db.ymin = 0;
+ db.format = format;
+ db.bpp = surface->texture->block.size * 8;
+ db.pitch = softpipe_texture(surface->texture)->stride[surface->level] /
+ surface->texture->block.size;
+ db.xsize = surface->width;
+ db.ysize = surface->height;
+ db.addr = gtt_offset;
+ db.unknown = /* surface->tiled ? 0x4 : */ 0x0;
+
+ write_dump_bmp(aubfile->file, &db);
+}
+
+
+
+struct brw_aubfile *brw_aubfile_create( void )
+{
+ struct brw_aubfile *aubfile = CALLOC_STRUCT(brw_aubfile);
+ char filename[80];
+ int val;
+ static int i = 0;
+
+ i++;
+
+ if (getenv("INTEL_AUBFILE")) {
+ val = snprintf(filename, sizeof(filename), "%s%d.aub", getenv("INTEL_AUBFILE"), i%4);
+ debug_printf("--> Aub file: %s\n", filename);
+ aubfile->file = fopen(filename, "w");
+ }
+ else {
+ val = snprintf(filename, sizeof(filename), "%s.aub", __progname);
+ if (val < 0 || val > sizeof(filename))
+ strcpy(filename, "default.aub");
+
+ debug_printf("--> Aub file: %s\n", filename);
+ aubfile->file = fopen(filename, "w");
+ }
+
+ if (!aubfile->file) {
+ debug_printf("couldn't open aubfile\n");
+ exit(1);
+ }
+
+ init_aubfile(aubfile->file);
+
+ /* The GTT is located starting address zero in main memory. Pages
+ * to populate the gtt start after this point.
+ */
+ aubfile->next_free_page = (NR_GTT_ENTRIES * 4 + 4095) & ~4095;
+
+ /* More or less correspond with all the agp regions mapped by the
+ * driver:
+ */
+ init_aub_gtt(aubfile, 0, 4096*4);
+ init_aub_gtt(aubfile, AUB_BUF_START, AUB_BUF_SIZE);
+
+ return aubfile;
+}
+
+void brw_aub_destroy( struct brw_aubfile *aubfile )
+{
+ fclose(aubfile->file);
+ FREE(aubfile);
+}
diff --git a/src/gallium/winsys/xlib/xlib_brw_aub.h b/src/gallium/winsys/xlib/xlib_brw_aub.h
new file mode 100644
index 0000000000..f5c60c7be2
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib_brw_aub.h
@@ -0,0 +1,114 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef BRW_AUB_H
+#define BRW_AUB_H
+
+/* We set up this region, buffers may be allocated here:
+ */
+#define AUB_BUF_START (4096*4)
+#define AUB_BUF_SIZE (8*1024*1024)
+
+struct intel_context;
+struct pipe_surface;
+
+struct brw_aubfile *brw_aubfile_create( void );
+
+void brw_aub_destroy( struct brw_aubfile *aubfile );
+
+void brw_aub_gtt_data( struct brw_aubfile *aubfile,
+ unsigned offset,
+ const void *data,
+ unsigned sz,
+ unsigned type,
+ unsigned state_type );
+
+void brw_aub_gtt_cmds( struct brw_aubfile *aubfile,
+ unsigned offset,
+ const void *data,
+ unsigned sz );
+
+void brw_aub_dump_bmp( struct brw_aubfile *aubfile,
+ struct pipe_surface *surface,
+ unsigned gtt_offset );
+
+
+enum data_write_type {
+ DW_NOTYPE,
+ DW_BATCH_BUFFER,
+ DW_BIN_BUFFER,
+ DW_BIN_POINTER_LIST,
+ DW_SLOW_STATE_BUFFER,
+ DW_VERTEX_BUFFER,
+ DW_2D_MAP,
+ DW_CUBE_MAP,
+ DW_INDIRECT_STATE_BUFFER,
+ DW_VOLUME_MAP,
+ DW_1D_MAP,
+ DW_CONSTANT_BUFFER,
+ DW_CONSTANT_URB_ENTRY,
+ DW_INDEX_BUFFER,
+ DW_GENERAL_STATE,
+ DW_SURFACE_STATE,
+ DW_MEDIA_OBJECT_INDIRECT_DATA,
+ DW_MAX_TYPE
+};
+
+enum data_write_general_state_type {
+ DWGS_NOTYPE,
+ DWGS_VERTEX_SHADER_STATE,
+ DWGS_GEOMETRY_SHADER_STATE ,
+ DWGS_CLIPPER_STATE,
+ DWGS_STRIPS_FANS_STATE,
+ DWGS_WINDOWER_IZ_STATE,
+ DWGS_COLOR_CALC_STATE,
+ DWGS_CLIPPER_VIEWPORT_STATE, /* was 0x7 */
+ DWGS_STRIPS_FANS_VIEWPORT_STATE,
+ DWGS_COLOR_CALC_VIEWPORT_STATE, /* was 0x9 */
+ DWGS_SAMPLER_STATE,
+ DWGS_KERNEL_INSTRUCTIONS,
+ DWGS_SCRATCH_SPACE,
+ DWGS_SAMPLER_DEFAULT_COLOR,
+ DWGS_INTERFACE_DESCRIPTOR,
+ DWGS_VLD_STATE,
+ DWGS_VFE_STATE,
+ DWGS_MAX_TYPE
+};
+
+enum data_write_surface_state_type {
+ DWSS_NOTYPE,
+ DWSS_BINDING_TABLE_STATE,
+ DWSS_SURFACE_STATE,
+ DWSS_MAX_TYPE
+};
+
+
+#endif
diff --git a/src/gallium/winsys/xlib/xlib_brw_context.c b/src/gallium/winsys/xlib/xlib_brw_context.c
new file mode 100644
index 0000000000..09599507f4
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib_brw_context.c
@@ -0,0 +1,209 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell
+ * Brian Paul
+ */
+
+
+//#include "glxheader.h"
+//#include "xmesaP.h"
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "i965simple/brw_winsys.h"
+#include "xlib_brw_aub.h"
+#include "xlib_brw.h"
+
+
+
+
+#define XBCWS_BATCHBUFFER_SIZE 1024
+
+
+/* The backend to the brw driver (ie struct brw_winsys) is actually a
+ * per-context entity.
+ */
+struct xlib_brw_context_winsys {
+ struct brw_winsys brw_context_winsys; /**< batch buffer funcs */
+ struct aub_context *aub;
+
+ struct pipe_winsys *pipe_winsys;
+
+ unsigned batch_data[XBCWS_BATCHBUFFER_SIZE];
+ unsigned batch_nr;
+ unsigned batch_size;
+ unsigned batch_alloc;
+};
+
+
+/* Turn a brw_winsys into an xlib_brw_context_winsys:
+ */
+static inline struct xlib_brw_context_winsys *
+xlib_brw_context_winsys( struct brw_winsys *sws )
+{
+ return (struct xlib_brw_context_winsys *)sws;
+}
+
+
+/* Simple batchbuffer interface:
+ */
+
+static unsigned *xbcws_batch_start( struct brw_winsys *sws,
+ unsigned dwords,
+ unsigned relocs )
+{
+ struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws);
+
+ if (xbcws->batch_size < xbcws->batch_nr + dwords)
+ return NULL;
+
+ xbcws->batch_alloc = xbcws->batch_nr + dwords;
+ return (void *)1; /* not a valid pointer! */
+}
+
+static void xbcws_batch_dword( struct brw_winsys *sws,
+ unsigned dword )
+{
+ struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws);
+
+ assert(xbcws->batch_nr < xbcws->batch_alloc);
+ xbcws->batch_data[xbcws->batch_nr++] = dword;
+}
+
+static void xbcws_batch_reloc( struct brw_winsys *sws,
+ struct pipe_buffer *buf,
+ unsigned access_flags,
+ unsigned delta )
+{
+ struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws);
+
+ assert(xbcws->batch_nr < xbcws->batch_alloc);
+ xbcws->batch_data[xbcws->batch_nr++] =
+ ( xlib_brw_get_buffer_offset( NULL, buf, access_flags ) +
+ delta );
+}
+
+static void xbcws_batch_end( struct brw_winsys *sws )
+{
+ struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws);
+
+ assert(xbcws->batch_nr <= xbcws->batch_alloc);
+ xbcws->batch_alloc = 0;
+}
+
+static void xbcws_batch_flush( struct brw_winsys *sws,
+ struct pipe_fence_handle **fence )
+{
+ struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws);
+ assert(xbcws->batch_nr <= xbcws->batch_size);
+
+ if (xbcws->batch_nr) {
+ xlib_brw_commands_aub( xbcws->pipe_winsys,
+ xbcws->batch_data,
+ xbcws->batch_nr );
+ }
+
+ xbcws->batch_nr = 0;
+}
+
+
+
+/* Really a per-device function, just pass through:
+ */
+static unsigned xbcws_get_buffer_offset( struct brw_winsys *sws,
+ struct pipe_buffer *buf,
+ unsigned access_flags )
+{
+ struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws);
+
+ return xlib_brw_get_buffer_offset( xbcws->pipe_winsys,
+ buf,
+ access_flags );
+}
+
+
+/* Really a per-device function, just pass through:
+ */
+static void xbcws_buffer_subdata_typed( struct brw_winsys *sws,
+ struct pipe_buffer *buf,
+ unsigned long offset,
+ unsigned long size,
+ const void *data,
+ unsigned data_type )
+{
+ struct xlib_brw_context_winsys *xbcws = xlib_brw_context_winsys(sws);
+
+ xlib_brw_buffer_subdata_typed( xbcws->pipe_winsys,
+ buf,
+ offset,
+ size,
+ data,
+ data_type );
+}
+
+
+/**
+ * Create i965 hardware rendering context, but plugged into a
+ * dump-to-aubfile backend.
+ */
+struct pipe_context *
+xlib_create_brw_context( struct pipe_screen *screen,
+ void *unused )
+{
+ struct xlib_brw_context_winsys *xbcws = CALLOC_STRUCT( xlib_brw_context_winsys );
+
+ /* Fill in this struct with callbacks that i965simple will need to
+ * communicate with the window system, buffer manager, etc.
+ */
+ xbcws->brw_context_winsys.batch_start = xbcws_batch_start;
+ xbcws->brw_context_winsys.batch_dword = xbcws_batch_dword;
+ xbcws->brw_context_winsys.batch_reloc = xbcws_batch_reloc;
+ xbcws->brw_context_winsys.batch_end = xbcws_batch_end;
+ xbcws->brw_context_winsys.batch_flush = xbcws_batch_flush;
+ xbcws->brw_context_winsys.buffer_subdata_typed = xbcws_buffer_subdata_typed;
+ xbcws->brw_context_winsys.get_buffer_offset = xbcws_get_buffer_offset;
+
+ xbcws->pipe_winsys = screen->winsys; /* redundant */
+
+ xbcws->batch_size = XBCWS_BATCHBUFFER_SIZE;
+
+ /* Create the i965simple context:
+ */
+#ifdef GALLIUM_CELL
+ return NULL;
+#else
+ return brw_create( screen,
+ &xbcws->brw_context_winsys,
+ 0 );
+#endif
+}
diff --git a/src/gallium/winsys/xlib/xlib_brw_screen.c b/src/gallium/winsys/xlib/xlib_brw_screen.c
new file mode 100644
index 0000000000..ef545796f3
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib_brw_screen.c
@@ -0,0 +1,469 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell
+ * Brian Paul
+ */
+
+
+//#include "state_trackers/xlib/glxheader.h"
+//#include "state_trackers/xlib/xmesaP.h"
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "i965simple/brw_winsys.h"
+#include "i965simple/brw_screen.h"
+#include "i965simple/brw_context.h"
+
+
+#include "xlib_brw_aub.h"
+#include "xlib_brw.h"
+#include "xlib.h"
+
+static struct pipe_buffer *
+buffer_from_surface(struct pipe_surface *surface)
+{
+ struct brw_texture *texture = (struct brw_texture *)surface;
+ return texture->buffer;
+}
+
+struct aub_buffer {
+ struct pipe_reference reference;
+ char *data;
+ unsigned offset;
+ unsigned size;
+ unsigned map_count;
+ boolean dump_on_unmap;
+};
+
+
+
+struct aub_pipe_winsys {
+ struct pipe_winsys winsys;
+
+ struct brw_aubfile *aubfile;
+
+ /* This is simple, isn't it:
+ */
+ char *pool;
+ unsigned size;
+ unsigned used;
+};
+
+
+/* Turn a pipe winsys into an aub/pipe winsys:
+ */
+static inline struct aub_pipe_winsys *
+aub_pipe_winsys( struct pipe_winsys *winsys )
+{
+ return (struct aub_pipe_winsys *)winsys;
+}
+
+
+
+static INLINE struct aub_buffer *
+aub_bo( struct pipe_buffer *bo )
+{
+ return (struct aub_buffer *)bo;
+}
+
+static INLINE struct pipe_buffer *
+pipe_bo( struct aub_buffer *bo )
+{
+ return (struct pipe_buffer *)bo;
+}
+
+
+
+
+static void *aub_buffer_map(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf,
+ unsigned flags )
+{
+ struct aub_buffer *sbo = aub_bo(buf);
+
+ assert(sbo->data);
+
+ if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
+ sbo->dump_on_unmap = 1;
+
+ sbo->map_count++;
+ return sbo->data;
+}
+
+static void aub_buffer_unmap(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf)
+{
+ struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
+ struct aub_buffer *sbo = aub_bo(buf);
+
+ sbo->map_count--;
+
+ if (sbo->map_count == 0 &&
+ sbo->dump_on_unmap) {
+
+ sbo->dump_on_unmap = 0;
+
+ brw_aub_gtt_data( iws->aubfile,
+ sbo->offset,
+ sbo->data,
+ sbo->size,
+ 0,
+ 0);
+ }
+}
+
+
+static void
+aub_buffer_destroy(struct pipe_buffer *buf)
+{
+ free(buf);
+}
+
+
+
+void xlib_brw_commands_aub(struct pipe_winsys *winsys,
+ unsigned *cmds,
+ unsigned nr_dwords)
+{
+ struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
+ unsigned size = nr_dwords * 4;
+
+ assert(iws->used + size < iws->size);
+
+ brw_aub_gtt_cmds( iws->aubfile,
+ AUB_BUF_START + iws->used,
+ cmds,
+ nr_dwords * sizeof(int) );
+
+ iws->used += align(size, 4096);
+}
+
+
+/* XXX: fix me:
+ */
+static struct aub_pipe_winsys *global_winsys = NULL;
+
+
+
+
+/* Pipe has no concept of pools. We choose the tex/region pool
+ * for all buffers.
+ */
+static struct pipe_buffer *
+aub_buffer_create(struct pipe_winsys *winsys,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
+ struct aub_buffer *sbo = CALLOC_STRUCT(aub_buffer);
+
+ pipe_reference_init(&sbo->reference, 1);
+
+ /* Could reuse buffers that are not referenced in current
+ * batchbuffer. Can't do that atm, so always reallocate:
+ */
+ assert(iws->used + size < iws->size);
+ sbo->data = iws->pool + iws->used;
+ sbo->offset = AUB_BUF_START + iws->used;
+ iws->used += align(size, 4096);
+
+ sbo->size = size;
+
+ return pipe_bo(sbo);
+}
+
+
+static struct pipe_buffer *
+aub_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes)
+{
+ struct aub_buffer *sbo;
+
+ /* Lets hope this is meant for upload, not as a result!
+ */
+ sbo = aub_bo(aub_buffer_create( winsys, 0, 0, 0 ));
+
+ sbo->data = ptr;
+ sbo->size = bytes;
+
+ return pipe_bo(sbo);
+}
+
+
+/* The state tracker (should!) keep track of whether the fake
+ * frontbuffer has been touched by any rendering since the last time
+ * we copied its contents to the real frontbuffer. Our task is easy:
+ */
+static void
+aub_flush_frontbuffer( struct pipe_winsys *winsys,
+ struct pipe_surface *surface,
+ void *context_private)
+{
+// struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
+ brw_aub_dump_bmp( global_winsys->aubfile,
+ surface,
+ aub_bo(buffer_from_surface(surface))->offset );
+}
+
+
+/**
+ * Round n up to next multiple.
+ */
+static INLINE unsigned
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+static struct pipe_buffer *
+aub_i915_surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ const unsigned alignment = 64;
+ struct pipe_format_block block;
+ unsigned nblocksx, nblocksy;
+
+ pf_get_block(format, &block);
+ nblocksx = pf_get_nblocksx(&block, width);
+ nblocksy = pf_get_nblocksy(&block, height);
+ *stride = round_up(nblocksx * block.size, alignment);
+
+ return winsys->buffer_create(winsys, alignment,
+ usage,
+ *stride * nblocksy);
+}
+
+
+static const char *
+aub_get_name( struct pipe_winsys *winsys )
+{
+ return "Aub/xlib";
+}
+
+static void
+xlib_brw_destroy_pipe_winsys_aub( struct pipe_winsys *winsys )
+
+{
+ struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
+ brw_aub_destroy(iws->aubfile);
+ free(iws->pool);
+ free(iws);
+}
+
+
+
+static struct pipe_winsys *
+xlib_create_brw_winsys( void )
+{
+ struct aub_pipe_winsys *iws = CALLOC_STRUCT( aub_pipe_winsys );
+
+ /* Fill in this struct with callbacks that pipe will need to
+ * communicate with the window system, buffer manager, etc.
+ *
+ * Pipe would be happy with a malloc based memory manager, but
+ * the SwapBuffers implementation in this winsys driver requires
+ * that rendering be done to an appropriate _DriBufferObject.
+ */
+ iws->winsys.buffer_create = aub_buffer_create;
+ iws->winsys.user_buffer_create = aub_user_buffer_create;
+ iws->winsys.buffer_map = aub_buffer_map;
+ iws->winsys.buffer_unmap = aub_buffer_unmap;
+ iws->winsys.buffer_destroy = aub_buffer_destroy;
+ iws->winsys.flush_frontbuffer = aub_flush_frontbuffer;
+ iws->winsys.get_name = aub_get_name;
+ iws->winsys.destroy = xlib_brw_destroy_pipe_winsys_aub;
+
+ iws->winsys.surface_buffer_create = aub_i915_surface_buffer_create;
+
+ iws->aubfile = brw_aubfile_create();
+ iws->size = AUB_BUF_SIZE;
+ iws->pool = malloc(AUB_BUF_SIZE);
+
+ /* HACK: static copy of this pointer:
+ */
+ assert(global_winsys == NULL);
+ global_winsys = iws;
+
+ return &iws->winsys;
+}
+
+
+static struct pipe_screen *
+xlib_create_brw_screen( void )
+{
+#ifndef GALLIUM_CELL
+ struct pipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ winsys = xlib_create_brw_winsys();
+ if (winsys == NULL)
+ return NULL;
+
+ screen = brw_create_screen(winsys, 0/* XXX pci_id */);
+ if (screen == NULL)
+ goto fail;
+
+ return screen;
+
+fail:
+ if (winsys)
+ winsys->destroy( winsys );
+
+#endif
+ return NULL;
+}
+
+
+/* These per-screen functions are acually made available to the driver
+ * through the brw_winsys (per-context) entity.
+ */
+unsigned xlib_brw_get_buffer_offset( struct pipe_winsys *pws,
+ struct pipe_buffer *buf,
+ unsigned access_flags )
+{
+ return aub_bo(buf)->offset;
+}
+
+void xlib_brw_buffer_subdata_typed( struct pipe_winsys *pws,
+ struct pipe_buffer *buf,
+ unsigned long offset,
+ unsigned long size,
+ const void *data,
+ unsigned data_type )
+{
+ unsigned aub_type = DW_GENERAL_STATE;
+ unsigned aub_sub_type = 0;
+
+ switch (data_type) {
+ case BRW_CC_VP:
+ aub_sub_type = DWGS_COLOR_CALC_VIEWPORT_STATE;
+ break;
+ case BRW_CC_UNIT:
+ aub_sub_type = DWGS_COLOR_CALC_STATE;
+ break;
+ case BRW_WM_PROG:
+ aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
+ break;
+ case BRW_SAMPLER_DEFAULT_COLOR:
+ aub_sub_type = DWGS_SAMPLER_DEFAULT_COLOR;
+ break;
+ case BRW_SAMPLER:
+ aub_sub_type = DWGS_SAMPLER_STATE;
+ break;
+ case BRW_WM_UNIT:
+ aub_sub_type = DWGS_WINDOWER_IZ_STATE;
+ break;
+ case BRW_SF_PROG:
+ aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
+ break;
+ case BRW_SF_VP:
+ aub_sub_type = DWGS_STRIPS_FANS_VIEWPORT_STATE;
+ break;
+ case BRW_SF_UNIT:
+ aub_sub_type = DWGS_STRIPS_FANS_STATE;
+ break;
+ case BRW_VS_UNIT:
+ aub_sub_type = DWGS_VERTEX_SHADER_STATE;
+ break;
+ case BRW_VS_PROG:
+ aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
+ break;
+ case BRW_GS_UNIT:
+ aub_sub_type = DWGS_GEOMETRY_SHADER_STATE;
+ break;
+ case BRW_GS_PROG:
+ aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
+ break;
+ case BRW_CLIP_VP:
+ aub_sub_type = DWGS_CLIPPER_VIEWPORT_STATE;
+ break;
+ case BRW_CLIP_UNIT:
+ aub_sub_type = DWGS_CLIPPER_STATE;
+ break;
+ case BRW_CLIP_PROG:
+ aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
+ break;
+ case BRW_SS_SURFACE:
+ aub_type = DW_SURFACE_STATE;
+ aub_sub_type = DWSS_SURFACE_STATE;
+ break;
+ case BRW_SS_SURF_BIND:
+ aub_type = DW_SURFACE_STATE;
+ aub_sub_type = DWSS_BINDING_TABLE_STATE;
+ break;
+ case BRW_CONSTANT_BUFFER:
+ aub_type = DW_CONSTANT_URB_ENTRY;
+ aub_sub_type = 0;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ {
+ struct aub_pipe_winsys *iws = aub_pipe_winsys(pws);
+ struct aub_buffer *sbo = aub_bo(buf);
+
+ assert(sbo->size > offset + size);
+ memcpy(sbo->data + offset, data, size);
+
+ brw_aub_gtt_data( iws->aubfile,
+ sbo->offset + offset,
+ sbo->data + offset,
+ size,
+ aub_type,
+ aub_sub_type );
+ }
+}
+
+
+static void
+xlib_brw_display_surface(struct xmesa_buffer *b,
+ struct pipe_surface *surf)
+{
+ brw_aub_dump_bmp( global_winsys->aubfile,
+ surf,
+ aub_bo(buffer_from_surface(surf))->offset );
+}
+
+
+struct xm_driver xlib_brw_driver =
+{
+ .create_pipe_screen = xlib_create_brw_screen,
+ .create_pipe_context = xlib_create_brw_context,
+ .display_surface = xlib_brw_display_surface,
+};
diff --git a/src/gallium/winsys/xlib/xlib_cell.c b/src/gallium/winsys/xlib/xlib_cell.c
new file mode 100644
index 0000000000..13e609f58f
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib_cell.c
@@ -0,0 +1,437 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell
+ * Brian Paul
+ */
+
+#include "xlib.h"
+
+#ifdef GALLIUM_CELL
+
+#include "xm_api.h"
+
+#undef ASSERT
+#undef Elements
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "cell/ppu/cell_context.h"
+#include "cell/ppu/cell_screen.h"
+#include "cell/ppu/cell_winsys.h"
+#include "cell/ppu/cell_texture.h"
+
+
+/**
+ * Subclass of pipe_buffer for Xlib winsys.
+ * Low-level OS/window system memory buffer
+ */
+struct xm_buffer
+{
+ struct pipe_buffer base;
+ boolean userBuffer; /** Is this a user-space buffer? */
+ void *data;
+ void *mapped;
+
+ XImage *tempImage;
+ int shm;
+};
+
+
+/**
+ * Subclass of pipe_winsys for Xlib winsys
+ */
+struct xmesa_pipe_winsys
+{
+ struct pipe_winsys base;
+};
+
+
+
+/** Cast wrapper */
+static INLINE struct xm_buffer *
+xm_buffer( struct pipe_buffer *buf )
+{
+ return (struct xm_buffer *)buf;
+}
+
+
+/* Most callbacks map direcly onto dri_bufmgr operations:
+ */
+static void *
+xm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
+ unsigned flags)
+{
+ struct xm_buffer *xm_buf = xm_buffer(buf);
+ xm_buf->mapped = xm_buf->data;
+ return xm_buf->mapped;
+}
+
+static void
+xm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+ struct xm_buffer *xm_buf = xm_buffer(buf);
+ xm_buf->mapped = NULL;
+}
+
+static void
+xm_buffer_destroy(/*struct pipe_winsys *pws,*/
+ struct pipe_buffer *buf)
+{
+ struct xm_buffer *oldBuf = xm_buffer(buf);
+
+ if (oldBuf) {
+ if (oldBuf->data) {
+ if (!oldBuf->userBuffer) {
+ align_free(oldBuf->data);
+ }
+
+ oldBuf->data = NULL;
+ }
+ free(oldBuf);
+ }
+}
+
+
+/**
+ * For Cell. Basically, rearrange the pixels/quads from this layout:
+ * +--+--+--+--+
+ * |p0|p1|p2|p3|....
+ * +--+--+--+--+
+ *
+ * to this layout:
+ * +--+--+
+ * |p0|p1|....
+ * +--+--+
+ * |p2|p3|
+ * +--+--+
+ */
+static void
+twiddle_tile(const uint *tileIn, uint *tileOut)
+{
+ int y, x;
+
+ for (y = 0; y < TILE_SIZE; y+=2) {
+ for (x = 0; x < TILE_SIZE; x+=2) {
+ int k = 4 * (y/2 * TILE_SIZE/2 + x/2);
+ tileOut[y * TILE_SIZE + (x + 0)] = tileIn[k];
+ tileOut[y * TILE_SIZE + (x + 1)] = tileIn[k+1];
+ tileOut[(y + 1) * TILE_SIZE + (x + 0)] = tileIn[k+2];
+ tileOut[(y + 1) * TILE_SIZE + (x + 1)] = tileIn[k+3];
+ }
+ }
+}
+
+
+
+/**
+ * Display a surface that's in a tiled configuration. That is, all the
+ * pixels for a TILE_SIZExTILE_SIZE block are contiguous in memory.
+ */
+static void
+xlib_cell_display_surface(struct xmesa_buffer *b, struct pipe_surface *surf)
+{
+ XImage *ximage;
+ struct xm_buffer *xm_buf = xm_buffer(
+ cell_texture(surf->texture)->buffer);
+ const uint tilesPerRow = (surf->width + TILE_SIZE - 1) / TILE_SIZE;
+ uint x, y;
+
+ ximage = b->tempImage;
+
+ /* check that the XImage has been previously initialized */
+ assert(ximage->format);
+ assert(ximage->bitmap_unit);
+
+ /* update XImage's fields */
+ ximage->width = TILE_SIZE;
+ ximage->height = TILE_SIZE;
+ ximage->bytes_per_line = TILE_SIZE * 4;
+
+ for (y = 0; y < surf->height; y += TILE_SIZE) {
+ for (x = 0; x < surf->width; x += TILE_SIZE) {
+ uint tmpTile[TILE_SIZE * TILE_SIZE];
+ int tx = x / TILE_SIZE;
+ int ty = y / TILE_SIZE;
+ int offset = ty * tilesPerRow + tx;
+ int w = TILE_SIZE;
+ int h = TILE_SIZE;
+
+ if (y + h > surf->height)
+ h = surf->height - y;
+ if (x + w > surf->width)
+ w = surf->width - x;
+
+ /* offset in pixels */
+ offset *= TILE_SIZE * TILE_SIZE;
+
+ /* twiddle from ximage buffer to temp tile */
+ twiddle_tile((uint *) xm_buf->data + offset, tmpTile);
+ /* display temp tile data */
+ ximage->data = (char *) tmpTile;
+ XPutImage(b->xm_visual->display, b->drawable, b->gc,
+ ximage, 0, 0, x, y, w, h);
+ }
+ }
+}
+
+
+
+
+
+static void
+xm_flush_frontbuffer(struct pipe_winsys *pws,
+ struct pipe_surface *surf,
+ void *context_private)
+{
+ /*
+ * The front color buffer is actually just another XImage buffer.
+ * This function copies that XImage to the actual X Window.
+ */
+ XMesaContext xmctx = (XMesaContext) context_private;
+ if (xmctx)
+ xlib_cell_display_surface(xmctx->xm_buffer, surf);
+}
+
+
+
+static const char *
+xm_get_name(struct pipe_winsys *pws)
+{
+ return "Xlib/Cell";
+}
+
+
+static struct pipe_buffer *
+xm_buffer_create(struct pipe_winsys *pws,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.alignment = alignment;
+ buffer->base.usage = usage;
+ buffer->base.size = size;
+
+
+ if (buffer->data == NULL) {
+ buffer->shm = 0;
+
+ /* align to 16-byte multiple for Cell */
+ buffer->data = align_malloc(size, max(alignment, 16));
+ }
+
+ return &buffer->base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
+{
+ struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.size = bytes;
+ buffer->userBuffer = TRUE;
+ buffer->data = ptr;
+ buffer->shm = 0;
+
+ return &buffer->base;
+}
+
+
+
+/**
+ * Round n up to next multiple.
+ */
+static INLINE unsigned
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+static struct pipe_buffer *
+xm_surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned *stride)
+{
+ const unsigned alignment = 64;
+ struct pipe_format_block block;
+ unsigned nblocksx, nblocksy;
+
+ pf_get_block(format, &block);
+ nblocksx = pf_get_nblocksx(&block, width);
+ nblocksy = pf_get_nblocksy(&block, height);
+ *stride = round_up(nblocksx * block.size, alignment);
+
+ return winsys->buffer_create(winsys, alignment,
+ usage,
+ /* XXX a bit of a hack */
+ *stride * round_up(nblocksy, TILE_SIZE));
+}
+
+
+/*
+ * Fence functions - basically nothing to do, as we don't create any actual
+ * fence objects.
+ */
+
+static void
+xm_fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+}
+
+
+static int
+xm_fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+static int
+xm_fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+
+static struct pipe_winsys *
+xlib_create_cell_winsys( void )
+{
+ static struct xmesa_pipe_winsys *ws = NULL;
+
+ if (!ws) {
+ ws = CALLOC_STRUCT(xmesa_pipe_winsys);
+
+ /* Fill in this struct with callbacks that pipe will need to
+ * communicate with the window system, buffer manager, etc.
+ */
+ ws->base.buffer_create = xm_buffer_create;
+ ws->base.user_buffer_create = xm_user_buffer_create;
+ ws->base.buffer_map = xm_buffer_map;
+ ws->base.buffer_unmap = xm_buffer_unmap;
+ ws->base.buffer_destroy = xm_buffer_destroy;
+
+ ws->base.surface_buffer_create = xm_surface_buffer_create;
+
+ ws->base.fence_reference = xm_fence_reference;
+ ws->base.fence_signalled = xm_fence_signalled;
+ ws->base.fence_finish = xm_fence_finish;
+
+ ws->base.flush_frontbuffer = xm_flush_frontbuffer;
+ ws->base.get_name = xm_get_name;
+ }
+
+ return &ws->base;
+}
+
+
+static struct pipe_screen *
+xlib_create_cell_screen( void )
+{
+ struct pipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ winsys = xlib_create_cell_winsys();
+ if (winsys == NULL)
+ return NULL;
+
+ screen = cell_create_screen(winsys);
+ if (screen == NULL)
+ goto fail;
+
+ return screen;
+
+fail:
+ if (winsys)
+ winsys->destroy( winsys );
+
+ return NULL;
+}
+
+
+static struct pipe_context *
+xlib_create_cell_context( struct pipe_screen *screen,
+ void *priv )
+{
+ struct pipe_context *pipe;
+
+
+ /* This takes a cell_winsys pointer, but probably that should be
+ * created and stored at screen creation, not context creation.
+ *
+ * The actual cell_winsys value isn't used for anything, so just
+ * passing NULL for now.
+ */
+ pipe = cell_create_context( screen, NULL);
+ if (pipe == NULL)
+ goto fail;
+
+ pipe->priv = priv;
+
+ return pipe;
+
+fail:
+ return NULL;
+}
+
+struct xm_driver xlib_cell_driver =
+{
+ .create_pipe_screen = xlib_create_cell_screen,
+ .create_pipe_context = xlib_create_cell_context,
+ .display_surface = xlib_cell_display_surface,
+};
+
+#else
+
+struct xm_driver xlib_cell_driver =
+{
+ .create_pipe_screen = NULL,
+ .create_pipe_context = NULL,
+ .display_surface = NULL,
+};
+
+#endif
diff --git a/src/gallium/winsys/xlib/xlib_llvmpipe.c b/src/gallium/winsys/xlib/xlib_llvmpipe.c
new file mode 100644
index 0000000000..bc876591c0
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib_llvmpipe.c
@@ -0,0 +1,461 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell
+ * Brian Paul
+ */
+
+
+#include "xm_api.h"
+
+#undef ASSERT
+#undef Elements
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "llvmpipe/lp_winsys.h"
+#include "llvmpipe/lp_texture.h"
+
+#include "xlib.h"
+
+/**
+ * Subclass of pipe_buffer for Xlib winsys.
+ * Low-level OS/window system memory buffer
+ */
+struct xm_displaytarget
+{
+ enum pipe_format format;
+ struct pipe_format_block block;
+ unsigned width;
+ unsigned height;
+ unsigned stride;
+
+ void *data;
+ void *mapped;
+
+ XImage *tempImage;
+#ifdef USE_XSHM
+ int shm;
+ XShmSegmentInfo shminfo;
+#endif
+};
+
+
+/**
+ * Subclass of llvmpipe_winsys for Xlib winsys
+ */
+struct xmesa_llvmpipe_winsys
+{
+ struct llvmpipe_winsys base;
+/* struct xmesa_visual *xm_visual; */
+};
+
+
+
+/** Cast wrapper */
+static INLINE struct xm_displaytarget *
+xm_displaytarget( struct llvmpipe_displaytarget *dt )
+{
+ return (struct xm_displaytarget *)dt;
+}
+
+
+/**
+ * X Shared Memory Image extension code
+ */
+
+#ifdef USE_XSHM
+
+static volatile int mesaXErrorFlag = 0;
+
+/**
+ * Catches potential Xlib errors.
+ */
+static int
+mesaHandleXError(Display *dpy, XErrorEvent *event)
+{
+ (void) dpy;
+ (void) event;
+ mesaXErrorFlag = 1;
+ return 0;
+}
+
+
+static char *alloc_shm(struct xm_displaytarget *buf, unsigned size)
+{
+ XShmSegmentInfo *const shminfo = & buf->shminfo;
+
+ shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
+ if (shminfo->shmid < 0) {
+ return NULL;
+ }
+
+ shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
+ if (shminfo->shmaddr == (char *) -1) {
+ shmctl(shminfo->shmid, IPC_RMID, 0);
+ return NULL;
+ }
+
+ shminfo->readOnly = False;
+ return shminfo->shmaddr;
+}
+
+
+/**
+ * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
+ */
+static void
+alloc_shm_ximage(struct xm_displaytarget *xm_buffer,
+ struct xmesa_buffer *xmb,
+ unsigned width, unsigned height)
+{
+ /*
+ * We have to do a _lot_ of error checking here to be sure we can
+ * really use the XSHM extension. It seems different servers trigger
+ * errors at different points if the extension won't work. Therefore
+ * we have to be very careful...
+ */
+ int (*old_handler)(Display *, XErrorEvent *);
+
+ xm_buffer->tempImage = XShmCreateImage(xmb->xm_visual->display,
+ xmb->xm_visual->visinfo->visual,
+ xmb->xm_visual->visinfo->depth,
+ ZPixmap,
+ NULL,
+ &xm_buffer->shminfo,
+ width, height);
+ if (xm_buffer->tempImage == NULL) {
+ xm_buffer->shm = 0;
+ return;
+ }
+
+
+ mesaXErrorFlag = 0;
+ old_handler = XSetErrorHandler(mesaHandleXError);
+ /* This may trigger the X protocol error we're ready to catch: */
+ XShmAttach(xmb->xm_visual->display, &xm_buffer->shminfo);
+ XSync(xmb->xm_visual->display, False);
+
+ if (mesaXErrorFlag) {
+ /* we are on a remote display, this error is normal, don't print it */
+ XFlush(xmb->xm_visual->display);
+ mesaXErrorFlag = 0;
+ XDestroyImage(xm_buffer->tempImage);
+ xm_buffer->tempImage = NULL;
+ xm_buffer->shm = 0;
+ (void) XSetErrorHandler(old_handler);
+ return;
+ }
+
+ xm_buffer->shm = 1;
+}
+
+#endif /* USE_XSHM */
+
+static boolean
+xm_is_displaytarget_format_supported( struct llvmpipe_winsys *ws,
+ enum pipe_format format )
+{
+ /* TODO: check visuals or other sensible thing here */
+ return TRUE;
+}
+
+
+static void *
+xm_displaytarget_map(struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt,
+ unsigned flags)
+{
+ struct xm_displaytarget *xm_dt = xm_displaytarget(dt);
+ xm_dt->mapped = xm_dt->data;
+ return xm_dt->mapped;
+}
+
+static void
+xm_displaytarget_unmap(struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt)
+{
+ struct xm_displaytarget *xm_dt = xm_displaytarget(dt);
+ xm_dt->mapped = NULL;
+}
+
+static void
+xm_displaytarget_destroy(struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt)
+{
+ struct xm_displaytarget *xm_dt = xm_displaytarget(dt);
+
+ if (xm_dt->data) {
+#ifdef USE_XSHM
+ if (xm_dt->shminfo.shmid >= 0) {
+ shmdt(xm_dt->shminfo.shmaddr);
+ shmctl(xm_dt->shminfo.shmid, IPC_RMID, 0);
+
+ xm_dt->shminfo.shmid = -1;
+ xm_dt->shminfo.shmaddr = (char *) -1;
+ }
+ else
+#endif
+ FREE(xm_dt->data);
+ }
+
+ FREE(xm_dt);
+}
+
+
+/**
+ * Display/copy the image in the surface into the X window specified
+ * by the XMesaBuffer.
+ */
+static void
+xm_llvmpipe_display(struct xmesa_buffer *xm_buffer,
+ struct llvmpipe_displaytarget *dt)
+{
+ XImage *ximage;
+ struct xm_displaytarget *xm_dt = xm_displaytarget(dt);
+ static boolean no_swap = 0;
+ static boolean firsttime = 1;
+
+ if (firsttime) {
+ no_swap = getenv("SP_NO_RAST") != NULL;
+ firsttime = 0;
+ }
+
+ if (no_swap)
+ return;
+
+#ifdef USE_XSHM
+ if (xm_dt->shm)
+ {
+ if (xm_dt->tempImage == NULL)
+ {
+ assert(xm_dt->block.width == 1);
+ assert(xm_dt->block.height == 1);
+ alloc_shm_ximage(xm_dt, xm_buffer,
+ xm_dt->stride / xm_dt->block.size,
+ xm_dt->height);
+ }
+
+ ximage = xm_dt->tempImage;
+ ximage->data = xm_dt->data;
+
+ /* _debug_printf("XSHM\n"); */
+ XShmPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc,
+ ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height, False);
+ }
+ else
+#endif
+ {
+ /* display image in Window */
+ ximage = xm_dt->tempImage;
+ ximage->data = xm_dt->data;
+
+ /* check that the XImage has been previously initialized */
+ assert(ximage->format);
+ assert(ximage->bitmap_unit);
+
+ /* update XImage's fields */
+ ximage->width = xm_dt->width;
+ ximage->height = xm_dt->height;
+ ximage->bytes_per_line = xm_dt->stride;
+
+ /* _debug_printf("XPUT\n"); */
+ XPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc,
+ ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height);
+ }
+}
+
+/**
+ * Display/copy the image in the surface into the X window specified
+ * by the XMesaBuffer.
+ */
+static void
+xm_displaytarget_display(struct llvmpipe_winsys *ws,
+ struct llvmpipe_displaytarget *dt,
+ void *context_private)
+{
+ XMesaContext xmctx = (XMesaContext) context_private;
+ struct xmesa_buffer *xm_buffer = xmctx->xm_buffer;
+ xm_llvmpipe_display(xm_buffer, dt);
+}
+
+
+static struct llvmpipe_displaytarget *
+xm_displaytarget_create(struct llvmpipe_winsys *winsys,
+ enum pipe_format format,
+ unsigned width, unsigned height,
+ unsigned alignment,
+ unsigned *stride)
+{
+ struct xm_displaytarget *xm_dt = CALLOC_STRUCT(xm_displaytarget);
+ unsigned nblocksx, nblocksy, size;
+
+ xm_dt = CALLOC_STRUCT(xm_displaytarget);
+ if(!xm_dt)
+ goto no_xm_dt;
+
+ xm_dt->format = format;
+ xm_dt->width = width;
+ xm_dt->height = height;
+
+ pf_get_block(format, &xm_dt->block);
+ nblocksx = pf_get_nblocksx(&xm_dt->block, width);
+ nblocksy = pf_get_nblocksy(&xm_dt->block, height);
+ xm_dt->stride = align(nblocksx * xm_dt->block.size, alignment);
+ size = xm_dt->stride * nblocksy;
+
+#ifdef USE_XSHM
+ if (!debug_get_bool_option("XLIB_NO_SHM", FALSE))
+ {
+ xm_dt->shminfo.shmid = -1;
+ xm_dt->shminfo.shmaddr = (char *) -1;
+ xm_dt->shm = TRUE;
+
+ xm_dt->data = alloc_shm(xm_dt, size);
+ if(!xm_dt->data)
+ goto no_data;
+ }
+#endif
+
+ if(!xm_dt->data) {
+ xm_dt->data = align_malloc(size, alignment);
+ if(!xm_dt->data)
+ goto no_data;
+ }
+
+ *stride = xm_dt->stride;
+ return (struct llvmpipe_displaytarget *)xm_dt;
+
+no_data:
+ FREE(xm_dt);
+no_xm_dt:
+ return NULL;
+}
+
+
+static void
+xm_destroy( struct llvmpipe_winsys *ws )
+{
+ FREE(ws);
+}
+
+
+static struct llvmpipe_winsys *
+xlib_create_llvmpipe_winsys( void )
+{
+ struct xmesa_llvmpipe_winsys *ws;
+
+ ws = CALLOC_STRUCT(xmesa_llvmpipe_winsys);
+ if (!ws)
+ return NULL;
+
+ ws->base.destroy = xm_destroy;
+
+ ws->base.is_displaytarget_format_supported = xm_is_displaytarget_format_supported;
+
+ ws->base.displaytarget_create = xm_displaytarget_create;
+ ws->base.displaytarget_map = xm_displaytarget_map;
+ ws->base.displaytarget_unmap = xm_displaytarget_unmap;
+ ws->base.displaytarget_destroy = xm_displaytarget_destroy;
+
+ ws->base.displaytarget_display = xm_displaytarget_display;
+
+ return &ws->base;
+}
+
+
+static struct pipe_screen *
+xlib_create_llvmpipe_screen( void )
+{
+ struct llvmpipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ winsys = xlib_create_llvmpipe_winsys();
+ if (winsys == NULL)
+ return NULL;
+
+ screen = llvmpipe_create_screen(winsys);
+ if (screen == NULL)
+ goto fail;
+
+ return screen;
+
+fail:
+ if (winsys)
+ winsys->destroy( winsys );
+
+ return NULL;
+}
+
+
+static struct pipe_context *
+xlib_create_llvmpipe_context( struct pipe_screen *screen,
+ void *context_private )
+{
+ struct pipe_context *pipe;
+
+ pipe = llvmpipe_create(screen);
+ if (pipe == NULL)
+ goto fail;
+
+ pipe->priv = context_private;
+ return pipe;
+
+fail:
+ /* Free stuff here */
+ return NULL;
+}
+
+
+static void
+xlib_llvmpipe_display_surface(struct xmesa_buffer *xm_buffer,
+ struct pipe_surface *surf)
+{
+ struct llvmpipe_texture *texture = llvmpipe_texture(surf->texture);
+
+ assert(texture->dt);
+ if (texture->dt)
+ xm_llvmpipe_display(xm_buffer, texture->dt);
+}
+
+
+struct xm_driver xlib_llvmpipe_driver =
+{
+ .create_pipe_screen = xlib_create_llvmpipe_screen,
+ .create_pipe_context = xlib_create_llvmpipe_context,
+ .display_surface = xlib_llvmpipe_display_surface
+};
+
+
+
diff --git a/src/gallium/winsys/xlib/xlib_softpipe.c b/src/gallium/winsys/xlib/xlib_softpipe.c
new file mode 100644
index 0000000000..67fea023a3
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib_softpipe.c
@@ -0,0 +1,507 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell
+ * Brian Paul
+ */
+
+
+#include "xm_api.h"
+
+#undef ASSERT
+#undef Elements
+
+#include "pipe/internal/p_winsys_screen.h"
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "softpipe/sp_winsys.h"
+#include "softpipe/sp_texture.h"
+
+#include "xlib.h"
+
+/**
+ * Subclass of pipe_buffer for Xlib winsys.
+ * Low-level OS/window system memory buffer
+ */
+struct xm_buffer
+{
+ struct pipe_buffer base;
+ boolean userBuffer; /** Is this a user-space buffer? */
+ void *data;
+ void *mapped;
+
+ XImage *tempImage;
+#ifdef USE_XSHM
+ int shm;
+ XShmSegmentInfo shminfo;
+#endif
+};
+
+
+/**
+ * Subclass of pipe_winsys for Xlib winsys
+ */
+struct xmesa_pipe_winsys
+{
+ struct pipe_winsys base;
+/* struct xmesa_visual *xm_visual; */
+#ifdef USE_XSHM
+ int shm;
+#endif
+};
+
+
+
+/** Cast wrapper */
+static INLINE struct xm_buffer *
+xm_buffer( struct pipe_buffer *buf )
+{
+ return (struct xm_buffer *)buf;
+}
+
+
+/**
+ * X Shared Memory Image extension code
+ */
+#ifdef USE_XSHM
+#define XSHM_ENABLED(b) ((b)->shm)
+#else
+#define XSHM_ENABLED(b) 0
+#endif
+
+#ifdef USE_XSHM
+
+static volatile int mesaXErrorFlag = 0;
+
+/**
+ * Catches potential Xlib errors.
+ */
+static int
+mesaHandleXError(Display *dpy, XErrorEvent *event)
+{
+ (void) dpy;
+ (void) event;
+ mesaXErrorFlag = 1;
+ return 0;
+}
+
+
+static GLboolean alloc_shm(struct xm_buffer *buf, unsigned size)
+{
+ XShmSegmentInfo *const shminfo = & buf->shminfo;
+
+ shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
+ if (shminfo->shmid < 0) {
+ return GL_FALSE;
+ }
+
+ shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
+ if (shminfo->shmaddr == (char *) -1) {
+ shmctl(shminfo->shmid, IPC_RMID, 0);
+ return GL_FALSE;
+ }
+
+ shminfo->readOnly = False;
+ return GL_TRUE;
+}
+
+
+/**
+ * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
+ */
+static void
+alloc_shm_ximage(struct xm_buffer *b, struct xmesa_buffer *xmb,
+ unsigned width, unsigned height)
+{
+ /*
+ * We have to do a _lot_ of error checking here to be sure we can
+ * really use the XSHM extension. It seems different servers trigger
+ * errors at different points if the extension won't work. Therefore
+ * we have to be very careful...
+ */
+ int (*old_handler)(Display *, XErrorEvent *);
+
+ b->tempImage = XShmCreateImage(xmb->xm_visual->display,
+ xmb->xm_visual->visinfo->visual,
+ xmb->xm_visual->visinfo->depth,
+ ZPixmap,
+ NULL,
+ &b->shminfo,
+ width, height);
+ if (b->tempImage == NULL) {
+ b->shm = 0;
+ return;
+ }
+
+
+ mesaXErrorFlag = 0;
+ old_handler = XSetErrorHandler(mesaHandleXError);
+ /* This may trigger the X protocol error we're ready to catch: */
+ XShmAttach(xmb->xm_visual->display, &b->shminfo);
+ XSync(xmb->xm_visual->display, False);
+
+ if (mesaXErrorFlag) {
+ /* we are on a remote display, this error is normal, don't print it */
+ XFlush(xmb->xm_visual->display);
+ mesaXErrorFlag = 0;
+ XDestroyImage(b->tempImage);
+ b->tempImage = NULL;
+ b->shm = 0;
+ (void) XSetErrorHandler(old_handler);
+ return;
+ }
+
+ b->shm = 1;
+}
+
+#endif /* USE_XSHM */
+
+
+
+/* Most callbacks map direcly onto dri_bufmgr operations:
+ */
+static void *
+xm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
+ unsigned flags)
+{
+ struct xm_buffer *xm_buf = xm_buffer(buf);
+ xm_buf->mapped = xm_buf->data;
+ return xm_buf->mapped;
+}
+
+static void
+xm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+ struct xm_buffer *xm_buf = xm_buffer(buf);
+ xm_buf->mapped = NULL;
+}
+
+static void
+xm_buffer_destroy(struct pipe_buffer *buf)
+{
+ struct xm_buffer *oldBuf = xm_buffer(buf);
+
+ if (oldBuf->data) {
+#ifdef USE_XSHM
+ if (oldBuf->shminfo.shmid >= 0) {
+ shmdt(oldBuf->shminfo.shmaddr);
+ shmctl(oldBuf->shminfo.shmid, IPC_RMID, 0);
+
+ oldBuf->shminfo.shmid = -1;
+ oldBuf->shminfo.shmaddr = (char *) -1;
+ }
+ else
+#endif
+ {
+ if (!oldBuf->userBuffer) {
+ align_free(oldBuf->data);
+ }
+ }
+
+ oldBuf->data = NULL;
+ }
+
+ free(oldBuf);
+}
+
+
+/**
+ * Display/copy the image in the surface into the X window specified
+ * by the XMesaBuffer.
+ */
+static void
+xlib_softpipe_display_surface(struct xmesa_buffer *b,
+ struct pipe_surface *surf)
+{
+ XImage *ximage;
+ struct softpipe_texture *spt = softpipe_texture(surf->texture);
+ struct xm_buffer *xm_buf = xm_buffer(spt->buffer);
+ static boolean no_swap = 0;
+ static boolean firsttime = 1;
+
+ if (firsttime) {
+ no_swap = getenv("SP_NO_RAST") != NULL;
+ firsttime = 0;
+ }
+
+ if (no_swap)
+ return;
+
+#ifdef USE_XSHM
+ if (XSHM_ENABLED(xm_buf) && (xm_buf->tempImage == NULL)) {
+ assert(surf->texture->block.width == 1);
+ assert(surf->texture->block.height == 1);
+ alloc_shm_ximage(xm_buf, b, spt->stride[surf->level] /
+ surf->texture->block.size, surf->height);
+ }
+#endif
+
+ ximage = (XSHM_ENABLED(xm_buf)) ? xm_buf->tempImage : b->tempImage;
+ ximage->data = xm_buf->data;
+
+ /* display image in Window */
+#ifdef USE_XSHM
+ if (XSHM_ENABLED(xm_buf)) {
+ XShmPutImage(b->xm_visual->display, b->drawable, b->gc,
+ ximage, 0, 0, 0, 0, surf->width, surf->height, False);
+ } else
+#endif
+ {
+ /* check that the XImage has been previously initialized */
+ assert(ximage->format);
+ assert(ximage->bitmap_unit);
+
+ /* update XImage's fields */
+ ximage->width = surf->width;
+ ximage->height = surf->height;
+ ximage->bytes_per_line = spt->stride[surf->level];
+
+ XPutImage(b->xm_visual->display, b->drawable, b->gc,
+ ximage, 0, 0, 0, 0, surf->width, surf->height);
+ }
+}
+
+
+static void
+xm_flush_frontbuffer(struct pipe_winsys *pws,
+ struct pipe_surface *surf,
+ void *context_private)
+{
+ /*
+ * The front color buffer is actually just another XImage buffer.
+ * This function copies that XImage to the actual X Window.
+ */
+ XMesaContext xmctx = (XMesaContext) context_private;
+ xlib_softpipe_display_surface(xmctx->xm_buffer, surf);
+ xmesa_check_and_update_buffer_size(xmctx, xmctx->xm_buffer);
+}
+
+
+
+static const char *
+xm_get_name(struct pipe_winsys *pws)
+{
+ return "Xlib";
+}
+
+
+static struct pipe_buffer *
+xm_buffer_create(struct pipe_winsys *pws,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
+#ifdef USE_XSHM
+ struct xmesa_pipe_winsys *xpws = (struct xmesa_pipe_winsys *) pws;
+
+ buffer->shminfo.shmid = -1;
+ buffer->shminfo.shmaddr = (char *) -1;
+
+ if (xpws->shm && (usage & PIPE_BUFFER_USAGE_PIXEL) != 0) {
+ buffer->shm = xpws->shm;
+
+ if (alloc_shm(buffer, size)) {
+ buffer->data = buffer->shminfo.shmaddr;
+ buffer->shm = 1;
+ }
+ }
+#endif
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.alignment = alignment;
+ buffer->base.usage = usage;
+ buffer->base.size = size;
+
+ if (buffer->data == NULL) {
+ /* align to 16-byte multiple for Cell */
+ buffer->data = align_malloc(size, max(alignment, 16));
+ }
+
+ return &buffer->base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
+{
+ struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.size = bytes;
+ buffer->userBuffer = TRUE;
+ buffer->data = ptr;
+#ifdef USE_XSHM
+ buffer->shm = 0;
+#endif
+
+ return &buffer->base;
+}
+
+
+static struct pipe_buffer *
+xm_surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned tex_usage,
+ unsigned *stride)
+{
+ const unsigned alignment = 64;
+ struct pipe_format_block block;
+ unsigned nblocksx, nblocksy;
+
+ pf_get_block(format, &block);
+ nblocksx = pf_get_nblocksx(&block, width);
+ nblocksy = pf_get_nblocksy(&block, height);
+ *stride = align(nblocksx * block.size, alignment);
+
+ return winsys->buffer_create(winsys, alignment,
+ usage,
+ *stride * nblocksy);
+}
+
+
+/*
+ * Fence functions - basically nothing to do, as we don't create any actual
+ * fence objects.
+ */
+
+static void
+xm_fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+}
+
+
+static int
+xm_fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+static int
+xm_fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+
+static struct pipe_winsys *
+xlib_create_softpipe_winsys( void )
+{
+ static struct xmesa_pipe_winsys *ws = NULL;
+
+ if (!ws) {
+ ws = CALLOC_STRUCT(xmesa_pipe_winsys);
+
+ /* Fill in this struct with callbacks that pipe will need to
+ * communicate with the window system, buffer manager, etc.
+ */
+ ws->base.buffer_create = xm_buffer_create;
+ ws->base.user_buffer_create = xm_user_buffer_create;
+ ws->base.buffer_map = xm_buffer_map;
+ ws->base.buffer_unmap = xm_buffer_unmap;
+ ws->base.buffer_destroy = xm_buffer_destroy;
+
+ ws->base.surface_buffer_create = xm_surface_buffer_create;
+
+ ws->base.fence_reference = xm_fence_reference;
+ ws->base.fence_signalled = xm_fence_signalled;
+ ws->base.fence_finish = xm_fence_finish;
+
+ ws->base.flush_frontbuffer = xm_flush_frontbuffer;
+ ws->base.get_name = xm_get_name;
+ }
+
+ return &ws->base;
+}
+
+
+static struct pipe_screen *
+xlib_create_softpipe_screen( void )
+{
+ struct pipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ winsys = xlib_create_softpipe_winsys();
+ if (winsys == NULL)
+ return NULL;
+
+ screen = softpipe_create_screen(winsys);
+ if (screen == NULL)
+ goto fail;
+
+ return screen;
+
+fail:
+ if (winsys)
+ winsys->destroy( winsys );
+
+ return NULL;
+}
+
+
+static struct pipe_context *
+xlib_create_softpipe_context( struct pipe_screen *screen,
+ void *context_private )
+{
+ struct pipe_context *pipe;
+
+ pipe = softpipe_create(screen);
+ if (pipe == NULL)
+ goto fail;
+
+ pipe->priv = context_private;
+ return pipe;
+
+fail:
+ /* Free stuff here */
+ return NULL;
+}
+
+struct xm_driver xlib_softpipe_driver =
+{
+ .create_pipe_screen = xlib_create_softpipe_screen,
+ .create_pipe_context = xlib_create_softpipe_context,
+ .display_surface = xlib_softpipe_display_surface
+};
+
+
+
diff --git a/src/gallium/winsys/xlib/xlib_trace.c b/src/gallium/winsys/xlib/xlib_trace.c
new file mode 100644
index 0000000000..dbea655ab4
--- /dev/null
+++ b/src/gallium/winsys/xlib/xlib_trace.c
@@ -0,0 +1,113 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell
+ * Brian Paul
+ */
+
+
+#include "xlib.h"
+
+#include "trace/tr_screen.h"
+#include "trace/tr_context.h"
+#include "trace/tr_texture.h"
+
+#include "pipe/p_screen.h"
+
+
+
+static struct pipe_screen *
+xlib_create_trace_screen( void )
+{
+ struct pipe_screen *screen, *trace_screen;
+
+ screen = xlib_softpipe_driver.create_pipe_screen();
+ if (screen == NULL)
+ goto fail;
+
+ /* Wrap it:
+ */
+ trace_screen = trace_screen_create(screen);
+ if (trace_screen == NULL)
+ goto fail;
+
+ return trace_screen;
+
+fail:
+ if (screen)
+ screen->destroy( screen );
+ return NULL;
+}
+
+static struct pipe_context *
+xlib_create_trace_context( struct pipe_screen *_screen,
+ void *priv )
+{
+ struct trace_screen *tr_scr = trace_screen( _screen );
+ struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_context *pipe, *trace_pipe;
+
+ pipe = xlib_softpipe_driver.create_pipe_context( screen, priv );
+ if (pipe == NULL)
+ goto fail;
+
+ /* Wrap it:
+ */
+ trace_pipe = trace_context_create(_screen, pipe);
+ if (trace_pipe == NULL)
+ goto fail;
+
+ trace_pipe->priv = priv;
+
+ return trace_pipe;
+
+fail:
+ if (pipe)
+ pipe->destroy( pipe );
+ return NULL;
+}
+
+static void
+xlib_trace_display_surface( struct xmesa_buffer *buffer,
+ struct pipe_surface *_surf )
+{
+ struct trace_surface *tr_surf = trace_surface( _surf );
+ struct pipe_surface *surf = tr_surf->surface;
+
+ xlib_softpipe_driver.display_surface( buffer, surf );
+}
+
+
+struct xm_driver xlib_trace_driver =
+{
+ .create_pipe_screen = xlib_create_trace_screen,
+ .create_pipe_context = xlib_create_trace_context,
+ .display_surface = xlib_trace_display_surface,
+};
diff --git a/src/gallium/winsys/xlib/xmesa.h b/src/gallium/winsys/xlib/xmesa.h
new file mode 100644
index 0000000000..98139af833
--- /dev/null
+++ b/src/gallium/winsys/xlib/xmesa.h
@@ -0,0 +1,424 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Mesa/X11 interface. This header file serves as the documentation for
+ * the Mesa/X11 interface functions.
+ *
+ * Note: this interface isn't intended for user programs. It's primarily
+ * just for implementing the pseudo-GLX interface.
+ */
+
+
+/* Sample Usage:
+
+In addition to the usual X calls to select a visual, create a colormap
+and create a window, you must do the following to use the X/Mesa interface:
+
+1. Call XMesaCreateVisual() to make an XMesaVisual from an XVisualInfo.
+
+2. Call XMesaCreateContext() to create an X/Mesa rendering context, given
+ the XMesaVisual.
+
+3. Call XMesaCreateWindowBuffer() to create an XMesaBuffer from an X window
+ and XMesaVisual.
+
+4. Call XMesaMakeCurrent() to bind the XMesaBuffer to an XMesaContext and
+ to make the context the current one.
+
+5. Make gl* calls to render your graphics.
+
+6. Use XMesaSwapBuffers() when double buffering to swap front/back buffers.
+
+7. Before the X window is destroyed, call XMesaDestroyBuffer().
+
+8. Before exiting, call XMesaDestroyVisual and XMesaDestroyContext.
+
+*/
+
+
+
+
+#ifndef XMESA_H
+#define XMESA_H
+
+#ifdef __VMS
+#include <GL/vms_x_fix.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef XFree86Server
+#include "xmesa_xf86.h"
+#else
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "xmesa_x.h"
+#endif
+#include "GL/gl.h"
+
+#ifdef AMIWIN
+#include <pragmas/xlib_pragmas.h>
+extern struct Library *XLibBase;
+#endif
+
+
+#define XMESA_MAJOR_VERSION 6
+#define XMESA_MINOR_VERSION 3
+
+
+
+/*
+ * Values passed to XMesaGetString:
+ */
+#define XMESA_VERSION 1
+#define XMESA_EXTENSIONS 2
+
+
+/*
+ * Values passed to XMesaSetFXmode:
+ */
+#define XMESA_FX_WINDOW 1
+#define XMESA_FX_FULLSCREEN 2
+
+
+
+typedef struct xmesa_context *XMesaContext;
+
+typedef struct xmesa_visual *XMesaVisual;
+
+typedef struct xmesa_buffer *XMesaBuffer;
+
+
+
+/*
+ * Create a new X/Mesa visual.
+ * Input: display - X11 display
+ * visinfo - an XVisualInfo pointer
+ * rgb_flag - GL_TRUE = RGB mode,
+ * GL_FALSE = color index mode
+ * alpha_flag - alpha buffer requested?
+ * db_flag - GL_TRUE = double-buffered,
+ * GL_FALSE = single buffered
+ * stereo_flag - stereo visual?
+ * ximage_flag - GL_TRUE = use an XImage for back buffer,
+ * GL_FALSE = use an off-screen pixmap for back buffer
+ * depth_size - requested bits/depth values, or zero
+ * stencil_size - requested bits/stencil values, or zero
+ * accum_red_size - requested bits/red accum values, or zero
+ * accum_green_size - requested bits/green accum values, or zero
+ * accum_blue_size - requested bits/blue accum values, or zero
+ * accum_alpha_size - requested bits/alpha accum values, or zero
+ * num_samples - number of samples/pixel if multisampling, or zero
+ * level - visual level, usually 0
+ * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT
+ * Return; a new XMesaVisual or 0 if error.
+ */
+extern XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
+ XMesaVisualInfo visinfo,
+ GLboolean rgb_flag,
+ GLboolean alpha_flag,
+ GLboolean db_flag,
+ GLboolean stereo_flag,
+ GLboolean ximage_flag,
+ GLint depth_size,
+ GLint stencil_size,
+ GLint accum_red_size,
+ GLint accum_green_size,
+ GLint accum_blue_size,
+ GLint accum_alpha_size,
+ GLint num_samples,
+ GLint level,
+ GLint visualCaveat );
+
+/*
+ * Destroy an XMesaVisual, but not the associated XVisualInfo.
+ */
+extern void XMesaDestroyVisual( XMesaVisual v );
+
+
+
+/*
+ * Create a new XMesaContext for rendering into an X11 window.
+ *
+ * Input: visual - an XMesaVisual
+ * share_list - another XMesaContext with which to share display
+ * lists or NULL if no sharing is wanted.
+ * Return: an XMesaContext or NULL if error.
+ */
+extern XMesaContext XMesaCreateContext( XMesaVisual v,
+ XMesaContext share_list );
+
+
+/*
+ * Destroy a rendering context as returned by XMesaCreateContext()
+ */
+extern void XMesaDestroyContext( XMesaContext c );
+
+
+#ifdef XFree86Server
+/*
+ * These are the extra routines required for integration with XFree86.
+ * None of these routines should be user visible. -KEM
+ */
+extern GLboolean XMesaForceCurrent( XMesaContext c );
+
+extern GLboolean XMesaLoseCurrent( XMesaContext c );
+
+extern GLboolean XMesaCopyContext( XMesaContext src,
+ XMesaContext dst,
+ GLuint mask );
+#endif /* XFree86Server */
+
+
+/*
+ * Create an XMesaBuffer from an X window.
+ */
+extern XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w );
+
+
+/*
+ * Create an XMesaBuffer from an X pixmap.
+ */
+extern XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v,
+ XMesaPixmap p,
+ XMesaColormap cmap );
+
+
+/*
+ * Destroy an XMesaBuffer, but not the corresponding window or pixmap.
+ */
+extern void XMesaDestroyBuffer( XMesaBuffer b );
+
+
+/*
+ * Return the XMesaBuffer handle which corresponds to an X drawable, if any.
+ *
+ * New in Mesa 2.3.
+ */
+extern XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy,
+ XMesaDrawable d );
+
+
+
+/*
+ * Bind a buffer to a context and make the context the current one.
+ */
+extern GLboolean XMesaMakeCurrent( XMesaContext c,
+ XMesaBuffer b );
+
+
+/*
+ * Bind two buffers (read and draw) to a context and make the
+ * context the current one.
+ * New in Mesa 3.3
+ */
+extern GLboolean XMesaMakeCurrent2( XMesaContext c,
+ XMesaBuffer drawBuffer,
+ XMesaBuffer readBuffer );
+
+
+/*
+ * Unbind the current context from its buffer.
+ */
+extern GLboolean XMesaUnbindContext( XMesaContext c );
+
+
+/*
+ * Return a handle to the current context.
+ */
+extern XMesaContext XMesaGetCurrentContext( void );
+
+
+/*
+ * Return handle to the current (draw) buffer.
+ */
+extern XMesaBuffer XMesaGetCurrentBuffer( void );
+
+
+/*
+ * Return handle to the current read buffer.
+ * New in Mesa 3.3
+ */
+extern XMesaBuffer XMesaGetCurrentReadBuffer( void );
+
+
+/*
+ * Swap the front and back buffers for the given buffer. No action is
+ * taken if the buffer is not double buffered.
+ */
+extern void XMesaSwapBuffers( XMesaBuffer b );
+
+
+/*
+ * Copy a sub-region of the back buffer to the front buffer.
+ *
+ * New in Mesa 2.6
+ */
+extern void XMesaCopySubBuffer( XMesaBuffer b,
+ int x,
+ int y,
+ int width,
+ int height );
+
+
+/*
+ * Return a pointer to the the Pixmap or XImage being used as the back
+ * color buffer of an XMesaBuffer. This function is a way to get "under
+ * the hood" of X/Mesa so one can manipulate the back buffer directly.
+ * Input: b - the XMesaBuffer
+ * Output: pixmap - pointer to back buffer's Pixmap, or 0
+ * ximage - pointer to back buffer's XImage, or NULL
+ * Return: GL_TRUE = context is double buffered
+ * GL_FALSE = context is single buffered
+ */
+extern GLboolean XMesaGetBackBuffer( XMesaBuffer b,
+ XMesaPixmap *pixmap,
+ XMesaImage **ximage );
+
+
+
+/*
+ * Return the depth buffer associated with an XMesaBuffer.
+ * Input: b - the XMesa buffer handle
+ * Output: width, height - size of buffer in pixels
+ * bytesPerValue - bytes per depth value (2 or 4)
+ * buffer - pointer to depth buffer values
+ * Return: GL_TRUE or GL_FALSE to indicate success or failure.
+ *
+ * New in Mesa 2.4.
+ */
+extern GLboolean XMesaGetDepthBuffer( XMesaBuffer b,
+ GLint *width,
+ GLint *height,
+ GLint *bytesPerValue,
+ void **buffer );
+
+
+
+/*
+ * Flush/sync a context
+ */
+extern void XMesaFlush( XMesaContext c );
+
+
+
+/*
+ * Get an X/Mesa-specific string.
+ * Input: name - either XMESA_VERSION or XMESA_EXTENSIONS
+ */
+extern const char *XMesaGetString( XMesaContext c, int name );
+
+
+
+/*
+ * Scan for XMesaBuffers whose window/pixmap has been destroyed, then free
+ * any memory used by that buffer.
+ *
+ * New in Mesa 2.3.
+ */
+extern void XMesaGarbageCollect( void );
+
+
+
+/*
+ * Return a dithered pixel value.
+ * Input: c - XMesaContext
+ * x, y - window coordinate
+ * red, green, blue, alpha - color components in [0,1]
+ * Return: pixel value
+ *
+ * New in Mesa 2.3.
+ */
+extern unsigned long XMesaDitherColor( XMesaContext xmesa,
+ GLint x,
+ GLint y,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha );
+
+
+
+/*
+ * 3Dfx Glide driver only!
+ * Set 3Dfx/Glide full-screen or window rendering mode.
+ * Input: mode - either XMESA_FX_WINDOW (window rendering mode) or
+ * XMESA_FX_FULLSCREEN (full-screen rendering mode)
+ * Return: GL_TRUE if success
+ * GL_FALSE if invalid mode or if not using 3Dfx driver
+ *
+ * New in Mesa 2.6.
+ */
+extern GLboolean XMesaSetFXmode( GLint mode );
+
+
+
+/*
+ * Reallocate the back/depth/stencil/accum/etc/ buffers associated with
+ * buffer <b> if its size has changed.
+ *
+ * New in Mesa 4.0.2
+ */
+extern void XMesaResizeBuffers( XMesaBuffer b );
+
+
+
+/*
+ * Create a pbuffer.
+ * New in Mesa 4.1
+ */
+extern XMesaBuffer XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
+ unsigned int width, unsigned int height);
+
+
+
+/*
+ * Texture from Pixmap
+ * New in Mesa 7.1
+ */
+extern void
+XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer,
+ const int *attrib_list);
+
+extern void
+XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer);
+
+
+extern XMesaBuffer
+XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p,
+ XMesaColormap cmap,
+ int format, int target, int mipmap);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/gallium/winsys/xlib/xmesa_x.h b/src/gallium/winsys/xlib/xmesa_x.h
new file mode 100644
index 0000000000..865bab4313
--- /dev/null
+++ b/src/gallium/winsys/xlib/xmesa_x.h
@@ -0,0 +1,86 @@
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ * When we're building the XMesa driver for stand-alone Mesa we
+ * include this file when building the xm_*.c files.
+ * We need to define some types and macros differently when building
+ * in the Xserver vs. stand-alone Mesa.
+ */
+
+#ifndef _XMESA_X_H_
+#define _XMESA_X_H_
+
+typedef Display XMesaDisplay;
+typedef Pixmap XMesaPixmap;
+typedef Colormap XMesaColormap;
+typedef Drawable XMesaDrawable;
+typedef Window XMesaWindow;
+typedef GC XMesaGC;
+typedef XVisualInfo *XMesaVisualInfo;
+typedef XImage XMesaImage;
+typedef XPoint XMesaPoint;
+typedef XColor XMesaColor;
+
+#define XMesaDestroyImage XDestroyImage
+
+#define XMesaPutPixel XPutPixel
+#define XMesaGetPixel XGetPixel
+
+#define XMesaSetForeground XSetForeground
+#define XMesaSetBackground XSetBackground
+#define XMesaSetPlaneMask XSetPlaneMask
+#define XMesaSetFunction XSetFunction
+#define XMesaSetFillStyle XSetFillStyle
+#define XMesaSetTile XSetTile
+
+#define XMesaDrawPoint XDrawPoint
+#define XMesaDrawPoints XDrawPoints
+#define XMesaDrawLine XDrawLine
+#define XMesaFillRectangle XFillRectangle
+#define XMesaGetImage XGetImage
+#define XMesaPutImage XPutImage
+#define XMesaCopyArea XCopyArea
+
+#define XMesaCreatePixmap XCreatePixmap
+#define XMesaFreePixmap XFreePixmap
+#define XMesaFreeGC XFreeGC
+
+#define GET_COLORMAP_SIZE(__v) __v->visinfo->colormap_size
+#define GET_REDMASK(__v) __v->mesa_visual.redMask
+#define GET_GREENMASK(__v) __v->mesa_visual.greenMask
+#define GET_BLUEMASK(__v) __v->mesa_visual.blueMask
+#define GET_VISUAL_DEPTH(__v) __v->visinfo->depth
+#define GET_BLACK_PIXEL(__v) BlackPixel(__v->display, __v->mesa_visual.screen)
+#define CHECK_BYTE_ORDER(__v) host_byte_order()==ImageByteOrder(__v->display)
+#define CHECK_FOR_HPCR(__v) XInternAtom(__v->display, "_HP_RGB_SMOOTH_MAP_LIST", True)
+
+#endif
diff --git a/src/glew/LICENSE.txt b/src/glew/LICENSE.txt
new file mode 100644
index 0000000000..f7078042e9
--- /dev/null
+++ b/src/glew/LICENSE.txt
@@ -0,0 +1,73 @@
+The OpenGL Extension Wrangler Library
+Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
+Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
+Copyright (C) 2002, Lev Povalahev
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+* The name of the author may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Mesa 3-D graphics library
+Version: 7.0
+
+Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright (c) 2007 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are 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 Materials.
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+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
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
diff --git a/src/glew/Makefile b/src/glew/Makefile
new file mode 100644
index 0000000000..cd692f3ef7
--- /dev/null
+++ b/src/glew/Makefile
@@ -0,0 +1,54 @@
+# src/glew/Makefile
+
+TOP = ../..
+include $(TOP)/configs/current
+
+
+##### MACROS #####
+
+GLEW_LIB_NAME = libGLEW.a
+
+MAJOR = 1
+MINOR = 5
+TINY = 0
+
+SOURCES = \
+ glew.c
+
+
+OBJECTS = $(SOURCES:.c=.o)
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c -I$(TOP)/include $(X11_INCLUDES) $(CFLAGS) $<
+
+
+
+##### TARGETS #####
+
+default: $(TOP)/$(LIB_DIR)/$(GLEW_LIB_NAME)
+
+
+
+# Make the library
+$(TOP)/$(LIB_DIR)/$(GLEW_LIB_NAME): depend $(OBJECTS)
+ $(MKLIB) -o $(GLEW_LIB) -static -install $(TOP)/$(LIB_DIR) $(OBJECTS)
+
+
+install:
+
+
+clean:
+ -rm -f *.o *~
+ -rm -f depend depend.bak
+
+
+depend: $(SOURCES)
+ @ rm -f depend
+ @ touch depend
+ @ $(MKDEP) $(MKDEP_OPTIONS) -I$(TOP)/include $(SOURCES) \
+ $(X11_INCLUDES) > /dev/null
+
+include depend
diff --git a/src/glew/SConscript b/src/glew/SConscript
new file mode 100644
index 0000000000..1161be6e63
--- /dev/null
+++ b/src/glew/SConscript
@@ -0,0 +1,50 @@
+Import('*')
+
+if env['platform'] not in ['windows', 'linux']:
+ Return()
+
+env = env.Clone()
+
+env.Append(CPPDEFINES = [
+ 'GLEW_BUILD',
+ 'GLEW_STATIC',
+ #'GLEW_MX', # Multiple Rendering Contexts support
+])
+
+env.PrependUnique(CPPPATH = [
+ '#/include',
+])
+
+glew = env.StaticLibrary(
+ target = 'glew',
+ source = [
+ 'glew.c',
+ ],
+)
+
+env = env.Clone()
+
+if env['platform'] == 'windows':
+ env.PrependUnique(LIBS = [
+ 'glu32',
+ 'opengl32',
+ 'gdi32',
+ 'user32',
+ ])
+else:
+ env.PrependUnique(LIBS = [
+ 'GLU',
+ 'GL',
+ 'X11',
+ ])
+env.Prepend(LIBS = [glew])
+
+env.Program(
+ target = 'glewinfo',
+ source = ['glewinfo.c'],
+)
+
+env.Program(
+ target = 'visualinfo',
+ source = ['visualinfo.c'],
+)
diff --git a/src/glew/glew.c b/src/glew/glew.c
new file mode 100644
index 0000000000..aa2278f6c0
--- /dev/null
+++ b/src/glew/glew.c
@@ -0,0 +1,12180 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**
+** * Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+** * The name of the author may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+** THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <GL/glew.h>
+#if defined(_WIN32)
+# include <GL/wglew.h>
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+# include <GL/glxew.h>
+#endif
+
+/*
+ * Define glewGetContext and related helper macros.
+ */
+#ifdef GLEW_MX
+# define glewGetContext() ctx
+# ifdef _WIN32
+# define GLEW_CONTEXT_ARG_DEF_INIT GLEWContext* ctx
+# define GLEW_CONTEXT_ARG_VAR_INIT ctx
+# define wglewGetContext() ctx
+# define WGLEW_CONTEXT_ARG_DEF_INIT WGLEWContext* ctx
+# define WGLEW_CONTEXT_ARG_DEF_LIST WGLEWContext* ctx
+# else /* _WIN32 */
+# define GLEW_CONTEXT_ARG_DEF_INIT void
+# define GLEW_CONTEXT_ARG_VAR_INIT
+# define glxewGetContext() ctx
+# define GLXEW_CONTEXT_ARG_DEF_INIT void
+# define GLXEW_CONTEXT_ARG_DEF_LIST GLXEWContext* ctx
+# endif /* _WIN32 */
+# define GLEW_CONTEXT_ARG_DEF_LIST GLEWContext* ctx
+#else /* GLEW_MX */
+# define GLEW_CONTEXT_ARG_DEF_INIT void
+# define GLEW_CONTEXT_ARG_VAR_INIT
+# define GLEW_CONTEXT_ARG_DEF_LIST void
+# define WGLEW_CONTEXT_ARG_DEF_INIT void
+# define WGLEW_CONTEXT_ARG_DEF_LIST void
+# define GLXEW_CONTEXT_ARG_DEF_INIT void
+# define GLXEW_CONTEXT_ARG_DEF_LIST void
+#endif /* GLEW_MX */
+
+#if defined(__APPLE__)
+#include <mach-o/dyld.h>
+#include <stdlib.h>
+#include <string.h>
+
+void* NSGLGetProcAddress (const GLubyte *name)
+{
+ static const struct mach_header* image = NULL;
+ NSSymbol symbol;
+ char* symbolName;
+ if (NULL == image)
+ {
+ image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ }
+ /* prepend a '_' for the Unix C symbol mangling convention */
+ symbolName = malloc(strlen((const char*)name) + 2);
+ strcpy(symbolName+1, (const char*)name);
+ symbolName[0] = '_';
+ symbol = NULL;
+ /* if (NSIsSymbolNameDefined(symbolName))
+ symbol = NSLookupAndBindSymbol(symbolName); */
+ symbol = image ? NSLookupSymbolInImage(image, symbolName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) : NULL;
+ free(symbolName);
+ return symbol ? NSAddressOfSymbol(symbol) : NULL;
+}
+#endif /* __APPLE__ */
+
+#if defined(__sgi) || defined (__sun)
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void* dlGetProcAddress (const GLubyte* name)
+{
+ static void* h = NULL;
+ static void* gpa;
+
+ if (h == NULL)
+ {
+ if ((h = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL)) == NULL) return NULL;
+ gpa = dlsym(h, "glXGetProcAddress");
+ }
+
+ if (gpa != NULL)
+ return ((void*(*)(const GLubyte*))gpa)(name);
+ else
+ return dlsym(h, (const char*)name);
+}
+#endif /* __sgi || __sun */
+
+/*
+ * Define glewGetProcAddress.
+ */
+#if defined(_WIN32)
+# define glewGetProcAddress(name) wglGetProcAddress((LPCSTR)name)
+#else
+# if defined(__APPLE__)
+# define glewGetProcAddress(name) NSGLGetProcAddress(name)
+# else
+# if defined(__sgi) || defined(__sun)
+# define glewGetProcAddress(name) dlGetProcAddress(name)
+# else /* __linux */
+# define glewGetProcAddress(name) (*glXGetProcAddressARB)(name)
+# endif
+# endif
+#endif
+
+/*
+ * Define GLboolean const cast.
+ */
+#define CONST_CAST(x) (*(GLboolean*)&x)
+
+/*
+ * GLEW, just like OpenGL or GLU, does not rely on the standard C library.
+ * These functions implement the functionality required in this file.
+ */
+static GLuint _glewStrLen (const GLubyte* s)
+{
+ GLuint i=0;
+ if (s == NULL) return 0;
+ while (s[i] != '\0') i++;
+ return i;
+}
+
+static GLuint _glewStrCLen (const GLubyte* s, GLubyte c)
+{
+ GLuint i=0;
+ if (s == NULL) return 0;
+ while (s[i] != '\0' && s[i] != c) i++;
+ return (s[i] == '\0' || s[i] == c) ? i : 0;
+}
+
+static GLboolean _glewStrSame (const GLubyte* a, const GLubyte* b, GLuint n)
+{
+ GLuint i=0;
+ if(a == NULL || b == NULL)
+ return (a == NULL && b == NULL && n == 0) ? GL_TRUE : GL_FALSE;
+ while (i < n && a[i] != '\0' && b[i] != '\0' && a[i] == b[i]) i++;
+ return i == n ? GL_TRUE : GL_FALSE;
+}
+
+static GLboolean _glewStrSame1 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb)
+{
+ while (*na > 0 && (**a == ' ' || **a == '\n' || **a == '\r' || **a == '\t'))
+ {
+ (*a)++;
+ (*na)--;
+ }
+ if(*na >= nb)
+ {
+ GLuint i=0;
+ while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++;
+ if(i == nb)
+ {
+ *a = *a + nb;
+ *na = *na - nb;
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+static GLboolean _glewStrSame2 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb)
+{
+ if(*na >= nb)
+ {
+ GLuint i=0;
+ while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++;
+ if(i == nb)
+ {
+ *a = *a + nb;
+ *na = *na - nb;
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+static GLboolean _glewStrSame3 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb)
+{
+ if(*na >= nb)
+ {
+ GLuint i=0;
+ while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++;
+ if (i == nb && (*na == nb || (*a)[i] == ' ' || (*a)[i] == '\n' || (*a)[i] == '\r' || (*a)[i] == '\t'))
+ {
+ *a = *a + nb;
+ *na = *na - nb;
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+#if !defined(_WIN32) || !defined(GLEW_MX)
+
+PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D = NULL;
+PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements = NULL;
+PFNGLTEXIMAGE3DPROC __glewTexImage3D = NULL;
+PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D = NULL;
+
+PFNGLACTIVETEXTUREPROC __glewActiveTexture = NULL;
+PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage = NULL;
+PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd = NULL;
+PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf = NULL;
+PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd = NULL;
+PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf = NULL;
+PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d = NULL;
+PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv = NULL;
+PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f = NULL;
+PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv = NULL;
+PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i = NULL;
+PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv = NULL;
+PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s = NULL;
+PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv = NULL;
+PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d = NULL;
+PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv = NULL;
+PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f = NULL;
+PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv = NULL;
+PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i = NULL;
+PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv = NULL;
+PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s = NULL;
+PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv = NULL;
+PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d = NULL;
+PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv = NULL;
+PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f = NULL;
+PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv = NULL;
+PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i = NULL;
+PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv = NULL;
+PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s = NULL;
+PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv = NULL;
+PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d = NULL;
+PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv = NULL;
+PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f = NULL;
+PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv = NULL;
+PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i = NULL;
+PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv = NULL;
+PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s = NULL;
+PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv = NULL;
+PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage = NULL;
+
+PFNGLBLENDCOLORPROC __glewBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC __glewBlendEquation = NULL;
+PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate = NULL;
+PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer = NULL;
+PFNGLFOGCOORDDPROC __glewFogCoordd = NULL;
+PFNGLFOGCOORDDVPROC __glewFogCoorddv = NULL;
+PFNGLFOGCOORDFPROC __glewFogCoordf = NULL;
+PFNGLFOGCOORDFVPROC __glewFogCoordfv = NULL;
+PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays = NULL;
+PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements = NULL;
+PFNGLPOINTPARAMETERFPROC __glewPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv = NULL;
+PFNGLPOINTPARAMETERIPROC __glewPointParameteri = NULL;
+PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv = NULL;
+PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b = NULL;
+PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv = NULL;
+PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d = NULL;
+PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv = NULL;
+PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f = NULL;
+PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv = NULL;
+PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i = NULL;
+PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv = NULL;
+PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s = NULL;
+PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv = NULL;
+PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub = NULL;
+PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv = NULL;
+PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui = NULL;
+PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv = NULL;
+PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us = NULL;
+PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv = NULL;
+PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer = NULL;
+PFNGLWINDOWPOS2DPROC __glewWindowPos2d = NULL;
+PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv = NULL;
+PFNGLWINDOWPOS2FPROC __glewWindowPos2f = NULL;
+PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv = NULL;
+PFNGLWINDOWPOS2IPROC __glewWindowPos2i = NULL;
+PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv = NULL;
+PFNGLWINDOWPOS2SPROC __glewWindowPos2s = NULL;
+PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv = NULL;
+PFNGLWINDOWPOS3DPROC __glewWindowPos3d = NULL;
+PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv = NULL;
+PFNGLWINDOWPOS3FPROC __glewWindowPos3f = NULL;
+PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv = NULL;
+PFNGLWINDOWPOS3IPROC __glewWindowPos3i = NULL;
+PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv = NULL;
+PFNGLWINDOWPOS3SPROC __glewWindowPos3s = NULL;
+PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv = NULL;
+
+PFNGLBEGINQUERYPROC __glewBeginQuery = NULL;
+PFNGLBINDBUFFERPROC __glewBindBuffer = NULL;
+PFNGLBUFFERDATAPROC __glewBufferData = NULL;
+PFNGLBUFFERSUBDATAPROC __glewBufferSubData = NULL;
+PFNGLDELETEBUFFERSPROC __glewDeleteBuffers = NULL;
+PFNGLDELETEQUERIESPROC __glewDeleteQueries = NULL;
+PFNGLENDQUERYPROC __glewEndQuery = NULL;
+PFNGLGENBUFFERSPROC __glewGenBuffers = NULL;
+PFNGLGENQUERIESPROC __glewGenQueries = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv = NULL;
+PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData = NULL;
+PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv = NULL;
+PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv = NULL;
+PFNGLGETQUERYIVPROC __glewGetQueryiv = NULL;
+PFNGLISBUFFERPROC __glewIsBuffer = NULL;
+PFNGLISQUERYPROC __glewIsQuery = NULL;
+PFNGLMAPBUFFERPROC __glewMapBuffer = NULL;
+PFNGLUNMAPBUFFERPROC __glewUnmapBuffer = NULL;
+
+PFNGLATTACHSHADERPROC __glewAttachShader = NULL;
+PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate = NULL;
+PFNGLCOMPILESHADERPROC __glewCompileShader = NULL;
+PFNGLCREATEPROGRAMPROC __glewCreateProgram = NULL;
+PFNGLCREATESHADERPROC __glewCreateShader = NULL;
+PFNGLDELETEPROGRAMPROC __glewDeleteProgram = NULL;
+PFNGLDELETESHADERPROC __glewDeleteShader = NULL;
+PFNGLDETACHSHADERPROC __glewDetachShader = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray = NULL;
+PFNGLDRAWBUFFERSPROC __glewDrawBuffers = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray = NULL;
+PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform = NULL;
+PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation = NULL;
+PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMIVPROC __glewGetProgramiv = NULL;
+PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog = NULL;
+PFNGLGETSHADERSOURCEPROC __glewGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC __glewGetShaderiv = NULL;
+PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC __glewGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC __glewGetUniformiv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv = NULL;
+PFNGLISPROGRAMPROC __glewIsProgram = NULL;
+PFNGLISSHADERPROC __glewIsShader = NULL;
+PFNGLLINKPROGRAMPROC __glewLinkProgram = NULL;
+PFNGLSHADERSOURCEPROC __glewShaderSource = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate = NULL;
+PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate = NULL;
+PFNGLUNIFORM1FPROC __glewUniform1f = NULL;
+PFNGLUNIFORM1FVPROC __glewUniform1fv = NULL;
+PFNGLUNIFORM1IPROC __glewUniform1i = NULL;
+PFNGLUNIFORM1IVPROC __glewUniform1iv = NULL;
+PFNGLUNIFORM2FPROC __glewUniform2f = NULL;
+PFNGLUNIFORM2FVPROC __glewUniform2fv = NULL;
+PFNGLUNIFORM2IPROC __glewUniform2i = NULL;
+PFNGLUNIFORM2IVPROC __glewUniform2iv = NULL;
+PFNGLUNIFORM3FPROC __glewUniform3f = NULL;
+PFNGLUNIFORM3FVPROC __glewUniform3fv = NULL;
+PFNGLUNIFORM3IPROC __glewUniform3i = NULL;
+PFNGLUNIFORM3IVPROC __glewUniform3iv = NULL;
+PFNGLUNIFORM4FPROC __glewUniform4f = NULL;
+PFNGLUNIFORM4FVPROC __glewUniform4fv = NULL;
+PFNGLUNIFORM4IPROC __glewUniform4i = NULL;
+PFNGLUNIFORM4IVPROC __glewUniform4iv = NULL;
+PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv = NULL;
+PFNGLUSEPROGRAMPROC __glewUseProgram = NULL;
+PFNGLVALIDATEPROGRAMPROC __glewValidateProgram = NULL;
+PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d = NULL;
+PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv = NULL;
+PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s = NULL;
+PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv = NULL;
+PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv = NULL;
+PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s = NULL;
+PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv = NULL;
+PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d = NULL;
+PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv = NULL;
+PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s = NULL;
+PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv = NULL;
+PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv = NULL;
+PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv = NULL;
+PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv = NULL;
+PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv = NULL;
+PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d = NULL;
+PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv = NULL;
+PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv = NULL;
+PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s = NULL;
+PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv = NULL;
+PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv = NULL;
+PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv = NULL;
+PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer = NULL;
+
+PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv = NULL;
+
+PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback = NULL;
+PFNGLBINDBUFFERBASEPROC __glewBindBufferBase = NULL;
+PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation = NULL;
+PFNGLCLAMPCOLORPROC __glewClampColor = NULL;
+PFNGLCLEARBUFFERFIPROC __glewClearBufferfi = NULL;
+PFNGLCLEARBUFFERFVPROC __glewClearBufferfv = NULL;
+PFNGLCLEARBUFFERIVPROC __glewClearBufferiv = NULL;
+PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv = NULL;
+PFNGLCOLORMASKIPROC __glewColorMaski = NULL;
+PFNGLDISABLEIPROC __glewDisablei = NULL;
+PFNGLENABLEIPROC __glewEnablei = NULL;
+PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback = NULL;
+PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v = NULL;
+PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation = NULL;
+PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v = NULL;
+PFNGLGETSTRINGIPROC __glewGetStringi = NULL;
+PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying = NULL;
+PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv = NULL;
+PFNGLISENABLEDIPROC __glewIsEnabledi = NULL;
+PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv = NULL;
+PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings = NULL;
+PFNGLUNIFORM1UIPROC __glewUniform1ui = NULL;
+PFNGLUNIFORM1UIVPROC __glewUniform1uiv = NULL;
+PFNGLUNIFORM2UIPROC __glewUniform2ui = NULL;
+PFNGLUNIFORM2UIVPROC __glewUniform2uiv = NULL;
+PFNGLUNIFORM3UIPROC __glewUniform3ui = NULL;
+PFNGLUNIFORM3UIVPROC __glewUniform3uiv = NULL;
+PFNGLUNIFORM4UIPROC __glewUniform4ui = NULL;
+PFNGLUNIFORM4UIVPROC __glewUniform4uiv = NULL;
+PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv = NULL;
+PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i = NULL;
+PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv = NULL;
+PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv = NULL;
+PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i = NULL;
+PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv = NULL;
+PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv = NULL;
+PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv = NULL;
+PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i = NULL;
+PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv = NULL;
+PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv = NULL;
+PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv = NULL;
+PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer = NULL;
+
+PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX = NULL;
+
+PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE = NULL;
+PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE = NULL;
+PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE = NULL;
+PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE = NULL;
+PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE = NULL;
+
+PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE = NULL;
+PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE = NULL;
+PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE = NULL;
+PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE = NULL;
+PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE = NULL;
+PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE = NULL;
+PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE = NULL;
+PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE = NULL;
+
+PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE = NULL;
+
+PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE = NULL;
+PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE = NULL;
+
+PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE = NULL;
+PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE = NULL;
+PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE = NULL;
+PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE = NULL;
+
+PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE = NULL;
+PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE = NULL;
+PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE = NULL;
+
+PFNGLCLAMPCOLORARBPROC __glewClampColorARB = NULL;
+
+PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB = NULL;
+
+PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB = NULL;
+PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB = NULL;
+
+PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer = NULL;
+PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer = NULL;
+PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers = NULL;
+PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC __glewFramebufferTextureLayer = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D = NULL;
+PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers = NULL;
+PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers = NULL;
+PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv = NULL;
+PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer = NULL;
+PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample = NULL;
+
+PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB = NULL;
+PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB = NULL;
+PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB = NULL;
+
+PFNGLCOLORSUBTABLEPROC __glewColorSubTable = NULL;
+PFNGLCOLORTABLEPROC __glewColorTable = NULL;
+PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv = NULL;
+PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv = NULL;
+PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D = NULL;
+PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D = NULL;
+PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf = NULL;
+PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv = NULL;
+PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri = NULL;
+PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv = NULL;
+PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable = NULL;
+PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable = NULL;
+PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D = NULL;
+PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D = NULL;
+PFNGLGETCOLORTABLEPROC __glewGetColorTable = NULL;
+PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv = NULL;
+PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv = NULL;
+PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter = NULL;
+PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv = NULL;
+PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv = NULL;
+PFNGLGETHISTOGRAMPROC __glewGetHistogram = NULL;
+PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv = NULL;
+PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv = NULL;
+PFNGLGETMINMAXPROC __glewGetMinmax = NULL;
+PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv = NULL;
+PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv = NULL;
+PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter = NULL;
+PFNGLHISTOGRAMPROC __glewHistogram = NULL;
+PFNGLMINMAXPROC __glewMinmax = NULL;
+PFNGLRESETHISTOGRAMPROC __glewResetHistogram = NULL;
+PFNGLRESETMINMAXPROC __glewResetMinmax = NULL;
+PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D = NULL;
+
+PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB = NULL;
+
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange = NULL;
+PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange = NULL;
+
+PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB = NULL;
+PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB = NULL;
+PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB = NULL;
+PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB = NULL;
+PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB = NULL;
+
+PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB = NULL;
+
+PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB = NULL;
+PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB = NULL;
+PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB = NULL;
+PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB = NULL;
+PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB = NULL;
+PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB = NULL;
+PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB = NULL;
+PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB = NULL;
+PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB = NULL;
+PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB = NULL;
+PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB = NULL;
+PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB = NULL;
+PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB = NULL;
+PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB = NULL;
+PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB = NULL;
+PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB = NULL;
+PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB = NULL;
+PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB = NULL;
+PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB = NULL;
+PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB = NULL;
+PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB = NULL;
+PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB = NULL;
+PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB = NULL;
+PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB = NULL;
+PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB = NULL;
+PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB = NULL;
+PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB = NULL;
+PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB = NULL;
+PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB = NULL;
+PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB = NULL;
+PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB = NULL;
+PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB = NULL;
+PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB = NULL;
+PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB = NULL;
+
+PFNGLBEGINQUERYARBPROC __glewBeginQueryARB = NULL;
+PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB = NULL;
+PFNGLENDQUERYARBPROC __glewEndQueryARB = NULL;
+PFNGLGENQUERIESARBPROC __glewGenQueriesARB = NULL;
+PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB = NULL;
+PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB = NULL;
+PFNGLGETQUERYIVARBPROC __glewGetQueryivARB = NULL;
+PFNGLISQUERYARBPROC __glewIsQueryARB = NULL;
+
+PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB = NULL;
+PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB = NULL;
+
+PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB = NULL;
+PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB = NULL;
+PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB = NULL;
+PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB = NULL;
+PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB = NULL;
+PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB = NULL;
+PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB = NULL;
+PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB = NULL;
+PFNGLGETHANDLEARBPROC __glewGetHandleARB = NULL;
+PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB = NULL;
+PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB = NULL;
+PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB = NULL;
+PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB = NULL;
+PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB = NULL;
+PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB = NULL;
+PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB = NULL;
+PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB = NULL;
+PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB = NULL;
+PFNGLUNIFORM1FARBPROC __glewUniform1fARB = NULL;
+PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB = NULL;
+PFNGLUNIFORM1IARBPROC __glewUniform1iARB = NULL;
+PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB = NULL;
+PFNGLUNIFORM2FARBPROC __glewUniform2fARB = NULL;
+PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB = NULL;
+PFNGLUNIFORM2IARBPROC __glewUniform2iARB = NULL;
+PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB = NULL;
+PFNGLUNIFORM3FARBPROC __glewUniform3fARB = NULL;
+PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB = NULL;
+PFNGLUNIFORM3IARBPROC __glewUniform3iARB = NULL;
+PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB = NULL;
+PFNGLUNIFORM4FARBPROC __glewUniform4fARB = NULL;
+PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB = NULL;
+PFNGLUNIFORM4IARBPROC __glewUniform4iARB = NULL;
+PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB = NULL;
+PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB = NULL;
+PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB = NULL;
+PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB = NULL;
+PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB = NULL;
+PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB = NULL;
+
+PFNGLTEXBUFFERARBPROC __glewTexBufferARB = NULL;
+
+PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB = NULL;
+
+PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB = NULL;
+PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB = NULL;
+PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB = NULL;
+PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB = NULL;
+
+PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray = NULL;
+PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays = NULL;
+PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays = NULL;
+PFNGLISVERTEXARRAYPROC __glewIsVertexArray = NULL;
+
+PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB = NULL;
+PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB = NULL;
+PFNGLWEIGHTBVARBPROC __glewWeightbvARB = NULL;
+PFNGLWEIGHTDVARBPROC __glewWeightdvARB = NULL;
+PFNGLWEIGHTFVARBPROC __glewWeightfvARB = NULL;
+PFNGLWEIGHTIVARBPROC __glewWeightivARB = NULL;
+PFNGLWEIGHTSVARBPROC __glewWeightsvARB = NULL;
+PFNGLWEIGHTUBVARBPROC __glewWeightubvARB = NULL;
+PFNGLWEIGHTUIVARBPROC __glewWeightuivARB = NULL;
+PFNGLWEIGHTUSVARBPROC __glewWeightusvARB = NULL;
+
+PFNGLBINDBUFFERARBPROC __glewBindBufferARB = NULL;
+PFNGLBUFFERDATAARBPROC __glewBufferDataARB = NULL;
+PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB = NULL;
+PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB = NULL;
+PFNGLGENBUFFERSARBPROC __glewGenBuffersARB = NULL;
+PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB = NULL;
+PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB = NULL;
+PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB = NULL;
+PFNGLISBUFFERARBPROC __glewIsBufferARB = NULL;
+PFNGLMAPBUFFERARBPROC __glewMapBufferARB = NULL;
+PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB = NULL;
+
+PFNGLBINDPROGRAMARBPROC __glewBindProgramARB = NULL;
+PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB = NULL;
+PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB = NULL;
+PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB = NULL;
+PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB = NULL;
+PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB = NULL;
+PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB = NULL;
+PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB = NULL;
+PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB = NULL;
+PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB = NULL;
+PFNGLISPROGRAMARBPROC __glewIsProgramARB = NULL;
+PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB = NULL;
+PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB = NULL;
+PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB = NULL;
+PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB = NULL;
+PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB = NULL;
+PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB = NULL;
+PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB = NULL;
+PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB = NULL;
+PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB = NULL;
+PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB = NULL;
+PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB = NULL;
+PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB = NULL;
+PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB = NULL;
+PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB = NULL;
+PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB = NULL;
+PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB = NULL;
+PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB = NULL;
+PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB = NULL;
+PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB = NULL;
+PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB = NULL;
+PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB = NULL;
+PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB = NULL;
+PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB = NULL;
+PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB = NULL;
+PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB = NULL;
+PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB = NULL;
+PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB = NULL;
+PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB = NULL;
+PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB = NULL;
+PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB = NULL;
+PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB = NULL;
+PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB = NULL;
+PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB = NULL;
+PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB = NULL;
+PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB = NULL;
+PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB = NULL;
+PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB = NULL;
+PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB = NULL;
+PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB = NULL;
+PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB = NULL;
+
+PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB = NULL;
+PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB = NULL;
+PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB = NULL;
+
+PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB = NULL;
+PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB = NULL;
+PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB = NULL;
+PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB = NULL;
+PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB = NULL;
+PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB = NULL;
+PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB = NULL;
+PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB = NULL;
+PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB = NULL;
+PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB = NULL;
+PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB = NULL;
+PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB = NULL;
+PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB = NULL;
+PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB = NULL;
+PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB = NULL;
+PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB = NULL;
+
+PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI = NULL;
+
+PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI = NULL;
+PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI = NULL;
+PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI = NULL;
+
+PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI = NULL;
+PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI = NULL;
+PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI = NULL;
+PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI = NULL;
+
+PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI = NULL;
+PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI = NULL;
+PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI = NULL;
+PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI = NULL;
+PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI = NULL;
+PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI = NULL;
+PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI = NULL;
+PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI = NULL;
+PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI = NULL;
+PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI = NULL;
+PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI = NULL;
+PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI = NULL;
+PFNGLSAMPLEMAPATIPROC __glewSampleMapATI = NULL;
+PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI = NULL;
+
+PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI = NULL;
+PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI = NULL;
+
+PFNGLPNTRIANGLESFATIPROC __glPNTrianglewesfATI = NULL;
+PFNGLPNTRIANGLESIATIPROC __glPNTrianglewesiATI = NULL;
+
+PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI = NULL;
+PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI = NULL;
+
+PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI = NULL;
+PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI = NULL;
+PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI = NULL;
+PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI = NULL;
+PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI = NULL;
+PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI = NULL;
+PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI = NULL;
+PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI = NULL;
+PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI = NULL;
+PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI = NULL;
+PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI = NULL;
+PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI = NULL;
+
+PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI = NULL;
+PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI = NULL;
+PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI = NULL;
+
+PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI = NULL;
+PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI = NULL;
+PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI = NULL;
+PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI = NULL;
+PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI = NULL;
+PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI = NULL;
+PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI = NULL;
+PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI = NULL;
+PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI = NULL;
+PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI = NULL;
+PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI = NULL;
+PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI = NULL;
+PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI = NULL;
+PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI = NULL;
+PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI = NULL;
+PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI = NULL;
+PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI = NULL;
+PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI = NULL;
+PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI = NULL;
+PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI = NULL;
+PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI = NULL;
+PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI = NULL;
+PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI = NULL;
+PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI = NULL;
+PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI = NULL;
+PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI = NULL;
+PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI = NULL;
+PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI = NULL;
+PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI = NULL;
+PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI = NULL;
+PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI = NULL;
+PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI = NULL;
+PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI = NULL;
+PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI = NULL;
+PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI = NULL;
+PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI = NULL;
+PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI = NULL;
+
+PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT = NULL;
+PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT = NULL;
+PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT = NULL;
+
+PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT = NULL;
+
+PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT = NULL;
+
+PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT = NULL;
+
+PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT = NULL;
+
+PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT = NULL;
+PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT = NULL;
+
+PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT = NULL;
+PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT = NULL;
+
+PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT = NULL;
+PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT = NULL;
+PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT = NULL;
+PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT = NULL;
+PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT = NULL;
+PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT = NULL;
+PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT = NULL;
+PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT = NULL;
+PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT = NULL;
+PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT = NULL;
+
+PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT = NULL;
+PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT = NULL;
+
+PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT = NULL;
+PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT = NULL;
+PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT = NULL;
+PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT = NULL;
+PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT = NULL;
+
+PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT = NULL;
+PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT = NULL;
+
+PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT = NULL;
+
+PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT = NULL;
+PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT = NULL;
+PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT = NULL;
+PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT = NULL;
+PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT = NULL;
+PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT = NULL;
+PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT = NULL;
+PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT = NULL;
+PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT = NULL;
+PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT = NULL;
+PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT = NULL;
+PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT = NULL;
+PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT = NULL;
+PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT = NULL;
+PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT = NULL;
+PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT = NULL;
+PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT = NULL;
+PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT = NULL;
+PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT = NULL;
+PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT = NULL;
+PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT = NULL;
+PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT = NULL;
+PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT = NULL;
+PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT = NULL;
+PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT = NULL;
+PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT = NULL;
+PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT = NULL;
+PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT = NULL;
+PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT = NULL;
+PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT = NULL;
+PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT = NULL;
+PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT = NULL;
+PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT = NULL;
+PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT = NULL;
+PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT = NULL;
+PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT = NULL;
+PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT = NULL;
+PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT = NULL;
+PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT = NULL;
+PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT = NULL;
+PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT = NULL;
+PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT = NULL;
+PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT = NULL;
+PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT = NULL;
+PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT = NULL;
+PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT = NULL;
+PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT = NULL;
+PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT = NULL;
+PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT = NULL;
+PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT = NULL;
+PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT = NULL;
+PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT = NULL;
+PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT = NULL;
+PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT = NULL;
+PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT = NULL;
+PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT = NULL;
+PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT = NULL;
+PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT = NULL;
+PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT = NULL;
+PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT = NULL;
+PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT = NULL;
+PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT = NULL;
+PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT = NULL;
+PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT = NULL;
+PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT = NULL;
+PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT = NULL;
+PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT = NULL;
+PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT = NULL;
+PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT = NULL;
+PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT = NULL;
+PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT = NULL;
+PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT = NULL;
+PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT = NULL;
+PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT = NULL;
+PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT = NULL;
+PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT = NULL;
+PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT = NULL;
+PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT = NULL;
+PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT = NULL;
+PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT = NULL;
+PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT = NULL;
+PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT = NULL;
+PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT = NULL;
+PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT = NULL;
+PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT = NULL;
+PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT = NULL;
+PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT = NULL;
+PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT = NULL;
+PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT = NULL;
+PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT = NULL;
+PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT = NULL;
+PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT = NULL;
+PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT = NULL;
+PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT = NULL;
+PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT = NULL;
+PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT = NULL;
+PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT = NULL;
+PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT = NULL;
+PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT = NULL;
+PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT = NULL;
+PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT = NULL;
+PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT = NULL;
+PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT = NULL;
+PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT = NULL;
+PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT = NULL;
+PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT = NULL;
+PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT = NULL;
+PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT = NULL;
+PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT = NULL;
+PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT = NULL;
+PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT = NULL;
+PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT = NULL;
+PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT = NULL;
+PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT = NULL;
+PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT = NULL;
+PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT = NULL;
+PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT = NULL;
+PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT = NULL;
+PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT = NULL;
+PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT = NULL;
+PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT = NULL;
+PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT = NULL;
+PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT = NULL;
+PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT = NULL;
+PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT = NULL;
+PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT = NULL;
+PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT = NULL;
+PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT = NULL;
+PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT = NULL;
+PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT = NULL;
+PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT = NULL;
+PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT = NULL;
+PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT = NULL;
+PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT = NULL;
+PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT = NULL;
+PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT = NULL;
+PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT = NULL;
+PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT = NULL;
+
+PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT = NULL;
+PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT = NULL;
+PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT = NULL;
+PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT = NULL;
+PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT = NULL;
+PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT = NULL;
+
+PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT = NULL;
+PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT = NULL;
+
+PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT = NULL;
+
+PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT = NULL;
+PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT = NULL;
+PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT = NULL;
+PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT = NULL;
+PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT = NULL;
+
+PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT = NULL;
+PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT = NULL;
+PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT = NULL;
+PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT = NULL;
+PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT = NULL;
+PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT = NULL;
+PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT = NULL;
+PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT = NULL;
+PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT = NULL;
+PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT = NULL;
+PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT = NULL;
+PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT = NULL;
+PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT = NULL;
+PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT = NULL;
+PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT = NULL;
+PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT = NULL;
+PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT = NULL;
+PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT = NULL;
+
+PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT = NULL;
+
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT = NULL;
+
+PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT = NULL;
+PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT = NULL;
+PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT = NULL;
+PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT = NULL;
+PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT = NULL;
+PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT = NULL;
+PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT = NULL;
+
+PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT = NULL;
+PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT = NULL;
+PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT = NULL;
+
+PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT = NULL;
+PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT = NULL;
+
+PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT = NULL;
+PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT = NULL;
+PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT = NULL;
+PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT = NULL;
+PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT = NULL;
+PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT = NULL;
+PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT = NULL;
+PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT = NULL;
+PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT = NULL;
+PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT = NULL;
+PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT = NULL;
+PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT = NULL;
+PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT = NULL;
+PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT = NULL;
+PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT = NULL;
+PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT = NULL;
+PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT = NULL;
+PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT = NULL;
+PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT = NULL;
+PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT = NULL;
+PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT = NULL;
+PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT = NULL;
+PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT = NULL;
+PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT = NULL;
+PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT = NULL;
+PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT = NULL;
+PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT = NULL;
+PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT = NULL;
+PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT = NULL;
+PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT = NULL;
+PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT = NULL;
+PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT = NULL;
+PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT = NULL;
+PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT = NULL;
+
+PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT = NULL;
+PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT = NULL;
+PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT = NULL;
+PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT = NULL;
+PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT = NULL;
+PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT = NULL;
+PFNGLHISTOGRAMEXTPROC __glewHistogramEXT = NULL;
+PFNGLMINMAXEXTPROC __glewMinmaxEXT = NULL;
+PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT = NULL;
+PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT = NULL;
+
+PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT = NULL;
+
+PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT = NULL;
+
+PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT = NULL;
+PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT = NULL;
+PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT = NULL;
+
+PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT = NULL;
+PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT = NULL;
+
+PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT = NULL;
+PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT = NULL;
+
+PFNGLCOLORTABLEEXTPROC __glewColorTableEXT = NULL;
+PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT = NULL;
+PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT = NULL;
+PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT = NULL;
+
+PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT = NULL;
+PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT = NULL;
+PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT = NULL;
+
+PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT = NULL;
+PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT = NULL;
+
+PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT = NULL;
+
+PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT = NULL;
+PFNGLENDSCENEEXTPROC __glewEndSceneEXT = NULL;
+
+PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT = NULL;
+PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT = NULL;
+PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT = NULL;
+PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT = NULL;
+PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT = NULL;
+PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT = NULL;
+PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT = NULL;
+PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT = NULL;
+PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT = NULL;
+PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT = NULL;
+PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT = NULL;
+PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT = NULL;
+PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT = NULL;
+PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT = NULL;
+PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT = NULL;
+PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT = NULL;
+PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT = NULL;
+
+PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT = NULL;
+
+PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT = NULL;
+PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT = NULL;
+PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT = NULL;
+
+PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT = NULL;
+
+PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT = NULL;
+
+PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT = NULL;
+PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT = NULL;
+PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT = NULL;
+PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT = NULL;
+PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT = NULL;
+PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT = NULL;
+
+PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT = NULL;
+PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT = NULL;
+PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT = NULL;
+PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT = NULL;
+PFNGLISTEXTUREEXTPROC __glewIsTextureEXT = NULL;
+PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT = NULL;
+
+PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT = NULL;
+
+PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT = NULL;
+PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT = NULL;
+
+PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT = NULL;
+PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT = NULL;
+PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT = NULL;
+PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT = NULL;
+PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT = NULL;
+
+PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT = NULL;
+PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT = NULL;
+PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT = NULL;
+PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT = NULL;
+PFNGLGETPOINTERVEXTPROC __glewGetPointervEXT = NULL;
+PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT = NULL;
+PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT = NULL;
+PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT = NULL;
+PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT = NULL;
+
+PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT = NULL;
+PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT = NULL;
+PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT = NULL;
+PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT = NULL;
+PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT = NULL;
+PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT = NULL;
+PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT = NULL;
+PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT = NULL;
+PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT = NULL;
+PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT = NULL;
+PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT = NULL;
+PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT = NULL;
+PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT = NULL;
+PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT = NULL;
+PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT = NULL;
+PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT = NULL;
+PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT = NULL;
+PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT = NULL;
+PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT = NULL;
+PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT = NULL;
+PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT = NULL;
+PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT = NULL;
+PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT = NULL;
+PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT = NULL;
+PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT = NULL;
+PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT = NULL;
+PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT = NULL;
+PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT = NULL;
+PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT = NULL;
+PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT = NULL;
+PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT = NULL;
+PFNGLSWIZZLEEXTPROC __glewSwizzleEXT = NULL;
+PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT = NULL;
+PFNGLVARIANTBVEXTPROC __glewVariantbvEXT = NULL;
+PFNGLVARIANTDVEXTPROC __glewVariantdvEXT = NULL;
+PFNGLVARIANTFVEXTPROC __glewVariantfvEXT = NULL;
+PFNGLVARIANTIVEXTPROC __glewVariantivEXT = NULL;
+PFNGLVARIANTSVEXTPROC __glewVariantsvEXT = NULL;
+PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT = NULL;
+PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT = NULL;
+PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT = NULL;
+PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT = NULL;
+
+PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT = NULL;
+PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT = NULL;
+PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT = NULL;
+
+PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY = NULL;
+
+PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY = NULL;
+
+PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP = NULL;
+PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP = NULL;
+PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP = NULL;
+
+PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM = NULL;
+PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM = NULL;
+
+PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM = NULL;
+PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM = NULL;
+PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM = NULL;
+PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM = NULL;
+PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM = NULL;
+PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM = NULL;
+PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM = NULL;
+PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM = NULL;
+
+PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL = NULL;
+PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL = NULL;
+PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL = NULL;
+PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL = NULL;
+
+PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL = NULL;
+PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL = NULL;
+
+PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT = NULL;
+PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT = NULL;
+PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT = NULL;
+PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT = NULL;
+PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT = NULL;
+
+PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA = NULL;
+
+PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA = NULL;
+PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA = NULL;
+PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA = NULL;
+PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA = NULL;
+PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA = NULL;
+PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA = NULL;
+PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA = NULL;
+PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA = NULL;
+PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA = NULL;
+PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA = NULL;
+PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA = NULL;
+PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA = NULL;
+PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA = NULL;
+PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA = NULL;
+PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA = NULL;
+PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA = NULL;
+PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA = NULL;
+PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA = NULL;
+PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA = NULL;
+PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA = NULL;
+PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA = NULL;
+PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA = NULL;
+PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA = NULL;
+PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA = NULL;
+
+PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV = NULL;
+PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV = NULL;
+
+PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV = NULL;
+PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV = NULL;
+PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV = NULL;
+
+PFNGLEVALMAPSNVPROC __glewEvalMapsNV = NULL;
+PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV = NULL;
+PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV = NULL;
+PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV = NULL;
+PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV = NULL;
+PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV = NULL;
+PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV = NULL;
+PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV = NULL;
+PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV = NULL;
+
+PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV = NULL;
+PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV = NULL;
+PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV = NULL;
+
+PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV = NULL;
+PFNGLFINISHFENCENVPROC __glewFinishFenceNV = NULL;
+PFNGLGENFENCESNVPROC __glewGenFencesNV = NULL;
+PFNGLGETFENCEIVNVPROC __glewGetFenceivNV = NULL;
+PFNGLISFENCENVPROC __glewIsFenceNV = NULL;
+PFNGLSETFENCENVPROC __glewSetFenceNV = NULL;
+PFNGLTESTFENCENVPROC __glewTestFenceNV = NULL;
+
+PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV = NULL;
+PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV = NULL;
+PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV = NULL;
+
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV = NULL;
+
+PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV = NULL;
+
+PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV = NULL;
+PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV = NULL;
+PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV = NULL;
+PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV = NULL;
+PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV = NULL;
+
+PFNGLCOLOR3HNVPROC __glewColor3hNV = NULL;
+PFNGLCOLOR3HVNVPROC __glewColor3hvNV = NULL;
+PFNGLCOLOR4HNVPROC __glewColor4hNV = NULL;
+PFNGLCOLOR4HVNVPROC __glewColor4hvNV = NULL;
+PFNGLFOGCOORDHNVPROC __glewFogCoordhNV = NULL;
+PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV = NULL;
+PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV = NULL;
+PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV = NULL;
+PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV = NULL;
+PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV = NULL;
+PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV = NULL;
+PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV = NULL;
+PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV = NULL;
+PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV = NULL;
+PFNGLNORMAL3HNVPROC __glewNormal3hNV = NULL;
+PFNGLNORMAL3HVNVPROC __glewNormal3hvNV = NULL;
+PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV = NULL;
+PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV = NULL;
+PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV = NULL;
+PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV = NULL;
+PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV = NULL;
+PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV = NULL;
+PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV = NULL;
+PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV = NULL;
+PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV = NULL;
+PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV = NULL;
+PFNGLVERTEX2HNVPROC __glewVertex2hNV = NULL;
+PFNGLVERTEX2HVNVPROC __glewVertex2hvNV = NULL;
+PFNGLVERTEX3HNVPROC __glewVertex3hNV = NULL;
+PFNGLVERTEX3HVNVPROC __glewVertex3hvNV = NULL;
+PFNGLVERTEX4HNVPROC __glewVertex4hNV = NULL;
+PFNGLVERTEX4HVNVPROC __glewVertex4hvNV = NULL;
+PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV = NULL;
+PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV = NULL;
+PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV = NULL;
+PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV = NULL;
+PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV = NULL;
+PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV = NULL;
+PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV = NULL;
+PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV = NULL;
+PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV = NULL;
+PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV = NULL;
+PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV = NULL;
+PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV = NULL;
+PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV = NULL;
+PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV = NULL;
+
+PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV = NULL;
+PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV = NULL;
+PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV = NULL;
+PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV = NULL;
+PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV = NULL;
+PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV = NULL;
+PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV = NULL;
+
+PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV = NULL;
+PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV = NULL;
+PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV = NULL;
+
+PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV = NULL;
+PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV = NULL;
+
+PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV = NULL;
+PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV = NULL;
+
+PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV = NULL;
+PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV = NULL;
+PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV = NULL;
+PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV = NULL;
+PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV = NULL;
+PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV = NULL;
+PFNGLVIDEOPARAMETERIVNVPROC __glewVideoParameterivNV = NULL;
+
+PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV = NULL;
+PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV = NULL;
+
+PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV = NULL;
+PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV = NULL;
+PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV = NULL;
+PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV = NULL;
+PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV = NULL;
+PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV = NULL;
+PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV = NULL;
+PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV = NULL;
+PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV = NULL;
+PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV = NULL;
+PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV = NULL;
+PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV = NULL;
+PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV = NULL;
+
+PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV = NULL;
+PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV = NULL;
+
+PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV = NULL;
+PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV = NULL;
+PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV = NULL;
+PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV = NULL;
+PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV = NULL;
+PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV = NULL;
+PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV = NULL;
+PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV = NULL;
+
+PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV = NULL;
+PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV = NULL;
+
+PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV = NULL;
+PFNGLBINDPROGRAMNVPROC __glewBindProgramNV = NULL;
+PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV = NULL;
+PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV = NULL;
+PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV = NULL;
+PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV = NULL;
+PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV = NULL;
+PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV = NULL;
+PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV = NULL;
+PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV = NULL;
+PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV = NULL;
+PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV = NULL;
+PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV = NULL;
+PFNGLISPROGRAMNVPROC __glewIsProgramNV = NULL;
+PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV = NULL;
+PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV = NULL;
+PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV = NULL;
+PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV = NULL;
+PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV = NULL;
+PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV = NULL;
+PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV = NULL;
+PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV = NULL;
+PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV = NULL;
+PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV = NULL;
+PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV = NULL;
+PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV = NULL;
+PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV = NULL;
+PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV = NULL;
+PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV = NULL;
+PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV = NULL;
+PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV = NULL;
+PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV = NULL;
+PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV = NULL;
+PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV = NULL;
+PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV = NULL;
+PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV = NULL;
+PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV = NULL;
+PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV = NULL;
+PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV = NULL;
+PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV = NULL;
+PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV = NULL;
+PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV = NULL;
+PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV = NULL;
+PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV = NULL;
+PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV = NULL;
+PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV = NULL;
+PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV = NULL;
+PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV = NULL;
+PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV = NULL;
+PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV = NULL;
+PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV = NULL;
+PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV = NULL;
+PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV = NULL;
+PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV = NULL;
+PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV = NULL;
+PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV = NULL;
+PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV = NULL;
+PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV = NULL;
+PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV = NULL;
+PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV = NULL;
+PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV = NULL;
+PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV = NULL;
+PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV = NULL;
+
+PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES = NULL;
+PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES = NULL;
+PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES = NULL;
+PFNGLFRUSTUMFOESPROC __glewFrustumfOES = NULL;
+PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES = NULL;
+PFNGLORTHOFOESPROC __glewOrthofOES = NULL;
+
+PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS = NULL;
+PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS = NULL;
+
+PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS = NULL;
+PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS = NULL;
+
+PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS = NULL;
+PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS = NULL;
+
+PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS = NULL;
+PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS = NULL;
+
+PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS = NULL;
+PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS = NULL;
+
+PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS = NULL;
+PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS = NULL;
+
+PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX = NULL;
+PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX = NULL;
+PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX = NULL;
+PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX = NULL;
+PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX = NULL;
+PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX = NULL;
+
+PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX = NULL;
+
+PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX = NULL;
+
+PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX = NULL;
+PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX = NULL;
+PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX = NULL;
+PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX = NULL;
+PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX = NULL;
+PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX = NULL;
+PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX = NULL;
+PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX = NULL;
+PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX = NULL;
+PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX = NULL;
+PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX = NULL;
+PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX = NULL;
+PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX = NULL;
+PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX = NULL;
+
+PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX = NULL;
+
+PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX = NULL;
+
+PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX = NULL;
+
+PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX = NULL;
+PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX = NULL;
+PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX = NULL;
+PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX = NULL;
+
+PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX = NULL;
+
+PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI = NULL;
+PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI = NULL;
+PFNGLCOLORTABLESGIPROC __glewColorTableSGI = NULL;
+PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI = NULL;
+PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI = NULL;
+PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI = NULL;
+PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI = NULL;
+
+PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX = NULL;
+
+PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN = NULL;
+PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN = NULL;
+PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN = NULL;
+PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN = NULL;
+PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN = NULL;
+PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN = NULL;
+PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN = NULL;
+PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN = NULL;
+
+PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN = NULL;
+
+PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN = NULL;
+PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN = NULL;
+PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN = NULL;
+PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN = NULL;
+PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN = NULL;
+PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN = NULL;
+PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN = NULL;
+
+PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN = NULL;
+PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN = NULL;
+PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN = NULL;
+PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN = NULL;
+PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN = NULL;
+PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN = NULL;
+PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN = NULL;
+PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN = NULL;
+PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN = NULL;
+PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN = NULL;
+PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN = NULL;
+PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN = NULL;
+PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN = NULL;
+PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN = NULL;
+PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN = NULL;
+PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN = NULL;
+PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN = NULL;
+PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN = NULL;
+
+PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN = NULL;
+
+#endif /* !WIN32 || !GLEW_MX */
+
+#if !defined(GLEW_MX)
+
+GLboolean __GLEW_VERSION_1_1 = GL_FALSE;
+GLboolean __GLEW_VERSION_1_2 = GL_FALSE;
+GLboolean __GLEW_VERSION_1_3 = GL_FALSE;
+GLboolean __GLEW_VERSION_1_4 = GL_FALSE;
+GLboolean __GLEW_VERSION_1_5 = GL_FALSE;
+GLboolean __GLEW_VERSION_2_0 = GL_FALSE;
+GLboolean __GLEW_VERSION_2_1 = GL_FALSE;
+GLboolean __GLEW_VERSION_3_0 = GL_FALSE;
+GLboolean __GLEW_3DFX_multisample = GL_FALSE;
+GLboolean __GLEW_3DFX_tbuffer = GL_FALSE;
+GLboolean __GLEW_3DFX_texture_compression_FXT1 = GL_FALSE;
+GLboolean __GLEW_APPLE_client_storage = GL_FALSE;
+GLboolean __GLEW_APPLE_element_array = GL_FALSE;
+GLboolean __GLEW_APPLE_fence = GL_FALSE;
+GLboolean __GLEW_APPLE_float_pixels = GL_FALSE;
+GLboolean __GLEW_APPLE_flush_buffer_range = GL_FALSE;
+GLboolean __GLEW_APPLE_pixel_buffer = GL_FALSE;
+GLboolean __GLEW_APPLE_specular_vector = GL_FALSE;
+GLboolean __GLEW_APPLE_texture_range = GL_FALSE;
+GLboolean __GLEW_APPLE_transform_hint = GL_FALSE;
+GLboolean __GLEW_APPLE_vertex_array_object = GL_FALSE;
+GLboolean __GLEW_APPLE_vertex_array_range = GL_FALSE;
+GLboolean __GLEW_APPLE_ycbcr_422 = GL_FALSE;
+GLboolean __GLEW_ARB_color_buffer_float = GL_FALSE;
+GLboolean __GLEW_ARB_depth_buffer_float = GL_FALSE;
+GLboolean __GLEW_ARB_depth_texture = GL_FALSE;
+GLboolean __GLEW_ARB_draw_buffers = GL_FALSE;
+GLboolean __GLEW_ARB_draw_instanced = GL_FALSE;
+GLboolean __GLEW_ARB_fragment_program = GL_FALSE;
+GLboolean __GLEW_ARB_fragment_program_shadow = GL_FALSE;
+GLboolean __GLEW_ARB_fragment_shader = GL_FALSE;
+GLboolean __GLEW_ARB_framebuffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_framebuffer_sRGB = GL_FALSE;
+GLboolean __GLEW_ARB_geometry_shader4 = GL_FALSE;
+GLboolean __GLEW_ARB_half_float_pixel = GL_FALSE;
+GLboolean __GLEW_ARB_half_float_vertex = GL_FALSE;
+GLboolean __GLEW_ARB_imaging = GL_FALSE;
+GLboolean __GLEW_ARB_instanced_arrays = GL_FALSE;
+GLboolean __GLEW_ARB_map_buffer_range = GL_FALSE;
+GLboolean __GLEW_ARB_matrix_palette = GL_FALSE;
+GLboolean __GLEW_ARB_multisample = GL_FALSE;
+GLboolean __GLEW_ARB_multitexture = GL_FALSE;
+GLboolean __GLEW_ARB_occlusion_query = GL_FALSE;
+GLboolean __GLEW_ARB_pixel_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_point_parameters = GL_FALSE;
+GLboolean __GLEW_ARB_point_sprite = GL_FALSE;
+GLboolean __GLEW_ARB_shader_objects = GL_FALSE;
+GLboolean __GLEW_ARB_shading_language_100 = GL_FALSE;
+GLboolean __GLEW_ARB_shadow = GL_FALSE;
+GLboolean __GLEW_ARB_shadow_ambient = GL_FALSE;
+GLboolean __GLEW_ARB_texture_border_clamp = GL_FALSE;
+GLboolean __GLEW_ARB_texture_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_texture_compression = GL_FALSE;
+GLboolean __GLEW_ARB_texture_compression_rgtc = GL_FALSE;
+GLboolean __GLEW_ARB_texture_cube_map = GL_FALSE;
+GLboolean __GLEW_ARB_texture_env_add = GL_FALSE;
+GLboolean __GLEW_ARB_texture_env_combine = GL_FALSE;
+GLboolean __GLEW_ARB_texture_env_crossbar = GL_FALSE;
+GLboolean __GLEW_ARB_texture_env_dot3 = GL_FALSE;
+GLboolean __GLEW_ARB_texture_float = GL_FALSE;
+GLboolean __GLEW_ARB_texture_mirrored_repeat = GL_FALSE;
+GLboolean __GLEW_ARB_texture_non_power_of_two = GL_FALSE;
+GLboolean __GLEW_ARB_texture_rectangle = GL_FALSE;
+GLboolean __GLEW_ARB_texture_rg = GL_FALSE;
+GLboolean __GLEW_ARB_transpose_matrix = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_array_object = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_blend = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_buffer_object = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_program = GL_FALSE;
+GLboolean __GLEW_ARB_vertex_shader = GL_FALSE;
+GLboolean __GLEW_ARB_window_pos = GL_FALSE;
+GLboolean __GLEW_ATIX_point_sprites = GL_FALSE;
+GLboolean __GLEW_ATIX_texture_env_combine3 = GL_FALSE;
+GLboolean __GLEW_ATIX_texture_env_route = GL_FALSE;
+GLboolean __GLEW_ATIX_vertex_shader_output_point_size = GL_FALSE;
+GLboolean __GLEW_ATI_draw_buffers = GL_FALSE;
+GLboolean __GLEW_ATI_element_array = GL_FALSE;
+GLboolean __GLEW_ATI_envmap_bumpmap = GL_FALSE;
+GLboolean __GLEW_ATI_fragment_shader = GL_FALSE;
+GLboolean __GLEW_ATI_map_object_buffer = GL_FALSE;
+GLboolean __GLEW_ATI_pn_triangles = GL_FALSE;
+GLboolean __GLEW_ATI_separate_stencil = GL_FALSE;
+GLboolean __GLEW_ATI_shader_texture_lod = GL_FALSE;
+GLboolean __GLEW_ATI_text_fragment_shader = GL_FALSE;
+GLboolean __GLEW_ATI_texture_compression_3dc = GL_FALSE;
+GLboolean __GLEW_ATI_texture_env_combine3 = GL_FALSE;
+GLboolean __GLEW_ATI_texture_float = GL_FALSE;
+GLboolean __GLEW_ATI_texture_mirror_once = GL_FALSE;
+GLboolean __GLEW_ATI_vertex_array_object = GL_FALSE;
+GLboolean __GLEW_ATI_vertex_attrib_array_object = GL_FALSE;
+GLboolean __GLEW_ATI_vertex_streams = GL_FALSE;
+GLboolean __GLEW_EXT_422_pixels = GL_FALSE;
+GLboolean __GLEW_EXT_Cg_shader = GL_FALSE;
+GLboolean __GLEW_EXT_abgr = GL_FALSE;
+GLboolean __GLEW_EXT_bgra = GL_FALSE;
+GLboolean __GLEW_EXT_bindable_uniform = GL_FALSE;
+GLboolean __GLEW_EXT_blend_color = GL_FALSE;
+GLboolean __GLEW_EXT_blend_equation_separate = GL_FALSE;
+GLboolean __GLEW_EXT_blend_func_separate = GL_FALSE;
+GLboolean __GLEW_EXT_blend_logic_op = GL_FALSE;
+GLboolean __GLEW_EXT_blend_minmax = GL_FALSE;
+GLboolean __GLEW_EXT_blend_subtract = GL_FALSE;
+GLboolean __GLEW_EXT_clip_volume_hint = GL_FALSE;
+GLboolean __GLEW_EXT_cmyka = GL_FALSE;
+GLboolean __GLEW_EXT_color_subtable = GL_FALSE;
+GLboolean __GLEW_EXT_compiled_vertex_array = GL_FALSE;
+GLboolean __GLEW_EXT_convolution = GL_FALSE;
+GLboolean __GLEW_EXT_coordinate_frame = GL_FALSE;
+GLboolean __GLEW_EXT_copy_texture = GL_FALSE;
+GLboolean __GLEW_EXT_cull_vertex = GL_FALSE;
+GLboolean __GLEW_EXT_depth_bounds_test = GL_FALSE;
+GLboolean __GLEW_EXT_direct_state_access = GL_FALSE;
+GLboolean __GLEW_EXT_draw_buffers2 = GL_FALSE;
+GLboolean __GLEW_EXT_draw_instanced = GL_FALSE;
+GLboolean __GLEW_EXT_draw_range_elements = GL_FALSE;
+GLboolean __GLEW_EXT_fog_coord = GL_FALSE;
+GLboolean __GLEW_EXT_fragment_lighting = GL_FALSE;
+GLboolean __GLEW_EXT_framebuffer_blit = GL_FALSE;
+GLboolean __GLEW_EXT_framebuffer_multisample = GL_FALSE;
+GLboolean __GLEW_EXT_framebuffer_object = GL_FALSE;
+GLboolean __GLEW_EXT_framebuffer_sRGB = GL_FALSE;
+GLboolean __GLEW_EXT_geometry_shader4 = GL_FALSE;
+GLboolean __GLEW_EXT_gpu_program_parameters = GL_FALSE;
+GLboolean __GLEW_EXT_gpu_shader4 = GL_FALSE;
+GLboolean __GLEW_EXT_histogram = GL_FALSE;
+GLboolean __GLEW_EXT_index_array_formats = GL_FALSE;
+GLboolean __GLEW_EXT_index_func = GL_FALSE;
+GLboolean __GLEW_EXT_index_material = GL_FALSE;
+GLboolean __GLEW_EXT_index_texture = GL_FALSE;
+GLboolean __GLEW_EXT_light_texture = GL_FALSE;
+GLboolean __GLEW_EXT_misc_attribute = GL_FALSE;
+GLboolean __GLEW_EXT_multi_draw_arrays = GL_FALSE;
+GLboolean __GLEW_EXT_multisample = GL_FALSE;
+GLboolean __GLEW_EXT_packed_depth_stencil = GL_FALSE;
+GLboolean __GLEW_EXT_packed_float = GL_FALSE;
+GLboolean __GLEW_EXT_packed_pixels = GL_FALSE;
+GLboolean __GLEW_EXT_paletted_texture = GL_FALSE;
+GLboolean __GLEW_EXT_pixel_buffer_object = GL_FALSE;
+GLboolean __GLEW_EXT_pixel_transform = GL_FALSE;
+GLboolean __GLEW_EXT_pixel_transform_color_table = GL_FALSE;
+GLboolean __GLEW_EXT_point_parameters = GL_FALSE;
+GLboolean __GLEW_EXT_polygon_offset = GL_FALSE;
+GLboolean __GLEW_EXT_rescale_normal = GL_FALSE;
+GLboolean __GLEW_EXT_scene_marker = GL_FALSE;
+GLboolean __GLEW_EXT_secondary_color = GL_FALSE;
+GLboolean __GLEW_EXT_separate_specular_color = GL_FALSE;
+GLboolean __GLEW_EXT_shadow_funcs = GL_FALSE;
+GLboolean __GLEW_EXT_shared_texture_palette = GL_FALSE;
+GLboolean __GLEW_EXT_stencil_clear_tag = GL_FALSE;
+GLboolean __GLEW_EXT_stencil_two_side = GL_FALSE;
+GLboolean __GLEW_EXT_stencil_wrap = GL_FALSE;
+GLboolean __GLEW_EXT_subtexture = GL_FALSE;
+GLboolean __GLEW_EXT_texture = GL_FALSE;
+GLboolean __GLEW_EXT_texture3D = GL_FALSE;
+GLboolean __GLEW_EXT_texture_array = GL_FALSE;
+GLboolean __GLEW_EXT_texture_buffer_object = GL_FALSE;
+GLboolean __GLEW_EXT_texture_compression_dxt1 = GL_FALSE;
+GLboolean __GLEW_EXT_texture_compression_latc = GL_FALSE;
+GLboolean __GLEW_EXT_texture_compression_rgtc = GL_FALSE;
+GLboolean __GLEW_EXT_texture_compression_s3tc = GL_FALSE;
+GLboolean __GLEW_EXT_texture_cube_map = GL_FALSE;
+GLboolean __GLEW_EXT_texture_edge_clamp = GL_FALSE;
+GLboolean __GLEW_EXT_texture_env = GL_FALSE;
+GLboolean __GLEW_EXT_texture_env_add = GL_FALSE;
+GLboolean __GLEW_EXT_texture_env_combine = GL_FALSE;
+GLboolean __GLEW_EXT_texture_env_dot3 = GL_FALSE;
+GLboolean __GLEW_EXT_texture_filter_anisotropic = GL_FALSE;
+GLboolean __GLEW_EXT_texture_integer = GL_FALSE;
+GLboolean __GLEW_EXT_texture_lod_bias = GL_FALSE;
+GLboolean __GLEW_EXT_texture_mirror_clamp = GL_FALSE;
+GLboolean __GLEW_EXT_texture_object = GL_FALSE;
+GLboolean __GLEW_EXT_texture_perturb_normal = GL_FALSE;
+GLboolean __GLEW_EXT_texture_rectangle = GL_FALSE;
+GLboolean __GLEW_EXT_texture_sRGB = GL_FALSE;
+GLboolean __GLEW_EXT_texture_shared_exponent = GL_FALSE;
+GLboolean __GLEW_EXT_texture_swizzle = GL_FALSE;
+GLboolean __GLEW_EXT_timer_query = GL_FALSE;
+GLboolean __GLEW_EXT_transform_feedback = GL_FALSE;
+GLboolean __GLEW_EXT_vertex_array = GL_FALSE;
+GLboolean __GLEW_EXT_vertex_array_bgra = GL_FALSE;
+GLboolean __GLEW_EXT_vertex_shader = GL_FALSE;
+GLboolean __GLEW_EXT_vertex_weighting = GL_FALSE;
+GLboolean __GLEW_GREMEDY_frame_terminator = GL_FALSE;
+GLboolean __GLEW_GREMEDY_string_marker = GL_FALSE;
+GLboolean __GLEW_HP_convolution_border_modes = GL_FALSE;
+GLboolean __GLEW_HP_image_transform = GL_FALSE;
+GLboolean __GLEW_HP_occlusion_test = GL_FALSE;
+GLboolean __GLEW_HP_texture_lighting = GL_FALSE;
+GLboolean __GLEW_IBM_cull_vertex = GL_FALSE;
+GLboolean __GLEW_IBM_multimode_draw_arrays = GL_FALSE;
+GLboolean __GLEW_IBM_rasterpos_clip = GL_FALSE;
+GLboolean __GLEW_IBM_static_data = GL_FALSE;
+GLboolean __GLEW_IBM_texture_mirrored_repeat = GL_FALSE;
+GLboolean __GLEW_IBM_vertex_array_lists = GL_FALSE;
+GLboolean __GLEW_INGR_color_clamp = GL_FALSE;
+GLboolean __GLEW_INGR_interlace_read = GL_FALSE;
+GLboolean __GLEW_INTEL_parallel_arrays = GL_FALSE;
+GLboolean __GLEW_INTEL_texture_scissor = GL_FALSE;
+GLboolean __GLEW_KTX_buffer_region = GL_FALSE;
+GLboolean __GLEW_MESAX_texture_stack = GL_FALSE;
+GLboolean __GLEW_MESA_pack_invert = GL_FALSE;
+GLboolean __GLEW_MESA_resize_buffers = GL_FALSE;
+GLboolean __GLEW_MESA_window_pos = GL_FALSE;
+GLboolean __GLEW_MESA_ycbcr_texture = GL_FALSE;
+GLboolean __GLEW_NV_blend_square = GL_FALSE;
+GLboolean __GLEW_NV_conditional_render = GL_FALSE;
+GLboolean __GLEW_NV_copy_depth_to_color = GL_FALSE;
+GLboolean __GLEW_NV_depth_buffer_float = GL_FALSE;
+GLboolean __GLEW_NV_depth_clamp = GL_FALSE;
+GLboolean __GLEW_NV_depth_range_unclamped = GL_FALSE;
+GLboolean __GLEW_NV_evaluators = GL_FALSE;
+GLboolean __GLEW_NV_explicit_multisample = GL_FALSE;
+GLboolean __GLEW_NV_fence = GL_FALSE;
+GLboolean __GLEW_NV_float_buffer = GL_FALSE;
+GLboolean __GLEW_NV_fog_distance = GL_FALSE;
+GLboolean __GLEW_NV_fragment_program = GL_FALSE;
+GLboolean __GLEW_NV_fragment_program2 = GL_FALSE;
+GLboolean __GLEW_NV_fragment_program4 = GL_FALSE;
+GLboolean __GLEW_NV_fragment_program_option = GL_FALSE;
+GLboolean __GLEW_NV_framebuffer_multisample_coverage = GL_FALSE;
+GLboolean __GLEW_NV_geometry_program4 = GL_FALSE;
+GLboolean __GLEW_NV_geometry_shader4 = GL_FALSE;
+GLboolean __GLEW_NV_gpu_program4 = GL_FALSE;
+GLboolean __GLEW_NV_half_float = GL_FALSE;
+GLboolean __GLEW_NV_light_max_exponent = GL_FALSE;
+GLboolean __GLEW_NV_multisample_filter_hint = GL_FALSE;
+GLboolean __GLEW_NV_occlusion_query = GL_FALSE;
+GLboolean __GLEW_NV_packed_depth_stencil = GL_FALSE;
+GLboolean __GLEW_NV_parameter_buffer_object = GL_FALSE;
+GLboolean __GLEW_NV_pixel_data_range = GL_FALSE;
+GLboolean __GLEW_NV_point_sprite = GL_FALSE;
+GLboolean __GLEW_NV_present_video = GL_FALSE;
+GLboolean __GLEW_NV_primitive_restart = GL_FALSE;
+GLboolean __GLEW_NV_register_combiners = GL_FALSE;
+GLboolean __GLEW_NV_register_combiners2 = GL_FALSE;
+GLboolean __GLEW_NV_texgen_emboss = GL_FALSE;
+GLboolean __GLEW_NV_texgen_reflection = GL_FALSE;
+GLboolean __GLEW_NV_texture_compression_vtc = GL_FALSE;
+GLboolean __GLEW_NV_texture_env_combine4 = GL_FALSE;
+GLboolean __GLEW_NV_texture_expand_normal = GL_FALSE;
+GLboolean __GLEW_NV_texture_rectangle = GL_FALSE;
+GLboolean __GLEW_NV_texture_shader = GL_FALSE;
+GLboolean __GLEW_NV_texture_shader2 = GL_FALSE;
+GLboolean __GLEW_NV_texture_shader3 = GL_FALSE;
+GLboolean __GLEW_NV_transform_feedback = GL_FALSE;
+GLboolean __GLEW_NV_vertex_array_range = GL_FALSE;
+GLboolean __GLEW_NV_vertex_array_range2 = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program1_1 = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program2 = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program2_option = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program3 = GL_FALSE;
+GLboolean __GLEW_NV_vertex_program4 = GL_FALSE;
+GLboolean __GLEW_OES_byte_coordinates = GL_FALSE;
+GLboolean __GLEW_OES_compressed_paletted_texture = GL_FALSE;
+GLboolean __GLEW_OES_read_format = GL_FALSE;
+GLboolean __GLEW_OES_single_precision = GL_FALSE;
+GLboolean __GLEW_OML_interlace = GL_FALSE;
+GLboolean __GLEW_OML_resample = GL_FALSE;
+GLboolean __GLEW_OML_subsample = GL_FALSE;
+GLboolean __GLEW_PGI_misc_hints = GL_FALSE;
+GLboolean __GLEW_PGI_vertex_hints = GL_FALSE;
+GLboolean __GLEW_REND_screen_coordinates = GL_FALSE;
+GLboolean __GLEW_S3_s3tc = GL_FALSE;
+GLboolean __GLEW_SGIS_color_range = GL_FALSE;
+GLboolean __GLEW_SGIS_detail_texture = GL_FALSE;
+GLboolean __GLEW_SGIS_fog_function = GL_FALSE;
+GLboolean __GLEW_SGIS_generate_mipmap = GL_FALSE;
+GLboolean __GLEW_SGIS_multisample = GL_FALSE;
+GLboolean __GLEW_SGIS_pixel_texture = GL_FALSE;
+GLboolean __GLEW_SGIS_point_line_texgen = GL_FALSE;
+GLboolean __GLEW_SGIS_sharpen_texture = GL_FALSE;
+GLboolean __GLEW_SGIS_texture4D = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_border_clamp = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_edge_clamp = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_filter4 = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_lod = GL_FALSE;
+GLboolean __GLEW_SGIS_texture_select = GL_FALSE;
+GLboolean __GLEW_SGIX_async = GL_FALSE;
+GLboolean __GLEW_SGIX_async_histogram = GL_FALSE;
+GLboolean __GLEW_SGIX_async_pixel = GL_FALSE;
+GLboolean __GLEW_SGIX_blend_alpha_minmax = GL_FALSE;
+GLboolean __GLEW_SGIX_clipmap = GL_FALSE;
+GLboolean __GLEW_SGIX_convolution_accuracy = GL_FALSE;
+GLboolean __GLEW_SGIX_depth_texture = GL_FALSE;
+GLboolean __GLEW_SGIX_flush_raster = GL_FALSE;
+GLboolean __GLEW_SGIX_fog_offset = GL_FALSE;
+GLboolean __GLEW_SGIX_fog_texture = GL_FALSE;
+GLboolean __GLEW_SGIX_fragment_specular_lighting = GL_FALSE;
+GLboolean __GLEW_SGIX_framezoom = GL_FALSE;
+GLboolean __GLEW_SGIX_interlace = GL_FALSE;
+GLboolean __GLEW_SGIX_ir_instrument1 = GL_FALSE;
+GLboolean __GLEW_SGIX_list_priority = GL_FALSE;
+GLboolean __GLEW_SGIX_pixel_texture = GL_FALSE;
+GLboolean __GLEW_SGIX_pixel_texture_bits = GL_FALSE;
+GLboolean __GLEW_SGIX_reference_plane = GL_FALSE;
+GLboolean __GLEW_SGIX_resample = GL_FALSE;
+GLboolean __GLEW_SGIX_shadow = GL_FALSE;
+GLboolean __GLEW_SGIX_shadow_ambient = GL_FALSE;
+GLboolean __GLEW_SGIX_sprite = GL_FALSE;
+GLboolean __GLEW_SGIX_tag_sample_buffer = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_add_env = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_coordinate_clamp = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_lod_bias = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_multi_buffer = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_range = GL_FALSE;
+GLboolean __GLEW_SGIX_texture_scale_bias = GL_FALSE;
+GLboolean __GLEW_SGIX_vertex_preclip = GL_FALSE;
+GLboolean __GLEW_SGIX_vertex_preclip_hint = GL_FALSE;
+GLboolean __GLEW_SGIX_ycrcb = GL_FALSE;
+GLboolean __GLEW_SGI_color_matrix = GL_FALSE;
+GLboolean __GLEW_SGI_color_table = GL_FALSE;
+GLboolean __GLEW_SGI_texture_color_table = GL_FALSE;
+GLboolean __GLEW_SUNX_constant_data = GL_FALSE;
+GLboolean __GLEW_SUN_convolution_border_modes = GL_FALSE;
+GLboolean __GLEW_SUN_global_alpha = GL_FALSE;
+GLboolean __GLEW_SUN_mesh_array = GL_FALSE;
+GLboolean __GLEW_SUN_read_video_pixels = GL_FALSE;
+GLboolean __GLEW_SUN_slice_accum = GL_FALSE;
+GLboolean __GLEW_SUN_triangle_list = GL_FALSE;
+GLboolean __GLEW_SUN_vertex = GL_FALSE;
+GLboolean __GLEW_WIN_phong_shading = GL_FALSE;
+GLboolean __GLEW_WIN_specular_fog = GL_FALSE;
+GLboolean __GLEW_WIN_swap_hint = GL_FALSE;
+
+#endif /* !GLEW_MX */
+
+#ifdef GL_VERSION_1_2
+
+static GLboolean _glewInit_GL_VERSION_1_2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3D")) == NULL) || r;
+ r = ((glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElements")) == NULL) || r;
+ r = ((glTexImage3D = (PFNGLTEXIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexImage3D")) == NULL) || r;
+ r = ((glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_1_2 */
+
+#ifdef GL_VERSION_1_3
+
+static GLboolean _glewInit_GL_VERSION_1_3 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveTexture = (PFNGLACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glActiveTexture")) == NULL) || r;
+ r = ((glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glClientActiveTexture")) == NULL) || r;
+ r = ((glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage1D")) == NULL) || r;
+ r = ((glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage2D")) == NULL) || r;
+ r = ((glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3D")) == NULL) || r;
+ r = ((glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage1D")) == NULL) || r;
+ r = ((glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage2D")) == NULL) || r;
+ r = ((glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3D")) == NULL) || r;
+ r = ((glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTexImage")) == NULL) || r;
+ r = ((glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixd")) == NULL) || r;
+ r = ((glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixf")) == NULL) || r;
+ r = ((glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixd")) == NULL) || r;
+ r = ((glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixf")) == NULL) || r;
+ r = ((glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1d")) == NULL) || r;
+ r = ((glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dv")) == NULL) || r;
+ r = ((glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1f")) == NULL) || r;
+ r = ((glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fv")) == NULL) || r;
+ r = ((glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1i")) == NULL) || r;
+ r = ((glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1iv")) == NULL) || r;
+ r = ((glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1s")) == NULL) || r;
+ r = ((glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1sv")) == NULL) || r;
+ r = ((glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2d")) == NULL) || r;
+ r = ((glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dv")) == NULL) || r;
+ r = ((glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2f")) == NULL) || r;
+ r = ((glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fv")) == NULL) || r;
+ r = ((glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2i")) == NULL) || r;
+ r = ((glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2iv")) == NULL) || r;
+ r = ((glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2s")) == NULL) || r;
+ r = ((glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2sv")) == NULL) || r;
+ r = ((glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3d")) == NULL) || r;
+ r = ((glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dv")) == NULL) || r;
+ r = ((glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3f")) == NULL) || r;
+ r = ((glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fv")) == NULL) || r;
+ r = ((glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3i")) == NULL) || r;
+ r = ((glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3iv")) == NULL) || r;
+ r = ((glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3s")) == NULL) || r;
+ r = ((glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3sv")) == NULL) || r;
+ r = ((glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4d")) == NULL) || r;
+ r = ((glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dv")) == NULL) || r;
+ r = ((glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4f")) == NULL) || r;
+ r = ((glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fv")) == NULL) || r;
+ r = ((glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4i")) == NULL) || r;
+ r = ((glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4iv")) == NULL) || r;
+ r = ((glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4s")) == NULL) || r;
+ r = ((glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4sv")) == NULL) || r;
+ r = ((glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)glewGetProcAddress((const GLubyte*)"glSampleCoverage")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_1_3 */
+
+#ifdef GL_VERSION_1_4
+
+static GLboolean _glewInit_GL_VERSION_1_4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendColor = (PFNGLBLENDCOLORPROC)glewGetProcAddress((const GLubyte*)"glBlendColor")) == NULL) || r;
+ r = ((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)"glBlendEquation")) == NULL) || r;
+ r = ((glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparate")) == NULL) || r;
+ r = ((glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointer")) == NULL) || r;
+ r = ((glFogCoordd = (PFNGLFOGCOORDDPROC)glewGetProcAddress((const GLubyte*)"glFogCoordd")) == NULL) || r;
+ r = ((glFogCoorddv = (PFNGLFOGCOORDDVPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddv")) == NULL) || r;
+ r = ((glFogCoordf = (PFNGLFOGCOORDFPROC)glewGetProcAddress((const GLubyte*)"glFogCoordf")) == NULL) || r;
+ r = ((glFogCoordfv = (PFNGLFOGCOORDFVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfv")) == NULL) || r;
+ r = ((glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArrays")) == NULL) || r;
+ r = ((glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElements")) == NULL) || r;
+ r = ((glPointParameterf = (PFNGLPOINTPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glPointParameterf")) == NULL) || r;
+ r = ((glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfv")) == NULL) || r;
+ r = ((glPointParameteri = (PFNGLPOINTPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glPointParameteri")) == NULL) || r;
+ r = ((glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glPointParameteriv")) == NULL) || r;
+ r = ((glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3b")) == NULL) || r;
+ r = ((glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bv")) == NULL) || r;
+ r = ((glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3d")) == NULL) || r;
+ r = ((glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dv")) == NULL) || r;
+ r = ((glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3f")) == NULL) || r;
+ r = ((glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fv")) == NULL) || r;
+ r = ((glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3i")) == NULL) || r;
+ r = ((glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3iv")) == NULL) || r;
+ r = ((glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3s")) == NULL) || r;
+ r = ((glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3sv")) == NULL) || r;
+ r = ((glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ub")) == NULL) || r;
+ r = ((glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubv")) == NULL) || r;
+ r = ((glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ui")) == NULL) || r;
+ r = ((glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uiv")) == NULL) || r;
+ r = ((glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3us")) == NULL) || r;
+ r = ((glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usv")) == NULL) || r;
+ r = ((glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointer")) == NULL) || r;
+ r = ((glWindowPos2d = (PFNGLWINDOWPOS2DPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2d")) == NULL) || r;
+ r = ((glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dv")) == NULL) || r;
+ r = ((glWindowPos2f = (PFNGLWINDOWPOS2FPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2f")) == NULL) || r;
+ r = ((glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fv")) == NULL) || r;
+ r = ((glWindowPos2i = (PFNGLWINDOWPOS2IPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2i")) == NULL) || r;
+ r = ((glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iv")) == NULL) || r;
+ r = ((glWindowPos2s = (PFNGLWINDOWPOS2SPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2s")) == NULL) || r;
+ r = ((glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sv")) == NULL) || r;
+ r = ((glWindowPos3d = (PFNGLWINDOWPOS3DPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3d")) == NULL) || r;
+ r = ((glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dv")) == NULL) || r;
+ r = ((glWindowPos3f = (PFNGLWINDOWPOS3FPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3f")) == NULL) || r;
+ r = ((glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fv")) == NULL) || r;
+ r = ((glWindowPos3i = (PFNGLWINDOWPOS3IPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3i")) == NULL) || r;
+ r = ((glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iv")) == NULL) || r;
+ r = ((glWindowPos3s = (PFNGLWINDOWPOS3SPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3s")) == NULL) || r;
+ r = ((glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_1_4 */
+
+#ifdef GL_VERSION_1_5
+
+static GLboolean _glewInit_GL_VERSION_1_5 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginQuery = (PFNGLBEGINQUERYPROC)glewGetProcAddress((const GLubyte*)"glBeginQuery")) == NULL) || r;
+ r = ((glBindBuffer = (PFNGLBINDBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindBuffer")) == NULL) || r;
+ r = ((glBufferData = (PFNGLBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferData")) == NULL) || r;
+ r = ((glBufferSubData = (PFNGLBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferSubData")) == NULL) || r;
+ r = ((glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffers")) == NULL) || r;
+ r = ((glDeleteQueries = (PFNGLDELETEQUERIESPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueries")) == NULL) || r;
+ r = ((glEndQuery = (PFNGLENDQUERYPROC)glewGetProcAddress((const GLubyte*)"glEndQuery")) == NULL) || r;
+ r = ((glGenBuffers = (PFNGLGENBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenBuffers")) == NULL) || r;
+ r = ((glGenQueries = (PFNGLGENQUERIESPROC)glewGetProcAddress((const GLubyte*)"glGenQueries")) == NULL) || r;
+ r = ((glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameteriv")) == NULL) || r;
+ r = ((glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferPointerv")) == NULL) || r;
+ r = ((glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glGetBufferSubData")) == NULL) || r;
+ r = ((glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectiv")) == NULL) || r;
+ r = ((glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuiv")) == NULL) || r;
+ r = ((glGetQueryiv = (PFNGLGETQUERYIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryiv")) == NULL) || r;
+ r = ((glIsBuffer = (PFNGLISBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsBuffer")) == NULL) || r;
+ r = ((glIsQuery = (PFNGLISQUERYPROC)glewGetProcAddress((const GLubyte*)"glIsQuery")) == NULL) || r;
+ r = ((glMapBuffer = (PFNGLMAPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glMapBuffer")) == NULL) || r;
+ r = ((glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glUnmapBuffer")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_1_5 */
+
+#ifdef GL_VERSION_2_0
+
+static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r;
+ r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r;
+ r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r;
+ r = ((glCompileShader = (PFNGLCOMPILESHADERPROC)glewGetProcAddress((const GLubyte*)"glCompileShader")) == NULL) || r;
+ r = ((glCreateProgram = (PFNGLCREATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glCreateProgram")) == NULL) || r;
+ r = ((glCreateShader = (PFNGLCREATESHADERPROC)glewGetProcAddress((const GLubyte*)"glCreateShader")) == NULL) || r;
+ r = ((glDeleteProgram = (PFNGLDELETEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgram")) == NULL) || r;
+ r = ((glDeleteShader = (PFNGLDELETESHADERPROC)glewGetProcAddress((const GLubyte*)"glDeleteShader")) == NULL) || r;
+ r = ((glDetachShader = (PFNGLDETACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glDetachShader")) == NULL) || r;
+ r = ((glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribArray")) == NULL) || r;
+ r = ((glDrawBuffers = (PFNGLDRAWBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffers")) == NULL) || r;
+ r = ((glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribArray")) == NULL) || r;
+ r = ((glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAttrib")) == NULL) || r;
+ r = ((glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniform")) == NULL) || r;
+ r = ((glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)glewGetProcAddress((const GLubyte*)"glGetAttachedShaders")) == NULL) || r;
+ r = ((glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetAttribLocation")) == NULL) || r;
+ r = ((glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetProgramInfoLog")) == NULL) || r;
+ r = ((glGetProgramiv = (PFNGLGETPROGRAMIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramiv")) == NULL) || r;
+ r = ((glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetShaderInfoLog")) == NULL) || r;
+ r = ((glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glGetShaderSource")) == NULL) || r;
+ r = ((glGetShaderiv = (PFNGLGETSHADERIVPROC)glewGetProcAddress((const GLubyte*)"glGetShaderiv")) == NULL) || r;
+ r = ((glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetUniformLocation")) == NULL) || r;
+ r = ((glGetUniformfv = (PFNGLGETUNIFORMFVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformfv")) == NULL) || r;
+ r = ((glGetUniformiv = (PFNGLGETUNIFORMIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformiv")) == NULL) || r;
+ r = ((glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointerv")) == NULL) || r;
+ r = ((glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdv")) == NULL) || r;
+ r = ((glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfv")) == NULL) || r;
+ r = ((glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribiv")) == NULL) || r;
+ r = ((glIsProgram = (PFNGLISPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glIsProgram")) == NULL) || r;
+ r = ((glIsShader = (PFNGLISSHADERPROC)glewGetProcAddress((const GLubyte*)"glIsShader")) == NULL) || r;
+ r = ((glLinkProgram = (PFNGLLINKPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glLinkProgram")) == NULL) || r;
+ r = ((glShaderSource = (PFNGLSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glShaderSource")) == NULL) || r;
+ r = ((glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilFuncSeparate")) == NULL) || r;
+ r = ((glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilMaskSeparate")) == NULL) || r;
+ r = ((glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilOpSeparate")) == NULL) || r;
+ r = ((glUniform1f = (PFNGLUNIFORM1FPROC)glewGetProcAddress((const GLubyte*)"glUniform1f")) == NULL) || r;
+ r = ((glUniform1fv = (PFNGLUNIFORM1FVPROC)glewGetProcAddress((const GLubyte*)"glUniform1fv")) == NULL) || r;
+ r = ((glUniform1i = (PFNGLUNIFORM1IPROC)glewGetProcAddress((const GLubyte*)"glUniform1i")) == NULL) || r;
+ r = ((glUniform1iv = (PFNGLUNIFORM1IVPROC)glewGetProcAddress((const GLubyte*)"glUniform1iv")) == NULL) || r;
+ r = ((glUniform2f = (PFNGLUNIFORM2FPROC)glewGetProcAddress((const GLubyte*)"glUniform2f")) == NULL) || r;
+ r = ((glUniform2fv = (PFNGLUNIFORM2FVPROC)glewGetProcAddress((const GLubyte*)"glUniform2fv")) == NULL) || r;
+ r = ((glUniform2i = (PFNGLUNIFORM2IPROC)glewGetProcAddress((const GLubyte*)"glUniform2i")) == NULL) || r;
+ r = ((glUniform2iv = (PFNGLUNIFORM2IVPROC)glewGetProcAddress((const GLubyte*)"glUniform2iv")) == NULL) || r;
+ r = ((glUniform3f = (PFNGLUNIFORM3FPROC)glewGetProcAddress((const GLubyte*)"glUniform3f")) == NULL) || r;
+ r = ((glUniform3fv = (PFNGLUNIFORM3FVPROC)glewGetProcAddress((const GLubyte*)"glUniform3fv")) == NULL) || r;
+ r = ((glUniform3i = (PFNGLUNIFORM3IPROC)glewGetProcAddress((const GLubyte*)"glUniform3i")) == NULL) || r;
+ r = ((glUniform3iv = (PFNGLUNIFORM3IVPROC)glewGetProcAddress((const GLubyte*)"glUniform3iv")) == NULL) || r;
+ r = ((glUniform4f = (PFNGLUNIFORM4FPROC)glewGetProcAddress((const GLubyte*)"glUniform4f")) == NULL) || r;
+ r = ((glUniform4fv = (PFNGLUNIFORM4FVPROC)glewGetProcAddress((const GLubyte*)"glUniform4fv")) == NULL) || r;
+ r = ((glUniform4i = (PFNGLUNIFORM4IPROC)glewGetProcAddress((const GLubyte*)"glUniform4i")) == NULL) || r;
+ r = ((glUniform4iv = (PFNGLUNIFORM4IVPROC)glewGetProcAddress((const GLubyte*)"glUniform4iv")) == NULL) || r;
+ r = ((glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2fv")) == NULL) || r;
+ r = ((glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3fv")) == NULL) || r;
+ r = ((glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4fv")) == NULL) || r;
+ r = ((glUseProgram = (PFNGLUSEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glUseProgram")) == NULL) || r;
+ r = ((glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glValidateProgram")) == NULL) || r;
+ r = ((glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1d")) == NULL) || r;
+ r = ((glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dv")) == NULL) || r;
+ r = ((glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1f")) == NULL) || r;
+ r = ((glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fv")) == NULL) || r;
+ r = ((glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1s")) == NULL) || r;
+ r = ((glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sv")) == NULL) || r;
+ r = ((glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2d")) == NULL) || r;
+ r = ((glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dv")) == NULL) || r;
+ r = ((glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2f")) == NULL) || r;
+ r = ((glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fv")) == NULL) || r;
+ r = ((glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2s")) == NULL) || r;
+ r = ((glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sv")) == NULL) || r;
+ r = ((glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3d")) == NULL) || r;
+ r = ((glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dv")) == NULL) || r;
+ r = ((glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3f")) == NULL) || r;
+ r = ((glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fv")) == NULL) || r;
+ r = ((glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3s")) == NULL) || r;
+ r = ((glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sv")) == NULL) || r;
+ r = ((glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nbv")) == NULL) || r;
+ r = ((glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Niv")) == NULL) || r;
+ r = ((glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nsv")) == NULL) || r;
+ r = ((glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nub")) == NULL) || r;
+ r = ((glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nubv")) == NULL) || r;
+ r = ((glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nuiv")) == NULL) || r;
+ r = ((glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nusv")) == NULL) || r;
+ r = ((glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4bv")) == NULL) || r;
+ r = ((glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4d")) == NULL) || r;
+ r = ((glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dv")) == NULL) || r;
+ r = ((glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4f")) == NULL) || r;
+ r = ((glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fv")) == NULL) || r;
+ r = ((glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4iv")) == NULL) || r;
+ r = ((glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4s")) == NULL) || r;
+ r = ((glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sv")) == NULL) || r;
+ r = ((glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubv")) == NULL) || r;
+ r = ((glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uiv")) == NULL) || r;
+ r = ((glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usv")) == NULL) || r;
+ r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_2_0 */
+
+#ifdef GL_VERSION_2_1
+
+static GLboolean _glewInit_GL_VERSION_2_1 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x3fv")) == NULL) || r;
+ r = ((glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x4fv")) == NULL) || r;
+ r = ((glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x2fv")) == NULL) || r;
+ r = ((glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x4fv")) == NULL) || r;
+ r = ((glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x2fv")) == NULL) || r;
+ r = ((glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x3fv")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_2_1 */
+
+#ifdef GL_VERSION_3_0
+
+static GLboolean _glewInit_GL_VERSION_3_0 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)glewGetProcAddress((const GLubyte*)"glBeginConditionalRender")) == NULL) || r;
+ r = ((glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedback")) == NULL) || r;
+ r = ((glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBase")) == NULL) || r;
+ r = ((glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRange")) == NULL) || r;
+ r = ((glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindFragDataLocation")) == NULL) || r;
+ r = ((glClampColor = (PFNGLCLAMPCOLORPROC)glewGetProcAddress((const GLubyte*)"glClampColor")) == NULL) || r;
+ r = ((glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)glewGetProcAddress((const GLubyte*)"glClearBufferfi")) == NULL) || r;
+ r = ((glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)glewGetProcAddress((const GLubyte*)"glClearBufferfv")) == NULL) || r;
+ r = ((glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)glewGetProcAddress((const GLubyte*)"glClearBufferiv")) == NULL) || r;
+ r = ((glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)glewGetProcAddress((const GLubyte*)"glClearBufferuiv")) == NULL) || r;
+ r = ((glColorMaski = (PFNGLCOLORMASKIPROC)glewGetProcAddress((const GLubyte*)"glColorMaski")) == NULL) || r;
+ r = ((glDisablei = (PFNGLDISABLEIPROC)glewGetProcAddress((const GLubyte*)"glDisablei")) == NULL) || r;
+ r = ((glEnablei = (PFNGLENABLEIPROC)glewGetProcAddress((const GLubyte*)"glEnablei")) == NULL) || r;
+ r = ((glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)glewGetProcAddress((const GLubyte*)"glEndConditionalRender")) == NULL) || r;
+ r = ((glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedback")) == NULL) || r;
+ r = ((glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC)glewGetProcAddress((const GLubyte*)"glGetBooleani_v")) == NULL) || r;
+ r = ((glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetFragDataLocation")) == NULL) || r;
+ r = ((glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)glewGetProcAddress((const GLubyte*)"glGetIntegeri_v")) == NULL) || r;
+ r = ((glGetStringi = (PFNGLGETSTRINGIPROC)glewGetProcAddress((const GLubyte*)"glGetStringi")) == NULL) || r;
+ r = ((glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIiv")) == NULL) || r;
+ r = ((glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIuiv")) == NULL) || r;
+ r = ((glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVarying")) == NULL) || r;
+ r = ((glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformuiv")) == NULL) || r;
+ r = ((glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIiv")) == NULL) || r;
+ r = ((glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIuiv")) == NULL) || r;
+ r = ((glIsEnabledi = (PFNGLISENABLEDIPROC)glewGetProcAddress((const GLubyte*)"glIsEnabledi")) == NULL) || r;
+ r = ((glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIiv")) == NULL) || r;
+ r = ((glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIuiv")) == NULL) || r;
+ r = ((glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryings")) == NULL) || r;
+ r = ((glUniform1ui = (PFNGLUNIFORM1UIPROC)glewGetProcAddress((const GLubyte*)"glUniform1ui")) == NULL) || r;
+ r = ((glUniform1uiv = (PFNGLUNIFORM1UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform1uiv")) == NULL) || r;
+ r = ((glUniform2ui = (PFNGLUNIFORM2UIPROC)glewGetProcAddress((const GLubyte*)"glUniform2ui")) == NULL) || r;
+ r = ((glUniform2uiv = (PFNGLUNIFORM2UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform2uiv")) == NULL) || r;
+ r = ((glUniform3ui = (PFNGLUNIFORM3UIPROC)glewGetProcAddress((const GLubyte*)"glUniform3ui")) == NULL) || r;
+ r = ((glUniform3uiv = (PFNGLUNIFORM3UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform3uiv")) == NULL) || r;
+ r = ((glUniform4ui = (PFNGLUNIFORM4UIPROC)glewGetProcAddress((const GLubyte*)"glUniform4ui")) == NULL) || r;
+ r = ((glUniform4uiv = (PFNGLUNIFORM4UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform4uiv")) == NULL) || r;
+ r = ((glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1i")) == NULL) || r;
+ r = ((glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1iv")) == NULL) || r;
+ r = ((glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1ui")) == NULL) || r;
+ r = ((glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uiv")) == NULL) || r;
+ r = ((glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2i")) == NULL) || r;
+ r = ((glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2iv")) == NULL) || r;
+ r = ((glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2ui")) == NULL) || r;
+ r = ((glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uiv")) == NULL) || r;
+ r = ((glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3i")) == NULL) || r;
+ r = ((glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3iv")) == NULL) || r;
+ r = ((glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3ui")) == NULL) || r;
+ r = ((glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uiv")) == NULL) || r;
+ r = ((glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4bv")) == NULL) || r;
+ r = ((glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4i")) == NULL) || r;
+ r = ((glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4iv")) == NULL) || r;
+ r = ((glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4sv")) == NULL) || r;
+ r = ((glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ubv")) == NULL) || r;
+ r = ((glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ui")) == NULL) || r;
+ r = ((glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uiv")) == NULL) || r;
+ r = ((glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4usv")) == NULL) || r;
+ r = ((glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIPointer")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_VERSION_3_0 */
+
+#ifdef GL_3DFX_multisample
+
+#endif /* GL_3DFX_multisample */
+
+#ifdef GL_3DFX_tbuffer
+
+static GLboolean _glewInit_GL_3DFX_tbuffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTbufferMask3DFX = (PFNGLTBUFFERMASK3DFXPROC)glewGetProcAddress((const GLubyte*)"glTbufferMask3DFX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_3DFX_tbuffer */
+
+#ifdef GL_3DFX_texture_compression_FXT1
+
+#endif /* GL_3DFX_texture_compression_FXT1 */
+
+#ifdef GL_APPLE_client_storage
+
+#endif /* GL_APPLE_client_storage */
+
+#ifdef GL_APPLE_element_array
+
+static GLboolean _glewInit_GL_APPLE_element_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawElementArrayAPPLE = (PFNGLDRAWELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementArrayAPPLE")) == NULL) || r;
+ r = ((glDrawRangeElementArrayAPPLE = (PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementArrayAPPLE")) == NULL) || r;
+ r = ((glElementPointerAPPLE = (PFNGLELEMENTPOINTERAPPLEPROC)glewGetProcAddress((const GLubyte*)"glElementPointerAPPLE")) == NULL) || r;
+ r = ((glMultiDrawElementArrayAPPLE = (PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementArrayAPPLE")) == NULL) || r;
+ r = ((glMultiDrawRangeElementArrayAPPLE = (PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawRangeElementArrayAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_element_array */
+
+#ifdef GL_APPLE_fence
+
+static GLboolean _glewInit_GL_APPLE_fence (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDeleteFencesAPPLE = (PFNGLDELETEFENCESAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteFencesAPPLE")) == NULL) || r;
+ r = ((glFinishFenceAPPLE = (PFNGLFINISHFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFinishFenceAPPLE")) == NULL) || r;
+ r = ((glFinishObjectAPPLE = (PFNGLFINISHOBJECTAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFinishObjectAPPLE")) == NULL) || r;
+ r = ((glGenFencesAPPLE = (PFNGLGENFENCESAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGenFencesAPPLE")) == NULL) || r;
+ r = ((glIsFenceAPPLE = (PFNGLISFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsFenceAPPLE")) == NULL) || r;
+ r = ((glSetFenceAPPLE = (PFNGLSETFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glSetFenceAPPLE")) == NULL) || r;
+ r = ((glTestFenceAPPLE = (PFNGLTESTFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTestFenceAPPLE")) == NULL) || r;
+ r = ((glTestObjectAPPLE = (PFNGLTESTOBJECTAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTestObjectAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_fence */
+
+#ifdef GL_APPLE_float_pixels
+
+#endif /* GL_APPLE_float_pixels */
+
+#ifdef GL_APPLE_flush_buffer_range
+
+static GLboolean _glewInit_GL_APPLE_flush_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBufferParameteriAPPLE = (PFNGLBUFFERPARAMETERIAPPLEPROC)glewGetProcAddress((const GLubyte*)"glBufferParameteriAPPLE")) == NULL) || r;
+ r = ((glFlushMappedBufferRangeAPPLE = (PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedBufferRangeAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_flush_buffer_range */
+
+#ifdef GL_APPLE_pixel_buffer
+
+#endif /* GL_APPLE_pixel_buffer */
+
+#ifdef GL_APPLE_specular_vector
+
+#endif /* GL_APPLE_specular_vector */
+
+#ifdef GL_APPLE_texture_range
+
+static GLboolean _glewInit_GL_APPLE_texture_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetTexParameterPointervAPPLE = (PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterPointervAPPLE")) == NULL) || r;
+ r = ((glTextureRangeAPPLE = (PFNGLTEXTURERANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTextureRangeAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_texture_range */
+
+#ifdef GL_APPLE_transform_hint
+
+#endif /* GL_APPLE_transform_hint */
+
+#ifdef GL_APPLE_vertex_array_object
+
+static GLboolean _glewInit_GL_APPLE_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindVertexArrayAPPLE = (PFNGLBINDVERTEXARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glBindVertexArrayAPPLE")) == NULL) || r;
+ r = ((glDeleteVertexArraysAPPLE = (PFNGLDELETEVERTEXARRAYSAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexArraysAPPLE")) == NULL) || r;
+ r = ((glGenVertexArraysAPPLE = (PFNGLGENVERTEXARRAYSAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGenVertexArraysAPPLE")) == NULL) || r;
+ r = ((glIsVertexArrayAPPLE = (PFNGLISVERTEXARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsVertexArrayAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_vertex_array_object */
+
+#ifdef GL_APPLE_vertex_array_range
+
+static GLboolean _glewInit_GL_APPLE_vertex_array_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushVertexArrayRangeAPPLE = (PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFlushVertexArrayRangeAPPLE")) == NULL) || r;
+ r = ((glVertexArrayParameteriAPPLE = (PFNGLVERTEXARRAYPARAMETERIAPPLEPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayParameteriAPPLE")) == NULL) || r;
+ r = ((glVertexArrayRangeAPPLE = (PFNGLVERTEXARRAYRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayRangeAPPLE")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_APPLE_vertex_array_range */
+
+#ifdef GL_APPLE_ycbcr_422
+
+#endif /* GL_APPLE_ycbcr_422 */
+
+#ifdef GL_ARB_color_buffer_float
+
+static GLboolean _glewInit_GL_ARB_color_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClampColorARB = (PFNGLCLAMPCOLORARBPROC)glewGetProcAddress((const GLubyte*)"glClampColorARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_color_buffer_float */
+
+#ifdef GL_ARB_depth_buffer_float
+
+#endif /* GL_ARB_depth_buffer_float */
+
+#ifdef GL_ARB_depth_texture
+
+#endif /* GL_ARB_depth_texture */
+
+#ifdef GL_ARB_draw_buffers
+
+static GLboolean _glewInit_GL_ARB_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_draw_buffers */
+
+#ifdef GL_ARB_draw_instanced
+
+static GLboolean _glewInit_GL_ARB_draw_instanced (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawArraysInstancedARB = (PFNGLDRAWARRAYSINSTANCEDARBPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedARB")) == NULL) || r;
+ r = ((glDrawElementsInstancedARB = (PFNGLDRAWELEMENTSINSTANCEDARBPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_draw_instanced */
+
+#ifdef GL_ARB_fragment_program
+
+#endif /* GL_ARB_fragment_program */
+
+#ifdef GL_ARB_fragment_program_shadow
+
+#endif /* GL_ARB_fragment_program_shadow */
+
+#ifdef GL_ARB_fragment_shader
+
+#endif /* GL_ARB_fragment_shader */
+
+#ifdef GL_ARB_framebuffer_object
+
+static GLboolean _glewInit_GL_ARB_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindFramebuffer")) == NULL) || r;
+ r = ((glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbuffer")) == NULL) || r;
+ r = ((glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebuffer")) == NULL) || r;
+ r = ((glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatus")) == NULL) || r;
+ r = ((glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteFramebuffers")) == NULL) || r;
+ r = ((glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteRenderbuffers")) == NULL) || r;
+ r = ((glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glFramebufferRenderbuffer")) == NULL) || r;
+ r = ((glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayer")) == NULL) || r;
+ r = ((glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture1D")) == NULL) || r;
+ r = ((glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2D")) == NULL) || r;
+ r = ((glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture3D")) == NULL) || r;
+ r = ((glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenFramebuffers")) == NULL) || r;
+ r = ((glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenRenderbuffers")) == NULL) || r;
+ r = ((glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)glewGetProcAddress((const GLubyte*)"glGenerateMipmap")) == NULL) || r;
+ r = ((glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferAttachmentParameteriv")) == NULL) || r;
+ r = ((glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetRenderbufferParameteriv")) == NULL) || r;
+ r = ((glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsFramebuffer")) == NULL) || r;
+ r = ((glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsRenderbuffer")) == NULL) || r;
+ r = ((glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorage")) == NULL) || r;
+ r = ((glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisample")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_framebuffer_object */
+
+#ifdef GL_ARB_framebuffer_sRGB
+
+#endif /* GL_ARB_framebuffer_sRGB */
+
+#ifdef GL_ARB_geometry_shader4
+
+static GLboolean _glewInit_GL_ARB_geometry_shader4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferTextureARB = (PFNGLFRAMEBUFFERTEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureARB")) == NULL) || r;
+ r = ((glFramebufferTextureFaceARB = (PFNGLFRAMEBUFFERTEXTUREFACEARBPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureFaceARB")) == NULL) || r;
+ r = ((glFramebufferTextureLayerARB = (PFNGLFRAMEBUFFERTEXTURELAYERARBPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayerARB")) == NULL) || r;
+ r = ((glProgramParameteriARB = (PFNGLPROGRAMPARAMETERIARBPROC)glewGetProcAddress((const GLubyte*)"glProgramParameteriARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_geometry_shader4 */
+
+#ifdef GL_ARB_half_float_pixel
+
+#endif /* GL_ARB_half_float_pixel */
+
+#ifdef GL_ARB_half_float_vertex
+
+#endif /* GL_ARB_half_float_vertex */
+
+#ifdef GL_ARB_imaging
+
+static GLboolean _glewInit_GL_ARB_imaging (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)"glBlendEquation")) == NULL) || r;
+ r = ((glColorSubTable = (PFNGLCOLORSUBTABLEPROC)glewGetProcAddress((const GLubyte*)"glColorSubTable")) == NULL) || r;
+ r = ((glColorTable = (PFNGLCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glColorTable")) == NULL) || r;
+ r = ((glColorTableParameterfv = (PFNGLCOLORTABLEPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterfv")) == NULL) || r;
+ r = ((glColorTableParameteriv = (PFNGLCOLORTABLEPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameteriv")) == NULL) || r;
+ r = ((glConvolutionFilter1D = (PFNGLCONVOLUTIONFILTER1DPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter1D")) == NULL) || r;
+ r = ((glConvolutionFilter2D = (PFNGLCONVOLUTIONFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter2D")) == NULL) || r;
+ r = ((glConvolutionParameterf = (PFNGLCONVOLUTIONPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterf")) == NULL) || r;
+ r = ((glConvolutionParameterfv = (PFNGLCONVOLUTIONPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfv")) == NULL) || r;
+ r = ((glConvolutionParameteri = (PFNGLCONVOLUTIONPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteri")) == NULL) || r;
+ r = ((glConvolutionParameteriv = (PFNGLCONVOLUTIONPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteriv")) == NULL) || r;
+ r = ((glCopyColorSubTable = (PFNGLCOPYCOLORSUBTABLEPROC)glewGetProcAddress((const GLubyte*)"glCopyColorSubTable")) == NULL) || r;
+ r = ((glCopyColorTable = (PFNGLCOPYCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glCopyColorTable")) == NULL) || r;
+ r = ((glCopyConvolutionFilter1D = (PFNGLCOPYCONVOLUTIONFILTER1DPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter1D")) == NULL) || r;
+ r = ((glCopyConvolutionFilter2D = (PFNGLCOPYCONVOLUTIONFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter2D")) == NULL) || r;
+ r = ((glGetColorTable = (PFNGLGETCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glGetColorTable")) == NULL) || r;
+ r = ((glGetColorTableParameterfv = (PFNGLGETCOLORTABLEPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfv")) == NULL) || r;
+ r = ((glGetColorTableParameteriv = (PFNGLGETCOLORTABLEPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameteriv")) == NULL) || r;
+ r = ((glGetConvolutionFilter = (PFNGLGETCONVOLUTIONFILTERPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionFilter")) == NULL) || r;
+ r = ((glGetConvolutionParameterfv = (PFNGLGETCONVOLUTIONPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterfv")) == NULL) || r;
+ r = ((glGetConvolutionParameteriv = (PFNGLGETCONVOLUTIONPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameteriv")) == NULL) || r;
+ r = ((glGetHistogram = (PFNGLGETHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glGetHistogram")) == NULL) || r;
+ r = ((glGetHistogramParameterfv = (PFNGLGETHISTOGRAMPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterfv")) == NULL) || r;
+ r = ((glGetHistogramParameteriv = (PFNGLGETHISTOGRAMPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameteriv")) == NULL) || r;
+ r = ((glGetMinmax = (PFNGLGETMINMAXPROC)glewGetProcAddress((const GLubyte*)"glGetMinmax")) == NULL) || r;
+ r = ((glGetMinmaxParameterfv = (PFNGLGETMINMAXPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterfv")) == NULL) || r;
+ r = ((glGetMinmaxParameteriv = (PFNGLGETMINMAXPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameteriv")) == NULL) || r;
+ r = ((glGetSeparableFilter = (PFNGLGETSEPARABLEFILTERPROC)glewGetProcAddress((const GLubyte*)"glGetSeparableFilter")) == NULL) || r;
+ r = ((glHistogram = (PFNGLHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glHistogram")) == NULL) || r;
+ r = ((glMinmax = (PFNGLMINMAXPROC)glewGetProcAddress((const GLubyte*)"glMinmax")) == NULL) || r;
+ r = ((glResetHistogram = (PFNGLRESETHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glResetHistogram")) == NULL) || r;
+ r = ((glResetMinmax = (PFNGLRESETMINMAXPROC)glewGetProcAddress((const GLubyte*)"glResetMinmax")) == NULL) || r;
+ r = ((glSeparableFilter2D = (PFNGLSEPARABLEFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glSeparableFilter2D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_imaging */
+
+#ifdef GL_ARB_instanced_arrays
+
+static GLboolean _glewInit_GL_ARB_instanced_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glVertexAttribDivisorARB = (PFNGLVERTEXATTRIBDIVISORARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribDivisorARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_instanced_arrays */
+
+#ifdef GL_ARB_map_buffer_range
+
+static GLboolean _glewInit_GL_ARB_map_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedBufferRange")) == NULL) || r;
+ r = ((glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glMapBufferRange")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_map_buffer_range */
+
+#ifdef GL_ARB_matrix_palette
+
+static GLboolean _glewInit_GL_ARB_matrix_palette (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCurrentPaletteMatrixARB = (PFNGLCURRENTPALETTEMATRIXARBPROC)glewGetProcAddress((const GLubyte*)"glCurrentPaletteMatrixARB")) == NULL) || r;
+ r = ((glMatrixIndexPointerARB = (PFNGLMATRIXINDEXPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexPointerARB")) == NULL) || r;
+ r = ((glMatrixIndexubvARB = (PFNGLMATRIXINDEXUBVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexubvARB")) == NULL) || r;
+ r = ((glMatrixIndexuivARB = (PFNGLMATRIXINDEXUIVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexuivARB")) == NULL) || r;
+ r = ((glMatrixIndexusvARB = (PFNGLMATRIXINDEXUSVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexusvARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_matrix_palette */
+
+#ifdef GL_ARB_multisample
+
+static GLboolean _glewInit_GL_ARB_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSampleCoverageARB = (PFNGLSAMPLECOVERAGEARBPROC)glewGetProcAddress((const GLubyte*)"glSampleCoverageARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_multisample */
+
+#ifdef GL_ARB_multitexture
+
+static GLboolean _glewInit_GL_ARB_multitexture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glActiveTextureARB")) == NULL) || r;
+ r = ((glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glClientActiveTextureARB")) == NULL) || r;
+ r = ((glMultiTexCoord1dARB = (PFNGLMULTITEXCOORD1DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dARB")) == NULL) || r;
+ r = ((glMultiTexCoord1dvARB = (PFNGLMULTITEXCOORD1DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dvARB")) == NULL) || r;
+ r = ((glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fARB")) == NULL) || r;
+ r = ((glMultiTexCoord1fvARB = (PFNGLMULTITEXCOORD1FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fvARB")) == NULL) || r;
+ r = ((glMultiTexCoord1iARB = (PFNGLMULTITEXCOORD1IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1iARB")) == NULL) || r;
+ r = ((glMultiTexCoord1ivARB = (PFNGLMULTITEXCOORD1IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1ivARB")) == NULL) || r;
+ r = ((glMultiTexCoord1sARB = (PFNGLMULTITEXCOORD1SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1sARB")) == NULL) || r;
+ r = ((glMultiTexCoord1svARB = (PFNGLMULTITEXCOORD1SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1svARB")) == NULL) || r;
+ r = ((glMultiTexCoord2dARB = (PFNGLMULTITEXCOORD2DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dARB")) == NULL) || r;
+ r = ((glMultiTexCoord2dvARB = (PFNGLMULTITEXCOORD2DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dvARB")) == NULL) || r;
+ r = ((glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fARB")) == NULL) || r;
+ r = ((glMultiTexCoord2fvARB = (PFNGLMULTITEXCOORD2FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fvARB")) == NULL) || r;
+ r = ((glMultiTexCoord2iARB = (PFNGLMULTITEXCOORD2IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2iARB")) == NULL) || r;
+ r = ((glMultiTexCoord2ivARB = (PFNGLMULTITEXCOORD2IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2ivARB")) == NULL) || r;
+ r = ((glMultiTexCoord2sARB = (PFNGLMULTITEXCOORD2SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2sARB")) == NULL) || r;
+ r = ((glMultiTexCoord2svARB = (PFNGLMULTITEXCOORD2SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2svARB")) == NULL) || r;
+ r = ((glMultiTexCoord3dARB = (PFNGLMULTITEXCOORD3DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dARB")) == NULL) || r;
+ r = ((glMultiTexCoord3dvARB = (PFNGLMULTITEXCOORD3DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dvARB")) == NULL) || r;
+ r = ((glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fARB")) == NULL) || r;
+ r = ((glMultiTexCoord3fvARB = (PFNGLMULTITEXCOORD3FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fvARB")) == NULL) || r;
+ r = ((glMultiTexCoord3iARB = (PFNGLMULTITEXCOORD3IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3iARB")) == NULL) || r;
+ r = ((glMultiTexCoord3ivARB = (PFNGLMULTITEXCOORD3IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3ivARB")) == NULL) || r;
+ r = ((glMultiTexCoord3sARB = (PFNGLMULTITEXCOORD3SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3sARB")) == NULL) || r;
+ r = ((glMultiTexCoord3svARB = (PFNGLMULTITEXCOORD3SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3svARB")) == NULL) || r;
+ r = ((glMultiTexCoord4dARB = (PFNGLMULTITEXCOORD4DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dARB")) == NULL) || r;
+ r = ((glMultiTexCoord4dvARB = (PFNGLMULTITEXCOORD4DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dvARB")) == NULL) || r;
+ r = ((glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fARB")) == NULL) || r;
+ r = ((glMultiTexCoord4fvARB = (PFNGLMULTITEXCOORD4FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fvARB")) == NULL) || r;
+ r = ((glMultiTexCoord4iARB = (PFNGLMULTITEXCOORD4IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4iARB")) == NULL) || r;
+ r = ((glMultiTexCoord4ivARB = (PFNGLMULTITEXCOORD4IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4ivARB")) == NULL) || r;
+ r = ((glMultiTexCoord4sARB = (PFNGLMULTITEXCOORD4SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4sARB")) == NULL) || r;
+ r = ((glMultiTexCoord4svARB = (PFNGLMULTITEXCOORD4SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4svARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_multitexture */
+
+#ifdef GL_ARB_occlusion_query
+
+static GLboolean _glewInit_GL_ARB_occlusion_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glBeginQueryARB")) == NULL) || r;
+ r = ((glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueriesARB")) == NULL) || r;
+ r = ((glEndQueryARB = (PFNGLENDQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glEndQueryARB")) == NULL) || r;
+ r = ((glGenQueriesARB = (PFNGLGENQUERIESARBPROC)glewGetProcAddress((const GLubyte*)"glGenQueriesARB")) == NULL) || r;
+ r = ((glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectivARB")) == NULL) || r;
+ r = ((glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuivARB")) == NULL) || r;
+ r = ((glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryivARB")) == NULL) || r;
+ r = ((glIsQueryARB = (PFNGLISQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glIsQueryARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_occlusion_query */
+
+#ifdef GL_ARB_pixel_buffer_object
+
+#endif /* GL_ARB_pixel_buffer_object */
+
+#ifdef GL_ARB_point_parameters
+
+static GLboolean _glewInit_GL_ARB_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfARB")) == NULL) || r;
+ r = ((glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfvARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_point_parameters */
+
+#ifdef GL_ARB_point_sprite
+
+#endif /* GL_ARB_point_sprite */
+
+#ifdef GL_ARB_shader_objects
+
+static GLboolean _glewInit_GL_ARB_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glAttachObjectARB")) == NULL) || r;
+ r = ((glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)glewGetProcAddress((const GLubyte*)"glCompileShaderARB")) == NULL) || r;
+ r = ((glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateProgramObjectARB")) == NULL) || r;
+ r = ((glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateShaderObjectARB")) == NULL) || r;
+ r = ((glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteObjectARB")) == NULL) || r;
+ r = ((glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glDetachObjectARB")) == NULL) || r;
+ r = ((glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformARB")) == NULL) || r;
+ r = ((glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC)glewGetProcAddress((const GLubyte*)"glGetAttachedObjectsARB")) == NULL) || r;
+ r = ((glGetHandleARB = (PFNGLGETHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetHandleARB")) == NULL) || r;
+ r = ((glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)glewGetProcAddress((const GLubyte*)"glGetInfoLogARB")) == NULL) || r;
+ r = ((glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterfvARB")) == NULL) || r;
+ r = ((glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterivARB")) == NULL) || r;
+ r = ((glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC)glewGetProcAddress((const GLubyte*)"glGetShaderSourceARB")) == NULL) || r;
+ r = ((glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformLocationARB")) == NULL) || r;
+ r = ((glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformfvARB")) == NULL) || r;
+ r = ((glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformivARB")) == NULL) || r;
+ r = ((glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glLinkProgramARB")) == NULL) || r;
+ r = ((glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)glewGetProcAddress((const GLubyte*)"glShaderSourceARB")) == NULL) || r;
+ r = ((glUniform1fARB = (PFNGLUNIFORM1FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1fARB")) == NULL) || r;
+ r = ((glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1fvARB")) == NULL) || r;
+ r = ((glUniform1iARB = (PFNGLUNIFORM1IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1iARB")) == NULL) || r;
+ r = ((glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1ivARB")) == NULL) || r;
+ r = ((glUniform2fARB = (PFNGLUNIFORM2FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2fARB")) == NULL) || r;
+ r = ((glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2fvARB")) == NULL) || r;
+ r = ((glUniform2iARB = (PFNGLUNIFORM2IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2iARB")) == NULL) || r;
+ r = ((glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2ivARB")) == NULL) || r;
+ r = ((glUniform3fARB = (PFNGLUNIFORM3FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3fARB")) == NULL) || r;
+ r = ((glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3fvARB")) == NULL) || r;
+ r = ((glUniform3iARB = (PFNGLUNIFORM3IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3iARB")) == NULL) || r;
+ r = ((glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3ivARB")) == NULL) || r;
+ r = ((glUniform4fARB = (PFNGLUNIFORM4FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4fARB")) == NULL) || r;
+ r = ((glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4fvARB")) == NULL) || r;
+ r = ((glUniform4iARB = (PFNGLUNIFORM4IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4iARB")) == NULL) || r;
+ r = ((glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4ivARB")) == NULL) || r;
+ r = ((glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2fvARB")) == NULL) || r;
+ r = ((glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3fvARB")) == NULL) || r;
+ r = ((glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4fvARB")) == NULL) || r;
+ r = ((glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glUseProgramObjectARB")) == NULL) || r;
+ r = ((glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glValidateProgramARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_shader_objects */
+
+#ifdef GL_ARB_shading_language_100
+
+#endif /* GL_ARB_shading_language_100 */
+
+#ifdef GL_ARB_shadow
+
+#endif /* GL_ARB_shadow */
+
+#ifdef GL_ARB_shadow_ambient
+
+#endif /* GL_ARB_shadow_ambient */
+
+#ifdef GL_ARB_texture_border_clamp
+
+#endif /* GL_ARB_texture_border_clamp */
+
+#ifdef GL_ARB_texture_buffer_object
+
+static GLboolean _glewInit_GL_ARB_texture_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexBufferARB = (PFNGLTEXBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glTexBufferARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_buffer_object */
+
+#ifdef GL_ARB_texture_compression
+
+static GLboolean _glewInit_GL_ARB_texture_compression (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCompressedTexImage1DARB = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage1DARB")) == NULL) || r;
+ r = ((glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage2DARB")) == NULL) || r;
+ r = ((glCompressedTexImage3DARB = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3DARB")) == NULL) || r;
+ r = ((glCompressedTexSubImage1DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage1DARB")) == NULL) || r;
+ r = ((glCompressedTexSubImage2DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage2DARB")) == NULL) || r;
+ r = ((glCompressedTexSubImage3DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3DARB")) == NULL) || r;
+ r = ((glGetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTexImageARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_texture_compression */
+
+#ifdef GL_ARB_texture_compression_rgtc
+
+#endif /* GL_ARB_texture_compression_rgtc */
+
+#ifdef GL_ARB_texture_cube_map
+
+#endif /* GL_ARB_texture_cube_map */
+
+#ifdef GL_ARB_texture_env_add
+
+#endif /* GL_ARB_texture_env_add */
+
+#ifdef GL_ARB_texture_env_combine
+
+#endif /* GL_ARB_texture_env_combine */
+
+#ifdef GL_ARB_texture_env_crossbar
+
+#endif /* GL_ARB_texture_env_crossbar */
+
+#ifdef GL_ARB_texture_env_dot3
+
+#endif /* GL_ARB_texture_env_dot3 */
+
+#ifdef GL_ARB_texture_float
+
+#endif /* GL_ARB_texture_float */
+
+#ifdef GL_ARB_texture_mirrored_repeat
+
+#endif /* GL_ARB_texture_mirrored_repeat */
+
+#ifdef GL_ARB_texture_non_power_of_two
+
+#endif /* GL_ARB_texture_non_power_of_two */
+
+#ifdef GL_ARB_texture_rectangle
+
+#endif /* GL_ARB_texture_rectangle */
+
+#ifdef GL_ARB_texture_rg
+
+#endif /* GL_ARB_texture_rg */
+
+#ifdef GL_ARB_transpose_matrix
+
+static GLboolean _glewInit_GL_ARB_transpose_matrix (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glLoadTransposeMatrixdARB = (PFNGLLOADTRANSPOSEMATRIXDARBPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixdARB")) == NULL) || r;
+ r = ((glLoadTransposeMatrixfARB = (PFNGLLOADTRANSPOSEMATRIXFARBPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixfARB")) == NULL) || r;
+ r = ((glMultTransposeMatrixdARB = (PFNGLMULTTRANSPOSEMATRIXDARBPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixdARB")) == NULL) || r;
+ r = ((glMultTransposeMatrixfARB = (PFNGLMULTTRANSPOSEMATRIXFARBPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixfARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_transpose_matrix */
+
+#ifdef GL_ARB_vertex_array_object
+
+static GLboolean _glewInit_GL_ARB_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)glewGetProcAddress((const GLubyte*)"glBindVertexArray")) == NULL) || r;
+ r = ((glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexArrays")) == NULL) || r;
+ r = ((glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)glewGetProcAddress((const GLubyte*)"glGenVertexArrays")) == NULL) || r;
+ r = ((glIsVertexArray = (PFNGLISVERTEXARRAYPROC)glewGetProcAddress((const GLubyte*)"glIsVertexArray")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_array_object */
+
+#ifdef GL_ARB_vertex_blend
+
+static GLboolean _glewInit_GL_ARB_vertex_blend (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glVertexBlendARB = (PFNGLVERTEXBLENDARBPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendARB")) == NULL) || r;
+ r = ((glWeightPointerARB = (PFNGLWEIGHTPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glWeightPointerARB")) == NULL) || r;
+ r = ((glWeightbvARB = (PFNGLWEIGHTBVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightbvARB")) == NULL) || r;
+ r = ((glWeightdvARB = (PFNGLWEIGHTDVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightdvARB")) == NULL) || r;
+ r = ((glWeightfvARB = (PFNGLWEIGHTFVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightfvARB")) == NULL) || r;
+ r = ((glWeightivARB = (PFNGLWEIGHTIVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightivARB")) == NULL) || r;
+ r = ((glWeightsvARB = (PFNGLWEIGHTSVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightsvARB")) == NULL) || r;
+ r = ((glWeightubvARB = (PFNGLWEIGHTUBVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightubvARB")) == NULL) || r;
+ r = ((glWeightuivARB = (PFNGLWEIGHTUIVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightuivARB")) == NULL) || r;
+ r = ((glWeightusvARB = (PFNGLWEIGHTUSVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightusvARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_blend */
+
+#ifdef GL_ARB_vertex_buffer_object
+
+static GLboolean _glewInit_GL_ARB_vertex_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindBufferARB = (PFNGLBINDBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glBindBufferARB")) == NULL) || r;
+ r = ((glBufferDataARB = (PFNGLBUFFERDATAARBPROC)glewGetProcAddress((const GLubyte*)"glBufferDataARB")) == NULL) || r;
+ r = ((glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)glewGetProcAddress((const GLubyte*)"glBufferSubDataARB")) == NULL) || r;
+ r = ((glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffersARB")) == NULL) || r;
+ r = ((glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glGenBuffersARB")) == NULL) || r;
+ r = ((glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameterivARB")) == NULL) || r;
+ r = ((glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferPointervARB")) == NULL) || r;
+ r = ((glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferSubDataARB")) == NULL) || r;
+ r = ((glIsBufferARB = (PFNGLISBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glIsBufferARB")) == NULL) || r;
+ r = ((glMapBufferARB = (PFNGLMAPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glMapBufferARB")) == NULL) || r;
+ r = ((glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glUnmapBufferARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_buffer_object */
+
+#ifdef GL_ARB_vertex_program
+
+static GLboolean _glewInit_GL_ARB_vertex_program (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindProgramARB = (PFNGLBINDPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glBindProgramARB")) == NULL) || r;
+ r = ((glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramsARB")) == NULL) || r;
+ r = ((glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribArrayARB")) == NULL) || r;
+ r = ((glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribArrayARB")) == NULL) || r;
+ r = ((glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)glewGetProcAddress((const GLubyte*)"glGenProgramsARB")) == NULL) || r;
+ r = ((glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramEnvParameterdvARB")) == NULL) || r;
+ r = ((glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramEnvParameterfvARB")) == NULL) || r;
+ r = ((glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramLocalParameterdvARB")) == NULL) || r;
+ r = ((glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramLocalParameterfvARB")) == NULL) || r;
+ r = ((glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStringARB")) == NULL) || r;
+ r = ((glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramivARB")) == NULL) || r;
+ r = ((glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointervARB")) == NULL) || r;
+ r = ((glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdvARB")) == NULL) || r;
+ r = ((glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfvARB")) == NULL) || r;
+ r = ((glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribivARB")) == NULL) || r;
+ r = ((glIsProgramARB = (PFNGLISPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glIsProgramARB")) == NULL) || r;
+ r = ((glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4dARB")) == NULL) || r;
+ r = ((glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4dvARB")) == NULL) || r;
+ r = ((glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4fARB")) == NULL) || r;
+ r = ((glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4fvARB")) == NULL) || r;
+ r = ((glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4dARB")) == NULL) || r;
+ r = ((glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4dvARB")) == NULL) || r;
+ r = ((glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4fARB")) == NULL) || r;
+ r = ((glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4fvARB")) == NULL) || r;
+ r = ((glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glProgramStringARB")) == NULL) || r;
+ r = ((glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dARB")) == NULL) || r;
+ r = ((glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dvARB")) == NULL) || r;
+ r = ((glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fARB")) == NULL) || r;
+ r = ((glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fvARB")) == NULL) || r;
+ r = ((glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sARB")) == NULL) || r;
+ r = ((glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1svARB")) == NULL) || r;
+ r = ((glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dARB")) == NULL) || r;
+ r = ((glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dvARB")) == NULL) || r;
+ r = ((glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fARB")) == NULL) || r;
+ r = ((glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fvARB")) == NULL) || r;
+ r = ((glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sARB")) == NULL) || r;
+ r = ((glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2svARB")) == NULL) || r;
+ r = ((glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dARB")) == NULL) || r;
+ r = ((glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dvARB")) == NULL) || r;
+ r = ((glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fARB")) == NULL) || r;
+ r = ((glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fvARB")) == NULL) || r;
+ r = ((glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sARB")) == NULL) || r;
+ r = ((glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3svARB")) == NULL) || r;
+ r = ((glVertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NbvARB")) == NULL) || r;
+ r = ((glVertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NivARB")) == NULL) || r;
+ r = ((glVertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NsvARB")) == NULL) || r;
+ r = ((glVertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NubARB")) == NULL) || r;
+ r = ((glVertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NubvARB")) == NULL) || r;
+ r = ((glVertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NuivARB")) == NULL) || r;
+ r = ((glVertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NusvARB")) == NULL) || r;
+ r = ((glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4bvARB")) == NULL) || r;
+ r = ((glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dARB")) == NULL) || r;
+ r = ((glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dvARB")) == NULL) || r;
+ r = ((glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fARB")) == NULL) || r;
+ r = ((glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fvARB")) == NULL) || r;
+ r = ((glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ivARB")) == NULL) || r;
+ r = ((glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sARB")) == NULL) || r;
+ r = ((glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4svARB")) == NULL) || r;
+ r = ((glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubvARB")) == NULL) || r;
+ r = ((glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uivARB")) == NULL) || r;
+ r = ((glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usvARB")) == NULL) || r;
+ r = ((glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointerARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_program */
+
+#ifdef GL_ARB_vertex_shader
+
+static GLboolean _glewInit_GL_ARB_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocationARB")) == NULL) || r;
+ r = ((glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAttribARB")) == NULL) || r;
+ r = ((glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glGetAttribLocationARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_vertex_shader */
+
+#ifdef GL_ARB_window_pos
+
+static GLboolean _glewInit_GL_ARB_window_pos (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glWindowPos2dARB = (PFNGLWINDOWPOS2DARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dARB")) == NULL) || r;
+ r = ((glWindowPos2dvARB = (PFNGLWINDOWPOS2DVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dvARB")) == NULL) || r;
+ r = ((glWindowPos2fARB = (PFNGLWINDOWPOS2FARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fARB")) == NULL) || r;
+ r = ((glWindowPos2fvARB = (PFNGLWINDOWPOS2FVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fvARB")) == NULL) || r;
+ r = ((glWindowPos2iARB = (PFNGLWINDOWPOS2IARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iARB")) == NULL) || r;
+ r = ((glWindowPos2ivARB = (PFNGLWINDOWPOS2IVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2ivARB")) == NULL) || r;
+ r = ((glWindowPos2sARB = (PFNGLWINDOWPOS2SARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sARB")) == NULL) || r;
+ r = ((glWindowPos2svARB = (PFNGLWINDOWPOS2SVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2svARB")) == NULL) || r;
+ r = ((glWindowPos3dARB = (PFNGLWINDOWPOS3DARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dARB")) == NULL) || r;
+ r = ((glWindowPos3dvARB = (PFNGLWINDOWPOS3DVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dvARB")) == NULL) || r;
+ r = ((glWindowPos3fARB = (PFNGLWINDOWPOS3FARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fARB")) == NULL) || r;
+ r = ((glWindowPos3fvARB = (PFNGLWINDOWPOS3FVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fvARB")) == NULL) || r;
+ r = ((glWindowPos3iARB = (PFNGLWINDOWPOS3IARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iARB")) == NULL) || r;
+ r = ((glWindowPos3ivARB = (PFNGLWINDOWPOS3IVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3ivARB")) == NULL) || r;
+ r = ((glWindowPos3sARB = (PFNGLWINDOWPOS3SARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sARB")) == NULL) || r;
+ r = ((glWindowPos3svARB = (PFNGLWINDOWPOS3SVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3svARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ARB_window_pos */
+
+#ifdef GL_ATIX_point_sprites
+
+#endif /* GL_ATIX_point_sprites */
+
+#ifdef GL_ATIX_texture_env_combine3
+
+#endif /* GL_ATIX_texture_env_combine3 */
+
+#ifdef GL_ATIX_texture_env_route
+
+#endif /* GL_ATIX_texture_env_route */
+
+#ifdef GL_ATIX_vertex_shader_output_point_size
+
+#endif /* GL_ATIX_vertex_shader_output_point_size */
+
+#ifdef GL_ATI_draw_buffers
+
+static GLboolean _glewInit_GL_ATI_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawBuffersATI = (PFNGLDRAWBUFFERSATIPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_draw_buffers */
+
+#ifdef GL_ATI_element_array
+
+static GLboolean _glewInit_GL_ATI_element_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawElementArrayATI = (PFNGLDRAWELEMENTARRAYATIPROC)glewGetProcAddress((const GLubyte*)"glDrawElementArrayATI")) == NULL) || r;
+ r = ((glDrawRangeElementArrayATI = (PFNGLDRAWRANGEELEMENTARRAYATIPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementArrayATI")) == NULL) || r;
+ r = ((glElementPointerATI = (PFNGLELEMENTPOINTERATIPROC)glewGetProcAddress((const GLubyte*)"glElementPointerATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_element_array */
+
+#ifdef GL_ATI_envmap_bumpmap
+
+static GLboolean _glewInit_GL_ATI_envmap_bumpmap (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetTexBumpParameterfvATI = (PFNGLGETTEXBUMPPARAMETERFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetTexBumpParameterfvATI")) == NULL) || r;
+ r = ((glGetTexBumpParameterivATI = (PFNGLGETTEXBUMPPARAMETERIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetTexBumpParameterivATI")) == NULL) || r;
+ r = ((glTexBumpParameterfvATI = (PFNGLTEXBUMPPARAMETERFVATIPROC)glewGetProcAddress((const GLubyte*)"glTexBumpParameterfvATI")) == NULL) || r;
+ r = ((glTexBumpParameterivATI = (PFNGLTEXBUMPPARAMETERIVATIPROC)glewGetProcAddress((const GLubyte*)"glTexBumpParameterivATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_envmap_bumpmap */
+
+#ifdef GL_ATI_fragment_shader
+
+static GLboolean _glewInit_GL_ATI_fragment_shader (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAlphaFragmentOp1ATI = (PFNGLALPHAFRAGMENTOP1ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp1ATI")) == NULL) || r;
+ r = ((glAlphaFragmentOp2ATI = (PFNGLALPHAFRAGMENTOP2ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp2ATI")) == NULL) || r;
+ r = ((glAlphaFragmentOp3ATI = (PFNGLALPHAFRAGMENTOP3ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp3ATI")) == NULL) || r;
+ r = ((glBeginFragmentShaderATI = (PFNGLBEGINFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glBeginFragmentShaderATI")) == NULL) || r;
+ r = ((glBindFragmentShaderATI = (PFNGLBINDFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glBindFragmentShaderATI")) == NULL) || r;
+ r = ((glColorFragmentOp1ATI = (PFNGLCOLORFRAGMENTOP1ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp1ATI")) == NULL) || r;
+ r = ((glColorFragmentOp2ATI = (PFNGLCOLORFRAGMENTOP2ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp2ATI")) == NULL) || r;
+ r = ((glColorFragmentOp3ATI = (PFNGLCOLORFRAGMENTOP3ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp3ATI")) == NULL) || r;
+ r = ((glDeleteFragmentShaderATI = (PFNGLDELETEFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glDeleteFragmentShaderATI")) == NULL) || r;
+ r = ((glEndFragmentShaderATI = (PFNGLENDFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glEndFragmentShaderATI")) == NULL) || r;
+ r = ((glGenFragmentShadersATI = (PFNGLGENFRAGMENTSHADERSATIPROC)glewGetProcAddress((const GLubyte*)"glGenFragmentShadersATI")) == NULL) || r;
+ r = ((glPassTexCoordATI = (PFNGLPASSTEXCOORDATIPROC)glewGetProcAddress((const GLubyte*)"glPassTexCoordATI")) == NULL) || r;
+ r = ((glSampleMapATI = (PFNGLSAMPLEMAPATIPROC)glewGetProcAddress((const GLubyte*)"glSampleMapATI")) == NULL) || r;
+ r = ((glSetFragmentShaderConstantATI = (PFNGLSETFRAGMENTSHADERCONSTANTATIPROC)glewGetProcAddress((const GLubyte*)"glSetFragmentShaderConstantATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_fragment_shader */
+
+#ifdef GL_ATI_map_object_buffer
+
+static GLboolean _glewInit_GL_ATI_map_object_buffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMapObjectBufferATI = (PFNGLMAPOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glMapObjectBufferATI")) == NULL) || r;
+ r = ((glUnmapObjectBufferATI = (PFNGLUNMAPOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glUnmapObjectBufferATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_map_object_buffer */
+
+#ifdef GL_ATI_pn_triangles
+
+static GLboolean _glewInit_GL_ATI_pn_triangles (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPNTrianglesfATI = (PFNGLPNTRIANGLESFATIPROC)glewGetProcAddress((const GLubyte*)"glPNTrianglesfATI")) == NULL) || r;
+ r = ((glPNTrianglesiATI = (PFNGLPNTRIANGLESIATIPROC)glewGetProcAddress((const GLubyte*)"glPNTrianglesiATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_pn_triangles */
+
+#ifdef GL_ATI_separate_stencil
+
+static GLboolean _glewInit_GL_ATI_separate_stencil (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glStencilFuncSeparateATI = (PFNGLSTENCILFUNCSEPARATEATIPROC)glewGetProcAddress((const GLubyte*)"glStencilFuncSeparateATI")) == NULL) || r;
+ r = ((glStencilOpSeparateATI = (PFNGLSTENCILOPSEPARATEATIPROC)glewGetProcAddress((const GLubyte*)"glStencilOpSeparateATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_separate_stencil */
+
+#ifdef GL_ATI_shader_texture_lod
+
+#endif /* GL_ATI_shader_texture_lod */
+
+#ifdef GL_ATI_text_fragment_shader
+
+#endif /* GL_ATI_text_fragment_shader */
+
+#ifdef GL_ATI_texture_compression_3dc
+
+#endif /* GL_ATI_texture_compression_3dc */
+
+#ifdef GL_ATI_texture_env_combine3
+
+#endif /* GL_ATI_texture_env_combine3 */
+
+#ifdef GL_ATI_texture_float
+
+#endif /* GL_ATI_texture_float */
+
+#ifdef GL_ATI_texture_mirror_once
+
+#endif /* GL_ATI_texture_mirror_once */
+
+#ifdef GL_ATI_vertex_array_object
+
+static GLboolean _glewInit_GL_ATI_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glArrayObjectATI = (PFNGLARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glArrayObjectATI")) == NULL) || r;
+ r = ((glFreeObjectBufferATI = (PFNGLFREEOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glFreeObjectBufferATI")) == NULL) || r;
+ r = ((glGetArrayObjectfvATI = (PFNGLGETARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetArrayObjectfvATI")) == NULL) || r;
+ r = ((glGetArrayObjectivATI = (PFNGLGETARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetArrayObjectivATI")) == NULL) || r;
+ r = ((glGetObjectBufferfvATI = (PFNGLGETOBJECTBUFFERFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetObjectBufferfvATI")) == NULL) || r;
+ r = ((glGetObjectBufferivATI = (PFNGLGETOBJECTBUFFERIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetObjectBufferivATI")) == NULL) || r;
+ r = ((glGetVariantArrayObjectfvATI = (PFNGLGETVARIANTARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVariantArrayObjectfvATI")) == NULL) || r;
+ r = ((glGetVariantArrayObjectivATI = (PFNGLGETVARIANTARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVariantArrayObjectivATI")) == NULL) || r;
+ r = ((glIsObjectBufferATI = (PFNGLISOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glIsObjectBufferATI")) == NULL) || r;
+ r = ((glNewObjectBufferATI = (PFNGLNEWOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glNewObjectBufferATI")) == NULL) || r;
+ r = ((glUpdateObjectBufferATI = (PFNGLUPDATEOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glUpdateObjectBufferATI")) == NULL) || r;
+ r = ((glVariantArrayObjectATI = (PFNGLVARIANTARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glVariantArrayObjectATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_vertex_array_object */
+
+#ifdef GL_ATI_vertex_attrib_array_object
+
+static GLboolean _glewInit_GL_ATI_vertex_attrib_array_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetVertexAttribArrayObjectfvATI = (PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribArrayObjectfvATI")) == NULL) || r;
+ r = ((glGetVertexAttribArrayObjectivATI = (PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribArrayObjectivATI")) == NULL) || r;
+ r = ((glVertexAttribArrayObjectATI = (PFNGLVERTEXATTRIBARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribArrayObjectATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_vertex_attrib_array_object */
+
+#ifdef GL_ATI_vertex_streams
+
+static GLboolean _glewInit_GL_ATI_vertex_streams (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClientActiveVertexStreamATI = (PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC)glewGetProcAddress((const GLubyte*)"glClientActiveVertexStreamATI")) == NULL) || r;
+ r = ((glNormalStream3bATI = (PFNGLNORMALSTREAM3BATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3bATI")) == NULL) || r;
+ r = ((glNormalStream3bvATI = (PFNGLNORMALSTREAM3BVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3bvATI")) == NULL) || r;
+ r = ((glNormalStream3dATI = (PFNGLNORMALSTREAM3DATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3dATI")) == NULL) || r;
+ r = ((glNormalStream3dvATI = (PFNGLNORMALSTREAM3DVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3dvATI")) == NULL) || r;
+ r = ((glNormalStream3fATI = (PFNGLNORMALSTREAM3FATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3fATI")) == NULL) || r;
+ r = ((glNormalStream3fvATI = (PFNGLNORMALSTREAM3FVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3fvATI")) == NULL) || r;
+ r = ((glNormalStream3iATI = (PFNGLNORMALSTREAM3IATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3iATI")) == NULL) || r;
+ r = ((glNormalStream3ivATI = (PFNGLNORMALSTREAM3IVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3ivATI")) == NULL) || r;
+ r = ((glNormalStream3sATI = (PFNGLNORMALSTREAM3SATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3sATI")) == NULL) || r;
+ r = ((glNormalStream3svATI = (PFNGLNORMALSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3svATI")) == NULL) || r;
+ r = ((glVertexBlendEnvfATI = (PFNGLVERTEXBLENDENVFATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnvfATI")) == NULL) || r;
+ r = ((glVertexBlendEnviATI = (PFNGLVERTEXBLENDENVIATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnviATI")) == NULL) || r;
+ r = ((glVertexStream2dATI = (PFNGLVERTEXSTREAM2DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dATI")) == NULL) || r;
+ r = ((glVertexStream2dvATI = (PFNGLVERTEXSTREAM2DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dvATI")) == NULL) || r;
+ r = ((glVertexStream2fATI = (PFNGLVERTEXSTREAM2FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fATI")) == NULL) || r;
+ r = ((glVertexStream2fvATI = (PFNGLVERTEXSTREAM2FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fvATI")) == NULL) || r;
+ r = ((glVertexStream2iATI = (PFNGLVERTEXSTREAM2IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2iATI")) == NULL) || r;
+ r = ((glVertexStream2ivATI = (PFNGLVERTEXSTREAM2IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2ivATI")) == NULL) || r;
+ r = ((glVertexStream2sATI = (PFNGLVERTEXSTREAM2SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2sATI")) == NULL) || r;
+ r = ((glVertexStream2svATI = (PFNGLVERTEXSTREAM2SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2svATI")) == NULL) || r;
+ r = ((glVertexStream3dATI = (PFNGLVERTEXSTREAM3DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3dATI")) == NULL) || r;
+ r = ((glVertexStream3dvATI = (PFNGLVERTEXSTREAM3DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3dvATI")) == NULL) || r;
+ r = ((glVertexStream3fATI = (PFNGLVERTEXSTREAM3FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3fATI")) == NULL) || r;
+ r = ((glVertexStream3fvATI = (PFNGLVERTEXSTREAM3FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3fvATI")) == NULL) || r;
+ r = ((glVertexStream3iATI = (PFNGLVERTEXSTREAM3IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3iATI")) == NULL) || r;
+ r = ((glVertexStream3ivATI = (PFNGLVERTEXSTREAM3IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3ivATI")) == NULL) || r;
+ r = ((glVertexStream3sATI = (PFNGLVERTEXSTREAM3SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3sATI")) == NULL) || r;
+ r = ((glVertexStream3svATI = (PFNGLVERTEXSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3svATI")) == NULL) || r;
+ r = ((glVertexStream4dATI = (PFNGLVERTEXSTREAM4DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4dATI")) == NULL) || r;
+ r = ((glVertexStream4dvATI = (PFNGLVERTEXSTREAM4DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4dvATI")) == NULL) || r;
+ r = ((glVertexStream4fATI = (PFNGLVERTEXSTREAM4FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4fATI")) == NULL) || r;
+ r = ((glVertexStream4fvATI = (PFNGLVERTEXSTREAM4FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4fvATI")) == NULL) || r;
+ r = ((glVertexStream4iATI = (PFNGLVERTEXSTREAM4IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4iATI")) == NULL) || r;
+ r = ((glVertexStream4ivATI = (PFNGLVERTEXSTREAM4IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4ivATI")) == NULL) || r;
+ r = ((glVertexStream4sATI = (PFNGLVERTEXSTREAM4SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4sATI")) == NULL) || r;
+ r = ((glVertexStream4svATI = (PFNGLVERTEXSTREAM4SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4svATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_ATI_vertex_streams */
+
+#ifdef GL_EXT_422_pixels
+
+#endif /* GL_EXT_422_pixels */
+
+#ifdef GL_EXT_Cg_shader
+
+#endif /* GL_EXT_Cg_shader */
+
+#ifdef GL_EXT_abgr
+
+#endif /* GL_EXT_abgr */
+
+#ifdef GL_EXT_bgra
+
+#endif /* GL_EXT_bgra */
+
+#ifdef GL_EXT_bindable_uniform
+
+static GLboolean _glewInit_GL_EXT_bindable_uniform (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetUniformBufferSizeEXT = (PFNGLGETUNIFORMBUFFERSIZEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformBufferSizeEXT")) == NULL) || r;
+ r = ((glGetUniformOffsetEXT = (PFNGLGETUNIFORMOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformOffsetEXT")) == NULL) || r;
+ r = ((glUniformBufferEXT = (PFNGLUNIFORMBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glUniformBufferEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_bindable_uniform */
+
+#ifdef GL_EXT_blend_color
+
+static GLboolean _glewInit_GL_EXT_blend_color (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendColorEXT = (PFNGLBLENDCOLOREXTPROC)glewGetProcAddress((const GLubyte*)"glBlendColorEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_blend_color */
+
+#ifdef GL_EXT_blend_equation_separate
+
+static GLboolean _glewInit_GL_EXT_blend_equation_separate (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquationSeparateEXT = (PFNGLBLENDEQUATIONSEPARATEEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparateEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_blend_equation_separate */
+
+#ifdef GL_EXT_blend_func_separate
+
+static GLboolean _glewInit_GL_EXT_blend_func_separate (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparateEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_blend_func_separate */
+
+#ifdef GL_EXT_blend_logic_op
+
+#endif /* GL_EXT_blend_logic_op */
+
+#ifdef GL_EXT_blend_minmax
+
+static GLboolean _glewInit_GL_EXT_blend_minmax (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlendEquationEXT = (PFNGLBLENDEQUATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_blend_minmax */
+
+#ifdef GL_EXT_blend_subtract
+
+#endif /* GL_EXT_blend_subtract */
+
+#ifdef GL_EXT_clip_volume_hint
+
+#endif /* GL_EXT_clip_volume_hint */
+
+#ifdef GL_EXT_cmyka
+
+#endif /* GL_EXT_cmyka */
+
+#ifdef GL_EXT_color_subtable
+
+static GLboolean _glewInit_GL_EXT_color_subtable (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorSubTableEXT = (PFNGLCOLORSUBTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glColorSubTableEXT")) == NULL) || r;
+ r = ((glCopyColorSubTableEXT = (PFNGLCOPYCOLORSUBTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyColorSubTableEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_color_subtable */
+
+#ifdef GL_EXT_compiled_vertex_array
+
+static GLboolean _glewInit_GL_EXT_compiled_vertex_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glLockArraysEXT")) == NULL) || r;
+ r = ((glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glUnlockArraysEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_compiled_vertex_array */
+
+#ifdef GL_EXT_convolution
+
+static GLboolean _glewInit_GL_EXT_convolution (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glConvolutionFilter1DEXT = (PFNGLCONVOLUTIONFILTER1DEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter1DEXT")) == NULL) || r;
+ r = ((glConvolutionFilter2DEXT = (PFNGLCONVOLUTIONFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter2DEXT")) == NULL) || r;
+ r = ((glConvolutionParameterfEXT = (PFNGLCONVOLUTIONPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfEXT")) == NULL) || r;
+ r = ((glConvolutionParameterfvEXT = (PFNGLCONVOLUTIONPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfvEXT")) == NULL) || r;
+ r = ((glConvolutionParameteriEXT = (PFNGLCONVOLUTIONPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteriEXT")) == NULL) || r;
+ r = ((glConvolutionParameterivEXT = (PFNGLCONVOLUTIONPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterivEXT")) == NULL) || r;
+ r = ((glCopyConvolutionFilter1DEXT = (PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter1DEXT")) == NULL) || r;
+ r = ((glCopyConvolutionFilter2DEXT = (PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter2DEXT")) == NULL) || r;
+ r = ((glGetConvolutionFilterEXT = (PFNGLGETCONVOLUTIONFILTEREXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionFilterEXT")) == NULL) || r;
+ r = ((glGetConvolutionParameterfvEXT = (PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterfvEXT")) == NULL) || r;
+ r = ((glGetConvolutionParameterivEXT = (PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterivEXT")) == NULL) || r;
+ r = ((glGetSeparableFilterEXT = (PFNGLGETSEPARABLEFILTEREXTPROC)glewGetProcAddress((const GLubyte*)"glGetSeparableFilterEXT")) == NULL) || r;
+ r = ((glSeparableFilter2DEXT = (PFNGLSEPARABLEFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glSeparableFilter2DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_convolution */
+
+#ifdef GL_EXT_coordinate_frame
+
+static GLboolean _glewInit_GL_EXT_coordinate_frame (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBinormalPointerEXT = (PFNGLBINORMALPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glBinormalPointerEXT")) == NULL) || r;
+ r = ((glTangentPointerEXT = (PFNGLTANGENTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glTangentPointerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_coordinate_frame */
+
+#ifdef GL_EXT_copy_texture
+
+static GLboolean _glewInit_GL_EXT_copy_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCopyTexImage1DEXT = (PFNGLCOPYTEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexImage1DEXT")) == NULL) || r;
+ r = ((glCopyTexImage2DEXT = (PFNGLCOPYTEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexImage2DEXT")) == NULL) || r;
+ r = ((glCopyTexSubImage1DEXT = (PFNGLCOPYTEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage1DEXT")) == NULL) || r;
+ r = ((glCopyTexSubImage2DEXT = (PFNGLCOPYTEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage2DEXT")) == NULL) || r;
+ r = ((glCopyTexSubImage3DEXT = (PFNGLCOPYTEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_copy_texture */
+
+#ifdef GL_EXT_cull_vertex
+
+static GLboolean _glewInit_GL_EXT_cull_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCullParameterdvEXT = (PFNGLCULLPARAMETERDVEXTPROC)glewGetProcAddress((const GLubyte*)"glCullParameterdvEXT")) == NULL) || r;
+ r = ((glCullParameterfvEXT = (PFNGLCULLPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glCullParameterfvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_cull_vertex */
+
+#ifdef GL_EXT_depth_bounds_test
+
+static GLboolean _glewInit_GL_EXT_depth_bounds_test (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDepthBoundsEXT = (PFNGLDEPTHBOUNDSEXTPROC)glewGetProcAddress((const GLubyte*)"glDepthBoundsEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_depth_bounds_test */
+
+#ifdef GL_EXT_direct_state_access
+
+static GLboolean _glewInit_GL_EXT_direct_state_access (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindMultiTextureEXT = (PFNGLBINDMULTITEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glBindMultiTextureEXT")) == NULL) || r;
+ r = ((glCheckNamedFramebufferStatusEXT = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC)glewGetProcAddress((const GLubyte*)"glCheckNamedFramebufferStatusEXT")) == NULL) || r;
+ r = ((glClientAttribDefaultEXT = (PFNGLCLIENTATTRIBDEFAULTEXTPROC)glewGetProcAddress((const GLubyte*)"glClientAttribDefaultEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexImage1DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexImage1DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexImage2DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexImage2DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexImage3DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexImage3DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexSubImage1DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexSubImage1DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexSubImage2DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexSubImage2DEXT")) == NULL) || r;
+ r = ((glCompressedMultiTexSubImage3DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexSubImage3DEXT")) == NULL) || r;
+ r = ((glCompressedTextureImage1DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureImage1DEXT")) == NULL) || r;
+ r = ((glCompressedTextureImage2DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureImage2DEXT")) == NULL) || r;
+ r = ((glCompressedTextureImage3DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureImage3DEXT")) == NULL) || r;
+ r = ((glCompressedTextureSubImage1DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureSubImage1DEXT")) == NULL) || r;
+ r = ((glCompressedTextureSubImage2DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureSubImage2DEXT")) == NULL) || r;
+ r = ((glCompressedTextureSubImage3DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureSubImage3DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexImage1DEXT = (PFNGLCOPYMULTITEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexImage1DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexImage2DEXT = (PFNGLCOPYMULTITEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexImage2DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexSubImage1DEXT = (PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexSubImage1DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexSubImage2DEXT = (PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexSubImage2DEXT")) == NULL) || r;
+ r = ((glCopyMultiTexSubImage3DEXT = (PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexSubImage3DEXT")) == NULL) || r;
+ r = ((glCopyTextureImage1DEXT = (PFNGLCOPYTEXTUREIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureImage1DEXT")) == NULL) || r;
+ r = ((glCopyTextureImage2DEXT = (PFNGLCOPYTEXTUREIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureImage2DEXT")) == NULL) || r;
+ r = ((glCopyTextureSubImage1DEXT = (PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureSubImage1DEXT")) == NULL) || r;
+ r = ((glCopyTextureSubImage2DEXT = (PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureSubImage2DEXT")) == NULL) || r;
+ r = ((glCopyTextureSubImage3DEXT = (PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureSubImage3DEXT")) == NULL) || r;
+ r = ((glDisableClientStateIndexedEXT = (PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableClientStateIndexedEXT")) == NULL) || r;
+ r = ((glEnableClientStateIndexedEXT = (PFNGLENABLECLIENTSTATEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableClientStateIndexedEXT")) == NULL) || r;
+ r = ((glFramebufferDrawBufferEXT = (PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferDrawBufferEXT")) == NULL) || r;
+ r = ((glFramebufferDrawBuffersEXT = (PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferDrawBuffersEXT")) == NULL) || r;
+ r = ((glFramebufferReadBufferEXT = (PFNGLFRAMEBUFFERREADBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferReadBufferEXT")) == NULL) || r;
+ r = ((glGenerateMultiTexMipmapEXT = (PFNGLGENERATEMULTITEXMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateMultiTexMipmapEXT")) == NULL) || r;
+ r = ((glGenerateTextureMipmapEXT = (PFNGLGENERATETEXTUREMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateTextureMipmapEXT")) == NULL) || r;
+ r = ((glGetCompressedMultiTexImageEXT = (PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedMultiTexImageEXT")) == NULL) || r;
+ r = ((glGetCompressedTextureImageEXT = (PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTextureImageEXT")) == NULL) || r;
+ r = ((glGetDoubleIndexedvEXT = (PFNGLGETDOUBLEINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetDoubleIndexedvEXT")) == NULL) || r;
+ r = ((glGetFloatIndexedvEXT = (PFNGLGETFLOATINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFloatIndexedvEXT")) == NULL) || r;
+ r = ((glGetFramebufferParameterivEXT = (PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferParameterivEXT")) == NULL) || r;
+ r = ((glGetMultiTexEnvfvEXT = (PFNGLGETMULTITEXENVFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexEnvfvEXT")) == NULL) || r;
+ r = ((glGetMultiTexEnvivEXT = (PFNGLGETMULTITEXENVIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexEnvivEXT")) == NULL) || r;
+ r = ((glGetMultiTexGendvEXT = (PFNGLGETMULTITEXGENDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexGendvEXT")) == NULL) || r;
+ r = ((glGetMultiTexGenfvEXT = (PFNGLGETMULTITEXGENFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexGenfvEXT")) == NULL) || r;
+ r = ((glGetMultiTexGenivEXT = (PFNGLGETMULTITEXGENIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexGenivEXT")) == NULL) || r;
+ r = ((glGetMultiTexImageEXT = (PFNGLGETMULTITEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexImageEXT")) == NULL) || r;
+ r = ((glGetMultiTexLevelParameterfvEXT = (PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexLevelParameterfvEXT")) == NULL) || r;
+ r = ((glGetMultiTexLevelParameterivEXT = (PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexLevelParameterivEXT")) == NULL) || r;
+ r = ((glGetMultiTexParameterIivEXT = (PFNGLGETMULTITEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterIivEXT")) == NULL) || r;
+ r = ((glGetMultiTexParameterIuivEXT = (PFNGLGETMULTITEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterIuivEXT")) == NULL) || r;
+ r = ((glGetMultiTexParameterfvEXT = (PFNGLGETMULTITEXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterfvEXT")) == NULL) || r;
+ r = ((glGetMultiTexParameterivEXT = (PFNGLGETMULTITEXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterivEXT")) == NULL) || r;
+ r = ((glGetNamedBufferParameterivEXT = (PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferParameterivEXT")) == NULL) || r;
+ r = ((glGetNamedBufferPointervEXT = (PFNGLGETNAMEDBUFFERPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferPointervEXT")) == NULL) || r;
+ r = ((glGetNamedBufferSubDataEXT = (PFNGLGETNAMEDBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferSubDataEXT")) == NULL) || r;
+ r = ((glGetNamedFramebufferAttachmentParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedFramebufferAttachmentParameterivEXT")) == NULL) || r;
+ r = ((glGetNamedProgramLocalParameterIivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterIivEXT")) == NULL) || r;
+ r = ((glGetNamedProgramLocalParameterIuivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterIuivEXT")) == NULL) || r;
+ r = ((glGetNamedProgramLocalParameterdvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterdvEXT")) == NULL) || r;
+ r = ((glGetNamedProgramLocalParameterfvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterfvEXT")) == NULL) || r;
+ r = ((glGetNamedProgramStringEXT = (PFNGLGETNAMEDPROGRAMSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramStringEXT")) == NULL) || r;
+ r = ((glGetNamedProgramivEXT = (PFNGLGETNAMEDPROGRAMIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramivEXT")) == NULL) || r;
+ r = ((glGetNamedRenderbufferParameterivEXT = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedRenderbufferParameterivEXT")) == NULL) || r;
+ r = ((glGetPointerIndexedvEXT = (PFNGLGETPOINTERINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPointerIndexedvEXT")) == NULL) || r;
+ r = ((glGetTextureImageEXT = (PFNGLGETTEXTUREIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureImageEXT")) == NULL) || r;
+ r = ((glGetTextureLevelParameterfvEXT = (PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureLevelParameterfvEXT")) == NULL) || r;
+ r = ((glGetTextureLevelParameterivEXT = (PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureLevelParameterivEXT")) == NULL) || r;
+ r = ((glGetTextureParameterIivEXT = (PFNGLGETTEXTUREPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterIivEXT")) == NULL) || r;
+ r = ((glGetTextureParameterIuivEXT = (PFNGLGETTEXTUREPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterIuivEXT")) == NULL) || r;
+ r = ((glGetTextureParameterfvEXT = (PFNGLGETTEXTUREPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterfvEXT")) == NULL) || r;
+ r = ((glGetTextureParameterivEXT = (PFNGLGETTEXTUREPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterivEXT")) == NULL) || r;
+ r = ((glMapNamedBufferEXT = (PFNGLMAPNAMEDBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glMapNamedBufferEXT")) == NULL) || r;
+ r = ((glMatrixFrustumEXT = (PFNGLMATRIXFRUSTUMEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixFrustumEXT")) == NULL) || r;
+ r = ((glMatrixLoadIdentityEXT = (PFNGLMATRIXLOADIDENTITYEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadIdentityEXT")) == NULL) || r;
+ r = ((glMatrixLoadTransposedEXT = (PFNGLMATRIXLOADTRANSPOSEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadTransposedEXT")) == NULL) || r;
+ r = ((glMatrixLoadTransposefEXT = (PFNGLMATRIXLOADTRANSPOSEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadTransposefEXT")) == NULL) || r;
+ r = ((glMatrixLoaddEXT = (PFNGLMATRIXLOADDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoaddEXT")) == NULL) || r;
+ r = ((glMatrixLoadfEXT = (PFNGLMATRIXLOADFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadfEXT")) == NULL) || r;
+ r = ((glMatrixMultTransposedEXT = (PFNGLMATRIXMULTTRANSPOSEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultTransposedEXT")) == NULL) || r;
+ r = ((glMatrixMultTransposefEXT = (PFNGLMATRIXMULTTRANSPOSEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultTransposefEXT")) == NULL) || r;
+ r = ((glMatrixMultdEXT = (PFNGLMATRIXMULTDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultdEXT")) == NULL) || r;
+ r = ((glMatrixMultfEXT = (PFNGLMATRIXMULTFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultfEXT")) == NULL) || r;
+ r = ((glMatrixOrthoEXT = (PFNGLMATRIXORTHOEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixOrthoEXT")) == NULL) || r;
+ r = ((glMatrixPopEXT = (PFNGLMATRIXPOPEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixPopEXT")) == NULL) || r;
+ r = ((glMatrixPushEXT = (PFNGLMATRIXPUSHEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixPushEXT")) == NULL) || r;
+ r = ((glMatrixRotatedEXT = (PFNGLMATRIXROTATEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixRotatedEXT")) == NULL) || r;
+ r = ((glMatrixRotatefEXT = (PFNGLMATRIXROTATEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixRotatefEXT")) == NULL) || r;
+ r = ((glMatrixScaledEXT = (PFNGLMATRIXSCALEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixScaledEXT")) == NULL) || r;
+ r = ((glMatrixScalefEXT = (PFNGLMATRIXSCALEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixScalefEXT")) == NULL) || r;
+ r = ((glMatrixTranslatedEXT = (PFNGLMATRIXTRANSLATEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixTranslatedEXT")) == NULL) || r;
+ r = ((glMatrixTranslatefEXT = (PFNGLMATRIXTRANSLATEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixTranslatefEXT")) == NULL) || r;
+ r = ((glMultiTexBufferEXT = (PFNGLMULTITEXBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexBufferEXT")) == NULL) || r;
+ r = ((glMultiTexCoordPointerEXT = (PFNGLMULTITEXCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordPointerEXT")) == NULL) || r;
+ r = ((glMultiTexEnvfEXT = (PFNGLMULTITEXENVFEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnvfEXT")) == NULL) || r;
+ r = ((glMultiTexEnvfvEXT = (PFNGLMULTITEXENVFVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnvfvEXT")) == NULL) || r;
+ r = ((glMultiTexEnviEXT = (PFNGLMULTITEXENVIEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnviEXT")) == NULL) || r;
+ r = ((glMultiTexEnvivEXT = (PFNGLMULTITEXENVIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnvivEXT")) == NULL) || r;
+ r = ((glMultiTexGendEXT = (PFNGLMULTITEXGENDEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGendEXT")) == NULL) || r;
+ r = ((glMultiTexGendvEXT = (PFNGLMULTITEXGENDVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGendvEXT")) == NULL) || r;
+ r = ((glMultiTexGenfEXT = (PFNGLMULTITEXGENFEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGenfEXT")) == NULL) || r;
+ r = ((glMultiTexGenfvEXT = (PFNGLMULTITEXGENFVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGenfvEXT")) == NULL) || r;
+ r = ((glMultiTexGeniEXT = (PFNGLMULTITEXGENIEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGeniEXT")) == NULL) || r;
+ r = ((glMultiTexGenivEXT = (PFNGLMULTITEXGENIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGenivEXT")) == NULL) || r;
+ r = ((glMultiTexImage1DEXT = (PFNGLMULTITEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexImage1DEXT")) == NULL) || r;
+ r = ((glMultiTexImage2DEXT = (PFNGLMULTITEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexImage2DEXT")) == NULL) || r;
+ r = ((glMultiTexImage3DEXT = (PFNGLMULTITEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexImage3DEXT")) == NULL) || r;
+ r = ((glMultiTexParameterIivEXT = (PFNGLMULTITEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterIivEXT")) == NULL) || r;
+ r = ((glMultiTexParameterIuivEXT = (PFNGLMULTITEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterIuivEXT")) == NULL) || r;
+ r = ((glMultiTexParameterfEXT = (PFNGLMULTITEXPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterfEXT")) == NULL) || r;
+ r = ((glMultiTexParameterfvEXT = (PFNGLMULTITEXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterfvEXT")) == NULL) || r;
+ r = ((glMultiTexParameteriEXT = (PFNGLMULTITEXPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameteriEXT")) == NULL) || r;
+ r = ((glMultiTexParameterivEXT = (PFNGLMULTITEXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterivEXT")) == NULL) || r;
+ r = ((glMultiTexRenderbufferEXT = (PFNGLMULTITEXRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexRenderbufferEXT")) == NULL) || r;
+ r = ((glMultiTexSubImage1DEXT = (PFNGLMULTITEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexSubImage1DEXT")) == NULL) || r;
+ r = ((glMultiTexSubImage2DEXT = (PFNGLMULTITEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexSubImage2DEXT")) == NULL) || r;
+ r = ((glMultiTexSubImage3DEXT = (PFNGLMULTITEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexSubImage3DEXT")) == NULL) || r;
+ r = ((glNamedBufferDataEXT = (PFNGLNAMEDBUFFERDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedBufferDataEXT")) == NULL) || r;
+ r = ((glNamedBufferSubDataEXT = (PFNGLNAMEDBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedBufferSubDataEXT")) == NULL) || r;
+ r = ((glNamedFramebufferRenderbufferEXT = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferRenderbufferEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTexture1DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTexture1DEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTexture2DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTexture2DEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTexture3DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTexture3DEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTextureEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTextureEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTextureFaceEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTextureFaceEXT")) == NULL) || r;
+ r = ((glNamedFramebufferTextureLayerEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTextureLayerEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameter4dEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4dEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameter4dvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4dvEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameter4fEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4fEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameter4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4fvEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameterI4iEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4iEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameterI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4ivEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameterI4uiEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4uiEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameterI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4uivEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParameters4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameters4fvEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParametersI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParametersI4ivEXT")) == NULL) || r;
+ r = ((glNamedProgramLocalParametersI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParametersI4uivEXT")) == NULL) || r;
+ r = ((glNamedProgramStringEXT = (PFNGLNAMEDPROGRAMSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramStringEXT")) == NULL) || r;
+ r = ((glNamedRenderbufferStorageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedRenderbufferStorageEXT")) == NULL) || r;
+ r = ((glNamedRenderbufferStorageMultisampleCoverageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedRenderbufferStorageMultisampleCoverageEXT")) == NULL) || r;
+ r = ((glNamedRenderbufferStorageMultisampleEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedRenderbufferStorageMultisampleEXT")) == NULL) || r;
+ r = ((glProgramUniform1fEXT = (PFNGLPROGRAMUNIFORM1FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1fEXT")) == NULL) || r;
+ r = ((glProgramUniform1fvEXT = (PFNGLPROGRAMUNIFORM1FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1fvEXT")) == NULL) || r;
+ r = ((glProgramUniform1iEXT = (PFNGLPROGRAMUNIFORM1IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1iEXT")) == NULL) || r;
+ r = ((glProgramUniform1ivEXT = (PFNGLPROGRAMUNIFORM1IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1ivEXT")) == NULL) || r;
+ r = ((glProgramUniform1uiEXT = (PFNGLPROGRAMUNIFORM1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1uiEXT")) == NULL) || r;
+ r = ((glProgramUniform1uivEXT = (PFNGLPROGRAMUNIFORM1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1uivEXT")) == NULL) || r;
+ r = ((glProgramUniform2fEXT = (PFNGLPROGRAMUNIFORM2FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2fEXT")) == NULL) || r;
+ r = ((glProgramUniform2fvEXT = (PFNGLPROGRAMUNIFORM2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2fvEXT")) == NULL) || r;
+ r = ((glProgramUniform2iEXT = (PFNGLPROGRAMUNIFORM2IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2iEXT")) == NULL) || r;
+ r = ((glProgramUniform2ivEXT = (PFNGLPROGRAMUNIFORM2IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2ivEXT")) == NULL) || r;
+ r = ((glProgramUniform2uiEXT = (PFNGLPROGRAMUNIFORM2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2uiEXT")) == NULL) || r;
+ r = ((glProgramUniform2uivEXT = (PFNGLPROGRAMUNIFORM2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2uivEXT")) == NULL) || r;
+ r = ((glProgramUniform3fEXT = (PFNGLPROGRAMUNIFORM3FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3fEXT")) == NULL) || r;
+ r = ((glProgramUniform3fvEXT = (PFNGLPROGRAMUNIFORM3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3fvEXT")) == NULL) || r;
+ r = ((glProgramUniform3iEXT = (PFNGLPROGRAMUNIFORM3IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3iEXT")) == NULL) || r;
+ r = ((glProgramUniform3ivEXT = (PFNGLPROGRAMUNIFORM3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3ivEXT")) == NULL) || r;
+ r = ((glProgramUniform3uiEXT = (PFNGLPROGRAMUNIFORM3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3uiEXT")) == NULL) || r;
+ r = ((glProgramUniform3uivEXT = (PFNGLPROGRAMUNIFORM3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3uivEXT")) == NULL) || r;
+ r = ((glProgramUniform4fEXT = (PFNGLPROGRAMUNIFORM4FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4fEXT")) == NULL) || r;
+ r = ((glProgramUniform4fvEXT = (PFNGLPROGRAMUNIFORM4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4fvEXT")) == NULL) || r;
+ r = ((glProgramUniform4iEXT = (PFNGLPROGRAMUNIFORM4IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4iEXT")) == NULL) || r;
+ r = ((glProgramUniform4ivEXT = (PFNGLPROGRAMUNIFORM4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4ivEXT")) == NULL) || r;
+ r = ((glProgramUniform4uiEXT = (PFNGLPROGRAMUNIFORM4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4uiEXT")) == NULL) || r;
+ r = ((glProgramUniform4uivEXT = (PFNGLPROGRAMUNIFORM4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4uivEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix2x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix3x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2fvEXT")) == NULL) || r;
+ r = ((glProgramUniformMatrix4x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3fvEXT")) == NULL) || r;
+ r = ((glPushClientAttribDefaultEXT = (PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC)glewGetProcAddress((const GLubyte*)"glPushClientAttribDefaultEXT")) == NULL) || r;
+ r = ((glTextureBufferEXT = (PFNGLTEXTUREBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTextureBufferEXT")) == NULL) || r;
+ r = ((glTextureImage1DEXT = (PFNGLTEXTUREIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureImage1DEXT")) == NULL) || r;
+ r = ((glTextureImage2DEXT = (PFNGLTEXTUREIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureImage2DEXT")) == NULL) || r;
+ r = ((glTextureImage3DEXT = (PFNGLTEXTUREIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureImage3DEXT")) == NULL) || r;
+ r = ((glTextureParameterIivEXT = (PFNGLTEXTUREPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterIivEXT")) == NULL) || r;
+ r = ((glTextureParameterIuivEXT = (PFNGLTEXTUREPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterIuivEXT")) == NULL) || r;
+ r = ((glTextureParameterfEXT = (PFNGLTEXTUREPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterfEXT")) == NULL) || r;
+ r = ((glTextureParameterfvEXT = (PFNGLTEXTUREPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterfvEXT")) == NULL) || r;
+ r = ((glTextureParameteriEXT = (PFNGLTEXTUREPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameteriEXT")) == NULL) || r;
+ r = ((glTextureParameterivEXT = (PFNGLTEXTUREPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterivEXT")) == NULL) || r;
+ r = ((glTextureRenderbufferEXT = (PFNGLTEXTURERENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTextureRenderbufferEXT")) == NULL) || r;
+ r = ((glTextureSubImage1DEXT = (PFNGLTEXTURESUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureSubImage1DEXT")) == NULL) || r;
+ r = ((glTextureSubImage2DEXT = (PFNGLTEXTURESUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureSubImage2DEXT")) == NULL) || r;
+ r = ((glTextureSubImage3DEXT = (PFNGLTEXTURESUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureSubImage3DEXT")) == NULL) || r;
+ r = ((glUnmapNamedBufferEXT = (PFNGLUNMAPNAMEDBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glUnmapNamedBufferEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_direct_state_access */
+
+#ifdef GL_EXT_draw_buffers2
+
+static GLboolean _glewInit_GL_EXT_draw_buffers2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorMaskIndexedEXT = (PFNGLCOLORMASKINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glColorMaskIndexedEXT")) == NULL) || r;
+ r = ((glDisableIndexedEXT = (PFNGLDISABLEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableIndexedEXT")) == NULL) || r;
+ r = ((glEnableIndexedEXT = (PFNGLENABLEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableIndexedEXT")) == NULL) || r;
+ r = ((glGetBooleanIndexedvEXT = (PFNGLGETBOOLEANINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetBooleanIndexedvEXT")) == NULL) || r;
+ r = ((glGetIntegerIndexedvEXT = (PFNGLGETINTEGERINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetIntegerIndexedvEXT")) == NULL) || r;
+ r = ((glIsEnabledIndexedEXT = (PFNGLISENABLEDINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glIsEnabledIndexedEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_draw_buffers2 */
+
+#ifdef GL_EXT_draw_instanced
+
+static GLboolean _glewInit_GL_EXT_draw_instanced (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedEXT")) == NULL) || r;
+ r = ((glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_draw_instanced */
+
+#ifdef GL_EXT_draw_range_elements
+
+static GLboolean _glewInit_GL_EXT_draw_range_elements (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDrawRangeElementsEXT = (PFNGLDRAWRANGEELEMENTSEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementsEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_draw_range_elements */
+
+#ifdef GL_EXT_fog_coord
+
+static GLboolean _glewInit_GL_EXT_fog_coord (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFogCoordPointerEXT = (PFNGLFOGCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointerEXT")) == NULL) || r;
+ r = ((glFogCoorddEXT = (PFNGLFOGCOORDDEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddEXT")) == NULL) || r;
+ r = ((glFogCoorddvEXT = (PFNGLFOGCOORDDVEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddvEXT")) == NULL) || r;
+ r = ((glFogCoordfEXT = (PFNGLFOGCOORDFEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfEXT")) == NULL) || r;
+ r = ((glFogCoordfvEXT = (PFNGLFOGCOORDFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_fog_coord */
+
+#ifdef GL_EXT_fragment_lighting
+
+static GLboolean _glewInit_GL_EXT_fragment_lighting (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFragmentColorMaterialEXT = (PFNGLFRAGMENTCOLORMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentColorMaterialEXT")) == NULL) || r;
+ r = ((glFragmentLightModelfEXT = (PFNGLFRAGMENTLIGHTMODELFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfEXT")) == NULL) || r;
+ r = ((glFragmentLightModelfvEXT = (PFNGLFRAGMENTLIGHTMODELFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfvEXT")) == NULL) || r;
+ r = ((glFragmentLightModeliEXT = (PFNGLFRAGMENTLIGHTMODELIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModeliEXT")) == NULL) || r;
+ r = ((glFragmentLightModelivEXT = (PFNGLFRAGMENTLIGHTMODELIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelivEXT")) == NULL) || r;
+ r = ((glFragmentLightfEXT = (PFNGLFRAGMENTLIGHTFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfEXT")) == NULL) || r;
+ r = ((glFragmentLightfvEXT = (PFNGLFRAGMENTLIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfvEXT")) == NULL) || r;
+ r = ((glFragmentLightiEXT = (PFNGLFRAGMENTLIGHTIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightiEXT")) == NULL) || r;
+ r = ((glFragmentLightivEXT = (PFNGLFRAGMENTLIGHTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightivEXT")) == NULL) || r;
+ r = ((glFragmentMaterialfEXT = (PFNGLFRAGMENTMATERIALFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfEXT")) == NULL) || r;
+ r = ((glFragmentMaterialfvEXT = (PFNGLFRAGMENTMATERIALFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfvEXT")) == NULL) || r;
+ r = ((glFragmentMaterialiEXT = (PFNGLFRAGMENTMATERIALIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialiEXT")) == NULL) || r;
+ r = ((glFragmentMaterialivEXT = (PFNGLFRAGMENTMATERIALIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialivEXT")) == NULL) || r;
+ r = ((glGetFragmentLightfvEXT = (PFNGLGETFRAGMENTLIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightfvEXT")) == NULL) || r;
+ r = ((glGetFragmentLightivEXT = (PFNGLGETFRAGMENTLIGHTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightivEXT")) == NULL) || r;
+ r = ((glGetFragmentMaterialfvEXT = (PFNGLGETFRAGMENTMATERIALFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialfvEXT")) == NULL) || r;
+ r = ((glGetFragmentMaterialivEXT = (PFNGLGETFRAGMENTMATERIALIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialivEXT")) == NULL) || r;
+ r = ((glLightEnviEXT = (PFNGLLIGHTENVIEXTPROC)glewGetProcAddress((const GLubyte*)"glLightEnviEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_fragment_lighting */
+
+#ifdef GL_EXT_framebuffer_blit
+
+static GLboolean _glewInit_GL_EXT_framebuffer_blit (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebufferEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_framebuffer_blit */
+
+#ifdef GL_EXT_framebuffer_multisample
+
+static GLboolean _glewInit_GL_EXT_framebuffer_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_framebuffer_multisample */
+
+#ifdef GL_EXT_framebuffer_object
+
+static GLboolean _glewInit_GL_EXT_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindFramebufferEXT")) == NULL) || r;
+ r = ((glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbufferEXT")) == NULL) || r;
+ r = ((glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatusEXT")) == NULL) || r;
+ r = ((glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteFramebuffersEXT")) == NULL) || r;
+ r = ((glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteRenderbuffersEXT")) == NULL) || r;
+ r = ((glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferRenderbufferEXT")) == NULL) || r;
+ r = ((glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture1DEXT")) == NULL) || r;
+ r = ((glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2DEXT")) == NULL) || r;
+ r = ((glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture3DEXT")) == NULL) || r;
+ r = ((glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenFramebuffersEXT")) == NULL) || r;
+ r = ((glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenRenderbuffersEXT")) == NULL) || r;
+ r = ((glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateMipmapEXT")) == NULL) || r;
+ r = ((glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferAttachmentParameterivEXT")) == NULL) || r;
+ r = ((glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetRenderbufferParameterivEXT")) == NULL) || r;
+ r = ((glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glIsFramebufferEXT")) == NULL) || r;
+ r = ((glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glIsRenderbufferEXT")) == NULL) || r;
+ r = ((glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_framebuffer_object */
+
+#ifdef GL_EXT_framebuffer_sRGB
+
+#endif /* GL_EXT_framebuffer_sRGB */
+
+#ifdef GL_EXT_geometry_shader4
+
+static GLboolean _glewInit_GL_EXT_geometry_shader4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureEXT")) == NULL) || r;
+ r = ((glFramebufferTextureFaceEXT = (PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureFaceEXT")) == NULL) || r;
+ r = ((glFramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayerEXT")) == NULL) || r;
+ r = ((glProgramParameteriEXT = (PFNGLPROGRAMPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramParameteriEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_geometry_shader4 */
+
+#ifdef GL_EXT_gpu_program_parameters
+
+static GLboolean _glewInit_GL_EXT_gpu_program_parameters (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProgramEnvParameters4fvEXT = (PFNGLPROGRAMENVPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameters4fvEXT")) == NULL) || r;
+ r = ((glProgramLocalParameters4fvEXT = (PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameters4fvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_gpu_program_parameters */
+
+#ifdef GL_EXT_gpu_shader4
+
+static GLboolean _glewInit_GL_EXT_gpu_shader4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBindFragDataLocationEXT = (PFNGLBINDFRAGDATALOCATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glBindFragDataLocationEXT")) == NULL) || r;
+ r = ((glGetFragDataLocationEXT = (PFNGLGETFRAGDATALOCATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragDataLocationEXT")) == NULL) || r;
+ r = ((glGetUniformuivEXT = (PFNGLGETUNIFORMUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformuivEXT")) == NULL) || r;
+ r = ((glGetVertexAttribIivEXT = (PFNGLGETVERTEXATTRIBIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIivEXT")) == NULL) || r;
+ r = ((glGetVertexAttribIuivEXT = (PFNGLGETVERTEXATTRIBIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIuivEXT")) == NULL) || r;
+ r = ((glUniform1uiEXT = (PFNGLUNIFORM1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform1uiEXT")) == NULL) || r;
+ r = ((glUniform1uivEXT = (PFNGLUNIFORM1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform1uivEXT")) == NULL) || r;
+ r = ((glUniform2uiEXT = (PFNGLUNIFORM2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform2uiEXT")) == NULL) || r;
+ r = ((glUniform2uivEXT = (PFNGLUNIFORM2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform2uivEXT")) == NULL) || r;
+ r = ((glUniform3uiEXT = (PFNGLUNIFORM3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform3uiEXT")) == NULL) || r;
+ r = ((glUniform3uivEXT = (PFNGLUNIFORM3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform3uivEXT")) == NULL) || r;
+ r = ((glUniform4uiEXT = (PFNGLUNIFORM4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform4uiEXT")) == NULL) || r;
+ r = ((glUniform4uivEXT = (PFNGLUNIFORM4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform4uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI1iEXT = (PFNGLVERTEXATTRIBI1IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1iEXT")) == NULL) || r;
+ r = ((glVertexAttribI1ivEXT = (PFNGLVERTEXATTRIBI1IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1ivEXT")) == NULL) || r;
+ r = ((glVertexAttribI1uiEXT = (PFNGLVERTEXATTRIBI1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uiEXT")) == NULL) || r;
+ r = ((glVertexAttribI1uivEXT = (PFNGLVERTEXATTRIBI1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI2iEXT = (PFNGLVERTEXATTRIBI2IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2iEXT")) == NULL) || r;
+ r = ((glVertexAttribI2ivEXT = (PFNGLVERTEXATTRIBI2IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2ivEXT")) == NULL) || r;
+ r = ((glVertexAttribI2uiEXT = (PFNGLVERTEXATTRIBI2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uiEXT")) == NULL) || r;
+ r = ((glVertexAttribI2uivEXT = (PFNGLVERTEXATTRIBI2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI3iEXT = (PFNGLVERTEXATTRIBI3IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3iEXT")) == NULL) || r;
+ r = ((glVertexAttribI3ivEXT = (PFNGLVERTEXATTRIBI3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3ivEXT")) == NULL) || r;
+ r = ((glVertexAttribI3uiEXT = (PFNGLVERTEXATTRIBI3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uiEXT")) == NULL) || r;
+ r = ((glVertexAttribI3uivEXT = (PFNGLVERTEXATTRIBI3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI4bvEXT = (PFNGLVERTEXATTRIBI4BVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4bvEXT")) == NULL) || r;
+ r = ((glVertexAttribI4iEXT = (PFNGLVERTEXATTRIBI4IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4iEXT")) == NULL) || r;
+ r = ((glVertexAttribI4ivEXT = (PFNGLVERTEXATTRIBI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ivEXT")) == NULL) || r;
+ r = ((glVertexAttribI4svEXT = (PFNGLVERTEXATTRIBI4SVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4svEXT")) == NULL) || r;
+ r = ((glVertexAttribI4ubvEXT = (PFNGLVERTEXATTRIBI4UBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ubvEXT")) == NULL) || r;
+ r = ((glVertexAttribI4uiEXT = (PFNGLVERTEXATTRIBI4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uiEXT")) == NULL) || r;
+ r = ((glVertexAttribI4uivEXT = (PFNGLVERTEXATTRIBI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uivEXT")) == NULL) || r;
+ r = ((glVertexAttribI4usvEXT = (PFNGLVERTEXATTRIBI4USVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4usvEXT")) == NULL) || r;
+ r = ((glVertexAttribIPointerEXT = (PFNGLVERTEXATTRIBIPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIPointerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_gpu_shader4 */
+
+#ifdef GL_EXT_histogram
+
+static GLboolean _glewInit_GL_EXT_histogram (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetHistogramEXT = (PFNGLGETHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramEXT")) == NULL) || r;
+ r = ((glGetHistogramParameterfvEXT = (PFNGLGETHISTOGRAMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterfvEXT")) == NULL) || r;
+ r = ((glGetHistogramParameterivEXT = (PFNGLGETHISTOGRAMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterivEXT")) == NULL) || r;
+ r = ((glGetMinmaxEXT = (PFNGLGETMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxEXT")) == NULL) || r;
+ r = ((glGetMinmaxParameterfvEXT = (PFNGLGETMINMAXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterfvEXT")) == NULL) || r;
+ r = ((glGetMinmaxParameterivEXT = (PFNGLGETMINMAXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterivEXT")) == NULL) || r;
+ r = ((glHistogramEXT = (PFNGLHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glHistogramEXT")) == NULL) || r;
+ r = ((glMinmaxEXT = (PFNGLMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glMinmaxEXT")) == NULL) || r;
+ r = ((glResetHistogramEXT = (PFNGLRESETHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glResetHistogramEXT")) == NULL) || r;
+ r = ((glResetMinmaxEXT = (PFNGLRESETMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glResetMinmaxEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_histogram */
+
+#ifdef GL_EXT_index_array_formats
+
+#endif /* GL_EXT_index_array_formats */
+
+#ifdef GL_EXT_index_func
+
+static GLboolean _glewInit_GL_EXT_index_func (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glIndexFuncEXT = (PFNGLINDEXFUNCEXTPROC)glewGetProcAddress((const GLubyte*)"glIndexFuncEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_index_func */
+
+#ifdef GL_EXT_index_material
+
+static GLboolean _glewInit_GL_EXT_index_material (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glIndexMaterialEXT = (PFNGLINDEXMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glIndexMaterialEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_index_material */
+
+#ifdef GL_EXT_index_texture
+
+#endif /* GL_EXT_index_texture */
+
+#ifdef GL_EXT_light_texture
+
+static GLboolean _glewInit_GL_EXT_light_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glApplyTextureEXT = (PFNGLAPPLYTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glApplyTextureEXT")) == NULL) || r;
+ r = ((glTextureLightEXT = (PFNGLTEXTURELIGHTEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureLightEXT")) == NULL) || r;
+ r = ((glTextureMaterialEXT = (PFNGLTEXTUREMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureMaterialEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_light_texture */
+
+#ifdef GL_EXT_misc_attribute
+
+#endif /* GL_EXT_misc_attribute */
+
+#ifdef GL_EXT_multi_draw_arrays
+
+static GLboolean _glewInit_GL_EXT_multi_draw_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysEXT")) == NULL) || r;
+ r = ((glMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_multi_draw_arrays */
+
+#ifdef GL_EXT_multisample
+
+static GLboolean _glewInit_GL_EXT_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSampleMaskEXT = (PFNGLSAMPLEMASKEXTPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskEXT")) == NULL) || r;
+ r = ((glSamplePatternEXT = (PFNGLSAMPLEPATTERNEXTPROC)glewGetProcAddress((const GLubyte*)"glSamplePatternEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_multisample */
+
+#ifdef GL_EXT_packed_depth_stencil
+
+#endif /* GL_EXT_packed_depth_stencil */
+
+#ifdef GL_EXT_packed_float
+
+#endif /* GL_EXT_packed_float */
+
+#ifdef GL_EXT_packed_pixels
+
+#endif /* GL_EXT_packed_pixels */
+
+#ifdef GL_EXT_paletted_texture
+
+static GLboolean _glewInit_GL_EXT_paletted_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorTableEXT = (PFNGLCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glColorTableEXT")) == NULL) || r;
+ r = ((glGetColorTableEXT = (PFNGLGETCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableEXT")) == NULL) || r;
+ r = ((glGetColorTableParameterfvEXT = (PFNGLGETCOLORTABLEPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfvEXT")) == NULL) || r;
+ r = ((glGetColorTableParameterivEXT = (PFNGLGETCOLORTABLEPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterivEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_paletted_texture */
+
+#ifdef GL_EXT_pixel_buffer_object
+
+#endif /* GL_EXT_pixel_buffer_object */
+
+#ifdef GL_EXT_pixel_transform
+
+static GLboolean _glewInit_GL_EXT_pixel_transform (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetPixelTransformParameterfvEXT = (PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPixelTransformParameterfvEXT")) == NULL) || r;
+ r = ((glGetPixelTransformParameterivEXT = (PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPixelTransformParameterivEXT")) == NULL) || r;
+ r = ((glPixelTransformParameterfEXT = (PFNGLPIXELTRANSFORMPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterfEXT")) == NULL) || r;
+ r = ((glPixelTransformParameterfvEXT = (PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterfvEXT")) == NULL) || r;
+ r = ((glPixelTransformParameteriEXT = (PFNGLPIXELTRANSFORMPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameteriEXT")) == NULL) || r;
+ r = ((glPixelTransformParameterivEXT = (PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterivEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_pixel_transform */
+
+#ifdef GL_EXT_pixel_transform_color_table
+
+#endif /* GL_EXT_pixel_transform_color_table */
+
+#ifdef GL_EXT_point_parameters
+
+static GLboolean _glewInit_GL_EXT_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfEXT")) == NULL) || r;
+ r = ((glPointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_point_parameters */
+
+#ifdef GL_EXT_polygon_offset
+
+static GLboolean _glewInit_GL_EXT_polygon_offset (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPolygonOffsetEXT = (PFNGLPOLYGONOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glPolygonOffsetEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_polygon_offset */
+
+#ifdef GL_EXT_rescale_normal
+
+#endif /* GL_EXT_rescale_normal */
+
+#ifdef GL_EXT_scene_marker
+
+static GLboolean _glewInit_GL_EXT_scene_marker (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginSceneEXT = (PFNGLBEGINSCENEEXTPROC)glewGetProcAddress((const GLubyte*)"glBeginSceneEXT")) == NULL) || r;
+ r = ((glEndSceneEXT = (PFNGLENDSCENEEXTPROC)glewGetProcAddress((const GLubyte*)"glEndSceneEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_scene_marker */
+
+#ifdef GL_EXT_secondary_color
+
+static GLboolean _glewInit_GL_EXT_secondary_color (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSecondaryColor3bEXT = (PFNGLSECONDARYCOLOR3BEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bEXT")) == NULL) || r;
+ r = ((glSecondaryColor3bvEXT = (PFNGLSECONDARYCOLOR3BVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bvEXT")) == NULL) || r;
+ r = ((glSecondaryColor3dEXT = (PFNGLSECONDARYCOLOR3DEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dEXT")) == NULL) || r;
+ r = ((glSecondaryColor3dvEXT = (PFNGLSECONDARYCOLOR3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dvEXT")) == NULL) || r;
+ r = ((glSecondaryColor3fEXT = (PFNGLSECONDARYCOLOR3FEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fEXT")) == NULL) || r;
+ r = ((glSecondaryColor3fvEXT = (PFNGLSECONDARYCOLOR3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fvEXT")) == NULL) || r;
+ r = ((glSecondaryColor3iEXT = (PFNGLSECONDARYCOLOR3IEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3iEXT")) == NULL) || r;
+ r = ((glSecondaryColor3ivEXT = (PFNGLSECONDARYCOLOR3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ivEXT")) == NULL) || r;
+ r = ((glSecondaryColor3sEXT = (PFNGLSECONDARYCOLOR3SEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3sEXT")) == NULL) || r;
+ r = ((glSecondaryColor3svEXT = (PFNGLSECONDARYCOLOR3SVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3svEXT")) == NULL) || r;
+ r = ((glSecondaryColor3ubEXT = (PFNGLSECONDARYCOLOR3UBEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubEXT")) == NULL) || r;
+ r = ((glSecondaryColor3ubvEXT = (PFNGLSECONDARYCOLOR3UBVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubvEXT")) == NULL) || r;
+ r = ((glSecondaryColor3uiEXT = (PFNGLSECONDARYCOLOR3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uiEXT")) == NULL) || r;
+ r = ((glSecondaryColor3uivEXT = (PFNGLSECONDARYCOLOR3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uivEXT")) == NULL) || r;
+ r = ((glSecondaryColor3usEXT = (PFNGLSECONDARYCOLOR3USEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usEXT")) == NULL) || r;
+ r = ((glSecondaryColor3usvEXT = (PFNGLSECONDARYCOLOR3USVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usvEXT")) == NULL) || r;
+ r = ((glSecondaryColorPointerEXT = (PFNGLSECONDARYCOLORPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_secondary_color */
+
+#ifdef GL_EXT_separate_specular_color
+
+#endif /* GL_EXT_separate_specular_color */
+
+#ifdef GL_EXT_shadow_funcs
+
+#endif /* GL_EXT_shadow_funcs */
+
+#ifdef GL_EXT_shared_texture_palette
+
+#endif /* GL_EXT_shared_texture_palette */
+
+#ifdef GL_EXT_stencil_clear_tag
+
+#endif /* GL_EXT_stencil_clear_tag */
+
+#ifdef GL_EXT_stencil_two_side
+
+static GLboolean _glewInit_GL_EXT_stencil_two_side (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glActiveStencilFaceEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_stencil_two_side */
+
+#ifdef GL_EXT_stencil_wrap
+
+#endif /* GL_EXT_stencil_wrap */
+
+#ifdef GL_EXT_subtexture
+
+static GLboolean _glewInit_GL_EXT_subtexture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexSubImage1DEXT = (PFNGLTEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage1DEXT")) == NULL) || r;
+ r = ((glTexSubImage2DEXT = (PFNGLTEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage2DEXT")) == NULL) || r;
+ r = ((glTexSubImage3DEXT = (PFNGLTEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_subtexture */
+
+#ifdef GL_EXT_texture
+
+#endif /* GL_EXT_texture */
+
+#ifdef GL_EXT_texture3D
+
+static GLboolean _glewInit_GL_EXT_texture3D (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexImage3DEXT = (PFNGLTEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture3D */
+
+#ifdef GL_EXT_texture_array
+
+#endif /* GL_EXT_texture_array */
+
+#ifdef GL_EXT_texture_buffer_object
+
+static GLboolean _glewInit_GL_EXT_texture_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexBufferEXT = (PFNGLTEXBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTexBufferEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_buffer_object */
+
+#ifdef GL_EXT_texture_compression_dxt1
+
+#endif /* GL_EXT_texture_compression_dxt1 */
+
+#ifdef GL_EXT_texture_compression_latc
+
+#endif /* GL_EXT_texture_compression_latc */
+
+#ifdef GL_EXT_texture_compression_rgtc
+
+#endif /* GL_EXT_texture_compression_rgtc */
+
+#ifdef GL_EXT_texture_compression_s3tc
+
+#endif /* GL_EXT_texture_compression_s3tc */
+
+#ifdef GL_EXT_texture_cube_map
+
+#endif /* GL_EXT_texture_cube_map */
+
+#ifdef GL_EXT_texture_edge_clamp
+
+#endif /* GL_EXT_texture_edge_clamp */
+
+#ifdef GL_EXT_texture_env
+
+#endif /* GL_EXT_texture_env */
+
+#ifdef GL_EXT_texture_env_add
+
+#endif /* GL_EXT_texture_env_add */
+
+#ifdef GL_EXT_texture_env_combine
+
+#endif /* GL_EXT_texture_env_combine */
+
+#ifdef GL_EXT_texture_env_dot3
+
+#endif /* GL_EXT_texture_env_dot3 */
+
+#ifdef GL_EXT_texture_filter_anisotropic
+
+#endif /* GL_EXT_texture_filter_anisotropic */
+
+#ifdef GL_EXT_texture_integer
+
+static GLboolean _glewInit_GL_EXT_texture_integer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearColorIiEXT = (PFNGLCLEARCOLORIIEXTPROC)glewGetProcAddress((const GLubyte*)"glClearColorIiEXT")) == NULL) || r;
+ r = ((glClearColorIuiEXT = (PFNGLCLEARCOLORIUIEXTPROC)glewGetProcAddress((const GLubyte*)"glClearColorIuiEXT")) == NULL) || r;
+ r = ((glGetTexParameterIivEXT = (PFNGLGETTEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIivEXT")) == NULL) || r;
+ r = ((glGetTexParameterIuivEXT = (PFNGLGETTEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIuivEXT")) == NULL) || r;
+ r = ((glTexParameterIivEXT = (PFNGLTEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIivEXT")) == NULL) || r;
+ r = ((glTexParameterIuivEXT = (PFNGLTEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIuivEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_integer */
+
+#ifdef GL_EXT_texture_lod_bias
+
+#endif /* GL_EXT_texture_lod_bias */
+
+#ifdef GL_EXT_texture_mirror_clamp
+
+#endif /* GL_EXT_texture_mirror_clamp */
+
+#ifdef GL_EXT_texture_object
+
+static GLboolean _glewInit_GL_EXT_texture_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAreTexturesResidentEXT = (PFNGLARETEXTURESRESIDENTEXTPROC)glewGetProcAddress((const GLubyte*)"glAreTexturesResidentEXT")) == NULL) || r;
+ r = ((glBindTextureEXT = (PFNGLBINDTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glBindTextureEXT")) == NULL) || r;
+ r = ((glDeleteTexturesEXT = (PFNGLDELETETEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteTexturesEXT")) == NULL) || r;
+ r = ((glGenTexturesEXT = (PFNGLGENTEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glGenTexturesEXT")) == NULL) || r;
+ r = ((glIsTextureEXT = (PFNGLISTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glIsTextureEXT")) == NULL) || r;
+ r = ((glPrioritizeTexturesEXT = (PFNGLPRIORITIZETEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glPrioritizeTexturesEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_object */
+
+#ifdef GL_EXT_texture_perturb_normal
+
+static GLboolean _glewInit_GL_EXT_texture_perturb_normal (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTextureNormalEXT = (PFNGLTEXTURENORMALEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureNormalEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_texture_perturb_normal */
+
+#ifdef GL_EXT_texture_rectangle
+
+#endif /* GL_EXT_texture_rectangle */
+
+#ifdef GL_EXT_texture_sRGB
+
+#endif /* GL_EXT_texture_sRGB */
+
+#ifdef GL_EXT_texture_shared_exponent
+
+#endif /* GL_EXT_texture_shared_exponent */
+
+#ifdef GL_EXT_texture_swizzle
+
+#endif /* GL_EXT_texture_swizzle */
+
+#ifdef GL_EXT_timer_query
+
+static GLboolean _glewInit_GL_EXT_timer_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetQueryObjecti64vEXT = (PFNGLGETQUERYOBJECTI64VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjecti64vEXT")) == NULL) || r;
+ r = ((glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectui64vEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_timer_query */
+
+#ifdef GL_EXT_transform_feedback
+
+static GLboolean _glewInit_GL_EXT_transform_feedback (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginTransformFeedbackEXT = (PFNGLBEGINTRANSFORMFEEDBACKEXTPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedbackEXT")) == NULL) || r;
+ r = ((glBindBufferBaseEXT = (PFNGLBINDBUFFERBASEEXTPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBaseEXT")) == NULL) || r;
+ r = ((glBindBufferOffsetEXT = (PFNGLBINDBUFFEROFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glBindBufferOffsetEXT")) == NULL) || r;
+ r = ((glBindBufferRangeEXT = (PFNGLBINDBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRangeEXT")) == NULL) || r;
+ r = ((glEndTransformFeedbackEXT = (PFNGLENDTRANSFORMFEEDBACKEXTPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedbackEXT")) == NULL) || r;
+ r = ((glGetTransformFeedbackVaryingEXT = (PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVaryingEXT")) == NULL) || r;
+ r = ((glTransformFeedbackVaryingsEXT = (PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryingsEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_transform_feedback */
+
+#ifdef GL_EXT_vertex_array
+
+static GLboolean _glewInit_GL_EXT_vertex_array (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glArrayElementEXT = (PFNGLARRAYELEMENTEXTPROC)glewGetProcAddress((const GLubyte*)"glArrayElementEXT")) == NULL) || r;
+ r = ((glColorPointerEXT = (PFNGLCOLORPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glColorPointerEXT")) == NULL) || r;
+ r = ((glDrawArraysEXT = (PFNGLDRAWARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysEXT")) == NULL) || r;
+ r = ((glEdgeFlagPointerEXT = (PFNGLEDGEFLAGPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagPointerEXT")) == NULL) || r;
+ r = ((glGetPointervEXT = (PFNGLGETPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPointervEXT")) == NULL) || r;
+ r = ((glIndexPointerEXT = (PFNGLINDEXPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glIndexPointerEXT")) == NULL) || r;
+ r = ((glNormalPointerEXT = (PFNGLNORMALPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glNormalPointerEXT")) == NULL) || r;
+ r = ((glTexCoordPointerEXT = (PFNGLTEXCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointerEXT")) == NULL) || r;
+ r = ((glVertexPointerEXT = (PFNGLVERTEXPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexPointerEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_vertex_array */
+
+#ifdef GL_EXT_vertex_array_bgra
+
+#endif /* GL_EXT_vertex_array_bgra */
+
+#ifdef GL_EXT_vertex_shader
+
+static GLboolean _glewInit_GL_EXT_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginVertexShaderEXT = (PFNGLBEGINVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glBeginVertexShaderEXT")) == NULL) || r;
+ r = ((glBindLightParameterEXT = (PFNGLBINDLIGHTPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindLightParameterEXT")) == NULL) || r;
+ r = ((glBindMaterialParameterEXT = (PFNGLBINDMATERIALPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindMaterialParameterEXT")) == NULL) || r;
+ r = ((glBindParameterEXT = (PFNGLBINDPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindParameterEXT")) == NULL) || r;
+ r = ((glBindTexGenParameterEXT = (PFNGLBINDTEXGENPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindTexGenParameterEXT")) == NULL) || r;
+ r = ((glBindTextureUnitParameterEXT = (PFNGLBINDTEXTUREUNITPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindTextureUnitParameterEXT")) == NULL) || r;
+ r = ((glBindVertexShaderEXT = (PFNGLBINDVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindVertexShaderEXT")) == NULL) || r;
+ r = ((glDeleteVertexShaderEXT = (PFNGLDELETEVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexShaderEXT")) == NULL) || r;
+ r = ((glDisableVariantClientStateEXT = (PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableVariantClientStateEXT")) == NULL) || r;
+ r = ((glEnableVariantClientStateEXT = (PFNGLENABLEVARIANTCLIENTSTATEEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableVariantClientStateEXT")) == NULL) || r;
+ r = ((glEndVertexShaderEXT = (PFNGLENDVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glEndVertexShaderEXT")) == NULL) || r;
+ r = ((glExtractComponentEXT = (PFNGLEXTRACTCOMPONENTEXTPROC)glewGetProcAddress((const GLubyte*)"glExtractComponentEXT")) == NULL) || r;
+ r = ((glGenSymbolsEXT = (PFNGLGENSYMBOLSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenSymbolsEXT")) == NULL) || r;
+ r = ((glGenVertexShadersEXT = (PFNGLGENVERTEXSHADERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenVertexShadersEXT")) == NULL) || r;
+ r = ((glGetInvariantBooleanvEXT = (PFNGLGETINVARIANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantBooleanvEXT")) == NULL) || r;
+ r = ((glGetInvariantFloatvEXT = (PFNGLGETINVARIANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantFloatvEXT")) == NULL) || r;
+ r = ((glGetInvariantIntegervEXT = (PFNGLGETINVARIANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantIntegervEXT")) == NULL) || r;
+ r = ((glGetLocalConstantBooleanvEXT = (PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantBooleanvEXT")) == NULL) || r;
+ r = ((glGetLocalConstantFloatvEXT = (PFNGLGETLOCALCONSTANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantFloatvEXT")) == NULL) || r;
+ r = ((glGetLocalConstantIntegervEXT = (PFNGLGETLOCALCONSTANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantIntegervEXT")) == NULL) || r;
+ r = ((glGetVariantBooleanvEXT = (PFNGLGETVARIANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantBooleanvEXT")) == NULL) || r;
+ r = ((glGetVariantFloatvEXT = (PFNGLGETVARIANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantFloatvEXT")) == NULL) || r;
+ r = ((glGetVariantIntegervEXT = (PFNGLGETVARIANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantIntegervEXT")) == NULL) || r;
+ r = ((glGetVariantPointervEXT = (PFNGLGETVARIANTPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantPointervEXT")) == NULL) || r;
+ r = ((glInsertComponentEXT = (PFNGLINSERTCOMPONENTEXTPROC)glewGetProcAddress((const GLubyte*)"glInsertComponentEXT")) == NULL) || r;
+ r = ((glIsVariantEnabledEXT = (PFNGLISVARIANTENABLEDEXTPROC)glewGetProcAddress((const GLubyte*)"glIsVariantEnabledEXT")) == NULL) || r;
+ r = ((glSetInvariantEXT = (PFNGLSETINVARIANTEXTPROC)glewGetProcAddress((const GLubyte*)"glSetInvariantEXT")) == NULL) || r;
+ r = ((glSetLocalConstantEXT = (PFNGLSETLOCALCONSTANTEXTPROC)glewGetProcAddress((const GLubyte*)"glSetLocalConstantEXT")) == NULL) || r;
+ r = ((glShaderOp1EXT = (PFNGLSHADEROP1EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp1EXT")) == NULL) || r;
+ r = ((glShaderOp2EXT = (PFNGLSHADEROP2EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp2EXT")) == NULL) || r;
+ r = ((glShaderOp3EXT = (PFNGLSHADEROP3EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp3EXT")) == NULL) || r;
+ r = ((glSwizzleEXT = (PFNGLSWIZZLEEXTPROC)glewGetProcAddress((const GLubyte*)"glSwizzleEXT")) == NULL) || r;
+ r = ((glVariantPointerEXT = (PFNGLVARIANTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVariantPointerEXT")) == NULL) || r;
+ r = ((glVariantbvEXT = (PFNGLVARIANTBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantbvEXT")) == NULL) || r;
+ r = ((glVariantdvEXT = (PFNGLVARIANTDVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantdvEXT")) == NULL) || r;
+ r = ((glVariantfvEXT = (PFNGLVARIANTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantfvEXT")) == NULL) || r;
+ r = ((glVariantivEXT = (PFNGLVARIANTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantivEXT")) == NULL) || r;
+ r = ((glVariantsvEXT = (PFNGLVARIANTSVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantsvEXT")) == NULL) || r;
+ r = ((glVariantubvEXT = (PFNGLVARIANTUBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantubvEXT")) == NULL) || r;
+ r = ((glVariantuivEXT = (PFNGLVARIANTUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantuivEXT")) == NULL) || r;
+ r = ((glVariantusvEXT = (PFNGLVARIANTUSVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantusvEXT")) == NULL) || r;
+ r = ((glWriteMaskEXT = (PFNGLWRITEMASKEXTPROC)glewGetProcAddress((const GLubyte*)"glWriteMaskEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_vertex_shader */
+
+#ifdef GL_EXT_vertex_weighting
+
+static GLboolean _glewInit_GL_EXT_vertex_weighting (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glVertexWeightPointerEXT = (PFNGLVERTEXWEIGHTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightPointerEXT")) == NULL) || r;
+ r = ((glVertexWeightfEXT = (PFNGLVERTEXWEIGHTFEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightfEXT")) == NULL) || r;
+ r = ((glVertexWeightfvEXT = (PFNGLVERTEXWEIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightfvEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_EXT_vertex_weighting */
+
+#ifdef GL_GREMEDY_frame_terminator
+
+static GLboolean _glewInit_GL_GREMEDY_frame_terminator (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFrameTerminatorGREMEDY = (PFNGLFRAMETERMINATORGREMEDYPROC)glewGetProcAddress((const GLubyte*)"glFrameTerminatorGREMEDY")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_GREMEDY_frame_terminator */
+
+#ifdef GL_GREMEDY_string_marker
+
+static GLboolean _glewInit_GL_GREMEDY_string_marker (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glStringMarkerGREMEDY = (PFNGLSTRINGMARKERGREMEDYPROC)glewGetProcAddress((const GLubyte*)"glStringMarkerGREMEDY")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_GREMEDY_string_marker */
+
+#ifdef GL_HP_convolution_border_modes
+
+#endif /* GL_HP_convolution_border_modes */
+
+#ifdef GL_HP_image_transform
+
+static GLboolean _glewInit_GL_HP_image_transform (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetImageTransformParameterfvHP = (PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC)glewGetProcAddress((const GLubyte*)"glGetImageTransformParameterfvHP")) == NULL) || r;
+ r = ((glGetImageTransformParameterivHP = (PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC)glewGetProcAddress((const GLubyte*)"glGetImageTransformParameterivHP")) == NULL) || r;
+ r = ((glImageTransformParameterfHP = (PFNGLIMAGETRANSFORMPARAMETERFHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterfHP")) == NULL) || r;
+ r = ((glImageTransformParameterfvHP = (PFNGLIMAGETRANSFORMPARAMETERFVHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterfvHP")) == NULL) || r;
+ r = ((glImageTransformParameteriHP = (PFNGLIMAGETRANSFORMPARAMETERIHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameteriHP")) == NULL) || r;
+ r = ((glImageTransformParameterivHP = (PFNGLIMAGETRANSFORMPARAMETERIVHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterivHP")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_HP_image_transform */
+
+#ifdef GL_HP_occlusion_test
+
+#endif /* GL_HP_occlusion_test */
+
+#ifdef GL_HP_texture_lighting
+
+#endif /* GL_HP_texture_lighting */
+
+#ifdef GL_IBM_cull_vertex
+
+#endif /* GL_IBM_cull_vertex */
+
+#ifdef GL_IBM_multimode_draw_arrays
+
+static GLboolean _glewInit_GL_IBM_multimode_draw_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glMultiModeDrawArraysIBM = (PFNGLMULTIMODEDRAWARRAYSIBMPROC)glewGetProcAddress((const GLubyte*)"glMultiModeDrawArraysIBM")) == NULL) || r;
+ r = ((glMultiModeDrawElementsIBM = (PFNGLMULTIMODEDRAWELEMENTSIBMPROC)glewGetProcAddress((const GLubyte*)"glMultiModeDrawElementsIBM")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_IBM_multimode_draw_arrays */
+
+#ifdef GL_IBM_rasterpos_clip
+
+#endif /* GL_IBM_rasterpos_clip */
+
+#ifdef GL_IBM_static_data
+
+#endif /* GL_IBM_static_data */
+
+#ifdef GL_IBM_texture_mirrored_repeat
+
+#endif /* GL_IBM_texture_mirrored_repeat */
+
+#ifdef GL_IBM_vertex_array_lists
+
+static GLboolean _glewInit_GL_IBM_vertex_array_lists (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorPointerListIBM = (PFNGLCOLORPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glColorPointerListIBM")) == NULL) || r;
+ r = ((glEdgeFlagPointerListIBM = (PFNGLEDGEFLAGPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagPointerListIBM")) == NULL) || r;
+ r = ((glFogCoordPointerListIBM = (PFNGLFOGCOORDPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointerListIBM")) == NULL) || r;
+ r = ((glIndexPointerListIBM = (PFNGLINDEXPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glIndexPointerListIBM")) == NULL) || r;
+ r = ((glNormalPointerListIBM = (PFNGLNORMALPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glNormalPointerListIBM")) == NULL) || r;
+ r = ((glSecondaryColorPointerListIBM = (PFNGLSECONDARYCOLORPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointerListIBM")) == NULL) || r;
+ r = ((glTexCoordPointerListIBM = (PFNGLTEXCOORDPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointerListIBM")) == NULL) || r;
+ r = ((glVertexPointerListIBM = (PFNGLVERTEXPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glVertexPointerListIBM")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_IBM_vertex_array_lists */
+
+#ifdef GL_INGR_color_clamp
+
+#endif /* GL_INGR_color_clamp */
+
+#ifdef GL_INGR_interlace_read
+
+#endif /* GL_INGR_interlace_read */
+
+#ifdef GL_INTEL_parallel_arrays
+
+static GLboolean _glewInit_GL_INTEL_parallel_arrays (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorPointervINTEL = (PFNGLCOLORPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glColorPointervINTEL")) == NULL) || r;
+ r = ((glNormalPointervINTEL = (PFNGLNORMALPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glNormalPointervINTEL")) == NULL) || r;
+ r = ((glTexCoordPointervINTEL = (PFNGLTEXCOORDPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointervINTEL")) == NULL) || r;
+ r = ((glVertexPointervINTEL = (PFNGLVERTEXPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glVertexPointervINTEL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_INTEL_parallel_arrays */
+
+#ifdef GL_INTEL_texture_scissor
+
+static GLboolean _glewInit_GL_INTEL_texture_scissor (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexScissorFuncINTEL = (PFNGLTEXSCISSORFUNCINTELPROC)glewGetProcAddress((const GLubyte*)"glTexScissorFuncINTEL")) == NULL) || r;
+ r = ((glTexScissorINTEL = (PFNGLTEXSCISSORINTELPROC)glewGetProcAddress((const GLubyte*)"glTexScissorINTEL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_INTEL_texture_scissor */
+
+#ifdef GL_KTX_buffer_region
+
+static GLboolean _glewInit_GL_KTX_buffer_region (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBufferRegionEnabledEXT = (PFNGLBUFFERREGIONENABLEDEXTPROC)glewGetProcAddress((const GLubyte*)"glBufferRegionEnabledEXT")) == NULL) || r;
+ r = ((glDeleteBufferRegionEXT = (PFNGLDELETEBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteBufferRegionEXT")) == NULL) || r;
+ r = ((glDrawBufferRegionEXT = (PFNGLDRAWBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawBufferRegionEXT")) == NULL) || r;
+ r = ((glNewBufferRegionEXT = (PFNGLNEWBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glNewBufferRegionEXT")) == NULL) || r;
+ r = ((glReadBufferRegionEXT = (PFNGLREADBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glReadBufferRegionEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_KTX_buffer_region */
+
+#ifdef GL_MESAX_texture_stack
+
+#endif /* GL_MESAX_texture_stack */
+
+#ifdef GL_MESA_pack_invert
+
+#endif /* GL_MESA_pack_invert */
+
+#ifdef GL_MESA_resize_buffers
+
+static GLboolean _glewInit_GL_MESA_resize_buffers (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glResizeBuffersMESA = (PFNGLRESIZEBUFFERSMESAPROC)glewGetProcAddress((const GLubyte*)"glResizeBuffersMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_MESA_resize_buffers */
+
+#ifdef GL_MESA_window_pos
+
+static GLboolean _glewInit_GL_MESA_window_pos (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glWindowPos2dMESA = (PFNGLWINDOWPOS2DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dMESA")) == NULL) || r;
+ r = ((glWindowPos2dvMESA = (PFNGLWINDOWPOS2DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dvMESA")) == NULL) || r;
+ r = ((glWindowPos2fMESA = (PFNGLWINDOWPOS2FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fMESA")) == NULL) || r;
+ r = ((glWindowPos2fvMESA = (PFNGLWINDOWPOS2FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fvMESA")) == NULL) || r;
+ r = ((glWindowPos2iMESA = (PFNGLWINDOWPOS2IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iMESA")) == NULL) || r;
+ r = ((glWindowPos2ivMESA = (PFNGLWINDOWPOS2IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2ivMESA")) == NULL) || r;
+ r = ((glWindowPos2sMESA = (PFNGLWINDOWPOS2SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sMESA")) == NULL) || r;
+ r = ((glWindowPos2svMESA = (PFNGLWINDOWPOS2SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2svMESA")) == NULL) || r;
+ r = ((glWindowPos3dMESA = (PFNGLWINDOWPOS3DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dMESA")) == NULL) || r;
+ r = ((glWindowPos3dvMESA = (PFNGLWINDOWPOS3DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dvMESA")) == NULL) || r;
+ r = ((glWindowPos3fMESA = (PFNGLWINDOWPOS3FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fMESA")) == NULL) || r;
+ r = ((glWindowPos3fvMESA = (PFNGLWINDOWPOS3FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fvMESA")) == NULL) || r;
+ r = ((glWindowPos3iMESA = (PFNGLWINDOWPOS3IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iMESA")) == NULL) || r;
+ r = ((glWindowPos3ivMESA = (PFNGLWINDOWPOS3IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3ivMESA")) == NULL) || r;
+ r = ((glWindowPos3sMESA = (PFNGLWINDOWPOS3SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sMESA")) == NULL) || r;
+ r = ((glWindowPos3svMESA = (PFNGLWINDOWPOS3SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3svMESA")) == NULL) || r;
+ r = ((glWindowPos4dMESA = (PFNGLWINDOWPOS4DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4dMESA")) == NULL) || r;
+ r = ((glWindowPos4dvMESA = (PFNGLWINDOWPOS4DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4dvMESA")) == NULL) || r;
+ r = ((glWindowPos4fMESA = (PFNGLWINDOWPOS4FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4fMESA")) == NULL) || r;
+ r = ((glWindowPos4fvMESA = (PFNGLWINDOWPOS4FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4fvMESA")) == NULL) || r;
+ r = ((glWindowPos4iMESA = (PFNGLWINDOWPOS4IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4iMESA")) == NULL) || r;
+ r = ((glWindowPos4ivMESA = (PFNGLWINDOWPOS4IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4ivMESA")) == NULL) || r;
+ r = ((glWindowPos4sMESA = (PFNGLWINDOWPOS4SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4sMESA")) == NULL) || r;
+ r = ((glWindowPos4svMESA = (PFNGLWINDOWPOS4SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4svMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_MESA_window_pos */
+
+#ifdef GL_MESA_ycbcr_texture
+
+#endif /* GL_MESA_ycbcr_texture */
+
+#ifdef GL_NV_blend_square
+
+#endif /* GL_NV_blend_square */
+
+#ifdef GL_NV_conditional_render
+
+static GLboolean _glewInit_GL_NV_conditional_render (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginConditionalRenderNV = (PFNGLBEGINCONDITIONALRENDERNVPROC)glewGetProcAddress((const GLubyte*)"glBeginConditionalRenderNV")) == NULL) || r;
+ r = ((glEndConditionalRenderNV = (PFNGLENDCONDITIONALRENDERNVPROC)glewGetProcAddress((const GLubyte*)"glEndConditionalRenderNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_conditional_render */
+
+#ifdef GL_NV_copy_depth_to_color
+
+#endif /* GL_NV_copy_depth_to_color */
+
+#ifdef GL_NV_depth_buffer_float
+
+static GLboolean _glewInit_GL_NV_depth_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearDepthdNV = (PFNGLCLEARDEPTHDNVPROC)glewGetProcAddress((const GLubyte*)"glClearDepthdNV")) == NULL) || r;
+ r = ((glDepthBoundsdNV = (PFNGLDEPTHBOUNDSDNVPROC)glewGetProcAddress((const GLubyte*)"glDepthBoundsdNV")) == NULL) || r;
+ r = ((glDepthRangedNV = (PFNGLDEPTHRANGEDNVPROC)glewGetProcAddress((const GLubyte*)"glDepthRangedNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_depth_buffer_float */
+
+#ifdef GL_NV_depth_clamp
+
+#endif /* GL_NV_depth_clamp */
+
+#ifdef GL_NV_depth_range_unclamped
+
+#endif /* GL_NV_depth_range_unclamped */
+
+#ifdef GL_NV_evaluators
+
+static GLboolean _glewInit_GL_NV_evaluators (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glEvalMapsNV = (PFNGLEVALMAPSNVPROC)glewGetProcAddress((const GLubyte*)"glEvalMapsNV")) == NULL) || r;
+ r = ((glGetMapAttribParameterfvNV = (PFNGLGETMAPATTRIBPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapAttribParameterfvNV")) == NULL) || r;
+ r = ((glGetMapAttribParameterivNV = (PFNGLGETMAPATTRIBPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapAttribParameterivNV")) == NULL) || r;
+ r = ((glGetMapControlPointsNV = (PFNGLGETMAPCONTROLPOINTSNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapControlPointsNV")) == NULL) || r;
+ r = ((glGetMapParameterfvNV = (PFNGLGETMAPPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapParameterfvNV")) == NULL) || r;
+ r = ((glGetMapParameterivNV = (PFNGLGETMAPPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapParameterivNV")) == NULL) || r;
+ r = ((glMapControlPointsNV = (PFNGLMAPCONTROLPOINTSNVPROC)glewGetProcAddress((const GLubyte*)"glMapControlPointsNV")) == NULL) || r;
+ r = ((glMapParameterfvNV = (PFNGLMAPPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glMapParameterfvNV")) == NULL) || r;
+ r = ((glMapParameterivNV = (PFNGLMAPPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glMapParameterivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_evaluators */
+
+#ifdef GL_NV_explicit_multisample
+
+static GLboolean _glewInit_GL_NV_explicit_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetMultisamplefvNV = (PFNGLGETMULTISAMPLEFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMultisamplefvNV")) == NULL) || r;
+ r = ((glSampleMaskIndexedNV = (PFNGLSAMPLEMASKINDEXEDNVPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskIndexedNV")) == NULL) || r;
+ r = ((glTexRenderbufferNV = (PFNGLTEXRENDERBUFFERNVPROC)glewGetProcAddress((const GLubyte*)"glTexRenderbufferNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_explicit_multisample */
+
+#ifdef GL_NV_fence
+
+static GLboolean _glewInit_GL_NV_fence (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDeleteFencesNV = (PFNGLDELETEFENCESNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteFencesNV")) == NULL) || r;
+ r = ((glFinishFenceNV = (PFNGLFINISHFENCENVPROC)glewGetProcAddress((const GLubyte*)"glFinishFenceNV")) == NULL) || r;
+ r = ((glGenFencesNV = (PFNGLGENFENCESNVPROC)glewGetProcAddress((const GLubyte*)"glGenFencesNV")) == NULL) || r;
+ r = ((glGetFenceivNV = (PFNGLGETFENCEIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFenceivNV")) == NULL) || r;
+ r = ((glIsFenceNV = (PFNGLISFENCENVPROC)glewGetProcAddress((const GLubyte*)"glIsFenceNV")) == NULL) || r;
+ r = ((glSetFenceNV = (PFNGLSETFENCENVPROC)glewGetProcAddress((const GLubyte*)"glSetFenceNV")) == NULL) || r;
+ r = ((glTestFenceNV = (PFNGLTESTFENCENVPROC)glewGetProcAddress((const GLubyte*)"glTestFenceNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_fence */
+
+#ifdef GL_NV_float_buffer
+
+#endif /* GL_NV_float_buffer */
+
+#ifdef GL_NV_fog_distance
+
+#endif /* GL_NV_fog_distance */
+
+#ifdef GL_NV_fragment_program
+
+static GLboolean _glewInit_GL_NV_fragment_program (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetProgramNamedParameterdvNV = (PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramNamedParameterdvNV")) == NULL) || r;
+ r = ((glGetProgramNamedParameterfvNV = (PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramNamedParameterfvNV")) == NULL) || r;
+ r = ((glProgramNamedParameter4dNV = (PFNGLPROGRAMNAMEDPARAMETER4DNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4dNV")) == NULL) || r;
+ r = ((glProgramNamedParameter4dvNV = (PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4dvNV")) == NULL) || r;
+ r = ((glProgramNamedParameter4fNV = (PFNGLPROGRAMNAMEDPARAMETER4FNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4fNV")) == NULL) || r;
+ r = ((glProgramNamedParameter4fvNV = (PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4fvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_fragment_program */
+
+#ifdef GL_NV_fragment_program2
+
+#endif /* GL_NV_fragment_program2 */
+
+#ifdef GL_NV_fragment_program4
+
+#endif /* GL_NV_fragment_program4 */
+
+#ifdef GL_NV_fragment_program_option
+
+#endif /* GL_NV_fragment_program_option */
+
+#ifdef GL_NV_framebuffer_multisample_coverage
+
+static GLboolean _glewInit_GL_NV_framebuffer_multisample_coverage (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glRenderbufferStorageMultisampleCoverageNV = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleCoverageNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_framebuffer_multisample_coverage */
+
+#ifdef GL_NV_geometry_program4
+
+static GLboolean _glewInit_GL_NV_geometry_program4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProgramVertexLimitNV = (PFNGLPROGRAMVERTEXLIMITNVPROC)glewGetProcAddress((const GLubyte*)"glProgramVertexLimitNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_geometry_program4 */
+
+#ifdef GL_NV_geometry_shader4
+
+#endif /* GL_NV_geometry_shader4 */
+
+#ifdef GL_NV_gpu_program4
+
+static GLboolean _glewInit_GL_NV_gpu_program4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProgramEnvParameterI4iNV = (PFNGLPROGRAMENVPARAMETERI4INVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4iNV")) == NULL) || r;
+ r = ((glProgramEnvParameterI4ivNV = (PFNGLPROGRAMENVPARAMETERI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4ivNV")) == NULL) || r;
+ r = ((glProgramEnvParameterI4uiNV = (PFNGLPROGRAMENVPARAMETERI4UINVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4uiNV")) == NULL) || r;
+ r = ((glProgramEnvParameterI4uivNV = (PFNGLPROGRAMENVPARAMETERI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4uivNV")) == NULL) || r;
+ r = ((glProgramEnvParametersI4ivNV = (PFNGLPROGRAMENVPARAMETERSI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParametersI4ivNV")) == NULL) || r;
+ r = ((glProgramEnvParametersI4uivNV = (PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParametersI4uivNV")) == NULL) || r;
+ r = ((glProgramLocalParameterI4iNV = (PFNGLPROGRAMLOCALPARAMETERI4INVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4iNV")) == NULL) || r;
+ r = ((glProgramLocalParameterI4ivNV = (PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4ivNV")) == NULL) || r;
+ r = ((glProgramLocalParameterI4uiNV = (PFNGLPROGRAMLOCALPARAMETERI4UINVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4uiNV")) == NULL) || r;
+ r = ((glProgramLocalParameterI4uivNV = (PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4uivNV")) == NULL) || r;
+ r = ((glProgramLocalParametersI4ivNV = (PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParametersI4ivNV")) == NULL) || r;
+ r = ((glProgramLocalParametersI4uivNV = (PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParametersI4uivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_gpu_program4 */
+
+#ifdef GL_NV_half_float
+
+static GLboolean _glewInit_GL_NV_half_float (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColor3hNV = (PFNGLCOLOR3HNVPROC)glewGetProcAddress((const GLubyte*)"glColor3hNV")) == NULL) || r;
+ r = ((glColor3hvNV = (PFNGLCOLOR3HVNVPROC)glewGetProcAddress((const GLubyte*)"glColor3hvNV")) == NULL) || r;
+ r = ((glColor4hNV = (PFNGLCOLOR4HNVPROC)glewGetProcAddress((const GLubyte*)"glColor4hNV")) == NULL) || r;
+ r = ((glColor4hvNV = (PFNGLCOLOR4HVNVPROC)glewGetProcAddress((const GLubyte*)"glColor4hvNV")) == NULL) || r;
+ r = ((glFogCoordhNV = (PFNGLFOGCOORDHNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordhNV")) == NULL) || r;
+ r = ((glFogCoordhvNV = (PFNGLFOGCOORDHVNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordhvNV")) == NULL) || r;
+ r = ((glMultiTexCoord1hNV = (PFNGLMULTITEXCOORD1HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1hNV")) == NULL) || r;
+ r = ((glMultiTexCoord1hvNV = (PFNGLMULTITEXCOORD1HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1hvNV")) == NULL) || r;
+ r = ((glMultiTexCoord2hNV = (PFNGLMULTITEXCOORD2HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2hNV")) == NULL) || r;
+ r = ((glMultiTexCoord2hvNV = (PFNGLMULTITEXCOORD2HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2hvNV")) == NULL) || r;
+ r = ((glMultiTexCoord3hNV = (PFNGLMULTITEXCOORD3HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3hNV")) == NULL) || r;
+ r = ((glMultiTexCoord3hvNV = (PFNGLMULTITEXCOORD3HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3hvNV")) == NULL) || r;
+ r = ((glMultiTexCoord4hNV = (PFNGLMULTITEXCOORD4HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4hNV")) == NULL) || r;
+ r = ((glMultiTexCoord4hvNV = (PFNGLMULTITEXCOORD4HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4hvNV")) == NULL) || r;
+ r = ((glNormal3hNV = (PFNGLNORMAL3HNVPROC)glewGetProcAddress((const GLubyte*)"glNormal3hNV")) == NULL) || r;
+ r = ((glNormal3hvNV = (PFNGLNORMAL3HVNVPROC)glewGetProcAddress((const GLubyte*)"glNormal3hvNV")) == NULL) || r;
+ r = ((glSecondaryColor3hNV = (PFNGLSECONDARYCOLOR3HNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3hNV")) == NULL) || r;
+ r = ((glSecondaryColor3hvNV = (PFNGLSECONDARYCOLOR3HVNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3hvNV")) == NULL) || r;
+ r = ((glTexCoord1hNV = (PFNGLTEXCOORD1HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1hNV")) == NULL) || r;
+ r = ((glTexCoord1hvNV = (PFNGLTEXCOORD1HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1hvNV")) == NULL) || r;
+ r = ((glTexCoord2hNV = (PFNGLTEXCOORD2HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2hNV")) == NULL) || r;
+ r = ((glTexCoord2hvNV = (PFNGLTEXCOORD2HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2hvNV")) == NULL) || r;
+ r = ((glTexCoord3hNV = (PFNGLTEXCOORD3HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3hNV")) == NULL) || r;
+ r = ((glTexCoord3hvNV = (PFNGLTEXCOORD3HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3hvNV")) == NULL) || r;
+ r = ((glTexCoord4hNV = (PFNGLTEXCOORD4HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4hNV")) == NULL) || r;
+ r = ((glTexCoord4hvNV = (PFNGLTEXCOORD4HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4hvNV")) == NULL) || r;
+ r = ((glVertex2hNV = (PFNGLVERTEX2HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex2hNV")) == NULL) || r;
+ r = ((glVertex2hvNV = (PFNGLVERTEX2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex2hvNV")) == NULL) || r;
+ r = ((glVertex3hNV = (PFNGLVERTEX3HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex3hNV")) == NULL) || r;
+ r = ((glVertex3hvNV = (PFNGLVERTEX3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex3hvNV")) == NULL) || r;
+ r = ((glVertex4hNV = (PFNGLVERTEX4HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex4hNV")) == NULL) || r;
+ r = ((glVertex4hvNV = (PFNGLVERTEX4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex4hvNV")) == NULL) || r;
+ r = ((glVertexAttrib1hNV = (PFNGLVERTEXATTRIB1HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1hNV")) == NULL) || r;
+ r = ((glVertexAttrib1hvNV = (PFNGLVERTEXATTRIB1HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1hvNV")) == NULL) || r;
+ r = ((glVertexAttrib2hNV = (PFNGLVERTEXATTRIB2HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2hNV")) == NULL) || r;
+ r = ((glVertexAttrib2hvNV = (PFNGLVERTEXATTRIB2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2hvNV")) == NULL) || r;
+ r = ((glVertexAttrib3hNV = (PFNGLVERTEXATTRIB3HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3hNV")) == NULL) || r;
+ r = ((glVertexAttrib3hvNV = (PFNGLVERTEXATTRIB3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3hvNV")) == NULL) || r;
+ r = ((glVertexAttrib4hNV = (PFNGLVERTEXATTRIB4HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4hNV")) == NULL) || r;
+ r = ((glVertexAttrib4hvNV = (PFNGLVERTEXATTRIB4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4hvNV")) == NULL) || r;
+ r = ((glVertexAttribs1hvNV = (PFNGLVERTEXATTRIBS1HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1hvNV")) == NULL) || r;
+ r = ((glVertexAttribs2hvNV = (PFNGLVERTEXATTRIBS2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2hvNV")) == NULL) || r;
+ r = ((glVertexAttribs3hvNV = (PFNGLVERTEXATTRIBS3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3hvNV")) == NULL) || r;
+ r = ((glVertexAttribs4hvNV = (PFNGLVERTEXATTRIBS4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4hvNV")) == NULL) || r;
+ r = ((glVertexWeighthNV = (PFNGLVERTEXWEIGHTHNVPROC)glewGetProcAddress((const GLubyte*)"glVertexWeighthNV")) == NULL) || r;
+ r = ((glVertexWeighthvNV = (PFNGLVERTEXWEIGHTHVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexWeighthvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_half_float */
+
+#ifdef GL_NV_light_max_exponent
+
+#endif /* GL_NV_light_max_exponent */
+
+#ifdef GL_NV_multisample_filter_hint
+
+#endif /* GL_NV_multisample_filter_hint */
+
+#ifdef GL_NV_occlusion_query
+
+static GLboolean _glewInit_GL_NV_occlusion_query (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glBeginOcclusionQueryNV")) == NULL) || r;
+ r = ((glDeleteOcclusionQueriesNV = (PFNGLDELETEOCCLUSIONQUERIESNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteOcclusionQueriesNV")) == NULL) || r;
+ r = ((glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glEndOcclusionQueryNV")) == NULL) || r;
+ r = ((glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC)glewGetProcAddress((const GLubyte*)"glGenOcclusionQueriesNV")) == NULL) || r;
+ r = ((glGetOcclusionQueryivNV = (PFNGLGETOCCLUSIONQUERYIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetOcclusionQueryivNV")) == NULL) || r;
+ r = ((glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetOcclusionQueryuivNV")) == NULL) || r;
+ r = ((glIsOcclusionQueryNV = (PFNGLISOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glIsOcclusionQueryNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_occlusion_query */
+
+#ifdef GL_NV_packed_depth_stencil
+
+#endif /* GL_NV_packed_depth_stencil */
+
+#ifdef GL_NV_parameter_buffer_object
+
+static GLboolean _glewInit_GL_NV_parameter_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glProgramBufferParametersIivNV = (PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersIivNV")) == NULL) || r;
+ r = ((glProgramBufferParametersIuivNV = (PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersIuivNV")) == NULL) || r;
+ r = ((glProgramBufferParametersfvNV = (PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersfvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_parameter_buffer_object */
+
+#ifdef GL_NV_pixel_data_range
+
+static GLboolean _glewInit_GL_NV_pixel_data_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushPixelDataRangeNV = (PFNGLFLUSHPIXELDATARANGENVPROC)glewGetProcAddress((const GLubyte*)"glFlushPixelDataRangeNV")) == NULL) || r;
+ r = ((glPixelDataRangeNV = (PFNGLPIXELDATARANGENVPROC)glewGetProcAddress((const GLubyte*)"glPixelDataRangeNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_pixel_data_range */
+
+#ifdef GL_NV_point_sprite
+
+static GLboolean _glewInit_GL_NV_point_sprite (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPointParameteriNV = (PFNGLPOINTPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glPointParameteriNV")) == NULL) || r;
+ r = ((glPointParameterivNV = (PFNGLPOINTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_point_sprite */
+
+#ifdef GL_NV_present_video
+
+static GLboolean _glewInit_GL_NV_present_video (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetVideoi64vNV = (PFNGLGETVIDEOI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoi64vNV")) == NULL) || r;
+ r = ((glGetVideoivNV = (PFNGLGETVIDEOIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoivNV")) == NULL) || r;
+ r = ((glGetVideoui64vNV = (PFNGLGETVIDEOUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoui64vNV")) == NULL) || r;
+ r = ((glGetVideouivNV = (PFNGLGETVIDEOUIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideouivNV")) == NULL) || r;
+ r = ((glPresentFrameDualFillNV = (PFNGLPRESENTFRAMEDUALFILLNVPROC)glewGetProcAddress((const GLubyte*)"glPresentFrameDualFillNV")) == NULL) || r;
+ r = ((glPresentFrameKeyedNV = (PFNGLPRESENTFRAMEKEYEDNVPROC)glewGetProcAddress((const GLubyte*)"glPresentFrameKeyedNV")) == NULL) || r;
+ r = ((glVideoParameterivNV = (PFNGLVIDEOPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glVideoParameterivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_present_video */
+
+#ifdef GL_NV_primitive_restart
+
+static GLboolean _glewInit_GL_NV_primitive_restart (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPrimitiveRestartIndexNV = (PFNGLPRIMITIVERESTARTINDEXNVPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartIndexNV")) == NULL) || r;
+ r = ((glPrimitiveRestartNV = (PFNGLPRIMITIVERESTARTNVPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_primitive_restart */
+
+#ifdef GL_NV_register_combiners
+
+static GLboolean _glewInit_GL_NV_register_combiners (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCombinerInputNV = (PFNGLCOMBINERINPUTNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerInputNV")) == NULL) || r;
+ r = ((glCombinerOutputNV = (PFNGLCOMBINEROUTPUTNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerOutputNV")) == NULL) || r;
+ r = ((glCombinerParameterfNV = (PFNGLCOMBINERPARAMETERFNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterfNV")) == NULL) || r;
+ r = ((glCombinerParameterfvNV = (PFNGLCOMBINERPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterfvNV")) == NULL) || r;
+ r = ((glCombinerParameteriNV = (PFNGLCOMBINERPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameteriNV")) == NULL) || r;
+ r = ((glCombinerParameterivNV = (PFNGLCOMBINERPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterivNV")) == NULL) || r;
+ r = ((glFinalCombinerInputNV = (PFNGLFINALCOMBINERINPUTNVPROC)glewGetProcAddress((const GLubyte*)"glFinalCombinerInputNV")) == NULL) || r;
+ r = ((glGetCombinerInputParameterfvNV = (PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerInputParameterfvNV")) == NULL) || r;
+ r = ((glGetCombinerInputParameterivNV = (PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerInputParameterivNV")) == NULL) || r;
+ r = ((glGetCombinerOutputParameterfvNV = (PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerOutputParameterfvNV")) == NULL) || r;
+ r = ((glGetCombinerOutputParameterivNV = (PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerOutputParameterivNV")) == NULL) || r;
+ r = ((glGetFinalCombinerInputParameterfvNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFinalCombinerInputParameterfvNV")) == NULL) || r;
+ r = ((glGetFinalCombinerInputParameterivNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFinalCombinerInputParameterivNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_register_combiners */
+
+#ifdef GL_NV_register_combiners2
+
+static GLboolean _glewInit_GL_NV_register_combiners2 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glCombinerStageParameterfvNV = (PFNGLCOMBINERSTAGEPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerStageParameterfvNV")) == NULL) || r;
+ r = ((glGetCombinerStageParameterfvNV = (PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerStageParameterfvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_register_combiners2 */
+
+#ifdef GL_NV_texgen_emboss
+
+#endif /* GL_NV_texgen_emboss */
+
+#ifdef GL_NV_texgen_reflection
+
+#endif /* GL_NV_texgen_reflection */
+
+#ifdef GL_NV_texture_compression_vtc
+
+#endif /* GL_NV_texture_compression_vtc */
+
+#ifdef GL_NV_texture_env_combine4
+
+#endif /* GL_NV_texture_env_combine4 */
+
+#ifdef GL_NV_texture_expand_normal
+
+#endif /* GL_NV_texture_expand_normal */
+
+#ifdef GL_NV_texture_rectangle
+
+#endif /* GL_NV_texture_rectangle */
+
+#ifdef GL_NV_texture_shader
+
+#endif /* GL_NV_texture_shader */
+
+#ifdef GL_NV_texture_shader2
+
+#endif /* GL_NV_texture_shader2 */
+
+#ifdef GL_NV_texture_shader3
+
+#endif /* GL_NV_texture_shader3 */
+
+#ifdef GL_NV_transform_feedback
+
+static GLboolean _glewInit_GL_NV_transform_feedback (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glActiveVaryingNV = (PFNGLACTIVEVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glActiveVaryingNV")) == NULL) || r;
+ r = ((glBeginTransformFeedbackNV = (PFNGLBEGINTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedbackNV")) == NULL) || r;
+ r = ((glBindBufferBaseNV = (PFNGLBINDBUFFERBASENVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBaseNV")) == NULL) || r;
+ r = ((glBindBufferOffsetNV = (PFNGLBINDBUFFEROFFSETNVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferOffsetNV")) == NULL) || r;
+ r = ((glBindBufferRangeNV = (PFNGLBINDBUFFERRANGENVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRangeNV")) == NULL) || r;
+ r = ((glEndTransformFeedbackNV = (PFNGLENDTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedbackNV")) == NULL) || r;
+ r = ((glGetActiveVaryingNV = (PFNGLGETACTIVEVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveVaryingNV")) == NULL) || r;
+ r = ((glGetTransformFeedbackVaryingNV = (PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVaryingNV")) == NULL) || r;
+ r = ((glGetVaryingLocationNV = (PFNGLGETVARYINGLOCATIONNVPROC)glewGetProcAddress((const GLubyte*)"glGetVaryingLocationNV")) == NULL) || r;
+ r = ((glTransformFeedbackAttribsNV = (PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackAttribsNV")) == NULL) || r;
+ r = ((glTransformFeedbackVaryingsNV = (PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryingsNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_transform_feedback */
+
+#ifdef GL_NV_vertex_array_range
+
+static GLboolean _glewInit_GL_NV_vertex_array_range (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushVertexArrayRangeNV = (PFNGLFLUSHVERTEXARRAYRANGENVPROC)glewGetProcAddress((const GLubyte*)"glFlushVertexArrayRangeNV")) == NULL) || r;
+ r = ((glVertexArrayRangeNV = (PFNGLVERTEXARRAYRANGENVPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayRangeNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_vertex_array_range */
+
+#ifdef GL_NV_vertex_array_range2
+
+#endif /* GL_NV_vertex_array_range2 */
+
+#ifdef GL_NV_vertex_program
+
+static GLboolean _glewInit_GL_NV_vertex_program (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAreProgramsResidentNV = (PFNGLAREPROGRAMSRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glAreProgramsResidentNV")) == NULL) || r;
+ r = ((glBindProgramNV = (PFNGLBINDPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glBindProgramNV")) == NULL) || r;
+ r = ((glDeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramsNV")) == NULL) || r;
+ r = ((glExecuteProgramNV = (PFNGLEXECUTEPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glExecuteProgramNV")) == NULL) || r;
+ r = ((glGenProgramsNV = (PFNGLGENPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glGenProgramsNV")) == NULL) || r;
+ r = ((glGetProgramParameterdvNV = (PFNGLGETPROGRAMPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramParameterdvNV")) == NULL) || r;
+ r = ((glGetProgramParameterfvNV = (PFNGLGETPROGRAMPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramParameterfvNV")) == NULL) || r;
+ r = ((glGetProgramStringNV = (PFNGLGETPROGRAMSTRINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStringNV")) == NULL) || r;
+ r = ((glGetProgramivNV = (PFNGLGETPROGRAMIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramivNV")) == NULL) || r;
+ r = ((glGetTrackMatrixivNV = (PFNGLGETTRACKMATRIXIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetTrackMatrixivNV")) == NULL) || r;
+ r = ((glGetVertexAttribPointervNV = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointervNV")) == NULL) || r;
+ r = ((glGetVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdvNV")) == NULL) || r;
+ r = ((glGetVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfvNV")) == NULL) || r;
+ r = ((glGetVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribivNV")) == NULL) || r;
+ r = ((glIsProgramNV = (PFNGLISPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glIsProgramNV")) == NULL) || r;
+ r = ((glLoadProgramNV = (PFNGLLOADPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glLoadProgramNV")) == NULL) || r;
+ r = ((glProgramParameter4dNV = (PFNGLPROGRAMPARAMETER4DNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4dNV")) == NULL) || r;
+ r = ((glProgramParameter4dvNV = (PFNGLPROGRAMPARAMETER4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4dvNV")) == NULL) || r;
+ r = ((glProgramParameter4fNV = (PFNGLPROGRAMPARAMETER4FNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4fNV")) == NULL) || r;
+ r = ((glProgramParameter4fvNV = (PFNGLPROGRAMPARAMETER4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4fvNV")) == NULL) || r;
+ r = ((glProgramParameters4dvNV = (PFNGLPROGRAMPARAMETERS4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameters4dvNV")) == NULL) || r;
+ r = ((glProgramParameters4fvNV = (PFNGLPROGRAMPARAMETERS4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameters4fvNV")) == NULL) || r;
+ r = ((glRequestResidentProgramsNV = (PFNGLREQUESTRESIDENTPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glRequestResidentProgramsNV")) == NULL) || r;
+ r = ((glTrackMatrixNV = (PFNGLTRACKMATRIXNVPROC)glewGetProcAddress((const GLubyte*)"glTrackMatrixNV")) == NULL) || r;
+ r = ((glVertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dNV")) == NULL) || r;
+ r = ((glVertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dvNV")) == NULL) || r;
+ r = ((glVertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fNV")) == NULL) || r;
+ r = ((glVertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fvNV")) == NULL) || r;
+ r = ((glVertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sNV")) == NULL) || r;
+ r = ((glVertexAttrib1svNV = (PFNGLVERTEXATTRIB1SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1svNV")) == NULL) || r;
+ r = ((glVertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dNV")) == NULL) || r;
+ r = ((glVertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dvNV")) == NULL) || r;
+ r = ((glVertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fNV")) == NULL) || r;
+ r = ((glVertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fvNV")) == NULL) || r;
+ r = ((glVertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sNV")) == NULL) || r;
+ r = ((glVertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2svNV")) == NULL) || r;
+ r = ((glVertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dNV")) == NULL) || r;
+ r = ((glVertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dvNV")) == NULL) || r;
+ r = ((glVertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fNV")) == NULL) || r;
+ r = ((glVertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fvNV")) == NULL) || r;
+ r = ((glVertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sNV")) == NULL) || r;
+ r = ((glVertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3svNV")) == NULL) || r;
+ r = ((glVertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dNV")) == NULL) || r;
+ r = ((glVertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dvNV")) == NULL) || r;
+ r = ((glVertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fNV")) == NULL) || r;
+ r = ((glVertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fvNV")) == NULL) || r;
+ r = ((glVertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sNV")) == NULL) || r;
+ r = ((glVertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4svNV")) == NULL) || r;
+ r = ((glVertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubNV")) == NULL) || r;
+ r = ((glVertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubvNV")) == NULL) || r;
+ r = ((glVertexAttribPointerNV = (PFNGLVERTEXATTRIBPOINTERNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointerNV")) == NULL) || r;
+ r = ((glVertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1dvNV")) == NULL) || r;
+ r = ((glVertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1fvNV")) == NULL) || r;
+ r = ((glVertexAttribs1svNV = (PFNGLVERTEXATTRIBS1SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1svNV")) == NULL) || r;
+ r = ((glVertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2dvNV")) == NULL) || r;
+ r = ((glVertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2fvNV")) == NULL) || r;
+ r = ((glVertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2svNV")) == NULL) || r;
+ r = ((glVertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3dvNV")) == NULL) || r;
+ r = ((glVertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3fvNV")) == NULL) || r;
+ r = ((glVertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3svNV")) == NULL) || r;
+ r = ((glVertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4dvNV")) == NULL) || r;
+ r = ((glVertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4fvNV")) == NULL) || r;
+ r = ((glVertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4svNV")) == NULL) || r;
+ r = ((glVertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4ubvNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_NV_vertex_program */
+
+#ifdef GL_NV_vertex_program1_1
+
+#endif /* GL_NV_vertex_program1_1 */
+
+#ifdef GL_NV_vertex_program2
+
+#endif /* GL_NV_vertex_program2 */
+
+#ifdef GL_NV_vertex_program2_option
+
+#endif /* GL_NV_vertex_program2_option */
+
+#ifdef GL_NV_vertex_program3
+
+#endif /* GL_NV_vertex_program3 */
+
+#ifdef GL_NV_vertex_program4
+
+#endif /* GL_NV_vertex_program4 */
+
+#ifdef GL_OES_byte_coordinates
+
+#endif /* GL_OES_byte_coordinates */
+
+#ifdef GL_OES_compressed_paletted_texture
+
+#endif /* GL_OES_compressed_paletted_texture */
+
+#ifdef GL_OES_read_format
+
+#endif /* GL_OES_read_format */
+
+#ifdef GL_OES_single_precision
+
+static GLboolean _glewInit_GL_OES_single_precision (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glClearDepthfOES = (PFNGLCLEARDEPTHFOESPROC)glewGetProcAddress((const GLubyte*)"glClearDepthfOES")) == NULL) || r;
+ r = ((glClipPlanefOES = (PFNGLCLIPPLANEFOESPROC)glewGetProcAddress((const GLubyte*)"glClipPlanefOES")) == NULL) || r;
+ r = ((glDepthRangefOES = (PFNGLDEPTHRANGEFOESPROC)glewGetProcAddress((const GLubyte*)"glDepthRangefOES")) == NULL) || r;
+ r = ((glFrustumfOES = (PFNGLFRUSTUMFOESPROC)glewGetProcAddress((const GLubyte*)"glFrustumfOES")) == NULL) || r;
+ r = ((glGetClipPlanefOES = (PFNGLGETCLIPPLANEFOESPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanefOES")) == NULL) || r;
+ r = ((glOrthofOES = (PFNGLORTHOFOESPROC)glewGetProcAddress((const GLubyte*)"glOrthofOES")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_OES_single_precision */
+
+#ifdef GL_OML_interlace
+
+#endif /* GL_OML_interlace */
+
+#ifdef GL_OML_resample
+
+#endif /* GL_OML_resample */
+
+#ifdef GL_OML_subsample
+
+#endif /* GL_OML_subsample */
+
+#ifdef GL_PGI_misc_hints
+
+#endif /* GL_PGI_misc_hints */
+
+#ifdef GL_PGI_vertex_hints
+
+#endif /* GL_PGI_vertex_hints */
+
+#ifdef GL_REND_screen_coordinates
+
+#endif /* GL_REND_screen_coordinates */
+
+#ifdef GL_S3_s3tc
+
+#endif /* GL_S3_s3tc */
+
+#ifdef GL_SGIS_color_range
+
+#endif /* GL_SGIS_color_range */
+
+#ifdef GL_SGIS_detail_texture
+
+static GLboolean _glewInit_GL_SGIS_detail_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glDetailTexFuncSGIS = (PFNGLDETAILTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glDetailTexFuncSGIS")) == NULL) || r;
+ r = ((glGetDetailTexFuncSGIS = (PFNGLGETDETAILTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetDetailTexFuncSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_detail_texture */
+
+#ifdef GL_SGIS_fog_function
+
+static GLboolean _glewInit_GL_SGIS_fog_function (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFogFuncSGIS = (PFNGLFOGFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glFogFuncSGIS")) == NULL) || r;
+ r = ((glGetFogFuncSGIS = (PFNGLGETFOGFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetFogFuncSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_fog_function */
+
+#ifdef GL_SGIS_generate_mipmap
+
+#endif /* GL_SGIS_generate_mipmap */
+
+#ifdef GL_SGIS_multisample
+
+static GLboolean _glewInit_GL_SGIS_multisample (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSampleMaskSGIS = (PFNGLSAMPLEMASKSGISPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskSGIS")) == NULL) || r;
+ r = ((glSamplePatternSGIS = (PFNGLSAMPLEPATTERNSGISPROC)glewGetProcAddress((const GLubyte*)"glSamplePatternSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_multisample */
+
+#ifdef GL_SGIS_pixel_texture
+
+#endif /* GL_SGIS_pixel_texture */
+
+#ifdef GL_SGIS_point_line_texgen
+
+#endif /* GL_SGIS_point_line_texgen */
+
+#ifdef GL_SGIS_sharpen_texture
+
+static GLboolean _glewInit_GL_SGIS_sharpen_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetSharpenTexFuncSGIS = (PFNGLGETSHARPENTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetSharpenTexFuncSGIS")) == NULL) || r;
+ r = ((glSharpenTexFuncSGIS = (PFNGLSHARPENTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glSharpenTexFuncSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_sharpen_texture */
+
+#ifdef GL_SGIS_texture4D
+
+static GLboolean _glewInit_GL_SGIS_texture4D (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTexImage4DSGIS = (PFNGLTEXIMAGE4DSGISPROC)glewGetProcAddress((const GLubyte*)"glTexImage4DSGIS")) == NULL) || r;
+ r = ((glTexSubImage4DSGIS = (PFNGLTEXSUBIMAGE4DSGISPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage4DSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_texture4D */
+
+#ifdef GL_SGIS_texture_border_clamp
+
+#endif /* GL_SGIS_texture_border_clamp */
+
+#ifdef GL_SGIS_texture_edge_clamp
+
+#endif /* GL_SGIS_texture_edge_clamp */
+
+#ifdef GL_SGIS_texture_filter4
+
+static GLboolean _glewInit_GL_SGIS_texture_filter4 (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGetTexFilterFuncSGIS = (PFNGLGETTEXFILTERFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetTexFilterFuncSGIS")) == NULL) || r;
+ r = ((glTexFilterFuncSGIS = (PFNGLTEXFILTERFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glTexFilterFuncSGIS")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIS_texture_filter4 */
+
+#ifdef GL_SGIS_texture_lod
+
+#endif /* GL_SGIS_texture_lod */
+
+#ifdef GL_SGIS_texture_select
+
+#endif /* GL_SGIS_texture_select */
+
+#ifdef GL_SGIX_async
+
+static GLboolean _glewInit_GL_SGIX_async (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAsyncMarkerSGIX = (PFNGLASYNCMARKERSGIXPROC)glewGetProcAddress((const GLubyte*)"glAsyncMarkerSGIX")) == NULL) || r;
+ r = ((glDeleteAsyncMarkersSGIX = (PFNGLDELETEASYNCMARKERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glDeleteAsyncMarkersSGIX")) == NULL) || r;
+ r = ((glFinishAsyncSGIX = (PFNGLFINISHASYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glFinishAsyncSGIX")) == NULL) || r;
+ r = ((glGenAsyncMarkersSGIX = (PFNGLGENASYNCMARKERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glGenAsyncMarkersSGIX")) == NULL) || r;
+ r = ((glIsAsyncMarkerSGIX = (PFNGLISASYNCMARKERSGIXPROC)glewGetProcAddress((const GLubyte*)"glIsAsyncMarkerSGIX")) == NULL) || r;
+ r = ((glPollAsyncSGIX = (PFNGLPOLLASYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glPollAsyncSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_async */
+
+#ifdef GL_SGIX_async_histogram
+
+#endif /* GL_SGIX_async_histogram */
+
+#ifdef GL_SGIX_async_pixel
+
+#endif /* GL_SGIX_async_pixel */
+
+#ifdef GL_SGIX_blend_alpha_minmax
+
+#endif /* GL_SGIX_blend_alpha_minmax */
+
+#ifdef GL_SGIX_clipmap
+
+#endif /* GL_SGIX_clipmap */
+
+#ifdef GL_SGIX_convolution_accuracy
+
+#endif /* GL_SGIX_convolution_accuracy */
+
+#ifdef GL_SGIX_depth_texture
+
+#endif /* GL_SGIX_depth_texture */
+
+#ifdef GL_SGIX_flush_raster
+
+static GLboolean _glewInit_GL_SGIX_flush_raster (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFlushRasterSGIX = (PFNGLFLUSHRASTERSGIXPROC)glewGetProcAddress((const GLubyte*)"glFlushRasterSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_flush_raster */
+
+#ifdef GL_SGIX_fog_offset
+
+#endif /* GL_SGIX_fog_offset */
+
+#ifdef GL_SGIX_fog_texture
+
+static GLboolean _glewInit_GL_SGIX_fog_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTextureFogSGIX = (PFNGLTEXTUREFOGSGIXPROC)glewGetProcAddress((const GLubyte*)"glTextureFogSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_fog_texture */
+
+#ifdef GL_SGIX_fragment_specular_lighting
+
+static GLboolean _glewInit_GL_SGIX_fragment_specular_lighting (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFragmentColorMaterialSGIX = (PFNGLFRAGMENTCOLORMATERIALSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentColorMaterialSGIX")) == NULL) || r;
+ r = ((glFragmentLightModelfSGIX = (PFNGLFRAGMENTLIGHTMODELFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfSGIX")) == NULL) || r;
+ r = ((glFragmentLightModelfvSGIX = (PFNGLFRAGMENTLIGHTMODELFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfvSGIX")) == NULL) || r;
+ r = ((glFragmentLightModeliSGIX = (PFNGLFRAGMENTLIGHTMODELISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModeliSGIX")) == NULL) || r;
+ r = ((glFragmentLightModelivSGIX = (PFNGLFRAGMENTLIGHTMODELIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelivSGIX")) == NULL) || r;
+ r = ((glFragmentLightfSGIX = (PFNGLFRAGMENTLIGHTFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfSGIX")) == NULL) || r;
+ r = ((glFragmentLightfvSGIX = (PFNGLFRAGMENTLIGHTFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfvSGIX")) == NULL) || r;
+ r = ((glFragmentLightiSGIX = (PFNGLFRAGMENTLIGHTISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightiSGIX")) == NULL) || r;
+ r = ((glFragmentLightivSGIX = (PFNGLFRAGMENTLIGHTIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightivSGIX")) == NULL) || r;
+ r = ((glFragmentMaterialfSGIX = (PFNGLFRAGMENTMATERIALFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfSGIX")) == NULL) || r;
+ r = ((glFragmentMaterialfvSGIX = (PFNGLFRAGMENTMATERIALFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfvSGIX")) == NULL) || r;
+ r = ((glFragmentMaterialiSGIX = (PFNGLFRAGMENTMATERIALISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialiSGIX")) == NULL) || r;
+ r = ((glFragmentMaterialivSGIX = (PFNGLFRAGMENTMATERIALIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialivSGIX")) == NULL) || r;
+ r = ((glGetFragmentLightfvSGIX = (PFNGLGETFRAGMENTLIGHTFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightfvSGIX")) == NULL) || r;
+ r = ((glGetFragmentLightivSGIX = (PFNGLGETFRAGMENTLIGHTIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightivSGIX")) == NULL) || r;
+ r = ((glGetFragmentMaterialfvSGIX = (PFNGLGETFRAGMENTMATERIALFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialfvSGIX")) == NULL) || r;
+ r = ((glGetFragmentMaterialivSGIX = (PFNGLGETFRAGMENTMATERIALIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialivSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_fragment_specular_lighting */
+
+#ifdef GL_SGIX_framezoom
+
+static GLboolean _glewInit_GL_SGIX_framezoom (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFrameZoomSGIX = (PFNGLFRAMEZOOMSGIXPROC)glewGetProcAddress((const GLubyte*)"glFrameZoomSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_framezoom */
+
+#ifdef GL_SGIX_interlace
+
+#endif /* GL_SGIX_interlace */
+
+#ifdef GL_SGIX_ir_instrument1
+
+#endif /* GL_SGIX_ir_instrument1 */
+
+#ifdef GL_SGIX_list_priority
+
+#endif /* GL_SGIX_list_priority */
+
+#ifdef GL_SGIX_pixel_texture
+
+static GLboolean _glewInit_GL_SGIX_pixel_texture (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glPixelTexGenSGIX = (PFNGLPIXELTEXGENSGIXPROC)glewGetProcAddress((const GLubyte*)"glPixelTexGenSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_pixel_texture */
+
+#ifdef GL_SGIX_pixel_texture_bits
+
+#endif /* GL_SGIX_pixel_texture_bits */
+
+#ifdef GL_SGIX_reference_plane
+
+static GLboolean _glewInit_GL_SGIX_reference_plane (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glReferencePlaneSGIX = (PFNGLREFERENCEPLANESGIXPROC)glewGetProcAddress((const GLubyte*)"glReferencePlaneSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_reference_plane */
+
+#ifdef GL_SGIX_resample
+
+#endif /* GL_SGIX_resample */
+
+#ifdef GL_SGIX_shadow
+
+#endif /* GL_SGIX_shadow */
+
+#ifdef GL_SGIX_shadow_ambient
+
+#endif /* GL_SGIX_shadow_ambient */
+
+#ifdef GL_SGIX_sprite
+
+static GLboolean _glewInit_GL_SGIX_sprite (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glSpriteParameterfSGIX = (PFNGLSPRITEPARAMETERFSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterfSGIX")) == NULL) || r;
+ r = ((glSpriteParameterfvSGIX = (PFNGLSPRITEPARAMETERFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterfvSGIX")) == NULL) || r;
+ r = ((glSpriteParameteriSGIX = (PFNGLSPRITEPARAMETERISGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameteriSGIX")) == NULL) || r;
+ r = ((glSpriteParameterivSGIX = (PFNGLSPRITEPARAMETERIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterivSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_sprite */
+
+#ifdef GL_SGIX_tag_sample_buffer
+
+static GLboolean _glewInit_GL_SGIX_tag_sample_buffer (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glTagSampleBufferSGIX = (PFNGLTAGSAMPLEBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glTagSampleBufferSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGIX_tag_sample_buffer */
+
+#ifdef GL_SGIX_texture_add_env
+
+#endif /* GL_SGIX_texture_add_env */
+
+#ifdef GL_SGIX_texture_coordinate_clamp
+
+#endif /* GL_SGIX_texture_coordinate_clamp */
+
+#ifdef GL_SGIX_texture_lod_bias
+
+#endif /* GL_SGIX_texture_lod_bias */
+
+#ifdef GL_SGIX_texture_multi_buffer
+
+#endif /* GL_SGIX_texture_multi_buffer */
+
+#ifdef GL_SGIX_texture_range
+
+#endif /* GL_SGIX_texture_range */
+
+#ifdef GL_SGIX_texture_scale_bias
+
+#endif /* GL_SGIX_texture_scale_bias */
+
+#ifdef GL_SGIX_vertex_preclip
+
+#endif /* GL_SGIX_vertex_preclip */
+
+#ifdef GL_SGIX_vertex_preclip_hint
+
+#endif /* GL_SGIX_vertex_preclip_hint */
+
+#ifdef GL_SGIX_ycrcb
+
+#endif /* GL_SGIX_ycrcb */
+
+#ifdef GL_SGI_color_matrix
+
+#endif /* GL_SGI_color_matrix */
+
+#ifdef GL_SGI_color_table
+
+static GLboolean _glewInit_GL_SGI_color_table (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColorTableParameterfvSGI = (PFNGLCOLORTABLEPARAMETERFVSGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterfvSGI")) == NULL) || r;
+ r = ((glColorTableParameterivSGI = (PFNGLCOLORTABLEPARAMETERIVSGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterivSGI")) == NULL) || r;
+ r = ((glColorTableSGI = (PFNGLCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableSGI")) == NULL) || r;
+ r = ((glCopyColorTableSGI = (PFNGLCOPYCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glCopyColorTableSGI")) == NULL) || r;
+ r = ((glGetColorTableParameterfvSGI = (PFNGLGETCOLORTABLEPARAMETERFVSGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfvSGI")) == NULL) || r;
+ r = ((glGetColorTableParameterivSGI = (PFNGLGETCOLORTABLEPARAMETERIVSGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterivSGI")) == NULL) || r;
+ r = ((glGetColorTableSGI = (PFNGLGETCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SGI_color_table */
+
+#ifdef GL_SGI_texture_color_table
+
+#endif /* GL_SGI_texture_color_table */
+
+#ifdef GL_SUNX_constant_data
+
+static GLboolean _glewInit_GL_SUNX_constant_data (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glFinishTextureSUNX = (PFNGLFINISHTEXTURESUNXPROC)glewGetProcAddress((const GLubyte*)"glFinishTextureSUNX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUNX_constant_data */
+
+#ifdef GL_SUN_convolution_border_modes
+
+#endif /* GL_SUN_convolution_border_modes */
+
+#ifdef GL_SUN_global_alpha
+
+static GLboolean _glewInit_GL_SUN_global_alpha (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glGlobalAlphaFactorbSUN = (PFNGLGLOBALALPHAFACTORBSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorbSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactordSUN = (PFNGLGLOBALALPHAFACTORDSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactordSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactorfSUN = (PFNGLGLOBALALPHAFACTORFSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorfSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactoriSUN = (PFNGLGLOBALALPHAFACTORISUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactoriSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactorsSUN = (PFNGLGLOBALALPHAFACTORSSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorsSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactorubSUN = (PFNGLGLOBALALPHAFACTORUBSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorubSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactoruiSUN = (PFNGLGLOBALALPHAFACTORUISUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactoruiSUN")) == NULL) || r;
+ r = ((glGlobalAlphaFactorusSUN = (PFNGLGLOBALALPHAFACTORUSSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorusSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUN_global_alpha */
+
+#ifdef GL_SUN_mesh_array
+
+#endif /* GL_SUN_mesh_array */
+
+#ifdef GL_SUN_read_video_pixels
+
+static GLboolean _glewInit_GL_SUN_read_video_pixels (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glReadVideoPixelsSUN = (PFNGLREADVIDEOPIXELSSUNPROC)glewGetProcAddress((const GLubyte*)"glReadVideoPixelsSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUN_read_video_pixels */
+
+#ifdef GL_SUN_slice_accum
+
+#endif /* GL_SUN_slice_accum */
+
+#ifdef GL_SUN_triangle_list
+
+static GLboolean _glewInit_GL_SUN_triangle_list (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glReplacementCodePointerSUN = (PFNGLREPLACEMENTCODEPOINTERSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodePointerSUN")) == NULL) || r;
+ r = ((glReplacementCodeubSUN = (PFNGLREPLACEMENTCODEUBSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeubSUN")) == NULL) || r;
+ r = ((glReplacementCodeubvSUN = (PFNGLREPLACEMENTCODEUBVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeubvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiSUN = (PFNGLREPLACEMENTCODEUISUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiSUN")) == NULL) || r;
+ r = ((glReplacementCodeuivSUN = (PFNGLREPLACEMENTCODEUIVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuivSUN")) == NULL) || r;
+ r = ((glReplacementCodeusSUN = (PFNGLREPLACEMENTCODEUSSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeusSUN")) == NULL) || r;
+ r = ((glReplacementCodeusvSUN = (PFNGLREPLACEMENTCODEUSVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeusvSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUN_triangle_list */
+
+#ifdef GL_SUN_vertex
+
+static GLboolean _glewInit_GL_SUN_vertex (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glColor3fVertex3fSUN = (PFNGLCOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor3fVertex3fSUN")) == NULL) || r;
+ r = ((glColor3fVertex3fvSUN = (PFNGLCOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor3fVertex3fvSUN")) == NULL) || r;
+ r = ((glColor4fNormal3fVertex3fSUN = (PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glColor4fNormal3fVertex3fvSUN = (PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glColor4ubVertex2fSUN = (PFNGLCOLOR4UBVERTEX2FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex2fSUN")) == NULL) || r;
+ r = ((glColor4ubVertex2fvSUN = (PFNGLCOLOR4UBVERTEX2FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex2fvSUN")) == NULL) || r;
+ r = ((glColor4ubVertex3fSUN = (PFNGLCOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex3fSUN")) == NULL) || r;
+ r = ((glColor4ubVertex3fvSUN = (PFNGLCOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex3fvSUN")) == NULL) || r;
+ r = ((glNormal3fVertex3fSUN = (PFNGLNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glNormal3fVertex3fvSUN = (PFNGLNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor3fVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor4fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor4fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor4ubVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4ubVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiColor4ubVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4ubVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiTexCoord2fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fVertex3fvSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiVertex3fSUN = (PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiVertex3fSUN")) == NULL) || r;
+ r = ((glReplacementCodeuiVertex3fvSUN = (PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor3fVertex3fSUN = (PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor3fVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor3fVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor3fVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor4fNormal3fVertex3fSUN = (PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor4fNormal3fVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor4ubVertex3fSUN = (PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4ubVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fColor4ubVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4ubVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fNormal3fVertex3fSUN = (PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fNormal3fVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fNormal3fVertex3fvSUN = (PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fNormal3fVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord2fVertex3fSUN = (PFNGLTEXCOORD2FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fVertex3fSUN")) == NULL) || r;
+ r = ((glTexCoord2fVertex3fvSUN = (PFNGLTEXCOORD2FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fVertex3fvSUN")) == NULL) || r;
+ r = ((glTexCoord4fColor4fNormal3fVertex4fSUN = (PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fColor4fNormal3fVertex4fSUN")) == NULL) || r;
+ r = ((glTexCoord4fColor4fNormal3fVertex4fvSUN = (PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fColor4fNormal3fVertex4fvSUN")) == NULL) || r;
+ r = ((glTexCoord4fVertex4fSUN = (PFNGLTEXCOORD4FVERTEX4FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fVertex4fSUN")) == NULL) || r;
+ r = ((glTexCoord4fVertex4fvSUN = (PFNGLTEXCOORD4FVERTEX4FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fVertex4fvSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_SUN_vertex */
+
+#ifdef GL_WIN_phong_shading
+
+#endif /* GL_WIN_phong_shading */
+
+#ifdef GL_WIN_specular_fog
+
+#endif /* GL_WIN_specular_fog */
+
+#ifdef GL_WIN_swap_hint
+
+static GLboolean _glewInit_GL_WIN_swap_hint (GLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glAddSwapHintRectWIN = (PFNGLADDSWAPHINTRECTWINPROC)glewGetProcAddress((const GLubyte*)"glAddSwapHintRectWIN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GL_WIN_swap_hint */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Search for name in the extensions string. Use of strstr()
+ * is not sufficient because extension names can be prefixes of
+ * other extension names. Could use strtok() but the constant
+ * string returned by glGetString might be in read-only memory.
+ */
+GLboolean glewGetExtension (const char* name)
+{
+ GLubyte* p;
+ GLubyte* end;
+ GLuint len = _glewStrLen((const GLubyte*)name);
+ p = (GLubyte*)glGetString(GL_EXTENSIONS);
+ if (0 == p) return GL_FALSE;
+ end = p + _glewStrLen(p);
+ while (p < end)
+ {
+ GLuint n = _glewStrCLen(p, ' ');
+ if (len == n && _glewStrSame((const GLubyte*)name, p, n)) return GL_TRUE;
+ p += n+1;
+ }
+ return GL_FALSE;
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifndef GLEW_MX
+static
+#endif
+GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
+{
+ const GLubyte* s;
+ GLuint dot, major, minor;
+ /* query opengl version */
+ s = glGetString(GL_VERSION);
+ dot = _glewStrCLen(s, '.');
+ major = dot-1;
+ minor = dot+1;
+ if (dot == 0 || s[minor] == '\0')
+ return GLEW_ERROR_NO_GL_VERSION;
+ if (s[major] == '1' && s[minor] == '0')
+ {
+ return GLEW_ERROR_GL_VERSION_10_ONLY;
+ }
+ else
+ {
+ CONST_CAST(GLEW_VERSION_1_1) = GL_TRUE;
+ if (s[major] >= '2')
+ {
+ CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_3) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_4) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_5) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_2_0) = GL_TRUE;
+ if (s[minor] >= '1')
+ {
+ CONST_CAST(GLEW_VERSION_2_1) = GL_TRUE;
+ }
+ }
+ else
+ {
+ if (s[minor] >= '5')
+ {
+ CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_3) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_4) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_5) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE;
+ }
+ if (s[minor] == '4')
+ {
+ CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_3) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_4) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_5) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE;
+ }
+ if (s[minor] == '3')
+ {
+ CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_3) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_4) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_5) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE;
+ }
+ if (s[minor] == '2')
+ {
+ CONST_CAST(GLEW_VERSION_1_2) = GL_TRUE;
+ CONST_CAST(GLEW_VERSION_1_3) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_4) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_5) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE;
+ }
+ if (s[minor] < '2')
+ {
+ CONST_CAST(GLEW_VERSION_1_2) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_3) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_4) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_1_5) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_0) = GL_FALSE;
+ CONST_CAST(GLEW_VERSION_2_1) = GL_FALSE;
+ }
+ }
+ }
+ /* initialize extensions */
+#ifdef GL_VERSION_1_2
+ if (glewExperimental || GLEW_VERSION_1_2) CONST_CAST(GLEW_VERSION_1_2) = !_glewInit_GL_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_1_2 */
+#ifdef GL_VERSION_1_3
+ if (glewExperimental || GLEW_VERSION_1_3) CONST_CAST(GLEW_VERSION_1_3) = !_glewInit_GL_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_1_3 */
+#ifdef GL_VERSION_1_4
+ if (glewExperimental || GLEW_VERSION_1_4) CONST_CAST(GLEW_VERSION_1_4) = !_glewInit_GL_VERSION_1_4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_1_4 */
+#ifdef GL_VERSION_1_5
+ if (glewExperimental || GLEW_VERSION_1_5) CONST_CAST(GLEW_VERSION_1_5) = !_glewInit_GL_VERSION_1_5(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_1_5 */
+#ifdef GL_VERSION_2_0
+ if (glewExperimental || GLEW_VERSION_2_0) CONST_CAST(GLEW_VERSION_2_0) = !_glewInit_GL_VERSION_2_0(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_2_0 */
+#ifdef GL_VERSION_2_1
+ if (glewExperimental || GLEW_VERSION_2_1) CONST_CAST(GLEW_VERSION_2_1) = !_glewInit_GL_VERSION_2_1(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_2_1 */
+#ifdef GL_VERSION_3_0
+ if (glewExperimental || GLEW_VERSION_3_0) CONST_CAST(GLEW_VERSION_3_0) = !_glewInit_GL_VERSION_3_0(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_VERSION_3_0 */
+#ifdef GL_3DFX_multisample
+ CONST_CAST(GLEW_3DFX_multisample) = glewGetExtension("GL_3DFX_multisample");
+#endif /* GL_3DFX_multisample */
+#ifdef GL_3DFX_tbuffer
+ CONST_CAST(GLEW_3DFX_tbuffer) = glewGetExtension("GL_3DFX_tbuffer");
+ if (glewExperimental || GLEW_3DFX_tbuffer) CONST_CAST(GLEW_3DFX_tbuffer) = !_glewInit_GL_3DFX_tbuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_3DFX_tbuffer */
+#ifdef GL_3DFX_texture_compression_FXT1
+ CONST_CAST(GLEW_3DFX_texture_compression_FXT1) = glewGetExtension("GL_3DFX_texture_compression_FXT1");
+#endif /* GL_3DFX_texture_compression_FXT1 */
+#ifdef GL_APPLE_client_storage
+ CONST_CAST(GLEW_APPLE_client_storage) = glewGetExtension("GL_APPLE_client_storage");
+#endif /* GL_APPLE_client_storage */
+#ifdef GL_APPLE_element_array
+ CONST_CAST(GLEW_APPLE_element_array) = glewGetExtension("GL_APPLE_element_array");
+ if (glewExperimental || GLEW_APPLE_element_array) CONST_CAST(GLEW_APPLE_element_array) = !_glewInit_GL_APPLE_element_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_element_array */
+#ifdef GL_APPLE_fence
+ CONST_CAST(GLEW_APPLE_fence) = glewGetExtension("GL_APPLE_fence");
+ if (glewExperimental || GLEW_APPLE_fence) CONST_CAST(GLEW_APPLE_fence) = !_glewInit_GL_APPLE_fence(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_fence */
+#ifdef GL_APPLE_float_pixels
+ CONST_CAST(GLEW_APPLE_float_pixels) = glewGetExtension("GL_APPLE_float_pixels");
+#endif /* GL_APPLE_float_pixels */
+#ifdef GL_APPLE_flush_buffer_range
+ CONST_CAST(GLEW_APPLE_flush_buffer_range) = glewGetExtension("GL_APPLE_flush_buffer_range");
+ if (glewExperimental || GLEW_APPLE_flush_buffer_range) CONST_CAST(GLEW_APPLE_flush_buffer_range) = !_glewInit_GL_APPLE_flush_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_flush_buffer_range */
+#ifdef GL_APPLE_pixel_buffer
+ CONST_CAST(GLEW_APPLE_pixel_buffer) = glewGetExtension("GL_APPLE_pixel_buffer");
+#endif /* GL_APPLE_pixel_buffer */
+#ifdef GL_APPLE_specular_vector
+ CONST_CAST(GLEW_APPLE_specular_vector) = glewGetExtension("GL_APPLE_specular_vector");
+#endif /* GL_APPLE_specular_vector */
+#ifdef GL_APPLE_texture_range
+ CONST_CAST(GLEW_APPLE_texture_range) = glewGetExtension("GL_APPLE_texture_range");
+ if (glewExperimental || GLEW_APPLE_texture_range) CONST_CAST(GLEW_APPLE_texture_range) = !_glewInit_GL_APPLE_texture_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_texture_range */
+#ifdef GL_APPLE_transform_hint
+ CONST_CAST(GLEW_APPLE_transform_hint) = glewGetExtension("GL_APPLE_transform_hint");
+#endif /* GL_APPLE_transform_hint */
+#ifdef GL_APPLE_vertex_array_object
+ CONST_CAST(GLEW_APPLE_vertex_array_object) = glewGetExtension("GL_APPLE_vertex_array_object");
+ if (glewExperimental || GLEW_APPLE_vertex_array_object) CONST_CAST(GLEW_APPLE_vertex_array_object) = !_glewInit_GL_APPLE_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_vertex_array_object */
+#ifdef GL_APPLE_vertex_array_range
+ CONST_CAST(GLEW_APPLE_vertex_array_range) = glewGetExtension("GL_APPLE_vertex_array_range");
+ if (glewExperimental || GLEW_APPLE_vertex_array_range) CONST_CAST(GLEW_APPLE_vertex_array_range) = !_glewInit_GL_APPLE_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_APPLE_vertex_array_range */
+#ifdef GL_APPLE_ycbcr_422
+ CONST_CAST(GLEW_APPLE_ycbcr_422) = glewGetExtension("GL_APPLE_ycbcr_422");
+#endif /* GL_APPLE_ycbcr_422 */
+#ifdef GL_ARB_color_buffer_float
+ CONST_CAST(GLEW_ARB_color_buffer_float) = glewGetExtension("GL_ARB_color_buffer_float");
+ if (glewExperimental || GLEW_ARB_color_buffer_float) CONST_CAST(GLEW_ARB_color_buffer_float) = !_glewInit_GL_ARB_color_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_color_buffer_float */
+#ifdef GL_ARB_depth_buffer_float
+ CONST_CAST(GLEW_ARB_depth_buffer_float) = glewGetExtension("GL_ARB_depth_buffer_float");
+#endif /* GL_ARB_depth_buffer_float */
+#ifdef GL_ARB_depth_texture
+ CONST_CAST(GLEW_ARB_depth_texture) = glewGetExtension("GL_ARB_depth_texture");
+#endif /* GL_ARB_depth_texture */
+#ifdef GL_ARB_draw_buffers
+ CONST_CAST(GLEW_ARB_draw_buffers) = glewGetExtension("GL_ARB_draw_buffers");
+ if (glewExperimental || GLEW_ARB_draw_buffers) CONST_CAST(GLEW_ARB_draw_buffers) = !_glewInit_GL_ARB_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_draw_buffers */
+#ifdef GL_ARB_draw_instanced
+ CONST_CAST(GLEW_ARB_draw_instanced) = glewGetExtension("GL_ARB_draw_instanced");
+ if (glewExperimental || GLEW_ARB_draw_instanced) CONST_CAST(GLEW_ARB_draw_instanced) = !_glewInit_GL_ARB_draw_instanced(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_draw_instanced */
+#ifdef GL_ARB_fragment_program
+ CONST_CAST(GLEW_ARB_fragment_program) = glewGetExtension("GL_ARB_fragment_program");
+#endif /* GL_ARB_fragment_program */
+#ifdef GL_ARB_fragment_program_shadow
+ CONST_CAST(GLEW_ARB_fragment_program_shadow) = glewGetExtension("GL_ARB_fragment_program_shadow");
+#endif /* GL_ARB_fragment_program_shadow */
+#ifdef GL_ARB_fragment_shader
+ CONST_CAST(GLEW_ARB_fragment_shader) = glewGetExtension("GL_ARB_fragment_shader");
+#endif /* GL_ARB_fragment_shader */
+#ifdef GL_ARB_framebuffer_object
+ CONST_CAST(GLEW_ARB_framebuffer_object) = glewGetExtension("GL_ARB_framebuffer_object");
+ if (glewExperimental || GLEW_ARB_framebuffer_object) CONST_CAST(GLEW_ARB_framebuffer_object) = !_glewInit_GL_ARB_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_framebuffer_object */
+#ifdef GL_ARB_framebuffer_sRGB
+ CONST_CAST(GLEW_ARB_framebuffer_sRGB) = glewGetExtension("GL_ARB_framebuffer_sRGB");
+#endif /* GL_ARB_framebuffer_sRGB */
+#ifdef GL_ARB_geometry_shader4
+ CONST_CAST(GLEW_ARB_geometry_shader4) = glewGetExtension("GL_ARB_geometry_shader4");
+ if (glewExperimental || GLEW_ARB_geometry_shader4) CONST_CAST(GLEW_ARB_geometry_shader4) = !_glewInit_GL_ARB_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_geometry_shader4 */
+#ifdef GL_ARB_half_float_pixel
+ CONST_CAST(GLEW_ARB_half_float_pixel) = glewGetExtension("GL_ARB_half_float_pixel");
+#endif /* GL_ARB_half_float_pixel */
+#ifdef GL_ARB_half_float_vertex
+ CONST_CAST(GLEW_ARB_half_float_vertex) = glewGetExtension("GL_ARB_half_float_vertex");
+#endif /* GL_ARB_half_float_vertex */
+#ifdef GL_ARB_imaging
+ CONST_CAST(GLEW_ARB_imaging) = glewGetExtension("GL_ARB_imaging");
+ if (glewExperimental || GLEW_ARB_imaging) CONST_CAST(GLEW_ARB_imaging) = !_glewInit_GL_ARB_imaging(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_imaging */
+#ifdef GL_ARB_instanced_arrays
+ CONST_CAST(GLEW_ARB_instanced_arrays) = glewGetExtension("GL_ARB_instanced_arrays");
+ if (glewExperimental || GLEW_ARB_instanced_arrays) CONST_CAST(GLEW_ARB_instanced_arrays) = !_glewInit_GL_ARB_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_instanced_arrays */
+#ifdef GL_ARB_map_buffer_range
+ CONST_CAST(GLEW_ARB_map_buffer_range) = glewGetExtension("GL_ARB_map_buffer_range");
+ if (glewExperimental || GLEW_ARB_map_buffer_range) CONST_CAST(GLEW_ARB_map_buffer_range) = !_glewInit_GL_ARB_map_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_map_buffer_range */
+#ifdef GL_ARB_matrix_palette
+ CONST_CAST(GLEW_ARB_matrix_palette) = glewGetExtension("GL_ARB_matrix_palette");
+ if (glewExperimental || GLEW_ARB_matrix_palette) CONST_CAST(GLEW_ARB_matrix_palette) = !_glewInit_GL_ARB_matrix_palette(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_matrix_palette */
+#ifdef GL_ARB_multisample
+ CONST_CAST(GLEW_ARB_multisample) = glewGetExtension("GL_ARB_multisample");
+ if (glewExperimental || GLEW_ARB_multisample) CONST_CAST(GLEW_ARB_multisample) = !_glewInit_GL_ARB_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_multisample */
+#ifdef GL_ARB_multitexture
+ CONST_CAST(GLEW_ARB_multitexture) = glewGetExtension("GL_ARB_multitexture");
+ if (glewExperimental || GLEW_ARB_multitexture) CONST_CAST(GLEW_ARB_multitexture) = !_glewInit_GL_ARB_multitexture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_multitexture */
+#ifdef GL_ARB_occlusion_query
+ CONST_CAST(GLEW_ARB_occlusion_query) = glewGetExtension("GL_ARB_occlusion_query");
+ if (glewExperimental || GLEW_ARB_occlusion_query) CONST_CAST(GLEW_ARB_occlusion_query) = !_glewInit_GL_ARB_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_occlusion_query */
+#ifdef GL_ARB_pixel_buffer_object
+ CONST_CAST(GLEW_ARB_pixel_buffer_object) = glewGetExtension("GL_ARB_pixel_buffer_object");
+#endif /* GL_ARB_pixel_buffer_object */
+#ifdef GL_ARB_point_parameters
+ CONST_CAST(GLEW_ARB_point_parameters) = glewGetExtension("GL_ARB_point_parameters");
+ if (glewExperimental || GLEW_ARB_point_parameters) CONST_CAST(GLEW_ARB_point_parameters) = !_glewInit_GL_ARB_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_point_parameters */
+#ifdef GL_ARB_point_sprite
+ CONST_CAST(GLEW_ARB_point_sprite) = glewGetExtension("GL_ARB_point_sprite");
+#endif /* GL_ARB_point_sprite */
+#ifdef GL_ARB_shader_objects
+ CONST_CAST(GLEW_ARB_shader_objects) = glewGetExtension("GL_ARB_shader_objects");
+ if (glewExperimental || GLEW_ARB_shader_objects) CONST_CAST(GLEW_ARB_shader_objects) = !_glewInit_GL_ARB_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_shader_objects */
+#ifdef GL_ARB_shading_language_100
+ CONST_CAST(GLEW_ARB_shading_language_100) = glewGetExtension("GL_ARB_shading_language_100");
+#endif /* GL_ARB_shading_language_100 */
+#ifdef GL_ARB_shadow
+ CONST_CAST(GLEW_ARB_shadow) = glewGetExtension("GL_ARB_shadow");
+#endif /* GL_ARB_shadow */
+#ifdef GL_ARB_shadow_ambient
+ CONST_CAST(GLEW_ARB_shadow_ambient) = glewGetExtension("GL_ARB_shadow_ambient");
+#endif /* GL_ARB_shadow_ambient */
+#ifdef GL_ARB_texture_border_clamp
+ CONST_CAST(GLEW_ARB_texture_border_clamp) = glewGetExtension("GL_ARB_texture_border_clamp");
+#endif /* GL_ARB_texture_border_clamp */
+#ifdef GL_ARB_texture_buffer_object
+ CONST_CAST(GLEW_ARB_texture_buffer_object) = glewGetExtension("GL_ARB_texture_buffer_object");
+ if (glewExperimental || GLEW_ARB_texture_buffer_object) CONST_CAST(GLEW_ARB_texture_buffer_object) = !_glewInit_GL_ARB_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_buffer_object */
+#ifdef GL_ARB_texture_compression
+ CONST_CAST(GLEW_ARB_texture_compression) = glewGetExtension("GL_ARB_texture_compression");
+ if (glewExperimental || GLEW_ARB_texture_compression) CONST_CAST(GLEW_ARB_texture_compression) = !_glewInit_GL_ARB_texture_compression(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_texture_compression */
+#ifdef GL_ARB_texture_compression_rgtc
+ CONST_CAST(GLEW_ARB_texture_compression_rgtc) = glewGetExtension("GL_ARB_texture_compression_rgtc");
+#endif /* GL_ARB_texture_compression_rgtc */
+#ifdef GL_ARB_texture_cube_map
+ CONST_CAST(GLEW_ARB_texture_cube_map) = glewGetExtension("GL_ARB_texture_cube_map");
+#endif /* GL_ARB_texture_cube_map */
+#ifdef GL_ARB_texture_env_add
+ CONST_CAST(GLEW_ARB_texture_env_add) = glewGetExtension("GL_ARB_texture_env_add");
+#endif /* GL_ARB_texture_env_add */
+#ifdef GL_ARB_texture_env_combine
+ CONST_CAST(GLEW_ARB_texture_env_combine) = glewGetExtension("GL_ARB_texture_env_combine");
+#endif /* GL_ARB_texture_env_combine */
+#ifdef GL_ARB_texture_env_crossbar
+ CONST_CAST(GLEW_ARB_texture_env_crossbar) = glewGetExtension("GL_ARB_texture_env_crossbar");
+#endif /* GL_ARB_texture_env_crossbar */
+#ifdef GL_ARB_texture_env_dot3
+ CONST_CAST(GLEW_ARB_texture_env_dot3) = glewGetExtension("GL_ARB_texture_env_dot3");
+#endif /* GL_ARB_texture_env_dot3 */
+#ifdef GL_ARB_texture_float
+ CONST_CAST(GLEW_ARB_texture_float) = glewGetExtension("GL_ARB_texture_float");
+#endif /* GL_ARB_texture_float */
+#ifdef GL_ARB_texture_mirrored_repeat
+ CONST_CAST(GLEW_ARB_texture_mirrored_repeat) = glewGetExtension("GL_ARB_texture_mirrored_repeat");
+#endif /* GL_ARB_texture_mirrored_repeat */
+#ifdef GL_ARB_texture_non_power_of_two
+ CONST_CAST(GLEW_ARB_texture_non_power_of_two) = glewGetExtension("GL_ARB_texture_non_power_of_two");
+#endif /* GL_ARB_texture_non_power_of_two */
+#ifdef GL_ARB_texture_rectangle
+ CONST_CAST(GLEW_ARB_texture_rectangle) = glewGetExtension("GL_ARB_texture_rectangle");
+#endif /* GL_ARB_texture_rectangle */
+#ifdef GL_ARB_texture_rg
+ CONST_CAST(GLEW_ARB_texture_rg) = glewGetExtension("GL_ARB_texture_rg");
+#endif /* GL_ARB_texture_rg */
+#ifdef GL_ARB_transpose_matrix
+ CONST_CAST(GLEW_ARB_transpose_matrix) = glewGetExtension("GL_ARB_transpose_matrix");
+ if (glewExperimental || GLEW_ARB_transpose_matrix) CONST_CAST(GLEW_ARB_transpose_matrix) = !_glewInit_GL_ARB_transpose_matrix(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_transpose_matrix */
+#ifdef GL_ARB_vertex_array_object
+ CONST_CAST(GLEW_ARB_vertex_array_object) = glewGetExtension("GL_ARB_vertex_array_object");
+ if (glewExperimental || GLEW_ARB_vertex_array_object) CONST_CAST(GLEW_ARB_vertex_array_object) = !_glewInit_GL_ARB_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_array_object */
+#ifdef GL_ARB_vertex_blend
+ CONST_CAST(GLEW_ARB_vertex_blend) = glewGetExtension("GL_ARB_vertex_blend");
+ if (glewExperimental || GLEW_ARB_vertex_blend) CONST_CAST(GLEW_ARB_vertex_blend) = !_glewInit_GL_ARB_vertex_blend(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_blend */
+#ifdef GL_ARB_vertex_buffer_object
+ CONST_CAST(GLEW_ARB_vertex_buffer_object) = glewGetExtension("GL_ARB_vertex_buffer_object");
+ if (glewExperimental || GLEW_ARB_vertex_buffer_object) CONST_CAST(GLEW_ARB_vertex_buffer_object) = !_glewInit_GL_ARB_vertex_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_buffer_object */
+#ifdef GL_ARB_vertex_program
+ CONST_CAST(GLEW_ARB_vertex_program) = glewGetExtension("GL_ARB_vertex_program");
+ if (glewExperimental || GLEW_ARB_vertex_program) CONST_CAST(GLEW_ARB_vertex_program) = !_glewInit_GL_ARB_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_program */
+#ifdef GL_ARB_vertex_shader
+ CONST_CAST(GLEW_ARB_vertex_shader) = glewGetExtension("GL_ARB_vertex_shader");
+ if (glewExperimental || GLEW_ARB_vertex_shader) CONST_CAST(GLEW_ARB_vertex_shader) = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_vertex_shader */
+#ifdef GL_ARB_window_pos
+ CONST_CAST(GLEW_ARB_window_pos) = glewGetExtension("GL_ARB_window_pos");
+ if (glewExperimental || GLEW_ARB_window_pos) CONST_CAST(GLEW_ARB_window_pos) = !_glewInit_GL_ARB_window_pos(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ARB_window_pos */
+#ifdef GL_ATIX_point_sprites
+ CONST_CAST(GLEW_ATIX_point_sprites) = glewGetExtension("GL_ATIX_point_sprites");
+#endif /* GL_ATIX_point_sprites */
+#ifdef GL_ATIX_texture_env_combine3
+ CONST_CAST(GLEW_ATIX_texture_env_combine3) = glewGetExtension("GL_ATIX_texture_env_combine3");
+#endif /* GL_ATIX_texture_env_combine3 */
+#ifdef GL_ATIX_texture_env_route
+ CONST_CAST(GLEW_ATIX_texture_env_route) = glewGetExtension("GL_ATIX_texture_env_route");
+#endif /* GL_ATIX_texture_env_route */
+#ifdef GL_ATIX_vertex_shader_output_point_size
+ CONST_CAST(GLEW_ATIX_vertex_shader_output_point_size) = glewGetExtension("GL_ATIX_vertex_shader_output_point_size");
+#endif /* GL_ATIX_vertex_shader_output_point_size */
+#ifdef GL_ATI_draw_buffers
+ CONST_CAST(GLEW_ATI_draw_buffers) = glewGetExtension("GL_ATI_draw_buffers");
+ if (glewExperimental || GLEW_ATI_draw_buffers) CONST_CAST(GLEW_ATI_draw_buffers) = !_glewInit_GL_ATI_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_draw_buffers */
+#ifdef GL_ATI_element_array
+ CONST_CAST(GLEW_ATI_element_array) = glewGetExtension("GL_ATI_element_array");
+ if (glewExperimental || GLEW_ATI_element_array) CONST_CAST(GLEW_ATI_element_array) = !_glewInit_GL_ATI_element_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_element_array */
+#ifdef GL_ATI_envmap_bumpmap
+ CONST_CAST(GLEW_ATI_envmap_bumpmap) = glewGetExtension("GL_ATI_envmap_bumpmap");
+ if (glewExperimental || GLEW_ATI_envmap_bumpmap) CONST_CAST(GLEW_ATI_envmap_bumpmap) = !_glewInit_GL_ATI_envmap_bumpmap(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_envmap_bumpmap */
+#ifdef GL_ATI_fragment_shader
+ CONST_CAST(GLEW_ATI_fragment_shader) = glewGetExtension("GL_ATI_fragment_shader");
+ if (glewExperimental || GLEW_ATI_fragment_shader) CONST_CAST(GLEW_ATI_fragment_shader) = !_glewInit_GL_ATI_fragment_shader(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_fragment_shader */
+#ifdef GL_ATI_map_object_buffer
+ CONST_CAST(GLEW_ATI_map_object_buffer) = glewGetExtension("GL_ATI_map_object_buffer");
+ if (glewExperimental || GLEW_ATI_map_object_buffer) CONST_CAST(GLEW_ATI_map_object_buffer) = !_glewInit_GL_ATI_map_object_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_map_object_buffer */
+#ifdef GL_ATI_pn_triangles
+ CONST_CAST(GLEW_ATI_pn_triangles) = glewGetExtension("GL_ATI_pn_triangles");
+ if (glewExperimental || GLEW_ATI_pn_triangles) CONST_CAST(GLEW_ATI_pn_triangles) = !_glewInit_GL_ATI_pn_triangles(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_pn_triangles */
+#ifdef GL_ATI_separate_stencil
+ CONST_CAST(GLEW_ATI_separate_stencil) = glewGetExtension("GL_ATI_separate_stencil");
+ if (glewExperimental || GLEW_ATI_separate_stencil) CONST_CAST(GLEW_ATI_separate_stencil) = !_glewInit_GL_ATI_separate_stencil(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_separate_stencil */
+#ifdef GL_ATI_shader_texture_lod
+ CONST_CAST(GLEW_ATI_shader_texture_lod) = glewGetExtension("GL_ATI_shader_texture_lod");
+#endif /* GL_ATI_shader_texture_lod */
+#ifdef GL_ATI_text_fragment_shader
+ CONST_CAST(GLEW_ATI_text_fragment_shader) = glewGetExtension("GL_ATI_text_fragment_shader");
+#endif /* GL_ATI_text_fragment_shader */
+#ifdef GL_ATI_texture_compression_3dc
+ CONST_CAST(GLEW_ATI_texture_compression_3dc) = glewGetExtension("GL_ATI_texture_compression_3dc");
+#endif /* GL_ATI_texture_compression_3dc */
+#ifdef GL_ATI_texture_env_combine3
+ CONST_CAST(GLEW_ATI_texture_env_combine3) = glewGetExtension("GL_ATI_texture_env_combine3");
+#endif /* GL_ATI_texture_env_combine3 */
+#ifdef GL_ATI_texture_float
+ CONST_CAST(GLEW_ATI_texture_float) = glewGetExtension("GL_ATI_texture_float");
+#endif /* GL_ATI_texture_float */
+#ifdef GL_ATI_texture_mirror_once
+ CONST_CAST(GLEW_ATI_texture_mirror_once) = glewGetExtension("GL_ATI_texture_mirror_once");
+#endif /* GL_ATI_texture_mirror_once */
+#ifdef GL_ATI_vertex_array_object
+ CONST_CAST(GLEW_ATI_vertex_array_object) = glewGetExtension("GL_ATI_vertex_array_object");
+ if (glewExperimental || GLEW_ATI_vertex_array_object) CONST_CAST(GLEW_ATI_vertex_array_object) = !_glewInit_GL_ATI_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_vertex_array_object */
+#ifdef GL_ATI_vertex_attrib_array_object
+ CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = glewGetExtension("GL_ATI_vertex_attrib_array_object");
+ if (glewExperimental || GLEW_ATI_vertex_attrib_array_object) CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = !_glewInit_GL_ATI_vertex_attrib_array_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_vertex_attrib_array_object */
+#ifdef GL_ATI_vertex_streams
+ CONST_CAST(GLEW_ATI_vertex_streams) = glewGetExtension("GL_ATI_vertex_streams");
+ if (glewExperimental || GLEW_ATI_vertex_streams) CONST_CAST(GLEW_ATI_vertex_streams) = !_glewInit_GL_ATI_vertex_streams(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_ATI_vertex_streams */
+#ifdef GL_EXT_422_pixels
+ CONST_CAST(GLEW_EXT_422_pixels) = glewGetExtension("GL_EXT_422_pixels");
+#endif /* GL_EXT_422_pixels */
+#ifdef GL_EXT_Cg_shader
+ CONST_CAST(GLEW_EXT_Cg_shader) = glewGetExtension("GL_EXT_Cg_shader");
+#endif /* GL_EXT_Cg_shader */
+#ifdef GL_EXT_abgr
+ CONST_CAST(GLEW_EXT_abgr) = glewGetExtension("GL_EXT_abgr");
+#endif /* GL_EXT_abgr */
+#ifdef GL_EXT_bgra
+ CONST_CAST(GLEW_EXT_bgra) = glewGetExtension("GL_EXT_bgra");
+#endif /* GL_EXT_bgra */
+#ifdef GL_EXT_bindable_uniform
+ CONST_CAST(GLEW_EXT_bindable_uniform) = glewGetExtension("GL_EXT_bindable_uniform");
+ if (glewExperimental || GLEW_EXT_bindable_uniform) CONST_CAST(GLEW_EXT_bindable_uniform) = !_glewInit_GL_EXT_bindable_uniform(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_bindable_uniform */
+#ifdef GL_EXT_blend_color
+ CONST_CAST(GLEW_EXT_blend_color) = glewGetExtension("GL_EXT_blend_color");
+ if (glewExperimental || GLEW_EXT_blend_color) CONST_CAST(GLEW_EXT_blend_color) = !_glewInit_GL_EXT_blend_color(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_blend_color */
+#ifdef GL_EXT_blend_equation_separate
+ CONST_CAST(GLEW_EXT_blend_equation_separate) = glewGetExtension("GL_EXT_blend_equation_separate");
+ if (glewExperimental || GLEW_EXT_blend_equation_separate) CONST_CAST(GLEW_EXT_blend_equation_separate) = !_glewInit_GL_EXT_blend_equation_separate(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_blend_equation_separate */
+#ifdef GL_EXT_blend_func_separate
+ CONST_CAST(GLEW_EXT_blend_func_separate) = glewGetExtension("GL_EXT_blend_func_separate");
+ if (glewExperimental || GLEW_EXT_blend_func_separate) CONST_CAST(GLEW_EXT_blend_func_separate) = !_glewInit_GL_EXT_blend_func_separate(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_blend_func_separate */
+#ifdef GL_EXT_blend_logic_op
+ CONST_CAST(GLEW_EXT_blend_logic_op) = glewGetExtension("GL_EXT_blend_logic_op");
+#endif /* GL_EXT_blend_logic_op */
+#ifdef GL_EXT_blend_minmax
+ CONST_CAST(GLEW_EXT_blend_minmax) = glewGetExtension("GL_EXT_blend_minmax");
+ if (glewExperimental || GLEW_EXT_blend_minmax) CONST_CAST(GLEW_EXT_blend_minmax) = !_glewInit_GL_EXT_blend_minmax(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_blend_minmax */
+#ifdef GL_EXT_blend_subtract
+ CONST_CAST(GLEW_EXT_blend_subtract) = glewGetExtension("GL_EXT_blend_subtract");
+#endif /* GL_EXT_blend_subtract */
+#ifdef GL_EXT_clip_volume_hint
+ CONST_CAST(GLEW_EXT_clip_volume_hint) = glewGetExtension("GL_EXT_clip_volume_hint");
+#endif /* GL_EXT_clip_volume_hint */
+#ifdef GL_EXT_cmyka
+ CONST_CAST(GLEW_EXT_cmyka) = glewGetExtension("GL_EXT_cmyka");
+#endif /* GL_EXT_cmyka */
+#ifdef GL_EXT_color_subtable
+ CONST_CAST(GLEW_EXT_color_subtable) = glewGetExtension("GL_EXT_color_subtable");
+ if (glewExperimental || GLEW_EXT_color_subtable) CONST_CAST(GLEW_EXT_color_subtable) = !_glewInit_GL_EXT_color_subtable(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_color_subtable */
+#ifdef GL_EXT_compiled_vertex_array
+ CONST_CAST(GLEW_EXT_compiled_vertex_array) = glewGetExtension("GL_EXT_compiled_vertex_array");
+ if (glewExperimental || GLEW_EXT_compiled_vertex_array) CONST_CAST(GLEW_EXT_compiled_vertex_array) = !_glewInit_GL_EXT_compiled_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_compiled_vertex_array */
+#ifdef GL_EXT_convolution
+ CONST_CAST(GLEW_EXT_convolution) = glewGetExtension("GL_EXT_convolution");
+ if (glewExperimental || GLEW_EXT_convolution) CONST_CAST(GLEW_EXT_convolution) = !_glewInit_GL_EXT_convolution(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_convolution */
+#ifdef GL_EXT_coordinate_frame
+ CONST_CAST(GLEW_EXT_coordinate_frame) = glewGetExtension("GL_EXT_coordinate_frame");
+ if (glewExperimental || GLEW_EXT_coordinate_frame) CONST_CAST(GLEW_EXT_coordinate_frame) = !_glewInit_GL_EXT_coordinate_frame(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_coordinate_frame */
+#ifdef GL_EXT_copy_texture
+ CONST_CAST(GLEW_EXT_copy_texture) = glewGetExtension("GL_EXT_copy_texture");
+ if (glewExperimental || GLEW_EXT_copy_texture) CONST_CAST(GLEW_EXT_copy_texture) = !_glewInit_GL_EXT_copy_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_copy_texture */
+#ifdef GL_EXT_cull_vertex
+ CONST_CAST(GLEW_EXT_cull_vertex) = glewGetExtension("GL_EXT_cull_vertex");
+ if (glewExperimental || GLEW_EXT_cull_vertex) CONST_CAST(GLEW_EXT_cull_vertex) = !_glewInit_GL_EXT_cull_vertex(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_cull_vertex */
+#ifdef GL_EXT_depth_bounds_test
+ CONST_CAST(GLEW_EXT_depth_bounds_test) = glewGetExtension("GL_EXT_depth_bounds_test");
+ if (glewExperimental || GLEW_EXT_depth_bounds_test) CONST_CAST(GLEW_EXT_depth_bounds_test) = !_glewInit_GL_EXT_depth_bounds_test(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_depth_bounds_test */
+#ifdef GL_EXT_direct_state_access
+ CONST_CAST(GLEW_EXT_direct_state_access) = glewGetExtension("GL_EXT_direct_state_access");
+ if (glewExperimental || GLEW_EXT_direct_state_access) CONST_CAST(GLEW_EXT_direct_state_access) = !_glewInit_GL_EXT_direct_state_access(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_direct_state_access */
+#ifdef GL_EXT_draw_buffers2
+ CONST_CAST(GLEW_EXT_draw_buffers2) = glewGetExtension("GL_EXT_draw_buffers2");
+ if (glewExperimental || GLEW_EXT_draw_buffers2) CONST_CAST(GLEW_EXT_draw_buffers2) = !_glewInit_GL_EXT_draw_buffers2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_draw_buffers2 */
+#ifdef GL_EXT_draw_instanced
+ CONST_CAST(GLEW_EXT_draw_instanced) = glewGetExtension("GL_EXT_draw_instanced");
+ if (glewExperimental || GLEW_EXT_draw_instanced) CONST_CAST(GLEW_EXT_draw_instanced) = !_glewInit_GL_EXT_draw_instanced(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_draw_instanced */
+#ifdef GL_EXT_draw_range_elements
+ CONST_CAST(GLEW_EXT_draw_range_elements) = glewGetExtension("GL_EXT_draw_range_elements");
+ if (glewExperimental || GLEW_EXT_draw_range_elements) CONST_CAST(GLEW_EXT_draw_range_elements) = !_glewInit_GL_EXT_draw_range_elements(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_draw_range_elements */
+#ifdef GL_EXT_fog_coord
+ CONST_CAST(GLEW_EXT_fog_coord) = glewGetExtension("GL_EXT_fog_coord");
+ if (glewExperimental || GLEW_EXT_fog_coord) CONST_CAST(GLEW_EXT_fog_coord) = !_glewInit_GL_EXT_fog_coord(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_fog_coord */
+#ifdef GL_EXT_fragment_lighting
+ CONST_CAST(GLEW_EXT_fragment_lighting) = glewGetExtension("GL_EXT_fragment_lighting");
+ if (glewExperimental || GLEW_EXT_fragment_lighting) CONST_CAST(GLEW_EXT_fragment_lighting) = !_glewInit_GL_EXT_fragment_lighting(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_fragment_lighting */
+#ifdef GL_EXT_framebuffer_blit
+ CONST_CAST(GLEW_EXT_framebuffer_blit) = glewGetExtension("GL_EXT_framebuffer_blit");
+ if (glewExperimental || GLEW_EXT_framebuffer_blit) CONST_CAST(GLEW_EXT_framebuffer_blit) = !_glewInit_GL_EXT_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_framebuffer_blit */
+#ifdef GL_EXT_framebuffer_multisample
+ CONST_CAST(GLEW_EXT_framebuffer_multisample) = glewGetExtension("GL_EXT_framebuffer_multisample");
+ if (glewExperimental || GLEW_EXT_framebuffer_multisample) CONST_CAST(GLEW_EXT_framebuffer_multisample) = !_glewInit_GL_EXT_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_framebuffer_multisample */
+#ifdef GL_EXT_framebuffer_object
+ CONST_CAST(GLEW_EXT_framebuffer_object) = glewGetExtension("GL_EXT_framebuffer_object");
+ if (glewExperimental || GLEW_EXT_framebuffer_object) CONST_CAST(GLEW_EXT_framebuffer_object) = !_glewInit_GL_EXT_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_framebuffer_object */
+#ifdef GL_EXT_framebuffer_sRGB
+ CONST_CAST(GLEW_EXT_framebuffer_sRGB) = glewGetExtension("GL_EXT_framebuffer_sRGB");
+#endif /* GL_EXT_framebuffer_sRGB */
+#ifdef GL_EXT_geometry_shader4
+ CONST_CAST(GLEW_EXT_geometry_shader4) = glewGetExtension("GL_EXT_geometry_shader4");
+ if (glewExperimental || GLEW_EXT_geometry_shader4) CONST_CAST(GLEW_EXT_geometry_shader4) = !_glewInit_GL_EXT_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_geometry_shader4 */
+#ifdef GL_EXT_gpu_program_parameters
+ CONST_CAST(GLEW_EXT_gpu_program_parameters) = glewGetExtension("GL_EXT_gpu_program_parameters");
+ if (glewExperimental || GLEW_EXT_gpu_program_parameters) CONST_CAST(GLEW_EXT_gpu_program_parameters) = !_glewInit_GL_EXT_gpu_program_parameters(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_gpu_program_parameters */
+#ifdef GL_EXT_gpu_shader4
+ CONST_CAST(GLEW_EXT_gpu_shader4) = glewGetExtension("GL_EXT_gpu_shader4");
+ if (glewExperimental || GLEW_EXT_gpu_shader4) CONST_CAST(GLEW_EXT_gpu_shader4) = !_glewInit_GL_EXT_gpu_shader4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_gpu_shader4 */
+#ifdef GL_EXT_histogram
+ CONST_CAST(GLEW_EXT_histogram) = glewGetExtension("GL_EXT_histogram");
+ if (glewExperimental || GLEW_EXT_histogram) CONST_CAST(GLEW_EXT_histogram) = !_glewInit_GL_EXT_histogram(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_histogram */
+#ifdef GL_EXT_index_array_formats
+ CONST_CAST(GLEW_EXT_index_array_formats) = glewGetExtension("GL_EXT_index_array_formats");
+#endif /* GL_EXT_index_array_formats */
+#ifdef GL_EXT_index_func
+ CONST_CAST(GLEW_EXT_index_func) = glewGetExtension("GL_EXT_index_func");
+ if (glewExperimental || GLEW_EXT_index_func) CONST_CAST(GLEW_EXT_index_func) = !_glewInit_GL_EXT_index_func(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_index_func */
+#ifdef GL_EXT_index_material
+ CONST_CAST(GLEW_EXT_index_material) = glewGetExtension("GL_EXT_index_material");
+ if (glewExperimental || GLEW_EXT_index_material) CONST_CAST(GLEW_EXT_index_material) = !_glewInit_GL_EXT_index_material(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_index_material */
+#ifdef GL_EXT_index_texture
+ CONST_CAST(GLEW_EXT_index_texture) = glewGetExtension("GL_EXT_index_texture");
+#endif /* GL_EXT_index_texture */
+#ifdef GL_EXT_light_texture
+ CONST_CAST(GLEW_EXT_light_texture) = glewGetExtension("GL_EXT_light_texture");
+ if (glewExperimental || GLEW_EXT_light_texture) CONST_CAST(GLEW_EXT_light_texture) = !_glewInit_GL_EXT_light_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_light_texture */
+#ifdef GL_EXT_misc_attribute
+ CONST_CAST(GLEW_EXT_misc_attribute) = glewGetExtension("GL_EXT_misc_attribute");
+#endif /* GL_EXT_misc_attribute */
+#ifdef GL_EXT_multi_draw_arrays
+ CONST_CAST(GLEW_EXT_multi_draw_arrays) = glewGetExtension("GL_EXT_multi_draw_arrays");
+ if (glewExperimental || GLEW_EXT_multi_draw_arrays) CONST_CAST(GLEW_EXT_multi_draw_arrays) = !_glewInit_GL_EXT_multi_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_multi_draw_arrays */
+#ifdef GL_EXT_multisample
+ CONST_CAST(GLEW_EXT_multisample) = glewGetExtension("GL_EXT_multisample");
+ if (glewExperimental || GLEW_EXT_multisample) CONST_CAST(GLEW_EXT_multisample) = !_glewInit_GL_EXT_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_multisample */
+#ifdef GL_EXT_packed_depth_stencil
+ CONST_CAST(GLEW_EXT_packed_depth_stencil) = glewGetExtension("GL_EXT_packed_depth_stencil");
+#endif /* GL_EXT_packed_depth_stencil */
+#ifdef GL_EXT_packed_float
+ CONST_CAST(GLEW_EXT_packed_float) = glewGetExtension("GL_EXT_packed_float");
+#endif /* GL_EXT_packed_float */
+#ifdef GL_EXT_packed_pixels
+ CONST_CAST(GLEW_EXT_packed_pixels) = glewGetExtension("GL_EXT_packed_pixels");
+#endif /* GL_EXT_packed_pixels */
+#ifdef GL_EXT_paletted_texture
+ CONST_CAST(GLEW_EXT_paletted_texture) = glewGetExtension("GL_EXT_paletted_texture");
+ if (glewExperimental || GLEW_EXT_paletted_texture) CONST_CAST(GLEW_EXT_paletted_texture) = !_glewInit_GL_EXT_paletted_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_paletted_texture */
+#ifdef GL_EXT_pixel_buffer_object
+ CONST_CAST(GLEW_EXT_pixel_buffer_object) = glewGetExtension("GL_EXT_pixel_buffer_object");
+#endif /* GL_EXT_pixel_buffer_object */
+#ifdef GL_EXT_pixel_transform
+ CONST_CAST(GLEW_EXT_pixel_transform) = glewGetExtension("GL_EXT_pixel_transform");
+ if (glewExperimental || GLEW_EXT_pixel_transform) CONST_CAST(GLEW_EXT_pixel_transform) = !_glewInit_GL_EXT_pixel_transform(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_pixel_transform */
+#ifdef GL_EXT_pixel_transform_color_table
+ CONST_CAST(GLEW_EXT_pixel_transform_color_table) = glewGetExtension("GL_EXT_pixel_transform_color_table");
+#endif /* GL_EXT_pixel_transform_color_table */
+#ifdef GL_EXT_point_parameters
+ CONST_CAST(GLEW_EXT_point_parameters) = glewGetExtension("GL_EXT_point_parameters");
+ if (glewExperimental || GLEW_EXT_point_parameters) CONST_CAST(GLEW_EXT_point_parameters) = !_glewInit_GL_EXT_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_point_parameters */
+#ifdef GL_EXT_polygon_offset
+ CONST_CAST(GLEW_EXT_polygon_offset) = glewGetExtension("GL_EXT_polygon_offset");
+ if (glewExperimental || GLEW_EXT_polygon_offset) CONST_CAST(GLEW_EXT_polygon_offset) = !_glewInit_GL_EXT_polygon_offset(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_polygon_offset */
+#ifdef GL_EXT_rescale_normal
+ CONST_CAST(GLEW_EXT_rescale_normal) = glewGetExtension("GL_EXT_rescale_normal");
+#endif /* GL_EXT_rescale_normal */
+#ifdef GL_EXT_scene_marker
+ CONST_CAST(GLEW_EXT_scene_marker) = glewGetExtension("GL_EXT_scene_marker");
+ if (glewExperimental || GLEW_EXT_scene_marker) CONST_CAST(GLEW_EXT_scene_marker) = !_glewInit_GL_EXT_scene_marker(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_scene_marker */
+#ifdef GL_EXT_secondary_color
+ CONST_CAST(GLEW_EXT_secondary_color) = glewGetExtension("GL_EXT_secondary_color");
+ if (glewExperimental || GLEW_EXT_secondary_color) CONST_CAST(GLEW_EXT_secondary_color) = !_glewInit_GL_EXT_secondary_color(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_secondary_color */
+#ifdef GL_EXT_separate_specular_color
+ CONST_CAST(GLEW_EXT_separate_specular_color) = glewGetExtension("GL_EXT_separate_specular_color");
+#endif /* GL_EXT_separate_specular_color */
+#ifdef GL_EXT_shadow_funcs
+ CONST_CAST(GLEW_EXT_shadow_funcs) = glewGetExtension("GL_EXT_shadow_funcs");
+#endif /* GL_EXT_shadow_funcs */
+#ifdef GL_EXT_shared_texture_palette
+ CONST_CAST(GLEW_EXT_shared_texture_palette) = glewGetExtension("GL_EXT_shared_texture_palette");
+#endif /* GL_EXT_shared_texture_palette */
+#ifdef GL_EXT_stencil_clear_tag
+ CONST_CAST(GLEW_EXT_stencil_clear_tag) = glewGetExtension("GL_EXT_stencil_clear_tag");
+#endif /* GL_EXT_stencil_clear_tag */
+#ifdef GL_EXT_stencil_two_side
+ CONST_CAST(GLEW_EXT_stencil_two_side) = glewGetExtension("GL_EXT_stencil_two_side");
+ if (glewExperimental || GLEW_EXT_stencil_two_side) CONST_CAST(GLEW_EXT_stencil_two_side) = !_glewInit_GL_EXT_stencil_two_side(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_stencil_two_side */
+#ifdef GL_EXT_stencil_wrap
+ CONST_CAST(GLEW_EXT_stencil_wrap) = glewGetExtension("GL_EXT_stencil_wrap");
+#endif /* GL_EXT_stencil_wrap */
+#ifdef GL_EXT_subtexture
+ CONST_CAST(GLEW_EXT_subtexture) = glewGetExtension("GL_EXT_subtexture");
+ if (glewExperimental || GLEW_EXT_subtexture) CONST_CAST(GLEW_EXT_subtexture) = !_glewInit_GL_EXT_subtexture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_subtexture */
+#ifdef GL_EXT_texture
+ CONST_CAST(GLEW_EXT_texture) = glewGetExtension("GL_EXT_texture");
+#endif /* GL_EXT_texture */
+#ifdef GL_EXT_texture3D
+ CONST_CAST(GLEW_EXT_texture3D) = glewGetExtension("GL_EXT_texture3D");
+ if (glewExperimental || GLEW_EXT_texture3D) CONST_CAST(GLEW_EXT_texture3D) = !_glewInit_GL_EXT_texture3D(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture3D */
+#ifdef GL_EXT_texture_array
+ CONST_CAST(GLEW_EXT_texture_array) = glewGetExtension("GL_EXT_texture_array");
+#endif /* GL_EXT_texture_array */
+#ifdef GL_EXT_texture_buffer_object
+ CONST_CAST(GLEW_EXT_texture_buffer_object) = glewGetExtension("GL_EXT_texture_buffer_object");
+ if (glewExperimental || GLEW_EXT_texture_buffer_object) CONST_CAST(GLEW_EXT_texture_buffer_object) = !_glewInit_GL_EXT_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_buffer_object */
+#ifdef GL_EXT_texture_compression_dxt1
+ CONST_CAST(GLEW_EXT_texture_compression_dxt1) = glewGetExtension("GL_EXT_texture_compression_dxt1");
+#endif /* GL_EXT_texture_compression_dxt1 */
+#ifdef GL_EXT_texture_compression_latc
+ CONST_CAST(GLEW_EXT_texture_compression_latc) = glewGetExtension("GL_EXT_texture_compression_latc");
+#endif /* GL_EXT_texture_compression_latc */
+#ifdef GL_EXT_texture_compression_rgtc
+ CONST_CAST(GLEW_EXT_texture_compression_rgtc) = glewGetExtension("GL_EXT_texture_compression_rgtc");
+#endif /* GL_EXT_texture_compression_rgtc */
+#ifdef GL_EXT_texture_compression_s3tc
+ CONST_CAST(GLEW_EXT_texture_compression_s3tc) = glewGetExtension("GL_EXT_texture_compression_s3tc");
+#endif /* GL_EXT_texture_compression_s3tc */
+#ifdef GL_EXT_texture_cube_map
+ CONST_CAST(GLEW_EXT_texture_cube_map) = glewGetExtension("GL_EXT_texture_cube_map");
+#endif /* GL_EXT_texture_cube_map */
+#ifdef GL_EXT_texture_edge_clamp
+ CONST_CAST(GLEW_EXT_texture_edge_clamp) = glewGetExtension("GL_EXT_texture_edge_clamp");
+#endif /* GL_EXT_texture_edge_clamp */
+#ifdef GL_EXT_texture_env
+ CONST_CAST(GLEW_EXT_texture_env) = glewGetExtension("GL_EXT_texture_env");
+#endif /* GL_EXT_texture_env */
+#ifdef GL_EXT_texture_env_add
+ CONST_CAST(GLEW_EXT_texture_env_add) = glewGetExtension("GL_EXT_texture_env_add");
+#endif /* GL_EXT_texture_env_add */
+#ifdef GL_EXT_texture_env_combine
+ CONST_CAST(GLEW_EXT_texture_env_combine) = glewGetExtension("GL_EXT_texture_env_combine");
+#endif /* GL_EXT_texture_env_combine */
+#ifdef GL_EXT_texture_env_dot3
+ CONST_CAST(GLEW_EXT_texture_env_dot3) = glewGetExtension("GL_EXT_texture_env_dot3");
+#endif /* GL_EXT_texture_env_dot3 */
+#ifdef GL_EXT_texture_filter_anisotropic
+ CONST_CAST(GLEW_EXT_texture_filter_anisotropic) = glewGetExtension("GL_EXT_texture_filter_anisotropic");
+#endif /* GL_EXT_texture_filter_anisotropic */
+#ifdef GL_EXT_texture_integer
+ CONST_CAST(GLEW_EXT_texture_integer) = glewGetExtension("GL_EXT_texture_integer");
+ if (glewExperimental || GLEW_EXT_texture_integer) CONST_CAST(GLEW_EXT_texture_integer) = !_glewInit_GL_EXT_texture_integer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_integer */
+#ifdef GL_EXT_texture_lod_bias
+ CONST_CAST(GLEW_EXT_texture_lod_bias) = glewGetExtension("GL_EXT_texture_lod_bias");
+#endif /* GL_EXT_texture_lod_bias */
+#ifdef GL_EXT_texture_mirror_clamp
+ CONST_CAST(GLEW_EXT_texture_mirror_clamp) = glewGetExtension("GL_EXT_texture_mirror_clamp");
+#endif /* GL_EXT_texture_mirror_clamp */
+#ifdef GL_EXT_texture_object
+ CONST_CAST(GLEW_EXT_texture_object) = glewGetExtension("GL_EXT_texture_object");
+ if (glewExperimental || GLEW_EXT_texture_object) CONST_CAST(GLEW_EXT_texture_object) = !_glewInit_GL_EXT_texture_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_object */
+#ifdef GL_EXT_texture_perturb_normal
+ CONST_CAST(GLEW_EXT_texture_perturb_normal) = glewGetExtension("GL_EXT_texture_perturb_normal");
+ if (glewExperimental || GLEW_EXT_texture_perturb_normal) CONST_CAST(GLEW_EXT_texture_perturb_normal) = !_glewInit_GL_EXT_texture_perturb_normal(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_texture_perturb_normal */
+#ifdef GL_EXT_texture_rectangle
+ CONST_CAST(GLEW_EXT_texture_rectangle) = glewGetExtension("GL_EXT_texture_rectangle");
+#endif /* GL_EXT_texture_rectangle */
+#ifdef GL_EXT_texture_sRGB
+ CONST_CAST(GLEW_EXT_texture_sRGB) = glewGetExtension("GL_EXT_texture_sRGB");
+#endif /* GL_EXT_texture_sRGB */
+#ifdef GL_EXT_texture_shared_exponent
+ CONST_CAST(GLEW_EXT_texture_shared_exponent) = glewGetExtension("GL_EXT_texture_shared_exponent");
+#endif /* GL_EXT_texture_shared_exponent */
+#ifdef GL_EXT_texture_swizzle
+ CONST_CAST(GLEW_EXT_texture_swizzle) = glewGetExtension("GL_EXT_texture_swizzle");
+#endif /* GL_EXT_texture_swizzle */
+#ifdef GL_EXT_timer_query
+ CONST_CAST(GLEW_EXT_timer_query) = glewGetExtension("GL_EXT_timer_query");
+ if (glewExperimental || GLEW_EXT_timer_query) CONST_CAST(GLEW_EXT_timer_query) = !_glewInit_GL_EXT_timer_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_timer_query */
+#ifdef GL_EXT_transform_feedback
+ CONST_CAST(GLEW_EXT_transform_feedback) = glewGetExtension("GL_EXT_transform_feedback");
+ if (glewExperimental || GLEW_EXT_transform_feedback) CONST_CAST(GLEW_EXT_transform_feedback) = !_glewInit_GL_EXT_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_transform_feedback */
+#ifdef GL_EXT_vertex_array
+ CONST_CAST(GLEW_EXT_vertex_array) = glewGetExtension("GL_EXT_vertex_array");
+ if (glewExperimental || GLEW_EXT_vertex_array) CONST_CAST(GLEW_EXT_vertex_array) = !_glewInit_GL_EXT_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_vertex_array */
+#ifdef GL_EXT_vertex_array_bgra
+ CONST_CAST(GLEW_EXT_vertex_array_bgra) = glewGetExtension("GL_EXT_vertex_array_bgra");
+#endif /* GL_EXT_vertex_array_bgra */
+#ifdef GL_EXT_vertex_shader
+ CONST_CAST(GLEW_EXT_vertex_shader) = glewGetExtension("GL_EXT_vertex_shader");
+ if (glewExperimental || GLEW_EXT_vertex_shader) CONST_CAST(GLEW_EXT_vertex_shader) = !_glewInit_GL_EXT_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_vertex_shader */
+#ifdef GL_EXT_vertex_weighting
+ CONST_CAST(GLEW_EXT_vertex_weighting) = glewGetExtension("GL_EXT_vertex_weighting");
+ if (glewExperimental || GLEW_EXT_vertex_weighting) CONST_CAST(GLEW_EXT_vertex_weighting) = !_glewInit_GL_EXT_vertex_weighting(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_EXT_vertex_weighting */
+#ifdef GL_GREMEDY_frame_terminator
+ CONST_CAST(GLEW_GREMEDY_frame_terminator) = glewGetExtension("GL_GREMEDY_frame_terminator");
+ if (glewExperimental || GLEW_GREMEDY_frame_terminator) CONST_CAST(GLEW_GREMEDY_frame_terminator) = !_glewInit_GL_GREMEDY_frame_terminator(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_GREMEDY_frame_terminator */
+#ifdef GL_GREMEDY_string_marker
+ CONST_CAST(GLEW_GREMEDY_string_marker) = glewGetExtension("GL_GREMEDY_string_marker");
+ if (glewExperimental || GLEW_GREMEDY_string_marker) CONST_CAST(GLEW_GREMEDY_string_marker) = !_glewInit_GL_GREMEDY_string_marker(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_GREMEDY_string_marker */
+#ifdef GL_HP_convolution_border_modes
+ CONST_CAST(GLEW_HP_convolution_border_modes) = glewGetExtension("GL_HP_convolution_border_modes");
+#endif /* GL_HP_convolution_border_modes */
+#ifdef GL_HP_image_transform
+ CONST_CAST(GLEW_HP_image_transform) = glewGetExtension("GL_HP_image_transform");
+ if (glewExperimental || GLEW_HP_image_transform) CONST_CAST(GLEW_HP_image_transform) = !_glewInit_GL_HP_image_transform(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_HP_image_transform */
+#ifdef GL_HP_occlusion_test
+ CONST_CAST(GLEW_HP_occlusion_test) = glewGetExtension("GL_HP_occlusion_test");
+#endif /* GL_HP_occlusion_test */
+#ifdef GL_HP_texture_lighting
+ CONST_CAST(GLEW_HP_texture_lighting) = glewGetExtension("GL_HP_texture_lighting");
+#endif /* GL_HP_texture_lighting */
+#ifdef GL_IBM_cull_vertex
+ CONST_CAST(GLEW_IBM_cull_vertex) = glewGetExtension("GL_IBM_cull_vertex");
+#endif /* GL_IBM_cull_vertex */
+#ifdef GL_IBM_multimode_draw_arrays
+ CONST_CAST(GLEW_IBM_multimode_draw_arrays) = glewGetExtension("GL_IBM_multimode_draw_arrays");
+ if (glewExperimental || GLEW_IBM_multimode_draw_arrays) CONST_CAST(GLEW_IBM_multimode_draw_arrays) = !_glewInit_GL_IBM_multimode_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_IBM_multimode_draw_arrays */
+#ifdef GL_IBM_rasterpos_clip
+ CONST_CAST(GLEW_IBM_rasterpos_clip) = glewGetExtension("GL_IBM_rasterpos_clip");
+#endif /* GL_IBM_rasterpos_clip */
+#ifdef GL_IBM_static_data
+ CONST_CAST(GLEW_IBM_static_data) = glewGetExtension("GL_IBM_static_data");
+#endif /* GL_IBM_static_data */
+#ifdef GL_IBM_texture_mirrored_repeat
+ CONST_CAST(GLEW_IBM_texture_mirrored_repeat) = glewGetExtension("GL_IBM_texture_mirrored_repeat");
+#endif /* GL_IBM_texture_mirrored_repeat */
+#ifdef GL_IBM_vertex_array_lists
+ CONST_CAST(GLEW_IBM_vertex_array_lists) = glewGetExtension("GL_IBM_vertex_array_lists");
+ if (glewExperimental || GLEW_IBM_vertex_array_lists) CONST_CAST(GLEW_IBM_vertex_array_lists) = !_glewInit_GL_IBM_vertex_array_lists(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_IBM_vertex_array_lists */
+#ifdef GL_INGR_color_clamp
+ CONST_CAST(GLEW_INGR_color_clamp) = glewGetExtension("GL_INGR_color_clamp");
+#endif /* GL_INGR_color_clamp */
+#ifdef GL_INGR_interlace_read
+ CONST_CAST(GLEW_INGR_interlace_read) = glewGetExtension("GL_INGR_interlace_read");
+#endif /* GL_INGR_interlace_read */
+#ifdef GL_INTEL_parallel_arrays
+ CONST_CAST(GLEW_INTEL_parallel_arrays) = glewGetExtension("GL_INTEL_parallel_arrays");
+ if (glewExperimental || GLEW_INTEL_parallel_arrays) CONST_CAST(GLEW_INTEL_parallel_arrays) = !_glewInit_GL_INTEL_parallel_arrays(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_INTEL_parallel_arrays */
+#ifdef GL_INTEL_texture_scissor
+ CONST_CAST(GLEW_INTEL_texture_scissor) = glewGetExtension("GL_INTEL_texture_scissor");
+ if (glewExperimental || GLEW_INTEL_texture_scissor) CONST_CAST(GLEW_INTEL_texture_scissor) = !_glewInit_GL_INTEL_texture_scissor(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_INTEL_texture_scissor */
+#ifdef GL_KTX_buffer_region
+ CONST_CAST(GLEW_KTX_buffer_region) = glewGetExtension("GL_KTX_buffer_region");
+ if (glewExperimental || GLEW_KTX_buffer_region) CONST_CAST(GLEW_KTX_buffer_region) = !_glewInit_GL_KTX_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_KTX_buffer_region */
+#ifdef GL_MESAX_texture_stack
+ CONST_CAST(GLEW_MESAX_texture_stack) = glewGetExtension("GL_MESAX_texture_stack");
+#endif /* GL_MESAX_texture_stack */
+#ifdef GL_MESA_pack_invert
+ CONST_CAST(GLEW_MESA_pack_invert) = glewGetExtension("GL_MESA_pack_invert");
+#endif /* GL_MESA_pack_invert */
+#ifdef GL_MESA_resize_buffers
+ CONST_CAST(GLEW_MESA_resize_buffers) = glewGetExtension("GL_MESA_resize_buffers");
+ if (glewExperimental || GLEW_MESA_resize_buffers) CONST_CAST(GLEW_MESA_resize_buffers) = !_glewInit_GL_MESA_resize_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_MESA_resize_buffers */
+#ifdef GL_MESA_window_pos
+ CONST_CAST(GLEW_MESA_window_pos) = glewGetExtension("GL_MESA_window_pos");
+ if (glewExperimental || GLEW_MESA_window_pos) CONST_CAST(GLEW_MESA_window_pos) = !_glewInit_GL_MESA_window_pos(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_MESA_window_pos */
+#ifdef GL_MESA_ycbcr_texture
+ CONST_CAST(GLEW_MESA_ycbcr_texture) = glewGetExtension("GL_MESA_ycbcr_texture");
+#endif /* GL_MESA_ycbcr_texture */
+#ifdef GL_NV_blend_square
+ CONST_CAST(GLEW_NV_blend_square) = glewGetExtension("GL_NV_blend_square");
+#endif /* GL_NV_blend_square */
+#ifdef GL_NV_conditional_render
+ CONST_CAST(GLEW_NV_conditional_render) = glewGetExtension("GL_NV_conditional_render");
+ if (glewExperimental || GLEW_NV_conditional_render) CONST_CAST(GLEW_NV_conditional_render) = !_glewInit_GL_NV_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_conditional_render */
+#ifdef GL_NV_copy_depth_to_color
+ CONST_CAST(GLEW_NV_copy_depth_to_color) = glewGetExtension("GL_NV_copy_depth_to_color");
+#endif /* GL_NV_copy_depth_to_color */
+#ifdef GL_NV_depth_buffer_float
+ CONST_CAST(GLEW_NV_depth_buffer_float) = glewGetExtension("GL_NV_depth_buffer_float");
+ if (glewExperimental || GLEW_NV_depth_buffer_float) CONST_CAST(GLEW_NV_depth_buffer_float) = !_glewInit_GL_NV_depth_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_depth_buffer_float */
+#ifdef GL_NV_depth_clamp
+ CONST_CAST(GLEW_NV_depth_clamp) = glewGetExtension("GL_NV_depth_clamp");
+#endif /* GL_NV_depth_clamp */
+#ifdef GL_NV_depth_range_unclamped
+ CONST_CAST(GLEW_NV_depth_range_unclamped) = glewGetExtension("GL_NV_depth_range_unclamped");
+#endif /* GL_NV_depth_range_unclamped */
+#ifdef GL_NV_evaluators
+ CONST_CAST(GLEW_NV_evaluators) = glewGetExtension("GL_NV_evaluators");
+ if (glewExperimental || GLEW_NV_evaluators) CONST_CAST(GLEW_NV_evaluators) = !_glewInit_GL_NV_evaluators(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_evaluators */
+#ifdef GL_NV_explicit_multisample
+ CONST_CAST(GLEW_NV_explicit_multisample) = glewGetExtension("GL_NV_explicit_multisample");
+ if (glewExperimental || GLEW_NV_explicit_multisample) CONST_CAST(GLEW_NV_explicit_multisample) = !_glewInit_GL_NV_explicit_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_explicit_multisample */
+#ifdef GL_NV_fence
+ CONST_CAST(GLEW_NV_fence) = glewGetExtension("GL_NV_fence");
+ if (glewExperimental || GLEW_NV_fence) CONST_CAST(GLEW_NV_fence) = !_glewInit_GL_NV_fence(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_fence */
+#ifdef GL_NV_float_buffer
+ CONST_CAST(GLEW_NV_float_buffer) = glewGetExtension("GL_NV_float_buffer");
+#endif /* GL_NV_float_buffer */
+#ifdef GL_NV_fog_distance
+ CONST_CAST(GLEW_NV_fog_distance) = glewGetExtension("GL_NV_fog_distance");
+#endif /* GL_NV_fog_distance */
+#ifdef GL_NV_fragment_program
+ CONST_CAST(GLEW_NV_fragment_program) = glewGetExtension("GL_NV_fragment_program");
+ if (glewExperimental || GLEW_NV_fragment_program) CONST_CAST(GLEW_NV_fragment_program) = !_glewInit_GL_NV_fragment_program(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_fragment_program */
+#ifdef GL_NV_fragment_program2
+ CONST_CAST(GLEW_NV_fragment_program2) = glewGetExtension("GL_NV_fragment_program2");
+#endif /* GL_NV_fragment_program2 */
+#ifdef GL_NV_fragment_program4
+ CONST_CAST(GLEW_NV_fragment_program4) = glewGetExtension("GL_NV_fragment_program4");
+#endif /* GL_NV_fragment_program4 */
+#ifdef GL_NV_fragment_program_option
+ CONST_CAST(GLEW_NV_fragment_program_option) = glewGetExtension("GL_NV_fragment_program_option");
+#endif /* GL_NV_fragment_program_option */
+#ifdef GL_NV_framebuffer_multisample_coverage
+ CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = glewGetExtension("GL_NV_framebuffer_multisample_coverage");
+ if (glewExperimental || GLEW_NV_framebuffer_multisample_coverage) CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = !_glewInit_GL_NV_framebuffer_multisample_coverage(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_framebuffer_multisample_coverage */
+#ifdef GL_NV_geometry_program4
+ CONST_CAST(GLEW_NV_geometry_program4) = glewGetExtension("GL_NV_geometry_program4");
+ if (glewExperimental || GLEW_NV_geometry_program4) CONST_CAST(GLEW_NV_geometry_program4) = !_glewInit_GL_NV_geometry_program4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_geometry_program4 */
+#ifdef GL_NV_geometry_shader4
+ CONST_CAST(GLEW_NV_geometry_shader4) = glewGetExtension("GL_NV_geometry_shader4");
+#endif /* GL_NV_geometry_shader4 */
+#ifdef GL_NV_gpu_program4
+ CONST_CAST(GLEW_NV_gpu_program4) = glewGetExtension("GL_NV_gpu_program4");
+ if (glewExperimental || GLEW_NV_gpu_program4) CONST_CAST(GLEW_NV_gpu_program4) = !_glewInit_GL_NV_gpu_program4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_gpu_program4 */
+#ifdef GL_NV_half_float
+ CONST_CAST(GLEW_NV_half_float) = glewGetExtension("GL_NV_half_float");
+ if (glewExperimental || GLEW_NV_half_float) CONST_CAST(GLEW_NV_half_float) = !_glewInit_GL_NV_half_float(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_half_float */
+#ifdef GL_NV_light_max_exponent
+ CONST_CAST(GLEW_NV_light_max_exponent) = glewGetExtension("GL_NV_light_max_exponent");
+#endif /* GL_NV_light_max_exponent */
+#ifdef GL_NV_multisample_filter_hint
+ CONST_CAST(GLEW_NV_multisample_filter_hint) = glewGetExtension("GL_NV_multisample_filter_hint");
+#endif /* GL_NV_multisample_filter_hint */
+#ifdef GL_NV_occlusion_query
+ CONST_CAST(GLEW_NV_occlusion_query) = glewGetExtension("GL_NV_occlusion_query");
+ if (glewExperimental || GLEW_NV_occlusion_query) CONST_CAST(GLEW_NV_occlusion_query) = !_glewInit_GL_NV_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_occlusion_query */
+#ifdef GL_NV_packed_depth_stencil
+ CONST_CAST(GLEW_NV_packed_depth_stencil) = glewGetExtension("GL_NV_packed_depth_stencil");
+#endif /* GL_NV_packed_depth_stencil */
+#ifdef GL_NV_parameter_buffer_object
+ CONST_CAST(GLEW_NV_parameter_buffer_object) = glewGetExtension("GL_NV_parameter_buffer_object");
+ if (glewExperimental || GLEW_NV_parameter_buffer_object) CONST_CAST(GLEW_NV_parameter_buffer_object) = !_glewInit_GL_NV_parameter_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_parameter_buffer_object */
+#ifdef GL_NV_pixel_data_range
+ CONST_CAST(GLEW_NV_pixel_data_range) = glewGetExtension("GL_NV_pixel_data_range");
+ if (glewExperimental || GLEW_NV_pixel_data_range) CONST_CAST(GLEW_NV_pixel_data_range) = !_glewInit_GL_NV_pixel_data_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_pixel_data_range */
+#ifdef GL_NV_point_sprite
+ CONST_CAST(GLEW_NV_point_sprite) = glewGetExtension("GL_NV_point_sprite");
+ if (glewExperimental || GLEW_NV_point_sprite) CONST_CAST(GLEW_NV_point_sprite) = !_glewInit_GL_NV_point_sprite(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_point_sprite */
+#ifdef GL_NV_present_video
+ CONST_CAST(GLEW_NV_present_video) = glewGetExtension("GL_NV_present_video");
+ if (glewExperimental || GLEW_NV_present_video) CONST_CAST(GLEW_NV_present_video) = !_glewInit_GL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_present_video */
+#ifdef GL_NV_primitive_restart
+ CONST_CAST(GLEW_NV_primitive_restart) = glewGetExtension("GL_NV_primitive_restart");
+ if (glewExperimental || GLEW_NV_primitive_restart) CONST_CAST(GLEW_NV_primitive_restart) = !_glewInit_GL_NV_primitive_restart(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_primitive_restart */
+#ifdef GL_NV_register_combiners
+ CONST_CAST(GLEW_NV_register_combiners) = glewGetExtension("GL_NV_register_combiners");
+ if (glewExperimental || GLEW_NV_register_combiners) CONST_CAST(GLEW_NV_register_combiners) = !_glewInit_GL_NV_register_combiners(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_register_combiners */
+#ifdef GL_NV_register_combiners2
+ CONST_CAST(GLEW_NV_register_combiners2) = glewGetExtension("GL_NV_register_combiners2");
+ if (glewExperimental || GLEW_NV_register_combiners2) CONST_CAST(GLEW_NV_register_combiners2) = !_glewInit_GL_NV_register_combiners2(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_register_combiners2 */
+#ifdef GL_NV_texgen_emboss
+ CONST_CAST(GLEW_NV_texgen_emboss) = glewGetExtension("GL_NV_texgen_emboss");
+#endif /* GL_NV_texgen_emboss */
+#ifdef GL_NV_texgen_reflection
+ CONST_CAST(GLEW_NV_texgen_reflection) = glewGetExtension("GL_NV_texgen_reflection");
+#endif /* GL_NV_texgen_reflection */
+#ifdef GL_NV_texture_compression_vtc
+ CONST_CAST(GLEW_NV_texture_compression_vtc) = glewGetExtension("GL_NV_texture_compression_vtc");
+#endif /* GL_NV_texture_compression_vtc */
+#ifdef GL_NV_texture_env_combine4
+ CONST_CAST(GLEW_NV_texture_env_combine4) = glewGetExtension("GL_NV_texture_env_combine4");
+#endif /* GL_NV_texture_env_combine4 */
+#ifdef GL_NV_texture_expand_normal
+ CONST_CAST(GLEW_NV_texture_expand_normal) = glewGetExtension("GL_NV_texture_expand_normal");
+#endif /* GL_NV_texture_expand_normal */
+#ifdef GL_NV_texture_rectangle
+ CONST_CAST(GLEW_NV_texture_rectangle) = glewGetExtension("GL_NV_texture_rectangle");
+#endif /* GL_NV_texture_rectangle */
+#ifdef GL_NV_texture_shader
+ CONST_CAST(GLEW_NV_texture_shader) = glewGetExtension("GL_NV_texture_shader");
+#endif /* GL_NV_texture_shader */
+#ifdef GL_NV_texture_shader2
+ CONST_CAST(GLEW_NV_texture_shader2) = glewGetExtension("GL_NV_texture_shader2");
+#endif /* GL_NV_texture_shader2 */
+#ifdef GL_NV_texture_shader3
+ CONST_CAST(GLEW_NV_texture_shader3) = glewGetExtension("GL_NV_texture_shader3");
+#endif /* GL_NV_texture_shader3 */
+#ifdef GL_NV_transform_feedback
+ CONST_CAST(GLEW_NV_transform_feedback) = glewGetExtension("GL_NV_transform_feedback");
+ if (glewExperimental || GLEW_NV_transform_feedback) CONST_CAST(GLEW_NV_transform_feedback) = !_glewInit_GL_NV_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_transform_feedback */
+#ifdef GL_NV_vertex_array_range
+ CONST_CAST(GLEW_NV_vertex_array_range) = glewGetExtension("GL_NV_vertex_array_range");
+ if (glewExperimental || GLEW_NV_vertex_array_range) CONST_CAST(GLEW_NV_vertex_array_range) = !_glewInit_GL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_vertex_array_range */
+#ifdef GL_NV_vertex_array_range2
+ CONST_CAST(GLEW_NV_vertex_array_range2) = glewGetExtension("GL_NV_vertex_array_range2");
+#endif /* GL_NV_vertex_array_range2 */
+#ifdef GL_NV_vertex_program
+ CONST_CAST(GLEW_NV_vertex_program) = glewGetExtension("GL_NV_vertex_program");
+ if (glewExperimental || GLEW_NV_vertex_program) CONST_CAST(GLEW_NV_vertex_program) = !_glewInit_GL_NV_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_NV_vertex_program */
+#ifdef GL_NV_vertex_program1_1
+ CONST_CAST(GLEW_NV_vertex_program1_1) = glewGetExtension("GL_NV_vertex_program1_1");
+#endif /* GL_NV_vertex_program1_1 */
+#ifdef GL_NV_vertex_program2
+ CONST_CAST(GLEW_NV_vertex_program2) = glewGetExtension("GL_NV_vertex_program2");
+#endif /* GL_NV_vertex_program2 */
+#ifdef GL_NV_vertex_program2_option
+ CONST_CAST(GLEW_NV_vertex_program2_option) = glewGetExtension("GL_NV_vertex_program2_option");
+#endif /* GL_NV_vertex_program2_option */
+#ifdef GL_NV_vertex_program3
+ CONST_CAST(GLEW_NV_vertex_program3) = glewGetExtension("GL_NV_vertex_program3");
+#endif /* GL_NV_vertex_program3 */
+#ifdef GL_NV_vertex_program4
+ CONST_CAST(GLEW_NV_vertex_program4) = glewGetExtension("GL_NV_vertex_program4");
+#endif /* GL_NV_vertex_program4 */
+#ifdef GL_OES_byte_coordinates
+ CONST_CAST(GLEW_OES_byte_coordinates) = glewGetExtension("GL_OES_byte_coordinates");
+#endif /* GL_OES_byte_coordinates */
+#ifdef GL_OES_compressed_paletted_texture
+ CONST_CAST(GLEW_OES_compressed_paletted_texture) = glewGetExtension("GL_OES_compressed_paletted_texture");
+#endif /* GL_OES_compressed_paletted_texture */
+#ifdef GL_OES_read_format
+ CONST_CAST(GLEW_OES_read_format) = glewGetExtension("GL_OES_read_format");
+#endif /* GL_OES_read_format */
+#ifdef GL_OES_single_precision
+ CONST_CAST(GLEW_OES_single_precision) = glewGetExtension("GL_OES_single_precision");
+ if (glewExperimental || GLEW_OES_single_precision) CONST_CAST(GLEW_OES_single_precision) = !_glewInit_GL_OES_single_precision(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_OES_single_precision */
+#ifdef GL_OML_interlace
+ CONST_CAST(GLEW_OML_interlace) = glewGetExtension("GL_OML_interlace");
+#endif /* GL_OML_interlace */
+#ifdef GL_OML_resample
+ CONST_CAST(GLEW_OML_resample) = glewGetExtension("GL_OML_resample");
+#endif /* GL_OML_resample */
+#ifdef GL_OML_subsample
+ CONST_CAST(GLEW_OML_subsample) = glewGetExtension("GL_OML_subsample");
+#endif /* GL_OML_subsample */
+#ifdef GL_PGI_misc_hints
+ CONST_CAST(GLEW_PGI_misc_hints) = glewGetExtension("GL_PGI_misc_hints");
+#endif /* GL_PGI_misc_hints */
+#ifdef GL_PGI_vertex_hints
+ CONST_CAST(GLEW_PGI_vertex_hints) = glewGetExtension("GL_PGI_vertex_hints");
+#endif /* GL_PGI_vertex_hints */
+#ifdef GL_REND_screen_coordinates
+ CONST_CAST(GLEW_REND_screen_coordinates) = glewGetExtension("GL_REND_screen_coordinates");
+#endif /* GL_REND_screen_coordinates */
+#ifdef GL_S3_s3tc
+ CONST_CAST(GLEW_S3_s3tc) = glewGetExtension("GL_S3_s3tc");
+#endif /* GL_S3_s3tc */
+#ifdef GL_SGIS_color_range
+ CONST_CAST(GLEW_SGIS_color_range) = glewGetExtension("GL_SGIS_color_range");
+#endif /* GL_SGIS_color_range */
+#ifdef GL_SGIS_detail_texture
+ CONST_CAST(GLEW_SGIS_detail_texture) = glewGetExtension("GL_SGIS_detail_texture");
+ if (glewExperimental || GLEW_SGIS_detail_texture) CONST_CAST(GLEW_SGIS_detail_texture) = !_glewInit_GL_SGIS_detail_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_detail_texture */
+#ifdef GL_SGIS_fog_function
+ CONST_CAST(GLEW_SGIS_fog_function) = glewGetExtension("GL_SGIS_fog_function");
+ if (glewExperimental || GLEW_SGIS_fog_function) CONST_CAST(GLEW_SGIS_fog_function) = !_glewInit_GL_SGIS_fog_function(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_fog_function */
+#ifdef GL_SGIS_generate_mipmap
+ CONST_CAST(GLEW_SGIS_generate_mipmap) = glewGetExtension("GL_SGIS_generate_mipmap");
+#endif /* GL_SGIS_generate_mipmap */
+#ifdef GL_SGIS_multisample
+ CONST_CAST(GLEW_SGIS_multisample) = glewGetExtension("GL_SGIS_multisample");
+ if (glewExperimental || GLEW_SGIS_multisample) CONST_CAST(GLEW_SGIS_multisample) = !_glewInit_GL_SGIS_multisample(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_multisample */
+#ifdef GL_SGIS_pixel_texture
+ CONST_CAST(GLEW_SGIS_pixel_texture) = glewGetExtension("GL_SGIS_pixel_texture");
+#endif /* GL_SGIS_pixel_texture */
+#ifdef GL_SGIS_point_line_texgen
+ CONST_CAST(GLEW_SGIS_point_line_texgen) = glewGetExtension("GL_SGIS_point_line_texgen");
+#endif /* GL_SGIS_point_line_texgen */
+#ifdef GL_SGIS_sharpen_texture
+ CONST_CAST(GLEW_SGIS_sharpen_texture) = glewGetExtension("GL_SGIS_sharpen_texture");
+ if (glewExperimental || GLEW_SGIS_sharpen_texture) CONST_CAST(GLEW_SGIS_sharpen_texture) = !_glewInit_GL_SGIS_sharpen_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_sharpen_texture */
+#ifdef GL_SGIS_texture4D
+ CONST_CAST(GLEW_SGIS_texture4D) = glewGetExtension("GL_SGIS_texture4D");
+ if (glewExperimental || GLEW_SGIS_texture4D) CONST_CAST(GLEW_SGIS_texture4D) = !_glewInit_GL_SGIS_texture4D(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_texture4D */
+#ifdef GL_SGIS_texture_border_clamp
+ CONST_CAST(GLEW_SGIS_texture_border_clamp) = glewGetExtension("GL_SGIS_texture_border_clamp");
+#endif /* GL_SGIS_texture_border_clamp */
+#ifdef GL_SGIS_texture_edge_clamp
+ CONST_CAST(GLEW_SGIS_texture_edge_clamp) = glewGetExtension("GL_SGIS_texture_edge_clamp");
+#endif /* GL_SGIS_texture_edge_clamp */
+#ifdef GL_SGIS_texture_filter4
+ CONST_CAST(GLEW_SGIS_texture_filter4) = glewGetExtension("GL_SGIS_texture_filter4");
+ if (glewExperimental || GLEW_SGIS_texture_filter4) CONST_CAST(GLEW_SGIS_texture_filter4) = !_glewInit_GL_SGIS_texture_filter4(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIS_texture_filter4 */
+#ifdef GL_SGIS_texture_lod
+ CONST_CAST(GLEW_SGIS_texture_lod) = glewGetExtension("GL_SGIS_texture_lod");
+#endif /* GL_SGIS_texture_lod */
+#ifdef GL_SGIS_texture_select
+ CONST_CAST(GLEW_SGIS_texture_select) = glewGetExtension("GL_SGIS_texture_select");
+#endif /* GL_SGIS_texture_select */
+#ifdef GL_SGIX_async
+ CONST_CAST(GLEW_SGIX_async) = glewGetExtension("GL_SGIX_async");
+ if (glewExperimental || GLEW_SGIX_async) CONST_CAST(GLEW_SGIX_async) = !_glewInit_GL_SGIX_async(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_async */
+#ifdef GL_SGIX_async_histogram
+ CONST_CAST(GLEW_SGIX_async_histogram) = glewGetExtension("GL_SGIX_async_histogram");
+#endif /* GL_SGIX_async_histogram */
+#ifdef GL_SGIX_async_pixel
+ CONST_CAST(GLEW_SGIX_async_pixel) = glewGetExtension("GL_SGIX_async_pixel");
+#endif /* GL_SGIX_async_pixel */
+#ifdef GL_SGIX_blend_alpha_minmax
+ CONST_CAST(GLEW_SGIX_blend_alpha_minmax) = glewGetExtension("GL_SGIX_blend_alpha_minmax");
+#endif /* GL_SGIX_blend_alpha_minmax */
+#ifdef GL_SGIX_clipmap
+ CONST_CAST(GLEW_SGIX_clipmap) = glewGetExtension("GL_SGIX_clipmap");
+#endif /* GL_SGIX_clipmap */
+#ifdef GL_SGIX_convolution_accuracy
+ CONST_CAST(GLEW_SGIX_convolution_accuracy) = glewGetExtension("GL_SGIX_convolution_accuracy");
+#endif /* GL_SGIX_convolution_accuracy */
+#ifdef GL_SGIX_depth_texture
+ CONST_CAST(GLEW_SGIX_depth_texture) = glewGetExtension("GL_SGIX_depth_texture");
+#endif /* GL_SGIX_depth_texture */
+#ifdef GL_SGIX_flush_raster
+ CONST_CAST(GLEW_SGIX_flush_raster) = glewGetExtension("GL_SGIX_flush_raster");
+ if (glewExperimental || GLEW_SGIX_flush_raster) CONST_CAST(GLEW_SGIX_flush_raster) = !_glewInit_GL_SGIX_flush_raster(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_flush_raster */
+#ifdef GL_SGIX_fog_offset
+ CONST_CAST(GLEW_SGIX_fog_offset) = glewGetExtension("GL_SGIX_fog_offset");
+#endif /* GL_SGIX_fog_offset */
+#ifdef GL_SGIX_fog_texture
+ CONST_CAST(GLEW_SGIX_fog_texture) = glewGetExtension("GL_SGIX_fog_texture");
+ if (glewExperimental || GLEW_SGIX_fog_texture) CONST_CAST(GLEW_SGIX_fog_texture) = !_glewInit_GL_SGIX_fog_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_fog_texture */
+#ifdef GL_SGIX_fragment_specular_lighting
+ CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = glewGetExtension("GL_SGIX_fragment_specular_lighting");
+ if (glewExperimental || GLEW_SGIX_fragment_specular_lighting) CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = !_glewInit_GL_SGIX_fragment_specular_lighting(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_fragment_specular_lighting */
+#ifdef GL_SGIX_framezoom
+ CONST_CAST(GLEW_SGIX_framezoom) = glewGetExtension("GL_SGIX_framezoom");
+ if (glewExperimental || GLEW_SGIX_framezoom) CONST_CAST(GLEW_SGIX_framezoom) = !_glewInit_GL_SGIX_framezoom(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_framezoom */
+#ifdef GL_SGIX_interlace
+ CONST_CAST(GLEW_SGIX_interlace) = glewGetExtension("GL_SGIX_interlace");
+#endif /* GL_SGIX_interlace */
+#ifdef GL_SGIX_ir_instrument1
+ CONST_CAST(GLEW_SGIX_ir_instrument1) = glewGetExtension("GL_SGIX_ir_instrument1");
+#endif /* GL_SGIX_ir_instrument1 */
+#ifdef GL_SGIX_list_priority
+ CONST_CAST(GLEW_SGIX_list_priority) = glewGetExtension("GL_SGIX_list_priority");
+#endif /* GL_SGIX_list_priority */
+#ifdef GL_SGIX_pixel_texture
+ CONST_CAST(GLEW_SGIX_pixel_texture) = glewGetExtension("GL_SGIX_pixel_texture");
+ if (glewExperimental || GLEW_SGIX_pixel_texture) CONST_CAST(GLEW_SGIX_pixel_texture) = !_glewInit_GL_SGIX_pixel_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_pixel_texture */
+#ifdef GL_SGIX_pixel_texture_bits
+ CONST_CAST(GLEW_SGIX_pixel_texture_bits) = glewGetExtension("GL_SGIX_pixel_texture_bits");
+#endif /* GL_SGIX_pixel_texture_bits */
+#ifdef GL_SGIX_reference_plane
+ CONST_CAST(GLEW_SGIX_reference_plane) = glewGetExtension("GL_SGIX_reference_plane");
+ if (glewExperimental || GLEW_SGIX_reference_plane) CONST_CAST(GLEW_SGIX_reference_plane) = !_glewInit_GL_SGIX_reference_plane(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_reference_plane */
+#ifdef GL_SGIX_resample
+ CONST_CAST(GLEW_SGIX_resample) = glewGetExtension("GL_SGIX_resample");
+#endif /* GL_SGIX_resample */
+#ifdef GL_SGIX_shadow
+ CONST_CAST(GLEW_SGIX_shadow) = glewGetExtension("GL_SGIX_shadow");
+#endif /* GL_SGIX_shadow */
+#ifdef GL_SGIX_shadow_ambient
+ CONST_CAST(GLEW_SGIX_shadow_ambient) = glewGetExtension("GL_SGIX_shadow_ambient");
+#endif /* GL_SGIX_shadow_ambient */
+#ifdef GL_SGIX_sprite
+ CONST_CAST(GLEW_SGIX_sprite) = glewGetExtension("GL_SGIX_sprite");
+ if (glewExperimental || GLEW_SGIX_sprite) CONST_CAST(GLEW_SGIX_sprite) = !_glewInit_GL_SGIX_sprite(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_sprite */
+#ifdef GL_SGIX_tag_sample_buffer
+ CONST_CAST(GLEW_SGIX_tag_sample_buffer) = glewGetExtension("GL_SGIX_tag_sample_buffer");
+ if (glewExperimental || GLEW_SGIX_tag_sample_buffer) CONST_CAST(GLEW_SGIX_tag_sample_buffer) = !_glewInit_GL_SGIX_tag_sample_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGIX_tag_sample_buffer */
+#ifdef GL_SGIX_texture_add_env
+ CONST_CAST(GLEW_SGIX_texture_add_env) = glewGetExtension("GL_SGIX_texture_add_env");
+#endif /* GL_SGIX_texture_add_env */
+#ifdef GL_SGIX_texture_coordinate_clamp
+ CONST_CAST(GLEW_SGIX_texture_coordinate_clamp) = glewGetExtension("GL_SGIX_texture_coordinate_clamp");
+#endif /* GL_SGIX_texture_coordinate_clamp */
+#ifdef GL_SGIX_texture_lod_bias
+ CONST_CAST(GLEW_SGIX_texture_lod_bias) = glewGetExtension("GL_SGIX_texture_lod_bias");
+#endif /* GL_SGIX_texture_lod_bias */
+#ifdef GL_SGIX_texture_multi_buffer
+ CONST_CAST(GLEW_SGIX_texture_multi_buffer) = glewGetExtension("GL_SGIX_texture_multi_buffer");
+#endif /* GL_SGIX_texture_multi_buffer */
+#ifdef GL_SGIX_texture_range
+ CONST_CAST(GLEW_SGIX_texture_range) = glewGetExtension("GL_SGIX_texture_range");
+#endif /* GL_SGIX_texture_range */
+#ifdef GL_SGIX_texture_scale_bias
+ CONST_CAST(GLEW_SGIX_texture_scale_bias) = glewGetExtension("GL_SGIX_texture_scale_bias");
+#endif /* GL_SGIX_texture_scale_bias */
+#ifdef GL_SGIX_vertex_preclip
+ CONST_CAST(GLEW_SGIX_vertex_preclip) = glewGetExtension("GL_SGIX_vertex_preclip");
+#endif /* GL_SGIX_vertex_preclip */
+#ifdef GL_SGIX_vertex_preclip_hint
+ CONST_CAST(GLEW_SGIX_vertex_preclip_hint) = glewGetExtension("GL_SGIX_vertex_preclip_hint");
+#endif /* GL_SGIX_vertex_preclip_hint */
+#ifdef GL_SGIX_ycrcb
+ CONST_CAST(GLEW_SGIX_ycrcb) = glewGetExtension("GL_SGIX_ycrcb");
+#endif /* GL_SGIX_ycrcb */
+#ifdef GL_SGI_color_matrix
+ CONST_CAST(GLEW_SGI_color_matrix) = glewGetExtension("GL_SGI_color_matrix");
+#endif /* GL_SGI_color_matrix */
+#ifdef GL_SGI_color_table
+ CONST_CAST(GLEW_SGI_color_table) = glewGetExtension("GL_SGI_color_table");
+ if (glewExperimental || GLEW_SGI_color_table) CONST_CAST(GLEW_SGI_color_table) = !_glewInit_GL_SGI_color_table(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SGI_color_table */
+#ifdef GL_SGI_texture_color_table
+ CONST_CAST(GLEW_SGI_texture_color_table) = glewGetExtension("GL_SGI_texture_color_table");
+#endif /* GL_SGI_texture_color_table */
+#ifdef GL_SUNX_constant_data
+ CONST_CAST(GLEW_SUNX_constant_data) = glewGetExtension("GL_SUNX_constant_data");
+ if (glewExperimental || GLEW_SUNX_constant_data) CONST_CAST(GLEW_SUNX_constant_data) = !_glewInit_GL_SUNX_constant_data(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUNX_constant_data */
+#ifdef GL_SUN_convolution_border_modes
+ CONST_CAST(GLEW_SUN_convolution_border_modes) = glewGetExtension("GL_SUN_convolution_border_modes");
+#endif /* GL_SUN_convolution_border_modes */
+#ifdef GL_SUN_global_alpha
+ CONST_CAST(GLEW_SUN_global_alpha) = glewGetExtension("GL_SUN_global_alpha");
+ if (glewExperimental || GLEW_SUN_global_alpha) CONST_CAST(GLEW_SUN_global_alpha) = !_glewInit_GL_SUN_global_alpha(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUN_global_alpha */
+#ifdef GL_SUN_mesh_array
+ CONST_CAST(GLEW_SUN_mesh_array) = glewGetExtension("GL_SUN_mesh_array");
+#endif /* GL_SUN_mesh_array */
+#ifdef GL_SUN_read_video_pixels
+ CONST_CAST(GLEW_SUN_read_video_pixels) = glewGetExtension("GL_SUN_read_video_pixels");
+ if (glewExperimental || GLEW_SUN_read_video_pixels) CONST_CAST(GLEW_SUN_read_video_pixels) = !_glewInit_GL_SUN_read_video_pixels(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUN_read_video_pixels */
+#ifdef GL_SUN_slice_accum
+ CONST_CAST(GLEW_SUN_slice_accum) = glewGetExtension("GL_SUN_slice_accum");
+#endif /* GL_SUN_slice_accum */
+#ifdef GL_SUN_triangle_list
+ CONST_CAST(GLEW_SUN_triangle_list) = glewGetExtension("GL_SUN_triangle_list");
+ if (glewExperimental || GLEW_SUN_triangle_list) CONST_CAST(GLEW_SUN_triangle_list) = !_glewInit_GL_SUN_triangle_list(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUN_triangle_list */
+#ifdef GL_SUN_vertex
+ CONST_CAST(GLEW_SUN_vertex) = glewGetExtension("GL_SUN_vertex");
+ if (glewExperimental || GLEW_SUN_vertex) CONST_CAST(GLEW_SUN_vertex) = !_glewInit_GL_SUN_vertex(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_SUN_vertex */
+#ifdef GL_WIN_phong_shading
+ CONST_CAST(GLEW_WIN_phong_shading) = glewGetExtension("GL_WIN_phong_shading");
+#endif /* GL_WIN_phong_shading */
+#ifdef GL_WIN_specular_fog
+ CONST_CAST(GLEW_WIN_specular_fog) = glewGetExtension("GL_WIN_specular_fog");
+#endif /* GL_WIN_specular_fog */
+#ifdef GL_WIN_swap_hint
+ CONST_CAST(GLEW_WIN_swap_hint) = glewGetExtension("GL_WIN_swap_hint");
+ if (glewExperimental || GLEW_WIN_swap_hint) CONST_CAST(GLEW_WIN_swap_hint) = !_glewInit_GL_WIN_swap_hint(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GL_WIN_swap_hint */
+
+ return GLEW_OK;
+}
+
+
+#if defined(_WIN32)
+
+#if !defined(GLEW_MX)
+
+PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL = NULL;
+
+PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB = NULL;
+PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB = NULL;
+PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB = NULL;
+PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB = NULL;
+
+PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB = NULL;
+
+PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB = NULL;
+
+PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB = NULL;
+PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB = NULL;
+
+PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB = NULL;
+PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB = NULL;
+PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB = NULL;
+PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB = NULL;
+PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB = NULL;
+
+PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB = NULL;
+PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB = NULL;
+PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB = NULL;
+
+PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB = NULL;
+PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB = NULL;
+PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB = NULL;
+
+PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT = NULL;
+PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT = NULL;
+PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT = NULL;
+PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT = NULL;
+
+PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT = NULL;
+
+PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT = NULL;
+PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT = NULL;
+
+PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT = NULL;
+PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT = NULL;
+PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT = NULL;
+PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT = NULL;
+PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT = NULL;
+
+PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT = NULL;
+PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT = NULL;
+PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT = NULL;
+
+PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT = NULL;
+PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT = NULL;
+
+PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D = NULL;
+PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D = NULL;
+
+PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D = NULL;
+PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D = NULL;
+PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D = NULL;
+PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D = NULL;
+
+PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D = NULL;
+PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D = NULL;
+PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D = NULL;
+PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D = NULL;
+PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D = NULL;
+PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D = NULL;
+PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D = NULL;
+PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D = NULL;
+PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D = NULL;
+PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D = NULL;
+PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D = NULL;
+PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D = NULL;
+
+PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D = NULL;
+PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D = NULL;
+PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D = NULL;
+PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D = NULL;
+
+PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D = NULL;
+PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D = NULL;
+PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D = NULL;
+PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D = NULL;
+
+PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D = NULL;
+PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D = NULL;
+PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D = NULL;
+PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D = NULL;
+
+PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV = NULL;
+PFNWGLDELETEDCNVPROC __wglewDeleteDCNV = NULL;
+PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV = NULL;
+PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV = NULL;
+PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV = NULL;
+
+PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV = NULL;
+PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV = NULL;
+PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV = NULL;
+
+PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV = NULL;
+PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV = NULL;
+PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV = NULL;
+PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV = NULL;
+PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV = NULL;
+PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV = NULL;
+
+PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV = NULL;
+PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV = NULL;
+
+PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV = NULL;
+PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV = NULL;
+PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV = NULL;
+PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV = NULL;
+PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV = NULL;
+PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV = NULL;
+
+PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML = NULL;
+PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML = NULL;
+PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML = NULL;
+PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML = NULL;
+PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML = NULL;
+PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML = NULL;
+GLboolean __WGLEW_3DFX_multisample = GL_FALSE;
+GLboolean __WGLEW_3DL_stereo_control = GL_FALSE;
+GLboolean __WGLEW_ARB_buffer_region = GL_FALSE;
+GLboolean __WGLEW_ARB_create_context = GL_FALSE;
+GLboolean __WGLEW_ARB_extensions_string = GL_FALSE;
+GLboolean __WGLEW_ARB_framebuffer_sRGB = GL_FALSE;
+GLboolean __WGLEW_ARB_make_current_read = GL_FALSE;
+GLboolean __WGLEW_ARB_multisample = GL_FALSE;
+GLboolean __WGLEW_ARB_pbuffer = GL_FALSE;
+GLboolean __WGLEW_ARB_pixel_format = GL_FALSE;
+GLboolean __WGLEW_ARB_pixel_format_float = GL_FALSE;
+GLboolean __WGLEW_ARB_render_texture = GL_FALSE;
+GLboolean __WGLEW_ATI_pixel_format_float = GL_FALSE;
+GLboolean __WGLEW_ATI_render_texture_rectangle = GL_FALSE;
+GLboolean __WGLEW_EXT_depth_float = GL_FALSE;
+GLboolean __WGLEW_EXT_display_color_table = GL_FALSE;
+GLboolean __WGLEW_EXT_extensions_string = GL_FALSE;
+GLboolean __WGLEW_EXT_framebuffer_sRGB = GL_FALSE;
+GLboolean __WGLEW_EXT_make_current_read = GL_FALSE;
+GLboolean __WGLEW_EXT_multisample = GL_FALSE;
+GLboolean __WGLEW_EXT_pbuffer = GL_FALSE;
+GLboolean __WGLEW_EXT_pixel_format = GL_FALSE;
+GLboolean __WGLEW_EXT_pixel_format_packed_float = GL_FALSE;
+GLboolean __WGLEW_EXT_swap_control = GL_FALSE;
+GLboolean __WGLEW_I3D_digital_video_control = GL_FALSE;
+GLboolean __WGLEW_I3D_gamma = GL_FALSE;
+GLboolean __WGLEW_I3D_genlock = GL_FALSE;
+GLboolean __WGLEW_I3D_image_buffer = GL_FALSE;
+GLboolean __WGLEW_I3D_swap_frame_lock = GL_FALSE;
+GLboolean __WGLEW_I3D_swap_frame_usage = GL_FALSE;
+GLboolean __WGLEW_NV_float_buffer = GL_FALSE;
+GLboolean __WGLEW_NV_gpu_affinity = GL_FALSE;
+GLboolean __WGLEW_NV_present_video = GL_FALSE;
+GLboolean __WGLEW_NV_render_depth_texture = GL_FALSE;
+GLboolean __WGLEW_NV_render_texture_rectangle = GL_FALSE;
+GLboolean __WGLEW_NV_swap_group = GL_FALSE;
+GLboolean __WGLEW_NV_vertex_array_range = GL_FALSE;
+GLboolean __WGLEW_NV_video_output = GL_FALSE;
+GLboolean __WGLEW_OML_sync_control = GL_FALSE;
+
+#endif /* !GLEW_MX */
+
+#ifdef WGL_3DFX_multisample
+
+#endif /* WGL_3DFX_multisample */
+
+#ifdef WGL_3DL_stereo_control
+
+static GLboolean _glewInit_WGL_3DL_stereo_control (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglSetStereoEmitterState3DL = (PFNWGLSETSTEREOEMITTERSTATE3DLPROC)glewGetProcAddress((const GLubyte*)"wglSetStereoEmitterState3DL")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_3DL_stereo_control */
+
+#ifdef WGL_ARB_buffer_region
+
+static GLboolean _glewInit_WGL_ARB_buffer_region (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreateBufferRegionARB = (PFNWGLCREATEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglCreateBufferRegionARB")) == NULL) || r;
+ r = ((wglDeleteBufferRegionARB = (PFNWGLDELETEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglDeleteBufferRegionARB")) == NULL) || r;
+ r = ((wglRestoreBufferRegionARB = (PFNWGLRESTOREBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglRestoreBufferRegionARB")) == NULL) || r;
+ r = ((wglSaveBufferRegionARB = (PFNWGLSAVEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglSaveBufferRegionARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_buffer_region */
+
+#ifdef WGL_ARB_create_context
+
+static GLboolean _glewInit_WGL_ARB_create_context (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)glewGetProcAddress((const GLubyte*)"wglCreateContextAttribsARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_create_context */
+
+#ifdef WGL_ARB_extensions_string
+
+static GLboolean _glewInit_WGL_ARB_extensions_string (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_extensions_string */
+
+#ifdef WGL_ARB_framebuffer_sRGB
+
+#endif /* WGL_ARB_framebuffer_sRGB */
+
+#ifdef WGL_ARB_make_current_read
+
+static GLboolean _glewInit_WGL_ARB_make_current_read (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetCurrentReadDCARB = (PFNWGLGETCURRENTREADDCARBPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentReadDCARB")) == NULL) || r;
+ r = ((wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)glewGetProcAddress((const GLubyte*)"wglMakeContextCurrentARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_make_current_read */
+
+#ifdef WGL_ARB_multisample
+
+#endif /* WGL_ARB_multisample */
+
+#ifdef WGL_ARB_pbuffer
+
+static GLboolean _glewInit_WGL_ARB_pbuffer (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglCreatePbufferARB")) == NULL) || r;
+ r = ((wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglDestroyPbufferARB")) == NULL) || r;
+ r = ((wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPbufferDCARB")) == NULL) || r;
+ r = ((wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglQueryPbufferARB")) == NULL) || r;
+ r = ((wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)glewGetProcAddress((const GLubyte*)"wglReleasePbufferDCARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_pbuffer */
+
+#ifdef WGL_ARB_pixel_format
+
+static GLboolean _glewInit_WGL_ARB_pixel_format (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatARB")) == NULL) || r;
+ r = ((wglGetPixelFormatAttribfvARB = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribfvARB")) == NULL) || r;
+ r = ((wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribivARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_pixel_format */
+
+#ifdef WGL_ARB_pixel_format_float
+
+#endif /* WGL_ARB_pixel_format_float */
+
+#ifdef WGL_ARB_render_texture
+
+static GLboolean _glewInit_WGL_ARB_render_texture (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindTexImageARB = (PFNWGLBINDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"wglBindTexImageARB")) == NULL) || r;
+ r = ((wglReleaseTexImageARB = (PFNWGLRELEASETEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"wglReleaseTexImageARB")) == NULL) || r;
+ r = ((wglSetPbufferAttribARB = (PFNWGLSETPBUFFERATTRIBARBPROC)glewGetProcAddress((const GLubyte*)"wglSetPbufferAttribARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_ARB_render_texture */
+
+#ifdef WGL_ATI_pixel_format_float
+
+#endif /* WGL_ATI_pixel_format_float */
+
+#ifdef WGL_ATI_render_texture_rectangle
+
+#endif /* WGL_ATI_render_texture_rectangle */
+
+#ifdef WGL_EXT_depth_float
+
+#endif /* WGL_EXT_depth_float */
+
+#ifdef WGL_EXT_display_color_table
+
+static GLboolean _glewInit_WGL_EXT_display_color_table (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindDisplayColorTableEXT = (PFNWGLBINDDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglBindDisplayColorTableEXT")) == NULL) || r;
+ r = ((wglCreateDisplayColorTableEXT = (PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglCreateDisplayColorTableEXT")) == NULL) || r;
+ r = ((wglDestroyDisplayColorTableEXT = (PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglDestroyDisplayColorTableEXT")) == NULL) || r;
+ r = ((wglLoadDisplayColorTableEXT = (PFNWGLLOADDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglLoadDisplayColorTableEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_display_color_table */
+
+#ifdef WGL_EXT_extensions_string
+
+static GLboolean _glewInit_WGL_EXT_extensions_string (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_extensions_string */
+
+#ifdef WGL_EXT_framebuffer_sRGB
+
+#endif /* WGL_EXT_framebuffer_sRGB */
+
+#ifdef WGL_EXT_make_current_read
+
+static GLboolean _glewInit_WGL_EXT_make_current_read (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetCurrentReadDCEXT = (PFNWGLGETCURRENTREADDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentReadDCEXT")) == NULL) || r;
+ r = ((wglMakeContextCurrentEXT = (PFNWGLMAKECONTEXTCURRENTEXTPROC)glewGetProcAddress((const GLubyte*)"wglMakeContextCurrentEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_make_current_read */
+
+#ifdef WGL_EXT_multisample
+
+#endif /* WGL_EXT_multisample */
+
+#ifdef WGL_EXT_pbuffer
+
+static GLboolean _glewInit_WGL_EXT_pbuffer (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreatePbufferEXT = (PFNWGLCREATEPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglCreatePbufferEXT")) == NULL) || r;
+ r = ((wglDestroyPbufferEXT = (PFNWGLDESTROYPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglDestroyPbufferEXT")) == NULL) || r;
+ r = ((wglGetPbufferDCEXT = (PFNWGLGETPBUFFERDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPbufferDCEXT")) == NULL) || r;
+ r = ((wglQueryPbufferEXT = (PFNWGLQUERYPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglQueryPbufferEXT")) == NULL) || r;
+ r = ((wglReleasePbufferDCEXT = (PFNWGLRELEASEPBUFFERDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglReleasePbufferDCEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_pbuffer */
+
+#ifdef WGL_EXT_pixel_format
+
+static GLboolean _glewInit_WGL_EXT_pixel_format (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglChoosePixelFormatEXT = (PFNWGLCHOOSEPIXELFORMATEXTPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatEXT")) == NULL) || r;
+ r = ((wglGetPixelFormatAttribfvEXT = (PFNWGLGETPIXELFORMATATTRIBFVEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribfvEXT")) == NULL) || r;
+ r = ((wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribivEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_pixel_format */
+
+#ifdef WGL_EXT_pixel_format_packed_float
+
+#endif /* WGL_EXT_pixel_format_packed_float */
+
+#ifdef WGL_EXT_swap_control
+
+static GLboolean _glewInit_WGL_EXT_swap_control (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetSwapIntervalEXT")) == NULL) || r;
+ r = ((wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"wglSwapIntervalEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_EXT_swap_control */
+
+#ifdef WGL_I3D_digital_video_control
+
+static GLboolean _glewInit_WGL_I3D_digital_video_control (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetDigitalVideoParametersI3D = (PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetDigitalVideoParametersI3D")) == NULL) || r;
+ r = ((wglSetDigitalVideoParametersI3D = (PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetDigitalVideoParametersI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_digital_video_control */
+
+#ifdef WGL_I3D_gamma
+
+static GLboolean _glewInit_WGL_I3D_gamma (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetGammaTableI3D = (PFNWGLGETGAMMATABLEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGammaTableI3D")) == NULL) || r;
+ r = ((wglGetGammaTableParametersI3D = (PFNWGLGETGAMMATABLEPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGammaTableParametersI3D")) == NULL) || r;
+ r = ((wglSetGammaTableI3D = (PFNWGLSETGAMMATABLEI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetGammaTableI3D")) == NULL) || r;
+ r = ((wglSetGammaTableParametersI3D = (PFNWGLSETGAMMATABLEPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetGammaTableParametersI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_gamma */
+
+#ifdef WGL_I3D_genlock
+
+static GLboolean _glewInit_WGL_I3D_genlock (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglDisableGenlockI3D = (PFNWGLDISABLEGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglDisableGenlockI3D")) == NULL) || r;
+ r = ((wglEnableGenlockI3D = (PFNWGLENABLEGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglEnableGenlockI3D")) == NULL) || r;
+ r = ((wglGenlockSampleRateI3D = (PFNWGLGENLOCKSAMPLERATEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSampleRateI3D")) == NULL) || r;
+ r = ((wglGenlockSourceDelayI3D = (PFNWGLGENLOCKSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceDelayI3D")) == NULL) || r;
+ r = ((wglGenlockSourceEdgeI3D = (PFNWGLGENLOCKSOURCEEDGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceEdgeI3D")) == NULL) || r;
+ r = ((wglGenlockSourceI3D = (PFNWGLGENLOCKSOURCEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceI3D")) == NULL) || r;
+ r = ((wglGetGenlockSampleRateI3D = (PFNWGLGETGENLOCKSAMPLERATEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSampleRateI3D")) == NULL) || r;
+ r = ((wglGetGenlockSourceDelayI3D = (PFNWGLGETGENLOCKSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceDelayI3D")) == NULL) || r;
+ r = ((wglGetGenlockSourceEdgeI3D = (PFNWGLGETGENLOCKSOURCEEDGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceEdgeI3D")) == NULL) || r;
+ r = ((wglGetGenlockSourceI3D = (PFNWGLGETGENLOCKSOURCEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceI3D")) == NULL) || r;
+ r = ((wglIsEnabledGenlockI3D = (PFNWGLISENABLEDGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglIsEnabledGenlockI3D")) == NULL) || r;
+ r = ((wglQueryGenlockMaxSourceDelayI3D = (PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryGenlockMaxSourceDelayI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_genlock */
+
+#ifdef WGL_I3D_image_buffer
+
+static GLboolean _glewInit_WGL_I3D_image_buffer (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglAssociateImageBufferEventsI3D = (PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC)glewGetProcAddress((const GLubyte*)"wglAssociateImageBufferEventsI3D")) == NULL) || r;
+ r = ((wglCreateImageBufferI3D = (PFNWGLCREATEIMAGEBUFFERI3DPROC)glewGetProcAddress((const GLubyte*)"wglCreateImageBufferI3D")) == NULL) || r;
+ r = ((wglDestroyImageBufferI3D = (PFNWGLDESTROYIMAGEBUFFERI3DPROC)glewGetProcAddress((const GLubyte*)"wglDestroyImageBufferI3D")) == NULL) || r;
+ r = ((wglReleaseImageBufferEventsI3D = (PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC)glewGetProcAddress((const GLubyte*)"wglReleaseImageBufferEventsI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_image_buffer */
+
+#ifdef WGL_I3D_swap_frame_lock
+
+static GLboolean _glewInit_WGL_I3D_swap_frame_lock (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglDisableFrameLockI3D = (PFNWGLDISABLEFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglDisableFrameLockI3D")) == NULL) || r;
+ r = ((wglEnableFrameLockI3D = (PFNWGLENABLEFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglEnableFrameLockI3D")) == NULL) || r;
+ r = ((wglIsEnabledFrameLockI3D = (PFNWGLISENABLEDFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglIsEnabledFrameLockI3D")) == NULL) || r;
+ r = ((wglQueryFrameLockMasterI3D = (PFNWGLQUERYFRAMELOCKMASTERI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameLockMasterI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_swap_frame_lock */
+
+#ifdef WGL_I3D_swap_frame_usage
+
+static GLboolean _glewInit_WGL_I3D_swap_frame_usage (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBeginFrameTrackingI3D = (PFNWGLBEGINFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglBeginFrameTrackingI3D")) == NULL) || r;
+ r = ((wglEndFrameTrackingI3D = (PFNWGLENDFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglEndFrameTrackingI3D")) == NULL) || r;
+ r = ((wglGetFrameUsageI3D = (PFNWGLGETFRAMEUSAGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetFrameUsageI3D")) == NULL) || r;
+ r = ((wglQueryFrameTrackingI3D = (PFNWGLQUERYFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameTrackingI3D")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_I3D_swap_frame_usage */
+
+#ifdef WGL_NV_float_buffer
+
+#endif /* WGL_NV_float_buffer */
+
+#ifdef WGL_NV_gpu_affinity
+
+static GLboolean _glewInit_WGL_NV_gpu_affinity (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglCreateAffinityDCNV = (PFNWGLCREATEAFFINITYDCNVPROC)glewGetProcAddress((const GLubyte*)"wglCreateAffinityDCNV")) == NULL) || r;
+ r = ((wglDeleteDCNV = (PFNWGLDELETEDCNVPROC)glewGetProcAddress((const GLubyte*)"wglDeleteDCNV")) == NULL) || r;
+ r = ((wglEnumGpuDevicesNV = (PFNWGLENUMGPUDEVICESNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpuDevicesNV")) == NULL) || r;
+ r = ((wglEnumGpusFromAffinityDCNV = (PFNWGLENUMGPUSFROMAFFINITYDCNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpusFromAffinityDCNV")) == NULL) || r;
+ r = ((wglEnumGpusNV = (PFNWGLENUMGPUSNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpusNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_gpu_affinity */
+
+#ifdef WGL_NV_present_video
+
+static GLboolean _glewInit_WGL_NV_present_video (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindVideoDeviceNV = (PFNWGLBINDVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglBindVideoDeviceNV")) == NULL) || r;
+ r = ((wglEnumerateVideoDevicesNV = (PFNWGLENUMERATEVIDEODEVICESNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumerateVideoDevicesNV")) == NULL) || r;
+ r = ((wglQueryCurrentContextNV = (PFNWGLQUERYCURRENTCONTEXTNVPROC)glewGetProcAddress((const GLubyte*)"wglQueryCurrentContextNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_present_video */
+
+#ifdef WGL_NV_render_depth_texture
+
+#endif /* WGL_NV_render_depth_texture */
+
+#ifdef WGL_NV_render_texture_rectangle
+
+#endif /* WGL_NV_render_texture_rectangle */
+
+#ifdef WGL_NV_swap_group
+
+static GLboolean _glewInit_WGL_NV_swap_group (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindSwapBarrierNV = (PFNWGLBINDSWAPBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"wglBindSwapBarrierNV")) == NULL) || r;
+ r = ((wglJoinSwapGroupNV = (PFNWGLJOINSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"wglJoinSwapGroupNV")) == NULL) || r;
+ r = ((wglQueryFrameCountNV = (PFNWGLQUERYFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameCountNV")) == NULL) || r;
+ r = ((wglQueryMaxSwapGroupsNV = (PFNWGLQUERYMAXSWAPGROUPSNVPROC)glewGetProcAddress((const GLubyte*)"wglQueryMaxSwapGroupsNV")) == NULL) || r;
+ r = ((wglQuerySwapGroupNV = (PFNWGLQUERYSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"wglQuerySwapGroupNV")) == NULL) || r;
+ r = ((wglResetFrameCountNV = (PFNWGLRESETFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"wglResetFrameCountNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_swap_group */
+
+#ifdef WGL_NV_vertex_array_range
+
+static GLboolean _glewInit_WGL_NV_vertex_array_range (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"wglAllocateMemoryNV")) == NULL) || r;
+ r = ((wglFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"wglFreeMemoryNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_vertex_array_range */
+
+#ifdef WGL_NV_video_output
+
+static GLboolean _glewInit_WGL_NV_video_output (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglBindVideoImageNV = (PFNWGLBINDVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"wglBindVideoImageNV")) == NULL) || r;
+ r = ((wglGetVideoDeviceNV = (PFNWGLGETVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglGetVideoDeviceNV")) == NULL) || r;
+ r = ((wglGetVideoInfoNV = (PFNWGLGETVIDEOINFONVPROC)glewGetProcAddress((const GLubyte*)"wglGetVideoInfoNV")) == NULL) || r;
+ r = ((wglReleaseVideoDeviceNV = (PFNWGLRELEASEVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglReleaseVideoDeviceNV")) == NULL) || r;
+ r = ((wglReleaseVideoImageNV = (PFNWGLRELEASEVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"wglReleaseVideoImageNV")) == NULL) || r;
+ r = ((wglSendPbufferToVideoNV = (PFNWGLSENDPBUFFERTOVIDEONVPROC)glewGetProcAddress((const GLubyte*)"wglSendPbufferToVideoNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_NV_video_output */
+
+#ifdef WGL_OML_sync_control
+
+static GLboolean _glewInit_WGL_OML_sync_control (WGLEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((wglGetMscRateOML = (PFNWGLGETMSCRATEOMLPROC)glewGetProcAddress((const GLubyte*)"wglGetMscRateOML")) == NULL) || r;
+ r = ((wglGetSyncValuesOML = (PFNWGLGETSYNCVALUESOMLPROC)glewGetProcAddress((const GLubyte*)"wglGetSyncValuesOML")) == NULL) || r;
+ r = ((wglSwapBuffersMscOML = (PFNWGLSWAPBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglSwapBuffersMscOML")) == NULL) || r;
+ r = ((wglSwapLayerBuffersMscOML = (PFNWGLSWAPLAYERBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglSwapLayerBuffersMscOML")) == NULL) || r;
+ r = ((wglWaitForMscOML = (PFNWGLWAITFORMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglWaitForMscOML")) == NULL) || r;
+ r = ((wglWaitForSbcOML = (PFNWGLWAITFORSBCOMLPROC)glewGetProcAddress((const GLubyte*)"wglWaitForSbcOML")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* WGL_OML_sync_control */
+
+/* ------------------------------------------------------------------------- */
+
+static PFNWGLGETEXTENSIONSSTRINGARBPROC _wglewGetExtensionsStringARB = NULL;
+static PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglewGetExtensionsStringEXT = NULL;
+
+GLboolean wglewGetExtension (const char* name)
+{
+ GLubyte* p;
+ GLubyte* end;
+ GLuint len = _glewStrLen((const GLubyte*)name);
+ if (_wglewGetExtensionsStringARB == NULL)
+ if (_wglewGetExtensionsStringEXT == NULL)
+ return GL_FALSE;
+ else
+ p = (GLubyte*)_wglewGetExtensionsStringEXT();
+ else
+ p = (GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC());
+ if (0 == p) return GL_FALSE;
+ end = p + _glewStrLen(p);
+ while (p < end)
+ {
+ GLuint n = _glewStrCLen(p, ' ');
+ if (len == n && _glewStrSame((const GLubyte*)name, p, n)) return GL_TRUE;
+ p += n+1;
+ }
+ return GL_FALSE;
+}
+
+GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
+{
+ GLboolean crippled;
+ /* find wgl extension string query functions */
+ _wglewGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringARB");
+ _wglewGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringEXT");
+ /* initialize extensions */
+ crippled = _wglewGetExtensionsStringARB == NULL && _wglewGetExtensionsStringEXT == NULL;
+#ifdef WGL_3DFX_multisample
+ CONST_CAST(WGLEW_3DFX_multisample) = wglewGetExtension("WGL_3DFX_multisample");
+#endif /* WGL_3DFX_multisample */
+#ifdef WGL_3DL_stereo_control
+ CONST_CAST(WGLEW_3DL_stereo_control) = wglewGetExtension("WGL_3DL_stereo_control");
+ if (glewExperimental || WGLEW_3DL_stereo_control|| crippled) CONST_CAST(WGLEW_3DL_stereo_control)= !_glewInit_WGL_3DL_stereo_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_3DL_stereo_control */
+#ifdef WGL_ARB_buffer_region
+ CONST_CAST(WGLEW_ARB_buffer_region) = wglewGetExtension("WGL_ARB_buffer_region");
+ if (glewExperimental || WGLEW_ARB_buffer_region|| crippled) CONST_CAST(WGLEW_ARB_buffer_region)= !_glewInit_WGL_ARB_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_buffer_region */
+#ifdef WGL_ARB_create_context
+ CONST_CAST(WGLEW_ARB_create_context) = wglewGetExtension("WGL_ARB_create_context");
+ if (glewExperimental || WGLEW_ARB_create_context|| crippled) CONST_CAST(WGLEW_ARB_create_context)= !_glewInit_WGL_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_create_context */
+#ifdef WGL_ARB_extensions_string
+ CONST_CAST(WGLEW_ARB_extensions_string) = wglewGetExtension("WGL_ARB_extensions_string");
+ if (glewExperimental || WGLEW_ARB_extensions_string|| crippled) CONST_CAST(WGLEW_ARB_extensions_string)= !_glewInit_WGL_ARB_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_extensions_string */
+#ifdef WGL_ARB_framebuffer_sRGB
+ CONST_CAST(WGLEW_ARB_framebuffer_sRGB) = wglewGetExtension("WGL_ARB_framebuffer_sRGB");
+#endif /* WGL_ARB_framebuffer_sRGB */
+#ifdef WGL_ARB_make_current_read
+ CONST_CAST(WGLEW_ARB_make_current_read) = wglewGetExtension("WGL_ARB_make_current_read");
+ if (glewExperimental || WGLEW_ARB_make_current_read|| crippled) CONST_CAST(WGLEW_ARB_make_current_read)= !_glewInit_WGL_ARB_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_make_current_read */
+#ifdef WGL_ARB_multisample
+ CONST_CAST(WGLEW_ARB_multisample) = wglewGetExtension("WGL_ARB_multisample");
+#endif /* WGL_ARB_multisample */
+#ifdef WGL_ARB_pbuffer
+ CONST_CAST(WGLEW_ARB_pbuffer) = wglewGetExtension("WGL_ARB_pbuffer");
+ if (glewExperimental || WGLEW_ARB_pbuffer|| crippled) CONST_CAST(WGLEW_ARB_pbuffer)= !_glewInit_WGL_ARB_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_pbuffer */
+#ifdef WGL_ARB_pixel_format
+ CONST_CAST(WGLEW_ARB_pixel_format) = wglewGetExtension("WGL_ARB_pixel_format");
+ if (glewExperimental || WGLEW_ARB_pixel_format|| crippled) CONST_CAST(WGLEW_ARB_pixel_format)= !_glewInit_WGL_ARB_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_pixel_format */
+#ifdef WGL_ARB_pixel_format_float
+ CONST_CAST(WGLEW_ARB_pixel_format_float) = wglewGetExtension("WGL_ARB_pixel_format_float");
+#endif /* WGL_ARB_pixel_format_float */
+#ifdef WGL_ARB_render_texture
+ CONST_CAST(WGLEW_ARB_render_texture) = wglewGetExtension("WGL_ARB_render_texture");
+ if (glewExperimental || WGLEW_ARB_render_texture|| crippled) CONST_CAST(WGLEW_ARB_render_texture)= !_glewInit_WGL_ARB_render_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_ARB_render_texture */
+#ifdef WGL_ATI_pixel_format_float
+ CONST_CAST(WGLEW_ATI_pixel_format_float) = wglewGetExtension("WGL_ATI_pixel_format_float");
+#endif /* WGL_ATI_pixel_format_float */
+#ifdef WGL_ATI_render_texture_rectangle
+ CONST_CAST(WGLEW_ATI_render_texture_rectangle) = wglewGetExtension("WGL_ATI_render_texture_rectangle");
+#endif /* WGL_ATI_render_texture_rectangle */
+#ifdef WGL_EXT_depth_float
+ CONST_CAST(WGLEW_EXT_depth_float) = wglewGetExtension("WGL_EXT_depth_float");
+#endif /* WGL_EXT_depth_float */
+#ifdef WGL_EXT_display_color_table
+ CONST_CAST(WGLEW_EXT_display_color_table) = wglewGetExtension("WGL_EXT_display_color_table");
+ if (glewExperimental || WGLEW_EXT_display_color_table|| crippled) CONST_CAST(WGLEW_EXT_display_color_table)= !_glewInit_WGL_EXT_display_color_table(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_display_color_table */
+#ifdef WGL_EXT_extensions_string
+ CONST_CAST(WGLEW_EXT_extensions_string) = wglewGetExtension("WGL_EXT_extensions_string");
+ if (glewExperimental || WGLEW_EXT_extensions_string|| crippled) CONST_CAST(WGLEW_EXT_extensions_string)= !_glewInit_WGL_EXT_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_extensions_string */
+#ifdef WGL_EXT_framebuffer_sRGB
+ CONST_CAST(WGLEW_EXT_framebuffer_sRGB) = wglewGetExtension("WGL_EXT_framebuffer_sRGB");
+#endif /* WGL_EXT_framebuffer_sRGB */
+#ifdef WGL_EXT_make_current_read
+ CONST_CAST(WGLEW_EXT_make_current_read) = wglewGetExtension("WGL_EXT_make_current_read");
+ if (glewExperimental || WGLEW_EXT_make_current_read|| crippled) CONST_CAST(WGLEW_EXT_make_current_read)= !_glewInit_WGL_EXT_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_make_current_read */
+#ifdef WGL_EXT_multisample
+ CONST_CAST(WGLEW_EXT_multisample) = wglewGetExtension("WGL_EXT_multisample");
+#endif /* WGL_EXT_multisample */
+#ifdef WGL_EXT_pbuffer
+ CONST_CAST(WGLEW_EXT_pbuffer) = wglewGetExtension("WGL_EXT_pbuffer");
+ if (glewExperimental || WGLEW_EXT_pbuffer|| crippled) CONST_CAST(WGLEW_EXT_pbuffer)= !_glewInit_WGL_EXT_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_pbuffer */
+#ifdef WGL_EXT_pixel_format
+ CONST_CAST(WGLEW_EXT_pixel_format) = wglewGetExtension("WGL_EXT_pixel_format");
+ if (glewExperimental || WGLEW_EXT_pixel_format|| crippled) CONST_CAST(WGLEW_EXT_pixel_format)= !_glewInit_WGL_EXT_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_pixel_format */
+#ifdef WGL_EXT_pixel_format_packed_float
+ CONST_CAST(WGLEW_EXT_pixel_format_packed_float) = wglewGetExtension("WGL_EXT_pixel_format_packed_float");
+#endif /* WGL_EXT_pixel_format_packed_float */
+#ifdef WGL_EXT_swap_control
+ CONST_CAST(WGLEW_EXT_swap_control) = wglewGetExtension("WGL_EXT_swap_control");
+ if (glewExperimental || WGLEW_EXT_swap_control|| crippled) CONST_CAST(WGLEW_EXT_swap_control)= !_glewInit_WGL_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_EXT_swap_control */
+#ifdef WGL_I3D_digital_video_control
+ CONST_CAST(WGLEW_I3D_digital_video_control) = wglewGetExtension("WGL_I3D_digital_video_control");
+ if (glewExperimental || WGLEW_I3D_digital_video_control|| crippled) CONST_CAST(WGLEW_I3D_digital_video_control)= !_glewInit_WGL_I3D_digital_video_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_digital_video_control */
+#ifdef WGL_I3D_gamma
+ CONST_CAST(WGLEW_I3D_gamma) = wglewGetExtension("WGL_I3D_gamma");
+ if (glewExperimental || WGLEW_I3D_gamma|| crippled) CONST_CAST(WGLEW_I3D_gamma)= !_glewInit_WGL_I3D_gamma(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_gamma */
+#ifdef WGL_I3D_genlock
+ CONST_CAST(WGLEW_I3D_genlock) = wglewGetExtension("WGL_I3D_genlock");
+ if (glewExperimental || WGLEW_I3D_genlock|| crippled) CONST_CAST(WGLEW_I3D_genlock)= !_glewInit_WGL_I3D_genlock(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_genlock */
+#ifdef WGL_I3D_image_buffer
+ CONST_CAST(WGLEW_I3D_image_buffer) = wglewGetExtension("WGL_I3D_image_buffer");
+ if (glewExperimental || WGLEW_I3D_image_buffer|| crippled) CONST_CAST(WGLEW_I3D_image_buffer)= !_glewInit_WGL_I3D_image_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_image_buffer */
+#ifdef WGL_I3D_swap_frame_lock
+ CONST_CAST(WGLEW_I3D_swap_frame_lock) = wglewGetExtension("WGL_I3D_swap_frame_lock");
+ if (glewExperimental || WGLEW_I3D_swap_frame_lock|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_lock)= !_glewInit_WGL_I3D_swap_frame_lock(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_swap_frame_lock */
+#ifdef WGL_I3D_swap_frame_usage
+ CONST_CAST(WGLEW_I3D_swap_frame_usage) = wglewGetExtension("WGL_I3D_swap_frame_usage");
+ if (glewExperimental || WGLEW_I3D_swap_frame_usage|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_usage)= !_glewInit_WGL_I3D_swap_frame_usage(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_I3D_swap_frame_usage */
+#ifdef WGL_NV_float_buffer
+ CONST_CAST(WGLEW_NV_float_buffer) = wglewGetExtension("WGL_NV_float_buffer");
+#endif /* WGL_NV_float_buffer */
+#ifdef WGL_NV_gpu_affinity
+ CONST_CAST(WGLEW_NV_gpu_affinity) = wglewGetExtension("WGL_NV_gpu_affinity");
+ if (glewExperimental || WGLEW_NV_gpu_affinity|| crippled) CONST_CAST(WGLEW_NV_gpu_affinity)= !_glewInit_WGL_NV_gpu_affinity(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_gpu_affinity */
+#ifdef WGL_NV_present_video
+ CONST_CAST(WGLEW_NV_present_video) = wglewGetExtension("WGL_NV_present_video");
+ if (glewExperimental || WGLEW_NV_present_video|| crippled) CONST_CAST(WGLEW_NV_present_video)= !_glewInit_WGL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_present_video */
+#ifdef WGL_NV_render_depth_texture
+ CONST_CAST(WGLEW_NV_render_depth_texture) = wglewGetExtension("WGL_NV_render_depth_texture");
+#endif /* WGL_NV_render_depth_texture */
+#ifdef WGL_NV_render_texture_rectangle
+ CONST_CAST(WGLEW_NV_render_texture_rectangle) = wglewGetExtension("WGL_NV_render_texture_rectangle");
+#endif /* WGL_NV_render_texture_rectangle */
+#ifdef WGL_NV_swap_group
+ CONST_CAST(WGLEW_NV_swap_group) = wglewGetExtension("WGL_NV_swap_group");
+ if (glewExperimental || WGLEW_NV_swap_group|| crippled) CONST_CAST(WGLEW_NV_swap_group)= !_glewInit_WGL_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_swap_group */
+#ifdef WGL_NV_vertex_array_range
+ CONST_CAST(WGLEW_NV_vertex_array_range) = wglewGetExtension("WGL_NV_vertex_array_range");
+ if (glewExperimental || WGLEW_NV_vertex_array_range|| crippled) CONST_CAST(WGLEW_NV_vertex_array_range)= !_glewInit_WGL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_vertex_array_range */
+#ifdef WGL_NV_video_output
+ CONST_CAST(WGLEW_NV_video_output) = wglewGetExtension("WGL_NV_video_output");
+ if (glewExperimental || WGLEW_NV_video_output|| crippled) CONST_CAST(WGLEW_NV_video_output)= !_glewInit_WGL_NV_video_output(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_NV_video_output */
+#ifdef WGL_OML_sync_control
+ CONST_CAST(WGLEW_OML_sync_control) = wglewGetExtension("WGL_OML_sync_control");
+ if (glewExperimental || WGLEW_OML_sync_control|| crippled) CONST_CAST(WGLEW_OML_sync_control)= !_glewInit_WGL_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* WGL_OML_sync_control */
+
+ return GLEW_OK;
+}
+
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+
+PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay = NULL;
+
+PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig = NULL;
+PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext = NULL;
+PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer = NULL;
+PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap = NULL;
+PFNGLXCREATEWINDOWPROC __glewXCreateWindow = NULL;
+PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer = NULL;
+PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap = NULL;
+PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow = NULL;
+PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable = NULL;
+PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib = NULL;
+PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs = NULL;
+PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent = NULL;
+PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig = NULL;
+PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent = NULL;
+PFNGLXQUERYCONTEXTPROC __glewXQueryContext = NULL;
+PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable = NULL;
+PFNGLXSELECTEVENTPROC __glewXSelectEvent = NULL;
+
+PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB = NULL;
+
+PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI = NULL;
+PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI = NULL;
+PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI = NULL;
+
+PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT = NULL;
+PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT = NULL;
+PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT = NULL;
+PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT = NULL;
+
+PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT = NULL;
+PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT = NULL;
+
+PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA = NULL;
+
+PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA = NULL;
+
+PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA = NULL;
+
+PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA = NULL;
+
+PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA = NULL;
+
+PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV = NULL;
+PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV = NULL;
+
+PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV = NULL;
+PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV = NULL;
+PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV = NULL;
+PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV = NULL;
+PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV = NULL;
+PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV = NULL;
+
+PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV = NULL;
+PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV = NULL;
+
+PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV = NULL;
+PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV = NULL;
+PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV = NULL;
+PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV = NULL;
+PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV = NULL;
+PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV = NULL;
+
+#ifdef GLX_OML_sync_control
+PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML = NULL;
+PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML = NULL;
+PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML = NULL;
+PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML = NULL;
+PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML = NULL;
+#endif
+
+PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX = NULL;
+PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX = NULL;
+PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX = NULL;
+PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX = NULL;
+PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX = NULL;
+PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX = NULL;
+
+PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX = NULL;
+PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX = NULL;
+PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX = NULL;
+PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX = NULL;
+PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX = NULL;
+PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX = NULL;
+PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX = NULL;
+PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX = NULL;
+
+PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX = NULL;
+PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX = NULL;
+PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX = NULL;
+PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX = NULL;
+PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX = NULL;
+
+PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX = NULL;
+PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX = NULL;
+
+PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX = NULL;
+
+PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX = NULL;
+PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX = NULL;
+PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX = NULL;
+PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX = NULL;
+PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX = NULL;
+
+PFNGLXCUSHIONSGIPROC __glewXCushionSGI = NULL;
+
+PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI = NULL;
+PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI = NULL;
+
+PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI = NULL;
+
+PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI = NULL;
+PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI = NULL;
+
+PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN = NULL;
+
+PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN = NULL;
+PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN = NULL;
+
+#if !defined(GLEW_MX)
+
+GLboolean __GLXEW_VERSION_1_0 = GL_FALSE;
+GLboolean __GLXEW_VERSION_1_1 = GL_FALSE;
+GLboolean __GLXEW_VERSION_1_2 = GL_FALSE;
+GLboolean __GLXEW_VERSION_1_3 = GL_FALSE;
+GLboolean __GLXEW_VERSION_1_4 = GL_FALSE;
+GLboolean __GLXEW_3DFX_multisample = GL_FALSE;
+GLboolean __GLXEW_ARB_create_context = GL_FALSE;
+GLboolean __GLXEW_ARB_fbconfig_float = GL_FALSE;
+GLboolean __GLXEW_ARB_framebuffer_sRGB = GL_FALSE;
+GLboolean __GLXEW_ARB_get_proc_address = GL_FALSE;
+GLboolean __GLXEW_ARB_multisample = GL_FALSE;
+GLboolean __GLXEW_ATI_pixel_format_float = GL_FALSE;
+GLboolean __GLXEW_ATI_render_texture = GL_FALSE;
+GLboolean __GLXEW_EXT_fbconfig_packed_float = GL_FALSE;
+GLboolean __GLXEW_EXT_framebuffer_sRGB = GL_FALSE;
+GLboolean __GLXEW_EXT_import_context = GL_FALSE;
+GLboolean __GLXEW_EXT_scene_marker = GL_FALSE;
+GLboolean __GLXEW_EXT_texture_from_pixmap = GL_FALSE;
+GLboolean __GLXEW_EXT_visual_info = GL_FALSE;
+GLboolean __GLXEW_EXT_visual_rating = GL_FALSE;
+GLboolean __GLXEW_MESA_agp_offset = GL_FALSE;
+GLboolean __GLXEW_MESA_copy_sub_buffer = GL_FALSE;
+GLboolean __GLXEW_MESA_pixmap_colormap = GL_FALSE;
+GLboolean __GLXEW_MESA_release_buffers = GL_FALSE;
+GLboolean __GLXEW_MESA_set_3dfx_mode = GL_FALSE;
+GLboolean __GLXEW_NV_float_buffer = GL_FALSE;
+GLboolean __GLXEW_NV_present_video = GL_FALSE;
+GLboolean __GLXEW_NV_swap_group = GL_FALSE;
+GLboolean __GLXEW_NV_vertex_array_range = GL_FALSE;
+GLboolean __GLXEW_NV_video_output = GL_FALSE;
+GLboolean __GLXEW_OML_swap_method = GL_FALSE;
+#ifdef GLX_OML_sync_control
+GLboolean __GLXEW_OML_sync_control = GL_FALSE;
+#endif
+GLboolean __GLXEW_SGIS_blended_overlay = GL_FALSE;
+GLboolean __GLXEW_SGIS_color_range = GL_FALSE;
+GLboolean __GLXEW_SGIS_multisample = GL_FALSE;
+GLboolean __GLXEW_SGIS_shared_multisample = GL_FALSE;
+GLboolean __GLXEW_SGIX_fbconfig = GL_FALSE;
+GLboolean __GLXEW_SGIX_hyperpipe = GL_FALSE;
+GLboolean __GLXEW_SGIX_pbuffer = GL_FALSE;
+GLboolean __GLXEW_SGIX_swap_barrier = GL_FALSE;
+GLboolean __GLXEW_SGIX_swap_group = GL_FALSE;
+GLboolean __GLXEW_SGIX_video_resize = GL_FALSE;
+GLboolean __GLXEW_SGIX_visual_select_group = GL_FALSE;
+GLboolean __GLXEW_SGI_cushion = GL_FALSE;
+GLboolean __GLXEW_SGI_make_current_read = GL_FALSE;
+GLboolean __GLXEW_SGI_swap_control = GL_FALSE;
+GLboolean __GLXEW_SGI_video_sync = GL_FALSE;
+GLboolean __GLXEW_SUN_get_transparent_index = GL_FALSE;
+GLboolean __GLXEW_SUN_video_resize = GL_FALSE;
+
+#endif /* !GLEW_MX */
+
+#ifdef GLX_VERSION_1_2
+
+static GLboolean _glewInit_GLX_VERSION_1_2 (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetCurrentDisplay = (PFNGLXGETCURRENTDISPLAYPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentDisplay")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_VERSION_1_2 */
+
+#ifdef GLX_VERSION_1_3
+
+static GLboolean _glewInit_GLX_VERSION_1_3 (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glewGetProcAddress((const GLubyte*)"glXChooseFBConfig")) == NULL) || r;
+ r = ((glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC)glewGetProcAddress((const GLubyte*)"glXCreateNewContext")) == NULL) || r;
+ r = ((glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glXCreatePbuffer")) == NULL) || r;
+ r = ((glXCreatePixmap = (PFNGLXCREATEPIXMAPPROC)glewGetProcAddress((const GLubyte*)"glXCreatePixmap")) == NULL) || r;
+ r = ((glXCreateWindow = (PFNGLXCREATEWINDOWPROC)glewGetProcAddress((const GLubyte*)"glXCreateWindow")) == NULL) || r;
+ r = ((glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glXDestroyPbuffer")) == NULL) || r;
+ r = ((glXDestroyPixmap = (PFNGLXDESTROYPIXMAPPROC)glewGetProcAddress((const GLubyte*)"glXDestroyPixmap")) == NULL) || r;
+ r = ((glXDestroyWindow = (PFNGLXDESTROYWINDOWPROC)glewGetProcAddress((const GLubyte*)"glXDestroyWindow")) == NULL) || r;
+ r = ((glXGetCurrentReadDrawable = (PFNGLXGETCURRENTREADDRAWABLEPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentReadDrawable")) == NULL) || r;
+ r = ((glXGetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigAttrib")) == NULL) || r;
+ r = ((glXGetFBConfigs = (PFNGLXGETFBCONFIGSPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigs")) == NULL) || r;
+ r = ((glXGetSelectedEvent = (PFNGLXGETSELECTEDEVENTPROC)glewGetProcAddress((const GLubyte*)"glXGetSelectedEvent")) == NULL) || r;
+ r = ((glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)glewGetProcAddress((const GLubyte*)"glXGetVisualFromFBConfig")) == NULL) || r;
+ r = ((glXMakeContextCurrent = (PFNGLXMAKECONTEXTCURRENTPROC)glewGetProcAddress((const GLubyte*)"glXMakeContextCurrent")) == NULL) || r;
+ r = ((glXQueryContext = (PFNGLXQUERYCONTEXTPROC)glewGetProcAddress((const GLubyte*)"glXQueryContext")) == NULL) || r;
+ r = ((glXQueryDrawable = (PFNGLXQUERYDRAWABLEPROC)glewGetProcAddress((const GLubyte*)"glXQueryDrawable")) == NULL) || r;
+ r = ((glXSelectEvent = (PFNGLXSELECTEVENTPROC)glewGetProcAddress((const GLubyte*)"glXSelectEvent")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_VERSION_1_3 */
+
+#ifdef GLX_VERSION_1_4
+
+#endif /* GLX_VERSION_1_4 */
+
+#ifdef GLX_3DFX_multisample
+
+#endif /* GLX_3DFX_multisample */
+
+#ifdef GLX_ARB_create_context
+
+static GLboolean _glewInit_GLX_ARB_create_context (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glewGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_ARB_create_context */
+
+#ifdef GLX_ARB_fbconfig_float
+
+#endif /* GLX_ARB_fbconfig_float */
+
+#ifdef GLX_ARB_framebuffer_sRGB
+
+#endif /* GLX_ARB_framebuffer_sRGB */
+
+#ifdef GLX_ARB_get_proc_address
+
+#endif /* GLX_ARB_get_proc_address */
+
+#ifdef GLX_ARB_multisample
+
+#endif /* GLX_ARB_multisample */
+
+#ifdef GLX_ATI_pixel_format_float
+
+#endif /* GLX_ATI_pixel_format_float */
+
+#ifdef GLX_ATI_render_texture
+
+static GLboolean _glewInit_GLX_ATI_render_texture (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindTexImageATI = (PFNGLXBINDTEXIMAGEATIPROC)glewGetProcAddress((const GLubyte*)"glXBindTexImageATI")) == NULL) || r;
+ r = ((glXDrawableAttribATI = (PFNGLXDRAWABLEATTRIBATIPROC)glewGetProcAddress((const GLubyte*)"glXDrawableAttribATI")) == NULL) || r;
+ r = ((glXReleaseTexImageATI = (PFNGLXRELEASETEXIMAGEATIPROC)glewGetProcAddress((const GLubyte*)"glXReleaseTexImageATI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_ATI_render_texture */
+
+#ifdef GLX_EXT_fbconfig_packed_float
+
+#endif /* GLX_EXT_fbconfig_packed_float */
+
+#ifdef GLX_EXT_framebuffer_sRGB
+
+#endif /* GLX_EXT_framebuffer_sRGB */
+
+#ifdef GLX_EXT_import_context
+
+static GLboolean _glewInit_GLX_EXT_import_context (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXFreeContextEXT = (PFNGLXFREECONTEXTEXTPROC)glewGetProcAddress((const GLubyte*)"glXFreeContextEXT")) == NULL) || r;
+ r = ((glXGetContextIDEXT = (PFNGLXGETCONTEXTIDEXTPROC)glewGetProcAddress((const GLubyte*)"glXGetContextIDEXT")) == NULL) || r;
+ r = ((glXImportContextEXT = (PFNGLXIMPORTCONTEXTEXTPROC)glewGetProcAddress((const GLubyte*)"glXImportContextEXT")) == NULL) || r;
+ r = ((glXQueryContextInfoEXT = (PFNGLXQUERYCONTEXTINFOEXTPROC)glewGetProcAddress((const GLubyte*)"glXQueryContextInfoEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_EXT_import_context */
+
+#ifdef GLX_EXT_scene_marker
+
+#endif /* GLX_EXT_scene_marker */
+
+#ifdef GLX_EXT_texture_from_pixmap
+
+static GLboolean _glewInit_GLX_EXT_texture_from_pixmap (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glXBindTexImageEXT")) == NULL) || r;
+ r = ((glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glXReleaseTexImageEXT")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_EXT_texture_from_pixmap */
+
+#ifdef GLX_EXT_visual_info
+
+#endif /* GLX_EXT_visual_info */
+
+#ifdef GLX_EXT_visual_rating
+
+#endif /* GLX_EXT_visual_rating */
+
+#ifdef GLX_MESA_agp_offset
+
+static GLboolean _glewInit_GLX_MESA_agp_offset (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetAGPOffsetMESA = (PFNGLXGETAGPOFFSETMESAPROC)glewGetProcAddress((const GLubyte*)"glXGetAGPOffsetMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_agp_offset */
+
+#ifdef GLX_MESA_copy_sub_buffer
+
+static GLboolean _glewInit_GLX_MESA_copy_sub_buffer (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCopySubBufferMESA = (PFNGLXCOPYSUBBUFFERMESAPROC)glewGetProcAddress((const GLubyte*)"glXCopySubBufferMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_copy_sub_buffer */
+
+#ifdef GLX_MESA_pixmap_colormap
+
+static GLboolean _glewInit_GLX_MESA_pixmap_colormap (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCreateGLXPixmapMESA = (PFNGLXCREATEGLXPIXMAPMESAPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPixmapMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_pixmap_colormap */
+
+#ifdef GLX_MESA_release_buffers
+
+static GLboolean _glewInit_GLX_MESA_release_buffers (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXReleaseBuffersMESA = (PFNGLXRELEASEBUFFERSMESAPROC)glewGetProcAddress((const GLubyte*)"glXReleaseBuffersMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_release_buffers */
+
+#ifdef GLX_MESA_set_3dfx_mode
+
+static GLboolean _glewInit_GLX_MESA_set_3dfx_mode (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXSet3DfxModeMESA = (PFNGLXSET3DFXMODEMESAPROC)glewGetProcAddress((const GLubyte*)"glXSet3DfxModeMESA")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_MESA_set_3dfx_mode */
+
+#ifdef GLX_NV_float_buffer
+
+#endif /* GLX_NV_float_buffer */
+
+#ifdef GLX_NV_present_video
+
+static GLboolean _glewInit_GLX_NV_present_video (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindVideoDeviceNV = (PFNGLXBINDVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXBindVideoDeviceNV")) == NULL) || r;
+ r = ((glXEnumerateVideoDevicesNV = (PFNGLXENUMERATEVIDEODEVICESNVPROC)glewGetProcAddress((const GLubyte*)"glXEnumerateVideoDevicesNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_present_video */
+
+#ifdef GLX_NV_swap_group
+
+static GLboolean _glewInit_GLX_NV_swap_group (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindSwapBarrierNV = (PFNGLXBINDSWAPBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"glXBindSwapBarrierNV")) == NULL) || r;
+ r = ((glXJoinSwapGroupNV = (PFNGLXJOINSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"glXJoinSwapGroupNV")) == NULL) || r;
+ r = ((glXQueryFrameCountNV = (PFNGLXQUERYFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"glXQueryFrameCountNV")) == NULL) || r;
+ r = ((glXQueryMaxSwapGroupsNV = (PFNGLXQUERYMAXSWAPGROUPSNVPROC)glewGetProcAddress((const GLubyte*)"glXQueryMaxSwapGroupsNV")) == NULL) || r;
+ r = ((glXQuerySwapGroupNV = (PFNGLXQUERYSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"glXQuerySwapGroupNV")) == NULL) || r;
+ r = ((glXResetFrameCountNV = (PFNGLXRESETFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"glXResetFrameCountNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_swap_group */
+
+#ifdef GLX_NV_vertex_array_range
+
+static GLboolean _glewInit_GLX_NV_vertex_array_range (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXAllocateMemoryNV = (PFNGLXALLOCATEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"glXAllocateMemoryNV")) == NULL) || r;
+ r = ((glXFreeMemoryNV = (PFNGLXFREEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"glXFreeMemoryNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_vertex_array_range */
+
+#ifdef GLX_NV_video_output
+
+static GLboolean _glewInit_GLX_NV_video_output (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindVideoImageNV = (PFNGLXBINDVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"glXBindVideoImageNV")) == NULL) || r;
+ r = ((glXGetVideoDeviceNV = (PFNGLXGETVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoDeviceNV")) == NULL) || r;
+ r = ((glXGetVideoInfoNV = (PFNGLXGETVIDEOINFONVPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoInfoNV")) == NULL) || r;
+ r = ((glXReleaseVideoDeviceNV = (PFNGLXRELEASEVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXReleaseVideoDeviceNV")) == NULL) || r;
+ r = ((glXReleaseVideoImageNV = (PFNGLXRELEASEVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"glXReleaseVideoImageNV")) == NULL) || r;
+ r = ((glXSendPbufferToVideoNV = (PFNGLXSENDPBUFFERTOVIDEONVPROC)glewGetProcAddress((const GLubyte*)"glXSendPbufferToVideoNV")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_NV_video_output */
+
+#ifdef GLX_OML_swap_method
+
+#endif /* GLX_OML_swap_method */
+
+#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#include <inttypes.h>
+
+static GLboolean _glewInit_GLX_OML_sync_control (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetMscRateOML = (PFNGLXGETMSCRATEOMLPROC)glewGetProcAddress((const GLubyte*)"glXGetMscRateOML")) == NULL) || r;
+ r = ((glXGetSyncValuesOML = (PFNGLXGETSYNCVALUESOMLPROC)glewGetProcAddress((const GLubyte*)"glXGetSyncValuesOML")) == NULL) || r;
+ r = ((glXSwapBuffersMscOML = (PFNGLXSWAPBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"glXSwapBuffersMscOML")) == NULL) || r;
+ r = ((glXWaitForMscOML = (PFNGLXWAITFORMSCOMLPROC)glewGetProcAddress((const GLubyte*)"glXWaitForMscOML")) == NULL) || r;
+ r = ((glXWaitForSbcOML = (PFNGLXWAITFORSBCOMLPROC)glewGetProcAddress((const GLubyte*)"glXWaitForSbcOML")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_OML_sync_control */
+
+#ifdef GLX_SGIS_blended_overlay
+
+#endif /* GLX_SGIS_blended_overlay */
+
+#ifdef GLX_SGIS_color_range
+
+#endif /* GLX_SGIS_color_range */
+
+#ifdef GLX_SGIS_multisample
+
+#endif /* GLX_SGIS_multisample */
+
+#ifdef GLX_SGIS_shared_multisample
+
+#endif /* GLX_SGIS_shared_multisample */
+
+#ifdef GLX_SGIX_fbconfig
+
+static GLboolean _glewInit_GLX_SGIX_fbconfig (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChooseFBConfigSGIX")) == NULL) || r;
+ r = ((glXCreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateContextWithConfigSGIX")) == NULL) || r;
+ r = ((glXCreateGLXPixmapWithConfigSGIX = (PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPixmapWithConfigSGIX")) == NULL) || r;
+ r = ((glXGetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigAttribSGIX")) == NULL) || r;
+ r = ((glXGetFBConfigFromVisualSGIX = (PFNGLXGETFBCONFIGFROMVISUALSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigFromVisualSGIX")) == NULL) || r;
+ r = ((glXGetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetVisualFromFBConfigSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_fbconfig */
+
+#ifdef GLX_SGIX_hyperpipe
+
+static GLboolean _glewInit_GLX_SGIX_hyperpipe (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindHyperpipeSGIX = (PFNGLXBINDHYPERPIPESGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindHyperpipeSGIX")) == NULL) || r;
+ r = ((glXDestroyHyperpipeConfigSGIX = (PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXDestroyHyperpipeConfigSGIX")) == NULL) || r;
+ r = ((glXHyperpipeAttribSGIX = (PFNGLXHYPERPIPEATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXHyperpipeAttribSGIX")) == NULL) || r;
+ r = ((glXHyperpipeConfigSGIX = (PFNGLXHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXHyperpipeConfigSGIX")) == NULL) || r;
+ r = ((glXQueryHyperpipeAttribSGIX = (PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeAttribSGIX")) == NULL) || r;
+ r = ((glXQueryHyperpipeBestAttribSGIX = (PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeBestAttribSGIX")) == NULL) || r;
+ r = ((glXQueryHyperpipeConfigSGIX = (PFNGLXQUERYHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeConfigSGIX")) == NULL) || r;
+ r = ((glXQueryHyperpipeNetworkSGIX = (PFNGLXQUERYHYPERPIPENETWORKSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeNetworkSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_hyperpipe */
+
+#ifdef GLX_SGIX_pbuffer
+
+static GLboolean _glewInit_GLX_SGIX_pbuffer (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCreateGLXPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPbufferSGIX")) == NULL) || r;
+ r = ((glXDestroyGLXPbufferSGIX = (PFNGLXDESTROYGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXDestroyGLXPbufferSGIX")) == NULL) || r;
+ r = ((glXGetSelectedEventSGIX = (PFNGLXGETSELECTEDEVENTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetSelectedEventSGIX")) == NULL) || r;
+ r = ((glXQueryGLXPbufferSGIX = (PFNGLXQUERYGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryGLXPbufferSGIX")) == NULL) || r;
+ r = ((glXSelectEventSGIX = (PFNGLXSELECTEVENTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXSelectEventSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_pbuffer */
+
+#ifdef GLX_SGIX_swap_barrier
+
+static GLboolean _glewInit_GLX_SGIX_swap_barrier (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindSwapBarrierSGIX = (PFNGLXBINDSWAPBARRIERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindSwapBarrierSGIX")) == NULL) || r;
+ r = ((glXQueryMaxSwapBarriersSGIX = (PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryMaxSwapBarriersSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_swap_barrier */
+
+#ifdef GLX_SGIX_swap_group
+
+static GLboolean _glewInit_GLX_SGIX_swap_group (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXJoinSwapGroupSGIX = (PFNGLXJOINSWAPGROUPSGIXPROC)glewGetProcAddress((const GLubyte*)"glXJoinSwapGroupSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_swap_group */
+
+#ifdef GLX_SGIX_video_resize
+
+static GLboolean _glewInit_GLX_SGIX_video_resize (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXBindChannelToWindowSGIX = (PFNGLXBINDCHANNELTOWINDOWSGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindChannelToWindowSGIX")) == NULL) || r;
+ r = ((glXChannelRectSGIX = (PFNGLXCHANNELRECTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChannelRectSGIX")) == NULL) || r;
+ r = ((glXChannelRectSyncSGIX = (PFNGLXCHANNELRECTSYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChannelRectSyncSGIX")) == NULL) || r;
+ r = ((glXQueryChannelDeltasSGIX = (PFNGLXQUERYCHANNELDELTASSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryChannelDeltasSGIX")) == NULL) || r;
+ r = ((glXQueryChannelRectSGIX = (PFNGLXQUERYCHANNELRECTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryChannelRectSGIX")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGIX_video_resize */
+
+#ifdef GLX_SGIX_visual_select_group
+
+#endif /* GLX_SGIX_visual_select_group */
+
+#ifdef GLX_SGI_cushion
+
+static GLboolean _glewInit_GLX_SGI_cushion (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXCushionSGI = (PFNGLXCUSHIONSGIPROC)glewGetProcAddress((const GLubyte*)"glXCushionSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGI_cushion */
+
+#ifdef GLX_SGI_make_current_read
+
+static GLboolean _glewInit_GLX_SGI_make_current_read (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetCurrentReadDrawableSGI = (PFNGLXGETCURRENTREADDRAWABLESGIPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentReadDrawableSGI")) == NULL) || r;
+ r = ((glXMakeCurrentReadSGI = (PFNGLXMAKECURRENTREADSGIPROC)glewGetProcAddress((const GLubyte*)"glXMakeCurrentReadSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGI_make_current_read */
+
+#ifdef GLX_SGI_swap_control
+
+static GLboolean _glewInit_GLX_SGI_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glewGetProcAddress((const GLubyte*)"glXSwapIntervalSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGI_swap_control */
+
+#ifdef GLX_SGI_video_sync
+
+static GLboolean _glewInit_GLX_SGI_video_sync (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoSyncSGI")) == NULL) || r;
+ r = ((glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)glewGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SGI_video_sync */
+
+#ifdef GLX_SUN_get_transparent_index
+
+static GLboolean _glewInit_GLX_SUN_get_transparent_index (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetTransparentIndexSUN = (PFNGLXGETTRANSPARENTINDEXSUNPROC)glewGetProcAddress((const GLubyte*)"glXGetTransparentIndexSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SUN_get_transparent_index */
+
+#ifdef GLX_SUN_video_resize
+
+static GLboolean _glewInit_GLX_SUN_video_resize (GLXEW_CONTEXT_ARG_DEF_INIT)
+{
+ GLboolean r = GL_FALSE;
+
+ r = ((glXGetVideoResizeSUN = (PFNGLXGETVIDEORESIZESUNPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoResizeSUN")) == NULL) || r;
+ r = ((glXVideoResizeSUN = (PFNGLXVIDEORESIZESUNPROC)glewGetProcAddress((const GLubyte*)"glXVideoResizeSUN")) == NULL) || r;
+
+ return r;
+}
+
+#endif /* GLX_SUN_video_resize */
+
+/* ------------------------------------------------------------------------ */
+
+GLboolean glxewGetExtension (const char* name)
+{
+ GLubyte* p;
+ GLubyte* end;
+ GLuint len = _glewStrLen((const GLubyte*)name);
+/* if (glXQueryExtensionsString == NULL || glXGetCurrentDisplay == NULL) return GL_FALSE; */
+/* p = (GLubyte*)glXQueryExtensionsString(glXGetCurrentDisplay(), DefaultScreen(glXGetCurrentDisplay())); */
+ if (glXGetClientString == NULL || glXGetCurrentDisplay == NULL) return GL_FALSE;
+ p = (GLubyte*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS);
+ if (0 == p) return GL_FALSE;
+ end = p + _glewStrLen(p);
+ while (p < end)
+ {
+ GLuint n = _glewStrCLen(p, ' ');
+ if (len == n && _glewStrSame((const GLubyte*)name, p, n)) return GL_TRUE;
+ p += n+1;
+ }
+ return GL_FALSE;
+}
+
+GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST)
+{
+ int major, minor;
+ /* initialize core GLX 1.2 */
+ if (_glewInit_GLX_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT)) return GLEW_ERROR_GLX_VERSION_11_ONLY;
+ /* initialize flags */
+ CONST_CAST(GLXEW_VERSION_1_0) = GL_TRUE;
+ CONST_CAST(GLXEW_VERSION_1_1) = GL_TRUE;
+ CONST_CAST(GLXEW_VERSION_1_2) = GL_TRUE;
+ CONST_CAST(GLXEW_VERSION_1_3) = GL_TRUE;
+ CONST_CAST(GLXEW_VERSION_1_4) = GL_TRUE;
+ /* query GLX version */
+ glXQueryVersion(glXGetCurrentDisplay(), &major, &minor);
+ if (major == 1 && minor <= 3)
+ {
+ switch (minor)
+ {
+ case 3:
+ CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE;
+ break;
+ case 2:
+ CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE;
+ CONST_CAST(GLXEW_VERSION_1_3) = GL_FALSE;
+ break;
+ default:
+ return GLEW_ERROR_GLX_VERSION_11_ONLY;
+ break;
+ }
+ }
+ /* initialize extensions */
+#ifdef GLX_VERSION_1_3
+ if (glewExperimental || GLXEW_VERSION_1_3) CONST_CAST(GLXEW_VERSION_1_3) = !_glewInit_GLX_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_VERSION_1_3 */
+#ifdef GLX_3DFX_multisample
+ CONST_CAST(GLXEW_3DFX_multisample) = glxewGetExtension("GLX_3DFX_multisample");
+#endif /* GLX_3DFX_multisample */
+#ifdef GLX_ARB_create_context
+ CONST_CAST(GLXEW_ARB_create_context) = glxewGetExtension("GLX_ARB_create_context");
+ if (glewExperimental || GLXEW_ARB_create_context) CONST_CAST(GLXEW_ARB_create_context) = !_glewInit_GLX_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_ARB_create_context */
+#ifdef GLX_ARB_fbconfig_float
+ CONST_CAST(GLXEW_ARB_fbconfig_float) = glxewGetExtension("GLX_ARB_fbconfig_float");
+#endif /* GLX_ARB_fbconfig_float */
+#ifdef GLX_ARB_framebuffer_sRGB
+ CONST_CAST(GLXEW_ARB_framebuffer_sRGB) = glxewGetExtension("GLX_ARB_framebuffer_sRGB");
+#endif /* GLX_ARB_framebuffer_sRGB */
+#ifdef GLX_ARB_get_proc_address
+ CONST_CAST(GLXEW_ARB_get_proc_address) = glxewGetExtension("GLX_ARB_get_proc_address");
+#endif /* GLX_ARB_get_proc_address */
+#ifdef GLX_ARB_multisample
+ CONST_CAST(GLXEW_ARB_multisample) = glxewGetExtension("GLX_ARB_multisample");
+#endif /* GLX_ARB_multisample */
+#ifdef GLX_ATI_pixel_format_float
+ CONST_CAST(GLXEW_ATI_pixel_format_float) = glxewGetExtension("GLX_ATI_pixel_format_float");
+#endif /* GLX_ATI_pixel_format_float */
+#ifdef GLX_ATI_render_texture
+ CONST_CAST(GLXEW_ATI_render_texture) = glxewGetExtension("GLX_ATI_render_texture");
+ if (glewExperimental || GLXEW_ATI_render_texture) CONST_CAST(GLXEW_ATI_render_texture) = !_glewInit_GLX_ATI_render_texture(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_ATI_render_texture */
+#ifdef GLX_EXT_fbconfig_packed_float
+ CONST_CAST(GLXEW_EXT_fbconfig_packed_float) = glxewGetExtension("GLX_EXT_fbconfig_packed_float");
+#endif /* GLX_EXT_fbconfig_packed_float */
+#ifdef GLX_EXT_framebuffer_sRGB
+ CONST_CAST(GLXEW_EXT_framebuffer_sRGB) = glxewGetExtension("GLX_EXT_framebuffer_sRGB");
+#endif /* GLX_EXT_framebuffer_sRGB */
+#ifdef GLX_EXT_import_context
+ CONST_CAST(GLXEW_EXT_import_context) = glxewGetExtension("GLX_EXT_import_context");
+ if (glewExperimental || GLXEW_EXT_import_context) CONST_CAST(GLXEW_EXT_import_context) = !_glewInit_GLX_EXT_import_context(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_EXT_import_context */
+#ifdef GLX_EXT_scene_marker
+ CONST_CAST(GLXEW_EXT_scene_marker) = glxewGetExtension("GLX_EXT_scene_marker");
+#endif /* GLX_EXT_scene_marker */
+#ifdef GLX_EXT_texture_from_pixmap
+ CONST_CAST(GLXEW_EXT_texture_from_pixmap) = glxewGetExtension("GLX_EXT_texture_from_pixmap");
+ if (glewExperimental || GLXEW_EXT_texture_from_pixmap) CONST_CAST(GLXEW_EXT_texture_from_pixmap) = !_glewInit_GLX_EXT_texture_from_pixmap(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_EXT_texture_from_pixmap */
+#ifdef GLX_EXT_visual_info
+ CONST_CAST(GLXEW_EXT_visual_info) = glxewGetExtension("GLX_EXT_visual_info");
+#endif /* GLX_EXT_visual_info */
+#ifdef GLX_EXT_visual_rating
+ CONST_CAST(GLXEW_EXT_visual_rating) = glxewGetExtension("GLX_EXT_visual_rating");
+#endif /* GLX_EXT_visual_rating */
+#ifdef GLX_MESA_agp_offset
+ CONST_CAST(GLXEW_MESA_agp_offset) = glxewGetExtension("GLX_MESA_agp_offset");
+ if (glewExperimental || GLXEW_MESA_agp_offset) CONST_CAST(GLXEW_MESA_agp_offset) = !_glewInit_GLX_MESA_agp_offset(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_agp_offset */
+#ifdef GLX_MESA_copy_sub_buffer
+ CONST_CAST(GLXEW_MESA_copy_sub_buffer) = glxewGetExtension("GLX_MESA_copy_sub_buffer");
+ if (glewExperimental || GLXEW_MESA_copy_sub_buffer) CONST_CAST(GLXEW_MESA_copy_sub_buffer) = !_glewInit_GLX_MESA_copy_sub_buffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_copy_sub_buffer */
+#ifdef GLX_MESA_pixmap_colormap
+ CONST_CAST(GLXEW_MESA_pixmap_colormap) = glxewGetExtension("GLX_MESA_pixmap_colormap");
+ if (glewExperimental || GLXEW_MESA_pixmap_colormap) CONST_CAST(GLXEW_MESA_pixmap_colormap) = !_glewInit_GLX_MESA_pixmap_colormap(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_pixmap_colormap */
+#ifdef GLX_MESA_release_buffers
+ CONST_CAST(GLXEW_MESA_release_buffers) = glxewGetExtension("GLX_MESA_release_buffers");
+ if (glewExperimental || GLXEW_MESA_release_buffers) CONST_CAST(GLXEW_MESA_release_buffers) = !_glewInit_GLX_MESA_release_buffers(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_release_buffers */
+#ifdef GLX_MESA_set_3dfx_mode
+ CONST_CAST(GLXEW_MESA_set_3dfx_mode) = glxewGetExtension("GLX_MESA_set_3dfx_mode");
+ if (glewExperimental || GLXEW_MESA_set_3dfx_mode) CONST_CAST(GLXEW_MESA_set_3dfx_mode) = !_glewInit_GLX_MESA_set_3dfx_mode(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_MESA_set_3dfx_mode */
+#ifdef GLX_NV_float_buffer
+ CONST_CAST(GLXEW_NV_float_buffer) = glxewGetExtension("GLX_NV_float_buffer");
+#endif /* GLX_NV_float_buffer */
+#ifdef GLX_NV_present_video
+ CONST_CAST(GLXEW_NV_present_video) = glxewGetExtension("GLX_NV_present_video");
+ if (glewExperimental || GLXEW_NV_present_video) CONST_CAST(GLXEW_NV_present_video) = !_glewInit_GLX_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_present_video */
+#ifdef GLX_NV_swap_group
+ CONST_CAST(GLXEW_NV_swap_group) = glxewGetExtension("GLX_NV_swap_group");
+ if (glewExperimental || GLXEW_NV_swap_group) CONST_CAST(GLXEW_NV_swap_group) = !_glewInit_GLX_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_swap_group */
+#ifdef GLX_NV_vertex_array_range
+ CONST_CAST(GLXEW_NV_vertex_array_range) = glxewGetExtension("GLX_NV_vertex_array_range");
+ if (glewExperimental || GLXEW_NV_vertex_array_range) CONST_CAST(GLXEW_NV_vertex_array_range) = !_glewInit_GLX_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_vertex_array_range */
+#ifdef GLX_NV_video_output
+ CONST_CAST(GLXEW_NV_video_output) = glxewGetExtension("GLX_NV_video_output");
+ if (glewExperimental || GLXEW_NV_video_output) CONST_CAST(GLXEW_NV_video_output) = !_glewInit_GLX_NV_video_output(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_NV_video_output */
+#ifdef GLX_OML_swap_method
+ CONST_CAST(GLXEW_OML_swap_method) = glxewGetExtension("GLX_OML_swap_method");
+#endif /* GLX_OML_swap_method */
+#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#include <inttypes.h>
+ CONST_CAST(GLXEW_OML_sync_control) = glxewGetExtension("GLX_OML_sync_control");
+ if (glewExperimental || GLXEW_OML_sync_control) CONST_CAST(GLXEW_OML_sync_control) = !_glewInit_GLX_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_OML_sync_control */
+#ifdef GLX_SGIS_blended_overlay
+ CONST_CAST(GLXEW_SGIS_blended_overlay) = glxewGetExtension("GLX_SGIS_blended_overlay");
+#endif /* GLX_SGIS_blended_overlay */
+#ifdef GLX_SGIS_color_range
+ CONST_CAST(GLXEW_SGIS_color_range) = glxewGetExtension("GLX_SGIS_color_range");
+#endif /* GLX_SGIS_color_range */
+#ifdef GLX_SGIS_multisample
+ CONST_CAST(GLXEW_SGIS_multisample) = glxewGetExtension("GLX_SGIS_multisample");
+#endif /* GLX_SGIS_multisample */
+#ifdef GLX_SGIS_shared_multisample
+ CONST_CAST(GLXEW_SGIS_shared_multisample) = glxewGetExtension("GLX_SGIS_shared_multisample");
+#endif /* GLX_SGIS_shared_multisample */
+#ifdef GLX_SGIX_fbconfig
+ CONST_CAST(GLXEW_SGIX_fbconfig) = glxewGetExtension("GLX_SGIX_fbconfig");
+ if (glewExperimental || GLXEW_SGIX_fbconfig) CONST_CAST(GLXEW_SGIX_fbconfig) = !_glewInit_GLX_SGIX_fbconfig(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_fbconfig */
+#ifdef GLX_SGIX_hyperpipe
+ CONST_CAST(GLXEW_SGIX_hyperpipe) = glxewGetExtension("GLX_SGIX_hyperpipe");
+ if (glewExperimental || GLXEW_SGIX_hyperpipe) CONST_CAST(GLXEW_SGIX_hyperpipe) = !_glewInit_GLX_SGIX_hyperpipe(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_hyperpipe */
+#ifdef GLX_SGIX_pbuffer
+ CONST_CAST(GLXEW_SGIX_pbuffer) = glxewGetExtension("GLX_SGIX_pbuffer");
+ if (glewExperimental || GLXEW_SGIX_pbuffer) CONST_CAST(GLXEW_SGIX_pbuffer) = !_glewInit_GLX_SGIX_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_pbuffer */
+#ifdef GLX_SGIX_swap_barrier
+ CONST_CAST(GLXEW_SGIX_swap_barrier) = glxewGetExtension("GLX_SGIX_swap_barrier");
+ if (glewExperimental || GLXEW_SGIX_swap_barrier) CONST_CAST(GLXEW_SGIX_swap_barrier) = !_glewInit_GLX_SGIX_swap_barrier(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_swap_barrier */
+#ifdef GLX_SGIX_swap_group
+ CONST_CAST(GLXEW_SGIX_swap_group) = glxewGetExtension("GLX_SGIX_swap_group");
+ if (glewExperimental || GLXEW_SGIX_swap_group) CONST_CAST(GLXEW_SGIX_swap_group) = !_glewInit_GLX_SGIX_swap_group(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_swap_group */
+#ifdef GLX_SGIX_video_resize
+ CONST_CAST(GLXEW_SGIX_video_resize) = glxewGetExtension("GLX_SGIX_video_resize");
+ if (glewExperimental || GLXEW_SGIX_video_resize) CONST_CAST(GLXEW_SGIX_video_resize) = !_glewInit_GLX_SGIX_video_resize(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGIX_video_resize */
+#ifdef GLX_SGIX_visual_select_group
+ CONST_CAST(GLXEW_SGIX_visual_select_group) = glxewGetExtension("GLX_SGIX_visual_select_group");
+#endif /* GLX_SGIX_visual_select_group */
+#ifdef GLX_SGI_cushion
+ CONST_CAST(GLXEW_SGI_cushion) = glxewGetExtension("GLX_SGI_cushion");
+ if (glewExperimental || GLXEW_SGI_cushion) CONST_CAST(GLXEW_SGI_cushion) = !_glewInit_GLX_SGI_cushion(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGI_cushion */
+#ifdef GLX_SGI_make_current_read
+ CONST_CAST(GLXEW_SGI_make_current_read) = glxewGetExtension("GLX_SGI_make_current_read");
+ if (glewExperimental || GLXEW_SGI_make_current_read) CONST_CAST(GLXEW_SGI_make_current_read) = !_glewInit_GLX_SGI_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGI_make_current_read */
+#ifdef GLX_SGI_swap_control
+ CONST_CAST(GLXEW_SGI_swap_control) = glxewGetExtension("GLX_SGI_swap_control");
+ if (glewExperimental || GLXEW_SGI_swap_control) CONST_CAST(GLXEW_SGI_swap_control) = !_glewInit_GLX_SGI_swap_control(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGI_swap_control */
+#ifdef GLX_SGI_video_sync
+ CONST_CAST(GLXEW_SGI_video_sync) = glxewGetExtension("GLX_SGI_video_sync");
+ if (glewExperimental || GLXEW_SGI_video_sync) CONST_CAST(GLXEW_SGI_video_sync) = !_glewInit_GLX_SGI_video_sync(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SGI_video_sync */
+#ifdef GLX_SUN_get_transparent_index
+ CONST_CAST(GLXEW_SUN_get_transparent_index) = glxewGetExtension("GLX_SUN_get_transparent_index");
+ if (glewExperimental || GLXEW_SUN_get_transparent_index) CONST_CAST(GLXEW_SUN_get_transparent_index) = !_glewInit_GLX_SUN_get_transparent_index(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SUN_get_transparent_index */
+#ifdef GLX_SUN_video_resize
+ CONST_CAST(GLXEW_SUN_video_resize) = glxewGetExtension("GLX_SUN_video_resize");
+ if (glewExperimental || GLXEW_SUN_video_resize) CONST_CAST(GLXEW_SUN_video_resize) = !_glewInit_GLX_SUN_video_resize(GLEW_CONTEXT_ARG_VAR_INIT);
+#endif /* GLX_SUN_video_resize */
+
+ return GLEW_OK;
+}
+
+#endif /* !__APPLE__ || GLEW_APPLE_GLX */
+
+/* ------------------------------------------------------------------------ */
+
+const GLubyte* glewGetErrorString (GLenum error)
+{
+ static const GLubyte* _glewErrorString[] =
+ {
+ (const GLubyte*)"No error",
+ (const GLubyte*)"Missing GL version",
+ (const GLubyte*)"GL 1.1 and up are not supported",
+ (const GLubyte*)"GLX 1.2 and up are not supported",
+ (const GLubyte*)"Unknown error"
+ };
+ const int max_error = sizeof(_glewErrorString)/sizeof(*_glewErrorString) - 1;
+ return _glewErrorString[(int)error > max_error ? max_error : (int)error];
+}
+
+const GLubyte* glewGetString (GLenum name)
+{
+ static const GLubyte* _glewString[] =
+ {
+ (const GLubyte*)NULL,
+ (const GLubyte*)"1.5.1",
+ (const GLubyte*)"1",
+ (const GLubyte*)"5",
+ (const GLubyte*)"1"
+ };
+ const int max_string = sizeof(_glewString)/sizeof(*_glewString) - 1;
+ return _glewString[(int)name > max_string ? 0 : (int)name];
+}
+
+/* ------------------------------------------------------------------------ */
+
+GLboolean glewExperimental = GL_FALSE;
+
+#if !defined(GLEW_MX)
+
+#if defined(_WIN32)
+extern GLenum wglewContextInit (void);
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */
+extern GLenum glxewContextInit (void);
+#endif /* _WIN32 */
+
+GLenum glewInit ()
+{
+ GLenum r;
+ if ( (r = glewContextInit()) ) return r;
+#if defined(_WIN32)
+ return wglewContextInit();
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */
+ return glxewContextInit();
+#else
+ return r;
+#endif /* _WIN32 */
+}
+
+#endif /* !GLEW_MX */
+#ifdef GLEW_MX
+GLboolean glewContextIsSupported (GLEWContext* ctx, const char* name)
+#else
+GLboolean glewIsSupported (const char* name)
+#endif
+{
+ GLubyte* pos = (GLubyte*)name;
+ GLuint len = _glewStrLen(pos);
+ GLboolean ret = GL_TRUE;
+ while (ret && len > 0)
+ {
+ if (_glewStrSame1(&pos, &len, (const GLubyte*)"GL_", 3))
+ {
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"VERSION_", 8))
+ {
+#ifdef GL_VERSION_1_2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2", 3))
+ {
+ ret = GLEW_VERSION_1_2;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_1_3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_3", 3))
+ {
+ ret = GLEW_VERSION_1_3;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_1_4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_4", 3))
+ {
+ ret = GLEW_VERSION_1_4;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_1_5
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_5", 3))
+ {
+ ret = GLEW_VERSION_1_5;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_2_0
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"2_0", 3))
+ {
+ ret = GLEW_VERSION_2_0;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_2_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"2_1", 3))
+ {
+ ret = GLEW_VERSION_2_1;
+ continue;
+ }
+#endif
+#ifdef GL_VERSION_3_0
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"3_0", 3))
+ {
+ ret = GLEW_VERSION_3_0;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5))
+ {
+#ifdef GL_3DFX_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLEW_3DFX_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_3DFX_tbuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"tbuffer", 7))
+ {
+ ret = GLEW_3DFX_tbuffer;
+ continue;
+ }
+#endif
+#ifdef GL_3DFX_texture_compression_FXT1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_FXT1", 24))
+ {
+ ret = GLEW_3DFX_texture_compression_FXT1;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"APPLE_", 6))
+ {
+#ifdef GL_APPLE_client_storage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"client_storage", 14))
+ {
+ ret = GLEW_APPLE_client_storage;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_element_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"element_array", 13))
+ {
+ ret = GLEW_APPLE_element_array;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_fence
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fence", 5))
+ {
+ ret = GLEW_APPLE_fence;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_float_pixels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_pixels", 12))
+ {
+ ret = GLEW_APPLE_float_pixels;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_flush_buffer_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"flush_buffer_range", 18))
+ {
+ ret = GLEW_APPLE_flush_buffer_range;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_pixel_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer", 12))
+ {
+ ret = GLEW_APPLE_pixel_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_specular_vector
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"specular_vector", 15))
+ {
+ ret = GLEW_APPLE_specular_vector;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_texture_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_range", 13))
+ {
+ ret = GLEW_APPLE_texture_range;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_transform_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_hint", 14))
+ {
+ ret = GLEW_APPLE_transform_hint;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_vertex_array_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19))
+ {
+ ret = GLEW_APPLE_vertex_array_object;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_vertex_array_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18))
+ {
+ ret = GLEW_APPLE_vertex_array_range;
+ continue;
+ }
+#endif
+#ifdef GL_APPLE_ycbcr_422
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycbcr_422", 9))
+ {
+ ret = GLEW_APPLE_ycbcr_422;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4))
+ {
+#ifdef GL_ARB_color_buffer_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_buffer_float", 18))
+ {
+ ret = GLEW_ARB_color_buffer_float;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_depth_buffer_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_buffer_float", 18))
+ {
+ ret = GLEW_ARB_depth_buffer_float;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_depth_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13))
+ {
+ ret = GLEW_ARB_depth_texture;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_draw_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers", 12))
+ {
+ ret = GLEW_ARB_draw_buffers;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_draw_instanced
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_instanced", 14))
+ {
+ ret = GLEW_ARB_draw_instanced;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_fragment_program
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16))
+ {
+ ret = GLEW_ARB_fragment_program;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_fragment_program_shadow
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program_shadow", 23))
+ {
+ ret = GLEW_ARB_fragment_program_shadow;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_fragment_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_shader", 15))
+ {
+ ret = GLEW_ARB_fragment_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_framebuffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18))
+ {
+ ret = GLEW_ARB_framebuffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = GLEW_ARB_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_geometry_shader4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16))
+ {
+ ret = GLEW_ARB_geometry_shader4;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_half_float_pixel
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float_pixel", 16))
+ {
+ ret = GLEW_ARB_half_float_pixel;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_half_float_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float_vertex", 17))
+ {
+ ret = GLEW_ARB_half_float_vertex;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_imaging
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"imaging", 7))
+ {
+ ret = GLEW_ARB_imaging;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_instanced_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"instanced_arrays", 16))
+ {
+ ret = GLEW_ARB_instanced_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_map_buffer_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_buffer_range", 16))
+ {
+ ret = GLEW_ARB_map_buffer_range;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_matrix_palette
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"matrix_palette", 14))
+ {
+ ret = GLEW_ARB_matrix_palette;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLEW_ARB_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_multitexture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multitexture", 12))
+ {
+ ret = GLEW_ARB_multitexture;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_occlusion_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query", 15))
+ {
+ ret = GLEW_ARB_occlusion_query;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_pixel_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer_object", 19))
+ {
+ ret = GLEW_ARB_pixel_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_point_parameters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_parameters", 16))
+ {
+ ret = GLEW_ARB_point_parameters;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_point_sprite
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprite", 12))
+ {
+ ret = GLEW_ARB_point_sprite;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shader_objects
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_objects", 14))
+ {
+ ret = GLEW_ARB_shader_objects;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shading_language_100
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_100", 20))
+ {
+ ret = GLEW_ARB_shading_language_100;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shadow
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow", 6))
+ {
+ ret = GLEW_ARB_shadow;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_shadow_ambient
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_ambient", 14))
+ {
+ ret = GLEW_ARB_shadow_ambient;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_border_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_border_clamp", 20))
+ {
+ ret = GLEW_ARB_texture_border_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_object", 21))
+ {
+ ret = GLEW_ARB_texture_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_compression
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression", 19))
+ {
+ ret = GLEW_ARB_texture_compression;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_compression_rgtc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_rgtc", 24))
+ {
+ ret = GLEW_ARB_texture_compression_rgtc;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_cube_map
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map", 16))
+ {
+ ret = GLEW_ARB_texture_cube_map;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_env_add
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_add", 15))
+ {
+ ret = GLEW_ARB_texture_env_add;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_env_combine
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine", 19))
+ {
+ ret = GLEW_ARB_texture_env_combine;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_env_crossbar
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_crossbar", 20))
+ {
+ ret = GLEW_ARB_texture_env_crossbar;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_env_dot3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_dot3", 16))
+ {
+ ret = GLEW_ARB_texture_env_dot3;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_float", 13))
+ {
+ ret = GLEW_ARB_texture_float;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_mirrored_repeat
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23))
+ {
+ ret = GLEW_ARB_texture_mirrored_repeat;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_non_power_of_two
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_non_power_of_two", 24))
+ {
+ ret = GLEW_ARB_texture_non_power_of_two;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17))
+ {
+ ret = GLEW_ARB_texture_rectangle;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_texture_rg
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rg", 10))
+ {
+ ret = GLEW_ARB_texture_rg;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_transpose_matrix
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transpose_matrix", 16))
+ {
+ ret = GLEW_ARB_transpose_matrix;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_array_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19))
+ {
+ ret = GLEW_ARB_vertex_array_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_blend
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_blend", 12))
+ {
+ ret = GLEW_ARB_vertex_blend;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_object", 20))
+ {
+ ret = GLEW_ARB_vertex_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_program
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program", 14))
+ {
+ ret = GLEW_ARB_vertex_program;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_vertex_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader", 13))
+ {
+ ret = GLEW_ARB_vertex_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ARB_window_pos
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"window_pos", 10))
+ {
+ ret = GLEW_ARB_window_pos;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATIX_", 5))
+ {
+#ifdef GL_ATIX_point_sprites
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprites", 13))
+ {
+ ret = GLEW_ATIX_point_sprites;
+ continue;
+ }
+#endif
+#ifdef GL_ATIX_texture_env_combine3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine3", 20))
+ {
+ ret = GLEW_ATIX_texture_env_combine3;
+ continue;
+ }
+#endif
+#ifdef GL_ATIX_texture_env_route
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_route", 17))
+ {
+ ret = GLEW_ATIX_texture_env_route;
+ continue;
+ }
+#endif
+#ifdef GL_ATIX_vertex_shader_output_point_size
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_output_point_size", 31))
+ {
+ ret = GLEW_ATIX_vertex_shader_output_point_size;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4))
+ {
+#ifdef GL_ATI_draw_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers", 12))
+ {
+ ret = GLEW_ATI_draw_buffers;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_element_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"element_array", 13))
+ {
+ ret = GLEW_ATI_element_array;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_envmap_bumpmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"envmap_bumpmap", 14))
+ {
+ ret = GLEW_ATI_envmap_bumpmap;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_fragment_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_shader", 15))
+ {
+ ret = GLEW_ATI_fragment_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_map_object_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_object_buffer", 17))
+ {
+ ret = GLEW_ATI_map_object_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_pn_triangles
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pn_triangles", 12))
+ {
+ ret = GLEW_ATI_pn_triangles;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_separate_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_stencil", 16))
+ {
+ ret = GLEW_ATI_separate_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_shader_texture_lod
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_texture_lod", 18))
+ {
+ ret = GLEW_ATI_shader_texture_lod;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_text_fragment_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"text_fragment_shader", 20))
+ {
+ ret = GLEW_ATI_text_fragment_shader;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_texture_compression_3dc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_3dc", 23))
+ {
+ ret = GLEW_ATI_texture_compression_3dc;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_texture_env_combine3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine3", 20))
+ {
+ ret = GLEW_ATI_texture_env_combine3;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_texture_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_float", 13))
+ {
+ ret = GLEW_ATI_texture_float;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_texture_mirror_once
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_once", 19))
+ {
+ ret = GLEW_ATI_texture_mirror_once;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_vertex_array_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19))
+ {
+ ret = GLEW_ATI_vertex_array_object;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_vertex_attrib_array_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_array_object", 26))
+ {
+ ret = GLEW_ATI_vertex_attrib_array_object;
+ continue;
+ }
+#endif
+#ifdef GL_ATI_vertex_streams
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_streams", 14))
+ {
+ ret = GLEW_ATI_vertex_streams;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4))
+ {
+#ifdef GL_EXT_422_pixels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"422_pixels", 10))
+ {
+ ret = GLEW_EXT_422_pixels;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_Cg_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"Cg_shader", 9))
+ {
+ ret = GLEW_EXT_Cg_shader;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_abgr
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"abgr", 4))
+ {
+ ret = GLEW_EXT_abgr;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_bgra
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"bgra", 4))
+ {
+ ret = GLEW_EXT_bgra;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_bindable_uniform
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindable_uniform", 16))
+ {
+ ret = GLEW_EXT_bindable_uniform;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_color
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_color", 11))
+ {
+ ret = GLEW_EXT_blend_color;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_equation_separate
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_equation_separate", 23))
+ {
+ ret = GLEW_EXT_blend_equation_separate;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_func_separate
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_func_separate", 19))
+ {
+ ret = GLEW_EXT_blend_func_separate;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_logic_op
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_logic_op", 14))
+ {
+ ret = GLEW_EXT_blend_logic_op;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_minmax
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_minmax", 12))
+ {
+ ret = GLEW_EXT_blend_minmax;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_blend_subtract
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_subtract", 14))
+ {
+ ret = GLEW_EXT_blend_subtract;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_clip_volume_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"clip_volume_hint", 16))
+ {
+ ret = GLEW_EXT_clip_volume_hint;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_cmyka
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"cmyka", 5))
+ {
+ ret = GLEW_EXT_cmyka;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_color_subtable
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_subtable", 14))
+ {
+ ret = GLEW_EXT_color_subtable;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_compiled_vertex_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compiled_vertex_array", 21))
+ {
+ ret = GLEW_EXT_compiled_vertex_array;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_convolution
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution", 11))
+ {
+ ret = GLEW_EXT_convolution;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_coordinate_frame
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"coordinate_frame", 16))
+ {
+ ret = GLEW_EXT_coordinate_frame;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_copy_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_texture", 12))
+ {
+ ret = GLEW_EXT_copy_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_cull_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"cull_vertex", 11))
+ {
+ ret = GLEW_EXT_cull_vertex;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_depth_bounds_test
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_bounds_test", 17))
+ {
+ ret = GLEW_EXT_depth_bounds_test;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_direct_state_access
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"direct_state_access", 19))
+ {
+ ret = GLEW_EXT_direct_state_access;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_draw_buffers2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers2", 13))
+ {
+ ret = GLEW_EXT_draw_buffers2;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_draw_instanced
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_instanced", 14))
+ {
+ ret = GLEW_EXT_draw_instanced;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_draw_range_elements
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_range_elements", 19))
+ {
+ ret = GLEW_EXT_draw_range_elements;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_fog_coord
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_coord", 9))
+ {
+ ret = GLEW_EXT_fog_coord;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_fragment_lighting
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_lighting", 17))
+ {
+ ret = GLEW_EXT_fragment_lighting;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_framebuffer_blit
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_blit", 16))
+ {
+ ret = GLEW_EXT_framebuffer_blit;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_framebuffer_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample", 23))
+ {
+ ret = GLEW_EXT_framebuffer_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_framebuffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18))
+ {
+ ret = GLEW_EXT_framebuffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = GLEW_EXT_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_geometry_shader4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16))
+ {
+ ret = GLEW_EXT_geometry_shader4;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_gpu_program_parameters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program_parameters", 22))
+ {
+ ret = GLEW_EXT_gpu_program_parameters;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_gpu_shader4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader4", 11))
+ {
+ ret = GLEW_EXT_gpu_shader4;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_histogram
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"histogram", 9))
+ {
+ ret = GLEW_EXT_histogram;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_index_array_formats
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_array_formats", 19))
+ {
+ ret = GLEW_EXT_index_array_formats;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_index_func
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_func", 10))
+ {
+ ret = GLEW_EXT_index_func;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_index_material
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_material", 14))
+ {
+ ret = GLEW_EXT_index_material;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_index_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_texture", 13))
+ {
+ ret = GLEW_EXT_index_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_light_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"light_texture", 13))
+ {
+ ret = GLEW_EXT_light_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_misc_attribute
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"misc_attribute", 14))
+ {
+ ret = GLEW_EXT_misc_attribute;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_multi_draw_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_arrays", 17))
+ {
+ ret = GLEW_EXT_multi_draw_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLEW_EXT_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_packed_depth_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_depth_stencil", 20))
+ {
+ ret = GLEW_EXT_packed_depth_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_packed_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_float", 12))
+ {
+ ret = GLEW_EXT_packed_float;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_packed_pixels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_pixels", 13))
+ {
+ ret = GLEW_EXT_packed_pixels;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_paletted_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"paletted_texture", 16))
+ {
+ ret = GLEW_EXT_paletted_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_pixel_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer_object", 19))
+ {
+ ret = GLEW_EXT_pixel_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_pixel_transform
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_transform", 15))
+ {
+ ret = GLEW_EXT_pixel_transform;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_pixel_transform_color_table
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_transform_color_table", 27))
+ {
+ ret = GLEW_EXT_pixel_transform_color_table;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_point_parameters
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_parameters", 16))
+ {
+ ret = GLEW_EXT_point_parameters;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_polygon_offset
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"polygon_offset", 14))
+ {
+ ret = GLEW_EXT_polygon_offset;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_rescale_normal
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"rescale_normal", 14))
+ {
+ ret = GLEW_EXT_rescale_normal;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_scene_marker
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"scene_marker", 12))
+ {
+ ret = GLEW_EXT_scene_marker;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_secondary_color
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"secondary_color", 15))
+ {
+ ret = GLEW_EXT_secondary_color;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_separate_specular_color
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_specular_color", 23))
+ {
+ ret = GLEW_EXT_separate_specular_color;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_shadow_funcs
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_funcs", 12))
+ {
+ ret = GLEW_EXT_shadow_funcs;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_shared_texture_palette
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shared_texture_palette", 22))
+ {
+ ret = GLEW_EXT_shared_texture_palette;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_stencil_clear_tag
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_clear_tag", 17))
+ {
+ ret = GLEW_EXT_stencil_clear_tag;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_stencil_two_side
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_two_side", 16))
+ {
+ ret = GLEW_EXT_stencil_two_side;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_stencil_wrap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_wrap", 12))
+ {
+ ret = GLEW_EXT_stencil_wrap;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_subtexture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"subtexture", 10))
+ {
+ ret = GLEW_EXT_subtexture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture", 7))
+ {
+ ret = GLEW_EXT_texture;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture3D
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture3D", 9))
+ {
+ ret = GLEW_EXT_texture3D;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_array", 13))
+ {
+ ret = GLEW_EXT_texture_array;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_object", 21))
+ {
+ ret = GLEW_EXT_texture_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_compression_dxt1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt1", 24))
+ {
+ ret = GLEW_EXT_texture_compression_dxt1;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_compression_latc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_latc", 24))
+ {
+ ret = GLEW_EXT_texture_compression_latc;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_compression_rgtc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_rgtc", 24))
+ {
+ ret = GLEW_EXT_texture_compression_rgtc;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_compression_s3tc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_s3tc", 24))
+ {
+ ret = GLEW_EXT_texture_compression_s3tc;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_cube_map
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map", 16))
+ {
+ ret = GLEW_EXT_texture_cube_map;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_edge_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_edge_clamp", 18))
+ {
+ ret = GLEW_EXT_texture_edge_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_env
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env", 11))
+ {
+ ret = GLEW_EXT_texture_env;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_env_add
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_add", 15))
+ {
+ ret = GLEW_EXT_texture_env_add;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_env_combine
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine", 19))
+ {
+ ret = GLEW_EXT_texture_env_combine;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_env_dot3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_dot3", 16))
+ {
+ ret = GLEW_EXT_texture_env_dot3;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_filter_anisotropic
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_filter_anisotropic", 26))
+ {
+ ret = GLEW_EXT_texture_filter_anisotropic;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_integer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_integer", 15))
+ {
+ ret = GLEW_EXT_texture_integer;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_lod_bias
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod_bias", 16))
+ {
+ ret = GLEW_EXT_texture_lod_bias;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_mirror_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_clamp", 20))
+ {
+ ret = GLEW_EXT_texture_mirror_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_object", 14))
+ {
+ ret = GLEW_EXT_texture_object;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_perturb_normal
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_perturb_normal", 22))
+ {
+ ret = GLEW_EXT_texture_perturb_normal;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17))
+ {
+ ret = GLEW_EXT_texture_rectangle;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_sRGB", 12))
+ {
+ ret = GLEW_EXT_texture_sRGB;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_shared_exponent
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shared_exponent", 23))
+ {
+ ret = GLEW_EXT_texture_shared_exponent;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_texture_swizzle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_swizzle", 15))
+ {
+ ret = GLEW_EXT_texture_swizzle;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_timer_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11))
+ {
+ ret = GLEW_EXT_timer_query;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_transform_feedback
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback", 18))
+ {
+ ret = GLEW_EXT_transform_feedback;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_vertex_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array", 12))
+ {
+ ret = GLEW_EXT_vertex_array;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_vertex_array_bgra
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_bgra", 17))
+ {
+ ret = GLEW_EXT_vertex_array_bgra;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_vertex_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader", 13))
+ {
+ ret = GLEW_EXT_vertex_shader;
+ continue;
+ }
+#endif
+#ifdef GL_EXT_vertex_weighting
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_weighting", 16))
+ {
+ ret = GLEW_EXT_vertex_weighting;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"GREMEDY_", 8))
+ {
+#ifdef GL_GREMEDY_frame_terminator
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"frame_terminator", 16))
+ {
+ ret = GLEW_GREMEDY_frame_terminator;
+ continue;
+ }
+#endif
+#ifdef GL_GREMEDY_string_marker
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"string_marker", 13))
+ {
+ ret = GLEW_GREMEDY_string_marker;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"HP_", 3))
+ {
+#ifdef GL_HP_convolution_border_modes
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_border_modes", 24))
+ {
+ ret = GLEW_HP_convolution_border_modes;
+ continue;
+ }
+#endif
+#ifdef GL_HP_image_transform
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_transform", 15))
+ {
+ ret = GLEW_HP_image_transform;
+ continue;
+ }
+#endif
+#ifdef GL_HP_occlusion_test
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_test", 14))
+ {
+ ret = GLEW_HP_occlusion_test;
+ continue;
+ }
+#endif
+#ifdef GL_HP_texture_lighting
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lighting", 16))
+ {
+ ret = GLEW_HP_texture_lighting;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"IBM_", 4))
+ {
+#ifdef GL_IBM_cull_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"cull_vertex", 11))
+ {
+ ret = GLEW_IBM_cull_vertex;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_multimode_draw_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multimode_draw_arrays", 21))
+ {
+ ret = GLEW_IBM_multimode_draw_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_rasterpos_clip
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"rasterpos_clip", 14))
+ {
+ ret = GLEW_IBM_rasterpos_clip;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_static_data
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"static_data", 11))
+ {
+ ret = GLEW_IBM_static_data;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_texture_mirrored_repeat
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23))
+ {
+ ret = GLEW_IBM_texture_mirrored_repeat;
+ continue;
+ }
+#endif
+#ifdef GL_IBM_vertex_array_lists
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_lists", 18))
+ {
+ ret = GLEW_IBM_vertex_array_lists;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"INGR_", 5))
+ {
+#ifdef GL_INGR_color_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_clamp", 11))
+ {
+ ret = GLEW_INGR_color_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_INGR_interlace_read
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace_read", 14))
+ {
+ ret = GLEW_INGR_interlace_read;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"INTEL_", 6))
+ {
+#ifdef GL_INTEL_parallel_arrays
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"parallel_arrays", 15))
+ {
+ ret = GLEW_INTEL_parallel_arrays;
+ continue;
+ }
+#endif
+#ifdef GL_INTEL_texture_scissor
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_scissor", 15))
+ {
+ ret = GLEW_INTEL_texture_scissor;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"KTX_", 4))
+ {
+#ifdef GL_KTX_buffer_region
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_region", 13))
+ {
+ ret = GLEW_KTX_buffer_region;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESAX_", 6))
+ {
+#ifdef GL_MESAX_texture_stack
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_stack", 13))
+ {
+ ret = GLEW_MESAX_texture_stack;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESA_", 5))
+ {
+#ifdef GL_MESA_pack_invert
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pack_invert", 11))
+ {
+ ret = GLEW_MESA_pack_invert;
+ continue;
+ }
+#endif
+#ifdef GL_MESA_resize_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"resize_buffers", 14))
+ {
+ ret = GLEW_MESA_resize_buffers;
+ continue;
+ }
+#endif
+#ifdef GL_MESA_window_pos
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"window_pos", 10))
+ {
+ ret = GLEW_MESA_window_pos;
+ continue;
+ }
+#endif
+#ifdef GL_MESA_ycbcr_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycbcr_texture", 13))
+ {
+ ret = GLEW_MESA_ycbcr_texture;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3))
+ {
+#ifdef GL_NV_blend_square
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_square", 12))
+ {
+ ret = GLEW_NV_blend_square;
+ continue;
+ }
+#endif
+#ifdef GL_NV_conditional_render
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"conditional_render", 18))
+ {
+ ret = GLEW_NV_conditional_render;
+ continue;
+ }
+#endif
+#ifdef GL_NV_copy_depth_to_color
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_depth_to_color", 19))
+ {
+ ret = GLEW_NV_copy_depth_to_color;
+ continue;
+ }
+#endif
+#ifdef GL_NV_depth_buffer_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_buffer_float", 18))
+ {
+ ret = GLEW_NV_depth_buffer_float;
+ continue;
+ }
+#endif
+#ifdef GL_NV_depth_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_clamp", 11))
+ {
+ ret = GLEW_NV_depth_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_NV_depth_range_unclamped
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_range_unclamped", 21))
+ {
+ ret = GLEW_NV_depth_range_unclamped;
+ continue;
+ }
+#endif
+#ifdef GL_NV_evaluators
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"evaluators", 10))
+ {
+ ret = GLEW_NV_evaluators;
+ continue;
+ }
+#endif
+#ifdef GL_NV_explicit_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_multisample", 20))
+ {
+ ret = GLEW_NV_explicit_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fence
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fence", 5))
+ {
+ ret = GLEW_NV_fence;
+ continue;
+ }
+#endif
+#ifdef GL_NV_float_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12))
+ {
+ ret = GLEW_NV_float_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fog_distance
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_distance", 12))
+ {
+ ret = GLEW_NV_fog_distance;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fragment_program
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16))
+ {
+ ret = GLEW_NV_fragment_program;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fragment_program2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program2", 17))
+ {
+ ret = GLEW_NV_fragment_program2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fragment_program4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program4", 17))
+ {
+ ret = GLEW_NV_fragment_program4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_fragment_program_option
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program_option", 23))
+ {
+ ret = GLEW_NV_fragment_program_option;
+ continue;
+ }
+#endif
+#ifdef GL_NV_framebuffer_multisample_coverage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample_coverage", 32))
+ {
+ ret = GLEW_NV_framebuffer_multisample_coverage;
+ continue;
+ }
+#endif
+#ifdef GL_NV_geometry_program4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_program4", 17))
+ {
+ ret = GLEW_NV_geometry_program4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_geometry_shader4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16))
+ {
+ ret = GLEW_NV_geometry_shader4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_gpu_program4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program4", 12))
+ {
+ ret = GLEW_NV_gpu_program4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_half_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float", 10))
+ {
+ ret = GLEW_NV_half_float;
+ continue;
+ }
+#endif
+#ifdef GL_NV_light_max_exponent
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"light_max_exponent", 18))
+ {
+ ret = GLEW_NV_light_max_exponent;
+ continue;
+ }
+#endif
+#ifdef GL_NV_multisample_filter_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_filter_hint", 23))
+ {
+ ret = GLEW_NV_multisample_filter_hint;
+ continue;
+ }
+#endif
+#ifdef GL_NV_occlusion_query
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query", 15))
+ {
+ ret = GLEW_NV_occlusion_query;
+ continue;
+ }
+#endif
+#ifdef GL_NV_packed_depth_stencil
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_depth_stencil", 20))
+ {
+ ret = GLEW_NV_packed_depth_stencil;
+ continue;
+ }
+#endif
+#ifdef GL_NV_parameter_buffer_object
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"parameter_buffer_object", 23))
+ {
+ ret = GLEW_NV_parameter_buffer_object;
+ continue;
+ }
+#endif
+#ifdef GL_NV_pixel_data_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_data_range", 16))
+ {
+ ret = GLEW_NV_pixel_data_range;
+ continue;
+ }
+#endif
+#ifdef GL_NV_point_sprite
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprite", 12))
+ {
+ ret = GLEW_NV_point_sprite;
+ continue;
+ }
+#endif
+#ifdef GL_NV_present_video
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"present_video", 13))
+ {
+ ret = GLEW_NV_present_video;
+ continue;
+ }
+#endif
+#ifdef GL_NV_primitive_restart
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"primitive_restart", 17))
+ {
+ ret = GLEW_NV_primitive_restart;
+ continue;
+ }
+#endif
+#ifdef GL_NV_register_combiners
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"register_combiners", 18))
+ {
+ ret = GLEW_NV_register_combiners;
+ continue;
+ }
+#endif
+#ifdef GL_NV_register_combiners2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"register_combiners2", 19))
+ {
+ ret = GLEW_NV_register_combiners2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texgen_emboss
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texgen_emboss", 13))
+ {
+ ret = GLEW_NV_texgen_emboss;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texgen_reflection
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texgen_reflection", 17))
+ {
+ ret = GLEW_NV_texgen_reflection;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_compression_vtc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_vtc", 23))
+ {
+ ret = GLEW_NV_texture_compression_vtc;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_env_combine4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine4", 20))
+ {
+ ret = GLEW_NV_texture_env_combine4;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_expand_normal
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_expand_normal", 21))
+ {
+ ret = GLEW_NV_texture_expand_normal;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17))
+ {
+ ret = GLEW_NV_texture_rectangle;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_shader
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader", 14))
+ {
+ ret = GLEW_NV_texture_shader;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_shader2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader2", 15))
+ {
+ ret = GLEW_NV_texture_shader2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_texture_shader3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader3", 15))
+ {
+ ret = GLEW_NV_texture_shader3;
+ continue;
+ }
+#endif
+#ifdef GL_NV_transform_feedback
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback", 18))
+ {
+ ret = GLEW_NV_transform_feedback;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_array_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18))
+ {
+ ret = GLEW_NV_vertex_array_range;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_array_range2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range2", 19))
+ {
+ ret = GLEW_NV_vertex_array_range2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program", 14))
+ {
+ ret = GLEW_NV_vertex_program;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program1_1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program1_1", 17))
+ {
+ ret = GLEW_NV_vertex_program1_1;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program2", 15))
+ {
+ ret = GLEW_NV_vertex_program2;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program2_option
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program2_option", 22))
+ {
+ ret = GLEW_NV_vertex_program2_option;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program3", 15))
+ {
+ ret = GLEW_NV_vertex_program3;
+ continue;
+ }
+#endif
+#ifdef GL_NV_vertex_program4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program4", 15))
+ {
+ ret = GLEW_NV_vertex_program4;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"OES_", 4))
+ {
+#ifdef GL_OES_byte_coordinates
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"byte_coordinates", 16))
+ {
+ ret = GLEW_OES_byte_coordinates;
+ continue;
+ }
+#endif
+#ifdef GL_OES_compressed_paletted_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"compressed_paletted_texture", 27))
+ {
+ ret = GLEW_OES_compressed_paletted_texture;
+ continue;
+ }
+#endif
+#ifdef GL_OES_read_format
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_format", 11))
+ {
+ ret = GLEW_OES_read_format;
+ continue;
+ }
+#endif
+#ifdef GL_OES_single_precision
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"single_precision", 16))
+ {
+ ret = GLEW_OES_single_precision;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4))
+ {
+#ifdef GL_OML_interlace
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace", 9))
+ {
+ ret = GLEW_OML_interlace;
+ continue;
+ }
+#endif
+#ifdef GL_OML_resample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"resample", 8))
+ {
+ ret = GLEW_OML_resample;
+ continue;
+ }
+#endif
+#ifdef GL_OML_subsample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"subsample", 9))
+ {
+ ret = GLEW_OML_subsample;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"PGI_", 4))
+ {
+#ifdef GL_PGI_misc_hints
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"misc_hints", 10))
+ {
+ ret = GLEW_PGI_misc_hints;
+ continue;
+ }
+#endif
+#ifdef GL_PGI_vertex_hints
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_hints", 12))
+ {
+ ret = GLEW_PGI_vertex_hints;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"REND_", 5))
+ {
+#ifdef GL_REND_screen_coordinates
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"screen_coordinates", 18))
+ {
+ ret = GLEW_REND_screen_coordinates;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"S3_", 3))
+ {
+#ifdef GL_S3_s3tc
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"s3tc", 4))
+ {
+ ret = GLEW_S3_s3tc;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIS_", 5))
+ {
+#ifdef GL_SGIS_color_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_range", 11))
+ {
+ ret = GLEW_SGIS_color_range;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_detail_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"detail_texture", 14))
+ {
+ ret = GLEW_SGIS_detail_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_fog_function
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_function", 12))
+ {
+ ret = GLEW_SGIS_fog_function;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_generate_mipmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"generate_mipmap", 15))
+ {
+ ret = GLEW_SGIS_generate_mipmap;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLEW_SGIS_multisample;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_pixel_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture", 13))
+ {
+ ret = GLEW_SGIS_pixel_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_point_line_texgen
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_line_texgen", 17))
+ {
+ ret = GLEW_SGIS_point_line_texgen;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_sharpen_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sharpen_texture", 15))
+ {
+ ret = GLEW_SGIS_sharpen_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture4D
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture4D", 9))
+ {
+ ret = GLEW_SGIS_texture4D;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_border_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_border_clamp", 20))
+ {
+ ret = GLEW_SGIS_texture_border_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_edge_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_edge_clamp", 18))
+ {
+ ret = GLEW_SGIS_texture_edge_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_filter4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_filter4", 15))
+ {
+ ret = GLEW_SGIS_texture_filter4;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_lod
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod", 11))
+ {
+ ret = GLEW_SGIS_texture_lod;
+ continue;
+ }
+#endif
+#ifdef GL_SGIS_texture_select
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_select", 14))
+ {
+ ret = GLEW_SGIS_texture_select;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIX_", 5))
+ {
+#ifdef GL_SGIX_async
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"async", 5))
+ {
+ ret = GLEW_SGIX_async;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_async_histogram
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"async_histogram", 15))
+ {
+ ret = GLEW_SGIX_async_histogram;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_async_pixel
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"async_pixel", 11))
+ {
+ ret = GLEW_SGIX_async_pixel;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_blend_alpha_minmax
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_alpha_minmax", 18))
+ {
+ ret = GLEW_SGIX_blend_alpha_minmax;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_clipmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"clipmap", 7))
+ {
+ ret = GLEW_SGIX_clipmap;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_convolution_accuracy
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_accuracy", 20))
+ {
+ ret = GLEW_SGIX_convolution_accuracy;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_depth_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13))
+ {
+ ret = GLEW_SGIX_depth_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_flush_raster
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"flush_raster", 12))
+ {
+ ret = GLEW_SGIX_flush_raster;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_fog_offset
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_offset", 10))
+ {
+ ret = GLEW_SGIX_fog_offset;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_fog_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_texture", 11))
+ {
+ ret = GLEW_SGIX_fog_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_fragment_specular_lighting
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_specular_lighting", 26))
+ {
+ ret = GLEW_SGIX_fragment_specular_lighting;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_framezoom
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framezoom", 9))
+ {
+ ret = GLEW_SGIX_framezoom;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_interlace
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace", 9))
+ {
+ ret = GLEW_SGIX_interlace;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_ir_instrument1
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ir_instrument1", 14))
+ {
+ ret = GLEW_SGIX_ir_instrument1;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_list_priority
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"list_priority", 13))
+ {
+ ret = GLEW_SGIX_list_priority;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_pixel_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture", 13))
+ {
+ ret = GLEW_SGIX_pixel_texture;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_pixel_texture_bits
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture_bits", 18))
+ {
+ ret = GLEW_SGIX_pixel_texture_bits;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_reference_plane
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"reference_plane", 15))
+ {
+ ret = GLEW_SGIX_reference_plane;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_resample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"resample", 8))
+ {
+ ret = GLEW_SGIX_resample;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_shadow
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow", 6))
+ {
+ ret = GLEW_SGIX_shadow;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_shadow_ambient
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_ambient", 14))
+ {
+ ret = GLEW_SGIX_shadow_ambient;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_sprite
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sprite", 6))
+ {
+ ret = GLEW_SGIX_sprite;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_tag_sample_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"tag_sample_buffer", 17))
+ {
+ ret = GLEW_SGIX_tag_sample_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_add_env
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_add_env", 15))
+ {
+ ret = GLEW_SGIX_texture_add_env;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_coordinate_clamp
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_coordinate_clamp", 24))
+ {
+ ret = GLEW_SGIX_texture_coordinate_clamp;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_lod_bias
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod_bias", 16))
+ {
+ ret = GLEW_SGIX_texture_lod_bias;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_multi_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_multi_buffer", 20))
+ {
+ ret = GLEW_SGIX_texture_multi_buffer;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_range", 13))
+ {
+ ret = GLEW_SGIX_texture_range;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_texture_scale_bias
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_scale_bias", 18))
+ {
+ ret = GLEW_SGIX_texture_scale_bias;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_vertex_preclip
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_preclip", 14))
+ {
+ ret = GLEW_SGIX_vertex_preclip;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_vertex_preclip_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_preclip_hint", 19))
+ {
+ ret = GLEW_SGIX_vertex_preclip_hint;
+ continue;
+ }
+#endif
+#ifdef GL_SGIX_ycrcb
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycrcb", 5))
+ {
+ ret = GLEW_SGIX_ycrcb;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGI_", 4))
+ {
+#ifdef GL_SGI_color_matrix
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_matrix", 12))
+ {
+ ret = GLEW_SGI_color_matrix;
+ continue;
+ }
+#endif
+#ifdef GL_SGI_color_table
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_table", 11))
+ {
+ ret = GLEW_SGI_color_table;
+ continue;
+ }
+#endif
+#ifdef GL_SGI_texture_color_table
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_color_table", 19))
+ {
+ ret = GLEW_SGI_texture_color_table;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUNX_", 5))
+ {
+#ifdef GL_SUNX_constant_data
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"constant_data", 13))
+ {
+ ret = GLEW_SUNX_constant_data;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUN_", 4))
+ {
+#ifdef GL_SUN_convolution_border_modes
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_border_modes", 24))
+ {
+ ret = GLEW_SUN_convolution_border_modes;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_global_alpha
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"global_alpha", 12))
+ {
+ ret = GLEW_SUN_global_alpha;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_mesh_array
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"mesh_array", 10))
+ {
+ ret = GLEW_SUN_mesh_array;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_read_video_pixels
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_video_pixels", 17))
+ {
+ ret = GLEW_SUN_read_video_pixels;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_slice_accum
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"slice_accum", 11))
+ {
+ ret = GLEW_SUN_slice_accum;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_triangle_list
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"triangle_list", 13))
+ {
+ ret = GLEW_SUN_triangle_list;
+ continue;
+ }
+#endif
+#ifdef GL_SUN_vertex
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex", 6))
+ {
+ ret = GLEW_SUN_vertex;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"WIN_", 4))
+ {
+#ifdef GL_WIN_phong_shading
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"phong_shading", 13))
+ {
+ ret = GLEW_WIN_phong_shading;
+ continue;
+ }
+#endif
+#ifdef GL_WIN_specular_fog
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"specular_fog", 12))
+ {
+ ret = GLEW_WIN_specular_fog;
+ continue;
+ }
+#endif
+#ifdef GL_WIN_swap_hint
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_hint", 9))
+ {
+ ret = GLEW_WIN_swap_hint;
+ continue;
+ }
+#endif
+ }
+ }
+ ret = (len == 0);
+ }
+ return ret;
+}
+
+#if defined(_WIN32)
+
+#if defined(GLEW_MX)
+GLboolean wglewContextIsSupported (WGLEWContext* ctx, const char* name)
+#else
+GLboolean wglewIsSupported (const char* name)
+#endif
+{
+ GLubyte* pos = (GLubyte*)name;
+ GLuint len = _glewStrLen(pos);
+ GLboolean ret = GL_TRUE;
+ while (ret && len > 0)
+ {
+ if (_glewStrSame1(&pos, &len, (const GLubyte*)"WGL_", 4))
+ {
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5))
+ {
+#ifdef WGL_3DFX_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = WGLEW_3DFX_multisample;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DL_", 4))
+ {
+#ifdef WGL_3DL_stereo_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"stereo_control", 14))
+ {
+ ret = WGLEW_3DL_stereo_control;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4))
+ {
+#ifdef WGL_ARB_buffer_region
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_region", 13))
+ {
+ ret = WGLEW_ARB_buffer_region;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_create_context
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context", 14))
+ {
+ ret = WGLEW_ARB_create_context;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_extensions_string
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"extensions_string", 17))
+ {
+ ret = WGLEW_ARB_extensions_string;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = WGLEW_ARB_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_make_current_read
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17))
+ {
+ ret = WGLEW_ARB_make_current_read;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = WGLEW_ARB_multisample;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_pbuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7))
+ {
+ ret = WGLEW_ARB_pbuffer;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_pixel_format
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format", 12))
+ {
+ ret = WGLEW_ARB_pixel_format;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_pixel_format_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18))
+ {
+ ret = WGLEW_ARB_pixel_format_float;
+ continue;
+ }
+#endif
+#ifdef WGL_ARB_render_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture", 14))
+ {
+ ret = WGLEW_ARB_render_texture;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4))
+ {
+#ifdef WGL_ATI_pixel_format_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18))
+ {
+ ret = WGLEW_ATI_pixel_format_float;
+ continue;
+ }
+#endif
+#ifdef WGL_ATI_render_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture_rectangle", 24))
+ {
+ ret = WGLEW_ATI_render_texture_rectangle;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4))
+ {
+#ifdef WGL_EXT_depth_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_float", 11))
+ {
+ ret = WGLEW_EXT_depth_float;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_display_color_table
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"display_color_table", 19))
+ {
+ ret = WGLEW_EXT_display_color_table;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_extensions_string
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"extensions_string", 17))
+ {
+ ret = WGLEW_EXT_extensions_string;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = WGLEW_EXT_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_make_current_read
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17))
+ {
+ ret = WGLEW_EXT_make_current_read;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = WGLEW_EXT_multisample;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_pbuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7))
+ {
+ ret = WGLEW_EXT_pbuffer;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_pixel_format
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format", 12))
+ {
+ ret = WGLEW_EXT_pixel_format;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_pixel_format_packed_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_packed_float", 25))
+ {
+ ret = WGLEW_EXT_pixel_format_packed_float;
+ continue;
+ }
+#endif
+#ifdef WGL_EXT_swap_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12))
+ {
+ ret = WGLEW_EXT_swap_control;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"I3D_", 4))
+ {
+#ifdef WGL_I3D_digital_video_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"digital_video_control", 21))
+ {
+ ret = WGLEW_I3D_digital_video_control;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_gamma
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gamma", 5))
+ {
+ ret = WGLEW_I3D_gamma;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_genlock
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"genlock", 7))
+ {
+ ret = WGLEW_I3D_genlock;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_image_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_buffer", 12))
+ {
+ ret = WGLEW_I3D_image_buffer;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_swap_frame_lock
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_frame_lock", 15))
+ {
+ ret = WGLEW_I3D_swap_frame_lock;
+ continue;
+ }
+#endif
+#ifdef WGL_I3D_swap_frame_usage
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_frame_usage", 16))
+ {
+ ret = WGLEW_I3D_swap_frame_usage;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3))
+ {
+#ifdef WGL_NV_float_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12))
+ {
+ ret = WGLEW_NV_float_buffer;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_gpu_affinity
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_affinity", 12))
+ {
+ ret = WGLEW_NV_gpu_affinity;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_present_video
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"present_video", 13))
+ {
+ ret = WGLEW_NV_present_video;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_render_depth_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_depth_texture", 20))
+ {
+ ret = WGLEW_NV_render_depth_texture;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_render_texture_rectangle
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture_rectangle", 24))
+ {
+ ret = WGLEW_NV_render_texture_rectangle;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_swap_group
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10))
+ {
+ ret = WGLEW_NV_swap_group;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_vertex_array_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18))
+ {
+ ret = WGLEW_NV_vertex_array_range;
+ continue;
+ }
+#endif
+#ifdef WGL_NV_video_output
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_output", 12))
+ {
+ ret = WGLEW_NV_video_output;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4))
+ {
+#ifdef WGL_OML_sync_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync_control", 12))
+ {
+ ret = WGLEW_OML_sync_control;
+ continue;
+ }
+#endif
+ }
+ }
+ ret = (len == 0);
+ }
+ return ret;
+}
+
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+
+#if defined(GLEW_MX)
+GLboolean glxewContextIsSupported (GLXEWContext* ctx, const char* name)
+#else
+GLboolean glxewIsSupported (const char* name)
+#endif
+{
+ GLubyte* pos = (GLubyte*)name;
+ GLuint len = _glewStrLen(pos);
+ GLboolean ret = GL_TRUE;
+ while (ret && len > 0)
+ {
+ if(_glewStrSame1(&pos, &len, (const GLubyte*)"GLX_", 4))
+ {
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"VERSION_", 8))
+ {
+#ifdef GLX_VERSION_1_2
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2", 3))
+ {
+ ret = GLXEW_VERSION_1_2;
+ continue;
+ }
+#endif
+#ifdef GLX_VERSION_1_3
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_3", 3))
+ {
+ ret = GLXEW_VERSION_1_3;
+ continue;
+ }
+#endif
+#ifdef GLX_VERSION_1_4
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_4", 3))
+ {
+ ret = GLXEW_VERSION_1_4;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5))
+ {
+#ifdef GLX_3DFX_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLXEW_3DFX_multisample;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4))
+ {
+#ifdef GLX_ARB_create_context
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context", 14))
+ {
+ ret = GLXEW_ARB_create_context;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_fbconfig_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_float", 14))
+ {
+ ret = GLXEW_ARB_fbconfig_float;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = GLXEW_ARB_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_get_proc_address
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_proc_address", 16))
+ {
+ ret = GLXEW_ARB_get_proc_address;
+ continue;
+ }
+#endif
+#ifdef GLX_ARB_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLXEW_ARB_multisample;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4))
+ {
+#ifdef GLX_ATI_pixel_format_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18))
+ {
+ ret = GLXEW_ATI_pixel_format_float;
+ continue;
+ }
+#endif
+#ifdef GLX_ATI_render_texture
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture", 14))
+ {
+ ret = GLXEW_ATI_render_texture;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4))
+ {
+#ifdef GLX_EXT_fbconfig_packed_float
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_packed_float", 21))
+ {
+ ret = GLXEW_EXT_fbconfig_packed_float;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_framebuffer_sRGB
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16))
+ {
+ ret = GLXEW_EXT_framebuffer_sRGB;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_import_context
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"import_context", 14))
+ {
+ ret = GLXEW_EXT_import_context;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_scene_marker
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"scene_marker", 12))
+ {
+ ret = GLXEW_EXT_scene_marker;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_texture_from_pixmap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_from_pixmap", 19))
+ {
+ ret = GLXEW_EXT_texture_from_pixmap;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_visual_info
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_info", 11))
+ {
+ ret = GLXEW_EXT_visual_info;
+ continue;
+ }
+#endif
+#ifdef GLX_EXT_visual_rating
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_rating", 13))
+ {
+ ret = GLXEW_EXT_visual_rating;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESA_", 5))
+ {
+#ifdef GLX_MESA_agp_offset
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"agp_offset", 10))
+ {
+ ret = GLXEW_MESA_agp_offset;
+ continue;
+ }
+#endif
+#ifdef GLX_MESA_copy_sub_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_sub_buffer", 15))
+ {
+ ret = GLXEW_MESA_copy_sub_buffer;
+ continue;
+ }
+#endif
+#ifdef GLX_MESA_pixmap_colormap
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixmap_colormap", 15))
+ {
+ ret = GLXEW_MESA_pixmap_colormap;
+ continue;
+ }
+#endif
+#ifdef GLX_MESA_release_buffers
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"release_buffers", 15))
+ {
+ ret = GLXEW_MESA_release_buffers;
+ continue;
+ }
+#endif
+#ifdef GLX_MESA_set_3dfx_mode
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"set_3dfx_mode", 13))
+ {
+ ret = GLXEW_MESA_set_3dfx_mode;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3))
+ {
+#ifdef GLX_NV_float_buffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12))
+ {
+ ret = GLXEW_NV_float_buffer;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_present_video
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"present_video", 13))
+ {
+ ret = GLXEW_NV_present_video;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_swap_group
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10))
+ {
+ ret = GLXEW_NV_swap_group;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_vertex_array_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18))
+ {
+ ret = GLXEW_NV_vertex_array_range;
+ continue;
+ }
+#endif
+#ifdef GLX_NV_video_output
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_output", 12))
+ {
+ ret = GLXEW_NV_video_output;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4))
+ {
+#ifdef GLX_OML_swap_method
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_method", 11))
+ {
+ ret = GLXEW_OML_swap_method;
+ continue;
+ }
+#endif
+#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#include <inttypes.h>
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync_control", 12))
+ {
+ ret = GLXEW_OML_sync_control;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIS_", 5))
+ {
+#ifdef GLX_SGIS_blended_overlay
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"blended_overlay", 15))
+ {
+ ret = GLXEW_SGIS_blended_overlay;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIS_color_range
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_range", 11))
+ {
+ ret = GLXEW_SGIS_color_range;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIS_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11))
+ {
+ ret = GLXEW_SGIS_multisample;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIS_shared_multisample
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"shared_multisample", 18))
+ {
+ ret = GLXEW_SGIS_shared_multisample;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIX_", 5))
+ {
+#ifdef GLX_SGIX_fbconfig
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig", 8))
+ {
+ ret = GLXEW_SGIX_fbconfig;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_hyperpipe
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"hyperpipe", 9))
+ {
+ ret = GLXEW_SGIX_hyperpipe;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_pbuffer
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7))
+ {
+ ret = GLXEW_SGIX_pbuffer;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_swap_barrier
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_barrier", 12))
+ {
+ ret = GLXEW_SGIX_swap_barrier;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_swap_group
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10))
+ {
+ ret = GLXEW_SGIX_swap_group;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_video_resize
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_resize", 12))
+ {
+ ret = GLXEW_SGIX_video_resize;
+ continue;
+ }
+#endif
+#ifdef GLX_SGIX_visual_select_group
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_select_group", 19))
+ {
+ ret = GLXEW_SGIX_visual_select_group;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGI_", 4))
+ {
+#ifdef GLX_SGI_cushion
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"cushion", 7))
+ {
+ ret = GLXEW_SGI_cushion;
+ continue;
+ }
+#endif
+#ifdef GLX_SGI_make_current_read
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17))
+ {
+ ret = GLXEW_SGI_make_current_read;
+ continue;
+ }
+#endif
+#ifdef GLX_SGI_swap_control
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12))
+ {
+ ret = GLXEW_SGI_swap_control;
+ continue;
+ }
+#endif
+#ifdef GLX_SGI_video_sync
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_sync", 10))
+ {
+ ret = GLXEW_SGI_video_sync;
+ continue;
+ }
+#endif
+ }
+ if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUN_", 4))
+ {
+#ifdef GLX_SUN_get_transparent_index
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_transparent_index", 21))
+ {
+ ret = GLXEW_SUN_get_transparent_index;
+ continue;
+ }
+#endif
+#ifdef GLX_SUN_video_resize
+ if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_resize", 12))
+ {
+ ret = GLXEW_SUN_video_resize;
+ continue;
+ }
+#endif
+ }
+ }
+ ret = (len == 0);
+ }
+ return ret;
+}
+
+#endif /* _WIN32 */
diff --git a/src/glew/glewinfo.c b/src/glew/glewinfo.c
new file mode 100644
index 0000000000..da2b241dea
--- /dev/null
+++ b/src/glew/glewinfo.c
@@ -0,0 +1,7180 @@
+/*
+** The OpenGL Extension Wrangler Library
+** Copyright (C) 2002-2008, Milan Ikits <milan ikits[]ieee org>
+** Copyright (C) 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+** Copyright (C) 2002, Lev Povalahev
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**
+** * Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+** * The name of the author may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+** THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <GL/glew.h>
+#if defined(_WIN32)
+#include <GL/wglew.h>
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+#include <GL/glxew.h>
+#endif
+
+static FILE* f;
+
+#ifdef GLEW_MX
+GLEWContext _glewctx;
+#define glewGetContext() (&_glewctx)
+#ifdef _WIN32
+WGLEWContext _wglewctx;
+#define wglewGetContext() (&_wglewctx)
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+GLXEWContext _glxewctx;
+#define glxewGetContext() (&_glxewctx)
+#endif
+#endif
+
+#if defined(_WIN32)
+GLboolean glewCreateContext (int* pixelformat);
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+GLboolean glewCreateContext (const char* display, int* visual);
+#else
+GLboolean glewCreateContext ();
+#endif
+
+#if defined(_WIN32) || !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+GLboolean glewParseArgs (int argc, char** argv, char** display, int* visual);
+#endif
+
+void glewDestroyContext ();
+
+/* ------------------------------------------------------------------------- */
+
+static void glewPrintExt (const char* name, GLboolean def1, GLboolean def2, GLboolean def3)
+{
+ unsigned int i;
+ fprintf(f, "\n%s:", name);
+ for (i=0; i<62-strlen(name); i++) fprintf(f, " ");
+ fprintf(f, "%s ", def1 ? "OK" : "MISSING");
+ if (def1 != def2)
+ fprintf(f, "[%s] ", def2 ? "OK" : "MISSING");
+ if (def1 != def3)
+ fprintf(f, "[%s]\n", def3 ? "OK" : "MISSING");
+ else
+ fprintf(f, "\n");
+ for (i=0; i<strlen(name)+1; i++) fprintf(f, "-");
+ fprintf(f, "\n");
+ fflush(f);
+}
+
+static void glewInfoFunc (const char* name, GLint undefined)
+{
+ unsigned int i;
+ fprintf(f, " %s:", name);
+ for (i=0; i<60-strlen(name); i++) fprintf(f, " ");
+ fprintf(f, "%s\n", undefined ? "MISSING" : "OK");
+ fflush(f);
+}
+
+/* ----------------------------- GL_VERSION_1_1 ---------------------------- */
+
+#ifdef GL_VERSION_1_1
+
+static void _glewInfo_GL_VERSION_1_1 (void)
+{
+ glewPrintExt("GL_VERSION_1_1", GLEW_VERSION_1_1, GLEW_VERSION_1_1, GLEW_VERSION_1_1);
+}
+
+#endif /* GL_VERSION_1_1 */
+
+#ifdef GL_VERSION_1_2
+
+static void _glewInfo_GL_VERSION_1_2 (void)
+{
+ glewPrintExt("GL_VERSION_1_2", GLEW_VERSION_1_2, GLEW_VERSION_1_2, GLEW_VERSION_1_2);
+
+ glewInfoFunc("glCopyTexSubImage3D", glCopyTexSubImage3D == NULL);
+ glewInfoFunc("glDrawRangeElements", glDrawRangeElements == NULL);
+ glewInfoFunc("glTexImage3D", glTexImage3D == NULL);
+ glewInfoFunc("glTexSubImage3D", glTexSubImage3D == NULL);
+}
+
+#endif /* GL_VERSION_1_2 */
+
+#ifdef GL_VERSION_1_3
+
+static void _glewInfo_GL_VERSION_1_3 (void)
+{
+ glewPrintExt("GL_VERSION_1_3", GLEW_VERSION_1_3, GLEW_VERSION_1_3, GLEW_VERSION_1_3);
+
+ glewInfoFunc("glActiveTexture", glActiveTexture == NULL);
+ glewInfoFunc("glClientActiveTexture", glClientActiveTexture == NULL);
+ glewInfoFunc("glCompressedTexImage1D", glCompressedTexImage1D == NULL);
+ glewInfoFunc("glCompressedTexImage2D", glCompressedTexImage2D == NULL);
+ glewInfoFunc("glCompressedTexImage3D", glCompressedTexImage3D == NULL);
+ glewInfoFunc("glCompressedTexSubImage1D", glCompressedTexSubImage1D == NULL);
+ glewInfoFunc("glCompressedTexSubImage2D", glCompressedTexSubImage2D == NULL);
+ glewInfoFunc("glCompressedTexSubImage3D", glCompressedTexSubImage3D == NULL);
+ glewInfoFunc("glGetCompressedTexImage", glGetCompressedTexImage == NULL);
+ glewInfoFunc("glLoadTransposeMatrixd", glLoadTransposeMatrixd == NULL);
+ glewInfoFunc("glLoadTransposeMatrixf", glLoadTransposeMatrixf == NULL);
+ glewInfoFunc("glMultTransposeMatrixd", glMultTransposeMatrixd == NULL);
+ glewInfoFunc("glMultTransposeMatrixf", glMultTransposeMatrixf == NULL);
+ glewInfoFunc("glMultiTexCoord1d", glMultiTexCoord1d == NULL);
+ glewInfoFunc("glMultiTexCoord1dv", glMultiTexCoord1dv == NULL);
+ glewInfoFunc("glMultiTexCoord1f", glMultiTexCoord1f == NULL);
+ glewInfoFunc("glMultiTexCoord1fv", glMultiTexCoord1fv == NULL);
+ glewInfoFunc("glMultiTexCoord1i", glMultiTexCoord1i == NULL);
+ glewInfoFunc("glMultiTexCoord1iv", glMultiTexCoord1iv == NULL);
+ glewInfoFunc("glMultiTexCoord1s", glMultiTexCoord1s == NULL);
+ glewInfoFunc("glMultiTexCoord1sv", glMultiTexCoord1sv == NULL);
+ glewInfoFunc("glMultiTexCoord2d", glMultiTexCoord2d == NULL);
+ glewInfoFunc("glMultiTexCoord2dv", glMultiTexCoord2dv == NULL);
+ glewInfoFunc("glMultiTexCoord2f", glMultiTexCoord2f == NULL);
+ glewInfoFunc("glMultiTexCoord2fv", glMultiTexCoord2fv == NULL);
+ glewInfoFunc("glMultiTexCoord2i", glMultiTexCoord2i == NULL);
+ glewInfoFunc("glMultiTexCoord2iv", glMultiTexCoord2iv == NULL);
+ glewInfoFunc("glMultiTexCoord2s", glMultiTexCoord2s == NULL);
+ glewInfoFunc("glMultiTexCoord2sv", glMultiTexCoord2sv == NULL);
+ glewInfoFunc("glMultiTexCoord3d", glMultiTexCoord3d == NULL);
+ glewInfoFunc("glMultiTexCoord3dv", glMultiTexCoord3dv == NULL);
+ glewInfoFunc("glMultiTexCoord3f", glMultiTexCoord3f == NULL);
+ glewInfoFunc("glMultiTexCoord3fv", glMultiTexCoord3fv == NULL);
+ glewInfoFunc("glMultiTexCoord3i", glMultiTexCoord3i == NULL);
+ glewInfoFunc("glMultiTexCoord3iv", glMultiTexCoord3iv == NULL);
+ glewInfoFunc("glMultiTexCoord3s", glMultiTexCoord3s == NULL);
+ glewInfoFunc("glMultiTexCoord3sv", glMultiTexCoord3sv == NULL);
+ glewInfoFunc("glMultiTexCoord4d", glMultiTexCoord4d == NULL);
+ glewInfoFunc("glMultiTexCoord4dv", glMultiTexCoord4dv == NULL);
+ glewInfoFunc("glMultiTexCoord4f", glMultiTexCoord4f == NULL);
+ glewInfoFunc("glMultiTexCoord4fv", glMultiTexCoord4fv == NULL);
+ glewInfoFunc("glMultiTexCoord4i", glMultiTexCoord4i == NULL);
+ glewInfoFunc("glMultiTexCoord4iv", glMultiTexCoord4iv == NULL);
+ glewInfoFunc("glMultiTexCoord4s", glMultiTexCoord4s == NULL);
+ glewInfoFunc("glMultiTexCoord4sv", glMultiTexCoord4sv == NULL);
+ glewInfoFunc("glSampleCoverage", glSampleCoverage == NULL);
+}
+
+#endif /* GL_VERSION_1_3 */
+
+#ifdef GL_VERSION_1_4
+
+static void _glewInfo_GL_VERSION_1_4 (void)
+{
+ glewPrintExt("GL_VERSION_1_4", GLEW_VERSION_1_4, GLEW_VERSION_1_4, GLEW_VERSION_1_4);
+
+ glewInfoFunc("glBlendColor", glBlendColor == NULL);
+ glewInfoFunc("glBlendEquation", glBlendEquation == NULL);
+ glewInfoFunc("glBlendFuncSeparate", glBlendFuncSeparate == NULL);
+ glewInfoFunc("glFogCoordPointer", glFogCoordPointer == NULL);
+ glewInfoFunc("glFogCoordd", glFogCoordd == NULL);
+ glewInfoFunc("glFogCoorddv", glFogCoorddv == NULL);
+ glewInfoFunc("glFogCoordf", glFogCoordf == NULL);
+ glewInfoFunc("glFogCoordfv", glFogCoordfv == NULL);
+ glewInfoFunc("glMultiDrawArrays", glMultiDrawArrays == NULL);
+ glewInfoFunc("glMultiDrawElements", glMultiDrawElements == NULL);
+ glewInfoFunc("glPointParameterf", glPointParameterf == NULL);
+ glewInfoFunc("glPointParameterfv", glPointParameterfv == NULL);
+ glewInfoFunc("glPointParameteri", glPointParameteri == NULL);
+ glewInfoFunc("glPointParameteriv", glPointParameteriv == NULL);
+ glewInfoFunc("glSecondaryColor3b", glSecondaryColor3b == NULL);
+ glewInfoFunc("glSecondaryColor3bv", glSecondaryColor3bv == NULL);
+ glewInfoFunc("glSecondaryColor3d", glSecondaryColor3d == NULL);
+ glewInfoFunc("glSecondaryColor3dv", glSecondaryColor3dv == NULL);
+ glewInfoFunc("glSecondaryColor3f", glSecondaryColor3f == NULL);
+ glewInfoFunc("glSecondaryColor3fv", glSecondaryColor3fv == NULL);
+ glewInfoFunc("glSecondaryColor3i", glSecondaryColor3i == NULL);
+ glewInfoFunc("glSecondaryColor3iv", glSecondaryColor3iv == NULL);
+ glewInfoFunc("glSecondaryColor3s", glSecondaryColor3s == NULL);
+ glewInfoFunc("glSecondaryColor3sv", glSecondaryColor3sv == NULL);
+ glewInfoFunc("glSecondaryColor3ub", glSecondaryColor3ub == NULL);
+ glewInfoFunc("glSecondaryColor3ubv", glSecondaryColor3ubv == NULL);
+ glewInfoFunc("glSecondaryColor3ui", glSecondaryColor3ui == NULL);
+ glewInfoFunc("glSecondaryColor3uiv", glSecondaryColor3uiv == NULL);
+ glewInfoFunc("glSecondaryColor3us", glSecondaryColor3us == NULL);
+ glewInfoFunc("glSecondaryColor3usv", glSecondaryColor3usv == NULL);
+ glewInfoFunc("glSecondaryColorPointer", glSecondaryColorPointer == NULL);
+ glewInfoFunc("glWindowPos2d", glWindowPos2d == NULL);
+ glewInfoFunc("glWindowPos2dv", glWindowPos2dv == NULL);
+ glewInfoFunc("glWindowPos2f", glWindowPos2f == NULL);
+ glewInfoFunc("glWindowPos2fv", glWindowPos2fv == NULL);
+ glewInfoFunc("glWindowPos2i", glWindowPos2i == NULL);
+ glewInfoFunc("glWindowPos2iv", glWindowPos2iv == NULL);
+ glewInfoFunc("glWindowPos2s", glWindowPos2s == NULL);
+ glewInfoFunc("glWindowPos2sv", glWindowPos2sv == NULL);
+ glewInfoFunc("glWindowPos3d", glWindowPos3d == NULL);
+ glewInfoFunc("glWindowPos3dv", glWindowPos3dv == NULL);
+ glewInfoFunc("glWindowPos3f", glWindowPos3f == NULL);
+ glewInfoFunc("glWindowPos3fv", glWindowPos3fv == NULL);
+ glewInfoFunc("glWindowPos3i", glWindowPos3i == NULL);
+ glewInfoFunc("glWindowPos3iv", glWindowPos3iv == NULL);
+ glewInfoFunc("glWindowPos3s", glWindowPos3s == NULL);
+ glewInfoFunc("glWindowPos3sv", glWindowPos3sv == NULL);
+}
+
+#endif /* GL_VERSION_1_4 */
+
+#ifdef GL_VERSION_1_5
+
+static void _glewInfo_GL_VERSION_1_5 (void)
+{
+ glewPrintExt("GL_VERSION_1_5", GLEW_VERSION_1_5, GLEW_VERSION_1_5, GLEW_VERSION_1_5);
+
+ glewInfoFunc("glBeginQuery", glBeginQuery == NULL);
+ glewInfoFunc("glBindBuffer", glBindBuffer == NULL);
+ glewInfoFunc("glBufferData", glBufferData == NULL);
+ glewInfoFunc("glBufferSubData", glBufferSubData == NULL);
+ glewInfoFunc("glDeleteBuffers", glDeleteBuffers == NULL);
+ glewInfoFunc("glDeleteQueries", glDeleteQueries == NULL);
+ glewInfoFunc("glEndQuery", glEndQuery == NULL);
+ glewInfoFunc("glGenBuffers", glGenBuffers == NULL);
+ glewInfoFunc("glGenQueries", glGenQueries == NULL);
+ glewInfoFunc("glGetBufferParameteriv", glGetBufferParameteriv == NULL);
+ glewInfoFunc("glGetBufferPointerv", glGetBufferPointerv == NULL);
+ glewInfoFunc("glGetBufferSubData", glGetBufferSubData == NULL);
+ glewInfoFunc("glGetQueryObjectiv", glGetQueryObjectiv == NULL);
+ glewInfoFunc("glGetQueryObjectuiv", glGetQueryObjectuiv == NULL);
+ glewInfoFunc("glGetQueryiv", glGetQueryiv == NULL);
+ glewInfoFunc("glIsBuffer", glIsBuffer == NULL);
+ glewInfoFunc("glIsQuery", glIsQuery == NULL);
+ glewInfoFunc("glMapBuffer", glMapBuffer == NULL);
+ glewInfoFunc("glUnmapBuffer", glUnmapBuffer == NULL);
+}
+
+#endif /* GL_VERSION_1_5 */
+
+#ifdef GL_VERSION_2_0
+
+static void _glewInfo_GL_VERSION_2_0 (void)
+{
+ glewPrintExt("GL_VERSION_2_0", GLEW_VERSION_2_0, GLEW_VERSION_2_0, GLEW_VERSION_2_0);
+
+ glewInfoFunc("glAttachShader", glAttachShader == NULL);
+ glewInfoFunc("glBindAttribLocation", glBindAttribLocation == NULL);
+ glewInfoFunc("glBlendEquationSeparate", glBlendEquationSeparate == NULL);
+ glewInfoFunc("glCompileShader", glCompileShader == NULL);
+ glewInfoFunc("glCreateProgram", glCreateProgram == NULL);
+ glewInfoFunc("glCreateShader", glCreateShader == NULL);
+ glewInfoFunc("glDeleteProgram", glDeleteProgram == NULL);
+ glewInfoFunc("glDeleteShader", glDeleteShader == NULL);
+ glewInfoFunc("glDetachShader", glDetachShader == NULL);
+ glewInfoFunc("glDisableVertexAttribArray", glDisableVertexAttribArray == NULL);
+ glewInfoFunc("glDrawBuffers", glDrawBuffers == NULL);
+ glewInfoFunc("glEnableVertexAttribArray", glEnableVertexAttribArray == NULL);
+ glewInfoFunc("glGetActiveAttrib", glGetActiveAttrib == NULL);
+ glewInfoFunc("glGetActiveUniform", glGetActiveUniform == NULL);
+ glewInfoFunc("glGetAttachedShaders", glGetAttachedShaders == NULL);
+ glewInfoFunc("glGetAttribLocation", glGetAttribLocation == NULL);
+ glewInfoFunc("glGetProgramInfoLog", glGetProgramInfoLog == NULL);
+ glewInfoFunc("glGetProgramiv", glGetProgramiv == NULL);
+ glewInfoFunc("glGetShaderInfoLog", glGetShaderInfoLog == NULL);
+ glewInfoFunc("glGetShaderSource", glGetShaderSource == NULL);
+ glewInfoFunc("glGetShaderiv", glGetShaderiv == NULL);
+ glewInfoFunc("glGetUniformLocation", glGetUniformLocation == NULL);
+ glewInfoFunc("glGetUniformfv", glGetUniformfv == NULL);
+ glewInfoFunc("glGetUniformiv", glGetUniformiv == NULL);
+ glewInfoFunc("glGetVertexAttribPointerv", glGetVertexAttribPointerv == NULL);
+ glewInfoFunc("glGetVertexAttribdv", glGetVertexAttribdv == NULL);
+ glewInfoFunc("glGetVertexAttribfv", glGetVertexAttribfv == NULL);
+ glewInfoFunc("glGetVertexAttribiv", glGetVertexAttribiv == NULL);
+ glewInfoFunc("glIsProgram", glIsProgram == NULL);
+ glewInfoFunc("glIsShader", glIsShader == NULL);
+ glewInfoFunc("glLinkProgram", glLinkProgram == NULL);
+ glewInfoFunc("glShaderSource", glShaderSource == NULL);
+ glewInfoFunc("glStencilFuncSeparate", glStencilFuncSeparate == NULL);
+ glewInfoFunc("glStencilMaskSeparate", glStencilMaskSeparate == NULL);
+ glewInfoFunc("glStencilOpSeparate", glStencilOpSeparate == NULL);
+ glewInfoFunc("glUniform1f", glUniform1f == NULL);
+ glewInfoFunc("glUniform1fv", glUniform1fv == NULL);
+ glewInfoFunc("glUniform1i", glUniform1i == NULL);
+ glewInfoFunc("glUniform1iv", glUniform1iv == NULL);
+ glewInfoFunc("glUniform2f", glUniform2f == NULL);
+ glewInfoFunc("glUniform2fv", glUniform2fv == NULL);
+ glewInfoFunc("glUniform2i", glUniform2i == NULL);
+ glewInfoFunc("glUniform2iv", glUniform2iv == NULL);
+ glewInfoFunc("glUniform3f", glUniform3f == NULL);
+ glewInfoFunc("glUniform3fv", glUniform3fv == NULL);
+ glewInfoFunc("glUniform3i", glUniform3i == NULL);
+ glewInfoFunc("glUniform3iv", glUniform3iv == NULL);
+ glewInfoFunc("glUniform4f", glUniform4f == NULL);
+ glewInfoFunc("glUniform4fv", glUniform4fv == NULL);
+ glewInfoFunc("glUniform4i", glUniform4i == NULL);
+ glewInfoFunc("glUniform4iv", glUniform4iv == NULL);
+ glewInfoFunc("glUniformMatrix2fv", glUniformMatrix2fv == NULL);
+ glewInfoFunc("glUniformMatrix3fv", glUniformMatrix3fv == NULL);
+ glewInfoFunc("glUniformMatrix4fv", glUniformMatrix4fv == NULL);
+ glewInfoFunc("glUseProgram", glUseProgram == NULL);
+ glewInfoFunc("glValidateProgram", glValidateProgram == NULL);
+ glewInfoFunc("glVertexAttrib1d", glVertexAttrib1d == NULL);
+ glewInfoFunc("glVertexAttrib1dv", glVertexAttrib1dv == NULL);
+ glewInfoFunc("glVertexAttrib1f", glVertexAttrib1f == NULL);
+ glewInfoFunc("glVertexAttrib1fv", glVertexAttrib1fv == NULL);
+ glewInfoFunc("glVertexAttrib1s", glVertexAttrib1s == NULL);
+ glewInfoFunc("glVertexAttrib1sv", glVertexAttrib1sv == NULL);
+ glewInfoFunc("glVertexAttrib2d", glVertexAttrib2d == NULL);
+ glewInfoFunc("glVertexAttrib2dv", glVertexAttrib2dv == NULL);
+ glewInfoFunc("glVertexAttrib2f", glVertexAttrib2f == NULL);
+ glewInfoFunc("glVertexAttrib2fv", glVertexAttrib2fv == NULL);
+ glewInfoFunc("glVertexAttrib2s", glVertexAttrib2s == NULL);
+ glewInfoFunc("glVertexAttrib2sv", glVertexAttrib2sv == NULL);
+ glewInfoFunc("glVertexAttrib3d", glVertexAttrib3d == NULL);
+ glewInfoFunc("glVertexAttrib3dv", glVertexAttrib3dv == NULL);
+ glewInfoFunc("glVertexAttrib3f", glVertexAttrib3f == NULL);
+ glewInfoFunc("glVertexAttrib3fv", glVertexAttrib3fv == NULL);
+ glewInfoFunc("glVertexAttrib3s", glVertexAttrib3s == NULL);
+ glewInfoFunc("glVertexAttrib3sv", glVertexAttrib3sv == NULL);
+ glewInfoFunc("glVertexAttrib4Nbv", glVertexAttrib4Nbv == NULL);
+ glewInfoFunc("glVertexAttrib4Niv", glVertexAttrib4Niv == NULL);
+ glewInfoFunc("glVertexAttrib4Nsv", glVertexAttrib4Nsv == NULL);
+ glewInfoFunc("glVertexAttrib4Nub", glVertexAttrib4Nub == NULL);
+ glewInfoFunc("glVertexAttrib4Nubv", glVertexAttrib4Nubv == NULL);
+ glewInfoFunc("glVertexAttrib4Nuiv", glVertexAttrib4Nuiv == NULL);
+ glewInfoFunc("glVertexAttrib4Nusv", glVertexAttrib4Nusv == NULL);
+ glewInfoFunc("glVertexAttrib4bv", glVertexAttrib4bv == NULL);
+ glewInfoFunc("glVertexAttrib4d", glVertexAttrib4d == NULL);
+ glewInfoFunc("glVertexAttrib4dv", glVertexAttrib4dv == NULL);
+ glewInfoFunc("glVertexAttrib4f", glVertexAttrib4f == NULL);
+ glewInfoFunc("glVertexAttrib4fv", glVertexAttrib4fv == NULL);
+ glewInfoFunc("glVertexAttrib4iv", glVertexAttrib4iv == NULL);
+ glewInfoFunc("glVertexAttrib4s", glVertexAttrib4s == NULL);
+ glewInfoFunc("glVertexAttrib4sv", glVertexAttrib4sv == NULL);
+ glewInfoFunc("glVertexAttrib4ubv", glVertexAttrib4ubv == NULL);
+ glewInfoFunc("glVertexAttrib4uiv", glVertexAttrib4uiv == NULL);
+ glewInfoFunc("glVertexAttrib4usv", glVertexAttrib4usv == NULL);
+ glewInfoFunc("glVertexAttribPointer", glVertexAttribPointer == NULL);
+}
+
+#endif /* GL_VERSION_2_0 */
+
+#ifdef GL_VERSION_2_1
+
+static void _glewInfo_GL_VERSION_2_1 (void)
+{
+ glewPrintExt("GL_VERSION_2_1", GLEW_VERSION_2_1, GLEW_VERSION_2_1, GLEW_VERSION_2_1);
+
+ glewInfoFunc("glUniformMatrix2x3fv", glUniformMatrix2x3fv == NULL);
+ glewInfoFunc("glUniformMatrix2x4fv", glUniformMatrix2x4fv == NULL);
+ glewInfoFunc("glUniformMatrix3x2fv", glUniformMatrix3x2fv == NULL);
+ glewInfoFunc("glUniformMatrix3x4fv", glUniformMatrix3x4fv == NULL);
+ glewInfoFunc("glUniformMatrix4x2fv", glUniformMatrix4x2fv == NULL);
+ glewInfoFunc("glUniformMatrix4x3fv", glUniformMatrix4x3fv == NULL);
+}
+
+#endif /* GL_VERSION_2_1 */
+
+#ifdef GL_VERSION_3_0
+
+static void _glewInfo_GL_VERSION_3_0 (void)
+{
+ glewPrintExt("GL_VERSION_3_0", GLEW_VERSION_3_0, GLEW_VERSION_3_0, GLEW_VERSION_3_0);
+
+ glewInfoFunc("glBeginConditionalRender", glBeginConditionalRender == NULL);
+ glewInfoFunc("glBeginTransformFeedback", glBeginTransformFeedback == NULL);
+ glewInfoFunc("glBindBufferBase", glBindBufferBase == NULL);
+ glewInfoFunc("glBindBufferRange", glBindBufferRange == NULL);
+ glewInfoFunc("glBindFragDataLocation", glBindFragDataLocation == NULL);
+ glewInfoFunc("glClampColor", glClampColor == NULL);
+ glewInfoFunc("glClearBufferfi", glClearBufferfi == NULL);
+ glewInfoFunc("glClearBufferfv", glClearBufferfv == NULL);
+ glewInfoFunc("glClearBufferiv", glClearBufferiv == NULL);
+ glewInfoFunc("glClearBufferuiv", glClearBufferuiv == NULL);
+ glewInfoFunc("glColorMaski", glColorMaski == NULL);
+ glewInfoFunc("glDisablei", glDisablei == NULL);
+ glewInfoFunc("glEnablei", glEnablei == NULL);
+ glewInfoFunc("glEndConditionalRender", glEndConditionalRender == NULL);
+ glewInfoFunc("glEndTransformFeedback", glEndTransformFeedback == NULL);
+ glewInfoFunc("glGetBooleani_v", glGetBooleani_v == NULL);
+ glewInfoFunc("glGetFragDataLocation", glGetFragDataLocation == NULL);
+ glewInfoFunc("glGetIntegeri_v", glGetIntegeri_v == NULL);
+ glewInfoFunc("glGetStringi", glGetStringi == NULL);
+ glewInfoFunc("glGetTexParameterIiv", glGetTexParameterIiv == NULL);
+ glewInfoFunc("glGetTexParameterIuiv", glGetTexParameterIuiv == NULL);
+ glewInfoFunc("glGetTransformFeedbackVarying", glGetTransformFeedbackVarying == NULL);
+ glewInfoFunc("glGetUniformuiv", glGetUniformuiv == NULL);
+ glewInfoFunc("glGetVertexAttribIiv", glGetVertexAttribIiv == NULL);
+ glewInfoFunc("glGetVertexAttribIuiv", glGetVertexAttribIuiv == NULL);
+ glewInfoFunc("glIsEnabledi", glIsEnabledi == NULL);
+ glewInfoFunc("glTexParameterIiv", glTexParameterIiv == NULL);
+ glewInfoFunc("glTexParameterIuiv", glTexParameterIuiv == NULL);
+ glewInfoFunc("glTransformFeedbackVaryings", glTransformFeedbackVaryings == NULL);
+ glewInfoFunc("glUniform1ui", glUniform1ui == NULL);
+ glewInfoFunc("glUniform1uiv", glUniform1uiv == NULL);
+ glewInfoFunc("glUniform2ui", glUniform2ui == NULL);
+ glewInfoFunc("glUniform2uiv", glUniform2uiv == NULL);
+ glewInfoFunc("glUniform3ui", glUniform3ui == NULL);
+ glewInfoFunc("glUniform3uiv", glUniform3uiv == NULL);
+ glewInfoFunc("glUniform4ui", glUniform4ui == NULL);
+ glewInfoFunc("glUniform4uiv", glUniform4uiv == NULL);
+ glewInfoFunc("glVertexAttribI1i", glVertexAttribI1i == NULL);
+ glewInfoFunc("glVertexAttribI1iv", glVertexAttribI1iv == NULL);
+ glewInfoFunc("glVertexAttribI1ui", glVertexAttribI1ui == NULL);
+ glewInfoFunc("glVertexAttribI1uiv", glVertexAttribI1uiv == NULL);
+ glewInfoFunc("glVertexAttribI2i", glVertexAttribI2i == NULL);
+ glewInfoFunc("glVertexAttribI2iv", glVertexAttribI2iv == NULL);
+ glewInfoFunc("glVertexAttribI2ui", glVertexAttribI2ui == NULL);
+ glewInfoFunc("glVertexAttribI2uiv", glVertexAttribI2uiv == NULL);
+ glewInfoFunc("glVertexAttribI3i", glVertexAttribI3i == NULL);
+ glewInfoFunc("glVertexAttribI3iv", glVertexAttribI3iv == NULL);
+ glewInfoFunc("glVertexAttribI3ui", glVertexAttribI3ui == NULL);
+ glewInfoFunc("glVertexAttribI3uiv", glVertexAttribI3uiv == NULL);
+ glewInfoFunc("glVertexAttribI4bv", glVertexAttribI4bv == NULL);
+ glewInfoFunc("glVertexAttribI4i", glVertexAttribI4i == NULL);
+ glewInfoFunc("glVertexAttribI4iv", glVertexAttribI4iv == NULL);
+ glewInfoFunc("glVertexAttribI4sv", glVertexAttribI4sv == NULL);
+ glewInfoFunc("glVertexAttribI4ubv", glVertexAttribI4ubv == NULL);
+ glewInfoFunc("glVertexAttribI4ui", glVertexAttribI4ui == NULL);
+ glewInfoFunc("glVertexAttribI4uiv", glVertexAttribI4uiv == NULL);
+ glewInfoFunc("glVertexAttribI4usv", glVertexAttribI4usv == NULL);
+ glewInfoFunc("glVertexAttribIPointer", glVertexAttribIPointer == NULL);
+}
+
+#endif /* GL_VERSION_3_0 */
+
+#ifdef GL_3DFX_multisample
+
+static void _glewInfo_GL_3DFX_multisample (void)
+{
+ glewPrintExt("GL_3DFX_multisample", GLEW_3DFX_multisample, glewIsSupported("GL_3DFX_multisample"), glewGetExtension("GL_3DFX_multisample"));
+}
+
+#endif /* GL_3DFX_multisample */
+
+#ifdef GL_3DFX_tbuffer
+
+static void _glewInfo_GL_3DFX_tbuffer (void)
+{
+ glewPrintExt("GL_3DFX_tbuffer", GLEW_3DFX_tbuffer, glewIsSupported("GL_3DFX_tbuffer"), glewGetExtension("GL_3DFX_tbuffer"));
+
+ glewInfoFunc("glTbufferMask3DFX", glTbufferMask3DFX == NULL);
+}
+
+#endif /* GL_3DFX_tbuffer */
+
+#ifdef GL_3DFX_texture_compression_FXT1
+
+static void _glewInfo_GL_3DFX_texture_compression_FXT1 (void)
+{
+ glewPrintExt("GL_3DFX_texture_compression_FXT1", GLEW_3DFX_texture_compression_FXT1, glewIsSupported("GL_3DFX_texture_compression_FXT1"), glewGetExtension("GL_3DFX_texture_compression_FXT1"));
+}
+
+#endif /* GL_3DFX_texture_compression_FXT1 */
+
+#ifdef GL_APPLE_client_storage
+
+static void _glewInfo_GL_APPLE_client_storage (void)
+{
+ glewPrintExt("GL_APPLE_client_storage", GLEW_APPLE_client_storage, glewIsSupported("GL_APPLE_client_storage"), glewGetExtension("GL_APPLE_client_storage"));
+}
+
+#endif /* GL_APPLE_client_storage */
+
+#ifdef GL_APPLE_element_array
+
+static void _glewInfo_GL_APPLE_element_array (void)
+{
+ glewPrintExt("GL_APPLE_element_array", GLEW_APPLE_element_array, glewIsSupported("GL_APPLE_element_array"), glewGetExtension("GL_APPLE_element_array"));
+
+ glewInfoFunc("glDrawElementArrayAPPLE", glDrawElementArrayAPPLE == NULL);
+ glewInfoFunc("glDrawRangeElementArrayAPPLE", glDrawRangeElementArrayAPPLE == NULL);
+ glewInfoFunc("glElementPointerAPPLE", glElementPointerAPPLE == NULL);
+ glewInfoFunc("glMultiDrawElementArrayAPPLE", glMultiDrawElementArrayAPPLE == NULL);
+ glewInfoFunc("glMultiDrawRangeElementArrayAPPLE", glMultiDrawRangeElementArrayAPPLE == NULL);
+}
+
+#endif /* GL_APPLE_element_array */
+
+#ifdef GL_APPLE_fence
+
+static void _glewInfo_GL_APPLE_fence (void)
+{
+ glewPrintExt("GL_APPLE_fence", GLEW_APPLE_fence, glewIsSupported("GL_APPLE_fence"), glewGetExtension("GL_APPLE_fence"));
+
+ glewInfoFunc("glDeleteFencesAPPLE", glDeleteFencesAPPLE == NULL);
+ glewInfoFunc("glFinishFenceAPPLE", glFinishFenceAPPLE == NULL);
+ glewInfoFunc("glFinishObjectAPPLE", glFinishObjectAPPLE == NULL);
+ glewInfoFunc("glGenFencesAPPLE", glGenFencesAPPLE == NULL);
+ glewInfoFunc("glIsFenceAPPLE", glIsFenceAPPLE == NULL);
+ glewInfoFunc("glSetFenceAPPLE", glSetFenceAPPLE == NULL);
+ glewInfoFunc("glTestFenceAPPLE", glTestFenceAPPLE == NULL);
+ glewInfoFunc("glTestObjectAPPLE", glTestObjectAPPLE == NULL);
+}
+
+#endif /* GL_APPLE_fence */
+
+#ifdef GL_APPLE_float_pixels
+
+static void _glewInfo_GL_APPLE_float_pixels (void)
+{
+ glewPrintExt("GL_APPLE_float_pixels", GLEW_APPLE_float_pixels, glewIsSupported("GL_APPLE_float_pixels"), glewGetExtension("GL_APPLE_float_pixels"));
+}
+
+#endif /* GL_APPLE_float_pixels */
+
+#ifdef GL_APPLE_flush_buffer_range
+
+static void _glewInfo_GL_APPLE_flush_buffer_range (void)
+{
+ glewPrintExt("GL_APPLE_flush_buffer_range", GLEW_APPLE_flush_buffer_range, glewIsSupported("GL_APPLE_flush_buffer_range"), glewGetExtension("GL_APPLE_flush_buffer_range"));
+
+ glewInfoFunc("glBufferParameteriAPPLE", glBufferParameteriAPPLE == NULL);
+ glewInfoFunc("glFlushMappedBufferRangeAPPLE", glFlushMappedBufferRangeAPPLE == NULL);
+}
+
+#endif /* GL_APPLE_flush_buffer_range */
+
+#ifdef GL_APPLE_pixel_buffer
+
+static void _glewInfo_GL_APPLE_pixel_buffer (void)
+{
+ glewPrintExt("GL_APPLE_pixel_buffer", GLEW_APPLE_pixel_buffer, glewIsSupported("GL_APPLE_pixel_buffer"), glewGetExtension("GL_APPLE_pixel_buffer"));
+}
+
+#endif /* GL_APPLE_pixel_buffer */
+
+#ifdef GL_APPLE_specular_vector
+
+static void _glewInfo_GL_APPLE_specular_vector (void)
+{
+ glewPrintExt("GL_APPLE_specular_vector", GLEW_APPLE_specular_vector, glewIsSupported("GL_APPLE_specular_vector"), glewGetExtension("GL_APPLE_specular_vector"));
+}
+
+#endif /* GL_APPLE_specular_vector */
+
+#ifdef GL_APPLE_texture_range
+
+static void _glewInfo_GL_APPLE_texture_range (void)
+{
+ glewPrintExt("GL_APPLE_texture_range", GLEW_APPLE_texture_range, glewIsSupported("GL_APPLE_texture_range"), glewGetExtension("GL_APPLE_texture_range"));
+
+ glewInfoFunc("glGetTexParameterPointervAPPLE", glGetTexParameterPointervAPPLE == NULL);
+ glewInfoFunc("glTextureRangeAPPLE", glTextureRangeAPPLE == NULL);
+}
+
+#endif /* GL_APPLE_texture_range */
+
+#ifdef GL_APPLE_transform_hint
+
+static void _glewInfo_GL_APPLE_transform_hint (void)
+{
+ glewPrintExt("GL_APPLE_transform_hint", GLEW_APPLE_transform_hint, glewIsSupported("GL_APPLE_transform_hint"), glewGetExtension("GL_APPLE_transform_hint"));
+}
+
+#endif /* GL_APPLE_transform_hint */
+
+#ifdef GL_APPLE_vertex_array_object
+
+static void _glewInfo_GL_APPLE_vertex_array_object (void)
+{
+ glewPrintExt("GL_APPLE_vertex_array_object", GLEW_APPLE_vertex_array_object, glewIsSupported("GL_APPLE_vertex_array_object"), glewGetExtension("GL_APPLE_vertex_array_object"));
+
+ glewInfoFunc("glBindVertexArrayAPPLE", glBindVertexArrayAPPLE == NULL);
+ glewInfoFunc("glDeleteVertexArraysAPPLE", glDeleteVertexArraysAPPLE == NULL);
+ glewInfoFunc("glGenVertexArraysAPPLE", glGenVertexArraysAPPLE == NULL);
+ glewInfoFunc("glIsVertexArrayAPPLE", glIsVertexArrayAPPLE == NULL);
+}
+
+#endif /* GL_APPLE_vertex_array_object */
+
+#ifdef GL_APPLE_vertex_array_range
+
+static void _glewInfo_GL_APPLE_vertex_array_range (void)
+{
+ glewPrintExt("GL_APPLE_vertex_array_range", GLEW_APPLE_vertex_array_range, glewIsSupported("GL_APPLE_vertex_array_range"), glewGetExtension("GL_APPLE_vertex_array_range"));
+
+ glewInfoFunc("glFlushVertexArrayRangeAPPLE", glFlushVertexArrayRangeAPPLE == NULL);
+ glewInfoFunc("glVertexArrayParameteriAPPLE", glVertexArrayParameteriAPPLE == NULL);
+ glewInfoFunc("glVertexArrayRangeAPPLE", glVertexArrayRangeAPPLE == NULL);
+}
+
+#endif /* GL_APPLE_vertex_array_range */
+
+#ifdef GL_APPLE_ycbcr_422
+
+static void _glewInfo_GL_APPLE_ycbcr_422 (void)
+{
+ glewPrintExt("GL_APPLE_ycbcr_422", GLEW_APPLE_ycbcr_422, glewIsSupported("GL_APPLE_ycbcr_422"), glewGetExtension("GL_APPLE_ycbcr_422"));
+}
+
+#endif /* GL_APPLE_ycbcr_422 */
+
+#ifdef GL_ARB_color_buffer_float
+
+static void _glewInfo_GL_ARB_color_buffer_float (void)
+{
+ glewPrintExt("GL_ARB_color_buffer_float", GLEW_ARB_color_buffer_float, glewIsSupported("GL_ARB_color_buffer_float"), glewGetExtension("GL_ARB_color_buffer_float"));
+
+ glewInfoFunc("glClampColorARB", glClampColorARB == NULL);
+}
+
+#endif /* GL_ARB_color_buffer_float */
+
+#ifdef GL_ARB_depth_buffer_float
+
+static void _glewInfo_GL_ARB_depth_buffer_float (void)
+{
+ glewPrintExt("GL_ARB_depth_buffer_float", GLEW_ARB_depth_buffer_float, glewIsSupported("GL_ARB_depth_buffer_float"), glewGetExtension("GL_ARB_depth_buffer_float"));
+}
+
+#endif /* GL_ARB_depth_buffer_float */
+
+#ifdef GL_ARB_depth_texture
+
+static void _glewInfo_GL_ARB_depth_texture (void)
+{
+ glewPrintExt("GL_ARB_depth_texture", GLEW_ARB_depth_texture, glewIsSupported("GL_ARB_depth_texture"), glewGetExtension("GL_ARB_depth_texture"));
+}
+
+#endif /* GL_ARB_depth_texture */
+
+#ifdef GL_ARB_draw_buffers
+
+static void _glewInfo_GL_ARB_draw_buffers (void)
+{
+ glewPrintExt("GL_ARB_draw_buffers", GLEW_ARB_draw_buffers, glewIsSupported("GL_ARB_draw_buffers"), glewGetExtension("GL_ARB_draw_buffers"));
+
+ glewInfoFunc("glDrawBuffersARB", glDrawBuffersARB == NULL);
+}
+
+#endif /* GL_ARB_draw_buffers */
+
+#ifdef GL_ARB_draw_instanced
+
+static void _glewInfo_GL_ARB_draw_instanced (void)
+{
+ glewPrintExt("GL_ARB_draw_instanced", GLEW_ARB_draw_instanced, glewIsSupported("GL_ARB_draw_instanced"), glewGetExtension("GL_ARB_draw_instanced"));
+
+ glewInfoFunc("glDrawArraysInstancedARB", glDrawArraysInstancedARB == NULL);
+ glewInfoFunc("glDrawElementsInstancedARB", glDrawElementsInstancedARB == NULL);
+}
+
+#endif /* GL_ARB_draw_instanced */
+
+#ifdef GL_ARB_fragment_program
+
+static void _glewInfo_GL_ARB_fragment_program (void)
+{
+ glewPrintExt("GL_ARB_fragment_program", GLEW_ARB_fragment_program, glewIsSupported("GL_ARB_fragment_program"), glewGetExtension("GL_ARB_fragment_program"));
+}
+
+#endif /* GL_ARB_fragment_program */
+
+#ifdef GL_ARB_fragment_program_shadow
+
+static void _glewInfo_GL_ARB_fragment_program_shadow (void)
+{
+ glewPrintExt("GL_ARB_fragment_program_shadow", GLEW_ARB_fragment_program_shadow, glewIsSupported("GL_ARB_fragment_program_shadow"), glewGetExtension("GL_ARB_fragment_program_shadow"));
+}
+
+#endif /* GL_ARB_fragment_program_shadow */
+
+#ifdef GL_ARB_fragment_shader
+
+static void _glewInfo_GL_ARB_fragment_shader (void)
+{
+ glewPrintExt("GL_ARB_fragment_shader", GLEW_ARB_fragment_shader, glewIsSupported("GL_ARB_fragment_shader"), glewGetExtension("GL_ARB_fragment_shader"));
+}
+
+#endif /* GL_ARB_fragment_shader */
+
+#ifdef GL_ARB_framebuffer_object
+
+static void _glewInfo_GL_ARB_framebuffer_object (void)
+{
+ glewPrintExt("GL_ARB_framebuffer_object", GLEW_ARB_framebuffer_object, glewIsSupported("GL_ARB_framebuffer_object"), glewGetExtension("GL_ARB_framebuffer_object"));
+
+ glewInfoFunc("glBindFramebuffer", glBindFramebuffer == NULL);
+ glewInfoFunc("glBindRenderbuffer", glBindRenderbuffer == NULL);
+ glewInfoFunc("glBlitFramebuffer", glBlitFramebuffer == NULL);
+ glewInfoFunc("glCheckFramebufferStatus", glCheckFramebufferStatus == NULL);
+ glewInfoFunc("glDeleteFramebuffers", glDeleteFramebuffers == NULL);
+ glewInfoFunc("glDeleteRenderbuffers", glDeleteRenderbuffers == NULL);
+ glewInfoFunc("glFramebufferRenderbuffer", glFramebufferRenderbuffer == NULL);
+ glewInfoFunc("glFramebufferTextureLayer", glFramebufferTextureLayer == NULL);
+ glewInfoFunc("glFramebufferTexture1D", glFramebufferTexture1D == NULL);
+ glewInfoFunc("glFramebufferTexture2D", glFramebufferTexture2D == NULL);
+ glewInfoFunc("glFramebufferTexture3D", glFramebufferTexture3D == NULL);
+ glewInfoFunc("glGenFramebuffers", glGenFramebuffers == NULL);
+ glewInfoFunc("glGenRenderbuffers", glGenRenderbuffers == NULL);
+ glewInfoFunc("glGenerateMipmap", glGenerateMipmap == NULL);
+ glewInfoFunc("glGetFramebufferAttachmentParameteriv", glGetFramebufferAttachmentParameteriv == NULL);
+ glewInfoFunc("glGetRenderbufferParameteriv", glGetRenderbufferParameteriv == NULL);
+ glewInfoFunc("glIsFramebuffer", glIsFramebuffer == NULL);
+ glewInfoFunc("glIsRenderbuffer", glIsRenderbuffer == NULL);
+ glewInfoFunc("glRenderbufferStorage", glRenderbufferStorage == NULL);
+ glewInfoFunc("glRenderbufferStorageMultisample", glRenderbufferStorageMultisample == NULL);
+}
+
+#endif /* GL_ARB_framebuffer_object */
+
+#ifdef GL_ARB_framebuffer_sRGB
+
+static void _glewInfo_GL_ARB_framebuffer_sRGB (void)
+{
+ glewPrintExt("GL_ARB_framebuffer_sRGB", GLEW_ARB_framebuffer_sRGB, glewIsSupported("GL_ARB_framebuffer_sRGB"), glewGetExtension("GL_ARB_framebuffer_sRGB"));
+}
+
+#endif /* GL_ARB_framebuffer_sRGB */
+
+#ifdef GL_ARB_geometry_shader4
+
+static void _glewInfo_GL_ARB_geometry_shader4 (void)
+{
+ glewPrintExt("GL_ARB_geometry_shader4", GLEW_ARB_geometry_shader4, glewIsSupported("GL_ARB_geometry_shader4"), glewGetExtension("GL_ARB_geometry_shader4"));
+
+ glewInfoFunc("glFramebufferTextureARB", glFramebufferTextureARB == NULL);
+ glewInfoFunc("glFramebufferTextureFaceARB", glFramebufferTextureFaceARB == NULL);
+ glewInfoFunc("glFramebufferTextureLayerARB", glFramebufferTextureLayerARB == NULL);
+ glewInfoFunc("glProgramParameteriARB", glProgramParameteriARB == NULL);
+}
+
+#endif /* GL_ARB_geometry_shader4 */
+
+#ifdef GL_ARB_half_float_pixel
+
+static void _glewInfo_GL_ARB_half_float_pixel (void)
+{
+ glewPrintExt("GL_ARB_half_float_pixel", GLEW_ARB_half_float_pixel, glewIsSupported("GL_ARB_half_float_pixel"), glewGetExtension("GL_ARB_half_float_pixel"));
+}
+
+#endif /* GL_ARB_half_float_pixel */
+
+#ifdef GL_ARB_half_float_vertex
+
+static void _glewInfo_GL_ARB_half_float_vertex (void)
+{
+ glewPrintExt("GL_ARB_half_float_vertex", GLEW_ARB_half_float_vertex, glewIsSupported("GL_ARB_half_float_vertex"), glewGetExtension("GL_ARB_half_float_vertex"));
+}
+
+#endif /* GL_ARB_half_float_vertex */
+
+#ifdef GL_ARB_imaging
+
+static void _glewInfo_GL_ARB_imaging (void)
+{
+ glewPrintExt("GL_ARB_imaging", GLEW_ARB_imaging, glewIsSupported("GL_ARB_imaging"), glewGetExtension("GL_ARB_imaging"));
+
+ glewInfoFunc("glBlendEquation", glBlendEquation == NULL);
+ glewInfoFunc("glColorSubTable", glColorSubTable == NULL);
+ glewInfoFunc("glColorTable", glColorTable == NULL);
+ glewInfoFunc("glColorTableParameterfv", glColorTableParameterfv == NULL);
+ glewInfoFunc("glColorTableParameteriv", glColorTableParameteriv == NULL);
+ glewInfoFunc("glConvolutionFilter1D", glConvolutionFilter1D == NULL);
+ glewInfoFunc("glConvolutionFilter2D", glConvolutionFilter2D == NULL);
+ glewInfoFunc("glConvolutionParameterf", glConvolutionParameterf == NULL);
+ glewInfoFunc("glConvolutionParameterfv", glConvolutionParameterfv == NULL);
+ glewInfoFunc("glConvolutionParameteri", glConvolutionParameteri == NULL);
+ glewInfoFunc("glConvolutionParameteriv", glConvolutionParameteriv == NULL);
+ glewInfoFunc("glCopyColorSubTable", glCopyColorSubTable == NULL);
+ glewInfoFunc("glCopyColorTable", glCopyColorTable == NULL);
+ glewInfoFunc("glCopyConvolutionFilter1D", glCopyConvolutionFilter1D == NULL);
+ glewInfoFunc("glCopyConvolutionFilter2D", glCopyConvolutionFilter2D == NULL);
+ glewInfoFunc("glGetColorTable", glGetColorTable == NULL);
+ glewInfoFunc("glGetColorTableParameterfv", glGetColorTableParameterfv == NULL);
+ glewInfoFunc("glGetColorTableParameteriv", glGetColorTableParameteriv == NULL);
+ glewInfoFunc("glGetConvolutionFilter", glGetConvolutionFilter == NULL);
+ glewInfoFunc("glGetConvolutionParameterfv", glGetConvolutionParameterfv == NULL);
+ glewInfoFunc("glGetConvolutionParameteriv", glGetConvolutionParameteriv == NULL);
+ glewInfoFunc("glGetHistogram", glGetHistogram == NULL);
+ glewInfoFunc("glGetHistogramParameterfv", glGetHistogramParameterfv == NULL);
+ glewInfoFunc("glGetHistogramParameteriv", glGetHistogramParameteriv == NULL);
+ glewInfoFunc("glGetMinmax", glGetMinmax == NULL);
+ glewInfoFunc("glGetMinmaxParameterfv", glGetMinmaxParameterfv == NULL);
+ glewInfoFunc("glGetMinmaxParameteriv", glGetMinmaxParameteriv == NULL);
+ glewInfoFunc("glGetSeparableFilter", glGetSeparableFilter == NULL);
+ glewInfoFunc("glHistogram", glHistogram == NULL);
+ glewInfoFunc("glMinmax", glMinmax == NULL);
+ glewInfoFunc("glResetHistogram", glResetHistogram == NULL);
+ glewInfoFunc("glResetMinmax", glResetMinmax == NULL);
+ glewInfoFunc("glSeparableFilter2D", glSeparableFilter2D == NULL);
+}
+
+#endif /* GL_ARB_imaging */
+
+#ifdef GL_ARB_instanced_arrays
+
+static void _glewInfo_GL_ARB_instanced_arrays (void)
+{
+ glewPrintExt("GL_ARB_instanced_arrays", GLEW_ARB_instanced_arrays, glewIsSupported("GL_ARB_instanced_arrays"), glewGetExtension("GL_ARB_instanced_arrays"));
+
+ glewInfoFunc("glVertexAttribDivisorARB", glVertexAttribDivisorARB == NULL);
+}
+
+#endif /* GL_ARB_instanced_arrays */
+
+#ifdef GL_ARB_map_buffer_range
+
+static void _glewInfo_GL_ARB_map_buffer_range (void)
+{
+ glewPrintExt("GL_ARB_map_buffer_range", GLEW_ARB_map_buffer_range, glewIsSupported("GL_ARB_map_buffer_range"), glewGetExtension("GL_ARB_map_buffer_range"));
+
+ glewInfoFunc("glFlushMappedBufferRange", glFlushMappedBufferRange == NULL);
+ glewInfoFunc("glMapBufferRange", glMapBufferRange == NULL);
+}
+
+#endif /* GL_ARB_map_buffer_range */
+
+#ifdef GL_ARB_matrix_palette
+
+static void _glewInfo_GL_ARB_matrix_palette (void)
+{
+ glewPrintExt("GL_ARB_matrix_palette", GLEW_ARB_matrix_palette, glewIsSupported("GL_ARB_matrix_palette"), glewGetExtension("GL_ARB_matrix_palette"));
+
+ glewInfoFunc("glCurrentPaletteMatrixARB", glCurrentPaletteMatrixARB == NULL);
+ glewInfoFunc("glMatrixIndexPointerARB", glMatrixIndexPointerARB == NULL);
+ glewInfoFunc("glMatrixIndexubvARB", glMatrixIndexubvARB == NULL);
+ glewInfoFunc("glMatrixIndexuivARB", glMatrixIndexuivARB == NULL);
+ glewInfoFunc("glMatrixIndexusvARB", glMatrixIndexusvARB == NULL);
+}
+
+#endif /* GL_ARB_matrix_palette */
+
+#ifdef GL_ARB_multisample
+
+static void _glewInfo_GL_ARB_multisample (void)
+{
+ glewPrintExt("GL_ARB_multisample", GLEW_ARB_multisample, glewIsSupported("GL_ARB_multisample"), glewGetExtension("GL_ARB_multisample"));
+
+ glewInfoFunc("glSampleCoverageARB", glSampleCoverageARB == NULL);
+}
+
+#endif /* GL_ARB_multisample */
+
+#ifdef GL_ARB_multitexture
+
+static void _glewInfo_GL_ARB_multitexture (void)
+{
+ glewPrintExt("GL_ARB_multitexture", GLEW_ARB_multitexture, glewIsSupported("GL_ARB_multitexture"), glewGetExtension("GL_ARB_multitexture"));
+
+ glewInfoFunc("glActiveTextureARB", glActiveTextureARB == NULL);
+ glewInfoFunc("glClientActiveTextureARB", glClientActiveTextureARB == NULL);
+ glewInfoFunc("glMultiTexCoord1dARB", glMultiTexCoord1dARB == NULL);
+ glewInfoFunc("glMultiTexCoord1dvARB", glMultiTexCoord1dvARB == NULL);
+ glewInfoFunc("glMultiTexCoord1fARB", glMultiTexCoord1fARB == NULL);
+ glewInfoFunc("glMultiTexCoord1fvARB", glMultiTexCoord1fvARB == NULL);
+ glewInfoFunc("glMultiTexCoord1iARB", glMultiTexCoord1iARB == NULL);
+ glewInfoFunc("glMultiTexCoord1ivARB", glMultiTexCoord1ivARB == NULL);
+ glewInfoFunc("glMultiTexCoord1sARB", glMultiTexCoord1sARB == NULL);
+ glewInfoFunc("glMultiTexCoord1svARB", glMultiTexCoord1svARB == NULL);
+ glewInfoFunc("glMultiTexCoord2dARB", glMultiTexCoord2dARB == NULL);
+ glewInfoFunc("glMultiTexCoord2dvARB", glMultiTexCoord2dvARB == NULL);
+ glewInfoFunc("glMultiTexCoord2fARB", glMultiTexCoord2fARB == NULL);
+ glewInfoFunc("glMultiTexCoord2fvARB", glMultiTexCoord2fvARB == NULL);
+ glewInfoFunc("glMultiTexCoord2iARB", glMultiTexCoord2iARB == NULL);
+ glewInfoFunc("glMultiTexCoord2ivARB", glMultiTexCoord2ivARB == NULL);
+ glewInfoFunc("glMultiTexCoord2sARB", glMultiTexCoord2sARB == NULL);
+ glewInfoFunc("glMultiTexCoord2svARB", glMultiTexCoord2svARB == NULL);
+ glewInfoFunc("glMultiTexCoord3dARB", glMultiTexCoord3dARB == NULL);
+ glewInfoFunc("glMultiTexCoord3dvARB", glMultiTexCoord3dvARB == NULL);
+ glewInfoFunc("glMultiTexCoord3fARB", glMultiTexCoord3fARB == NULL);
+ glewInfoFunc("glMultiTexCoord3fvARB", glMultiTexCoord3fvARB == NULL);
+ glewInfoFunc("glMultiTexCoord3iARB", glMultiTexCoord3iARB == NULL);
+ glewInfoFunc("glMultiTexCoord3ivARB", glMultiTexCoord3ivARB == NULL);
+ glewInfoFunc("glMultiTexCoord3sARB", glMultiTexCoord3sARB == NULL);
+ glewInfoFunc("glMultiTexCoord3svARB", glMultiTexCoord3svARB == NULL);
+ glewInfoFunc("glMultiTexCoord4dARB", glMultiTexCoord4dARB == NULL);
+ glewInfoFunc("glMultiTexCoord4dvARB", glMultiTexCoord4dvARB == NULL);
+ glewInfoFunc("glMultiTexCoord4fARB", glMultiTexCoord4fARB == NULL);
+ glewInfoFunc("glMultiTexCoord4fvARB", glMultiTexCoord4fvARB == NULL);
+ glewInfoFunc("glMultiTexCoord4iARB", glMultiTexCoord4iARB == NULL);
+ glewInfoFunc("glMultiTexCoord4ivARB", glMultiTexCoord4ivARB == NULL);
+ glewInfoFunc("glMultiTexCoord4sARB", glMultiTexCoord4sARB == NULL);
+ glewInfoFunc("glMultiTexCoord4svARB", glMultiTexCoord4svARB == NULL);
+}
+
+#endif /* GL_ARB_multitexture */
+
+#ifdef GL_ARB_occlusion_query
+
+static void _glewInfo_GL_ARB_occlusion_query (void)
+{
+ glewPrintExt("GL_ARB_occlusion_query", GLEW_ARB_occlusion_query, glewIsSupported("GL_ARB_occlusion_query"), glewGetExtension("GL_ARB_occlusion_query"));
+
+ glewInfoFunc("glBeginQueryARB", glBeginQueryARB == NULL);
+ glewInfoFunc("glDeleteQueriesARB", glDeleteQueriesARB == NULL);
+ glewInfoFunc("glEndQueryARB", glEndQueryARB == NULL);
+ glewInfoFunc("glGenQueriesARB", glGenQueriesARB == NULL);
+ glewInfoFunc("glGetQueryObjectivARB", glGetQueryObjectivARB == NULL);
+ glewInfoFunc("glGetQueryObjectuivARB", glGetQueryObjectuivARB == NULL);
+ glewInfoFunc("glGetQueryivARB", glGetQueryivARB == NULL);
+ glewInfoFunc("glIsQueryARB", glIsQueryARB == NULL);
+}
+
+#endif /* GL_ARB_occlusion_query */
+
+#ifdef GL_ARB_pixel_buffer_object
+
+static void _glewInfo_GL_ARB_pixel_buffer_object (void)
+{
+ glewPrintExt("GL_ARB_pixel_buffer_object", GLEW_ARB_pixel_buffer_object, glewIsSupported("GL_ARB_pixel_buffer_object"), glewGetExtension("GL_ARB_pixel_buffer_object"));
+}
+
+#endif /* GL_ARB_pixel_buffer_object */
+
+#ifdef GL_ARB_point_parameters
+
+static void _glewInfo_GL_ARB_point_parameters (void)
+{
+ glewPrintExt("GL_ARB_point_parameters", GLEW_ARB_point_parameters, glewIsSupported("GL_ARB_point_parameters"), glewGetExtension("GL_ARB_point_parameters"));
+
+ glewInfoFunc("glPointParameterfARB", glPointParameterfARB == NULL);
+ glewInfoFunc("glPointParameterfvARB", glPointParameterfvARB == NULL);
+}
+
+#endif /* GL_ARB_point_parameters */
+
+#ifdef GL_ARB_point_sprite
+
+static void _glewInfo_GL_ARB_point_sprite (void)
+{
+ glewPrintExt("GL_ARB_point_sprite", GLEW_ARB_point_sprite, glewIsSupported("GL_ARB_point_sprite"), glewGetExtension("GL_ARB_point_sprite"));
+}
+
+#endif /* GL_ARB_point_sprite */
+
+#ifdef GL_ARB_shader_objects
+
+static void _glewInfo_GL_ARB_shader_objects (void)
+{
+ glewPrintExt("GL_ARB_shader_objects", GLEW_ARB_shader_objects, glewIsSupported("GL_ARB_shader_objects"), glewGetExtension("GL_ARB_shader_objects"));
+
+ glewInfoFunc("glAttachObjectARB", glAttachObjectARB == NULL);
+ glewInfoFunc("glCompileShaderARB", glCompileShaderARB == NULL);
+ glewInfoFunc("glCreateProgramObjectARB", glCreateProgramObjectARB == NULL);
+ glewInfoFunc("glCreateShaderObjectARB", glCreateShaderObjectARB == NULL);
+ glewInfoFunc("glDeleteObjectARB", glDeleteObjectARB == NULL);
+ glewInfoFunc("glDetachObjectARB", glDetachObjectARB == NULL);
+ glewInfoFunc("glGetActiveUniformARB", glGetActiveUniformARB == NULL);
+ glewInfoFunc("glGetAttachedObjectsARB", glGetAttachedObjectsARB == NULL);
+ glewInfoFunc("glGetHandleARB", glGetHandleARB == NULL);
+ glewInfoFunc("glGetInfoLogARB", glGetInfoLogARB == NULL);
+ glewInfoFunc("glGetObjectParameterfvARB", glGetObjectParameterfvARB == NULL);
+ glewInfoFunc("glGetObjectParameterivARB", glGetObjectParameterivARB == NULL);
+ glewInfoFunc("glGetShaderSourceARB", glGetShaderSourceARB == NULL);
+ glewInfoFunc("glGetUniformLocationARB", glGetUniformLocationARB == NULL);
+ glewInfoFunc("glGetUniformfvARB", glGetUniformfvARB == NULL);
+ glewInfoFunc("glGetUniformivARB", glGetUniformivARB == NULL);
+ glewInfoFunc("glLinkProgramARB", glLinkProgramARB == NULL);
+ glewInfoFunc("glShaderSourceARB", glShaderSourceARB == NULL);
+ glewInfoFunc("glUniform1fARB", glUniform1fARB == NULL);
+ glewInfoFunc("glUniform1fvARB", glUniform1fvARB == NULL);
+ glewInfoFunc("glUniform1iARB", glUniform1iARB == NULL);
+ glewInfoFunc("glUniform1ivARB", glUniform1ivARB == NULL);
+ glewInfoFunc("glUniform2fARB", glUniform2fARB == NULL);
+ glewInfoFunc("glUniform2fvARB", glUniform2fvARB == NULL);
+ glewInfoFunc("glUniform2iARB", glUniform2iARB == NULL);
+ glewInfoFunc("glUniform2ivARB", glUniform2ivARB == NULL);
+ glewInfoFunc("glUniform3fARB", glUniform3fARB == NULL);
+ glewInfoFunc("glUniform3fvARB", glUniform3fvARB == NULL);
+ glewInfoFunc("glUniform3iARB", glUniform3iARB == NULL);
+ glewInfoFunc("glUniform3ivARB", glUniform3ivARB == NULL);
+ glewInfoFunc("glUniform4fARB", glUniform4fARB == NULL);
+ glewInfoFunc("glUniform4fvARB", glUniform4fvARB == NULL);
+ glewInfoFunc("glUniform4iARB", glUniform4iARB == NULL);
+ glewInfoFunc("glUniform4ivARB", glUniform4ivARB == NULL);
+ glewInfoFunc("glUniformMatrix2fvARB", glUniformMatrix2fvARB == NULL);
+ glewInfoFunc("glUniformMatrix3fvARB", glUniformMatrix3fvARB == NULL);
+ glewInfoFunc("glUniformMatrix4fvARB", glUniformMatrix4fvARB == NULL);
+ glewInfoFunc("glUseProgramObjectARB", glUseProgramObjectARB == NULL);
+ glewInfoFunc("glValidateProgramARB", glValidateProgramARB == NULL);
+}
+
+#endif /* GL_ARB_shader_objects */
+
+#ifdef GL_ARB_shading_language_100
+
+static void _glewInfo_GL_ARB_shading_language_100 (void)
+{
+ glewPrintExt("GL_ARB_shading_language_100", GLEW_ARB_shading_language_100, glewIsSupported("GL_ARB_shading_language_100"), glewGetExtension("GL_ARB_shading_language_100"));
+}
+
+#endif /* GL_ARB_shading_language_100 */
+
+#ifdef GL_ARB_shadow
+
+static void _glewInfo_GL_ARB_shadow (void)
+{
+ glewPrintExt("GL_ARB_shadow", GLEW_ARB_shadow, glewIsSupported("GL_ARB_shadow"), glewGetExtension("GL_ARB_shadow"));
+}
+
+#endif /* GL_ARB_shadow */
+
+#ifdef GL_ARB_shadow_ambient
+
+static void _glewInfo_GL_ARB_shadow_ambient (void)
+{
+ glewPrintExt("GL_ARB_shadow_ambient", GLEW_ARB_shadow_ambient, glewIsSupported("GL_ARB_shadow_ambient"), glewGetExtension("GL_ARB_shadow_ambient"));
+}
+
+#endif /* GL_ARB_shadow_ambient */
+
+#ifdef GL_ARB_texture_border_clamp
+
+static void _glewInfo_GL_ARB_texture_border_clamp (void)
+{
+ glewPrintExt("GL_ARB_texture_border_clamp", GLEW_ARB_texture_border_clamp, glewIsSupported("GL_ARB_texture_border_clamp"), glewGetExtension("GL_ARB_texture_border_clamp"));
+}
+
+#endif /* GL_ARB_texture_border_clamp */
+
+#ifdef GL_ARB_texture_buffer_object
+
+static void _glewInfo_GL_ARB_texture_buffer_object (void)
+{
+ glewPrintExt("GL_ARB_texture_buffer_object", GLEW_ARB_texture_buffer_object, glewIsSupported("GL_ARB_texture_buffer_object"), glewGetExtension("GL_ARB_texture_buffer_object"));
+
+ glewInfoFunc("glTexBufferARB", glTexBufferARB == NULL);
+}
+
+#endif /* GL_ARB_texture_buffer_object */
+
+#ifdef GL_ARB_texture_compression
+
+static void _glewInfo_GL_ARB_texture_compression (void)
+{
+ glewPrintExt("GL_ARB_texture_compression", GLEW_ARB_texture_compression, glewIsSupported("GL_ARB_texture_compression"), glewGetExtension("GL_ARB_texture_compression"));
+
+ glewInfoFunc("glCompressedTexImage1DARB", glCompressedTexImage1DARB == NULL);
+ glewInfoFunc("glCompressedTexImage2DARB", glCompressedTexImage2DARB == NULL);
+ glewInfoFunc("glCompressedTexImage3DARB", glCompressedTexImage3DARB == NULL);
+ glewInfoFunc("glCompressedTexSubImage1DARB", glCompressedTexSubImage1DARB == NULL);
+ glewInfoFunc("glCompressedTexSubImage2DARB", glCompressedTexSubImage2DARB == NULL);
+ glewInfoFunc("glCompressedTexSubImage3DARB", glCompressedTexSubImage3DARB == NULL);
+ glewInfoFunc("glGetCompressedTexImageARB", glGetCompressedTexImageARB == NULL);
+}
+
+#endif /* GL_ARB_texture_compression */
+
+#ifdef GL_ARB_texture_compression_rgtc
+
+static void _glewInfo_GL_ARB_texture_compression_rgtc (void)
+{
+ glewPrintExt("GL_ARB_texture_compression_rgtc", GLEW_ARB_texture_compression_rgtc, glewIsSupported("GL_ARB_texture_compression_rgtc"), glewGetExtension("GL_ARB_texture_compression_rgtc"));
+}
+
+#endif /* GL_ARB_texture_compression_rgtc */
+
+#ifdef GL_ARB_texture_cube_map
+
+static void _glewInfo_GL_ARB_texture_cube_map (void)
+{
+ glewPrintExt("GL_ARB_texture_cube_map", GLEW_ARB_texture_cube_map, glewIsSupported("GL_ARB_texture_cube_map"), glewGetExtension("GL_ARB_texture_cube_map"));
+}
+
+#endif /* GL_ARB_texture_cube_map */
+
+#ifdef GL_ARB_texture_env_add
+
+static void _glewInfo_GL_ARB_texture_env_add (void)
+{
+ glewPrintExt("GL_ARB_texture_env_add", GLEW_ARB_texture_env_add, glewIsSupported("GL_ARB_texture_env_add"), glewGetExtension("GL_ARB_texture_env_add"));
+}
+
+#endif /* GL_ARB_texture_env_add */
+
+#ifdef GL_ARB_texture_env_combine
+
+static void _glewInfo_GL_ARB_texture_env_combine (void)
+{
+ glewPrintExt("GL_ARB_texture_env_combine", GLEW_ARB_texture_env_combine, glewIsSupported("GL_ARB_texture_env_combine"), glewGetExtension("GL_ARB_texture_env_combine"));
+}
+
+#endif /* GL_ARB_texture_env_combine */
+
+#ifdef GL_ARB_texture_env_crossbar
+
+static void _glewInfo_GL_ARB_texture_env_crossbar (void)
+{
+ glewPrintExt("GL_ARB_texture_env_crossbar", GLEW_ARB_texture_env_crossbar, glewIsSupported("GL_ARB_texture_env_crossbar"), glewGetExtension("GL_ARB_texture_env_crossbar"));
+}
+
+#endif /* GL_ARB_texture_env_crossbar */
+
+#ifdef GL_ARB_texture_env_dot3
+
+static void _glewInfo_GL_ARB_texture_env_dot3 (void)
+{
+ glewPrintExt("GL_ARB_texture_env_dot3", GLEW_ARB_texture_env_dot3, glewIsSupported("GL_ARB_texture_env_dot3"), glewGetExtension("GL_ARB_texture_env_dot3"));
+}
+
+#endif /* GL_ARB_texture_env_dot3 */
+
+#ifdef GL_ARB_texture_float
+
+static void _glewInfo_GL_ARB_texture_float (void)
+{
+ glewPrintExt("GL_ARB_texture_float", GLEW_ARB_texture_float, glewIsSupported("GL_ARB_texture_float"), glewGetExtension("GL_ARB_texture_float"));
+}
+
+#endif /* GL_ARB_texture_float */
+
+#ifdef GL_ARB_texture_mirrored_repeat
+
+static void _glewInfo_GL_ARB_texture_mirrored_repeat (void)
+{
+ glewPrintExt("GL_ARB_texture_mirrored_repeat", GLEW_ARB_texture_mirrored_repeat, glewIsSupported("GL_ARB_texture_mirrored_repeat"), glewGetExtension("GL_ARB_texture_mirrored_repeat"));
+}
+
+#endif /* GL_ARB_texture_mirrored_repeat */
+
+#ifdef GL_ARB_texture_non_power_of_two
+
+static void _glewInfo_GL_ARB_texture_non_power_of_two (void)
+{
+ glewPrintExt("GL_ARB_texture_non_power_of_two", GLEW_ARB_texture_non_power_of_two, glewIsSupported("GL_ARB_texture_non_power_of_two"), glewGetExtension("GL_ARB_texture_non_power_of_two"));
+}
+
+#endif /* GL_ARB_texture_non_power_of_two */
+
+#ifdef GL_ARB_texture_rectangle
+
+static void _glewInfo_GL_ARB_texture_rectangle (void)
+{
+ glewPrintExt("GL_ARB_texture_rectangle", GLEW_ARB_texture_rectangle, glewIsSupported("GL_ARB_texture_rectangle"), glewGetExtension("GL_ARB_texture_rectangle"));
+}
+
+#endif /* GL_ARB_texture_rectangle */
+
+#ifdef GL_ARB_texture_rg
+
+static void _glewInfo_GL_ARB_texture_rg (void)
+{
+ glewPrintExt("GL_ARB_texture_rg", GLEW_ARB_texture_rg, glewIsSupported("GL_ARB_texture_rg"), glewGetExtension("GL_ARB_texture_rg"));
+}
+
+#endif /* GL_ARB_texture_rg */
+
+#ifdef GL_ARB_transpose_matrix
+
+static void _glewInfo_GL_ARB_transpose_matrix (void)
+{
+ glewPrintExt("GL_ARB_transpose_matrix", GLEW_ARB_transpose_matrix, glewIsSupported("GL_ARB_transpose_matrix"), glewGetExtension("GL_ARB_transpose_matrix"));
+
+ glewInfoFunc("glLoadTransposeMatrixdARB", glLoadTransposeMatrixdARB == NULL);
+ glewInfoFunc("glLoadTransposeMatrixfARB", glLoadTransposeMatrixfARB == NULL);
+ glewInfoFunc("glMultTransposeMatrixdARB", glMultTransposeMatrixdARB == NULL);
+ glewInfoFunc("glMultTransposeMatrixfARB", glMultTransposeMatrixfARB == NULL);
+}
+
+#endif /* GL_ARB_transpose_matrix */
+
+#ifdef GL_ARB_vertex_array_object
+
+static void _glewInfo_GL_ARB_vertex_array_object (void)
+{
+ glewPrintExt("GL_ARB_vertex_array_object", GLEW_ARB_vertex_array_object, glewIsSupported("GL_ARB_vertex_array_object"), glewGetExtension("GL_ARB_vertex_array_object"));
+
+ glewInfoFunc("glBindVertexArray", glBindVertexArray == NULL);
+ glewInfoFunc("glDeleteVertexArrays", glDeleteVertexArrays == NULL);
+ glewInfoFunc("glGenVertexArrays", glGenVertexArrays == NULL);
+ glewInfoFunc("glIsVertexArray", glIsVertexArray == NULL);
+}
+
+#endif /* GL_ARB_vertex_array_object */
+
+#ifdef GL_ARB_vertex_blend
+
+static void _glewInfo_GL_ARB_vertex_blend (void)
+{
+ glewPrintExt("GL_ARB_vertex_blend", GLEW_ARB_vertex_blend, glewIsSupported("GL_ARB_vertex_blend"), glewGetExtension("GL_ARB_vertex_blend"));
+
+ glewInfoFunc("glVertexBlendARB", glVertexBlendARB == NULL);
+ glewInfoFunc("glWeightPointerARB", glWeightPointerARB == NULL);
+ glewInfoFunc("glWeightbvARB", glWeightbvARB == NULL);
+ glewInfoFunc("glWeightdvARB", glWeightdvARB == NULL);
+ glewInfoFunc("glWeightfvARB", glWeightfvARB == NULL);
+ glewInfoFunc("glWeightivARB", glWeightivARB == NULL);
+ glewInfoFunc("glWeightsvARB", glWeightsvARB == NULL);
+ glewInfoFunc("glWeightubvARB", glWeightubvARB == NULL);
+ glewInfoFunc("glWeightuivARB", glWeightuivARB == NULL);
+ glewInfoFunc("glWeightusvARB", glWeightusvARB == NULL);
+}
+
+#endif /* GL_ARB_vertex_blend */
+
+#ifdef GL_ARB_vertex_buffer_object
+
+static void _glewInfo_GL_ARB_vertex_buffer_object (void)
+{
+ glewPrintExt("GL_ARB_vertex_buffer_object", GLEW_ARB_vertex_buffer_object, glewIsSupported("GL_ARB_vertex_buffer_object"), glewGetExtension("GL_ARB_vertex_buffer_object"));
+
+ glewInfoFunc("glBindBufferARB", glBindBufferARB == NULL);
+ glewInfoFunc("glBufferDataARB", glBufferDataARB == NULL);
+ glewInfoFunc("glBufferSubDataARB", glBufferSubDataARB == NULL);
+ glewInfoFunc("glDeleteBuffersARB", glDeleteBuffersARB == NULL);
+ glewInfoFunc("glGenBuffersARB", glGenBuffersARB == NULL);
+ glewInfoFunc("glGetBufferParameterivARB", glGetBufferParameterivARB == NULL);
+ glewInfoFunc("glGetBufferPointervARB", glGetBufferPointervARB == NULL);
+ glewInfoFunc("glGetBufferSubDataARB", glGetBufferSubDataARB == NULL);
+ glewInfoFunc("glIsBufferARB", glIsBufferARB == NULL);
+ glewInfoFunc("glMapBufferARB", glMapBufferARB == NULL);
+ glewInfoFunc("glUnmapBufferARB", glUnmapBufferARB == NULL);
+}
+
+#endif /* GL_ARB_vertex_buffer_object */
+
+#ifdef GL_ARB_vertex_program
+
+static void _glewInfo_GL_ARB_vertex_program (void)
+{
+ glewPrintExt("GL_ARB_vertex_program", GLEW_ARB_vertex_program, glewIsSupported("GL_ARB_vertex_program"), glewGetExtension("GL_ARB_vertex_program"));
+
+ glewInfoFunc("glBindProgramARB", glBindProgramARB == NULL);
+ glewInfoFunc("glDeleteProgramsARB", glDeleteProgramsARB == NULL);
+ glewInfoFunc("glDisableVertexAttribArrayARB", glDisableVertexAttribArrayARB == NULL);
+ glewInfoFunc("glEnableVertexAttribArrayARB", glEnableVertexAttribArrayARB == NULL);
+ glewInfoFunc("glGenProgramsARB", glGenProgramsARB == NULL);
+ glewInfoFunc("glGetProgramEnvParameterdvARB", glGetProgramEnvParameterdvARB == NULL);
+ glewInfoFunc("glGetProgramEnvParameterfvARB", glGetProgramEnvParameterfvARB == NULL);
+ glewInfoFunc("glGetProgramLocalParameterdvARB", glGetProgramLocalParameterdvARB == NULL);
+ glewInfoFunc("glGetProgramLocalParameterfvARB", glGetProgramLocalParameterfvARB == NULL);
+ glewInfoFunc("glGetProgramStringARB", glGetProgramStringARB == NULL);
+ glewInfoFunc("glGetProgramivARB", glGetProgramivARB == NULL);
+ glewInfoFunc("glGetVertexAttribPointervARB", glGetVertexAttribPointervARB == NULL);
+ glewInfoFunc("glGetVertexAttribdvARB", glGetVertexAttribdvARB == NULL);
+ glewInfoFunc("glGetVertexAttribfvARB", glGetVertexAttribfvARB == NULL);
+ glewInfoFunc("glGetVertexAttribivARB", glGetVertexAttribivARB == NULL);
+ glewInfoFunc("glIsProgramARB", glIsProgramARB == NULL);
+ glewInfoFunc("glProgramEnvParameter4dARB", glProgramEnvParameter4dARB == NULL);
+ glewInfoFunc("glProgramEnvParameter4dvARB", glProgramEnvParameter4dvARB == NULL);
+ glewInfoFunc("glProgramEnvParameter4fARB", glProgramEnvParameter4fARB == NULL);
+ glewInfoFunc("glProgramEnvParameter4fvARB", glProgramEnvParameter4fvARB == NULL);
+ glewInfoFunc("glProgramLocalParameter4dARB", glProgramLocalParameter4dARB == NULL);
+ glewInfoFunc("glProgramLocalParameter4dvARB", glProgramLocalParameter4dvARB == NULL);
+ glewInfoFunc("glProgramLocalParameter4fARB", glProgramLocalParameter4fARB == NULL);
+ glewInfoFunc("glProgramLocalParameter4fvARB", glProgramLocalParameter4fvARB == NULL);
+ glewInfoFunc("glProgramStringARB", glProgramStringARB == NULL);
+ glewInfoFunc("glVertexAttrib1dARB", glVertexAttrib1dARB == NULL);
+ glewInfoFunc("glVertexAttrib1dvARB", glVertexAttrib1dvARB == NULL);
+ glewInfoFunc("glVertexAttrib1fARB", glVertexAttrib1fARB == NULL);
+ glewInfoFunc("glVertexAttrib1fvARB", glVertexAttrib1fvARB == NULL);
+ glewInfoFunc("glVertexAttrib1sARB", glVertexAttrib1sARB == NULL);
+ glewInfoFunc("glVertexAttrib1svARB", glVertexAttrib1svARB == NULL);
+ glewInfoFunc("glVertexAttrib2dARB", glVertexAttrib2dARB == NULL);
+ glewInfoFunc("glVertexAttrib2dvARB", glVertexAttrib2dvARB == NULL);
+ glewInfoFunc("glVertexAttrib2fARB", glVertexAttrib2fARB == NULL);
+ glewInfoFunc("glVertexAttrib2fvARB", glVertexAttrib2fvARB == NULL);
+ glewInfoFunc("glVertexAttrib2sARB", glVertexAttrib2sARB == NULL);
+ glewInfoFunc("glVertexAttrib2svARB", glVertexAttrib2svARB == NULL);
+ glewInfoFunc("glVertexAttrib3dARB", glVertexAttrib3dARB == NULL);
+ glewInfoFunc("glVertexAttrib3dvARB", glVertexAttrib3dvARB == NULL);
+ glewInfoFunc("glVertexAttrib3fARB", glVertexAttrib3fARB == NULL);
+ glewInfoFunc("glVertexAttrib3fvARB", glVertexAttrib3fvARB == NULL);
+ glewInfoFunc("glVertexAttrib3sARB", glVertexAttrib3sARB == NULL);
+ glewInfoFunc("glVertexAttrib3svARB", glVertexAttrib3svARB == NULL);
+ glewInfoFunc("glVertexAttrib4NbvARB", glVertexAttrib4NbvARB == NULL);
+ glewInfoFunc("glVertexAttrib4NivARB", glVertexAttrib4NivARB == NULL);
+ glewInfoFunc("glVertexAttrib4NsvARB", glVertexAttrib4NsvARB == NULL);
+ glewInfoFunc("glVertexAttrib4NubARB", glVertexAttrib4NubARB == NULL);
+ glewInfoFunc("glVertexAttrib4NubvARB", glVertexAttrib4NubvARB == NULL);
+ glewInfoFunc("glVertexAttrib4NuivARB", glVertexAttrib4NuivARB == NULL);
+ glewInfoFunc("glVertexAttrib4NusvARB", glVertexAttrib4NusvARB == NULL);
+ glewInfoFunc("glVertexAttrib4bvARB", glVertexAttrib4bvARB == NULL);
+ glewInfoFunc("glVertexAttrib4dARB", glVertexAttrib4dARB == NULL);
+ glewInfoFunc("glVertexAttrib4dvARB", glVertexAttrib4dvARB == NULL);
+ glewInfoFunc("glVertexAttrib4fARB", glVertexAttrib4fARB == NULL);
+ glewInfoFunc("glVertexAttrib4fvARB", glVertexAttrib4fvARB == NULL);
+ glewInfoFunc("glVertexAttrib4ivARB", glVertexAttrib4ivARB == NULL);
+ glewInfoFunc("glVertexAttrib4sARB", glVertexAttrib4sARB == NULL);
+ glewInfoFunc("glVertexAttrib4svARB", glVertexAttrib4svARB == NULL);
+ glewInfoFunc("glVertexAttrib4ubvARB", glVertexAttrib4ubvARB == NULL);
+ glewInfoFunc("glVertexAttrib4uivARB", glVertexAttrib4uivARB == NULL);
+ glewInfoFunc("glVertexAttrib4usvARB", glVertexAttrib4usvARB == NULL);
+ glewInfoFunc("glVertexAttribPointerARB", glVertexAttribPointerARB == NULL);
+}
+
+#endif /* GL_ARB_vertex_program */
+
+#ifdef GL_ARB_vertex_shader
+
+static void _glewInfo_GL_ARB_vertex_shader (void)
+{
+ glewPrintExt("GL_ARB_vertex_shader", GLEW_ARB_vertex_shader, glewIsSupported("GL_ARB_vertex_shader"), glewGetExtension("GL_ARB_vertex_shader"));
+
+ glewInfoFunc("glBindAttribLocationARB", glBindAttribLocationARB == NULL);
+ glewInfoFunc("glGetActiveAttribARB", glGetActiveAttribARB == NULL);
+ glewInfoFunc("glGetAttribLocationARB", glGetAttribLocationARB == NULL);
+}
+
+#endif /* GL_ARB_vertex_shader */
+
+#ifdef GL_ARB_window_pos
+
+static void _glewInfo_GL_ARB_window_pos (void)
+{
+ glewPrintExt("GL_ARB_window_pos", GLEW_ARB_window_pos, glewIsSupported("GL_ARB_window_pos"), glewGetExtension("GL_ARB_window_pos"));
+
+ glewInfoFunc("glWindowPos2dARB", glWindowPos2dARB == NULL);
+ glewInfoFunc("glWindowPos2dvARB", glWindowPos2dvARB == NULL);
+ glewInfoFunc("glWindowPos2fARB", glWindowPos2fARB == NULL);
+ glewInfoFunc("glWindowPos2fvARB", glWindowPos2fvARB == NULL);
+ glewInfoFunc("glWindowPos2iARB", glWindowPos2iARB == NULL);
+ glewInfoFunc("glWindowPos2ivARB", glWindowPos2ivARB == NULL);
+ glewInfoFunc("glWindowPos2sARB", glWindowPos2sARB == NULL);
+ glewInfoFunc("glWindowPos2svARB", glWindowPos2svARB == NULL);
+ glewInfoFunc("glWindowPos3dARB", glWindowPos3dARB == NULL);
+ glewInfoFunc("glWindowPos3dvARB", glWindowPos3dvARB == NULL);
+ glewInfoFunc("glWindowPos3fARB", glWindowPos3fARB == NULL);
+ glewInfoFunc("glWindowPos3fvARB", glWindowPos3fvARB == NULL);
+ glewInfoFunc("glWindowPos3iARB", glWindowPos3iARB == NULL);
+ glewInfoFunc("glWindowPos3ivARB", glWindowPos3ivARB == NULL);
+ glewInfoFunc("glWindowPos3sARB", glWindowPos3sARB == NULL);
+ glewInfoFunc("glWindowPos3svARB", glWindowPos3svARB == NULL);
+}
+
+#endif /* GL_ARB_window_pos */
+
+#ifdef GL_ATIX_point_sprites
+
+static void _glewInfo_GL_ATIX_point_sprites (void)
+{
+ glewPrintExt("GL_ATIX_point_sprites", GLEW_ATIX_point_sprites, glewIsSupported("GL_ATIX_point_sprites"), glewGetExtension("GL_ATIX_point_sprites"));
+}
+
+#endif /* GL_ATIX_point_sprites */
+
+#ifdef GL_ATIX_texture_env_combine3
+
+static void _glewInfo_GL_ATIX_texture_env_combine3 (void)
+{
+ glewPrintExt("GL_ATIX_texture_env_combine3", GLEW_ATIX_texture_env_combine3, glewIsSupported("GL_ATIX_texture_env_combine3"), glewGetExtension("GL_ATIX_texture_env_combine3"));
+}
+
+#endif /* GL_ATIX_texture_env_combine3 */
+
+#ifdef GL_ATIX_texture_env_route
+
+static void _glewInfo_GL_ATIX_texture_env_route (void)
+{
+ glewPrintExt("GL_ATIX_texture_env_route", GLEW_ATIX_texture_env_route, glewIsSupported("GL_ATIX_texture_env_route"), glewGetExtension("GL_ATIX_texture_env_route"));
+}
+
+#endif /* GL_ATIX_texture_env_route */
+
+#ifdef GL_ATIX_vertex_shader_output_point_size
+
+static void _glewInfo_GL_ATIX_vertex_shader_output_point_size (void)
+{
+ glewPrintExt("GL_ATIX_vertex_shader_output_point_size", GLEW_ATIX_vertex_shader_output_point_size, glewIsSupported("GL_ATIX_vertex_shader_output_point_size"), glewGetExtension("GL_ATIX_vertex_shader_output_point_size"));
+}
+
+#endif /* GL_ATIX_vertex_shader_output_point_size */
+
+#ifdef GL_ATI_draw_buffers
+
+static void _glewInfo_GL_ATI_draw_buffers (void)
+{
+ glewPrintExt("GL_ATI_draw_buffers", GLEW_ATI_draw_buffers, glewIsSupported("GL_ATI_draw_buffers"), glewGetExtension("GL_ATI_draw_buffers"));
+
+ glewInfoFunc("glDrawBuffersATI", glDrawBuffersATI == NULL);
+}
+
+#endif /* GL_ATI_draw_buffers */
+
+#ifdef GL_ATI_element_array
+
+static void _glewInfo_GL_ATI_element_array (void)
+{
+ glewPrintExt("GL_ATI_element_array", GLEW_ATI_element_array, glewIsSupported("GL_ATI_element_array"), glewGetExtension("GL_ATI_element_array"));
+
+ glewInfoFunc("glDrawElementArrayATI", glDrawElementArrayATI == NULL);
+ glewInfoFunc("glDrawRangeElementArrayATI", glDrawRangeElementArrayATI == NULL);
+ glewInfoFunc("glElementPointerATI", glElementPointerATI == NULL);
+}
+
+#endif /* GL_ATI_element_array */
+
+#ifdef GL_ATI_envmap_bumpmap
+
+static void _glewInfo_GL_ATI_envmap_bumpmap (void)
+{
+ glewPrintExt("GL_ATI_envmap_bumpmap", GLEW_ATI_envmap_bumpmap, glewIsSupported("GL_ATI_envmap_bumpmap"), glewGetExtension("GL_ATI_envmap_bumpmap"));
+
+ glewInfoFunc("glGetTexBumpParameterfvATI", glGetTexBumpParameterfvATI == NULL);
+ glewInfoFunc("glGetTexBumpParameterivATI", glGetTexBumpParameterivATI == NULL);
+ glewInfoFunc("glTexBumpParameterfvATI", glTexBumpParameterfvATI == NULL);
+ glewInfoFunc("glTexBumpParameterivATI", glTexBumpParameterivATI == NULL);
+}
+
+#endif /* GL_ATI_envmap_bumpmap */
+
+#ifdef GL_ATI_fragment_shader
+
+static void _glewInfo_GL_ATI_fragment_shader (void)
+{
+ glewPrintExt("GL_ATI_fragment_shader", GLEW_ATI_fragment_shader, glewIsSupported("GL_ATI_fragment_shader"), glewGetExtension("GL_ATI_fragment_shader"));
+
+ glewInfoFunc("glAlphaFragmentOp1ATI", glAlphaFragmentOp1ATI == NULL);
+ glewInfoFunc("glAlphaFragmentOp2ATI", glAlphaFragmentOp2ATI == NULL);
+ glewInfoFunc("glAlphaFragmentOp3ATI", glAlphaFragmentOp3ATI == NULL);
+ glewInfoFunc("glBeginFragmentShaderATI", glBeginFragmentShaderATI == NULL);
+ glewInfoFunc("glBindFragmentShaderATI", glBindFragmentShaderATI == NULL);
+ glewInfoFunc("glColorFragmentOp1ATI", glColorFragmentOp1ATI == NULL);
+ glewInfoFunc("glColorFragmentOp2ATI", glColorFragmentOp2ATI == NULL);
+ glewInfoFunc("glColorFragmentOp3ATI", glColorFragmentOp3ATI == NULL);
+ glewInfoFunc("glDeleteFragmentShaderATI", glDeleteFragmentShaderATI == NULL);
+ glewInfoFunc("glEndFragmentShaderATI", glEndFragmentShaderATI == NULL);
+ glewInfoFunc("glGenFragmentShadersATI", glGenFragmentShadersATI == NULL);
+ glewInfoFunc("glPassTexCoordATI", glPassTexCoordATI == NULL);
+ glewInfoFunc("glSampleMapATI", glSampleMapATI == NULL);
+ glewInfoFunc("glSetFragmentShaderConstantATI", glSetFragmentShaderConstantATI == NULL);
+}
+
+#endif /* GL_ATI_fragment_shader */
+
+#ifdef GL_ATI_map_object_buffer
+
+static void _glewInfo_GL_ATI_map_object_buffer (void)
+{
+ glewPrintExt("GL_ATI_map_object_buffer", GLEW_ATI_map_object_buffer, glewIsSupported("GL_ATI_map_object_buffer"), glewGetExtension("GL_ATI_map_object_buffer"));
+
+ glewInfoFunc("glMapObjectBufferATI", glMapObjectBufferATI == NULL);
+ glewInfoFunc("glUnmapObjectBufferATI", glUnmapObjectBufferATI == NULL);
+}
+
+#endif /* GL_ATI_map_object_buffer */
+
+#ifdef GL_ATI_pn_triangles
+
+static void _glewInfo_GL_ATI_pn_triangles (void)
+{
+ glewPrintExt("GL_ATI_pn_triangles", GLEW_ATI_pn_triangles, glewIsSupported("GL_ATI_pn_triangles"), glewGetExtension("GL_ATI_pn_triangles"));
+
+ glewInfoFunc("glPNTrianglesfATI", glPNTrianglesfATI == NULL);
+ glewInfoFunc("glPNTrianglesiATI", glPNTrianglesiATI == NULL);
+}
+
+#endif /* GL_ATI_pn_triangles */
+
+#ifdef GL_ATI_separate_stencil
+
+static void _glewInfo_GL_ATI_separate_stencil (void)
+{
+ glewPrintExt("GL_ATI_separate_stencil", GLEW_ATI_separate_stencil, glewIsSupported("GL_ATI_separate_stencil"), glewGetExtension("GL_ATI_separate_stencil"));
+
+ glewInfoFunc("glStencilFuncSeparateATI", glStencilFuncSeparateATI == NULL);
+ glewInfoFunc("glStencilOpSeparateATI", glStencilOpSeparateATI == NULL);
+}
+
+#endif /* GL_ATI_separate_stencil */
+
+#ifdef GL_ATI_shader_texture_lod
+
+static void _glewInfo_GL_ATI_shader_texture_lod (void)
+{
+ glewPrintExt("GL_ATI_shader_texture_lod", GLEW_ATI_shader_texture_lod, glewIsSupported("GL_ATI_shader_texture_lod"), glewGetExtension("GL_ATI_shader_texture_lod"));
+}
+
+#endif /* GL_ATI_shader_texture_lod */
+
+#ifdef GL_ATI_text_fragment_shader
+
+static void _glewInfo_GL_ATI_text_fragment_shader (void)
+{
+ glewPrintExt("GL_ATI_text_fragment_shader", GLEW_ATI_text_fragment_shader, glewIsSupported("GL_ATI_text_fragment_shader"), glewGetExtension("GL_ATI_text_fragment_shader"));
+}
+
+#endif /* GL_ATI_text_fragment_shader */
+
+#ifdef GL_ATI_texture_compression_3dc
+
+static void _glewInfo_GL_ATI_texture_compression_3dc (void)
+{
+ glewPrintExt("GL_ATI_texture_compression_3dc", GLEW_ATI_texture_compression_3dc, glewIsSupported("GL_ATI_texture_compression_3dc"), glewGetExtension("GL_ATI_texture_compression_3dc"));
+}
+
+#endif /* GL_ATI_texture_compression_3dc */
+
+#ifdef GL_ATI_texture_env_combine3
+
+static void _glewInfo_GL_ATI_texture_env_combine3 (void)
+{
+ glewPrintExt("GL_ATI_texture_env_combine3", GLEW_ATI_texture_env_combine3, glewIsSupported("GL_ATI_texture_env_combine3"), glewGetExtension("GL_ATI_texture_env_combine3"));
+}
+
+#endif /* GL_ATI_texture_env_combine3 */
+
+#ifdef GL_ATI_texture_float
+
+static void _glewInfo_GL_ATI_texture_float (void)
+{
+ glewPrintExt("GL_ATI_texture_float", GLEW_ATI_texture_float, glewIsSupported("GL_ATI_texture_float"), glewGetExtension("GL_ATI_texture_float"));
+}
+
+#endif /* GL_ATI_texture_float */
+
+#ifdef GL_ATI_texture_mirror_once
+
+static void _glewInfo_GL_ATI_texture_mirror_once (void)
+{
+ glewPrintExt("GL_ATI_texture_mirror_once", GLEW_ATI_texture_mirror_once, glewIsSupported("GL_ATI_texture_mirror_once"), glewGetExtension("GL_ATI_texture_mirror_once"));
+}
+
+#endif /* GL_ATI_texture_mirror_once */
+
+#ifdef GL_ATI_vertex_array_object
+
+static void _glewInfo_GL_ATI_vertex_array_object (void)
+{
+ glewPrintExt("GL_ATI_vertex_array_object", GLEW_ATI_vertex_array_object, glewIsSupported("GL_ATI_vertex_array_object"), glewGetExtension("GL_ATI_vertex_array_object"));
+
+ glewInfoFunc("glArrayObjectATI", glArrayObjectATI == NULL);
+ glewInfoFunc("glFreeObjectBufferATI", glFreeObjectBufferATI == NULL);
+ glewInfoFunc("glGetArrayObjectfvATI", glGetArrayObjectfvATI == NULL);
+ glewInfoFunc("glGetArrayObjectivATI", glGetArrayObjectivATI == NULL);
+ glewInfoFunc("glGetObjectBufferfvATI", glGetObjectBufferfvATI == NULL);
+ glewInfoFunc("glGetObjectBufferivATI", glGetObjectBufferivATI == NULL);
+ glewInfoFunc("glGetVariantArrayObjectfvATI", glGetVariantArrayObjectfvATI == NULL);
+ glewInfoFunc("glGetVariantArrayObjectivATI", glGetVariantArrayObjectivATI == NULL);
+ glewInfoFunc("glIsObjectBufferATI", glIsObjectBufferATI == NULL);
+ glewInfoFunc("glNewObjectBufferATI", glNewObjectBufferATI == NULL);
+ glewInfoFunc("glUpdateObjectBufferATI", glUpdateObjectBufferATI == NULL);
+ glewInfoFunc("glVariantArrayObjectATI", glVariantArrayObjectATI == NULL);
+}
+
+#endif /* GL_ATI_vertex_array_object */
+
+#ifdef GL_ATI_vertex_attrib_array_object
+
+static void _glewInfo_GL_ATI_vertex_attrib_array_object (void)
+{
+ glewPrintExt("GL_ATI_vertex_attrib_array_object", GLEW_ATI_vertex_attrib_array_object, glewIsSupported("GL_ATI_vertex_attrib_array_object"), glewGetExtension("GL_ATI_vertex_attrib_array_object"));
+
+ glewInfoFunc("glGetVertexAttribArrayObjectfvATI", glGetVertexAttribArrayObjectfvATI == NULL);
+ glewInfoFunc("glGetVertexAttribArrayObjectivATI", glGetVertexAttribArrayObjectivATI == NULL);
+ glewInfoFunc("glVertexAttribArrayObjectATI", glVertexAttribArrayObjectATI == NULL);
+}
+
+#endif /* GL_ATI_vertex_attrib_array_object */
+
+#ifdef GL_ATI_vertex_streams
+
+static void _glewInfo_GL_ATI_vertex_streams (void)
+{
+ glewPrintExt("GL_ATI_vertex_streams", GLEW_ATI_vertex_streams, glewIsSupported("GL_ATI_vertex_streams"), glewGetExtension("GL_ATI_vertex_streams"));
+
+ glewInfoFunc("glClientActiveVertexStreamATI", glClientActiveVertexStreamATI == NULL);
+ glewInfoFunc("glNormalStream3bATI", glNormalStream3bATI == NULL);
+ glewInfoFunc("glNormalStream3bvATI", glNormalStream3bvATI == NULL);
+ glewInfoFunc("glNormalStream3dATI", glNormalStream3dATI == NULL);
+ glewInfoFunc("glNormalStream3dvATI", glNormalStream3dvATI == NULL);
+ glewInfoFunc("glNormalStream3fATI", glNormalStream3fATI == NULL);
+ glewInfoFunc("glNormalStream3fvATI", glNormalStream3fvATI == NULL);
+ glewInfoFunc("glNormalStream3iATI", glNormalStream3iATI == NULL);
+ glewInfoFunc("glNormalStream3ivATI", glNormalStream3ivATI == NULL);
+ glewInfoFunc("glNormalStream3sATI", glNormalStream3sATI == NULL);
+ glewInfoFunc("glNormalStream3svATI", glNormalStream3svATI == NULL);
+ glewInfoFunc("glVertexBlendEnvfATI", glVertexBlendEnvfATI == NULL);
+ glewInfoFunc("glVertexBlendEnviATI", glVertexBlendEnviATI == NULL);
+ glewInfoFunc("glVertexStream2dATI", glVertexStream2dATI == NULL);
+ glewInfoFunc("glVertexStream2dvATI", glVertexStream2dvATI == NULL);
+ glewInfoFunc("glVertexStream2fATI", glVertexStream2fATI == NULL);
+ glewInfoFunc("glVertexStream2fvATI", glVertexStream2fvATI == NULL);
+ glewInfoFunc("glVertexStream2iATI", glVertexStream2iATI == NULL);
+ glewInfoFunc("glVertexStream2ivATI", glVertexStream2ivATI == NULL);
+ glewInfoFunc("glVertexStream2sATI", glVertexStream2sATI == NULL);
+ glewInfoFunc("glVertexStream2svATI", glVertexStream2svATI == NULL);
+ glewInfoFunc("glVertexStream3dATI", glVertexStream3dATI == NULL);
+ glewInfoFunc("glVertexStream3dvATI", glVertexStream3dvATI == NULL);
+ glewInfoFunc("glVertexStream3fATI", glVertexStream3fATI == NULL);
+ glewInfoFunc("glVertexStream3fvATI", glVertexStream3fvATI == NULL);
+ glewInfoFunc("glVertexStream3iATI", glVertexStream3iATI == NULL);
+ glewInfoFunc("glVertexStream3ivATI", glVertexStream3ivATI == NULL);
+ glewInfoFunc("glVertexStream3sATI", glVertexStream3sATI == NULL);
+ glewInfoFunc("glVertexStream3svATI", glVertexStream3svATI == NULL);
+ glewInfoFunc("glVertexStream4dATI", glVertexStream4dATI == NULL);
+ glewInfoFunc("glVertexStream4dvATI", glVertexStream4dvATI == NULL);
+ glewInfoFunc("glVertexStream4fATI", glVertexStream4fATI == NULL);
+ glewInfoFunc("glVertexStream4fvATI", glVertexStream4fvATI == NULL);
+ glewInfoFunc("glVertexStream4iATI", glVertexStream4iATI == NULL);
+ glewInfoFunc("glVertexStream4ivATI", glVertexStream4ivATI == NULL);
+ glewInfoFunc("glVertexStream4sATI", glVertexStream4sATI == NULL);
+ glewInfoFunc("glVertexStream4svATI", glVertexStream4svATI == NULL);
+}
+
+#endif /* GL_ATI_vertex_streams */
+
+#ifdef GL_EXT_422_pixels
+
+static void _glewInfo_GL_EXT_422_pixels (void)
+{
+ glewPrintExt("GL_EXT_422_pixels", GLEW_EXT_422_pixels, glewIsSupported("GL_EXT_422_pixels"), glewGetExtension("GL_EXT_422_pixels"));
+}
+
+#endif /* GL_EXT_422_pixels */
+
+#ifdef GL_EXT_Cg_shader
+
+static void _glewInfo_GL_EXT_Cg_shader (void)
+{
+ glewPrintExt("GL_EXT_Cg_shader", GLEW_EXT_Cg_shader, glewIsSupported("GL_EXT_Cg_shader"), glewGetExtension("GL_EXT_Cg_shader"));
+}
+
+#endif /* GL_EXT_Cg_shader */
+
+#ifdef GL_EXT_abgr
+
+static void _glewInfo_GL_EXT_abgr (void)
+{
+ glewPrintExt("GL_EXT_abgr", GLEW_EXT_abgr, glewIsSupported("GL_EXT_abgr"), glewGetExtension("GL_EXT_abgr"));
+}
+
+#endif /* GL_EXT_abgr */
+
+#ifdef GL_EXT_bgra
+
+static void _glewInfo_GL_EXT_bgra (void)
+{
+ glewPrintExt("GL_EXT_bgra", GLEW_EXT_bgra, glewIsSupported("GL_EXT_bgra"), glewGetExtension("GL_EXT_bgra"));
+}
+
+#endif /* GL_EXT_bgra */
+
+#ifdef GL_EXT_bindable_uniform
+
+static void _glewInfo_GL_EXT_bindable_uniform (void)
+{
+ glewPrintExt("GL_EXT_bindable_uniform", GLEW_EXT_bindable_uniform, glewIsSupported("GL_EXT_bindable_uniform"), glewGetExtension("GL_EXT_bindable_uniform"));
+
+ glewInfoFunc("glGetUniformBufferSizeEXT", glGetUniformBufferSizeEXT == NULL);
+ glewInfoFunc("glGetUniformOffsetEXT", glGetUniformOffsetEXT == NULL);
+ glewInfoFunc("glUniformBufferEXT", glUniformBufferEXT == NULL);
+}
+
+#endif /* GL_EXT_bindable_uniform */
+
+#ifdef GL_EXT_blend_color
+
+static void _glewInfo_GL_EXT_blend_color (void)
+{
+ glewPrintExt("GL_EXT_blend_color", GLEW_EXT_blend_color, glewIsSupported("GL_EXT_blend_color"), glewGetExtension("GL_EXT_blend_color"));
+
+ glewInfoFunc("glBlendColorEXT", glBlendColorEXT == NULL);
+}
+
+#endif /* GL_EXT_blend_color */
+
+#ifdef GL_EXT_blend_equation_separate
+
+static void _glewInfo_GL_EXT_blend_equation_separate (void)
+{
+ glewPrintExt("GL_EXT_blend_equation_separate", GLEW_EXT_blend_equation_separate, glewIsSupported("GL_EXT_blend_equation_separate"), glewGetExtension("GL_EXT_blend_equation_separate"));
+
+ glewInfoFunc("glBlendEquationSeparateEXT", glBlendEquationSeparateEXT == NULL);
+}
+
+#endif /* GL_EXT_blend_equation_separate */
+
+#ifdef GL_EXT_blend_func_separate
+
+static void _glewInfo_GL_EXT_blend_func_separate (void)
+{
+ glewPrintExt("GL_EXT_blend_func_separate", GLEW_EXT_blend_func_separate, glewIsSupported("GL_EXT_blend_func_separate"), glewGetExtension("GL_EXT_blend_func_separate"));
+
+ glewInfoFunc("glBlendFuncSeparateEXT", glBlendFuncSeparateEXT == NULL);
+}
+
+#endif /* GL_EXT_blend_func_separate */
+
+#ifdef GL_EXT_blend_logic_op
+
+static void _glewInfo_GL_EXT_blend_logic_op (void)
+{
+ glewPrintExt("GL_EXT_blend_logic_op", GLEW_EXT_blend_logic_op, glewIsSupported("GL_EXT_blend_logic_op"), glewGetExtension("GL_EXT_blend_logic_op"));
+}
+
+#endif /* GL_EXT_blend_logic_op */
+
+#ifdef GL_EXT_blend_minmax
+
+static void _glewInfo_GL_EXT_blend_minmax (void)
+{
+ glewPrintExt("GL_EXT_blend_minmax", GLEW_EXT_blend_minmax, glewIsSupported("GL_EXT_blend_minmax"), glewGetExtension("GL_EXT_blend_minmax"));
+
+ glewInfoFunc("glBlendEquationEXT", glBlendEquationEXT == NULL);
+}
+
+#endif /* GL_EXT_blend_minmax */
+
+#ifdef GL_EXT_blend_subtract
+
+static void _glewInfo_GL_EXT_blend_subtract (void)
+{
+ glewPrintExt("GL_EXT_blend_subtract", GLEW_EXT_blend_subtract, glewIsSupported("GL_EXT_blend_subtract"), glewGetExtension("GL_EXT_blend_subtract"));
+}
+
+#endif /* GL_EXT_blend_subtract */
+
+#ifdef GL_EXT_clip_volume_hint
+
+static void _glewInfo_GL_EXT_clip_volume_hint (void)
+{
+ glewPrintExt("GL_EXT_clip_volume_hint", GLEW_EXT_clip_volume_hint, glewIsSupported("GL_EXT_clip_volume_hint"), glewGetExtension("GL_EXT_clip_volume_hint"));
+}
+
+#endif /* GL_EXT_clip_volume_hint */
+
+#ifdef GL_EXT_cmyka
+
+static void _glewInfo_GL_EXT_cmyka (void)
+{
+ glewPrintExt("GL_EXT_cmyka", GLEW_EXT_cmyka, glewIsSupported("GL_EXT_cmyka"), glewGetExtension("GL_EXT_cmyka"));
+}
+
+#endif /* GL_EXT_cmyka */
+
+#ifdef GL_EXT_color_subtable
+
+static void _glewInfo_GL_EXT_color_subtable (void)
+{
+ glewPrintExt("GL_EXT_color_subtable", GLEW_EXT_color_subtable, glewIsSupported("GL_EXT_color_subtable"), glewGetExtension("GL_EXT_color_subtable"));
+
+ glewInfoFunc("glColorSubTableEXT", glColorSubTableEXT == NULL);
+ glewInfoFunc("glCopyColorSubTableEXT", glCopyColorSubTableEXT == NULL);
+}
+
+#endif /* GL_EXT_color_subtable */
+
+#ifdef GL_EXT_compiled_vertex_array
+
+static void _glewInfo_GL_EXT_compiled_vertex_array (void)
+{
+ glewPrintExt("GL_EXT_compiled_vertex_array", GLEW_EXT_compiled_vertex_array, glewIsSupported("GL_EXT_compiled_vertex_array"), glewGetExtension("GL_EXT_compiled_vertex_array"));
+
+ glewInfoFunc("glLockArraysEXT", glLockArraysEXT == NULL);
+ glewInfoFunc("glUnlockArraysEXT", glUnlockArraysEXT == NULL);
+}
+
+#endif /* GL_EXT_compiled_vertex_array */
+
+#ifdef GL_EXT_convolution
+
+static void _glewInfo_GL_EXT_convolution (void)
+{
+ glewPrintExt("GL_EXT_convolution", GLEW_EXT_convolution, glewIsSupported("GL_EXT_convolution"), glewGetExtension("GL_EXT_convolution"));
+
+ glewInfoFunc("glConvolutionFilter1DEXT", glConvolutionFilter1DEXT == NULL);
+ glewInfoFunc("glConvolutionFilter2DEXT", glConvolutionFilter2DEXT == NULL);
+ glewInfoFunc("glConvolutionParameterfEXT", glConvolutionParameterfEXT == NULL);
+ glewInfoFunc("glConvolutionParameterfvEXT", glConvolutionParameterfvEXT == NULL);
+ glewInfoFunc("glConvolutionParameteriEXT", glConvolutionParameteriEXT == NULL);
+ glewInfoFunc("glConvolutionParameterivEXT", glConvolutionParameterivEXT == NULL);
+ glewInfoFunc("glCopyConvolutionFilter1DEXT", glCopyConvolutionFilter1DEXT == NULL);
+ glewInfoFunc("glCopyConvolutionFilter2DEXT", glCopyConvolutionFilter2DEXT == NULL);
+ glewInfoFunc("glGetConvolutionFilterEXT", glGetConvolutionFilterEXT == NULL);
+ glewInfoFunc("glGetConvolutionParameterfvEXT", glGetConvolutionParameterfvEXT == NULL);
+ glewInfoFunc("glGetConvolutionParameterivEXT", glGetConvolutionParameterivEXT == NULL);
+ glewInfoFunc("glGetSeparableFilterEXT", glGetSeparableFilterEXT == NULL);
+ glewInfoFunc("glSeparableFilter2DEXT", glSeparableFilter2DEXT == NULL);
+}
+
+#endif /* GL_EXT_convolution */
+
+#ifdef GL_EXT_coordinate_frame
+
+static void _glewInfo_GL_EXT_coordinate_frame (void)
+{
+ glewPrintExt("GL_EXT_coordinate_frame", GLEW_EXT_coordinate_frame, glewIsSupported("GL_EXT_coordinate_frame"), glewGetExtension("GL_EXT_coordinate_frame"));
+
+ glewInfoFunc("glBinormalPointerEXT", glBinormalPointerEXT == NULL);
+ glewInfoFunc("glTangentPointerEXT", glTangentPointerEXT == NULL);
+}
+
+#endif /* GL_EXT_coordinate_frame */
+
+#ifdef GL_EXT_copy_texture
+
+static void _glewInfo_GL_EXT_copy_texture (void)
+{
+ glewPrintExt("GL_EXT_copy_texture", GLEW_EXT_copy_texture, glewIsSupported("GL_EXT_copy_texture"), glewGetExtension("GL_EXT_copy_texture"));
+
+ glewInfoFunc("glCopyTexImage1DEXT", glCopyTexImage1DEXT == NULL);
+ glewInfoFunc("glCopyTexImage2DEXT", glCopyTexImage2DEXT == NULL);
+ glewInfoFunc("glCopyTexSubImage1DEXT", glCopyTexSubImage1DEXT == NULL);
+ glewInfoFunc("glCopyTexSubImage2DEXT", glCopyTexSubImage2DEXT == NULL);
+ glewInfoFunc("glCopyTexSubImage3DEXT", glCopyTexSubImage3DEXT == NULL);
+}
+
+#endif /* GL_EXT_copy_texture */
+
+#ifdef GL_EXT_cull_vertex
+
+static void _glewInfo_GL_EXT_cull_vertex (void)
+{
+ glewPrintExt("GL_EXT_cull_vertex", GLEW_EXT_cull_vertex, glewIsSupported("GL_EXT_cull_vertex"), glewGetExtension("GL_EXT_cull_vertex"));
+
+ glewInfoFunc("glCullParameterdvEXT", glCullParameterdvEXT == NULL);
+ glewInfoFunc("glCullParameterfvEXT", glCullParameterfvEXT == NULL);
+}
+
+#endif /* GL_EXT_cull_vertex */
+
+#ifdef GL_EXT_depth_bounds_test
+
+static void _glewInfo_GL_EXT_depth_bounds_test (void)
+{
+ glewPrintExt("GL_EXT_depth_bounds_test", GLEW_EXT_depth_bounds_test, glewIsSupported("GL_EXT_depth_bounds_test"), glewGetExtension("GL_EXT_depth_bounds_test"));
+
+ glewInfoFunc("glDepthBoundsEXT", glDepthBoundsEXT == NULL);
+}
+
+#endif /* GL_EXT_depth_bounds_test */
+
+#ifdef GL_EXT_direct_state_access
+
+static void _glewInfo_GL_EXT_direct_state_access (void)
+{
+ glewPrintExt("GL_EXT_direct_state_access", GLEW_EXT_direct_state_access, glewIsSupported("GL_EXT_direct_state_access"), glewGetExtension("GL_EXT_direct_state_access"));
+
+ glewInfoFunc("glBindMultiTextureEXT", glBindMultiTextureEXT == NULL);
+ glewInfoFunc("glCheckNamedFramebufferStatusEXT", glCheckNamedFramebufferStatusEXT == NULL);
+ glewInfoFunc("glClientAttribDefaultEXT", glClientAttribDefaultEXT == NULL);
+ glewInfoFunc("glCompressedMultiTexImage1DEXT", glCompressedMultiTexImage1DEXT == NULL);
+ glewInfoFunc("glCompressedMultiTexImage2DEXT", glCompressedMultiTexImage2DEXT == NULL);
+ glewInfoFunc("glCompressedMultiTexImage3DEXT", glCompressedMultiTexImage3DEXT == NULL);
+ glewInfoFunc("glCompressedMultiTexSubImage1DEXT", glCompressedMultiTexSubImage1DEXT == NULL);
+ glewInfoFunc("glCompressedMultiTexSubImage2DEXT", glCompressedMultiTexSubImage2DEXT == NULL);
+ glewInfoFunc("glCompressedMultiTexSubImage3DEXT", glCompressedMultiTexSubImage3DEXT == NULL);
+ glewInfoFunc("glCompressedTextureImage1DEXT", glCompressedTextureImage1DEXT == NULL);
+ glewInfoFunc("glCompressedTextureImage2DEXT", glCompressedTextureImage2DEXT == NULL);
+ glewInfoFunc("glCompressedTextureImage3DEXT", glCompressedTextureImage3DEXT == NULL);
+ glewInfoFunc("glCompressedTextureSubImage1DEXT", glCompressedTextureSubImage1DEXT == NULL);
+ glewInfoFunc("glCompressedTextureSubImage2DEXT", glCompressedTextureSubImage2DEXT == NULL);
+ glewInfoFunc("glCompressedTextureSubImage3DEXT", glCompressedTextureSubImage3DEXT == NULL);
+ glewInfoFunc("glCopyMultiTexImage1DEXT", glCopyMultiTexImage1DEXT == NULL);
+ glewInfoFunc("glCopyMultiTexImage2DEXT", glCopyMultiTexImage2DEXT == NULL);
+ glewInfoFunc("glCopyMultiTexSubImage1DEXT", glCopyMultiTexSubImage1DEXT == NULL);
+ glewInfoFunc("glCopyMultiTexSubImage2DEXT", glCopyMultiTexSubImage2DEXT == NULL);
+ glewInfoFunc("glCopyMultiTexSubImage3DEXT", glCopyMultiTexSubImage3DEXT == NULL);
+ glewInfoFunc("glCopyTextureImage1DEXT", glCopyTextureImage1DEXT == NULL);
+ glewInfoFunc("glCopyTextureImage2DEXT", glCopyTextureImage2DEXT == NULL);
+ glewInfoFunc("glCopyTextureSubImage1DEXT", glCopyTextureSubImage1DEXT == NULL);
+ glewInfoFunc("glCopyTextureSubImage2DEXT", glCopyTextureSubImage2DEXT == NULL);
+ glewInfoFunc("glCopyTextureSubImage3DEXT", glCopyTextureSubImage3DEXT == NULL);
+ glewInfoFunc("glDisableClientStateIndexedEXT", glDisableClientStateIndexedEXT == NULL);
+ glewInfoFunc("glEnableClientStateIndexedEXT", glEnableClientStateIndexedEXT == NULL);
+ glewInfoFunc("glFramebufferDrawBufferEXT", glFramebufferDrawBufferEXT == NULL);
+ glewInfoFunc("glFramebufferDrawBuffersEXT", glFramebufferDrawBuffersEXT == NULL);
+ glewInfoFunc("glFramebufferReadBufferEXT", glFramebufferReadBufferEXT == NULL);
+ glewInfoFunc("glGenerateMultiTexMipmapEXT", glGenerateMultiTexMipmapEXT == NULL);
+ glewInfoFunc("glGenerateTextureMipmapEXT", glGenerateTextureMipmapEXT == NULL);
+ glewInfoFunc("glGetCompressedMultiTexImageEXT", glGetCompressedMultiTexImageEXT == NULL);
+ glewInfoFunc("glGetCompressedTextureImageEXT", glGetCompressedTextureImageEXT == NULL);
+ glewInfoFunc("glGetDoubleIndexedvEXT", glGetDoubleIndexedvEXT == NULL);
+ glewInfoFunc("glGetFloatIndexedvEXT", glGetFloatIndexedvEXT == NULL);
+ glewInfoFunc("glGetFramebufferParameterivEXT", glGetFramebufferParameterivEXT == NULL);
+ glewInfoFunc("glGetMultiTexEnvfvEXT", glGetMultiTexEnvfvEXT == NULL);
+ glewInfoFunc("glGetMultiTexEnvivEXT", glGetMultiTexEnvivEXT == NULL);
+ glewInfoFunc("glGetMultiTexGendvEXT", glGetMultiTexGendvEXT == NULL);
+ glewInfoFunc("glGetMultiTexGenfvEXT", glGetMultiTexGenfvEXT == NULL);
+ glewInfoFunc("glGetMultiTexGenivEXT", glGetMultiTexGenivEXT == NULL);
+ glewInfoFunc("glGetMultiTexImageEXT", glGetMultiTexImageEXT == NULL);
+ glewInfoFunc("glGetMultiTexLevelParameterfvEXT", glGetMultiTexLevelParameterfvEXT == NULL);
+ glewInfoFunc("glGetMultiTexLevelParameterivEXT", glGetMultiTexLevelParameterivEXT == NULL);
+ glewInfoFunc("glGetMultiTexParameterIivEXT", glGetMultiTexParameterIivEXT == NULL);
+ glewInfoFunc("glGetMultiTexParameterIuivEXT", glGetMultiTexParameterIuivEXT == NULL);
+ glewInfoFunc("glGetMultiTexParameterfvEXT", glGetMultiTexParameterfvEXT == NULL);
+ glewInfoFunc("glGetMultiTexParameterivEXT", glGetMultiTexParameterivEXT == NULL);
+ glewInfoFunc("glGetNamedBufferParameterivEXT", glGetNamedBufferParameterivEXT == NULL);
+ glewInfoFunc("glGetNamedBufferPointervEXT", glGetNamedBufferPointervEXT == NULL);
+ glewInfoFunc("glGetNamedBufferSubDataEXT", glGetNamedBufferSubDataEXT == NULL);
+ glewInfoFunc("glGetNamedFramebufferAttachmentParameterivEXT", glGetNamedFramebufferAttachmentParameterivEXT == NULL);
+ glewInfoFunc("glGetNamedProgramLocalParameterIivEXT", glGetNamedProgramLocalParameterIivEXT == NULL);
+ glewInfoFunc("glGetNamedProgramLocalParameterIuivEXT", glGetNamedProgramLocalParameterIuivEXT == NULL);
+ glewInfoFunc("glGetNamedProgramLocalParameterdvEXT", glGetNamedProgramLocalParameterdvEXT == NULL);
+ glewInfoFunc("glGetNamedProgramLocalParameterfvEXT", glGetNamedProgramLocalParameterfvEXT == NULL);
+ glewInfoFunc("glGetNamedProgramStringEXT", glGetNamedProgramStringEXT == NULL);
+ glewInfoFunc("glGetNamedProgramivEXT", glGetNamedProgramivEXT == NULL);
+ glewInfoFunc("glGetNamedRenderbufferParameterivEXT", glGetNamedRenderbufferParameterivEXT == NULL);
+ glewInfoFunc("glGetPointerIndexedvEXT", glGetPointerIndexedvEXT == NULL);
+ glewInfoFunc("glGetTextureImageEXT", glGetTextureImageEXT == NULL);
+ glewInfoFunc("glGetTextureLevelParameterfvEXT", glGetTextureLevelParameterfvEXT == NULL);
+ glewInfoFunc("glGetTextureLevelParameterivEXT", glGetTextureLevelParameterivEXT == NULL);
+ glewInfoFunc("glGetTextureParameterIivEXT", glGetTextureParameterIivEXT == NULL);
+ glewInfoFunc("glGetTextureParameterIuivEXT", glGetTextureParameterIuivEXT == NULL);
+ glewInfoFunc("glGetTextureParameterfvEXT", glGetTextureParameterfvEXT == NULL);
+ glewInfoFunc("glGetTextureParameterivEXT", glGetTextureParameterivEXT == NULL);
+ glewInfoFunc("glMapNamedBufferEXT", glMapNamedBufferEXT == NULL);
+ glewInfoFunc("glMatrixFrustumEXT", glMatrixFrustumEXT == NULL);
+ glewInfoFunc("glMatrixLoadIdentityEXT", glMatrixLoadIdentityEXT == NULL);
+ glewInfoFunc("glMatrixLoadTransposedEXT", glMatrixLoadTransposedEXT == NULL);
+ glewInfoFunc("glMatrixLoadTransposefEXT", glMatrixLoadTransposefEXT == NULL);
+ glewInfoFunc("glMatrixLoaddEXT", glMatrixLoaddEXT == NULL);
+ glewInfoFunc("glMatrixLoadfEXT", glMatrixLoadfEXT == NULL);
+ glewInfoFunc("glMatrixMultTransposedEXT", glMatrixMultTransposedEXT == NULL);
+ glewInfoFunc("glMatrixMultTransposefEXT", glMatrixMultTransposefEXT == NULL);
+ glewInfoFunc("glMatrixMultdEXT", glMatrixMultdEXT == NULL);
+ glewInfoFunc("glMatrixMultfEXT", glMatrixMultfEXT == NULL);
+ glewInfoFunc("glMatrixOrthoEXT", glMatrixOrthoEXT == NULL);
+ glewInfoFunc("glMatrixPopEXT", glMatrixPopEXT == NULL);
+ glewInfoFunc("glMatrixPushEXT", glMatrixPushEXT == NULL);
+ glewInfoFunc("glMatrixRotatedEXT", glMatrixRotatedEXT == NULL);
+ glewInfoFunc("glMatrixRotatefEXT", glMatrixRotatefEXT == NULL);
+ glewInfoFunc("glMatrixScaledEXT", glMatrixScaledEXT == NULL);
+ glewInfoFunc("glMatrixScalefEXT", glMatrixScalefEXT == NULL);
+ glewInfoFunc("glMatrixTranslatedEXT", glMatrixTranslatedEXT == NULL);
+ glewInfoFunc("glMatrixTranslatefEXT", glMatrixTranslatefEXT == NULL);
+ glewInfoFunc("glMultiTexBufferEXT", glMultiTexBufferEXT == NULL);
+ glewInfoFunc("glMultiTexCoordPointerEXT", glMultiTexCoordPointerEXT == NULL);
+ glewInfoFunc("glMultiTexEnvfEXT", glMultiTexEnvfEXT == NULL);
+ glewInfoFunc("glMultiTexEnvfvEXT", glMultiTexEnvfvEXT == NULL);
+ glewInfoFunc("glMultiTexEnviEXT", glMultiTexEnviEXT == NULL);
+ glewInfoFunc("glMultiTexEnvivEXT", glMultiTexEnvivEXT == NULL);
+ glewInfoFunc("glMultiTexGendEXT", glMultiTexGendEXT == NULL);
+ glewInfoFunc("glMultiTexGendvEXT", glMultiTexGendvEXT == NULL);
+ glewInfoFunc("glMultiTexGenfEXT", glMultiTexGenfEXT == NULL);
+ glewInfoFunc("glMultiTexGenfvEXT", glMultiTexGenfvEXT == NULL);
+ glewInfoFunc("glMultiTexGeniEXT", glMultiTexGeniEXT == NULL);
+ glewInfoFunc("glMultiTexGenivEXT", glMultiTexGenivEXT == NULL);
+ glewInfoFunc("glMultiTexImage1DEXT", glMultiTexImage1DEXT == NULL);
+ glewInfoFunc("glMultiTexImage2DEXT", glMultiTexImage2DEXT == NULL);
+ glewInfoFunc("glMultiTexImage3DEXT", glMultiTexImage3DEXT == NULL);
+ glewInfoFunc("glMultiTexParameterIivEXT", glMultiTexParameterIivEXT == NULL);
+ glewInfoFunc("glMultiTexParameterIuivEXT", glMultiTexParameterIuivEXT == NULL);
+ glewInfoFunc("glMultiTexParameterfEXT", glMultiTexParameterfEXT == NULL);
+ glewInfoFunc("glMultiTexParameterfvEXT", glMultiTexParameterfvEXT == NULL);
+ glewInfoFunc("glMultiTexParameteriEXT", glMultiTexParameteriEXT == NULL);
+ glewInfoFunc("glMultiTexParameterivEXT", glMultiTexParameterivEXT == NULL);
+ glewInfoFunc("glMultiTexRenderbufferEXT", glMultiTexRenderbufferEXT == NULL);
+ glewInfoFunc("glMultiTexSubImage1DEXT", glMultiTexSubImage1DEXT == NULL);
+ glewInfoFunc("glMultiTexSubImage2DEXT", glMultiTexSubImage2DEXT == NULL);
+ glewInfoFunc("glMultiTexSubImage3DEXT", glMultiTexSubImage3DEXT == NULL);
+ glewInfoFunc("glNamedBufferDataEXT", glNamedBufferDataEXT == NULL);
+ glewInfoFunc("glNamedBufferSubDataEXT", glNamedBufferSubDataEXT == NULL);
+ glewInfoFunc("glNamedFramebufferRenderbufferEXT", glNamedFramebufferRenderbufferEXT == NULL);
+ glewInfoFunc("glNamedFramebufferTexture1DEXT", glNamedFramebufferTexture1DEXT == NULL);
+ glewInfoFunc("glNamedFramebufferTexture2DEXT", glNamedFramebufferTexture2DEXT == NULL);
+ glewInfoFunc("glNamedFramebufferTexture3DEXT", glNamedFramebufferTexture3DEXT == NULL);
+ glewInfoFunc("glNamedFramebufferTextureEXT", glNamedFramebufferTextureEXT == NULL);
+ glewInfoFunc("glNamedFramebufferTextureFaceEXT", glNamedFramebufferTextureFaceEXT == NULL);
+ glewInfoFunc("glNamedFramebufferTextureLayerEXT", glNamedFramebufferTextureLayerEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParameter4dEXT", glNamedProgramLocalParameter4dEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParameter4dvEXT", glNamedProgramLocalParameter4dvEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParameter4fEXT", glNamedProgramLocalParameter4fEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParameter4fvEXT", glNamedProgramLocalParameter4fvEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParameterI4iEXT", glNamedProgramLocalParameterI4iEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParameterI4ivEXT", glNamedProgramLocalParameterI4ivEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParameterI4uiEXT", glNamedProgramLocalParameterI4uiEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParameterI4uivEXT", glNamedProgramLocalParameterI4uivEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParameters4fvEXT", glNamedProgramLocalParameters4fvEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParametersI4ivEXT", glNamedProgramLocalParametersI4ivEXT == NULL);
+ glewInfoFunc("glNamedProgramLocalParametersI4uivEXT", glNamedProgramLocalParametersI4uivEXT == NULL);
+ glewInfoFunc("glNamedProgramStringEXT", glNamedProgramStringEXT == NULL);
+ glewInfoFunc("glNamedRenderbufferStorageEXT", glNamedRenderbufferStorageEXT == NULL);
+ glewInfoFunc("glNamedRenderbufferStorageMultisampleCoverageEXT", glNamedRenderbufferStorageMultisampleCoverageEXT == NULL);
+ glewInfoFunc("glNamedRenderbufferStorageMultisampleEXT", glNamedRenderbufferStorageMultisampleEXT == NULL);
+ glewInfoFunc("glProgramUniform1fEXT", glProgramUniform1fEXT == NULL);
+ glewInfoFunc("glProgramUniform1fvEXT", glProgramUniform1fvEXT == NULL);
+ glewInfoFunc("glProgramUniform1iEXT", glProgramUniform1iEXT == NULL);
+ glewInfoFunc("glProgramUniform1ivEXT", glProgramUniform1ivEXT == NULL);
+ glewInfoFunc("glProgramUniform1uiEXT", glProgramUniform1uiEXT == NULL);
+ glewInfoFunc("glProgramUniform1uivEXT", glProgramUniform1uivEXT == NULL);
+ glewInfoFunc("glProgramUniform2fEXT", glProgramUniform2fEXT == NULL);
+ glewInfoFunc("glProgramUniform2fvEXT", glProgramUniform2fvEXT == NULL);
+ glewInfoFunc("glProgramUniform2iEXT", glProgramUniform2iEXT == NULL);
+ glewInfoFunc("glProgramUniform2ivEXT", glProgramUniform2ivEXT == NULL);
+ glewInfoFunc("glProgramUniform2uiEXT", glProgramUniform2uiEXT == NULL);
+ glewInfoFunc("glProgramUniform2uivEXT", glProgramUniform2uivEXT == NULL);
+ glewInfoFunc("glProgramUniform3fEXT", glProgramUniform3fEXT == NULL);
+ glewInfoFunc("glProgramUniform3fvEXT", glProgramUniform3fvEXT == NULL);
+ glewInfoFunc("glProgramUniform3iEXT", glProgramUniform3iEXT == NULL);
+ glewInfoFunc("glProgramUniform3ivEXT", glProgramUniform3ivEXT == NULL);
+ glewInfoFunc("glProgramUniform3uiEXT", glProgramUniform3uiEXT == NULL);
+ glewInfoFunc("glProgramUniform3uivEXT", glProgramUniform3uivEXT == NULL);
+ glewInfoFunc("glProgramUniform4fEXT", glProgramUniform4fEXT == NULL);
+ glewInfoFunc("glProgramUniform4fvEXT", glProgramUniform4fvEXT == NULL);
+ glewInfoFunc("glProgramUniform4iEXT", glProgramUniform4iEXT == NULL);
+ glewInfoFunc("glProgramUniform4ivEXT", glProgramUniform4ivEXT == NULL);
+ glewInfoFunc("glProgramUniform4uiEXT", glProgramUniform4uiEXT == NULL);
+ glewInfoFunc("glProgramUniform4uivEXT", glProgramUniform4uivEXT == NULL);
+ glewInfoFunc("glProgramUniformMatrix2fvEXT", glProgramUniformMatrix2fvEXT == NULL);
+ glewInfoFunc("glProgramUniformMatrix2x3fvEXT", glProgramUniformMatrix2x3fvEXT == NULL);
+ glewInfoFunc("glProgramUniformMatrix2x4fvEXT", glProgramUniformMatrix2x4fvEXT == NULL);
+ glewInfoFunc("glProgramUniformMatrix3fvEXT", glProgramUniformMatrix3fvEXT == NULL);
+ glewInfoFunc("glProgramUniformMatrix3x2fvEXT", glProgramUniformMatrix3x2fvEXT == NULL);
+ glewInfoFunc("glProgramUniformMatrix3x4fvEXT", glProgramUniformMatrix3x4fvEXT == NULL);
+ glewInfoFunc("glProgramUniformMatrix4fvEXT", glProgramUniformMatrix4fvEXT == NULL);
+ glewInfoFunc("glProgramUniformMatrix4x2fvEXT", glProgramUniformMatrix4x2fvEXT == NULL);
+ glewInfoFunc("glProgramUniformMatrix4x3fvEXT", glProgramUniformMatrix4x3fvEXT == NULL);
+ glewInfoFunc("glPushClientAttribDefaultEXT", glPushClientAttribDefaultEXT == NULL);
+ glewInfoFunc("glTextureBufferEXT", glTextureBufferEXT == NULL);
+ glewInfoFunc("glTextureImage1DEXT", glTextureImage1DEXT == NULL);
+ glewInfoFunc("glTextureImage2DEXT", glTextureImage2DEXT == NULL);
+ glewInfoFunc("glTextureImage3DEXT", glTextureImage3DEXT == NULL);
+ glewInfoFunc("glTextureParameterIivEXT", glTextureParameterIivEXT == NULL);
+ glewInfoFunc("glTextureParameterIuivEXT", glTextureParameterIuivEXT == NULL);
+ glewInfoFunc("glTextureParameterfEXT", glTextureParameterfEXT == NULL);
+ glewInfoFunc("glTextureParameterfvEXT", glTextureParameterfvEXT == NULL);
+ glewInfoFunc("glTextureParameteriEXT", glTextureParameteriEXT == NULL);
+ glewInfoFunc("glTextureParameterivEXT", glTextureParameterivEXT == NULL);
+ glewInfoFunc("glTextureRenderbufferEXT", glTextureRenderbufferEXT == NULL);
+ glewInfoFunc("glTextureSubImage1DEXT", glTextureSubImage1DEXT == NULL);
+ glewInfoFunc("glTextureSubImage2DEXT", glTextureSubImage2DEXT == NULL);
+ glewInfoFunc("glTextureSubImage3DEXT", glTextureSubImage3DEXT == NULL);
+ glewInfoFunc("glUnmapNamedBufferEXT", glUnmapNamedBufferEXT == NULL);
+}
+
+#endif /* GL_EXT_direct_state_access */
+
+#ifdef GL_EXT_draw_buffers2
+
+static void _glewInfo_GL_EXT_draw_buffers2 (void)
+{
+ glewPrintExt("GL_EXT_draw_buffers2", GLEW_EXT_draw_buffers2, glewIsSupported("GL_EXT_draw_buffers2"), glewGetExtension("GL_EXT_draw_buffers2"));
+
+ glewInfoFunc("glColorMaskIndexedEXT", glColorMaskIndexedEXT == NULL);
+ glewInfoFunc("glDisableIndexedEXT", glDisableIndexedEXT == NULL);
+ glewInfoFunc("glEnableIndexedEXT", glEnableIndexedEXT == NULL);
+ glewInfoFunc("glGetBooleanIndexedvEXT", glGetBooleanIndexedvEXT == NULL);
+ glewInfoFunc("glGetIntegerIndexedvEXT", glGetIntegerIndexedvEXT == NULL);
+ glewInfoFunc("glIsEnabledIndexedEXT", glIsEnabledIndexedEXT == NULL);
+}
+
+#endif /* GL_EXT_draw_buffers2 */
+
+#ifdef GL_EXT_draw_instanced
+
+static void _glewInfo_GL_EXT_draw_instanced (void)
+{
+ glewPrintExt("GL_EXT_draw_instanced", GLEW_EXT_draw_instanced, glewIsSupported("GL_EXT_draw_instanced"), glewGetExtension("GL_EXT_draw_instanced"));
+
+ glewInfoFunc("glDrawArraysInstancedEXT", glDrawArraysInstancedEXT == NULL);
+ glewInfoFunc("glDrawElementsInstancedEXT", glDrawElementsInstancedEXT == NULL);
+}
+
+#endif /* GL_EXT_draw_instanced */
+
+#ifdef GL_EXT_draw_range_elements
+
+static void _glewInfo_GL_EXT_draw_range_elements (void)
+{
+ glewPrintExt("GL_EXT_draw_range_elements", GLEW_EXT_draw_range_elements, glewIsSupported("GL_EXT_draw_range_elements"), glewGetExtension("GL_EXT_draw_range_elements"));
+
+ glewInfoFunc("glDrawRangeElementsEXT", glDrawRangeElementsEXT == NULL);
+}
+
+#endif /* GL_EXT_draw_range_elements */
+
+#ifdef GL_EXT_fog_coord
+
+static void _glewInfo_GL_EXT_fog_coord (void)
+{
+ glewPrintExt("GL_EXT_fog_coord", GLEW_EXT_fog_coord, glewIsSupported("GL_EXT_fog_coord"), glewGetExtension("GL_EXT_fog_coord"));
+
+ glewInfoFunc("glFogCoordPointerEXT", glFogCoordPointerEXT == NULL);
+ glewInfoFunc("glFogCoorddEXT", glFogCoorddEXT == NULL);
+ glewInfoFunc("glFogCoorddvEXT", glFogCoorddvEXT == NULL);
+ glewInfoFunc("glFogCoordfEXT", glFogCoordfEXT == NULL);
+ glewInfoFunc("glFogCoordfvEXT", glFogCoordfvEXT == NULL);
+}
+
+#endif /* GL_EXT_fog_coord */
+
+#ifdef GL_EXT_fragment_lighting
+
+static void _glewInfo_GL_EXT_fragment_lighting (void)
+{
+ glewPrintExt("GL_EXT_fragment_lighting", GLEW_EXT_fragment_lighting, glewIsSupported("GL_EXT_fragment_lighting"), glewGetExtension("GL_EXT_fragment_lighting"));
+
+ glewInfoFunc("glFragmentColorMaterialEXT", glFragmentColorMaterialEXT == NULL);
+ glewInfoFunc("glFragmentLightModelfEXT", glFragmentLightModelfEXT == NULL);
+ glewInfoFunc("glFragmentLightModelfvEXT", glFragmentLightModelfvEXT == NULL);
+ glewInfoFunc("glFragmentLightModeliEXT", glFragmentLightModeliEXT == NULL);
+ glewInfoFunc("glFragmentLightModelivEXT", glFragmentLightModelivEXT == NULL);
+ glewInfoFunc("glFragmentLightfEXT", glFragmentLightfEXT == NULL);
+ glewInfoFunc("glFragmentLightfvEXT", glFragmentLightfvEXT == NULL);
+ glewInfoFunc("glFragmentLightiEXT", glFragmentLightiEXT == NULL);
+ glewInfoFunc("glFragmentLightivEXT", glFragmentLightivEXT == NULL);
+ glewInfoFunc("glFragmentMaterialfEXT", glFragmentMaterialfEXT == NULL);
+ glewInfoFunc("glFragmentMaterialfvEXT", glFragmentMaterialfvEXT == NULL);
+ glewInfoFunc("glFragmentMaterialiEXT", glFragmentMaterialiEXT == NULL);
+ glewInfoFunc("glFragmentMaterialivEXT", glFragmentMaterialivEXT == NULL);
+ glewInfoFunc("glGetFragmentLightfvEXT", glGetFragmentLightfvEXT == NULL);
+ glewInfoFunc("glGetFragmentLightivEXT", glGetFragmentLightivEXT == NULL);
+ glewInfoFunc("glGetFragmentMaterialfvEXT", glGetFragmentMaterialfvEXT == NULL);
+ glewInfoFunc("glGetFragmentMaterialivEXT", glGetFragmentMaterialivEXT == NULL);
+ glewInfoFunc("glLightEnviEXT", glLightEnviEXT == NULL);
+}
+
+#endif /* GL_EXT_fragment_lighting */
+
+#ifdef GL_EXT_framebuffer_blit
+
+static void _glewInfo_GL_EXT_framebuffer_blit (void)
+{
+ glewPrintExt("GL_EXT_framebuffer_blit", GLEW_EXT_framebuffer_blit, glewIsSupported("GL_EXT_framebuffer_blit"), glewGetExtension("GL_EXT_framebuffer_blit"));
+
+ glewInfoFunc("glBlitFramebufferEXT", glBlitFramebufferEXT == NULL);
+}
+
+#endif /* GL_EXT_framebuffer_blit */
+
+#ifdef GL_EXT_framebuffer_multisample
+
+static void _glewInfo_GL_EXT_framebuffer_multisample (void)
+{
+ glewPrintExt("GL_EXT_framebuffer_multisample", GLEW_EXT_framebuffer_multisample, glewIsSupported("GL_EXT_framebuffer_multisample"), glewGetExtension("GL_EXT_framebuffer_multisample"));
+
+ glewInfoFunc("glRenderbufferStorageMultisampleEXT", glRenderbufferStorageMultisampleEXT == NULL);
+}
+
+#endif /* GL_EXT_framebuffer_multisample */
+
+#ifdef GL_EXT_framebuffer_object
+
+static void _glewInfo_GL_EXT_framebuffer_object (void)
+{
+ glewPrintExt("GL_EXT_framebuffer_object", GLEW_EXT_framebuffer_object, glewIsSupported("GL_EXT_framebuffer_object"), glewGetExtension("GL_EXT_framebuffer_object"));
+
+ glewInfoFunc("glBindFramebufferEXT", glBindFramebufferEXT == NULL);
+ glewInfoFunc("glBindRenderbufferEXT", glBindRenderbufferEXT == NULL);
+ glewInfoFunc("glCheckFramebufferStatusEXT", glCheckFramebufferStatusEXT == NULL);
+ glewInfoFunc("glDeleteFramebuffersEXT", glDeleteFramebuffersEXT == NULL);
+ glewInfoFunc("glDeleteRenderbuffersEXT", glDeleteRenderbuffersEXT == NULL);
+ glewInfoFunc("glFramebufferRenderbufferEXT", glFramebufferRenderbufferEXT == NULL);
+ glewInfoFunc("glFramebufferTexture1DEXT", glFramebufferTexture1DEXT == NULL);
+ glewInfoFunc("glFramebufferTexture2DEXT", glFramebufferTexture2DEXT == NULL);
+ glewInfoFunc("glFramebufferTexture3DEXT", glFramebufferTexture3DEXT == NULL);
+ glewInfoFunc("glGenFramebuffersEXT", glGenFramebuffersEXT == NULL);
+ glewInfoFunc("glGenRenderbuffersEXT", glGenRenderbuffersEXT == NULL);
+ glewInfoFunc("glGenerateMipmapEXT", glGenerateMipmapEXT == NULL);
+ glewInfoFunc("glGetFramebufferAttachmentParameterivEXT", glGetFramebufferAttachmentParameterivEXT == NULL);
+ glewInfoFunc("glGetRenderbufferParameterivEXT", glGetRenderbufferParameterivEXT == NULL);
+ glewInfoFunc("glIsFramebufferEXT", glIsFramebufferEXT == NULL);
+ glewInfoFunc("glIsRenderbufferEXT", glIsRenderbufferEXT == NULL);
+ glewInfoFunc("glRenderbufferStorageEXT", glRenderbufferStorageEXT == NULL);
+}
+
+#endif /* GL_EXT_framebuffer_object */
+
+#ifdef GL_EXT_framebuffer_sRGB
+
+static void _glewInfo_GL_EXT_framebuffer_sRGB (void)
+{
+ glewPrintExt("GL_EXT_framebuffer_sRGB", GLEW_EXT_framebuffer_sRGB, glewIsSupported("GL_EXT_framebuffer_sRGB"), glewGetExtension("GL_EXT_framebuffer_sRGB"));
+}
+
+#endif /* GL_EXT_framebuffer_sRGB */
+
+#ifdef GL_EXT_geometry_shader4
+
+static void _glewInfo_GL_EXT_geometry_shader4 (void)
+{
+ glewPrintExt("GL_EXT_geometry_shader4", GLEW_EXT_geometry_shader4, glewIsSupported("GL_EXT_geometry_shader4"), glewGetExtension("GL_EXT_geometry_shader4"));
+
+ glewInfoFunc("glFramebufferTextureEXT", glFramebufferTextureEXT == NULL);
+ glewInfoFunc("glFramebufferTextureFaceEXT", glFramebufferTextureFaceEXT == NULL);
+ glewInfoFunc("glFramebufferTextureLayerEXT", glFramebufferTextureLayerEXT == NULL);
+ glewInfoFunc("glProgramParameteriEXT", glProgramParameteriEXT == NULL);
+}
+
+#endif /* GL_EXT_geometry_shader4 */
+
+#ifdef GL_EXT_gpu_program_parameters
+
+static void _glewInfo_GL_EXT_gpu_program_parameters (void)
+{
+ glewPrintExt("GL_EXT_gpu_program_parameters", GLEW_EXT_gpu_program_parameters, glewIsSupported("GL_EXT_gpu_program_parameters"), glewGetExtension("GL_EXT_gpu_program_parameters"));
+
+ glewInfoFunc("glProgramEnvParameters4fvEXT", glProgramEnvParameters4fvEXT == NULL);
+ glewInfoFunc("glProgramLocalParameters4fvEXT", glProgramLocalParameters4fvEXT == NULL);
+}
+
+#endif /* GL_EXT_gpu_program_parameters */
+
+#ifdef GL_EXT_gpu_shader4
+
+static void _glewInfo_GL_EXT_gpu_shader4 (void)
+{
+ glewPrintExt("GL_EXT_gpu_shader4", GLEW_EXT_gpu_shader4, glewIsSupported("GL_EXT_gpu_shader4"), glewGetExtension("GL_EXT_gpu_shader4"));
+
+ glewInfoFunc("glBindFragDataLocationEXT", glBindFragDataLocationEXT == NULL);
+ glewInfoFunc("glGetFragDataLocationEXT", glGetFragDataLocationEXT == NULL);
+ glewInfoFunc("glGetUniformuivEXT", glGetUniformuivEXT == NULL);
+ glewInfoFunc("glGetVertexAttribIivEXT", glGetVertexAttribIivEXT == NULL);
+ glewInfoFunc("glGetVertexAttribIuivEXT", glGetVertexAttribIuivEXT == NULL);
+ glewInfoFunc("glUniform1uiEXT", glUniform1uiEXT == NULL);
+ glewInfoFunc("glUniform1uivEXT", glUniform1uivEXT == NULL);
+ glewInfoFunc("glUniform2uiEXT", glUniform2uiEXT == NULL);
+ glewInfoFunc("glUniform2uivEXT", glUniform2uivEXT == NULL);
+ glewInfoFunc("glUniform3uiEXT", glUniform3uiEXT == NULL);
+ glewInfoFunc("glUniform3uivEXT", glUniform3uivEXT == NULL);
+ glewInfoFunc("glUniform4uiEXT", glUniform4uiEXT == NULL);
+ glewInfoFunc("glUniform4uivEXT", glUniform4uivEXT == NULL);
+ glewInfoFunc("glVertexAttribI1iEXT", glVertexAttribI1iEXT == NULL);
+ glewInfoFunc("glVertexAttribI1ivEXT", glVertexAttribI1ivEXT == NULL);
+ glewInfoFunc("glVertexAttribI1uiEXT", glVertexAttribI1uiEXT == NULL);
+ glewInfoFunc("glVertexAttribI1uivEXT", glVertexAttribI1uivEXT == NULL);
+ glewInfoFunc("glVertexAttribI2iEXT", glVertexAttribI2iEXT == NULL);
+ glewInfoFunc("glVertexAttribI2ivEXT", glVertexAttribI2ivEXT == NULL);
+ glewInfoFunc("glVertexAttribI2uiEXT", glVertexAttribI2uiEXT == NULL);
+ glewInfoFunc("glVertexAttribI2uivEXT", glVertexAttribI2uivEXT == NULL);
+ glewInfoFunc("glVertexAttribI3iEXT", glVertexAttribI3iEXT == NULL);
+ glewInfoFunc("glVertexAttribI3ivEXT", glVertexAttribI3ivEXT == NULL);
+ glewInfoFunc("glVertexAttribI3uiEXT", glVertexAttribI3uiEXT == NULL);
+ glewInfoFunc("glVertexAttribI3uivEXT", glVertexAttribI3uivEXT == NULL);
+ glewInfoFunc("glVertexAttribI4bvEXT", glVertexAttribI4bvEXT == NULL);
+ glewInfoFunc("glVertexAttribI4iEXT", glVertexAttribI4iEXT == NULL);
+ glewInfoFunc("glVertexAttribI4ivEXT", glVertexAttribI4ivEXT == NULL);
+ glewInfoFunc("glVertexAttribI4svEXT", glVertexAttribI4svEXT == NULL);
+ glewInfoFunc("glVertexAttribI4ubvEXT", glVertexAttribI4ubvEXT == NULL);
+ glewInfoFunc("glVertexAttribI4uiEXT", glVertexAttribI4uiEXT == NULL);
+ glewInfoFunc("glVertexAttribI4uivEXT", glVertexAttribI4uivEXT == NULL);
+ glewInfoFunc("glVertexAttribI4usvEXT", glVertexAttribI4usvEXT == NULL);
+ glewInfoFunc("glVertexAttribIPointerEXT", glVertexAttribIPointerEXT == NULL);
+}
+
+#endif /* GL_EXT_gpu_shader4 */
+
+#ifdef GL_EXT_histogram
+
+static void _glewInfo_GL_EXT_histogram (void)
+{
+ glewPrintExt("GL_EXT_histogram", GLEW_EXT_histogram, glewIsSupported("GL_EXT_histogram"), glewGetExtension("GL_EXT_histogram"));
+
+ glewInfoFunc("glGetHistogramEXT", glGetHistogramEXT == NULL);
+ glewInfoFunc("glGetHistogramParameterfvEXT", glGetHistogramParameterfvEXT == NULL);
+ glewInfoFunc("glGetHistogramParameterivEXT", glGetHistogramParameterivEXT == NULL);
+ glewInfoFunc("glGetMinmaxEXT", glGetMinmaxEXT == NULL);
+ glewInfoFunc("glGetMinmaxParameterfvEXT", glGetMinmaxParameterfvEXT == NULL);
+ glewInfoFunc("glGetMinmaxParameterivEXT", glGetMinmaxParameterivEXT == NULL);
+ glewInfoFunc("glHistogramEXT", glHistogramEXT == NULL);
+ glewInfoFunc("glMinmaxEXT", glMinmaxEXT == NULL);
+ glewInfoFunc("glResetHistogramEXT", glResetHistogramEXT == NULL);
+ glewInfoFunc("glResetMinmaxEXT", glResetMinmaxEXT == NULL);
+}
+
+#endif /* GL_EXT_histogram */
+
+#ifdef GL_EXT_index_array_formats
+
+static void _glewInfo_GL_EXT_index_array_formats (void)
+{
+ glewPrintExt("GL_EXT_index_array_formats", GLEW_EXT_index_array_formats, glewIsSupported("GL_EXT_index_array_formats"), glewGetExtension("GL_EXT_index_array_formats"));
+}
+
+#endif /* GL_EXT_index_array_formats */
+
+#ifdef GL_EXT_index_func
+
+static void _glewInfo_GL_EXT_index_func (void)
+{
+ glewPrintExt("GL_EXT_index_func", GLEW_EXT_index_func, glewIsSupported("GL_EXT_index_func"), glewGetExtension("GL_EXT_index_func"));
+
+ glewInfoFunc("glIndexFuncEXT", glIndexFuncEXT == NULL);
+}
+
+#endif /* GL_EXT_index_func */
+
+#ifdef GL_EXT_index_material
+
+static void _glewInfo_GL_EXT_index_material (void)
+{
+ glewPrintExt("GL_EXT_index_material", GLEW_EXT_index_material, glewIsSupported("GL_EXT_index_material"), glewGetExtension("GL_EXT_index_material"));
+
+ glewInfoFunc("glIndexMaterialEXT", glIndexMaterialEXT == NULL);
+}
+
+#endif /* GL_EXT_index_material */
+
+#ifdef GL_EXT_index_texture
+
+static void _glewInfo_GL_EXT_index_texture (void)
+{
+ glewPrintExt("GL_EXT_index_texture", GLEW_EXT_index_texture, glewIsSupported("GL_EXT_index_texture"), glewGetExtension("GL_EXT_index_texture"));
+}
+
+#endif /* GL_EXT_index_texture */
+
+#ifdef GL_EXT_light_texture
+
+static void _glewInfo_GL_EXT_light_texture (void)
+{
+ glewPrintExt("GL_EXT_light_texture", GLEW_EXT_light_texture, glewIsSupported("GL_EXT_light_texture"), glewGetExtension("GL_EXT_light_texture"));
+
+ glewInfoFunc("glApplyTextureEXT", glApplyTextureEXT == NULL);
+ glewInfoFunc("glTextureLightEXT", glTextureLightEXT == NULL);
+ glewInfoFunc("glTextureMaterialEXT", glTextureMaterialEXT == NULL);
+}
+
+#endif /* GL_EXT_light_texture */
+
+#ifdef GL_EXT_misc_attribute
+
+static void _glewInfo_GL_EXT_misc_attribute (void)
+{
+ glewPrintExt("GL_EXT_misc_attribute", GLEW_EXT_misc_attribute, glewIsSupported("GL_EXT_misc_attribute"), glewGetExtension("GL_EXT_misc_attribute"));
+}
+
+#endif /* GL_EXT_misc_attribute */
+
+#ifdef GL_EXT_multi_draw_arrays
+
+static void _glewInfo_GL_EXT_multi_draw_arrays (void)
+{
+ glewPrintExt("GL_EXT_multi_draw_arrays", GLEW_EXT_multi_draw_arrays, glewIsSupported("GL_EXT_multi_draw_arrays"), glewGetExtension("GL_EXT_multi_draw_arrays"));
+
+ glewInfoFunc("glMultiDrawArraysEXT", glMultiDrawArraysEXT == NULL);
+ glewInfoFunc("glMultiDrawElementsEXT", glMultiDrawElementsEXT == NULL);
+}
+
+#endif /* GL_EXT_multi_draw_arrays */
+
+#ifdef GL_EXT_multisample
+
+static void _glewInfo_GL_EXT_multisample (void)
+{
+ glewPrintExt("GL_EXT_multisample", GLEW_EXT_multisample, glewIsSupported("GL_EXT_multisample"), glewGetExtension("GL_EXT_multisample"));
+
+ glewInfoFunc("glSampleMaskEXT", glSampleMaskEXT == NULL);
+ glewInfoFunc("glSamplePatternEXT", glSamplePatternEXT == NULL);
+}
+
+#endif /* GL_EXT_multisample */
+
+#ifdef GL_EXT_packed_depth_stencil
+
+static void _glewInfo_GL_EXT_packed_depth_stencil (void)
+{
+ glewPrintExt("GL_EXT_packed_depth_stencil", GLEW_EXT_packed_depth_stencil, glewIsSupported("GL_EXT_packed_depth_stencil"), glewGetExtension("GL_EXT_packed_depth_stencil"));
+}
+
+#endif /* GL_EXT_packed_depth_stencil */
+
+#ifdef GL_EXT_packed_float
+
+static void _glewInfo_GL_EXT_packed_float (void)
+{
+ glewPrintExt("GL_EXT_packed_float", GLEW_EXT_packed_float, glewIsSupported("GL_EXT_packed_float"), glewGetExtension("GL_EXT_packed_float"));
+}
+
+#endif /* GL_EXT_packed_float */
+
+#ifdef GL_EXT_packed_pixels
+
+static void _glewInfo_GL_EXT_packed_pixels (void)
+{
+ glewPrintExt("GL_EXT_packed_pixels", GLEW_EXT_packed_pixels, glewIsSupported("GL_EXT_packed_pixels"), glewGetExtension("GL_EXT_packed_pixels"));
+}
+
+#endif /* GL_EXT_packed_pixels */
+
+#ifdef GL_EXT_paletted_texture
+
+static void _glewInfo_GL_EXT_paletted_texture (void)
+{
+ glewPrintExt("GL_EXT_paletted_texture", GLEW_EXT_paletted_texture, glewIsSupported("GL_EXT_paletted_texture"), glewGetExtension("GL_EXT_paletted_texture"));
+
+ glewInfoFunc("glColorTableEXT", glColorTableEXT == NULL);
+ glewInfoFunc("glGetColorTableEXT", glGetColorTableEXT == NULL);
+ glewInfoFunc("glGetColorTableParameterfvEXT", glGetColorTableParameterfvEXT == NULL);
+ glewInfoFunc("glGetColorTableParameterivEXT", glGetColorTableParameterivEXT == NULL);
+}
+
+#endif /* GL_EXT_paletted_texture */
+
+#ifdef GL_EXT_pixel_buffer_object
+
+static void _glewInfo_GL_EXT_pixel_buffer_object (void)
+{
+ glewPrintExt("GL_EXT_pixel_buffer_object", GLEW_EXT_pixel_buffer_object, glewIsSupported("GL_EXT_pixel_buffer_object"), glewGetExtension("GL_EXT_pixel_buffer_object"));
+}
+
+#endif /* GL_EXT_pixel_buffer_object */
+
+#ifdef GL_EXT_pixel_transform
+
+static void _glewInfo_GL_EXT_pixel_transform (void)
+{
+ glewPrintExt("GL_EXT_pixel_transform", GLEW_EXT_pixel_transform, glewIsSupported("GL_EXT_pixel_transform"), glewGetExtension("GL_EXT_pixel_transform"));
+
+ glewInfoFunc("glGetPixelTransformParameterfvEXT", glGetPixelTransformParameterfvEXT == NULL);
+ glewInfoFunc("glGetPixelTransformParameterivEXT", glGetPixelTransformParameterivEXT == NULL);
+ glewInfoFunc("glPixelTransformParameterfEXT", glPixelTransformParameterfEXT == NULL);
+ glewInfoFunc("glPixelTransformParameterfvEXT", glPixelTransformParameterfvEXT == NULL);
+ glewInfoFunc("glPixelTransformParameteriEXT", glPixelTransformParameteriEXT == NULL);
+ glewInfoFunc("glPixelTransformParameterivEXT", glPixelTransformParameterivEXT == NULL);
+}
+
+#endif /* GL_EXT_pixel_transform */
+
+#ifdef GL_EXT_pixel_transform_color_table
+
+static void _glewInfo_GL_EXT_pixel_transform_color_table (void)
+{
+ glewPrintExt("GL_EXT_pixel_transform_color_table", GLEW_EXT_pixel_transform_color_table, glewIsSupported("GL_EXT_pixel_transform_color_table"), glewGetExtension("GL_EXT_pixel_transform_color_table"));
+}
+
+#endif /* GL_EXT_pixel_transform_color_table */
+
+#ifdef GL_EXT_point_parameters
+
+static void _glewInfo_GL_EXT_point_parameters (void)
+{
+ glewPrintExt("GL_EXT_point_parameters", GLEW_EXT_point_parameters, glewIsSupported("GL_EXT_point_parameters"), glewGetExtension("GL_EXT_point_parameters"));
+
+ glewInfoFunc("glPointParameterfEXT", glPointParameterfEXT == NULL);
+ glewInfoFunc("glPointParameterfvEXT", glPointParameterfvEXT == NULL);
+}
+
+#endif /* GL_EXT_point_parameters */
+
+#ifdef GL_EXT_polygon_offset
+
+static void _glewInfo_GL_EXT_polygon_offset (void)
+{
+ glewPrintExt("GL_EXT_polygon_offset", GLEW_EXT_polygon_offset, glewIsSupported("GL_EXT_polygon_offset"), glewGetExtension("GL_EXT_polygon_offset"));
+
+ glewInfoFunc("glPolygonOffsetEXT", glPolygonOffsetEXT == NULL);
+}
+
+#endif /* GL_EXT_polygon_offset */
+
+#ifdef GL_EXT_rescale_normal
+
+static void _glewInfo_GL_EXT_rescale_normal (void)
+{
+ glewPrintExt("GL_EXT_rescale_normal", GLEW_EXT_rescale_normal, glewIsSupported("GL_EXT_rescale_normal"), glewGetExtension("GL_EXT_rescale_normal"));
+}
+
+#endif /* GL_EXT_rescale_normal */
+
+#ifdef GL_EXT_scene_marker
+
+static void _glewInfo_GL_EXT_scene_marker (void)
+{
+ glewPrintExt("GL_EXT_scene_marker", GLEW_EXT_scene_marker, glewIsSupported("GL_EXT_scene_marker"), glewGetExtension("GL_EXT_scene_marker"));
+
+ glewInfoFunc("glBeginSceneEXT", glBeginSceneEXT == NULL);
+ glewInfoFunc("glEndSceneEXT", glEndSceneEXT == NULL);
+}
+
+#endif /* GL_EXT_scene_marker */
+
+#ifdef GL_EXT_secondary_color
+
+static void _glewInfo_GL_EXT_secondary_color (void)
+{
+ glewPrintExt("GL_EXT_secondary_color", GLEW_EXT_secondary_color, glewIsSupported("GL_EXT_secondary_color"), glewGetExtension("GL_EXT_secondary_color"));
+
+ glewInfoFunc("glSecondaryColor3bEXT", glSecondaryColor3bEXT == NULL);
+ glewInfoFunc("glSecondaryColor3bvEXT", glSecondaryColor3bvEXT == NULL);
+ glewInfoFunc("glSecondaryColor3dEXT", glSecondaryColor3dEXT == NULL);
+ glewInfoFunc("glSecondaryColor3dvEXT", glSecondaryColor3dvEXT == NULL);
+ glewInfoFunc("glSecondaryColor3fEXT", glSecondaryColor3fEXT == NULL);
+ glewInfoFunc("glSecondaryColor3fvEXT", glSecondaryColor3fvEXT == NULL);
+ glewInfoFunc("glSecondaryColor3iEXT", glSecondaryColor3iEXT == NULL);
+ glewInfoFunc("glSecondaryColor3ivEXT", glSecondaryColor3ivEXT == NULL);
+ glewInfoFunc("glSecondaryColor3sEXT", glSecondaryColor3sEXT == NULL);
+ glewInfoFunc("glSecondaryColor3svEXT", glSecondaryColor3svEXT == NULL);
+ glewInfoFunc("glSecondaryColor3ubEXT", glSecondaryColor3ubEXT == NULL);
+ glewInfoFunc("glSecondaryColor3ubvEXT", glSecondaryColor3ubvEXT == NULL);
+ glewInfoFunc("glSecondaryColor3uiEXT", glSecondaryColor3uiEXT == NULL);
+ glewInfoFunc("glSecondaryColor3uivEXT", glSecondaryColor3uivEXT == NULL);
+ glewInfoFunc("glSecondaryColor3usEXT", glSecondaryColor3usEXT == NULL);
+ glewInfoFunc("glSecondaryColor3usvEXT", glSecondaryColor3usvEXT == NULL);
+ glewInfoFunc("glSecondaryColorPointerEXT", glSecondaryColorPointerEXT == NULL);
+}
+
+#endif /* GL_EXT_secondary_color */
+
+#ifdef GL_EXT_separate_specular_color
+
+static void _glewInfo_GL_EXT_separate_specular_color (void)
+{
+ glewPrintExt("GL_EXT_separate_specular_color", GLEW_EXT_separate_specular_color, glewIsSupported("GL_EXT_separate_specular_color"), glewGetExtension("GL_EXT_separate_specular_color"));
+}
+
+#endif /* GL_EXT_separate_specular_color */
+
+#ifdef GL_EXT_shadow_funcs
+
+static void _glewInfo_GL_EXT_shadow_funcs (void)
+{
+ glewPrintExt("GL_EXT_shadow_funcs", GLEW_EXT_shadow_funcs, glewIsSupported("GL_EXT_shadow_funcs"), glewGetExtension("GL_EXT_shadow_funcs"));
+}
+
+#endif /* GL_EXT_shadow_funcs */
+
+#ifdef GL_EXT_shared_texture_palette
+
+static void _glewInfo_GL_EXT_shared_texture_palette (void)
+{
+ glewPrintExt("GL_EXT_shared_texture_palette", GLEW_EXT_shared_texture_palette, glewIsSupported("GL_EXT_shared_texture_palette"), glewGetExtension("GL_EXT_shared_texture_palette"));
+}
+
+#endif /* GL_EXT_shared_texture_palette */
+
+#ifdef GL_EXT_stencil_clear_tag
+
+static void _glewInfo_GL_EXT_stencil_clear_tag (void)
+{
+ glewPrintExt("GL_EXT_stencil_clear_tag", GLEW_EXT_stencil_clear_tag, glewIsSupported("GL_EXT_stencil_clear_tag"), glewGetExtension("GL_EXT_stencil_clear_tag"));
+}
+
+#endif /* GL_EXT_stencil_clear_tag */
+
+#ifdef GL_EXT_stencil_two_side
+
+static void _glewInfo_GL_EXT_stencil_two_side (void)
+{
+ glewPrintExt("GL_EXT_stencil_two_side", GLEW_EXT_stencil_two_side, glewIsSupported("GL_EXT_stencil_two_side"), glewGetExtension("GL_EXT_stencil_two_side"));
+
+ glewInfoFunc("glActiveStencilFaceEXT", glActiveStencilFaceEXT == NULL);
+}
+
+#endif /* GL_EXT_stencil_two_side */
+
+#ifdef GL_EXT_stencil_wrap
+
+static void _glewInfo_GL_EXT_stencil_wrap (void)
+{
+ glewPrintExt("GL_EXT_stencil_wrap", GLEW_EXT_stencil_wrap, glewIsSupported("GL_EXT_stencil_wrap"), glewGetExtension("GL_EXT_stencil_wrap"));
+}
+
+#endif /* GL_EXT_stencil_wrap */
+
+#ifdef GL_EXT_subtexture
+
+static void _glewInfo_GL_EXT_subtexture (void)
+{
+ glewPrintExt("GL_EXT_subtexture", GLEW_EXT_subtexture, glewIsSupported("GL_EXT_subtexture"), glewGetExtension("GL_EXT_subtexture"));
+
+ glewInfoFunc("glTexSubImage1DEXT", glTexSubImage1DEXT == NULL);
+ glewInfoFunc("glTexSubImage2DEXT", glTexSubImage2DEXT == NULL);
+ glewInfoFunc("glTexSubImage3DEXT", glTexSubImage3DEXT == NULL);
+}
+
+#endif /* GL_EXT_subtexture */
+
+#ifdef GL_EXT_texture
+
+static void _glewInfo_GL_EXT_texture (void)
+{
+ glewPrintExt("GL_EXT_texture", GLEW_EXT_texture, glewIsSupported("GL_EXT_texture"), glewGetExtension("GL_EXT_texture"));
+}
+
+#endif /* GL_EXT_texture */
+
+#ifdef GL_EXT_texture3D
+
+static void _glewInfo_GL_EXT_texture3D (void)
+{
+ glewPrintExt("GL_EXT_texture3D", GLEW_EXT_texture3D, glewIsSupported("GL_EXT_texture3D"), glewGetExtension("GL_EXT_texture3D"));
+
+ glewInfoFunc("glTexImage3DEXT", glTexImage3DEXT == NULL);
+}
+
+#endif /* GL_EXT_texture3D */
+
+#ifdef GL_EXT_texture_array
+
+static void _glewInfo_GL_EXT_texture_array (void)
+{
+ glewPrintExt("GL_EXT_texture_array", GLEW_EXT_texture_array, glewIsSupported("GL_EXT_texture_array"), glewGetExtension("GL_EXT_texture_array"));
+}
+
+#endif /* GL_EXT_texture_array */
+
+#ifdef GL_EXT_texture_buffer_object
+
+static void _glewInfo_GL_EXT_texture_buffer_object (void)
+{
+ glewPrintExt("GL_EXT_texture_buffer_object", GLEW_EXT_texture_buffer_object, glewIsSupported("GL_EXT_texture_buffer_object"), glewGetExtension("GL_EXT_texture_buffer_object"));
+
+ glewInfoFunc("glTexBufferEXT", glTexBufferEXT == NULL);
+}
+
+#endif /* GL_EXT_texture_buffer_object */
+
+#ifdef GL_EXT_texture_compression_dxt1
+
+static void _glewInfo_GL_EXT_texture_compression_dxt1 (void)
+{
+ glewPrintExt("GL_EXT_texture_compression_dxt1", GLEW_EXT_texture_compression_dxt1, glewIsSupported("GL_EXT_texture_compression_dxt1"), glewGetExtension("GL_EXT_texture_compression_dxt1"));
+}
+
+#endif /* GL_EXT_texture_compression_dxt1 */
+
+#ifdef GL_EXT_texture_compression_latc
+
+static void _glewInfo_GL_EXT_texture_compression_latc (void)
+{
+ glewPrintExt("GL_EXT_texture_compression_latc", GLEW_EXT_texture_compression_latc, glewIsSupported("GL_EXT_texture_compression_latc"), glewGetExtension("GL_EXT_texture_compression_latc"));
+}
+
+#endif /* GL_EXT_texture_compression_latc */
+
+#ifdef GL_EXT_texture_compression_rgtc
+
+static void _glewInfo_GL_EXT_texture_compression_rgtc (void)
+{
+ glewPrintExt("GL_EXT_texture_compression_rgtc", GLEW_EXT_texture_compression_rgtc, glewIsSupported("GL_EXT_texture_compression_rgtc"), glewGetExtension("GL_EXT_texture_compression_rgtc"));
+}
+
+#endif /* GL_EXT_texture_compression_rgtc */
+
+#ifdef GL_EXT_texture_compression_s3tc
+
+static void _glewInfo_GL_EXT_texture_compression_s3tc (void)
+{
+ glewPrintExt("GL_EXT_texture_compression_s3tc", GLEW_EXT_texture_compression_s3tc, glewIsSupported("GL_EXT_texture_compression_s3tc"), glewGetExtension("GL_EXT_texture_compression_s3tc"));
+}
+
+#endif /* GL_EXT_texture_compression_s3tc */
+
+#ifdef GL_EXT_texture_cube_map
+
+static void _glewInfo_GL_EXT_texture_cube_map (void)
+{
+ glewPrintExt("GL_EXT_texture_cube_map", GLEW_EXT_texture_cube_map, glewIsSupported("GL_EXT_texture_cube_map"), glewGetExtension("GL_EXT_texture_cube_map"));
+}
+
+#endif /* GL_EXT_texture_cube_map */
+
+#ifdef GL_EXT_texture_edge_clamp
+
+static void _glewInfo_GL_EXT_texture_edge_clamp (void)
+{
+ glewPrintExt("GL_EXT_texture_edge_clamp", GLEW_EXT_texture_edge_clamp, glewIsSupported("GL_EXT_texture_edge_clamp"), glewGetExtension("GL_EXT_texture_edge_clamp"));
+}
+
+#endif /* GL_EXT_texture_edge_clamp */
+
+#ifdef GL_EXT_texture_env
+
+static void _glewInfo_GL_EXT_texture_env (void)
+{
+ glewPrintExt("GL_EXT_texture_env", GLEW_EXT_texture_env, glewIsSupported("GL_EXT_texture_env"), glewGetExtension("GL_EXT_texture_env"));
+}
+
+#endif /* GL_EXT_texture_env */
+
+#ifdef GL_EXT_texture_env_add
+
+static void _glewInfo_GL_EXT_texture_env_add (void)
+{
+ glewPrintExt("GL_EXT_texture_env_add", GLEW_EXT_texture_env_add, glewIsSupported("GL_EXT_texture_env_add"), glewGetExtension("GL_EXT_texture_env_add"));
+}
+
+#endif /* GL_EXT_texture_env_add */
+
+#ifdef GL_EXT_texture_env_combine
+
+static void _glewInfo_GL_EXT_texture_env_combine (void)
+{
+ glewPrintExt("GL_EXT_texture_env_combine", GLEW_EXT_texture_env_combine, glewIsSupported("GL_EXT_texture_env_combine"), glewGetExtension("GL_EXT_texture_env_combine"));
+}
+
+#endif /* GL_EXT_texture_env_combine */
+
+#ifdef GL_EXT_texture_env_dot3
+
+static void _glewInfo_GL_EXT_texture_env_dot3 (void)
+{
+ glewPrintExt("GL_EXT_texture_env_dot3", GLEW_EXT_texture_env_dot3, glewIsSupported("GL_EXT_texture_env_dot3"), glewGetExtension("GL_EXT_texture_env_dot3"));
+}
+
+#endif /* GL_EXT_texture_env_dot3 */
+
+#ifdef GL_EXT_texture_filter_anisotropic
+
+static void _glewInfo_GL_EXT_texture_filter_anisotropic (void)
+{
+ glewPrintExt("GL_EXT_texture_filter_anisotropic", GLEW_EXT_texture_filter_anisotropic, glewIsSupported("GL_EXT_texture_filter_anisotropic"), glewGetExtension("GL_EXT_texture_filter_anisotropic"));
+}
+
+#endif /* GL_EXT_texture_filter_anisotropic */
+
+#ifdef GL_EXT_texture_integer
+
+static void _glewInfo_GL_EXT_texture_integer (void)
+{
+ glewPrintExt("GL_EXT_texture_integer", GLEW_EXT_texture_integer, glewIsSupported("GL_EXT_texture_integer"), glewGetExtension("GL_EXT_texture_integer"));
+
+ glewInfoFunc("glClearColorIiEXT", glClearColorIiEXT == NULL);
+ glewInfoFunc("glClearColorIuiEXT", glClearColorIuiEXT == NULL);
+ glewInfoFunc("glGetTexParameterIivEXT", glGetTexParameterIivEXT == NULL);
+ glewInfoFunc("glGetTexParameterIuivEXT", glGetTexParameterIuivEXT == NULL);
+ glewInfoFunc("glTexParameterIivEXT", glTexParameterIivEXT == NULL);
+ glewInfoFunc("glTexParameterIuivEXT", glTexParameterIuivEXT == NULL);
+}
+
+#endif /* GL_EXT_texture_integer */
+
+#ifdef GL_EXT_texture_lod_bias
+
+static void _glewInfo_GL_EXT_texture_lod_bias (void)
+{
+ glewPrintExt("GL_EXT_texture_lod_bias", GLEW_EXT_texture_lod_bias, glewIsSupported("GL_EXT_texture_lod_bias"), glewGetExtension("GL_EXT_texture_lod_bias"));
+}
+
+#endif /* GL_EXT_texture_lod_bias */
+
+#ifdef GL_EXT_texture_mirror_clamp
+
+static void _glewInfo_GL_EXT_texture_mirror_clamp (void)
+{
+ glewPrintExt("GL_EXT_texture_mirror_clamp", GLEW_EXT_texture_mirror_clamp, glewIsSupported("GL_EXT_texture_mirror_clamp"), glewGetExtension("GL_EXT_texture_mirror_clamp"));
+}
+
+#endif /* GL_EXT_texture_mirror_clamp */
+
+#ifdef GL_EXT_texture_object
+
+static void _glewInfo_GL_EXT_texture_object (void)
+{
+ glewPrintExt("GL_EXT_texture_object", GLEW_EXT_texture_object, glewIsSupported("GL_EXT_texture_object"), glewGetExtension("GL_EXT_texture_object"));
+
+ glewInfoFunc("glAreTexturesResidentEXT", glAreTexturesResidentEXT == NULL);
+ glewInfoFunc("glBindTextureEXT", glBindTextureEXT == NULL);
+ glewInfoFunc("glDeleteTexturesEXT", glDeleteTexturesEXT == NULL);
+ glewInfoFunc("glGenTexturesEXT", glGenTexturesEXT == NULL);
+ glewInfoFunc("glIsTextureEXT", glIsTextureEXT == NULL);
+ glewInfoFunc("glPrioritizeTexturesEXT", glPrioritizeTexturesEXT == NULL);
+}
+
+#endif /* GL_EXT_texture_object */
+
+#ifdef GL_EXT_texture_perturb_normal
+
+static void _glewInfo_GL_EXT_texture_perturb_normal (void)
+{
+ glewPrintExt("GL_EXT_texture_perturb_normal", GLEW_EXT_texture_perturb_normal, glewIsSupported("GL_EXT_texture_perturb_normal"), glewGetExtension("GL_EXT_texture_perturb_normal"));
+
+ glewInfoFunc("glTextureNormalEXT", glTextureNormalEXT == NULL);
+}
+
+#endif /* GL_EXT_texture_perturb_normal */
+
+#ifdef GL_EXT_texture_rectangle
+
+static void _glewInfo_GL_EXT_texture_rectangle (void)
+{
+ glewPrintExt("GL_EXT_texture_rectangle", GLEW_EXT_texture_rectangle, glewIsSupported("GL_EXT_texture_rectangle"), glewGetExtension("GL_EXT_texture_rectangle"));
+}
+
+#endif /* GL_EXT_texture_rectangle */
+
+#ifdef GL_EXT_texture_sRGB
+
+static void _glewInfo_GL_EXT_texture_sRGB (void)
+{
+ glewPrintExt("GL_EXT_texture_sRGB", GLEW_EXT_texture_sRGB, glewIsSupported("GL_EXT_texture_sRGB"), glewGetExtension("GL_EXT_texture_sRGB"));
+}
+
+#endif /* GL_EXT_texture_sRGB */
+
+#ifdef GL_EXT_texture_shared_exponent
+
+static void _glewInfo_GL_EXT_texture_shared_exponent (void)
+{
+ glewPrintExt("GL_EXT_texture_shared_exponent", GLEW_EXT_texture_shared_exponent, glewIsSupported("GL_EXT_texture_shared_exponent"), glewGetExtension("GL_EXT_texture_shared_exponent"));
+}
+
+#endif /* GL_EXT_texture_shared_exponent */
+
+#ifdef GL_EXT_texture_swizzle
+
+static void _glewInfo_GL_EXT_texture_swizzle (void)
+{
+ glewPrintExt("GL_EXT_texture_swizzle", GLEW_EXT_texture_swizzle, glewIsSupported("GL_EXT_texture_swizzle"), glewGetExtension("GL_EXT_texture_swizzle"));
+}
+
+#endif /* GL_EXT_texture_swizzle */
+
+#ifdef GL_EXT_timer_query
+
+static void _glewInfo_GL_EXT_timer_query (void)
+{
+ glewPrintExt("GL_EXT_timer_query", GLEW_EXT_timer_query, glewIsSupported("GL_EXT_timer_query"), glewGetExtension("GL_EXT_timer_query"));
+
+ glewInfoFunc("glGetQueryObjecti64vEXT", glGetQueryObjecti64vEXT == NULL);
+ glewInfoFunc("glGetQueryObjectui64vEXT", glGetQueryObjectui64vEXT == NULL);
+}
+
+#endif /* GL_EXT_timer_query */
+
+#ifdef GL_EXT_transform_feedback
+
+static void _glewInfo_GL_EXT_transform_feedback (void)
+{
+ glewPrintExt("GL_EXT_transform_feedback", GLEW_EXT_transform_feedback, glewIsSupported("GL_EXT_transform_feedback"), glewGetExtension("GL_EXT_transform_feedback"));
+
+ glewInfoFunc("glBeginTransformFeedbackEXT", glBeginTransformFeedbackEXT == NULL);
+ glewInfoFunc("glBindBufferBaseEXT", glBindBufferBaseEXT == NULL);
+ glewInfoFunc("glBindBufferOffsetEXT", glBindBufferOffsetEXT == NULL);
+ glewInfoFunc("glBindBufferRangeEXT", glBindBufferRangeEXT == NULL);
+ glewInfoFunc("glEndTransformFeedbackEXT", glEndTransformFeedbackEXT == NULL);
+ glewInfoFunc("glGetTransformFeedbackVaryingEXT", glGetTransformFeedbackVaryingEXT == NULL);
+ glewInfoFunc("glTransformFeedbackVaryingsEXT", glTransformFeedbackVaryingsEXT == NULL);
+}
+
+#endif /* GL_EXT_transform_feedback */
+
+#ifdef GL_EXT_vertex_array
+
+static void _glewInfo_GL_EXT_vertex_array (void)
+{
+ glewPrintExt("GL_EXT_vertex_array", GLEW_EXT_vertex_array, glewIsSupported("GL_EXT_vertex_array"), glewGetExtension("GL_EXT_vertex_array"));
+
+ glewInfoFunc("glArrayElementEXT", glArrayElementEXT == NULL);
+ glewInfoFunc("glColorPointerEXT", glColorPointerEXT == NULL);
+ glewInfoFunc("glDrawArraysEXT", glDrawArraysEXT == NULL);
+ glewInfoFunc("glEdgeFlagPointerEXT", glEdgeFlagPointerEXT == NULL);
+ glewInfoFunc("glGetPointervEXT", glGetPointervEXT == NULL);
+ glewInfoFunc("glIndexPointerEXT", glIndexPointerEXT == NULL);
+ glewInfoFunc("glNormalPointerEXT", glNormalPointerEXT == NULL);
+ glewInfoFunc("glTexCoordPointerEXT", glTexCoordPointerEXT == NULL);
+ glewInfoFunc("glVertexPointerEXT", glVertexPointerEXT == NULL);
+}
+
+#endif /* GL_EXT_vertex_array */
+
+#ifdef GL_EXT_vertex_array_bgra
+
+static void _glewInfo_GL_EXT_vertex_array_bgra (void)
+{
+ glewPrintExt("GL_EXT_vertex_array_bgra", GLEW_EXT_vertex_array_bgra, glewIsSupported("GL_EXT_vertex_array_bgra"), glewGetExtension("GL_EXT_vertex_array_bgra"));
+}
+
+#endif /* GL_EXT_vertex_array_bgra */
+
+#ifdef GL_EXT_vertex_shader
+
+static void _glewInfo_GL_EXT_vertex_shader (void)
+{
+ glewPrintExt("GL_EXT_vertex_shader", GLEW_EXT_vertex_shader, glewIsSupported("GL_EXT_vertex_shader"), glewGetExtension("GL_EXT_vertex_shader"));
+
+ glewInfoFunc("glBeginVertexShaderEXT", glBeginVertexShaderEXT == NULL);
+ glewInfoFunc("glBindLightParameterEXT", glBindLightParameterEXT == NULL);
+ glewInfoFunc("glBindMaterialParameterEXT", glBindMaterialParameterEXT == NULL);
+ glewInfoFunc("glBindParameterEXT", glBindParameterEXT == NULL);
+ glewInfoFunc("glBindTexGenParameterEXT", glBindTexGenParameterEXT == NULL);
+ glewInfoFunc("glBindTextureUnitParameterEXT", glBindTextureUnitParameterEXT == NULL);
+ glewInfoFunc("glBindVertexShaderEXT", glBindVertexShaderEXT == NULL);
+ glewInfoFunc("glDeleteVertexShaderEXT", glDeleteVertexShaderEXT == NULL);
+ glewInfoFunc("glDisableVariantClientStateEXT", glDisableVariantClientStateEXT == NULL);
+ glewInfoFunc("glEnableVariantClientStateEXT", glEnableVariantClientStateEXT == NULL);
+ glewInfoFunc("glEndVertexShaderEXT", glEndVertexShaderEXT == NULL);
+ glewInfoFunc("glExtractComponentEXT", glExtractComponentEXT == NULL);
+ glewInfoFunc("glGenSymbolsEXT", glGenSymbolsEXT == NULL);
+ glewInfoFunc("glGenVertexShadersEXT", glGenVertexShadersEXT == NULL);
+ glewInfoFunc("glGetInvariantBooleanvEXT", glGetInvariantBooleanvEXT == NULL);
+ glewInfoFunc("glGetInvariantFloatvEXT", glGetInvariantFloatvEXT == NULL);
+ glewInfoFunc("glGetInvariantIntegervEXT", glGetInvariantIntegervEXT == NULL);
+ glewInfoFunc("glGetLocalConstantBooleanvEXT", glGetLocalConstantBooleanvEXT == NULL);
+ glewInfoFunc("glGetLocalConstantFloatvEXT", glGetLocalConstantFloatvEXT == NULL);
+ glewInfoFunc("glGetLocalConstantIntegervEXT", glGetLocalConstantIntegervEXT == NULL);
+ glewInfoFunc("glGetVariantBooleanvEXT", glGetVariantBooleanvEXT == NULL);
+ glewInfoFunc("glGetVariantFloatvEXT", glGetVariantFloatvEXT == NULL);
+ glewInfoFunc("glGetVariantIntegervEXT", glGetVariantIntegervEXT == NULL);
+ glewInfoFunc("glGetVariantPointervEXT", glGetVariantPointervEXT == NULL);
+ glewInfoFunc("glInsertComponentEXT", glInsertComponentEXT == NULL);
+ glewInfoFunc("glIsVariantEnabledEXT", glIsVariantEnabledEXT == NULL);
+ glewInfoFunc("glSetInvariantEXT", glSetInvariantEXT == NULL);
+ glewInfoFunc("glSetLocalConstantEXT", glSetLocalConstantEXT == NULL);
+ glewInfoFunc("glShaderOp1EXT", glShaderOp1EXT == NULL);
+ glewInfoFunc("glShaderOp2EXT", glShaderOp2EXT == NULL);
+ glewInfoFunc("glShaderOp3EXT", glShaderOp3EXT == NULL);
+ glewInfoFunc("glSwizzleEXT", glSwizzleEXT == NULL);
+ glewInfoFunc("glVariantPointerEXT", glVariantPointerEXT == NULL);
+ glewInfoFunc("glVariantbvEXT", glVariantbvEXT == NULL);
+ glewInfoFunc("glVariantdvEXT", glVariantdvEXT == NULL);
+ glewInfoFunc("glVariantfvEXT", glVariantfvEXT == NULL);
+ glewInfoFunc("glVariantivEXT", glVariantivEXT == NULL);
+ glewInfoFunc("glVariantsvEXT", glVariantsvEXT == NULL);
+ glewInfoFunc("glVariantubvEXT", glVariantubvEXT == NULL);
+ glewInfoFunc("glVariantuivEXT", glVariantuivEXT == NULL);
+ glewInfoFunc("glVariantusvEXT", glVariantusvEXT == NULL);
+ glewInfoFunc("glWriteMaskEXT", glWriteMaskEXT == NULL);
+}
+
+#endif /* GL_EXT_vertex_shader */
+
+#ifdef GL_EXT_vertex_weighting
+
+static void _glewInfo_GL_EXT_vertex_weighting (void)
+{
+ glewPrintExt("GL_EXT_vertex_weighting", GLEW_EXT_vertex_weighting, glewIsSupported("GL_EXT_vertex_weighting"), glewGetExtension("GL_EXT_vertex_weighting"));
+
+ glewInfoFunc("glVertexWeightPointerEXT", glVertexWeightPointerEXT == NULL);
+ glewInfoFunc("glVertexWeightfEXT", glVertexWeightfEXT == NULL);
+ glewInfoFunc("glVertexWeightfvEXT", glVertexWeightfvEXT == NULL);
+}
+
+#endif /* GL_EXT_vertex_weighting */
+
+#ifdef GL_GREMEDY_frame_terminator
+
+static void _glewInfo_GL_GREMEDY_frame_terminator (void)
+{
+ glewPrintExt("GL_GREMEDY_frame_terminator", GLEW_GREMEDY_frame_terminator, glewIsSupported("GL_GREMEDY_frame_terminator"), glewGetExtension("GL_GREMEDY_frame_terminator"));
+
+ glewInfoFunc("glFrameTerminatorGREMEDY", glFrameTerminatorGREMEDY == NULL);
+}
+
+#endif /* GL_GREMEDY_frame_terminator */
+
+#ifdef GL_GREMEDY_string_marker
+
+static void _glewInfo_GL_GREMEDY_string_marker (void)
+{
+ glewPrintExt("GL_GREMEDY_string_marker", GLEW_GREMEDY_string_marker, glewIsSupported("GL_GREMEDY_string_marker"), glewGetExtension("GL_GREMEDY_string_marker"));
+
+ glewInfoFunc("glStringMarkerGREMEDY", glStringMarkerGREMEDY == NULL);
+}
+
+#endif /* GL_GREMEDY_string_marker */
+
+#ifdef GL_HP_convolution_border_modes
+
+static void _glewInfo_GL_HP_convolution_border_modes (void)
+{
+ glewPrintExt("GL_HP_convolution_border_modes", GLEW_HP_convolution_border_modes, glewIsSupported("GL_HP_convolution_border_modes"), glewGetExtension("GL_HP_convolution_border_modes"));
+}
+
+#endif /* GL_HP_convolution_border_modes */
+
+#ifdef GL_HP_image_transform
+
+static void _glewInfo_GL_HP_image_transform (void)
+{
+ glewPrintExt("GL_HP_image_transform", GLEW_HP_image_transform, glewIsSupported("GL_HP_image_transform"), glewGetExtension("GL_HP_image_transform"));
+
+ glewInfoFunc("glGetImageTransformParameterfvHP", glGetImageTransformParameterfvHP == NULL);
+ glewInfoFunc("glGetImageTransformParameterivHP", glGetImageTransformParameterivHP == NULL);
+ glewInfoFunc("glImageTransformParameterfHP", glImageTransformParameterfHP == NULL);
+ glewInfoFunc("glImageTransformParameterfvHP", glImageTransformParameterfvHP == NULL);
+ glewInfoFunc("glImageTransformParameteriHP", glImageTransformParameteriHP == NULL);
+ glewInfoFunc("glImageTransformParameterivHP", glImageTransformParameterivHP == NULL);
+}
+
+#endif /* GL_HP_image_transform */
+
+#ifdef GL_HP_occlusion_test
+
+static void _glewInfo_GL_HP_occlusion_test (void)
+{
+ glewPrintExt("GL_HP_occlusion_test", GLEW_HP_occlusion_test, glewIsSupported("GL_HP_occlusion_test"), glewGetExtension("GL_HP_occlusion_test"));
+}
+
+#endif /* GL_HP_occlusion_test */
+
+#ifdef GL_HP_texture_lighting
+
+static void _glewInfo_GL_HP_texture_lighting (void)
+{
+ glewPrintExt("GL_HP_texture_lighting", GLEW_HP_texture_lighting, glewIsSupported("GL_HP_texture_lighting"), glewGetExtension("GL_HP_texture_lighting"));
+}
+
+#endif /* GL_HP_texture_lighting */
+
+#ifdef GL_IBM_cull_vertex
+
+static void _glewInfo_GL_IBM_cull_vertex (void)
+{
+ glewPrintExt("GL_IBM_cull_vertex", GLEW_IBM_cull_vertex, glewIsSupported("GL_IBM_cull_vertex"), glewGetExtension("GL_IBM_cull_vertex"));
+}
+
+#endif /* GL_IBM_cull_vertex */
+
+#ifdef GL_IBM_multimode_draw_arrays
+
+static void _glewInfo_GL_IBM_multimode_draw_arrays (void)
+{
+ glewPrintExt("GL_IBM_multimode_draw_arrays", GLEW_IBM_multimode_draw_arrays, glewIsSupported("GL_IBM_multimode_draw_arrays"), glewGetExtension("GL_IBM_multimode_draw_arrays"));
+
+ glewInfoFunc("glMultiModeDrawArraysIBM", glMultiModeDrawArraysIBM == NULL);
+ glewInfoFunc("glMultiModeDrawElementsIBM", glMultiModeDrawElementsIBM == NULL);
+}
+
+#endif /* GL_IBM_multimode_draw_arrays */
+
+#ifdef GL_IBM_rasterpos_clip
+
+static void _glewInfo_GL_IBM_rasterpos_clip (void)
+{
+ glewPrintExt("GL_IBM_rasterpos_clip", GLEW_IBM_rasterpos_clip, glewIsSupported("GL_IBM_rasterpos_clip"), glewGetExtension("GL_IBM_rasterpos_clip"));
+}
+
+#endif /* GL_IBM_rasterpos_clip */
+
+#ifdef GL_IBM_static_data
+
+static void _glewInfo_GL_IBM_static_data (void)
+{
+ glewPrintExt("GL_IBM_static_data", GLEW_IBM_static_data, glewIsSupported("GL_IBM_static_data"), glewGetExtension("GL_IBM_static_data"));
+}
+
+#endif /* GL_IBM_static_data */
+
+#ifdef GL_IBM_texture_mirrored_repeat
+
+static void _glewInfo_GL_IBM_texture_mirrored_repeat (void)
+{
+ glewPrintExt("GL_IBM_texture_mirrored_repeat", GLEW_IBM_texture_mirrored_repeat, glewIsSupported("GL_IBM_texture_mirrored_repeat"), glewGetExtension("GL_IBM_texture_mirrored_repeat"));
+}
+
+#endif /* GL_IBM_texture_mirrored_repeat */
+
+#ifdef GL_IBM_vertex_array_lists
+
+static void _glewInfo_GL_IBM_vertex_array_lists (void)
+{
+ glewPrintExt("GL_IBM_vertex_array_lists", GLEW_IBM_vertex_array_lists, glewIsSupported("GL_IBM_vertex_array_lists"), glewGetExtension("GL_IBM_vertex_array_lists"));
+
+ glewInfoFunc("glColorPointerListIBM", glColorPointerListIBM == NULL);
+ glewInfoFunc("glEdgeFlagPointerListIBM", glEdgeFlagPointerListIBM == NULL);
+ glewInfoFunc("glFogCoordPointerListIBM", glFogCoordPointerListIBM == NULL);
+ glewInfoFunc("glIndexPointerListIBM", glIndexPointerListIBM == NULL);
+ glewInfoFunc("glNormalPointerListIBM", glNormalPointerListIBM == NULL);
+ glewInfoFunc("glSecondaryColorPointerListIBM", glSecondaryColorPointerListIBM == NULL);
+ glewInfoFunc("glTexCoordPointerListIBM", glTexCoordPointerListIBM == NULL);
+ glewInfoFunc("glVertexPointerListIBM", glVertexPointerListIBM == NULL);
+}
+
+#endif /* GL_IBM_vertex_array_lists */
+
+#ifdef GL_INGR_color_clamp
+
+static void _glewInfo_GL_INGR_color_clamp (void)
+{
+ glewPrintExt("GL_INGR_color_clamp", GLEW_INGR_color_clamp, glewIsSupported("GL_INGR_color_clamp"), glewGetExtension("GL_INGR_color_clamp"));
+}
+
+#endif /* GL_INGR_color_clamp */
+
+#ifdef GL_INGR_interlace_read
+
+static void _glewInfo_GL_INGR_interlace_read (void)
+{
+ glewPrintExt("GL_INGR_interlace_read", GLEW_INGR_interlace_read, glewIsSupported("GL_INGR_interlace_read"), glewGetExtension("GL_INGR_interlace_read"));
+}
+
+#endif /* GL_INGR_interlace_read */
+
+#ifdef GL_INTEL_parallel_arrays
+
+static void _glewInfo_GL_INTEL_parallel_arrays (void)
+{
+ glewPrintExt("GL_INTEL_parallel_arrays", GLEW_INTEL_parallel_arrays, glewIsSupported("GL_INTEL_parallel_arrays"), glewGetExtension("GL_INTEL_parallel_arrays"));
+
+ glewInfoFunc("glColorPointervINTEL", glColorPointervINTEL == NULL);
+ glewInfoFunc("glNormalPointervINTEL", glNormalPointervINTEL == NULL);
+ glewInfoFunc("glTexCoordPointervINTEL", glTexCoordPointervINTEL == NULL);
+ glewInfoFunc("glVertexPointervINTEL", glVertexPointervINTEL == NULL);
+}
+
+#endif /* GL_INTEL_parallel_arrays */
+
+#ifdef GL_INTEL_texture_scissor
+
+static void _glewInfo_GL_INTEL_texture_scissor (void)
+{
+ glewPrintExt("GL_INTEL_texture_scissor", GLEW_INTEL_texture_scissor, glewIsSupported("GL_INTEL_texture_scissor"), glewGetExtension("GL_INTEL_texture_scissor"));
+
+ glewInfoFunc("glTexScissorFuncINTEL", glTexScissorFuncINTEL == NULL);
+ glewInfoFunc("glTexScissorINTEL", glTexScissorINTEL == NULL);
+}
+
+#endif /* GL_INTEL_texture_scissor */
+
+#ifdef GL_KTX_buffer_region
+
+static void _glewInfo_GL_KTX_buffer_region (void)
+{
+ glewPrintExt("GL_KTX_buffer_region", GLEW_KTX_buffer_region, glewIsSupported("GL_KTX_buffer_region"), glewGetExtension("GL_KTX_buffer_region"));
+
+ glewInfoFunc("glBufferRegionEnabledEXT", glBufferRegionEnabledEXT == NULL);
+ glewInfoFunc("glDeleteBufferRegionEXT", glDeleteBufferRegionEXT == NULL);
+ glewInfoFunc("glDrawBufferRegionEXT", glDrawBufferRegionEXT == NULL);
+ glewInfoFunc("glNewBufferRegionEXT", glNewBufferRegionEXT == NULL);
+ glewInfoFunc("glReadBufferRegionEXT", glReadBufferRegionEXT == NULL);
+}
+
+#endif /* GL_KTX_buffer_region */
+
+#ifdef GL_MESAX_texture_stack
+
+static void _glewInfo_GL_MESAX_texture_stack (void)
+{
+ glewPrintExt("GL_MESAX_texture_stack", GLEW_MESAX_texture_stack, glewIsSupported("GL_MESAX_texture_stack"), glewGetExtension("GL_MESAX_texture_stack"));
+}
+
+#endif /* GL_MESAX_texture_stack */
+
+#ifdef GL_MESA_pack_invert
+
+static void _glewInfo_GL_MESA_pack_invert (void)
+{
+ glewPrintExt("GL_MESA_pack_invert", GLEW_MESA_pack_invert, glewIsSupported("GL_MESA_pack_invert"), glewGetExtension("GL_MESA_pack_invert"));
+}
+
+#endif /* GL_MESA_pack_invert */
+
+#ifdef GL_MESA_resize_buffers
+
+static void _glewInfo_GL_MESA_resize_buffers (void)
+{
+ glewPrintExt("GL_MESA_resize_buffers", GLEW_MESA_resize_buffers, glewIsSupported("GL_MESA_resize_buffers"), glewGetExtension("GL_MESA_resize_buffers"));
+
+ glewInfoFunc("glResizeBuffersMESA", glResizeBuffersMESA == NULL);
+}
+
+#endif /* GL_MESA_resize_buffers */
+
+#ifdef GL_MESA_window_pos
+
+static void _glewInfo_GL_MESA_window_pos (void)
+{
+ glewPrintExt("GL_MESA_window_pos", GLEW_MESA_window_pos, glewIsSupported("GL_MESA_window_pos"), glewGetExtension("GL_MESA_window_pos"));
+
+ glewInfoFunc("glWindowPos2dMESA", glWindowPos2dMESA == NULL);
+ glewInfoFunc("glWindowPos2dvMESA", glWindowPos2dvMESA == NULL);
+ glewInfoFunc("glWindowPos2fMESA", glWindowPos2fMESA == NULL);
+ glewInfoFunc("glWindowPos2fvMESA", glWindowPos2fvMESA == NULL);
+ glewInfoFunc("glWindowPos2iMESA", glWindowPos2iMESA == NULL);
+ glewInfoFunc("glWindowPos2ivMESA", glWindowPos2ivMESA == NULL);
+ glewInfoFunc("glWindowPos2sMESA", glWindowPos2sMESA == NULL);
+ glewInfoFunc("glWindowPos2svMESA", glWindowPos2svMESA == NULL);
+ glewInfoFunc("glWindowPos3dMESA", glWindowPos3dMESA == NULL);
+ glewInfoFunc("glWindowPos3dvMESA", glWindowPos3dvMESA == NULL);
+ glewInfoFunc("glWindowPos3fMESA", glWindowPos3fMESA == NULL);
+ glewInfoFunc("glWindowPos3fvMESA", glWindowPos3fvMESA == NULL);
+ glewInfoFunc("glWindowPos3iMESA", glWindowPos3iMESA == NULL);
+ glewInfoFunc("glWindowPos3ivMESA", glWindowPos3ivMESA == NULL);
+ glewInfoFunc("glWindowPos3sMESA", glWindowPos3sMESA == NULL);
+ glewInfoFunc("glWindowPos3svMESA", glWindowPos3svMESA == NULL);
+ glewInfoFunc("glWindowPos4dMESA", glWindowPos4dMESA == NULL);
+ glewInfoFunc("glWindowPos4dvMESA", glWindowPos4dvMESA == NULL);
+ glewInfoFunc("glWindowPos4fMESA", glWindowPos4fMESA == NULL);
+ glewInfoFunc("glWindowPos4fvMESA", glWindowPos4fvMESA == NULL);
+ glewInfoFunc("glWindowPos4iMESA", glWindowPos4iMESA == NULL);
+ glewInfoFunc("glWindowPos4ivMESA", glWindowPos4ivMESA == NULL);
+ glewInfoFunc("glWindowPos4sMESA", glWindowPos4sMESA == NULL);
+ glewInfoFunc("glWindowPos4svMESA", glWindowPos4svMESA == NULL);
+}
+
+#endif /* GL_MESA_window_pos */
+
+#ifdef GL_MESA_ycbcr_texture
+
+static void _glewInfo_GL_MESA_ycbcr_texture (void)
+{
+ glewPrintExt("GL_MESA_ycbcr_texture", GLEW_MESA_ycbcr_texture, glewIsSupported("GL_MESA_ycbcr_texture"), glewGetExtension("GL_MESA_ycbcr_texture"));
+}
+
+#endif /* GL_MESA_ycbcr_texture */
+
+#ifdef GL_NV_blend_square
+
+static void _glewInfo_GL_NV_blend_square (void)
+{
+ glewPrintExt("GL_NV_blend_square", GLEW_NV_blend_square, glewIsSupported("GL_NV_blend_square"), glewGetExtension("GL_NV_blend_square"));
+}
+
+#endif /* GL_NV_blend_square */
+
+#ifdef GL_NV_conditional_render
+
+static void _glewInfo_GL_NV_conditional_render (void)
+{
+ glewPrintExt("GL_NV_conditional_render", GLEW_NV_conditional_render, glewIsSupported("GL_NV_conditional_render"), glewGetExtension("GL_NV_conditional_render"));
+
+ glewInfoFunc("glBeginConditionalRenderNV", glBeginConditionalRenderNV == NULL);
+ glewInfoFunc("glEndConditionalRenderNV", glEndConditionalRenderNV == NULL);
+}
+
+#endif /* GL_NV_conditional_render */
+
+#ifdef GL_NV_copy_depth_to_color
+
+static void _glewInfo_GL_NV_copy_depth_to_color (void)
+{
+ glewPrintExt("GL_NV_copy_depth_to_color", GLEW_NV_copy_depth_to_color, glewIsSupported("GL_NV_copy_depth_to_color"), glewGetExtension("GL_NV_copy_depth_to_color"));
+}
+
+#endif /* GL_NV_copy_depth_to_color */
+
+#ifdef GL_NV_depth_buffer_float
+
+static void _glewInfo_GL_NV_depth_buffer_float (void)
+{
+ glewPrintExt("GL_NV_depth_buffer_float", GLEW_NV_depth_buffer_float, glewIsSupported("GL_NV_depth_buffer_float"), glewGetExtension("GL_NV_depth_buffer_float"));
+
+ glewInfoFunc("glClearDepthdNV", glClearDepthdNV == NULL);
+ glewInfoFunc("glDepthBoundsdNV", glDepthBoundsdNV == NULL);
+ glewInfoFunc("glDepthRangedNV", glDepthRangedNV == NULL);
+}
+
+#endif /* GL_NV_depth_buffer_float */
+
+#ifdef GL_NV_depth_clamp
+
+static void _glewInfo_GL_NV_depth_clamp (void)
+{
+ glewPrintExt("GL_NV_depth_clamp", GLEW_NV_depth_clamp, glewIsSupported("GL_NV_depth_clamp"), glewGetExtension("GL_NV_depth_clamp"));
+}
+
+#endif /* GL_NV_depth_clamp */
+
+#ifdef GL_NV_depth_range_unclamped
+
+static void _glewInfo_GL_NV_depth_range_unclamped (void)
+{
+ glewPrintExt("GL_NV_depth_range_unclamped", GLEW_NV_depth_range_unclamped, glewIsSupported("GL_NV_depth_range_unclamped"), glewGetExtension("GL_NV_depth_range_unclamped"));
+}
+
+#endif /* GL_NV_depth_range_unclamped */
+
+#ifdef GL_NV_evaluators
+
+static void _glewInfo_GL_NV_evaluators (void)
+{
+ glewPrintExt("GL_NV_evaluators", GLEW_NV_evaluators, glewIsSupported("GL_NV_evaluators"), glewGetExtension("GL_NV_evaluators"));
+
+ glewInfoFunc("glEvalMapsNV", glEvalMapsNV == NULL);
+ glewInfoFunc("glGetMapAttribParameterfvNV", glGetMapAttribParameterfvNV == NULL);
+ glewInfoFunc("glGetMapAttribParameterivNV", glGetMapAttribParameterivNV == NULL);
+ glewInfoFunc("glGetMapControlPointsNV", glGetMapControlPointsNV == NULL);
+ glewInfoFunc("glGetMapParameterfvNV", glGetMapParameterfvNV == NULL);
+ glewInfoFunc("glGetMapParameterivNV", glGetMapParameterivNV == NULL);
+ glewInfoFunc("glMapControlPointsNV", glMapControlPointsNV == NULL);
+ glewInfoFunc("glMapParameterfvNV", glMapParameterfvNV == NULL);
+ glewInfoFunc("glMapParameterivNV", glMapParameterivNV == NULL);
+}
+
+#endif /* GL_NV_evaluators */
+
+#ifdef GL_NV_explicit_multisample
+
+static void _glewInfo_GL_NV_explicit_multisample (void)
+{
+ glewPrintExt("GL_NV_explicit_multisample", GLEW_NV_explicit_multisample, glewIsSupported("GL_NV_explicit_multisample"), glewGetExtension("GL_NV_explicit_multisample"));
+
+ glewInfoFunc("glGetMultisamplefvNV", glGetMultisamplefvNV == NULL);
+ glewInfoFunc("glSampleMaskIndexedNV", glSampleMaskIndexedNV == NULL);
+ glewInfoFunc("glTexRenderbufferNV", glTexRenderbufferNV == NULL);
+}
+
+#endif /* GL_NV_explicit_multisample */
+
+#ifdef GL_NV_fence
+
+static void _glewInfo_GL_NV_fence (void)
+{
+ glewPrintExt("GL_NV_fence", GLEW_NV_fence, glewIsSupported("GL_NV_fence"), glewGetExtension("GL_NV_fence"));
+
+ glewInfoFunc("glDeleteFencesNV", glDeleteFencesNV == NULL);
+ glewInfoFunc("glFinishFenceNV", glFinishFenceNV == NULL);
+ glewInfoFunc("glGenFencesNV", glGenFencesNV == NULL);
+ glewInfoFunc("glGetFenceivNV", glGetFenceivNV == NULL);
+ glewInfoFunc("glIsFenceNV", glIsFenceNV == NULL);
+ glewInfoFunc("glSetFenceNV", glSetFenceNV == NULL);
+ glewInfoFunc("glTestFenceNV", glTestFenceNV == NULL);
+}
+
+#endif /* GL_NV_fence */
+
+#ifdef GL_NV_float_buffer
+
+static void _glewInfo_GL_NV_float_buffer (void)
+{
+ glewPrintExt("GL_NV_float_buffer", GLEW_NV_float_buffer, glewIsSupported("GL_NV_float_buffer"), glewGetExtension("GL_NV_float_buffer"));
+}
+
+#endif /* GL_NV_float_buffer */
+
+#ifdef GL_NV_fog_distance
+
+static void _glewInfo_GL_NV_fog_distance (void)
+{
+ glewPrintExt("GL_NV_fog_distance", GLEW_NV_fog_distance, glewIsSupported("GL_NV_fog_distance"), glewGetExtension("GL_NV_fog_distance"));
+}
+
+#endif /* GL_NV_fog_distance */
+
+#ifdef GL_NV_fragment_program
+
+static void _glewInfo_GL_NV_fragment_program (void)
+{
+ glewPrintExt("GL_NV_fragment_program", GLEW_NV_fragment_program, glewIsSupported("GL_NV_fragment_program"), glewGetExtension("GL_NV_fragment_program"));
+
+ glewInfoFunc("glGetProgramNamedParameterdvNV", glGetProgramNamedParameterdvNV == NULL);
+ glewInfoFunc("glGetProgramNamedParameterfvNV", glGetProgramNamedParameterfvNV == NULL);
+ glewInfoFunc("glProgramNamedParameter4dNV", glProgramNamedParameter4dNV == NULL);
+ glewInfoFunc("glProgramNamedParameter4dvNV", glProgramNamedParameter4dvNV == NULL);
+ glewInfoFunc("glProgramNamedParameter4fNV", glProgramNamedParameter4fNV == NULL);
+ glewInfoFunc("glProgramNamedParameter4fvNV", glProgramNamedParameter4fvNV == NULL);
+}
+
+#endif /* GL_NV_fragment_program */
+
+#ifdef GL_NV_fragment_program2
+
+static void _glewInfo_GL_NV_fragment_program2 (void)
+{
+ glewPrintExt("GL_NV_fragment_program2", GLEW_NV_fragment_program2, glewIsSupported("GL_NV_fragment_program2"), glewGetExtension("GL_NV_fragment_program2"));
+}
+
+#endif /* GL_NV_fragment_program2 */
+
+#ifdef GL_NV_fragment_program4
+
+static void _glewInfo_GL_NV_fragment_program4 (void)
+{
+ glewPrintExt("GL_NV_fragment_program4", GLEW_NV_fragment_program4, glewIsSupported("GL_NV_fragment_program4"), glewGetExtension("GL_NV_fragment_program4"));
+}
+
+#endif /* GL_NV_fragment_program4 */
+
+#ifdef GL_NV_fragment_program_option
+
+static void _glewInfo_GL_NV_fragment_program_option (void)
+{
+ glewPrintExt("GL_NV_fragment_program_option", GLEW_NV_fragment_program_option, glewIsSupported("GL_NV_fragment_program_option"), glewGetExtension("GL_NV_fragment_program_option"));
+}
+
+#endif /* GL_NV_fragment_program_option */
+
+#ifdef GL_NV_framebuffer_multisample_coverage
+
+static void _glewInfo_GL_NV_framebuffer_multisample_coverage (void)
+{
+ glewPrintExt("GL_NV_framebuffer_multisample_coverage", GLEW_NV_framebuffer_multisample_coverage, glewIsSupported("GL_NV_framebuffer_multisample_coverage"), glewGetExtension("GL_NV_framebuffer_multisample_coverage"));
+
+ glewInfoFunc("glRenderbufferStorageMultisampleCoverageNV", glRenderbufferStorageMultisampleCoverageNV == NULL);
+}
+
+#endif /* GL_NV_framebuffer_multisample_coverage */
+
+#ifdef GL_NV_geometry_program4
+
+static void _glewInfo_GL_NV_geometry_program4 (void)
+{
+ glewPrintExt("GL_NV_geometry_program4", GLEW_NV_geometry_program4, glewIsSupported("GL_NV_geometry_program4"), glewGetExtension("GL_NV_geometry_program4"));
+
+ glewInfoFunc("glProgramVertexLimitNV", glProgramVertexLimitNV == NULL);
+}
+
+#endif /* GL_NV_geometry_program4 */
+
+#ifdef GL_NV_geometry_shader4
+
+static void _glewInfo_GL_NV_geometry_shader4 (void)
+{
+ glewPrintExt("GL_NV_geometry_shader4", GLEW_NV_geometry_shader4, glewIsSupported("GL_NV_geometry_shader4"), glewGetExtension("GL_NV_geometry_shader4"));
+}
+
+#endif /* GL_NV_geometry_shader4 */
+
+#ifdef GL_NV_gpu_program4
+
+static void _glewInfo_GL_NV_gpu_program4 (void)
+{
+ glewPrintExt("GL_NV_gpu_program4", GLEW_NV_gpu_program4, glewIsSupported("GL_NV_gpu_program4"), glewGetExtension("GL_NV_gpu_program4"));
+
+ glewInfoFunc("glProgramEnvParameterI4iNV", glProgramEnvParameterI4iNV == NULL);
+ glewInfoFunc("glProgramEnvParameterI4ivNV", glProgramEnvParameterI4ivNV == NULL);
+ glewInfoFunc("glProgramEnvParameterI4uiNV", glProgramEnvParameterI4uiNV == NULL);
+ glewInfoFunc("glProgramEnvParameterI4uivNV", glProgramEnvParameterI4uivNV == NULL);
+ glewInfoFunc("glProgramEnvParametersI4ivNV", glProgramEnvParametersI4ivNV == NULL);
+ glewInfoFunc("glProgramEnvParametersI4uivNV", glProgramEnvParametersI4uivNV == NULL);
+ glewInfoFunc("glProgramLocalParameterI4iNV", glProgramLocalParameterI4iNV == NULL);
+ glewInfoFunc("glProgramLocalParameterI4ivNV", glProgramLocalParameterI4ivNV == NULL);
+ glewInfoFunc("glProgramLocalParameterI4uiNV", glProgramLocalParameterI4uiNV == NULL);
+ glewInfoFunc("glProgramLocalParameterI4uivNV", glProgramLocalParameterI4uivNV == NULL);
+ glewInfoFunc("glProgramLocalParametersI4ivNV", glProgramLocalParametersI4ivNV == NULL);
+ glewInfoFunc("glProgramLocalParametersI4uivNV", glProgramLocalParametersI4uivNV == NULL);
+}
+
+#endif /* GL_NV_gpu_program4 */
+
+#ifdef GL_NV_half_float
+
+static void _glewInfo_GL_NV_half_float (void)
+{
+ glewPrintExt("GL_NV_half_float", GLEW_NV_half_float, glewIsSupported("GL_NV_half_float"), glewGetExtension("GL_NV_half_float"));
+
+ glewInfoFunc("glColor3hNV", glColor3hNV == NULL);
+ glewInfoFunc("glColor3hvNV", glColor3hvNV == NULL);
+ glewInfoFunc("glColor4hNV", glColor4hNV == NULL);
+ glewInfoFunc("glColor4hvNV", glColor4hvNV == NULL);
+ glewInfoFunc("glFogCoordhNV", glFogCoordhNV == NULL);
+ glewInfoFunc("glFogCoordhvNV", glFogCoordhvNV == NULL);
+ glewInfoFunc("glMultiTexCoord1hNV", glMultiTexCoord1hNV == NULL);
+ glewInfoFunc("glMultiTexCoord1hvNV", glMultiTexCoord1hvNV == NULL);
+ glewInfoFunc("glMultiTexCoord2hNV", glMultiTexCoord2hNV == NULL);
+ glewInfoFunc("glMultiTexCoord2hvNV", glMultiTexCoord2hvNV == NULL);
+ glewInfoFunc("glMultiTexCoord3hNV", glMultiTexCoord3hNV == NULL);
+ glewInfoFunc("glMultiTexCoord3hvNV", glMultiTexCoord3hvNV == NULL);
+ glewInfoFunc("glMultiTexCoord4hNV", glMultiTexCoord4hNV == NULL);
+ glewInfoFunc("glMultiTexCoord4hvNV", glMultiTexCoord4hvNV == NULL);
+ glewInfoFunc("glNormal3hNV", glNormal3hNV == NULL);
+ glewInfoFunc("glNormal3hvNV", glNormal3hvNV == NULL);
+ glewInfoFunc("glSecondaryColor3hNV", glSecondaryColor3hNV == NULL);
+ glewInfoFunc("glSecondaryColor3hvNV", glSecondaryColor3hvNV == NULL);
+ glewInfoFunc("glTexCoord1hNV", glTexCoord1hNV == NULL);
+ glewInfoFunc("glTexCoord1hvNV", glTexCoord1hvNV == NULL);
+ glewInfoFunc("glTexCoord2hNV", glTexCoord2hNV == NULL);
+ glewInfoFunc("glTexCoord2hvNV", glTexCoord2hvNV == NULL);
+ glewInfoFunc("glTexCoord3hNV", glTexCoord3hNV == NULL);
+ glewInfoFunc("glTexCoord3hvNV", glTexCoord3hvNV == NULL);
+ glewInfoFunc("glTexCoord4hNV", glTexCoord4hNV == NULL);
+ glewInfoFunc("glTexCoord4hvNV", glTexCoord4hvNV == NULL);
+ glewInfoFunc("glVertex2hNV", glVertex2hNV == NULL);
+ glewInfoFunc("glVertex2hvNV", glVertex2hvNV == NULL);
+ glewInfoFunc("glVertex3hNV", glVertex3hNV == NULL);
+ glewInfoFunc("glVertex3hvNV", glVertex3hvNV == NULL);
+ glewInfoFunc("glVertex4hNV", glVertex4hNV == NULL);
+ glewInfoFunc("glVertex4hvNV", glVertex4hvNV == NULL);
+ glewInfoFunc("glVertexAttrib1hNV", glVertexAttrib1hNV == NULL);
+ glewInfoFunc("glVertexAttrib1hvNV", glVertexAttrib1hvNV == NULL);
+ glewInfoFunc("glVertexAttrib2hNV", glVertexAttrib2hNV == NULL);
+ glewInfoFunc("glVertexAttrib2hvNV", glVertexAttrib2hvNV == NULL);
+ glewInfoFunc("glVertexAttrib3hNV", glVertexAttrib3hNV == NULL);
+ glewInfoFunc("glVertexAttrib3hvNV", glVertexAttrib3hvNV == NULL);
+ glewInfoFunc("glVertexAttrib4hNV", glVertexAttrib4hNV == NULL);
+ glewInfoFunc("glVertexAttrib4hvNV", glVertexAttrib4hvNV == NULL);
+ glewInfoFunc("glVertexAttribs1hvNV", glVertexAttribs1hvNV == NULL);
+ glewInfoFunc("glVertexAttribs2hvNV", glVertexAttribs2hvNV == NULL);
+ glewInfoFunc("glVertexAttribs3hvNV", glVertexAttribs3hvNV == NULL);
+ glewInfoFunc("glVertexAttribs4hvNV", glVertexAttribs4hvNV == NULL);
+ glewInfoFunc("glVertexWeighthNV", glVertexWeighthNV == NULL);
+ glewInfoFunc("glVertexWeighthvNV", glVertexWeighthvNV == NULL);
+}
+
+#endif /* GL_NV_half_float */
+
+#ifdef GL_NV_light_max_exponent
+
+static void _glewInfo_GL_NV_light_max_exponent (void)
+{
+ glewPrintExt("GL_NV_light_max_exponent", GLEW_NV_light_max_exponent, glewIsSupported("GL_NV_light_max_exponent"), glewGetExtension("GL_NV_light_max_exponent"));
+}
+
+#endif /* GL_NV_light_max_exponent */
+
+#ifdef GL_NV_multisample_filter_hint
+
+static void _glewInfo_GL_NV_multisample_filter_hint (void)
+{
+ glewPrintExt("GL_NV_multisample_filter_hint", GLEW_NV_multisample_filter_hint, glewIsSupported("GL_NV_multisample_filter_hint"), glewGetExtension("GL_NV_multisample_filter_hint"));
+}
+
+#endif /* GL_NV_multisample_filter_hint */
+
+#ifdef GL_NV_occlusion_query
+
+static void _glewInfo_GL_NV_occlusion_query (void)
+{
+ glewPrintExt("GL_NV_occlusion_query", GLEW_NV_occlusion_query, glewIsSupported("GL_NV_occlusion_query"), glewGetExtension("GL_NV_occlusion_query"));
+
+ glewInfoFunc("glBeginOcclusionQueryNV", glBeginOcclusionQueryNV == NULL);
+ glewInfoFunc("glDeleteOcclusionQueriesNV", glDeleteOcclusionQueriesNV == NULL);
+ glewInfoFunc("glEndOcclusionQueryNV", glEndOcclusionQueryNV == NULL);
+ glewInfoFunc("glGenOcclusionQueriesNV", glGenOcclusionQueriesNV == NULL);
+ glewInfoFunc("glGetOcclusionQueryivNV", glGetOcclusionQueryivNV == NULL);
+ glewInfoFunc("glGetOcclusionQueryuivNV", glGetOcclusionQueryuivNV == NULL);
+ glewInfoFunc("glIsOcclusionQueryNV", glIsOcclusionQueryNV == NULL);
+}
+
+#endif /* GL_NV_occlusion_query */
+
+#ifdef GL_NV_packed_depth_stencil
+
+static void _glewInfo_GL_NV_packed_depth_stencil (void)
+{
+ glewPrintExt("GL_NV_packed_depth_stencil", GLEW_NV_packed_depth_stencil, glewIsSupported("GL_NV_packed_depth_stencil"), glewGetExtension("GL_NV_packed_depth_stencil"));
+}
+
+#endif /* GL_NV_packed_depth_stencil */
+
+#ifdef GL_NV_parameter_buffer_object
+
+static void _glewInfo_GL_NV_parameter_buffer_object (void)
+{
+ glewPrintExt("GL_NV_parameter_buffer_object", GLEW_NV_parameter_buffer_object, glewIsSupported("GL_NV_parameter_buffer_object"), glewGetExtension("GL_NV_parameter_buffer_object"));
+
+ glewInfoFunc("glProgramBufferParametersIivNV", glProgramBufferParametersIivNV == NULL);
+ glewInfoFunc("glProgramBufferParametersIuivNV", glProgramBufferParametersIuivNV == NULL);
+ glewInfoFunc("glProgramBufferParametersfvNV", glProgramBufferParametersfvNV == NULL);
+}
+
+#endif /* GL_NV_parameter_buffer_object */
+
+#ifdef GL_NV_pixel_data_range
+
+static void _glewInfo_GL_NV_pixel_data_range (void)
+{
+ glewPrintExt("GL_NV_pixel_data_range", GLEW_NV_pixel_data_range, glewIsSupported("GL_NV_pixel_data_range"), glewGetExtension("GL_NV_pixel_data_range"));
+
+ glewInfoFunc("glFlushPixelDataRangeNV", glFlushPixelDataRangeNV == NULL);
+ glewInfoFunc("glPixelDataRangeNV", glPixelDataRangeNV == NULL);
+}
+
+#endif /* GL_NV_pixel_data_range */
+
+#ifdef GL_NV_point_sprite
+
+static void _glewInfo_GL_NV_point_sprite (void)
+{
+ glewPrintExt("GL_NV_point_sprite", GLEW_NV_point_sprite, glewIsSupported("GL_NV_point_sprite"), glewGetExtension("GL_NV_point_sprite"));
+
+ glewInfoFunc("glPointParameteriNV", glPointParameteriNV == NULL);
+ glewInfoFunc("glPointParameterivNV", glPointParameterivNV == NULL);
+}
+
+#endif /* GL_NV_point_sprite */
+
+#ifdef GL_NV_present_video
+
+static void _glewInfo_GL_NV_present_video (void)
+{
+ glewPrintExt("GL_NV_present_video", GLEW_NV_present_video, glewIsSupported("GL_NV_present_video"), glewGetExtension("GL_NV_present_video"));
+
+ glewInfoFunc("glGetVideoi64vNV", glGetVideoi64vNV == NULL);
+ glewInfoFunc("glGetVideoivNV", glGetVideoivNV == NULL);
+ glewInfoFunc("glGetVideoui64vNV", glGetVideoui64vNV == NULL);
+ glewInfoFunc("glGetVideouivNV", glGetVideouivNV == NULL);
+ glewInfoFunc("glPresentFrameDualFillNV", glPresentFrameDualFillNV == NULL);
+ glewInfoFunc("glPresentFrameKeyedNV", glPresentFrameKeyedNV == NULL);
+ glewInfoFunc("glVideoParameterivNV", glVideoParameterivNV == NULL);
+}
+
+#endif /* GL_NV_present_video */
+
+#ifdef GL_NV_primitive_restart
+
+static void _glewInfo_GL_NV_primitive_restart (void)
+{
+ glewPrintExt("GL_NV_primitive_restart", GLEW_NV_primitive_restart, glewIsSupported("GL_NV_primitive_restart"), glewGetExtension("GL_NV_primitive_restart"));
+
+ glewInfoFunc("glPrimitiveRestartIndexNV", glPrimitiveRestartIndexNV == NULL);
+ glewInfoFunc("glPrimitiveRestartNV", glPrimitiveRestartNV == NULL);
+}
+
+#endif /* GL_NV_primitive_restart */
+
+#ifdef GL_NV_register_combiners
+
+static void _glewInfo_GL_NV_register_combiners (void)
+{
+ glewPrintExt("GL_NV_register_combiners", GLEW_NV_register_combiners, glewIsSupported("GL_NV_register_combiners"), glewGetExtension("GL_NV_register_combiners"));
+
+ glewInfoFunc("glCombinerInputNV", glCombinerInputNV == NULL);
+ glewInfoFunc("glCombinerOutputNV", glCombinerOutputNV == NULL);
+ glewInfoFunc("glCombinerParameterfNV", glCombinerParameterfNV == NULL);
+ glewInfoFunc("glCombinerParameterfvNV", glCombinerParameterfvNV == NULL);
+ glewInfoFunc("glCombinerParameteriNV", glCombinerParameteriNV == NULL);
+ glewInfoFunc("glCombinerParameterivNV", glCombinerParameterivNV == NULL);
+ glewInfoFunc("glFinalCombinerInputNV", glFinalCombinerInputNV == NULL);
+ glewInfoFunc("glGetCombinerInputParameterfvNV", glGetCombinerInputParameterfvNV == NULL);
+ glewInfoFunc("glGetCombinerInputParameterivNV", glGetCombinerInputParameterivNV == NULL);
+ glewInfoFunc("glGetCombinerOutputParameterfvNV", glGetCombinerOutputParameterfvNV == NULL);
+ glewInfoFunc("glGetCombinerOutputParameterivNV", glGetCombinerOutputParameterivNV == NULL);
+ glewInfoFunc("glGetFinalCombinerInputParameterfvNV", glGetFinalCombinerInputParameterfvNV == NULL);
+ glewInfoFunc("glGetFinalCombinerInputParameterivNV", glGetFinalCombinerInputParameterivNV == NULL);
+}
+
+#endif /* GL_NV_register_combiners */
+
+#ifdef GL_NV_register_combiners2
+
+static void _glewInfo_GL_NV_register_combiners2 (void)
+{
+ glewPrintExt("GL_NV_register_combiners2", GLEW_NV_register_combiners2, glewIsSupported("GL_NV_register_combiners2"), glewGetExtension("GL_NV_register_combiners2"));
+
+ glewInfoFunc("glCombinerStageParameterfvNV", glCombinerStageParameterfvNV == NULL);
+ glewInfoFunc("glGetCombinerStageParameterfvNV", glGetCombinerStageParameterfvNV == NULL);
+}
+
+#endif /* GL_NV_register_combiners2 */
+
+#ifdef GL_NV_texgen_emboss
+
+static void _glewInfo_GL_NV_texgen_emboss (void)
+{
+ glewPrintExt("GL_NV_texgen_emboss", GLEW_NV_texgen_emboss, glewIsSupported("GL_NV_texgen_emboss"), glewGetExtension("GL_NV_texgen_emboss"));
+}
+
+#endif /* GL_NV_texgen_emboss */
+
+#ifdef GL_NV_texgen_reflection
+
+static void _glewInfo_GL_NV_texgen_reflection (void)
+{
+ glewPrintExt("GL_NV_texgen_reflection", GLEW_NV_texgen_reflection, glewIsSupported("GL_NV_texgen_reflection"), glewGetExtension("GL_NV_texgen_reflection"));
+}
+
+#endif /* GL_NV_texgen_reflection */
+
+#ifdef GL_NV_texture_compression_vtc
+
+static void _glewInfo_GL_NV_texture_compression_vtc (void)
+{
+ glewPrintExt("GL_NV_texture_compression_vtc", GLEW_NV_texture_compression_vtc, glewIsSupported("GL_NV_texture_compression_vtc"), glewGetExtension("GL_NV_texture_compression_vtc"));
+}
+
+#endif /* GL_NV_texture_compression_vtc */
+
+#ifdef GL_NV_texture_env_combine4
+
+static void _glewInfo_GL_NV_texture_env_combine4 (void)
+{
+ glewPrintExt("GL_NV_texture_env_combine4", GLEW_NV_texture_env_combine4, glewIsSupported("GL_NV_texture_env_combine4"), glewGetExtension("GL_NV_texture_env_combine4"));
+}
+
+#endif /* GL_NV_texture_env_combine4 */
+
+#ifdef GL_NV_texture_expand_normal
+
+static void _glewInfo_GL_NV_texture_expand_normal (void)
+{
+ glewPrintExt("GL_NV_texture_expand_normal", GLEW_NV_texture_expand_normal, glewIsSupported("GL_NV_texture_expand_normal"), glewGetExtension("GL_NV_texture_expand_normal"));
+}
+
+#endif /* GL_NV_texture_expand_normal */
+
+#ifdef GL_NV_texture_rectangle
+
+static void _glewInfo_GL_NV_texture_rectangle (void)
+{
+ glewPrintExt("GL_NV_texture_rectangle", GLEW_NV_texture_rectangle, glewIsSupported("GL_NV_texture_rectangle"), glewGetExtension("GL_NV_texture_rectangle"));
+}
+
+#endif /* GL_NV_texture_rectangle */
+
+#ifdef GL_NV_texture_shader
+
+static void _glewInfo_GL_NV_texture_shader (void)
+{
+ glewPrintExt("GL_NV_texture_shader", GLEW_NV_texture_shader, glewIsSupported("GL_NV_texture_shader"), glewGetExtension("GL_NV_texture_shader"));
+}
+
+#endif /* GL_NV_texture_shader */
+
+#ifdef GL_NV_texture_shader2
+
+static void _glewInfo_GL_NV_texture_shader2 (void)
+{
+ glewPrintExt("GL_NV_texture_shader2", GLEW_NV_texture_shader2, glewIsSupported("GL_NV_texture_shader2"), glewGetExtension("GL_NV_texture_shader2"));
+}
+
+#endif /* GL_NV_texture_shader2 */
+
+#ifdef GL_NV_texture_shader3
+
+static void _glewInfo_GL_NV_texture_shader3 (void)
+{
+ glewPrintExt("GL_NV_texture_shader3", GLEW_NV_texture_shader3, glewIsSupported("GL_NV_texture_shader3"), glewGetExtension("GL_NV_texture_shader3"));
+}
+
+#endif /* GL_NV_texture_shader3 */
+
+#ifdef GL_NV_transform_feedback
+
+static void _glewInfo_GL_NV_transform_feedback (void)
+{
+ glewPrintExt("GL_NV_transform_feedback", GLEW_NV_transform_feedback, glewIsSupported("GL_NV_transform_feedback"), glewGetExtension("GL_NV_transform_feedback"));
+
+ glewInfoFunc("glActiveVaryingNV", glActiveVaryingNV == NULL);
+ glewInfoFunc("glBeginTransformFeedbackNV", glBeginTransformFeedbackNV == NULL);
+ glewInfoFunc("glBindBufferBaseNV", glBindBufferBaseNV == NULL);
+ glewInfoFunc("glBindBufferOffsetNV", glBindBufferOffsetNV == NULL);
+ glewInfoFunc("glBindBufferRangeNV", glBindBufferRangeNV == NULL);
+ glewInfoFunc("glEndTransformFeedbackNV", glEndTransformFeedbackNV == NULL);
+ glewInfoFunc("glGetActiveVaryingNV", glGetActiveVaryingNV == NULL);
+ glewInfoFunc("glGetTransformFeedbackVaryingNV", glGetTransformFeedbackVaryingNV == NULL);
+ glewInfoFunc("glGetVaryingLocationNV", glGetVaryingLocationNV == NULL);
+ glewInfoFunc("glTransformFeedbackAttribsNV", glTransformFeedbackAttribsNV == NULL);
+ glewInfoFunc("glTransformFeedbackVaryingsNV", glTransformFeedbackVaryingsNV == NULL);
+}
+
+#endif /* GL_NV_transform_feedback */
+
+#ifdef GL_NV_vertex_array_range
+
+static void _glewInfo_GL_NV_vertex_array_range (void)
+{
+ glewPrintExt("GL_NV_vertex_array_range", GLEW_NV_vertex_array_range, glewIsSupported("GL_NV_vertex_array_range"), glewGetExtension("GL_NV_vertex_array_range"));
+
+ glewInfoFunc("glFlushVertexArrayRangeNV", glFlushVertexArrayRangeNV == NULL);
+ glewInfoFunc("glVertexArrayRangeNV", glVertexArrayRangeNV == NULL);
+}
+
+#endif /* GL_NV_vertex_array_range */
+
+#ifdef GL_NV_vertex_array_range2
+
+static void _glewInfo_GL_NV_vertex_array_range2 (void)
+{
+ glewPrintExt("GL_NV_vertex_array_range2", GLEW_NV_vertex_array_range2, glewIsSupported("GL_NV_vertex_array_range2"), glewGetExtension("GL_NV_vertex_array_range2"));
+}
+
+#endif /* GL_NV_vertex_array_range2 */
+
+#ifdef GL_NV_vertex_program
+
+static void _glewInfo_GL_NV_vertex_program (void)
+{
+ glewPrintExt("GL_NV_vertex_program", GLEW_NV_vertex_program, glewIsSupported("GL_NV_vertex_program"), glewGetExtension("GL_NV_vertex_program"));
+
+ glewInfoFunc("glAreProgramsResidentNV", glAreProgramsResidentNV == NULL);
+ glewInfoFunc("glBindProgramNV", glBindProgramNV == NULL);
+ glewInfoFunc("glDeleteProgramsNV", glDeleteProgramsNV == NULL);
+ glewInfoFunc("glExecuteProgramNV", glExecuteProgramNV == NULL);
+ glewInfoFunc("glGenProgramsNV", glGenProgramsNV == NULL);
+ glewInfoFunc("glGetProgramParameterdvNV", glGetProgramParameterdvNV == NULL);
+ glewInfoFunc("glGetProgramParameterfvNV", glGetProgramParameterfvNV == NULL);
+ glewInfoFunc("glGetProgramStringNV", glGetProgramStringNV == NULL);
+ glewInfoFunc("glGetProgramivNV", glGetProgramivNV == NULL);
+ glewInfoFunc("glGetTrackMatrixivNV", glGetTrackMatrixivNV == NULL);
+ glewInfoFunc("glGetVertexAttribPointervNV", glGetVertexAttribPointervNV == NULL);
+ glewInfoFunc("glGetVertexAttribdvNV", glGetVertexAttribdvNV == NULL);
+ glewInfoFunc("glGetVertexAttribfvNV", glGetVertexAttribfvNV == NULL);
+ glewInfoFunc("glGetVertexAttribivNV", glGetVertexAttribivNV == NULL);
+ glewInfoFunc("glIsProgramNV", glIsProgramNV == NULL);
+ glewInfoFunc("glLoadProgramNV", glLoadProgramNV == NULL);
+ glewInfoFunc("glProgramParameter4dNV", glProgramParameter4dNV == NULL);
+ glewInfoFunc("glProgramParameter4dvNV", glProgramParameter4dvNV == NULL);
+ glewInfoFunc("glProgramParameter4fNV", glProgramParameter4fNV == NULL);
+ glewInfoFunc("glProgramParameter4fvNV", glProgramParameter4fvNV == NULL);
+ glewInfoFunc("glProgramParameters4dvNV", glProgramParameters4dvNV == NULL);
+ glewInfoFunc("glProgramParameters4fvNV", glProgramParameters4fvNV == NULL);
+ glewInfoFunc("glRequestResidentProgramsNV", glRequestResidentProgramsNV == NULL);
+ glewInfoFunc("glTrackMatrixNV", glTrackMatrixNV == NULL);
+ glewInfoFunc("glVertexAttrib1dNV", glVertexAttrib1dNV == NULL);
+ glewInfoFunc("glVertexAttrib1dvNV", glVertexAttrib1dvNV == NULL);
+ glewInfoFunc("glVertexAttrib1fNV", glVertexAttrib1fNV == NULL);
+ glewInfoFunc("glVertexAttrib1fvNV", glVertexAttrib1fvNV == NULL);
+ glewInfoFunc("glVertexAttrib1sNV", glVertexAttrib1sNV == NULL);
+ glewInfoFunc("glVertexAttrib1svNV", glVertexAttrib1svNV == NULL);
+ glewInfoFunc("glVertexAttrib2dNV", glVertexAttrib2dNV == NULL);
+ glewInfoFunc("glVertexAttrib2dvNV", glVertexAttrib2dvNV == NULL);
+ glewInfoFunc("glVertexAttrib2fNV", glVertexAttrib2fNV == NULL);
+ glewInfoFunc("glVertexAttrib2fvNV", glVertexAttrib2fvNV == NULL);
+ glewInfoFunc("glVertexAttrib2sNV", glVertexAttrib2sNV == NULL);
+ glewInfoFunc("glVertexAttrib2svNV", glVertexAttrib2svNV == NULL);
+ glewInfoFunc("glVertexAttrib3dNV", glVertexAttrib3dNV == NULL);
+ glewInfoFunc("glVertexAttrib3dvNV", glVertexAttrib3dvNV == NULL);
+ glewInfoFunc("glVertexAttrib3fNV", glVertexAttrib3fNV == NULL);
+ glewInfoFunc("glVertexAttrib3fvNV", glVertexAttrib3fvNV == NULL);
+ glewInfoFunc("glVertexAttrib3sNV", glVertexAttrib3sNV == NULL);
+ glewInfoFunc("glVertexAttrib3svNV", glVertexAttrib3svNV == NULL);
+ glewInfoFunc("glVertexAttrib4dNV", glVertexAttrib4dNV == NULL);
+ glewInfoFunc("glVertexAttrib4dvNV", glVertexAttrib4dvNV == NULL);
+ glewInfoFunc("glVertexAttrib4fNV", glVertexAttrib4fNV == NULL);
+ glewInfoFunc("glVertexAttrib4fvNV", glVertexAttrib4fvNV == NULL);
+ glewInfoFunc("glVertexAttrib4sNV", glVertexAttrib4sNV == NULL);
+ glewInfoFunc("glVertexAttrib4svNV", glVertexAttrib4svNV == NULL);
+ glewInfoFunc("glVertexAttrib4ubNV", glVertexAttrib4ubNV == NULL);
+ glewInfoFunc("glVertexAttrib4ubvNV", glVertexAttrib4ubvNV == NULL);
+ glewInfoFunc("glVertexAttribPointerNV", glVertexAttribPointerNV == NULL);
+ glewInfoFunc("glVertexAttribs1dvNV", glVertexAttribs1dvNV == NULL);
+ glewInfoFunc("glVertexAttribs1fvNV", glVertexAttribs1fvNV == NULL);
+ glewInfoFunc("glVertexAttribs1svNV", glVertexAttribs1svNV == NULL);
+ glewInfoFunc("glVertexAttribs2dvNV", glVertexAttribs2dvNV == NULL);
+ glewInfoFunc("glVertexAttribs2fvNV", glVertexAttribs2fvNV == NULL);
+ glewInfoFunc("glVertexAttribs2svNV", glVertexAttribs2svNV == NULL);
+ glewInfoFunc("glVertexAttribs3dvNV", glVertexAttribs3dvNV == NULL);
+ glewInfoFunc("glVertexAttribs3fvNV", glVertexAttribs3fvNV == NULL);
+ glewInfoFunc("glVertexAttribs3svNV", glVertexAttribs3svNV == NULL);
+ glewInfoFunc("glVertexAttribs4dvNV", glVertexAttribs4dvNV == NULL);
+ glewInfoFunc("glVertexAttribs4fvNV", glVertexAttribs4fvNV == NULL);
+ glewInfoFunc("glVertexAttribs4svNV", glVertexAttribs4svNV == NULL);
+ glewInfoFunc("glVertexAttribs4ubvNV", glVertexAttribs4ubvNV == NULL);
+}
+
+#endif /* GL_NV_vertex_program */
+
+#ifdef GL_NV_vertex_program1_1
+
+static void _glewInfo_GL_NV_vertex_program1_1 (void)
+{
+ glewPrintExt("GL_NV_vertex_program1_1", GLEW_NV_vertex_program1_1, glewIsSupported("GL_NV_vertex_program1_1"), glewGetExtension("GL_NV_vertex_program1_1"));
+}
+
+#endif /* GL_NV_vertex_program1_1 */
+
+#ifdef GL_NV_vertex_program2
+
+static void _glewInfo_GL_NV_vertex_program2 (void)
+{
+ glewPrintExt("GL_NV_vertex_program2", GLEW_NV_vertex_program2, glewIsSupported("GL_NV_vertex_program2"), glewGetExtension("GL_NV_vertex_program2"));
+}
+
+#endif /* GL_NV_vertex_program2 */
+
+#ifdef GL_NV_vertex_program2_option
+
+static void _glewInfo_GL_NV_vertex_program2_option (void)
+{
+ glewPrintExt("GL_NV_vertex_program2_option", GLEW_NV_vertex_program2_option, glewIsSupported("GL_NV_vertex_program2_option"), glewGetExtension("GL_NV_vertex_program2_option"));
+}
+
+#endif /* GL_NV_vertex_program2_option */
+
+#ifdef GL_NV_vertex_program3
+
+static void _glewInfo_GL_NV_vertex_program3 (void)
+{
+ glewPrintExt("GL_NV_vertex_program3", GLEW_NV_vertex_program3, glewIsSupported("GL_NV_vertex_program3"), glewGetExtension("GL_NV_vertex_program3"));
+}
+
+#endif /* GL_NV_vertex_program3 */
+
+#ifdef GL_NV_vertex_program4
+
+static void _glewInfo_GL_NV_vertex_program4 (void)
+{
+ glewPrintExt("GL_NV_vertex_program4", GLEW_NV_vertex_program4, glewIsSupported("GL_NV_vertex_program4"), glewGetExtension("GL_NV_vertex_program4"));
+}
+
+#endif /* GL_NV_vertex_program4 */
+
+#ifdef GL_OES_byte_coordinates
+
+static void _glewInfo_GL_OES_byte_coordinates (void)
+{
+ glewPrintExt("GL_OES_byte_coordinates", GLEW_OES_byte_coordinates, glewIsSupported("GL_OES_byte_coordinates"), glewGetExtension("GL_OES_byte_coordinates"));
+}
+
+#endif /* GL_OES_byte_coordinates */
+
+#ifdef GL_OES_compressed_paletted_texture
+
+static void _glewInfo_GL_OES_compressed_paletted_texture (void)
+{
+ glewPrintExt("GL_OES_compressed_paletted_texture", GLEW_OES_compressed_paletted_texture, glewIsSupported("GL_OES_compressed_paletted_texture"), glewGetExtension("GL_OES_compressed_paletted_texture"));
+}
+
+#endif /* GL_OES_compressed_paletted_texture */
+
+#ifdef GL_OES_read_format
+
+static void _glewInfo_GL_OES_read_format (void)
+{
+ glewPrintExt("GL_OES_read_format", GLEW_OES_read_format, glewIsSupported("GL_OES_read_format"), glewGetExtension("GL_OES_read_format"));
+}
+
+#endif /* GL_OES_read_format */
+
+#ifdef GL_OES_single_precision
+
+static void _glewInfo_GL_OES_single_precision (void)
+{
+ glewPrintExt("GL_OES_single_precision", GLEW_OES_single_precision, glewIsSupported("GL_OES_single_precision"), glewGetExtension("GL_OES_single_precision"));
+
+ glewInfoFunc("glClearDepthfOES", glClearDepthfOES == NULL);
+ glewInfoFunc("glClipPlanefOES", glClipPlanefOES == NULL);
+ glewInfoFunc("glDepthRangefOES", glDepthRangefOES == NULL);
+ glewInfoFunc("glFrustumfOES", glFrustumfOES == NULL);
+ glewInfoFunc("glGetClipPlanefOES", glGetClipPlanefOES == NULL);
+ glewInfoFunc("glOrthofOES", glOrthofOES == NULL);
+}
+
+#endif /* GL_OES_single_precision */
+
+#ifdef GL_OML_interlace
+
+static void _glewInfo_GL_OML_interlace (void)
+{
+ glewPrintExt("GL_OML_interlace", GLEW_OML_interlace, glewIsSupported("GL_OML_interlace"), glewGetExtension("GL_OML_interlace"));
+}
+
+#endif /* GL_OML_interlace */
+
+#ifdef GL_OML_resample
+
+static void _glewInfo_GL_OML_resample (void)
+{
+ glewPrintExt("GL_OML_resample", GLEW_OML_resample, glewIsSupported("GL_OML_resample"), glewGetExtension("GL_OML_resample"));
+}
+
+#endif /* GL_OML_resample */
+
+#ifdef GL_OML_subsample
+
+static void _glewInfo_GL_OML_subsample (void)
+{
+ glewPrintExt("GL_OML_subsample", GLEW_OML_subsample, glewIsSupported("GL_OML_subsample"), glewGetExtension("GL_OML_subsample"));
+}
+
+#endif /* GL_OML_subsample */
+
+#ifdef GL_PGI_misc_hints
+
+static void _glewInfo_GL_PGI_misc_hints (void)
+{
+ glewPrintExt("GL_PGI_misc_hints", GLEW_PGI_misc_hints, glewIsSupported("GL_PGI_misc_hints"), glewGetExtension("GL_PGI_misc_hints"));
+}
+
+#endif /* GL_PGI_misc_hints */
+
+#ifdef GL_PGI_vertex_hints
+
+static void _glewInfo_GL_PGI_vertex_hints (void)
+{
+ glewPrintExt("GL_PGI_vertex_hints", GLEW_PGI_vertex_hints, glewIsSupported("GL_PGI_vertex_hints"), glewGetExtension("GL_PGI_vertex_hints"));
+}
+
+#endif /* GL_PGI_vertex_hints */
+
+#ifdef GL_REND_screen_coordinates
+
+static void _glewInfo_GL_REND_screen_coordinates (void)
+{
+ glewPrintExt("GL_REND_screen_coordinates", GLEW_REND_screen_coordinates, glewIsSupported("GL_REND_screen_coordinates"), glewGetExtension("GL_REND_screen_coordinates"));
+}
+
+#endif /* GL_REND_screen_coordinates */
+
+#ifdef GL_S3_s3tc
+
+static void _glewInfo_GL_S3_s3tc (void)
+{
+ glewPrintExt("GL_S3_s3tc", GLEW_S3_s3tc, glewIsSupported("GL_S3_s3tc"), glewGetExtension("GL_S3_s3tc"));
+}
+
+#endif /* GL_S3_s3tc */
+
+#ifdef GL_SGIS_color_range
+
+static void _glewInfo_GL_SGIS_color_range (void)
+{
+ glewPrintExt("GL_SGIS_color_range", GLEW_SGIS_color_range, glewIsSupported("GL_SGIS_color_range"), glewGetExtension("GL_SGIS_color_range"));
+}
+
+#endif /* GL_SGIS_color_range */
+
+#ifdef GL_SGIS_detail_texture
+
+static void _glewInfo_GL_SGIS_detail_texture (void)
+{
+ glewPrintExt("GL_SGIS_detail_texture", GLEW_SGIS_detail_texture, glewIsSupported("GL_SGIS_detail_texture"), glewGetExtension("GL_SGIS_detail_texture"));
+
+ glewInfoFunc("glDetailTexFuncSGIS", glDetailTexFuncSGIS == NULL);
+ glewInfoFunc("glGetDetailTexFuncSGIS", glGetDetailTexFuncSGIS == NULL);
+}
+
+#endif /* GL_SGIS_detail_texture */
+
+#ifdef GL_SGIS_fog_function
+
+static void _glewInfo_GL_SGIS_fog_function (void)
+{
+ glewPrintExt("GL_SGIS_fog_function", GLEW_SGIS_fog_function, glewIsSupported("GL_SGIS_fog_function"), glewGetExtension("GL_SGIS_fog_function"));
+
+ glewInfoFunc("glFogFuncSGIS", glFogFuncSGIS == NULL);
+ glewInfoFunc("glGetFogFuncSGIS", glGetFogFuncSGIS == NULL);
+}
+
+#endif /* GL_SGIS_fog_function */
+
+#ifdef GL_SGIS_generate_mipmap
+
+static void _glewInfo_GL_SGIS_generate_mipmap (void)
+{
+ glewPrintExt("GL_SGIS_generate_mipmap", GLEW_SGIS_generate_mipmap, glewIsSupported("GL_SGIS_generate_mipmap"), glewGetExtension("GL_SGIS_generate_mipmap"));
+}
+
+#endif /* GL_SGIS_generate_mipmap */
+
+#ifdef GL_SGIS_multisample
+
+static void _glewInfo_GL_SGIS_multisample (void)
+{
+ glewPrintExt("GL_SGIS_multisample", GLEW_SGIS_multisample, glewIsSupported("GL_SGIS_multisample"), glewGetExtension("GL_SGIS_multisample"));
+
+ glewInfoFunc("glSampleMaskSGIS", glSampleMaskSGIS == NULL);
+ glewInfoFunc("glSamplePatternSGIS", glSamplePatternSGIS == NULL);
+}
+
+#endif /* GL_SGIS_multisample */
+
+#ifdef GL_SGIS_pixel_texture
+
+static void _glewInfo_GL_SGIS_pixel_texture (void)
+{
+ glewPrintExt("GL_SGIS_pixel_texture", GLEW_SGIS_pixel_texture, glewIsSupported("GL_SGIS_pixel_texture"), glewGetExtension("GL_SGIS_pixel_texture"));
+}
+
+#endif /* GL_SGIS_pixel_texture */
+
+#ifdef GL_SGIS_point_line_texgen
+
+static void _glewInfo_GL_SGIS_point_line_texgen (void)
+{
+ glewPrintExt("GL_SGIS_point_line_texgen", GLEW_SGIS_point_line_texgen, glewIsSupported("GL_SGIS_point_line_texgen"), glewGetExtension("GL_SGIS_point_line_texgen"));
+}
+
+#endif /* GL_SGIS_point_line_texgen */
+
+#ifdef GL_SGIS_sharpen_texture
+
+static void _glewInfo_GL_SGIS_sharpen_texture (void)
+{
+ glewPrintExt("GL_SGIS_sharpen_texture", GLEW_SGIS_sharpen_texture, glewIsSupported("GL_SGIS_sharpen_texture"), glewGetExtension("GL_SGIS_sharpen_texture"));
+
+ glewInfoFunc("glGetSharpenTexFuncSGIS", glGetSharpenTexFuncSGIS == NULL);
+ glewInfoFunc("glSharpenTexFuncSGIS", glSharpenTexFuncSGIS == NULL);
+}
+
+#endif /* GL_SGIS_sharpen_texture */
+
+#ifdef GL_SGIS_texture4D
+
+static void _glewInfo_GL_SGIS_texture4D (void)
+{
+ glewPrintExt("GL_SGIS_texture4D", GLEW_SGIS_texture4D, glewIsSupported("GL_SGIS_texture4D"), glewGetExtension("GL_SGIS_texture4D"));
+
+ glewInfoFunc("glTexImage4DSGIS", glTexImage4DSGIS == NULL);
+ glewInfoFunc("glTexSubImage4DSGIS", glTexSubImage4DSGIS == NULL);
+}
+
+#endif /* GL_SGIS_texture4D */
+
+#ifdef GL_SGIS_texture_border_clamp
+
+static void _glewInfo_GL_SGIS_texture_border_clamp (void)
+{
+ glewPrintExt("GL_SGIS_texture_border_clamp", GLEW_SGIS_texture_border_clamp, glewIsSupported("GL_SGIS_texture_border_clamp"), glewGetExtension("GL_SGIS_texture_border_clamp"));
+}
+
+#endif /* GL_SGIS_texture_border_clamp */
+
+#ifdef GL_SGIS_texture_edge_clamp
+
+static void _glewInfo_GL_SGIS_texture_edge_clamp (void)
+{
+ glewPrintExt("GL_SGIS_texture_edge_clamp", GLEW_SGIS_texture_edge_clamp, glewIsSupported("GL_SGIS_texture_edge_clamp"), glewGetExtension("GL_SGIS_texture_edge_clamp"));
+}
+
+#endif /* GL_SGIS_texture_edge_clamp */
+
+#ifdef GL_SGIS_texture_filter4
+
+static void _glewInfo_GL_SGIS_texture_filter4 (void)
+{
+ glewPrintExt("GL_SGIS_texture_filter4", GLEW_SGIS_texture_filter4, glewIsSupported("GL_SGIS_texture_filter4"), glewGetExtension("GL_SGIS_texture_filter4"));
+
+ glewInfoFunc("glGetTexFilterFuncSGIS", glGetTexFilterFuncSGIS == NULL);
+ glewInfoFunc("glTexFilterFuncSGIS", glTexFilterFuncSGIS == NULL);
+}
+
+#endif /* GL_SGIS_texture_filter4 */
+
+#ifdef GL_SGIS_texture_lod
+
+static void _glewInfo_GL_SGIS_texture_lod (void)
+{
+ glewPrintExt("GL_SGIS_texture_lod", GLEW_SGIS_texture_lod, glewIsSupported("GL_SGIS_texture_lod"), glewGetExtension("GL_SGIS_texture_lod"));
+}
+
+#endif /* GL_SGIS_texture_lod */
+
+#ifdef GL_SGIS_texture_select
+
+static void _glewInfo_GL_SGIS_texture_select (void)
+{
+ glewPrintExt("GL_SGIS_texture_select", GLEW_SGIS_texture_select, glewIsSupported("GL_SGIS_texture_select"), glewGetExtension("GL_SGIS_texture_select"));
+}
+
+#endif /* GL_SGIS_texture_select */
+
+#ifdef GL_SGIX_async
+
+static void _glewInfo_GL_SGIX_async (void)
+{
+ glewPrintExt("GL_SGIX_async", GLEW_SGIX_async, glewIsSupported("GL_SGIX_async"), glewGetExtension("GL_SGIX_async"));
+
+ glewInfoFunc("glAsyncMarkerSGIX", glAsyncMarkerSGIX == NULL);
+ glewInfoFunc("glDeleteAsyncMarkersSGIX", glDeleteAsyncMarkersSGIX == NULL);
+ glewInfoFunc("glFinishAsyncSGIX", glFinishAsyncSGIX == NULL);
+ glewInfoFunc("glGenAsyncMarkersSGIX", glGenAsyncMarkersSGIX == NULL);
+ glewInfoFunc("glIsAsyncMarkerSGIX", glIsAsyncMarkerSGIX == NULL);
+ glewInfoFunc("glPollAsyncSGIX", glPollAsyncSGIX == NULL);
+}
+
+#endif /* GL_SGIX_async */
+
+#ifdef GL_SGIX_async_histogram
+
+static void _glewInfo_GL_SGIX_async_histogram (void)
+{
+ glewPrintExt("GL_SGIX_async_histogram", GLEW_SGIX_async_histogram, glewIsSupported("GL_SGIX_async_histogram"), glewGetExtension("GL_SGIX_async_histogram"));
+}
+
+#endif /* GL_SGIX_async_histogram */
+
+#ifdef GL_SGIX_async_pixel
+
+static void _glewInfo_GL_SGIX_async_pixel (void)
+{
+ glewPrintExt("GL_SGIX_async_pixel", GLEW_SGIX_async_pixel, glewIsSupported("GL_SGIX_async_pixel"), glewGetExtension("GL_SGIX_async_pixel"));
+}
+
+#endif /* GL_SGIX_async_pixel */
+
+#ifdef GL_SGIX_blend_alpha_minmax
+
+static void _glewInfo_GL_SGIX_blend_alpha_minmax (void)
+{
+ glewPrintExt("GL_SGIX_blend_alpha_minmax", GLEW_SGIX_blend_alpha_minmax, glewIsSupported("GL_SGIX_blend_alpha_minmax"), glewGetExtension("GL_SGIX_blend_alpha_minmax"));
+}
+
+#endif /* GL_SGIX_blend_alpha_minmax */
+
+#ifdef GL_SGIX_clipmap
+
+static void _glewInfo_GL_SGIX_clipmap (void)
+{
+ glewPrintExt("GL_SGIX_clipmap", GLEW_SGIX_clipmap, glewIsSupported("GL_SGIX_clipmap"), glewGetExtension("GL_SGIX_clipmap"));
+}
+
+#endif /* GL_SGIX_clipmap */
+
+#ifdef GL_SGIX_convolution_accuracy
+
+static void _glewInfo_GL_SGIX_convolution_accuracy (void)
+{
+ glewPrintExt("GL_SGIX_convolution_accuracy", GLEW_SGIX_convolution_accuracy, glewIsSupported("GL_SGIX_convolution_accuracy"), glewGetExtension("GL_SGIX_convolution_accuracy"));
+}
+
+#endif /* GL_SGIX_convolution_accuracy */
+
+#ifdef GL_SGIX_depth_texture
+
+static void _glewInfo_GL_SGIX_depth_texture (void)
+{
+ glewPrintExt("GL_SGIX_depth_texture", GLEW_SGIX_depth_texture, glewIsSupported("GL_SGIX_depth_texture"), glewGetExtension("GL_SGIX_depth_texture"));
+}
+
+#endif /* GL_SGIX_depth_texture */
+
+#ifdef GL_SGIX_flush_raster
+
+static void _glewInfo_GL_SGIX_flush_raster (void)
+{
+ glewPrintExt("GL_SGIX_flush_raster", GLEW_SGIX_flush_raster, glewIsSupported("GL_SGIX_flush_raster"), glewGetExtension("GL_SGIX_flush_raster"));
+
+ glewInfoFunc("glFlushRasterSGIX", glFlushRasterSGIX == NULL);
+}
+
+#endif /* GL_SGIX_flush_raster */
+
+#ifdef GL_SGIX_fog_offset
+
+static void _glewInfo_GL_SGIX_fog_offset (void)
+{
+ glewPrintExt("GL_SGIX_fog_offset", GLEW_SGIX_fog_offset, glewIsSupported("GL_SGIX_fog_offset"), glewGetExtension("GL_SGIX_fog_offset"));
+}
+
+#endif /* GL_SGIX_fog_offset */
+
+#ifdef GL_SGIX_fog_texture
+
+static void _glewInfo_GL_SGIX_fog_texture (void)
+{
+ glewPrintExt("GL_SGIX_fog_texture", GLEW_SGIX_fog_texture, glewIsSupported("GL_SGIX_fog_texture"), glewGetExtension("GL_SGIX_fog_texture"));
+
+ glewInfoFunc("glTextureFogSGIX", glTextureFogSGIX == NULL);
+}
+
+#endif /* GL_SGIX_fog_texture */
+
+#ifdef GL_SGIX_fragment_specular_lighting
+
+static void _glewInfo_GL_SGIX_fragment_specular_lighting (void)
+{
+ glewPrintExt("GL_SGIX_fragment_specular_lighting", GLEW_SGIX_fragment_specular_lighting, glewIsSupported("GL_SGIX_fragment_specular_lighting"), glewGetExtension("GL_SGIX_fragment_specular_lighting"));
+
+ glewInfoFunc("glFragmentColorMaterialSGIX", glFragmentColorMaterialSGIX == NULL);
+ glewInfoFunc("glFragmentLightModelfSGIX", glFragmentLightModelfSGIX == NULL);
+ glewInfoFunc("glFragmentLightModelfvSGIX", glFragmentLightModelfvSGIX == NULL);
+ glewInfoFunc("glFragmentLightModeliSGIX", glFragmentLightModeliSGIX == NULL);
+ glewInfoFunc("glFragmentLightModelivSGIX", glFragmentLightModelivSGIX == NULL);
+ glewInfoFunc("glFragmentLightfSGIX", glFragmentLightfSGIX == NULL);
+ glewInfoFunc("glFragmentLightfvSGIX", glFragmentLightfvSGIX == NULL);
+ glewInfoFunc("glFragmentLightiSGIX", glFragmentLightiSGIX == NULL);
+ glewInfoFunc("glFragmentLightivSGIX", glFragmentLightivSGIX == NULL);
+ glewInfoFunc("glFragmentMaterialfSGIX", glFragmentMaterialfSGIX == NULL);
+ glewInfoFunc("glFragmentMaterialfvSGIX", glFragmentMaterialfvSGIX == NULL);
+ glewInfoFunc("glFragmentMaterialiSGIX", glFragmentMaterialiSGIX == NULL);
+ glewInfoFunc("glFragmentMaterialivSGIX", glFragmentMaterialivSGIX == NULL);
+ glewInfoFunc("glGetFragmentLightfvSGIX", glGetFragmentLightfvSGIX == NULL);
+ glewInfoFunc("glGetFragmentLightivSGIX", glGetFragmentLightivSGIX == NULL);
+ glewInfoFunc("glGetFragmentMaterialfvSGIX", glGetFragmentMaterialfvSGIX == NULL);
+ glewInfoFunc("glGetFragmentMaterialivSGIX", glGetFragmentMaterialivSGIX == NULL);
+}
+
+#endif /* GL_SGIX_fragment_specular_lighting */
+
+#ifdef GL_SGIX_framezoom
+
+static void _glewInfo_GL_SGIX_framezoom (void)
+{
+ glewPrintExt("GL_SGIX_framezoom", GLEW_SGIX_framezoom, glewIsSupported("GL_SGIX_framezoom"), glewGetExtension("GL_SGIX_framezoom"));
+
+ glewInfoFunc("glFrameZoomSGIX", glFrameZoomSGIX == NULL);
+}
+
+#endif /* GL_SGIX_framezoom */
+
+#ifdef GL_SGIX_interlace
+
+static void _glewInfo_GL_SGIX_interlace (void)
+{
+ glewPrintExt("GL_SGIX_interlace", GLEW_SGIX_interlace, glewIsSupported("GL_SGIX_interlace"), glewGetExtension("GL_SGIX_interlace"));
+}
+
+#endif /* GL_SGIX_interlace */
+
+#ifdef GL_SGIX_ir_instrument1
+
+static void _glewInfo_GL_SGIX_ir_instrument1 (void)
+{
+ glewPrintExt("GL_SGIX_ir_instrument1", GLEW_SGIX_ir_instrument1, glewIsSupported("GL_SGIX_ir_instrument1"), glewGetExtension("GL_SGIX_ir_instrument1"));
+}
+
+#endif /* GL_SGIX_ir_instrument1 */
+
+#ifdef GL_SGIX_list_priority
+
+static void _glewInfo_GL_SGIX_list_priority (void)
+{
+ glewPrintExt("GL_SGIX_list_priority", GLEW_SGIX_list_priority, glewIsSupported("GL_SGIX_list_priority"), glewGetExtension("GL_SGIX_list_priority"));
+}
+
+#endif /* GL_SGIX_list_priority */
+
+#ifdef GL_SGIX_pixel_texture
+
+static void _glewInfo_GL_SGIX_pixel_texture (void)
+{
+ glewPrintExt("GL_SGIX_pixel_texture", GLEW_SGIX_pixel_texture, glewIsSupported("GL_SGIX_pixel_texture"), glewGetExtension("GL_SGIX_pixel_texture"));
+
+ glewInfoFunc("glPixelTexGenSGIX", glPixelTexGenSGIX == NULL);
+}
+
+#endif /* GL_SGIX_pixel_texture */
+
+#ifdef GL_SGIX_pixel_texture_bits
+
+static void _glewInfo_GL_SGIX_pixel_texture_bits (void)
+{
+ glewPrintExt("GL_SGIX_pixel_texture_bits", GLEW_SGIX_pixel_texture_bits, glewIsSupported("GL_SGIX_pixel_texture_bits"), glewGetExtension("GL_SGIX_pixel_texture_bits"));
+}
+
+#endif /* GL_SGIX_pixel_texture_bits */
+
+#ifdef GL_SGIX_reference_plane
+
+static void _glewInfo_GL_SGIX_reference_plane (void)
+{
+ glewPrintExt("GL_SGIX_reference_plane", GLEW_SGIX_reference_plane, glewIsSupported("GL_SGIX_reference_plane"), glewGetExtension("GL_SGIX_reference_plane"));
+
+ glewInfoFunc("glReferencePlaneSGIX", glReferencePlaneSGIX == NULL);
+}
+
+#endif /* GL_SGIX_reference_plane */
+
+#ifdef GL_SGIX_resample
+
+static void _glewInfo_GL_SGIX_resample (void)
+{
+ glewPrintExt("GL_SGIX_resample", GLEW_SGIX_resample, glewIsSupported("GL_SGIX_resample"), glewGetExtension("GL_SGIX_resample"));
+}
+
+#endif /* GL_SGIX_resample */
+
+#ifdef GL_SGIX_shadow
+
+static void _glewInfo_GL_SGIX_shadow (void)
+{
+ glewPrintExt("GL_SGIX_shadow", GLEW_SGIX_shadow, glewIsSupported("GL_SGIX_shadow"), glewGetExtension("GL_SGIX_shadow"));
+}
+
+#endif /* GL_SGIX_shadow */
+
+#ifdef GL_SGIX_shadow_ambient
+
+static void _glewInfo_GL_SGIX_shadow_ambient (void)
+{
+ glewPrintExt("GL_SGIX_shadow_ambient", GLEW_SGIX_shadow_ambient, glewIsSupported("GL_SGIX_shadow_ambient"), glewGetExtension("GL_SGIX_shadow_ambient"));
+}
+
+#endif /* GL_SGIX_shadow_ambient */
+
+#ifdef GL_SGIX_sprite
+
+static void _glewInfo_GL_SGIX_sprite (void)
+{
+ glewPrintExt("GL_SGIX_sprite", GLEW_SGIX_sprite, glewIsSupported("GL_SGIX_sprite"), glewGetExtension("GL_SGIX_sprite"));
+
+ glewInfoFunc("glSpriteParameterfSGIX", glSpriteParameterfSGIX == NULL);
+ glewInfoFunc("glSpriteParameterfvSGIX", glSpriteParameterfvSGIX == NULL);
+ glewInfoFunc("glSpriteParameteriSGIX", glSpriteParameteriSGIX == NULL);
+ glewInfoFunc("glSpriteParameterivSGIX", glSpriteParameterivSGIX == NULL);
+}
+
+#endif /* GL_SGIX_sprite */
+
+#ifdef GL_SGIX_tag_sample_buffer
+
+static void _glewInfo_GL_SGIX_tag_sample_buffer (void)
+{
+ glewPrintExt("GL_SGIX_tag_sample_buffer", GLEW_SGIX_tag_sample_buffer, glewIsSupported("GL_SGIX_tag_sample_buffer"), glewGetExtension("GL_SGIX_tag_sample_buffer"));
+
+ glewInfoFunc("glTagSampleBufferSGIX", glTagSampleBufferSGIX == NULL);
+}
+
+#endif /* GL_SGIX_tag_sample_buffer */
+
+#ifdef GL_SGIX_texture_add_env
+
+static void _glewInfo_GL_SGIX_texture_add_env (void)
+{
+ glewPrintExt("GL_SGIX_texture_add_env", GLEW_SGIX_texture_add_env, glewIsSupported("GL_SGIX_texture_add_env"), glewGetExtension("GL_SGIX_texture_add_env"));
+}
+
+#endif /* GL_SGIX_texture_add_env */
+
+#ifdef GL_SGIX_texture_coordinate_clamp
+
+static void _glewInfo_GL_SGIX_texture_coordinate_clamp (void)
+{
+ glewPrintExt("GL_SGIX_texture_coordinate_clamp", GLEW_SGIX_texture_coordinate_clamp, glewIsSupported("GL_SGIX_texture_coordinate_clamp"), glewGetExtension("GL_SGIX_texture_coordinate_clamp"));
+}
+
+#endif /* GL_SGIX_texture_coordinate_clamp */
+
+#ifdef GL_SGIX_texture_lod_bias
+
+static void _glewInfo_GL_SGIX_texture_lod_bias (void)
+{
+ glewPrintExt("GL_SGIX_texture_lod_bias", GLEW_SGIX_texture_lod_bias, glewIsSupported("GL_SGIX_texture_lod_bias"), glewGetExtension("GL_SGIX_texture_lod_bias"));
+}
+
+#endif /* GL_SGIX_texture_lod_bias */
+
+#ifdef GL_SGIX_texture_multi_buffer
+
+static void _glewInfo_GL_SGIX_texture_multi_buffer (void)
+{
+ glewPrintExt("GL_SGIX_texture_multi_buffer", GLEW_SGIX_texture_multi_buffer, glewIsSupported("GL_SGIX_texture_multi_buffer"), glewGetExtension("GL_SGIX_texture_multi_buffer"));
+}
+
+#endif /* GL_SGIX_texture_multi_buffer */
+
+#ifdef GL_SGIX_texture_range
+
+static void _glewInfo_GL_SGIX_texture_range (void)
+{
+ glewPrintExt("GL_SGIX_texture_range", GLEW_SGIX_texture_range, glewIsSupported("GL_SGIX_texture_range"), glewGetExtension("GL_SGIX_texture_range"));
+}
+
+#endif /* GL_SGIX_texture_range */
+
+#ifdef GL_SGIX_texture_scale_bias
+
+static void _glewInfo_GL_SGIX_texture_scale_bias (void)
+{
+ glewPrintExt("GL_SGIX_texture_scale_bias", GLEW_SGIX_texture_scale_bias, glewIsSupported("GL_SGIX_texture_scale_bias"), glewGetExtension("GL_SGIX_texture_scale_bias"));
+}
+
+#endif /* GL_SGIX_texture_scale_bias */
+
+#ifdef GL_SGIX_vertex_preclip
+
+static void _glewInfo_GL_SGIX_vertex_preclip (void)
+{
+ glewPrintExt("GL_SGIX_vertex_preclip", GLEW_SGIX_vertex_preclip, glewIsSupported("GL_SGIX_vertex_preclip"), glewGetExtension("GL_SGIX_vertex_preclip"));
+}
+
+#endif /* GL_SGIX_vertex_preclip */
+
+#ifdef GL_SGIX_vertex_preclip_hint
+
+static void _glewInfo_GL_SGIX_vertex_preclip_hint (void)
+{
+ glewPrintExt("GL_SGIX_vertex_preclip_hint", GLEW_SGIX_vertex_preclip_hint, glewIsSupported("GL_SGIX_vertex_preclip_hint"), glewGetExtension("GL_SGIX_vertex_preclip_hint"));
+}
+
+#endif /* GL_SGIX_vertex_preclip_hint */
+
+#ifdef GL_SGIX_ycrcb
+
+static void _glewInfo_GL_SGIX_ycrcb (void)
+{
+ glewPrintExt("GL_SGIX_ycrcb", GLEW_SGIX_ycrcb, glewIsSupported("GL_SGIX_ycrcb"), glewGetExtension("GL_SGIX_ycrcb"));
+}
+
+#endif /* GL_SGIX_ycrcb */
+
+#ifdef GL_SGI_color_matrix
+
+static void _glewInfo_GL_SGI_color_matrix (void)
+{
+ glewPrintExt("GL_SGI_color_matrix", GLEW_SGI_color_matrix, glewIsSupported("GL_SGI_color_matrix"), glewGetExtension("GL_SGI_color_matrix"));
+}
+
+#endif /* GL_SGI_color_matrix */
+
+#ifdef GL_SGI_color_table
+
+static void _glewInfo_GL_SGI_color_table (void)
+{
+ glewPrintExt("GL_SGI_color_table", GLEW_SGI_color_table, glewIsSupported("GL_SGI_color_table"), glewGetExtension("GL_SGI_color_table"));
+
+ glewInfoFunc("glColorTableParameterfvSGI", glColorTableParameterfvSGI == NULL);
+ glewInfoFunc("glColorTableParameterivSGI", glColorTableParameterivSGI == NULL);
+ glewInfoFunc("glColorTableSGI", glColorTableSGI == NULL);
+ glewInfoFunc("glCopyColorTableSGI", glCopyColorTableSGI == NULL);
+ glewInfoFunc("glGetColorTableParameterfvSGI", glGetColorTableParameterfvSGI == NULL);
+ glewInfoFunc("glGetColorTableParameterivSGI", glGetColorTableParameterivSGI == NULL);
+ glewInfoFunc("glGetColorTableSGI", glGetColorTableSGI == NULL);
+}
+
+#endif /* GL_SGI_color_table */
+
+#ifdef GL_SGI_texture_color_table
+
+static void _glewInfo_GL_SGI_texture_color_table (void)
+{
+ glewPrintExt("GL_SGI_texture_color_table", GLEW_SGI_texture_color_table, glewIsSupported("GL_SGI_texture_color_table"), glewGetExtension("GL_SGI_texture_color_table"));
+}
+
+#endif /* GL_SGI_texture_color_table */
+
+#ifdef GL_SUNX_constant_data
+
+static void _glewInfo_GL_SUNX_constant_data (void)
+{
+ glewPrintExt("GL_SUNX_constant_data", GLEW_SUNX_constant_data, glewIsSupported("GL_SUNX_constant_data"), glewGetExtension("GL_SUNX_constant_data"));
+
+ glewInfoFunc("glFinishTextureSUNX", glFinishTextureSUNX == NULL);
+}
+
+#endif /* GL_SUNX_constant_data */
+
+#ifdef GL_SUN_convolution_border_modes
+
+static void _glewInfo_GL_SUN_convolution_border_modes (void)
+{
+ glewPrintExt("GL_SUN_convolution_border_modes", GLEW_SUN_convolution_border_modes, glewIsSupported("GL_SUN_convolution_border_modes"), glewGetExtension("GL_SUN_convolution_border_modes"));
+}
+
+#endif /* GL_SUN_convolution_border_modes */
+
+#ifdef GL_SUN_global_alpha
+
+static void _glewInfo_GL_SUN_global_alpha (void)
+{
+ glewPrintExt("GL_SUN_global_alpha", GLEW_SUN_global_alpha, glewIsSupported("GL_SUN_global_alpha"), glewGetExtension("GL_SUN_global_alpha"));
+
+ glewInfoFunc("glGlobalAlphaFactorbSUN", glGlobalAlphaFactorbSUN == NULL);
+ glewInfoFunc("glGlobalAlphaFactordSUN", glGlobalAlphaFactordSUN == NULL);
+ glewInfoFunc("glGlobalAlphaFactorfSUN", glGlobalAlphaFactorfSUN == NULL);
+ glewInfoFunc("glGlobalAlphaFactoriSUN", glGlobalAlphaFactoriSUN == NULL);
+ glewInfoFunc("glGlobalAlphaFactorsSUN", glGlobalAlphaFactorsSUN == NULL);
+ glewInfoFunc("glGlobalAlphaFactorubSUN", glGlobalAlphaFactorubSUN == NULL);
+ glewInfoFunc("glGlobalAlphaFactoruiSUN", glGlobalAlphaFactoruiSUN == NULL);
+ glewInfoFunc("glGlobalAlphaFactorusSUN", glGlobalAlphaFactorusSUN == NULL);
+}
+
+#endif /* GL_SUN_global_alpha */
+
+#ifdef GL_SUN_mesh_array
+
+static void _glewInfo_GL_SUN_mesh_array (void)
+{
+ glewPrintExt("GL_SUN_mesh_array", GLEW_SUN_mesh_array, glewIsSupported("GL_SUN_mesh_array"), glewGetExtension("GL_SUN_mesh_array"));
+}
+
+#endif /* GL_SUN_mesh_array */
+
+#ifdef GL_SUN_read_video_pixels
+
+static void _glewInfo_GL_SUN_read_video_pixels (void)
+{
+ glewPrintExt("GL_SUN_read_video_pixels", GLEW_SUN_read_video_pixels, glewIsSupported("GL_SUN_read_video_pixels"), glewGetExtension("GL_SUN_read_video_pixels"));
+
+ glewInfoFunc("glReadVideoPixelsSUN", glReadVideoPixelsSUN == NULL);
+}
+
+#endif /* GL_SUN_read_video_pixels */
+
+#ifdef GL_SUN_slice_accum
+
+static void _glewInfo_GL_SUN_slice_accum (void)
+{
+ glewPrintExt("GL_SUN_slice_accum", GLEW_SUN_slice_accum, glewIsSupported("GL_SUN_slice_accum"), glewGetExtension("GL_SUN_slice_accum"));
+}
+
+#endif /* GL_SUN_slice_accum */
+
+#ifdef GL_SUN_triangle_list
+
+static void _glewInfo_GL_SUN_triangle_list (void)
+{
+ glewPrintExt("GL_SUN_triangle_list", GLEW_SUN_triangle_list, glewIsSupported("GL_SUN_triangle_list"), glewGetExtension("GL_SUN_triangle_list"));
+
+ glewInfoFunc("glReplacementCodePointerSUN", glReplacementCodePointerSUN == NULL);
+ glewInfoFunc("glReplacementCodeubSUN", glReplacementCodeubSUN == NULL);
+ glewInfoFunc("glReplacementCodeubvSUN", glReplacementCodeubvSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiSUN", glReplacementCodeuiSUN == NULL);
+ glewInfoFunc("glReplacementCodeuivSUN", glReplacementCodeuivSUN == NULL);
+ glewInfoFunc("glReplacementCodeusSUN", glReplacementCodeusSUN == NULL);
+ glewInfoFunc("glReplacementCodeusvSUN", glReplacementCodeusvSUN == NULL);
+}
+
+#endif /* GL_SUN_triangle_list */
+
+#ifdef GL_SUN_vertex
+
+static void _glewInfo_GL_SUN_vertex (void)
+{
+ glewPrintExt("GL_SUN_vertex", GLEW_SUN_vertex, glewIsSupported("GL_SUN_vertex"), glewGetExtension("GL_SUN_vertex"));
+
+ glewInfoFunc("glColor3fVertex3fSUN", glColor3fVertex3fSUN == NULL);
+ glewInfoFunc("glColor3fVertex3fvSUN", glColor3fVertex3fvSUN == NULL);
+ glewInfoFunc("glColor4fNormal3fVertex3fSUN", glColor4fNormal3fVertex3fSUN == NULL);
+ glewInfoFunc("glColor4fNormal3fVertex3fvSUN", glColor4fNormal3fVertex3fvSUN == NULL);
+ glewInfoFunc("glColor4ubVertex2fSUN", glColor4ubVertex2fSUN == NULL);
+ glewInfoFunc("glColor4ubVertex2fvSUN", glColor4ubVertex2fvSUN == NULL);
+ glewInfoFunc("glColor4ubVertex3fSUN", glColor4ubVertex3fSUN == NULL);
+ glewInfoFunc("glColor4ubVertex3fvSUN", glColor4ubVertex3fvSUN == NULL);
+ glewInfoFunc("glNormal3fVertex3fSUN", glNormal3fVertex3fSUN == NULL);
+ glewInfoFunc("glNormal3fVertex3fvSUN", glNormal3fVertex3fvSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiColor3fVertex3fSUN", glReplacementCodeuiColor3fVertex3fSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiColor3fVertex3fvSUN", glReplacementCodeuiColor3fVertex3fvSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiColor4fNormal3fVertex3fSUN", glReplacementCodeuiColor4fNormal3fVertex3fSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiColor4fNormal3fVertex3fvSUN", glReplacementCodeuiColor4fNormal3fVertex3fvSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiColor4ubVertex3fSUN", glReplacementCodeuiColor4ubVertex3fSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiColor4ubVertex3fvSUN", glReplacementCodeuiColor4ubVertex3fvSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiNormal3fVertex3fSUN", glReplacementCodeuiNormal3fVertex3fSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiNormal3fVertex3fvSUN", glReplacementCodeuiNormal3fVertex3fvSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN", glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN", glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN", glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN", glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiTexCoord2fVertex3fSUN", glReplacementCodeuiTexCoord2fVertex3fSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiTexCoord2fVertex3fvSUN", glReplacementCodeuiTexCoord2fVertex3fvSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiVertex3fSUN", glReplacementCodeuiVertex3fSUN == NULL);
+ glewInfoFunc("glReplacementCodeuiVertex3fvSUN", glReplacementCodeuiVertex3fvSUN == NULL);
+ glewInfoFunc("glTexCoord2fColor3fVertex3fSUN", glTexCoord2fColor3fVertex3fSUN == NULL);
+ glewInfoFunc("glTexCoord2fColor3fVertex3fvSUN", glTexCoord2fColor3fVertex3fvSUN == NULL);
+ glewInfoFunc("glTexCoord2fColor4fNormal3fVertex3fSUN", glTexCoord2fColor4fNormal3fVertex3fSUN == NULL);
+ glewInfoFunc("glTexCoord2fColor4fNormal3fVertex3fvSUN", glTexCoord2fColor4fNormal3fVertex3fvSUN == NULL);
+ glewInfoFunc("glTexCoord2fColor4ubVertex3fSUN", glTexCoord2fColor4ubVertex3fSUN == NULL);
+ glewInfoFunc("glTexCoord2fColor4ubVertex3fvSUN", glTexCoord2fColor4ubVertex3fvSUN == NULL);
+ glewInfoFunc("glTexCoord2fNormal3fVertex3fSUN", glTexCoord2fNormal3fVertex3fSUN == NULL);
+ glewInfoFunc("glTexCoord2fNormal3fVertex3fvSUN", glTexCoord2fNormal3fVertex3fvSUN == NULL);
+ glewInfoFunc("glTexCoord2fVertex3fSUN", glTexCoord2fVertex3fSUN == NULL);
+ glewInfoFunc("glTexCoord2fVertex3fvSUN", glTexCoord2fVertex3fvSUN == NULL);
+ glewInfoFunc("glTexCoord4fColor4fNormal3fVertex4fSUN", glTexCoord4fColor4fNormal3fVertex4fSUN == NULL);
+ glewInfoFunc("glTexCoord4fColor4fNormal3fVertex4fvSUN", glTexCoord4fColor4fNormal3fVertex4fvSUN == NULL);
+ glewInfoFunc("glTexCoord4fVertex4fSUN", glTexCoord4fVertex4fSUN == NULL);
+ glewInfoFunc("glTexCoord4fVertex4fvSUN", glTexCoord4fVertex4fvSUN == NULL);
+}
+
+#endif /* GL_SUN_vertex */
+
+#ifdef GL_WIN_phong_shading
+
+static void _glewInfo_GL_WIN_phong_shading (void)
+{
+ glewPrintExt("GL_WIN_phong_shading", GLEW_WIN_phong_shading, glewIsSupported("GL_WIN_phong_shading"), glewGetExtension("GL_WIN_phong_shading"));
+}
+
+#endif /* GL_WIN_phong_shading */
+
+#ifdef GL_WIN_specular_fog
+
+static void _glewInfo_GL_WIN_specular_fog (void)
+{
+ glewPrintExt("GL_WIN_specular_fog", GLEW_WIN_specular_fog, glewIsSupported("GL_WIN_specular_fog"), glewGetExtension("GL_WIN_specular_fog"));
+}
+
+#endif /* GL_WIN_specular_fog */
+
+#ifdef GL_WIN_swap_hint
+
+static void _glewInfo_GL_WIN_swap_hint (void)
+{
+ glewPrintExt("GL_WIN_swap_hint", GLEW_WIN_swap_hint, glewIsSupported("GL_WIN_swap_hint"), glewGetExtension("GL_WIN_swap_hint"));
+
+ glewInfoFunc("glAddSwapHintRectWIN", glAddSwapHintRectWIN == NULL);
+}
+
+#endif /* GL_WIN_swap_hint */
+
+#ifdef _WIN32
+
+#ifdef WGL_3DFX_multisample
+
+static void _glewInfo_WGL_3DFX_multisample (void)
+{
+ glewPrintExt("WGL_3DFX_multisample", WGLEW_3DFX_multisample, wglewIsSupported("WGL_3DFX_multisample"), wglewGetExtension("WGL_3DFX_multisample"));
+}
+
+#endif /* WGL_3DFX_multisample */
+
+#ifdef WGL_3DL_stereo_control
+
+static void _glewInfo_WGL_3DL_stereo_control (void)
+{
+ glewPrintExt("WGL_3DL_stereo_control", WGLEW_3DL_stereo_control, wglewIsSupported("WGL_3DL_stereo_control"), wglewGetExtension("WGL_3DL_stereo_control"));
+
+ glewInfoFunc("wglSetStereoEmitterState3DL", wglSetStereoEmitterState3DL == NULL);
+}
+
+#endif /* WGL_3DL_stereo_control */
+
+#ifdef WGL_ARB_buffer_region
+
+static void _glewInfo_WGL_ARB_buffer_region (void)
+{
+ glewPrintExt("WGL_ARB_buffer_region", WGLEW_ARB_buffer_region, wglewIsSupported("WGL_ARB_buffer_region"), wglewGetExtension("WGL_ARB_buffer_region"));
+
+ glewInfoFunc("wglCreateBufferRegionARB", wglCreateBufferRegionARB == NULL);
+ glewInfoFunc("wglDeleteBufferRegionARB", wglDeleteBufferRegionARB == NULL);
+ glewInfoFunc("wglRestoreBufferRegionARB", wglRestoreBufferRegionARB == NULL);
+ glewInfoFunc("wglSaveBufferRegionARB", wglSaveBufferRegionARB == NULL);
+}
+
+#endif /* WGL_ARB_buffer_region */
+
+#ifdef WGL_ARB_create_context
+
+static void _glewInfo_WGL_ARB_create_context (void)
+{
+ glewPrintExt("WGL_ARB_create_context", WGLEW_ARB_create_context, wglewIsSupported("WGL_ARB_create_context"), wglewGetExtension("WGL_ARB_create_context"));
+
+ glewInfoFunc("wglCreateContextAttribsARB", wglCreateContextAttribsARB == NULL);
+}
+
+#endif /* WGL_ARB_create_context */
+
+#ifdef WGL_ARB_extensions_string
+
+static void _glewInfo_WGL_ARB_extensions_string (void)
+{
+ glewPrintExt("WGL_ARB_extensions_string", WGLEW_ARB_extensions_string, wglewIsSupported("WGL_ARB_extensions_string"), wglewGetExtension("WGL_ARB_extensions_string"));
+
+ glewInfoFunc("wglGetExtensionsStringARB", wglGetExtensionsStringARB == NULL);
+}
+
+#endif /* WGL_ARB_extensions_string */
+
+#ifdef WGL_ARB_framebuffer_sRGB
+
+static void _glewInfo_WGL_ARB_framebuffer_sRGB (void)
+{
+ glewPrintExt("WGL_ARB_framebuffer_sRGB", WGLEW_ARB_framebuffer_sRGB, wglewIsSupported("WGL_ARB_framebuffer_sRGB"), wglewGetExtension("WGL_ARB_framebuffer_sRGB"));
+}
+
+#endif /* WGL_ARB_framebuffer_sRGB */
+
+#ifdef WGL_ARB_make_current_read
+
+static void _glewInfo_WGL_ARB_make_current_read (void)
+{
+ glewPrintExt("WGL_ARB_make_current_read", WGLEW_ARB_make_current_read, wglewIsSupported("WGL_ARB_make_current_read"), wglewGetExtension("WGL_ARB_make_current_read"));
+
+ glewInfoFunc("wglGetCurrentReadDCARB", wglGetCurrentReadDCARB == NULL);
+ glewInfoFunc("wglMakeContextCurrentARB", wglMakeContextCurrentARB == NULL);
+}
+
+#endif /* WGL_ARB_make_current_read */
+
+#ifdef WGL_ARB_multisample
+
+static void _glewInfo_WGL_ARB_multisample (void)
+{
+ glewPrintExt("WGL_ARB_multisample", WGLEW_ARB_multisample, wglewIsSupported("WGL_ARB_multisample"), wglewGetExtension("WGL_ARB_multisample"));
+}
+
+#endif /* WGL_ARB_multisample */
+
+#ifdef WGL_ARB_pbuffer
+
+static void _glewInfo_WGL_ARB_pbuffer (void)
+{
+ glewPrintExt("WGL_ARB_pbuffer", WGLEW_ARB_pbuffer, wglewIsSupported("WGL_ARB_pbuffer"), wglewGetExtension("WGL_ARB_pbuffer"));
+
+ glewInfoFunc("wglCreatePbufferARB", wglCreatePbufferARB == NULL);
+ glewInfoFunc("wglDestroyPbufferARB", wglDestroyPbufferARB == NULL);
+ glewInfoFunc("wglGetPbufferDCARB", wglGetPbufferDCARB == NULL);
+ glewInfoFunc("wglQueryPbufferARB", wglQueryPbufferARB == NULL);
+ glewInfoFunc("wglReleasePbufferDCARB", wglReleasePbufferDCARB == NULL);
+}
+
+#endif /* WGL_ARB_pbuffer */
+
+#ifdef WGL_ARB_pixel_format
+
+static void _glewInfo_WGL_ARB_pixel_format (void)
+{
+ glewPrintExt("WGL_ARB_pixel_format", WGLEW_ARB_pixel_format, wglewIsSupported("WGL_ARB_pixel_format"), wglewGetExtension("WGL_ARB_pixel_format"));
+
+ glewInfoFunc("wglChoosePixelFormatARB", wglChoosePixelFormatARB == NULL);
+ glewInfoFunc("wglGetPixelFormatAttribfvARB", wglGetPixelFormatAttribfvARB == NULL);
+ glewInfoFunc("wglGetPixelFormatAttribivARB", wglGetPixelFormatAttribivARB == NULL);
+}
+
+#endif /* WGL_ARB_pixel_format */
+
+#ifdef WGL_ARB_pixel_format_float
+
+static void _glewInfo_WGL_ARB_pixel_format_float (void)
+{
+ glewPrintExt("WGL_ARB_pixel_format_float", WGLEW_ARB_pixel_format_float, wglewIsSupported("WGL_ARB_pixel_format_float"), wglewGetExtension("WGL_ARB_pixel_format_float"));
+}
+
+#endif /* WGL_ARB_pixel_format_float */
+
+#ifdef WGL_ARB_render_texture
+
+static void _glewInfo_WGL_ARB_render_texture (void)
+{
+ glewPrintExt("WGL_ARB_render_texture", WGLEW_ARB_render_texture, wglewIsSupported("WGL_ARB_render_texture"), wglewGetExtension("WGL_ARB_render_texture"));
+
+ glewInfoFunc("wglBindTexImageARB", wglBindTexImageARB == NULL);
+ glewInfoFunc("wglReleaseTexImageARB", wglReleaseTexImageARB == NULL);
+ glewInfoFunc("wglSetPbufferAttribARB", wglSetPbufferAttribARB == NULL);
+}
+
+#endif /* WGL_ARB_render_texture */
+
+#ifdef WGL_ATI_pixel_format_float
+
+static void _glewInfo_WGL_ATI_pixel_format_float (void)
+{
+ glewPrintExt("WGL_ATI_pixel_format_float", WGLEW_ATI_pixel_format_float, wglewIsSupported("WGL_ATI_pixel_format_float"), wglewGetExtension("WGL_ATI_pixel_format_float"));
+}
+
+#endif /* WGL_ATI_pixel_format_float */
+
+#ifdef WGL_ATI_render_texture_rectangle
+
+static void _glewInfo_WGL_ATI_render_texture_rectangle (void)
+{
+ glewPrintExt("WGL_ATI_render_texture_rectangle", WGLEW_ATI_render_texture_rectangle, wglewIsSupported("WGL_ATI_render_texture_rectangle"), wglewGetExtension("WGL_ATI_render_texture_rectangle"));
+}
+
+#endif /* WGL_ATI_render_texture_rectangle */
+
+#ifdef WGL_EXT_depth_float
+
+static void _glewInfo_WGL_EXT_depth_float (void)
+{
+ glewPrintExt("WGL_EXT_depth_float", WGLEW_EXT_depth_float, wglewIsSupported("WGL_EXT_depth_float"), wglewGetExtension("WGL_EXT_depth_float"));
+}
+
+#endif /* WGL_EXT_depth_float */
+
+#ifdef WGL_EXT_display_color_table
+
+static void _glewInfo_WGL_EXT_display_color_table (void)
+{
+ glewPrintExt("WGL_EXT_display_color_table", WGLEW_EXT_display_color_table, wglewIsSupported("WGL_EXT_display_color_table"), wglewGetExtension("WGL_EXT_display_color_table"));
+
+ glewInfoFunc("wglBindDisplayColorTableEXT", wglBindDisplayColorTableEXT == NULL);
+ glewInfoFunc("wglCreateDisplayColorTableEXT", wglCreateDisplayColorTableEXT == NULL);
+ glewInfoFunc("wglDestroyDisplayColorTableEXT", wglDestroyDisplayColorTableEXT == NULL);
+ glewInfoFunc("wglLoadDisplayColorTableEXT", wglLoadDisplayColorTableEXT == NULL);
+}
+
+#endif /* WGL_EXT_display_color_table */
+
+#ifdef WGL_EXT_extensions_string
+
+static void _glewInfo_WGL_EXT_extensions_string (void)
+{
+ glewPrintExt("WGL_EXT_extensions_string", WGLEW_EXT_extensions_string, wglewIsSupported("WGL_EXT_extensions_string"), wglewGetExtension("WGL_EXT_extensions_string"));
+
+ glewInfoFunc("wglGetExtensionsStringEXT", wglGetExtensionsStringEXT == NULL);
+}
+
+#endif /* WGL_EXT_extensions_string */
+
+#ifdef WGL_EXT_framebuffer_sRGB
+
+static void _glewInfo_WGL_EXT_framebuffer_sRGB (void)
+{
+ glewPrintExt("WGL_EXT_framebuffer_sRGB", WGLEW_EXT_framebuffer_sRGB, wglewIsSupported("WGL_EXT_framebuffer_sRGB"), wglewGetExtension("WGL_EXT_framebuffer_sRGB"));
+}
+
+#endif /* WGL_EXT_framebuffer_sRGB */
+
+#ifdef WGL_EXT_make_current_read
+
+static void _glewInfo_WGL_EXT_make_current_read (void)
+{
+ glewPrintExt("WGL_EXT_make_current_read", WGLEW_EXT_make_current_read, wglewIsSupported("WGL_EXT_make_current_read"), wglewGetExtension("WGL_EXT_make_current_read"));
+
+ glewInfoFunc("wglGetCurrentReadDCEXT", wglGetCurrentReadDCEXT == NULL);
+ glewInfoFunc("wglMakeContextCurrentEXT", wglMakeContextCurrentEXT == NULL);
+}
+
+#endif /* WGL_EXT_make_current_read */
+
+#ifdef WGL_EXT_multisample
+
+static void _glewInfo_WGL_EXT_multisample (void)
+{
+ glewPrintExt("WGL_EXT_multisample", WGLEW_EXT_multisample, wglewIsSupported("WGL_EXT_multisample"), wglewGetExtension("WGL_EXT_multisample"));
+}
+
+#endif /* WGL_EXT_multisample */
+
+#ifdef WGL_EXT_pbuffer
+
+static void _glewInfo_WGL_EXT_pbuffer (void)
+{
+ glewPrintExt("WGL_EXT_pbuffer", WGLEW_EXT_pbuffer, wglewIsSupported("WGL_EXT_pbuffer"), wglewGetExtension("WGL_EXT_pbuffer"));
+
+ glewInfoFunc("wglCreatePbufferEXT", wglCreatePbufferEXT == NULL);
+ glewInfoFunc("wglDestroyPbufferEXT", wglDestroyPbufferEXT == NULL);
+ glewInfoFunc("wglGetPbufferDCEXT", wglGetPbufferDCEXT == NULL);
+ glewInfoFunc("wglQueryPbufferEXT", wglQueryPbufferEXT == NULL);
+ glewInfoFunc("wglReleasePbufferDCEXT", wglReleasePbufferDCEXT == NULL);
+}
+
+#endif /* WGL_EXT_pbuffer */
+
+#ifdef WGL_EXT_pixel_format
+
+static void _glewInfo_WGL_EXT_pixel_format (void)
+{
+ glewPrintExt("WGL_EXT_pixel_format", WGLEW_EXT_pixel_format, wglewIsSupported("WGL_EXT_pixel_format"), wglewGetExtension("WGL_EXT_pixel_format"));
+
+ glewInfoFunc("wglChoosePixelFormatEXT", wglChoosePixelFormatEXT == NULL);
+ glewInfoFunc("wglGetPixelFormatAttribfvEXT", wglGetPixelFormatAttribfvEXT == NULL);
+ glewInfoFunc("wglGetPixelFormatAttribivEXT", wglGetPixelFormatAttribivEXT == NULL);
+}
+
+#endif /* WGL_EXT_pixel_format */
+
+#ifdef WGL_EXT_pixel_format_packed_float
+
+static void _glewInfo_WGL_EXT_pixel_format_packed_float (void)
+{
+ glewPrintExt("WGL_EXT_pixel_format_packed_float", WGLEW_EXT_pixel_format_packed_float, wglewIsSupported("WGL_EXT_pixel_format_packed_float"), wglewGetExtension("WGL_EXT_pixel_format_packed_float"));
+}
+
+#endif /* WGL_EXT_pixel_format_packed_float */
+
+#ifdef WGL_EXT_swap_control
+
+static void _glewInfo_WGL_EXT_swap_control (void)
+{
+ glewPrintExt("WGL_EXT_swap_control", WGLEW_EXT_swap_control, wglewIsSupported("WGL_EXT_swap_control"), wglewGetExtension("WGL_EXT_swap_control"));
+
+ glewInfoFunc("wglGetSwapIntervalEXT", wglGetSwapIntervalEXT == NULL);
+ glewInfoFunc("wglSwapIntervalEXT", wglSwapIntervalEXT == NULL);
+}
+
+#endif /* WGL_EXT_swap_control */
+
+#ifdef WGL_I3D_digital_video_control
+
+static void _glewInfo_WGL_I3D_digital_video_control (void)
+{
+ glewPrintExt("WGL_I3D_digital_video_control", WGLEW_I3D_digital_video_control, wglewIsSupported("WGL_I3D_digital_video_control"), wglewGetExtension("WGL_I3D_digital_video_control"));
+
+ glewInfoFunc("wglGetDigitalVideoParametersI3D", wglGetDigitalVideoParametersI3D == NULL);
+ glewInfoFunc("wglSetDigitalVideoParametersI3D", wglSetDigitalVideoParametersI3D == NULL);
+}
+
+#endif /* WGL_I3D_digital_video_control */
+
+#ifdef WGL_I3D_gamma
+
+static void _glewInfo_WGL_I3D_gamma (void)
+{
+ glewPrintExt("WGL_I3D_gamma", WGLEW_I3D_gamma, wglewIsSupported("WGL_I3D_gamma"), wglewGetExtension("WGL_I3D_gamma"));
+
+ glewInfoFunc("wglGetGammaTableI3D", wglGetGammaTableI3D == NULL);
+ glewInfoFunc("wglGetGammaTableParametersI3D", wglGetGammaTableParametersI3D == NULL);
+ glewInfoFunc("wglSetGammaTableI3D", wglSetGammaTableI3D == NULL);
+ glewInfoFunc("wglSetGammaTableParametersI3D", wglSetGammaTableParametersI3D == NULL);
+}
+
+#endif /* WGL_I3D_gamma */
+
+#ifdef WGL_I3D_genlock
+
+static void _glewInfo_WGL_I3D_genlock (void)
+{
+ glewPrintExt("WGL_I3D_genlock", WGLEW_I3D_genlock, wglewIsSupported("WGL_I3D_genlock"), wglewGetExtension("WGL_I3D_genlock"));
+
+ glewInfoFunc("wglDisableGenlockI3D", wglDisableGenlockI3D == NULL);
+ glewInfoFunc("wglEnableGenlockI3D", wglEnableGenlockI3D == NULL);
+ glewInfoFunc("wglGenlockSampleRateI3D", wglGenlockSampleRateI3D == NULL);
+ glewInfoFunc("wglGenlockSourceDelayI3D", wglGenlockSourceDelayI3D == NULL);
+ glewInfoFunc("wglGenlockSourceEdgeI3D", wglGenlockSourceEdgeI3D == NULL);
+ glewInfoFunc("wglGenlockSourceI3D", wglGenlockSourceI3D == NULL);
+ glewInfoFunc("wglGetGenlockSampleRateI3D", wglGetGenlockSampleRateI3D == NULL);
+ glewInfoFunc("wglGetGenlockSourceDelayI3D", wglGetGenlockSourceDelayI3D == NULL);
+ glewInfoFunc("wglGetGenlockSourceEdgeI3D", wglGetGenlockSourceEdgeI3D == NULL);
+ glewInfoFunc("wglGetGenlockSourceI3D", wglGetGenlockSourceI3D == NULL);
+ glewInfoFunc("wglIsEnabledGenlockI3D", wglIsEnabledGenlockI3D == NULL);
+ glewInfoFunc("wglQueryGenlockMaxSourceDelayI3D", wglQueryGenlockMaxSourceDelayI3D == NULL);
+}
+
+#endif /* WGL_I3D_genlock */
+
+#ifdef WGL_I3D_image_buffer
+
+static void _glewInfo_WGL_I3D_image_buffer (void)
+{
+ glewPrintExt("WGL_I3D_image_buffer", WGLEW_I3D_image_buffer, wglewIsSupported("WGL_I3D_image_buffer"), wglewGetExtension("WGL_I3D_image_buffer"));
+
+ glewInfoFunc("wglAssociateImageBufferEventsI3D", wglAssociateImageBufferEventsI3D == NULL);
+ glewInfoFunc("wglCreateImageBufferI3D", wglCreateImageBufferI3D == NULL);
+ glewInfoFunc("wglDestroyImageBufferI3D", wglDestroyImageBufferI3D == NULL);
+ glewInfoFunc("wglReleaseImageBufferEventsI3D", wglReleaseImageBufferEventsI3D == NULL);
+}
+
+#endif /* WGL_I3D_image_buffer */
+
+#ifdef WGL_I3D_swap_frame_lock
+
+static void _glewInfo_WGL_I3D_swap_frame_lock (void)
+{
+ glewPrintExt("WGL_I3D_swap_frame_lock", WGLEW_I3D_swap_frame_lock, wglewIsSupported("WGL_I3D_swap_frame_lock"), wglewGetExtension("WGL_I3D_swap_frame_lock"));
+
+ glewInfoFunc("wglDisableFrameLockI3D", wglDisableFrameLockI3D == NULL);
+ glewInfoFunc("wglEnableFrameLockI3D", wglEnableFrameLockI3D == NULL);
+ glewInfoFunc("wglIsEnabledFrameLockI3D", wglIsEnabledFrameLockI3D == NULL);
+ glewInfoFunc("wglQueryFrameLockMasterI3D", wglQueryFrameLockMasterI3D == NULL);
+}
+
+#endif /* WGL_I3D_swap_frame_lock */
+
+#ifdef WGL_I3D_swap_frame_usage
+
+static void _glewInfo_WGL_I3D_swap_frame_usage (void)
+{
+ glewPrintExt("WGL_I3D_swap_frame_usage", WGLEW_I3D_swap_frame_usage, wglewIsSupported("WGL_I3D_swap_frame_usage"), wglewGetExtension("WGL_I3D_swap_frame_usage"));
+
+ glewInfoFunc("wglBeginFrameTrackingI3D", wglBeginFrameTrackingI3D == NULL);
+ glewInfoFunc("wglEndFrameTrackingI3D", wglEndFrameTrackingI3D == NULL);
+ glewInfoFunc("wglGetFrameUsageI3D", wglGetFrameUsageI3D == NULL);
+ glewInfoFunc("wglQueryFrameTrackingI3D", wglQueryFrameTrackingI3D == NULL);
+}
+
+#endif /* WGL_I3D_swap_frame_usage */
+
+#ifdef WGL_NV_float_buffer
+
+static void _glewInfo_WGL_NV_float_buffer (void)
+{
+ glewPrintExt("WGL_NV_float_buffer", WGLEW_NV_float_buffer, wglewIsSupported("WGL_NV_float_buffer"), wglewGetExtension("WGL_NV_float_buffer"));
+}
+
+#endif /* WGL_NV_float_buffer */
+
+#ifdef WGL_NV_gpu_affinity
+
+static void _glewInfo_WGL_NV_gpu_affinity (void)
+{
+ glewPrintExt("WGL_NV_gpu_affinity", WGLEW_NV_gpu_affinity, wglewIsSupported("WGL_NV_gpu_affinity"), wglewGetExtension("WGL_NV_gpu_affinity"));
+
+ glewInfoFunc("wglCreateAffinityDCNV", wglCreateAffinityDCNV == NULL);
+ glewInfoFunc("wglDeleteDCNV", wglDeleteDCNV == NULL);
+ glewInfoFunc("wglEnumGpuDevicesNV", wglEnumGpuDevicesNV == NULL);
+ glewInfoFunc("wglEnumGpusFromAffinityDCNV", wglEnumGpusFromAffinityDCNV == NULL);
+ glewInfoFunc("wglEnumGpusNV", wglEnumGpusNV == NULL);
+}
+
+#endif /* WGL_NV_gpu_affinity */
+
+#ifdef WGL_NV_present_video
+
+static void _glewInfo_WGL_NV_present_video (void)
+{
+ glewPrintExt("WGL_NV_present_video", WGLEW_NV_present_video, wglewIsSupported("WGL_NV_present_video"), wglewGetExtension("WGL_NV_present_video"));
+
+ glewInfoFunc("wglBindVideoDeviceNV", wglBindVideoDeviceNV == NULL);
+ glewInfoFunc("wglEnumerateVideoDevicesNV", wglEnumerateVideoDevicesNV == NULL);
+ glewInfoFunc("wglQueryCurrentContextNV", wglQueryCurrentContextNV == NULL);
+}
+
+#endif /* WGL_NV_present_video */
+
+#ifdef WGL_NV_render_depth_texture
+
+static void _glewInfo_WGL_NV_render_depth_texture (void)
+{
+ glewPrintExt("WGL_NV_render_depth_texture", WGLEW_NV_render_depth_texture, wglewIsSupported("WGL_NV_render_depth_texture"), wglewGetExtension("WGL_NV_render_depth_texture"));
+}
+
+#endif /* WGL_NV_render_depth_texture */
+
+#ifdef WGL_NV_render_texture_rectangle
+
+static void _glewInfo_WGL_NV_render_texture_rectangle (void)
+{
+ glewPrintExt("WGL_NV_render_texture_rectangle", WGLEW_NV_render_texture_rectangle, wglewIsSupported("WGL_NV_render_texture_rectangle"), wglewGetExtension("WGL_NV_render_texture_rectangle"));
+}
+
+#endif /* WGL_NV_render_texture_rectangle */
+
+#ifdef WGL_NV_swap_group
+
+static void _glewInfo_WGL_NV_swap_group (void)
+{
+ glewPrintExt("WGL_NV_swap_group", WGLEW_NV_swap_group, wglewIsSupported("WGL_NV_swap_group"), wglewGetExtension("WGL_NV_swap_group"));
+
+ glewInfoFunc("wglBindSwapBarrierNV", wglBindSwapBarrierNV == NULL);
+ glewInfoFunc("wglJoinSwapGroupNV", wglJoinSwapGroupNV == NULL);
+ glewInfoFunc("wglQueryFrameCountNV", wglQueryFrameCountNV == NULL);
+ glewInfoFunc("wglQueryMaxSwapGroupsNV", wglQueryMaxSwapGroupsNV == NULL);
+ glewInfoFunc("wglQuerySwapGroupNV", wglQuerySwapGroupNV == NULL);
+ glewInfoFunc("wglResetFrameCountNV", wglResetFrameCountNV == NULL);
+}
+
+#endif /* WGL_NV_swap_group */
+
+#ifdef WGL_NV_vertex_array_range
+
+static void _glewInfo_WGL_NV_vertex_array_range (void)
+{
+ glewPrintExt("WGL_NV_vertex_array_range", WGLEW_NV_vertex_array_range, wglewIsSupported("WGL_NV_vertex_array_range"), wglewGetExtension("WGL_NV_vertex_array_range"));
+
+ glewInfoFunc("wglAllocateMemoryNV", wglAllocateMemoryNV == NULL);
+ glewInfoFunc("wglFreeMemoryNV", wglFreeMemoryNV == NULL);
+}
+
+#endif /* WGL_NV_vertex_array_range */
+
+#ifdef WGL_NV_video_output
+
+static void _glewInfo_WGL_NV_video_output (void)
+{
+ glewPrintExt("WGL_NV_video_output", WGLEW_NV_video_output, wglewIsSupported("WGL_NV_video_output"), wglewGetExtension("WGL_NV_video_output"));
+
+ glewInfoFunc("wglBindVideoImageNV", wglBindVideoImageNV == NULL);
+ glewInfoFunc("wglGetVideoDeviceNV", wglGetVideoDeviceNV == NULL);
+ glewInfoFunc("wglGetVideoInfoNV", wglGetVideoInfoNV == NULL);
+ glewInfoFunc("wglReleaseVideoDeviceNV", wglReleaseVideoDeviceNV == NULL);
+ glewInfoFunc("wglReleaseVideoImageNV", wglReleaseVideoImageNV == NULL);
+ glewInfoFunc("wglSendPbufferToVideoNV", wglSendPbufferToVideoNV == NULL);
+}
+
+#endif /* WGL_NV_video_output */
+
+#ifdef WGL_OML_sync_control
+
+static void _glewInfo_WGL_OML_sync_control (void)
+{
+ glewPrintExt("WGL_OML_sync_control", WGLEW_OML_sync_control, wglewIsSupported("WGL_OML_sync_control"), wglewGetExtension("WGL_OML_sync_control"));
+
+ glewInfoFunc("wglGetMscRateOML", wglGetMscRateOML == NULL);
+ glewInfoFunc("wglGetSyncValuesOML", wglGetSyncValuesOML == NULL);
+ glewInfoFunc("wglSwapBuffersMscOML", wglSwapBuffersMscOML == NULL);
+ glewInfoFunc("wglSwapLayerBuffersMscOML", wglSwapLayerBuffersMscOML == NULL);
+ glewInfoFunc("wglWaitForMscOML", wglWaitForMscOML == NULL);
+ glewInfoFunc("wglWaitForSbcOML", wglWaitForSbcOML == NULL);
+}
+
+#endif /* WGL_OML_sync_control */
+
+#else /* _UNIX */
+
+#ifdef GLX_VERSION_1_2
+
+static void _glewInfo_GLX_VERSION_1_2 (void)
+{
+ glewPrintExt("GLX_VERSION_1_2", GLXEW_VERSION_1_2, GLXEW_VERSION_1_2, GLXEW_VERSION_1_2);
+
+ glewInfoFunc("glXGetCurrentDisplay", glXGetCurrentDisplay == NULL);
+}
+
+#endif /* GLX_VERSION_1_2 */
+
+#ifdef GLX_VERSION_1_3
+
+static void _glewInfo_GLX_VERSION_1_3 (void)
+{
+ glewPrintExt("GLX_VERSION_1_3", GLXEW_VERSION_1_3, GLXEW_VERSION_1_3, GLXEW_VERSION_1_3);
+
+ glewInfoFunc("glXChooseFBConfig", glXChooseFBConfig == NULL);
+ glewInfoFunc("glXCreateNewContext", glXCreateNewContext == NULL);
+ glewInfoFunc("glXCreatePbuffer", glXCreatePbuffer == NULL);
+ glewInfoFunc("glXCreatePixmap", glXCreatePixmap == NULL);
+ glewInfoFunc("glXCreateWindow", glXCreateWindow == NULL);
+ glewInfoFunc("glXDestroyPbuffer", glXDestroyPbuffer == NULL);
+ glewInfoFunc("glXDestroyPixmap", glXDestroyPixmap == NULL);
+ glewInfoFunc("glXDestroyWindow", glXDestroyWindow == NULL);
+ glewInfoFunc("glXGetCurrentReadDrawable", glXGetCurrentReadDrawable == NULL);
+ glewInfoFunc("glXGetFBConfigAttrib", glXGetFBConfigAttrib == NULL);
+ glewInfoFunc("glXGetFBConfigs", glXGetFBConfigs == NULL);
+ glewInfoFunc("glXGetSelectedEvent", glXGetSelectedEvent == NULL);
+ glewInfoFunc("glXGetVisualFromFBConfig", glXGetVisualFromFBConfig == NULL);
+ glewInfoFunc("glXMakeContextCurrent", glXMakeContextCurrent == NULL);
+ glewInfoFunc("glXQueryContext", glXQueryContext == NULL);
+ glewInfoFunc("glXQueryDrawable", glXQueryDrawable == NULL);
+ glewInfoFunc("glXSelectEvent", glXSelectEvent == NULL);
+}
+
+#endif /* GLX_VERSION_1_3 */
+
+#ifdef GLX_VERSION_1_4
+
+static void _glewInfo_GLX_VERSION_1_4 (void)
+{
+ glewPrintExt("GLX_VERSION_1_4", GLXEW_VERSION_1_4, GLXEW_VERSION_1_4, GLXEW_VERSION_1_4);
+}
+
+#endif /* GLX_VERSION_1_4 */
+
+#ifdef GLX_3DFX_multisample
+
+static void _glewInfo_GLX_3DFX_multisample (void)
+{
+ glewPrintExt("GLX_3DFX_multisample", GLXEW_3DFX_multisample, glxewIsSupported("GLX_3DFX_multisample"), glxewGetExtension("GLX_3DFX_multisample"));
+}
+
+#endif /* GLX_3DFX_multisample */
+
+#ifdef GLX_ARB_create_context
+
+static void _glewInfo_GLX_ARB_create_context (void)
+{
+ glewPrintExt("GLX_ARB_create_context", GLXEW_ARB_create_context, glxewIsSupported("GLX_ARB_create_context"), glxewGetExtension("GLX_ARB_create_context"));
+
+ glewInfoFunc("glXCreateContextAttribsARB", glXCreateContextAttribsARB == NULL);
+}
+
+#endif /* GLX_ARB_create_context */
+
+#ifdef GLX_ARB_fbconfig_float
+
+static void _glewInfo_GLX_ARB_fbconfig_float (void)
+{
+ glewPrintExt("GLX_ARB_fbconfig_float", GLXEW_ARB_fbconfig_float, glxewIsSupported("GLX_ARB_fbconfig_float"), glxewGetExtension("GLX_ARB_fbconfig_float"));
+}
+
+#endif /* GLX_ARB_fbconfig_float */
+
+#ifdef GLX_ARB_framebuffer_sRGB
+
+static void _glewInfo_GLX_ARB_framebuffer_sRGB (void)
+{
+ glewPrintExt("GLX_ARB_framebuffer_sRGB", GLXEW_ARB_framebuffer_sRGB, glxewIsSupported("GLX_ARB_framebuffer_sRGB"), glxewGetExtension("GLX_ARB_framebuffer_sRGB"));
+}
+
+#endif /* GLX_ARB_framebuffer_sRGB */
+
+#ifdef GLX_ARB_get_proc_address
+
+static void _glewInfo_GLX_ARB_get_proc_address (void)
+{
+ glewPrintExt("GLX_ARB_get_proc_address", GLXEW_ARB_get_proc_address, glxewIsSupported("GLX_ARB_get_proc_address"), glxewGetExtension("GLX_ARB_get_proc_address"));
+}
+
+#endif /* GLX_ARB_get_proc_address */
+
+#ifdef GLX_ARB_multisample
+
+static void _glewInfo_GLX_ARB_multisample (void)
+{
+ glewPrintExt("GLX_ARB_multisample", GLXEW_ARB_multisample, glxewIsSupported("GLX_ARB_multisample"), glxewGetExtension("GLX_ARB_multisample"));
+}
+
+#endif /* GLX_ARB_multisample */
+
+#ifdef GLX_ATI_pixel_format_float
+
+static void _glewInfo_GLX_ATI_pixel_format_float (void)
+{
+ glewPrintExt("GLX_ATI_pixel_format_float", GLXEW_ATI_pixel_format_float, glxewIsSupported("GLX_ATI_pixel_format_float"), glxewGetExtension("GLX_ATI_pixel_format_float"));
+}
+
+#endif /* GLX_ATI_pixel_format_float */
+
+#ifdef GLX_ATI_render_texture
+
+static void _glewInfo_GLX_ATI_render_texture (void)
+{
+ glewPrintExt("GLX_ATI_render_texture", GLXEW_ATI_render_texture, glxewIsSupported("GLX_ATI_render_texture"), glxewGetExtension("GLX_ATI_render_texture"));
+
+ glewInfoFunc("glXBindTexImageATI", glXBindTexImageATI == NULL);
+ glewInfoFunc("glXDrawableAttribATI", glXDrawableAttribATI == NULL);
+ glewInfoFunc("glXReleaseTexImageATI", glXReleaseTexImageATI == NULL);
+}
+
+#endif /* GLX_ATI_render_texture */
+
+#ifdef GLX_EXT_fbconfig_packed_float
+
+static void _glewInfo_GLX_EXT_fbconfig_packed_float (void)
+{
+ glewPrintExt("GLX_EXT_fbconfig_packed_float", GLXEW_EXT_fbconfig_packed_float, glxewIsSupported("GLX_EXT_fbconfig_packed_float"), glxewGetExtension("GLX_EXT_fbconfig_packed_float"));
+}
+
+#endif /* GLX_EXT_fbconfig_packed_float */
+
+#ifdef GLX_EXT_framebuffer_sRGB
+
+static void _glewInfo_GLX_EXT_framebuffer_sRGB (void)
+{
+ glewPrintExt("GLX_EXT_framebuffer_sRGB", GLXEW_EXT_framebuffer_sRGB, glxewIsSupported("GLX_EXT_framebuffer_sRGB"), glxewGetExtension("GLX_EXT_framebuffer_sRGB"));
+}
+
+#endif /* GLX_EXT_framebuffer_sRGB */
+
+#ifdef GLX_EXT_import_context
+
+static void _glewInfo_GLX_EXT_import_context (void)
+{
+ glewPrintExt("GLX_EXT_import_context", GLXEW_EXT_import_context, glxewIsSupported("GLX_EXT_import_context"), glxewGetExtension("GLX_EXT_import_context"));
+
+ glewInfoFunc("glXFreeContextEXT", glXFreeContextEXT == NULL);
+ glewInfoFunc("glXGetContextIDEXT", glXGetContextIDEXT == NULL);
+ glewInfoFunc("glXImportContextEXT", glXImportContextEXT == NULL);
+ glewInfoFunc("glXQueryContextInfoEXT", glXQueryContextInfoEXT == NULL);
+}
+
+#endif /* GLX_EXT_import_context */
+
+#ifdef GLX_EXT_scene_marker
+
+static void _glewInfo_GLX_EXT_scene_marker (void)
+{
+ glewPrintExt("GLX_EXT_scene_marker", GLXEW_EXT_scene_marker, glxewIsSupported("GLX_EXT_scene_marker"), glxewGetExtension("GLX_EXT_scene_marker"));
+}
+
+#endif /* GLX_EXT_scene_marker */
+
+#ifdef GLX_EXT_texture_from_pixmap
+
+static void _glewInfo_GLX_EXT_texture_from_pixmap (void)
+{
+ glewPrintExt("GLX_EXT_texture_from_pixmap", GLXEW_EXT_texture_from_pixmap, glxewIsSupported("GLX_EXT_texture_from_pixmap"), glxewGetExtension("GLX_EXT_texture_from_pixmap"));
+
+ glewInfoFunc("glXBindTexImageEXT", glXBindTexImageEXT == NULL);
+ glewInfoFunc("glXReleaseTexImageEXT", glXReleaseTexImageEXT == NULL);
+}
+
+#endif /* GLX_EXT_texture_from_pixmap */
+
+#ifdef GLX_EXT_visual_info
+
+static void _glewInfo_GLX_EXT_visual_info (void)
+{
+ glewPrintExt("GLX_EXT_visual_info", GLXEW_EXT_visual_info, glxewIsSupported("GLX_EXT_visual_info"), glxewGetExtension("GLX_EXT_visual_info"));
+}
+
+#endif /* GLX_EXT_visual_info */
+
+#ifdef GLX_EXT_visual_rating
+
+static void _glewInfo_GLX_EXT_visual_rating (void)
+{
+ glewPrintExt("GLX_EXT_visual_rating", GLXEW_EXT_visual_rating, glxewIsSupported("GLX_EXT_visual_rating"), glxewGetExtension("GLX_EXT_visual_rating"));
+}
+
+#endif /* GLX_EXT_visual_rating */
+
+#ifdef GLX_MESA_agp_offset
+
+static void _glewInfo_GLX_MESA_agp_offset (void)
+{
+ glewPrintExt("GLX_MESA_agp_offset", GLXEW_MESA_agp_offset, glxewIsSupported("GLX_MESA_agp_offset"), glxewGetExtension("GLX_MESA_agp_offset"));
+
+ glewInfoFunc("glXGetAGPOffsetMESA", glXGetAGPOffsetMESA == NULL);
+}
+
+#endif /* GLX_MESA_agp_offset */
+
+#ifdef GLX_MESA_copy_sub_buffer
+
+static void _glewInfo_GLX_MESA_copy_sub_buffer (void)
+{
+ glewPrintExt("GLX_MESA_copy_sub_buffer", GLXEW_MESA_copy_sub_buffer, glxewIsSupported("GLX_MESA_copy_sub_buffer"), glxewGetExtension("GLX_MESA_copy_sub_buffer"));
+
+ glewInfoFunc("glXCopySubBufferMESA", glXCopySubBufferMESA == NULL);
+}
+
+#endif /* GLX_MESA_copy_sub_buffer */
+
+#ifdef GLX_MESA_pixmap_colormap
+
+static void _glewInfo_GLX_MESA_pixmap_colormap (void)
+{
+ glewPrintExt("GLX_MESA_pixmap_colormap", GLXEW_MESA_pixmap_colormap, glxewIsSupported("GLX_MESA_pixmap_colormap"), glxewGetExtension("GLX_MESA_pixmap_colormap"));
+
+ glewInfoFunc("glXCreateGLXPixmapMESA", glXCreateGLXPixmapMESA == NULL);
+}
+
+#endif /* GLX_MESA_pixmap_colormap */
+
+#ifdef GLX_MESA_release_buffers
+
+static void _glewInfo_GLX_MESA_release_buffers (void)
+{
+ glewPrintExt("GLX_MESA_release_buffers", GLXEW_MESA_release_buffers, glxewIsSupported("GLX_MESA_release_buffers"), glxewGetExtension("GLX_MESA_release_buffers"));
+
+ glewInfoFunc("glXReleaseBuffersMESA", glXReleaseBuffersMESA == NULL);
+}
+
+#endif /* GLX_MESA_release_buffers */
+
+#ifdef GLX_MESA_set_3dfx_mode
+
+static void _glewInfo_GLX_MESA_set_3dfx_mode (void)
+{
+ glewPrintExt("GLX_MESA_set_3dfx_mode", GLXEW_MESA_set_3dfx_mode, glxewIsSupported("GLX_MESA_set_3dfx_mode"), glxewGetExtension("GLX_MESA_set_3dfx_mode"));
+
+ glewInfoFunc("glXSet3DfxModeMESA", glXSet3DfxModeMESA == NULL);
+}
+
+#endif /* GLX_MESA_set_3dfx_mode */
+
+#ifdef GLX_NV_float_buffer
+
+static void _glewInfo_GLX_NV_float_buffer (void)
+{
+ glewPrintExt("GLX_NV_float_buffer", GLXEW_NV_float_buffer, glxewIsSupported("GLX_NV_float_buffer"), glxewGetExtension("GLX_NV_float_buffer"));
+}
+
+#endif /* GLX_NV_float_buffer */
+
+#ifdef GLX_NV_present_video
+
+static void _glewInfo_GLX_NV_present_video (void)
+{
+ glewPrintExt("GLX_NV_present_video", GLXEW_NV_present_video, glxewIsSupported("GLX_NV_present_video"), glxewGetExtension("GLX_NV_present_video"));
+
+ glewInfoFunc("glXBindVideoDeviceNV", glXBindVideoDeviceNV == NULL);
+ glewInfoFunc("glXEnumerateVideoDevicesNV", glXEnumerateVideoDevicesNV == NULL);
+}
+
+#endif /* GLX_NV_present_video */
+
+#ifdef GLX_NV_swap_group
+
+static void _glewInfo_GLX_NV_swap_group (void)
+{
+ glewPrintExt("GLX_NV_swap_group", GLXEW_NV_swap_group, glxewIsSupported("GLX_NV_swap_group"), glxewGetExtension("GLX_NV_swap_group"));
+
+ glewInfoFunc("glXBindSwapBarrierNV", glXBindSwapBarrierNV == NULL);
+ glewInfoFunc("glXJoinSwapGroupNV", glXJoinSwapGroupNV == NULL);
+ glewInfoFunc("glXQueryFrameCountNV", glXQueryFrameCountNV == NULL);
+ glewInfoFunc("glXQueryMaxSwapGroupsNV", glXQueryMaxSwapGroupsNV == NULL);
+ glewInfoFunc("glXQuerySwapGroupNV", glXQuerySwapGroupNV == NULL);
+ glewInfoFunc("glXResetFrameCountNV", glXResetFrameCountNV == NULL);
+}
+
+#endif /* GLX_NV_swap_group */
+
+#ifdef GLX_NV_vertex_array_range
+
+static void _glewInfo_GLX_NV_vertex_array_range (void)
+{
+ glewPrintExt("GLX_NV_vertex_array_range", GLXEW_NV_vertex_array_range, glxewIsSupported("GLX_NV_vertex_array_range"), glxewGetExtension("GLX_NV_vertex_array_range"));
+
+ glewInfoFunc("glXAllocateMemoryNV", glXAllocateMemoryNV == NULL);
+ glewInfoFunc("glXFreeMemoryNV", glXFreeMemoryNV == NULL);
+}
+
+#endif /* GLX_NV_vertex_array_range */
+
+#ifdef GLX_NV_video_output
+
+static void _glewInfo_GLX_NV_video_output (void)
+{
+ glewPrintExt("GLX_NV_video_output", GLXEW_NV_video_output, glxewIsSupported("GLX_NV_video_output"), glxewGetExtension("GLX_NV_video_output"));
+
+ glewInfoFunc("glXBindVideoImageNV", glXBindVideoImageNV == NULL);
+ glewInfoFunc("glXGetVideoDeviceNV", glXGetVideoDeviceNV == NULL);
+ glewInfoFunc("glXGetVideoInfoNV", glXGetVideoInfoNV == NULL);
+ glewInfoFunc("glXReleaseVideoDeviceNV", glXReleaseVideoDeviceNV == NULL);
+ glewInfoFunc("glXReleaseVideoImageNV", glXReleaseVideoImageNV == NULL);
+ glewInfoFunc("glXSendPbufferToVideoNV", glXSendPbufferToVideoNV == NULL);
+}
+
+#endif /* GLX_NV_video_output */
+
+#ifdef GLX_OML_swap_method
+
+static void _glewInfo_GLX_OML_swap_method (void)
+{
+ glewPrintExt("GLX_OML_swap_method", GLXEW_OML_swap_method, glxewIsSupported("GLX_OML_swap_method"), glxewGetExtension("GLX_OML_swap_method"));
+}
+
+#endif /* GLX_OML_swap_method */
+
+#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#include <inttypes.h>
+
+static void _glewInfo_GLX_OML_sync_control (void)
+{
+ glewPrintExt("GLX_OML_sync_control", GLXEW_OML_sync_control, glxewIsSupported("GLX_OML_sync_control"), glxewGetExtension("GLX_OML_sync_control"));
+
+ glewInfoFunc("glXGetMscRateOML", glXGetMscRateOML == NULL);
+ glewInfoFunc("glXGetSyncValuesOML", glXGetSyncValuesOML == NULL);
+ glewInfoFunc("glXSwapBuffersMscOML", glXSwapBuffersMscOML == NULL);
+ glewInfoFunc("glXWaitForMscOML", glXWaitForMscOML == NULL);
+ glewInfoFunc("glXWaitForSbcOML", glXWaitForSbcOML == NULL);
+}
+
+#endif /* GLX_OML_sync_control */
+
+#ifdef GLX_SGIS_blended_overlay
+
+static void _glewInfo_GLX_SGIS_blended_overlay (void)
+{
+ glewPrintExt("GLX_SGIS_blended_overlay", GLXEW_SGIS_blended_overlay, glxewIsSupported("GLX_SGIS_blended_overlay"), glxewGetExtension("GLX_SGIS_blended_overlay"));
+}
+
+#endif /* GLX_SGIS_blended_overlay */
+
+#ifdef GLX_SGIS_color_range
+
+static void _glewInfo_GLX_SGIS_color_range (void)
+{
+ glewPrintExt("GLX_SGIS_color_range", GLXEW_SGIS_color_range, glxewIsSupported("GLX_SGIS_color_range"), glxewGetExtension("GLX_SGIS_color_range"));
+}
+
+#endif /* GLX_SGIS_color_range */
+
+#ifdef GLX_SGIS_multisample
+
+static void _glewInfo_GLX_SGIS_multisample (void)
+{
+ glewPrintExt("GLX_SGIS_multisample", GLXEW_SGIS_multisample, glxewIsSupported("GLX_SGIS_multisample"), glxewGetExtension("GLX_SGIS_multisample"));
+}
+
+#endif /* GLX_SGIS_multisample */
+
+#ifdef GLX_SGIS_shared_multisample
+
+static void _glewInfo_GLX_SGIS_shared_multisample (void)
+{
+ glewPrintExt("GLX_SGIS_shared_multisample", GLXEW_SGIS_shared_multisample, glxewIsSupported("GLX_SGIS_shared_multisample"), glxewGetExtension("GLX_SGIS_shared_multisample"));
+}
+
+#endif /* GLX_SGIS_shared_multisample */
+
+#ifdef GLX_SGIX_fbconfig
+
+static void _glewInfo_GLX_SGIX_fbconfig (void)
+{
+ glewPrintExt("GLX_SGIX_fbconfig", GLXEW_SGIX_fbconfig, glxewIsSupported("GLX_SGIX_fbconfig"), glxewGetExtension("GLX_SGIX_fbconfig"));
+
+ glewInfoFunc("glXChooseFBConfigSGIX", glXChooseFBConfigSGIX == NULL);
+ glewInfoFunc("glXCreateContextWithConfigSGIX", glXCreateContextWithConfigSGIX == NULL);
+ glewInfoFunc("glXCreateGLXPixmapWithConfigSGIX", glXCreateGLXPixmapWithConfigSGIX == NULL);
+ glewInfoFunc("glXGetFBConfigAttribSGIX", glXGetFBConfigAttribSGIX == NULL);
+ glewInfoFunc("glXGetFBConfigFromVisualSGIX", glXGetFBConfigFromVisualSGIX == NULL);
+ glewInfoFunc("glXGetVisualFromFBConfigSGIX", glXGetVisualFromFBConfigSGIX == NULL);
+}
+
+#endif /* GLX_SGIX_fbconfig */
+
+#ifdef GLX_SGIX_hyperpipe
+
+static void _glewInfo_GLX_SGIX_hyperpipe (void)
+{
+ glewPrintExt("GLX_SGIX_hyperpipe", GLXEW_SGIX_hyperpipe, glxewIsSupported("GLX_SGIX_hyperpipe"), glxewGetExtension("GLX_SGIX_hyperpipe"));
+
+ glewInfoFunc("glXBindHyperpipeSGIX", glXBindHyperpipeSGIX == NULL);
+ glewInfoFunc("glXDestroyHyperpipeConfigSGIX", glXDestroyHyperpipeConfigSGIX == NULL);
+ glewInfoFunc("glXHyperpipeAttribSGIX", glXHyperpipeAttribSGIX == NULL);
+ glewInfoFunc("glXHyperpipeConfigSGIX", glXHyperpipeConfigSGIX == NULL);
+ glewInfoFunc("glXQueryHyperpipeAttribSGIX", glXQueryHyperpipeAttribSGIX == NULL);
+ glewInfoFunc("glXQueryHyperpipeBestAttribSGIX", glXQueryHyperpipeBestAttribSGIX == NULL);
+ glewInfoFunc("glXQueryHyperpipeConfigSGIX", glXQueryHyperpipeConfigSGIX == NULL);
+ glewInfoFunc("glXQueryHyperpipeNetworkSGIX", glXQueryHyperpipeNetworkSGIX == NULL);
+}
+
+#endif /* GLX_SGIX_hyperpipe */
+
+#ifdef GLX_SGIX_pbuffer
+
+static void _glewInfo_GLX_SGIX_pbuffer (void)
+{
+ glewPrintExt("GLX_SGIX_pbuffer", GLXEW_SGIX_pbuffer, glxewIsSupported("GLX_SGIX_pbuffer"), glxewGetExtension("GLX_SGIX_pbuffer"));
+
+ glewInfoFunc("glXCreateGLXPbufferSGIX", glXCreateGLXPbufferSGIX == NULL);
+ glewInfoFunc("glXDestroyGLXPbufferSGIX", glXDestroyGLXPbufferSGIX == NULL);
+ glewInfoFunc("glXGetSelectedEventSGIX", glXGetSelectedEventSGIX == NULL);
+ glewInfoFunc("glXQueryGLXPbufferSGIX", glXQueryGLXPbufferSGIX == NULL);
+ glewInfoFunc("glXSelectEventSGIX", glXSelectEventSGIX == NULL);
+}
+
+#endif /* GLX_SGIX_pbuffer */
+
+#ifdef GLX_SGIX_swap_barrier
+
+static void _glewInfo_GLX_SGIX_swap_barrier (void)
+{
+ glewPrintExt("GLX_SGIX_swap_barrier", GLXEW_SGIX_swap_barrier, glxewIsSupported("GLX_SGIX_swap_barrier"), glxewGetExtension("GLX_SGIX_swap_barrier"));
+
+ glewInfoFunc("glXBindSwapBarrierSGIX", glXBindSwapBarrierSGIX == NULL);
+ glewInfoFunc("glXQueryMaxSwapBarriersSGIX", glXQueryMaxSwapBarriersSGIX == NULL);
+}
+
+#endif /* GLX_SGIX_swap_barrier */
+
+#ifdef GLX_SGIX_swap_group
+
+static void _glewInfo_GLX_SGIX_swap_group (void)
+{
+ glewPrintExt("GLX_SGIX_swap_group", GLXEW_SGIX_swap_group, glxewIsSupported("GLX_SGIX_swap_group"), glxewGetExtension("GLX_SGIX_swap_group"));
+
+ glewInfoFunc("glXJoinSwapGroupSGIX", glXJoinSwapGroupSGIX == NULL);
+}
+
+#endif /* GLX_SGIX_swap_group */
+
+#ifdef GLX_SGIX_video_resize
+
+static void _glewInfo_GLX_SGIX_video_resize (void)
+{
+ glewPrintExt("GLX_SGIX_video_resize", GLXEW_SGIX_video_resize, glxewIsSupported("GLX_SGIX_video_resize"), glxewGetExtension("GLX_SGIX_video_resize"));
+
+ glewInfoFunc("glXBindChannelToWindowSGIX", glXBindChannelToWindowSGIX == NULL);
+ glewInfoFunc("glXChannelRectSGIX", glXChannelRectSGIX == NULL);
+ glewInfoFunc("glXChannelRectSyncSGIX", glXChannelRectSyncSGIX == NULL);
+ glewInfoFunc("glXQueryChannelDeltasSGIX", glXQueryChannelDeltasSGIX == NULL);
+ glewInfoFunc("glXQueryChannelRectSGIX", glXQueryChannelRectSGIX == NULL);
+}
+
+#endif /* GLX_SGIX_video_resize */
+
+#ifdef GLX_SGIX_visual_select_group
+
+static void _glewInfo_GLX_SGIX_visual_select_group (void)
+{
+ glewPrintExt("GLX_SGIX_visual_select_group", GLXEW_SGIX_visual_select_group, glxewIsSupported("GLX_SGIX_visual_select_group"), glxewGetExtension("GLX_SGIX_visual_select_group"));
+}
+
+#endif /* GLX_SGIX_visual_select_group */
+
+#ifdef GLX_SGI_cushion
+
+static void _glewInfo_GLX_SGI_cushion (void)
+{
+ glewPrintExt("GLX_SGI_cushion", GLXEW_SGI_cushion, glxewIsSupported("GLX_SGI_cushion"), glxewGetExtension("GLX_SGI_cushion"));
+
+ glewInfoFunc("glXCushionSGI", glXCushionSGI == NULL);
+}
+
+#endif /* GLX_SGI_cushion */
+
+#ifdef GLX_SGI_make_current_read
+
+static void _glewInfo_GLX_SGI_make_current_read (void)
+{
+ glewPrintExt("GLX_SGI_make_current_read", GLXEW_SGI_make_current_read, glxewIsSupported("GLX_SGI_make_current_read"), glxewGetExtension("GLX_SGI_make_current_read"));
+
+ glewInfoFunc("glXGetCurrentReadDrawableSGI", glXGetCurrentReadDrawableSGI == NULL);
+ glewInfoFunc("glXMakeCurrentReadSGI", glXMakeCurrentReadSGI == NULL);
+}
+
+#endif /* GLX_SGI_make_current_read */
+
+#ifdef GLX_SGI_swap_control
+
+static void _glewInfo_GLX_SGI_swap_control (void)
+{
+ glewPrintExt("GLX_SGI_swap_control", GLXEW_SGI_swap_control, glxewIsSupported("GLX_SGI_swap_control"), glxewGetExtension("GLX_SGI_swap_control"));
+
+ glewInfoFunc("glXSwapIntervalSGI", glXSwapIntervalSGI == NULL);
+}
+
+#endif /* GLX_SGI_swap_control */
+
+#ifdef GLX_SGI_video_sync
+
+static void _glewInfo_GLX_SGI_video_sync (void)
+{
+ glewPrintExt("GLX_SGI_video_sync", GLXEW_SGI_video_sync, glxewIsSupported("GLX_SGI_video_sync"), glxewGetExtension("GLX_SGI_video_sync"));
+
+ glewInfoFunc("glXGetVideoSyncSGI", glXGetVideoSyncSGI == NULL);
+ glewInfoFunc("glXWaitVideoSyncSGI", glXWaitVideoSyncSGI == NULL);
+}
+
+#endif /* GLX_SGI_video_sync */
+
+#ifdef GLX_SUN_get_transparent_index
+
+static void _glewInfo_GLX_SUN_get_transparent_index (void)
+{
+ glewPrintExt("GLX_SUN_get_transparent_index", GLXEW_SUN_get_transparent_index, glxewIsSupported("GLX_SUN_get_transparent_index"), glxewGetExtension("GLX_SUN_get_transparent_index"));
+
+ glewInfoFunc("glXGetTransparentIndexSUN", glXGetTransparentIndexSUN == NULL);
+}
+
+#endif /* GLX_SUN_get_transparent_index */
+
+#ifdef GLX_SUN_video_resize
+
+static void _glewInfo_GLX_SUN_video_resize (void)
+{
+ glewPrintExt("GLX_SUN_video_resize", GLXEW_SUN_video_resize, glxewIsSupported("GLX_SUN_video_resize"), glxewGetExtension("GLX_SUN_video_resize"));
+
+ glewInfoFunc("glXGetVideoResizeSUN", glXGetVideoResizeSUN == NULL);
+ glewInfoFunc("glXVideoResizeSUN", glXVideoResizeSUN == NULL);
+}
+
+#endif /* GLX_SUN_video_resize */
+
+#endif /* _WIN32 */
+
+/* ------------------------------------------------------------------------ */
+
+static void glewInfo (void)
+{
+#ifdef GL_VERSION_1_1
+ _glewInfo_GL_VERSION_1_1();
+#endif /* GL_VERSION_1_1 */
+#ifdef GL_VERSION_1_2
+ _glewInfo_GL_VERSION_1_2();
+#endif /* GL_VERSION_1_2 */
+#ifdef GL_VERSION_1_3
+ _glewInfo_GL_VERSION_1_3();
+#endif /* GL_VERSION_1_3 */
+#ifdef GL_VERSION_1_4
+ _glewInfo_GL_VERSION_1_4();
+#endif /* GL_VERSION_1_4 */
+#ifdef GL_VERSION_1_5
+ _glewInfo_GL_VERSION_1_5();
+#endif /* GL_VERSION_1_5 */
+#ifdef GL_VERSION_2_0
+ _glewInfo_GL_VERSION_2_0();
+#endif /* GL_VERSION_2_0 */
+#ifdef GL_VERSION_2_1
+ _glewInfo_GL_VERSION_2_1();
+#endif /* GL_VERSION_2_1 */
+#ifdef GL_VERSION_3_0
+ _glewInfo_GL_VERSION_3_0();
+#endif /* GL_VERSION_3_0 */
+#ifdef GL_3DFX_multisample
+ _glewInfo_GL_3DFX_multisample();
+#endif /* GL_3DFX_multisample */
+#ifdef GL_3DFX_tbuffer
+ _glewInfo_GL_3DFX_tbuffer();
+#endif /* GL_3DFX_tbuffer */
+#ifdef GL_3DFX_texture_compression_FXT1
+ _glewInfo_GL_3DFX_texture_compression_FXT1();
+#endif /* GL_3DFX_texture_compression_FXT1 */
+#ifdef GL_APPLE_client_storage
+ _glewInfo_GL_APPLE_client_storage();
+#endif /* GL_APPLE_client_storage */
+#ifdef GL_APPLE_element_array
+ _glewInfo_GL_APPLE_element_array();
+#endif /* GL_APPLE_element_array */
+#ifdef GL_APPLE_fence
+ _glewInfo_GL_APPLE_fence();
+#endif /* GL_APPLE_fence */
+#ifdef GL_APPLE_float_pixels
+ _glewInfo_GL_APPLE_float_pixels();
+#endif /* GL_APPLE_float_pixels */
+#ifdef GL_APPLE_flush_buffer_range
+ _glewInfo_GL_APPLE_flush_buffer_range();
+#endif /* GL_APPLE_flush_buffer_range */
+#ifdef GL_APPLE_pixel_buffer
+ _glewInfo_GL_APPLE_pixel_buffer();
+#endif /* GL_APPLE_pixel_buffer */
+#ifdef GL_APPLE_specular_vector
+ _glewInfo_GL_APPLE_specular_vector();
+#endif /* GL_APPLE_specular_vector */
+#ifdef GL_APPLE_texture_range
+ _glewInfo_GL_APPLE_texture_range();
+#endif /* GL_APPLE_texture_range */
+#ifdef GL_APPLE_transform_hint
+ _glewInfo_GL_APPLE_transform_hint();
+#endif /* GL_APPLE_transform_hint */
+#ifdef GL_APPLE_vertex_array_object
+ _glewInfo_GL_APPLE_vertex_array_object();
+#endif /* GL_APPLE_vertex_array_object */
+#ifdef GL_APPLE_vertex_array_range
+ _glewInfo_GL_APPLE_vertex_array_range();
+#endif /* GL_APPLE_vertex_array_range */
+#ifdef GL_APPLE_ycbcr_422
+ _glewInfo_GL_APPLE_ycbcr_422();
+#endif /* GL_APPLE_ycbcr_422 */
+#ifdef GL_ARB_color_buffer_float
+ _glewInfo_GL_ARB_color_buffer_float();
+#endif /* GL_ARB_color_buffer_float */
+#ifdef GL_ARB_depth_buffer_float
+ _glewInfo_GL_ARB_depth_buffer_float();
+#endif /* GL_ARB_depth_buffer_float */
+#ifdef GL_ARB_depth_texture
+ _glewInfo_GL_ARB_depth_texture();
+#endif /* GL_ARB_depth_texture */
+#ifdef GL_ARB_draw_buffers
+ _glewInfo_GL_ARB_draw_buffers();
+#endif /* GL_ARB_draw_buffers */
+#ifdef GL_ARB_draw_instanced
+ _glewInfo_GL_ARB_draw_instanced();
+#endif /* GL_ARB_draw_instanced */
+#ifdef GL_ARB_fragment_program
+ _glewInfo_GL_ARB_fragment_program();
+#endif /* GL_ARB_fragment_program */
+#ifdef GL_ARB_fragment_program_shadow
+ _glewInfo_GL_ARB_fragment_program_shadow();
+#endif /* GL_ARB_fragment_program_shadow */
+#ifdef GL_ARB_fragment_shader
+ _glewInfo_GL_ARB_fragment_shader();
+#endif /* GL_ARB_fragment_shader */
+#ifdef GL_ARB_framebuffer_object
+ _glewInfo_GL_ARB_framebuffer_object();
+#endif /* GL_ARB_framebuffer_object */
+#ifdef GL_ARB_framebuffer_sRGB
+ _glewInfo_GL_ARB_framebuffer_sRGB();
+#endif /* GL_ARB_framebuffer_sRGB */
+#ifdef GL_ARB_geometry_shader4
+ _glewInfo_GL_ARB_geometry_shader4();
+#endif /* GL_ARB_geometry_shader4 */
+#ifdef GL_ARB_half_float_pixel
+ _glewInfo_GL_ARB_half_float_pixel();
+#endif /* GL_ARB_half_float_pixel */
+#ifdef GL_ARB_half_float_vertex
+ _glewInfo_GL_ARB_half_float_vertex();
+#endif /* GL_ARB_half_float_vertex */
+#ifdef GL_ARB_imaging
+ _glewInfo_GL_ARB_imaging();
+#endif /* GL_ARB_imaging */
+#ifdef GL_ARB_instanced_arrays
+ _glewInfo_GL_ARB_instanced_arrays();
+#endif /* GL_ARB_instanced_arrays */
+#ifdef GL_ARB_map_buffer_range
+ _glewInfo_GL_ARB_map_buffer_range();
+#endif /* GL_ARB_map_buffer_range */
+#ifdef GL_ARB_matrix_palette
+ _glewInfo_GL_ARB_matrix_palette();
+#endif /* GL_ARB_matrix_palette */
+#ifdef GL_ARB_multisample
+ _glewInfo_GL_ARB_multisample();
+#endif /* GL_ARB_multisample */
+#ifdef GL_ARB_multitexture
+ _glewInfo_GL_ARB_multitexture();
+#endif /* GL_ARB_multitexture */
+#ifdef GL_ARB_occlusion_query
+ _glewInfo_GL_ARB_occlusion_query();
+#endif /* GL_ARB_occlusion_query */
+#ifdef GL_ARB_pixel_buffer_object
+ _glewInfo_GL_ARB_pixel_buffer_object();
+#endif /* GL_ARB_pixel_buffer_object */
+#ifdef GL_ARB_point_parameters
+ _glewInfo_GL_ARB_point_parameters();
+#endif /* GL_ARB_point_parameters */
+#ifdef GL_ARB_point_sprite
+ _glewInfo_GL_ARB_point_sprite();
+#endif /* GL_ARB_point_sprite */
+#ifdef GL_ARB_shader_objects
+ _glewInfo_GL_ARB_shader_objects();
+#endif /* GL_ARB_shader_objects */
+#ifdef GL_ARB_shading_language_100
+ _glewInfo_GL_ARB_shading_language_100();
+#endif /* GL_ARB_shading_language_100 */
+#ifdef GL_ARB_shadow
+ _glewInfo_GL_ARB_shadow();
+#endif /* GL_ARB_shadow */
+#ifdef GL_ARB_shadow_ambient
+ _glewInfo_GL_ARB_shadow_ambient();
+#endif /* GL_ARB_shadow_ambient */
+#ifdef GL_ARB_texture_border_clamp
+ _glewInfo_GL_ARB_texture_border_clamp();
+#endif /* GL_ARB_texture_border_clamp */
+#ifdef GL_ARB_texture_buffer_object
+ _glewInfo_GL_ARB_texture_buffer_object();
+#endif /* GL_ARB_texture_buffer_object */
+#ifdef GL_ARB_texture_compression
+ _glewInfo_GL_ARB_texture_compression();
+#endif /* GL_ARB_texture_compression */
+#ifdef GL_ARB_texture_compression_rgtc
+ _glewInfo_GL_ARB_texture_compression_rgtc();
+#endif /* GL_ARB_texture_compression_rgtc */
+#ifdef GL_ARB_texture_cube_map
+ _glewInfo_GL_ARB_texture_cube_map();
+#endif /* GL_ARB_texture_cube_map */
+#ifdef GL_ARB_texture_env_add
+ _glewInfo_GL_ARB_texture_env_add();
+#endif /* GL_ARB_texture_env_add */
+#ifdef GL_ARB_texture_env_combine
+ _glewInfo_GL_ARB_texture_env_combine();
+#endif /* GL_ARB_texture_env_combine */
+#ifdef GL_ARB_texture_env_crossbar
+ _glewInfo_GL_ARB_texture_env_crossbar();
+#endif /* GL_ARB_texture_env_crossbar */
+#ifdef GL_ARB_texture_env_dot3
+ _glewInfo_GL_ARB_texture_env_dot3();
+#endif /* GL_ARB_texture_env_dot3 */
+#ifdef GL_ARB_texture_float
+ _glewInfo_GL_ARB_texture_float();
+#endif /* GL_ARB_texture_float */
+#ifdef GL_ARB_texture_mirrored_repeat
+ _glewInfo_GL_ARB_texture_mirrored_repeat();
+#endif /* GL_ARB_texture_mirrored_repeat */
+#ifdef GL_ARB_texture_non_power_of_two
+ _glewInfo_GL_ARB_texture_non_power_of_two();
+#endif /* GL_ARB_texture_non_power_of_two */
+#ifdef GL_ARB_texture_rectangle
+ _glewInfo_GL_ARB_texture_rectangle();
+#endif /* GL_ARB_texture_rectangle */
+#ifdef GL_ARB_texture_rg
+ _glewInfo_GL_ARB_texture_rg();
+#endif /* GL_ARB_texture_rg */
+#ifdef GL_ARB_transpose_matrix
+ _glewInfo_GL_ARB_transpose_matrix();
+#endif /* GL_ARB_transpose_matrix */
+#ifdef GL_ARB_vertex_array_object
+ _glewInfo_GL_ARB_vertex_array_object();
+#endif /* GL_ARB_vertex_array_object */
+#ifdef GL_ARB_vertex_blend
+ _glewInfo_GL_ARB_vertex_blend();
+#endif /* GL_ARB_vertex_blend */
+#ifdef GL_ARB_vertex_buffer_object
+ _glewInfo_GL_ARB_vertex_buffer_object();
+#endif /* GL_ARB_vertex_buffer_object */
+#ifdef GL_ARB_vertex_program
+ _glewInfo_GL_ARB_vertex_program();
+#endif /* GL_ARB_vertex_program */
+#ifdef GL_ARB_vertex_shader
+ _glewInfo_GL_ARB_vertex_shader();
+#endif /* GL_ARB_vertex_shader */
+#ifdef GL_ARB_window_pos
+ _glewInfo_GL_ARB_window_pos();
+#endif /* GL_ARB_window_pos */
+#ifdef GL_ATIX_point_sprites
+ _glewInfo_GL_ATIX_point_sprites();
+#endif /* GL_ATIX_point_sprites */
+#ifdef GL_ATIX_texture_env_combine3
+ _glewInfo_GL_ATIX_texture_env_combine3();
+#endif /* GL_ATIX_texture_env_combine3 */
+#ifdef GL_ATIX_texture_env_route
+ _glewInfo_GL_ATIX_texture_env_route();
+#endif /* GL_ATIX_texture_env_route */
+#ifdef GL_ATIX_vertex_shader_output_point_size
+ _glewInfo_GL_ATIX_vertex_shader_output_point_size();
+#endif /* GL_ATIX_vertex_shader_output_point_size */
+#ifdef GL_ATI_draw_buffers
+ _glewInfo_GL_ATI_draw_buffers();
+#endif /* GL_ATI_draw_buffers */
+#ifdef GL_ATI_element_array
+ _glewInfo_GL_ATI_element_array();
+#endif /* GL_ATI_element_array */
+#ifdef GL_ATI_envmap_bumpmap
+ _glewInfo_GL_ATI_envmap_bumpmap();
+#endif /* GL_ATI_envmap_bumpmap */
+#ifdef GL_ATI_fragment_shader
+ _glewInfo_GL_ATI_fragment_shader();
+#endif /* GL_ATI_fragment_shader */
+#ifdef GL_ATI_map_object_buffer
+ _glewInfo_GL_ATI_map_object_buffer();
+#endif /* GL_ATI_map_object_buffer */
+#ifdef GL_ATI_pn_triangles
+ _glewInfo_GL_ATI_pn_triangles();
+#endif /* GL_ATI_pn_triangles */
+#ifdef GL_ATI_separate_stencil
+ _glewInfo_GL_ATI_separate_stencil();
+#endif /* GL_ATI_separate_stencil */
+#ifdef GL_ATI_shader_texture_lod
+ _glewInfo_GL_ATI_shader_texture_lod();
+#endif /* GL_ATI_shader_texture_lod */
+#ifdef GL_ATI_text_fragment_shader
+ _glewInfo_GL_ATI_text_fragment_shader();
+#endif /* GL_ATI_text_fragment_shader */
+#ifdef GL_ATI_texture_compression_3dc
+ _glewInfo_GL_ATI_texture_compression_3dc();
+#endif /* GL_ATI_texture_compression_3dc */
+#ifdef GL_ATI_texture_env_combine3
+ _glewInfo_GL_ATI_texture_env_combine3();
+#endif /* GL_ATI_texture_env_combine3 */
+#ifdef GL_ATI_texture_float
+ _glewInfo_GL_ATI_texture_float();
+#endif /* GL_ATI_texture_float */
+#ifdef GL_ATI_texture_mirror_once
+ _glewInfo_GL_ATI_texture_mirror_once();
+#endif /* GL_ATI_texture_mirror_once */
+#ifdef GL_ATI_vertex_array_object
+ _glewInfo_GL_ATI_vertex_array_object();
+#endif /* GL_ATI_vertex_array_object */
+#ifdef GL_ATI_vertex_attrib_array_object
+ _glewInfo_GL_ATI_vertex_attrib_array_object();
+#endif /* GL_ATI_vertex_attrib_array_object */
+#ifdef GL_ATI_vertex_streams
+ _glewInfo_GL_ATI_vertex_streams();
+#endif /* GL_ATI_vertex_streams */
+#ifdef GL_EXT_422_pixels
+ _glewInfo_GL_EXT_422_pixels();
+#endif /* GL_EXT_422_pixels */
+#ifdef GL_EXT_Cg_shader
+ _glewInfo_GL_EXT_Cg_shader();
+#endif /* GL_EXT_Cg_shader */
+#ifdef GL_EXT_abgr
+ _glewInfo_GL_EXT_abgr();
+#endif /* GL_EXT_abgr */
+#ifdef GL_EXT_bgra
+ _glewInfo_GL_EXT_bgra();
+#endif /* GL_EXT_bgra */
+#ifdef GL_EXT_bindable_uniform
+ _glewInfo_GL_EXT_bindable_uniform();
+#endif /* GL_EXT_bindable_uniform */
+#ifdef GL_EXT_blend_color
+ _glewInfo_GL_EXT_blend_color();
+#endif /* GL_EXT_blend_color */
+#ifdef GL_EXT_blend_equation_separate
+ _glewInfo_GL_EXT_blend_equation_separate();
+#endif /* GL_EXT_blend_equation_separate */
+#ifdef GL_EXT_blend_func_separate
+ _glewInfo_GL_EXT_blend_func_separate();
+#endif /* GL_EXT_blend_func_separate */
+#ifdef GL_EXT_blend_logic_op
+ _glewInfo_GL_EXT_blend_logic_op();
+#endif /* GL_EXT_blend_logic_op */
+#ifdef GL_EXT_blend_minmax
+ _glewInfo_GL_EXT_blend_minmax();
+#endif /* GL_EXT_blend_minmax */
+#ifdef GL_EXT_blend_subtract
+ _glewInfo_GL_EXT_blend_subtract();
+#endif /* GL_EXT_blend_subtract */
+#ifdef GL_EXT_clip_volume_hint
+ _glewInfo_GL_EXT_clip_volume_hint();
+#endif /* GL_EXT_clip_volume_hint */
+#ifdef GL_EXT_cmyka
+ _glewInfo_GL_EXT_cmyka();
+#endif /* GL_EXT_cmyka */
+#ifdef GL_EXT_color_subtable
+ _glewInfo_GL_EXT_color_subtable();
+#endif /* GL_EXT_color_subtable */
+#ifdef GL_EXT_compiled_vertex_array
+ _glewInfo_GL_EXT_compiled_vertex_array();
+#endif /* GL_EXT_compiled_vertex_array */
+#ifdef GL_EXT_convolution
+ _glewInfo_GL_EXT_convolution();
+#endif /* GL_EXT_convolution */
+#ifdef GL_EXT_coordinate_frame
+ _glewInfo_GL_EXT_coordinate_frame();
+#endif /* GL_EXT_coordinate_frame */
+#ifdef GL_EXT_copy_texture
+ _glewInfo_GL_EXT_copy_texture();
+#endif /* GL_EXT_copy_texture */
+#ifdef GL_EXT_cull_vertex
+ _glewInfo_GL_EXT_cull_vertex();
+#endif /* GL_EXT_cull_vertex */
+#ifdef GL_EXT_depth_bounds_test
+ _glewInfo_GL_EXT_depth_bounds_test();
+#endif /* GL_EXT_depth_bounds_test */
+#ifdef GL_EXT_direct_state_access
+ _glewInfo_GL_EXT_direct_state_access();
+#endif /* GL_EXT_direct_state_access */
+#ifdef GL_EXT_draw_buffers2
+ _glewInfo_GL_EXT_draw_buffers2();
+#endif /* GL_EXT_draw_buffers2 */
+#ifdef GL_EXT_draw_instanced
+ _glewInfo_GL_EXT_draw_instanced();
+#endif /* GL_EXT_draw_instanced */
+#ifdef GL_EXT_draw_range_elements
+ _glewInfo_GL_EXT_draw_range_elements();
+#endif /* GL_EXT_draw_range_elements */
+#ifdef GL_EXT_fog_coord
+ _glewInfo_GL_EXT_fog_coord();
+#endif /* GL_EXT_fog_coord */
+#ifdef GL_EXT_fragment_lighting
+ _glewInfo_GL_EXT_fragment_lighting();
+#endif /* GL_EXT_fragment_lighting */
+#ifdef GL_EXT_framebuffer_blit
+ _glewInfo_GL_EXT_framebuffer_blit();
+#endif /* GL_EXT_framebuffer_blit */
+#ifdef GL_EXT_framebuffer_multisample
+ _glewInfo_GL_EXT_framebuffer_multisample();
+#endif /* GL_EXT_framebuffer_multisample */
+#ifdef GL_EXT_framebuffer_object
+ _glewInfo_GL_EXT_framebuffer_object();
+#endif /* GL_EXT_framebuffer_object */
+#ifdef GL_EXT_framebuffer_sRGB
+ _glewInfo_GL_EXT_framebuffer_sRGB();
+#endif /* GL_EXT_framebuffer_sRGB */
+#ifdef GL_EXT_geometry_shader4
+ _glewInfo_GL_EXT_geometry_shader4();
+#endif /* GL_EXT_geometry_shader4 */
+#ifdef GL_EXT_gpu_program_parameters
+ _glewInfo_GL_EXT_gpu_program_parameters();
+#endif /* GL_EXT_gpu_program_parameters */
+#ifdef GL_EXT_gpu_shader4
+ _glewInfo_GL_EXT_gpu_shader4();
+#endif /* GL_EXT_gpu_shader4 */
+#ifdef GL_EXT_histogram
+ _glewInfo_GL_EXT_histogram();
+#endif /* GL_EXT_histogram */
+#ifdef GL_EXT_index_array_formats
+ _glewInfo_GL_EXT_index_array_formats();
+#endif /* GL_EXT_index_array_formats */
+#ifdef GL_EXT_index_func
+ _glewInfo_GL_EXT_index_func();
+#endif /* GL_EXT_index_func */
+#ifdef GL_EXT_index_material
+ _glewInfo_GL_EXT_index_material();
+#endif /* GL_EXT_index_material */
+#ifdef GL_EXT_index_texture
+ _glewInfo_GL_EXT_index_texture();
+#endif /* GL_EXT_index_texture */
+#ifdef GL_EXT_light_texture
+ _glewInfo_GL_EXT_light_texture();
+#endif /* GL_EXT_light_texture */
+#ifdef GL_EXT_misc_attribute
+ _glewInfo_GL_EXT_misc_attribute();
+#endif /* GL_EXT_misc_attribute */
+#ifdef GL_EXT_multi_draw_arrays
+ _glewInfo_GL_EXT_multi_draw_arrays();
+#endif /* GL_EXT_multi_draw_arrays */
+#ifdef GL_EXT_multisample
+ _glewInfo_GL_EXT_multisample();
+#endif /* GL_EXT_multisample */
+#ifdef GL_EXT_packed_depth_stencil
+ _glewInfo_GL_EXT_packed_depth_stencil();
+#endif /* GL_EXT_packed_depth_stencil */
+#ifdef GL_EXT_packed_float
+ _glewInfo_GL_EXT_packed_float();
+#endif /* GL_EXT_packed_float */
+#ifdef GL_EXT_packed_pixels
+ _glewInfo_GL_EXT_packed_pixels();
+#endif /* GL_EXT_packed_pixels */
+#ifdef GL_EXT_paletted_texture
+ _glewInfo_GL_EXT_paletted_texture();
+#endif /* GL_EXT_paletted_texture */
+#ifdef GL_EXT_pixel_buffer_object
+ _glewInfo_GL_EXT_pixel_buffer_object();
+#endif /* GL_EXT_pixel_buffer_object */
+#ifdef GL_EXT_pixel_transform
+ _glewInfo_GL_EXT_pixel_transform();
+#endif /* GL_EXT_pixel_transform */
+#ifdef GL_EXT_pixel_transform_color_table
+ _glewInfo_GL_EXT_pixel_transform_color_table();
+#endif /* GL_EXT_pixel_transform_color_table */
+#ifdef GL_EXT_point_parameters
+ _glewInfo_GL_EXT_point_parameters();
+#endif /* GL_EXT_point_parameters */
+#ifdef GL_EXT_polygon_offset
+ _glewInfo_GL_EXT_polygon_offset();
+#endif /* GL_EXT_polygon_offset */
+#ifdef GL_EXT_rescale_normal
+ _glewInfo_GL_EXT_rescale_normal();
+#endif /* GL_EXT_rescale_normal */
+#ifdef GL_EXT_scene_marker
+ _glewInfo_GL_EXT_scene_marker();
+#endif /* GL_EXT_scene_marker */
+#ifdef GL_EXT_secondary_color
+ _glewInfo_GL_EXT_secondary_color();
+#endif /* GL_EXT_secondary_color */
+#ifdef GL_EXT_separate_specular_color
+ _glewInfo_GL_EXT_separate_specular_color();
+#endif /* GL_EXT_separate_specular_color */
+#ifdef GL_EXT_shadow_funcs
+ _glewInfo_GL_EXT_shadow_funcs();
+#endif /* GL_EXT_shadow_funcs */
+#ifdef GL_EXT_shared_texture_palette
+ _glewInfo_GL_EXT_shared_texture_palette();
+#endif /* GL_EXT_shared_texture_palette */
+#ifdef GL_EXT_stencil_clear_tag
+ _glewInfo_GL_EXT_stencil_clear_tag();
+#endif /* GL_EXT_stencil_clear_tag */
+#ifdef GL_EXT_stencil_two_side
+ _glewInfo_GL_EXT_stencil_two_side();
+#endif /* GL_EXT_stencil_two_side */
+#ifdef GL_EXT_stencil_wrap
+ _glewInfo_GL_EXT_stencil_wrap();
+#endif /* GL_EXT_stencil_wrap */
+#ifdef GL_EXT_subtexture
+ _glewInfo_GL_EXT_subtexture();
+#endif /* GL_EXT_subtexture */
+#ifdef GL_EXT_texture
+ _glewInfo_GL_EXT_texture();
+#endif /* GL_EXT_texture */
+#ifdef GL_EXT_texture3D
+ _glewInfo_GL_EXT_texture3D();
+#endif /* GL_EXT_texture3D */
+#ifdef GL_EXT_texture_array
+ _glewInfo_GL_EXT_texture_array();
+#endif /* GL_EXT_texture_array */
+#ifdef GL_EXT_texture_buffer_object
+ _glewInfo_GL_EXT_texture_buffer_object();
+#endif /* GL_EXT_texture_buffer_object */
+#ifdef GL_EXT_texture_compression_dxt1
+ _glewInfo_GL_EXT_texture_compression_dxt1();
+#endif /* GL_EXT_texture_compression_dxt1 */
+#ifdef GL_EXT_texture_compression_latc
+ _glewInfo_GL_EXT_texture_compression_latc();
+#endif /* GL_EXT_texture_compression_latc */
+#ifdef GL_EXT_texture_compression_rgtc
+ _glewInfo_GL_EXT_texture_compression_rgtc();
+#endif /* GL_EXT_texture_compression_rgtc */
+#ifdef GL_EXT_texture_compression_s3tc
+ _glewInfo_GL_EXT_texture_compression_s3tc();
+#endif /* GL_EXT_texture_compression_s3tc */
+#ifdef GL_EXT_texture_cube_map
+ _glewInfo_GL_EXT_texture_cube_map();
+#endif /* GL_EXT_texture_cube_map */
+#ifdef GL_EXT_texture_edge_clamp
+ _glewInfo_GL_EXT_texture_edge_clamp();
+#endif /* GL_EXT_texture_edge_clamp */
+#ifdef GL_EXT_texture_env
+ _glewInfo_GL_EXT_texture_env();
+#endif /* GL_EXT_texture_env */
+#ifdef GL_EXT_texture_env_add
+ _glewInfo_GL_EXT_texture_env_add();
+#endif /* GL_EXT_texture_env_add */
+#ifdef GL_EXT_texture_env_combine
+ _glewInfo_GL_EXT_texture_env_combine();
+#endif /* GL_EXT_texture_env_combine */
+#ifdef GL_EXT_texture_env_dot3
+ _glewInfo_GL_EXT_texture_env_dot3();
+#endif /* GL_EXT_texture_env_dot3 */
+#ifdef GL_EXT_texture_filter_anisotropic
+ _glewInfo_GL_EXT_texture_filter_anisotropic();
+#endif /* GL_EXT_texture_filter_anisotropic */
+#ifdef GL_EXT_texture_integer
+ _glewInfo_GL_EXT_texture_integer();
+#endif /* GL_EXT_texture_integer */
+#ifdef GL_EXT_texture_lod_bias
+ _glewInfo_GL_EXT_texture_lod_bias();
+#endif /* GL_EXT_texture_lod_bias */
+#ifdef GL_EXT_texture_mirror_clamp
+ _glewInfo_GL_EXT_texture_mirror_clamp();
+#endif /* GL_EXT_texture_mirror_clamp */
+#ifdef GL_EXT_texture_object
+ _glewInfo_GL_EXT_texture_object();
+#endif /* GL_EXT_texture_object */
+#ifdef GL_EXT_texture_perturb_normal
+ _glewInfo_GL_EXT_texture_perturb_normal();
+#endif /* GL_EXT_texture_perturb_normal */
+#ifdef GL_EXT_texture_rectangle
+ _glewInfo_GL_EXT_texture_rectangle();
+#endif /* GL_EXT_texture_rectangle */
+#ifdef GL_EXT_texture_sRGB
+ _glewInfo_GL_EXT_texture_sRGB();
+#endif /* GL_EXT_texture_sRGB */
+#ifdef GL_EXT_texture_shared_exponent
+ _glewInfo_GL_EXT_texture_shared_exponent();
+#endif /* GL_EXT_texture_shared_exponent */
+#ifdef GL_EXT_texture_swizzle
+ _glewInfo_GL_EXT_texture_swizzle();
+#endif /* GL_EXT_texture_swizzle */
+#ifdef GL_EXT_timer_query
+ _glewInfo_GL_EXT_timer_query();
+#endif /* GL_EXT_timer_query */
+#ifdef GL_EXT_transform_feedback
+ _glewInfo_GL_EXT_transform_feedback();
+#endif /* GL_EXT_transform_feedback */
+#ifdef GL_EXT_vertex_array
+ _glewInfo_GL_EXT_vertex_array();
+#endif /* GL_EXT_vertex_array */
+#ifdef GL_EXT_vertex_array_bgra
+ _glewInfo_GL_EXT_vertex_array_bgra();
+#endif /* GL_EXT_vertex_array_bgra */
+#ifdef GL_EXT_vertex_shader
+ _glewInfo_GL_EXT_vertex_shader();
+#endif /* GL_EXT_vertex_shader */
+#ifdef GL_EXT_vertex_weighting
+ _glewInfo_GL_EXT_vertex_weighting();
+#endif /* GL_EXT_vertex_weighting */
+#ifdef GL_GREMEDY_frame_terminator
+ _glewInfo_GL_GREMEDY_frame_terminator();
+#endif /* GL_GREMEDY_frame_terminator */
+#ifdef GL_GREMEDY_string_marker
+ _glewInfo_GL_GREMEDY_string_marker();
+#endif /* GL_GREMEDY_string_marker */
+#ifdef GL_HP_convolution_border_modes
+ _glewInfo_GL_HP_convolution_border_modes();
+#endif /* GL_HP_convolution_border_modes */
+#ifdef GL_HP_image_transform
+ _glewInfo_GL_HP_image_transform();
+#endif /* GL_HP_image_transform */
+#ifdef GL_HP_occlusion_test
+ _glewInfo_GL_HP_occlusion_test();
+#endif /* GL_HP_occlusion_test */
+#ifdef GL_HP_texture_lighting
+ _glewInfo_GL_HP_texture_lighting();
+#endif /* GL_HP_texture_lighting */
+#ifdef GL_IBM_cull_vertex
+ _glewInfo_GL_IBM_cull_vertex();
+#endif /* GL_IBM_cull_vertex */
+#ifdef GL_IBM_multimode_draw_arrays
+ _glewInfo_GL_IBM_multimode_draw_arrays();
+#endif /* GL_IBM_multimode_draw_arrays */
+#ifdef GL_IBM_rasterpos_clip
+ _glewInfo_GL_IBM_rasterpos_clip();
+#endif /* GL_IBM_rasterpos_clip */
+#ifdef GL_IBM_static_data
+ _glewInfo_GL_IBM_static_data();
+#endif /* GL_IBM_static_data */
+#ifdef GL_IBM_texture_mirrored_repeat
+ _glewInfo_GL_IBM_texture_mirrored_repeat();
+#endif /* GL_IBM_texture_mirrored_repeat */
+#ifdef GL_IBM_vertex_array_lists
+ _glewInfo_GL_IBM_vertex_array_lists();
+#endif /* GL_IBM_vertex_array_lists */
+#ifdef GL_INGR_color_clamp
+ _glewInfo_GL_INGR_color_clamp();
+#endif /* GL_INGR_color_clamp */
+#ifdef GL_INGR_interlace_read
+ _glewInfo_GL_INGR_interlace_read();
+#endif /* GL_INGR_interlace_read */
+#ifdef GL_INTEL_parallel_arrays
+ _glewInfo_GL_INTEL_parallel_arrays();
+#endif /* GL_INTEL_parallel_arrays */
+#ifdef GL_INTEL_texture_scissor
+ _glewInfo_GL_INTEL_texture_scissor();
+#endif /* GL_INTEL_texture_scissor */
+#ifdef GL_KTX_buffer_region
+ _glewInfo_GL_KTX_buffer_region();
+#endif /* GL_KTX_buffer_region */
+#ifdef GL_MESAX_texture_stack
+ _glewInfo_GL_MESAX_texture_stack();
+#endif /* GL_MESAX_texture_stack */
+#ifdef GL_MESA_pack_invert
+ _glewInfo_GL_MESA_pack_invert();
+#endif /* GL_MESA_pack_invert */
+#ifdef GL_MESA_resize_buffers
+ _glewInfo_GL_MESA_resize_buffers();
+#endif /* GL_MESA_resize_buffers */
+#ifdef GL_MESA_window_pos
+ _glewInfo_GL_MESA_window_pos();
+#endif /* GL_MESA_window_pos */
+#ifdef GL_MESA_ycbcr_texture
+ _glewInfo_GL_MESA_ycbcr_texture();
+#endif /* GL_MESA_ycbcr_texture */
+#ifdef GL_NV_blend_square
+ _glewInfo_GL_NV_blend_square();
+#endif /* GL_NV_blend_square */
+#ifdef GL_NV_conditional_render
+ _glewInfo_GL_NV_conditional_render();
+#endif /* GL_NV_conditional_render */
+#ifdef GL_NV_copy_depth_to_color
+ _glewInfo_GL_NV_copy_depth_to_color();
+#endif /* GL_NV_copy_depth_to_color */
+#ifdef GL_NV_depth_buffer_float
+ _glewInfo_GL_NV_depth_buffer_float();
+#endif /* GL_NV_depth_buffer_float */
+#ifdef GL_NV_depth_clamp
+ _glewInfo_GL_NV_depth_clamp();
+#endif /* GL_NV_depth_clamp */
+#ifdef GL_NV_depth_range_unclamped
+ _glewInfo_GL_NV_depth_range_unclamped();
+#endif /* GL_NV_depth_range_unclamped */
+#ifdef GL_NV_evaluators
+ _glewInfo_GL_NV_evaluators();
+#endif /* GL_NV_evaluators */
+#ifdef GL_NV_explicit_multisample
+ _glewInfo_GL_NV_explicit_multisample();
+#endif /* GL_NV_explicit_multisample */
+#ifdef GL_NV_fence
+ _glewInfo_GL_NV_fence();
+#endif /* GL_NV_fence */
+#ifdef GL_NV_float_buffer
+ _glewInfo_GL_NV_float_buffer();
+#endif /* GL_NV_float_buffer */
+#ifdef GL_NV_fog_distance
+ _glewInfo_GL_NV_fog_distance();
+#endif /* GL_NV_fog_distance */
+#ifdef GL_NV_fragment_program
+ _glewInfo_GL_NV_fragment_program();
+#endif /* GL_NV_fragment_program */
+#ifdef GL_NV_fragment_program2
+ _glewInfo_GL_NV_fragment_program2();
+#endif /* GL_NV_fragment_program2 */
+#ifdef GL_NV_fragment_program4
+ _glewInfo_GL_NV_fragment_program4();
+#endif /* GL_NV_fragment_program4 */
+#ifdef GL_NV_fragment_program_option
+ _glewInfo_GL_NV_fragment_program_option();
+#endif /* GL_NV_fragment_program_option */
+#ifdef GL_NV_framebuffer_multisample_coverage
+ _glewInfo_GL_NV_framebuffer_multisample_coverage();
+#endif /* GL_NV_framebuffer_multisample_coverage */
+#ifdef GL_NV_geometry_program4
+ _glewInfo_GL_NV_geometry_program4();
+#endif /* GL_NV_geometry_program4 */
+#ifdef GL_NV_geometry_shader4
+ _glewInfo_GL_NV_geometry_shader4();
+#endif /* GL_NV_geometry_shader4 */
+#ifdef GL_NV_gpu_program4
+ _glewInfo_GL_NV_gpu_program4();
+#endif /* GL_NV_gpu_program4 */
+#ifdef GL_NV_half_float
+ _glewInfo_GL_NV_half_float();
+#endif /* GL_NV_half_float */
+#ifdef GL_NV_light_max_exponent
+ _glewInfo_GL_NV_light_max_exponent();
+#endif /* GL_NV_light_max_exponent */
+#ifdef GL_NV_multisample_filter_hint
+ _glewInfo_GL_NV_multisample_filter_hint();
+#endif /* GL_NV_multisample_filter_hint */
+#ifdef GL_NV_occlusion_query
+ _glewInfo_GL_NV_occlusion_query();
+#endif /* GL_NV_occlusion_query */
+#ifdef GL_NV_packed_depth_stencil
+ _glewInfo_GL_NV_packed_depth_stencil();
+#endif /* GL_NV_packed_depth_stencil */
+#ifdef GL_NV_parameter_buffer_object
+ _glewInfo_GL_NV_parameter_buffer_object();
+#endif /* GL_NV_parameter_buffer_object */
+#ifdef GL_NV_pixel_data_range
+ _glewInfo_GL_NV_pixel_data_range();
+#endif /* GL_NV_pixel_data_range */
+#ifdef GL_NV_point_sprite
+ _glewInfo_GL_NV_point_sprite();
+#endif /* GL_NV_point_sprite */
+#ifdef GL_NV_present_video
+ _glewInfo_GL_NV_present_video();
+#endif /* GL_NV_present_video */
+#ifdef GL_NV_primitive_restart
+ _glewInfo_GL_NV_primitive_restart();
+#endif /* GL_NV_primitive_restart */
+#ifdef GL_NV_register_combiners
+ _glewInfo_GL_NV_register_combiners();
+#endif /* GL_NV_register_combiners */
+#ifdef GL_NV_register_combiners2
+ _glewInfo_GL_NV_register_combiners2();
+#endif /* GL_NV_register_combiners2 */
+#ifdef GL_NV_texgen_emboss
+ _glewInfo_GL_NV_texgen_emboss();
+#endif /* GL_NV_texgen_emboss */
+#ifdef GL_NV_texgen_reflection
+ _glewInfo_GL_NV_texgen_reflection();
+#endif /* GL_NV_texgen_reflection */
+#ifdef GL_NV_texture_compression_vtc
+ _glewInfo_GL_NV_texture_compression_vtc();
+#endif /* GL_NV_texture_compression_vtc */
+#ifdef GL_NV_texture_env_combine4
+ _glewInfo_GL_NV_texture_env_combine4();
+#endif /* GL_NV_texture_env_combine4 */
+#ifdef GL_NV_texture_expand_normal
+ _glewInfo_GL_NV_texture_expand_normal();
+#endif /* GL_NV_texture_expand_normal */
+#ifdef GL_NV_texture_rectangle
+ _glewInfo_GL_NV_texture_rectangle();
+#endif /* GL_NV_texture_rectangle */
+#ifdef GL_NV_texture_shader
+ _glewInfo_GL_NV_texture_shader();
+#endif /* GL_NV_texture_shader */
+#ifdef GL_NV_texture_shader2
+ _glewInfo_GL_NV_texture_shader2();
+#endif /* GL_NV_texture_shader2 */
+#ifdef GL_NV_texture_shader3
+ _glewInfo_GL_NV_texture_shader3();
+#endif /* GL_NV_texture_shader3 */
+#ifdef GL_NV_transform_feedback
+ _glewInfo_GL_NV_transform_feedback();
+#endif /* GL_NV_transform_feedback */
+#ifdef GL_NV_vertex_array_range
+ _glewInfo_GL_NV_vertex_array_range();
+#endif /* GL_NV_vertex_array_range */
+#ifdef GL_NV_vertex_array_range2
+ _glewInfo_GL_NV_vertex_array_range2();
+#endif /* GL_NV_vertex_array_range2 */
+#ifdef GL_NV_vertex_program
+ _glewInfo_GL_NV_vertex_program();
+#endif /* GL_NV_vertex_program */
+#ifdef GL_NV_vertex_program1_1
+ _glewInfo_GL_NV_vertex_program1_1();
+#endif /* GL_NV_vertex_program1_1 */
+#ifdef GL_NV_vertex_program2
+ _glewInfo_GL_NV_vertex_program2();
+#endif /* GL_NV_vertex_program2 */
+#ifdef GL_NV_vertex_program2_option
+ _glewInfo_GL_NV_vertex_program2_option();
+#endif /* GL_NV_vertex_program2_option */
+#ifdef GL_NV_vertex_program3
+ _glewInfo_GL_NV_vertex_program3();
+#endif /* GL_NV_vertex_program3 */
+#ifdef GL_NV_vertex_program4
+ _glewInfo_GL_NV_vertex_program4();
+#endif /* GL_NV_vertex_program4 */
+#ifdef GL_OES_byte_coordinates
+ _glewInfo_GL_OES_byte_coordinates();
+#endif /* GL_OES_byte_coordinates */
+#ifdef GL_OES_compressed_paletted_texture
+ _glewInfo_GL_OES_compressed_paletted_texture();
+#endif /* GL_OES_compressed_paletted_texture */
+#ifdef GL_OES_read_format
+ _glewInfo_GL_OES_read_format();
+#endif /* GL_OES_read_format */
+#ifdef GL_OES_single_precision
+ _glewInfo_GL_OES_single_precision();
+#endif /* GL_OES_single_precision */
+#ifdef GL_OML_interlace
+ _glewInfo_GL_OML_interlace();
+#endif /* GL_OML_interlace */
+#ifdef GL_OML_resample
+ _glewInfo_GL_OML_resample();
+#endif /* GL_OML_resample */
+#ifdef GL_OML_subsample
+ _glewInfo_GL_OML_subsample();
+#endif /* GL_OML_subsample */
+#ifdef GL_PGI_misc_hints
+ _glewInfo_GL_PGI_misc_hints();
+#endif /* GL_PGI_misc_hints */
+#ifdef GL_PGI_vertex_hints
+ _glewInfo_GL_PGI_vertex_hints();
+#endif /* GL_PGI_vertex_hints */
+#ifdef GL_REND_screen_coordinates
+ _glewInfo_GL_REND_screen_coordinates();
+#endif /* GL_REND_screen_coordinates */
+#ifdef GL_S3_s3tc
+ _glewInfo_GL_S3_s3tc();
+#endif /* GL_S3_s3tc */
+#ifdef GL_SGIS_color_range
+ _glewInfo_GL_SGIS_color_range();
+#endif /* GL_SGIS_color_range */
+#ifdef GL_SGIS_detail_texture
+ _glewInfo_GL_SGIS_detail_texture();
+#endif /* GL_SGIS_detail_texture */
+#ifdef GL_SGIS_fog_function
+ _glewInfo_GL_SGIS_fog_function();
+#endif /* GL_SGIS_fog_function */
+#ifdef GL_SGIS_generate_mipmap
+ _glewInfo_GL_SGIS_generate_mipmap();
+#endif /* GL_SGIS_generate_mipmap */
+#ifdef GL_SGIS_multisample
+ _glewInfo_GL_SGIS_multisample();
+#endif /* GL_SGIS_multisample */
+#ifdef GL_SGIS_pixel_texture
+ _glewInfo_GL_SGIS_pixel_texture();
+#endif /* GL_SGIS_pixel_texture */
+#ifdef GL_SGIS_point_line_texgen
+ _glewInfo_GL_SGIS_point_line_texgen();
+#endif /* GL_SGIS_point_line_texgen */
+#ifdef GL_SGIS_sharpen_texture
+ _glewInfo_GL_SGIS_sharpen_texture();
+#endif /* GL_SGIS_sharpen_texture */
+#ifdef GL_SGIS_texture4D
+ _glewInfo_GL_SGIS_texture4D();
+#endif /* GL_SGIS_texture4D */
+#ifdef GL_SGIS_texture_border_clamp
+ _glewInfo_GL_SGIS_texture_border_clamp();
+#endif /* GL_SGIS_texture_border_clamp */
+#ifdef GL_SGIS_texture_edge_clamp
+ _glewInfo_GL_SGIS_texture_edge_clamp();
+#endif /* GL_SGIS_texture_edge_clamp */
+#ifdef GL_SGIS_texture_filter4
+ _glewInfo_GL_SGIS_texture_filter4();
+#endif /* GL_SGIS_texture_filter4 */
+#ifdef GL_SGIS_texture_lod
+ _glewInfo_GL_SGIS_texture_lod();
+#endif /* GL_SGIS_texture_lod */
+#ifdef GL_SGIS_texture_select
+ _glewInfo_GL_SGIS_texture_select();
+#endif /* GL_SGIS_texture_select */
+#ifdef GL_SGIX_async
+ _glewInfo_GL_SGIX_async();
+#endif /* GL_SGIX_async */
+#ifdef GL_SGIX_async_histogram
+ _glewInfo_GL_SGIX_async_histogram();
+#endif /* GL_SGIX_async_histogram */
+#ifdef GL_SGIX_async_pixel
+ _glewInfo_GL_SGIX_async_pixel();
+#endif /* GL_SGIX_async_pixel */
+#ifdef GL_SGIX_blend_alpha_minmax
+ _glewInfo_GL_SGIX_blend_alpha_minmax();
+#endif /* GL_SGIX_blend_alpha_minmax */
+#ifdef GL_SGIX_clipmap
+ _glewInfo_GL_SGIX_clipmap();
+#endif /* GL_SGIX_clipmap */
+#ifdef GL_SGIX_convolution_accuracy
+ _glewInfo_GL_SGIX_convolution_accuracy();
+#endif /* GL_SGIX_convolution_accuracy */
+#ifdef GL_SGIX_depth_texture
+ _glewInfo_GL_SGIX_depth_texture();
+#endif /* GL_SGIX_depth_texture */
+#ifdef GL_SGIX_flush_raster
+ _glewInfo_GL_SGIX_flush_raster();
+#endif /* GL_SGIX_flush_raster */
+#ifdef GL_SGIX_fog_offset
+ _glewInfo_GL_SGIX_fog_offset();
+#endif /* GL_SGIX_fog_offset */
+#ifdef GL_SGIX_fog_texture
+ _glewInfo_GL_SGIX_fog_texture();
+#endif /* GL_SGIX_fog_texture */
+#ifdef GL_SGIX_fragment_specular_lighting
+ _glewInfo_GL_SGIX_fragment_specular_lighting();
+#endif /* GL_SGIX_fragment_specular_lighting */
+#ifdef GL_SGIX_framezoom
+ _glewInfo_GL_SGIX_framezoom();
+#endif /* GL_SGIX_framezoom */
+#ifdef GL_SGIX_interlace
+ _glewInfo_GL_SGIX_interlace();
+#endif /* GL_SGIX_interlace */
+#ifdef GL_SGIX_ir_instrument1
+ _glewInfo_GL_SGIX_ir_instrument1();
+#endif /* GL_SGIX_ir_instrument1 */
+#ifdef GL_SGIX_list_priority
+ _glewInfo_GL_SGIX_list_priority();
+#endif /* GL_SGIX_list_priority */
+#ifdef GL_SGIX_pixel_texture
+ _glewInfo_GL_SGIX_pixel_texture();
+#endif /* GL_SGIX_pixel_texture */
+#ifdef GL_SGIX_pixel_texture_bits
+ _glewInfo_GL_SGIX_pixel_texture_bits();
+#endif /* GL_SGIX_pixel_texture_bits */
+#ifdef GL_SGIX_reference_plane
+ _glewInfo_GL_SGIX_reference_plane();
+#endif /* GL_SGIX_reference_plane */
+#ifdef GL_SGIX_resample
+ _glewInfo_GL_SGIX_resample();
+#endif /* GL_SGIX_resample */
+#ifdef GL_SGIX_shadow
+ _glewInfo_GL_SGIX_shadow();
+#endif /* GL_SGIX_shadow */
+#ifdef GL_SGIX_shadow_ambient
+ _glewInfo_GL_SGIX_shadow_ambient();
+#endif /* GL_SGIX_shadow_ambient */
+#ifdef GL_SGIX_sprite
+ _glewInfo_GL_SGIX_sprite();
+#endif /* GL_SGIX_sprite */
+#ifdef GL_SGIX_tag_sample_buffer
+ _glewInfo_GL_SGIX_tag_sample_buffer();
+#endif /* GL_SGIX_tag_sample_buffer */
+#ifdef GL_SGIX_texture_add_env
+ _glewInfo_GL_SGIX_texture_add_env();
+#endif /* GL_SGIX_texture_add_env */
+#ifdef GL_SGIX_texture_coordinate_clamp
+ _glewInfo_GL_SGIX_texture_coordinate_clamp();
+#endif /* GL_SGIX_texture_coordinate_clamp */
+#ifdef GL_SGIX_texture_lod_bias
+ _glewInfo_GL_SGIX_texture_lod_bias();
+#endif /* GL_SGIX_texture_lod_bias */
+#ifdef GL_SGIX_texture_multi_buffer
+ _glewInfo_GL_SGIX_texture_multi_buffer();
+#endif /* GL_SGIX_texture_multi_buffer */
+#ifdef GL_SGIX_texture_range
+ _glewInfo_GL_SGIX_texture_range();
+#endif /* GL_SGIX_texture_range */
+#ifdef GL_SGIX_texture_scale_bias
+ _glewInfo_GL_SGIX_texture_scale_bias();
+#endif /* GL_SGIX_texture_scale_bias */
+#ifdef GL_SGIX_vertex_preclip
+ _glewInfo_GL_SGIX_vertex_preclip();
+#endif /* GL_SGIX_vertex_preclip */
+#ifdef GL_SGIX_vertex_preclip_hint
+ _glewInfo_GL_SGIX_vertex_preclip_hint();
+#endif /* GL_SGIX_vertex_preclip_hint */
+#ifdef GL_SGIX_ycrcb
+ _glewInfo_GL_SGIX_ycrcb();
+#endif /* GL_SGIX_ycrcb */
+#ifdef GL_SGI_color_matrix
+ _glewInfo_GL_SGI_color_matrix();
+#endif /* GL_SGI_color_matrix */
+#ifdef GL_SGI_color_table
+ _glewInfo_GL_SGI_color_table();
+#endif /* GL_SGI_color_table */
+#ifdef GL_SGI_texture_color_table
+ _glewInfo_GL_SGI_texture_color_table();
+#endif /* GL_SGI_texture_color_table */
+#ifdef GL_SUNX_constant_data
+ _glewInfo_GL_SUNX_constant_data();
+#endif /* GL_SUNX_constant_data */
+#ifdef GL_SUN_convolution_border_modes
+ _glewInfo_GL_SUN_convolution_border_modes();
+#endif /* GL_SUN_convolution_border_modes */
+#ifdef GL_SUN_global_alpha
+ _glewInfo_GL_SUN_global_alpha();
+#endif /* GL_SUN_global_alpha */
+#ifdef GL_SUN_mesh_array
+ _glewInfo_GL_SUN_mesh_array();
+#endif /* GL_SUN_mesh_array */
+#ifdef GL_SUN_read_video_pixels
+ _glewInfo_GL_SUN_read_video_pixels();
+#endif /* GL_SUN_read_video_pixels */
+#ifdef GL_SUN_slice_accum
+ _glewInfo_GL_SUN_slice_accum();
+#endif /* GL_SUN_slice_accum */
+#ifdef GL_SUN_triangle_list
+ _glewInfo_GL_SUN_triangle_list();
+#endif /* GL_SUN_triangle_list */
+#ifdef GL_SUN_vertex
+ _glewInfo_GL_SUN_vertex();
+#endif /* GL_SUN_vertex */
+#ifdef GL_WIN_phong_shading
+ _glewInfo_GL_WIN_phong_shading();
+#endif /* GL_WIN_phong_shading */
+#ifdef GL_WIN_specular_fog
+ _glewInfo_GL_WIN_specular_fog();
+#endif /* GL_WIN_specular_fog */
+#ifdef GL_WIN_swap_hint
+ _glewInfo_GL_WIN_swap_hint();
+#endif /* GL_WIN_swap_hint */
+}
+
+/* ------------------------------------------------------------------------ */
+
+#ifdef _WIN32
+
+static void wglewInfo ()
+{
+#ifdef WGL_3DFX_multisample
+ _glewInfo_WGL_3DFX_multisample();
+#endif /* WGL_3DFX_multisample */
+#ifdef WGL_3DL_stereo_control
+ _glewInfo_WGL_3DL_stereo_control();
+#endif /* WGL_3DL_stereo_control */
+#ifdef WGL_ARB_buffer_region
+ _glewInfo_WGL_ARB_buffer_region();
+#endif /* WGL_ARB_buffer_region */
+#ifdef WGL_ARB_create_context
+ _glewInfo_WGL_ARB_create_context();
+#endif /* WGL_ARB_create_context */
+#ifdef WGL_ARB_extensions_string
+ _glewInfo_WGL_ARB_extensions_string();
+#endif /* WGL_ARB_extensions_string */
+#ifdef WGL_ARB_framebuffer_sRGB
+ _glewInfo_WGL_ARB_framebuffer_sRGB();
+#endif /* WGL_ARB_framebuffer_sRGB */
+#ifdef WGL_ARB_make_current_read
+ _glewInfo_WGL_ARB_make_current_read();
+#endif /* WGL_ARB_make_current_read */
+#ifdef WGL_ARB_multisample
+ _glewInfo_WGL_ARB_multisample();
+#endif /* WGL_ARB_multisample */
+#ifdef WGL_ARB_pbuffer
+ _glewInfo_WGL_ARB_pbuffer();
+#endif /* WGL_ARB_pbuffer */
+#ifdef WGL_ARB_pixel_format
+ _glewInfo_WGL_ARB_pixel_format();
+#endif /* WGL_ARB_pixel_format */
+#ifdef WGL_ARB_pixel_format_float
+ _glewInfo_WGL_ARB_pixel_format_float();
+#endif /* WGL_ARB_pixel_format_float */
+#ifdef WGL_ARB_render_texture
+ _glewInfo_WGL_ARB_render_texture();
+#endif /* WGL_ARB_render_texture */
+#ifdef WGL_ATI_pixel_format_float
+ _glewInfo_WGL_ATI_pixel_format_float();
+#endif /* WGL_ATI_pixel_format_float */
+#ifdef WGL_ATI_render_texture_rectangle
+ _glewInfo_WGL_ATI_render_texture_rectangle();
+#endif /* WGL_ATI_render_texture_rectangle */
+#ifdef WGL_EXT_depth_float
+ _glewInfo_WGL_EXT_depth_float();
+#endif /* WGL_EXT_depth_float */
+#ifdef WGL_EXT_display_color_table
+ _glewInfo_WGL_EXT_display_color_table();
+#endif /* WGL_EXT_display_color_table */
+#ifdef WGL_EXT_extensions_string
+ _glewInfo_WGL_EXT_extensions_string();
+#endif /* WGL_EXT_extensions_string */
+#ifdef WGL_EXT_framebuffer_sRGB
+ _glewInfo_WGL_EXT_framebuffer_sRGB();
+#endif /* WGL_EXT_framebuffer_sRGB */
+#ifdef WGL_EXT_make_current_read
+ _glewInfo_WGL_EXT_make_current_read();
+#endif /* WGL_EXT_make_current_read */
+#ifdef WGL_EXT_multisample
+ _glewInfo_WGL_EXT_multisample();
+#endif /* WGL_EXT_multisample */
+#ifdef WGL_EXT_pbuffer
+ _glewInfo_WGL_EXT_pbuffer();
+#endif /* WGL_EXT_pbuffer */
+#ifdef WGL_EXT_pixel_format
+ _glewInfo_WGL_EXT_pixel_format();
+#endif /* WGL_EXT_pixel_format */
+#ifdef WGL_EXT_pixel_format_packed_float
+ _glewInfo_WGL_EXT_pixel_format_packed_float();
+#endif /* WGL_EXT_pixel_format_packed_float */
+#ifdef WGL_EXT_swap_control
+ _glewInfo_WGL_EXT_swap_control();
+#endif /* WGL_EXT_swap_control */
+#ifdef WGL_I3D_digital_video_control
+ _glewInfo_WGL_I3D_digital_video_control();
+#endif /* WGL_I3D_digital_video_control */
+#ifdef WGL_I3D_gamma
+ _glewInfo_WGL_I3D_gamma();
+#endif /* WGL_I3D_gamma */
+#ifdef WGL_I3D_genlock
+ _glewInfo_WGL_I3D_genlock();
+#endif /* WGL_I3D_genlock */
+#ifdef WGL_I3D_image_buffer
+ _glewInfo_WGL_I3D_image_buffer();
+#endif /* WGL_I3D_image_buffer */
+#ifdef WGL_I3D_swap_frame_lock
+ _glewInfo_WGL_I3D_swap_frame_lock();
+#endif /* WGL_I3D_swap_frame_lock */
+#ifdef WGL_I3D_swap_frame_usage
+ _glewInfo_WGL_I3D_swap_frame_usage();
+#endif /* WGL_I3D_swap_frame_usage */
+#ifdef WGL_NV_float_buffer
+ _glewInfo_WGL_NV_float_buffer();
+#endif /* WGL_NV_float_buffer */
+#ifdef WGL_NV_gpu_affinity
+ _glewInfo_WGL_NV_gpu_affinity();
+#endif /* WGL_NV_gpu_affinity */
+#ifdef WGL_NV_present_video
+ _glewInfo_WGL_NV_present_video();
+#endif /* WGL_NV_present_video */
+#ifdef WGL_NV_render_depth_texture
+ _glewInfo_WGL_NV_render_depth_texture();
+#endif /* WGL_NV_render_depth_texture */
+#ifdef WGL_NV_render_texture_rectangle
+ _glewInfo_WGL_NV_render_texture_rectangle();
+#endif /* WGL_NV_render_texture_rectangle */
+#ifdef WGL_NV_swap_group
+ _glewInfo_WGL_NV_swap_group();
+#endif /* WGL_NV_swap_group */
+#ifdef WGL_NV_vertex_array_range
+ _glewInfo_WGL_NV_vertex_array_range();
+#endif /* WGL_NV_vertex_array_range */
+#ifdef WGL_NV_video_output
+ _glewInfo_WGL_NV_video_output();
+#endif /* WGL_NV_video_output */
+#ifdef WGL_OML_sync_control
+ _glewInfo_WGL_OML_sync_control();
+#endif /* WGL_OML_sync_control */
+}
+
+#else /* _UNIX */
+
+static void glxewInfo ()
+{
+#ifdef GLX_VERSION_1_2
+ _glewInfo_GLX_VERSION_1_2();
+#endif /* GLX_VERSION_1_2 */
+#ifdef GLX_VERSION_1_3
+ _glewInfo_GLX_VERSION_1_3();
+#endif /* GLX_VERSION_1_3 */
+#ifdef GLX_VERSION_1_4
+ _glewInfo_GLX_VERSION_1_4();
+#endif /* GLX_VERSION_1_4 */
+#ifdef GLX_3DFX_multisample
+ _glewInfo_GLX_3DFX_multisample();
+#endif /* GLX_3DFX_multisample */
+#ifdef GLX_ARB_create_context
+ _glewInfo_GLX_ARB_create_context();
+#endif /* GLX_ARB_create_context */
+#ifdef GLX_ARB_fbconfig_float
+ _glewInfo_GLX_ARB_fbconfig_float();
+#endif /* GLX_ARB_fbconfig_float */
+#ifdef GLX_ARB_framebuffer_sRGB
+ _glewInfo_GLX_ARB_framebuffer_sRGB();
+#endif /* GLX_ARB_framebuffer_sRGB */
+#ifdef GLX_ARB_get_proc_address
+ _glewInfo_GLX_ARB_get_proc_address();
+#endif /* GLX_ARB_get_proc_address */
+#ifdef GLX_ARB_multisample
+ _glewInfo_GLX_ARB_multisample();
+#endif /* GLX_ARB_multisample */
+#ifdef GLX_ATI_pixel_format_float
+ _glewInfo_GLX_ATI_pixel_format_float();
+#endif /* GLX_ATI_pixel_format_float */
+#ifdef GLX_ATI_render_texture
+ _glewInfo_GLX_ATI_render_texture();
+#endif /* GLX_ATI_render_texture */
+#ifdef GLX_EXT_fbconfig_packed_float
+ _glewInfo_GLX_EXT_fbconfig_packed_float();
+#endif /* GLX_EXT_fbconfig_packed_float */
+#ifdef GLX_EXT_framebuffer_sRGB
+ _glewInfo_GLX_EXT_framebuffer_sRGB();
+#endif /* GLX_EXT_framebuffer_sRGB */
+#ifdef GLX_EXT_import_context
+ _glewInfo_GLX_EXT_import_context();
+#endif /* GLX_EXT_import_context */
+#ifdef GLX_EXT_scene_marker
+ _glewInfo_GLX_EXT_scene_marker();
+#endif /* GLX_EXT_scene_marker */
+#ifdef GLX_EXT_texture_from_pixmap
+ _glewInfo_GLX_EXT_texture_from_pixmap();
+#endif /* GLX_EXT_texture_from_pixmap */
+#ifdef GLX_EXT_visual_info
+ _glewInfo_GLX_EXT_visual_info();
+#endif /* GLX_EXT_visual_info */
+#ifdef GLX_EXT_visual_rating
+ _glewInfo_GLX_EXT_visual_rating();
+#endif /* GLX_EXT_visual_rating */
+#ifdef GLX_MESA_agp_offset
+ _glewInfo_GLX_MESA_agp_offset();
+#endif /* GLX_MESA_agp_offset */
+#ifdef GLX_MESA_copy_sub_buffer
+ _glewInfo_GLX_MESA_copy_sub_buffer();
+#endif /* GLX_MESA_copy_sub_buffer */
+#ifdef GLX_MESA_pixmap_colormap
+ _glewInfo_GLX_MESA_pixmap_colormap();
+#endif /* GLX_MESA_pixmap_colormap */
+#ifdef GLX_MESA_release_buffers
+ _glewInfo_GLX_MESA_release_buffers();
+#endif /* GLX_MESA_release_buffers */
+#ifdef GLX_MESA_set_3dfx_mode
+ _glewInfo_GLX_MESA_set_3dfx_mode();
+#endif /* GLX_MESA_set_3dfx_mode */
+#ifdef GLX_NV_float_buffer
+ _glewInfo_GLX_NV_float_buffer();
+#endif /* GLX_NV_float_buffer */
+#ifdef GLX_NV_present_video
+ _glewInfo_GLX_NV_present_video();
+#endif /* GLX_NV_present_video */
+#ifdef GLX_NV_swap_group
+ _glewInfo_GLX_NV_swap_group();
+#endif /* GLX_NV_swap_group */
+#ifdef GLX_NV_vertex_array_range
+ _glewInfo_GLX_NV_vertex_array_range();
+#endif /* GLX_NV_vertex_array_range */
+#ifdef GLX_NV_video_output
+ _glewInfo_GLX_NV_video_output();
+#endif /* GLX_NV_video_output */
+#ifdef GLX_OML_swap_method
+ _glewInfo_GLX_OML_swap_method();
+#endif /* GLX_OML_swap_method */
+#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#include <inttypes.h>
+ _glewInfo_GLX_OML_sync_control();
+#endif /* GLX_OML_sync_control */
+#ifdef GLX_SGIS_blended_overlay
+ _glewInfo_GLX_SGIS_blended_overlay();
+#endif /* GLX_SGIS_blended_overlay */
+#ifdef GLX_SGIS_color_range
+ _glewInfo_GLX_SGIS_color_range();
+#endif /* GLX_SGIS_color_range */
+#ifdef GLX_SGIS_multisample
+ _glewInfo_GLX_SGIS_multisample();
+#endif /* GLX_SGIS_multisample */
+#ifdef GLX_SGIS_shared_multisample
+ _glewInfo_GLX_SGIS_shared_multisample();
+#endif /* GLX_SGIS_shared_multisample */
+#ifdef GLX_SGIX_fbconfig
+ _glewInfo_GLX_SGIX_fbconfig();
+#endif /* GLX_SGIX_fbconfig */
+#ifdef GLX_SGIX_hyperpipe
+ _glewInfo_GLX_SGIX_hyperpipe();
+#endif /* GLX_SGIX_hyperpipe */
+#ifdef GLX_SGIX_pbuffer
+ _glewInfo_GLX_SGIX_pbuffer();
+#endif /* GLX_SGIX_pbuffer */
+#ifdef GLX_SGIX_swap_barrier
+ _glewInfo_GLX_SGIX_swap_barrier();
+#endif /* GLX_SGIX_swap_barrier */
+#ifdef GLX_SGIX_swap_group
+ _glewInfo_GLX_SGIX_swap_group();
+#endif /* GLX_SGIX_swap_group */
+#ifdef GLX_SGIX_video_resize
+ _glewInfo_GLX_SGIX_video_resize();
+#endif /* GLX_SGIX_video_resize */
+#ifdef GLX_SGIX_visual_select_group
+ _glewInfo_GLX_SGIX_visual_select_group();
+#endif /* GLX_SGIX_visual_select_group */
+#ifdef GLX_SGI_cushion
+ _glewInfo_GLX_SGI_cushion();
+#endif /* GLX_SGI_cushion */
+#ifdef GLX_SGI_make_current_read
+ _glewInfo_GLX_SGI_make_current_read();
+#endif /* GLX_SGI_make_current_read */
+#ifdef GLX_SGI_swap_control
+ _glewInfo_GLX_SGI_swap_control();
+#endif /* GLX_SGI_swap_control */
+#ifdef GLX_SGI_video_sync
+ _glewInfo_GLX_SGI_video_sync();
+#endif /* GLX_SGI_video_sync */
+#ifdef GLX_SUN_get_transparent_index
+ _glewInfo_GLX_SUN_get_transparent_index();
+#endif /* GLX_SUN_get_transparent_index */
+#ifdef GLX_SUN_video_resize
+ _glewInfo_GLX_SUN_video_resize();
+#endif /* GLX_SUN_video_resize */
+}
+
+#endif /* _WIN32 */
+
+/* ------------------------------------------------------------------------ */
+
+#if defined(_WIN32) || !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+int main (int argc, char** argv)
+#else
+int main (void)
+#endif
+{
+ GLuint err;
+
+#if defined(_WIN32) || !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+ char* display = NULL;
+ int visual = -1;
+
+ if (glewParseArgs(argc-1, argv+1, &display, &visual))
+ {
+#if defined(_WIN32)
+ fprintf(stderr, "Usage: glewinfo [-pf <id>]\n");
+#else
+ fprintf(stderr, "Usage: glewinfo [-display <display>] [-visual <id>]\n");
+#endif
+ return 1;
+ }
+#endif
+
+#if defined(_WIN32)
+ if (GL_TRUE == glewCreateContext(&visual))
+#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
+ if (GL_TRUE == glewCreateContext())
+#else
+ if (GL_TRUE == glewCreateContext(display, &visual))
+#endif
+ {
+ fprintf(stderr, "Error: glewCreateContext failed\n");
+ glewDestroyContext();
+ return 1;
+ }
+ glewExperimental = GL_TRUE;
+#ifdef GLEW_MX
+ err = glewContextInit(glewGetContext());
+#ifdef _WIN32
+ err = err || wglewContextInit(wglewGetContext());
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+ err = err || glxewContextInit(glxewGetContext());
+#endif
+
+#else
+ err = glewInit();
+#endif
+ if (GLEW_OK != err)
+ {
+ fprintf(stderr, "Error [main]: glewInit failed: %s\n", glewGetErrorString(err));
+ glewDestroyContext();
+ return 1;
+ }
+#if defined(_WIN32)
+ f = fopen("glewinfo.txt", "w");
+ if (f == NULL) f = stdout;
+#else
+ f = stdout;
+#endif
+ fprintf(f, "---------------------------\n");
+ fprintf(f, " GLEW Extension Info\n");
+ fprintf(f, "---------------------------\n\n");
+ fprintf(f, "GLEW version %s\n", glewGetString(GLEW_VERSION));
+#if defined(_WIN32)
+ fprintf(f, "Reporting capabilities of pixelformat %d\n", visual);
+#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+ fprintf(f, "Reporting capabilities of display %s, visual 0x%x\n",
+ display == NULL ? getenv("DISPLAY") : display, visual);
+#endif
+ fprintf(f, "Running on a %s from %s\n",
+ glGetString(GL_RENDERER), glGetString(GL_VENDOR));
+ fprintf(f, "OpenGL version %s is supported\n", glGetString(GL_VERSION));
+ glewInfo();
+#if defined(_WIN32)
+ wglewInfo();
+#else
+ glxewInfo();
+#endif
+ if (f != stdout) fclose(f);
+ glewDestroyContext();
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if defined(_WIN32) || !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+GLboolean glewParseArgs (int argc, char** argv, char** display, int* visual)
+{
+ int p = 0;
+ while (p < argc)
+ {
+#if defined(_WIN32)
+ if (!strcmp(argv[p], "-pf") || !strcmp(argv[p], "-pixelformat"))
+ {
+ if (++p >= argc) return GL_TRUE;
+ *display = 0;
+ *visual = strtol(argv[p++], NULL, 0);
+ }
+ else
+ return GL_TRUE;
+#else
+ if (!strcmp(argv[p], "-display"))
+ {
+ if (++p >= argc) return GL_TRUE;
+ *display = argv[p++];
+ }
+ else if (!strcmp(argv[p], "-visual"))
+ {
+ if (++p >= argc) return GL_TRUE;
+ *visual = (int)strtol(argv[p++], NULL, 0);
+ }
+ else
+ return GL_TRUE;
+#endif
+ }
+ return GL_FALSE;
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+#if defined(_WIN32)
+
+HWND wnd = NULL;
+HDC dc = NULL;
+HGLRC rc = NULL;
+
+GLboolean glewCreateContext (int* pixelformat)
+{
+ WNDCLASS wc;
+ PIXELFORMATDESCRIPTOR pfd;
+ /* register window class */
+ ZeroMemory(&wc, sizeof(WNDCLASS));
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.lpfnWndProc = DefWindowProc;
+ wc.lpszClassName = "GLEW";
+ if (0 == RegisterClass(&wc)) return GL_TRUE;
+ /* create window */
+ wnd = CreateWindow("GLEW", "GLEW", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL);
+ if (NULL == wnd) return GL_TRUE;
+ /* get the device context */
+ dc = GetDC(wnd);
+ if (NULL == dc) return GL_TRUE;
+ /* find pixel format */
+ ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
+ if (*pixelformat == -1) /* find default */
+ {
+ pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ *pixelformat = ChoosePixelFormat(dc, &pfd);
+ if (*pixelformat == 0) return GL_TRUE;
+ }
+ /* set the pixel format for the dc */
+ if (FALSE == SetPixelFormat(dc, *pixelformat, &pfd)) return GL_TRUE;
+ /* create rendering context */
+ rc = wglCreateContext(dc);
+ if (NULL == rc) return GL_TRUE;
+ if (FALSE == wglMakeCurrent(dc, rc)) return GL_TRUE;
+ return GL_FALSE;
+}
+
+void glewDestroyContext ()
+{
+ if (NULL != rc) wglMakeCurrent(NULL, NULL);
+ if (NULL != rc) wglDeleteContext(wglGetCurrentContext());
+ if (NULL != wnd && NULL != dc) ReleaseDC(wnd, dc);
+ if (NULL != wnd) DestroyWindow(wnd);
+ UnregisterClass("GLEW", GetModuleHandle(NULL));
+}
+
+/* ------------------------------------------------------------------------ */
+
+#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
+
+#include <AGL/agl.h>
+
+AGLContext ctx, octx;
+
+GLboolean glewCreateContext ()
+{
+ int attrib[] = { AGL_RGBA, AGL_NONE };
+ AGLPixelFormat pf;
+ /*int major, minor;
+ SetPortWindowPort(wnd);
+ aglGetVersion(&major, &minor);
+ fprintf(stderr, "GL %d.%d\n", major, minor);*/
+ pf = aglChoosePixelFormat(NULL, 0, attrib);
+ if (NULL == pf) return GL_TRUE;
+ ctx = aglCreateContext(pf, NULL);
+ if (NULL == ctx || AGL_NO_ERROR != aglGetError()) return GL_TRUE;
+ aglDestroyPixelFormat(pf);
+ /*aglSetDrawable(ctx, GetWindowPort(wnd));*/
+ octx = aglGetCurrentContext();
+ if (NULL == aglSetCurrentContext(ctx)) return GL_TRUE;
+ return GL_FALSE;
+}
+
+void glewDestroyContext ()
+{
+ aglSetCurrentContext(octx);
+ if (NULL != ctx) aglDestroyContext(ctx);
+}
+
+/* ------------------------------------------------------------------------ */
+
+#else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */
+
+Display* dpy = NULL;
+XVisualInfo* vi = NULL;
+XVisualInfo* vis = NULL;
+GLXContext ctx = NULL;
+Window wnd = 0;
+Colormap cmap = 0;
+
+GLboolean glewCreateContext (const char* display, int* visual)
+{
+ int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
+ int erb, evb;
+ XSetWindowAttributes swa;
+ /* open display */
+ dpy = XOpenDisplay(display);
+ if (NULL == dpy) return GL_TRUE;
+ /* query for glx */
+ if (!glXQueryExtension(dpy, &erb, &evb)) return GL_TRUE;
+ /* choose visual */
+ if (*visual == -1)
+ {
+ vi = glXChooseVisual(dpy, DefaultScreen(dpy), attrib);
+ if (NULL == vi) return GL_TRUE;
+ *visual = (int)XVisualIDFromVisual(vi->visual);
+ }
+ else
+ {
+ int n_vis, i;
+ vis = XGetVisualInfo(dpy, 0, NULL, &n_vis);
+ for (i=0; i<n_vis; i++)
+ {
+ if ((int)XVisualIDFromVisual(vis[i].visual) == *visual)
+ vi = &vis[i];
+ }
+ if (vi == NULL) return GL_TRUE;
+ }
+ /* create context */
+ ctx = glXCreateContext(dpy, vi, None, True);
+ if (NULL == ctx) return GL_TRUE;
+ /* create window */
+ /*wnd = XCreateSimpleWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 1, 1, 1, 0, 0);*/
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ swa.border_pixel = 0;
+ swa.colormap = cmap;
+ wnd = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+ 0, 0, 1, 1, 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel | CWColormap, &swa);
+ /* make context current */
+ if (!glXMakeCurrent(dpy, wnd, ctx)) return GL_TRUE;
+ return GL_FALSE;
+}
+
+void glewDestroyContext ()
+{
+ if (NULL != dpy && NULL != ctx) glXDestroyContext(dpy, ctx);
+ if (NULL != dpy && 0 != wnd) XDestroyWindow(dpy, wnd);
+ if (NULL != dpy && 0 != cmap) XFreeColormap(dpy, cmap);
+ if (NULL != vis)
+ XFree(vis);
+ else if (NULL != vi)
+ XFree(vi);
+ if (NULL != dpy) XCloseDisplay(dpy);
+}
+
+#endif /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */
diff --git a/src/glew/visualinfo.c b/src/glew/visualinfo.c
new file mode 100644
index 0000000000..384313df22
--- /dev/null
+++ b/src/glew/visualinfo.c
@@ -0,0 +1,1173 @@
+/*
+** visualinfo.c
+**
+** Copyright (C) Nate Robins, 1997
+** Michael Wimmer, 1999
+** Milan Ikits, 2002-2008
+**
+** visualinfo is a small utility that displays all available visuals,
+** aka. pixelformats, in an OpenGL system along with renderer version
+** information. It shows a table of all the visuals that support OpenGL
+** along with their capabilities. The format of the table is similar to
+** that of glxinfo on Unix systems:
+**
+** visual ~= pixel format descriptor
+** id = visual id (integer from 1 - max visuals)
+** tp = type (wn: window, pb: pbuffer, wp: window & pbuffer, bm: bitmap)
+** ac = acceleration (ge: generic, fu: full, no: none)
+** fm = format (i: integer, f: float, c: color index)
+** db = double buffer (y = yes)
+** sw = swap method (x: exchange, c: copy, u: undefined)
+** st = stereo (y = yes)
+** sz = total # bits
+** r = # bits of red
+** g = # bits of green
+** b = # bits of blue
+** a = # bits of alpha
+** axbf = # aux buffers
+** dpth = # bits of depth
+** stcl = # bits of stencil
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <GL/glew.h>
+#if defined(_WIN32)
+#include <GL/wglew.h>
+#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
+#include <AGL/agl.h>
+#else
+#include <GL/glxew.h>
+#endif
+
+#ifdef GLEW_MX
+GLEWContext _glewctx;
+# define glewGetContext() (&_glewctx)
+# ifdef _WIN32
+WGLEWContext _wglewctx;
+# define wglewGetContext() (&_wglewctx)
+# elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+GLXEWContext _glxewctx;
+# define glxewGetContext() (&_glxewctx)
+# endif
+#endif /* GLEW_MX */
+
+typedef struct GLContextStruct
+{
+#ifdef _WIN32
+ HWND wnd;
+ HDC dc;
+ HGLRC rc;
+#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
+ AGLContext ctx, octx;
+#else
+ Display* dpy;
+ XVisualInfo* vi;
+ GLXContext ctx;
+ Window wnd;
+ Colormap cmap;
+#endif
+} GLContext;
+
+void InitContext (GLContext* ctx);
+GLboolean CreateContext (GLContext* ctx);
+void DestroyContext (GLContext* ctx);
+void VisualInfo (GLContext* ctx);
+void PrintExtensions (const char* s);
+GLboolean ParseArgs (int argc, char** argv);
+
+int showall = 0;
+int displaystdout = 0;
+int verbose = 0;
+int drawableonly = 0;
+
+char* display = NULL;
+int visual = -1;
+
+FILE* file = 0;
+GLContext ctx;
+
+int
+main (int argc, char** argv)
+{
+ GLenum err;
+
+ /* ---------------------------------------------------------------------- */
+ /* parse arguments */
+ if (GL_TRUE == ParseArgs(argc-1, argv+1))
+ {
+#if defined(_WIN32)
+ fprintf(stderr, "Usage: visualinfo [-a] [-s] [-h] [-pf <id>]\n");
+ fprintf(stderr, " -a: show all visuals\n");
+ fprintf(stderr, " -s: display to stdout instead of visualinfo.txt\n");
+ fprintf(stderr, " -pf <id>: use given pixelformat\n");
+ fprintf(stderr, " -h: this screen\n");
+#else
+ fprintf(stderr, "Usage: visualinfo [-h] [-display <display>] [-visual <id>]\n");
+ fprintf(stderr, " -h: this screen\n");
+ fprintf(stderr, " -display <display>: use given display\n");
+ fprintf(stderr, " -visual <id>: use given visual\n");
+#endif
+ return 1;
+ }
+
+ /* ---------------------------------------------------------------------- */
+ /* create OpenGL rendering context */
+ InitContext(&ctx);
+ if (GL_TRUE == CreateContext(&ctx))
+ {
+ fprintf(stderr, "Error: CreateContext failed\n");
+ DestroyContext(&ctx);
+ return 1;
+ }
+
+ /* ---------------------------------------------------------------------- */
+ /* initialize GLEW */
+ glewExperimental = GL_TRUE;
+#ifdef GLEW_MX
+ err = glewContextInit(glewGetContext());
+# ifdef _WIN32
+ err = err || wglewContextInit(wglewGetContext());
+# elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX)
+ err = err || glxewContextInit(glxewGetContext());
+# endif
+#else
+ err = glewInit();
+#endif
+ if (GLEW_OK != err)
+ {
+ fprintf(stderr, "Error [main]: glewInit failed: %s\n", glewGetErrorString(err));
+ DestroyContext(&ctx);
+ return 1;
+ }
+
+ /* ---------------------------------------------------------------------- */
+ /* open file */
+#if defined(_WIN32)
+ if (!displaystdout)
+ file = fopen("visualinfo.txt", "w");
+ if (file == NULL)
+ file = stdout;
+#else
+ file = stdout;
+#endif
+
+ /* ---------------------------------------------------------------------- */
+ /* output header information */
+ /* OpenGL extensions */
+ fprintf(file, "OpenGL vendor string: %s\n", glGetString(GL_VENDOR));
+ fprintf(file, "OpenGL renderer string: %s\n", glGetString(GL_RENDERER));
+ fprintf(file, "OpenGL version string: %s\n", glGetString(GL_VERSION));
+ fprintf(file, "OpenGL extensions (GL_): \n");
+ PrintExtensions((char*)glGetString(GL_EXTENSIONS));
+ /* GLU extensions */
+ fprintf(file, "GLU version string: %s\n", gluGetString(GLU_VERSION));
+ fprintf(file, "GLU extensions (GLU_): \n");
+ PrintExtensions((char*)gluGetString(GLU_EXTENSIONS));
+
+ /* ---------------------------------------------------------------------- */
+ /* extensions string */
+#if defined(_WIN32)
+ /* WGL extensions */
+ if (WGLEW_ARB_extensions_string || WGLEW_EXT_extensions_string)
+ {
+ fprintf(file, "WGL extensions (WGL_): \n");
+ PrintExtensions(wglGetExtensionsStringARB ?
+ (char*)wglGetExtensionsStringARB(ctx.dc) :
+ (char*)wglGetExtensionsStringEXT());
+ }
+#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
+
+#else
+ /* GLX extensions */
+ fprintf(file, "GLX extensions (GLX_): \n");
+ PrintExtensions(glXQueryExtensionsString(glXGetCurrentDisplay(),
+ DefaultScreen(glXGetCurrentDisplay())));
+#endif
+
+ /* ---------------------------------------------------------------------- */
+ /* enumerate all the formats */
+ VisualInfo(&ctx);
+
+ /* ---------------------------------------------------------------------- */
+ /* release resources */
+ DestroyContext(&ctx);
+ if (file != stdout)
+ fclose(file);
+ return 0;
+}
+
+/* do the magic to separate all extensions with comma's, except
+ for the last one that _may_ terminate in a space. */
+void PrintExtensions (const char* s)
+{
+ char t[80];
+ int i=0;
+ char* p=0;
+
+ t[79] = '\0';
+ while (*s)
+ {
+ t[i++] = *s;
+ if(*s == ' ')
+ {
+ if (*(s+1) != '\0') {
+ t[i-1] = ',';
+ t[i] = ' ';
+ p = &t[i++];
+ }
+ else /* zoinks! last one terminated in a space! */
+ {
+ t[i-1] = '\0';
+ }
+ }
+ if(i > 80 - 5)
+ {
+ *p = t[i] = '\0';
+ fprintf(file, " %s\n", t);
+ p++;
+ i = (int)strlen(p);
+ strcpy(t, p);
+ }
+ s++;
+ }
+ t[i] = '\0';
+ fprintf(file, " %s.\n", t);
+}
+
+/* ---------------------------------------------------------------------- */
+
+#if defined(_WIN32)
+
+void
+VisualInfoARB (GLContext* ctx)
+{
+ int attrib[32], value[32], n_attrib, n_pbuffer=0, n_float=0;
+ int i, pf, maxpf;
+ unsigned int c;
+
+ /* to get pbuffer capable pixel formats */
+ attrib[0] = WGL_DRAW_TO_PBUFFER_ARB;
+ attrib[1] = GL_TRUE;
+ attrib[2] = 0;
+ wglChoosePixelFormatARB(ctx->dc, attrib, 0, 1, &pf, &c);
+ /* query number of pixel formats */
+ attrib[0] = WGL_NUMBER_PIXEL_FORMATS_ARB;
+ wglGetPixelFormatAttribivARB(ctx->dc, 0, 0, 1, attrib, value);
+ maxpf = value[0];
+ for (i=0; i<32; i++)
+ value[i] = 0;
+
+ attrib[0] = WGL_SUPPORT_OPENGL_ARB;
+ attrib[1] = WGL_DRAW_TO_WINDOW_ARB;
+ attrib[2] = WGL_DRAW_TO_BITMAP_ARB;
+ attrib[3] = WGL_ACCELERATION_ARB;
+ /* WGL_NO_ACCELERATION_ARB, WGL_GENERIC_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB */
+ attrib[4] = WGL_SWAP_METHOD_ARB;
+ /* WGL_SWAP_EXCHANGE_ARB, WGL_SWAP_COPY_ARB, WGL_SWAP_UNDEFINED_ARB */
+ attrib[5] = WGL_DOUBLE_BUFFER_ARB;
+ attrib[6] = WGL_STEREO_ARB;
+ attrib[7] = WGL_PIXEL_TYPE_ARB;
+ /* WGL_TYPE_RGBA_ARB, WGL_TYPE_COLORINDEX_ARB,
+ WGL_TYPE_RGBA_FLOAT_ATI (WGL_ATI_pixel_format_float) */
+ /* Color buffer information */
+ attrib[8] = WGL_COLOR_BITS_ARB;
+ attrib[9] = WGL_RED_BITS_ARB;
+ attrib[10] = WGL_GREEN_BITS_ARB;
+ attrib[11] = WGL_BLUE_BITS_ARB;
+ attrib[12] = WGL_ALPHA_BITS_ARB;
+ /* Accumulation buffer information */
+ attrib[13] = WGL_ACCUM_BITS_ARB;
+ attrib[14] = WGL_ACCUM_RED_BITS_ARB;
+ attrib[15] = WGL_ACCUM_GREEN_BITS_ARB;
+ attrib[16] = WGL_ACCUM_BLUE_BITS_ARB;
+ attrib[17] = WGL_ACCUM_ALPHA_BITS_ARB;
+ /* Depth, stencil, and aux buffer information */
+ attrib[18] = WGL_DEPTH_BITS_ARB;
+ attrib[19] = WGL_STENCIL_BITS_ARB;
+ attrib[20] = WGL_AUX_BUFFERS_ARB;
+ /* Layer information */
+ attrib[21] = WGL_NUMBER_OVERLAYS_ARB;
+ attrib[22] = WGL_NUMBER_UNDERLAYS_ARB;
+ attrib[23] = WGL_SWAP_LAYER_BUFFERS_ARB;
+ attrib[24] = WGL_SAMPLES_ARB;
+ attrib[25] = WGL_SUPPORT_GDI_ARB;
+ n_attrib = 26;
+ if (WGLEW_ARB_pbuffer)
+ {
+ attrib[n_attrib] = WGL_DRAW_TO_PBUFFER_ARB;
+ n_pbuffer = n_attrib;
+ n_attrib++;
+ }
+ if (WGLEW_NV_float_buffer)
+ {
+ attrib[n_attrib] = WGL_FLOAT_COMPONENTS_NV;
+ n_float = n_attrib;
+ n_attrib++;
+ }
+
+ if (!verbose)
+ {
+ /* print table header */
+ fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n");
+ fprintf(file, " | | visual | color | ax dp st | accum | layer |\n");
+ fprintf(file, " | id | tp ac gd fm db sw st ms | sz r g b a | bf th cl | sz r g b a | ov un sw |\n");
+ fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n");
+ /* loop through all the pixel formats */
+ for(i = 1; i <= maxpf; i++)
+ {
+ wglGetPixelFormatAttribivARB(ctx->dc, i, 0, n_attrib, attrib, value);
+ /* only describe this format if it supports OpenGL */
+ if (!value[0]) continue;
+ /* by default show only fully accelerated window or pbuffer capable visuals */
+ if (!showall
+ && ((value[2] && !value[1])
+ || (!WGLEW_ARB_pbuffer || !value[n_pbuffer])
+ || (value[3] != WGL_FULL_ACCELERATION_ARB))) continue;
+ /* print out the information for this visual */
+ /* visual id */
+ fprintf(file, " |% 4d | ", i);
+ /* visual type */
+ if (value[1])
+ {
+ if (WGLEW_ARB_pbuffer && value[n_pbuffer]) fprintf(file, "wp ");
+ else fprintf(file, "wn ");
+ }
+ else
+ {
+ if (value[2]) fprintf(file, "bm ");
+ else if (WGLEW_ARB_pbuffer && value[n_pbuffer]) fprintf(file, "pb ");
+ }
+ /* acceleration */
+ fprintf(file, "%s ", value[3] == WGL_FULL_ACCELERATION_ARB ? "fu" :
+ value[3] == WGL_GENERIC_ACCELERATION_ARB ? "ge" :
+ value[3] == WGL_NO_ACCELERATION_ARB ? "no" : ". ");
+ /* gdi support */
+ fprintf(file, " %c ", value[25] ? 'y' : '.');
+ /* format */
+ if (WGLEW_NV_float_buffer && value[n_float]) fprintf(file, " f ");
+ else if (WGLEW_ATI_pixel_format_float && value[7] == WGL_TYPE_RGBA_FLOAT_ATI) fprintf(file, " f ");
+ else if (value[7] == WGL_TYPE_RGBA_ARB) fprintf(file, " i ");
+ else if (value[7] == WGL_TYPE_COLORINDEX_ARB) fprintf(file, " c ");
+ /* double buffer */
+ fprintf(file, " %c ", value[5] ? 'y' : '.');
+ /* swap method */
+ if (value[4] == WGL_SWAP_EXCHANGE_ARB) fprintf(file, " x ");
+ else if (value[4] == WGL_SWAP_COPY_ARB) fprintf(file, " c ");
+ else if (value[4] == WGL_SWAP_UNDEFINED_ARB) fprintf(file, " . ");
+ else fprintf(file, " . ");
+ /* stereo */
+ fprintf(file, " %c ", value[6] ? 'y' : '.');
+ /* multisample */
+ if (value[24] > 0)
+ fprintf(file, "%2d | ", value[24]);
+ else
+ fprintf(file, " . | ");
+ /* color size */
+ if (value[8]) fprintf(file, "%3d ", value[8]);
+ else fprintf(file, " . ");
+ /* red */
+ if (value[9]) fprintf(file, "%2d ", value[9]);
+ else fprintf(file, " . ");
+ /* green */
+ if (value[10]) fprintf(file, "%2d ", value[10]);
+ else fprintf(file, " . ");
+ /* blue */
+ if (value[11]) fprintf(file, "%2d ", value[11]);
+ else fprintf(file, " . ");
+ /* alpha */
+ if (value[12]) fprintf(file, "%2d | ", value[12]);
+ else fprintf(file, " . | ");
+ /* aux buffers */
+ if (value[20]) fprintf(file, "%2d ", value[20]);
+ else fprintf(file, " . ");
+ /* depth */
+ if (value[18]) fprintf(file, "%2d ", value[18]);
+ else fprintf(file, " . ");
+ /* stencil */
+ if (value[19]) fprintf(file, "%2d | ", value[19]);
+ else fprintf(file, " . | ");
+ /* accum size */
+ if (value[13]) fprintf(file, "%3d ", value[13]);
+ else fprintf(file, " . ");
+ /* accum red */
+ if (value[14]) fprintf(file, "%2d ", value[14]);
+ else fprintf(file, " . ");
+ /* accum green */
+ if (value[15]) fprintf(file, "%2d ", value[15]);
+ else fprintf(file, " . ");
+ /* accum blue */
+ if (value[16]) fprintf(file, "%2d ", value[16]);
+ else fprintf(file, " . ");
+ /* accum alpha */
+ if (value[17]) fprintf(file, "%2d | ", value[17]);
+ else fprintf(file, " . | ");
+ /* overlay */
+ if (value[21]) fprintf(file, "%2d ", value[21]);
+ else fprintf(file, " . ");
+ /* underlay */
+ if (value[22]) fprintf(file, "%2d ", value[22]);
+ else fprintf(file, " . ");
+ /* layer swap */
+ if (value[23]) fprintf(file, "y ");
+ else fprintf(file, " . ");
+ fprintf(file, "|\n");
+ }
+ /* print table footer */
+ fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n");
+ fprintf(file, " | | visual | color | ax dp st | accum | layer |\n");
+ fprintf(file, " | id | tp ac gd fm db sw st ms | sz r g b a | bf th cl | sz r g b a | ov un sw |\n");
+ fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n");
+ }
+ else /* verbose */
+ {
+#if 0
+ fprintf(file, "\n");
+ /* loop through all the pixel formats */
+ for(i = 1; i <= maxpf; i++)
+ {
+ DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+ /* only describe this format if it supports OpenGL */
+ if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL)
+ || (drawableonly && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))) continue;
+ fprintf(file, "Visual ID: %2d depth=%d class=%s\n", i, pfd.cDepthBits,
+ pfd.cColorBits <= 8 ? "PseudoColor" : "TrueColor");
+ fprintf(file, " bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n", pfd.cColorBits, pfd.bReserved, pfd.iPixelType == PFD_TYPE_RGBA ? "rgba" : "ci", pfd.dwFlags & PFD_DOUBLEBUFFER, pfd.dwFlags & PFD_STEREO);
+ fprintf(file, " generic=%d generic accelerated=%d\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) == PFD_GENERIC_FORMAT, (pfd.dwFlags & PFD_GENERIC_ACCELERATED) == PFD_GENERIC_ACCELERATED);
+ fprintf(file, " rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits);
+ fprintf(file, " auxBuffers=%d depthSize=%d stencilSize=%d\n", pfd.cAuxBuffers, pfd.cDepthBits, pfd.cStencilBits);
+ fprintf(file, " accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cAccumRedBits, pfd.cAccumGreenBits, pfd.cAccumBlueBits, pfd.cAccumAlphaBits);
+ fprintf(file, " multiSample=%d multisampleBuffers=%d\n", 0, 0);
+ fprintf(file, " Opaque.\n");
+ }
+#endif
+ }
+}
+
+void
+VisualInfoGDI (GLContext* ctx)
+{
+ int i, maxpf;
+ PIXELFORMATDESCRIPTOR pfd;
+
+ /* calling DescribePixelFormat() with NULL pfd (!!!) return maximum
+ number of pixel formats */
+ maxpf = DescribePixelFormat(ctx->dc, 1, 0, NULL);
+
+ if (!verbose)
+ {
+ fprintf(file, "-----------------------------------------------------------------------------\n");
+ fprintf(file, " visual x bf lv rg d st ge ge r g b a ax dp st accum buffs ms \n");
+ fprintf(file, " id dep tp sp sz l ci b ro ne ac sz sz sz sz bf th cl sz r g b a ns b\n");
+ fprintf(file, "-----------------------------------------------------------------------------\n");
+
+ /* loop through all the pixel formats */
+ for(i = 1; i <= maxpf; i++)
+ {
+ DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+ /* only describe this format if it supports OpenGL */
+ if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL)
+ || (drawableonly && (pfd.dwFlags & PFD_DRAW_TO_BITMAP))) continue;
+ /* other criteria could be tested here for actual pixel format
+ choosing in an application:
+
+ for (...each pixel format...) {
+ if (pfd.dwFlags & PFD_SUPPORT_OPENGL &&
+ pfd.dwFlags & PFD_DOUBLEBUFFER &&
+ pfd.cDepthBits >= 24 &&
+ pfd.cColorBits >= 24)
+ {
+ goto found;
+ }
+ }
+ ... not found so exit ...
+ found:
+ ... found so use it ...
+ */
+ /* print out the information for this pixel format */
+ fprintf(file, "0x%02x ", i);
+ fprintf(file, "%3d ", pfd.cColorBits);
+ if(pfd.dwFlags & PFD_DRAW_TO_WINDOW) fprintf(file, "wn ");
+ else if(pfd.dwFlags & PFD_DRAW_TO_BITMAP) fprintf(file, "bm ");
+ else fprintf(file, "pb ");
+ /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
+ fprintf(file, " . ");
+ fprintf(file, "%3d ", pfd.cColorBits);
+ /* bReserved field indicates number of over/underlays */
+ if(pfd.bReserved) fprintf(file, " %d ", pfd.bReserved);
+ else fprintf(file, " . ");
+ fprintf(file, " %c ", pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
+ fprintf(file, "%c ", pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
+ fprintf(file, " %c ", pfd.dwFlags & PFD_STEREO ? 'y' : '.');
+ /* added: */
+ fprintf(file, " %c ", pfd.dwFlags & PFD_GENERIC_FORMAT ? 'y' : '.');
+ fprintf(file, " %c ", pfd.dwFlags & PFD_GENERIC_ACCELERATED ? 'y' : '.');
+ if(pfd.cRedBits && pfd.iPixelType == PFD_TYPE_RGBA)
+ fprintf(file, "%2d ", pfd.cRedBits);
+ else fprintf(file, " . ");
+ if(pfd.cGreenBits && pfd.iPixelType == PFD_TYPE_RGBA)
+ fprintf(file, "%2d ", pfd.cGreenBits);
+ else fprintf(file, " . ");
+ if(pfd.cBlueBits && pfd.iPixelType == PFD_TYPE_RGBA)
+ fprintf(file, "%2d ", pfd.cBlueBits);
+ else fprintf(file, " . ");
+ if(pfd.cAlphaBits && pfd.iPixelType == PFD_TYPE_RGBA)
+ fprintf(file, "%2d ", pfd.cAlphaBits);
+ else fprintf(file, " . ");
+ if(pfd.cAuxBuffers) fprintf(file, "%2d ", pfd.cAuxBuffers);
+ else fprintf(file, " . ");
+ if(pfd.cDepthBits) fprintf(file, "%2d ", pfd.cDepthBits);
+ else fprintf(file, " . ");
+ if(pfd.cStencilBits) fprintf(file, "%2d ", pfd.cStencilBits);
+ else fprintf(file, " . ");
+ if(pfd.cAccumBits) fprintf(file, "%3d ", pfd.cAccumBits);
+ else fprintf(file, " . ");
+ if(pfd.cAccumRedBits) fprintf(file, "%2d ", pfd.cAccumRedBits);
+ else fprintf(file, " . ");
+ if(pfd.cAccumGreenBits) fprintf(file, "%2d ", pfd.cAccumGreenBits);
+ else fprintf(file, " . ");
+ if(pfd.cAccumBlueBits) fprintf(file, "%2d ", pfd.cAccumBlueBits);
+ else fprintf(file, " . ");
+ if(pfd.cAccumAlphaBits) fprintf(file, "%2d ", pfd.cAccumAlphaBits);
+ else fprintf(file, " . ");
+ /* no multisample in win32 */
+ fprintf(file, " . .\n");
+ }
+ /* print table footer */
+ fprintf(file, "-----------------------------------------------------------------------------\n");
+ fprintf(file, " visual x bf lv rg d st ge ge r g b a ax dp st accum buffs ms \n");
+ fprintf(file, " id dep tp sp sz l ci b ro ne ac sz sz sz sz bf th cl sz r g b a ns b\n");
+ fprintf(file, "-----------------------------------------------------------------------------\n");
+ }
+ else /* verbose */
+ {
+ fprintf(file, "\n");
+ /* loop through all the pixel formats */
+ for(i = 1; i <= maxpf; i++)
+ {
+ DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+ /* only describe this format if it supports OpenGL */
+ if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL)
+ || (drawableonly && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))) continue;
+ fprintf(file, "Visual ID: %2d depth=%d class=%s\n", i, pfd.cDepthBits,
+ pfd.cColorBits <= 8 ? "PseudoColor" : "TrueColor");
+ fprintf(file, " bufferSize=%d level=%d renderType=%s doubleBuffer=%ld stereo=%ld\n", pfd.cColorBits, pfd.bReserved, pfd.iPixelType == PFD_TYPE_RGBA ? "rgba" : "ci", pfd.dwFlags & PFD_DOUBLEBUFFER, pfd.dwFlags & PFD_STEREO);
+ fprintf(file, " generic=%d generic accelerated=%d\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) == PFD_GENERIC_FORMAT, (pfd.dwFlags & PFD_GENERIC_ACCELERATED) == PFD_GENERIC_ACCELERATED);
+ fprintf(file, " rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits);
+ fprintf(file, " auxBuffers=%d depthSize=%d stencilSize=%d\n", pfd.cAuxBuffers, pfd.cDepthBits, pfd.cStencilBits);
+ fprintf(file, " accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cAccumRedBits, pfd.cAccumGreenBits, pfd.cAccumBlueBits, pfd.cAccumAlphaBits);
+ fprintf(file, " multiSample=%d multisampleBuffers=%d\n", 0, 0);
+ fprintf(file, " Opaque.\n");
+ }
+ }
+}
+
+void
+VisualInfo (GLContext* ctx)
+{
+ if (WGLEW_ARB_pixel_format)
+ VisualInfoARB(ctx);
+ else
+ VisualInfoGDI(ctx);
+}
+
+/* ---------------------------------------------------------------------- */
+
+#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
+
+void
+VisualInfo (GLContext* ctx)
+{
+/*
+ int attrib[] = { AGL_RGBA, AGL_NONE };
+ AGLPixelFormat pf;
+ GLint value;
+ pf = aglChoosePixelFormat(NULL, 0, attrib);
+ while (pf != NULL)
+ {
+ aglDescribePixelFormat(pf, GL_RGBA, &value);
+ fprintf(stderr, "%d\n", value);
+ pf = aglNextPixelFormat(pf);
+ }
+*/
+}
+
+#else /* GLX */
+
+void
+VisualInfo (GLContext* ctx)
+{
+ int n_fbc;
+ GLXFBConfig* fbc;
+ int value, ret, i;
+
+ fbc = glXGetFBConfigs(ctx->dpy, DefaultScreen(ctx->dpy), &n_fbc);
+
+ if (fbc)
+ {
+ if (!verbose)
+ {
+ /* print table header */
+ fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n");
+ fprintf(file, " | | visual | color | ax dp st | accum | ms | cav |\n");
+ fprintf(file, " | id | tp xr cl fm db st lv xp | sz r g b a | bf th cl | r g b a | ns b | eat |\n");
+ fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n");
+ /* loop through all the fbcs */
+ for (i=0; i<n_fbc; i++)
+ {
+ /* print out the information for this fbc */
+ /* visual id */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_FBCONFIG_ID, &value);
+ if (ret != Success)
+ {
+ fprintf(file, "| ? |");
+ }
+ else
+ {
+ fprintf(file, " |% 4d | ", value);
+ }
+ /* visual type */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DRAWABLE_TYPE, &value);
+ if (ret != Success)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value & GLX_WINDOW_BIT)
+ {
+ if (value & GLX_PBUFFER_BIT)
+ {
+ fprintf(file, "wp ");
+ }
+ else
+ {
+ fprintf(file, "wn ");
+ }
+ }
+ else
+ {
+ if (value & GLX_PBUFFER_BIT)
+ {
+ fprintf(file, "pb ");
+ }
+ else if (value & GLX_PIXMAP_BIT)
+ {
+ fprintf(file, "pm ");
+ }
+ else
+ {
+ fprintf(file, " ? ");
+ }
+ }
+ }
+ /* x renderable */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_X_RENDERABLE, &value);
+ if (ret != Success)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ fprintf(file, value ? " y " : " n ");
+ }
+ /* class */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_X_VISUAL_TYPE, &value);
+ if (ret != Success)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (GLX_TRUE_COLOR == value)
+ fprintf(file, "tc ");
+ else if (GLX_DIRECT_COLOR == value)
+ fprintf(file, "dc ");
+ else if (GLX_PSEUDO_COLOR == value)
+ fprintf(file, "pc ");
+ else if (GLX_STATIC_COLOR == value)
+ fprintf(file, "sc ");
+ else if (GLX_GRAY_SCALE == value)
+ fprintf(file, "gs ");
+ else if (GLX_STATIC_GRAY == value)
+ fprintf(file, "sg ");
+ else if (GLX_X_VISUAL_TYPE == value)
+ fprintf(file, " . ");
+ else
+ fprintf(file, " ? ");
+ }
+ /* format */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_RENDER_TYPE, &value);
+ if (ret != Success)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (GLXEW_NV_float_buffer)
+ {
+ int ret2, value2;
+ ret2 = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_FLOAT_COMPONENTS_NV, &value2);
+ if (Success == ret2 && GL_TRUE == value2)
+ {
+ fprintf(file, " f ");
+ }
+ else if (value & GLX_RGBA_BIT)
+ fprintf(file, " i ");
+ else if (value & GLX_COLOR_INDEX_BIT)
+ fprintf(file, " c ");
+ else
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value & GLX_RGBA_FLOAT_ATI_BIT)
+ fprintf(file, " f ");
+ else if (value & GLX_RGBA_BIT)
+ fprintf(file, " i ");
+ else if (value & GLX_COLOR_INDEX_BIT)
+ fprintf(file, " c ");
+ else
+ fprintf(file, " ? ");
+ }
+ }
+ /* double buffer */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DOUBLEBUFFER, &value);
+ fprintf(file, " %c ", Success != ret ? '?' : (value ? 'y' : '.'));
+ /* stereo */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_STEREO, &value);
+ fprintf(file, " %c ", Success != ret ? '?' : (value ? 'y' : '.'));
+ /* level */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_LEVEL, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ fprintf(file, "%2d ", value);
+ }
+ /* transparency */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_TRANSPARENT_TYPE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? | ");
+ }
+ else
+ {
+ if (GLX_TRANSPARENT_RGB == value)
+ fprintf(file, " r | ");
+ else if (GLX_TRANSPARENT_INDEX == value)
+ fprintf(file, " i | ");
+ else if (GLX_NONE == value)
+ fprintf(file, " . | ");
+ else
+ fprintf(file, " ? | ");
+ }
+ /* color size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_BUFFER_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%3d ", value);
+ else
+ fprintf(file, " . ");
+ }
+ /* red size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_RED_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d ", value);
+ else
+ fprintf(file, " . ");
+ }
+ /* green size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_GREEN_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d ", value);
+ else
+ fprintf(file, " . ");
+ }
+ /* blue size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_BLUE_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d ", value);
+ else
+ fprintf(file, " . ");
+ }
+ /* alpha size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ALPHA_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? | ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d | ", value);
+ else
+ fprintf(file, " . | ");
+ }
+ /* aux buffers */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_AUX_BUFFERS, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d ", value);
+ else
+ fprintf(file, " . ");
+ }
+ /* depth size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DEPTH_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d ", value);
+ else
+ fprintf(file, " . ");
+ }
+ /* stencil size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_STENCIL_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? | ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d | ", value);
+ else
+ fprintf(file, " . | ");
+ }
+ /* accum red size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_RED_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d ", value);
+ else
+ fprintf(file, " . ");
+ }
+ /* accum green size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_GREEN_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d ", value);
+ else
+ fprintf(file, " . ");
+ }
+ /* accum blue size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_BLUE_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d ", value);
+ else
+ fprintf(file, " . ");
+ }
+ /* accum alpha size */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_ALPHA_SIZE, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? | ");
+ }
+ else
+ {
+ if (value)
+ fprintf(file, "%2d | ", value);
+ else
+ fprintf(file, " . | ");
+ }
+ /* multisample */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_SAMPLES, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? ");
+ }
+ else
+ {
+ fprintf(file, "%2d ", value);
+ }
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_SAMPLE_BUFFERS, &value);
+ if (Success != ret)
+ {
+ fprintf(file, " ? | ");
+ }
+ else
+ {
+ fprintf(file, "%2d | ", value);
+ }
+ /* caveat */
+ ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_CONFIG_CAVEAT, &value);
+ if (Success != ret)
+ {
+ fprintf(file, "???? |");
+ }
+ else
+ {
+ if (GLX_NONE == value)
+ fprintf(file, "none |\n");
+ else if (GLX_SLOW_CONFIG == value)
+ fprintf(file, "slow |\n");
+ else if (GLX_NON_CONFORMANT_CONFIG == value)
+ fprintf(file, "ncft |\n");
+ else
+ fprintf(file, "???? |\n");
+ }
+ }
+ /* print table footer */
+ fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n");
+ fprintf(file, " | id | tp xr cl fm db st lv xp | sz r g b a | bf th cl | r g b a | ns b | eat |\n");
+ fprintf(file, " | | visual | color | ax dp st | accum | ms | cav |\n");
+ fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n");
+ }
+ }
+}
+
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+#if defined(_WIN32)
+
+void InitContext (GLContext* ctx)
+{
+ ctx->wnd = NULL;
+ ctx->dc = NULL;
+ ctx->rc = NULL;
+}
+
+GLboolean CreateContext (GLContext* ctx)
+{
+ WNDCLASS wc;
+ PIXELFORMATDESCRIPTOR pfd;
+ /* check for input */
+ if (NULL == ctx) return GL_TRUE;
+ /* register window class */
+ ZeroMemory(&wc, sizeof(WNDCLASS));
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.lpfnWndProc = DefWindowProc;
+ wc.lpszClassName = "GLEW";
+ if (0 == RegisterClass(&wc)) return GL_TRUE;
+ /* create window */
+ ctx->wnd = CreateWindow("GLEW", "GLEW", 0, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
+ GetModuleHandle(NULL), NULL);
+ if (NULL == ctx->wnd) return GL_TRUE;
+ /* get the device context */
+ ctx->dc = GetDC(ctx->wnd);
+ if (NULL == ctx->dc) return GL_TRUE;
+ /* find pixel format */
+ ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
+ if (visual == -1) /* find default */
+ {
+ pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ visual = ChoosePixelFormat(ctx->dc, &pfd);
+ if (0 == visual) return GL_TRUE;
+ }
+ /* set the pixel format for the dc */
+ if (FALSE == SetPixelFormat(ctx->dc, visual, &pfd)) return GL_TRUE;
+ /* create rendering context */
+ ctx->rc = wglCreateContext(ctx->dc);
+ if (NULL == ctx->rc) return GL_TRUE;
+ if (FALSE == wglMakeCurrent(ctx->dc, ctx->rc)) return GL_TRUE;
+ return GL_FALSE;
+}
+
+void DestroyContext (GLContext* ctx)
+{
+ if (NULL == ctx) return;
+ if (NULL != ctx->rc) wglMakeCurrent(NULL, NULL);
+ if (NULL != ctx->rc) wglDeleteContext(wglGetCurrentContext());
+ if (NULL != ctx->wnd && NULL != ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
+ if (NULL != ctx->wnd) DestroyWindow(ctx->wnd);
+ UnregisterClass("GLEW", GetModuleHandle(NULL));
+}
+
+/* ------------------------------------------------------------------------ */
+
+#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX)
+
+void InitContext (GLContext* ctx)
+{
+ ctx->ctx = NULL;
+ ctx->octx = NULL;
+}
+
+GLboolean CreateContext (GLContext* ctx)
+{
+ int attrib[] = { AGL_RGBA, AGL_NONE };
+ AGLPixelFormat pf;
+ /* check input */
+ if (NULL == ctx) return GL_TRUE;
+ /*int major, minor;
+ SetPortWindowPort(wnd);
+ aglGetVersion(&major, &minor);
+ fprintf(stderr, "GL %d.%d\n", major, minor);*/
+ pf = aglChoosePixelFormat(NULL, 0, attrib);
+ if (NULL == pf) return GL_TRUE;
+ ctx->ctx = aglCreateContext(pf, NULL);
+ if (NULL == ctx->ctx || AGL_NO_ERROR != aglGetError()) return GL_TRUE;
+ aglDestroyPixelFormat(pf);
+ /*aglSetDrawable(ctx, GetWindowPort(wnd));*/
+ ctx->octx = aglGetCurrentContext();
+ if (NULL == aglSetCurrentContext(ctx->ctx)) return GL_TRUE;
+ return GL_FALSE;
+}
+
+void DestroyContext (GLContext* ctx)
+{
+ if (NULL == ctx) return;
+ aglSetCurrentContext(ctx->octx);
+ if (NULL != ctx->ctx) aglDestroyContext(ctx->ctx);
+}
+
+/* ------------------------------------------------------------------------ */
+
+#else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */
+
+void InitContext (GLContext* ctx)
+{
+ ctx->dpy = NULL;
+ ctx->vi = NULL;
+ ctx->ctx = NULL;
+ ctx->wnd = 0;
+ ctx->cmap = 0;
+}
+
+GLboolean CreateContext (GLContext* ctx)
+{
+ int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
+ int erb, evb;
+ XSetWindowAttributes swa;
+ /* check input */
+ if (NULL == ctx) return GL_TRUE;
+ /* open display */
+ ctx->dpy = XOpenDisplay(display);
+ if (NULL == ctx->dpy) return GL_TRUE;
+ /* query for glx */
+ if (!glXQueryExtension(ctx->dpy, &erb, &evb)) return GL_TRUE;
+ /* choose visual */
+ ctx->vi = glXChooseVisual(ctx->dpy, DefaultScreen(ctx->dpy), attrib);
+ if (NULL == ctx->vi) return GL_TRUE;
+ /* create context */
+ ctx->ctx = glXCreateContext(ctx->dpy, ctx->vi, None, True);
+ if (NULL == ctx->ctx) return GL_TRUE;
+ /* create window */
+ /*wnd = XCreateSimpleWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 1, 1, 1, 0, 0);*/
+ ctx->cmap = XCreateColormap(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen),
+ ctx->vi->visual, AllocNone);
+ swa.border_pixel = 0;
+ swa.colormap = ctx->cmap;
+ ctx->wnd = XCreateWindow(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen),
+ 0, 0, 1, 1, 0, ctx->vi->depth, InputOutput, ctx->vi->visual,
+ CWBorderPixel | CWColormap, &swa);
+ /* make context current */
+ if (!glXMakeCurrent(ctx->dpy, ctx->wnd, ctx->ctx)) return GL_TRUE;
+ return GL_FALSE;
+}
+
+void DestroyContext (GLContext* ctx)
+{
+ if (NULL != ctx->dpy && NULL != ctx->ctx) glXDestroyContext(ctx->dpy, ctx->ctx);
+ if (NULL != ctx->dpy && 0 != ctx->wnd) XDestroyWindow(ctx->dpy, ctx->wnd);
+ if (NULL != ctx->dpy && 0 != ctx->cmap) XFreeColormap(ctx->dpy, ctx->cmap);
+ if (NULL != ctx->vi) XFree(ctx->vi);
+ if (NULL != ctx->dpy) XCloseDisplay(ctx->dpy);
+}
+
+#endif /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */
+
+GLboolean ParseArgs (int argc, char** argv)
+{
+ int p = 0;
+ while (p < argc)
+ {
+#if defined(_WIN32)
+ if (!strcmp(argv[p], "-pf") || !strcmp(argv[p], "-pixelformat"))
+ {
+ if (++p >= argc) return GL_TRUE;
+ display = NULL;
+ visual = strtol(argv[p], NULL, 0);
+ }
+ else if (!strcmp(argv[p], "-a"))
+ {
+ showall = 1;
+ }
+ else if (!strcmp(argv[p], "-s"))
+ {
+ displaystdout = 1;
+ }
+ else if (!strcmp(argv[p], "-h"))
+ {
+ return GL_TRUE;
+ }
+ else
+ return GL_TRUE;
+#else
+ if (!strcmp(argv[p], "-display"))
+ {
+ if (++p >= argc) return GL_TRUE;
+ display = argv[p];
+ }
+ else if (!strcmp(argv[p], "-visual"))
+ {
+ if (++p >= argc) return GL_TRUE;
+ visual = (int)strtol(argv[p], NULL, 0);
+ }
+ else if (!strcmp(argv[p], "-h"))
+ {
+ return GL_TRUE;
+ }
+ else
+ return GL_TRUE;
+#endif
+ p++;
+ }
+ return GL_FALSE;
+}
diff --git a/src/glu/.gitignore b/src/glu/.gitignore
new file mode 100644
index 0000000000..279ea7d434
--- /dev/null
+++ b/src/glu/.gitignore
@@ -0,0 +1 @@
+exptmp
diff --git a/src/glu/Makefile b/src/glu/Makefile
index e519dfeec4..b268265976 100644
--- a/src/glu/Makefile
+++ b/src/glu/Makefile
@@ -22,14 +22,15 @@ pcedit = sed \
-e 's,@GLU_PC_REQ@,$(GLU_PC_REQ),' \
-e 's,@GLU_PC_REQ_PRIV@,$(GLU_PC_REQ_PRIV),' \
-e 's,@GLU_PC_LIB_PRIV@,$(GLU_PC_LIB_PRIV),' \
- -e 's,@GLU_PC_CFLAGS@,$(GLU_PC_CFLAGS),'
+ -e 's,@GLU_PC_CFLAGS@,$(GLU_PC_CFLAGS),' \
+ -e 's,@GLU_LIB@,$(GLU_LIB),'
glu.pc: glu.pc.in
$(pcedit) $< > $@
install: glu.pc
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
- $(INSTALL) $(TOP)/$(LIB_DIR)/$(GLU_LIB_GLOB) $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GLU_LIB_GLOB) $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -m 644 glu.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
clean:
diff --git a/src/glu/descrip.mms b/src/glu/descrip.mms
deleted file mode 100644
index 6d5cd858da..0000000000
--- a/src/glu/descrip.mms
+++ /dev/null
@@ -1,9 +0,0 @@
-# Makefile for Mesa for VMS
-# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl
-
-all :
-# PIPE is avalailable on VMS7.0 and higher. For lower versions split the
-#command in two conditional command. JJ
- if f$search("SYS$SYSTEM:CXX$COMPILER.EXE") .nes. "" then pipe set default [.sgi] ; $(MMS)$(MMSQUALIFIERS)
- if f$search("SYS$SYSTEM:CXX$COMPILER.EXE") .eqs. "" then pipe set default [.mesa] ; $(MMS)$(MMSQUALIFIERS)
- set default [-]
diff --git a/src/glu/glu.pc.in b/src/glu/glu.pc.in
index bc2517e90e..f7d9109823 100644
--- a/src/glu/glu.pc.in
+++ b/src/glu/glu.pc.in
@@ -8,6 +8,6 @@ Description: Mesa OpenGL Utility library
Requires: @GLU_PC_REQ@
Requires.private: @GLU_PC_REQ_PRIV@
Version: @VERSION@
-Libs: -L${libdir} -lGLU
+Libs: -L${libdir} -l@GLU_LIB@
Libs.private: @GLU_PC_LIB_PRIV@
Cflags: -I${includedir} @GLU_PC_CFLAGS@
diff --git a/src/glu/mesa/Makefile.DJ b/src/glu/mesa/Makefile.DJ
deleted file mode 100644
index 92bcdaae94..0000000000
--- a/src/glu/mesa/Makefile.DJ
+++ /dev/null
@@ -1,100 +0,0 @@
-# Mesa 3-D graphics library
-# Version: 4.0
-#
-# Copyright (C) 1999 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.
-
-# DOS/DJGPP glu makefile v1.5 for Mesa
-#
-# Copyright (C) 2002 - Daniel Borca
-# Email : dborca@users.sourceforge.net
-# Web : http://www.geocities.com/dborca
-
-
-#
-# Available options:
-#
-# Environment variables:
-# CFLAGS
-#
-# Targets:
-# all: build GLU
-# clean: remove object files
-#
-
-
-
-.PHONY: all clean
-
-TOP = ../../..
-LIBDIR = $(TOP)/lib
-GLU_LIB = libglu.a
-GLU_DXE = glu.dxe
-GLU_IMP = libiglu.a
-
-export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH);$(LIBDIR);$(GLIDE)/lib
-
-CC = gcc
-CFLAGS += -I$(TOP)/include
-
-AR = ar
-ARFLAGS = crus
-
-HAVEDXE3 = $(wildcard $(DJDIR)/bin/dxe3gen.exe)
-
-ifeq ($(wildcard $(addsuffix /rm.exe,$(subst ;, ,$(PATH)))),)
-UNLINK = del $(subst /,\,$(1))
-else
-UNLINK = $(RM) $(1)
-endif
-
-CORE_SOURCES = \
- glu.c \
- mipmap.c \
- nurbs.c \
- nurbscrv.c \
- nurbssrf.c \
- nurbsutl.c \
- polytest.c \
- project.c \
- quadric.c \
- tess.c \
- tesselat.c
-
-SOURCES = $(CORE_SOURCES)
-
-OBJECTS = $(SOURCES:.c=.o)
-
-.c.o:
- $(CC) -o $@ $(CFLAGS) -c $<
-
-all: $(LIBDIR)/$(GLU_LIB) $(LIBDIR)/$(GLU_DXE) $(LIBDIR)/$(GLU_IMP)
-
-$(LIBDIR)/$(GLU_LIB): $(OBJECTS)
- $(AR) $(ARFLAGS) $@ $^
-
-$(LIBDIR)/$(GLU_DXE) $(LIBDIR)/$(GLU_IMP): $(OBJECTS)
-ifeq ($(HAVEDXE3),)
- $(warning Missing DXE3 package... Skipping $(GLU_DXE))
-else
- -dxe3gen -o $(LIBDIR)/$(GLU_DXE) -Y $(LIBDIR)/$(GLU_IMP) -D "MesaGLU DJGPP" -E _glu -P gl.dxe -U $^
-endif
-
-clean:
- -$(call UNLINK,*.o)
diff --git a/src/glu/mesa/descrip.mms b/src/glu/mesa/descrip.mms
deleted file mode 100644
index 2b3f64d8bc..0000000000
--- a/src/glu/mesa/descrip.mms
+++ /dev/null
@@ -1,61 +0,0 @@
-# Makefile for GLU for VMS
-# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl
-
-.first
- define gl [-.include.gl]
-
-.include [-]mms-config.
-
-##### MACROS #####
-
-VPATH = RCS
-
-INCDIR = $disk2:[-.include]
-LIBDIR = [-.lib]
-CFLAGS = /include=$(INCDIR)/define=(FBIND=1)/name=(as_is,short)/float=ieee/ieee=denorm
-
-SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \
- polytest.c project.c quadric.c tess.c tesselat.c
-
-OBJECTS =glu.obj,mipmap.obj,nurbs.obj,nurbscrv.obj,nurbssrf.obj,nurbsutl.obj,\
- polytest.obj,project.obj,quadric.obj,tess.obj,tesselat.obj
-
-
-##### RULES #####
-
-VERSION=MesaGlu V3.2
-
-##### TARGETS #####
-
-# Make the library:
-$(LIBDIR)$(GLU_LIB) : $(OBJECTS)
-.ifdef SHARE
- @ WRITE_ SYS$OUTPUT " generating mesagl1.opt"
- @ OPEN_/WRITE FILE mesagl1.opt
- @ WRITE_ FILE "!"
- @ WRITE_ FILE "! mesagl1.opt generated by DESCRIP.$(MMS_EXT)"
- @ WRITE_ FILE "!"
- @ WRITE_ FILE "IDENTIFICATION=""$(VERSION)"""
- @ WRITE_ FILE "GSMATCH=LEQUAL,3,2
- @ WRITE_ FILE "$(OBJECTS)"
- @ WRITE_ FILE "[-.lib]libmesagl.exe/SHARE"
- @ WRITE_ FILE "SYS$SHARE:DECW$XEXTLIBSHR/SHARE"
- @ WRITE_ FILE "SYS$SHARE:DECW$XLIBSHR/SHARE"
- @ CLOSE_ FILE
- @ WRITE_ SYS$OUTPUT " generating mesagl.map ..."
- @ LINK_/NODEB/NOSHARE/NOEXE/MAP=mesagl.map/FULL mesagl1.opt/OPT
- @ WRITE_ SYS$OUTPUT " analyzing mesagl.map ..."
- @ @[-.vms]ANALYZE_MAP.COM mesagl.map mesagl.opt
- @ WRITE_ SYS$OUTPUT " linking $(GLU_LIB) ..."
- @ LINK_/noinform/NODEB/SHARE=$(GLU_LIB)/MAP=mesagl.map/FULL mesagl1.opt/opt,mesagl.opt/opt
-.else
- @ $(MAKELIB) $(GLU_LIB) $(OBJECTS)
-.endif
- @ rename $(GLU_LIB)* $(LIBDIR)
-
-clean :
- delete *.obj;*
- purge
-
-include mms_depend.
-
diff --git a/src/glu/mesa/mms_depend b/src/glu/mesa/mms_depend
deleted file mode 100644
index ed59ca9de8..0000000000
--- a/src/glu/mesa/mms_depend
+++ /dev/null
@@ -1,15 +0,0 @@
-# DO NOT DELETE THIS LINE -- make depend depends on it.
-
-glu.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
-mipmap.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
-nurbs.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h nurbs.h
-nurbscrv.obj : nurbs.h gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
-nurbssrf.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h nurbs.h
-nurbsutl.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h nurbs.h
-project.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
-quadric.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
-tess.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
-tess_fist.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
-tess_hash.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
-tess_heap.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
-tess_clip.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
diff --git a/src/glu/sgi/.gitignore b/src/glu/sgi/.gitignore
new file mode 100644
index 0000000000..279ea7d434
--- /dev/null
+++ b/src/glu/sgi/.gitignore
@@ -0,0 +1 @@
+exptmp
diff --git a/src/glu/sgi/Makefile.DJ b/src/glu/sgi/Makefile.DJ
deleted file mode 100644
index b5df3e846a..0000000000
--- a/src/glu/sgi/Makefile.DJ
+++ /dev/null
@@ -1,188 +0,0 @@
-# Mesa 3-D graphics library
-# Version: 4.0
-#
-# Copyright (C) 1999 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.
-
-# DOS/DJGPP glu makefile v1.5 for Mesa
-#
-# Copyright (C) 2002 - Daniel Borca
-# Email : dborca@users.sourceforge.net
-# Web : http://www.geocities.com/dborca
-
-
-#
-# Available options:
-#
-# Environment variables:
-# CFLAGS
-#
-# Targets:
-# all: build GLU
-# clean: remove object files
-#
-
-
-
-.PHONY: all clean
-
-TOP = ../../..
-LIBDIR = $(TOP)/lib
-GLU_LIB = libglu.a
-GLU_DXE = glu.dxe
-GLU_IMP = libiglu.a
-
-export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH);$(LIBDIR);$(GLIDE)/lib
-
-CC = gcc
-CFLAGS += -DNDEBUG -DLIBRARYBUILD -I$(TOP)/include -Iinclude
-CXX = gpp
-CXXFLAGS = $(CFLAGS) -Ilibnurbs/internals -Ilibnurbs/interface -Ilibnurbs/nurbtess
-
-AR = ar
-ARFLAGS = crus
-
-HAVEDXE3 = $(wildcard $(DJDIR)/bin/dxe3gen.exe)
-
-ifeq ($(wildcard $(addsuffix /rm.exe,$(subst ;, ,$(PATH)))),)
-UNLINK = del $(subst /,\,$(1))
-else
-UNLINK = $(RM) $(1)
-endif
-
-C_SOURCES = \
- libutil/error.c \
- libutil/glue.c \
- libutil/mipmap.c \
- libutil/project.c \
- libutil/quad.c \
- libutil/registry.c \
- libtess/dict.c \
- libtess/geom.c \
- libtess/memalloc.c \
- libtess/mesh.c \
- libtess/normal.c \
- libtess/priorityq.c \
- libtess/render.c \
- libtess/sweep.c \
- libtess/tess.c \
- libtess/tessmono.c
-
-CC_SOURCES = \
- libnurbs/interface/bezierEval.cc \
- libnurbs/interface/bezierPatch.cc \
- libnurbs/interface/bezierPatchMesh.cc \
- libnurbs/interface/glcurveval.cc \
- libnurbs/interface/glinterface.cc \
- libnurbs/interface/glrenderer.cc \
- libnurbs/interface/glsurfeval.cc \
- libnurbs/interface/incurveeval.cc \
- libnurbs/interface/insurfeval.cc \
- libnurbs/internals/arc.cc \
- libnurbs/internals/arcsorter.cc \
- libnurbs/internals/arctess.cc \
- libnurbs/internals/backend.cc \
- libnurbs/internals/basiccrveval.cc \
- libnurbs/internals/basicsurfeval.cc \
- libnurbs/internals/bin.cc \
- libnurbs/internals/bufpool.cc \
- libnurbs/internals/cachingeval.cc \
- libnurbs/internals/ccw.cc \
- libnurbs/internals/coveandtiler.cc \
- libnurbs/internals/curve.cc \
- libnurbs/internals/curvelist.cc \
- libnurbs/internals/curvesub.cc \
- libnurbs/internals/dataTransform.cc \
- libnurbs/internals/displaylist.cc \
- libnurbs/internals/flist.cc \
- libnurbs/internals/flistsorter.cc \
- libnurbs/internals/hull.cc \
- libnurbs/internals/intersect.cc \
- libnurbs/internals/knotvector.cc \
- libnurbs/internals/mapdesc.cc \
- libnurbs/internals/mapdescv.cc \
- libnurbs/internals/maplist.cc \
- libnurbs/internals/mesher.cc \
- libnurbs/internals/monoTriangulationBackend.cc \
- libnurbs/internals/monotonizer.cc \
- libnurbs/internals/mycode.cc \
- libnurbs/internals/nurbsinterfac.cc \
- libnurbs/internals/nurbstess.cc \
- libnurbs/internals/patch.cc \
- libnurbs/internals/patchlist.cc \
- libnurbs/internals/quilt.cc \
- libnurbs/internals/reader.cc \
- libnurbs/internals/renderhints.cc \
- libnurbs/internals/slicer.cc \
- libnurbs/internals/sorter.cc \
- libnurbs/internals/splitarcs.cc \
- libnurbs/internals/subdivider.cc \
- libnurbs/internals/tobezier.cc \
- libnurbs/internals/trimline.cc \
- libnurbs/internals/trimregion.cc \
- libnurbs/internals/trimvertpool.cc \
- libnurbs/internals/uarray.cc \
- libnurbs/internals/varray.cc \
- libnurbs/nurbtess/directedLine.cc \
- libnurbs/nurbtess/gridWrap.cc \
- libnurbs/nurbtess/monoChain.cc \
- libnurbs/nurbtess/monoPolyPart.cc \
- libnurbs/nurbtess/monoTriangulation.cc \
- libnurbs/nurbtess/partitionX.cc \
- libnurbs/nurbtess/partitionY.cc \
- libnurbs/nurbtess/polyDBG.cc \
- libnurbs/nurbtess/polyUtil.cc \
- libnurbs/nurbtess/primitiveStream.cc \
- libnurbs/nurbtess/quicksort.cc \
- libnurbs/nurbtess/rectBlock.cc \
- libnurbs/nurbtess/sampleComp.cc \
- libnurbs/nurbtess/sampleCompBot.cc \
- libnurbs/nurbtess/sampleCompRight.cc \
- libnurbs/nurbtess/sampleCompTop.cc \
- libnurbs/nurbtess/sampleMonoPoly.cc \
- libnurbs/nurbtess/sampledLine.cc \
- libnurbs/nurbtess/searchTree.cc
-
-SOURCES = $(C_SOURCES) $(CC_SOURCES)
-
-OBJECTS = $(addsuffix .o,$(basename $(SOURCES)))
-
-.c.o:
- $(CC) -o $@ $(CFLAGS) -c $<
-.cc.o:
- $(CXX) -o $@ $(CXXFLAGS) -c $<
-
-all: $(LIBDIR)/$(GLU_LIB) $(LIBDIR)/$(GLU_DXE) $(LIBDIR)/$(GLU_IMP)
-
-$(LIBDIR)/$(GLU_LIB): $(OBJECTS)
- $(AR) $(ARFLAGS) $@ $^
-
-$(LIBDIR)/$(GLU_DXE) $(LIBDIR)/$(GLU_IMP): $(OBJECTS)
-ifeq ($(HAVEDXE3),)
- $(warning Missing DXE3 package... Skipping $(GLU_DXE))
-else
- -dxe3gen -o $(LIBDIR)/$(GLU_DXE) -Y $(LIBDIR)/$(GLU_IMP) -D "MesaGLU/SGI DJGPP" -E _glu -P gl.dxe -U $^
-endif
-
-clean:
- -$(call UNLINK,libutil/*.o)
- -$(call UNLINK,libtess/*.o)
- -$(call UNLINK,libnurbs/interface/*.o)
- -$(call UNLINK,libnurbs/internals/*.o)
- -$(call UNLINK,libnurbs/nurbtess/*.o)
diff --git a/src/glu/sgi/descrip.mms b/src/glu/sgi/descrip.mms
deleted file mode 100644
index 5abc8b2e04..0000000000
--- a/src/glu/sgi/descrip.mms
+++ /dev/null
@@ -1,451 +0,0 @@
-# Makefile for GLU for VMS
-# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl
-
-.first
- define gl [---.include.gl]
-
-.include [---]mms-config.
-
-##### MACROS #####
-
-VPATH = RCS
-
-INCDIR =([-.include],[.include],[.internals],[.libnurbs.internals],\
- [.libnurbs.interface],[.libnurbs.nurbtess])
-LIBDIR = [---.lib]
-CFLAGS = /include=$(INCDIR)/name=(as_is,short)/float=ieee/ieee=denorm
-
-LU_OBJECTS=\
- [.libutil]error.obj, \
- [.libutil]glue.obj, \
- [.libutil]mipmap.obj,\
- [.libutil]project.obj,\
- [.libutil]quad.obj, \
- [.libutil]registry.obj
-
-LT_OBJECTS=[.libtess]dict.obj, \
- [.libtess]geom.obj, \
- [.libtess]memalloc.obj,\
- [.libtess]mesh.obj, \
- [.libtess]normal.obj,\
- [.libtess]priorityq.obj,\
- [.libtess]render.obj,\
- [.libtess]sweep.obj, \
- [.libtess]tess.obj, \
- [.libtess]tessmono.obj
-
-LI_OBJECTS=[.libnurbs.interface]bezierEval.obj, \
- [.libnurbs.interface]bezierPatch.obj, \
- [.libnurbs.interface]bezierPatchMesh.obj, \
- [.libnurbs.interface]glcurveval.obj, \
- [.libnurbs.interface]glinterface.obj
-
-LI_OBJECTS1=[.libnurbs.interface]glrenderer.obj, \
- [.libnurbs.interface]glsurfeval.obj, \
- [.libnurbs.interface]incurveeval.obj, \
- [.libnurbs.interface]insurfeval.obj
-
-LI2_OBJECTS=[.libnurbs.internals]arc.obj, \
- [.libnurbs.internals]arcsorter.obj, \
- [.libnurbs.internals]arctess.obj, \
- [.libnurbs.internals]backend.obj, \
- [.libnurbs.internals]basiccrveval.obj, \
- [.libnurbs.internals]basicsurfeval.obj
-
-LI2_OBJECTS1=[.libnurbs.internals]bin.obj, \
- [.libnurbs.internals]bufpool.obj, \
- [.libnurbs.internals]cachingeval.obj, \
- [.libnurbs.internals]ccw.obj, \
- [.libnurbs.internals]coveandtiler.obj, \
- [.libnurbs.internals]curve.obj, \
- [.libnurbs.internals]curvelist.obj
-
-LI2_OBJECTS2=[.libnurbs.internals]curvesub.obj, \
- [.libnurbs.internals]dataTransform.obj, \
- [.libnurbs.internals]displaylist.obj, \
- [.libnurbs.internals]flist.obj, \
- [.libnurbs.internals]flistsorter.obj
-
-LI2_OBJECTS3=[.libnurbs.internals]hull.obj, \
- [.libnurbs.internals]intersect.obj, \
- [.libnurbs.internals]knotvector.obj, \
- [.libnurbs.internals]mapdesc.obj
-
-LI2_OBJECTS4=[.libnurbs.internals]mapdescv.obj, \
- [.libnurbs.internals]maplist.obj, \
- [.libnurbs.internals]mesher.obj, \
- [.libnurbs.internals]monoTriangulationBackend.obj,\
- [.libnurbs.internals]monotonizer.obj
-
-LI2_OBJECTS5=[.libnurbs.internals]mycode.obj, \
- [.libnurbs.internals]nurbsinterfac.obj, \
- [.libnurbs.internals]nurbstess.obj, \
- [.libnurbs.internals]patch.obj
-
-LI2_OBJECTS6=[.libnurbs.internals]patchlist.obj, \
- [.libnurbs.internals]quilt.obj, \
- [.libnurbs.internals]reader.obj, \
- [.libnurbs.internals]renderhints.obj, \
- [.libnurbs.internals]slicer.obj
-
-LI2_OBJECTS7=[.libnurbs.internals]sorter.obj, \
- [.libnurbs.internals]splitarcs.obj, \
- [.libnurbs.internals]subdivider.obj, \
- [.libnurbs.internals]tobezier.obj
-
-LI2_OBJECTS8=[.libnurbs.internals]trimline.obj, \
- [.libnurbs.internals]trimregion.obj, \
- [.libnurbs.internals]trimvertpool.obj, \
- [.libnurbs.internals]uarray.obj, \
- [.libnurbs.internals]varray.obj
-
-LN_OBJECTS=[.libnurbs.nurbtess]directedLine.obj, \
- [.libnurbs.nurbtess]gridWrap.obj, \
- [.libnurbs.nurbtess]monoChain.obj, \
- [.libnurbs.nurbtess]monoPolyPart.obj, \
- [.libnurbs.nurbtess]monoTriangulation.obj
-
-LN_OBJECTS1=[.libnurbs.nurbtess]partitionX.obj, \
- [.libnurbs.nurbtess]partitionY.obj, \
- [.libnurbs.nurbtess]polyDBG.obj
-
-LN_OBJECTS2=[.libnurbs.nurbtess]polyUtil.obj, \
- [.libnurbs.nurbtess]primitiveStream.obj, \
- [.libnurbs.nurbtess]quicksort.obj, \
- [.libnurbs.nurbtess]rectBlock.obj
-
-LN_OBJECTS3=[.libnurbs.nurbtess]sampleComp.obj, \
- [.libnurbs.nurbtess]sampleCompBot.obj, \
- [.libnurbs.nurbtess]sampleCompRight.obj
-
-LN_OBJECTS4=[.libnurbs.nurbtess]sampleCompTop.obj, \
- [.libnurbs.nurbtess]sampleMonoPoly.obj,\
- [.libnurbs.nurbtess]sampledLine.obj, \
- [.libnurbs.nurbtess]searchTree.obj
-
-##### RULES #####
-
-VERSION=MesaGlu V3.5
-
-##### TARGETS #####
-
-# Make the library:
-$(LIBDIR)$(GLU_LIB) : $(LU_OBJECTS) $(LT_OBJECTS) $(LI_OBJECTS) $(LI_OBJECTS1)\
- $(LI2_OBJECTS) $(LI2_OBJECTS1) $(LI2_OBJECTS2)\
- $(LI2_OBJECTS3) $(LI2_OBJECTS4) $(LI2_OBJECTS5)\
- $(LI2_OBJECTS6) $(LI2_OBJECTS7) $(LI2_OBJECTS8)\
- $(LN_OBJECTS) $(LN_OBJECTS1) $(LN_OBJECTS2)\
- $(LN_OBJECTS3) $(LN_OBJECTS4)
- @ $(MAKELIB) $(GLU_LIB) $(LU_OBJECTS),$(LT_OBJECTS),$(LI_OBJECTS),\
- $(LI2_OBJECTS),$(LN_OBJECTS)
- @ rename $(GLU_LIB)* $(LIBDIR)
-.ifdef SHARE
- @ WRITE_ SYS$OUTPUT " generating mesagl1.opt"
- @ OPEN_/WRITE FILE mesagl1.opt
- @ WRITE_ FILE "!"
- @ WRITE_ FILE "! mesagl1.opt generated by DESCRIP.$(MMS_EXT)"
- @ WRITE_ FILE "!"
- @ WRITE_ FILE "IDENTIFICATION=""$(VERSION)"""
- @ WRITE_ FILE "GSMATCH=LEQUAL,3,5
- @ WRITE_ FILE "$(LU_OBJECTS)"
- @ WRITE_ FILE "$(LT_OBJECTS)"
- @ WRITE_ FILE "$(LI_OBJECTS)"
- @ WRITE_ FILE "$(LI_OBJECTS1)"
- @ WRITE_ FILE "$(LI2_OBJECTS)"
- @ WRITE_ FILE "$(LI2_OBJECTS1)"
- @ WRITE_ FILE "$(LI2_OBJECTS2)"
- @ WRITE_ FILE "$(LI2_OBJECTS3)"
- @ WRITE_ FILE "$(LI2_OBJECTS4)"
- @ WRITE_ FILE "$(LI2_OBJECTS5)"
- @ WRITE_ FILE "$(LI2_OBJECTS6)"
- @ WRITE_ FILE "$(LI2_OBJECTS7)"
- @ WRITE_ FILE "$(LI2_OBJECTS8)"
- @ WRITE_ FILE "$(LN_OBJECTS)"
- @ WRITE_ FILE "$(LN_OBJECTS1)"
- @ WRITE_ FILE "$(LN_OBJECTS2)"
- @ WRITE_ FILE "$(LN_OBJECTS3)"
- @ WRITE_ FILE "$(LN_OBJECTS4)"
- @ WRITE_ FILE "[---.lib]libmesagl.exe/SHARE"
- @ WRITE_ FILE "SYS$SHARE:DECW$XEXTLIBSHR/SHARE"
- @ WRITE_ FILE "SYS$SHARE:DECW$XLIBSHR/SHARE"
- @ CLOSE_ FILE
-# @ WRITE_ SYS$OUTPUT " generating mesagl.map ..."
-# @ CXXLINK_/NODEB/NOSHARE/NOEXE/MAP=mesagl.map/FULL mesagl1.opt/OPT
-# @ WRITE_ SYS$OUTPUT " analyzing mesagl.map ..."
-# @ @[-.vms]ANALYZE_MAP.COM mesagl.map mesagl.opt
- @ WRITE_ SYS$OUTPUT " linking $(GLU_SHAR) ..."
-# @ CXXLINK_/noinform/NODEB/SHARE=$(GLU_SHAR)/MAP=mesagl.map/FULL mesagl1.opt/opt,mesagl.opt/opt
- @ CXXLINK_/noinform/NODEB/SHARE=$(GLU_SHAR)/MAP=mesagl.map/FULL mesagl1.opt/opt,mesaglu.opt/opt
- @ rename $(GLU_SHAR)* $(LIBDIR)
-.endif
-
-clean :
- delete [...]*.obj;*
- purge
-
-[.libutil]error.obj : [.libutil]error.c
- $(CC) $(CFLAGS) /obj=[.libutil]error.obj [.libutil]error.c
-
-[.libutil]glue.obj : [.libutil]glue.c
- $(CC) $(CFLAGS) /obj=[.libutil]glue.obj [.libutil]glue.c
-
-[.libutil]mipmap.obj : [.libutil]mipmap.c
- $(CC) $(CFLAGS) /obj=[.libutil]mipmap.obj [.libutil]mipmap.c
-
-[.libutil]project.obj : [.libutil]project.c
- $(CC) $(CFLAGS) /obj=[.libutil]project.obj [.libutil]project.c
-
-[.libutil]quad.obj : [.libutil]quad.c
- $(CC) $(CFLAGS) /obj=[.libutil]quad.obj [.libutil]quad.c
-
-[.libutil]registry.obj : [.libutil]registry.c
- $(CC) $(CFLAGS) /obj=[.libutil]registry.obj [.libutil]registry.c
-
-[.libtess]dict.obj : [.libtess]dict.c
- $(CC) $(CFLAGS) /obj=[.libtess]dict.obj [.libtess]dict.c
-
-[.libtess]geom.obj : [.libtess]geom.c
- $(CC) $(CFLAGS) /obj=[.libtess]geom.obj [.libtess]geom.c
-
-[.libtess]memalloc.obj : [.libtess]memalloc.c
- $(CC) $(CFLAGS) /obj=[.libtess]memalloc.obj [.libtess]memalloc.c
-
-[.libtess]mesh.obj : [.libtess]mesh.c
- $(CC) $(CFLAGS) /obj=[.libtess]mesh.obj [.libtess]mesh.c
-
-[.libtess]normal.obj : [.libtess]normal.c
- $(CC) $(CFLAGS) /obj=[.libtess]normal.obj [.libtess]normal.c
-
-[.libtess]priorityq.obj : [.libtess]priorityq.c
- $(CC) $(CFLAGS) /obj=[.libtess]priorityq.obj [.libtess]priorityq.c
-
-[.libtess]render.obj : [.libtess]render.c
- $(CC) $(CFLAGS) /obj=[.libtess]render.obj [.libtess]render.c
-
-[.libtess]sweep.obj : [.libtess]sweep.c
- $(CC) $(CFLAGS) /obj=[.libtess]sweep.obj [.libtess]sweep.c
-
-[.libtess]tess.obj : [.libtess]tess.c
- $(CC) $(CFLAGS) /obj=[.libtess]tess.obj [.libtess]tess.c
-
-[.libtess]tessmono.obj : [.libtess]tessmono.c
- $(CC) $(CFLAGS) /obj=[.libtess]tessmono.obj [.libtess]tessmono.c
-
-[.libnurbs.interface]bezierEval.obj : [.libnurbs.interface]bezierEval.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.interface]bezierEval.obj [.libnurbs.interface]bezierEval.cc
-
-[.libnurbs.interface]bezierPatch.obj : [.libnurbs.interface]bezierPatch.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.interface]bezierPatch.obj [.libnurbs.interface]bezierPatch.cc
-
-[.libnurbs.interface]bezierPatchMesh.obj : [.libnurbs.interface]bezierPatchMesh.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.interface]bezierPatchMesh.obj [.libnurbs.interface]bezierPatchMesh.cc
-
-[.libnurbs.interface]glcurveval.obj : [.libnurbs.interface]glcurveval.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.interface]glcurveval.obj [.libnurbs.interface]glcurveval.cc
-
-[.libnurbs.interface]glinterface.obj : [.libnurbs.interface]glinterface.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.interface]glinterface.obj [.libnurbs.interface]glinterface.cc
-
-[.libnurbs.interface]glrenderer.obj : [.libnurbs.interface]glrenderer.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.interface]glrenderer.obj [.libnurbs.interface]glrenderer.cc
-
-[.libnurbs.interface]glsurfeval.obj : [.libnurbs.interface]glsurfeval.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.interface]glsurfeval.obj [.libnurbs.interface]glsurfeval.cc
-
-[.libnurbs.interface]incurveeval.obj : [.libnurbs.interface]incurveeval.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.interface]incurveeval.obj [.libnurbs.interface]incurveeval.cc
-
-[.libnurbs.interface]insurfeval.obj : [.libnurbs.interface]insurfeval.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.interface]insurfeval.obj [.libnurbs.interface]insurfeval.cc
-
-[.libnurbs.internals]arc.obj : [.libnurbs.internals]arc.cc
- $(CXX) $(CFLAGS)/list/show=all /obj=[.libnurbs.internals]arc.obj [.libnurbs.internals]arc.cc
-
-[.libnurbs.internals]arcsorter.obj : [.libnurbs.internals]arcsorter.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]arcsorter.obj [.libnurbs.internals]arcsorter.cc
-
-[.libnurbs.internals]arctess.obj : [.libnurbs.internals]arctess.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]arctess.obj [.libnurbs.internals]arctess.cc
-
-[.libnurbs.internals]backend.obj : [.libnurbs.internals]backend.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]backend.obj [.libnurbs.internals]backend.cc
-
-[.libnurbs.internals]basiccrveval.obj : [.libnurbs.internals]basiccrveval.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]basiccrveval.obj [.libnurbs.internals]basiccrveval.cc
-
-[.libnurbs.internals]basicsurfeval.obj : [.libnurbs.internals]basicsurfeval.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]basicsurfeval.obj [.libnurbs.internals]basicsurfeval.cc
-
-[.libnurbs.internals]bin.obj : [.libnurbs.internals]bin.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]bin.obj [.libnurbs.internals]bin.cc
-
-[.libnurbs.internals]bufpool.obj : [.libnurbs.internals]bufpool.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]bufpool.obj [.libnurbs.internals]bufpool.cc
-
-[.libnurbs.internals]cachingeval.obj : [.libnurbs.internals]cachingeval.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]cachingeval.obj [.libnurbs.internals]cachingeval.cc
-
-[.libnurbs.internals]ccw.obj : [.libnurbs.internals]ccw.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]ccw.obj [.libnurbs.internals]ccw.cc
-
-[.libnurbs.internals]coveandtiler.obj : [.libnurbs.internals]coveandtiler.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]coveandtiler.obj [.libnurbs.internals]coveandtiler.cc
-
-[.libnurbs.internals]curve.obj : [.libnurbs.internals]curve.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]curve.obj [.libnurbs.internals]curve.cc
-
-[.libnurbs.internals]curvelist.obj : [.libnurbs.internals]curvelist.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]curvelist.obj [.libnurbs.internals]curvelist.cc
-
-[.libnurbs.internals]curvesub.obj : [.libnurbs.internals]curvesub.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]curvesub.obj [.libnurbs.internals]curvesub.cc
-
-[.libnurbs.internals]dataTransform.obj : [.libnurbs.internals]dataTransform.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]dataTransform.obj [.libnurbs.internals]dataTransform.cc
-
-[.libnurbs.internals]displaylist.obj : [.libnurbs.internals]displaylist.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]displaylist.obj [.libnurbs.internals]displaylist.cc
-
-[.libnurbs.internals]flist.obj : [.libnurbs.internals]flist.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]flist.obj [.libnurbs.internals]flist.cc
-
-[.libnurbs.internals]flistsorter.obj : [.libnurbs.internals]flistsorter.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]flistsorter.obj [.libnurbs.internals]flistsorter.cc
-
-[.libnurbs.internals]hull.obj : [.libnurbs.internals]hull.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]hull.obj [.libnurbs.internals]hull.cc
-
-[.libnurbs.internals]intersect.obj : [.libnurbs.internals]intersect.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]intersect.obj [.libnurbs.internals]intersect.cc
-
-[.libnurbs.internals]knotvector.obj : [.libnurbs.internals]knotvector.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]knotvector.obj [.libnurbs.internals]knotvector.cc
-
-[.libnurbs.internals]mapdesc.obj : [.libnurbs.internals]mapdesc.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]mapdesc.obj [.libnurbs.internals]mapdesc.cc
-
-[.libnurbs.internals]mapdescv.obj : [.libnurbs.internals]mapdescv.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]mapdescv.obj [.libnurbs.internals]mapdescv.cc
-
-[.libnurbs.internals]maplist.obj : [.libnurbs.internals]maplist.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]maplist.obj [.libnurbs.internals]maplist.cc
-
-[.libnurbs.internals]mesher.obj : [.libnurbs.internals]mesher.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]mesher.obj [.libnurbs.internals]mesher.cc
-
-[.libnurbs.internals]monoTriangulationBackend.obj : [.libnurbs.internals]monoTriangulationBackend.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]monoTriangulationBackend.obj [.libnurbs.internals]monoTriangulationBackend.cc
-
-[.libnurbs.internals]monotonizer.obj : [.libnurbs.internals]monotonizer.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]monotonizer.obj [.libnurbs.internals]monotonizer.cc
-
-[.libnurbs.internals]mycode.obj : [.libnurbs.internals]mycode.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]mycode.obj [.libnurbs.internals]mycode.cc
-
-[.libnurbs.internals]nurbsinterfac.obj : [.libnurbs.internals]nurbsinterfac.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]nurbsinterfac.obj [.libnurbs.internals]nurbsinterfac.cc
-
-[.libnurbs.internals]nurbstess.obj : [.libnurbs.internals]nurbstess.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]nurbstess.obj [.libnurbs.internals]nurbstess.cc
-
-[.libnurbs.internals]patch.obj : [.libnurbs.internals]patch.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]patch.obj [.libnurbs.internals]patch.cc
-
-[.libnurbs.internals]patchlist.obj : [.libnurbs.internals]patchlist.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]patchlist.obj [.libnurbs.internals]patchlist.cc
-
-[.libnurbs.internals]quilt.obj : [.libnurbs.internals]quilt.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]quilt.obj [.libnurbs.internals]quilt.cc
-
-[.libnurbs.internals]reader.obj : [.libnurbs.internals]reader.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]reader.obj [.libnurbs.internals]reader.cc
-
-[.libnurbs.internals]renderhints.obj : [.libnurbs.internals]renderhints.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]renderhints.obj [.libnurbs.internals]renderhints.cc
-
-[.libnurbs.internals]slicer.obj : [.libnurbs.internals]slicer.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]slicer.obj [.libnurbs.internals]slicer.cc
-
-[.libnurbs.internals]sorter.obj : [.libnurbs.internals]sorter.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]sorter.obj [.libnurbs.internals]sorter.cc
-
-[.libnurbs.internals]splitarcs.obj : [.libnurbs.internals]splitarcs.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]splitarcs.obj [.libnurbs.internals]splitarcs.cc
-
-[.libnurbs.internals]subdivider.obj : [.libnurbs.internals]subdivider.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]subdivider.obj [.libnurbs.internals]subdivider.cc
-
-[.libnurbs.internals]tobezier.obj : [.libnurbs.internals]tobezier.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]tobezier.obj [.libnurbs.internals]tobezier.cc
-
-[.libnurbs.internals]trimline.obj : [.libnurbs.internals]trimline.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]trimline.obj [.libnurbs.internals]trimline.cc
-
-[.libnurbs.internals]trimregion.obj : [.libnurbs.internals]trimregion.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]trimregion.obj [.libnurbs.internals]trimregion.cc
-
-[.libnurbs.internals]trimvertpool.obj : [.libnurbs.internals]trimvertpool.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]trimvertpool.obj [.libnurbs.internals]trimvertpool.cc
-
-[.libnurbs.internals]uarray.obj : [.libnurbs.internals]uarray.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]uarray.obj [.libnurbs.internals]uarray.cc
-
-[.libnurbs.internals]varray.obj : [.libnurbs.internals]varray.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.internals]varray.obj [.libnurbs.internals]varray.cc
-
-[.libnurbs.nurbtess]directedLine.obj : [.libnurbs.nurbtess]directedLine.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]directedLine.obj [.libnurbs.nurbtess]directedLine.cc
-
-[.libnurbs.nurbtess]gridWrap.obj : [.libnurbs.nurbtess]gridWrap.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]gridWrap.obj [.libnurbs.nurbtess]gridWrap.cc
-
-[.libnurbs.nurbtess]monoChain.obj : [.libnurbs.nurbtess]monoChain.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]monoChain.obj [.libnurbs.nurbtess]monoChain.cc
-
-[.libnurbs.nurbtess]monoPolyPart.obj : [.libnurbs.nurbtess]monoPolyPart.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]monoPolyPart.obj [.libnurbs.nurbtess]monoPolyPart.cc
-
-[.libnurbs.nurbtess]monoTriangulation.obj : [.libnurbs.nurbtess]monoTriangulation.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]monoTriangulation.obj [.libnurbs.nurbtess]monoTriangulation.cc
-
-[.libnurbs.nurbtess]partitionX.obj : [.libnurbs.nurbtess]partitionX.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]partitionX.obj [.libnurbs.nurbtess]partitionX.cc
-
-[.libnurbs.nurbtess]partitionY.obj : [.libnurbs.nurbtess]partitionY.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]partitionY.obj [.libnurbs.nurbtess]partitionY.cc
-
-[.libnurbs.nurbtess]polyDBG.obj : [.libnurbs.nurbtess]polyDBG.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]polyDBG.obj [.libnurbs.nurbtess]polyDBG.cc
-
-[.libnurbs.nurbtess]polyUtil.obj : [.libnurbs.nurbtess]polyUtil.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]polyUtil.obj [.libnurbs.nurbtess]polyUtil.cc
-
-[.libnurbs.nurbtess]primitiveStream.obj : [.libnurbs.nurbtess]primitiveStream.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]primitiveStream.obj [.libnurbs.nurbtess]primitiveStream.cc
-
-[.libnurbs.nurbtess]quicksort.obj : [.libnurbs.nurbtess]quicksort.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]quicksort.obj [.libnurbs.nurbtess]quicksort.cc
-
-[.libnurbs.nurbtess]rectBlock.obj : [.libnurbs.nurbtess]rectBlock.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]rectBlock.obj [.libnurbs.nurbtess]rectBlock.cc
-
-[.libnurbs.nurbtess]sampleComp.obj : [.libnurbs.nurbtess]sampleComp.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]sampleComp.obj [.libnurbs.nurbtess]sampleComp.cc
-
-[.libnurbs.nurbtess]sampleCompBot.obj : [.libnurbs.nurbtess]sampleCompBot.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]sampleCompBot.obj [.libnurbs.nurbtess]sampleCompBot.cc
-
-[.libnurbs.nurbtess]sampleCompRight.obj : [.libnurbs.nurbtess]sampleCompRight.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]sampleCompRight.obj [.libnurbs.nurbtess]sampleCompRight.cc
-
-[.libnurbs.nurbtess]sampleCompTop.obj : [.libnurbs.nurbtess]sampleCompTop.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]sampleCompTop.obj [.libnurbs.nurbtess]sampleCompTop.cc
-
-[.libnurbs.nurbtess]sampleMonoPoly.obj : [.libnurbs.nurbtess]sampleMonoPoly.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]sampleMonoPoly.obj [.libnurbs.nurbtess]sampleMonoPoly.cc
-
-[.libnurbs.nurbtess]sampledLine.obj : [.libnurbs.nurbtess]sampledLine.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]sampledLine.obj [.libnurbs.nurbtess]sampledLine.cc
-
-[.libnurbs.nurbtess]searchTree.obj : [.libnurbs.nurbtess]searchTree.cc
- $(CXX) $(CFLAGS) /obj=[.libnurbs.nurbtess]searchTree.obj [.libnurbs.nurbtess]searchTree.cc
diff --git a/src/glu/sgi/glu.exports.darwin b/src/glu/sgi/glu.exports.darwin
index 62d20ae1fb..4f56e36f3b 100644
--- a/src/glu/sgi/glu.exports.darwin
+++ b/src/glu/sgi/glu.exports.darwin
@@ -1,59 +1,59 @@
-_gluBeginCurve
-_gluBeginPolygon
-_gluBeginSurface
-_gluBeginTrim
-_gluBuild1DMipmapLevels
-_gluBuild1DMipmaps
-_gluBuild2DMipmapLevels
-_gluBuild2DMipmaps
-_gluBuild3DMipmapLevels
-_gluBuild3DMipmaps
-_gluCheckExtension
-_gluCylinder
-_gluDeleteNurbsRenderer
-_gluDeleteQuadric
-_gluDeleteTess
-_gluDisk
-_gluEndCurve
-_gluEndPolygon
-_gluEndSurface
-_gluEndTrim
-_gluErrorString
-_gluGetNurbsProperty
-_gluGetString
-_gluGetTessProperty
-_gluLoadSamplingMatrices
-_gluLookAt
-_gluNewNurbsRenderer
-_gluNewQuadric
-_gluNewTess
-_gluNextContour
-_gluNurbsCallback
-_gluNurbsCallbackData
-_gluNurbsCallbackDataEXT
-_gluNurbsCurve
-_gluNurbsProperty
-_gluNurbsSurface
-_gluOrtho2D
-_gluPartialDisk
-_gluPerspective
-_gluPickMatrix
-_gluProject
-_gluPwlCurve
-_gluQuadricCallback
-_gluQuadricDrawStyle
-_gluQuadricNormals
-_gluQuadricOrientation
-_gluQuadricTexture
-_gluScaleImage
-_gluSphere
-_gluTessBeginContour
-_gluTessBeginPolygon
-_gluTessCallback
-_gluTessEndContour
-_gluTessEndPolygon
-_gluTessNormal
-_gluTessProperty
-_gluTessVertex
-_gluUnProject
-_gluUnProject4
+_*gluBeginCurve
+_*gluBeginPolygon
+_*gluBeginSurface
+_*gluBeginTrim
+_*gluBuild1DMipmapLevels
+_*gluBuild1DMipmaps
+_*gluBuild2DMipmapLevels
+_*gluBuild2DMipmaps
+_*gluBuild3DMipmapLevels
+_*gluBuild3DMipmaps
+_*gluCheckExtension
+_*gluCylinder
+_*gluDeleteNurbsRenderer
+_*gluDeleteQuadric
+_*gluDeleteTess
+_*gluDisk
+_*gluEndCurve
+_*gluEndPolygon
+_*gluEndSurface
+_*gluEndTrim
+_*gluErrorString
+_*gluGetNurbsProperty
+_*gluGetString
+_*gluGetTessProperty
+_*gluLoadSamplingMatrices
+_*gluLookAt
+_*gluNewNurbsRenderer
+_*gluNewQuadric
+_*gluNewTess
+_*gluNextContour
+_*gluNurbsCallback
+_*gluNurbsCallbackData
+_*gluNurbsCallbackDataEXT
+_*gluNurbsCurve
+_*gluNurbsProperty
+_*gluNurbsSurface
+_*gluOrtho2D
+_*gluPartialDisk
+_*gluPerspective
+_*gluPickMatrix
+_*gluProject
+_*gluPwlCurve
+_*gluQuadricCallback
+_*gluQuadricDrawStyle
+_*gluQuadricNormals
+_*gluQuadricOrientation
+_*gluQuadricTexture
+_*gluScaleImage
+_*gluSphere
+_*gluTessBeginContour
+_*gluTessBeginPolygon
+_*gluTessCallback
+_*gluTessEndContour
+_*gluTessEndPolygon
+_*gluTessNormal
+_*gluTessProperty
+_*gluTessVertex
+_*gluUnProject
+_*gluUnProject4
diff --git a/src/glut/beos/Makefile b/src/glut/beos/Makefile
index 14f4f43f84..a9f8684c9b 100644
--- a/src/glut/beos/Makefile
+++ b/src/glut/beos/Makefile
@@ -92,6 +92,7 @@ clean:
-rm -f *.o
depend: $(SOURCES)
+ rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES) > /dev/null
diff --git a/src/glut/directfb/Makefile b/src/glut/directfb/Makefile
index 34c3743ef4..bf93d63e30 100644
--- a/src/glut/directfb/Makefile
+++ b/src/glut/directfb/Makefile
@@ -70,6 +70,7 @@ $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME): depend $(OBJECTS)
# Run 'make -f Makefile.solo dep' to update the dependencies if you change
# what's included by any source file.
depend: $(SOURCES)
+ rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES) > /dev/null
diff --git a/src/glut/dos/Makefile.DJ b/src/glut/dos/Makefile.DJ
deleted file mode 100644
index 7e4e0b8576..0000000000
--- a/src/glut/dos/Makefile.DJ
+++ /dev/null
@@ -1,126 +0,0 @@
-# DOS/DJGPP Mesa Utility Toolkit
-# Version: 1.0
-#
-# Copyright (C) 2005 Daniel Borca 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
-# DANIEL BORCA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-#
-# Available options:
-#
-# Environment variables:
-# CFLAGS
-#
-# GLIDE path to Glide3 SDK; used to resolve DXEs.
-# default = $(TOP)/glide3
-#
-# Targets:
-# all: build GLUT
-# clean: remove object files
-#
-
-
-
-.PHONY: all clean
-
-TOP = ../../..
-GLIDE ?= $(TOP)/glide3
-LIBDIR = $(TOP)/lib
-GLUT_LIB = libglut.a
-GLUT_DXE = glut.dxe
-GLUT_IMP = libiglut.a
-
-export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH);$(LIBDIR);$(GLIDE)/lib
-
-CC = gcc
-CFLAGS += -I$(TOP)/include -I. -IPC_HW
-CFLAGS += -DGLUT_IMPORT_LIB
-
-AR = ar
-ARFLAGS = crus
-
-HAVEDXE3 = $(wildcard $(DJDIR)/bin/dxe3gen.exe)
-
-ifeq ($(wildcard $(addsuffix /rm.exe,$(subst ;, ,$(PATH)))),)
-UNLINK = del $(subst /,\,$(1))
-else
-UNLINK = $(RM) $(1)
-endif
-
-CORE_SOURCES = \
- loop.c \
- callback.c \
- color.c \
- extens.c \
- init.c \
- menu.c \
- mouse.c \
- overlay.c \
- state.c \
- util.c \
- window.c \
- f8x13.c \
- f9x15.c \
- hel10.c \
- hel12.c \
- hel18.c \
- tr10.c \
- tr24.c \
- mroman.c \
- roman.c \
- bitmap.c \
- stroke.c \
- teapot.c \
- shapes.c
-
-PC_HW_SOURCES = \
- PC_HW/pc_hw.c \
- PC_HW/pc_keyb.c \
- PC_HW/pc_mouse.c \
- PC_HW/pc_timer.c \
- PC_HW/pc_irq.S
-
-SOURCES = $(CORE_SOURCES) $(PC_HW_SOURCES)
-
-OBJECTS = $(addsuffix .o,$(basename $(SOURCES)))
-
-.c.o:
- $(CC) -o $@ $(CFLAGS) -c $<
-.S.o:
- $(CC) -o $@ $(CFLAGS) -c $<
-.s.o:
- $(CC) -o $@ $(CFLAGS) -x assembler-with-cpp -c $<
-
-all: $(LIBDIR)/$(GLUT_LIB) $(LIBDIR)/$(GLUT_DXE) $(LIBDIR)/$(GLUT_IMP)
-
-$(LIBDIR)/$(GLUT_LIB): $(OBJECTS)
- $(AR) $(ARFLAGS) $@ $^
-
-$(LIBDIR)/$(GLUT_DXE) $(LIBDIR)/$(GLUT_IMP): $(OBJECTS)
-ifeq ($(HAVEDXE3),)
- $(warning Missing DXE3 package... Skipping $(GLUT_DXE))
-else
- -dxe3gen -o $(LIBDIR)/$(GLUT_DXE) -Y $(LIBDIR)/$(GLUT_IMP) -D "MesaGLUT DJGPP" -E _glut -P gl.dxe -U $^
-endif
-
-clean:
- -$(call UNLINK,*.o)
- -$(call UNLINK,PC_HW/*.o)
-
--include depend
diff --git a/src/glut/fbdev/Makefile b/src/glut/fbdev/Makefile
index 4081ccec74..c150ea88dc 100644
--- a/src/glut/fbdev/Makefile
+++ b/src/glut/fbdev/Makefile
@@ -72,11 +72,12 @@ install:
$(INSTALL) -d $(DESTDIR)$(INSTALL_INC_DIR)/GL
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -m 644 $(TOP)/include/GL/glut.h $(DESTDIR)$(INSTALL_INC_DIR)/GL
- $(INSTALL) $(TOP)/$(LIB_DIR)/libglut* $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/libglut* $(DESTDIR)$(INSTALL_LIB_DIR)
# Run 'make -f Makefile.solo dep' to update the dependencies if you change
# what's included by any source file.
depend: $(SOURCES)
+ rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES) > /dev/null
diff --git a/src/glut/ggi/Makefile b/src/glut/ggi/Makefile
index 1ae1ba0d70..c23dfcac10 100644
--- a/src/glut/ggi/Makefile
+++ b/src/glut/ggi/Makefile
@@ -46,6 +46,7 @@ clean:
depend: $(SOURCES)
+ rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) -I$(TOP)/include $(SOURCES)
diff --git a/src/glut/glx/Makefile b/src/glut/glx/Makefile
index 87301f1b77..6889cd4b40 100644
--- a/src/glut/glx/Makefile
+++ b/src/glut/glx/Makefile
@@ -107,7 +107,8 @@ pcedit = sed \
-e 's,@VERSION@,$(GLUT_MAJOR).$(GLUT_MINOR).$(GLUT_TINY),' \
-e 's,@GLUT_PC_REQ_PRIV@,$(GLUT_PC_REQ_PRIV),' \
-e 's,@GLUT_PC_LIB_PRIV@,$(GLUT_PC_LIB_PRIV),' \
- -e 's,@GLUT_PC_CFLAGS@,$(GLUT_PC_CFLAGS),'
+ -e 's,@GLUT_PC_CFLAGS@,$(GLUT_PC_CFLAGS),' \
+ -e 's,@GLUT_LIB@,$(GLUT_LIB),'
glut.pc: glut.pc.in
$(pcedit) $< > $@
@@ -116,7 +117,7 @@ install: glut.pc
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
$(INSTALL) -m 644 $(TOP)/include/GL/glut.h $(DESTDIR)$(INSTALL_INC_DIR)/GL
- $(INSTALL) $(TOP)/$(LIB_DIR)/$(GLUT_LIB_GLOB) $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GLUT_LIB_GLOB) $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -m 644 glut.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
@@ -131,6 +132,7 @@ clean:
depend: $(SOURCES)
@ echo "running $(MKDEP)"
+ @ rm -f depend
@ touch depend
@ $(MKDEP) $(MKDEP_OPTIONS) -I$(TOP)/include $(SOURCES) \
$(X11_INCLUDES) > /dev/null
diff --git a/src/glut/glx/SConscript b/src/glut/glx/SConscript
new file mode 100644
index 0000000000..938fec03df
--- /dev/null
+++ b/src/glut/glx/SConscript
@@ -0,0 +1,87 @@
+Import('*')
+
+env = env.Clone()
+
+if env['platform'] != 'windows':
+ Return()
+
+target = 'glut32'
+
+env.Replace(CPPDEFINES = [
+ 'BUILD_GLUT32',
+ 'GLUT_BUILDING_LIB',
+ 'NDEBUG',
+ 'GLUT_NO_WARNING_DISABLE',
+])
+
+env.AppendUnique(CPPPATH = [
+ '#/include',
+])
+
+env.PrependUnique(LIBS = [
+ 'winmm',
+ 'gdi32',
+ 'user32',
+ 'opengl32',
+ 'glu32',
+])
+
+sources = [
+ 'glut_bitmap.c',
+ 'glut_bwidth.c',
+ 'glut_cindex.c',
+ 'glut_cmap.c',
+ 'glut_cursor.c',
+ 'glut_dials.c',
+ 'glut_dstr.c',
+ 'glut_event.c',
+ 'glut_ext.c',
+ 'glut_fullscrn.c',
+ 'glut_gamemode.c',
+ 'glut_get.c',
+ 'glut_init.c',
+ 'glut_input.c',
+ 'glut_joy.c',
+ 'glut_key.c',
+ 'glut_keyctrl.c',
+ 'glut_keyup.c',
+ 'glut_mesa.c',
+ 'glut_modifier.c',
+ 'glut_overlay.c',
+ 'glut_ppm.c',
+ 'glut_shapes.c',
+ 'glut_space.c',
+ 'glut_stroke.c',
+ 'glut_swap.c',
+ 'glut_swidth.c',
+ 'glut_tablet.c',
+ 'glut_teapot.c',
+ 'glut_util.c',
+ 'glut_vidresize.c',
+ 'glut_warp.c',
+ 'glut_win.c',
+ 'glut_winmisc.c',
+
+ 'win32_glx.c',
+ 'win32_menu.c',
+ 'win32_util.c',
+ 'win32_winproc.c',
+ 'win32_x11.c',
+
+ 'glut_8x13.c',
+ 'glut_9x15.c',
+ 'glut_hel10.c',
+ 'glut_hel12.c',
+ 'glut_hel18.c',
+ 'glut_mroman.c',
+ 'glut_roman.c',
+ 'glut_tr10.c',
+ 'glut_tr24.c',
+
+ 'glut.def',
+]
+
+env.SharedLibrary(
+ target = target,
+ source = sources,
+)
diff --git a/src/glut/glx/descrip.mms b/src/glut/glx/descrip.mms
deleted file mode 100644
index 2e858309b6..0000000000
--- a/src/glut/glx/descrip.mms
+++ /dev/null
@@ -1,208 +0,0 @@
-# Makefile for GLUT for VMS
-# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl
-
-.first
- define gl [---.include.gl]
-
-.include [---]mms-config.
-
-##### MACROS #####
-GLUT_MAJOR = 3
-GLUT_MINOR = 7
-
-VPATH = RCS
-
-INCDIR = [---.include]
-LIBDIR = [---.lib]
-CFLAGS = /nowarn/include=$(INCDIR)/prefix=all/name=(as_is,short)/float=ieee/ieee=denorm
-
-SOURCES = \
-glut_8x13.c \
-glut_9x15.c \
-glut_bitmap.c \
-glut_bwidth.c \
-glut_cindex.c \
-glut_cmap.c \
-glut_cursor.c \
-glut_dials.c \
-glut_dstr.c \
-glut_event.c \
-glut_ext.c \
-glut_fullscrn.c \
-glut_gamemode.c \
-glut_get.c \
-glut_glxext.c \
-glut_hel10.c \
-glut_hel12.c \
-glut_hel18.c \
-glut_init.c \
-glut_input.c \
-glut_joy.c \
-glut_key.c \
-glut_keyctrl.c \
-glut_keyup.c \
-glut_menu.c \
-glut_menu2.c \
-glut_mesa.c \
-glut_modifier.c \
-glut_mroman.c \
-glut_overlay.c \
-glut_roman.c \
-glut_shapes.c \
-glut_space.c \
-glut_stroke.c \
-glut_swap.c \
-glut_swidth.c \
-glut_tablet.c \
-glut_teapot.c \
-glut_tr10.c \
-glut_tr24.c \
-glut_util.c \
-glut_vidresize.c \
-glut_warp.c \
-glut_win.c \
-glut_winmisc.c \
-layerutil.c
-
-OBJECTS0=glut_8x13.obj,\
-glut_9x15.obj,\
-glut_bitmap.obj,\
-glut_bwidth.obj,\
-glut_cindex.obj,\
-glut_cmap.obj,\
-glut_cursor.obj,\
-glut_dials.obj,\
-glut_dstr.obj,\
-glut_event.obj,\
-glut_ext.obj,\
-glut_fullscrn.obj,\
-glut_gamemode.obj
-
-OBJECTS1=glut_get.obj,\
-glut_glxext.obj,\
-glut_hel10.obj,\
-glut_hel12.obj,\
-glut_hel18.obj,\
-glut_init.obj,\
-glut_input.obj,\
-glut_joy.obj,\
-glut_key.obj,\
-glut_keyctrl.obj,\
-glut_keyup.obj,\
-glut_menu.obj,\
-glut_menu2.obj,\
-glut_mesa.obj,\
-glut_modifier.obj
-
-OBJECTS2=glut_mroman.obj,\
-glut_overlay.obj,\
-glut_roman.obj,\
-glut_shapes.obj,\
-glut_space.obj,\
-glut_stroke.obj,\
-glut_swap.obj,\
-glut_swidth.obj,\
-glut_tablet.obj,\
-glut_teapot.obj,\
-glut_tr10.obj,\
-glut_tr24.obj,\
-glut_util.obj,\
-glut_vidresize.obj
-
-OBJECTS3=glut_warp.obj,\
-glut_win.obj,\
-glut_winmisc.obj,\
-layerutil.obj
-
-##### RULES #####
-
-VERSION=Glut V3.7
-
-##### TARGETS #####
-
-# Make the library
-$(LIBDIR)$(GLUT_LIB) : $(OBJECTS0) $(OBJECTS1) $(OBJECTS2) $(OBJECTS3)
- @ $(MAKELIB) $(GLUT_LIB) $(OBJECTS0)
- @ library $(GLUT_LIB) $(OBJECTS1)
- @ library $(GLUT_LIB) $(OBJECTS2)
- @ library $(GLUT_LIB) $(OBJECTS3)
- @ rename $(GLUT_LIB)* $(LIBDIR)
-.ifdef SHARE
- @ WRITE_ SYS$OUTPUT " generating mesagl1.opt"
- @ OPEN_/WRITE FILE mesagl1.opt
- @ WRITE_ FILE "!"
- @ WRITE_ FILE "! mesagl1.opt generated by DESCRIP.$(MMS_EXT)"
- @ WRITE_ FILE "!"
- @ WRITE_ FILE "IDENTIFICATION=""$(VERSION)"""
- @ WRITE_ FILE "GSMATCH=LEQUAL,3,7
- @ WRITE_ FILE "$(OBJECTS0)"
- @ WRITE_ FILE "$(OBJECTS1)"
- @ WRITE_ FILE "$(OBJECTS2)"
- @ WRITE_ FILE "$(OBJECTS3)"
- @ WRITE_ FILE "[---.lib]libmesaglu.exe/SHARE"
- @ WRITE_ FILE "[---.lib]libmesagl.exe/SHARE"
- @ write file "sys$library:decw$xmulibshr.exe/share"
- @ WRITE_ FILE "SYS$SHARE:DECW$XEXTLIBSHR/SHARE"
- @ WRITE_ FILE "SYS$SHARE:DECW$XLIBSHR/SHARE"
- @ CLOSE_ FILE
- @ WRITE_ SYS$OUTPUT " generating mesagl.map ..."
- @ CXXLINK_/NODEB/NOSHARE/NOEXE/MAP=mesagl.map/FULL mesagl1.opt/OPT
- @ WRITE_ SYS$OUTPUT " analyzing mesagl.map ..."
- @ @[---.vms]ANALYZE_MAP.COM mesagl.map mesagl.opt
- @ WRITE_ SYS$OUTPUT " linking $(GLUT_SHAR) ..."
- @ CXXLINK_/NODEB/SHARE=$(GLUT_SHAR)/MAP=mesagl.map/FULL mesagl1.opt/opt,mesagl.opt/opt
- @ rename $(GLUT_SHAR)* $(LIBDIR)
-.endif
-
-clean :
- delete *.obj;*
- purge
-
-include mms_depend.
-
-glut_8x13.obj : glut_8x13.c
-glut_9x15.obj : glut_9x15.c
-glut_bitmap.obj : glut_bitmap.c
-glut_bwidth.obj : glut_bwidth.c
-glut_cindex.obj : glut_cindex.c
-glut_cmap.obj : glut_cmap.c
-glut_cursor.obj : glut_cursor.c
-glut_dials.obj : glut_dials.c
-glut_dstr.obj : glut_dstr.c
-glut_event.obj : glut_event.c
-glut_ext.obj : glut_ext.c
-glut_fullscrn.obj : glut_fullscrn.c
-glut_gamemode.obj : glut_gamemode.c
-glut_get.obj : glut_get.c
-glut_glxext.obj : glut_glxext.c
-glut_hel10.obj : glut_hel10.c
-glut_hel12.obj : glut_hel12.c
-glut_hel18.obj : glut_hel18.c
-glut_init.obj : glut_init.c
-glut_input.obj : glut_input.c
-glut_joy.obj : glut_joy.c
-glut_key.obj : glut_key.c
-glut_keyctrl.obj : glut_keyctrl.c
-glut_keyup.obj : glut_keyup.c
-glut_menu.obj : glut_menu.c
-glut_menu2.obj : glut_menu2.c
-glut_mesa.obj : glut_mesa.c
-glut_modifier.obj : glut_modifier.c
-glut_mroman.obj : glut_mroman.c
-glut_overlay.obj : glut_overlay.c
-glut_roman.obj : glut_roman.c
-glut_shapes.obj : glut_shapes.c
-glut_space.obj : glut_space.c
-glut_stroke.obj : glut_stroke.c
-glut_swap.obj : glut_swap.c
-glut_swidth.obj : glut_swidth.c
-glut_tablet.obj : glut_tablet.c
-glut_teapot.obj : glut_teapot.c
-glut_tr10.obj : glut_tr10.c
-glut_tr24.obj : glut_tr24.c
-glut_util.obj : glut_util.c
-glut_vidresize.obj : glut_vidresize.c
-glut_warp.obj : glut_warp.c
-glut_win.obj : glut_win.c
-glut_winmisc.obj : glut_winmisc.c
-layerutil.obj : layerutil.c
diff --git a/src/glut/glx/glut.def b/src/glut/glx/glut.def
index d5e0e0cf2a..90010815e4 100644
--- a/src/glut/glx/glut.def
+++ b/src/glut/glx/glut.def
@@ -1,9 +1,4 @@
-DESCRIPTION 'OpenGL Utility Toolkit for Win32'
-
-VERSION 3.7
-
EXPORTS
-
glutAddMenuEntry
glutAddSubMenu
glutAttachMenu
@@ -128,4 +123,3 @@ EXPORTS
glutBitmapTimesRoman24
; __glutSetFCB
; __glutGetFCB
-
diff --git a/src/glut/glx/glut.pc.in b/src/glut/glx/glut.pc.in
index ae0689d7e8..151dd0b802 100644
--- a/src/glut/glx/glut.pc.in
+++ b/src/glut/glx/glut.pc.in
@@ -8,6 +8,6 @@ Description: Mesa OpenGL Utility Toolkit library
Requires: gl glu
Requires.private: @GLUT_PC_REQ_PRIV@
Version: @VERSION@
-Libs: -L${libdir} -lglut
+Libs: -L${libdir} -l@GLUT_LIB@
Libs.private: @GLUT_PC_LIB_PRIV@
Cflags: -I${includedir} @GLUT_PC_CFLAGS@
diff --git a/src/glut/glx/glut_event.c b/src/glut/glx/glut_event.c
index b5df7b2311..d6d963896a 100644
--- a/src/glut/glx/glut_event.c
+++ b/src/glut/glx/glut_event.c
@@ -1321,7 +1321,12 @@ processWindowWorkList(GLUTwindow * window)
is where the finish works gets queued for indirect
contexts. */
__glutSetWindow(window);
- glFinish();
+#if !defined(_WIN32)
+ if (!window->isDirect)
+#endif
+ {
+ glFinish();
+ }
}
if (workMask & GLUT_DEBUG_WORK) {
__glutSetWindow(window);
@@ -1338,9 +1343,7 @@ processWindowWorkList(GLUTwindow * window)
}
}
-#ifndef _WIN32
static /* X11 implementations do not need this global. */
-#endif
void
__glutProcessWindowWorkLists(void)
{
diff --git a/src/glut/glx/glut_input.c b/src/glut/glx/glut_input.c
index a76ff9a435..7d2eda00f7 100644
--- a/src/glut/glx/glut_input.c
+++ b/src/glut/glx/glut_input.c
@@ -295,6 +295,7 @@ __glutProcessDeviceEvents(XEvent * event)
static GLUTeventParser eventParser =
{__glutProcessDeviceEvents, NULL};
+#if !defined(_WIN32)
static void
addDeviceEventParser(void)
{
@@ -305,6 +306,7 @@ addDeviceEventParser(void)
been_here = True;
__glutRegisterEventParser(&eventParser);
}
+#endif
static int
probeDevices(void)
diff --git a/src/glut/glx/glutint.h b/src/glut/glx/glutint.h
index f32da28239..ba30af60f0 100644
--- a/src/glut/glx/glutint.h
+++ b/src/glut/glx/glutint.h
@@ -32,10 +32,6 @@
#include <GL/glut.h>
-#if defined(MESA) && defined(_WIN32) && !defined(__CYGWIN32__)
-#include <gl/mesa_wgl.h>
-#endif
-
#ifndef _WIN32
/* added by BrianP: */
#ifndef APIENTRY
@@ -48,24 +44,6 @@
/* GLUT_BUILDING_LIB is used by <GL/glut.h> to 1) not #pragma link
with the GLUT library, and 2) avoid the Win32 atexit hack. */
-/* This must be done after <GL/gl.h> is included. MESA is defined
- if the <GL/gl.h> is supplied by Brian Paul's Mesa library. */
-#if defined(MESA) && defined(_WIN32)
-/* Mesa implements "wgl" versions of GDI entry points needed for
- using OpenGL. Map these "wgl" versions to the GDI names via
- macros. */
-#define ChoosePixelFormat wglChoosePixelFormat
-#define DescribePixelFormat wglDescribePixelFormat
-#define GetPixelFormat wglGetPixelFormat
-#define SetPixelFormat wglSetPixelFormat
-#define SwapBuffers wglSwapBuffers
-#define GetCurrentContext wglGetCurrentContext
-#define GetCurrentDC wglGetCurrentDC
-#define MakeCurrent wglMakeCurrent
-#define CreateContext wglCreateContext
-#define DeleteContext wglDeleteContext
-#endif /* MESA */
-
#ifdef SUPPORT_FORTRAN
#include <GL/glutf90.h>
#endif
@@ -572,27 +550,27 @@ typedef struct {
#ifdef _WIN32
#define MAKE_CURRENT_LAYER(window) \
{ \
- HGLRC currentContext = GetCurrentContext(); \
- HDC currentDc = GetCurrentDC(); \
+ HGLRC currentContext = wglGetCurrentContext(); \
+ HDC currentDc = wglGetCurrentDC(); \
\
if (currentContext != window->renderCtx \
|| currentDc != window->renderDc) { \
- MakeCurrent(window->renderDc, window->renderCtx); \
+ wglMakeCurrent(window->renderDc, window->renderCtx); \
} \
}
#define MAKE_CURRENT_WINDOW(window) \
{ \
- HGLRC currentContext = GetCurrentContext(); \
- HDC currentDc = GetCurrentDC(); \
+ HGLRC currentContext = wglGetCurrentContext(); \
+ HDC currentDc = wglGetCurrentDC(); \
\
if (currentContext != window->ctx || currentDc != window->hdc) { \
- MakeCurrent(window->hdc, window->ctx); \
+ wglMakeCurrent(window->hdc, window->ctx); \
} \
}
#define MAKE_CURRENT_OVERLAY(overlay) \
- MakeCurrent(overlay->hdc, overlay->ctx)
+ wglMakeCurrent(overlay->hdc, overlay->ctx)
#define UNMAKE_CURRENT() \
- MakeCurrent(NULL, NULL)
+ wglMakeCurrent(NULL, NULL)
#define SWAP_BUFFERS_WINDOW(window) \
SwapBuffers(window->hdc)
#define SWAP_BUFFERS_LAYER(window) \
diff --git a/src/glut/glx/glutstroke.h b/src/glut/glx/glutstroke.h
index cbc9e156fe..74b60314aa 100644
--- a/src/glut/glx/glutstroke.h
+++ b/src/glut/glx/glutstroke.h
@@ -7,7 +7,7 @@
and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
-#if defined(_WIN32)
+#if defined(_MSC_VER)
#pragma warning (disable:4244) /* disable bogus conversion warnings */
#pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */
#endif
diff --git a/src/glut/glx/glutwin32.h b/src/glut/glx/glutwin32.h
index 304eeb20a2..01db99fad6 100644
--- a/src/glut/glx/glutwin32.h
+++ b/src/glut/glx/glutwin32.h
@@ -41,6 +41,7 @@
/* Private routines from win32_util.c */
#ifndef __CYGWIN32__
+struct timeval;
extern int gettimeofday(struct timeval* tp, void* tzp);
#endif
extern void *__glutFont(void *font);
diff --git a/src/glut/glx/mms_depend b/src/glut/glx/mms_depend
deleted file mode 100644
index 98f87c29e2..0000000000
--- a/src/glut/glx/mms_depend
+++ /dev/null
@@ -1,72 +0,0 @@
-# DO NOT DELETE
-
-glut_8x13.obj : glutbitmap.h [---.include.gl]gl.h
-glut_9x15.obj : glutbitmap.h [---.include.gl]gl.h
-glut_bitmap.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_bitmap.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_bitmap.obj : glutbitmap.h
-glut_bwidth.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_bwidth.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_bwidth.obj : glutbitmap.h
-glut_cindex.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_cindex.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_cindex.obj : layerutil.h
-glut_cursor.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_cursor.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_dials.obj : glutint.h [---.include.gl]glx.h [---.include.gl]gl.h
-glut_dials.obj : [---.include.gl]xmesa.h [---.include.gl]glut.h [---.include.gl]glu.h
-glut_dstr.obj : glutint.h [---.include.gl]glx.h [---.include.gl]gl.h
-glut_dstr.obj : [---.include.gl]xmesa.h [---.include.gl]glut.h [---.include.gl]glu.h
-glut_event.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_event.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_ext.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_ext.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_fullscrn.obj : glutint.h [---.include.gl]glx.h [---.include.gl]gl.h
-glut_fullscrn.obj : [---.include.gl]xmesa.h [---.include.gl]glut.h
-glut_fullscrn.obj : [---.include.gl]glu.h
-glut_get.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_get.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_hel10.obj : glutbitmap.h [---.include.gl]gl.h
-glut_hel12.obj : glutbitmap.h [---.include.gl]gl.h
-glut_hel18.obj : glutbitmap.h [---.include.gl]gl.h
-glut_init.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_init.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_menu.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_menu.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h layerutil.h
-glut_mesa.obj : glutint.h [---.include.gl]glx.h [---.include.gl]gl.h
-glut_mesa.obj : [---.include.gl]xmesa.h [---.include.gl]glut.h [---.include.gl]glu.h
-glut_modifier.obj : glutint.h [---.include.gl]glx.h [---.include.gl]gl.h
-glut_modifier.obj : [---.include.gl]xmesa.h [---.include.gl]glut.h
-glut_modifier.obj : [---.include.gl]glu.h
-glut_mroman.obj : glutstroke.h
-glut_overlay.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_overlay.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_overlay.obj : layerutil.h
-glut_roman.obj : glutstroke.h
-glut_shapes.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_shapes.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_space.obj : glutint.h [---.include.gl]glx.h [---.include.gl]gl.h
-glut_space.obj : [---.include.gl]xmesa.h [---.include.gl]glut.h [---.include.gl]glu.h
-glut_stroke.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_stroke.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_stroke.obj : glutstroke.h
-glut_swidth.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_swidth.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_swidth.obj : glutstroke.h
-glut_tablet.obj : glutint.h [---.include.gl]glx.h [---.include.gl]gl.h
-glut_tablet.obj : [---.include.gl]xmesa.h [---.include.gl]glut.h [---.include.gl]glu.h
-glut_teapot.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_tr10.obj : glutbitmap.h [---.include.gl]gl.h
-glut_tr24.obj : glutbitmap.h [---.include.gl]gl.h
-glut_util.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_util.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_vidresize.obj : [---.include.gl]glx.h [---.include.gl]gl.h
-glut_vidresize.obj : [---.include.gl]xmesa.h glutint.h [---.include.gl]glut.h
-glut_vidresize.obj : [---.include.gl]glu.h
-glut_warp.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_warp.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_win.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_win.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-glut_winmisc.obj : [---.include.gl]glut.h [---.include.gl]gl.h [---.include.gl]glu.h
-glut_winmisc.obj : glutint.h [---.include.gl]glx.h [---.include.gl]xmesa.h
-layerutil.obj : layerutil.h
diff --git a/src/glut/glx/win32_glx.c b/src/glut/glx/win32_glx.c
index ecfff44b93..3522e606ec 100644
--- a/src/glut/glx/win32_glx.c
+++ b/src/glut/glx/win32_glx.c
@@ -22,7 +22,7 @@ glXCreateContext(Display * display, XVisualInfo * visinfo,
routine. */
HGLRC context;
- context = CreateContext(XHDC);
+ context = wglCreateContext(XHDC);
#if 0
/* XXX GLUT doesn't support it now, so don't worry about display list
diff --git a/src/glut/glx/win32_winproc.c b/src/glut/glx/win32_winproc.c
index e1fc785ebb..1b3a297828 100644
--- a/src/glut/glx/win32_winproc.c
+++ b/src/glut/glx/win32_winproc.c
@@ -20,10 +20,10 @@
extern unsigned __glutMenuButton;
extern GLUTidleCB __glutIdleFunc;
extern GLUTtimer *__glutTimerList;
-extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, int unique);
+extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, UINT unique);
static HMENU __glutHMenu;
-void
+static void
updateWindowState(GLUTwindow *window, int visState)
{
GLUTwindow* child;
@@ -548,8 +548,13 @@ __glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
window to be bigger than the screen, and smaller than 100x100
(although it doesn't seem to help the y minimum). */
minmax = (LPMINMAXINFO)lParam;
+#if 0
+ /* These two lines are disabled to fix incorrect handling of
+ * window maximization on Vista. See bug 23182.
+ */
minmax->ptMaxSize.x = __glutScreenWidth;
minmax->ptMaxSize.y = __glutScreenHeight;
+#endif
minmax->ptMinTrackSize.x = 0;
minmax->ptMinTrackSize.y = 0;
minmax->ptMaxTrackSize.x = __glutScreenWidth +
diff --git a/src/glut/glx/win32_x11.h b/src/glut/glx/win32_x11.h
index 6f5c3a9aea..daf065e27b 100644
--- a/src/glut/glx/win32_x11.h
+++ b/src/glut/glx/win32_x11.h
@@ -228,7 +228,7 @@ typedef struct {
SetWindowPos(window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
#define XSetWMName(display, window, tp) \
- SetWindowText(window, (tp)->value)
+ SetWindowText(window, (const char *)(tp)->value)
/* There really isn't a way to set the icon name separate from the
windows name in Win32, so, just set the windows name. */
diff --git a/src/glut/mini/Makefile b/src/glut/mini/Makefile
index 112a250bbd..b82a758d2c 100644
--- a/src/glut/mini/Makefile
+++ b/src/glut/mini/Makefile
@@ -64,6 +64,7 @@ $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME): depend $(OBJECTS)
# Run 'make -f Makefile.solo dep' to update the dependencies if you change
# what's included by any source file.
depend: $(SOURCES)
+ rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES) > /dev/null
@@ -80,7 +81,8 @@ pcedit = sed \
-e 's,@VERSION@,$(GLUT_MAJOR).$(GLUT_MINOR).$(GLUT_TINY),' \
-e 's,@GLUT_PC_REQ_PRIV@,$(GLUT_PC_REQ_PRIV),' \
-e 's,@GLUT_PC_LIB_PRIV@,$(GLUT_PC_LIB_PRIV),' \
- -e 's,@GLUT_PC_CFLAGS@,$(GLUT_PC_CFLAGS),'
+ -e 's,@GLUT_PC_CFLAGS@,$(GLUT_PC_CFLAGS),' \
+ -e 's,@GLUT_LIB@,$(GLUT_LIB),'
glut.pc: glut.pc.in
$(pcedit) $< > $@
@@ -89,7 +91,7 @@ install: glut.pc
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
$(INSTALL) -m 644 $(TOP)/include/GL/glut.h $(DESTDIR)$(INSTALL_INC_DIR)/GL
- $(INSTALL) $(TOP)/$(LIB_DIR)/libglut* $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/libglut* $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -m 644 glut.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
diff --git a/src/glut/mini/glut.pc.in b/src/glut/mini/glut.pc.in
index ae0689d7e8..151dd0b802 100644
--- a/src/glut/mini/glut.pc.in
+++ b/src/glut/mini/glut.pc.in
@@ -8,6 +8,6 @@ Description: Mesa OpenGL Utility Toolkit library
Requires: gl glu
Requires.private: @GLUT_PC_REQ_PRIV@
Version: @VERSION@
-Libs: -L${libdir} -lglut
+Libs: -L${libdir} -l@GLUT_LIB@
Libs.private: @GLUT_PC_LIB_PRIV@
Cflags: -I${includedir} @GLUT_PC_CFLAGS@
diff --git a/src/glw/Makefile b/src/glw/Makefile
index cf412b225e..1fb3d3c320 100644
--- a/src/glw/Makefile
+++ b/src/glw/Makefile
@@ -33,7 +33,8 @@ pcedit = sed \
-e 's,@VERSION@,$(MAJOR).$(MINOR).$(TINY),' \
-e 's,@GLW_PC_REQ_PRIV@,$(GLW_PC_REQ_PRIV),' \
-e 's,@GLW_PC_LIB_PRIV@,$(GLW_PC_LIB_PRIV),' \
- -e 's,@GLW_PC_CFLAGS@,$(GLW_PC_CFLAGS),'
+ -e 's,@GLW_PC_CFLAGS@,$(GLW_PC_CFLAGS),' \
+ -e 's,@GLW_LIB@,$(GLW_LIB),'
glw.pc: glw.pc.in
$(pcedit) $< > $@
@@ -42,7 +43,7 @@ install: glw.pc
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
$(INSTALL) -m 644 *.h $(DESTDIR)$(INSTALL_INC_DIR)/GL
- $(INSTALL) $(TOP)/$(LIB_DIR)/$(GLW_LIB_GLOB) $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GLW_LIB_GLOB) $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -m 644 glw.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
clean:
@@ -64,6 +65,7 @@ $(TOP)/$(LIB_DIR)/$(GLW_LIB_NAME): $(OBJECTS)
# by any source file.
#
depend: $(GLW_SOURCES)
+ rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) -I$(TOP)/include $(GLW_SOURCES) \
$(X11_INCLUDES) > /dev/null
diff --git a/src/glw/glw.pc.in b/src/glw/glw.pc.in
index 5493093be1..19a7c307c0 100644
--- a/src/glw/glw.pc.in
+++ b/src/glw/glw.pc.in
@@ -8,6 +8,6 @@ Description: Mesa OpenGL widget library
Requires: gl
Requires.private: @GLW_PC_REQ_PRIV@
Version: @VERSION@
-Libs: -L${libdir} -lGLw
+Libs: -L${libdir} -l@GLW_LIB@
Libs.private: @GLW_PC_LIB_PRIV@
Cflags: -I${includedir} @GLW_PC_CFLAGS@
diff --git a/src/glx/mini/Makefile b/src/glx/mini/Makefile
index aabc1d2be3..6b5a3c76d7 100644
--- a/src/glx/mini/Makefile
+++ b/src/glx/mini/Makefile
@@ -65,6 +65,7 @@ drmtest: xf86drm.o drmtest.o
depend: $(C_SOURCES) $(ASM_SOURCES)
+ rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \
> /dev/null
diff --git a/src/glx/x11/Makefile b/src/glx/x11/Makefile
index 419cb2853b..86d84d4b9f 100644
--- a/src/glx/x11/Makefile
+++ b/src/glx/x11/Makefile
@@ -39,9 +39,9 @@ SOURCES = \
dri2_glx.c \
dri2.c
-include $(TOP)/src/mesa/sources
+include $(TOP)/src/mesa/sources.mak
-MESA_ASM_API = $(addprefix $(TOP)/src/mesa/, $(ASM_API))
+MESA_GLAPI_ASM_SOURCES = $(addprefix $(TOP)/src/mesa/, $(GLAPI_ASM_SOURCES))
MESA_GLAPI_SOURCES = $(addprefix $(TOP)/src/mesa/, $(GLAPI_SOURCES))
MESA_GLAPI_OBJECTS = $(addprefix $(TOP)/src/mesa/, $(GLAPI_OBJECTS))
@@ -77,10 +77,11 @@ $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(OBJECTS) Makefile
$(GL_LIB_DEPS) $(OBJECTS)
-depend: $(SOURCES) $(MESA_GLAPI_SOURCES) $(MESA_ASM_API) Makefile
+depend: $(SOURCES) $(MESA_GLAPI_SOURCES) $(MESA_GLAPI_ASM_SOURCES) Makefile
+ rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(SOURCES) \
- $(MESA_GLAPI_SOURCES) $(MESA_ASM_API)
+ $(MESA_GLAPI_SOURCES) $(MESA_GLAPI_ASM_SOURCES)
# Emacs tags
diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c
index 3b48cd9c1c..e144ed3e1f 100644
--- a/src/glx/x11/dri2.c
+++ b/src/glx/x11/dri2.c
@@ -39,263 +39,341 @@
#include "xf86drm.h"
#include "dri2.h"
+/* Allow the build to work with an older versions of dri2proto.h and
+ * dri2tokens.h.
+ */
+#if DRI2_MINOR < 1
+#undef DRI2_MINOR
+#define DRI2_MINOR 1
+#define X_DRI2GetBuffersWithFormat 7
+#endif
+
+
static char dri2ExtensionName[] = DRI2_NAME;
static XExtensionInfo *dri2Info;
static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
+
static /* const */ XExtensionHooks dri2ExtensionHooks = {
- NULL, /* create_gc */
- NULL, /* copy_gc */
- NULL, /* flush_gc */
- NULL, /* free_gc */
- NULL, /* create_font */
- NULL, /* free_font */
- DRI2CloseDisplay, /* close_display */
- NULL, /* wire_to_event */
- NULL, /* event_to_wire */
- NULL, /* error */
- NULL, /* error_string */
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ DRI2CloseDisplay, /* close_display */
+ NULL, /* wire_to_event */
+ NULL, /* event_to_wire */
+ NULL, /* error */
+ NULL, /* error_string */
};
-static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, dri2Info,
- dri2ExtensionName,
- &dri2ExtensionHooks,
- 0, NULL)
+static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
+ dri2Info,
+ dri2ExtensionName,
+ &dri2ExtensionHooks,
+ 0, NULL)
-Bool DRI2QueryExtension(Display *dpy, int *eventBase, int *errorBase)
+Bool
+DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
{
- XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
- if (XextHasExtension(info)) {
- *eventBase = info->codes->first_event;
- *errorBase = info->codes->first_error;
- return True;
- }
+ if (XextHasExtension(info)) {
+ *eventBase = info->codes->first_event;
+ *errorBase = info->codes->first_error;
+ return True;
+ }
- return False;
+ return False;
}
-Bool DRI2QueryVersion(Display *dpy, int *major, int *minor)
+Bool
+DRI2QueryVersion(Display * dpy, int *major, int *minor)
{
- XExtDisplayInfo *info = DRI2FindDisplay (dpy);
- xDRI2QueryVersionReply rep;
- xDRI2QueryVersionReq *req;
-
- XextCheckExtension (dpy, info, dri2ExtensionName, False);
-
- LockDisplay(dpy);
- GetReq(DRI2QueryVersion, req);
- req->reqType = info->codes->major_opcode;
- req->dri2ReqType = X_DRI2QueryVersion;
- req->majorVersion = DRI2_MAJOR;
- req->minorVersion = DRI2_MINOR;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- *major = rep.majorVersion;
- *minor = rep.minorVersion;
- UnlockDisplay(dpy);
- SyncHandle();
-
- return True;
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2QueryVersionReply rep;
+ xDRI2QueryVersionReq *req;
+
+ XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+ LockDisplay(dpy);
+ GetReq(DRI2QueryVersion, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2QueryVersion;
+ req->majorVersion = DRI2_MAJOR;
+ req->minorVersion = DRI2_MINOR;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ *major = rep.majorVersion;
+ *minor = rep.minorVersion;
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return True;
}
-Bool DRI2Connect(Display *dpy, XID window,
- char **driverName, char **deviceName)
+Bool
+DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
{
- XExtDisplayInfo *info = DRI2FindDisplay(dpy);
- xDRI2ConnectReply rep;
- xDRI2ConnectReq *req;
-
- XextCheckExtension (dpy, info, dri2ExtensionName, False);
-
- LockDisplay(dpy);
- GetReq(DRI2Connect, req);
- req->reqType = info->codes->major_opcode;
- req->dri2ReqType = X_DRI2Connect;
- req->window = window;
- req->driverType = DRI2DriverDRI;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
-
- if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
-
- *driverName = Xmalloc(rep.driverNameLength + 1);
- if (*driverName == NULL) {
- _XEatData(dpy,
- ((rep.driverNameLength + 3) & ~3) +
- ((rep.deviceNameLength + 3) & ~3));
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- _XReadPad(dpy, *driverName, rep.driverNameLength);
- (*driverName)[rep.driverNameLength] = '\0';
-
- *deviceName = Xmalloc(rep.deviceNameLength + 1);
- if (*deviceName == NULL) {
- Xfree(*driverName);
- _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
- _XReadPad(dpy, *deviceName, rep.deviceNameLength);
- (*deviceName)[rep.deviceNameLength] = '\0';
-
- UnlockDisplay(dpy);
- SyncHandle();
-
- return True;
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2ConnectReply rep;
+ xDRI2ConnectReq *req;
+
+ XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+ LockDisplay(dpy);
+ GetReq(DRI2Connect, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2Connect;
+ req->window = window;
+ req->driverType = DRI2DriverDRI;
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+
+ if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+
+ *driverName = Xmalloc(rep.driverNameLength + 1);
+ if (*driverName == NULL) {
+ _XEatData(dpy,
+ ((rep.driverNameLength + 3) & ~3) +
+ ((rep.deviceNameLength + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ _XReadPad(dpy, *driverName, rep.driverNameLength);
+ (*driverName)[rep.driverNameLength] = '\0';
+
+ *deviceName = Xmalloc(rep.deviceNameLength + 1);
+ if (*deviceName == NULL) {
+ Xfree(*driverName);
+ _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ _XReadPad(dpy, *deviceName, rep.deviceNameLength);
+ (*deviceName)[rep.deviceNameLength] = '\0';
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return True;
}
-Bool DRI2Authenticate(Display *dpy, XID window, drm_magic_t magic)
+Bool
+DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
{
- XExtDisplayInfo *info = DRI2FindDisplay(dpy);
- xDRI2AuthenticateReq *req;
- xDRI2AuthenticateReply rep;
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2AuthenticateReq *req;
+ xDRI2AuthenticateReply rep;
- XextCheckExtension (dpy, info, dri2ExtensionName, False);
+ XextCheckExtension(dpy, info, dri2ExtensionName, False);
- LockDisplay(dpy);
- GetReq(DRI2Authenticate, req);
- req->reqType = info->codes->major_opcode;
- req->dri2ReqType = X_DRI2Authenticate;
- req->window = window;
- req->magic = magic;
+ LockDisplay(dpy);
+ GetReq(DRI2Authenticate, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2Authenticate;
+ req->window = window;
+ req->magic = magic;
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return False;
- }
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
- UnlockDisplay(dpy);
- SyncHandle();
+ UnlockDisplay(dpy);
+ SyncHandle();
- return rep.authenticated;
+ return rep.authenticated;
}
-void DRI2CreateDrawable(Display *dpy, XID drawable)
+void
+DRI2CreateDrawable(Display * dpy, XID drawable)
{
- XExtDisplayInfo *info = DRI2FindDisplay(dpy);
- xDRI2CreateDrawableReq *req;
-
- XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
-
- LockDisplay(dpy);
- GetReq(DRI2CreateDrawable, req);
- req->reqType = info->codes->major_opcode;
- req->dri2ReqType = X_DRI2CreateDrawable;
- req->drawable = drawable;
- UnlockDisplay(dpy);
- SyncHandle();
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2CreateDrawableReq *req;
+
+ XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
+
+ LockDisplay(dpy);
+ GetReq(DRI2CreateDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2CreateDrawable;
+ req->drawable = drawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
}
-void DRI2DestroyDrawable(Display *dpy, XID drawable)
+void
+DRI2DestroyDrawable(Display * dpy, XID drawable)
{
- XExtDisplayInfo *info = DRI2FindDisplay(dpy);
- xDRI2DestroyDrawableReq *req;
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2DestroyDrawableReq *req;
- XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
+ XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
- XSync(dpy, False);
+ XSync(dpy, False);
- LockDisplay(dpy);
- GetReq(DRI2DestroyDrawable, req);
- req->reqType = info->codes->major_opcode;
- req->dri2ReqType = X_DRI2DestroyDrawable;
- req->drawable = drawable;
- UnlockDisplay(dpy);
- SyncHandle();
+ LockDisplay(dpy);
+ GetReq(DRI2DestroyDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2DestroyDrawable;
+ req->drawable = drawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
}
-DRI2Buffer *DRI2GetBuffers(Display *dpy, XID drawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *outCount)
+DRI2Buffer *
+DRI2GetBuffers(Display * dpy, XID drawable,
+ int *width, int *height,
+ unsigned int *attachments, int count, int *outCount)
{
- XExtDisplayInfo *info = DRI2FindDisplay(dpy);
- xDRI2GetBuffersReply rep;
- xDRI2GetBuffersReq *req;
- DRI2Buffer *buffers;
- xDRI2Buffer repBuffer;
- CARD32 *p;
- int i;
-
- XextCheckExtension (dpy, info, dri2ExtensionName, False);
-
- LockDisplay(dpy);
- GetReqExtra(DRI2GetBuffers, count * 4, req);
- req->reqType = info->codes->major_opcode;
- req->dri2ReqType = X_DRI2GetBuffers;
- req->drawable = drawable;
- req->count = count;
- p = (CARD32 *) &req[1];
- for (i = 0; i < count; i++)
- p[i] = attachments[i];
-
- if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
- UnlockDisplay(dpy);
- SyncHandle();
- return NULL;
- }
-
- *width = rep.width;
- *height = rep.height;
- *outCount = rep.count;
-
- buffers = Xmalloc(count * sizeof buffers[0]);
- if (buffers == NULL) {
- _XEatData(dpy, rep.count * sizeof repBuffer);
- UnlockDisplay(dpy);
- SyncHandle();
- return NULL;
- }
-
- for (i = 0; i < rep.count; i++) {
- _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
- buffers[i].attachment = repBuffer.attachment;
- buffers[i].name = repBuffer.name;
- buffers[i].pitch = repBuffer.pitch;
- buffers[i].cpp = repBuffer.cpp;
- buffers[i].flags = repBuffer.flags;
- }
-
- UnlockDisplay(dpy);
- SyncHandle();
-
- return buffers;
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2GetBuffersReply rep;
+ xDRI2GetBuffersReq *req;
+ DRI2Buffer *buffers;
+ xDRI2Buffer repBuffer;
+ CARD32 *p;
+ int i;
+
+ XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+ LockDisplay(dpy);
+ GetReqExtra(DRI2GetBuffers, count * 4, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2GetBuffers;
+ req->drawable = drawable;
+ req->count = count;
+ p = (CARD32 *) & req[1];
+ for (i = 0; i < count; i++)
+ p[i] = attachments[i];
+
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return NULL;
+ }
+
+ *width = rep.width;
+ *height = rep.height;
+ *outCount = rep.count;
+
+ buffers = Xmalloc(rep.count * sizeof buffers[0]);
+ if (buffers == NULL) {
+ _XEatData(dpy, rep.count * sizeof repBuffer);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return NULL;
+ }
+
+ for (i = 0; i < rep.count; i++) {
+ _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
+ buffers[i].attachment = repBuffer.attachment;
+ buffers[i].name = repBuffer.name;
+ buffers[i].pitch = repBuffer.pitch;
+ buffers[i].cpp = repBuffer.cpp;
+ buffers[i].flags = repBuffer.flags;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return buffers;
}
-void DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region,
- CARD32 dest, CARD32 src)
+
+DRI2Buffer *
+DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
+ int *width, int *height,
+ unsigned int *attachments, int count, int *outCount)
+{
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2GetBuffersReply rep;
+ xDRI2GetBuffersReq *req;
+ DRI2Buffer *buffers;
+ xDRI2Buffer repBuffer;
+ CARD32 *p;
+ int i;
+
+ XextCheckExtension(dpy, info, dri2ExtensionName, False);
+
+ LockDisplay(dpy);
+ GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2GetBuffersWithFormat;
+ req->drawable = drawable;
+ req->count = count;
+ p = (CARD32 *) & req[1];
+ for (i = 0; i < (count * 2); i++)
+ p[i] = attachments[i];
+
+ if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return NULL;
+ }
+
+ *width = rep.width;
+ *height = rep.height;
+ *outCount = rep.count;
+
+ buffers = Xmalloc(rep.count * sizeof buffers[0]);
+ if (buffers == NULL) {
+ _XEatData(dpy, rep.count * sizeof repBuffer);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return NULL;
+ }
+
+ for (i = 0; i < rep.count; i++) {
+ _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
+ buffers[i].attachment = repBuffer.attachment;
+ buffers[i].name = repBuffer.name;
+ buffers[i].pitch = repBuffer.pitch;
+ buffers[i].cpp = repBuffer.cpp;
+ buffers[i].flags = repBuffer.flags;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return buffers;
+}
+
+
+void
+DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
+ CARD32 dest, CARD32 src)
{
- XExtDisplayInfo *info = DRI2FindDisplay(dpy);
- xDRI2CopyRegionReq *req;
- xDRI2CopyRegionReply rep;
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ xDRI2CopyRegionReq *req;
+ xDRI2CopyRegionReply rep;
- XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
+ XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
- LockDisplay(dpy);
- GetReq(DRI2CopyRegion, req);
- req->reqType = info->codes->major_opcode;
- req->dri2ReqType = X_DRI2CopyRegion;
- req->drawable = drawable;
- req->region = region;
- req->dest = dest;
- req->src = src;
+ LockDisplay(dpy);
+ GetReq(DRI2CopyRegion, req);
+ req->reqType = info->codes->major_opcode;
+ req->dri2ReqType = X_DRI2CopyRegion;
+ req->drawable = drawable;
+ req->region = region;
+ req->dest = dest;
+ req->src = src;
- _XReply(dpy, (xReply *)&rep, 0, xFalse);
+ _XReply(dpy, (xReply *) & rep, 0, xFalse);
- UnlockDisplay(dpy);
- SyncHandle();
+ UnlockDisplay(dpy);
+ SyncHandle();
}
diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h
index 356c6bcb55..a6fe66e136 100644
--- a/src/glx/x11/dri2.h
+++ b/src/glx/x11/dri2.h
@@ -36,35 +36,53 @@
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/dri2tokens.h>
-typedef struct {
- unsigned int attachment;
- unsigned int name;
- unsigned int pitch;
- unsigned int cpp;
- unsigned int flags;
+typedef struct
+{
+ unsigned int attachment;
+ unsigned int name;
+ unsigned int pitch;
+ unsigned int cpp;
+ unsigned int flags;
} DRI2Buffer;
extern Bool
-DRI2QueryExtension(Display *display, int *eventBase, int *errorBase);
+DRI2QueryExtension(Display * display, int *eventBase, int *errorBase);
+
extern Bool
-DRI2QueryVersion(Display *display, int *major, int *minor);
+DRI2QueryVersion(Display * display, int *major, int *minor);
+
extern Bool
-DRI2Connect(Display *display, XID window,
- char **driverName, char **deviceName);
+DRI2Connect(Display * display, XID window,
+ char **driverName, char **deviceName);
+
extern Bool
-DRI2Authenticate(Display *display, XID window, drm_magic_t magic);
+DRI2Authenticate(Display * display, XID window, drm_magic_t magic);
+
extern void
-DRI2CreateDrawable(Display *display, XID drawable);
+DRI2CreateDrawable(Display * display, XID drawable);
+
extern void
-DRI2DestroyDrawable(Display *display, XID handle);
-extern DRI2Buffer *
-DRI2GetBuffers(Display *dpy, XID drawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *outCount);
+DRI2DestroyDrawable(Display * display, XID handle);
+
+extern DRI2Buffer*
+DRI2GetBuffers(Display * dpy, XID drawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *outCount);
+
+/**
+ * \note
+ * This function is only supported with DRI2 version 1.1 or later.
+ */
+extern DRI2Buffer*
+DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
+ int *width, int *height,
+ unsigned int *attachments,
+ int count, int *outCount);
extern void
-DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region,
- CARD32 dest, CARD32 src);
+DRI2CopyRegion(Display * dpy, XID drawable,
+ XserverRegion region,
+ CARD32 dest, CARD32 src);
#endif
diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c
index 2bee67780b..89efe3ab29 100644
--- a/src/glx/x11/dri2_glx.c
+++ b/src/glx/x11/dri2_glx.c
@@ -47,316 +47,492 @@
#include "dri2.h"
#include "dri_common.h"
+#undef DRI2_MINOR
+#define DRI2_MINOR 1
+
typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
typedef struct __GLXDRIdrawablePrivateRec __GLXDRIdrawablePrivate;
-struct __GLXDRIdisplayPrivateRec {
- __GLXDRIdisplay base;
+struct __GLXDRIdisplayPrivateRec
+{
+ __GLXDRIdisplay base;
- /*
+ /*
** XFree86-DRI version information
*/
- int driMajor;
- int driMinor;
- int driPatch;
+ int driMajor;
+ int driMinor;
+ int driPatch;
};
-struct __GLXDRIcontextPrivateRec {
- __GLXDRIcontext base;
- __DRIcontext *driContext;
- __GLXscreenConfigs *psc;
+struct __GLXDRIcontextPrivateRec
+{
+ __GLXDRIcontext base;
+ __DRIcontext *driContext;
+ __GLXscreenConfigs *psc;
};
-struct __GLXDRIdrawablePrivateRec {
- __GLXDRIdrawable base;
- __DRIbuffer buffers[5];
- int bufferCount;
- int width, height;
+struct __GLXDRIdrawablePrivateRec
+{
+ __GLXDRIdrawable base;
+ __DRIbuffer buffers[5];
+ int bufferCount;
+ int width, height;
+ int have_back;
+ int have_fake_front;
};
-static void dri2DestroyContext(__GLXDRIcontext *context,
- __GLXscreenConfigs *psc, Display *dpy)
+static void dri2WaitX(__GLXDRIdrawable * pdraw);
+
+static void
+dri2DestroyContext(__GLXDRIcontext * context,
+ __GLXscreenConfigs * psc, Display * dpy)
{
- __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
- const __DRIcoreExtension *core = pcp->psc->core;
+ __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+ const __DRIcoreExtension *core = pcp->psc->core;
- (*core->destroyContext)(pcp->driContext);
+ (*core->destroyContext) (pcp->driContext);
- Xfree(pcp);
+ Xfree(pcp);
}
-static Bool dri2BindContext(__GLXDRIcontext *context,
- __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
+static Bool
+dri2BindContext(__GLXDRIcontext * context,
+ __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
{
- __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
- const __DRIcoreExtension *core = pcp->psc->core;
+ __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+ const __DRIcoreExtension *core = pcp->psc->core;
- return (*core->bindContext)(pcp->driContext,
- draw->driDrawable,
- read->driDrawable);
+ return (*core->bindContext) (pcp->driContext,
+ draw->driDrawable, read->driDrawable);
}
-static void dri2UnbindContext(__GLXDRIcontext *context)
+static void
+dri2UnbindContext(__GLXDRIcontext * context)
{
- __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
- const __DRIcoreExtension *core = pcp->psc->core;
+ __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+ const __DRIcoreExtension *core = pcp->psc->core;
+
+ (*core->unbindContext) (pcp->driContext);
+}
- (*core->unbindContext)(pcp->driContext);
+static __GLXDRIcontext *
+dri2CreateContext(__GLXscreenConfigs * psc,
+ const __GLcontextModes * mode,
+ GLXContext gc, GLXContext shareList, int renderType)
+{
+ __GLXDRIcontextPrivate *pcp, *pcp_shared;
+ __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
+ __DRIcontext *shared = NULL;
+
+ if (shareList) {
+ pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
+ shared = pcp_shared->driContext;
+ }
+
+ pcp = Xmalloc(sizeof *pcp);
+ if (pcp == NULL)
+ return NULL;
+
+ pcp->psc = psc;
+ pcp->driContext =
+ (*psc->dri2->createNewContext) (psc->__driScreen,
+ config->driConfig, shared, pcp);
+ gc->__driContext = pcp->driContext;
+
+ if (pcp->driContext == NULL) {
+ Xfree(pcp);
+ return NULL;
+ }
+
+ pcp->base.destroyContext = dri2DestroyContext;
+ pcp->base.bindContext = dri2BindContext;
+ pcp->base.unbindContext = dri2UnbindContext;
+
+ return &pcp->base;
}
-static __GLXDRIcontext *dri2CreateContext(__GLXscreenConfigs *psc,
- const __GLcontextModes *mode,
- GLXContext gc,
- GLXContext shareList, int renderType)
+static void
+dri2DestroyDrawable(__GLXDRIdrawable * pdraw)
{
- __GLXDRIcontextPrivate *pcp, *pcp_shared;
- __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
- __DRIcontext *shared = NULL;
-
- if (shareList) {
- pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
- shared = pcp_shared->driContext;
- }
-
- pcp = Xmalloc(sizeof *pcp);
- if (pcp == NULL)
- return NULL;
-
- pcp->psc = psc;
- pcp->driContext =
- (*psc->dri2->createNewContext)(psc->__driScreen,
- config->driConfig, shared, pcp);
- gc->__driContext = pcp->driContext;
-
- if (pcp->driContext == NULL) {
- Xfree(pcp);
- return NULL;
- }
-
- pcp->base.destroyContext = dri2DestroyContext;
- pcp->base.bindContext = dri2BindContext;
- pcp->base.unbindContext = dri2UnbindContext;
-
- return &pcp->base;
+ const __DRIcoreExtension *core = pdraw->psc->core;
+
+ (*core->destroyDrawable) (pdraw->driDrawable);
+ DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->xDrawable);
+ Xfree(pdraw);
}
-static void dri2DestroyDrawable(__GLXDRIdrawable *pdraw)
+static __GLXDRIdrawable *
+dri2CreateDrawable(__GLXscreenConfigs * psc,
+ XID xDrawable,
+ GLXDrawable drawable, const __GLcontextModes * modes)
{
- const __DRIcoreExtension *core = pdraw->psc->core;
+ __GLXDRIdrawablePrivate *pdraw;
+ __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+
+ pdraw = Xmalloc(sizeof(*pdraw));
+ if (!pdraw)
+ return NULL;
+
+ pdraw->base.destroyDrawable = dri2DestroyDrawable;
+ pdraw->base.xDrawable = xDrawable;
+ pdraw->base.drawable = drawable;
+ pdraw->base.psc = psc;
+ pdraw->bufferCount = 0;
+
+ DRI2CreateDrawable(psc->dpy, xDrawable);
- (*core->destroyDrawable)(pdraw->driDrawable);
- DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->drawable);
- Xfree(pdraw);
+ /* Create a new drawable */
+ pdraw->base.driDrawable =
+ (*psc->dri2->createNewDrawable) (psc->__driScreen,
+ config->driConfig, pdraw);
+
+ if (!pdraw->base.driDrawable) {
+ DRI2DestroyDrawable(psc->dpy, xDrawable);
+ Xfree(pdraw);
+ return NULL;
+ }
+
+ return &pdraw->base;
}
-static __GLXDRIdrawable *dri2CreateDrawable(__GLXscreenConfigs *psc,
- XID xDrawable,
- GLXDrawable drawable,
- const __GLcontextModes *modes)
+static void
+dri2CopySubBuffer(__GLXDRIdrawable * pdraw,
+ int x, int y, int width, int height)
{
- __GLXDRIdrawablePrivate *pdraw;
- __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+ __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
+ XRectangle xrect;
+ XserverRegion region;
+
+ /* Check we have the right attachments */
+ if (!priv->have_back)
+ return;
+
+ xrect.x = x;
+ xrect.y = priv->height - y - height;
+ xrect.width = width;
+ xrect.height = height;
+
+#ifdef __DRI2_FLUSH
+ if (pdraw->psc->f)
+ (*pdraw->psc->f->flush) (pdraw->driDrawable);
+#endif
+
+ region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
+ /* should get a fence ID back from here at some point */
+ DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
+ DRI2BufferFrontLeft, DRI2BufferBackLeft);
+ XFixesDestroyRegion(pdraw->psc->dpy, region);
+
+ /* Refresh the fake front (if present) after we just damaged the real
+ * front.
+ */
+ dri2WaitX(pdraw);
+}
- pdraw = Xmalloc(sizeof(*pdraw));
- if (!pdraw)
- return NULL;
+static void
+dri2SwapBuffers(__GLXDRIdrawable * pdraw)
+{
+ __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
- pdraw->base.destroyDrawable = dri2DestroyDrawable;
- pdraw->base.xDrawable = xDrawable;
- pdraw->base.drawable = drawable;
- pdraw->base.psc = psc;
+ dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
+}
- DRI2CreateDrawable(psc->dpy, xDrawable);
+static void
+dri2WaitX(__GLXDRIdrawable * pdraw)
+{
+ __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
+ XRectangle xrect;
+ XserverRegion region;
+
+ /* Check we have the right attachments */
+ if (!priv->have_fake_front)
+ return;
+
+ xrect.x = 0;
+ xrect.y = 0;
+ xrect.width = priv->width;
+ xrect.height = priv->height;
+
+#ifdef __DRI2_FLUSH
+ if (pdraw->psc->f)
+ (*pdraw->psc->f->flush) (pdraw->driDrawable);
+#endif
+
+ region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
+ DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
+ DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+ XFixesDestroyRegion(pdraw->psc->dpy, region);
+}
- /* Create a new drawable */
- pdraw->base.driDrawable =
- (*psc->dri2->createNewDrawable)(psc->__driScreen,
- config->driConfig, pdraw);
+static void
+dri2WaitGL(__GLXDRIdrawable * pdraw)
+{
+ __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
+ XRectangle xrect;
+ XserverRegion region;
+
+ if (!priv->have_fake_front)
+ return;
+
+ xrect.x = 0;
+ xrect.y = 0;
+ xrect.width = priv->width;
+ xrect.height = priv->height;
+
+#ifdef __DRI2_FLUSH
+ if (pdraw->psc->f)
+ (*pdraw->psc->f->flush) (pdraw->driDrawable);
+#endif
+
+ region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
+ DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+ XFixesDestroyRegion(pdraw->psc->dpy, region);
+}
- if (!pdraw->base.driDrawable) {
- DRI2DestroyDrawable(psc->dpy, drawable);
- Xfree(pdraw);
- return NULL;
- }
- return &pdraw->base;
+static void
+dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
+{
+ (void) driDrawable;
+ dri2WaitGL((__GLXDRIdrawable *) loaderPrivate);
}
-static void dri2CopySubBuffer(__GLXDRIdrawable *pdraw,
- int x, int y, int width, int height)
+
+static void
+dri2DestroyScreen(__GLXscreenConfigs * psc)
{
- __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
- XRectangle xrect;
- XserverRegion region;
-
- xrect.x = x;
- xrect.y = priv->height - y - height;
- xrect.width = width;
- xrect.height = height;
-
- region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
- DRI2CopyRegion(pdraw->psc->dpy, pdraw->drawable, region,
- DRI2BufferFrontLeft, DRI2BufferBackLeft);
- XFixesDestroyRegion(pdraw->psc->dpy, region);
+ /* Free the direct rendering per screen data */
+ (*psc->core->destroyScreen) (psc->__driScreen);
+ close(psc->fd);
+ psc->__driScreen = NULL;
}
-static void dri2SwapBuffers(__GLXDRIdrawable *pdraw)
+/**
+ * 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
+process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers,
+ unsigned count)
{
- __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
+ int i;
+
+ pdraw->bufferCount = count;
+ pdraw->have_fake_front = 0;
+ pdraw->have_back = 0;
+
+ /* This assumes the DRI2 buffer attachment tokens matches the
+ * __DRIbuffer tokens. */
+ for (i = 0; i < count; i++) {
+ pdraw->buffers[i].attachment = buffers[i].attachment;
+ pdraw->buffers[i].name = buffers[i].name;
+ pdraw->buffers[i].pitch = buffers[i].pitch;
+ pdraw->buffers[i].cpp = buffers[i].cpp;
+ pdraw->buffers[i].flags = buffers[i].flags;
+ if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
+ pdraw->have_fake_front = 1;
+ if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
+ pdraw->have_back = 1;
+ }
- dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
}
-static void dri2DestroyScreen(__GLXscreenConfigs *psc)
+static __DRIbuffer *
+dri2GetBuffers(__DRIdrawable * driDrawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, void *loaderPrivate)
{
- /* Free the direct rendering per screen data */
- (*psc->core->destroyScreen)(psc->__driScreen);
- close(psc->fd);
- psc->__driScreen = NULL;
+ __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
+ DRI2Buffer *buffers;
+
+ buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
+ width, height, attachments, count, out_count);
+ if (buffers == NULL)
+ return NULL;
+
+ pdraw->width = *width;
+ pdraw->height = *height;
+ process_buffers(pdraw, buffers, *out_count);
+
+ Xfree(buffers);
+
+ return pdraw->buffers;
}
static __DRIbuffer *
-dri2GetBuffers(__DRIdrawable *driDrawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *out_count, void *loaderPrivate)
+dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, void *loaderPrivate)
{
- __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
- DRI2Buffer *buffers;
- int i;
-
- buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
- width, height, attachments, count, out_count);
- if (buffers == NULL)
- return NULL;
-
- pdraw->width = *width;
- pdraw->height = *height;
-
- /* This assumes the DRI2 buffer attachment tokens matches the
- * __DRIbuffer tokens. */
- for (i = 0; i < *out_count; i++) {
- pdraw->buffers[i].attachment = buffers[i].attachment;
- pdraw->buffers[i].name = buffers[i].name;
- pdraw->buffers[i].pitch = buffers[i].pitch;
- pdraw->buffers[i].cpp = buffers[i].cpp;
- pdraw->buffers[i].flags = buffers[i].flags;
- }
-
- Xfree(buffers);
-
- return pdraw->buffers;
+ __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
+ DRI2Buffer *buffers;
+
+ buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy,
+ pdraw->base.xDrawable,
+ width, height, attachments,
+ count, out_count);
+ if (buffers == NULL)
+ return NULL;
+
+ pdraw->width = *width;
+ pdraw->height = *height;
+ process_buffers(pdraw, buffers, *out_count);
+
+ Xfree(buffers);
+
+ return pdraw->buffers;
}
static const __DRIdri2LoaderExtension dri2LoaderExtension = {
- { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
- dri2GetBuffers,
+ {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
+ dri2GetBuffers,
+ dri2FlushFrontBuffer,
+ dri2GetBuffersWithFormat,
+};
+
+static const __DRIdri2LoaderExtension dri2LoaderExtension_old = {
+ {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
+ dri2GetBuffers,
+ dri2FlushFrontBuffer,
+ NULL,
};
static const __DRIextension *loader_extensions[] = {
- &dri2LoaderExtension.base,
- &systemTimeExtension.base,
- NULL
+ &dri2LoaderExtension.base,
+ &systemTimeExtension.base,
+ NULL
+};
+
+static const __DRIextension *loader_extensions_old[] = {
+ &dri2LoaderExtension_old.base,
+ &systemTimeExtension.base,
+ NULL
};
-static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen,
- __GLXdisplayPrivate *priv)
+static __GLXDRIscreen *
+dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
+ __GLXdisplayPrivate * priv)
{
- const __DRIconfig **driver_configs;
- const __DRIextension **extensions;
- __GLXDRIscreen *psp;
- char *driverName, *deviceName;
- drm_magic_t magic;
- int i;
-
- psp = Xmalloc(sizeof *psp);
- if (psp == NULL)
- return NULL;
-
- /* Initialize per screen dynamic client GLX extensions */
- psc->ext_list_first_time = GL_TRUE;
-
- if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen),
- &driverName, &deviceName))
- return NULL;
-
- psc->driver = driOpenDriver(driverName);
- if (psc->driver == NULL)
- goto handle_error;
-
- extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
- if (extensions == NULL) {
- ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
- goto handle_error;
- }
-
- for (i = 0; extensions[i]; i++) {
- if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
- psc->core = (__DRIcoreExtension *) extensions[i];
- if (strcmp(extensions[i]->name, __DRI_DRI2) == 0)
- psc->dri2 = (__DRIdri2Extension *) extensions[i];
- }
-
- if (psc->core == NULL || psc->dri2 == NULL) {
- ErrorMessageF("core dri or dri2 extension not found\n");
- goto handle_error;
- }
-
- psc->fd = open(deviceName, O_RDWR);
- if (psc->fd < 0) {
- ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
- return NULL;
- }
-
- if (drmGetMagic(psc->fd, &magic))
- return NULL;
-
- if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic))
- return NULL;
-
- psc->__driScreen =
- psc->dri2->createNewScreen(screen, psc->fd,
- loader_extensions, &driver_configs, psc);
- if (psc->__driScreen == NULL) {
- ErrorMessageF("failed to create dri screen\n");
- return NULL;
- }
-
- driBindExtensions(psc, 1);
-
- psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
- psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
-
- psp->destroyScreen = dri2DestroyScreen;
- psp->createContext = dri2CreateContext;
- psp->createDrawable = dri2CreateDrawable;
- psp->swapBuffers = dri2SwapBuffers;
-
- /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
- * available.*/
- psp->copySubBuffer = dri2CopySubBuffer;
- __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
-
- Xfree(driverName);
- Xfree(deviceName);
-
- return psp;
+ const __DRIconfig **driver_configs;
+ const __DRIextension **extensions;
+ const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *)
+ priv->dri2Display;
+ __GLXDRIscreen *psp;
+ char *driverName, *deviceName;
+ drm_magic_t magic;
+ int i;
+
+ psp = Xmalloc(sizeof *psp);
+ if (psp == NULL)
+ return NULL;
+
+ /* Initialize per screen dynamic client GLX extensions */
+ psc->ext_list_first_time = GL_TRUE;
+
+ if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen),
+ &driverName, &deviceName))
+ return NULL;
+
+ psc->driver = driOpenDriver(driverName);
+ if (psc->driver == NULL) {
+ ErrorMessageF("driver pointer missing\n");
+ goto handle_error;
+ }
+
+ extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
+ if (extensions == NULL) {
+ ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
+ goto handle_error;
+ }
+
+ for (i = 0; extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
+ psc->core = (__DRIcoreExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_DRI2) == 0)
+ psc->dri2 = (__DRIdri2Extension *) extensions[i];
+ }
+
+ if (psc->core == NULL || psc->dri2 == NULL) {
+ ErrorMessageF("core dri or dri2 extension not found\n");
+ goto handle_error;
+ }
+
+ psc->fd = open(deviceName, O_RDWR);
+ if (psc->fd < 0) {
+ ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ if (drmGetMagic(psc->fd, &magic)) {
+ ErrorMessageF("failed to get magic\n");
+ return NULL;
+ }
+
+ if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) {
+ ErrorMessageF("failed to authenticate magic %d\n", magic);
+ return NULL;
+ }
+
+ /* If the server does not support the protocol for
+ * DRI2GetBuffersWithFormat, don't supply that interface to the driver.
+ */
+ psc->__driScreen =
+ psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1)
+ ? loader_extensions_old
+ : loader_extensions),
+ &driver_configs, psc);
+
+ if (psc->__driScreen == NULL) {
+ ErrorMessageF("failed to create dri screen\n");
+ return NULL;
+ }
+
+ driBindExtensions(psc, 1);
+
+ psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
+ psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+
+ psc->driver_configs = driver_configs;
+
+ psp->destroyScreen = dri2DestroyScreen;
+ psp->createContext = dri2CreateContext;
+ psp->createDrawable = dri2CreateDrawable;
+ psp->swapBuffers = dri2SwapBuffers;
+ psp->waitGL = dri2WaitGL;
+ psp->waitX = dri2WaitX;
+
+ /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
+ * available.*/
+ psp->copySubBuffer = dri2CopySubBuffer;
+ __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
+
+ Xfree(driverName);
+ Xfree(deviceName);
+
+ return psp;
handle_error:
- Xfree(driverName);
- Xfree(deviceName);
+ Xfree(driverName);
+ Xfree(deviceName);
- /* FIXME: clean up here */
+ /* FIXME: clean up here */
- return NULL;
+ return NULL;
}
/* Called from __glXFreeDisplayPrivate.
*/
-static void dri2DestroyDisplay(__GLXDRIdisplay *dpy)
+static void
+dri2DestroyDisplay(__GLXDRIdisplay * dpy)
{
- Xfree(dpy);
+ Xfree(dpy);
}
/*
@@ -364,29 +540,30 @@ static void dri2DestroyDisplay(__GLXDRIdisplay *dpy)
* This is called from __glXInitialize() when we are given a new
* display pointer.
*/
-_X_HIDDEN __GLXDRIdisplay *dri2CreateDisplay(Display *dpy)
+_X_HIDDEN __GLXDRIdisplay *
+dri2CreateDisplay(Display * dpy)
{
- __GLXDRIdisplayPrivate *pdp;
- int eventBase, errorBase;
+ __GLXDRIdisplayPrivate *pdp;
+ int eventBase, errorBase;
- if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
- return NULL;
+ if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
+ return NULL;
- pdp = Xmalloc(sizeof *pdp);
- if (pdp == NULL)
- return NULL;
+ pdp = Xmalloc(sizeof *pdp);
+ if (pdp == NULL)
+ return NULL;
- if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
- Xfree(pdp);
- return NULL;
- }
+ if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
+ Xfree(pdp);
+ return NULL;
+ }
- pdp->driPatch = 0;
+ pdp->driPatch = 0;
- pdp->base.destroyDisplay = dri2DestroyDisplay;
- pdp->base.createScreen = dri2CreateScreen;
+ pdp->base.destroyDisplay = dri2DestroyDisplay;
+ pdp->base.createScreen = dri2CreateScreen;
- return &pdp->base;
+ return &pdp->base;
}
#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/x11/dri_common.c b/src/glx/x11/dri_common.c
index 4fda649e59..9c825ad74a 100644
--- a/src/glx/x11/dri_common.c
+++ b/src/glx/x11/dri_common.c
@@ -49,33 +49,35 @@
#define RTLD_GLOBAL 0
#endif
-_X_HIDDEN void InfoMessageF(const char *f, ...)
+_X_HIDDEN void
+InfoMessageF(const char *f, ...)
{
- va_list args;
- const char *env;
-
- if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) {
- fprintf(stderr, "libGL: ");
- va_start(args, f);
- vfprintf(stderr, f, args);
- va_end(args);
- }
+ va_list args;
+ const char *env;
+
+ if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) {
+ fprintf(stderr, "libGL: ");
+ va_start(args, f);
+ vfprintf(stderr, f, args);
+ va_end(args);
+ }
}
/**
* Print error to stderr, unless LIBGL_DEBUG=="quiet".
*/
-_X_HIDDEN void ErrorMessageF(const char *f, ...)
+_X_HIDDEN void
+ErrorMessageF(const char *f, ...)
{
- va_list args;
- const char *env;
-
- if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) {
- fprintf(stderr, "libGL error: ");
- va_start(args, f);
- vfprintf(stderr, f, args);
- va_end(args);
- }
+ va_list args;
+ const char *env;
+
+ if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) {
+ fprintf(stderr, "libGL error: ");
+ va_start(args, f);
+ vfprintf(stderr, f, args);
+ va_end(args);
+ }
}
#ifndef DEFAULT_DRIVER_DIR
@@ -95,7 +97,8 @@ _X_HIDDEN void ErrorMessageF(const char *f, ...)
* \returns
* A handle from \c dlopen, or \c NULL if driver file not found.
*/
-_X_HIDDEN void *driOpenDriver(const char *driverName)
+_X_HIDDEN void *
+driOpenDriver(const char *driverName)
{
void *glhandle, *handle;
const char *libPaths, *p, *next;
@@ -110,40 +113,41 @@ _X_HIDDEN void *driOpenDriver(const char *driverName)
/* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
libPaths = getenv("LIBGL_DRIVERS_PATH");
if (!libPaths)
- libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
+ libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
}
if (libPaths == NULL)
- libPaths = DEFAULT_DRIVER_DIR;
+ libPaths = DEFAULT_DRIVER_DIR;
handle = NULL;
for (p = libPaths; *p; p = next) {
- next = strchr(p, ':');
- if (next == NULL) {
- len = strlen(p);
- next = p + len;
- } else {
- len = next - p;
- next++;
- }
+ next = strchr(p, ':');
+ if (next == NULL) {
+ len = strlen(p);
+ next = p + len;
+ }
+ else {
+ len = next - p;
+ next++;
+ }
#ifdef GLX_USE_TLS
snprintf(realDriverName, sizeof realDriverName,
- "%.*s/tls/%s_dri.so", len, p, driverName);
+ "%.*s/tls/%s_dri.so", len, p, driverName);
InfoMessageF("OpenDriver: trying %s\n", realDriverName);
handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
#endif
- if ( handle == NULL ) {
- snprintf(realDriverName, sizeof realDriverName,
- "%.*s/%s_dri.so", len, p, driverName);
- InfoMessageF("OpenDriver: trying %s\n", realDriverName);
- handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
+ if (handle == NULL) {
+ snprintf(realDriverName, sizeof realDriverName,
+ "%.*s/%s_dri.so", len, p, driverName);
+ InfoMessageF("OpenDriver: trying %s\n", realDriverName);
+ handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
}
- if ( handle != NULL )
- break;
+ if (handle != NULL)
+ break;
else
- ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
+ ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
}
if (!handle)
@@ -156,244 +160,258 @@ _X_HIDDEN void *driOpenDriver(const char *driverName)
}
_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = {
- { __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION },
- __glXGetUST,
- __driGetMscRateOML
+ {__DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION},
+ __glXGetUST,
+ __driGetMscRateOML
};
#define __ATTRIB(attrib, field) \
{ attrib, offsetof(__GLcontextModes, field) }
-static const struct { unsigned int attrib, offset; } attribMap[] = {
- __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
- __ATTRIB(__DRI_ATTRIB_LEVEL, level),
- __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
- __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
- __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
- __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
- __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
- __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
- __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
- __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
- __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
- __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
- __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
- __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
- __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
- __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
- __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
+static const struct
+{
+ unsigned int attrib, offset;
+} attribMap[] = {
+ __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
+ __ATTRIB(__DRI_ATTRIB_LEVEL, level),
+ __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
+ __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
+ __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
+ __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
+ __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
+ __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
+ __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
+ __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
+ __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
+ __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
+ __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
#if 0
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
- __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
- __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
- __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
- __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
+ __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
+ __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
+ __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
+ __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
#endif
- __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
- __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
- __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
- __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
- __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
+ __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
+ __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
#if 0
- __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
+ __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
#endif
- __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
- __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
- __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
- __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
-};
+__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE,
+ bindToMipmapTexture),
+ __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),};
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
static int
-scalarEqual(__GLcontextModes *mode, unsigned int attrib, unsigned int value)
+scalarEqual(__GLcontextModes * mode, unsigned int attrib, unsigned int value)
{
- unsigned int glxValue;
- int i;
+ unsigned int glxValue;
+ int i;
- for (i = 0; i < ARRAY_SIZE(attribMap); i++)
- if (attribMap[i].attrib == attrib) {
- glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset);
- return glxValue == GLX_DONT_CARE || glxValue == value;
- }
+ for (i = 0; i < ARRAY_SIZE(attribMap); i++)
+ if (attribMap[i].attrib == attrib) {
+ glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset);
+ return glxValue == GLX_DONT_CARE || glxValue == value;
+ }
- return GL_TRUE; /* Is a non-existing attribute equal to value? */
+ return GL_TRUE; /* Is a non-existing attribute equal to value? */
}
static int
-driConfigEqual(const __DRIcoreExtension *core,
- __GLcontextModes *modes, const __DRIconfig *driConfig)
+driConfigEqual(const __DRIcoreExtension * core,
+ __GLcontextModes * modes, const __DRIconfig * driConfig)
{
- unsigned int attrib, value, glxValue;
- int i;
-
- i = 0;
- while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
- switch (attrib) {
- case __DRI_ATTRIB_RENDER_TYPE:
- glxValue = 0;
- if (value & __DRI_ATTRIB_RGBA_BIT) {
- glxValue |= GLX_RGBA_BIT;
- } else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) {
- glxValue |= GLX_COLOR_INDEX_BIT;
- }
- if (glxValue != modes->renderType)
- return GL_FALSE;
- break;
-
- case __DRI_ATTRIB_CONFIG_CAVEAT:
- if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
- glxValue = GLX_NON_CONFORMANT_CONFIG;
- else if (value & __DRI_ATTRIB_SLOW_BIT)
- glxValue = GLX_SLOW_CONFIG;
- else
- glxValue = GLX_NONE;
- if (glxValue != modes->visualRating)
- return GL_FALSE;
- break;
-
- case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
- glxValue = 0;
- if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
- glxValue |= GLX_TEXTURE_1D_BIT_EXT;
- if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
- glxValue |= GLX_TEXTURE_2D_BIT_EXT;
- if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
- glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
- if (modes->bindToTextureTargets != GLX_DONT_CARE &&
- glxValue != modes->bindToTextureTargets)
- return GL_FALSE;
- break;
-
- default:
- if (!scalarEqual(modes, attrib, value))
- return GL_FALSE;
- }
- }
-
- return GL_TRUE;
+ unsigned int attrib, value, glxValue;
+ int i;
+
+ i = 0;
+ while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
+ switch (attrib) {
+ case __DRI_ATTRIB_RENDER_TYPE:
+ glxValue = 0;
+ if (value & __DRI_ATTRIB_RGBA_BIT) {
+ glxValue |= GLX_RGBA_BIT;
+ }
+ else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) {
+ glxValue |= GLX_COLOR_INDEX_BIT;
+ }
+ if (glxValue != modes->renderType)
+ return GL_FALSE;
+ break;
+
+ case __DRI_ATTRIB_CONFIG_CAVEAT:
+ if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
+ glxValue = GLX_NON_CONFORMANT_CONFIG;
+ else if (value & __DRI_ATTRIB_SLOW_BIT)
+ glxValue = GLX_SLOW_CONFIG;
+ else
+ glxValue = GLX_NONE;
+ if (glxValue != modes->visualRating)
+ return GL_FALSE;
+ break;
+
+ case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
+ glxValue = 0;
+ if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
+ glxValue |= GLX_TEXTURE_1D_BIT_EXT;
+ if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
+ glxValue |= GLX_TEXTURE_2D_BIT_EXT;
+ if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
+ glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
+ if (modes->bindToTextureTargets != GLX_DONT_CARE &&
+ glxValue != modes->bindToTextureTargets)
+ return GL_FALSE;
+ break;
+
+ default:
+ if (!scalarEqual(modes, attrib, value))
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
}
static __GLcontextModes *
-createDriMode(const __DRIcoreExtension *core,
- __GLcontextModes *modes, const __DRIconfig **driConfigs)
+createDriMode(const __DRIcoreExtension * core,
+ __GLcontextModes * modes, const __DRIconfig ** driConfigs)
{
- __GLXDRIconfigPrivate *config;
- int i;
+ __GLXDRIconfigPrivate *config;
+ int i;
- for (i = 0; driConfigs[i]; i++) {
- if (driConfigEqual(core, modes, driConfigs[i]))
- break;
- }
+ for (i = 0; driConfigs[i]; i++) {
+ if (driConfigEqual(core, modes, driConfigs[i]))
+ break;
+ }
- if (driConfigs[i] == NULL)
- return NULL;
+ if (driConfigs[i] == NULL)
+ return NULL;
- config = Xmalloc(sizeof *config);
- if (config == NULL)
- return NULL;
+ config = Xmalloc(sizeof *config);
+ if (config == NULL)
+ return NULL;
- config->modes = *modes;
- config->driConfig = driConfigs[i];
+ config->modes = *modes;
+ config->driConfig = driConfigs[i];
- return &config->modes;
+ return &config->modes;
}
_X_HIDDEN __GLcontextModes *
-driConvertConfigs(const __DRIcoreExtension *core,
- __GLcontextModes *modes, const __DRIconfig **configs)
+driConvertConfigs(const __DRIcoreExtension * core,
+ __GLcontextModes * modes, const __DRIconfig ** configs)
{
- __GLcontextModes head, *tail, *m;
-
- tail = &head;
- head.next = NULL;
- for (m = modes; m; m = m->next) {
- tail->next = createDriMode(core, m, configs);
- if (tail->next == NULL) {
- /* no matching dri config for m */
- continue;
- }
+ __GLcontextModes head, *tail, *m;
+
+ tail = &head;
+ head.next = NULL;
+ for (m = modes; m; m = m->next) {
+ tail->next = createDriMode(core, m, configs);
+ if (tail->next == NULL) {
+ /* no matching dri config for m */
+ continue;
+ }
- tail = tail->next;
- }
+ tail = tail->next;
+ }
- _gl_context_modes_destroy(modes);
+ _gl_context_modes_destroy(modes);
- return head.next;
+ return head.next;
}
_X_HIDDEN void
-driBindExtensions(__GLXscreenConfigs *psc, int dri2)
+driBindExtensions(__GLXscreenConfigs * psc, int dri2)
{
- const __DRIextension **extensions;
- int i;
+ const __DRIextension **extensions;
+ int i;
- extensions = psc->core->getExtensions(psc->__driScreen);
+ extensions = psc->core->getExtensions(psc->__driScreen);
- for (i = 0; extensions[i]; i++) {
+ for (i = 0; extensions[i]; i++) {
#ifdef __DRI_COPY_SUB_BUFFER
- if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
- psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
- __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
- }
+ if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
+ psc->driCopySubBuffer =
+ (__DRIcopySubBufferExtension *) extensions[i];
+ __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
+ }
#endif
#ifdef __DRI_SWAP_CONTROL
- if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
- psc->swapControl = (__DRIswapControlExtension *) extensions[i];
- __glXEnableDirectExtension(psc, "GLX_SGI_swap_control");
- __glXEnableDirectExtension(psc, "GLX_MESA_swap_control");
- }
+ /* No DRI2 support for swap_control at the moment, since SwapBuffers
+ * is done by the X server */
+ if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0 && !dri2) {
+ psc->swapControl = (__DRIswapControlExtension *) extensions[i];
+ __glXEnableDirectExtension(psc, "GLX_SGI_swap_control");
+ __glXEnableDirectExtension(psc, "GLX_MESA_swap_control");
+ }
#endif
#ifdef __DRI_ALLOCATE
- if (strcmp(extensions[i]->name, __DRI_ALLOCATE) == 0) {
- psc->allocate = (__DRIallocateExtension *) extensions[i];
- __glXEnableDirectExtension(psc, "GLX_MESA_allocate_memory");
- }
+ if (strcmp(extensions[i]->name, __DRI_ALLOCATE) == 0) {
+ psc->allocate = (__DRIallocateExtension *) extensions[i];
+ __glXEnableDirectExtension(psc, "GLX_MESA_allocate_memory");
+ }
#endif
#ifdef __DRI_FRAME_TRACKING
- if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) {
- psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i];
- __glXEnableDirectExtension(psc, "GLX_MESA_swap_frame_usage");
- }
+ if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) {
+ psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i];
+ __glXEnableDirectExtension(psc, "GLX_MESA_swap_frame_usage");
+ }
#endif
#ifdef __DRI_MEDIA_STREAM_COUNTER
- if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
- psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
- __glXEnableDirectExtension(psc, "GLX_SGI_video_sync");
- }
+ if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
+ psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
+ __glXEnableDirectExtension(psc, "GLX_SGI_video_sync");
+ }
#endif
#ifdef __DRI_SWAP_BUFFER_COUNTER
- /* No driver supports this at this time and the extension is
- * not defined in dri_interface.h. Will enable
- * GLX_OML_sync_control if implemented. */
+ /* No driver supports this at this time and the extension is
+ * not defined in dri_interface.h. Will enable
+ * GLX_OML_sync_control if implemented. */
#endif
#ifdef __DRI_READ_DRAWABLE
- if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
- __glXEnableDirectExtension(psc, "GLX_SGI_make_current_read");
- }
+ if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
+ __glXEnableDirectExtension(psc, "GLX_SGI_make_current_read");
+ }
#endif
#ifdef __DRI_TEX_BUFFER
- if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) && dri2) {
- psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
- __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap");
- }
+ if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) && dri2) {
+ psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
+ __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap");
+ }
+#endif
+
+#ifdef __DRI2_FLUSH
+ if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0) && dri2) {
+ psc->f = (__DRI2flushExtension *) extensions[i];
+ /* internal driver extension, no GL extension exposed */
+ }
#endif
- /* Ignore unknown extensions */
- }
+ /* Ignore unknown extensions */
+ }
}
#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c
index 44724d2c7d..ab24bd8ffe 100644
--- a/src/glx/x11/dri_glx.c
+++ b/src/glx/x11/dri_glx.c
@@ -40,6 +40,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "glxclient.h"
#include "glcontextmodes.h"
#include "xf86dri.h"
+#include "dri2.h"
#include "sarea.h"
#include <dlfcn.h>
#include <sys/types.h>
@@ -50,22 +51,24 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
-struct __GLXDRIdisplayPrivateRec {
- __GLXDRIdisplay base;
+struct __GLXDRIdisplayPrivateRec
+{
+ __GLXDRIdisplay base;
- /*
+ /*
** XFree86-DRI version information
*/
- int driMajor;
- int driMinor;
- int driPatch;
+ int driMajor;
+ int driMinor;
+ int driPatch;
};
-struct __GLXDRIcontextPrivateRec {
- __GLXDRIcontext base;
- __DRIcontext *driContext;
- XID hwContextID;
- __GLXscreenConfigs *psc;
+struct __GLXDRIcontextPrivateRec
+{
+ __GLXDRIcontext base;
+ __DRIcontext *driContext;
+ XID hwContextID;
+ __GLXscreenConfigs *psc;
};
/*
@@ -73,34 +76,51 @@ struct __GLXDRIcontextPrivateRec {
* the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
* Return True for success, False for failure.
*/
-static Bool driGetDriverName(Display *dpy, int scrNum, char **driverName)
+static Bool
+driGetDriverName(Display * dpy, int scrNum, char **driverName)
{
int directCapable;
Bool b;
+ int event, error;
int driverMajor, driverMinor, driverPatch;
*driverName = NULL;
- if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
- ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
- return False;
- }
- if (!directCapable) {
- ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
- return False;
+ if (XF86DRIQueryExtension(dpy, &event, &error)) { /* DRI1 */
+ if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
+ ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
+ return False;
+ }
+ if (!directCapable) {
+ ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
+ return False;
+ }
+
+ b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
+ &driverPatch, driverName);
+ if (!b) {
+ ErrorMessageF("Cannot determine driver name for screen %d\n",
+ scrNum);
+ return False;
+ }
+
+ InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
+ driverMajor, driverMinor, driverPatch, *driverName,
+ scrNum);
+
+ return True;
}
+ else if (DRI2QueryExtension(dpy, &event, &error)) { /* DRI2 */
+ char *dev;
+ Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);
- b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
- &driverPatch, driverName);
- if (!b) {
- ErrorMessageF("Cannot determine driver name for screen %d\n", scrNum);
- return False;
- }
+ if (ret)
+ Xfree(dev);
- InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
- driverMajor, driverMinor, driverPatch, *driverName, scrNum);
+ return ret;
+ }
- return True;
+ return False;
}
/*
@@ -109,17 +129,19 @@ static Bool driGetDriverName(Display *dpy, int scrNum, char **driverName)
* The returned char pointer points to a static array that will be
* overwritten by subsequent calls.
*/
-PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) {
+PUBLIC const char *
+glXGetScreenDriver(Display * dpy, int scrNum)
+{
static char ret[32];
char *driverName;
if (driGetDriverName(dpy, scrNum, &driverName)) {
int len;
if (!driverName)
- return NULL;
- len = strlen (driverName);
+ return NULL;
+ len = strlen(driverName);
if (len >= 31)
- return NULL;
- memcpy (ret, driverName, len+1);
+ return NULL;
+ memcpy(ret, driverName, len + 1);
Xfree(driverName);
return ret;
}
@@ -137,121 +159,125 @@ PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) {
*
* Note: The driver remains opened after this function returns.
*/
-PUBLIC const char *glXGetDriverConfig (const char *driverName)
+PUBLIC const char *
+glXGetDriverConfig(const char *driverName)
{
- void *handle = driOpenDriver (driverName);
+ void *handle = driOpenDriver(driverName);
if (handle)
- return dlsym (handle, "__driConfigOptions");
+ return dlsym(handle, "__driConfigOptions");
else
return NULL;
}
#ifdef XDAMAGE_1_1_INTERFACE
-static GLboolean has_damage_post(Display *dpy)
+static GLboolean
+has_damage_post(Display * dpy)
{
- static GLboolean inited = GL_FALSE;
- static GLboolean has_damage;
-
- if (!inited) {
- int major, minor;
-
- if (XDamageQueryVersion(dpy, &major, &minor) &&
- major == 1 && minor >= 1)
- {
- has_damage = GL_TRUE;
- } else {
- has_damage = GL_FALSE;
- }
- inited = GL_TRUE;
- }
-
- return has_damage;
+ static GLboolean inited = GL_FALSE;
+ static GLboolean has_damage;
+
+ if (!inited) {
+ int major, minor;
+
+ if (XDamageQueryVersion(dpy, &major, &minor) &&
+ major == 1 && minor >= 1) {
+ has_damage = GL_TRUE;
+ }
+ else {
+ has_damage = GL_FALSE;
+ }
+ inited = GL_TRUE;
+ }
+
+ return has_damage;
}
-static void __glXReportDamage(__DRIdrawable *driDraw,
- int x, int y,
- drm_clip_rect_t *rects, int num_rects,
- GLboolean front_buffer,
- void *loaderPrivate)
+static void
+__glXReportDamage(__DRIdrawable * driDraw,
+ int x, int y,
+ drm_clip_rect_t * rects, int num_rects,
+ GLboolean front_buffer, void *loaderPrivate)
{
- XRectangle *xrects;
- XserverRegion region;
- int i;
- int x_off, y_off;
- __GLXDRIdrawable *glxDraw = loaderPrivate;
- __GLXscreenConfigs *psc = glxDraw->psc;
- Display *dpy = psc->dpy;
- Drawable drawable;
-
- if (!has_damage_post(dpy))
- return;
-
- if (front_buffer) {
- x_off = x;
- y_off = y;
- drawable = RootWindow(dpy, psc->scr);
- } else{
- x_off = 0;
- y_off = 0;
- drawable = glxDraw->xDrawable;
- }
-
- xrects = malloc(sizeof(XRectangle) * num_rects);
- if (xrects == NULL)
- return;
-
- for (i = 0; i < num_rects; i++) {
- xrects[i].x = rects[i].x1 + x_off;
- xrects[i].y = rects[i].y1 + y_off;
- xrects[i].width = rects[i].x2 - rects[i].x1;
- xrects[i].height = rects[i].y2 - rects[i].y1;
- }
- region = XFixesCreateRegion(dpy, xrects, num_rects);
- free(xrects);
- XDamageAdd(dpy, drawable, region);
- XFixesDestroyRegion(dpy, region);
+ XRectangle *xrects;
+ XserverRegion region;
+ int i;
+ int x_off, y_off;
+ __GLXDRIdrawable *glxDraw = loaderPrivate;
+ __GLXscreenConfigs *psc = glxDraw->psc;
+ Display *dpy = psc->dpy;
+ Drawable drawable;
+
+ if (!has_damage_post(dpy))
+ return;
+
+ if (front_buffer) {
+ x_off = x;
+ y_off = y;
+ drawable = RootWindow(dpy, psc->scr);
+ }
+ else {
+ x_off = 0;
+ y_off = 0;
+ drawable = glxDraw->xDrawable;
+ }
+
+ xrects = malloc(sizeof(XRectangle) * num_rects);
+ if (xrects == NULL)
+ return;
+
+ for (i = 0; i < num_rects; i++) {
+ xrects[i].x = rects[i].x1 + x_off;
+ xrects[i].y = rects[i].y1 + y_off;
+ xrects[i].width = rects[i].x2 - rects[i].x1;
+ xrects[i].height = rects[i].y2 - rects[i].y1;
+ }
+ region = XFixesCreateRegion(dpy, xrects, num_rects);
+ free(xrects);
+ XDamageAdd(dpy, drawable, region);
+ XFixesDestroyRegion(dpy, region);
}
static const __DRIdamageExtension damageExtension = {
- { __DRI_DAMAGE, __DRI_DAMAGE_VERSION },
- __glXReportDamage,
+ {__DRI_DAMAGE, __DRI_DAMAGE_VERSION},
+ __glXReportDamage,
};
#endif
static GLboolean
-__glXDRIGetDrawableInfo(__DRIdrawable *drawable,
- unsigned int *index, unsigned int *stamp,
- int *X, int *Y, int *W, int *H,
- int *numClipRects, drm_clip_rect_t ** pClipRects,
- int *backX, int *backY,
- int *numBackClipRects, drm_clip_rect_t **pBackClipRects,
- void *loaderPrivate)
+__glXDRIGetDrawableInfo(__DRIdrawable * drawable,
+ unsigned int *index, unsigned int *stamp,
+ int *X, int *Y, int *W, int *H,
+ int *numClipRects, drm_clip_rect_t ** pClipRects,
+ int *backX, int *backY,
+ int *numBackClipRects,
+ drm_clip_rect_t ** pBackClipRects,
+ void *loaderPrivate)
{
- __GLXDRIdrawable *glxDraw = loaderPrivate;
- __GLXscreenConfigs *psc = glxDraw->psc;
- Display *dpy = psc->dpy;
-
- return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
- index, stamp, X, Y, W, H,
- numClipRects, pClipRects,
- backX, backY,
- numBackClipRects, pBackClipRects);
+ __GLXDRIdrawable *glxDraw = loaderPrivate;
+ __GLXscreenConfigs *psc = glxDraw->psc;
+ Display *dpy = psc->dpy;
+
+ return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
+ index, stamp, X, Y, W, H,
+ numClipRects, pClipRects,
+ backX, backY,
+ numBackClipRects, pBackClipRects);
}
static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
- { __DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION },
- __glXDRIGetDrawableInfo
+ {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION},
+ __glXDRIGetDrawableInfo
};
static const __DRIextension *loader_extensions[] = {
- &systemTimeExtension.base,
- &getDrawableInfoExtension.base,
+ &systemTimeExtension.base,
+ &getDrawableInfoExtension.base,
#ifdef XDAMAGE_1_1_INTERFACE
- &damageExtension.base,
+ &damageExtension.base,
#endif
- NULL
+ NULL
};
#ifndef GLX_USE_APPLEGL
@@ -270,400 +296,429 @@ static const __DRIextension *loader_extensions[] = {
* the client-side driver on success, or \c NULL on failure.
*/
static void *
-CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
- __GLXDRIdisplayPrivate * driDpy)
+CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc,
+ __GLXDRIdisplayPrivate * driDpy)
{
- void *psp = NULL;
- drm_handle_t hSAREA;
- drmAddress pSAREA = MAP_FAILED;
- char *BusID;
- __DRIversion ddx_version;
- __DRIversion dri_version;
- __DRIversion drm_version;
- __DRIframebuffer framebuffer;
- int fd = -1;
- int status;
-
- drm_magic_t magic;
- drmVersionPtr version;
- int newlyopened;
- char *driverName;
- drm_handle_t hFB;
- int junk;
- const __DRIconfig **driver_configs;
-
- /* DRI protocol version. */
- dri_version.major = driDpy->driMajor;
- dri_version.minor = driDpy->driMinor;
- dri_version.patch = driDpy->driPatch;
-
- framebuffer.base = MAP_FAILED;
- framebuffer.dev_priv = NULL;
-
- if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
- ErrorMessageF("XF86DRIOpenConnection failed\n");
- goto handle_error;
- }
-
- fd = drmOpenOnce(NULL, BusID, &newlyopened);
-
- Xfree(BusID); /* No longer needed */
-
- if (fd < 0) {
- ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
- goto handle_error;
- }
-
- if (drmGetMagic(fd, &magic)) {
- ErrorMessageF("drmGetMagic failed\n");
- goto handle_error;
- }
-
- version = drmGetVersion(fd);
- if (version) {
- drm_version.major = version->version_major;
- drm_version.minor = version->version_minor;
- drm_version.patch = version->version_patchlevel;
- drmFreeVersion(version);
- }
- else {
- drm_version.major = -1;
- drm_version.minor = -1;
- drm_version.patch = -1;
- }
-
- if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
- ErrorMessageF("XF86DRIAuthConnection failed\n");
- goto handle_error;
- }
-
- /* Get device name (like "tdfx") and the ddx version numbers.
- * We'll check the version in each DRI driver's "createNewScreen"
- * function. */
- if (!XF86DRIGetClientDriverName(dpy, scrn,
- &ddx_version.major,
- &ddx_version.minor,
- &ddx_version.patch,
- &driverName)) {
- ErrorMessageF("XF86DRIGetClientDriverName failed\n");
- goto handle_error;
- }
-
- Xfree(driverName); /* No longer needed. */
-
- /*
- * Get device-specific info. pDevPriv will point to a struct
- * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
- * has information about the screen size, depth, pitch, ancilliary
- * buffers, DRM mmap handles, etc.
- */
- if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
- &framebuffer.size, &framebuffer.stride,
- &framebuffer.dev_priv_size, &framebuffer.dev_priv)) {
- ErrorMessageF("XF86DRIGetDeviceInfo failed");
- goto handle_error;
- }
-
- framebuffer.width = DisplayWidth(dpy, scrn);
- framebuffer.height = DisplayHeight(dpy, scrn);
-
- /* Map the framebuffer region. */
- status = drmMap(fd, hFB, framebuffer.size,
- (drmAddressPtr)&framebuffer.base);
- if (status != 0) {
- ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
- goto handle_error;
- }
-
- /* Map the SAREA region. Further mmap regions may be setup in
- * each DRI driver's "createNewScreen" function.
- */
- status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
- if (status != 0) {
- ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
- goto handle_error;
- }
-
- psp = (*psc->legacy->createNewScreen)(scrn,
- &ddx_version,
- &dri_version,
- &drm_version,
- &framebuffer,
- pSAREA,
- fd,
- loader_extensions,
- &driver_configs,
- psc);
-
- if (psp == NULL) {
- ErrorMessageF("Calling driver entry point failed");
- goto handle_error;
- }
-
- psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
- psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
-
- return psp;
+ void *psp = NULL;
+ drm_handle_t hSAREA;
+ drmAddress pSAREA = MAP_FAILED;
+ char *BusID;
+ __DRIversion ddx_version;
+ __DRIversion dri_version;
+ __DRIversion drm_version;
+ __DRIframebuffer framebuffer;
+ int fd = -1;
+ int status;
+
+ drm_magic_t magic;
+ drmVersionPtr version;
+ int newlyopened;
+ char *driverName;
+ drm_handle_t hFB;
+ int junk;
+ const __DRIconfig **driver_configs;
+ __GLcontextModes *visual;
+
+ /* DRI protocol version. */
+ dri_version.major = driDpy->driMajor;
+ dri_version.minor = driDpy->driMinor;
+ dri_version.patch = driDpy->driPatch;
+
+ framebuffer.base = MAP_FAILED;
+ framebuffer.dev_priv = NULL;
+
+ if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
+ ErrorMessageF("XF86DRIOpenConnection failed\n");
+ goto handle_error;
+ }
+
+ fd = drmOpenOnce(NULL, BusID, &newlyopened);
+
+ Xfree(BusID); /* No longer needed */
+
+ if (fd < 0) {
+ ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
+ goto handle_error;
+ }
+
+ if (drmGetMagic(fd, &magic)) {
+ ErrorMessageF("drmGetMagic failed\n");
+ goto handle_error;
+ }
+
+ version = drmGetVersion(fd);
+ if (version) {
+ drm_version.major = version->version_major;
+ drm_version.minor = version->version_minor;
+ drm_version.patch = version->version_patchlevel;
+ drmFreeVersion(version);
+ }
+ else {
+ drm_version.major = -1;
+ drm_version.minor = -1;
+ drm_version.patch = -1;
+ }
+
+ if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
+ ErrorMessageF("XF86DRIAuthConnection failed\n");
+ goto handle_error;
+ }
+
+ /* Get device name (like "tdfx") and the ddx version numbers.
+ * We'll check the version in each DRI driver's "createNewScreen"
+ * function. */
+ if (!XF86DRIGetClientDriverName(dpy, scrn,
+ &ddx_version.major,
+ &ddx_version.minor,
+ &ddx_version.patch, &driverName)) {
+ ErrorMessageF("XF86DRIGetClientDriverName failed\n");
+ goto handle_error;
+ }
+
+ Xfree(driverName); /* No longer needed. */
+
+ /*
+ * Get device-specific info. pDevPriv will point to a struct
+ * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
+ * has information about the screen size, depth, pitch, ancilliary
+ * buffers, DRM mmap handles, etc.
+ */
+ if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
+ &framebuffer.size, &framebuffer.stride,
+ &framebuffer.dev_priv_size,
+ &framebuffer.dev_priv)) {
+ ErrorMessageF("XF86DRIGetDeviceInfo failed");
+ goto handle_error;
+ }
+
+ framebuffer.width = DisplayWidth(dpy, scrn);
+ framebuffer.height = DisplayHeight(dpy, scrn);
+
+ /* Map the framebuffer region. */
+ status = drmMap(fd, hFB, framebuffer.size,
+ (drmAddressPtr) & framebuffer.base);
+ if (status != 0) {
+ ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
+ goto handle_error;
+ }
+
+ /* Map the SAREA region. Further mmap regions may be setup in
+ * each DRI driver's "createNewScreen" function.
+ */
+ status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
+ if (status != 0) {
+ ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
+ goto handle_error;
+ }
+
+ psp = (*psc->legacy->createNewScreen) (scrn,
+ &ddx_version,
+ &dri_version,
+ &drm_version,
+ &framebuffer,
+ pSAREA,
+ fd,
+ loader_extensions,
+ &driver_configs, psc);
+
+ if (psp == NULL) {
+ ErrorMessageF("Calling driver entry point failed");
+ goto handle_error;
+ }
+
+ psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
+ psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+
+ psc->driver_configs = driver_configs;
+
+ /* Visuals with depth != screen depth are subject to automatic compositing
+ * in the X server, so DRI1 can't render to them properly. Mark them as
+ * non-conformant to prevent apps from picking them up accidentally.
+ */
+ for (visual = psc->visuals; visual; visual = visual->next) {
+ XVisualInfo template;
+ XVisualInfo *visuals;
+ int num_visuals;
+ long mask;
+
+ template.visualid = visual->visualID;
+ mask = VisualIDMask;
+ visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals);
+
+ if (visuals) {
+ if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn))
+ visual->visualRating = GLX_NON_CONFORMANT_CONFIG;
+
+ XFree(visuals);
+ }
+ }
+
+ return psp;
handle_error:
- if (pSAREA != MAP_FAILED)
- drmUnmap(pSAREA, SAREA_MAX);
+ if (pSAREA != MAP_FAILED)
+ drmUnmap(pSAREA, SAREA_MAX);
- if (framebuffer.base != MAP_FAILED)
- drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
+ if (framebuffer.base != MAP_FAILED)
+ drmUnmap((drmAddress) framebuffer.base, framebuffer.size);
- if (framebuffer.dev_priv != NULL)
- Xfree(framebuffer.dev_priv);
+ if (framebuffer.dev_priv != NULL)
+ Xfree(framebuffer.dev_priv);
- if (fd >= 0)
- drmCloseOnce(fd);
+ if (fd >= 0)
+ drmCloseOnce(fd);
- XF86DRICloseConnection(dpy, scrn);
+ XF86DRICloseConnection(dpy, scrn);
- ErrorMessageF("reverting to software direct rendering\n");
+ ErrorMessageF("reverting to software direct rendering\n");
- return NULL;
+ return NULL;
}
#else /* !GLX_USE_APPLEGL */
static void *
-CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
- __GLXDRIdisplayPrivate * driDpy)
+CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc,
+ __GLXDRIdisplayPrivate * driDpy)
{
- return NULL;
+ return NULL;
}
#endif /* !GLX_USE_APPLEGL */
-static void driDestroyContext(__GLXDRIcontext *context,
- __GLXscreenConfigs *psc, Display *dpy)
+static void
+driDestroyContext(__GLXDRIcontext * context,
+ __GLXscreenConfigs * psc, Display * dpy)
{
- __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
-
- (*psc->core->destroyContext)(pcp->driContext);
+ __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+
+ (*psc->core->destroyContext) (pcp->driContext);
- XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
- Xfree(pcp);
+ XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+ Xfree(pcp);
}
-static Bool driBindContext(__GLXDRIcontext *context,
- __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
+static Bool
+driBindContext(__GLXDRIcontext * context,
+ __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
{
- __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
- const __DRIcoreExtension *core = pcp->psc->core;
+ __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+ const __DRIcoreExtension *core = pcp->psc->core;
- return (*core->bindContext)(pcp->driContext,
- draw->driDrawable,
- read->driDrawable);
+ return (*core->bindContext) (pcp->driContext,
+ draw->driDrawable, read->driDrawable);
}
-static void driUnbindContext(__GLXDRIcontext *context)
+static void
+driUnbindContext(__GLXDRIcontext * context)
{
- __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
- const __DRIcoreExtension *core = pcp->psc->core;
+ __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+ const __DRIcoreExtension *core = pcp->psc->core;
- (*core->unbindContext)(pcp->driContext);
+ (*core->unbindContext) (pcp->driContext);
}
-static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc,
- const __GLcontextModes *mode,
- GLXContext gc,
- GLXContext shareList, int renderType)
+static __GLXDRIcontext *
+driCreateContext(__GLXscreenConfigs * psc,
+ const __GLcontextModes * mode,
+ GLXContext gc, GLXContext shareList, int renderType)
{
- __GLXDRIcontextPrivate *pcp, *pcp_shared;
- drm_context_t hwContext;
- __DRIcontext *shared = NULL;
- __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
-
- if (!psc || !psc->driScreen)
- return NULL;
-
- if (shareList) {
- pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
- shared = pcp_shared->driContext;
- }
-
- pcp = Xmalloc(sizeof *pcp);
- if (pcp == NULL)
- return NULL;
-
- pcp->psc = psc;
- if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
- mode->visualID,
- &pcp->hwContextID, &hwContext)) {
- Xfree(pcp);
- return NULL;
- }
-
- pcp->driContext =
- (*psc->legacy->createNewContext)(psc->__driScreen,
- config->driConfig,
- renderType,
- shared,
- hwContext,
- pcp);
- if (pcp->driContext == NULL) {
- XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
- Xfree(pcp);
- return NULL;
- }
-
- pcp->base.destroyContext = driDestroyContext;
- pcp->base.bindContext = driBindContext;
- pcp->base.unbindContext = driUnbindContext;
-
- return &pcp->base;
+ __GLXDRIcontextPrivate *pcp, *pcp_shared;
+ drm_context_t hwContext;
+ __DRIcontext *shared = NULL;
+ __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
+
+ if (!psc || !psc->driScreen)
+ return NULL;
+
+ if (shareList) {
+ pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
+ shared = pcp_shared->driContext;
+ }
+
+ pcp = Xmalloc(sizeof *pcp);
+ if (pcp == NULL)
+ return NULL;
+
+ pcp->psc = psc;
+ if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
+ mode->visualID,
+ &pcp->hwContextID, &hwContext)) {
+ Xfree(pcp);
+ return NULL;
+ }
+
+ pcp->driContext =
+ (*psc->legacy->createNewContext) (psc->__driScreen,
+ config->driConfig,
+ renderType, shared, hwContext, pcp);
+ if (pcp->driContext == NULL) {
+ XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+ Xfree(pcp);
+ return NULL;
+ }
+
+ pcp->base.destroyContext = driDestroyContext;
+ pcp->base.bindContext = driBindContext;
+ pcp->base.unbindContext = driUnbindContext;
+
+ return &pcp->base;
}
-static void driDestroyDrawable(__GLXDRIdrawable *pdraw)
+static void
+driDestroyDrawable(__GLXDRIdrawable * pdraw)
{
- __GLXscreenConfigs *psc = pdraw->psc;
+ __GLXscreenConfigs *psc = pdraw->psc;
- (*psc->core->destroyDrawable)(pdraw->driDrawable);
- XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
- Xfree(pdraw);
+ (*psc->core->destroyDrawable) (pdraw->driDrawable);
+ XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
+ Xfree(pdraw);
}
-static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc,
- XID xDrawable,
- GLXDrawable drawable,
- const __GLcontextModes *modes)
+static __GLXDRIdrawable *
+driCreateDrawable(__GLXscreenConfigs * psc,
+ XID xDrawable,
+ GLXDrawable drawable, const __GLcontextModes * modes)
{
- __GLXDRIdrawable *pdraw;
- drm_drawable_t hwDrawable;
- void *empty_attribute_list = NULL;
- __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
-
- /* Old dri can't handle GLX 1.3+ drawable constructors. */
- if (xDrawable != drawable)
- return NULL;
-
- pdraw = Xmalloc(sizeof(*pdraw));
- if (!pdraw)
- return NULL;
-
- pdraw->drawable = drawable;
- pdraw->psc = psc;
-
- if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable))
- return NULL;
-
- /* Create a new drawable */
- pdraw->driDrawable =
- (*psc->legacy->createNewDrawable)(psc->__driScreen,
- config->driConfig,
- hwDrawable,
- GLX_WINDOW_BIT,
- empty_attribute_list,
- pdraw);
-
- if (!pdraw->driDrawable) {
- XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
- Xfree(pdraw);
- return NULL;
- }
-
- pdraw->destroyDrawable = driDestroyDrawable;
-
- return pdraw;
+ __GLXDRIdrawable *pdraw;
+ drm_drawable_t hwDrawable;
+ void *empty_attribute_list = NULL;
+ __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
+
+ /* Old dri can't handle GLX 1.3+ drawable constructors. */
+ if (xDrawable != drawable)
+ return NULL;
+
+ pdraw = Xmalloc(sizeof(*pdraw));
+ if (!pdraw)
+ return NULL;
+
+ pdraw->drawable = drawable;
+ pdraw->psc = psc;
+
+ if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable))
+ return NULL;
+
+ /* Create a new drawable */
+ pdraw->driDrawable =
+ (*psc->legacy->createNewDrawable) (psc->__driScreen,
+ config->driConfig,
+ hwDrawable,
+ GLX_WINDOW_BIT,
+ empty_attribute_list, pdraw);
+
+ if (!pdraw->driDrawable) {
+ XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
+ Xfree(pdraw);
+ return NULL;
+ }
+
+ pdraw->destroyDrawable = driDestroyDrawable;
+
+ return pdraw;
}
-static void driSwapBuffers(__GLXDRIdrawable *pdraw)
+static void
+driSwapBuffers(__GLXDRIdrawable * pdraw)
{
- (*pdraw->psc->core->swapBuffers)(pdraw->driDrawable);
+ (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable);
}
-static void driCopySubBuffer(__GLXDRIdrawable *pdraw,
- int x, int y, int width, int height)
+static void
+driCopySubBuffer(__GLXDRIdrawable * pdraw,
+ int x, int y, int width, int height)
{
- (*pdraw->psc->driCopySubBuffer->copySubBuffer)(pdraw->driDrawable,
- x, y, width, height);
+ (*pdraw->psc->driCopySubBuffer->copySubBuffer) (pdraw->driDrawable,
+ x, y, width, height);
}
-static void driDestroyScreen(__GLXscreenConfigs *psc)
+static void
+driDestroyScreen(__GLXscreenConfigs * psc)
{
- /* Free the direct rendering per screen data */
- if (psc->__driScreen)
- (*psc->core->destroyScreen)(psc->__driScreen);
- psc->__driScreen = NULL;
- if (psc->driver)
- dlclose(psc->driver);
+ /* Free the direct rendering per screen data */
+ if (psc->__driScreen)
+ (*psc->core->destroyScreen) (psc->__driScreen);
+ psc->__driScreen = NULL;
+ if (psc->driver)
+ dlclose(psc->driver);
}
-static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen,
- __GLXdisplayPrivate *priv)
+static __GLXDRIscreen *
+driCreateScreen(__GLXscreenConfigs * psc, int screen,
+ __GLXdisplayPrivate * priv)
{
- __GLXDRIdisplayPrivate *pdp;
- __GLXDRIscreen *psp;
- const __DRIextension **extensions;
- char *driverName;
- int i;
-
- psp = Xmalloc(sizeof *psp);
- if (psp == NULL)
- return NULL;
-
- /* Initialize per screen dynamic client GLX extensions */
- psc->ext_list_first_time = GL_TRUE;
-
- if (!driGetDriverName(priv->dpy, screen, &driverName)) {
- Xfree(psp);
- return NULL;
- }
-
- psc->driver = driOpenDriver(driverName);
- Xfree(driverName);
- if (psc->driver == NULL) {
- Xfree(psp);
- return NULL;
- }
-
- extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
- if (extensions == NULL) {
- ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
- Xfree(psp);
- return NULL;
- }
-
- for (i = 0; extensions[i]; i++) {
- if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
- psc->core = (__DRIcoreExtension *) extensions[i];
- if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
- psc->legacy = (__DRIlegacyExtension *) extensions[i];
- }
-
- if (psc->core == NULL || psc->legacy == NULL) {
- Xfree(psp);
- return NULL;
- }
-
- pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay;
- psc->__driScreen =
- CallCreateNewScreen(psc->dpy, screen, psc, pdp);
- if (psc->__driScreen == NULL) {
- dlclose(psc->driver);
- Xfree(psp);
- return NULL;
- }
-
- driBindExtensions(psc, 0);
- if (psc->driCopySubBuffer)
- psp->copySubBuffer = driCopySubBuffer;
-
- psp->destroyScreen = driDestroyScreen;
- psp->createContext = driCreateContext;
- psp->createDrawable = driCreateDrawable;
- psp->swapBuffers = driSwapBuffers;
-
- return psp;
+ __GLXDRIdisplayPrivate *pdp;
+ __GLXDRIscreen *psp;
+ const __DRIextension **extensions;
+ char *driverName;
+ int i;
+
+ psp = Xcalloc(1, sizeof *psp);
+ if (psp == NULL)
+ return NULL;
+
+ /* Initialize per screen dynamic client GLX extensions */
+ psc->ext_list_first_time = GL_TRUE;
+
+ if (!driGetDriverName(priv->dpy, screen, &driverName)) {
+ Xfree(psp);
+ return NULL;
+ }
+
+ psc->driver = driOpenDriver(driverName);
+ Xfree(driverName);
+ if (psc->driver == NULL) {
+ Xfree(psp);
+ return NULL;
+ }
+
+ extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
+ if (extensions == NULL) {
+ ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
+ Xfree(psp);
+ return NULL;
+ }
+
+ for (i = 0; extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
+ psc->core = (__DRIcoreExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
+ psc->legacy = (__DRIlegacyExtension *) extensions[i];
+ }
+
+ if (psc->core == NULL || psc->legacy == NULL) {
+ Xfree(psp);
+ return NULL;
+ }
+
+ pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay;
+ psc->__driScreen = CallCreateNewScreen(psc->dpy, screen, psc, pdp);
+ if (psc->__driScreen == NULL) {
+ dlclose(psc->driver);
+ Xfree(psp);
+ return NULL;
+ }
+
+ driBindExtensions(psc, 0);
+ if (psc->driCopySubBuffer)
+ psp->copySubBuffer = driCopySubBuffer;
+
+ psp->destroyScreen = driDestroyScreen;
+ psp->createContext = driCreateContext;
+ psp->createDrawable = driCreateDrawable;
+ psp->swapBuffers = driSwapBuffers;
+ psp->waitX = NULL;
+ psp->waitGL = NULL;
+
+ return psp;
}
/* Called from __glXFreeDisplayPrivate.
*/
-static void driDestroyDisplay(__GLXDRIdisplay *dpy)
+static void
+driDestroyDisplay(__GLXDRIdisplay * dpy)
{
- Xfree(dpy);
+ Xfree(dpy);
}
/*
@@ -671,33 +726,34 @@ static void driDestroyDisplay(__GLXDRIdisplay *dpy)
* This is called from __glXInitialize() when we are given a new
* display pointer.
*/
-_X_HIDDEN __GLXDRIdisplay *driCreateDisplay(Display *dpy)
+_X_HIDDEN __GLXDRIdisplay *
+driCreateDisplay(Display * dpy)
{
- __GLXDRIdisplayPrivate *pdpyp;
- int eventBase, errorBase;
- int major, minor, patch;
+ __GLXDRIdisplayPrivate *pdpyp;
+ int eventBase, errorBase;
+ int major, minor, patch;
- if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
- return NULL;
- }
+ if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
+ return NULL;
+ }
- if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
- return NULL;
- }
+ if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
+ return NULL;
+ }
- pdpyp = Xmalloc(sizeof *pdpyp);
- if (!pdpyp) {
- return NULL;
- }
+ pdpyp = Xmalloc(sizeof *pdpyp);
+ if (!pdpyp) {
+ return NULL;
+ }
- pdpyp->driMajor = major;
- pdpyp->driMinor = minor;
- pdpyp->driPatch = patch;
+ pdpyp->driMajor = major;
+ pdpyp->driMinor = minor;
+ pdpyp->driPatch = patch;
- pdpyp->base.destroyDisplay = driDestroyDisplay;
- pdpyp->base.createScreen = driCreateScreen;
+ pdpyp->base.destroyDisplay = driDestroyDisplay;
+ pdpyp->base.createScreen = driCreateScreen;
- return &pdpyp->base;
+ return &pdpyp->base;
}
#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/x11/drisw_glx.c b/src/glx/x11/drisw_glx.c
index 35bbd9151c..15e1586658 100644
--- a/src/glx/x11/drisw_glx.c
+++ b/src/glx/x11/drisw_glx.c
@@ -359,7 +359,7 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen,
const char *driverName = "swrast";
int i;
- psp = Xmalloc(sizeof *psp);
+ psp = Xcalloc(1, sizeof *psp);
if (psp == NULL)
return NULL;
@@ -401,10 +401,14 @@ driCreateScreen(__GLXscreenConfigs * psc, int screen,
psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
+ psc->driver_configs = driver_configs;
+
psp->destroyScreen = driDestroyScreen;
psp->createContext = driCreateContext;
psp->createDrawable = driCreateDrawable;
psp->swapBuffers = driSwapBuffers;
+ psp->waitX = NULL;
+ psp->waitGL = NULL;
return psp;
diff --git a/src/glx/x11/glx_pbuffer.c b/src/glx/x11/glx_pbuffer.c
index a602cd2881..88a17df6f8 100644
--- a/src/glx/x11/glx_pbuffer.c
+++ b/src/glx/x11/glx_pbuffer.c
@@ -25,7 +25,7 @@
/**
* \file glx_pbuffer.c
* Implementation of pbuffer related functions.
- *
+ *
* \author Ian Romanick <idr@us.ibm.com>
*/
@@ -114,7 +114,7 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
* \note
* This function dynamically determines whether to use the SGIX_pbuffer
* version of the protocol or the GLX 1.3 version of the protocol.
- *
+ *
* \todo
* This function needs to be modified to work with direct-rendering drivers.
*/
@@ -189,6 +189,20 @@ determineTextureTarget(const int *attribs, int numAttribs)
return target;
}
+
+
+static GLenum
+determineTextureFormat(const int *attribs, int numAttribs)
+{
+ int i;
+
+ for (i = 0; i < numAttribs; i++) {
+ if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
+ return attribs[2 * i + 1];
+ }
+
+ return 0;
+}
#endif
/**
@@ -294,6 +308,9 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable,
if (pdraw != NULL && !pdraw->textureTarget)
pdraw->textureTarget =
determineTextureTarget((const int *) data, num_attributes);
+ if (pdraw != NULL && !pdraw->textureFormat)
+ pdraw->textureFormat =
+ determineTextureFormat((const int *) data, num_attributes);
}
#endif
@@ -374,6 +391,7 @@ CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig,
}
pdraw->textureTarget = determineTextureTarget(attrib_list, i);
+ pdraw->textureFormat = determineTextureFormat(attrib_list, i);
} while (0);
#endif
@@ -663,8 +681,7 @@ GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
PUBLIC
GLX_ALIAS_VOID(glXSelectEventSGIX,
(Display * dpy, GLXDrawable drawable,
- unsigned long mask), (dpy, drawable, mask),
- glXSelectEvent)
+ unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
PUBLIC
GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
diff --git a/src/glx/x11/glx_query.c b/src/glx/x11/glx_query.c
index 2789b841b1..efad13d376 100644
--- a/src/glx/x11/glx_query.c
+++ b/src/glx/x11/glx_query.c
@@ -25,7 +25,7 @@
/**
* \file glx_query.c
* Generic utility functions to query internal data from the server.
- *
+ *
* \author Ian Romanick <idr@us.ibm.com>
*/
@@ -43,13 +43,10 @@
* Exchange a protocol request for glXQueryServerString.
*/
char *
-__glXQueryServerString(Display* dpy,
- int opcode,
- CARD32 screen,
- CARD32 name)
+__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
{
xcb_connection_t *c = XGetXCBConnection(dpy);
- xcb_glx_query_server_string_reply_t* reply =
+ xcb_glx_query_server_string_reply_t *reply =
xcb_glx_query_server_string_reply(c,
xcb_glx_query_server_string(c,
screen,
@@ -59,7 +56,7 @@ __glXQueryServerString(Display* dpy,
/* The spec doesn't mention this, but the Xorg server replies with
* a string already terminated with '\0'. */
uint32_t len = xcb_glx_query_server_string_string_length(reply);
- char* buf = Xmalloc(len);
+ char *buf = Xmalloc(len);
memcpy(buf, xcb_glx_query_server_string_string(reply), len);
free(reply);
@@ -70,23 +67,20 @@ __glXQueryServerString(Display* dpy,
* Exchange a protocol request for glGetString.
*/
char *
-__glXGetString(Display* dpy,
- int opcode,
- CARD32 contextTag,
- CARD32 name)
+__glXGetString(Display * dpy, int opcode, CARD32 contextTag, CARD32 name)
{
xcb_connection_t *c = XGetXCBConnection(dpy);
- xcb_glx_get_string_reply_t* reply =
- xcb_glx_get_string_reply(c,
- xcb_glx_get_string(c,
- contextTag,
- name),
- NULL);
+ xcb_glx_get_string_reply_t *reply = xcb_glx_get_string_reply(c,
+ xcb_glx_get_string
+ (c,
+ contextTag,
+ name),
+ NULL);
/* The spec doesn't mention this, but the Xorg server replies with
* a string already terminated with '\0'. */
uint32_t len = xcb_glx_get_string_string_length(reply);
- char* buf = Xmalloc(len);
+ char *buf = Xmalloc(len);
memcpy(buf, xcb_glx_get_string_string(reply), len);
free(reply);
@@ -97,7 +91,7 @@ __glXGetString(Display* dpy,
/**
* GLX protocol structure for the ficticious "GXLGenericGetString" request.
- *
+ *
* This is a non-existant protocol packet. It just so happens that all of
* the real protocol packets used to request a string from the server have
* an identical binary layout. The only difference between them is the
@@ -167,25 +161,17 @@ __glXGetStringFromServer(Display * dpy, int opcode, CARD32 glxCode,
}
char *
-__glXQueryServerString(Display* dpy,
- int opcode,
- CARD32 screen,
- CARD32 name)
+__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
{
return __glXGetStringFromServer(dpy, opcode,
- X_GLXQueryServerString,
- screen, name);
+ X_GLXQueryServerString, screen, name);
}
char *
-__glXGetString(Display* dpy,
- int opcode,
- CARD32 contextTag,
- CARD32 name)
+__glXGetString(Display * dpy, int opcode, CARD32 contextTag, CARD32 name)
{
return __glXGetStringFromServer(dpy, opcode, X_GLsop_GetString,
contextTag, name);
}
#endif /* USE_XCB */
-
diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h
index 16f6074ed8..00ee14fb05 100644
--- a/src/glx/x11/glxclient.h
+++ b/src/glx/x11/glxclient.h
@@ -55,9 +55,7 @@
#include "GL/internal/glcore.h"
#include "glapi/glapitable.h"
#include "glxhash.h"
-#if defined( USE_XTHREADS )
-# include <X11/Xthreads.h>
-#elif defined( PTHREADS )
+#if defined( PTHREADS )
# include <pthread.h>
#endif
@@ -67,7 +65,7 @@
/* If we build the library with gcc's -fvisibility=hidden flag, we'll
* use the PUBLIC macro to mark functions that are to be exported.
*
- * We also need to define a USED attribute, so the optimizer doesn't
+ * We also need to define a USED attribute, so the optimizer doesn't
* inline a static function that we later use in an alias. - ajax
*/
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
@@ -80,8 +78,8 @@
-#define GLX_MAJOR_VERSION 1 /* current version numbers */
-#define GLX_MINOR_VERSION 4
+#define GLX_MAJOR_VERSION 1 /* current version numbers */
+#define GLX_MINOR_VERSION 4
#define __GLX_MAX_TEXTURE_UNITS 32
@@ -95,7 +93,7 @@ typedef struct _glapi_table __GLapi;
#ifdef GLX_DIRECT_RENDERING
-#define containerOf(ptr, type, member) \
+#define containerOf(ptr, type, member) \
(type *)( (char *)ptr - offsetof(type,member) )
#include <GL/internal/dri_interface.h>
@@ -112,72 +110,78 @@ typedef struct __GLXDRIcontextRec __GLXDRIcontext;
#include "glxextensions.h"
-struct __GLXDRIdisplayRec {
+struct __GLXDRIdisplayRec
+{
/**
* Method to destroy the private DRI display data.
*/
- void (*destroyDisplay)(__GLXDRIdisplay *display);
+ void (*destroyDisplay) (__GLXDRIdisplay * display);
- __GLXDRIscreen *(*createScreen)(__GLXscreenConfigs *psc, int screen,
- __GLXdisplayPrivate *priv);
+ __GLXDRIscreen *(*createScreen) (__GLXscreenConfigs * psc, int screen,
+ __GLXdisplayPrivate * priv);
};
-struct __GLXDRIscreenRec {
+struct __GLXDRIscreenRec
+{
- void (*destroyScreen)(__GLXscreenConfigs *psc);
+ void (*destroyScreen) (__GLXscreenConfigs * psc);
- __GLXDRIcontext *(*createContext)(__GLXscreenConfigs *psc,
- const __GLcontextModes *mode,
- GLXContext gc,
- GLXContext shareList, int renderType);
-
- __GLXDRIdrawable *(*createDrawable)(__GLXscreenConfigs *psc,
- XID drawable,
- GLXDrawable glxDrawable,
- const __GLcontextModes *modes);
+ __GLXDRIcontext *(*createContext) (__GLXscreenConfigs * psc,
+ const __GLcontextModes * mode,
+ GLXContext gc,
+ GLXContext shareList, int renderType);
- void (*swapBuffers)(__GLXDRIdrawable *pdraw);
- void (*copySubBuffer)(__GLXDRIdrawable *pdraw,
- int x, int y, int width, int height);
+ __GLXDRIdrawable *(*createDrawable) (__GLXscreenConfigs * psc,
+ XID drawable,
+ GLXDrawable glxDrawable,
+ const __GLcontextModes * modes);
+
+ void (*swapBuffers) (__GLXDRIdrawable * pdraw);
+ void (*copySubBuffer) (__GLXDRIdrawable * pdraw,
+ int x, int y, int width, int height);
+ void (*waitX) (__GLXDRIdrawable * pdraw);
+ void (*waitGL) (__GLXDRIdrawable * pdraw);
};
-struct __GLXDRIcontextRec {
- void (*destroyContext)(__GLXDRIcontext *context, __GLXscreenConfigs *psc,
- Display *dpy);
- Bool (*bindContext)(__GLXDRIcontext *context,
- __GLXDRIdrawable *pdraw,
- __GLXDRIdrawable *pread);
-
- void (*unbindContext)(__GLXDRIcontext *context);
+struct __GLXDRIcontextRec
+{
+ void (*destroyContext) (__GLXDRIcontext * context,
+ __GLXscreenConfigs * psc, Display * dpy);
+ Bool(*bindContext) (__GLXDRIcontext * context, __GLXDRIdrawable * pdraw,
+ __GLXDRIdrawable * pread);
+
+ void (*unbindContext) (__GLXDRIcontext * context);
};
-struct __GLXDRIdrawableRec {
- void (*destroyDrawable)(__GLXDRIdrawable *drawable);
+struct __GLXDRIdrawableRec
+{
+ void (*destroyDrawable) (__GLXDRIdrawable * drawable);
- XID xDrawable;
- XID drawable;
- __GLXscreenConfigs *psc;
- GLenum textureTarget;
- __DRIdrawable *driDrawable;
+ XID xDrawable;
+ XID drawable;
+ __GLXscreenConfigs *psc;
+ GLenum textureTarget;
+ __DRIdrawable *driDrawable;
+ GLenum textureFormat; /* EXT_texture_from_pixmap support */
};
/*
** Function to create and DRI display data and initialize the display
** dependent methods.
*/
-extern __GLXDRIdisplay *driswCreateDisplay(Display *dpy);
-extern __GLXDRIdisplay *driCreateDisplay(Display *dpy);
-extern __GLXDRIdisplay *dri2CreateDisplay(Display *dpy);
+extern __GLXDRIdisplay *driswCreateDisplay(Display * dpy);
+extern __GLXDRIdisplay *driCreateDisplay(Display * dpy);
+extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy);
-extern void DRI_glXUseXFont( Font font, int first, int count, int listbase );
+extern void DRI_glXUseXFont(Font font, int first, int count, int listbase);
/*
** Functions to obtain driver configuration information from a direct
** rendering client application
*/
-extern const char *glXGetScreenDriver (Display *dpy, int scrNum);
+extern const char *glXGetScreenDriver(Display * dpy, int scrNum);
-extern const char *glXGetDriverConfig (const char *driverName);
+extern const char *glXGetDriverConfig(const char *driverName);
#endif
@@ -185,53 +189,57 @@ extern const char *glXGetDriverConfig (const char *driverName);
#define __GL_CLIENT_ATTRIB_STACK_DEPTH 16
-typedef struct __GLXpixelStoreModeRec {
- GLboolean swapEndian;
- GLboolean lsbFirst;
- GLuint rowLength;
- GLuint imageHeight;
- GLuint imageDepth;
- GLuint skipRows;
- GLuint skipPixels;
- GLuint skipImages;
- GLuint alignment;
+typedef struct __GLXpixelStoreModeRec
+{
+ GLboolean swapEndian;
+ GLboolean lsbFirst;
+ GLuint rowLength;
+ GLuint imageHeight;
+ GLuint imageDepth;
+ GLuint skipRows;
+ GLuint skipPixels;
+ GLuint skipImages;
+ GLuint alignment;
} __GLXpixelStoreMode;
-typedef struct __GLXattributeRec {
- GLuint mask;
+typedef struct __GLXattributeRec
+{
+ GLuint mask;
/**
* Pixel storage state. Most of the pixel store mode state is kept
* here and used by the client code to manage the packing and
* unpacking of data sent to/received from the server.
*/
- __GLXpixelStoreMode storePack, storeUnpack;
+ __GLXpixelStoreMode storePack, storeUnpack;
/**
* Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically
* disabled?
*/
- GLboolean NoDrawArraysProtocol;
-
+ GLboolean NoDrawArraysProtocol;
+
/**
* Vertex Array storage state. The vertex array component
* state is stored here and is used to manage the packing of
* DrawArrays data sent to the server.
*/
- struct array_state_vector * array_state;
+ struct array_state_vector *array_state;
} __GLXattribute;
-typedef struct __GLXattributeMachineRec {
- __GLXattribute *stack[__GL_CLIENT_ATTRIB_STACK_DEPTH];
- __GLXattribute **stackPointer;
+typedef struct __GLXattributeMachineRec
+{
+ __GLXattribute *stack[__GL_CLIENT_ATTRIB_STACK_DEPTH];
+ __GLXattribute **stackPointer;
} __GLXattributeMachine;
/**
* GLX state that needs to be kept on the client. One of these records
* exist for each context that has been made current by this client.
*/
-struct __GLXcontextRec {
+struct __GLXcontextRec
+{
/**
* \name Drawing command buffer.
*
@@ -248,13 +256,13 @@ struct __GLXcontextRec {
* These must be the first 6 fields since they are static initialized
* in the dummy context in glxext.c
*/
- /*@{*/
- GLubyte *buf;
- GLubyte *pc;
- GLubyte *limit;
- GLubyte *bufEnd;
- GLint bufSize;
- /*@}*/
+ /*@{ */
+ GLubyte *buf;
+ GLubyte *pc;
+ GLubyte *limit;
+ GLubyte *bufEnd;
+ GLint bufSize;
+ /*@} */
/**
* The XID of this rendering context. When the context is created a
@@ -262,24 +270,24 @@ struct __GLXcontextRec {
* destroyed but is still current to some thread. In this case the
* context will be freed on next MakeCurrent.
*/
- XID xid;
+ XID xid;
/**
* The XID of the \c shareList context.
*/
- XID share_xid;
+ XID share_xid;
/**
* Screen number.
*/
- GLint screen;
- __GLXscreenConfigs *psc;
+ GLint screen;
+ __GLXscreenConfigs *psc;
/**
* \c GL_TRUE if the context was created with ImportContext, which
* means the server-side context was created by another X client.
*/
- GLboolean imported;
+ GLboolean imported;
/**
* The context tag returned by MakeCurrent when this context is made
@@ -289,7 +297,7 @@ struct __GLXcontextRec {
* \c WaitX, \c WaitGL, \c UseXFont, and \c MakeCurrent (for the old
* context)).
*/
- GLXContextTag currentContextTag;
+ GLXContextTag currentContextTag;
/**
* \name Rendering mode
@@ -298,11 +306,11 @@ struct __GLXcontextRec {
* When \c glRenderMode is called, the buffer associated with the
* previous rendering mode (feedback or select) is filled.
*/
- /*@{*/
- GLenum renderMode;
- GLfloat *feedbackBuf;
- GLuint *selectBuf;
- /*@}*/
+ /*@{ */
+ GLenum renderMode;
+ GLfloat *feedbackBuf;
+ GLuint *selectBuf;
+ /*@} */
/**
* This is \c GL_TRUE if the pixel unpack modes are such that an image
@@ -310,43 +318,43 @@ struct __GLXcontextRec {
* still be true that the server will have to do some work. This
* just promises that a straight copy will fetch the correct bytes.
*/
- GLboolean fastImageUnpack;
+ GLboolean fastImageUnpack;
/**
* Fill newImage with the unpacked form of \c oldImage getting it
* ready for transport to the server.
*/
- void (*fillImage)(__GLXcontext*, GLint, GLint, GLint, GLint, GLenum,
- GLenum, const GLvoid*, GLubyte*, GLubyte*);
+ void (*fillImage) (__GLXcontext *, GLint, GLint, GLint, GLint, GLenum,
+ GLenum, const GLvoid *, GLubyte *, GLubyte *);
/**
* Client side attribs.
*/
- __GLXattributeMachine attributes;
+ __GLXattributeMachine attributes;
/**
* Client side error code. This is set when client side gl API
* routines need to set an error because of a bad enumerant or
* running out of memory, etc.
*/
- GLenum error;
+ GLenum error;
/**
* Whether this context does direct rendering.
*/
- Bool isDirect;
+ Bool isDirect;
/**
* \c dpy of current display for this context. Will be \c NULL if not
* current to any display, or if this is the "dummy context".
*/
- Display *currentDpy;
+ Display *currentDpy;
/**
* The current drawable for this context. Will be None if this
* context is not current to any drawable. currentReadable is below.
*/
- GLXDrawable currentDrawable;
+ GLXDrawable currentDrawable;
/**
* \name GL Constant Strings
@@ -355,38 +363,38 @@ struct __GLXcontextRec {
* These pertain to GL attributes, not to be confused with
* GLX versioning attributes.
*/
- /*@{*/
- GLubyte *vendor;
- GLubyte *renderer;
- GLubyte *version;
- GLubyte *extensions;
- /*@}*/
+ /*@{ */
+ GLubyte *vendor;
+ GLubyte *renderer;
+ GLubyte *version;
+ GLubyte *extensions;
+ /*@} */
/**
* Record the dpy this context was created on for later freeing
*/
- Display *createDpy;
+ Display *createDpy;
/**
* Maximum small render command size. This is the smaller of 64k and
* the size of the above buffer.
*/
- GLint maxSmallRenderCommandSize;
+ GLint maxSmallRenderCommandSize;
/**
* Major opcode for the extension. Copied here so a lookup isn't
* needed.
*/
- GLint majorOpcode;
+ GLint majorOpcode;
/**
* Pointer to the mode used to create this context.
*/
- const __GLcontextModes * mode;
+ const __GLcontextModes *mode;
#ifdef GLX_DIRECT_RENDERING
- __GLXDRIcontext *driContext;
- __DRIcontext *__driContext;
+ __GLXDRIcontext *driContext;
+ __DRIcontext *__driContext;
#endif
/**
@@ -395,22 +403,22 @@ struct __GLXcontextRec {
*
* \since Internal API version 20030606.
*/
- GLXDrawable currentReadable;
+ GLXDrawable currentReadable;
- /**
+ /**
* Pointer to client-state data that is private to libGL. This is only
* used for indirect rendering contexts.
*
* No internal API version change was made for this change. Client-side
* drivers should NEVER use this data or even care that it exists.
*/
- void * client_state_private;
+ void *client_state_private;
/**
* Stored value for \c glXQueryContext attribute \c GLX_RENDER_TYPE.
*/
int renderType;
-
+
/**
* \name Raw server GL version
*
@@ -418,18 +426,23 @@ struct __GLXcontextRec {
* returned by the server, and it may not reflect what is actually
* supported (or reported) by the client-side library.
*/
- /*@{*/
+ /*@{ */
int server_major; /**< Major version number. */
int server_minor; /**< Minor version number. */
- /*@}*/
+ /*@} */
- char gl_extension_bits[ __GL_EXT_BYTES ];
+ /**
+ * Thread ID we're currently current in. Zero if none.
+ */
+ unsigned long thread_id;
+
+ char gl_extension_bits[__GL_EXT_BYTES];
};
-#define __glXSetError(gc,code) \
- if (!(gc)->error) { \
- (gc)->error = code; \
- }
+#define __glXSetError(gc,code) \
+ if (!(gc)->error) { \
+ (gc)->error = code; \
+ }
extern void __glFreeAttributeState(__GLXcontext *);
@@ -440,7 +453,7 @@ extern void __glFreeAttributeState(__GLXcontext *);
* that will use the GLXRender GLX command. In this case it is
* \c glPolygonStipple.
*/
-#define __GLX_MAX_SMALL_RENDER_CMD_SIZE 156
+#define __GLX_MAX_SMALL_RENDER_CMD_SIZE 156
/**
* To keep the implementation fast, the code uses a "limit" pointer
@@ -452,69 +465,76 @@ extern void __glFreeAttributeState(__GLXcontext *);
* efficacy of the buffer. The "+32" is just to keep the code working
* in case somebody counts wrong.
*/
-#define __GLX_BUFFER_LIMIT_SIZE (__GLX_MAX_SMALL_RENDER_CMD_SIZE + 32)
+#define __GLX_BUFFER_LIMIT_SIZE (__GLX_MAX_SMALL_RENDER_CMD_SIZE + 32)
/**
* This implementation uses a smaller threshold for switching
* to the RenderLarge protocol than the protcol requires so that
* large copies don't occur.
*/
-#define __GLX_RENDER_CMD_SIZE_LIMIT 4096
+#define __GLX_RENDER_CMD_SIZE_LIMIT 4096
/**
* One of these records exists per screen of the display. It contains
* a pointer to the config data for that screen (if the screen supports GL).
*/
-struct __GLXscreenConfigsRec {
+struct __GLXscreenConfigsRec
+{
/**
* GLX extension string reported by the X-server.
*/
- const char *serverGLXexts;
+ const char *serverGLXexts;
/**
* GLX extension string to be reported to applications. This is the
* set of extensions that the application can actually use.
*/
- char *effectiveGLXexts;
+ char *effectiveGLXexts;
#ifdef GLX_DIRECT_RENDERING
/**
* Per screen direct rendering interface functions and data.
*/
- __DRIscreen *__driScreen;
- const __DRIcoreExtension *core;
- const __DRIlegacyExtension *legacy;
- const __DRIswrastExtension *swrast;
- const __DRIdri2Extension *dri2;
- __glxHashTable *drawHash;
- Display *dpy;
- int scr, fd;
- void *driver;
+ __DRIscreen *__driScreen;
+ const __DRIcoreExtension *core;
+ const __DRIlegacyExtension *legacy;
+ const __DRIswrastExtension *swrast;
+ const __DRIdri2Extension *dri2;
+ __glxHashTable *drawHash;
+ Display *dpy;
+ int scr, fd;
+ void *driver;
+
+ __GLXDRIscreen *driScreen;
- __GLXDRIscreen *driScreen;
+ const __DRIconfig **driver_configs;
#ifdef __DRI_COPY_SUB_BUFFER
- const __DRIcopySubBufferExtension *driCopySubBuffer;
+ const __DRIcopySubBufferExtension *driCopySubBuffer;
#endif
#ifdef __DRI_SWAP_CONTROL
- const __DRIswapControlExtension *swapControl;
+ const __DRIswapControlExtension *swapControl;
#endif
#ifdef __DRI_ALLOCATE
- const __DRIallocateExtension *allocate;
+ const __DRIallocateExtension *allocate;
#endif
#ifdef __DRI_FRAME_TRACKING
- const __DRIframeTrackingExtension *frameTracking;
+ const __DRIframeTrackingExtension *frameTracking;
#endif
#ifdef __DRI_MEDIA_STREAM_COUNTER
- const __DRImediaStreamCounterExtension *msc;
+ const __DRImediaStreamCounterExtension *msc;
#endif
#ifdef __DRI_TEX_BUFFER
- const __DRItexBufferExtension *texBuffer;
+ const __DRItexBufferExtension *texBuffer;
+#endif
+
+#ifdef __DRI2_FLUSH
+ const __DRI2flushExtension *f;
#endif
#endif
@@ -522,7 +542,7 @@ struct __GLXscreenConfigsRec {
/**
* Linked list of glx visuals and fbconfigs for this screen.
*/
- __GLcontextModes *visuals, *configs;
+ __GLcontextModes *visuals, *configs;
/**
* Per-screen dynamic GLX extension tracking. The \c direct_support
@@ -531,10 +551,10 @@ struct __GLXscreenConfigsRec {
* this field. The \c __GLXscreenConfigs structure is not used outside
* libGL.
*/
- /*@{*/
- unsigned char direct_support[8];
- GLboolean ext_list_first_time;
- /*@}*/
+ /*@{ */
+ unsigned char direct_support[8];
+ GLboolean ext_list_first_time;
+ /*@} */
};
@@ -542,83 +562,86 @@ struct __GLXscreenConfigsRec {
* Per display private data. One of these records exists for each display
* that is using the OpenGL (GLX) extension.
*/
-struct __GLXdisplayPrivateRec {
+struct __GLXdisplayPrivateRec
+{
/**
* Back pointer to the display
*/
- Display *dpy;
+ Display *dpy;
/**
* The \c majorOpcode is common to all connections to the same server.
* It is also copied into the context structure.
*/
- int majorOpcode;
+ int majorOpcode;
/**
* \name Server Version
*
* Major and minor version returned by the server during initialization.
*/
- /*@{*/
- int majorVersion, minorVersion;
- /*@}*/
+ /*@{ */
+ int majorVersion, minorVersion;
+ /*@} */
/**
* \name Storage for the servers GLX vendor and versions strings.
- *
+ *
* These are the same for all screens on this display. These fields will
* be filled in on demand.
*/
- /*@{*/
- const char *serverGLXvendor;
- const char *serverGLXversion;
- /*@}*/
+ /*@{ */
+ const char *serverGLXvendor;
+ const char *serverGLXversion;
+ /*@} */
/**
* Configurations of visuals for all screens on this display.
* Also, per screen data which now includes the server \c GLX_EXTENSION
* string.
*/
- __GLXscreenConfigs *screenConfigs;
+ __GLXscreenConfigs *screenConfigs;
#ifdef GLX_DIRECT_RENDERING
/**
* Per display direct rendering interface functions and data.
*/
- __GLXDRIdisplay *driswDisplay;
- __GLXDRIdisplay *driDisplay;
- __GLXDRIdisplay *dri2Display;
+ __GLXDRIdisplay *driswDisplay;
+ __GLXDRIdisplay *driDisplay;
+ __GLXDRIdisplay *dri2Display;
#endif
};
-extern GLubyte *__glXFlushRenderBuffer(__GLXcontext*, GLubyte*);
+extern GLubyte *__glXFlushRenderBuffer(__GLXcontext *, GLubyte *);
-extern void __glXSendLargeChunk(__GLXcontext *gc, GLint requestNumber,
- GLint totalRequests,
- const GLvoid * data, GLint dataLen);
+extern void __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber,
+ GLint totalRequests,
+ const GLvoid * data, GLint dataLen);
extern void __glXSendLargeCommand(__GLXcontext *, const GLvoid *, GLint,
- const GLvoid *, GLint);
+ const GLvoid *, GLint);
/* Initialize the GLX extension for dpy */
-extern __GLXdisplayPrivate *__glXInitialize(Display*);
+extern __GLXdisplayPrivate *__glXInitialize(Display *);
+
+extern void __glXPreferEGL(int state);
/************************************************************************/
extern int __glXDebug;
/* This is per-thread storage in an MT environment */
-#if defined( USE_XTHREADS ) || defined( PTHREADS )
+#if defined( PTHREADS )
-extern void __glXSetCurrentContext(__GLXcontext *c);
+extern void __glXSetCurrentContext(__GLXcontext * c);
# if defined( GLX_USE_TLS )
-extern __thread void * __glX_tls_Context
- __attribute__((tls_model("initial-exec")));
+extern __thread void *__glX_tls_Context
+ __attribute__ ((tls_model("initial-exec")));
-# define __glXGetCurrentContext() __glX_tls_Context
+# define __glXGetCurrentContext() __glX_tls_Context
# else
@@ -629,25 +652,21 @@ extern __GLXcontext *__glXGetCurrentContext(void);
#else
extern __GLXcontext *__glXcurrentContext;
-#define __glXGetCurrentContext() __glXcurrentContext
-#define __glXSetCurrentContext(gc) __glXcurrentContext = gc
+#define __glXGetCurrentContext() __glXcurrentContext
+#define __glXSetCurrentContext(gc) __glXcurrentContext = gc
-#endif /* defined( USE_XTHREADS ) || defined( PTHREADS ) */
+#endif /* defined( PTHREADS ) */
extern void __glXSetCurrentContextNull(void);
-extern void __glXFreeContext(__GLXcontext*);
+extern void __glXFreeContext(__GLXcontext *);
/*
** Global lock for all threads in this address space using the GLX
** extension
*/
-#if defined( USE_XTHREADS )
-extern xmutex_rec __glXmutex;
-#define __glXLock() xmutex_lock(&__glXmutex)
-#define __glXUnlock() xmutex_unlock(&__glXmutex)
-#elif defined( PTHREADS )
+#if defined( PTHREADS )
extern pthread_mutex_t __glXmutex;
#define __glXLock() pthread_mutex_lock(&__glXmutex)
#define __glXUnlock() pthread_mutex_unlock(&__glXmutex)
@@ -659,7 +678,7 @@ extern pthread_mutex_t __glXmutex;
/*
** Setup for a command. Initialize the extension for dpy if necessary.
*/
-extern CARD8 __glXSetupForCommand(Display *dpy);
+extern CARD8 __glXSetupForCommand(Display * dpy);
/************************************************************************/
@@ -670,9 +689,11 @@ extern CARD8 __glXSetupForCommand(Display *dpy);
extern const GLuint __glXDefaultPixelStore[9];
/* Send an image to the server using RenderLarge. */
-extern void __glXSendLargeImage(__GLXcontext *gc, GLint compsize, GLint dim,
- GLint width, GLint height, GLint depth, GLenum format, GLenum type,
- const GLvoid *src, GLubyte *pc, GLubyte *modes);
+extern void __glXSendLargeImage(__GLXcontext * gc, GLint compsize, GLint dim,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type,
+ const GLvoid * src, GLubyte * pc,
+ GLubyte * modes);
/* Return the size, in bytes, of some pixel data */
extern GLint __glImageSize(GLint, GLint, GLint, GLenum, GLenum, GLenum);
@@ -692,23 +713,23 @@ extern GLint __glBytesPerElement(GLenum type);
** updated to contain the modes needed by the server to decode the
** sent data.
*/
-extern void __glFillImage(__GLXcontext*, GLint, GLint, GLint, GLint, GLenum,
- GLenum, const GLvoid*, GLubyte*, GLubyte*);
+extern void __glFillImage(__GLXcontext *, GLint, GLint, GLint, GLint, GLenum,
+ GLenum, const GLvoid *, GLubyte *, GLubyte *);
/* Copy map data with a stride into a packed buffer */
extern void __glFillMap1f(GLint, GLint, GLint, const GLfloat *, GLubyte *);
extern void __glFillMap1d(GLint, GLint, GLint, const GLdouble *, GLubyte *);
extern void __glFillMap2f(GLint, GLint, GLint, GLint, GLint,
- const GLfloat *, GLfloat *);
+ const GLfloat *, GLfloat *);
extern void __glFillMap2d(GLint, GLint, GLint, GLint, GLint,
- const GLdouble *, GLdouble *);
+ const GLdouble *, GLdouble *);
/*
** Empty an image out of the reply buffer into the clients memory applying
** the pack modes to pack back into the clients requested format.
*/
-extern void __glEmptyImage(__GLXcontext*, GLint, GLint, GLint, GLint, GLenum,
- GLenum, const GLubyte *, GLvoid *);
+extern void __glEmptyImage(__GLXcontext *, GLint, GLint, GLint, GLint, GLenum,
+ GLenum, const GLubyte *, GLvoid *);
/*
@@ -721,7 +742,7 @@ extern void __glXFreeVertexArrayState(__GLXcontext *);
** Inform the Server of the major and minor numbers and of the client
** libraries extension string.
*/
-extern void __glXClientInfo ( Display *dpy, int opcode );
+extern void __glXClientInfo(Display * dpy, int opcode);
/************************************************************************/
@@ -729,20 +750,22 @@ extern void __glXClientInfo ( Display *dpy, int opcode );
** Declarations that should be in Xlib
*/
#ifdef __GL_USE_OUR_PROTOTYPES
-extern void _XFlush(Display*);
-extern Status _XReply(Display*, xReply*, int, Bool);
-extern void _XRead(Display*, void*, long);
-extern void _XSend(Display*, const void*, long);
+extern void _XFlush(Display *);
+extern Status _XReply(Display *, xReply *, int, Bool);
+extern void _XRead(Display *, void *, long);
+extern void _XSend(Display *, const void *, long);
#endif
-extern void __glXInitializeVisualConfigFromTags( __GLcontextModes *config,
- int count, const INT32 *bp, Bool tagged_only, Bool fbconfig_style_tags );
+extern void __glXInitializeVisualConfigFromTags(__GLcontextModes * config,
+ int count, const INT32 * bp,
+ Bool tagged_only,
+ Bool fbconfig_style_tags);
-extern char * __glXQueryServerString(Display* dpy, int opcode,
- CARD32 screen, CARD32 name);
-extern char * __glXGetString(Display* dpy, int opcode,
- CARD32 screen, CARD32 name);
+extern char *__glXQueryServerString(Display * dpy, int opcode,
+ CARD32 screen, CARD32 name);
+extern char *__glXGetString(Display * dpy, int opcode,
+ CARD32 screen, CARD32 name);
extern char *__glXstrdup(const char *str);
@@ -751,15 +774,16 @@ extern const char __glXGLClientVersion[];
extern const char __glXGLClientExtensions[];
/* Get the unadjusted system time */
-extern int __glXGetUST( int64_t * ust );
+extern int __glXGetUST(int64_t * ust);
extern GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
- int32_t * numerator, int32_t * denominator);
+ int32_t * numerator,
+ int32_t * denominator);
#ifdef GLX_DIRECT_RENDERING
GLboolean
-__driGetMscRateOML(__DRIdrawable *draw,
- int32_t *numerator, int32_t *denominator, void *private);
+__driGetMscRateOML(__DRIdrawable * draw,
+ int32_t * numerator, int32_t * denominator, void *private);
#endif
#endif /* !__GLX_client_h__ */
diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c
index c68b6ac4ef..ea55cc49ef 100644
--- a/src/glx/x11/glxcmds.c
+++ b/src/glx/x11/glxcmds.c
@@ -59,56 +59,59 @@ static const char __glXGLXClientVersion[] = "1.4";
#ifdef GLX_DIRECT_RENDERING
static Bool windowExistsFlag;
-static int windowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
+static int
+windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr)
{
- if (xerr->error_code == BadWindow) {
- windowExistsFlag = GL_FALSE;
- }
- return 0;
+ if (xerr->error_code == BadWindow) {
+ windowExistsFlag = GL_FALSE;
+ }
+ return 0;
}
/**
* Find drawables in the local hash that have been destroyed on the
* server.
- *
+ *
* \param dpy Display to destroy drawables for
* \param screen Screen number to destroy drawables for
*/
-static void GarbageCollectDRIDrawables(Display *dpy, __GLXscreenConfigs *sc)
-{
- XID draw;
- __GLXDRIdrawable *pdraw;
- XWindowAttributes xwa;
- int (*oldXErrorHandler)(Display *, XErrorEvent *);
-
- /* Set no-op error handler so Xlib doesn't bail out if the windows
- * has alreay been destroyed on the server. */
- XSync(dpy, GL_FALSE);
- oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
-
- if (__glxHashFirst(sc->drawHash, &draw, (void *)&pdraw) == 1) {
- do {
- windowExistsFlag = GL_TRUE;
- XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
- if (!windowExistsFlag) {
- /* Destroy the local drawable data, if the drawable no
- longer exists in the Xserver */
- (*pdraw->destroyDrawable)(pdraw);
- __glxHashDelete(sc->drawHash, draw);
- }
- } while (__glxHashNext(sc->drawHash, &draw, (void *)&pdraw) == 1);
- }
-
- XSync(dpy, GL_FALSE);
- XSetErrorHandler(oldXErrorHandler);
-}
-
-extern __GLXDRIdrawable *
-GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num);
+static void
+GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc)
+{
+ XID draw;
+ __GLXDRIdrawable *pdraw;
+ XWindowAttributes xwa;
+ int (*oldXErrorHandler) (Display *, XErrorEvent *);
+
+ /* Set no-op error handler so Xlib doesn't bail out if the windows
+ * has alreay been destroyed on the server. */
+ XSync(dpy, GL_FALSE);
+ oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
+
+ if (__glxHashFirst(sc->drawHash, &draw, (void *) &pdraw) == 1) {
+ do {
+ windowExistsFlag = GL_TRUE;
+ XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
+ if (!windowExistsFlag) {
+ /* Destroy the local drawable data, if the drawable no
+ longer exists in the Xserver */
+ (*pdraw->destroyDrawable) (pdraw);
+ __glxHashDelete(sc->drawHash, draw);
+ }
+ } while (__glxHashNext(sc->drawHash, &draw, (void *) &pdraw) == 1);
+ }
+
+ XSync(dpy, GL_FALSE);
+ XSetErrorHandler(oldXErrorHandler);
+}
+
+extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
+ GLXDrawable drawable,
+ int *const scrn_num);
/**
* Get the __DRIdrawable for the drawable associated with a GLXContext
- *
+ *
* \param dpy The display associated with \c drawable.
* \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved.
* \param scrn_num If non-NULL, the drawables screen is stored there
@@ -116,30 +119,30 @@ GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num);
* the drawable is not associated with a direct-rendering context.
*/
_X_HIDDEN __GLXDRIdrawable *
-GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num)
+GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable, int *const scrn_num)
{
- __GLXdisplayPrivate *priv = __glXInitialize(dpy);
- __GLXDRIdrawable *pdraw;
- const unsigned screen_count = ScreenCount(dpy);
- unsigned i;
- __GLXscreenConfigs *psc;
+ __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+ __GLXDRIdrawable *pdraw;
+ const unsigned screen_count = ScreenCount(dpy);
+ unsigned i;
+ __GLXscreenConfigs *psc;
- if (priv == NULL)
- return NULL;
-
- for (i = 0; i < screen_count; i++) {
- psc = &priv->screenConfigs[i];
- if (psc->drawHash == NULL)
- continue;
+ if (priv == NULL)
+ return NULL;
- if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) {
- if (scrn_num != NULL)
- *scrn_num = i;
- return pdraw;
- }
- }
+ for (i = 0; i < screen_count; i++) {
+ psc = &priv->screenConfigs[i];
+ if (psc->drawHash == NULL)
+ continue;
+
+ if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) {
+ if (scrn_num != NULL)
+ *scrn_num = i;
+ return pdraw;
+ }
+ }
- return NULL;
+ return NULL;
}
#endif
@@ -147,57 +150,59 @@ GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num)
/**
* Get the GLX per-screen data structure associated with a GLX context.
- *
+ *
* \param dpy Display for which the GLX per-screen information is to be
* retrieved.
* \param scrn Screen on \c dpy for which the GLX per-screen information is
* to be retrieved.
* \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
* specify a valid GLX screen, or NULL otherwise.
- *
+ *
* \todo Should this function validate that \c scrn is within the screen
* number range for \c dpy?
*/
static __GLXscreenConfigs *
-GetGLXScreenConfigs(Display *dpy, int scrn)
+GetGLXScreenConfigs(Display * dpy, int scrn)
{
- __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
+ __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
- return (priv->screenConfigs != NULL) ? &priv->screenConfigs[scrn] : NULL;
+ return (priv
+ && priv->screenConfigs !=
+ NULL) ? &priv->screenConfigs[scrn] : NULL;
}
static int
-GetGLXPrivScreenConfig( Display *dpy, int scrn, __GLXdisplayPrivate ** ppriv,
- __GLXscreenConfigs ** ppsc )
+GetGLXPrivScreenConfig(Display * dpy, int scrn, __GLXdisplayPrivate ** ppriv,
+ __GLXscreenConfigs ** ppsc)
{
- /* Initialize the extension, if needed . This has the added value
- * of initializing/allocating the display private
- */
-
- if ( dpy == NULL ) {
- return GLX_NO_EXTENSION;
- }
+ /* Initialize the extension, if needed . This has the added value
+ * of initializing/allocating the display private
+ */
- *ppriv = __glXInitialize(dpy);
- if ( *ppriv == NULL ) {
- return GLX_NO_EXTENSION;
- }
+ if (dpy == NULL) {
+ return GLX_NO_EXTENSION;
+ }
+
+ *ppriv = __glXInitialize(dpy);
+ if (*ppriv == NULL) {
+ return GLX_NO_EXTENSION;
+ }
- /* Check screen number to see if its valid */
- if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
- return GLX_BAD_SCREEN;
- }
+ /* Check screen number to see if its valid */
+ if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
+ return GLX_BAD_SCREEN;
+ }
- /* Check to see if the GL is supported on this screen */
- *ppsc = &((*ppriv)->screenConfigs[scrn]);
- if ( (*ppsc)->configs == NULL ) {
- /* No support for GL on this screen regardless of visual */
- return GLX_BAD_VISUAL;
- }
+ /* Check to see if the GL is supported on this screen */
+ *ppsc = &((*ppriv)->screenConfigs[scrn]);
+ if ((*ppsc)->configs == NULL) {
+ /* No support for GL on this screen regardless of visual */
+ return GLX_BAD_VISUAL;
+ }
- return Success;
+ return Success;
}
@@ -212,27 +217,26 @@ GetGLXPrivScreenConfig( Display *dpy, int scrn, __GLXdisplayPrivate ** ppriv,
* is returned.
*/
static __GLcontextModes *
-ValidateGLXFBConfig( Display * dpy, GLXFBConfig config )
-{
- __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
- const unsigned num_screens = ScreenCount(dpy);
- unsigned i;
- const __GLcontextModes * modes;
-
-
- if ( priv != NULL ) {
- for ( i = 0 ; i < num_screens ; i++ ) {
- for ( modes = priv->screenConfigs[i].configs
- ; modes != NULL
- ; modes = modes->next ) {
- if ( modes == (__GLcontextModes *) config ) {
- return (__GLcontextModes *) config;
- }
- }
- }
- }
+ValidateGLXFBConfig(Display * dpy, GLXFBConfig config)
+{
+ __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+ const unsigned num_screens = ScreenCount(dpy);
+ unsigned i;
+ const __GLcontextModes *modes;
+
+
+ if (priv != NULL) {
+ for (i = 0; i < num_screens; i++) {
+ for (modes = priv->screenConfigs[i].configs; modes != NULL;
+ modes = modes->next) {
+ if (modes == (__GLcontextModes *) config) {
+ return (__GLcontextModes *) config;
+ }
+ }
+ }
+ }
- return NULL;
+ return NULL;
}
@@ -241,459 +245,497 @@ ValidateGLXFBConfig( Display * dpy, GLXFBConfig config )
* later in the function for direct-rendering contexts. Direct-rendering
* contexts don't need to track client state, so they don't need that memory
* at all.
- *
+ *
* \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new
* function called \c __glXAllocateClientState that allocates the memory and
* does all the initialization (including the pixel pack / unpack).
*/
-static
-GLXContext AllocateGLXContext( Display *dpy )
-{
- GLXContext gc;
- int bufSize;
- CARD8 opcode;
- __GLXattribute *state;
-
- if (!dpy)
- return NULL;
-
- opcode = __glXSetupForCommand(dpy);
- if (!opcode) {
- return NULL;
- }
-
- /* Allocate our context record */
- gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));
- if (!gc) {
- /* Out of memory */
- return NULL;
- }
- memset(gc, 0, sizeof(struct __GLXcontextRec));
-
- state = Xmalloc(sizeof(struct __GLXattributeRec));
- if (state == NULL) {
- /* Out of memory */
- Xfree(gc);
- return NULL;
- }
- gc->client_state_private = state;
- memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));
- state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
-
- /*
+static GLXContext
+AllocateGLXContext(Display * dpy)
+{
+ GLXContext gc;
+ int bufSize;
+ CARD8 opcode;
+ __GLXattribute *state;
+
+ if (!dpy)
+ return NULL;
+
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode) {
+ return NULL;
+ }
+
+ /* Allocate our context record */
+ gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));
+ if (!gc) {
+ /* Out of memory */
+ return NULL;
+ }
+ memset(gc, 0, sizeof(struct __GLXcontextRec));
+
+ state = Xmalloc(sizeof(struct __GLXattributeRec));
+ if (state == NULL) {
+ /* Out of memory */
+ Xfree(gc);
+ return NULL;
+ }
+ gc->client_state_private = state;
+ memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));
+ state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
+
+ /*
** Create a temporary buffer to hold GLX rendering commands. The size
** of the buffer is selected so that the maximum number of GLX rendering
** commands can fit in a single X packet and still have room in the X
** packet for the GLXRenderReq header.
*/
- bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
- gc->buf = (GLubyte *) Xmalloc(bufSize);
- if (!gc->buf) {
- Xfree(gc->client_state_private);
- Xfree(gc);
- return NULL;
- }
- gc->bufSize = bufSize;
+ bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
+ gc->buf = (GLubyte *) Xmalloc(bufSize);
+ if (!gc->buf) {
+ Xfree(gc->client_state_private);
+ Xfree(gc);
+ return NULL;
+ }
+ gc->bufSize = bufSize;
- /* Fill in the new context */
- gc->renderMode = GL_RENDER;
+ /* Fill in the new context */
+ gc->renderMode = GL_RENDER;
- state->storePack.alignment = 4;
- state->storeUnpack.alignment = 4;
+ state->storePack.alignment = 4;
+ state->storeUnpack.alignment = 4;
- gc->attributes.stackPointer = &gc->attributes.stack[0];
+ gc->attributes.stackPointer = &gc->attributes.stack[0];
- /*
+ /*
** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
** Other code uses the fastImageUnpack bit, but it is never set
** to GL_TRUE.
*/
- gc->fastImageUnpack = GL_FALSE;
- gc->fillImage = __glFillImage;
- gc->pc = gc->buf;
- gc->bufEnd = gc->buf + bufSize;
- gc->isDirect = GL_FALSE;
- if (__glXDebug) {
- /*
- ** Set limit register so that there will be one command per packet
- */
- gc->limit = gc->buf;
- } else {
- gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
- }
- gc->createDpy = dpy;
- gc->majorOpcode = opcode;
-
- /*
+ gc->fastImageUnpack = GL_FALSE;
+ gc->fillImage = __glFillImage;
+ gc->pc = gc->buf;
+ gc->bufEnd = gc->buf + bufSize;
+ gc->isDirect = GL_FALSE;
+ if (__glXDebug) {
+ /*
+ ** Set limit register so that there will be one command per packet
+ */
+ gc->limit = gc->buf;
+ }
+ else {
+ gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
+ }
+ gc->createDpy = dpy;
+ gc->majorOpcode = opcode;
+
+ /*
** Constrain the maximum drawing command size allowed to be
** transfered using the X_GLXRender protocol request. First
** constrain by a software limit, then constrain by the protocl
** limit.
*/
- if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
- bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
- }
- if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
- bufSize = __GLX_MAX_RENDER_CMD_SIZE;
- }
- gc->maxSmallRenderCommandSize = bufSize;
- return gc;
+ if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
+ bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
+ }
+ if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
+ bufSize = __GLX_MAX_RENDER_CMD_SIZE;
+ }
+ gc->maxSmallRenderCommandSize = bufSize;
+ return gc;
}
/**
* Create a new context. Exactly one of \c vis and \c fbconfig should be
* non-NULL.
- *
+ *
* \param use_glx_1_3 For FBConfigs, should GLX 1.3 protocol or
* SGIX_fbconfig protocol be used?
* \param renderType For FBConfigs, what is the rendering type?
*/
static GLXContext
-CreateContext(Display *dpy, XVisualInfo *vis,
- const __GLcontextModes * const fbconfig,
- GLXContext shareList,
- Bool allowDirect, GLXContextID contextID,
- Bool use_glx_1_3, int renderType)
+CreateContext(Display * dpy, XVisualInfo * vis,
+ const __GLcontextModes * const fbconfig,
+ GLXContext shareList,
+ Bool allowDirect, GLXContextID contextID,
+ Bool use_glx_1_3, int renderType)
{
- GLXContext gc;
+ GLXContext gc;
#ifdef GLX_DIRECT_RENDERING
- int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen;
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
+ int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen;
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
#endif
- if ( dpy == NULL )
- return NULL;
+ if (dpy == NULL)
+ return NULL;
- gc = AllocateGLXContext(dpy);
- if (!gc)
- return NULL;
+ gc = AllocateGLXContext(dpy);
+ if (!gc)
+ return NULL;
- if (None == contextID) {
- if ( (vis == NULL) && (fbconfig == NULL) )
- return NULL;
+ if (None == contextID) {
+ if ((vis == NULL) && (fbconfig == NULL))
+ return NULL;
#ifdef GLX_DIRECT_RENDERING
- if (allowDirect && psc->driScreen) {
- const __GLcontextModes * mode;
-
- if (fbconfig == NULL) {
- mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
- if (mode == NULL) {
- xError error;
-
- error.errorCode = BadValue;
- error.resourceID = vis->visualid;
- error.sequenceNumber = dpy->request;
- error.type = X_Error;
- error.majorCode = gc->majorOpcode;
- error.minorCode = X_GLXCreateContext;
- _XError(dpy, &error);
- return None;
- }
- }
- else {
- mode = fbconfig;
- }
-
- gc->driContext = psc->driScreen->createContext(psc, mode, gc,
- shareList,
- renderType);
- if (gc->driContext != NULL) {
- gc->screen = mode->screen;
- gc->psc = psc;
- gc->mode = mode;
- gc->isDirect = GL_TRUE;
- }
- }
+ if (allowDirect && psc->driScreen) {
+ const __GLcontextModes *mode;
+
+ if (fbconfig == NULL) {
+ mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
+ if (mode == NULL) {
+ xError error;
+
+ error.errorCode = BadValue;
+ error.resourceID = vis->visualid;
+ error.sequenceNumber = dpy->request;
+ error.type = X_Error;
+ error.majorCode = gc->majorOpcode;
+ error.minorCode = X_GLXCreateContext;
+ _XError(dpy, &error);
+ return None;
+ }
+ }
+ else {
+ mode = fbconfig;
+ }
+
+ gc->driContext = psc->driScreen->createContext(psc, mode, gc,
+ shareList,
+ renderType);
+ if (gc->driContext != NULL) {
+ gc->screen = mode->screen;
+ gc->psc = psc;
+ gc->mode = mode;
+ gc->isDirect = GL_TRUE;
+ }
+ }
#endif
- LockDisplay(dpy);
- if ( fbconfig == NULL ) {
- xGLXCreateContextReq *req;
-
- /* Send the glXCreateContext request */
- GetReq(GLXCreateContext,req);
- req->reqType = gc->majorOpcode;
- req->glxCode = X_GLXCreateContext;
- req->context = gc->xid = XAllocID(dpy);
- req->visual = vis->visualid;
- req->screen = vis->screen;
- req->shareList = shareList ? shareList->xid : None;
+ LockDisplay(dpy);
+ if (fbconfig == NULL) {
+ xGLXCreateContextReq *req;
+
+ /* Send the glXCreateContext request */
+ GetReq(GLXCreateContext, req);
+ req->reqType = gc->majorOpcode;
+ req->glxCode = X_GLXCreateContext;
+ req->context = gc->xid = XAllocID(dpy);
+ req->visual = vis->visualid;
+ req->screen = vis->screen;
+ req->shareList = shareList ? shareList->xid : None;
#ifdef GLX_DIRECT_RENDERING
- req->isDirect = gc->driContext != NULL;
+ req->isDirect = gc->driContext != NULL;
#else
- req->isDirect = 0;
+ req->isDirect = 0;
#endif
- }
- else if ( use_glx_1_3 ) {
- xGLXCreateNewContextReq *req;
-
- /* Send the glXCreateNewContext request */
- GetReq(GLXCreateNewContext,req);
- req->reqType = gc->majorOpcode;
- req->glxCode = X_GLXCreateNewContext;
- req->context = gc->xid = XAllocID(dpy);
- req->fbconfig = fbconfig->fbconfigID;
- req->screen = fbconfig->screen;
- req->renderType = renderType;
- req->shareList = shareList ? shareList->xid : None;
+ }
+ else if (use_glx_1_3) {
+ xGLXCreateNewContextReq *req;
+
+ /* Send the glXCreateNewContext request */
+ GetReq(GLXCreateNewContext, req);
+ req->reqType = gc->majorOpcode;
+ req->glxCode = X_GLXCreateNewContext;
+ req->context = gc->xid = XAllocID(dpy);
+ req->fbconfig = fbconfig->fbconfigID;
+ req->screen = fbconfig->screen;
+ req->renderType = renderType;
+ req->shareList = shareList ? shareList->xid : None;
#ifdef GLX_DIRECT_RENDERING
- req->isDirect = gc->driContext != NULL;
+ req->isDirect = gc->driContext != NULL;
#else
- req->isDirect = 0;
+ req->isDirect = 0;
#endif
- }
- else {
- xGLXVendorPrivateWithReplyReq *vpreq;
- xGLXCreateContextWithConfigSGIXReq *req;
-
- /* Send the glXCreateNewContext request */
- GetReqExtra(GLXVendorPrivateWithReply,
- sz_xGLXCreateContextWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
- req = (xGLXCreateContextWithConfigSGIXReq *)vpreq;
- req->reqType = gc->majorOpcode;
- req->glxCode = X_GLXVendorPrivateWithReply;
- req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
- req->context = gc->xid = XAllocID(dpy);
- req->fbconfig = fbconfig->fbconfigID;
- req->screen = fbconfig->screen;
- req->renderType = renderType;
- req->shareList = shareList ? shareList->xid : None;
+ }
+ else {
+ xGLXVendorPrivateWithReplyReq *vpreq;
+ xGLXCreateContextWithConfigSGIXReq *req;
+
+ /* Send the glXCreateNewContext request */
+ GetReqExtra(GLXVendorPrivateWithReply,
+ sz_xGLXCreateContextWithConfigSGIXReq -
+ sz_xGLXVendorPrivateWithReplyReq, vpreq);
+ req = (xGLXCreateContextWithConfigSGIXReq *) vpreq;
+ req->reqType = gc->majorOpcode;
+ req->glxCode = X_GLXVendorPrivateWithReply;
+ req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
+ req->context = gc->xid = XAllocID(dpy);
+ req->fbconfig = fbconfig->fbconfigID;
+ req->screen = fbconfig->screen;
+ req->renderType = renderType;
+ req->shareList = shareList ? shareList->xid : None;
#ifdef GLX_DIRECT_RENDERING
- req->isDirect = gc->driContext != NULL;
+ req->isDirect = gc->driContext != NULL;
#else
- req->isDirect = 0;
+ req->isDirect = 0;
#endif
- }
+ }
- UnlockDisplay(dpy);
- SyncHandle();
- gc->imported = GL_FALSE;
- }
- else {
- gc->xid = contextID;
- gc->imported = GL_TRUE;
- }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ gc->imported = GL_FALSE;
+ }
+ else {
+ gc->xid = contextID;
+ gc->imported = GL_TRUE;
+ }
- return gc;
+ return gc;
}
-PUBLIC GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis,
- GLXContext shareList, Bool allowDirect)
+PUBLIC GLXContext
+glXCreateContext(Display * dpy, XVisualInfo * vis,
+ GLXContext shareList, Bool allowDirect)
{
return CreateContext(dpy, vis, NULL, shareList, allowDirect, None,
- False, 0);
+ False, 0);
}
-_X_HIDDEN void __glXFreeContext(__GLXcontext *gc)
+_X_HIDDEN void
+__glXFreeContext(__GLXcontext * gc)
{
- if (gc->vendor) XFree((char *) gc->vendor);
- if (gc->renderer) XFree((char *) gc->renderer);
- if (gc->version) XFree((char *) gc->version);
- if (gc->extensions) XFree((char *) gc->extensions);
- __glFreeAttributeState(gc);
- XFree((char *) gc->buf);
- Xfree((char *) gc->client_state_private);
- XFree((char *) gc);
-
+ if (gc->vendor)
+ XFree((char *) gc->vendor);
+ if (gc->renderer)
+ XFree((char *) gc->renderer);
+ if (gc->version)
+ XFree((char *) gc->version);
+ if (gc->extensions)
+ XFree((char *) gc->extensions);
+ __glFreeAttributeState(gc);
+ XFree((char *) gc->buf);
+ Xfree((char *) gc->client_state_private);
+ XFree((char *) gc);
+
}
/*
** Destroy the named context
*/
-static void
-DestroyContext(Display *dpy, GLXContext gc)
+static void
+DestroyContext(Display * dpy, GLXContext gc)
{
- xGLXDestroyContextReq *req;
- GLXContextID xid;
- CARD8 opcode;
- GLboolean imported;
+ xGLXDestroyContextReq *req;
+ GLXContextID xid;
+ CARD8 opcode;
+ GLboolean imported;
- opcode = __glXSetupForCommand(dpy);
- if (!opcode || !gc) {
- return;
- }
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode || !gc) {
+ return;
+ }
- __glXLock();
- xid = gc->xid;
- imported = gc->imported;
- gc->xid = None;
+ __glXLock();
+ xid = gc->xid;
+ imported = gc->imported;
+ gc->xid = None;
#ifdef GLX_DIRECT_RENDERING
- /* Destroy the direct rendering context */
- if (gc->driContext) {
- (*gc->driContext->destroyContext)(gc->driContext, gc->psc, dpy);
- gc->driContext = NULL;
- GarbageCollectDRIDrawables(dpy, gc->psc);
- }
+ /* Destroy the direct rendering context */
+ if (gc->driContext) {
+ (*gc->driContext->destroyContext) (gc->driContext, gc->psc, dpy);
+ gc->driContext = NULL;
+ GarbageCollectDRIDrawables(dpy, gc->psc);
+ }
#endif
- __glXFreeVertexArrayState(gc);
+ __glXFreeVertexArrayState(gc);
- if (gc->currentDpy) {
- /* Have to free later cuz it's in use now */
- __glXUnlock();
- } else {
- /* Destroy the handle if not current to anybody */
- __glXUnlock();
- __glXFreeContext(gc);
- }
+ if (gc->currentDpy) {
+ /* Have to free later cuz it's in use now */
+ __glXUnlock();
+ }
+ else {
+ /* Destroy the handle if not current to anybody */
+ __glXUnlock();
+ __glXFreeContext(gc);
+ }
- if (!imported) {
- /*
- ** This dpy also created the server side part of the context.
- ** Send the glXDestroyContext request.
- */
- LockDisplay(dpy);
- GetReq(GLXDestroyContext,req);
- req->reqType = opcode;
- req->glxCode = X_GLXDestroyContext;
- req->context = xid;
- UnlockDisplay(dpy);
- SyncHandle();
- }
+ if (!imported) {
+ /*
+ ** This dpy also created the server side part of the context.
+ ** Send the glXDestroyContext request.
+ */
+ LockDisplay(dpy);
+ GetReq(GLXDestroyContext, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXDestroyContext;
+ req->context = xid;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ }
}
-PUBLIC void glXDestroyContext(Display *dpy, GLXContext gc)
+PUBLIC void
+glXDestroyContext(Display * dpy, GLXContext gc)
{
- DestroyContext(dpy, gc);
+ DestroyContext(dpy, gc);
}
/*
** Return the major and minor version #s for the GLX extension
*/
-PUBLIC Bool glXQueryVersion(Display *dpy, int *major, int *minor)
+PUBLIC Bool
+glXQueryVersion(Display * dpy, int *major, int *minor)
{
- __GLXdisplayPrivate *priv;
+ __GLXdisplayPrivate *priv;
- /* Init the extension. This fetches the major and minor version. */
- priv = __glXInitialize(dpy);
- if (!priv) return GL_FALSE;
+ /* Init the extension. This fetches the major and minor version. */
+ priv = __glXInitialize(dpy);
+ if (!priv)
+ return GL_FALSE;
- if (major) *major = priv->majorVersion;
- if (minor) *minor = priv->minorVersion;
- return GL_TRUE;
+ if (major)
+ *major = priv->majorVersion;
+ if (minor)
+ *minor = priv->minorVersion;
+ return GL_TRUE;
}
/*
** Query the existance of the GLX extension
*/
-PUBLIC Bool glXQueryExtension(Display *dpy, int *errorBase, int *eventBase)
-{
- int major_op, erb, evb;
- Bool rv;
-
- rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
- if (rv) {
- if (errorBase) *errorBase = erb;
- if (eventBase) *eventBase = evb;
- }
- return rv;
+PUBLIC Bool
+glXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
+{
+ int major_op, erb, evb;
+ Bool rv;
+
+ rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
+ if (rv) {
+ if (errorBase)
+ *errorBase = erb;
+ if (eventBase)
+ *eventBase = evb;
+ }
+ return rv;
}
/*
** Put a barrier in the token stream that forces the GL to finish its
** work before X can proceed.
*/
-PUBLIC void glXWaitGL(void)
+PUBLIC void
+glXWaitGL(void)
{
- xGLXWaitGLReq *req;
- GLXContext gc = __glXGetCurrentContext();
- Display *dpy = gc->currentDpy;
+ xGLXWaitGLReq *req;
+ GLXContext gc = __glXGetCurrentContext();
+ Display *dpy = gc->currentDpy;
- if (!dpy) return;
+ if (!dpy)
+ return;
- /* Flush any pending commands out */
- __glXFlushRenderBuffer(gc, gc->pc);
+ /* Flush any pending commands out */
+ __glXFlushRenderBuffer(gc, gc->pc);
#ifdef GLX_DIRECT_RENDERING
- if (gc->driContext) {
-/* This bit of ugliness unwraps the glFinish function */
-#ifdef glFinish
-#undef glFinish
-#endif
- glFinish();
- return;
- }
+ if (gc->driContext) {
+ int screen;
+ __GLXDRIdrawable *pdraw =
+ GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen);
+
+ if (pdraw != NULL) {
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+ glFlush();
+ if (psc->driScreen->waitGL != NULL)
+ (*psc->driScreen->waitGL) (pdraw);
+ }
+ return;
+ }
#endif
- /* Send the glXWaitGL request */
- LockDisplay(dpy);
- GetReq(GLXWaitGL,req);
- req->reqType = gc->majorOpcode;
- req->glxCode = X_GLXWaitGL;
- req->contextTag = gc->currentContextTag;
- UnlockDisplay(dpy);
- SyncHandle();
+ /* Send the glXWaitGL request */
+ LockDisplay(dpy);
+ GetReq(GLXWaitGL, req);
+ req->reqType = gc->majorOpcode;
+ req->glxCode = X_GLXWaitGL;
+ req->contextTag = gc->currentContextTag;
+ UnlockDisplay(dpy);
+ SyncHandle();
}
/*
** Put a barrier in the token stream that forces X to finish its
** work before GL can proceed.
*/
-PUBLIC void glXWaitX(void)
+PUBLIC void
+glXWaitX(void)
{
- xGLXWaitXReq *req;
- GLXContext gc = __glXGetCurrentContext();
- Display *dpy = gc->currentDpy;
+ xGLXWaitXReq *req;
+ GLXContext gc = __glXGetCurrentContext();
+ Display *dpy = gc->currentDpy;
- if (!dpy) return;
+ if (!dpy)
+ return;
- /* Flush any pending commands out */
- __glXFlushRenderBuffer(gc, gc->pc);
+ /* Flush any pending commands out */
+ __glXFlushRenderBuffer(gc, gc->pc);
#ifdef GLX_DIRECT_RENDERING
- if (gc->driContext) {
- XSync(dpy, False);
- return;
- }
+ if (gc->driContext) {
+ int screen;
+ __GLXDRIdrawable *pdraw =
+ GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen);
+
+ if (pdraw != NULL) {
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+ if (psc->driScreen->waitX != NULL)
+ (*psc->driScreen->waitX) (pdraw);
+ }
+ else
+ XSync(dpy, False);
+ return;
+ }
#endif
- /*
+ /*
** Send the glXWaitX request.
*/
- LockDisplay(dpy);
- GetReq(GLXWaitX,req);
- req->reqType = gc->majorOpcode;
- req->glxCode = X_GLXWaitX;
- req->contextTag = gc->currentContextTag;
- UnlockDisplay(dpy);
- SyncHandle();
+ LockDisplay(dpy);
+ GetReq(GLXWaitX, req);
+ req->reqType = gc->majorOpcode;
+ req->glxCode = X_GLXWaitX;
+ req->contextTag = gc->currentContextTag;
+ UnlockDisplay(dpy);
+ SyncHandle();
}
-PUBLIC void glXUseXFont(Font font, int first, int count, int listBase)
+PUBLIC void
+glXUseXFont(Font font, int first, int count, int listBase)
{
- xGLXUseXFontReq *req;
- GLXContext gc = __glXGetCurrentContext();
- Display *dpy = gc->currentDpy;
+ xGLXUseXFontReq *req;
+ GLXContext gc = __glXGetCurrentContext();
+ Display *dpy = gc->currentDpy;
- if (!dpy) return;
+ if (!dpy)
+ return;
- /* Flush any pending commands out */
- (void) __glXFlushRenderBuffer(gc, gc->pc);
+ /* Flush any pending commands out */
+ (void) __glXFlushRenderBuffer(gc, gc->pc);
#ifdef GLX_DIRECT_RENDERING
- if (gc->driContext) {
+ if (gc->driContext) {
DRI_glXUseXFont(font, first, count, listBase);
return;
- }
+ }
#endif
- /* Send the glXUseFont request */
- LockDisplay(dpy);
- GetReq(GLXUseXFont,req);
- req->reqType = gc->majorOpcode;
- req->glxCode = X_GLXUseXFont;
- req->contextTag = gc->currentContextTag;
- req->font = font;
- req->first = first;
- req->count = count;
- req->listBase = listBase;
- UnlockDisplay(dpy);
- SyncHandle();
+ /* Send the glXUseFont request */
+ LockDisplay(dpy);
+ GetReq(GLXUseXFont, req);
+ req->reqType = gc->majorOpcode;
+ req->glxCode = X_GLXUseXFont;
+ req->contextTag = gc->currentContextTag;
+ req->font = font;
+ req->first = first;
+ req->count = count;
+ req->listBase = listBase;
+ UnlockDisplay(dpy);
+ SyncHandle();
}
/************************************************************************/
@@ -702,46 +744,48 @@ PUBLIC void glXUseXFont(Font font, int first, int count, int listBase)
** Copy the source context to the destination context using the
** attribute "mask".
*/
-PUBLIC void glXCopyContext(Display *dpy, GLXContext source,
- GLXContext dest, unsigned long mask)
+PUBLIC void
+glXCopyContext(Display * dpy, GLXContext source,
+ GLXContext dest, unsigned long mask)
{
- xGLXCopyContextReq *req;
- GLXContext gc = __glXGetCurrentContext();
- GLXContextTag tag;
- CARD8 opcode;
+ xGLXCopyContextReq *req;
+ GLXContext gc = __glXGetCurrentContext();
+ GLXContextTag tag;
+ CARD8 opcode;
- opcode = __glXSetupForCommand(dpy);
- if (!opcode) {
- return;
- }
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode) {
+ return;
+ }
#ifdef GLX_DIRECT_RENDERING
- if (gc->driContext) {
- /* NOT_DONE: This does not work yet */
- }
+ if (gc->driContext) {
+ /* NOT_DONE: This does not work yet */
+ }
#endif
- /*
+ /*
** If the source is the current context, send its tag so that the context
** can be flushed before the copy.
*/
- if (source == gc && dpy == gc->currentDpy) {
- tag = gc->currentContextTag;
- } else {
- tag = 0;
- }
-
- /* Send the glXCopyContext request */
- LockDisplay(dpy);
- GetReq(GLXCopyContext,req);
- req->reqType = opcode;
- req->glxCode = X_GLXCopyContext;
- req->source = source ? source->xid : None;
- req->dest = dest ? dest->xid : None;
- req->mask = mask;
- req->contextTag = tag;
- UnlockDisplay(dpy);
- SyncHandle();
+ if (source == gc && dpy == gc->currentDpy) {
+ tag = gc->currentContextTag;
+ }
+ else {
+ tag = 0;
+ }
+
+ /* Send the glXCopyContext request */
+ LockDisplay(dpy);
+ GetReq(GLXCopyContext, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXCopyContext;
+ req->source = source ? source->xid : None;
+ req->dest = dest ? dest->xid : None;
+ req->mask = mask;
+ req->contextTag = tag;
+ UnlockDisplay(dpy);
+ SyncHandle();
}
@@ -753,42 +797,43 @@ PUBLIC void glXCopyContext(Display *dpy, GLXContext source,
*
* \returns \c GL_TRUE if the context is direct rendering or not.
*/
-static Bool __glXIsDirect(Display *dpy, GLXContextID contextID)
+static Bool
+__glXIsDirect(Display * dpy, GLXContextID contextID)
{
#if !defined(USE_XCB)
- xGLXIsDirectReq *req;
- xGLXIsDirectReply reply;
+ xGLXIsDirectReq *req;
+ xGLXIsDirectReply reply;
#endif
- CARD8 opcode;
+ CARD8 opcode;
- opcode = __glXSetupForCommand(dpy);
- if (!opcode) {
- return GL_FALSE;
- }
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode) {
+ return GL_FALSE;
+ }
#ifdef USE_XCB
- xcb_connection_t* c = XGetXCBConnection(dpy);
- xcb_glx_is_direct_reply_t* reply =
- xcb_glx_is_direct_reply(c,
- xcb_glx_is_direct(c, contextID),
- NULL);
+ xcb_connection_t *c = XGetXCBConnection(dpy);
+ xcb_glx_is_direct_reply_t *reply = xcb_glx_is_direct_reply(c,
+ xcb_glx_is_direct
+ (c, contextID),
+ NULL);
const Bool is_direct = reply->is_direct ? True : False;
free(reply);
return is_direct;
#else
- /* Send the glXIsDirect request */
- LockDisplay(dpy);
- GetReq(GLXIsDirect,req);
- req->reqType = opcode;
- req->glxCode = X_GLXIsDirect;
- req->context = contextID;
- _XReply(dpy, (xReply*) &reply, 0, False);
- UnlockDisplay(dpy);
- SyncHandle();
-
- return reply.isDirect;
+ /* Send the glXIsDirect request */
+ LockDisplay(dpy);
+ GetReq(GLXIsDirect, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXIsDirect;
+ req->context = contextID;
+ _XReply(dpy, (xReply *) & reply, 0, False);
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return reply.isDirect;
#endif /* USE_XCB */
}
@@ -798,120 +843,168 @@ static Bool __glXIsDirect(Display *dpy, GLXContextID contextID)
* \c GLX_DIRECT_RENDERING is not defined? Do we really need to bother with
* the GLX protocol here at all?
*/
-PUBLIC Bool glXIsDirect(Display *dpy, GLXContext gc)
+PUBLIC Bool
+glXIsDirect(Display * dpy, GLXContext gc)
{
- if (!gc) {
- return GL_FALSE;
+ if (!gc) {
+ return GL_FALSE;
#ifdef GLX_DIRECT_RENDERING
- } else if (gc->driContext) {
- return GL_TRUE;
+ }
+ else if (gc->driContext) {
+ return GL_TRUE;
#endif
- }
- return __glXIsDirect(dpy, gc->xid);
+ }
+ return __glXIsDirect(dpy, gc->xid);
}
-PUBLIC GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *vis,
- Pixmap pixmap)
+PUBLIC GLXPixmap
+glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
{
- xGLXCreateGLXPixmapReq *req;
- GLXPixmap xid;
- CARD8 opcode;
+ xGLXCreateGLXPixmapReq *req;
+ GLXPixmap xid;
+ CARD8 opcode;
- opcode = __glXSetupForCommand(dpy);
- if (!opcode) {
- return None;
- }
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode) {
+ return None;
+ }
+
+ /* Send the glXCreateGLXPixmap request */
+ LockDisplay(dpy);
+ GetReq(GLXCreateGLXPixmap, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXCreateGLXPixmap;
+ req->screen = vis->screen;
+ req->visual = vis->visualid;
+ req->pixmap = pixmap;
+ req->glxpixmap = xid = XAllocID(dpy);
+ UnlockDisplay(dpy);
+ SyncHandle();
- /* Send the glXCreateGLXPixmap request */
- LockDisplay(dpy);
- GetReq(GLXCreateGLXPixmap,req);
- req->reqType = opcode;
- req->glxCode = X_GLXCreateGLXPixmap;
- req->screen = vis->screen;
- req->visual = vis->visualid;
- req->pixmap = pixmap;
- req->glxpixmap = xid = XAllocID(dpy);
- UnlockDisplay(dpy);
- SyncHandle();
- return xid;
+#ifdef GLX_DIRECT_RENDERING
+ do {
+ /* FIXME: Maybe delay __DRIdrawable creation until the drawable
+ * is actually bound to a context... */
+
+ __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+ __GLXDRIdrawable *pdraw;
+ __GLXscreenConfigs *psc;
+ __GLcontextModes *modes;
+
+ psc = &priv->screenConfigs[vis->screen];
+ if (psc->driScreen == NULL)
+ break;
+ modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
+ pdraw = psc->driScreen->createDrawable(psc, pixmap, req->glxpixmap, modes);
+ if (pdraw == NULL) {
+ fprintf(stderr, "failed to create pixmap\n");
+ break;
+ }
+
+ if (__glxHashInsert(psc->drawHash, req->glxpixmap, pdraw)) {
+ (*pdraw->destroyDrawable) (pdraw);
+ return None; /* FIXME: Check what we're supposed to do here... */
+ }
+ } while (0);
+#endif
+
+ return xid;
}
/*
** Destroy the named pixmap
*/
-PUBLIC void glXDestroyGLXPixmap(Display *dpy, GLXPixmap glxpixmap)
-{
- xGLXDestroyGLXPixmapReq *req;
- CARD8 opcode;
-
- opcode = __glXSetupForCommand(dpy);
- if (!opcode) {
- return;
- }
-
- /* Send the glXDestroyGLXPixmap request */
- LockDisplay(dpy);
- GetReq(GLXDestroyGLXPixmap,req);
- req->reqType = opcode;
- req->glxCode = X_GLXDestroyGLXPixmap;
- req->glxpixmap = glxpixmap;
- UnlockDisplay(dpy);
- SyncHandle();
-}
-
-PUBLIC void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
-{
- GLXContext gc;
- GLXContextTag tag;
- CARD8 opcode;
+PUBLIC void
+glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
+{
+ xGLXDestroyGLXPixmapReq *req;
+ CARD8 opcode;
+
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode) {
+ return;
+ }
+
+ /* Send the glXDestroyGLXPixmap request */
+ LockDisplay(dpy);
+ GetReq(GLXDestroyGLXPixmap, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXDestroyGLXPixmap;
+ req->glxpixmap = glxpixmap;
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+#ifdef GLX_DIRECT_RENDERING
+ {
+ int screen;
+ __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap, &screen);
+ __GLXscreenConfigs *psc = &priv->screenConfigs[screen];
+
+ if (pdraw != NULL) {
+ (*pdraw->destroyDrawable) (pdraw);
+ __glxHashDelete(psc->drawHash, glxpixmap);
+ }
+ }
+#endif
+}
+
+PUBLIC void
+glXSwapBuffers(Display * dpy, GLXDrawable drawable)
+{
+ GLXContext gc;
+ GLXContextTag tag;
+ CARD8 opcode;
#ifdef USE_XCB
- xcb_connection_t *c;
+ xcb_connection_t *c;
#else
- xGLXSwapBuffersReq *req;
+ xGLXSwapBuffersReq *req;
#endif
#ifdef GLX_DIRECT_RENDERING
- __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
- if (pdraw != NULL) {
- glFlush();
- (*pdraw->psc->driScreen->swapBuffers)(pdraw);
- return;
- }
+ if (pdraw != NULL) {
+ glFlush();
+ (*pdraw->psc->driScreen->swapBuffers) (pdraw);
+ return;
+ }
#endif
- opcode = __glXSetupForCommand(dpy);
- if (!opcode) {
- return;
- }
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode) {
+ return;
+ }
- /*
+ /*
** The calling thread may or may not have a current context. If it
** does, send the context tag so the server can do a flush.
*/
- gc = __glXGetCurrentContext();
- if ((gc != NULL) && (dpy == gc->currentDpy) &&
- ((drawable == gc->currentDrawable) || (drawable == gc->currentReadable)) ) {
- tag = gc->currentContextTag;
- } else {
- tag = 0;
- }
+ gc = __glXGetCurrentContext();
+ if ((gc != NULL) && (dpy == gc->currentDpy) &&
+ ((drawable == gc->currentDrawable)
+ || (drawable == gc->currentReadable))) {
+ tag = gc->currentContextTag;
+ }
+ else {
+ tag = 0;
+ }
#ifdef USE_XCB
- c = XGetXCBConnection(dpy);
- xcb_glx_swap_buffers(c, tag, drawable);
- xcb_flush(c);
+ c = XGetXCBConnection(dpy);
+ xcb_glx_swap_buffers(c, tag, drawable);
+ xcb_flush(c);
#else
- /* Send the glXSwapBuffers request */
- LockDisplay(dpy);
- GetReq(GLXSwapBuffers,req);
- req->reqType = opcode;
- req->glxCode = X_GLXSwapBuffers;
- req->drawable = drawable;
- req->contextTag = tag;
- UnlockDisplay(dpy);
- SyncHandle();
- XFlush(dpy);
+ /* Send the glXSwapBuffers request */
+ LockDisplay(dpy);
+ GetReq(GLXSwapBuffers, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXSwapBuffers;
+ req->drawable = drawable;
+ req->contextTag = tag;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ XFlush(dpy);
#endif /* USE_XCB */
}
@@ -920,94 +1013,96 @@ PUBLIC void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
** Return configuration information for the given display, screen and
** visual combination.
*/
-PUBLIC int glXGetConfig(Display *dpy, XVisualInfo *vis, int attribute,
- int *value_return)
-{
- __GLXdisplayPrivate *priv;
- __GLXscreenConfigs *psc;
- __GLcontextModes *modes;
- int status;
-
- status = GetGLXPrivScreenConfig( dpy, vis->screen, & priv, & psc );
- if ( status == Success ) {
- modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
-
- /* Lookup attribute after first finding a match on the visual */
- if ( modes != NULL ) {
- return _gl_get_context_mode_data( modes, attribute, value_return );
- }
-
- status = GLX_BAD_VISUAL;
- }
-
- /*
+PUBLIC int
+glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute,
+ int *value_return)
+{
+ __GLXdisplayPrivate *priv;
+ __GLXscreenConfigs *psc;
+ __GLcontextModes *modes;
+ int status;
+
+ status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc);
+ if (status == Success) {
+ modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
+
+ /* Lookup attribute after first finding a match on the visual */
+ if (modes != NULL) {
+ return _gl_get_context_mode_data(modes, attribute, value_return);
+ }
+
+ status = GLX_BAD_VISUAL;
+ }
+
+ /*
** If we can't find the config for this visual, this visual is not
** supported by the OpenGL implementation on the server.
*/
- if ( (status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL) ) {
- *value_return = GL_FALSE;
- status = Success;
- }
+ if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) {
+ *value_return = GL_FALSE;
+ status = Success;
+ }
- return status;
+ return status;
}
/************************************************************************/
static void
-init_fbconfig_for_chooser( __GLcontextModes * config,
- GLboolean fbconfig_style_tags )
-{
- memset( config, 0, sizeof( __GLcontextModes ) );
- config->visualID = (XID) GLX_DONT_CARE;
- config->visualType = GLX_DONT_CARE;
-
- /* glXChooseFBConfig specifies different defaults for these two than
- * glXChooseVisual.
- */
- if ( fbconfig_style_tags ) {
- config->rgbMode = GL_TRUE;
- config->doubleBufferMode = GLX_DONT_CARE;
- }
-
- config->visualRating = GLX_DONT_CARE;
- config->transparentPixel = GLX_NONE;
- config->transparentRed = GLX_DONT_CARE;
- config->transparentGreen = GLX_DONT_CARE;
- config->transparentBlue = GLX_DONT_CARE;
- config->transparentAlpha = GLX_DONT_CARE;
- config->transparentIndex = GLX_DONT_CARE;
-
- config->drawableType = GLX_WINDOW_BIT;
- config->renderType = (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
- config->xRenderable = GLX_DONT_CARE;
- config->fbconfigID = (GLXFBConfigID)(GLX_DONT_CARE);
-
- config->swapMethod = GLX_DONT_CARE;
-}
-
-#define MATCH_DONT_CARE( param ) \
- do { \
- if ( (a-> param != GLX_DONT_CARE) \
- && (a-> param != b-> param) ) { \
- return False; \
- } \
- } while ( 0 )
-
-#define MATCH_MINIMUM( param ) \
- do { \
- if ( (a-> param != GLX_DONT_CARE) \
- && (a-> param > b-> param) ) { \
- return False; \
- } \
- } while ( 0 )
-
-#define MATCH_EXACT( param ) \
- do { \
- if ( a-> param != b-> param) { \
- return False; \
- } \
- } while ( 0 )
+init_fbconfig_for_chooser(__GLcontextModes * config,
+ GLboolean fbconfig_style_tags)
+{
+ memset(config, 0, sizeof(__GLcontextModes));
+ config->visualID = (XID) GLX_DONT_CARE;
+ config->visualType = GLX_DONT_CARE;
+
+ /* glXChooseFBConfig specifies different defaults for these two than
+ * glXChooseVisual.
+ */
+ if (fbconfig_style_tags) {
+ config->rgbMode = GL_TRUE;
+ config->doubleBufferMode = GLX_DONT_CARE;
+ }
+
+ config->visualRating = GLX_DONT_CARE;
+ config->transparentPixel = GLX_NONE;
+ config->transparentRed = GLX_DONT_CARE;
+ config->transparentGreen = GLX_DONT_CARE;
+ config->transparentBlue = GLX_DONT_CARE;
+ config->transparentAlpha = GLX_DONT_CARE;
+ config->transparentIndex = GLX_DONT_CARE;
+
+ config->drawableType = GLX_WINDOW_BIT;
+ config->renderType =
+ (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
+ config->xRenderable = GLX_DONT_CARE;
+ config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE);
+
+ config->swapMethod = GLX_DONT_CARE;
+}
+
+#define MATCH_DONT_CARE( param ) \
+ do { \
+ if ( (a-> param != GLX_DONT_CARE) \
+ && (a-> param != b-> param) ) { \
+ return False; \
+ } \
+ } while ( 0 )
+
+#define MATCH_MINIMUM( param ) \
+ do { \
+ if ( (a-> param != GLX_DONT_CARE) \
+ && (a-> param > b-> param) ) { \
+ return False; \
+ } \
+ } while ( 0 )
+
+#define MATCH_EXACT( param ) \
+ do { \
+ if ( a-> param != b-> param) { \
+ return False; \
+ } \
+ } while ( 0 )
/**
* Determine if two GLXFBConfigs are compatible.
@@ -1016,80 +1111,80 @@ init_fbconfig_for_chooser( __GLcontextModes * config,
* \param b Server specified config to test against \c a.
*/
static Bool
-fbconfigs_compatible( const __GLcontextModes * const a,
- const __GLcontextModes * const b )
-{
- MATCH_DONT_CARE( doubleBufferMode );
- MATCH_DONT_CARE( visualType );
- MATCH_DONT_CARE( visualRating );
- MATCH_DONT_CARE( xRenderable );
- MATCH_DONT_CARE( fbconfigID );
- MATCH_DONT_CARE( swapMethod );
-
- MATCH_MINIMUM( rgbBits );
- MATCH_MINIMUM( numAuxBuffers );
- MATCH_MINIMUM( redBits );
- MATCH_MINIMUM( greenBits );
- MATCH_MINIMUM( blueBits );
- MATCH_MINIMUM( alphaBits );
- MATCH_MINIMUM( depthBits );
- MATCH_MINIMUM( stencilBits );
- MATCH_MINIMUM( accumRedBits );
- MATCH_MINIMUM( accumGreenBits );
- MATCH_MINIMUM( accumBlueBits );
- MATCH_MINIMUM( accumAlphaBits );
- MATCH_MINIMUM( sampleBuffers );
- MATCH_MINIMUM( maxPbufferWidth );
- MATCH_MINIMUM( maxPbufferHeight );
- MATCH_MINIMUM( maxPbufferPixels );
- MATCH_MINIMUM( samples );
-
- MATCH_DONT_CARE( stereoMode );
- MATCH_EXACT( level );
-
- if ( ((a->drawableType & b->drawableType) == 0)
- || ((a->renderType & b->renderType) == 0) ) {
- return False;
- }
-
-
- /* There is a bug in a few of the XFree86 DDX drivers. They contain
- * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
- * Technically speaking, it is a bug in the DDX driver, but there is
- * enough of an installed base to work around the problem here. In any
- * case, 0 is not a valid value of the transparent type, so we'll treat 0
- * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
- * 0 from the server to be a match to maintain backward compatibility with
- * the (broken) drivers.
- */
-
- if ( a->transparentPixel != GLX_DONT_CARE
- && a->transparentPixel != 0 ) {
- if ( a->transparentPixel == GLX_NONE ) {
- if ( b->transparentPixel != GLX_NONE && b->transparentPixel != 0 )
- return False;
- } else {
- MATCH_EXACT( transparentPixel );
- }
-
- switch ( a->transparentPixel ) {
- case GLX_TRANSPARENT_RGB:
- MATCH_DONT_CARE( transparentRed );
- MATCH_DONT_CARE( transparentGreen );
- MATCH_DONT_CARE( transparentBlue );
- MATCH_DONT_CARE( transparentAlpha );
- break;
-
- case GLX_TRANSPARENT_INDEX:
- MATCH_DONT_CARE( transparentIndex );
- break;
-
- default:
- break;
- }
- }
-
- return True;
+fbconfigs_compatible(const __GLcontextModes * const a,
+ const __GLcontextModes * const b)
+{
+ MATCH_DONT_CARE(doubleBufferMode);
+ MATCH_DONT_CARE(visualType);
+ MATCH_DONT_CARE(visualRating);
+ MATCH_DONT_CARE(xRenderable);
+ MATCH_DONT_CARE(fbconfigID);
+ MATCH_DONT_CARE(swapMethod);
+
+ MATCH_MINIMUM(rgbBits);
+ MATCH_MINIMUM(numAuxBuffers);
+ MATCH_MINIMUM(redBits);
+ MATCH_MINIMUM(greenBits);
+ MATCH_MINIMUM(blueBits);
+ MATCH_MINIMUM(alphaBits);
+ MATCH_MINIMUM(depthBits);
+ MATCH_MINIMUM(stencilBits);
+ MATCH_MINIMUM(accumRedBits);
+ MATCH_MINIMUM(accumGreenBits);
+ MATCH_MINIMUM(accumBlueBits);
+ MATCH_MINIMUM(accumAlphaBits);
+ MATCH_MINIMUM(sampleBuffers);
+ MATCH_MINIMUM(maxPbufferWidth);
+ MATCH_MINIMUM(maxPbufferHeight);
+ MATCH_MINIMUM(maxPbufferPixels);
+ MATCH_MINIMUM(samples);
+
+ MATCH_DONT_CARE(stereoMode);
+ MATCH_EXACT(level);
+
+ if (((a->drawableType & b->drawableType) == 0)
+ || ((a->renderType & b->renderType) == 0)) {
+ return False;
+ }
+
+
+ /* There is a bug in a few of the XFree86 DDX drivers. They contain
+ * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
+ * Technically speaking, it is a bug in the DDX driver, but there is
+ * enough of an installed base to work around the problem here. In any
+ * case, 0 is not a valid value of the transparent type, so we'll treat 0
+ * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
+ * 0 from the server to be a match to maintain backward compatibility with
+ * the (broken) drivers.
+ */
+
+ if (a->transparentPixel != GLX_DONT_CARE && a->transparentPixel != 0) {
+ if (a->transparentPixel == GLX_NONE) {
+ if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0)
+ return False;
+ }
+ else {
+ MATCH_EXACT(transparentPixel);
+ }
+
+ switch (a->transparentPixel) {
+ case GLX_TRANSPARENT_RGB:
+ MATCH_DONT_CARE(transparentRed);
+ MATCH_DONT_CARE(transparentGreen);
+ MATCH_DONT_CARE(transparentBlue);
+ MATCH_DONT_CARE(transparentAlpha);
+ break;
+
+ case GLX_TRANSPARENT_INDEX:
+ MATCH_DONT_CARE(transparentIndex);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return True;
}
@@ -1099,39 +1194,39 @@ fbconfigs_compatible( const __GLcontextModes * const a,
* Well, that's really hard to do with the code as-is. This behavior is
* closer to correct, but still not technically right.
*/
-#define PREFER_LARGER_OR_ZERO(comp) \
- do { \
- if ( ((*a)-> comp) != ((*b)-> comp) ) { \
- if ( ((*a)-> comp) == 0 ) { \
- return -1; \
- } \
- else if ( ((*b)-> comp) == 0 ) { \
- return 1; \
- } \
- else { \
- return ((*b)-> comp) - ((*a)-> comp) ; \
- } \
- } \
- } while( 0 )
-
-#define PREFER_LARGER(comp) \
- do { \
- if ( ((*a)-> comp) != ((*b)-> comp) ) { \
- return ((*b)-> comp) - ((*a)-> comp) ; \
- } \
- } while( 0 )
-
-#define PREFER_SMALLER(comp) \
- do { \
- if ( ((*a)-> comp) != ((*b)-> comp) ) { \
- return ((*a)-> comp) - ((*b)-> comp) ; \
- } \
- } while( 0 )
+#define PREFER_LARGER_OR_ZERO(comp) \
+ do { \
+ if ( ((*a)-> comp) != ((*b)-> comp) ) { \
+ if ( ((*a)-> comp) == 0 ) { \
+ return -1; \
+ } \
+ else if ( ((*b)-> comp) == 0 ) { \
+ return 1; \
+ } \
+ else { \
+ return ((*b)-> comp) - ((*a)-> comp) ; \
+ } \
+ } \
+ } while( 0 )
+
+#define PREFER_LARGER(comp) \
+ do { \
+ if ( ((*a)-> comp) != ((*b)-> comp) ) { \
+ return ((*b)-> comp) - ((*a)-> comp) ; \
+ } \
+ } while( 0 )
+
+#define PREFER_SMALLER(comp) \
+ do { \
+ if ( ((*a)-> comp) != ((*b)-> comp) ) { \
+ return ((*a)-> comp) - ((*b)-> comp) ; \
+ } \
+ } while( 0 )
/**
* Compare two GLXFBConfigs. This function is intended to be used as the
* compare function passed in to qsort.
- *
+ *
* \returns If \c a is a "better" config, according to the specification of
* SGIX_fbconfig, a number less than zero is returned. If \c b is
* better, then a number greater than zero is return. If both are
@@ -1139,66 +1234,66 @@ fbconfigs_compatible( const __GLcontextModes * const a,
* \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
*/
static int
-fbconfig_compare( const __GLcontextModes * const * const a,
- const __GLcontextModes * const * const b )
+fbconfig_compare(const __GLcontextModes * const *const a,
+ const __GLcontextModes * const *const b)
{
- /* The order of these comparisons must NOT change. It is defined by
- * the GLX 1.3 spec and ARB_multisample.
- */
+ /* The order of these comparisons must NOT change. It is defined by
+ * the GLX 1.3 spec and ARB_multisample.
+ */
- PREFER_SMALLER( visualSelectGroup );
+ PREFER_SMALLER(visualSelectGroup);
- /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
- * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the
- * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
- */
- PREFER_SMALLER( visualRating );
+ /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
+ * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the
+ * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
+ */
+ PREFER_SMALLER(visualRating);
- /* This isn't quite right. It is supposed to compare the sum of the
- * components the user specifically set minimums for.
- */
- PREFER_LARGER_OR_ZERO( redBits );
- PREFER_LARGER_OR_ZERO( greenBits );
- PREFER_LARGER_OR_ZERO( blueBits );
- PREFER_LARGER_OR_ZERO( alphaBits );
+ /* This isn't quite right. It is supposed to compare the sum of the
+ * components the user specifically set minimums for.
+ */
+ PREFER_LARGER_OR_ZERO(redBits);
+ PREFER_LARGER_OR_ZERO(greenBits);
+ PREFER_LARGER_OR_ZERO(blueBits);
+ PREFER_LARGER_OR_ZERO(alphaBits);
- PREFER_SMALLER( rgbBits );
+ PREFER_SMALLER(rgbBits);
- if ( ((*a)->doubleBufferMode != (*b)->doubleBufferMode) ) {
- /* Prefer single-buffer.
- */
- return ( !(*a)->doubleBufferMode ) ? -1 : 1;
- }
+ if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) {
+ /* Prefer single-buffer.
+ */
+ return (!(*a)->doubleBufferMode) ? -1 : 1;
+ }
- PREFER_SMALLER( numAuxBuffers );
+ PREFER_SMALLER(numAuxBuffers);
- PREFER_LARGER_OR_ZERO( depthBits );
- PREFER_SMALLER( stencilBits );
+ PREFER_LARGER_OR_ZERO(depthBits);
+ PREFER_SMALLER(stencilBits);
- /* This isn't quite right. It is supposed to compare the sum of the
- * components the user specifically set minimums for.
- */
- PREFER_LARGER_OR_ZERO( accumRedBits );
- PREFER_LARGER_OR_ZERO( accumGreenBits );
- PREFER_LARGER_OR_ZERO( accumBlueBits );
- PREFER_LARGER_OR_ZERO( accumAlphaBits );
+ /* This isn't quite right. It is supposed to compare the sum of the
+ * components the user specifically set minimums for.
+ */
+ PREFER_LARGER_OR_ZERO(accumRedBits);
+ PREFER_LARGER_OR_ZERO(accumGreenBits);
+ PREFER_LARGER_OR_ZERO(accumBlueBits);
+ PREFER_LARGER_OR_ZERO(accumAlphaBits);
- PREFER_SMALLER( visualType );
+ PREFER_SMALLER(visualType);
- /* None of the multisample specs say where this comparison should happen,
- * so I put it near the end.
- */
- PREFER_SMALLER( sampleBuffers );
- PREFER_SMALLER( samples );
+ /* None of the multisample specs say where this comparison should happen,
+ * so I put it near the end.
+ */
+ PREFER_SMALLER(sampleBuffers);
+ PREFER_SMALLER(samples);
- /* None of the pbuffer or fbconfig specs say that this comparison needs
- * to happen at all, but it seems like it should.
- */
- PREFER_LARGER( maxPbufferWidth );
- PREFER_LARGER( maxPbufferHeight );
- PREFER_LARGER( maxPbufferPixels );
+ /* None of the pbuffer or fbconfig specs say that this comparison needs
+ * to happen at all, but it seems like it should.
+ */
+ PREFER_LARGER(maxPbufferWidth);
+ PREFER_LARGER(maxPbufferHeight);
+ PREFER_LARGER(maxPbufferPixels);
- return 0;
+ return 0;
}
@@ -1206,7 +1301,7 @@ fbconfig_compare( const __GLcontextModes * const * const a,
* Selects and sorts a subset of the supplied configs based on the attributes.
* This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig,
* and \c glXChooseFBConfigSGIX.
- *
+ *
* \param configs Array of pointers to possible configs. The elements of
* this array that do not meet the criteria will be set to
* NULL. The remaining elements will be sorted according to
@@ -1221,53 +1316,52 @@ fbconfig_compare( const __GLcontextModes * const * const a,
* \c glXChooseVisual style or
* \c glXChooseFBConfig style.
* \returns The number of valid elements left in \c configs.
- *
+ *
* \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
*/
static int
-choose_visual( __GLcontextModes ** configs, int num_configs,
- const int *attribList, GLboolean fbconfig_style_tags )
-{
- __GLcontextModes test_config;
- int base;
- int i;
-
- /* This is a fairly direct implementation of the selection method
- * described by GLX_SGIX_fbconfig. Start by culling out all the
- * configs that are not compatible with the selected parameter
- * list.
- */
-
- init_fbconfig_for_chooser( & test_config, fbconfig_style_tags );
- __glXInitializeVisualConfigFromTags( & test_config, 512,
- (const INT32 *) attribList,
- GL_TRUE, fbconfig_style_tags );
-
- base = 0;
- for ( i = 0 ; i < num_configs ; i++ ) {
- if ( fbconfigs_compatible( & test_config, configs[i] ) ) {
- configs[ base ] = configs[ i ];
- base++;
- }
- }
-
- if ( base == 0 ) {
- return 0;
- }
-
- if ( base < num_configs ) {
- (void) memset( & configs[ base ], 0,
- sizeof( void * ) * (num_configs - base) );
- }
-
- /* After the incompatible configs are removed, the resulting
- * list is sorted according to the rules set out in the various
- * specifications.
- */
-
- qsort( configs, base, sizeof( __GLcontextModes * ),
- (int (*)(const void*, const void*)) fbconfig_compare );
- return base;
+choose_visual(__GLcontextModes ** configs, int num_configs,
+ const int *attribList, GLboolean fbconfig_style_tags)
+{
+ __GLcontextModes test_config;
+ int base;
+ int i;
+
+ /* This is a fairly direct implementation of the selection method
+ * described by GLX_SGIX_fbconfig. Start by culling out all the
+ * configs that are not compatible with the selected parameter
+ * list.
+ */
+
+ init_fbconfig_for_chooser(&test_config, fbconfig_style_tags);
+ __glXInitializeVisualConfigFromTags(&test_config, 512,
+ (const INT32 *) attribList,
+ GL_TRUE, fbconfig_style_tags);
+
+ base = 0;
+ for (i = 0; i < num_configs; i++) {
+ if (fbconfigs_compatible(&test_config, configs[i])) {
+ configs[base] = configs[i];
+ base++;
+ }
+ }
+
+ if (base == 0) {
+ return 0;
+ }
+
+ if (base < num_configs) {
+ (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base));
+ }
+
+ /* After the incompatible configs are removed, the resulting
+ * list is sorted according to the rules set out in the various
+ * specifications.
+ */
+
+ qsort(configs, base, sizeof(__GLcontextModes *),
+ (int (*)(const void *, const void *)) fbconfig_compare);
+ return base;
}
@@ -1277,169 +1371,176 @@ choose_visual( __GLcontextModes ** configs, int num_configs,
** Return the visual that best matches the template. Return None if no
** visual matches the template.
*/
-PUBLIC XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList)
+PUBLIC XVisualInfo *
+glXChooseVisual(Display * dpy, int screen, int *attribList)
{
- XVisualInfo *visualList = NULL;
- __GLXdisplayPrivate *priv;
- __GLXscreenConfigs *psc;
- __GLcontextModes test_config;
- __GLcontextModes *modes;
- const __GLcontextModes *best_config = NULL;
+ XVisualInfo *visualList = NULL;
+ __GLXdisplayPrivate *priv;
+ __GLXscreenConfigs *psc;
+ __GLcontextModes test_config;
+ __GLcontextModes *modes;
+ const __GLcontextModes *best_config = NULL;
- /*
+ /*
** Get a list of all visuals, return if list is empty
*/
- if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) {
- return None;
- }
-
+ if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
+ return None;
+ }
- /*
+
+ /*
** Build a template from the defaults and the attribute list
** Free visual list and return if an unexpected token is encountered
*/
- init_fbconfig_for_chooser( & test_config, GL_FALSE );
- __glXInitializeVisualConfigFromTags( & test_config, 512,
- (const INT32 *) attribList,
- GL_TRUE, GL_FALSE );
+ init_fbconfig_for_chooser(&test_config, GL_FALSE);
+ __glXInitializeVisualConfigFromTags(&test_config, 512,
+ (const INT32 *) attribList,
+ GL_TRUE, GL_FALSE);
- /*
+ /*
** Eliminate visuals that don't meet minimum requirements
** Compute a score for those that do
** Remember which visual, if any, got the highest score
- */
- for ( modes = psc->visuals ; modes != NULL ; modes = modes->next ) {
- if ( fbconfigs_compatible( & test_config, modes )
- && ((best_config == NULL)
- || (fbconfig_compare( (const __GLcontextModes * const * const)&modes, &best_config ) < 0)) ) {
- best_config = modes;
- }
- }
-
- /*
** If no visual is acceptable, return None
** Otherwise, create an XVisualInfo list with just the selected X visual
** and return this.
*/
- if (best_config != NULL) {
- XVisualInfo visualTemplate;
- int i;
-
- visualTemplate.screen = screen;
- visualTemplate.visualid = best_config->visualID;
- visualList = XGetVisualInfo( dpy, VisualScreenMask|VisualIDMask,
- &visualTemplate, &i );
- }
+ for (modes = psc->visuals; modes != NULL; modes = modes->next) {
+ if (fbconfigs_compatible(&test_config, modes)
+ && ((best_config == NULL)
+ ||
+ (fbconfig_compare
+ ((const __GLcontextModes * const *const) &modes,
+ &best_config) < 0))) {
+ XVisualInfo visualTemplate;
+ XVisualInfo *newList;
+ int i;
+
+ visualTemplate.screen = screen;
+ visualTemplate.visualid = modes->visualID;
+ newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
+ &visualTemplate, &i);
+
+ if (newList) {
+ Xfree(visualList);
+ visualList = newList;
+ best_config = modes;
+ }
+ }
+ }
- return visualList;
+ return visualList;
}
-PUBLIC const char *glXQueryExtensionsString( Display *dpy, int screen )
+PUBLIC const char *
+glXQueryExtensionsString(Display * dpy, int screen)
{
- __GLXscreenConfigs *psc;
- __GLXdisplayPrivate *priv;
+ __GLXscreenConfigs *psc;
+ __GLXdisplayPrivate *priv;
- if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) {
- return NULL;
- }
+ if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
+ return NULL;
+ }
- if (!psc->effectiveGLXexts) {
- if (!psc->serverGLXexts) {
- psc->serverGLXexts =
- __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
- }
+ if (!psc->effectiveGLXexts) {
+ if (!psc->serverGLXexts) {
+ psc->serverGLXexts =
+ __glXQueryServerString(dpy, priv->majorOpcode, screen,
+ GLX_EXTENSIONS);
+ }
- __glXCalculateUsableExtensions(psc,
+ __glXCalculateUsableExtensions(psc,
#ifdef GLX_DIRECT_RENDERING
- (psc->driScreen != NULL),
+ (psc->driScreen != NULL),
#else
- GL_FALSE,
+ GL_FALSE,
#endif
- priv->minorVersion);
- }
+ priv->minorVersion);
+ }
- return psc->effectiveGLXexts;
+ return psc->effectiveGLXexts;
}
-PUBLIC const char *glXGetClientString( Display *dpy, int name )
+PUBLIC const char *
+glXGetClientString(Display * dpy, int name)
{
- switch(name) {
- case GLX_VENDOR:
- return (__glXGLXClientVendorName);
- case GLX_VERSION:
- return (__glXGLXClientVersion);
- case GLX_EXTENSIONS:
- return (__glXGetClientExtensions());
- default:
- return NULL;
- }
+ switch (name) {
+ case GLX_VENDOR:
+ return (__glXGLXClientVendorName);
+ case GLX_VERSION:
+ return (__glXGLXClientVersion);
+ case GLX_EXTENSIONS:
+ return (__glXGetClientExtensions());
+ default:
+ return NULL;
+ }
}
-PUBLIC const char *glXQueryServerString( Display *dpy, int screen, int name )
+PUBLIC const char *
+glXQueryServerString(Display * dpy, int screen, int name)
{
- __GLXscreenConfigs *psc;
- __GLXdisplayPrivate *priv;
- const char ** str;
+ __GLXscreenConfigs *psc;
+ __GLXdisplayPrivate *priv;
+ const char **str;
+
+ if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
+ return NULL;
+ }
- if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) {
- return NULL;
- }
+ switch (name) {
+ case GLX_VENDOR:
+ str = &priv->serverGLXvendor;
+ break;
+ case GLX_VERSION:
+ str = &priv->serverGLXversion;
+ break;
+ case GLX_EXTENSIONS:
+ str = &psc->serverGLXexts;
+ break;
+ default:
+ return NULL;
+ }
- switch(name) {
- case GLX_VENDOR:
- str = & priv->serverGLXvendor;
- break;
- case GLX_VERSION:
- str = & priv->serverGLXversion;
- break;
- case GLX_EXTENSIONS:
- str = & psc->serverGLXexts;
- break;
- default:
- return NULL;
- }
+ if (*str == NULL) {
+ *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name);
+ }
- if ( *str == NULL ) {
- *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name);
- }
-
- return *str;
+ return *str;
}
-void __glXClientInfo ( Display *dpy, int opcode )
+void
+__glXClientInfo(Display * dpy, int opcode)
{
- char * ext_str = __glXGetClientGLExtensionString();
- int size = strlen( ext_str ) + 1;
+ char *ext_str = __glXGetClientGLExtensionString();
+ int size = strlen(ext_str) + 1;
#ifdef USE_XCB
xcb_connection_t *c = XGetXCBConnection(dpy);
xcb_glx_client_info(c,
- GLX_MAJOR_VERSION,
- GLX_MINOR_VERSION,
- size,
- (const uint8_t *)ext_str);
+ GLX_MAJOR_VERSION, GLX_MINOR_VERSION, size, ext_str);
#else
- xGLXClientInfoReq *req;
-
- /* Send the glXClientInfo request */
- LockDisplay(dpy);
- GetReq(GLXClientInfo,req);
- req->reqType = opcode;
- req->glxCode = X_GLXClientInfo;
- req->major = GLX_MAJOR_VERSION;
- req->minor = GLX_MINOR_VERSION;
-
- req->length += (size + 3) >> 2;
- req->numbytes = size;
- Data(dpy, ext_str, size);
-
- UnlockDisplay(dpy);
- SyncHandle();
+ xGLXClientInfoReq *req;
+
+ /* Send the glXClientInfo request */
+ LockDisplay(dpy);
+ GetReq(GLXClientInfo, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXClientInfo;
+ req->major = GLX_MAJOR_VERSION;
+ req->minor = GLX_MINOR_VERSION;
+
+ req->length += (size + 3) >> 2;
+ req->numbytes = size;
+ Data(dpy, ext_str, size);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
#endif /* USE_XCB */
- Xfree( ext_str );
+ Xfree(ext_str);
}
@@ -1447,194 +1548,201 @@ void __glXClientInfo ( Display *dpy, int opcode )
** EXT_import_context
*/
-PUBLIC Display *glXGetCurrentDisplay(void)
+PUBLIC Display *
+glXGetCurrentDisplay(void)
{
- GLXContext gc = __glXGetCurrentContext();
- if (NULL == gc) return NULL;
- return gc->currentDpy;
+ GLXContext gc = __glXGetCurrentContext();
+ if (NULL == gc)
+ return NULL;
+ return gc->currentDpy;
}
-PUBLIC GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
- glXGetCurrentDisplay)
+PUBLIC
+GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
+ glXGetCurrentDisplay)
/**
* Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests
* to the X-server.
- *
+ *
* \param dpy Display where \c ctx was created.
* \param ctx Context to query.
* \returns \c Success on success. \c GLX_BAD_CONTEXT if \c ctx is invalid,
* or zero if the request failed due to internal problems (i.e.,
* unable to allocate temporary memory, etc.)
- *
+ *
* \note
* This function dynamically determines whether to use the EXT_import_context
* version of the protocol or the GLX 1.3 version of the protocol.
*/
-static int __glXQueryContextInfo(Display *dpy, GLXContext ctx)
-{
- __GLXdisplayPrivate *priv = __glXInitialize(dpy);
- xGLXQueryContextReply reply;
- CARD8 opcode;
- GLuint numValues;
- int retval;
-
- if (ctx == NULL) {
- return GLX_BAD_CONTEXT;
- }
- opcode = __glXSetupForCommand(dpy);
- if (!opcode) {
- return 0;
- }
-
- /* Send the glXQueryContextInfoEXT request */
- LockDisplay(dpy);
-
- if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
- xGLXQueryContextReq *req;
-
- GetReq(GLXQueryContext, req);
-
- req->reqType = opcode;
- req->glxCode = X_GLXQueryContext;
- req->context = (unsigned int)(ctx->xid);
- }
- else {
- xGLXVendorPrivateReq *vpreq;
- xGLXQueryContextInfoEXTReq *req;
-
- GetReqExtra( GLXVendorPrivate,
- sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
- vpreq );
- req = (xGLXQueryContextInfoEXTReq *)vpreq;
- req->reqType = opcode;
- req->glxCode = X_GLXVendorPrivateWithReply;
- req->vendorCode = X_GLXvop_QueryContextInfoEXT;
- req->context = (unsigned int)(ctx->xid);
- }
-
- _XReply(dpy, (xReply*) &reply, 0, False);
-
- numValues = reply.n;
- if (numValues == 0)
- retval = Success;
- else if (numValues > __GLX_MAX_CONTEXT_PROPS)
- retval = 0;
- else
- {
- int *propList, *pProp;
- int nPropListBytes;
- int i;
-
- nPropListBytes = numValues << 3;
- propList = (int *) Xmalloc(nPropListBytes);
- if (NULL == propList) {
- retval = 0;
- } else {
- _XRead(dpy, (char *)propList, nPropListBytes);
- pProp = propList;
- for (i=0; i < numValues; i++) {
- switch (*pProp++) {
- case GLX_SHARE_CONTEXT_EXT:
- ctx->share_xid = *pProp++;
- break;
- case GLX_VISUAL_ID_EXT:
- ctx->mode =
- _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
- break;
- case GLX_SCREEN:
- ctx->screen = *pProp++;
- break;
- case GLX_FBCONFIG_ID:
- ctx->mode =
- _gl_context_modes_find_fbconfig(ctx->psc->configs, *pProp++);
- break;
- case GLX_RENDER_TYPE:
- ctx->renderType = *pProp++;
- break;
- default:
- pProp++;
- continue;
- }
- }
- Xfree((char *)propList);
- retval = Success;
- }
- }
- UnlockDisplay(dpy);
- SyncHandle();
- return retval;
+ static int __glXQueryContextInfo(Display * dpy, GLXContext ctx)
+{
+ __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+ xGLXQueryContextReply reply;
+ CARD8 opcode;
+ GLuint numValues;
+ int retval;
+
+ if (ctx == NULL) {
+ return GLX_BAD_CONTEXT;
+ }
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode) {
+ return 0;
+ }
+
+ /* Send the glXQueryContextInfoEXT request */
+ LockDisplay(dpy);
+
+ if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
+ xGLXQueryContextReq *req;
+
+ GetReq(GLXQueryContext, req);
+
+ req->reqType = opcode;
+ req->glxCode = X_GLXQueryContext;
+ req->context = (unsigned int) (ctx->xid);
+ }
+ else {
+ xGLXVendorPrivateReq *vpreq;
+ xGLXQueryContextInfoEXTReq *req;
+
+ GetReqExtra(GLXVendorPrivate,
+ sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
+ vpreq);
+ req = (xGLXQueryContextInfoEXTReq *) vpreq;
+ req->reqType = opcode;
+ req->glxCode = X_GLXVendorPrivateWithReply;
+ req->vendorCode = X_GLXvop_QueryContextInfoEXT;
+ req->context = (unsigned int) (ctx->xid);
+ }
+
+ _XReply(dpy, (xReply *) & reply, 0, False);
+
+ numValues = reply.n;
+ if (numValues == 0)
+ retval = Success;
+ else if (numValues > __GLX_MAX_CONTEXT_PROPS)
+ retval = 0;
+ else {
+ int *propList, *pProp;
+ int nPropListBytes;
+ int i;
+
+ nPropListBytes = numValues << 3;
+ propList = (int *) Xmalloc(nPropListBytes);
+ if (NULL == propList) {
+ retval = 0;
+ }
+ else {
+ _XRead(dpy, (char *) propList, nPropListBytes);
+ pProp = propList;
+ for (i = 0; i < numValues; i++) {
+ switch (*pProp++) {
+ case GLX_SHARE_CONTEXT_EXT:
+ ctx->share_xid = *pProp++;
+ break;
+ case GLX_VISUAL_ID_EXT:
+ ctx->mode =
+ _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
+ break;
+ case GLX_SCREEN:
+ ctx->screen = *pProp++;
+ break;
+ case GLX_FBCONFIG_ID:
+ ctx->mode =
+ _gl_context_modes_find_fbconfig(ctx->psc->configs,
+ *pProp++);
+ break;
+ case GLX_RENDER_TYPE:
+ ctx->renderType = *pProp++;
+ break;
+ default:
+ pProp++;
+ continue;
+ }
+ }
+ Xfree((char *) propList);
+ retval = Success;
+ }
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return retval;
}
PUBLIC int
-glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value)
+glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value)
{
- int retVal;
+ int retVal;
- /* get the information from the server if we don't have it already */
+ /* get the information from the server if we don't have it already */
#ifdef GLX_DIRECT_RENDERING
- if (!ctx->driContext && (ctx->mode == NULL)) {
+ if (!ctx->driContext && (ctx->mode == NULL)) {
#else
- if (ctx->mode == NULL) {
+ if (ctx->mode == NULL) {
#endif
- retVal = __glXQueryContextInfo(dpy, ctx);
- if (Success != retVal) return retVal;
- }
- switch (attribute) {
- case GLX_SHARE_CONTEXT_EXT:
- *value = (int)(ctx->share_xid);
- break;
- case GLX_VISUAL_ID_EXT:
- *value = ctx->mode ? ctx->mode->visualID : None;
- break;
- case GLX_SCREEN:
- *value = (int)(ctx->screen);
- break;
- case GLX_FBCONFIG_ID:
- *value = ctx->mode ? ctx->mode->fbconfigID : None;
- break;
- case GLX_RENDER_TYPE:
- *value = (int)(ctx->renderType);
- break;
- default:
- return GLX_BAD_ATTRIBUTE;
- }
- return Success;
+ retVal = __glXQueryContextInfo(dpy, ctx);
+ if (Success != retVal)
+ return retVal;
+ }
+ switch (attribute) {
+ case GLX_SHARE_CONTEXT_EXT:
+ *value = (int) (ctx->share_xid);
+ break;
+ case GLX_VISUAL_ID_EXT:
+ *value = ctx->mode ? ctx->mode->visualID : None;
+ break;
+ case GLX_SCREEN:
+ *value = (int) (ctx->screen);
+ break;
+ case GLX_FBCONFIG_ID:
+ *value = ctx->mode ? ctx->mode->fbconfigID : None;
+ break;
+ case GLX_RENDER_TYPE:
+ *value = (int) (ctx->renderType);
+ break;
+ default:
+ return GLX_BAD_ATTRIBUTE;
+ }
+ return Success;
}
-PUBLIC GLX_ALIAS( int, glXQueryContextInfoEXT,
- (Display *dpy, GLXContext ctx, int attribute, int *value),
- (dpy, ctx, attribute, value),
- glXQueryContext )
+PUBLIC
+GLX_ALIAS(int, glXQueryContextInfoEXT,
+ (Display * dpy, GLXContext ctx, int attribute, int *value),
+ (dpy, ctx, attribute, value), glXQueryContext)
-PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
+ PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
{
- return ctx->xid;
+ return ctx->xid;
}
-PUBLIC GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID)
+PUBLIC GLXContext
+glXImportContextEXT(Display * dpy, GLXContextID contextID)
{
- GLXContext ctx;
+ GLXContext ctx;
- if (contextID == None) {
- return NULL;
- }
- if (__glXIsDirect(dpy, contextID)) {
- return NULL;
- }
+ if (contextID == None) {
+ return NULL;
+ }
+ if (__glXIsDirect(dpy, contextID)) {
+ return NULL;
+ }
- ctx = CreateContext(dpy, NULL, NULL, NULL, False, contextID, False, 0);
- if (NULL != ctx) {
- if (Success != __glXQueryContextInfo(dpy, ctx)) {
- return NULL;
- }
- }
- return ctx;
+ ctx = CreateContext(dpy, NULL, NULL, NULL, False, contextID, False, 0);
+ if (NULL != ctx) {
+ if (Success != __glXQueryContextInfo(dpy, ctx)) {
+ return NULL;
+ }
+ }
+ return ctx;
}
-PUBLIC void glXFreeContextEXT(Display *dpy, GLXContext ctx)
+PUBLIC void
+glXFreeContextEXT(Display * dpy, GLXContext ctx)
{
- DestroyContext(dpy, ctx);
+ DestroyContext(dpy, ctx);
}
@@ -1643,146 +1751,149 @@ PUBLIC void glXFreeContextEXT(Display *dpy, GLXContext ctx)
* GLX 1.3 functions - these are just stubs for now!
*/
-PUBLIC GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen,
- const int *attribList, int *nitems)
+PUBLIC GLXFBConfig *
+glXChooseFBConfig(Display * dpy, int screen,
+ const int *attribList, int *nitems)
{
- __GLcontextModes ** config_list;
- int list_size;
+ __GLcontextModes **config_list;
+ int list_size;
- config_list = (__GLcontextModes **)
- glXGetFBConfigs( dpy, screen, & list_size );
+ config_list = (__GLcontextModes **)
+ glXGetFBConfigs(dpy, screen, &list_size);
- if ( (config_list != NULL) && (list_size > 0) && (attribList != NULL) ) {
- list_size = choose_visual( config_list, list_size, attribList,
- GL_TRUE );
- if ( list_size == 0 ) {
- XFree( config_list );
- config_list = NULL;
- }
- }
+ if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
+ list_size = choose_visual(config_list, list_size, attribList, GL_TRUE);
+ if (list_size == 0) {
+ XFree(config_list);
+ config_list = NULL;
+ }
+ }
- *nitems = list_size;
- return (GLXFBConfig *) config_list;
+ *nitems = list_size;
+ return (GLXFBConfig *) config_list;
}
-PUBLIC GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config,
- int renderType, GLXContext shareList,
- Bool allowDirect)
+PUBLIC GLXContext
+glXCreateNewContext(Display * dpy, GLXFBConfig config,
+ int renderType, GLXContext shareList, Bool allowDirect)
{
- return CreateContext( dpy, NULL, (__GLcontextModes *) config, shareList,
- allowDirect, None, True, renderType );
+ return CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList,
+ allowDirect, None, True, renderType);
}
-PUBLIC GLXDrawable glXGetCurrentReadDrawable(void)
+PUBLIC GLXDrawable
+glXGetCurrentReadDrawable(void)
{
- GLXContext gc = __glXGetCurrentContext();
- return gc->currentReadable;
+ GLXContext gc = __glXGetCurrentContext();
+ return gc->currentReadable;
}
-PUBLIC GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements)
+PUBLIC GLXFBConfig *
+glXGetFBConfigs(Display * dpy, int screen, int *nelements)
{
- __GLXdisplayPrivate *priv = __glXInitialize(dpy);
- __GLcontextModes ** config = NULL;
- int i;
+ __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+ __GLcontextModes **config = NULL;
+ int i;
- *nelements = 0;
- if ( (priv->screenConfigs != NULL)
- && (screen >= 0) && (screen <= ScreenCount(dpy))
- && (priv->screenConfigs[screen].configs != NULL)
- && (priv->screenConfigs[screen].configs->fbconfigID != GLX_DONT_CARE) ) {
- unsigned num_configs = 0;
- __GLcontextModes * modes;
+ *nelements = 0;
+ if (priv && (priv->screenConfigs != NULL)
+ && (screen >= 0) && (screen <= ScreenCount(dpy))
+ && (priv->screenConfigs[screen].configs != NULL)
+ && (priv->screenConfigs[screen].configs->fbconfigID != GLX_DONT_CARE)) {
+ unsigned num_configs = 0;
+ __GLcontextModes *modes;
- for ( modes = priv->screenConfigs[screen].configs
- ; modes != NULL
- ; modes = modes->next ) {
- if ( modes->fbconfigID != GLX_DONT_CARE ) {
- num_configs++;
- }
- }
+ for (modes = priv->screenConfigs[screen].configs; modes != NULL;
+ modes = modes->next) {
+ if (modes->fbconfigID != GLX_DONT_CARE) {
+ num_configs++;
+ }
+ }
- config = (__GLcontextModes **) Xmalloc( sizeof(__GLcontextModes *)
- * num_configs );
- if ( config != NULL ) {
- *nelements = num_configs;
- i = 0;
- for ( modes = priv->screenConfigs[screen].configs
- ; modes != NULL
- ; modes = modes->next ) {
- if ( modes->fbconfigID != GLX_DONT_CARE ) {
- config[i] = modes;
- i++;
- }
- }
- }
- }
- return (GLXFBConfig *) config;
+ config = (__GLcontextModes **) Xmalloc(sizeof(__GLcontextModes *)
+ * num_configs);
+ if (config != NULL) {
+ *nelements = num_configs;
+ i = 0;
+ for (modes = priv->screenConfigs[screen].configs; modes != NULL;
+ modes = modes->next) {
+ if (modes->fbconfigID != GLX_DONT_CARE) {
+ config[i] = modes;
+ i++;
+ }
+ }
+ }
+ }
+ return (GLXFBConfig *) config;
}
-PUBLIC int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config,
- int attribute, int *value)
+PUBLIC int
+glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config,
+ int attribute, int *value)
{
- __GLcontextModes * const modes = ValidateGLXFBConfig( dpy, config );
+ __GLcontextModes *const modes = ValidateGLXFBConfig(dpy, config);
- return (modes != NULL)
- ? _gl_get_context_mode_data( modes, attribute, value )
- : GLXBadFBConfig;
+ return (modes != NULL)
+ ? _gl_get_context_mode_data(modes, attribute, value)
+ : GLXBadFBConfig;
}
-PUBLIC XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
+PUBLIC XVisualInfo *
+glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config)
{
- XVisualInfo visualTemplate;
- __GLcontextModes * fbconfig = (__GLcontextModes *) config;
- int count;
+ XVisualInfo visualTemplate;
+ __GLcontextModes *fbconfig = (__GLcontextModes *) config;
+ int count;
- /*
+ /*
** Get a list of all visuals, return if list is empty
*/
- visualTemplate.visualid = fbconfig->visualID;
- return XGetVisualInfo(dpy,VisualIDMask,&visualTemplate,&count);
+ visualTemplate.visualid = fbconfig->visualID;
+ return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count);
}
/*
** GLX_SGI_swap_control
*/
-static int __glXSwapIntervalSGI(int interval)
+static int
+__glXSwapIntervalSGI(int interval)
{
xGLXVendorPrivateReq *req;
GLXContext gc = __glXGetCurrentContext();
- Display * dpy;
- CARD32 * interval_ptr;
+ Display *dpy;
+ CARD32 *interval_ptr;
CARD8 opcode;
- if ( gc == NULL ) {
+ if (gc == NULL) {
return GLX_BAD_CONTEXT;
}
-
- if ( interval <= 0 ) {
+
+ if (interval <= 0) {
return GLX_BAD_VALUE;
}
#ifdef __DRI_SWAP_CONTROL
if (gc->driContext) {
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
- gc->screen );
- __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
- gc->currentDrawable,
- NULL);
- if (psc->swapControl != NULL && pdraw != NULL) {
- psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
- return 0;
- }
- else {
- return GLX_BAD_CONTEXT;
- }
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
+ gc->screen);
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
+ gc->currentDrawable,
+ NULL);
+ if (psc->swapControl != NULL && pdraw != NULL) {
+ psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
+ return 0;
+ }
+ else {
+ return GLX_BAD_CONTEXT;
+ }
}
#endif
dpy = gc->currentDpy;
@@ -1793,7 +1904,7 @@ static int __glXSwapIntervalSGI(int interval)
/* Send the glXSwapIntervalSGI request */
LockDisplay(dpy);
- GetReqExtra(GLXVendorPrivate,sizeof(CARD32),req);
+ GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req);
req->reqType = opcode;
req->glxCode = X_GLXVendorPrivate;
req->vendorCode = X_GLXvop_SwapIntervalSGI;
@@ -1813,26 +1924,27 @@ static int __glXSwapIntervalSGI(int interval)
/*
** GLX_MESA_swap_control
*/
-static int __glXSwapIntervalMESA(unsigned int interval)
+static int
+__glXSwapIntervalMESA(unsigned int interval)
{
#ifdef __DRI_SWAP_CONTROL
GLXContext gc = __glXGetCurrentContext();
- if ( interval < 0 ) {
+ if (interval < 0) {
return GLX_BAD_VALUE;
}
if (gc != NULL && gc->driContext) {
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
- gc->screen );
-
- if ( (psc != NULL) && (psc->driScreen != NULL) ) {
- __GLXDRIdrawable *pdraw =
- GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
- if (psc->swapControl != NULL && pdraw != NULL) {
- psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
- return 0;
- }
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
+ gc->screen);
+
+ if ((psc != NULL) && (psc->driScreen != NULL)) {
+ __GLXDRIdrawable *pdraw =
+ GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
+ if (psc->swapControl != NULL && pdraw != NULL) {
+ psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
+ return 0;
+ }
}
}
#else
@@ -1841,23 +1953,24 @@ static int __glXSwapIntervalMESA(unsigned int interval)
return GLX_BAD_CONTEXT;
}
-
-static int __glXGetSwapIntervalMESA(void)
+
+static int
+__glXGetSwapIntervalMESA(void)
{
#ifdef __DRI_SWAP_CONTROL
GLXContext gc = __glXGetCurrentContext();
if (gc != NULL && gc->driContext) {
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
- gc->screen );
-
- if ( (psc != NULL) && (psc->driScreen != NULL) ) {
- __GLXDRIdrawable *pdraw =
- GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
- if (psc->swapControl != NULL && pdraw != NULL) {
- return psc->swapControl->getSwapInterval(pdraw->driDrawable);
- }
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
+ gc->screen);
+
+ if ((psc != NULL) && (psc->driScreen != NULL)) {
+ __GLXDRIdrawable *pdraw =
+ GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
+ if (psc->swapControl != NULL && pdraw != NULL) {
+ return psc->swapControl->getSwapInterval(pdraw->driDrawable);
+ }
}
}
#endif
@@ -1870,16 +1983,17 @@ static int __glXGetSwapIntervalMESA(void)
** GLX_MESA_swap_frame_usage
*/
-static GLint __glXBeginFrameTrackingMESA(Display *dpy, GLXDrawable drawable)
+static GLint
+__glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
{
- int status = GLX_BAD_CONTEXT;
+ int status = GLX_BAD_CONTEXT;
#ifdef __DRI_FRAME_TRACKING
- int screen;
+ int screen = 0;
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
if (pdraw != NULL && psc->frameTracking != NULL)
- status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE);
+ status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE);
#else
(void) dpy;
(void) drawable;
@@ -1887,18 +2001,19 @@ static GLint __glXBeginFrameTrackingMESA(Display *dpy, GLXDrawable drawable)
return status;
}
-
-static GLint __glXEndFrameTrackingMESA(Display *dpy, GLXDrawable drawable)
+
+static GLint
+__glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
{
- int status = GLX_BAD_CONTEXT;
+ int status = GLX_BAD_CONTEXT;
#ifdef __DRI_FRAME_TRACKING
- int screen;
- __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, & screen);
+ int screen = 0;
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
__GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen);
if (pdraw != NULL && psc->frameTracking != NULL)
- status = psc->frameTracking->frameTracking(pdraw->driDrawable,
- GL_FALSE);
+ status = psc->frameTracking->frameTracking(pdraw->driDrawable,
+ GL_FALSE);
#else
(void) dpy;
(void) drawable;
@@ -1907,24 +2022,24 @@ static GLint __glXEndFrameTrackingMESA(Display *dpy, GLXDrawable drawable)
}
-static GLint __glXGetFrameUsageMESA(Display *dpy, GLXDrawable drawable,
- GLfloat *usage)
+static GLint
+__glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage)
{
- int status = GLX_BAD_CONTEXT;
+ int status = GLX_BAD_CONTEXT;
#ifdef __DRI_FRAME_TRACKING
- int screen;
- __GLXDRIdrawable * const pdraw = GetGLXDRIDrawable(dpy, drawable, & screen);
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
+ int screen = 0;
+ __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
if (pdraw != NULL && psc->frameTracking != NULL) {
- int64_t sbc, missedFrames;
- float lastMissedUsage;
+ int64_t sbc, missedFrames;
+ float lastMissedUsage;
- status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
- &sbc,
- &missedFrames,
- &lastMissedUsage,
- usage);
+ status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
+ &sbc,
+ &missedFrames,
+ &lastMissedUsage,
+ usage);
}
#else
(void) dpy;
@@ -1935,22 +2050,24 @@ static GLint __glXGetFrameUsageMESA(Display *dpy, GLXDrawable drawable,
}
-static GLint __glXQueryFrameTrackingMESA(Display *dpy, GLXDrawable drawable,
- int64_t *sbc, int64_t *missedFrames,
- GLfloat *lastMissedUsage)
+static GLint
+__glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable,
+ int64_t * sbc, int64_t * missedFrames,
+ GLfloat * lastMissedUsage)
{
- int status = GLX_BAD_CONTEXT;
+ int status = GLX_BAD_CONTEXT;
#ifdef __DRI_FRAME_TRACKING
- int screen;
- __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, & screen);
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
+ int screen = 0;
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
if (pdraw != NULL && psc->frameTracking != NULL) {
- float usage;
+ float usage;
status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
- sbc, missedFrames,
- lastMissedUsage, &usage);
+ sbc, missedFrames,
+ lastMissedUsage,
+ &usage);
}
#else
(void) dpy;
@@ -1966,7 +2083,8 @@ static GLint __glXQueryFrameTrackingMESA(Display *dpy, GLXDrawable drawable,
/*
** GLX_SGI_video_sync
*/
-static int __glXGetVideoSyncSGI(unsigned int *count)
+static int
+__glXGetVideoSyncSGI(unsigned int *count)
{
/* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
* FIXME: there should be a GLX encoding for this call. I can find no
@@ -1977,49 +2095,50 @@ static int __glXGetVideoSyncSGI(unsigned int *count)
if (gc != NULL && gc->driContext) {
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
- gc->screen );
- if ( psc->msc && psc->driScreen ) {
- __GLXDRIdrawable *pdraw =
- GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
- int64_t temp;
- int ret;
-
- ret = (*psc->msc->getDrawableMSC)(psc->__driScreen,
- pdraw->driDrawable, &temp);
- *count = (unsigned) temp;
-
- return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
+ gc->screen);
+ if (psc->msc && psc->driScreen) {
+ __GLXDRIdrawable *pdraw =
+ GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
+ int64_t temp;
+ int ret;
+
+ ret = (*psc->msc->getDrawableMSC) (psc->__driScreen,
+ pdraw->driDrawable, &temp);
+ *count = (unsigned) temp;
+
+ return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
}
}
#else
- (void) count;
+ (void) count;
#endif
return GLX_BAD_CONTEXT;
}
-static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
+static int
+__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
{
#ifdef __DRI_MEDIA_STREAM_COUNTER
GLXContext gc = __glXGetCurrentContext();
- if ( divisor <= 0 || remainder < 0 )
- return GLX_BAD_VALUE;
+ if (divisor <= 0 || remainder < 0)
+ return GLX_BAD_VALUE;
if (gc != NULL && gc->driContext) {
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
- gc->screen );
- if (psc->msc != NULL && psc->driScreen ) {
- __GLXDRIdrawable *pdraw =
- GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
- int ret;
- int64_t msc;
- int64_t sbc;
-
- ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0,
- divisor, remainder, &msc, &sbc);
- *count = (unsigned) msc;
- return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
+ gc->screen);
+ if (psc->msc != NULL && psc->driScreen) {
+ __GLXDRIdrawable *pdraw =
+ GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
+ int ret;
+ int64_t msc;
+ int64_t sbc;
+
+ ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, 0,
+ divisor, remainder, &msc, &sbc);
+ *count = (unsigned) msc;
+ return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
}
}
#else
@@ -2035,109 +2154,112 @@ static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count
** GLX_functions table.
*/
-PUBLIC GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
- (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value),
- (dpy, config, attribute, value),
- glXGetFBConfigAttrib)
+PUBLIC
+GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
+ (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
+ (dpy, config, attribute, value), glXGetFBConfigAttrib)
-PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
- (Display *dpy, int screen, int *attrib_list, int *nelements),
- (dpy, screen, attrib_list, nelements),
- glXChooseFBConfig)
+ PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
+ (Display * dpy, int screen, int *attrib_list,
+ int *nelements), (dpy, screen, attrib_list, nelements),
+ glXChooseFBConfig)
-PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
- (Display * dpy, GLXFBConfigSGIX config),
- (dpy, config),
- glXGetVisualFromFBConfig)
+ PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
+ (Display * dpy, GLXFBConfigSGIX config),
+ (dpy, config), glXGetVisualFromFBConfig)
-PUBLIC GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display *dpy,
- GLXFBConfigSGIX config, Pixmap pixmap)
+ PUBLIC GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
+ GLXFBConfigSGIX config,
+ Pixmap pixmap)
{
- xGLXVendorPrivateWithReplyReq *vpreq;
- xGLXCreateGLXPixmapWithConfigSGIXReq *req;
- GLXPixmap xid = None;
- CARD8 opcode;
- const __GLcontextModes * const fbconfig = (__GLcontextModes *) config;
- __GLXscreenConfigs * psc;
+ xGLXVendorPrivateWithReplyReq *vpreq;
+ xGLXCreateGLXPixmapWithConfigSGIXReq *req;
+ GLXPixmap xid = None;
+ CARD8 opcode;
+ const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
+ __GLXscreenConfigs *psc;
- if ( (dpy == NULL) || (config == NULL) ) {
- return None;
- }
+ if ((dpy == NULL) || (config == NULL)) {
+ return None;
+ }
- psc = GetGLXScreenConfigs( dpy, fbconfig->screen );
- if ( (psc != NULL)
- && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) {
- opcode = __glXSetupForCommand(dpy);
- if (!opcode) {
- return None;
- }
+ psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
+ if ((psc != NULL)
+ && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode) {
+ return None;
+ }
- /* Send the glXCreateGLXPixmapWithConfigSGIX request */
- LockDisplay(dpy);
- GetReqExtra(GLXVendorPrivateWithReply,
- sz_xGLXCreateGLXPixmapWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
- req = (xGLXCreateGLXPixmapWithConfigSGIXReq *)vpreq;
- req->reqType = opcode;
- req->glxCode = X_GLXVendorPrivateWithReply;
- req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
- req->screen = fbconfig->screen;
- req->fbconfig = fbconfig->fbconfigID;
- req->pixmap = pixmap;
- req->glxpixmap = xid = XAllocID(dpy);
- UnlockDisplay(dpy);
- SyncHandle();
- }
+ /* Send the glXCreateGLXPixmapWithConfigSGIX request */
+ LockDisplay(dpy);
+ GetReqExtra(GLXVendorPrivateWithReply,
+ sz_xGLXCreateGLXPixmapWithConfigSGIXReq -
+ sz_xGLXVendorPrivateWithReplyReq, vpreq);
+ req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq;
+ req->reqType = opcode;
+ req->glxCode = X_GLXVendorPrivateWithReply;
+ req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
+ req->screen = fbconfig->screen;
+ req->fbconfig = fbconfig->fbconfigID;
+ req->pixmap = pixmap;
+ req->glxpixmap = xid = XAllocID(dpy);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ }
- return xid;
+ return xid;
}
-PUBLIC GLXContext glXCreateContextWithConfigSGIX(Display *dpy,
- GLXFBConfigSGIX config, int renderType,
- GLXContext shareList, Bool allowDirect)
+PUBLIC GLXContext
+glXCreateContextWithConfigSGIX(Display * dpy,
+ GLXFBConfigSGIX config, int renderType,
+ GLXContext shareList, Bool allowDirect)
{
- GLXContext gc = NULL;
- const __GLcontextModes * const fbconfig = (__GLcontextModes *) config;
- __GLXscreenConfigs * psc;
+ GLXContext gc = NULL;
+ const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
+ __GLXscreenConfigs *psc;
- if ( (dpy == NULL) || (config == NULL) ) {
- return None;
- }
+ if ((dpy == NULL) || (config == NULL)) {
+ return None;
+ }
- psc = GetGLXScreenConfigs( dpy, fbconfig->screen );
- if ( (psc != NULL)
- && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) {
- gc = CreateContext( dpy, NULL, (__GLcontextModes *) config, shareList,
- allowDirect, None, False, renderType );
- }
+ psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
+ if ((psc != NULL)
+ && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
+ gc = CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList,
+ allowDirect, None, False, renderType);
+ }
- return gc;
+ return gc;
}
-PUBLIC GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX(Display *dpy,
- XVisualInfo *vis)
+PUBLIC GLXFBConfigSGIX
+glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
{
- __GLXdisplayPrivate *priv;
- __GLXscreenConfigs *psc;
+ __GLXdisplayPrivate *priv;
+ __GLXscreenConfigs *psc = NULL;
- if ( (GetGLXPrivScreenConfig( dpy, vis->screen, & priv, & psc ) != Success)
- && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit )
- && (psc->configs->fbconfigID != GLX_DONT_CARE) ) {
- return (GLXFBConfigSGIX) _gl_context_modes_find_visual( psc->configs,
- vis->visualid );
- }
+ if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success)
+ && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
+ && (psc->configs->fbconfigID != GLX_DONT_CARE)) {
+ return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs,
+ vis->visualid);
+ }
- return NULL;
+ return NULL;
}
/*
** GLX_SGIX_swap_group
*/
-static void __glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable,
- GLXDrawable member)
+static void
+__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable,
+ GLXDrawable member)
{
(void) dpy;
(void) drawable;
@@ -2148,15 +2270,16 @@ static void __glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable,
/*
** GLX_SGIX_swap_barrier
*/
-static void __glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable,
- int barrier)
+static void
+__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier)
{
(void) dpy;
(void) drawable;
(void) barrier;
}
-static Bool __glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
+static Bool
+__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max)
{
(void) dpy;
(void) screen;
@@ -2168,23 +2291,24 @@ static Bool __glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
/*
** GLX_OML_sync_control
*/
-static Bool __glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable,
- int64_t *ust, int64_t *msc, int64_t *sbc)
+static Bool
+__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
+ int64_t * ust, int64_t * msc, int64_t * sbc)
{
#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER)
- __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
-
- if ( priv != NULL ) {
- int i;
- __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &i);
- __GLXscreenConfigs * const psc = &priv->screenConfigs[i];
-
- assert( (pdraw == NULL) || (i != -1) );
- return ( (pdraw && psc->sbc && psc->msc)
- && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0)
- && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0)
- && (__glXGetUST(ust) == 0) );
- }
+ __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
+
+ if (priv != NULL) {
+ int i;
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &i);
+ __GLXscreenConfigs *const psc = &priv->screenConfigs[i];
+
+ assert((pdraw == NULL) || (i != -1));
+ return ((pdraw && psc->sbc && psc->msc)
+ && ((*psc->msc->getMSC) (psc->driScreen, msc) == 0)
+ && ((*psc->sbc->getSBC) (pdraw->driDrawable, sbc) == 0)
+ && (__glXGetUST(ust) == 0));
+ }
#else
(void) dpy;
(void) drawable;
@@ -2197,94 +2321,94 @@ static Bool __glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable,
#ifdef GLX_DIRECT_RENDERING
_X_HIDDEN GLboolean
-__driGetMscRateOML(__DRIdrawable *draw,
- int32_t *numerator, int32_t *denominator, void *private)
+__driGetMscRateOML(__DRIdrawable * draw,
+ int32_t * numerator, int32_t * denominator, void *private)
{
#ifdef XF86VIDMODE
- __GLXscreenConfigs *psc;
- XF86VidModeModeLine mode_line;
- int dot_clock;
- int i;
- __GLXDRIdrawable *glxDraw = private;
-
- psc = glxDraw->psc;
- if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
- XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line) ) {
- unsigned n = dot_clock * 1000;
- unsigned d = mode_line.vtotal * mode_line.htotal;
-
+ __GLXscreenConfigs *psc;
+ XF86VidModeModeLine mode_line;
+ int dot_clock;
+ int i;
+ __GLXDRIdrawable *glxDraw = private;
+
+ psc = glxDraw->psc;
+ if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
+ XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
+ unsigned n = dot_clock * 1000;
+ unsigned d = mode_line.vtotal * mode_line.htotal;
+
# define V_INTERLACE 0x010
# define V_DBLSCAN 0x020
- if (mode_line.flags & V_INTERLACE)
- n *= 2;
- else if (mode_line.flags & V_DBLSCAN)
- d *= 2;
-
- /* The OML_sync_control spec requires that if the refresh rate is a
- * whole number, that the returned numerator be equal to the refresh
- * rate and the denominator be 1.
- */
-
- if (n % d == 0) {
- n /= d;
- d = 1;
- }
- else {
- static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
-
- /* This is a poor man's way to reduce a fraction. It's far from
- * perfect, but it will work well enough for this situation.
- */
-
- for (i = 0; f[i] != 0; i++) {
- while (n % f[i] == 0 && d % f[i] == 0) {
- d /= f[i];
- n /= f[i];
- }
- }
- }
-
- *numerator = n;
- *denominator = d;
-
- return True;
- }
- else
- return False;
+ if (mode_line.flags & V_INTERLACE)
+ n *= 2;
+ else if (mode_line.flags & V_DBLSCAN)
+ d *= 2;
+
+ /* The OML_sync_control spec requires that if the refresh rate is a
+ * whole number, that the returned numerator be equal to the refresh
+ * rate and the denominator be 1.
+ */
+
+ if (n % d == 0) {
+ n /= d;
+ d = 1;
+ }
+ else {
+ static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
+
+ /* This is a poor man's way to reduce a fraction. It's far from
+ * perfect, but it will work well enough for this situation.
+ */
+
+ for (i = 0; f[i] != 0; i++) {
+ while (n % f[i] == 0 && d % f[i] == 0) {
+ d /= f[i];
+ n /= f[i];
+ }
+ }
+ }
+
+ *numerator = n;
+ *denominator = d;
+
+ return True;
+ }
+ else
+ return False;
#else
- return False;
+ return False;
#endif
}
#endif
/**
* Determine the refresh rate of the specified drawable and display.
- *
+ *
* \param dpy Display whose refresh rate is to be determined.
* \param drawable Drawable whose refresh rate is to be determined.
* \param numerator Numerator of the refresh rate.
* \param demoninator Denominator of the refresh rate.
* \return If the refresh rate for the specified display and drawable could
* be calculated, True is returned. Otherwise False is returned.
- *
+ *
* \note This function is implemented entirely client-side. A lot of other
* functionality is required to export GLX_OML_sync_control, so on
* XFree86 this function can be called for direct-rendering contexts
* when GLX_OML_sync_control appears in the client extension string.
*/
-_X_HIDDEN GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
- int32_t * numerator,
- int32_t * denominator)
+_X_HIDDEN GLboolean
+__glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
+ int32_t * numerator, int32_t * denominator)
{
#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE )
- __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL);
+ __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL);
- if (draw == NULL)
- return False;
+ if (draw == NULL)
+ return False;
- return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw);
+ return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw);
#else
(void) dpy;
(void) drawable;
@@ -2295,28 +2419,28 @@ _X_HIDDEN GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
}
-static int64_t __glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable,
- int64_t target_msc, int64_t divisor,
- int64_t remainder)
+static int64_t
+__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable,
+ int64_t target_msc, int64_t divisor, int64_t remainder)
{
#ifdef __DRI_SWAP_BUFFER_COUNTER
int screen;
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
/* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
* error", but it also says "It [glXSwapBuffersMscOML] will return a value
* of -1 if the function failed because of errors detected in the input
* parameters"
*/
- if ( divisor < 0 || remainder < 0 || target_msc < 0 )
+ if (divisor < 0 || remainder < 0 || target_msc < 0)
return -1;
- if ( divisor > 0 && remainder >= divisor )
+ if (divisor > 0 && remainder >= divisor)
return -1;
if (pdraw != NULL && psc->counters != NULL)
- return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc,
- divisor, remainder);
+ return (*psc->sbc->swapBuffersMSC) (pdraw->driDrawable, target_msc,
+ divisor, remainder);
#else
(void) dpy;
@@ -2329,33 +2453,34 @@ static int64_t __glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable,
}
-static Bool __glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
- int64_t target_msc, int64_t divisor,
- int64_t remainder, int64_t *ust,
- int64_t *msc, int64_t *sbc)
+static Bool
+__glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
+ int64_t target_msc, int64_t divisor,
+ int64_t remainder, int64_t * ust,
+ int64_t * msc, int64_t * sbc)
{
#ifdef __DRI_MEDIA_STREAM_COUNTER
- int screen;
+ int screen = 0;
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
- int ret;
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+ int ret;
/* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
* error", but the return type in the spec is Bool.
*/
- if ( divisor < 0 || remainder < 0 || target_msc < 0 )
+ if (divisor < 0 || remainder < 0 || target_msc < 0)
return False;
- if ( divisor > 0 && remainder >= divisor )
+ if (divisor > 0 && remainder >= divisor)
return False;
if (pdraw != NULL && psc->msc != NULL) {
- ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, target_msc,
- divisor, remainder, msc, sbc);
+ ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc,
+ divisor, remainder, msc, sbc);
/* __glXGetUST returns zero on success and non-zero on failure.
* This function returns True on success and False on failure.
*/
- return ( (ret == 0) && (__glXGetUST( ust ) == 0) );
+ return ((ret == 0) && (__glXGetUST(ust) == 0));
}
#else
(void) dpy;
@@ -2371,29 +2496,31 @@ static Bool __glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
}
-static Bool __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
- int64_t target_sbc, int64_t *ust,
- int64_t *msc, int64_t *sbc )
+static Bool
+__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
+ int64_t target_sbc, int64_t * ust,
+ int64_t * msc, int64_t * sbc)
{
#ifdef __DRI_SWAP_BUFFER_COUNTER
int screen;
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
- int ret;
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+ int ret;
/* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
* error", but the return type in the spec is Bool.
*/
- if ( target_sbc < 0 )
+ if (target_sbc < 0)
return False;
if (pdraw != NULL && psc->sbc != NULL) {
- ret = (*psc->sbc->waitForSBC)(pdraw->driDrawable, target_sbc, msc, sbc);
+ ret =
+ (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc);
/* __glXGetUST returns zero on success and non-zero on failure.
* This function returns True on success and False on failure.
*/
- return( (ret == 0) && (__glXGetUST( ust ) == 0) );
+ return ((ret == 0) && (__glXGetUST(ust) == 0));
}
#else
(void) dpy;
@@ -2412,16 +2539,17 @@ static Bool __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
*/
/*@{*/
-PUBLIC void *glXAllocateMemoryMESA(Display *dpy, int scrn,
- size_t size, float readFreq,
- float writeFreq, float priority)
+PUBLIC void *
+glXAllocateMemoryMESA(Display * dpy, int scrn,
+ size_t size, float readFreq,
+ float writeFreq, float priority)
{
#ifdef __DRI_ALLOCATE
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn );
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
if (psc && psc->allocate)
- return (*psc->allocate->allocateMemory)(psc->__driScreen, size,
- readFreq, writeFreq, priority);
+ return (*psc->allocate->allocateMemory) (psc->__driScreen, size,
+ readFreq, writeFreq, priority);
#else
(void) dpy;
@@ -2436,13 +2564,14 @@ PUBLIC void *glXAllocateMemoryMESA(Display *dpy, int scrn,
}
-PUBLIC void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer)
+PUBLIC void
+glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer)
{
#ifdef __DRI_ALLOCATE
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn );
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
if (psc && psc->allocate)
- (*psc->allocate->freeMemory)(psc->__driScreen, pointer);
+ (*psc->allocate->freeMemory) (psc->__driScreen, pointer);
#else
(void) dpy;
@@ -2452,14 +2581,14 @@ PUBLIC void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer)
}
-PUBLIC GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn,
- const void *pointer )
+PUBLIC GLuint
+glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer)
{
#ifdef __DRI_ALLOCATE
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn );
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
if (psc && psc->allocate)
- return (*psc->allocate->memoryOffset)(psc->__driScreen, pointer);
+ return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer);
#else
(void) dpy;
@@ -2469,6 +2598,7 @@ PUBLIC GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn,
return ~0L;
}
+
/*@}*/
@@ -2499,7 +2629,8 @@ PUBLIC GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn,
* glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
* glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
*/
-static Bool __glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
+static Bool
+__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
{
(void) dpy;
(void) d;
@@ -2507,8 +2638,9 @@ static Bool __glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
}
-PUBLIC GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual,
- Pixmap pixmap, Colormap cmap )
+PUBLIC GLXPixmap
+glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
+ Pixmap pixmap, Colormap cmap)
{
(void) dpy;
(void) visual;
@@ -2516,6 +2648,7 @@ PUBLIC GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual,
(void) cmap;
return 0;
}
+
/*@}*/
@@ -2523,68 +2656,70 @@ PUBLIC GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual,
* GLX_MESA_copy_sub_buffer
*/
#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
-static void __glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
- int x, int y, int width, int height)
+static void
+__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable,
+ int x, int y, int width, int height)
{
- xGLXVendorPrivateReq *req;
- GLXContext gc;
- GLXContextTag tag;
- CARD32 *drawable_ptr;
- INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
- CARD8 opcode;
+ xGLXVendorPrivateReq *req;
+ GLXContext gc;
+ GLXContextTag tag;
+ CARD32 *drawable_ptr;
+ INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
+ CARD8 opcode;
#ifdef __DRI_COPY_SUB_BUFFER
- int screen;
- __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
- if ( pdraw != NULL ) {
- __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
- if (psc->driScreen->copySubBuffer != NULL) {
- glFlush();
- (*psc->driScreen->copySubBuffer)(pdraw, x, y, width, height);
- }
-
- return;
- }
+ int screen;
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
+ if (pdraw != NULL) {
+ __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
+ if (psc->driScreen->copySubBuffer != NULL) {
+ glFlush();
+ (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height);
+ }
+
+ return;
+ }
#endif
- opcode = __glXSetupForCommand(dpy);
- if (!opcode)
- return;
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode)
+ return;
- /*
+ /*
** The calling thread may or may not have a current context. If it
** does, send the context tag so the server can do a flush.
*/
- gc = __glXGetCurrentContext();
- if ((gc != NULL) && (dpy == gc->currentDpy) &&
- ((drawable == gc->currentDrawable) ||
- (drawable == gc->currentReadable)) ) {
- tag = gc->currentContextTag;
- } else {
- tag = 0;
- }
-
- LockDisplay(dpy);
- GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4,req);
- req->reqType = opcode;
- req->glxCode = X_GLXVendorPrivate;
- req->vendorCode = X_GLXvop_CopySubBufferMESA;
- req->contextTag = tag;
-
- drawable_ptr = (CARD32 *) (req + 1);
- x_ptr = (INT32 *) (drawable_ptr + 1);
- y_ptr = (INT32 *) (drawable_ptr + 2);
- w_ptr = (INT32 *) (drawable_ptr + 3);
- h_ptr = (INT32 *) (drawable_ptr + 4);
-
- *drawable_ptr = drawable;
- *x_ptr = x;
- *y_ptr = y;
- *w_ptr = width;
- *h_ptr = height;
-
- UnlockDisplay(dpy);
- SyncHandle();
+ gc = __glXGetCurrentContext();
+ if ((gc != NULL) && (dpy == gc->currentDpy) &&
+ ((drawable == gc->currentDrawable) ||
+ (drawable == gc->currentReadable))) {
+ tag = gc->currentContextTag;
+ }
+ else {
+ tag = 0;
+ }
+
+ LockDisplay(dpy);
+ GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXVendorPrivate;
+ req->vendorCode = X_GLXvop_CopySubBufferMESA;
+ req->contextTag = tag;
+
+ drawable_ptr = (CARD32 *) (req + 1);
+ x_ptr = (INT32 *) (drawable_ptr + 1);
+ y_ptr = (INT32 *) (drawable_ptr + 2);
+ w_ptr = (INT32 *) (drawable_ptr + 3);
+ h_ptr = (INT32 *) (drawable_ptr + 4);
+
+ *drawable_ptr = drawable;
+ *x_ptr = x;
+ *y_ptr = y;
+ *w_ptr = width;
+ *h_ptr = height;
+
+ UnlockDisplay(dpy);
+ SyncHandle();
}
@@ -2592,120 +2727,127 @@ static void __glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
* GLX_EXT_texture_from_pixmap
*/
/*@{*/
-static void __glXBindTexImageEXT(Display *dpy,
- GLXDrawable drawable,
- int buffer,
- const int *attrib_list)
-{
- xGLXVendorPrivateReq *req;
- GLXContext gc = __glXGetCurrentContext();
- CARD32 *drawable_ptr;
- INT32 *buffer_ptr;
- CARD32 *num_attrib_ptr;
- CARD32 *attrib_ptr;
- CARD8 opcode;
- unsigned int i;
-
- if (gc == NULL)
- return;
-
- i = 0;
- if (attrib_list) {
- while (attrib_list[i * 2] != None)
- i++;
- }
-
-#ifdef GLX_DIRECT_RENDERING
- if (gc->driContext) {
- __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
+static void
+__glXBindTexImageEXT(Display * dpy,
+ GLXDrawable drawable, int buffer, const int *attrib_list)
+{
+ xGLXVendorPrivateReq *req;
+ GLXContext gc = __glXGetCurrentContext();
+ CARD32 *drawable_ptr;
+ INT32 *buffer_ptr;
+ CARD32 *num_attrib_ptr;
+ CARD32 *attrib_ptr;
+ CARD8 opcode;
+ unsigned int i;
- if (pdraw != NULL)
- (*pdraw->psc->texBuffer->setTexBuffer)(gc->__driContext,
- pdraw->textureTarget,
- pdraw->driDrawable);
+ if (gc == NULL)
+ return;
+
+ i = 0;
+ if (attrib_list) {
+ while (attrib_list[i * 2] != None)
+ i++;
+ }
- return;
- }
+#ifdef GLX_DIRECT_RENDERING
+ if (gc->driContext) {
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
+
+ if (pdraw != NULL) {
+ if (pdraw->psc->texBuffer->base.version >= 2 &&
+ pdraw->psc->texBuffer->setTexBuffer2 != NULL) {
+ (*pdraw->psc->texBuffer->setTexBuffer2) (gc->__driContext,
+ pdraw->textureTarget,
+ pdraw->textureFormat,
+ pdraw->driDrawable);
+ }
+ else {
+ (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext,
+ pdraw->textureTarget,
+ pdraw->driDrawable);
+ }
+ }
+ return;
+ }
#endif
- opcode = __glXSetupForCommand(dpy);
- if (!opcode)
- return;
-
- LockDisplay(dpy);
- GetReqExtra(GLXVendorPrivate, 12 + 8 * i,req);
- req->reqType = opcode;
- req->glxCode = X_GLXVendorPrivate;
- req->vendorCode = X_GLXvop_BindTexImageEXT;
- req->contextTag = gc->currentContextTag;
-
- drawable_ptr = (CARD32 *) (req + 1);
- buffer_ptr = (INT32 *) (drawable_ptr + 1);
- num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
- attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
-
- *drawable_ptr = drawable;
- *buffer_ptr = buffer;
- *num_attrib_ptr = (CARD32) i;
-
- i = 0;
- if (attrib_list) {
- while (attrib_list[i * 2] != None)
- {
- *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
- *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
- i++;
- }
- }
-
- UnlockDisplay(dpy);
- SyncHandle();
-}
-
-static void __glXReleaseTexImageEXT(Display *dpy,
- GLXDrawable drawable,
- int buffer)
-{
- xGLXVendorPrivateReq *req;
- GLXContext gc = __glXGetCurrentContext();
- CARD32 *drawable_ptr;
- INT32 *buffer_ptr;
- CARD8 opcode;
-
- if (gc == NULL)
- return;
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode)
+ return;
+
+ LockDisplay(dpy);
+ GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXVendorPrivate;
+ req->vendorCode = X_GLXvop_BindTexImageEXT;
+ req->contextTag = gc->currentContextTag;
+
+ drawable_ptr = (CARD32 *) (req + 1);
+ buffer_ptr = (INT32 *) (drawable_ptr + 1);
+ num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
+ attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
+
+ *drawable_ptr = drawable;
+ *buffer_ptr = buffer;
+ *num_attrib_ptr = (CARD32) i;
+
+ i = 0;
+ if (attrib_list) {
+ while (attrib_list[i * 2] != None) {
+ *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
+ *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
+ i++;
+ }
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+}
+
+static void
+__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer)
+{
+ xGLXVendorPrivateReq *req;
+ GLXContext gc = __glXGetCurrentContext();
+ CARD32 *drawable_ptr;
+ INT32 *buffer_ptr;
+ CARD8 opcode;
+
+ if (gc == NULL)
+ return;
#ifdef GLX_DIRECT_RENDERING
- if (gc->driContext)
- return;
+ if (gc->driContext)
+ return;
#endif
- opcode = __glXSetupForCommand(dpy);
- if (!opcode)
- return;
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode)
+ return;
- LockDisplay(dpy);
- GetReqExtra(GLXVendorPrivate, sizeof(CARD32)+sizeof(INT32),req);
- req->reqType = opcode;
- req->glxCode = X_GLXVendorPrivate;
- req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
- req->contextTag = gc->currentContextTag;
+ LockDisplay(dpy);
+ GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXVendorPrivate;
+ req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
+ req->contextTag = gc->currentContextTag;
- drawable_ptr = (CARD32 *) (req + 1);
- buffer_ptr = (INT32 *) (drawable_ptr + 1);
+ drawable_ptr = (CARD32 *) (req + 1);
+ buffer_ptr = (INT32 *) (drawable_ptr + 1);
- *drawable_ptr = drawable;
- *buffer_ptr = buffer;
+ *drawable_ptr = drawable;
+ *buffer_ptr = buffer;
- UnlockDisplay(dpy);
- SyncHandle();
+ UnlockDisplay(dpy);
+ SyncHandle();
}
+
/*@}*/
/**
* \c strdup is actually not a standard ANSI C or POSIX routine.
* Irix will not define it if ANSI mode is in effect.
- *
+ *
* \sa strdup
*/
_X_HIDDEN char *
@@ -2723,7 +2865,8 @@ __glXstrdup(const char *str)
** glXGetProcAddress support
*/
-struct name_address_pair {
+struct name_address_pair
+{
const char *Name;
GLvoid *Address;
};
@@ -2733,139 +2876,139 @@ struct name_address_pair {
static const struct name_address_pair GLX_functions[] = {
/*** GLX_VERSION_1_0 ***/
- GLX_FUNCTION( glXChooseVisual ),
- GLX_FUNCTION( glXCopyContext ),
- GLX_FUNCTION( glXCreateContext ),
- GLX_FUNCTION( glXCreateGLXPixmap ),
- GLX_FUNCTION( glXDestroyContext ),
- GLX_FUNCTION( glXDestroyGLXPixmap ),
- GLX_FUNCTION( glXGetConfig ),
- GLX_FUNCTION( glXGetCurrentContext ),
- GLX_FUNCTION( glXGetCurrentDrawable ),
- GLX_FUNCTION( glXIsDirect ),
- GLX_FUNCTION( glXMakeCurrent ),
- GLX_FUNCTION( glXQueryExtension ),
- GLX_FUNCTION( glXQueryVersion ),
- GLX_FUNCTION( glXSwapBuffers ),
- GLX_FUNCTION( glXUseXFont ),
- GLX_FUNCTION( glXWaitGL ),
- GLX_FUNCTION( glXWaitX ),
+ GLX_FUNCTION(glXChooseVisual),
+ GLX_FUNCTION(glXCopyContext),
+ GLX_FUNCTION(glXCreateContext),
+ GLX_FUNCTION(glXCreateGLXPixmap),
+ GLX_FUNCTION(glXDestroyContext),
+ GLX_FUNCTION(glXDestroyGLXPixmap),
+ GLX_FUNCTION(glXGetConfig),
+ GLX_FUNCTION(glXGetCurrentContext),
+ GLX_FUNCTION(glXGetCurrentDrawable),
+ GLX_FUNCTION(glXIsDirect),
+ GLX_FUNCTION(glXMakeCurrent),
+ GLX_FUNCTION(glXQueryExtension),
+ GLX_FUNCTION(glXQueryVersion),
+ GLX_FUNCTION(glXSwapBuffers),
+ GLX_FUNCTION(glXUseXFont),
+ GLX_FUNCTION(glXWaitGL),
+ GLX_FUNCTION(glXWaitX),
/*** GLX_VERSION_1_1 ***/
- GLX_FUNCTION( glXGetClientString ),
- GLX_FUNCTION( glXQueryExtensionsString ),
- GLX_FUNCTION( glXQueryServerString ),
+ GLX_FUNCTION(glXGetClientString),
+ GLX_FUNCTION(glXQueryExtensionsString),
+ GLX_FUNCTION(glXQueryServerString),
/*** GLX_VERSION_1_2 ***/
- GLX_FUNCTION( glXGetCurrentDisplay ),
+ GLX_FUNCTION(glXGetCurrentDisplay),
/*** GLX_VERSION_1_3 ***/
- GLX_FUNCTION( glXChooseFBConfig ),
- GLX_FUNCTION( glXCreateNewContext ),
- GLX_FUNCTION( glXCreatePbuffer ),
- GLX_FUNCTION( glXCreatePixmap ),
- GLX_FUNCTION( glXCreateWindow ),
- GLX_FUNCTION( glXDestroyPbuffer ),
- GLX_FUNCTION( glXDestroyPixmap ),
- GLX_FUNCTION( glXDestroyWindow ),
- GLX_FUNCTION( glXGetCurrentReadDrawable ),
- GLX_FUNCTION( glXGetFBConfigAttrib ),
- GLX_FUNCTION( glXGetFBConfigs ),
- GLX_FUNCTION( glXGetSelectedEvent ),
- GLX_FUNCTION( glXGetVisualFromFBConfig ),
- GLX_FUNCTION( glXMakeContextCurrent ),
- GLX_FUNCTION( glXQueryContext ),
- GLX_FUNCTION( glXQueryDrawable ),
- GLX_FUNCTION( glXSelectEvent ),
+ GLX_FUNCTION(glXChooseFBConfig),
+ GLX_FUNCTION(glXCreateNewContext),
+ GLX_FUNCTION(glXCreatePbuffer),
+ GLX_FUNCTION(glXCreatePixmap),
+ GLX_FUNCTION(glXCreateWindow),
+ GLX_FUNCTION(glXDestroyPbuffer),
+ GLX_FUNCTION(glXDestroyPixmap),
+ GLX_FUNCTION(glXDestroyWindow),
+ GLX_FUNCTION(glXGetCurrentReadDrawable),
+ GLX_FUNCTION(glXGetFBConfigAttrib),
+ GLX_FUNCTION(glXGetFBConfigs),
+ GLX_FUNCTION(glXGetSelectedEvent),
+ GLX_FUNCTION(glXGetVisualFromFBConfig),
+ GLX_FUNCTION(glXMakeContextCurrent),
+ GLX_FUNCTION(glXQueryContext),
+ GLX_FUNCTION(glXQueryDrawable),
+ GLX_FUNCTION(glXSelectEvent),
/*** GLX_SGI_swap_control ***/
- GLX_FUNCTION2( glXSwapIntervalSGI, __glXSwapIntervalSGI ),
+ GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI),
/*** GLX_SGI_video_sync ***/
- GLX_FUNCTION2( glXGetVideoSyncSGI, __glXGetVideoSyncSGI ),
- GLX_FUNCTION2( glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI ),
+ GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI),
+ GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI),
/*** GLX_SGI_make_current_read ***/
- GLX_FUNCTION2( glXMakeCurrentReadSGI, glXMakeContextCurrent ),
- GLX_FUNCTION2( glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable ),
+ GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent),
+ GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable),
/*** GLX_EXT_import_context ***/
- GLX_FUNCTION( glXFreeContextEXT ),
- GLX_FUNCTION( glXGetContextIDEXT ),
- GLX_FUNCTION2( glXGetCurrentDisplayEXT, glXGetCurrentDisplay ),
- GLX_FUNCTION( glXImportContextEXT ),
- GLX_FUNCTION2( glXQueryContextInfoEXT, glXQueryContext ),
+ GLX_FUNCTION(glXFreeContextEXT),
+ GLX_FUNCTION(glXGetContextIDEXT),
+ GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay),
+ GLX_FUNCTION(glXImportContextEXT),
+ GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext),
/*** GLX_SGIX_fbconfig ***/
- GLX_FUNCTION2( glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib ),
- GLX_FUNCTION2( glXChooseFBConfigSGIX, glXChooseFBConfig ),
- GLX_FUNCTION( glXCreateGLXPixmapWithConfigSGIX ),
- GLX_FUNCTION( glXCreateContextWithConfigSGIX ),
- GLX_FUNCTION2( glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig ),
- GLX_FUNCTION( glXGetFBConfigFromVisualSGIX ),
+ GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib),
+ GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig),
+ GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX),
+ GLX_FUNCTION(glXCreateContextWithConfigSGIX),
+ GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig),
+ GLX_FUNCTION(glXGetFBConfigFromVisualSGIX),
/*** GLX_SGIX_pbuffer ***/
- GLX_FUNCTION( glXCreateGLXPbufferSGIX ),
- GLX_FUNCTION( glXDestroyGLXPbufferSGIX ),
- GLX_FUNCTION( glXQueryGLXPbufferSGIX ),
- GLX_FUNCTION( glXSelectEventSGIX ),
- GLX_FUNCTION( glXGetSelectedEventSGIX ),
+ GLX_FUNCTION(glXCreateGLXPbufferSGIX),
+ GLX_FUNCTION(glXDestroyGLXPbufferSGIX),
+ GLX_FUNCTION(glXQueryGLXPbufferSGIX),
+ GLX_FUNCTION(glXSelectEventSGIX),
+ GLX_FUNCTION(glXGetSelectedEventSGIX),
/*** GLX_SGIX_swap_group ***/
- GLX_FUNCTION2( glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX ),
+ GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX),
/*** GLX_SGIX_swap_barrier ***/
- GLX_FUNCTION2( glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX ),
- GLX_FUNCTION2( glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX ),
+ GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX),
+ GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX),
/*** GLX_MESA_allocate_memory ***/
- GLX_FUNCTION( glXAllocateMemoryMESA ),
- GLX_FUNCTION( glXFreeMemoryMESA ),
- GLX_FUNCTION( glXGetMemoryOffsetMESA ),
+ GLX_FUNCTION(glXAllocateMemoryMESA),
+ GLX_FUNCTION(glXFreeMemoryMESA),
+ GLX_FUNCTION(glXGetMemoryOffsetMESA),
/*** GLX_MESA_copy_sub_buffer ***/
- GLX_FUNCTION2( glXCopySubBufferMESA, __glXCopySubBufferMESA ),
+ GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA),
/*** GLX_MESA_pixmap_colormap ***/
- GLX_FUNCTION( glXCreateGLXPixmapMESA ),
+ GLX_FUNCTION(glXCreateGLXPixmapMESA),
/*** GLX_MESA_release_buffers ***/
- GLX_FUNCTION2( glXReleaseBuffersMESA, __glXReleaseBuffersMESA ),
+ GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA),
/*** GLX_MESA_swap_control ***/
- GLX_FUNCTION2( glXSwapIntervalMESA, __glXSwapIntervalMESA ),
- GLX_FUNCTION2( glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA ),
+ GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA),
+ GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA),
/*** GLX_MESA_swap_frame_usage ***/
- GLX_FUNCTION2( glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA ),
- GLX_FUNCTION2( glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA ),
- GLX_FUNCTION2( glXGetFrameUsageMESA, __glXGetFrameUsageMESA ),
- GLX_FUNCTION2( glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA ),
+ GLX_FUNCTION2(glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA),
+ GLX_FUNCTION2(glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA),
+ GLX_FUNCTION2(glXGetFrameUsageMESA, __glXGetFrameUsageMESA),
+ GLX_FUNCTION2(glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA),
/*** GLX_ARB_get_proc_address ***/
- GLX_FUNCTION( glXGetProcAddressARB ),
+ GLX_FUNCTION(glXGetProcAddressARB),
/*** GLX 1.4 ***/
- GLX_FUNCTION2( glXGetProcAddress, glXGetProcAddressARB ),
+ GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB),
/*** GLX_OML_sync_control ***/
- GLX_FUNCTION2( glXWaitForSbcOML, __glXWaitForSbcOML ),
- GLX_FUNCTION2( glXWaitForMscOML, __glXWaitForMscOML ),
- GLX_FUNCTION2( glXSwapBuffersMscOML, __glXSwapBuffersMscOML ),
- GLX_FUNCTION2( glXGetMscRateOML, __glXGetMscRateOML ),
- GLX_FUNCTION2( glXGetSyncValuesOML, __glXGetSyncValuesOML ),
+ GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML),
+ GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML),
+ GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML),
+ GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML),
+ GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML),
/*** GLX_EXT_texture_from_pixmap ***/
- GLX_FUNCTION2( glXBindTexImageEXT, __glXBindTexImageEXT ),
- GLX_FUNCTION2( glXReleaseTexImageEXT, __glXReleaseTexImageEXT ),
+ GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT),
+ GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT),
#ifdef GLX_DIRECT_RENDERING
/*** DRI configuration ***/
- GLX_FUNCTION( glXGetScreenDriver ),
- GLX_FUNCTION( glXGetDriverConfig ),
+ GLX_FUNCTION(glXGetScreenDriver),
+ GLX_FUNCTION(glXGetDriverConfig),
#endif
- { NULL, NULL } /* end of list */
+ {NULL, NULL} /* end of list */
};
@@ -2877,7 +3020,7 @@ get_glx_proc_address(const char *funcName)
/* try static functions */
for (i = 0; GLX_functions[i].Name; i++) {
if (strcmp(GLX_functions[i].Name, funcName) == 0)
- return GLX_functions[i].Address;
+ return GLX_functions[i].Address;
}
return NULL;
@@ -2893,9 +3036,9 @@ get_glx_proc_address(const char *funcName)
*
* \sa glXGetProcAddress
*/
-PUBLIC void (*glXGetProcAddressARB(const GLubyte *procName))( void )
+PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
{
- typedef void (*gl_function)( void );
+ typedef void (*gl_function) (void);
gl_function f;
@@ -2907,8 +3050,8 @@ PUBLIC void (*glXGetProcAddressARB(const GLubyte *procName))( void )
*/
f = (gl_function) get_glx_proc_address((const char *) procName);
- if ( (f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
- && (procName[2] != 'X') ) {
+ if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
+ && (procName[2] != 'X')) {
f = (gl_function) _glapi_get_proc_address((const char *) procName);
}
@@ -2924,9 +3067,9 @@ PUBLIC void (*glXGetProcAddressARB(const GLubyte *procName))( void )
*
* \sa glXGetProcAddressARB
*/
-PUBLIC void (*glXGetProcAddress(const GLubyte *procName))( void )
+PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void)
#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
- __attribute__ ((alias ("glXGetProcAddressARB")));
+ __attribute__ ((alias("glXGetProcAddressARB")));
#else
{
return glXGetProcAddressARB(procName);
@@ -2944,24 +3087,26 @@ PUBLIC void (*glXGetProcAddress(const GLubyte *procName))( void )
*
* \param ust Location to store the 64-bit UST
* \returns Zero on success or a negative errno value on failure.
- *
+ *
* \sa glXGetProcAddress, PFNGLXGETUSTPROC
*
* \since Internal API version 20030317.
*/
-_X_HIDDEN int __glXGetUST( int64_t * ust )
-{
- struct timeval tv;
-
- if ( ust == NULL ) {
- return -EFAULT;
- }
-
- if ( gettimeofday( & tv, NULL ) == 0 ) {
- ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
- return 0;
- } else {
- return -errno;
- }
+_X_HIDDEN int
+__glXGetUST(int64_t * ust)
+{
+ struct timeval tv;
+
+ if (ust == NULL) {
+ return -EFAULT;
+ }
+
+ if (gettimeofday(&tv, NULL) == 0) {
+ ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
+ return 0;
+ }
+ else {
+ return -errno;
+ }
}
#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/x11/glxcurrent.c b/src/glx/x11/glxcurrent.c
index 4d0a7c65eb..f1e3e161be 100644
--- a/src/glx/x11/glxcurrent.c
+++ b/src/glx/x11/glxcurrent.c
@@ -73,45 +73,7 @@ static __GLapi *IndirectAPI = NULL;
* Current context management and locking
*/
-#if defined( USE_XTHREADS )
-
-/* thread safe */
-static GLboolean TSDinitialized = GL_FALSE;
-static xthread_key_t ContextTSD;
-
-_X_HIDDEN __GLXcontext *
-__glXGetCurrentContext(void)
-{
- if (!TSDinitialized) {
- xthread_key_create(&ContextTSD, NULL);
- TSDinitialized = GL_TRUE;
- return &dummyContext;
- }
- else {
- void *p;
- xthread_get_specific(ContextTSD, &p);
- if (!p)
- return &dummyContext;
- else
- return (__GLXcontext *) p;
- }
-}
-
-_X_HIDDEN void
-__glXSetCurrentContext(__GLXcontext * c)
-{
- if (!TSDinitialized) {
- xthread_key_create(&ContextTSD, NULL);
- TSDinitialized = GL_TRUE;
- }
- xthread_set_specific(ContextTSD, c);
-}
-
-
-/* Used by the __glXLock() and __glXUnlock() macros */
-_X_HIDDEN xmutex_rec __glXmutex;
-
-#elif defined( PTHREADS )
+#if defined( PTHREADS )
_X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
@@ -119,7 +81,7 @@ _X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
/**
* Per-thread GLX context pointer.
- *
+ *
* \c __glXSetCurrentContext is written is such a way that this pointer can
* \b never be \c NULL. This is important! Because of this
* \c __glXGetCurrentContext can be implemented as trivial macro.
@@ -139,7 +101,7 @@ static pthread_once_t once_control = PTHREAD_ONCE_INIT;
/**
* Per-thread data key.
- *
+ *
* Once \c init_thread_data has been called, the per-thread data key will
* take a value of \c NULL. As each new thread is created the default
* value, in that thread, will be \c NULL.
@@ -148,7 +110,7 @@ static pthread_key_t ContextTSD;
/**
* Initialize the per-thread data key.
- *
+ *
* This function is called \b exactly once per-process (not per-thread!) to
* initialize the per-thread data key. This is ideally done using the
* \c pthread_once mechanism.
@@ -339,10 +301,24 @@ FetchDRIDrawable(Display * dpy, GLXDrawable glxDrawable, GLXContext gc)
}
#endif /* GLX_DIRECT_RENDERING */
+static void
+__glXGenerateError(Display * dpy, GLXContext gc, XID resource,
+ BYTE errorCode, CARD16 minorCode)
+{
+ xError error;
+
+ error.errorCode = errorCode;
+ error.resourceID = resource;
+ error.sequenceNumber = dpy->request;
+ error.type = X_Error;
+ error.majorCode = gc->majorOpcode;
+ error.minorCode = minorCode;
+ _XError(dpy, &error);
+}
/**
* Make a particular context current.
- *
+ *
* \note This is in this file so that it can access dummyContext.
*/
static Bool
@@ -369,8 +345,24 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
return GL_FALSE;
}
+ if (gc == NULL && (draw != None || read != None)) {
+ __glXGenerateError(dpy, gc, (draw != None) ? draw : read,
+ BadMatch, X_GLXMakeContextCurrent);
+ return False;
+ }
+ if (gc != NULL && (draw == None || read == None)) {
+ __glXGenerateError(dpy, gc, None, BadMatch, X_GLXMakeContextCurrent);
+ return False;
+ }
+
_glapi_check_multithread();
+ if (gc != NULL && gc->thread_id != 0 && gc->thread_id != _glthread_GetID()) {
+ __glXGenerateError(dpy, gc, gc->xid,
+ BadAccess, X_GLXMakeContextCurrent);
+ return False;
+ }
+
#ifdef GLX_DIRECT_RENDERING
/* Bind the direct rendering context to the drawable */
if (gc && gc->driContext) {
@@ -378,21 +370,17 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
__GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc);
if ((pdraw == NULL) || (pread == NULL)) {
- xError error;
-
- error.errorCode = GLXBadDrawable;
- error.resourceID = (pdraw == NULL) ? draw : read;
- error.sequenceNumber = dpy->request;
- error.type = X_Error;
- error.majorCode = gc->majorOpcode;
- error.minorCode = X_GLXMakeContextCurrent;
- _XError(dpy, &error);
+ __glXGenerateError(dpy, gc, (pdraw == NULL) ? draw : read,
+ GLXBadDrawable, X_GLXMakeContextCurrent);
return False;
}
bindReturnValue =
(gc->driContext->bindContext) (gc->driContext, pdraw, pread);
}
+ else if (!gc && oldGC && oldGC->driContext) {
+ bindReturnValue = True;
+ }
else
#endif
{
@@ -429,7 +417,7 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
&dummy_reply);
}
#ifdef GLX_DIRECT_RENDERING
- else if (oldGC->driContext) {
+ else if (oldGC->driContext && oldGC != gc) {
oldGC->driContext->unbindContext(oldGC->driContext);
}
#endif
@@ -453,6 +441,7 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
oldGC->currentDrawable = None;
oldGC->currentReadable = None;
oldGC->currentContextTag = 0;
+ oldGC->thread_id = 0;
if (oldGC->xid == None) {
/* We are switching away from a context that was
@@ -477,6 +466,7 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
gc->currentDpy = dpy;
gc->currentDrawable = draw;
gc->currentReadable = read;
+ gc->thread_id = _glthread_GetID();
#ifdef GLX_DIRECT_RENDERING
if (!gc->driContext) {
@@ -529,6 +519,5 @@ GLX_ALIAS(Bool, glXMakeCurrentReadSGI,
PUBLIC
GLX_ALIAS(Bool, glXMakeContextCurrent,
- (Display * dpy, GLXDrawable d, GLXDrawable r,
- GLXContext ctx), (dpy, d, r, ctx),
- MakeContextCurrent)
+ (Display * dpy, GLXDrawable d, GLXDrawable r,
+ GLXContext ctx), (dpy, d, r, ctx), MakeContextCurrent)
diff --git a/src/glx/x11/glxext.c b/src/glx/x11/glxext.c
index be6edf9b19..e5553cbf76 100644
--- a/src/glx/x11/glxext.c
+++ b/src/glx/x11/glxext.c
@@ -56,19 +56,6 @@
void __glXDumpDrawBuffer(__GLXcontext * ctx);
#endif
-#ifdef USE_SPARC_ASM
-static void _glx_mesa_init_sparc_glapi_relocs(void);
-static int _mesa_sparc_needs_init = 1;
-#define INIT_MESA_SPARC do { \
- if (_mesa_sparc_needs_init) { \
- _glx_mesa_init_sparc_glapi_relocs(); \
- _mesa_sparc_needs_init = 0; \
- } \
- } while(0)
-#else
-#define INIT_MESA_SPARC do { } while(0)
-#endif
-
/*
** You can set this cell to 1 to force the gl drawing stuff to be
** one command per packet
@@ -115,19 +102,19 @@ static
XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
__GLX_NUMBER_ERRORS, error_list)
- static /* const */ XExtensionHooks __glXExtensionHooks = {
- NULL, /* create_gc */
- NULL, /* copy_gc */
- NULL, /* flush_gc */
- NULL, /* free_gc */
- NULL, /* create_font */
- NULL, /* free_font */
- __glXCloseDisplay, /* close_display */
- NULL, /* wire_to_event */
- NULL, /* event_to_wire */
- NULL, /* error */
- __glXErrorString, /* error_string */
- };
+static /* const */ XExtensionHooks __glXExtensionHooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ __glXCloseDisplay, /* close_display */
+ NULL, /* wire_to_event */
+ NULL, /* event_to_wire */
+ NULL, /* error */
+ __glXErrorString, /* error_string */
+};
static
XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
@@ -162,6 +149,12 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv)
Xfree((char *) psc->serverGLXexts);
#ifdef GLX_DIRECT_RENDERING
+ if (psc->driver_configs) {
+ for (unsigned int i = 0; psc->driver_configs[i]; i++)
+ free((__DRIconfig *) psc->driver_configs[i]);
+ free(psc->driver_configs);
+ psc->driver_configs = NULL;
+ }
if (psc->driScreen) {
psc->driScreen->destroyScreen(psc);
__glxHashDestroy(psc->drawHash);
@@ -224,15 +217,14 @@ QueryVersion(Display * dpy, int opcode, int *major, int *minor)
{
#ifdef USE_XCB
xcb_connection_t *c = XGetXCBConnection(dpy);
- xcb_glx_query_version_reply_t* reply =
- xcb_glx_query_version_reply(c,
- xcb_glx_query_version(c,
- GLX_MAJOR_VERSION,
- GLX_MINOR_VERSION),
- NULL);
-
- if(reply->major_version != GLX_MAJOR_VERSION)
- {
+ xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
+ xcb_glx_query_version
+ (c,
+ GLX_MAJOR_VERSION,
+ GLX_MINOR_VERSION),
+ NULL);
+
+ if (reply->major_version != GLX_MAJOR_VERSION) {
free(reply);
return GL_FALSE;
}
@@ -550,7 +542,8 @@ getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
__GLXscreenConfigs *psc;
psc = priv->screenConfigs + screen;
- psc->serverGLXexts = __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
+ psc->serverGLXexts =
+ __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
LockDisplay(dpy);
@@ -608,7 +601,8 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
priv->screenConfigs = psc;
- priv->serverGLXversion = __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
+ priv->serverGLXversion =
+ __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
if (priv->serverGLXversion == NULL) {
FreeScreenConfigs(priv);
return GL_FALSE;
@@ -659,18 +653,6 @@ __glXInitialize(Display * dpy)
Bool glx_direct, glx_accel;
#endif
-#if defined(USE_XTHREADS)
- {
- static int firstCall = 1;
- if (firstCall) {
- /* initialize the GLX mutexes */
- xmutex_init(&__glXmutex);
- firstCall = 0;
- }
- }
-#endif
-
- INIT_MESA_SPARC;
/* The one and only long long lock */
__glXLock();
@@ -785,7 +767,6 @@ __glXSetupForCommand(Display * dpy)
if (gc->currentDpy == dpy) {
/* Use opcode from gc because its right */
- INIT_MESA_SPARC;
return gc->majorOpcode;
}
else {
@@ -806,10 +787,10 @@ __glXSetupForCommand(Display * dpy)
/**
* Flush the drawing command transport buffer.
- *
+ *
* \param ctx Context whose transport buffer is to be flushed.
* \param pc Pointer to first unused buffer location.
- *
+ *
* \todo
* Modify this function to use \c ctx->pc instead of the explicit
* \c pc parameter.
@@ -901,11 +882,11 @@ __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber,
/**
* Send a command that is too large for the GLXRender protocol request.
- *
+ *
* Send a large command, one that is too large for some reason to
* send using the GLXRender protocol request. One reason to send
* a large command is to avoid copying the data.
- *
+ *
* \param ctx GLX context
* \param header Header data.
* \param headerLen Size, in bytes, of the header data. It is assumed that
@@ -979,74 +960,3 @@ __glXDumpDrawBuffer(__GLXcontext * ctx)
}
}
#endif
-
-#ifdef USE_SPARC_ASM
-/*
- * This is where our dispatch table's bounds are.
- * And the static mesa_init is taken directly from
- * Mesa's 'sparc.c' initializer.
- *
- * We need something like this here, because this version
- * of openGL/glx never initializes a Mesa context, and so
- * the address of the dispatch table pointer never gets stuffed
- * into the dispatch jump table otherwise.
- *
- * It matters only on SPARC, and only if you are using assembler
- * code instead of C-code indirect dispatch.
- *
- * -- FEM, 04.xii.03
- */
-extern unsigned int _mesa_sparc_glapi_begin;
-extern unsigned int _mesa_sparc_glapi_end;
-extern void __glapi_sparc_icache_flush(unsigned int *);
-
-static void
-_glx_mesa_init_sparc_glapi_relocs(void)
-{
- unsigned int *insn_ptr, *end_ptr;
- unsigned long disp_addr;
-
- insn_ptr = &_mesa_sparc_glapi_begin;
- end_ptr = &_mesa_sparc_glapi_end;
- disp_addr = (unsigned long) &_glapi_Dispatch;
-
- /*
- * Verbatim from Mesa sparc.c. It's needed because there doesn't
- * seem to be a better way to do this:
- *
- * UNCONDITIONAL_JUMP ( (*_glapi_Dispatch) + entry_offset )
- *
- * This code is patching in the ADDRESS of the pointer to the
- * dispatch table. Hence, it must be called exactly once, because
- * that address is not going to change.
- *
- * What it points to can change, but Mesa (and hence, we) assume
- * that there is only one pointer.
- *
- */
- while (insn_ptr < end_ptr) {
-#if ( defined(__sparc_v9__) && ( !defined(__linux__) || defined(__linux_64__) ) )
-/*
- This code patches for 64-bit addresses. This had better
- not happen for Sparc/Linux, no matter what architecture we
- are building for. So, don't do this.
-
- The 'defined(__linux_64__)' is used here as a placeholder for
- when we do do 64-bit usermode on sparc linux.
- */
- insn_ptr[0] |= (disp_addr >> (32 + 10));
- insn_ptr[1] |= ((disp_addr & 0xffffffff) >> 10);
- __glapi_sparc_icache_flush(&insn_ptr[0]);
- insn_ptr[2] |= ((disp_addr >> 32) & ((1 << 10) - 1));
- insn_ptr[3] |= (disp_addr & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&insn_ptr[2]);
- insn_ptr += 11;
-#else
- insn_ptr[0] |= (disp_addr >> 10);
- insn_ptr[1] |= (disp_addr & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&insn_ptr[0]);
- insn_ptr += 5;
-#endif
- }
-}
-#endif /* sparc ASM in use */
diff --git a/src/glx/x11/glxextensions.c b/src/glx/x11/glxextensions.c
index d061fa9333..473f46d1e5 100644
--- a/src/glx/x11/glxextensions.c
+++ b/src/glx/x11/glxextensions.c
@@ -99,7 +99,7 @@ static const struct extension_info known_glx_extensions[] = {
{ GLX(SGIS_color_range), VER(0,0), N, N, N, N },
{ GLX(SGIS_multisample), VER(0,0), Y, Y, N, N },
{ GLX(SGIX_fbconfig), VER(1,3), Y, Y, N, N },
- { GLX(SGIX_pbuffer), VER(1,3), Y, N, N, N },
+ { GLX(SGIX_pbuffer), VER(1,3), Y, Y, N, N },
{ GLX(SGIX_swap_barrier), VER(0,0), N, N, N, N },
{ GLX(SGIX_swap_group), VER(0,0), N, N, N, N },
{ GLX(SGIX_visual_select_group), VER(0,0), Y, Y, N, N },
@@ -315,10 +315,10 @@ set_glx_extension(const struct extension_info *ext,
/**
* Convert the server's extension string to a bit-field.
- *
+ *
* \param server_string GLX extension string from the server.
* \param server_support Bit-field of supported extensions.
- *
+ *
* \note
* This function is used to process both GLX and GL extension strings. The
* bit-fields used to track each of these have different sizes. Therefore,
@@ -336,8 +336,7 @@ __glXProcessServerString(const struct extension_info *ext,
/* Determine the length of the next extension name.
*/
for (len = 0; (server_string[base + len] != SEPARATOR)
- && (server_string[base + len] != NUL);
- len++) {
+ && (server_string[base + len] != NUL); len++) {
/* empty */
}
@@ -351,8 +350,7 @@ __glXProcessServerString(const struct extension_info *ext,
* over the previous string and any trialing white-space.
*/
for (base += len; (server_string[base] == SEPARATOR)
- && (server_string[base] != NUL);
- base++) {
+ && (server_string[base] != NUL); base++) {
/* empty */
}
}
@@ -549,7 +547,7 @@ __glXGetClientExtensions(void)
/**
* Calculate the list of application usable extensions. The resulting
* string is stored in \c psc->effectiveGLXexts.
- *
+ *
* \param psc Pointer to GLX per-screen record.
* \param display_is_direct_capable True if the display is capable of
* direct rendering.
@@ -600,7 +598,7 @@ __glXCalculateUsableExtensions(__GLXscreenConfigs * psc,
* it and the "server" supports it. In this case that means that either
* the true server supports it or it is only for direct-rendering and
* the direct rendering driver supports it.
- *
+ *
* If the display is not capable of direct rendering, then the extension
* is enabled if and only if the client-side library and the server
* support it.
@@ -609,10 +607,10 @@ __glXCalculateUsableExtensions(__GLXscreenConfigs * psc,
if (display_is_direct_capable) {
for (i = 0; i < 8; i++) {
usable[i] = (client_glx_support[i] & client_glx_only[i])
- | (client_glx_support[i] & psc->
- direct_support[i] & server_support[i])
- | (client_glx_support[i] & psc->
- direct_support[i] & direct_glx_only[i]);
+ | (client_glx_support[i] & psc->direct_support[i] &
+ server_support[i])
+ | (client_glx_support[i] & psc->direct_support[i] &
+ direct_glx_only[i]);
}
}
else {
@@ -630,7 +628,7 @@ __glXCalculateUsableExtensions(__GLXscreenConfigs * psc,
/**
* Calculate the list of application usable extensions. The resulting
* string is stored in \c gc->extensions.
- *
+ *
* \param gc Pointer to GLX context.
* \param server_string Extension string from the server.
* \param major_version GL major version from the server.
diff --git a/src/glx/x11/indirect.c b/src/glx/x11/indirect.c
index 08d52aeea3..e0cafd43bc 100644
--- a/src/glx/x11/indirect.c
+++ b/src/glx/x11/indirect.c
@@ -5198,9 +5198,12 @@ glDeleteTexturesEXT(GLsizei n, const GLuint * textures)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_DeleteTextures(GET_DISPATCH(), (n, textures));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 4 + __GLX_PAD((n * 4));
@@ -5266,9 +5269,12 @@ glGenTexturesEXT(GLsizei n, GLuint * textures)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GenTextures(GET_DISPATCH(), (n, textures));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 4;
@@ -5328,9 +5334,12 @@ glIsTextureEXT(GLuint texture)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
return CALL_IsTexture(GET_DISPATCH(), (texture));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
GLboolean retval = (GLboolean) 0;
@@ -5641,9 +5650,12 @@ glGetColorTableEXT(GLenum target, GLenum format, GLenum type, GLvoid * table)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetColorTable(GET_DISPATCH(), (target, format, type, table));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
const __GLXattribute *const state = gc->client_state_private;
Display *const dpy = gc->currentDpy;
@@ -5714,10 +5726,13 @@ glGetColorTableParameterfvEXT(GLenum target, GLenum pname, GLfloat * params)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetColorTableParameterfv(GET_DISPATCH(),
(target, pname, params));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 8;
@@ -5784,10 +5799,13 @@ glGetColorTableParameterivEXT(GLenum target, GLenum pname, GLint * params)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetColorTableParameteriv(GET_DISPATCH(),
(target, pname, params));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 8;
@@ -6107,10 +6125,13 @@ gl_dispatch_stub_356(GLenum target, GLenum format, GLenum type,
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetConvolutionFilter(GET_DISPATCH(),
(target, format, type, image));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
const __GLXattribute *const state = gc->client_state_private;
Display *const dpy = gc->currentDpy;
@@ -6182,10 +6203,13 @@ gl_dispatch_stub_357(GLenum target, GLenum pname, GLfloat * params)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetConvolutionParameterfv(GET_DISPATCH(),
(target, pname, params));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 8;
@@ -6252,10 +6276,13 @@ gl_dispatch_stub_358(GLenum target, GLenum pname, GLint * params)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetConvolutionParameteriv(GET_DISPATCH(),
(target, pname, params));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 8;
@@ -6329,10 +6356,13 @@ gl_dispatch_stub_361(GLenum target, GLboolean reset, GLenum format,
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetHistogram(GET_DISPATCH(),
(target, reset, format, type, values));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
const __GLXattribute *const state = gc->client_state_private;
Display *const dpy = gc->currentDpy;
@@ -6403,9 +6433,12 @@ gl_dispatch_stub_362(GLenum target, GLenum pname, GLfloat * params)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetHistogramParameterfv(GET_DISPATCH(), (target, pname, params));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 8;
@@ -6471,9 +6504,12 @@ gl_dispatch_stub_363(GLenum target, GLenum pname, GLint * params)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetHistogramParameteriv(GET_DISPATCH(), (target, pname, params));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 8;
@@ -6543,9 +6579,12 @@ gl_dispatch_stub_364(GLenum target, GLboolean reset, GLenum format,
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetMinmax(GET_DISPATCH(), (target, reset, format, type, values));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
const __GLXattribute *const state = gc->client_state_private;
Display *const dpy = gc->currentDpy;
@@ -6614,9 +6653,12 @@ gl_dispatch_stub_365(GLenum target, GLenum pname, GLfloat * params)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetMinmaxParameterfv(GET_DISPATCH(), (target, pname, params));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 8;
@@ -6679,9 +6721,12 @@ gl_dispatch_stub_366(GLenum target, GLenum pname, GLint * params)
{
__GLXcontext *const gc = __glXGetCurrentContext();
+#ifdef GLX_DIRECT_RENDERING
if (gc->driContext) {
CALL_GetMinmaxParameteriv(GET_DISPATCH(), (target, pname, params));
- } else {
+ } else
+#endif
+ {
__GLXcontext *const gc = __glXGetCurrentContext();
Display *const dpy = gc->currentDpy;
const GLuint cmdlen = 8;
diff --git a/src/glx/x11/indirect_size.c b/src/glx/x11/indirect_size.c
index 12214d7fe4..cdaf02ffe6 100644
--- a/src/glx/x11/indirect_size.c
+++ b/src/glx/x11/indirect_size.c
@@ -192,6 +192,10 @@ __glTexParameterfv_size(GLenum e)
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
case GL_TEXTURE_LOD_BIAS:
/* case GL_TEXTURE_LOD_BIAS_EXT:*/
+ case GL_TEXTURE_STORAGE_HINT_APPLE:
+ case GL_STORAGE_PRIVATE_APPLE:
+ case GL_STORAGE_CACHED_APPLE:
+ case GL_STORAGE_SHARED_APPLE:
case GL_DEPTH_TEXTURE_MODE:
/* case GL_DEPTH_TEXTURE_MODE_ARB:*/
case GL_TEXTURE_COMPARE_MODE:
@@ -240,6 +244,7 @@ __glTexEnvfv_size(GLenum e)
case GL_OPERAND1_ALPHA:
case GL_OPERAND2_ALPHA:
case GL_OPERAND3_ALPHA_NV:
+ case GL_BUMP_TARGET_ATI:
case GL_COORD_REPLACE_ARB:
/* case GL_COORD_REPLACE_NV:*/
return 1;
diff --git a/src/glx/x11/indirect_vertex_array.c b/src/glx/x11/indirect_vertex_array.c
index bb5232f618..ad9882528f 100644
--- a/src/glx/x11/indirect_vertex_array.c
+++ b/src/glx/x11/indirect_vertex_array.c
@@ -1,18 +1,18 @@
/*
* (C) Copyright IBM Corporation 2004, 2005
* 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
@@ -39,7 +39,7 @@
/**
* \file indirect_vertex_array.c
* Implement GLX protocol for vertex arrays and vertex buffer objects.
- *
+ *
* The most important function in this fill is \c fill_array_info_cache.
* The \c array_state_vector contains a cache of the ARRAY_INFO data sent
* in the DrawArrays protocol. Certain operations, such as enabling or
@@ -47,7 +47,7 @@
* fills-in this data. Additionally, it examines the enabled state and
* other factors to determine what "version" of DrawArrays protocoal can be
* used.
- *
+ *
* Current, only two versions of DrawArrays protocol are implemented. The
* first version is the "none" protocol. This is the fallback when the
* server does not support GL 1.1 / EXT_vertex_arrays. It is implemented
@@ -90,11 +90,11 @@ static GLboolean validate_type(__GLXcontext * gc, GLenum type);
/**
- * Table of sizes, in bytes, of a GL types. All of the type enums are be in
+ * Table of sizes, in bytes, of a GL types. All of the type enums are be in
* the range 0x1400 - 0x140F. That includes types added by extensions (i.e.,
* \c GL_HALF_FLOAT_NV). This elements of this table correspond to the
* type enums masked with 0x0f.
- *
+ *
* \notes
* \c GL_HALF_FLOAT_NV is not included. Neither are \c GL_2_BYTES,
* \c GL_3_BYTES, or \c GL_4_BYTES.
@@ -131,15 +131,15 @@ __glXFreeVertexArrayState(__GLXcontext * gc)
/**
* Initialize vertex array state of a GLX context.
- *
+ *
* \param gc GLX context whose vertex array state is to be initialized.
- *
+ *
* \warning
* This function may only be called after __GLXcontext::gl_extension_bits,
* __GLXcontext::server_minor, and __GLXcontext::server_major have been
* initialized. These values are used to determine what vertex arrays are
* supported.
- *
+ *
* \bug
* Return values from malloc are not properly tested.
*/
@@ -171,7 +171,7 @@ __glXInitVertexArrayState(__GLXcontext * gc)
* are supported by the server are create. For example, if the server
* supports only 2 texture units, then only 2 texture coordinate arrays
* are created.
- *
+ *
* At the very least, GL_VERTEX_ARRAY, GL_NORMAL_ARRAY,
* GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_TEXTURE_COORD_ARRAY, and
* GL_EDGE_FLAG_ARRAY are supported.
@@ -532,7 +532,7 @@ emit_DrawArrays_none(GLenum mode, GLint first, GLsizei count)
/**
* Emit the header data for the GL 1.1 / EXT_vertex_arrays DrawArrays
* protocol.
- *
+ *
* \param gc GLX context.
* \param arrays Array state.
* \param elements_per_request Location to store the number of elements that
@@ -543,7 +543,7 @@ emit_DrawArrays_none(GLenum mode, GLint first, GLsizei count)
* will be zero.
* \param mode Drawing mode.
* \param count Number of vertices.
- *
+ *
* \returns
* A pointer to the buffer for array data.
*/
@@ -594,7 +594,7 @@ emit_DrawArrays_header_old(__GLXcontext * gc,
/* Calculate the number of data packets that will be required to send
* the whole command. To do this, the number of verticies that
* will fit in a single buffer must be calculated.
- *
+ *
* The important value here is elements_per_request. This is the
* number of complete array elements that will fit in a single
* buffer. There may be some wasted space at the end of the buffer,
@@ -869,7 +869,7 @@ emit_DrawElements_old(GLenum mode, GLsizei count, GLenum type,
/**
* Validate that the \c mode parameter to \c glDrawArrays, et. al. is valid.
* If it is not valid, then an error code is set in the GLX context.
- *
+ *
* \returns
* \c GL_TRUE if the argument is valid, \c GL_FALSE if is not.
*/
@@ -902,7 +902,7 @@ validate_mode(__GLXcontext * gc, GLenum mode)
* A value less than zero is invalid and will result in \c GL_INVALID_VALUE
* being set. A value of zero will not result in an error being set, but
* will result in \c GL_FALSE being returned.
- *
+ *
* \returns
* \c GL_TRUE if the argument is valid, \c GL_FALSE if it is not.
*/
@@ -1084,21 +1084,21 @@ __indirect_glMultiDrawElementsEXT(GLenum mode, const GLsizei * count,
#define COMMON_ARRAY_DATA_INIT(a, PTR, TYPE, STRIDE, COUNT, NORMALIZED, HDR_SIZE, OPCODE) \
- do { \
- (a)->data = PTR; \
- (a)->data_type = TYPE; \
- (a)->user_stride = STRIDE; \
- (a)->count = COUNT; \
- (a)->normalized = NORMALIZED; \
- \
- (a)->element_size = __glXTypeSize( TYPE ) * COUNT; \
- (a)->true_stride = (STRIDE == 0) \
- ? (a)->element_size : STRIDE; \
- \
- (a)->header_size = HDR_SIZE; \
- ((uint16_t *) (a)->header)[0] = __GLX_PAD((a)->header_size + (a)->element_size); \
- ((uint16_t *) (a)->header)[1] = OPCODE; \
- } while(0)
+ do { \
+ (a)->data = PTR; \
+ (a)->data_type = TYPE; \
+ (a)->user_stride = STRIDE; \
+ (a)->count = COUNT; \
+ (a)->normalized = NORMALIZED; \
+ \
+ (a)->element_size = __glXTypeSize( TYPE ) * COUNT; \
+ (a)->true_stride = (STRIDE == 0) \
+ ? (a)->element_size : STRIDE; \
+ \
+ (a)->header_size = HDR_SIZE; \
+ ((uint16_t *) (a)->header)[0] = __GLX_PAD((a)->header_size + (a)->element_size); \
+ ((uint16_t *) (a)->header)[1] = OPCODE; \
+ } while(0)
void
@@ -1363,36 +1363,36 @@ __indirect_glTexCoordPointer(GLint size, GLenum type, GLsizei stride,
{
static const uint16_t short_ops[5] = {
0, X_GLrop_TexCoord1sv, X_GLrop_TexCoord2sv, X_GLrop_TexCoord3sv,
- X_GLrop_TexCoord4sv
+ X_GLrop_TexCoord4sv
};
static const uint16_t int_ops[5] = {
0, X_GLrop_TexCoord1iv, X_GLrop_TexCoord2iv, X_GLrop_TexCoord3iv,
- X_GLrop_TexCoord4iv
+ X_GLrop_TexCoord4iv
};
static const uint16_t float_ops[5] = {
0, X_GLrop_TexCoord1dv, X_GLrop_TexCoord2fv, X_GLrop_TexCoord3fv,
- X_GLrop_TexCoord4fv
+ X_GLrop_TexCoord4fv
};
static const uint16_t double_ops[5] = {
0, X_GLrop_TexCoord1dv, X_GLrop_TexCoord2dv, X_GLrop_TexCoord3dv,
- X_GLrop_TexCoord4dv
+ X_GLrop_TexCoord4dv
};
static const uint16_t mshort_ops[5] = {
0, X_GLrop_MultiTexCoord1svARB, X_GLrop_MultiTexCoord2svARB,
- X_GLrop_MultiTexCoord3svARB, X_GLrop_MultiTexCoord4svARB
+ X_GLrop_MultiTexCoord3svARB, X_GLrop_MultiTexCoord4svARB
};
static const uint16_t mint_ops[5] = {
0, X_GLrop_MultiTexCoord1ivARB, X_GLrop_MultiTexCoord2ivARB,
- X_GLrop_MultiTexCoord3ivARB, X_GLrop_MultiTexCoord4ivARB
+ X_GLrop_MultiTexCoord3ivARB, X_GLrop_MultiTexCoord4ivARB
};
static const uint16_t mfloat_ops[5] = {
0, X_GLrop_MultiTexCoord1dvARB, X_GLrop_MultiTexCoord2fvARB,
- X_GLrop_MultiTexCoord3fvARB, X_GLrop_MultiTexCoord4fvARB
+ X_GLrop_MultiTexCoord3fvARB, X_GLrop_MultiTexCoord4fvARB
};
static const uint16_t mdouble_ops[5] = {
0, X_GLrop_MultiTexCoord1dvARB, X_GLrop_MultiTexCoord2dvARB,
- X_GLrop_MultiTexCoord3dvARB, X_GLrop_MultiTexCoord4dvARB
+ X_GLrop_MultiTexCoord3dvARB, X_GLrop_MultiTexCoord4dvARB
};
uint16_t opcode;
diff --git a/src/glx/x11/indirect_vertex_program.c b/src/glx/x11/indirect_vertex_program.c
index 865a4b1ba1..3313ac008a 100644
--- a/src/glx/x11/indirect_vertex_program.c
+++ b/src/glx/x11/indirect_vertex_program.c
@@ -30,6 +30,10 @@
#include "indirect_vertex_array.h"
#include <GL/glxproto.h>
+#if !defined __GNUC__ || __GNUC__ < 3
+# define __builtin_expect(x, y) x
+#endif
+
static void
do_vertex_attrib_enable(GLuint index, GLboolean val)
{
diff --git a/src/glx/x11/pixelstore.c b/src/glx/x11/pixelstore.c
index 0eb31bf1e3..8b51b5d8b7 100644
--- a/src/glx/x11/pixelstore.c
+++ b/src/glx/x11/pixelstore.c
@@ -31,6 +31,10 @@
#include "glxclient.h"
#include "indirect.h"
+#if !defined __GNUC__ || __GNUC__ < 3
+# define __builtin_expect(x, y) x
+#endif
+
/**
* Send glPixelStore command to the server
*
diff --git a/src/glx/x11/single2.c b/src/glx/x11/single2.c
index 0b2d5113cc..d128ba2053 100644
--- a/src/glx/x11/single2.c
+++ b/src/glx/x11/single2.c
@@ -147,7 +147,7 @@ __indirect_glGetError(void)
/**
* Get the selected attribute from the client state.
- *
+ *
* \returns
* On success \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned.
*/
@@ -679,7 +679,8 @@ __indirect_glGetString(GLenum name)
*/
(void) __glXFlushRenderBuffer(gc, gc->pc);
- s = (GLubyte *) __glXGetString(dpy, gc->majorOpcode, gc->currentContextTag, name);
+ s = (GLubyte *) __glXGetString(dpy, gc->majorOpcode, gc->currentContextTag,
+ name);
if (!s) {
/* Throw data on the floor */
__glXSetError(gc, GL_OUT_OF_MEMORY);
@@ -753,7 +754,7 @@ __indirect_glGetString(GLenum name)
* hardware accelerated. For example, a TNT will show core
* version 1.5, but most of the post-1.2 functionality is a
* software fallback.
- *
+ *
* I don't want to break applications that rely on this odd
* behavior. At the same time, the code is written and tested,
* so I didn't want to throw it away. Therefore, the code is here
@@ -766,7 +767,7 @@ __indirect_glGetString(GLenum name)
* gc->server_minor are set. This version may be higher than we
* can completely support, but it may imply support for some
* extensions that we can support.
- *
+ *
* For example, at the time of this writing, the client-side
* library only supports upto core GL version 1.2. However, cubic
* textures, multitexture, multisampling, and some other 1.3
@@ -880,50 +881,50 @@ GLboolean
__indirect_glAreTexturesResident(GLsizei n, const GLuint * textures,
GLboolean * residences)
{
- __GLXcontext *const gc = __glXGetCurrentContext();
- Display *const dpy = gc->currentDpy;
- GLboolean retval = (GLboolean) 0;
- const GLuint cmdlen = 4 + __GLX_PAD((n * 4));
- if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) {
+ __GLXcontext *const gc = __glXGetCurrentContext();
+ Display *const dpy = gc->currentDpy;
+ GLboolean retval = (GLboolean) 0;
+ const GLuint cmdlen = 4 + __GLX_PAD((n * 4));
+ if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) {
#ifdef USE_XCB
- xcb_connection_t *c = XGetXCBConnection(dpy);
- (void) __glXFlushRenderBuffer(gc, gc->pc);
- xcb_glx_are_textures_resident_reply_t *reply =
- xcb_glx_are_textures_resident_reply(c,
- xcb_glx_are_textures_resident
- (c, gc->currentContextTag, n,
- textures), NULL);
- (void) memcpy(residences, xcb_glx_are_textures_resident_data(reply),
- xcb_glx_are_textures_resident_data_length(reply) *
- sizeof(GLboolean));
- retval = reply->ret_val;
- free(reply);
+ xcb_connection_t *c = XGetXCBConnection(dpy);
+ (void) __glXFlushRenderBuffer(gc, gc->pc);
+ xcb_glx_are_textures_resident_reply_t *reply =
+ xcb_glx_are_textures_resident_reply(c,
+ xcb_glx_are_textures_resident
+ (c, gc->currentContextTag, n,
+ textures), NULL);
+ (void) memcpy(residences, xcb_glx_are_textures_resident_data(reply),
+ xcb_glx_are_textures_resident_data_length(reply) *
+ sizeof(GLboolean));
+ retval = reply->ret_val;
+ free(reply);
#else
- GLubyte const *pc =
- __glXSetupSingleRequest(gc, X_GLsop_AreTexturesResident, cmdlen);
- (void) memcpy((void *) (pc + 0), (void *) (&n), 4);
- (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4));
- if (n & 3) {
- /* n is not a multiple of four.
- * When reply_is_always_array is TRUE, __glXReadReply() will
- * put a multiple of four bytes into the dest buffer. If the
- * caller's buffer is not a multiple of four in size, we'll write
- * out of bounds. So use a temporary buffer that's a few bytes
- * larger.
- */
- GLboolean *res4 = malloc((n + 3) & ~3);
- retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE);
- memcpy(residences, res4, n);
- free(res4);
- }
- else {
- retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE);
- }
- UnlockDisplay(dpy);
- SyncHandle();
+ GLubyte const *pc =
+ __glXSetupSingleRequest(gc, X_GLsop_AreTexturesResident, cmdlen);
+ (void) memcpy((void *) (pc + 0), (void *) (&n), 4);
+ (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4));
+ if (n & 3) {
+ /* n is not a multiple of four.
+ * When reply_is_always_array is TRUE, __glXReadReply() will
+ * put a multiple of four bytes into the dest buffer. If the
+ * caller's buffer is not a multiple of four in size, we'll write
+ * out of bounds. So use a temporary buffer that's a few bytes
+ * larger.
+ */
+ GLboolean *res4 = malloc((n + 3) & ~3);
+ retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE);
+ memcpy(residences, res4, n);
+ free(res4);
+ }
+ else {
+ retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE);
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
#endif /* USE_XCB */
- }
- return retval;
+ }
+ return retval;
}
@@ -936,36 +937,37 @@ GLboolean
glAreTexturesResidentEXT(GLsizei n, const GLuint * textures,
GLboolean * residences)
{
- __GLXcontext *const gc = __glXGetCurrentContext();
-
- if (gc->isDirect) {
- return CALL_AreTexturesResident(GET_DISPATCH(),
- (n, textures, residences));
- } else {
- __GLXcontext *const gc = __glXGetCurrentContext();
- Display *const dpy = gc->currentDpy;
- GLboolean retval = (GLboolean) 0;
- const GLuint cmdlen = 4 + __GLX_PAD((n * 4));
- if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) {
- GLubyte const *pc =
- __glXSetupVendorRequest(gc, X_GLXVendorPrivateWithReply,
- X_GLvop_AreTexturesResidentEXT,
- cmdlen);
- (void) memcpy((void *) (pc + 0), (void *) (&n), 4);
- (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4));
- if (n & 3) {
- /* see comments in __indirect_glAreTexturesResident() */
- GLboolean *res4 = malloc((n + 3) & ~3);
- retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE);
- memcpy(residences, res4, n);
- free(res4);
- }
- else {
- retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE);
- }
- UnlockDisplay(dpy);
- SyncHandle();
- }
- return retval;
- }
+ __GLXcontext *const gc = __glXGetCurrentContext();
+
+ if (gc->isDirect) {
+ return CALL_AreTexturesResident(GET_DISPATCH(),
+ (n, textures, residences));
+ }
+ else {
+ __GLXcontext *const gc = __glXGetCurrentContext();
+ Display *const dpy = gc->currentDpy;
+ GLboolean retval = (GLboolean) 0;
+ const GLuint cmdlen = 4 + __GLX_PAD((n * 4));
+ if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) {
+ GLubyte const *pc =
+ __glXSetupVendorRequest(gc, X_GLXVendorPrivateWithReply,
+ X_GLvop_AreTexturesResidentEXT,
+ cmdlen);
+ (void) memcpy((void *) (pc + 0), (void *) (&n), 4);
+ (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4));
+ if (n & 3) {
+ /* see comments in __indirect_glAreTexturesResident() */
+ GLboolean *res4 = malloc((n + 3) & ~3);
+ retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE);
+ memcpy(residences, res4, n);
+ free(res4);
+ }
+ else {
+ retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE);
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ }
+ return retval;
+ }
}
diff --git a/src/mesa/Makefile b/src/mesa/Makefile
index 6b4057030e..8300b30144 100644
--- a/src/mesa/Makefile
+++ b/src/mesa/Makefile
@@ -3,8 +3,7 @@
TOP = ../..
include $(TOP)/configs/current
-include sources
-
+include sources.mak
.SUFFIXES : .cpp
@@ -19,9 +18,11 @@ include sources
+
# Default: build dependencies, then asm_subdirs, then convenience
# libs (.a) and finally the device drivers:
-default: depend asm_subdirs libmesa.a libglapi.a driver_subdirs
+default: depend asm_subdirs libmesa.a libmesagallium.a libglapi.a \
+ driver_subdirs
@@ -32,15 +33,22 @@ default: depend asm_subdirs libmesa.a libglapi.a driver_subdirs
libmesa.a: $(MESA_OBJECTS)
@ $(MKLIB) -o mesa -static $(MESA_OBJECTS)
+# Make archive of subset of core mesa object files for gallium
+libmesagallium.a: $(MESA_GALLIUM_OBJECTS)
+ @ $(MKLIB) -o mesagallium -static $(MESA_GALLIUM_OBJECTS)
+
# Make archive of gl* API dispatcher functions only
libglapi.a: $(GLAPI_OBJECTS)
- @ $(MKLIB) -o glapi -static $(GLAPI_OBJECTS)
-
+ @if [ "${WINDOW_SYSTEM}" = "dri" ] ; then \
+ touch libglapi.a ; \
+ else \
+ $(MKLIB) -o glapi -static $(GLAPI_OBJECTS) ; \
+ fi
######################################################################
# Device drivers
driver_subdirs: libmesa.a libglapi.a
- (cd drivers && $(MAKE))
+ @ (cd drivers && $(MAKE))
######################################################################
@@ -95,7 +103,8 @@ gl_pcedit = sed \
-e 's,@VERSION@,$(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY),' \
-e 's,@GL_PC_REQ_PRIV@,$(GL_PC_REQ_PRIV),' \
-e 's,@GL_PC_LIB_PRIV@,$(GL_PC_LIB_PRIV),' \
- -e 's,@GL_PC_CFLAGS@,$(GL_PC_CFLAGS),'
+ -e 's,@GL_PC_CFLAGS@,$(GL_PC_CFLAGS),' \
+ -e 's,@GL_LIB@,$(GL_LIB),'
gl.pc: gl.pc.in
$(gl_pcedit) $< > $@
@@ -120,14 +129,14 @@ install-headers:
install-libgl: default gl.pc install-headers
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
- $(INSTALL) $(TOP)/$(LIB_DIR)/$(GL_LIB_GLOB) \
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GL_LIB_GLOB) \
$(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -m 644 gl.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
install-osmesa: default osmesa.pc
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
- $(INSTALL) $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_GLOB) \
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_GLOB) \
$(DESTDIR)$(INSTALL_LIB_DIR)
$(INSTALL) -m 644 osmesa.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
diff --git a/src/mesa/Makefile.DJ b/src/mesa/Makefile.DJ
deleted file mode 100644
index 06a13fb1ab..0000000000
--- a/src/mesa/Makefile.DJ
+++ /dev/null
@@ -1,166 +0,0 @@
-# Mesa 3-D graphics library
-# Version: 5.1
-#
-# Copyright (C) 1999-2003 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.
-
-# DOS/DJGPP core makefile v1.7 for Mesa
-#
-# Copyright (C) 2002 - Daniel Borca
-# Email : dborca@users.sourceforge.net
-# Web : http://www.geocities.com/dborca
-
-
-#
-# Available options:
-#
-# Environment variables:
-# CFLAGS
-#
-# GLIDE path to Glide3 SDK; used with FX.
-# default = $(TOP)/glide3
-# FX=1 build for 3dfx Glide3. Note that this disables
-# compilation of most DMesa code and requires fxMesa.
-# As a consequence, you'll need the DJGPP Glide3
-# library to build any application.
-# default = no
-# X86=1 optimize for x86 (if possible, use MMX, SSE, 3DNow).
-# default = no
-#
-# Targets:
-# all: build GL
-# clean: remove object files
-#
-
-
-
-.PHONY: all clean
-.INTERMEDIATE: x86/gen_matypes.exe
-
-TOP = ../..
-GLIDE ?= $(TOP)/glide3
-LIBDIR = $(TOP)/lib
-GL_LIB = libgl.a
-GL_DXE = gl.dxe
-GL_IMP = libigl.a
-
-export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH);$(LIBDIR);$(GLIDE)/lib
-
-CC = gcc
-CFLAGS += $(INCLUDE_DIRS)
-CFLAGS += -DUSE_EXTERNAL_DXTN_LIB=1
-ifeq ($(FX),1)
-CFLAGS += -D__DOS__
-CFLAGS += -I$(GLIDE)/include -DFX
-LIBNAME = "Mesa/FX DJGPP"
-else
-LIBNAME = "Mesa DJGPP"
-endif
-
-AR = ar
-ARFLAGS = crus
-
-HAVEDXE3 = $(wildcard $(DJDIR)/bin/dxe3gen.exe)
-
-ifeq ($(wildcard $(addsuffix /rm.exe,$(subst ;, ,$(PATH)))),)
-UNLINK = del $(subst /,\,$(1))
-else
-UNLINK = $(RM) $(1)
-endif
-
-include sources
-
-ifeq ($(X86),1)
-CFLAGS += -DUSE_X86_ASM
-CFLAGS += -DUSE_MMX_ASM
-CFLAGS += -DUSE_SSE_ASM
-CFLAGS += -DUSE_3DNOW_ASM
-X86_SOURCES += $(X86_API)
-else
-X86_SOURCES =
-endif
-
-DRIVER_SOURCES = \
- drivers/dos/dmesa.c
-ifeq ($(FX),1)
-DRIVER_SOURCES += \
- $(GLIDE_DRIVER_SOURCES)
-else
-DRIVER_SOURCES += \
- $(OSMESA_DRIVER_SOURCES) \
- drivers/dos/video.c \
- drivers/dos/vesa.c \
- drivers/dos/blit.S \
- drivers/dos/vga.c \
- drivers/dos/null.c \
- drivers/dos/dpmi.c
-endif
-
-SOURCES = $(CORE_SOURCES) $(X86_SOURCES) $(COMMON_DRIVER_SOURCES) $(DRIVER_SOURCES)
-
-OBJECTS = $(addsuffix .o,$(basename $(SOURCES)))
-
-X86_OBJECTS = $(addsuffix .o,$(basename $(X86_SOURCES)))
-
-.c.o:
- $(CC) -o $@ $(CFLAGS) -c $<
-.S.o:
- $(CC) -o $@ $(CFLAGS) -c $<
-.s.o:
- $(CC) -o $@ $(CFLAGS) -x assembler-with-cpp -c $<
-
-all: $(LIBDIR)/$(GL_LIB) $(LIBDIR)/$(GL_DXE) $(LIBDIR)/$(GL_IMP)
-
-$(LIBDIR)/$(GL_LIB): $(OBJECTS)
- $(AR) $(ARFLAGS) $@ $^
-
-$(LIBDIR)/$(GL_DXE) $(LIBDIR)/$(GL_IMP): $(OBJECTS)
-ifeq ($(HAVEDXE3),)
- $(warning Missing DXE3 package... Skipping $(GL_DXE))
-else
-ifeq ($(FX),1)
- -dxe3gen -o $(LIBDIR)/$(GL_DXE) -Y $(LIBDIR)/$(GL_IMP) -D $(LIBNAME) -E _gl -E _DMesa -P glide3x.dxe -U $^
-else
- -dxe3gen -o $(LIBDIR)/$(GL_DXE) -Y $(LIBDIR)/$(GL_IMP) -D $(LIBNAME) -E _gl -E _DMesa -U $^
-endif
-endif
-
-$(X86_OBJECTS): x86/matypes.h
-
-x86/matypes.h: x86/gen_matypes.exe
- $< > $@
-
-x86/gen_matypes.exe: x86/gen_matypes.c
- $(CC) -o $@ $(CFLAGS) -s $<
-
-clean:
- -$(call UNLINK,array_cache/*.o)
- -$(call UNLINK,glapi/*.o)
- -$(call UNLINK,main/*.o)
- -$(call UNLINK,math/*.o)
- -$(call UNLINK,shader/*.o)
- -$(call UNLINK,sparc/*.o)
- -$(call UNLINK,ppc/*.o)
- -$(call UNLINK,swrast/*.o)
- -$(call UNLINK,swrast_setup/*.o)
- -$(call UNLINK,tnl/*.o)
- -$(call UNLINK,x86/*.o)
- -$(call UNLINK,drivers/common/*.o)
- -$(call UNLINK,drivers/dos/*.o)
- -$(call UNLINK,drivers/glide/*.o)
diff --git a/src/mesa/Makefile.mgw b/src/mesa/Makefile.mgw
index 886b344ec9..097c390a83 100644
--- a/src/mesa/Makefile.mgw
+++ b/src/mesa/Makefile.mgw
@@ -124,7 +124,7 @@ ifneq ($(wildcard $(addsuffix /rm,$(subst :, ,$(PATH)))),)
UNLINK = $(RM) $(1)
endif
-include sources
+include sources.mak
CFLAGS += $(INCLUDE_DIRS)
diff --git a/src/mesa/SConscript b/src/mesa/SConscript
new file mode 100644
index 0000000000..cad5676320
--- /dev/null
+++ b/src/mesa/SConscript
@@ -0,0 +1,356 @@
+#######################################################################
+# SConscript for Mesa
+
+
+Import('*')
+
+if env['platform'] != 'winddk':
+
+ env = env.Clone()
+
+ env.Append(CPPPATH = [
+ '#/src/mesa',
+ ])
+
+ 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
+ 'WIN32_THREADS', # use Win32 thread API
+ ])
+
+ #
+ # Source files
+ #
+
+ main_sources = [
+ 'main/api_arrayelt.c',
+ 'main/api_exec.c',
+ 'main/api_loopback.c',
+ 'main/api_noop.c',
+ 'main/api_validate.c',
+ 'main/accum.c',
+ 'main/attrib.c',
+ 'main/arrayobj.c',
+ 'main/blend.c',
+ 'main/bufferobj.c',
+ 'main/buffers.c',
+ 'main/clear.c',
+ 'main/clip.c',
+ 'main/colortab.c',
+ 'main/context.c',
+ 'main/convolve.c',
+ 'main/cpuinfo.c',
+ 'main/debug.c',
+ 'main/depth.c',
+ 'main/depthstencil.c',
+ 'main/dlist.c',
+ 'main/dlopen.c',
+ 'main/drawpix.c',
+ 'main/enable.c',
+ 'main/enums.c',
+ 'main/eval.c',
+ 'main/execmem.c',
+ 'main/extensions.c',
+ 'main/fbobject.c',
+ 'main/feedback.c',
+ 'main/ffvertex_prog.c',
+ 'main/fog.c',
+ 'main/framebuffer.c',
+ 'main/get.c',
+ 'main/getstring.c',
+ 'main/hash.c',
+ 'main/hint.c',
+ 'main/histogram.c',
+ 'main/image.c',
+ 'main/imports.c',
+ 'main/light.c',
+ 'main/lines.c',
+ 'main/matrix.c',
+ 'main/mipmap.c',
+ 'main/mm.c',
+ 'main/multisample.c',
+ 'main/pixel.c',
+ 'main/pixelstore.c',
+ 'main/points.c',
+ 'main/polygon.c',
+ 'main/queryobj.c',
+ 'main/rastpos.c',
+ 'main/rbadaptors.c',
+ 'main/readpix.c',
+ 'main/renderbuffer.c',
+ 'main/scissor.c',
+ 'main/shaders.c',
+ 'main/shared.c',
+ 'main/state.c',
+ 'main/stencil.c',
+ 'main/syncobj.c',
+ 'main/texcompress.c',
+ 'main/texcompress_s3tc.c',
+ 'main/texcompress_fxt1.c',
+ 'main/texenv.c',
+ 'main/texenvprogram.c',
+ 'main/texformat.c',
+ 'main/texgen.c',
+ 'main/texgetimage.c',
+ 'main/teximage.c',
+ 'main/texobj.c',
+ 'main/texparam.c',
+ 'main/texrender.c',
+ 'main/texstate.c',
+ 'main/texstore.c',
+ 'main/varray.c',
+ 'main/viewport.c',
+ 'main/vtxfmt.c',
+ ]
+
+ math_sources = [
+ 'math/m_debug_clip.c',
+ 'math/m_debug_norm.c',
+ 'math/m_debug_xform.c',
+ 'math/m_eval.c',
+ 'math/m_matrix.c',
+ 'math/m_translate.c',
+ 'math/m_vector.c',
+ 'math/m_xform.c',
+ ]
+
+ vbo_sources = [
+ 'vbo/vbo_context.c',
+ 'vbo/vbo_exec.c',
+ 'vbo/vbo_exec_api.c',
+ 'vbo/vbo_exec_array.c',
+ 'vbo/vbo_exec_draw.c',
+ 'vbo/vbo_exec_eval.c',
+ 'vbo/vbo_rebase.c',
+ 'vbo/vbo_split.c',
+ 'vbo/vbo_split_copy.c',
+ 'vbo/vbo_split_inplace.c',
+ 'vbo/vbo_save.c',
+ 'vbo/vbo_save_api.c',
+ 'vbo/vbo_save_draw.c',
+ 'vbo/vbo_save_loopback.c',
+ ]
+
+ vf_sources = [
+ 'vf/vf.c',
+ 'vf/vf_generic.c',
+ 'vf/vf_sse.c',
+ ]
+
+ statetracker_sources = [
+ 'state_tracker/st_atom.c',
+ 'state_tracker/st_atom_blend.c',
+ 'state_tracker/st_atom_clip.c',
+ 'state_tracker/st_atom_constbuf.c',
+ 'state_tracker/st_atom_depth.c',
+ 'state_tracker/st_atom_framebuffer.c',
+ 'state_tracker/st_atom_pixeltransfer.c',
+ 'state_tracker/st_atom_sampler.c',
+ 'state_tracker/st_atom_scissor.c',
+ 'state_tracker/st_atom_shader.c',
+ 'state_tracker/st_atom_rasterizer.c',
+ 'state_tracker/st_atom_stipple.c',
+ 'state_tracker/st_atom_texture.c',
+ 'state_tracker/st_atom_viewport.c',
+ 'state_tracker/st_cb_accum.c',
+ 'state_tracker/st_cb_bitmap.c',
+ 'state_tracker/st_cb_blit.c',
+ 'state_tracker/st_cb_bufferobjects.c',
+ 'state_tracker/st_cb_clear.c',
+ 'state_tracker/st_cb_flush.c',
+ 'state_tracker/st_cb_drawpixels.c',
+ 'state_tracker/st_cb_fbo.c',
+ 'state_tracker/st_cb_get.c',
+ 'state_tracker/st_cb_feedback.c',
+ 'state_tracker/st_cb_program.c',
+ 'state_tracker/st_cb_queryobj.c',
+ 'state_tracker/st_cb_rasterpos.c',
+ 'state_tracker/st_cb_readpixels.c',
+ 'state_tracker/st_cb_strings.c',
+ 'state_tracker/st_cb_texture.c',
+ 'state_tracker/st_cb_viewport.c',
+ 'state_tracker/st_context.c',
+ 'state_tracker/st_debug.c',
+ 'state_tracker/st_draw.c',
+ 'state_tracker/st_draw_feedback.c',
+ 'state_tracker/st_extensions.c',
+ 'state_tracker/st_format.c',
+ 'state_tracker/st_framebuffer.c',
+ 'state_tracker/st_gen_mipmap.c',
+ 'state_tracker/st_mesa_to_tgsi.c',
+ 'state_tracker/st_program.c',
+ 'state_tracker/st_texture.c',
+ ]
+
+ shader_sources = [
+ 'shader/arbprogparse.c',
+ 'shader/arbprogram.c',
+ 'shader/atifragshader.c',
+ 'shader/grammar/grammar_mesa.c',
+ 'shader/hash_table.c',
+ 'shader/lex.yy.c',
+ 'shader/nvfragparse.c',
+ 'shader/nvprogram.c',
+ 'shader/nvvertparse.c',
+ 'shader/program.c',
+ 'shader/program_parse.tab.c',
+ 'shader/program_parse_extra.c',
+ 'shader/prog_cache.c',
+ 'shader/prog_execute.c',
+ 'shader/prog_instruction.c',
+ 'shader/prog_noise.c',
+ 'shader/prog_optimize.c',
+ 'shader/prog_parameter.c',
+ 'shader/prog_parameter_layout.c',
+ 'shader/prog_print.c',
+ 'shader/prog_statevars.c',
+ 'shader/prog_uniform.c',
+ 'shader/programopt.c',
+ 'shader/symbol_table.c',
+ 'shader/shader_api.c',
+ ]
+
+ slang_sources = [
+ 'shader/slang/slang_builtin.c',
+ 'shader/slang/slang_codegen.c',
+ 'shader/slang/slang_compile.c',
+ 'shader/slang/slang_compile_function.c',
+ 'shader/slang/slang_compile_operation.c',
+ 'shader/slang/slang_compile_struct.c',
+ 'shader/slang/slang_compile_variable.c',
+ 'shader/slang/slang_emit.c',
+ 'shader/slang/slang_ir.c',
+ 'shader/slang/slang_label.c',
+ 'shader/slang/slang_link.c',
+ 'shader/slang/slang_log.c',
+ 'shader/slang/slang_mem.c',
+ 'shader/slang/slang_preprocess.c',
+ 'shader/slang/slang_print.c',
+ 'shader/slang/slang_simplify.c',
+ 'shader/slang/slang_storage.c',
+ 'shader/slang/slang_typeinfo.c',
+ 'shader/slang/slang_vartable.c',
+ 'shader/slang/slang_utility.c',
+ ]
+
+ mesa_sources = (
+ main_sources +
+ math_sources +
+ vbo_sources +
+ vf_sources +
+ statetracker_sources +
+ shader_sources +
+ slang_sources
+ )
+
+ glapi_sources = [
+ 'main/dispatch.c',
+ 'glapi/glapi.c',
+ 'glapi/glapi_getproc.c',
+ 'glapi/glthread.c',
+ ]
+
+ #
+ # Assembly sources
+ #
+ if gcc and env['machine'] == 'x86':
+ env.Append(CPPDEFINES = [
+ 'USE_X86_ASM',
+ 'USE_MMX_ASM',
+ 'USE_3DNOW_ASM',
+ 'USE_SSE_ASM',
+ ])
+ mesa_sources += [
+ 'x86/common_x86.c',
+ 'x86/x86_xform.c',
+ 'x86/3dnow.c',
+ 'x86/sse.c',
+ 'x86/common_x86_asm.S',
+ 'x86/x86_xform2.S',
+ 'x86/x86_xform3.S',
+ 'x86/x86_xform4.S',
+ 'x86/x86_cliptest.S',
+ 'x86/mmx_blend.S',
+ 'x86/3dnow_xform1.S',
+ 'x86/3dnow_xform2.S',
+ 'x86/3dnow_xform3.S',
+ 'x86/3dnow_xform4.S',
+ 'x86/3dnow_normal.S',
+ 'x86/sse_xform1.S',
+ 'x86/sse_xform2.S',
+ 'x86/sse_xform3.S',
+ 'x86/sse_xform4.S',
+ 'x86/sse_normal.S',
+ 'x86/read_rgba_span_x86.S',
+ ]
+ glapi_sources += [
+ 'x86/glapi_x86.S',
+ ]
+ elif gcc and env['machine'] == 'x86_64':
+ env.Append(CPPDEFINES = [
+ 'USE_X86_64_ASM',
+ ])
+ mesa_sources += [
+ 'x86-64/x86-64.c',
+ 'x86-64/xform4.S',
+ ]
+ glapi_sources += [
+ 'x86-64/glapi_x86-64.S'
+ ]
+ elif gcc and env['machine'] == 'ppc':
+ env.Append(CPPDEFINES = [
+ 'USE_PPC_ASM',
+ 'USE_VMX_ASM',
+ ])
+ mesa_sources += [
+ 'ppc/common_ppc.c',
+ ]
+ glapi_sources += [
+ ]
+ elif gcc and env['machine'] == 'sparc':
+ mesa_sources += [
+ 'sparc/sparc.c',
+ 'sparc/clip.S',
+ 'sparc/norm.S',
+ 'sparc/xform.S',
+ ]
+ glapi_sources += [
+ 'sparc/glapi_sparc.S'
+ ]
+ else:
+ pass
+
+ # Generate matypes.h
+ if gcc and env['machine'] in ('x86', 'x86_64'):
+ # See http://www.scons.org/wiki/UsingCodeGenerators
+ gen_matypes = env.Program(
+ target = 'gen_matypes',
+ source = 'x86/gen_matypes.c',
+ )
+ matypes = env.Command(
+ 'matypes.h',
+ gen_matypes,
+ gen_matypes[0].abspath + ' > $TARGET',
+ )
+ # Add the dir containing the generated header (somewhere inside the
+ # build dir) to the include path
+ env.Append(CPPPATH = [matypes[0].dir])
+
+ #
+ # Libraries
+ #
+
+ mesa = env.ConvenienceLibrary(
+ target = 'mesa',
+ source = mesa_sources,
+ )
+ Export('mesa')
+
+ if not dri:
+ glapi = env.ConvenienceLibrary(
+ target = 'glapi',
+ source = glapi_sources,
+ )
+ Export('glapi')
+
diff --git a/src/mesa/drivers/allegro/amesa.c b/src/mesa/drivers/allegro/amesa.c
index a9d8f62f92..0744677d2b 100644
--- a/src/mesa/drivers/allegro/amesa.c
+++ b/src/mesa/drivers/allegro/amesa.c
@@ -338,7 +338,7 @@ void AMesaDestroyBuffer(AMesaBuffer buffer)
{
if (buffer->Screen) destroy_bitmap(buffer->Screen);
if (buffer->Background) destroy_bitmap(buffer->Background);
- _mesa_unreference_framebuffer(&buffer->GLBuffer);
+ _mesa_reference_framebuffer(&buffer->GLBuffer, NULL);
free(buffer);
}
diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
index 986f751bdc..31a027e0e4 100644
--- a/src/mesa/drivers/common/driverfuncs.c
+++ b/src/mesa/drivers/common/driverfuncs.c
@@ -24,16 +24,22 @@
#include "main/glheader.h"
+#include "main/accum.h"
#include "main/imports.h"
#include "main/arrayobj.h"
#include "main/buffers.h"
+#include "main/colortab.h"
#include "main/context.h"
+#include "main/convolve.h"
+#include "main/drawpix.h"
#include "main/framebuffer.h"
#include "main/mipmap.h"
#include "main/queryobj.h"
+#include "main/rastpos.h"
#include "main/renderbuffer.h"
#include "main/texcompress.h"
#include "main/texformat.h"
+#include "main/texgetimage.h"
#include "main/teximage.h"
#include "main/texobj.h"
#include "main/texstore.h"
@@ -44,6 +50,9 @@
#include "main/fbobject.h"
#include "main/texrender.h"
#endif
+#if FEATURE_ARB_sync
+#include "main/syncobj.h"
+#endif
#include "shader/program.h"
#include "shader/prog_execute.h"
@@ -80,12 +89,13 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
/* framebuffer/image functions */
driver->Clear = _swrast_Clear;
- driver->Accum = _swrast_Accum;
- driver->RasterPos = _tnl_RasterPos;
- driver->DrawPixels = _swrast_DrawPixels;
+
+ _MESA_INIT_ACCUM_FUNCTIONS(driver, _swrast_);
+ _MESA_INIT_DRAWPIX_FUNCTIONS(driver, _swrast_);
+
+ _MESA_INIT_RASTPOS_FUNCTIONS(driver, _tnl_);
+
driver->ReadPixels = _swrast_ReadPixels;
- driver->CopyPixels = _swrast_CopyPixels;
- driver->Bitmap = _swrast_Bitmap;
/* Texture functions */
driver->ChooseTextureFormat = _mesa_choose_tex_format;
@@ -125,18 +135,15 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
driver->UpdateTexturePalette = NULL;
/* imaging */
- driver->CopyColorTable = _swrast_CopyColorTable;
- driver->CopyColorSubTable = _swrast_CopyColorSubTable;
- driver->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
- driver->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+ /* swrast does not need UpdateTexturePalette */
+#define _swrast_UpdateTexturePalette NULL
+ _MESA_INIT_COLORTABLE_FUNCTIONS(driver, _swrast_);
+ _MESA_INIT_CONVOLVE_FUNCTIONS(driver, _swrast_);
/* Vertex/fragment programs */
driver->BindProgram = NULL;
driver->NewProgram = _mesa_new_program;
driver->DeleteProgram = _mesa_delete_program;
-#if FEATURE_MESA_program_debug
- driver->GetProgramRegister = _mesa_get_program_register;
-#endif /* FEATURE_MESA_program_debug */
/* simple state commands */
driver->AlphaFunc = NULL;
@@ -202,17 +209,17 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
driver->GetDoublev = NULL;
driver->GetFloatv = NULL;
driver->GetIntegerv = NULL;
+ driver->GetInteger64v = NULL;
driver->GetPointerv = NULL;
-#if FEATURE_ARB_vertex_buffer_object
- driver->NewBufferObject = _mesa_new_buffer_object;
- driver->DeleteBuffer = _mesa_delete_buffer_object;
- driver->BindBuffer = NULL;
- driver->BufferData = _mesa_buffer_data;
- driver->BufferSubData = _mesa_buffer_subdata;
- driver->GetBufferSubData = _mesa_buffer_get_subdata;
- driver->MapBuffer = _mesa_buffer_map;
- driver->UnmapBuffer = _mesa_buffer_unmap;
+ /* buffer objects */
+ _mesa_init_buffer_object_functions(driver);
+
+ /* query objects */
+ _mesa_init_query_object_functions(driver);
+
+#if FEATURE_ARB_sync
+ _mesa_init_sync_object_functions(driver);
#endif
#if FEATURE_EXT_framebuffer_object
@@ -227,13 +234,6 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
driver->BlitFramebuffer = _swrast_BlitFramebuffer;
#endif
- /* query objects */
- driver->NewQueryObject = _mesa_new_query_object;
- driver->DeleteQuery = _mesa_delete_query;
- driver->BeginQuery = _mesa_begin_query;
- driver->EndQuery = _mesa_end_query;
- driver->WaitQuery = _mesa_wait_query;
-
/* APPLE_vertex_array_object */
driver->NewArrayObject = _mesa_new_array_object;
driver->DeleteArrayObject = _mesa_delete_array_object;
@@ -308,7 +308,7 @@ _mesa_init_driver_state(GLcontext *ctx)
ctx->Driver.Enable(ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag);
ctx->Driver.Enable(ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag);
ctx->Driver.Enable(ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled);
- ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
+ ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil._Enabled);
ctx->Driver.Enable(ctx, GL_TEXTURE_1D, GL_FALSE);
ctx->Driver.Enable(ctx, GL_TEXTURE_2D, GL_FALSE);
ctx->Driver.Enable(ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE);
diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
new file mode 100644
index 0000000000..05909cfa30
--- /dev/null
+++ b/src/mesa/drivers/common/meta.c
@@ -0,0 +1,2039 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Meta operations. Some GL operations can be expressed in terms of
+ * other GL operations. For example, glBlitFramebuffer() can be done
+ * with texture mapping and glClear() can be done with polygon rendering.
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "main/arrayobj.h"
+#include "main/blend.h"
+#include "main/bufferobj.h"
+#include "main/buffers.h"
+#include "main/depth.h"
+#include "main/enable.h"
+#include "main/fbobject.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/matrix.h"
+#include "main/mipmap.h"
+#include "main/polygon.h"
+#include "main/readpix.h"
+#include "main/scissor.h"
+#include "main/shaders.h"
+#include "main/stencil.h"
+#include "main/texobj.h"
+#include "main/texenv.h"
+#include "main/teximage.h"
+#include "main/texparam.h"
+#include "main/texstate.h"
+#include "main/varray.h"
+#include "main/viewport.h"
+#include "shader/program.h"
+#include "shader/arbprogram.h"
+#include "swrast/swrast.h"
+#include "drivers/common/meta.h"
+
+
+/** Return offset in bytes of the field within a vertex struct */
+#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
+
+
+/**
+ * State which we may save/restore across meta ops.
+ * XXX this may be incomplete...
+ */
+struct save_state
+{
+ GLbitfield SavedState; /**< bitmask of META_* flags */
+
+ /** META_ALPHA_TEST */
+ GLboolean AlphaEnabled;
+
+ /** META_BLEND */
+ GLboolean BlendEnabled;
+ GLboolean ColorLogicOpEnabled;
+
+ /** META_COLOR_MASK */
+ GLubyte ColorMask[4];
+
+ /** META_DEPTH_TEST */
+ struct gl_depthbuffer_attrib Depth;
+
+ /** META_FOG */
+ GLboolean Fog;
+
+ /** META_PIXEL_STORE */
+ struct gl_pixelstore_attrib Pack, Unpack;
+
+ /** META_RASTERIZATION */
+ GLenum FrontPolygonMode, BackPolygonMode;
+ GLboolean PolygonOffset;
+ GLboolean PolygonSmooth;
+ GLboolean PolygonStipple;
+ GLboolean PolygonCull;
+
+ /** META_SCISSOR */
+ struct gl_scissor_attrib Scissor;
+
+ /** META_SHADER */
+ GLboolean VertexProgramEnabled;
+ struct gl_vertex_program *VertexProgram;
+ GLboolean FragmentProgramEnabled;
+ struct gl_fragment_program *FragmentProgram;
+ GLuint Shader;
+
+ /** META_STENCIL_TEST */
+ struct gl_stencil_attrib Stencil;
+
+ /** META_TRANSFORM */
+ GLenum MatrixMode;
+ GLfloat ModelviewMatrix[16];
+ GLfloat ProjectionMatrix[16];
+ GLfloat TextureMatrix[16];
+ GLbitfield ClipPlanesEnabled;
+
+ /** META_TEXTURE */
+ GLuint ActiveUnit;
+ GLuint ClientActiveUnit;
+ /** for unit[0] only */
+ struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS];
+ /** mask of TEXTURE_2D_BIT, etc */
+ GLbitfield TexEnabled[MAX_TEXTURE_UNITS];
+ GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS];
+ GLuint EnvMode; /* unit[0] only */
+
+ /** META_VERTEX */
+ struct gl_array_object *ArrayObj;
+ struct gl_buffer_object *ArrayBufferObj;
+
+ /** META_VIEWPORT */
+ GLint ViewportX, ViewportY, ViewportW, ViewportH;
+ GLclampd DepthNear, DepthFar;
+
+ /** Miscellaneous (always disabled) */
+ GLboolean Lighting;
+};
+
+
+/**
+ * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc.
+ * This is currently shared by all the meta ops. But we could create a
+ * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc.
+ */
+struct temp_texture
+{
+ GLuint TexObj;
+ GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */
+ GLsizei MinSize; /**< Min texture size to allocate */
+ GLsizei MaxSize; /**< Max possible texture size */
+ GLboolean NPOT; /**< Non-power of two size OK? */
+ GLsizei Width, Height; /**< Current texture size */
+ GLenum IntFormat;
+ GLfloat Sright, Ttop; /**< right, top texcoords */
+};
+
+
+/**
+ * State for glBlitFramebufer()
+ */
+struct blit_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+ GLuint DepthFP;
+};
+
+
+/**
+ * State for glClear()
+ */
+struct clear_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+};
+
+
+/**
+ * State for glCopyPixels()
+ */
+struct copypix_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+};
+
+
+/**
+ * State for glDrawPixels()
+ */
+struct drawpix_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+
+ GLuint StencilFP; /**< Fragment program for drawing stencil images */
+ GLuint DepthFP; /**< Fragment program for drawing depth images */
+};
+
+
+/**
+ * State for glBitmap()
+ */
+struct bitmap_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+ struct temp_texture Tex; /**< separate texture from other meta ops */
+};
+
+
+/**
+ * State for _mesa_meta_generate_mipmap()
+ */
+struct gen_mipmap_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+ GLuint FBO;
+};
+
+
+/**
+ * All per-context meta state.
+ */
+struct gl_meta_state
+{
+ struct save_state Save; /**< state saved during meta-ops */
+
+ struct temp_texture TempTex;
+
+ struct blit_state Blit; /**< For _mesa_meta_blit_framebuffer() */
+ struct clear_state Clear; /**< For _mesa_meta_clear() */
+ struct copypix_state CopyPix; /**< For _mesa_meta_copy_pixels() */
+ struct drawpix_state DrawPix; /**< For _mesa_meta_draw_pixels() */
+ struct bitmap_state Bitmap; /**< For _mesa_meta_bitmap() */
+ struct gen_mipmap_state Mipmap; /**< For _mesa_meta_generate_mipmap() */
+};
+
+
+/**
+ * Initialize meta-ops for a context.
+ * To be called once during context creation.
+ */
+void
+_mesa_meta_init(GLcontext *ctx)
+{
+ ASSERT(!ctx->Meta);
+
+ ctx->Meta = CALLOC_STRUCT(gl_meta_state);
+}
+
+
+/**
+ * Free context meta-op state.
+ * To be called once during context destruction.
+ */
+void
+_mesa_meta_free(GLcontext *ctx)
+{
+ struct gl_meta_state *meta = ctx->Meta;
+
+ if (_mesa_get_current_context()) {
+ /* if there's no current context, these textures, buffers, etc should
+ * still get freed by _mesa_free_context_data().
+ */
+
+ /* the temporary texture */
+ _mesa_DeleteTextures(1, &meta->TempTex.TexObj);
+
+ /* glBlitFramebuffer */
+ _mesa_DeleteBuffersARB(1, & meta->Blit.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->Blit.ArrayObj);
+ _mesa_DeletePrograms(1, &meta->Blit.DepthFP);
+
+ /* glClear */
+ _mesa_DeleteBuffersARB(1, & meta->Clear.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->Clear.ArrayObj);
+
+ /* glCopyPixels */
+ _mesa_DeleteBuffersARB(1, & meta->CopyPix.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->CopyPix.ArrayObj);
+
+ /* glDrawPixels */
+ _mesa_DeleteBuffersARB(1, & meta->DrawPix.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->DrawPix.ArrayObj);
+ _mesa_DeletePrograms(1, &meta->DrawPix.DepthFP);
+ _mesa_DeletePrograms(1, &meta->DrawPix.StencilFP);
+
+ /* glBitmap */
+ _mesa_DeleteBuffersARB(1, & meta->Bitmap.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->Bitmap.ArrayObj);
+ _mesa_DeleteTextures(1, &meta->Bitmap.Tex.TexObj);
+ }
+
+ _mesa_free(ctx->Meta);
+ ctx->Meta = NULL;
+}
+
+
+/**
+ * Enter meta state. This is like a light-weight version of glPushAttrib
+ * but it also resets most GL state back to default values.
+ *
+ * \param state bitmask of META_* flags indicating which attribute groups
+ * to save and reset to their defaults
+ */
+static void
+_mesa_meta_begin(GLcontext *ctx, GLbitfield state)
+{
+ struct save_state *save = &ctx->Meta->Save;
+
+ save->SavedState = state;
+
+ if (state & META_ALPHA_TEST) {
+ save->AlphaEnabled = ctx->Color.AlphaEnabled;
+ if (ctx->Color.AlphaEnabled)
+ _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE);
+ }
+
+ if (state & META_BLEND) {
+ save->BlendEnabled = ctx->Color.BlendEnabled;
+ if (ctx->Color.BlendEnabled)
+ _mesa_set_enable(ctx, GL_BLEND, GL_FALSE);
+ save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
+ if (ctx->Color.ColorLogicOpEnabled)
+ _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE);
+ }
+
+ if (state & META_COLOR_MASK) {
+ COPY_4V(save->ColorMask, ctx->Color.ColorMask);
+ if (!ctx->Color.ColorMask[0] ||
+ !ctx->Color.ColorMask[1] ||
+ !ctx->Color.ColorMask[2] ||
+ !ctx->Color.ColorMask[3])
+ _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+
+ if (state & META_DEPTH_TEST) {
+ save->Depth = ctx->Depth; /* struct copy */
+ if (ctx->Depth.Test)
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
+ }
+
+ if (state & META_FOG) {
+ save->Fog = ctx->Fog.Enabled;
+ if (ctx->Fog.Enabled)
+ _mesa_set_enable(ctx, GL_FOG, GL_FALSE);
+ }
+
+ if (state & META_PIXEL_STORE) {
+ save->Pack = ctx->Pack;
+ save->Unpack = ctx->Unpack;
+ ctx->Pack = ctx->DefaultPacking;
+ ctx->Unpack = ctx->DefaultPacking;
+ }
+
+ if (state & META_RASTERIZATION) {
+ save->FrontPolygonMode = ctx->Polygon.FrontMode;
+ save->BackPolygonMode = ctx->Polygon.BackMode;
+ save->PolygonOffset = ctx->Polygon.OffsetFill;
+ save->PolygonSmooth = ctx->Polygon.SmoothFlag;
+ save->PolygonStipple = ctx->Polygon.StippleFlag;
+ save->PolygonCull = ctx->Polygon.CullFlag;
+ _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE);
+ _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE);
+ _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE);
+ }
+
+ if (state & META_SCISSOR) {
+ save->Scissor = ctx->Scissor; /* struct copy */
+ }
+
+ if (state & META_SHADER) {
+ if (ctx->Extensions.ARB_vertex_program) {
+ save->VertexProgramEnabled = ctx->VertexProgram.Enabled;
+ save->VertexProgram = ctx->VertexProgram.Current;
+ _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE);
+ }
+
+ if (ctx->Extensions.ARB_fragment_program) {
+ save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled;
+ save->FragmentProgram = ctx->FragmentProgram.Current;
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE);
+ }
+
+ if (ctx->Extensions.ARB_shader_objects) {
+ save->Shader = ctx->Shader.CurrentProgram ?
+ ctx->Shader.CurrentProgram->Name : 0;
+ _mesa_UseProgramObjectARB(0);
+ }
+ }
+
+ if (state & META_STENCIL_TEST) {
+ save->Stencil = ctx->Stencil; /* struct copy */
+ if (ctx->Stencil.Enabled)
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE);
+ /* NOTE: other stencil state not reset */
+ }
+
+ if (state & META_TEXTURE) {
+ GLuint u, tgt;
+
+ save->ActiveUnit = ctx->Texture.CurrentUnit;
+ save->ClientActiveUnit = ctx->Array.ActiveTexture;
+ save->EnvMode = ctx->Texture.Unit[0].EnvMode;
+
+ if (ctx->Texture._EnabledUnits |
+ ctx->Texture._EnabledCoordUnits |
+ ctx->Texture._TexGenEnabled |
+ ctx->Texture._TexMatEnabled) {
+
+ /* Disable all texture units */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled;
+ save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled;
+ if (ctx->Texture.Unit[u].Enabled ||
+ ctx->Texture.Unit[u].TexGenEnabled) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
+ _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
+ }
+ }
+ }
+
+ /* save current texture objects for unit[0] only */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&save->CurrentTexture[tgt],
+ ctx->Texture.Unit[0].CurrentTex[tgt]);
+ }
+
+ /* set defaults for unit[0] */
+ _mesa_ActiveTextureARB(GL_TEXTURE0);
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ }
+
+ if (state & META_TRANSFORM) {
+ GLuint activeTexture = ctx->Texture.CurrentUnit;
+ _mesa_memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m,
+ 16 * sizeof(GLfloat));
+ _mesa_memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m,
+ 16 * sizeof(GLfloat));
+ _mesa_memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m,
+ 16 * sizeof(GLfloat));
+ save->MatrixMode = ctx->Transform.MatrixMode;
+ /* set 1:1 vertex:pixel coordinate transform */
+ _mesa_ActiveTextureARB(GL_TEXTURE0);
+ _mesa_MatrixMode(GL_TEXTURE);
+ _mesa_LoadIdentity();
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_LoadIdentity();
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_LoadIdentity();
+ _mesa_Ortho(0.0F, ctx->DrawBuffer->Width,
+ 0.0F, ctx->DrawBuffer->Height,
+ -1.0F, 1.0F);
+ save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
+ if (ctx->Transform.ClipPlanesEnabled) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
+ }
+ }
+ }
+
+ if (state & META_VERTEX) {
+ /* save vertex array object state */
+ _mesa_reference_array_object(ctx, &save->ArrayObj,
+ ctx->Array.ArrayObj);
+ _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj,
+ ctx->Array.ArrayBufferObj);
+ /* set some default state? */
+ }
+
+ if (state & META_VIEWPORT) {
+ /* save viewport state */
+ save->ViewportX = ctx->Viewport.X;
+ save->ViewportY = ctx->Viewport.Y;
+ save->ViewportW = ctx->Viewport.Width;
+ save->ViewportH = ctx->Viewport.Height;
+ /* set viewport to match window size */
+ if (ctx->Viewport.X != 0 ||
+ ctx->Viewport.Y != 0 ||
+ ctx->Viewport.Width != ctx->DrawBuffer->Width ||
+ ctx->Viewport.Height != ctx->DrawBuffer->Height) {
+ _mesa_set_viewport(ctx, 0, 0,
+ ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
+ }
+ /* save depth range state */
+ save->DepthNear = ctx->Viewport.Near;
+ save->DepthFar = ctx->Viewport.Far;
+ /* set depth range to default */
+ _mesa_DepthRange(0.0, 1.0);
+ }
+
+ /* misc */
+ {
+ save->Lighting = ctx->Light.Enabled;
+ if (ctx->Light.Enabled)
+ _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE);
+ }
+}
+
+
+/**
+ * Leave meta state. This is like a light-weight version of glPopAttrib().
+ */
+static void
+_mesa_meta_end(GLcontext *ctx)
+{
+ struct save_state *save = &ctx->Meta->Save;
+ const GLbitfield state = save->SavedState;
+
+ if (state & META_ALPHA_TEST) {
+ if (ctx->Color.AlphaEnabled != save->AlphaEnabled)
+ _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled);
+ }
+
+ if (state & META_BLEND) {
+ if (ctx->Color.BlendEnabled != save->BlendEnabled)
+ _mesa_set_enable(ctx, GL_BLEND, save->BlendEnabled);
+ if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
+ _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
+ }
+
+ if (state & META_COLOR_MASK) {
+ if (!TEST_EQ_4V(ctx->Color.ColorMask, save->ColorMask))
+ _mesa_ColorMask(save->ColorMask[0], save->ColorMask[1],
+ save->ColorMask[2], save->ColorMask[3]);
+ }
+
+ if (state & META_DEPTH_TEST) {
+ if (ctx->Depth.Test != save->Depth.Test)
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test);
+ _mesa_DepthFunc(save->Depth.Func);
+ _mesa_DepthMask(save->Depth.Mask);
+ }
+
+ if (state & META_FOG) {
+ _mesa_set_enable(ctx, GL_FOG, save->Fog);
+ }
+
+ if (state & META_PIXEL_STORE) {
+ ctx->Pack = save->Pack;
+ ctx->Unpack = save->Unpack;
+ }
+
+ if (state & META_RASTERIZATION) {
+ _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode);
+ _mesa_PolygonMode(GL_BACK, save->BackPolygonMode);
+ _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset);
+ _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth);
+ _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull);
+ }
+
+ if (state & META_SCISSOR) {
+ _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled);
+ _mesa_Scissor(save->Scissor.X, save->Scissor.Y,
+ save->Scissor.Width, save->Scissor.Height);
+ }
+
+ if (state & META_SHADER) {
+ if (ctx->Extensions.ARB_vertex_program) {
+ _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB,
+ save->VertexProgramEnabled);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ save->VertexProgram);
+ }
+
+ if (ctx->Extensions.ARB_fragment_program) {
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ save->FragmentProgramEnabled);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ save->FragmentProgram);
+ }
+
+ if (ctx->Extensions.ARB_shader_objects) {
+ _mesa_UseProgramObjectARB(save->Shader);
+ }
+ }
+
+ if (state & META_STENCIL_TEST) {
+ const struct gl_stencil_attrib *stencil = &save->Stencil;
+
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
+ _mesa_ClearStencil(stencil->Clear);
+ if (ctx->Extensions.EXT_stencil_two_side) {
+ _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
+ stencil->TestTwoSide);
+ _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
+ ? GL_BACK : GL_FRONT);
+ }
+ /* front state */
+ _mesa_StencilFuncSeparate(GL_FRONT,
+ stencil->Function[0],
+ stencil->Ref[0],
+ stencil->ValueMask[0]);
+ _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
+ _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
+ stencil->ZFailFunc[0],
+ stencil->ZPassFunc[0]);
+ /* back state */
+ _mesa_StencilFuncSeparate(GL_BACK,
+ stencil->Function[1],
+ stencil->Ref[1],
+ stencil->ValueMask[1]);
+ _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
+ _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
+ stencil->ZFailFunc[1],
+ stencil->ZPassFunc[1]);
+ }
+
+ if (state & META_TEXTURE) {
+ GLuint u, tgt;
+
+ ASSERT(ctx->Texture.CurrentUnit == 0);
+
+ /* restore texenv for unit[0] */
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode);
+
+ /* restore texture objects for unit[0] only */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
+ save->CurrentTexture[tgt]);
+ }
+
+ /* Re-enable textures, texgen */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ if (save->TexEnabled[u]) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
+
+ if (save->TexEnabled[u] & TEXTURE_1D_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_2D_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_3D_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_CUBE_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_RECT_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_TRUE);
+ }
+
+ if (save->TexGenEnabled[u]) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
+
+ if (save->TexGenEnabled[u] & S_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_TRUE);
+ if (save->TexGenEnabled[u] & T_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_TRUE);
+ if (save->TexGenEnabled[u] & R_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_TRUE);
+ if (save->TexGenEnabled[u] & Q_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_TRUE);
+ }
+ }
+
+ /* restore current unit state */
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit);
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit);
+ }
+
+ if (state & META_TRANSFORM) {
+ GLuint activeTexture = ctx->Texture.CurrentUnit;
+ _mesa_ActiveTextureARB(GL_TEXTURE0);
+ _mesa_MatrixMode(GL_TEXTURE);
+ _mesa_LoadMatrixf(save->TextureMatrix);
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
+
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_LoadMatrixf(save->ModelviewMatrix);
+
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_LoadMatrixf(save->ProjectionMatrix);
+
+ _mesa_MatrixMode(save->MatrixMode);
+
+ save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
+ if (save->ClipPlanesEnabled) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
+ if (save->ClipPlanesEnabled & (1 << i)) {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
+ }
+ }
+ }
+ }
+
+ if (state & META_VERTEX) {
+ /* restore vertex buffer object */
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name);
+ _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL);
+
+ /* restore vertex array object */
+ _mesa_BindVertexArray(save->ArrayObj->Name);
+ _mesa_reference_array_object(ctx, &save->ArrayObj, NULL);
+ }
+
+ if (state & META_VIEWPORT) {
+ if (save->ViewportX != ctx->Viewport.X ||
+ save->ViewportY != ctx->Viewport.Y ||
+ save->ViewportW != ctx->Viewport.Width ||
+ save->ViewportH != ctx->Viewport.Height) {
+ _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY,
+ save->ViewportW, save->ViewportH);
+ }
+ _mesa_DepthRange(save->DepthNear, save->DepthFar);
+ }
+
+ /* misc */
+ if (save->Lighting) {
+ _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE);
+ }
+ if (save->Fog) {
+ _mesa_set_enable(ctx, GL_FOG, GL_TRUE);
+ }
+}
+
+
+/**
+ * One-time init for a temp_texture object.
+ * Choose tex target, compute max tex size, etc.
+ */
+static void
+init_temp_texture(GLcontext *ctx, struct temp_texture *tex)
+{
+ /* prefer texture rectangle */
+ if (ctx->Extensions.NV_texture_rectangle) {
+ tex->Target = GL_TEXTURE_RECTANGLE;
+ tex->MaxSize = ctx->Const.MaxTextureRectSize;
+ tex->NPOT = GL_TRUE;
+ }
+ else {
+ /* use 2D texture, NPOT if possible */
+ tex->Target = GL_TEXTURE_2D;
+ tex->MaxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ tex->NPOT = ctx->Extensions.ARB_texture_non_power_of_two;
+ }
+ tex->MinSize = 16; /* 16 x 16 at least */
+ assert(tex->MaxSize > 0);
+
+ _mesa_GenTextures(1, &tex->TexObj);
+ _mesa_BindTexture(tex->Target, tex->TexObj);
+}
+
+
+/**
+ * Return pointer to temp_texture info for non-bitmap ops.
+ * This does some one-time init if needed.
+ */
+static struct temp_texture *
+get_temp_texture(GLcontext *ctx)
+{
+ struct temp_texture *tex = &ctx->Meta->TempTex;
+
+ if (!tex->TexObj) {
+ init_temp_texture(ctx, tex);
+ }
+
+ return tex;
+}
+
+
+/**
+ * Return pointer to temp_texture info for _mesa_meta_bitmap().
+ * We use a separate texture for bitmaps to reduce texture
+ * allocation/deallocation.
+ */
+static struct temp_texture *
+get_bitmap_temp_texture(GLcontext *ctx)
+{
+ struct temp_texture *tex = &ctx->Meta->Bitmap.Tex;
+
+ if (!tex->TexObj) {
+ init_temp_texture(ctx, tex);
+ }
+
+ return tex;
+}
+
+
+/**
+ * Compute the width/height of texture needed to draw an image of the
+ * given size. Return a flag indicating whether the current texture
+ * can be re-used (glTexSubImage2D) or if a new texture needs to be
+ * allocated (glTexImage2D).
+ * Also, compute s/t texcoords for drawing.
+ *
+ * \return GL_TRUE if new texture is needed, GL_FALSE otherwise
+ */
+static GLboolean
+alloc_texture(struct temp_texture *tex,
+ GLsizei width, GLsizei height, GLenum intFormat)
+{
+ GLboolean newTex = GL_FALSE;
+
+ ASSERT(width <= tex->MaxSize);
+ ASSERT(height <= tex->MaxSize);
+
+ if (width > tex->Width ||
+ height > tex->Height ||
+ intFormat != tex->IntFormat) {
+ /* alloc new texture (larger or different format) */
+
+ if (tex->NPOT) {
+ /* use non-power of two size */
+ tex->Width = MAX2(tex->MinSize, width);
+ tex->Height = MAX2(tex->MinSize, height);
+ }
+ else {
+ /* find power of two size */
+ GLsizei w, h;
+ w = h = tex->MinSize;
+ while (w < width)
+ w *= 2;
+ while (h < height)
+ h *= 2;
+ tex->Width = w;
+ tex->Height = h;
+ }
+
+ tex->IntFormat = intFormat;
+
+ newTex = GL_TRUE;
+ }
+
+ /* compute texcoords */
+ if (tex->Target == GL_TEXTURE_RECTANGLE) {
+ tex->Sright = (GLfloat) width;
+ tex->Ttop = (GLfloat) height;
+ }
+ else {
+ tex->Sright = (GLfloat) width / tex->Width;
+ tex->Ttop = (GLfloat) height / tex->Height;
+ }
+
+ return newTex;
+}
+
+
+/**
+ * Setup/load texture for glCopyPixels or glBlitFramebuffer.
+ */
+static void
+setup_copypix_texture(struct temp_texture *tex,
+ GLboolean newTex,
+ GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height, GLenum intFormat,
+ GLenum filter)
+{
+ _mesa_BindTexture(tex->Target, tex->TexObj);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ /* copy framebuffer image to texture */
+ if (newTex) {
+ /* create new tex image */
+ if (tex->Width == width && tex->Height == height) {
+ /* create new tex with framebuffer data */
+ _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat,
+ srcX, srcY, width, height, 0);
+ }
+ else {
+ /* create empty texture */
+ _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
+ tex->Width, tex->Height, 0,
+ intFormat, GL_UNSIGNED_BYTE, NULL);
+ /* load image */
+ _mesa_CopyTexSubImage2D(tex->Target, 0,
+ 0, 0, srcX, srcY, width, height);
+ }
+ }
+ else {
+ /* replace existing tex image */
+ _mesa_CopyTexSubImage2D(tex->Target, 0,
+ 0, 0, srcX, srcY, width, height);
+ }
+}
+
+
+/**
+ * Setup/load texture for glDrawPixels.
+ */
+static void
+setup_drawpix_texture(struct temp_texture *tex,
+ GLboolean newTex,
+ GLenum texIntFormat,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels)
+{
+ _mesa_BindTexture(tex->Target, tex->TexObj);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ /* copy pixel data to texture */
+ if (newTex) {
+ /* create new tex image */
+ if (tex->Width == width && tex->Height == height) {
+ /* create new tex and load image data */
+ _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
+ tex->Width, tex->Height, 0, format, type, pixels);
+ }
+ else {
+ /* create empty texture */
+ _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
+ tex->Width, tex->Height, 0, format, type, NULL);
+ /* load image */
+ _mesa_TexSubImage2D(tex->Target, 0,
+ 0, 0, width, height, format, type, pixels);
+ }
+ }
+ else {
+ /* replace existing tex image */
+ _mesa_TexSubImage2D(tex->Target, 0,
+ 0, 0, width, height, format, type, pixels);
+ }
+}
+
+
+
+/**
+ * One-time init for drawing depth pixels.
+ */
+static void
+init_blit_depth_pixels(GLcontext *ctx)
+{
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
+ "END \n";
+ char program2[200];
+ struct blit_state *blit = &ctx->Meta->Blit;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(blit->DepthFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &blit->DepthFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
+ * of texture mapping and polygon rendering.
+ */
+void
+_mesa_meta_blit_framebuffer(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ struct blit_state *blit = &ctx->Meta->Blit;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const GLsizei maxTexSize = tex->MaxSize;
+ const GLint srcX = MIN2(srcX0, srcX1);
+ const GLint srcY = MIN2(srcY0, srcY1);
+ const GLint srcW = abs(srcX1 - srcX0);
+ const GLint srcH = abs(srcY1 - srcY0);
+ const GLboolean srcFlipX = srcX1 < srcX0;
+ const GLboolean srcFlipY = srcY1 < srcY0;
+ struct vertex {
+ GLfloat x, y, s, t;
+ };
+ struct vertex verts[4];
+ GLboolean newTex;
+
+ if (srcW > maxTexSize || srcH > maxTexSize) {
+ /* XXX avoid this fallback */
+ _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter);
+ return;
+ }
+
+ if (srcFlipX) {
+ GLint tmp = dstX0;
+ dstX0 = dstX1;
+ dstX1 = tmp;
+ }
+
+ if (srcFlipY) {
+ GLint tmp = dstY0;
+ dstY0 = dstY1;
+ dstY1 = tmp;
+ }
+
+ /* only scissor effects blit so save/clear all other relevant state */
+ _mesa_meta_begin(ctx, ~META_SCISSOR);
+
+ if (blit->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &blit->ArrayObj);
+ _mesa_BindVertexArray(blit->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &blit->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(blit->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
+ }
+
+ newTex = alloc_texture(tex, srcW, srcH, GL_RGBA);
+
+ /* vertex positions/texcoords (after texture allocation!) */
+ {
+ verts[0].x = (GLfloat) dstX0;
+ verts[0].y = (GLfloat) dstY0;
+ verts[1].x = (GLfloat) dstX1;
+ verts[1].y = (GLfloat) dstY0;
+ verts[2].x = (GLfloat) dstX1;
+ verts[2].y = (GLfloat) dstY1;
+ verts[3].x = (GLfloat) dstX0;
+ verts[3].y = (GLfloat) dstY1;
+
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[1].s = tex->Sright;
+ verts[1].t = 0.0F;
+ verts[2].s = tex->Sright;
+ verts[2].t = tex->Ttop;
+ verts[3].s = 0.0F;
+ verts[3].t = tex->Ttop;
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ _mesa_set_enable(ctx, tex->Target, GL_TRUE);
+
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ setup_copypix_texture(tex, newTex, srcX, srcY, srcW, srcH,
+ GL_RGBA, filter);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ GLuint *tmp = (GLuint *) _mesa_malloc(srcW * srcH * sizeof(GLuint));
+ if (tmp) {
+ if (!blit->DepthFP)
+ init_blit_depth_pixels(ctx);
+
+ /* maybe change tex format here */
+ newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT);
+
+ _mesa_ReadPixels(srcX, srcY, srcW, srcH,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
+
+ setup_drawpix_texture(tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
+ _mesa_DepthFunc(GL_ALWAYS);
+ _mesa_DepthMask(GL_TRUE);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+
+ _mesa_free(tmp);
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ /* XXX can't easily do stencil */
+ }
+
+ _mesa_set_enable(ctx, tex->Target, GL_FALSE);
+
+ _mesa_meta_end(ctx);
+
+ if (mask) {
+ _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter);
+ }
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
+ */
+void
+_mesa_meta_clear(GLcontext *ctx, GLbitfield buffers)
+{
+ struct clear_state *clear = &ctx->Meta->Clear;
+ struct vertex {
+ GLfloat x, y, z, r, g, b, a;
+ };
+ struct vertex verts[4];
+ /* save all state but scissor, pixel pack/unpack */
+ GLbitfield metaSave = META_ALL - META_SCISSOR - META_PIXEL_STORE;
+
+ if (buffers & BUFFER_BITS_COLOR) {
+ /* if clearing color buffers, don't save/restore colormask */
+ metaSave -= META_COLOR_MASK;
+ }
+
+ _mesa_meta_begin(ctx, metaSave);
+
+ if (clear->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &clear->ArrayObj);
+ _mesa_BindVertexArray(clear->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &clear->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_COLOR_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(clear->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
+ }
+
+ /* GL_COLOR_BUFFER_BIT */
+ if (buffers & BUFFER_BITS_COLOR) {
+ /* leave colormask, glDrawBuffer state as-is */
+ }
+ else {
+ ASSERT(metaSave & META_COLOR_MASK);
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ }
+
+ /* GL_DEPTH_BUFFER_BIT */
+ if (buffers & BUFFER_BIT_DEPTH) {
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
+ _mesa_DepthFunc(GL_ALWAYS);
+ _mesa_DepthMask(GL_TRUE);
+ }
+ else {
+ assert(!ctx->Depth.Test);
+ }
+
+ /* GL_STENCIL_BUFFER_BIT */
+ if (buffers & BUFFER_BIT_STENCIL) {
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
+ _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
+ GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
+ ctx->Stencil.Clear & 0x7fffffff,
+ ctx->Stencil.WriteMask[0]);
+ }
+ else {
+ assert(!ctx->Stencil.Enabled);
+ }
+
+ /* vertex positions/colors */
+ {
+ const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
+ const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
+ const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
+ const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
+ const GLfloat z = 1.0 - 2.0 * ctx->Depth.Clear;
+ GLuint i;
+
+ verts[0].x = x0;
+ verts[0].y = y0;
+ verts[0].z = z;
+ verts[1].x = x1;
+ verts[1].y = y0;
+ verts[1].z = z;
+ verts[2].x = x1;
+ verts[2].y = y1;
+ verts[2].z = z;
+ verts[3].x = x0;
+ verts[3].y = y1;
+ verts[3].z = z;
+
+ /* vertex colors */
+ for (i = 0; i < 4; i++) {
+ verts[i].r = ctx->Color.ClearColor[0];
+ verts[i].g = ctx->Color.ClearColor[1];
+ verts[i].b = ctx->Color.ClearColor[2];
+ verts[i].a = ctx->Color.ClearColor[3];
+ }
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ /* draw quad */
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ _mesa_meta_end(ctx);
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.CopyPixels() in terms
+ * of texture mapping and polygon rendering.
+ */
+void
+_mesa_meta_copy_pixels(GLcontext *ctx, GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height,
+ GLint dstX, GLint dstY, GLenum type)
+{
+ struct copypix_state *copypix = &ctx->Meta->CopyPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ struct vertex {
+ GLfloat x, y, z, s, t;
+ };
+ struct vertex verts[4];
+ GLboolean newTex;
+ GLenum intFormat = GL_RGBA;
+
+ if (type != GL_COLOR ||
+ ctx->_ImageTransferState ||
+ ctx->Fog.Enabled ||
+ width > tex->MaxSize ||
+ height > tex->MaxSize) {
+ /* XXX avoid this fallback */
+ _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type);
+ return;
+ }
+
+ /* Most GL state applies to glCopyPixels, but a there's a few things
+ * we need to override:
+ */
+ _mesa_meta_begin(ctx, (META_RASTERIZATION |
+ META_SHADER |
+ META_TEXTURE |
+ META_TRANSFORM |
+ META_VERTEX |
+ META_VIEWPORT));
+
+ if (copypix->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &copypix->ArrayObj);
+ _mesa_BindVertexArray(copypix->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &copypix->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(copypix->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
+ }
+
+ newTex = alloc_texture(tex, width, height, intFormat);
+
+ /* vertex positions, texcoords (after texture allocation!) */
+ {
+ const GLfloat dstX0 = (GLfloat) dstX;
+ const GLfloat dstY0 = (GLfloat) dstY;
+ const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX;
+ const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY;
+ const GLfloat z = ctx->Current.RasterPos[2];
+
+ verts[0].x = dstX0;
+ verts[0].y = dstY0;
+ verts[0].z = z;
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[1].x = dstX1;
+ verts[1].y = dstY0;
+ verts[1].z = z;
+ verts[1].s = tex->Sright;
+ verts[1].t = 0.0F;
+ verts[2].x = dstX1;
+ verts[2].y = dstY1;
+ verts[2].z = z;
+ verts[2].s = tex->Sright;
+ verts[2].t = tex->Ttop;
+ verts[3].x = dstX0;
+ verts[3].y = dstY1;
+ verts[3].z = z;
+ verts[3].s = 0.0F;
+ verts[3].t = tex->Ttop;
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ /* Alloc/setup texture */
+ setup_copypix_texture(tex, newTex, srcX, srcY, width, height,
+ GL_RGBA, GL_NEAREST);
+
+ _mesa_set_enable(ctx, tex->Target, GL_TRUE);
+
+ /* draw textured quad */
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ _mesa_set_enable(ctx, tex->Target, GL_FALSE);
+
+ _mesa_meta_end(ctx);
+}
+
+
+
+/**
+ * When the glDrawPixels() image size is greater than the max rectangle
+ * texture size we use this function to break the glDrawPixels() image
+ * into tiles which fit into the max texture size.
+ */
+static void
+tiled_draw_pixels(GLcontext *ctx,
+ GLint tileSize,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ struct gl_pixelstore_attrib tileUnpack = *unpack;
+ GLint i, j;
+
+ if (tileUnpack.RowLength == 0)
+ tileUnpack.RowLength = width;
+
+ for (i = 0; i < width; i += tileSize) {
+ const GLint tileWidth = MIN2(tileSize, width - i);
+ const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX);
+
+ tileUnpack.SkipPixels = unpack->SkipPixels + i;
+
+ for (j = 0; j < height; j += tileSize) {
+ const GLint tileHeight = MIN2(tileSize, height - j);
+ const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY);
+
+ tileUnpack.SkipRows = unpack->SkipRows + j;
+
+ _mesa_meta_draw_pixels(ctx, tileX, tileY,
+ tileWidth, tileHeight,
+ format, type, &tileUnpack, pixels);
+ }
+ }
+}
+
+
+/**
+ * One-time init for drawing stencil pixels.
+ */
+static void
+init_draw_stencil_pixels(GLcontext *ctx)
+{
+ /* This program is run eight times, once for each stencil bit.
+ * The stencil values to draw are found in an 8-bit alpha texture.
+ * We read the texture/stencil value and test if bit 'b' is set.
+ * If the bit is not set, use KIL to kill the fragment.
+ * Finally, we use the stencil test to update the stencil buffer.
+ *
+ * The basic algorithm for checking if a bit is set is:
+ * if (is_odd(value / (1 << bit)))
+ * result is one (or non-zero).
+ * else
+ * result is zero.
+ * The program parameter contains three values:
+ * parm.x = 255 / (1 << bit)
+ * parm.y = 0.5
+ * parm.z = 0.0
+ */
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "PARAM parm = program.local[0]; \n"
+ "TEMP t; \n"
+ "TEX t, fragment.texcoord[0], texture[0], %s; \n" /* NOTE %s here! */
+ "# t = t * 255 / bit \n"
+ "MUL t.x, t.a, parm.x; \n"
+ "# t = (int) t \n"
+ "FRC t.y, t.x; \n"
+ "SUB t.x, t.x, t.y; \n"
+ "# t = t * 0.5 \n"
+ "MUL t.x, t.x, parm.y; \n"
+ "# t = fract(t.x) \n"
+ "FRC t.x, t.x; # if t.x != 0, then the bit is set \n"
+ "# t.x = (t.x == 0 ? 1 : 0) \n"
+ "SGE t.x, -t.x, parm.z; \n"
+ "KIL -t.x; \n"
+ "# for debug only \n"
+ "#MOV result.color, t.x; \n"
+ "END \n";
+ char program2[1000];
+ struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(drawpix->StencilFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &drawpix->StencilFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
+/**
+ * One-time init for drawing depth pixels.
+ */
+static void
+init_draw_depth_pixels(GLcontext *ctx)
+{
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "PARAM color = program.local[0]; \n"
+ "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
+ "MOV result.color, color; \n"
+ "END \n";
+ char program2[200];
+ struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(drawpix->DepthFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &drawpix->DepthFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.DrawPixels() in terms
+ * of texture mapping and polygon rendering.
+ */
+void
+_mesa_meta_draw_pixels(GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const struct gl_pixelstore_attrib unpackSave = ctx->Unpack;
+ const GLuint origStencilMask = ctx->Stencil.WriteMask[0];
+ struct vertex {
+ GLfloat x, y, z, s, t;
+ };
+ struct vertex verts[4];
+ GLenum texIntFormat;
+ GLboolean fallback, newTex;
+ GLbitfield metaExtraSave = 0x0;
+
+ /*
+ * Determine if we can do the glDrawPixels with texture mapping.
+ */
+ fallback = GL_FALSE;
+ if (ctx->_ImageTransferState ||
+ ctx->Fog.Enabled) {
+ fallback = GL_TRUE;
+ }
+
+ if (_mesa_is_color_format(format)) {
+ /* use more compact format when possible */
+ /* XXX disable special case for GL_LUMINANCE for now to work around
+ * apparent i965 driver bug (see bug #23670).
+ */
+ if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA)
+ texIntFormat = format;
+ else
+ texIntFormat = GL_RGBA;
+ }
+ else if (_mesa_is_stencil_format(format)) {
+ if (ctx->Extensions.ARB_fragment_program &&
+ ctx->Pixel.IndexShift == 0 &&
+ ctx->Pixel.IndexOffset == 0 &&
+ type == GL_UNSIGNED_BYTE) {
+ /* We'll store stencil as alpha. This only works for GLubyte
+ * image data because of how incoming values are mapped to alpha
+ * in [0,1].
+ */
+ texIntFormat = GL_ALPHA;
+ metaExtraSave = (META_COLOR_MASK |
+ META_DEPTH_TEST |
+ META_SHADER |
+ META_STENCIL_TEST);
+ }
+ else {
+ fallback = GL_TRUE;
+ }
+ }
+ else if (_mesa_is_depth_format(format)) {
+ if (ctx->Extensions.ARB_depth_texture &&
+ ctx->Extensions.ARB_fragment_program) {
+ texIntFormat = GL_DEPTH_COMPONENT;
+ metaExtraSave = (META_SHADER);
+ }
+ else {
+ fallback = GL_TRUE;
+ }
+ }
+ else {
+ fallback = GL_TRUE;
+ }
+
+ if (fallback) {
+ _swrast_DrawPixels(ctx, x, y, width, height,
+ format, type, unpack, pixels);
+ return;
+ }
+
+ /*
+ * Check image size against max texture size, draw as tiles if needed.
+ */
+ if (width > tex->MaxSize || height > tex->MaxSize) {
+ tiled_draw_pixels(ctx, tex->MaxSize, x, y, width, height,
+ format, type, unpack, pixels);
+ return;
+ }
+
+ /* Most GL state applies to glDrawPixels (like blending, stencil, etc),
+ * but a there's a few things we need to override:
+ */
+ _mesa_meta_begin(ctx, (META_RASTERIZATION |
+ META_SHADER |
+ META_TEXTURE |
+ META_TRANSFORM |
+ META_VERTEX |
+ META_VIEWPORT |
+ metaExtraSave));
+
+ if (drawpix->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &drawpix->ArrayObj);
+ _mesa_BindVertexArray(drawpix->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &drawpix->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawpix->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(drawpix->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawpix->VBO);
+ }
+
+ newTex = alloc_texture(tex, width, height, texIntFormat);
+
+ /* vertex positions, texcoords (after texture allocation!) */
+ {
+ const GLfloat x0 = (GLfloat) x;
+ const GLfloat y0 = (GLfloat) y;
+ const GLfloat x1 = x + width * ctx->Pixel.ZoomX;
+ const GLfloat y1 = y + height * ctx->Pixel.ZoomY;
+ const GLfloat z = ctx->Current.RasterPos[2];
+
+ verts[0].x = x0;
+ verts[0].y = y0;
+ verts[0].z = z;
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[1].x = x1;
+ verts[1].y = y0;
+ verts[1].z = z;
+ verts[1].s = tex->Sright;
+ verts[1].t = 0.0F;
+ verts[2].x = x1;
+ verts[2].y = y1;
+ verts[2].z = z;
+ verts[2].s = tex->Sright;
+ verts[2].t = tex->Ttop;
+ verts[3].x = x0;
+ verts[3].y = y1;
+ verts[3].z = z;
+ verts[3].s = 0.0F;
+ verts[3].t = tex->Ttop;
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ /* set given unpack params */
+ ctx->Unpack = *unpack;
+
+ _mesa_set_enable(ctx, tex->Target, GL_TRUE);
+
+ if (_mesa_is_stencil_format(format)) {
+ /* Drawing stencil */
+ GLint bit;
+
+ if (!drawpix->StencilFP)
+ init_draw_stencil_pixels(ctx);
+
+ setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ GL_ALPHA, type, pixels);
+
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
+
+ /* set all stencil bits to 0 */
+ _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ _mesa_StencilFunc(GL_ALWAYS, 0, 255);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ /* set stencil bits to 1 where needed */
+ _mesa_StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+
+ for (bit = 0; bit < ctx->Visual.stencilBits; bit++) {
+ const GLuint mask = 1 << bit;
+ if (mask & origStencilMask) {
+ _mesa_StencilFunc(GL_ALWAYS, mask, mask);
+ _mesa_StencilMask(mask);
+
+ _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
+ 255.0 / mask, 0.5, 0.0, 0.0);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+ }
+ }
+ else if (_mesa_is_depth_format(format)) {
+ /* Drawing depth */
+ if (!drawpix->DepthFP)
+ init_draw_depth_pixels(ctx);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+
+ /* polygon color = current raster color */
+ _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0,
+ ctx->Current.RasterColor);
+
+ setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ format, type, pixels);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+ else {
+ /* Drawing RGBA */
+ setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ format, type, pixels);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+
+ _mesa_set_enable(ctx, tex->Target, GL_FALSE);
+
+ /* restore unpack params */
+ ctx->Unpack = unpackSave;
+
+ _mesa_meta_end(ctx);
+}
+
+
+/**
+ * Do glBitmap with a alpha texture quad. Use the alpha test to
+ * cull the 'off' bits. If alpha test is already enabled, fall back
+ * to swrast (should be a rare case).
+ * A bitmap cache as in the gallium/mesa state tracker would
+ * improve performance a lot.
+ */
+void
+_mesa_meta_bitmap(GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap1)
+{
+ struct bitmap_state *bitmap = &ctx->Meta->Bitmap;
+ struct temp_texture *tex = get_bitmap_temp_texture(ctx);
+ const GLenum texIntFormat = GL_ALPHA;
+ const struct gl_pixelstore_attrib unpackSave = *unpack;
+ struct vertex {
+ GLfloat x, y, z, s, t, r, g, b, a;
+ };
+ struct vertex verts[4];
+ GLboolean newTex;
+ GLubyte *bitmap8;
+
+ /*
+ * Check if swrast fallback is needed.
+ */
+ if (ctx->_ImageTransferState ||
+ ctx->Color.AlphaEnabled ||
+ ctx->Fog.Enabled ||
+ ctx->Texture._EnabledUnits ||
+ width > tex->MaxSize ||
+ height > tex->MaxSize) {
+ _swrast_Bitmap(ctx, x, y, width, height, unpack, bitmap1);
+ return;
+ }
+
+ /* Most GL state applies to glBitmap (like blending, stencil, etc),
+ * but a there's a few things we need to override:
+ */
+ _mesa_meta_begin(ctx, (META_ALPHA_TEST |
+ META_PIXEL_STORE |
+ META_RASTERIZATION |
+ META_SHADER |
+ META_TEXTURE |
+ META_TRANSFORM |
+ META_VERTEX |
+ META_VIEWPORT));
+
+ if (bitmap->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArraysAPPLE(1, &bitmap->ArrayObj);
+ _mesa_BindVertexArrayAPPLE(bitmap->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &bitmap->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ _mesa_EnableClientState(GL_COLOR_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(bitmap->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
+ }
+
+ newTex = alloc_texture(tex, width, height, texIntFormat);
+
+ /* vertex positions, texcoords, colors (after texture allocation!) */
+ {
+ const GLfloat x0 = (GLfloat) x;
+ const GLfloat y0 = (GLfloat) y;
+ const GLfloat x1 = (GLfloat) (x + width);
+ const GLfloat y1 = (GLfloat) (y + height);
+ const GLfloat z = ctx->Current.RasterPos[2];
+ GLuint i;
+
+ verts[0].x = x0;
+ verts[0].y = y0;
+ verts[0].z = z;
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[1].x = x1;
+ verts[1].y = y0;
+ verts[1].z = z;
+ verts[1].s = tex->Sright;
+ verts[1].t = 0.0F;
+ verts[2].x = x1;
+ verts[2].y = y1;
+ verts[2].z = z;
+ verts[2].s = tex->Sright;
+ verts[2].t = tex->Ttop;
+ verts[3].x = x0;
+ verts[3].y = y1;
+ verts[3].z = z;
+ verts[3].s = 0.0F;
+ verts[3].t = tex->Ttop;
+
+ for (i = 0; i < 4; i++) {
+ verts[i].r = ctx->Current.RasterColor[0];
+ verts[i].g = ctx->Current.RasterColor[1];
+ verts[i].b = ctx->Current.RasterColor[2];
+ verts[i].a = ctx->Current.RasterColor[3];
+ }
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1);
+ if (!bitmap1)
+ return;
+
+ bitmap8 = (GLubyte *) _mesa_calloc(width * height);
+ if (bitmap8) {
+ _mesa_expand_bitmap(width, height, &unpackSave, bitmap1,
+ bitmap8, width, 0xff);
+
+ _mesa_set_enable(ctx, tex->Target, GL_TRUE);
+
+ _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE);
+ _mesa_AlphaFunc(GL_GREATER, 0.0);
+
+ setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ _mesa_set_enable(ctx, tex->Target, GL_FALSE);
+
+ _mesa_free(bitmap8);
+ }
+
+ _mesa_unmap_pbo_source(ctx, &unpackSave);
+
+ _mesa_meta_end(ctx);
+}
+
+
+void
+_mesa_meta_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
+ struct vertex {
+ GLfloat x, y, s, t, r;
+ };
+ struct vertex verts[4];
+ const GLuint baseLevel = texObj->BaseLevel;
+ const GLuint maxLevel = texObj->MaxLevel;
+ const GLenum minFilterSave = texObj->MinFilter;
+ const GLenum magFilterSave = texObj->MagFilter;
+ const GLuint fboSave = ctx->DrawBuffer->Name;
+ GLenum faceTarget;
+ GLuint level;
+ GLuint border = 0;
+
+ /* check for fallbacks */
+ if (!ctx->Extensions.EXT_framebuffer_object) {
+ _mesa_generate_mipmap(ctx, target, texObj);
+ return;
+ }
+
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
+ faceTarget = target;
+ target = GL_TEXTURE_CUBE_MAP;
+ }
+ else {
+ faceTarget = target;
+ }
+
+ _mesa_meta_begin(ctx, META_ALL);
+
+ if (mipmap->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArraysAPPLE(1, &mipmap->ArrayObj);
+ _mesa_BindVertexArrayAPPLE(mipmap->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &mipmap->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(mipmap->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
+ }
+
+ if (!mipmap->FBO) {
+ /* Bind the new renderbuffer to the color attachment point. */
+ _mesa_GenFramebuffersEXT(1, &mipmap->FBO);
+ }
+
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
+
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ _mesa_set_enable(ctx, target, GL_TRUE);
+
+ /* setup texcoords once (XXX what about border?) */
+ switch (faceTarget) {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ break;
+ case GL_TEXTURE_2D:
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[0].r = 0.0F;
+ verts[1].s = 1.0F;
+ verts[1].t = 0.0F;
+ verts[1].r = 0.0F;
+ verts[2].s = 1.0F;
+ verts[2].t = 1.0F;
+ verts[2].r = 0.0F;
+ verts[3].s = 0.0F;
+ verts[3].t = 1.0F;
+ verts[3].r = 0.0F;
+ break;
+ }
+
+
+ for (level = baseLevel + 1; level <= maxLevel; level++) {
+ const struct gl_texture_image *srcImage;
+ const GLuint srcLevel = level - 1;
+ GLsizei srcWidth, srcHeight;
+ GLsizei newWidth, newHeight;
+ GLenum status;
+
+ srcImage = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
+ assert(srcImage->Border == 0); /* XXX we can fix this */
+
+ srcWidth = srcImage->Width - 2 * border;
+ srcHeight = srcImage->Height - 2 * border;
+
+ newWidth = MAX2(1, srcWidth / 2) + 2 * border;
+ newHeight = MAX2(1, srcHeight / 2) + 2 * border;
+
+ if (newWidth == srcImage->Width && newHeight == srcImage->Height) {
+ break;
+ }
+
+ /* Create empty image */
+ _mesa_TexImage2D(GL_TEXTURE_2D, level, srcImage->InternalFormat,
+ newWidth, newHeight, border,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ /* vertex positions */
+ {
+ verts[0].x = 0.0F;
+ verts[0].y = 0.0F;
+ verts[1].x = (GLfloat) newWidth;
+ verts[1].y = 0.0F;
+ verts[2].x = (GLfloat) newWidth;
+ verts[2].y = (GLfloat) newHeight;
+ verts[3].x = 0.0F;
+ verts[3].y = (GLfloat) newHeight;
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ /* limit sampling to src level */
+ _mesa_TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, srcLevel);
+ _mesa_TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, srcLevel);
+
+ /* Set to draw into the current level */
+ _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target,
+ texObj->Name,
+ level);
+
+ /* Choose to render to the color attachment. */
+ _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+
+ status = _mesa_CheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ abort();
+ break;
+ }
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+
+ _mesa_meta_end(ctx);
+
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
+
+ /* restore (XXX add to meta_begin/end()? */
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
+}
diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
new file mode 100644
index 0000000000..171ad27f26
--- /dev/null
+++ b/src/mesa/drivers/common/meta.h
@@ -0,0 +1,91 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef META_H
+#define META_H
+
+
+/**
+ * Flags passed to _mesa_meta_begin().
+ * XXX these flags may evolve...
+ */
+/*@{*/
+#define META_ALPHA_TEST 0x1
+#define META_BLEND 0x2 /**< includes logicop */
+#define META_COLOR_MASK 0x4
+#define META_DEPTH_TEST 0x8
+#define META_FOG 0x10
+#define META_RASTERIZATION 0x20
+#define META_SCISSOR 0x40
+#define META_SHADER 0x80
+#define META_STENCIL_TEST 0x100
+#define META_TRANSFORM 0x200 /**< modelview, projection */
+#define META_TEXTURE 0x400
+#define META_VERTEX 0x800
+#define META_VIEWPORT 0x1000
+#define META_PIXEL_STORE 0x2000
+#define META_ALL ~0x0
+/*@}*/
+
+
+extern void
+_mesa_meta_init(GLcontext *ctx);
+
+extern void
+_mesa_meta_free(GLcontext *ctx);
+
+extern void
+_mesa_meta_blit_framebuffer(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+
+extern void
+_mesa_meta_clear(GLcontext *ctx, GLbitfield buffers);
+
+extern void
+_mesa_meta_copy_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty, GLenum type);
+
+extern void
+_mesa_meta_draw_pixels(GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels);
+
+extern void
+_mesa_meta_bitmap(GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap);
+
+extern void
+_mesa_meta_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj);
+
+
+#endif /* META_H */
diff --git a/src/mesa/drivers/dri/Makefile b/src/mesa/drivers/dri/Makefile
index 9e49fb16f5..32db097861 100644
--- a/src/mesa/drivers/dri/Makefile
+++ b/src/mesa/drivers/dri/Makefile
@@ -6,7 +6,7 @@ include $(TOP)/configs/current
-default: $(TOP)/$(LIB_DIR) subdirs
+default: $(TOP)/$(LIB_DIR) subdirs dri.pc
$(TOP)/$(LIB_DIR):
diff --git a/src/mesa/drivers/dri/Makefile.es b/src/mesa/drivers/dri/Makefile.es
new file mode 100644
index 0000000000..32cf9bd222
--- /dev/null
+++ b/src/mesa/drivers/dri/Makefile.es
@@ -0,0 +1,104 @@
+# -*-makefile-*-
+
+ES_VERSION ?= 1
+DRIVER_DEFINES += -UIN_DRI_DRIVER
+
+MESA_MODULES = $(TOP)/src/mesa/es/libes$(ES_VERSION).a
+
+COMMON_GALLIUM_SOURCES = \
+ ../common/utils.c \
+ ../common/vblank.c \
+ ../common/dri_util.c \
+ ../common/xmlconfig.c
+
+COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
+ ../../common/driverfuncs.c \
+ ../common/texmem.c \
+ ../common/drirenderbuffer.c \
+ ../common/dri_metaops.c
+
+ifeq ($(WINDOW_SYSTEM),dri)
+WINOBJ=
+WINLIB=
+INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES)
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+else
+# miniglx
+WINOBJ=
+WINLIB=-L$(MESA)/src/glx/mini
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
+INCLUDES = $(MINIGLX_INCLUDES) \
+ $(SHARED_INCLUDES) \
+ $(PCIACCESS_CFLAGS)
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(MINIGLX_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+endif
+
+
+### Include directories
+SHARED_INCLUDES = \
+ -I. \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -Iserver \
+ -I$(TOP)/src/mesa/es/glapi/headers-es$(ES_VERSION) \
+ -I$(TOP)/src/mesa/es \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/src/egl/drivers/dri \
+ $(LIBDRM_CFLAGS)
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+default: symlinks depend $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME)
+
+
+$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template
+ $(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+ $(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS)
+
+
+$(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
+ $(INSTALL) $(LIBNAME) $(TOP)/$(LIB_DIR)
+
+
+depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend
+ @ touch depend
+ @ $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
+ $(ASM_SOURCES) > /dev/null 2>/dev/null
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+ -rm -f *.o */*.o *~ *.so *~ server/*.o $(SYMLINKS)
+ -rm -f depend depend.bak
+
+
+install: $(LIBNAME)
+ $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+ $(MINSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+
+
+-include depend
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template
index 2dc3664cc6..18dbeba24a 100644
--- a/src/mesa/drivers/dri/Makefile.template
+++ b/src/mesa/drivers/dri/Makefile.template
@@ -2,13 +2,17 @@
MESA_MODULES = $(TOP)/src/mesa/libmesa.a
-COMMON_SOURCES = \
+COMMON_GALLIUM_SOURCES = \
../common/utils.c \
- ../common/texmem.c \
../common/vblank.c \
../common/dri_util.c \
- ../common/xmlconfig.c \
- ../common/drirenderbuffer.c
+ ../common/xmlconfig.c
+
+COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
+ ../../common/driverfuncs.c \
+ ../common/texmem.c \
+ ../common/drirenderbuffer.c \
+ ../common/dri_metaops.c
ifeq ($(WINDOW_SYSTEM),dri)
WINOBJ=
@@ -59,9 +63,9 @@ SHARED_INCLUDES = \
default: symlinks depend $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME)
-$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template
+$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template
$(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
- $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS)
+ $(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS)
$(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
@@ -69,9 +73,11 @@ $(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
- touch depend
- $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
- $(ASM_SOURCES)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend
+ @ touch depend
+ @ $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
+ $(ASM_SOURCES) > /dev/null 2>/dev/null
# Emacs tags
@@ -87,7 +93,7 @@ clean:
install: $(LIBNAME)
$(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
- $(INSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+ $(MINSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
-include depend
diff --git a/src/mesa/drivers/dri/common/.gitignore b/src/mesa/drivers/dri/common/.gitignore
new file mode 100644
index 0000000000..1edeb79fd1
--- /dev/null
+++ b/src/mesa/drivers/dri/common/.gitignore
@@ -0,0 +1 @@
+*.os
diff --git a/src/mesa/drivers/dri/common/dri_metaops.c b/src/mesa/drivers/dri/common/dri_metaops.c
new file mode 100644
index 0000000000..c7bea07dc9
--- /dev/null
+++ b/src/mesa/drivers/dri/common/dri_metaops.c
@@ -0,0 +1,298 @@
+/**************************************************************************
+ *
+ * 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/arrayobj.h"
+#include "main/attrib.h"
+#include "main/blend.h"
+#include "main/bufferobj.h"
+#include "main/buffers.h"
+#include "main/depth.h"
+#include "main/enable.h"
+#include "main/matrix.h"
+#include "main/macros.h"
+#include "main/polygon.h"
+#include "main/shaders.h"
+#include "main/stencil.h"
+#include "main/texstate.h"
+#include "main/varray.h"
+#include "main/viewport.h"
+#include "shader/arbprogram.h"
+#include "shader/program.h"
+#include "dri_metaops.h"
+
+void
+meta_set_passthrough_transform(struct dri_metaops *meta)
+{
+ GLcontext *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)
+{
+ GLcontext *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)
+{
+ GLcontext *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)
+{
+ GLcontext *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)
+{
+ GLcontext *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)
+{
+ GLcontext *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)
+{
+ GLcontext *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(GLcontext *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
new file mode 100644
index 0000000000..2487145326
--- /dev/null
+++ b/src/mesa/drivers/dri/common/dri_metaops.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * 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 {
+ GLcontext *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(GLcontext *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 ae79055405..e48e10d7c0 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -1,4 +1,3 @@
-/* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */
/**
* \file dri_util.c
* DRI utility functions.
@@ -37,6 +36,9 @@
typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
#endif
+static void dri_get_drawable(__DRIdrawable *pdp);
+static void dri_put_drawable(__DRIdrawable *pdp);
+
/**
* This is just a token extension used to signal that the driver
* supports setting a read drawable.
@@ -59,7 +61,7 @@ __driUtilMessage(const char *f, ...)
va_list args;
if (getenv("LIBGL_DEBUG")) {
- fprintf(stderr, "libGL error: \n");
+ fprintf(stderr, "libGL: ");
va_start(args, f);
vfprintf(stderr, f, args);
va_end(args);
@@ -119,6 +121,9 @@ static int driUnbindContext(__DRIcontext *pcp)
pdp = pcp->driDrawablePriv;
prp = pcp->driReadablePriv;
+ /* already unbound */
+ if (!pdp && !prp)
+ return GL_TRUE;
/* Let driver unbind drawable from context */
(*psp->DriverAPI.UnbindContext)(pcp);
@@ -127,7 +132,7 @@ static int driUnbindContext(__DRIcontext *pcp)
return GL_FALSE;
}
- pdp->refcount--;
+ dri_put_drawable(pdp);
if (prp != pdp) {
if (prp->refcount == 0) {
@@ -135,7 +140,7 @@ static int driUnbindContext(__DRIcontext *pcp)
return GL_FALSE;
}
- prp->refcount--;
+ dri_put_drawable(prp);
}
@@ -143,9 +148,10 @@ static int driUnbindContext(__DRIcontext *pcp)
* window we can determine the last context bound to the window and
* use that context's lock. (BrianP, 2-Dec-2000)
*/
+ pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
+
#if 0
/* Unbind the drawable */
- pcp->driDrawablePriv = NULL;
pdp->driContextPriv = &psp->dummyContextPriv;
#endif
@@ -163,21 +169,18 @@ static int driBindContext(__DRIcontext *pcp,
{
__DRIscreenPrivate *psp = pcp->driScreenPriv;
- /*
- ** Assume error checking is done properly in glXMakeCurrent before
- ** calling driBindContext.
- */
-
- if (pcp == NULL || pdp == None || prp == None)
- return GL_FALSE;
-
/* Bind the drawable to the context */
- pcp->driDrawablePriv = pdp;
- pcp->driReadablePriv = prp;
- pdp->driContextPriv = pcp;
- pdp->refcount++;
- if ( pdp != prp ) {
- prp->refcount++;
+
+ if (pcp) {
+ pcp->driDrawablePriv = pdp;
+ pcp->driReadablePriv = prp;
+ if (pdp) {
+ pdp->driContextPriv = pcp;
+ dri_get_drawable(pdp);
+ }
+ if ( prp && pdp != prp ) {
+ dri_get_drawable(prp);
+ }
}
/*
@@ -186,23 +189,21 @@ static int driBindContext(__DRIcontext *pcp,
*/
if (!psp->dri2.enabled) {
- if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
+ if (pdp && !pdp->pStamp) {
DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
__driUtilUpdateDrawableInfo(pdp);
DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
}
-
- if ((pdp != prp) && (!prp->pStamp || *prp->pStamp != prp->lastStamp)) {
+ if (prp && pdp != prp && !prp->pStamp) {
DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
__driUtilUpdateDrawableInfo(prp);
DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
- }
+ }
}
/* Call device-specific MakeCurrent */
- (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
- return GL_TRUE;
+ return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
}
/*@}*/
@@ -316,12 +317,12 @@ static void driSwapBuffers(__DRIdrawable *dPriv)
__DRIscreen *psp = dPriv->driScreenPriv;
drm_clip_rect_t *rects;
int i;
-
- if (!dPriv->numClipRects)
- return;
psp->DriverAPI.SwapBuffers(dPriv);
+ if (!dPriv->numClipRects)
+ return;
+
rects = _mesa_malloc(sizeof(*rects) * dPriv->numClipRects);
if (!rects)
@@ -435,7 +436,7 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
pdp->loaderPrivate = data;
pdp->hHWDrawable = hwDrawable;
- pdp->refcount = 0;
+ pdp->refcount = 1;
pdp->pStamp = NULL;
pdp->lastStamp = 0;
pdp->index = 0;
@@ -488,12 +489,19 @@ dri2CreateNewDrawable(__DRIscreen *screen,
return pdraw;
}
-
-static void
-driDestroyDrawable(__DRIdrawable *pdp)
+static void dri_get_drawable(__DRIdrawable *pdp)
+{
+ pdp->refcount++;
+}
+
+static void dri_put_drawable(__DRIdrawable *pdp)
{
__DRIscreenPrivate *psp;
+ pdp->refcount--;
+ if (pdp->refcount)
+ return;
+
if (pdp) {
psp = pdp->driScreenPriv;
(*psp->DriverAPI.DestroyBuffer)(pdp);
@@ -509,6 +517,12 @@ driDestroyDrawable(__DRIdrawable *pdp)
}
}
+static void
+driDestroyDrawable(__DRIdrawable *pdp)
+{
+ dri_put_drawable(pdp);
+}
+
/*@}*/
@@ -764,7 +778,7 @@ dri2CreateNewScreen(int scrn, int fd,
if (driDriverAPI.InitScreen2 == NULL)
return NULL;
- psp = _mesa_malloc(sizeof(*psp));
+ psp = _mesa_calloc(sizeof(*psp));
if (!psp)
return NULL;
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index c6781f1c7a..c95a5c8299 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -1,25 +1,3 @@
-/* $XFree86: xc/lib/GL/dri/dri_util.h,v 1.1 2002/02/22 21:32:52 dawes Exp $ */
-/**
- * \file dri_util.h
- * DRI utility functions definitions.
- *
- * This module acts as glue between GLX and the actual hardware driver. A DRI
- * driver doesn't really \e have to use any of this - it's optional. But, some
- * useful stuff is done here that otherwise would have to be duplicated in most
- * drivers.
- *
- * Basically, these utility functions take care of some of the dirty details of
- * screen initialization, context creation, context binding, DRM setup, etc.
- *
- * These functions are compiled into each DRI driver so libGL.so knows nothing
- * about them.
- *
- * \sa dri_util.c.
- *
- * \author Kevin E. Martin <kevin@precisioninsight.com>
- * \author Brian Paul <brian@precisioninsight.com>
- */
-
/*
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
@@ -45,6 +23,26 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+/**
+ * \file dri_util.h
+ * DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \sa dri_util.c.
+ *
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
#ifndef _DRI_UTIL_H_
#define _DRI_UTIL_H_
diff --git a/src/mesa/drivers/dri/common/drirenderbuffer.c b/src/mesa/drivers/dri/common/drirenderbuffer.c
index b99bf2033b..15af99136c 100644
--- a/src/mesa/drivers/dri/common/drirenderbuffer.c
+++ b/src/mesa/drivers/dri/common/drirenderbuffer.c
@@ -209,6 +209,8 @@ driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawablePrivate *dPriv)
struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h);
+ /* if the driver needs the hw lock for ResizeBuffers, the drawable
+ might have changed again by now */
assert(fb->Width == dPriv->w);
assert(fb->Height == dPriv->h);
}
diff --git a/src/mesa/drivers/dri/common/extension_helper.h b/src/mesa/drivers/dri/common/extension_helper.h
index b977ebf015..49e7278adb 100644
--- a/src/mesa/drivers/dri/common/extension_helper.h
+++ b/src/mesa/drivers/dri/common/extension_helper.h
@@ -32,8 +32,10 @@
# define NULL 0
#endif
+#if defined(IN_DRI_DRIVER)
+
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char UniformMatrix3fvARB_names[] =
+static const char UniformMatrix3fvARB_names[] =
"iiip\0" /* Parameter signature */
"glUniformMatrix3fv\0"
"glUniformMatrix3fvARB\0"
@@ -41,7 +43,7 @@ static const char UniformMatrix3fvARB_names[] =
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_multisample)
-static const char SampleCoverageARB_names[] =
+static const char SampleCoverageARB_names[] =
"fi\0" /* Parameter signature */
"glSampleCoverage\0"
"glSampleCoverageARB\0"
@@ -49,7 +51,7 @@ static const char SampleCoverageARB_names[] =
#endif
#if defined(need_GL_EXT_convolution)
-static const char ConvolutionFilter1D_names[] =
+static const char ConvolutionFilter1D_names[] =
"iiiiip\0" /* Parameter signature */
"glConvolutionFilter1D\0"
"glConvolutionFilter1DEXT\0"
@@ -57,7 +59,7 @@ static const char ConvolutionFilter1D_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
-static const char BeginQueryARB_names[] =
+static const char BeginQueryARB_names[] =
"ii\0" /* Parameter signature */
"glBeginQuery\0"
"glBeginQueryARB\0"
@@ -65,7 +67,7 @@ static const char BeginQueryARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_NV_point_sprite)
-static const char PointParameteriNV_names[] =
+static const char PointParameteriNV_names[] =
"ii\0" /* Parameter signature */
"glPointParameteri\0"
"glPointParameteriNV\0"
@@ -73,14 +75,14 @@ static const char PointParameteriNV_names[] =
#endif
#if defined(need_GL_VERSION_2_0)
-static const char GetProgramiv_names[] =
+static const char GetProgramiv_names[] =
"iip\0" /* Parameter signature */
"glGetProgramiv\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord3sARB_names[] =
+static const char MultiTexCoord3sARB_names[] =
"iiii\0" /* Parameter signature */
"glMultiTexCoord3s\0"
"glMultiTexCoord3sARB\0"
@@ -88,7 +90,7 @@ static const char MultiTexCoord3sARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3iEXT_names[] =
+static const char SecondaryColor3iEXT_names[] =
"iii\0" /* Parameter signature */
"glSecondaryColor3i\0"
"glSecondaryColor3iEXT\0"
@@ -96,7 +98,7 @@ static const char SecondaryColor3iEXT_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos3fMESA_names[] =
+static const char WindowPos3fMESA_names[] =
"fff\0" /* Parameter signature */
"glWindowPos3f\0"
"glWindowPos3fARB\0"
@@ -105,43 +107,44 @@ static const char WindowPos3fMESA_names[] =
#endif
#if defined(need_GL_SGIS_pixel_texture)
-static const char PixelTexGenParameterfvSGIS_names[] =
+static const char PixelTexGenParameterfvSGIS_names[] =
"ip\0" /* Parameter signature */
"glPixelTexGenParameterfvSGIS\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char ActiveTextureARB_names[] =
+static const char ActiveTextureARB_names[] =
"i\0" /* Parameter signature */
"glActiveTexture\0"
"glActiveTextureARB\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_blit)
-static const char BlitFramebufferEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_blit)
+static const char BlitFramebufferEXT_names[] =
"iiiiiiiiii\0" /* Parameter signature */
+ "glBlitFramebuffer\0"
"glBlitFramebufferEXT\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib4ubvNV_names[] =
+static const char VertexAttrib4ubvNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4ubvNV\0"
"";
#endif
#if defined(need_GL_NV_fragment_program)
-static const char GetProgramNamedParameterdvNV_names[] =
+static const char GetProgramNamedParameterdvNV_names[] =
"iipp\0" /* Parameter signature */
"glGetProgramNamedParameterdvNV\0"
"";
#endif
#if defined(need_GL_EXT_histogram)
-static const char Histogram_names[] =
+static const char Histogram_names[] =
"iiii\0" /* Parameter signature */
"glHistogram\0"
"glHistogramEXT\0"
@@ -149,14 +152,14 @@ static const char Histogram_names[] =
#endif
#if defined(need_GL_SGIS_texture4D)
-static const char TexImage4DSGIS_names[] =
+static const char TexImage4DSGIS_names[] =
"iiiiiiiiiip\0" /* Parameter signature */
"glTexImage4DSGIS\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos2dvMESA_names[] =
+static const char WindowPos2dvMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos2dv\0"
"glWindowPos2dvARB\0"
@@ -165,14 +168,14 @@ static const char WindowPos2dvMESA_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiColor3fVertex3fvSUN_names[] =
+static const char ReplacementCodeuiColor3fVertex3fvSUN_names[] =
"ppp\0" /* Parameter signature */
"glReplacementCodeuiColor3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_EXT_blend_equation_separate) || defined(need_GL_ATI_blend_equation_separate)
-static const char BlendEquationSeparateEXT_names[] =
+static const char BlendEquationSeparateEXT_names[] =
"ii\0" /* Parameter signature */
"glBlendEquationSeparate\0"
"glBlendEquationSeparateEXT\0"
@@ -181,14 +184,14 @@ static const char BlendEquationSeparateEXT_names[] =
#endif
#if defined(need_GL_SGIX_list_priority)
-static const char ListParameterfSGIX_names[] =
+static const char ListParameterfSGIX_names[] =
"iif\0" /* Parameter signature */
"glListParameterfSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3bEXT_names[] =
+static const char SecondaryColor3bEXT_names[] =
"iii\0" /* Parameter signature */
"glSecondaryColor3b\0"
"glSecondaryColor3bEXT\0"
@@ -196,21 +199,21 @@ static const char SecondaryColor3bEXT_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord4fColor4fNormal3fVertex4fvSUN_names[] =
+static const char TexCoord4fColor4fNormal3fVertex4fvSUN_names[] =
"pppp\0" /* Parameter signature */
"glTexCoord4fColor4fNormal3fVertex4fvSUN\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib4svNV_names[] =
+static const char VertexAttrib4svNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4svNV\0"
"";
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char GetBufferSubDataARB_names[] =
+static const char GetBufferSubDataARB_names[] =
"iiip\0" /* Parameter signature */
"glGetBufferSubData\0"
"glGetBufferSubDataARB\0"
@@ -218,7 +221,7 @@ static const char GetBufferSubDataARB_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char BufferSubDataARB_names[] =
+static const char BufferSubDataARB_names[] =
"iiip\0" /* Parameter signature */
"glBufferSubData\0"
"glBufferSubDataARB\0"
@@ -226,21 +229,21 @@ static const char BufferSubDataARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fColor4ubVertex3fvSUN_names[] =
+static const char TexCoord2fColor4ubVertex3fvSUN_names[] =
"ppp\0" /* Parameter signature */
"glTexCoord2fColor4ubVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0)
-static const char AttachShader_names[] =
+static const char AttachShader_names[] =
"ii\0" /* Parameter signature */
"glAttachShader\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib2fARB_names[] =
+static const char VertexAttrib2fARB_names[] =
"iff\0" /* Parameter signature */
"glVertexAttrib2f\0"
"glVertexAttrib2fARB\0"
@@ -248,14 +251,14 @@ static const char VertexAttrib2fARB_names[] =
#endif
#if defined(need_GL_MESA_shader_debug)
-static const char GetDebugLogLengthMESA_names[] =
+static const char GetDebugLogLengthMESA_names[] =
"iii\0" /* Parameter signature */
"glGetDebugLogLengthMESA\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib3fARB_names[] =
+static const char VertexAttrib3fARB_names[] =
"ifff\0" /* Parameter signature */
"glVertexAttrib3f\0"
"glVertexAttrib3fARB\0"
@@ -263,7 +266,7 @@ static const char VertexAttrib3fARB_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
-static const char GetQueryivARB_names[] =
+static const char GetQueryivARB_names[] =
"iip\0" /* Parameter signature */
"glGetQueryiv\0"
"glGetQueryivARB\0"
@@ -271,7 +274,7 @@ static const char GetQueryivARB_names[] =
#endif
#if defined(need_GL_EXT_texture3D)
-static const char TexImage3D_names[] =
+static const char TexImage3D_names[] =
"iiiiiiiiip\0" /* Parameter signature */
"glTexImage3D\0"
"glTexImage3DEXT\0"
@@ -279,14 +282,14 @@ static const char TexImage3D_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiVertex3fvSUN_names[] =
+static const char ReplacementCodeuiVertex3fvSUN_names[] =
"pp\0" /* Parameter signature */
"glReplacementCodeuiVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
-static const char GetQueryObjectivARB_names[] =
+static const char GetQueryObjectivARB_names[] =
"iip\0" /* Parameter signature */
"glGetQueryObjectiv\0"
"glGetQueryObjectivARB\0"
@@ -294,14 +297,14 @@ static const char GetQueryObjectivARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiTexCoord2fVertex3fvSUN_names[] =
+static const char ReplacementCodeuiTexCoord2fVertex3fvSUN_names[] =
"ppp\0" /* Parameter signature */
"glReplacementCodeuiTexCoord2fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
-static const char CompressedTexSubImage2DARB_names[] =
+static const char CompressedTexSubImage2DARB_names[] =
"iiiiiiiip\0" /* Parameter signature */
"glCompressedTexSubImage2D\0"
"glCompressedTexSubImage2DARB\0"
@@ -309,14 +312,21 @@ static const char CompressedTexSubImage2DARB_names[] =
#endif
#if defined(need_GL_NV_register_combiners)
-static const char CombinerOutputNV_names[] =
+static const char CombinerOutputNV_names[] =
"iiiiiiiiii\0" /* Parameter signature */
"glCombinerOutputNV\0"
"";
#endif
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs3fvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs3fvNV\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform2fARB_names[] =
+static const char Uniform2fARB_names[] =
"iff\0" /* Parameter signature */
"glUniform2f\0"
"glUniform2fARB\0"
@@ -324,7 +334,7 @@ static const char Uniform2fARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib1svARB_names[] =
+static const char VertexAttrib1svARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib1sv\0"
"glVertexAttrib1svARB\0"
@@ -332,14 +342,14 @@ static const char VertexAttrib1svARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs1dvNV_names[] =
+static const char VertexAttribs1dvNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs1dvNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform2ivARB_names[] =
+static const char Uniform2ivARB_names[] =
"iip\0" /* Parameter signature */
"glUniform2iv\0"
"glUniform2ivARB\0"
@@ -347,28 +357,28 @@ static const char Uniform2ivARB_names[] =
#endif
#if defined(need_GL_HP_image_transform)
-static const char GetImageTransformParameterfvHP_names[] =
+static const char GetImageTransformParameterfvHP_names[] =
"iip\0" /* Parameter signature */
"glGetImageTransformParameterfvHP\0"
"";
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char WeightubvARB_names[] =
+static const char WeightubvARB_names[] =
"ip\0" /* Parameter signature */
"glWeightubvARB\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib1fvNV_names[] =
+static const char VertexAttrib1fvNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib1fvNV\0"
"";
#endif
#if defined(need_GL_EXT_convolution)
-static const char CopyConvolutionFilter1D_names[] =
+static const char CopyConvolutionFilter1D_names[] =
"iiiii\0" /* Parameter signature */
"glCopyConvolutionFilter1D\0"
"glCopyConvolutionFilter1DEXT\0"
@@ -376,21 +386,28 @@ static const char CopyConvolutionFilter1D_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiNormal3fVertex3fSUN_names[] =
+static const char ReplacementCodeuiNormal3fVertex3fSUN_names[] =
"iffffff\0" /* Parameter signature */
"glReplacementCodeuiNormal3fVertex3fSUN\0"
"";
#endif
+#if defined(need_GL_ARB_sync)
+static const char DeleteSync_names[] =
+ "i\0" /* Parameter signature */
+ "glDeleteSync\0"
+ "";
+#endif
+
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentMaterialfvSGIX_names[] =
+static const char FragmentMaterialfvSGIX_names[] =
"iip\0" /* Parameter signature */
"glFragmentMaterialfvSGIX\0"
"";
#endif
#if defined(need_GL_EXT_blend_color)
-static const char BlendColor_names[] =
+static const char BlendColor_names[] =
"ffff\0" /* Parameter signature */
"glBlendColor\0"
"glBlendColorEXT\0"
@@ -398,57 +415,59 @@ static const char BlendColor_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char UniformMatrix4fvARB_names[] =
+static const char UniformMatrix4fvARB_names[] =
"iiip\0" /* Parameter signature */
"glUniformMatrix4fv\0"
"glUniformMatrix4fvARB\0"
"";
#endif
-#if defined(need_GL_APPLE_vertex_array_object)
-static const char DeleteVertexArraysAPPLE_names[] =
+#if defined(need_GL_ARB_vertex_array_object) || defined(need_GL_APPLE_vertex_array_object)
+static const char DeleteVertexArraysAPPLE_names[] =
"ip\0" /* Parameter signature */
+ "glDeleteVertexArrays\0"
"glDeleteVertexArraysAPPLE\0"
"";
#endif
#if defined(need_GL_SGIX_instruments)
-static const char ReadInstrumentsSGIX_names[] =
+static const char ReadInstrumentsSGIX_names[] =
"i\0" /* Parameter signature */
"glReadInstrumentsSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_1)
-static const char UniformMatrix2x4fv_names[] =
+static const char UniformMatrix2x4fv_names[] =
"iiip\0" /* Parameter signature */
"glUniformMatrix2x4fv\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char Color4ubVertex3fvSUN_names[] =
+static const char Color4ubVertex3fvSUN_names[] =
"pp\0" /* Parameter signature */
"glColor4ubVertex3fvSUN\0"
"";
#endif
-#if defined(need_GL_EXT_texture_array)
-static const char FramebufferTextureLayerEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_texture_array)
+static const char FramebufferTextureLayerEXT_names[] =
"iiiii\0" /* Parameter signature */
+ "glFramebufferTextureLayer\0"
"glFramebufferTextureLayerEXT\0"
"";
#endif
#if defined(need_GL_SGIX_list_priority)
-static const char GetListParameterivSGIX_names[] =
+static const char GetListParameterfvSGIX_names[] =
"iip\0" /* Parameter signature */
- "glGetListParameterivSGIX\0"
+ "glGetListParameterfvSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4NusvARB_names[] =
+static const char VertexAttrib4NusvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4Nusv\0"
"glVertexAttrib4NusvARB\0"
@@ -456,35 +475,35 @@ static const char VertexAttrib4NusvARB_names[] =
#endif
#if defined(need_GL_MESA_window_pos)
-static const char WindowPos4svMESA_names[] =
+static const char WindowPos4svMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos4svMESA\0"
"";
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char CreateProgramObjectARB_names[] =
+static const char CreateProgramObjectARB_names[] =
"\0" /* Parameter signature */
"glCreateProgramObjectARB\0"
"";
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentLightModelivSGIX_names[] =
+static const char FragmentLightModelivSGIX_names[] =
"ip\0" /* Parameter signature */
"glFragmentLightModelivSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_1)
-static const char UniformMatrix4x3fv_names[] =
+static const char UniformMatrix4x3fv_names[] =
"iiip\0" /* Parameter signature */
"glUniformMatrix4x3fv\0"
"";
#endif
#if defined(need_GL_EXT_texture_object)
-static const char PrioritizeTextures_names[] =
+static const char PrioritizeTextures_names[] =
"ipp\0" /* Parameter signature */
"glPrioritizeTextures\0"
"glPrioritizeTexturesEXT\0"
@@ -492,28 +511,28 @@ static const char PrioritizeTextures_names[] =
#endif
#if defined(need_GL_SGIX_async)
-static const char AsyncMarkerSGIX_names[] =
+static const char AsyncMarkerSGIX_names[] =
"i\0" /* Parameter signature */
"glAsyncMarkerSGIX\0"
"";
#endif
#if defined(need_GL_SUN_global_alpha)
-static const char GlobalAlphaFactorubSUN_names[] =
+static const char GlobalAlphaFactorubSUN_names[] =
"i\0" /* Parameter signature */
"glGlobalAlphaFactorubSUN\0"
"";
#endif
#if defined(need_GL_MESA_shader_debug)
-static const char ClearDebugLogMESA_names[] =
+static const char ClearDebugLogMESA_names[] =
"iii\0" /* Parameter signature */
"glClearDebugLogMESA\0"
"";
#endif
#if defined(need_GL_EXT_histogram)
-static const char ResetHistogram_names[] =
+static const char ResetHistogram_names[] =
"i\0" /* Parameter signature */
"glResetHistogram\0"
"glResetHistogramEXT\0"
@@ -521,14 +540,14 @@ static const char ResetHistogram_names[] =
#endif
#if defined(need_GL_NV_fragment_program)
-static const char GetProgramNamedParameterfvNV_names[] =
+static const char GetProgramNamedParameterfvNV_names[] =
"iipp\0" /* Parameter signature */
"glGetProgramNamedParameterfvNV\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_point_parameters) || defined(need_GL_EXT_point_parameters) || defined(need_GL_SGIS_point_parameters)
-static const char PointParameterfEXT_names[] =
+static const char PointParameterfEXT_names[] =
"if\0" /* Parameter signature */
"glPointParameterf\0"
"glPointParameterfARB\0"
@@ -538,35 +557,42 @@ static const char PointParameterfEXT_names[] =
#endif
#if defined(need_GL_SGIX_polynomial_ffd)
-static const char LoadIdentityDeformationMapSGIX_names[] =
+static const char LoadIdentityDeformationMapSGIX_names[] =
"i\0" /* Parameter signature */
"glLoadIdentityDeformationMapSGIX\0"
"";
#endif
#if defined(need_GL_NV_fence)
-static const char GenFencesNV_names[] =
+static const char GenFencesNV_names[] =
"ip\0" /* Parameter signature */
"glGenFencesNV\0"
"";
#endif
#if defined(need_GL_HP_image_transform)
-static const char ImageTransformParameterfHP_names[] =
+static const char ImageTransformParameterfHP_names[] =
"iif\0" /* Parameter signature */
"glImageTransformParameterfHP\0"
"";
#endif
#if defined(need_GL_ARB_matrix_palette)
-static const char MatrixIndexusvARB_names[] =
+static const char MatrixIndexusvARB_names[] =
"ip\0" /* Parameter signature */
"glMatrixIndexusvARB\0"
"";
#endif
+#if defined(need_GL_ARB_draw_elements_base_vertex)
+static const char DrawElementsBaseVertex_names[] =
+ "iiipi\0" /* Parameter signature */
+ "glDrawElementsBaseVertex\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char DisableVertexAttribArrayARB_names[] =
+static const char DisableVertexAttribArrayARB_names[] =
"i\0" /* Parameter signature */
"glDisableVertexAttribArray\0"
"glDisableVertexAttribArrayARB\0"
@@ -574,21 +600,21 @@ static const char DisableVertexAttribArrayARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0)
-static const char StencilMaskSeparate_names[] =
+static const char StencilMaskSeparate_names[] =
"ii\0" /* Parameter signature */
"glStencilMaskSeparate\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char ProgramLocalParameter4dARB_names[] =
+static const char ProgramLocalParameter4dARB_names[] =
"iidddd\0" /* Parameter signature */
"glProgramLocalParameter4dARB\0"
"";
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
-static const char CompressedTexImage3DARB_names[] =
+static const char CompressedTexImage3DARB_names[] =
"iiiiiiiip\0" /* Parameter signature */
"glCompressedTexImage3D\0"
"glCompressedTexImage3DARB\0"
@@ -596,7 +622,7 @@ static const char CompressedTexImage3DARB_names[] =
#endif
#if defined(need_GL_EXT_convolution)
-static const char GetConvolutionParameteriv_names[] =
+static const char GetConvolutionParameteriv_names[] =
"iip\0" /* Parameter signature */
"glGetConvolutionParameteriv\0"
"glGetConvolutionParameterivEXT\0"
@@ -604,7 +630,7 @@ static const char GetConvolutionParameteriv_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib1fARB_names[] =
+static const char VertexAttrib1fARB_names[] =
"if\0" /* Parameter signature */
"glVertexAttrib1f\0"
"glVertexAttrib1fARB\0"
@@ -612,14 +638,14 @@ static const char VertexAttrib1fARB_names[] =
#endif
#if defined(need_GL_NV_fence)
-static const char TestFenceNV_names[] =
+static const char TestFenceNV_names[] =
"i\0" /* Parameter signature */
"glTestFenceNV\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord1fvARB_names[] =
+static const char MultiTexCoord1fvARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord1fv\0"
"glMultiTexCoord1fvARB\0"
@@ -627,56 +653,56 @@ static const char MultiTexCoord1fvARB_names[] =
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char ColorFragmentOp2ATI_names[] =
+static const char ColorFragmentOp2ATI_names[] =
"iiiiiiiiii\0" /* Parameter signature */
"glColorFragmentOp2ATI\0"
"";
#endif
#if defined(need_GL_IBM_vertex_array_lists)
-static const char SecondaryColorPointerListIBM_names[] =
+static const char SecondaryColorPointerListIBM_names[] =
"iiipi\0" /* Parameter signature */
"glSecondaryColorPointerListIBM\0"
"";
#endif
#if defined(need_GL_SGIS_pixel_texture)
-static const char GetPixelTexGenParameterivSGIS_names[] =
+static const char GetPixelTexGenParameterivSGIS_names[] =
"ip\0" /* Parameter signature */
"glGetPixelTexGenParameterivSGIS\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib4fNV_names[] =
+static const char VertexAttrib4fNV_names[] =
"iffff\0" /* Parameter signature */
"glVertexAttrib4fNV\0"
"";
#endif
#if defined(need_GL_SUN_triangle_list)
-static const char ReplacementCodeubSUN_names[] =
+static const char ReplacementCodeubSUN_names[] =
"i\0" /* Parameter signature */
"glReplacementCodeubSUN\0"
"";
#endif
#if defined(need_GL_SGIX_async)
-static const char FinishAsyncSGIX_names[] =
+static const char FinishAsyncSGIX_names[] =
"p\0" /* Parameter signature */
"glFinishAsyncSGIX\0"
"";
#endif
#if defined(need_GL_MESA_shader_debug)
-static const char GetDebugLogMESA_names[] =
+static const char GetDebugLogMESA_names[] =
"iiiipp\0" /* Parameter signature */
"glGetDebugLogMESA\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
-static const char FogCoorddEXT_names[] =
+static const char FogCoorddEXT_names[] =
"d\0" /* Parameter signature */
"glFogCoordd\0"
"glFogCoorddEXT\0"
@@ -684,14 +710,14 @@ static const char FogCoorddEXT_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char Color4ubVertex3fSUN_names[] =
+static const char Color4ubVertex3fSUN_names[] =
"iiiifff\0" /* Parameter signature */
"glColor4ubVertex3fSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
-static const char FogCoordfEXT_names[] =
+static const char FogCoordfEXT_names[] =
"f\0" /* Parameter signature */
"glFogCoordf\0"
"glFogCoordfEXT\0"
@@ -699,35 +725,35 @@ static const char FogCoordfEXT_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fVertex3fSUN_names[] =
+static const char TexCoord2fVertex3fSUN_names[] =
"fffff\0" /* Parameter signature */
"glTexCoord2fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_SUN_global_alpha)
-static const char GlobalAlphaFactoriSUN_names[] =
+static const char GlobalAlphaFactoriSUN_names[] =
"i\0" /* Parameter signature */
"glGlobalAlphaFactoriSUN\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib2dNV_names[] =
+static const char VertexAttrib2dNV_names[] =
"idd\0" /* Parameter signature */
"glVertexAttrib2dNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0)
-static const char GetProgramInfoLog_names[] =
+static const char GetProgramInfoLog_names[] =
"iipp\0" /* Parameter signature */
"glGetProgramInfoLog\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4NbvARB_names[] =
+static const char VertexAttrib4NbvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4Nbv\0"
"glVertexAttrib4NbvARB\0"
@@ -735,7 +761,7 @@ static const char VertexAttrib4NbvARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_shader)
-static const char GetActiveAttribARB_names[] =
+static const char GetActiveAttribARB_names[] =
"iiipppp\0" /* Parameter signature */
"glGetActiveAttrib\0"
"glGetActiveAttribARB\0"
@@ -743,77 +769,91 @@ static const char GetActiveAttribARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib4ubNV_names[] =
+static const char VertexAttrib4ubNV_names[] =
"iiiii\0" /* Parameter signature */
"glVertexAttrib4ubNV\0"
"";
#endif
+#if defined(need_GL_APPLE_texture_range)
+static const char TextureRangeAPPLE_names[] =
+ "iip\0" /* Parameter signature */
+ "glTextureRangeAPPLE\0"
+ "";
+#endif
+
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fColor4fNormal3fVertex3fSUN_names[] =
+static const char TexCoord2fColor4fNormal3fVertex3fSUN_names[] =
"ffffffffffff\0" /* Parameter signature */
"glTexCoord2fColor4fNormal3fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_NV_register_combiners)
-static const char CombinerParameterfvNV_names[] =
+static const char CombinerParameterfvNV_names[] =
"ip\0" /* Parameter signature */
"glCombinerParameterfvNV\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs3dvNV_names[] =
+static const char VertexAttribs3dvNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs3dvNV\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs4fvNV_names[] =
+static const char VertexAttribs4fvNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs4fvNV\0"
"";
#endif
+#if defined(need_GL_NV_vertex_array_range)
+static const char VertexArrayRangeNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexArrayRangeNV\0"
+ "";
+#endif
+
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentLightiSGIX_names[] =
+static const char FragmentLightiSGIX_names[] =
"iii\0" /* Parameter signature */
"glFragmentLightiSGIX\0"
"";
#endif
#if defined(need_GL_EXT_polygon_offset)
-static const char PolygonOffsetEXT_names[] =
+static const char PolygonOffsetEXT_names[] =
"ff\0" /* Parameter signature */
"glPolygonOffsetEXT\0"
"";
#endif
#if defined(need_GL_SGIX_async)
-static const char PollAsyncSGIX_names[] =
+static const char PollAsyncSGIX_names[] =
"p\0" /* Parameter signature */
"glPollAsyncSGIX\0"
"";
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char DeleteFragmentShaderATI_names[] =
+static const char DeleteFragmentShaderATI_names[] =
"i\0" /* Parameter signature */
"glDeleteFragmentShaderATI\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fNormal3fVertex3fvSUN_names[] =
+static const char TexCoord2fNormal3fVertex3fvSUN_names[] =
"ppp\0" /* Parameter signature */
"glTexCoord2fNormal3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_transpose_matrix)
-static const char MultTransposeMatrixdARB_names[] =
+static const char MultTransposeMatrixdARB_names[] =
"p\0" /* Parameter signature */
"glMultTransposeMatrixd\0"
"glMultTransposeMatrixdARB\0"
@@ -821,7 +861,7 @@ static const char MultTransposeMatrixdARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos2svMESA_names[] =
+static const char WindowPos2svMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos2sv\0"
"glWindowPos2svARB\0"
@@ -830,7 +870,7 @@ static const char WindowPos2svMESA_names[] =
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
-static const char CompressedTexImage1DARB_names[] =
+static const char CompressedTexImage1DARB_names[] =
"iiiiiip\0" /* Parameter signature */
"glCompressedTexImage1D\0"
"glCompressedTexImage1DARB\0"
@@ -838,35 +878,35 @@ static const char CompressedTexImage1DARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib2sNV_names[] =
+static const char VertexAttrib2sNV_names[] =
"iii\0" /* Parameter signature */
"glVertexAttrib2sNV\0"
"";
#endif
#if defined(need_GL_IBM_vertex_array_lists)
-static const char NormalPointerListIBM_names[] =
+static const char NormalPointerListIBM_names[] =
"iipi\0" /* Parameter signature */
"glNormalPointerListIBM\0"
"";
#endif
#if defined(need_GL_EXT_vertex_array)
-static const char IndexPointerEXT_names[] =
+static const char IndexPointerEXT_names[] =
"iiip\0" /* Parameter signature */
"glIndexPointerEXT\0"
"";
#endif
#if defined(need_GL_EXT_vertex_array)
-static const char NormalPointerEXT_names[] =
+static const char NormalPointerEXT_names[] =
"iiip\0" /* Parameter signature */
"glNormalPointerEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord3dARB_names[] =
+static const char MultiTexCoord3dARB_names[] =
"iddd\0" /* Parameter signature */
"glMultiTexCoord3d\0"
"glMultiTexCoord3dARB\0"
@@ -874,7 +914,7 @@ static const char MultiTexCoord3dARB_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord2iARB_names[] =
+static const char MultiTexCoord2iARB_names[] =
"iii\0" /* Parameter signature */
"glMultiTexCoord2i\0"
"glMultiTexCoord2iARB\0"
@@ -882,14 +922,14 @@ static const char MultiTexCoord2iARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN_names[] =
+static const char ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN_names[] =
"iffffffff\0" /* Parameter signature */
"glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord2svARB_names[] =
+static const char MultiTexCoord2svARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord2sv\0"
"glMultiTexCoord2svARB\0"
@@ -897,14 +937,14 @@ static const char MultiTexCoord2svARB_names[] =
#endif
#if defined(need_GL_SUN_triangle_list)
-static const char ReplacementCodeubvSUN_names[] =
+static const char ReplacementCodeubvSUN_names[] =
"p\0" /* Parameter signature */
"glReplacementCodeubvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform3iARB_names[] =
+static const char Uniform3iARB_names[] =
"iiii\0" /* Parameter signature */
"glUniform3i\0"
"glUniform3iARB\0"
@@ -912,77 +952,85 @@ static const char Uniform3iARB_names[] =
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char GetFragmentMaterialfvSGIX_names[] =
+static const char GetFragmentMaterialfvSGIX_names[] =
"iip\0" /* Parameter signature */
"glGetFragmentMaterialfvSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_0)
-static const char GetShaderInfoLog_names[] =
+static const char GetShaderInfoLog_names[] =
"iipp\0" /* Parameter signature */
"glGetShaderInfoLog\0"
"";
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char WeightivARB_names[] =
+static const char WeightivARB_names[] =
"ip\0" /* Parameter signature */
"glWeightivARB\0"
"";
#endif
+#if defined(need_GL_SGIX_instruments)
+static const char PollInstrumentsSGIX_names[] =
+ "p\0" /* Parameter signature */
+ "glPollInstrumentsSGIX\0"
+ "";
+#endif
+
#if defined(need_GL_SUN_global_alpha)
-static const char GlobalAlphaFactordSUN_names[] =
+static const char GlobalAlphaFactordSUN_names[] =
"d\0" /* Parameter signature */
"glGlobalAlphaFactordSUN\0"
"";
#endif
-#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs3fvNV_names[] =
+#if defined(need_GL_NV_register_combiners)
+static const char GetFinalCombinerInputParameterfvNV_names[] =
"iip\0" /* Parameter signature */
- "glVertexAttribs3fvNV\0"
+ "glGetFinalCombinerInputParameterfvNV\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char GenerateMipmapEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GenerateMipmapEXT_names[] =
"i\0" /* Parameter signature */
+ "glGenerateMipmap\0"
"glGenerateMipmapEXT\0"
"";
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char SetFragmentShaderConstantATI_names[] =
+static const char SetFragmentShaderConstantATI_names[] =
"ip\0" /* Parameter signature */
"glSetFragmentShaderConstantATI\0"
"";
#endif
#if defined(need_GL_NV_evaluators)
-static const char GetMapAttribParameterivNV_names[] =
+static const char GetMapAttribParameterivNV_names[] =
"iiip\0" /* Parameter signature */
"glGetMapAttribParameterivNV\0"
"";
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char CreateShaderObjectARB_names[] =
+static const char CreateShaderObjectARB_names[] =
"i\0" /* Parameter signature */
"glCreateShaderObjectARB\0"
"";
#endif
#if defined(need_GL_SGIS_sharpen_texture)
-static const char GetSharpenTexFuncSGIS_names[] =
+static const char GetSharpenTexFuncSGIS_names[] =
"ip\0" /* Parameter signature */
"glGetSharpenTexFuncSGIS\0"
"";
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char BufferDataARB_names[] =
+static const char BufferDataARB_names[] =
"iipi\0" /* Parameter signature */
"glBufferData\0"
"glBufferDataARB\0"
@@ -990,42 +1038,42 @@ static const char BufferDataARB_names[] =
#endif
#if defined(need_GL_NV_vertex_array_range)
-static const char FlushVertexArrayRangeNV_names[] =
+static const char FlushVertexArrayRangeNV_names[] =
"\0" /* Parameter signature */
"glFlushVertexArrayRangeNV\0"
"";
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char SampleMapATI_names[] =
+static const char SampleMapATI_names[] =
"iii\0" /* Parameter signature */
"glSampleMapATI\0"
"";
#endif
#if defined(need_GL_EXT_vertex_array)
-static const char VertexPointerEXT_names[] =
+static const char VertexPointerEXT_names[] =
"iiiip\0" /* Parameter signature */
"glVertexPointerEXT\0"
"";
#endif
#if defined(need_GL_SGIS_texture_filter4)
-static const char GetTexFilterFuncSGIS_names[] =
+static const char GetTexFilterFuncSGIS_names[] =
"iip\0" /* Parameter signature */
"glGetTexFilterFuncSGIS\0"
"";
#endif
#if defined(need_GL_NV_register_combiners)
-static const char GetCombinerOutputParameterfvNV_names[] =
+static const char GetCombinerOutputParameterfvNV_names[] =
"iiip\0" /* Parameter signature */
"glGetCombinerOutputParameterfvNV\0"
"";
#endif
#if defined(need_GL_EXT_subtexture)
-static const char TexSubImage1D_names[] =
+static const char TexSubImage1D_names[] =
"iiiiiip\0" /* Parameter signature */
"glTexSubImage1D\0"
"glTexSubImage1DEXT\0"
@@ -1033,36 +1081,43 @@ static const char TexSubImage1D_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib1sARB_names[] =
+static const char VertexAttrib1sARB_names[] =
"ii\0" /* Parameter signature */
"glVertexAttrib1s\0"
"glVertexAttrib1sARB\0"
"";
#endif
+#if defined(need_GL_ARB_sync)
+static const char FenceSync_names[] =
+ "ii\0" /* Parameter signature */
+ "glFenceSync\0"
+ "";
+#endif
+
#if defined(need_GL_NV_register_combiners)
-static const char FinalCombinerInputNV_names[] =
+static const char FinalCombinerInputNV_names[] =
"iiii\0" /* Parameter signature */
"glFinalCombinerInputNV\0"
"";
#endif
#if defined(need_GL_SGIX_flush_raster)
-static const char FlushRasterSGIX_names[] =
+static const char FlushRasterSGIX_names[] =
"\0" /* Parameter signature */
"glFlushRasterSGIX\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiTexCoord2fVertex3fSUN_names[] =
+static const char ReplacementCodeuiTexCoord2fVertex3fSUN_names[] =
"ifffff\0" /* Parameter signature */
"glReplacementCodeuiTexCoord2fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform1fARB_names[] =
+static const char Uniform1fARB_names[] =
"if\0" /* Parameter signature */
"glUniform1f\0"
"glUniform1fARB\0"
@@ -1070,22 +1125,15 @@ static const char Uniform1fARB_names[] =
#endif
#if defined(need_GL_EXT_texture_object)
-static const char AreTexturesResident_names[] =
+static const char AreTexturesResident_names[] =
"ipp\0" /* Parameter signature */
"glAreTexturesResident\0"
"glAreTexturesResidentEXT\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char IsRenderbufferEXT_names[] =
- "i\0" /* Parameter signature */
- "glIsRenderbufferEXT\0"
- "";
-#endif
-
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ATI_separate_stencil)
-static const char StencilOpSeparate_names[] =
+static const char StencilOpSeparate_names[] =
"iiii\0" /* Parameter signature */
"glStencilOpSeparate\0"
"glStencilOpSeparateATI\0"
@@ -1093,7 +1141,7 @@ static const char StencilOpSeparate_names[] =
#endif
#if defined(need_GL_SGI_color_table)
-static const char ColorTableParameteriv_names[] =
+static const char ColorTableParameteriv_names[] =
"iip\0" /* Parameter signature */
"glColorTableParameteriv\0"
"glColorTableParameterivSGI\0"
@@ -1101,14 +1149,14 @@ static const char ColorTableParameteriv_names[] =
#endif
#if defined(need_GL_IBM_vertex_array_lists)
-static const char FogCoordPointerListIBM_names[] =
+static const char FogCoordPointerListIBM_names[] =
"iipi\0" /* Parameter signature */
"glFogCoordPointerListIBM\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos3dMESA_names[] =
+static const char WindowPos3dMESA_names[] =
"ddd\0" /* Parameter signature */
"glWindowPos3d\0"
"glWindowPos3dARB\0"
@@ -1117,7 +1165,7 @@ static const char WindowPos3dMESA_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_point_parameters) || defined(need_GL_EXT_point_parameters) || defined(need_GL_SGIS_point_parameters)
-static const char PointParameterfvEXT_names[] =
+static const char PointParameterfvEXT_names[] =
"ip\0" /* Parameter signature */
"glPointParameterfv\0"
"glPointParameterfvARB\0"
@@ -1127,7 +1175,7 @@ static const char PointParameterfvEXT_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos2fvMESA_names[] =
+static const char WindowPos2fvMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos2fv\0"
"glWindowPos2fvARB\0"
@@ -1136,7 +1184,7 @@ static const char WindowPos2fvMESA_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3bvEXT_names[] =
+static const char SecondaryColor3bvEXT_names[] =
"p\0" /* Parameter signature */
"glSecondaryColor3bv\0"
"glSecondaryColor3bvEXT\0"
@@ -1144,63 +1192,64 @@ static const char SecondaryColor3bvEXT_names[] =
#endif
#if defined(need_GL_IBM_vertex_array_lists)
-static const char VertexPointerListIBM_names[] =
+static const char VertexPointerListIBM_names[] =
"iiipi\0" /* Parameter signature */
"glVertexPointerListIBM\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char GetProgramLocalParameterfvARB_names[] =
+static const char GetProgramLocalParameterfvARB_names[] =
"iip\0" /* Parameter signature */
"glGetProgramLocalParameterfvARB\0"
"";
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentMaterialfSGIX_names[] =
+static const char FragmentMaterialfSGIX_names[] =
"iif\0" /* Parameter signature */
"glFragmentMaterialfSGIX\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fNormal3fVertex3fSUN_names[] =
+static const char TexCoord2fNormal3fVertex3fSUN_names[] =
"ffffffff\0" /* Parameter signature */
"glTexCoord2fNormal3fVertex3fSUN\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char RenderbufferStorageEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char RenderbufferStorageEXT_names[] =
"iiii\0" /* Parameter signature */
+ "glRenderbufferStorage\0"
"glRenderbufferStorageEXT\0"
"";
#endif
#if defined(need_GL_NV_fence)
-static const char IsFenceNV_names[] =
+static const char IsFenceNV_names[] =
"i\0" /* Parameter signature */
"glIsFenceNV\0"
"";
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char AttachObjectARB_names[] =
+static const char AttachObjectARB_names[] =
"ii\0" /* Parameter signature */
"glAttachObjectARB\0"
"";
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char GetFragmentLightivSGIX_names[] =
+static const char GetFragmentLightivSGIX_names[] =
"iip\0" /* Parameter signature */
"glGetFragmentLightivSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char UniformMatrix2fvARB_names[] =
+static const char UniformMatrix2fvARB_names[] =
"iiip\0" /* Parameter signature */
"glUniformMatrix2fv\0"
"glUniformMatrix2fvARB\0"
@@ -1208,7 +1257,7 @@ static const char UniformMatrix2fvARB_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord2fARB_names[] =
+static const char MultiTexCoord2fARB_names[] =
"iff\0" /* Parameter signature */
"glMultiTexCoord2f\0"
"glMultiTexCoord2fARB\0"
@@ -1216,7 +1265,7 @@ static const char MultiTexCoord2fARB_names[] =
#endif
#if defined(need_GL_SGI_color_table) || defined(need_GL_EXT_paletted_texture)
-static const char ColorTable_names[] =
+static const char ColorTable_names[] =
"iiiiip\0" /* Parameter signature */
"glColorTable\0"
"glColorTableSGI\0"
@@ -1225,14 +1274,14 @@ static const char ColorTable_names[] =
#endif
#if defined(need_GL_NV_evaluators)
-static const char MapControlPointsNV_names[] =
+static const char MapControlPointsNV_names[] =
"iiiiiiiip\0" /* Parameter signature */
"glMapControlPointsNV\0"
"";
#endif
#if defined(need_GL_EXT_convolution)
-static const char ConvolutionFilter2D_names[] =
+static const char ConvolutionFilter2D_names[] =
"iiiiiip\0" /* Parameter signature */
"glConvolutionFilter2D\0"
"glConvolutionFilter2DEXT\0"
@@ -1240,14 +1289,14 @@ static const char ConvolutionFilter2D_names[] =
#endif
#if defined(need_GL_NV_evaluators)
-static const char MapParameterfvNV_names[] =
+static const char MapParameterfvNV_names[] =
"iip\0" /* Parameter signature */
"glMapParameterfvNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib3dvARB_names[] =
+static const char VertexAttrib3dvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib3dv\0"
"glVertexAttrib3dvARB\0"
@@ -1255,14 +1304,14 @@ static const char VertexAttrib3dvARB_names[] =
#endif
#if defined(need_GL_PGI_misc_hints)
-static const char HintPGI_names[] =
+static const char HintPGI_names[] =
"ii\0" /* Parameter signature */
"glHintPGI\0"
"";
#endif
#if defined(need_GL_EXT_convolution)
-static const char ConvolutionParameteriv_names[] =
+static const char ConvolutionParameteriv_names[] =
"iip\0" /* Parameter signature */
"glConvolutionParameteriv\0"
"glConvolutionParameterivEXT\0"
@@ -1270,28 +1319,28 @@ static const char ConvolutionParameteriv_names[] =
#endif
#if defined(need_GL_EXT_cull_vertex)
-static const char CullParameterdvEXT_names[] =
+static const char CullParameterdvEXT_names[] =
"ip\0" /* Parameter signature */
"glCullParameterdvEXT\0"
"";
#endif
#if defined(need_GL_NV_fragment_program)
-static const char ProgramNamedParameter4fNV_names[] =
+static const char ProgramNamedParameter4fNV_names[] =
"iipffff\0" /* Parameter signature */
"glProgramNamedParameter4fNV\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char Color3fVertex3fSUN_names[] =
+static const char Color3fVertex3fSUN_names[] =
"ffffff\0" /* Parameter signature */
"glColor3fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
-static const char ProgramEnvParameter4fvARB_names[] =
+static const char ProgramEnvParameter4fvARB_names[] =
"iip\0" /* Parameter signature */
"glProgramEnvParameter4fvARB\0"
"glProgramParameter4fvNV\0"
@@ -1299,14 +1348,14 @@ static const char ProgramEnvParameter4fvARB_names[] =
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentLightModeliSGIX_names[] =
+static const char FragmentLightModeliSGIX_names[] =
"ii\0" /* Parameter signature */
"glFragmentLightModeliSGIX\0"
"";
#endif
#if defined(need_GL_EXT_convolution)
-static const char ConvolutionParameterfv_names[] =
+static const char ConvolutionParameterfv_names[] =
"iip\0" /* Parameter signature */
"glConvolutionParameterfv\0"
"glConvolutionParameterfvEXT\0"
@@ -1314,35 +1363,42 @@ static const char ConvolutionParameterfv_names[] =
#endif
#if defined(need_GL_3DFX_tbuffer)
-static const char TbufferMask3DFX_names[] =
+static const char TbufferMask3DFX_names[] =
"i\0" /* Parameter signature */
"glTbufferMask3DFX\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char LoadProgramNV_names[] =
+static const char LoadProgramNV_names[] =
"iiip\0" /* Parameter signature */
"glLoadProgramNV\0"
"";
#endif
+#if defined(need_GL_ARB_sync)
+static const char WaitSync_names[] =
+ "iii\0" /* Parameter signature */
+ "glWaitSync\0"
+ "";
+#endif
+
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib4fvNV_names[] =
+static const char VertexAttrib4fvNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4fvNV\0"
"";
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char GetAttachedObjectsARB_names[] =
+static const char GetAttachedObjectsARB_names[] =
"iipp\0" /* Parameter signature */
"glGetAttachedObjectsARB\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform3fvARB_names[] =
+static const char Uniform3fvARB_names[] =
"iip\0" /* Parameter signature */
"glUniform3fv\0"
"glUniform3fvARB\0"
@@ -1350,7 +1406,7 @@ static const char Uniform3fvARB_names[] =
#endif
#if defined(need_GL_EXT_draw_range_elements)
-static const char DrawRangeElements_names[] =
+static const char DrawRangeElements_names[] =
"iiiiip\0" /* Parameter signature */
"glDrawRangeElements\0"
"glDrawRangeElementsEXT\0"
@@ -1358,35 +1414,36 @@ static const char DrawRangeElements_names[] =
#endif
#if defined(need_GL_SGIX_sprite)
-static const char SpriteParameterfvSGIX_names[] =
+static const char SpriteParameterfvSGIX_names[] =
"ip\0" /* Parameter signature */
"glSpriteParameterfvSGIX\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char CheckFramebufferStatusEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char CheckFramebufferStatusEXT_names[] =
"i\0" /* Parameter signature */
+ "glCheckFramebufferStatus\0"
"glCheckFramebufferStatusEXT\0"
"";
#endif
#if defined(need_GL_SUN_global_alpha)
-static const char GlobalAlphaFactoruiSUN_names[] =
+static const char GlobalAlphaFactoruiSUN_names[] =
"i\0" /* Parameter signature */
"glGlobalAlphaFactoruiSUN\0"
"";
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char GetHandleARB_names[] =
+static const char GetHandleARB_names[] =
"i\0" /* Parameter signature */
"glGetHandleARB\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char GetVertexAttribivARB_names[] =
+static const char GetVertexAttribivARB_names[] =
"iip\0" /* Parameter signature */
"glGetVertexAttribiv\0"
"glGetVertexAttribivARB\0"
@@ -1394,21 +1451,21 @@ static const char GetVertexAttribivARB_names[] =
#endif
#if defined(need_GL_NV_register_combiners)
-static const char GetCombinerInputParameterfvNV_names[] =
+static const char GetCombinerInputParameterfvNV_names[] =
"iiiip\0" /* Parameter signature */
"glGetCombinerInputParameterfvNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0)
-static const char CreateProgram_names[] =
+static const char CreateProgram_names[] =
"\0" /* Parameter signature */
"glCreateProgram\0"
"";
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_transpose_matrix)
-static const char LoadTransposeMatrixdARB_names[] =
+static const char LoadTransposeMatrixdARB_names[] =
"p\0" /* Parameter signature */
"glLoadTransposeMatrixd\0"
"glLoadTransposeMatrixdARB\0"
@@ -1416,7 +1473,7 @@ static const char LoadTransposeMatrixdARB_names[] =
#endif
#if defined(need_GL_EXT_histogram)
-static const char GetMinmax_names[] =
+static const char GetMinmax_names[] =
"iiiip\0" /* Parameter signature */
"glGetMinmax\0"
"glGetMinmaxEXT\0"
@@ -1424,14 +1481,14 @@ static const char GetMinmax_names[] =
#endif
#if defined(need_GL_VERSION_2_0)
-static const char StencilFuncSeparate_names[] =
+static const char StencilFuncSeparate_names[] =
"iiii\0" /* Parameter signature */
"glStencilFuncSeparate\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3sEXT_names[] =
+static const char SecondaryColor3sEXT_names[] =
"iii\0" /* Parameter signature */
"glSecondaryColor3s\0"
"glSecondaryColor3sEXT\0"
@@ -1439,28 +1496,28 @@ static const char SecondaryColor3sEXT_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char Color3fVertex3fvSUN_names[] =
+static const char Color3fVertex3fvSUN_names[] =
"pp\0" /* Parameter signature */
"glColor3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_SUN_global_alpha)
-static const char GlobalAlphaFactorbSUN_names[] =
+static const char GlobalAlphaFactorbSUN_names[] =
"i\0" /* Parameter signature */
"glGlobalAlphaFactorbSUN\0"
"";
#endif
#if defined(need_GL_HP_image_transform)
-static const char ImageTransformParameterfvHP_names[] =
+static const char ImageTransformParameterfvHP_names[] =
"iip\0" /* Parameter signature */
"glImageTransformParameterfvHP\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4ivARB_names[] =
+static const char VertexAttrib4ivARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4iv\0"
"glVertexAttrib4ivARB\0"
@@ -1468,28 +1525,28 @@ static const char VertexAttrib4ivARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib3fNV_names[] =
+static const char VertexAttrib3fNV_names[] =
"ifff\0" /* Parameter signature */
"glVertexAttrib3fNV\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs2dvNV_names[] =
+static const char VertexAttribs2dvNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs2dvNV\0"
"";
#endif
#if defined(need_GL_EXT_timer_query)
-static const char GetQueryObjectui64vEXT_names[] =
+static const char GetQueryObjectui64vEXT_names[] =
"iip\0" /* Parameter signature */
"glGetQueryObjectui64vEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord3fvARB_names[] =
+static const char MultiTexCoord3fvARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord3fv\0"
"glMultiTexCoord3fvARB\0"
@@ -1497,7 +1554,7 @@ static const char MultiTexCoord3fvARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3dEXT_names[] =
+static const char SecondaryColor3dEXT_names[] =
"ddd\0" /* Parameter signature */
"glSecondaryColor3d\0"
"glSecondaryColor3dEXT\0"
@@ -1505,42 +1562,42 @@ static const char SecondaryColor3dEXT_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char GetProgramParameterfvNV_names[] =
+static const char GetProgramParameterfvNV_names[] =
"iiip\0" /* Parameter signature */
"glGetProgramParameterfvNV\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char TangentPointerEXT_names[] =
+static const char TangentPointerEXT_names[] =
"iip\0" /* Parameter signature */
"glTangentPointerEXT\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char Color4fNormal3fVertex3fvSUN_names[] =
+static const char Color4fNormal3fVertex3fvSUN_names[] =
"ppp\0" /* Parameter signature */
"glColor4fNormal3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_SGIX_instruments)
-static const char GetInstrumentsSGIX_names[] =
+static const char GetInstrumentsSGIX_names[] =
"\0" /* Parameter signature */
"glGetInstrumentsSGIX\0"
"";
#endif
#if defined(need_GL_NV_evaluators)
-static const char EvalMapsNV_names[] =
+static const char EvalMapsNV_names[] =
"ii\0" /* Parameter signature */
"glEvalMapsNV\0"
"";
#endif
#if defined(need_GL_EXT_subtexture)
-static const char TexSubImage2D_names[] =
+static const char TexSubImage2D_names[] =
"iiiiiiiip\0" /* Parameter signature */
"glTexSubImage2D\0"
"glTexSubImage2DEXT\0"
@@ -1548,28 +1605,28 @@ static const char TexSubImage2D_names[] =
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentLightivSGIX_names[] =
+static const char FragmentLightivSGIX_names[] =
"iip\0" /* Parameter signature */
"glFragmentLightivSGIX\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char DeleteRenderbuffersEXT_names[] =
- "ip\0" /* Parameter signature */
- "glDeleteRenderbuffersEXT\0"
+#if defined(need_GL_APPLE_texture_range)
+static const char GetTexParameterPointervAPPLE_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetTexParameterPointervAPPLE\0"
"";
#endif
#if defined(need_GL_EXT_pixel_transform)
-static const char PixelTransformParameterfvEXT_names[] =
+static const char PixelTransformParameterfvEXT_names[] =
"iip\0" /* Parameter signature */
"glPixelTransformParameterfvEXT\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4bvARB_names[] =
+static const char VertexAttrib4bvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4bv\0"
"glVertexAttrib4bvARB\0"
@@ -1577,14 +1634,14 @@ static const char VertexAttrib4bvARB_names[] =
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char AlphaFragmentOp2ATI_names[] =
+static const char AlphaFragmentOp2ATI_names[] =
"iiiiiiiii\0" /* Parameter signature */
"glAlphaFragmentOp2ATI\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord4sARB_names[] =
+static const char MultiTexCoord4sARB_names[] =
"iiiii\0" /* Parameter signature */
"glMultiTexCoord4s\0"
"glMultiTexCoord4sARB\0"
@@ -1592,28 +1649,28 @@ static const char MultiTexCoord4sARB_names[] =
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char GetFragmentMaterialivSGIX_names[] =
+static const char GetFragmentMaterialivSGIX_names[] =
"iip\0" /* Parameter signature */
"glGetFragmentMaterialivSGIX\0"
"";
#endif
#if defined(need_GL_MESA_window_pos)
-static const char WindowPos4dMESA_names[] =
+static const char WindowPos4dMESA_names[] =
"dddd\0" /* Parameter signature */
"glWindowPos4dMESA\0"
"";
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char WeightPointerARB_names[] =
+static const char WeightPointerARB_names[] =
"iiip\0" /* Parameter signature */
"glWeightPointerARB\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos2dMESA_names[] =
+static const char WindowPos2dMESA_names[] =
"dd\0" /* Parameter signature */
"glWindowPos2d\0"
"glWindowPos2dARB\0"
@@ -1621,15 +1678,16 @@ static const char WindowPos2dMESA_names[] =
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char FramebufferTexture3DEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char FramebufferTexture3DEXT_names[] =
"iiiiii\0" /* Parameter signature */
+ "glFramebufferTexture3D\0"
"glFramebufferTexture3DEXT\0"
"";
#endif
#if defined(need_GL_EXT_blend_minmax)
-static const char BlendEquation_names[] =
+static const char BlendEquation_names[] =
"i\0" /* Parameter signature */
"glBlendEquation\0"
"glBlendEquationEXT\0"
@@ -1637,14 +1695,14 @@ static const char BlendEquation_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib3dNV_names[] =
+static const char VertexAttrib3dNV_names[] =
"iddd\0" /* Parameter signature */
"glVertexAttrib3dNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib3dARB_names[] =
+static const char VertexAttrib3dARB_names[] =
"iddd\0" /* Parameter signature */
"glVertexAttrib3d\0"
"glVertexAttrib3dARB\0"
@@ -1652,14 +1710,14 @@ static const char VertexAttrib3dARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN_names[] =
+static const char ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN_names[] =
"ppppp\0" /* Parameter signature */
"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4fARB_names[] =
+static const char VertexAttrib4fARB_names[] =
"iffff\0" /* Parameter signature */
"glVertexAttrib4f\0"
"glVertexAttrib4fARB\0"
@@ -1667,21 +1725,22 @@ static const char VertexAttrib4fARB_names[] =
#endif
#if defined(need_GL_EXT_index_func)
-static const char IndexFuncEXT_names[] =
+static const char IndexFuncEXT_names[] =
"if\0" /* Parameter signature */
"glIndexFuncEXT\0"
"";
#endif
-#if defined(need_GL_SGIX_list_priority)
-static const char GetListParameterfvSGIX_names[] =
- "iip\0" /* Parameter signature */
- "glGetListParameterfvSGIX\0"
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char FramebufferTexture2DEXT_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glFramebufferTexture2D\0"
+ "glFramebufferTexture2DEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord2dvARB_names[] =
+static const char MultiTexCoord2dvARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord2dv\0"
"glMultiTexCoord2dvARB\0"
@@ -1689,21 +1748,21 @@ static const char MultiTexCoord2dvARB_names[] =
#endif
#if defined(need_GL_EXT_cull_vertex)
-static const char CullParameterfvEXT_names[] =
+static const char CullParameterfvEXT_names[] =
"ip\0" /* Parameter signature */
"glCullParameterfvEXT\0"
"";
#endif
#if defined(need_GL_NV_fragment_program)
-static const char ProgramNamedParameter4fvNV_names[] =
+static const char ProgramNamedParameter4fvNV_names[] =
"iipp\0" /* Parameter signature */
"glProgramNamedParameter4fvNV\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColorPointerEXT_names[] =
+static const char SecondaryColorPointerEXT_names[] =
"iiip\0" /* Parameter signature */
"glSecondaryColorPointer\0"
"glSecondaryColorPointerEXT\0"
@@ -1711,7 +1770,7 @@ static const char SecondaryColorPointerEXT_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4fvARB_names[] =
+static const char VertexAttrib4fvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4fv\0"
"glVertexAttrib4fvARB\0"
@@ -1719,14 +1778,14 @@ static const char VertexAttrib4fvARB_names[] =
#endif
#if defined(need_GL_IBM_vertex_array_lists)
-static const char ColorPointerListIBM_names[] =
+static const char ColorPointerListIBM_names[] =
"iiipi\0" /* Parameter signature */
"glColorPointerListIBM\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char GetActiveUniformARB_names[] =
+static const char GetActiveUniformARB_names[] =
"iiipppp\0" /* Parameter signature */
"glGetActiveUniform\0"
"glGetActiveUniformARB\0"
@@ -1734,14 +1793,14 @@ static const char GetActiveUniformARB_names[] =
#endif
#if defined(need_GL_HP_image_transform)
-static const char ImageTransformParameteriHP_names[] =
+static const char ImageTransformParameteriHP_names[] =
"iii\0" /* Parameter signature */
"glImageTransformParameteriHP\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord1svARB_names[] =
+static const char MultiTexCoord1svARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord1sv\0"
"glMultiTexCoord1svARB\0"
@@ -1749,7 +1808,7 @@ static const char MultiTexCoord1svARB_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
-static const char EndQueryARB_names[] =
+static const char EndQueryARB_names[] =
"i\0" /* Parameter signature */
"glEndQuery\0"
"glEndQueryARB\0"
@@ -1757,42 +1816,35 @@ static const char EndQueryARB_names[] =
#endif
#if defined(need_GL_NV_fence)
-static const char DeleteFencesNV_names[] =
+static const char DeleteFencesNV_names[] =
"ip\0" /* Parameter signature */
"glDeleteFencesNV\0"
"";
#endif
-#if defined(need_GL_SGIX_polynomial_ffd)
-static const char DeformationMap3dSGIX_names[] =
- "iddiiddiiddiip\0" /* Parameter signature */
- "glDeformationMap3dSGIX\0"
- "";
-#endif
-
#if defined(need_GL_VERSION_2_0)
-static const char IsShader_names[] =
+static const char IsShader_names[] =
"i\0" /* Parameter signature */
"glIsShader\0"
"";
#endif
#if defined(need_GL_HP_image_transform)
-static const char GetImageTransformParameterivHP_names[] =
+static const char GetImageTransformParameterivHP_names[] =
"iip\0" /* Parameter signature */
"glGetImageTransformParameterivHP\0"
"";
#endif
#if defined(need_GL_MESA_window_pos)
-static const char WindowPos4ivMESA_names[] =
+static const char WindowPos4ivMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos4ivMESA\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord3svARB_names[] =
+static const char MultiTexCoord3svARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord3sv\0"
"glMultiTexCoord3svARB\0"
@@ -1800,7 +1852,7 @@ static const char MultiTexCoord3svARB_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord4iARB_names[] =
+static const char MultiTexCoord4iARB_names[] =
"iiiii\0" /* Parameter signature */
"glMultiTexCoord4i\0"
"glMultiTexCoord4iARB\0"
@@ -1808,21 +1860,21 @@ static const char MultiTexCoord4iARB_names[] =
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3ivEXT_names[] =
+static const char Binormal3ivEXT_names[] =
"p\0" /* Parameter signature */
"glBinormal3ivEXT\0"
"";
#endif
#if defined(need_GL_MESA_resize_buffers)
-static const char ResizeBuffersMESA_names[] =
+static const char ResizeBuffersMESA_names[] =
"\0" /* Parameter signature */
"glResizeBuffersMESA\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char GetUniformivARB_names[] =
+static const char GetUniformivARB_names[] =
"iip\0" /* Parameter signature */
"glGetUniformiv\0"
"glGetUniformivARB\0"
@@ -1830,28 +1882,28 @@ static const char GetUniformivARB_names[] =
#endif
#if defined(need_GL_SGIS_pixel_texture)
-static const char PixelTexGenParameteriSGIS_names[] =
+static const char PixelTexGenParameteriSGIS_names[] =
"ii\0" /* Parameter signature */
"glPixelTexGenParameteriSGIS\0"
"";
#endif
#if defined(need_GL_INTEL_parallel_arrays)
-static const char VertexPointervINTEL_names[] =
+static const char VertexPointervINTEL_names[] =
"iip\0" /* Parameter signature */
"glVertexPointervINTEL\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiColor4fNormal3fVertex3fvSUN_names[] =
+static const char ReplacementCodeuiColor4fNormal3fVertex3fvSUN_names[] =
"pppp\0" /* Parameter signature */
"glReplacementCodeuiColor4fNormal3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3uiEXT_names[] =
+static const char SecondaryColor3uiEXT_names[] =
"iii\0" /* Parameter signature */
"glSecondaryColor3ui\0"
"glSecondaryColor3uiEXT\0"
@@ -1859,14 +1911,14 @@ static const char SecondaryColor3uiEXT_names[] =
#endif
#if defined(need_GL_SGIX_instruments)
-static const char StartInstrumentsSGIX_names[] =
+static const char StartInstrumentsSGIX_names[] =
"\0" /* Parameter signature */
"glStartInstrumentsSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3usvEXT_names[] =
+static const char SecondaryColor3usvEXT_names[] =
"p\0" /* Parameter signature */
"glSecondaryColor3usv\0"
"glSecondaryColor3usvEXT\0"
@@ -1874,42 +1926,49 @@ static const char SecondaryColor3usvEXT_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib2fvNV_names[] =
+static const char VertexAttrib2fvNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib2fvNV\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char ProgramLocalParameter4dvARB_names[] =
+static const char ProgramLocalParameter4dvARB_names[] =
"iip\0" /* Parameter signature */
"glProgramLocalParameter4dvARB\0"
"";
#endif
#if defined(need_GL_ARB_matrix_palette)
-static const char MatrixIndexuivARB_names[] =
+static const char MatrixIndexuivARB_names[] =
"ip\0" /* Parameter signature */
"glMatrixIndexuivARB\0"
"";
#endif
+#if defined(need_GL_ARB_framebuffer_object)
+static const char RenderbufferStorageMultisample_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glRenderbufferStorageMultisample\0"
+ "";
+#endif
+
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3sEXT_names[] =
+static const char Tangent3sEXT_names[] =
"iii\0" /* Parameter signature */
"glTangent3sEXT\0"
"";
#endif
#if defined(need_GL_SUN_global_alpha)
-static const char GlobalAlphaFactorfSUN_names[] =
+static const char GlobalAlphaFactorfSUN_names[] =
"f\0" /* Parameter signature */
"glGlobalAlphaFactorfSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord3iARB_names[] =
+static const char MultiTexCoord3iARB_names[] =
"iiii\0" /* Parameter signature */
"glMultiTexCoord3i\0"
"glMultiTexCoord3iARB\0"
@@ -1917,49 +1976,50 @@ static const char MultiTexCoord3iARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0)
-static const char IsProgram_names[] =
+static const char IsProgram_names[] =
"i\0" /* Parameter signature */
"glIsProgram\0"
"";
#endif
#if defined(need_GL_IBM_vertex_array_lists)
-static const char TexCoordPointerListIBM_names[] =
+static const char TexCoordPointerListIBM_names[] =
"iiipi\0" /* Parameter signature */
"glTexCoordPointerListIBM\0"
"";
#endif
#if defined(need_GL_SUN_global_alpha)
-static const char GlobalAlphaFactorusSUN_names[] =
+static const char GlobalAlphaFactorusSUN_names[] =
"i\0" /* Parameter signature */
"glGlobalAlphaFactorusSUN\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib2dvNV_names[] =
+static const char VertexAttrib2dvNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib2dvNV\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char FramebufferRenderbufferEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char FramebufferRenderbufferEXT_names[] =
"iiii\0" /* Parameter signature */
+ "glFramebufferRenderbuffer\0"
"glFramebufferRenderbufferEXT\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib1dvNV_names[] =
+static const char VertexAttrib1dvNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib1dvNV\0"
"";
#endif
#if defined(need_GL_EXT_texture_object)
-static const char GenTextures_names[] =
+static const char GenTextures_names[] =
"ip\0" /* Parameter signature */
"glGenTextures\0"
"glGenTexturesEXT\0"
@@ -1967,63 +2027,71 @@ static const char GenTextures_names[] =
#endif
#if defined(need_GL_NV_fence)
-static const char SetFenceNV_names[] =
+static const char SetFenceNV_names[] =
"ii\0" /* Parameter signature */
"glSetFenceNV\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char FramebufferTexture1DEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char FramebufferTexture1DEXT_names[] =
"iiiii\0" /* Parameter signature */
+ "glFramebufferTexture1D\0"
"glFramebufferTexture1DEXT\0"
"";
#endif
#if defined(need_GL_NV_register_combiners)
-static const char GetCombinerOutputParameterivNV_names[] =
+static const char GetCombinerOutputParameterivNV_names[] =
"iiip\0" /* Parameter signature */
"glGetCombinerOutputParameterivNV\0"
"";
#endif
+#if defined(need_GL_IBM_multimode_draw_arrays)
+static const char MultiModeDrawArraysIBM_names[] =
+ "pppii\0" /* Parameter signature */
+ "glMultiModeDrawArraysIBM\0"
+ "";
+#endif
+
#if defined(need_GL_SGIS_pixel_texture)
-static const char PixelTexGenParameterivSGIS_names[] =
+static const char PixelTexGenParameterivSGIS_names[] =
"ip\0" /* Parameter signature */
"glPixelTexGenParameterivSGIS\0"
"";
#endif
#if defined(need_GL_EXT_texture_perturb_normal)
-static const char TextureNormalEXT_names[] =
+static const char TextureNormalEXT_names[] =
"i\0" /* Parameter signature */
"glTextureNormalEXT\0"
"";
#endif
#if defined(need_GL_IBM_vertex_array_lists)
-static const char IndexPointerListIBM_names[] =
+static const char IndexPointerListIBM_names[] =
"iipi\0" /* Parameter signature */
"glIndexPointerListIBM\0"
"";
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char WeightfvARB_names[] =
+static const char WeightfvARB_names[] =
"ip\0" /* Parameter signature */
"glWeightfvARB\0"
"";
#endif
#if defined(need_GL_MESA_window_pos)
-static const char WindowPos4fMESA_names[] =
+static const char WindowPos4fMESA_names[] =
"ffff\0" /* Parameter signature */
"glWindowPos4fMESA\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos3dvMESA_names[] =
+static const char WindowPos3dvMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos3dv\0"
"glWindowPos3dvARB\0"
@@ -2032,14 +2100,14 @@ static const char WindowPos3dvMESA_names[] =
#endif
#if defined(need_GL_EXT_timer_query)
-static const char GetQueryObjecti64vEXT_names[] =
+static const char GetQueryObjecti64vEXT_names[] =
"iip\0" /* Parameter signature */
"glGetQueryObjecti64vEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord1dARB_names[] =
+static const char MultiTexCoord1dARB_names[] =
"id\0" /* Parameter signature */
"glMultiTexCoord1d\0"
"glMultiTexCoord1dARB\0"
@@ -2047,7 +2115,7 @@ static const char MultiTexCoord1dARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_NV_point_sprite)
-static const char PointParameterivNV_names[] =
+static const char PointParameterivNV_names[] =
"ip\0" /* Parameter signature */
"glPointParameteriv\0"
"glPointParameterivNV\0"
@@ -2055,15 +2123,22 @@ static const char PointParameterivNV_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform2fvARB_names[] =
+static const char Uniform2fvARB_names[] =
"iip\0" /* Parameter signature */
"glUniform2fv\0"
"glUniform2fvARB\0"
"";
#endif
+#if defined(need_GL_APPLE_flush_buffer_range)
+static const char BufferParameteriAPPLE_names[] =
+ "iii\0" /* Parameter signature */
+ "glBufferParameteriAPPLE\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord3dvARB_names[] =
+static const char MultiTexCoord3dvARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord3dv\0"
"glMultiTexCoord3dvARB\0"
@@ -2071,56 +2146,64 @@ static const char MultiTexCoord3dvARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN_names[] =
+static const char ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN_names[] =
"pppp\0" /* Parameter signature */
"glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char DeleteObjectARB_names[] =
+static const char DeleteObjectARB_names[] =
"i\0" /* Parameter signature */
"glDeleteObjectARB\0"
"";
#endif
#if defined(need_GL_ARB_matrix_palette)
-static const char MatrixIndexPointerARB_names[] =
+static const char MatrixIndexPointerARB_names[] =
"iiip\0" /* Parameter signature */
"glMatrixIndexPointerARB\0"
"";
#endif
#if defined(need_GL_NV_fragment_program)
-static const char ProgramNamedParameter4dvNV_names[] =
+static const char ProgramNamedParameter4dvNV_names[] =
"iipp\0" /* Parameter signature */
"glProgramNamedParameter4dvNV\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3fvEXT_names[] =
+static const char Tangent3fvEXT_names[] =
"p\0" /* Parameter signature */
"glTangent3fvEXT\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char BindFramebufferEXT_names[] =
+#if defined(need_GL_ARB_vertex_array_object)
+static const char GenVertexArrays_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenVertexArrays\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char BindFramebufferEXT_names[] =
"ii\0" /* Parameter signature */
+ "glBindFramebuffer\0"
"glBindFramebufferEXT\0"
"";
#endif
#if defined(need_GL_SGIX_reference_plane)
-static const char ReferencePlaneSGIX_names[] =
+static const char ReferencePlaneSGIX_names[] =
"p\0" /* Parameter signature */
"glReferencePlaneSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char ValidateProgramARB_names[] =
+static const char ValidateProgramARB_names[] =
"i\0" /* Parameter signature */
"glValidateProgram\0"
"glValidateProgramARB\0"
@@ -2128,21 +2211,21 @@ static const char ValidateProgramARB_names[] =
#endif
#if defined(need_GL_EXT_compiled_vertex_array)
-static const char UnlockArraysEXT_names[] =
+static const char UnlockArraysEXT_names[] =
"\0" /* Parameter signature */
"glUnlockArraysEXT\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fColor3fVertex3fSUN_names[] =
+static const char TexCoord2fColor3fVertex3fSUN_names[] =
"ffffffff\0" /* Parameter signature */
"glTexCoord2fColor3fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos3fvMESA_names[] =
+static const char WindowPos3fvMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos3fv\0"
"glWindowPos3fvARB\0"
@@ -2151,14 +2234,14 @@ static const char WindowPos3fvMESA_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib1svNV_names[] =
+static const char VertexAttrib1svNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib1svNV\0"
"";
#endif
#if defined(need_GL_EXT_copy_texture)
-static const char CopyTexSubImage3D_names[] =
+static const char CopyTexSubImage3D_names[] =
"iiiiiiiii\0" /* Parameter signature */
"glCopyTexSubImage3D\0"
"glCopyTexSubImage3DEXT\0"
@@ -2166,22 +2249,29 @@ static const char CopyTexSubImage3D_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib2dARB_names[] =
+static const char VertexAttrib2dARB_names[] =
"idd\0" /* Parameter signature */
"glVertexAttrib2d\0"
"glVertexAttrib2dARB\0"
"";
#endif
+#if defined(need_GL_ARB_sync)
+static const char GetInteger64v_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetInteger64v\0"
+ "";
+#endif
+
#if defined(need_GL_SGIS_texture_color_mask)
-static const char TextureColorMaskSGIS_names[] =
+static const char TextureColorMaskSGIS_names[] =
"iiii\0" /* Parameter signature */
"glTextureColorMaskSGIS\0"
"";
#endif
#if defined(need_GL_SGI_color_table) || defined(need_GL_EXT_paletted_texture)
-static const char GetColorTable_names[] =
+static const char GetColorTable_names[] =
"iiip\0" /* Parameter signature */
"glGetColorTable\0"
"glGetColorTableSGI\0"
@@ -2190,7 +2280,7 @@ static const char GetColorTable_names[] =
#endif
#if defined(need_GL_SGI_color_table)
-static const char CopyColorTable_names[] =
+static const char CopyColorTable_names[] =
"iiiii\0" /* Parameter signature */
"glCopyColorTable\0"
"glCopyColorTableSGI\0"
@@ -2198,7 +2288,7 @@ static const char CopyColorTable_names[] =
#endif
#if defined(need_GL_EXT_histogram)
-static const char GetHistogramParameterfv_names[] =
+static const char GetHistogramParameterfv_names[] =
"iip\0" /* Parameter signature */
"glGetHistogramParameterfv\0"
"glGetHistogramParameterfvEXT\0"
@@ -2206,21 +2296,21 @@ static const char GetHistogramParameterfv_names[] =
#endif
#if defined(need_GL_INTEL_parallel_arrays)
-static const char ColorPointervINTEL_names[] =
+static const char ColorPointervINTEL_names[] =
"iip\0" /* Parameter signature */
"glColorPointervINTEL\0"
"";
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char AlphaFragmentOp1ATI_names[] =
+static const char AlphaFragmentOp1ATI_names[] =
"iiiiii\0" /* Parameter signature */
"glAlphaFragmentOp1ATI\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord3ivARB_names[] =
+static const char MultiTexCoord3ivARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord3iv\0"
"glMultiTexCoord3ivARB\0"
@@ -2228,7 +2318,7 @@ static const char MultiTexCoord3ivARB_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord2sARB_names[] =
+static const char MultiTexCoord2sARB_names[] =
"iii\0" /* Parameter signature */
"glMultiTexCoord2s\0"
"glMultiTexCoord2sARB\0"
@@ -2236,7 +2326,7 @@ static const char MultiTexCoord2sARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib1dvARB_names[] =
+static const char VertexAttrib1dvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib1dv\0"
"glVertexAttrib1dvARB\0"
@@ -2244,7 +2334,7 @@ static const char VertexAttrib1dvARB_names[] =
#endif
#if defined(need_GL_EXT_texture_object)
-static const char DeleteTextures_names[] =
+static const char DeleteTextures_names[] =
"ip\0" /* Parameter signature */
"glDeleteTextures\0"
"glDeleteTexturesEXT\0"
@@ -2252,49 +2342,49 @@ static const char DeleteTextures_names[] =
#endif
#if defined(need_GL_EXT_vertex_array)
-static const char TexCoordPointerEXT_names[] =
+static const char TexCoordPointerEXT_names[] =
"iiiip\0" /* Parameter signature */
"glTexCoordPointerEXT\0"
"";
#endif
#if defined(need_GL_SGIS_texture4D)
-static const char TexSubImage4DSGIS_names[] =
+static const char TexSubImage4DSGIS_names[] =
"iiiiiiiiiiiip\0" /* Parameter signature */
"glTexSubImage4DSGIS\0"
"";
#endif
#if defined(need_GL_NV_register_combiners2)
-static const char CombinerStageParameterfvNV_names[] =
+static const char CombinerStageParameterfvNV_names[] =
"iip\0" /* Parameter signature */
"glCombinerStageParameterfvNV\0"
"";
#endif
#if defined(need_GL_SGIX_instruments)
-static const char StopInstrumentsSGIX_names[] =
+static const char StopInstrumentsSGIX_names[] =
"i\0" /* Parameter signature */
"glStopInstrumentsSGIX\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord4fColor4fNormal3fVertex4fSUN_names[] =
+static const char TexCoord4fColor4fNormal3fVertex4fSUN_names[] =
"fffffffffffffff\0" /* Parameter signature */
"glTexCoord4fColor4fNormal3fVertex4fSUN\0"
"";
#endif
#if defined(need_GL_SGIX_polynomial_ffd)
-static const char DeformSGIX_names[] =
+static const char DeformSGIX_names[] =
"i\0" /* Parameter signature */
"glDeformSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char GetVertexAttribfvARB_names[] =
+static const char GetVertexAttribfvARB_names[] =
"iip\0" /* Parameter signature */
"glGetVertexAttribfv\0"
"glGetVertexAttribfvARB\0"
@@ -2302,7 +2392,7 @@ static const char GetVertexAttribfvARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3ivEXT_names[] =
+static const char SecondaryColor3ivEXT_names[] =
"p\0" /* Parameter signature */
"glSecondaryColor3iv\0"
"glSecondaryColor3ivEXT\0"
@@ -2310,49 +2400,49 @@ static const char SecondaryColor3ivEXT_names[] =
#endif
#if defined(need_GL_VERSION_2_1)
-static const char UniformMatrix4x2fv_names[] =
+static const char UniformMatrix4x2fv_names[] =
"iiip\0" /* Parameter signature */
"glUniformMatrix4x2fv\0"
"";
#endif
#if defined(need_GL_SGIS_detail_texture)
-static const char GetDetailTexFuncSGIS_names[] =
+static const char GetDetailTexFuncSGIS_names[] =
"ip\0" /* Parameter signature */
"glGetDetailTexFuncSGIS\0"
"";
#endif
#if defined(need_GL_NV_register_combiners2)
-static const char GetCombinerStageParameterfvNV_names[] =
+static const char GetCombinerStageParameterfvNV_names[] =
"iip\0" /* Parameter signature */
"glGetCombinerStageParameterfvNV\0"
"";
#endif
-#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3fEXT_names[] =
- "fff\0" /* Parameter signature */
- "glBinormal3fEXT\0"
+#if defined(need_GL_ARB_vertex_array_object)
+static const char BindVertexArray_names[] =
+ "i\0" /* Parameter signature */
+ "glBindVertexArray\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char Color4ubVertex2fvSUN_names[] =
+static const char Color4ubVertex2fvSUN_names[] =
"pp\0" /* Parameter signature */
"glColor4ubVertex2fvSUN\0"
"";
#endif
#if defined(need_GL_SGIS_texture_filter4)
-static const char TexFilterFuncSGIS_names[] =
+static const char TexFilterFuncSGIS_names[] =
"iiip\0" /* Parameter signature */
"glTexFilterFuncSGIS\0"
"";
#endif
#if defined(need_GL_SGIS_multisample) || defined(need_GL_EXT_multisample)
-static const char SampleMaskSGIS_names[] =
+static const char SampleMaskSGIS_names[] =
"fi\0" /* Parameter signature */
"glSampleMaskSGIS\0"
"glSampleMaskEXT\0"
@@ -2360,7 +2450,7 @@ static const char SampleMaskSGIS_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_shader)
-static const char GetAttribLocationARB_names[] =
+static const char GetAttribLocationARB_names[] =
"ip\0" /* Parameter signature */
"glGetAttribLocation\0"
"glGetAttribLocationARB\0"
@@ -2368,7 +2458,7 @@ static const char GetAttribLocationARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4ubvARB_names[] =
+static const char VertexAttrib4ubvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4ubv\0"
"glVertexAttrib4ubvARB\0"
@@ -2376,21 +2466,21 @@ static const char VertexAttrib4ubvARB_names[] =
#endif
#if defined(need_GL_SGIS_detail_texture)
-static const char DetailTexFuncSGIS_names[] =
+static const char DetailTexFuncSGIS_names[] =
"iip\0" /* Parameter signature */
"glDetailTexFuncSGIS\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char Normal3fVertex3fSUN_names[] =
+static const char Normal3fVertex3fSUN_names[] =
"ffffff\0" /* Parameter signature */
"glNormal3fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_EXT_copy_texture)
-static const char CopyTexImage2D_names[] =
+static const char CopyTexImage2D_names[] =
"iiiiiiii\0" /* Parameter signature */
"glCopyTexImage2D\0"
"glCopyTexImage2DEXT\0"
@@ -2398,7 +2488,7 @@ static const char CopyTexImage2D_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char GetBufferPointervARB_names[] =
+static const char GetBufferPointervARB_names[] =
"iip\0" /* Parameter signature */
"glGetBufferPointerv\0"
"glGetBufferPointervARB\0"
@@ -2406,7 +2496,7 @@ static const char GetBufferPointervARB_names[] =
#endif
#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
-static const char ProgramEnvParameter4fARB_names[] =
+static const char ProgramEnvParameter4fARB_names[] =
"iiffff\0" /* Parameter signature */
"glProgramEnvParameter4fARB\0"
"glProgramParameter4fNV\0"
@@ -2414,7 +2504,7 @@ static const char ProgramEnvParameter4fARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform3ivARB_names[] =
+static const char Uniform3ivARB_names[] =
"iip\0" /* Parameter signature */
"glUniform3iv\0"
"glUniform3ivARB\0"
@@ -2422,21 +2512,21 @@ static const char Uniform3ivARB_names[] =
#endif
#if defined(need_GL_NV_fence)
-static const char GetFenceivNV_names[] =
+static const char GetFenceivNV_names[] =
"iip\0" /* Parameter signature */
"glGetFenceivNV\0"
"";
#endif
#if defined(need_GL_MESA_window_pos)
-static const char WindowPos4dvMESA_names[] =
+static const char WindowPos4dvMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos4dvMESA\0"
"";
#endif
#if defined(need_GL_EXT_color_subtable)
-static const char ColorSubTable_names[] =
+static const char ColorSubTable_names[] =
"iiiiip\0" /* Parameter signature */
"glColorSubTable\0"
"glColorSubTableEXT\0"
@@ -2444,7 +2534,7 @@ static const char ColorSubTable_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord4ivARB_names[] =
+static const char MultiTexCoord4ivARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord4iv\0"
"glMultiTexCoord4ivARB\0"
@@ -2452,21 +2542,21 @@ static const char MultiTexCoord4ivARB_names[] =
#endif
#if defined(need_GL_EXT_gpu_program_parameters)
-static const char ProgramLocalParameters4fvEXT_names[] =
+static const char ProgramLocalParameters4fvEXT_names[] =
"iiip\0" /* Parameter signature */
"glProgramLocalParameters4fvEXT\0"
"";
#endif
#if defined(need_GL_NV_evaluators)
-static const char GetMapAttribParameterfvNV_names[] =
+static const char GetMapAttribParameterfvNV_names[] =
"iiip\0" /* Parameter signature */
"glGetMapAttribParameterfvNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4sARB_names[] =
+static const char VertexAttrib4sARB_names[] =
"iiiii\0" /* Parameter signature */
"glVertexAttrib4s\0"
"glVertexAttrib4sARB\0"
@@ -2474,7 +2564,7 @@ static const char VertexAttrib4sARB_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
-static const char GetQueryObjectuivARB_names[] =
+static const char GetQueryObjectuivARB_names[] =
"iip\0" /* Parameter signature */
"glGetQueryObjectuiv\0"
"glGetQueryObjectuivARB\0"
@@ -2482,21 +2572,22 @@ static const char GetQueryObjectuivARB_names[] =
#endif
#if defined(need_GL_NV_evaluators)
-static const char MapParameterivNV_names[] =
+static const char MapParameterivNV_names[] =
"iip\0" /* Parameter signature */
"glMapParameterivNV\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char GenRenderbuffersEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GenRenderbuffersEXT_names[] =
"ip\0" /* Parameter signature */
+ "glGenRenderbuffers\0"
"glGenRenderbuffersEXT\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib2dvARB_names[] =
+static const char VertexAttrib2dvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib2dv\0"
"glVertexAttrib2dvARB\0"
@@ -2504,28 +2595,28 @@ static const char VertexAttrib2dvARB_names[] =
#endif
#if defined(need_GL_EXT_vertex_array)
-static const char EdgeFlagPointerEXT_names[] =
+static const char EdgeFlagPointerEXT_names[] =
"iip\0" /* Parameter signature */
"glEdgeFlagPointerEXT\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs2svNV_names[] =
+static const char VertexAttribs2svNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs2svNV\0"
"";
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char WeightbvARB_names[] =
+static const char WeightbvARB_names[] =
"ip\0" /* Parameter signature */
"glWeightbvARB\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib2fvARB_names[] =
+static const char VertexAttrib2fvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib2fv\0"
"glVertexAttrib2fvARB\0"
@@ -2533,7 +2624,7 @@ static const char VertexAttrib2fvARB_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char GetBufferParameterivARB_names[] =
+static const char GetBufferParameterivARB_names[] =
"iip\0" /* Parameter signature */
"glGetBufferParameteriv\0"
"glGetBufferParameterivARB\0"
@@ -2541,28 +2632,28 @@ static const char GetBufferParameterivARB_names[] =
#endif
#if defined(need_GL_SGIX_list_priority)
-static const char ListParameteriSGIX_names[] =
+static const char ListParameteriSGIX_names[] =
"iii\0" /* Parameter signature */
"glListParameteriSGIX\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiColor4fNormal3fVertex3fSUN_names[] =
+static const char ReplacementCodeuiColor4fNormal3fVertex3fSUN_names[] =
"iffffffffff\0" /* Parameter signature */
"glReplacementCodeuiColor4fNormal3fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_SGIX_instruments)
-static const char InstrumentsBufferSGIX_names[] =
+static const char InstrumentsBufferSGIX_names[] =
"ip\0" /* Parameter signature */
"glInstrumentsBufferSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4NivARB_names[] =
+static const char VertexAttrib4NivARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4Niv\0"
"glVertexAttrib4NivARB\0"
@@ -2570,35 +2661,35 @@ static const char VertexAttrib4NivARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0)
-static const char GetAttachedShaders_names[] =
+static const char GetAttachedShaders_names[] =
"iipp\0" /* Parameter signature */
"glGetAttachedShaders\0"
"";
#endif
#if defined(need_GL_APPLE_vertex_array_object)
-static const char GenVertexArraysAPPLE_names[] =
+static const char GenVertexArraysAPPLE_names[] =
"ip\0" /* Parameter signature */
"glGenVertexArraysAPPLE\0"
"";
#endif
#if defined(need_GL_EXT_gpu_program_parameters)
-static const char ProgramEnvParameters4fvEXT_names[] =
+static const char ProgramEnvParameters4fvEXT_names[] =
"iiip\0" /* Parameter signature */
"glProgramEnvParameters4fvEXT\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fColor4fNormal3fVertex3fvSUN_names[] =
+static const char TexCoord2fColor4fNormal3fVertex3fvSUN_names[] =
"pppp\0" /* Parameter signature */
"glTexCoord2fColor4fNormal3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos2iMESA_names[] =
+static const char WindowPos2iMESA_names[] =
"ii\0" /* Parameter signature */
"glWindowPos2i\0"
"glWindowPos2iARB\0"
@@ -2607,7 +2698,7 @@ static const char WindowPos2iMESA_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3fvEXT_names[] =
+static const char SecondaryColor3fvEXT_names[] =
"p\0" /* Parameter signature */
"glSecondaryColor3fv\0"
"glSecondaryColor3fvEXT\0"
@@ -2615,7 +2706,7 @@ static const char SecondaryColor3fvEXT_names[] =
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
-static const char CompressedTexSubImage1DARB_names[] =
+static const char CompressedTexSubImage1DARB_names[] =
"iiiiiip\0" /* Parameter signature */
"glCompressedTexSubImage1D\0"
"glCompressedTexSubImage1DARB\0"
@@ -2623,21 +2714,28 @@ static const char CompressedTexSubImage1DARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char GetVertexAttribivNV_names[] =
+static const char GetVertexAttribivNV_names[] =
"iip\0" /* Parameter signature */
"glGetVertexAttribivNV\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char GetProgramStringARB_names[] =
+static const char GetProgramStringARB_names[] =
"iip\0" /* Parameter signature */
"glGetProgramStringARB\0"
"";
#endif
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const char TexBumpParameterfvATI_names[] =
+ "ip\0" /* Parameter signature */
+ "glTexBumpParameterfvATI\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char CompileShaderARB_names[] =
+static const char CompileShaderARB_names[] =
"i\0" /* Parameter signature */
"glCompileShader\0"
"glCompileShaderARB\0"
@@ -2645,14 +2743,14 @@ static const char CompileShaderARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0)
-static const char DeleteShader_names[] =
+static const char DeleteShader_names[] =
"i\0" /* Parameter signature */
"glDeleteShader\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform3fARB_names[] =
+static const char Uniform3fARB_names[] =
"ifff\0" /* Parameter signature */
"glUniform3f\0"
"glUniform3fARB\0"
@@ -2660,28 +2758,28 @@ static const char Uniform3fARB_names[] =
#endif
#if defined(need_GL_SGIX_list_priority)
-static const char ListParameterfvSGIX_names[] =
+static const char ListParameterfvSGIX_names[] =
"iip\0" /* Parameter signature */
"glListParameterfvSGIX\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3dvEXT_names[] =
+static const char Tangent3dvEXT_names[] =
"p\0" /* Parameter signature */
"glTangent3dvEXT\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char GetVertexAttribfvNV_names[] =
+static const char GetVertexAttribfvNV_names[] =
"iip\0" /* Parameter signature */
"glGetVertexAttribfvNV\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos3sMESA_names[] =
+static const char WindowPos3sMESA_names[] =
"iii\0" /* Parameter signature */
"glWindowPos3s\0"
"glWindowPos3sARB\0"
@@ -2690,35 +2788,35 @@ static const char WindowPos3sMESA_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib2svNV_names[] =
+static const char VertexAttrib2svNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib2svNV\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs1fvNV_names[] =
+static const char VertexAttribs1fvNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs1fvNV\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fVertex3fvSUN_names[] =
+static const char TexCoord2fVertex3fvSUN_names[] =
"pp\0" /* Parameter signature */
"glTexCoord2fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_MESA_window_pos)
-static const char WindowPos4sMESA_names[] =
+static const char WindowPos4sMESA_names[] =
"iiii\0" /* Parameter signature */
"glWindowPos4sMESA\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4NuivARB_names[] =
+static const char VertexAttrib4NuivARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4Nuiv\0"
"glVertexAttrib4NuivARB\0"
@@ -2726,7 +2824,7 @@ static const char VertexAttrib4NuivARB_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char ClientActiveTextureARB_names[] =
+static const char ClientActiveTextureARB_names[] =
"i\0" /* Parameter signature */
"glClientActiveTexture\0"
"glClientActiveTextureARB\0"
@@ -2734,51 +2832,58 @@ static const char ClientActiveTextureARB_names[] =
#endif
#if defined(need_GL_SGIX_pixel_texture)
-static const char PixelTexGenSGIX_names[] =
+static const char PixelTexGenSGIX_names[] =
"i\0" /* Parameter signature */
"glPixelTexGenSGIX\0"
"";
#endif
#if defined(need_GL_SUN_triangle_list)
-static const char ReplacementCodeusvSUN_names[] =
+static const char ReplacementCodeusvSUN_names[] =
"p\0" /* Parameter signature */
"glReplacementCodeusvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform4fARB_names[] =
+static const char Uniform4fARB_names[] =
"iffff\0" /* Parameter signature */
"glUniform4f\0"
"glUniform4fARB\0"
"";
#endif
-#if defined(need_GL_IBM_multimode_draw_arrays)
-static const char MultiModeDrawArraysIBM_names[] =
- "pppii\0" /* Parameter signature */
- "glMultiModeDrawArraysIBM\0"
+#if defined(need_GL_ARB_map_buffer_range)
+static const char FlushMappedBufferRange_names[] =
+ "iii\0" /* Parameter signature */
+ "glFlushMappedBufferRange\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
-static const char IsProgramNV_names[] =
+static const char IsProgramNV_names[] =
"i\0" /* Parameter signature */
"glIsProgramARB\0"
"glIsProgramNV\0"
"";
#endif
+#if defined(need_GL_APPLE_flush_buffer_range)
+static const char FlushMappedBufferRangeAPPLE_names[] =
+ "iii\0" /* Parameter signature */
+ "glFlushMappedBufferRangeAPPLE\0"
+ "";
+#endif
+
#if defined(need_GL_SUN_triangle_list)
-static const char ReplacementCodePointerSUN_names[] =
+static const char ReplacementCodePointerSUN_names[] =
"iip\0" /* Parameter signature */
"glReplacementCodePointerSUN\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
-static const char ProgramEnvParameter4dARB_names[] =
+static const char ProgramEnvParameter4dARB_names[] =
"iidddd\0" /* Parameter signature */
"glProgramEnvParameter4dARB\0"
"glProgramParameter4dNV\0"
@@ -2786,7 +2891,7 @@ static const char ProgramEnvParameter4dARB_names[] =
#endif
#if defined(need_GL_SGI_color_table)
-static const char ColorTableParameterfv_names[] =
+static const char ColorTableParameterfv_names[] =
"iip\0" /* Parameter signature */
"glColorTableParameterfv\0"
"glColorTableParameterfvSGI\0"
@@ -2794,21 +2899,21 @@ static const char ColorTableParameterfv_names[] =
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentLightModelfSGIX_names[] =
+static const char FragmentLightModelfSGIX_names[] =
"if\0" /* Parameter signature */
"glFragmentLightModelfSGIX\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3bvEXT_names[] =
+static const char Binormal3bvEXT_names[] =
"p\0" /* Parameter signature */
"glBinormal3bvEXT\0"
"";
#endif
#if defined(need_GL_EXT_texture_object)
-static const char IsTexture_names[] =
+static const char IsTexture_names[] =
"i\0" /* Parameter signature */
"glIsTexture\0"
"glIsTextureEXT\0"
@@ -2816,14 +2921,14 @@ static const char IsTexture_names[] =
#endif
#if defined(need_GL_EXT_vertex_weighting)
-static const char VertexWeightfvEXT_names[] =
+static const char VertexWeightfvEXT_names[] =
"p\0" /* Parameter signature */
"glVertexWeightfvEXT\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib1dARB_names[] =
+static const char VertexAttrib1dARB_names[] =
"id\0" /* Parameter signature */
"glVertexAttrib1d\0"
"glVertexAttrib1dARB\0"
@@ -2831,14 +2936,14 @@ static const char VertexAttrib1dARB_names[] =
#endif
#if defined(need_GL_HP_image_transform)
-static const char ImageTransformParameterivHP_names[] =
+static const char ImageTransformParameterivHP_names[] =
"iip\0" /* Parameter signature */
"glImageTransformParameterivHP\0"
"";
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
-static const char DeleteQueriesARB_names[] =
+static const char DeleteQueriesARB_names[] =
"ip\0" /* Parameter signature */
"glDeleteQueries\0"
"glDeleteQueriesARB\0"
@@ -2846,28 +2951,28 @@ static const char DeleteQueriesARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char Color4ubVertex2fSUN_names[] =
+static const char Color4ubVertex2fSUN_names[] =
"iiiiff\0" /* Parameter signature */
"glColor4ubVertex2fSUN\0"
"";
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentColorMaterialSGIX_names[] =
+static const char FragmentColorMaterialSGIX_names[] =
"ii\0" /* Parameter signature */
"glFragmentColorMaterialSGIX\0"
"";
#endif
#if defined(need_GL_ARB_matrix_palette)
-static const char CurrentPaletteMatrixARB_names[] =
+static const char CurrentPaletteMatrixARB_names[] =
"i\0" /* Parameter signature */
"glCurrentPaletteMatrixARB\0"
"";
#endif
#if defined(need_GL_SGIS_multisample) || defined(need_GL_EXT_multisample)
-static const char SamplePatternSGIS_names[] =
+static const char SamplePatternSGIS_names[] =
"i\0" /* Parameter signature */
"glSamplePatternSGIS\0"
"glSamplePatternEXT\0"
@@ -2875,7 +2980,7 @@ static const char SamplePatternSGIS_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
-static const char IsQueryARB_names[] =
+static const char IsQueryARB_names[] =
"i\0" /* Parameter signature */
"glIsQuery\0"
"glIsQueryARB\0"
@@ -2883,14 +2988,14 @@ static const char IsQueryARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiColor4ubVertex3fSUN_names[] =
+static const char ReplacementCodeuiColor4ubVertex3fSUN_names[] =
"iiiiifff\0" /* Parameter signature */
"glReplacementCodeuiColor4ubVertex3fSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4usvARB_names[] =
+static const char VertexAttrib4usvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4usv\0"
"glVertexAttrib4usvARB\0"
@@ -2898,7 +3003,7 @@ static const char VertexAttrib4usvARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char LinkProgramARB_names[] =
+static const char LinkProgramARB_names[] =
"i\0" /* Parameter signature */
"glLinkProgram\0"
"glLinkProgramARB\0"
@@ -2906,14 +3011,14 @@ static const char LinkProgramARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib2fNV_names[] =
+static const char VertexAttrib2fNV_names[] =
"iff\0" /* Parameter signature */
"glVertexAttrib2fNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char ShaderSourceARB_names[] =
+static const char ShaderSourceARB_names[] =
"iipp\0" /* Parameter signature */
"glShaderSource\0"
"glShaderSourceARB\0"
@@ -2921,14 +3026,14 @@ static const char ShaderSourceARB_names[] =
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentMaterialiSGIX_names[] =
+static const char FragmentMaterialiSGIX_names[] =
"iii\0" /* Parameter signature */
"glFragmentMaterialiSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib3svARB_names[] =
+static const char VertexAttrib3svARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib3sv\0"
"glVertexAttrib3svARB\0"
@@ -2936,7 +3041,7 @@ static const char VertexAttrib3svARB_names[] =
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
-static const char CompressedTexSubImage3DARB_names[] =
+static const char CompressedTexSubImage3DARB_names[] =
"iiiiiiiiiip\0" /* Parameter signature */
"glCompressedTexSubImage3D\0"
"glCompressedTexSubImage3DARB\0"
@@ -2944,7 +3049,7 @@ static const char CompressedTexSubImage3DARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos2ivMESA_names[] =
+static const char WindowPos2ivMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos2iv\0"
"glWindowPos2ivARB\0"
@@ -2952,15 +3057,16 @@ static const char WindowPos2ivMESA_names[] =
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char IsFramebufferEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char IsFramebufferEXT_names[] =
"i\0" /* Parameter signature */
+ "glIsFramebuffer\0"
"glIsFramebufferEXT\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform4ivARB_names[] =
+static const char Uniform4ivARB_names[] =
"iip\0" /* Parameter signature */
"glUniform4iv\0"
"glUniform4ivARB\0"
@@ -2968,15 +3074,22 @@ static const char Uniform4ivARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char GetVertexAttribdvARB_names[] =
+static const char GetVertexAttribdvARB_names[] =
"iip\0" /* Parameter signature */
"glGetVertexAttribdv\0"
"glGetVertexAttribdvARB\0"
"";
#endif
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const char TexBumpParameterivATI_names[] =
+ "ip\0" /* Parameter signature */
+ "glTexBumpParameterivATI\0"
+ "";
+#endif
+
#if defined(need_GL_EXT_convolution)
-static const char GetSeparableFilter_names[] =
+static const char GetSeparableFilter_names[] =
"iiippp\0" /* Parameter signature */
"glGetSeparableFilter\0"
"glGetSeparableFilterEXT\0"
@@ -2984,49 +3097,49 @@ static const char GetSeparableFilter_names[] =
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3dEXT_names[] =
+static const char Binormal3dEXT_names[] =
"ddd\0" /* Parameter signature */
"glBinormal3dEXT\0"
"";
#endif
#if defined(need_GL_SGIX_sprite)
-static const char SpriteParameteriSGIX_names[] =
+static const char SpriteParameteriSGIX_names[] =
"ii\0" /* Parameter signature */
"glSpriteParameteriSGIX\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char RequestResidentProgramsNV_names[] =
+static const char RequestResidentProgramsNV_names[] =
"ip\0" /* Parameter signature */
"glRequestResidentProgramsNV\0"
"";
#endif
#if defined(need_GL_SGIX_tag_sample_buffer)
-static const char TagSampleBufferSGIX_names[] =
+static const char TagSampleBufferSGIX_names[] =
"\0" /* Parameter signature */
"glTagSampleBufferSGIX\0"
"";
#endif
#if defined(need_GL_SUN_triangle_list)
-static const char ReplacementCodeusSUN_names[] =
+static const char ReplacementCodeusSUN_names[] =
"i\0" /* Parameter signature */
"glReplacementCodeusSUN\0"
"";
#endif
#if defined(need_GL_SGIX_list_priority)
-static const char ListParameterivSGIX_names[] =
+static const char ListParameterivSGIX_names[] =
"iip\0" /* Parameter signature */
"glListParameterivSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_multi_draw_arrays)
-static const char MultiDrawElementsEXT_names[] =
+static const char MultiDrawElementsEXT_names[] =
"ipipi\0" /* Parameter signature */
"glMultiDrawElements\0"
"glMultiDrawElementsEXT\0"
@@ -3034,7 +3147,7 @@ static const char MultiDrawElementsEXT_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform1ivARB_names[] =
+static const char Uniform1ivARB_names[] =
"iip\0" /* Parameter signature */
"glUniform1iv\0"
"glUniform1ivARB\0"
@@ -3042,7 +3155,7 @@ static const char Uniform1ivARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos2sMESA_names[] =
+static const char WindowPos2sMESA_names[] =
"ii\0" /* Parameter signature */
"glWindowPos2s\0"
"glWindowPos2sARB\0"
@@ -3051,14 +3164,14 @@ static const char WindowPos2sMESA_names[] =
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char WeightusvARB_names[] =
+static const char WeightusvARB_names[] =
"ip\0" /* Parameter signature */
"glWeightusvARB\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
-static const char FogCoordPointerEXT_names[] =
+static const char FogCoordPointerEXT_names[] =
"iip\0" /* Parameter signature */
"glFogCoordPointer\0"
"glFogCoordPointerEXT\0"
@@ -3066,14 +3179,14 @@ static const char FogCoordPointerEXT_names[] =
#endif
#if defined(need_GL_EXT_index_material)
-static const char IndexMaterialEXT_names[] =
+static const char IndexMaterialEXT_names[] =
"ii\0" /* Parameter signature */
"glIndexMaterialEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3ubvEXT_names[] =
+static const char SecondaryColor3ubvEXT_names[] =
"p\0" /* Parameter signature */
"glSecondaryColor3ubv\0"
"glSecondaryColor3ubvEXT\0"
@@ -3081,7 +3194,7 @@ static const char SecondaryColor3ubvEXT_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4dvARB_names[] =
+static const char VertexAttrib4dvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4dv\0"
"glVertexAttrib4dvARB\0"
@@ -3089,7 +3202,7 @@ static const char VertexAttrib4dvARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_shader)
-static const char BindAttribLocationARB_names[] =
+static const char BindAttribLocationARB_names[] =
"iip\0" /* Parameter signature */
"glBindAttribLocation\0"
"glBindAttribLocationARB\0"
@@ -3097,7 +3210,7 @@ static const char BindAttribLocationARB_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord2dARB_names[] =
+static const char MultiTexCoord2dARB_names[] =
"idd\0" /* Parameter signature */
"glMultiTexCoord2d\0"
"glMultiTexCoord2dARB\0"
@@ -3105,49 +3218,50 @@ static const char MultiTexCoord2dARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char ExecuteProgramNV_names[] =
+static const char ExecuteProgramNV_names[] =
"iip\0" /* Parameter signature */
"glExecuteProgramNV\0"
"";
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char LightEnviSGIX_names[] =
+static const char LightEnviSGIX_names[] =
"ii\0" /* Parameter signature */
"glLightEnviSGIX\0"
"";
#endif
#if defined(need_GL_SUN_triangle_list)
-static const char ReplacementCodeuiSUN_names[] =
+static const char ReplacementCodeuiSUN_names[] =
"i\0" /* Parameter signature */
"glReplacementCodeuiSUN\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char FramebufferTexture2DEXT_names[] =
- "iiiii\0" /* Parameter signature */
- "glFramebufferTexture2DEXT\0"
- "";
-#endif
-
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribPointerNV_names[] =
+static const char VertexAttribPointerNV_names[] =
"iiiip\0" /* Parameter signature */
"glVertexAttribPointerNV\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char GetFramebufferAttachmentParameterivEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GetFramebufferAttachmentParameterivEXT_names[] =
"iiip\0" /* Parameter signature */
+ "glGetFramebufferAttachmentParameteriv\0"
"glGetFramebufferAttachmentParameterivEXT\0"
"";
#endif
+#if defined(need_GL_EXT_pixel_transform)
+static const char PixelTransformParameterfEXT_names[] =
+ "iif\0" /* Parameter signature */
+ "glPixelTransformParameterfEXT\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord4dvARB_names[] =
+static const char MultiTexCoord4dvARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord4dv\0"
"glMultiTexCoord4dvARB\0"
@@ -3155,21 +3269,21 @@ static const char MultiTexCoord4dvARB_names[] =
#endif
#if defined(need_GL_EXT_pixel_transform)
-static const char PixelTransformParameteriEXT_names[] =
+static const char PixelTransformParameteriEXT_names[] =
"iii\0" /* Parameter signature */
"glPixelTransformParameteriEXT\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fColor4ubVertex3fSUN_names[] =
+static const char TexCoord2fColor4ubVertex3fSUN_names[] =
"ffiiiifff\0" /* Parameter signature */
"glTexCoord2fColor4ubVertex3fSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform1iARB_names[] =
+static const char Uniform1iARB_names[] =
"ii\0" /* Parameter signature */
"glUniform1i\0"
"glUniform1iARB\0"
@@ -3177,7 +3291,7 @@ static const char Uniform1iARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttribPointerARB_names[] =
+static const char VertexAttribPointerARB_names[] =
"iiiiip\0" /* Parameter signature */
"glVertexAttribPointer\0"
"glVertexAttribPointerARB\0"
@@ -3185,14 +3299,14 @@ static const char VertexAttribPointerARB_names[] =
#endif
#if defined(need_GL_SGIS_sharpen_texture)
-static const char SharpenTexFuncSGIS_names[] =
+static const char SharpenTexFuncSGIS_names[] =
"iip\0" /* Parameter signature */
"glSharpenTexFuncSGIS\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord4fvARB_names[] =
+static const char MultiTexCoord4fvARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord4fv\0"
"glMultiTexCoord4fvARB\0"
@@ -3200,56 +3314,56 @@ static const char MultiTexCoord4fvARB_names[] =
#endif
#if defined(need_GL_VERSION_2_1)
-static const char UniformMatrix2x3fv_names[] =
+static const char UniformMatrix2x3fv_names[] =
"iiip\0" /* Parameter signature */
"glUniformMatrix2x3fv\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char TrackMatrixNV_names[] =
+static const char TrackMatrixNV_names[] =
"iiii\0" /* Parameter signature */
"glTrackMatrixNV\0"
"";
#endif
#if defined(need_GL_NV_register_combiners)
-static const char CombinerParameteriNV_names[] =
+static const char CombinerParameteriNV_names[] =
"ii\0" /* Parameter signature */
"glCombinerParameteriNV\0"
"";
#endif
#if defined(need_GL_SGIX_async)
-static const char DeleteAsyncMarkersSGIX_names[] =
+static const char DeleteAsyncMarkersSGIX_names[] =
"ii\0" /* Parameter signature */
"glDeleteAsyncMarkersSGIX\0"
"";
#endif
#if defined(need_GL_SGIX_async)
-static const char IsAsyncMarkerSGIX_names[] =
+static const char IsAsyncMarkerSGIX_names[] =
"i\0" /* Parameter signature */
"glIsAsyncMarkerSGIX\0"
"";
#endif
#if defined(need_GL_SGIX_framezoom)
-static const char FrameZoomSGIX_names[] =
+static const char FrameZoomSGIX_names[] =
"i\0" /* Parameter signature */
"glFrameZoomSGIX\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char Normal3fVertex3fvSUN_names[] =
+static const char Normal3fVertex3fvSUN_names[] =
"pp\0" /* Parameter signature */
"glNormal3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4NsvARB_names[] =
+static const char VertexAttrib4NsvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4Nsv\0"
"glVertexAttrib4NsvARB\0"
@@ -3257,29 +3371,37 @@ static const char VertexAttrib4NsvARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib3fvARB_names[] =
+static const char VertexAttrib3fvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib3fv\0"
"glVertexAttrib3fvARB\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char DeleteFramebuffersEXT_names[] =
+#if defined(need_GL_ARB_sync)
+static const char GetSynciv_names[] =
+ "iiipp\0" /* Parameter signature */
+ "glGetSynciv\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char DeleteFramebuffersEXT_names[] =
"ip\0" /* Parameter signature */
+ "glDeleteFramebuffers\0"
"glDeleteFramebuffersEXT\0"
"";
#endif
#if defined(need_GL_SUN_global_alpha)
-static const char GlobalAlphaFactorsSUN_names[] =
+static const char GlobalAlphaFactorsSUN_names[] =
"i\0" /* Parameter signature */
"glGlobalAlphaFactorsSUN\0"
"";
#endif
#if defined(need_GL_EXT_texture3D)
-static const char TexSubImage3D_names[] =
+static const char TexSubImage3D_names[] =
"iiiiiiiiiip\0" /* Parameter signature */
"glTexSubImage3D\0"
"glTexSubImage3DEXT\0"
@@ -3287,14 +3409,14 @@ static const char TexSubImage3D_names[] =
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3fEXT_names[] =
+static const char Tangent3fEXT_names[] =
"fff\0" /* Parameter signature */
"glTangent3fEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3uivEXT_names[] =
+static const char SecondaryColor3uivEXT_names[] =
"p\0" /* Parameter signature */
"glSecondaryColor3uiv\0"
"glSecondaryColor3uivEXT\0"
@@ -3302,35 +3424,35 @@ static const char SecondaryColor3uivEXT_names[] =
#endif
#if defined(need_GL_ARB_matrix_palette)
-static const char MatrixIndexubvARB_names[] =
+static const char MatrixIndexubvARB_names[] =
"ip\0" /* Parameter signature */
"glMatrixIndexubvARB\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char Color4fNormal3fVertex3fSUN_names[] =
+static const char Color4fNormal3fVertex3fSUN_names[] =
"ffffffffff\0" /* Parameter signature */
"glColor4fNormal3fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_SGIS_pixel_texture)
-static const char PixelTexGenParameterfSGIS_names[] =
+static const char PixelTexGenParameterfSGIS_names[] =
"if\0" /* Parameter signature */
"glPixelTexGenParameterfSGIS\0"
"";
#endif
#if defined(need_GL_VERSION_2_0)
-static const char CreateShader_names[] =
+static const char CreateShader_names[] =
"i\0" /* Parameter signature */
"glCreateShader\0"
"";
#endif
#if defined(need_GL_SGI_color_table) || defined(need_GL_EXT_paletted_texture)
-static const char GetColorTableParameterfv_names[] =
+static const char GetColorTableParameterfv_names[] =
"iip\0" /* Parameter signature */
"glGetColorTableParameterfv\0"
"glGetColorTableParameterfvSGI\0"
@@ -3339,14 +3461,14 @@ static const char GetColorTableParameterfv_names[] =
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentLightModelfvSGIX_names[] =
+static const char FragmentLightModelfvSGIX_names[] =
"ip\0" /* Parameter signature */
"glFragmentLightModelfvSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord3fARB_names[] =
+static const char MultiTexCoord3fARB_names[] =
"ifff\0" /* Parameter signature */
"glMultiTexCoord3f\0"
"glMultiTexCoord3fARB\0"
@@ -3354,49 +3476,51 @@ static const char MultiTexCoord3fARB_names[] =
#endif
#if defined(need_GL_SGIS_pixel_texture)
-static const char GetPixelTexGenParameterfvSGIS_names[] =
+static const char GetPixelTexGenParameterfvSGIS_names[] =
"ip\0" /* Parameter signature */
"glGetPixelTexGenParameterfvSGIS\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char GenFramebuffersEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GenFramebuffersEXT_names[] =
"ip\0" /* Parameter signature */
+ "glGenFramebuffers\0"
"glGenFramebuffersEXT\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char GetProgramParameterdvNV_names[] =
+static const char GetProgramParameterdvNV_names[] =
"iiip\0" /* Parameter signature */
"glGetProgramParameterdvNV\0"
"";
#endif
-#if defined(need_GL_EXT_pixel_transform)
-static const char PixelTransformParameterfEXT_names[] =
- "iif\0" /* Parameter signature */
- "glPixelTransformParameterfEXT\0"
+#if defined(need_GL_ARB_vertex_array_object) || defined(need_GL_APPLE_vertex_array_object)
+static const char IsVertexArrayAPPLE_names[] =
+ "i\0" /* Parameter signature */
+ "glIsVertexArray\0"
+ "glIsVertexArrayAPPLE\0"
"";
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentLightfvSGIX_names[] =
+static const char FragmentLightfvSGIX_names[] =
"iip\0" /* Parameter signature */
"glFragmentLightfvSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_2_0)
-static const char DetachShader_names[] =
+static const char DetachShader_names[] =
"ii\0" /* Parameter signature */
"glDetachShader\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4NubARB_names[] =
+static const char VertexAttrib4NubARB_names[] =
"iiiii\0" /* Parameter signature */
"glVertexAttrib4Nub\0"
"glVertexAttrib4NubARB\0"
@@ -3404,28 +3528,28 @@ static const char VertexAttrib4NubARB_names[] =
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char GetProgramEnvParameterfvARB_names[] =
+static const char GetProgramEnvParameterfvARB_names[] =
"iip\0" /* Parameter signature */
"glGetProgramEnvParameterfvARB\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char GetTrackMatrixivNV_names[] =
+static const char GetTrackMatrixivNV_names[] =
"iiip\0" /* Parameter signature */
"glGetTrackMatrixivNV\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib3svNV_names[] =
+static const char VertexAttrib3svNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib3svNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform4fvARB_names[] =
+static const char Uniform4fvARB_names[] =
"iip\0" /* Parameter signature */
"glUniform4fv\0"
"glUniform4fvARB\0"
@@ -3433,7 +3557,7 @@ static const char Uniform4fvARB_names[] =
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_transpose_matrix)
-static const char MultTransposeMatrixfARB_names[] =
+static const char MultTransposeMatrixfARB_names[] =
"p\0" /* Parameter signature */
"glMultTransposeMatrixf\0"
"glMultTransposeMatrixfARB\0"
@@ -3441,14 +3565,14 @@ static const char MultTransposeMatrixfARB_names[] =
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char ColorFragmentOp1ATI_names[] =
+static const char ColorFragmentOp1ATI_names[] =
"iiiiiii\0" /* Parameter signature */
"glColorFragmentOp1ATI\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char GetUniformfvARB_names[] =
+static const char GetUniformfvARB_names[] =
"iip\0" /* Parameter signature */
"glGetUniformfv\0"
"glGetUniformfvARB\0"
@@ -3456,28 +3580,28 @@ static const char GetUniformfvARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN_names[] =
+static const char ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN_names[] =
"iffffffffffff\0" /* Parameter signature */
"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char DetachObjectARB_names[] =
+static const char DetachObjectARB_names[] =
"ii\0" /* Parameter signature */
"glDetachObjectARB\0"
"";
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char VertexBlendARB_names[] =
+static const char VertexBlendARB_names[] =
"i\0" /* Parameter signature */
"glVertexBlendARB\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos3iMESA_names[] =
+static const char WindowPos3iMESA_names[] =
"iii\0" /* Parameter signature */
"glWindowPos3i\0"
"glWindowPos3iARB\0"
@@ -3486,7 +3610,7 @@ static const char WindowPos3iMESA_names[] =
#endif
#if defined(need_GL_EXT_convolution)
-static const char SeparableFilter2D_names[] =
+static const char SeparableFilter2D_names[] =
"iiiiiipp\0" /* Parameter signature */
"glSeparableFilter2D\0"
"glSeparableFilter2DEXT\0"
@@ -3494,14 +3618,14 @@ static const char SeparableFilter2D_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiColor4ubVertex3fvSUN_names[] =
+static const char ReplacementCodeuiColor4ubVertex3fvSUN_names[] =
"ppp\0" /* Parameter signature */
"glReplacementCodeuiColor4ubVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
-static const char CompressedTexImage2DARB_names[] =
+static const char CompressedTexImage2DARB_names[] =
"iiiiiiip\0" /* Parameter signature */
"glCompressedTexImage2D\0"
"glCompressedTexImage2DARB\0"
@@ -3509,7 +3633,7 @@ static const char CompressedTexImage2DARB_names[] =
#endif
#if defined(need_GL_EXT_vertex_array)
-static const char ArrayElement_names[] =
+static const char ArrayElement_names[] =
"i\0" /* Parameter signature */
"glArrayElement\0"
"glArrayElementEXT\0"
@@ -3517,35 +3641,35 @@ static const char ArrayElement_names[] =
#endif
#if defined(need_GL_EXT_depth_bounds_test)
-static const char DepthBoundsEXT_names[] =
+static const char DepthBoundsEXT_names[] =
"dd\0" /* Parameter signature */
"glDepthBoundsEXT\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char ProgramParameters4fvNV_names[] =
+static const char ProgramParameters4fvNV_names[] =
"iiip\0" /* Parameter signature */
"glProgramParameters4fvNV\0"
"";
#endif
#if defined(need_GL_SGIX_polynomial_ffd)
-static const char DeformationMap3fSGIX_names[] =
+static const char DeformationMap3fSGIX_names[] =
"iffiiffiiffiip\0" /* Parameter signature */
"glDeformationMap3fSGIX\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char GetProgramivNV_names[] =
+static const char GetProgramivNV_names[] =
"iip\0" /* Parameter signature */
"glGetProgramivNV\0"
"";
#endif
#if defined(need_GL_EXT_histogram)
-static const char GetMinmaxParameteriv_names[] =
+static const char GetMinmaxParameteriv_names[] =
"iip\0" /* Parameter signature */
"glGetMinmaxParameteriv\0"
"glGetMinmaxParameterivEXT\0"
@@ -3553,7 +3677,7 @@ static const char GetMinmaxParameteriv_names[] =
#endif
#if defined(need_GL_EXT_copy_texture)
-static const char CopyTexImage1D_names[] =
+static const char CopyTexImage1D_names[] =
"iiiiiii\0" /* Parameter signature */
"glCopyTexImage1D\0"
"glCopyTexImage1DEXT\0"
@@ -3561,42 +3685,42 @@ static const char CopyTexImage1D_names[] =
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char AlphaFragmentOp3ATI_names[] =
+static const char AlphaFragmentOp3ATI_names[] =
"iiiiiiiiiiii\0" /* Parameter signature */
"glAlphaFragmentOp3ATI\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char GetVertexAttribdvNV_names[] =
+static const char GetVertexAttribdvNV_names[] =
"iip\0" /* Parameter signature */
"glGetVertexAttribdvNV\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib3fvNV_names[] =
+static const char VertexAttrib3fvNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib3fvNV\0"
"";
#endif
#if defined(need_GL_NV_register_combiners)
-static const char GetFinalCombinerInputParameterivNV_names[] =
+static const char GetFinalCombinerInputParameterivNV_names[] =
"iip\0" /* Parameter signature */
"glGetFinalCombinerInputParameterivNV\0"
"";
#endif
#if defined(need_GL_NV_evaluators)
-static const char GetMapParameterivNV_names[] =
+static const char GetMapParameterivNV_names[] =
"iip\0" /* Parameter signature */
"glGetMapParameterivNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform4iARB_names[] =
+static const char Uniform4iARB_names[] =
"iiiii\0" /* Parameter signature */
"glUniform4i\0"
"glUniform4iARB\0"
@@ -3604,7 +3728,7 @@ static const char Uniform4iARB_names[] =
#endif
#if defined(need_GL_EXT_convolution)
-static const char ConvolutionParameteri_names[] =
+static const char ConvolutionParameteri_names[] =
"iii\0" /* Parameter signature */
"glConvolutionParameteri\0"
"glConvolutionParameteriEXT\0"
@@ -3612,14 +3736,14 @@ static const char ConvolutionParameteri_names[] =
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3sEXT_names[] =
+static const char Binormal3sEXT_names[] =
"iii\0" /* Parameter signature */
"glBinormal3sEXT\0"
"";
#endif
#if defined(need_GL_EXT_convolution)
-static const char ConvolutionParameterf_names[] =
+static const char ConvolutionParameterf_names[] =
"iif\0" /* Parameter signature */
"glConvolutionParameterf\0"
"glConvolutionParameterfEXT\0"
@@ -3627,7 +3751,7 @@ static const char ConvolutionParameterf_names[] =
#endif
#if defined(need_GL_SGI_color_table) || defined(need_GL_EXT_paletted_texture)
-static const char GetColorTableParameteriv_names[] =
+static const char GetColorTableParameteriv_names[] =
"iip\0" /* Parameter signature */
"glGetColorTableParameteriv\0"
"glGetColorTableParameterivSGI\0"
@@ -3636,7 +3760,7 @@ static const char GetColorTableParameteriv_names[] =
#endif
#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
-static const char ProgramEnvParameter4dvARB_names[] =
+static const char ProgramEnvParameter4dvARB_names[] =
"iip\0" /* Parameter signature */
"glProgramEnvParameter4dvARB\0"
"glProgramParameter4dvNV\0"
@@ -3644,14 +3768,14 @@ static const char ProgramEnvParameter4dvARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs2fvNV_names[] =
+static const char VertexAttribs2fvNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs2fvNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char UseProgramObjectARB_names[] =
+static const char UseProgramObjectARB_names[] =
"i\0" /* Parameter signature */
"glUseProgram\0"
"glUseProgramObjectARB\0"
@@ -3659,42 +3783,42 @@ static const char UseProgramObjectARB_names[] =
#endif
#if defined(need_GL_NV_evaluators)
-static const char GetMapParameterfvNV_names[] =
+static const char GetMapParameterfvNV_names[] =
"iip\0" /* Parameter signature */
"glGetMapParameterfvNV\0"
"";
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char PassTexCoordATI_names[] =
+static const char PassTexCoordATI_names[] =
"iii\0" /* Parameter signature */
"glPassTexCoordATI\0"
"";
#endif
#if defined(need_GL_VERSION_2_0)
-static const char DeleteProgram_names[] =
+static const char DeleteProgram_names[] =
"i\0" /* Parameter signature */
"glDeleteProgram\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3ivEXT_names[] =
+static const char Tangent3ivEXT_names[] =
"p\0" /* Parameter signature */
"glTangent3ivEXT\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3dEXT_names[] =
+static const char Tangent3dEXT_names[] =
"ddd\0" /* Parameter signature */
"glTangent3dEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3dvEXT_names[] =
+static const char SecondaryColor3dvEXT_names[] =
"p\0" /* Parameter signature */
"glSecondaryColor3dv\0"
"glSecondaryColor3dvEXT\0"
@@ -3702,22 +3826,23 @@ static const char SecondaryColor3dvEXT_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_multi_draw_arrays)
-static const char MultiDrawArraysEXT_names[] =
+static const char MultiDrawArraysEXT_names[] =
"ippi\0" /* Parameter signature */
"glMultiDrawArrays\0"
"glMultiDrawArraysEXT\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char BindRenderbufferEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char BindRenderbufferEXT_names[] =
"ii\0" /* Parameter signature */
+ "glBindRenderbuffer\0"
"glBindRenderbufferEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord4dARB_names[] =
+static const char MultiTexCoord4dARB_names[] =
"idddd\0" /* Parameter signature */
"glMultiTexCoord4d\0"
"glMultiTexCoord4dARB\0"
@@ -3725,7 +3850,7 @@ static const char MultiTexCoord4dARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3usEXT_names[] =
+static const char SecondaryColor3usEXT_names[] =
"iii\0" /* Parameter signature */
"glSecondaryColor3us\0"
"glSecondaryColor3usEXT\0"
@@ -3733,14 +3858,14 @@ static const char SecondaryColor3usEXT_names[] =
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char ProgramLocalParameter4fvARB_names[] =
+static const char ProgramLocalParameter4fvARB_names[] =
"iip\0" /* Parameter signature */
"glProgramLocalParameter4fvARB\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
-static const char DeleteProgramsNV_names[] =
+static const char DeleteProgramsNV_names[] =
"ip\0" /* Parameter signature */
"glDeleteProgramsARB\0"
"glDeleteProgramsNV\0"
@@ -3748,7 +3873,7 @@ static const char DeleteProgramsNV_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord1sARB_names[] =
+static const char MultiTexCoord1sARB_names[] =
"ii\0" /* Parameter signature */
"glMultiTexCoord1s\0"
"glMultiTexCoord1sARB\0"
@@ -3756,14 +3881,14 @@ static const char MultiTexCoord1sARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiColor3fVertex3fSUN_names[] =
+static const char ReplacementCodeuiColor3fVertex3fSUN_names[] =
"iffffff\0" /* Parameter signature */
"glReplacementCodeuiColor3fVertex3fSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
-static const char GetVertexAttribPointervNV_names[] =
+static const char GetVertexAttribPointervNV_names[] =
"iip\0" /* Parameter signature */
"glGetVertexAttribPointerv\0"
"glGetVertexAttribPointervARB\0"
@@ -3772,7 +3897,7 @@ static const char GetVertexAttribPointervNV_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord1dvARB_names[] =
+static const char MultiTexCoord1dvARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord1dv\0"
"glMultiTexCoord1dvARB\0"
@@ -3780,7 +3905,7 @@ static const char MultiTexCoord1dvARB_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform2iARB_names[] =
+static const char Uniform2iARB_names[] =
"iii\0" /* Parameter signature */
"glUniform2i\0"
"glUniform2iARB\0"
@@ -3788,57 +3913,64 @@ static const char Uniform2iARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char GetProgramStringNV_names[] =
+static const char GetProgramStringNV_names[] =
"iip\0" /* Parameter signature */
"glGetProgramStringNV\0"
"";
#endif
#if defined(need_GL_EXT_vertex_array)
-static const char ColorPointerEXT_names[] =
+static const char ColorPointerEXT_names[] =
"iiiip\0" /* Parameter signature */
"glColorPointerEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char MapBufferARB_names[] =
+static const char MapBufferARB_names[] =
"ii\0" /* Parameter signature */
"glMapBuffer\0"
"glMapBufferARB\0"
"";
#endif
+#if defined(need_GL_ARB_draw_elements_base_vertex)
+static const char MultiDrawElementsBaseVertex_names[] =
+ "ipipip\0" /* Parameter signature */
+ "glMultiDrawElementsBaseVertex\0"
+ "";
+#endif
+
#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3svEXT_names[] =
+static const char Binormal3svEXT_names[] =
"p\0" /* Parameter signature */
"glBinormal3svEXT\0"
"";
#endif
#if defined(need_GL_EXT_light_texture)
-static const char ApplyTextureEXT_names[] =
+static const char ApplyTextureEXT_names[] =
"i\0" /* Parameter signature */
"glApplyTextureEXT\0"
"";
#endif
#if defined(need_GL_EXT_light_texture)
-static const char TextureMaterialEXT_names[] =
+static const char TextureMaterialEXT_names[] =
"ii\0" /* Parameter signature */
"glTextureMaterialEXT\0"
"";
#endif
#if defined(need_GL_EXT_light_texture)
-static const char TextureLightEXT_names[] =
+static const char TextureLightEXT_names[] =
"i\0" /* Parameter signature */
"glTextureLightEXT\0"
"";
#endif
#if defined(need_GL_EXT_histogram)
-static const char ResetMinmax_names[] =
+static const char ResetMinmax_names[] =
"i\0" /* Parameter signature */
"glResetMinmax\0"
"glResetMinmaxEXT\0"
@@ -3846,21 +3978,21 @@ static const char ResetMinmax_names[] =
#endif
#if defined(need_GL_SGIX_sprite)
-static const char SpriteParameterfSGIX_names[] =
+static const char SpriteParameterfSGIX_names[] =
"if\0" /* Parameter signature */
"glSpriteParameterfSGIX\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib4sNV_names[] =
+static const char VertexAttrib4sNV_names[] =
"iiiii\0" /* Parameter signature */
"glVertexAttrib4sNV\0"
"";
#endif
#if defined(need_GL_EXT_convolution)
-static const char GetConvolutionParameterfv_names[] =
+static const char GetConvolutionParameterfv_names[] =
"iip\0" /* Parameter signature */
"glGetConvolutionParameterfv\0"
"glGetConvolutionParameterfvEXT\0"
@@ -3868,36 +4000,50 @@ static const char GetConvolutionParameterfv_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs4dvNV_names[] =
+static const char VertexAttribs4dvNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs4dvNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4dARB_names[] =
+static const char VertexAttrib4dARB_names[] =
"idddd\0" /* Parameter signature */
"glVertexAttrib4d\0"
"glVertexAttrib4dARB\0"
"";
#endif
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const char GetTexBumpParameterfvATI_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetTexBumpParameterfvATI\0"
+ "";
+#endif
+
#if defined(need_GL_NV_fragment_program)
-static const char ProgramNamedParameter4dNV_names[] =
+static const char ProgramNamedParameter4dNV_names[] =
"iipdddd\0" /* Parameter signature */
"glProgramNamedParameter4dNV\0"
"";
#endif
#if defined(need_GL_EXT_vertex_weighting)
-static const char VertexWeightfEXT_names[] =
+static const char VertexWeightfEXT_names[] =
"f\0" /* Parameter signature */
"glVertexWeightfEXT\0"
"";
#endif
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3fEXT_names[] =
+ "fff\0" /* Parameter signature */
+ "glBinormal3fEXT\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
-static const char FogCoordfvEXT_names[] =
+static const char FogCoordfvEXT_names[] =
"p\0" /* Parameter signature */
"glFogCoordfv\0"
"glFogCoordfvEXT\0"
@@ -3905,7 +4051,7 @@ static const char FogCoordfvEXT_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord1ivARB_names[] =
+static const char MultiTexCoord1ivARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord1iv\0"
"glMultiTexCoord1ivARB\0"
@@ -3913,7 +4059,7 @@ static const char MultiTexCoord1ivARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3ubEXT_names[] =
+static const char SecondaryColor3ubEXT_names[] =
"iii\0" /* Parameter signature */
"glSecondaryColor3ub\0"
"glSecondaryColor3ubEXT\0"
@@ -3921,7 +4067,7 @@ static const char SecondaryColor3ubEXT_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord2ivARB_names[] =
+static const char MultiTexCoord2ivARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord2iv\0"
"glMultiTexCoord2ivARB\0"
@@ -3929,14 +4075,14 @@ static const char MultiTexCoord2ivARB_names[] =
#endif
#if defined(need_GL_SGIS_fog_function)
-static const char FogFuncSGIS_names[] =
+static const char FogFuncSGIS_names[] =
"ip\0" /* Parameter signature */
"glFogFuncSGIS\0"
"";
#endif
#if defined(need_GL_EXT_copy_texture)
-static const char CopyTexSubImage2D_names[] =
+static const char CopyTexSubImage2D_names[] =
"iiiiiiii\0" /* Parameter signature */
"glCopyTexSubImage2D\0"
"glCopyTexSubImage2DEXT\0"
@@ -3944,35 +4090,35 @@ static const char CopyTexSubImage2D_names[] =
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char GetObjectParameterivARB_names[] =
+static const char GetObjectParameterivARB_names[] =
"iip\0" /* Parameter signature */
"glGetObjectParameterivARB\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord4fVertex4fSUN_names[] =
+static const char TexCoord4fVertex4fSUN_names[] =
"ffffffff\0" /* Parameter signature */
"glTexCoord4fVertex4fSUN\0"
"";
#endif
#if defined(need_GL_APPLE_vertex_array_object)
-static const char BindVertexArrayAPPLE_names[] =
+static const char BindVertexArrayAPPLE_names[] =
"i\0" /* Parameter signature */
"glBindVertexArrayAPPLE\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char GetProgramLocalParameterdvARB_names[] =
+static const char GetProgramLocalParameterdvARB_names[] =
"iip\0" /* Parameter signature */
"glGetProgramLocalParameterdvARB\0"
"";
#endif
#if defined(need_GL_EXT_histogram)
-static const char GetHistogramParameteriv_names[] =
+static const char GetHistogramParameteriv_names[] =
"iip\0" /* Parameter signature */
"glGetHistogramParameteriv\0"
"glGetHistogramParameterivEXT\0"
@@ -3980,7 +4126,7 @@ static const char GetHistogramParameteriv_names[] =
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord1iARB_names[] =
+static const char MultiTexCoord1iARB_names[] =
"ii\0" /* Parameter signature */
"glMultiTexCoord1i\0"
"glMultiTexCoord1iARB\0"
@@ -3988,7 +4134,7 @@ static const char MultiTexCoord1iARB_names[] =
#endif
#if defined(need_GL_EXT_convolution)
-static const char GetConvolutionFilter_names[] =
+static const char GetConvolutionFilter_names[] =
"iiip\0" /* Parameter signature */
"glGetConvolutionFilter\0"
"glGetConvolutionFilterEXT\0"
@@ -3996,14 +4142,14 @@ static const char GetConvolutionFilter_names[] =
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char GetProgramivARB_names[] =
+static const char GetProgramivARB_names[] =
"iip\0" /* Parameter signature */
"glGetProgramivARB\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_blend_func_separate) || defined(need_GL_INGR_blend_func_separate)
-static const char BlendFuncSeparateEXT_names[] =
+static const char BlendFuncSeparateEXT_names[] =
"iiii\0" /* Parameter signature */
"glBlendFuncSeparate\0"
"glBlendFuncSeparateEXT\0"
@@ -4011,50 +4157,50 @@ static const char BlendFuncSeparateEXT_names[] =
"";
#endif
-#if defined(need_GL_APPLE_vertex_array_object)
-static const char IsVertexArrayAPPLE_names[] =
- "i\0" /* Parameter signature */
- "glIsVertexArrayAPPLE\0"
+#if defined(need_GL_ARB_map_buffer_range)
+static const char MapBufferRange_names[] =
+ "iiii\0" /* Parameter signature */
+ "glMapBufferRange\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char ProgramParameters4dvNV_names[] =
+static const char ProgramParameters4dvNV_names[] =
"iiip\0" /* Parameter signature */
"glProgramParameters4dvNV\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord2fColor3fVertex3fvSUN_names[] =
+static const char TexCoord2fColor3fVertex3fvSUN_names[] =
"ppp\0" /* Parameter signature */
"glTexCoord2fColor3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3dvEXT_names[] =
+static const char Binormal3dvEXT_names[] =
"p\0" /* Parameter signature */
"glBinormal3dvEXT\0"
"";
#endif
#if defined(need_GL_NV_fence)
-static const char FinishFenceNV_names[] =
+static const char FinishFenceNV_names[] =
"i\0" /* Parameter signature */
"glFinishFenceNV\0"
"";
#endif
#if defined(need_GL_SGIS_fog_function)
-static const char GetFogFuncSGIS_names[] =
+static const char GetFogFuncSGIS_names[] =
"p\0" /* Parameter signature */
"glGetFogFuncSGIS\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char GetUniformLocationARB_names[] =
+static const char GetUniformLocationARB_names[] =
"ip\0" /* Parameter signature */
"glGetUniformLocation\0"
"glGetUniformLocationARB\0"
@@ -4062,7 +4208,7 @@ static const char GetUniformLocationARB_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3fEXT_names[] =
+static const char SecondaryColor3fEXT_names[] =
"fff\0" /* Parameter signature */
"glSecondaryColor3f\0"
"glSecondaryColor3fEXT\0"
@@ -4070,14 +4216,14 @@ static const char SecondaryColor3fEXT_names[] =
#endif
#if defined(need_GL_NV_register_combiners)
-static const char CombinerInputNV_names[] =
+static const char CombinerInputNV_names[] =
"iiiiii\0" /* Parameter signature */
"glCombinerInputNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib3sARB_names[] =
+static const char VertexAttrib3sARB_names[] =
"iiii\0" /* Parameter signature */
"glVertexAttrib3s\0"
"glVertexAttrib3sARB\0"
@@ -4085,49 +4231,49 @@ static const char VertexAttrib3sARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiNormal3fVertex3fvSUN_names[] =
+static const char ReplacementCodeuiNormal3fVertex3fvSUN_names[] =
"ppp\0" /* Parameter signature */
"glReplacementCodeuiNormal3fVertex3fvSUN\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char ProgramStringARB_names[] =
+static const char ProgramStringARB_names[] =
"iiip\0" /* Parameter signature */
"glProgramStringARB\0"
"";
#endif
#if defined(need_GL_SUN_vertex)
-static const char TexCoord4fVertex4fvSUN_names[] =
+static const char TexCoord4fVertex4fvSUN_names[] =
"pp\0" /* Parameter signature */
"glTexCoord4fVertex4fvSUN\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib3sNV_names[] =
+static const char VertexAttrib3sNV_names[] =
"iiii\0" /* Parameter signature */
"glVertexAttrib3sNV\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib1fNV_names[] =
+static const char VertexAttrib1fNV_names[] =
"if\0" /* Parameter signature */
"glVertexAttrib1fNV\0"
"";
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentLightfSGIX_names[] =
+static const char FragmentLightfSGIX_names[] =
"iif\0" /* Parameter signature */
"glFragmentLightfSGIX\0"
"";
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
-static const char GetCompressedTexImageARB_names[] =
+static const char GetCompressedTexImageARB_names[] =
"iip\0" /* Parameter signature */
"glGetCompressedTexImage\0"
"glGetCompressedTexImageARB\0"
@@ -4135,14 +4281,14 @@ static const char GetCompressedTexImageARB_names[] =
#endif
#if defined(need_GL_EXT_vertex_weighting)
-static const char VertexWeightPointerEXT_names[] =
+static const char VertexWeightPointerEXT_names[] =
"iiip\0" /* Parameter signature */
"glVertexWeightPointerEXT\0"
"";
#endif
#if defined(need_GL_EXT_histogram)
-static const char GetHistogram_names[] =
+static const char GetHistogram_names[] =
"iiiip\0" /* Parameter signature */
"glGetHistogram\0"
"glGetHistogramEXT\0"
@@ -4150,21 +4296,21 @@ static const char GetHistogram_names[] =
#endif
#if defined(need_GL_EXT_stencil_two_side)
-static const char ActiveStencilFaceEXT_names[] =
+static const char ActiveStencilFaceEXT_names[] =
"i\0" /* Parameter signature */
"glActiveStencilFaceEXT\0"
"";
#endif
#if defined(need_GL_ATI_separate_stencil)
-static const char StencilFuncSeparateATI_names[] =
+static const char StencilFuncSeparateATI_names[] =
"iiii\0" /* Parameter signature */
"glStencilFuncSeparateATI\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char GetShaderSourceARB_names[] =
+static const char GetShaderSourceARB_names[] =
"iipp\0" /* Parameter signature */
"glGetShaderSource\0"
"glGetShaderSourceARB\0"
@@ -4172,28 +4318,28 @@ static const char GetShaderSourceARB_names[] =
#endif
#if defined(need_GL_SGIX_igloo_interface)
-static const char IglooInterfaceSGIX_names[] =
+static const char IglooInterfaceSGIX_names[] =
"ip\0" /* Parameter signature */
"glIglooInterfaceSGIX\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib4dNV_names[] =
+static const char VertexAttrib4dNV_names[] =
"idddd\0" /* Parameter signature */
"glVertexAttrib4dNV\0"
"";
#endif
#if defined(need_GL_IBM_multimode_draw_arrays)
-static const char MultiModeDrawElementsIBM_names[] =
+static const char MultiModeDrawElementsIBM_names[] =
"ppipii\0" /* Parameter signature */
"glMultiModeDrawElementsIBM\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord4svARB_names[] =
+static const char MultiTexCoord4svARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord4sv\0"
"glMultiTexCoord4svARB\0"
@@ -4201,7 +4347,7 @@ static const char MultiTexCoord4svARB_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
-static const char GenQueriesARB_names[] =
+static const char GenQueriesARB_names[] =
"ip\0" /* Parameter signature */
"glGenQueries\0"
"glGenQueriesARB\0"
@@ -4209,35 +4355,42 @@ static const char GenQueriesARB_names[] =
#endif
#if defined(need_GL_SUN_vertex)
-static const char ReplacementCodeuiVertex3fSUN_names[] =
+static const char ReplacementCodeuiVertex3fSUN_names[] =
"ifff\0" /* Parameter signature */
"glReplacementCodeuiVertex3fSUN\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3iEXT_names[] =
+static const char Tangent3iEXT_names[] =
"iii\0" /* Parameter signature */
"glTangent3iEXT\0"
"";
#endif
#if defined(need_GL_SUN_mesh_array)
-static const char DrawMeshArraysSUN_names[] =
+static const char DrawMeshArraysSUN_names[] =
"iiii\0" /* Parameter signature */
"glDrawMeshArraysSUN\0"
"";
#endif
+#if defined(need_GL_ARB_sync)
+static const char IsSync_names[] =
+ "i\0" /* Parameter signature */
+ "glIsSync\0"
+ "";
+#endif
+
#if defined(need_GL_NV_evaluators)
-static const char GetMapControlPointsNV_names[] =
+static const char GetMapControlPointsNV_names[] =
"iiiiiip\0" /* Parameter signature */
"glGetMapControlPointsNV\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_draw_buffers) || defined(need_GL_ATI_draw_buffers)
-static const char DrawBuffersARB_names[] =
+static const char DrawBuffersARB_names[] =
"ip\0" /* Parameter signature */
"glDrawBuffers\0"
"glDrawBuffersARB\0"
@@ -4246,21 +4399,28 @@ static const char DrawBuffersARB_names[] =
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char ProgramLocalParameter4fARB_names[] =
+static const char ProgramLocalParameter4fARB_names[] =
"iiffff\0" /* Parameter signature */
"glProgramLocalParameter4fARB\0"
"";
#endif
#if defined(need_GL_SGIX_sprite)
-static const char SpriteParameterivSGIX_names[] =
+static const char SpriteParameterivSGIX_names[] =
"ip\0" /* Parameter signature */
"glSpriteParameterivSGIX\0"
"";
#endif
+#if defined(need_GL_EXT_provoking_vertex)
+static const char ProvokingVertexEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glProvokingVertexEXT\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord1fARB_names[] =
+static const char MultiTexCoord1fARB_names[] =
"if\0" /* Parameter signature */
"glMultiTexCoord1f\0"
"glMultiTexCoord1fARB\0"
@@ -4268,21 +4428,21 @@ static const char MultiTexCoord1fARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs4ubvNV_names[] =
+static const char VertexAttribs4ubvNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs4ubvNV\0"
"";
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char WeightsvARB_names[] =
+static const char WeightsvARB_names[] =
"ip\0" /* Parameter signature */
"glWeightsvARB\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
-static const char Uniform1fvARB_names[] =
+static const char Uniform1fvARB_names[] =
"iip\0" /* Parameter signature */
"glUniform1fv\0"
"glUniform1fvARB\0"
@@ -4290,7 +4450,7 @@ static const char Uniform1fvARB_names[] =
#endif
#if defined(need_GL_EXT_copy_texture)
-static const char CopyTexSubImage1D_names[] =
+static const char CopyTexSubImage1D_names[] =
"iiiiii\0" /* Parameter signature */
"glCopyTexSubImage1D\0"
"glCopyTexSubImage1DEXT\0"
@@ -4298,7 +4458,7 @@ static const char CopyTexSubImage1D_names[] =
#endif
#if defined(need_GL_EXT_texture_object)
-static const char BindTexture_names[] =
+static const char BindTexture_names[] =
"ii\0" /* Parameter signature */
"glBindTexture\0"
"glBindTextureEXT\0"
@@ -4306,14 +4466,14 @@ static const char BindTexture_names[] =
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char BeginFragmentShaderATI_names[] =
+static const char BeginFragmentShaderATI_names[] =
"\0" /* Parameter signature */
"glBeginFragmentShaderATI\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord4fARB_names[] =
+static const char MultiTexCoord4fARB_names[] =
"iffff\0" /* Parameter signature */
"glMultiTexCoord4f\0"
"glMultiTexCoord4fARB\0"
@@ -4321,21 +4481,21 @@ static const char MultiTexCoord4fARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs3svNV_names[] =
+static const char VertexAttribs3svNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs3svNV\0"
"";
#endif
#if defined(need_GL_SUN_triangle_list)
-static const char ReplacementCodeuivSUN_names[] =
+static const char ReplacementCodeuivSUN_names[] =
"p\0" /* Parameter signature */
"glReplacementCodeuivSUN\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char EnableVertexAttribArrayARB_names[] =
+static const char EnableVertexAttribArrayARB_names[] =
"i\0" /* Parameter signature */
"glEnableVertexAttribArray\0"
"glEnableVertexAttribArrayARB\0"
@@ -4343,14 +4503,14 @@ static const char EnableVertexAttribArrayARB_names[] =
#endif
#if defined(need_GL_INTEL_parallel_arrays)
-static const char NormalPointervINTEL_names[] =
+static const char NormalPointervINTEL_names[] =
"ip\0" /* Parameter signature */
"glNormalPointervINTEL\0"
"";
#endif
#if defined(need_GL_EXT_convolution)
-static const char CopyConvolutionFilter2D_names[] =
+static const char CopyConvolutionFilter2D_names[] =
"iiiiii\0" /* Parameter signature */
"glCopyConvolutionFilter2D\0"
"glCopyConvolutionFilter2DEXT\0"
@@ -4358,7 +4518,7 @@ static const char CopyConvolutionFilter2D_names[] =
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos3ivMESA_names[] =
+static const char WindowPos3ivMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos3iv\0"
"glWindowPos3ivARB\0"
@@ -4366,8 +4526,15 @@ static const char WindowPos3ivMESA_names[] =
"";
#endif
+#if defined(need_GL_ARB_copy_buffer)
+static const char CopyBufferSubData_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glCopyBufferSubData\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char IsBufferARB_names[] =
+static const char IsBufferARB_names[] =
"i\0" /* Parameter signature */
"glIsBuffer\0"
"glIsBufferARB\0"
@@ -4375,14 +4542,14 @@ static const char IsBufferARB_names[] =
#endif
#if defined(need_GL_MESA_window_pos)
-static const char WindowPos4iMESA_names[] =
+static const char WindowPos4iMESA_names[] =
"iiii\0" /* Parameter signature */
"glWindowPos4iMESA\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4uivARB_names[] =
+static const char VertexAttrib4uivARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4uiv\0"
"glVertexAttrib4uivARB\0"
@@ -4390,35 +4557,35 @@ static const char VertexAttrib4uivARB_names[] =
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3bvEXT_names[] =
+static const char Tangent3bvEXT_names[] =
"p\0" /* Parameter signature */
"glTangent3bvEXT\0"
"";
#endif
#if defined(need_GL_VERSION_2_1)
-static const char UniformMatrix3x4fv_names[] =
+static const char UniformMatrix3x4fv_names[] =
"iiip\0" /* Parameter signature */
"glUniformMatrix3x4fv\0"
"";
#endif
-#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3fvEXT_names[] =
- "p\0" /* Parameter signature */
- "glBinormal3fvEXT\0"
+#if defined(need_GL_ARB_draw_elements_base_vertex)
+static const char DrawRangeElementsBaseVertex_names[] =
+ "iiiiipi\0" /* Parameter signature */
+ "glDrawRangeElementsBaseVertex\0"
"";
#endif
#if defined(need_GL_INTEL_parallel_arrays)
-static const char TexCoordPointervINTEL_names[] =
+static const char TexCoordPointervINTEL_names[] =
"iip\0" /* Parameter signature */
"glTexCoordPointervINTEL\0"
"";
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char DeleteBuffersARB_names[] =
+static const char DeleteBuffersARB_names[] =
"ip\0" /* Parameter signature */
"glDeleteBuffers\0"
"glDeleteBuffersARB\0"
@@ -4426,21 +4593,21 @@ static const char DeleteBuffersARB_names[] =
#endif
#if defined(need_GL_MESA_window_pos)
-static const char WindowPos4fvMESA_names[] =
+static const char WindowPos4fvMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos4fvMESA\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib1sNV_names[] =
+static const char VertexAttrib1sNV_names[] =
"ii\0" /* Parameter signature */
"glVertexAttrib1sNV\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
-static const char SecondaryColor3svEXT_names[] =
+static const char SecondaryColor3svEXT_names[] =
"p\0" /* Parameter signature */
"glSecondaryColor3sv\0"
"glSecondaryColor3svEXT\0"
@@ -4448,7 +4615,7 @@ static const char SecondaryColor3svEXT_names[] =
#endif
#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_transpose_matrix)
-static const char LoadTransposeMatrixfARB_names[] =
+static const char LoadTransposeMatrixfARB_names[] =
"p\0" /* Parameter signature */
"glLoadTransposeMatrixf\0"
"glLoadTransposeMatrixfARB\0"
@@ -4456,7 +4623,7 @@ static const char LoadTransposeMatrixfARB_names[] =
#endif
#if defined(need_GL_EXT_vertex_array)
-static const char GetPointerv_names[] =
+static const char GetPointerv_names[] =
"ip\0" /* Parameter signature */
"glGetPointerv\0"
"glGetPointervEXT\0"
@@ -4464,21 +4631,21 @@ static const char GetPointerv_names[] =
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3bEXT_names[] =
+static const char Tangent3bEXT_names[] =
"iii\0" /* Parameter signature */
"glTangent3bEXT\0"
"";
#endif
#if defined(need_GL_NV_register_combiners)
-static const char CombinerParameterfNV_names[] =
+static const char CombinerParameterfNV_names[] =
"if\0" /* Parameter signature */
"glCombinerParameterfNV\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
-static const char BindProgramNV_names[] =
+static const char BindProgramNV_names[] =
"ii\0" /* Parameter signature */
"glBindProgramARB\0"
"glBindProgramNV\0"
@@ -4486,7 +4653,7 @@ static const char BindProgramNV_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4svARB_names[] =
+static const char VertexAttrib4svARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4sv\0"
"glVertexAttrib4svARB\0"
@@ -4494,28 +4661,35 @@ static const char VertexAttrib4svARB_names[] =
#endif
#if defined(need_GL_MESA_shader_debug)
-static const char CreateDebugObjectMESA_names[] =
+static const char CreateDebugObjectMESA_names[] =
"\0" /* Parameter signature */
"glCreateDebugObjectMESA\0"
"";
#endif
#if defined(need_GL_VERSION_2_0)
-static const char GetShaderiv_names[] =
+static const char GetShaderiv_names[] =
"iip\0" /* Parameter signature */
"glGetShaderiv\0"
"";
#endif
+#if defined(need_GL_ARB_sync)
+static const char ClientWaitSync_names[] =
+ "iii\0" /* Parameter signature */
+ "glClientWaitSync\0"
+ "";
+#endif
+
#if defined(need_GL_ATI_fragment_shader)
-static const char BindFragmentShaderATI_names[] =
+static const char BindFragmentShaderATI_names[] =
"i\0" /* Parameter signature */
"glBindFragmentShaderATI\0"
"";
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char UnmapBufferARB_names[] =
+static const char UnmapBufferARB_names[] =
"i\0" /* Parameter signature */
"glUnmapBuffer\0"
"glUnmapBufferARB\0"
@@ -4523,15 +4697,22 @@ static const char UnmapBufferARB_names[] =
#endif
#if defined(need_GL_EXT_histogram)
-static const char Minmax_names[] =
+static const char Minmax_names[] =
"iii\0" /* Parameter signature */
"glMinmax\0"
"glMinmaxEXT\0"
"";
#endif
+#if defined(need_GL_SGIX_polynomial_ffd)
+static const char DeformationMap3dSGIX_names[] =
+ "iddiiddiiddiip\0" /* Parameter signature */
+ "glDeformationMap3dSGIX\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
-static const char FogCoorddvEXT_names[] =
+static const char FogCoorddvEXT_names[] =
"p\0" /* Parameter signature */
"glFogCoorddv\0"
"glFogCoorddvEXT\0"
@@ -4539,35 +4720,35 @@ static const char FogCoorddvEXT_names[] =
#endif
#if defined(need_GL_SUNX_constant_data)
-static const char FinishTextureSUNX_names[] =
+static const char FinishTextureSUNX_names[] =
"\0" /* Parameter signature */
"glFinishTextureSUNX\0"
"";
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char GetFragmentLightfvSGIX_names[] =
+static const char GetFragmentLightfvSGIX_names[] =
"iip\0" /* Parameter signature */
"glGetFragmentLightfvSGIX\0"
"";
#endif
-#if defined(need_GL_NV_register_combiners)
-static const char GetFinalCombinerInputParameterfvNV_names[] =
- "iip\0" /* Parameter signature */
- "glGetFinalCombinerInputParameterfvNV\0"
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3fvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glBinormal3fvEXT\0"
"";
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char ColorFragmentOp3ATI_names[] =
+static const char ColorFragmentOp3ATI_names[] =
"iiiiiiiiiiiii\0" /* Parameter signature */
"glColorFragmentOp3ATI\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib2svARB_names[] =
+static const char VertexAttrib2svARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib2sv\0"
"glVertexAttrib2svARB\0"
@@ -4575,14 +4756,14 @@ static const char VertexAttrib2svARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char AreProgramsResidentNV_names[] =
+static const char AreProgramsResidentNV_names[] =
"ipp\0" /* Parameter signature */
"glAreProgramsResidentNV\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos3svMESA_names[] =
+static const char WindowPos3svMESA_names[] =
"p\0" /* Parameter signature */
"glWindowPos3sv\0"
"glWindowPos3svARB\0"
@@ -4591,7 +4772,7 @@ static const char WindowPos3svMESA_names[] =
#endif
#if defined(need_GL_EXT_color_subtable)
-static const char CopyColorSubTable_names[] =
+static const char CopyColorSubTable_names[] =
"iiiii\0" /* Parameter signature */
"glCopyColorSubTable\0"
"glCopyColorSubTableEXT\0"
@@ -4599,21 +4780,22 @@ static const char CopyColorSubTable_names[] =
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char WeightdvARB_names[] =
+static const char WeightdvARB_names[] =
"ip\0" /* Parameter signature */
"glWeightdvARB\0"
"";
#endif
-#if defined(need_GL_SGIX_instruments)
-static const char PollInstrumentsSGIX_names[] =
- "p\0" /* Parameter signature */
- "glPollInstrumentsSGIX\0"
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char DeleteRenderbuffersEXT_names[] =
+ "ip\0" /* Parameter signature */
+ "glDeleteRenderbuffers\0"
+ "glDeleteRenderbuffersEXT\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib4NubvARB_names[] =
+static const char VertexAttrib4NubvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4Nubv\0"
"glVertexAttrib4NubvARB\0"
@@ -4621,92 +4803,93 @@ static const char VertexAttrib4NubvARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib3dvNV_names[] =
+static const char VertexAttrib3dvNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib3dvNV\0"
"";
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char GetObjectParameterfvARB_names[] =
+static const char GetObjectParameterfvARB_names[] =
"iip\0" /* Parameter signature */
"glGetObjectParameterfvARB\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program)
-static const char GetProgramEnvParameterdvARB_names[] =
+static const char GetProgramEnvParameterdvARB_names[] =
"iip\0" /* Parameter signature */
"glGetProgramEnvParameterdvARB\0"
"";
#endif
#if defined(need_GL_EXT_compiled_vertex_array)
-static const char LockArraysEXT_names[] =
+static const char LockArraysEXT_names[] =
"ii\0" /* Parameter signature */
"glLockArraysEXT\0"
"";
#endif
#if defined(need_GL_EXT_pixel_transform)
-static const char PixelTransformParameterivEXT_names[] =
+static const char PixelTransformParameterivEXT_names[] =
"iip\0" /* Parameter signature */
"glPixelTransformParameterivEXT\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char BinormalPointerEXT_names[] =
+static const char BinormalPointerEXT_names[] =
"iip\0" /* Parameter signature */
"glBinormalPointerEXT\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib1dNV_names[] =
+static const char VertexAttrib1dNV_names[] =
"id\0" /* Parameter signature */
"glVertexAttrib1dNV\0"
"";
#endif
#if defined(need_GL_NV_register_combiners)
-static const char GetCombinerInputParameterivNV_names[] =
+static const char GetCombinerInputParameterivNV_names[] =
"iiiip\0" /* Parameter signature */
"glGetCombinerInputParameterivNV\0"
"";
#endif
#if defined(need_GL_VERSION_1_3)
-static const char MultiTexCoord2fvARB_names[] =
+static const char MultiTexCoord2fvARB_names[] =
"ip\0" /* Parameter signature */
"glMultiTexCoord2fv\0"
"glMultiTexCoord2fvARB\0"
"";
#endif
-#if defined(need_GL_EXT_framebuffer_object)
-static const char GetRenderbufferParameterivEXT_names[] =
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GetRenderbufferParameterivEXT_names[] =
"iip\0" /* Parameter signature */
+ "glGetRenderbufferParameteriv\0"
"glGetRenderbufferParameterivEXT\0"
"";
#endif
#if defined(need_GL_NV_register_combiners)
-static const char CombinerParameterivNV_names[] =
+static const char CombinerParameterivNV_names[] =
"ip\0" /* Parameter signature */
"glCombinerParameterivNV\0"
"";
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char GenFragmentShadersATI_names[] =
+static const char GenFragmentShadersATI_names[] =
"i\0" /* Parameter signature */
"glGenFragmentShadersATI\0"
"";
#endif
#if defined(need_GL_EXT_vertex_array)
-static const char DrawArrays_names[] =
+static const char DrawArrays_names[] =
"iii\0" /* Parameter signature */
"glDrawArrays\0"
"glDrawArraysEXT\0"
@@ -4714,14 +4897,14 @@ static const char DrawArrays_names[] =
#endif
#if defined(need_GL_ARB_vertex_blend)
-static const char WeightuivARB_names[] =
+static const char WeightuivARB_names[] =
"ip\0" /* Parameter signature */
"glWeightuivARB\0"
"";
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib2sARB_names[] =
+static const char VertexAttrib2sARB_names[] =
"iii\0" /* Parameter signature */
"glVertexAttrib2s\0"
"glVertexAttrib2sARB\0"
@@ -4729,21 +4912,28 @@ static const char VertexAttrib2sARB_names[] =
#endif
#if defined(need_GL_SGIX_async)
-static const char GenAsyncMarkersSGIX_names[] =
+static const char GenAsyncMarkersSGIX_names[] =
"i\0" /* Parameter signature */
"glGenAsyncMarkersSGIX\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Tangent3svEXT_names[] =
+static const char Tangent3svEXT_names[] =
"p\0" /* Parameter signature */
"glTangent3svEXT\0"
"";
#endif
+#if defined(need_GL_SGIX_list_priority)
+static const char GetListParameterivSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetListParameterivSGIX\0"
+ "";
+#endif
+
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char BindBufferARB_names[] =
+static const char BindBufferARB_names[] =
"ii\0" /* Parameter signature */
"glBindBuffer\0"
"glBindBufferARB\0"
@@ -4751,35 +4941,35 @@ static const char BindBufferARB_names[] =
#endif
#if defined(need_GL_ARB_shader_objects)
-static const char GetInfoLogARB_names[] =
+static const char GetInfoLogARB_names[] =
"iipp\0" /* Parameter signature */
"glGetInfoLogARB\0"
"";
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs4svNV_names[] =
+static const char VertexAttribs4svNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs4svNV\0"
"";
#endif
#if defined(need_GL_IBM_vertex_array_lists)
-static const char EdgeFlagPointerListIBM_names[] =
+static const char EdgeFlagPointerListIBM_names[] =
"ipi\0" /* Parameter signature */
"glEdgeFlagPointerListIBM\0"
"";
#endif
#if defined(need_GL_VERSION_2_1)
-static const char UniformMatrix3x2fv_names[] =
+static const char UniformMatrix3x2fv_names[] =
"iiip\0" /* Parameter signature */
"glUniformMatrix3x2fv\0"
"";
#endif
#if defined(need_GL_EXT_histogram)
-static const char GetMinmaxParameterfv_names[] =
+static const char GetMinmaxParameterfv_names[] =
"iip\0" /* Parameter signature */
"glGetMinmaxParameterfv\0"
"glGetMinmaxParameterfvEXT\0"
@@ -4787,7 +4977,7 @@ static const char GetMinmaxParameterfv_names[] =
#endif
#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
-static const char VertexAttrib1fvARB_names[] =
+static const char VertexAttrib1fvARB_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib1fv\0"
"glVertexAttrib1fvARB\0"
@@ -4795,7 +4985,7 @@ static const char VertexAttrib1fvARB_names[] =
#endif
#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
-static const char GenBuffersARB_names[] =
+static const char GenBuffersARB_names[] =
"ip\0" /* Parameter signature */
"glGenBuffers\0"
"glGenBuffersARB\0"
@@ -4803,35 +4993,43 @@ static const char GenBuffersARB_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttribs1svNV_names[] =
+static const char VertexAttribs1svNV_names[] =
"iip\0" /* Parameter signature */
"glVertexAttribs1svNV\0"
"";
#endif
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const char GetTexBumpParameterivATI_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetTexBumpParameterivATI\0"
+ "";
+#endif
+
#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3bEXT_names[] =
+static const char Binormal3bEXT_names[] =
"iii\0" /* Parameter signature */
"glBinormal3bEXT\0"
"";
#endif
#if defined(need_GL_SGIX_fragment_lighting)
-static const char FragmentMaterialivSGIX_names[] =
+static const char FragmentMaterialivSGIX_names[] =
"iip\0" /* Parameter signature */
"glFragmentMaterialivSGIX\0"
"";
#endif
-#if defined(need_GL_NV_vertex_array_range)
-static const char VertexArrayRangeNV_names[] =
- "ip\0" /* Parameter signature */
- "glVertexArrayRangeNV\0"
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char IsRenderbufferEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glIsRenderbuffer\0"
+ "glIsRenderbufferEXT\0"
"";
#endif
#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
-static const char GenProgramsNV_names[] =
+static const char GenProgramsNV_names[] =
"ip\0" /* Parameter signature */
"glGenProgramsARB\0"
"glGenProgramsNV\0"
@@ -4839,28 +5037,28 @@ static const char GenProgramsNV_names[] =
#endif
#if defined(need_GL_NV_vertex_program)
-static const char VertexAttrib4dvNV_names[] =
+static const char VertexAttrib4dvNV_names[] =
"ip\0" /* Parameter signature */
"glVertexAttrib4dvNV\0"
"";
#endif
#if defined(need_GL_ATI_fragment_shader)
-static const char EndFragmentShaderATI_names[] =
+static const char EndFragmentShaderATI_names[] =
"\0" /* Parameter signature */
"glEndFragmentShaderATI\0"
"";
#endif
#if defined(need_GL_EXT_coordinate_frame)
-static const char Binormal3iEXT_names[] =
+static const char Binormal3iEXT_names[] =
"iii\0" /* Parameter signature */
"glBinormal3iEXT\0"
"";
#endif
#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
-static const char WindowPos2fMESA_names[] =
+static const char WindowPos2fMESA_names[] =
"ff\0" /* Parameter signature */
"glWindowPos2f\0"
"glWindowPos2fARB\0"
@@ -4875,12 +5073,35 @@ static const struct dri_extension_function GL_3DFX_tbuffer_functions[] = {
};
#endif
+#if defined(need_GL_APPLE_flush_buffer_range)
+static const struct dri_extension_function GL_APPLE_flush_buffer_range_functions[] = {
+ { BufferParameteriAPPLE_names, BufferParameteriAPPLE_remap_index, -1 },
+ { FlushMappedBufferRangeAPPLE_names, FlushMappedBufferRangeAPPLE_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_APPLE_texture_range)
+static const struct dri_extension_function GL_APPLE_texture_range_functions[] = {
+ { TextureRangeAPPLE_names, TextureRangeAPPLE_remap_index, -1 },
+ { GetTexParameterPointervAPPLE_names, GetTexParameterPointervAPPLE_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
#if defined(need_GL_APPLE_vertex_array_object)
static const struct dri_extension_function GL_APPLE_vertex_array_object_functions[] = {
{ DeleteVertexArraysAPPLE_names, DeleteVertexArraysAPPLE_remap_index, -1 },
{ GenVertexArraysAPPLE_names, GenVertexArraysAPPLE_remap_index, -1 },
- { BindVertexArrayAPPLE_names, BindVertexArrayAPPLE_remap_index, -1 },
{ IsVertexArrayAPPLE_names, IsVertexArrayAPPLE_remap_index, -1 },
+ { BindVertexArrayAPPLE_names, BindVertexArrayAPPLE_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_copy_buffer)
+static const struct dri_extension_function GL_ARB_copy_buffer_functions[] = {
+ { CopyBufferSubData_names, CopyBufferSubData_remap_index, -1 },
{ NULL, 0, 0 }
};
#endif
@@ -4892,6 +5113,49 @@ static const struct dri_extension_function GL_ARB_draw_buffers_functions[] = {
};
#endif
+#if defined(need_GL_ARB_draw_elements_base_vertex)
+static const struct dri_extension_function GL_ARB_draw_elements_base_vertex_functions[] = {
+ { DrawElementsBaseVertex_names, DrawElementsBaseVertex_remap_index, -1 },
+ { MultiDrawElementsBaseVertex_names, MultiDrawElementsBaseVertex_remap_index, -1 },
+ { DrawRangeElementsBaseVertex_names, DrawRangeElementsBaseVertex_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object)
+static const struct dri_extension_function GL_ARB_framebuffer_object_functions[] = {
+ { BlitFramebufferEXT_names, BlitFramebufferEXT_remap_index, -1 },
+ { FramebufferTextureLayerEXT_names, FramebufferTextureLayerEXT_remap_index, -1 },
+ { GenerateMipmapEXT_names, GenerateMipmapEXT_remap_index, -1 },
+ { RenderbufferStorageEXT_names, RenderbufferStorageEXT_remap_index, -1 },
+ { CheckFramebufferStatusEXT_names, CheckFramebufferStatusEXT_remap_index, -1 },
+ { FramebufferTexture3DEXT_names, FramebufferTexture3DEXT_remap_index, -1 },
+ { FramebufferTexture2DEXT_names, FramebufferTexture2DEXT_remap_index, -1 },
+ { RenderbufferStorageMultisample_names, RenderbufferStorageMultisample_remap_index, -1 },
+ { FramebufferRenderbufferEXT_names, FramebufferRenderbufferEXT_remap_index, -1 },
+ { FramebufferTexture1DEXT_names, FramebufferTexture1DEXT_remap_index, -1 },
+ { BindFramebufferEXT_names, BindFramebufferEXT_remap_index, -1 },
+ { GenRenderbuffersEXT_names, GenRenderbuffersEXT_remap_index, -1 },
+ { IsFramebufferEXT_names, IsFramebufferEXT_remap_index, -1 },
+ { GetFramebufferAttachmentParameterivEXT_names, GetFramebufferAttachmentParameterivEXT_remap_index, -1 },
+ { DeleteFramebuffersEXT_names, DeleteFramebuffersEXT_remap_index, -1 },
+ { GenFramebuffersEXT_names, GenFramebuffersEXT_remap_index, -1 },
+ { BindRenderbufferEXT_names, BindRenderbufferEXT_remap_index, -1 },
+ { DeleteRenderbuffersEXT_names, DeleteRenderbuffersEXT_remap_index, -1 },
+ { GetRenderbufferParameterivEXT_names, GetRenderbufferParameterivEXT_remap_index, -1 },
+ { IsRenderbufferEXT_names, IsRenderbufferEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_map_buffer_range)
+static const struct dri_extension_function GL_ARB_map_buffer_range_functions[] = {
+ { FlushMappedBufferRange_names, FlushMappedBufferRange_remap_index, -1 },
+ { MapBufferRange_names, MapBufferRange_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
#if defined(need_GL_ARB_matrix_palette)
static const struct dri_extension_function GL_ARB_matrix_palette_functions[] = {
{ MatrixIndexusvARB_names, MatrixIndexusvARB_remap_index, -1 },
@@ -4977,6 +5241,19 @@ static const struct dri_extension_function GL_ARB_shader_objects_functions[] = {
};
#endif
+#if defined(need_GL_ARB_sync)
+static const struct dri_extension_function GL_ARB_sync_functions[] = {
+ { DeleteSync_names, DeleteSync_remap_index, -1 },
+ { FenceSync_names, FenceSync_remap_index, -1 },
+ { WaitSync_names, WaitSync_remap_index, -1 },
+ { GetInteger64v_names, GetInteger64v_remap_index, -1 },
+ { GetSynciv_names, GetSynciv_remap_index, -1 },
+ { IsSync_names, IsSync_remap_index, -1 },
+ { ClientWaitSync_names, ClientWaitSync_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
#if defined(need_GL_ARB_texture_compression)
static const struct dri_extension_function GL_ARB_texture_compression_functions[] = {
{ CompressedTexSubImage2DARB_names, CompressedTexSubImage2DARB_remap_index, -1 },
@@ -5000,6 +5277,16 @@ static const struct dri_extension_function GL_ARB_transpose_matrix_functions[] =
};
#endif
+#if defined(need_GL_ARB_vertex_array_object)
+static const struct dri_extension_function GL_ARB_vertex_array_object_functions[] = {
+ { DeleteVertexArraysAPPLE_names, DeleteVertexArraysAPPLE_remap_index, -1 },
+ { GenVertexArrays_names, GenVertexArrays_remap_index, -1 },
+ { BindVertexArray_names, BindVertexArray_remap_index, -1 },
+ { IsVertexArrayAPPLE_names, IsVertexArrayAPPLE_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
#if defined(need_GL_ARB_vertex_blend)
static const struct dri_extension_function GL_ARB_vertex_blend_functions[] = {
{ WeightubvARB_names, WeightubvARB_remap_index, -1 },
@@ -5146,6 +5433,16 @@ static const struct dri_extension_function GL_ATI_draw_buffers_functions[] = {
};
#endif
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const struct dri_extension_function GL_ATI_envmap_bumpmap_functions[] = {
+ { TexBumpParameterfvATI_names, TexBumpParameterfvATI_remap_index, -1 },
+ { TexBumpParameterivATI_names, TexBumpParameterivATI_remap_index, -1 },
+ { GetTexBumpParameterfvATI_names, GetTexBumpParameterfvATI_remap_index, -1 },
+ { GetTexBumpParameterivATI_names, GetTexBumpParameterivATI_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
#if defined(need_GL_ATI_fragment_shader)
static const struct dri_extension_function GL_ATI_fragment_shader_functions[] = {
{ ColorFragmentOp2ATI_names, ColorFragmentOp2ATI_remap_index, -1 },
@@ -5243,7 +5540,6 @@ static const struct dri_extension_function GL_EXT_coordinate_frame_functions[] =
{ Binormal3ivEXT_names, Binormal3ivEXT_remap_index, -1 },
{ Tangent3sEXT_names, Tangent3sEXT_remap_index, -1 },
{ Tangent3fvEXT_names, Tangent3fvEXT_remap_index, -1 },
- { Binormal3fEXT_names, Binormal3fEXT_remap_index, -1 },
{ Tangent3dvEXT_names, Tangent3dvEXT_remap_index, -1 },
{ Binormal3bvEXT_names, Binormal3bvEXT_remap_index, -1 },
{ Binormal3dEXT_names, Binormal3dEXT_remap_index, -1 },
@@ -5252,11 +5548,12 @@ static const struct dri_extension_function GL_EXT_coordinate_frame_functions[] =
{ Tangent3ivEXT_names, Tangent3ivEXT_remap_index, -1 },
{ Tangent3dEXT_names, Tangent3dEXT_remap_index, -1 },
{ Binormal3svEXT_names, Binormal3svEXT_remap_index, -1 },
+ { Binormal3fEXT_names, Binormal3fEXT_remap_index, -1 },
{ Binormal3dvEXT_names, Binormal3dvEXT_remap_index, -1 },
{ Tangent3iEXT_names, Tangent3iEXT_remap_index, -1 },
{ Tangent3bvEXT_names, Tangent3bvEXT_remap_index, -1 },
- { Binormal3fvEXT_names, Binormal3fvEXT_remap_index, -1 },
{ Tangent3bEXT_names, Tangent3bEXT_remap_index, -1 },
+ { Binormal3fvEXT_names, Binormal3fvEXT_remap_index, -1 },
{ BinormalPointerEXT_names, BinormalPointerEXT_remap_index, -1 },
{ Tangent3svEXT_names, Tangent3svEXT_remap_index, -1 },
{ Binormal3bEXT_names, Binormal3bEXT_remap_index, -1 },
@@ -5319,22 +5616,22 @@ static const struct dri_extension_function GL_EXT_framebuffer_blit_functions[] =
#if defined(need_GL_EXT_framebuffer_object)
static const struct dri_extension_function GL_EXT_framebuffer_object_functions[] = {
{ GenerateMipmapEXT_names, GenerateMipmapEXT_remap_index, -1 },
- { IsRenderbufferEXT_names, IsRenderbufferEXT_remap_index, -1 },
{ RenderbufferStorageEXT_names, RenderbufferStorageEXT_remap_index, -1 },
{ CheckFramebufferStatusEXT_names, CheckFramebufferStatusEXT_remap_index, -1 },
- { DeleteRenderbuffersEXT_names, DeleteRenderbuffersEXT_remap_index, -1 },
{ FramebufferTexture3DEXT_names, FramebufferTexture3DEXT_remap_index, -1 },
+ { FramebufferTexture2DEXT_names, FramebufferTexture2DEXT_remap_index, -1 },
{ FramebufferRenderbufferEXT_names, FramebufferRenderbufferEXT_remap_index, -1 },
{ FramebufferTexture1DEXT_names, FramebufferTexture1DEXT_remap_index, -1 },
{ BindFramebufferEXT_names, BindFramebufferEXT_remap_index, -1 },
{ GenRenderbuffersEXT_names, GenRenderbuffersEXT_remap_index, -1 },
{ IsFramebufferEXT_names, IsFramebufferEXT_remap_index, -1 },
- { FramebufferTexture2DEXT_names, FramebufferTexture2DEXT_remap_index, -1 },
{ GetFramebufferAttachmentParameterivEXT_names, GetFramebufferAttachmentParameterivEXT_remap_index, -1 },
{ DeleteFramebuffersEXT_names, DeleteFramebuffersEXT_remap_index, -1 },
{ GenFramebuffersEXT_names, GenFramebuffersEXT_remap_index, -1 },
{ BindRenderbufferEXT_names, BindRenderbufferEXT_remap_index, -1 },
+ { DeleteRenderbuffersEXT_names, DeleteRenderbuffersEXT_remap_index, -1 },
{ GetRenderbufferParameterivEXT_names, GetRenderbufferParameterivEXT_remap_index, -1 },
+ { IsRenderbufferEXT_names, IsRenderbufferEXT_remap_index, -1 },
{ NULL, 0, 0 }
};
#endif
@@ -5415,8 +5712,8 @@ static const struct dri_extension_function GL_EXT_paletted_texture_functions[] =
#if defined(need_GL_EXT_pixel_transform)
static const struct dri_extension_function GL_EXT_pixel_transform_functions[] = {
{ PixelTransformParameterfvEXT_names, PixelTransformParameterfvEXT_remap_index, -1 },
- { PixelTransformParameteriEXT_names, PixelTransformParameteriEXT_remap_index, -1 },
{ PixelTransformParameterfEXT_names, PixelTransformParameterfEXT_remap_index, -1 },
+ { PixelTransformParameteriEXT_names, PixelTransformParameteriEXT_remap_index, -1 },
{ PixelTransformParameterivEXT_names, PixelTransformParameterivEXT_remap_index, -1 },
{ NULL, 0, 0 }
};
@@ -5437,6 +5734,13 @@ static const struct dri_extension_function GL_EXT_polygon_offset_functions[] = {
};
#endif
+#if defined(need_GL_EXT_provoking_vertex)
+static const struct dri_extension_function GL_EXT_provoking_vertex_functions[] = {
+ { ProvokingVertexEXT_names, ProvokingVertexEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
#if defined(need_GL_EXT_secondary_color)
static const struct dri_extension_function GL_EXT_secondary_color_functions[] = {
{ SecondaryColor3iEXT_names, SecondaryColor3iEXT_remap_index, -1 },
@@ -5691,6 +5995,7 @@ static const struct dri_extension_function GL_NV_point_sprite_functions[] = {
static const struct dri_extension_function GL_NV_register_combiners_functions[] = {
{ CombinerOutputNV_names, CombinerOutputNV_remap_index, -1 },
{ CombinerParameterfvNV_names, CombinerParameterfvNV_remap_index, -1 },
+ { GetFinalCombinerInputParameterfvNV_names, GetFinalCombinerInputParameterfvNV_remap_index, -1 },
{ GetCombinerOutputParameterfvNV_names, GetCombinerOutputParameterfvNV_remap_index, -1 },
{ FinalCombinerInputNV_names, FinalCombinerInputNV_remap_index, -1 },
{ GetCombinerInputParameterfvNV_names, GetCombinerInputParameterfvNV_remap_index, -1 },
@@ -5699,7 +6004,6 @@ static const struct dri_extension_function GL_NV_register_combiners_functions[]
{ GetFinalCombinerInputParameterivNV_names, GetFinalCombinerInputParameterivNV_remap_index, -1 },
{ CombinerInputNV_names, CombinerInputNV_remap_index, -1 },
{ CombinerParameterfNV_names, CombinerParameterfNV_remap_index, -1 },
- { GetFinalCombinerInputParameterfvNV_names, GetFinalCombinerInputParameterfvNV_remap_index, -1 },
{ GetCombinerInputParameterivNV_names, GetCombinerInputParameterivNV_remap_index, -1 },
{ CombinerParameterivNV_names, CombinerParameterivNV_remap_index, -1 },
{ NULL, 0, 0 }
@@ -5716,8 +6020,8 @@ static const struct dri_extension_function GL_NV_register_combiners2_functions[]
#if defined(need_GL_NV_vertex_array_range)
static const struct dri_extension_function GL_NV_vertex_array_range_functions[] = {
- { FlushVertexArrayRangeNV_names, FlushVertexArrayRangeNV_remap_index, -1 },
{ VertexArrayRangeNV_names, VertexArrayRangeNV_remap_index, -1 },
+ { FlushVertexArrayRangeNV_names, FlushVertexArrayRangeNV_remap_index, -1 },
{ NULL, 0, 0 }
};
#endif
@@ -5726,6 +6030,7 @@ static const struct dri_extension_function GL_NV_vertex_array_range_functions[]
static const struct dri_extension_function GL_NV_vertex_program_functions[] = {
{ VertexAttrib4ubvNV_names, VertexAttrib4ubvNV_remap_index, -1 },
{ VertexAttrib4svNV_names, VertexAttrib4svNV_remap_index, -1 },
+ { VertexAttribs3fvNV_names, VertexAttribs3fvNV_remap_index, -1 },
{ VertexAttribs1dvNV_names, VertexAttribs1dvNV_remap_index, -1 },
{ VertexAttrib1fvNV_names, VertexAttrib1fvNV_remap_index, -1 },
{ VertexAttrib4fNV_names, VertexAttrib4fNV_remap_index, -1 },
@@ -5734,7 +6039,6 @@ static const struct dri_extension_function GL_NV_vertex_program_functions[] = {
{ VertexAttribs3dvNV_names, VertexAttribs3dvNV_remap_index, -1 },
{ VertexAttribs4fvNV_names, VertexAttribs4fvNV_remap_index, -1 },
{ VertexAttrib2sNV_names, VertexAttrib2sNV_remap_index, -1 },
- { VertexAttribs3fvNV_names, VertexAttribs3fvNV_remap_index, -1 },
{ ProgramEnvParameter4fvARB_names, ProgramEnvParameter4fvARB_remap_index, -1 },
{ LoadProgramNV_names, LoadProgramNV_remap_index, -1 },
{ VertexAttrib4fvNV_names, VertexAttrib4fvNV_remap_index, -1 },
@@ -5934,11 +6238,11 @@ static const struct dri_extension_function GL_SGIX_igloo_interface_functions[] =
#if defined(need_GL_SGIX_instruments)
static const struct dri_extension_function GL_SGIX_instruments_functions[] = {
{ ReadInstrumentsSGIX_names, ReadInstrumentsSGIX_remap_index, -1 },
+ { PollInstrumentsSGIX_names, PollInstrumentsSGIX_remap_index, -1 },
{ GetInstrumentsSGIX_names, GetInstrumentsSGIX_remap_index, -1 },
{ StartInstrumentsSGIX_names, StartInstrumentsSGIX_remap_index, -1 },
{ StopInstrumentsSGIX_names, StopInstrumentsSGIX_remap_index, -1 },
{ InstrumentsBufferSGIX_names, InstrumentsBufferSGIX_remap_index, -1 },
- { PollInstrumentsSGIX_names, PollInstrumentsSGIX_remap_index, -1 },
{ NULL, 0, 0 }
};
#endif
@@ -5946,11 +6250,11 @@ static const struct dri_extension_function GL_SGIX_instruments_functions[] = {
#if defined(need_GL_SGIX_list_priority)
static const struct dri_extension_function GL_SGIX_list_priority_functions[] = {
{ ListParameterfSGIX_names, ListParameterfSGIX_remap_index, -1 },
- { GetListParameterivSGIX_names, GetListParameterivSGIX_remap_index, -1 },
{ GetListParameterfvSGIX_names, GetListParameterfvSGIX_remap_index, -1 },
{ ListParameteriSGIX_names, ListParameteriSGIX_remap_index, -1 },
{ ListParameterfvSGIX_names, ListParameterfvSGIX_remap_index, -1 },
{ ListParameterivSGIX_names, ListParameterivSGIX_remap_index, -1 },
+ { GetListParameterivSGIX_names, GetListParameterivSGIX_remap_index, -1 },
{ NULL, 0, 0 }
};
#endif
@@ -5965,9 +6269,9 @@ static const struct dri_extension_function GL_SGIX_pixel_texture_functions[] = {
#if defined(need_GL_SGIX_polynomial_ffd)
static const struct dri_extension_function GL_SGIX_polynomial_ffd_functions[] = {
{ LoadIdentityDeformationMapSGIX_names, LoadIdentityDeformationMapSGIX_remap_index, -1 },
- { DeformationMap3dSGIX_names, DeformationMap3dSGIX_remap_index, -1 },
{ DeformSGIX_names, DeformSGIX_remap_index, -1 },
{ DeformationMap3fSGIX_names, DeformationMap3fSGIX_remap_index, -1 },
+ { DeformationMap3dSGIX_names, DeformationMap3dSGIX_remap_index, -1 },
{ NULL, 0, 0 }
};
#endif
@@ -6335,3 +6639,463 @@ static const struct dri_extension_function GL_VERSION_2_1_functions[] = {
};
#endif
+#else /* IN_DRI_DRIVER */
+
+#if defined(need_GL_3DFX_tbuffer)
+#define GL_3DFX_tbuffer_functions NULL
+#endif
+
+#if defined(need_GL_APPLE_flush_buffer_range)
+#define GL_APPLE_flush_buffer_range_functions NULL
+#endif
+
+#if defined(need_GL_APPLE_texture_range)
+#define GL_APPLE_texture_range_functions NULL
+#endif
+
+#if defined(need_GL_APPLE_vertex_array_object)
+#define GL_APPLE_vertex_array_object_functions NULL
+#endif
+
+#if defined(need_GL_ARB_copy_buffer)
+#define GL_ARB_copy_buffer_functions NULL
+#endif
+
+#if defined(need_GL_ARB_draw_buffers)
+#define GL_ARB_draw_buffers_functions NULL
+#endif
+
+#if defined(need_GL_ARB_draw_elements_base_vertex)
+#define GL_ARB_draw_elements_base_vertex_functions NULL
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object)
+#define GL_ARB_framebuffer_object_functions NULL
+#endif
+
+#if defined(need_GL_ARB_map_buffer_range)
+#define GL_ARB_map_buffer_range_functions NULL
+#endif
+
+#if defined(need_GL_ARB_matrix_palette)
+#define GL_ARB_matrix_palette_functions NULL
+#endif
+
+#if defined(need_GL_ARB_multisample)
+#define GL_ARB_multisample_functions NULL
+#endif
+
+#if defined(need_GL_ARB_occlusion_query)
+#define GL_ARB_occlusion_query_functions NULL
+#endif
+
+#if defined(need_GL_ARB_point_parameters)
+#define GL_ARB_point_parameters_functions NULL
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+#define GL_ARB_shader_objects_functions NULL
+#endif
+
+#if defined(need_GL_ARB_sync)
+#define GL_ARB_sync_functions NULL
+#endif
+
+#if defined(need_GL_ARB_texture_compression)
+#define GL_ARB_texture_compression_functions NULL
+#endif
+
+#if defined(need_GL_ARB_transpose_matrix)
+#define GL_ARB_transpose_matrix_functions NULL
+#endif
+
+#if defined(need_GL_ARB_vertex_array_object)
+#define GL_ARB_vertex_array_object_functions NULL
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+#define GL_ARB_vertex_blend_functions NULL
+#endif
+
+#if defined(need_GL_ARB_vertex_buffer_object)
+#define GL_ARB_vertex_buffer_object_functions NULL
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+#define GL_ARB_vertex_program_functions NULL
+#endif
+
+#if defined(need_GL_ARB_vertex_shader)
+#define GL_ARB_vertex_shader_functions NULL
+#endif
+
+#if defined(need_GL_ARB_window_pos)
+#define GL_ARB_window_pos_functions NULL
+#endif
+
+#if defined(need_GL_ATI_blend_equation_separate)
+#define GL_ATI_blend_equation_separate_functions NULL
+#endif
+
+#if defined(need_GL_ATI_draw_buffers)
+#define GL_ATI_draw_buffers_functions NULL
+#endif
+
+#if defined(need_GL_ATI_envmap_bumpmap)
+#define GL_ATI_envmap_bumpmap_functions NULL
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+#define GL_ATI_fragment_shader_functions NULL
+#endif
+
+#if defined(need_GL_ATI_separate_stencil)
+#define GL_ATI_separate_stencil_functions NULL
+#endif
+
+#if defined(need_GL_EXT_blend_color)
+#define GL_EXT_blend_color_functions NULL
+#endif
+
+#if defined(need_GL_EXT_blend_equation_separate)
+#define GL_EXT_blend_equation_separate_functions NULL
+#endif
+
+#if defined(need_GL_EXT_blend_func_separate)
+#define GL_EXT_blend_func_separate_functions NULL
+#endif
+
+#if defined(need_GL_EXT_blend_minmax)
+#define GL_EXT_blend_minmax_functions NULL
+#endif
+
+#if defined(need_GL_EXT_color_subtable)
+#define GL_EXT_color_subtable_functions NULL
+#endif
+
+#if defined(need_GL_EXT_compiled_vertex_array)
+#define GL_EXT_compiled_vertex_array_functions NULL
+#endif
+
+#if defined(need_GL_EXT_convolution)
+#define GL_EXT_convolution_functions NULL
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+#define GL_EXT_coordinate_frame_functions NULL
+#endif
+
+#if defined(need_GL_EXT_copy_texture)
+#define GL_EXT_copy_texture_functions NULL
+#endif
+
+#if defined(need_GL_EXT_cull_vertex)
+#define GL_EXT_cull_vertex_functions NULL
+#endif
+
+#if defined(need_GL_EXT_depth_bounds_test)
+#define GL_EXT_depth_bounds_test_functions NULL
+#endif
+
+#if defined(need_GL_EXT_draw_range_elements)
+#define GL_EXT_draw_range_elements_functions NULL
+#endif
+
+#if defined(need_GL_EXT_fog_coord)
+#define GL_EXT_fog_coord_functions NULL
+#endif
+
+#if defined(need_GL_EXT_framebuffer_blit)
+#define GL_EXT_framebuffer_blit_functions NULL
+#endif
+
+#if defined(need_GL_EXT_framebuffer_object)
+#define GL_EXT_framebuffer_object_functions NULL
+#endif
+
+#if defined(need_GL_EXT_gpu_program_parameters)
+#define GL_EXT_gpu_program_parameters_functions NULL
+#endif
+
+#if defined(need_GL_EXT_histogram)
+#define GL_EXT_histogram_functions NULL
+#endif
+
+#if defined(need_GL_EXT_index_func)
+#define GL_EXT_index_func_functions NULL
+#endif
+
+#if defined(need_GL_EXT_index_material)
+#define GL_EXT_index_material_functions NULL
+#endif
+
+#if defined(need_GL_EXT_light_texture)
+#define GL_EXT_light_texture_functions NULL
+#endif
+
+#if defined(need_GL_EXT_multi_draw_arrays)
+#define GL_EXT_multi_draw_arrays_functions NULL
+#endif
+
+#if defined(need_GL_EXT_multisample)
+#define GL_EXT_multisample_functions NULL
+#endif
+
+#if defined(need_GL_EXT_paletted_texture)
+#define GL_EXT_paletted_texture_functions NULL
+#endif
+
+#if defined(need_GL_EXT_pixel_transform)
+#define GL_EXT_pixel_transform_functions NULL
+#endif
+
+#if defined(need_GL_EXT_point_parameters)
+#define GL_EXT_point_parameters_functions NULL
+#endif
+
+#if defined(need_GL_EXT_polygon_offset)
+#define GL_EXT_polygon_offset_functions NULL
+#endif
+
+#if defined(need_GL_EXT_provoking_vertex)
+#define GL_EXT_provoking_vertex_functions NULL
+#endif
+
+#if defined(need_GL_EXT_secondary_color)
+#define GL_EXT_secondary_color_functions NULL
+#endif
+
+#if defined(need_GL_EXT_stencil_two_side)
+#define GL_EXT_stencil_two_side_functions NULL
+#endif
+
+#if defined(need_GL_EXT_subtexture)
+#define GL_EXT_subtexture_functions NULL
+#endif
+
+#if defined(need_GL_EXT_texture3D)
+#define GL_EXT_texture3D_functions NULL
+#endif
+
+#if defined(need_GL_EXT_texture_array)
+#define GL_EXT_texture_array_functions NULL
+#endif
+
+#if defined(need_GL_EXT_texture_object)
+#define GL_EXT_texture_object_functions NULL
+#endif
+
+#if defined(need_GL_EXT_texture_perturb_normal)
+#define GL_EXT_texture_perturb_normal_functions NULL
+#endif
+
+#if defined(need_GL_EXT_timer_query)
+#define GL_EXT_timer_query_functions NULL
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+#define GL_EXT_vertex_array_functions NULL
+#endif
+
+#if defined(need_GL_EXT_vertex_weighting)
+#define GL_EXT_vertex_weighting_functions NULL
+#endif
+
+#if defined(need_GL_HP_image_transform)
+#define GL_HP_image_transform_functions NULL
+#endif
+
+#if defined(need_GL_IBM_multimode_draw_arrays)
+#define GL_IBM_multimode_draw_arrays_functions NULL
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+#define GL_IBM_vertex_array_lists_functions NULL
+#endif
+
+#if defined(need_GL_INGR_blend_func_separate)
+#define GL_INGR_blend_func_separate_functions NULL
+#endif
+
+#if defined(need_GL_INTEL_parallel_arrays)
+#define GL_INTEL_parallel_arrays_functions NULL
+#endif
+
+#if defined(need_GL_MESA_resize_buffers)
+#define GL_MESA_resize_buffers_functions NULL
+#endif
+
+#if defined(need_GL_MESA_shader_debug)
+#define GL_MESA_shader_debug_functions NULL
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+#define GL_MESA_window_pos_functions NULL
+#endif
+
+#if defined(need_GL_NV_evaluators)
+#define GL_NV_evaluators_functions NULL
+#endif
+
+#if defined(need_GL_NV_fence)
+#define GL_NV_fence_functions NULL
+#endif
+
+#if defined(need_GL_NV_fragment_program)
+#define GL_NV_fragment_program_functions NULL
+#endif
+
+#if defined(need_GL_NV_point_sprite)
+#define GL_NV_point_sprite_functions NULL
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+#define GL_NV_register_combiners_functions NULL
+#endif
+
+#if defined(need_GL_NV_register_combiners2)
+#define GL_NV_register_combiners2_functions NULL
+#endif
+
+#if defined(need_GL_NV_vertex_array_range)
+#define GL_NV_vertex_array_range_functions NULL
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+#define GL_NV_vertex_program_functions NULL
+#endif
+
+#if defined(need_GL_PGI_misc_hints)
+#define GL_PGI_misc_hints_functions NULL
+#endif
+
+#if defined(need_GL_SGIS_detail_texture)
+#define GL_SGIS_detail_texture_functions NULL
+#endif
+
+#if defined(need_GL_SGIS_fog_function)
+#define GL_SGIS_fog_function_functions NULL
+#endif
+
+#if defined(need_GL_SGIS_multisample)
+#define GL_SGIS_multisample_functions NULL
+#endif
+
+#if defined(need_GL_SGIS_pixel_texture)
+#define GL_SGIS_pixel_texture_functions NULL
+#endif
+
+#if defined(need_GL_SGIS_point_parameters)
+#define GL_SGIS_point_parameters_functions NULL
+#endif
+
+#if defined(need_GL_SGIS_sharpen_texture)
+#define GL_SGIS_sharpen_texture_functions NULL
+#endif
+
+#if defined(need_GL_SGIS_texture4D)
+#define GL_SGIS_texture4D_functions NULL
+#endif
+
+#if defined(need_GL_SGIS_texture_color_mask)
+#define GL_SGIS_texture_color_mask_functions NULL
+#endif
+
+#if defined(need_GL_SGIS_texture_filter4)
+#define GL_SGIS_texture_filter4_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_async)
+#define GL_SGIX_async_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_flush_raster)
+#define GL_SGIX_flush_raster_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+#define GL_SGIX_fragment_lighting_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_framezoom)
+#define GL_SGIX_framezoom_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_igloo_interface)
+#define GL_SGIX_igloo_interface_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_instruments)
+#define GL_SGIX_instruments_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_list_priority)
+#define GL_SGIX_list_priority_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_pixel_texture)
+#define GL_SGIX_pixel_texture_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_polynomial_ffd)
+#define GL_SGIX_polynomial_ffd_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_reference_plane)
+#define GL_SGIX_reference_plane_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_sprite)
+#define GL_SGIX_sprite_functions NULL
+#endif
+
+#if defined(need_GL_SGIX_tag_sample_buffer)
+#define GL_SGIX_tag_sample_buffer_functions NULL
+#endif
+
+#if defined(need_GL_SGI_color_table)
+#define GL_SGI_color_table_functions NULL
+#endif
+
+#if defined(need_GL_SUNX_constant_data)
+#define GL_SUNX_constant_data_functions NULL
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+#define GL_SUN_global_alpha_functions NULL
+#endif
+
+#if defined(need_GL_SUN_mesh_array)
+#define GL_SUN_mesh_array_functions NULL
+#endif
+
+#if defined(need_GL_SUN_triangle_list)
+#define GL_SUN_triangle_list_functions NULL
+#endif
+
+#if defined(need_GL_SUN_vertex)
+#define GL_SUN_vertex_functions NULL
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+#define GL_VERSION_1_3_functions NULL
+#endif
+
+#if defined(need_GL_VERSION_1_4)
+#define GL_VERSION_1_4_functions NULL
+#endif
+
+#if defined(need_GL_VERSION_1_5)
+#define GL_VERSION_1_5_functions NULL
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+#define GL_VERSION_2_0_functions NULL
+#endif
+
+#if defined(need_GL_VERSION_2_1)
+#define GL_VERSION_2_1_functions NULL
+#endif
+
+#endif /* IN_DRI_DRIVER */
+
diff --git a/src/mesa/drivers/dri/common/spantmp2.h b/src/mesa/drivers/dri/common/spantmp2.h
index f2868cb58a..89c815722f 100644
--- a/src/mesa/drivers/dri/common/spantmp2.h
+++ b/src/mesa/drivers/dri/common/spantmp2.h
@@ -82,6 +82,71 @@
rgba[3] = 0xff; \
} while (0)
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_4_4_4_4_REV)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_4444(color[3], color[0], color[1], color[2])
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, PACK_COLOR_4444(a, r, g, b)) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = ((p >> 8) & 0xf) * 0x11; \
+ rgba[1] = ((p >> 4) & 0xf) * 0x11; \
+ rgba[2] = ((p >> 0) & 0xf) * 0x11; \
+ rgba[3] = ((p >> 12) & 0xf) * 0x11; \
+ } while (0)
+
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_1_5_5_5_REV)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_1555(color[3], color[0], color[1], color[2])
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, PACK_COLOR_1555(a, r, g, b)) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = ((p >> 7) & 0xf8) * 255 / 0xf8; \
+ rgba[1] = ((p >> 2) & 0xf8) * 255 / 0xf8; \
+ rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ rgba[3] = ((p >> 15) & 0x1) * 0xff; \
+ } while (0)
+
#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
/**
diff --git a/src/mesa/drivers/dri/common/texmem.c b/src/mesa/drivers/dri/common/texmem.c
index ff174a251d..b64618a03c 100644
--- a/src/mesa/drivers/dri/common/texmem.c
+++ b/src/mesa/drivers/dri/common/texmem.c
@@ -1063,31 +1063,31 @@ void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped,
ctx->Texture.CurrentUnit = i;
if ( (targets & DRI_TEXMGR_DO_TEXTURE_1D) != 0 ) {
- texObj = ctx->Texture.Unit[i].Current1D;
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_1D_INDEX];
ctx->Driver.BindTexture( ctx, GL_TEXTURE_1D, texObj );
move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
}
if ( (targets & DRI_TEXMGR_DO_TEXTURE_2D) != 0 ) {
- texObj = ctx->Texture.Unit[i].Current2D;
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_2D_INDEX];
ctx->Driver.BindTexture( ctx, GL_TEXTURE_2D, texObj );
move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
}
if ( (targets & DRI_TEXMGR_DO_TEXTURE_3D) != 0 ) {
- texObj = ctx->Texture.Unit[i].Current3D;
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_3D_INDEX];
ctx->Driver.BindTexture( ctx, GL_TEXTURE_3D, texObj );
move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
}
if ( (targets & DRI_TEXMGR_DO_TEXTURE_CUBE) != 0 ) {
- texObj = ctx->Texture.Unit[i].CurrentCubeMap;
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_CUBE_INDEX];
ctx->Driver.BindTexture( ctx, GL_TEXTURE_CUBE_MAP_ARB, texObj );
move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
}
if ( (targets & DRI_TEXMGR_DO_TEXTURE_RECT) != 0 ) {
- texObj = ctx->Texture.Unit[i].CurrentRect;
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_RECT_INDEX];
ctx->Driver.BindTexture( ctx, GL_TEXTURE_RECTANGLE_NV, texObj );
move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
}
diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c
index 30c860b96c..6f4a4f7f22 100644
--- a/src/mesa/drivers/dri/common/utils.c
+++ b/src/mesa/drivers/dri/common/utils.c
@@ -32,19 +32,22 @@
#include <string.h>
#include <stdlib.h>
#include "main/mtypes.h"
+#include "main/cpuinfo.h"
#include "main/extensions.h"
#include "glapi/dispatch.h"
#include "utils.h"
+
+#ifdef IN_DRI_DRIVER
+
int driDispatchRemapTable[ driDispatchRemapTable_size ];
-#if defined(USE_X86_ASM)
-#include "x86/common_x86_asm.h"
-#endif
+#else /* IN_DRI_DRIVER */
-#if defined(USE_PPC_ASM)
-#include "ppc/common_ppc_features.h"
-#endif
+#define driDispatchRemapTable_size 1
+static int driDispatchRemapTable[ driDispatchRemapTable_size ];
+
+#endif /* IN_DRI_DRIVER */
unsigned
driParseDebugString( const char * debug,
@@ -93,12 +96,8 @@ unsigned
driGetRendererString( char * buffer, const char * hardware_name,
const char * driver_date, GLuint agp_mode )
{
-#define MAX_INFO 4
- const char * cpu[MAX_INFO];
- unsigned next = 0;
- unsigned i;
- unsigned offset;
-
+ unsigned offset;
+ char *cpu;
offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date );
@@ -118,59 +117,10 @@ driGetRendererString( char * buffer, const char * hardware_name,
/* Append any CPU-specific information.
*/
-#ifdef USE_X86_ASM
- if ( _mesa_x86_cpu_features ) {
- cpu[next] = " x86";
- next++;
- }
-# ifdef USE_MMX_ASM
- if ( cpu_has_mmx ) {
- cpu[next] = (cpu_has_mmxext) ? "/MMX+" : "/MMX";
- next++;
- }
-# endif
-# ifdef USE_3DNOW_ASM
- if ( cpu_has_3dnow ) {
- cpu[next] = (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!";
- next++;
- }
-# endif
-# ifdef USE_SSE_ASM
- if ( cpu_has_xmm ) {
- cpu[next] = (cpu_has_xmm2) ? "/SSE2" : "/SSE";
- next++;
- }
-# endif
-
-#elif defined(USE_SPARC_ASM)
-
- cpu[0] = " SPARC";
- next = 1;
-
-#elif defined(USE_PPC_ASM)
- if ( _mesa_ppc_cpu_features ) {
- cpu[next] = (cpu_has_64) ? " PowerPC 64" : " PowerPC";
- next++;
- }
-
-# ifdef USE_VMX_ASM
- if ( cpu_has_vmx ) {
- cpu[next] = "/Altivec";
- next++;
- }
-# endif
-
- if ( ! cpu_has_fpu ) {
- cpu[next] = "/No FPU";
- next++;
- }
-#endif
-
- for ( i = 0 ; i < next ; i++ ) {
- const size_t len = strlen( cpu[i] );
-
- strncpy( & buffer[ offset ], cpu[i], len );
- offset += len;
+ cpu = _mesa_get_cpu_string();
+ if (cpu) {
+ offset += sprintf(buffer + offset, " %s", cpu);
+ _mesa_free(cpu);
}
return offset;
@@ -179,13 +129,18 @@ driGetRendererString( char * buffer, const char * hardware_name,
+#define need_GL_ARB_draw_buffers
#define need_GL_ARB_multisample
+#define need_GL_ARB_texture_compression
#define need_GL_ARB_transpose_matrix
+#define need_GL_ARB_vertex_buffer_object
#define need_GL_ARB_window_pos
#define need_GL_EXT_compiled_vertex_array
+#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_polygon_offset
#define need_GL_EXT_texture_object
#define need_GL_EXT_vertex_array
+#define need_GL_IBM_multimode_draw_arrays
#define need_GL_MESA_window_pos
/* These are needed in *all* drivers because Mesa internally implements
@@ -198,14 +153,19 @@ driGetRendererString( char * buffer, const char * hardware_name,
#include "extension_helper.h"
static const struct dri_extension all_mesa_extensions[] = {
+ { "GL_ARB_draw_buffers", GL_ARB_draw_buffers_functions },
{ "GL_ARB_multisample", GL_ARB_multisample_functions },
+ { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
{ "GL_ARB_transpose_matrix", GL_ARB_transpose_matrix_functions },
+ { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
{ "GL_ARB_window_pos", GL_ARB_window_pos_functions },
{ "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions },
{ "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
+ { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
{ "GL_EXT_polygon_offset", GL_EXT_polygon_offset_functions },
{ "GL_EXT_texture_object", GL_EXT_texture_object_functions },
{ "GL_EXT_vertex_array", GL_EXT_vertex_array_functions },
+ { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
{ "GL_MESA_window_pos", GL_MESA_window_pos_functions },
{ "GL_NV_vertex_program", GL_NV_vertex_program_functions },
{ NULL, NULL }
@@ -310,8 +270,10 @@ void driInitSingleExtension( GLcontext * ctx,
*/
offset = _glapi_add_dispatch( functions, parameter_signature );
if (offset == -1) {
+#if 0 /* this causes noise with egl */
fprintf(stderr, "DISPATCH ERROR! _glapi_add_dispatch failed "
"to add %s!\n", functions[0]);
+#endif
}
else if (ext->functions[i].remap_index != -1) {
driDispatchRemapTable[ ext->functions[i].remap_index ] =
@@ -504,6 +466,9 @@ GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
* \c GLX_SWAP_UNDEFINED_OML. See the
* GLX_OML_swap_method extension spec for more details.
* \param num_db_modes Number of entries in \c db_modes.
+ * \param msaa_samples Array of msaa sample count. 0 represents a visual
+ * without a multisample buffer.
+ * \param num_msaa_modes Number of entries in \c msaa_samples.
* \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
* \c GLX_DIRECT_COLOR.
*
@@ -523,7 +488,8 @@ __DRIconfig **
driCreateConfigs(GLenum fb_format, GLenum fb_type,
const uint8_t * depth_bits, const uint8_t * stencil_bits,
unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes)
+ const GLenum * db_modes, unsigned num_db_modes,
+ const uint8_t * msaa_samples, unsigned num_msaa_modes)
{
static const uint8_t bits_table[4][4] = {
/* R G B A */
@@ -583,9 +549,7 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type,
int index;
__DRIconfig **configs, **c;
__GLcontextModes *modes;
- unsigned i;
- unsigned j;
- unsigned k;
+ unsigned i, j, k, h;
unsigned num_modes;
unsigned num_accum_bits = 2;
@@ -658,7 +622,7 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type,
break;
}
- num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits;
+ num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes;
configs = _mesa_calloc((num_modes + 1) * sizeof *configs);
if (configs == NULL)
return NULL;
@@ -666,66 +630,72 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type,
c = configs;
for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
for ( i = 0 ; i < num_db_modes ; i++ ) {
- for ( j = 0 ; j < num_accum_bits ; j++ ) {
- *c = _mesa_malloc (sizeof **c);
- modes = &(*c)->modes;
- c++;
-
- memset(modes, 0, sizeof *modes);
- modes->redBits = bits[0];
- modes->greenBits = bits[1];
- modes->blueBits = bits[2];
- modes->alphaBits = bits[3];
- modes->redMask = masks[0];
- modes->greenMask = masks[1];
- modes->blueMask = masks[2];
- modes->alphaMask = masks[3];
- modes->rgbBits = modes->redBits + modes->greenBits
- + modes->blueBits + modes->alphaBits;
-
- modes->accumRedBits = 16 * j;
- modes->accumGreenBits = 16 * j;
- modes->accumBlueBits = 16 * j;
- modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
- modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
-
- modes->stencilBits = stencil_bits[k];
- modes->depthBits = depth_bits[k];
-
- modes->transparentPixel = GLX_NONE;
- modes->transparentRed = GLX_DONT_CARE;
- modes->transparentGreen = GLX_DONT_CARE;
- modes->transparentBlue = GLX_DONT_CARE;
- modes->transparentAlpha = GLX_DONT_CARE;
- modes->transparentIndex = GLX_DONT_CARE;
- modes->visualType = GLX_DONT_CARE;
- modes->renderType = GLX_RGBA_BIT;
- modes->drawableType = GLX_WINDOW_BIT;
- modes->rgbMode = GL_TRUE;
-
- if ( db_modes[i] == GLX_NONE ) {
- modes->doubleBufferMode = GL_FALSE;
- }
- else {
- modes->doubleBufferMode = GL_TRUE;
- modes->swapMethod = db_modes[i];
- }
-
- modes->haveAccumBuffer = ((modes->accumRedBits +
+ for ( h = 0 ; h < num_msaa_modes; h++ ) {
+ for ( j = 0 ; j < num_accum_bits ; j++ ) {
+ *c = _mesa_malloc (sizeof **c);
+ modes = &(*c)->modes;
+ c++;
+
+ memset(modes, 0, sizeof *modes);
+ modes->redBits = bits[0];
+ modes->greenBits = bits[1];
+ modes->blueBits = bits[2];
+ modes->alphaBits = bits[3];
+ modes->redMask = masks[0];
+ modes->greenMask = masks[1];
+ modes->blueMask = masks[2];
+ modes->alphaMask = masks[3];
+ modes->rgbBits = modes->redBits + modes->greenBits
+ + modes->blueBits + modes->alphaBits;
+
+ modes->accumRedBits = 16 * j;
+ modes->accumGreenBits = 16 * j;
+ modes->accumBlueBits = 16 * j;
+ modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
+ modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
+
+ modes->stencilBits = stencil_bits[k];
+ modes->depthBits = depth_bits[k];
+
+ modes->transparentPixel = GLX_NONE;
+ modes->transparentRed = GLX_DONT_CARE;
+ modes->transparentGreen = GLX_DONT_CARE;
+ modes->transparentBlue = GLX_DONT_CARE;
+ modes->transparentAlpha = GLX_DONT_CARE;
+ modes->transparentIndex = GLX_DONT_CARE;
+ modes->visualType = GLX_DONT_CARE;
+ modes->renderType = GLX_RGBA_BIT;
+ modes->drawableType = GLX_WINDOW_BIT;
+ modes->rgbMode = GL_TRUE;
+
+ if ( db_modes[i] == GLX_NONE ) {
+ modes->doubleBufferMode = GL_FALSE;
+ }
+ else {
+ modes->doubleBufferMode = GL_TRUE;
+ modes->swapMethod = db_modes[i];
+ }
+
+ modes->samples = msaa_samples[h];
+ modes->sampleBuffers = modes->samples ? 1 : 0;
+
+
+ modes->haveAccumBuffer = ((modes->accumRedBits +
modes->accumGreenBits +
modes->accumBlueBits +
modes->accumAlphaBits) > 0);
- modes->haveDepthBuffer = (modes->depthBits > 0);
- modes->haveStencilBuffer = (modes->stencilBits > 0);
-
- modes->bindToTextureRgb = GL_TRUE;
- modes->bindToTextureRgba = GL_TRUE;
- modes->bindToMipmapTexture = GL_FALSE;
- modes->bindToTextureTargets = modes->rgbMode ?
- __DRI_ATTRIB_TEXTURE_1D_BIT |
- __DRI_ATTRIB_TEXTURE_2D_BIT |
- __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT :
- 0;
+ modes->haveDepthBuffer = (modes->depthBits > 0);
+ modes->haveStencilBuffer = (modes->stencilBits > 0);
+
+ modes->bindToTextureRgb = GL_TRUE;
+ modes->bindToTextureRgba = GL_TRUE;
+ modes->bindToMipmapTexture = GL_FALSE;
+ modes->bindToTextureTargets = modes->rgbMode ?
+ __DRI_ATTRIB_TEXTURE_1D_BIT |
+ __DRI_ATTRIB_TEXTURE_2D_BIT |
+ __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT :
+ 0;
+ }
}
}
}
@@ -734,9 +704,10 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type,
return configs;
}
-const __DRIconfig **driConcatConfigs(__DRIconfig **a, __DRIconfig **b)
+__DRIconfig **driConcatConfigs(__DRIconfig **a,
+ __DRIconfig **b)
{
- const __DRIconfig **all;
+ __DRIconfig **all;
int i, j, index;
i = 0;
diff --git a/src/mesa/drivers/dri/common/utils.h b/src/mesa/drivers/dri/common/utils.h
index 0c974dbff3..9e9e5bc224 100644
--- a/src/mesa/drivers/dri/common/utils.h
+++ b/src/mesa/drivers/dri/common/utils.h
@@ -131,9 +131,11 @@ extern __DRIconfig **
driCreateConfigs(GLenum fb_format, GLenum fb_type,
const uint8_t * depth_bits, const uint8_t * stencil_bits,
unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes);
+ const GLenum * db_modes, unsigned num_db_modes,
+ const uint8_t * msaa_samples, unsigned num_msaa_modes);
-const __DRIconfig **driConcatConfigs(__DRIconfig **a, __DRIconfig **b);
+__DRIconfig **driConcatConfigs(__DRIconfig **a,
+ __DRIconfig **b);
int
driGetConfigAttrib(const __DRIconfig *config,
diff --git a/src/mesa/drivers/dri/common/xmlpool.h b/src/mesa/drivers/dri/common/xmlpool.h
index 7fbc6e800d..587517ea10 100644
--- a/src/mesa/drivers/dri/common/xmlpool.h
+++ b/src/mesa/drivers/dri/common/xmlpool.h
@@ -60,6 +60,10 @@
#define DRI_CONF_OPT_BEGIN(name,type,def) \
"<option name=\""#name"\" type=\""#type"\" default=\""#def"\">\n"
+/** \brief Begin an option definition with qouted default value */
+#define DRI_CONF_OPT_BEGIN_Q(name,type,def) \
+"<option name=\""#name"\" type=\""#type"\" default="#def">\n"
+
/** \brief Begin an option definition with restrictions on valid values */
#define DRI_CONF_OPT_BEGIN_V(name,type,def,valid) \
"<option name=\""#name"\" type=\""#type"\" default=\""#def"\" valid=\""valid"\">\n"
diff --git a/src/mesa/drivers/dri/common/xmlpool/options.h b/src/mesa/drivers/dri/common/xmlpool/options.h
index d5f4fc3491..d76595578c 100644
--- a/src/mesa/drivers/dri/common/xmlpool/options.h
+++ b/src/mesa/drivers/dri/common/xmlpool/options.h
@@ -546,3 +546,23 @@ DRI_CONF_OPT_BEGIN(nv_vertex_program,bool,def) \
DRI_CONF_DESC(fr,"Activer l'extension GL_NV_vertex_program") \
DRI_CONF_DESC(sv,"Aktivera tillägget GL_NV_vertex_program") \
DRI_CONF_OPT_END
+
+#define DRI_CONF_ALWAYS_FLUSH_BATCH(def) \
+DRI_CONF_OPT_BEGIN(always_flush_batch,bool,def) \
+ DRI_CONF_DESC(en,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(de,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(es,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(nl,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(fr,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(sv,"Enable flushing batchbuffer after each draw call") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ALWAYS_FLUSH_CACHE(def) \
+DRI_CONF_OPT_BEGIN(always_flush_cache,bool,def) \
+ DRI_CONF_DESC(en,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(de,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(es,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(nl,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(fr,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(sv,"Enable flushing GPU caches with each draw call") \
+DRI_CONF_OPT_END
diff --git a/src/mesa/drivers/dri/common/xmlpool/t_options.h b/src/mesa/drivers/dri/common/xmlpool/t_options.h
index 4df1916aad..5fd6ec65bf 100644
--- a/src/mesa/drivers/dri/common/xmlpool/t_options.h
+++ b/src/mesa/drivers/dri/common/xmlpool/t_options.h
@@ -237,3 +237,13 @@ DRI_CONF_OPT_END
DRI_CONF_OPT_BEGIN(nv_vertex_program,bool,def) \
DRI_CONF_DESC(en,gettext("Enable extension GL_NV_vertex_program")) \
DRI_CONF_OPT_END
+
+#define DRI_CONF_ALWAYS_FLUSH_BATCH(def) \
+DRI_CONF_OPT_BEGIN(always_flush_batch,bool,def) \
+ DRI_CONF_DESC(en,gettext("Enable flushing batchbuffer after each draw call")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ALWAYS_FLUSH_CACHE(def) \
+DRI_CONF_OPT_BEGIN(always_flush_cache,bool,def) \
+ DRI_CONF_DESC(en,gettext("Enable flushing GPU caches with each draw call")) \
+DRI_CONF_OPT_END
diff --git a/src/mesa/drivers/dri/fb/fb_dri.c b/src/mesa/drivers/dri/fb/fb_dri.c
index f1194d7ce8..571b8922d5 100644
--- a/src/mesa/drivers/dri/fb/fb_dri.c
+++ b/src/mesa/drivers/dri/fb/fb_dri.c
@@ -480,7 +480,7 @@ fbCreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
fbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
diff --git a/src/mesa/drivers/dri/fb/fb_egl.c b/src/mesa/drivers/dri/fb/fb_egl.c
index 35c268441c..4e41860d8c 100644
--- a/src/mesa/drivers/dri/fb/fb_egl.c
+++ b/src/mesa/drivers/dri/fb/fb_egl.c
@@ -472,8 +472,8 @@ fbCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext sh
c->Base.DrawSurface = EGL_NO_SURFACE;
c->Base.ReadSurface = EGL_NO_SURFACE;
- /* generate handle and insert into hash table */
- _eglSaveContext(&c->Base);
+ /* link to display */
+ _eglLinkContext(&c->Base, disp);
assert(c->Base.Handle);
/* Init default driver functions then plug in our FBdev-specific functions
@@ -604,13 +604,9 @@ static EGLBoolean
fbDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
{
fbSurface *fs = Lookup_fbSurface(surface);
- _eglRemoveSurface(&fs->Base);
- if (fs->Base.IsBound) {
- fs->Base.DeletePending = EGL_TRUE;
- }
- else {
+ _eglUnlinkSurface(&fs->Base);
+ if (!_eglIsSurfaceBound(&fs->Base))
free(fs);
- }
return EGL_TRUE;
}
@@ -619,13 +615,9 @@ static EGLBoolean
fbDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
{
fbContext *fc = Lookup_fbContext(context);
- _eglRemoveContext(&fc->Base);
- if (fc->Base.IsBound) {
- fc->Base.DeletePending = EGL_TRUE;
- }
- else {
+ _eglUnlinkContext(&fc->Base);
+ if (!_eglIsContextBound(&fc->Base))
free(fc);
- }
return EGL_TRUE;
}
@@ -688,7 +680,7 @@ fbCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
surface->mesa_framebuffer = _mesa_create_framebuffer(&vis);
if (!surface->mesa_framebuffer) {
free(surface);
- _eglRemoveSurface(&surface->Base);
+ _eglUnlinkSurface(&surface->Base);
return EGL_NO_SURFACE;
}
diff --git a/src/mesa/drivers/dri/ffb/ffb_state.c b/src/mesa/drivers/dri/ffb/ffb_state.c
index ee0fe4e0db..5eb8f417ff 100644
--- a/src/mesa/drivers/dri/ffb/ffb_state.c
+++ b/src/mesa/drivers/dri/ffb/ffb_state.c
@@ -275,7 +275,7 @@ ffbDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
/* We will properly update sw/hw state when stenciling is
* enabled.
*/
- if (! ctx->Stencil.Enabled)
+ if (! ctx->Stencil._Enabled)
return;
stencilctl = fmesa->stencilctl;
@@ -333,7 +333,7 @@ ffbDDStencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
/* We will properly update sw/hw state when stenciling is
* enabled.
*/
- if (! ctx->Stencil.Enabled)
+ if (! ctx->Stencil._Enabled)
return;
stencilctl = fmesa->stencilctl;
diff --git a/src/mesa/drivers/dri/ffb/ffb_xmesa.c b/src/mesa/drivers/dri/ffb/ffb_xmesa.c
index 679f8561d2..3b9f5c6759 100644
--- a/src/mesa/drivers/dri/ffb/ffb_xmesa.c
+++ b/src/mesa/drivers/dri/ffb/ffb_xmesa.c
@@ -260,6 +260,8 @@ ffbCreateContext(const __GLcontextModes *mesaVis,
ctx->Const.MaxLineWidthAA = 1.0;
ctx->Const.LineWidthGranularity = 1.0;
+ ctx->Const.MaxDrawBuffers = 1;
+
/* Instead of having GCC emit these constants a zillion times
* everywhere in the driver, put them here.
*/
@@ -392,7 +394,7 @@ ffbCreateBuffer(__DRIscreenPrivate *driScrnPriv,
static void
ffbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
@@ -626,6 +628,7 @@ ffbFillInModes( __DRIscreenPrivate *psp,
uint8_t depth_bits_array[3];
uint8_t stencil_bits_array[3];
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = 0;
depth_bits_array[1] = depth_bits;
@@ -639,6 +642,8 @@ ffbFillInModes( __DRIscreenPrivate *psp,
stencil_bits_array[1] = 0;
stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
+ msaa_samples_array[0] = 0;
+
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
back_buffer_factor = (have_back_buffer) ? 3 : 1;
@@ -654,9 +659,10 @@ ffbFillInModes( __DRIscreenPrivate *psp,
configs = driCreateConfigs(fb_format, fb_type,
depth_bits_array, stencil_bits_array,
depth_buffer_factor, back_buffer_modes,
- back_buffer_factor);
+ back_buffer_factor,
+ msaa_samples_array, 1);
if (configs == NULL) {
- fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
__LINE__);
return NULL;
}
diff --git a/src/mesa/drivers/dri/gamma/gamma_context.c b/src/mesa/drivers/dri/gamma/gamma_context.c
index c91bedce3a..b0ac299daa 100644
--- a/src/mesa/drivers/dri/gamma/gamma_context.c
+++ b/src/mesa/drivers/dri/gamma/gamma_context.c
@@ -133,6 +133,8 @@ GLboolean gammaCreateContext( const __GLcontextModes *glVisual,
ctx->Const.MaxPointSizeAA = 16.0;
ctx->Const.PointSizeGranularity = 0.25;
+ ctx->Const.MaxDrawBuffers = 1;
+
gmesa->texHeap = mmInit( 0, gmesa->gammaScreen->textureSize );
make_empty_list(&gmesa->TexObjList);
diff --git a/src/mesa/drivers/dri/gamma/gamma_tex.c b/src/mesa/drivers/dri/gamma/gamma_tex.c
index 2ffb790f28..97797d4788 100644
--- a/src/mesa/drivers/dri/gamma/gamma_tex.c
+++ b/src/mesa/drivers/dri/gamma/gamma_tex.c
@@ -107,9 +107,14 @@ static void gammaSetTexFilter(gammaContextPtr gmesa,
static void gammaSetTexBorderColor(gammaContextPtr gmesa,
gammaTextureObjectPtr t,
- GLubyte color[4])
+ const GLfloat color[4])
{
- t->TextureBorderColor = PACK_COLOR_8888(color[0], color[1], color[2], color[3]);
+ GLubyte c[4];
+ CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
+ t->TextureBorderColor = PACK_COLOR_8888(c[0], c[1], c[2], c[3]);
}
@@ -143,7 +148,7 @@ static void gammaTexParameter( GLcontext *ctx, GLenum target,
break;
case GL_TEXTURE_BORDER_COLOR:
- gammaSetTexBorderColor( gmesa, t, tObj->_BorderChan );
+ gammaSetTexBorderColor( gmesa, t, tObj->BorderColor );
break;
case GL_TEXTURE_BASE_LEVEL:
@@ -347,7 +352,7 @@ static void gammaBindTexture( GLcontext *ctx, GLenum target,
gammaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
gammaSetTexFilter( gmesa, t, tObj->MinFilter, tObj->MagFilter, bias );
- gammaSetTexBorderColor( gmesa, t, tObj->_BorderChan );
+ gammaSetTexBorderColor( gmesa, t, tObj->BorderColor );
}
}
@@ -400,19 +405,19 @@ void gammaInitTextureObjects( GLcontext *ctx )
ctx->Texture.CurrentUnit = 0;
- texObj = ctx->Texture.Unit[0].Current1D;
+ texObj = ctx->Texture.Unit[0].CurrentTex[TEXTURE_1D_INDEX];
gammaBindTexture( ctx, GL_TEXTURE_1D, texObj );
- texObj = ctx->Texture.Unit[0].Current2D;
+ texObj = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];
gammaBindTexture( ctx, GL_TEXTURE_2D, texObj );
#if 0
ctx->Texture.CurrentUnit = 1;
- texObj = ctx->Texture.Unit[1].Current1D;
+ texObj = ctx->Texture.Unit[1].CurrentTex[TEXTURE_1D_INDEX];
gammaBindTexture( ctx, GL_TEXTURE_1D, texObj );
- texObj = ctx->Texture.Unit[1].Current2D;
+ texObj = ctx->Texture.Unit[1].CurrentTex[TEXTURE_2D_INDEX];
gammaBindTexture( ctx, GL_TEXTURE_2D, texObj );
#endif
diff --git a/src/mesa/drivers/dri/gamma/gamma_xmesa.c b/src/mesa/drivers/dri/gamma/gamma_xmesa.c
index 2a28902e1e..7b5b53589c 100644
--- a/src/mesa/drivers/dri/gamma/gamma_xmesa.c
+++ b/src/mesa/drivers/dri/gamma/gamma_xmesa.c
@@ -96,7 +96,7 @@ gammaCreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
gammaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
static void
diff --git a/src/mesa/drivers/dri/glcore/Makefile b/src/mesa/drivers/dri/glcore/Makefile
new file mode 100644
index 0000000000..ac7e1de928
--- /dev/null
+++ b/src/mesa/drivers/dri/glcore/Makefile
@@ -0,0 +1,84 @@
+# src/mesa/drivers/dri/glcore/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = glcore_dri.so
+
+DRIVER_SOURCES = glcore_driver.c \
+ $(TOP)/src/mesa/drivers/common/driverfuncs.c \
+ ../common/dri_util.c
+
+C_SOURCES = \
+ $(DRIVER_SOURCES) \
+ $(DRI_SOURCES)
+
+
+# Include directories
+INCLUDE_DIRS = \
+ -I. \
+ -I../common \
+ -I../dri_client \
+ -I../dri_client/imports \
+ -Iserver \
+ -I$(TOP)/include \
+ -I$(DRM_SOURCE_PATH)/shared-core \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/mesa/math \
+ -I$(TOP)/src/mesa/transform \
+ -I$(TOP)/src/mesa/shader \
+ -I$(TOP)/src/mesa/swrast \
+ -I$(TOP)/src/mesa/swrast_setup
+
+# Core Mesa objects
+MESA_MODULES = $(TOP)/src/mesa/libmesa.a
+
+# Libraries that the driver shared lib depends on
+LIB_DEPS = -lm -lpthread -lc
+# LIB_DEPS = -lGL -lm -lpthread -lc
+
+
+ASM_SOURCES =
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+default: depend $(TOP)/$(LIB_DIR)/$(LIBNAME)
+
+
+$(TOP)/$(LIB_DIR)/$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile
+ CC="$(CC)" CXX="$(CXX)" $(TOP)/bin/mklib -o $(LIBNAME) -noprefix -install $(TOP)/$(LIB_DIR) \
+ $(OBJECTS) $(WINLIB) $(LIB_DEPS) $(WINOBJ) $(MESA_MODULES)
+
+
+depend: $(C_SOURCES) $(ASM_SOURCES)
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDE_DIRS) $(C_SOURCES) $(ASM_SOURCES) \
+ > /dev/null
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+
+clean:
+ -rm -f *.o server/*.o
+
+
+include depend
diff --git a/src/mesa/drivers/dri/i810/i810context.c b/src/mesa/drivers/dri/i810/i810context.c
index c281a4990e..6785655686 100644
--- a/src/mesa/drivers/dri/i810/i810context.c
+++ b/src/mesa/drivers/dri/i810/i810context.c
@@ -63,11 +63,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "drirenderbuffer.h"
#include "utils.h"
-#define need_GL_ARB_multisample
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
-#include "extension_helper.h"
-
#ifndef I810_DEBUG
int I810_DEBUG = (0);
#endif
@@ -123,14 +118,11 @@ static void i810BufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
*/
const struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_multitexture", NULL },
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
{ "GL_ARB_texture_env_add", NULL },
{ "GL_ARB_texture_env_combine", NULL },
{ "GL_ARB_texture_env_crossbar", NULL },
{ "GL_ARB_texture_mirrored_repeat", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_stencil_wrap", NULL },
{ "GL_EXT_texture_edge_clamp", NULL },
{ "GL_EXT_texture_env_combine", NULL },
diff --git a/src/mesa/drivers/dri/i810/i810screen.c b/src/mesa/drivers/dri/i810/i810screen.c
index 48603f5d79..6e49f3466c 100644
--- a/src/mesa/drivers/dri/i810/i810screen.c
+++ b/src/mesa/drivers/dri/i810/i810screen.c
@@ -77,6 +77,7 @@ i810FillInModes( __DRIscreenPrivate *psp,
uint8_t depth_bits_array[2];
uint8_t stencil_bits_array[2];
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = depth_bits;
depth_bits_array[1] = depth_bits;
@@ -88,13 +89,16 @@ i810FillInModes( __DRIscreenPrivate *psp,
stencil_bits_array[0] = 0;
stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+ msaa_samples_array[0] = 0;
+
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
back_buffer_factor = (have_back_buffer) ? 2 : 1;
configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
depth_bits_array, stencil_bits_array,
depth_buffer_factor,
- back_buffer_modes, back_buffer_factor);
+ back_buffer_modes, back_buffer_factor,
+ msaa_samples_array, 1);
if (configs == NULL) {
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
__func__, __LINE__ );
@@ -337,7 +341,7 @@ i810CreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
i810DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
const struct __DriverAPIRec driDriverAPI = {
diff --git a/src/mesa/drivers/dri/i810/i810tex.c b/src/mesa/drivers/dri/i810/i810tex.c
index ba4e6b5b0b..cd6e1a8e6e 100644
--- a/src/mesa/drivers/dri/i810/i810tex.c
+++ b/src/mesa/drivers/dri/i810/i810tex.c
@@ -162,7 +162,7 @@ static void i810SetTexFilter(i810ContextPtr imesa,
static void
-i810SetTexBorderColor( i810TextureObjectPtr t, GLubyte color[4] )
+i810SetTexBorderColor( i810TextureObjectPtr t, const GLfloat color[4] )
{
/* Need a fallback.
*/
@@ -211,7 +211,7 @@ i810AllocTexObj( GLcontext *ctx, struct gl_texture_object *texObj )
i810SetTexWrapping( t, texObj->WrapS, texObj->WrapT );
/*i830SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );*/
i810SetTexFilter( imesa, t, texObj->MinFilter, texObj->MagFilter, bias );
- i810SetTexBorderColor( t, texObj->_BorderChan );
+ i810SetTexBorderColor( t, texObj->BorderColor );
}
return t;
@@ -252,7 +252,7 @@ static void i810TexParameter( GLcontext *ctx, GLenum target,
break;
case GL_TEXTURE_BORDER_COLOR:
- i810SetTexBorderColor( t, tObj->_BorderChan );
+ i810SetTexBorderColor( t, tObj->BorderColor );
break;
case GL_TEXTURE_BASE_LEVEL:
diff --git a/src/mesa/drivers/dri/i915/Makefile b/src/mesa/drivers/dri/i915/Makefile
index 5858e0ee9f..f5242ddc7b 100644
--- a/src/mesa/drivers/dri/i915/Makefile
+++ b/src/mesa/drivers/dri/i915/Makefile
@@ -11,15 +11,17 @@ DRIVER_SOURCES = \
i830_metaops.c \
i830_state.c \
i830_texblend.c \
- i830_tex.c \
i830_texstate.c \
i830_vtbl.c \
intel_render.c \
intel_regions.c \
intel_buffer_objects.c \
intel_batchbuffer.c \
+ intel_clear.c \
+ intel_eglimage.c \
+ intel_extensions.c \
+ intel_generatemipmap.c \
intel_mipmap_tree.c \
- i915_tex_layout.c \
intel_tex_layout.c \
intel_tex_image.c \
intel_tex_subimage.c \
@@ -28,13 +30,11 @@ DRIVER_SOURCES = \
intel_tex_format.c \
intel_tex.c \
intel_pixel.c \
- intel_pixel_bitmap.c \
- intel_pixel_copy.c \
- intel_pixel_draw.c \
intel_pixel_read.c \
intel_buffers.c \
intel_blit.c \
- i915_tex.c \
+ intel_swapbuffers.c \
+ i915_tex_layout.c \
i915_texstate.c \
i915_context.c \
i915_debug.c \
@@ -49,9 +49,9 @@ DRIVER_SOURCES = \
intel_screen.c \
intel_span.c \
intel_state.c \
+ intel_syncobj.c \
intel_tris.c \
- intel_fbo.c \
- intel_depthstencil.c
+ intel_fbo.c
C_SOURCES = \
$(COMMON_SOURCES) \
@@ -65,7 +65,7 @@ DRIVER_DEFINES = -I../intel -I../intel/server -DI915 \
DRI_LIB_DEPS += -ldrm_intel
-include ../Makefile.template
+include ../Makefile.es
intel_decode.o: ../intel/intel_decode.c
diff --git a/src/mesa/drivers/dri/i915/i830_context.c b/src/mesa/drivers/dri/i915/i830_context.c
index 09b1ec922f..840946f908 100644
--- a/src/mesa/drivers/dri/i915/i830_context.c
+++ b/src/mesa/drivers/dri/i915/i830_context.c
@@ -47,7 +47,6 @@ i830InitDriverFunctions(struct dd_function_table *functions)
{
intelInitDriverFunctions(functions);
i830InitStateFuncs(functions);
- i830InitTextureFuncs(functions);
}
extern const struct tnl_pipeline_stage *intel_pipeline[];
@@ -73,6 +72,8 @@ i830CreateContext(const __GLcontextModes * mesaVis,
return GL_FALSE;
}
+ _math_matrix_ctr(&intel->ViewportMatrix);
+
/* Initialize swrast, tnl driver tables: */
intelInitSpanFuncs(ctx);
intelInitTriFuncs(ctx);
@@ -97,6 +98,10 @@ i830CreateContext(const __GLcontextModes * mesaVis,
ctx->Const.MaxTextureRectSize = (1 << 11);
ctx->Const.MaxTextureUnits = I830_TEX_UNITS;
+ ctx->Const.MaxTextureMaxAnisotropy = 2.0;
+
+ ctx->Const.MaxDrawBuffers = 1;
+
_tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12,
18 * sizeof(GLfloat));
diff --git a/src/mesa/drivers/dri/i915/i830_context.h b/src/mesa/drivers/dri/i915/i830_context.h
index 1bdb32049d..f73cbbf88b 100644
--- a/src/mesa/drivers/dri/i915/i830_context.h
+++ b/src/mesa/drivers/dri/i915/i830_context.h
@@ -40,6 +40,7 @@
#define I830_UPLOAD_BUFFERS 0x2
#define I830_UPLOAD_STIPPLE 0x4
#define I830_UPLOAD_INVARIENT 0x8
+#define I830_UPLOAD_RASTER_RULES 0x10
#define I830_UPLOAD_TEX(i) (0x10<<(i))
#define I830_UPLOAD_TEXBLEND(i) (0x100<<(i))
#define I830_UPLOAD_TEX_ALL (0x0f0)
@@ -99,6 +100,11 @@
#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */
+enum {
+ I830_RASTER_RULES,
+ I830_RASTER_RULES_SIZE
+};
+
struct i830_texture_object
{
struct intel_texture_object intel;
@@ -112,6 +118,7 @@ struct i830_hw_state
GLuint Ctx[I830_CTX_SETUP_SIZE];
GLuint Buffer[I830_DEST_SETUP_SIZE];
GLuint Stipple[I830_STP_SETUP_SIZE];
+ GLuint RasterRules[I830_RASTER_RULES_SIZE];
GLuint Tex[I830_TEX_UNITS][I830_TEX_SETUP_SIZE];
GLuint TexBlend[I830_TEX_UNITS][I830_TEXBLEND_SIZE];
GLuint TexBlendWordsUsed[I830_TEX_UNITS];
@@ -197,6 +204,7 @@ extern void i830InitStateFuncs(struct dd_function_table *functions);
extern void i830EmitState(struct i830_context *i830);
extern void i830InitState(struct i830_context *i830);
+extern void i830_update_provoking_vertex(GLcontext *ctx);
/* i830_metaops.c
*/
diff --git a/src/mesa/drivers/dri/i915/i830_reg.h b/src/mesa/drivers/dri/i915/i830_reg.h
index d210c2d08e..ae1317029a 100644
--- a/src/mesa/drivers/dri/i915/i830_reg.h
+++ b/src/mesa/drivers/dri/i915/i830_reg.h
@@ -48,19 +48,6 @@
#define AA_LINE_ENABLE ((1<<1) | 1)
#define AA_LINE_DISABLE (1<<1)
-#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
-/* Dword 1 */
-#define BUF_3D_ID_COLOR_BACK (0x3<<24)
-#define BUF_3D_ID_DEPTH (0x7<<24)
-#define BUF_3D_USE_FENCE (1<<23)
-#define BUF_3D_TILED_SURFACE (1<<22)
-#define BUF_3D_TILE_WALK_X 0
-#define BUF_3D_TILE_WALK_Y (1<<21)
-#define BUF_3D_PITCH(x) (((x)/4)<<2)
-/* Dword 2 */
-#define BUF_3D_ADDR(x) ((x) & ~0x3)
-
-
#define _3DSTATE_COLOR_FACTOR_CMD (CMD_3D | (0x1d<<24) | (0x1<<16))
#define _3DSTATE_COLOR_FACTOR_N_CMD(stage) (CMD_3D | (0x1d<<24) | \
@@ -433,8 +420,11 @@
#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8)
#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5)
#define ENABLE_TRI_STRIP_PROVOKE_VRTX (1<<2)
+#define LINE_STRIP_PROVOKE_VRTX_MASK (3<<6)
#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6)
+#define TRI_FAN_PROVOKE_VRTX_MASK (3<<3)
#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3)
+#define TRI_STRIP_PROVOKE_VRTX_MASK (3<<0)
#define TRI_STRIP_PROVOKE_VRTX(x) (x)
/* _3DSTATE_SCISSOR_ENABLE, p200 */
diff --git a/src/mesa/drivers/dri/i915/i830_state.c b/src/mesa/drivers/dri/i915/i830_state.c
index d9cad0c4bf..645ebe3057 100644
--- a/src/mesa/drivers/dri/i915/i830_state.c
+++ b/src/mesa/drivers/dri/i915/i830_state.c
@@ -39,6 +39,7 @@
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_fbo.h"
+#include "intel_buffers.h"
#include "i830_context.h"
#include "i830_reg.h"
@@ -446,6 +447,24 @@ i830DepthMask(GLcontext * ctx, GLboolean flag)
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
}
+/** Called from ctx->Driver.Viewport() */
+static void
+i830Viewport(GLcontext * ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ intelCalcViewport(ctx);
+
+ intel_viewport(ctx, x, y, width, height);
+}
+
+
+/** Called from ctx->Driver.DepthRange() */
+static void
+i830DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
+{
+ intelCalcViewport(ctx);
+}
+
/* =============================================================
* Polygon stipple
*
@@ -1028,6 +1047,16 @@ i830_init_packets(struct i830_context *i830)
TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
TEXBIND_SET0(TEXCOORDSRC_VTXSET_0));
+ i830->state.RasterRules[I830_RASTER_RULES] = (_3DSTATE_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ ENABLE_TRI_STRIP_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) |
+ TRI_STRIP_PROVOKE_VRTX(2));
+
i830->state.Stipple[I830_STPREG_ST0] = _3DSTATE_STIPPLE;
@@ -1039,6 +1068,27 @@ i830_init_packets(struct i830_context *i830)
i830->state.Buffer[I830_DESTREG_SR2] = 0;
}
+void
+i830_update_provoking_vertex(GLcontext * ctx)
+{
+ struct i830_context *i830 = i830_context(ctx);
+
+ I830_STATECHANGE(i830, I830_UPLOAD_RASTER_RULES);
+ i830->state.RasterRules[I830_RASTER_RULES] &= ~(LINE_STRIP_PROVOKE_VRTX_MASK |
+ TRI_FAN_PROVOKE_VRTX_MASK |
+ TRI_STRIP_PROVOKE_VRTX_MASK);
+
+ /* _NEW_LIGHT */
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION) {
+ i830->state.RasterRules[I830_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) |
+ TRI_STRIP_PROVOKE_VRTX(2));
+ } else {
+ i830->state.RasterRules[I830_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(0) |
+ TRI_FAN_PROVOKE_VRTX(1) |
+ TRI_STRIP_PROVOKE_VRTX(0));
+ }
+}
void
i830InitStateFuncs(struct dd_function_table *functions)
@@ -1064,6 +1114,8 @@ i830InitStateFuncs(struct dd_function_table *functions)
functions->StencilFuncSeparate = i830StencilFuncSeparate;
functions->StencilMaskSeparate = i830StencilMaskSeparate;
functions->StencilOpSeparate = i830StencilOpSeparate;
+ functions->DepthRange = i830DepthRange;
+ functions->Viewport = i830Viewport;
}
void
@@ -1080,6 +1132,7 @@ i830InitState(struct i830_context *i830)
i830->current = &i830->state;
i830->state.emitted = 0;
i830->state.active = (I830_UPLOAD_INVARIENT |
+ I830_UPLOAD_RASTER_RULES |
I830_UPLOAD_TEXBLEND(0) |
I830_UPLOAD_STIPPLE |
I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS);
diff --git a/src/mesa/drivers/dri/i915/i830_tex.c b/src/mesa/drivers/dri/i915/i830_tex.c
deleted file mode 100644
index 34ac42a78e..0000000000
--- a/src/mesa/drivers/dri/i915/i830_tex.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "main/imports.h"
-#include "main/simple_list.h"
-#include "main/enums.h"
-#include "main/image.h"
-#include "main/mm.h"
-#include "main/texstore.h"
-#include "main/texformat.h"
-#include "swrast/swrast.h"
-
-#include "texmem.h"
-
-#include "i830_context.h"
-#include "i830_reg.h"
-
-
-
-static void
-i830TexEnv(GLcontext * ctx, GLenum target,
- GLenum pname, const GLfloat * param)
-{
-
- switch (pname) {
- case GL_TEXTURE_ENV_COLOR:
- case GL_TEXTURE_ENV_MODE:
- case GL_COMBINE_RGB:
- case GL_COMBINE_ALPHA:
- case GL_SOURCE0_RGB:
- case GL_SOURCE1_RGB:
- case GL_SOURCE2_RGB:
- case GL_SOURCE0_ALPHA:
- case GL_SOURCE1_ALPHA:
- case GL_SOURCE2_ALPHA:
- case GL_OPERAND0_RGB:
- case GL_OPERAND1_RGB:
- case GL_OPERAND2_RGB:
- case GL_OPERAND0_ALPHA:
- case GL_OPERAND1_ALPHA:
- case GL_OPERAND2_ALPHA:
- case GL_RGB_SCALE:
- case GL_ALPHA_SCALE:
- break;
-
- case GL_TEXTURE_LOD_BIAS:{
- struct i830_context *i830 = i830_context(ctx);
- GLuint unit = ctx->Texture.CurrentUnit;
- int b = (int) ((*param) * 16.0);
- if (b > 63)
- b = 63;
- if (b < -64)
- b = -64;
- I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
- i830->lodbias_tm0s3[unit] =
- ((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK);
- break;
- }
-
- default:
- break;
- }
-}
-
-
-
-
-void
-i830InitTextureFuncs(struct dd_function_table *functions)
-{
-/*
- functions->TexEnv = i830TexEnv;
-*/
-}
diff --git a/src/mesa/drivers/dri/i915/i830_texstate.c b/src/mesa/drivers/dri/i915/i830_texstate.c
index c718bb0055..6f998fa6f7 100644
--- a/src/mesa/drivers/dri/i915/i830_texstate.c
+++ b/src/mesa/drivers/dri/i915/i830_texstate.c
@@ -38,7 +38,7 @@
static GLuint
-translate_texture_format(GLuint mesa_format)
+translate_texture_format(GLuint mesa_format, GLuint internal_format)
{
switch (mesa_format) {
case MESA_FORMAT_L8:
@@ -56,7 +56,10 @@ translate_texture_format(GLuint mesa_format)
case MESA_FORMAT_ARGB4444:
return MAPSURF_16BIT | MT_16BIT_ARGB4444;
case MESA_FORMAT_ARGB8888:
- return MAPSURF_32BIT | MT_32BIT_ARGB8888;
+ if (internal_format == GL_RGB)
+ return MAPSURF_32BIT | MT_32BIT_XRGB8888;
+ else
+ return MAPSURF_32BIT | MT_32BIT_ARGB8888;
case MESA_FORMAT_YCBCR_REV:
return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
case MESA_FORMAT_YCBCR:
@@ -119,6 +122,7 @@ i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
struct gl_texture_image *firstImage;
GLuint *state = i830->state.Tex[unit], format, pitch;
GLint lodbias;
+ GLubyte border[4];
memset(state, 0, sizeof(state));
@@ -162,21 +166,24 @@ i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
0, intelObj->
firstLevel);
- format = translate_texture_format(firstImage->TexFormat->MesaFormat);
+ format = translate_texture_format(firstImage->TexFormat->MesaFormat,
+ firstImage->InternalFormat);
pitch = intelObj->mt->pitch * intelObj->mt->cpp;
}
state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
(LOAD_TEXTURE_MAP0 << unit) | 4);
-/* state[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | */
-/* t->intel.TextureOffset); */
-
-
state[I830_TEXREG_TM0S1] =
(((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format);
+ if (intelObj->mt->region->tiling != I915_TILING_NONE) {
+ state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE;
+ if (intelObj->mt->region->tiling == I915_TILING_Y)
+ state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK;
+ }
+
state[I830_TEXREG_TM0S2] =
((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);
@@ -290,11 +297,16 @@ i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
(ws)));
}
+ /* convert border color from float to ubyte */
+ CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor[3]);
- state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0],
- tObj->_BorderChan[1],
- tObj->_BorderChan[2],
- tObj->_BorderChan[3]);
+ state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(border[0],
+ border[1],
+ border[2],
+ border[3]);
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c
index 8fc8aa5f90..983f6724c9 100644
--- a/src/mesa/drivers/dri/i915/i830_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i830_vtbl.c
@@ -26,12 +26,14 @@
**************************************************************************/
#include "glapi/glapi.h"
+#include "main/texformat.h"
#include "i830_context.h"
#include "i830_reg.h"
#include "intel_batchbuffer.h"
#include "intel_regions.h"
#include "intel_tris.h"
+#include "intel_fbo.h"
#include "tnl/t_context.h"
#include "tnl/t_vertex.h"
@@ -297,7 +299,7 @@ i830_emit_invarient_state(struct intel_context *intel)
{
BATCH_LOCALS;
- BEGIN_BATCH(30, IGNORE_CLIPRECTS);
+ BEGIN_BATCH(29, IGNORE_CLIPRECTS);
OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
OUT_BATCH(0);
@@ -349,15 +351,6 @@ i830_emit_invarient_state(struct intel_context *intel)
OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3));
- OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
- ENABLE_POINT_RASTER_RULE |
- OGL_POINT_RASTER_RULE |
- ENABLE_LINE_STRIP_PROVOKE_VRTX |
- ENABLE_TRI_FAN_PROVOKE_VRTX |
- ENABLE_TRI_STRIP_PROVOKE_VRTX |
- LINE_STRIP_PROVOKE_VRTX(1) |
- TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2));
-
OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
@@ -392,6 +385,9 @@ get_state_size(struct i830_hw_state *state)
if (dirty & I830_UPLOAD_INVARIENT)
sz += 40 * sizeof(int);
+ if (dirty & I830_UPLOAD_RASTER_RULES)
+ sz += sizeof(state->RasterRules);
+
if (dirty & I830_UPLOAD_CTX)
sz += sizeof(state->Ctx);
@@ -422,10 +418,10 @@ i830_emit_state(struct intel_context *intel)
struct i830_hw_state *state = i830->current;
int i, count;
GLuint dirty;
- GET_CURRENT_CONTEXT(ctx);
- BATCH_LOCALS;
dri_bo *aper_array[3 + I830_TEX_UNITS];
int aper_count;
+ GET_CURRENT_CONTEXT(ctx);
+ BATCH_LOCALS;
/* We don't hold the lock at this point, so want to make sure that
* there won't be a buffer wrap between the state emits and the primitive
@@ -484,6 +480,11 @@ i830_emit_state(struct intel_context *intel)
i830_emit_invarient_state(intel);
}
+ if (dirty & I830_UPLOAD_RASTER_RULES) {
+ DBG("I830_UPLOAD_RASTER_RULES:\n");
+ emit(intel, state->RasterRules, sizeof(state->RasterRules));
+ }
+
if (dirty & I830_UPLOAD_CTX) {
DBG("I830_UPLOAD_CTX:\n");
emit(intel, state->Ctx, sizeof(state->Ctx));
@@ -550,7 +551,7 @@ i830_emit_state(struct intel_context *intel)
if (state->tex_buffer[i]) {
OUT_RELOC(state->tex_buffer[i],
I915_GEM_DOMAIN_SAMPLER, 0,
- state->tex_offset[i] | TM0S0_USE_FENCE);
+ state->tex_offset[i]);
}
else if (state == &i830->meta) {
assert(i == 0);
@@ -614,6 +615,8 @@ i830_state_draw_region(struct intel_context *intel,
{
struct i830_context *i830 = i830_context(&intel->ctx);
GLcontext *ctx = &intel->ctx;
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
GLuint value;
ASSERT(state == &i830->state || state == &i830->meta);
@@ -630,34 +633,38 @@ i830_state_draw_region(struct intel_context *intel,
/*
* Set stride/cpp values
*/
- if (color_region) {
- state->Buffer[I830_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
- state->Buffer[I830_DESTREG_CBUFADDR1] =
- (BUF_3D_ID_COLOR_BACK |
- BUF_3D_PITCH(color_region->pitch * color_region->cpp) |
- BUF_3D_USE_FENCE);
- }
+ i915_set_buf_info_for_region(&state->Buffer[I830_DESTREG_CBUFADDR0],
+ color_region, BUF_3D_ID_COLOR_BACK);
- if (depth_region) {
- state->Buffer[I830_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
- state->Buffer[I830_DESTREG_DBUFADDR1] =
- (BUF_3D_ID_DEPTH |
- BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) |
- BUF_3D_USE_FENCE);
- }
+ i915_set_buf_info_for_region(&state->Buffer[I830_DESTREG_DBUFADDR0],
+ depth_region, BUF_3D_ID_DEPTH);
/*
* Compute/set I830_DESTREG_DV1 value
*/
value = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | DEPTH_IS_Z); /* .5 */
-
- if (color_region && color_region->cpp == 4) {
- value |= DV_PF_8888;
- }
- else {
- value |= DV_PF_565;
+
+ if (irb != NULL) {
+ switch (irb->texformat->MesaFormat) {
+ case MESA_FORMAT_ARGB8888:
+ value |= DV_PF_8888;
+ break;
+ case MESA_FORMAT_RGB565:
+ value |= DV_PF_565;
+ break;
+ case MESA_FORMAT_ARGB1555:
+ value |= DV_PF_1555;
+ break;
+ case MESA_FORMAT_ARGB4444:
+ value |= DV_PF_4444;
+ break;
+ default:
+ _mesa_problem(ctx, "Bad renderbuffer format: %d\n",
+ irb->texformat->MesaFormat);
+ }
}
+
if (depth_region && depth_region->cpp == 4) {
value |= DEPTH_FRMT_24_FIXED_8_OTHER;
}
@@ -700,26 +707,6 @@ i830_set_draw_region(struct intel_context *intel,
i830_state_draw_region(intel, &i830->state, color_regions[0], depth_region);
}
-#if 0
-static void
-i830_update_color_z_regions(intelContextPtr intel,
- const intelRegion * colorRegion,
- const intelRegion * depthRegion)
-{
- i830ContextPtr i830 = I830_CONTEXT(intel);
-
- i830->state.Buffer[I830_DESTREG_CBUFADDR1] =
- (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) |
- BUF_3D_USE_FENCE);
- i830->state.Buffer[I830_DESTREG_CBUFADDR2] = colorRegion->offset;
-
- i830->state.Buffer[I830_DESTREG_DBUFADDR1] =
- (BUF_3D_ID_DEPTH | BUF_3D_PITCH(depthRegion->pitch) | BUF_3D_USE_FENCE);
- i830->state.Buffer[I830_DESTREG_DBUFADDR2] = depthRegion->offset;
-}
-#endif
-
-
/* This isn't really handled at the moment.
*/
static void
@@ -750,9 +737,10 @@ i830_assert_not_dirty( struct intel_context *intel )
}
static void
-i830_note_unlock( struct intel_context *intel )
+i830_invalidate_state(struct intel_context *intel, GLuint new_state)
{
- /* nothing */
+ if (new_state & _NEW_LIGHT)
+ i830_update_provoking_vertex(&intel->ctx);
}
void
@@ -769,6 +757,6 @@ i830InitVtbl(struct i830_context *i830)
i830->intel.vtbl.render_start = i830_render_start;
i830->intel.vtbl.render_prevalidate = i830_render_prevalidate;
i830->intel.vtbl.assert_not_dirty = i830_assert_not_dirty;
- i830->intel.vtbl.note_unlock = i830_note_unlock;
i830->intel.vtbl.finish_batch = intel_finish_vb;
+ i830->intel.vtbl.invalidate_state = i830_invalidate_state;
}
diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c
index 3d6af38057..3ab7d682ee 100644
--- a/src/mesa/drivers/dri/i915/i915_context.c
+++ b/src/mesa/drivers/dri/i915/i915_context.c
@@ -27,6 +27,7 @@
#include "i915_context.h"
#include "main/imports.h"
+#include "main/macros.h"
#include "intel_tex.h"
#include "intel_tris.h"
#include "tnl/t_context.h"
@@ -50,16 +51,6 @@
* Mesa's Driver Functions
***************************************/
-static const struct dri_extension i915_extensions[] = {
- {"GL_ARB_depth_texture", NULL},
- {"GL_ARB_fragment_program", NULL},
- {"GL_ARB_shadow", NULL},
- {"GL_ARB_texture_non_power_of_two", NULL},
- {"GL_ATI_texture_env_combine3", NULL},
- {"GL_EXT_shadow_funcs", NULL},
- {NULL, NULL}
-};
-
/* Override intel default.
*/
static void
@@ -83,8 +74,12 @@ i915InvalidateState(GLcontext * ctx, GLuint new_state)
p->params_uptodate = 0;
}
- if (new_state & (_NEW_FOG | _NEW_HINT | _NEW_PROGRAM))
+ if (new_state & (_NEW_FOG | _NEW_HINT | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS))
i915_update_fog(ctx);
+ if (new_state & (_NEW_STENCIL | _NEW_BUFFERS | _NEW_POLYGON))
+ i915_update_stencil(ctx);
+ if (new_state & (_NEW_LIGHT))
+ i915_update_provoking_vertex(ctx);
}
@@ -93,7 +88,6 @@ i915InitDriverFunctions(struct dd_function_table *functions)
{
intelInitDriverFunctions(functions);
i915InitStateFunctions(functions);
- i915InitTextureFuncs(functions);
i915InitFragProgFuncs(functions);
functions->UpdateState = i915InvalidateState;
}
@@ -129,6 +123,8 @@ i915CreateContext(const __GLcontextModes * mesaVis,
return GL_FALSE;
}
+ _math_matrix_ctr(&intel->ViewportMatrix);
+
/* Initialize swrast, tnl driver tables: */
intelInitSpanFuncs(ctx);
intelInitTriFuncs(ctx);
@@ -154,6 +150,8 @@ i915CreateContext(const __GLcontextModes * mesaVis,
ctx->Const.MaxTextureRectSize = (1 << 11);
ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
+ ctx->Const.MaxTextureMaxAnisotropy = 4.0;
+
/* GL_ARB_fragment_program limits - don't think Mesa actually
* validates programs against these, and in any case one ARB
* instruction can translate to more than one HW instruction, so
@@ -169,11 +167,13 @@ i915CreateContext(const __GLcontextModes * mesaVis,
ctx->Const.FragmentProgram.MaxNativeTexIndirections =
I915_MAX_TEX_INDIRECT;
ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */
+ ctx->Const.FragmentProgram.MaxEnvParams =
+ MIN2(ctx->Const.FragmentProgram.MaxNativeParameters,
+ ctx->Const.FragmentProgram.MaxEnvParams);
ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
- driInitExtensions(ctx, i915_extensions, GL_FALSE);
-
+ ctx->Const.MaxDrawBuffers = 1;
_tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12,
36 * sizeof(GLfloat));
diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h
index 87bbf5f927..8de4a9d0d3 100644
--- a/src/mesa/drivers/dri/i915/i915_context.h
+++ b/src/mesa/drivers/dri/i915/i915_context.h
@@ -48,6 +48,7 @@
#define I915_UPLOAD_FOG 0x20
#define I915_UPLOAD_INVARIENT 0x40
#define I915_UPLOAD_DEFAULTS 0x80
+#define I915_UPLOAD_RASTER_RULES 0x100
#define I915_UPLOAD_TEX(i) (0x00010000<<(i))
#define I915_UPLOAD_TEX_ALL (0x00ff0000)
#define I915_UPLOAD_TEX_0_SHIFT 16
@@ -82,7 +83,9 @@
#define I915_CTXREG_IAB 6
#define I915_CTXREG_BLENDCOLOR0 7
#define I915_CTXREG_BLENDCOLOR1 8
-#define I915_CTX_SETUP_SIZE 9
+#define I915_CTXREG_BF_STENCIL_OPS 9
+#define I915_CTXREG_BF_STENCIL_MASKS 10
+#define I915_CTX_SETUP_SIZE 11
#define I915_FOGREG_COLOR 0
#define I915_FOGREG_MODE0 1
@@ -110,6 +113,10 @@
#define I915_DEFREG_Z1 5
#define I915_DEF_SETUP_SIZE 6
+enum {
+ I915_RASTER_RULES,
+ I915_RASTER_RULES_SETUP_SIZE,
+};
#define I915_MAX_CONSTANT 32
#define I915_CONSTANT_SIZE (2+(4*I915_MAX_CONSTANT))
@@ -206,6 +213,7 @@ struct i915_hw_state
GLuint Stipple[I915_STP_SETUP_SIZE];
GLuint Fog[I915_FOG_SETUP_SIZE];
GLuint Defaults[I915_DEF_SETUP_SIZE];
+ GLuint RasterRules[I915_RASTER_RULES_SETUP_SIZE];
GLuint Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE];
GLuint Constant[I915_CONSTANT_SIZE];
GLuint ConstantSize;
@@ -321,6 +329,8 @@ extern void i915_print_ureg(const char *msg, GLuint ureg);
extern void i915InitStateFunctions(struct dd_function_table *functions);
extern void i915InitState(struct i915_context *i915);
extern void i915_update_fog(GLcontext * ctx);
+extern void i915_update_stencil(GLcontext * ctx);
+extern void i915_update_provoking_vertex(GLcontext *ctx);
/*======================================================================
diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
index f091d600c3..2db10c60e9 100644
--- a/src/mesa/drivers/dri/i915/i915_fragprog.c
+++ b/src/mesa/drivers/dri/i915/i915_fragprog.c
@@ -162,12 +162,12 @@ src_vector(struct i915_fragment_program *p,
GET_SWZ(source->Swizzle, 1),
GET_SWZ(source->Swizzle, 2), GET_SWZ(source->Swizzle, 3));
- if (source->NegateBase)
+ if (source->Negate)
src = negate(src,
- GET_BIT(source->NegateBase, 0),
- GET_BIT(source->NegateBase, 1),
- GET_BIT(source->NegateBase, 2),
- GET_BIT(source->NegateBase, 3));
+ GET_BIT(source->Negate, 0),
+ GET_BIT(source->Negate, 1),
+ GET_BIT(source->Negate, 2),
+ GET_BIT(source->Negate, 3));
return src;
}
@@ -180,9 +180,9 @@ get_result_vector(struct i915_fragment_program *p,
switch (inst->DstReg.File) {
case PROGRAM_OUTPUT:
switch (inst->DstReg.Index) {
- case FRAG_RESULT_COLR:
+ case FRAG_RESULT_COLOR:
return UREG(REG_TYPE_OC, 0);
- case FRAG_RESULT_DEPR:
+ case FRAG_RESULT_DEPTH:
p->depth_written = 1;
return UREG(REG_TYPE_OD, 0);
default:
@@ -323,7 +323,8 @@ upload_program(struct i915_fragment_program *p)
p->ctx->FragmentProgram._Current;
const struct prog_instruction *inst = program->Base.Instructions;
-/* _mesa_debug_fp_inst(program->Base.NumInstructions, inst); */
+ if (INTEL_DEBUG & DEBUG_WM)
+ _mesa_print_program(&program->Base);
/* Is this a parse-failed program? Ensure a valid program is
* loaded, as the flagging of an error isn't sufficient to stop
@@ -1049,9 +1050,6 @@ i915ProgramStringNotify(GLcontext * ctx,
_mesa_append_fog_code(ctx, &p->FragProg);
p->FragProg.FogOption = GL_NONE;
}
-
- if (INTEL_DEBUG & DEBUG_STATE)
- _mesa_print_program(prog);
}
_tnl_program_string(ctx, target, prog);
diff --git a/src/mesa/drivers/dri/i915/i915_reg.h b/src/mesa/drivers/dri/i915/i915_reg.h
index 8891e11c6f..b5fa7fddb9 100644
--- a/src/mesa/drivers/dri/i915/i915_reg.h
+++ b/src/mesa/drivers/dri/i915/i915_reg.h
@@ -86,27 +86,15 @@
#define BFM_ENABLE_STENCIL_WRITE_MASK (1<<16)
#define BFM_STENCIL_TEST_MASK_SHIFT 8
#define BFM_STENCIL_TEST_MASK_MASK (0xff<<8)
+#define BFM_STENCIL_TEST_MASK(x) (((x)&0xff) << 8)
#define BFM_STENCIL_WRITE_MASK_SHIFT 0
#define BFM_STENCIL_WRITE_MASK_MASK (0xff<<0)
+#define BFM_STENCIL_WRITE_MASK(x) ((x)&0xff)
/* 3DSTATE_BIN_CONTROL p141 */
-/* p143 */
-#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
-/* Dword 1 */
-#define BUF_3D_ID_COLOR_BACK (0x3<<24)
-#define BUF_3D_ID_DEPTH (0x7<<24)
-#define BUF_3D_USE_FENCE (1<<23)
-#define BUF_3D_TILED_SURFACE (1<<22)
-#define BUF_3D_TILE_WALK_X 0
-#define BUF_3D_TILE_WALK_Y (1<<21)
-#define BUF_3D_PITCH(x) (((x)/4)<<2)
-/* Dword 2 */
-#define BUF_3D_ADDR(x) ((x) & ~0x3)
-
-
/* 3DSTATE_CHROMA_KEY */
/* 3DSTATE_CLEAR_PARAMETERS, p150 */
@@ -155,6 +143,7 @@
/* p161 */
#define _3DSTATE_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16))
/* Dword 1 */
+#define CLASSIC_EARLY_DEPTH (1<<31)
#define TEX_DEFAULT_COLOR_OGL (0<<30)
#define TEX_DEFAULT_COLOR_D3D (1<<30)
#define ZR_EARLY_DEPTH (1<<29)
@@ -308,7 +297,9 @@
#define TEXKILL_4D (1<<9)
#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8)
#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5)
+#define LINE_STRIP_PROVOKE_VRTX_MASK (3 << 6)
#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6)
+#define TRI_FAN_PROVOKE_VRTX_MASK (3 << 3)
#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3)
/* _3DSTATE_SCISSOR_ENABLE, p256 */
diff --git a/src/mesa/drivers/dri/i915/i915_state.c b/src/mesa/drivers/dri/i915/i915_state.c
index a53f120a81..b60efea75b 100644
--- a/src/mesa/drivers/dri/i915/i915_state.c
+++ b/src/mesa/drivers/dri/i915/i915_state.c
@@ -41,79 +41,126 @@
#include "intel_fbo.h"
#include "intel_screen.h"
#include "intel_batchbuffer.h"
+#include "intel_buffers.h"
#include "i915_context.h"
#include "i915_reg.h"
#define FILE_DEBUG_FLAG DEBUG_STATE
-static void
-i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref,
- GLuint mask)
+void
+i915_update_stencil(GLcontext * ctx)
{
struct i915_context *i915 = I915_CONTEXT(ctx);
- int test = intel_translate_compare_func(func);
-
- mask = mask & 0xff;
+ GLuint front_ref, front_writemask, front_mask;
+ 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;
- DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
- _mesa_lookup_enum_by_nr(func), ref, mask);
+ I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+ /* The 915 considers CW to be "front" for two-sided stencil, so choose
+ * appropriately.
+ */
+ /* _NEW_POLYGON | _NEW_STENCIL */
+ if (ctx->Polygon.FrontFace == GL_CW) {
+ front_ref = ctx->Stencil.Ref[0];
+ front_mask = ctx->Stencil.ValueMask[0];
+ front_writemask = ctx->Stencil.WriteMask[0];
+ front_func = ctx->Stencil.Function[0];
+ front_fail = ctx->Stencil.FailFunc[0];
+ front_pass_z_fail = ctx->Stencil.ZFailFunc[0];
+ front_pass_z_pass = ctx->Stencil.ZPassFunc[0];
+ back_ref = ctx->Stencil.Ref[ctx->Stencil._BackFace];
+ back_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace];
+ back_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace];
+ back_func = ctx->Stencil.Function[ctx->Stencil._BackFace];
+ back_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace];
+ back_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace];
+ back_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace];
+ } else {
+ front_ref = ctx->Stencil.Ref[ctx->Stencil._BackFace];
+ front_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace];
+ front_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace];
+ front_func = ctx->Stencil.Function[ctx->Stencil._BackFace];
+ front_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace];
+ front_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace];
+ front_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace];
+ back_ref = ctx->Stencil.Ref[0];
+ back_mask = ctx->Stencil.ValueMask[0];
+ back_writemask = ctx->Stencil.WriteMask[0];
+ back_func = ctx->Stencil.Function[0];
+ back_fail = ctx->Stencil.FailFunc[0];
+ back_pass_z_fail = ctx->Stencil.ZFailFunc[0];
+ back_pass_z_pass = ctx->Stencil.ZPassFunc[0];
+ }
- I915_STATECHANGE(i915, I915_UPLOAD_CTX);
- i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
+ /* 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 |
- STENCIL_TEST_MASK(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_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 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);
+ } else {
+ i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= ~BFO_STENCIL_TWO_SIDE;
+ }
+}
- i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) |
- (test <<
- S5_STENCIL_TEST_FUNC_SHIFT));
+static void
+i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref,
+ GLuint mask)
+{
}
static void
i915StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask)
{
- struct i915_context *i915 = I915_CONTEXT(ctx);
-
- DBG("%s : mask 0x%x\n", __FUNCTION__, mask);
-
- mask = mask & 0xff;
-
- I915_STATECHANGE(i915, I915_UPLOAD_CTX);
- i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
- i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
- STENCIL_WRITE_MASK(mask));
}
-
static void
i915StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail,
GLenum zpass)
{
- struct i915_context *i915 = I915_CONTEXT(ctx);
- int fop = intel_translate_stencil_op(fail);
- int dfop = intel_translate_stencil_op(zfail);
- int dpop = intel_translate_stencil_op(zpass);
-
-
- DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
- _mesa_lookup_enum_by_nr(fail),
- _mesa_lookup_enum_by_nr(zfail), _mesa_lookup_enum_by_nr(zpass));
-
- I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-
- i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
- S5_STENCIL_PASS_Z_FAIL_MASK |
- S5_STENCIL_PASS_Z_PASS_MASK);
-
- i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) |
- (dfop <<
- S5_STENCIL_PASS_Z_FAIL_SHIFT) |
- (dpop <<
- S5_STENCIL_PASS_Z_PASS_SHIFT));
}
static void
@@ -301,6 +348,65 @@ i915DepthMask(GLcontext * ctx, GLboolean flag)
i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_WRITE_ENABLE;
}
+
+
+/**
+ * Update the viewport transformation matrix. Depends on:
+ * - viewport pos/size
+ * - depthrange
+ * - window pos/size or FBO size
+ */
+void
+intelCalcViewport(GLcontext * ctx)
+{
+ struct intel_context *intel = intel_context(ctx);
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+ const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+ GLfloat *m = intel->ViewportMatrix.m;
+ GLfloat yScale, yBias;
+
+ if (ctx->DrawBuffer->Name) {
+ /* User created FBO */
+ /* y=0=bottom */
+ yScale = 1.0;
+ yBias = 0.0;
+ }
+ else {
+ /* window buffer, y=0=top */
+ yScale = -1.0;
+ yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F;
+ }
+
+ m[MAT_SX] = v[MAT_SX];
+ m[MAT_TX] = v[MAT_TX];
+
+ m[MAT_SY] = v[MAT_SY] * yScale;
+ m[MAT_TY] = v[MAT_TY] * yScale + yBias;
+
+ m[MAT_SZ] = v[MAT_SZ] * depthScale;
+ m[MAT_TZ] = v[MAT_TZ] * depthScale;
+}
+
+
+/** Called from ctx->Driver.Viewport() */
+static void
+i915Viewport(GLcontext * ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ intelCalcViewport(ctx);
+
+ intel_viewport(ctx, x, y, width, height);
+}
+
+
+/** Called from ctx->Driver.DepthRange() */
+static void
+i915DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
+{
+ intelCalcViewport(ctx);
+}
+
+
/* =============================================================
* Polygon stipple
*
@@ -885,6 +991,17 @@ i915_init_packets(struct i915_context *i915)
_3DSTATE_CONST_BLEND_COLOR_CMD;
i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0;
+ i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] =
+ _3DSTATE_BACKFACE_STENCIL_MASKS |
+ BFM_ENABLE_STENCIL_TEST_MASK |
+ BFM_ENABLE_STENCIL_WRITE_MASK |
+ (0xff << BFM_STENCIL_WRITE_MASK_SHIFT) |
+ (0xff << BFM_STENCIL_TEST_MASK_SHIFT);
+ i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] =
+ _3DSTATE_BACKFACE_STENCIL_OPS |
+ BFO_ENABLE_STENCIL_REF |
+ BFO_ENABLE_STENCIL_FUNCS |
+ BFO_ENABLE_STENCIL_TWO_SIDE;
}
{
@@ -916,6 +1033,13 @@ i915_init_packets(struct i915_context *i915)
i915->state.Buffer[I915_DESTREG_SR2] = 0;
}
+ i915->state.RasterRules[I915_RASTER_RULES] = _3DSTATE_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D;
#if 0
{
@@ -936,7 +1060,33 @@ i915_init_packets(struct i915_context *i915)
i915->state.active = (I915_UPLOAD_PROGRAM |
I915_UPLOAD_STIPPLE |
I915_UPLOAD_CTX |
- I915_UPLOAD_BUFFERS | I915_UPLOAD_INVARIENT);
+ I915_UPLOAD_BUFFERS |
+ I915_UPLOAD_INVARIENT |
+ I915_UPLOAD_RASTER_RULES);
+}
+
+void
+i915_update_provoking_vertex(GLcontext * ctx)
+{
+ struct i915_context *i915 = I915_CONTEXT(ctx);
+
+ I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+ i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_TRISTRIP_PV_MASK);
+
+ I915_STATECHANGE(i915, I915_UPLOAD_RASTER_RULES);
+ i915->state.RasterRules[I915_RASTER_RULES] &= ~(LINE_STRIP_PROVOKE_VRTX_MASK |
+ TRI_FAN_PROVOKE_VRTX_MASK);
+
+ /* _NEW_LIGHT */
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION) {
+ i915->state.RasterRules[I915_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2));
+ i915->state.Ctx[I915_CTXREG_LIS6] |= (2 << S6_TRISTRIP_PV_SHIFT);
+ } else {
+ i915->state.RasterRules[I915_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(0) |
+ TRI_FAN_PROVOKE_VRTX(1));
+ i915->state.Ctx[I915_CTXREG_LIS6] |= (0 << S6_TRISTRIP_PV_SHIFT);
+ }
}
void
@@ -964,6 +1114,8 @@ i915InitStateFunctions(struct dd_function_table *functions)
functions->StencilFuncSeparate = i915StencilFuncSeparate;
functions->StencilMaskSeparate = i915StencilMaskSeparate;
functions->StencilOpSeparate = i915StencilOpSeparate;
+ functions->DepthRange = i915DepthRange;
+ functions->Viewport = i915Viewport;
}
diff --git a/src/mesa/drivers/dri/i915/i915_tex_layout.c b/src/mesa/drivers/dri/i915/i915_tex_layout.c
index d44a2f47b3..d9588e5b56 100644
--- a/src/mesa/drivers/dri/i915/i915_tex_layout.c
+++ b/src/mesa/drivers/dri/i915/i915_tex_layout.c
@@ -55,6 +55,17 @@ static GLint step_offsets[6][2] = {
[FACE_NEG_Z] = {-1, 1},
};
+
+static GLint bottom_offsets[6] = {
+ [FACE_POS_X] = 16 + 0 * 8,
+ [FACE_POS_Y] = 16 + 1 * 8,
+ [FACE_POS_Z] = 16 + 2 * 8,
+ [FACE_NEG_X] = 16 + 3 * 8,
+ [FACE_NEG_Y] = 16 + 4 * 8,
+ [FACE_NEG_Z] = 16 + 5 * 8,
+};
+
+
/**
* Cube texture map layout for i830M-GM915.
*
@@ -101,7 +112,8 @@ static GLint step_offsets[6][2] = {
*/
static void
i915_miptree_layout_cube(struct intel_context *intel,
- struct intel_mipmap_tree * mt)
+ struct intel_mipmap_tree * mt,
+ uint32_t tiling)
{
const GLuint dim = mt->width0;
GLuint face;
@@ -111,7 +123,7 @@ i915_miptree_layout_cube(struct intel_context *intel,
assert(lvlWidth == lvlHeight); /* cubemap images are square */
/* double pitch for cube layouts */
- mt->pitch = intel_miptree_pitch_align (intel, mt, dim * 2);
+ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, dim * 2);
mt->total_height = dim * 4;
for (level = mt->first_level; level <= mt->last_level; level++) {
@@ -145,7 +157,8 @@ i915_miptree_layout_cube(struct intel_context *intel,
static void
i915_miptree_layout_3d(struct intel_context *intel,
- struct intel_mipmap_tree * mt)
+ struct intel_mipmap_tree * mt,
+ uint32_t tiling)
{
GLuint width = mt->width0;
GLuint height = mt->height0;
@@ -154,7 +167,7 @@ i915_miptree_layout_3d(struct intel_context *intel,
GLint level;
/* Calculate the size of a single slice. */
- mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
+ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
/* XXX: hardware expects/requires 9 levels at minimum. */
for (level = mt->first_level; level <= MAX2(8, mt->last_level); level++) {
@@ -189,14 +202,15 @@ i915_miptree_layout_3d(struct intel_context *intel,
static void
i915_miptree_layout_2d(struct intel_context *intel,
- struct intel_mipmap_tree * mt)
+ struct intel_mipmap_tree * mt,
+ uint32_t tiling)
{
GLuint width = mt->width0;
GLuint height = mt->height0;
GLuint img_height;
GLint level;
- mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
+ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
mt->total_height = 0;
for (level = mt->first_level; level <= mt->last_level; level++) {
@@ -217,19 +231,20 @@ i915_miptree_layout_2d(struct intel_context *intel,
}
GLboolean
-i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
+i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt,
+ uint32_t tiling)
{
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP:
- i915_miptree_layout_cube(intel, mt);
+ i915_miptree_layout_cube(intel, mt, tiling);
break;
case GL_TEXTURE_3D:
- i915_miptree_layout_3d(intel, mt);
+ i915_miptree_layout_3d(intel, mt, tiling);
break;
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_ARB:
- i915_miptree_layout_2d(intel, mt);
+ i915_miptree_layout_2d(intel, mt, tiling);
break;
default:
_mesa_problem(NULL, "Unexpected tex target in i915_miptree_layout()");
@@ -297,7 +312,7 @@ i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
* +---+ +---+ +---+ +---+ +---+ +---+
*
* The bottom row continues with the remaining 2x2 then the 1x1 mip contents
- * in order, with each of them aligned to a 4x4 block boundary. Thus, for
+ * in order, with each of them aligned to a 8x8 block boundary. Thus, for
* 32x32 cube maps and smaller, the bottom row layout is going to dictate the
* pitch of the tree. For a tree with 4x4 images, the pitch is at least
* 14 * 8 = 112 texels, for 2x2 it is at least 12 * 8 texels, and for 1x1
@@ -306,7 +321,8 @@ i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
static void
i945_miptree_layout_cube(struct intel_context *intel,
- struct intel_mipmap_tree * mt)
+ struct intel_mipmap_tree * mt,
+ uint32_t tiling)
{
const GLuint dim = mt->width0;
GLuint face;
@@ -320,9 +336,9 @@ i945_miptree_layout_cube(struct intel_context *intel,
* or the final row of 4x4, 2x2 and 1x1 faces below this.
*/
if (dim > 32)
- mt->pitch = intel_miptree_pitch_align (intel, mt, dim * 2);
+ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, dim * 2);
else
- mt->pitch = intel_miptree_pitch_align (intel, mt, 14 * 8);
+ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, 14 * 8);
if (dim >= 4)
mt->total_height = dim * 4 + 4;
@@ -375,10 +391,11 @@ i945_miptree_layout_cube(struct intel_context *intel,
x = (face - 4) * 8;
break;
}
+ break;
case 2:
y = mt->total_height - 4;
- x = 16 + face * 8;
+ x = bottom_offsets[face];
break;
case 1:
@@ -396,7 +413,8 @@ i945_miptree_layout_cube(struct intel_context *intel,
static void
i945_miptree_layout_3d(struct intel_context *intel,
- struct intel_mipmap_tree * mt)
+ struct intel_mipmap_tree * mt,
+ uint32_t tiling)
{
GLuint width = mt->width0;
GLuint height = mt->height0;
@@ -405,7 +423,7 @@ i945_miptree_layout_3d(struct intel_context *intel,
GLuint pack_y_pitch;
GLuint level;
- mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
+ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
mt->total_height = 0;
pack_y_pitch = MAX2(mt->height0, 2);
@@ -450,19 +468,23 @@ i945_miptree_layout_3d(struct intel_context *intel,
}
GLboolean
-i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
+i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt,
+ uint32_t tiling)
{
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP:
- i945_miptree_layout_cube(intel, mt);
+ if (mt->compressed)
+ i945_miptree_layout_cube(intel, mt, tiling);
+ else
+ i915_miptree_layout_cube(intel, mt, tiling);
break;
case GL_TEXTURE_3D:
- i945_miptree_layout_3d(intel, mt);
+ i945_miptree_layout_3d(intel, mt, tiling);
break;
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_ARB:
- i945_miptree_layout_2d(intel, mt);
+ i945_miptree_layout_2d(intel, mt, tiling);
break;
default:
_mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()");
diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c
index adbb52a3a3..32d4b30cf9 100644
--- a/src/mesa/drivers/dri/i915/i915_texstate.c
+++ b/src/mesa/drivers/dri/i915/i915_texstate.c
@@ -37,7 +37,8 @@
static GLuint
-translate_texture_format(GLuint mesa_format, GLenum DepthMode)
+translate_texture_format(GLuint mesa_format, GLuint internal_format,
+ GLenum DepthMode)
{
switch (mesa_format) {
case MESA_FORMAT_L8:
@@ -55,7 +56,10 @@ translate_texture_format(GLuint mesa_format, GLenum DepthMode)
case MESA_FORMAT_ARGB4444:
return MAPSURF_16BIT | MT_16BIT_ARGB4444;
case MESA_FORMAT_ARGB8888:
- return MAPSURF_32BIT | MT_32BIT_ARGB8888;
+ if (internal_format == GL_RGB)
+ return MAPSURF_32BIT | MT_32BIT_XRGB8888;
+ else
+ return MAPSURF_32BIT | MT_32BIT_ARGB8888;
case MESA_FORMAT_YCBCR_REV:
return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
case MESA_FORMAT_YCBCR:
@@ -128,7 +132,8 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
struct intel_texture_object *intelObj = intel_texture_object(tObj);
struct gl_texture_image *firstImage;
GLuint *state = i915->state.Tex[unit], format, pitch;
- GLint lodbias;
+ GLint lodbias, aniso = 0;
+ GLubyte border[4];
memset(state, 0, sizeof(state));
@@ -173,14 +178,20 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
firstLevel);
format = translate_texture_format(firstImage->TexFormat->MesaFormat,
- tObj->DepthMode);
+ firstImage->InternalFormat,
+ tObj->DepthMode);
pitch = intelObj->mt->pitch * intelObj->mt->cpp;
}
state[I915_TEXREG_MS3] =
(((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) |
- ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format |
- MS3_USE_FENCE_REGS);
+ ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format);
+
+ if (intelObj->mt->region->tiling != I915_TILING_NONE) {
+ state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE;
+ if (intelObj->mt->region->tiling == I915_TILING_Y)
+ state[I915_TEXREG_MS3] |= MS3_TILE_WALK;
+ }
state[I915_TEXREG_MS4] =
((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK |
@@ -224,6 +235,10 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
if (tObj->MaxAnisotropy > 1.0) {
minFilt = FILTER_ANISOTROPIC;
magFilt = FILTER_ANISOTROPIC;
+ if (tObj->MaxAnisotropy > 2.0)
+ aniso = SS2_MAX_ANISO_4;
+ else
+ aniso = SS2_MAX_ANISO_2;
}
else {
switch (tObj->MagFilter) {
@@ -269,7 +284,8 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
(mipFilt << SS2_MIP_FILTER_SHIFT) |
- (magFilt << SS2_MAG_FILTER_SHIFT));
+ (magFilt << SS2_MAG_FILTER_SHIFT) |
+ aniso);
}
{
@@ -313,21 +329,26 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
}
+ /* convert border color from float to ubyte */
+ CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor[3]);
if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) {
/* GL specs that border color for depth textures is taken from the
* R channel, while the hardware uses A. Spam R into all the channels
* for safety.
*/
- state[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0],
- tObj->_BorderChan[0],
- tObj->_BorderChan[0],
- tObj->_BorderChan[0]);
+ state[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(border[0],
+ border[0],
+ border[0],
+ border[0]);
} else {
- state[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0],
- tObj->_BorderChan[1],
- tObj->_BorderChan[2],
- tObj->_BorderChan[3]);
+ state[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(border[0],
+ border[1],
+ border[2],
+ border[3]);
}
diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c
index 3f6d282d34..9a723d3cd7 100644
--- a/src/mesa/drivers/dri/i915/i915_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i915_vtbl.c
@@ -32,6 +32,7 @@
#include "main/imports.h"
#include "main/macros.h"
#include "main/colormac.h"
+#include "main/texformat.h"
#include "tnl/t_context.h"
#include "tnl/t_vertex.h"
@@ -40,6 +41,8 @@
#include "intel_tex.h"
#include "intel_regions.h"
#include "intel_tris.h"
+#include "intel_fbo.h"
+#include "intel_chipset.h"
#include "i915_reg.h"
#include "i915_context.h"
@@ -173,7 +176,7 @@ i915_emit_invarient_state(struct intel_context *intel)
{
BATCH_LOCALS;
- BEGIN_BATCH(20, IGNORE_CLIPRECTS);
+ BEGIN_BATCH(17, IGNORE_CLIPRECTS);
OUT_BATCH(_3DSTATE_AA_CMD |
AA_LINE_ECAAR_WIDTH_ENABLE |
@@ -197,14 +200,6 @@ i915_emit_invarient_state(struct intel_context *intel)
CSB_TCB(3, 3) |
CSB_TCB(4, 4) | CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7));
- OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
- ENABLE_POINT_RASTER_RULE |
- OGL_POINT_RASTER_RULE |
- ENABLE_LINE_STRIP_PROVOKE_VRTX |
- ENABLE_TRI_FAN_PROVOKE_VRTX |
- LINE_STRIP_PROVOKE_VRTX(1) |
- TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D);
-
/* Need to initialize this to zero.
*/
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (0));
@@ -222,11 +217,6 @@ i915_emit_invarient_state(struct intel_context *intel)
OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
OUT_BATCH(0);
-
- /* Don't support twosided stencil yet */
- OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
- OUT_BATCH(0);
-
ADVANCE_BATCH();
}
@@ -260,6 +250,9 @@ get_state_size(struct i915_hw_state *state)
if (dirty & I915_UPLOAD_INVARIENT)
sz += 30 * 4;
+ if (dirty & I915_UPLOAD_RASTER_RULES)
+ sz += sizeof(state->RasterRules);
+
if (dirty & I915_UPLOAD_CTX)
sz += sizeof(state->Ctx);
@@ -368,6 +361,12 @@ i915_emit_state(struct intel_context *intel)
i915_emit_invarient_state(intel);
}
+ if (dirty & I915_UPLOAD_RASTER_RULES) {
+ if (INTEL_DEBUG & DEBUG_STATE)
+ fprintf(stderr, "I915_UPLOAD_RASTER_RULES:\n");
+ emit(intel, state->RasterRules, sizeof(state->RasterRules));
+ }
+
if (dirty & I915_UPLOAD_CTX) {
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "I915_UPLOAD_CTX:\n");
@@ -527,6 +526,23 @@ i915_destroy_context(struct intel_context *intel)
_tnl_free_vertices(&intel->ctx);
}
+void
+i915_set_buf_info_for_region(uint32_t *state, struct intel_region *region,
+ uint32_t buffer_id)
+{
+ state[0] = _3DSTATE_BUF_INFO_CMD;
+ state[1] = buffer_id;
+
+ if (region != NULL) {
+ state[1] |= BUF_3D_PITCH(region->pitch * region->cpp);
+
+ if (region->tiling != I915_TILING_NONE) {
+ state[1] |= BUF_3D_TILED_SURFACE;
+ if (region->tiling == I915_TILING_Y)
+ state[1] |= BUF_3D_TILE_WALK_Y;
+ }
+ }
+}
/**
* Set the drawing regions for the color and depth/stencil buffers.
@@ -542,6 +558,8 @@ i915_state_draw_region(struct intel_context *intel,
{
struct i915_context *i915 = i915_context(&intel->ctx);
GLcontext *ctx = &intel->ctx;
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
GLuint value;
ASSERT(state == &i915->state || state == &i915->meta);
@@ -558,21 +576,11 @@ i915_state_draw_region(struct intel_context *intel,
/*
* Set stride/cpp values
*/
- if (color_region) {
- state->Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
- state->Buffer[I915_DESTREG_CBUFADDR1] =
- (BUF_3D_ID_COLOR_BACK |
- BUF_3D_PITCH(color_region->pitch * color_region->cpp) |
- BUF_3D_USE_FENCE);
- }
+ i915_set_buf_info_for_region(&state->Buffer[I915_DESTREG_CBUFADDR0],
+ color_region, BUF_3D_ID_COLOR_BACK);
- if (depth_region) {
- state->Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
- state->Buffer[I915_DESTREG_DBUFADDR1] =
- (BUF_3D_ID_DEPTH |
- BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) |
- BUF_3D_USE_FENCE);
- }
+ i915_set_buf_info_for_region(&state->Buffer[I915_DESTREG_DBUFADDR0],
+ depth_region, BUF_3D_ID_DEPTH);
/*
* Compute/set I915_DESTREG_DV1 value
@@ -580,12 +588,34 @@ i915_state_draw_region(struct intel_context *intel,
value = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
LOD_PRECLAMP_OGL | TEX_DEFAULT_COLOR_OGL);
- if (color_region && color_region->cpp == 4) {
- value |= DV_PF_8888;
- }
- else {
- value |= (DITHER_FULL_ALWAYS | DV_PF_565);
+ if (irb != NULL) {
+ switch (irb->texformat->MesaFormat) {
+ case MESA_FORMAT_ARGB8888:
+ value |= DV_PF_8888;
+ break;
+ case MESA_FORMAT_RGB565:
+ value |= DV_PF_565 | DITHER_FULL_ALWAYS;
+ break;
+ case MESA_FORMAT_ARGB1555:
+ value |= DV_PF_1555 | DITHER_FULL_ALWAYS;
+ break;
+ case MESA_FORMAT_ARGB4444:
+ value |= DV_PF_4444 | DITHER_FULL_ALWAYS;
+ break;
+ default:
+ _mesa_problem(ctx, "Bad renderbuffer format: %d\n",
+ irb->texformat->MesaFormat);
+ }
}
+
+ /* This isn't quite safe, thus being hidden behind an option. When changing
+ * the value of this bit, the pipeline needs to be MI_FLUSHed. And it
+ * can only be set when a depth buffer is already defined.
+ */
+ if (IS_945(intel->intelScreen->deviceID) && intel->use_early_z &&
+ depth_region->tiling != I915_TILING_NONE)
+ value |= CLASSIC_EARLY_DEPTH;
+
if (depth_region && depth_region->cpp == 4) {
value |= DEPTH_FRMT_24_FIXED_8_OTHER;
}
@@ -658,13 +688,6 @@ i915_assert_not_dirty( struct intel_context *intel )
assert(!dirty);
}
-static void
-i915_note_unlock( struct intel_context *intel )
-{
- /* nothing */
-}
-
-
void
i915InitVtbl(struct i915_context *i915)
{
@@ -679,6 +702,5 @@ i915InitVtbl(struct i915_context *i915)
i915->intel.vtbl.update_texture_state = i915UpdateTextureState;
i915->intel.vtbl.flush_cmd = i915_flush_cmd;
i915->intel.vtbl.assert_not_dirty = i915_assert_not_dirty;
- i915->intel.vtbl.note_unlock = i915_note_unlock;
i915->intel.vtbl.finish_batch = intel_finish_vb;
}
diff --git a/src/mesa/drivers/dri/i915/intel_clear.c b/src/mesa/drivers/dri/i915/intel_clear.c
new file mode 120000
index 0000000000..9a2a742a0d
--- /dev/null
+++ b/src/mesa/drivers/dri/i915/intel_clear.c
@@ -0,0 +1 @@
+../intel/intel_clear.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_depthstencil.c b/src/mesa/drivers/dri/i915/intel_depthstencil.c
deleted file mode 120000
index 4ac4ae690a..0000000000
--- a/src/mesa/drivers/dri/i915/intel_depthstencil.c
+++ /dev/null
@@ -1 +0,0 @@
-../intel/intel_depthstencil.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_eglimage.c b/src/mesa/drivers/dri/i915/intel_eglimage.c
new file mode 120000
index 0000000000..6047b254a0
--- /dev/null
+++ b/src/mesa/drivers/dri/i915/intel_eglimage.c
@@ -0,0 +1 @@
+../intel/intel_eglimage.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_eglimage.h b/src/mesa/drivers/dri/i915/intel_eglimage.h
new file mode 120000
index 0000000000..a2cde85a28
--- /dev/null
+++ b/src/mesa/drivers/dri/i915/intel_eglimage.h
@@ -0,0 +1 @@
+../intel/intel_eglimage.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_extensions.c b/src/mesa/drivers/dri/i915/intel_extensions.c
new file mode 120000
index 0000000000..a2f3e8cd20
--- /dev/null
+++ b/src/mesa/drivers/dri/i915/intel_extensions.c
@@ -0,0 +1 @@
+../intel/intel_extensions.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_generatemipmap.c b/src/mesa/drivers/dri/i915/intel_generatemipmap.c
new file mode 120000
index 0000000000..4c6b37ada0
--- /dev/null
+++ b/src/mesa/drivers/dri/i915/intel_generatemipmap.c
@@ -0,0 +1 @@
+../intel/intel_generatemipmap.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_pixel_read.c b/src/mesa/drivers/dri/i915/intel_pixel_read.c
index 56087aacd4..cc4589f4d4 100644..120000
--- a/src/mesa/drivers/dri/i915/intel_pixel_read.c
+++ b/src/mesa/drivers/dri/i915/intel_pixel_read.c
@@ -1,306 +1 @@
-/**************************************************************************
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "main/glheader.h"
-#include "main/enums.h"
-#include "main/mtypes.h"
-#include "main/macros.h"
-#include "main/image.h"
-#include "main/bufferobj.h"
-#include "swrast/swrast.h"
-
-#include "intel_screen.h"
-#include "intel_context.h"
-#include "intel_batchbuffer.h"
-#include "intel_blit.h"
-#include "intel_buffers.h"
-#include "intel_regions.h"
-#include "intel_pixel.h"
-#include "intel_buffer_objects.h"
-
-/* For many applications, the new ability to pull the source buffers
- * back out of the GTT and then do the packing/conversion operations
- * in software will be as much of an improvement as trying to get the
- * blitter and/or texture engine to do the work.
- *
- * This step is gated on private backbuffers.
- *
- * Obviously the frontbuffer can't be pulled back, so that is either
- * an argument for blit/texture readpixels, or for blitting to a
- * temporary and then pulling that back.
- *
- * When the destination is a pbo, however, it's not clear if it is
- * ever going to be pulled to main memory (though the access param
- * will be a good hint). So it sounds like we do want to be able to
- * choose between blit/texture implementation on the gpu and pullback
- * and cpu-based copying.
- *
- * Unless you can magically turn client memory into a PBO for the
- * duration of this call, there will be a cpu-based copying step in
- * any case.
- */
-
-
-static GLboolean
-do_texture_readpixels(GLcontext * ctx,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *pack,
- struct intel_region *dest_region)
-{
-#if 0
- struct intel_context *intel = intel_context(ctx);
- intelScreenPrivate *screen = intel->intelScreen;
- GLint pitch = pack->RowLength ? pack->RowLength : width;
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
- int textureFormat;
- GLenum glTextureFormat;
- int destFormat, depthFormat, destPitch;
- drm_clip_rect_t tmp;
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
-
- if (ctx->_ImageTransferState ||
- pack->SwapBytes || pack->LsbFirst || !pack->Invert) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
- return GL_FALSE;
- }
-
- intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel));
-
- if (!intel->vtbl.meta_render_dest(intel, dest_region, type, format)) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s: couldn't set dest %s/%s\n",
- __FUNCTION__,
- _mesa_lookup_enum_by_nr(type),
- _mesa_lookup_enum_by_nr(format));
- return GL_FALSE;
- }
-
- LOCK_HARDWARE(intel);
-
- if (intel->driDrawable->numClipRects) {
- intel->vtbl.install_meta_state(intel);
- intel->vtbl.meta_no_depth_write(intel);
- intel->vtbl.meta_no_stencil_write(intel);
-
- if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
- UNLOCK_HARDWARE(intel);
- SET_STATE(i830, state);
- if (INTEL_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
- return GL_TRUE;
- }
-
- y = dPriv->h - y - height;
- x += dPriv->x;
- y += dPriv->y;
-
-
- /* Set the frontbuffer up as a large rectangular texture.
- */
- intel->vtbl.meta_tex_rect_source(intel, src_region, textureFormat);
-
-
- intel->vtbl.meta_texture_blend_replace(i830, glTextureFormat);
-
-
- /* Set the 3d engine to draw into the destination region:
- */
-
- intel->vtbl.meta_draw_region(intel, dest_region);
- intel->vtbl.meta_draw_format(intel, destFormat, depthFormat); /* ?? */
-
-
- /* Draw a single quad, no cliprects:
- */
- intel->vtbl.meta_disable_cliprects(intel);
-
- intel->vtbl.draw_quad(intel,
- 0, width, 0, height,
- 0x00ff00ff, x, x + width, y, y + height);
-
- intel->vtbl.leave_meta_state(intel);
- }
- UNLOCK_HARDWARE(intel);
-
- intel_region_wait_fence(ctx, dest_region); /* required by GL */
- return GL_TRUE;
-#endif
-
- return GL_FALSE;
-}
-
-
-
-
-static GLboolean
-do_blit_readpixels(GLcontext * ctx,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_region *src = intel_readbuf_region(intel);
- struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
- GLuint dst_offset;
- GLuint rowLength;
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s\n", __FUNCTION__);
-
- if (!src)
- return GL_FALSE;
-
- if (dst) {
- /* XXX This validation should be done by core mesa:
- */
- if (!_mesa_validate_pbo_access(2, pack, width, height, 1,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
- return GL_TRUE;
- }
- }
- else {
- /* PBO only for now:
- */
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - not PBO\n", __FUNCTION__);
- return GL_FALSE;
- }
-
-
- if (ctx->_ImageTransferState ||
- !intel_check_blit_format(src, format, type)) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
- return GL_FALSE;
- }
-
- if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s: bad packing params\n", __FUNCTION__);
- return GL_FALSE;
- }
-
- if (pack->RowLength > 0)
- rowLength = pack->RowLength;
- else
- rowLength = width;
-
- if (pack->Invert) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__);
- return GL_FALSE;
- }
- else {
- rowLength = -rowLength;
- }
-
- /* XXX 64-bit cast? */
- dst_offset = (GLuint) _mesa_image_address(2, pack, pixels, width, height,
- format, type, 0, 0, 0);
-
-
- /* Although the blits go on the command buffer, need to do this and
- * fire with lock held to guarentee cliprects are correct.
- */
- intelFlush(&intel->ctx);
- LOCK_HARDWARE(intel);
-
- if (intel->driDrawable->numClipRects) {
- GLboolean all = (width * height * src->cpp == dst->Base.Size &&
- x == 0 && dst_offset == 0);
-
- dri_bo *dst_buffer = intel_bufferobj_buffer(intel, dst,
- all ? INTEL_WRITE_FULL :
- INTEL_WRITE_PART);
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
- int nbox = dPriv->numClipRects;
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t rect;
- drm_clip_rect_t src_rect;
- int i;
-
- src_rect.x1 = dPriv->x + x;
- src_rect.y1 = dPriv->y + dPriv->h - (y + height);
- src_rect.x2 = src_rect.x1 + width;
- src_rect.y2 = src_rect.y1 + height;
-
-
-
- for (i = 0; i < nbox; i++) {
- if (!intel_intersect_cliprects(&rect, &src_rect, &box[i]))
- continue;
-
- intelEmitCopyBlit(intel,
- src->cpp,
- src->pitch, src->buffer, 0, src->tiling,
- rowLength, dst_buffer, dst_offset, GL_FALSE,
- rect.x1,
- rect.y1,
- rect.x1 - src_rect.x1,
- rect.y2 - src_rect.y2,
- rect.x2 - rect.x1, rect.y2 - rect.y1,
- GL_COPY);
- }
- }
- UNLOCK_HARDWARE(intel);
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s - DONE\n", __FUNCTION__);
-
- return GL_TRUE;
-}
-
-void
-intelReadPixels(GLcontext * ctx,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
-{
- if (INTEL_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- intelFlush(ctx);
-
- if (do_blit_readpixels
- (ctx, x, y, width, height, format, type, pack, pixels))
- return;
-
- if (do_texture_readpixels
- (ctx, x, y, width, height, format, type, pack, pixels))
- return;
-
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
-
- _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels);
-}
+../intel/intel_pixel_read.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_state.c b/src/mesa/drivers/dri/i915/intel_state.c
index 4aa43e5f3a..519672fc35 100644..120000
--- a/src/mesa/drivers/dri/i915/intel_state.c
+++ b/src/mesa/drivers/dri/i915/intel_state.c
@@ -1,297 +1 @@
-/**************************************************************************
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "main/enums.h"
-#include "main/colormac.h"
-#include "main/dd.h"
-
-#include "intel_screen.h"
-#include "intel_context.h"
-#include "intel_fbo.h"
-#include "intel_regions.h"
-#include "swrast/swrast.h"
-
-int
-intel_translate_shadow_compare_func( GLenum func )
-{
- switch(func) {
- case GL_NEVER:
- return COMPAREFUNC_ALWAYS;
- case GL_LESS:
- return COMPAREFUNC_LEQUAL;
- case GL_LEQUAL:
- return COMPAREFUNC_LESS;
- case GL_GREATER:
- return COMPAREFUNC_GEQUAL;
- case GL_GEQUAL:
- return COMPAREFUNC_GREATER;
- case GL_NOTEQUAL:
- return COMPAREFUNC_EQUAL;
- case GL_EQUAL:
- return COMPAREFUNC_NOTEQUAL;
- case GL_ALWAYS:
- return COMPAREFUNC_NEVER;
- }
-
- fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func);
- return COMPAREFUNC_NEVER;
-}
-
-int
-intel_translate_compare_func(GLenum func)
-{
- switch (func) {
- case GL_NEVER:
- return COMPAREFUNC_NEVER;
- case GL_LESS:
- return COMPAREFUNC_LESS;
- case GL_LEQUAL:
- return COMPAREFUNC_LEQUAL;
- case GL_GREATER:
- return COMPAREFUNC_GREATER;
- case GL_GEQUAL:
- return COMPAREFUNC_GEQUAL;
- case GL_NOTEQUAL:
- return COMPAREFUNC_NOTEQUAL;
- case GL_EQUAL:
- return COMPAREFUNC_EQUAL;
- case GL_ALWAYS:
- return COMPAREFUNC_ALWAYS;
- }
-
- fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func);
- return COMPAREFUNC_ALWAYS;
-}
-
-int
-intel_translate_stencil_op(GLenum op)
-{
- switch (op) {
- case GL_KEEP:
- return STENCILOP_KEEP;
- case GL_ZERO:
- return STENCILOP_ZERO;
- case GL_REPLACE:
- return STENCILOP_REPLACE;
- case GL_INCR:
- return STENCILOP_INCRSAT;
- case GL_DECR:
- return STENCILOP_DECRSAT;
- case GL_INCR_WRAP:
- return STENCILOP_INCR;
- case GL_DECR_WRAP:
- return STENCILOP_DECR;
- case GL_INVERT:
- return STENCILOP_INVERT;
- default:
- return STENCILOP_ZERO;
- }
-}
-
-int
-intel_translate_blend_factor(GLenum factor)
-{
- switch (factor) {
- case GL_ZERO:
- return BLENDFACT_ZERO;
- case GL_SRC_ALPHA:
- return BLENDFACT_SRC_ALPHA;
- case GL_ONE:
- return BLENDFACT_ONE;
- case GL_SRC_COLOR:
- return BLENDFACT_SRC_COLR;
- case GL_ONE_MINUS_SRC_COLOR:
- return BLENDFACT_INV_SRC_COLR;
- case GL_DST_COLOR:
- return BLENDFACT_DST_COLR;
- case GL_ONE_MINUS_DST_COLOR:
- return BLENDFACT_INV_DST_COLR;
- case GL_ONE_MINUS_SRC_ALPHA:
- return BLENDFACT_INV_SRC_ALPHA;
- case GL_DST_ALPHA:
- return BLENDFACT_DST_ALPHA;
- case GL_ONE_MINUS_DST_ALPHA:
- return BLENDFACT_INV_DST_ALPHA;
- case GL_SRC_ALPHA_SATURATE:
- return BLENDFACT_SRC_ALPHA_SATURATE;
- case GL_CONSTANT_COLOR:
- return BLENDFACT_CONST_COLOR;
- case GL_ONE_MINUS_CONSTANT_COLOR:
- return BLENDFACT_INV_CONST_COLOR;
- case GL_CONSTANT_ALPHA:
- return BLENDFACT_CONST_ALPHA;
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- return BLENDFACT_INV_CONST_ALPHA;
- }
-
- fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, factor);
- return BLENDFACT_ZERO;
-}
-
-int
-intel_translate_logic_op(GLenum opcode)
-{
- switch (opcode) {
- case GL_CLEAR:
- return LOGICOP_CLEAR;
- case GL_AND:
- return LOGICOP_AND;
- case GL_AND_REVERSE:
- return LOGICOP_AND_RVRSE;
- case GL_COPY:
- return LOGICOP_COPY;
- case GL_COPY_INVERTED:
- return LOGICOP_COPY_INV;
- case GL_AND_INVERTED:
- return LOGICOP_AND_INV;
- case GL_NOOP:
- return LOGICOP_NOOP;
- case GL_XOR:
- return LOGICOP_XOR;
- case GL_OR:
- return LOGICOP_OR;
- case GL_OR_INVERTED:
- return LOGICOP_OR_INV;
- case GL_NOR:
- return LOGICOP_NOR;
- case GL_EQUIV:
- return LOGICOP_EQUIV;
- case GL_INVERT:
- return LOGICOP_INV;
- case GL_OR_REVERSE:
- return LOGICOP_OR_RVRSE;
- case GL_NAND:
- return LOGICOP_NAND;
- case GL_SET:
- return LOGICOP_SET;
- default:
- return LOGICOP_SET;
- }
-}
-
-
-static void
-intelClearColor(GLcontext * ctx, const GLfloat color[4])
-{
- struct intel_context *intel = intel_context(ctx);
- GLubyte clear[4];
-
- CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
- CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
- CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
- CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);
-
- /* compute both 32 and 16-bit clear values */
- intel->ClearColor8888 = INTEL_PACKCOLOR8888(clear[0], clear[1],
- clear[2], clear[3]);
- intel->ClearColor565 = INTEL_PACKCOLOR565(clear[0], clear[1], clear[2]);
-}
-
-
-/**
- * Update the viewport transformation matrix. Depends on:
- * - viewport pos/size
- * - depthrange
- * - window pos/size or FBO size
- */
-static void
-intelCalcViewport(GLcontext * ctx)
-{
- struct intel_context *intel = intel_context(ctx);
- const GLfloat *v = ctx->Viewport._WindowMap.m;
- const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
- GLfloat *m = intel->ViewportMatrix.m;
- GLfloat yScale, yBias;
-
- if (ctx->DrawBuffer->Name) {
- /* User created FBO */
- struct intel_renderbuffer *irb
- = intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
- if (irb && !irb->RenderToTexture) {
- /* y=0=top */
- yScale = -1.0;
- yBias = irb->Base.Height;
- }
- else {
- /* y=0=bottom */
- yScale = 1.0;
- yBias = 0.0;
- }
- }
- else {
- /* window buffer, y=0=top */
- yScale = -1.0;
- yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F;
- }
-
- m[MAT_SX] = v[MAT_SX];
- m[MAT_TX] = v[MAT_TX];
-
- m[MAT_SY] = v[MAT_SY] * yScale;
- m[MAT_TY] = v[MAT_TY] * yScale + yBias;
-
- m[MAT_SZ] = v[MAT_SZ] * depthScale;
- m[MAT_TZ] = v[MAT_TZ] * depthScale;
-}
-
-static void
-intelViewport(GLcontext * ctx,
- GLint x, GLint y, GLsizei width, GLsizei height)
-{
- intelCalcViewport(ctx);
-
- intel_viewport(ctx, x, y, width, height);
-}
-
-static void
-intelDepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
-{
- intelCalcViewport(ctx);
-}
-
-/* Fallback to swrast for select and feedback.
- */
-static void
-intelRenderMode(GLcontext * ctx, GLenum mode)
-{
- struct intel_context *intel = intel_context(ctx);
- FALLBACK(intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER));
-}
-
-
-void
-intelInitStateFuncs(struct dd_function_table *functions)
-{
- functions->RenderMode = intelRenderMode;
- functions->Viewport = intelViewport;
- functions->DepthRange = intelDepthRange;
- functions->ClearColor = intelClearColor;
-}
+../intel/intel_state.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_swapbuffers.c b/src/mesa/drivers/dri/i915/intel_swapbuffers.c
new file mode 120000
index 0000000000..148d5215aa
--- /dev/null
+++ b/src/mesa/drivers/dri/i915/intel_swapbuffers.c
@@ -0,0 +1 @@
+../intel/intel_swapbuffers.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_syncobj.c b/src/mesa/drivers/dri/i915/intel_syncobj.c
new file mode 120000
index 0000000000..0b2e56ab24
--- /dev/null
+++ b/src/mesa/drivers/dri/i915/intel_syncobj.c
@@ -0,0 +1 @@
+../intel/intel_syncobj.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c
index e80996580c..a905455342 100644
--- a/src/mesa/drivers/dri/i915/intel_tris.c
+++ b/src/mesa/drivers/dri/i915/intel_tris.c
@@ -89,8 +89,8 @@ intel_flush_inline_primitive(struct intel_context *intel)
static void intel_start_inline(struct intel_context *intel, uint32_t prim)
{
- BATCH_LOCALS;
uint32_t batch_flags = LOOP_CLIPRECTS;
+ BATCH_LOCALS;
intel->vtbl.emit_state(intel);
@@ -201,10 +201,10 @@ uint32_t *intel_get_prim_space(struct intel_context *intel, unsigned int count)
/** Dispatches the accumulated primitive to the batchbuffer. */
void intel_flush_prim(struct intel_context *intel)
{
- BATCH_LOCALS;
dri_bo *aper_array[2];
dri_bo *vb_bo;
unsigned int offset, count;
+ BATCH_LOCALS;
/* Must be called after an intel_start_prim. */
assert(intel->prim.primitive != ~0);
@@ -989,7 +989,7 @@ intelChooseRenderState(GLcontext * ctx)
intel->draw_tri = intel_fallback_tri;
if (flags & DD_TRI_SMOOTH) {
- if (intel->strict_conformance)
+ if (intel->conformance_mode > 0)
intel->draw_tri = intel_fallback_tri;
}
@@ -1001,7 +1001,7 @@ intelChooseRenderState(GLcontext * ctx)
}
if (flags & DD_POINT_SMOOTH) {
- if (intel->strict_conformance)
+ if (intel->conformance_mode > 0)
intel->draw_point = intel_fallback_point;
}
@@ -1255,11 +1255,9 @@ intel_meta_draw_poly(struct intel_context *intel,
{
union fi *vb;
GLint i;
- GLboolean was_locked = intel->locked;
unsigned int saved_vertex_size = intel->vertex_size;
- if (!was_locked)
- LOCK_HARDWARE(intel);
+ LOCK_HARDWARE(intel);
intel->vertex_size = 6;
@@ -1283,8 +1281,7 @@ intel_meta_draw_poly(struct intel_context *intel,
intel->vertex_size = saved_vertex_size;
- if (!was_locked)
- UNLOCK_HARDWARE(intel);
+ UNLOCK_HARDWARE(intel);
}
static void
diff --git a/src/mesa/drivers/dri/i965/Makefile b/src/mesa/drivers/dri/i965/Makefile
index 37a470f2e2..6e9a9a29a3 100644
--- a/src/mesa/drivers/dri/i965/Makefile
+++ b/src/mesa/drivers/dri/i965/Makefile
@@ -9,10 +9,12 @@ DRIVER_SOURCES = \
intel_blit.c \
intel_buffer_objects.c \
intel_buffers.c \
+ intel_clear.c \
intel_context.c \
intel_decode.c \
- intel_depthstencil.c \
+ intel_extensions.c \
intel_fbo.c \
+ intel_generatemipmap.c \
intel_mipmap_tree.c \
intel_regions.c \
intel_screen.c \
@@ -21,7 +23,10 @@ DRIVER_SOURCES = \
intel_pixel_bitmap.c \
intel_pixel_copy.c \
intel_pixel_draw.c \
+ intel_pixel_read.c \
intel_state.c \
+ intel_swapbuffers.c \
+ intel_syncobj.c \
intel_tex.c \
intel_tex_copy.c \
intel_tex_format.c \
@@ -39,6 +44,7 @@ DRIVER_SOURCES = \
brw_clip_util.c \
brw_context.c \
brw_curbe.c \
+ brw_disasm.c \
brw_draw.c \
brw_draw_upload.c \
brw_eu.c \
@@ -49,7 +55,6 @@ DRIVER_SOURCES = \
brw_gs.c \
brw_gs_emit.c \
brw_gs_state.c \
- brw_metaops.c \
brw_misc_state.c \
brw_program.c \
brw_queryobj.c \
@@ -68,6 +73,7 @@ DRIVER_SOURCES = \
brw_vs_constval.c \
brw_vs_emit.c \
brw_vs_state.c \
+ brw_vs_surface_state.c \
brw_vtbl.c \
brw_wm.c \
brw_wm_debug.c \
diff --git a/src/mesa/drivers/dri/i965/brw_cc.c b/src/mesa/drivers/dri/i965/brw_cc.c
index fa8121e02d..1088a7a607 100644
--- a/src/mesa/drivers/dri/i965/brw_cc.c
+++ b/src/mesa/drivers/dri/i965/brw_cc.c
@@ -39,12 +39,14 @@
static void prepare_cc_vp( struct brw_context *brw )
{
+ GLcontext *ctx = &brw->intel.ctx;
struct brw_cc_viewport ccv;
memset(&ccv, 0, sizeof(ccv));
- ccv.min_depth = 0.0;
- ccv.max_depth = 1.0;
+ /* _NEW_VIEWPORT */
+ ccv.min_depth = ctx->Viewport.Near;
+ ccv.max_depth = ctx->Viewport.Far;
dri_bo_unreference(brw->cc.vp_bo);
brw->cc.vp_bo = brw_cache_data( &brw->cache, BRW_CC_VP, &ccv, NULL, 0 );
@@ -52,7 +54,7 @@ static void prepare_cc_vp( struct brw_context *brw )
const struct brw_tracked_state brw_cc_vp = {
.dirty = {
- .mesa = 0,
+ .mesa = _NEW_VIEWPORT,
.brw = BRW_NEW_CONTEXT,
.cache = 0
},
@@ -83,59 +85,60 @@ struct brw_cc_unit_key {
static void
cc_unit_populate_key(struct brw_context *brw, struct brw_cc_unit_key *key)
{
- struct gl_stencil_attrib *stencil = brw->attribs.Stencil;
+ GLcontext *ctx = &brw->intel.ctx;
+ const unsigned back = ctx->Stencil._BackFace;
memset(key, 0, sizeof(*key));
- key->stencil = stencil->Enabled;
- key->stencil_two_side = stencil->_TestTwoSide;
+ key->stencil = ctx->Stencil._Enabled;
+ key->stencil_two_side = ctx->Stencil._TestTwoSide;
if (key->stencil) {
- key->stencil_func[0] = stencil->Function[0];
- key->stencil_fail_op[0] = stencil->FailFunc[0];
- key->stencil_pass_depth_fail_op[0] = stencil->ZFailFunc[0];
- key->stencil_pass_depth_pass_op[0] = stencil->ZPassFunc[0];
- key->stencil_ref[0] = stencil->Ref[0];
- key->stencil_write_mask[0] = stencil->WriteMask[0];
- key->stencil_test_mask[0] = stencil->ValueMask[0];
+ key->stencil_func[0] = ctx->Stencil.Function[0];
+ key->stencil_fail_op[0] = ctx->Stencil.FailFunc[0];
+ key->stencil_pass_depth_fail_op[0] = ctx->Stencil.ZFailFunc[0];
+ key->stencil_pass_depth_pass_op[0] = ctx->Stencil.ZPassFunc[0];
+ key->stencil_ref[0] = ctx->Stencil.Ref[0];
+ key->stencil_write_mask[0] = ctx->Stencil.WriteMask[0];
+ key->stencil_test_mask[0] = ctx->Stencil.ValueMask[0];
}
if (key->stencil_two_side) {
- key->stencil_func[1] = stencil->Function[1];
- key->stencil_fail_op[1] = stencil->FailFunc[1];
- key->stencil_pass_depth_fail_op[1] = stencil->ZFailFunc[1];
- key->stencil_pass_depth_pass_op[1] = stencil->ZPassFunc[1];
- key->stencil_ref[1] = stencil->Ref[1];
- key->stencil_write_mask[1] = stencil->WriteMask[1];
- key->stencil_test_mask[1] = stencil->ValueMask[1];
+ key->stencil_func[1] = ctx->Stencil.Function[back];
+ key->stencil_fail_op[1] = ctx->Stencil.FailFunc[back];
+ key->stencil_pass_depth_fail_op[1] = ctx->Stencil.ZFailFunc[back];
+ key->stencil_pass_depth_pass_op[1] = ctx->Stencil.ZPassFunc[back];
+ key->stencil_ref[1] = ctx->Stencil.Ref[back];
+ key->stencil_write_mask[1] = ctx->Stencil.WriteMask[back];
+ key->stencil_test_mask[1] = ctx->Stencil.ValueMask[back];
}
- if (brw->attribs.Color->_LogicOpEnabled)
- key->logic_op = brw->attribs.Color->LogicOp;
+ if (ctx->Color._LogicOpEnabled)
+ key->logic_op = ctx->Color.LogicOp;
else
key->logic_op = GL_COPY;
- key->color_blend = brw->attribs.Color->BlendEnabled;
+ key->color_blend = ctx->Color.BlendEnabled;
if (key->color_blend) {
- key->blend_eq_rgb = brw->attribs.Color->BlendEquationRGB;
- key->blend_eq_a = brw->attribs.Color->BlendEquationA;
- key->blend_src_rgb = brw->attribs.Color->BlendSrcRGB;
- key->blend_dst_rgb = brw->attribs.Color->BlendDstRGB;
- key->blend_src_a = brw->attribs.Color->BlendSrcA;
- key->blend_dst_a = brw->attribs.Color->BlendDstA;
+ key->blend_eq_rgb = ctx->Color.BlendEquationRGB;
+ key->blend_eq_a = ctx->Color.BlendEquationA;
+ key->blend_src_rgb = ctx->Color.BlendSrcRGB;
+ key->blend_dst_rgb = ctx->Color.BlendDstRGB;
+ key->blend_src_a = ctx->Color.BlendSrcA;
+ key->blend_dst_a = ctx->Color.BlendDstA;
}
- key->alpha_enabled = brw->attribs.Color->AlphaEnabled;
+ key->alpha_enabled = ctx->Color.AlphaEnabled;
if (key->alpha_enabled) {
- key->alpha_func = brw->attribs.Color->AlphaFunc;
- key->alpha_ref = brw->attribs.Color->AlphaRef;
+ key->alpha_func = ctx->Color.AlphaFunc;
+ key->alpha_ref = ctx->Color.AlphaRef;
}
- key->dither = brw->attribs.Color->DitherFlag;
+ key->dither = ctx->Color.DitherFlag;
- key->depth_test = brw->attribs.Depth->Test;
+ key->depth_test = ctx->Depth.Test;
if (key->depth_test) {
- key->depth_func = brw->attribs.Depth->Func;
- key->depth_write = brw->attribs.Depth->Mask;
+ key->depth_func = ctx->Depth.Func;
+ key->depth_write = ctx->Depth.Mask;
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_clip.c b/src/mesa/drivers/dri/i965/brw_clip.c
index 38d8b704d7..20a927cf38 100644
--- a/src/mesa/drivers/dri/i965/brw_clip.c
+++ b/src/mesa/drivers/dri/i965/brw_clip.c
@@ -65,21 +65,31 @@ static void compile_clip_prog( struct brw_context *brw,
c.func.single_program_flow = 1;
c.key = *key;
-
+ c.need_ff_sync = BRW_IS_IGDNG(brw);
/* Need to locate the two positions present in vertex + header.
* These are currently hardcoded:
*/
c.header_position_offset = ATTR_SIZE;
- for (i = 0, delta = REG_SIZE; i < VERT_RESULT_MAX; i++)
+ if (BRW_IS_IGDNG(brw))
+ delta = 3 * REG_SIZE;
+ else
+ delta = REG_SIZE;
+
+ for (i = 0; i < VERT_RESULT_MAX; i++)
if (c.key.attrs & (1<<i)) {
c.offset[i] = delta;
delta += ATTR_SIZE;
}
c.nr_attrs = brw_count_bits(c.key.attrs);
- c.nr_regs = (c.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */
+
+ if (BRW_IS_IGDNG(brw))
+ c.nr_regs = (c.nr_attrs + 1) / 2 + 3; /* are vertices packed, or reg-aligned? */
+ else
+ c.nr_regs = (c.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */
+
c.nr_bytes = c.nr_regs * REG_SIZE;
c.prog_data.clip_mode = c.key.clip_mode; /* XXX */
@@ -145,14 +155,19 @@ static void upload_clip_prog(struct brw_context *brw)
/* CACHE_NEW_VS_PROG */
key.attrs = brw->vs.prog_data->outputs_written;
/* _NEW_LIGHT */
- key.do_flat_shading = (brw->attribs.Light->ShadeModel == GL_FLAT);
+ key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);
/* _NEW_TRANSFORM */
- key.nr_userclip = brw_count_bits(brw->attribs.Transform->ClipPlanesEnabled);
- key.clip_mode = BRW_CLIPMODE_NORMAL;
+ key.nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled);
+
+ if (BRW_IS_IGDNG(brw))
+ key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
+ else
+ key.clip_mode = BRW_CLIPMODE_NORMAL;
/* _NEW_POLYGON */
if (key.primitive == GL_TRIANGLES) {
- if (brw->attribs.Polygon->CullFaceMode == GL_FRONT_AND_BACK)
+ if (ctx->Polygon.CullFlag &&
+ ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
else {
GLuint fill_front = CLIP_CULL;
@@ -160,44 +175,44 @@ static void upload_clip_prog(struct brw_context *brw)
GLuint offset_front = 0;
GLuint offset_back = 0;
- if (!brw->attribs.Polygon->CullFlag ||
- brw->attribs.Polygon->CullFaceMode != GL_FRONT) {
- switch (brw->attribs.Polygon->FrontMode) {
+ if (!ctx->Polygon.CullFlag ||
+ ctx->Polygon.CullFaceMode != GL_FRONT) {
+ switch (ctx->Polygon.FrontMode) {
case GL_FILL:
fill_front = CLIP_FILL;
offset_front = 0;
break;
case GL_LINE:
fill_front = CLIP_LINE;
- offset_front = brw->attribs.Polygon->OffsetLine;
+ offset_front = ctx->Polygon.OffsetLine;
break;
case GL_POINT:
fill_front = CLIP_POINT;
- offset_front = brw->attribs.Polygon->OffsetPoint;
+ offset_front = ctx->Polygon.OffsetPoint;
break;
}
}
- if (!brw->attribs.Polygon->CullFlag ||
- brw->attribs.Polygon->CullFaceMode != GL_BACK) {
- switch (brw->attribs.Polygon->BackMode) {
+ if (!ctx->Polygon.CullFlag ||
+ ctx->Polygon.CullFaceMode != GL_BACK) {
+ switch (ctx->Polygon.BackMode) {
case GL_FILL:
fill_back = CLIP_FILL;
offset_back = 0;
break;
case GL_LINE:
fill_back = CLIP_LINE;
- offset_back = brw->attribs.Polygon->OffsetLine;
+ offset_back = ctx->Polygon.OffsetLine;
break;
case GL_POINT:
fill_back = CLIP_POINT;
- offset_back = brw->attribs.Polygon->OffsetPoint;
+ offset_back = ctx->Polygon.OffsetPoint;
break;
}
}
- if (brw->attribs.Polygon->BackMode != GL_FILL ||
- brw->attribs.Polygon->FrontMode != GL_FILL) {
+ if (ctx->Polygon.BackMode != GL_FILL ||
+ ctx->Polygon.FrontMode != GL_FILL) {
key.do_unfilled = 1;
/* Most cases the fixed function units will handle. Cases where
@@ -207,17 +222,17 @@ static void upload_clip_prog(struct brw_context *brw)
if (offset_back || offset_front) {
/* _NEW_POLYGON, _NEW_BUFFERS */
- key.offset_units = brw->attribs.Polygon->OffsetUnits * brw->intel.polygon_offset_scale;
- key.offset_factor = brw->attribs.Polygon->OffsetFactor * ctx->DrawBuffer->_MRD;
+ key.offset_units = ctx->Polygon.OffsetUnits * brw->intel.polygon_offset_scale;
+ key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD;
}
- switch (brw->attribs.Polygon->FrontFace) {
+ switch (ctx->Polygon.FrontFace) {
case GL_CCW:
key.fill_ccw = fill_front;
key.fill_cw = fill_back;
key.offset_ccw = offset_front;
key.offset_cw = offset_back;
- if (brw->attribs.Light->Model.TwoSide &&
+ if (ctx->Light.Model.TwoSide &&
key.fill_cw != CLIP_CULL)
key.copy_bfc_cw = 1;
break;
@@ -226,7 +241,7 @@ static void upload_clip_prog(struct brw_context *brw)
key.fill_ccw = fill_back;
key.offset_cw = offset_front;
key.offset_ccw = offset_back;
- if (brw->attribs.Light->Model.TwoSide &&
+ if (ctx->Light.Model.TwoSide &&
key.fill_ccw != CLIP_CULL)
key.copy_bfc_ccw = 1;
break;
diff --git a/src/mesa/drivers/dri/i965/brw_clip.h b/src/mesa/drivers/dri/i965/brw_clip.h
index e06747864b..957df441ab 100644
--- a/src/mesa/drivers/dri/i965/brw_clip.h
+++ b/src/mesa/drivers/dri/i965/brw_clip.h
@@ -100,6 +100,8 @@ struct brw_clip_compile {
struct brw_reg fixed_planes;
struct brw_reg plane_equation;
+
+ struct brw_reg ff_sync;
} reg;
/* 3 different ways of expressing vertex size:
@@ -117,6 +119,7 @@ struct brw_clip_compile {
GLuint header_position_offset;
GLuint offset[VERT_ATTRIB_MAX];
+ GLboolean need_ff_sync;
};
#define ATTR_SIZE (4*4)
@@ -171,5 +174,6 @@ struct brw_reg get_tmp( struct brw_clip_compile *c );
void brw_clip_project_position(struct brw_clip_compile *c,
struct brw_reg pos );
-
+void brw_clip_ff_sync(struct brw_clip_compile *c);
+void brw_clip_init_ff_sync(struct brw_clip_compile *c);
#endif
diff --git a/src/mesa/drivers/dri/i965/brw_clip_line.c b/src/mesa/drivers/dri/i965/brw_clip_line.c
index c45d48dff8..048ca620fa 100644
--- a/src/mesa/drivers/dri/i965/brw_clip_line.c
+++ b/src/mesa/drivers/dri/i965/brw_clip_line.c
@@ -85,6 +85,10 @@ static void brw_clip_line_alloc_regs( struct brw_clip_compile *c )
i++;
}
+ if (c->need_ff_sync) {
+ c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
+ i++;
+ }
c->first_tmp = i;
c->last_tmp = i;
@@ -130,7 +134,7 @@ static void clip_and_emit_line( struct brw_clip_compile *c )
struct brw_instruction *plane_loop;
struct brw_instruction *plane_active;
struct brw_instruction *is_negative;
- struct brw_instruction *is_neg2;
+ struct brw_instruction *is_neg2 = NULL;
struct brw_instruction *not_culled;
struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD);
@@ -148,7 +152,7 @@ static void clip_and_emit_line( struct brw_clip_compile *c )
brw_clip_init_clipmask(c);
/* -ve rhw workaround */
- if (!BRW_IS_G4X(p->brw)) {
+ if (BRW_IS_965(p->brw)) {
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
brw_imm_ud(1<<20));
@@ -181,34 +185,54 @@ static void clip_and_emit_line( struct brw_clip_compile *c )
brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
is_negative = brw_IF(p, BRW_EXECUTE_1);
{
- brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
- brw_math_invert(p, c->reg.t, c->reg.t);
- brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);
-
- brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
- brw_MOV(p, c->reg.t1, c->reg.t);
- brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ /*
+ * Both can be negative on GM965/G965 due to RHW workaround
+ * if so, this object should be rejected.
+ */
+ if (BRW_IS_965(p->brw)) {
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0));
+ is_neg2 = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_kill_thread(c);
+ }
+ brw_ENDIF(p, is_neg2);
+ }
+
+ brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
+ brw_math_invert(p, c->reg.t, c->reg.t);
+ brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);
+
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
+ brw_MOV(p, c->reg.t1, c->reg.t);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
}
is_negative = brw_ELSE(p, is_negative);
{
- /* Coming back in. We know that both cannot be negative
- * because the line would have been culled in that case.
- */
+ /* Coming back in. We know that both cannot be negative
+ * because the line would have been culled in that case.
+ */
+
+ /* If both are positive, do nothing */
+ /* Only on GM965/G965 */
+ if (BRW_IS_965(p->brw)) {
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
+ is_neg2 = brw_IF(p, BRW_EXECUTE_1);
+ }
- /* If both are positive, do nothing */
- brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
- is_neg2 = brw_IF(p, BRW_EXECUTE_1);
{
- brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
- brw_math_invert(p, c->reg.t, c->reg.t);
- brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);
-
- brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
- brw_MOV(p, c->reg.t0, c->reg.t);
- brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- }
- brw_ENDIF(p, is_neg2);
- }
+ brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
+ brw_math_invert(p, c->reg.t, c->reg.t);
+ brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);
+
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
+ brw_MOV(p, c->reg.t0, c->reg.t);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ }
+
+ if (BRW_IS_965(p->brw)) {
+ brw_ENDIF(p, is_neg2);
+ }
+ }
brw_ENDIF(p, is_negative);
}
brw_ENDIF(p, plane_active);
@@ -243,6 +267,7 @@ static void clip_and_emit_line( struct brw_clip_compile *c )
void brw_emit_line_clip( struct brw_clip_compile *c )
{
brw_clip_line_alloc_regs(c);
+ brw_clip_init_ff_sync(c);
if (c->key.do_flat_shading)
brw_clip_copy_colors(c, 0, 1);
diff --git a/src/mesa/drivers/dri/i965/brw_clip_point.c b/src/mesa/drivers/dri/i965/brw_clip_point.c
index d17b199b89..8458f61c5a 100644
--- a/src/mesa/drivers/dri/i965/brw_clip_point.c
+++ b/src/mesa/drivers/dri/i965/brw_clip_point.c
@@ -50,5 +50,7 @@ void brw_emit_point_clip( struct brw_clip_compile *c )
/* Send an empty message to kill the thread:
*/
brw_clip_tri_alloc_regs(c, 0);
+ brw_clip_init_ff_sync(c);
+
brw_clip_kill_thread(c);
}
diff --git a/src/mesa/drivers/dri/i965/brw_clip_state.c b/src/mesa/drivers/dri/i965/brw_clip_state.c
index 9b0d7eab7b..234b3744bf 100644
--- a/src/mesa/drivers/dri/i965/brw_clip_state.c
+++ b/src/mesa/drivers/dri/i965/brw_clip_state.c
@@ -43,11 +43,14 @@ struct brw_clip_unit_key {
unsigned int curbe_offset;
unsigned int nr_urb_entries, urb_size;
+
+ GLboolean depth_clamp;
};
static void
clip_unit_populate_key(struct brw_context *brw, struct brw_clip_unit_key *key)
{
+ GLcontext *ctx = &brw->intel.ctx;
memset(key, 0, sizeof(*key));
/* CACHE_NEW_CLIP_PROG */
@@ -62,6 +65,9 @@ clip_unit_populate_key(struct brw_context *brw, struct brw_clip_unit_key *key)
/* BRW_NEW_URB_FENCE */
key->nr_urb_entries = brw->urb.nr_clip_entries;
key->urb_size = brw->urb.vsize;
+
+ /* _NEW_TRANSOFORM */
+ key->depth_clamp = ctx->Transform.DepthClamp;
}
static dri_bo *
@@ -95,7 +101,14 @@ clip_unit_create_from_key(struct brw_context *brw,
* even number.
*/
assert(key->nr_urb_entries % 2 == 0);
- clip.thread4.max_threads = 2 - 1;
+
+ /* Although up to 16 concurrent Clip threads are allowed on IGDNG,
+ * only 2 threads can output VUEs at a time.
+ */
+ if (BRW_IS_IGDNG(brw))
+ clip.thread4.max_threads = 16 - 1;
+ else
+ clip.thread4.max_threads = 2 - 1;
} else {
assert(key->nr_urb_entries >= 5);
clip.thread4.max_threads = 1 - 1;
@@ -110,7 +123,8 @@ clip_unit_create_from_key(struct brw_context *brw,
clip.clip5.userclip_enable_flags = 0x7f;
clip.clip5.userclip_must_clip = 1;
clip.clip5.guard_band_enable = 0;
- clip.clip5.viewport_z_clip_enable = 1;
+ if (!key->depth_clamp)
+ clip.clip5.viewport_z_clip_enable = 1;
clip.clip5.viewport_xy_clip_enable = 1;
clip.clip5.vertex_position_space = BRW_CLIP_NDCSPACE;
clip.clip5.api_mode = BRW_CLIP_API_OGL;
@@ -161,7 +175,7 @@ static void upload_clip_unit( struct brw_context *brw )
const struct brw_tracked_state brw_clip_unit = {
.dirty = {
- .mesa = 0,
+ .mesa = _NEW_TRANSFORM,
.brw = (BRW_NEW_CURBE_OFFSETS |
BRW_NEW_URB_FENCE),
.cache = CACHE_NEW_CLIP_PROG
diff --git a/src/mesa/drivers/dri/i965/brw_clip_tri.c b/src/mesa/drivers/dri/i965/brw_clip_tri.c
index 1dbba37fe7..0efd77225e 100644
--- a/src/mesa/drivers/dri/i965/brw_clip_tri.c
+++ b/src/mesa/drivers/dri/i965/brw_clip_tri.c
@@ -77,6 +77,10 @@ void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
if (c->nr_attrs & 1) {
for (j = 0; j < 3; j++) {
GLuint delta = c->nr_attrs*16 + 32;
+
+ if (BRW_IS_IGDNG(c->func.brw))
+ delta = c->nr_attrs * 16 + 32 * 3;
+
brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
}
}
@@ -115,6 +119,11 @@ void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
i++;
}
+ if (c->need_ff_sync) {
+ c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
+ i++;
+ }
+
c->first_tmp = i;
c->last_tmp = i;
@@ -455,6 +464,8 @@ static void brw_clip_test( struct brw_clip_compile *c )
struct brw_indirect vt2 = brw_indirect(2, 0);
struct brw_compile *p = &c->func;
+ struct brw_instruction *is_outside;
+ struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
@@ -462,53 +473,87 @@ static void brw_clip_test( struct brw_clip_compile *c )
brw_MOV(p, v0, deref_4f(vt0, c->offset[VERT_RESULT_HPOS]));
brw_MOV(p, v1, deref_4f(vt1, c->offset[VERT_RESULT_HPOS]));
brw_MOV(p, v2, deref_4f(vt2, c->offset[VERT_RESULT_HPOS]));
+ brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
/* test nearz, xmin, ymin plane */
- brw_CMP(p, t1, BRW_CONDITIONAL_LE, negate(v0), get_element(v0, 3));
+ /* clip.xyz < -clip.w */
+ brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_CMP(p, t2, BRW_CONDITIONAL_LE, negate(v1), get_element(v1, 3));
+ brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_CMP(p, t3, BRW_CONDITIONAL_LE, negate(v2), get_element(v2, 3));
+
+ /* All vertices are outside of a plane, rejected */
+ brw_AND(p, t, t1, t2);
+ brw_AND(p, t, t, t3);
+ brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
+ brw_OR(p, tmp0, tmp0, get_element(t, 2));
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
+ is_outside = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_kill_thread(c);
+ }
+ brw_ENDIF(p, is_outside);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ /* some vertices are inside a plane, some are outside,need to clip */
brw_XOR(p, t, t1, t2);
brw_XOR(p, t1, t2, t3);
brw_OR(p, t, t, t1);
-
- brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
- get_element(t, 0), brw_imm_ud(0));
+ brw_AND(p, t, t, brw_imm_ud(0x1));
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 0), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
- get_element(t, 1), brw_imm_ud(0));
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 1), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
- get_element(t, 2), brw_imm_ud(0));
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 2), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
/* test farz, xmax, ymax plane */
- brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, get_element(v0, 3));
+ /* clip.xyz > clip.w */
+ brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, get_element(v1, 3));
+ brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, get_element(v2, 3));
+ brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+ /* All vertices are outside of a plane, rejected */
+ brw_AND(p, t, t1, t2);
+ brw_AND(p, t, t, t3);
+ brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
+ brw_OR(p, tmp0, tmp0, get_element(t, 2));
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+ brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
+ is_outside = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_clip_kill_thread(c);
+ }
+ brw_ENDIF(p, is_outside);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ /* some vertices are inside a plane, some are outside,need to clip */
brw_XOR(p, t, t1, t2);
brw_XOR(p, t1, t2, t3);
brw_OR(p, t, t, t1);
-
- brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
- get_element(t, 0), brw_imm_ud(0));
+ brw_AND(p, t, t, brw_imm_ud(0x1));
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 0), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
- get_element(t, 1), brw_imm_ud(0));
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 1), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
- get_element(t, 2), brw_imm_ud(0));
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
+ get_element(t, 2), brw_imm_ud(0));
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
@@ -523,10 +568,11 @@ void brw_emit_tri_clip( struct brw_clip_compile *c )
brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
brw_clip_tri_init_vertices(c);
brw_clip_init_clipmask(c);
+ brw_clip_init_ff_sync(c);
/* if -ve rhw workaround bit is set,
do cliptest */
- if (!BRW_IS_G4X(p->brw)) {
+ if (BRW_IS_965(p->brw)) {
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
brw_imm_ud(1<<20));
@@ -543,11 +589,12 @@ void brw_emit_tri_clip( struct brw_clip_compile *c )
if (c->key.do_flat_shading)
brw_clip_tri_flat_shade(c);
- if (c->key.clip_mode == BRW_CLIPMODE_NORMAL)
+ if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
+ (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
do_clip_tri(c);
else
maybe_do_clip_tri(c);
-
+
brw_clip_tri_emit_polygon(c);
/* Send an empty message to kill the thread:
diff --git a/src/mesa/drivers/dri/i965/brw_clip_unfilled.c b/src/mesa/drivers/dri/i965/brw_clip_unfilled.c
index d7ca517927..ad1bfa435f 100644
--- a/src/mesa/drivers/dri/i965/brw_clip_unfilled.c
+++ b/src/mesa/drivers/dri/i965/brw_clip_unfilled.c
@@ -453,6 +453,7 @@ void brw_emit_unfilled_clip( struct brw_clip_compile *c )
brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
brw_clip_tri_init_vertices(c);
+ brw_clip_init_ff_sync(c);
assert(c->offset[VERT_RESULT_EDGE]);
diff --git a/src/mesa/drivers/dri/i965/brw_clip_util.c b/src/mesa/drivers/dri/i965/brw_clip_util.c
index 9d3b0be694..5a73abdfee 100644
--- a/src/mesa/drivers/dri/i965/brw_clip_util.c
+++ b/src/mesa/drivers/dri/i965/brw_clip_util.c
@@ -140,6 +140,10 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,
/* Just copy the vertex header:
*/
+ /*
+ * After CLIP stage, only first 256 bits of the VUE are read
+ * back on IGDNG, so needn't change it
+ */
brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);
/* Iterate over each attribute (could be done in pairs?)
@@ -147,6 +151,9 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,
for (i = 0; i < c->nr_attrs; i++) {
GLuint delta = i*16 + 32;
+ if (BRW_IS_IGDNG(p->brw))
+ delta = i * 16 + 32 * 3;
+
if (delta == c->offset[VERT_RESULT_EDGE]) {
if (force_edgeflag)
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
@@ -177,6 +184,10 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,
if (i & 1) {
GLuint delta = i*16 + 32;
+
+ if (BRW_IS_IGDNG(p->brw))
+ delta = i * 16 + 32 * 3;
+
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
}
@@ -202,6 +213,8 @@ void brw_clip_emit_vue(struct brw_clip_compile *c,
struct brw_compile *p = &c->func;
GLuint start = c->last_mrf;
+ brw_clip_ff_sync(c);
+
assert(!(allocate && eot));
/* Cycle through mrf regs - probably futile as we have to wait for
@@ -252,6 +265,7 @@ void brw_clip_kill_thread(struct brw_clip_compile *c)
{
struct brw_compile *p = &c->func;
+ brw_clip_ff_sync(c);
/* Send an empty message to kill the thread and release any
* allocated urb entry:
*/
@@ -343,3 +357,40 @@ void brw_clip_init_clipmask( struct brw_clip_compile *c )
}
}
+void brw_clip_ff_sync(struct brw_clip_compile *c)
+{
+ if (c->need_ff_sync) {
+ struct brw_compile *p = &c->func;
+ struct brw_instruction *need_ff_sync;
+
+ brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
+ brw_AND(p, brw_null_reg(), c->reg.ff_sync, brw_imm_ud(0x1));
+ need_ff_sync = brw_IF(p, BRW_EXECUTE_1);
+ {
+ brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1));
+ brw_ff_sync(p,
+ c->reg.R0,
+ 0,
+ c->reg.R0,
+ 1,
+ 1, /* used */
+ 1, /* msg length */
+ 1, /* response length */
+ 0, /* eot */
+ 1, /* write compelete */
+ 0, /* urb offset */
+ BRW_URB_SWIZZLE_NONE);
+ }
+ brw_ENDIF(p, need_ff_sync);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ }
+}
+
+void brw_clip_init_ff_sync(struct brw_clip_compile *c)
+{
+ if (c->need_ff_sync) {
+ struct brw_compile *p = &c->func;
+
+ brw_MOV(p, c->reg.ff_sync, brw_imm_ud(0));
+ }
+}
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index d7a2bd95ee..3c5b848319 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -76,30 +76,6 @@ static void brwInitDriverFunctions( struct dd_function_table *functions )
functions->Viewport = intel_viewport;
}
-
-static void brw_init_attribs( struct brw_context *brw )
-{
- GLcontext *ctx = &brw->intel.ctx;
-
- brw->attribs.Color = &ctx->Color;
- brw->attribs.Depth = &ctx->Depth;
- brw->attribs.Fog = &ctx->Fog;
- brw->attribs.Hint = &ctx->Hint;
- brw->attribs.Light = &ctx->Light;
- brw->attribs.Line = &ctx->Line;
- brw->attribs.Point = &ctx->Point;
- brw->attribs.Polygon = &ctx->Polygon;
- brw->attribs.Scissor = &ctx->Scissor;
- brw->attribs.Stencil = &ctx->Stencil;
- brw->attribs.Texture = &ctx->Texture;
- brw->attribs.Transform = &ctx->Transform;
- brw->attribs.Viewport = &ctx->Viewport;
- brw->attribs.VertexProgram = &ctx->VertexProgram;
- brw->attribs.FragmentProgram = &ctx->FragmentProgram;
- brw->attribs.PolygonStipple = &ctx->PolygonStipple[0];
-}
-
-
GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate)
@@ -135,21 +111,48 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
ctx->Const.MaxTextureImageUnits);
ctx->Const.MaxVertexTextureImageUnits = 0; /* no vertex shader textures */
- /* Advertise the full hardware capabilities. The new memory
- * manager should cope much better with overload situations:
+ /* Mesa limits textures to 4kx4k; it would be nice to fix that someday
*/
- ctx->Const.MaxTextureLevels = 12;
+ ctx->Const.MaxTextureLevels = 13;
ctx->Const.Max3DTextureLevels = 9;
ctx->Const.MaxCubeTextureLevels = 12;
- ctx->Const.MaxTextureRectSize = (1<<11);
+ ctx->Const.MaxTextureRectSize = (1<<12);
+ ctx->Const.MaxTextureMaxAnisotropy = 16.0;
+
/* if conformance mode is set, swrast can handle any size AA point */
ctx->Const.MaxPointSizeAA = 255.0;
-/* ctx->Const.MaxNativeVertexProgramTemps = 32; */
+ /* We want the GLSL compiler to emit code that uses condition codes */
+ ctx->Shader.EmitCondCodes = GL_TRUE;
+
+ ctx->Const.VertexProgram.MaxNativeInstructions = (16 * 1024);
+ ctx->Const.VertexProgram.MaxAluInstructions = 0;
+ ctx->Const.VertexProgram.MaxTexInstructions = 0;
+ ctx->Const.VertexProgram.MaxTexIndirections = 0;
+ ctx->Const.VertexProgram.MaxNativeAluInstructions = 0;
+ ctx->Const.VertexProgram.MaxNativeTexInstructions = 0;
+ ctx->Const.VertexProgram.MaxNativeTexIndirections = 0;
+ ctx->Const.VertexProgram.MaxNativeAttribs = 16;
+ ctx->Const.VertexProgram.MaxNativeTemps = 256;
+ ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
+ ctx->Const.VertexProgram.MaxNativeParameters = 1024;
+ ctx->Const.VertexProgram.MaxEnvParams =
+ MIN2(ctx->Const.VertexProgram.MaxNativeParameters,
+ ctx->Const.VertexProgram.MaxEnvParams);
+
+ ctx->Const.FragmentProgram.MaxNativeInstructions = (16 * 1024);
+ ctx->Const.FragmentProgram.MaxNativeAluInstructions = (16 * 1024);
+ ctx->Const.FragmentProgram.MaxNativeTexInstructions = (16 * 1024);
+ ctx->Const.FragmentProgram.MaxNativeTexIndirections = (16 * 1024);
+ ctx->Const.FragmentProgram.MaxNativeAttribs = 12;
+ ctx->Const.FragmentProgram.MaxNativeTemps = 256;
+ ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0;
+ ctx->Const.FragmentProgram.MaxNativeParameters = 1024;
+ ctx->Const.FragmentProgram.MaxEnvParams =
+ MIN2(ctx->Const.FragmentProgram.MaxNativeParameters,
+ ctx->Const.FragmentProgram.MaxEnvParams);
- brw_init_attribs( brw );
- brw_init_metaops( brw );
brw_init_state( brw );
brw->state.dirty.mesa = ~0;
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 5d3f99e025..a5209ac41b 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -46,7 +46,7 @@
*
* CURBE - constant URB entry. An urb region (entry) used to hold
* constant values which the fixed function units can be instructed to
- * preload into the GRF when spawining a thread.
+ * preload into the GRF when spawning a thread.
*
* VUE - vertex URB entry. An urb entry holding a vertex and usually
* a vertex header. The header contains control information and
@@ -63,7 +63,7 @@
* special and may be overwritten.
*
* MRF - message register file. Threads communicate (and terminate)
- * by sending messages. Message parameters are placed in contigous
+ * by sending messages. Message parameters are placed in contiguous
* MRF registers. All program output is via these messages. URB
* entries are populated by sending a message to the shared URB
* function containing the new data, together with a control word,
@@ -129,9 +129,8 @@ struct brw_context;
#define BRW_NEW_PRIMITIVE 0x40
#define BRW_NEW_CONTEXT 0x80
#define BRW_NEW_WM_INPUT_DIMENSIONS 0x100
-#define BRW_NEW_INPUT_VARYING 0x200
#define BRW_NEW_PSP 0x800
-#define BRW_NEW_METAOPS 0x1000
+#define BRW_NEW_WM_SURFACES 0x1000
#define BRW_NEW_FENCE 0x2000
#define BRW_NEW_INDICES 0x4000
#define BRW_NEW_VERTICES 0x8000
@@ -142,7 +141,9 @@ struct brw_context;
#define BRW_NEW_BATCH 0x10000
/** brw->depth_region updated */
#define BRW_NEW_DEPTH_BUFFER 0x20000
-#define BRW_NEW_NR_SURFACES 0x40000
+#define BRW_NEW_NR_WM_SURFACES 0x40000
+#define BRW_NEW_NR_VS_SURFACES 0x80000
+#define BRW_NEW_INDEX_BUFFER 0x100000
struct brw_state_flags {
/** State update flags signalled by mesa internals */
@@ -155,19 +156,28 @@ struct brw_state_flags {
GLuint cache;
};
+
+/** Subclass of Mesa vertex program */
struct brw_vertex_program {
struct gl_vertex_program program;
GLuint id;
+ dri_bo *const_buffer; /** Program constant buffer/surface */
+ GLboolean use_const_buffer;
};
-
+/** Subclass of Mesa fragment program */
struct brw_fragment_program {
struct gl_fragment_program program;
- GLuint id;
-};
+ GLuint id; /**< serial no. to identify frag progs, never re-used */
+ GLboolean isGLSL; /**< really, any IF/LOOP/CONT/BREAK instructions */
+ dri_bo *const_buffer; /** Program constant buffer/surface */
+ GLboolean use_const_buffer;
+ /** for debugging, which texture units are referenced */
+ GLbitfield tex_units_used;
+};
/* Data about a particular attempt to compile a program. Note that
@@ -183,7 +193,7 @@ struct brw_wm_prog_data {
GLuint total_grf;
GLuint total_scratch;
- GLuint nr_params;
+ GLuint nr_params; /**< number of float params/constants */
GLboolean error;
/* Pointer to tracked values (only valid once
@@ -222,6 +232,7 @@ struct brw_vs_prog_data {
GLuint urb_read_length;
GLuint total_grf;
GLuint outputs_written;
+ GLuint nr_params; /**< number of float params/constants */
GLuint inputs_read;
@@ -238,8 +249,35 @@ struct brw_vs_ouput_sizes {
};
+/** Number of texture sampler units */
#define BRW_MAX_TEX_UNIT 16
-#define BRW_WM_MAX_SURF BRW_MAX_TEX_UNIT + MAX_DRAW_BUFFERS
+
+/**
+ * Size of our surface binding table for the WM.
+ * This contains pointers to the drawing surfaces and current texture
+ * objects and shader constant buffers (+2).
+ */
+#define BRW_WM_MAX_SURF (MAX_DRAW_BUFFERS + BRW_MAX_TEX_UNIT + 1)
+
+/**
+ * Helpers to convert drawing buffers, textures and constant buffers
+ * to surface binding table indexes, for WM.
+ */
+#define SURF_INDEX_DRAW(d) (d)
+#define SURF_INDEX_FRAG_CONST_BUFFER (MAX_DRAW_BUFFERS)
+#define SURF_INDEX_TEXTURE(t) (MAX_DRAW_BUFFERS + 1 + (t))
+
+/**
+ * Size of surface binding table for the VS.
+ * Only one constant buffer for now.
+ */
+#define BRW_VS_MAX_SURF 1
+
+/**
+ * Only a VS constant buffer
+ */
+#define SURF_INDEX_VERT_CONST_BUFFER 0
+
enum brw_cache_id {
BRW_CC_VP,
@@ -303,26 +341,6 @@ struct brw_cache {
};
-
-struct brw_state_pointers {
- struct gl_colorbuffer_attrib *Color;
- struct gl_depthbuffer_attrib *Depth;
- struct gl_fog_attrib *Fog;
- struct gl_hint_attrib *Hint;
- struct gl_light_attrib *Light;
- struct gl_line_attrib *Line;
- struct gl_point_attrib *Point;
- struct gl_polygon_attrib *Polygon;
- GLuint *PolygonStipple;
- struct gl_scissor_attrib *Scissor;
- struct gl_stencil_attrib *Stencil;
- struct gl_texture_attrib *Texture;
- struct gl_transform_attrib *Transform;
- struct gl_viewport_attrib *Viewport;
- struct gl_vertex_program_state *VertexProgram;
- struct gl_fragment_program_state *FragmentProgram;
-};
-
/* Considered adding a member to this struct to document which flags
* an update might raise so that ordering of the state atoms can be
* checked or derived at runtime. Dropped the idea in favor of having
@@ -372,6 +390,8 @@ struct brw_cached_batch_item {
struct brw_vertex_element {
const struct gl_client_array *glarray;
+ /** The corresponding Mesa vertex attribute */
+ gl_vert_attrib attrib;
/** Size of a complete element */
GLuint element_size;
/** Number of uploaded elements for this input. */
@@ -387,7 +407,6 @@ struct brw_vertex_element {
struct brw_vertex_info {
- GLuint varying; /* varying:1[VERT_ATTRIB_MAX] */
GLuint sizes[ATTRIB_BIT_DWORDS * 2]; /* sizes:2[VERT_ATTRIB_MAX] */
};
@@ -425,9 +444,13 @@ struct brw_query_object {
unsigned int count;
};
+
+/**
+ * brw_context is derived from intel_context.
+ */
struct brw_context
{
- struct intel_context intel;
+ struct intel_context intel; /**< base class, must be first field */
GLuint primitive;
GLboolean emit_state_always;
@@ -436,11 +459,9 @@ struct brw_context
struct {
struct brw_state_flags dirty;
- struct brw_tracked_state **atoms;
- GLuint nr_atoms;
- GLuint nr_draw_regions;
- struct intel_region *draw_regions[MAX_DRAW_BUFFERS];
+ GLuint nr_color_regions;
+ struct intel_region *color_regions[MAX_DRAW_BUFFERS];
struct intel_region *depth_region;
/**
@@ -457,13 +478,16 @@ struct brw_context
int validated_bo_count;
} state;
- struct brw_state_pointers attribs;
- struct brw_cache cache;
+ struct brw_cache cache; /** non-surface items */
+ struct brw_cache surface_cache; /* surface items */
struct brw_cached_batch_item *cached_batch_items;
struct {
struct brw_vertex_element inputs[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)
@@ -487,31 +511,16 @@ struct brw_context
*/
const struct _mesa_index_buffer *ib;
+ /* Updates to these fields are signaled by BRW_NEW_INDEX_BUFFER. */
dri_bo *bo;
unsigned int offset;
- } ib;
-
- struct {
- /* Will be allocated on demand if needed.
+ 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.
*/
- struct brw_state_pointers attribs;
- struct gl_vertex_program *vp;
- struct gl_fragment_program *fp, *fp_tex;
-
- struct gl_buffer_object *vbo;
-
- struct intel_region *saved_draw_region;
- GLuint saved_nr_draw_regions;
- struct intel_region *saved_depth_region;
-
- GLuint restore_draw_buffers[MAX_DRAW_BUFFERS];
- GLuint restore_num_draw_buffers;
-
- struct gl_fragment_program *restore_fp;
-
- GLboolean active;
- } metaops;
-
+ unsigned int start_vertex_offset;
+ } ib;
/* Active vertex program:
*/
@@ -556,19 +565,14 @@ struct brw_context
/* BRW_NEW_CURBE_OFFSETS:
*/
struct {
- GLuint wm_start;
- GLuint wm_size;
+ GLuint wm_start; /**< pos of first wm const in CURBE buffer */
+ GLuint wm_size; /**< number of float[4] consts, multiple of 16 */
GLuint clip_start;
GLuint clip_size;
GLuint vs_start;
GLuint vs_size;
GLuint total_size;
- /* Dynamic tracker which changes to reflect the state referenced
- * by active fp and vp program parameters:
- */
- struct brw_tracked_state tracked_state;
-
dri_bo *curbe_bo;
/** Offset within curbe_bo of space for current curbe entry */
GLuint curbe_offset;
@@ -589,6 +593,11 @@ struct brw_context
dri_bo *prog_bo;
dri_bo *state_bo;
+
+ /** Binding table of pointers to surf_bo entries */
+ dri_bo *bind_bo;
+ dri_bo *surf_bo[BRW_VS_MAX_SURF];
+ GLuint nr_surfaces;
} vs;
struct {
@@ -620,9 +629,10 @@ struct brw_context
struct brw_wm_prog_data *prog_data;
struct brw_wm_compile *compile_data;
- /* Input sizes, calculated from active vertex program:
+ /** Input sizes, calculated from active vertex program.
+ * One bit per fragment program input attribute.
*/
- GLuint input_size_masks[4];
+ GLbitfield input_size_masks[4];
/** Array of surface default colors (texture border color) */
dri_bo *sdc_bo[BRW_MAX_TEX_UNIT];
@@ -631,7 +641,7 @@ struct brw_context
GLuint nr_surfaces;
GLuint max_threads;
- dri_bo *scratch_buffer;
+ dri_bo *scratch_bo;
GLuint sampler_count;
dri_bo *sampler_bo;
@@ -671,8 +681,6 @@ struct brw_context
* brw_vtbl.c
*/
void brwInitVtbl( struct brw_context *brw );
-void brw_do_flush( struct brw_context *brw,
- GLuint flags );
/*======================================================================
* brw_context.c
@@ -703,13 +711,6 @@ void brw_FrameBufferTexInit( struct brw_context *brw,
void brw_FrameBufferTexDestroy( struct brw_context *brw );
void brw_validate_textures( struct brw_context *brw );
-/*======================================================================
- * brw_metaops.c
- */
-
-void brw_init_metaops( struct brw_context *brw );
-void brw_destroy_metaops( struct brw_context *brw );
-
/*======================================================================
* brw_program.c
@@ -721,8 +722,12 @@ void brwInitFragProgFuncs( struct dd_function_table *functions );
*/
void brw_upload_urb_fence(struct brw_context *brw);
-void brw_upload_constant_buffer_state(struct brw_context *brw);
+/* brw_curbe.c
+ */
+void brw_upload_cs_urb_state(struct brw_context *brw);
+/* brw_disasm.c */
+int brw_disasm (FILE *file, struct brw_instruction *inst);
/*======================================================================
* Inline conversion functions. These are better-typed than the
@@ -734,6 +739,32 @@ brw_context( GLcontext *ctx )
return (struct brw_context *)ctx;
}
+static INLINE struct brw_vertex_program *
+brw_vertex_program(struct gl_vertex_program *p)
+{
+ return (struct brw_vertex_program *) p;
+}
+
+static INLINE const struct brw_vertex_program *
+brw_vertex_program_const(const struct gl_vertex_program *p)
+{
+ return (const struct brw_vertex_program *) p;
+}
+
+static INLINE struct brw_fragment_program *
+brw_fragment_program(struct gl_fragment_program *p)
+{
+ return (struct brw_fragment_program *) p;
+}
+
+static INLINE const struct brw_fragment_program *
+brw_fragment_program_const(const struct gl_fragment_program *p)
+{
+ return (const struct brw_fragment_program *) p;
+}
+
+
+
#define DO_SETUP_BITS ((1<<(FRAG_ATTRIB_MAX)) - 1)
#endif
diff --git a/src/mesa/drivers/dri/i965/brw_curbe.c b/src/mesa/drivers/dri/i965/brw_curbe.c
index fbf473abf6..0b0e6931a0 100644
--- a/src/mesa/drivers/dri/i965/brw_curbe.c
+++ b/src/mesa/drivers/dri/i965/brw_curbe.c
@@ -36,30 +36,37 @@
#include "main/macros.h"
#include "main/enums.h"
#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
#include "shader/prog_statevars.h"
#include "intel_batchbuffer.h"
+#include "intel_regions.h"
#include "brw_context.h"
#include "brw_defines.h"
#include "brw_state.h"
#include "brw_util.h"
-/* Partition the CURBE between the various users of constant values:
+/**
+ * Partition the CURBE between the various users of constant values:
+ * Note that vertex and fragment shaders can now fetch constants out
+ * of constant buffers. We no longer allocatea block of the GRF for
+ * constants. That greatly reduces the demand for space in the CURBE.
+ * Some of the comments within are dated...
*/
static void calculate_curbe_offsets( struct brw_context *brw )
{
+ GLcontext *ctx = &brw->intel.ctx;
/* CACHE_NEW_WM_PROG */
- GLuint nr_fp_regs = (brw->wm.prog_data->nr_params + 15) / 16;
+ const GLuint nr_fp_regs = (brw->wm.prog_data->nr_params + 15) / 16;
/* BRW_NEW_VERTEX_PROGRAM */
- struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program;
- GLuint nr_vp_regs = (vp->program.Base.Parameters->NumParameters * 4 + 15) / 16;
+ const GLuint nr_vp_regs = (brw->vs.prog_data->nr_params + 15) / 16;
GLuint nr_clip_regs = 0;
GLuint total_regs;
/* _NEW_TRANSFORM */
- if (brw->attribs.Transform->ClipPlanesEnabled) {
- GLuint nr_planes = 6 + brw_count_bits(brw->attribs.Transform->ClipPlanesEnabled);
+ if (ctx->Transform.ClipPlanesEnabled) {
+ GLuint nr_planes = 6 + brw_count_bits(ctx->Transform.ClipPlanesEnabled);
nr_clip_regs = (nr_planes * 4 + 15) / 16;
}
@@ -137,24 +144,24 @@ const struct brw_tracked_state brw_curbe_offsets = {
* fixed-function hardware in a double-buffering scheme to avoid a
* pipeline stall each time the contents of the curbe is changed.
*/
-void brw_upload_constant_buffer_state(struct brw_context *brw)
+void brw_upload_cs_urb_state(struct brw_context *brw)
{
- struct brw_constant_buffer_state cbs;
- memset(&cbs, 0, sizeof(cbs));
+ struct brw_cs_urb_state cs_urb;
+ memset(&cs_urb, 0, sizeof(cs_urb));
/* 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.
*/
- cbs.header.opcode = CMD_CONST_BUFFER_STATE;
- cbs.header.length = sizeof(cbs)/4 - 2;
+ cs_urb.header.opcode = CMD_CS_URB_STATE;
+ cs_urb.header.length = sizeof(cs_urb)/4 - 2;
/* BRW_NEW_URB_FENCE */
- cbs.bits0.nr_urb_entries = brw->urb.nr_cs_entries;
- cbs.bits0.urb_entry_size = brw->urb.csize - 1;
+ 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, &cbs);
+ BRW_CACHED_BATCH_STRUCT(brw, &cs_urb);
}
static GLfloat fixed_plane[6][4] = {
@@ -173,42 +180,35 @@ static GLfloat fixed_plane[6][4] = {
static void prepare_constant_buffer(struct brw_context *brw)
{
GLcontext *ctx = &brw->intel.ctx;
- struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program;
- struct brw_fragment_program *fp = (struct brw_fragment_program *)brw->fragment_program;
- GLuint sz = brw->curbe.total_size;
- GLuint bufsz = sz * 16 * sizeof(GLfloat);
+ const struct brw_vertex_program *vp =
+ brw_vertex_program_const(brw->vertex_program);
+ const struct brw_fragment_program *fp =
+ brw_fragment_program_const(brw->fragment_program);
+ const GLuint sz = brw->curbe.total_size;
+ const GLuint bufsz = sz * 16 * sizeof(GLfloat);
GLfloat *buf;
GLuint i;
- /* Update our own dependency flags. This works because this
- * function will also be called whenever fp or vp changes.
- */
- brw->curbe.tracked_state.dirty.mesa = (_NEW_TRANSFORM|_NEW_PROJECTION);
- brw->curbe.tracked_state.dirty.mesa |= vp->program.Base.Parameters->StateFlags;
- brw->curbe.tracked_state.dirty.mesa |= fp->program.Base.Parameters->StateFlags;
-
if (sz == 0) {
-
if (brw->curbe.last_buf) {
free(brw->curbe.last_buf);
brw->curbe.last_buf = NULL;
brw->curbe.last_bufsz = 0;
}
-
return;
}
- buf = (GLfloat *)malloc(bufsz);
-
- memset(buf, 0, bufsz);
+ buf = (GLfloat *) _mesa_calloc(bufsz);
+ /* fragment shader constants */
if (brw->curbe.wm_size) {
GLuint offset = brw->curbe.wm_start * 16;
_mesa_load_state_parameters(ctx, fp->program.Base.Parameters);
+ /* copy float constants */
for (i = 0; i < brw->wm.prog_data->nr_params; i++)
- buf[offset + i] = brw->wm.prog_data->param[i][0];
+ buf[offset + i] = *brw->wm.prog_data->param[i];
}
@@ -233,28 +233,33 @@ static void prepare_constant_buffer(struct brw_context *brw)
*/
assert(MAX_CLIP_PLANES == 6);
for (j = 0; j < MAX_CLIP_PLANES; j++) {
- if (brw->attribs.Transform->ClipPlanesEnabled & (1<<j)) {
- buf[offset + i * 4 + 0] = brw->attribs.Transform->_ClipUserPlane[j][0];
- buf[offset + i * 4 + 1] = brw->attribs.Transform->_ClipUserPlane[j][1];
- buf[offset + i * 4 + 2] = brw->attribs.Transform->_ClipUserPlane[j][2];
- buf[offset + i * 4 + 3] = brw->attribs.Transform->_ClipUserPlane[j][3];
+ if (ctx->Transform.ClipPlanesEnabled & (1<<j)) {
+ buf[offset + i * 4 + 0] = ctx->Transform._ClipUserPlane[j][0];
+ buf[offset + i * 4 + 1] = ctx->Transform._ClipUserPlane[j][1];
+ buf[offset + i * 4 + 2] = ctx->Transform._ClipUserPlane[j][2];
+ buf[offset + i * 4 + 3] = ctx->Transform._ClipUserPlane[j][3];
i++;
}
}
}
-
+ /* vertex shader constants */
if (brw->curbe.vs_size) {
GLuint offset = brw->curbe.vs_start * 16;
- GLuint nr = vp->program.Base.Parameters->NumParameters;
+ GLuint nr = brw->vs.prog_data->nr_params / 4;
+ /* Updates the ParamaterValues[i] pointers for all parameters of the
+ * basic type of PROGRAM_STATE_VAR.
+ */
_mesa_load_state_parameters(ctx, vp->program.Base.Parameters);
+ /* XXX just use a memcpy here */
for (i = 0; i < nr; i++) {
- buf[offset + i * 4 + 0] = vp->program.Base.Parameters->ParameterValues[i][0];
- buf[offset + i * 4 + 1] = vp->program.Base.Parameters->ParameterValues[i][1];
- buf[offset + i * 4 + 2] = vp->program.Base.Parameters->ParameterValues[i][2];
- buf[offset + i * 4 + 3] = vp->program.Base.Parameters->ParameterValues[i][3];
+ const GLfloat *value = vp->program.Base.Parameters->ParameterValues[i];
+ buf[offset + i * 4 + 0] = value[0];
+ buf[offset + i * 4 + 1] = value[1];
+ buf[offset + i * 4 + 2] = value[2];
+ buf[offset + i * 4 + 3] = value[3];
}
}
@@ -273,11 +278,14 @@ static void prepare_constant_buffer(struct brw_context *brw)
brw->curbe.last_buf &&
bufsz == brw->curbe.last_bufsz &&
memcmp(buf, brw->curbe.last_buf, bufsz) == 0) {
- free(buf);
+ /* constants have not changed */
+ _mesa_free(buf);
}
else {
+ /* constants have changed */
if (brw->curbe.last_buf)
- free(brw->curbe.last_buf);
+ _mesa_free(brw->curbe.last_buf);
+
brw->curbe.last_buf = buf;
brw->curbe.last_bufsz = bufsz;
@@ -324,7 +332,6 @@ static void prepare_constant_buffer(struct brw_context *brw)
*/
}
-
static void emit_constant_buffer(struct brw_context *brw)
{
struct intel_context *intel = &brw->intel;
@@ -351,7 +358,7 @@ static void emit_constant_buffer(struct brw_context *brw)
*/
const struct brw_tracked_state brw_constant_buffer = {
.dirty = {
- .mesa = (_NEW_TRANSFORM|_NEW_PROJECTION), /* plus fp and vp flags */
+ .mesa = _NEW_PROGRAM_CONSTANTS,
.brw = (BRW_NEW_FRAGMENT_PROGRAM |
BRW_NEW_VERTEX_PROGRAM |
BRW_NEW_URB_FENCE | /* Implicit - hardware requires this, not used above */
diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h
index 39c32255f8..78d457ad2b 100644
--- a/src/mesa/drivers/dri/i965/brw_defines.h
+++ b/src/mesa/drivers/dri/i965/brw_defines.h
@@ -139,6 +139,7 @@
#define BRW_CLIPMODE_CLIP_NON_REJECTED 2
#define BRW_CLIPMODE_REJECT_ALL 3
#define BRW_CLIPMODE_ACCEPT_ALL 4
+#define BRW_CLIPMODE_KERNEL_CLIP 5
#define BRW_CLIP_NDCSPACE 0
#define BRW_CLIP_SCREENSPACE 1
@@ -225,6 +226,24 @@
#define BRW_RASTRULE_UPPER_LEFT 0
#define BRW_RASTRULE_UPPER_RIGHT 1
+/* These are listed as "Reserved, but not seen as useful"
+ * in Intel documentation (page 212, "Point Rasterization Rule",
+ * section 7.4 "SF Pipeline State Summary", of document
+ * "Intel® 965 Express Chipset Family and Intel® G35 Express
+ * Chipset Graphics Controller Programmer's Reference Manual,
+ * Volume 2: 3D/Media", Revision 1.0b as of January 2008,
+ * available at
+ * http://intellinuxgraphics.org/documentation.html
+ * at the time of this writing).
+ *
+ * These appear to be supported on at least some
+ * i965-family devices, and the BRW_RASTRULE_LOWER_RIGHT
+ * is useful when using OpenGL to render to a FBO
+ * (which has the pixel coordinate Y orientation inverted
+ * with respect to the normal OpenGL pixel coordinate system).
+ */
+#define BRW_RASTRULE_LOWER_LEFT 2
+#define BRW_RASTRULE_LOWER_RIGHT 3
#define BRW_RENDERTARGET_CLAMPRANGE_UNORM 0
#define BRW_RENDERTARGET_CLAMPRANGE_SNORM 1
@@ -349,9 +368,10 @@
#define BRW_SURFACEFORMAT_L8A8_UNORM 0x114
#define BRW_SURFACEFORMAT_I16_FLOAT 0x115
#define BRW_SURFACEFORMAT_L16_FLOAT 0x116
-#define BRW_SURFACEFORMAT_A16_FLOAT 0x117
-#define BRW_SURFACEFORMAT_R5G5_SNORM_B6_UNORM 0x119
-#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM 0x11A
+#define BRW_SURFACEFORMAT_A16_FLOAT 0x117
+#define BRW_SURFACEFORMAT_L8A8_UNORM_SRGB 0x118
+#define BRW_SURFACEFORMAT_R5G5_SNORM_B6_UNORM 0x119
+#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM 0x11A
#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM_SRGB 0x11B
#define BRW_SURFACEFORMAT_R8G8_SSCALED 0x11C
#define BRW_SURFACEFORMAT_R8G8_USCALED 0x11D
@@ -368,6 +388,7 @@
#define BRW_SURFACEFORMAT_A4P4_UNORM 0x148
#define BRW_SURFACEFORMAT_R8_SSCALED 0x149
#define BRW_SURFACEFORMAT_R8_USCALED 0x14A
+#define BRW_SURFACEFORMAT_L8_UNORM_SRGB 0x14C
#define BRW_SURFACEFORMAT_R1_UINT 0x181
#define BRW_SURFACEFORMAT_YCRCB_NORMAL 0x182
#define BRW_SURFACEFORMAT_YCRCB_SWAPUVY 0x183
@@ -450,8 +471,9 @@
#define BRW_CONDITIONAL_GE 4
#define BRW_CONDITIONAL_L 5
#define BRW_CONDITIONAL_LE 6
-#define BRW_CONDITIONAL_C 7
+#define BRW_CONDITIONAL_R 7
#define BRW_CONDITIONAL_O 8
+#define BRW_CONDITIONAL_U 9
#define BRW_DEBUG_NONE 0
#define BRW_DEBUG_BREAKPOINT 1
@@ -491,6 +513,7 @@
#define BRW_OPCODE_RSL 11
#define BRW_OPCODE_ASR 12
#define BRW_OPCODE_CMP 16
+#define BRW_OPCODE_CMPN 17
#define BRW_OPCODE_JMPI 32
#define BRW_OPCODE_IF 34
#define BRW_OPCODE_IFF 35
@@ -650,6 +673,25 @@
#define BRW_SAMPLER_MESSAGE_SIMD8_LD 3
#define BRW_SAMPLER_MESSAGE_SIMD16_LD 3
+#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_IGDNG 0
+#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_IGDNG 0
+#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_IGDNG 0
+#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_BIAS_IGDNG 1
+#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_BIAS_IGDNG 1
+#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS_IGDNG 1
+#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_LOD_IGDNG 2
+#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD_IGDNG 2
+#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD_IGDNG 2
+#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_COMPARE_IGDNG 3
+#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE_IGDNG 3
+#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE_IGDNG 3
+
+/* for IGDNG only */
+#define BRW_SAMPLER_SIMD_MODE_SIMD4X2 0
+#define BRW_SAMPLER_SIMD_MODE_SIMD8 1
+#define BRW_SAMPLER_SIMD_MODE_SIMD16 2
+#define BRW_SAMPLER_SIMD_MODE_SIMD32_64 3
+
#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDLOW 0
#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDHIGH 1
#define BRW_DATAPORT_OWORD_BLOCK_2_OWORDS 2
@@ -734,7 +776,7 @@
#define CMD_URB_FENCE 0x6000
-#define CMD_CONST_BUFFER_STATE 0x6001
+#define CMD_CS_URB_STATE 0x6001
#define CMD_CONST_BUFFER 0x6002
#define CMD_STATE_BASE_ADDRESS 0x6101
@@ -799,8 +841,11 @@
#include "intel_chipset.h"
#define BRW_IS_G4X(brw) (IS_G4X((brw)->intel.intelScreen->deviceID))
-#define CMD_PIPELINE_SELECT(brw) (BRW_IS_G4X(brw) ? CMD_PIPELINE_SELECT_GM45 : CMD_PIPELINE_SELECT_965)
-#define CMD_VF_STATISTICS(brw) (BRW_IS_G4X(brw) ? CMD_VF_STATISTICS_GM45 : CMD_VF_STATISTICS_965)
-#define URB_SIZES(brw) (BRW_IS_G4X(brw) ? 384 : 256) /* 512 bit units */
+#define BRW_IS_IGDNG(brw) (IS_IGDNG((brw)->intel.intelScreen->deviceID))
+#define BRW_IS_965(brw) (!(BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw)))
+#define CMD_PIPELINE_SELECT(brw) ((BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw)) ? CMD_PIPELINE_SELECT_GM45 : CMD_PIPELINE_SELECT_965)
+#define CMD_VF_STATISTICS(brw) ((BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw)) ? CMD_VF_STATISTICS_GM45 : CMD_VF_STATISTICS_965)
+#define URB_SIZES(brw) (BRW_IS_IGDNG(brw) ? 1024 : \
+ (BRW_IS_G4X(brw) ? 384 : 256)) /* 512 bit units */
#endif
diff --git a/src/mesa/drivers/dri/i965/brw_disasm.c b/src/mesa/drivers/dri/i965/brw_disasm.c
new file mode 100644
index 0000000000..9fef230507
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_disasm.c
@@ -0,0 +1,903 @@
+/*
+ * Copyright © 2008 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "main/mtypes.h"
+
+#include "brw_context.h"
+#include "brw_defines.h"
+
+struct {
+ char *name;
+ int nsrc;
+ int ndst;
+} opcode[128] = {
+ [BRW_OPCODE_MOV] = { .name = "mov", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_FRC] = { .name = "frc", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_RNDU] = { .name = "rndu", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_RNDD] = { .name = "rndd", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_RNDE] = { .name = "rnde", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_RNDZ] = { .name = "rndz", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_NOT] = { .name = "not", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_LZD] = { .name = "lzd", .nsrc = 1, .ndst = 1 },
+
+ [BRW_OPCODE_MUL] = { .name = "mul", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_MAC] = { .name = "mac", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_MACH] = { .name = "mach", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_LINE] = { .name = "line", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_SAD2] = { .name = "sad2", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_SADA2] = { .name = "sada2", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_DP4] = { .name = "dp4", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_DPH] = { .name = "dph", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_DP3] = { .name = "dp3", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_DP2] = { .name = "dp2", .nsrc = 2, .ndst = 1 },
+
+ [BRW_OPCODE_AVG] = { .name = "avg", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_ADD] = { .name = "add", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_SEL] = { .name = "sel", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_AND] = { .name = "and", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_OR] = { .name = "or", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_XOR] = { .name = "xor", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_SHR] = { .name = "shr", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_SHL] = { .name = "shl", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_ASR] = { .name = "asr", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_CMP] = { .name = "cmp", .nsrc = 2, .ndst = 1 },
+ [BRW_OPCODE_CMPN] = { .name = "cmpn", .nsrc = 2, .ndst = 1 },
+
+ [BRW_OPCODE_SEND] = { .name = "send", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_NOP] = { .name = "nop", .nsrc = 0, .ndst = 0 },
+ [BRW_OPCODE_JMPI] = { .name = "jmpi", .nsrc = 1, .ndst = 0 },
+ [BRW_OPCODE_IF] = { .name = "if", .nsrc = 2, .ndst = 0 },
+ [BRW_OPCODE_IFF] = { .name = "iff", .nsrc = 1, .ndst = 01 },
+ [BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 1, .ndst = 0 },
+ [BRW_OPCODE_ELSE] = { .name = "else", .nsrc = 2, .ndst = 0 },
+ [BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 1, .ndst = 0 },
+ [BRW_OPCODE_CONTINUE] = { .name = "cont", .nsrc = 1, .ndst = 0 },
+ [BRW_OPCODE_HALT] = { .name = "halt", .nsrc = 1, .ndst = 0 },
+ [BRW_OPCODE_MSAVE] = { .name = "msave", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_PUSH] = { .name = "push", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_MRESTORE] = { .name = "mrest", .nsrc = 1, .ndst = 1 },
+ [BRW_OPCODE_POP] = { .name = "pop", .nsrc = 2, .ndst = 0 },
+ [BRW_OPCODE_WAIT] = { .name = "wait", .nsrc = 1, .ndst = 0 },
+ [BRW_OPCODE_DO] = { .name = "do", .nsrc = 0, .ndst = 0 },
+ [BRW_OPCODE_ENDIF] = { .name = "endif", .nsrc = 2, .ndst = 0 },
+};
+
+char *conditional_modifier[16] = {
+ [BRW_CONDITIONAL_NONE] = "",
+ [BRW_CONDITIONAL_Z] = ".e",
+ [BRW_CONDITIONAL_NZ] = ".ne",
+ [BRW_CONDITIONAL_G] = ".g",
+ [BRW_CONDITIONAL_GE] = ".ge",
+ [BRW_CONDITIONAL_L] = ".l",
+ [BRW_CONDITIONAL_LE] = ".le",
+ [BRW_CONDITIONAL_R] = ".r",
+ [BRW_CONDITIONAL_O] = ".o",
+ [BRW_CONDITIONAL_U] = ".u",
+};
+
+char *negate[2] = {
+ [0] = "",
+ [1] = "-",
+};
+
+char *_abs[2] = {
+ [0] = "",
+ [1] = "(abs)",
+};
+
+char *vert_stride[16] = {
+ [0] = "0",
+ [1] = "1",
+ [2] = "2",
+ [3] = "4",
+ [4] = "8",
+ [5] = "16",
+ [6] = "32",
+ [15] = "VxH",
+};
+
+char *width[8] = {
+ [0] = "1",
+ [1] = "2",
+ [2] = "4",
+ [3] = "8",
+ [4] = "16",
+};
+
+char *horiz_stride[4] = {
+ [0] = "0",
+ [1] = "1",
+ [2] = "2",
+ [3] = "4"
+};
+
+char *chan_sel[4] = {
+ [0] = "x",
+ [1] = "y",
+ [2] = "z",
+ [3] = "w",
+};
+
+char *dest_condmod[16] = {
+};
+
+char *debug_ctrl[2] = {
+ [0] = "",
+ [1] = ".breakpoint"
+};
+
+char *saturate[2] = {
+ [0] = "",
+ [1] = ".sat"
+};
+
+char *exec_size[8] = {
+ [0] = "1",
+ [1] = "2",
+ [2] = "4",
+ [3] = "8",
+ [4] = "16",
+ [5] = "32"
+};
+
+char *pred_inv[2] = {
+ [0] = "+",
+ [1] = "-"
+};
+
+char *pred_ctrl_align16[16] = {
+ [1] = "",
+ [2] = ".x",
+ [3] = ".y",
+ [4] = ".z",
+ [5] = ".w",
+ [6] = ".any4h",
+ [7] = ".all4h",
+};
+
+char *pred_ctrl_align1[16] = {
+ [1] = "",
+ [2] = ".anyv",
+ [3] = ".allv",
+ [4] = ".any2h",
+ [5] = ".all2h",
+ [6] = ".any4h",
+ [7] = ".all4h",
+ [8] = ".any8h",
+ [9] = ".all8h",
+ [10] = ".any16h",
+ [11] = ".all16h",
+};
+
+char *thread_ctrl[4] = {
+ [0] = "",
+ [2] = "switch"
+};
+
+char *compr_ctrl[4] = {
+ [0] = "",
+ [1] = "sechalf",
+ [2] = "compr",
+};
+
+char *dep_ctrl[4] = {
+ [0] = "",
+ [1] = "NoDDClr",
+ [2] = "NoDDChk",
+ [3] = "NoDDClr,NoDDChk",
+};
+
+char *mask_ctrl[4] = {
+ [0] = "",
+ [1] = "nomask",
+};
+
+char *access_mode[2] = {
+ [0] = "align1",
+ [1] = "align16",
+};
+
+char *reg_encoding[8] = {
+ [0] = "UD",
+ [1] = "D",
+ [2] = "UW",
+ [3] = "W",
+ [4] = "UB",
+ [5] = "B",
+ [7] = "F"
+};
+
+char *imm_encoding[8] = {
+ [0] = "UD",
+ [1] = "D",
+ [2] = "UW",
+ [3] = "W",
+ [5] = "VF",
+ [5] = "V",
+ [7] = "F"
+};
+
+char *reg_file[4] = {
+ [0] = "A",
+ [1] = "g",
+ [2] = "m",
+ [3] = "imm",
+};
+
+char *writemask[16] = {
+ [0x0] = ".",
+ [0x1] = ".x",
+ [0x2] = ".y",
+ [0x3] = ".xy",
+ [0x4] = ".z",
+ [0x5] = ".xz",
+ [0x6] = ".yz",
+ [0x7] = ".xyz",
+ [0x8] = ".w",
+ [0x9] = ".xw",
+ [0xa] = ".yw",
+ [0xb] = ".xyw",
+ [0xc] = ".zw",
+ [0xd] = ".xzw",
+ [0xe] = ".yzw",
+ [0xf] = "",
+};
+
+char *end_of_thread[2] = {
+ [0] = "",
+ [1] = "EOT"
+};
+
+char *target_function[16] = {
+ [BRW_MESSAGE_TARGET_NULL] = "null",
+ [BRW_MESSAGE_TARGET_MATH] = "math",
+ [BRW_MESSAGE_TARGET_SAMPLER] = "sampler",
+ [BRW_MESSAGE_TARGET_GATEWAY] = "gateway",
+ [BRW_MESSAGE_TARGET_DATAPORT_READ] = "read",
+ [BRW_MESSAGE_TARGET_DATAPORT_WRITE] = "write",
+ [BRW_MESSAGE_TARGET_URB] = "urb",
+ [BRW_MESSAGE_TARGET_THREAD_SPAWNER] = "thread_spawner"
+};
+
+char *math_function[16] = {
+ [BRW_MATH_FUNCTION_INV] = "inv",
+ [BRW_MATH_FUNCTION_LOG] = "log",
+ [BRW_MATH_FUNCTION_EXP] = "exp",
+ [BRW_MATH_FUNCTION_SQRT] = "sqrt",
+ [BRW_MATH_FUNCTION_RSQ] = "rsq",
+ [BRW_MATH_FUNCTION_SIN] = "sin",
+ [BRW_MATH_FUNCTION_COS] = "cos",
+ [BRW_MATH_FUNCTION_SINCOS] = "sincos",
+ [BRW_MATH_FUNCTION_TAN] = "tan",
+ [BRW_MATH_FUNCTION_POW] = "pow",
+ [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod",
+ [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intmod",
+ [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intdiv",
+};
+
+char *math_saturate[2] = {
+ [0] = "",
+ [1] = "sat"
+};
+
+char *math_signed[2] = {
+ [0] = "",
+ [1] = "signed"
+};
+
+char *math_scalar[2] = {
+ [0] = "",
+ [1] = "scalar"
+};
+
+char *math_precision[2] = {
+ [0] = "",
+ [1] = "partial_precision"
+};
+
+char *urb_swizzle[4] = {
+ [BRW_URB_SWIZZLE_NONE] = "",
+ [BRW_URB_SWIZZLE_INTERLEAVE] = "interleave",
+ [BRW_URB_SWIZZLE_TRANSPOSE] = "transpose",
+};
+
+char *urb_allocate[2] = {
+ [0] = "",
+ [1] = "allocate"
+};
+
+char *urb_used[2] = {
+ [0] = "",
+ [1] = "used"
+};
+
+char *urb_complete[2] = {
+ [0] = "",
+ [1] = "complete"
+};
+
+char *sampler_target_format[4] = {
+ [0] = "F",
+ [2] = "UD",
+ [3] = "D"
+};
+
+
+static int column;
+
+static int string (FILE *file, char *string)
+{
+ fputs (string, file);
+ column += strlen (string);
+ return 0;
+}
+
+static int format (FILE *f, char *format, ...)
+{
+ char buf[1024];
+ va_list args;
+ va_start (args, format);
+
+ vsnprintf (buf, sizeof (buf) - 1, format, args);
+ string (f, buf);
+ return 0;
+}
+
+static int newline (FILE *f)
+{
+ putc ('\n', f);
+ column = 0;
+ return 0;
+}
+
+static int pad (FILE *f, int c)
+{
+ do
+ string (f, " ");
+ while (column < c);
+ return 0;
+}
+
+static int control (FILE *file, char *name, char *ctrl[], GLuint id, int *space)
+{
+ if (!ctrl[id]) {
+ fprintf (file, "*** invalid %s value %d ",
+ name, id);
+ return 1;
+ }
+ if (ctrl[id][0])
+ {
+ if (space && *space)
+ string (file, " ");
+ string (file, ctrl[id]);
+ if (space)
+ *space = 1;
+ }
+ return 0;
+}
+
+static int print_opcode (FILE *file, int id)
+{
+ if (!opcode[id].name) {
+ format (file, "*** invalid opcode value %d ", id);
+ return 1;
+ }
+ string (file, opcode[id].name);
+ return 0;
+}
+
+static int reg (FILE *file, GLuint _reg_file, GLuint _reg_nr)
+{
+ int err = 0;
+ if (_reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
+ switch (_reg_nr & 0xf0) {
+ case BRW_ARF_NULL:
+ string (file, "null");
+ return -1;
+ case BRW_ARF_ADDRESS:
+ format (file, "a%d", _reg_nr & 0x0f);
+ break;
+ case BRW_ARF_ACCUMULATOR:
+ format (file, "acc%d", _reg_nr & 0x0f);
+ break;
+ case BRW_ARF_MASK:
+ format (file, "mask%d", _reg_nr & 0x0f);
+ break;
+ case BRW_ARF_MASK_STACK:
+ format (file, "msd%d", _reg_nr & 0x0f);
+ break;
+ case BRW_ARF_STATE:
+ format (file, "sr%d", _reg_nr & 0x0f);
+ break;
+ case BRW_ARF_CONTROL:
+ format (file, "cr%d", _reg_nr & 0x0f);
+ break;
+ case BRW_ARF_NOTIFICATION_COUNT:
+ format (file, "n%d", _reg_nr & 0x0f);
+ break;
+ case BRW_ARF_IP:
+ string (file, "ip");
+ return -1;
+ break;
+ default:
+ format (file, "ARF%d", _reg_nr);
+ break;
+ }
+ } else {
+ err |= control (file, "src reg file", reg_file, _reg_file, NULL);
+ format (file, "%d", _reg_nr);
+ }
+ return err;
+}
+
+static int dest (FILE *file, struct brw_instruction *inst)
+{
+ int err = 0;
+
+ if (inst->header.access_mode == BRW_ALIGN_1)
+ {
+ if (inst->bits1.da1.dest_address_mode == BRW_ADDRESS_DIRECT)
+ {
+ err |= reg (file, inst->bits1.da1.dest_reg_file, inst->bits1.da1.dest_reg_nr);
+ if (err == -1)
+ return 0;
+ if (inst->bits1.da1.dest_subreg_nr)
+ format (file, ".%d", inst->bits1.da1.dest_subreg_nr);
+ format (file, "<%d>", inst->bits1.da1.dest_horiz_stride);
+ err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da1.dest_reg_type, NULL);
+ }
+ else
+ {
+ string (file, "g[a0");
+ if (inst->bits1.ia1.dest_subreg_nr)
+ format (file, ".%d", inst->bits1.ia1.dest_subreg_nr);
+ if (inst->bits1.ia1.dest_indirect_offset)
+ format (file, " %d", inst->bits1.ia1.dest_indirect_offset);
+ string (file, "]");
+ format (file, "<%d>", inst->bits1.ia1.dest_horiz_stride);
+ err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.ia1.dest_reg_type, NULL);
+ }
+ }
+ else
+ {
+ if (inst->bits1.da16.dest_address_mode == BRW_ADDRESS_DIRECT)
+ {
+ err |= reg (file, inst->bits1.da16.dest_reg_file, inst->bits1.da16.dest_reg_nr);
+ if (err == -1)
+ return 0;
+ if (inst->bits1.da16.dest_subreg_nr)
+ format (file, ".%d", inst->bits1.da16.dest_subreg_nr);
+ string (file, "<1>");
+ err |= control (file, "writemask", writemask, inst->bits1.da16.dest_writemask, NULL);
+ err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da16.dest_reg_type, NULL);
+ }
+ else
+ {
+ err = 1;
+ string (file, "Indirect align16 address mode not supported");
+ }
+ }
+
+ return 0;
+}
+
+static int src_align1_region (FILE *file,
+ GLuint _vert_stride, GLuint _width, GLuint _horiz_stride)
+{
+ int err = 0;
+ string (file, "<");
+ err |= control (file, "vert stride", vert_stride, _vert_stride, NULL);
+ string (file, ",");
+ err |= control (file, "width", width, _width, NULL);
+ string (file, ",");
+ err |= control (file, "horiz_stride", horiz_stride, _horiz_stride, NULL);
+ string (file, ">");
+ return err;
+}
+
+static int src_da1 (FILE *file, GLuint type, GLuint _reg_file,
+ GLuint _vert_stride, GLuint _width, GLuint _horiz_stride,
+ GLuint reg_num, GLuint sub_reg_num, GLuint __abs, GLuint _negate)
+{
+ int err = 0;
+ err |= control (file, "negate", negate, _negate, NULL);
+ err |= control (file, "abs", _abs, __abs, NULL);
+
+ err |= reg (file, _reg_file, reg_num);
+ if (err == -1)
+ return 0;
+ if (sub_reg_num)
+ format (file, ".%d", sub_reg_num);
+ src_align1_region (file, _vert_stride, _width, _horiz_stride);
+ err |= control (file, "src reg encoding", reg_encoding, type, NULL);
+ return err;
+}
+
+static int src_ia1 (FILE *file,
+ GLuint type,
+ GLuint _reg_file,
+ GLint _addr_imm,
+ GLuint _addr_subreg_nr,
+ GLuint _negate,
+ GLuint __abs,
+ GLuint _addr_mode,
+ GLuint _horiz_stride,
+ GLuint _width,
+ GLuint _vert_stride)
+{
+ int err = 0;
+ err |= control (file, "negate", negate, _negate, NULL);
+ err |= control (file, "abs", _abs, __abs, NULL);
+
+ string (file, "g[a0");
+ if (_addr_subreg_nr)
+ format (file, ".%d", _addr_subreg_nr);
+ if (_addr_imm)
+ format (file, " %d", _addr_imm);
+ string (file, "]");
+ src_align1_region (file, _vert_stride, _width, _horiz_stride);
+ err |= control (file, "src reg encoding", reg_encoding, type, NULL);
+ return err;
+}
+
+static int src_da16 (FILE *file,
+ GLuint _reg_type,
+ GLuint _reg_file,
+ GLuint _vert_stride,
+ GLuint _reg_nr,
+ GLuint _subreg_nr,
+ GLuint __abs,
+ GLuint _negate,
+ GLuint swz_x,
+ GLuint swz_y,
+ GLuint swz_z,
+ GLuint swz_w)
+{
+ int err = 0;
+ err |= control (file, "negate", negate, _negate, NULL);
+ err |= control (file, "abs", _abs, __abs, NULL);
+
+ err |= reg (file, _reg_file, _reg_nr);
+ if (err == -1)
+ return 0;
+ if (_subreg_nr)
+ format (file, ".%d", _subreg_nr);
+ string (file, "<");
+ err |= control (file, "vert stride", vert_stride, _vert_stride, NULL);
+ string (file, ",1,1>");
+ err |= control (file, "src da16 reg type", reg_encoding, _reg_type, NULL);
+ /*
+ * Three kinds of swizzle display:
+ * identity - nothing printed
+ * 1->all - print the single channel
+ * 1->1 - print the mapping
+ */
+ if (swz_x == BRW_CHANNEL_X &&
+ swz_y == BRW_CHANNEL_Y &&
+ swz_z == BRW_CHANNEL_Z &&
+ swz_w == BRW_CHANNEL_W)
+ {
+ ;
+ }
+ else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
+ {
+ string (file, ".");
+ err |= control (file, "channel select", chan_sel, swz_x, NULL);
+ }
+ else
+ {
+ string (file, ".");
+ err |= control (file, "channel select", chan_sel, swz_x, NULL);
+ err |= control (file, "channel select", chan_sel, swz_y, NULL);
+ err |= control (file, "channel select", chan_sel, swz_z, NULL);
+ err |= control (file, "channel select", chan_sel, swz_w, NULL);
+ }
+ return err;
+}
+
+
+static int imm (FILE *file, GLuint type, struct brw_instruction *inst) {
+ switch (type) {
+ case BRW_REGISTER_TYPE_UD:
+ format (file, "0x%08xUD", inst->bits3.ud);
+ break;
+ case BRW_REGISTER_TYPE_D:
+ format (file, "%dD", inst->bits3.d);
+ break;
+ case BRW_REGISTER_TYPE_UW:
+ format (file, "0x%04xUW", (uint16_t) inst->bits3.ud);
+ break;
+ case BRW_REGISTER_TYPE_W:
+ format (file, "%dW", (int16_t) inst->bits3.d);
+ break;
+ case BRW_REGISTER_TYPE_UB:
+ format (file, "0x%02xUB", (int8_t) inst->bits3.ud);
+ break;
+ case BRW_REGISTER_TYPE_VF:
+ format (file, "Vector Float");
+ break;
+ case BRW_REGISTER_TYPE_V:
+ format (file, "0x%08xV", inst->bits3.ud);
+ break;
+ case BRW_REGISTER_TYPE_F:
+ format (file, "%-gF", inst->bits3.f);
+ }
+ return 0;
+}
+
+static int src0 (FILE *file, struct brw_instruction *inst)
+{
+ if (inst->bits1.da1.src0_reg_file == BRW_IMMEDIATE_VALUE)
+ return imm (file, inst->bits1.da1.src0_reg_type,
+ inst);
+ else if (inst->header.access_mode == BRW_ALIGN_1)
+ {
+ if (inst->bits2.da1.src0_address_mode == BRW_ADDRESS_DIRECT)
+ {
+ return src_da1 (file,
+ inst->bits1.da1.src0_reg_type,
+ inst->bits1.da1.src0_reg_file,
+ inst->bits2.da1.src0_vert_stride,
+ inst->bits2.da1.src0_width,
+ inst->bits2.da1.src0_horiz_stride,
+ inst->bits2.da1.src0_reg_nr,
+ inst->bits2.da1.src0_subreg_nr,
+ inst->bits2.da1.src0_abs,
+ inst->bits2.da1.src0_negate);
+ }
+ else
+ {
+ return src_ia1 (file,
+ inst->bits1.ia1.src0_reg_type,
+ inst->bits1.ia1.src0_reg_file,
+ inst->bits2.ia1.src0_indirect_offset,
+ inst->bits2.ia1.src0_subreg_nr,
+ inst->bits2.ia1.src0_negate,
+ inst->bits2.ia1.src0_abs,
+ inst->bits2.ia1.src0_address_mode,
+ inst->bits2.ia1.src0_horiz_stride,
+ inst->bits2.ia1.src0_width,
+ inst->bits2.ia1.src0_vert_stride);
+ }
+ }
+ else
+ {
+ if (inst->bits2.da16.src0_address_mode == BRW_ADDRESS_DIRECT)
+ {
+ return src_da16 (file,
+ inst->bits1.da16.src0_reg_type,
+ inst->bits1.da16.src0_reg_file,
+ inst->bits2.da16.src0_vert_stride,
+ inst->bits2.da16.src0_reg_nr,
+ inst->bits2.da16.src0_subreg_nr,
+ inst->bits2.da16.src0_abs,
+ inst->bits2.da16.src0_negate,
+ inst->bits2.da16.src0_swz_x,
+ inst->bits2.da16.src0_swz_y,
+ inst->bits2.da16.src0_swz_z,
+ inst->bits2.da16.src0_swz_w);
+ }
+ else
+ {
+ string (file, "Indirect align16 address mode not supported");
+ return 1;
+ }
+ }
+}
+
+static int src1 (FILE *file, struct brw_instruction *inst)
+{
+ if (inst->bits1.da1.src1_reg_file == BRW_IMMEDIATE_VALUE)
+ return imm (file, inst->bits1.da1.src1_reg_type,
+ inst);
+ else if (inst->header.access_mode == BRW_ALIGN_1)
+ {
+ if (inst->bits3.da1.src1_address_mode == BRW_ADDRESS_DIRECT)
+ {
+ return src_da1 (file,
+ inst->bits1.da1.src1_reg_type,
+ inst->bits1.da1.src1_reg_file,
+ inst->bits3.da1.src1_vert_stride,
+ inst->bits3.da1.src1_width,
+ inst->bits3.da1.src1_horiz_stride,
+ inst->bits3.da1.src1_reg_nr,
+ inst->bits3.da1.src1_subreg_nr,
+ inst->bits3.da1.src1_abs,
+ inst->bits3.da1.src1_negate);
+ }
+ else
+ {
+ return src_ia1 (file,
+ inst->bits1.ia1.src1_reg_type,
+ inst->bits1.ia1.src1_reg_file,
+ inst->bits3.ia1.src1_indirect_offset,
+ inst->bits3.ia1.src1_subreg_nr,
+ inst->bits3.ia1.src1_negate,
+ inst->bits3.ia1.src1_abs,
+ inst->bits3.ia1.src1_address_mode,
+ inst->bits3.ia1.src1_horiz_stride,
+ inst->bits3.ia1.src1_width,
+ inst->bits3.ia1.src1_vert_stride);
+ }
+ }
+ else
+ {
+ if (inst->bits3.da16.src1_address_mode == BRW_ADDRESS_DIRECT)
+ {
+ return src_da16 (file,
+ inst->bits1.da16.src1_reg_type,
+ inst->bits1.da16.src1_reg_file,
+ inst->bits3.da16.src1_vert_stride,
+ inst->bits3.da16.src1_reg_nr,
+ inst->bits3.da16.src1_subreg_nr,
+ inst->bits3.da16.src1_abs,
+ inst->bits3.da16.src1_negate,
+ inst->bits3.da16.src1_swz_x,
+ inst->bits3.da16.src1_swz_y,
+ inst->bits3.da16.src1_swz_z,
+ inst->bits3.da16.src1_swz_w);
+ }
+ else
+ {
+ string (file, "Indirect align16 address mode not supported");
+ return 1;
+ }
+ }
+}
+
+int brw_disasm (FILE *file, struct brw_instruction *inst)
+{
+ int err = 0;
+ int space = 0;
+
+ if (inst->header.predicate_control) {
+ string (file, "(");
+ err |= control (file, "predicate inverse", pred_inv, inst->header.predicate_inverse, NULL);
+ string (file, "f0");
+ if (inst->bits2.da1.flag_reg_nr)
+ format (file, ".%d", inst->bits2.da1.flag_reg_nr);
+ if (inst->header.access_mode == BRW_ALIGN_1)
+ err |= control (file, "predicate control align1", pred_ctrl_align1,
+ inst->header.predicate_control, NULL);
+ else
+ err |= control (file, "predicate control align16", pred_ctrl_align16,
+ inst->header.predicate_control, NULL);
+ string (file, ") ");
+ }
+
+ err |= print_opcode (file, inst->header.opcode);
+ err |= control (file, "saturate", saturate, inst->header.saturate, NULL);
+ err |= control (file, "debug control", debug_ctrl, inst->header.debug_control, NULL);
+
+ if (inst->header.opcode != BRW_OPCODE_SEND)
+ err |= control (file, "conditional modifier", conditional_modifier,
+ inst->header.destreg__conditionalmod, NULL);
+
+ if (inst->header.opcode != BRW_OPCODE_NOP) {
+ string (file, "(");
+ err |= control (file, "execution size", exec_size, inst->header.execution_size, NULL);
+ string (file, ")");
+ }
+
+ if (inst->header.opcode == BRW_OPCODE_SEND)
+ format (file, " %d", inst->header.destreg__conditionalmod);
+
+ if (opcode[inst->header.opcode].ndst > 0) {
+ pad (file, 16);
+ err |= dest (file, inst);
+ }
+ if (opcode[inst->header.opcode].nsrc > 0) {
+ pad (file, 32);
+ err |= src0 (file, inst);
+ }
+ if (opcode[inst->header.opcode].nsrc > 1) {
+ pad (file, 48);
+ err |= src1 (file, inst);
+ }
+
+ if (inst->header.opcode == BRW_OPCODE_SEND) {
+ newline (file);
+ pad (file, 16);
+ space = 0;
+ err |= control (file, "target function", target_function,
+ inst->bits3.generic.msg_target, &space);
+ switch (inst->bits3.generic.msg_target) {
+ case BRW_MESSAGE_TARGET_MATH:
+ err |= control (file, "math function", math_function,
+ inst->bits3.math.function, &space);
+ err |= control (file, "math saturate", math_saturate,
+ inst->bits3.math.saturate, &space);
+ err |= control (file, "math signed", math_signed,
+ inst->bits3.math.int_type, &space);
+ err |= control (file, "math scalar", math_scalar,
+ inst->bits3.math.data_type, &space);
+ err |= control (file, "math precision", math_precision,
+ inst->bits3.math.precision, &space);
+ break;
+ case BRW_MESSAGE_TARGET_SAMPLER:
+ format (file, " (%d, %d, ",
+ inst->bits3.sampler.binding_table_index,
+ inst->bits3.sampler.sampler);
+ err |= control (file, "sampler target format", sampler_target_format,
+ inst->bits3.sampler.return_format, NULL);
+ string (file, ")");
+ break;
+ case BRW_MESSAGE_TARGET_DATAPORT_WRITE:
+ format (file, " (%d, %d, %d, %d)",
+ inst->bits3.dp_write.binding_table_index,
+ (inst->bits3.dp_write.pixel_scoreboard_clear << 3) |
+ inst->bits3.dp_write.msg_control,
+ inst->bits3.dp_write.msg_type,
+ inst->bits3.dp_write.send_commit_msg);
+ break;
+ case BRW_MESSAGE_TARGET_URB:
+ format (file, " %d", inst->bits3.urb.offset);
+ space = 1;
+ err |= control (file, "urb swizzle", urb_swizzle,
+ inst->bits3.urb.swizzle_control, &space);
+ err |= control (file, "urb allocate", urb_allocate,
+ inst->bits3.urb.allocate, &space);
+ err |= control (file, "urb used", urb_used,
+ inst->bits3.urb.used, &space);
+ err |= control (file, "urb complete", urb_complete,
+ inst->bits3.urb.complete, &space);
+ break;
+ case BRW_MESSAGE_TARGET_THREAD_SPAWNER:
+ break;
+ default:
+ format (file, "unsupported target %d", inst->bits3.generic.msg_target);
+ break;
+ }
+ if (space)
+ string (file, " ");
+ format (file, "mlen %d",
+ inst->bits3.generic.msg_length);
+ format (file, " rlen %d",
+ inst->bits3.generic.response_length);
+ }
+ pad (file, 64);
+ if (inst->header.opcode != BRW_OPCODE_NOP) {
+ string (file, "{");
+ space = 1;
+ err |= control(file, "access mode", access_mode, inst->header.access_mode, &space);
+ err |= control (file, "mask control", mask_ctrl, inst->header.mask_control, &space);
+ err |= control (file, "dependency control", dep_ctrl, inst->header.dependency_control, &space);
+ err |= control (file, "compression control", compr_ctrl, inst->header.compression_control, &space);
+ err |= control (file, "thread control", thread_ctrl, inst->header.thread_control, &space);
+ if (inst->header.opcode == BRW_OPCODE_SEND)
+ err |= control (file, "end of thread", end_of_thread,
+ inst->bits3.generic.end_of_thread, &space);
+ if (space)
+ string (file, " ");
+ string (file, "}");
+ }
+ string (file, ";");
+ newline (file);
+ return err;
+}
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 785fb784ca..44bb7bd588 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -25,13 +25,15 @@
*
**************************************************************************/
-#include <stdlib.h>
#include "main/glheader.h"
#include "main/context.h"
#include "main/state.h"
-#include "main/api_validate.h"
#include "main/enums.h"
+#include "tnl/tnl.h"
+#include "vbo/vbo_context.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
#include "brw_draw.h"
#include "brw_defines.h"
@@ -42,11 +44,6 @@
#include "intel_batchbuffer.h"
#include "intel_buffer_objects.h"
-#include "tnl/tnl.h"
-#include "vbo/vbo_context.h"
-#include "swrast/swrast.h"
-#include "swrast_setup/swrast_setup.h"
-
#define FILE_DEBUG_FLAG DEBUG_BATCH
static GLuint prim_to_hw_prim[GL_POLYGON+1] = {
@@ -84,15 +81,17 @@ static const GLenum reduced_prim[GL_POLYGON+1] = {
*/
static GLuint brw_set_prim(struct brw_context *brw, GLenum prim)
{
+ GLcontext *ctx = &brw->intel.ctx;
+
if (INTEL_DEBUG & DEBUG_PRIMS)
_mesa_printf("PRIM: %s\n", _mesa_lookup_enum_by_nr(prim));
/* Slight optimization to avoid the GS program when not needed:
*/
if (prim == GL_QUAD_STRIP &&
- brw->attribs.Light->ShadeModel != GL_FLAT &&
- brw->attribs.Polygon->FrontMode == GL_FILL &&
- brw->attribs.Polygon->BackMode == GL_FILL)
+ ctx->Light.ShadeModel != GL_FLAT &&
+ ctx->Polygon.FrontMode == GL_FILL &&
+ ctx->Polygon.BackMode == GL_FILL)
prim = GL_TRIANGLE_STRIP;
if (prim != brw->primitive) {
@@ -125,6 +124,7 @@ static void brw_emit_prim(struct brw_context *brw,
uint32_t hw_prim)
{
struct brw_3d_primitive prim_packet;
+ struct intel_context *intel = &brw->intel;
if (INTEL_DEBUG & DEBUG_PRIMS)
_mesa_printf("PRIM: %s %d %d\n", _mesa_lookup_enum_by_nr(prim->mode),
@@ -138,16 +138,35 @@ static void brw_emit_prim(struct brw_context *brw,
prim_packet.verts_per_instance = trim(prim->mode, prim->count);
prim_packet.start_vert_location = prim->start;
+ if (prim->indexed)
+ prim_packet.start_vert_location += brw->ib.start_vertex_offset;
prim_packet.instance_count = 1;
prim_packet.start_instance_location = 0;
- prim_packet.base_vert_location = 0;
+ prim_packet.base_vert_location = prim->basevertex;
/* Can't wrap here, since we rely on the validated state. */
brw->no_batch_wrap = GL_TRUE;
+
+ /* 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
+ * and missed flushes of the render cache as it heads to other parts of
+ * the besides the draw code.
+ */
+ if (intel->always_flush_cache) {
+ BEGIN_BATCH(1, IGNORE_CLIPRECTS);
+ OUT_BATCH(intel->vtbl.flush_cmd());
+ ADVANCE_BATCH();
+ }
if (prim_packet.verts_per_instance) {
intel_batchbuffer_data( brw->intel.batch, &prim_packet,
sizeof(prim_packet), LOOP_CLIPRECTS);
}
+ if (intel->always_flush_cache) {
+ BEGIN_BATCH(1, IGNORE_CLIPRECTS);
+ OUT_BATCH(intel->vtbl.flush_cmd());
+ ADVANCE_BATCH();
+ }
+
brw->no_batch_wrap = GL_FALSE;
}
@@ -165,24 +184,16 @@ static void brw_merge_inputs( struct brw_context *brw,
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
brw->vb.inputs[i].glarray = arrays[i];
+ brw->vb.inputs[i].attrib = (gl_vert_attrib) i;
- /* XXX: metaops passes null arrays */
- if (arrays[i]) {
- if (arrays[i]->StrideB != 0)
- brw->vb.info.varying |= 1 << i;
-
+ if (arrays[i]->StrideB != 0)
brw->vb.info.sizes[i/16] |= (brw->vb.inputs[i].glarray->Size - 1) <<
((i%16) * 2);
- }
}
- /* Raise statechanges if input sizes and varying have changed:
- */
+ /* Raise statechanges if input sizes have changed. */
if (memcmp(brw->vb.info.sizes, old.sizes, sizeof(old.sizes)) != 0)
brw->state.dirty.brw |= BRW_NEW_INPUT_DIMENSIONS;
-
- if (brw->vb.info.varying != old.varying)
- brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING;
}
/* XXX: could split the primitive list to fallback only on the
@@ -192,12 +203,20 @@ static GLboolean check_fallbacks( struct brw_context *brw,
const struct _mesa_prim *prim,
GLuint nr_prims )
{
+ GLcontext *ctx = &brw->intel.ctx;
GLuint i;
- if (!brw->intel.strict_conformance)
+ /* If we don't require strict OpenGL conformance, never
+ * use fallbacks. If we're forcing fallbacks, always
+ * use fallfacks.
+ */
+ if (brw->intel.conformance_mode == 0)
return GL_FALSE;
- if (brw->attribs.Polygon->SmoothFlag) {
+ if (brw->intel.conformance_mode == 2)
+ return GL_TRUE;
+
+ if (ctx->Polygon.SmoothFlag) {
for (i = 0; i < nr_prims; i++)
if (reduced_prim[prim[i].mode] == GL_TRIANGLES)
return GL_TRUE;
@@ -206,7 +225,7 @@ static GLboolean check_fallbacks( struct brw_context *brw,
/* BRW hardware will do AA lines, but they are non-conformant it
* seems. TBD whether we keep this fallback:
*/
- if (brw->attribs.Line->SmoothFlag) {
+ if (ctx->Line.SmoothFlag) {
for (i = 0; i < nr_prims; i++)
if (reduced_prim[prim[i].mode] == GL_LINES)
return GL_TRUE;
@@ -215,28 +234,61 @@ static GLboolean check_fallbacks( struct brw_context *brw,
/* Stipple -- these fallbacks could be resolved with a little
* bit of work?
*/
- if (brw->attribs.Line->StippleFlag) {
+ if (ctx->Line.StippleFlag) {
for (i = 0; i < nr_prims; i++) {
/* GS doesn't get enough information to know when to reset
* the stipple counter?!?
*/
- if (prim[i].mode == GL_LINE_LOOP)
+ if (prim[i].mode == GL_LINE_LOOP || prim[i].mode == GL_LINE_STRIP)
return GL_TRUE;
if (prim[i].mode == GL_POLYGON &&
- (brw->attribs.Polygon->FrontMode == GL_LINE ||
- brw->attribs.Polygon->BackMode == GL_LINE))
+ (ctx->Polygon.FrontMode == GL_LINE ||
+ ctx->Polygon.BackMode == GL_LINE))
return GL_TRUE;
}
}
-
- if (brw->attribs.Point->SmoothFlag) {
+ if (ctx->Point.SmoothFlag) {
for (i = 0; i < nr_prims; i++)
if (prim[i].mode == GL_POINTS)
return GL_TRUE;
}
+
+ /* BRW hardware doesn't handle GL_CLAMP texturing correctly;
+ * brw_wm_sampler_state:translate_wrap_mode() treats GL_CLAMP
+ * as GL_CLAMP_TO_EDGE instead. If we're using GL_CLAMP, and
+ * we want strict conformance, force the fallback.
+ * Right now, we only do this for 2D textures.
+ */
+ {
+ int u;
+ for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
+ if (texUnit->Enabled) {
+ if (texUnit->Enabled & TEXTURE_1D_BIT) {
+ if (texUnit->CurrentTex[TEXTURE_1D_INDEX]->WrapS == GL_CLAMP) {
+ return GL_TRUE;
+ }
+ }
+ if (texUnit->Enabled & TEXTURE_2D_BIT) {
+ if (texUnit->CurrentTex[TEXTURE_2D_INDEX]->WrapS == GL_CLAMP ||
+ texUnit->CurrentTex[TEXTURE_2D_INDEX]->WrapT == GL_CLAMP) {
+ return GL_TRUE;
+ }
+ }
+ if (texUnit->Enabled & TEXTURE_3D_BIT) {
+ if (texUnit->CurrentTex[TEXTURE_3D_INDEX]->WrapS == GL_CLAMP ||
+ texUnit->CurrentTex[TEXTURE_3D_INDEX]->WrapT == GL_CLAMP ||
+ texUnit->CurrentTex[TEXTURE_3D_INDEX]->WrapR == GL_CLAMP) {
+ return GL_TRUE;
+ }
+ }
+ }
+ }
+ }
+ /* Nothing stopping us from the fast path now */
return GL_FALSE;
}
@@ -261,11 +313,18 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
if (ctx->NewState)
_mesa_update_state( ctx );
+ /* We have to validate the textures *before* checking for fallbacks;
+ * otherwise, the software fallback won't be able to rely on the
+ * texture state, the firstLevel and lastLevel fields won't be
+ * set in the intel texture object (they'll both be 0), and the
+ * software fallback will segfault if it attempts to access any
+ * texture level other than level 0.
+ */
+ brw_validate_textures( brw );
+
if (check_fallbacks(brw, prim, nr_prims))
return GL_FALSE;
- brw_validate_textures( brw );
-
/* Bind all inputs, derive varying and size information:
*/
brw_merge_inputs( brw, arrays );
@@ -346,9 +405,13 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
retval = GL_TRUE;
}
+ if (intel->always_flush_batch)
+ intel_batchbuffer_flush(intel->batch);
out:
UNLOCK_HARDWARE(intel);
+ brw_state_cache_check_size(brw);
+
if (warn)
fprintf(stderr, "i965: Single primitive emit potentially exceeded "
"available aperture space\n");
@@ -359,54 +422,31 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
return retval;
}
-static GLboolean brw_need_rebase( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct _mesa_index_buffer *ib,
- GLuint min_index )
-{
- if (min_index == 0)
- return GL_FALSE;
-
- if (ib) {
- if (!vbo_all_varyings_in_vbos(arrays))
- return GL_TRUE;
- else
- return GL_FALSE;
- }
- else {
- /* Hmm. This isn't quite what I wanted. BRW can actually
- * handle the mixed case well enough that we shouldn't need to
- * rebase. However, it's probably not very common, nor hugely
- * expensive to do it this way:
- */
- if (!vbo_all_varyings_in_vbos(arrays))
- return GL_TRUE;
- else
- return GL_FALSE;
- }
-}
-
-
void brw_draw_prims( GLcontext *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index )
{
GLboolean retval;
- /* Decide if we want to rebase. If so we end up recursing once
- * only into this function.
- */
- if (brw_need_rebase( ctx, arrays, ib, min_index )) {
- vbo_rebase_prims( ctx, arrays,
- prim, nr_prims,
- ib, min_index, max_index,
- brw_draw_prims );
-
- return;
+ if (!vbo_all_varyings_in_vbos(arrays)) {
+ if (!index_bounds_valid)
+ vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+
+ /* Decide if we want to rebase. If so we end up recursing once
+ * only into this function.
+ */
+ if (min_index != 0) {
+ vbo_rebase_prims(ctx, arrays,
+ prim, nr_prims,
+ ib, min_index, max_index,
+ brw_draw_prims );
+ return;
+ }
}
/* Make a first attempt at drawing:
diff --git a/src/mesa/drivers/dri/i965/brw_draw.h b/src/mesa/drivers/dri/i965/brw_draw.h
index 9aebbdb1b8..2a14db217f 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.h
+++ b/src/mesa/drivers/dri/i965/brw_draw.h
@@ -39,6 +39,7 @@ void brw_draw_prims( GLcontext *ctx,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index );
diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c
index 73d6dea01e..765ae5a2fe 100644
--- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
@@ -25,9 +25,9 @@
*
**************************************************************************/
-#include <stdlib.h>
#include "main/glheader.h"
+#include "main/bufferobj.h"
#include "main/context.h"
#include "main/state.h"
#include "main/api_validate.h"
@@ -156,7 +156,13 @@ static GLuint byte_types_scale[5] = {
};
-static GLuint get_surface_type( GLenum type, GLuint size, GLboolean normalized )
+/**
+ * Given vertex array type/size/format/normalized info, return
+ * the appopriate hardware surface type.
+ * Format will be GL_RGBA or possibly GL_BGRA for GLubyte[4] color arrays.
+ */
+static GLuint get_surface_type( GLenum type, GLuint size,
+ GLenum format, GLboolean normalized )
{
if (INTEL_DEBUG & DEBUG_VERTS)
_mesa_printf("type %s size %d normalized %d\n",
@@ -171,11 +177,20 @@ static GLuint get_surface_type( GLenum type, GLuint size, GLboolean normalized )
case GL_BYTE: return byte_types_norm[size];
case GL_UNSIGNED_INT: return uint_types_norm[size];
case GL_UNSIGNED_SHORT: return ushort_types_norm[size];
- case GL_UNSIGNED_BYTE: return ubyte_types_norm[size];
+ case GL_UNSIGNED_BYTE:
+ if (format == GL_BGRA) {
+ /* See GL_EXT_vertex_array_bgra */
+ assert(size == 4);
+ return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+ }
+ else {
+ return ubyte_types_norm[size];
+ }
default: assert(0); return 0;
}
}
else {
+ assert(format == GL_RGBA); /* sanity check */
switch (type) {
case GL_DOUBLE: return double_types[size];
case GL_FLOAT: return float_types[size];
@@ -262,6 +277,7 @@ copy_array_to_vbo_array( struct brw_context *brw,
struct brw_vertex_element *element,
GLuint dst_stride)
{
+ struct intel_context *intel = &brw->intel;
GLuint size = element->count * dst_stride;
get_space(brw, size, &element->bo, &element->offset);
@@ -274,29 +290,52 @@ copy_array_to_vbo_array( struct brw_context *brw,
}
if (dst_stride == element->glarray->StrideB) {
- dri_bo_subdata(element->bo,
- element->offset,
- size,
- element->glarray->Ptr);
+ if (intel->intelScreen->kernel_exec_fencing) {
+ 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);
+ } else {
+ dri_bo_subdata(element->bo,
+ element->offset,
+ size,
+ element->glarray->Ptr);
+ }
} else {
- void *data;
char *dest;
- const char *src = element->glarray->Ptr;
+ const unsigned char *src = element->glarray->Ptr;
int i;
- data = _mesa_malloc(dst_stride * element->count);
- dest = data;
- for (i = 0; i < element->count; i++) {
- memcpy(dest, src, dst_stride);
- src += element->glarray->StrideB;
- dest += dst_stride;
- }
+ if (intel->intelScreen->kernel_exec_fencing) {
+ 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);
+ src += element->glarray->StrideB;
+ dest += dst_stride;
+ }
- dri_bo_subdata(element->bo,
- element->offset,
- size,
- data);
- _mesa_free(data);
+ drm_intel_gem_bo_unmap_gtt(element->bo);
+ } else {
+ void *data;
+
+ data = _mesa_malloc(dst_stride * element->count);
+ dest = data;
+ for (i = 0; i < element->count; i++) {
+ memcpy(dest, src, dst_stride);
+ src += element->glarray->StrideB;
+ dest += dst_stride;
+ }
+
+ dri_bo_subdata(element->bo,
+ element->offset,
+ size,
+ data);
+
+ _mesa_free(data);
+ }
}
}
@@ -304,16 +343,13 @@ static void brw_prepare_vertices(struct brw_context *brw)
{
GLcontext *ctx = &brw->intel.ctx;
struct intel_context *intel = intel_context(ctx);
- GLuint tmp = brw->vs.prog_data->inputs_read;
+ GLbitfield vs_inputs = brw->vs.prog_data->inputs_read;
GLuint i;
const unsigned char *ptr = NULL;
GLuint interleave = 0;
unsigned int min_index = brw->vb.min_index;
unsigned int max_index = brw->vb.max_index;
- struct brw_vertex_element *enabled[VERT_ATTRIB_MAX];
- GLuint nr_enabled = 0;
-
struct brw_vertex_element *upload[VERT_ATTRIB_MAX];
GLuint nr_uploads = 0;
@@ -323,12 +359,13 @@ static void brw_prepare_vertices(struct brw_context *brw)
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
/* Accumulate the list of enabled arrays. */
- while (tmp) {
- GLuint i = _mesa_ffsll(tmp)-1;
+ brw->vb.nr_enabled = 0;
+ while (vs_inputs) {
+ GLuint i = _mesa_ffsll(vs_inputs) - 1;
struct brw_vertex_element *input = &brw->vb.inputs[i];
- tmp &= ~(1<<i);
- enabled[nr_enabled++] = input;
+ vs_inputs &= ~(1 << i);
+ brw->vb.enabled[brw->vb.nr_enabled++] = input;
}
/* XXX: In the rare cases where this happens we fallback all
@@ -337,18 +374,17 @@ static void brw_prepare_vertices(struct brw_context *brw)
* cases with > 17 vertex attributes enabled, so it probably
* isn't an issue at this point.
*/
- if (nr_enabled >= BRW_VEP_MAX) {
+ if (brw->vb.nr_enabled >= BRW_VEP_MAX) {
intel->Fallback = 1;
return;
}
- for (i = 0; i < nr_enabled; i++) {
- struct brw_vertex_element *input = enabled[i];
+ for (i = 0; i < brw->vb.nr_enabled; i++) {
+ struct brw_vertex_element *input = brw->vb.enabled[i];
input->element_size = get_size(input->glarray->Type) * input->glarray->Size;
- input->count = input->glarray->StrideB ? max_index + 1 - min_index : 1;
- if (input->glarray->BufferObj->Name != 0) {
+ if (_mesa_is_bufferobj(input->glarray->BufferObj)) {
struct intel_buffer_object *intel_buffer =
intel_buffer_object(input->glarray->BufferObj);
@@ -359,7 +395,23 @@ static void brw_prepare_vertices(struct brw_context *brw)
dri_bo_reference(input->bo);
input->offset = (unsigned long)input->glarray->Ptr;
input->stride = input->glarray->StrideB;
+ input->count = input->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,
+ * we may end up dereferencing a pointer beyond the bounds of the
+ * GTT. We would hope that the VBO's max_index would save us, but
+ * Mesa appears to hand us min/max values not clipped to the
+ * array object's _MaxElement, and _MaxElement frequently appears
+ * to be wrong anyway.
+ *
+ * The VBO spec allows application termination in this case, and it's
+ * probably a service to the poor programmer to do so rather than
+ * trying to just not render.
+ */
+ assert(input->offset < input->bo->size);
} else {
+ input->count = input->glarray->StrideB ? max_index + 1 - min_index : 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
@@ -371,7 +423,7 @@ static void brw_prepare_vertices(struct brw_context *brw)
/* Queue the buffer object up to be uploaded in the next pass,
* when we've decided if we're doing interleaved or not.
*/
- if (i == 0) {
+ if (input->attrib == VERT_ATTRIB_POS) {
/* Position array not properly enabled:
*/
if (input->glarray->StrideB == 0) {
@@ -427,8 +479,8 @@ static void brw_prepare_vertices(struct brw_context *brw)
brw_prepare_query_begin(brw);
- for (i = 0; i < nr_enabled; i++) {
- struct brw_vertex_element *input = enabled[i];
+ for (i = 0; i < brw->vb.nr_enabled; i++) {
+ struct brw_vertex_element *input = brw->vb.enabled[i];
brw_add_validated_bo(brw, input->bo);
}
@@ -438,34 +490,44 @@ static void brw_emit_vertices(struct brw_context *brw)
{
GLcontext *ctx = &brw->intel.ctx;
struct intel_context *intel = intel_context(ctx);
- GLuint tmp = brw->vs.prog_data->inputs_read;
- struct brw_vertex_element *enabled[VERT_ATTRIB_MAX];
GLuint i;
- GLuint nr_enabled = 0;
- /* Accumulate the list of enabled arrays. */
- while (tmp) {
- i = _mesa_ffsll(tmp)-1;
- struct brw_vertex_element *input = &brw->vb.inputs[i];
+ brw_emit_query_begin(brw);
- tmp &= ~(1<<i);
- enabled[nr_enabled++] = input;
+ /* If the VS doesn't read any inputs (calculating vertex position from
+ * a state variable for some reason, for example), emit a single pad
+ * VERTEX_ELEMENT struct and bail.
+ *
+ * The stale VB state stays in place, but they don't do anything unless
+ * a VE loads from them.
+ */
+ if (brw->vb.nr_enabled == 0) {
+ BEGIN_BATCH(3, IGNORE_CLIPRECTS);
+ OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | 1);
+ OUT_BATCH((0 << BRW_VE0_INDEX_SHIFT) |
+ BRW_VE0_VALID |
+ (BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) |
+ (0 << BRW_VE0_SRC_OFFSET_SHIFT));
+ OUT_BATCH((BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_0_SHIFT) |
+ (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();
+ return;
}
- brw_emit_query_begin(brw);
-
/* 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 + nr_enabled * 4, IGNORE_CLIPRECTS);
+ BEGIN_BATCH(1 + brw->vb.nr_enabled * 4, IGNORE_CLIPRECTS);
OUT_BATCH((CMD_VERTEX_BUFFER << 16) |
- ((1 + nr_enabled * 4) - 2));
+ ((1 + brw->vb.nr_enabled * 4) - 2));
- for (i = 0; i < nr_enabled; i++) {
- struct brw_vertex_element *input = enabled[i];
+ for (i = 0; i < brw->vb.nr_enabled; i++) {
+ struct brw_vertex_element *input = brw->vb.enabled[i];
OUT_BATCH((i << BRW_VB0_INDEX_SHIFT) |
BRW_VB0_ACCESS_VERTEXDATA |
@@ -473,17 +535,30 @@ static void brw_emit_vertices(struct brw_context *brw)
OUT_RELOC(input->bo,
I915_GEM_DOMAIN_VERTEX, 0,
input->offset);
- OUT_BATCH(brw->vb.max_index);
+ if (BRW_IS_IGDNG(brw)) {
+ if (input->stride) {
+ OUT_RELOC(input->bo,
+ I915_GEM_DOMAIN_VERTEX, 0,
+ input->offset + input->stride * input->count);
+ } else {
+ assert(input->count == 1);
+ OUT_RELOC(input->bo,
+ I915_GEM_DOMAIN_VERTEX, 0,
+ input->offset + input->element_size);
+ }
+ } else
+ OUT_BATCH(input->stride ? input->count : 0);
OUT_BATCH(0); /* Instance data step rate */
}
ADVANCE_BATCH();
- BEGIN_BATCH(1 + nr_enabled * 2, IGNORE_CLIPRECTS);
- OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + nr_enabled * 2) - 2));
- for (i = 0; i < nr_enabled; i++) {
- struct brw_vertex_element *input = enabled[i];
+ BEGIN_BATCH(1 + brw->vb.nr_enabled * 2, IGNORE_CLIPRECTS);
+ OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + brw->vb.nr_enabled * 2) - 2));
+ 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,
input->glarray->Size,
+ input->glarray->Format,
input->glarray->Normalized);
uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC;
uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC;
@@ -502,11 +577,18 @@ static void brw_emit_vertices(struct brw_context *brw)
BRW_VE0_VALID |
(format << BRW_VE0_FORMAT_SHIFT) |
(0 << BRW_VE0_SRC_OFFSET_SHIFT));
- OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
- (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
- (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
- (comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
- ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
+
+ if (BRW_IS_IGDNG(brw))
+ OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
+ (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
+ (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
+ (comp3 << BRW_VE1_COMPONENT_3_SHIFT));
+ else
+ OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
+ (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
+ (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
+ (comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
+ ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
}
ADVANCE_BATCH();
}
@@ -530,26 +612,36 @@ static void brw_prepare_indices(struct brw_context *brw)
dri_bo *bo = NULL;
struct gl_buffer_object *bufferobj;
GLuint offset;
+ GLuint ib_type_size;
if (index_buffer == NULL)
return;
- ib_size = get_size(index_buffer->type) * index_buffer->count;
+ ib_type_size = get_size(index_buffer->type);
+ ib_size = ib_type_size * index_buffer->count;
bufferobj = index_buffer->obj;;
/* Turn into a proper VBO:
*/
- if (!bufferobj->Name) {
-
+ if (!_mesa_is_bufferobj(bufferobj)) {
+ brw->ib.start_vertex_offset = 0;
+
/* Get new bufferobj, offset:
*/
get_space(brw, ib_size, &bo, &offset);
/* Straight upload
*/
- dri_bo_subdata(bo, offset, ib_size, index_buffer->ptr);
+ if (intel->intelScreen->kernel_exec_fencing) {
+ drm_intel_gem_bo_map_gtt(bo);
+ memcpy((char *)bo->virtual + offset, index_buffer->ptr, ib_size);
+ drm_intel_gem_bo_unmap_gtt(bo);
+ } else {
+ dri_bo_subdata(bo, offset, ib_size, index_buffer->ptr);
+ }
} else {
- offset = (GLuint)index_buffer->ptr;
+ 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.
@@ -570,39 +662,62 @@ static void brw_prepare_indices(struct brw_context *brw)
bo = intel_bufferobj_buffer(intel, intel_buffer_object(bufferobj),
INTEL_READ);
dri_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;
}
}
- dri_bo_unreference(brw->ib.bo);
- brw->ib.bo = bo;
- brw->ib.offset = offset;
+ if (brw->ib.bo != bo ||
+ brw->ib.offset != offset ||
+ brw->ib.size != ib_size)
+ {
+ drm_intel_bo_unreference(brw->ib.bo);
+ brw->ib.bo = bo;
+ brw->ib.offset = offset;
+ brw->ib.size = ib_size;
+
+ brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER;
+ } else {
+ drm_intel_bo_unreference(bo);
+ }
brw_add_validated_bo(brw, brw->ib.bo);
}
-static void brw_emit_indices(struct brw_context *brw)
+const struct brw_tracked_state brw_indices = {
+ .dirty = {
+ .mesa = 0,
+ .brw = BRW_NEW_INDICES,
+ .cache = 0,
+ },
+ .prepare = brw_prepare_indices,
+};
+
+static void brw_emit_index_buffer(struct brw_context *brw)
{
struct intel_context *intel = &brw->intel;
const struct _mesa_index_buffer *index_buffer = brw->ib.ib;
- GLuint ib_size;
if (index_buffer == NULL)
return;
- ib_size = get_size(index_buffer->type) * index_buffer->count;
-
/* 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, IGNORE_CLIPRECTS);
OUT_BATCH( ib.header.dword );
@@ -611,18 +726,17 @@ static void brw_emit_indices(struct brw_context *brw)
brw->ib.offset);
OUT_RELOC(brw->ib.bo,
I915_GEM_DOMAIN_VERTEX, 0,
- brw->ib.offset + ib_size);
+ brw->ib.offset + brw->ib.size);
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
}
-const struct brw_tracked_state brw_indices = {
+const struct brw_tracked_state brw_index_buffer = {
.dirty = {
.mesa = 0,
- .brw = BRW_NEW_BATCH | BRW_NEW_INDICES,
+ .brw = BRW_NEW_BATCH | BRW_NEW_INDEX_BUFFER,
.cache = 0,
},
- .prepare = brw_prepare_indices,
- .emit = brw_emit_indices,
+ .emit = brw_emit_index_buffer,
};
diff --git a/src/mesa/drivers/dri/i965/brw_eu.c b/src/mesa/drivers/dri/i965/brw_eu.c
index b3ae4eef33..1df561386e 100644
--- a/src/mesa/drivers/dri/i965/brw_eu.c
+++ b/src/mesa/drivers/dri/i965/brw_eu.c
@@ -62,7 +62,7 @@ void brw_set_predicate_control( struct brw_compile *p, GLuint pc )
void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional )
{
- p->current->header.destreg__conditonalmod = conditional;
+ p->current->header.destreg__conditionalmod = conditional;
}
void brw_set_access_mode( struct brw_compile *p, GLuint access_mode )
@@ -129,3 +129,126 @@ const GLuint *brw_get_program( struct brw_compile *p,
return (const GLuint *)p->store;
}
+
+
+/**
+ * Subroutine calls require special attention.
+ * Mesa instructions may be expanded into multiple hardware instructions
+ * so the prog_instruction::BranchTarget field can't be used as an index
+ * into the hardware instructions.
+ *
+ * The BranchTarget field isn't needed, however. Mesa's GLSL compiler
+ * emits CAL and BGNSUB instructions with labels that can be used to map
+ * subroutine calls to actual subroutine code blocks.
+ *
+ * The structures and function here implement patching of CAL instructions
+ * so they jump to the right subroutine code...
+ */
+
+
+/**
+ * For each OPCODE_BGNSUB we create one of these.
+ */
+struct brw_glsl_label
+{
+ const char *name; /**< the label string */
+ GLuint position; /**< the position of the brw instruction for this label */
+ struct brw_glsl_label *next; /**< next in linked list */
+};
+
+
+/**
+ * For each OPCODE_CAL we create one of these.
+ */
+struct brw_glsl_call
+{
+ GLuint call_inst_pos; /**< location of the CAL instruction */
+ const char *sub_name; /**< name of subroutine to call */
+ struct brw_glsl_call *next; /**< next in linked list */
+};
+
+
+/**
+ * Called for each OPCODE_BGNSUB.
+ */
+void
+brw_save_label(struct brw_compile *c, const char *name, GLuint position)
+{
+ struct brw_glsl_label *label = CALLOC_STRUCT(brw_glsl_label);
+ label->name = name;
+ label->position = position;
+ label->next = c->first_label;
+ c->first_label = label;
+}
+
+
+/**
+ * Called for each OPCODE_CAL.
+ */
+void
+brw_save_call(struct brw_compile *c, const char *name, GLuint call_pos)
+{
+ struct brw_glsl_call *call = CALLOC_STRUCT(brw_glsl_call);
+ call->call_inst_pos = call_pos;
+ call->sub_name = name;
+ call->next = c->first_call;
+ c->first_call = call;
+}
+
+
+/**
+ * Lookup a label, return label's position/offset.
+ */
+static GLuint
+brw_lookup_label(struct brw_compile *c, const char *name)
+{
+ const struct brw_glsl_label *label;
+ for (label = c->first_label; label; label = label->next) {
+ if (strcmp(name, label->name) == 0) {
+ return label->position;
+ }
+ }
+ abort(); /* should never happen */
+ return ~0;
+}
+
+
+/**
+ * When we're done generating code, this function is called to resolve
+ * subroutine calls.
+ */
+void
+brw_resolve_cals(struct brw_compile *c)
+{
+ const struct brw_glsl_call *call;
+
+ for (call = c->first_call; call; call = call->next) {
+ const GLuint sub_loc = brw_lookup_label(c, call->sub_name);
+ struct brw_instruction *brw_call_inst = &c->store[call->call_inst_pos];
+ struct brw_instruction *brw_sub_inst = &c->store[sub_loc];
+ GLint offset = brw_sub_inst - brw_call_inst;
+
+ /* patch brw_inst1 to point to brw_inst2 */
+ brw_set_src1(brw_call_inst, brw_imm_d(offset * 16));
+ }
+
+ /* free linked list of calls */
+ {
+ struct brw_glsl_call *call, *next;
+ for (call = c->first_call; call; call = next) {
+ next = call->next;
+ _mesa_free(call);
+ }
+ c->first_call = NULL;
+ }
+
+ /* free linked list of labels */
+ {
+ struct brw_glsl_label *label, *next;
+ for (label = c->first_label; label; label = next) {
+ next = label->next;
+ _mesa_free(label);
+ }
+ c->first_label = NULL;
+ }
+}
diff --git a/src/mesa/drivers/dri/i965/brw_eu.h b/src/mesa/drivers/dri/i965/brw_eu.h
index 9e2b39af9b..30603bdd0e 100644
--- a/src/mesa/drivers/dri/i965/brw_eu.h
+++ b/src/mesa/drivers/dri/i965/brw_eu.h
@@ -91,8 +91,13 @@ struct brw_indirect {
};
+struct brw_glsl_label;
+struct brw_glsl_call;
+
+
+
#define BRW_EU_MAX_INSN_STACK 5
-#define BRW_EU_MAX_INSN 1200
+#define BRW_EU_MAX_INSN 10000
struct brw_compile {
struct brw_instruction store[BRW_EU_MAX_INSN];
@@ -106,9 +111,22 @@ struct brw_compile {
GLuint flag_value;
GLboolean single_program_flow;
struct brw_context *brw;
+
+ struct brw_glsl_label *first_label; /**< linked list of labels */
+ struct brw_glsl_call *first_call; /**< linked list of CALs */
};
+void
+brw_save_label(struct brw_compile *c, const char *name, GLuint position);
+
+void
+brw_save_call(struct brw_compile *c, const char *name, GLuint call_pos);
+
+void
+brw_resolve_cals(struct brw_compile *c);
+
+
static INLINE int type_sz( GLuint type )
{
@@ -152,6 +170,13 @@ static INLINE struct brw_reg brw_reg( GLuint file,
GLuint writemask )
{
struct brw_reg reg;
+ if (type == BRW_GENERAL_REGISTER_FILE)
+ assert(nr < BRW_MAX_GRF);
+ else if (type == BRW_MESSAGE_REGISTER_FILE)
+ assert(nr < BRW_MAX_MRF);
+ else if (type == BRW_ARCHITECTURE_REGISTER_FILE)
+ assert(nr <= BRW_ARF_IP);
+
reg.type = type;
reg.file = file;
reg.nr = nr;
@@ -513,6 +538,7 @@ static INLINE struct brw_reg brw_mask_reg( GLuint subnr )
static INLINE struct brw_reg brw_message_reg( GLuint nr )
{
+ assert(nr < BRW_MAX_MRF);
return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE,
nr,
0);
@@ -705,6 +731,13 @@ static INLINE struct brw_indirect brw_indirect( GLuint addr_subnr, GLint offset
return ptr;
}
+/** Do two brw_regs refer to the same register? */
+static INLINE GLboolean
+brw_same_reg(struct brw_reg r1, struct brw_reg r2)
+{
+ return r1.file == r2.file && r1.nr == r2.nr;
+}
+
static INLINE struct brw_instruction *current_insn( struct brw_compile *p)
{
return &p->store[p->nr_insn];
@@ -783,6 +816,19 @@ void brw_urb_WRITE(struct brw_compile *p,
GLuint offset,
GLuint swizzle);
+void brw_ff_sync(struct brw_compile *p,
+ struct brw_reg dest,
+ GLuint msg_reg_nr,
+ struct brw_reg src0,
+ GLboolean allocate,
+ GLboolean used,
+ GLuint msg_length,
+ GLuint response_length,
+ GLboolean eot,
+ GLboolean writes_complete,
+ GLuint offset,
+ GLuint swizzle);
+
void brw_fb_WRITE(struct brw_compile *p,
struct brw_reg dest,
GLuint msg_reg_nr,
@@ -802,7 +848,9 @@ void brw_SAMPLE(struct brw_compile *p,
GLuint msg_type,
GLuint response_length,
GLuint msg_length,
- GLboolean eot);
+ GLboolean eot,
+ GLuint header_present,
+ GLuint simd_mode);
void brw_math_16( struct brw_compile *p,
struct brw_reg dest,
@@ -823,12 +871,24 @@ void brw_math( struct brw_compile *p,
void brw_dp_READ_16( struct brw_compile *p,
struct brw_reg dest,
- GLuint msg_reg_nr,
GLuint scratch_offset );
+void brw_dp_READ_4( struct brw_compile *p,
+ struct brw_reg dest,
+ GLboolean relAddr,
+ GLuint location,
+ GLuint bind_table_index );
+
+void brw_dp_READ_4_vs( struct brw_compile *p,
+ struct brw_reg dest,
+ GLuint oword,
+ GLboolean relAddr,
+ struct brw_reg addrReg,
+ GLuint location,
+ GLuint bind_table_index );
+
void brw_dp_WRITE_16( struct brw_compile *p,
struct brw_reg src,
- GLuint msg_reg_nr,
GLuint scratch_offset );
/* If/else/endif. Works by manipulating the execution flags on each
diff --git a/src/mesa/drivers/dri/i965/brw_eu_debug.c b/src/mesa/drivers/dri/i965/brw_eu_debug.c
index 91dbbd5af6..29f3f6d02f 100644
--- a/src/mesa/drivers/dri/i965/brw_eu_debug.c
+++ b/src/mesa/drivers/dri/i965/brw_eu_debug.c
@@ -65,6 +65,7 @@ void brw_print_reg( struct brw_reg hwreg )
hwreg.width == BRW_WIDTH_8 &&
hwreg.hstride == BRW_HORIZONTAL_STRIDE_1 &&
hwreg.type == BRW_REGISTER_TYPE_F) {
+ /* vector register */
_mesa_printf("vec%d", hwreg.nr);
}
else if (hwreg.file == BRW_GENERAL_REGISTER_FILE &&
@@ -72,8 +73,12 @@ void brw_print_reg( struct brw_reg hwreg )
hwreg.width == BRW_WIDTH_1 &&
hwreg.hstride == BRW_HORIZONTAL_STRIDE_0 &&
hwreg.type == BRW_REGISTER_TYPE_F) {
+ /* "scalar" register */
_mesa_printf("scl%d.%d", hwreg.nr, hwreg.subnr / 4);
}
+ else if (hwreg.file == BRW_IMMEDIATE_VALUE) {
+ _mesa_printf("imm %f", hwreg.dw1.f);
+ }
else {
_mesa_printf("%s%d.%d<%d;%d,%d>:%s",
file[hwreg.file],
diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c
index 4e099b5945..241cdc33f8 100644
--- a/src/mesa/drivers/dri/i965/brw_eu_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c
@@ -55,6 +55,9 @@ static void guess_execution_size( struct brw_instruction *insn,
static void brw_set_dest( struct brw_instruction *insn,
struct brw_reg dest )
{
+ if (dest.type != BRW_ARCHITECTURE_REGISTER_FILE)
+ assert(dest.nr < 128);
+
insn->bits1.da1.dest_reg_file = dest.file;
insn->bits1.da1.dest_reg_type = dest.type;
insn->bits1.da1.dest_address_mode = dest.address_mode;
@@ -96,10 +99,13 @@ static void brw_set_dest( struct brw_instruction *insn,
}
static void brw_set_src0( struct brw_instruction *insn,
- struct brw_reg reg )
+ struct brw_reg reg )
{
assert(reg.file != BRW_MESSAGE_REGISTER_FILE);
+ if (reg.type != BRW_ARCHITECTURE_REGISTER_FILE)
+ assert(reg.nr < 128);
+
insn->bits1.da1.src0_reg_file = reg.file;
insn->bits1.da1.src0_reg_type = reg.type;
insn->bits2.da1.src0_abs = reg.abs;
@@ -169,10 +175,12 @@ static void brw_set_src0( struct brw_instruction *insn,
void brw_set_src1( struct brw_instruction *insn,
- struct brw_reg reg )
+ struct brw_reg reg )
{
assert(reg.file != BRW_MESSAGE_REGISTER_FILE);
+ assert(reg.nr < 128);
+
insn->bits1.da1.src1_reg_file = reg.file;
insn->bits1.da1.src1_reg_type = reg.type;
insn->bits3.da1.src1_abs = reg.abs;
@@ -233,7 +241,8 @@ void brw_set_src1( struct brw_instruction *insn,
-static void brw_set_math_message( struct brw_instruction *insn,
+static void brw_set_math_message( struct brw_context *brw,
+ struct brw_instruction *insn,
GLuint msg_length,
GLuint response_length,
GLuint function,
@@ -244,18 +253,35 @@ static void brw_set_math_message( struct brw_instruction *insn,
{
brw_set_src1(insn, brw_imm_d(0));
- insn->bits3.math.function = function;
- insn->bits3.math.int_type = integer_type;
- insn->bits3.math.precision = low_precision;
- insn->bits3.math.saturate = saturate;
- insn->bits3.math.data_type = dataType;
- insn->bits3.math.response_length = response_length;
- insn->bits3.math.msg_length = msg_length;
- insn->bits3.math.msg_target = BRW_MESSAGE_TARGET_MATH;
- insn->bits3.math.end_of_thread = 0;
+ if (BRW_IS_IGDNG(brw)) {
+ insn->bits3.math_igdng.function = function;
+ insn->bits3.math_igdng.int_type = integer_type;
+ insn->bits3.math_igdng.precision = low_precision;
+ insn->bits3.math_igdng.saturate = saturate;
+ insn->bits3.math_igdng.data_type = dataType;
+ insn->bits3.math_igdng.snapshot = 0;
+ insn->bits3.math_igdng.header_present = 0;
+ insn->bits3.math_igdng.response_length = response_length;
+ insn->bits3.math_igdng.msg_length = msg_length;
+ insn->bits3.math_igdng.end_of_thread = 0;
+ insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_MATH;
+ insn->bits2.send_igdng.end_of_thread = 0;
+ } else {
+ insn->bits3.math.function = function;
+ insn->bits3.math.int_type = integer_type;
+ insn->bits3.math.precision = low_precision;
+ insn->bits3.math.saturate = saturate;
+ insn->bits3.math.data_type = dataType;
+ insn->bits3.math.response_length = response_length;
+ insn->bits3.math.msg_length = msg_length;
+ insn->bits3.math.msg_target = BRW_MESSAGE_TARGET_MATH;
+ insn->bits3.math.end_of_thread = 0;
+ }
}
-static void brw_set_urb_message( struct brw_instruction *insn,
+
+static void brw_set_ff_sync_message( struct brw_context *brw,
+ struct brw_instruction *insn,
GLboolean allocate,
GLboolean used,
GLuint msg_length,
@@ -265,21 +291,64 @@ static void brw_set_urb_message( struct brw_instruction *insn,
GLuint offset,
GLuint swizzle_control )
{
- brw_set_src1(insn, brw_imm_d(0));
+ brw_set_src1(insn, brw_imm_d(0));
+
+ insn->bits3.urb_igdng.opcode = 1;
+ insn->bits3.urb_igdng.offset = offset;
+ insn->bits3.urb_igdng.swizzle_control = swizzle_control;
+ insn->bits3.urb_igdng.allocate = allocate;
+ insn->bits3.urb_igdng.used = used;
+ insn->bits3.urb_igdng.complete = complete;
+ insn->bits3.urb_igdng.header_present = 1;
+ insn->bits3.urb_igdng.response_length = response_length;
+ insn->bits3.urb_igdng.msg_length = msg_length;
+ insn->bits3.urb_igdng.end_of_thread = end_of_thread;
+ insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_URB;
+ insn->bits2.send_igdng.end_of_thread = end_of_thread;
+}
- insn->bits3.urb.opcode = 0; /* ? */
- insn->bits3.urb.offset = offset;
- insn->bits3.urb.swizzle_control = swizzle_control;
- insn->bits3.urb.allocate = allocate;
- insn->bits3.urb.used = used; /* ? */
- insn->bits3.urb.complete = complete;
- insn->bits3.urb.response_length = response_length;
- insn->bits3.urb.msg_length = msg_length;
- insn->bits3.urb.msg_target = BRW_MESSAGE_TARGET_URB;
- insn->bits3.urb.end_of_thread = end_of_thread;
+static void brw_set_urb_message( struct brw_context *brw,
+ struct brw_instruction *insn,
+ GLboolean allocate,
+ GLboolean used,
+ GLuint msg_length,
+ GLuint response_length,
+ GLboolean end_of_thread,
+ GLboolean complete,
+ GLuint offset,
+ GLuint swizzle_control )
+{
+ brw_set_src1(insn, brw_imm_d(0));
+
+ if (BRW_IS_IGDNG(brw)) {
+ insn->bits3.urb_igdng.opcode = 0; /* ? */
+ insn->bits3.urb_igdng.offset = offset;
+ insn->bits3.urb_igdng.swizzle_control = swizzle_control;
+ insn->bits3.urb_igdng.allocate = allocate;
+ insn->bits3.urb_igdng.used = used; /* ? */
+ insn->bits3.urb_igdng.complete = complete;
+ insn->bits3.urb_igdng.header_present = 1;
+ insn->bits3.urb_igdng.response_length = response_length;
+ insn->bits3.urb_igdng.msg_length = msg_length;
+ insn->bits3.urb_igdng.end_of_thread = end_of_thread;
+ insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_URB;
+ insn->bits2.send_igdng.end_of_thread = end_of_thread;
+ } else {
+ insn->bits3.urb.opcode = 0; /* ? */
+ insn->bits3.urb.offset = offset;
+ insn->bits3.urb.swizzle_control = swizzle_control;
+ insn->bits3.urb.allocate = allocate;
+ insn->bits3.urb.used = used; /* ? */
+ insn->bits3.urb.complete = complete;
+ insn->bits3.urb.response_length = response_length;
+ insn->bits3.urb.msg_length = msg_length;
+ insn->bits3.urb.msg_target = BRW_MESSAGE_TARGET_URB;
+ insn->bits3.urb.end_of_thread = end_of_thread;
+ }
}
-static void brw_set_dp_write_message( struct brw_instruction *insn,
+static void brw_set_dp_write_message( struct brw_context *brw,
+ struct brw_instruction *insn,
GLuint binding_table_index,
GLuint msg_control,
GLuint msg_type,
@@ -290,18 +359,33 @@ static void brw_set_dp_write_message( struct brw_instruction *insn,
{
brw_set_src1(insn, brw_imm_d(0));
- insn->bits3.dp_write.binding_table_index = binding_table_index;
- insn->bits3.dp_write.msg_control = msg_control;
- insn->bits3.dp_write.pixel_scoreboard_clear = pixel_scoreboard_clear;
- insn->bits3.dp_write.msg_type = msg_type;
- insn->bits3.dp_write.send_commit_msg = 0;
- insn->bits3.dp_write.response_length = response_length;
- insn->bits3.dp_write.msg_length = msg_length;
- insn->bits3.dp_write.msg_target = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
- insn->bits3.urb.end_of_thread = end_of_thread;
+ if (BRW_IS_IGDNG(brw)) {
+ insn->bits3.dp_write_igdng.binding_table_index = binding_table_index;
+ insn->bits3.dp_write_igdng.msg_control = msg_control;
+ insn->bits3.dp_write_igdng.pixel_scoreboard_clear = pixel_scoreboard_clear;
+ insn->bits3.dp_write_igdng.msg_type = msg_type;
+ insn->bits3.dp_write_igdng.send_commit_msg = 0;
+ insn->bits3.dp_write_igdng.header_present = 1;
+ insn->bits3.dp_write_igdng.response_length = response_length;
+ insn->bits3.dp_write_igdng.msg_length = msg_length;
+ insn->bits3.dp_write_igdng.end_of_thread = end_of_thread;
+ insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
+ insn->bits2.send_igdng.end_of_thread = end_of_thread;
+ } else {
+ insn->bits3.dp_write.binding_table_index = binding_table_index;
+ insn->bits3.dp_write.msg_control = msg_control;
+ insn->bits3.dp_write.pixel_scoreboard_clear = pixel_scoreboard_clear;
+ insn->bits3.dp_write.msg_type = msg_type;
+ insn->bits3.dp_write.send_commit_msg = 0;
+ insn->bits3.dp_write.response_length = response_length;
+ insn->bits3.dp_write.msg_length = msg_length;
+ insn->bits3.dp_write.msg_target = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
+ insn->bits3.dp_write.end_of_thread = end_of_thread;
+ }
}
-static void brw_set_dp_read_message( struct brw_instruction *insn,
+static void brw_set_dp_read_message( struct brw_context *brw,
+ struct brw_instruction *insn,
GLuint binding_table_index,
GLuint msg_control,
GLuint msg_type,
@@ -312,28 +396,57 @@ static void brw_set_dp_read_message( struct brw_instruction *insn,
{
brw_set_src1(insn, brw_imm_d(0));
- insn->bits3.dp_read.binding_table_index = binding_table_index;
- insn->bits3.dp_read.msg_control = msg_control;
- insn->bits3.dp_read.msg_type = msg_type;
- insn->bits3.dp_read.target_cache = target_cache;
- insn->bits3.dp_read.response_length = response_length;
- insn->bits3.dp_read.msg_length = msg_length;
- insn->bits3.dp_read.msg_target = BRW_MESSAGE_TARGET_DATAPORT_READ;
- insn->bits3.dp_read.end_of_thread = end_of_thread;
+ if (BRW_IS_IGDNG(brw)) {
+ insn->bits3.dp_read_igdng.binding_table_index = binding_table_index;
+ insn->bits3.dp_read_igdng.msg_control = msg_control;
+ insn->bits3.dp_read_igdng.msg_type = msg_type;
+ insn->bits3.dp_read_igdng.target_cache = target_cache;
+ insn->bits3.dp_read_igdng.header_present = 1;
+ insn->bits3.dp_read_igdng.response_length = response_length;
+ insn->bits3.dp_read_igdng.msg_length = msg_length;
+ insn->bits3.dp_read_igdng.pad1 = 0;
+ insn->bits3.dp_read_igdng.end_of_thread = end_of_thread;
+ insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_DATAPORT_READ;
+ insn->bits2.send_igdng.end_of_thread = end_of_thread;
+ } else {
+ insn->bits3.dp_read.binding_table_index = binding_table_index; /*0:7*/
+ insn->bits3.dp_read.msg_control = msg_control; /*8:11*/
+ insn->bits3.dp_read.msg_type = msg_type; /*12:13*/
+ insn->bits3.dp_read.target_cache = target_cache; /*14:15*/
+ insn->bits3.dp_read.response_length = response_length; /*16:19*/
+ insn->bits3.dp_read.msg_length = msg_length; /*20:23*/
+ insn->bits3.dp_read.msg_target = BRW_MESSAGE_TARGET_DATAPORT_READ; /*24:27*/
+ insn->bits3.dp_read.pad1 = 0; /*28:30*/
+ insn->bits3.dp_read.end_of_thread = end_of_thread; /*31*/
+ }
}
static void brw_set_sampler_message(struct brw_context *brw,
- struct brw_instruction *insn,
- GLuint binding_table_index,
- GLuint sampler,
- GLuint msg_type,
- GLuint response_length,
- GLuint msg_length,
- GLboolean eot)
+ struct brw_instruction *insn,
+ GLuint binding_table_index,
+ GLuint sampler,
+ GLuint msg_type,
+ GLuint response_length,
+ GLuint msg_length,
+ GLboolean eot,
+ GLuint header_present,
+ GLuint simd_mode)
{
+ assert(eot == 0);
brw_set_src1(insn, brw_imm_d(0));
- if (BRW_IS_G4X(brw)) {
+ if (BRW_IS_IGDNG(brw)) {
+ insn->bits3.sampler_igdng.binding_table_index = binding_table_index;
+ insn->bits3.sampler_igdng.sampler = sampler;
+ insn->bits3.sampler_igdng.msg_type = msg_type;
+ insn->bits3.sampler_igdng.simd_mode = simd_mode;
+ insn->bits3.sampler_igdng.header_present = header_present;
+ insn->bits3.sampler_igdng.response_length = response_length;
+ insn->bits3.sampler_igdng.msg_length = msg_length;
+ insn->bits3.sampler_igdng.end_of_thread = eot;
+ insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_SAMPLER;
+ insn->bits2.send_igdng.end_of_thread = eot;
+ } else if (BRW_IS_G4X(brw)) {
insn->bits3.sampler_g4x.binding_table_index = binding_table_index;
insn->bits3.sampler_g4x.sampler = sampler;
insn->bits3.sampler_g4x.msg_type = msg_type;
@@ -368,8 +481,8 @@ static struct brw_instruction *next_insn( struct brw_compile *p,
/* Reset this one-shot flag:
*/
- if (p->current->header.destreg__conditonalmod) {
- p->current->header.destreg__conditonalmod = 0;
+ if (p->current->header.destreg__conditionalmod) {
+ p->current->header.destreg__conditionalmod = 0;
p->current->header.predicate_control = BRW_PREDICATE_NORMAL;
}
@@ -407,7 +520,7 @@ static struct brw_instruction *brw_alu2(struct brw_compile *p,
* Convenience routines.
*/
#define ALU1(OP) \
-struct brw_instruction *brw_##OP(struct brw_compile *p, \
+struct brw_instruction *brw_##OP(struct brw_compile *p, \
struct brw_reg dest, \
struct brw_reg src0) \
{ \
@@ -415,7 +528,7 @@ struct brw_instruction *brw_##OP(struct brw_compile *p, \
}
#define ALU2(OP) \
-struct brw_instruction *brw_##OP(struct brw_compile *p, \
+struct brw_instruction *brw_##OP(struct brw_compile *p, \
struct brw_reg dest, \
struct brw_reg src0, \
struct brw_reg src1) \
@@ -469,12 +582,16 @@ void brw_NOP(struct brw_compile *p)
*/
struct brw_instruction *brw_JMPI(struct brw_compile *p,
- struct brw_reg dest,
- struct brw_reg src0,
- struct brw_reg src1)
+ struct brw_reg dest,
+ struct brw_reg src0,
+ struct brw_reg src1)
{
struct brw_instruction *insn = brw_alu2(p, BRW_OPCODE_JMPI, dest, src0, src1);
+ insn->header.execution_size = 1;
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.mask_control = BRW_MASK_DISABLE;
+
p->current->header.predicate_control = BRW_PREDICATE_NONE;
return insn;
@@ -531,6 +648,10 @@ struct brw_instruction *brw_ELSE(struct brw_compile *p,
struct brw_instruction *if_insn)
{
struct brw_instruction *insn;
+ GLuint br = 1;
+
+ if (BRW_IS_IGDNG(p->brw))
+ br = 2;
if (p->single_program_flow) {
insn = next_insn(p, BRW_OPCODE_ADD);
@@ -557,8 +678,8 @@ struct brw_instruction *brw_ELSE(struct brw_compile *p,
} else {
assert(if_insn->header.opcode == BRW_OPCODE_IF);
- if_insn->bits3.if_else.jump_count = insn - if_insn;
- if_insn->bits3.if_else.pop_count = 1;
+ if_insn->bits3.if_else.jump_count = br * (insn - if_insn);
+ if_insn->bits3.if_else.pop_count = 0;
if_insn->bits3.if_else.pad0 = 0;
}
@@ -568,6 +689,11 @@ struct brw_instruction *brw_ELSE(struct brw_compile *p,
void brw_ENDIF(struct brw_compile *p,
struct brw_instruction *patch_insn)
{
+ GLuint br = 1;
+
+ if (BRW_IS_IGDNG(p->brw))
+ br = 2;
+
if (p->single_program_flow) {
/* In single program flow mode, there's no need to execute an ENDIF,
* since we don't need to do any stack operations, and if we're executing
@@ -599,11 +725,11 @@ void brw_ENDIF(struct brw_compile *p,
/* Automagically turn it into an IFF:
*/
patch_insn->header.opcode = BRW_OPCODE_IFF;
- patch_insn->bits3.if_else.jump_count = insn - patch_insn + 1;
+ patch_insn->bits3.if_else.jump_count = br * (insn - patch_insn + 1);
patch_insn->bits3.if_else.pop_count = 0;
patch_insn->bits3.if_else.pad0 = 0;
} else if (patch_insn->header.opcode == BRW_OPCODE_ELSE) {
- patch_insn->bits3.if_else.jump_count = insn - patch_insn + 1;
+ patch_insn->bits3.if_else.jump_count = br * (insn - patch_insn + 1);
patch_insn->bits3.if_else.pop_count = 1;
patch_insn->bits3.if_else.pad0 = 0;
} else {
@@ -674,9 +800,13 @@ struct brw_instruction *brw_DO(struct brw_compile *p, GLuint execute_size)
struct brw_instruction *brw_WHILE(struct brw_compile *p,
- struct brw_instruction *do_insn)
+ struct brw_instruction *do_insn)
{
struct brw_instruction *insn;
+ GLuint br = 1;
+
+ if (BRW_IS_IGDNG(p->brw))
+ br = 2;
if (p->single_program_flow)
insn = next_insn(p, BRW_OPCODE_ADD);
@@ -697,7 +827,7 @@ struct brw_instruction *brw_WHILE(struct brw_compile *p,
insn->header.execution_size = do_insn->header.execution_size;
assert(do_insn->header.opcode == BRW_OPCODE_DO);
- insn->bits3.if_else.jump_count = do_insn - insn + 1;
+ insn->bits3.if_else.jump_count = br * (do_insn - insn + 1);
insn->bits3.if_else.pop_count = 0;
insn->bits3.if_else.pad0 = 0;
}
@@ -716,11 +846,15 @@ void brw_land_fwd_jump(struct brw_compile *p,
struct brw_instruction *jmp_insn)
{
struct brw_instruction *landing = &p->store[p->nr_insn];
+ GLuint jmpi = 1;
+
+ if (BRW_IS_IGDNG(p->brw))
+ jmpi = 2;
assert(jmp_insn->header.opcode == BRW_OPCODE_JMPI);
assert(jmp_insn->bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE);
- jmp_insn->bits3.ud = (landing - jmp_insn) - 1;
+ jmp_insn->bits3.ud = jmpi * ((landing - jmp_insn) - 1);
}
@@ -737,7 +871,7 @@ void brw_CMP(struct brw_compile *p,
{
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_CMP);
- insn->header.destreg__conditonalmod = conditional;
+ insn->header.destreg__conditionalmod = conditional;
brw_set_dest(insn, dest);
brw_set_src0(insn, src0);
brw_set_src1(insn, src1);
@@ -762,7 +896,7 @@ void brw_CMP(struct brw_compile *p,
* Helpers for the various SEND message types:
*/
-/* Invert 8 values
+/** Extended math function, float[8].
*/
void brw_math( struct brw_compile *p,
struct brw_reg dest,
@@ -781,11 +915,12 @@ void brw_math( struct brw_compile *p,
* instructions.
*/
insn->header.predicate_control = 0;
- insn->header.destreg__conditonalmod = msg_reg_nr;
+ insn->header.destreg__conditionalmod = msg_reg_nr;
brw_set_dest(insn, dest);
brw_set_src0(insn, src);
- brw_set_math_message(insn,
+ brw_set_math_message(p->brw,
+ insn,
msg_length, response_length,
function,
BRW_MATH_INTEGER_UNSIGNED,
@@ -794,7 +929,9 @@ void brw_math( struct brw_compile *p,
data_type);
}
-/* Use 2 send instructions to invert 16 elements
+/**
+ * Extended math function, float[16].
+ * Use 2 send instructions.
*/
void brw_math_16( struct brw_compile *p,
struct brw_reg dest,
@@ -815,11 +952,12 @@ void brw_math_16( struct brw_compile *p,
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
insn = next_insn(p, BRW_OPCODE_SEND);
- insn->header.destreg__conditonalmod = msg_reg_nr;
+ insn->header.destreg__conditionalmod = msg_reg_nr;
brw_set_dest(insn, dest);
brw_set_src0(insn, src);
- brw_set_math_message(insn,
+ brw_set_math_message(p->brw,
+ insn,
msg_length, response_length,
function,
BRW_MATH_INTEGER_UNSIGNED,
@@ -831,11 +969,12 @@ void brw_math_16( struct brw_compile *p,
*/
insn = next_insn(p, BRW_OPCODE_SEND);
insn->header.compression_control = BRW_COMPRESSION_2NDHALF;
- insn->header.destreg__conditonalmod = msg_reg_nr+1;
+ insn->header.destreg__conditionalmod = msg_reg_nr+1;
brw_set_dest(insn, offset(dest,1));
brw_set_src0(insn, src);
- brw_set_math_message(insn,
+ brw_set_math_message(p->brw,
+ insn,
msg_length, response_length,
function,
BRW_MATH_INTEGER_UNSIGNED,
@@ -847,22 +986,26 @@ void brw_math_16( struct brw_compile *p,
}
-
-
+/**
+ * Write block of 16 dwords/floats to the data port Render Cache scratch buffer.
+ * Scratch offset should be a multiple of 64.
+ * Used for register spilling.
+ */
void brw_dp_WRITE_16( struct brw_compile *p,
struct brw_reg src,
- GLuint msg_reg_nr,
GLuint scratch_offset )
{
+ GLuint msg_reg_nr = 1;
{
brw_push_insn_state(p);
brw_set_mask_control(p, BRW_MASK_DISABLE);
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+ /* set message header global offset field (reg 0, element 2) */
brw_MOV(p,
retype(brw_vec1_grf(0, 2), BRW_REGISTER_TYPE_D),
brw_imm_d(scratch_offset));
-
+
brw_pop_insn_state(p);
}
@@ -873,13 +1016,14 @@ void brw_dp_WRITE_16( struct brw_compile *p,
insn->header.predicate_control = 0; /* XXX */
insn->header.compression_control = BRW_COMPRESSION_NONE;
- insn->header.destreg__conditonalmod = msg_reg_nr;
+ insn->header.destreg__conditionalmod = msg_reg_nr;
brw_set_dest(insn, dest);
brw_set_src0(insn, src);
- brw_set_dp_write_message(insn,
- 255, /* bti */
+ brw_set_dp_write_message(p->brw,
+ insn,
+ 255, /* binding table index (255=stateless) */
BRW_DATAPORT_OWORD_BLOCK_4_OWORDS, /* msg_control */
BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE, /* msg_type */
msg_length,
@@ -887,24 +1031,29 @@ void brw_dp_WRITE_16( struct brw_compile *p,
0, /* response_length */
0); /* eot */
}
-
}
+/**
+ * Read block of 16 dwords/floats from the data port Render Cache scratch buffer.
+ * Scratch offset should be a multiple of 64.
+ * Used for register spilling.
+ */
void brw_dp_READ_16( struct brw_compile *p,
struct brw_reg dest,
- GLuint msg_reg_nr,
GLuint scratch_offset )
{
+ GLuint msg_reg_nr = 1;
{
brw_push_insn_state(p);
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
brw_set_mask_control(p, BRW_MASK_DISABLE);
+ /* set message header global offset field (reg 0, element 2) */
brw_MOV(p,
retype(brw_vec1_grf(0, 2), BRW_REGISTER_TYPE_D),
brw_imm_d(scratch_offset));
-
+
brw_pop_insn_state(p);
}
@@ -913,16 +1062,17 @@ void brw_dp_READ_16( struct brw_compile *p,
insn->header.predicate_control = 0; /* XXX */
insn->header.compression_control = BRW_COMPRESSION_NONE;
- insn->header.destreg__conditonalmod = msg_reg_nr;
+ insn->header.destreg__conditionalmod = msg_reg_nr;
brw_set_dest(insn, dest); /* UW? */
brw_set_src0(insn, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW));
- brw_set_dp_read_message(insn,
- 255, /* bti */
- 3, /* msg_control */
+ brw_set_dp_read_message(p->brw,
+ insn,
+ 255, /* binding table index (255=stateless) */
+ 3, /* msg_control (3 means 4 Owords) */
BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, /* msg_type */
- 1, /* target cache */
+ 1, /* target cache (render/scratch) */
1, /* msg_length */
2, /* response_length */
0); /* eot */
@@ -930,24 +1080,156 @@ void brw_dp_READ_16( struct brw_compile *p,
}
+/**
+ * Read a float[4] vector from the data port Data Cache (const buffer).
+ * Location (in buffer) should be a multiple of 16.
+ * Used for fetching shader constants.
+ * If relAddr is true, we'll do an indirect fetch using the address register.
+ */
+void brw_dp_READ_4( struct brw_compile *p,
+ struct brw_reg dest,
+ GLboolean relAddr,
+ GLuint location,
+ GLuint bind_table_index )
+{
+ /* XXX: relAddr not implemented */
+ GLuint msg_reg_nr = 1;
+ {
+ struct brw_reg b;
+ brw_push_insn_state(p);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_set_mask_control(p, BRW_MASK_DISABLE);
+
+ /* Setup MRF[1] with location/offset into const buffer */
+ b = brw_message_reg(msg_reg_nr);
+ b = retype(b, BRW_REGISTER_TYPE_UD);
+ /* XXX I think we're setting all the dwords of MRF[1] to 'location'.
+ * when the docs say only dword[2] should be set. Hmmm. But it works.
+ */
+ brw_MOV(p, b, brw_imm_ud(location));
+ brw_pop_insn_state(p);
+ }
+
+ {
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+
+ insn->header.predicate_control = BRW_PREDICATE_NONE;
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.destreg__conditionalmod = msg_reg_nr;
+ insn->header.mask_control = BRW_MASK_DISABLE;
+
+ /* cast dest to a uword[8] vector */
+ dest = retype(vec8(dest), BRW_REGISTER_TYPE_UW);
+
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, brw_null_reg());
+
+ brw_set_dp_read_message(p->brw,
+ insn,
+ bind_table_index,
+ 0, /* msg_control (0 means 1 Oword) */
+ BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, /* msg_type */
+ 0, /* source cache = data cache */
+ 1, /* msg_length */
+ 1, /* response_length (1 Oword) */
+ 0); /* eot */
+ }
+}
+
+
+/**
+ * Read float[4] constant(s) from VS constant buffer.
+ * For relative addressing, two float[4] constants will be read into 'dest'.
+ * Otherwise, one float[4] constant will be read into the lower half of 'dest'.
+ */
+void brw_dp_READ_4_vs(struct brw_compile *p,
+ struct brw_reg dest,
+ GLuint oword,
+ GLboolean relAddr,
+ struct brw_reg addrReg,
+ GLuint location,
+ GLuint bind_table_index)
+{
+ GLuint msg_reg_nr = 1;
+
+ assert(oword < 2);
+ /*
+ printf("vs const read msg, location %u, msg_reg_nr %d\n",
+ location, msg_reg_nr);
+ */
+
+ /* Setup MRF[1] with location/offset into const buffer */
+ {
+ struct brw_reg b;
+
+ brw_push_insn_state(p);
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+ brw_set_mask_control(p, BRW_MASK_DISABLE);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ /*brw_set_access_mode(p, BRW_ALIGN_16);*/
+
+ /* XXX I think we're setting all the dwords of MRF[1] to 'location'.
+ * when the docs say only dword[2] should be set. Hmmm. But it works.
+ */
+ b = brw_message_reg(msg_reg_nr);
+ b = retype(b, BRW_REGISTER_TYPE_UD);
+ /*b = get_element_ud(b, 2);*/
+ if (relAddr) {
+ brw_ADD(p, b, addrReg, brw_imm_ud(location));
+ }
+ else {
+ brw_MOV(p, b, brw_imm_ud(location));
+ }
+
+ brw_pop_insn_state(p);
+ }
+
+ {
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+
+ insn->header.predicate_control = BRW_PREDICATE_NONE;
+ insn->header.compression_control = BRW_COMPRESSION_NONE;
+ insn->header.destreg__conditionalmod = msg_reg_nr;
+ insn->header.mask_control = BRW_MASK_DISABLE;
+ /*insn->header.access_mode = BRW_ALIGN_16;*/
+
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, brw_null_reg());
+
+ brw_set_dp_read_message(p->brw,
+ insn,
+ bind_table_index,
+ oword, /* 0 = lower Oword, 1 = upper Oword */
+ BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, /* msg_type */
+ 0, /* source cache = data cache */
+ 1, /* msg_length */
+ 1, /* response_length (1 Oword) */
+ 0); /* eot */
+ }
+}
+
+
+
void brw_fb_WRITE(struct brw_compile *p,
- struct brw_reg dest,
- GLuint msg_reg_nr,
- struct brw_reg src0,
- GLuint binding_table_index,
- GLuint msg_length,
- GLuint response_length,
- GLboolean eot)
+ struct brw_reg dest,
+ GLuint msg_reg_nr,
+ struct brw_reg src0,
+ GLuint binding_table_index,
+ GLuint msg_length,
+ GLuint response_length,
+ GLboolean eot)
{
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
insn->header.predicate_control = 0; /* XXX */
insn->header.compression_control = BRW_COMPRESSION_NONE;
- insn->header.destreg__conditonalmod = msg_reg_nr;
+ insn->header.destreg__conditionalmod = msg_reg_nr;
brw_set_dest(insn, dest);
brw_set_src0(insn, src0);
- brw_set_dp_write_message(insn,
+ brw_set_dp_write_message(p->brw,
+ insn,
binding_table_index,
BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE, /* msg_control */
BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE, /* msg_type */
@@ -958,7 +1240,11 @@ void brw_fb_WRITE(struct brw_compile *p,
}
-
+/**
+ * Texture sample instruction.
+ * Note: the msg_type plus msg_length values determine exactly what kind
+ * of sampling operation is performed. See volume 4, page 161 of docs.
+ */
void brw_SAMPLE(struct brw_compile *p,
struct brw_reg dest,
GLuint msg_reg_nr,
@@ -969,12 +1255,14 @@ void brw_SAMPLE(struct brw_compile *p,
GLuint msg_type,
GLuint response_length,
GLuint msg_length,
- GLboolean eot)
+ GLboolean eot,
+ GLuint header_present,
+ GLuint simd_mode)
{
GLboolean need_stall = 0;
- if(writemask == 0) {
-/* _mesa_printf("%s: zero writemask??\n", __FUNCTION__); */
+ if (writemask == 0) {
+ /*_mesa_printf("%s: zero writemask??\n", __FUNCTION__); */
return;
}
@@ -1006,7 +1294,7 @@ void brw_SAMPLE(struct brw_compile *p,
if (newmask != writemask) {
need_stall = 1;
-/* _mesa_printf("need stall %x %x\n", newmask , writemask); */
+ /* _mesa_printf("need stall %x %x\n", newmask , writemask); */
}
else {
struct brw_reg m1 = brw_message_reg(msg_reg_nr);
@@ -1034,7 +1322,7 @@ void brw_SAMPLE(struct brw_compile *p,
insn->header.predicate_control = 0; /* XXX */
insn->header.compression_control = BRW_COMPRESSION_NONE;
- insn->header.destreg__conditonalmod = msg_reg_nr;
+ insn->header.destreg__conditionalmod = msg_reg_nr;
brw_set_dest(insn, dest);
brw_set_src0(insn, src0);
@@ -1044,17 +1332,18 @@ void brw_SAMPLE(struct brw_compile *p,
msg_type,
response_length,
msg_length,
- eot);
+ eot,
+ header_present,
+ simd_mode);
}
- if (need_stall)
- {
+ if (need_stall) {
struct brw_reg reg = vec8(offset(dest, response_length-1));
/* mov (8) r9.0<1>:f r9.0<8;8,1>:f { Align1 }
*/
brw_push_insn_state(p);
- brw_set_compression_control(p, GL_FALSE);
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
brw_MOV(p, reg, reg);
brw_pop_insn_state(p);
}
@@ -1080,15 +1369,16 @@ void brw_urb_WRITE(struct brw_compile *p,
{
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
- assert(msg_length < 16);
+ assert(msg_length < BRW_MAX_MRF);
brw_set_dest(insn, dest);
brw_set_src0(insn, src0);
brw_set_src1(insn, brw_imm_d(0));
- insn->header.destreg__conditonalmod = msg_reg_nr;
+ insn->header.destreg__conditionalmod = msg_reg_nr;
- brw_set_urb_message(insn,
+ brw_set_urb_message(p->brw,
+ insn,
allocate,
used,
msg_length,
@@ -1099,3 +1389,37 @@ void brw_urb_WRITE(struct brw_compile *p,
swizzle);
}
+void brw_ff_sync(struct brw_compile *p,
+ struct brw_reg dest,
+ GLuint msg_reg_nr,
+ struct brw_reg src0,
+ GLboolean allocate,
+ GLboolean used,
+ GLuint msg_length,
+ GLuint response_length,
+ GLboolean eot,
+ GLboolean writes_complete,
+ GLuint offset,
+ GLuint swizzle)
+{
+ struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+
+ assert(msg_length < 16);
+
+ brw_set_dest(insn, dest);
+ brw_set_src0(insn, src0);
+ brw_set_src1(insn, brw_imm_d(0));
+
+ insn->header.destreg__conditionalmod = msg_reg_nr;
+
+ brw_set_ff_sync_message(p->brw,
+ insn,
+ allocate,
+ used,
+ msg_length,
+ response_length,
+ eot,
+ writes_complete,
+ offset,
+ swizzle);
+}
diff --git a/src/mesa/drivers/dri/i965/brw_fallback.c b/src/mesa/drivers/dri/i965/brw_fallback.c
index 4ea660a51a..d27c6c24ca 100644
--- a/src/mesa/drivers/dri/i965/brw_fallback.c
+++ b/src/mesa/drivers/dri/i965/brw_fallback.c
@@ -37,6 +37,9 @@
#include "tnl/tnl.h"
#include "brw_context.h"
#include "brw_fallback.h"
+#include "intel_chipset.h"
+#include "intel_fbo.h"
+#include "intel_regions.h"
#include "glapi/glapi.h"
@@ -44,23 +47,16 @@
static GLboolean do_check_fallback(struct brw_context *brw)
{
+ struct intel_context *intel = &brw->intel;
GLcontext *ctx = &brw->intel.ctx;
GLuint i;
- /* BRW_NEW_METAOPS
- */
- if (brw->metaops.active)
- return GL_FALSE;
-
if (brw->intel.no_rast) {
DBG("FALLBACK: rasterization disabled\n");
return GL_TRUE;
}
/* _NEW_RENDERMODE
- *
- * XXX: need to save/restore RenderMode in metaops state, or
- * somehow move to a new attribs pointer:
*/
if (ctx->RenderMode != GL_RENDER) {
DBG("FALLBACK: render mode\n");
@@ -70,7 +66,7 @@ static GLboolean do_check_fallback(struct brw_context *brw)
/* _NEW_TEXTURE:
*/
for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
- struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[i];
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
if (texUnit->_ReallyEnabled) {
struct intel_texture_object *intelObj = intel_texture_object(texUnit->_Current);
struct gl_texture_image *texImage = intelObj->base.Image[0][intelObj->firstLevel];
@@ -83,12 +79,39 @@ static GLboolean do_check_fallback(struct brw_context *brw)
/* _NEW_STENCIL
*/
- if (brw->attribs.Stencil->Enabled &&
- !brw->intel.hw_stencil) {
+ if (ctx->Stencil._Enabled &&
+ (ctx->DrawBuffer->Name == 0 && !brw->intel.hw_stencil)) {
DBG("FALLBACK: stencil\n");
return GL_TRUE;
}
+ /* _NEW_BUFFERS */
+ if (IS_965(intel->intelScreen->deviceID) &&
+ !IS_G4X(intel->intelScreen->deviceID)) {
+ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+
+ /* The original gen4 hardware couldn't set up WM surfaces pointing
+ * at an offset within a tile, which can happen when rendering to
+ * anything but the base level of a texture or the +X face/0 depth.
+ * This was fixed with the 4 Series hardware.
+ *
+ * For these original chips, you would have to make the depth and
+ * color destination surfaces include information on the texture
+ * type, LOD, face, and various limits to use them as a destination.
+ * I would have done this, but there's also a nasty requirement that
+ * the depth and the color surfaces all be of the same LOD, which
+ * may be a worse requirement than this alignment. (Also, we may
+ * want to just demote the texture to untiled, instead).
+ */
+ if (irb->region && irb->region->tiling != I915_TILING_NONE &&
+ (irb->region->draw_offset & 4095)) {
+ DBG("FALLBACK: non-tile-aligned destination for tiled FBO\n");
+ return GL_TRUE;
+ }
+ }
+ }
return GL_FALSE;
}
@@ -101,7 +124,7 @@ static void check_fallback(struct brw_context *brw)
const struct brw_tracked_state brw_check_fallback = {
.dirty = {
.mesa = _NEW_BUFFERS | _NEW_RENDERMODE | _NEW_TEXTURE | _NEW_STENCIL,
- .brw = BRW_NEW_METAOPS,
+ .brw = 0,
.cache = 0
},
.prepare = check_fallback
diff --git a/src/mesa/drivers/dri/i965/brw_gs.c b/src/mesa/drivers/dri/i965/brw_gs.c
index a8b74a0afe..48c2b9a41c 100644
--- a/src/mesa/drivers/dri/i965/brw_gs.c
+++ b/src/mesa/drivers/dri/i965/brw_gs.c
@@ -54,12 +54,17 @@ static void compile_gs_prog( struct brw_context *brw,
memset(&c, 0, sizeof(c));
c.key = *key;
-
+ c.need_ff_sync = BRW_IS_IGDNG(brw);
/* Need to locate the two positions present in vertex + header.
* These are currently hardcoded:
*/
c.nr_attrs = brw_count_bits(c.key.attrs);
- c.nr_regs = (c.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */
+
+ if (BRW_IS_IGDNG(brw))
+ c.nr_regs = (c.nr_attrs + 1) / 2 + 3; /* are vertices packed, or reg-aligned? */
+ else
+ c.nr_regs = (c.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */
+
c.nr_bytes = c.nr_regs * REG_SIZE;
diff --git a/src/mesa/drivers/dri/i965/brw_gs.h b/src/mesa/drivers/dri/i965/brw_gs.h
index 18a4537c32..bbb991ea2e 100644
--- a/src/mesa/drivers/dri/i965/brw_gs.h
+++ b/src/mesa/drivers/dri/i965/brw_gs.h
@@ -62,6 +62,7 @@ struct brw_gs_compile {
GLuint nr_attrs;
GLuint nr_regs;
GLuint nr_bytes;
+ GLboolean need_ff_sync;
};
#define ATTR_SIZE (4*4)
diff --git a/src/mesa/drivers/dri/i965/brw_gs_emit.c b/src/mesa/drivers/dri/i965/brw_gs_emit.c
index 22e0d25c2e..a9b2aa2eac 100644
--- a/src/mesa/drivers/dri/i965/brw_gs_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_gs_emit.c
@@ -101,6 +101,23 @@ static void brw_gs_emit_vue(struct brw_gs_compile *c,
BRW_URB_SWIZZLE_NONE);
}
+static void brw_gs_ff_sync(struct brw_gs_compile *c, int num_prim)
+{
+ struct brw_compile *p = &c->func;
+ brw_MOV(p, get_element_ud(c->reg.R0, 1), brw_imm_ud(num_prim));
+ brw_ff_sync(p,
+ c->reg.R0,
+ 0,
+ c->reg.R0,
+ 1,
+ 1, /* used */
+ 1, /* msg length */
+ 1, /* response length */
+ 0, /* eot */
+ 1, /* write compelete */
+ 0, /* urb offset */
+ BRW_URB_SWIZZLE_NONE);
+}
void brw_gs_quads( struct brw_gs_compile *c )
@@ -110,6 +127,8 @@ void brw_gs_quads( struct brw_gs_compile *c )
/* Use polygons for correct edgeflag behaviour. Note that vertex 3
* is the PV for quads, but vertex 0 for polygons:
*/
+ if (c->need_ff_sync)
+ brw_gs_ff_sync(c, 1);
brw_gs_emit_vue(c, c->reg.vertex[3], 0, ((_3DPRIM_POLYGON << 2) | R02_PRIM_START));
brw_gs_emit_vue(c, c->reg.vertex[0], 0, (_3DPRIM_POLYGON << 2));
brw_gs_emit_vue(c, c->reg.vertex[1], 0, (_3DPRIM_POLYGON << 2));
@@ -120,6 +139,8 @@ void brw_gs_quad_strip( struct brw_gs_compile *c )
{
brw_gs_alloc_regs(c, 4);
+ if (c->need_ff_sync)
+ brw_gs_ff_sync(c, 1);
brw_gs_emit_vue(c, c->reg.vertex[2], 0, ((_3DPRIM_POLYGON << 2) | R02_PRIM_START));
brw_gs_emit_vue(c, c->reg.vertex[3], 0, (_3DPRIM_POLYGON << 2));
brw_gs_emit_vue(c, c->reg.vertex[0], 0, (_3DPRIM_POLYGON << 2));
@@ -129,6 +150,9 @@ void brw_gs_quad_strip( struct brw_gs_compile *c )
void brw_gs_tris( struct brw_gs_compile *c )
{
brw_gs_alloc_regs(c, 3);
+
+ if (c->need_ff_sync)
+ brw_gs_ff_sync(c, 1);
brw_gs_emit_vue(c, c->reg.vertex[0], 0, ((_3DPRIM_TRILIST << 2) | R02_PRIM_START));
brw_gs_emit_vue(c, c->reg.vertex[1], 0, (_3DPRIM_TRILIST << 2));
brw_gs_emit_vue(c, c->reg.vertex[2], 1, ((_3DPRIM_TRILIST << 2) | R02_PRIM_END));
@@ -137,6 +161,9 @@ void brw_gs_tris( struct brw_gs_compile *c )
void brw_gs_lines( struct brw_gs_compile *c )
{
brw_gs_alloc_regs(c, 2);
+
+ if (c->need_ff_sync)
+ brw_gs_ff_sync(c, 1);
brw_gs_emit_vue(c, c->reg.vertex[0], 0, ((_3DPRIM_LINESTRIP << 2) | R02_PRIM_START));
brw_gs_emit_vue(c, c->reg.vertex[1], 1, ((_3DPRIM_LINESTRIP << 2) | R02_PRIM_END));
}
@@ -144,6 +171,9 @@ void brw_gs_lines( struct brw_gs_compile *c )
void brw_gs_points( struct brw_gs_compile *c )
{
brw_gs_alloc_regs(c, 1);
+
+ if (c->need_ff_sync)
+ brw_gs_ff_sync(c, 1);
brw_gs_emit_vue(c, c->reg.vertex[0], 1, ((_3DPRIM_POINTLIST << 2) | R02_PRIM_START | R02_PRIM_END));
}
diff --git a/src/mesa/drivers/dri/i965/brw_gs_state.c b/src/mesa/drivers/dri/i965/brw_gs_state.c
index 27023cf034..ed9d2ffe60 100644
--- a/src/mesa/drivers/dri/i965/brw_gs_state.c
+++ b/src/mesa/drivers/dri/i965/brw_gs_state.c
@@ -93,7 +93,13 @@ gs_unit_create_from_key(struct brw_context *brw, struct brw_gs_unit_key *key)
gs.thread4.nr_urb_entries = key->nr_urb_entries;
gs.thread4.urb_entry_allocation_size = key->urb_size - 1;
- gs.thread4.max_threads = 0; /* Hardware requirement */
+ if (key->nr_urb_entries >= 8)
+ gs.thread4.max_threads = 1;
+ else
+ gs.thread4.max_threads = 0;
+
+ if (BRW_IS_IGDNG(brw))
+ gs.thread4.rendering_enable = 1;
if (INTEL_DEBUG & DEBUG_STATS)
gs.thread4.stats_enable = 1;
diff --git a/src/mesa/drivers/dri/i965/brw_metaops.c b/src/mesa/drivers/dri/i965/brw_metaops.c
deleted file mode 100644
index 41bfa2e256..0000000000
--- a/src/mesa/drivers/dri/i965/brw_metaops.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- Copyright (C) Intel Corp. 2006. All Rights Reserved.
- Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- develop this 3D driver.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice (including the
- next paragraph) shall be included in all copies or substantial
- portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- **********************************************************************/
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- * frame buffer texture by Gary Wong <gtw@gnu.org>
- */
-
-
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/macros.h"
-
-#include "shader/arbprogparse.h"
-
-#include "intel_screen.h"
-#include "intel_batchbuffer.h"
-#include "intel_regions.h"
-#include "intel_buffers.h"
-
-#include "brw_context.h"
-#include "brw_defines.h"
-#include "brw_draw.h"
-#include "brw_fallback.h"
-
-#define INIT(brw, STRUCT, ATTRIB) \
-do { \
- brw->attribs.ATTRIB = &ctx->ATTRIB; \
-} while (0)
-
-#define DUP(brw, STRUCT, ATTRIB) \
-do { \
- brw->metaops.attribs.ATTRIB = MALLOC_STRUCT(STRUCT); \
- memcpy(brw->metaops.attribs.ATTRIB, \
- brw->attribs.ATTRIB, \
- sizeof(struct STRUCT)); \
-} while (0)
-
-
-#define INSTALL(brw, ATTRIB, STATE) \
-do { \
- brw->attribs.ATTRIB = brw->metaops.attribs.ATTRIB; \
- brw->state.dirty.mesa |= STATE; \
-} while (0)
-
-#define RESTORE(brw, ATTRIB, STATE) \
-do { \
- brw->attribs.ATTRIB = &brw->intel.ctx.ATTRIB; \
- brw->state.dirty.mesa |= STATE; \
-} while (0)
-
-static void init_attribs( struct brw_context *brw )
-{
- DUP(brw, gl_colorbuffer_attrib, Color);
- DUP(brw, gl_depthbuffer_attrib, Depth);
- DUP(brw, gl_fog_attrib, Fog);
- DUP(brw, gl_hint_attrib, Hint);
- DUP(brw, gl_light_attrib, Light);
- DUP(brw, gl_line_attrib, Line);
- DUP(brw, gl_point_attrib, Point);
- DUP(brw, gl_polygon_attrib, Polygon);
- DUP(brw, gl_scissor_attrib, Scissor);
- DUP(brw, gl_stencil_attrib, Stencil);
- DUP(brw, gl_texture_attrib, Texture);
- DUP(brw, gl_transform_attrib, Transform);
- DUP(brw, gl_viewport_attrib, Viewport);
- DUP(brw, gl_vertex_program_state, VertexProgram);
- DUP(brw, gl_fragment_program_state, FragmentProgram);
-}
-
-static void install_attribs( struct brw_context *brw )
-{
- INSTALL(brw, Color, _NEW_COLOR);
- INSTALL(brw, Depth, _NEW_DEPTH);
- INSTALL(brw, Fog, _NEW_FOG);
- INSTALL(brw, Hint, _NEW_HINT);
- INSTALL(brw, Light, _NEW_LIGHT);
- INSTALL(brw, Line, _NEW_LINE);
- INSTALL(brw, Point, _NEW_POINT);
- INSTALL(brw, Polygon, _NEW_POLYGON);
- INSTALL(brw, Scissor, _NEW_SCISSOR);
- INSTALL(brw, Stencil, _NEW_STENCIL);
- INSTALL(brw, Texture, _NEW_TEXTURE);
- INSTALL(brw, Transform, _NEW_TRANSFORM);
- INSTALL(brw, Viewport, _NEW_VIEWPORT);
- INSTALL(brw, VertexProgram, _NEW_PROGRAM);
- INSTALL(brw, FragmentProgram, _NEW_PROGRAM);
-}
-
-static void restore_attribs( struct brw_context *brw )
-{
- RESTORE(brw, Color, _NEW_COLOR);
- RESTORE(brw, Depth, _NEW_DEPTH);
- RESTORE(brw, Fog, _NEW_FOG);
- RESTORE(brw, Hint, _NEW_HINT);
- RESTORE(brw, Light, _NEW_LIGHT);
- RESTORE(brw, Line, _NEW_LINE);
- RESTORE(brw, Point, _NEW_POINT);
- RESTORE(brw, Polygon, _NEW_POLYGON);
- RESTORE(brw, Scissor, _NEW_SCISSOR);
- RESTORE(brw, Stencil, _NEW_STENCIL);
- RESTORE(brw, Texture, _NEW_TEXTURE);
- RESTORE(brw, Transform, _NEW_TRANSFORM);
- RESTORE(brw, Viewport, _NEW_VIEWPORT);
- RESTORE(brw, VertexProgram, _NEW_PROGRAM);
- RESTORE(brw, FragmentProgram, _NEW_PROGRAM);
-}
-
-
-static const char *vp_prog =
- "!!ARBvp1.0\n"
- "MOV result.color, vertex.color;\n"
- "MOV result.position, vertex.position;\n"
- "END\n";
-
-static const char *fp_prog =
- "!!ARBfp1.0\n"
- "MOV result.color, fragment.color;\n"
- "END\n";
-
-static const char *fp_tex_prog =
- "!!ARBfp1.0\n"
- "TEMP a;\n"
- "ADD a, fragment.position, program.local[0];\n"
- "MUL a, a, program.local[1];\n"
- "TEX result.color, a, texture[0], 2D;\n"
- "MOV result.depth.z, fragment.position;\n"
- "END\n";
-
-/* Derived values of importance:
- *
- * FragmentProgram->_Current
- * VertexProgram->_Enabled
- * brw->vertex_program
- * DrawBuffer->_ColorDrawBufferIndexes[0]
- *
- *
- * More if drawpixels-through-texture is added.
- */
-static void init_metaops_state( struct brw_context *brw )
-{
- GLcontext *ctx = &brw->intel.ctx;
-
- brw->metaops.vbo = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB);
-
- ctx->Driver.BufferData(ctx,
- GL_ARRAY_BUFFER_ARB,
- 4096,
- NULL,
- GL_DYNAMIC_DRAW_ARB,
- brw->metaops.vbo);
-
- brw->metaops.fp = (struct gl_fragment_program *)
- ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 1 );
-
- brw->metaops.fp_tex = (struct gl_fragment_program *)
- ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 1 );
-
- brw->metaops.vp = (struct gl_vertex_program *)
- ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 1 );
-
- _mesa_parse_arb_fragment_program(ctx, GL_FRAGMENT_PROGRAM_ARB,
- fp_prog, strlen(fp_prog),
- brw->metaops.fp);
-
- _mesa_parse_arb_fragment_program(ctx, GL_FRAGMENT_PROGRAM_ARB,
- fp_tex_prog, strlen(fp_tex_prog),
- brw->metaops.fp_tex);
-
- _mesa_parse_arb_vertex_program(ctx, GL_VERTEX_PROGRAM_ARB,
- vp_prog, strlen(vp_prog),
- brw->metaops.vp);
-
- brw->metaops.attribs.VertexProgram->_Current = brw->metaops.vp;
- brw->metaops.attribs.VertexProgram->_Enabled = GL_TRUE;
-
- brw->metaops.attribs.FragmentProgram->_Current = brw->metaops.fp;
-}
-
-static void meta_flat_shade( struct intel_context *intel )
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- brw->metaops.attribs.Light->ShadeModel = GL_FLAT;
- brw->state.dirty.mesa |= _NEW_LIGHT;
-}
-
-
-static void meta_no_stencil_write( struct intel_context *intel )
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- brw->metaops.attribs.Stencil->Enabled = GL_FALSE;
- brw->metaops.attribs.Stencil->WriteMask[0] = GL_FALSE;
- brw->state.dirty.mesa |= _NEW_STENCIL;
-}
-
-static void meta_no_depth_write( struct intel_context *intel )
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- brw->metaops.attribs.Depth->Test = GL_FALSE;
- brw->metaops.attribs.Depth->Mask = GL_FALSE;
- brw->state.dirty.mesa |= _NEW_DEPTH;
-}
-
-
-static void meta_depth_replace( struct intel_context *intel )
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_TRUE )
- * ctx->Driver.DepthMask( ctx, GL_TRUE )
- */
- brw->metaops.attribs.Depth->Test = GL_TRUE;
- brw->metaops.attribs.Depth->Mask = GL_TRUE;
- brw->state.dirty.mesa |= _NEW_DEPTH;
-
- /* ctx->Driver.DepthFunc( ctx, GL_ALWAYS )
- */
- brw->metaops.attribs.Depth->Func = GL_ALWAYS;
-
- brw->state.dirty.mesa |= _NEW_DEPTH;
-}
-
-
-static void meta_stencil_replace( struct intel_context *intel,
- GLuint s_mask,
- GLuint s_clear)
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- brw->metaops.attribs.Stencil->Enabled = GL_TRUE;
- brw->metaops.attribs.Stencil->WriteMask[0] = s_mask;
- brw->metaops.attribs.Stencil->ValueMask[0] = 0xff;
- brw->metaops.attribs.Stencil->Ref[0] = s_clear;
- brw->metaops.attribs.Stencil->Function[0] = GL_ALWAYS;
- brw->metaops.attribs.Stencil->FailFunc[0] = GL_REPLACE;
- brw->metaops.attribs.Stencil->ZPassFunc[0] = GL_REPLACE;
- brw->metaops.attribs.Stencil->ZFailFunc[0] = GL_REPLACE;
- brw->state.dirty.mesa |= _NEW_STENCIL;
-}
-
-
-static void meta_color_mask( struct intel_context *intel, GLboolean state )
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- if (state)
- COPY_4V(brw->metaops.attribs.Color->ColorMask,
- brw->intel.ctx.Color.ColorMask);
- else
- ASSIGN_4V(brw->metaops.attribs.Color->ColorMask, 0, 0, 0, 0);
-
- brw->state.dirty.mesa |= _NEW_COLOR;
-}
-
-static void meta_no_texture( struct intel_context *intel )
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- brw->metaops.attribs.FragmentProgram->_Current = brw->metaops.fp;
-
- brw->metaops.attribs.Texture->CurrentUnit = 0;
- brw->metaops.attribs.Texture->_EnabledUnits = 0;
- brw->metaops.attribs.Texture->_EnabledCoordUnits = 0;
- brw->metaops.attribs.Texture->Unit[ 0 ].Enabled = 0;
- brw->metaops.attribs.Texture->Unit[ 0 ]._ReallyEnabled = 0;
-
- brw->state.dirty.mesa |= _NEW_TEXTURE | _NEW_PROGRAM;
-}
-
-static void meta_texture_blend_replace(struct intel_context *intel)
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- brw->metaops.attribs.Texture->CurrentUnit = 0;
- brw->metaops.attribs.Texture->_EnabledUnits = 1;
- brw->metaops.attribs.Texture->_EnabledCoordUnits = 1;
- brw->metaops.attribs.Texture->Unit[ 0 ].Enabled = TEXTURE_2D_BIT;
- brw->metaops.attribs.Texture->Unit[ 0 ]._ReallyEnabled = TEXTURE_2D_BIT;
- brw->metaops.attribs.Texture->Unit[ 0 ].Current2D =
- intel->frame_buffer_texobj;
- brw->metaops.attribs.Texture->Unit[ 0 ]._Current =
- intel->frame_buffer_texobj;
-
- brw->state.dirty.mesa |= _NEW_TEXTURE | _NEW_PROGRAM;
-}
-
-static void meta_import_pixel_state(struct intel_context *intel)
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- RESTORE(brw, Color, _NEW_COLOR);
- RESTORE(brw, Depth, _NEW_DEPTH);
- RESTORE(brw, Fog, _NEW_FOG);
- RESTORE(brw, Scissor, _NEW_SCISSOR);
- RESTORE(brw, Stencil, _NEW_STENCIL);
- RESTORE(brw, Texture, _NEW_TEXTURE);
- RESTORE(brw, FragmentProgram, _NEW_PROGRAM);
-}
-
-static void meta_frame_buffer_texture( struct intel_context *intel,
- GLint xoff, GLint yoff )
-{
- struct brw_context *brw = brw_context(&intel->ctx);
- struct intel_region *region = intel_drawbuf_region( intel );
-
- INSTALL(brw, FragmentProgram, _NEW_PROGRAM);
-
- brw->metaops.attribs.FragmentProgram->_Current = brw->metaops.fp_tex;
- /* This is unfortunate, but seems to be necessary, since later on we
- will end up calling _mesa_load_state_parameters to lookup the
- local params (below), and that will want to look in ctx.FragmentProgram
- instead of brw->attribs.FragmentProgram. */
- intel->ctx.FragmentProgram.Current = brw->metaops.fp_tex;
-
- brw->metaops.fp_tex->Base.LocalParams[ 0 ][ 0 ] = xoff;
- brw->metaops.fp_tex->Base.LocalParams[ 0 ][ 1 ] = yoff;
- brw->metaops.fp_tex->Base.LocalParams[ 0 ][ 2 ] = 0.0;
- brw->metaops.fp_tex->Base.LocalParams[ 0 ][ 3 ] = 0.0;
- brw->metaops.fp_tex->Base.LocalParams[ 1 ][ 0 ] =
- 1.0 / region->pitch;
- brw->metaops.fp_tex->Base.LocalParams[ 1 ][ 1 ] =
- -1.0 / region->height;
- brw->metaops.fp_tex->Base.LocalParams[ 1 ][ 2 ] = 0.0;
- brw->metaops.fp_tex->Base.LocalParams[ 1 ][ 3 ] = 1.0;
-
- brw->state.dirty.mesa |= _NEW_PROGRAM;
-}
-
-
-static void meta_draw_region( struct intel_context *intel,
- struct intel_region *draw_region,
- struct intel_region *depth_region )
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- if (!brw->metaops.saved_draw_region) {
- brw->metaops.saved_draw_region = brw->state.draw_regions[0];
- brw->metaops.saved_nr_draw_regions = brw->state.nr_draw_regions;
- brw->metaops.saved_depth_region = brw->state.depth_region;
- }
-
- brw->state.draw_regions[0] = draw_region;
- brw->state.nr_draw_regions = 1;
- brw->state.depth_region = depth_region;
-
- if (intel->frame_buffer_texobj != NULL)
- brw_FrameBufferTexDestroy(brw);
-
- if (draw_region)
- brw_FrameBufferTexInit(brw, draw_region);
-
- brw->state.dirty.mesa |= _NEW_BUFFERS;
-}
-
-
-static void meta_draw_quad(struct intel_context *intel,
- GLfloat x0, GLfloat x1,
- GLfloat y0, GLfloat y1,
- GLfloat z,
- GLuint color,
- GLfloat s0, GLfloat s1,
- GLfloat t0, GLfloat t1)
-{
- GLcontext *ctx = &intel->ctx;
- struct brw_context *brw = brw_context(&intel->ctx);
- struct gl_client_array pos_array;
- struct gl_client_array color_array;
- struct gl_client_array *attribs[VERT_ATTRIB_MAX];
- struct _mesa_prim prim[1];
- GLfloat pos[4][3];
-
- ctx->Driver.BufferData(ctx,
- GL_ARRAY_BUFFER_ARB,
- sizeof(pos) + sizeof(color),
- NULL,
- GL_DYNAMIC_DRAW_ARB,
- brw->metaops.vbo);
-
- pos[0][0] = x0;
- pos[0][1] = y0;
- pos[0][2] = z;
-
- pos[1][0] = x1;
- pos[1][1] = y0;
- pos[1][2] = z;
-
- pos[2][0] = x1;
- pos[2][1] = y1;
- pos[2][2] = z;
-
- pos[3][0] = x0;
- pos[3][1] = y1;
- pos[3][2] = z;
-
- ctx->Driver.BufferSubData(ctx,
- GL_ARRAY_BUFFER_ARB,
- 0,
- sizeof(pos),
- pos,
- brw->metaops.vbo);
-
- /* Convert incoming ARGB to required RGBA */
- /* Note this color is stored as GL_UNSIGNED_BYTE */
- color = (color & 0xff00ff00) | (((color >> 16) | (color << 16)) & 0xff00ff);
-
- ctx->Driver.BufferSubData(ctx,
- GL_ARRAY_BUFFER_ARB,
- sizeof(pos),
- sizeof(color),
- &color,
- brw->metaops.vbo);
-
- /* Ignoring texture coords.
- */
-
- memset(attribs, 0, VERT_ATTRIB_MAX * sizeof(*attribs));
-
- attribs[VERT_ATTRIB_POS] = &pos_array;
- attribs[VERT_ATTRIB_POS]->Ptr = 0;
- attribs[VERT_ATTRIB_POS]->Type = GL_FLOAT;
- attribs[VERT_ATTRIB_POS]->Enabled = 1;
- attribs[VERT_ATTRIB_POS]->Size = 3;
- attribs[VERT_ATTRIB_POS]->StrideB = 3 * sizeof(GLfloat);
- attribs[VERT_ATTRIB_POS]->Stride = 3 * sizeof(GLfloat);
- attribs[VERT_ATTRIB_POS]->_MaxElement = 4;
- attribs[VERT_ATTRIB_POS]->Normalized = 0;
- attribs[VERT_ATTRIB_POS]->BufferObj = brw->metaops.vbo;
-
- attribs[VERT_ATTRIB_COLOR0] = &color_array;
- attribs[VERT_ATTRIB_COLOR0]->Ptr = (const GLubyte *)sizeof(pos);
- attribs[VERT_ATTRIB_COLOR0]->Type = GL_UNSIGNED_BYTE;
- attribs[VERT_ATTRIB_COLOR0]->Enabled = 1;
- attribs[VERT_ATTRIB_COLOR0]->Size = 4;
- attribs[VERT_ATTRIB_COLOR0]->StrideB = 0;
- attribs[VERT_ATTRIB_COLOR0]->Stride = 0;
- attribs[VERT_ATTRIB_COLOR0]->_MaxElement = 1;
- attribs[VERT_ATTRIB_COLOR0]->Normalized = 1;
- attribs[VERT_ATTRIB_COLOR0]->BufferObj = brw->metaops.vbo;
-
- /* Just ignoring texture coordinates for now.
- */
-
- memset(prim, 0, sizeof(*prim));
-
- prim[0].mode = GL_TRIANGLE_FAN;
- prim[0].begin = 1;
- prim[0].end = 1;
- prim[0].weak = 0;
- prim[0].pad = 0;
- prim[0].start = 0;
- prim[0].count = 4;
-
- brw_draw_prims(&brw->intel.ctx,
- (const struct gl_client_array **)attribs,
- prim, 1,
- NULL,
- 0,
- 3 );
-}
-
-
-static void install_meta_state( struct intel_context *intel )
-{
- GLcontext *ctx = &intel->ctx;
- struct brw_context *brw = brw_context(ctx);
- GLuint i;
-
- if (!brw->metaops.vbo) {
- init_metaops_state(brw);
- }
-
- install_attribs(brw);
-
- meta_no_texture(&brw->intel);
- meta_flat_shade(&brw->intel);
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- brw->metaops.restore_draw_buffers[i]
- = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
- }
- brw->metaops.restore_num_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers;
-
- brw->metaops.restore_fp = ctx->FragmentProgram.Current;
-
- /* This works without adjusting refcounts. Fix later?
- */
- brw->metaops.saved_draw_region = brw->state.draw_regions[0];
- brw->metaops.saved_nr_draw_regions = brw->state.nr_draw_regions;
- brw->metaops.saved_depth_region = brw->state.depth_region;
- brw->metaops.active = 1;
-
- brw->state.dirty.brw |= BRW_NEW_METAOPS;
-}
-
-static void leave_meta_state( struct intel_context *intel )
-{
- GLcontext *ctx = &intel->ctx;
- struct brw_context *brw = brw_context(ctx);
- GLuint i;
-
- restore_attribs(brw);
-
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- ctx->DrawBuffer->_ColorDrawBufferIndexes[i]
- = brw->metaops.restore_draw_buffers[i];
- }
- ctx->DrawBuffer->_NumColorDrawBuffers = brw->metaops.restore_num_draw_buffers;
-
- ctx->FragmentProgram.Current = brw->metaops.restore_fp;
-
- brw->state.draw_regions[0] = brw->metaops.saved_draw_region;
- brw->state.nr_draw_regions = brw->metaops.saved_nr_draw_regions;
- brw->state.depth_region = brw->metaops.saved_depth_region;
- brw->metaops.saved_draw_region = NULL;
- brw->metaops.saved_depth_region = NULL;
- brw->metaops.active = 0;
-
- brw->state.dirty.mesa |= _NEW_BUFFERS;
- brw->state.dirty.brw |= BRW_NEW_METAOPS;
-}
-
-
-
-void brw_init_metaops( struct brw_context *brw )
-{
- init_attribs(brw);
-
-
- brw->intel.vtbl.install_meta_state = install_meta_state;
- brw->intel.vtbl.leave_meta_state = leave_meta_state;
- brw->intel.vtbl.meta_no_depth_write = meta_no_depth_write;
- brw->intel.vtbl.meta_no_stencil_write = meta_no_stencil_write;
- brw->intel.vtbl.meta_stencil_replace = meta_stencil_replace;
- brw->intel.vtbl.meta_depth_replace = meta_depth_replace;
- brw->intel.vtbl.meta_color_mask = meta_color_mask;
- brw->intel.vtbl.meta_no_texture = meta_no_texture;
- brw->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state;
- brw->intel.vtbl.meta_frame_buffer_texture = meta_frame_buffer_texture;
- brw->intel.vtbl.meta_draw_region = meta_draw_region;
- brw->intel.vtbl.meta_draw_quad = meta_draw_quad;
- brw->intel.vtbl.meta_texture_blend_replace = meta_texture_blend_replace;
-/* brw->intel.vtbl.meta_tex_rect_source = meta_tex_rect_source; */
-/* brw->intel.vtbl.meta_draw_format = set_draw_format; */
-}
-
-void brw_destroy_metaops( struct brw_context *brw )
-{
- GLcontext *ctx = &brw->intel.ctx;
-
- if (brw->metaops.vbo)
- ctx->Driver.DeleteBuffer( ctx, brw->metaops.vbo );
-
-/* ctx->Driver.DeleteProgram( ctx, brw->metaops.fp ); */
-/* ctx->Driver.DeleteProgram( ctx, brw->metaops.fp_tex ); */
-/* ctx->Driver.DeleteProgram( ctx, brw->metaops.vp ); */
-}
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index 627705fa9b..ea71857548 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -48,15 +48,16 @@
static void upload_blend_constant_color(struct brw_context *brw)
{
+ GLcontext *ctx = &brw->intel.ctx;
struct brw_blend_constant_color bcc;
memset(&bcc, 0, sizeof(bcc));
bcc.header.opcode = CMD_BLEND_CONSTANT_COLOR;
bcc.header.length = sizeof(bcc)/4-2;
- bcc.blend_constant_color[0] = brw->attribs.Color->BlendColor[0];
- bcc.blend_constant_color[1] = brw->attribs.Color->BlendColor[1];
- bcc.blend_constant_color[2] = brw->attribs.Color->BlendColor[2];
- bcc.blend_constant_color[3] = brw->attribs.Color->BlendColor[3];
+ 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);
}
@@ -100,6 +101,7 @@ const struct brw_tracked_state brw_drawing_rect = {
static void prepare_binding_table_pointers(struct brw_context *brw)
{
+ brw_add_validated_bo(brw, brw->vs.bind_bo);
brw_add_validated_bo(brw, brw->wm.bind_bo);
}
@@ -116,13 +118,14 @@ static void upload_binding_table_pointers(struct brw_context *brw)
BEGIN_BATCH(6, IGNORE_CLIPRECTS);
OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | (6 - 2));
- OUT_BATCH(0); /* vs */
+ if (brw->vs.bind_bo != NULL)
+ OUT_RELOC(brw->vs.bind_bo, I915_GEM_DOMAIN_SAMPLER, 0, 0); /* vs */
+ else
+ OUT_BATCH(0);
OUT_BATCH(0); /* gs */
OUT_BATCH(0); /* clip */
OUT_BATCH(0); /* sf */
- OUT_RELOC(brw->wm.bind_bo,
- I915_GEM_DOMAIN_SAMPLER, 0,
- 0);
+ OUT_RELOC(brw->wm.bind_bo, I915_GEM_DOMAIN_SAMPLER, 0, 0); /* wm/ps */
ADVANCE_BATCH();
}
@@ -154,10 +157,7 @@ static void upload_pipelined_state_pointers(struct brw_context *brw )
OUT_RELOC(brw->gs.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
else
OUT_BATCH(0);
- if (!brw->metaops.active)
- OUT_RELOC(brw->clip.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
- else
- OUT_BATCH(0);
+ 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, 0);
@@ -172,6 +172,7 @@ static void prepare_psp_urb_cbs(struct brw_context *brw)
brw_add_validated_bo(brw, brw->vs.state_bo);
brw_add_validated_bo(brw, brw->gs.state_bo);
brw_add_validated_bo(brw, brw->clip.state_bo);
+ brw_add_validated_bo(brw, brw->sf.state_bo);
brw_add_validated_bo(brw, brw->wm.state_bo);
brw_add_validated_bo(brw, brw->cc.state_bo);
}
@@ -180,13 +181,13 @@ static void upload_psp_urb_cbs(struct brw_context *brw )
{
upload_pipelined_state_pointers(brw);
brw_upload_urb_fence(brw);
- brw_upload_constant_buffer_state(brw);
+ brw_upload_cs_urb_state(brw);
}
const struct brw_tracked_state brw_psp_urb_cbs = {
.dirty = {
.mesa = 0,
- .brw = BRW_NEW_URB_FENCE | BRW_NEW_METAOPS | BRW_NEW_BATCH,
+ .brw = BRW_NEW_URB_FENCE | BRW_NEW_BATCH,
.cache = (CACHE_NEW_VS_UNIT |
CACHE_NEW_GS_UNIT |
CACHE_NEW_GS_PROG |
@@ -211,7 +212,7 @@ static void emit_depthbuffer(struct brw_context *brw)
{
struct intel_context *intel = &brw->intel;
struct intel_region *region = brw->state.depth_region;
- unsigned int len = BRW_IS_G4X(brw) ? 6 : 5;
+ unsigned int len = (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw)) ? 6 : 5;
if (region == NULL) {
BEGIN_BATCH(len, IGNORE_CLIPRECTS);
@@ -222,7 +223,7 @@ static void emit_depthbuffer(struct brw_context *brw)
OUT_BATCH(0);
OUT_BATCH(0);
- if (BRW_IS_G4X(brw))
+ if (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw))
OUT_BATCH(0);
ADVANCE_BATCH();
@@ -244,6 +245,8 @@ static void emit_depthbuffer(struct brw_context *brw)
return;
}
+ assert(region->tiling != I915_TILING_X);
+
BEGIN_BATCH(len, IGNORE_CLIPRECTS);
OUT_BATCH(CMD_DEPTH_BUFFER << 16 | (len - 2));
OUT_BATCH(((region->pitch * region->cpp) - 1) |
@@ -259,7 +262,7 @@ static void emit_depthbuffer(struct brw_context *brw)
((region->height - 1) << 19));
OUT_BATCH(0);
- if (BRW_IS_G4X(brw))
+ if (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw))
OUT_BATCH(0);
ADVANCE_BATCH();
@@ -284,6 +287,7 @@ const struct brw_tracked_state brw_depthbuffer = {
static void upload_polygon_stipple(struct brw_context *brw)
{
+ GLcontext *ctx = &brw->intel.ctx;
struct brw_polygon_stipple bps;
GLuint i;
@@ -291,8 +295,21 @@ static void upload_polygon_stipple(struct brw_context *brw)
bps.header.opcode = CMD_POLY_STIPPLE_PATTERN;
bps.header.length = sizeof(bps)/4-2;
- for (i = 0; i < 32; i++)
- bps.stipple[i] = brw->attribs.PolygonStipple[31 - i]; /* invert */
+ /* Polygon stipple is provided in OpenGL order, i.e. bottom
+ * row first. If we're rendering to a window (i.e. the
+ * default frame buffer object, 0), then we need to invert
+ * it to match our pixel layout. But if we're rendering
+ * to a FBO (i.e. any named frame buffer object), we *don't*
+ * need to invert - we already match the layout.
+ */
+ if (ctx->DrawBuffer->Name == 0) {
+ for (i = 0; i < 32; i++)
+ bps.stipple[i] = ctx->PolygonStipple[31 - i]; /* invert */
+ }
+ else {
+ for (i = 0; i < 32; i++)
+ bps.stipple[i] = ctx->PolygonStipple[i]; /* don't invert */
+ }
BRW_CACHED_BATCH_STRUCT(brw, &bps);
}
@@ -320,8 +337,22 @@ static void upload_polygon_stipple_offset(struct brw_context *brw)
bpso.header.opcode = CMD_POLY_STIPPLE_OFFSET;
bpso.header.length = sizeof(bpso)/4-2;
- bpso.bits0.x_offset = (32 - (dPriv->x & 31)) & 31;
- bpso.bits0.y_offset = (32 - ((dPriv->y + dPriv->h) & 31)) & 31;
+ /* 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
+ * pixel coordinate system, and our offset must be matched
+ * to the window position. If we're drawing to a FBO
+ * (ctx->DrawBuffer->Name != 0), then our native pixel coordinate
+ * system works just fine, and there's no window system to
+ * worry about.
+ */
+ if (brw->intel.ctx.DrawBuffer->Name == 0) {
+ bpso.bits0.x_offset = (32 - (dPriv->x & 31)) & 31;
+ bpso.bits0.y_offset = (32 - ((dPriv->y + dPriv->h) & 31)) & 31;
+ }
+ else {
+ bpso.bits0.y_offset = 0;
+ bpso.bits0.x_offset = 0;
+ }
BRW_CACHED_BATCH_STRUCT(brw, &bpso);
}
@@ -344,7 +375,7 @@ static void upload_aa_line_parameters(struct brw_context *brw)
{
struct brw_aa_line_parameters balp;
- if (!BRW_IS_G4X(brw))
+ if (BRW_IS_965(brw))
return;
/* use legacy aa line coverage computation */
@@ -370,6 +401,7 @@ const struct brw_tracked_state brw_aa_line_parameters = {
static void upload_line_stipple(struct brw_context *brw)
{
+ GLcontext *ctx = &brw->intel.ctx;
struct brw_line_stipple bls;
GLfloat tmp;
GLint tmpi;
@@ -378,10 +410,10 @@ static void upload_line_stipple(struct brw_context *brw)
bls.header.opcode = CMD_LINE_STIPPLE_PATTERN;
bls.header.length = sizeof(bls)/4 - 2;
- bls.bits0.pattern = brw->attribs.Line->StipplePattern;
- bls.bits1.repeat_count = brw->attribs.Line->StippleFactor;
+ bls.bits0.pattern = ctx->Line.StipplePattern;
+ bls.bits1.repeat_count = ctx->Line.StippleFactor;
- tmp = 1.0 / (GLfloat) brw->attribs.Line->StippleFactor;
+ tmp = 1.0 / (GLfloat) ctx->Line.StippleFactor;
tmpi = tmp * (1<<13);
@@ -480,14 +512,27 @@ static void upload_state_base_address( struct brw_context *brw )
/* Output the structure (brw_state_base_address) directly to the
* batchbuffer, so we can emit relocations inline.
*/
- BEGIN_BATCH(6, IGNORE_CLIPRECTS);
- OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2));
- OUT_BATCH(1); /* General state base address */
- OUT_BATCH(1); /* Surface state base address */
- OUT_BATCH(1); /* Indirect object base address */
- OUT_BATCH(1); /* General state upper bound */
- OUT_BATCH(1); /* Indirect object upper bound */
- ADVANCE_BATCH();
+ if (BRW_IS_IGDNG(brw)) {
+ BEGIN_BATCH(8, IGNORE_CLIPRECTS);
+ OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (8 - 2));
+ OUT_BATCH(1); /* General state base address */
+ OUT_BATCH(1); /* Surface state base address */
+ OUT_BATCH(1); /* Indirect object base address */
+ OUT_BATCH(1); /* Instruction base address */
+ OUT_BATCH(1); /* General state upper bound */
+ OUT_BATCH(1); /* Indirect object upper bound */
+ OUT_BATCH(1); /* Instruction access upper bound */
+ ADVANCE_BATCH();
+ } else {
+ BEGIN_BATCH(6, IGNORE_CLIPRECTS);
+ OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2));
+ OUT_BATCH(1); /* General state base address */
+ OUT_BATCH(1); /* Surface state base address */
+ OUT_BATCH(1); /* Indirect object base address */
+ OUT_BATCH(1); /* General state upper bound */
+ OUT_BATCH(1); /* Indirect object upper bound */
+ ADVANCE_BATCH();
+ }
}
const struct brw_tracked_state brw_state_base_address = {
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index 0c86911044..bac69187c1 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -38,6 +38,7 @@
#include "brw_context.h"
#include "brw_util.h"
+#include "brw_wm.h"
static void brwBindProgram( GLcontext *ctx,
GLenum target,
@@ -94,7 +95,12 @@ static struct gl_program *brwNewProgram( GLcontext *ctx,
static void brwDeleteProgram( GLcontext *ctx,
struct gl_program *prog )
{
-
+ if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
+ struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
+ struct brw_fragment_program *brw_fprog = brw_fragment_program(fprog);
+ dri_bo_unreference(brw_fprog->const_buffer);
+ }
+
_mesa_delete_program( ctx, prog );
}
@@ -110,30 +116,36 @@ static void brwProgramStringNotify( GLcontext *ctx,
GLenum target,
struct gl_program *prog )
{
+ struct brw_context *brw = brw_context(ctx);
+
if (target == GL_FRAGMENT_PROGRAM_ARB) {
struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
- struct brw_context *brw = brw_context(ctx);
- struct brw_fragment_program *p = (struct brw_fragment_program *)prog;
- struct brw_fragment_program *fp = (struct brw_fragment_program *)brw->fragment_program;
+ struct brw_fragment_program *newFP = brw_fragment_program(fprog);
+ const struct brw_fragment_program *curFP =
+ brw_fragment_program_const(brw->fragment_program);
+
if (fprog->FogOption) {
_mesa_append_fog_code(ctx, fprog);
fprog->FogOption = GL_NONE;
}
- if (p == fp)
+ if (newFP == curFP)
brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM;
- p->id = brw->program_id++;
+ newFP->id = brw->program_id++;
+ newFP->isGLSL = brw_wm_is_glsl(fprog);
}
else if (target == GL_VERTEX_PROGRAM_ARB) {
- struct brw_context *brw = brw_context(ctx);
- struct brw_vertex_program *p = (struct brw_vertex_program *)prog;
- struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program;
- if (p == vp)
+ struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
+ struct brw_vertex_program *newVP = brw_vertex_program(vprog);
+ const struct brw_vertex_program *curVP =
+ brw_vertex_program_const(brw->vertex_program);
+
+ if (newVP == curVP)
brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM;
- if (p->program.IsPositionInvariant) {
- _mesa_insert_mvp_code(ctx, &p->program);
+ if (newVP->program.IsPositionInvariant) {
+ _mesa_insert_mvp_code(ctx, &newVP->program);
}
- p->id = brw->program_id++;
+ newVP->id = brw->program_id++;
/* Also tell tnl about it:
*/
diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c
index cb9169e2ee..a195bc32b0 100644
--- a/src/mesa/drivers/dri/i965/brw_queryobj.c
+++ b/src/mesa/drivers/dri/i965/brw_queryobj.c
@@ -146,17 +146,12 @@ static void brw_wait_query(GLcontext *ctx, struct gl_query_object *q)
static void brw_check_query(GLcontext *ctx, struct gl_query_object *q)
{
- /* XXX: Need to expose dri_bo_is_idle from bufmgr. */
-#if 0
struct brw_query_object *query = (struct brw_query_object *)q;
- if (dri_bo_is_idle(query->bo)) {
+ if (query->bo == NULL || !drm_intel_bo_busy(query->bo)) {
brw_queryobj_get_results(query);
query->Base.Ready = GL_TRUE;
}
-#else
- brw_wait_query(ctx, q);
-#endif
}
/** Called to set up the query BO and account for its aperture space */
diff --git a/src/mesa/drivers/dri/i965/brw_sf.c b/src/mesa/drivers/dri/i965/brw_sf.c
index 1a11d54621..e1c2c7777b 100644
--- a/src/mesa/drivers/dri/i965/brw_sf.c
+++ b/src/mesa/drivers/dri/i965/brw_sf.c
@@ -46,6 +46,7 @@
static void compile_sf_prog( struct brw_context *brw,
struct brw_sf_prog_key *key )
{
+ GLcontext *ctx = &brw->intel.ctx;
struct brw_sf_compile c;
const GLuint *program;
GLuint program_size;
@@ -74,7 +75,7 @@ static void compile_sf_prog( struct brw_context *brw,
c.idx_to_attr[idx] = i;
if (i >= VERT_RESULT_TEX0 && i <= VERT_RESULT_TEX7) {
c.point_attrs[i].CoordReplace =
- brw->attribs.Point->CoordReplace[i - VERT_RESULT_TEX0];
+ ctx->Point.CoordReplace[i - VERT_RESULT_TEX0];
}
else {
c.point_attrs[i].CoordReplace = GL_FALSE;
@@ -128,6 +129,7 @@ static void compile_sf_prog( struct brw_context *brw,
*/
static void upload_sf_prog(struct brw_context *brw)
{
+ GLcontext *ctx = &brw->intel.ctx;
struct brw_sf_prog_key key;
memset(&key, 0, sizeof(key));
@@ -158,15 +160,24 @@ static void upload_sf_prog(struct brw_context *brw)
break;
}
- key.do_point_sprite = brw->attribs.Point->PointSprite;
- key.SpriteOrigin = brw->attribs.Point->SpriteOrigin;
+ key.do_point_sprite = ctx->Point.PointSprite;
+ key.SpriteOrigin = ctx->Point.SpriteOrigin;
/* _NEW_LIGHT */
- key.do_flat_shading = (brw->attribs.Light->ShadeModel == GL_FLAT);
- key.do_twoside_color = (brw->attribs.Light->Enabled && brw->attribs.Light->Model.TwoSide);
+ key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);
+ key.do_twoside_color = (ctx->Light.Enabled && ctx->Light.Model.TwoSide);
+
+ /* _NEW_HINT */
+ key.linear_color = (ctx->Hint.PerspectiveCorrection == GL_FASTEST);
/* _NEW_POLYGON */
- if (key.do_twoside_color)
- key.frontface_ccw = (brw->attribs.Polygon->FrontFace == GL_CCW);
+ if (key.do_twoside_color) {
+ /* If we're rendering to a FBO, we have to invert the polygon
+ * face orientation, just as we invert the viewport in
+ * sf_unit_create_from_key(). ctx->DrawBuffer->Name will be
+ * nonzero if we're rendering to such an FBO.
+ */
+ key.frontface_ccw = (ctx->Polygon.FrontFace == GL_CCW) ^ (ctx->DrawBuffer->Name != 0);
+ }
dri_bo_unreference(brw->sf.prog_bo);
brw->sf.prog_bo = brw_search_cache(&brw->cache, BRW_SF_PROG,
@@ -180,7 +191,7 @@ static void upload_sf_prog(struct brw_context *brw)
const struct brw_tracked_state brw_sf_prog = {
.dirty = {
- .mesa = (_NEW_LIGHT|_NEW_POLYGON|_NEW_POINT),
+ .mesa = (_NEW_HINT | _NEW_LIGHT | _NEW_POLYGON | _NEW_POINT),
.brw = (BRW_NEW_REDUCED_PRIMITIVE),
.cache = CACHE_NEW_VS_PROG
},
diff --git a/src/mesa/drivers/dri/i965/brw_sf.h b/src/mesa/drivers/dri/i965/brw_sf.h
index 1c0fb70fe0..6426b6df9f 100644
--- a/src/mesa/drivers/dri/i965/brw_sf.h
+++ b/src/mesa/drivers/dri/i965/brw_sf.h
@@ -51,7 +51,8 @@ struct brw_sf_prog_key {
GLuint do_flat_shading:1;
GLuint frontface_ccw:1;
GLuint do_point_sprite:1;
- GLuint pad:10;
+ GLuint linear_color:1; /**< linear interp vs. perspective interp */
+ GLuint pad:25;
GLenum SpriteOrigin;
};
diff --git a/src/mesa/drivers/dri/i965/brw_sf_emit.c b/src/mesa/drivers/dri/i965/brw_sf_emit.c
index ffdb0ae6df..ca8f97f9f9 100644
--- a/src/mesa/drivers/dri/i965/brw_sf_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_sf_emit.c
@@ -59,37 +59,6 @@ static GLboolean have_attr(struct brw_sf_compile *c,
return (c->key.attrs & (1<<attr)) ? 1 : 0;
}
-/**
- * Sets VERT_RESULT_FOGC.Y for gl_FrontFacing
- *
- * This is currently executed if the fragment program uses VERT_RESULT_FOGC
- * at all, but this could be eliminated with a scan of the FP contents.
- */
-static void
-do_front_facing( struct brw_sf_compile *c )
-{
- struct brw_compile *p = &c->func;
- int i;
-
- if (!have_attr(c, VERT_RESULT_FOGC))
- return;
-
- brw_push_insn_state(p);
- brw_CMP(p, brw_null_reg(),
- c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L,
- c->det, brw_imm_f(0));
- brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- for (i = 0; i < 3; i++) {
- struct brw_reg fogc = get_vert_attr(c, c->vert[i],FRAG_ATTRIB_FOGC);
- brw_MOV(p, get_element(fogc, 1), brw_imm_f(0));
- brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
- brw_MOV(p, get_element(fogc, 1), brw_imm_f(1));
- brw_set_predicate_control(p, BRW_PREDICATE_NONE);
- }
- brw_pop_insn_state(p);
-}
-
-
/***********************************************************************
* Twoside lighting
*/
@@ -182,6 +151,8 @@ static void do_flatshade_triangle( struct brw_sf_compile *c )
struct brw_compile *p = &c->func;
struct brw_reg ip = brw_ip_reg();
GLuint nr = brw_count_bits(c->key.attrs & VERT_RESULT_COLOR_BITS);
+ GLuint jmpi = 1;
+
if (!nr)
return;
@@ -190,18 +161,21 @@ static void do_flatshade_triangle( struct brw_sf_compile *c )
if (c->key.primitive == SF_UNFILLED_TRIS)
return;
+ if (BRW_IS_IGDNG(p->brw))
+ jmpi = 2;
+
brw_push_insn_state(p);
- brw_MUL(p, c->pv, c->pv, brw_imm_ud(nr*2+1));
+ brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr*2+1)));
brw_JMPI(p, ip, ip, c->pv);
copy_colors(c, c->vert[1], c->vert[0]);
copy_colors(c, c->vert[2], c->vert[0]);
- brw_JMPI(p, ip, ip, brw_imm_ud(nr*4+1));
+ brw_JMPI(p, ip, ip, brw_imm_d(jmpi*(nr*4+1)));
copy_colors(c, c->vert[0], c->vert[1]);
copy_colors(c, c->vert[2], c->vert[1]);
- brw_JMPI(p, ip, ip, brw_imm_ud(nr*2));
+ brw_JMPI(p, ip, ip, brw_imm_d(jmpi*nr*2));
copy_colors(c, c->vert[0], c->vert[2]);
copy_colors(c, c->vert[1], c->vert[2]);
@@ -215,7 +189,8 @@ static void do_flatshade_line( struct brw_sf_compile *c )
struct brw_compile *p = &c->func;
struct brw_reg ip = brw_ip_reg();
GLuint nr = brw_count_bits(c->key.attrs & VERT_RESULT_COLOR_BITS);
-
+ GLuint jmpi = 1;
+
if (!nr)
return;
@@ -224,13 +199,16 @@ static void do_flatshade_line( struct brw_sf_compile *c )
if (c->key.primitive == SF_UNFILLED_TRIS)
return;
+ if (BRW_IS_IGDNG(p->brw))
+ jmpi = 2;
+
brw_push_insn_state(p);
- brw_MUL(p, c->pv, c->pv, brw_imm_ud(nr+1));
+ brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr+1)));
brw_JMPI(p, ip, ip, c->pv);
copy_colors(c, c->vert[1], c->vert[0]);
- brw_JMPI(p, ip, ip, brw_imm_ud(nr));
+ brw_JMPI(p, ip, ip, brw_imm_ud(jmpi*nr));
copy_colors(c, c->vert[0], c->vert[1]);
brw_pop_insn_state(p);
@@ -249,7 +227,7 @@ static void alloc_regs( struct brw_sf_compile *c )
/* Values computed by fixed function unit:
*/
- c->pv = retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_UD);
+ c->pv = retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_D);
c->det = brw_vec1_grf(1, 2);
c->dx0 = brw_vec1_grf(1, 3);
c->dx2 = brw_vec1_grf(1, 4);
@@ -326,9 +304,6 @@ static void invert_det( struct brw_sf_compile *c)
}
-#define NON_PERPECTIVE_ATTRS (FRAG_BIT_WPOS | \
- FRAG_BIT_COL0 | \
- FRAG_BIT_COL1)
static GLboolean calculate_masks( struct brw_sf_compile *c,
GLuint reg,
@@ -337,9 +312,16 @@ static GLboolean calculate_masks( struct brw_sf_compile *c,
GLushort *pc_linear)
{
GLboolean is_last_attr = (reg == c->nr_setup_regs - 1);
- GLuint persp_mask = c->key.attrs & ~NON_PERPECTIVE_ATTRS;
+ GLuint persp_mask;
GLuint linear_mask;
+ if (c->key.do_flat_shading || c->key.linear_color)
+ persp_mask = c->key.attrs & ~(FRAG_BIT_WPOS |
+ FRAG_BIT_COL0 |
+ FRAG_BIT_COL1);
+ else
+ persp_mask = c->key.attrs & ~(FRAG_BIT_WPOS);
+
if (c->key.do_flat_shading)
linear_mask = c->key.attrs & ~(FRAG_BIT_COL0|FRAG_BIT_COL1);
else
@@ -384,7 +366,6 @@ void brw_emit_tri_setup( struct brw_sf_compile *c, GLboolean allocate)
invert_det(c);
copy_z_inv_w(c);
- do_front_facing(c);
if (c->key.do_twoside_color)
do_twoside_color(c);
@@ -706,7 +687,7 @@ void brw_emit_anyprim_setup( struct brw_sf_compile *c )
(1<<_3DPRIM_POLYGON) |
(1<<_3DPRIM_RECTLIST) |
(1<<_3DPRIM_TRIFAN_NOSTIPPLE)));
- jmp = brw_JMPI(p, ip, ip, brw_imm_w(0));
+ jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
{
saveflag = p->flag_value;
brw_push_insn_state(p);
@@ -727,7 +708,7 @@ void brw_emit_anyprim_setup( struct brw_sf_compile *c )
(1<<_3DPRIM_LINESTRIP_CONT) |
(1<<_3DPRIM_LINESTRIP_BF) |
(1<<_3DPRIM_LINESTRIP_CONT_BF)));
- jmp = brw_JMPI(p, ip, ip, brw_imm_w(0));
+ jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
{
saveflag = p->flag_value;
brw_push_insn_state(p);
@@ -740,7 +721,7 @@ void brw_emit_anyprim_setup( struct brw_sf_compile *c )
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
brw_AND(p, v1_null_ud, payload_attr, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE));
- jmp = brw_JMPI(p, ip, ip, brw_imm_w(0));
+ jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
{
saveflag = p->flag_value;
brw_push_insn_state(p);
diff --git a/src/mesa/drivers/dri/i965/brw_sf_state.c b/src/mesa/drivers/dri/i965/brw_sf_state.c
index 242b7047a1..bc0f076073 100644
--- a/src/mesa/drivers/dri/i965/brw_sf_state.c
+++ b/src/mesa/drivers/dri/i965/brw_sf_state.c
@@ -43,10 +43,12 @@ static void upload_sf_vp(struct brw_context *brw)
const GLfloat depth_scale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
struct brw_sf_viewport sfv;
GLfloat y_scale, y_bias;
+ const GLboolean render_to_fbo = (ctx->DrawBuffer->Name != 0);
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
memset(&sfv, 0, sizeof(sfv));
- if (intel_rendering_to_texture(ctx)) {
+ if (render_to_fbo) {
y_scale = 1.0;
y_bias = 0;
}
@@ -55,27 +57,18 @@ static void upload_sf_vp(struct brw_context *brw)
y_bias = ctx->DrawBuffer->Height;
}
- /* _NEW_VIEWPORT, BRW_NEW_METAOPS */
+ /* _NEW_VIEWPORT */
- if (!brw->metaops.active) {
- const GLfloat *v = ctx->Viewport._WindowMap.m;
+ sfv.viewport.m00 = v[MAT_SX];
+ sfv.viewport.m11 = v[MAT_SY] * y_scale;
+ sfv.viewport.m22 = v[MAT_SZ] * depth_scale;
+ sfv.viewport.m30 = v[MAT_TX];
+ sfv.viewport.m31 = v[MAT_TY] * y_scale + y_bias;
+ sfv.viewport.m32 = v[MAT_TZ] * depth_scale;
- sfv.viewport.m00 = v[MAT_SX];
- sfv.viewport.m11 = v[MAT_SY] * y_scale;
- sfv.viewport.m22 = v[MAT_SZ] * depth_scale;
- sfv.viewport.m30 = v[MAT_TX];
- sfv.viewport.m31 = v[MAT_TY] * y_scale + y_bias;
- sfv.viewport.m32 = v[MAT_TZ] * depth_scale;
- } else {
- sfv.viewport.m00 = 1;
- sfv.viewport.m11 = - 1;
- sfv.viewport.m22 = 1;
- sfv.viewport.m30 = 0;
- sfv.viewport.m31 = ctx->DrawBuffer->Height;
- sfv.viewport.m32 = 0;
- }
-
- /* _NEW_SCISSOR */
+ /* _NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT
+ * for DrawBuffer->_[XY]{min,max}
+ */
/* The scissor only needs to handle the intersection of drawable and
* scissor rect. Clipping to the boundaries of static shared buffers
@@ -84,10 +77,20 @@ static void upload_sf_vp(struct brw_context *brw)
* Note that the hardware's coordinates are inclusive, while Mesa's min is
* inclusive but max is exclusive.
*/
- sfv.scissor.xmin = ctx->DrawBuffer->_Xmin;
- sfv.scissor.xmax = ctx->DrawBuffer->_Xmax - 1;
- sfv.scissor.ymin = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax;
- sfv.scissor.ymax = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin - 1;
+ if (render_to_fbo) {
+ /* texmemory: Y=0=bottom */
+ sfv.scissor.xmin = ctx->DrawBuffer->_Xmin;
+ sfv.scissor.xmax = ctx->DrawBuffer->_Xmax - 1;
+ sfv.scissor.ymin = ctx->DrawBuffer->_Ymin;
+ sfv.scissor.ymax = ctx->DrawBuffer->_Ymax - 1;
+ }
+ else {
+ /* memory: Y=0=top */
+ sfv.scissor.xmin = ctx->DrawBuffer->_Xmin;
+ sfv.scissor.xmax = ctx->DrawBuffer->_Xmax - 1;
+ sfv.scissor.ymin = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax;
+ sfv.scissor.ymax = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin - 1;
+ }
dri_bo_unreference(brw->sf.vp_bo);
brw->sf.vp_bo = brw_cache_data( &brw->cache, BRW_SF_VP, &sfv, NULL, 0 );
@@ -96,8 +99,9 @@ static void upload_sf_vp(struct brw_context *brw)
const struct brw_tracked_state brw_sf_vp = {
.dirty = {
.mesa = (_NEW_VIEWPORT |
- _NEW_SCISSOR),
- .brw = BRW_NEW_METAOPS,
+ _NEW_SCISSOR |
+ _NEW_BUFFERS),
+ .brw = 0,
.cache = 0
},
.prepare = upload_sf_vp
@@ -109,16 +113,20 @@ struct brw_sf_unit_key {
unsigned int nr_urb_entries, urb_size, sfsize;
- GLenum front_face, cull_face;
- GLboolean scissor, line_smooth, point_sprite, point_attenuated;
+ GLenum front_face, cull_face, provoking_vertex;
+ unsigned scissor:1;
+ unsigned line_smooth:1;
+ unsigned point_sprite:1;
+ unsigned point_attenuated:1;
+ unsigned render_to_fbo:1;
float line_width;
float point_size;
- GLboolean render_to_texture;
};
static void
sf_unit_populate_key(struct brw_context *brw, struct brw_sf_unit_key *key)
{
+ GLcontext *ctx = &brw->intel.ctx;
memset(key, 0, sizeof(*key));
/* CACHE_NEW_SF_PROG */
@@ -130,22 +138,25 @@ sf_unit_populate_key(struct brw_context *brw, struct brw_sf_unit_key *key)
key->urb_size = brw->urb.vsize;
key->sfsize = brw->urb.sfsize;
- key->scissor = brw->attribs.Scissor->Enabled;
- key->front_face = brw->attribs.Polygon->FrontFace;
+ key->scissor = ctx->Scissor.Enabled;
+ key->front_face = ctx->Polygon.FrontFace;
- if (brw->attribs.Polygon->CullFlag)
- key->cull_face = brw->attribs.Polygon->CullFaceMode;
+ if (ctx->Polygon.CullFlag)
+ key->cull_face = ctx->Polygon.CullFaceMode;
else
key->cull_face = GL_NONE;
- key->line_width = brw->attribs.Line->Width;
- key->line_smooth = brw->attribs.Line->SmoothFlag;
+ key->line_width = ctx->Line.Width;
+ key->line_smooth = ctx->Line.SmoothFlag;
+
+ key->point_sprite = ctx->Point.PointSprite;
+ key->point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize);
+ key->point_attenuated = ctx->Point._Attenuated;
- key->point_sprite = brw->attribs.Point->PointSprite;
- key->point_size = brw->attribs.Point->Size;
- key->point_attenuated = brw->attribs.Point->_Attenuated;
+ /* _NEW_LIGHT */
+ key->provoking_vertex = ctx->Light.ProvokingVertex;
- key->render_to_texture = intel_rendering_to_texture(&brw->intel.ctx);
+ key->render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0;
}
static dri_bo *
@@ -154,7 +165,7 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
{
struct brw_sf_unit_state sf;
dri_bo *bo;
-
+ int chipset_max_threads;
memset(&sf, 0, sizeof(sf));
sf.thread0.grf_reg_count = ALIGN(key->total_grf, 16) / 16 - 1;
@@ -163,13 +174,26 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
sf.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
sf.thread3.dispatch_grf_start_reg = 3;
- sf.thread3.urb_entry_read_offset = 1;
+
+ if (BRW_IS_IGDNG(brw))
+ sf.thread3.urb_entry_read_offset = 3;
+ else
+ sf.thread3.urb_entry_read_offset = 1;
+
sf.thread3.urb_entry_read_length = key->urb_entry_read_length;
sf.thread4.nr_urb_entries = key->nr_urb_entries;
sf.thread4.urb_entry_allocation_size = key->sfsize - 1;
- /* Each SF thread produces 1 PUE, and there can be up to 24 threads */
- sf.thread4.max_threads = MIN2(24, key->nr_urb_entries) - 1;
+
+ /* Each SF thread produces 1 PUE, and there can be up to 24(Pre-IGDNG) or
+ * 48(IGDNG) threads
+ */
+ if (BRW_IS_IGDNG(brw))
+ chipset_max_threads = 48;
+ else
+ chipset_max_threads = 24;
+
+ sf.thread4.max_threads = MIN2(chipset_max_threads, key->nr_urb_entries) - 1;
if (INTEL_DEBUG & DEBUG_SINGLE_THREAD)
sf.thread4.max_threads = 0;
@@ -192,10 +216,10 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
else
sf.sf5.front_winding = BRW_FRONTWINDING_CW;
- /* The viewport is inverted for rendering to texture, and that inverts
+ /* The viewport is inverted for rendering to a FBO, and that inverts
* polygon front/back orientation.
*/
- sf.sf5.front_winding ^= key->render_to_texture;
+ sf.sf5.front_winding ^= key->render_to_fbo;
switch (key->cull_face) {
case GL_FRONT:
@@ -225,10 +249,37 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
else if (sf.sf6.line_width <= 0x2)
sf.sf6.line_width = 0;
- /* _NEW_POINT */
- sf.sf6.point_rast_rule = BRW_RASTRULE_UPPER_RIGHT; /* opengl conventions */
+ /* _NEW_BUFFERS */
+ key->render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0;
+ if (!key->render_to_fbo) {
+ /* Rendering to an OpenGL window */
+ sf.sf6.point_rast_rule = BRW_RASTRULE_UPPER_RIGHT;
+ }
+ else {
+ /* If rendering to an FBO, the pixel coordinate system is
+ * inverted with respect to the normal OpenGL coordinate
+ * system, so BRW_RASTRULE_LOWER_RIGHT is correct.
+ * But this value is listed as "Reserved, but not seen as useful"
+ * in Intel documentation (page 212, "Point Rasterization Rule",
+ * section 7.4 "SF Pipeline State Summary", of document
+ * "Intel® 965 Express Chipset Family and Intel® G35 Express
+ * Chipset Graphics Controller Programmer's Reference Manual,
+ * Volume 2: 3D/Media", Revision 1.0b as of January 2008,
+ * available at
+ * http://intellinuxgraphics.org/documentation.html
+ * at the time of this writing).
+ *
+ * It does work on at least some devices, if not all;
+ * if devices that don't support it can be identified,
+ * the likely failure case is that points are rasterized
+ * incorrectly, which is no worse than occurs without
+ * the value, so we're using it here.
+ */
+ sf.sf6.point_rast_rule = BRW_RASTRULE_LOWER_RIGHT;
+ }
/* XXX clamp max depends on AA vs. non-AA */
+ /* _NEW_POINT */
sf.sf7.sprite_point = key->point_sprite;
sf.sf7.point_size = CLAMP(rint(key->point_size), 1, 255) * (1<<3);
sf.sf7.use_point_size_state = !key->point_attenuated;
@@ -236,9 +287,15 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
/* might be BRW_NEW_PRIMITIVE if we have to adjust pv for polygons:
*/
- sf.sf7.trifan_pv = 2;
- sf.sf7.linestrip_pv = 1;
- sf.sf7.tristrip_pv = 2;
+ if (key->provoking_vertex == GL_LAST_VERTEX_CONVENTION) {
+ sf.sf7.trifan_pv = 2;
+ sf.sf7.linestrip_pv = 1;
+ sf.sf7.tristrip_pv = 2;
+ } else {
+ sf.sf7.trifan_pv = 1;
+ sf.sf7.linestrip_pv = 0;
+ sf.sf7.tristrip_pv = 0;
+ }
sf.sf7.line_last_pixel_enable = 0;
/* Set bias for OpenGL rasterization rules:
@@ -252,6 +309,9 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
&sf, sizeof(sf),
NULL, NULL);
+ /* STATE_PREFETCH command description describes this state as being
+ * something loaded through the GPE (L2 ISC), so it's INSTRUCTION domain.
+ */
/* Emit SF program relocation */
dri_bo_emit_reloc(bo,
I915_GEM_DOMAIN_INSTRUCTION, 0,
@@ -292,11 +352,12 @@ static void upload_sf_unit( struct brw_context *brw )
const struct brw_tracked_state brw_sf_unit = {
.dirty = {
.mesa = (_NEW_POLYGON |
+ _NEW_LIGHT |
_NEW_LINE |
_NEW_POINT |
- _NEW_SCISSOR),
- .brw = (BRW_NEW_URB_FENCE |
- BRW_NEW_METAOPS),
+ _NEW_SCISSOR |
+ _NEW_BUFFERS),
+ .brw = BRW_NEW_URB_FENCE,
.cache = (CACHE_NEW_SF_VP |
CACHE_NEW_SF_PROG)
},
diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h
index df839c5b30..78572356a3 100644
--- a/src/mesa/drivers/dri/i965/brw_state.h
+++ b/src/mesa/drivers/dri/i965/brw_state.h
@@ -52,7 +52,6 @@ const struct brw_tracked_state brw_cc_vp;
const struct brw_tracked_state brw_check_fallback;
const struct brw_tracked_state brw_clip_prog;
const struct brw_tracked_state brw_clip_unit;
-const struct brw_tracked_state brw_constant_buffer_state;
const struct brw_tracked_state brw_constant_buffer;
const struct brw_tracked_state brw_curbe_offsets;
const struct brw_tracked_state brw_invarient_state;
@@ -73,11 +72,13 @@ const struct brw_tracked_state brw_sf_vp;
const struct brw_tracked_state brw_state_base_address;
const struct brw_tracked_state brw_urb_fence;
const struct brw_tracked_state brw_vertex_state;
+const struct brw_tracked_state brw_vs_surfaces;
const struct brw_tracked_state brw_vs_prog;
const struct brw_tracked_state brw_vs_unit;
const struct brw_tracked_state brw_wm_input_sizes;
const struct brw_tracked_state brw_wm_prog;
const struct brw_tracked_state brw_wm_samplers;
+const struct brw_tracked_state brw_wm_constant_surface;
const struct brw_tracked_state brw_wm_surfaces;
const struct brw_tracked_state brw_wm_unit;
@@ -91,6 +92,21 @@ const struct brw_tracked_state brw_clear_batch_cache;
const struct brw_tracked_state brw_drawing_rect;
const struct brw_tracked_state brw_indices;
const struct brw_tracked_state brw_vertices;
+const struct brw_tracked_state brw_index_buffer;
+
+/**
+ * Use same key for WM and VS surfaces.
+ */
+struct brw_surface_key {
+ GLenum target, depthmode;
+ dri_bo *bo;
+ GLint format, internal_format;
+ GLint first_level, last_level;
+ GLint width, height, depth;
+ GLint pitch, cpp;
+ uint32_t tiling;
+ GLuint offset;
+};
/***********************************************************************
* brw_state.c
@@ -136,8 +152,8 @@ dri_bo *brw_search_cache( struct brw_cache *cache,
void *aux_return);
void brw_state_cache_check_size( struct brw_context *brw );
-void brw_init_cache( struct brw_context *brw );
-void brw_destroy_cache( struct brw_context *brw );
+void brw_init_caches( struct brw_context *brw );
+void brw_destroy_caches( struct brw_context *brw );
/***********************************************************************
* brw_state_batch.c
@@ -151,4 +167,9 @@ GLboolean brw_cached_batch_struct( struct brw_context *brw,
void brw_destroy_batch_cache( struct brw_context *brw );
void brw_clear_batch_cache_flush( struct brw_context *brw );
+/* brw_wm_surface_state.c */
+dri_bo *
+brw_create_constant_surface( struct brw_context *brw,
+ struct brw_surface_key *key );
+
#endif
diff --git a/src/mesa/drivers/dri/i965/brw_state_batch.c b/src/mesa/drivers/dri/i965/brw_state_batch.c
index dc87859f3f..811940edc0 100644
--- a/src/mesa/drivers/dri/i965/brw_state_batch.c
+++ b/src/mesa/drivers/dri/i965/brw_state_batch.c
@@ -97,8 +97,6 @@ void brw_clear_batch_cache_flush( struct brw_context *brw )
{
clear_batch_cache(brw);
-/* brw_do_flush(brw, BRW_FLUSH_STATE_CACHE|BRW_FLUSH_READ_CACHE); */
-
brw->state.dirty.mesa |= ~0;
brw->state.dirty.brw |= ~0;
brw->state.dirty.cache |= ~0;
diff --git a/src/mesa/drivers/dri/i965/brw_state_cache.c b/src/mesa/drivers/dri/i965/brw_state_cache.c
index d5b5166406..e40d7a0416 100644
--- a/src/mesa/drivers/dri/i965/brw_state_cache.c
+++ b/src/mesa/drivers/dri/i965/brw_state_cache.c
@@ -56,9 +56,9 @@
* incorrect program is run for the other instance.
*/
+#include "main/imports.h"
#include "brw_state.h"
#include "intel_batchbuffer.h"
-#include "main/imports.h"
/* XXX: Fixme - have to include these to get the sizes of the prog_key
* structs:
@@ -69,8 +69,10 @@
#include "brw_sf.h"
#include "brw_gs.h"
-static GLuint hash_key( const void *key, GLuint key_size,
- dri_bo **reloc_bufs, GLuint nr_reloc_bufs)
+
+static GLuint
+hash_key(const void *key, GLuint key_size,
+ dri_bo **reloc_bufs, GLuint nr_reloc_bufs)
{
GLuint *ikey = (GLuint *)key;
GLuint hash = 0, i;
@@ -95,6 +97,7 @@ static GLuint hash_key( const void *key, GLuint key_size,
return hash;
}
+
/**
* Marks a new buffer as being chosen for the given cache id.
*/
@@ -111,6 +114,7 @@ update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id,
cache->brw->state.dirty.cache |= 1 << cache_id;
}
+
static struct brw_cache_item *
search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
GLuint hash, const void *key, GLuint key_size,
@@ -143,7 +147,8 @@ search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
}
-static void rehash( struct brw_cache *cache )
+static void
+rehash(struct brw_cache *cache)
{
struct brw_cache_item **items;
struct brw_cache_item *c, *next;
@@ -164,15 +169,17 @@ static void rehash( struct brw_cache *cache )
cache->size = size;
}
+
/**
* Returns the buffer object matching cache_id and key, or NULL.
*/
-dri_bo *brw_search_cache( struct brw_cache *cache,
- enum brw_cache_id cache_id,
- const void *key,
- GLuint key_size,
- dri_bo **reloc_bufs, GLuint nr_reloc_bufs,
- void *aux_return )
+dri_bo *
+brw_search_cache(struct brw_cache *cache,
+ enum brw_cache_id cache_id,
+ const void *key,
+ GLuint key_size,
+ dri_bo **reloc_bufs, GLuint nr_reloc_bufs,
+ void *aux_return)
{
struct brw_cache_item *item;
GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
@@ -192,6 +199,7 @@ dri_bo *brw_search_cache( struct brw_cache *cache,
return item->bo;
}
+
dri_bo *
brw_upload_cache( struct brw_cache *cache,
enum brw_cache_id cache_id,
@@ -265,7 +273,9 @@ brw_upload_cache( struct brw_cache *cache,
return bo;
}
-/* This doesn't really work with aux data. Use search/upload instead
+
+/**
+ * This doesn't really work with aux data. Use search/upload instead
*/
dri_bo *
brw_cache_data_sz(struct brw_cache *cache,
@@ -296,6 +306,7 @@ brw_cache_data_sz(struct brw_cache *cache,
return bo;
}
+
/**
* Wrapper around brw_cache_data_sz using the cache_id's canonical key size.
*
@@ -319,21 +330,22 @@ enum pool_type {
DW_GENERAL_STATE
};
+
static void
-brw_init_cache_id( struct brw_context *brw,
- const char *name,
- enum brw_cache_id id,
- GLuint key_size,
- GLuint aux_size)
+brw_init_cache_id(struct brw_cache *cache,
+ const char *name,
+ enum brw_cache_id id,
+ GLuint key_size,
+ GLuint aux_size)
{
- struct brw_cache *cache = &brw->cache;
-
cache->name[id] = strdup(name);
cache->key_size[id] = key_size;
cache->aux_size[id] = aux_size;
}
-void brw_init_cache( struct brw_context *brw )
+
+static void
+brw_init_non_surface_cache(struct brw_context *brw)
{
struct brw_cache *cache = &brw->cache;
@@ -342,114 +354,136 @@ void brw_init_cache( struct brw_context *brw )
cache->size = 7;
cache->n_items = 0;
cache->items = (struct brw_cache_item **)
- _mesa_calloc(cache->size *
- sizeof(struct brw_cache_item));
+ _mesa_calloc(cache->size * sizeof(struct brw_cache_item));
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"CC_VP",
BRW_CC_VP,
sizeof(struct brw_cc_viewport),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"CC_UNIT",
BRW_CC_UNIT,
sizeof(struct brw_cc_unit_state),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"WM_PROG",
BRW_WM_PROG,
sizeof(struct brw_wm_prog_key),
sizeof(struct brw_wm_prog_data));
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"SAMPLER_DEFAULT_COLOR",
BRW_SAMPLER_DEFAULT_COLOR,
sizeof(struct brw_sampler_default_color),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"SAMPLER",
BRW_SAMPLER,
0, /* variable key/data size */
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"WM_UNIT",
BRW_WM_UNIT,
sizeof(struct brw_wm_unit_state),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"SF_PROG",
BRW_SF_PROG,
sizeof(struct brw_sf_prog_key),
sizeof(struct brw_sf_prog_data));
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"SF_VP",
BRW_SF_VP,
sizeof(struct brw_sf_viewport),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"SF_UNIT",
BRW_SF_UNIT,
sizeof(struct brw_sf_unit_state),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"VS_UNIT",
BRW_VS_UNIT,
sizeof(struct brw_vs_unit_state),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"VS_PROG",
BRW_VS_PROG,
sizeof(struct brw_vs_prog_key),
sizeof(struct brw_vs_prog_data));
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"CLIP_UNIT",
BRW_CLIP_UNIT,
sizeof(struct brw_clip_unit_state),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"CLIP_PROG",
BRW_CLIP_PROG,
sizeof(struct brw_clip_prog_key),
sizeof(struct brw_clip_prog_data));
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"GS_UNIT",
BRW_GS_UNIT,
sizeof(struct brw_gs_unit_state),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"GS_PROG",
BRW_GS_PROG,
sizeof(struct brw_gs_prog_key),
sizeof(struct brw_gs_prog_data));
+}
+
+
+static void
+brw_init_surface_cache(struct brw_context *brw)
+{
+ struct brw_cache *cache = &brw->surface_cache;
+
+ cache->brw = brw;
- brw_init_cache_id(brw,
+ cache->size = 7;
+ cache->n_items = 0;
+ cache->items = (struct brw_cache_item **)
+ _mesa_calloc(cache->size * sizeof(struct brw_cache_item));
+
+ brw_init_cache_id(cache,
"SS_SURFACE",
BRW_SS_SURFACE,
sizeof(struct brw_surface_state),
0);
- brw_init_cache_id(brw,
+ brw_init_cache_id(cache,
"SS_SURF_BIND",
BRW_SS_SURF_BIND,
0,
0);
}
+
+void
+brw_init_caches(struct brw_context *brw)
+{
+ brw_init_non_surface_cache(brw);
+ brw_init_surface_cache(brw);
+}
+
+
static void
-brw_clear_cache( struct brw_context *brw )
+brw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
{
struct brw_cache_item *c, *next;
GLuint i;
@@ -457,8 +491,8 @@ brw_clear_cache( struct brw_context *brw )
if (INTEL_DEBUG & DEBUG_STATE)
_mesa_printf("%s\n", __FUNCTION__);
- for (i = 0; i < brw->cache.size; i++) {
- for (c = brw->cache.items[i]; c; c = next) {
+ for (i = 0; i < cache->size; i++) {
+ for (c = cache->items[i]; c; c = next) {
int j;
next = c->next;
@@ -468,10 +502,10 @@ brw_clear_cache( struct brw_context *brw )
free((void *)c->key);
free(c);
}
- brw->cache.items[i] = NULL;
+ cache->items[i] = NULL;
}
- brw->cache.n_items = 0;
+ cache->n_items = 0;
if (brw->curbe.last_buf) {
_mesa_free(brw->curbe.last_buf);
@@ -483,25 +517,46 @@ brw_clear_cache( struct brw_context *brw )
brw->state.dirty.cache |= ~0;
}
-void brw_state_cache_check_size( struct brw_context *brw )
+
+void
+brw_state_cache_check_size(struct brw_context *brw)
{
+ if (INTEL_DEBUG & DEBUG_STATE)
+ _mesa_printf("%s (n_items=%d)\n", __FUNCTION__, brw->cache.n_items);
+
/* un-tuned guess. We've got around 20 state objects for a total of around
* 32k, so 1000 of them is around 1.5MB.
*/
if (brw->cache.n_items > 1000)
- brw_clear_cache(brw);
+ brw_clear_cache(brw, &brw->cache);
+
+ if (brw->surface_cache.n_items > 1000)
+ brw_clear_cache(brw, &brw->surface_cache);
}
-void brw_destroy_cache( struct brw_context *brw )
+
+static void
+brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache)
{
GLuint i;
- brw_clear_cache(brw);
+ if (INTEL_DEBUG & DEBUG_STATE)
+ _mesa_printf("%s\n", __FUNCTION__);
+
+ brw_clear_cache(brw, cache);
for (i = 0; i < BRW_MAX_CACHE; i++) {
- dri_bo_unreference(brw->cache.last_bo[i]);
- free(brw->cache.name[i]);
+ dri_bo_unreference(cache->last_bo[i]);
+ free(cache->name[i]);
}
- free(brw->cache.items);
- brw->cache.items = NULL;
- brw->cache.size = 0;
+ free(cache->items);
+ cache->items = NULL;
+ cache->size = 0;
+}
+
+
+void
+brw_destroy_caches(struct brw_context *brw)
+{
+ brw_destroy_cache(brw, &brw->cache);
+ brw_destroy_cache(brw, &brw->surface_cache);
}
diff --git a/src/mesa/drivers/dri/i965/brw_state_dump.c b/src/mesa/drivers/dri/i965/brw_state_dump.c
index b28c57c2bc..e94fa7d2b4 100644
--- a/src/mesa/drivers/dri/i965/brw_state_dump.c
+++ b/src/mesa/drivers/dri/i965/brw_state_dump.c
@@ -84,6 +84,19 @@ get_965_surfacetype(unsigned int surfacetype)
}
}
+static const char *
+get_965_surface_format(unsigned int surface_format)
+{
+ switch (surface_format) {
+ case 0x000: return "r32g32b32a32_float";
+ case 0x0c1: return "b8g8r8a8_unorm";
+ case 0x100: return "b5g6r5_unorm";
+ case 0x102: return "b5g5r5a1_unorm";
+ case 0x104: return "b4g4r4a4_unorm";
+ default: return "unknown";
+ }
+}
+
static void dump_wm_surface_state(struct brw_context *brw)
{
int i;
@@ -95,7 +108,7 @@ static void dump_wm_surface_state(struct brw_context *brw)
char name[20];
if (surf_bo == NULL) {
- fprintf(stderr, "WM SS%d: NULL\n", i);
+ fprintf(stderr, " WM SS%d: NULL\n", i);
continue;
}
dri_bo_map(surf_bo, GL_FALSE);
@@ -103,8 +116,9 @@ static void dump_wm_surface_state(struct brw_context *brw)
surf = (struct brw_surface_state *)(surf_bo->virtual);
sprintf(name, "WM SS%d", i);
- state_out(name, surf, surfoff, 0, "%s\n",
- get_965_surfacetype(surf->ss0.surface_type));
+ state_out(name, surf, surfoff, 0, "%s %s\n",
+ get_965_surfacetype(surf->ss0.surface_type),
+ get_965_surface_format(surf->ss0.surface_format));
state_out(name, surf, surfoff, 1, "offset\n");
state_out(name, surf, surfoff, 2, "%dx%d size, %d mips\n",
surf->ss2.width + 1, surf->ss2.height + 1, surf->ss2.mip_count);
@@ -112,6 +126,8 @@ static void dump_wm_surface_state(struct brw_context *brw)
surf->ss3.pitch + 1, surf->ss3.tiled_surface ? "" : "not ");
state_out(name, surf, surfoff, 4, "mip base %d\n",
surf->ss4.min_lod);
+ state_out(name, surf, surfoff, 5, "x,y offset: %d,%d\n",
+ surf->ss5.x_offset, surf->ss5.y_offset);
dri_bo_unmap(surf_bo);
}
@@ -162,6 +178,14 @@ static void brw_debug_prog(const char *name, dri_bo *prog)
fprintf(stderr, "%8s: 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
name, (unsigned int)prog->offset + i * 4 * 4,
data[i * 4], data[i * 4 + 1], data[i * 4 + 2], data[i * 4 + 3]);
+ /* Stop at the end of the program. It'd be nice to keep track of the actual
+ * intended program size instead of guessing like this.
+ */
+ if (data[i * 4 + 0] == 0 &&
+ data[i * 4 + 1] == 0 &&
+ data[i * 4 + 2] == 0 &&
+ data[i * 4 + 3] == 0)
+ break;
}
dri_bo_unmap(prog);
diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c
index 4845859b3e..414620d0b3 100644
--- a/src/mesa/drivers/dri/i965/brw_state_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_state_upload.c
@@ -59,11 +59,12 @@ const struct brw_tracked_state *atoms[] =
&brw_curbe_offsets,
&brw_recalculate_urb_fence,
-
&brw_cc_vp,
&brw_cc_unit,
- &brw_wm_surfaces, /* must do before samplers */
+ &brw_vs_surfaces, /* must do before unit */
+ &brw_wm_constant_surface, /* must do before wm surfaces/bind bo */
+ &brw_wm_surfaces, /* must do before samplers and unit */
&brw_wm_samplers,
&brw_wm_unit,
@@ -88,54 +89,27 @@ const struct brw_tracked_state *atoms[] =
&brw_line_stipple,
&brw_aa_line_parameters,
- /* Ordering of the commands below is documented as fixed.
- */
-#if 0
- &brw_pipelined_state_pointers,
- &brw_urb_fence,
- &brw_constant_buffer_state,
-#else
+
&brw_psp_urb_cbs,
-#endif
&brw_drawing_rect,
&brw_indices,
+ &brw_index_buffer,
&brw_vertices,
- NULL, /* brw_constant_buffer */
+ &brw_constant_buffer
};
void brw_init_state( struct brw_context *brw )
{
- GLuint i;
-
- brw_init_cache(brw);
-
- brw->state.atoms = _mesa_malloc(sizeof(atoms));
- brw->state.nr_atoms = sizeof(atoms)/sizeof(*atoms);
- _mesa_memcpy(brw->state.atoms, atoms, sizeof(atoms));
-
- /* Patch in a pointer to the dynamic state atom:
- */
- for (i = 0; i < brw->state.nr_atoms; i++)
- if (brw->state.atoms[i] == NULL)
- brw->state.atoms[i] = &brw->curbe.tracked_state;
-
- _mesa_memcpy(&brw->curbe.tracked_state,
- &brw_constant_buffer,
- sizeof(brw_constant_buffer));
+ brw_init_caches(brw);
}
void brw_destroy_state( struct brw_context *brw )
{
- if (brw->state.atoms) {
- _mesa_free(brw->state.atoms);
- brw->state.atoms = NULL;
- }
-
- brw_destroy_cache(brw);
+ brw_destroy_caches(brw);
brw_destroy_batch_cache(brw);
}
@@ -218,6 +192,7 @@ static struct dirty_bit_map mesa_bits[] = {
DEFINE_BIT(_NEW_MULTISAMPLE),
DEFINE_BIT(_NEW_TRACK_MATRIX),
DEFINE_BIT(_NEW_PROGRAM),
+ DEFINE_BIT(_NEW_PROGRAM_CONSTANTS),
{0, 0, 0}
};
@@ -231,11 +206,10 @@ static struct dirty_bit_map brw_bits[] = {
DEFINE_BIT(BRW_NEW_PRIMITIVE),
DEFINE_BIT(BRW_NEW_CONTEXT),
DEFINE_BIT(BRW_NEW_WM_INPUT_DIMENSIONS),
- DEFINE_BIT(BRW_NEW_INPUT_VARYING),
DEFINE_BIT(BRW_NEW_PSP),
- DEFINE_BIT(BRW_NEW_METAOPS),
DEFINE_BIT(BRW_NEW_FENCE),
DEFINE_BIT(BRW_NEW_INDICES),
+ DEFINE_BIT(BRW_NEW_INDEX_BUFFER),
DEFINE_BIT(BRW_NEW_VERTICES),
DEFINE_BIT(BRW_NEW_BATCH),
DEFINE_BIT(BRW_NEW_DEPTH_BUFFER),
@@ -298,6 +272,7 @@ brw_print_dirty_count(struct dirty_bit_map *bit_map, int32_t bits)
*/
void brw_validate_state( struct brw_context *brw )
{
+ GLcontext *ctx = &brw->intel.ctx;
struct intel_context *intel = &brw->intel;
struct brw_state_flags *state = &brw->state.dirty;
GLuint i;
@@ -314,13 +289,13 @@ void brw_validate_state( struct brw_context *brw )
state->brw |= ~0;
}
- if (brw->fragment_program != brw->attribs.FragmentProgram->_Current) {
- brw->fragment_program = brw->attribs.FragmentProgram->_Current;
+ if (brw->fragment_program != ctx->FragmentProgram._Current) {
+ brw->fragment_program = ctx->FragmentProgram._Current;
brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM;
}
- if (brw->vertex_program != brw->attribs.VertexProgram->_Current) {
- brw->vertex_program = brw->attribs.VertexProgram->_Current;
+ if (brw->vertex_program != ctx->VertexProgram._Current) {
+ brw->vertex_program = ctx->VertexProgram._Current;
brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM;
}
@@ -336,7 +311,7 @@ void brw_validate_state( struct brw_context *brw )
/* do prepare stage for all atoms */
for (i = 0; i < Elements(atoms); i++) {
- const struct brw_tracked_state *atom = brw->state.atoms[i];
+ const struct brw_tracked_state *atom = atoms[i];
if (brw->intel.Fallback)
break;
@@ -347,6 +322,19 @@ void brw_validate_state( struct brw_context *brw )
}
}
}
+
+ /* Make sure that the textures which are referenced by the current
+ * brw fragment program are actually present/valid.
+ * If this fails, we can experience GPU lock-ups.
+ */
+ {
+ const struct brw_fragment_program *fp;
+ fp = brw_fragment_program_const(brw->fragment_program);
+ if (fp) {
+ assert((fp->tex_units_used & ctx->Texture._EnabledUnits)
+ == fp->tex_units_used);
+ }
+ }
}
@@ -367,8 +355,8 @@ void brw_upload_state(struct brw_context *brw)
_mesa_memset(&examined, 0, sizeof(examined));
prev = *state;
- for (i = 0; i < brw->state.nr_atoms; i++) {
- const struct brw_tracked_state *atom = brw->state.atoms[i];
+ for (i = 0; i < Elements(atoms); i++) {
+ const struct brw_tracked_state *atom = atoms[i];
struct brw_state_flags generated;
assert(atom->dirty.mesa ||
@@ -397,7 +385,7 @@ void brw_upload_state(struct brw_context *brw)
}
else {
for (i = 0; i < Elements(atoms); i++) {
- const struct brw_tracked_state *atom = brw->state.atoms[i];
+ const struct brw_tracked_state *atom = atoms[i];
if (brw->intel.Fallback)
break;
diff --git a/src/mesa/drivers/dri/i965/brw_structs.h b/src/mesa/drivers/dri/i965/brw_structs.h
index 4e577d0f6a..66d4127271 100644
--- a/src/mesa/drivers/dri/i965/brw_structs.h
+++ b/src/mesa/drivers/dri/i965/brw_structs.h
@@ -33,6 +33,14 @@
#ifndef BRW_STRUCTS_H
#define BRW_STRUCTS_H
+
+/** Number of general purpose registers (VS, WM, etc) */
+#define BRW_MAX_GRF 128
+
+/** Number of message register file registers */
+#define BRW_MAX_MRF 16
+
+
/* Command packets:
*/
struct header
@@ -434,12 +442,12 @@ struct brw_urb_fence
{
GLuint sf_fence:10;
GLuint vf_fence:10;
- GLuint cs_fence:10;
- GLuint pad:2;
+ GLuint cs_fence:11;
+ GLuint pad:1;
} bits1;
};
-struct brw_constant_buffer_state /* previously brw_command_streamer */
+struct brw_cs_urb_state
{
struct header header;
@@ -815,7 +823,9 @@ struct brw_gs_unit_state
struct
{
- GLuint pad0:10;
+ GLuint pad0:8;
+ GLuint rendering_enable:1; /* for IGDNG */
+ GLuint pad4:1;
GLuint stats_enable:1;
GLuint nr_urb_entries:7;
GLuint pad1:1;
@@ -923,6 +933,28 @@ struct brw_wm_unit_state
GLfloat global_depth_offset_constant;
GLfloat global_depth_offset_scale;
+
+ /* for IGDNG only */
+ struct {
+ GLuint pad0:1;
+ GLuint grf_reg_count_1:3;
+ GLuint pad1:2;
+ GLuint kernel_start_pointer_1:26;
+ } wm8;
+
+ struct {
+ GLuint pad0:1;
+ GLuint grf_reg_count_2:3;
+ GLuint pad1:2;
+ GLuint kernel_start_pointer_2:26;
+ } wm9;
+
+ struct {
+ GLuint pad0:1;
+ GLuint grf_reg_count_3:3;
+ GLuint pad1:2;
+ GLuint kernel_start_pointer_3:26;
+ } wm10;
};
struct brw_sampler_default_color {
@@ -1031,10 +1063,10 @@ struct brw_surface_state
GLuint writedisable_green:1;
GLuint writedisable_red:1;
GLuint writedisable_alpha:1;
- GLuint surface_format:9;
+ GLuint surface_format:9; /**< BRW_SURFACEFORMAT_x */
GLuint data_return_format:1;
GLuint pad0:1;
- GLuint surface_type:3;
+ GLuint surface_type:3; /**< BRW_SURFACE_1D/2D/3D/CUBE */
} ss0;
struct {
@@ -1075,7 +1107,7 @@ struct brw_surface_state
GLuint y_offset:4;
GLuint pad0:1;
GLuint x_offset:7;
- } ss5; /* NEW in Integrated Graphics Device */
+ } ss5; /* New in G4X */
};
@@ -1168,7 +1200,7 @@ struct brw_instruction
GLuint predicate_control:4;
GLuint predicate_inverse:1;
GLuint execution_size:3;
- GLuint destreg__conditonalmod:4; /* destreg - send, conditionalmod - others */
+ GLuint destreg__conditionalmod:4; /* destreg - send, conditionalmod - others */
GLuint pad0:2;
GLuint debug_control:1;
GLuint saturate:1;
@@ -1196,7 +1228,9 @@ struct brw_instruction
GLuint dest_reg_type:3;
GLuint src0_reg_file:2;
GLuint src0_reg_type:3;
- GLuint pad:6;
+ GLuint src1_reg_file:2; /* 0x00000c00 */
+ GLuint src1_reg_type:3; /* 0x00007000 */
+ GLuint pad:1;
GLint dest_indirect_offset:10; /* offset against the deref'd address reg */
GLuint dest_subreg_nr:3; /* subnr for the address reg a0.x */
GLuint dest_horiz_stride:2;
@@ -1211,7 +1245,7 @@ struct brw_instruction
GLuint src0_reg_type:3;
GLuint src1_reg_file:2;
GLuint src1_reg_type:3;
- GLuint pad0:1;
+ GLuint pad:1;
GLuint dest_writemask:4;
GLuint dest_subreg_nr:1;
GLuint dest_reg_nr:8;
@@ -1298,6 +1332,14 @@ struct brw_instruction
GLuint pad1:6;
} ia16;
+ struct
+ {
+ GLuint pad:26;
+ GLuint end_of_thread:1;
+ GLuint pad1:1;
+ GLuint sfid:4;
+ } send_igdng; /* for IGDNG only */
+
} bits2;
union
@@ -1308,7 +1350,7 @@ struct brw_instruction
GLuint src1_reg_nr:8;
GLuint src1_abs:1;
GLuint src1_negate:1;
- GLuint pad:1;
+ GLuint src1_address_mode:1;
GLuint src1_horiz_stride:2;
GLuint src1_width:3;
GLuint src1_vert_stride:4;
@@ -1323,7 +1365,7 @@ struct brw_instruction
GLuint src1_reg_nr:8;
GLuint src1_abs:1;
GLuint src1_negate:1;
- GLuint pad0:1;
+ GLuint src1_address_mode:1;
GLuint src1_swz_z:2;
GLuint src1_swz_w:2;
GLuint pad1:1;
@@ -1337,7 +1379,7 @@ struct brw_instruction
GLuint src1_subreg_nr:3;
GLuint src1_abs:1;
GLuint src1_negate:1;
- GLuint pad0:1;
+ GLuint src1_address_mode:1;
GLuint src1_horiz_stride:2;
GLuint src1_width:3;
GLuint src1_vert_stride:4;
@@ -1385,6 +1427,21 @@ struct brw_instruction
} math;
struct {
+ GLuint function:4;
+ GLuint int_type:1;
+ GLuint precision:1;
+ GLuint saturate:1;
+ GLuint data_type:1;
+ GLuint snapshot:1;
+ GLuint pad0:10;
+ GLuint header_present:1;
+ GLuint response_length:5;
+ GLuint msg_length:4;
+ GLuint pad1:2;
+ GLuint end_of_thread:1;
+ } math_igdng;
+
+ struct {
GLuint binding_table_index:8;
GLuint sampler:4;
GLuint return_format:2;
@@ -1407,9 +1464,38 @@ struct brw_instruction
GLuint end_of_thread:1;
} sampler_g4x;
+ struct {
+ GLuint binding_table_index:8;
+ GLuint sampler:4;
+ GLuint msg_type:4;
+ GLuint simd_mode:2;
+ GLuint pad0:1;
+ GLuint header_present:1;
+ GLuint response_length:5;
+ GLuint msg_length:4;
+ GLuint pad1:2;
+ GLuint end_of_thread:1;
+ } sampler_igdng;
+
struct brw_urb_immediate urb;
struct {
+ GLuint opcode:4;
+ GLuint offset:6;
+ GLuint swizzle_control:2;
+ GLuint pad:1;
+ GLuint allocate:1;
+ GLuint used:1;
+ GLuint complete:1;
+ GLuint pad0:3;
+ GLuint header_present:1;
+ GLuint response_length:5;
+ GLuint msg_length:4;
+ GLuint pad1:2;
+ GLuint end_of_thread:1;
+ } urb_igdng;
+
+ struct {
GLuint binding_table_index:8;
GLuint msg_control:4;
GLuint msg_type:2;
@@ -1423,6 +1509,19 @@ struct brw_instruction
struct {
GLuint binding_table_index:8;
+ GLuint msg_control:3;
+ GLuint msg_type:3;
+ GLuint target_cache:2;
+ GLuint pad0:3;
+ GLuint header_present:1;
+ GLuint response_length:5;
+ GLuint msg_length:4;
+ GLuint pad1:2;
+ GLuint end_of_thread:1;
+ } dp_read_igdng;
+
+ struct {
+ GLuint binding_table_index:8;
GLuint msg_control:3;
GLuint pixel_scoreboard_clear:1;
GLuint msg_type:3;
@@ -1435,6 +1534,20 @@ struct brw_instruction
} dp_write;
struct {
+ GLuint binding_table_index:8;
+ GLuint msg_control:3;
+ GLuint pixel_scoreboard_clear:1;
+ GLuint msg_type:3;
+ GLuint send_commit_msg:1;
+ GLuint pad0:3;
+ GLuint header_present:1;
+ GLuint response_length:5;
+ GLuint msg_length:4;
+ GLuint pad1:2;
+ GLuint end_of_thread:1;
+ } dp_write_igdng;
+
+ struct {
GLuint pad:16;
GLuint response_length:4;
GLuint msg_length:4;
@@ -1443,8 +1556,18 @@ struct brw_instruction
GLuint end_of_thread:1;
} generic;
+ struct {
+ GLuint pad:19;
+ GLuint header_present:1;
+ GLuint response_length:5;
+ GLuint msg_length:4;
+ GLuint pad1:2;
+ GLuint end_of_thread:1;
+ } generic_igdng;
+
GLint d;
GLuint ud;
+ float f;
} bits3;
};
diff --git a/src/mesa/drivers/dri/i965/brw_tex.c b/src/mesa/drivers/dri/i965/brw_tex.c
index 0bb6f176a0..71bff166dd 100644
--- a/src/mesa/drivers/dri/i965/brw_tex.c
+++ b/src/mesa/drivers/dri/i965/brw_tex.c
@@ -32,21 +32,12 @@
#include "main/glheader.h"
#include "main/mtypes.h"
-#include "main/imports.h"
-#include "main/simple_list.h"
-#include "main/enums.h"
-#include "main/image.h"
#include "main/teximage.h"
-#include "main/texstore.h"
-#include "main/texformat.h"
-
-#include "texmem.h"
#include "intel_context.h"
#include "intel_regions.h"
#include "intel_tex.h"
#include "brw_context.h"
-#include "brw_defines.h"
void brw_FrameBufferTexInit( struct brw_context *brw,
@@ -86,11 +77,12 @@ void brw_FrameBufferTexDestroy( struct brw_context *brw )
*/
void brw_validate_textures( struct brw_context *brw )
{
+ GLcontext *ctx = &brw->intel.ctx;
struct intel_context *intel = &brw->intel;
int i;
for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
- struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[i];
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
if (texUnit->_ReallyEnabled) {
intel_finalize_mipmap_tree(intel, i);
diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index 51a617fcb4..5986cbffad 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -28,7 +28,6 @@
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
-
/* Code to layout images in a mipmap tree for i965.
*/
@@ -37,17 +36,93 @@
#include "intel_tex_layout.h"
#include "intel_context.h"
#include "main/macros.h"
+#include "intel_chipset.h"
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
-GLboolean brw_miptree_layout( struct intel_context *intel, struct intel_mipmap_tree *mt )
+GLboolean brw_miptree_layout(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t tiling)
{
- /* XXX: these vary depending on image format:
- */
-/* GLint align_w = 4; */
+ /* XXX: these vary depending on image format: */
+ /* GLint align_w = 4; */
switch (mt->target) {
- case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP:
+ if (IS_IGDNG(intel->intelScreen->deviceID)) {
+ GLuint align_h = 2, align_w = 4;
+ GLuint level;
+ GLuint x = 0;
+ GLuint y = 0;
+ GLuint width = mt->width0;
+ GLuint height = mt->height0;
+ GLuint qpitch = 0;
+ GLuint y_pitch = 0;
+
+ mt->pitch = mt->width0;
+ intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h);
+ y_pitch = ALIGN(height, align_h);
+
+ if (mt->compressed) {
+ mt->pitch = ALIGN(mt->width0, align_w);
+ }
+
+ if (mt->first_level != mt->last_level) {
+ GLuint mip1_width;
+
+ if (mt->compressed) {
+ mip1_width = ALIGN(minify(mt->width0), align_w)
+ + ALIGN(minify(minify(mt->width0)), align_w);
+ } else {
+ mip1_width = ALIGN(minify(mt->width0), align_w)
+ + minify(minify(mt->width0));
+ }
+
+ if (mip1_width > mt->pitch) {
+ mt->pitch = mip1_width;
+ }
+ }
+
+ mt->pitch = intel_miptree_pitch_align(intel, mt, tiling, mt->pitch);
+
+ if (mt->compressed) {
+ qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * mt->pitch * mt->cpp;
+ mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * 6;
+ } else {
+ qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * mt->pitch * mt->cpp;
+ mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * 6;
+ }
+
+ for (level = mt->first_level; level <= mt->last_level; level++) {
+ GLuint img_height;
+ GLuint nr_images = 6;
+ GLuint q = 0;
+
+ intel_miptree_set_level_info(mt, level, nr_images, x, y, width,
+ height, 1);
+
+ for (q = 0; q < nr_images; q++)
+ intel_miptree_set_image_offset_ex(mt, level, q, x, y, q * qpitch);
+
+ if (mt->compressed)
+ img_height = MAX2(1, height/4);
+ else
+ img_height = ALIGN(height, align_h);
+
+ if (level == mt->first_level + 1) {
+ x += ALIGN(width, align_w);
+ }
+ else {
+ y += img_height;
+ }
+
+ width = minify(width);
+ height = minify(height);
+ }
+
+ break;
+ }
+
case GL_TEXTURE_3D: {
GLuint width = mt->width0;
GLuint height = mt->height0;
@@ -59,25 +134,25 @@ GLboolean brw_miptree_layout( struct intel_context *intel, struct intel_mipmap_t
GLuint align_w = 4;
mt->total_height = 0;
-
+ intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h);
+
if (mt->compressed) {
- align_w = intel_compressed_alignment(mt->internal_format);
mt->pitch = ALIGN(width, align_w);
pack_y_pitch = (height + 3) / 4;
} else {
- mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
- pack_y_pitch = ALIGN(mt->height0, align_h);
+ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
+ pack_y_pitch = ALIGN(mt->height0, align_h);
}
- pack_x_pitch = mt->pitch;
+ pack_x_pitch = width;
pack_x_nr = 1;
- for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {
+ for (level = mt->first_level ; level <= mt->last_level ; level++) {
GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6;
GLint x = 0;
GLint y = 0;
GLint q, j;
-
+
intel_miptree_set_level_info(mt, level, nr_images,
0, mt->total_height,
width, height, depth);
@@ -89,7 +164,7 @@ GLboolean brw_miptree_layout( struct intel_context *intel, struct intel_mipmap_t
}
x = 0;
- y += pack_y_pitch;
+ y += pack_y_pitch;
}
@@ -98,40 +173,50 @@ GLboolean brw_miptree_layout( struct intel_context *intel, struct intel_mipmap_t
height = minify(height);
depth = minify(depth);
- if (mt->compressed) {
- pack_y_pitch = (height + 3) / 4;
-
- if (pack_x_pitch > ALIGN(width, align_w)) {
- pack_x_pitch = ALIGN(width, align_w);
- pack_x_nr <<= 1;
- }
- } else {
- if (pack_x_pitch > 4) {
- pack_x_pitch >>= 1;
- pack_x_nr <<= 1;
- assert(pack_x_pitch * pack_x_nr <= mt->pitch);
- }
-
- if (pack_y_pitch > 2) {
- pack_y_pitch >>= 1;
- pack_y_pitch = ALIGN(pack_y_pitch, align_h);
- }
- }
+ if (mt->compressed) {
+ pack_y_pitch = (height + 3) / 4;
+
+ if (pack_x_pitch > ALIGN(width, align_w)) {
+ pack_x_pitch = ALIGN(width, align_w);
+ pack_x_nr <<= 1;
+ }
+ } else {
+ if (pack_x_pitch > 4) {
+ pack_x_pitch >>= 1;
+ pack_x_nr <<= 1;
+ assert(pack_x_pitch * pack_x_nr <= mt->pitch);
+ }
+
+ if (pack_y_pitch > 2) {
+ pack_y_pitch >>= 1;
+ pack_y_pitch = ALIGN(pack_y_pitch, align_h);
+ }
+ }
}
+ /* The 965's sampler lays cachelines out according to how accesses
+ * in the texture surfaces run, so they may be "vertical" through
+ * memory. As a result, the docs say in Surface Padding Requirements:
+ * Sampling Engine Surfaces that two extra rows of padding are required.
+ * We don't know of similar requirements for pre-965, but given that
+ * those docs are silent on padding requirements in general, let's play
+ * it safe.
+ */
+ if (mt->target == GL_TEXTURE_CUBE_MAP)
+ mt->total_height += 2;
break;
}
default:
- i945_miptree_layout_2d(intel, mt);
+ i945_miptree_layout_2d(intel, mt, tiling);
break;
}
- DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
- mt->pitch,
+ DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
+ mt->pitch,
mt->total_height,
mt->cpp,
mt->pitch * mt->total_height * mt->cpp );
-
+
return GL_TRUE;
}
diff --git a/src/mesa/drivers/dri/i965/brw_urb.c b/src/mesa/drivers/dri/i965/brw_urb.c
index 7673dd36eb..8c6f4355a6 100644
--- a/src/mesa/drivers/dri/i965/brw_urb.c
+++ b/src/mesa/drivers/dri/i965/brw_urb.c
@@ -143,7 +143,29 @@ static void recalculate_urb_fence( struct brw_context *brw )
brw->urb.nr_clip_entries = limits[CLP].preferred_nr_entries;
brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;
brw->urb.nr_cs_entries = limits[CS].preferred_nr_entries;
-
+
+ brw->urb.constrained = 0;
+
+ if (BRW_IS_IGDNG(brw)) {
+ brw->urb.nr_vs_entries = 128;
+ brw->urb.nr_sf_entries = 48;
+ if (check_urb_layout(brw)) {
+ goto done;
+ } else {
+ brw->urb.constrained = 1;
+ brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
+ brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;
+ }
+ } else if (BRW_IS_G4X(brw)) {
+ brw->urb.nr_vs_entries = 64;
+ if (check_urb_layout(brw)) {
+ goto done;
+ } else {
+ brw->urb.constrained = 1;
+ brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
+ }
+ }
+
if (!check_urb_layout(brw)) {
brw->urb.nr_vs_entries = limits[VS].min_nr_entries;
brw->urb.nr_gs_entries = limits[GS].min_nr_entries;
@@ -169,9 +191,8 @@ static void recalculate_urb_fence( struct brw_context *brw )
if (INTEL_DEBUG & (DEBUG_URB|DEBUG_FALLBACKS))
_mesa_printf("URB CONSTRAINED\n");
}
- else
- brw->urb.constrained = 0;
+done:
if (INTEL_DEBUG & DEBUG_URB)
_mesa_printf("URB fence: %d ..VS.. %d ..GS.. %d ..CLP.. %d ..SF.. %d ..CS.. %d\n",
brw->urb.vs_start,
diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c
index 1db7ceebcf..e3111c6680 100644
--- a/src/mesa/drivers/dri/i965/brw_vs.c
+++ b/src/mesa/drivers/dri/i965/brw_vs.c
@@ -85,6 +85,7 @@ static void do_vs_prog( struct brw_context *brw,
static void brw_upload_vs_prog(struct brw_context *brw)
{
+ GLcontext *ctx = &brw->intel.ctx;
struct brw_vs_prog_key key;
struct brw_vertex_program *vp =
(struct brw_vertex_program *)brw->vertex_program;
@@ -97,14 +98,9 @@ static void brw_upload_vs_prog(struct brw_context *brw)
* the inputs it asks for, whether they are varying or not.
*/
key.program_string_id = vp->id;
- key.nr_userclip = brw_count_bits(brw->attribs.Transform->ClipPlanesEnabled);
- key.copy_edgeflag = (brw->attribs.Polygon->FrontMode != GL_FILL ||
- brw->attribs.Polygon->BackMode != GL_FILL);
-
- /* BRW_NEW_METAOPS
- */
- if (brw->metaops.active)
- key.know_w_is_one = 1;
+ key.nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled);
+ key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL);
/* Make an early check for the key.
*/
@@ -123,7 +119,7 @@ static void brw_upload_vs_prog(struct brw_context *brw)
const struct brw_tracked_state brw_vs_prog = {
.dirty = {
.mesa = _NEW_TRANSFORM | _NEW_POLYGON,
- .brw = BRW_NEW_VERTEX_PROGRAM | BRW_NEW_METAOPS,
+ .brw = BRW_NEW_VERTEX_PROGRAM,
.cache = 0
},
.prepare = brw_upload_vs_prog
diff --git a/src/mesa/drivers/dri/i965/brw_vs.h b/src/mesa/drivers/dri/i965/brw_vs.h
index 22388ec99d..4a591365c9 100644
--- a/src/mesa/drivers/dri/i965/brw_vs.h
+++ b/src/mesa/drivers/dri/i965/brw_vs.h
@@ -43,7 +43,6 @@ struct brw_vs_prog_key {
GLuint program_string_id;
GLuint nr_userclip:4;
GLuint copy_edgeflag:1;
- GLuint know_w_is_one:1;
GLuint pad:26;
};
@@ -59,6 +58,7 @@ struct brw_vs_compile {
GLuint first_output;
GLuint nr_outputs;
+ GLuint first_overflow_output; /**< VERT_ATTRIB_x */
GLuint first_tmp;
GLuint last_tmp;
@@ -76,6 +76,11 @@ struct brw_vs_compile {
struct brw_reg userplane[6];
+ /** we may need up to 3 constants per instruction (if use_const_buffer) */
+ struct {
+ GLint index;
+ struct brw_reg reg;
+ } current_const[3];
};
void brw_vs_emit( struct brw_vs_compile *c );
diff --git a/src/mesa/drivers/dri/i965/brw_vs_constval.c b/src/mesa/drivers/dri/i965/brw_vs_constval.c
index 6fbac02de6..249a800bf4 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_constval.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_constval.c
@@ -39,8 +39,8 @@
*/
struct tracker {
GLboolean twoside;
- GLubyte active[PROGRAM_OUTPUT+1][128];
- GLuint size_masks[4];
+ GLubyte active[PROGRAM_OUTPUT+1][MAX_PROGRAM_TEMPS];
+ GLbitfield size_masks[4]; /**< one bit per fragment program input attrib */
};
@@ -53,8 +53,10 @@ static void set_active_component( struct tracker *t,
case PROGRAM_TEMPORARY:
case PROGRAM_INPUT:
case PROGRAM_OUTPUT:
+ assert(file < PROGRAM_OUTPUT + 1);
+ assert(index < Elements(t->active[0]));
t->active[file][index] |= active;
-
+ break;
default:
break;
}
@@ -96,7 +98,7 @@ static GLubyte get_active( struct tracker *t,
struct prog_src_register src )
{
GLuint i;
- GLubyte active = src.NegateBase; /* NOTE! */
+ GLubyte active = src.Negate; /* NOTE! */
if (src.RelAddr)
return 0xf;
@@ -108,10 +110,15 @@ static GLubyte get_active( struct tracker *t,
return active;
}
+/**
+ * Return the size (1,2,3 or 4) of the output/result for VERT_RESULT_idx.
+ */
static GLubyte get_output_size( struct tracker *t,
GLuint idx )
{
- GLubyte active = t->active[PROGRAM_OUTPUT][idx];
+ GLubyte active;
+ assert(idx < VERT_RESULT_MAX);
+ active = t->active[PROGRAM_OUTPUT][idx];
if (active & (1<<3)) return 4;
if (active & (1<<2)) return 3;
if (active & (1<<1)) return 2;
@@ -123,7 +130,7 @@ static GLubyte get_output_size( struct tracker *t,
*/
static void calc_sizes( struct tracker *t )
{
- GLuint i;
+ GLint vertRes;
if (t->twoside) {
t->active[PROGRAM_OUTPUT][VERT_RESULT_COL0] |=
@@ -133,12 +140,27 @@ static void calc_sizes( struct tracker *t )
t->active[PROGRAM_OUTPUT][VERT_RESULT_BFC1];
}
- for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
- switch (get_output_size(t, i)) {
- case 4: t->size_masks[4-1] |= 1<<i;
- case 3: t->size_masks[3-1] |= 1<<i;
- case 2: t->size_masks[2-1] |= 1<<i;
- case 1: t->size_masks[1-1] |= 1<<i;
+ /* Examine vertex program output sizes to set the size_masks[] info
+ * which describes the fragment program input sizes.
+ */
+ for (vertRes = VERT_RESULT_TEX0; vertRes < VERT_RESULT_MAX; vertRes++) {
+ GLint fragAttrib;
+
+ /* map vertex program output index to fragment program input index */
+ if (vertRes <= VERT_RESULT_TEX7)
+ fragAttrib = FRAG_ATTRIB_TEX0 + vertRes - VERT_RESULT_TEX0;
+ else if (vertRes >= VERT_RESULT_VAR0)
+ fragAttrib = FRAG_ATTRIB_VAR0 + vertRes - VERT_RESULT_VAR0;
+ else
+ continue;
+ assert(fragAttrib >= FRAG_ATTRIB_TEX0);
+ assert(fragAttrib <= FRAG_ATTRIB_MAX);
+
+ switch (get_output_size(t, vertRes)) {
+ case 4: t->size_masks[4-1] |= 1 << fragAttrib;
+ case 3: t->size_masks[3-1] |= 1 << fragAttrib;
+ case 2: t->size_masks[2-1] |= 1 << fragAttrib;
+ case 1: t->size_masks[1-1] |= 1 << fragAttrib;
break;
}
}
@@ -168,9 +190,10 @@ static GLuint get_input_size(struct brw_context *brw,
*/
static void calc_wm_input_sizes( struct brw_context *brw )
{
+ GLcontext *ctx = &brw->intel.ctx;
/* BRW_NEW_VERTEX_PROGRAM */
- struct brw_vertex_program *vp =
- (struct brw_vertex_program *)brw->vertex_program;
+ const struct brw_vertex_program *vp =
+ brw_vertex_program_const(brw->vertex_program);
/* BRW_NEW_INPUT_DIMENSIONS */
struct tracker t;
GLuint insn;
@@ -179,7 +202,7 @@ static void calc_wm_input_sizes( struct brw_context *brw )
memset(&t, 0, sizeof(t));
/* _NEW_LIGHT */
- if (brw->attribs.Light->Model.TwoSide)
+ if (ctx->Light.Model.TwoSide)
t.twoside = 1;
for (i = 0; i < VERT_ATTRIB_MAX; i++)
diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c
index 174331a765..1638ef8111 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c
@@ -38,18 +38,55 @@
#include "brw_vs.h"
+static struct brw_reg get_tmp( struct brw_vs_compile *c )
+{
+ struct brw_reg tmp = brw_vec8_grf(c->last_tmp, 0);
+
+ if (++c->last_tmp > c->prog_data.total_grf)
+ c->prog_data.total_grf = c->last_tmp;
+
+ return tmp;
+}
+
+static void release_tmp( struct brw_vs_compile *c, struct brw_reg tmp )
+{
+ if (tmp.nr == c->last_tmp-1)
+ c->last_tmp--;
+}
+
+static void release_tmps( struct brw_vs_compile *c )
+{
+ c->last_tmp = c->first_tmp;
+}
+
-/* Do things as simply as possible. Allocate and populate all regs
+/**
+ * Preallocate GRF register before code emit.
+ * Do things as simply as possible. Allocate and populate all regs
* ahead of time.
*/
static void brw_vs_alloc_regs( struct brw_vs_compile *c )
{
GLuint i, reg = 0, mrf;
- GLuint nr_params;
+ int attributes_in_vue;
+
+ /* Determine whether to use a real constant buffer or use a block
+ * of GRF registers for constants. The later is faster but only
+ * works if everything fits in the GRF.
+ * XXX this heuristic/check may need some fine tuning...
+ */
+ if (c->vp->program.Base.Parameters->NumParameters +
+ c->vp->program.Base.NumTemporaries + 20 > BRW_MAX_GRF)
+ c->vp->use_const_buffer = GL_TRUE;
+ else
+ c->vp->use_const_buffer = GL_FALSE;
+
+ /*printf("use_const_buffer = %d\n", c->vp->use_const_buffer);*/
/* r0 -- reserved as usual
*/
- c->r0 = brw_vec8_grf(reg, 0); reg++;
+ c->r0 = brw_vec8_grf(reg, 0);
+ reg++;
/* User clip planes from curbe:
*/
@@ -60,39 +97,59 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
/* Deal with curbe alignment:
*/
- reg += ((6+c->key.nr_userclip+3)/4)*2;
+ reg += ((6 + c->key.nr_userclip + 3) / 4) * 2;
}
/* Vertex program parameters from curbe:
*/
- nr_params = c->vp->program.Base.Parameters->NumParameters;
- for (i = 0; i < nr_params; i++) {
- c->regs[PROGRAM_STATE_VAR][i] = stride( brw_vec4_grf(reg+i/2, (i%2) * 4), 0, 4, 1);
- }
- reg += (nr_params+1)/2;
+ if (c->vp->use_const_buffer) {
+ /* get constants from a real constant buffer */
+ c->prog_data.curb_read_length = 0;
+ c->prog_data.nr_params = 4; /* XXX 0 causes a bug elsewhere... */
+ }
+ else {
+ /* use a section of the GRF for constants */
+ GLuint nr_params = c->vp->program.Base.Parameters->NumParameters;
+ for (i = 0; i < nr_params; i++) {
+ c->regs[PROGRAM_STATE_VAR][i] = stride( brw_vec4_grf(reg+i/2, (i%2) * 4), 0, 4, 1);
+ }
+ reg += (nr_params + 1) / 2;
+ c->prog_data.curb_read_length = reg - 1;
- c->prog_data.curb_read_length = reg - 1;
+ c->prog_data.nr_params = nr_params * 4;
+ }
/* Allocate input regs:
*/
c->nr_inputs = 0;
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- if (c->prog_data.inputs_read & (1<<i)) {
+ if (c->prog_data.inputs_read & (1 << i)) {
c->nr_inputs++;
c->regs[PROGRAM_INPUT][i] = brw_vec8_grf(reg, 0);
reg++;
}
}
+ /* If there are no inputs, we'll still be reading one attribute's worth
+ * because it's required -- see urb_read_length setting.
+ */
+ if (c->nr_inputs == 0)
+ reg++;
- /* Allocate outputs: TODO: could organize the non-position outputs
- * to go straight into message regs.
+ /* Allocate outputs. The non-position outputs go straight into message regs.
*/
c->nr_outputs = 0;
c->first_output = reg;
- mrf = 4;
+ c->first_overflow_output = 0;
+
+ if (BRW_IS_IGDNG(c->func.brw))
+ mrf = 8;
+ else
+ mrf = 4;
+
for (i = 0; i < VERT_RESULT_MAX; i++) {
- if (c->prog_data.outputs_written & (1<<i)) {
+ if (c->prog_data.outputs_written & (1 << i)) {
c->nr_outputs++;
+ assert(i < Elements(c->regs[PROGRAM_OUTPUT]));
if (i == VERT_RESULT_HPOS) {
c->regs[PROGRAM_OUTPUT][i] = brw_vec8_grf(reg, 0);
reg++;
@@ -103,8 +160,17 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
mrf++; /* just a placeholder? XXX fix later stages & remove this */
}
else {
- c->regs[PROGRAM_OUTPUT][i] = brw_message_reg(mrf);
- mrf++;
+ if (mrf < 16) {
+ c->regs[PROGRAM_OUTPUT][i] = brw_message_reg(mrf);
+ mrf++;
+ }
+ else {
+ /* too many vertex results to fit in MRF, use GRF for overflow */
+ if (!c->first_overflow_output)
+ c->first_overflow_output = i;
+ c->regs[PROGRAM_OUTPUT][i] = brw_vec8_grf(reg, 0);
+ reg++;
+ }
}
}
}
@@ -132,17 +198,24 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
reg++;
}
+ if (c->vp->use_const_buffer) {
+ for (i = 0; i < 3; i++) {
+ c->current_const[i].index = -1;
+ c->current_const[i].reg = brw_vec8_grf(reg, 0);
+ reg++;
+ }
+ }
+
for (i = 0; i < 128; i++) {
- if (c->output_regs[i].used_in_src) {
- c->output_regs[i].reg = brw_vec8_grf(reg, 0);
- reg++;
- }
+ if (c->output_regs[i].used_in_src) {
+ c->output_regs[i].reg = brw_vec8_grf(reg, 0);
+ reg++;
+ }
}
c->stack = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, reg, 0);
reg += 2;
-
-
+
/* Some opcodes need an internal temporary:
*/
c->first_tmp = reg;
@@ -152,35 +225,38 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
* urb_read_length is the number of registers read from *each*
* vertex urb, so is half the amount:
*/
- c->prog_data.urb_read_length = (c->nr_inputs+1)/2;
-
- c->prog_data.urb_entry_size = (c->nr_outputs+2+3)/4;
- c->prog_data.total_grf = reg;
-}
-
+ c->prog_data.urb_read_length = (c->nr_inputs + 1) / 2;
+ /* Setting this field to 0 leads to undefined behavior according to the
+ * the VS_STATE docs. Our VUEs will always have at least one attribute
+ * sitting in them, even if it's padding.
+ */
+ if (c->prog_data.urb_read_length == 0)
+ c->prog_data.urb_read_length = 1;
-static struct brw_reg get_tmp( struct brw_vs_compile *c )
-{
- struct brw_reg tmp = brw_vec8_grf(c->last_tmp, 0);
+ /* The VS VUEs are shared by VF (outputting our inputs) and VS, so size
+ * them to fit the biggest thing they need to.
+ */
+ attributes_in_vue = MAX2(c->nr_outputs, c->nr_inputs);
- if (++c->last_tmp > c->prog_data.total_grf)
- c->prog_data.total_grf = c->last_tmp;
+ if (BRW_IS_IGDNG(c->func.brw))
+ c->prog_data.urb_entry_size = (attributes_in_vue + 6 + 3) / 4;
+ else
+ c->prog_data.urb_entry_size = (attributes_in_vue + 2 + 3) / 4;
- return tmp;
-}
+ c->prog_data.total_grf = reg;
-static void release_tmp( struct brw_vs_compile *c, struct brw_reg tmp )
-{
- if (tmp.nr == c->last_tmp-1)
- c->last_tmp--;
-}
-
-static void release_tmps( struct brw_vs_compile *c )
-{
- c->last_tmp = c->first_tmp;
+ if (INTEL_DEBUG & DEBUG_VS) {
+ _mesa_printf("%s NumAddrRegs %d\n", __FUNCTION__, c->vp->program.Base.NumAddressRegs);
+ _mesa_printf("%s NumTemps %d\n", __FUNCTION__, c->vp->program.Base.NumTemporaries);
+ _mesa_printf("%s reg = %d\n", __FUNCTION__, reg);
+ }
}
+/**
+ * If an instruction uses a temp reg both as a src and the dest, we
+ * sometimes need to allocate an intermediate temporary.
+ */
static void unalias1( struct brw_vs_compile *c,
struct brw_reg dst,
struct brw_reg arg0,
@@ -200,6 +276,10 @@ static void unalias1( struct brw_vs_compile *c,
}
}
+/**
+ * \sa unalias2
+ * Checkes if 2-operand instruction needs an intermediate temporary.
+ */
static void unalias2( struct brw_vs_compile *c,
struct brw_reg dst,
struct brw_reg arg0,
@@ -222,6 +302,10 @@ static void unalias2( struct brw_vs_compile *c,
}
}
+/**
+ * \sa unalias2
+ * Checkes if 3-operand instruction needs an intermediate temporary.
+ */
static void unalias3( struct brw_vs_compile *c,
struct brw_reg dst,
struct brw_reg arg0,
@@ -615,6 +699,8 @@ static void emit_lit_noalias( struct brw_vs_compile *c,
}
brw_ENDIF(p, if_insn);
+
+ release_tmp(c, tmp);
}
static void emit_lrp_noalias(struct brw_vs_compile *c,
@@ -655,13 +741,84 @@ static void emit_nrm( struct brw_vs_compile *c,
}
+static struct brw_reg
+get_constant(struct brw_vs_compile *c,
+ const struct prog_instruction *inst,
+ GLuint argIndex)
+{
+ const struct prog_src_register *src = &inst->SrcReg[argIndex];
+ struct brw_compile *p = &c->func;
+ struct brw_reg const_reg;
+ struct brw_reg const2_reg;
+ const GLboolean relAddr = src->RelAddr;
+
+ assert(argIndex < 3);
+
+ if (c->current_const[argIndex].index != src->Index || relAddr) {
+ struct brw_reg addrReg = c->regs[PROGRAM_ADDRESS][0];
+
+ c->current_const[argIndex].index = src->Index;
+
+#if 0
+ printf(" fetch const[%d] for arg %d into reg %d\n",
+ src->Index, argIndex, c->current_const[argIndex].reg.nr);
+#endif
+ /* need to fetch the constant now */
+ brw_dp_READ_4_vs(p,
+ c->current_const[argIndex].reg,/* writeback dest */
+ 0, /* oword */
+ relAddr, /* relative indexing? */
+ addrReg, /* address register */
+ 16 * src->Index, /* byte offset */
+ SURF_INDEX_VERT_CONST_BUFFER /* binding table index */
+ );
+
+ if (relAddr) {
+ /* second read */
+ const2_reg = get_tmp(c);
+
+ /* use upper half of address reg for second read */
+ addrReg = stride(addrReg, 0, 4, 0);
+ addrReg.subnr = 16;
+
+ brw_dp_READ_4_vs(p,
+ const2_reg, /* writeback dest */
+ 1, /* oword */
+ relAddr, /* relative indexing? */
+ addrReg, /* address register */
+ 16 * src->Index, /* byte offset */
+ SURF_INDEX_VERT_CONST_BUFFER
+ );
+ }
+ }
+
+ const_reg = c->current_const[argIndex].reg;
+
+ if (relAddr) {
+ /* merge the two Owords into the constant register */
+ /* const_reg[7..4] = const2_reg[7..4] */
+ brw_MOV(p,
+ suboffset(stride(const_reg, 0, 4, 1), 4),
+ suboffset(stride(const2_reg, 0, 4, 1), 4));
+ release_tmp(c, const2_reg);
+ }
+ else {
+ /* replicate lower four floats into upper half (to get XYZWXYZW) */
+ const_reg = stride(const_reg, 0, 4, 0);
+ const_reg.subnr = 0;
+ }
+
+ return const_reg;
+}
+
+
+
/* TODO: relative addressing!
*/
static struct brw_reg get_reg( struct brw_vs_compile *c,
- GLuint file,
+ gl_register_file file,
GLuint index )
{
-
switch (file) {
case PROGRAM_TEMPORARY:
case PROGRAM_INPUT:
@@ -690,13 +847,17 @@ static struct brw_reg get_reg( struct brw_vs_compile *c,
}
+/**
+ * Indirect addressing: get reg[[arg] + offset].
+ */
static struct brw_reg deref( struct brw_vs_compile *c,
struct brw_reg arg,
GLint offset)
{
struct brw_compile *p = &c->func;
struct brw_reg tmp = vec4(get_tmp(c));
- struct brw_reg vp_address = retype(vec1(get_reg(c, PROGRAM_ADDRESS, 0)), BRW_REGISTER_TYPE_UW);
+ struct brw_reg addr_reg = c->regs[PROGRAM_ADDRESS][0];
+ struct brw_reg vp_address = retype(vec1(addr_reg), BRW_REGISTER_TYPE_UW);
GLuint byte_offset = arg.nr * 32 + arg.subnr + offset * 16;
struct brw_reg indirect = brw_vec4_indirect(0,0);
@@ -717,10 +878,67 @@ static struct brw_reg deref( struct brw_vs_compile *c,
brw_pop_insn_state(p);
}
+ /* NOTE: tmp not released */
return vec8(tmp);
}
+/**
+ * Get brw reg corresponding to the instruction's [argIndex] src reg.
+ * TODO: relative addressing!
+ */
+static struct brw_reg
+get_src_reg( struct brw_vs_compile *c,
+ const struct prog_instruction *inst,
+ GLuint argIndex )
+{
+ const GLuint file = inst->SrcReg[argIndex].File;
+ const GLint index = inst->SrcReg[argIndex].Index;
+ const GLboolean relAddr = inst->SrcReg[argIndex].RelAddr;
+
+ switch (file) {
+ case PROGRAM_TEMPORARY:
+ case PROGRAM_INPUT:
+ case PROGRAM_OUTPUT:
+ if (relAddr) {
+ return deref(c, c->regs[file][0], index);
+ }
+ else {
+ assert(c->regs[file][index].nr != 0);
+ return c->regs[file][index];
+ }
+
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_CONSTANT:
+ case PROGRAM_UNIFORM:
+ case PROGRAM_ENV_PARAM:
+ if (c->vp->use_const_buffer) {
+ return get_constant(c, inst, argIndex);
+ }
+ else if (relAddr) {
+ return deref(c, c->regs[PROGRAM_STATE_VAR][0], index);
+ }
+ else {
+ assert(c->regs[PROGRAM_STATE_VAR][index].nr != 0);
+ return c->regs[PROGRAM_STATE_VAR][index];
+ }
+ case PROGRAM_ADDRESS:
+ assert(index == 0);
+ return c->regs[file][index];
+
+ case PROGRAM_UNDEFINED:
+ /* this is a normal case since we loop over all three src args */
+ return brw_null_reg();
+
+ case PROGRAM_LOCAL_PARAM:
+ case PROGRAM_WRITE_ONLY:
+ default:
+ assert(0);
+ return brw_null_reg();
+ }
+}
+
+
static void emit_arl( struct brw_vs_compile *c,
struct brw_reg dst,
struct brw_reg arg0 )
@@ -732,30 +950,31 @@ static void emit_arl( struct brw_vs_compile *c,
if (need_tmp)
tmp = get_tmp(c);
- brw_RNDD(p, tmp, arg0);
- brw_MUL(p, dst, tmp, brw_imm_d(16));
+ brw_RNDD(p, tmp, arg0); /* tmp = round(arg0) */
+ brw_MUL(p, dst, tmp, brw_imm_d(16)); /* dst = tmp * 16 */
if (need_tmp)
release_tmp(c, tmp);
}
-/* Will return mangled results for SWZ op. The emit_swz() function
+/**
+ * Return the brw reg for the given instruction's src argument.
+ * Will return mangled results for SWZ op. The emit_swz() function
* ignores this result and recalculates taking extended swizzles into
* account.
*/
static struct brw_reg get_arg( struct brw_vs_compile *c,
- struct prog_src_register *src )
+ const struct prog_instruction *inst,
+ GLuint argIndex )
{
+ const struct prog_src_register *src = &inst->SrcReg[argIndex];
struct brw_reg reg;
if (src->File == PROGRAM_UNDEFINED)
return brw_null_reg();
- if (src->RelAddr)
- reg = deref(c, c->regs[PROGRAM_STATE_VAR][0], src->Index);
- else
- reg = get_reg(c, src->File, src->Index);
+ reg = get_src_reg(c, inst, argIndex);
/* Convert 3-bit swizzle to 2-bit.
*/
@@ -766,16 +985,38 @@ static struct brw_reg get_arg( struct brw_vs_compile *c,
/* Note this is ok for non-swizzle instructions:
*/
- reg.negate = src->NegateBase ? 1 : 0;
+ reg.negate = src->Negate ? 1 : 0;
return reg;
}
+/**
+ * Get brw register for the given program dest register.
+ */
static struct brw_reg get_dst( struct brw_vs_compile *c,
struct prog_dst_register dst )
{
- struct brw_reg reg = get_reg(c, dst.File, dst.Index);
+ struct brw_reg reg;
+
+ switch (dst.File) {
+ case PROGRAM_TEMPORARY:
+ case PROGRAM_OUTPUT:
+ assert(c->regs[dst.File][dst.Index].nr != 0);
+ reg = c->regs[dst.File][dst.Index];
+ break;
+ case PROGRAM_ADDRESS:
+ assert(dst.Index == 0);
+ reg = c->regs[dst.File][dst.Index];
+ break;
+ case PROGRAM_UNDEFINED:
+ /* we may hit this for OPCODE_END, OPCODE_KIL, etc */
+ reg = brw_null_reg();
+ break;
+ default:
+ assert(0);
+ reg = brw_null_reg();
+ }
reg.dw1.bits.writemask = dst.WriteMask;
@@ -785,14 +1026,16 @@ static struct brw_reg get_dst( struct brw_vs_compile *c,
static void emit_swz( struct brw_vs_compile *c,
struct brw_reg dst,
- struct prog_src_register src )
+ const struct prog_instruction *inst)
{
+ const GLuint argIndex = 0;
+ const struct prog_src_register src = inst->SrcReg[argIndex];
struct brw_compile *p = &c->func;
GLuint zeros_mask = 0;
GLuint ones_mask = 0;
GLuint src_mask = 0;
GLubyte src_swz[4];
- GLboolean need_tmp = (src.NegateBase &&
+ GLboolean need_tmp = (src.Negate &&
dst.file != BRW_GENERAL_REGISTER_FILE);
struct brw_reg tmp = dst;
GLuint i;
@@ -826,10 +1069,7 @@ static void emit_swz( struct brw_vs_compile *c,
if (src_mask) {
struct brw_reg arg0;
- if (src.RelAddr)
- arg0 = deref(c, c->regs[PROGRAM_STATE_VAR][0], src.Index);
- else
- arg0 = get_reg(c, src.File, src.Index);
+ arg0 = get_src_reg(c, inst, argIndex);
arg0 = brw_swizzle(arg0,
src_swz[0], src_swz[1],
@@ -844,8 +1084,8 @@ static void emit_swz( struct brw_vs_compile *c,
if (ones_mask)
brw_MOV(p, brw_writemask(tmp, ones_mask), brw_imm_f(1));
- if (src.NegateBase)
- brw_MOV(p, brw_writemask(tmp, src.NegateBase), negate(tmp));
+ if (src.Negate)
+ brw_MOV(p, brw_writemask(tmp, src.Negate), negate(tmp));
if (need_tmp) {
brw_MOV(p, dst, tmp);
@@ -863,6 +1103,8 @@ static void emit_vertex_write( struct brw_vs_compile *c)
struct brw_reg m0 = brw_message_reg(0);
struct brw_reg pos = c->regs[PROGRAM_OUTPUT][VERT_RESULT_HPOS];
struct brw_reg ndc;
+ int eot;
+ GLuint len_vertext_header = 2;
if (c->key.copy_edgeflag) {
brw_MOV(p,
@@ -871,21 +1113,17 @@ static void emit_vertex_write( struct brw_vs_compile *c)
}
/* Build ndc coords */
- if (!c->key.know_w_is_one) {
- ndc = get_tmp(c);
- emit_math1(c, BRW_MATH_FUNCTION_INV, ndc, brw_swizzle1(pos, 3), BRW_MATH_PRECISION_FULL);
- brw_MUL(p, brw_writemask(ndc, WRITEMASK_XYZ), pos, ndc);
- }
- else {
- ndc = pos;
- }
+ ndc = get_tmp(c);
+ /* ndc = 1.0 / pos.w */
+ emit_math1(c, BRW_MATH_FUNCTION_INV, ndc, brw_swizzle1(pos, 3), BRW_MATH_PRECISION_FULL);
+ /* ndc.xyz = pos * ndc */
+ brw_MUL(p, brw_writemask(ndc, WRITEMASK_XYZ), pos, ndc);
/* Update the header for point size, user clipping flags, and -ve rhw
* workaround.
*/
if ((c->prog_data.outputs_written & (1<<VERT_RESULT_PSIZ)) ||
- c->key.nr_userclip ||
- (!BRW_IS_G4X(p->brw) && !c->key.know_w_is_one))
+ c->key.nr_userclip || BRW_IS_965(p->brw))
{
struct brw_reg header1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
GLuint i;
@@ -916,7 +1154,7 @@ static void emit_vertex_write( struct brw_vs_compile *c)
* Later, clipping will detect ucp[6] and ensure the primitive is
* clipped against all fixed planes.
*/
- if (!BRW_IS_G4X(p->brw) && !c->key.know_w_is_one) {
+ if (BRW_IS_965(p->brw)) {
brw_CMP(p,
vec8(brw_null_reg()),
BRW_CONDITIONAL_L,
@@ -943,7 +1181,23 @@ static void emit_vertex_write( struct brw_vs_compile *c)
*/
brw_set_access_mode(p, BRW_ALIGN_1);
brw_MOV(p, offset(m0, 2), ndc);
- brw_MOV(p, offset(m0, 3), pos);
+
+ if (BRW_IS_IGDNG(p->brw)) {
+ /* There are 20 DWs (D0-D19) in VUE vertex header on IGDNG */
+ brw_MOV(p, offset(m0, 3), pos); /* a portion of vertex header */
+ /* m4, m5 contain the distances from vertex to the user clip planeXXX.
+ * Seems it is useless for us.
+ * m6 is used for aligning, so that the remainder of vertex element is
+ * reg-aligned.
+ */
+ brw_MOV(p, offset(m0, 7), pos); /* the remainder of vertex element */
+ len_vertext_header = 6;
+ } else {
+ brw_MOV(p, offset(m0, 3), pos);
+ len_vertext_header = 2;
+ }
+
+ eot = (c->first_overflow_output == 0);
brw_urb_WRITE(p,
brw_null_reg(), /* dest */
@@ -951,62 +1205,126 @@ static void emit_vertex_write( struct brw_vs_compile *c)
c->r0, /* src */
0, /* allocate */
1, /* used */
- c->nr_outputs + 3, /* msg len */
+ MIN2(c->nr_outputs + 1 + len_vertext_header, (BRW_MAX_MRF-1)), /* msg len */
0, /* response len */
- 1, /* eot */
- 1, /* writes complete */
+ eot, /* eot */
+ eot, /* writes complete */
0, /* urb destination offset */
BRW_URB_SWIZZLE_INTERLEAVE);
+
+ if (c->first_overflow_output > 0) {
+ /* Not all of the vertex outputs/results fit into the MRF.
+ * Move the overflowed attributes from the GRF to the MRF and
+ * issue another brw_urb_WRITE().
+ */
+ /* XXX I'm not 100% sure about which MRF regs to use here. Starting
+ * at mrf[4] atm...
+ */
+ GLuint i, mrf = 0;
+ for (i = c->first_overflow_output; i < VERT_RESULT_MAX; i++) {
+ if (c->prog_data.outputs_written & (1 << i)) {
+ /* move from GRF to MRF */
+ brw_MOV(p, brw_message_reg(4+mrf), c->regs[PROGRAM_OUTPUT][i]);
+ mrf++;
+ }
+ }
+
+ brw_urb_WRITE(p,
+ brw_null_reg(), /* dest */
+ 4, /* starting mrf reg nr */
+ c->r0, /* src */
+ 0, /* allocate */
+ 1, /* used */
+ mrf+1, /* msg len */
+ 0, /* response len */
+ 1, /* eot */
+ 1, /* writes complete */
+ BRW_MAX_MRF-1, /* urb destination offset */
+ BRW_URB_SWIZZLE_INTERLEAVE);
+ }
}
+/**
+ * Called after code generation to resolve subroutine calls and the
+ * END instruction.
+ * \param end_inst points to brw code for END instruction
+ * \param last_inst points to last instruction emitted before vertex write
+ */
static void
-post_vs_emit( struct brw_vs_compile *c, struct brw_instruction *end_inst )
+post_vs_emit( struct brw_vs_compile *c,
+ struct brw_instruction *end_inst,
+ struct brw_instruction *last_inst )
{
- GLuint nr_insns = c->vp->program.Base.NumInstructions;
- GLuint insn, target_insn;
- struct prog_instruction *inst1, *inst2;
- struct brw_instruction *brw_inst1, *brw_inst2;
- int offset;
- for (insn = 0; insn < nr_insns; insn++) {
- inst1 = &c->vp->program.Base.Instructions[insn];
- brw_inst1 = inst1->Data;
- switch (inst1->Opcode) {
- case OPCODE_CAL:
- case OPCODE_BRA:
- target_insn = inst1->BranchTarget;
- inst2 = &c->vp->program.Base.Instructions[target_insn];
- brw_inst2 = inst2->Data;
- offset = brw_inst2 - brw_inst1;
- brw_set_src1(brw_inst1, brw_imm_d(offset*16));
- break;
- case OPCODE_END:
- offset = end_inst - brw_inst1;
- brw_set_src1(brw_inst1, brw_imm_d(offset*16));
- break;
- default:
- break;
- }
+ GLint offset;
+
+ brw_resolve_cals(&c->func);
+
+ /* patch up the END code to jump past subroutines, etc */
+ offset = last_inst - end_inst;
+ if (offset > 1) {
+ brw_set_src1(end_inst, brw_imm_d(offset * 16));
+ } else {
+ end_inst->header.opcode = BRW_OPCODE_NOP;
+ }
+}
+
+static uint32_t
+get_predicate(const struct prog_instruction *inst)
+{
+ if (inst->DstReg.CondMask == COND_TR)
+ return BRW_PREDICATE_NONE;
+
+ /* All of GLSL only produces predicates for COND_NE and one channel per
+ * vector. Fail badly if someone starts doing something else, as it might
+ * mean infinite looping or something.
+ *
+ * We'd like to support all the condition codes, but our hardware doesn't
+ * quite match the Mesa IR, which is modeled after the NV extensions. For
+ * those, the instruction may update the condition codes or not, then any
+ * later instruction may use one of those condition codes. For gen4, the
+ * instruction may update the flags register based on one of the condition
+ * codes output by the instruction, and then further instructions may
+ * predicate on that. We can probably support this, but it won't
+ * necessarily be easy.
+ */
+ assert(inst->DstReg.CondMask == COND_NE);
+
+ switch (inst->DstReg.CondSwizzle) {
+ case SWIZZLE_XXXX:
+ return BRW_PREDICATE_ALIGN16_REPLICATE_X;
+ case SWIZZLE_YYYY:
+ return BRW_PREDICATE_ALIGN16_REPLICATE_Y;
+ case SWIZZLE_ZZZZ:
+ return BRW_PREDICATE_ALIGN16_REPLICATE_Z;
+ case SWIZZLE_WWWW:
+ return BRW_PREDICATE_ALIGN16_REPLICATE_W;
+ default:
+ _mesa_problem(NULL, "Unexpected predicate: 0x%08x\n",
+ inst->DstReg.CondMask);
+ return BRW_PREDICATE_NORMAL;
}
}
-/* Emit the fragment program instructions here.
+/* Emit the vertex program instructions here.
*/
void brw_vs_emit(struct brw_vs_compile *c )
{
-#define MAX_IFSN 32
+#define MAX_IF_DEPTH 32
+#define MAX_LOOP_DEPTH 32
struct brw_compile *p = &c->func;
- GLuint nr_insns = c->vp->program.Base.NumInstructions;
- GLuint insn, if_insn = 0;
- struct brw_instruction *end_inst;
- struct brw_instruction *if_inst[MAX_IFSN];
- struct brw_indirect stack_index = brw_indirect(0, 0);
-
+ struct brw_context *brw = p->brw;
+ const GLuint nr_insns = c->vp->program.Base.NumInstructions;
+ GLuint insn, if_depth = 0, loop_depth = 0;
+ GLuint end_offset = 0;
+ struct brw_instruction *end_inst, *last_inst;
+ struct brw_instruction *if_inst[MAX_IF_DEPTH], *loop_inst[MAX_LOOP_DEPTH];
+ const struct brw_indirect stack_index = brw_indirect(0, 0);
GLuint index;
GLuint file;
if (INTEL_DEBUG & DEBUG_VS) {
- _mesa_printf("vs-emit:\n");
+ _mesa_printf("vs-mesa:\n");
_mesa_print_program(&c->vp->program.Base);
_mesa_printf("\n");
}
@@ -1035,22 +1353,26 @@ void brw_vs_emit(struct brw_vs_compile *c )
for (insn = 0; insn < nr_insns; insn++) {
- struct prog_instruction *inst = &c->vp->program.Base.Instructions[insn];
+ const struct prog_instruction *inst = &c->vp->program.Base.Instructions[insn];
struct brw_reg args[3], dst;
GLuint i;
+#if 0
+ printf("%d: ", insn);
+ _mesa_print_instruction(inst);
+#endif
+
/* Get argument regs. SWZ is special and does this itself.
*/
- inst->Data = &p->store[p->nr_insn];
if (inst->Opcode != OPCODE_SWZ)
for (i = 0; i < 3; i++) {
- struct prog_src_register *src = &inst->SrcReg[i];
+ const struct prog_src_register *src = &inst->SrcReg[i];
index = src->Index;
file = src->File;
- if (file == PROGRAM_OUTPUT&&c->output_regs[index].used_in_src)
+ if (file == PROGRAM_OUTPUT && c->output_regs[index].used_in_src)
args[i] = c->output_regs[index].reg;
else
- args[i] = get_arg(c, src);
+ args[i] = get_arg(c, inst, i);
}
/* Get dest regs. Note that it is possible for a reg to be both
@@ -1178,7 +1500,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
/* The args[0] value can't be used here as it won't have
* correctly encoded the full swizzle:
*/
- emit_swz(c, dst, inst->SrcReg[0] );
+ emit_swz(c, dst, inst);
break;
case OPCODE_TRUNC:
/* round toward zero */
@@ -1188,20 +1510,61 @@ void brw_vs_emit(struct brw_vs_compile *c )
emit_xpd(p, dst, args[0], args[1]);
break;
case OPCODE_IF:
- assert(if_insn < MAX_IFSN);
- if_inst[if_insn++] = brw_IF(p, BRW_EXECUTE_8);
+ assert(if_depth < MAX_IF_DEPTH);
+ if_inst[if_depth] = brw_IF(p, BRW_EXECUTE_8);
+ /* Note that brw_IF smashes the predicate_control field. */
+ if_inst[if_depth]->header.predicate_control = get_predicate(inst);
+ if_depth++;
break;
case OPCODE_ELSE:
- if_inst[if_insn-1] = brw_ELSE(p, if_inst[if_insn-1]);
+ if_inst[if_depth-1] = brw_ELSE(p, if_inst[if_depth-1]);
break;
case OPCODE_ENDIF:
- assert(if_insn > 0);
- brw_ENDIF(p, if_inst[--if_insn]);
+ assert(if_depth > 0);
+ brw_ENDIF(p, if_inst[--if_depth]);
break;
+ case OPCODE_BGNLOOP:
+ loop_inst[loop_depth++] = brw_DO(p, BRW_EXECUTE_8);
+ break;
+ case OPCODE_BRK:
+ brw_set_predicate_control(p, get_predicate(inst));
+ brw_BREAK(p);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ break;
+ case OPCODE_CONT:
+ brw_set_predicate_control(p, get_predicate(inst));
+ brw_CONT(p);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ break;
+ case OPCODE_ENDLOOP:
+ {
+ struct brw_instruction *inst0, *inst1;
+ GLuint br = 1;
+
+ loop_depth--;
+
+ if (BRW_IS_IGDNG(brw))
+ br = 2;
+
+ inst0 = inst1 = brw_WHILE(p, loop_inst[loop_depth]);
+ /* patch all the BREAK/CONT instructions from last BEGINLOOP */
+ while (inst0 > loop_inst[loop_depth]) {
+ inst0--;
+ if (inst0->header.opcode == BRW_OPCODE_BREAK) {
+ inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1);
+ inst0->bits3.if_else.pop_count = 0;
+ }
+ else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) {
+ inst0->bits3.if_else.jump_count = br * (inst1 - inst0);
+ inst0->bits3.if_else.pop_count = 0;
+ }
+ }
+ }
+ break;
case OPCODE_BRA:
- brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+ brw_set_predicate_control(p, get_predicate(inst));
brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
- brw_set_predicate_control_flag_value(p, 0xff);
+ brw_set_predicate_control(p, BRW_PREDICATE_NONE);
break;
case OPCODE_CAL:
brw_set_access_mode(p, BRW_ALIGN_1);
@@ -1209,7 +1572,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
brw_set_access_mode(p, BRW_ALIGN_16);
brw_ADD(p, get_addr_reg(stack_index),
get_addr_reg(stack_index), brw_imm_d(4));
- inst->Data = &p->store[p->nr_insn];
+ brw_save_call(p, inst->Comment, p->nr_insn);
brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
break;
case OPCODE_RET:
@@ -1218,14 +1581,23 @@ void brw_vs_emit(struct brw_vs_compile *c )
brw_set_access_mode(p, BRW_ALIGN_1);
brw_MOV(p, brw_ip_reg(), deref_1d(stack_index, 0));
brw_set_access_mode(p, BRW_ALIGN_16);
+ break;
case OPCODE_END:
+ end_offset = p->nr_insn;
+ /* this instruction will get patched later to jump past subroutine
+ * code, etc.
+ */
brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
break;
case OPCODE_PRINT:
+ /* no-op */
+ break;
case OPCODE_BGNSUB:
+ brw_save_label(p, inst->Comment, p->nr_insn);
+ break;
case OPCODE_ENDSUB:
- /* no-op instructions */
- break;
+ /* no-op */
+ break;
default:
_mesa_problem(NULL, "Unsupported opcode %i (%s) in vertex shader",
inst->Opcode, inst->Opcode < MAX_OPCODE ?
@@ -1233,6 +1605,19 @@ void brw_vs_emit(struct brw_vs_compile *c )
"unknown");
}
+ /* Set the predication update on the last instruction of the native
+ * instruction sequence.
+ *
+ * This would be problematic if it was set on a math instruction,
+ * but that shouldn't be the case with the current GLSL compiler.
+ */
+ if (inst->CondUpdate) {
+ struct brw_instruction *hw_insn = &p->store[p->nr_insn - 1];
+
+ assert(hw_insn->header.destreg__conditionalmod == 0);
+ hw_insn->header.destreg__conditionalmod = BRW_CONDITIONAL_NZ;
+ }
+
if ((inst->DstReg.File == PROGRAM_OUTPUT)
&& (inst->DstReg.Index != VERT_RESULT_HPOS)
&& c->output_regs[inst->DstReg.Index].used_in_src) {
@@ -1263,9 +1648,20 @@ void brw_vs_emit(struct brw_vs_compile *c )
release_tmps(c);
}
- end_inst = &p->store[p->nr_insn];
+ end_inst = &p->store[end_offset];
+ last_inst = &p->store[p->nr_insn];
+
+ /* The END instruction will be patched to jump to this code */
emit_vertex_write(c);
- post_vs_emit(c, end_inst);
- for (insn = 0; insn < nr_insns; insn++)
- c->vp->program.Base.Instructions[insn].Data = NULL;
+
+ post_vs_emit(c, end_inst, last_inst);
+
+ if (INTEL_DEBUG & DEBUG_VS) {
+ int i;
+
+ _mesa_printf("vs-native:\n");
+ for (i = 0; i < p->nr_insn; i++)
+ brw_disasm(stderr, &p->store[i]);
+ _mesa_printf("\n");
+ }
}
diff --git a/src/mesa/drivers/dri/i965/brw_vs_state.c b/src/mesa/drivers/dri/i965/brw_vs_state.c
index 942581696d..d790ab6555 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_state.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_state.c
@@ -44,11 +44,15 @@ struct brw_vs_unit_key {
unsigned int curbe_offset;
unsigned int nr_urb_entries, urb_size;
+
+ unsigned int nr_surfaces;
};
static void
vs_unit_populate_key(struct brw_context *brw, struct brw_vs_unit_key *key)
{
+ GLcontext *ctx = &brw->intel.ctx;
+
memset(key, 0, sizeof(*key));
/* CACHE_NEW_VS_PROG */
@@ -60,8 +64,11 @@ vs_unit_populate_key(struct brw_context *brw, struct brw_vs_unit_key *key)
key->nr_urb_entries = brw->urb.nr_vs_entries;
key->urb_size = brw->urb.vsize;
+ /* BRW_NEW_NR_VS_SURFACES */
+ key->nr_surfaces = brw->vs.nr_surfaces;
+
/* BRW_NEW_CURBE_OFFSETS, _NEW_TRANSFORM */
- if (brw->attribs.Transform->ClipPlanesEnabled) {
+ if (ctx->Transform.ClipPlanesEnabled) {
/* Note that we read in the userclip planes as well, hence
* clip_start:
*/
@@ -90,16 +97,28 @@ vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key)
* brw_urb_WRITE() results.
*/
vs.thread1.single_program_flow = 0;
+
+ if (BRW_IS_IGDNG(brw))
+ vs.thread1.binding_table_entry_count = 0; /* hardware requirement */
+ else
+ vs.thread1.binding_table_entry_count = key->nr_surfaces;
+
vs.thread3.urb_entry_read_length = key->urb_entry_read_length;
vs.thread3.const_urb_entry_read_length = key->curb_entry_read_length;
vs.thread3.dispatch_grf_start_reg = 1;
vs.thread3.urb_entry_read_offset = 0;
vs.thread3.const_urb_entry_read_offset = key->curbe_offset * 2;
- vs.thread4.nr_urb_entries = key->nr_urb_entries;
+ if (BRW_IS_IGDNG(brw))
+ vs.thread4.nr_urb_entries = key->nr_urb_entries >> 2;
+ else
+ vs.thread4.nr_urb_entries = key->nr_urb_entries;
+
vs.thread4.urb_entry_allocation_size = key->urb_size - 1;
- if (BRW_IS_G4X(brw))
+ if (BRW_IS_IGDNG(brw))
+ chipset_max_threads = 72;
+ else if (BRW_IS_G4X(brw))
chipset_max_threads = 32;
else
chipset_max_threads = 16;
@@ -111,6 +130,8 @@ vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key)
/* No samplers for ARB_vp programs:
*/
+ /* It has to be set to 0 for IGDNG
+ */
vs.vs5.sampler_count = 0;
if (INTEL_DEBUG & DEBUG_STATS)
@@ -156,6 +177,7 @@ const struct brw_tracked_state brw_vs_unit = {
.dirty = {
.mesa = _NEW_TRANSFORM,
.brw = (BRW_NEW_CURBE_OFFSETS |
+ BRW_NEW_NR_VS_SURFACES |
BRW_NEW_URB_FENCE),
.cache = CACHE_NEW_VS_PROG
},
diff --git a/src/mesa/drivers/dri/i965/brw_vs_surface_state.c b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c
new file mode 100644
index 0000000000..89f47522a1
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c
@@ -0,0 +1,226 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/mtypes.h"
+#include "main/texformat.h"
+#include "main/texstore.h"
+#include "shader/prog_parameter.h"
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+
+/* Creates a new VS constant buffer reflecting the current VS program's
+ * constants, if needed by the VS program.
+ *
+ * Otherwise, constants go through the CURBEs using the brw_constant_buffer
+ * state atom.
+ */
+static drm_intel_bo *
+brw_vs_update_constant_buffer(struct brw_context *brw)
+{
+ struct intel_context *intel = &brw->intel;
+ struct brw_vertex_program *vp =
+ (struct brw_vertex_program *) brw->vertex_program;
+ const struct gl_program_parameter_list *params = vp->program.Base.Parameters;
+ const int size = params->NumParameters * 4 * sizeof(GLfloat);
+ drm_intel_bo *const_buffer;
+
+ /* BRW_NEW_VERTEX_PROGRAM */
+ if (!vp->use_const_buffer)
+ return NULL;
+
+ const_buffer = drm_intel_bo_alloc(intel->bufmgr, "vp_const_buffer",
+ size, 64);
+
+ /* _NEW_PROGRAM_CONSTANTS */
+ dri_bo_subdata(const_buffer, 0, size, params->ParameterValues);
+
+ return const_buffer;
+}
+
+/**
+ * Update the surface state for a VS constant buffer.
+ *
+ * Sets brw->vs.surf_bo[surf] and brw->vp->const_buffer.
+ */
+static void
+brw_update_vs_constant_surface( GLcontext *ctx,
+ GLuint surf)
+{
+ struct brw_context *brw = brw_context(ctx);
+ struct brw_surface_key key;
+ struct brw_vertex_program *vp =
+ (struct brw_vertex_program *) brw->vertex_program;
+ const struct gl_program_parameter_list *params = vp->program.Base.Parameters;
+
+ assert(surf == 0);
+
+ /* If we're in this state update atom, we need to update VS constants, so
+ * free the old buffer and create a new one for the new contents.
+ */
+ dri_bo_unreference(vp->const_buffer);
+ vp->const_buffer = brw_vs_update_constant_buffer(brw);
+
+ /* If there's no constant buffer, then no surface BO is needed to point at
+ * it.
+ */
+ if (vp->const_buffer == 0) {
+ drm_intel_bo_unreference(brw->vs.surf_bo[surf]);
+ brw->vs.surf_bo[surf] = NULL;
+ return;
+ }
+
+ memset(&key, 0, sizeof(key));
+
+ key.format = MESA_FORMAT_RGBA_FLOAT32;
+ key.internal_format = GL_RGBA;
+ key.bo = vp->const_buffer;
+ key.depthmode = GL_NONE;
+ key.pitch = params->NumParameters;
+ key.width = params->NumParameters;
+ key.height = 1;
+ key.depth = 1;
+ key.cpp = 16;
+
+ /*
+ printf("%s:\n", __FUNCTION__);
+ printf(" width %d height %d depth %d cpp %d pitch %d\n",
+ key.width, key.height, key.depth, key.cpp, key.pitch);
+ */
+
+ drm_intel_bo_unreference(brw->vs.surf_bo[surf]);
+ brw->vs.surf_bo[surf] = brw_search_cache(&brw->surface_cache,
+ BRW_SS_SURFACE,
+ &key, sizeof(key),
+ &key.bo, key.bo ? 1 : 0,
+ NULL);
+ if (brw->vs.surf_bo[surf] == NULL) {
+ brw->vs.surf_bo[surf] = brw_create_constant_surface(brw, &key);
+ }
+}
+
+
+/**
+ * Constructs the binding table for the VS surface state.
+ */
+static dri_bo *
+brw_vs_get_binding_table(struct brw_context *brw)
+{
+ dri_bo *bind_bo;
+
+ bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
+ NULL, 0,
+ brw->vs.surf_bo, BRW_VS_MAX_SURF,
+ NULL);
+
+ if (bind_bo == NULL) {
+ GLuint data_size = BRW_VS_MAX_SURF * sizeof(GLuint);
+ uint32_t *data = malloc(data_size);
+ int i;
+
+ for (i = 0; i < BRW_VS_MAX_SURF; i++)
+ if (brw->vs.surf_bo[i])
+ data[i] = brw->vs.surf_bo[i]->offset;
+ else
+ data[i] = 0;
+
+ bind_bo = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
+ NULL, 0,
+ brw->vs.surf_bo, BRW_VS_MAX_SURF,
+ data, data_size,
+ NULL, NULL);
+
+ /* Emit binding table relocations to surface state */
+ for (i = 0; i < BRW_VS_MAX_SURF; i++) {
+ if (brw->vs.surf_bo[i] != NULL) {
+ /* The presumed offsets were set in the data values for
+ * brw_upload_cache.
+ */
+ drm_intel_bo_emit_reloc(bind_bo, i * 4,
+ brw->vs.surf_bo[i], 0,
+ I915_GEM_DOMAIN_INSTRUCTION, 0);
+ }
+ }
+
+ free(data);
+ }
+
+ return bind_bo;
+}
+
+/**
+ * Vertex shader surfaces (constant buffer).
+ *
+ * This consumes the state updates for the constant buffer needing
+ * to be updated, and produces BRW_NEW_NR_VS_SURFACES for the VS unit and
+ * CACHE_NEW_SURF_BIND for the binding table upload.
+ */
+static void prepare_vs_surfaces(struct brw_context *brw )
+{
+ GLcontext *ctx = &brw->intel.ctx;
+ int i;
+ int nr_surfaces = 0;
+
+ brw_update_vs_constant_surface(ctx, SURF_INDEX_VERT_CONST_BUFFER);
+
+ for (i = 0; i < BRW_VS_MAX_SURF; i++) {
+ if (brw->vs.surf_bo[i] != NULL) {
+ nr_surfaces = i + 1;
+ }
+ }
+
+ if (brw->vs.nr_surfaces != nr_surfaces) {
+ brw->state.dirty.brw |= BRW_NEW_NR_VS_SURFACES;
+ brw->vs.nr_surfaces = nr_surfaces;
+ }
+
+ /* Note that we don't end up updating the bind_bo if we don't have a
+ * surface to be pointing at. This should be relatively harmless, as it
+ * just slightly increases our working set size.
+ */
+ if (brw->vs.nr_surfaces != 0) {
+ dri_bo_unreference(brw->vs.bind_bo);
+ brw->vs.bind_bo = brw_vs_get_binding_table(brw);
+ }
+}
+
+const struct brw_tracked_state brw_vs_surfaces = {
+ .dirty = {
+ .mesa = (_NEW_PROGRAM_CONSTANTS),
+ .brw = (BRW_NEW_VERTEX_PROGRAM),
+ .cache = 0
+ },
+ .prepare = prepare_vs_surfaces,
+};
+
+
+
diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c
index f7293ef423..ac11790151 100644
--- a/src/mesa/drivers/dri/i965/brw_vtbl.c
+++ b/src/mesa/drivers/dri/i965/brw_vtbl.c
@@ -23,14 +23,12 @@
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- **********************************************************************/
- /*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-
+**********************************************************************/
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
#include "main/glheader.h"
#include "main/mtypes.h"
@@ -44,12 +42,11 @@
#include "brw_context.h"
#include "brw_defines.h"
#include "brw_state.h"
-
#include "brw_draw.h"
#include "brw_state.h"
#include "brw_fallback.h"
#include "brw_vs.h"
-#include <stdarg.h>
+
static void
dri_bo_release(dri_bo **bo)
@@ -58,27 +55,31 @@ dri_bo_release(dri_bo **bo)
*bo = NULL;
}
-/* called from intelDestroyContext()
+
+/**
+ * called from intelDestroyContext()
*/
static void brw_destroy_context( struct intel_context *intel )
{
struct brw_context *brw = brw_context(&intel->ctx);
int i;
- brw_destroy_metaops(brw);
brw_destroy_state(brw);
brw_draw_destroy( brw );
+ _mesa_free(brw->wm.compile_data);
+
brw_FrameBufferTexDestroy( brw );
- for (i = 0; i < brw->state.nr_draw_regions; i++)
- intel_region_release(&brw->state.draw_regions[i]);
- brw->state.nr_draw_regions = 0;
+ 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->gs.prog_bo);
dri_bo_release(&brw->gs.state_bo);
dri_bo_release(&brw->clip.prog_bo);
@@ -92,6 +93,7 @@ static void brw_destroy_context( struct intel_context *intel )
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->cc.prog_bo);
@@ -99,37 +101,46 @@ static void brw_destroy_context( struct intel_context *intel )
dri_bo_release(&brw->cc.vp_bo);
}
-/* called from intelDrawBuffer()
+
+/**
+ * called from intelDrawBuffer()
*/
static void brw_set_draw_region( struct intel_context *intel,
- struct intel_region *draw_regions[],
- struct intel_region *depth_region,
- GLuint num_regions)
+ struct intel_region *color_regions[],
+ struct intel_region *depth_region,
+ GLuint num_color_regions)
{
struct brw_context *brw = brw_context(&intel->ctx);
- int i;
+ 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_draw_regions; i++)
- intel_region_release(&brw->state.draw_regions[i]);
+ 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);
- for (i = 0; i < num_regions; i++)
- intel_region_reference(&brw->state.draw_regions[i], draw_regions[i]);
+
+ /* 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_draw_regions = num_regions;
+ brw->state.nr_color_regions = num_color_regions;
}
-/* called from intel_batchbuffer_flush and children before sending a
+
+/**
+ * called from intel_batchbuffer_flush and children before sending a
* batchbuffer off.
*/
static void brw_finish_batch(struct intel_context *intel)
{
struct brw_context *brw = brw_context(&intel->ctx);
-
brw_emit_query_end(brw);
}
-/* called from intelFlushBatchLocked
+
+/**
+ * called from intelFlushBatchLocked
*/
static void brw_new_batch( struct intel_context *intel )
{
@@ -160,39 +171,12 @@ static void brw_new_batch( struct intel_context *intel )
}
}
-static void brw_note_fence( struct intel_context *intel,
- GLuint fence )
-{
- brw_context(&intel->ctx)->state.dirty.brw |= BRW_NEW_FENCE;
-}
-
-static void brw_note_unlock( struct intel_context *intel )
-{
- struct brw_context *brw = brw_context(&intel->ctx);
-
- brw_state_cache_check_size(brw);
-}
-
-
-void brw_do_flush( struct brw_context *brw,
- GLuint flags )
-{
- struct brw_mi_flush flush;
- memset(&flush, 0, sizeof(flush));
- flush.opcode = CMD_MI_FLUSH;
- flush.flags = flags;
- BRW_BATCH_STRUCT(brw, &flush);
-}
-
-static void brw_emit_flush( struct intel_context *intel,
- GLuint unused )
+static void brw_note_fence( struct intel_context *intel, GLuint fence )
{
- brw_do_flush(brw_context(&intel->ctx),
- BRW_FLUSH_STATE_CACHE|BRW_FLUSH_READ_CACHE);
+ brw_context(&intel->ctx)->state.dirty.brw |= BRW_NEW_FENCE;
}
-
/* called from intelWaitForIdle() and intelFlush()
*
* For now, just flush everything. Could be smarter later.
@@ -202,10 +186,11 @@ static GLuint brw_flush_cmd( void )
struct brw_mi_flush flush;
flush.opcode = CMD_MI_FLUSH;
flush.pad = 0;
- flush.flags = BRW_FLUSH_READ_CACHE | BRW_FLUSH_STATE_CACHE;
+ flush.flags = BRW_FLUSH_STATE_CACHE;
return *(GLuint *)&flush;
}
+
static void brw_invalidate_state( struct intel_context *intel, GLuint new_state )
{
/* nothing */
@@ -215,20 +200,17 @@ static void brw_invalidate_state( struct intel_context *intel, GLuint new_state
void brwInitVtbl( struct brw_context *brw )
{
brw->intel.vtbl.check_vertex_size = 0;
- brw->intel.vtbl.emit_state = 0;
- brw->intel.vtbl.reduced_primitive_state = 0;
+ brw->intel.vtbl.emit_state = 0;
+ brw->intel.vtbl.reduced_primitive_state = 0;
brw->intel.vtbl.render_start = 0;
- brw->intel.vtbl.update_texture_state = 0;
+ brw->intel.vtbl.update_texture_state = 0;
- brw->intel.vtbl.invalidate_state = brw_invalidate_state;
- brw->intel.vtbl.note_fence = brw_note_fence;
- brw->intel.vtbl.note_unlock = brw_note_unlock;
+ brw->intel.vtbl.invalidate_state = brw_invalidate_state;
+ brw->intel.vtbl.note_fence = brw_note_fence;
brw->intel.vtbl.new_batch = brw_new_batch;
brw->intel.vtbl.finish_batch = brw_finish_batch;
brw->intel.vtbl.destroy = brw_destroy_context;
brw->intel.vtbl.set_draw_region = brw_set_draw_region;
brw->intel.vtbl.flush_cmd = brw_flush_cmd;
- brw->intel.vtbl.emit_flush = brw_emit_flush;
brw->intel.vtbl.debug_batch = brw_debug_batch;
}
-
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
index c50b0d2dd9..2292de94c4 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.c
+++ b/src/mesa/drivers/dri/i965/brw_wm.c
@@ -40,12 +40,14 @@
GLuint brw_wm_nr_args( GLuint opcode )
{
switch (opcode) {
+ case WM_FRONTFACING:
case WM_PIXELXY:
+ return 0;
case WM_CINTERP:
case WM_WPOSXY:
+ case WM_DELTAXY:
return 1;
case WM_LINTERP:
- case WM_DELTAXY:
case WM_PIXELW:
return 2;
case WM_FB_WRITE:
@@ -80,6 +82,58 @@ GLuint brw_wm_is_scalar_result( GLuint opcode )
}
+/**
+ * Do GPU code generation for non-GLSL shader. non-GLSL shaders have
+ * no flow control instructions so we can more readily do SSA-style
+ * optimizations.
+ */
+static void
+brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
+{
+ /* Augment fragment program. Add instructions for pre- and
+ * post-fragment-program tasks such as interpolation and fogging.
+ */
+ brw_wm_pass_fp(c);
+
+ /* Translate to intermediate representation. Build register usage
+ * chains.
+ */
+ brw_wm_pass0(c);
+
+ /* Dead code removal.
+ */
+ brw_wm_pass1(c);
+
+ /* Register allocation.
+ * Divide by two because we operate on 16 pixels at a time and require
+ * two GRF entries for each logical shader register.
+ */
+ c->grf_limit = BRW_WM_MAX_GRF / 2;
+
+ brw_wm_pass2(c);
+
+ /* how many general-purpose registers are used */
+ c->prog_data.total_grf = c->max_wm_grf;
+
+ /* Scratch space is used for register spilling */
+ if (c->last_scratch) {
+ c->prog_data.total_scratch = c->last_scratch + 0x40;
+ }
+ else {
+ c->prog_data.total_scratch = 0;
+ }
+
+ /* Emit GEN4 code.
+ */
+ brw_wm_emit(c);
+}
+
+
+/**
+ * All Mesa program -> GPU code generation goes through this function.
+ * Depending on the instructions used (i.e. flow control instructions)
+ * we'll use one of two code generators.
+ */
static void do_wm_prog( struct brw_context *brw,
struct brw_fragment_program *fp,
struct brw_wm_prog_key *key)
@@ -90,52 +144,41 @@ static void do_wm_prog( struct brw_context *brw,
c = brw->wm.compile_data;
if (c == NULL) {
- brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data));
- c = brw->wm.compile_data;
+ brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data));
+ c = brw->wm.compile_data;
+ if (c == NULL) {
+ /* Ouch - big out of memory problem. Can't continue
+ * without triggering a segfault, no way to signal,
+ * so just return.
+ */
+ return;
+ }
} else {
- memset(c, 0, sizeof(*brw->wm.compile_data));
+ memset(c, 0, sizeof(*brw->wm.compile_data));
}
memcpy(&c->key, key, sizeof(*key));
c->fp = fp;
c->env_param = brw->intel.ctx.FragmentProgram.Parameters;
- brw_init_compile(brw, &c->func);
- if (brw_wm_is_glsl(&c->fp->program)) {
- brw_wm_glsl_emit(brw, c);
- } else {
- /* Augment fragment program. Add instructions for pre- and
- * post-fragment-program tasks such as interpolation and fogging.
- */
- brw_wm_pass_fp(c);
-
- /* Translate to intermediate representation. Build register usage
- * chains.
- */
- brw_wm_pass0(c);
-
- /* Dead code removal.
- */
- brw_wm_pass1(c);
-
- /* Register allocation.
- */
- c->grf_limit = BRW_WM_MAX_GRF/2;
-
- brw_wm_pass2(c);
-
- c->prog_data.total_grf = c->max_wm_grf;
- if (c->last_scratch) {
- c->prog_data.total_scratch =
- c->last_scratch + 0x40;
- } else {
- c->prog_data.total_scratch = 0;
- }
-
- /* Emit GEN4 code.
- */
- brw_wm_emit(c);
+ brw_init_compile(brw, &c->func);
+
+ /* temporary sanity check assertion */
+ ASSERT(fp->isGLSL == brw_wm_is_glsl(&c->fp->program));
+
+ /*
+ * Shader which use GLSL features such as flow control are handled
+ * differently from "simple" shaders.
+ */
+ if (fp->isGLSL) {
+ c->dispatch_width = 8;
+ brw_wm_glsl_emit(brw, c);
}
+ else {
+ c->dispatch_width = 16;
+ brw_wm_non_glsl_emit(brw, c);
+ }
+
if (INTEL_DEBUG & DEBUG_WM)
fprintf(stderr, "\n");
@@ -157,9 +200,11 @@ static void do_wm_prog( struct brw_context *brw,
static void brw_wm_populate_key( struct brw_context *brw,
struct brw_wm_prog_key *key )
{
+ GLcontext *ctx = &brw->intel.ctx;
/* BRW_NEW_FRAGMENT_PROGRAM */
- struct brw_fragment_program *fp =
+ const struct brw_fragment_program *fp =
(struct brw_fragment_program *)brw->fragment_program;
+ GLboolean uses_depth = (fp->program.Base.InputsRead & (1 << FRAG_ATTRIB_WPOS)) != 0;
GLuint lookup = 0;
GLuint line_aa;
GLuint i;
@@ -170,51 +215,50 @@ static void brw_wm_populate_key( struct brw_context *brw,
*/
/* _NEW_COLOR */
if (fp->program.UsesKill ||
- brw->attribs.Color->AlphaEnabled)
+ ctx->Color.AlphaEnabled)
lookup |= IZ_PS_KILL_ALPHATEST_BIT;
- if (fp->program.Base.OutputsWritten & (1<<FRAG_RESULT_DEPR))
+ if (fp->program.Base.OutputsWritten & (1<<FRAG_RESULT_DEPTH))
lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
/* _NEW_DEPTH */
- if (brw->attribs.Depth->Test)
+ if (ctx->Depth.Test)
lookup |= IZ_DEPTH_TEST_ENABLE_BIT;
- if (brw->attribs.Depth->Test &&
- brw->attribs.Depth->Mask) /* ?? */
+ if (ctx->Depth.Test &&
+ ctx->Depth.Mask) /* ?? */
lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;
/* _NEW_STENCIL */
- if (brw->attribs.Stencil->Enabled) {
+ if (ctx->Stencil._Enabled) {
lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
- if (brw->attribs.Stencil->WriteMask[0] ||
- (brw->attribs.Stencil->_TestTwoSide &&
- brw->attribs.Stencil->WriteMask[1]))
+ if (ctx->Stencil.WriteMask[0] ||
+ ctx->Stencil.WriteMask[ctx->Stencil._BackFace])
lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
}
line_aa = AA_NEVER;
/* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */
- if (brw->attribs.Line->SmoothFlag) {
+ if (ctx->Line.SmoothFlag) {
if (brw->intel.reduced_primitive == GL_LINES) {
line_aa = AA_ALWAYS;
}
else if (brw->intel.reduced_primitive == GL_TRIANGLES) {
- if (brw->attribs.Polygon->FrontMode == GL_LINE) {
+ if (ctx->Polygon.FrontMode == GL_LINE) {
line_aa = AA_SOMETIMES;
- if (brw->attribs.Polygon->BackMode == GL_LINE ||
- (brw->attribs.Polygon->CullFlag &&
- brw->attribs.Polygon->CullFaceMode == GL_BACK))
+ if (ctx->Polygon.BackMode == GL_LINE ||
+ (ctx->Polygon.CullFlag &&
+ ctx->Polygon.CullFaceMode == GL_BACK))
line_aa = AA_ALWAYS;
}
- else if (brw->attribs.Polygon->BackMode == GL_LINE) {
+ else if (ctx->Polygon.BackMode == GL_LINE) {
line_aa = AA_SOMETIMES;
- if ((brw->attribs.Polygon->CullFlag &&
- brw->attribs.Polygon->CullFaceMode == GL_FRONT))
+ if ((ctx->Polygon.CullFlag &&
+ ctx->Polygon.CullFaceMode == GL_FRONT))
line_aa = AA_ALWAYS;
}
}
@@ -222,27 +266,36 @@ static void brw_wm_populate_key( struct brw_context *brw,
brw_wm_lookup_iz(line_aa,
lookup,
+ uses_depth,
key);
/* BRW_NEW_WM_INPUT_DIMENSIONS */
- key->projtex_mask = brw->wm.input_size_masks[4-1] >> (FRAG_ATTRIB_TEX0 - FRAG_ATTRIB_WPOS);
+ key->proj_attrib_mask = brw->wm.input_size_masks[4-1];
/* _NEW_LIGHT */
- key->flat_shade = (brw->attribs.Light->ShadeModel == GL_FLAT);
+ key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT);
+
+ /* _NEW_HINT */
+ key->linear_color = (ctx->Hint.PerspectiveCorrection == GL_FASTEST);
/* _NEW_TEXTURE */
for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
- const struct gl_texture_unit *unit = &brw->attribs.Texture->Unit[i];
- const struct gl_texture_object *t = unit->_Current;
+ const struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
if (unit->_ReallyEnabled) {
- if (t->Image[0][t->BaseLevel]->InternalFormat == GL_YCBCR_MESA) {
- key->yuvtex_mask |= 1<<i;
- if (t->Image[0][t->BaseLevel]->TexFormat->MesaFormat ==
- MESA_FORMAT_YCBCR)
- key->yuvtex_swap_mask |= 1<< i;
+ const struct gl_texture_object *t = unit->_Current;
+ const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
+ if (img->InternalFormat == GL_YCBCR_MESA) {
+ key->yuvtex_mask |= 1 << i;
+ if (img->TexFormat->MesaFormat == MESA_FORMAT_YCBCR)
+ key->yuvtex_swap_mask |= 1 << i;
}
+
+ key->tex_swizzles[i] = t->_Swizzle;
+ }
+ else {
+ key->tex_swizzles[i] = SWIZZLE_NOOP;
}
}
@@ -273,10 +326,11 @@ static void brw_wm_populate_key( struct brw_context *brw,
key->drawable_height = brw->intel.driDrawable->h;
}
- /* Extra info:
- */
- key->program_string_id = fp->id;
+ /* CACHE_NEW_VS_PROG */
+ key->vp_outputs_written = brw->vs.prog_data->outputs_written & DO_SETUP_BITS;
+ /* The unique fragment program ID */
+ key->program_string_id = fp->id;
}
@@ -300,12 +354,11 @@ static void brw_prepare_wm_prog(struct brw_context *brw)
}
-/* See brw_wm.c:
- */
const struct brw_tracked_state brw_wm_prog = {
.dirty = {
.mesa = (_NEW_COLOR |
_NEW_DEPTH |
+ _NEW_HINT |
_NEW_STENCIL |
_NEW_POLYGON |
_NEW_LINE |
@@ -315,7 +368,7 @@ const struct brw_tracked_state brw_wm_prog = {
.brw = (BRW_NEW_FRAGMENT_PROGRAM |
BRW_NEW_WM_INPUT_DIMENSIONS |
BRW_NEW_REDUCED_PRIMITIVE),
- .cache = 0
+ .cache = CACHE_NEW_VS_PROG,
},
.prepare = brw_prepare_wm_prog
};
diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h
index ded079695e..872b1f3ecf 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.h
+++ b/src/mesa/drivers/dri/i965/brw_wm.h
@@ -38,6 +38,8 @@
#include "brw_context.h"
#include "brw_eu.h"
+#define SATURATE (1<<5)
+
/* A big lookup table is used to figure out which and how many
* additional regs will inserted before the main payload in the WM
* program execution. These mainly relate to depth and stencil
@@ -60,20 +62,23 @@ struct brw_wm_prog_key {
GLuint aa_dest_stencil_reg:3;
GLuint dest_depth_reg:3;
GLuint nr_depth_regs:3;
- GLuint projtex_mask:8;
- GLuint shadowtex_mask:8;
GLuint computes_depth:1; /* could be derived from program string */
GLuint source_depth_to_render_target:1;
GLuint flat_shade:1;
+ GLuint linear_color:1; /**< linear interpolation vs perspective interp */
GLuint runtime_check_aads_emit:1;
- GLuint yuvtex_mask:8;
- GLuint yuvtex_swap_mask:8; /* UV swaped */
- GLuint pad1:16;
+ GLbitfield proj_attrib_mask; /**< one bit per fragment program attribute */
+ GLuint shadowtex_mask:16;
+ GLuint yuvtex_mask:16;
+ GLuint yuvtex_swap_mask:16; /* UV swaped */
+
+ GLuint tex_swizzles[BRW_MAX_TEX_UNIT];
GLuint program_string_id:32;
GLuint origin_x, origin_y;
GLuint drawable_height;
+ GLuint vp_outputs_written;
};
@@ -142,13 +147,12 @@ struct brw_wm_instruction {
GLuint writemask:4;
GLuint tex_unit:4; /* texture unit for TEX, TXD, TXP instructions */
GLuint tex_idx:3; /* TEXTURE_1D,2D,3D,CUBE,RECT_INDEX source target */
+ GLuint tex_shadow:1; /* do shadow comparison? */
GLuint eot:1; /* End of thread indicator for FB_WRITE*/
GLuint target:10; /* target binding table index for FB_WRITE*/
};
-#define PROGRAM_INTERNAL_PARAM
-
#define BRW_WM_MAX_INSN (MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS*3 + FRAG_ATTRIB_MAX + 3)
#define BRW_WM_MAX_GRF 128 /* hardware limit */
#define BRW_WM_MAX_VREG (BRW_WM_MAX_INSN * 4)
@@ -172,7 +176,8 @@ struct brw_wm_instruction {
#define WM_CINTERP (MAX_OPCODE + 5)
#define WM_WPOSXY (MAX_OPCODE + 6)
#define WM_FB_WRITE (MAX_OPCODE + 7)
-#define MAX_WM_OPCODE (MAX_OPCODE + 8)
+#define WM_FRONTFACING (MAX_OPCODE + 8)
+#define MAX_WM_OPCODE (MAX_OPCODE + 9)
#define PROGRAM_PAYLOAD (PROGRAM_FILE_MAX)
#define PAYLOAD_DEPTH (FRAG_ATTRIB_MAX)
@@ -200,7 +205,6 @@ struct brw_wm_compile {
GLuint fp_temp;
GLuint fp_interp_emitted;
GLuint fp_fragcolor_emitted;
- GLuint fp_deriv_emitted;
struct prog_src_register pixel_xy;
struct prog_src_register delta_xy;
@@ -239,17 +243,31 @@ struct brw_wm_compile {
GLuint max_wm_grf;
GLuint last_scratch;
+ GLuint cur_inst; /**< index of current instruction */
+
+ GLboolean out_of_regs; /**< ran out of GRF registers? */
+
+ /** Mapping from Mesa registers to hardware registers */
struct {
- GLboolean inited;
- struct brw_reg reg;
+ GLboolean inited;
+ struct brw_reg reg;
} wm_regs[PROGRAM_PAYLOAD+1][256][4];
+
+ GLboolean used_grf[BRW_WM_MAX_GRF];
+ GLuint first_free_grf;
struct brw_reg stack;
struct brw_reg emit_mask_reg;
- GLuint reg_index;
GLuint tmp_regs[BRW_WM_MAX_GRF];
GLuint tmp_index;
GLuint tmp_max;
GLuint subroutines[BRW_WM_MAX_SUBROUTINE];
+ GLuint dispatch_width;
+
+ /** we may need up to 3 constants per instruction (if use_const_buffer) */
+ struct {
+ GLint index;
+ struct brw_reg reg;
+ } current_const[3];
};
@@ -276,8 +294,16 @@ void brw_wm_print_program( struct brw_wm_compile *c,
void brw_wm_lookup_iz( GLuint line_aa,
GLuint lookup,
+ GLboolean ps_uses_depth,
struct brw_wm_prog_key *key );
GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp);
void brw_wm_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c);
+
+void emit_ddxy(struct brw_compile *p,
+ const struct brw_reg *dst,
+ GLuint mask,
+ GLboolean is_ddx,
+ const struct brw_reg *arg0);
+
#endif
diff --git a/src/mesa/drivers/dri/i965/brw_wm_debug.c b/src/mesa/drivers/dri/i965/brw_wm_debug.c
index 8f07f89ebc..220821087c 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_debug.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_debug.c
@@ -130,6 +130,9 @@ void brw_wm_print_insn( struct brw_wm_compile *c,
case WM_FB_WRITE:
_mesa_printf(" = FB_WRITE");
break;
+ case WM_FRONTFACING:
+ _mesa_printf(" = FRONTFACING");
+ break;
default:
_mesa_printf(" = %s", _mesa_opcode_string(inst->opcode));
break;
diff --git a/src/mesa/drivers/dri/i965/brw_wm_emit.c b/src/mesa/drivers/dri/i965/brw_wm_emit.c
index b5050a3e40..bf80a2942a 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_emit.c
@@ -34,8 +34,6 @@
#include "brw_context.h"
#include "brw_wm.h"
-#define SATURATE (1<<5)
-
/* Not quite sure how correct this is - need to understand horiz
* vs. vertical strides a little better.
*/
@@ -65,8 +63,7 @@ static INLINE struct brw_reg sechalf( struct brw_reg reg )
static void emit_pixel_xy(struct brw_compile *p,
const struct brw_reg *dst,
- GLuint mask,
- const struct brw_reg *arg0)
+ GLuint mask)
{
struct brw_reg r1 = brw_vec1_grf(1, 0);
struct brw_reg r1_uw = retype(r1, BRW_REGISTER_TYPE_UW);
@@ -98,8 +95,7 @@ static void emit_pixel_xy(struct brw_compile *p,
static void emit_delta_xy(struct brw_compile *p,
const struct brw_reg *dst,
GLuint mask,
- const struct brw_reg *arg0,
- const struct brw_reg *arg1)
+ const struct brw_reg *arg0)
{
struct brw_reg r1 = brw_vec1_grf(1, 0);
@@ -254,6 +250,107 @@ static void emit_cinterp( struct brw_compile *p,
}
}
+/* Sets the destination channels to 1.0 or 0.0 according to glFrontFacing. */
+static void emit_frontfacing( struct brw_compile *p,
+ const struct brw_reg *dst,
+ GLuint mask )
+{
+ struct brw_reg r1_6ud = retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD);
+ GLuint i;
+
+ if (!(mask & WRITEMASK_XYZW))
+ return;
+
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ brw_MOV(p, dst[i], brw_imm_f(0.0));
+ }
+ }
+
+ /* bit 31 is "primitive is back face", so checking < (1 << 31) gives
+ * us front face
+ */
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, r1_6ud, brw_imm_ud(1 << 31));
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ brw_MOV(p, dst[i], brw_imm_f(1.0));
+ }
+ }
+ brw_set_predicate_control_flag_value(p, 0xff);
+}
+
+/* For OPCODE_DDX and OPCODE_DDY, per channel of output we've got input
+ * looking like:
+ *
+ * arg0: ss0.tl ss0.tr ss0.bl ss0.br ss1.tl ss1.tr ss1.bl ss1.br
+ *
+ * and we're trying to produce:
+ *
+ * DDX DDY
+ * dst: (ss0.tr - ss0.tl) (ss0.tl - ss0.bl)
+ * (ss0.tr - ss0.tl) (ss0.tr - ss0.br)
+ * (ss0.br - ss0.bl) (ss0.tl - ss0.bl)
+ * (ss0.br - ss0.bl) (ss0.tr - ss0.br)
+ * (ss1.tr - ss1.tl) (ss1.tl - ss1.bl)
+ * (ss1.tr - ss1.tl) (ss1.tr - ss1.br)
+ * (ss1.br - ss1.bl) (ss1.tl - ss1.bl)
+ * (ss1.br - ss1.bl) (ss1.tr - ss1.br)
+ *
+ * and add another set of two more subspans if in 16-pixel dispatch mode.
+ *
+ * For DDX, it ends up being easy: width = 2, horiz=0 gets us the same result
+ * for each pair, and vertstride = 2 jumps us 2 elements after processing a
+ * pair. But for DDY, it's harder, as we want to produce the pairs swizzled
+ * between each other. We could probably do it like ddx and swizzle the right
+ * order later, but bail for now and just produce
+ * ((ss0.tl - ss0.bl)x4 (ss1.tl - ss1.bl)x4)
+ */
+void emit_ddxy(struct brw_compile *p,
+ const struct brw_reg *dst,
+ GLuint mask,
+ GLboolean is_ddx,
+ const struct brw_reg *arg0)
+{
+ int i;
+ struct brw_reg src0, src1;
+
+ if (mask & SATURATE)
+ brw_set_saturate(p, 1);
+ for (i = 0; i < 4; i++ ) {
+ if (mask & (1<<i)) {
+ if (is_ddx) {
+ src0 = brw_reg(arg0[i].file, arg0[i].nr, 1,
+ BRW_REGISTER_TYPE_F,
+ BRW_VERTICAL_STRIDE_2,
+ BRW_WIDTH_2,
+ BRW_HORIZONTAL_STRIDE_0,
+ BRW_SWIZZLE_XYZW, WRITEMASK_XYZW);
+ src1 = brw_reg(arg0[i].file, arg0[i].nr, 0,
+ BRW_REGISTER_TYPE_F,
+ BRW_VERTICAL_STRIDE_2,
+ BRW_WIDTH_2,
+ BRW_HORIZONTAL_STRIDE_0,
+ BRW_SWIZZLE_XYZW, WRITEMASK_XYZW);
+ } else {
+ src0 = brw_reg(arg0[i].file, arg0[i].nr, 0,
+ BRW_REGISTER_TYPE_F,
+ BRW_VERTICAL_STRIDE_4,
+ BRW_WIDTH_4,
+ BRW_HORIZONTAL_STRIDE_0,
+ BRW_SWIZZLE_XYZW, WRITEMASK_XYZW);
+ src1 = brw_reg(arg0[i].file, arg0[i].nr, 2,
+ BRW_REGISTER_TYPE_F,
+ BRW_VERTICAL_STRIDE_4,
+ BRW_WIDTH_4,
+ BRW_HORIZONTAL_STRIDE_0,
+ BRW_SWIZZLE_XYZW, WRITEMASK_XYZW);
+ }
+ brw_ADD(p, dst[i], src0, negate(src1));
+ }
+ }
+ if (mask & SATURATE)
+ brw_set_saturate(p, 0);
+}
static void emit_alu1( struct brw_compile *p,
struct brw_instruction *(*func)(struct brw_compile *,
@@ -325,6 +422,19 @@ static void emit_mad( struct brw_compile *p,
}
}
+static void emit_trunc( struct brw_compile *p,
+ const struct brw_reg *dst,
+ GLuint mask,
+ const struct brw_reg *arg0)
+{
+ GLuint i;
+
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ brw_RNDZ(p, dst[i], arg0[i]);
+ }
+ }
+}
static void emit_lrp( struct brw_compile *p,
const struct brw_reg *dst,
@@ -504,16 +614,18 @@ static void emit_dp3( struct brw_compile *p,
const struct brw_reg *arg0,
const struct brw_reg *arg1 )
{
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
- assert((mask & WRITEMASK_XYZW) == WRITEMASK_X);
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]);
brw_MAC(p, brw_null_reg(), arg0[1], arg1[1]);
brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
- brw_MAC(p, dst[0], arg0[2], arg1[2]);
+ brw_MAC(p, dst[dst_chan], arg0[2], arg1[2]);
brw_set_saturate(p, 0);
}
@@ -524,17 +636,19 @@ static void emit_dp4( struct brw_compile *p,
const struct brw_reg *arg0,
const struct brw_reg *arg1 )
{
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
- assert((mask & WRITEMASK_XYZW) == WRITEMASK_X);
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]);
brw_MAC(p, brw_null_reg(), arg0[1], arg1[1]);
brw_MAC(p, brw_null_reg(), arg0[2], arg1[2]);
brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
- brw_MAC(p, dst[0], arg0[3], arg1[3]);
+ brw_MAC(p, dst[dst_chan], arg0[3], arg1[3]);
brw_set_saturate(p, 0);
}
@@ -545,17 +659,19 @@ static void emit_dph( struct brw_compile *p,
const struct brw_reg *arg0,
const struct brw_reg *arg1 )
{
+ const int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
- assert((mask & WRITEMASK_XYZW) == WRITEMASK_X);
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]);
brw_MAC(p, brw_null_reg(), arg0[1], arg1[1]);
- brw_MAC(p, dst[0], arg0[2], arg1[2]);
+ brw_MAC(p, dst[dst_chan], arg0[2], arg1[2]);
brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
- brw_ADD(p, dst[0], dst[0], arg1[3]);
+ brw_ADD(p, dst[dst_chan], dst[dst_chan], arg1[3]);
brw_set_saturate(p, 0);
}
@@ -591,18 +707,19 @@ static void emit_math1( struct brw_compile *p,
GLuint mask,
const struct brw_reg *arg0 )
{
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
- //assert((mask & WRITEMASK_XYZW) == WRITEMASK_X ||
- // function == BRW_MATH_FUNCTION_SINCOS);
-
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
+
brw_MOV(p, brw_message_reg(2), arg0[0]);
/* Send two messages to perform all 16 operations:
*/
brw_math_16(p,
- dst[0],
+ dst[dst_chan],
function,
(mask & SATURATE) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE,
2,
@@ -618,10 +735,12 @@ static void emit_math2( struct brw_compile *p,
const struct brw_reg *arg0,
const struct brw_reg *arg1)
{
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
if (!(mask & WRITEMASK_XYZW))
return; /* Do not emit dead code */
- assert((mask & WRITEMASK_XYZW) == WRITEMASK_X);
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
brw_push_insn_state(p);
@@ -640,7 +759,7 @@ static void emit_math2( struct brw_compile *p,
*/
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
brw_math(p,
- dst[0],
+ dst[dst_chan],
function,
(mask & SATURATE) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE,
2,
@@ -650,7 +769,7 @@ static void emit_math2( struct brw_compile *p,
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF);
brw_math(p,
- offset(dst[0],1),
+ offset(dst[dst_chan],1),
function,
(mask & SATURATE) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE,
4,
@@ -671,9 +790,9 @@ static void emit_tex( struct brw_wm_compile *c,
{
struct brw_compile *p = &c->func;
GLuint msgLength, responseLength;
- GLboolean shadow = (c->key.shadowtex_mask & (1<<inst->tex_unit)) ? 1 : 0;
GLuint i, nr;
GLuint emit;
+ GLuint msg_type;
/* How many input regs are there?
*/
@@ -687,13 +806,17 @@ static void emit_tex( struct brw_wm_compile *c,
emit = WRITEMASK_XY;
nr = 2;
break;
- default:
+ case TEXTURE_3D_INDEX:
+ case TEXTURE_CUBE_INDEX:
emit = WRITEMASK_XYZ;
nr = 3;
break;
+ default:
+ /* unexpected target */
+ abort();
}
- if (shadow) {
+ if (inst->tex_shadow) {
nr = 4;
emit |= WRITEMASK_W;
}
@@ -711,19 +834,31 @@ static void emit_tex( struct brw_wm_compile *c,
responseLength = 8; /* always */
+ if (BRW_IS_IGDNG(p->brw)) {
+ if (inst->tex_shadow)
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE_IGDNG;
+ else
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_IGDNG;
+ } else {
+ if (inst->tex_shadow)
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE;
+ else
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE;
+ }
+
brw_SAMPLE(p,
retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW),
1,
retype(c->payload.depth[0].hw_reg, BRW_REGISTER_TYPE_UW),
- inst->tex_unit + MAX_DRAW_BUFFERS, /* surface */
+ SURF_INDEX_TEXTURE(inst->tex_unit),
inst->tex_unit, /* sampler */
inst->writemask,
- (shadow ?
- BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE :
- BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE),
+ msg_type,
responseLength,
msgLength,
- 0);
+ 0,
+ 1,
+ BRW_SAMPLER_SIMD_MODE_SIMD16);
}
@@ -735,7 +870,7 @@ static void emit_txb( struct brw_wm_compile *c,
{
struct brw_compile *p = &c->func;
GLuint msgLength;
-
+ GLuint msg_type;
/* Shadow ignored for txb.
*/
switch (inst->tex_idx) {
@@ -750,27 +885,38 @@ static void emit_txb( struct brw_wm_compile *c,
brw_MOV(p, brw_message_reg(4), arg[1]);
brw_MOV(p, brw_message_reg(6), brw_imm_f(0));
break;
- default:
+ case TEXTURE_3D_INDEX:
+ case TEXTURE_CUBE_INDEX:
brw_MOV(p, brw_message_reg(2), arg[0]);
brw_MOV(p, brw_message_reg(4), arg[1]);
brw_MOV(p, brw_message_reg(6), arg[2]);
break;
+ default:
+ /* unexpected target */
+ abort();
}
brw_MOV(p, brw_message_reg(8), arg[3]);
msgLength = 9;
+ if (BRW_IS_IGDNG(p->brw))
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS_IGDNG;
+ else
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS;
+
brw_SAMPLE(p,
retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW),
1,
retype(c->payload.depth[0].hw_reg, BRW_REGISTER_TYPE_UW),
- inst->tex_unit + MAX_DRAW_BUFFERS, /* surface */
+ SURF_INDEX_TEXTURE(inst->tex_unit),
inst->tex_unit, /* sampler */
inst->writemask,
- BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
+ msg_type,
8, /* responseLength */
msgLength,
- 0);
+ 0,
+ 1,
+ BRW_SAMPLER_SIMD_MODE_SIMD16);
}
@@ -833,6 +979,20 @@ static void emit_kil( struct brw_wm_compile *c,
}
}
+/* KIL_NV kills the pixels that are currently executing, not based on a test
+ * of the arguments.
+ */
+static void emit_kil_nv( struct brw_wm_compile *c )
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg r0uw = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);
+
+ brw_push_insn_state(p);
+ brw_set_mask_control(p, BRW_MASK_DISABLE);
+ brw_NOT(p, c->emit_mask_reg, brw_mask_reg(1)); //IMASK
+ brw_AND(p, r0uw, c->emit_mask_reg, r0uw);
+ brw_pop_insn_state(p);
+}
static void fire_fb_write( struct brw_wm_compile *c,
GLuint base_reg,
@@ -886,6 +1046,9 @@ static void emit_aa( struct brw_wm_compile *c,
/* Post-fragment-program processing. Send the results to the
* framebuffer.
+ * \param arg0 the fragment color
+ * \param arg1 the pass-through depth value
+ * \param arg2 the shader-computed depth value
*/
static void emit_fb_write( struct brw_wm_compile *c,
struct brw_reg *arg0,
@@ -979,7 +1142,7 @@ static void emit_fb_write( struct brw_wm_compile *c,
get_element_ud(brw_vec8_grf(1,0), 6),
brw_imm_ud(1<<26));
- jmp = brw_JMPI(p, ip, ip, brw_imm_w(0));
+ jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
{
emit_aa(c, arg1, 2);
fire_fb_write(c, 0, nr, target, eot);
@@ -994,8 +1157,8 @@ static void emit_fb_write( struct brw_wm_compile *c,
}
-/* Post-fragment-program processing. Send the results to the
- * framebuffer.
+/**
+ * Move a GPR to scratch memory.
*/
static void emit_spill( struct brw_wm_compile *c,
struct brw_reg reg,
@@ -1014,11 +1177,13 @@ static void emit_spill( struct brw_wm_compile *c,
*/
brw_dp_WRITE_16(p,
retype(vec16(brw_vec8_grf(0, 0)), BRW_REGISTER_TYPE_UW),
- 1,
slot);
}
+/**
+ * Load a GPR from scratch memory.
+ */
static void emit_unspill( struct brw_wm_compile *c,
struct brw_reg reg,
GLuint slot )
@@ -1039,13 +1204,13 @@ static void emit_unspill( struct brw_wm_compile *c,
brw_dp_READ_16(p,
retype(vec16(reg), BRW_REGISTER_TYPE_UW),
- 1,
slot);
}
/**
- * Retrieve upto 4 GEN4 register pairs for the given wm reg:
+ * Retrieve up to 4 GEN4 register pairs for the given wm reg:
+ * Args with unspill_reg != 0 will be loaded from scratch memory.
*/
static void get_argument_regs( struct brw_wm_compile *c,
struct brw_wm_ref *arg[],
@@ -1055,13 +1220,12 @@ static void get_argument_regs( struct brw_wm_compile *c,
for (i = 0; i < 4; i++) {
if (arg[i]) {
-
- if (arg[i]->unspill_reg)
- emit_unspill(c,
+ if (arg[i]->unspill_reg)
+ emit_unspill(c,
brw_vec8_grf(arg[i]->unspill_reg, 0),
arg[i]->value->spill_slot);
- regs[i] = arg[i]->hw_reg;
+ regs[i] = arg[i]->hw_reg;
}
else {
regs[i] = brw_null_reg();
@@ -1070,6 +1234,9 @@ static void get_argument_regs( struct brw_wm_compile *c,
}
+/**
+ * For values that have a spill_slot!=0, write those regs to scratch memory.
+ */
static void spill_values( struct brw_wm_compile *c,
struct brw_wm_value *values,
GLuint nr )
@@ -1127,11 +1294,11 @@ void brw_wm_emit( struct brw_wm_compile *c )
/* Generated instructions for calculating triangle interpolants:
*/
case WM_PIXELXY:
- emit_pixel_xy(p, dst, dst_flags, args[0]);
+ emit_pixel_xy(p, dst, dst_flags);
break;
case WM_DELTAXY:
- emit_delta_xy(p, dst, dst_flags, args[0], args[1]);
+ emit_delta_xy(p, dst, dst_flags, args[0]);
break;
case WM_WPOSXY:
@@ -1158,6 +1325,10 @@ void brw_wm_emit( struct brw_wm_compile *c )
emit_fb_write(c, args[0], args[1], args[2], inst->target, inst->eot);
break;
+ case WM_FRONTFACING:
+ emit_frontfacing(p, dst, dst_flags);
+ break;
+
/* Straightforward arithmetic:
*/
case OPCODE_ADD:
@@ -1172,6 +1343,14 @@ void brw_wm_emit( struct brw_wm_compile *c )
emit_alu1(p, brw_RNDD, dst, dst_flags, args[0]);
break;
+ case OPCODE_DDX:
+ emit_ddxy(p, dst, dst_flags, GL_TRUE, args[0]);
+ break;
+
+ case OPCODE_DDY:
+ emit_ddxy(p, dst, dst_flags, GL_FALSE, args[0]);
+ break;
+
case OPCODE_DP3:
emit_dp3(p, dst, dst_flags, args[0], args[1]);
break;
@@ -1184,6 +1363,10 @@ void brw_wm_emit( struct brw_wm_compile *c )
emit_dph(p, dst, dst_flags, args[0], args[1]);
break;
+ case OPCODE_TRUNC:
+ emit_trunc(p, dst, dst_flags, args[0]);
+ break;
+
case OPCODE_LRP:
emit_lrp(p, dst, dst_flags, args[0], args[1], args[2]);
break;
@@ -1297,6 +1480,10 @@ void brw_wm_emit( struct brw_wm_compile *c )
emit_kil(c, args[0]);
break;
+ case OPCODE_KIL_NV:
+ emit_kil_nv(c);
+ break;
+
default:
_mesa_printf("Unsupported opcode %i (%s) in fragment shader\n",
inst->opcode, inst->opcode < MAX_OPCODE ?
@@ -1310,4 +1497,13 @@ void brw_wm_emit( struct brw_wm_compile *c )
inst->dst[i]->hw_reg,
inst->dst[i]->spill_slot);
}
+
+ if (INTEL_DEBUG & DEBUG_WM) {
+ int i;
+
+ _mesa_printf("wm-native:\n");
+ for (i = 0; i < p->nr_insn; i++)
+ brw_disasm(stderr, &p->store[i]);
+ _mesa_printf("\n");
+ }
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_fp.c b/src/mesa/drivers/dri/i965/brw_wm_fp.c
index 6df2c95d80..4e3edfbbff 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_fp.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_fp.c
@@ -42,6 +42,12 @@
#include "shader/prog_statevars.h"
+/** An invalid texture target */
+#define TEX_TARGET_NONE NUM_TEXTURE_TARGETS
+
+/** An invalid texture unit */
+#define TEX_UNIT_NONE BRW_MAX_TEX_UNIT
+
#define FIRST_INTERNAL_TEMP MAX_NV_FRAGMENT_PROGRAM_TEMPS
#define X 0
@@ -58,7 +64,8 @@ static const char *wm_opcode_strings[] = {
"PINTERP",
"CINTERP",
"WPOSXY",
- "FB_WRITE"
+ "FB_WRITE",
+ "FRONTFACING",
};
#if 0
@@ -79,9 +86,8 @@ static struct prog_src_register src_reg(GLuint file, GLuint idx)
reg.Index = idx;
reg.Swizzle = SWIZZLE_NOOP;
reg.RelAddr = 0;
- reg.NegateBase = 0;
+ reg.Negate = NEGATE_NONE;
reg.Abs = 0;
- reg.NegateAbs = 0;
return reg;
}
@@ -111,6 +117,12 @@ static struct prog_src_register src_swizzle1( struct prog_src_register reg, int
return src_swizzle(reg, x, x, x, x);
}
+static struct prog_src_register src_swizzle4( struct prog_src_register reg, uint swizzle )
+{
+ reg.Swizzle = swizzle;
+ return reg;
+}
+
/***********************************************************************
* Dest regs
@@ -123,7 +135,7 @@ static struct prog_dst_register dst_reg(GLuint file, GLuint idx)
reg.Index = idx;
reg.WriteMask = WRITEMASK_XYZW;
reg.RelAddr = 0;
- reg.CondMask = 0;
+ reg.CondMask = COND_TR;
reg.CondSwizzle = 0;
reg.CondSrc = 0;
reg.pad = 0;
@@ -177,22 +189,31 @@ static struct prog_instruction *emit_insn(struct brw_wm_compile *c,
{
struct prog_instruction *inst = get_fp_inst(c);
*inst = *inst0;
- inst->Data = (void *)inst0;
return inst;
}
-static struct prog_instruction * emit_op(struct brw_wm_compile *c,
+static struct prog_instruction * emit_tex_op(struct brw_wm_compile *c,
GLuint op,
struct prog_dst_register dest,
GLuint saturate,
GLuint tex_src_unit,
GLuint tex_src_target,
+ GLuint tex_shadow,
struct prog_src_register src0,
struct prog_src_register src1,
struct prog_src_register src2 )
{
struct prog_instruction *inst = get_fp_inst(c);
+ assert(tex_src_unit < BRW_MAX_TEX_UNIT ||
+ tex_src_unit == TEX_UNIT_NONE);
+ assert(tex_src_target < NUM_TEXTURE_TARGETS ||
+ tex_src_target == TEX_TARGET_NONE);
+
+ /* update mask of which texture units are referenced by this program */
+ if (tex_src_unit != TEX_UNIT_NONE)
+ c->fp->tex_units_used |= (1 << tex_src_unit);
+
memset(inst, 0, sizeof(*inst));
inst->Opcode = op;
@@ -200,6 +221,7 @@ static struct prog_instruction * emit_op(struct brw_wm_compile *c,
inst->SaturateMode = saturate;
inst->TexSrcUnit = tex_src_unit;
inst->TexSrcTarget = tex_src_target;
+ inst->TexShadow = tex_shadow;
inst->SrcReg[0] = src0;
inst->SrcReg[1] = src1;
inst->SrcReg[2] = src2;
@@ -207,6 +229,53 @@ static struct prog_instruction * emit_op(struct brw_wm_compile *c,
}
+static struct prog_instruction * emit_op(struct brw_wm_compile *c,
+ GLuint op,
+ struct prog_dst_register dest,
+ GLuint saturate,
+ struct prog_src_register src0,
+ struct prog_src_register src1,
+ struct prog_src_register src2 )
+{
+ return emit_tex_op(c, op, dest, saturate,
+ TEX_UNIT_NONE, TEX_TARGET_NONE, 0, /* unit, tgt, shadow */
+ src0, src1, src2);
+}
+
+
+/* Many Mesa opcodes produce the same value across all the result channels.
+ * We'd rather not have to support that splatting in the opcode implementations,
+ * and brw_wm_pass*.c wants to optimize them out by shuffling references around
+ * anyway. We can easily get both by emitting the opcode to one channel, and
+ * then MOVing it to the others, which brw_wm_pass*.c already understands.
+ */
+static struct prog_instruction *emit_scalar_insn(struct brw_wm_compile *c,
+ const struct prog_instruction *inst0)
+{
+ struct prog_instruction *inst;
+ unsigned int dst_chan;
+ unsigned int other_channel_mask;
+
+ if (inst0->DstReg.WriteMask == 0)
+ return NULL;
+
+ dst_chan = _mesa_ffs(inst0->DstReg.WriteMask) - 1;
+ inst = get_fp_inst(c);
+ *inst = *inst0;
+ inst->DstReg.WriteMask = 1 << dst_chan;
+
+ other_channel_mask = inst0->DstReg.WriteMask & ~(1 << dst_chan);
+ if (other_channel_mask != 0) {
+ inst = emit_op(c,
+ OPCODE_MOV,
+ dst_mask(inst0->DstReg, other_channel_mask),
+ 0,
+ src_swizzle1(src_reg_from_dst(inst0->DstReg), dst_chan),
+ src_undef(),
+ src_undef());
+ }
+ return inst;
+}
/***********************************************************************
@@ -228,7 +297,7 @@ static struct prog_src_register get_pixel_xy( struct brw_wm_compile *c )
emit_op(c,
WM_PIXELXY,
dst_mask(pixel_xy, WRITEMASK_XY),
- 0, 0, 0,
+ 0,
payload_r0_depth,
src_undef(),
src_undef());
@@ -251,7 +320,7 @@ static struct prog_src_register get_delta_xy( struct brw_wm_compile *c )
emit_op(c,
WM_DELTAXY,
dst_mask(delta_xy, WRITEMASK_XY),
- 0, 0, 0,
+ 0,
pixel_xy,
payload_r0_depth,
src_undef());
@@ -268,14 +337,13 @@ static struct prog_src_register get_pixel_w( struct brw_wm_compile *c )
struct prog_dst_register pixel_w = get_temp(c);
struct prog_src_register deltas = get_delta_xy(c);
struct prog_src_register interp_wpos = src_reg(PROGRAM_PAYLOAD, FRAG_ATTRIB_WPOS);
-
-
+
/* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x
*/
emit_op(c,
WM_PIXELW,
dst_mask(pixel_w, WRITEMASK_W),
- 0, 0, 0,
+ 0,
interp_wpos,
deltas,
src_undef());
@@ -293,24 +361,19 @@ static void emit_interp( struct brw_wm_compile *c,
struct prog_dst_register dst = dst_reg(PROGRAM_INPUT, idx);
struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
struct prog_src_register deltas = get_delta_xy(c);
- struct prog_src_register arg2;
- GLuint opcode;
-
+
/* Need to use PINTERP on attributes which have been
* multiplied by 1/W in the SF program, and LINTERP on those
* which have not:
*/
switch (idx) {
case FRAG_ATTRIB_WPOS:
- opcode = WM_LINTERP;
- arg2 = src_undef();
-
/* Have to treat wpos.xy specially:
*/
emit_op(c,
WM_WPOSXY,
dst_mask(dst, WRITEMASK_XY),
- 0, 0, 0,
+ 0,
get_pixel_xy(c),
src_undef(),
src_undef());
@@ -322,10 +385,10 @@ static void emit_interp( struct brw_wm_compile *c,
emit_op(c,
WM_LINTERP,
dst,
- 0, 0, 0,
+ 0,
interp,
deltas,
- arg2);
+ src_undef());
break;
case FRAG_ATTRIB_COL0:
case FRAG_ATTRIB_COL1:
@@ -333,26 +396,95 @@ static void emit_interp( struct brw_wm_compile *c,
emit_op(c,
WM_CINTERP,
dst,
- 0, 0, 0,
+ 0,
interp,
src_undef(),
src_undef());
}
else {
- emit_op(c,
- WM_LINTERP,
- dst,
- 0, 0, 0,
- interp,
- deltas,
- src_undef());
+ if (c->key.linear_color) {
+ emit_op(c,
+ WM_LINTERP,
+ dst,
+ 0,
+ interp,
+ deltas,
+ src_undef());
+ }
+ else {
+ /* perspective-corrected color interpolation */
+ emit_op(c,
+ WM_PINTERP,
+ dst,
+ 0,
+ interp,
+ deltas,
+ get_pixel_w(c));
+ }
}
break;
+ case FRAG_ATTRIB_FOGC:
+ /* Interpolate the fog coordinate */
+ emit_op(c,
+ WM_PINTERP,
+ dst_mask(dst, WRITEMASK_X),
+ 0,
+ interp,
+ deltas,
+ get_pixel_w(c));
+
+ emit_op(c,
+ OPCODE_MOV,
+ dst_mask(dst, WRITEMASK_YZW),
+ 0,
+ src_swizzle(interp,
+ SWIZZLE_ZERO,
+ SWIZZLE_ZERO,
+ SWIZZLE_ZERO,
+ SWIZZLE_ONE),
+ src_undef(),
+ src_undef());
+ break;
+
+ case FRAG_ATTRIB_FACE:
+ /* XXX review/test this case */
+ emit_op(c,
+ WM_FRONTFACING,
+ dst_mask(dst, WRITEMASK_X),
+ 0,
+ src_undef(),
+ src_undef(),
+ src_undef());
+ break;
+
+ case FRAG_ATTRIB_PNTC:
+ /* XXX review/test this case */
+ emit_op(c,
+ WM_PINTERP,
+ dst_mask(dst, WRITEMASK_XY),
+ 0,
+ interp,
+ deltas,
+ get_pixel_w(c));
+
+ emit_op(c,
+ OPCODE_MOV,
+ dst_mask(dst, WRITEMASK_ZW),
+ 0,
+ src_swizzle(interp,
+ SWIZZLE_ZERO,
+ SWIZZLE_ZERO,
+ SWIZZLE_ZERO,
+ SWIZZLE_ONE),
+ src_undef(),
+ src_undef());
+ break;
+
default:
emit_op(c,
WM_PINTERP,
dst,
- 0, 0, 0,
+ 0,
interp,
deltas,
get_pixel_w(c));
@@ -362,38 +494,6 @@ static void emit_interp( struct brw_wm_compile *c,
c->fp_interp_emitted |= 1<<idx;
}
-static void emit_ddx( struct brw_wm_compile *c,
- const struct prog_instruction *inst )
-{
- GLuint idx = inst->SrcReg[0].Index;
- struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
-
- c->fp_deriv_emitted |= 1<<idx;
- emit_op(c,
- OPCODE_DDX,
- inst->DstReg,
- 0, 0, 0,
- interp,
- get_pixel_w(c),
- src_undef());
-}
-
-static void emit_ddy( struct brw_wm_compile *c,
- const struct prog_instruction *inst )
-{
- GLuint idx = inst->SrcReg[0].Index;
- struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
-
- c->fp_deriv_emitted |= 1<<idx;
- emit_op(c,
- OPCODE_DDY,
- inst->DstReg,
- 0, 0, 0,
- interp,
- get_pixel_w(c),
- src_undef());
-}
-
/***********************************************************************
* Hacks to extend the program parameter and constant lists.
*/
@@ -483,13 +583,12 @@ static void precalc_dst( struct brw_wm_compile *c,
emit_op(c,
OPCODE_MUL,
dst_mask(dst, WRITEMASK_Y),
- inst->SaturateMode, 0, 0,
+ inst->SaturateMode,
src0,
src1,
src_undef());
}
-
if (dst.WriteMask & WRITEMASK_XZ) {
struct prog_instruction *swz;
GLuint z = GET_SWZ(src0.Swizzle, Z);
@@ -499,12 +598,12 @@ static void precalc_dst( struct brw_wm_compile *c,
swz = emit_op(c,
OPCODE_SWZ,
dst_mask(dst, WRITEMASK_XZ),
- inst->SaturateMode, 0, 0,
+ inst->SaturateMode,
src_swizzle(src0, SWIZZLE_ONE, z, z, z),
src_undef(),
src_undef());
/* Avoid letting negation flag of src0 affect our 1 constant. */
- swz->SrcReg[0].NegateBase &= ~NEGATE_X;
+ swz->SrcReg[0].Negate &= ~NEGATE_X;
}
if (dst.WriteMask & WRITEMASK_W) {
/* dst.w = mov src1.w
@@ -512,7 +611,7 @@ static void precalc_dst( struct brw_wm_compile *c,
emit_op(c,
OPCODE_MOV,
dst_mask(dst, WRITEMASK_W),
- inst->SaturateMode, 0, 0,
+ inst->SaturateMode,
src1,
src_undef(),
src_undef());
@@ -534,32 +633,40 @@ static void precalc_lit( struct brw_wm_compile *c,
swz = emit_op(c,
OPCODE_SWZ,
dst_mask(dst, WRITEMASK_XW),
- 0, 0, 0,
+ 0,
src_swizzle1(src0, SWIZZLE_ONE),
src_undef(),
src_undef());
/* Avoid letting the negation flag of src0 affect our 1 constant. */
- swz->SrcReg[0].NegateBase = 0;
+ swz->SrcReg[0].Negate = NEGATE_NONE;
}
-
if (dst.WriteMask & WRITEMASK_YZ) {
emit_op(c,
OPCODE_LIT,
dst_mask(dst, WRITEMASK_YZ),
- inst->SaturateMode, 0, 0,
+ inst->SaturateMode,
src0,
src_undef(),
src_undef());
}
}
+
+/**
+ * Some TEX instructions require extra code, cube map coordinate
+ * normalization, or coordinate scaling for RECT textures, etc.
+ * This function emits those extra instructions and the TEX
+ * instruction itself.
+ */
static void precalc_tex( struct brw_wm_compile *c,
const struct prog_instruction *inst )
{
struct prog_src_register coord;
struct prog_dst_register tmpcoord;
- GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+ const GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+
+ assert(unit < BRW_MAX_TEX_UNIT);
if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) {
struct prog_instruction *out;
@@ -569,49 +676,56 @@ static void precalc_tex( struct brw_wm_compile *c,
struct prog_src_register tmp1src = src_reg_from_dst(tmp1);
struct prog_src_register src0 = inst->SrcReg[0];
+ /* find longest component of coord vector and normalize it */
tmpcoord = get_temp(c);
coord = src_reg_from_dst(tmpcoord);
+ /* tmpcoord = src0 (i.e.: coord = src0) */
out = emit_op(c, OPCODE_MOV,
tmpcoord,
- 0, 0, 0,
+ 0,
src0,
src_undef(),
src_undef());
- out->SrcReg[0].NegateBase = 0;
+ out->SrcReg[0].Negate = NEGATE_NONE;
out->SrcReg[0].Abs = 1;
+ /* tmp0 = MAX(coord.X, coord.Y) */
emit_op(c, OPCODE_MAX,
tmp0,
- 0, 0, 0,
+ 0,
src_swizzle1(coord, X),
src_swizzle1(coord, Y),
src_undef());
+ /* tmp1 = MAX(tmp0, coord.Z) */
emit_op(c, OPCODE_MAX,
tmp1,
- 0, 0, 0,
+ 0,
tmp0src,
src_swizzle1(coord, Z),
src_undef());
+ /* tmp0 = 1 / tmp1 */
emit_op(c, OPCODE_RCP,
- tmp0,
- 0, 0, 0,
+ dst_mask(tmp0, WRITEMASK_X),
+ 0,
tmp1src,
src_undef(),
src_undef());
+ /* tmpCoord = src0 * tmp0 */
emit_op(c, OPCODE_MUL,
tmpcoord,
- 0, 0, 0,
+ 0,
src0,
- tmp0src,
+ src_swizzle1(tmp0src, SWIZZLE_X),
src_undef());
release_temp(c, tmp0);
release_temp(c, tmp1);
- } else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
+ }
+ else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
struct prog_src_register scale =
search_or_add_param5( c,
STATE_INTERNAL,
@@ -626,9 +740,13 @@ static void precalc_tex( struct brw_wm_compile *c,
emit_op(c,
OPCODE_MUL,
tmpcoord,
- 0, 0, 0,
+ 0,
inst->SrcReg[0],
- scale,
+ src_swizzle(scale,
+ SWIZZLE_X,
+ SWIZZLE_Y,
+ SWIZZLE_ONE,
+ SWIZZLE_ONE),
src_undef());
coord = src_reg_from_dst(tmpcoord);
@@ -642,19 +760,9 @@ static void precalc_tex( struct brw_wm_compile *c,
* conversion requires allocating a temporary variable which we
* don't have the facility to do that late in the compilation.
*/
- if (!(c->key.yuvtex_mask & (1<<unit))) {
- emit_op(c,
- OPCODE_TEX,
- inst->DstReg,
- inst->SaturateMode,
- unit,
- inst->TexSrcTarget,
- coord,
- src_undef(),
- src_undef());
- }
- else {
- GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit);
+ if (c->key.yuvtex_mask & (1 << unit)) {
+ /* convert ycbcr to RGBA */
+ GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit);
/*
CONST C0 = { -.5, -.0625, -.5, 1.164 }
@@ -676,22 +784,23 @@ static void precalc_tex( struct brw_wm_compile *c,
/* tmp = TEX ...
*/
- emit_op(c,
- OPCODE_TEX,
- tmp,
- inst->SaturateMode,
- unit,
- inst->TexSrcTarget,
- coord,
- src_undef(),
- src_undef());
+ emit_tex_op(c,
+ OPCODE_TEX,
+ tmp,
+ inst->SaturateMode,
+ unit,
+ inst->TexSrcTarget,
+ inst->TexShadow,
+ coord,
+ src_undef(),
+ src_undef());
/* tmp.xyz = ADD TMP, C0
*/
emit_op(c,
OPCODE_ADD,
dst_mask(tmp, WRITEMASK_XYZ),
- 0, 0, 0,
+ 0,
tmpsrc,
C0,
src_undef());
@@ -702,7 +811,7 @@ static void precalc_tex( struct brw_wm_compile *c,
emit_op(c,
OPCODE_MUL,
dst_mask(tmp, WRITEMASK_Y),
- 0, 0, 0,
+ 0,
tmpsrc,
src_swizzle1(C0, W),
src_undef());
@@ -717,7 +826,7 @@ static void precalc_tex( struct brw_wm_compile *c,
emit_op(c,
OPCODE_MAD,
dst_mask(dst, WRITEMASK_XYZ),
- 0, 0, 0,
+ 0,
swap_uv?src_swizzle(tmpsrc, Z,Z,X,X):src_swizzle(tmpsrc, X,X,Z,Z),
C1,
src_swizzle1(tmpsrc, Y));
@@ -727,13 +836,38 @@ static void precalc_tex( struct brw_wm_compile *c,
emit_op(c,
OPCODE_MAD,
dst_mask(dst, WRITEMASK_Y),
- 0, 0, 0,
+ 0,
src_swizzle1(tmpsrc, Z),
src_swizzle1(C1, W),
src_swizzle1(src_reg_from_dst(dst), Y));
release_temp(c, tmp);
}
+ else {
+ /* ordinary RGBA tex instruction */
+ emit_tex_op(c,
+ OPCODE_TEX,
+ inst->DstReg,
+ inst->SaturateMode,
+ unit,
+ inst->TexSrcTarget,
+ inst->TexShadow,
+ coord,
+ src_undef(),
+ src_undef());
+ }
+
+ /* For GL_EXT_texture_swizzle: */
+ if (c->key.tex_swizzles[unit] != SWIZZLE_NOOP) {
+ /* swizzle the result of the TEX instruction */
+ struct prog_src_register tmpsrc = src_reg_from_dst(inst->DstReg);
+ emit_op(c, OPCODE_SWZ,
+ inst->DstReg,
+ SATURATE_OFF, /* saturate already done above */
+ src_swizzle4(tmpsrc, c->key.tex_swizzles[unit]),
+ src_undef(),
+ src_undef());
+ }
if ((inst->TexSrcTarget == TEXTURE_RECT_INDEX) ||
(inst->TexSrcTarget == TEXTURE_CUBE_INDEX))
@@ -741,10 +875,16 @@ static void precalc_tex( struct brw_wm_compile *c,
}
+/**
+ * Check if the given TXP instruction really needs the divide-by-W step.
+ */
static GLboolean projtex( struct brw_wm_compile *c,
const struct prog_instruction *inst )
{
- struct prog_src_register src = inst->SrcReg[0];
+ const struct prog_src_register src = inst->SrcReg[0];
+ GLboolean retVal;
+
+ assert(inst->Opcode == OPCODE_TXP);
/* Only try to detect the simplest cases. Could detect (later)
* cases where we are trying to emit code like RCP {1.0}, MUL x,
@@ -754,16 +894,21 @@ static GLboolean projtex( struct brw_wm_compile *c,
* user-provided fragment programs anyway:
*/
if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX)
- return 0; /* ut2004 gun rendering !?! */
+ retVal = GL_FALSE; /* ut2004 gun rendering !?! */
else if (src.File == PROGRAM_INPUT &&
GET_SWZ(src.Swizzle, W) == W &&
- (c->key.projtex_mask & (1<<(src.Index + FRAG_ATTRIB_WPOS - FRAG_ATTRIB_TEX0))) == 0)
- return 0;
+ (c->key.proj_attrib_mask & (1 << src.Index)) == 0)
+ retVal = GL_FALSE;
else
- return 1;
+ retVal = GL_TRUE;
+
+ return retVal;
}
+/**
+ * Emit code for TXP.
+ */
static void precalc_txp( struct brw_wm_compile *c,
const struct prog_instruction *inst )
{
@@ -778,7 +923,7 @@ static void precalc_txp( struct brw_wm_compile *c,
emit_op(c,
OPCODE_RCP,
dst_mask(tmp, WRITEMASK_W),
- 0, 0, 0,
+ 0,
src_swizzle1(src0, GET_SWZ(src0.Swizzle, W)),
src_undef(),
src_undef());
@@ -788,7 +933,7 @@ static void precalc_txp( struct brw_wm_compile *c,
emit_op(c,
OPCODE_MUL,
dst_mask(tmp, WRITEMASK_XYZ),
- 0, 0, 0,
+ 0,
src0,
src_swizzle1(src_reg_from_dst(tmp), W),
src_undef());
@@ -814,42 +959,41 @@ static void precalc_txp( struct brw_wm_compile *c,
static void emit_fb_write( struct brw_wm_compile *c )
{
struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH);
- struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPR);
+ struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPTH);
struct prog_src_register outcolor;
GLuint i;
struct prog_instruction *inst, *last_inst;
struct brw_context *brw = c->func.brw;
- /* inst->Sampler is not used by backend,
- use it for fb write target and eot */
-
- if (brw->state.nr_draw_regions > 1) {
- for (i = 0 ; i < brw->state.nr_draw_regions; i++) {
- outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i);
- last_inst = inst = emit_op(c,
- WM_FB_WRITE, dst_mask(dst_undef(),0), 0, 0, 0,
- outcolor, payload_r0_depth, outdepth);
- inst->Sampler = (i<<1);
- if (c->fp_fragcolor_emitted) {
- outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
- last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
- 0, 0, 0, outcolor, payload_r0_depth, outdepth);
- inst->Sampler = (i<<1);
- }
- }
- last_inst->Sampler |= 1; //eot
+ /* The inst->Aux field is used for FB write target and the EOT marker */
+
+ if (brw->state.nr_color_regions > 1) {
+ for (i = 0 ; i < brw->state.nr_color_regions; i++) {
+ outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i);
+ last_inst = inst = emit_op(c,
+ WM_FB_WRITE, dst_mask(dst_undef(),0), 0,
+ outcolor, payload_r0_depth, outdepth);
+ inst->Aux = (i<<1);
+ if (c->fp_fragcolor_emitted) {
+ outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
+ last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
+ 0, outcolor, payload_r0_depth, outdepth);
+ inst->Aux = (i<<1);
+ }
+ }
+ last_inst->Aux |= 1; //eot
}
else {
/* if gl_FragData[0] is written, use it, else use gl_FragColor */
if (c->fp->program.Base.OutputsWritten & (1 << FRAG_RESULT_DATA0))
outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0);
else
- outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
+ outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
- inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
- 0, 0, 0, outcolor, payload_r0_depth, outdepth);
- inst->Sampler = 1|(0<<1);
+ inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
+ 0, outcolor, payload_r0_depth, outdepth);
+ inst->Aux = 1|(0<<1);
}
}
@@ -880,9 +1024,9 @@ static void validate_dst_regs( struct brw_wm_compile *c,
const struct prog_instruction *inst )
{
if (inst->DstReg.File == PROGRAM_OUTPUT) {
- GLuint idx = inst->DstReg.Index;
- if (idx == FRAG_RESULT_COLR)
- c->fp_fragcolor_emitted = 1;
+ GLuint idx = inst->DstReg.Index;
+ if (idx == FRAG_RESULT_COLOR)
+ c->fp_fragcolor_emitted = 1;
}
}
@@ -902,11 +1046,15 @@ static void print_insns( const struct prog_instruction *insn,
3);
}
else
- _mesa_printf("UNKNOWN\n");
-
+ _mesa_printf("965 Opcode %d\n", insn->Opcode);
}
}
+
+/**
+ * Initial pass for fragment program code generation.
+ * This function is used by both the GLSL and non-GLSL paths.
+ */
void brw_wm_pass_fp( struct brw_wm_compile *c )
{
struct brw_fragment_program *fp = c->fp;
@@ -922,16 +1070,21 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
c->delta_xy = src_undef();
c->pixel_w = src_undef();
c->nr_fp_insns = 0;
+ c->fp->tex_units_used = 0x0;
- /* Emit preamble instructions:
+ /* Emit preamble instructions. This is where special instructions such as
+ * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
+ * compute shader inputs from varying vars.
*/
-
-
for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) {
const struct prog_instruction *inst = &fp->program.Base.Instructions[insn];
validate_src_regs(c, inst);
validate_dst_regs(c, inst);
}
+
+ /* Loop over all instructions doing assorted simplifications and
+ * transformations.
+ */
for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) {
const struct prog_instruction *inst = &fp->program.Base.Instructions[insn];
struct prog_instruction *out;
@@ -940,7 +1093,6 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
* necessary:
*/
-
switch (inst->Opcode) {
case OPCODE_SWZ:
out = emit_insn(c, inst);
@@ -950,14 +1102,14 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
case OPCODE_ABS:
out = emit_insn(c, inst);
out->Opcode = OPCODE_MOV;
- out->SrcReg[0].NegateBase = 0;
+ out->SrcReg[0].Negate = NEGATE_NONE;
out->SrcReg[0].Abs = 1;
break;
case OPCODE_SUB:
out = emit_insn(c, inst);
out->Opcode = OPCODE_ADD;
- out->SrcReg[1].NegateBase ^= 0xf;
+ out->SrcReg[1].Negate ^= NEGATE_XYZW;
break;
case OPCODE_SCS:
@@ -986,6 +1138,7 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
case OPCODE_TXB:
out = emit_insn(c, inst);
out->TexSrcUnit = fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+ assert(out->TexSrcUnit < BRW_MAX_TEX_UNIT);
break;
case OPCODE_XPD:
@@ -1001,28 +1154,24 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
*/
out->DstReg.WriteMask = 0;
break;
- case OPCODE_DDX:
- emit_ddx(c, inst);
- break;
- case OPCODE_DDY:
- emit_ddy(c, inst);
- break;
case OPCODE_END:
emit_fb_write(c);
break;
case OPCODE_PRINT:
break;
-
default:
- emit_insn(c, inst);
+ if (brw_wm_is_scalar_result(inst->Opcode))
+ emit_scalar_insn(c, inst);
+ else
+ emit_insn(c, inst);
break;
}
}
if (INTEL_DEBUG & DEBUG_WM) {
- _mesa_printf("pass_fp:\n");
- print_insns( c->prog_instructions, c->nr_fp_insns );
- _mesa_printf("\n");
+ _mesa_printf("pass_fp:\n");
+ print_insns( c->prog_instructions, c->nr_fp_insns );
+ _mesa_printf("\n");
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c
index 8fd776ac39..c9fe1dd8ad 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c
@@ -1,5 +1,7 @@
#include "main/macros.h"
#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_optimize.h"
#include "brw_context.h"
#include "brw_eu.h"
#include "brw_wm.h"
@@ -8,21 +10,28 @@ enum _subroutine {
SUB_NOISE1, SUB_NOISE2, SUB_NOISE3, SUB_NOISE4
};
-/* Only guess, need a flag in gl_fragment_program later */
+static struct brw_reg get_dst_reg(struct brw_wm_compile *c,
+ const struct prog_instruction *inst,
+ GLuint component);
+
+/**
+ * Determine if the given fragment program uses GLSL features such
+ * as flow conditionals, loops, subroutines.
+ * Some GLSL shaders may use these features, others might not.
+ */
GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp)
{
int i;
+
for (i = 0; i < fp->Base.NumInstructions; i++) {
- struct prog_instruction *inst = &fp->Base.Instructions[i];
+ const struct prog_instruction *inst = &fp->Base.Instructions[i];
switch (inst->Opcode) {
+ case OPCODE_ARL:
case OPCODE_IF:
- case OPCODE_TRUNC:
case OPCODE_ENDIF:
case OPCODE_CAL:
case OPCODE_BRK:
case OPCODE_RET:
- case OPCODE_DDX:
- case OPCODE_DDY:
case OPCODE_NOISE1:
case OPCODE_NOISE2:
case OPCODE_NOISE3:
@@ -36,6 +45,87 @@ GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp)
return GL_FALSE;
}
+
+
+static void
+reclaim_temps(struct brw_wm_compile *c);
+
+
+/** Mark GRF register as used. */
+static void
+prealloc_grf(struct brw_wm_compile *c, int r)
+{
+ c->used_grf[r] = GL_TRUE;
+}
+
+
+/** Mark given GRF register as not in use. */
+static void
+release_grf(struct brw_wm_compile *c, int r)
+{
+ /*assert(c->used_grf[r]);*/
+ c->used_grf[r] = GL_FALSE;
+ c->first_free_grf = MIN2(c->first_free_grf, r);
+}
+
+
+/** Return index of a free GRF, mark it as used. */
+static int
+alloc_grf(struct brw_wm_compile *c)
+{
+ GLuint r;
+ for (r = c->first_free_grf; r < BRW_WM_MAX_GRF; r++) {
+ if (!c->used_grf[r]) {
+ c->used_grf[r] = GL_TRUE;
+ c->first_free_grf = r + 1; /* a guess */
+ return r;
+ }
+ }
+
+ /* no free temps, try to reclaim some */
+ reclaim_temps(c);
+ c->first_free_grf = 0;
+
+ /* try alloc again */
+ for (r = c->first_free_grf; r < BRW_WM_MAX_GRF; r++) {
+ if (!c->used_grf[r]) {
+ c->used_grf[r] = GL_TRUE;
+ c->first_free_grf = r + 1; /* a guess */
+ return r;
+ }
+ }
+
+ for (r = 0; r < BRW_WM_MAX_GRF; r++) {
+ assert(c->used_grf[r]);
+ }
+
+ /* really, no free GRF regs found */
+ if (!c->out_of_regs) {
+ /* print warning once per compilation */
+ _mesa_warning(NULL, "i965: ran out of registers for fragment program");
+ c->out_of_regs = GL_TRUE;
+ }
+
+ return -1;
+}
+
+
+/** Return number of GRF registers used */
+static int
+num_grf_used(const struct brw_wm_compile *c)
+{
+ int r;
+ for (r = BRW_WM_MAX_GRF - 1; r >= 0; r--)
+ if (c->used_grf[r])
+ return r + 1;
+ return 0;
+}
+
+
+
+/**
+ * Record the mapping of a Mesa register to a hardware register.
+ */
static void set_reg(struct brw_wm_compile *c, int file, int index,
int component, struct brw_reg reg)
{
@@ -43,25 +133,32 @@ static void set_reg(struct brw_wm_compile *c, int file, int index,
c->wm_regs[file][index][component].inited = GL_TRUE;
}
-static int get_scalar_dst_index(struct prog_instruction *inst)
-{
- int i;
- for (i = 0; i < 4; i++)
- if (inst->DstReg.WriteMask & (1<<i))
- break;
- return i;
-}
-
static struct brw_reg alloc_tmp(struct brw_wm_compile *c)
{
struct brw_reg reg;
- if(c->tmp_index == c->tmp_max)
- c->tmp_regs[ c->tmp_max++ ] = c->reg_index++;
-
+
+ /* if we need to allocate another temp, grow the tmp_regs[] array */
+ if (c->tmp_index == c->tmp_max) {
+ int r = alloc_grf(c);
+ if (r < 0) {
+ /*printf("Out of temps in %s\n", __FUNCTION__);*/
+ r = 50; /* XXX random register! */
+ }
+ c->tmp_regs[ c->tmp_max++ ] = r;
+ }
+
+ /* form the GRF register */
reg = brw_vec8_grf(c->tmp_regs[ c->tmp_index++ ], 0);
+ /*printf("alloc_temp %d\n", reg.nr);*/
+ assert(reg.nr < BRW_WM_MAX_GRF);
return reg;
+
}
+/**
+ * Save current temp register info.
+ * There must be a matching call to release_tmps().
+ */
static int mark_tmps(struct brw_wm_compile *c)
{
return c->tmp_index;
@@ -77,8 +174,22 @@ static void release_tmps(struct brw_wm_compile *c, int mark)
c->tmp_index = mark;
}
+/**
+ * Convert Mesa src register to brw register.
+ *
+ * Since we're running in SOA mode each Mesa register corresponds to four
+ * hardware registers. We allocate the hardware registers as needed here.
+ *
+ * \param file register file, one of PROGRAM_x
+ * \param index register number
+ * \param component src component (X=0, Y=1, Z=2, W=3)
+ * \param nr not used?!?
+ * \param neg negate value?
+ * \param abs take absolute value?
+ */
static struct brw_reg
-get_reg(struct brw_wm_compile *c, int file, int index, int component, int nr, GLuint neg, GLuint abs)
+get_reg(struct brw_wm_compile *c, int file, int index, int component,
+ int nr, GLuint neg, GLuint abs)
{
struct brw_reg reg;
switch (file) {
@@ -89,21 +200,40 @@ get_reg(struct brw_wm_compile *c, int file, int index, int component, int nr, GL
break;
case PROGRAM_UNDEFINED:
return brw_null_reg();
- default:
+ case PROGRAM_TEMPORARY:
+ case PROGRAM_INPUT:
+ case PROGRAM_OUTPUT:
+ case PROGRAM_PAYLOAD:
break;
+ default:
+ _mesa_problem(NULL, "Unexpected file in get_reg()");
+ return brw_null_reg();
}
- if(c->wm_regs[file][index][component].inited)
- reg = c->wm_regs[file][index][component].reg;
- else
- reg = brw_vec8_grf(c->reg_index, 0);
+ assert(index < 256);
+ assert(component < 4);
- if(!c->wm_regs[file][index][component].inited) {
- set_reg(c, file, index, component, reg);
- c->reg_index++;
+ /* see if we've already allocated a HW register for this Mesa register */
+ if (c->wm_regs[file][index][component].inited) {
+ /* yes, re-use */
+ reg = c->wm_regs[file][index][component].reg;
+ }
+ else {
+ /* no, allocate new register */
+ int grf = alloc_grf(c);
+ /*printf("alloc grf %d for reg %d:%d.%d\n", grf, file, index, component);*/
+ if (grf < 0) {
+ /* totally out of temps */
+ grf = 51; /* XXX random register! */
+ }
+
+ reg = brw_vec8_grf(grf, 0);
+ /*printf("Alloc new grf %d for %d.%d\n", reg.nr, index, component);*/
+
+ set_reg(c, file, index, component, reg);
}
- if (neg & (1<< component)) {
+ if (neg & (1 << component)) {
reg = negate(reg);
}
if (abs)
@@ -111,78 +241,360 @@ get_reg(struct brw_wm_compile *c, int file, int index, int component, int nr, GL
return reg;
}
+
+
+/**
+ * This is called if we run out of GRF registers. Examine the live intervals
+ * of temp regs in the program and free those which won't be used again.
+ */
+static void
+reclaim_temps(struct brw_wm_compile *c)
+{
+ GLint intBegin[MAX_PROGRAM_TEMPS];
+ GLint intEnd[MAX_PROGRAM_TEMPS];
+ int index;
+
+ /*printf("Reclaim temps:\n");*/
+
+ _mesa_find_temp_intervals(c->prog_instructions, c->nr_fp_insns,
+ intBegin, intEnd);
+
+ for (index = 0; index < MAX_PROGRAM_TEMPS; index++) {
+ if (intEnd[index] != -1 && intEnd[index] < c->cur_inst) {
+ /* program temp[i] can be freed */
+ int component;
+ /*printf(" temp[%d] is dead\n", index);*/
+ for (component = 0; component < 4; component++) {
+ if (c->wm_regs[PROGRAM_TEMPORARY][index][component].inited) {
+ int r = c->wm_regs[PROGRAM_TEMPORARY][index][component].reg.nr;
+ release_grf(c, r);
+ /*
+ printf(" Reclaim temp %d, reg %d at inst %d\n",
+ index, r, c->cur_inst);
+ */
+ c->wm_regs[PROGRAM_TEMPORARY][index][component].inited = GL_FALSE;
+ }
+ }
+ }
+ }
+}
+
+
+
+
+/**
+ * Preallocate registers. This sets up the Mesa to hardware register
+ * mapping for certain registers, such as constants (uniforms/state vars)
+ * and shader inputs.
+ */
static void prealloc_reg(struct brw_wm_compile *c)
{
int i, j;
struct brw_reg reg;
- int nr_interp_regs = 0;
- GLuint inputs = FRAG_BIT_WPOS | c->fp_interp_emitted | c->fp_deriv_emitted;
+ int urb_read_length = 0;
+ GLuint inputs = FRAG_BIT_WPOS | c->fp_interp_emitted;
+ GLuint reg_index = 0;
+
+ memset(c->used_grf, GL_FALSE, sizeof(c->used_grf));
+ c->first_free_grf = 0;
for (i = 0; i < 4; i++) {
- reg = (i < c->key.nr_depth_regs)
- ? brw_vec8_grf(i*2, 0) : brw_vec8_grf(0, 0);
+ if (i < c->key.nr_depth_regs)
+ reg = brw_vec8_grf(i * 2, 0);
+ else
+ reg = brw_vec8_grf(0, 0);
set_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, i, reg);
}
- c->reg_index += 2*c->key.nr_depth_regs;
+ reg_index += 2 * c->key.nr_depth_regs;
+
+ /* constants */
{
- int nr_params = c->fp->program.Base.Parameters->NumParameters;
- struct gl_program_parameter_list *plist =
- c->fp->program.Base.Parameters;
- int index = 0;
- c->prog_data.nr_params = 4*nr_params;
- for (i = 0; i < nr_params; i++) {
- for (j = 0; j < 4; j++, index++) {
- reg = brw_vec1_grf(c->reg_index + index/8,
- index%8);
- c->prog_data.param[index] =
- &plist->ParameterValues[i][j];
- set_reg(c, PROGRAM_STATE_VAR, i, j, reg);
- }
- }
- c->nr_creg = 2*((4*nr_params+15)/16);
- c->reg_index += c->nr_creg;
+ const GLuint nr_params = c->fp->program.Base.Parameters->NumParameters;
+ const GLuint nr_temps = c->fp->program.Base.NumTemporaries;
+
+ /* use a real constant buffer, or just use a section of the GRF? */
+ /* XXX this heuristic may need adjustment... */
+ if ((nr_params + nr_temps) * 4 + reg_index > 80)
+ c->fp->use_const_buffer = GL_TRUE;
+ else
+ c->fp->use_const_buffer = GL_FALSE;
+ /*printf("WM use_const_buffer = %d\n", c->fp->use_const_buffer);*/
+
+ if (c->fp->use_const_buffer) {
+ /* We'll use a real constant buffer and fetch constants from
+ * it with a dataport read message.
+ */
+
+ /* number of float constants in CURBE */
+ c->prog_data.nr_params = 0;
+ }
+ else {
+ const struct gl_program_parameter_list *plist =
+ c->fp->program.Base.Parameters;
+ int index = 0;
+
+ /* number of float constants in CURBE */
+ c->prog_data.nr_params = 4 * nr_params;
+
+ /* loop over program constants (float[4]) */
+ for (i = 0; i < nr_params; i++) {
+ /* loop over XYZW channels */
+ for (j = 0; j < 4; j++, index++) {
+ reg = brw_vec1_grf(reg_index + index / 8, index % 8);
+ /* Save pointer to parameter/constant value.
+ * Constants will be copied in prepare_constant_buffer()
+ */
+ c->prog_data.param[index] = &plist->ParameterValues[i][j];
+ set_reg(c, PROGRAM_STATE_VAR, i, j, reg);
+ }
+ }
+ /* number of constant regs used (each reg is float[8]) */
+ c->nr_creg = 2 * ((4 * nr_params + 15) / 16);
+ reg_index += c->nr_creg;
+ }
}
- for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
- if (inputs & (1<<i)) {
- nr_interp_regs++;
- reg = brw_vec8_grf(c->reg_index, 0);
- for (j = 0; j < 4; j++)
- set_reg(c, PROGRAM_PAYLOAD, i, j, reg);
- c->reg_index += 2;
- }
+ /* fragment shader inputs */
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ int fp_input;
+
+ if (i >= VERT_RESULT_VAR0)
+ fp_input = i - VERT_RESULT_VAR0 + FRAG_ATTRIB_VAR0;
+ else if (i <= VERT_RESULT_TEX7)
+ fp_input = i;
+ else
+ fp_input = -1;
+
+ if (fp_input >= 0 && inputs & (1 << fp_input)) {
+ urb_read_length = reg_index;
+ reg = brw_vec8_grf(reg_index, 0);
+ for (j = 0; j < 4; j++)
+ set_reg(c, PROGRAM_PAYLOAD, fp_input, j, reg);
+ }
+ if (c->key.vp_outputs_written & (1 << i)) {
+ reg_index += 2;
+ }
}
+
c->prog_data.first_curbe_grf = c->key.nr_depth_regs * 2;
- c->prog_data.urb_read_length = nr_interp_regs * 2;
+ c->prog_data.urb_read_length = urb_read_length;
c->prog_data.curb_read_length = c->nr_creg;
- c->emit_mask_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0);
- c->reg_index++;
- c->stack = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0);
- c->reg_index += 2;
+ c->emit_mask_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, reg_index, 0);
+ reg_index++;
+ c->stack = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, reg_index, 0);
+ reg_index += 2;
+
+ /* mark GRF regs [0..reg_index-1] as in-use */
+ for (i = 0; i < reg_index; i++)
+ prealloc_grf(c, i);
+
+ /* Don't use GRF 126, 127. Using them seems to lead to GPU lock-ups */
+ prealloc_grf(c, 126);
+ prealloc_grf(c, 127);
+
+ for (i = 0; i < c->nr_fp_insns; i++) {
+ const struct prog_instruction *inst = &c->prog_instructions[i];
+ struct brw_reg dst[4];
+
+ switch (inst->Opcode) {
+ case OPCODE_TEX:
+ case OPCODE_TXB:
+ /* Allocate the channels of texture results contiguously,
+ * since they are written out that way by the sampler unit.
+ */
+ for (j = 0; j < 4; j++) {
+ dst[j] = get_dst_reg(c, inst, j);
+ if (j != 0)
+ assert(dst[j].nr == dst[j - 1].nr + 1);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* An instruction may reference up to three constants.
+ * They'll be found in these registers.
+ * XXX alloc these on demand!
+ */
+ if (c->fp->use_const_buffer) {
+ for (i = 0; i < 3; i++) {
+ c->current_const[i].index = -1;
+ c->current_const[i].reg = brw_vec8_grf(alloc_grf(c), 0);
+ }
+ }
+#if 0
+ printf("USE CONST BUFFER? %d\n", c->fp->use_const_buffer);
+ printf("AFTER PRE_ALLOC, reg_index = %d\n", reg_index);
+#endif
+}
+
+
+/**
+ * Check if any of the instruction's src registers are constants, uniforms,
+ * or statevars. If so, fetch any constants that we don't already have in
+ * the three GRF slots.
+ */
+static void fetch_constants(struct brw_wm_compile *c,
+ const struct prog_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ GLuint i;
+
+ /* loop over instruction src regs */
+ for (i = 0; i < 3; i++) {
+ const struct prog_src_register *src = &inst->SrcReg[i];
+ if (src->File == PROGRAM_STATE_VAR ||
+ src->File == PROGRAM_CONSTANT ||
+ src->File == PROGRAM_UNIFORM) {
+ c->current_const[i].index = src->Index;
+
+#if 0
+ printf(" fetch const[%d] for arg %d into reg %d\n",
+ src->Index, i, c->current_const[i].reg.nr);
+#endif
+
+ /* need to fetch the constant now */
+ brw_dp_READ_4(p,
+ c->current_const[i].reg, /* writeback dest */
+ src->RelAddr, /* relative indexing? */
+ 16 * src->Index, /* byte offset */
+ SURF_INDEX_FRAG_CONST_BUFFER/* binding table index */
+ );
+ }
+ }
}
+
+/**
+ * Convert Mesa dst register to brw register.
+ */
static struct brw_reg get_dst_reg(struct brw_wm_compile *c,
- struct prog_instruction *inst, int component, int nr)
+ const struct prog_instruction *inst,
+ GLuint component)
{
+ const int nr = 1;
return get_reg(c, inst->DstReg.File, inst->DstReg.Index, component, nr,
0, 0);
}
+
+static struct brw_reg
+get_src_reg_const(struct brw_wm_compile *c,
+ const struct prog_instruction *inst,
+ GLuint srcRegIndex, GLuint component)
+{
+ /* We should have already fetched the constant from the constant
+ * buffer in fetch_constants(). Now we just have to return a
+ * register description that extracts the needed component and
+ * smears it across all eight vector components.
+ */
+ const struct prog_src_register *src = &inst->SrcReg[srcRegIndex];
+ struct brw_reg const_reg;
+
+ assert(component < 4);
+ assert(srcRegIndex < 3);
+ assert(c->current_const[srcRegIndex].index != -1);
+ const_reg = c->current_const[srcRegIndex].reg;
+
+ /* extract desired float from the const_reg, and smear */
+ const_reg = stride(const_reg, 0, 1, 0);
+ const_reg.subnr = component * 4;
+
+ if (src->Negate & (1 << component))
+ const_reg = negate(const_reg);
+ if (src->Abs)
+ const_reg = brw_abs(const_reg);
+
+#if 0
+ printf(" form const[%d].%d for arg %d, reg %d\n",
+ c->current_const[srcRegIndex].index,
+ component,
+ srcRegIndex,
+ const_reg.nr);
+#endif
+
+ return const_reg;
+}
+
+
+/**
+ * Convert Mesa src register to brw register.
+ */
static struct brw_reg get_src_reg(struct brw_wm_compile *c,
- struct prog_src_register *src, int index, int nr)
+ const struct prog_instruction *inst,
+ GLuint srcRegIndex, GLuint channel)
{
- int component = GET_SWZ(src->Swizzle, index);
- return get_reg(c, src->File, src->Index, component, nr,
- src->NegateBase, src->Abs);
+ const struct prog_src_register *src = &inst->SrcReg[srcRegIndex];
+ const GLuint nr = 1;
+ const GLuint component = GET_SWZ(src->Swizzle, channel);
+
+ /* Extended swizzle terms */
+ if (component == SWIZZLE_ZERO) {
+ return brw_imm_f(0.0F);
+ }
+ else if (component == SWIZZLE_ONE) {
+ return brw_imm_f(1.0F);
+ }
+
+ if (c->fp->use_const_buffer &&
+ (src->File == PROGRAM_STATE_VAR ||
+ src->File == PROGRAM_CONSTANT ||
+ src->File == PROGRAM_UNIFORM)) {
+ return get_src_reg_const(c, inst, srcRegIndex, component);
+ }
+ else {
+ /* other type of source register */
+ return get_reg(c, src->File, src->Index, component, nr,
+ src->Negate, src->Abs);
+ }
}
-/* Subroutines are minimal support for resusable instruction sequences.
- They are implemented as simply as possible to minimise overhead: there
- is no explicit support for communication between the caller and callee
- other than saving the return address in a temporary register, nor is
- there any automatic local storage. This implies that great care is
- required before attempting reentrancy or any kind of nested
- subroutine invocations. */
+
+/**
+ * Same as \sa get_src_reg() but if the register is a literal, emit
+ * a brw_reg encoding the literal.
+ * Note that a brw instruction only allows one src operand to be a literal.
+ * For instructions with more than one operand, only the second can be a
+ * literal. This means that we treat some literals as constants/uniforms
+ * (which why PROGRAM_CONSTANT is checked in fetch_constants()).
+ *
+ */
+static struct brw_reg get_src_reg_imm(struct brw_wm_compile *c,
+ const struct prog_instruction *inst,
+ GLuint srcRegIndex, GLuint channel)
+{
+ const struct prog_src_register *src = &inst->SrcReg[srcRegIndex];
+ if (src->File == PROGRAM_CONSTANT) {
+ /* a literal */
+ const int component = GET_SWZ(src->Swizzle, channel);
+ const GLfloat *param =
+ c->fp->program.Base.Parameters->ParameterValues[src->Index];
+ GLfloat value = param[component];
+ if (src->Negate & (1 << channel))
+ value = -value;
+ if (src->Abs)
+ value = FABSF(value);
+#if 0
+ printf(" form immed value %f for chan %d\n", value, channel);
+#endif
+ return brw_imm_f(value);
+ }
+ else {
+ return get_src_reg(c, inst, srcRegIndex, channel);
+ }
+}
+
+
+/**
+ * Subroutines are minimal support for resusable instruction sequences.
+ * They are implemented as simply as possible to minimise overhead: there
+ * is no explicit support for communication between the caller and callee
+ * other than saving the return address in a temporary register, nor is
+ * there any automatic local storage. This implies that great care is
+ * required before attempting reentrancy or any kind of nested
+ * subroutine invocations.
+ */
static void invoke_subroutine( struct brw_wm_compile *c,
enum _subroutine subroutine,
void (*emit)( struct brw_wm_compile * ) )
@@ -238,25 +650,8 @@ static void invoke_subroutine( struct brw_wm_compile *c,
}
}
-static void emit_abs( struct brw_wm_compile *c,
- struct prog_instruction *inst)
-{
- int i;
- struct brw_compile *p = &c->func;
- brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
- for (i = 0; i < 4; i++) {
- if (inst->DstReg.WriteMask & (1<<i)) {
- struct brw_reg src, dst;
- dst = get_dst_reg(c, inst, i, 1);
- src = get_src_reg(c, &inst->SrcReg[0], i, 1);
- brw_MOV(p, dst, brw_abs(src));
- }
- }
- brw_set_saturate(p, 0);
-}
-
static void emit_trunc( struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
int i;
struct brw_compile *p = &c->func;
@@ -265,8 +660,8 @@ static void emit_trunc( struct brw_wm_compile *c,
for (i = 0; i < 4; i++) {
if (mask & (1<<i)) {
struct brw_reg src, dst;
- dst = get_dst_reg(c, inst, i, 1) ;
- src = get_src_reg(c, &inst->SrcReg[0], i, 1);
+ dst = get_dst_reg(c, inst, i);
+ src = get_src_reg(c, inst, 0, i);
brw_RNDZ(p, dst, src);
}
}
@@ -274,7 +669,7 @@ static void emit_trunc( struct brw_wm_compile *c,
}
static void emit_mov( struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
int i;
struct brw_compile *p = &c->func;
@@ -283,8 +678,10 @@ static void emit_mov( struct brw_wm_compile *c,
for (i = 0; i < 4; i++) {
if (mask & (1<<i)) {
struct brw_reg src, dst;
- dst = get_dst_reg(c, inst, i, 1);
- src = get_src_reg(c, &inst->SrcReg[0], i, 1);
+ dst = get_dst_reg(c, inst, i);
+ /* XXX some moves from immediate value don't work reliably!!! */
+ /*src = get_src_reg_imm(c, inst, 0, i);*/
+ src = get_src_reg(c, inst, 0, i);
brw_MOV(p, dst, src);
}
}
@@ -292,7 +689,7 @@ static void emit_mov( struct brw_wm_compile *c,
}
static void emit_pixel_xy(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_reg r1 = brw_vec1_grf(1, 0);
struct brw_reg r1_uw = retype(r1, BRW_REGISTER_TYPE_UW);
@@ -301,8 +698,8 @@ static void emit_pixel_xy(struct brw_wm_compile *c,
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
- dst0 = get_dst_reg(c, inst, 0, 1);
- dst1 = get_dst_reg(c, inst, 1, 1);
+ dst0 = get_dst_reg(c, inst, 0);
+ dst1 = get_dst_reg(c, inst, 1);
/* Calculate pixel centers by adding 1 or 0 to each of the
* micro-tile coordinates passed in r1.
*/
@@ -319,21 +716,20 @@ static void emit_pixel_xy(struct brw_wm_compile *c,
stride(suboffset(r1_uw, 5), 2, 4, 0),
brw_imm_v(0x11001100));
}
-
}
static void emit_delta_xy(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_reg r1 = brw_vec1_grf(1, 0);
struct brw_reg dst0, dst1, src0, src1;
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
- dst0 = get_dst_reg(c, inst, 0, 1);
- dst1 = get_dst_reg(c, inst, 1, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- src1 = get_src_reg(c, &inst->SrcReg[0], 1, 1);
+ dst0 = get_dst_reg(c, inst, 0);
+ dst1 = get_dst_reg(c, inst, 1);
+ src0 = get_src_reg(c, inst, 0, 0);
+ src1 = get_src_reg(c, inst, 0, 1);
/* Calc delta X,Y by subtracting origin in r1 from the pixel
* centers.
*/
@@ -351,10 +747,8 @@ static void emit_delta_xy(struct brw_wm_compile *c,
negate(suboffset(r1,1)));
}
-
}
-
static void fire_fb_write( struct brw_wm_compile *c,
GLuint base_reg,
GLuint nr,
@@ -385,7 +779,7 @@ static void fire_fb_write( struct brw_wm_compile *c,
}
static void emit_fb_write(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
int nr = 2;
@@ -397,38 +791,63 @@ static void emit_fb_write(struct brw_wm_compile *c,
*/
if (c->key.aa_dest_stencil_reg)
nr += 1;
- {
- brw_push_insn_state(p);
- for (channel = 0; channel < 4; channel++) {
- src0 = get_src_reg(c, &inst->SrcReg[0], channel, 1);
- /* mov (8) m2.0<1>:ud r28.0<8;8,1>:ud { Align1 } */
- /* mov (8) m6.0<1>:ud r29.0<8;8,1>:ud { Align1 SecHalf } */
- brw_MOV(p, brw_message_reg(nr + channel), src0);
- }
- /* skip over the regs populated above: */
- nr += 8;
- brw_pop_insn_state(p);
+
+ brw_push_insn_state(p);
+ for (channel = 0; channel < 4; channel++) {
+ src0 = get_src_reg(c, inst, 0, channel);
+ /* mov (8) m2.0<1>:ud r28.0<8;8,1>:ud { Align1 } */
+ /* mov (8) m6.0<1>:ud r29.0<8;8,1>:ud { Align1 SecHalf } */
+ brw_MOV(p, brw_message_reg(nr + channel), src0);
}
+ /* skip over the regs populated above: */
+ nr += 8;
+ brw_pop_insn_state(p);
- if (c->key.source_depth_to_render_target)
- {
- if (c->key.computes_depth) {
- src0 = get_src_reg(c, &inst->SrcReg[2], 2, 1);
- brw_MOV(p, brw_message_reg(nr), src0);
- } else {
- src0 = get_src_reg(c, &inst->SrcReg[1], 1, 1);
- brw_MOV(p, brw_message_reg(nr), src0);
- }
+ if (c->key.source_depth_to_render_target) {
+ if (c->key.computes_depth) {
+ src0 = get_src_reg(c, inst, 2, 2);
+ brw_MOV(p, brw_message_reg(nr), src0);
+ }
+ else {
+ src0 = get_src_reg(c, inst, 1, 1);
+ brw_MOV(p, brw_message_reg(nr), src0);
+ }
+
+ nr += 2;
+ }
+
+ if (c->key.dest_depth_reg) {
+ const GLuint comp = c->key.dest_depth_reg / 2;
+ const GLuint off = c->key.dest_depth_reg % 2;
+
+ if (off != 0) {
+ /* XXX this code needs review/testing */
+ struct brw_reg arg1_0 = get_src_reg(c, inst, 1, comp);
+ struct brw_reg arg1_1 = get_src_reg(c, inst, 1, comp+1);
- nr += 2;
+ brw_push_insn_state(p);
+ brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+
+ brw_MOV(p, brw_message_reg(nr), offset(arg1_0, 1));
+ /* 2nd half? */
+ brw_MOV(p, brw_message_reg(nr+1), arg1_1);
+ brw_pop_insn_state(p);
+ }
+ else
+ {
+ struct brw_reg src = get_src_reg(c, inst, 1, 1);
+ brw_MOV(p, brw_message_reg(nr), src);
+ }
+ nr += 2;
}
- target = inst->Sampler >> 1;
- eot = inst->Sampler & 1;
+
+ target = inst->Aux >> 1;
+ eot = inst->Aux & 1;
fire_fb_write(c, 0, nr, target, eot);
}
static void emit_pixel_w( struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
@@ -436,10 +855,10 @@ static void emit_pixel_w( struct brw_wm_compile *c,
struct brw_reg dst, src0, delta0, delta1;
struct brw_reg interp3;
- dst = get_dst_reg(c, inst, 3, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- delta0 = get_src_reg(c, &inst->SrcReg[1], 0, 1);
- delta1 = get_src_reg(c, &inst->SrcReg[1], 1, 1);
+ dst = get_dst_reg(c, inst, 3);
+ src0 = get_src_reg(c, inst, 0, 0);
+ delta0 = get_src_reg(c, inst, 1, 0);
+ delta1 = get_src_reg(c, inst, 1, 1);
interp3 = brw_vec1_grf(src0.nr+1, 4);
/* Calc 1/w - just linterp wpos[3] optimized by putting the
@@ -458,19 +877,19 @@ static void emit_pixel_w( struct brw_wm_compile *c,
}
static void emit_linterp(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
struct brw_reg interp[4];
struct brw_reg dst, delta0, delta1;
struct brw_reg src0;
+ GLuint nr, i;
- src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- delta0 = get_src_reg(c, &inst->SrcReg[1], 0, 1);
- delta1 = get_src_reg(c, &inst->SrcReg[1], 1, 1);
- GLuint nr = src0.nr;
- int i;
+ src0 = get_src_reg(c, inst, 0, 0);
+ delta0 = get_src_reg(c, inst, 1, 0);
+ delta1 = get_src_reg(c, inst, 1, 1);
+ nr = src0.nr;
interp[0] = brw_vec1_grf(nr, 0);
interp[1] = brw_vec1_grf(nr, 4);
@@ -479,7 +898,7 @@ static void emit_linterp(struct brw_wm_compile *c,
for(i = 0; i < 4; i++ ) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
+ dst = get_dst_reg(c, inst, i);
brw_LINE(p, brw_null_reg(), interp[i], delta0);
brw_MAC(p, dst, suboffset(interp[i],1), delta1);
}
@@ -487,17 +906,17 @@ static void emit_linterp(struct brw_wm_compile *c,
}
static void emit_cinterp(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
struct brw_reg interp[4];
struct brw_reg dst, src0;
+ GLuint nr, i;
- src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- GLuint nr = src0.nr;
- int i;
+ src0 = get_src_reg(c, inst, 0, 0);
+ nr = src0.nr;
interp[0] = brw_vec1_grf(nr, 0);
interp[1] = brw_vec1_grf(nr, 4);
@@ -506,14 +925,14 @@ static void emit_cinterp(struct brw_wm_compile *c,
for(i = 0; i < 4; i++ ) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
+ dst = get_dst_reg(c, inst, i);
brw_MOV(p, dst, suboffset(interp[i],3));
}
}
}
static void emit_pinterp(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
@@ -521,13 +940,13 @@ static void emit_pinterp(struct brw_wm_compile *c,
struct brw_reg interp[4];
struct brw_reg dst, delta0, delta1;
struct brw_reg src0, w;
+ GLuint nr, i;
- src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- delta0 = get_src_reg(c, &inst->SrcReg[1], 0, 1);
- delta1 = get_src_reg(c, &inst->SrcReg[1], 1, 1);
- w = get_src_reg(c, &inst->SrcReg[2], 3, 1);
- GLuint nr = src0.nr;
- int i;
+ src0 = get_src_reg(c, inst, 0, 0);
+ delta0 = get_src_reg(c, inst, 1, 0);
+ delta1 = get_src_reg(c, inst, 1, 1);
+ w = get_src_reg(c, inst, 2, 3);
+ nr = src0.nr;
interp[0] = brw_vec1_grf(nr, 0);
interp[1] = brw_vec1_grf(nr, 4);
@@ -536,7 +955,7 @@ static void emit_pinterp(struct brw_wm_compile *c,
for(i = 0; i < 4; i++ ) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
+ dst = get_dst_reg(c, inst, i);
brw_LINE(p, brw_null_reg(), interp[i], delta0);
brw_MAC(p, dst, suboffset(interp[i],1),
delta1);
@@ -545,8 +964,38 @@ static void emit_pinterp(struct brw_wm_compile *c,
}
}
+/* Sets the destination channels to 1.0 or 0.0 according to glFrontFacing. */
+static void emit_frontfacing(struct brw_wm_compile *c,
+ const struct prog_instruction *inst)
+{
+ struct brw_compile *p = &c->func;
+ struct brw_reg r1_6ud = retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD);
+ struct brw_reg dst;
+ GLuint mask = inst->DstReg.WriteMask;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ brw_MOV(p, dst, brw_imm_f(0.0));
+ }
+ }
+
+ /* bit 31 is "primitive is back face", so checking < (1 << 31) gives
+ * us front face
+ */
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, r1_6ud, brw_imm_ud(1 << 31));
+ for (i = 0; i < 4; i++) {
+ if (mask & (1<<i)) {
+ dst = get_dst_reg(c, inst, i);
+ brw_MOV(p, dst, brw_imm_f(1.0));
+ }
+ }
+ brw_set_predicate_control_flag_value(p, 0xff);
+}
+
static void emit_xpd(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
int i;
struct brw_compile *p = &c->func;
@@ -556,12 +1005,12 @@ static void emit_xpd(struct brw_wm_compile *c,
GLuint i1 = (i+1)%3;
if (mask & (1<<i)) {
struct brw_reg src0, src1, dst;
- dst = get_dst_reg(c, inst, i, 1);
- src0 = negate(get_src_reg(c, &inst->SrcReg[0], i2, 1));
- src1 = get_src_reg(c, &inst->SrcReg[1], i1, 1);
+ dst = get_dst_reg(c, inst, i);
+ src0 = negate(get_src_reg(c, inst, 0, i2));
+ src1 = get_src_reg_imm(c, inst, 1, i1);
brw_MUL(p, brw_null_reg(), src0, src1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i1, 1);
- src1 = get_src_reg(c, &inst->SrcReg[1], i2, 1);
+ src0 = get_src_reg(c, inst, 0, i1);
+ src1 = get_src_reg_imm(c, inst, 1, i2);
brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
brw_MAC(p, dst, src0, src1);
brw_set_saturate(p, 0);
@@ -571,17 +1020,25 @@ static void emit_xpd(struct brw_wm_compile *c,
}
static void emit_dp3(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_reg src0[3], src1[3], dst;
int i;
struct brw_compile *p = &c->func;
+ GLuint mask = inst->DstReg.WriteMask;
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
+ if (!(mask & WRITEMASK_XYZW))
+ return;
+
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
+
for (i = 0; i < 3; i++) {
- src0[i] = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1[i] = get_src_reg(c, &inst->SrcReg[1], i, 1);
+ src0[i] = get_src_reg(c, inst, 0, i);
+ src1[i] = get_src_reg_imm(c, inst, 1, i);
}
- dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1);
+ dst = get_dst_reg(c, inst, dst_chan);
brw_MUL(p, brw_null_reg(), src0[0], src1[0]);
brw_MAC(p, brw_null_reg(), src0[1], src1[1]);
brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
@@ -590,16 +1047,24 @@ static void emit_dp3(struct brw_wm_compile *c,
}
static void emit_dp4(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_reg src0[4], src1[4], dst;
int i;
struct brw_compile *p = &c->func;
+ GLuint mask = inst->DstReg.WriteMask;
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
+ if (!(mask & WRITEMASK_XYZW))
+ return;
+
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
+
for (i = 0; i < 4; i++) {
- src0[i] = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1[i] = get_src_reg(c, &inst->SrcReg[1], i, 1);
+ src0[i] = get_src_reg(c, inst, 0, i);
+ src1[i] = get_src_reg_imm(c, inst, 1, i);
}
- dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1);
+ dst = get_dst_reg(c, inst, dst_chan);
brw_MUL(p, brw_null_reg(), src0[0], src1[0]);
brw_MAC(p, brw_null_reg(), src0[1], src1[1]);
brw_MAC(p, brw_null_reg(), src0[2], src1[2]);
@@ -609,16 +1074,24 @@ static void emit_dp4(struct brw_wm_compile *c,
}
static void emit_dph(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_reg src0[4], src1[4], dst;
int i;
struct brw_compile *p = &c->func;
+ GLuint mask = inst->DstReg.WriteMask;
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
+ if (!(mask & WRITEMASK_XYZW))
+ return;
+
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
+
for (i = 0; i < 4; i++) {
- src0[i] = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1[i] = get_src_reg(c, &inst->SrcReg[1], i, 1);
+ src0[i] = get_src_reg(c, inst, 0, i);
+ src1[i] = get_src_reg_imm(c, inst, 1, i);
}
- dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1);
+ dst = get_dst_reg(c, inst, dst_chan);
brw_MUL(p, brw_null_reg(), src0[0], src1[0]);
brw_MAC(p, brw_null_reg(), src0[1], src1[1]);
brw_MAC(p, dst, src0[2], src1[2]);
@@ -627,63 +1100,77 @@ static void emit_dph(struct brw_wm_compile *c,
brw_set_saturate(p, 0);
}
+/**
+ * Emit a scalar instruction, like RCP, RSQ, LOG, EXP.
+ * Note that the result of the function is smeared across the dest
+ * register's X, Y, Z and W channels (subject to writemasking of course).
+ */
static void emit_math1(struct brw_wm_compile *c,
- struct prog_instruction *inst, GLuint func)
+ const struct prog_instruction *inst, GLuint func)
{
struct brw_compile *p = &c->func;
struct brw_reg src0, dst;
+ GLuint mask = inst->DstReg.WriteMask;
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
+ if (!(mask & WRITEMASK_XYZW))
+ return;
+
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
+
+ /* Get first component of source register */
+ dst = get_dst_reg(c, inst, dst_chan);
+ src0 = get_src_reg(c, inst, 0, 0);
- src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1);
brw_MOV(p, brw_message_reg(2), src0);
brw_math(p,
- dst,
- func,
- (inst->SaturateMode != SATURATE_OFF) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE,
- 2,
- brw_null_reg(),
- BRW_MATH_DATA_VECTOR,
- BRW_MATH_PRECISION_FULL);
+ dst,
+ func,
+ (inst->SaturateMode != SATURATE_OFF) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE,
+ 2,
+ brw_null_reg(),
+ BRW_MATH_DATA_VECTOR,
+ BRW_MATH_PRECISION_FULL);
}
static void emit_rcp(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_math1(c, inst, BRW_MATH_FUNCTION_INV);
}
static void emit_rsq(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_math1(c, inst, BRW_MATH_FUNCTION_RSQ);
}
static void emit_sin(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_math1(c, inst, BRW_MATH_FUNCTION_SIN);
}
static void emit_cos(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_math1(c, inst, BRW_MATH_FUNCTION_COS);
}
static void emit_ex2(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_math1(c, inst, BRW_MATH_FUNCTION_EXP);
}
static void emit_lg2(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_math1(c, inst, BRW_MATH_FUNCTION_LOG);
}
static void emit_add(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
struct brw_reg src0, src1, dst;
@@ -692,36 +1179,31 @@ static void emit_add(struct brw_wm_compile *c,
brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
for (i = 0 ; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, inst, 0, i);
+ src1 = get_src_reg_imm(c, inst, 1, i);
brw_ADD(p, dst, src0, src1);
}
}
brw_set_saturate(p, 0);
}
-static void emit_sub(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+static void emit_arl(struct brw_wm_compile *c,
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
- struct brw_reg src0, src1, dst;
- GLuint mask = inst->DstReg.WriteMask;
- int i;
+ struct brw_reg src0, addr_reg;
brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
- for (i = 0 ; i < 4; i++) {
- if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);
- brw_ADD(p, dst, src0, negate(src1));
- }
- }
+ addr_reg = brw_uw8_reg(BRW_ARCHITECTURE_REGISTER_FILE,
+ BRW_ARF_ADDRESS, 0);
+ src0 = get_src_reg(c, inst, 0, 0); /* channel 0 */
+ brw_MOV(p, addr_reg, src0);
brw_set_saturate(p, 0);
}
+
static void emit_mul(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
struct brw_reg src0, src1, dst;
@@ -730,9 +1212,9 @@ static void emit_mul(struct brw_wm_compile *c,
brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
for (i = 0 ; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, inst, 0, i);
+ src1 = get_src_reg_imm(c, inst, 1, i);
brw_MUL(p, dst, src0, src1);
}
}
@@ -740,7 +1222,7 @@ static void emit_mul(struct brw_wm_compile *c,
}
static void emit_frc(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
struct brw_reg src0, dst;
@@ -749,8 +1231,8 @@ static void emit_frc(struct brw_wm_compile *c,
brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
for (i = 0 ; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg_imm(c, inst, 0, i);
brw_FRC(p, dst, src0);
}
}
@@ -759,7 +1241,7 @@ static void emit_frc(struct brw_wm_compile *c,
}
static void emit_flr(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
struct brw_reg src0, dst;
@@ -768,78 +1250,79 @@ static void emit_flr(struct brw_wm_compile *c,
brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
for (i = 0 ; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg_imm(c, inst, 0, i);
brw_RNDD(p, dst, src0);
}
}
brw_set_saturate(p, 0);
}
-static void emit_max(struct brw_wm_compile *c,
- struct prog_instruction *inst)
-{
- struct brw_compile *p = &c->func;
- GLuint mask = inst->DstReg.WriteMask;
- struct brw_reg src0, src1, dst;
- int i;
- brw_push_insn_state(p);
- for (i = 0; i < 4; i++) {
- if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);
- brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
- brw_MOV(p, dst, src0);
- brw_set_saturate(p, 0);
-
- brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, src0, src1);
- brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
- brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
- brw_MOV(p, dst, src1);
- brw_set_saturate(p, 0);
- brw_set_predicate_control_flag_value(p, 0xff);
- }
- }
- brw_pop_insn_state(p);
-}
-static void emit_min(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+static void emit_min_max(struct brw_wm_compile *c,
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
- GLuint mask = inst->DstReg.WriteMask;
- struct brw_reg src0, src1, dst;
+ const GLuint mask = inst->DstReg.WriteMask;
+ const int mark = mark_tmps(c);
int i;
brw_push_insn_state(p);
for (i = 0; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);
+ struct brw_reg real_dst = get_dst_reg(c, inst, i);
+ struct brw_reg src0 = get_src_reg(c, inst, 0, i);
+ struct brw_reg src1 = get_src_reg(c, inst, 1, i);
+ struct brw_reg dst;
+ /* if dst==src0 or dst==src1 we need to use a temp reg */
+ GLboolean use_temp = brw_same_reg(dst, src0) ||
+ brw_same_reg(dst, src1);
+ if (use_temp)
+ dst = alloc_tmp(c);
+ else
+ dst = real_dst;
+
+ /*
+ printf(" Min/max: dst %d src0 %d src1 %d\n",
+ dst.nr, src0.nr, src1.nr);
+ */
brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
brw_MOV(p, dst, src0);
brw_set_saturate(p, 0);
- brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, src1, src0);
+ if (inst->Opcode == OPCODE_MIN)
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, src1, src0);
+ else
+ brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_G, src1, src0);
+
brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
brw_MOV(p, dst, src1);
brw_set_saturate(p, 0);
brw_set_predicate_control_flag_value(p, 0xff);
+ if (use_temp)
+ brw_MOV(p, real_dst, dst);
}
}
brw_pop_insn_state(p);
+ release_tmps(c, mark);
}
static void emit_pow(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
struct brw_reg dst, src0, src1;
- dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- src1 = get_src_reg(c, &inst->SrcReg[1], 0, 1);
+ GLuint mask = inst->DstReg.WriteMask;
+ int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
+ if (!(mask & WRITEMASK_XYZW))
+ return;
+
+ assert(is_power_of_two(mask & WRITEMASK_XYZW));
+
+ dst = get_dst_reg(c, inst, dst_chan);
+ src0 = get_src_reg_imm(c, inst, 0, 0);
+ src1 = get_src_reg_imm(c, inst, 1, 0);
brw_MOV(p, brw_message_reg(2), src0);
brw_MOV(p, brw_message_reg(3), src1);
@@ -855,7 +1338,7 @@ static void emit_pow(struct brw_wm_compile *c,
}
static void emit_lrp(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
@@ -864,10 +1347,10 @@ static void emit_lrp(struct brw_wm_compile *c,
int mark = mark_tmps(c);
for (i = 0; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, inst, 0, i);
- src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);
+ src1 = get_src_reg_imm(c, inst, 1, i);
if (src1.nr == dst.nr) {
tmp1 = alloc_tmp(c);
@@ -875,7 +1358,7 @@ static void emit_lrp(struct brw_wm_compile *c,
} else
tmp1 = src1;
- src2 = get_src_reg(c, &inst->SrcReg[2], i, 1);
+ src2 = get_src_reg(c, inst, 2, i);
if (src2.nr == dst.nr) {
tmp2 = alloc_tmp(c);
brw_MOV(p, tmp2, src2);
@@ -908,7 +1391,7 @@ static void emit_kil(struct brw_wm_compile *c)
}
static void emit_mad(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
@@ -917,10 +1400,10 @@ static void emit_mad(struct brw_wm_compile *c,
for (i = 0; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);
- src2 = get_src_reg(c, &inst->SrcReg[2], i, 1);
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, inst, 0, i);
+ src1 = get_src_reg_imm(c, inst, 1, i);
+ src2 = get_src_reg_imm(c, inst, 2, i);
brw_MUL(p, dst, src0, src1);
brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0);
@@ -931,7 +1414,7 @@ static void emit_mad(struct brw_wm_compile *c,
}
static void emit_sop(struct brw_wm_compile *c,
- struct prog_instruction *inst, GLuint cond)
+ const struct prog_instruction *inst, GLuint cond)
{
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
@@ -940,9 +1423,9 @@ static void emit_sop(struct brw_wm_compile *c,
for (i = 0; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- src0 = get_src_reg(c, &inst->SrcReg[0], i, 1);
- src1 = get_src_reg(c, &inst->SrcReg[1], i, 1);
+ dst = get_dst_reg(c, inst, i);
+ src0 = get_src_reg(c, inst, 0, i);
+ src1 = get_src_reg_imm(c, inst, 1, i);
brw_push_insn_state(p);
brw_CMP(p, brw_null_reg(), cond, src0, src1);
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
@@ -955,113 +1438,58 @@ static void emit_sop(struct brw_wm_compile *c,
}
static void emit_slt(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_sop(c, inst, BRW_CONDITIONAL_L);
}
static void emit_sle(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_sop(c, inst, BRW_CONDITIONAL_LE);
}
static void emit_sgt(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_sop(c, inst, BRW_CONDITIONAL_G);
}
static void emit_sge(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_sop(c, inst, BRW_CONDITIONAL_GE);
}
static void emit_seq(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_sop(c, inst, BRW_CONDITIONAL_EQ);
}
static void emit_sne(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
emit_sop(c, inst, BRW_CONDITIONAL_NEQ);
}
-static void emit_ddx(struct brw_wm_compile *c,
- struct prog_instruction *inst)
-{
- struct brw_compile *p = &c->func;
- GLuint mask = inst->DstReg.WriteMask;
- struct brw_reg interp[4];
- struct brw_reg dst;
- struct brw_reg src0, w;
- GLuint nr, i;
- src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- w = get_src_reg(c, &inst->SrcReg[1], 3, 1);
- nr = src0.nr;
- interp[0] = brw_vec1_grf(nr, 0);
- interp[1] = brw_vec1_grf(nr, 4);
- interp[2] = brw_vec1_grf(nr+1, 0);
- interp[3] = brw_vec1_grf(nr+1, 4);
- brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
- for(i = 0; i < 4; i++ ) {
- if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- brw_MOV(p, dst, interp[i]);
- brw_MUL(p, dst, dst, w);
- }
- }
- brw_set_saturate(p, 0);
-}
-
-static void emit_ddy(struct brw_wm_compile *c,
- struct prog_instruction *inst)
-{
- struct brw_compile *p = &c->func;
- GLuint mask = inst->DstReg.WriteMask;
- struct brw_reg interp[4];
- struct brw_reg dst;
- struct brw_reg src0, w;
- GLuint nr, i;
-
- src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- nr = src0.nr;
- w = get_src_reg(c, &inst->SrcReg[1], 3, 1);
- interp[0] = brw_vec1_grf(nr, 0);
- interp[1] = brw_vec1_grf(nr, 4);
- interp[2] = brw_vec1_grf(nr+1, 0);
- interp[3] = brw_vec1_grf(nr+1, 4);
- brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
- for(i = 0; i < 4; i++ ) {
- if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
- brw_MOV(p, dst, suboffset(interp[i], 1));
- brw_MUL(p, dst, dst, w);
- }
- }
- brw_set_saturate(p, 0);
-}
-
-static __inline struct brw_reg high_words( struct brw_reg reg )
+static INLINE struct brw_reg high_words( struct brw_reg reg )
{
return stride( suboffset( retype( reg, BRW_REGISTER_TYPE_W ), 1 ),
0, 8, 2 );
}
-static __inline struct brw_reg low_words( struct brw_reg reg )
+static INLINE struct brw_reg low_words( struct brw_reg reg )
{
return stride( retype( reg, BRW_REGISTER_TYPE_W ), 0, 8, 2 );
}
-static __inline struct brw_reg even_bytes( struct brw_reg reg )
+static INLINE struct brw_reg even_bytes( struct brw_reg reg )
{
return stride( retype( reg, BRW_REGISTER_TYPE_B ), 0, 16, 2 );
}
-static __inline struct brw_reg odd_bytes( struct brw_reg reg )
+static INLINE struct brw_reg odd_bytes( struct brw_reg reg )
{
return stride( suboffset( retype( reg, BRW_REGISTER_TYPE_B ), 1 ),
0, 16, 2 );
@@ -1161,7 +1589,7 @@ static void noise1_sub( struct brw_wm_compile *c ) {
}
static void emit_noise1( struct brw_wm_compile *c,
- struct prog_instruction *inst )
+ const struct prog_instruction *inst )
{
struct brw_compile *p = &c->func;
struct brw_reg src, param, dst;
@@ -1171,7 +1599,7 @@ static void emit_noise1( struct brw_wm_compile *c,
assert( mark == 0 );
- src = get_src_reg( c, inst->SrcReg, 0, 1 );
+ src = get_src_reg( c, inst, 0, 0 );
param = alloc_tmp( c );
@@ -1183,7 +1611,7 @@ static void emit_noise1( struct brw_wm_compile *c,
brw_set_saturate( p, inst->SaturateMode == SATURATE_ZERO_ONE );
for (i = 0 ; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
+ dst = get_dst_reg(c, inst, i);
brw_MOV( p, dst, param );
}
}
@@ -1331,7 +1759,7 @@ static void noise2_sub( struct brw_wm_compile *c ) {
}
static void emit_noise2( struct brw_wm_compile *c,
- struct prog_instruction *inst )
+ const struct prog_instruction *inst )
{
struct brw_compile *p = &c->func;
struct brw_reg src0, src1, param0, param1, dst;
@@ -1341,8 +1769,8 @@ static void emit_noise2( struct brw_wm_compile *c,
assert( mark == 0 );
- src0 = get_src_reg( c, inst->SrcReg, 0, 1 );
- src1 = get_src_reg( c, inst->SrcReg, 1, 1 );
+ src0 = get_src_reg( c, inst, 0, 0 );
+ src1 = get_src_reg( c, inst, 0, 1 );
param0 = alloc_tmp( c );
param1 = alloc_tmp( c );
@@ -1356,7 +1784,7 @@ static void emit_noise2( struct brw_wm_compile *c,
brw_set_saturate( p, inst->SaturateMode == SATURATE_ZERO_ONE );
for (i = 0 ; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
+ dst = get_dst_reg(c, inst, i);
brw_MOV( p, dst, param0 );
}
}
@@ -1366,9 +1794,11 @@ static void emit_noise2( struct brw_wm_compile *c,
release_tmps( c, mark );
}
-/* The three-dimensional case is much like the one- and two- versions above,
- but since the number of corners is rapidly growing we now pack 16 16-bit
- hashes into each register to extract more parallelism from the EUs. */
+/**
+ * The three-dimensional case is much like the one- and two- versions above,
+ * but since the number of corners is rapidly growing we now pack 16 16-bit
+ * hashes into each register to extract more parallelism from the EUs.
+ */
static void noise3_sub( struct brw_wm_compile *c ) {
struct brw_compile *p = &c->func;
@@ -1632,7 +2062,7 @@ static void noise3_sub( struct brw_wm_compile *c ) {
}
static void emit_noise3( struct brw_wm_compile *c,
- struct prog_instruction *inst )
+ const struct prog_instruction *inst )
{
struct brw_compile *p = &c->func;
struct brw_reg src0, src1, src2, param0, param1, param2, dst;
@@ -1642,9 +2072,9 @@ static void emit_noise3( struct brw_wm_compile *c,
assert( mark == 0 );
- src0 = get_src_reg( c, inst->SrcReg, 0, 1 );
- src1 = get_src_reg( c, inst->SrcReg, 1, 1 );
- src2 = get_src_reg( c, inst->SrcReg, 2, 1 );
+ src0 = get_src_reg( c, inst, 0, 0 );
+ src1 = get_src_reg( c, inst, 0, 1 );
+ src2 = get_src_reg( c, inst, 0, 2 );
param0 = alloc_tmp( c );
param1 = alloc_tmp( c );
@@ -1660,7 +2090,7 @@ static void emit_noise3( struct brw_wm_compile *c,
brw_set_saturate( p, inst->SaturateMode == SATURATE_ZERO_ONE );
for (i = 0 ; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
+ dst = get_dst_reg(c, inst, i);
brw_MOV( p, dst, param0 );
}
}
@@ -1670,13 +2100,15 @@ static void emit_noise3( struct brw_wm_compile *c,
release_tmps( c, mark );
}
-/* For the four-dimensional case, the little micro-optimisation benefits
- we obtain by unrolling all the loops aren't worth the massive bloat it
- now causes. Instead, we loop twice around performing a similar operation
- to noise3, once for the w=0 cube and once for the w=1, with a bit more
- code to glue it all together. */
-static void noise4_sub( struct brw_wm_compile *c ) {
-
+/**
+ * For the four-dimensional case, the little micro-optimisation benefits
+ * we obtain by unrolling all the loops aren't worth the massive bloat it
+ * now causes. Instead, we loop twice around performing a similar operation
+ * to noise3, once for the w=0 cube and once for the w=1, with a bit more
+ * code to glue it all together.
+ */
+static void noise4_sub( struct brw_wm_compile *c )
+{
struct brw_compile *p = &c->func;
struct brw_reg param[ 4 ],
x0y0, x0y1, x1y0, x1y1, /* gradients at four of the corners */
@@ -2053,7 +2485,7 @@ static void noise4_sub( struct brw_wm_compile *c ) {
}
static void emit_noise4( struct brw_wm_compile *c,
- struct prog_instruction *inst )
+ const struct prog_instruction *inst )
{
struct brw_compile *p = &c->func;
struct brw_reg src0, src1, src2, src3, param0, param1, param2, param3, dst;
@@ -2063,10 +2495,10 @@ static void emit_noise4( struct brw_wm_compile *c,
assert( mark == 0 );
- src0 = get_src_reg( c, inst->SrcReg, 0, 1 );
- src1 = get_src_reg( c, inst->SrcReg, 1, 1 );
- src2 = get_src_reg( c, inst->SrcReg, 2, 1 );
- src3 = get_src_reg( c, inst->SrcReg, 3, 1 );
+ src0 = get_src_reg( c, inst, 0, 0 );
+ src1 = get_src_reg( c, inst, 0, 1 );
+ src2 = get_src_reg( c, inst, 0, 2 );
+ src3 = get_src_reg( c, inst, 0, 3 );
param0 = alloc_tmp( c );
param1 = alloc_tmp( c );
@@ -2084,7 +2516,7 @@ static void emit_noise4( struct brw_wm_compile *c,
brw_set_saturate( p, inst->SaturateMode == SATURATE_ZERO_ONE );
for (i = 0 ; i < 4; i++) {
if (mask & (1<<i)) {
- dst = get_dst_reg(c, inst, i, 1);
+ dst = get_dst_reg(c, inst, i);
brw_MOV( p, dst, param0 );
}
}
@@ -2095,17 +2527,17 @@ static void emit_noise4( struct brw_wm_compile *c,
}
static void emit_wpos_xy(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
GLuint mask = inst->DstReg.WriteMask;
struct brw_reg src0[2], dst[2];
- dst[0] = get_dst_reg(c, inst, 0, 1);
- dst[1] = get_dst_reg(c, inst, 1, 1);
+ dst[0] = get_dst_reg(c, inst, 0);
+ dst[1] = get_dst_reg(c, inst, 1);
- src0[0] = get_src_reg(c, &inst->SrcReg[0], 0, 1);
- src0[1] = get_src_reg(c, &inst->SrcReg[0], 1, 1);
+ src0[0] = get_src_reg(c, inst, 0, 0);
+ src0[1] = get_src_reg(c, inst, 0, 1);
/* Calculate the pixel offset from window bottom left into destination
* X and Y channels.
@@ -2128,27 +2560,32 @@ static void emit_wpos_xy(struct brw_wm_compile *c,
}
/* TODO
- BIAS on SIMD8 not workind yet...
+ BIAS on SIMD8 not working yet...
*/
static void emit_txb(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
struct brw_reg dst[4], src[4], payload_reg;
- GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
-
+ /* Note: TexSrcUnit was already looked up through SamplerTextures[] */
+ const GLuint unit = inst->TexSrcUnit;
GLuint i;
+ GLuint msg_type;
+
+ assert(unit < BRW_MAX_TEX_UNIT);
+
payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0);
+
for (i = 0; i < 4; i++)
- dst[i] = get_dst_reg(c, inst, i, 1);
+ dst[i] = get_dst_reg(c, inst, i);
for (i = 0; i < 4; i++)
- src[i] = get_src_reg(c, &inst->SrcReg[0], i, 1);
+ src[i] = get_src_reg(c, inst, 0, i);
switch (inst->TexSrcTarget) {
case TEXTURE_1D_INDEX:
- brw_MOV(p, brw_message_reg(2), src[0]);
- brw_MOV(p, brw_message_reg(3), brw_imm_f(0));
- brw_MOV(p, brw_message_reg(4), brw_imm_f(0));
+ brw_MOV(p, brw_message_reg(2), src[0]); /* s coord */
+ brw_MOV(p, brw_message_reg(3), brw_imm_f(0)); /* t coord */
+ brw_MOV(p, brw_message_reg(4), brw_imm_f(0)); /* r coord */
break;
case TEXTURE_2D_INDEX:
case TEXTURE_RECT_INDEX:
@@ -2156,46 +2593,63 @@ static void emit_txb(struct brw_wm_compile *c,
brw_MOV(p, brw_message_reg(3), src[1]);
brw_MOV(p, brw_message_reg(4), brw_imm_f(0));
break;
- default:
+ case TEXTURE_3D_INDEX:
+ case TEXTURE_CUBE_INDEX:
brw_MOV(p, brw_message_reg(2), src[0]);
brw_MOV(p, brw_message_reg(3), src[1]);
brw_MOV(p, brw_message_reg(4), src[2]);
break;
+ default:
+ /* invalid target */
+ abort();
}
- brw_MOV(p, brw_message_reg(5), src[3]);
- brw_MOV(p, brw_message_reg(6), brw_imm_f(0));
+ brw_MOV(p, brw_message_reg(5), src[3]); /* bias */
+ brw_MOV(p, brw_message_reg(6), brw_imm_f(0)); /* ref (unused?) */
+
+ if (BRW_IS_IGDNG(p->brw)) {
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_BIAS_IGDNG;
+ } else {
+ /* Does it work well on SIMD8? */
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS;
+ }
+
brw_SAMPLE(p,
- retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
- 1,
- retype(payload_reg, BRW_REGISTER_TYPE_UW),
- unit + MAX_DRAW_BUFFERS, /* surface */
- unit, /* sampler */
- inst->DstReg.WriteMask,
- BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
- 4,
- 4,
- 0);
+ retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW), /* dest */
+ 1, /* msg_reg_nr */
+ retype(payload_reg, BRW_REGISTER_TYPE_UW), /* src0 */
+ SURF_INDEX_TEXTURE(unit),
+ unit, /* sampler */
+ inst->DstReg.WriteMask, /* writemask */
+ msg_type, /* msg_type */
+ 4, /* response_length */
+ 4, /* msg_length */
+ 0, /* eot */
+ 1,
+ BRW_SAMPLER_SIMD_MODE_SIMD8);
}
+
static void emit_tex(struct brw_wm_compile *c,
- struct prog_instruction *inst)
+ const struct prog_instruction *inst)
{
struct brw_compile *p = &c->func;
struct brw_reg dst[4], src[4], payload_reg;
- GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
-
+ /* Note: TexSrcUnit was already looked up through SamplerTextures[] */
+ const GLuint unit = inst->TexSrcUnit;
GLuint msg_len;
GLuint i, nr;
GLuint emit;
GLboolean shadow = (c->key.shadowtex_mask & (1<<unit)) ? 1 : 0;
+ GLuint msg_type;
+
+ assert(unit < BRW_MAX_TEX_UNIT);
payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0);
for (i = 0; i < 4; i++)
- dst[i] = get_dst_reg(c, inst, i, 1);
+ dst[i] = get_dst_reg(c, inst, i);
for (i = 0; i < 4; i++)
- src[i] = get_src_reg(c, &inst->SrcReg[0], i, 1);
-
+ src[i] = get_src_reg(c, inst, 0, i);
switch (inst->TexSrcTarget) {
case TEXTURE_1D_INDEX:
@@ -2207,13 +2661,18 @@ static void emit_tex(struct brw_wm_compile *c,
emit = WRITEMASK_XY;
nr = 2;
break;
- default:
+ case TEXTURE_3D_INDEX:
+ case TEXTURE_CUBE_INDEX:
emit = WRITEMASK_XYZ;
nr = 3;
break;
+ default:
+ /* invalid target */
+ abort();
}
msg_len = 1;
+ /* move/load S, T, R coords */
for (i = 0; i < nr; i++) {
static const GLuint swz[4] = {0,1,2,2};
if (emit & (1<<i))
@@ -2224,77 +2683,103 @@ static void emit_tex(struct brw_wm_compile *c,
}
if (shadow) {
- brw_MOV(p, brw_message_reg(5), brw_imm_f(0));
- brw_MOV(p, brw_message_reg(6), src[2]);
+ brw_MOV(p, brw_message_reg(5), brw_imm_f(0)); /* lod / bias */
+ brw_MOV(p, brw_message_reg(6), src[2]); /* ref value / R coord */
}
+ if (BRW_IS_IGDNG(p->brw)) {
+ if (shadow)
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_COMPARE_IGDNG;
+ else
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_IGDNG;
+ } else {
+ /* Does it work for shadow on SIMD8 ? */
+ msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE;
+ }
+
brw_SAMPLE(p,
- retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
- 1,
- retype(payload_reg, BRW_REGISTER_TYPE_UW),
- unit + MAX_DRAW_BUFFERS, /* surface */
- unit, /* sampler */
- inst->DstReg.WriteMask,
- BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE,
- 4,
- shadow ? 6 : 4,
- 0);
+ retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW), /* dest */
+ 1, /* msg_reg_nr */
+ retype(payload_reg, BRW_REGISTER_TYPE_UW), /* src0 */
+ SURF_INDEX_TEXTURE(unit),
+ unit, /* sampler */
+ inst->DstReg.WriteMask, /* writemask */
+ msg_type, /* msg_type */
+ 4, /* response_length */
+ shadow ? 6 : 4, /* msg_length */
+ 0, /* eot */
+ 1,
+ BRW_SAMPLER_SIMD_MODE_SIMD8);
if (shadow)
brw_MOV(p, dst[3], brw_imm_f(1.0));
}
+
+/**
+ * Resolve subroutine calls after code emit is done.
+ */
static void post_wm_emit( struct brw_wm_compile *c )
{
- GLuint nr_insns = c->fp->program.Base.NumInstructions;
- GLuint insn, target_insn;
- struct prog_instruction *inst1, *inst2;
- struct brw_instruction *brw_inst1, *brw_inst2;
- int offset;
- for (insn = 0; insn < nr_insns; insn++) {
- inst1 = &c->fp->program.Base.Instructions[insn];
- brw_inst1 = inst1->Data;
- switch (inst1->Opcode) {
- case OPCODE_CAL:
- target_insn = inst1->BranchTarget;
- inst2 = &c->fp->program.Base.Instructions[target_insn];
- brw_inst2 = inst2->Data;
- offset = brw_inst2 - brw_inst1;
- brw_set_src1(brw_inst1, brw_imm_d(offset*16));
- break;
- default:
- break;
- }
+ brw_resolve_cals(&c->func);
+}
+
+static void
+get_argument_regs(struct brw_wm_compile *c,
+ const struct prog_instruction *inst,
+ int index,
+ struct brw_reg *regs,
+ int mask)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (mask & (1 << i))
+ regs[i] = get_src_reg(c, inst, index, i);
}
}
static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
{
-#define MAX_IFSN 32
+#define MAX_IF_DEPTH 32
#define MAX_LOOP_DEPTH 32
- struct brw_instruction *if_inst[MAX_IFSN], *loop_inst[MAX_LOOP_DEPTH];
- struct brw_instruction *inst0, *inst1;
- int i, if_insn = 0, loop_insn = 0;
+ struct brw_instruction *if_inst[MAX_IF_DEPTH], *loop_inst[MAX_LOOP_DEPTH];
+ GLuint i, if_depth = 0, loop_depth = 0;
struct brw_compile *p = &c->func;
struct brw_indirect stack_index = brw_indirect(0, 0);
- c->reg_index = 0;
+ c->out_of_regs = GL_FALSE;
+
prealloc_reg(c);
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
brw_MOV(p, get_addr_reg(stack_index), brw_address(c->stack));
for (i = 0; i < c->nr_fp_insns; i++) {
- struct prog_instruction *inst = &c->prog_instructions[i];
- struct prog_instruction *orig_inst;
+ const struct prog_instruction *inst = &c->prog_instructions[i];
+ int dst_flags;
+ struct brw_reg args[3][4], dst[4];
+ int j;
- if ((orig_inst = inst->Data) != 0)
- orig_inst->Data = current_insn(p);
+ c->cur_inst = i;
+
+#if 0
+ _mesa_printf("Inst %d: ", i);
+ _mesa_print_instruction(inst);
+#endif
+
+ /* fetch any constants that this instruction needs */
+ if (c->fp->use_const_buffer)
+ fetch_constants(c, inst);
if (inst->CondUpdate)
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
else
brw_set_conditionalmod(p, BRW_CONDITIONAL_NONE);
+ dst_flags = inst->DstReg.WriteMask;
+ if (inst->SaturateMode == SATURATE_ZERO_ONE)
+ dst_flags |= SATURATE;
+
switch (inst->Opcode) {
case WM_PIXELXY:
emit_pixel_xy(c, inst);
@@ -2320,14 +2805,14 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
case WM_FB_WRITE:
emit_fb_write(c, inst);
break;
- case OPCODE_ABS:
- emit_abs(c, inst);
+ case WM_FRONTFACING:
+ emit_frontfacing(c, inst);
break;
case OPCODE_ADD:
emit_add(c, inst);
break;
- case OPCODE_SUB:
- emit_sub(c, inst);
+ case OPCODE_ARL:
+ emit_arl(c, inst);
break;
case OPCODE_FRC:
emit_frc(c, inst);
@@ -2342,6 +2827,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
emit_trunc(c, inst);
break;
case OPCODE_MOV:
+ case OPCODE_SWZ:
emit_mov(c, inst);
break;
case OPCODE_DP3:
@@ -2374,17 +2860,21 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
case OPCODE_LG2:
emit_lg2(c, inst);
break;
- case OPCODE_MAX:
- emit_max(c, inst);
- break;
case OPCODE_MIN:
- emit_min(c, inst);
+ case OPCODE_MAX:
+ emit_min_max(c, inst);
break;
case OPCODE_DDX:
- emit_ddx(c, inst);
- break;
case OPCODE_DDY:
- emit_ddy(c, inst);
+ for (j = 0; j < 4; j++) {
+ if (inst->DstReg.WriteMask & (1 << j))
+ dst[j] = get_dst_reg(c, inst, j);
+ else
+ dst[j] = brw_null_reg();
+ }
+ get_argument_regs(c, inst, 0, args[0], WRITEMASK_XYZW);
+ emit_ddxy(p, dst, dst_flags, (inst->Opcode == OPCODE_DDX),
+ args[0]);
break;
case OPCODE_SLT:
emit_slt(c, inst);
@@ -2435,18 +2925,21 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
emit_kil(c);
break;
case OPCODE_IF:
- assert(if_insn < MAX_IFSN);
- if_inst[if_insn++] = brw_IF(p, BRW_EXECUTE_8);
+ assert(if_depth < MAX_IF_DEPTH);
+ if_inst[if_depth++] = brw_IF(p, BRW_EXECUTE_8);
break;
case OPCODE_ELSE:
- if_inst[if_insn-1] = brw_ELSE(p, if_inst[if_insn-1]);
+ if_inst[if_depth-1] = brw_ELSE(p, if_inst[if_depth-1]);
break;
case OPCODE_ENDIF:
- assert(if_insn > 0);
- brw_ENDIF(p, if_inst[--if_insn]);
+ assert(if_depth > 0);
+ brw_ENDIF(p, if_inst[--if_depth]);
break;
case OPCODE_BGNSUB:
+ brw_save_label(p, inst->Comment, p->nr_insn);
+ break;
case OPCODE_ENDSUB:
+ /* no-op */
break;
case OPCODE_CAL:
brw_push_insn_state(p);
@@ -2456,8 +2949,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
brw_set_access_mode(p, BRW_ALIGN_16);
brw_ADD(p, get_addr_reg(stack_index),
get_addr_reg(stack_index), brw_imm_d(4));
- orig_inst = inst->Data;
- orig_inst->Data = &p->store[p->nr_insn];
+ brw_save_call(&c->func, inst->Comment, p->nr_insn);
brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
brw_pop_insn_state(p);
break;
@@ -2474,7 +2966,8 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
break;
case OPCODE_BGNLOOP:
- loop_inst[loop_insn++] = brw_DO(p, BRW_EXECUTE_8);
+ /* XXX may need to invalidate the current_constant regs */
+ loop_inst[loop_depth++] = brw_DO(p, BRW_EXECUTE_8);
break;
case OPCODE_BRK:
brw_BREAK(p);
@@ -2485,39 +2978,69 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
break;
case OPCODE_ENDLOOP:
- loop_insn--;
- inst0 = inst1 = brw_WHILE(p, loop_inst[loop_insn]);
- /* patch all the BREAK instructions from
- last BEGINLOOP */
- while (inst0 > loop_inst[loop_insn]) {
- inst0--;
- if (inst0->header.opcode == BRW_OPCODE_BREAK) {
- inst0->bits3.if_else.jump_count = inst1 - inst0 + 1;
+ {
+ struct brw_instruction *inst0, *inst1;
+ GLuint br = 1;
+
+ if (BRW_IS_IGDNG(brw))
+ br = 2;
+
+ loop_depth--;
+ inst0 = inst1 = brw_WHILE(p, loop_inst[loop_depth]);
+ /* patch all the BREAK/CONT instructions from last BGNLOOP */
+ while (inst0 > loop_inst[loop_depth]) {
+ inst0--;
+ if (inst0->header.opcode == BRW_OPCODE_BREAK) {
+ inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1);
inst0->bits3.if_else.pop_count = 0;
- } else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) {
- inst0->bits3.if_else.jump_count = inst1 - inst0;
+ }
+ else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) {
+ inst0->bits3.if_else.jump_count = br * (inst1 - inst0);
inst0->bits3.if_else.pop_count = 0;
- }
- }
- break;
+ }
+ }
+ }
+ break;
default:
_mesa_printf("unsupported IR in fragment shader %d\n",
inst->Opcode);
}
+
if (inst->CondUpdate)
brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
else
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
}
post_wm_emit(c);
- for (i = 0; i < c->fp->program.Base.NumInstructions; i++)
- c->fp->program.Base.Instructions[i].Data = NULL;
+
+ if (INTEL_DEBUG & DEBUG_WM) {
+ _mesa_printf("wm-native:\n");
+ for (i = 0; i < p->nr_insn; i++)
+ brw_disasm(stderr, &p->store[i]);
+ _mesa_printf("\n");
+ }
}
+/**
+ * Do GPU code generation for shaders that use GLSL features such as
+ * flow control. Other shaders will be compiled with the
+ */
void brw_wm_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
{
+ if (INTEL_DEBUG & DEBUG_WM) {
+ _mesa_printf("brw_wm_glsl_emit:\n");
+ }
+
+ /* initial instruction translation/simplification */
brw_wm_pass_fp(c);
+
+ /* actual code generation */
brw_wm_emit_glsl(brw, c);
- c->prog_data.total_grf = c->reg_index;
+
+ if (INTEL_DEBUG & DEBUG_WM) {
+ brw_wm_print_program(c, "brw_wm_glsl_emit done");
+ }
+
+ c->prog_data.total_grf = num_grf_used(c);
c->prog_data.total_scratch = 0;
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_iz.c b/src/mesa/drivers/dri/i965/brw_wm_iz.c
index bd60ac9b31..5e399ac62a 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_iz.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_iz.c
@@ -116,8 +116,13 @@ const struct {
{ C, 0, 1, 1, 1 }
};
+/**
+ * \param line_aa AA_NEVER, AA_ALWAYS or AA_SOMETIMES
+ * \param lookup bitmask of IZ_* flags
+ */
void brw_wm_lookup_iz( GLuint line_aa,
GLuint lookup,
+ GLboolean ps_uses_depth,
struct brw_wm_prog_key *key )
{
GLuint reg = 2;
@@ -127,7 +132,7 @@ void brw_wm_lookup_iz( GLuint line_aa,
if (lookup & IZ_PS_COMPUTES_DEPTH_BIT)
key->computes_depth = 1;
- if (wm_iz_table[lookup].sd_present) {
+ if (wm_iz_table[lookup].sd_present || ps_uses_depth) {
key->source_depth_reg = reg;
reg += 2;
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_pass0.c b/src/mesa/drivers/dri/i965/brw_wm_pass0.c
index 205a7160d3..6279258339 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_pass0.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_pass0.c
@@ -51,6 +51,7 @@ static struct brw_wm_value *get_value( struct brw_wm_compile *c)
return &c->vreg[c->nr_vreg++];
}
+/** return pointer to a newly allocated instruction */
static struct brw_wm_instruction *get_instruction( struct brw_wm_compile *c )
{
assert(c->nr_insns < BRW_WM_MAX_INSN);
@@ -60,6 +61,7 @@ static struct brw_wm_instruction *get_instruction( struct brw_wm_compile *c )
/***********************************************************************
*/
+/** Init the "undef" register */
static void pass0_init_undef( struct brw_wm_compile *c)
{
struct brw_wm_ref *ref = &c->undef_ref;
@@ -69,6 +71,7 @@ static void pass0_init_undef( struct brw_wm_compile *c)
ref->prevuse = NULL;
}
+/** Set a FP register to a value */
static void pass0_set_fpreg_value( struct brw_wm_compile *c,
GLuint file,
GLuint idx,
@@ -83,6 +86,7 @@ static void pass0_set_fpreg_value( struct brw_wm_compile *c,
c->pass0_fp_reg[file][idx][component] = ref;
}
+/** Set a FP register to a ref */
static void pass0_set_fpreg_ref( struct brw_wm_compile *c,
GLuint file,
GLuint idx,
@@ -115,12 +119,13 @@ static const struct brw_wm_ref *get_param_ref( struct brw_wm_compile *c,
ref->value = &c->creg[i/16];
ref->insn = 0;
ref->prevuse = NULL;
-
+
return ref;
}
}
+/** Return a ref to a constant/literal value */
static const struct brw_wm_ref *get_const_ref( struct brw_wm_compile *c,
const GLfloat *constval )
{
@@ -142,7 +147,7 @@ static const struct brw_wm_ref *get_const_ref( struct brw_wm_compile *c,
*/
c->constref[i].constval = *constval;
c->constref[i].ref = get_param_ref(c, constval);
-
+
return c->constref[i].ref;
}
else {
@@ -187,7 +192,7 @@ static const struct brw_wm_ref *pass0_get_reg( struct brw_wm_compile *c,
/* There's something really hokey about parameters parsed in
* arb programs - they all end up in here, whether they be
- * state values, paramters or constants. This duplicates the
+ * state values, parameters or constants. This duplicates the
* structure above & also seems to subvert the limits set for
* each type of constant/param.
*/
@@ -198,7 +203,7 @@ static const struct brw_wm_ref *pass0_get_reg( struct brw_wm_compile *c,
*/
ref = get_const_ref(c, &plist->ParameterValues[idx][component]);
break;
-
+
case PROGRAM_STATE_VAR:
case PROGRAM_UNIFORM:
/* These may change from run to run:
@@ -229,14 +234,13 @@ static const struct brw_wm_ref *pass0_get_reg( struct brw_wm_compile *c,
-
/***********************************************************************
* Straight translation to internal instruction format
*/
static void pass0_set_dst( struct brw_wm_compile *c,
- struct brw_wm_instruction *out,
- const struct prog_instruction *inst,
+ struct brw_wm_instruction *out,
+ const struct prog_instruction *inst,
GLuint writemask )
{
const struct prog_dst_register *dst = &inst->DstReg;
@@ -245,44 +249,14 @@ static void pass0_set_dst( struct brw_wm_compile *c,
for (i = 0; i < 4; i++) {
if (writemask & (1<<i)) {
out->dst[i] = get_value(c);
-
pass0_set_fpreg_value(c, dst->File, dst->Index, i, out->dst[i]);
}
}
-
- out->writemask = writemask;
-}
-
-static void pass0_set_dst_scalar( struct brw_wm_compile *c,
- struct brw_wm_instruction *out,
- const struct prog_instruction *inst,
- GLuint writemask )
-{
- if (writemask) {
- const struct prog_dst_register *dst = &inst->DstReg;
- GLuint i;
-
- /* Compute only the first (X) value:
- */
- out->writemask = WRITEMASK_X;
- out->dst[0] = get_value(c);
-
- /* Update our tracking register file for all the components in
- * writemask:
- */
- for (i = 0; i < 4; i++) {
- if (writemask & (1<<i)) {
- pass0_set_fpreg_value(c, dst->File, dst->Index, i, out->dst[0]);
- }
- }
- }
- else
- out->writemask = 0;
+ out->writemask = writemask;
}
-
static const struct brw_wm_ref *get_fp_src_reg_ref( struct brw_wm_compile *c,
struct prog_src_register src,
GLuint i )
@@ -292,14 +266,13 @@ static const struct brw_wm_ref *get_fp_src_reg_ref( struct brw_wm_compile *c,
static const GLfloat const_zero = 0.0;
static const GLfloat const_one = 1.0;
-
if (component == SWIZZLE_ZERO)
src_ref = get_const_ref(c, &const_zero);
else if (component == SWIZZLE_ONE)
src_ref = get_const_ref(c, &const_one);
else
src_ref = pass0_get_reg(c, src.File, src.Index, component);
-
+
return src_ref;
}
@@ -311,19 +284,19 @@ static struct brw_wm_ref *get_new_ref( struct brw_wm_compile *c,
{
const struct brw_wm_ref *ref = get_fp_src_reg_ref(c, src, i);
struct brw_wm_ref *newref = get_ref(c);
-
+
newref->value = ref->value;
newref->hw_reg = ref->hw_reg;
- if (insn) {
+ if (insn) {
newref->insn = insn - c->instruction;
newref->prevuse = newref->value->lastuse;
newref->value->lastuse = newref;
}
- if (src.NegateBase & (1<<i))
+ if (src.Negate & (1 << i))
newref->hw_reg.negate ^= 1;
-
+
if (src.Abs) {
newref->hw_reg.negate = 0;
newref->hw_reg.abs = 1;
@@ -333,9 +306,9 @@ static struct brw_wm_ref *get_new_ref( struct brw_wm_compile *c,
}
-
-static struct brw_wm_instruction *translate_insn( struct brw_wm_compile *c,
- const struct prog_instruction *inst )
+static void
+translate_insn(struct brw_wm_compile *c,
+ const struct prog_instruction *inst)
{
struct brw_wm_instruction *out = get_instruction(c);
GLuint writemask = inst->DstReg.WriteMask;
@@ -348,8 +321,9 @@ static struct brw_wm_instruction *translate_insn( struct brw_wm_compile *c,
out->saturate = (inst->SaturateMode != SATURATE_OFF);
out->tex_unit = inst->TexSrcUnit;
out->tex_idx = inst->TexSrcTarget;
- out->eot = inst->Sampler & 1;
- out->target = inst->Sampler>>1;
+ out->tex_shadow = inst->TexShadow;
+ out->eot = inst->Aux & 1;
+ out->target = inst->Aux >> 1;
/* Args:
*/
@@ -361,12 +335,7 @@ static struct brw_wm_instruction *translate_insn( struct brw_wm_compile *c,
/* Dst:
*/
- if (brw_wm_is_scalar_result(out->opcode))
- pass0_set_dst_scalar(c, out, inst, writemask);
- else
- pass0_set_dst(c, out, inst, writemask);
-
- return out;
+ pass0_set_dst(c, out, inst, writemask);
}
@@ -379,14 +348,22 @@ static void pass0_precalc_mov( struct brw_wm_compile *c,
{
const struct prog_dst_register *dst = &inst->DstReg;
GLuint writemask = inst->DstReg.WriteMask;
+ struct brw_wm_ref *refs[4];
GLuint i;
/* Get the effect of a MOV by manipulating our register table:
+ * First get all refs, then assign refs. This ensures that "in-place"
+ * swizzles such as:
+ * MOV t, t.xxyx
+ * are handled correctly. Previously, these two steps were done in
+ * one loop and the above case was incorrectly handled.
*/
for (i = 0; i < 4; i++) {
- if (writemask & (1<<i)) {
- pass0_set_fpreg_ref( c, dst->File, dst->Index, i,
- get_new_ref(c, inst->SrcReg[0], i, NULL));
+ refs[i] = get_new_ref(c, inst->SrcReg[0], i, NULL);
+ }
+ for (i = 0; i < 4; i++) {
+ if (writemask & (1 << i)) {
+ pass0_set_fpreg_ref( c, dst->File, dst->Index, i, refs[i]);
}
}
}
@@ -418,6 +395,7 @@ static void pass0_init_payload( struct brw_wm_compile *c )
&c->payload.input_interp[i] );
}
+
/***********************************************************************
* PASS 0
*
@@ -440,7 +418,6 @@ void brw_wm_pass0( struct brw_wm_compile *c )
for (insn = 0; insn < c->nr_fp_insns; insn++) {
const struct prog_instruction *inst = &c->prog_instructions[insn];
-
/* Optimize away moves, otherwise emit translated instruction:
*/
switch (inst->Opcode) {
@@ -453,8 +430,6 @@ void brw_wm_pass0( struct brw_wm_compile *c )
translate_insn(c, inst);
}
break;
-
-
default:
translate_insn(c, inst);
break;
@@ -465,4 +440,3 @@ void brw_wm_pass0( struct brw_wm_compile *c )
brw_wm_print_program(c, "pass0");
}
}
-
diff --git a/src/mesa/drivers/dri/i965/brw_wm_pass1.c b/src/mesa/drivers/dri/i965/brw_wm_pass1.c
index f6f3a38e9e..b449394029 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_pass1.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_pass1.c
@@ -58,7 +58,8 @@ static void unlink_ref(struct brw_wm_ref *ref)
if (ref == value->lastuse) {
value->lastuse = ref->prevuse;
- } else {
+ }
+ else {
struct brw_wm_ref *i = value->lastuse;
while (i->prevuse != ref) i = i->prevuse;
i->prevuse = ref->prevuse;
@@ -75,8 +76,9 @@ static void track_arg(struct brw_wm_compile *c,
for (i = 0; i < 4; i++) {
struct brw_wm_ref *ref = inst->src[arg][i];
if (ref) {
- if (readmask & (1<<i))
+ if (readmask & (1<<i)) {
ref->value->contributes_to_output = 1;
+ }
else {
unlink_ref(ref);
inst->src[arg][i] = NULL;
@@ -88,15 +90,21 @@ static void track_arg(struct brw_wm_compile *c,
static GLuint get_texcoord_mask( GLuint tex_idx )
{
switch (tex_idx) {
- case TEXTURE_1D_INDEX: return WRITEMASK_X;
- case TEXTURE_2D_INDEX: return WRITEMASK_XY;
- case TEXTURE_3D_INDEX: return WRITEMASK_XYZ;
- case TEXTURE_CUBE_INDEX: return WRITEMASK_XYZ;
- case TEXTURE_RECT_INDEX: return WRITEMASK_XY;
+ case TEXTURE_1D_INDEX:
+ return WRITEMASK_X;
+ case TEXTURE_2D_INDEX:
+ return WRITEMASK_XY;
+ case TEXTURE_3D_INDEX:
+ return WRITEMASK_XYZ;
+ case TEXTURE_CUBE_INDEX:
+ return WRITEMASK_XYZ;
+ case TEXTURE_RECT_INDEX:
+ return WRITEMASK_XY;
default: return 0;
}
}
+
/* Step two: Basically this is dead code elimination.
*
* Iterate backwards over instructions, noting which values
@@ -151,6 +159,7 @@ void brw_wm_pass1( struct brw_wm_compile *c )
case OPCODE_FRC:
case OPCODE_MOV:
case OPCODE_SWZ:
+ case OPCODE_TRUNC:
read0 = writemask;
break;
@@ -169,6 +178,11 @@ void brw_wm_pass1( struct brw_wm_compile *c )
read1 = writemask;
break;
+ case OPCODE_DDX:
+ case OPCODE_DDY:
+ read0 = writemask;
+ break;
+
case OPCODE_MAD:
case OPCODE_CMP:
case OPCODE_LRP:
@@ -202,9 +216,10 @@ void brw_wm_pass1( struct brw_wm_compile *c )
break;
case OPCODE_TEX:
+ case OPCODE_TXP:
read0 = get_texcoord_mask(inst->tex_idx);
- if (c->key.shadowtex_mask & (1<<inst->tex_unit))
+ if (inst->tex_shadow)
read0 |= WRITEMASK_Z;
break;
@@ -259,7 +274,8 @@ void brw_wm_pass1( struct brw_wm_compile *c )
break;
case OPCODE_DST:
- case OPCODE_TXP:
+ case WM_FRONTFACING:
+ case OPCODE_KIL_NV:
default:
break;
}
@@ -273,6 +289,3 @@ void brw_wm_pass1( struct brw_wm_compile *c )
brw_wm_print_program(c, "pass1");
}
}
-
-
-
diff --git a/src/mesa/drivers/dri/i965/brw_wm_pass2.c b/src/mesa/drivers/dri/i965/brw_wm_pass2.c
index 6fca9ad220..6faea018fb 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_pass2.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_pass2.c
@@ -69,8 +69,6 @@ static void prealloc_reg(struct brw_wm_compile *c,
*/
static void init_registers( struct brw_wm_compile *c )
{
- struct brw_context *brw = c->func.brw;
- GLuint inputs = (brw->vs.prog_data->outputs_written & DO_SETUP_BITS);
GLuint nr_interp_regs = 0;
GLuint i = 0;
GLuint j;
@@ -84,18 +82,22 @@ static void init_registers( struct brw_wm_compile *c )
for (j = 0; j < c->nr_creg; j++)
prealloc_reg(c, &c->creg[j], i++);
- for (j = 0; j < FRAG_ATTRIB_MAX; j++)
- if (inputs & (1<<j)) {
- /* index for vs output and ps input are not the same
- in shader varying */
- GLuint index;
- if (j > FRAG_ATTRIB_VAR0)
- index = j - (VERT_RESULT_VAR0 - FRAG_ATTRIB_VAR0);
+ for (j = 0; j < FRAG_ATTRIB_MAX; j++) {
+ if (c->key.vp_outputs_written & (1<<j)) {
+ int fp_index;
+
+ if (j >= VERT_RESULT_VAR0)
+ fp_index = j - (VERT_RESULT_VAR0 - FRAG_ATTRIB_VAR0);
+ else if (j <= VERT_RESULT_TEX7)
+ fp_index = j;
else
- index = j;
+ fp_index = -1;
+
nr_interp_regs++;
- prealloc_reg(c, &c->payload.input_interp[index], i++);
+ if (fp_index >= 0)
+ prealloc_reg(c, &c->payload.input_interp[fp_index], i++);
}
+ }
assert(nr_interp_regs >= 1);
@@ -120,7 +122,7 @@ static void update_register_usage(struct brw_wm_compile *c,
/* Only search those which can change:
*/
if (grf->nextuse < thisinsn) {
- struct brw_wm_ref *ref = grf->value->lastuse;
+ const struct brw_wm_ref *ref = grf->value->lastuse;
/* Has last use of value been passed?
*/
@@ -148,7 +150,7 @@ static void spill_value(struct brw_wm_compile *c,
/* Allocate a spill slot. Note that allocations start from 0x40 -
* the first slot is reserved to mean "undef" in brw_wm_emit.c
*/
- if (!value->spill_slot) {
+ if (!value->spill_slot) {
c->last_scratch += 0x40;
value->spill_slot = c->last_scratch;
}
@@ -189,7 +191,7 @@ static GLuint search_contiguous_regs(struct brw_wm_compile *c,
if (grf[i+j].nextuse < group_nextuse)
group_nextuse = grf[i+j].nextuse;
}
-
+
if (group_nextuse > furthest) {
furthest = group_nextuse;
reg = i;
@@ -197,7 +199,7 @@ static GLuint search_contiguous_regs(struct brw_wm_compile *c,
}
assert(furthest != thisinsn);
-
+
/* Any non-empty regs will need to be spilled:
*/
for (j = 0; j < nr; j++)
@@ -243,7 +245,7 @@ static void alloc_contiguous_dest(struct brw_wm_compile *c,
static void load_args(struct brw_wm_compile *c,
struct brw_wm_instruction *inst)
-{
+{
GLuint thisinsn = inst - c->instruction;
GLuint i,j;
@@ -258,17 +260,17 @@ static void load_args(struct brw_wm_compile *c,
* register allocation and mark the ref as requiring a fill.
*/
GLuint reg = search_contiguous_regs(c, 1, thisinsn);
-
+
c->pass2_grf[reg].value = ref->value;
c->pass2_grf[reg].nextuse = thisinsn;
-
+
ref->value->resident = &c->pass2_grf[reg];
/* Note that a fill is required:
*/
ref->unspill_reg = reg*2;
}
-
+
/* Adjust the hw_reg to point at the value's current location:
*/
assert(ref->value == ref->value->resident->value);
@@ -294,7 +296,7 @@ void brw_wm_pass2( struct brw_wm_compile *c )
for (insn = 0; insn < c->nr_insns; insn++) {
struct brw_wm_instruction *inst = &c->instruction[insn];
-
+
/* Update registers' nextuse values:
*/
update_register_usage(c, insn);
@@ -322,11 +324,11 @@ void brw_wm_pass2( struct brw_wm_compile *c )
break;
}
- if (TEST_DST_SPILLS && inst->opcode != WM_PIXELXY)
+ if (TEST_DST_SPILLS && inst->opcode != WM_PIXELXY) {
for (i = 0; i < 4; i++)
if (inst->dst[i])
spill_value(c, inst->dst[i]);
-
+ }
}
if (INTEL_DEBUG & DEBUG_WM) {
@@ -339,6 +341,3 @@ void brw_wm_pass2( struct brw_wm_compile *c )
brw_wm_print_program(c, "pass2/done");
}
}
-
-
-
diff --git a/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c b/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c
index 8c9cb78945..dff466587a 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c
@@ -95,6 +95,7 @@ struct wm_sampler_key {
int sampler_count;
struct wm_sampler_entry {
+ GLenum tex_target;
GLenum wrap_r, wrap_s, wrap_t;
float maxlod, minlod;
float lod_bias;
@@ -102,6 +103,10 @@ struct wm_sampler_key {
GLenum minfilter, magfilter;
GLenum comparemode, comparefunc;
dri_bo *sdc_bo;
+
+ /** If target is cubemap, take context setting.
+ */
+ GLboolean seamless_cube_map;
} sampler[BRW_MAX_TEX_UNIT];
};
@@ -151,7 +156,7 @@ static void brw_update_sampler_state(struct wm_sampler_entry *key,
sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
if (key->max_aniso > 2.0) {
- sampler->ss3.max_aniso = MAX2((key->max_aniso - 2) / 2,
+ sampler->ss3.max_aniso = MIN2((key->max_aniso - 2) / 2,
BRW_ANISORATIO_16);
}
}
@@ -172,15 +177,29 @@ static void brw_update_sampler_state(struct wm_sampler_entry *key,
sampler->ss1.s_wrap_mode = translate_wrap_mode(key->wrap_s);
sampler->ss1.t_wrap_mode = translate_wrap_mode(key->wrap_t);
- /* Fulsim complains if I don't do this. Hardware doesn't mind:
+ /* Cube-maps on 965 and later must use the same wrap mode for all 3
+ * coordinate dimensions. Futher, only CUBE and CLAMP are valid.
*/
-#if 0
- if (texObj->Target == GL_TEXTURE_CUBE_MAP_ARB) {
- sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
- sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
- sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ if (key->tex_target == GL_TEXTURE_CUBE_MAP) {
+ if (key->seamless_cube_map &&
+ (key->minfilter != GL_NEAREST || key->magfilter != GL_NEAREST)) {
+ sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
+ } else {
+ sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+ sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+ sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
+ }
+ } else if (key->tex_target == GL_TEXTURE_1D) {
+ /* There's a bug in 1D texture sampling - it actually pays
+ * attention to the wrap_t value, though it should not.
+ * Override the wrap_t value here to GL_REPEAT to keep
+ * any nonexistent border pixels from floating in.
+ */
+ sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
}
-#endif
+
/* Set shadow function:
*/
@@ -215,24 +234,31 @@ static void brw_update_sampler_state(struct wm_sampler_entry *key,
sampler->ss2.default_color_pointer = sdc_bo->offset >> 5; /* reloc */
}
+
/** Sets up the cache key for sampler state for all texture units */
static void
brw_wm_sampler_populate_key(struct brw_context *brw,
struct wm_sampler_key *key)
{
+ GLcontext *ctx = &brw->intel.ctx;
int unit;
memset(key, 0, sizeof(*key));
for (unit = 0; unit < BRW_MAX_TEX_UNIT; unit++) {
- if (brw->attribs.Texture->Unit[unit]._ReallyEnabled) {
+ if (ctx->Texture.Unit[unit]._ReallyEnabled) {
struct wm_sampler_entry *entry = &key->sampler[unit];
- struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[unit];
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *texObj = texUnit->_Current;
struct intel_texture_object *intelObj = intel_texture_object(texObj);
struct gl_texture_image *firstImage =
texObj->Image[0][intelObj->firstLevel];
+ entry->tex_target = texObj->Target;
+
+ entry->seamless_cube_map = (texObj->Target == GL_TEXTURE_CUBE_MAP)
+ ? ctx->Texture.CubeMapSeamless : GL_FALSE;
+
entry->wrap_r = texObj->WrapR;
entry->wrap_s = texObj->WrapS;
entry->wrap_t = texObj->WrapT;
@@ -274,6 +300,7 @@ brw_wm_sampler_populate_key(struct brw_context *brw,
*/
static void upload_wm_samplers( struct brw_context *brw )
{
+ GLcontext *ctx = &brw->intel.ctx;
struct wm_sampler_key key;
int i;
@@ -317,7 +344,7 @@ static void upload_wm_samplers( struct brw_context *brw )
/* Emit SDC relocations */
for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
- if (!brw->attribs.Texture->Unit[i]._ReallyEnabled)
+ if (!ctx->Texture.Unit[i]._ReallyEnabled)
continue;
dri_bo_emit_reloc(brw->wm.sampler_bo,
diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c
index 5302405eda..361f91292b 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_state.c
@@ -60,7 +60,9 @@ struct brw_wm_unit_key {
static void
wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key)
{
+ GLcontext *ctx = &brw->intel.ctx;
const struct gl_fragment_program *fp = brw->fragment_program;
+ const struct brw_fragment_program *bfp = (struct brw_fragment_program *) fp;
struct intel_context *intel = &brw->intel;
memset(key, 0, sizeof(*key));
@@ -69,7 +71,9 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key)
key->max_threads = 1;
else {
/* WM maximum threads is number of EUs times number of threads per EU. */
- if (BRW_IS_G4X(brw))
+ if (BRW_IS_IGDNG(brw))
+ key->max_threads = 12 * 6;
+ else if (BRW_IS_G4X(brw))
key->max_threads = 10 * 5;
else
key->max_threads = 8 * 4;
@@ -95,31 +99,43 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key)
key->sampler_count = brw->wm.sampler_count;
/* _NEW_POLYGONSTIPPLE */
- key->polygon_stipple = brw->attribs.Polygon->StippleFlag;
+ key->polygon_stipple = ctx->Polygon.StippleFlag;
/* BRW_NEW_FRAGMENT_PROGRAM */
key->uses_depth = (fp->Base.InputsRead & (1 << FRAG_ATTRIB_WPOS)) != 0;
/* as far as we can tell */
key->computes_depth =
- (fp->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR)) != 0;
+ (fp->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH)) != 0;
+ /* BRW_NEW_DEPTH_BUFFER
+ * Override for NULL depthbuffer case, required by the Pixel Shader Computed
+ * Depth field.
+ */
+ if (brw->state.depth_region == NULL)
+ key->computes_depth = 0;
/* _NEW_COLOR */
- key->uses_kill = fp->UsesKill || brw->attribs.Color->AlphaEnabled;
- key->is_glsl = brw_wm_is_glsl(fp);
+ key->uses_kill = fp->UsesKill || ctx->Color.AlphaEnabled;
+ key->is_glsl = bfp->isGLSL;
+
+ /* temporary sanity check assertion */
+ ASSERT(bfp->isGLSL == brw_wm_is_glsl(fp));
- /* XXX: This needs a flag to indicate when it changes. */
+ /* _NEW_DEPTH */
key->stats_wm = intel->stats_wm;
/* _NEW_LINE */
- key->line_stipple = brw->attribs.Line->StippleFlag;
+ key->line_stipple = ctx->Line.StippleFlag;
/* _NEW_POLYGON */
- key->offset_enable = brw->attribs.Polygon->OffsetFill;
- key->offset_units = brw->attribs.Polygon->OffsetUnits;
- key->offset_factor = brw->attribs.Polygon->OffsetFactor;
+ key->offset_enable = ctx->Polygon.OffsetFill;
+ key->offset_units = ctx->Polygon.OffsetUnits;
+ key->offset_factor = ctx->Polygon.OffsetFactor;
}
+/**
+ * Setup wm hardware state. See page 225 of Volume 2
+ */
static dri_bo *
wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
dri_bo **reloc_bufs)
@@ -133,11 +149,15 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
wm.thread0.kernel_start_pointer = brw->wm.prog_bo->offset >> 6; /* reloc */
wm.thread1.depth_coef_urb_read_offset = 1;
wm.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
- wm.thread1.binding_table_entry_count = key->nr_surfaces;
+
+ if (BRW_IS_IGDNG(brw))
+ wm.thread1.binding_table_entry_count = 0; /* hardware requirement */
+ else
+ wm.thread1.binding_table_entry_count = key->nr_surfaces;
if (key->total_scratch != 0) {
wm.thread2.scratch_space_base_pointer =
- brw->wm.scratch_buffer->offset >> 10; /* reloc */
+ brw->wm.scratch_bo->offset >> 10; /* reloc */
wm.thread2.per_thread_scratch_space = key->total_scratch / 1024 - 1;
} else {
wm.thread2.scratch_space_base_pointer = 0;
@@ -146,11 +166,15 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
wm.thread3.dispatch_grf_start_reg = key->dispatch_grf_start_reg;
wm.thread3.urb_entry_read_length = key->urb_entry_read_length;
+ wm.thread3.urb_entry_read_offset = 0;
wm.thread3.const_urb_entry_read_length = key->curb_entry_read_length;
wm.thread3.const_urb_entry_read_offset = key->curbe_offset * 2;
- wm.thread3.urb_entry_read_offset = 0;
- wm.wm4.sampler_count = (key->sampler_count + 1) / 4;
+ if (BRW_IS_IGDNG(brw))
+ wm.wm4.sampler_count = 0; /* hardware requirement */
+ else
+ wm.wm4.sampler_count = (key->sampler_count + 1) / 4;
+
if (brw->wm.sampler_bo != NULL) {
/* reloc */
wm.wm4.sampler_state_pointer = brw->wm.sampler_bo->offset >> 5;
@@ -215,7 +239,7 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
0, 0,
wm.thread2.per_thread_scratch_space,
offsetof(struct brw_wm_unit_state, thread2),
- brw->wm.scratch_buffer);
+ brw->wm.scratch_bo);
}
/* Emit sampler state relocation */
@@ -246,20 +270,20 @@ static void upload_wm_unit( struct brw_context *brw )
if (key.total_scratch) {
GLuint total = key.total_scratch * key.max_threads;
- if (brw->wm.scratch_buffer && total > brw->wm.scratch_buffer->size) {
- dri_bo_unreference(brw->wm.scratch_buffer);
- brw->wm.scratch_buffer = NULL;
+ if (brw->wm.scratch_bo && total > brw->wm.scratch_bo->size) {
+ dri_bo_unreference(brw->wm.scratch_bo);
+ brw->wm.scratch_bo = NULL;
}
- if (brw->wm.scratch_buffer == NULL) {
- brw->wm.scratch_buffer = dri_bo_alloc(intel->bufmgr,
- "wm scratch",
- total,
- 4096);
+ if (brw->wm.scratch_bo == NULL) {
+ brw->wm.scratch_bo = dri_bo_alloc(intel->bufmgr,
+ "wm scratch",
+ total,
+ 4096);
}
}
reloc_bufs[0] = brw->wm.prog_bo;
- reloc_bufs[1] = brw->wm.scratch_buffer;
+ reloc_bufs[1] = brw->wm.scratch_bo;
reloc_bufs[2] = brw->wm.sampler_bo;
dri_bo_unreference(brw->wm.state_bo);
@@ -277,11 +301,13 @@ const struct brw_tracked_state brw_wm_unit = {
.mesa = (_NEW_POLYGON |
_NEW_POLYGONSTIPPLE |
_NEW_LINE |
- _NEW_COLOR),
+ _NEW_COLOR |
+ _NEW_DEPTH),
.brw = (BRW_NEW_FRAGMENT_PROGRAM |
BRW_NEW_CURBE_OFFSETS |
- BRW_NEW_NR_SURFACES),
+ BRW_NEW_DEPTH_BUFFER |
+ BRW_NEW_NR_WM_SURFACES),
.cache = (CACHE_NEW_WM_PROG |
CACHE_NEW_SAMPLER)
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 06e71e6d69..51539ac1e7 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -33,11 +33,12 @@
#include "main/mtypes.h"
#include "main/texformat.h"
#include "main/texstore.h"
+#include "shader/prog_parameter.h"
#include "intel_mipmap_tree.h"
#include "intel_batchbuffer.h"
#include "intel_tex.h"
-
+#include "intel_fbo.h"
#include "brw_context.h"
#include "brw_state.h"
@@ -69,7 +70,8 @@ static GLuint translate_tex_target( GLenum target )
}
-static GLuint translate_tex_format( GLuint mesa_format, GLenum depth_mode )
+static GLuint translate_tex_format( GLuint mesa_format, GLenum internal_format,
+ GLenum depth_mode )
{
switch( mesa_format ) {
case MESA_FORMAT_L8:
@@ -89,10 +91,16 @@ static GLuint translate_tex_format( GLuint mesa_format, GLenum depth_mode )
return BRW_SURFACEFORMAT_R8G8B8_UNORM;
case MESA_FORMAT_ARGB8888:
- return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+ if (internal_format == GL_RGB)
+ return BRW_SURFACEFORMAT_B8G8R8X8_UNORM;
+ else
+ return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
case MESA_FORMAT_RGBA8888_REV:
- return BRW_SURFACEFORMAT_R8G8B8A8_UNORM;
+ if (internal_format == GL_RGB)
+ return BRW_SURFACEFORMAT_R8G8B8X8_UNORM;
+ else
+ return BRW_SURFACEFORMAT_R8G8B8A8_UNORM;
case MESA_FORMAT_RGB565:
return BRW_SURFACEFORMAT_B5G6R5_UNORM;
@@ -133,13 +141,34 @@ static GLuint translate_tex_format( GLuint mesa_format, GLenum depth_mode )
case MESA_FORMAT_RGBA_DXT5:
return BRW_SURFACEFORMAT_BC3_UNORM;
- case MESA_FORMAT_SRGBA8:
- return BRW_SURFACEFORMAT_R8G8B8A8_UNORM_SRGB;
+ case MESA_FORMAT_SARGB8:
+ return BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB;
+
+ case MESA_FORMAT_SLA8:
+ return BRW_SURFACEFORMAT_L8A8_UNORM_SRGB;
+
+ case MESA_FORMAT_SL8:
+ return BRW_SURFACEFORMAT_L8_UNORM_SRGB;
+
case MESA_FORMAT_SRGB_DXT1:
return BRW_SURFACEFORMAT_BC1_UNORM_SRGB;
case MESA_FORMAT_S8_Z24:
- return BRW_SURFACEFORMAT_I24X8_UNORM;
+ /* XXX: these different surface formats don't seem to
+ * make any difference for shadow sampler/compares.
+ */
+ if (depth_mode == GL_INTENSITY)
+ return BRW_SURFACEFORMAT_I24X8_UNORM;
+ else if (depth_mode == GL_ALPHA)
+ return BRW_SURFACEFORMAT_A24X8_UNORM;
+ else
+ return BRW_SURFACEFORMAT_L24X8_UNORM;
+
+ case MESA_FORMAT_DUDV8:
+ return BRW_SURFACEFORMAT_R8G8_SNORM;
+
+ case MESA_FORMAT_SIGNED_RGBA8888_REV:
+ return BRW_SURFACEFORMAT_R8G8B8A8_SNORM;
default:
assert(0);
@@ -147,17 +176,6 @@ static GLuint translate_tex_format( GLuint mesa_format, GLenum depth_mode )
}
}
-struct brw_wm_surface_key {
- GLenum target, depthmode;
- dri_bo *bo;
- GLint format;
- GLint first_level, last_level;
- GLint width, height, depth;
- GLint pitch, cpp;
- uint32_t tiling;
- GLuint offset;
-};
-
static void
brw_set_surface_tiling(struct brw_surface_state *surf, uint32_t tiling)
{
@@ -179,7 +197,7 @@ brw_set_surface_tiling(struct brw_surface_state *surf, uint32_t tiling)
static dri_bo *
brw_create_texture_surface( struct brw_context *brw,
- struct brw_wm_surface_key *key )
+ struct brw_surface_key *key )
{
struct brw_surface_state surf;
dri_bo *bo;
@@ -188,9 +206,11 @@ brw_create_texture_surface( struct brw_context *brw,
surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
surf.ss0.surface_type = translate_tex_target(key->target);
-
- if (key->bo)
- surf.ss0.surface_format = translate_tex_format(key->format, key->depthmode);
+ if (key->bo) {
+ surf.ss0.surface_format = translate_tex_format(key->format,
+ key->internal_format,
+ key->depthmode);
+ }
else {
switch (key->depth) {
case 32:
@@ -232,7 +252,7 @@ brw_create_texture_surface( struct brw_context *brw,
surf.ss0.cube_neg_z = 1;
}
- bo = brw_upload_cache(&brw->cache, BRW_SS_SURFACE,
+ bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
key, sizeof(*key),
&key->bo, key->bo ? 1 : 0,
&surf, sizeof(surf),
@@ -253,10 +273,11 @@ static void
brw_update_texture_surface( GLcontext *ctx, GLuint unit )
{
struct brw_context *brw = brw_context(ctx);
- struct gl_texture_object *tObj = brw->attribs.Texture->Unit[unit]._Current;
+ struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
struct gl_texture_image *firstImage = tObj->Image[0][intelObj->firstLevel];
- struct brw_wm_surface_key key;
+ struct brw_surface_key key;
+ const GLuint surf = SURF_INDEX_TEXTURE(unit);
memset(&key, 0, sizeof(key));
@@ -267,6 +288,7 @@ brw_update_texture_surface( GLcontext *ctx, GLuint unit )
key.offset = intelObj->textureOffset;
} else {
key.format = firstImage->TexFormat->MesaFormat;
+ key.internal_format = firstImage->InternalFormat;
key.pitch = intelObj->mt->pitch;
key.depth = firstImage->Depth;
key.bo = intelObj->mt->region->buffer;
@@ -282,33 +304,221 @@ brw_update_texture_surface( GLcontext *ctx, GLuint unit )
key.cpp = intelObj->mt->cpp;
key.tiling = intelObj->mt->region->tiling;
- dri_bo_unreference(brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS]);
- brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] = brw_search_cache(&brw->cache, BRW_SS_SURFACE,
- &key, sizeof(key),
- &key.bo, key.bo ? 1 : 0,
- NULL);
- if (brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] == NULL) {
- brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] = brw_create_texture_surface(brw, &key);
+ dri_bo_unreference(brw->wm.surf_bo[surf]);
+ brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache,
+ BRW_SS_SURFACE,
+ &key, sizeof(key),
+ &key.bo, key.bo ? 1 : 0,
+ NULL);
+ if (brw->wm.surf_bo[surf] == NULL) {
+ brw->wm.surf_bo[surf] = brw_create_texture_surface(brw, &key);
+ }
+}
+
+
+
+/**
+ * Create the constant buffer surface. Vertex/fragment shader constants will be
+ * read from this buffer with Data Port Read instructions/messages.
+ */
+dri_bo *
+brw_create_constant_surface( struct brw_context *brw,
+ struct brw_surface_key *key )
+{
+ const GLint w = key->width - 1;
+ struct brw_surface_state surf;
+ dri_bo *bo;
+
+ 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;
+
+ assert(key->bo);
+ if (key->bo)
+ surf.ss1.base_addr = key->bo->offset; /* reloc */
+ else
+ surf.ss1.base_addr = key->offset;
+
+ 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 = (key->pitch * key->cpp) - 1; /* ignored?? */
+ brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */
+
+ bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
+ key, sizeof(*key),
+ &key->bo, key->bo ? 1 : 0,
+ &surf, sizeof(surf),
+ NULL, NULL);
+
+ if (key->bo) {
+ /* Emit relocation to surface contents */
+ dri_bo_emit_reloc(bo,
+ I915_GEM_DOMAIN_SAMPLER, 0,
+ 0,
+ offsetof(struct brw_surface_state, ss1),
+ key->bo);
+ }
+
+ return bo;
+}
+
+/* Creates a new WM constant buffer reflecting the current fragment program's
+ * constants, if needed by the fragment program.
+ *
+ * Otherwise, constants go through the CURBEs using the brw_constant_buffer
+ * state atom.
+ */
+static drm_intel_bo *
+brw_wm_update_constant_buffer(struct brw_context *brw)
+{
+ struct intel_context *intel = &brw->intel;
+ struct brw_fragment_program *fp =
+ (struct brw_fragment_program *) brw->fragment_program;
+ const struct gl_program_parameter_list *params = fp->program.Base.Parameters;
+ const int size = params->NumParameters * 4 * sizeof(GLfloat);
+ drm_intel_bo *const_buffer;
+
+ /* BRW_NEW_FRAGMENT_PROGRAM */
+ if (!fp->use_const_buffer)
+ return NULL;
+
+ const_buffer = drm_intel_bo_alloc(intel->bufmgr, "fp_const_buffer",
+ size, 64);
+
+ /* _NEW_PROGRAM_CONSTANTS */
+ dri_bo_subdata(const_buffer, 0, size, params->ParameterValues);
+
+ return const_buffer;
+}
+
+/**
+ * Update the surface state for a WM constant buffer.
+ * The constant buffer will be (re)allocated here if needed.
+ */
+static void
+brw_update_wm_constant_surface( GLcontext *ctx,
+ GLuint surf)
+{
+ struct brw_context *brw = brw_context(ctx);
+ struct brw_surface_key key;
+ struct brw_fragment_program *fp =
+ (struct brw_fragment_program *) brw->fragment_program;
+ const struct gl_program_parameter_list *params =
+ fp->program.Base.Parameters;
+
+ /* If we're in this state update atom, we need to update WM constants, so
+ * free the old buffer and create a new one for the new contents.
+ */
+ dri_bo_unreference(fp->const_buffer);
+ fp->const_buffer = brw_wm_update_constant_buffer(brw);
+
+ /* If there's no constant buffer, then no surface BO is needed to point at
+ * it.
+ */
+ if (fp->const_buffer == 0) {
+ drm_intel_bo_unreference(brw->wm.surf_bo[surf]);
+ brw->wm.surf_bo[surf] = NULL;
+ return;
+ }
+
+ memset(&key, 0, sizeof(key));
+
+ key.format = MESA_FORMAT_RGBA_FLOAT32;
+ key.internal_format = GL_RGBA;
+ key.bo = fp->const_buffer;
+ key.depthmode = GL_NONE;
+ key.pitch = params->NumParameters;
+ key.width = params->NumParameters;
+ key.height = 1;
+ key.depth = 1;
+ key.cpp = 16;
+
+ /*
+ printf("%s:\n", __FUNCTION__);
+ printf(" width %d height %d depth %d cpp %d pitch %d\n",
+ key.width, key.height, key.depth, key.cpp, key.pitch);
+ */
+
+ dri_bo_unreference(brw->wm.surf_bo[surf]);
+ brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache,
+ BRW_SS_SURFACE,
+ &key, sizeof(key),
+ &key.bo, key.bo ? 1 : 0,
+ NULL);
+ if (brw->wm.surf_bo[surf] == NULL) {
+ brw->wm.surf_bo[surf] = brw_create_constant_surface(brw, &key);
+ }
+ brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
+}
+
+/**
+ * Updates surface / buffer for fragment shader constant buffer, if
+ * one is required.
+ *
+ * This consumes the state updates for the constant buffer, and produces
+ * BRW_NEW_WM_SURFACES to get picked up by brw_prepare_wm_surfaces for
+ * inclusion in the binding table.
+ */
+static void prepare_wm_constant_surface(struct brw_context *brw )
+{
+ GLcontext *ctx = &brw->intel.ctx;
+ struct brw_fragment_program *fp =
+ (struct brw_fragment_program *) brw->fragment_program;
+ GLuint surf = SURF_INDEX_FRAG_CONST_BUFFER;
+
+ drm_intel_bo_unreference(fp->const_buffer);
+ fp->const_buffer = brw_wm_update_constant_buffer(brw);
+
+ /* If there's no constant buffer, then no surface BO is needed to point at
+ * it.
+ */
+ if (fp->const_buffer == 0) {
+ if (brw->wm.surf_bo[surf] != NULL) {
+ drm_intel_bo_unreference(brw->wm.surf_bo[surf]);
+ brw->wm.surf_bo[surf] = NULL;
+ brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
+ }
+ return;
}
+
+ brw_update_wm_constant_surface(ctx, surf);
}
+const struct brw_tracked_state brw_wm_constant_surface = {
+ .dirty = {
+ .mesa = (_NEW_PROGRAM_CONSTANTS),
+ .brw = (BRW_NEW_FRAGMENT_PROGRAM),
+ .cache = 0
+ },
+ .prepare = prepare_wm_constant_surface,
+};
+
+
/**
* Sets up a surface state structure to point at the given region.
* While it is only used for the front/back buffer currently, it should be
* usable for further buffers when doing ARB_draw_buffer support.
*/
static void
-brw_update_region_surface(struct brw_context *brw, struct intel_region *region,
- unsigned int unit, GLboolean cached)
+brw_update_renderbuffer_surface(struct brw_context *brw,
+ struct gl_renderbuffer *rb,
+ unsigned int unit)
{
+ GLcontext *ctx = &brw->intel.ctx;
dri_bo *region_bo = NULL;
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+ struct intel_region *region = irb ? irb->region : NULL;
struct {
unsigned int surface_type;
unsigned int surface_format;
- unsigned int width, height, cpp;
+ unsigned int width, height, pitch, cpp;
GLubyte color_mask[4];
GLboolean color_blend;
uint32_t tiling;
+ uint32_t draw_offset;
} key;
memset(&key, 0, sizeof(key));
@@ -317,34 +527,54 @@ brw_update_region_surface(struct brw_context *brw, struct intel_region *region,
region_bo = region->buffer;
key.surface_type = BRW_SURFACE_2D;
- if (region->cpp == 4)
+ switch (irb->texformat->MesaFormat) {
+ case MESA_FORMAT_ARGB8888:
key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
- else
+ break;
+ case MESA_FORMAT_RGB565:
key.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
+ break;
+ case MESA_FORMAT_ARGB1555:
+ key.surface_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
+ break;
+ case MESA_FORMAT_ARGB4444:
+ key.surface_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
+ break;
+ default:
+ _mesa_problem(ctx, "Bad renderbuffer format: %d\n",
+ irb->texformat->MesaFormat);
+ }
key.tiling = region->tiling;
- key.width = region->pitch; /* XXX: not really! */
- key.height = region->height;
+ if (brw->intel.intelScreen->driScrnPriv->dri2.enabled) {
+ key.width = rb->Width;
+ key.height = rb->Height;
+ } else {
+ key.width = region->width;
+ key.height = region->height;
+ }
+ key.pitch = region->pitch;
key.cpp = region->cpp;
+ key.draw_offset = region->draw_offset; /* cur 3d or cube face offset */
} else {
key.surface_type = BRW_SURFACE_NULL;
key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
- key.tiling = 0;
+ key.tiling = I915_TILING_X;
key.width = 1;
key.height = 1;
key.cpp = 4;
+ key.draw_offset = 0;
}
- memcpy(key.color_mask, brw->attribs.Color->ColorMask,
+ memcpy(key.color_mask, ctx->Color.ColorMask,
sizeof(key.color_mask));
- key.color_blend = (!brw->attribs.Color->_LogicOpEnabled &&
- brw->attribs.Color->BlendEnabled);
+ key.color_blend = (!ctx->Color._LogicOpEnabled &&
+ ctx->Color.BlendEnabled);
dri_bo_unreference(brw->wm.surf_bo[unit]);
- brw->wm.surf_bo[unit] = NULL;
- if (cached)
- brw->wm.surf_bo[unit] = brw_search_cache(&brw->cache, BRW_SS_SURFACE,
- &key, sizeof(key),
- &region_bo, 1,
- NULL);
+ brw->wm.surf_bo[unit] = brw_search_cache(&brw->surface_cache,
+ BRW_SS_SURFACE,
+ &key, sizeof(key),
+ &region_bo, 1,
+ NULL);
if (brw->wm.surf_bo[unit] == NULL) {
struct brw_surface_state surf;
@@ -353,13 +583,34 @@ brw_update_region_surface(struct brw_context *brw, struct intel_region *region,
surf.ss0.surface_format = key.surface_format;
surf.ss0.surface_type = key.surface_type;
+ if (key.tiling == I915_TILING_NONE) {
+ surf.ss1.base_addr = key.draw_offset;
+ } else {
+ uint32_t tile_offset = key.draw_offset % 4096;
+
+ surf.ss1.base_addr = key.draw_offset - tile_offset;
+
+ assert(BRW_IS_G4X(brw) || tile_offset == 0);
+ if (BRW_IS_G4X(brw)) {
+ if (key.tiling == I915_TILING_X) {
+ /* Note that the low bits of these fields are missing, so
+ * there's the possibility of getting in trouble.
+ */
+ surf.ss5.x_offset = (tile_offset % 512) / key.cpp / 4;
+ surf.ss5.y_offset = tile_offset / 512 / 2;
+ } else {
+ surf.ss5.x_offset = (tile_offset % 128) / key.cpp / 4;
+ surf.ss5.y_offset = tile_offset / 128 / 2;
+ }
+ }
+ }
if (region_bo != NULL)
- surf.ss1.base_addr = region_bo->offset; /* reloc */
+ surf.ss1.base_addr += region_bo->offset; /* reloc */
surf.ss2.width = key.width - 1;
surf.ss2.height = key.height - 1;
brw_set_surface_tiling(&surf, key.tiling);
- surf.ss3.pitch = (key.width * key.cpp) - 1;
+ surf.ss3.pitch = (key.pitch * key.cpp) - 1;
/* _NEW_COLOR */
surf.ss0.color_blend = key.color_blend;
@@ -369,8 +620,9 @@ brw_update_region_surface(struct brw_context *brw, struct intel_region *region,
surf.ss0.writedisable_alpha = !key.color_mask[3];
/* Key size will never match key size for textures, so we're safe. */
- brw->wm.surf_bo[unit] = brw_upload_cache(&brw->cache, BRW_SS_SURFACE,
- &key, sizeof(key),
+ brw->wm.surf_bo[unit] = brw_upload_cache(&brw->surface_cache,
+ BRW_SS_SURFACE,
+ &key, sizeof(key),
&region_bo, 1,
&surf, sizeof(surf),
NULL, NULL);
@@ -379,13 +631,12 @@ brw_update_region_surface(struct brw_context *brw, struct intel_region *region,
* them both. We might be able to figure out from other state
* a more restrictive relocation to emit.
*/
- dri_bo_emit_reloc(brw->wm.surf_bo[unit],
- I915_GEM_DOMAIN_RENDER |
- I915_GEM_DOMAIN_SAMPLER,
- I915_GEM_DOMAIN_RENDER,
- 0,
- offsetof(struct brw_surface_state, ss1),
- region_bo);
+ drm_intel_bo_emit_reloc(brw->wm.surf_bo[unit],
+ offsetof(struct brw_surface_state, ss1),
+ region_bo,
+ surf.ss1.base_addr - region_bo->offset,
+ I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER);
}
}
}
@@ -400,7 +651,9 @@ brw_wm_get_binding_table(struct brw_context *brw)
{
dri_bo *bind_bo;
- bind_bo = brw_search_cache(&brw->cache, BRW_SS_SURF_BIND,
+ assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF);
+
+ bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
NULL, 0,
brw->wm.surf_bo, brw->wm.nr_surfaces,
NULL);
@@ -416,7 +669,7 @@ brw_wm_get_binding_table(struct brw_context *brw)
else
data[i] = 0;
- bind_bo = brw_upload_cache( &brw->cache, BRW_SS_SURF_BIND,
+ bind_bo = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
NULL, 0,
brw->wm.surf_bo, brw->wm.nr_surfaces,
data, data_size,
@@ -446,51 +699,62 @@ static void prepare_wm_surfaces(struct brw_context *brw )
GLuint i;
int old_nr_surfaces;
- if (brw->state.nr_draw_regions > 1) {
- for (i = 0; i < brw->state.nr_draw_regions; i++) {
- brw_update_region_surface(brw, brw->state.draw_regions[i], i,
- GL_FALSE);
+ /* _NEW_BUFFERS */
+ /* Update surfaces for drawing buffers */
+ if (ctx->DrawBuffer->_NumColorDrawBuffers >= 1) {
+ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+ brw_update_renderbuffer_surface(brw,
+ ctx->DrawBuffer->_ColorDrawBuffers[i],
+ i);
}
- }else {
- brw_update_region_surface(brw, brw->state.draw_regions[0], 0, GL_TRUE);
+ } else {
+ brw_update_renderbuffer_surface(brw, NULL, 0);
}
old_nr_surfaces = brw->wm.nr_surfaces;
brw->wm.nr_surfaces = MAX_DRAW_BUFFERS;
+ if (brw->wm.surf_bo[SURF_INDEX_FRAG_CONST_BUFFER] != NULL)
+ brw->wm.nr_surfaces = SURF_INDEX_FRAG_CONST_BUFFER + 1;
+
+ /* Update surfaces for textures */
for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
- struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[i];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+ const GLuint surf = SURF_INDEX_TEXTURE(i);
/* _NEW_TEXTURE, BRW_NEW_TEXDATA */
- if(texUnit->_ReallyEnabled) {
+ if (texUnit->_ReallyEnabled) {
if (texUnit->_Current == intel->frame_buffer_texobj) {
- dri_bo_unreference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
- brw->wm.surf_bo[i+MAX_DRAW_BUFFERS] = brw->wm.surf_bo[0];
- dri_bo_reference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
- brw->wm.nr_surfaces = i + MAX_DRAW_BUFFERS + 1;
+ /* render to texture */
+ dri_bo_unreference(brw->wm.surf_bo[surf]);
+ brw->wm.surf_bo[surf] = brw->wm.surf_bo[0];
+ dri_bo_reference(brw->wm.surf_bo[surf]);
+ brw->wm.nr_surfaces = surf + 1;
} else {
+ /* regular texture */
brw_update_texture_surface(ctx, i);
- brw->wm.nr_surfaces = i + MAX_DRAW_BUFFERS + 1;
+ brw->wm.nr_surfaces = surf + 1;
}
} else {
- dri_bo_unreference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
- brw->wm.surf_bo[i+MAX_DRAW_BUFFERS] = NULL;
+ dri_bo_unreference(brw->wm.surf_bo[surf]);
+ brw->wm.surf_bo[surf] = NULL;
}
-
}
dri_bo_unreference(brw->wm.bind_bo);
brw->wm.bind_bo = brw_wm_get_binding_table(brw);
if (brw->wm.nr_surfaces != old_nr_surfaces)
- brw->state.dirty.brw |= BRW_NEW_NR_SURFACES;
+ brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES;
}
-
const struct brw_tracked_state brw_wm_surfaces = {
.dirty = {
- .mesa = _NEW_COLOR | _NEW_TEXTURE | _NEW_BUFFERS,
- .brw = BRW_NEW_CONTEXT,
+ .mesa = (_NEW_COLOR |
+ _NEW_TEXTURE |
+ _NEW_BUFFERS),
+ .brw = (BRW_NEW_CONTEXT |
+ BRW_NEW_WM_SURFACES),
.cache = 0
},
.prepare = prepare_wm_surfaces,
diff --git a/src/mesa/drivers/dri/i965/intel_clear.c b/src/mesa/drivers/dri/i965/intel_clear.c
new file mode 120000
index 0000000000..9a2a742a0d
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_clear.c
@@ -0,0 +1 @@
+../intel/intel_clear.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i965/intel_depthstencil.c b/src/mesa/drivers/dri/i965/intel_depthstencil.c
deleted file mode 120000
index 4ac4ae690a..0000000000
--- a/src/mesa/drivers/dri/i965/intel_depthstencil.c
+++ /dev/null
@@ -1 +0,0 @@
-../intel/intel_depthstencil.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c
new file mode 120000
index 0000000000..a2f3e8cd20
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_extensions.c
@@ -0,0 +1 @@
+../intel/intel_extensions.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i965/intel_generatemipmap.c b/src/mesa/drivers/dri/i965/intel_generatemipmap.c
new file mode 120000
index 0000000000..4c6b37ada0
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_generatemipmap.c
@@ -0,0 +1 @@
+../intel/intel_generatemipmap.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i965/intel_pixel_read.c b/src/mesa/drivers/dri/i965/intel_pixel_read.c
new file mode 120000
index 0000000000..cc4589f4d4
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_pixel_read.c
@@ -0,0 +1 @@
+../intel/intel_pixel_read.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i965/intel_state.c b/src/mesa/drivers/dri/i965/intel_state.c
index 67ef5f78c1..519672fc35 100644..120000
--- a/src/mesa/drivers/dri/i965/intel_state.c
+++ b/src/mesa/drivers/dri/i965/intel_state.c
@@ -1,225 +1 @@
-/**************************************************************************
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "main/enums.h"
-#include "main/colormac.h"
-#include "main/dd.h"
-
-#include "intel_screen.h"
-#include "intel_context.h"
-#include "intel_regions.h"
-#include "swrast/swrast.h"
-
-int intel_translate_shadow_compare_func( GLenum func )
-{
- switch(func) {
- case GL_NEVER:
- return COMPAREFUNC_ALWAYS;
- case GL_LESS:
- return COMPAREFUNC_LEQUAL;
- case GL_LEQUAL:
- return COMPAREFUNC_LESS;
- case GL_GREATER:
- return COMPAREFUNC_GEQUAL;
- case GL_GEQUAL:
- return COMPAREFUNC_GREATER;
- case GL_NOTEQUAL:
- return COMPAREFUNC_EQUAL;
- case GL_EQUAL:
- return COMPAREFUNC_NOTEQUAL;
- case GL_ALWAYS:
- return COMPAREFUNC_NEVER;
- }
-
- fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func);
- return COMPAREFUNC_NEVER;
-}
-
-int intel_translate_compare_func( GLenum func )
-{
- switch(func) {
- case GL_NEVER:
- return COMPAREFUNC_NEVER;
- case GL_LESS:
- return COMPAREFUNC_LESS;
- case GL_LEQUAL:
- return COMPAREFUNC_LEQUAL;
- case GL_GREATER:
- return COMPAREFUNC_GREATER;
- case GL_GEQUAL:
- return COMPAREFUNC_GEQUAL;
- case GL_NOTEQUAL:
- return COMPAREFUNC_NOTEQUAL;
- case GL_EQUAL:
- return COMPAREFUNC_EQUAL;
- case GL_ALWAYS:
- return COMPAREFUNC_ALWAYS;
- }
-
- fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func);
- return COMPAREFUNC_ALWAYS;
-}
-
-int intel_translate_stencil_op( GLenum op )
-{
- switch(op) {
- case GL_KEEP:
- return STENCILOP_KEEP;
- case GL_ZERO:
- return STENCILOP_ZERO;
- case GL_REPLACE:
- return STENCILOP_REPLACE;
- case GL_INCR:
- return STENCILOP_INCRSAT;
- case GL_DECR:
- return STENCILOP_DECRSAT;
- case GL_INCR_WRAP:
- return STENCILOP_INCR;
- case GL_DECR_WRAP:
- return STENCILOP_DECR;
- case GL_INVERT:
- return STENCILOP_INVERT;
- default:
- return STENCILOP_ZERO;
- }
-}
-
-int intel_translate_blend_factor( GLenum factor )
-{
- switch(factor) {
- case GL_ZERO:
- return BLENDFACT_ZERO;
- case GL_SRC_ALPHA:
- return BLENDFACT_SRC_ALPHA;
- case GL_ONE:
- return BLENDFACT_ONE;
- case GL_SRC_COLOR:
- return BLENDFACT_SRC_COLR;
- case GL_ONE_MINUS_SRC_COLOR:
- return BLENDFACT_INV_SRC_COLR;
- case GL_DST_COLOR:
- return BLENDFACT_DST_COLR;
- case GL_ONE_MINUS_DST_COLOR:
- return BLENDFACT_INV_DST_COLR;
- case GL_ONE_MINUS_SRC_ALPHA:
- return BLENDFACT_INV_SRC_ALPHA;
- case GL_DST_ALPHA:
- return BLENDFACT_DST_ALPHA;
- case GL_ONE_MINUS_DST_ALPHA:
- return BLENDFACT_INV_DST_ALPHA;
- case GL_SRC_ALPHA_SATURATE:
- return BLENDFACT_SRC_ALPHA_SATURATE;
- case GL_CONSTANT_COLOR:
- return BLENDFACT_CONST_COLOR;
- case GL_ONE_MINUS_CONSTANT_COLOR:
- return BLENDFACT_INV_CONST_COLOR;
- case GL_CONSTANT_ALPHA:
- return BLENDFACT_CONST_ALPHA;
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- return BLENDFACT_INV_CONST_ALPHA;
- }
-
- fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, factor);
- return BLENDFACT_ZERO;
-}
-
-int intel_translate_logic_op( GLenum opcode )
-{
- switch(opcode) {
- case GL_CLEAR:
- return LOGICOP_CLEAR;
- case GL_AND:
- return LOGICOP_AND;
- case GL_AND_REVERSE:
- return LOGICOP_AND_RVRSE;
- case GL_COPY:
- return LOGICOP_COPY;
- case GL_COPY_INVERTED:
- return LOGICOP_COPY_INV;
- case GL_AND_INVERTED:
- return LOGICOP_AND_INV;
- case GL_NOOP:
- return LOGICOP_NOOP;
- case GL_XOR:
- return LOGICOP_XOR;
- case GL_OR:
- return LOGICOP_OR;
- case GL_OR_INVERTED:
- return LOGICOP_OR_INV;
- case GL_NOR:
- return LOGICOP_NOR;
- case GL_EQUIV:
- return LOGICOP_EQUIV;
- case GL_INVERT:
- return LOGICOP_INV;
- case GL_OR_REVERSE:
- return LOGICOP_OR_RVRSE;
- case GL_NAND:
- return LOGICOP_NAND;
- case GL_SET:
- return LOGICOP_SET;
- default:
- return LOGICOP_SET;
- }
-}
-
-
-static void intelClearColor(GLcontext *ctx, const GLfloat color[4])
-{
- struct intel_context *intel = intel_context(ctx);
-
- UNCLAMPED_FLOAT_TO_RGBA_CHAN(intel->clear_chan, color);
-
- intel->ClearColor8888 = INTEL_PACKCOLOR8888(intel->clear_chan[0],
- intel->clear_chan[1],
- intel->clear_chan[2],
- intel->clear_chan[3]);
- intel->ClearColor565 = INTEL_PACKCOLOR565(intel->clear_chan[0],
- intel->clear_chan[1],
- intel->clear_chan[2]);
-}
-
-
-
-/* Fallback to swrast for select and feedback.
- */
-static void intelRenderMode( GLcontext *ctx, GLenum mode )
-{
- struct intel_context *intel = intel_context(ctx);
- FALLBACK( intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
-}
-
-
-void intelInitStateFuncs( struct dd_function_table *functions )
-{
- functions->RenderMode = intelRenderMode;
- functions->ClearColor = intelClearColor;
-}
+../intel/intel_state.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i965/intel_swapbuffers.c b/src/mesa/drivers/dri/i965/intel_swapbuffers.c
new file mode 120000
index 0000000000..148d5215aa
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_swapbuffers.c
@@ -0,0 +1 @@
+../intel/intel_swapbuffers.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/i965/intel_syncobj.c b/src/mesa/drivers/dri/i965/intel_syncobj.c
new file mode 120000
index 0000000000..0b2e56ab24
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_syncobj.c
@@ -0,0 +1 @@
+../intel/intel_syncobj.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c
index 9d9937289a..6aa36d10b1 100644
--- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c
@@ -195,7 +195,16 @@ _intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file,
{
struct intel_context *intel = batch->intel;
GLuint used = batch->ptr - batch->map;
- GLboolean was_locked = intel->locked;
+
+ 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 (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) {
batch->cliprect_mode = IGNORE_CLIPRECTS;
@@ -207,7 +216,7 @@ _intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file,
used);
/* Emit a flush if the bufmgr doesn't do it for us. */
- if (!intel->ttm) {
+ if (intel->always_flush_cache || !intel->ttm) {
*(GLuint *) (batch->ptr) = intel->vtbl.flush_cmd();
batch->ptr += 4;
used = batch->ptr - batch->map;
@@ -243,13 +252,9 @@ _intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file,
/* TODO: Just pass the relocation list and dma buffer up to the
* kernel.
*/
- if (!was_locked)
- LOCK_HARDWARE(intel);
-
+ LOCK_HARDWARE(intel);
do_flush_locked(batch, used, GL_FALSE);
-
- if (!was_locked)
- UNLOCK_HARDWARE(intel);
+ UNLOCK_HARDWARE(intel);
if (INTEL_DEBUG & DEBUG_SYNC) {
fprintf(stderr, "waiting for idle\n");
diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c
index 208f90c0ab..43141c509c 100644
--- a/src/mesa/drivers/dri/intel/intel_blit.c
+++ b/src/mesa/drivers/dri/intel/intel_blit.c
@@ -26,12 +26,11 @@
**************************************************************************/
-#include <stdio.h>
-#include <errno.h>
-
#include "main/mtypes.h"
#include "main/context.h"
#include "main/enums.h"
+#include "main/texformat.h"
+#include "main/colormac.h"
#include "intel_blit.h"
#include "intel_buffers.h"
@@ -98,14 +97,16 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
ASSERT(src->cpp == dst->cpp);
if (cpp == 2) {
- BR13 = (0xCC << 16) | (1 << 24);
+ BR13 = (0xCC << 16) | BR13_565;
CMD = XY_SRC_COPY_BLT_CMD;
}
else {
- BR13 = (0xCC << 16) | (1 << 24) | (1 << 25);
+ BR13 = (0xCC << 16) | BR13_8888;
CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
}
+ assert(src->tiling != I915_TILING_Y);
+ assert(dst->tiling != I915_TILING_Y);
#ifndef I915
if (src->tiling != I915_TILING_NONE) {
CMD |= XY_SRC_TILED;
@@ -173,64 +174,6 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
UNLOCK_HARDWARE(intel);
}
-
-
-
-void
-intelEmitFillBlit(struct intel_context *intel,
- GLuint cpp,
- GLshort dst_pitch,
- dri_bo *dst_buffer,
- GLuint dst_offset,
- uint32_t dst_tiling,
- GLshort x, GLshort y,
- GLshort w, GLshort h,
- GLuint color)
-{
- GLuint BR13, CMD;
- BATCH_LOCALS;
-
- dst_pitch *= cpp;
-
- switch (cpp) {
- case 1:
- case 2:
- case 3:
- BR13 = (0xF0 << 16) | (1 << 24);
- CMD = XY_COLOR_BLT_CMD;
- break;
- case 4:
- BR13 = (0xF0 << 16) | (1 << 24) | (1 << 25);
- CMD = XY_COLOR_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
- break;
- default:
- return;
- }
-#ifndef I915
- if (dst_tiling != I915_TILING_NONE) {
- CMD |= XY_DST_TILED;
- dst_pitch /= 4;
- }
-#endif
-
- DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
- __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h);
-
- assert(w > 0);
- assert(h > 0);
-
- BEGIN_BATCH(6, NO_LOOP_CLIPRECTS);
- OUT_BATCH(CMD);
- OUT_BATCH(BR13 | dst_pitch);
- OUT_BATCH((y << 16) | x);
- OUT_BATCH(((y + h) << 16) | (x + w));
- OUT_RELOC(dst_buffer,
- I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
- dst_offset);
- OUT_BATCH(color);
- ADVANCE_BATCH();
-}
-
static GLuint translate_raster_op(GLenum logicop)
{
switch(logicop) {
@@ -257,7 +200,7 @@ static GLuint translate_raster_op(GLenum logicop)
/* Copy BitBlt
*/
-void
+GLboolean
intelEmitCopyBlit(struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
@@ -279,6 +222,19 @@ intelEmitCopyBlit(struct intel_context *intel,
dri_bo *aper_array[3];
BATCH_LOCALS;
+ if (dst_tiling != I915_TILING_NONE) {
+ if (dst_offset & 4095)
+ return GL_FALSE;
+ if (dst_tiling == I915_TILING_Y)
+ return GL_FALSE;
+ }
+ if (src_tiling != I915_TILING_NONE) {
+ if (src_offset & 4095)
+ return GL_FALSE;
+ if (src_tiling == I915_TILING_Y)
+ return GL_FALSE;
+ }
+
/* do space/cliprects check before going any further */
do {
aper_array[0] = intel->batch->buf;
@@ -293,12 +249,7 @@ intelEmitCopyBlit(struct intel_context *intel,
} while (pass < 2);
if (pass >= 2) {
- GLboolean locked = GL_FALSE;
- if (!intel->locked) {
- LOCK_HARDWARE(intel);
- locked = GL_TRUE;
- }
-
+ LOCK_HARDWARE(intel);
dri_bo_map(dst_buffer, GL_TRUE);
dri_bo_map(src_buffer, GL_FALSE);
_mesa_copy_rect((GLubyte *)dst_buffer->virtual + dst_offset,
@@ -312,11 +263,9 @@ intelEmitCopyBlit(struct intel_context *intel,
dri_bo_unmap(src_buffer);
dri_bo_unmap(dst_buffer);
-
- if (locked)
- UNLOCK_HARDWARE(intel);
+ UNLOCK_HARDWARE(intel);
- return;
+ return GL_TRUE;
}
intel_batchbuffer_require_space(intel->batch, 8 * 4, NO_LOOP_CLIPRECTS);
@@ -332,17 +281,18 @@ intelEmitCopyBlit(struct intel_context *intel,
switch (cpp) {
case 1:
+ CMD = XY_SRC_COPY_BLT_CMD;
+ break;
case 2:
- case 3:
- BR13 |= (1 << 24);
+ BR13 |= BR13_565;
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
- BR13 |= (1 << 24) | (1 << 25);
+ BR13 |= BR13_8888;
CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
break;
default:
- return;
+ return GL_FALSE;
}
#ifndef I915
@@ -357,7 +307,7 @@ intelEmitCopyBlit(struct intel_context *intel,
#endif
if (dst_y2 <= dst_y || dst_x2 <= dst_x) {
- return;
+ return GL_TRUE;
}
assert(dst_x < dst_x2);
@@ -379,6 +329,8 @@ intelEmitCopyBlit(struct intel_context *intel,
ADVANCE_BATCH();
intel_batchbuffer_emit_mi_flush(intel->batch);
+
+ return GL_TRUE;
}
@@ -481,10 +433,9 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
const GLbitfield bufBit = 1 << buf;
if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
/* OK, clear this renderbuffer */
- struct intel_region *irb_region =
- intel_get_rb_region(fb, buf);
+ struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, buf);
dri_bo *write_buffer =
- intel_region_buffer(intel, irb_region,
+ intel_region_buffer(intel, irb->region,
all ? INTEL_WRITE_FULL :
INTEL_WRITE_PART);
@@ -492,15 +443,13 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
GLint pitch, cpp;
GLuint BR13, CMD;
- ASSERT(irb_region);
-
- pitch = irb_region->pitch;
- cpp = irb_region->cpp;
+ pitch = irb->region->pitch;
+ cpp = irb->region->cpp;
DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
__FUNCTION__,
- irb_region->buffer, (pitch * cpp),
- irb_region->draw_offset,
+ irb->region->buffer, (pitch * cpp),
+ irb->region->draw_offset,
b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1);
BR13 = 0xf0 << 16;
@@ -508,7 +457,7 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
/* Setup the blit command */
if (cpp == 4) {
- BR13 |= (1 << 24) | (1 << 25);
+ BR13 |= BR13_8888;
if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
if (clearMask & BUFFER_BIT_DEPTH)
CMD |= XY_BLT_WRITE_RGB;
@@ -521,12 +470,14 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
}
}
else {
- ASSERT(cpp == 2 || cpp == 0);
- BR13 |= (1 << 24);
+ ASSERT(cpp == 2);
+ BR13 |= BR13_565;
}
+ assert(irb->region->tiling != I915_TILING_Y);
+
#ifndef I915
- if (irb_region->tiling != I915_TILING_NONE) {
+ if (irb->region->tiling != I915_TILING_NONE) {
CMD |= XY_DST_TILED;
pitch /= 4;
}
@@ -537,9 +488,36 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
clearVal = clear_depth;
}
else {
- clearVal = (cpp == 4)
- ? intel->ClearColor8888 : intel->ClearColor565;
- }
+ uint8_t clear[4];
+ GLclampf *color = ctx->Color.ClearColor;
+
+ CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);
+
+ switch (irb->texformat->MesaFormat) {
+ case MESA_FORMAT_ARGB8888:
+ clearVal = intel->ClearColor8888;
+ break;
+ case MESA_FORMAT_RGB565:
+ clearVal = intel->ClearColor565;
+ break;
+ case MESA_FORMAT_ARGB4444:
+ clearVal = PACK_COLOR_4444(clear[3], clear[0],
+ clear[1], clear[2]);
+ break;
+ case MESA_FORMAT_ARGB1555:
+ clearVal = PACK_COLOR_1555(clear[3], clear[0],
+ clear[1], clear[2]);
+ break;
+ default:
+ _mesa_problem(ctx, "Unexpected renderbuffer format: %d\n",
+ irb->texformat->MesaFormat);
+ clearVal = 0;
+ }
+ }
+
/*
_mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
buf, irb->Base.Name);
@@ -555,20 +533,19 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
OUT_BATCH((b.y2 << 16) | b.x2);
OUT_RELOC(write_buffer,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
- irb_region->draw_offset);
+ irb->region->draw_offset);
OUT_BATCH(clearVal);
ADVANCE_BATCH();
clearMask &= ~bufBit; /* turn off bit, for faster loop exit */
}
}
}
- intel_batchbuffer_emit_mi_flush(intel->batch);
}
UNLOCK_HARDWARE(intel);
}
-void
+GLboolean
intelEmitImmediateColorExpandBlit(struct intel_context *intel,
GLuint cpp,
GLubyte *src_bits, GLuint src_size,
@@ -584,11 +561,19 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel,
int dwords = ALIGN(src_size, 8) / 4;
uint32_t opcode, br13, blit_cmd;
+ if (dst_tiling != I915_TILING_NONE) {
+ if (dst_offset & 4095)
+ return GL_FALSE;
+ if (dst_tiling == I915_TILING_Y)
+ return GL_FALSE;
+ }
+
assert( logic_op - GL_CLEAR >= 0 );
assert( logic_op - GL_CLEAR < 0x10 );
+ assert(dst_pitch > 0);
if (w < 0 || h < 0)
- return;
+ return GL_TRUE;
dst_pitch *= cpp;
@@ -645,4 +630,46 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel,
REFERENCES_CLIPRECTS );
intel_batchbuffer_emit_mi_flush(intel->batch);
+
+ return GL_TRUE;
+}
+
+/* We don't have a memmove-type blit like some other hardware, so we'll do a
+ * rectangular blit covering a large space, then emit 1-scanline blit at the
+ * end to cover the last if we need.
+ */
+void
+intel_emit_linear_blit(struct intel_context *intel,
+ drm_intel_bo *dst_bo,
+ unsigned int dst_offset,
+ drm_intel_bo *src_bo,
+ unsigned int src_offset,
+ unsigned int size)
+{
+ GLuint pitch, height;
+
+ /* The pitch is a signed value. */
+ pitch = MIN2(size, (1 << 15) - 1);
+ height = size / pitch;
+ intelEmitCopyBlit(intel, 1,
+ pitch, src_bo, src_offset, I915_TILING_NONE,
+ pitch, dst_bo, dst_offset, I915_TILING_NONE,
+ 0, 0, /* src x/y */
+ 0, 0, /* dst x/y */
+ pitch, height, /* w, h */
+ GL_COPY);
+
+ src_offset += pitch * height;
+ dst_offset += pitch * height;
+ size -= pitch * height;
+ assert (size < (1 << 15));
+ if (size != 0) {
+ intelEmitCopyBlit(intel, 1,
+ size, src_bo, src_offset, I915_TILING_NONE,
+ size, dst_bo, dst_offset, I915_TILING_NONE,
+ 0, 0, /* src x/y */
+ 0, 0, /* dst x/y */
+ size, 1, /* w, h */
+ GL_COPY);
+ }
}
diff --git a/src/mesa/drivers/dri/intel/intel_blit.h b/src/mesa/drivers/dri/intel/intel_blit.h
index 52065b13ed..240cb7cd1b 100644
--- a/src/mesa/drivers/dri/intel/intel_blit.h
+++ b/src/mesa/drivers/dri/intel/intel_blit.h
@@ -35,7 +35,8 @@ extern void intelCopyBuffer(const __DRIdrawablePrivate * dpriv,
extern void intelClearWithBlit(GLcontext * ctx, GLbitfield mask);
-extern void intelEmitCopyBlit(struct intel_context *intel,
+GLboolean
+intelEmitCopyBlit(struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
dri_bo *src_buffer,
@@ -50,16 +51,7 @@ extern void intelEmitCopyBlit(struct intel_context *intel,
GLshort w, GLshort h,
GLenum logicop );
-extern void intelEmitFillBlit(struct intel_context *intel,
- GLuint cpp,
- GLshort dst_pitch,
- dri_bo *dst_buffer,
- GLuint dst_offset,
- uint32_t dst_tiling,
- GLshort x, GLshort y,
- GLshort w, GLshort h, GLuint color);
-
-void
+GLboolean
intelEmitImmediateColorExpandBlit(struct intel_context *intel,
GLuint cpp,
GLubyte *src_bits, GLuint src_size,
@@ -71,5 +63,11 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLenum logic_op);
+void intel_emit_linear_blit(struct intel_context *intel,
+ drm_intel_bo *dst_bo,
+ unsigned int dst_offset,
+ drm_intel_bo *src_bo,
+ unsigned int src_offset,
+ unsigned int size);
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
index 60d7bb3770..c55c5c426e 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
@@ -28,16 +28,18 @@
#include "main/imports.h"
#include "main/mtypes.h"
+#include "main/macros.h"
#include "main/bufferobj.h"
#include "intel_context.h"
+#include "intel_blit.h"
#include "intel_buffer_objects.h"
#include "intel_batchbuffer.h"
#include "intel_regions.h"
-static GLboolean intel_bufferobj_unmap(GLcontext * ctx,
- GLenum target,
- struct gl_buffer_object *obj);
+static GLboolean
+intel_bufferobj_unmap(GLcontext * ctx,
+ GLenum target, struct gl_buffer_object *obj);
/** Allocates a new dri_bo to store the data for the buffer object. */
static void
@@ -105,11 +107,13 @@ intel_bufferobj_free(GLcontext * ctx, struct gl_buffer_object *obj)
assert(intel_obj);
/* Buffer objects are automatically unmapped when deleting according
- * to the spec.
+ * to the spec, but Mesa doesn't do UnmapBuffer for us at context destroy
+ * (though it does if you call glDeleteBuffers)
*/
if (obj->Pointer)
intel_bufferobj_unmap(ctx, 0, obj);
+ _mesa_free(intel_obj->sys_buffer);
if (intel_obj->region) {
intel_bufferobj_release_region(intel, intel_obj);
}
@@ -126,9 +130,10 @@ intel_bufferobj_free(GLcontext * ctx, struct gl_buffer_object *obj)
* Allocate space for and store data in a buffer object. Any data that was
* previously stored in the buffer object is lost. If data is NULL,
* memory will be allocated, but no copy will occur.
- * Called via glBufferDataARB().
+ * Called via ctx->Driver.BufferData().
+ * \return GL_TRUE for success, GL_FALSE if out of memory
*/
-static void
+static GLboolean
intel_bufferobj_data(GLcontext * ctx,
GLenum target,
GLsizeiptrARB size,
@@ -141,11 +146,7 @@ intel_bufferobj_data(GLcontext * ctx,
intel_obj->Base.Size = size;
intel_obj->Base.Usage = usage;
- /* Buffer objects are automatically unmapped when creating new data buffers
- * according to the spec.
- */
- if (obj->Pointer)
- intel_bufferobj_unmap(ctx, 0, obj);
+ assert(!obj->Pointer); /* Mesa should have unmapped it */
if (intel_obj->region)
intel_bufferobj_release_region(intel, intel_obj);
@@ -154,12 +155,32 @@ intel_bufferobj_data(GLcontext * ctx,
dri_bo_unreference(intel_obj->buffer);
intel_obj->buffer = NULL;
}
+ _mesa_free(intel_obj->sys_buffer);
+ intel_obj->sys_buffer = NULL;
+
if (size != 0) {
+#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) {
+ intel_obj->sys_buffer = _mesa_malloc(size);
+ if (intel_obj->sys_buffer != NULL) {
+ if (data != NULL)
+ memcpy(intel_obj->sys_buffer, data, size);
+ return GL_TRUE;
+ }
+ }
+#endif
intel_bufferobj_alloc_buffer(intel, intel_obj);
+ if (!intel_obj->buffer)
+ return GL_FALSE;
if (data != NULL)
dri_bo_subdata(intel_obj->buffer, 0, size, data);
}
+
+ return GL_TRUE;
}
@@ -184,7 +205,10 @@ intel_bufferobj_subdata(GLcontext * ctx,
if (intel_obj->region)
intel_bufferobj_cow(intel, intel_obj);
- dri_bo_subdata(intel_obj->buffer, offset, size, data);
+ if (intel_obj->sys_buffer)
+ memcpy((char *)intel_obj->sys_buffer + offset, data, size);
+ else
+ dri_bo_subdata(intel_obj->buffer, offset, size, data);
}
@@ -216,11 +240,21 @@ intel_bufferobj_map(GLcontext * 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);
+ GLboolean write_only = (access == GL_WRITE_ONLY_ARB);
- /* XXX: Translate access to flags arg below:
- */
assert(intel_obj);
+ if (intel_obj->sys_buffer) {
+ obj->Pointer = intel_obj->sys_buffer;
+ return obj->Pointer;
+ }
+
+ /* Flush any existing batchbuffer that might have written to this
+ * buffer.
+ */
+ intelFlush(ctx);
+
if (intel_obj->region)
intel_bufferobj_cow(intel, intel_obj);
@@ -229,27 +263,214 @@ intel_bufferobj_map(GLcontext * ctx,
return NULL;
}
- dri_bo_map(intel_obj->buffer, GL_TRUE);
+ if (write_only && intel->intelScreen->kernel_exec_fencing) {
+ drm_intel_gem_bo_map_gtt(intel_obj->buffer);
+ intel_obj->mapped_gtt = GL_TRUE;
+ } else {
+ drm_intel_bo_map(intel_obj->buffer, !read_only);
+ intel_obj->mapped_gtt = GL_FALSE;
+ }
+
obj->Pointer = intel_obj->buffer->virtual;
+ obj->Length = obj->Size;
+ obj->Offset = 0;
+
+ return obj->Pointer;
+}
+
+/**
+ * Called via glMapBufferRange().
+ *
+ * The goal of this extension is to allow apps to accumulate their rendering
+ * at the same time as they accumulate their buffer object. Without it,
+ * you'd end up blocking on execution of rendering every time you mapped
+ * the buffer to put new data in.
+ *
+ * We support it in 3 ways: If unsynchronized, then don't bother
+ * flushing the batchbuffer before mapping the buffer, which can save blocking
+ * in many cases. If we would still block, and they allow the whole buffer
+ * to be invalidated, then just allocate a new buffer to replace the old one.
+ * If not, and we'd block, and they allow the subrange of the buffer to be
+ * invalidated, then we can make a new little BO, let them write into that,
+ * and blit it into the real BO at unmap time.
+ */
+static void *
+intel_bufferobj_map_range(GLcontext * ctx,
+ GLenum target, GLintptr offset, GLsizeiptr length,
+ GLbitfield access, struct gl_buffer_object *obj)
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+
+ assert(intel_obj);
+
+ /* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also
+ * internally uses our functions directly.
+ */
+ obj->Offset = offset;
+ obj->Length = length;
+ obj->AccessFlags = access;
+
+ if (intel_obj->sys_buffer) {
+ obj->Pointer = intel_obj->sys_buffer + offset;
+ return obj->Pointer;
+ }
+
+ if (intel_obj->region)
+ intel_bufferobj_cow(intel, intel_obj);
+
+ /* If the mapping is synchronized with other GL operations, flush
+ * the batchbuffer so that GEM knows about the buffer access for later
+ * syncing.
+ */
+ if (!(access & GL_MAP_UNSYNCHRONIZED_BIT))
+ intelFlush(ctx);
+
+ if (intel_obj->buffer == NULL) {
+ obj->Pointer = NULL;
+ return NULL;
+ }
+
+ /* If the user doesn't care about existing buffer contents and mapping
+ * would cause us to block, then throw out the old buffer.
+ */
+ if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) &&
+ (access & GL_MAP_INVALIDATE_BUFFER_BIT) &&
+ drm_intel_bo_busy(intel_obj->buffer)) {
+ drm_intel_bo_unreference(intel_obj->buffer);
+ intel_obj->buffer = dri_bo_alloc(intel->bufmgr, "bufferobj",
+ intel_obj->Base.Size, 64);
+ }
+
+ /* If the user is mapping a range of an active buffer object but
+ * doesn't require the current contents of that range, make a new
+ * BO, and we'll copy what they put in there out at unmap or
+ * FlushRange time.
+ */
+ if ((access & GL_MAP_INVALIDATE_RANGE_BIT) &&
+ drm_intel_bo_busy(intel_obj->buffer)) {
+ if (access & GL_MAP_FLUSH_EXPLICIT_BIT) {
+ intel_obj->range_map_buffer = _mesa_malloc(length);
+ obj->Pointer = intel_obj->range_map_buffer;
+ } else {
+ intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr,
+ "range map",
+ length, 64);
+ if (!(access & GL_MAP_READ_BIT) &&
+ intel->intelScreen->kernel_exec_fencing) {
+ drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo);
+ intel_obj->mapped_gtt = GL_TRUE;
+ } else {
+ drm_intel_bo_map(intel_obj->range_map_bo,
+ (access & GL_MAP_WRITE_BIT) != 0);
+ intel_obj->mapped_gtt = GL_FALSE;
+ }
+ obj->Pointer = intel_obj->range_map_bo->virtual;
+ }
+ return obj->Pointer;
+ }
+
+ if (!(access & GL_MAP_READ_BIT) &&
+ intel->intelScreen->kernel_exec_fencing) {
+ drm_intel_gem_bo_map_gtt(intel_obj->buffer);
+ intel_obj->mapped_gtt = GL_TRUE;
+ } else {
+ drm_intel_bo_map(intel_obj->buffer, (access & GL_MAP_WRITE_BIT) != 0);
+ intel_obj->mapped_gtt = GL_FALSE;
+ }
+
+ obj->Pointer = intel_obj->buffer->virtual + offset;
return obj->Pointer;
}
+/* Ideally we'd use a BO to avoid taking up cache space for the temporary
+ * data, but FlushMappedBufferRange may be followed by further writes to
+ * the pointer, so we would have to re-map after emitting our blit, which
+ * would defeat the point.
+ */
+static void
+intel_bufferobj_flush_mapped_range(GLcontext *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length,
+ struct gl_buffer_object *obj)
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+ drm_intel_bo *temp_bo;
+
+ /* Unless we're in the range map using a temporary system buffer,
+ * there's no work to do.
+ */
+ if (intel_obj->range_map_buffer == NULL)
+ return;
+
+ temp_bo = drm_intel_bo_alloc(intel->bufmgr, "range map flush", length, 64);
+
+ drm_intel_bo_subdata(temp_bo, 0, length, intel_obj->range_map_buffer);
+
+ intel_emit_linear_blit(intel,
+ intel_obj->buffer, obj->Offset + offset,
+ temp_bo, 0,
+ length);
+
+ drm_intel_bo_unreference(temp_bo);
+}
+
/**
- * Called via glMapBufferARB().
+ * Called via glUnmapBuffer().
*/
static GLboolean
intel_bufferobj_unmap(GLcontext * ctx,
GLenum target, struct gl_buffer_object *obj)
{
+ struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
- if (intel_obj->buffer != NULL) {
- assert(obj->Pointer);
- dri_bo_unmap(intel_obj->buffer);
- obj->Pointer = NULL;
+ assert(obj->Pointer);
+ if (intel_obj->sys_buffer != NULL) {
+ /* always keep the mapping around. */
+ } else if (intel_obj->range_map_buffer != NULL) {
+ /* 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);
+ free(intel_obj->range_map_buffer);
+ intel_obj->range_map_buffer = NULL;
+ } else if (intel_obj->range_map_bo != NULL) {
+ if (intel_obj->mapped_gtt) {
+ drm_intel_gem_bo_unmap_gtt(intel_obj->range_map_bo);
+ } else {
+ drm_intel_bo_unmap(intel_obj->range_map_bo);
+ }
+
+ intel_emit_linear_blit(intel,
+ intel_obj->buffer, obj->Offset,
+ intel_obj->range_map_bo, 0,
+ obj->Length);
+
+ /* 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);
+
+ drm_intel_bo_unreference(intel_obj->range_map_bo);
+ intel_obj->range_map_bo = NULL;
+ } else if (intel_obj->buffer != NULL) {
+ if (intel_obj->mapped_gtt) {
+ drm_intel_gem_bo_unmap_gtt(intel_obj->buffer);
+ } else {
+ drm_intel_bo_unmap(intel_obj->buffer);
+ }
}
+ obj->Pointer = NULL;
+ obj->Offset = 0;
+ obj->Length = 0;
+
return GL_TRUE;
}
@@ -266,19 +487,95 @@ intel_bufferobj_buffer(struct intel_context *intel,
}
}
+ if (intel_obj->buffer == NULL) {
+ void *sys_buffer = intel_obj->sys_buffer;
+
+ /* only one of buffer and sys_buffer could be non-NULL */
+ intel_bufferobj_alloc_buffer(intel, intel_obj);
+ intel_obj->sys_buffer = NULL;
+
+ intel_bufferobj_subdata(&intel->ctx,
+ GL_ARRAY_BUFFER_ARB,
+ 0,
+ intel_obj->Base.Size,
+ sys_buffer,
+ &intel_obj->Base);
+ _mesa_free(sys_buffer);
+ intel_obj->sys_buffer = NULL;
+ }
+
return intel_obj->buffer;
}
+static void
+intel_bufferobj_copy_subdata(GLcontext *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr read_offset, GLintptr write_offset,
+ GLsizeiptr size)
+{
+ struct intel_context *intel = intel_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;
+
+ if (size == 0)
+ return;
+
+ /* If we're in system memory, just map and memcpy. */
+ if (intel_src->sys_buffer || intel_dst->sys_buffer) {
+ /* The same buffer may be used, but note that regions copied may
+ * not overlap.
+ */
+ 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);
+ intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst);
+ } else {
+ const char *src_ptr;
+ char *dst_ptr;
+
+ src_ptr = intel_bufferobj_map(ctx, GL_COPY_READ_BUFFER,
+ GL_READ_ONLY, src);
+ dst_ptr = intel_bufferobj_map(ctx, GL_COPY_WRITE_BUFFER,
+ GL_WRITE_ONLY, dst);
+
+ memcpy(dst_ptr + write_offset, src_ptr + read_offset, size);
+
+ intel_bufferobj_unmap(ctx, GL_COPY_READ_BUFFER, src);
+ intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst);
+ }
+ }
+
+ /* 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);
+
+ intel_emit_linear_blit(intel,
+ dst_bo, write_offset,
+ src_bo, read_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);
+}
+
void
-intel_bufferobj_init(struct intel_context *intel)
+intelInitBufferObjectFuncs(struct dd_function_table *functions)
{
- GLcontext *ctx = &intel->ctx;
-
- ctx->Driver.NewBufferObject = intel_bufferobj_alloc;
- ctx->Driver.DeleteBuffer = intel_bufferobj_free;
- ctx->Driver.BufferData = intel_bufferobj_data;
- ctx->Driver.BufferSubData = intel_bufferobj_subdata;
- ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata;
- ctx->Driver.MapBuffer = intel_bufferobj_map;
- ctx->Driver.UnmapBuffer = intel_bufferobj_unmap;
+ functions->NewBufferObject = intel_bufferobj_alloc;
+ functions->DeleteBuffer = intel_bufferobj_free;
+ functions->BufferData = intel_bufferobj_data;
+ functions->BufferSubData = intel_bufferobj_subdata;
+ functions->GetBufferSubData = intel_bufferobj_get_subdata;
+ functions->MapBuffer = intel_bufferobj_map;
+ functions->MapBufferRange = intel_bufferobj_map_range;
+ functions->FlushMappedBufferRange = intel_bufferobj_flush_mapped_range;
+ functions->UnmapBuffer = intel_bufferobj_unmap;
+ functions->CopyBufferSubData = intel_bufferobj_copy_subdata;
}
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.h b/src/mesa/drivers/dri/intel/intel_buffer_objects.h
index bf6dbd58f2..bf3e08a320 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.h
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.h
@@ -42,10 +42,19 @@ struct intel_buffer_object
{
struct gl_buffer_object Base;
dri_bo *buffer; /* the low-level buffer manager's buffer handle */
+ /** System memory buffer data, if not using a BO to store the data. */
+ void *sys_buffer;
struct intel_region *region; /* Is there a zero-copy texture
associated with this (pixel)
buffer object? */
+
+ drm_intel_bo *range_map_bo;
+ void *range_map_buffer;
+ unsigned int range_map_offset;
+ GLsizei range_map_size;
+
+ GLboolean mapped_gtt;
};
@@ -57,7 +66,7 @@ dri_bo *intel_bufferobj_buffer(struct intel_context *intel,
/* Hook the bufferobject implementation into mesa:
*/
-void intel_bufferobj_init(struct intel_context *intel);
+void intelInitBufferObjectFuncs(struct dd_function_table *functions);
@@ -69,10 +78,7 @@ void intel_bufferobj_init(struct intel_context *intel);
static INLINE struct intel_buffer_object *
intel_buffer_object(struct gl_buffer_object *obj)
{
- if (obj->Name)
- return (struct intel_buffer_object *) obj;
- else
- return NULL;
+ return (struct intel_buffer_object *) obj;
}
/* Helpers for zerocopy image uploads. See also intel_regions.h:
diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c
index 0fd2f16a8f..e7357e78c5 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.c
+++ b/src/mesa/drivers/dri/intel/intel_buffers.c
@@ -25,25 +25,14 @@
*
**************************************************************************/
-#include "intel_screen.h"
#include "intel_context.h"
-#include "intel_blit.h"
#include "intel_buffers.h"
-#include "intel_chipset.h"
-#include "intel_depthstencil.h"
#include "intel_fbo.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
-#include "intel_reg.h"
-#include "main/context.h"
#include "main/framebuffer.h"
-#include "swrast/swrast.h"
-#include "utils.h"
#include "drirenderbuffer.h"
-#include "vblank.h"
-#include "i915_drm.h"
-#define FILE_DEBUG_FLAG DEBUG_BLIT
/**
* XXX move this into a new dri/common/cliprects.c file.
@@ -114,7 +103,6 @@ intel_get_cliprects(struct intel_context *intel,
int *x_off, int *y_off)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
- struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
if (intel->constant_cliprect) {
/* FBO or DRI2 rendering, which can just use the fb's size. */
@@ -143,399 +131,6 @@ intel_get_cliprects(struct intel_context *intel,
}
}
-/**
- * This will be called whenever the currently bound window is moved/resized.
- * XXX: actually, it seems to NOT be called when the window is only moved (BP).
- */
-void
-intelWindowMoved(struct intel_context *intel)
-{
- GLcontext *ctx = &intel->ctx;
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
- struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
-
- if (!intel->intelScreen->driScrnPriv->dri2.enabled &&
- intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) {
- volatile drm_i915_sarea_t *sarea = intel->sarea;
- drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
- .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
- drm_clip_rect_t planeA_rect = { .x1 = sarea->planeA_x, .y1 = sarea->planeA_y,
- .x2 = sarea->planeA_x + sarea->planeA_w,
- .y2 = sarea->planeA_y + sarea->planeA_h };
- drm_clip_rect_t planeB_rect = { .x1 = sarea->planeB_x, .y1 = sarea->planeB_y,
- .x2 = sarea->planeB_x + sarea->planeB_w,
- .y2 = sarea->planeB_y + sarea->planeB_h };
- GLint areaA = driIntersectArea( drw_rect, planeA_rect );
- GLint areaB = driIntersectArea( drw_rect, planeB_rect );
- GLuint flags = dPriv->vblFlags;
-
- /* Update vblank info
- */
- if (areaB > areaA || (areaA == areaB && areaB > 0)) {
- flags = dPriv->vblFlags | VBLANK_FLAG_SECONDARY;
- } else {
- flags = dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY;
- }
-
- /* Check to see if we changed pipes */
- if (flags != dPriv->vblFlags && dPriv->vblFlags &&
- !(dPriv->vblFlags & VBLANK_FLAG_NO_IRQ)) {
- int64_t count;
- drmVBlank vbl;
- int i;
-
- /*
- * Deal with page flipping
- */
- vbl.request.type = DRM_VBLANK_ABSOLUTE;
-
- if ( dPriv->vblFlags & VBLANK_FLAG_SECONDARY ) {
- vbl.request.type |= DRM_VBLANK_SECONDARY;
- }
-
- for (i = 0; i < 2; i++) {
- if (!intel_fb->color_rb[i] ||
- (intel_fb->vbl_waited - intel_fb->color_rb[i]->vbl_pending) <=
- (1<<23))
- continue;
-
- vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending;
- drmWaitVBlank(intel->driFd, &vbl);
- }
-
- /*
- * Update msc_base from old pipe
- */
- driDrawableGetMSC32(dPriv->driScreenPriv, dPriv, &count);
- dPriv->msc_base = count;
- /*
- * Then get new vblank_base and vblSeq values
- */
- dPriv->vblFlags = flags;
- driGetCurrentVBlank(dPriv);
- dPriv->vblank_base = dPriv->vblSeq;
-
- intel_fb->vbl_waited = dPriv->vblSeq;
-
- for (i = 0; i < 2; i++) {
- if (intel_fb->color_rb[i])
- intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited;
- }
- }
- } else {
- dPriv->vblFlags &= ~VBLANK_FLAG_SECONDARY;
- }
-
- /* Update Mesa's notion of window size */
- driUpdateFramebufferSize(ctx, dPriv);
- intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */
-
- /* Update hardware scissor */
- if (ctx->Driver.Scissor != NULL) {
- ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
- ctx->Scissor.Width, ctx->Scissor.Height);
- }
-
- /* Re-calculate viewport related state */
- if (ctx->Driver.DepthRange != NULL)
- ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far );
-}
-
-
-
-/* A true meta version of this would be very simple and additionally
- * machine independent. Maybe we'll get there one day.
- */
-static void
-intelClearWithTris(struct intel_context *intel, GLbitfield mask)
-{
- GLcontext *ctx = &intel->ctx;
- struct gl_framebuffer *fb = ctx->DrawBuffer;
- GLuint buf;
-
- intel->vtbl.install_meta_state(intel);
-
- /* Back and stencil cliprects are the same. Try and do both
- * buffers at once:
- */
- if (mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) {
- struct intel_region *backRegion =
- intel_get_rb_region(fb, BUFFER_BACK_LEFT);
- struct intel_region *depthRegion =
- intel_get_rb_region(fb, BUFFER_DEPTH);
-
- intel->vtbl.meta_draw_region(intel, backRegion, depthRegion);
-
- if (mask & BUFFER_BIT_BACK_LEFT)
- intel->vtbl.meta_color_mask(intel, GL_TRUE);
- else
- intel->vtbl.meta_color_mask(intel, GL_FALSE);
-
- if (mask & BUFFER_BIT_STENCIL)
- intel->vtbl.meta_stencil_replace(intel,
- intel->ctx.Stencil.WriteMask[0],
- intel->ctx.Stencil.Clear);
- else
- intel->vtbl.meta_no_stencil_write(intel);
-
- if (mask & BUFFER_BIT_DEPTH)
- intel->vtbl.meta_depth_replace(intel);
- else
- intel->vtbl.meta_no_depth_write(intel);
-
- intel->vtbl.meta_draw_quad(intel,
- fb->_Xmin,
- fb->_Xmax,
- fb->_Ymin,
- fb->_Ymax,
- intel->ctx.Depth.Clear,
- intel->ClearColor8888,
- 0, 0, 0, 0); /* texcoords */
-
- mask &= ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH);
- }
-
- /* clear the remaining (color) renderbuffers */
- for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
- const GLuint bufBit = 1 << buf;
- if (mask & bufBit) {
- struct intel_renderbuffer *irbColor =
- intel_renderbuffer(fb->Attachment[buf].Renderbuffer);
-
- ASSERT(irbColor);
-
- intel->vtbl.meta_no_depth_write(intel);
- intel->vtbl.meta_no_stencil_write(intel);
- intel->vtbl.meta_color_mask(intel, GL_TRUE);
- intel->vtbl.meta_draw_region(intel, irbColor->region, NULL);
-
- intel->vtbl.meta_draw_quad(intel,
- fb->_Xmin,
- fb->_Xmax,
- fb->_Ymin,
- fb->_Ymax,
- 0, intel->ClearColor8888,
- 0, 0, 0, 0); /* texcoords */
-
- mask &= ~bufBit;
- }
- }
-
- intel->vtbl.leave_meta_state(intel);
-}
-
-static const char *buffer_names[] = {
- [BUFFER_FRONT_LEFT] = "front",
- [BUFFER_BACK_LEFT] = "back",
- [BUFFER_FRONT_RIGHT] = "front right",
- [BUFFER_BACK_RIGHT] = "back right",
- [BUFFER_AUX0] = "aux0",
- [BUFFER_AUX1] = "aux1",
- [BUFFER_AUX2] = "aux2",
- [BUFFER_AUX3] = "aux3",
- [BUFFER_DEPTH] = "depth",
- [BUFFER_STENCIL] = "stencil",
- [BUFFER_ACCUM] = "accum",
- [BUFFER_COLOR0] = "color0",
- [BUFFER_COLOR1] = "color1",
- [BUFFER_COLOR2] = "color2",
- [BUFFER_COLOR3] = "color3",
- [BUFFER_COLOR4] = "color4",
- [BUFFER_COLOR5] = "color5",
- [BUFFER_COLOR6] = "color6",
- [BUFFER_COLOR7] = "color7",
-};
-
-/**
- * Called by ctx->Driver.Clear.
- */
-static void
-intelClear(GLcontext *ctx, GLbitfield mask)
-{
- struct intel_context *intel = intel_context(ctx);
- const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
- GLbitfield tri_mask = 0;
- GLbitfield blit_mask = 0;
- GLbitfield swrast_mask = 0;
- struct gl_framebuffer *fb = ctx->DrawBuffer;
- GLuint i;
-
- if (0)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- /* HW color buffers (front, back, aux, generic FBO, etc) */
- if (colorMask == ~0) {
- /* clear all R,G,B,A */
- /* XXX FBO: need to check if colorbuffers are software RBOs! */
- blit_mask |= (mask & BUFFER_BITS_COLOR);
- }
- else {
- /* glColorMask in effect */
- tri_mask |= (mask & BUFFER_BITS_COLOR);
- }
-
- /* HW stencil */
- if (mask & BUFFER_BIT_STENCIL) {
- const struct intel_region *stencilRegion
- = intel_get_rb_region(fb, BUFFER_STENCIL);
- if (stencilRegion) {
- /* have hw stencil */
- if (IS_965(intel->intelScreen->deviceID) ||
- (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
- /* We have to use the 3D engine if we're clearing a partial mask
- * of the stencil buffer, or if we're on a 965 which has a tiled
- * depth/stencil buffer in a layout we can't blit to.
- */
- tri_mask |= BUFFER_BIT_STENCIL;
- }
- else {
- /* clearing all stencil bits, use blitting */
- blit_mask |= BUFFER_BIT_STENCIL;
- }
- }
- }
-
- /* HW depth */
- if (mask & BUFFER_BIT_DEPTH) {
- /* clear depth with whatever method is used for stencil (see above) */
- if (IS_965(intel->intelScreen->deviceID) ||
- tri_mask & BUFFER_BIT_STENCIL)
- tri_mask |= BUFFER_BIT_DEPTH;
- else
- blit_mask |= BUFFER_BIT_DEPTH;
- }
-
- /* SW fallback clearing */
- swrast_mask = mask & ~tri_mask & ~blit_mask;
-
- for (i = 0; i < BUFFER_COUNT; i++) {
- GLuint bufBit = 1 << i;
- if ((blit_mask | tri_mask) & bufBit) {
- if (!fb->Attachment[i].Renderbuffer->ClassID) {
- blit_mask &= ~bufBit;
- tri_mask &= ~bufBit;
- swrast_mask |= bufBit;
- }
- }
- }
-
- if (blit_mask) {
- if (INTEL_DEBUG & DEBUG_BLIT) {
- DBG("blit clear:");
- for (i = 0; i < BUFFER_COUNT; i++) {
- if (blit_mask & (1 << i))
- DBG(" %s", buffer_names[i]);
- }
- DBG("\n");
- }
- intelClearWithBlit(ctx, blit_mask);
- }
-
- if (tri_mask) {
- if (INTEL_DEBUG & DEBUG_BLIT) {
- DBG("tri clear:");
- for (i = 0; i < BUFFER_COUNT; i++) {
- if (tri_mask & (1 << i))
- DBG(" %s", buffer_names[i]);
- }
- DBG("\n");
- }
- intelClearWithTris(intel, tri_mask);
- }
-
- if (swrast_mask) {
- if (INTEL_DEBUG & DEBUG_BLIT) {
- DBG("swrast clear:");
- for (i = 0; i < BUFFER_COUNT; i++) {
- if (swrast_mask & (1 << i))
- DBG(" %s", buffer_names[i]);
- }
- DBG("\n");
- }
- _swrast_Clear(ctx, swrast_mask);
- }
-}
-
-void
-intelSwapBuffers(__DRIdrawablePrivate * dPriv)
-{
- __DRIscreenPrivate *psp = dPriv->driScreenPriv;
-
- if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
- GET_CURRENT_CONTEXT(ctx);
- struct intel_context *intel;
-
- if (ctx == NULL)
- return;
-
- intel = intel_context(ctx);
-
- if (ctx->Visual.doubleBufferMode) {
- GLboolean missed_target;
- struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
- int64_t ust;
-
- _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
-
- /*
- * The old swapping ioctl was incredibly racy, just wait for vblank
- * and do the swap ourselves.
- */
- driWaitForVBlank(dPriv, &missed_target);
-
- /*
- * Update each buffer's vbl_pending so we don't get too out of
- * sync
- */
- intel_get_renderbuffer(&intel_fb->Base,
- BUFFER_BACK_LEFT)->vbl_pending = dPriv->vblSeq;
- intel_get_renderbuffer(&intel_fb->Base,
- BUFFER_FRONT_LEFT)->vbl_pending = dPriv->vblSeq;
-
- intelCopyBuffer(dPriv, NULL);
-
- intel_fb->swap_count++;
- (*psp->systemTime->getUST) (&ust);
- if (missed_target) {
- intel_fb->swap_missed_count++;
- intel_fb->swap_missed_ust = ust - intel_fb->swap_ust;
- }
-
- intel_fb->swap_ust = ust;
- }
- drmCommandNone(intel->driFd, DRM_I915_GEM_THROTTLE);
-
- }
- else {
- /* XXX this shouldn't be an error but we can't handle it for now */
- fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
- }
-}
-
-void
-intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
-{
- if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
- struct intel_context *intel =
- (struct intel_context *) dPriv->driContextPriv->driverPrivate;
- GLcontext *ctx = &intel->ctx;
-
- if (ctx->Visual.doubleBufferMode) {
- drm_clip_rect_t rect;
- rect.x1 = x + dPriv->x;
- rect.y1 = (dPriv->h - y - h) + dPriv->y;
- rect.x2 = rect.x1 + w;
- rect.y2 = rect.y1 + h;
- _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
- intelCopyBuffer(dPriv, &rect);
- }
- }
- else {
- /* XXX this shouldn't be an error but we can't handle it for now */
- fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
- }
-}
-
/**
* Update the hardware state for drawing into a window or framebuffer object.
@@ -559,10 +154,10 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
return;
}
- /* Do this here, note core Mesa, since this function is called from
+ /* Do this here, not core Mesa, since this function is called from
* many places within the driver.
*/
- if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
+ if (ctx->NewState & _NEW_BUFFERS) {
/* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
_mesa_update_framebuffer(ctx);
/* this updates the DrawBuffer's Width/Height if it's a FBO */
@@ -577,9 +172,6 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
return;
}
- if (fb->Name)
- intel_validate_paired_depth_stencil(ctx, fb);
-
/*
* How many color buffers are we drawing into?
*/
@@ -587,7 +179,8 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
/* writing to 0 */
colorRegions[0] = NULL;
intel->constant_cliprect = GL_TRUE;
- } else if (fb->_NumColorDrawBuffers > 1) {
+ }
+ else if (fb->_NumColorDrawBuffers > 1) {
int i;
struct intel_renderbuffer *irb;
@@ -609,6 +202,8 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
intel_batchbuffer_flush(intel->batch);
intel->front_cliprects = GL_TRUE;
colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
+
+ intel->front_buffer_dirty = GL_TRUE;
}
else {
if (!intel->constant_cliprect && intel->front_cliprects)
@@ -626,14 +221,6 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
}
}
- /* Update culling direction which changes depending on the
- * orientation of the buffer:
- */
- if (ctx->Driver.FrontFace)
- ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
- else
- ctx->NewState |= _NEW_POLYGON;
-
if (!colorRegions[0]) {
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
}
@@ -665,59 +252,50 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
/***
*** Stencil buffer
*** This can only be hardware accelerated if we're using a
- *** combined DEPTH_STENCIL buffer (for now anyway).
+ *** combined DEPTH_STENCIL buffer.
***/
if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
if (irbStencil && irbStencil->region) {
ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
- /* need to re-compute stencil hw state */
- if (ctx->Driver.Enable != NULL)
- ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
- else
- ctx->NewState |= _NEW_STENCIL;
- if (!depthRegion)
- depthRegion = irbStencil->region;
}
else {
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
}
}
else {
- /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
+ /* XXX FBO: instead of FALSE, pass ctx->Stencil._Enabled ??? */
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
- /* need to re-compute stencil hw state */
- if (ctx->Driver.Enable != NULL)
- ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
- else
- ctx->NewState |= _NEW_STENCIL;
}
/*
- * Update depth test state
+ * Update depth and stencil test state
*/
if (ctx->Driver.Enable) {
- if (ctx->Depth.Test && fb->Visual.depthBits > 0) {
- ctx->Driver.Enable(ctx, GL_DEPTH_TEST, GL_TRUE);
- } else {
- ctx->Driver.Enable(ctx, GL_DEPTH_TEST, GL_FALSE);
- }
- } else {
- ctx->NewState |= _NEW_DEPTH;
+ ctx->Driver.Enable(ctx, GL_DEPTH_TEST,
+ (ctx->Depth.Test && fb->Visual.depthBits > 0));
+ ctx->Driver.Enable(ctx, GL_STENCIL_TEST,
+ (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0));
+ }
+ else {
+ /* Mesa's Stencil._Enabled field is updated when
+ * _NEW_BUFFERS | _NEW_STENCIL, but i965 code assumes that the value
+ * only changes with _NEW_STENCIL (which seems sensible). So flag it
+ * here since this is the _NEW_BUFFERS path.
+ */
+ ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL);
}
intel->vtbl.set_draw_region(intel, colorRegions, depthRegion,
- fb->_NumColorDrawBuffers);
+ fb->_NumColorDrawBuffers);
/* update viewport since it depends on window size */
- if (ctx->Driver.Viewport) {
- ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
- ctx->Viewport.Width, ctx->Viewport.Height);
- } else {
- ctx->NewState |= _NEW_VIEWPORT;
- }
-
+#ifdef I915
+ intelCalcViewport(ctx);
+#else
+ ctx->NewState |= _NEW_VIEWPORT;
+#endif
/* Set state we know depends on drawable parameters:
*/
if (ctx->Driver.Scissor)
@@ -729,12 +307,37 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
ctx->Driver.DepthRange(ctx,
ctx->Viewport.Near,
ctx->Viewport.Far);
+
+ /* Update culling direction which changes depending on the
+ * orientation of the buffer:
+ */
+ if (ctx->Driver.FrontFace)
+ ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
+ else
+ ctx->NewState |= _NEW_POLYGON;
}
static void
intelDrawBuffer(GLcontext * ctx, GLenum mode)
{
+ if ((ctx->DrawBuffer != NULL) && (ctx->DrawBuffer->Name == 0)) {
+ struct intel_context *const intel = intel_context(ctx);
+ const GLboolean was_front_buffer_rendering =
+ intel->is_front_buffer_rendering;
+
+ intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT)
+ || (mode == GL_FRONT);
+
+ /* If we weren't front-buffer rendering before but we are now, make sure
+ * that the front-buffer has actually been allocated.
+ */
+ if (!was_front_buffer_rendering && intel->is_front_buffer_rendering) {
+ intel_update_renderbuffers(intel->driContext,
+ intel->driContext->driDrawablePriv);
+ }
+ }
+
intel_draw_buffer(ctx, ctx->DrawBuffer);
}
@@ -742,6 +345,23 @@ intelDrawBuffer(GLcontext * ctx, GLenum mode)
static void
intelReadBuffer(GLcontext * ctx, GLenum mode)
{
+ if ((ctx->DrawBuffer != NULL) && (ctx->DrawBuffer->Name == 0)) {
+ struct intel_context *const intel = intel_context(ctx);
+ const GLboolean was_front_buffer_reading =
+ intel->is_front_buffer_reading;
+
+ intel->is_front_buffer_reading = (mode == GL_FRONT_LEFT)
+ || (mode == GL_FRONT);
+
+ /* If we weren't front-buffer reading before but we are now, make sure
+ * that the front-buffer has actually been allocated.
+ */
+ if (!was_front_buffer_reading && intel->is_front_buffer_reading) {
+ intel_update_renderbuffers(intel->driContext,
+ intel->driContext->driDrawablePriv);
+ }
+ }
+
if (ctx->ReadBuffer == ctx->DrawBuffer) {
/* This will update FBO completeness status.
* A framebuffer will be incomplete if the GL_READ_BUFFER setting
@@ -759,7 +379,6 @@ intelReadBuffer(GLcontext * ctx, GLenum mode)
void
intelInitBufferFuncs(struct dd_function_table *functions)
{
- functions->Clear = intelClear;
functions->DrawBuffer = intelDrawBuffer;
functions->ReadBuffer = intelReadBuffer;
}
diff --git a/src/mesa/drivers/dri/intel/intel_buffers.h b/src/mesa/drivers/dri/intel/intel_buffers.h
index 0be1cee091..6069d38e9e 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.h
+++ b/src/mesa/drivers/dri/intel/intel_buffers.h
@@ -45,10 +45,6 @@ extern struct intel_region *intel_readbuf_region(struct intel_context *intel);
extern struct intel_region *intel_drawbuf_region(struct intel_context *intel);
-extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv);
-
-extern void intelWindowMoved(struct intel_context *intel);
-
extern void intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb);
extern void intelInitBufferFuncs(struct dd_function_table *functions);
@@ -57,5 +53,8 @@ void intel_get_cliprects(struct intel_context *intel,
struct drm_clip_rect **cliprects,
unsigned int *num_cliprects,
int *x_off, int *y_off);
+#ifdef I915
+void intelCalcViewport(GLcontext * ctx);
+#endif
#endif /* INTEL_BUFFERS_H */
diff --git a/src/mesa/drivers/dri/intel/intel_chipset.h b/src/mesa/drivers/dri/intel/intel_chipset.h
index d1b4941601..3dc8653a73 100644
--- a/src/mesa/drivers/dri/intel/intel_chipset.h
+++ b/src/mesa/drivers/dri/intel/intel_chipset.h
@@ -46,6 +46,13 @@
#define PCI_CHIP_G33_G 0x29C2
#define PCI_CHIP_Q33_G 0x29D2
+#define PCI_CHIP_IGD_GM 0xA011
+#define PCI_CHIP_IGD_G 0xA001
+
+#define IS_IGDGM(devid) (devid == PCI_CHIP_IGD_GM)
+#define IS_IGDG(devid) (devid == PCI_CHIP_IGD_G)
+#define IS_IGD(devid) (IS_IGDG(devid) || IS_IGDGM(devid))
+
#define PCI_CHIP_I965_G 0x29A2
#define PCI_CHIP_I965_Q 0x2992
#define PCI_CHIP_I965_G_1 0x2982
@@ -59,6 +66,10 @@
#define PCI_CHIP_Q45_G 0x2E12
#define PCI_CHIP_G45_G 0x2E22
#define PCI_CHIP_G41_G 0x2E32
+#define PCI_CHIP_B43_G 0x2E42
+
+#define PCI_CHIP_ILD_G 0x0042
+#define PCI_CHIP_ILM_G 0x0046
#define IS_MOBILE(devid) (devid == PCI_CHIP_I855_GM || \
devid == PCI_CHIP_I915_GM || \
@@ -66,15 +77,22 @@
devid == PCI_CHIP_I945_GME || \
devid == PCI_CHIP_I965_GM || \
devid == PCI_CHIP_I965_GME || \
- devid == PCI_CHIP_GM45_GM)
+ devid == PCI_CHIP_GM45_GM || \
+ IS_IGD(devid) || \
+ devid == PCI_CHIP_ILM_G)
#define IS_G45(devid) (devid == PCI_CHIP_IGD_E_G || \
devid == PCI_CHIP_Q45_G || \
devid == PCI_CHIP_G45_G || \
- devid == PCI_CHIP_G41_G)
+ devid == PCI_CHIP_G41_G || \
+ devid == PCI_CHIP_B43_G)
#define IS_GM45(devid) (devid == PCI_CHIP_GM45_GM)
#define IS_G4X(devid) (IS_G45(devid) || IS_GM45(devid))
+#define IS_ILD(devid) (devid == PCI_CHIP_ILD_G)
+#define IS_ILM(devid) (devid == PCI_CHIP_ILM_G)
+#define IS_IGDNG(devid) (IS_ILD(devid) || IS_ILM(devid))
+
#define IS_915(devid) (devid == PCI_CHIP_I915_G || \
devid == PCI_CHIP_E7221_G || \
devid == PCI_CHIP_I915_GM)
@@ -84,7 +102,7 @@
devid == PCI_CHIP_I945_GME || \
devid == PCI_CHIP_G33_G || \
devid == PCI_CHIP_Q33_G || \
- devid == PCI_CHIP_Q35_G)
+ devid == PCI_CHIP_Q35_G || IS_IGD(devid))
#define IS_965(devid) (devid == PCI_CHIP_I965_G || \
devid == PCI_CHIP_I965_Q || \
@@ -92,7 +110,8 @@
devid == PCI_CHIP_I965_GM || \
devid == PCI_CHIP_I965_GME || \
devid == PCI_CHIP_I946_GZ || \
- IS_G4X(devid))
+ IS_G4X(devid) || \
+ IS_IGDNG(devid))
#define IS_9XX(devid) (IS_915(devid) || \
IS_945(devid) || \
diff --git a/src/mesa/drivers/dri/intel/intel_clear.c b/src/mesa/drivers/dri/intel/intel_clear.c
new file mode 100644
index 0000000000..bce23724b3
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_clear.c
@@ -0,0 +1,194 @@
+/**************************************************************************
+ *
+ * Copyright 2003 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/glheader.h"
+#include "main/mtypes.h"
+#include "swrast/swrast.h"
+#include "drivers/common/meta.h"
+
+#include "intel_context.h"
+#include "intel_blit.h"
+#include "intel_chipset.h"
+#include "intel_clear.h"
+#include "intel_fbo.h"
+#include "intel_pixel.h"
+#include "intel_regions.h"
+
+#define FILE_DEBUG_FLAG DEBUG_BLIT
+
+static const char *buffer_names[] = {
+ [BUFFER_FRONT_LEFT] = "front",
+ [BUFFER_BACK_LEFT] = "back",
+ [BUFFER_FRONT_RIGHT] = "front right",
+ [BUFFER_BACK_RIGHT] = "back right",
+ [BUFFER_DEPTH] = "depth",
+ [BUFFER_STENCIL] = "stencil",
+ [BUFFER_ACCUM] = "accum",
+ [BUFFER_AUX0] = "aux0",
+ [BUFFER_COLOR0] = "color0",
+ [BUFFER_COLOR1] = "color1",
+ [BUFFER_COLOR2] = "color2",
+ [BUFFER_COLOR3] = "color3",
+ [BUFFER_COLOR4] = "color4",
+ [BUFFER_COLOR5] = "color5",
+ [BUFFER_COLOR6] = "color6",
+ [BUFFER_COLOR7] = "color7",
+};
+
+/**
+ * Called by ctx->Driver.Clear.
+ */
+static void
+intelClear(GLcontext *ctx, GLbitfield mask)
+{
+ struct intel_context *intel = intel_context(ctx);
+ const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
+ GLbitfield tri_mask = 0;
+ GLbitfield blit_mask = 0;
+ GLbitfield swrast_mask = 0;
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ GLuint i;
+
+ if (0)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ /* HW color buffers (front, back, aux, generic FBO, etc) */
+ if (colorMask == ~0) {
+ /* clear all R,G,B,A */
+ /* XXX FBO: need to check if colorbuffers are software RBOs! */
+ blit_mask |= (mask & BUFFER_BITS_COLOR);
+ }
+ else {
+ /* glColorMask in effect */
+ tri_mask |= (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT));
+ }
+
+ /* HW stencil */
+ if (mask & BUFFER_BIT_STENCIL) {
+ const struct intel_region *stencilRegion
+ = intel_get_rb_region(fb, BUFFER_STENCIL);
+ if (stencilRegion) {
+ /* have hw stencil */
+ if (stencilRegion->tiling == I915_TILING_Y ||
+ (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
+ /* We have to use the 3D engine if we're clearing a partial mask
+ * of the stencil buffer, or if we're on a 965 which has a tiled
+ * depth/stencil buffer in a layout we can't blit to.
+ */
+ tri_mask |= BUFFER_BIT_STENCIL;
+ }
+ else {
+ /* clearing all stencil bits, use blitting */
+ blit_mask |= BUFFER_BIT_STENCIL;
+ }
+ }
+ }
+
+ /* HW depth */
+ if (mask & BUFFER_BIT_DEPTH) {
+ const struct intel_region *irb = intel_get_rb_region(fb, BUFFER_DEPTH);
+
+ /* clear depth with whatever method is used for stencil (see above) */
+ if (irb->tiling == I915_TILING_Y || tri_mask & BUFFER_BIT_STENCIL)
+ tri_mask |= BUFFER_BIT_DEPTH;
+ else
+ blit_mask |= BUFFER_BIT_DEPTH;
+ }
+
+ /* If we're doing a tri pass for depth/stencil, include a likely color
+ * buffer with it.
+ */
+ if (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) {
+ int color_bit = _mesa_ffs(mask & BUFFER_BITS_COLOR);
+ if (color_bit != 0) {
+ tri_mask |= blit_mask & (1 << (color_bit - 1));
+ blit_mask &= ~(1 << (color_bit - 1));
+ }
+ }
+
+ /* SW fallback clearing */
+ swrast_mask = mask & ~tri_mask & ~blit_mask;
+
+ {
+ /* look for non-Intel renderbuffers (clear them with swrast) */
+ GLbitfield blit_or_tri = blit_mask | tri_mask;
+ while (blit_or_tri) {
+ GLuint i = _mesa_ffs(blit_or_tri) - 1;
+ GLbitfield bufBit = 1 << i;
+ if (!fb->Attachment[i].Renderbuffer->ClassID) {
+ blit_mask &= ~bufBit;
+ tri_mask &= ~bufBit;
+ swrast_mask |= bufBit;
+ }
+ blit_or_tri ^= bufBit;
+ }
+ }
+
+ if (blit_mask) {
+ if (INTEL_DEBUG & DEBUG_BLIT) {
+ DBG("blit clear:");
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (blit_mask & (1 << i))
+ DBG(" %s", buffer_names[i]);
+ }
+ DBG("\n");
+ }
+ intelClearWithBlit(ctx, blit_mask);
+ }
+
+ if (tri_mask) {
+ if (INTEL_DEBUG & DEBUG_BLIT) {
+ DBG("tri clear:");
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (tri_mask & (1 << i))
+ DBG(" %s", buffer_names[i]);
+ }
+ DBG("\n");
+ }
+ _mesa_meta_clear(&intel->ctx, tri_mask);
+ }
+
+ if (swrast_mask) {
+ if (INTEL_DEBUG & DEBUG_BLIT) {
+ DBG("swrast clear:");
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (swrast_mask & (1 << i))
+ DBG(" %s", buffer_names[i]);
+ }
+ DBG("\n");
+ }
+ _swrast_Clear(ctx, swrast_mask);
+ }
+}
+
+
+void
+intelInitClearFuncs(struct dd_function_table *functions)
+{
+ functions->Clear = intelClear;
+}
diff --git a/src/mesa/drivers/dri/intel/intel_clear.h b/src/mesa/drivers/dri/intel/intel_clear.h
new file mode 100644
index 0000000000..7fd6b310a9
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_clear.h
@@ -0,0 +1,38 @@
+
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef INTEL_CLEAR_H
+#define INTEL_CLEAR_H
+
+struct dd_function_table;
+
+extern void
+intelInitClearFuncs(struct dd_function_table *functions);
+
+
+#endif /* INTEL_CLEAR_H */
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index c4a24d7397..7a2e7617d0 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -27,9 +27,10 @@
#include "main/glheader.h"
+#include "main/colortab.h"
#include "main/context.h"
-#include "main/matrix.h"
-#include "main/simple_list.h"
+#include "main/convolve.h"
+#include "main/arrayobj.h"
#include "main/extensions.h"
#include "main/framebuffer.h"
#include "main/imports.h"
@@ -38,13 +39,8 @@
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
-
-#include "tnl/t_pipeline.h"
-#include "tnl/t_vertex.h"
-
#include "drivers/common/driverfuncs.h"
-
-#include "intel_screen.h"
+#include "drivers/common/meta.h"
#include "i830_dri.h"
@@ -52,52 +48,35 @@
#include "intel_buffers.h"
#include "intel_tex.h"
#include "intel_batchbuffer.h"
-#include "intel_blit.h"
+#include "intel_clear.h"
+#include "intel_extensions.h"
#include "intel_pixel.h"
#include "intel_regions.h"
#include "intel_buffer_objects.h"
#include "intel_fbo.h"
+#include "intel_eglimage.h"
#include "intel_decode.h"
#include "intel_bufmgr.h"
+#include "intel_screen.h"
+#include "intel_swapbuffers.h"
#include "drirenderbuffer.h"
#include "vblank.h"
#include "utils.h"
#include "xmlpool.h" /* for symbolic values of enum-type options */
+
+
#ifndef INTEL_DEBUG
int INTEL_DEBUG = (0);
#endif
-#define need_GL_ARB_multisample
-#define need_GL_ARB_occlusion_query
-#define need_GL_ARB_point_parameters
-#define need_GL_ARB_shader_objects
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
-#define need_GL_ARB_vertex_program
-#define need_GL_ARB_vertex_shader
-#define need_GL_ARB_window_pos
-#define need_GL_EXT_blend_color
-#define need_GL_EXT_blend_equation_separate
-#define need_GL_EXT_blend_func_separate
-#define need_GL_EXT_blend_minmax
-#define need_GL_EXT_cull_vertex
-#define need_GL_EXT_fog_coord
-#define need_GL_EXT_framebuffer_object
-#define need_GL_EXT_multi_draw_arrays
-#define need_GL_EXT_point_parameters
-#define need_GL_EXT_secondary_color
-#define need_GL_ATI_separate_stencil
-#define need_GL_NV_point_sprite
-#define need_GL_NV_vertex_program
-#define need_GL_VERSION_2_0
-#define need_GL_VERSION_2_1
-
-#include "extension_helper.h"
-
-#define DRIVER_DATE "20090114"
+
+#define DRIVER_DATE "20090712 2009Q2 RC3"
#define DRIVER_DATE_GEM "GEM " DRIVER_DATE
+
+static void intel_flush(GLcontext *ctx, GLboolean needs_mi_flush);
+
static const GLubyte *
intelGetString(GLcontext * ctx, GLenum name)
{
@@ -151,6 +130,10 @@ intelGetString(GLcontext * ctx, GLenum name)
case PCI_CHIP_Q33_G:
chipset = "Intel(R) Q33";
break;
+ case PCI_CHIP_IGD_GM:
+ case PCI_CHIP_IGD_G:
+ chipset = "Intel(R) IGD";
+ break;
case PCI_CHIP_I965_Q:
chipset = "Intel(R) 965Q";
break;
@@ -182,6 +165,15 @@ intelGetString(GLcontext * ctx, GLenum name)
case PCI_CHIP_G41_G:
chipset = "Intel(R) G41";
break;
+ case PCI_CHIP_B43_G:
+ chipset = "Intel(R) B43";
+ break;
+ case PCI_CHIP_ILD_G:
+ chipset = "Intel(R) IGDNG_D";
+ break;
+ case PCI_CHIP_ILM_G:
+ chipset = "Intel(R) IGDNG_M";
+ break;
default:
chipset = "Unknown Intel Chipset";
break;
@@ -197,6 +189,24 @@ intelGetString(GLcontext * ctx, GLenum name)
}
}
+static unsigned
+intel_bits_per_pixel(const struct intel_renderbuffer *rb)
+{
+ switch (rb->Base._ActualFormat) {
+ case GL_RGB5:
+ case GL_DEPTH_COMPONENT16:
+ return 16;
+ case GL_RGB8:
+ case GL_RGBA8:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH24_STENCIL8_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ return 32;
+ default:
+ return 0;
+ }
+}
+
void
intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
{
@@ -204,7 +214,7 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
struct intel_renderbuffer *rb;
struct intel_region *region, *depth_region;
struct intel_context *intel = context->driverPrivate;
- __DRIbuffer *buffers;
+ __DRIbuffer *buffers = NULL;
__DRIscreen *screen;
int i, count;
unsigned int attachments[10];
@@ -216,22 +226,65 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
screen = intel->intelScreen->driScrnPriv;
- i = 0;
- if (intel_fb->color_rb[0])
- attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
- if (intel_fb->color_rb[1])
- attachments[i++] = __DRI_BUFFER_BACK_LEFT;
- if (intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH))
- attachments[i++] = __DRI_BUFFER_DEPTH;
- if (intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL))
- attachments[i++] = __DRI_BUFFER_STENCIL;
-
- buffers = (*screen->dri2.loader->getBuffers)(drawable,
- &drawable->w,
- &drawable->h,
- attachments, i,
- &count,
- drawable->loaderPrivate);
+ if (screen->dri2.loader
+ && (screen->dri2.loader->base.version > 2)
+ && (screen->dri2.loader->getBuffersWithFormat != NULL)) {
+ struct intel_renderbuffer *depth_rb;
+ struct intel_renderbuffer *stencil_rb;
+
+ i = 0;
+ if ((intel->is_front_buffer_rendering ||
+ intel->is_front_buffer_reading ||
+ !intel_fb->color_rb[1])
+ && intel_fb->color_rb[0]) {
+ attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+ attachments[i++] = intel_bits_per_pixel(intel_fb->color_rb[0]);
+ }
+
+ if (intel_fb->color_rb[1]) {
+ attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+ attachments[i++] = intel_bits_per_pixel(intel_fb->color_rb[1]);
+ }
+
+ depth_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);
+ stencil_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL);
+
+ if ((depth_rb != NULL) && (stencil_rb != NULL)) {
+ attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
+ attachments[i++] = intel_bits_per_pixel(depth_rb);
+ } else if (depth_rb != NULL) {
+ attachments[i++] = __DRI_BUFFER_DEPTH;
+ attachments[i++] = intel_bits_per_pixel(depth_rb);
+ } else if (stencil_rb != NULL) {
+ attachments[i++] = __DRI_BUFFER_STENCIL;
+ attachments[i++] = intel_bits_per_pixel(stencil_rb);
+ }
+
+ buffers =
+ (*screen->dri2.loader->getBuffersWithFormat)(drawable,
+ &drawable->w,
+ &drawable->h,
+ attachments, i / 2,
+ &count,
+ drawable->loaderPrivate);
+ } else if (screen->dri2.loader) {
+ i = 0;
+ if (intel_fb->color_rb[0])
+ attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+ if (intel_fb->color_rb[1])
+ attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+ if (intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH))
+ attachments[i++] = __DRI_BUFFER_DEPTH;
+ if (intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL))
+ attachments[i++] = __DRI_BUFFER_STENCIL;
+
+ buffers = (*screen->dri2.loader->getBuffers)(drawable,
+ &drawable->w,
+ &drawable->h,
+ attachments, i,
+ &count,
+ drawable->loaderPrivate);
+ }
if (buffers == NULL)
return;
@@ -259,6 +312,11 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
region_name = "dri2 front buffer";
break;
+ case __DRI_BUFFER_FAKE_FRONT_LEFT:
+ rb = intel_fb->color_rb[0];
+ region_name = "dri2 fake front buffer";
+ break;
+
case __DRI_BUFFER_BACK_LEFT:
rb = intel_fb->color_rb[1];
region_name = "dri2 back buffer";
@@ -269,6 +327,11 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
region_name = "dri2 depth buffer";
break;
+ case __DRI_BUFFER_DEPTH_STENCIL:
+ rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);
+ region_name = "dri2 depth / stencil buffer";
+ break;
+
case __DRI_BUFFER_STENCIL:
rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL);
region_name = "dri2 stencil buffer";
@@ -282,6 +345,9 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
return;
}
+ if (rb == NULL)
+ continue;
+
if (rb->region) {
dri_bo_flink(rb->region->buffer, &name);
if (name == buffers[i].name)
@@ -312,6 +378,23 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
intel_renderbuffer_set_region(rb, region);
intel_region_release(&region);
+
+ if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) {
+ rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL);
+ if (rb != NULL) {
+ struct intel_region *stencil_region = NULL;
+
+ if (rb->region) {
+ dri_bo_flink(rb->region->buffer, &name);
+ if (name == buffers[i].name)
+ continue;
+ }
+
+ intel_region_reference(&stencil_region, region);
+ intel_renderbuffer_set_region(rb, stencil_region);
+ intel_region_release(&stencil_region);
+ }
+ }
}
driUpdateFramebufferSize(&intel->ctx, drawable);
@@ -328,9 +411,20 @@ intel_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
if (!driContext->driScreenPriv->dri2.enabled)
return;
- intel_update_renderbuffers(driContext, driContext->driDrawablePriv);
- if (driContext->driDrawablePriv != driContext->driReadablePriv)
- intel_update_renderbuffers(driContext, driContext->driReadablePriv);
+ if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
+ /* If we're rendering to the fake front buffer, make sure all the pending
+ * drawing has landed on the real front buffer. Otherwise when we
+ * eventually get to DRI2GetBuffersWithFormat the stale real front
+ * buffer contents will get copied to the new fake front buffer.
+ */
+ if (intel->is_front_buffer_rendering) {
+ intel_flush(ctx, GL_FALSE);
+ }
+
+ intel_update_renderbuffers(driContext, driContext->driDrawablePriv);
+ if (driContext->driDrawablePriv != driContext->driReadablePriv)
+ intel_update_renderbuffers(driContext, driContext->driReadablePriv);
+ }
old_viewport = ctx->Driver.Viewport;
ctx->Driver.Viewport = NULL;
@@ -340,112 +434,6 @@ intel_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
ctx->Driver.Viewport = old_viewport;
}
-/**
- * Extension strings exported by the intel driver.
- *
- * Extensions supported by all chips supported by i830_dri, i915_dri, or
- * i965_dri.
- */
-static const struct dri_extension card_extensions[] = {
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
- { "GL_ARB_multitexture", NULL },
- { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
- { "GL_ARB_texture_border_clamp", NULL },
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
- { "GL_ARB_texture_cube_map", NULL },
- { "GL_ARB_texture_env_add", NULL },
- { "GL_ARB_texture_env_combine", NULL },
- { "GL_ARB_texture_env_crossbar", NULL },
- { "GL_ARB_texture_env_dot3", NULL },
- { "GL_ARB_texture_mirrored_repeat", NULL },
- { "GL_ARB_texture_rectangle", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
- { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
- { "GL_ARB_window_pos", GL_ARB_window_pos_functions },
- { "GL_EXT_blend_color", GL_EXT_blend_color_functions },
- { "GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions },
- { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions },
- { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions },
- { "GL_EXT_blend_logic_op", NULL },
- { "GL_EXT_blend_subtract", NULL },
- { "GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions },
- { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
- { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
- { "GL_EXT_packed_depth_stencil", NULL },
- { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
- { "GL_EXT_stencil_wrap", NULL },
- { "GL_EXT_texture_edge_clamp", NULL },
- { "GL_EXT_texture_env_combine", NULL },
- { "GL_EXT_texture_env_dot3", NULL },
- { "GL_EXT_texture_filter_anisotropic", NULL },
- { "GL_EXT_texture_lod_bias", NULL },
- { "GL_3DFX_texture_compression_FXT1", NULL },
- { "GL_APPLE_client_storage", NULL },
- { "GL_MESA_pack_invert", NULL },
- { "GL_MESA_ycbcr_texture", NULL },
- { "GL_NV_blend_square", NULL },
- { "GL_NV_point_sprite", GL_NV_point_sprite_functions },
- { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
- { "GL_NV_vertex_program1_1", NULL },
- { "GL_SGIS_generate_mipmap", NULL },
- { NULL, NULL }
-};
-
-static const struct dri_extension brw_extensions[] = {
- { "GL_ARB_depth_texture", NULL },
- { "GL_ARB_draw_buffers", NULL },
- { "GL_ARB_fragment_program", NULL },
- { "GL_ARB_fragment_program_shadow", NULL },
- { "GL_ARB_fragment_shader", NULL },
- { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions },
- { "GL_ARB_point_sprite", NULL },
- { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
- { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions },
-#if 0
- /* Support for GLSL 1.20 is currently broken in core Mesa.
- */
- { "GL_ARB_shading_language_120", GL_VERSION_2_1_functions },
-#endif
- { "GL_ARB_shadow", NULL },
- { "GL_ARB_texture_non_power_of_two", NULL },
- { "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions },
- { "GL_EXT_shadow_funcs", NULL },
- { "GL_EXT_texture_sRGB", NULL },
- { "GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions },
- { "GL_ATI_texture_env_combine3", NULL },
- { NULL, NULL }
-};
-
-static const struct dri_extension arb_oq_extensions[] = {
- { NULL, NULL }
-};
-
-static const struct dri_extension ttm_extensions[] = {
- { "GL_ARB_pixel_buffer_object", NULL },
- { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
- { NULL, NULL }
-};
-
-/**
- * Initializes potential list of extensions if ctx == NULL, or actually enables
- * extensions for a context.
- */
-void intelInitExtensions(GLcontext *ctx, GLboolean enable_imaging)
-{
- struct intel_context *intel = ctx?intel_context(ctx):NULL;
-
- /* Disable imaging extension until convolution is working in teximage paths.
- */
- enable_imaging = GL_FALSE;
-
- driInitExtensions(ctx, card_extensions, enable_imaging);
-
- if (intel == NULL || intel->ttm)
- driInitExtensions(ctx, ttm_extensions, GL_FALSE);
-
- if (intel == NULL || IS_965(intel->intelScreen->deviceID))
- driInitExtensions(ctx, brw_extensions, GL_FALSE);
-}
static const struct dri_debug_control debug_control[] = {
{ "tex", DEBUG_TEXTURE},
@@ -496,9 +484,8 @@ intelInvalidateState(GLcontext * ctx, GLuint new_state)
intel->vtbl.invalidate_state( intel, new_state );
}
-
-void
-intelFlush(GLcontext * ctx)
+static void
+intel_flush(GLcontext *ctx, GLboolean needs_mi_flush)
{
struct intel_context *intel = intel_context(ctx);
@@ -512,10 +499,64 @@ intelFlush(GLcontext * ctx)
* lands onscreen in a timely manner, even if the X Server doesn't trigger
* a flush for us.
*/
- intel_batchbuffer_emit_mi_flush(intel->batch);
+ if (needs_mi_flush)
+ intel_batchbuffer_emit_mi_flush(intel->batch);
if (intel->batch->map != intel->batch->ptr)
intel_batchbuffer_flush(intel->batch);
+
+ if ((ctx->DrawBuffer->Name == 0) && intel->front_buffer_dirty) {
+ __DRIscreen *const screen = intel->intelScreen->driScrnPriv;
+
+ if (screen->dri2.loader &&
+ (screen->dri2.loader->base.version >= 2)
+ && (screen->dri2.loader->flushFrontBuffer != NULL)) {
+ (*screen->dri2.loader->flushFrontBuffer)(intel->driDrawable,
+ intel->driDrawable->loaderPrivate);
+
+ /* Only clear the dirty bit if front-buffer rendering is no longer
+ * enabled. This is done so that the dirty bit can only be set in
+ * glDrawBuffer. Otherwise the dirty bit would have to be set at
+ * each of N places that do rendering. This has worse performances,
+ * but it is much easier to get correct.
+ */
+ if (!intel->is_front_buffer_rendering) {
+ intel->front_buffer_dirty = GL_FALSE;
+ }
+ }
+ }
+}
+
+void
+intelFlush(GLcontext * ctx)
+{
+ intel_flush(ctx, GL_FALSE);
+}
+
+static void
+intel_glFlush(GLcontext *ctx)
+{
+ struct intel_context *intel = intel_context(ctx);
+
+ intel_flush(ctx, GL_TRUE);
+
+ /* We're using glFlush as an indicator that a frame is done, which is
+ * what DRI2 does before calling SwapBuffers (and means we should catch
+ * people doing front-buffer rendering, as well)..
+ *
+ * Wait for the swapbuffers before the one we just emitted, so we don't
+ * get too many swaps outstanding for apps that are GPU-heavy but not
+ * CPU-heavy.
+ *
+ * Unfortunately, we don't have a handle to the batch containing 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->first_post_swapbuffers_batch != NULL) {
+ 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;
+ }
}
void
@@ -531,7 +572,7 @@ intelFinish(GLcontext * ctx)
irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
- if (irb->region)
+ if (irb && irb->region)
dri_bo_wait_rendering(irb->region->buffer);
}
if (fb->_DepthBuffer) {
@@ -544,20 +585,26 @@ intelInitDriverFunctions(struct dd_function_table *functions)
{
_mesa_init_driver_functions(functions);
- functions->Flush = intelFlush;
+ functions->Flush = intel_glFlush;
functions->Finish = intelFinish;
functions->GetString = intelGetString;
functions->UpdateState = intelInvalidateState;
- functions->CopyColorTable = _swrast_CopyColorTable;
- functions->CopyColorSubTable = _swrast_CopyColorSubTable;
- functions->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
- functions->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+ _MESA_INIT_COLORTABLE_FUNCTIONS(functions, _swrast_);
+ _MESA_INIT_CONVOLVE_FUNCTIONS(functions, _swrast_);
intelInitTextureFuncs(functions);
+ intelInitTextureImageFuncs(functions);
+ intelInitTextureSubImageFuncs(functions);
+ intelInitTextureCopyImageFuncs(functions);
intelInitStateFuncs(functions);
+ intelInitClearFuncs(functions);
intelInitBufferFuncs(functions);
intelInitPixelFuncs(functions);
+ intelInitBufferObjectFuncs(functions);
+ intel_init_syncobj_functions(functions);
+
+ intelInitEGLImageFuncs(functions);
}
@@ -614,16 +661,20 @@ intelInitContext(struct intel_context *intel,
}
}
- ctx->Const.MaxTextureMaxAnisotropy = 2.0;
-
/* This doesn't yet catch all non-conformant rendering, but it's a
* start.
*/
if (getenv("INTEL_STRICT_CONFORMANCE")) {
- intel->strict_conformance = 1;
+ unsigned int value = atoi(getenv("INTEL_STRICT_CONFORMANCE"));
+ if (value > 0) {
+ intel->conformance_mode = value;
+ }
+ else {
+ intel->conformance_mode = 1;
+ }
}
- if (intel->strict_conformance) {
+ if (intel->conformance_mode > 0) {
ctx->Const.MinLineWidth = 1.0;
ctx->Const.MinLineWidthAA = 1.0;
ctx->Const.MaxLineWidth = 1.0;
@@ -649,7 +700,15 @@ intelInitContext(struct intel_context *intel,
*/
_mesa_init_point(ctx);
+ meta_init_metaops(ctx, &intel->meta);
ctx->Const.MaxColorAttachments = 4; /* XXX FBO: review this */
+ if (IS_965(intelScreen->deviceID)) {
+ if (MAX_WIDTH > 8192)
+ ctx->Const.MaxRenderbufferSize = 8192;
+ } else {
+ if (MAX_WIDTH > 2048)
+ ctx->Const.MaxRenderbufferSize = 2048;
+ }
/* Initialize the software rasterizer and helper modules. */
_swrast_CreateContext(ctx);
@@ -661,6 +720,8 @@ intelInitContext(struct intel_context *intel,
_swrast_allow_pixel_fog(ctx, GL_FALSE);
_swrast_allow_vertex_fog(ctx, GL_TRUE);
+ _mesa_meta_init(ctx);
+
intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
intel->hw_stipple = 1;
@@ -691,8 +752,6 @@ intelInitContext(struct intel_context *intel,
intel->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
- _math_matrix_ctr(&intel->ViewportMatrix);
-
if (IS_965(intelScreen->deviceID) && !intel->intelScreen->irq_active) {
_mesa_printf("IRQs not active. Exiting\n");
exit(1);
@@ -709,7 +768,6 @@ intelInitContext(struct intel_context *intel,
intel->batch = intel_batchbuffer_alloc(intel);
- intel_bufferobj_init(intel);
intel_fbo_init(intel);
if (intel->ctx.Mesa_DXTn) {
@@ -719,6 +777,15 @@ intelInitContext(struct intel_context *intel,
else if (driQueryOptionb(&intel->optionCache, "force_s3tc_enable")) {
_mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
}
+ intel->use_texture_tiling = driQueryOptionb(&intel->optionCache,
+ "texture_tiling");
+ if (intel->use_texture_tiling &&
+ !intel->intelScreen->kernel_exec_fencing) {
+ fprintf(stderr, "No kernel support for execution fencing, "
+ "disabling texture tiling\n");
+ intel->use_texture_tiling = GL_FALSE;
+ }
+ intel->use_early_z = driQueryOptionb(&intel->optionCache, "early_z");
intel->prim.primitive = ~0;
@@ -728,6 +795,16 @@ intelInitContext(struct intel_context *intel,
intel->no_rast = 1;
}
+ if (driQueryOptionb(&intel->optionCache, "always_flush_batch")) {
+ fprintf(stderr, "flushing batchbuffer before/after each draw call\n");
+ intel->always_flush_batch = 1;
+ }
+
+ if (driQueryOptionb(&intel->optionCache, "always_flush_cache")) {
+ fprintf(stderr, "flushing GPU caches before/after each draw call\n");
+ intel->always_flush_cache = 1;
+ }
+
/* Disable all hardware rendering (skip emitting batches and fences/waits
* to the kernel)
*/
@@ -748,6 +825,10 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
INTEL_FIREVERTICES(intel);
+ _mesa_meta_free(&intel->ctx);
+
+ meta_destroy_metaops(&intel->meta);
+
intel->vtbl.destroy(intel);
release_texture_heaps = (intel->ctx.Shared->RefCount == 1);
@@ -765,15 +846,68 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
intel->prim.vb = NULL;
dri_bo_unreference(intel->prim.vb_bo);
intel->prim.vb_bo = NULL;
+ dri_bo_unreference(intel->first_post_swapbuffers_batch);
+ intel->first_post_swapbuffers_batch = NULL;
if (release_texture_heaps) {
- /* This share group is about to go away, free our private
- * texture object data.
+ /* Nothing is currently done here to free texture heaps;
+ * but we're not using the texture heap utilities, so I
+ * rather think we shouldn't. I've taken a look, and can't
+ * find any private texture data hanging around anywhere, but
+ * I'm not yet certain there isn't any at all...
*/
- if (INTEL_DEBUG & DEBUG_TEXTURE)
+ /* if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "do something to free texture heaps\n");
+ */
}
+ /* XXX In intelMakeCurrent() below, the context's static regions are
+ * referenced inside the frame buffer; it's listed as a hack,
+ * with a comment of "XXX FBO temporary fix-ups!", but
+ * as long as it's there, we should release the regions here.
+ * The do/while loop around the block is used to allow the
+ * "continue" statements inside the block to exit the block,
+ * to avoid many layers of "if" constructs.
+ */
+ do {
+ __DRIdrawablePrivate * driDrawPriv = intel->driDrawable;
+ struct intel_framebuffer *intel_fb;
+ struct intel_renderbuffer *irbDepth, *irbStencil;
+ if (!driDrawPriv) {
+ /* We're already detached from the drawable; exit this block. */
+ continue;
+ }
+ intel_fb = (struct intel_framebuffer *) driDrawPriv->driverPrivate;
+ if (!intel_fb) {
+ /* The frame buffer is already gone; exit this block. */
+ continue;
+ }
+ irbDepth = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);
+ irbStencil = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL);
+
+ /* If the regions of the frame buffer still match the regions
+ * of the context, release them. If they've changed somehow,
+ * leave them alone.
+ */
+ if (intel_fb->color_rb[0] && intel_fb->color_rb[0]->region == intel->front_region) {
+ intel_renderbuffer_set_region(intel_fb->color_rb[0], NULL);
+ }
+ if (intel_fb->color_rb[1] && intel_fb->color_rb[1]->region == intel->back_region) {
+ intel_renderbuffer_set_region(intel_fb->color_rb[1], NULL);
+ }
+
+ if (irbDepth && irbDepth->region == intel->depth_region) {
+ intel_renderbuffer_set_region(irbDepth, NULL);
+ }
+ /* Usually, the stencil buffer is the same as the depth buffer;
+ * but they're handled separately in MakeCurrent, so we'll
+ * handle them separately here.
+ */
+ if (irbStencil && irbStencil->region == intel->depth_region) {
+ intel_renderbuffer_set_region(irbStencil, NULL);
+ }
+ } while (0);
+
intel_region_release(&intel->front_region);
intel_region_release(&intel->back_region);
intel_region_release(&intel->depth_region);
@@ -782,6 +916,9 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
/* free the Mesa context */
_mesa_free_context_data(&intel->ctx);
+
+ FREE(intel);
+ driContextPriv->driverPrivate = NULL;
}
}
@@ -810,7 +947,10 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
if (driDrawPriv != driReadPriv)
intel_update_renderbuffers(driContextPriv, driReadPriv);
} else {
- /* XXX FBO temporary fix-ups! */
+ /* XXX FBO temporary fix-ups! These are released in
+ * intelDextroyContext(), above. Changes here should be
+ * reflected there.
+ */
/* if the renderbuffers don't have regions, init them from the context */
struct intel_renderbuffer *irbDepth
= intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);
@@ -858,6 +998,11 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
? driGetDefaultVBlankFlags(&intel->optionCache)
: VBLANK_FLAG_NO_IRQ;
+ /* Prevent error printf if one crtc is disabled, this will
+ * be properly calculated in intelWindowMoved() next.
+ */
+ driDrawPriv->vblFlags = intelFixupVblank(intel, driDrawPriv);
+
(*psp->systemTime->getUST) (&intel_fb->swap_ust);
driDrawableInitVBlank(driDrawPriv);
intel_fb->vbl_waited = driDrawPriv->vblSeq;
@@ -890,7 +1035,6 @@ intelContendedLock(struct intel_context *intel, GLuint flags)
int me = intel->hHWContext;
drmGetLock(intel->driFd, intel->hHWContext, flags);
- intel->locked = 1;
if (INTEL_DEBUG & DEBUG_LOCK)
_mesa_printf("%s - got contended lock\n", __progname);
@@ -947,9 +1091,12 @@ void LOCK_HARDWARE( struct intel_context *intel )
struct intel_framebuffer *intel_fb = NULL;
struct intel_renderbuffer *intel_rb = NULL;
- _glthread_LOCK_MUTEX(lockMutex);
- assert(!intel->locked);
- intel->locked = 1;
+ intel->locked++;
+ if (intel->locked >= 2)
+ return;
+
+ if (!sPriv->dri2.enabled)
+ _glthread_LOCK_MUTEX(lockMutex);
if (intel->driDrawable) {
intel_fb = intel->driDrawable->driverPrivate;
@@ -996,13 +1143,16 @@ void UNLOCK_HARDWARE( struct intel_context *intel )
{
__DRIscreen *sPriv = intel->driScreen;
- intel->vtbl.note_unlock( intel );
- intel->locked = 0;
+ intel->locked--;
+ if (intel->locked > 0)
+ return;
- if (!sPriv->dri2.enabled)
- DRM_UNLOCK(intel->driFd, intel->driHwLock, intel->hHWContext);
+ assert(intel->locked == 0);
- _glthread_UNLOCK_MUTEX(lockMutex);
+ if (!sPriv->dri2.enabled) {
+ DRM_UNLOCK(intel->driFd, intel->driHwLock, intel->hHWContext);
+ _glthread_UNLOCK_MUTEX(lockMutex);
+ }
if (INTEL_DEBUG & DEBUG_LOCK)
_mesa_printf("%s - unlocked\n", __progname);
diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h
index 048286c196..03e7cf39d6 100644
--- a/src/mesa/drivers/dri/intel/intel_context.h
+++ b/src/mesa/drivers/dri/intel/intel_context.h
@@ -33,6 +33,7 @@
#include "main/mtypes.h"
#include "main/mm.h"
#include "texmem.h"
+#include "dri_metaops.h"
#include "drm.h"
#include "intel_bufmgr.h"
@@ -48,6 +49,8 @@
#define DV_PF_555 (1<<8)
#define DV_PF_565 (2<<8)
#define DV_PF_8888 (3<<8)
+#define DV_PF_4444 (8<<8)
+#define DV_PF_1555 (9<<8)
struct intel_region;
struct intel_context;
@@ -77,9 +80,19 @@ extern void intelFallback(struct intel_context *intel, GLuint bit,
#define INTEL_MAX_FIXUP 64
+struct intel_sync_object {
+ struct gl_sync_object Base;
+
+ /** Batch associated with this sync object */
+ drm_intel_bo *bo;
+};
+
+/**
+ * intel_context is derived from Mesa's context class: GLcontext.
+ */
struct intel_context
{
- GLcontext ctx; /* the parent class */
+ GLcontext ctx; /**< base class, must be first field */
struct
{
@@ -89,7 +102,6 @@ struct intel_context
void (*new_batch) (struct intel_context * intel);
void (*emit_invarient_state) (struct intel_context * intel);
void (*note_fence) (struct intel_context *intel, GLuint fence);
- void (*note_unlock) (struct intel_context *intel);
void (*update_texture_state) (struct intel_context * intel);
void (*render_start) (struct intel_context * intel);
@@ -100,7 +112,6 @@ struct intel_context
GLuint num_regions);
GLuint (*flush_cmd) (void);
- void (*emit_flush) (struct intel_context *intel, GLuint unused);
void (*reduced_primitive_state) (struct intel_context * intel,
GLenum rprim);
@@ -157,18 +168,7 @@ struct intel_context
void (*debug_batch)(struct intel_context *intel);
} vtbl;
- struct {
- struct gl_fragment_program *bitmap_fp;
- struct gl_vertex_program *passthrough_vp;
-
- struct gl_fragment_program *saved_fp;
- GLboolean saved_fp_enable;
- struct gl_vertex_program *saved_vp;
- GLboolean saved_vp_enable;
-
- GLint saved_vp_x, saved_vp_y;
- GLsizei saved_vp_width, saved_vp_height;
- } meta;
+ struct dri_metaops meta;
GLint refcount;
GLuint Fallback;
@@ -188,6 +188,7 @@ struct intel_context
GLboolean ttm;
struct intel_batchbuffer *batch;
+ drm_intel_bo *first_post_swapbuffers_batch;
GLboolean no_batch_wrap;
unsigned batch_id;
@@ -209,10 +210,10 @@ struct intel_context
char *prevLockFile;
int prevLockLine;
- GLubyte clear_chan[4];
GLuint ClearColor565;
GLuint ClearColor8888;
+
/* Offsets of fields within the current vertex:
*/
GLuint coloroffset;
@@ -229,7 +230,14 @@ struct intel_context
GLboolean hw_stipple;
GLboolean depth_buffer_is_float;
GLboolean no_rast;
- GLboolean strict_conformance;
+ GLboolean always_flush_batch;
+ GLboolean always_flush_cache;
+
+ /* 0 - nonconformant, best performance;
+ * 1 - fallback to sw for known conformance bugs
+ * 2 - always fallback to sw
+ */
+ GLuint conformance_mode;
/* State for intelvb.c and inteltris.c.
*/
@@ -255,11 +263,40 @@ struct intel_context
* flush time while the lock is held.
*/
GLboolean constant_cliprect;
+
/**
* In !constant_cliprect mode, set to true if the front cliprects should be
* used instead of back.
*/
GLboolean front_cliprects;
+
+ /**
+ * Set if rendering has occured to the drawable's front buffer.
+ *
+ * This is used in the DRI2 case to detect that glFlush should also copy
+ * the contents of the fake front buffer to the real front buffer.
+ */
+ GLboolean front_buffer_dirty;
+
+ /**
+ * Track whether front-buffer rendering is currently enabled
+ *
+ * A separate flag is used to track this in order to support MRT more
+ * easily.
+ */
+ GLboolean is_front_buffer_rendering;
+ /**
+ * Track whether front-buffer is the current read target.
+ *
+ * This is closely associated with is_front_buffer_rendering, but may
+ * be set separately. The DRI2 fake front buffer must be referenced
+ * either way.
+ */
+ GLboolean is_front_buffer_reading;
+
+ GLboolean use_texture_tiling;
+ GLboolean use_early_z;
+
drm_clip_rect_t fboRect; /**< cliprect for FBO rendering */
int perf_boxes;
@@ -281,7 +318,7 @@ struct intel_context
__DRIdrawablePrivate *driReadDrawable;
__DRIscreenPrivate *driScreen;
intelScreenPrivate *intelScreen;
- volatile struct drm_i915_sarea *sarea;
+ volatile drm_i915_sarea_t *sarea;
GLuint lastStamp;
@@ -312,6 +349,7 @@ extern char *__progname;
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#define ALIGN(value, alignment) ((value + alignment - 1) & ~(alignment - 1))
+#define IS_POWER_OF_TWO(val) (((val) & (val - 1)) == 0)
#define INTEL_FIREVERTICES(intel) \
do { \
@@ -437,7 +475,8 @@ extern void intelFinish(GLcontext * ctx);
extern void intelFlush(GLcontext * ctx);
extern void intelInitDriverFunctions(struct dd_function_table *functions);
-extern void intelInitExtensions(GLcontext *ctx, GLboolean enable_imaging);
+
+void intel_init_syncobj_functions(struct dd_function_table *functions);
/* ================================================================
@@ -514,6 +553,9 @@ void intel_viewport(GLcontext * ctx, GLint x, GLint y,
void intel_update_renderbuffers(__DRIcontext *context,
__DRIdrawable *drawable);
+void i915_set_buf_info_for_region(uint32_t *state, struct intel_region *region,
+ uint32_t buffer_id);
+
/*======================================================================
* Inline conversion functions.
* These are better-typed than the macros used previously:
@@ -524,4 +566,10 @@ intel_context(GLcontext * ctx)
return (struct intel_context *) ctx;
}
+static INLINE GLboolean
+is_power_of_two(uint32_t value)
+{
+ return (value & (value - 1)) == 0;
+}
+
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_decode.c b/src/mesa/drivers/dri/intel/intel_decode.c
index 5f90ca22ec..a9dfe281cb 100644
--- a/src/mesa/drivers/dri/intel/intel_decode.c
+++ b/src/mesa/drivers/dri/intel/intel_decode.c
@@ -87,27 +87,28 @@ decode_mi(uint32_t *data, int count, uint32_t hw_offset, int *failures)
struct {
uint32_t opcode;
+ int len_mask;
int min_len;
int max_len;
char *name;
} opcodes_mi[] = {
- { 0x08, 1, 1, "MI_ARB_ON_OFF" },
- { 0x0a, 1, 1, "MI_BATCH_BUFFER_END" },
- { 0x31, 2, 2, "MI_BATCH_BUFFER_START" },
- { 0x14, 3, 3, "MI_DISPLAY_BUFFER_INFO" },
- { 0x04, 1, 1, "MI_FLUSH" },
- { 0x22, 3, 3, "MI_LOAD_REGISTER_IMM" },
- { 0x13, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" },
- { 0x12, 2, 2, "MI_LOAD_SCAN_LINES_INCL" },
- { 0x00, 1, 1, "MI_NOOP" },
- { 0x11, 2, 2, "MI_OVERLAY_FLIP" },
- { 0x07, 1, 1, "MI_REPORT_HEAD" },
- { 0x18, 2, 2, "MI_SET_CONTEXT" },
- { 0x20, 3, 4, "MI_STORE_DATA_IMM" },
- { 0x21, 3, 4, "MI_STORE_DATA_INDEX" },
- { 0x24, 3, 3, "MI_STORE_REGISTER_MEM" },
- { 0x02, 1, 1, "MI_USER_INTERRUPT" },
- { 0x03, 1, 1, "MI_WAIT_FOR_EVENT" },
+ { 0x08, 0, 1, 1, "MI_ARB_ON_OFF" },
+ { 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" },
+ { 0x31, 0x3f, 2, 2, "MI_BATCH_BUFFER_START" },
+ { 0x14, 0x3f, 3, 3, "MI_DISPLAY_BUFFER_INFO" },
+ { 0x04, 0, 1, 1, "MI_FLUSH" },
+ { 0x22, 0, 3, 3, "MI_LOAD_REGISTER_IMM" },
+ { 0x13, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" },
+ { 0x12, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_INCL" },
+ { 0x00, 0, 1, 1, "MI_NOOP" },
+ { 0x11, 0x3f, 2, 2, "MI_OVERLAY_FLIP" },
+ { 0x07, 0, 1, 1, "MI_REPORT_HEAD" },
+ { 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT" },
+ { 0x20, 0x3f, 3, 4, "MI_STORE_DATA_IMM" },
+ { 0x21, 0x3f, 3, 4, "MI_STORE_DATA_INDEX" },
+ { 0x24, 0x3f, 3, 3, "MI_STORE_REGISTER_MEM" },
+ { 0x02, 0, 1, 1, "MI_USER_INTERRUPT" },
+ { 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT" },
};
@@ -118,12 +119,14 @@ decode_mi(uint32_t *data, int count, uint32_t hw_offset, int *failures)
instr_out(data, hw_offset, 0, "%s\n", opcodes_mi[opcode].name);
if (opcodes_mi[opcode].max_len > 1) {
- len = (data[0] & 0x000000ff) + 2;
+ len = (data[0] & opcodes_mi[opcode].len_mask) + 2;
if (len < opcodes_mi[opcode].min_len ||
len > opcodes_mi[opcode].max_len)
{
- fprintf(out, "Bad length in %s\n",
- opcodes_mi[opcode].name);
+ fprintf(out, "Bad length (%d) in %s, [%d, %d]\n",
+ len, opcodes_mi[opcode].name,
+ opcodes_mi[opcode].min_len,
+ opcodes_mi[opcode].max_len);
}
}
@@ -797,6 +800,7 @@ static int
decode_3d_1d(uint32_t *data, int count, uint32_t hw_offset, int *failures, int i830)
{
unsigned int len, i, c, opcode, word, map, sampler, instr;
+ char *format;
struct {
uint32_t opcode;
@@ -932,7 +936,7 @@ decode_3d_1d(uint32_t *data, int count, uint32_t hw_offset, int *failures, int i
instr_out(data, hw_offset, 0, "3DSTATE_PIXEL_SHADER_CONSTANTS\n");
len = (data[0] & 0x000000ff) + 2;
- i = 1;
+ i = 2;
for (c = 0; c <= 31; c++) {
if (data[1] & (1 << c)) {
if (i + 4 >= count)
@@ -952,7 +956,7 @@ decode_3d_1d(uint32_t *data, int count, uint32_t hw_offset, int *failures, int i
}
}
if (len != i) {
- fprintf(out, "Bad count in 3DSTATE_MAP_STATE\n");
+ fprintf(out, "Bad count in 3DSTATE_PIXEL_SHADER_CONSTANTS\n");
(*failures)++;
}
return len;
@@ -998,6 +1002,35 @@ decode_3d_1d(uint32_t *data, int count, uint32_t hw_offset, int *failures, int i
(*failures)++;
}
return len;
+ case 0x85:
+ len = (data[0] & 0x0000000f) + 2;
+
+ if (len != 2)
+ fprintf(out, "Bad count in 3DSTATE_DEST_BUFFER_VARIABLES\n");
+ if (count < 2)
+ BUFFER_FAIL(count, len, "3DSTATE_DEST_BUFFER_VARIABLES");
+
+ instr_out(data, hw_offset, 0,
+ "3DSTATE_DEST_BUFFER_VARIABLES\n");
+
+ switch ((data[1] >> 8) & 0xf) {
+ case 0x0: format = "g8"; break;
+ case 0x1: format = "x1r5g5b5"; break;
+ case 0x2: format = "r5g6b5"; break;
+ case 0x3: format = "a8r8g8b8"; break;
+ case 0x4: format = "ycrcb_swapy"; break;
+ case 0x5: format = "ycrcb_normal"; break;
+ case 0x6: format = "ycrcb_swapuv"; break;
+ case 0x7: format = "ycrcb_swapuvy"; break;
+ case 0x8: format = "a4r4g4b4"; break;
+ case 0x9: format = "a1r5g5b5"; break;
+ case 0xa: format = "a2r10g10b10"; break;
+ default: format = "BAD"; break;
+ }
+ instr_out(data, hw_offset, 1, "%s format, early Z %sabled\n",
+ format,
+ (data[1] & (1 << 31)) ? "en" : "dis");
+ return len;
}
for (opcode = 0; opcode < sizeof(opcodes_3d_1d) / sizeof(opcodes_3d_1d[0]);
@@ -1510,7 +1543,7 @@ decode_3d_965(uint32_t *data, int count, uint32_t hw_offset, int *failures)
for (i = 1; i < len;) {
instr_out(data, hw_offset, i, "buffer %d: %svalid, type 0x%04x, "
- "src offset 0x%04xd bytes\n",
+ "src offset 0x%04x bytes\n",
data[i] >> 27,
data[i] & (1 << 26) ? "" : "in",
(data[i] >> 16) & 0x1ff,
@@ -1592,7 +1625,7 @@ decode_3d_965(uint32_t *data, int count, uint32_t hw_offset, int *failures)
"3DPRIMITIVE: %s %s\n",
get_965_prim_type(data[0]),
(data[0] & (1 << 15)) ? "random" : "sequential");
- instr_out(data, hw_offset, 1, "primitive count\n");
+ instr_out(data, hw_offset, 1, "vertex count\n");
instr_out(data, hw_offset, 2, "start vertex\n");
instr_out(data, hw_offset, 3, "instance count\n");
instr_out(data, hw_offset, 4, "start instance\n");
diff --git a/src/mesa/drivers/dri/intel/intel_depthstencil.c b/src/mesa/drivers/dri/intel/intel_depthstencil.c
deleted file mode 100644
index 354b3bf0d7..0000000000
--- a/src/mesa/drivers/dri/intel/intel_depthstencil.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/depthstencil.h"
-#include "main/fbobject.h"
-#include "main/framebuffer.h"
-#include "main/hash.h"
-#include "main/mtypes.h"
-#include "main/renderbuffer.h"
-
-#include "intel_context.h"
-#include "intel_fbo.h"
-#include "intel_depthstencil.h"
-#include "intel_regions.h"
-#include "intel_span.h"
-
-/**
- * The GL_EXT_framebuffer_object allows the user to create their own
- * framebuffer objects consisting of color renderbuffers (0 or more),
- * depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1).
- *
- * The spec considers depth and stencil renderbuffers to be totally independent
- * buffers. In reality, most graphics hardware today uses a combined
- * depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil).
- *
- * This causes difficulty because the user may create some number of depth
- * renderbuffers and some number of stencil renderbuffers and bind them
- * together in framebuffers in any combination.
- *
- * This code manages all that.
- *
- * 1. Depth renderbuffers are always allocated in hardware as 32bpp
- * GL_DEPTH24_STENCIL8 buffers.
- *
- * 2. Stencil renderbuffers are initially allocated in software as 8bpp
- * GL_STENCIL_INDEX8 buffers.
- *
- * 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth
- * fields (respectively) to indicate if the buffer's currently paired
- * with another stencil or depth buffer (respectively).
- *
- * 4. When a depth and stencil buffer are initially both attached to the
- * current framebuffer, we merge the stencil buffer values into the
- * depth buffer (really a depth+stencil buffer). The then hardware uses
- * the combined buffer.
- *
- * 5. Whenever a depth or stencil buffer is reallocated (with
- * glRenderbufferStorage) we undo the pairing and copy the stencil values
- * from the combined depth/stencil buffer back to the stencil-only buffer.
- *
- * 6. We also undo the pairing when we find a change in buffer bindings.
- *
- * 7. If a framebuffer is only using a depth renderbuffer (no stencil), we
- * just use the combined depth/stencil buffer and ignore the stencil values.
- *
- * 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have
- * to promote the 8bpp software stencil buffer to a 32bpp hardware
- * depth+stencil buffer.
- *
- */
-
-/**
- * Undo the pairing/interleaving between depth and stencil buffers.
- * irb should be a depth/stencil or stencil renderbuffer.
- */
-void
-intel_unpair_depth_stencil(GLcontext *ctx, struct intel_renderbuffer *irb)
-{
- struct intel_context *intel = intel_context(ctx);
- struct gl_renderbuffer *rb = &irb->Base;
-
- if (irb->PairedStencil) {
- /* irb is a depth/stencil buffer */
- struct gl_renderbuffer *stencilRb;
- struct intel_renderbuffer *stencilIrb;
-
- ASSERT(rb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
-
- stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil);
- stencilIrb = intel_renderbuffer(stencilRb);
- if (stencilIrb) {
- /* need to extract stencil values from the depth buffer */
- ASSERT(stencilIrb->PairedDepth == rb->Name);
- intel_renderbuffer_map(intel, rb);
- intel_renderbuffer_map(intel, stencilRb);
-#if 0
- /* disable for now */
- _mesa_extract_stencil(ctx, rb, stencilRb);
-#endif
- intel_renderbuffer_unmap(intel, stencilRb);
- intel_renderbuffer_unmap(intel, rb);
- stencilIrb->PairedDepth = 0;
- }
- irb->PairedStencil = 0;
- }
- else if (irb->PairedDepth) {
- /* irb is a stencil buffer */
- struct gl_renderbuffer *depthRb;
- struct intel_renderbuffer *depthIrb;
-
- ASSERT(rb->_ActualFormat == GL_STENCIL_INDEX8_EXT ||
- rb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
-
- depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth);
- depthIrb = intel_renderbuffer(depthRb);
- if (depthIrb) {
- /* need to extract stencil values from the depth buffer */
- ASSERT(depthIrb->PairedStencil == rb->Name);
- intel_renderbuffer_map(intel, rb);
- intel_renderbuffer_map(intel, depthRb);
-#if 0
- /* disable for now */
- _mesa_extract_stencil(ctx, depthRb, rb);
-#endif
- intel_renderbuffer_unmap(intel, depthRb);
- intel_renderbuffer_unmap(intel, rb);
- depthIrb->PairedStencil = 0;
- }
- irb->PairedDepth = 0;
- }
- else {
- _mesa_problem(ctx, "Problem in undo_depth_stencil_pairing");
- }
-
- ASSERT(irb->PairedStencil == 0);
- ASSERT(irb->PairedDepth == 0);
-}
-
-
-/**
- * Examine the depth and stencil renderbuffers which are attached to the
- * framebuffer. If both depth and stencil are attached, make sure that the
- * renderbuffers are 'paired' (combined). If only depth or only stencil is
- * attached, undo any previous pairing.
- *
- * Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments
- * change, for example).
- */
-void
-intel_validate_paired_depth_stencil(GLcontext * ctx,
- struct gl_framebuffer *fb)
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_renderbuffer *depthRb, *stencilRb;
-
- depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
- stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
-
- if (depthRb && stencilRb) {
- if (depthRb == stencilRb) {
- /* Using a user-created combined depth/stencil buffer.
- * Nothing to do.
- */
- ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT);
- ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
- }
- else {
- /* Separate depth/stencil buffers, need to interleave now */
- ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT ||
- depthRb->Base._BaseFormat == GL_DEPTH_STENCIL);
- ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX ||
- stencilRb->Base._BaseFormat == GL_DEPTH_STENCIL);
-
- /* may need to interleave depth/stencil now */
- if (depthRb->PairedStencil == stencilRb->Base.Name) {
- /* OK, the depth and stencil buffers are already interleaved */
- ASSERT(stencilRb->PairedDepth == depthRb->Base.Name);
- }
- else {
- /* need to setup new pairing/interleaving */
- if (depthRb->PairedStencil) {
- intel_unpair_depth_stencil(ctx, depthRb);
- }
- if (stencilRb->PairedDepth) {
- intel_unpair_depth_stencil(ctx, stencilRb);
- }
-
- ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
- ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
- stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
-
- /* establish new pairing: interleave stencil into depth buffer */
- intel_renderbuffer_map(intel, &depthRb->Base);
- intel_renderbuffer_map(intel, &stencilRb->Base);
- _mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base);
- intel_renderbuffer_unmap(intel, &stencilRb->Base);
- intel_renderbuffer_unmap(intel, &depthRb->Base);
- depthRb->PairedStencil = stencilRb->Base.Name;
- stencilRb->PairedDepth = depthRb->Base.Name;
- }
-
- }
- }
- else if (depthRb) {
- /* Depth buffer but no stencil buffer.
- * We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits.
- */
- /* can't assert this until storage is allocated:
- ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
- */
- /* intel_undo any previous pairing */
- if (depthRb->PairedStencil) {
- intel_unpair_depth_stencil(ctx, depthRb);
- }
- }
- else if (stencilRb) {
- /* Stencil buffer but no depth buffer.
- * Since h/w doesn't typically support just 8bpp stencil w/out Z,
- * we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits.
- */
- /* undo any previous pairing */
- if (stencilRb->PairedDepth) {
- intel_unpair_depth_stencil(ctx, stencilRb);
- }
- if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) {
- /* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */
- _mesa_promote_stencil(ctx, &stencilRb->Base);
- ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
- }
- }
-
- /* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */
- _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
- if (depthRb && depthRb->PairedStencil)
- _mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH);
- else
- _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL);
-
-
- /* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer
- * first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer
- * if present.
- */
-}
diff --git a/src/mesa/drivers/dri/intel/intel_depthstencil.h b/src/mesa/drivers/dri/intel/intel_depthstencil.h
deleted file mode 100644
index 740eb0d989..0000000000
--- a/src/mesa/drivers/dri/intel/intel_depthstencil.h
+++ /dev/null
@@ -1,15 +0,0 @@
-
-#ifndef INTEL_DEPTH_STENCIL_H
-#define INTEL_DEPTH_STENCIL_H
-
-#include "intel_fbo.h"
-
-extern void
-intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb);
-
-extern void
-intel_validate_paired_depth_stencil(GLcontext * ctx,
- struct gl_framebuffer *fb);
-
-
-#endif /* INTEL_DEPTH_STENCIL_H */
diff --git a/src/mesa/drivers/dri/intel/intel_depthtmp.h b/src/mesa/drivers/dri/intel/intel_depthtmp.h
new file mode 100644
index 0000000000..16d7708453
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_depthtmp.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/**
+ * Wrapper around the depthtmp.h macrofest to generate spans code for
+ * all the tiling styles.
+ */
+
+#define VALUE_TYPE INTEL_VALUE_TYPE
+#define WRITE_DEPTH(_x, _y, d) INTEL_WRITE_DEPTH(NO_TILE(_x, _y), d)
+#define READ_DEPTH(d, _x, _y) d = INTEL_READ_DEPTH(NO_TILE(_x, _y))
+#define TAG(x) INTEL_TAG(intel##x)
+#include "depthtmp.h"
+
+#define VALUE_TYPE INTEL_VALUE_TYPE
+#define WRITE_DEPTH(_x, _y, d) INTEL_WRITE_DEPTH(X_TILE(_x, _y), d)
+#define READ_DEPTH(d, _x, _y) d = INTEL_READ_DEPTH(X_TILE(_x, _y))
+#define TAG(x) INTEL_TAG(intel_XTile_##x)
+#include "depthtmp.h"
+
+#define VALUE_TYPE INTEL_VALUE_TYPE
+#define WRITE_DEPTH(_x, _y, d) INTEL_WRITE_DEPTH(Y_TILE(_x, _y), d)
+#define READ_DEPTH(d, _x, _y) d = INTEL_READ_DEPTH(Y_TILE(_x, _y))
+#define TAG(x) INTEL_TAG(intel_YTile_##x)
+#include "depthtmp.h"
+
+#undef INTEL_VALUE_TYPE
+#undef INTEL_WRITE_DEPTH
+#undef INTEL_READ_DEPTH
+#undef INTEL_TAG
diff --git a/src/mesa/drivers/dri/intel/intel_eglimage.c b/src/mesa/drivers/dri/intel/intel_eglimage.c
new file mode 100644
index 0000000000..fed8675c26
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_eglimage.c
@@ -0,0 +1,139 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL 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/mtypes.h"
+#include "main/teximage.h"
+
+#include "intel_context.h"
+#include "intel_fbo.h"
+#include "intel_tex.h"
+
+#include "intel_eglimage.h"
+#include "main/eglimage.h"
+
+#include "EGL/internal/eglimage_dri.h"
+
+
+#if FEATURE_OES_EGL_image
+
+
+/* move to intel_fbo.c */
+static void
+copy_renderbuffer(struct intel_renderbuffer *dst,
+ struct intel_renderbuffer *src)
+{
+ dst->Base.Width = src->Base.Width;
+ dst->Base.Height = src->Base.Height;
+ dst->Base.InternalFormat = src->Base.InternalFormat;
+ dst->Base._ActualFormat = src->Base._ActualFormat;
+ dst->Base._BaseFormat = src->Base._BaseFormat;
+
+ dst->Base.ColorEncoding = src->Base.ColorEncoding;
+ dst->Base.ComponentType = src->Base.ComponentType;
+
+ dst->Base.RedBits = src->Base.RedBits;
+ dst->Base.GreenBits = src->Base.GreenBits;
+ dst->Base.BlueBits = src->Base.BlueBits;
+ dst->Base.AlphaBits = src->Base.AlphaBits;
+ dst->Base.IndexBits = src->Base.IndexBits;
+ dst->Base.DepthBits = src->Base.DepthBits;
+ dst->Base.StencilBits = src->Base.StencilBits;
+ dst->Base.NumSamples = src->Base.NumSamples;
+
+ dst->Base.DataType = src->Base.DataType;
+
+ intel_renderbuffer_set_region(dst, src->region);
+}
+
+static __DRIEGLImage *
+get_image(GLcontext *ctx, GLeglImageOES image)
+{
+ __DRIEGLImage *driImage;
+
+ driImage = _eglClientGetImageData((__DRIEGLImageHandle) image);
+ if (!driImage || driImage->magic != __DRI_EGL_IMAGE_MAGIC) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glEGLImageTargetTexture2DOES(image=0x%x)", image);
+ return NULL;
+ }
+
+ return driImage;
+}
+
+void
+intelEGLImageTargetRenderbufferStorage(GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLeglImageOES image)
+{
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+ __DRIEGLImage *driImage;
+ struct intel_framebuffer *image_fb;
+ struct intel_renderbuffer *image_rb;
+
+ driImage = get_image(ctx, image);
+ if (!driImage)
+ return;
+
+ image_fb = driImage->drawable->driverPrivate;
+ image_rb = image_fb->color_rb[0];
+
+ copy_renderbuffer(irb, image_rb);
+}
+
+
+void
+intelEGLImageTargetTexture2D(GLcontext *ctx,
+ struct gl_texture_object *texObj,
+ GLeglImageOES image)
+{
+ struct intel_context *intel = intel_context(ctx);
+ __DRIEGLImage *driImage;
+ GLint glx_texture_format;
+
+ driImage = get_image(ctx, image);
+ if (!driImage)
+ return;
+
+ /* only level == 0 is supported */
+ if (driImage->level) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glEGLImageTargetTexture2DOES(level=%d)", driImage->level);
+ return;
+ }
+
+ glx_texture_format = (driImage->texture_format_rgba)
+ ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT;
+
+ /* TODO refactor intelSetTexBuffer2 to avoid lock... */
+ _mesa_unlock_texture(ctx, texObj);
+ intelSetTexBuffer2(intel->driContext, texObj->Target, glx_texture_format,
+ driImage->drawable);
+ _mesa_lock_texture(ctx, texObj);
+}
+
+
+#endif /* FEATURE_OES_EGL_image */
diff --git a/src/mesa/drivers/dri/intel/intel_eglimage.h b/src/mesa/drivers/dri/intel/intel_eglimage.h
new file mode 100644
index 0000000000..ef1bf2eacd
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_eglimage.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL 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 INTEL_EGLIMAGE_H
+#define INTEL_EGLIMAGE_H
+
+#include "main/mtypes.h"
+
+/* main/eglimage.h might not exist */
+#if FEATURE_OES_EGL_image
+
+#ifndef GL_OES_EGL_image
+typedef void *GLeglImageOES;
+#endif
+
+#include "main/eglimage.h"
+
+extern void
+intelEGLImageTargetRenderbufferStorage(GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLeglImageOES image);
+
+extern void
+intelEGLImageTargetTexture2D(GLcontext *ctx,
+ struct gl_texture_object *texObj,
+ GLeglImageOES image);
+
+#else
+#define _MESA_INIT_EGLIMAGE_FUNCTIONS(driver, impl) do { } while (0)
+#endif /* FEATURE_OES_EGL_image */
+
+static INLINE void
+intelInitEGLImageFuncs(struct dd_function_table *functions)
+{
+ _MESA_INIT_EGLIMAGE_FUNCTIONS(functions, intel);
+}
+
+#endif /* INTEL_EGLIMAGE_H */
diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c
new file mode 100644
index 0000000000..21af22fbfb
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_extensions.c
@@ -0,0 +1,213 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "intel_chipset.h"
+#include "intel_context.h"
+#include "intel_extensions.h"
+
+
+#define need_GL_ARB_copy_buffer
+#define need_GL_ARB_draw_elements_base_vertex
+#define need_GL_ARB_framebuffer_object
+#define need_GL_ARB_map_buffer_range
+#define need_GL_ARB_occlusion_query
+#define need_GL_ARB_point_parameters
+#define need_GL_ARB_shader_objects
+#define need_GL_ARB_sync
+#define need_GL_ARB_vertex_array_object
+#define need_GL_ARB_vertex_program
+#define need_GL_ARB_vertex_shader
+#define need_GL_ARB_window_pos
+#define need_GL_EXT_blend_color
+#define need_GL_EXT_blend_equation_separate
+#define need_GL_EXT_blend_func_separate
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_cull_vertex
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_framebuffer_blit
+#define need_GL_EXT_gpu_program_parameters
+#define need_GL_EXT_point_parameters
+#define need_GL_EXT_provoking_vertex
+#define need_GL_EXT_secondary_color
+#define need_GL_EXT_stencil_two_side
+#define need_GL_APPLE_vertex_array_object
+#define need_GL_ATI_separate_stencil
+#define need_GL_ATI_envmap_bumpmap
+#define need_GL_NV_point_sprite
+#define need_GL_NV_vertex_program
+#define need_GL_VERSION_2_0
+#define need_GL_VERSION_2_1
+
+#include "extension_helper.h"
+
+
+/**
+ * Extension strings exported by the intel driver.
+ *
+ * Extensions supported by all chips supported by i830_dri, i915_dri, or
+ * i965_dri.
+ */
+static const struct dri_extension card_extensions[] = {
+ { "GL_ARB_copy_buffer", GL_ARB_copy_buffer_functions },
+ { "GL_ARB_draw_elements_base_vertex", GL_ARB_draw_elements_base_vertex_functions },
+ { "GL_ARB_half_float_pixel", NULL },
+ { "GL_ARB_map_buffer_range", GL_ARB_map_buffer_range_functions },
+ { "GL_ARB_multitexture", NULL },
+ { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
+ { "GL_ARB_point_sprite", NULL },
+ { "GL_ARB_sync", GL_ARB_sync_functions },
+ { "GL_ARB_texture_border_clamp", NULL },
+ { "GL_ARB_texture_cube_map", NULL },
+ { "GL_ARB_texture_env_add", NULL },
+ { "GL_ARB_texture_env_combine", NULL },
+ { "GL_ARB_texture_env_crossbar", NULL },
+ { "GL_ARB_texture_env_dot3", NULL },
+ { "GL_ARB_texture_mirrored_repeat", NULL },
+ { "GL_ARB_texture_rectangle", NULL },
+ { "GL_ARB_vertex_array_object", GL_ARB_vertex_array_object_functions},
+ { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
+ { "GL_ARB_window_pos", GL_ARB_window_pos_functions },
+ { "GL_EXT_blend_color", GL_EXT_blend_color_functions },
+ { "GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions },
+ { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions },
+ { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions },
+ { "GL_EXT_blend_logic_op", NULL },
+ { "GL_EXT_blend_subtract", NULL },
+ { "GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions },
+ { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
+ { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
+ { "GL_EXT_packed_depth_stencil", NULL },
+ { "GL_EXT_provoking_vertex", GL_EXT_provoking_vertex_functions },
+ { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
+ { "GL_EXT_stencil_wrap", NULL },
+ { "GL_EXT_texture_edge_clamp", NULL },
+ { "GL_EXT_texture_env_combine", NULL },
+ { "GL_EXT_texture_env_dot3", NULL },
+ { "GL_EXT_texture_filter_anisotropic", NULL },
+ { "GL_EXT_texture_lod_bias", NULL },
+ { "GL_3DFX_texture_compression_FXT1", NULL },
+ { "GL_APPLE_client_storage", NULL },
+ { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions},
+ { "GL_MESA_pack_invert", NULL },
+ { "GL_MESA_ycbcr_texture", NULL },
+ { "GL_NV_blend_square", NULL },
+ { "GL_NV_point_sprite", GL_NV_point_sprite_functions },
+ { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
+ { "GL_NV_vertex_program1_1", NULL },
+ { "GL_SGIS_generate_mipmap", NULL },
+ { NULL, NULL }
+};
+
+
+/** i915 / i945-only extensions */
+static const struct dri_extension i915_extensions[] = {
+ { "GL_ARB_depth_texture", NULL },
+ { "GL_ARB_fragment_program", NULL },
+ { "GL_ARB_shadow", NULL },
+ { "GL_ARB_texture_non_power_of_two", NULL },
+ { "GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions },
+ { "GL_ATI_texture_env_combine3", NULL },
+ { "GL_EXT_shadow_funcs", NULL },
+ { "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions },
+ { "GL_NV_texture_env_combine4", NULL },
+ { NULL, NULL }
+};
+
+
+/** i965-only extensions */
+static const struct dri_extension brw_extensions[] = {
+ { "GL_ARB_depth_clamp", NULL },
+ { "GL_ARB_depth_texture", NULL },
+ { "GL_ARB_fragment_program", NULL },
+ { "GL_ARB_fragment_program_shadow", NULL },
+ { "GL_ARB_fragment_shader", NULL },
+ { "GL_ARB_framebuffer_object", GL_ARB_framebuffer_object_functions},
+ { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions },
+ { "GL_ARB_point_sprite", NULL },
+ { "GL_ARB_seamless_cube_map", NULL },
+ { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
+ { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions },
+ { "GL_ARB_shading_language_120", GL_VERSION_2_1_functions },
+ { "GL_ARB_shadow", NULL },
+ { "GL_MESA_texture_signed_rgba", NULL },
+ { "GL_ARB_texture_non_power_of_two", NULL },
+ { "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions },
+ { "GL_EXT_shadow_funcs", NULL },
+ { "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions },
+ { "GL_EXT_texture_sRGB", NULL },
+ { "GL_EXT_texture_swizzle", NULL },
+ { "GL_EXT_vertex_array_bgra", NULL },
+ { "GL_ATI_envmap_bumpmap", GL_ATI_envmap_bumpmap_functions },
+ { "GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions },
+ { "GL_ATI_texture_env_combine3", NULL },
+ { "GL_NV_texture_env_combine4", NULL },
+ { NULL, NULL }
+};
+
+
+static const struct dri_extension arb_oq_extensions[] = {
+ { NULL, NULL }
+};
+
+
+static const struct dri_extension ttm_extensions[] = {
+ { "GL_ARB_pixel_buffer_object", NULL },
+ { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
+ { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+#if FEATURE_OES_EGL_image
+ { "GL_OES_EGL_image", NULL },
+#endif
+ { NULL, NULL }
+};
+
+
+/**
+ * Initializes potential list of extensions if ctx == NULL, or actually enables
+ * extensions for a context.
+ */
+void
+intelInitExtensions(GLcontext *ctx, GLboolean enable_imaging)
+{
+ struct intel_context *intel = ctx?intel_context(ctx):NULL;
+
+ /* Disable imaging extension until convolution is working in teximage paths.
+ */
+ enable_imaging = GL_FALSE;
+
+ driInitExtensions(ctx, card_extensions, enable_imaging);
+
+ if (intel == NULL || intel->ttm)
+ driInitExtensions(ctx, ttm_extensions, GL_FALSE);
+
+ if (intel == NULL || IS_965(intel->intelScreen->deviceID))
+ driInitExtensions(ctx, brw_extensions, GL_FALSE);
+
+ if (intel == NULL || IS_915(intel->intelScreen->deviceID)
+ || IS_945(intel->intelScreen->deviceID))
+ driInitExtensions(ctx, i915_extensions, GL_FALSE);
+}
diff --git a/src/mesa/drivers/dri/intel/intel_extensions.h b/src/mesa/drivers/dri/intel/intel_extensions.h
new file mode 100644
index 0000000000..97147ecdb0
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_extensions.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef INTEL_EXTENSIONS_H
+#define INTEL_EXTENSIONS_H
+
+
+extern void
+intelInitExtensions(GLcontext *ctx, GLboolean enable_imaging);
+
+
+#endif
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 7cf12619d6..084095fc96 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -27,6 +27,7 @@
#include "main/imports.h"
+#include "main/macros.h"
#include "main/mtypes.h"
#include "main/fbobject.h"
#include "main/framebuffer.h"
@@ -34,61 +35,17 @@
#include "main/context.h"
#include "main/texformat.h"
#include "main/texrender.h"
+#include "drivers/common/meta.h"
#include "intel_context.h"
#include "intel_buffers.h"
-#include "intel_depthstencil.h"
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
-#include "intel_span.h"
#define FILE_DEBUG_FLAG DEBUG_FBO
-#define INTEL_RB_CLASS 0x12345678
-
-
-/* XXX FBO: move this to intel_context.h (inlined) */
-/**
- * Return a gl_renderbuffer ptr casted to intel_renderbuffer.
- * NULL will be returned if the rb isn't really an intel_renderbuffer.
- * This is determiend by checking the ClassID.
- */
-struct intel_renderbuffer *
-intel_renderbuffer(struct gl_renderbuffer *rb)
-{
- struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
- if (irb && irb->Base.ClassID == INTEL_RB_CLASS) {
- /*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
- return irb;
- }
- else
- return NULL;
-}
-
-
-struct intel_renderbuffer *
-intel_get_renderbuffer(struct gl_framebuffer *fb, int attIndex)
-{
- if (attIndex >= 0)
- return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
- else
- return NULL;
-}
-
-struct intel_region *
-intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
-{
- struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
-
- if (irb)
- return irb->region;
- else
- return NULL;
-}
-
-
/**
* Create a new framebuffer object.
@@ -103,6 +60,7 @@ intel_new_framebuffer(GLcontext * ctx, GLuint name)
}
+/** Called by gl_renderbuffer::Delete() */
static void
intel_delete_renderbuffer(struct gl_renderbuffer *rb)
{
@@ -112,10 +70,6 @@ intel_delete_renderbuffer(struct gl_renderbuffer *rb)
ASSERT(irb);
- if (irb->PairedStencil || irb->PairedDepth) {
- intel_unpair_depth_stencil(ctx, irb);
- }
-
if (irb->span_cache != NULL)
_mesa_free(irb->span_cache);
@@ -127,7 +81,6 @@ intel_delete_renderbuffer(struct gl_renderbuffer *rb)
}
-
/**
* Return a pointer to a specific pixel in a renderbuffer.
*/
@@ -142,7 +95,6 @@ intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
}
-
/**
* Called via glRenderbufferStorageEXT() to set the format and allocate
* storage for a user-created renderbuffer.
@@ -168,6 +120,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->RedBits = 5;
rb->GreenBits = 6;
rb->BlueBits = 5;
+ irb->texformat = &_mesa_texformat_rgb565;
cpp = 2;
break;
case GL_RGB:
@@ -181,6 +134,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->GreenBits = 8;
rb->BlueBits = 8;
rb->AlphaBits = 0;
+ irb->texformat = &_mesa_texformat_argb8888; /* XXX: Need xrgb8888 */
cpp = 4;
break;
case GL_RGBA:
@@ -197,6 +151,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->GreenBits = 8;
rb->BlueBits = 8;
rb->AlphaBits = 8;
+ irb->texformat = &_mesa_texformat_argb8888;
cpp = 4;
break;
case GL_STENCIL_INDEX:
@@ -209,20 +164,15 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->StencilBits = 8;
cpp = 4;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
case GL_DEPTH_COMPONENT16:
-#if 0
rb->_ActualFormat = GL_DEPTH_COMPONENT16;
rb->DataType = GL_UNSIGNED_SHORT;
rb->DepthBits = 16;
cpp = 2;
+ irb->texformat = &_mesa_texformat_z16;
break;
-#else
- /* fall-through.
- * 16bpp depth renderbuffer can't be paired with a stencil buffer so
- * always used combined depth/stencil format.
- */
-#endif
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
@@ -230,6 +180,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->DepthBits = 24;
cpp = 4;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
case GL_DEPTH_STENCIL_EXT:
case GL_DEPTH24_STENCIL8_EXT:
@@ -238,6 +189,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->DepthBits = 24;
rb->StencilBits = 8;
cpp = 4;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
default:
_mesa_problem(ctx,
@@ -266,7 +218,9 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width,
height, pitch);
- irb->region = intel_region_alloc(intel, cpp, width, height, pitch);
+ irb->region = intel_region_alloc(intel, I915_TILING_NONE,
+ cpp, width, height, pitch,
+ GL_TRUE);
if (!irb->region)
return GL_FALSE; /* out of memory? */
@@ -280,7 +234,6 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
}
-
/**
* Called for each hardware renderbuffer when a _window_ is resized.
* Just update fields.
@@ -298,6 +251,7 @@ intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
return GL_TRUE;
}
+
static void
intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint width, GLuint height)
@@ -324,6 +278,8 @@ intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
}
}
+
+/** Dummy function for gl_renderbuffer::AllocStorage() */
static GLboolean
intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
@@ -343,10 +299,9 @@ intel_renderbuffer_set_region(struct intel_renderbuffer *rb,
rb->region = NULL;
intel_region_reference(&rb->region, region);
intel_region_release(&old);
-
- rb->pfPitch = region->pitch;
}
+
/**
* Create a new intel_renderbuffer which corresponds to an on-screen window,
* not a user-created renderbuffer.
@@ -376,6 +331,17 @@ intel_create_renderbuffer(GLenum intFormat)
irb->Base.GreenBits = 6;
irb->Base.BlueBits = 5;
irb->Base.DataType = GL_UNSIGNED_BYTE;
+ irb->texformat = &_mesa_texformat_rgb565;
+ break;
+ case GL_RGB8:
+ irb->Base._ActualFormat = GL_RGB8;
+ irb->Base._BaseFormat = GL_RGB;
+ irb->Base.RedBits = 8;
+ irb->Base.GreenBits = 8;
+ irb->Base.BlueBits = 8;
+ irb->Base.AlphaBits = 0;
+ irb->Base.DataType = GL_UNSIGNED_BYTE;
+ irb->texformat = &_mesa_texformat_argb8888; /* XXX: Need xrgb8888 */
break;
case GL_RGBA8:
irb->Base._ActualFormat = GL_RGBA8;
@@ -385,24 +351,28 @@ intel_create_renderbuffer(GLenum intFormat)
irb->Base.BlueBits = 8;
irb->Base.AlphaBits = 8;
irb->Base.DataType = GL_UNSIGNED_BYTE;
+ irb->texformat = &_mesa_texformat_argb8888;
break;
case GL_STENCIL_INDEX8_EXT:
irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT;
irb->Base._BaseFormat = GL_STENCIL_INDEX;
irb->Base.StencilBits = 8;
irb->Base.DataType = GL_UNSIGNED_BYTE;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
case GL_DEPTH_COMPONENT16:
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
irb->Base.DepthBits = 16;
irb->Base.DataType = GL_UNSIGNED_SHORT;
+ irb->texformat = &_mesa_texformat_z16;
break;
case GL_DEPTH_COMPONENT24:
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
irb->Base.DepthBits = 24;
irb->Base.DataType = GL_UNSIGNED_INT;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
case GL_DEPTH24_STENCIL8_EXT:
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
@@ -410,6 +380,7 @@ intel_create_renderbuffer(GLenum intFormat)
irb->Base.DepthBits = 24;
irb->Base.StencilBits = 8;
irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
default:
_mesa_problem(NULL,
@@ -466,9 +437,6 @@ intel_bind_framebuffer(GLcontext * ctx, GLenum target,
{
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
intel_draw_buffer(ctx, fb);
- /* Integer depth range depends on depth buffer bits */
- if (ctx->Driver.DepthRange != NULL)
- ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far);
}
else {
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
@@ -492,10 +460,13 @@ intel_framebuffer_renderbuffer(GLcontext * ctx,
intel_draw_buffer(ctx, fb);
}
+
static GLboolean
intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb,
struct gl_texture_image *texImage)
{
+ irb->texformat = texImage->TexFormat;
+
if (texImage->TexFormat == &_mesa_texformat_argb8888) {
irb->Base._ActualFormat = GL_RGBA8;
irb->Base._BaseFormat = GL_RGBA;
@@ -505,9 +476,21 @@ intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb,
else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
irb->Base._ActualFormat = GL_RGB5;
irb->Base._BaseFormat = GL_RGB;
- irb->Base.DataType = GL_UNSIGNED_SHORT;
+ irb->Base.DataType = GL_UNSIGNED_BYTE;
DBG("Render to RGB5 texture OK\n");
}
+ else if (texImage->TexFormat == &_mesa_texformat_argb1555) {
+ irb->Base._ActualFormat = GL_RGB5_A1;
+ irb->Base._BaseFormat = GL_RGBA;
+ irb->Base.DataType = GL_UNSIGNED_BYTE;
+ DBG("Render to ARGB1555 texture OK\n");
+ }
+ else if (texImage->TexFormat == &_mesa_texformat_argb4444) {
+ irb->Base._ActualFormat = GL_RGBA4;
+ irb->Base._BaseFormat = GL_RGBA;
+ irb->Base.DataType = GL_UNSIGNED_BYTE;
+ DBG("Render to ARGB4444 texture OK\n");
+ }
else if (texImage->TexFormat == &_mesa_texformat_z16) {
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
@@ -534,15 +517,15 @@ intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb,
irb->Base.BlueBits = texImage->TexFormat->BlueBits;
irb->Base.AlphaBits = texImage->TexFormat->AlphaBits;
irb->Base.DepthBits = texImage->TexFormat->DepthBits;
+ irb->Base.StencilBits = texImage->TexFormat->StencilBits;
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_nop_alloc_storage;
- irb->RenderToTexture = GL_TRUE;
-
return GL_TRUE;
}
+
/**
* When glFramebufferTexture[123]D is called this function sets up the
* gl_renderbuffer wrapper around the texture image.
@@ -551,7 +534,7 @@ intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb,
static struct intel_renderbuffer *
intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
{
- const GLuint name = ~0; /* not significant, but distinct for debugging */
+ const GLuint name = ~0; /* not significant, but distinct for debugging */
struct intel_renderbuffer *irb;
/* make an intel_renderbuffer to wrap the texture image */
@@ -594,14 +577,16 @@ intel_render_texture(GLcontext * ctx,
ASSERT(newImage);
- if (newImage->Border != 0) {
- /* Fallback on drawing to a texture with a border, which won't have a
- * miptree.
+ intel_image = intel_texture_image(newImage);
+ if (!intel_image->mt) {
+ /* Fallback on drawing to a texture that doesn't have a miptree
+ * (has a border, width/height 0, etc.)
*/
- _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
- _mesa_render_texture(ctx, fb, att);
- return;
- } else if (!irb) {
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+ _mesa_render_texture(ctx, fb, att);
+ return;
+ }
+ else if (!irb) {
irb = intel_wrap_texture(ctx, newImage);
if (irb) {
/* bind the wrapper to the attachment point */
@@ -612,7 +597,9 @@ intel_render_texture(GLcontext * ctx,
_mesa_render_texture(ctx, fb, att);
return;
}
- } if (!intel_update_wrapper(ctx, irb, newImage)) {
+ }
+
+ if (!intel_update_wrapper(ctx, irb, newImage)) {
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
_mesa_render_texture(ctx, fb, att);
return;
@@ -624,7 +611,6 @@ intel_render_texture(GLcontext * ctx,
irb->Base.RefCount);
/* point the renderbufer's region to the texture image region */
- intel_image = intel_texture_image(newImage);
if (irb->region != intel_image->mt->region) {
if (irb->region)
intel_region_release(&irb->region);
@@ -657,18 +643,59 @@ static void
intel_finish_render_texture(GLcontext * ctx,
struct gl_renderbuffer_attachment *att)
{
- struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
+ /* no-op
+ * Previously we released the renderbuffer's intel_region but
+ * that's not necessary and actually caused problems when trying
+ * to do a glRead/CopyPixels from the renderbuffer later.
+ * The region will be released later if the texture is replaced
+ * or the renderbuffer deleted.
+ *
+ * The intention of this driver hook is more of a "done rendering
+ * to texture, please re-twiddle/etc if necessary".
+ */
+}
- DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name);
- if (irb) {
- /* just release the region */
- intel_region_release(&irb->region);
+/**
+ * Do additional "completeness" testing of a framebuffer object.
+ */
+static void
+intel_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ const struct intel_renderbuffer *depthRb =
+ intel_get_renderbuffer(fb, BUFFER_DEPTH);
+ const struct intel_renderbuffer *stencilRb =
+ intel_get_renderbuffer(fb, BUFFER_STENCIL);
+ int i;
+
+ if (stencilRb && stencilRb != depthRb) {
+ /* we only support combined depth/stencil buffers, not separate
+ * stencil buffers.
+ */
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
}
- else if (att->Renderbuffer) {
- /* software fallback */
- _mesa_finish_render_texture(ctx, att);
- /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */
+
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+
+ if (rb == NULL)
+ continue;
+
+ if (irb == NULL) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ continue;
+ }
+
+ switch (irb->texformat->MesaFormat) {
+ case MESA_FORMAT_ARGB8888:
+ case MESA_FORMAT_RGB565:
+ case MESA_FORMAT_ARGB1555:
+ case MESA_FORMAT_ARGB4444:
+ break;
+ default:
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ }
}
}
@@ -687,4 +714,8 @@ intel_fbo_init(struct intel_context *intel)
intel->ctx.Driver.RenderTexture = intel_render_texture;
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
+ intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
+#if FEATURE_EXT_framebuffer_blit
+ intel->ctx.Driver.BlitFramebuffer = _mesa_meta_blit_framebuffer;
+#endif
}
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h
index b7e9280e8c..f0665af482 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.h
+++ b/src/mesa/drivers/dri/intel/intel_fbo.h
@@ -55,19 +55,13 @@ struct intel_framebuffer
/**
* Intel renderbuffer, derived from gl_renderbuffer.
- * Note: The PairedDepth and PairedStencil fields use renderbuffer IDs,
- * not pointers because in some circumstances a deleted renderbuffer could
- * result in a dangling pointer here.
*/
struct intel_renderbuffer
{
struct gl_renderbuffer Base;
struct intel_region *region;
- GLuint pfPitch; /* possibly paged flipped pitch */
- GLboolean RenderToTexture; /* RTT? */
- GLuint PairedDepth; /**< only used if this is a depth renderbuffer */
- GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */
+ const struct gl_texture_format *texformat;
GLuint vbl_pending; /**< vblank sequence number of pending flip */
@@ -75,48 +69,70 @@ struct intel_renderbuffer
unsigned long span_cache_offset;
};
-extern struct intel_renderbuffer *intel_renderbuffer(struct gl_renderbuffer
- *rb);
+
+/**
+ * gl_renderbuffer is a base class which we subclass. The Class field
+ * is used for simple run-time type checking.
+ */
+#define INTEL_RB_CLASS 0x12345678
+
+
+/**
+ * Return a gl_renderbuffer ptr casted to intel_renderbuffer.
+ * NULL will be returned if the rb isn't really an intel_renderbuffer.
+ * This is determined by checking the ClassID.
+ */
+static INLINE struct intel_renderbuffer *
+intel_renderbuffer(struct gl_renderbuffer *rb)
+{
+ struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
+ if (irb && irb->Base.ClassID == INTEL_RB_CLASS) {
+ /*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
+ return irb;
+ }
+ else
+ return NULL;
+}
+
+
+/**
+ * Return a framebuffer's renderbuffer, named by a BUFFER_x index.
+ */
+static INLINE struct intel_renderbuffer *
+intel_get_renderbuffer(struct gl_framebuffer *fb, int attIndex)
+{
+ if (attIndex >= 0)
+ return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
+ else
+ return NULL;
+}
+
extern void
intel_renderbuffer_set_region(struct intel_renderbuffer *irb,
struct intel_region *region);
+
extern struct intel_renderbuffer *
intel_create_renderbuffer(GLenum intFormat);
-extern void intel_fbo_init(struct intel_context *intel);
-
-
-/* XXX make inline or macro */
-extern struct intel_renderbuffer *intel_get_renderbuffer(struct gl_framebuffer
- *fb,
- int attIndex);
-
-extern void intel_flip_renderbuffers(struct intel_framebuffer *intel_fb);
+extern void
+intel_fbo_init(struct intel_context *intel);
-/* XXX make inline or macro */
-extern struct intel_region *intel_get_rb_region(struct gl_framebuffer *fb,
- GLuint attIndex);
+extern void
+intel_flip_renderbuffers(struct intel_framebuffer *intel_fb);
-/**
- * Are we currently rendering into a texture?
- */
-static INLINE GLboolean
-intel_rendering_to_texture(const GLcontext *ctx)
+static INLINE struct intel_region *
+intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
{
- if (ctx->DrawBuffer->Name) {
- /* User-created FBO */
- const struct intel_renderbuffer *irb =
- intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
- return irb && irb->RenderToTexture;
- }
- else {
- return GL_FALSE;
- }
+ struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
+ if (irb)
+ return irb->region;
+ else
+ return NULL;
}
diff --git a/src/mesa/drivers/dri/intel/intel_generatemipmap.c b/src/mesa/drivers/dri/intel/intel_generatemipmap.c
new file mode 100644
index 0000000000..0052abb42d
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_generatemipmap.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "main/glheader.h"
+#include "main/enums.h"
+#include "main/image.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/bufferobj.h"
+#include "main/teximage.h"
+#include "main/texenv.h"
+#include "main/texobj.h"
+#include "main/texstate.h"
+#include "main/texparam.h"
+#include "main/varray.h"
+#include "main/attrib.h"
+#include "main/enable.h"
+#include "main/buffers.h"
+#include "main/fbobject.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+#include "main/depth.h"
+#include "main/hash.h"
+#include "main/mipmap.h"
+#include "main/blend.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_batchbuffer.h"
+#include "intel_pixel.h"
+#include "intel_tex.h"
+#include "intel_mipmap_tree.h"
+
+#if FEATURE_attrib_stack
+static const char *intel_fp_tex2d =
+ "!!ARBfp1.0\n"
+ "TEX result.color, fragment.texcoord[0], texture[0], 2D;\n"
+ "END\n";
+
+static GLboolean
+intel_generate_mipmap_level(GLcontext *ctx, GLuint tex_name,
+ int level, int width, int height)
+{
+ struct intel_context *intel = intel_context(ctx);
+ GLfloat vertices[4][2];
+ GLint status;
+
+ /* Set to source from the previous level */
+ _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level - 1);
+ _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level - 1);
+
+ /* Set to draw into the current level */
+ _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D,
+ tex_name,
+ level);
+ /* Choose to render to the color attachment. */
+ _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+
+ status = _mesa_CheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ return GL_FALSE;
+
+ meta_set_passthrough_transform(&intel->meta);
+
+ /* XXX: Doing it right would involve setting up the transformation to do
+ * 0-1 mapping or something, and not changing the vertex data.
+ */
+ vertices[0][0] = 0;
+ vertices[0][1] = 0;
+ vertices[1][0] = width;
+ vertices[1][1] = 0;
+ vertices[2][0] = width;
+ vertices[2][1] = height;
+ vertices[3][0] = 0;
+ vertices[3][1] = height;
+
+ _mesa_VertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &vertices);
+ _mesa_Enable(GL_VERTEX_ARRAY);
+ meta_set_default_texrect(&intel->meta);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ meta_restore_texcoords(&intel->meta);
+ meta_restore_transform(&intel->meta);
+
+ return GL_TRUE;
+}
+
+static GLboolean
+intel_generate_mipmap_2d(GLcontext *ctx,
+ GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct intel_context *intel = intel_context(ctx);
+ GLint old_active_texture;
+ int level, max_levels, start_level, end_level;
+ GLuint fb_name;
+ GLboolean success = GL_FALSE;
+ struct gl_framebuffer *saved_fbo = NULL;
+
+ _mesa_PushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT |
+ GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT |
+ GL_DEPTH_BUFFER_BIT);
+ _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+ old_active_texture = ctx->Texture.CurrentUnit;
+ _mesa_reference_framebuffer(&saved_fbo, ctx->DrawBuffer);
+
+ _mesa_Disable(GL_POLYGON_STIPPLE);
+ _mesa_Disable(GL_DEPTH_TEST);
+ _mesa_Disable(GL_STENCIL_TEST);
+ _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ _mesa_DepthMask(GL_FALSE);
+
+ /* Bind the given texture to GL_TEXTURE_2D with linear filtering for our
+ * minification.
+ */
+ _mesa_ActiveTextureARB(GL_TEXTURE0_ARB);
+ _mesa_Enable(GL_TEXTURE_2D);
+ _mesa_BindTexture(GL_TEXTURE_2D, texObj->Name);
+ _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_NEAREST);
+ _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ /* Bind the new renderbuffer to the color attachment point. */
+ _mesa_GenFramebuffersEXT(1, &fb_name);
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_name);
+
+ meta_set_fragment_program(&intel->meta, &intel->meta.tex2d_fp,
+ intel_fp_tex2d);
+ meta_set_passthrough_vertex_program(&intel->meta);
+
+ max_levels = _mesa_max_texture_levels(ctx, texObj->Target);
+ start_level = texObj->BaseLevel;
+ end_level = texObj->MaxLevel;
+
+ /* Loop generating level+1 from level. */
+ for (level = start_level; level < end_level && level < max_levels - 1; level++) {
+ const struct gl_texture_image *srcImage;
+ int width, height;
+
+ srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (srcImage->Border != 0)
+ goto fail;
+
+ width = srcImage->Width / 2;
+ if (width < 1)
+ width = 1;
+ height = srcImage->Height / 2;
+ if (height < 1)
+ height = 1;
+
+ if (width == srcImage->Width &&
+ height == srcImage->Height) {
+ /* Neither _mesa_max_texture_levels nor texObj->MaxLevel are the
+ * maximum texture level for the object, so break out when we've gone
+ * over the edge.
+ */
+ break;
+ }
+
+ /* Make sure that there's space allocated for the target level.
+ * We could skip this if there's already space allocated and save some
+ * time.
+ */
+ _mesa_TexImage2D(GL_TEXTURE_2D, level + 1, srcImage->InternalFormat,
+ width, height, 0,
+ GL_RGBA, GL_UNSIGNED_INT, NULL);
+
+ if (!intel_generate_mipmap_level(ctx, texObj->Name, level + 1,
+ width, height))
+ goto fail;
+ }
+
+ success = GL_TRUE;
+
+fail:
+ meta_restore_fragment_program(&intel->meta);
+ meta_restore_vertex_program(&intel->meta);
+
+ _mesa_DeleteFramebuffersEXT(1, &fb_name);
+ _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + old_active_texture);
+ if (saved_fbo)
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, saved_fbo->Name);
+ _mesa_reference_framebuffer(&saved_fbo, NULL);
+ _mesa_PopClientAttrib();
+ _mesa_PopAttrib();
+
+ return success;
+}
+#endif /* FEATURE_attrib_stack */
+
+
+/**
+ * Generate new mipmap data from BASE+1 to BASE+p (the minimally-sized mipmap
+ * level).
+ *
+ * The texture object's miptree must be mapped.
+ *
+ * It would be really nice if this was just called by Mesa whenever mipmaps
+ * needed to be regenerated, rather than us having to remember to do so in
+ * each texture image modification path.
+ *
+ * This function should also include an accelerated path.
+ */
+void
+intel_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_texture_object *intelObj = intel_texture_object(texObj);
+ GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ int face, i;
+
+#if FEATURE_attrib_stack
+ /* HW path */
+ if (target == GL_TEXTURE_2D &&
+ ctx->Extensions.EXT_framebuffer_object &&
+ ctx->Extensions.ARB_fragment_program &&
+ ctx->Extensions.ARB_vertex_program) {
+ GLboolean success;
+
+ /* We'll be accessing this texture using GL entrypoints, which should
+ * be resilient against other access to this texture.
+ */
+ _mesa_unlock_texture(ctx, texObj);
+ success = intel_generate_mipmap_2d(ctx, target, texObj);
+ _mesa_lock_texture(ctx, texObj);
+
+ if (success)
+ return;
+ }
+#endif /* FEATURE_attrib_stack */
+
+ /* SW path */
+ intel_tex_map_level_images(intel, intelObj, texObj->BaseLevel);
+ _mesa_generate_mipmap(ctx, target, texObj);
+ intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel);
+
+ /* Update the level information in our private data in the new images, since
+ * it didn't get set as part of a normal TexImage path.
+ */
+ for (face = 0; face < nr_faces; face++) {
+ for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) {
+ struct intel_texture_image *intelImage;
+
+ intelImage = intel_texture_image(texObj->Image[face][i]);
+ if (intelImage == NULL)
+ break;
+
+ intelImage->level = i;
+ intelImage->face = face;
+ /* Unreference the miptree to signal that the new Data is a bare
+ * pointer from mesa.
+ */
+ intel_miptree_release(intel, &intelImage->mt);
+ }
+ }
+}
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index bf1c3f03f0..c985da5aa2 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -57,14 +57,16 @@ intel_miptree_create_internal(struct intel_context *intel,
GLuint last_level,
GLuint width0,
GLuint height0,
- GLuint depth0, GLuint cpp, GLuint compress_byte)
+ GLuint depth0, GLuint cpp, GLuint compress_byte,
+ uint32_t tiling)
{
GLboolean ok;
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
- DBG("%s target %s format %s level %d..%d\n", __FUNCTION__,
+ DBG("%s target %s format %s level %d..%d <-- %p\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
- _mesa_lookup_enum_by_nr(internal_format), first_level, last_level);
+ _mesa_lookup_enum_by_nr(internal_format),
+ first_level, last_level, mt);
mt->target = target_to_target(target);
mt->internal_format = internal_format;
@@ -80,15 +82,16 @@ intel_miptree_create_internal(struct intel_context *intel,
#ifdef I915
if (IS_945(intel->intelScreen->deviceID))
- ok = i945_miptree_layout(intel, mt);
+ ok = i945_miptree_layout(intel, mt, tiling);
else
- ok = i915_miptree_layout(intel, mt);
+ ok = i915_miptree_layout(intel, mt, tiling);
#else
- ok = brw_miptree_layout(intel, mt);
+ ok = brw_miptree_layout(intel, mt, tiling);
#endif
if (!ok) {
free(mt);
+ DBG("%s not okay - returning NULL\n", __FUNCTION__);
return NULL;
}
@@ -98,18 +101,33 @@ intel_miptree_create_internal(struct intel_context *intel,
struct intel_mipmap_tree *
intel_miptree_create(struct intel_context *intel,
GLenum target,
+ GLenum base_format,
GLenum internal_format,
GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
- GLuint depth0, GLuint cpp, GLuint compress_byte)
+ GLuint depth0, GLuint cpp, GLuint compress_byte,
+ GLboolean expect_accelerated_upload)
{
struct intel_mipmap_tree *mt;
+ uint32_t tiling;
+
+ if (intel->use_texture_tiling && compress_byte == 0 &&
+ intel->intelScreen->kernel_exec_fencing) {
+ if (IS_965(intel->intelScreen->deviceID) &&
+ (base_format == GL_DEPTH_COMPONENT ||
+ base_format == GL_DEPTH_STENCIL_EXT))
+ tiling = I915_TILING_Y;
+ else
+ tiling = I915_TILING_X;
+ } else
+ tiling = I915_TILING_NONE;
mt = intel_miptree_create_internal(intel, target, internal_format,
first_level, last_level, width0,
- height0, depth0, cpp, compress_byte);
+ height0, depth0, cpp, compress_byte,
+ tiling);
/*
* pitch == 0 || height == 0 indicates the null texture
*/
@@ -117,10 +135,12 @@ intel_miptree_create(struct intel_context *intel,
return NULL;
mt->region = intel_region_alloc(intel,
+ tiling,
mt->cpp,
mt->pitch,
mt->total_height,
- mt->pitch);
+ mt->pitch,
+ expect_accelerated_upload);
if (!mt->region) {
free(mt);
@@ -145,7 +165,8 @@ intel_miptree_create_for_region(struct intel_context *intel,
mt = intel_miptree_create_internal(intel, target, internal_format,
first_level, last_level,
region->width, region->height, 1,
- region->cpp, compress_byte);
+ region->cpp, compress_byte,
+ I915_TILING_NONE);
if (!mt)
return mt;
#if 0
@@ -183,6 +204,7 @@ intel_miptree_create_for_region(struct intel_context *intel,
int intel_miptree_pitch_align (struct intel_context *intel,
struct intel_mipmap_tree *mt,
+ uint32_t tiling,
int pitch)
{
#ifdef I915
@@ -203,6 +225,11 @@ int intel_miptree_pitch_align (struct intel_context *intel,
pitch_align = 4;
}
+ if (tiling == I915_TILING_X)
+ pitch_align = 512;
+ else if (tiling == I915_TILING_Y)
+ pitch_align = 128;
+
pitch = ALIGN(pitch * mt->cpp, pitch_align);
#ifdef I915
@@ -326,23 +353,31 @@ intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
}
-
void
-intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
- GLuint level, GLuint img,
- GLuint x, GLuint y)
+intel_miptree_set_image_offset_ex(struct intel_mipmap_tree *mt,
+ GLuint level, GLuint img,
+ GLuint x, GLuint y,
+ GLuint offset)
{
if (img == 0 && level == 0)
assert(x == 0 && y == 0);
assert(img < mt->level[level].nr_images);
- mt->level[level].image_offset[img] = (x + y * mt->pitch) * mt->cpp;
+ mt->level[level].image_offset[img] = (x + y * mt->pitch) * mt->cpp + offset;
DBG("%s level %d img %d pos %d,%d image_offset %x\n",
__FUNCTION__, level, img, x, y, mt->level[level].image_offset[img]);
}
+void
+intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
+ GLuint level, GLuint img,
+ GLuint x, GLuint y)
+{
+ intel_miptree_set_image_offset_ex(mt, level, img, x, y, 0);
+}
+
/* Although we use the image_offset[] array to store relative offsets
* to cube faces, Mesa doesn't know anything about this and expects
@@ -452,11 +487,11 @@ intel_miptree_image_data(struct intel_context *intel,
0, 0, /* source x, y */
dst->level[level].width, height); /* width, height */
- src += src_image_pitch * dst->cpp;
+ src = (char *)src + src_image_pitch * dst->cpp;
}
}
-extern GLuint intel_compressed_alignment(GLenum);
+extern void intel_get_texture_alignment_unit(GLenum, GLuint *, GLuint *);
/* Copy mipmap image between trees
*/
void
@@ -473,20 +508,37 @@ intel_miptree_image_copy(struct intel_context *intel,
const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level);
const GLuint *src_depth_offset = intel_miptree_depth_offsets(src, level);
GLuint i;
+ GLboolean success;
if (dst->compressed) {
- GLuint alignment = intel_compressed_alignment(dst->internal_format);
+ GLuint align_w, align_h;
+
+ intel_get_texture_alignment_unit(dst->internal_format, &align_w, &align_h);
height = (height + 3) / 4;
- width = ((width + alignment - 1) & ~(alignment - 1));
+ width = ALIGN(width, align_w);
}
for (i = 0; i < depth; i++) {
- intel_region_copy(intel,
- dst->region, dst_offset + dst_depth_offset[i],
- 0,
- 0,
- src->region, src_offset + src_depth_offset[i],
- 0, 0, width, height);
+ success = intel_region_copy(intel,
+ dst->region, dst_offset + dst_depth_offset[i],
+ 0, 0,
+ src->region, src_offset + src_depth_offset[i],
+ 0, 0, width, height, GL_COPY);
+ if (!success) {
+ GLubyte *src_ptr, *dst_ptr;
+
+ src_ptr = intel_region_map(intel, src->region);
+ dst_ptr = intel_region_map(intel, dst->region);
+
+ _mesa_copy_rect(dst_ptr + dst_offset + dst_depth_offset[i],
+ dst->cpp,
+ dst->pitch,
+ 0, 0, width, height,
+ src_ptr + src_offset + src_depth_offset[i],
+ src->pitch,
+ 0, 0);
+ intel_region_unmap(intel, src->region);
+ intel_region_unmap(intel, dst->region);
+ }
}
-
}
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index c9537dbb9a..c890b2a0d0 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -126,6 +126,7 @@ struct intel_mipmap_tree
struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel,
GLenum target,
+ GLenum base_format,
GLenum internal_format,
GLuint first_level,
GLuint last_level,
@@ -133,7 +134,8 @@ struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel,
GLuint height0,
GLuint depth0,
GLuint cpp,
- GLuint compress_byte);
+ GLuint compress_byte,
+ GLboolean expect_accelerated_upload);
struct intel_mipmap_tree *
intel_miptree_create_for_region(struct intel_context *intel,
@@ -147,6 +149,7 @@ intel_miptree_create_for_region(struct intel_context *intel,
int intel_miptree_pitch_align (struct intel_context *intel,
struct intel_mipmap_tree *mt,
+ uint32_t tiling,
int pitch);
void intel_miptree_reference(struct intel_mipmap_tree **dst,
@@ -193,6 +196,11 @@ void intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d);
+void intel_miptree_set_image_offset_ex(struct intel_mipmap_tree *mt,
+ GLuint level,
+ GLuint img, GLuint x, GLuint y,
+ GLuint offset);
+
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
GLuint level,
GLuint img, GLuint x, GLuint y);
@@ -217,10 +225,13 @@ void intel_miptree_image_copy(struct intel_context *intel,
/* i915_mipmap_tree.c:
*/
GLboolean i915_miptree_layout(struct intel_context *intel,
- struct intel_mipmap_tree *mt);
+ struct intel_mipmap_tree *mt,
+ uint32_t tiling);
GLboolean i945_miptree_layout(struct intel_context *intel,
- struct intel_mipmap_tree *mt);
+ struct intel_mipmap_tree *mt,
+ uint32_t tiling);
GLboolean brw_miptree_layout(struct intel_context *intel,
- struct intel_mipmap_tree *mt);
+ struct intel_mipmap_tree *mt,
+ uint32_t tiling);
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_pixel.c b/src/mesa/drivers/dri/intel/intel_pixel.c
index cf2f32d384..b5850df9ff 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel.c
@@ -25,11 +25,17 @@
*
**************************************************************************/
+#include "main/accum.h"
+#include "main/drawpix.h"
#include "main/enums.h"
#include "main/state.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 "swrast/swrast.h"
#include "shader/arbprogram.h"
#include "shader/program.h"
@@ -112,7 +118,7 @@ intel_check_blit_fragment_ops(GLcontext * ctx, GLboolean src_alpha_is_one)
return GL_FALSE;
}
- if (ctx->Stencil.Enabled) {
+ if (ctx->Stencil._Enabled) {
DBG("fallback due to image stencil\n");
return GL_FALSE;
}
@@ -173,179 +179,12 @@ intel_check_blit_format(struct intel_region * region,
}
void
-intel_meta_set_passthrough_transform(struct intel_context *intel)
-{
- GLcontext *ctx = &intel->ctx;
-
- intel->meta.saved_vp_x = ctx->Viewport.X;
- intel->meta.saved_vp_y = ctx->Viewport.Y;
- intel->meta.saved_vp_width = ctx->Viewport.Width;
- intel->meta.saved_vp_height = ctx->Viewport.Height;
-
- _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
-
- _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
-intel_meta_restore_transform(struct intel_context *intel)
-{
- _mesa_MatrixMode(GL_PROJECTION);
- _mesa_PopMatrix();
- _mesa_MatrixMode(GL_MODELVIEW);
- _mesa_PopMatrix();
-
- _mesa_Viewport(intel->meta.saved_vp_x, intel->meta.saved_vp_y,
- intel->meta.saved_vp_width, intel->meta.saved_vp_height);
-}
-
-/**
- * Set up a vertex program to pass through the position and first texcoord
- * for pixel path.
- */
-void
-intel_meta_set_passthrough_vertex_program(struct intel_context *intel)
-{
- GLcontext *ctx = &intel->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(intel->meta.saved_vp == NULL);
-
- _mesa_reference_vertprog(ctx, &intel->meta.saved_vp,
- ctx->VertexProgram.Current);
- if (intel->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, &intel->meta.passthrough_vp,
- ctx->VertexProgram.Current);
- _mesa_DeletePrograms(1, &prog_name);
- }
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
- intel->meta.passthrough_vp);
- ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
- &intel->meta.passthrough_vp->Base);
-
- intel->meta.saved_vp_enable = ctx->VertexProgram.Enabled;
- _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
-}
-
-/**
- * Restores the previous vertex program after
- * intel_meta_set_passthrough_vertex_program()
- */
-void
-intel_meta_restore_vertex_program(struct intel_context *intel)
-{
- GLcontext *ctx = &intel->ctx;
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
- intel->meta.saved_vp);
- _mesa_reference_vertprog(ctx, &intel->meta.saved_vp, NULL);
- ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
- &ctx->VertexProgram.Current->Base);
-
- if (!intel->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
-intel_meta_set_fragment_program(struct intel_context *intel,
- struct gl_fragment_program **prog,
- const char *prog_string)
-{
- GLcontext *ctx = &intel->ctx;
- assert(intel->meta.saved_fp == NULL);
-
- _mesa_reference_fragprog(ctx, &intel->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));
-
- intel->meta.saved_fp_enable = ctx->FragmentProgram.Enabled;
- _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
-}
-
-/**
- * Restores the previous fragment program after
- * intel_meta_set_fragment_program()
- */
-void
-intel_meta_restore_fragment_program(struct intel_context *intel)
-{
- GLcontext *ctx = &intel->ctx;
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
- intel->meta.saved_fp);
- _mesa_reference_fragprog(ctx, &intel->meta.saved_fp, NULL);
- ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
- &ctx->FragmentProgram.Current->Base);
-
- if (!intel->meta.saved_fp_enable)
- _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
-}
-
-void
intelInitPixelFuncs(struct dd_function_table *functions)
{
- functions->Accum = _swrast_Accum;
+ _MESA_INIT_ACCUM_FUNCTIONS(functions, _swrast_);
if (!getenv("INTEL_NO_BLIT")) {
- functions->Bitmap = intelBitmap;
- functions->CopyPixels = intelCopyPixels;
- functions->DrawPixels = intelDrawPixels;
-#ifdef I915
- functions->ReadPixels = intelReadPixels;
-#endif
+ _MESA_INIT_DRAWPIX_FUNCTIONS(functions, intel);
}
-}
-
-void
-intel_free_pixel_state(struct intel_context *intel)
-{
- GLcontext *ctx = &intel->ctx;
-
- _mesa_reference_vertprog(ctx, &intel->meta.passthrough_vp, NULL);
- _mesa_reference_fragprog(ctx, &intel->meta.bitmap_fp, NULL);
+ functions->ReadPixels = intelReadPixels;
}
diff --git a/src/mesa/drivers/dri/intel/intel_pixel.h b/src/mesa/drivers/dri/intel/intel_pixel.h
index 76b8781316..96a6dd17b2 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel.h
+++ b/src/mesa/drivers/dri/intel/intel_pixel.h
@@ -31,16 +31,6 @@
#include "main/mtypes.h"
void intelInitPixelFuncs(struct dd_function_table *functions);
-void intel_meta_set_passthrough_transform(struct intel_context *intel);
-void intel_meta_restore_transform(struct intel_context *intel);
-void intel_meta_set_passthrough_vertex_program(struct intel_context *intel);
-void intel_meta_restore_vertex_program(struct intel_context *intel);
-void intel_meta_set_fragment_program(struct intel_context *intel,
- struct gl_fragment_program **prog,
- const char *prog_string);
-void intel_meta_restore_fragment_program(struct intel_context *intel);
-void intel_free_pixel_state(struct intel_context *intel);
-
GLboolean intel_check_blit_fragment_ops(GLcontext * ctx,
GLboolean src_alpha_is_one);
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
index 3a01f63dc7..9a0bcc07a5 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
@@ -42,6 +42,7 @@
#include "main/varray.h"
#include "main/attrib.h"
#include "main/enable.h"
+#include "main/viewport.h"
#include "shader/arbprogram.h"
#include "glapi/dispatch.h"
#include "swrast/swrast.h"
@@ -92,19 +93,12 @@ static const GLubyte *map_pbo( GLcontext *ctx,
return ADD_POINTERS(buf, bitmap);
}
-static GLboolean test_bit( const GLubyte *src,
- GLuint bit )
+static GLboolean test_bit( const GLubyte *src, GLuint bit )
{
return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0;
}
-static GLboolean test_msb_bit(const GLubyte *src, GLuint bit)
-{
- return (src[bit/8] & (1<<(7 - (bit % 8)))) ? 1 : 0;
-}
-
-static void set_bit( GLubyte *dest,
- GLuint bit )
+static void set_bit( GLubyte *dest, GLuint bit )
{
dest[bit/8] |= 1 << (bit % 8);
}
@@ -194,7 +188,7 @@ do_blit_bitmap( GLcontext *ctx,
struct gl_framebuffer *fb = ctx->DrawBuffer;
GLfloat tmpColor[4];
GLubyte ubcolor[4];
- GLuint color8888, color565;
+ GLuint color;
unsigned int num_cliprects;
drm_clip_rect_t *cliprects;
int x_off, y_off;
@@ -215,7 +209,7 @@ do_blit_bitmap( GLcontext *ctx,
if (!dst)
return GL_FALSE;
- if (unpack->BufferObj->Name) {
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
bitmap = map_pbo(ctx, width, height, unpack, bitmap);
if (bitmap == NULL)
return GL_TRUE; /* even though this is an error, we're done */
@@ -232,8 +226,11 @@ do_blit_bitmap( GLcontext *ctx,
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]);
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]);
- color8888 = INTEL_PACKCOLOR8888(ubcolor[0], ubcolor[1], ubcolor[2], ubcolor[3]);
- color565 = INTEL_PACKCOLOR565(ubcolor[0], ubcolor[1], ubcolor[2]);
+ if (dst->cpp == 2)
+ color = INTEL_PACKCOLOR565(ubcolor[0], ubcolor[1], ubcolor[2]);
+ else
+ color = INTEL_PACKCOLOR8888(ubcolor[0], ubcolor[1],
+ ubcolor[2], ubcolor[3]);
if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F))
return GL_FALSE;
@@ -307,21 +304,21 @@ do_blit_bitmap( GLcontext *ctx,
fb->Name == 0 ? GL_TRUE : GL_FALSE) == 0)
continue;
- /*
- */
- intelEmitImmediateColorExpandBlit( intel,
- dst->cpp,
- (GLubyte *)stipple,
- sz,
- (dst->cpp == 2) ? color565 : color8888,
- dst->pitch,
- dst->buffer,
- 0,
- dst->tiling,
- box_x + px,
- box_y + py,
- w, h,
- logic_op);
+ if (!intelEmitImmediateColorExpandBlit(intel,
+ dst->cpp,
+ (GLubyte *)stipple,
+ sz,
+ color,
+ dst->pitch,
+ dst->buffer,
+ 0,
+ dst->tiling,
+ box_x + px,
+ box_y + py,
+ w, h,
+ logic_op)) {
+ return GL_FALSE;
+ }
}
}
}
@@ -332,7 +329,7 @@ out:
if (INTEL_DEBUG & DEBUG_SYNC)
intel_batchbuffer_flush(intel->batch);
- if (unpack->BufferObj->Name) {
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
/* done with PBO so unmap it now */
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
unpack->BufferObj);
@@ -360,11 +357,8 @@ intel_texture_bitmap(GLcontext * ctx,
"END\n";
GLuint texname;
GLfloat vertices[4][4];
- GLfloat texcoords[4][2];
GLint old_active_texture;
- GLubyte *unpacked_bitmap;
GLubyte *a8_bitmap;
- int x, y;
GLfloat dst_z;
/* We need a fragment program for the KIL effect */
@@ -401,6 +395,20 @@ intel_texture_bitmap(GLcontext * ctx,
return GL_FALSE;
}
+ if (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ (!is_power_of_two(width) || !is_power_of_two(height))) {
+ if (INTEL_DEBUG & DEBUG_FALLBACKS)
+ fprintf(stderr,
+ "glBitmap() fallback: NPOT texture\n");
+ return GL_FALSE;
+ }
+
+ if (ctx->Fog.Enabled) {
+ if (INTEL_DEBUG & DEBUG_FALLBACKS)
+ fprintf(stderr, "glBitmap() fallback: fog\n");
+ return GL_FALSE;
+ }
+
/* Check that we can load in a texture this big. */
if (width > (1 << (ctx->Const.MaxTextureLevels - 1)) ||
height > (1 << (ctx->Const.MaxTextureLevels - 1))) {
@@ -410,23 +418,17 @@ intel_texture_bitmap(GLcontext * ctx,
return GL_FALSE;
}
- /* Convert the A1 bitmap to an A8 format suitable for glTexImage */
- if (unpack->BufferObj->Name) {
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
bitmap = map_pbo(ctx, width, height, unpack, bitmap);
if (bitmap == NULL)
return GL_TRUE; /* even though this is an error, we're done */
}
- unpacked_bitmap = _mesa_unpack_bitmap(width, height, bitmap,
- unpack);
+
+ /* Convert the A1 bitmap to an A8 format suitable for glTexImage */
a8_bitmap = _mesa_calloc(width * height);
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- if (test_msb_bit(unpacked_bitmap, ALIGN(width, 8) * y + x))
- a8_bitmap[y * width + x] = 0xff;
- }
- }
- _mesa_free(unpacked_bitmap);
- if (unpack->BufferObj->Name) {
+ _mesa_expand_bitmap(width, height, unpack, bitmap, a8_bitmap, width, 0xff);
+
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
/* done with PBO so unmap it now */
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
unpack->BufferObj);
@@ -459,15 +461,18 @@ intel_texture_bitmap(GLcontext * ctx,
GL_ALPHA, GL_UNSIGNED_BYTE, a8_bitmap);
_mesa_free(a8_bitmap);
- intel_meta_set_fragment_program(intel, &intel->meta.bitmap_fp, fp);
+ meta_set_fragment_program(&intel->meta, &intel->meta.bitmap_fp, fp);
_mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0,
ctx->Current.RasterColor);
- intel_meta_set_passthrough_vertex_program(intel);
- intel_meta_set_passthrough_transform(intel);
+ meta_set_passthrough_vertex_program(&intel->meta);
+ meta_set_passthrough_transform(&intel->meta);
/* convert rasterpos Z from [0,1] to NDC coord in [-1,1] */
dst_z = -1.0 + 2.0 * ctx->Current.RasterPos[2];
+ /* RasterPos[2] already takes into account the DepthRange mapping. */
+ _mesa_DepthRange(0.0, 1.0);
+
vertices[0][0] = dst_x;
vertices[0][1] = dst_y;
vertices[0][2] = dst_z;
@@ -485,24 +490,15 @@ intel_texture_bitmap(GLcontext * ctx,
vertices[3][2] = dst_z;
vertices[3][3] = 1.0;
- texcoords[0][0] = 0.0;
- texcoords[0][1] = 0.0;
- texcoords[1][0] = 1.0;
- texcoords[1][1] = 0.0;
- texcoords[2][0] = 1.0;
- texcoords[2][1] = 1.0;
- texcoords[3][0] = 0.0;
- texcoords[3][1] = 1.0;
-
_mesa_VertexPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), &vertices);
- _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &texcoords);
_mesa_Enable(GL_VERTEX_ARRAY);
- _mesa_Enable(GL_TEXTURE_COORD_ARRAY);
- CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4));
+ meta_set_default_texrect(&intel->meta);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
- intel_meta_restore_transform(intel);
- intel_meta_restore_fragment_program(intel);
- intel_meta_restore_vertex_program(intel);
+ meta_restore_texcoords(&intel->meta);
+ meta_restore_transform(&intel->meta);
+ meta_restore_fragment_program(&intel->meta);
+ meta_restore_vertex_program(&intel->meta);
_mesa_PopClientAttrib();
_mesa_Disable(GL_TEXTURE_2D); /* asserted that it was disabled at entry */
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_copy.c b/src/mesa/drivers/dri/intel/intel_pixel_copy.c
index 7c7aa6097c..07ca8f7ddb 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_copy.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_copy.c
@@ -26,18 +26,13 @@
**************************************************************************/
#include "main/glheader.h"
-#include "main/enums.h"
#include "main/image.h"
#include "main/state.h"
#include "main/mtypes.h"
-#include "main/macros.h"
-#include "swrast/swrast.h"
+#include "drivers/common/meta.h"
-#include "intel_screen.h"
#include "intel_context.h"
-#include "intel_batchbuffer.h"
#include "intel_buffers.h"
-#include "intel_blit.h"
#include "intel_regions.h"
#include "intel_pixel.h"
@@ -87,7 +82,7 @@ intel_check_copypixel_blit_fragment_ops(GLcontext * ctx)
ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
- ctx->Stencil.Enabled ||
+ ctx->Stencil._Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
@@ -97,162 +92,6 @@ intel_check_copypixel_blit_fragment_ops(GLcontext * ctx)
ctx->Color.BlendEnabled);
}
-#ifdef I915
-/* Doesn't work for overlapping regions. Could do a double copy or
- * just fallback.
- */
-static GLboolean
-do_texture_copypixels(GLcontext * ctx,
- GLint srcx, GLint srcy,
- GLsizei width, GLsizei height,
- GLint dstx, GLint dsty, GLenum type)
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_region *dst = intel_drawbuf_region(intel);
- struct intel_region *src = copypix_src_region(intel, type);
- GLenum src_format;
- GLenum src_type;
-
- DBG("%s %d,%d %dx%d --> %d,%d\n", __FUNCTION__,
- srcx, srcy, width, height, dstx, dsty);
-
- if (!src || !dst || type != GL_COLOR)
- return GL_FALSE;
-
- if (ctx->_ImageTransferState) {
- if (INTEL_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
- return GL_FALSE;
- }
-
- /* Can't handle overlapping regions. Don't have sufficient control
- * over rasterization to pull it off in-place. Punt on these for
- * now.
- *
- * XXX: do a copy to a temporary.
- */
- if (src->buffer == dst->buffer) {
- drm_clip_rect_t srcbox;
- drm_clip_rect_t dstbox;
- drm_clip_rect_t tmp;
-
- srcbox.x1 = srcx;
- srcbox.y1 = srcy;
- srcbox.x2 = srcx + width;
- srcbox.y2 = srcy + height;
-
- if (ctx->Pixel.ZoomX > 0) {
- dstbox.x1 = dstx;
- dstbox.x2 = dstx + width * ctx->Pixel.ZoomX;
- } else {
- dstbox.x1 = dstx + width * ctx->Pixel.ZoomX;
- dstbox.x2 = dstx;
- }
- if (ctx->Pixel.ZoomY > 0) {
- dstbox.y1 = dsty;
- dstbox.y2 = dsty + height * ctx->Pixel.ZoomY;
- } else {
- dstbox.y1 = dsty + height * ctx->Pixel.ZoomY;
- dstbox.y2 = dsty;
- }
-
- DBG("src %d,%d %d,%d\n", srcbox.x1, srcbox.y1, srcbox.x2, srcbox.y2);
- DBG("dst %d,%d %d,%d (%dx%d) (%f,%f)\n", dstbox.x1, dstbox.y1, dstbox.x2, dstbox.y2,
- width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
-
- if (intel_intersect_cliprects(&tmp, &srcbox, &dstbox)) {
- DBG("%s: regions overlap\n", __FUNCTION__);
- return GL_FALSE;
- }
- }
-
- intelFlush(&intel->ctx);
-
- intel->vtbl.install_meta_state(intel);
-
- /* Is this true? Also will need to turn depth testing on according
- * to state:
- */
- intel->vtbl.meta_no_stencil_write(intel);
- intel->vtbl.meta_no_depth_write(intel);
-
- /* Set the 3d engine to draw into the destination region:
- */
- intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
-
- intel->vtbl.meta_import_pixel_state(intel);
-
- if (src->cpp == 2) {
- src_format = GL_RGB;
- src_type = GL_UNSIGNED_SHORT_5_6_5;
- }
- else {
- src_format = GL_BGRA;
- src_type = GL_UNSIGNED_BYTE;
- }
-
- /* Set the frontbuffer up as a large rectangular texture.
- */
- if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, 0,
- src->pitch,
- src->height, src_format, src_type)) {
- intel->vtbl.leave_meta_state(intel);
- return GL_FALSE;
- }
-
-
- intel->vtbl.meta_texture_blend_replace(intel);
-
- LOCK_HARDWARE(intel);
-
- if (intel->driDrawable->numClipRects) {
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
-
-
- srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
-
- srcx += dPriv->x;
- srcy += dPriv->y;
-
- /* Clip against the source region. This is the only source
- * clipping we do. XXX: Just set the texcord wrap mode to clamp
- * or similar.
- *
- */
- if (0) {
- GLint orig_x = srcx;
- GLint orig_y = srcy;
-
- if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
- &srcx, &srcy, &width, &height))
- goto out;
-
- dstx += srcx - orig_x;
- dsty += (srcy - orig_y) * ctx->Pixel.ZoomY;
- }
-
- /* Just use the regular cliprect mechanism... Does this need to
- * even hold the lock???
- */
- intel->vtbl.meta_draw_quad(intel,
- dstx,
- dstx + width * ctx->Pixel.ZoomX,
- dPriv->h - (dsty + height * ctx->Pixel.ZoomY),
- dPriv->h - (dsty), 0, /* XXX: what z value? */
- 0x00ff00ff,
- srcx, srcx + width, srcy, srcy + height);
-
- out:
- intel->vtbl.leave_meta_state(intel);
- intel_batchbuffer_emit_mi_flush(intel->batch);
- }
- UNLOCK_HARDWARE(intel);
-
- DBG("%s: success\n", __FUNCTION__);
- return GL_TRUE;
-}
-#endif /* I915 */
-
/**
* CopyPixels with the blitter. Don't support zooming, pixel transfer, etc.
@@ -272,6 +111,12 @@ do_blit_copypixels(GLcontext * ctx,
drm_clip_rect_t *cliprects;
int x_off, y_off;
+ if (type == GL_DEPTH || type == GL_STENCIL) {
+ if (INTEL_DEBUG & DEBUG_FALLBACKS)
+ fprintf(stderr, "glCopyPixels() fallback: GL_DEPTH || GL_STENCIL\n");
+ return GL_FALSE;
+ }
+
/* Update draw buffer bounds */
_mesa_update_state(ctx);
@@ -362,14 +207,16 @@ do_blit_copypixels(GLcontext * ctx,
&clip_x, &clip_y, &clip_w, &clip_h))
continue;
- intelEmitCopyBlit(intel, dst->cpp,
- src->pitch, src->buffer, 0, src->tiling,
- dst->pitch, dst->buffer, 0, dst->tiling,
- clip_x + delta_x, clip_y + delta_y, /* srcx, srcy */
- clip_x, clip_y, /* dstx, dsty */
- clip_w, clip_h,
- ctx->Color.ColorLogicOpEnabled ?
- ctx->Color.LogicOp : GL_COPY);
+ if (!intel_region_copy(intel,
+ dst, 0, clip_x, clip_y,
+ src, 0, clip_x + delta_x, clip_y + delta_y,
+ clip_w, clip_h,
+ ctx->Color.ColorLogicOpEnabled ?
+ ctx->Color.LogicOp : GL_COPY)) {
+ DBG("%s: blit failure\n", __FUNCTION__);
+ UNLOCK_HARDWARE(intel);
+ return GL_FALSE;
+ }
}
}
out:
@@ -392,12 +239,6 @@ intelCopyPixels(GLcontext * ctx,
if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
return;
-#ifdef I915
- if (do_texture_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
- return;
-#endif
-
- DBG("fallback to _swrast_CopyPixels\n");
-
- _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type);
+ /* this will use swrast if needed */
+ _mesa_meta_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type);
}
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_draw.c b/src/mesa/drivers/dri/intel/intel_pixel_draw.c
index 0e83afa645..7fbb89fd6a 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_draw.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_draw.c
@@ -29,8 +29,6 @@
#include "main/enums.h"
#include "main/image.h"
#include "main/mtypes.h"
-#include "main/macros.h"
-#include "main/bufferobj.h"
#include "main/teximage.h"
#include "main/texenv.h"
#include "main/texobj.h"
@@ -41,155 +39,22 @@
#include "main/enable.h"
#include "main/buffers.h"
#include "main/fbobject.h"
-#include "main/renderbuffer.h"
#include "main/depth.h"
#include "main/hash.h"
#include "main/blend.h"
-#include "glapi/dispatch.h"
#include "swrast/swrast.h"
+#include "drivers/common/meta.h"
-#include "intel_screen.h"
#include "intel_context.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_buffers.h"
#include "intel_regions.h"
#include "intel_pixel.h"
-#include "intel_buffer_objects.h"
#include "intel_fbo.h"
-static GLboolean
-intel_texture_drawpixels(GLcontext * ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height,
- GLenum format,
- GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *pixels)
-{
- struct intel_context *intel = intel_context(ctx);
- GLuint texname;
- GLfloat vertices[4][4];
- GLfloat texcoords[4][2];
- GLfloat z;
-
- /* We're going to mess with texturing with no regard to existing texture
- * state, so if there is some set up we have to bail.
- */
- if (ctx->Texture._EnabledUnits != 0) {
- if (INTEL_DEBUG & DEBUG_FALLBACKS)
- fprintf(stderr, "glDrawPixels() fallback: texturing enabled\n");
- return GL_FALSE;
- }
-
- /* Can't do textured DrawPixels with a fragment program, unless we were
- * to generate a new program that sampled our texture and put the results
- * in the fragment color before the user's program started.
- */
- if (ctx->FragmentProgram.Enabled) {
- if (INTEL_DEBUG & DEBUG_FALLBACKS)
- fprintf(stderr, "glDrawPixels() fallback: fragment program enabled\n");
- return GL_FALSE;
- }
-
- /* We don't have a way to generate fragments with stencil values which *
- * will set the resulting stencil value.
- */
- if (format == GL_STENCIL_INDEX)
- return GL_FALSE;
-
- /* Check that we can load in a texture this big. */
- if (width > (1 << (ctx->Const.MaxTextureLevels - 1)) ||
- height > (1 << (ctx->Const.MaxTextureLevels - 1))) {
- if (INTEL_DEBUG & DEBUG_FALLBACKS)
- fprintf(stderr, "glDrawPixels() fallback: bitmap too large (%dx%d)\n",
- width, height);
- return GL_FALSE;
- }
-
- /* To do DEPTH_COMPONENT, we would need to change our setup to not draw to
- * the color buffer, and sample the texture values into the fragment depth
- * in a program.
- */
- if (format == GL_DEPTH_COMPONENT) {
- if (INTEL_DEBUG & DEBUG_FALLBACKS)
- fprintf(stderr,
- "glDrawPixels() fallback: format == GL_DEPTH_COMPONENT\n");
- return GL_FALSE;
- }
-
- _mesa_PushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT |
- GL_CURRENT_BIT);
- _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
-
- /* XXX: pixel store stuff */
- _mesa_Disable(GL_POLYGON_STIPPLE);
-
- _mesa_ActiveTextureARB(GL_TEXTURE0_ARB);
- _mesa_Enable(GL_TEXTURE_2D);
- _mesa_GenTextures(1, &texname);
- _mesa_BindTexture(GL_TEXTURE_2D, texname);
- _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- _mesa_TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- /*
- _mesa_TexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
- _mesa_TexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
- */
- _mesa_TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format,
- type, pixels);
-
- intel_meta_set_passthrough_transform(intel);
-
- /* convert rasterpos Z from [0,1] to NDC coord in [-1,1] */
- z = -1.0 + 2.0 * ctx->Current.RasterPos[2];
-
- /* Create the vertex buffer based on the current raster pos. The x and y
- * we're handed are ctx->Current.RasterPos[0,1] rounded to integers.
- * We also apply the depth. However, the W component is already multiplied
- * into ctx->Current.RasterPos[0,1,2] and we can ignore it at this point.
- */
- vertices[0][0] = x;
- vertices[0][1] = y;
- vertices[0][2] = z;
- vertices[0][3] = 1.0;
- vertices[1][0] = x + width * ctx->Pixel.ZoomX;
- vertices[1][1] = y;
- vertices[1][2] = z;
- vertices[1][3] = 1.0;
- vertices[2][0] = x + width * ctx->Pixel.ZoomX;
- vertices[2][1] = y + height * ctx->Pixel.ZoomY;
- vertices[2][2] = z;
- vertices[2][3] = 1.0;
- vertices[3][0] = x;
- vertices[3][1] = y + height * ctx->Pixel.ZoomY;
- vertices[3][2] = z;
- vertices[3][3] = 1.0;
-
- texcoords[0][0] = 0.0;
- texcoords[0][1] = 0.0;
- texcoords[1][0] = 1.0;
- texcoords[1][1] = 0.0;
- texcoords[2][0] = 1.0;
- texcoords[2][1] = 1.0;
- texcoords[3][0] = 0.0;
- texcoords[3][1] = 1.0;
-
- _mesa_VertexPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), &vertices);
- _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &texcoords);
- _mesa_Enable(GL_VERTEX_ARRAY);
- _mesa_Enable(GL_TEXTURE_COORD_ARRAY);
- CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4));
-
- intel_meta_restore_transform(intel);
- _mesa_PopClientAttrib();
- _mesa_PopAttrib();
-
- _mesa_DeleteTextures(1, &texname);
-
- return GL_TRUE;
-}
+/** XXX compare perf of this vs. _mesa_meta_draw_pixels(STENCIL) */
static GLboolean
intel_stencil_drawpixels(GLcontext * ctx,
GLint x, GLint y,
@@ -202,13 +67,14 @@ intel_stencil_drawpixels(GLcontext * ctx,
struct intel_context *intel = intel_context(ctx);
GLuint texname, rb_name, fb_name, old_fb_name;
GLfloat vertices[4][2];
- GLfloat texcoords[4][2];
struct intel_renderbuffer *irb;
struct intel_renderbuffer *depth_irb;
struct gl_renderbuffer *rb;
struct gl_pixelstore_attrib old_unpack;
GLstencil *stencil_pixels;
- int row;
+ int row, y1, y2;
+ GLint old_active_texture;
+ GLboolean rendering_to_fbo = ctx->DrawBuffer->Name != 0;
if (format != GL_STENCIL_INDEX)
return GL_FALSE;
@@ -225,6 +91,10 @@ intel_stencil_drawpixels(GLcontext * ctx,
return GL_FALSE;
}
+ /* We don't support stencil testing/ops here */
+ if (ctx->Stencil._Enabled)
+ return GL_FALSE;
+
/* We use FBOs for our wrapping of the depthbuffer into a color
* destination.
*/
@@ -262,10 +132,19 @@ intel_stencil_drawpixels(GLcontext * ctx,
return GL_FALSE;
}
+ if (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ (!is_power_of_two(width) || !is_power_of_two(height))) {
+ if (INTEL_DEBUG & DEBUG_FALLBACKS)
+ fprintf(stderr,
+ "glDrawPixels(GL_STENCIL_INDEX) fallback: NPOT texture\n");
+ return GL_FALSE;
+ }
+
_mesa_PushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT |
GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
old_fb_name = ctx->DrawBuffer->Name;
+ old_active_texture = ctx->Texture.CurrentUnit;
_mesa_Disable(GL_POLYGON_STIPPLE);
_mesa_Disable(GL_DEPTH_TEST);
@@ -330,34 +209,37 @@ intel_stencil_drawpixels(GLcontext * ctx,
ctx->Unpack = old_unpack;
_mesa_free(stencil_pixels);
- intel_meta_set_passthrough_transform(intel);
+ meta_set_passthrough_transform(&intel->meta);
+ /* Since we're rendering to the framebuffer as if it was an FBO,
+ * if it's the window system we have to flip the coordinates.
+ */
+ if (rendering_to_fbo) {
+ y1 = y;
+ y2 = y + height * ctx->Pixel.ZoomY;
+ } else {
+ y1 = irb->Base.Height - (y + height * ctx->Pixel.ZoomY);
+ y2 = irb->Base.Height - y;
+ }
vertices[0][0] = x;
- vertices[0][1] = y;
+ vertices[0][1] = y1;
vertices[1][0] = x + width * ctx->Pixel.ZoomX;
- vertices[1][1] = y;
+ vertices[1][1] = y1;
vertices[2][0] = x + width * ctx->Pixel.ZoomX;
- vertices[2][1] = y + height * ctx->Pixel.ZoomY;
+ vertices[2][1] = y2;
vertices[3][0] = x;
- vertices[3][1] = y + height * ctx->Pixel.ZoomY;
-
- texcoords[0][0] = 0.0;
- texcoords[0][1] = 0.0;
- texcoords[1][0] = 1.0;
- texcoords[1][1] = 0.0;
- texcoords[2][0] = 1.0;
- texcoords[2][1] = 1.0;
- texcoords[3][0] = 0.0;
- texcoords[3][1] = 1.0;
+ vertices[3][1] = y2;
_mesa_VertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &vertices);
- _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &texcoords);
_mesa_Enable(GL_VERTEX_ARRAY);
- _mesa_Enable(GL_TEXTURE_COORD_ARRAY);
- CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4));
+ meta_set_default_texrect(&intel->meta);
- intel_meta_restore_transform(intel);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ meta_restore_texcoords(&intel->meta);
+ meta_restore_transform(&intel->meta);
+
+ _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + old_active_texture);
_mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, old_fb_name);
_mesa_PopClientAttrib();
@@ -379,17 +261,25 @@ intelDrawPixels(GLcontext * ctx,
const struct gl_pixelstore_attrib *unpack,
const GLvoid * pixels)
{
- if (intel_texture_drawpixels(ctx, x, y, width, height, format, type,
- unpack, pixels))
- return;
-
+#if 0
+ /* XXX this function doesn't seem to work reliably even when all
+ * the pre-requisite conditions are met.
+ * Note that this function is never hit with conform.
+ * Fall back to swrast because even the _mesa_meta_draw_pixels() approach
+ * isn't working because of an apparent stencil bug.
+ */
if (intel_stencil_drawpixels(ctx, x, y, width, height, format, type,
unpack, pixels))
return;
+#else
+ (void) intel_stencil_drawpixels; /* silence warning */
+ if (format == GL_STENCIL_INDEX) {
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type,
+ unpack, pixels);
+ return;
+ }
+#endif
- if (INTEL_DEBUG & DEBUG_PIXEL)
- _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
-
- _swrast_DrawPixels(ctx, x, y, width, height, format, type,
- unpack, pixels);
+ _mesa_meta_draw_pixels(ctx, x, y, width, height, format, type,
+ unpack, pixels);
}
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_read.c b/src/mesa/drivers/dri/intel/intel_pixel_read.c
new file mode 100644
index 0000000000..bc67f6242a
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_pixel_read.c
@@ -0,0 +1,315 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/glheader.h"
+#include "main/enums.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/image.h"
+#include "main/bufferobj.h"
+#include "main/state.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_batchbuffer.h"
+#include "intel_blit.h"
+#include "intel_buffers.h"
+#include "intel_regions.h"
+#include "intel_pixel.h"
+#include "intel_buffer_objects.h"
+
+/* For many applications, the new ability to pull the source buffers
+ * back out of the GTT and then do the packing/conversion operations
+ * in software will be as much of an improvement as trying to get the
+ * blitter and/or texture engine to do the work.
+ *
+ * This step is gated on private backbuffers.
+ *
+ * Obviously the frontbuffer can't be pulled back, so that is either
+ * an argument for blit/texture readpixels, or for blitting to a
+ * temporary and then pulling that back.
+ *
+ * When the destination is a pbo, however, it's not clear if it is
+ * ever going to be pulled to main memory (though the access param
+ * will be a good hint). So it sounds like we do want to be able to
+ * choose between blit/texture implementation on the gpu and pullback
+ * and cpu-based copying.
+ *
+ * Unless you can magically turn client memory into a PBO for the
+ * duration of this call, there will be a cpu-based copying step in
+ * any case.
+ */
+
+
+static GLboolean
+do_texture_readpixels(GLcontext * ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ struct intel_region *dest_region)
+{
+#if 0
+ struct intel_context *intel = intel_context(ctx);
+ intelScreenPrivate *screen = intel->intelScreen;
+ GLint pitch = pack->RowLength ? pack->RowLength : width;
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ int textureFormat;
+ GLenum glTextureFormat;
+ int destFormat, depthFormat, destPitch;
+ drm_clip_rect_t tmp;
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+
+ if (ctx->_ImageTransferState ||
+ pack->SwapBytes || pack->LsbFirst || !pack->Invert) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel));
+
+ if (!intel->vtbl.meta_render_dest(intel, dest_region, type, format)) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s: couldn't set dest %s/%s\n",
+ __FUNCTION__,
+ _mesa_lookup_enum_by_nr(type),
+ _mesa_lookup_enum_by_nr(format));
+ return GL_FALSE;
+ }
+
+ LOCK_HARDWARE(intel);
+
+ if (intel->driDrawable->numClipRects) {
+ intel->vtbl.install_meta_state(intel);
+ intel->vtbl.meta_no_depth_write(intel);
+ intel->vtbl.meta_no_stencil_write(intel);
+
+ if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
+ UNLOCK_HARDWARE(intel);
+ SET_STATE(i830, state);
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
+ return GL_TRUE;
+ }
+
+ y = dPriv->h - y - height;
+ x += dPriv->x;
+ y += dPriv->y;
+
+
+ /* Set the frontbuffer up as a large rectangular texture.
+ */
+ intel->vtbl.meta_tex_rect_source(intel, src_region, textureFormat);
+
+
+ intel->vtbl.meta_texture_blend_replace(i830, glTextureFormat);
+
+
+ /* Set the 3d engine to draw into the destination region:
+ */
+
+ intel->vtbl.meta_draw_region(intel, dest_region);
+ intel->vtbl.meta_draw_format(intel, destFormat, depthFormat); /* ?? */
+
+
+ /* Draw a single quad, no cliprects:
+ */
+ intel->vtbl.meta_disable_cliprects(intel);
+
+ intel->vtbl.draw_quad(intel,
+ 0, width, 0, height,
+ 0x00ff00ff, x, x + width, y, y + height);
+
+ intel->vtbl.leave_meta_state(intel);
+ }
+ UNLOCK_HARDWARE(intel);
+
+ intel_region_wait_fence(ctx, dest_region); /* required by GL */
+ return GL_TRUE;
+#endif
+
+ return GL_FALSE;
+}
+
+
+
+
+static GLboolean
+do_blit_readpixels(GLcontext * ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_region *src = intel_readbuf_region(intel);
+ struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
+ GLuint dst_offset;
+ GLuint rowLength;
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s\n", __FUNCTION__);
+
+ if (!src)
+ return GL_FALSE;
+
+ if (!_mesa_is_bufferobj(pack->BufferObj)) {
+ /* PBO only for now:
+ */
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - not PBO\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+
+ if (ctx->_ImageTransferState ||
+ !intel_check_blit_format(src, format, type)) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s: bad packing params\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ if (pack->RowLength > 0)
+ rowLength = pack->RowLength;
+ else
+ rowLength = width;
+
+ if (pack->Invert) {
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+ else {
+ rowLength = -rowLength;
+ }
+
+ /* XXX 64-bit cast? */
+ dst_offset = (GLuint) _mesa_image_address(2, pack, pixels, width, height,
+ format, type, 0, 0, 0);
+
+
+ /* Although the blits go on the command buffer, need to do this and
+ * fire with lock held to guarentee cliprects are correct.
+ */
+ intelFlush(&intel->ctx);
+ LOCK_HARDWARE(intel);
+
+ if (intel->driDrawable->numClipRects) {
+ GLboolean all = (width * height * src->cpp == dst->Base.Size &&
+ x == 0 && dst_offset == 0);
+
+ dri_bo *dst_buffer = intel_bufferobj_buffer(intel, dst,
+ all ? INTEL_WRITE_FULL :
+ INTEL_WRITE_PART);
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ int nbox = dPriv->numClipRects;
+ drm_clip_rect_t *box = dPriv->pClipRects;
+ drm_clip_rect_t rect;
+ drm_clip_rect_t src_rect;
+ int i;
+
+ src_rect.x1 = dPriv->x + x;
+ src_rect.y1 = dPriv->y + dPriv->h - (y + height);
+ src_rect.x2 = src_rect.x1 + width;
+ src_rect.y2 = src_rect.y1 + height;
+
+
+
+ for (i = 0; i < nbox; i++) {
+ if (!intel_intersect_cliprects(&rect, &src_rect, &box[i]))
+ continue;
+
+ if (!intelEmitCopyBlit(intel,
+ src->cpp,
+ src->pitch, src->buffer, 0, src->tiling,
+ rowLength, dst_buffer, dst_offset, GL_FALSE,
+ rect.x1,
+ rect.y1,
+ rect.x1 - src_rect.x1,
+ rect.y2 - src_rect.y2,
+ rect.x2 - rect.x1, rect.y2 - rect.y1,
+ GL_COPY)) {
+ UNLOCK_HARDWARE(intel);
+ return GL_FALSE;
+ }
+ }
+ }
+ UNLOCK_HARDWARE(intel);
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s - DONE\n", __FUNCTION__);
+
+ return GL_TRUE;
+}
+
+void
+intelReadPixels(GLcontext * ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
+{
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ intelFlush(ctx);
+
+#ifdef I915
+ if (do_blit_readpixels
+ (ctx, x, y, width, height, format, type, pack, pixels))
+ return;
+
+ if (do_texture_readpixels
+ (ctx, x, y, width, height, format, type, pack, pixels))
+ return;
+#else
+ (void)do_blit_readpixels;
+ (void)do_texture_readpixels;
+#endif
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
+
+ /* Update Mesa state before calling down into _swrast_ReadPixels, as
+ * the spans code requires the computed buffer states to be up to date,
+ * but _swrast_ReadPixels only updates Mesa state after setting up
+ * the spans code.
+ */
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels);
+}
diff --git a/src/mesa/drivers/dri/intel/intel_reg.h b/src/mesa/drivers/dri/intel/intel_reg.h
index 57ac8f0cc1..d19f1bae34 100644
--- a/src/mesa/drivers/dri/intel/intel_reg.h
+++ b/src/mesa/drivers/dri/intel/intel_reg.h
@@ -189,6 +189,19 @@
#define S7_DEPTH_OFFSET_CONST_MASK ~0
+/* p143 */
+#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
+/* Dword 1 */
+#define BUF_3D_ID_COLOR_BACK (0x3<<24)
+#define BUF_3D_ID_DEPTH (0x7<<24)
+#define BUF_3D_USE_FENCE (1<<23)
+#define BUF_3D_TILED_SURFACE (1<<22)
+#define BUF_3D_TILE_WALK_X 0
+#define BUF_3D_TILE_WALK_Y (1<<21)
+#define BUF_3D_PITCH(x) (((x)/4)<<2)
+/* Dword 2 */
+#define BUF_3D_ADDR(x) ((x) & ~0x3)
+
/* Primitive dispatch on 830-945 */
#define _3DPRIMITIVE (CMD_3D | (0x1f << 24))
#define PRIM_INDIRECT (1<<23)
diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c
index 51ce32a967..a86c66a844 100644
--- a/src/mesa/drivers/dri/intel/intel_regions.c
+++ b/src/mesa/drivers/dri/intel/intel_regions.c
@@ -52,17 +52,77 @@
#define FILE_DEBUG_FLAG DEBUG_REGION
+/* This should be set to the maximum backtrace size desired.
+ * Set it to 0 to disable backtrace debugging.
+ */
+#define DEBUG_BACKTRACE_SIZE 0
+
+#if DEBUG_BACKTRACE_SIZE == 0
+/* Use the standard debug output */
+#define _DBG(...) DBG(__VA_ARGS__)
+#else
+/* Use backtracing debug output */
+#define _DBG(...) {debug_backtrace(); DBG(__VA_ARGS__);}
+
+/* Backtracing debug support */
+#include <execinfo.h>
+
+static void
+debug_backtrace(void)
+{
+ void *trace[DEBUG_BACKTRACE_SIZE];
+ char **strings = NULL;
+ int traceSize;
+ register int i;
+
+ traceSize = backtrace(trace, DEBUG_BACKTRACE_SIZE);
+ strings = backtrace_symbols(trace, traceSize);
+ if (strings == NULL) {
+ DBG("no backtrace:");
+ return;
+ }
+
+ /* Spit out all the strings with a colon separator. Ignore
+ * the first, since we don't really care about the call
+ * to debug_backtrace() itself. Skip until the final "/" in
+ * the trace to avoid really long lines.
+ */
+ for (i = 1; i < traceSize; i++) {
+ char *p = strings[i], *slash = strings[i];
+ while (*p) {
+ if (*p++ == '/') {
+ slash = p;
+ }
+ }
+
+ DBG("%s:", slash);
+ }
+
+ /* Free up the memory, and we're done */
+ free(strings);
+}
+
+#endif
+
+
+
/* XXX: Thread safety?
*/
GLubyte *
intel_region_map(struct intel_context *intel, struct intel_region *region)
{
- DBG("%s\n", __FUNCTION__);
+ intelFlush(&intel->ctx);
+
+ _DBG("%s %p\n", __FUNCTION__, region);
if (!region->map_refcount++) {
if (region->pbo)
intel_region_cow(intel, region);
- dri_bo_map(region->buffer, GL_TRUE);
+ if (region->tiling != I915_TILING_NONE &&
+ intel->intelScreen->kernel_exec_fencing)
+ drm_intel_gem_bo_map_gtt(region->buffer);
+ else
+ dri_bo_map(region->buffer, GL_TRUE);
region->map = region->buffer->virtual;
}
@@ -72,9 +132,13 @@ intel_region_map(struct intel_context *intel, struct intel_region *region)
void
intel_region_unmap(struct intel_context *intel, struct intel_region *region)
{
- DBG("%s\n", __FUNCTION__);
+ _DBG("%s %p\n", __FUNCTION__, region);
if (!--region->map_refcount) {
- dri_bo_unmap(region->buffer);
+ if (region->tiling != I915_TILING_NONE &&
+ intel->intelScreen->kernel_exec_fencing)
+ drm_intel_gem_bo_unmap_gtt(region->buffer);
+ else
+ dri_bo_unmap(region->buffer);
region->map = NULL;
}
}
@@ -87,10 +151,10 @@ intel_region_alloc_internal(struct intel_context *intel,
{
struct intel_region *region;
- DBG("%s\n", __FUNCTION__);
-
- if (buffer == NULL)
+ if (buffer == NULL) {
+ _DBG("%s <-- NULL\n", __FUNCTION__);
return NULL;
+ }
region = calloc(sizeof(*region), 1);
region->cpp = cpp;
@@ -104,19 +168,59 @@ intel_region_alloc_internal(struct intel_context *intel,
region->tiling = I915_TILING_NONE;
region->bit_6_swizzle = I915_BIT_6_SWIZZLE_NONE;
+ _DBG("%s <-- %p\n", __FUNCTION__, region);
return region;
}
struct intel_region *
intel_region_alloc(struct intel_context *intel,
- GLuint cpp, GLuint width, GLuint height, GLuint pitch)
+ uint32_t tiling,
+ GLuint cpp, GLuint width, GLuint height, GLuint pitch,
+ GLboolean expect_accelerated_upload)
{
dri_bo *buffer;
+ struct intel_region *region;
+
+ /* If we're tiled, our allocations are in 8 or 32-row blocks, so
+ * failure to align our height means that we won't allocate enough pages.
+ *
+ * If we're untiled, we still have to align to 2 rows high because the
+ * data port accesses 2x2 blocks even if the bottom row isn't to be
+ * rendered, so failure to align means we could walk off the end of the
+ * GTT and fault.
+ */
+ if (tiling == I915_TILING_X)
+ height = ALIGN(height, 8);
+ else if (tiling == I915_TILING_Y)
+ height = ALIGN(height, 32);
+ else
+ height = ALIGN(height, 2);
- buffer = dri_bo_alloc(intel->bufmgr, "region",
- pitch * cpp * height, 64);
+ /* If we're untiled, we have to align to 2 rows high because the
+ * data port accesses 2x2 blocks even if the bottom row isn't to be
+ * rendered, so failure to align means we could walk off the end of the
+ * GTT and fault.
+ */
+ height = ALIGN(height, 2);
- return intel_region_alloc_internal(intel, cpp, width, height, pitch, buffer);
+ if (expect_accelerated_upload) {
+ buffer = drm_intel_bo_alloc_for_render(intel->bufmgr, "region",
+ pitch * cpp * height, 64);
+ } else {
+ buffer = drm_intel_bo_alloc(intel->bufmgr, "region",
+ pitch * cpp * height, 64);
+ }
+
+ region = intel_region_alloc_internal(intel, cpp, width, height,
+ pitch, buffer);
+
+ if (tiling != I915_TILING_NONE) {
+ assert(((pitch * cpp) & 127) == 0);
+ drm_intel_bo_set_tiling(buffer, &tiling, pitch * cpp);
+ drm_intel_bo_get_tiling(buffer, &region->tiling, &region->bit_6_swizzle);
+ }
+
+ return region;
}
struct intel_region *
@@ -152,7 +256,7 @@ void
intel_region_reference(struct intel_region **dst, struct intel_region *src)
{
if (src)
- DBG("%s %d\n", __FUNCTION__, src->refcount);
+ _DBG("%s %p %d\n", __FUNCTION__, src, src->refcount);
assert(*dst == NULL);
if (src) {
@@ -166,10 +270,12 @@ intel_region_release(struct intel_region **region_handle)
{
struct intel_region *region = *region_handle;
- if (region == NULL)
+ if (region == NULL) {
+ _DBG("%s NULL\n", __FUNCTION__);
return;
+ }
- DBG("%s %d\n", __FUNCTION__, region->refcount - 1);
+ _DBG("%s %p %d\n", __FUNCTION__, region, region->refcount - 1);
ASSERT(region->refcount > 0);
region->refcount--;
@@ -243,9 +349,7 @@ intel_region_data(struct intel_context *intel,
const void *src, GLuint src_pitch,
GLuint srcx, GLuint srcy, GLuint width, GLuint height)
{
- GLboolean locked = GL_FALSE;
-
- DBG("%s\n", __FUNCTION__);
+ _DBG("%s\n", __FUNCTION__);
if (intel == NULL)
return;
@@ -258,39 +362,33 @@ intel_region_data(struct intel_context *intel,
intel_region_cow(intel, dst);
}
- if (!intel->locked) {
- LOCK_HARDWARE(intel);
- locked = GL_TRUE;
- }
-
+ LOCK_HARDWARE(intel);
_mesa_copy_rect(intel_region_map(intel, dst) + dst_offset,
dst->cpp,
dst->pitch,
dstx, dsty, width, height, src, src_pitch, srcx, srcy);
intel_region_unmap(intel, dst);
-
- if (locked)
- UNLOCK_HARDWARE(intel);
-
+ UNLOCK_HARDWARE(intel);
}
/* Copy rectangular sub-regions. Need better logic about when to
* push buffers into AGP - will currently do so whenever possible.
*/
-void
+GLboolean
intel_region_copy(struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
struct intel_region *src,
GLuint src_offset,
- GLuint srcx, GLuint srcy, GLuint width, GLuint height)
+ GLuint srcx, GLuint srcy, GLuint width, GLuint height,
+ GLenum logicop)
{
- DBG("%s\n", __FUNCTION__);
+ _DBG("%s\n", __FUNCTION__);
if (intel == NULL)
- return;
+ return GL_FALSE;
if (dst->pbo) {
if (dstx == 0 &&
@@ -302,41 +400,12 @@ intel_region_copy(struct intel_context *intel,
assert(src->cpp == dst->cpp);
- intelEmitCopyBlit(intel,
- dst->cpp,
- src->pitch, src->buffer, src_offset, src->tiling,
- dst->pitch, dst->buffer, dst_offset, dst->tiling,
- srcx, srcy, dstx, dsty, width, height,
- GL_COPY);
-}
-
-/* Fill a rectangular sub-region. Need better logic about when to
- * push buffers into AGP - will currently do so whenever possible.
- */
-void
-intel_region_fill(struct intel_context *intel,
- struct intel_region *dst,
- GLuint dst_offset,
- GLuint dstx, GLuint dsty,
- GLuint width, GLuint height, GLuint color)
-{
- DBG("%s\n", __FUNCTION__);
-
- if (intel == NULL)
- return;
-
- if (dst->pbo) {
- if (dstx == 0 &&
- dsty == 0 && width == dst->pitch && height == dst->height)
- intel_region_release_pbo(intel, dst);
- else
- intel_region_cow(intel, dst);
- }
-
- intelEmitFillBlit(intel,
- dst->cpp,
- dst->pitch, dst->buffer, dst_offset, dst->tiling,
- dstx, dsty, width, height, color);
+ return intelEmitCopyBlit(intel,
+ dst->cpp,
+ src->pitch, src->buffer, src_offset, src->tiling,
+ dst->pitch, dst->buffer, dst_offset, dst->tiling,
+ srcx, srcy, dstx, dsty, width, height,
+ logicop);
}
/* Attach to a pbo, discarding our data. Effectively zero-copy upload
@@ -347,9 +416,13 @@ intel_region_attach_pbo(struct intel_context *intel,
struct intel_region *region,
struct intel_buffer_object *pbo)
{
+ dri_bo *buffer;
+
if (region->pbo == pbo)
return;
+ _DBG("%s %p %p\n", __FUNCTION__, region, pbo);
+
/* If there is already a pbo attached, break the cow tie now.
* Don't call intel_region_release_pbo() as that would
* unnecessarily allocate a new buffer we would have to immediately
@@ -365,10 +438,13 @@ intel_region_attach_pbo(struct intel_context *intel,
region->buffer = NULL;
}
+ /* make sure pbo has a buffer of its own */
+ buffer = intel_bufferobj_buffer(intel, pbo, INTEL_WRITE_FULL);
+
region->pbo = pbo;
region->pbo->region = region;
- dri_bo_reference(pbo->buffer);
- region->buffer = pbo->buffer;
+ dri_bo_reference(buffer);
+ region->buffer = buffer;
}
@@ -379,6 +455,7 @@ void
intel_region_release_pbo(struct intel_context *intel,
struct intel_region *region)
{
+ _DBG("%s %p\n", __FUNCTION__, region);
assert(region->buffer == region->pbo->buffer);
region->pbo->region = NULL;
region->pbo = NULL;
@@ -397,34 +474,27 @@ void
intel_region_cow(struct intel_context *intel, struct intel_region *region)
{
struct intel_buffer_object *pbo = region->pbo;
- GLboolean was_locked = intel->locked;
-
- if (intel == NULL)
- return;
+ GLboolean ok;
intel_region_release_pbo(intel, region);
assert(region->cpp * region->pitch * region->height == pbo->Base.Size);
- DBG("%s (%d bytes)\n", __FUNCTION__, pbo->Base.Size);
+ _DBG("%s %p (%d bytes)\n", __FUNCTION__, region, pbo->Base.Size);
/* Now blit from the texture buffer to the new buffer:
*/
- was_locked = intel->locked;
- if (!was_locked)
- LOCK_HARDWARE(intel);
-
- intelEmitCopyBlit(intel,
- region->cpp,
- region->pitch, region->buffer, 0, region->tiling,
- region->pitch, pbo->buffer, 0, region->tiling,
- 0, 0, 0, 0,
- region->pitch, region->height,
- GL_COPY);
-
- if (!was_locked)
- UNLOCK_HARDWARE(intel);
+ LOCK_HARDWARE(intel);
+ ok = intelEmitCopyBlit(intel,
+ region->cpp,
+ region->pitch, pbo->buffer, 0, region->tiling,
+ region->pitch, region->buffer, 0, region->tiling,
+ 0, 0, 0, 0,
+ region->pitch, region->height,
+ GL_COPY);
+ assert(ok);
+ UNLOCK_HARDWARE(intel);
}
dri_bo *
@@ -453,6 +523,10 @@ intel_recreate_static(struct intel_context *intel,
if (region == NULL) {
region = calloc(sizeof(*region), 1);
region->refcount = 1;
+ _DBG("%s creating new region %p\n", __FUNCTION__, region);
+ }
+ else {
+ _DBG("%s %p\n", __FUNCTION__, region);
}
if (intel->ctx.Visual.rgbBits == 24)
@@ -460,7 +534,8 @@ intel_recreate_static(struct intel_context *intel,
else
region->cpp = intel->ctx.Visual.rgbBits / 8;
region->pitch = intelScreen->pitch;
- region->height = intelScreen->height; /* needed? */
+ region->width = intelScreen->width;
+ region->height = intelScreen->height;
if (region->buffer != NULL) {
dri_bo_unreference(region->buffer);
diff --git a/src/mesa/drivers/dri/intel/intel_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h
index 4b120ba4ce..0d379bdc6e 100644
--- a/src/mesa/drivers/dri/intel/intel_regions.h
+++ b/src/mesa/drivers/dri/intel/intel_regions.h
@@ -73,8 +73,10 @@ struct intel_region
* copied by calling intel_reference_region().
*/
struct intel_region *intel_region_alloc(struct intel_context *intel,
- GLuint cpp, GLuint width,
- GLuint height, GLuint pitch);
+ uint32_t tiling,
+ GLuint cpp, GLuint width,
+ GLuint height, GLuint pitch,
+ GLboolean expect_accelerated_upload);
struct intel_region *
intel_region_alloc_for_handle(struct intel_context *intel,
@@ -108,21 +110,15 @@ void intel_region_data(struct intel_context *intel,
/* Copy rectangular sub-regions
*/
-void intel_region_copy(struct intel_context *intel,
- struct intel_region *dest,
- GLuint dest_offset,
- GLuint destx, GLuint desty,
- struct intel_region *src,
- GLuint src_offset,
- GLuint srcx, GLuint srcy, GLuint width, GLuint height);
-
-/* Fill a rectangular sub-region
- */
-void intel_region_fill(struct intel_context *intel,
- struct intel_region *dest,
- GLuint dest_offset,
- GLuint destx, GLuint desty,
- GLuint width, GLuint height, GLuint color);
+GLboolean
+intel_region_copy(struct intel_context *intel,
+ struct intel_region *dest,
+ GLuint dest_offset,
+ GLuint destx, GLuint desty,
+ struct intel_region *src,
+ GLuint src_offset,
+ GLuint srcx, GLuint srcy, GLuint width, GLuint height,
+ GLenum logicop);
/* Helpers for zerocopy uploads, particularly texture image uploads:
*/
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 2809fadd88..d547077929 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -29,27 +29,31 @@
#include "main/glheader.h"
#include "main/context.h"
#include "main/framebuffer.h"
-#include "main/matrix.h"
#include "main/renderbuffer.h"
-#include "main/simple_list.h"
+
#include "utils.h"
#include "vblank.h"
#include "xmlpool.h"
-
-#include "intel_screen.h"
-
+#include "intel_batchbuffer.h"
#include "intel_buffers.h"
-#include "intel_tex.h"
-#include "intel_span.h"
-#include "intel_fbo.h"
+#include "intel_bufmgr.h"
#include "intel_chipset.h"
+#include "intel_extensions.h"
+#include "intel_fbo.h"
+#include "intel_regions.h"
+#include "intel_swapbuffers.h"
+#include "intel_screen.h"
+#include "intel_span.h"
+#include "intel_tex.h"
#include "i915_drm.h"
#include "i830_dri.h"
-#include "intel_regions.h"
-#include "intel_batchbuffer.h"
-#include "intel_bufmgr.h"
+
+#define DRI_CONF_TEXTURE_TILING(def) \
+ DRI_CONF_OPT_BEGIN(texture_tiling, bool, def) \
+ DRI_CONF_DESC(en, "Enable texture tiling") \
+ DRI_CONF_OPT_END \
PUBLIC const char __driConfigOptions[] =
DRI_CONF_BEGIN
@@ -65,6 +69,17 @@ PUBLIC const char __driConfigOptions[] =
DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects")
DRI_CONF_DESC_END
DRI_CONF_OPT_END
+
+#ifdef I915
+ DRI_CONF_TEXTURE_TILING(false)
+#else
+ DRI_CONF_TEXTURE_TILING(true)
+#endif
+
+ DRI_CONF_OPT_BEGIN(early_z, bool, false)
+ DRI_CONF_DESC(en, "Enable early Z in classic mode (unstable, 945-only).")
+ DRI_CONF_OPT_END
+
DRI_CONF_SECTION_END
DRI_CONF_SECTION_QUALITY
DRI_CONF_FORCE_S3TC_ENABLE(false)
@@ -72,10 +87,12 @@ PUBLIC const char __driConfigOptions[] =
DRI_CONF_SECTION_END
DRI_CONF_SECTION_DEBUG
DRI_CONF_NO_RAST(false)
+ DRI_CONF_ALWAYS_FLUSH_BATCH(false)
+ DRI_CONF_ALWAYS_FLUSH_CACHE(false)
DRI_CONF_SECTION_END
DRI_CONF_END;
-const GLuint __driNConfigOptions = 6;
+const GLuint __driNConfigOptions = 10;
#ifdef USE_NEW_INTERFACE
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
@@ -160,7 +177,7 @@ intelPrintSAREA(const drm_i915_sarea_t * sarea)
* A number of the screen parameters are obtained/computed from
* information in the SAREA. This function updates those parameters.
*/
-void
+static void
intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
drm_i915_sarea_t * sarea)
{
@@ -210,6 +227,7 @@ static const __DRItexOffsetExtension intelTexOffsetExtension = {
static const __DRItexBufferExtension intelTexBufferExtension = {
{ __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
intelSetTexBuffer,
+ intelSetTexBuffer2,
};
static int
@@ -279,7 +297,7 @@ intel_get_param(__DRIscreenPrivate *psp, int param, int *value)
ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
if (ret) {
- fprintf(stderr, "drm_i915_getparam: %d\n", ret);
+ _mesa_warning(NULL, "drm_i915_getparam: %d", ret);
return GL_FALSE;
}
@@ -348,6 +366,7 @@ intelDestroyScreen(__DRIscreenPrivate * sPriv)
dri_bufmgr_destroy(intelScreen->bufmgr);
intelUnmapScreenRegions(intelScreen);
+ driDestroyOptionInfo(&intelScreen->optionCache);
FREE(intelScreen);
sPriv->private = NULL;
@@ -362,15 +381,13 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
__DRIdrawablePrivate * driDrawPriv,
const __GLcontextModes * mesaVis, GLboolean isPixmap)
{
- intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
-
if (isPixmap) {
return GL_FALSE; /* not implemented */
}
else {
GLboolean swStencil = (mesaVis->stencilBits > 0 &&
mesaVis->depthBits != 24);
- GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
+ GLenum rgbFormat;
struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer);
@@ -379,6 +396,13 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
_mesa_initialize_framebuffer(&intel_fb->Base, mesaVis);
+ if (mesaVis->redBits == 5)
+ rgbFormat = GL_RGB5;
+ else if (mesaVis->alphaBits == 0)
+ rgbFormat = GL_RGB8;
+ else
+ rgbFormat = GL_RGBA8;
+
/* setup the hardware-based renderbuffers */
intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat);
_mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
@@ -432,7 +456,31 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
static void
intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ struct intel_framebuffer *intel_fb = driDrawPriv->driverPrivate;
+ struct intel_renderbuffer *depth_rb;
+ struct intel_renderbuffer *stencil_rb;
+
+ if (intel_fb) {
+ if (intel_fb->color_rb[0]) {
+ intel_renderbuffer_set_region(intel_fb->color_rb[0], NULL);
+ }
+
+ if (intel_fb->color_rb[1]) {
+ intel_renderbuffer_set_region(intel_fb->color_rb[1], NULL);
+ }
+
+ depth_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);
+ if (depth_rb) {
+ intel_renderbuffer_set_region(depth_rb, NULL);
+ }
+
+ stencil_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL);
+ if (stencil_rb) {
+ intel_renderbuffer_set_region(stencil_rb, NULL);
+ }
+ }
+
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
@@ -513,8 +561,6 @@ intelFillInModes(__DRIscreenPrivate *psp,
__GLcontextModes *m;
unsigned depth_buffer_factor;
unsigned back_buffer_factor;
- GLenum fb_format;
- GLenum fb_type;
int i;
/* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
@@ -526,6 +572,7 @@ intelFillInModes(__DRIscreenPrivate *psp,
uint8_t depth_bits_array[3];
uint8_t stencil_bits_array[3];
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = 0;
depth_bits_array[1] = depth_bits;
@@ -542,22 +589,39 @@ intelFillInModes(__DRIscreenPrivate *psp,
stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
+ msaa_samples_array[0] = 0;
+
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
back_buffer_factor = (have_back_buffer) ? 3 : 1;
if (pixel_bits == 16) {
- fb_format = GL_RGB;
- fb_type = GL_UNSIGNED_SHORT_5_6_5;
+ configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+ depth_bits_array, stencil_bits_array,
+ depth_buffer_factor, back_buffer_modes,
+ back_buffer_factor,
+ msaa_samples_array, 1);
}
else {
- fb_format = GL_BGRA;
- fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ __DRIconfig **configs_a8r8g8b8;
+ __DRIconfig **configs_x8r8g8b8;
+
+ configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ depth_bits_array,
+ stencil_bits_array,
+ depth_buffer_factor,
+ back_buffer_modes,
+ back_buffer_factor,
+ msaa_samples_array, 1);
+ configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV,
+ depth_bits_array,
+ stencil_bits_array,
+ depth_buffer_factor,
+ back_buffer_modes,
+ back_buffer_factor,
+ msaa_samples_array, 1);
+ configs = driConcatConfigs(configs_a8r8g8b8, configs_x8r8g8b8);
}
- configs = driCreateConfigs(fb_format, fb_type,
- depth_bits_array, stencil_bits_array,
- depth_buffer_factor, back_buffer_modes,
- back_buffer_factor);
if (configs == NULL) {
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
__LINE__);
@@ -584,6 +648,7 @@ intel_init_bufmgr(intelScreenPrivate *intelScreen)
GLboolean gem_supported;
struct drm_i915_getparam gp;
__DRIscreenPrivate *spriv = intelScreen->driScrnPriv;
+ int num_fences = 0;
intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL;
@@ -613,10 +678,10 @@ intel_init_bufmgr(intelScreenPrivate *intelScreen)
/* Otherwise, use the classic buffer manager. */
if (intelScreen->bufmgr == NULL) {
if (gem_disable) {
- fprintf(stderr, "GEM disabled. Using classic.\n");
+ _mesa_warning(NULL, "GEM disabled. Using classic.");
} else {
- fprintf(stderr, "Failed to initialize GEM. "
- "Falling back to classic.\n");
+ _mesa_warning(NULL,
+ "Failed to initialize GEM. Falling back to classic.");
}
if (intelScreen->tex.size == 0) {
@@ -634,8 +699,10 @@ intel_init_bufmgr(intelScreenPrivate *intelScreen)
&intelScreen->sarea->last_dispatch);
}
- /* XXX bufmgr should be per-screen, not per-context */
- intelScreen->ttm = intelScreen->ttm;
+ if (intel_get_param(spriv, I915_PARAM_NUM_FENCES_AVAIL, &num_fences))
+ intelScreen->kernel_exec_fencing = !!num_fences;
+ else
+ intelScreen->kernel_exec_fencing = GL_FALSE;
return GL_TRUE;
}
@@ -719,6 +786,17 @@ static const
__DRIconfig **intelInitScreen2(__DRIscreenPrivate *psp)
{
intelScreenPrivate *intelScreen;
+ GLenum fb_format[3];
+ GLenum fb_type[3];
+ /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+ * support pageflipping at all.
+ */
+ static const GLenum back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+ };
+ uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1];
+ int color;
+ __DRIconfig **configs = NULL;
/* Calling driInitExtensions here, with a NULL context pointer,
* does not actually enable the extensions. It just makes sure
@@ -758,8 +836,71 @@ __DRIconfig **intelInitScreen2(__DRIscreenPrivate *psp)
intelScreen->irq_active = 1;
psp->extensions = intelScreenExtensions;
- return driConcatConfigs(intelFillInModes(psp, 16, 16, 0, 1),
- intelFillInModes(psp, 32, 24, 8, 1));
+ depth_bits[0] = 0;
+ stencil_bits[0] = 0;
+ depth_bits[1] = 16;
+ stencil_bits[1] = 0;
+ depth_bits[2] = 24;
+ stencil_bits[2] = 0;
+ depth_bits[3] = 24;
+ stencil_bits[3] = 8;
+
+ msaa_samples_array[0] = 0;
+
+ fb_format[0] = GL_RGB;
+ fb_type[0] = GL_UNSIGNED_SHORT_5_6_5;
+
+ fb_format[1] = GL_BGR;
+ fb_type[1] = GL_UNSIGNED_INT_8_8_8_8_REV;
+
+ fb_format[2] = GL_BGRA;
+ fb_type[2] = GL_UNSIGNED_INT_8_8_8_8_REV;
+
+ depth_bits[0] = 0;
+ stencil_bits[0] = 0;
+
+ for (color = 0; color < ARRAY_SIZE(fb_format); color++) {
+ __DRIconfig **new_configs;
+ int depth_factor;
+
+ /* With DRI2 right now, GetBuffers always returns a depth/stencil buffer
+ * with the same cpp as the drawable. So we can't support depth cpp !=
+ * color cpp currently.
+ */
+ if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) {
+ depth_bits[1] = 16;
+ stencil_bits[1] = 0;
+
+ depth_factor = 2;
+ } else {
+ depth_bits[1] = 24;
+ stencil_bits[1] = 0;
+ depth_bits[2] = 24;
+ stencil_bits[2] = 8;
+
+ depth_factor = 3;
+ }
+ new_configs = driCreateConfigs(fb_format[color], fb_type[color],
+ depth_bits,
+ stencil_bits,
+ depth_factor,
+ back_buffer_modes,
+ ARRAY_SIZE(back_buffer_modes),
+ msaa_samples_array,
+ ARRAY_SIZE(msaa_samples_array));
+ if (configs == NULL)
+ configs = new_configs;
+ else
+ configs = driConcatConfigs(configs, new_configs);
+ }
+
+ if (configs == NULL) {
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+ __LINE__);
+ return NULL;
+ }
+
+ return (const __DRIconfig **)configs;
}
const struct __DriverAPIRec driDriverAPI = {
diff --git a/src/mesa/drivers/dri/intel/intel_screen.h b/src/mesa/drivers/dri/intel/intel_screen.h
index fcd0d9c28c..a9b9e109a6 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.h
+++ b/src/mesa/drivers/dri/intel/intel_screen.h
@@ -79,6 +79,7 @@ typedef struct
GLboolean no_vbo;
int ttm;
dri_bufmgr *bufmgr;
+ GLboolean kernel_exec_fencing;
/**
* Configuration cache with default values for all contexts
@@ -92,10 +93,6 @@ extern GLboolean intelMapScreenRegions(__DRIscreenPrivate * sPriv);
extern void intelUnmapScreenRegions(intelScreenPrivate * intelScreen);
-extern void
-intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
- drm_i915_sarea_t * sarea);
-
extern void intelDestroyContext(__DRIcontextPrivate * driContextPriv);
extern GLboolean intelUnbindContext(__DRIcontextPrivate * driContextPriv);
@@ -105,11 +102,6 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
__DRIdrawablePrivate * driDrawPriv,
__DRIdrawablePrivate * driReadPriv);
-extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv);
-
-extern void
-intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h);
-
extern struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen);
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c
index d9315043e6..1e73943457 100644
--- a/src/mesa/drivers/dri/intel/intel_span.c
+++ b/src/mesa/drivers/dri/intel/intel_span.c
@@ -29,6 +29,7 @@
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/colormac.h"
+#include "main/texformat.h"
#include "intel_buffers.h"
#include "intel_fbo.h"
@@ -131,6 +132,18 @@ pwrite_8(struct intel_renderbuffer *irb, uint32_t offset, uint8_t val)
dri_bo_subdata(irb->region->buffer, offset, 1, &val);
}
+static uint32_t
+z24s8_to_s8z24(uint32_t val)
+{
+ return (val << 24) | (val >> 8);
+}
+
+static uint32_t
+s8z24_to_z24s8(uint32_t val)
+{
+ return (val >> 24) | (val << 8);
+}
+
static uint32_t no_tile_swizzle(struct intel_renderbuffer *irb,
int x, int y)
{
@@ -150,7 +163,7 @@ static uint32_t x_tile_swizzle(struct intel_renderbuffer *irb,
int x_tile_number, y_tile_number;
int tile_off, tile_base;
- tile_stride = (irb->pfPitch * irb->region->cpp) << 3;
+ tile_stride = (irb->region->pitch * irb->region->cpp) << 3;
xbyte = x * irb->region->cpp;
@@ -190,7 +203,7 @@ static uint32_t x_tile_swizzle(struct intel_renderbuffer *irb,
printf("(%d,%d) -> %d + %d = %d (pitch = %d, tstride = %d)\n",
x, y, tile_off, tile_base,
tile_off + tile_base,
- irb->pfPitch, tile_stride);
+ irb->region->pitch, tile_stride);
#endif
return tile_base + tile_off;
@@ -205,7 +218,7 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
int x_tile_number, y_tile_number;
int tile_off, tile_base;
- tile_stride = (irb->pfPitch * irb->region->cpp) << 5;
+ tile_stride = (irb->region->pitch * irb->region->cpp) << 5;
xbyte = x * irb->region->cpp;
@@ -255,8 +268,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
#define LOCAL_VARS \
struct intel_context *intel = intel_context(ctx); \
struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
- const GLint yScale = irb->RenderToTexture ? 1 : -1; \
- const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1; \
+ const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \
+ const GLint yBias = ctx->DrawBuffer->Name ? 0 : irb->Base.Height - 1;\
unsigned int num_cliprects; \
struct drm_clip_rect *cliprects; \
int x_off, y_off; \
@@ -293,107 +306,51 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
#define X_TILE(_X, _Y) x_tile_swizzle(irb, (_X) + x_off, (_Y) + y_off)
#define Y_TILE(_X, _Y) y_tile_swizzle(irb, (_X) + x_off, (_Y) + y_off)
-/* 16 bit, RGB565 color spanline and pixel functions
- */
-#define SPANTMP_PIXEL_FMT GL_RGB
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
-
-#define TAG(x) intel##x##_RGB565
-#define TAG2(x,y) intel##x##_RGB565##y
-#define GET_VALUE(X, Y) pread_16(irb, NO_TILE(X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_16(irb, NO_TILE(X, Y), V)
-#include "spantmp2.h"
-
-/* 32 bit, ARGB8888 color spanline and pixel functions
- */
-#define SPANTMP_PIXEL_FMT GL_BGRA
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
-#define TAG(x) intel##x##_ARGB8888
-#define TAG2(x,y) intel##x##_ARGB8888##y
-#define GET_VALUE(X, Y) pread_32(irb, NO_TILE(X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_32(irb, NO_TILE(X, Y), V)
-#include "spantmp2.h"
-
-/* 32 bit, xRGB8888 color spanline and pixel functions
- */
-#define SPANTMP_PIXEL_FMT GL_BGRA
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
-#define TAG(x) intel##x##_xRGB8888
-#define TAG2(x,y) intel##x##_xRGB8888##y
-#define GET_VALUE(X, Y) pread_xrgb8888(irb, NO_TILE(X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_xrgb8888(irb, NO_TILE(X, Y), V)
-#include "spantmp2.h"
-
-/* 16 bit RGB565 color tile spanline and pixel functions
- */
-
-#define SPANTMP_PIXEL_FMT GL_RGB
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
-
-#define TAG(x) intel_XTile_##x##_RGB565
-#define TAG2(x,y) intel_XTile_##x##_RGB565##y
-#define GET_VALUE(X, Y) pread_16(irb, X_TILE(X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_16(irb, X_TILE(X, Y), V)
-#include "spantmp2.h"
-
-#define SPANTMP_PIXEL_FMT GL_RGB
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
-
-#define TAG(x) intel_YTile_##x##_RGB565
-#define TAG2(x,y) intel_YTile_##x##_RGB565##y
-#define GET_VALUE(X, Y) pread_16(irb, Y_TILE(X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_16(irb, Y_TILE(X, Y), V)
-#include "spantmp2.h"
-
-/* 32 bit ARGB888 color tile spanline and pixel functions
- */
-
-#define SPANTMP_PIXEL_FMT GL_BGRA
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
-#define TAG(x) intel_XTile_##x##_ARGB8888
-#define TAG2(x,y) intel_XTile_##x##_ARGB8888##y
-#define GET_VALUE(X, Y) pread_32(irb, X_TILE(X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_32(irb, X_TILE(X, Y), V)
-#include "spantmp2.h"
-
-#define SPANTMP_PIXEL_FMT GL_BGRA
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
-#define TAG(x) intel_YTile_##x##_ARGB8888
-#define TAG2(x,y) intel_YTile_##x##_ARGB8888##y
-#define GET_VALUE(X, Y) pread_32(irb, Y_TILE(X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_32(irb, Y_TILE(X, Y), V)
-#include "spantmp2.h"
-
-/* 32 bit xRGB888 color tile spanline and pixel functions
- */
-
-#define SPANTMP_PIXEL_FMT GL_BGRA
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
-#define TAG(x) intel_XTile_##x##_xRGB8888
-#define TAG2(x,y) intel_XTile_##x##_xRGB8888##y
-#define GET_VALUE(X, Y) pread_xrgb8888(irb, X_TILE(X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_xrgb8888(irb, X_TILE(X, Y), V)
-#include "spantmp2.h"
-
-#define SPANTMP_PIXEL_FMT GL_BGRA
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
-#define TAG(x) intel_YTile_##x##_xRGB8888
-#define TAG2(x,y) intel_YTile_##x##_xRGB8888##y
-#define GET_VALUE(X, Y) pread_xrgb8888(irb, Y_TILE(X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_xrgb8888(irb, Y_TILE(X, Y), V)
-#include "spantmp2.h"
+/* r5g6b5 color span and pixel functions */
+#define INTEL_PIXEL_FMT GL_RGB
+#define INTEL_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
+#define INTEL_READ_VALUE(offset) pread_16(irb, offset)
+#define INTEL_WRITE_VALUE(offset, v) pwrite_16(irb, offset, v)
+#define INTEL_TAG(x) x##_RGB565
+#include "intel_spantmp.h"
+
+/* a4r4g4b4 color span and pixel functions */
+#define INTEL_PIXEL_FMT GL_BGRA
+#define INTEL_PIXEL_TYPE GL_UNSIGNED_SHORT_4_4_4_4_REV
+#define INTEL_READ_VALUE(offset) pread_16(irb, offset)
+#define INTEL_WRITE_VALUE(offset, v) pwrite_16(irb, offset, v)
+#define INTEL_TAG(x) x##_ARGB4444
+#include "intel_spantmp.h"
+
+/* a1r5g5b5 color span and pixel functions */
+#define INTEL_PIXEL_FMT GL_BGRA
+#define INTEL_PIXEL_TYPE GL_UNSIGNED_SHORT_1_5_5_5_REV
+#define INTEL_READ_VALUE(offset) pread_16(irb, offset)
+#define INTEL_WRITE_VALUE(offset, v) pwrite_16(irb, offset, v)
+#define INTEL_TAG(x) x##_ARGB1555
+#include "intel_spantmp.h"
+
+/* a8r8g8b8 color span and pixel functions */
+#define INTEL_PIXEL_FMT GL_BGRA
+#define INTEL_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
+#define INTEL_READ_VALUE(offset) pread_32(irb, offset)
+#define INTEL_WRITE_VALUE(offset, v) pwrite_32(irb, offset, v)
+#define INTEL_TAG(x) x##_ARGB8888
+#include "intel_spantmp.h"
+
+/* x8r8g8b8 color span and pixel functions */
+#define INTEL_PIXEL_FMT GL_BGRA
+#define INTEL_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
+#define INTEL_READ_VALUE(offset) pread_xrgb8888(irb, offset)
+#define INTEL_WRITE_VALUE(offset, v) pwrite_xrgb8888(irb, offset, v)
+#define INTEL_TAG(x) x##_xRGB8888
+#include "intel_spantmp.h"
#define LOCAL_DEPTH_VARS \
struct intel_context *intel = intel_context(ctx); \
struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
- const GLint yScale = irb->RenderToTexture ? 1 : -1; \
- const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1; \
+ const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \
+ const GLint yBias = ctx->DrawBuffer->Name ? 0 : irb->Base.Height - 1;\
unsigned int num_cliprects; \
struct drm_clip_rect *cliprects; \
int x_off, y_off; \
@@ -402,98 +359,26 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
-/**
- ** 16-bit depthbuffer functions.
- **/
-#define VALUE_TYPE GLushort
-#define WRITE_DEPTH(_x, _y, d) pwrite_16(irb, NO_TILE(_x, _y), d)
-#define READ_DEPTH(d, _x, _y) d = pread_16(irb, NO_TILE(_x, _y))
-#define TAG(x) intel##x##_z16
-#include "depthtmp.h"
-
+/* z16 depthbuffer functions. */
+#define INTEL_VALUE_TYPE GLushort
+#define INTEL_WRITE_DEPTH(offset, d) pwrite_16(irb, offset, d)
+#define INTEL_READ_DEPTH(offset) pread_16(irb, offset)
+#define INTEL_TAG(name) name##_z16
+#include "intel_depthtmp.h"
-/**
- ** 16-bit x tile depthbuffer functions.
- **/
-#define VALUE_TYPE GLushort
-#define WRITE_DEPTH(_x, _y, d) pwrite_16(irb, X_TILE(_x, _y), d)
-#define READ_DEPTH(d, _x, _y) d = pread_16(irb, X_TILE(_x, _y))
-#define TAG(x) intel_XTile_##x##_z16
-#include "depthtmp.h"
+/* z24 depthbuffer functions. */
+#define INTEL_VALUE_TYPE GLuint
+#define INTEL_WRITE_DEPTH(offset, d) pwrite_32(irb, offset, d)
+#define INTEL_READ_DEPTH(offset) pread_32(irb, offset)
+#define INTEL_TAG(name) name##_z24
+#include "intel_depthtmp.h"
-/**
- ** 16-bit y tile depthbuffer functions.
- **/
-#define VALUE_TYPE GLushort
-#define WRITE_DEPTH(_x, _y, d) pwrite_16(irb, Y_TILE(_x, _y), d)
-#define READ_DEPTH(d, _x, _y) d = pread_16(irb, Y_TILE(_x, _y))
-#define TAG(x) intel_YTile_##x##_z16
-#include "depthtmp.h"
-
-
-/**
- ** 24/8-bit interleaved depth/stencil functions
- ** Note: we're actually reading back combined depth+stencil values.
- ** The wrappers in main/depthstencil.c are used to extract the depth
- ** and stencil values.
- **/
-#define VALUE_TYPE GLuint
-
-/* Change ZZZS -> SZZZ */
-#define WRITE_DEPTH(_x, _y, d) \
- pwrite_32(irb, NO_TILE(_x, _y), ((d) >> 8) | ((d) << 24))
-
-/* Change SZZZ -> ZZZS */
-#define READ_DEPTH( d, _x, _y ) { \
- GLuint tmp = pread_32(irb, NO_TILE(_x, _y)); \
- d = (tmp << 8) | (tmp >> 24); \
-}
-
-#define TAG(x) intel##x##_z24_s8
-#include "depthtmp.h"
-
-
-/**
- ** 24/8-bit x-tile interleaved depth/stencil functions
- ** Note: we're actually reading back combined depth+stencil values.
- ** The wrappers in main/depthstencil.c are used to extract the depth
- ** and stencil values.
- **/
-#define VALUE_TYPE GLuint
-
-/* Change ZZZS -> SZZZ */
-#define WRITE_DEPTH(_x, _y, d) \
- pwrite_32(irb, X_TILE(_x, _y), ((d) >> 8) | ((d) << 24))
-
-/* Change SZZZ -> ZZZS */
-#define READ_DEPTH( d, _x, _y ) { \
- GLuint tmp = pread_32(irb, X_TILE(_x, _y)); \
- d = (tmp << 8) | (tmp >> 24); \
-}
-
-#define TAG(x) intel_XTile_##x##_z24_s8
-#include "depthtmp.h"
-
-/**
- ** 24/8-bit y-tile interleaved depth/stencil functions
- ** Note: we're actually reading back combined depth+stencil values.
- ** The wrappers in main/depthstencil.c are used to extract the depth
- ** and stencil values.
- **/
-#define VALUE_TYPE GLuint
-
-/* Change ZZZS -> SZZZ */
-#define WRITE_DEPTH(_x, _y, d) \
- pwrite_32(irb, Y_TILE(_x, _y), ((d) >> 8) | ((d) << 24))
-
-/* Change SZZZ -> ZZZS */
-#define READ_DEPTH( d, _x, _y ) { \
- GLuint tmp = pread_32(irb, Y_TILE(_x, _y)); \
- d = (tmp << 8) | (tmp >> 24); \
-}
-
-#define TAG(x) intel_YTile_##x##_z24_s8
-#include "depthtmp.h"
+/* z24s8 depthbuffer functions. */
+#define INTEL_VALUE_TYPE GLuint
+#define INTEL_WRITE_DEPTH(offset, d) pwrite_32(irb, offset, z24s8_to_s8z24(d))
+#define INTEL_READ_DEPTH(offset) s8z24_to_z24s8(pread_32(irb, offset))
+#define INTEL_TAG(name) name##_z24_s8
+#include "intel_depthtmp.h"
/**
@@ -528,8 +413,6 @@ intel_renderbuffer_map(struct intel_context *intel, struct gl_renderbuffer *rb)
if (irb == NULL || irb->region == NULL)
return;
- irb->pfPitch = irb->region->pitch;
-
intel_set_span_functions(intel, rb);
}
@@ -543,7 +426,6 @@ intel_renderbuffer_unmap(struct intel_context *intel,
return;
clear_span_cache(irb);
- irb->pfPitch = 0;
rb->GetRow = NULL;
rb->PutRow = NULL;
@@ -562,23 +444,32 @@ intel_renderbuffer_unmap(struct intel_context *intel,
* _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields.
*/
static void
-intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
+intel_map_unmap_framebuffer(struct intel_context *intel,
+ struct gl_framebuffer *fb,
+ GLboolean map)
{
GLcontext *ctx = &intel->ctx;
GLuint i, j;
- /* color draw buffers */
- for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers; j++) {
+ /* color buffers */
+ if (fb == ctx->DrawBuffer) {
+ for (j = 0; j < fb->_NumColorDrawBuffers; j++) {
+ if (map)
+ intel_renderbuffer_map(intel, fb->_ColorDrawBuffers[j]);
+ else
+ intel_renderbuffer_unmap(intel, fb->_ColorDrawBuffers[j]);
+ }
+ } else {
if (map)
- intel_renderbuffer_map(intel, ctx->DrawBuffer->_ColorDrawBuffers[j]);
+ intel_renderbuffer_map(intel, fb->_ColorReadBuffer);
else
- intel_renderbuffer_unmap(intel, ctx->DrawBuffer->_ColorDrawBuffers[j]);
+ intel_renderbuffer_unmap(intel, fb->_ColorReadBuffer);
}
/* check for render to textures */
for (i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att =
- ctx->DrawBuffer->Attachment + i;
+ fb->Attachment + i;
struct gl_texture_object *tex = att->Texture;
if (tex) {
/* render to texture */
@@ -590,36 +481,28 @@ intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
}
}
- /* color read buffers */
- if (map)
- intel_renderbuffer_map(intel, ctx->ReadBuffer->_ColorReadBuffer);
- else
- intel_renderbuffer_unmap(intel, ctx->ReadBuffer->_ColorReadBuffer);
-
/* depth buffer (Note wrapper!) */
- if (ctx->DrawBuffer->_DepthBuffer) {
+ if (fb->_DepthBuffer) {
if (map)
- intel_renderbuffer_map(intel, ctx->DrawBuffer->_DepthBuffer->Wrapped);
+ intel_renderbuffer_map(intel, fb->_DepthBuffer->Wrapped);
else
intel_renderbuffer_unmap(intel,
- ctx->DrawBuffer->_DepthBuffer->Wrapped);
+ fb->_DepthBuffer->Wrapped);
}
/* stencil buffer (Note wrapper!) */
- if (ctx->DrawBuffer->_StencilBuffer) {
+ if (fb->_StencilBuffer) {
if (map)
intel_renderbuffer_map(intel,
- ctx->DrawBuffer->_StencilBuffer->Wrapped);
+ fb->_StencilBuffer->Wrapped);
else
intel_renderbuffer_unmap(intel,
- ctx->DrawBuffer->_StencilBuffer->Wrapped);
+ fb->_StencilBuffer->Wrapped);
}
}
-
-
/**
- * Prepare for softare rendering. Map current read/draw framebuffers'
+ * Prepare for software rendering. Map current read/draw framebuffers'
* renderbuffes and all currently bound texture objects.
*
* Old note: Moved locking out to get reasonable span performance.
@@ -640,11 +523,12 @@ intelSpanRenderStart(GLcontext * ctx)
}
}
- intel_map_unmap_buffers(intel, GL_TRUE);
+ intel_map_unmap_framebuffer(intel, ctx->DrawBuffer, GL_TRUE);
+ intel_map_unmap_framebuffer(intel, ctx->ReadBuffer, GL_TRUE);
}
/**
- * Called when done softare rendering. Unmap the buffers we mapped in
+ * Called when done software rendering. Unmap the buffers we mapped in
* the above function.
*/
void
@@ -662,7 +546,8 @@ intelSpanRenderFinish(GLcontext * ctx)
}
}
- intel_map_unmap_buffers(intel, GL_FALSE);
+ intel_map_unmap_framebuffer(intel, ctx->DrawBuffer, GL_FALSE);
+ intel_map_unmap_framebuffer(intel, ctx->ReadBuffer, GL_FALSE);
UNLOCK_HARDWARE(intel);
}
@@ -696,8 +581,8 @@ intel_set_span_functions(struct intel_context *intel,
else
tiling = I915_TILING_NONE;
- if (rb->_ActualFormat == GL_RGB5) {
- /* 565 RGB */
+ switch (irb->texformat->MesaFormat) {
+ case MESA_FORMAT_RGB565:
switch (tiling) {
case I915_TILING_NONE:
default:
@@ -710,38 +595,67 @@ intel_set_span_functions(struct intel_context *intel,
intel_YTile_InitPointers_RGB565(rb);
break;
}
- }
- else if (rb->_ActualFormat == GL_RGB8) {
- /* 8888 RGBx */
+ break;
+ case MESA_FORMAT_ARGB4444:
switch (tiling) {
case I915_TILING_NONE:
default:
- intelInitPointers_xRGB8888(rb);
+ intelInitPointers_ARGB4444(rb);
break;
case I915_TILING_X:
- intel_XTile_InitPointers_xRGB8888(rb);
+ intel_XTile_InitPointers_ARGB4444(rb);
break;
case I915_TILING_Y:
- intel_YTile_InitPointers_xRGB8888(rb);
+ intel_YTile_InitPointers_ARGB4444(rb);
break;
}
- }
- else if (rb->_ActualFormat == GL_RGBA8) {
- /* 8888 RGBA */
+ break;
+ case MESA_FORMAT_ARGB1555:
switch (tiling) {
case I915_TILING_NONE:
default:
- intelInitPointers_ARGB8888(rb);
+ intelInitPointers_ARGB1555(rb);
break;
case I915_TILING_X:
- intel_XTile_InitPointers_ARGB8888(rb);
+ intel_XTile_InitPointers_ARGB1555(rb);
break;
case I915_TILING_Y:
- intel_YTile_InitPointers_ARGB8888(rb);
+ intel_YTile_InitPointers_ARGB1555(rb);
break;
}
- }
- else if (rb->_ActualFormat == GL_DEPTH_COMPONENT16) {
+ break;
+ case MESA_FORMAT_ARGB8888:
+ if (rb->AlphaBits == 0) { /* XXX: Need xRGB8888 Mesa format */
+ /* 8888 RGBx */
+ switch (tiling) {
+ case I915_TILING_NONE:
+ default:
+ intelInitPointers_xRGB8888(rb);
+ break;
+ case I915_TILING_X:
+ intel_XTile_InitPointers_xRGB8888(rb);
+ break;
+ case I915_TILING_Y:
+ intel_YTile_InitPointers_xRGB8888(rb);
+ break;
+ }
+ } else {
+ /* 8888 RGBA */
+ switch (tiling) {
+ case I915_TILING_NONE:
+ default:
+ intelInitPointers_ARGB8888(rb);
+ break;
+ case I915_TILING_X:
+ intel_XTile_InitPointers_ARGB8888(rb);
+ break;
+ case I915_TILING_Y:
+ intel_YTile_InitPointers_ARGB8888(rb);
+ break;
+ }
+ }
+ break;
+ case MESA_FORMAT_Z16:
switch (tiling) {
case I915_TILING_NONE:
default:
@@ -754,38 +668,60 @@ intel_set_span_functions(struct intel_context *intel,
intel_YTile_InitDepthPointers_z16(rb);
break;
}
- }
- else if (rb->_ActualFormat == GL_DEPTH_COMPONENT24 || /* XXX FBO remove */
- rb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) {
- switch (tiling) {
- case I915_TILING_NONE:
- default:
- intelInitDepthPointers_z24_s8(rb);
- break;
- case I915_TILING_X:
- intel_XTile_InitDepthPointers_z24_s8(rb);
- break;
- case I915_TILING_Y:
- intel_YTile_InitDepthPointers_z24_s8(rb);
- break;
- }
- }
- else if (rb->_ActualFormat == GL_STENCIL_INDEX8_EXT) {
- switch (tiling) {
- case I915_TILING_NONE:
- default:
- intelInitStencilPointers_z24_s8(rb);
- break;
- case I915_TILING_X:
- intel_XTile_InitStencilPointers_z24_s8(rb);
- break;
- case I915_TILING_Y:
- intel_YTile_InitStencilPointers_z24_s8(rb);
- break;
+ break;
+ case MESA_FORMAT_S8_Z24:
+ /* There are a few different ways SW asks us to access the S8Z24 data:
+ * Z24 depth-only depth reads
+ * S8Z24 depth reads
+ * S8Z24 stencil reads.
+ */
+ if (rb->_ActualFormat == GL_DEPTH_COMPONENT24) {
+ switch (tiling) {
+ case I915_TILING_NONE:
+ default:
+ intelInitDepthPointers_z24(rb);
+ break;
+ case I915_TILING_X:
+ intel_XTile_InitDepthPointers_z24(rb);
+ break;
+ case I915_TILING_Y:
+ intel_YTile_InitDepthPointers_z24(rb);
+ break;
+ }
+ } else if (rb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) {
+ switch (tiling) {
+ case I915_TILING_NONE:
+ default:
+ intelInitDepthPointers_z24_s8(rb);
+ break;
+ case I915_TILING_X:
+ intel_XTile_InitDepthPointers_z24_s8(rb);
+ break;
+ case I915_TILING_Y:
+ intel_YTile_InitDepthPointers_z24_s8(rb);
+ break;
+ }
+ } else if (rb->_ActualFormat == GL_STENCIL_INDEX8_EXT) {
+ switch (tiling) {
+ case I915_TILING_NONE:
+ default:
+ intelInitStencilPointers_z24_s8(rb);
+ break;
+ case I915_TILING_X:
+ intel_XTile_InitStencilPointers_z24_s8(rb);
+ break;
+ case I915_TILING_Y:
+ intel_YTile_InitStencilPointers_z24_s8(rb);
+ break;
+ }
+ } else {
+ _mesa_problem(NULL,
+ "Unexpected ActualFormat in intelSetSpanFunctions");
}
- }
- else {
+ break;
+ default:
_mesa_problem(NULL,
- "Unexpected _ActualFormat in intelSetSpanFunctions");
+ "Unexpected MesaFormat in intelSetSpanFunctions");
+ break;
}
}
diff --git a/src/mesa/drivers/dri/intel/intel_spantmp.h b/src/mesa/drivers/dri/intel/intel_spantmp.h
new file mode 100644
index 0000000000..ead0b1c168
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_spantmp.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/**
+ * Wrapper around the spantmp.h macrofest to generate spans code for
+ * all the tiling styles.
+ */
+
+#define SPANTMP_PIXEL_FMT INTEL_PIXEL_FMT
+#define SPANTMP_PIXEL_TYPE INTEL_PIXEL_TYPE
+#define PUT_VALUE(_x, _y, v) INTEL_WRITE_VALUE(NO_TILE(_x, _y), v)
+#define GET_VALUE(_x, _y) INTEL_READ_VALUE(NO_TILE(_x, _y))
+#define TAG(x) INTEL_TAG(intel##x)
+#define TAG2(x, y) INTEL_TAG(intel##x)##y
+#include "spantmp2.h"
+
+#define SPANTMP_PIXEL_FMT INTEL_PIXEL_FMT
+#define SPANTMP_PIXEL_TYPE INTEL_PIXEL_TYPE
+#define PUT_VALUE(_x, _y, v) INTEL_WRITE_VALUE(X_TILE(_x, _y), v)
+#define GET_VALUE(_x, _y) INTEL_READ_VALUE(X_TILE(_x, _y))
+#define TAG(x) INTEL_TAG(intel_XTile_##x)
+#define TAG2(x, y) INTEL_TAG(intel_XTile_##x)##y
+#include "spantmp2.h"
+
+#define SPANTMP_PIXEL_FMT INTEL_PIXEL_FMT
+#define SPANTMP_PIXEL_TYPE INTEL_PIXEL_TYPE
+#define PUT_VALUE(_x, _y, v) INTEL_WRITE_VALUE(X_TILE(_x, _y), v)
+#define GET_VALUE(_x, _y) INTEL_READ_VALUE(X_TILE(_x, _y))
+#define TAG(x) INTEL_TAG(intel_YTile_##x)
+#define TAG2(x, y) INTEL_TAG(intel_YTile_##x)##y
+#include "spantmp2.h"
+
+#undef INTEL_PIXEL_FMT
+#undef INTEL_PIXEL_TYPE
+#undef INTEL_WRITE_VALUE
+#undef INTEL_READ_VALUE
+#undef INTEL_TAG
diff --git a/src/mesa/drivers/dri/intel/intel_state.c b/src/mesa/drivers/dri/intel/intel_state.c
new file mode 100644
index 0000000000..4ee742377d
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_state.c
@@ -0,0 +1,233 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "main/colormac.h"
+#include "main/dd.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_regions.h"
+#include "swrast/swrast.h"
+
+int
+intel_translate_shadow_compare_func(GLenum func)
+{
+ switch (func) {
+ case GL_NEVER:
+ return COMPAREFUNC_ALWAYS;
+ case GL_LESS:
+ return COMPAREFUNC_LEQUAL;
+ case GL_LEQUAL:
+ return COMPAREFUNC_LESS;
+ case GL_GREATER:
+ return COMPAREFUNC_GEQUAL;
+ case GL_GEQUAL:
+ return COMPAREFUNC_GREATER;
+ case GL_NOTEQUAL:
+ return COMPAREFUNC_EQUAL;
+ case GL_EQUAL:
+ return COMPAREFUNC_NOTEQUAL;
+ case GL_ALWAYS:
+ return COMPAREFUNC_NEVER;
+ }
+
+ fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func);
+ return COMPAREFUNC_NEVER;
+}
+
+int
+intel_translate_compare_func(GLenum func)
+{
+ switch (func) {
+ case GL_NEVER:
+ return COMPAREFUNC_NEVER;
+ case GL_LESS:
+ return COMPAREFUNC_LESS;
+ case GL_LEQUAL:
+ return COMPAREFUNC_LEQUAL;
+ case GL_GREATER:
+ return COMPAREFUNC_GREATER;
+ case GL_GEQUAL:
+ return COMPAREFUNC_GEQUAL;
+ case GL_NOTEQUAL:
+ return COMPAREFUNC_NOTEQUAL;
+ case GL_EQUAL:
+ return COMPAREFUNC_EQUAL;
+ case GL_ALWAYS:
+ return COMPAREFUNC_ALWAYS;
+ }
+
+ fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func);
+ return COMPAREFUNC_ALWAYS;
+}
+
+int
+intel_translate_stencil_op(GLenum op)
+{
+ switch (op) {
+ case GL_KEEP:
+ return STENCILOP_KEEP;
+ case GL_ZERO:
+ return STENCILOP_ZERO;
+ case GL_REPLACE:
+ return STENCILOP_REPLACE;
+ case GL_INCR:
+ return STENCILOP_INCRSAT;
+ case GL_DECR:
+ return STENCILOP_DECRSAT;
+ case GL_INCR_WRAP:
+ return STENCILOP_INCR;
+ case GL_DECR_WRAP:
+ return STENCILOP_DECR;
+ case GL_INVERT:
+ return STENCILOP_INVERT;
+ default:
+ return STENCILOP_ZERO;
+ }
+}
+
+int
+intel_translate_blend_factor(GLenum factor)
+{
+ switch (factor) {
+ case GL_ZERO:
+ return BLENDFACT_ZERO;
+ case GL_SRC_ALPHA:
+ return BLENDFACT_SRC_ALPHA;
+ case GL_ONE:
+ return BLENDFACT_ONE;
+ case GL_SRC_COLOR:
+ return BLENDFACT_SRC_COLR;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return BLENDFACT_INV_SRC_COLR;
+ case GL_DST_COLOR:
+ return BLENDFACT_DST_COLR;
+ case GL_ONE_MINUS_DST_COLOR:
+ return BLENDFACT_INV_DST_COLR;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return BLENDFACT_INV_SRC_ALPHA;
+ case GL_DST_ALPHA:
+ return BLENDFACT_DST_ALPHA;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return BLENDFACT_INV_DST_ALPHA;
+ case GL_SRC_ALPHA_SATURATE:
+ return BLENDFACT_SRC_ALPHA_SATURATE;
+ case GL_CONSTANT_COLOR:
+ return BLENDFACT_CONST_COLOR;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ return BLENDFACT_INV_CONST_COLOR;
+ case GL_CONSTANT_ALPHA:
+ return BLENDFACT_CONST_ALPHA;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ return BLENDFACT_INV_CONST_ALPHA;
+ }
+
+ fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, factor);
+ return BLENDFACT_ZERO;
+}
+
+int
+intel_translate_logic_op(GLenum opcode)
+{
+ switch (opcode) {
+ case GL_CLEAR:
+ return LOGICOP_CLEAR;
+ case GL_AND:
+ return LOGICOP_AND;
+ case GL_AND_REVERSE:
+ return LOGICOP_AND_RVRSE;
+ case GL_COPY:
+ return LOGICOP_COPY;
+ case GL_COPY_INVERTED:
+ return LOGICOP_COPY_INV;
+ case GL_AND_INVERTED:
+ return LOGICOP_AND_INV;
+ case GL_NOOP:
+ return LOGICOP_NOOP;
+ case GL_XOR:
+ return LOGICOP_XOR;
+ case GL_OR:
+ return LOGICOP_OR;
+ case GL_OR_INVERTED:
+ return LOGICOP_OR_INV;
+ case GL_NOR:
+ return LOGICOP_NOR;
+ case GL_EQUIV:
+ return LOGICOP_EQUIV;
+ case GL_INVERT:
+ return LOGICOP_INV;
+ case GL_OR_REVERSE:
+ return LOGICOP_OR_RVRSE;
+ case GL_NAND:
+ return LOGICOP_NAND;
+ case GL_SET:
+ return LOGICOP_SET;
+ default:
+ return LOGICOP_SET;
+ }
+}
+
+
+static void
+intelClearColor(GLcontext *ctx, const GLfloat color[4])
+{
+ struct intel_context *intel = intel_context(ctx);
+ GLubyte clear[4];
+
+ CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);
+
+ /* compute both 32 and 16-bit clear values */
+ intel->ClearColor8888 = INTEL_PACKCOLOR8888(clear[0], clear[1],
+ clear[2], clear[3]);
+ intel->ClearColor565 = INTEL_PACKCOLOR565(clear[0], clear[1], clear[2]);
+}
+
+
+/* Fallback to swrast for select and feedback.
+ */
+static void
+intelRenderMode(GLcontext *ctx, GLenum mode)
+{
+ struct intel_context *intel = intel_context(ctx);
+ FALLBACK(intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER));
+}
+
+
+void
+intelInitStateFuncs(struct dd_function_table *functions)
+{
+ functions->RenderMode = intelRenderMode;
+ functions->ClearColor = intelClearColor;
+}
diff --git a/src/mesa/drivers/dri/intel/intel_swapbuffers.c b/src/mesa/drivers/dri/intel/intel_swapbuffers.c
new file mode 100644
index 0000000000..7d035b9f6e
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_swapbuffers.c
@@ -0,0 +1,248 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "intel_blit.h"
+#include "intel_buffers.h"
+#include "intel_swapbuffers.h"
+#include "intel_fbo.h"
+#include "intel_batchbuffer.h"
+#include "drirenderbuffer.h"
+#include "vblank.h"
+#include "i915_drm.h"
+
+
+
+/*
+ * Correct a drawablePrivate's set of vblank flags WRT the current context.
+ * When considering multiple crtcs.
+ */
+GLuint
+intelFixupVblank(struct intel_context *intel, __DRIdrawablePrivate *dPriv)
+{
+ if (!intel->intelScreen->driScrnPriv->dri2.enabled &&
+ intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) {
+ volatile drm_i915_sarea_t *sarea = intel->sarea;
+ drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
+ .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
+ drm_clip_rect_t planeA_rect = { .x1 = sarea->planeA_x, .y1 = sarea->planeA_y,
+ .x2 = sarea->planeA_x + sarea->planeA_w,
+ .y2 = sarea->planeA_y + sarea->planeA_h };
+ drm_clip_rect_t planeB_rect = { .x1 = sarea->planeB_x, .y1 = sarea->planeB_y,
+ .x2 = sarea->planeB_x + sarea->planeB_w,
+ .y2 = sarea->planeB_y + sarea->planeB_h };
+ GLint areaA = driIntersectArea( drw_rect, planeA_rect );
+ GLint areaB = driIntersectArea( drw_rect, planeB_rect );
+ GLuint flags = dPriv->vblFlags;
+
+ /* Update vblank info
+ */
+ if (areaB > areaA || (areaA == areaB && areaB > 0)) {
+ flags = dPriv->vblFlags | VBLANK_FLAG_SECONDARY;
+ } else {
+ flags = dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY;
+ }
+
+ /* Do the stupid test: Is one of them actually disabled?
+ */
+ if (sarea->planeA_w == 0 || sarea->planeA_h == 0) {
+ flags = dPriv->vblFlags | VBLANK_FLAG_SECONDARY;
+ } else if (sarea->planeB_w == 0 || sarea->planeB_h == 0) {
+ flags = dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY;
+ }
+
+ return flags;
+ } else {
+ return dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY;
+ }
+}
+
+
+/**
+ * Called from driSwapBuffers()
+ */
+void
+intelSwapBuffers(__DRIdrawablePrivate * dPriv)
+{
+ __DRIscreenPrivate *psp = dPriv->driScreenPriv;
+
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ GET_CURRENT_CONTEXT(ctx);
+ struct intel_context *intel;
+
+ if (ctx == NULL)
+ return;
+
+ intel = intel_context(ctx);
+
+ if (ctx->Visual.doubleBufferMode) {
+ GLboolean missed_target;
+ struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
+ int64_t ust;
+
+ _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
+
+ /*
+ * The old swapping ioctl was incredibly racy, just wait for vblank
+ * and do the swap ourselves.
+ */
+ driWaitForVBlank(dPriv, &missed_target);
+
+ /*
+ * Update each buffer's vbl_pending so we don't get too out of
+ * sync
+ */
+ intel_get_renderbuffer(&intel_fb->Base,
+ BUFFER_BACK_LEFT)->vbl_pending = dPriv->vblSeq;
+ intel_get_renderbuffer(&intel_fb->Base,
+ BUFFER_FRONT_LEFT)->vbl_pending = dPriv->vblSeq;
+
+ intelCopyBuffer(dPriv, NULL);
+
+ intel_fb->swap_count++;
+ (*psp->systemTime->getUST) (&ust);
+ if (missed_target) {
+ intel_fb->swap_missed_count++;
+ intel_fb->swap_missed_ust = ust - intel_fb->swap_ust;
+ }
+
+ intel_fb->swap_ust = ust;
+ }
+ drmCommandNone(intel->driFd, DRM_I915_GEM_THROTTLE);
+ }
+ else {
+ /* XXX this shouldn't be an error but we can't handle it for now */
+ fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
+ }
+}
+
+
+/**
+ * Called from driCopySubBuffer()
+ */
+void
+intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
+{
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ struct intel_context *intel =
+ (struct intel_context *) dPriv->driContextPriv->driverPrivate;
+ GLcontext *ctx = &intel->ctx;
+
+ if (ctx->Visual.doubleBufferMode) {
+ drm_clip_rect_t rect;
+ rect.x1 = x + dPriv->x;
+ rect.y1 = (dPriv->h - y - h) + dPriv->y;
+ rect.x2 = rect.x1 + w;
+ rect.y2 = rect.y1 + h;
+ _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
+ intelCopyBuffer(dPriv, &rect);
+ }
+ }
+ else {
+ /* XXX this shouldn't be an error but we can't handle it for now */
+ fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
+ }
+}
+
+
+/**
+ * This will be called whenever the currently bound window is moved/resized.
+ * XXX: actually, it seems to NOT be called when the window is only moved (BP).
+ */
+void
+intelWindowMoved(struct intel_context *intel)
+{
+ GLcontext *ctx = &intel->ctx;
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
+
+ if (!intel->intelScreen->driScrnPriv->dri2.enabled &&
+ intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) {
+ GLuint flags = intelFixupVblank(intel, dPriv);
+
+ /* Check to see if we changed pipes */
+ if (flags != dPriv->vblFlags && dPriv->vblFlags &&
+ !(dPriv->vblFlags & VBLANK_FLAG_NO_IRQ)) {
+ int64_t count;
+ drmVBlank vbl;
+ int i;
+
+ /*
+ * Deal with page flipping
+ */
+ vbl.request.type = DRM_VBLANK_ABSOLUTE;
+
+ if ( dPriv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (!intel_fb->color_rb[i] ||
+ (intel_fb->vbl_waited - intel_fb->color_rb[i]->vbl_pending) <=
+ (1<<23))
+ continue;
+
+ vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending;
+ drmWaitVBlank(intel->driFd, &vbl);
+ }
+
+ /*
+ * Update msc_base from old pipe
+ */
+ driDrawableGetMSC32(dPriv->driScreenPriv, dPriv, &count);
+ dPriv->msc_base = count;
+ /*
+ * Then get new vblank_base and vblSeq values
+ */
+ dPriv->vblFlags = flags;
+ driGetCurrentVBlank(dPriv);
+ dPriv->vblank_base = dPriv->vblSeq;
+
+ intel_fb->vbl_waited = dPriv->vblSeq;
+
+ for (i = 0; i < 2; i++) {
+ if (intel_fb->color_rb[i])
+ intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited;
+ }
+ }
+ } else {
+ dPriv->vblFlags &= ~VBLANK_FLAG_SECONDARY;
+ }
+
+ /* Update Mesa's notion of window size */
+ driUpdateFramebufferSize(ctx, dPriv);
+ intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */
+
+ /* Update hardware scissor */
+ if (ctx->Driver.Scissor != NULL) {
+ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+ }
+
+ /* Re-calculate viewport related state */
+ if (ctx->Driver.DepthRange != NULL)
+ ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far );
+}
diff --git a/src/mesa/drivers/dri/intel/intel_swapbuffers.h b/src/mesa/drivers/dri/intel/intel_swapbuffers.h
new file mode 100644
index 0000000000..75bb6242ff
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_swapbuffers.h
@@ -0,0 +1,52 @@
+
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef INTEL_SWAPBUFFERS_H
+#define INTEL_SWAPBUFFERS_H
+
+#include "dri_util.h"
+#include "drm.h"
+
+struct intel_context;
+struct intel_framebuffer;
+
+
+extern void
+intelSwapBuffers(__DRIdrawablePrivate * dPriv);
+
+extern void
+intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h);
+
+extern GLuint
+intelFixupVblank(struct intel_context *intel, __DRIdrawablePrivate *dPriv);
+
+extern void
+intelWindowMoved(struct intel_context *intel);
+
+
+#endif /* INTEL_SWAPBUFFERS_H */
diff --git a/src/mesa/drivers/dri/intel/intel_syncobj.c b/src/mesa/drivers/dri/intel/intel_syncobj.c
new file mode 100644
index 0000000000..b6ea56d547
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_syncobj.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file intel_syncobj.c
+ *
+ * Support for ARB_sync
+ *
+ * ARB_sync is implemented by flushing the current batchbuffer and keeping a
+ * reference on it. We can then check for completion or wait for compeltion
+ * using the normal buffer object mechanisms. This does mean that if an
+ * application is using many sync objects, it will emit small batchbuffers
+ * which may end up being a significant overhead. In other tests of removing
+ * gratuitous batchbuffer syncs in Mesa, it hasn't appeared to be a significant
+ * performance bottleneck, though.
+ */
+
+#include "main/simple_list.h"
+#include "main/imports.h"
+
+#include "intel_context.h"
+#include "intel_batchbuffer.h"
+#include "intel_reg.h"
+
+#if FEATURE_ARB_sync
+
+static struct gl_sync_object *
+intel_new_sync_object(GLcontext *ctx, GLuint id)
+{
+ struct intel_sync_object *sync;
+
+ sync = _mesa_calloc(sizeof(struct intel_sync_object));
+
+ return &sync->Base;
+}
+
+static void
+intel_delete_sync_object(GLcontext *ctx, struct gl_sync_object *s)
+{
+ struct intel_sync_object *sync = (struct intel_sync_object *)s;
+
+ drm_intel_bo_unreference(sync->bo);
+ _mesa_free(sync);
+}
+
+static void
+intel_fence_sync(GLcontext *ctx, struct gl_sync_object *s,
+ GLenum condition, GLbitfield flags)
+{
+ struct intel_context *intel = intel_context(ctx);
+ struct intel_sync_object *sync = (struct intel_sync_object *)s;
+
+ assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE);
+ intel_batchbuffer_emit_mi_flush(intel->batch);
+
+ sync->bo = intel->batch->buf;
+ drm_intel_bo_reference(sync->bo);
+
+ intelFlush(ctx);
+}
+
+/* We ignore the user-supplied timeout. This is weaselly -- we're allowed to
+ * round to an implementation-dependent accuracy, and right now our
+ * implementation "rounds" to the wait-forever value.
+ *
+ * The fix would be a new kernel function to do the GTT transition with a
+ * timeout.
+ */
+static void intel_client_wait_sync(GLcontext *ctx, struct gl_sync_object *s,
+ GLbitfield flags, GLuint64 timeout)
+{
+ struct intel_sync_object *sync = (struct intel_sync_object *)s;
+
+ if (sync->bo) {
+ drm_intel_bo_wait_rendering(sync->bo);
+ s->StatusFlag = 1;
+ drm_intel_bo_unreference(sync->bo);
+ sync->bo = NULL;
+ }
+}
+
+/* We have nothing to do for WaitSync. Our GL command stream is sequential,
+ * so given that the sync object has already flushed the batchbuffer,
+ * any batchbuffers coming after this waitsync will naturally not occur until
+ * the previous one is done.
+ */
+static void intel_server_wait_sync(GLcontext *ctx, struct gl_sync_object *s,
+ GLbitfield flags, GLuint64 timeout)
+{
+}
+
+static void intel_check_sync(GLcontext *ctx, struct gl_sync_object *s)
+{
+ struct intel_sync_object *sync = (struct intel_sync_object *)s;
+
+ if (sync->bo && drm_intel_bo_busy(sync->bo)) {
+ drm_intel_bo_unreference(sync->bo);
+ sync->bo = NULL;
+ s->StatusFlag = 1;
+ }
+}
+
+void intel_init_syncobj_functions(struct dd_function_table *functions)
+{
+ functions->NewSyncObject = intel_new_sync_object;
+ functions->DeleteSyncObject = intel_delete_sync_object;
+ functions->FenceSync = intel_fence_sync;
+ functions->CheckSync = intel_check_sync;
+ functions->ClientWaitSync = intel_client_wait_sync;
+ functions->ServerWaitSync = intel_server_wait_sync;
+}
+
+#else /* FEATURE_ARB_sync */
+
+void intel_init_syncobj_functions(struct dd_function_table *functions)
+{
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/intel/intel_tex.c b/src/mesa/drivers/dri/intel/intel_tex.c
index e64d8a1556..df63f29a42 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.c
+++ b/src/mesa/drivers/dri/intel/intel_tex.c
@@ -93,7 +93,7 @@ intelFreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
static void *
do_memcpy(void *dest, const void *src, size_t n)
{
- if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) {
+ if ((((unsigned long) src) & 63) || (((unsigned long) dest) & 63)) {
return __memcpy(dest, src, n);
}
else
@@ -158,81 +158,11 @@ timed_memcpy(void *dest, const void *src, size_t n)
}
#endif /* DO_DEBUG */
-/**
- * Generate new mipmap data from BASE+1 to BASE+p (the minimally-sized mipmap
- * level).
- *
- * The texture object's miptree must be mapped.
- *
- * It would be really nice if this was just called by Mesa whenever mipmaps
- * needed to be regenerated, rather than us having to remember to do so in
- * each texture image modification path.
- *
- * This function should also include an accelerated path.
- */
-void
-intel_generate_mipmap(GLcontext *ctx, GLenum target,
- struct gl_texture_object *texObj)
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_texture_object *intelObj = intel_texture_object(texObj);
- GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
- int face, i;
-
- _mesa_generate_mipmap(ctx, target, texObj);
-
- /* Update the level information in our private data in the new images, since
- * it didn't get set as part of a normal TexImage path.
- */
- for (face = 0; face < nr_faces; face++) {
- for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) {
- struct intel_texture_image *intelImage;
-
- intelImage = intel_texture_image(texObj->Image[face][i]);
- if (intelImage == NULL)
- break;
-
- intelImage->level = i;
- intelImage->face = face;
- /* Unreference the miptree to signal that the new Data is a bare
- * pointer from mesa.
- */
- intel_miptree_release(intel, &intelImage->mt);
- }
- }
-}
-
-static void intelGenerateMipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj)
-{
- struct intel_context *intel = intel_context(ctx);
- struct intel_texture_object *intelObj = intel_texture_object(texObj);
-
- intel_tex_map_level_images(intel, intelObj, texObj->BaseLevel);
- intel_generate_mipmap(ctx, target, texObj);
- intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel);
-}
-
void
intelInitTextureFuncs(struct dd_function_table *functions)
{
functions->ChooseTextureFormat = intelChooseTextureFormat;
- functions->TexImage1D = intelTexImage1D;
- functions->TexImage2D = intelTexImage2D;
- functions->TexImage3D = intelTexImage3D;
- functions->TexSubImage1D = intelTexSubImage1D;
- functions->TexSubImage2D = intelTexSubImage2D;
- functions->TexSubImage3D = intelTexSubImage3D;
- functions->CopyTexImage1D = intelCopyTexImage1D;
- functions->CopyTexImage2D = intelCopyTexImage2D;
- functions->CopyTexSubImage1D = intelCopyTexSubImage1D;
- functions->CopyTexSubImage2D = intelCopyTexSubImage2D;
- functions->GetTexImage = intelGetTexImage;
- functions->GenerateMipmap = intelGenerateMipmap;
-
- /* compressed texture functions */
- functions->CompressedTexImage2D = intelCompressedTexImage2D;
- functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D;
- functions->GetCompressedTexImage = intelGetCompressedTexImage;
+ functions->GenerateMipmap = intel_generate_mipmap;
functions->NewTextureObject = intelNewTextureObject;
functions->NewTextureImage = intelNewTextureImage;
diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h
index 742ccc043a..471aa2a240 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.h
+++ b/src/mesa/drivers/dri/intel/intel_tex.h
@@ -35,120 +35,23 @@
void intelInitTextureFuncs(struct dd_function_table *functions);
+void intelInitTextureImageFuncs(struct dd_function_table *functions);
+
+void intelInitTextureSubImageFuncs(struct dd_function_table *functions);
+
+void intelInitTextureCopyImageFuncs(struct dd_function_table *functions);
+
const struct gl_texture_format *intelChooseTextureFormat(GLcontext * ctx,
GLint internalFormat,
GLenum format,
GLenum type);
-
-void intelTexImage3D(GLcontext * ctx,
- GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint depth,
- GLint border,
- GLenum format, GLenum type, const void *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
-void intelTexSubImage3D(GLcontext * ctx,
- GLenum target,
- GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
-void intelTexImage2D(GLcontext * ctx,
- GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLenum format, GLenum type, const void *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
-void intelTexSubImage2D(GLcontext * ctx,
- GLenum target,
- GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
-void intelTexImage1D(GLcontext * ctx,
- GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint border,
- GLenum format, GLenum type, const void *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
-void intelTexSubImage1D(GLcontext * ctx,
- GLenum target,
- GLint level,
- GLint xoffset,
- GLsizei width,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
-void intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
- GLenum internalFormat,
- GLint x, GLint y, GLsizei width, GLint border);
-
-void intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
- GLenum internalFormat,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLint border);
-
-void intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
- GLint xoffset, GLint x, GLint y, GLsizei width);
-
-void intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLint x, GLint y, GLsizei width, GLsizei height);
-
-void intelGetTexImage(GLcontext * ctx, GLenum target, GLint level,
- GLenum format, GLenum type, GLvoid * pixels,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
-void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLsizei imageSize, const GLvoid *data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage );
-
-void intelCompressedTexSubImage2D(GLcontext * ctx,
- GLenum target,
- GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLsizei imageSize,
- const GLvoid * pixels,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
-void intelGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
- GLvoid *pixels,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
void intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname,
unsigned long long offset, GLint depth, GLuint pitch);
void intelSetTexBuffer(__DRIcontext *pDRICtx,
GLint target, __DRIdrawable *pDraw);
+void intelSetTexBuffer2(__DRIcontext *pDRICtx,
+ GLint target, GLint format, __DRIdrawable *pDraw);
GLuint intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit);
diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c
index 08437aa0e2..028b49c14d 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_copy.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c
@@ -73,11 +73,8 @@ get_teximage_source(struct intel_context *intel, GLenum internalFormat)
return NULL;
case GL_RGBA:
case GL_RGBA8:
- return intel_readbuf_region(intel);
case GL_RGB:
- if (intel->ctx.Visual.rgbBits == 16)
- return intel_readbuf_region(intel);
- return NULL;
+ return intel_readbuf_region(intel);
default:
return NULL;
}
@@ -99,14 +96,24 @@ do_copy_texsubimage(struct intel_context *intel,
if (!intelImage->mt || !src) {
if (INTEL_DEBUG & DEBUG_FALLBACKS)
- fprintf(stderr, "%s fail %p %p\n",
- __FUNCTION__, intelImage->mt, src);
+ fprintf(stderr, "%s fail %p %p (0x%08x)\n",
+ __FUNCTION__, intelImage->mt, src, internalFormat);
+ return GL_FALSE;
+ }
+
+ if (intelImage->mt->cpp != src->cpp) {
+ if (INTEL_DEBUG & DEBUG_FALLBACKS)
+ fprintf(stderr, "%s fail %d vs %d cpp\n",
+ __FUNCTION__, intelImage->mt->cpp, src->cpp);
return GL_FALSE;
}
intelFlush(ctx);
LOCK_HARDWARE(intel);
{
+ drm_intel_bo *dst_bo = intel_region_buffer(intel,
+ intelImage->mt->region,
+ INTEL_WRITE_PART);
GLuint image_offset = intel_miptree_image_offset(intelImage->mt,
intelImage->face,
intelImage->level);
@@ -118,8 +125,12 @@ do_copy_texsubimage(struct intel_context *intel,
dstx += x - orig_x;
dsty += y - orig_y;
- /* image_offset may be non-page-aligned, but that's illegal for tiling. */
- assert(intelImage->mt->region->tiling == I915_TILING_NONE);
+ /* Can't blit to tiled buffers with non-tile-aligned offset. */
+ if (intelImage->mt->region->tiling != I915_TILING_NONE &&
+ (image_offset & 4095) != 0) {
+ UNLOCK_HARDWARE(intel);
+ return GL_FALSE;
+ }
if (ctx->ReadBuffer->Name == 0) {
/* reading from a window, adjust x, y */
@@ -140,35 +151,35 @@ do_copy_texsubimage(struct intel_context *intel,
src_pitch = src->pitch;
}
- intelEmitCopyBlit(intel,
- intelImage->mt->cpp,
- src_pitch,
- src->buffer,
- 0,
- src->tiling,
- intelImage->mt->pitch,
- intelImage->mt->region->buffer,
- image_offset,
- intelImage->mt->region->tiling,
- x, y, dstx, dsty, width, height,
- GL_COPY);
+ if (!intelEmitCopyBlit(intel,
+ intelImage->mt->cpp,
+ src_pitch,
+ src->buffer,
+ 0,
+ src->tiling,
+ intelImage->mt->pitch,
+ dst_bo,
+ image_offset,
+ intelImage->mt->region->tiling,
+ x, y, dstx, dsty, width, height,
+ GL_COPY)) {
+ UNLOCK_HARDWARE(intel);
+ return GL_FALSE;
+ }
}
UNLOCK_HARDWARE(intel);
/* GL_SGIS_generate_mipmap */
if (intelImage->level == texObj->BaseLevel && texObj->GenerateMipmap) {
- ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ intel_generate_mipmap(ctx, target, texObj);
}
return GL_TRUE;
}
-
-
-
-void
+static void
intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLint border)
@@ -214,7 +225,8 @@ intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
width, border);
}
-void
+
+static void
intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
@@ -231,6 +243,14 @@ intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
if (border)
goto fail;
+ /* Setup or redefine the texture object, mipmap tree and texture
+ * image. Don't populate yet.
+ */
+ ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ width, height, border,
+ GL_RGBA, CHAN_TYPE, NULL,
+ &ctx->DefaultPacking, texObj, texImage);
+
srcx = x;
srcy = y;
dstx = 0;
@@ -241,15 +261,6 @@ intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
&width, &height))
return;
- /* Setup or redefine the texture object, mipmap tree and texture
- * image. Don't populate yet.
- */
- ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
- width, height, border,
- GL_RGBA, CHAN_TYPE, NULL,
- &ctx->DefaultPacking, texObj, texImage);
-
-
if (!do_copy_texsubimage(intel_context(ctx), target,
intel_texture_image(texImage),
internalFormat, 0, 0, x, y, width, height))
@@ -263,7 +274,7 @@ intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
}
-void
+static void
intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
GLint xoffset, GLint x, GLint y, GLsizei width)
{
@@ -288,8 +299,7 @@ intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
}
-
-void
+static void
intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height)
@@ -302,7 +312,6 @@ intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
_mesa_select_tex_image(ctx, texObj, target, level);
GLenum internalFormat = texImage->InternalFormat;
-
/* Need to check texture is compatible with source format.
*/
@@ -317,3 +326,13 @@ intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
xoffset, yoffset, x, y, width, height);
}
}
+
+
+void
+intelInitTextureCopyImageFuncs(struct dd_function_table *functions)
+{
+ functions->CopyTexImage1D = intelCopyTexImage1D;
+ functions->CopyTexImage2D = intelCopyTexImage2D;
+ functions->CopyTexSubImage1D = intelCopyTexSubImage1D;
+ functions->CopyTexSubImage2D = intelCopyTexSubImage2D;
+}
diff --git a/src/mesa/drivers/dri/intel/intel_tex_format.c b/src/mesa/drivers/dri/intel/intel_tex_format.c
index 5e418ac446..3322a71130 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_format.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_format.c
@@ -1,13 +1,18 @@
#include "intel_context.h"
#include "intel_tex.h"
+#include "intel_chipset.h"
#include "main/texformat.h"
#include "main/enums.h"
-/* It works out that this function is fine for all the supported
+
+/**
+ * Choose hardware texture format given the user's glTexImage parameters.
+ *
+ * It works out that this function is fine for all the supported
* hardware. However, there is still a need to map the formats onto
* hardware descriptors.
- */
-/* Note that the i915 can actually support many more formats than
+ *
+ * Note that the i915 can actually support many more formats than
* these if we take the step of simply swizzling the colors
* immediately after sampling...
*/
@@ -16,7 +21,12 @@ intelChooseTextureFormat(GLcontext * ctx, GLint internalFormat,
GLenum format, GLenum type)
{
struct intel_context *intel = intel_context(ctx);
- const GLboolean do32bpt = (intel->ctx.Visual.rgbBits == 32);
+ const GLboolean do32bpt = (intel->ctx.Visual.rgbBits >= 24);
+
+#if 0
+ printf("%s intFmt=0x%x format=0x%x type=0x%x\n",
+ __FUNCTION__, internalFormat, format, type);
+#endif
switch (internalFormat) {
case 4:
@@ -151,20 +161,36 @@ intelChooseTextureFormat(GLcontext * ctx, GLint internalFormat,
case GL_SRGB8_EXT:
case GL_SRGB_ALPHA_EXT:
case GL_SRGB8_ALPHA8_EXT:
- case GL_SLUMINANCE_EXT:
- case GL_SLUMINANCE8_EXT:
- case GL_SLUMINANCE_ALPHA_EXT:
- case GL_SLUMINANCE8_ALPHA8_EXT:
case GL_COMPRESSED_SRGB_EXT:
case GL_COMPRESSED_SRGB_ALPHA_EXT:
case GL_COMPRESSED_SLUMINANCE_EXT:
case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
- return &_mesa_texformat_srgba8;
+ return &_mesa_texformat_sargb8;
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ if (IS_G4X(intel->intelScreen->deviceID))
+ return &_mesa_texformat_sl8;
+ else
+ return &_mesa_texformat_sargb8;
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ if (IS_G4X(intel->intelScreen->deviceID))
+ return &_mesa_texformat_sla8;
+ else
+ return &_mesa_texformat_sargb8;
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
return &_mesa_texformat_srgb_dxt1;
+
+ /* i915 could also do this */
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return &_mesa_texformat_dudv8;
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ return &_mesa_texformat_signed_rgba8888_rev;
#endif
default:
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index 2ac7dceb0f..a206fe6805 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -1,17 +1,14 @@
-#include <stdlib.h>
-#include <stdio.h>
-
#include "main/glheader.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/enums.h"
-#include "main/colortab.h"
+#include "main/bufferobj.h"
#include "main/convolve.h"
#include "main/context.h"
-#include "main/simple_list.h"
#include "main/texcompress.h"
#include "main/texformat.h"
+#include "main/texgetimage.h"
#include "main/texobj.h"
#include "main/texstore.h"
#include "main/teximage.h"
@@ -62,7 +59,8 @@ logbase2(int n)
static void
guess_and_alloc_mipmap_tree(struct intel_context *intel,
struct intel_texture_object *intelObj,
- struct intel_texture_image *intelImage)
+ struct intel_texture_image *intelImage,
+ GLboolean expect_accelerated_upload)
{
GLuint firstLevel;
GLuint lastLevel;
@@ -129,6 +127,7 @@ guess_and_alloc_mipmap_tree(struct intel_context *intel,
comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat->MesaFormat);
intelObj->mt = intel_miptree_create(intel,
intelObj->base.Target,
+ intelImage->base._BaseFormat,
intelImage->base.InternalFormat,
firstLevel,
lastLevel,
@@ -136,7 +135,8 @@ guess_and_alloc_mipmap_tree(struct intel_context *intel,
height,
depth,
intelImage->base.TexFormat->TexelBytes,
- comp_byte);
+ comp_byte,
+ expect_accelerated_upload);
DBG("%s - success\n", __FUNCTION__);
}
@@ -202,14 +202,15 @@ try_pbo_upload(struct intel_context *intel,
GLuint src_offset, src_stride;
GLuint dst_offset, dst_stride;
- if (!pbo ||
+ if (!_mesa_is_bufferobj(unpack->BufferObj) ||
intel->ctx._ImageTransferState ||
unpack->SkipPixels || unpack->SkipRows) {
- _mesa_printf("%s: failure 1\n", __FUNCTION__);
+ DBG("%s: failure 1\n", __FUNCTION__);
return GL_FALSE;
}
- src_offset = (GLuint) pixels;
+ /* note: potential 64-bit ptr to 32-bit int cast */
+ src_offset = (GLuint) (unsigned long) pixels;
if (unpack->RowLength > 0)
src_stride = unpack->RowLength;
@@ -231,12 +232,15 @@ try_pbo_upload(struct intel_context *intel,
INTEL_WRITE_FULL);
- intelEmitCopyBlit(intel,
- intelImage->mt->cpp,
- src_stride, src_buffer, src_offset, GL_FALSE,
- dst_stride, dst_buffer, dst_offset, GL_FALSE,
- 0, 0, 0, 0, width, height,
- GL_COPY);
+ if (!intelEmitCopyBlit(intel,
+ intelImage->mt->cpp,
+ src_stride, src_buffer, src_offset, GL_FALSE,
+ dst_stride, dst_buffer, dst_offset, GL_FALSE,
+ 0, 0, 0, 0, width, height,
+ GL_COPY)) {
+ UNLOCK_HARDWARE(intel);
+ return GL_FALSE;
+ }
}
UNLOCK_HARDWARE(intel);
@@ -244,7 +248,6 @@ try_pbo_upload(struct intel_context *intel,
}
-
static GLboolean
try_pbo_zcopy(struct intel_context *intel,
struct intel_texture_image *intelImage,
@@ -257,14 +260,15 @@ try_pbo_zcopy(struct intel_context *intel,
GLuint src_offset, src_stride;
GLuint dst_offset, dst_stride;
- if (!pbo ||
+ if (!_mesa_is_bufferobj(unpack->BufferObj) ||
intel->ctx._ImageTransferState ||
unpack->SkipPixels || unpack->SkipRows) {
- _mesa_printf("%s: failure 1\n", __FUNCTION__);
+ DBG("%s: failure 1\n", __FUNCTION__);
return GL_FALSE;
}
- src_offset = (GLuint) pixels;
+ /* note: potential 64-bit ptr to 32-bit int cast */
+ src_offset = (GLuint) (unsigned long) pixels;
if (unpack->RowLength > 0)
src_stride = unpack->RowLength;
@@ -278,7 +282,7 @@ try_pbo_zcopy(struct intel_context *intel,
dst_stride = intelImage->mt->pitch;
if (src_stride != dst_stride || dst_offset != 0 || src_offset != 0) {
- _mesa_printf("%s: failure 2\n", __FUNCTION__);
+ DBG("%s: failure 2\n", __FUNCTION__);
return GL_FALSE;
}
@@ -288,10 +292,6 @@ try_pbo_zcopy(struct intel_context *intel,
}
-
-
-
-
static void
intelTexImage(GLcontext * ctx,
GLint dims,
@@ -302,7 +302,8 @@ intelTexImage(GLcontext * ctx,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
- struct gl_texture_image *texImage, GLsizei imageSize, int compressed)
+ struct gl_texture_image *texImage, GLsizei imageSize,
+ GLboolean compressed)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_object *intelObj = intel_texture_object(texObj);
@@ -310,8 +311,7 @@ intelTexImage(GLcontext * ctx,
GLint postConvWidth = width;
GLint postConvHeight = height;
GLint texelBytes, sizeInBytes;
- GLuint dstRowStride, srcRowStride = texImage->RowStride;
-
+ GLuint dstRowStride = 0, srcRowStride = texImage->RowStride;
DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
@@ -383,7 +383,7 @@ intelTexImage(GLcontext * ctx,
}
if (!intelObj->mt) {
- guess_and_alloc_mipmap_tree(intel, intelObj, intelImage);
+ guess_and_alloc_mipmap_tree(intel, intelObj, intelImage, pixels == NULL);
if (!intelObj->mt) {
DBG("guess_and_alloc_mipmap_tree: failed\n");
}
@@ -409,11 +409,13 @@ intelTexImage(GLcontext * ctx,
* a miptree, so create one just for our level and store it in the image.
* It'll get moved into the object miptree at validate time.
*/
- intelImage->mt = intel_miptree_create(intel, target, internalFormat,
+ intelImage->mt = intel_miptree_create(intel, target,
+ intelImage->base.TexFormat->BaseFormat,
+ internalFormat,
level, level,
width, height, depth,
intelImage->base.TexFormat->TexelBytes,
- comp_byte);
+ comp_byte, pixels == NULL);
}
@@ -421,7 +423,7 @@ intelTexImage(GLcontext * ctx,
*/
if (dims <= 2 &&
intelImage->mt &&
- intel_buffer_object(unpack->BufferObj) &&
+ _mesa_is_bufferobj(unpack->BufferObj) &&
check_pbo_format(internalFormat, format,
type, intelImage->base.TexFormat)) {
@@ -459,8 +461,6 @@ intelTexImage(GLcontext * ctx,
DBG("pbo upload failed\n");
}
-
-
/* intelCopyTexImage calls this function with pixels == NULL, with
* the expectation that the mipmap tree will be set up but nothing
* more will be done. This is where those calls return:
@@ -478,12 +478,13 @@ intelTexImage(GLcontext * ctx,
LOCK_HARDWARE(intel);
if (intelImage->mt) {
- texImage->Data = intel_miptree_image_map(intel,
- intelImage->mt,
- intelImage->face,
- intelImage->level,
- &dstRowStride,
- intelImage->base.ImageOffsets);
+ if (pixels != NULL)
+ texImage->Data = intel_miptree_image_map(intel,
+ intelImage->mt,
+ intelImage->face,
+ intelImage->level,
+ &dstRowStride,
+ intelImage->base.ImageOffsets);
texImage->RowStride = dstRowStride / intelImage->mt->cpp;
}
else {
@@ -503,8 +504,9 @@ intelTexImage(GLcontext * ctx,
}
DBG("Upload image %dx%dx%d row_len %d "
- "pitch %d\n",
- width, height, depth, width * texelBytes, dstRowStride);
+ "pitch %d pixels %d compressed %d\n",
+ width, height, depth, width * texelBytes, dstRowStride,
+ pixels ? 1 : 0, compressed);
/* Copy data. Would like to know when it's ok for us to eg. use
* the blitter to copy. Or, use the hardware to do the format
@@ -517,7 +519,7 @@ intelTexImage(GLcontext * ctx,
_mesa_copy_rect(texImage->Data, dst->cpp, dst->pitch,
0, 0,
intelImage->mt->level[level].width,
- intelImage->mt->level[level].height/4,
+ (intelImage->mt->level[level].height+3)/4,
pixels,
srcRowStride,
0, 0);
@@ -535,22 +537,24 @@ intelTexImage(GLcontext * ctx,
}
}
- /* GL_SGIS_generate_mipmap */
- if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
- intel_generate_mipmap(ctx, target, texObj);
- }
-
_mesa_unmap_teximage_pbo(ctx, unpack);
if (intelImage->mt) {
- intel_miptree_image_unmap(intel, intelImage->mt);
+ if (pixels != NULL)
+ intel_miptree_image_unmap(intel, intelImage->mt);
texImage->Data = NULL;
}
UNLOCK_HARDWARE(intel);
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ intel_generate_mipmap(ctx, target, texObj);
+ }
}
-void
+
+static void
intelTexImage3D(GLcontext * ctx,
GLenum target, GLint level,
GLint internalFormat,
@@ -563,11 +567,11 @@ intelTexImage3D(GLcontext * ctx,
{
intelTexImage(ctx, 3, target, level,
internalFormat, width, height, depth, border,
- format, type, pixels, unpack, texObj, texImage, 0, 0);
+ format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
}
-void
+static void
intelTexImage2D(GLcontext * ctx,
GLenum target, GLint level,
GLint internalFormat,
@@ -579,10 +583,11 @@ intelTexImage2D(GLcontext * ctx,
{
intelTexImage(ctx, 2, target, level,
internalFormat, width, height, 1, border,
- format, type, pixels, unpack, texObj, texImage, 0, 0);
+ format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
}
-void
+
+static void
intelTexImage1D(GLcontext * ctx,
GLenum target, GLint level,
GLint internalFormat,
@@ -594,21 +599,24 @@ intelTexImage1D(GLcontext * ctx,
{
intelTexImage(ctx, 1, target, level,
internalFormat, width, 1, 1, border,
- format, type, pixels, unpack, texObj, texImage, 0, 0);
+ format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
}
-void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLsizei imageSize, const GLvoid *data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
+
+static void
+intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
{
intelTexImage(ctx, 2, target, level,
internalFormat, width, height, 1, border,
- 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1);
+ 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, GL_TRUE);
}
+
/**
* Need to map texture image into memory before copying image data,
* then unmap it.
@@ -617,11 +625,17 @@ static void
intel_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
GLenum format, GLenum type, GLvoid * pixels,
struct gl_texture_object *texObj,
- struct gl_texture_image *texImage, int compressed)
+ struct gl_texture_image *texImage, GLboolean compressed)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
+ /* If we're reading from a texture that has been rendered to, need to
+ * make sure rendering is complete.
+ * We could probably predicate this on texObj->_RenderToTexture
+ */
+ intelFlush(ctx);
+
/* Map */
if (intelImage->mt) {
/* Image is stored in hardware format in a buffer managed by the
@@ -665,28 +679,29 @@ intel_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
}
}
-void
+
+static void
intelGetTexImage(GLcontext * ctx, GLenum target, GLint level,
GLenum format, GLenum type, GLvoid * pixels,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intel_get_tex_image(ctx, target, level, format, type, pixels,
- texObj, texImage, 0);
-
-
+ texObj, texImage, GL_FALSE);
}
-void
+
+static void
intelGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
GLvoid *pixels,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intel_get_tex_image(ctx, target, level, 0, 0, pixels,
- texObj, texImage, 1);
+ texObj, texImage, GL_TRUE);
}
+
void
intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname,
unsigned long long offset, GLint depth, GLuint pitch)
@@ -710,7 +725,9 @@ intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname,
}
void
-intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
+intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
+ GLint glx_texture_format,
+ __DRIdrawable *dPriv)
{
struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
struct intel_context *intel = pDRICtx->driverPrivate;
@@ -741,7 +758,10 @@ intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
type = GL_BGRA;
format = GL_UNSIGNED_BYTE;
- internalFormat = (rb->region->cpp == 3 ? 3 : 4);
+ if (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT)
+ internalFormat = GL_RGB;
+ else
+ internalFormat = GL_RGBA;
mt = intel_miptree_create_for_region(intel, target,
internalFormat,
@@ -751,16 +771,21 @@ intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
_mesa_lock_texture(&intel->ctx, texObj);
+ texImage = _mesa_get_tex_image(&intel->ctx, texObj, target, level);
+ intelImage = intel_texture_image(texImage);
+
+ if (intelImage->mt) {
+ intel_miptree_release(intel, &intelImage->mt);
+ assert(!texImage->Data);
+ }
if (intelObj->mt)
intel_miptree_release(intel, &intelObj->mt);
intelObj->mt = mt;
- texImage = _mesa_get_tex_image(&intel->ctx, texObj, target, level);
_mesa_init_teximage_fields(&intel->ctx, target, texImage,
rb->region->width, rb->region->height, 1,
0, internalFormat);
- intelImage = intel_texture_image(texImage);
intelImage->face = target_to_face(target);
intelImage->level = level;
texImage->TexFormat = intelChooseTextureFormat(&intel->ctx, internalFormat,
@@ -776,3 +801,25 @@ intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
_mesa_unlock_texture(&intel->ctx, texObj);
}
+
+void
+intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
+{
+ /* The old interface didn't have the format argument, so copy our
+ * implementation's behavior at the time.
+ */
+ intelSetTexBuffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
+}
+
+
+void
+intelInitTextureImageFuncs(struct dd_function_table *functions)
+{
+ functions->TexImage1D = intelTexImage1D;
+ functions->TexImage2D = intelTexImage2D;
+ functions->TexImage3D = intelTexImage3D;
+ functions->GetTexImage = intelGetTexImage;
+
+ functions->CompressedTexImage2D = intelCompressedTexImage2D;
+ functions->GetCompressedTexImage = intelGetCompressedTexImage;
+}
diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c
index e6f9a41779..7d69ea4484 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_layout.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c
@@ -35,26 +35,39 @@
#include "intel_context.h"
#include "main/macros.h"
-GLuint intel_compressed_alignment(GLenum internalFormat)
+void intel_get_texture_alignment_unit(GLenum internalFormat, GLuint *w, GLuint *h)
{
- GLuint alignment = 4;
-
switch (internalFormat) {
case GL_COMPRESSED_RGB_FXT1_3DFX:
case GL_COMPRESSED_RGBA_FXT1_3DFX:
- alignment = 8;
+ *w = 8;
+ *h = 4;
+ break;
+
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ *w = 4;
+ *h = 4;
break;
default:
+ *w = 4;
+ *h = 2;
break;
}
-
- return alignment;
}
-void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tree *mt )
+void i945_miptree_layout_2d( struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t tiling )
{
- GLint align_h = 2, align_w = 4;
+ GLuint align_h = 2, align_w = 4;
GLuint level;
GLuint x = 0;
GLuint y = 0;
@@ -62,9 +75,9 @@ void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tr
GLuint height = mt->height0;
mt->pitch = mt->width0;
+ intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h);
if (mt->compressed) {
- align_w = intel_compressed_alignment(mt->internal_format);
mt->pitch = ALIGN(mt->width0, align_w);
}
@@ -92,7 +105,7 @@ void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tr
/* Pitch must be a whole number of dwords, even though we
* express it in texels.
*/
- mt->pitch = intel_miptree_pitch_align (intel, mt, mt->pitch);
+ mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->pitch);
mt->total_height = 0;
for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {
diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.h b/src/mesa/drivers/dri/intel/intel_tex_layout.h
index dbc90e6f9b..c9de9b5678 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_layout.h
+++ b/src/mesa/drivers/dri/intel/intel_tex_layout.h
@@ -38,5 +38,7 @@ static GLuint minify( GLuint d )
return MAX2(1, d>>1);
}
-extern void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tree *mt );
-extern GLuint intel_compressed_alignment(GLenum);
+extern void i945_miptree_layout_2d(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t tiling);
+extern void intel_get_texture_alignment_unit(GLenum, GLuint *, GLuint *);
diff --git a/src/mesa/drivers/dri/intel/intel_tex_subimage.c b/src/mesa/drivers/dri/intel/intel_tex_subimage.c
index f86de56897..89037073f8 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_subimage.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_subimage.c
@@ -44,10 +44,12 @@ intelTexSubimage(GLcontext * ctx,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
+ GLsizei imageSize,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
+ struct gl_texture_image *texImage,
+ GLboolean compressed)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
@@ -59,9 +61,14 @@ intelTexSubimage(GLcontext * ctx,
intelFlush(ctx);
- pixels =
- _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
- type, pixels, packing, "glTexSubImage2D");
+ if (compressed)
+ pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize,
+ pixels, packing,
+ "glCompressedTexImage");
+ else
+ pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
+ format, type, pixels, packing,
+ "glTexSubImage");
if (!pixels)
return;
@@ -90,20 +97,28 @@ intelTexSubimage(GLcontext * ctx,
assert(dstRowStride);
- if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
- texImage->TexFormat,
- texImage->Data,
- xoffset, yoffset, zoffset,
- dstRowStride,
- texImage->ImageOffsets,
- width, height, depth,
- format, type, pixels, packing)) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
+ if (compressed) {
+ if (intelImage->mt) {
+ struct intel_region *dst = intelImage->mt->region;
+
+ _mesa_copy_rect(texImage->Data, dst->cpp, dst->pitch,
+ xoffset, yoffset / 4,
+ (width + 3) & ~3, (height + 3) / 4,
+ pixels, (width + 3) & ~3, 0, 0);
+ } else
+ memcpy(texImage->Data, pixels, imageSize);
}
-
- /* GL_SGIS_generate_mipmap */
- if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
- intel_generate_mipmap(ctx, target, texObj);
+ else {
+ if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ xoffset, yoffset, zoffset,
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, depth,
+ format, type, pixels, packing)) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
+ }
}
_mesa_unmap_teximage_pbo(ctx, packing);
@@ -114,13 +129,15 @@ intelTexSubimage(GLcontext * ctx,
}
UNLOCK_HARDWARE(intel);
-}
-
-
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ intel_generate_mipmap(ctx, target, texObj);
+ }
+}
-void
+static void
intelTexSubImage3D(GLcontext * ctx,
GLenum target,
GLint level,
@@ -132,18 +149,15 @@ intelTexSubImage3D(GLcontext * ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
-
intelTexSubimage(ctx, 3,
target, level,
xoffset, yoffset, zoffset,
- width, height, depth,
- format, type, pixels, packing, texObj, texImage);
-
+ width, height, depth, 0,
+ format, type, pixels, packing, texObj, texImage, GL_FALSE);
}
-
-void
+static void
intelTexSubImage2D(GLcontext * ctx,
GLenum target,
GLint level,
@@ -155,17 +169,15 @@ intelTexSubImage2D(GLcontext * ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
-
intelTexSubimage(ctx, 2,
target, level,
xoffset, yoffset, 0,
- width, height, 1,
- format, type, pixels, packing, texObj, texImage);
-
+ width, height, 1, 0,
+ format, type, pixels, packing, texObj, texImage, GL_FALSE);
}
-void
+static void
intelTexSubImage1D(GLcontext * ctx,
GLenum target,
GLint level,
@@ -180,12 +192,11 @@ intelTexSubImage1D(GLcontext * ctx,
intelTexSubimage(ctx, 1,
target, level,
xoffset, 0, 0,
- width, 1, 1,
- format, type, pixels, packing, texObj, texImage);
-
+ width, 1, 1, 0,
+ format, type, pixels, packing, texObj, texImage, GL_FALSE);
}
-void
+static void
intelCompressedTexSubImage2D(GLcontext * ctx,
GLenum target,
GLint level,
@@ -196,6 +207,20 @@ intelCompressedTexSubImage2D(GLcontext * ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
- fprintf(stderr, "stubbed CompressedTexSubImage2D: %dx%d@%dx%d\n",
- width, height, xoffset, yoffset);
+ intelTexSubimage(ctx, 2,
+ target, level,
+ xoffset, yoffset, 0,
+ width, height, 1, imageSize,
+ format, 0, pixels, &ctx->Unpack, texObj, texImage, GL_TRUE);
+}
+
+
+
+void
+intelInitTextureSubImageFuncs(struct dd_function_table *functions)
+{
+ functions->TexSubImage1D = intelTexSubImage1D;
+ functions->TexSubImage2D = intelTexSubImage2D;
+ functions->TexSubImage3D = intelTexSubImage3D;
+ functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D;
}
diff --git a/src/mesa/drivers/dri/intel/intel_tex_validate.c b/src/mesa/drivers/dri/intel/intel_tex_validate.c
index 820683d42e..a284d5475f 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_validate.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_validate.c
@@ -199,6 +199,7 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
if (!intelObj->mt) {
intelObj->mt = intel_miptree_create(intel,
intelObj->base.Target,
+ firstImage->base._BaseFormat,
firstImage->base.InternalFormat,
intelObj->firstLevel,
intelObj->lastLevel,
@@ -206,7 +207,8 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
firstImage->base.Height,
firstImage->base.Depth,
cpp,
- comp_byte);
+ comp_byte,
+ GL_TRUE);
}
/* Pull in any images not in the object's tree:
@@ -240,7 +242,7 @@ intel_tex_map_level_images(struct intel_context *intel,
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][level]);
- if (intelImage->mt) {
+ if (intelImage && intelImage->mt) {
intelImage->base.Data =
intel_miptree_image_map(intel,
intelImage->mt,
@@ -267,7 +269,7 @@ intel_tex_unmap_level_images(struct intel_context *intel,
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][level]);
- if (intelImage->mt) {
+ if (intelImage && intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
intelImage->base.Data = NULL;
}
diff --git a/src/mesa/drivers/dri/mach64/mach64_context.c b/src/mesa/drivers/dri/mach64/mach64_context.c
index 99abd209b6..9c7f513c6f 100644
--- a/src/mesa/drivers/dri/mach64/mach64_context.c
+++ b/src/mesa/drivers/dri/mach64/mach64_context.c
@@ -57,10 +57,6 @@
#include "utils.h"
#include "vblank.h"
-#define need_GL_ARB_multisample
-#define need_GL_ARB_vertex_buffer_object
-#include "extension_helper.h"
-
#ifndef MACH64_DEBUG
int MACH64_DEBUG = (0);
#endif
@@ -82,9 +78,7 @@ static const struct dri_debug_control debug_control[] =
const struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_multitexture", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_texture_edge_clamp", NULL },
{ "GL_MESA_ycbcr_texture", NULL },
{ "GL_SGIS_generate_mipmap", NULL },
@@ -196,6 +190,7 @@ GLboolean mach64CreateContext( const __GLcontextModes *glVisual,
ctx->Const.MaxTextureUnits = 2;
ctx->Const.MaxTextureImageUnits = 2;
ctx->Const.MaxTextureCoordUnits = 2;
+ ctx->Const.MaxDrawBuffers = 1;
heap = mach64Screen->IsPCI ? MACH64_CARD_HEAP : MACH64_AGP_HEAP;
diff --git a/src/mesa/drivers/dri/mach64/mach64_screen.c b/src/mesa/drivers/dri/mach64/mach64_screen.c
index 6bfb4c32b1..6440027ca4 100644
--- a/src/mesa/drivers/dri/mach64/mach64_screen.c
+++ b/src/mesa/drivers/dri/mach64/mach64_screen.c
@@ -93,6 +93,7 @@ mach64FillInModes( __DRIscreenPrivate *psp,
uint8_t depth_bits_array[2];
uint8_t stencil_bits_array[2];
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = depth_bits;
depth_bits_array[1] = depth_bits;
@@ -104,6 +105,8 @@ mach64FillInModes( __DRIscreenPrivate *psp,
stencil_bits_array[0] = 0;
stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+ msaa_samples_array[0] = 0;
+
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
back_buffer_factor = (have_back_buffer) ? 2 : 1;
@@ -119,7 +122,8 @@ mach64FillInModes( __DRIscreenPrivate *psp,
configs = driCreateConfigs(fb_format, fb_type,
depth_bits_array, stencil_bits_array,
depth_buffer_factor, back_buffer_modes,
- back_buffer_factor);
+ back_buffer_factor,
+ msaa_samples_array, 1);
if (configs == NULL) {
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n",
__func__, __LINE__);
@@ -370,7 +374,7 @@ mach64CreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
mach64DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
diff --git a/src/mesa/drivers/dri/mach64/mach64_tex.c b/src/mesa/drivers/dri/mach64/mach64_tex.c
index 1f9d3c57eb..225d23179e 100644
--- a/src/mesa/drivers/dri/mach64/mach64_tex.c
+++ b/src/mesa/drivers/dri/mach64/mach64_tex.c
@@ -99,7 +99,7 @@ static void mach64SetTexFilter( mach64TexObjPtr t,
}
}
-static void mach64SetTexBorderColor( mach64TexObjPtr t, GLubyte c[4] )
+static void mach64SetTexBorderColor( mach64TexObjPtr t, const GLfloat c[4] )
{
#if 0
GLuint border = mach64PackColor( 4, c[0], c[1], c[2], c[3] );
@@ -131,7 +131,7 @@ mach64AllocTexObj( struct gl_texture_object *texObj )
mach64SetTexWrap( t, texObj->WrapS, texObj->WrapT );
mach64SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
- mach64SetTexBorderColor( t, texObj->_BorderChan );
+ mach64SetTexBorderColor( t, texObj->BorderColor );
return t;
}
@@ -152,6 +152,7 @@ mach64ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
+ case GL_COMPRESSED_ALPHA:
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
@@ -160,9 +161,11 @@ mach64ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
case 4:
case GL_RGBA:
case GL_RGBA2:
+ case GL_COMPRESSED_RGBA:
if (mmesa->mach64Screen->cpp == 4)
return &_mesa_texformat_argb8888;
else
@@ -193,6 +196,7 @@ mach64ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
+ case GL_COMPRESSED_RGB:
if (mmesa->mach64Screen->cpp == 4)
return &_mesa_texformat_argb8888;
else
@@ -204,6 +208,7 @@ mach64ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
+ case GL_COMPRESSED_LUMINANCE:
if (mmesa->mach64Screen->cpp == 4)
return &_mesa_texformat_argb8888; /* inefficient but accurate */
else
@@ -214,6 +219,7 @@ mach64ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
+ case GL_COMPRESSED_INTENSITY:
if (mmesa->mach64Screen->cpp == 4)
return &_mesa_texformat_argb8888; /* inefficient but accurate */
else
@@ -465,7 +471,7 @@ static void mach64DDTexParameter( GLcontext *ctx, GLenum target,
case GL_TEXTURE_BORDER_COLOR:
if ( t->base.bound ) FLUSH_BATCH( mmesa );
- mach64SetTexBorderColor( t, tObj->_BorderChan );
+ mach64SetTexBorderColor( t, tObj->BorderColor );
break;
case GL_TEXTURE_BASE_LEVEL:
diff --git a/src/mesa/drivers/dri/mga/mga_texstate.c b/src/mesa/drivers/dri/mga/mga_texstate.c
index d4c5b6fd97..ad765d1dd7 100644
--- a/src/mesa/drivers/dri/mga/mga_texstate.c
+++ b/src/mesa/drivers/dri/mga/mga_texstate.c
@@ -206,8 +206,8 @@ static void mgaUpdateTextureEnvG200( GLcontext *ctx, GLuint unit )
mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
- if (tObj != ctx->Texture.Unit[0].Current2D &&
- tObj != ctx->Texture.Unit[0].CurrentRect)
+ if (tObj != ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX] &&
+ tObj != ctx->Texture.Unit[0].CurrentTex[TEXTURE_RECT_INDEX])
return;
@@ -635,8 +635,8 @@ static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit )
mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
- if (tObj != ctx->Texture.Unit[source].Current2D &&
- tObj != ctx->Texture.Unit[source].CurrentRect)
+ if (tObj != ctx->Texture.Unit[source].CurrentTex[TEXTURE_2D_INDEX] &&
+ tObj != ctx->Texture.Unit[source].CurrentTex[TEXTURE_RECT_INDEX])
return;
switch (ctx->Texture.Unit[source].EnvMode) {
diff --git a/src/mesa/drivers/dri/mga/mga_xmesa.c b/src/mesa/drivers/dri/mga/mga_xmesa.c
index 86da3a2cac..0dc76fea50 100644
--- a/src/mesa/drivers/dri/mga/mga_xmesa.c
+++ b/src/mesa/drivers/dri/mga/mga_xmesa.c
@@ -69,13 +69,9 @@
#include "GL/internal/dri_interface.h"
-#define need_GL_ARB_multisample
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
#define need_GL_ARB_vertex_program
#define need_GL_EXT_fog_coord
#define need_GL_EXT_gpu_program_parameters
-#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_secondary_color
#if 0
#define need_GL_EXT_paletted_texture
@@ -133,6 +129,7 @@ mgaFillInModes( __DRIscreenPrivate *psp,
uint8_t depth_bits_array[3];
uint8_t stencil_bits_array[3];
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = 0;
@@ -147,6 +144,8 @@ mgaFillInModes( __DRIscreenPrivate *psp,
stencil_bits_array[1] = 0;
stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
+ msaa_samples_array[0] = 0;
+
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
back_buffer_factor = (have_back_buffer) ? 2 : 1;
@@ -162,7 +161,8 @@ mgaFillInModes( __DRIscreenPrivate *psp,
configs = driCreateConfigs(fb_format, fb_type,
depth_bits_array, stencil_bits_array,
depth_buffer_factor,
- back_buffer_modes, back_buffer_factor);
+ back_buffer_modes, back_buffer_factor,
+ msaa_samples_array, 1);
if (configs == NULL) {
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
__func__, __LINE__ );
@@ -385,13 +385,9 @@ static const struct dri_extension g400_extensions[] =
static const struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
{ "GL_ARB_texture_rectangle", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_blend_logic_op", NULL },
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
- { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
/* paletted_textures currently doesn't work, but we could fix them later */
#if defined( need_GL_EXT_paletted_texture )
{ "GL_EXT_shared_texture_palette", NULL },
@@ -539,6 +535,8 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
ctx->Const.MaxLineWidthAA = 10.0;
ctx->Const.LineWidthGranularity = 1.0;
+ ctx->Const.MaxDrawBuffers = 1;
+
mmesa->texture_depth = driQueryOptioni (&mmesa->optionCache,
"texture_depth");
if (mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
@@ -818,7 +816,7 @@ mgaCreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
mgaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
static void
diff --git a/src/mesa/drivers/dri/mga/mgapixel.c b/src/mesa/drivers/dri/mga/mgapixel.c
index 9f90047ba5..977dfa0b76 100644
--- a/src/mesa/drivers/dri/mga/mgapixel.c
+++ b/src/mesa/drivers/dri/mga/mgapixel.c
@@ -133,7 +133,7 @@ check_color_per_fragment_ops( const GLcontext *ctx )
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
- ctx->Stencil.Enabled ||
+ ctx->Stencil._Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
diff --git a/src/mesa/drivers/dri/mga/mgatex.c b/src/mesa/drivers/dri/mga/mgatex.c
index 2392622b90..33eb0be449 100644
--- a/src/mesa/drivers/dri/mga/mgatex.c
+++ b/src/mesa/drivers/dri/mga/mgatex.c
@@ -153,10 +153,14 @@ mgaSetTexFilter( mgaTextureObjectPtr t, GLenum minf, GLenum magf )
t->setup.texfilter |= val;
}
-static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4])
+static void mgaSetTexBorderColor(mgaTextureObjectPtr t, const GLfloat color[4])
{
- t->setup.texbordercol = PACK_COLOR_8888(color[3], color[0],
- color[1], color[2] );
+ GLubyte c[4];
+ CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
+ t->setup.texbordercol = PACK_COLOR_8888(c[3], c[0], c[1], c[2] );
}
@@ -329,7 +333,7 @@ mgaAllocTexObj( struct gl_texture_object *tObj )
mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
- mgaSetTexBorderColor( t, tObj->_BorderChan );
+ mgaSetTexBorderColor( t, tObj->BorderColor );
}
return( t );
@@ -458,7 +462,7 @@ mgaTexParameter( GLcontext *ctx, GLenum target,
case GL_TEXTURE_BORDER_COLOR:
FLUSH_BATCH(mmesa);
- mgaSetTexBorderColor(t, tObj->_BorderChan);
+ mgaSetTexBorderColor(t, tObj->BorderColor);
break;
case GL_TEXTURE_BASE_LEVEL:
diff --git a/src/mesa/drivers/dri/r128/r128_context.c b/src/mesa/drivers/dri/r128/r128_context.c
index 535a98cc01..f511a67bad 100644
--- a/src/mesa/drivers/dri/r128/r128_context.c
+++ b/src/mesa/drivers/dri/r128/r128_context.c
@@ -65,9 +65,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
int R128_DEBUG = 0;
#endif
-#define need_GL_ARB_multisample
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
#define need_GL_EXT_blend_minmax
#define need_GL_EXT_fog_coord
#define need_GL_EXT_secondary_color
@@ -75,12 +72,9 @@ int R128_DEBUG = 0;
const struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_multitexture", NULL },
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
{ "GL_ARB_texture_env_add", NULL },
{ "GL_ARB_texture_mirrored_repeat", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_blend_subtract", GL_EXT_blend_minmax_functions },
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
{ "GL_EXT_texture_edge_clamp", NULL },
@@ -229,6 +223,8 @@ GLboolean r128CreateContext( const __GLcontextModes *glVisual,
ctx->Const.MaxLineWidthAA = 1.0;
ctx->Const.LineWidthGranularity = 1.0;
+ ctx->Const.MaxDrawBuffers = 1;
+
#if ENABLE_PERF_BOXES
rmesa->boxes = driQueryOptionb(&rmesa->optionCache, "performance_boxes");
#endif
diff --git a/src/mesa/drivers/dri/r128/r128_screen.c b/src/mesa/drivers/dri/r128/r128_screen.c
index cb3a147dba..f5bcc2f290 100644
--- a/src/mesa/drivers/dri/r128/r128_screen.c
+++ b/src/mesa/drivers/dri/r128/r128_screen.c
@@ -353,7 +353,7 @@ r128CreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
@@ -422,7 +422,7 @@ r128FillInModes( __DRIscreenPrivate *psp,
uint8_t depth_bits_array[2];
uint8_t stencil_bits_array[2];
-
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = depth_bits;
depth_bits_array[1] = depth_bits;
@@ -434,6 +434,8 @@ r128FillInModes( __DRIscreenPrivate *psp,
stencil_bits_array[0] = 0;
stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+ msaa_samples_array[0] = 0;
+
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
back_buffer_factor = (have_back_buffer) ? 2 : 1;
@@ -446,26 +448,27 @@ r128FillInModes( __DRIscreenPrivate *psp,
fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
- configs = driCreateConfigs(fb_format, fb_type,
- depth_bits_array, stencil_bits_array,
- depth_buffer_factor, back_buffer_modes,
- back_buffer_factor);
- if (configs == NULL) {
- fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
- __LINE__);
- return NULL;
- }
+ configs = driCreateConfigs(fb_format, fb_type,
+ depth_bits_array, stencil_bits_array,
+ depth_buffer_factor, back_buffer_modes,
+ back_buffer_factor,
+ msaa_samples_array, 1);
+ if (configs == NULL) {
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+ __LINE__);
+ return NULL;
+ }
- /* Mark the visual as slow if there are "fake" stencil bits.
- */
- for (i = 0; configs[i]; i++) {
- m = &configs[i]->modes;
- if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
- m->visualRating = GLX_SLOW_CONFIG;
- }
- }
+ /* Mark the visual as slow if there are "fake" stencil bits.
+ */
+ for (i = 0; configs[i]; i++) {
+ m = &configs[i]->modes;
+ if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
+ m->visualRating = GLX_SLOW_CONFIG;
+ }
+ }
- return (const __DRIconfig **) configs;
+ return (const __DRIconfig **) configs;
}
diff --git a/src/mesa/drivers/dri/r128/r128_state.c b/src/mesa/drivers/dri/r128/r128_state.c
index 451dcd1b55..4ae7bf5b97 100644
--- a/src/mesa/drivers/dri/r128/r128_state.c
+++ b/src/mesa/drivers/dri/r128/r128_state.c
@@ -771,6 +771,11 @@ static void r128DDLightModelfv( GLcontext *ctx, GLenum pname,
FLUSH_BATCH( rmesa );
updateSpecularLighting(ctx);
}
+
+ if ( pname == GL_LIGHT_MODEL_TWO_SIDE ) {
+ FLUSH_BATCH( rmesa );
+ r128ChooseRenderState( ctx );
+ }
}
static void r128DDShadeModel( GLcontext *ctx, GLenum mode )
diff --git a/src/mesa/drivers/dri/r128/r128_tex.c b/src/mesa/drivers/dri/r128/r128_tex.c
index 3fc9c06cfa..0920270d7b 100644
--- a/src/mesa/drivers/dri/r128/r128_tex.c
+++ b/src/mesa/drivers/dri/r128/r128_tex.c
@@ -135,8 +135,13 @@ static void r128SetTexFilter( r128TexObjPtr t, GLenum minf, GLenum magf )
}
}
-static void r128SetTexBorderColor( r128TexObjPtr t, GLubyte c[4] )
+static void r128SetTexBorderColor( r128TexObjPtr t, const GLfloat color[4] )
{
+ GLubyte c[4];
+ CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
t->setup.tex_border_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
}
@@ -165,7 +170,7 @@ static r128TexObjPtr r128AllocTexObj( struct gl_texture_object *texObj )
r128SetTexWrap( t, texObj->WrapS, texObj->WrapT );
r128SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
- r128SetTexBorderColor( t, texObj->_BorderChan );
+ r128SetTexBorderColor( t, texObj->BorderColor );
}
return t;
@@ -531,7 +536,7 @@ static void r128TexParameter( GLcontext *ctx, GLenum target,
case GL_TEXTURE_BORDER_COLOR:
if ( t->base.bound ) FLUSH_BATCH( rmesa );
- r128SetTexBorderColor( t, tObj->_BorderChan );
+ r128SetTexBorderColor( t, tObj->BorderColor );
break;
case GL_TEXTURE_BASE_LEVEL:
diff --git a/src/mesa/drivers/dri/r128/r128_tris.c b/src/mesa/drivers/dri/r128/r128_tris.c
index bcc9ffa651..5b91271d74 100644
--- a/src/mesa/drivers/dri/r128/r128_tris.c
+++ b/src/mesa/drivers/dri/r128/r128_tris.c
@@ -426,7 +426,7 @@ r128_fallback_point( r128ContextPtr rmesa,
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
#define _R128_NEW_RENDER_STATE (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)
-static void r128ChooseRenderState(GLcontext *ctx)
+void r128ChooseRenderState(GLcontext *ctx)
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLuint flags = ctx->_TriangleCaps;
diff --git a/src/mesa/drivers/dri/r128/r128_tris.h b/src/mesa/drivers/dri/r128/r128_tris.h
index d90ca31534..c0667edb61 100644
--- a/src/mesa/drivers/dri/r128/r128_tris.h
+++ b/src/mesa/drivers/dri/r128/r128_tris.h
@@ -38,7 +38,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/mtypes.h"
extern void r128InitTriFuncs( GLcontext *ctx );
-
+extern void r128ChooseRenderState( GLcontext *ctx );
extern void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define FALLBACK( rmesa, bit, mode ) r128Fallback( rmesa->glCtx, bit, mode )
diff --git a/src/mesa/drivers/dri/r200/.gitignore b/src/mesa/drivers/dri/r200/.gitignore
deleted file mode 100644
index 3773d8ea73..0000000000
--- a/src/mesa/drivers/dri/r200/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-radeon_chipset.h
-radeon_screen.*
-server
diff --git a/src/mesa/drivers/dri/r200/Makefile b/src/mesa/drivers/dri/r200/Makefile
index e9144ac75c..42635bf9d9 100644
--- a/src/mesa/drivers/dri/r200/Makefile
+++ b/src/mesa/drivers/dri/r200/Makefile
@@ -3,6 +3,8 @@
TOP = ../../../../..
include $(TOP)/configs/current
+CFLAGS += $(RADEON_CFLAGS)
+
LIBNAME = r200_dri.so
MINIGLX_SOURCES = server/radeon_dri.c
@@ -11,44 +13,52 @@ ifeq ($(USING_EGL), 1)
EGL_SOURCES = server/radeon_egl.c
endif
+ifeq ($(RADEON_LDFLAGS),)
+CS_SOURCES = radeon_cs_space_drm.c
+endif
+
+RADEON_COMMON_SOURCES = \
+ radeon_bo_legacy.c \
+ radeon_common_context.c \
+ radeon_common.c \
+ radeon_cs_legacy.c \
+ radeon_dma.c \
+ radeon_debug.c \
+ radeon_fbo.c \
+ radeon_lock.c \
+ radeon_mipmap_tree.c \
+ radeon_queryobj.c \
+ radeon_span.c \
+ radeon_texture.c
+
+
DRIVER_SOURCES = r200_context.c \
r200_ioctl.c \
- r200_lock.c \
r200_state.c \
r200_state_init.c \
r200_cmdbuf.c \
r200_pixel.c \
r200_tex.c \
- r200_texmem.c \
r200_texstate.c \
r200_tcl.c \
r200_swtcl.c \
- r200_span.c \
r200_maos.c \
r200_sanity.c \
r200_fragshader.c \
r200_vertprog.c \
radeon_screen.c \
- $(EGL_SOURCES)
+ $(EGL_SOURCES) \
+ $(RADEON_COMMON_SOURCES) \
+ $(CS_SOURCES)
C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES)
X86_SOURCES =
-DRIVER_DEFINES = -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R200
-
-SYMLINKS = \
- server/radeon_egl.c \
- server/radeon_dri.c \
- server/radeon_dri.h \
- server/radeon.h \
- server/radeon_macros.h \
- server/radeon_reg.h
+DRIVER_DEFINES = -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R200 \
+ -Wall
-COMMON_SYMLINKS = \
- radeon_chipset.h \
- radeon_screen.c \
- radeon_screen.h
+DRI_LIB_DEPS += $(RADEON_LDFLAGS)
##### TARGETS #####
@@ -57,15 +67,4 @@ include ../Makefile.template
#INCLUDES += -I../radeon/server
-server:
- mkdir -p server
-
-$(SYMLINKS): server
- @[ -e $@ ] || ln -sf ../../radeon/$@ server/
-
-
-$(COMMON_SYMLINKS):
- @[ -e $@ ] || ln -sf ../radeon/$@ ./
-
-symlinks: $(SYMLINKS) $(COMMON_SYMLINKS)
-
+symlinks:
diff --git a/src/mesa/drivers/dri/r200/r200_cmdbuf.c b/src/mesa/drivers/dri/r200/r200_cmdbuf.c
index e1633772a1..1d1bea6f5f 100644
--- a/src/mesa/drivers/dri/r200/r200_cmdbuf.c
+++ b/src/mesa/drivers/dri/r200/r200_cmdbuf.c
@@ -38,6 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "swrast/swrast.h"
#include "main/simple_list.h"
+#include "radeon_common.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
@@ -45,160 +46,71 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r200_sanity.h"
#include "radeon_reg.h"
-static void print_state_atom( struct r200_state_atom *state )
-{
- int i;
-
- fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size);
-
- if (0 & R200_DEBUG & DEBUG_VERBOSE)
- for (i = 0 ; i < state->cmd_size ; i++)
- fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]);
-
-}
-
/* The state atoms will be emitted in the order they appear in the atom list,
* so this step is important.
*/
+#define insert_at_tail_if(atom_list, atom) \
+ do { \
+ struct radeon_state_atom* __atom = (atom); \
+ if (__atom->check) \
+ insert_at_tail((atom_list), __atom); \
+ } while(0)
+
void r200SetUpAtomList( r200ContextPtr rmesa )
{
int i, mtu;
- mtu = rmesa->glCtx->Const.MaxTextureUnits;
-
- make_empty_list(&rmesa->hw.atomlist);
- rmesa->hw.atomlist.name = "atom-list";
-
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ctx );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.set );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lin );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msk );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vpt );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vtx );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vap );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vte );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msc );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.cst );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.zbs );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tcl );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msl );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tcg );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.grd );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.fog );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tam );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tf );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.atf );
+ mtu = rmesa->radeon.glCtx->Const.MaxTextureUnits;
+
+ make_empty_list(&rmesa->radeon.hw.atomlist);
+ rmesa->radeon.hw.atomlist.name = "atom-list";
+
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ctx );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.set );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.lin );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msk );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpt );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vtx );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vap );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vte );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msc );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.cst );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.zbs );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcl );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msl );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcg );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.grd );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.fog );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tam );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tf );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.atf );
for (i = 0; i < mtu; ++i)
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tex[i] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i] );
for (i = 0; i < mtu; ++i)
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.cube[i] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i] );
for (i = 0; i < 6; ++i)
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.pix[i] );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.afs[0] );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.afs[1] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.pix[i] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[0] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[1] );
for (i = 0; i < 8; ++i)
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lit[i] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i] );
for (i = 0; i < 3 + mtu; ++i)
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mat[i] );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.eye );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.glt );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.eye );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.glt );
for (i = 0; i < 2; ++i)
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mtl[i] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.mtl[i] );
for (i = 0; i < 6; ++i)
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ucp[i] );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.spr );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ptp );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.prf );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.pvs );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vpp[0] );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vpp[1] );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vpi[0] );
- insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vpi[1] );
-}
-
-static void r200SaveHwState( r200ContextPtr rmesa )
-{
- struct r200_state_atom *atom;
- char * dest = rmesa->backup_store.cmd_buf;
-
- if (R200_DEBUG & DEBUG_STATE)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- rmesa->backup_store.cmd_used = 0;
-
- foreach( atom, &rmesa->hw.atomlist ) {
- if ( atom->check( rmesa->glCtx, atom->idx ) ) {
- int size = atom->cmd_size * 4;
- memcpy( dest, atom->cmd, size);
- dest += size;
- rmesa->backup_store.cmd_used += size;
- if (R200_DEBUG & DEBUG_STATE)
- print_state_atom( atom );
- }
- }
-
- assert( rmesa->backup_store.cmd_used <= R200_CMD_BUF_SZ );
- if (R200_DEBUG & DEBUG_STATE)
- fprintf(stderr, "Returning to r200EmitState\n");
-}
-
-void r200EmitState( r200ContextPtr rmesa )
-{
- char *dest;
- int mtu;
- struct r200_state_atom *atom;
-
- if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (rmesa->save_on_next_emit) {
- r200SaveHwState(rmesa);
- rmesa->save_on_next_emit = GL_FALSE;
- }
-
- if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
- return;
-
- mtu = rmesa->glCtx->Const.MaxTextureUnits;
-
- /* To avoid going across the entire set of states multiple times, just check
- * for enough space for the case of emitting all state, and inline the
- * r200AllocCmdBuf code here without all the checks.
- */
- r200EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size );
-
- /* we need to calculate dest after EnsureCmdBufSpace
- as we may flush the buffer - airlied */
- dest = rmesa->store.cmd_buf + rmesa->store.cmd_used;
- if (R200_DEBUG & DEBUG_STATE) {
- foreach( atom, &rmesa->hw.atomlist ) {
- if ( atom->dirty || rmesa->hw.all_dirty ) {
- if ( atom->check( rmesa->glCtx, atom->idx ) )
- print_state_atom( atom );
- else
- fprintf(stderr, "skip state %s\n", atom->name);
- }
- }
- }
-
- foreach( atom, &rmesa->hw.atomlist ) {
- if ( rmesa->hw.all_dirty )
- atom->dirty = GL_TRUE;
- if ( atom->dirty ) {
- if ( atom->check( rmesa->glCtx, atom->idx ) ) {
- int size = atom->cmd_size * 4;
- memcpy( dest, atom->cmd, size);
- dest += size;
- rmesa->store.cmd_used += size;
- atom->dirty = GL_FALSE;
- }
- }
- }
-
- assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ );
-
- rmesa->hw.is_dirty = GL_FALSE;
- rmesa->hw.all_dirty = GL_FALSE;
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.spr );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ptp );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.prf );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.pvs );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[0] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[1] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[0] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[1] );
+ insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.sci );
}
/* Fire a section of the retained (indexed_verts) buffer as a regular
@@ -208,51 +120,81 @@ void r200EmitVbufPrim( r200ContextPtr rmesa,
GLuint primitive,
GLuint vertex_nr )
{
- drm_radeon_cmd_header_t *cmd;
+ BATCH_LOCALS(&rmesa->radeon);
assert(!(primitive & R200_VF_PRIM_WALK_IND));
- r200EmitState( rmesa );
-
- if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
- fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
- rmesa->store.cmd_used/4, primitive, vertex_nr);
+ radeonEmitState(&rmesa->radeon);
- cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VBUF_BUFSZ,
- __FUNCTION__ );
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
- cmd[1].i = R200_CP_CMD_3D_DRAW_VBUF_2;
- cmd[2].i = (primitive |
- R200_VF_PRIM_WALK_LIST |
- R200_VF_COLOR_ORDER_RGBA |
- (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
+ radeon_print(RADEON_RENDER|RADEON_SWRENDER,RADEON_VERBOSE,
+ "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
+ rmesa->store.cmd_used/4, primitive, vertex_nr);
+
+ BEGIN_BATCH(3);
+ OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_VBUF_2, 0);
+ OUT_BATCH(primitive | R200_VF_PRIM_WALK_LIST | R200_VF_COLOR_ORDER_RGBA |
+ (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
+ END_BATCH();
}
+static void r200FireEB(r200ContextPtr rmesa, int vertex_count, int type)
+{
+ BATCH_LOCALS(&rmesa->radeon);
+
+ if (vertex_count > 0) {
+ BEGIN_BATCH(8+2);
+ OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_INDX_2, 0);
+ OUT_BATCH(R200_VF_PRIM_WALK_IND |
+ R200_VF_COLOR_ORDER_RGBA |
+ ((vertex_count + 0) << 16) |
+ type);
+
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ OUT_BATCH_PACKET3(R200_CP_CMD_INDX_BUFFER, 2);
+ OUT_BATCH((0x80 << 24) | (0 << 16) | 0x810);
+ OUT_BATCH_RELOC(rmesa->radeon.tcl.elt_dma_offset,
+ rmesa->radeon.tcl.elt_dma_bo,
+ rmesa->radeon.tcl.elt_dma_offset,
+ RADEON_GEM_DOMAIN_GTT, 0, 0);
+ OUT_BATCH((vertex_count + 1)/2);
+ } else {
+ OUT_BATCH_PACKET3(R200_CP_CMD_INDX_BUFFER, 2);
+ OUT_BATCH((0x80 << 24) | (0 << 16) | 0x810);
+ OUT_BATCH(rmesa->radeon.tcl.elt_dma_offset);
+ OUT_BATCH((vertex_count + 1)/2);
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.elt_dma_bo,
+ RADEON_GEM_DOMAIN_GTT, 0, 0);
+ }
+ END_BATCH();
+ }
+}
-void r200FlushElts( r200ContextPtr rmesa )
+void r200FlushElts(GLcontext *ctx)
{
- int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
- int dwords;
- int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2;
+ r200ContextPtr rmesa = R200_CONTEXT(ctx);
+ int nr, elt_used = rmesa->tcl.elt_used;
+
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %x %d\n", __FUNCTION__, rmesa->tcl.hw_primitive, elt_used);
+
+ assert( rmesa->radeon.dma.flush == r200FlushElts );
+ rmesa->radeon.dma.flush = NULL;
- if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
- fprintf(stderr, "%s\n", __FUNCTION__);
+ nr = elt_used / 2;
- assert( rmesa->dma.flush == r200FlushElts );
- rmesa->dma.flush = NULL;
+ radeon_bo_unmap(rmesa->radeon.tcl.elt_dma_bo);
- /* Cope with odd number of elts:
- */
- rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
- dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
+ r200FireEB(rmesa, nr, rmesa->tcl.hw_primitive);
- cmd[1] |= (dwords - 3) << 16;
- cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT;
+ radeon_bo_unref(rmesa->radeon.tcl.elt_dma_bo);
+ rmesa->radeon.tcl.elt_dma_bo = NULL;
- if (R200_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
- r200Finish( rmesa->glCtx );
+ if (R200_ELT_BUF_SZ > elt_used)
+ radeonReturnDmaRegion(&rmesa->radeon, R200_ELT_BUF_SZ - elt_used);
+
+ if (radeon_is_debug_enabled(RADEON_SYNC, RADEON_CRITICAL)) {
+ radeon_print(RADEON_SYNC, RADEON_NORMAL, "%s: Syncing\n", __FUNCTION__);
+ radeonFinish( rmesa->radeon.glCtx );
}
}
@@ -261,168 +203,153 @@ GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
GLuint primitive,
GLuint min_nr )
{
- drm_radeon_cmd_header_t *cmd;
GLushort *retval;
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
assert((primitive & R200_VF_PRIM_WALK_IND));
- r200EmitState( rmesa );
-
- cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, ELTS_BUFSZ(min_nr),
- __FUNCTION__ );
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
- cmd[1].i = R200_CP_CMD_3D_DRAW_INDX_2;
- cmd[2].i = (primitive |
- R200_VF_PRIM_WALK_IND |
- R200_VF_COLOR_ORDER_RGBA);
-
-
- retval = (GLushort *)(cmd+3);
+ radeonEmitState(&rmesa->radeon);
- if (R200_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s: header 0x%x prim %x \n",
- __FUNCTION__,
- cmd[1].i, primitive);
+ radeonAllocDmaRegion(&rmesa->radeon, &rmesa->radeon.tcl.elt_dma_bo,
+ &rmesa->radeon.tcl.elt_dma_offset, R200_ELT_BUF_SZ, 4);
+ rmesa->tcl.elt_used = min_nr * 2;
- assert(!rmesa->dma.flush);
- rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
- rmesa->dma.flush = r200FlushElts;
-
- rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
+ radeon_bo_map(rmesa->radeon.tcl.elt_dma_bo, 1);
+ retval = rmesa->radeon.tcl.elt_dma_bo->ptr + rmesa->radeon.tcl.elt_dma_offset;
+
+ assert(!rmesa->radeon.dma.flush);
+ rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ rmesa->radeon.dma.flush = r200FlushElts;
return retval;
}
+void r200EmitMaxVtxIndex(r200ContextPtr rmesa, int count)
+{
+ BATCH_LOCALS(&rmesa->radeon);
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ OUT_BATCH(CP_PACKET0(R200_SE_VF_MAX_VTX_INDX, 0));
+ OUT_BATCH(count);
+ END_BATCH();
+ }
+}
void r200EmitVertexAOS( r200ContextPtr rmesa,
- GLuint vertex_size,
- GLuint offset )
+ GLuint vertex_size,
+ struct radeon_bo *bo,
+ GLuint offset )
{
- drm_radeon_cmd_header_t *cmd;
+ BATCH_LOCALS(&rmesa->radeon);
- if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
- fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
+ radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s: vertex_size 0x%x offset 0x%x \n",
__FUNCTION__, vertex_size, offset);
- cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
- __FUNCTION__ );
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
- cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16);
- cmd[2].i = 1;
- cmd[3].i = vertex_size | (vertex_size << 8);
- cmd[4].i = offset;
+ BEGIN_BATCH(7);
+ OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, 2);
+ OUT_BATCH(1);
+ OUT_BATCH(vertex_size | (vertex_size << 8));
+ OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ END_BATCH();
}
-
-void r200EmitAOS( r200ContextPtr rmesa,
- struct r200_dma_region **component,
- GLuint nr,
- GLuint offset )
+void r200EmitAOS(r200ContextPtr rmesa, GLuint nr, GLuint offset)
{
- drm_radeon_cmd_header_t *cmd;
- int sz = AOS_BUFSZ(nr);
+ BATCH_LOCALS(&rmesa->radeon);
+ uint32_t voffset;
+ int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
int i;
- int *tmp;
-
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr);
-
- cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sz, __FUNCTION__ );
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
- cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (((sz / sizeof(int)) - 3) << 16);
- cmd[2].i = nr;
- tmp = &cmd[0].i;
- cmd += 3;
-
- for (i = 0 ; i < nr ; i++) {
- if (i & 1) {
- cmd[0].i |= ((component[i]->aos_stride << 24) |
- (component[i]->aos_size << 16));
- cmd[2].i = (component[i]->aos_start +
- offset * component[i]->aos_stride * 4);
- cmd += 3;
+
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE,
+ "%s: nr=%d, ofs=0x%08x\n",
+ __FUNCTION__, nr, offset);
+
+ BEGIN_BATCH(sz+2+ (nr*2));
+ OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, sz - 1);
+ OUT_BATCH(nr);
+
+
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ for (i = 0; i + 1 < nr; i += 2) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
+ (rmesa->radeon.tcl.aos[i].stride << 8) |
+ (rmesa->radeon.tcl.aos[i + 1].components << 16) |
+ (rmesa->radeon.tcl.aos[i + 1].stride << 24));
+
+ voffset = rmesa->radeon.tcl.aos[i + 0].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
+ OUT_BATCH_RELOC(voffset,
+ rmesa->radeon.tcl.aos[i].bo,
+ voffset,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ voffset = rmesa->radeon.tcl.aos[i + 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
+ OUT_BATCH_RELOC(voffset,
+ rmesa->radeon.tcl.aos[i+1].bo,
+ voffset,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
}
- else {
- cmd[0].i = ((component[i]->aos_stride << 8) |
- (component[i]->aos_size << 0));
- cmd[1].i = (component[i]->aos_start +
- offset * component[i]->aos_stride * 4);
+
+ if (nr & 1) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
+ (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
+ voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
+ OUT_BATCH_RELOC(voffset,
+ rmesa->radeon.tcl.aos[nr - 1].bo,
+ voffset,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ }
+ } else {
+ for (i = 0; i + 1 < nr; i += 2) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
+ (rmesa->radeon.tcl.aos[i].stride << 8) |
+ (rmesa->radeon.tcl.aos[i + 1].components << 16) |
+ (rmesa->radeon.tcl.aos[i + 1].stride << 24));
+
+ voffset = rmesa->radeon.tcl.aos[i + 0].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
+ OUT_BATCH(voffset);
+ voffset = rmesa->radeon.tcl.aos[i + 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
+ OUT_BATCH(voffset);
+ }
+
+ if (nr & 1) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
+ (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
+ voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
+ OUT_BATCH(voffset);
+ }
+ for (i = 0; i + 1 < nr; i += 2) {
+ voffset = rmesa->radeon.tcl.aos[i + 0].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.aos[i+0].bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ voffset = rmesa->radeon.tcl.aos[i + 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.aos[i+1].bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ }
+ if (nr & 1) {
+ voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.aos[nr-1].bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
}
}
-
- if (R200_DEBUG & DEBUG_VERTS) {
- fprintf(stderr, "%s:\n", __FUNCTION__);
- for (i = 0 ; i < sz ; i++)
- fprintf(stderr, " %d: %x\n", i, tmp[i]);
- }
-}
-
-void r200EmitBlit( r200ContextPtr rmesa,
- GLuint color_fmt,
- GLuint src_pitch,
- GLuint src_offset,
- GLuint dst_pitch,
- GLuint dst_offset,
- GLint srcx, GLint srcy,
- GLint dstx, GLint dsty,
- GLuint w, GLuint h )
-{
- drm_radeon_cmd_header_t *cmd;
-
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
- __FUNCTION__,
- src_pitch, src_offset, srcx, srcy,
- dst_pitch, dst_offset, dstx, dsty,
- w, h);
-
- assert( (src_pitch & 63) == 0 );
- assert( (dst_pitch & 63) == 0 );
- assert( (src_offset & 1023) == 0 );
- assert( (dst_offset & 1023) == 0 );
- assert( w < (1<<16) );
- assert( h < (1<<16) );
-
- cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 8 * sizeof(int),
- __FUNCTION__ );
-
-
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
- cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16);
- cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
- RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_NONE |
- (color_fmt << 8) |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_S |
- RADEON_DP_SRC_SOURCE_MEMORY |
- RADEON_GMC_CLR_CMP_CNTL_DIS |
- RADEON_GMC_WR_MSK_DIS );
-
- cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
- cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
- cmd[5].i = (srcx << 16) | srcy;
- cmd[6].i = (dstx << 16) | dsty; /* dst */
- cmd[7].i = (w << 16) | h;
-}
-
-
-void r200EmitWait( r200ContextPtr rmesa, GLuint flags )
-{
- drm_radeon_cmd_header_t *cmd;
-
- assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
-
- cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 1 * sizeof(int),
- __FUNCTION__ );
- cmd[0].i = 0;
- cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
- cmd[0].wait.flags = flags;
+ END_BATCH();
}
diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c
index 5531e0a739..3ddb5bf7d6 100644
--- a/src/mesa/drivers/dri/r200/r200_context.c
+++ b/src/mesa/drivers/dri/r200/r200_context.c
@@ -54,27 +54,27 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r200_context.h"
#include "r200_ioctl.h"
#include "r200_state.h"
-#include "r200_span.h"
#include "r200_pixel.h"
#include "r200_tex.h"
#include "r200_swtcl.h"
#include "r200_tcl.h"
#include "r200_maos.h"
#include "r200_vertprog.h"
+#include "radeon_queryobj.h"
-#define need_GL_ARB_multisample
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
+#include "radeon_span.h"
+
+#define need_GL_ARB_occlusion_query
#define need_GL_ARB_vertex_program
#define need_GL_ATI_fragment_shader
#define need_GL_EXT_blend_minmax
#define need_GL_EXT_fog_coord
-#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_secondary_color
#define need_GL_EXT_blend_equation_separate
#define need_GL_EXT_blend_func_separate
#define need_GL_NV_vertex_program
#define need_GL_ARB_point_parameters
+#define need_GL_EXT_framebuffer_object
#include "extension_helper.h"
#define DRIVER_DATE "20060602"
@@ -82,9 +82,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "vblank.h"
#include "utils.h"
#include "xmlpool.h" /* for symbolic values of enum-type options */
-#ifndef R200_DEBUG
-int R200_DEBUG = (0);
-#endif
/* Return various strings for glGetString().
*/
@@ -93,8 +90,8 @@ static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
r200ContextPtr rmesa = R200_CONTEXT(ctx);
static char buffer[128];
unsigned offset;
- GLuint agp_mode = (rmesa->r200Screen->card_type == RADEON_CARD_PCI)? 0 :
- rmesa->r200Screen->AGPMode;
+ GLuint agp_mode = (rmesa->radeon.radeonScreen->card_type == RADEON_CARD_PCI)? 0 :
+ rmesa->radeon.radeonScreen->AGPMode;
switch ( name ) {
case GL_VENDOR:
@@ -105,7 +102,7 @@ static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
agp_mode );
sprintf( & buffer[ offset ], " %sTCL",
- !(rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
+ !(rmesa->radeon.TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
? "" : "NO-" );
return (GLubyte *)buffer;
@@ -120,20 +117,18 @@ static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
*/
const struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_multitexture", NULL },
+ { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions},
{ "GL_ARB_texture_border_clamp", NULL },
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
{ "GL_ARB_texture_env_add", NULL },
{ "GL_ARB_texture_env_combine", NULL },
{ "GL_ARB_texture_env_dot3", NULL },
{ "GL_ARB_texture_env_crossbar", NULL },
{ "GL_ARB_texture_mirrored_repeat", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions },
{ "GL_EXT_blend_subtract", NULL },
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
- { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
+ { "GL_EXT_packed_depth_stencil", NULL},
{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
{ "GL_EXT_stencil_wrap", NULL },
{ "GL_EXT_texture_edge_clamp", NULL },
@@ -175,6 +170,11 @@ const struct dri_extension point_extensions[] = {
{ NULL, NULL }
};
+const struct dri_extension mm_extensions[] = {
+ { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+ { NULL, NULL }
+};
+
extern const struct tnl_pipeline_stage _r200_render_stage;
extern const struct tnl_pipeline_stage _r200_tcl_stage;
@@ -221,26 +221,54 @@ static void r200InitDriverFuncs( struct dd_function_table *functions )
functions->GetString = r200GetString;
}
-static const struct dri_debug_control debug_control[] =
+
+static void r200_get_lock(radeonContextPtr radeon)
{
- { "fall", DEBUG_FALLBACKS },
- { "tex", DEBUG_TEXTURE },
- { "ioctl", DEBUG_IOCTL },
- { "prim", DEBUG_PRIMS },
- { "vert", DEBUG_VERTS },
- { "state", DEBUG_STATE },
- { "code", DEBUG_CODEGEN },
- { "vfmt", DEBUG_VFMT },
- { "vtxf", DEBUG_VFMT },
- { "verb", DEBUG_VERBOSE },
- { "dri", DEBUG_DRI },
- { "dma", DEBUG_DMA },
- { "san", DEBUG_SANITY },
- { "sync", DEBUG_SYNC },
- { "pix", DEBUG_PIXEL },
- { "mem", DEBUG_MEMORY },
- { NULL, 0 }
-};
+ r200ContextPtr rmesa = (r200ContextPtr)radeon;
+ drm_radeon_sarea_t *sarea = radeon->sarea;
+
+ R200_STATECHANGE( rmesa, ctx );
+ if (rmesa->radeon.sarea->tiling_enabled) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
+ }
+ else rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &= ~R200_COLOR_TILE_ENABLE;
+
+ if ( sarea->ctx_owner != rmesa->radeon.dri.hwContext ) {
+ sarea->ctx_owner = rmesa->radeon.dri.hwContext;
+ if (!radeon->radeonScreen->kernel_mm)
+ radeon_bo_legacy_texture_age(radeon->radeonScreen->bom);
+ }
+
+}
+
+static void r200_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
+{
+}
+
+static void r200_emit_query_finish(radeonContextPtr radeon)
+{
+ BATCH_LOCALS(radeon);
+ struct radeon_query_object *query = radeon->query.current;
+
+ BEGIN_BATCH_NO_AUTOSTATE(4);
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0));
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ END_BATCH();
+ query->curr_offset += sizeof(uint32_t);
+ assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+ query->emitted_begin = GL_FALSE;
+}
+
+static void r200_init_vtbl(radeonContextPtr radeon)
+{
+ radeon->vtbl.get_lock = r200_get_lock;
+ radeon->vtbl.update_viewport_offset = r200UpdateViewportOffset;
+ radeon->vtbl.emit_cs_header = r200_vtbl_emit_cs_header;
+ radeon->vtbl.swtcl_flush = r200_swtcl_flush;
+ radeon->vtbl.fallback = r200Fallback;
+ radeon->vtbl.update_scissor = r200_vtbl_update_scissor;
+ radeon->vtbl.emit_query_finish = r200_emit_query_finish;
+}
/* Create the device specific rendering context.
@@ -253,9 +281,9 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
struct dd_function_table functions;
r200ContextPtr rmesa;
- GLcontext *ctx, *shareCtx;
+ GLcontext *ctx;
int i;
- int tcl_mode, fthrottle_mode;
+ int tcl_mode;
assert(glVisual);
assert(driContextPriv);
@@ -265,7 +293,8 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
rmesa = (r200ContextPtr) CALLOC( sizeof(*rmesa) );
if ( !rmesa )
return GL_FALSE;
-
+
+ r200_init_vtbl(&rmesa->radeon);
/* init exp fog table data */
r200InitStaticFogData();
@@ -273,12 +302,13 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
* Do this here so that initialMaxAnisotropy is set before we create
* the default textures.
*/
- driParseConfigFiles (&rmesa->optionCache, &screen->optionCache,
+ driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache,
screen->driScreen->myNum, "r200");
- rmesa->initialMaxAnisotropy = driQueryOptionf(&rmesa->optionCache,
- "def_max_anisotropy");
+ rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache,
+ "def_max_anisotropy");
- if ( driQueryOptionb( &rmesa->optionCache, "hyperz" ) ) {
+ if ( sPriv->drm_version.major == 1
+ && driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) {
if ( sPriv->drm_version.minor < 13 )
fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
"disabling.\n", sPriv->drm_version.minor );
@@ -295,63 +325,20 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
_mesa_init_driver_functions(&functions);
r200InitDriverFuncs(&functions);
r200InitIoctlFuncs(&functions);
- r200InitStateFuncs(&functions);
+ r200InitStateFuncs(&functions, screen->kernel_mm);
r200InitTextureFuncs(&functions);
r200InitShaderFuncs(&functions);
+ radeonInitQueryObjFunctions(&functions);
- /* Allocate and initialize the Mesa context */
- if (sharedContextPrivate)
- shareCtx = ((r200ContextPtr) sharedContextPrivate)->glCtx;
- else
- shareCtx = NULL;
- rmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
- &functions, (void *) rmesa);
- if (!rmesa->glCtx) {
- FREE(rmesa);
- return GL_FALSE;
+ if (!radeonInitContext(&rmesa->radeon, &functions,
+ glVisual, driContextPriv,
+ sharedContextPrivate)) {
+ FREE(rmesa);
+ return GL_FALSE;
}
- driContextPriv->driverPrivate = rmesa;
-
- /* Init r200 context data */
- rmesa->dri.context = driContextPriv;
- rmesa->dri.screen = sPriv;
- rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */
- rmesa->dri.hwContext = driContextPriv->hHWContext;
- rmesa->dri.hwLock = &sPriv->pSAREA->lock;
- rmesa->dri.fd = sPriv->fd;
- rmesa->dri.drmMinor = sPriv->drm_version.minor;
-
- rmesa->r200Screen = screen;
- rmesa->sarea = (drm_radeon_sarea_t *)((GLubyte *)sPriv->pSAREA +
- screen->sarea_priv_offset);
-
-
- rmesa->dma.buf0_address = rmesa->r200Screen->buffers->list[0].address;
-
- (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
- make_empty_list( & rmesa->swapped );
-
- rmesa->nr_heaps = 1 /* screen->numTexHeaps */ ;
- assert(rmesa->nr_heaps < RADEON_NR_TEX_HEAPS);
- for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
- rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
- screen->texSize[i],
- 12,
- RADEON_NR_TEX_REGIONS,
- (drmTextureRegionPtr)rmesa->sarea->tex_list[i],
- & rmesa->sarea->tex_age[i],
- & rmesa->swapped,
- sizeof( r200TexObj ),
- (destroy_texture_object_t *) r200DestroyTexObj );
- }
- rmesa->texture_depth = driQueryOptioni (&rmesa->optionCache,
- "texture_depth");
- if (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
- rmesa->texture_depth = ( screen->cpp == 4 ) ?
- DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
- rmesa->swtcl.RenderIndex = ~0;
- rmesa->hw.all_dirty = 1;
+ rmesa->radeon.swtcl.RenderIndex = ~0;
+ rmesa->radeon.hw.all_dirty = 1;
/* Set the maximum texture size small enough that we can guarentee that
* all texture units can bind a maximal texture and have all of them in
@@ -359,29 +346,20 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
* setting allow larger textures.
*/
- ctx = rmesa->glCtx;
- ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->optionCache,
+ ctx = rmesa->radeon.glCtx;
+ ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache,
"texture_units");
ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
- i = driQueryOptioni( &rmesa->optionCache, "allow_large_textures");
-
- driCalculateMaxTextureLevels( rmesa->texture_heaps,
- rmesa->nr_heaps,
- & ctx->Const,
- 4,
- 11, /* max 2D texture size is 2048x2048 */
-#if ENABLE_HW_3D_TEXTURE
- 8, /* max 3D texture size is 256^3 */
-#else
- 0, /* 3D textures unsupported */
-#endif
- 11, /* max cube texture size is 2048x2048 */
- 11, /* max texture rectangle size is 2048x2048 */
- 12,
- GL_FALSE,
- i );
+ i = driQueryOptioni( &rmesa->radeon.optionCache, "allow_large_textures");
+
+ /* FIXME: When no memory manager is available we should set this
+ * to some reasonable value based on texture memory pool size */
+ ctx->Const.MaxTextureLevels = 12;
+ ctx->Const.Max3DTextureLevels = 9;
+ ctx->Const.MaxCubeTextureLevels = 12;
+ ctx->Const.MaxTextureRectSize = 2048;
ctx->Const.MaxTextureMaxAnisotropy = 16.0;
@@ -391,7 +369,7 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
ctx->Const.MinPointSizeAA = 1.0;
ctx->Const.MaxPointSizeAA = 1.0;
ctx->Const.PointSizeGranularity = 0.0625;
- if (rmesa->r200Screen->drmSupportsPointSprites)
+ if (rmesa->radeon.radeonScreen->drmSupportsPointSprites)
ctx->Const.MaxPointSize = 2047.0;
else
ctx->Const.MaxPointSize = 1.0;
@@ -411,6 +389,10 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
ctx->Const.VertexProgram.MaxNativeParameters = R200_VSF_MAX_PARAM;
ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
+ ctx->Const.MaxDrawBuffers = 1;
+
+ _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
+
/* Initialize the software rasterizer and helper modules.
*/
_swrast_CreateContext( ctx );
@@ -445,33 +427,39 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
_math_matrix_set_identity( &rmesa->tmpmat );
driInitExtensions( ctx, card_extensions, GL_TRUE );
- if (!(rmesa->r200Screen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) {
+
+ if (rmesa->radeon.radeonScreen->kernel_mm)
+ driInitExtensions(ctx, mm_extensions, GL_FALSE);
+ if (!(rmesa->radeon.radeonScreen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) {
/* yuv textures don't work with some chips - R200 / rv280 okay so far
others get the bit ordering right but don't actually do YUV-RGB conversion */
_mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" );
}
- if (rmesa->glCtx->Mesa_DXTn) {
+ if (rmesa->radeon.glCtx->Mesa_DXTn) {
_mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
_mesa_enable_extension( ctx, "GL_S3_s3tc" );
}
- else if (driQueryOptionb (&rmesa->optionCache, "force_s3tc_enable")) {
+ else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) {
_mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
}
- if (rmesa->r200Screen->drmSupportsCubeMapsR200)
+ if (rmesa->radeon.radeonScreen->drmSupportsCubeMapsR200)
_mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" );
- if (rmesa->r200Screen->drmSupportsBlendColor) {
+ if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) {
driInitExtensions( ctx, blend_extensions, GL_FALSE );
}
- if(rmesa->r200Screen->drmSupportsVertexProgram)
+ if(rmesa->radeon.radeonScreen->drmSupportsVertexProgram)
driInitSingleExtension( ctx, ARB_vp_extension );
- if(driQueryOptionb(&rmesa->optionCache, "nv_vertex_program"))
+ if(driQueryOptionb(&rmesa->radeon.optionCache, "nv_vertex_program"))
driInitSingleExtension( ctx, NV_vp_extension );
- if ((ctx->Const.MaxTextureUnits == 6) && rmesa->r200Screen->drmSupportsFragShader)
+ if ((ctx->Const.MaxTextureUnits == 6) && rmesa->radeon.radeonScreen->drmSupportsFragShader)
driInitSingleExtension( ctx, ATI_fs_extension );
- if (rmesa->r200Screen->drmSupportsPointSprites)
+ if (rmesa->radeon.radeonScreen->drmSupportsPointSprites)
driInitExtensions( ctx, point_extensions, GL_FALSE );
+
+ if (!rmesa->radeon.radeonScreen->kernel_mm)
+ _mesa_disable_extension(ctx, "GL_ARB_occlusion_query");
#if 0
r200InitDriverFuncs( ctx );
r200InitIoctlFuncs( ctx );
@@ -480,236 +468,43 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
#endif
/* plug in a few more device driver functions */
/* XXX these should really go right after _mesa_init_driver_functions() */
+ radeon_fbo_init(&rmesa->radeon);
+ radeonInitSpanFuncs( ctx );
r200InitPixelFuncs( ctx );
- r200InitSpanFuncs( ctx );
r200InitTnlFuncs( ctx );
r200InitState( rmesa );
r200InitSwtcl( ctx );
- fthrottle_mode = driQueryOptioni(&rmesa->optionCache, "fthrottle_mode");
- rmesa->iw.irq_seq = -1;
- rmesa->irqsEmitted = 0;
- rmesa->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
- rmesa->r200Screen->irq);
-
- rmesa->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
-
- if (!rmesa->do_irqs)
- fprintf(stderr,
- "IRQ's not enabled, falling back to %s: %d %d\n",
- rmesa->do_usleeps ? "usleeps" : "busy waits",
- fthrottle_mode,
- rmesa->r200Screen->irq);
-
rmesa->prefer_gart_client_texturing =
(getenv("R200_GART_CLIENT_TEXTURES") != 0);
- (*sPriv->systemTime->getUST)( & rmesa->swap_ust );
-
-
-#if DO_DEBUG
- R200_DEBUG = driParseDebugString( getenv( "R200_DEBUG" ),
- debug_control );
- R200_DEBUG |= driParseDebugString( getenv( "RADEON_DEBUG" ),
- debug_control );
-#endif
-
- tcl_mode = driQueryOptioni(&rmesa->optionCache, "tcl_mode");
- if (driQueryOptionb(&rmesa->optionCache, "no_rast")) {
+ tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode");
+ if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) {
fprintf(stderr, "disabling 3D acceleration\n");
FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
}
else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") ||
- !(rmesa->r200Screen->chip_flags & RADEON_CHIPSET_TCL)) {
- if (rmesa->r200Screen->chip_flags & RADEON_CHIPSET_TCL) {
- rmesa->r200Screen->chip_flags &= ~RADEON_CHIPSET_TCL;
+ !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
+ if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
+ rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
fprintf(stderr, "Disabling HW TCL support\n");
}
- TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
+ TCL_FALLBACK(rmesa->radeon.glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
}
return GL_TRUE;
}
-/* Destroy the device specific context.
- */
-/* Destroy the Mesa and driver specific context data.
- */
void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
{
- GET_CURRENT_CONTEXT(ctx);
- r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
- r200ContextPtr current = ctx ? R200_CONTEXT(ctx) : NULL;
-
- /* check if we're deleting the currently bound context */
- if (rmesa == current) {
- R200_FIREVERTICES( rmesa );
- _mesa_make_current(NULL, NULL, NULL);
- }
-
- /* Free r200 context resources */
- assert(rmesa); /* should never be null */
- if ( rmesa ) {
- GLboolean release_texture_heaps;
-
-
- release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
- _swsetup_DestroyContext( rmesa->glCtx );
- _tnl_DestroyContext( rmesa->glCtx );
- _vbo_DestroyContext( rmesa->glCtx );
- _swrast_DestroyContext( rmesa->glCtx );
-
- r200DestroySwtcl( rmesa->glCtx );
- r200ReleaseArrays( rmesa->glCtx, ~0 );
-
- if (rmesa->dma.current.buf) {
- r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
- r200FlushCmdBuf( rmesa, __FUNCTION__ );
- }
-
- if (rmesa->state.scissor.pClipRects) {
- FREE(rmesa->state.scissor.pClipRects);
- rmesa->state.scissor.pClipRects = NULL;
- }
-
- if ( release_texture_heaps ) {
- /* This share group is about to go away, free our private
- * texture object data.
- */
- int i;
-
- for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
- driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
- rmesa->texture_heaps[ i ] = NULL;
- }
-
- assert( is_empty_list( & rmesa->swapped ) );
- }
-
- /* free the Mesa context */
- rmesa->glCtx->DriverCtx = NULL;
- _mesa_destroy_context( rmesa->glCtx );
-
- /* free the option cache */
- driDestroyOptionCache (&rmesa->optionCache);
-
- FREE( rmesa );
- }
-}
-
-
-
-
-void
-r200SwapBuffers( __DRIdrawablePrivate *dPriv )
-{
- if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
- r200ContextPtr rmesa;
- GLcontext *ctx;
- rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
- ctx = rmesa->glCtx;
- if (ctx->Visual.doubleBufferMode) {
- _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
- if ( rmesa->doPageFlip ) {
- r200PageFlip( dPriv );
- }
- else {
- r200CopyBuffer( dPriv, NULL );
- }
- }
- }
- else {
- /* XXX this shouldn't be an error but we can't handle it for now */
- _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
- }
-}
-
-void
-r200CopySubBuffer( __DRIdrawablePrivate *dPriv,
- int x, int y, int w, int h )
-{
- if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
- r200ContextPtr rmesa;
- GLcontext *ctx;
- rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
- ctx = rmesa->glCtx;
- if (ctx->Visual.doubleBufferMode) {
- drm_clip_rect_t rect;
- rect.x1 = x + dPriv->x;
- rect.y1 = (dPriv->h - y - h) + dPriv->y;
- rect.x2 = rect.x1 + w;
- rect.y2 = rect.y1 + h;
- _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
- r200CopyBuffer( dPriv, &rect );
- }
- }
- else {
- /* XXX this shouldn't be an error but we can't handle it for now */
- _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
- }
-}
-
-/* Force the context `c' to be the current context and associate with it
- * buffer `b'.
- */
-GLboolean
-r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
- __DRIdrawablePrivate *driDrawPriv,
- __DRIdrawablePrivate *driReadPriv )
-{
- if ( driContextPriv ) {
- r200ContextPtr newCtx =
- (r200ContextPtr) driContextPriv->driverPrivate;
-
- if (R200_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)newCtx->glCtx);
-
- newCtx->dri.readable = driReadPriv;
-
- if ( newCtx->dri.drawable != driDrawPriv ||
- newCtx->lastStamp != driDrawPriv->lastStamp ) {
- if (driDrawPriv->swap_interval == (unsigned)-1) {
- driDrawPriv->vblFlags = (newCtx->r200Screen->irq != 0)
- ? driGetDefaultVBlankFlags(&newCtx->optionCache)
- : VBLANK_FLAG_NO_IRQ;
-
- driDrawableInitVBlank( driDrawPriv );
- }
-
- newCtx->dri.drawable = driDrawPriv;
-
- r200SetCliprects(newCtx);
- r200UpdateViewportOffset( newCtx->glCtx );
- }
-
- _mesa_make_current( newCtx->glCtx,
- (GLframebuffer *) driDrawPriv->driverPrivate,
- (GLframebuffer *) driReadPriv->driverPrivate );
-
- _mesa_update_state( newCtx->glCtx );
- r200ValidateState( newCtx->glCtx );
-
- } else {
- if (R200_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
- _mesa_make_current( NULL, NULL, NULL );
- }
-
- if (R200_DEBUG & DEBUG_DRI)
- fprintf(stderr, "End %s\n", __FUNCTION__);
- return GL_TRUE;
-}
-
-/* Force the context `c' to be unbound from its buffer.
- */
-GLboolean
-r200UnbindContext( __DRIcontextPrivate *driContextPriv )
-{
- r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
-
- if (R200_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)rmesa->glCtx);
-
- return GL_TRUE;
+ int i;
+ r200ContextPtr rmesa = (r200ContextPtr)driContextPriv->driverPrivate;
+ if (rmesa)
+ {
+ for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
+ _math_matrix_dtr( &rmesa->TexGenMatrix[i] );
+ }
+ }
+ radeonDestroyContext(driContextPriv);
}
diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h
index 14a1dda46a..246f98c6dc 100644
--- a/src/mesa/drivers/dri/r200/r200_context.h
+++ b/src/mesa/drivers/dri/r200/r200_context.h
@@ -53,51 +53,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#error This driver requires a newer libdrm to compile
#endif
+#include "radeon_screen.h"
+#include "radeon_common.h"
+
+#include "radeon_lock.h"
+
struct r200_context;
typedef struct r200_context r200ContextRec;
typedef struct r200_context *r200ContextPtr;
-/* This union is used to avoid warnings/miscompilation
- with float to uint32_t casts due to strict-aliasing */
-typedef union { GLfloat f; uint32_t ui32; } float_ui32_type;
-
-#include "r200_lock.h"
-#include "radeon_screen.h"
#include "main/mm.h"
-/* Flags for software fallback cases */
-/* See correponding strings in r200_swtcl.c */
-#define R200_FALLBACK_TEXTURE 0x01
-#define R200_FALLBACK_DRAW_BUFFER 0x02
-#define R200_FALLBACK_STENCIL 0x04
-#define R200_FALLBACK_RENDER_MODE 0x08
-#define R200_FALLBACK_DISABLE 0x10
-#define R200_FALLBACK_BORDER_MODE 0x20
-
-/* The blit width for texture uploads
- */
-#define BLIT_WIDTH_BYTES 1024
-
-/* Use the templated vertex format:
- */
-#define COLOR_IS_RGBA
-#define TAG(x) r200##x
-#include "tnl_dd/t_dd_vertex.h"
-#undef TAG
-
-typedef void (*r200_tri_func)( r200ContextPtr,
- r200Vertex *,
- r200Vertex *,
- r200Vertex * );
-
-typedef void (*r200_line_func)( r200ContextPtr,
- r200Vertex *,
- r200Vertex * );
-
-typedef void (*r200_point_func)( r200ContextPtr,
- r200Vertex * );
-
-
struct r200_vertex_program {
struct gl_vertex_program mesa_program; /* Must be first */
int translated;
@@ -112,93 +78,11 @@ struct r200_vertex_program {
int fogmode;
};
-struct r200_colorbuffer_state {
- GLuint clear;
-#if 000
- GLint drawOffset, drawPitch;
-#endif
- int roundEnable;
-};
-
-
-struct r200_depthbuffer_state {
- GLuint clear;
- GLfloat scale;
-};
-
-#if 000
-struct r200_pixel_state {
- GLint readOffset, readPitch;
-};
-#endif
-
-struct r200_scissor_state {
- drm_clip_rect_t rect;
- GLboolean enabled;
-
- GLuint numClipRects; /* Cliprects active */
- GLuint numAllocedClipRects; /* Cliprects available */
- drm_clip_rect_t *pClipRects;
-};
-
-struct r200_stencilbuffer_state {
- GLboolean hwBuffer;
- GLuint clear; /* rb3d_stencilrefmask value */
-};
-
-struct r200_stipple_state {
- GLuint mask[32];
-};
-
-
-
-#define TEX_0 0x1
-#define TEX_1 0x2
-#define TEX_2 0x4
-#define TEX_3 0x8
-#define TEX_4 0x10
-#define TEX_5 0x20
-#define TEX_ALL 0x3f
-
-typedef struct r200_tex_obj r200TexObj, *r200TexObjPtr;
-
-/* Texture object in locally shared texture space.
- */
-struct r200_tex_obj {
- driTextureObject base;
-
- GLuint bufAddr; /* Offset to start of locally
- shared texture block */
-
- GLuint dirty_state; /* Flags (1 per texunit) for
- whether or not this texobj
- has dirty hardware state
- (pp_*) that needs to be
- brought into the
- texunit. */
-
- drm_radeon_tex_image_t image[6][RADEON_MAX_TEXTURE_LEVELS];
- /* Six, for the cube faces */
- GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
-
- GLuint pp_txfilter; /* hardware register values */
- GLuint pp_txformat;
- GLuint pp_txformat_x;
- GLuint pp_txoffset; /* Image location in texmem.
- All cube faces follow. */
- GLuint pp_txsize; /* npot only */
- GLuint pp_txpitch; /* npot only */
- GLuint pp_border_color;
- GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */
-
- GLboolean border_fallback;
-
- GLuint tile_bits; /* hw texture tile bits used on this texture */
-};
+#define R200_TEX_ALL 0x3f
struct r200_texture_env_state {
- r200TexObjPtr texobj;
+ radeonTexObjPtr texobj;
GLuint outputreg;
GLuint unitneeded;
};
@@ -210,19 +94,6 @@ struct r200_texture_state {
};
-struct r200_state_atom {
- struct r200_state_atom *next, *prev;
- const char *name; /* for debug */
- int cmd_size; /* size in bytes */
- GLuint idx;
- int *cmd; /* one or more cmd's */
- int *lastcmd; /* one or more cmd's */
- GLboolean dirty;
- GLboolean (*check)( GLcontext *, int ); /* is this state active? */
-};
-
-
-
/* Trying to keep these relatively short as the variables are becoming
* extravagently long. Drop the driver name prefix off the front of
* everything - I think we know which driver we're in by now, and keep the
@@ -596,182 +467,96 @@ struct r200_state_atom {
#define PRF_STATE_SIZE 3
-struct r200_hw_state {
- /* Head of the linked list of state atoms. */
- struct r200_state_atom atomlist;
+#define SCI_CMD_0 0
+#define SCI_RE_AUX 1
+#define SCI_CMD_1 2
+#define SCI_XY_1 3
+#define SCI_CMD_2 4
+#define SCI_XY_2 5
+#define SCI_STATE_SIZE 6
+
+#define R200_QUERYOBJ_CMD_0 0
+#define R200_QUERYOBJ_DATA_0 1
+#define R200_QUERYOBJ_CMDSIZE 2
+
+#define STP_CMD_0 0
+#define STP_DATA_0 1
+#define STP_CMD_1 2
+#define STP_STATE_SIZE 35
+struct r200_hw_state {
/* Hardware state, stored as cmdbuf commands:
* -- Need to doublebuffer for
* - reviving state after loss of context
* - eliding noop statechange loops? (except line stipple count)
*/
- struct r200_state_atom ctx;
- struct r200_state_atom set;
- struct r200_state_atom vte;
- struct r200_state_atom lin;
- struct r200_state_atom msk;
- struct r200_state_atom vpt;
- struct r200_state_atom vap;
- struct r200_state_atom vtx;
- struct r200_state_atom tcl;
- struct r200_state_atom msl;
- struct r200_state_atom tcg;
- struct r200_state_atom msc;
- struct r200_state_atom cst;
- struct r200_state_atom tam;
- struct r200_state_atom tf;
- struct r200_state_atom tex[6];
- struct r200_state_atom cube[6];
- struct r200_state_atom zbs;
- struct r200_state_atom mtl[2];
- struct r200_state_atom mat[9];
- struct r200_state_atom lit[8]; /* includes vec, scl commands */
- struct r200_state_atom ucp[6];
- struct r200_state_atom pix[6]; /* pixshader stages */
- struct r200_state_atom eye; /* eye pos */
- struct r200_state_atom grd; /* guard band clipping */
- struct r200_state_atom fog;
- struct r200_state_atom glt;
- struct r200_state_atom prf;
- struct r200_state_atom afs[2];
- struct r200_state_atom pvs;
- struct r200_state_atom vpi[2];
- struct r200_state_atom vpp[2];
- struct r200_state_atom atf;
- struct r200_state_atom spr;
- struct r200_state_atom ptp;
-
- int max_state_size; /* Number of bytes necessary for a full state emit. */
- GLboolean is_dirty, all_dirty;
+ struct radeon_state_atom ctx;
+ struct radeon_state_atom set;
+ struct radeon_state_atom sci;
+ struct radeon_state_atom vte;
+ struct radeon_state_atom lin;
+ struct radeon_state_atom msk;
+ struct radeon_state_atom vpt;
+ struct radeon_state_atom vap;
+ struct radeon_state_atom vtx;
+ struct radeon_state_atom tcl;
+ struct radeon_state_atom msl;
+ struct radeon_state_atom tcg;
+ struct radeon_state_atom msc;
+ struct radeon_state_atom cst;
+ struct radeon_state_atom tam;
+ struct radeon_state_atom tf;
+ struct radeon_state_atom tex[6];
+ struct radeon_state_atom cube[6];
+ struct radeon_state_atom zbs;
+ struct radeon_state_atom mtl[2];
+ struct radeon_state_atom mat[9];
+ struct radeon_state_atom lit[8]; /* includes vec, scl commands */
+ struct radeon_state_atom ucp[6];
+ struct radeon_state_atom pix[6]; /* pixshader stages */
+ struct radeon_state_atom eye; /* eye pos */
+ struct radeon_state_atom grd; /* guard band clipping */
+ struct radeon_state_atom fog;
+ struct radeon_state_atom glt;
+ struct radeon_state_atom prf;
+ struct radeon_state_atom afs[2];
+ struct radeon_state_atom pvs;
+ struct radeon_state_atom vpi[2];
+ struct radeon_state_atom vpp[2];
+ struct radeon_state_atom atf;
+ struct radeon_state_atom spr;
+ struct radeon_state_atom ptp;
+ struct radeon_state_atom stp;
};
struct r200_state {
/* Derived state for internal purposes:
*/
- struct r200_colorbuffer_state color;
- struct r200_depthbuffer_state depth;
-#if 00
- struct r200_pixel_state pixel;
-#endif
- struct r200_scissor_state scissor;
- struct r200_stencilbuffer_state stencil;
- struct r200_stipple_state stipple;
struct r200_texture_state texture;
GLuint envneeded;
};
-/* Need refcounting on dma buffers:
- */
-struct r200_dma_buffer {
- int refcount; /* the number of retained regions in buf */
- drmBufPtr buf;
-};
-
-#define GET_START(rvb) (rmesa->r200Screen->gart_buffer_offset + \
- (rvb)->address - rmesa->dma.buf0_address + \
- (rvb)->start)
-
-/* A retained region, eg vertices for indexed vertices.
- */
-struct r200_dma_region {
- struct r200_dma_buffer *buf;
- char *address; /* == buf->address */
- int start, end, ptr; /* offsets from start of buf */
- int aos_start;
- int aos_stride;
- int aos_size;
-};
-
-
-struct r200_dma {
- /* Active dma region. Allocations for vertices and retained
- * regions come from here. Also used for emitting random vertices,
- * these may be flushed by calling flush_current();
- */
- struct r200_dma_region current;
-
- void (*flush)( r200ContextPtr );
-
- char *buf0_address; /* start of buf[0], for index calcs */
- GLuint nr_released_bufs; /* flush after so many buffers released */
-};
-
-struct r200_dri_mirror {
- __DRIcontextPrivate *context; /* DRI context */
- __DRIscreenPrivate *screen; /* DRI screen */
- __DRIdrawablePrivate *drawable; /* DRI drawable bound to this ctx */
- __DRIdrawablePrivate *readable; /* DRI readable bound to this ctx */
-
- drm_context_t hwContext;
- drm_hw_lock_t *hwLock;
- int fd;
- int drmMinor;
-};
-
-
#define R200_CMD_BUF_SZ (16*1024)
-struct r200_store {
- GLuint statenr;
- GLuint primnr;
- char cmd_buf[R200_CMD_BUF_SZ];
- int cmd_used;
- int elts_start;
-};
-
-
+#define R200_ELT_BUF_SZ (16*1024)
/* r200_tcl.c
*/
struct r200_tcl_info {
GLuint hw_primitive;
-/* hw can handle 12 components max */
- struct r200_dma_region *aos_components[12];
- GLuint nr_aos_components;
-
- GLuint *Elts;
+ int elt_used;
- struct r200_dma_region indexed_verts;
- struct r200_dma_region vertex_data[15];
};
/* r200_swtcl.c
*/
struct r200_swtcl_info {
- GLuint RenderIndex;
-
- /**
- * Size of a hardware vertex. This is calculated when \c ::vertex_attrs is
- * installed in the Mesa state vector.
- */
- GLuint vertex_size;
- /**
- * Attributes instructing the Mesa TCL pipeline where / how to put vertex
- * data in the hardware buffer.
- */
- struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
- /**
- * Number of elements of \c ::vertex_attrs that are actually used.
- */
- GLuint vertex_attr_count;
-
- /**
- * Cached pointer to the buffer where Mesa will store vertex data.
- */
- GLubyte *verts;
-
- /* Fallback rasterization functions
- */
- r200_point_func draw_point;
- r200_line_func draw_line;
- r200_tri_func draw_tri;
-
- GLuint hw_primitive;
- GLenum render_primitive;
- GLuint numverts;
+ radeon_point_func draw_point;
+ radeon_line_func draw_line;
+ radeon_tri_func draw_tri;
/**
* Offset of the 4UB color data within a hardware (swtcl) vertex.
@@ -787,27 +572,10 @@ struct r200_swtcl_info {
* Should Mesa project vertex data or will the hardware do it?
*/
GLboolean needproj;
-
- struct r200_dma_region indexed_verts;
-};
-
-
-struct r200_ioctl {
- GLuint vertex_offset;
- GLuint vertex_size;
};
-#define R200_MAX_PRIMS 64
-
-
-
-struct r200_prim {
- GLuint start;
- GLuint end;
- GLuint prim;
-};
/* A maximum total of 29 elements per vertex: 3 floats for position, 3
* floats for normal, 4 floats for color, 4 bytes for secondary color,
@@ -822,9 +590,8 @@ struct r200_prim {
#define R200_MAX_VERTEX_SIZE ((3*6)+11)
-
struct r200_context {
- GLcontext *glCtx; /* Mesa context */
+ struct radeon_context radeon;
/* Driver and hardware state management
*/
@@ -832,56 +599,15 @@ struct r200_context {
struct r200_state state;
struct r200_vertex_program *curr_vp_hw;
- /* Texture object bookkeeping
- */
- unsigned nr_heaps;
- driTexHeap * texture_heaps[ RADEON_NR_TEX_HEAPS ];
- driTextureObject swapped;
- int texture_depth;
- float initialMaxAnisotropy;
-
- /* Rasterization and vertex state:
- */
- GLuint TclFallback;
- GLuint Fallback;
- GLuint NewGLState;
- DECLARE_RENDERINPUTS(tnl_index_bitset); /* index of bits for last tnl_install_attrs */
-
/* Vertex buffers
*/
- struct r200_ioctl ioctl;
- struct r200_dma dma;
- struct r200_store store;
- /* A full state emit as of the first state emit in the main store, in case
- * the context is lost.
- */
- struct r200_store backup_store;
-
- /* Page flipping
- */
- GLuint doPageFlip;
-
- /* Busy waiting
- */
- GLuint do_usleeps;
- GLuint do_irqs;
- GLuint irqsEmitted;
- drm_radeon_irq_wait_t iw;
+ struct radeon_ioctl ioctl;
+ struct radeon_store store;
/* Clientdata textures;
*/
GLuint prefer_gart_client_texturing;
- /* Drawable, cliprect and scissor information
- */
- GLuint numClipRects; /* Cliprects for the draw buffer */
- drm_clip_rect_t *pClipRects;
- unsigned int lastStamp;
- GLboolean lost_context;
- GLboolean save_on_next_emit;
- radeonScreenPtr r200Screen; /* Screen private DRI data */
- drm_radeon_sarea_t *sarea; /* Private SAREA data */
-
/* TCL stuff
*/
GLmatrix TexGenMatrix[R200_MAX_TEXTURE_UNITS];
@@ -893,15 +619,6 @@ struct r200_context {
GLuint TexGenCompSel;
GLmatrix tmpmat;
- /* buffer swap
- */
- int64_t swap_ust;
- int64_t swap_missed_ust;
-
- GLuint swap_count;
- GLuint swap_missed_count;
-
-
/* r200_tcl.c
*/
struct r200_tcl_info tcl;
@@ -910,14 +627,6 @@ struct r200_context {
*/
struct r200_swtcl_info swtcl;
- /* Mirrors of some DRI state
- */
- struct r200_dri_mirror dri;
-
- /* Configuration cache
- */
- driOptionCache optionCache;
-
GLboolean using_hyperz;
GLboolean texmicrotile;
@@ -927,28 +636,10 @@ struct r200_context {
#define R200_CONTEXT(ctx) ((r200ContextPtr)(ctx->DriverCtx))
-static INLINE GLuint r200PackColor( GLuint cpp,
- GLubyte r, GLubyte g,
- GLubyte b, GLubyte a )
-{
- switch ( cpp ) {
- case 2:
- return PACK_COLOR_565( r, g, b );
- case 4:
- return PACK_COLOR_8888( a, r, g, b );
- default:
- return 0;
- }
-}
-
-
extern void r200DestroyContext( __DRIcontextPrivate *driContextPriv );
extern GLboolean r200CreateContext( const __GLcontextModes *glVisual,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate);
-extern void r200SwapBuffers( __DRIdrawablePrivate *dPriv );
-extern void r200CopySubBuffer( __DRIdrawablePrivate * dPriv,
- int x, int y, int w, int h );
extern GLboolean r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv );
@@ -957,28 +648,9 @@ extern GLboolean r200UnbindContext( __DRIcontextPrivate *driContextPriv );
/* ================================================================
* Debugging:
*/
-#define DO_DEBUG 1
-#if DO_DEBUG
-extern int R200_DEBUG;
-#else
-#define R200_DEBUG 0
-#endif
+#define R200_DEBUG RADEON_DEBUG
+
-#define DEBUG_TEXTURE 0x001
-#define DEBUG_STATE 0x002
-#define DEBUG_IOCTL 0x004
-#define DEBUG_PRIMS 0x008
-#define DEBUG_VERTS 0x010
-#define DEBUG_FALLBACKS 0x020
-#define DEBUG_VFMT 0x040
-#define DEBUG_CODEGEN 0x080
-#define DEBUG_VERBOSE 0x100
-#define DEBUG_DRI 0x200
-#define DEBUG_DMA 0x400
-#define DEBUG_SANITY 0x800
-#define DEBUG_SYNC 0x1000
-#define DEBUG_PIXEL 0x2000
-#define DEBUG_MEMORY 0x4000
#endif /* __R200_CONTEXT_H__ */
diff --git a/src/mesa/drivers/dri/r200/r200_fragshader.c b/src/mesa/drivers/dri/r200/r200_fragshader.c
index d514b28219..85c1b7bdd1 100644
--- a/src/mesa/drivers/dri/r200/r200_fragshader.c
+++ b/src/mesa/drivers/dri/r200/r200_fragshader.c
@@ -522,7 +522,7 @@ static void r200UpdateFSConstants( GLcontext *ctx )
CLAMPED_FLOAT_TO_UBYTE(con_byte[2], ctx->ATIFragmentShader.GlobalConstants[i][2]);
CLAMPED_FLOAT_TO_UBYTE(con_byte[3], ctx->ATIFragmentShader.GlobalConstants[i][3]);
}
- rmesa->hw.atf.cmd[ATF_TFACTOR_0 + i] = r200PackColor (
+ rmesa->hw.atf.cmd[ATF_TFACTOR_0 + i] = radeonPackColor (
4, con_byte[0], con_byte[1], con_byte[2], con_byte[3] );
}
}
diff --git a/src/mesa/drivers/dri/r200/r200_ioctl.c b/src/mesa/drivers/dri/r200/r200_ioctl.c
index 0741e57af7..b238adb972 100644
--- a/src/mesa/drivers/dri/r200/r200_ioctl.c
+++ b/src/mesa/drivers/dri/r200/r200_ioctl.c
@@ -31,7 +31,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
-
+
#include <sched.h>
#include <errno.h>
@@ -41,6 +41,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/context.h"
#include "swrast/swrast.h"
+
+
+#include "radeon_common.h"
+#include "radeon_lock.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
@@ -54,635 +58,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R200_TIMEOUT 512
#define R200_IDLE_RETRY 16
-
-static void r200WaitForIdle( r200ContextPtr rmesa );
-
-
-/* At this point we were in FlushCmdBufLocked but we had lost our context, so
- * we need to unwire our current cmdbuf, hook the one with the saved state in
- * it, flush it, and then put the current one back. This is so commands at the
- * start of a cmdbuf can rely on the state being kept from the previous one.
- */
-static void r200BackUpAndEmitLostStateLocked( r200ContextPtr rmesa )
-{
- GLuint nr_released_bufs;
- struct r200_store saved_store;
-
- if (rmesa->backup_store.cmd_used == 0)
- return;
-
- if (R200_DEBUG & DEBUG_STATE)
- fprintf(stderr, "Emitting backup state on lost context\n");
-
- rmesa->lost_context = GL_FALSE;
-
- nr_released_bufs = rmesa->dma.nr_released_bufs;
- saved_store = rmesa->store;
- rmesa->dma.nr_released_bufs = 0;
- rmesa->store = rmesa->backup_store;
- r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
- rmesa->dma.nr_released_bufs = nr_released_bufs;
- rmesa->store = saved_store;
-}
-
-int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller )
-{
- int ret, i;
- drm_radeon_cmd_buffer_t cmd;
-
- if (rmesa->lost_context)
- r200BackUpAndEmitLostStateLocked( rmesa );
-
- if (R200_DEBUG & DEBUG_IOCTL) {
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (0 & R200_DEBUG & DEBUG_VERBOSE)
- for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 )
- fprintf(stderr, "%d: %x\n", i/4,
- *(int *)(&rmesa->store.cmd_buf[i]));
- }
-
- if (R200_DEBUG & DEBUG_DMA)
- fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__,
- rmesa->dma.nr_released_bufs);
-
-
- if (R200_DEBUG & DEBUG_SANITY) {
- if (rmesa->state.scissor.enabled)
- ret = r200SanityCmdBuffer( rmesa,
- rmesa->state.scissor.numClipRects,
- rmesa->state.scissor.pClipRects);
- else
- ret = r200SanityCmdBuffer( rmesa,
- rmesa->numClipRects,
- rmesa->pClipRects);
- if (ret) {
- fprintf(stderr, "drmSanityCommandWrite: %d\n", ret);
- goto out;
- }
- }
-
-
- if (R200_DEBUG & DEBUG_MEMORY) {
- if (! driValidateTextureHeaps( rmesa->texture_heaps, rmesa->nr_heaps,
- & rmesa->swapped ) ) {
- fprintf( stderr, "%s: texture memory is inconsistent - expect "
- "mangled textures\n", __FUNCTION__ );
- }
- }
-
-
- cmd.bufsz = rmesa->store.cmd_used;
- cmd.buf = rmesa->store.cmd_buf;
-
- if (rmesa->state.scissor.enabled) {
- cmd.nbox = rmesa->state.scissor.numClipRects;
- cmd.boxes = (drm_clip_rect_t *)rmesa->state.scissor.pClipRects;
- } else {
- cmd.nbox = rmesa->numClipRects;
- cmd.boxes = (drm_clip_rect_t *)rmesa->pClipRects;
- }
-
- ret = drmCommandWrite( rmesa->dri.fd,
- DRM_RADEON_CMDBUF,
- &cmd, sizeof(cmd) );
-
- if (ret)
- fprintf(stderr, "drmCommandWrite: %d\n", ret);
-
- if (R200_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "\nSyncing in %s\n\n", __FUNCTION__);
- r200WaitForIdleLocked( rmesa );
- }
-
-
- out:
- rmesa->store.primnr = 0;
- rmesa->store.statenr = 0;
- rmesa->store.cmd_used = 0;
- rmesa->dma.nr_released_bufs = 0;
- rmesa->save_on_next_emit = 1;
-
- return ret;
-}
-
-
-/* Note: does not emit any commands to avoid recursion on
- * r200AllocCmdBuf.
- */
-void r200FlushCmdBuf( r200ContextPtr rmesa, const char *caller )
-{
- int ret;
-
- LOCK_HARDWARE( rmesa );
-
- ret = r200FlushCmdBufLocked( rmesa, caller );
-
- UNLOCK_HARDWARE( rmesa );
-
- if (ret) {
- fprintf(stderr, "drmRadeonCmdBuffer: %d (exiting)\n", ret);
- exit(ret);
- }
-}
-
-
-/* =============================================================
- * Hardware vertex buffer handling
- */
-
-
-void r200RefillCurrentDmaRegion( r200ContextPtr rmesa )
-{
- struct r200_dma_buffer *dmabuf;
- int fd = rmesa->dri.fd;
- int index = 0;
- int size = 0;
- drmDMAReq dma;
- int ret;
-
- if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (rmesa->dma.flush) {
- rmesa->dma.flush( rmesa );
- }
-
- if (rmesa->dma.current.buf)
- r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
-
- if (rmesa->dma.nr_released_bufs > 4)
- r200FlushCmdBuf( rmesa, __FUNCTION__ );
-
- dma.context = rmesa->dri.hwContext;
- dma.send_count = 0;
- dma.send_list = NULL;
- dma.send_sizes = NULL;
- dma.flags = 0;
- dma.request_count = 1;
- dma.request_size = RADEON_BUFFER_SIZE;
- dma.request_list = &index;
- dma.request_sizes = &size;
- dma.granted_count = 0;
-
- LOCK_HARDWARE(rmesa); /* no need to validate */
-
- while (1) {
- ret = drmDMA( fd, &dma );
- if (ret == 0)
- break;
-
- if (rmesa->dma.nr_released_bufs) {
- r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
- }
-
- if (rmesa->do_usleeps) {
- UNLOCK_HARDWARE( rmesa );
- DO_USLEEP( 1 );
- LOCK_HARDWARE( rmesa );
- }
- }
-
- UNLOCK_HARDWARE(rmesa);
-
- if (R200_DEBUG & DEBUG_DMA)
- fprintf(stderr, "Allocated buffer %d\n", index);
-
- dmabuf = CALLOC_STRUCT( r200_dma_buffer );
- dmabuf->buf = &rmesa->r200Screen->buffers->list[index];
- dmabuf->refcount = 1;
-
- rmesa->dma.current.buf = dmabuf;
- rmesa->dma.current.address = dmabuf->buf->address;
- rmesa->dma.current.end = dmabuf->buf->total;
- rmesa->dma.current.start = 0;
- rmesa->dma.current.ptr = 0;
-}
-
-void r200ReleaseDmaRegion( r200ContextPtr rmesa,
- struct r200_dma_region *region,
- const char *caller )
-{
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (!region->buf)
- return;
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
-
- if (--region->buf->refcount == 0) {
- drm_radeon_cmd_header_t *cmd;
-
- if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
- fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
- region->buf->buf->idx);
-
- cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sizeof(*cmd),
- __FUNCTION__ );
- cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
- cmd->dma.buf_idx = region->buf->buf->idx;
- FREE(region->buf);
- rmesa->dma.nr_released_bufs++;
- }
-
- region->buf = NULL;
- region->start = 0;
-}
-
-/* Allocates a region from rmesa->dma.current. If there isn't enough
- * space in current, grab a new buffer (and discard what was left of current)
- */
-void r200AllocDmaRegion( r200ContextPtr rmesa,
- struct r200_dma_region *region,
- int bytes,
- int alignment )
-{
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
-
- if (region->buf)
- r200ReleaseDmaRegion( rmesa, region, __FUNCTION__ );
-
- alignment--;
- rmesa->dma.current.start = rmesa->dma.current.ptr =
- (rmesa->dma.current.ptr + alignment) & ~alignment;
-
- if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
- r200RefillCurrentDmaRegion( rmesa );
-
- region->start = rmesa->dma.current.start;
- region->ptr = rmesa->dma.current.start;
- region->end = rmesa->dma.current.start + bytes;
- region->address = rmesa->dma.current.address;
- region->buf = rmesa->dma.current.buf;
- region->buf->refcount++;
-
- rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
- rmesa->dma.current.start =
- rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
-
- assert( rmesa->dma.current.ptr <= rmesa->dma.current.end );
-}
-
-/* ================================================================
- * SwapBuffers with client-side throttling
- */
-
-static uint32_t r200GetLastFrame(r200ContextPtr rmesa)
-{
- drm_radeon_getparam_t gp;
- int ret;
- uint32_t frame;
-
- gp.param = RADEON_PARAM_LAST_FRAME;
- gp.value = (int *)&frame;
- ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
- &gp, sizeof(gp) );
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
- exit(1);
- }
-
- return frame;
-}
-
-static void r200EmitIrqLocked( r200ContextPtr rmesa )
-{
- drm_radeon_irq_emit_t ie;
- int ret;
-
- ie.irq_seq = &rmesa->iw.irq_seq;
- ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_IRQ_EMIT,
- &ie, sizeof(ie) );
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
- exit(1);
- }
-}
-
-
-static void r200WaitIrq( r200ContextPtr rmesa )
-{
- int ret;
-
- do {
- ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT,
- &rmesa->iw, sizeof(rmesa->iw) );
- } while (ret && (errno == EINTR || errno == EBUSY));
-
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
- exit(1);
- }
-}
-
-
-static void r200WaitForFrameCompletion( r200ContextPtr rmesa )
-{
- drm_radeon_sarea_t *sarea = rmesa->sarea;
-
- if (rmesa->do_irqs) {
- if (r200GetLastFrame(rmesa) < sarea->last_frame) {
- if (!rmesa->irqsEmitted) {
- while (r200GetLastFrame (rmesa) < sarea->last_frame)
- ;
- }
- else {
- UNLOCK_HARDWARE( rmesa );
- r200WaitIrq( rmesa );
- LOCK_HARDWARE( rmesa );
- }
- rmesa->irqsEmitted = 10;
- }
-
- if (rmesa->irqsEmitted) {
- r200EmitIrqLocked( rmesa );
- rmesa->irqsEmitted--;
- }
- }
- else {
- while (r200GetLastFrame (rmesa) < sarea->last_frame) {
- UNLOCK_HARDWARE( rmesa );
- if (rmesa->do_usleeps)
- DO_USLEEP( 1 );
- LOCK_HARDWARE( rmesa );
- }
- }
-}
-
-
-
-/* Copy the back color buffer to the front color buffer.
- */
-void r200CopyBuffer( __DRIdrawablePrivate *dPriv,
- const drm_clip_rect_t *rect)
-{
- r200ContextPtr rmesa;
- GLint nbox, i, ret;
- GLboolean missed_target;
- int64_t ust;
- __DRIscreenPrivate *psp = dPriv->driScreenPriv;
-
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
-
- rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
-
- if ( R200_DEBUG & DEBUG_IOCTL ) {
- fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, (void *)rmesa->glCtx );
- }
-
- R200_FIREVERTICES( rmesa );
-
- LOCK_HARDWARE( rmesa );
-
-
- /* Throttle the frame rate -- only allow one pending swap buffers
- * request at a time.
- */
- r200WaitForFrameCompletion( rmesa );
- if (!rect)
- {
- UNLOCK_HARDWARE( rmesa );
- driWaitForVBlank( dPriv, & missed_target );
- LOCK_HARDWARE( rmesa );
- }
-
- nbox = dPriv->numClipRects; /* must be in locked region */
-
- for ( i = 0 ; i < nbox ; ) {
- GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox );
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t *b = rmesa->sarea->boxes;
- GLint n = 0;
-
- for ( ; i < nr ; i++ ) {
-
- *b = box[i];
-
- if (rect)
- {
- if (rect->x1 > b->x1)
- b->x1 = rect->x1;
- if (rect->y1 > b->y1)
- b->y1 = rect->y1;
- if (rect->x2 < b->x2)
- b->x2 = rect->x2;
- if (rect->y2 < b->y2)
- b->y2 = rect->y2;
-
- if (b->x1 >= b->x2 || b->y1 >= b->y2)
- continue;
- }
-
- b++;
- n++;
- }
- rmesa->sarea->nbox = n;
-
- if (!n)
- continue;
-
- ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP );
-
- if ( ret ) {
- fprintf( stderr, "DRM_R200_SWAP_BUFFERS: return = %d\n", ret );
- UNLOCK_HARDWARE( rmesa );
- exit( 1 );
- }
- }
-
- UNLOCK_HARDWARE( rmesa );
- if (!rect)
- {
- rmesa->hw.all_dirty = GL_TRUE;
-
- rmesa->swap_count++;
- (*psp->systemTime->getUST)( & ust );
- if ( missed_target ) {
- rmesa->swap_missed_count++;
- rmesa->swap_missed_ust = ust - rmesa->swap_ust;
- }
-
- rmesa->swap_ust = ust;
-
- sched_yield();
- }
-}
-
-void r200PageFlip( __DRIdrawablePrivate *dPriv )
-{
- r200ContextPtr rmesa;
- GLint ret;
- GLboolean missed_target;
- __DRIscreenPrivate *psp = dPriv->driScreenPriv;
-
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
-
- rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
-
- if ( R200_DEBUG & DEBUG_IOCTL ) {
- fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__,
- rmesa->sarea->pfCurrentPage);
- }
-
- R200_FIREVERTICES( rmesa );
- LOCK_HARDWARE( rmesa );
-
- if (!dPriv->numClipRects) {
- UNLOCK_HARDWARE( rmesa );
- usleep( 10000 ); /* throttle invisible client 10ms */
- return;
- }
-
- /* Need to do this for the perf box placement:
- */
- {
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t *b = rmesa->sarea->boxes;
- b[0] = box[0];
- rmesa->sarea->nbox = 1;
- }
-
- /* Throttle the frame rate -- only allow a few pending swap buffers
- * request at a time.
- */
- r200WaitForFrameCompletion( rmesa );
- UNLOCK_HARDWARE( rmesa );
- driWaitForVBlank( dPriv, & missed_target );
- if ( missed_target ) {
- rmesa->swap_missed_count++;
- (void) (*psp->systemTime->getUST)( & rmesa->swap_missed_ust );
- }
- LOCK_HARDWARE( rmesa );
-
- ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP );
-
- UNLOCK_HARDWARE( rmesa );
-
- if ( ret ) {
- fprintf( stderr, "DRM_RADEON_FLIP: return = %d\n", ret );
- exit( 1 );
- }
-
- rmesa->swap_count++;
- (void) (*psp->systemTime->getUST)( & rmesa->swap_ust );
-
-#if 000
- if ( rmesa->sarea->pfCurrentPage == 1 ) {
- rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset;
- rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch;
- } else {
- rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset;
- rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch;
- }
-
- R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset
- + rmesa->r200Screen->fbLocation;
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
- if (rmesa->sarea->tiling_enabled) {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
- }
-#else
- /* Get ready for drawing next frame. Update the renderbuffers'
- * flippedOffset/Pitch fields so we draw into the right place.
- */
- driFlipRenderbuffers(rmesa->glCtx->WinSysDrawBuffer,
- rmesa->sarea->pfCurrentPage);
-
-
- r200UpdateDrawBuffer(rmesa->glCtx);
-#endif
-}
-
-
-/* ================================================================
- * Buffer clear
- */
-static void r200Clear( GLcontext *ctx, GLbitfield mask )
+static void r200KernelClear(GLcontext *ctx, GLuint flags)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
- GLuint flags = 0;
- GLuint color_mask = 0;
- GLint ret, i;
- GLint cx, cy, cw, ch;
-
- if ( R200_DEBUG & DEBUG_IOCTL ) {
- fprintf( stderr, "r200Clear\n");
- }
-
- {
- LOCK_HARDWARE( rmesa );
- UNLOCK_HARDWARE( rmesa );
- if ( dPriv->numClipRects == 0 )
- return;
- }
-
- r200Flush( ctx );
-
- if ( mask & BUFFER_BIT_FRONT_LEFT ) {
- flags |= RADEON_FRONT;
- color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~BUFFER_BIT_FRONT_LEFT;
- }
-
- if ( mask & BUFFER_BIT_BACK_LEFT ) {
- flags |= RADEON_BACK;
- color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~BUFFER_BIT_BACK_LEFT;
- }
-
- if ( mask & BUFFER_BIT_DEPTH ) {
- flags |= RADEON_DEPTH;
- mask &= ~BUFFER_BIT_DEPTH;
- }
-
- if ( (mask & BUFFER_BIT_STENCIL) && rmesa->state.stencil.hwBuffer ) {
- flags |= RADEON_STENCIL;
- mask &= ~BUFFER_BIT_STENCIL;
- }
-
- if ( mask ) {
- if (R200_DEBUG & DEBUG_FALLBACKS)
- fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
- _swrast_Clear( ctx, mask );
- }
-
- if ( !flags )
- return;
-
- if (rmesa->using_hyperz) {
- flags |= RADEON_USE_COMP_ZBUF;
-/* if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200)
- flags |= RADEON_USE_HIERZ; */
- if (!(rmesa->state.stencil.hwBuffer) ||
- ((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
- ((rmesa->state.stencil.clear & R200_STENCIL_WRITE_MASK) == R200_STENCIL_WRITE_MASK))) {
- flags |= RADEON_CLEAR_FASTZ;
- }
- }
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
+ GLint cx, cy, cw, ch, ret;
+ GLuint i;
- LOCK_HARDWARE( rmesa );
-
- /* compute region after locking: */
- cx = ctx->DrawBuffer->_Xmin;
- cy = ctx->DrawBuffer->_Ymin;
- cw = ctx->DrawBuffer->_Xmax - cx;
- ch = ctx->DrawBuffer->_Ymax - cy;
-
- /* Flip top to bottom */
- cx += dPriv->x;
- cy = dPriv->y + dPriv->h - cy - ch;
+ LOCK_HARDWARE( &rmesa->radeon );
/* Throttle the number of clear ioctls we do.
*/
@@ -693,7 +76,7 @@ static void r200Clear( GLcontext *ctx, GLbitfield mask )
gp.param = RADEON_PARAM_LAST_CLEAR;
gp.value = (int *)&clear;
- ret = drmCommandWriteRead( rmesa->dri.fd,
+ ret = drmCommandWriteRead( rmesa->radeon.dri.fd,
DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
if ( ret ) {
@@ -703,24 +86,34 @@ static void r200Clear( GLcontext *ctx, GLbitfield mask )
/* Clear throttling needs more thought.
*/
- if ( rmesa->sarea->last_clear - clear <= 25 ) {
+ if ( rmesa->radeon.sarea->last_clear - clear <= 25 ) {
break;
}
-
- if (rmesa->do_usleeps) {
- UNLOCK_HARDWARE( rmesa );
+
+ if (rmesa->radeon.do_usleeps) {
+ UNLOCK_HARDWARE( &rmesa->radeon );
DO_USLEEP( 1 );
- LOCK_HARDWARE( rmesa );
+ LOCK_HARDWARE( &rmesa->radeon );
}
}
/* Send current state to the hardware */
- r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
+ rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
+
+
+ /* compute region after locking: */
+ cx = ctx->DrawBuffer->_Xmin;
+ cy = ctx->DrawBuffer->_Ymin;
+ cw = ctx->DrawBuffer->_Xmax - cx;
+ ch = ctx->DrawBuffer->_Ymax - cy;
+ /* Flip top to bottom */
+ cx += dPriv->x;
+ cy = dPriv->y + dPriv->h - cy - ch;
for ( i = 0 ; i < dPriv->numClipRects ; ) {
GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t *b = rmesa->sarea->boxes;
+ drm_clip_rect_t *b = rmesa->radeon.sarea->boxes;
drm_radeon_clear_t clear;
drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
GLint n = 0;
@@ -755,17 +148,17 @@ static void r200Clear( GLcontext *ctx, GLbitfield mask )
}
}
- rmesa->sarea->nbox = n;
+ rmesa->radeon.sarea->nbox = n;
clear.flags = flags;
- clear.clear_color = rmesa->state.color.clear;
- clear.clear_depth = rmesa->state.depth.clear; /* needed for hyperz */
+ clear.clear_color = rmesa->radeon.state.color.clear;
+ clear.clear_depth = rmesa->radeon.state.depth.clear; /* needed for hyperz */
clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- clear.depth_mask = rmesa->state.stencil.clear;
+ clear.depth_mask = rmesa->radeon.state.stencil.clear;
clear.depth_boxes = depth_boxes;
n--;
- b = rmesa->sarea->boxes;
+ b = rmesa->radeon.sarea->boxes;
for ( ; n >= 0 ; n-- ) {
depth_boxes[n].f[CLEAR_X1] = (float)b[n].x1;
depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1;
@@ -774,84 +167,94 @@ static void r200Clear( GLcontext *ctx, GLbitfield mask )
depth_boxes[n].f[CLEAR_DEPTH] = ctx->Depth.Clear;
}
- ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR,
+ ret = drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_CLEAR,
&clear, sizeof(clear));
if ( ret ) {
- UNLOCK_HARDWARE( rmesa );
+ UNLOCK_HARDWARE( &rmesa->radeon );
fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
exit( 1 );
}
}
-
- UNLOCK_HARDWARE( rmesa );
- rmesa->hw.all_dirty = GL_TRUE;
+ UNLOCK_HARDWARE( &rmesa->radeon );
}
+/* ================================================================
+ * Buffer clear
+ */
+static void r200Clear( GLcontext *ctx, GLbitfield mask )
+{
+ r200ContextPtr rmesa = R200_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
+ GLuint flags = 0;
+ GLuint color_mask = 0;
+ GLuint orig_mask = mask;
+ if ( R200_DEBUG & RADEON_IOCTL ) {
+ if (rmesa->radeon.sarea)
+ fprintf( stderr, "r200Clear %x %d\n", mask, rmesa->radeon.sarea->pfCurrentPage);
+ else
+ fprintf( stderr, "r200Clear %x radeon->sarea is NULL\n", mask);
+ }
-void r200WaitForIdleLocked( r200ContextPtr rmesa )
-{
- int ret;
- int i = 0;
-
- do {
- ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_CP_IDLE);
- if (ret)
- DO_USLEEP( 1 );
- } while (ret && ++i < 100);
-
- if ( ret < 0 ) {
- UNLOCK_HARDWARE( rmesa );
- fprintf( stderr, "Error: R200 timed out... exiting\n" );
- exit( -1 );
- }
-}
+ {
+ LOCK_HARDWARE( &rmesa->radeon );
+ UNLOCK_HARDWARE( &rmesa->radeon );
+ if ( dPriv->numClipRects == 0 )
+ return;
+ }
+ radeonFlush( ctx );
-static void r200WaitForIdle( r200ContextPtr rmesa )
-{
- LOCK_HARDWARE(rmesa);
- r200WaitForIdleLocked( rmesa );
- UNLOCK_HARDWARE(rmesa);
-}
+ if ( mask & BUFFER_BIT_FRONT_LEFT ) {
+ flags |= RADEON_FRONT;
+ color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+ mask &= ~BUFFER_BIT_FRONT_LEFT;
+ }
+ if ( mask & BUFFER_BIT_BACK_LEFT ) {
+ flags |= RADEON_BACK;
+ color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+ mask &= ~BUFFER_BIT_BACK_LEFT;
+ }
-void r200Flush( GLcontext *ctx )
-{
- r200ContextPtr rmesa = R200_CONTEXT( ctx );
+ if ( mask & BUFFER_BIT_DEPTH ) {
+ flags |= RADEON_DEPTH;
+ mask &= ~BUFFER_BIT_DEPTH;
+ }
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ if ( (mask & BUFFER_BIT_STENCIL) ) {
+ flags |= RADEON_STENCIL;
+ mask &= ~BUFFER_BIT_STENCIL;
+ }
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
+ if ( mask ) {
+ if (R200_DEBUG & RADEON_FALLBACKS)
+ fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
+ _swrast_Clear( ctx, mask );
+ }
- r200EmitState( rmesa );
-
- if (rmesa->store.cmd_used)
- r200FlushCmdBuf( rmesa, __FUNCTION__ );
-}
+ if ( !flags )
+ return;
-/* Make sure all commands have been sent to the hardware and have
- * completed processing.
- */
-void r200Finish( GLcontext *ctx )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- r200Flush( ctx );
+ if (rmesa->using_hyperz) {
+ flags |= RADEON_USE_COMP_ZBUF;
+/* if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200)
+ flags |= RADEON_USE_HIERZ; */
+ if (!((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
+ ((rmesa->radeon.state.stencil.clear & R200_STENCIL_WRITE_MASK) == R200_STENCIL_WRITE_MASK))) {
+ flags |= RADEON_CLEAR_FASTZ;
+ }
+ }
- if (rmesa->do_irqs) {
- LOCK_HARDWARE( rmesa );
- r200EmitIrqLocked( rmesa );
- UNLOCK_HARDWARE( rmesa );
- r200WaitIrq( rmesa );
+ if (rmesa->radeon.radeonScreen->kernel_mm)
+ radeonUserClear(ctx, orig_mask);
+ else {
+ r200KernelClear(ctx, flags);
+ rmesa->radeon.hw.all_dirty = GL_TRUE;
}
- else
- r200WaitForIdle( rmesa );
}
-
/* This version of AllocateMemoryMESA allocates only GART memory, and
* only does so after the point at which the driver has been
* initialized.
@@ -862,7 +265,7 @@ void r200Finish( GLcontext *ctx )
* device fd.
*/
void *r200AllocateMemoryMESA(__DRIscreen *screen, GLsizei size,
- GLfloat readfreq, GLfloat writefreq,
+ GLfloat readfreq, GLfloat writefreq,
GLfloat priority)
{
GET_CURRENT_CONTEXT(ctx);
@@ -871,11 +274,11 @@ void *r200AllocateMemoryMESA(__DRIscreen *screen, GLsizei size,
drm_radeon_mem_alloc_t alloc;
int ret;
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
+ if (R200_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
writefreq, priority);
- if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || !rmesa->r200Screen->gartTextures.map)
+ if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || !rmesa->radeon.radeonScreen->gartTextures.map)
return NULL;
if (getenv("R200_NO_ALLOC"))
@@ -886,17 +289,17 @@ void *r200AllocateMemoryMESA(__DRIscreen *screen, GLsizei size,
alloc.size = size;
alloc.region_offset = &region_offset;
- ret = drmCommandWriteRead( rmesa->r200Screen->driScreen->fd,
+ ret = drmCommandWriteRead( rmesa->radeon.radeonScreen->driScreen->fd,
DRM_RADEON_ALLOC,
&alloc, sizeof(alloc));
-
+
if (ret) {
fprintf(stderr, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__, ret);
return NULL;
}
-
+
{
- char *region_start = (char *)rmesa->r200Screen->gartTextures.map;
+ char *region_start = (char *)rmesa->radeon.radeonScreen->gartTextures.map;
return (void *)(region_start + region_offset);
}
}
@@ -911,31 +314,31 @@ void r200FreeMemoryMESA(__DRIscreen *screen, GLvoid *pointer)
drm_radeon_mem_free_t memfree;
int ret;
- if (R200_DEBUG & DEBUG_IOCTL)
+ if (R200_DEBUG & RADEON_IOCTL)
fprintf(stderr, "%s %p\n", __FUNCTION__, pointer);
- if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || !rmesa->r200Screen->gartTextures.map) {
+ if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || !rmesa->radeon.radeonScreen->gartTextures.map) {
fprintf(stderr, "%s: no context\n", __FUNCTION__);
return;
}
- region_offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map;
+ region_offset = (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
- if (region_offset < 0 ||
- region_offset > rmesa->r200Screen->gartTextures.size) {
+ if (region_offset < 0 ||
+ region_offset > rmesa->radeon.radeonScreen->gartTextures.size) {
fprintf(stderr, "offset %d outside range 0..%d\n", region_offset,
- rmesa->r200Screen->gartTextures.size);
+ rmesa->radeon.radeonScreen->gartTextures.size);
return;
}
memfree.region = RADEON_MEM_REGION_GART;
memfree.region_offset = region_offset;
-
- ret = drmCommandWrite( rmesa->r200Screen->driScreen->fd,
+
+ ret = drmCommandWrite( rmesa->radeon.radeonScreen->driScreen->fd,
DRM_RADEON_FREE,
&memfree, sizeof(memfree));
-
- if (ret)
+
+ if (ret)
fprintf(stderr, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__, ret);
}
@@ -956,32 +359,32 @@ GLuint r200GetMemoryOffsetMESA(__DRIscreen *screen, const GLvoid *pointer)
card_offset = r200GartOffsetFromVirtual( rmesa, pointer );
- return card_offset - rmesa->r200Screen->gart_base;
+ return card_offset - rmesa->radeon.radeonScreen->gart_base;
}
GLboolean r200IsGartMemory( r200ContextPtr rmesa, const GLvoid *pointer,
GLint size )
{
- ptrdiff_t offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map;
+ ptrdiff_t offset = (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
int valid = (size >= 0 &&
offset >= 0 &&
- offset + size < rmesa->r200Screen->gartTextures.size);
+ offset + size < rmesa->radeon.radeonScreen->gartTextures.size);
- if (R200_DEBUG & DEBUG_IOCTL)
+ if (R200_DEBUG & RADEON_IOCTL)
fprintf(stderr, "r200IsGartMemory( %p ) : %d\n", pointer, valid );
-
+
return valid;
}
GLuint r200GartOffsetFromVirtual( r200ContextPtr rmesa, const GLvoid *pointer )
{
- ptrdiff_t offset = (char *)pointer - (char *)rmesa->r200Screen->gartTextures.map;
+ ptrdiff_t offset = (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
- if (offset < 0 || offset > rmesa->r200Screen->gartTextures.size)
+ if (offset < 0 || offset > rmesa->radeon.radeonScreen->gartTextures.size)
return ~0;
else
- return rmesa->r200Screen->gart_texture_offset + offset;
+ return rmesa->radeon.radeonScreen->gart_texture_offset + offset;
}
@@ -989,7 +392,7 @@ GLuint r200GartOffsetFromVirtual( r200ContextPtr rmesa, const GLvoid *pointer )
void r200InitIoctlFuncs( struct dd_function_table *functions )
{
functions->Clear = r200Clear;
- functions->Finish = r200Finish;
- functions->Flush = r200Flush;
+ functions->Finish = radeonFinish;
+ functions->Flush = radeonFlush;
}
diff --git a/src/mesa/drivers/dri/r200/r200_ioctl.h b/src/mesa/drivers/dri/r200/r200_ioctl.h
index f7458e4a0e..8d51aefa04 100644
--- a/src/mesa/drivers/dri/r200/r200_ioctl.h
+++ b/src/mesa/drivers/dri/r200/r200_ioctl.h
@@ -37,65 +37,31 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/simple_list.h"
#include "radeon_dri.h"
-#include "r200_lock.h"
+
+#include "radeon_bocs_wrapper.h"
#include "xf86drm.h"
#include "drm.h"
#include "radeon_drm.h"
-extern void r200EmitState( r200ContextPtr rmesa );
+extern void r200EmitMaxVtxIndex(r200ContextPtr rmesa, int count);
extern void r200EmitVertexAOS( r200ContextPtr rmesa,
- GLuint vertex_size,
- GLuint offset );
+ GLuint vertex_size,
+ struct radeon_bo *bo,
+ GLuint offset );
extern void r200EmitVbufPrim( r200ContextPtr rmesa,
GLuint primitive,
GLuint vertex_nr );
-extern void r200FlushElts( r200ContextPtr rmesa );
+extern void r200FlushElts(GLcontext *ctx);
extern GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
GLuint primitive,
GLuint min_nr );
-extern void r200EmitAOS( r200ContextPtr rmesa,
- struct r200_dma_region **regions,
- GLuint n,
- GLuint offset );
-
-extern void r200EmitBlit( r200ContextPtr rmesa,
- GLuint color_fmt,
- GLuint src_pitch,
- GLuint src_offset,
- GLuint dst_pitch,
- GLuint dst_offset,
- GLint srcx, GLint srcy,
- GLint dstx, GLint dsty,
- GLuint w, GLuint h );
-
-extern void r200EmitWait( r200ContextPtr rmesa, GLuint flags );
-
-extern void r200FlushCmdBuf( r200ContextPtr rmesa, const char * );
-extern int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller );
-
-extern void r200RefillCurrentDmaRegion( r200ContextPtr rmesa );
-
-extern void r200AllocDmaRegion( r200ContextPtr rmesa,
- struct r200_dma_region *region,
- int bytes,
- int alignment );
-
-extern void r200ReleaseDmaRegion( r200ContextPtr rmesa,
- struct r200_dma_region *region,
- const char *caller );
-
-extern void r200CopyBuffer( __DRIdrawablePrivate *drawable,
- const drm_clip_rect_t *rect);
-extern void r200PageFlip( __DRIdrawablePrivate *drawable );
-extern void r200Flush( GLcontext *ctx );
-extern void r200Finish( GLcontext *ctx );
-extern void r200WaitForIdleLocked( r200ContextPtr rmesa );
-extern void r200WaitForVBlank( r200ContextPtr rmesa );
+extern void r200EmitAOS(r200ContextPtr rmesa, GLuint nr, GLuint offset);
+
extern void r200InitIoctlFuncs( struct dd_function_table *functions );
extern void *r200AllocateMemoryMESA( __DRIscreen *screen, GLsizei size, GLfloat readfreq,
@@ -119,8 +85,8 @@ void r200SetUpAtomList( r200ContextPtr rmesa );
*/
#define R200_NEWPRIM( rmesa ) \
do { \
- if ( rmesa->dma.flush ) \
- rmesa->dma.flush( rmesa ); \
+ if ( rmesa->radeon.dma.flush ) \
+ rmesa->radeon.dma.flush( rmesa->radeon.glCtx ); \
} while (0)
/* Can accomodate several state changes and primitive changes without
@@ -130,22 +96,32 @@ do { \
do { \
R200_NEWPRIM( rmesa ); \
rmesa->hw.ATOM.dirty = GL_TRUE; \
- rmesa->hw.is_dirty = GL_TRUE; \
+ rmesa->radeon.hw.is_dirty = GL_TRUE; \
} while (0)
+#define R200_SET_STATE( rmesa, ATOM, index, newvalue ) \
+ do { \
+ uint32_t __index = (index); \
+ uint32_t __dword = (newvalue); \
+ if (__dword != (rmesa)->hw.ATOM.cmd[__index]) { \
+ R200_STATECHANGE( (rmesa), ATOM ); \
+ (rmesa)->hw.ATOM.cmd[__index] = __dword; \
+ } \
+ } while(0)
+
#define R200_DB_STATE( ATOM ) \
memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \
rmesa->hw.ATOM.cmd_size * 4)
static INLINE int R200_DB_STATECHANGE(
r200ContextPtr rmesa,
- struct r200_state_atom *atom )
+ struct radeon_state_atom *atom )
{
if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) {
- int *tmp;
+ GLuint *tmp;
R200_NEWPRIM( rmesa );
atom->dirty = GL_TRUE;
- rmesa->hw.is_dirty = GL_TRUE;
+ rmesa->radeon.hw.is_dirty = GL_TRUE;
tmp = atom->cmd;
atom->cmd = atom->lastcmd;
atom->lastcmd = tmp;
@@ -156,54 +132,47 @@ static INLINE int R200_DB_STATECHANGE(
}
-/* Fire the buffered vertices no matter what.
- */
-#define R200_FIREVERTICES( rmesa ) \
-do { \
- if ( rmesa->store.cmd_used || rmesa->dma.flush ) { \
- r200Flush( rmesa->glCtx ); \
- } \
-} while (0)
-
/* Command lengths. Note that any time you ensure ELTS_BUFSZ or VBUF_BUFSZ
* are available, you will also be adding an rmesa->state.max_state_size because
* r200EmitState is called from within r200EmitVbufPrim and r200FlushElts.
*/
-#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2)) * sizeof(int))
-#define VERT_AOS_BUFSZ (5 * sizeof(int))
+#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2) + nr*2))
+#define VERT_AOS_BUFSZ (5)
#define ELTS_BUFSZ(nr) (12 + nr * 2)
-#define VBUF_BUFSZ (3 * sizeof(int))
-
-/* Ensure that a minimum amount of space is available in the command buffer.
- * This is used to ensure atomicity of state updates with the rendering requests
- * that rely on them.
- *
- * An alternative would be to implement a "soft lock" such that when the buffer
- * wraps at an inopportune time, we grab the lock, flush the current buffer,
- * and hang on to the lock until the critical section is finished and we flush
- * the buffer again and unlock.
- */
-static INLINE void r200EnsureCmdBufSpace( r200ContextPtr rmesa, int bytes )
-{
- if (rmesa->store.cmd_used + bytes > R200_CMD_BUF_SZ)
- r200FlushCmdBuf( rmesa, __FUNCTION__ );
- assert( bytes <= R200_CMD_BUF_SZ );
-}
+#define VBUF_BUFSZ (3)
+#define SCISSOR_BUFSZ (8)
+#define INDEX_BUFSZ (8+2)
-/* Alloc space in the command buffer
- */
-static INLINE char *r200AllocCmdBuf( r200ContextPtr rmesa,
- int bytes, const char *where )
+static inline uint32_t cmdpacket3(int cmd_type)
{
- char * head;
+ drm_radeon_cmd_header_t cmd;
- if (rmesa->store.cmd_used + bytes > R200_CMD_BUF_SZ)
- r200FlushCmdBuf( rmesa, where );
+ cmd.i = 0;
+ cmd.header.cmd_type = cmd_type;
+
+ return (uint32_t)cmd.i;
- head = rmesa->store.cmd_buf + rmesa->store.cmd_used;
- rmesa->store.cmd_used += bytes;
- assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ );
- return head;
}
+#define OUT_BATCH_PACKET3(packet, num_extra) do { \
+ if (!b_l_rmesa->radeonScreen->kernel_mm) { \
+ OUT_BATCH(cmdpacket3(RADEON_CMD_PACKET3)); \
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
+ } else { \
+ OUT_BATCH(CP_PACKET2); \
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
+ } \
+ } while(0)
+
+#define OUT_BATCH_PACKET3_CLIP(packet, num_extra) do { \
+ if (!b_l_rmesa->radeonScreen->kernel_mm) { \
+ OUT_BATCH(cmdpacket3(RADEON_CMD_PACKET3_CLIP)); \
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
+ } else { \
+ OUT_BATCH(CP_PACKET2); \
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
+ } \
+ } while(0)
+
+
#endif /* __R200_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/r200/r200_lock.c b/src/mesa/drivers/dri/r200/r200_lock.c
deleted file mode 100644
index 99661a4bfb..0000000000
--- a/src/mesa/drivers/dri/r200/r200_lock.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "r200_context.h"
-#include "r200_lock.h"
-#include "r200_tex.h"
-#include "r200_state.h"
-#include "r200_ioctl.h"
-
-#include "drirenderbuffer.h"
-
-
-#if DEBUG_LOCKING
-char *prevLockFile = NULL;
-int prevLockLine = 0;
-#endif
-
-/* Turn on/off page flipping according to the flags in the sarea:
- */
-static void
-r200UpdatePageFlipping( r200ContextPtr rmesa )
-{
- rmesa->doPageFlip = rmesa->sarea->pfState;
- if (rmesa->glCtx->WinSysDrawBuffer) {
- driFlipRenderbuffers(rmesa->glCtx->WinSysDrawBuffer,
- rmesa->sarea->pfCurrentPage);
- }
-}
-
-
-
-/* Update the hardware state. This is called if another main/context.has
- * grabbed the hardware lock, which includes the X server. This
- * function also updates the driver's window state after the X server
- * moves, resizes or restacks a window -- the change will be reflected
- * in the drawable position and clip rects. Since the X server grabs
- * the hardware lock when it changes the window state, this routine will
- * automatically be called after such a change.
- */
-void r200GetLock( r200ContextPtr rmesa, GLuint flags )
-{
- __DRIdrawablePrivate *drawable = rmesa->dri.drawable;
- __DRIdrawablePrivate *readable = rmesa->dri.readable;
- __DRIscreenPrivate *sPriv = rmesa->dri.screen;
- drm_radeon_sarea_t *sarea = rmesa->sarea;
- int i;
-
- drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags );
-
- /* The window might have moved, so we might need to get new clip
- * rects.
- *
- * NOTE: This releases and regrabs the hw lock to allow the X server
- * to respond to the DRI protocol request for new drawable info.
- * Since the hardware state depends on having the latest drawable
- * clip rects, all state checking must be done _after_ this call.
- */
- DRI_VALIDATE_DRAWABLE_INFO( sPriv, drawable );
- if (drawable != readable) {
- DRI_VALIDATE_DRAWABLE_INFO( sPriv, readable );
- }
-
- if ( rmesa->lastStamp != drawable->lastStamp ) {
- r200UpdatePageFlipping( rmesa );
- r200SetCliprects( rmesa );
- r200UpdateViewportOffset( rmesa->glCtx );
- driUpdateFramebufferSize(rmesa->glCtx, drawable);
- }
-
- R200_STATECHANGE( rmesa, ctx );
- if (rmesa->sarea->tiling_enabled) {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
- }
- else rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &= ~R200_COLOR_TILE_ENABLE;
-
- if ( sarea->ctx_owner != rmesa->dri.hwContext ) {
- sarea->ctx_owner = rmesa->dri.hwContext;
- }
-
- for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
- DRI_AGE_TEXTURES( rmesa->texture_heaps[ i ] );
- }
-
- rmesa->lost_context = GL_TRUE;
-}
diff --git a/src/mesa/drivers/dri/r200/r200_lock.h b/src/mesa/drivers/dri/r200/r200_lock.h
deleted file mode 100644
index 4ff98907fb..0000000000
--- a/src/mesa/drivers/dri/r200/r200_lock.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#ifndef __R200_LOCK_H__
-#define __R200_LOCK_H__
-
-extern void r200GetLock( r200ContextPtr rmesa, GLuint flags );
-
-/* Turn DEBUG_LOCKING on to find locking conflicts.
- */
-#define DEBUG_LOCKING 0
-
-#if DEBUG_LOCKING
-extern char *prevLockFile;
-extern int prevLockLine;
-
-#define DEBUG_LOCK() \
- do { \
- prevLockFile = (__FILE__); \
- prevLockLine = (__LINE__); \
- } while (0)
-
-#define DEBUG_RESET() \
- do { \
- prevLockFile = 0; \
- prevLockLine = 0; \
- } while (0)
-
-#define DEBUG_CHECK_LOCK() \
- do { \
- if ( prevLockFile ) { \
- fprintf( stderr, \
- "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
- prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
- exit( 1 ); \
- } \
- } while (0)
-
-#else
-
-#define DEBUG_LOCK()
-#define DEBUG_RESET()
-#define DEBUG_CHECK_LOCK()
-
-#endif
-
-/*
- * !!! We may want to separate locks from locks with validation. This
- * could be used to improve performance for those things commands that
- * do not do any drawing !!!
- */
-
-
-/* Lock the hardware and validate our state.
- */
-#define LOCK_HARDWARE( rmesa ) \
- do { \
- char __ret = 0; \
- DEBUG_CHECK_LOCK(); \
- DRM_CAS( rmesa->dri.hwLock, rmesa->dri.hwContext, \
- (DRM_LOCK_HELD | rmesa->dri.hwContext), __ret ); \
- if ( __ret ) \
- r200GetLock( rmesa, 0 ); \
- DEBUG_LOCK(); \
- } while (0)
-
-#define UNLOCK_HARDWARE( rmesa ) \
- do { \
- DRM_UNLOCK( rmesa->dri.fd, \
- rmesa->dri.hwLock, \
- rmesa->dri.hwContext ); \
- DEBUG_RESET(); \
- } while (0)
-
-#endif /* __R200_LOCK_H__ */
diff --git a/src/mesa/drivers/dri/r200/r200_maos.h b/src/mesa/drivers/dri/r200/r200_maos.h
index d3ed06d402..16a70475e1 100644
--- a/src/mesa/drivers/dri/r200/r200_maos.h
+++ b/src/mesa/drivers/dri/r200/r200_maos.h
@@ -38,6 +38,5 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r200_context.h"
extern void r200EmitArrays( GLcontext *ctx, GLubyte *vimap_rev );
-extern void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs );
#endif
diff --git a/src/mesa/drivers/dri/r200/r200_maos_arrays.c b/src/mesa/drivers/dri/r200/r200_maos_arrays.c
index 8512b9af47..383a0c4b0d 100644
--- a/src/mesa/drivers/dri/r200/r200_maos_arrays.c
+++ b/src/mesa/drivers/dri/r200/r200_maos_arrays.c
@@ -50,110 +50,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r200_maos.h"
#include "r200_tcl.h"
-
-#if 0
-/* Usage:
- * - from r200_tcl_render
- * - call r200EmitArrays to ensure uptodate arrays in dma
- * - emit primitives (new type?) which reference the data
- * -- need to use elts for lineloop, quads, quadstrip/flat
- * -- other primitives are all well-formed (need tristrip-1,fake-poly)
- *
- */
-static void emit_ubyte_rgba3( GLcontext *ctx,
- struct r200_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- r200_color_t *out = (r200_color_t *)(rvb->start + rvb->address);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d out %p\n",
- __FUNCTION__, count, stride, (void *)out);
-
- for (i = 0; i < count; i++) {
- out->red = *data;
- out->green = *(data+1);
- out->blue = *(data+2);
- out->alpha = 0xFF;
- out++;
- data += stride;
- }
-}
-
-static void emit_ubyte_rgba4( GLcontext *ctx,
- struct r200_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
-
- if (stride == 4) {
- for (i = 0; i < count; i++)
- ((int *)out)[i] = LE32_TO_CPU(((int *)data)[i]);
- } else {
- for (i = 0; i < count; i++) {
- *(int *)out++ = LE32_TO_CPU(*(int *)data);
- data += stride;
- }
- }
-}
-
-
-static void emit_ubyte_rgba( GLcontext *ctx,
- struct r200_dma_region *rvb,
- char *data,
- int size,
- int stride,
- int count )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
-
- assert (!rvb->buf);
-
- if (stride == 0) {
- r200AllocDmaRegion( rmesa, rvb, 4, 4 );
- count = 1;
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 0;
- rvb->aos_size = 1;
- }
- else {
- r200AllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 1;
- rvb->aos_size = 1;
- }
-
- /* Emit the data
- */
- switch (size) {
- case 3:
- emit_ubyte_rgba3( ctx, rvb, data, stride, count );
- break;
- case 4:
- emit_ubyte_rgba4( ctx, rvb, data, stride, count );
- break;
- default:
- assert(0);
- exit(1);
- break;
- }
-}
-#endif
-
-
#if defined(USE_X86_ASM)
#define COPY_DWORDS( dst, src, nr ) \
do { \
@@ -174,204 +70,34 @@ do { \
} while (0)
#endif
-
-static void emit_vecfog( GLcontext *ctx,
- struct r200_dma_region *rvb,
- char *data,
- int stride,
- int count )
+static void r200_emit_vecfog(GLcontext *ctx, struct radeon_aos *aos,
+ GLvoid *data, int stride, int count)
{
- int i;
- GLfloat *out;
-
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
-
- assert (!rvb->buf);
-
- if (stride == 0) {
- r200AllocDmaRegion( rmesa, rvb, 4, 4 );
- count = 1;
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 0;
- rvb->aos_size = 1;
- }
- else {
- r200AllocDmaRegion( rmesa, rvb, count * 4, 4 ); /* alignment? */
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 1;
- rvb->aos_size = 1;
- }
-
- /* Emit the data
- */
- out = (GLfloat *)(rvb->address + rvb->start);
- for (i = 0; i < count; i++) {
- out[0] = r200ComputeFogBlendFactor( ctx, *(GLfloat *)data );
- out++;
- data += stride;
- }
-
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ uint32_t *out;
+ int i;
+ int size = 1;
+
+ if (stride == 0) {
+ radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * 4, 32);
+ count = 1;
+ aos->stride = 0;
+ } else {
+ radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * 4, 32);
+ aos->stride = size;
+ }
+
+ aos->components = size;
+ aos->count = count;
+
+ out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
+ for (i = 0; i < count; i++) {
+ out[0] = r200ComputeFogBlendFactor( ctx, *(GLfloat *)data );
+ out++;
+ data += stride;
+ }
}
-
-static void emit_vec4( GLcontext *ctx,
- struct r200_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
-
- if (stride == 4)
- COPY_DWORDS( out, data, count );
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out++;
- data += stride;
- }
-}
-
-
-static void emit_vec8( GLcontext *ctx,
- struct r200_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
-
- if (stride == 8)
- COPY_DWORDS( out, data, count*2 );
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out[1] = *(int *)(data+4);
- out += 2;
- data += stride;
- }
-}
-
-static void emit_vec12( GLcontext *ctx,
- struct r200_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d out %p data %p\n",
- __FUNCTION__, count, stride, (void *)out, (void *)data);
-
- if (stride == 12)
- COPY_DWORDS( out, data, count*3 );
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out[1] = *(int *)(data+4);
- out[2] = *(int *)(data+8);
- out += 3;
- data += stride;
- }
-}
-
-static void emit_vec16( GLcontext *ctx,
- struct r200_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
-
- if (stride == 16)
- COPY_DWORDS( out, data, count*4 );
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out[1] = *(int *)(data+4);
- out[2] = *(int *)(data+8);
- out[3] = *(int *)(data+12);
- out += 4;
- data += stride;
- }
-}
-
-
-static void emit_vector( GLcontext *ctx,
- struct r200_dma_region *rvb,
- char *data,
- int size,
- int stride,
- int count )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d size %d stride %d\n",
- __FUNCTION__, count, size, stride);
-
- assert (!rvb->buf);
-
- if (stride == 0) {
- r200AllocDmaRegion( rmesa, rvb, size * 4, 4 );
- count = 1;
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 0;
- rvb->aos_size = size;
- }
- else {
- r200AllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = size;
- rvb->aos_size = size;
- }
-
- /* Emit the data
- */
- switch (size) {
- case 1:
- emit_vec4( ctx, rvb, data, stride, count );
- break;
- case 2:
- emit_vec8( ctx, rvb, data, stride, count );
- break;
- case 3:
- emit_vec12( ctx, rvb, data, stride, count );
- break;
- case 4:
- emit_vec16( ctx, rvb, data, stride, count );
- break;
- default:
- assert(0);
- exit(1);
- break;
- }
-
-}
-
-
-
/* Emit any changed arrays to new GART memory, re-emit a packet to
* update the arrays.
*/
@@ -379,12 +105,12 @@ void r200EmitArrays( GLcontext *ctx, GLubyte *vimap_rev )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
- struct r200_dma_region **component = rmesa->tcl.aos_components;
GLuint nr = 0;
GLuint vfmt0 = 0, vfmt1 = 0;
GLuint count = VB->Count;
GLuint i, emitsize;
+ // fprintf(stderr,"emit arrays\n");
for ( i = 0; i < 15; i++ ) {
GLubyte attrib = vimap_rev[i];
if (attrib != 255) {
@@ -416,20 +142,20 @@ void r200EmitArrays( GLcontext *ctx, GLubyte *vimap_rev )
case 3:
/* special handling to fix up fog. Will get us into trouble with vbos...*/
assert(attrib == VERT_ATTRIB_FOG);
- if (!rmesa->tcl.vertex_data[i].buf) {
+ if (!rmesa->radeon.tcl.aos[i].bo) {
if (ctx->VertexProgram._Enabled)
- emit_vector( ctx,
- &(rmesa->tcl.vertex_data[i]),
- (char *)VB->AttribPtr[attrib]->data,
- 1,
- VB->AttribPtr[attrib]->stride,
- count);
+ rcommon_emit_vector( ctx,
+ &(rmesa->radeon.tcl.aos[nr]),
+ (char *)VB->AttribPtr[attrib]->data,
+ 1,
+ VB->AttribPtr[attrib]->stride,
+ count);
else
- emit_vecfog( ctx,
- &(rmesa->tcl.vertex_data[i]),
- (char *)VB->AttribPtr[attrib]->data,
- VB->AttribPtr[attrib]->stride,
- count);
+ r200_emit_vecfog( ctx,
+ &(rmesa->radeon.tcl.aos[nr]),
+ (char *)VB->AttribPtr[attrib]->data,
+ VB->AttribPtr[attrib]->stride,
+ count);
}
vfmt0 |= R200_VTX_DISCRETE_FOG;
goto after_emit;
@@ -473,17 +199,17 @@ void r200EmitArrays( GLcontext *ctx, GLubyte *vimap_rev )
default:
assert(0);
}
- if (!rmesa->tcl.vertex_data[i].buf) {
- emit_vector( ctx,
- &(rmesa->tcl.vertex_data[i]),
- (char *)VB->AttribPtr[attrib]->data,
- emitsize,
- VB->AttribPtr[attrib]->stride,
- count );
+ if (!rmesa->radeon.tcl.aos[nr].bo) {
+ rcommon_emit_vector( ctx,
+ &(rmesa->radeon.tcl.aos[nr]),
+ (char *)VB->AttribPtr[attrib]->data,
+ emitsize,
+ VB->AttribPtr[attrib]->stride,
+ count );
}
after_emit:
assert(nr < 12);
- component[nr++] = &rmesa->tcl.vertex_data[i];
+ nr++;
}
}
@@ -494,19 +220,6 @@ after_emit:
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = vfmt1;
}
- rmesa->tcl.nr_aos_components = nr;
+ rmesa->radeon.tcl.aos_count = nr;
}
-
-void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs )
-{
- r200ContextPtr rmesa = R200_CONTEXT( ctx );
-
- /* only do it for changed inputs ? */
- int i;
- for (i = 0; i < 15; i++) {
- if (newinputs & (1 << i))
- r200ReleaseDmaRegion( rmesa,
- &rmesa->tcl.vertex_data[i], __FUNCTION__ );
- }
-}
diff --git a/src/mesa/drivers/dri/r200/r200_pixel.c b/src/mesa/drivers/dri/r200/r200_pixel.c
index be68821dc1..95773871e0 100644
--- a/src/mesa/drivers/dri/r200/r200_pixel.c
+++ b/src/mesa/drivers/dri/r200/r200_pixel.c
@@ -51,29 +51,29 @@ check_color( const GLcontext *ctx, GLenum type, GLenum format,
const void *pixels, GLint sz, GLint pitch )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- GLuint cpp = rmesa->r200Screen->cpp;
+ GLuint cpp = rmesa->radeon.radeonScreen->cpp;
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( (pitch & 63) ||
ctx->_ImageTransferState ||
packing->SwapBytes ||
packing->LsbFirst) {
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
return GL_FALSE;
}
- if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&
- cpp == 4 &&
+ if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&
+ cpp == 4 &&
format == GL_BGRA ) {
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s: passed 2\n", __FUNCTION__);
return GL_TRUE;
}
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s: failed\n", __FUNCTION__);
return GL_FALSE;
@@ -83,11 +83,11 @@ static GLboolean
check_color_per_fragment_ops( const GLcontext *ctx )
{
int result;
- result = (!( ctx->Color.AlphaEnabled ||
+ result = (!( ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
- ctx->Stencil.Enabled ||
+ ctx->Stencil._Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
@@ -96,12 +96,12 @@ check_color_per_fragment_ops( const GLcontext *ctx )
ctx->Texture._EnabledUnits
) &&
ctx->Current.RasterPosValid);
-
+
return result;
}
-
+#if 0
static GLboolean
clip_pixelrect( const GLcontext *ctx,
const GLframebuffer *buffer,
@@ -137,11 +137,12 @@ clip_pixelrect( const GLcontext *ctx,
if (*height <= 0)
return GL_FALSE;
- *size = ((*y + *height - 1) * rmesa->r200Screen->frontPitch +
- (*x + *width - 1) * rmesa->r200Screen->cpp);
+ *size = ((*y + *height - 1) * rmesa->radeon.radeonScreen->frontPitch +
+ (*x + *width - 1) * rmesa->radeon.radeonScreen->cpp);
return GL_TRUE;
}
+#endif
static GLboolean
r200TryReadPixels( GLcontext *ctx,
@@ -150,29 +151,30 @@ r200TryReadPixels( GLcontext *ctx,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
+ return GL_FALSE;
+#if 0
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLint pitch = pack->RowLength ? pack->RowLength : width;
GLint blit_format;
- GLuint cpp = rmesa->r200Screen->cpp;
+ GLuint cpp = rmesa->radeon.radeonScreen->cpp;
GLint size = width * height * cpp;
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Only accelerate reading to GART buffers.
*/
- if ( !r200IsGartMemory(rmesa, pixels,
- pitch * height * rmesa->r200Screen->cpp ) ) {
- if (R200_DEBUG & DEBUG_PIXEL)
+ if ( !r200IsGartMemory(rmesa, pixels,
+ pitch * height * rmesa->radeon.radeonScreen->cpp ) ) {
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s: dest not GART\n", __FUNCTION__);
- return GL_FALSE;
}
/* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
* blitter:
*/
if (!pack->Invert) {
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
return GL_FALSE;
}
@@ -180,7 +182,7 @@ r200TryReadPixels( GLcontext *ctx,
if (!check_color(ctx, type, format, pack, pixels, size, pitch))
return GL_FALSE;
- switch ( rmesa->r200Screen->cpp ) {
+ switch ( rmesa->radeon.radeonScreen->cpp ) {
case 4:
blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
break;
@@ -197,40 +199,40 @@ r200TryReadPixels( GLcontext *ctx,
* a full command buffer expects to be called unlocked. As a
* workaround, immediately flush the buffer on aquiring the lock.
*/
- LOCK_HARDWARE( rmesa );
+ LOCK_HARDWARE( &rmesa->radeon );
if (rmesa->store.cmd_used)
- r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
+ rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
&size)) {
- UNLOCK_HARDWARE( rmesa );
- if (R200_DEBUG & DEBUG_PIXEL)
+ UNLOCK_HARDWARE( &rmesa->radeon );
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s totally clipped -- nothing to do\n",
__FUNCTION__);
return GL_TRUE;
}
{
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+ __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
driRenderbuffer *drb = (driRenderbuffer *) ctx->ReadBuffer->_ColorReadBuffer;
int nbox = dPriv->numClipRects;
int src_offset = drb->offset
- + rmesa->r200Screen->fbLocation;
+ + rmesa->radeon.radeonScreen->fbLocation;
int src_pitch = drb->pitch * drb->cpp;
int dst_offset = r200GartOffsetFromVirtual( rmesa, pixels );
- int dst_pitch = pitch * rmesa->r200Screen->cpp;
+ int dst_pitch = pitch * rmesa->radeon.radeonScreen->cpp;
drm_clip_rect_t *box = dPriv->pClipRects;
int i;
- r200EmitWait( rmesa, RADEON_WAIT_3D );
+ r200EmitWait( rmesa, RADEON_WAIT_3D );
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
src_pitch, dst_pitch);
@@ -240,7 +242,7 @@ r200TryReadPixels( GLcontext *ctx,
GLint by = box[i].y1;
GLint bw = box[i].x2 - bx;
GLint bh = box[i].y2 - by;
-
+
if (bx < x) bw -= x - bx, bx = x;
if (by < y) bh -= y - by, by = y;
if (bx + bw > x + width) bw = x + width - bx;
@@ -257,12 +259,12 @@ r200TryReadPixels( GLcontext *ctx,
bw, bh );
}
- r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
+ rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
}
- UNLOCK_HARDWARE( rmesa );
-
- r200Finish( ctx ); /* required by GL */
+ UNLOCK_HARDWARE( &rmesa->radeon );
+ radeonFinish( ctx ); /* required by GL */
+#endif
return GL_TRUE;
}
@@ -273,12 +275,12 @@ r200ReadPixels( GLcontext *ctx,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
- if (!r200TryReadPixels( ctx, x, y, width, height, format, type, pack,
+ if (!r200TryReadPixels( ctx, x, y, width, height, format, type, pack,
pixels))
- _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,
+ _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,
pixels);
}
@@ -291,8 +293,12 @@ static void do_draw_pix( GLcontext *ctx,
const void *pixels,
GLuint planemask)
{
+ if (R200_DEBUG & RADEON_PIXEL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+#if 0
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
drm_clip_rect_t *box = dPriv->pClipRects;
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorDrawBuffers[0];
driRenderbuffer *drb = (driRenderbuffer *) rb;
@@ -301,12 +307,9 @@ static void do_draw_pix( GLcontext *ctx,
int blit_format;
int size;
int src_offset = r200GartOffsetFromVirtual( rmesa, pixels );
- int src_pitch = pitch * rmesa->r200Screen->cpp;
+ int src_pitch = pitch * rmesa->radeon.radeonScreen->cpp;
- if (R200_DEBUG & DEBUG_PIXEL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- switch ( rmesa->r200Screen->cpp ) {
+ switch ( rmesa->radeon.radeonScreen->cpp ) {
case 2:
blit_format = R200_CP_COLOR_FORMAT_RGB565;
break;
@@ -318,17 +321,17 @@ static void do_draw_pix( GLcontext *ctx,
}
- LOCK_HARDWARE( rmesa );
+ LOCK_HARDWARE( &rmesa->radeon );
if (rmesa->store.cmd_used)
- r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
+ rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
y -= height; /* cope with pixel zoom */
-
+
if (!clip_pixelrect(ctx, ctx->DrawBuffer,
&x, &y, &width, &height,
&size)) {
- UNLOCK_HARDWARE( rmesa );
+ UNLOCK_HARDWARE( &rmesa->radeon );
return;
}
@@ -357,15 +360,16 @@ static void do_draw_pix( GLcontext *ctx,
blit_format,
src_pitch, src_offset,
drb->pitch * drb->cpp,
- drb->offset + rmesa->r200Screen->fbLocation,
+ drb->offset + rmesa->radeon.radeonScreen->fbLocation,
bx - x, by - y,
bx, by,
bw, bh );
}
- r200FlushCmdBufLocked( rmesa, __FUNCTION__ );
- r200WaitForIdleLocked( rmesa ); /* required by GL */
- UNLOCK_HARDWARE( rmesa );
+ rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
+ radeonWaitForIdleLocked( &rmesa->radeon ); /* required by GL */
+ UNLOCK_HARDWARE( &rmesa->radeon );
+#endif
}
@@ -381,10 +385,10 @@ r200TryDrawPixels( GLcontext *ctx,
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
GLuint planemask;
- GLuint cpp = rmesa->r200Screen->cpp;
+ GLuint cpp = rmesa->radeon.radeonScreen->cpp;
GLint size = height * pitch * cpp;
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
/* check that we're drawing to exactly one color buffer */
@@ -395,7 +399,7 @@ r200TryDrawPixels( GLcontext *ctx,
case GL_RGB:
case GL_RGBA:
case GL_BGRA:
- planemask = r200PackColor(cpp,
+ planemask = radeonPackColor(cpp,
ctx->Color.ColorMask[RCOMP],
ctx->Color.ColorMask[GCOMP],
ctx->Color.ColorMask[BCOMP],
@@ -407,10 +411,10 @@ r200TryDrawPixels( GLcontext *ctx,
if (planemask != ~0)
return GL_FALSE; /* fix me -- should be possible */
- /* Can't do conversions on GART reads/draws.
+ /* Can't do conversions on GART reads/draws.
*/
if ( !r200IsGartMemory( rmesa, pixels, size ) ) {
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s: not GART memory\n", __FUNCTION__);
return GL_FALSE;
}
@@ -431,7 +435,7 @@ r200TryDrawPixels( GLcontext *ctx,
return GL_FALSE;
}
- if ( r200IsGartMemory(rmesa, pixels, size) )
+ if (0)// r200IsGartMemory(rmesa, pixels, size) )
{
do_draw_pix( ctx, x, y, width, height, pitch, pixels, planemask );
return GL_TRUE;
@@ -453,7 +457,7 @@ r200DrawPixels( GLcontext *ctx,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
- if (R200_DEBUG & DEBUG_PIXEL)
+ if (R200_DEBUG & RADEON_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!r200TryDrawPixels( ctx, x, y, width, height, format, type,
@@ -471,7 +475,7 @@ r200Bitmap( GLcontext *ctx, GLint px, GLint py,
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- if (rmesa->Fallback)
+ if (rmesa->radeon.Fallback)
_swrast_Bitmap( ctx, px, py, width, height, unpack, bitmap );
else
r200PointsBitmap( ctx, px, py, width, height, unpack, bitmap );
@@ -482,9 +486,9 @@ r200Bitmap( GLcontext *ctx, GLint px, GLint py,
void r200InitPixelFuncs( GLcontext *ctx )
{
if (!getenv("R200_NO_BLITS")) {
- ctx->Driver.ReadPixels = r200ReadPixels;
- ctx->Driver.DrawPixels = r200DrawPixels;
- if (getenv("R200_HW_BITMAP"))
+ ctx->Driver.ReadPixels = r200ReadPixels;
+ ctx->Driver.DrawPixels = r200DrawPixels;
+ if (getenv("R200_HW_BITMAP"))
ctx->Driver.Bitmap = r200Bitmap;
}
}
diff --git a/src/mesa/drivers/dri/r200/r200_reg.h b/src/mesa/drivers/dri/r200/r200_reg.h
index 5ce287f7a5..526a624b69 100644
--- a/src/mesa/drivers/dri/r200/r200_reg.h
+++ b/src/mesa/drivers/dri/r200/r200_reg.h
@@ -463,8 +463,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R200_VSC_UPDATE_USER_COLOR_1_ENABLE 0x00020000
/* gap */
#define R200_SE_TCL_VECTOR_INDX_REG 0x2200
+# define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT 16
+# define RADEON_VEC_INDX_DWORD_COUNT_SHIFT 28
#define R200_SE_TCL_VECTOR_DATA_REG 0x2204
#define R200_SE_TCL_SCALAR_INDX_REG 0x2208
+# define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT 16
#define R200_SE_TCL_SCALAR_DATA_REG 0x220c
/* gap */
#define R200_SE_TCL_MATRIX_SEL_0 0x2230
@@ -949,6 +952,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R200_LOD_BIAS_MASK (0xfff80000)
#define R200_LOD_BIAS_SHIFT 19
#define R200_PP_TXSIZE_0 0x2c0c /* NPOT only */
+#define R200_PP_TX_WIDTHMASK_SHIFT 0
+#define R200_PP_TX_HEIGHTMASK_SHIFT 16
+
#define R200_PP_TXPITCH_0 0x2c10 /* NPOT only */
#define R200_PP_BORDER_COLOR_0 0x2c14
#define R200_PP_CUBIC_FACES_0 0x2c18
diff --git a/src/mesa/drivers/dri/r200/r200_sanity.c b/src/mesa/drivers/dri/r200/r200_sanity.c
index 36530c224e..1241a926ba 100644
--- a/src/mesa/drivers/dri/r200/r200_sanity.c
+++ b/src/mesa/drivers/dri/r200/r200_sanity.c
@@ -48,11 +48,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define MORE_VERBOSE 1
#if MORE_VERBOSE
-#define VERBOSE (R200_DEBUG & DEBUG_VERBOSE)
+#define VERBOSE (R200_DEBUG & RADEON_VERBOSE)
#define NORMAL (1)
#else
#define VERBOSE 0
-#define NORMAL (R200_DEBUG & DEBUG_VERBOSE)
+#define NORMAL (R200_DEBUG & RADEON_VERBOSE)
#endif
diff --git a/src/mesa/drivers/dri/r200/r200_span.c b/src/mesa/drivers/dri/r200/r200_span.c
deleted file mode 100644
index 9783678028..0000000000
--- a/src/mesa/drivers/dri/r200/r200_span.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/colormac.h"
-#include "swrast/swrast.h"
-
-#include "r200_context.h"
-#include "r200_ioctl.h"
-#include "r200_state.h"
-#include "r200_span.h"
-#include "r200_tex.h"
-
-#define DBG 0
-
-/*
- * Note that all information needed to access pixels in a renderbuffer
- * should be obtained through the gl_renderbuffer parameter, not per-context
- * information.
- */
-#define LOCAL_VARS \
- driRenderbuffer *drb = (driRenderbuffer *) rb; \
- const __DRIdrawablePrivate *dPriv = drb->dPriv; \
- const GLuint bottom = dPriv->h - 1; \
- GLubyte *buf = (GLubyte *) drb->flippedData \
- + (dPriv->y * drb->flippedPitch + dPriv->x) * drb->cpp; \
- GLuint p; \
- (void) p;
-
-#define LOCAL_DEPTH_VARS \
- driRenderbuffer *drb = (driRenderbuffer *) rb; \
- const __DRIdrawablePrivate *dPriv = drb->dPriv; \
- const GLuint bottom = dPriv->h - 1; \
- GLuint xo = dPriv->x; \
- GLuint yo = dPriv->y; \
- GLubyte *buf = (GLubyte *) drb->Base.Data;
-
-#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
-
-#define Y_FLIP(Y) (bottom - (Y))
-
-#define HW_LOCK()
-
-#define HW_UNLOCK()
-
-
-
-/* ================================================================
- * Color buffer
- */
-
-/* 16 bit, RGB565 color spanline and pixel functions
- */
-#define SPANTMP_PIXEL_FMT GL_RGB
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
-
-#define TAG(x) r200##x##_RGB565
-#define TAG2(x,y) r200##x##_RGB565##y
-#define GET_PTR(X,Y) (buf + ((Y) * drb->flippedPitch + (X)) * 2)
-#include "spantmp2.h"
-
-/* 32 bit, ARGB8888 color spanline and pixel functions
- */
-#define SPANTMP_PIXEL_FMT GL_BGRA
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
-#define TAG(x) r200##x##_ARGB8888
-#define TAG2(x,y) r200##x##_ARGB8888##y
-#define GET_PTR(X,Y) (buf + ((Y) * drb->flippedPitch + (X)) * 4)
-#include "spantmp2.h"
-
-
-/* ================================================================
- * Depth buffer
- */
-
-/* The Radeon family has depth tiling on all the time, so we have to convert
- * the x,y coordinates into the memory bus address (mba) in the same
- * manner as the engine. In each case, the linear block address (ba)
- * is calculated, and then wired with x and y to produce the final
- * memory address.
- * The chip will do address translation on its own if the surface registers
- * are set up correctly. It is not quite enough to get it working with hyperz too...
- */
-
-/* extract bit 'b' of x, result is zero or one */
-#define BIT(x,b) ((x & (1<<b))>>b)
-
-static GLuint
-r200_mba_z32( driRenderbuffer *drb, GLint x, GLint y )
-{
- GLuint pitch = drb->pitch;
- if (drb->depthHasSurface) {
- return 4 * (x + y * pitch);
- }
- else {
- GLuint b = ((y & 0x7FF) >> 4) * ((pitch & 0xFFF) >> 5) + ((x & 0x7FF) >> 5);
- GLuint a =
- (BIT(x,0) << 2) |
- (BIT(y,0) << 3) |
- (BIT(x,1) << 4) |
- (BIT(y,1) << 5) |
- (BIT(x,3) << 6) |
- (BIT(x,4) << 7) |
- (BIT(x,2) << 8) |
- (BIT(y,2) << 9) |
- (BIT(y,3) << 10) |
- (((pitch & 0x20) ? (b & 0x01) : ((b & 0x01) ^ (BIT(y,4)))) << 11) |
- ((b >> 1) << 12);
- return a;
- }
-}
-
-static GLuint
-r200_mba_z16( driRenderbuffer *drb, GLint x, GLint y )
-{
- GLuint pitch = drb->pitch;
- if (drb->depthHasSurface) {
- return 2 * (x + y * pitch);
- }
- else {
- GLuint b = ((y & 0x7FF) >> 4) * ((pitch & 0xFFF) >> 6) + ((x & 0x7FF) >> 6);
- GLuint a =
- (BIT(x,0) << 1) |
- (BIT(y,0) << 2) |
- (BIT(x,1) << 3) |
- (BIT(y,1) << 4) |
- (BIT(x,2) << 5) |
- (BIT(x,4) << 6) |
- (BIT(x,5) << 7) |
- (BIT(x,3) << 8) |
- (BIT(y,2) << 9) |
- (BIT(y,3) << 10) |
- (((pitch & 0x40) ? (b & 0x01) : ((b & 0x01) ^ (BIT(y,4)))) << 11) |
- ((b >> 1) << 12);
- return a;
- }
-}
-
-
-/* 16-bit depth buffer functions
- */
-#define VALUE_TYPE GLushort
-
-#define WRITE_DEPTH( _x, _y, d ) \
- *(GLushort *)(buf + r200_mba_z16( drb, _x + xo, _y + yo )) = d;
-
-#define READ_DEPTH( d, _x, _y ) \
- d = *(GLushort *)(buf + r200_mba_z16( drb, _x + xo, _y + yo ));
-
-#define TAG(x) r200##x##_z16
-#include "depthtmp.h"
-
-
-/* 24 bit depth, 8 bit stencil depthbuffer functions
- */
-#define VALUE_TYPE GLuint
-
-#define WRITE_DEPTH( _x, _y, d ) \
-do { \
- GLuint offset = r200_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
- tmp &= 0xff000000; \
- tmp |= ((d) & 0x00ffffff); \
- *(GLuint *)(buf + offset) = tmp; \
-} while (0)
-
-#define READ_DEPTH( d, _x, _y ) \
- d = *(GLuint *)(buf + r200_mba_z32( drb, _x + xo, \
- _y + yo )) & 0x00ffffff;
-
-#define TAG(x) r200##x##_z24_s8
-#include "depthtmp.h"
-
-
-/* ================================================================
- * Stencil buffer
- */
-
-/* 24 bit depth, 8 bit stencil depthbuffer functions
- */
-#define WRITE_STENCIL( _x, _y, d ) \
-do { \
- GLuint offset = r200_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
- tmp &= 0x00ffffff; \
- tmp |= (((d) & 0xff) << 24); \
- *(GLuint *)(buf + offset) = tmp; \
-} while (0)
-
-#define READ_STENCIL( d, _x, _y ) \
-do { \
- GLuint offset = r200_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
- tmp &= 0xff000000; \
- d = tmp >> 24; \
-} while (0)
-
-#define TAG(x) r200##x##_z24_s8
-#include "stenciltmp.h"
-
-
-/* Move locking out to get reasonable span performance (10x better
- * than doing this in HW_LOCK above). WaitForIdle() is the main
- * culprit.
- */
-
-static void r200SpanRenderStart( GLcontext *ctx )
-{
- r200ContextPtr rmesa = R200_CONTEXT( ctx );
-
- R200_FIREVERTICES( rmesa );
- LOCK_HARDWARE( rmesa );
- r200WaitForIdleLocked( rmesa );
-
- /* Read & rewrite the first pixel in the frame buffer. This should
- * be a noop, right? In fact without this conform fails as reading
- * from the framebuffer sometimes produces old results -- the
- * on-card read cache gets mixed up and doesn't notice that the
- * framebuffer has been updated.
- *
- * In the worst case this is buggy too as p might get the wrong
- * value first time, so really need a hidden pixel somewhere for this.
- */
- {
- int p;
- driRenderbuffer *drb =
- (driRenderbuffer *) ctx->WinSysDrawBuffer->_ColorDrawBuffers[0];
- volatile int *buf =
- (volatile int *)(rmesa->dri.screen->pFB + drb->offset);
- p = *buf;
- *buf = p;
- }
-}
-
-static void r200SpanRenderFinish( GLcontext *ctx )
-{
- r200ContextPtr rmesa = R200_CONTEXT( ctx );
- _swrast_flush( ctx );
- UNLOCK_HARDWARE( rmesa );
-}
-
-void r200InitSpanFuncs( GLcontext *ctx )
-{
- struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
- swdd->SpanRenderStart = r200SpanRenderStart;
- swdd->SpanRenderFinish = r200SpanRenderFinish;
-}
-
-
-
-/**
- * Plug in the Get/Put routines for the given driRenderbuffer.
- */
-void
-radeonSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
-{
- if (drb->Base.InternalFormat == GL_RGBA) {
- if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
- r200InitPointers_RGB565(&drb->Base);
- }
- else {
- r200InitPointers_ARGB8888(&drb->Base);
- }
- }
- else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
- r200InitDepthPointers_z16(&drb->Base);
- }
- else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
- r200InitDepthPointers_z24_s8(&drb->Base);
- }
- else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
- r200InitStencilPointers_z24_s8(&drb->Base);
- }
-}
diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c
index 0eaaaf69ac..76852e315c 100644
--- a/src/mesa/drivers/dri/r200/r200_state.c
+++ b/src/mesa/drivers/dri/r200/r200_state.c
@@ -47,6 +47,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "tnl/t_pipeline.h"
#include "swrast_setup/swrast_setup.h"
+#include "radeon_common.h"
+#include "radeon_mipmap_tree.h"
#include "r200_context.h"
#include "r200_ioctl.h"
#include "r200_state.h"
@@ -77,7 +79,7 @@ static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
switch ( func ) {
case GL_NEVER:
- pp_misc |= R200_ALPHA_TEST_FAIL;
+ pp_misc |= R200_ALPHA_TEST_FAIL;
break;
case GL_LESS:
pp_misc |= R200_ALPHA_TEST_LESS;
@@ -114,8 +116,8 @@ static void r200BlendColor( GLcontext *ctx, const GLfloat cf[4] )
CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]);
CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
- if (rmesa->r200Screen->drmSupportsBlendColor)
- rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = r200PackColor( 4, color[0], color[1], color[2], color[3] );
+ if (rmesa->radeon.radeonScreen->drmSupportsBlendColor)
+ rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = radeonPackColor( 4, color[0], color[1], color[2], color[3] );
}
/**
@@ -213,7 +215,7 @@ static void r200_set_blend_state( GLcontext * ctx )
R200_STATECHANGE( rmesa, ctx );
- if (rmesa->r200Screen->drmSupportsBlendColor) {
+ if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) {
if (ctx->Color.ColorLogicOpEnabled) {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
@@ -278,7 +280,7 @@ static void r200_set_blend_state( GLcontext * ctx )
return;
}
- if (!rmesa->r200Screen->drmSupportsBlendColor) {
+ if (!rmesa->radeon.radeonScreen->drmSupportsBlendColor) {
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
return;
}
@@ -383,10 +385,10 @@ static void r200ClearDepth( GLcontext *ctx, GLclampd d )
switch ( format ) {
case R200_DEPTH_FORMAT_16BIT_INT_Z:
- rmesa->state.depth.clear = d * 0x0000ffff;
+ rmesa->radeon.state.depth.clear = d * 0x0000ffff;
break;
case R200_DEPTH_FORMAT_24BIT_INT_Z:
- rmesa->state.depth.clear = d * 0x00ffffff;
+ rmesa->radeon.state.depth.clear = d * 0x00ffffff;
break;
}
}
@@ -477,10 +479,10 @@ static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
}
}
break;
- case GL_FOG_COLOR:
+ case GL_FOG_COLOR:
R200_STATECHANGE( rmesa, ctx );
UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
- i = r200PackColor( 4, col[0], col[1], col[2], 0 );
+ i = radeonPackColor( 4, col[0], col[1], col[2], 0 );
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
break;
@@ -505,7 +507,7 @@ static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) {
R200_STATECHANGE( rmesa, vtx );
- rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;
}
break;
@@ -521,102 +523,6 @@ static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
}
}
-
-/* =============================================================
- * Scissoring
- */
-
-
-static GLboolean intersect_rect( drm_clip_rect_t *out,
- drm_clip_rect_t *a,
- drm_clip_rect_t *b )
-{
- *out = *a;
- if ( b->x1 > out->x1 ) out->x1 = b->x1;
- if ( b->y1 > out->y1 ) out->y1 = b->y1;
- if ( b->x2 < out->x2 ) out->x2 = b->x2;
- if ( b->y2 < out->y2 ) out->y2 = b->y2;
- if ( out->x1 >= out->x2 ) return GL_FALSE;
- if ( out->y1 >= out->y2 ) return GL_FALSE;
- return GL_TRUE;
-}
-
-
-void r200RecalcScissorRects( r200ContextPtr rmesa )
-{
- drm_clip_rect_t *out;
- int i;
-
- /* Grow cliprect store?
- */
- if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
- while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
- rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
- rmesa->state.scissor.numAllocedClipRects *= 2;
- }
-
- if (rmesa->state.scissor.pClipRects)
- FREE(rmesa->state.scissor.pClipRects);
-
- rmesa->state.scissor.pClipRects =
- MALLOC( rmesa->state.scissor.numAllocedClipRects *
- sizeof(drm_clip_rect_t) );
-
- if ( rmesa->state.scissor.pClipRects == NULL ) {
- rmesa->state.scissor.numAllocedClipRects = 0;
- return;
- }
- }
-
- out = rmesa->state.scissor.pClipRects;
- rmesa->state.scissor.numClipRects = 0;
-
- for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
- if ( intersect_rect( out,
- &rmesa->pClipRects[i],
- &rmesa->state.scissor.rect ) ) {
- rmesa->state.scissor.numClipRects++;
- out++;
- }
- }
-}
-
-
-static void r200UpdateScissor( GLcontext *ctx )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if ( rmesa->dri.drawable ) {
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
-
- int x = ctx->Scissor.X;
- int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
- int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
- int h = dPriv->h - ctx->Scissor.Y - 1;
-
- rmesa->state.scissor.rect.x1 = x + dPriv->x;
- rmesa->state.scissor.rect.y1 = y + dPriv->y;
- rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
- rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
-
- r200RecalcScissorRects( rmesa );
- }
-}
-
-
-static void r200Scissor( GLcontext *ctx,
- GLint x, GLint y, GLsizei w, GLsizei h )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if ( ctx->Scissor.Enabled ) {
- R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
- r200UpdateScissor( ctx );
- }
-
-}
-
-
/* =============================================================
* Culling
*/
@@ -668,6 +574,10 @@ static void r200FrontFace( GLcontext *ctx, GLenum mode )
R200_STATECHANGE( rmesa, tcl );
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
+ /* Winding is inverted when rendering to FBO */
+ if (ctx->DrawBuffer && ctx->DrawBuffer->Name)
+ mode = (mode == GL_CW) ? GL_CCW : GL_CW;
+
switch ( mode ) {
case GL_CW:
rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW;
@@ -790,7 +700,7 @@ static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
r200ContextPtr rmesa = R200_CONTEXT(ctx);
R200_STATECHANGE( rmesa, lin );
- rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
+ rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
}
@@ -803,21 +713,27 @@ static void r200ColorMask( GLcontext *ctx,
GLboolean b, GLboolean a )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- GLuint mask = r200PackColor( rmesa->r200Screen->cpp,
- ctx->Color.ColorMask[RCOMP],
- ctx->Color.ColorMask[GCOMP],
- ctx->Color.ColorMask[BCOMP],
- ctx->Color.ColorMask[ACOMP] );
-
+ GLuint mask;
+ struct radeon_renderbuffer *rrb;
GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
+ rrb = radeon_get_colorbuffer(&rmesa->radeon);
+ if (!rrb)
+ return;
+ mask = radeonPackColor( rrb->cpp,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] );
+
+
if (!(r && g && b && a))
flag |= R200_PLANE_MASK_ENABLE;
- if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
- R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
- }
+ if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
+ R200_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
+ }
if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
R200_STATECHANGE( rmesa, msk );
@@ -834,7 +750,8 @@ static void r200PolygonOffset( GLcontext *ctx,
GLfloat factor, GLfloat units )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- float_ui32_type constant = { units * rmesa->state.depth.scale };
+ const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+ float_ui32_type constant = { units * depthScale };
float_ui32_type factoru = { factor };
/* factor *= 2; */
@@ -847,41 +764,16 @@ static void r200PolygonOffset( GLcontext *ctx,
rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
}
-static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- GLuint i;
- drm_radeon_stipple_t stipple;
-
- /* Must flip pattern upside down.
- */
- for ( i = 0 ; i < 32 ; i++ ) {
- rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
- }
-
- /* TODO: push this into cmd mechanism
- */
- R200_FIREVERTICES( rmesa );
- LOCK_HARDWARE( rmesa );
-
- /* FIXME: Use window x,y offsets into stipple RAM.
- */
- stipple.mask = rmesa->state.stipple.mask;
- drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
- &stipple, sizeof(stipple) );
- UNLOCK_HARDWARE( rmesa );
-}
-
static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
/* Can't generally do unfilled via tcl, but some good special
- * cases work.
+ * cases work.
*/
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
- if (rmesa->TclFallback) {
+ if (rmesa->radeon.TclFallback) {
r200ChooseRenderState( ctx );
r200ChooseVertexState( ctx );
}
@@ -920,34 +812,34 @@ static void r200UpdateSpecular( GLcontext *ctx )
if (ctx->Light.Enabled &&
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
- rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
- (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
+ (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
p |= R200_SPECULAR_ENABLE;
- rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
~R200_DIFFUSE_SPECULAR_COMBINE;
}
else if (ctx->Light.Enabled) {
- rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
- ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
+ ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
} else if (ctx->Fog.ColorSumEnabled ) {
- rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
- (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
+ (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
p |= R200_SPECULAR_ENABLE;
} else {
- rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
- ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
+ ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
}
if (ctx->Fog.Enabled) {
- rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
- ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
+ ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
}
@@ -958,7 +850,7 @@ static void r200UpdateSpecular( GLcontext *ctx )
/* Update vertex/render formats
*/
- if (rmesa->TclFallback) {
+ if (rmesa->radeon.TclFallback) {
r200ChooseRenderState( ctx );
r200ChooseVertexState( ctx );
}
@@ -970,7 +862,7 @@ static void r200UpdateSpecular( GLcontext *ctx )
*/
-/* Update on colormaterial, material emmissive/ambient,
+/* Update on colormaterial, material emmissive/ambient,
* lightmodel.globalambient
*/
static void update_global_ambient( GLcontext *ctx )
@@ -984,23 +876,23 @@ static void update_global_ambient( GLcontext *ctx )
*/
if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
- (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
+ (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
{
- COPY_3V( &fcmd[GLT_RED],
+ COPY_3V( &fcmd[GLT_RED],
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
ACC_SCALE_3V( &fcmd[GLT_RED],
ctx->Light.Model.Ambient,
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
- }
+ }
else
{
COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
}
-
+
R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
}
-/* Update on change to
+/* Update on change to
* - light[p].colors
* - light[p].enabled
*/
@@ -1014,10 +906,10 @@ static void update_light_colors( GLcontext *ctx, GLuint p )
r200ContextPtr rmesa = R200_CONTEXT(ctx);
float *fcmd = (float *)R200_DB_STATE( lit[p] );
- COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
+ COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
-
+
R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
}
}
@@ -1037,7 +929,7 @@ static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
if (ctx->Light.ColorMaterialEnabled) {
GLuint mask = ctx->Light.ColorMaterialBitmask;
-
+
if (mask & MAT_BIT_FRONT_EMISSION) {
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
R200_FRONT_EMISSIVE_SOURCE_SHIFT);
@@ -1053,7 +945,7 @@ static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
else
light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
R200_FRONT_AMBIENT_SOURCE_SHIFT);
-
+
if (mask & MAT_BIT_FRONT_DIFFUSE) {
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
R200_FRONT_DIFFUSE_SOURCE_SHIFT);
@@ -1061,7 +953,7 @@ static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
else
light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
R200_FRONT_DIFFUSE_SOURCE_SHIFT);
-
+
if (mask & MAT_BIT_FRONT_SPECULAR) {
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
R200_FRONT_SPECULAR_SOURCE_SHIFT);
@@ -1070,7 +962,7 @@ static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
R200_FRONT_SPECULAR_SOURCE_SHIFT);
}
-
+
if (mask & MAT_BIT_BACK_EMISSION) {
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
R200_BACK_EMISSIVE_SOURCE_SHIFT);
@@ -1120,8 +1012,8 @@ static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
R200_STATECHANGE( rmesa, tcl );
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
}
-
-
+
+
}
void r200UpdateMaterial( GLcontext *ctx )
@@ -1131,12 +1023,12 @@ void r200UpdateMaterial( GLcontext *ctx )
GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
GLuint mask = ~0;
-
+
/* Might be possible and faster to update everything unconditionally? */
if (ctx->Light.ColorMaterialEnabled)
mask &= ~ctx->Light.ColorMaterialBitmask;
- if (R200_DEBUG & DEBUG_STATE)
+ if (R200_DEBUG & RADEON_STATE)
fprintf(stderr, "%s\n", __FUNCTION__);
if (mask & MAT_BIT_FRONT_EMISSION) {
@@ -1210,14 +1102,14 @@ void r200UpdateMaterial( GLcontext *ctx )
* _VP_inf_norm
* _h_inf_norm
* _Position
- * _NormDirection
+ * _NormSpotDirection
* _ModelViewInvScale
* _NeedEyeCoords
* _EyeZDir
*
* which are calculated in light.c and are correct for the current
* lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
- * and _MESA_NEW_NEED_EYE_COORDS.
+ * and _MESA_NEW_NEED_EYE_COORDS.
*/
static void update_light( GLcontext *ctx )
{
@@ -1234,8 +1126,8 @@ static void update_light( GLcontext *ctx )
tmp &= ~R200_LIGHT_IN_MODELSPACE;
else
tmp |= R200_LIGHT_IN_MODELSPACE;
-
- if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
+
+ if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
{
R200_STATECHANGE( rmesa, tcl );
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
@@ -1259,17 +1151,17 @@ static void update_light( GLcontext *ctx )
if (ctx->Light.Light[p].Enabled) {
struct gl_light *l = &ctx->Light.Light[p];
GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
-
+
if (l->EyePosition[3] == 0.0) {
- COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
- COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
+ COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
+ COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
fcmd[LIT_POSITION_W] = 0;
fcmd[LIT_DIRECTION_W] = 0;
} else {
COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
- fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
- fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
- fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
+ fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0];
+ fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1];
+ fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2];
fcmd[LIT_DIRECTION_W] = 0;
}
@@ -1286,21 +1178,21 @@ static void r200Lightfv( GLcontext *ctx, GLenum light,
GLint p = light - GL_LIGHT0;
struct gl_light *l = &ctx->Light.Light[p];
GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
-
+
switch (pname) {
- case GL_AMBIENT:
+ case GL_AMBIENT:
case GL_DIFFUSE:
case GL_SPECULAR:
update_light_colors( ctx, p );
break;
- case GL_SPOT_DIRECTION:
- /* picked up in update_light */
+ case GL_SPOT_DIRECTION:
+ /* picked up in update_light */
break;
case GL_POSITION: {
- /* positions picked up in update_light, but can do flag here */
+ /* positions picked up in update_light, but can do flag here */
GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
@@ -1416,7 +1308,7 @@ static void r200LightModelfv( GLcontext *ctx, GLenum pname,
r200ContextPtr rmesa = R200_CONTEXT(ctx);
switch (pname) {
- case GL_LIGHT_MODEL_AMBIENT:
+ case GL_LIGHT_MODEL_AMBIENT:
update_global_ambient( ctx );
break;
@@ -1430,7 +1322,7 @@ static void r200LightModelfv( GLcontext *ctx, GLenum pname,
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
else
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
- if (rmesa->TclFallback) {
+ if (rmesa->radeon.TclFallback) {
r200ChooseRenderState( ctx );
r200ChooseVertexState( ctx );
}
@@ -1675,7 +1567,7 @@ static void r200ClearStencil( GLcontext *ctx, GLint s )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- rmesa->state.stencil.clear =
+ rmesa->radeon.state.stencil.clear =
((GLuint) (ctx->Stencil.Clear & 0xff) |
(0xff << R200_STENCIL_MASK_SHIFT) |
((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT));
@@ -1700,19 +1592,29 @@ static void r200ClearStencil( GLcontext *ctx, GLint s )
void r200UpdateWindow( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
- GLfloat xoffset = (GLfloat)dPriv->x;
- GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
+ GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
+ GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
const GLfloat *v = ctx->Viewport._WindowMap.m;
+ const GLboolean render_to_fbo = (ctx->DrawBuffer ? (ctx->DrawBuffer->Name != 0) : 0);
+ const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+ GLfloat y_scale, y_bias;
+
+ if (render_to_fbo) {
+ y_scale = 1.0;
+ y_bias = 0;
+ } else {
+ y_scale = -1.0;
+ y_bias = yoffset;
+ }
float_ui32_type sx = { v[MAT_SX] };
float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
- float_ui32_type sy = { - v[MAT_SY] };
- float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
- float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale };
- float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale };
+ float_ui32_type sy = { v[MAT_SY] * y_scale };
+ float_ui32_type ty = { (v[MAT_TY] * y_scale) + y_bias + SUBPIXEL_Y };
+ float_ui32_type sz = { v[MAT_SZ] * depthScale };
+ float_ui32_type tz = { v[MAT_TZ] * depthScale };
- R200_FIREVERTICES( rmesa );
R200_STATECHANGE( rmesa, vpt );
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
@@ -1723,6 +1625,30 @@ void r200UpdateWindow( GLcontext *ctx )
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
}
+void r200_vtbl_update_scissor( GLcontext *ctx )
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ unsigned x1, y1, x2, y2;
+ struct radeon_renderbuffer *rrb;
+
+ R200_SET_STATE(r200, set, SET_RE_CNTL, R200_SCISSOR_ENABLE | r200->hw.set.cmd[SET_RE_CNTL]);
+
+ if (r200->radeon.state.scissor.enabled) {
+ x1 = r200->radeon.state.scissor.rect.x1;
+ y1 = r200->radeon.state.scissor.rect.y1;
+ x2 = r200->radeon.state.scissor.rect.x2;
+ y2 = r200->radeon.state.scissor.rect.y2;
+ } else {
+ rrb = radeon_get_colorbuffer(&r200->radeon);
+ x1 = 0;
+ y1 = 0;
+ x2 = rrb->base.Width - 1;
+ y2 = rrb->base.Height - 1;
+ }
+
+ R200_SET_STATE(r200, sci, SCI_XY_1, x1 | (y1 << 16));
+ R200_SET_STATE(r200, sci, SCI_XY_2, x2 | (y2 << 16));
+}
static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
@@ -1733,6 +1659,8 @@ static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
* values, or keep the originals hanging around.
*/
r200UpdateWindow( ctx );
+
+ radeon_viewport(ctx, x, y, width, height);
}
static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
@@ -1744,7 +1672,7 @@ static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
void r200UpdateViewportOffset( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
GLfloat xoffset = (GLfloat)dPriv->x;
GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
const GLfloat *v = ctx->Viewport._WindowMap.m;
@@ -1774,8 +1702,8 @@ void r200UpdateViewportOffset( GLcontext *ctx )
R200_STIPPLE_Y_OFFSET_MASK);
/* add magic offsets, then invert */
- stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
- sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
+ stx = 31 - ((dPriv->x - 1) & R200_STIPPLE_COORD_MASK);
+ sty = 31 - ((dPriv->y + dPriv->h - 1)
& R200_STIPPLE_COORD_MASK);
m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
@@ -1788,7 +1716,7 @@ void r200UpdateViewportOffset( GLcontext *ctx )
}
}
- r200UpdateScissor( ctx );
+ radeonUpdateScissor( ctx );
}
@@ -1801,11 +1729,16 @@ static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLubyte color[4];
+ struct radeon_renderbuffer *rrb;
+
+ rrb = radeon_get_colorbuffer(&rmesa->radeon);
+ if (!rrb)
+ return;
CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
- rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
+ rmesa->radeon.state.color.clear = radeonPackColor( rrb->cpp,
color[0], color[1],
color[2], color[3] );
}
@@ -1848,96 +1781,6 @@ static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
}
-
-/*
- * Set up the cliprects for either front or back-buffer drawing.
- */
-void r200SetCliprects( r200ContextPtr rmesa )
-{
- __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
- __DRIdrawablePrivate *const readable = rmesa->dri.readable;
- GLframebuffer *const draw_fb = (GLframebuffer*) drawable->driverPrivate;
- GLframebuffer *const read_fb = (GLframebuffer*) readable->driverPrivate;
-
- if (draw_fb->_ColorDrawBufferIndexes[0] == BUFFER_BIT_BACK_LEFT) {
- /* Can't ignore 2d windows if we are page flipping.
- */
- if ( drawable->numBackClipRects == 0 || rmesa->doPageFlip ) {
- rmesa->numClipRects = drawable->numClipRects;
- rmesa->pClipRects = drawable->pClipRects;
- }
- else {
- rmesa->numClipRects = drawable->numBackClipRects;
- rmesa->pClipRects = drawable->pBackClipRects;
- }
- }
- else {
- /* front buffer (or none, or multiple buffers) */
- rmesa->numClipRects = drawable->numClipRects;
- rmesa->pClipRects = drawable->pClipRects;
- }
-
- if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) {
- _mesa_resize_framebuffer(rmesa->glCtx, draw_fb,
- drawable->w, drawable->h);
- draw_fb->Initialized = GL_TRUE;
- }
-
- if (drawable != readable) {
- if ((read_fb->Width != readable->w) ||
- (read_fb->Height != readable->h)) {
- _mesa_resize_framebuffer(rmesa->glCtx, read_fb,
- readable->w, readable->h);
- read_fb->Initialized = GL_TRUE;
- }
- }
-
- if (rmesa->state.scissor.enabled)
- r200RecalcScissorRects( rmesa );
-
- rmesa->lastStamp = drawable->lastStamp;
-}
-
-
-static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if (R200_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s %s\n", __FUNCTION__,
- _mesa_lookup_enum_by_nr( mode ));
-
- R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
-
- if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
- /* 0 (GL_NONE) buffers or multiple color drawing buffers */
- FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
- return;
- }
-
- switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
- case BUFFER_FRONT_LEFT:
- case BUFFER_BACK_LEFT:
- FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
- break;
- default:
- FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
- return;
- }
-
- r200SetCliprects( rmesa );
-
- /* We'll set the drawing engine's offset/pitch parameters later
- * when we update other state.
- */
-}
-
-
-static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
-{
- /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
-}
-
/* =============================================================
* State enable/disable
*/
@@ -1947,7 +1790,7 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint p, flag;
- if ( R200_DEBUG & DEBUG_STATE )
+ if ( R200_DEBUG & RADEON_STATE )
fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr( cap ),
state ? "GL_TRUE" : "GL_FALSE" );
@@ -1979,7 +1822,7 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
case GL_CLIP_PLANE2:
case GL_CLIP_PLANE3:
case GL_CLIP_PLANE4:
- case GL_CLIP_PLANE5:
+ case GL_CLIP_PLANE5:
p = cap-GL_CLIP_PLANE0;
R200_STATECHANGE( rmesa, tcl );
if (state) {
@@ -2013,10 +1856,10 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
R200_STATECHANGE(rmesa, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
} else {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;
}
break;
@@ -2031,7 +1874,7 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
}
r200UpdateSpecular( ctx ); /* for PK_SPEC */
- if (rmesa->TclFallback)
+ if (rmesa->radeon.TclFallback)
r200ChooseVertexState( ctx );
_mesa_allow_light_in_model( ctx, !state );
break;
@@ -2046,13 +1889,13 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
case GL_LIGHT7:
R200_STATECHANGE(rmesa, tcl);
p = cap - GL_LIGHT0;
- if (p&1)
+ if (p&1)
flag = (R200_LIGHT_1_ENABLE |
- R200_LIGHT_1_ENABLE_AMBIENT |
+ R200_LIGHT_1_ENABLE_AMBIENT |
R200_LIGHT_1_ENABLE_SPECULAR);
else
flag = (R200_LIGHT_0_ENABLE |
- R200_LIGHT_0_ENABLE_AMBIENT |
+ R200_LIGHT_0_ENABLE_AMBIENT |
R200_LIGHT_0_ENABLE_SPECULAR);
if (state)
@@ -2060,7 +1903,7 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
else
rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
- /*
+ /*
*/
update_light_colors( ctx, p );
break;
@@ -2068,7 +1911,7 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
case GL_LIGHTING:
r200UpdateSpecular(ctx);
/* for reflection map fixup - might set recheck_texgen for all units too */
- rmesa->NewGLState |= _NEW_TEXTURE;
+ rmesa->radeon.NewGLState |= _NEW_TEXTURE;
break;
case GL_LINE_SMOOTH:
@@ -2181,21 +2024,30 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
}
case GL_SCISSOR_TEST:
- R200_FIREVERTICES( rmesa );
- rmesa->state.scissor.enabled = state;
- r200UpdateScissor( ctx );
+ radeon_firevertices(&rmesa->radeon);
+ rmesa->radeon.state.scissor.enabled = state;
+ radeonUpdateScissor( ctx );
break;
case GL_STENCIL_TEST:
- if ( rmesa->state.stencil.hwBuffer ) {
- R200_STATECHANGE( rmesa, ctx );
- if ( state ) {
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
+ {
+ GLboolean hw_stencil = GL_FALSE;
+ if (ctx->DrawBuffer) {
+ struct radeon_renderbuffer *rrbStencil
+ = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
+ hw_stencil = (rrbStencil && rrbStencil->bo);
+ }
+
+ if (hw_stencil) {
+ R200_STATECHANGE( rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
+ }
} else {
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
+ FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
}
- } else {
- FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
}
break;
@@ -2205,7 +2057,7 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
case GL_TEXTURE_GEN_T:
/* Picked up in r200UpdateTextureState.
*/
- rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
+ rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
break;
case GL_COLOR_SUM_EXT:
@@ -2322,7 +2174,7 @@ void r200LightingSpaceChange( GLcontext *ctx )
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLboolean tmp;
- if (R200_DEBUG & DEBUG_STATE)
+ if (R200_DEBUG & RADEON_STATE)
fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
@@ -2338,7 +2190,7 @@ void r200LightingSpaceChange( GLcontext *ctx )
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
}
- if (R200_DEBUG & DEBUG_STATE)
+ if (R200_DEBUG & RADEON_STATE)
fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
}
@@ -2381,7 +2233,7 @@ static void update_texturematrix( GLcontext *ctx )
GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
int unit;
- if (R200_DEBUG & DEBUG_STATE)
+ if (R200_DEBUG & RADEON_STATE)
fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
@@ -2389,7 +2241,7 @@ static void update_texturematrix( GLcontext *ctx )
rmesa->TexMatCompSel = 0;
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
- if (!ctx->Texture.Unit[unit]._ReallyEnabled)
+ if (!ctx->Texture.Unit[unit]._ReallyEnabled)
continue;
if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
@@ -2399,21 +2251,21 @@ static void update_texturematrix( GLcontext *ctx )
rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
- /* Need to preconcatenate any active texgen
+ /* Need to preconcatenate any active texgen
* obj/eyeplane matrices:
*/
_math_matrix_mul_matrix( &rmesa->tmpmat,
- ctx->TextureMatrixStack[unit].Top,
+ ctx->TextureMatrixStack[unit].Top,
&rmesa->TexGenMatrix[unit] );
upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
- }
+ }
else {
- upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
+ upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
R200_MTX_TEX0+unit );
}
}
else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
- upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
+ upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
R200_MTX_TEX0+unit );
}
}
@@ -2432,69 +2284,84 @@ static void update_texturematrix( GLcontext *ctx )
}
}
-
-
-/**
- * Tell the card where to render (offset, pitch).
- * Effected by glDrawBuffer, etc
- */
-void
-r200UpdateDrawBuffer(GLcontext *ctx)
+static GLboolean r200ValidateBuffers(GLcontext *ctx)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- struct gl_framebuffer *fb = ctx->DrawBuffer;
- driRenderbuffer *drb;
+ struct radeon_renderbuffer *rrb;
+ struct radeon_dma_bo *dma_bo;
+ int i, ret;
- if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
- /* draw to front */
- drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
- }
- else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
- /* draw to back */
- drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+ radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
+
+ rrb = radeon_get_colorbuffer(&rmesa->radeon);
+ /* color buffer */
+ if (rrb && rrb->bo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
+ 0, RADEON_GEM_DOMAIN_VRAM);
}
- else {
- /* drawing to multiple buffers, or none */
- return;
+
+ /* depth buffer */
+ rrb = radeon_get_depthbuffer(&rmesa->radeon);
+ /* color buffer */
+ if (rrb && rrb->bo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
+ 0, RADEON_GEM_DOMAIN_VRAM);
}
- assert(drb);
- assert(drb->flippedPitch);
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
+ radeonTexObj *t;
- R200_STATECHANGE( rmesa, ctx );
+ if (!ctx->Texture.Unit[i]._ReallyEnabled)
+ continue;
- /* Note: we used the (possibly) page-flipped values */
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
- = ((drb->flippedOffset + rmesa->r200Screen->fbLocation)
- & R200_COLOROFFSET_MASK);
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
- if (rmesa->sarea->tiling_enabled) {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
+ t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
+ if (t->image_override && t->bo)
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+ else if (t->mt->bo)
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
}
-}
-
+ dma_bo = first_elem(&rmesa->radeon.dma.reserved);
+ {
+ ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, dma_bo->bo, RADEON_GEM_DOMAIN_GTT, 0);
+ if (ret)
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
-void r200ValidateState( GLcontext *ctx )
+GLboolean r200ValidateState( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- GLuint new_state = rmesa->NewGLState;
+ GLuint new_state = rmesa->radeon.NewGLState;
- if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
- r200UpdateDrawBuffer(ctx);
+ if (new_state & _NEW_BUFFERS) {
+ _mesa_update_framebuffer(ctx);
+ /* this updates the DrawBuffer's Width/Height if it's a FBO */
+ _mesa_update_draw_buffer_bounds(ctx);
+
+ R200_STATECHANGE(rmesa, ctx);
}
- if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) {
+ if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) {
r200UpdateTextureState( ctx );
- new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
+ new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
r200UpdateLocalViewer( ctx );
}
+ /* we need to do a space check here */
+ if (!r200ValidateBuffers(ctx))
+ return GL_FALSE;
+
/* FIXME: don't really need most of these when vertex progs are enabled */
/* Need an event driven matrix update?
*/
- if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
+ if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
/* Need these for lighting (shouldn't upload otherwise)
@@ -2518,11 +2385,12 @@ void r200ValidateState( GLcontext *ctx )
/* emit all active clip planes if projection matrix changes.
*/
if (new_state & (_NEW_PROJECTION)) {
- if (ctx->Transform.ClipPlanesEnabled)
+ if (ctx->Transform.ClipPlanesEnabled)
r200UpdateClipPlanes( ctx );
}
if (new_state & (_NEW_PROGRAM|
+ _NEW_PROGRAM_CONSTANTS |
/* need to test for pretty much anything due to possible parameter bindings */
_NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
_NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
@@ -2533,7 +2401,8 @@ void r200ValidateState( GLcontext *ctx )
else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
}
- rmesa->NewGLState = 0;
+ rmesa->radeon.NewGLState = 0;
+ return GL_TRUE;
}
@@ -2544,7 +2413,7 @@ static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
_vbo_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
_ae_invalidate_state( ctx, new_state );
- R200_CONTEXT(ctx)->NewGLState |= new_state;
+ R200_CONTEXT(ctx)->radeon.NewGLState |= new_state;
}
/* A hack. The r200 can actually cope just fine with materials
@@ -2573,12 +2442,13 @@ static void r200WrapRunPipeline( GLcontext *ctx )
GLboolean has_material;
if (0)
- fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
+ fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState);
/* Validate state:
*/
- if (rmesa->NewGLState)
- r200ValidateState( ctx );
+ if (rmesa->radeon.NewGLState)
+ if (!r200ValidateState( ctx ))
+ FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
@@ -2587,7 +2457,7 @@ static void r200WrapRunPipeline( GLcontext *ctx )
}
/* Run the pipeline.
- */
+ */
_tnl_run_pipeline( ctx );
if (has_material) {
@@ -2596,15 +2466,30 @@ static void r200WrapRunPipeline( GLcontext *ctx )
}
+static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ GLint i;
+
+ radeon_firevertices(&r200->radeon);
+
+ R200_STATECHANGE(r200, stp);
+
+ /* Must flip pattern upside down.
+ */
+ for ( i = 31 ; i >= 0; i--) {
+ r200->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i];
+ }
+}
/* Initialize the driver's state functions.
*/
-void r200InitStateFuncs( struct dd_function_table *functions )
+void r200InitStateFuncs( struct dd_function_table *functions, GLboolean dri2 )
{
functions->UpdateState = r200InvalidateState;
functions->LightingSpaceChange = r200LightingSpaceChange;
- functions->DrawBuffer = r200DrawBuffer;
- functions->ReadBuffer = r200ReadBuffer;
+ functions->DrawBuffer = radeonDrawBuffer;
+ functions->ReadBuffer = radeonReadBuffer;
functions->AlphaFunc = r200AlphaFunc;
functions->BlendColor = r200BlendColor;
@@ -2632,11 +2517,14 @@ void r200InitStateFuncs( struct dd_function_table *functions )
functions->LogicOpcode = r200LogicOpCode;
functions->PolygonMode = r200PolygonMode;
functions->PolygonOffset = r200PolygonOffset;
- functions->PolygonStipple = r200PolygonStipple;
+ if (dri2)
+ functions->PolygonStipple = r200PolygonStipple;
+ else
+ functions->PolygonStipple = radeonPolygonStipplePreKMS;
functions->PointParameterfv = r200PointParameter;
functions->PointSize = r200PointSize;
functions->RenderMode = r200RenderMode;
- functions->Scissor = r200Scissor;
+ functions->Scissor = radeonScissor;
functions->ShadeModel = r200ShadeModel;
functions->StencilFuncSeparate = r200StencilFuncSeparate;
functions->StencilMaskSeparate = r200StencilMaskSeparate;
diff --git a/src/mesa/drivers/dri/r200/r200_state.h b/src/mesa/drivers/dri/r200/r200_state.h
index a917163a00..9c62f0a644 100644
--- a/src/mesa/drivers/dri/r200/r200_state.h
+++ b/src/mesa/drivers/dri/r200/r200_state.h
@@ -38,28 +38,24 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r200_context.h"
extern void r200InitState( r200ContextPtr rmesa );
-extern void r200InitStateFuncs( struct dd_function_table *functions );
+extern void r200InitStateFuncs( struct dd_function_table *functions, GLboolean dri2 );
extern void r200InitTnlFuncs( GLcontext *ctx );
extern void r200UpdateMaterial( GLcontext *ctx );
-extern void r200SetCliprects( r200ContextPtr rmesa );
-extern void r200RecalcScissorRects( r200ContextPtr rmesa );
extern void r200UpdateViewportOffset( GLcontext *ctx );
extern void r200UpdateWindow( GLcontext *ctx );
extern void r200UpdateDrawBuffer(GLcontext *ctx);
-extern void r200ValidateState( GLcontext *ctx );
-
-extern void r200PrintDirty( r200ContextPtr rmesa,
- const char *msg );
+extern GLboolean r200ValidateState( GLcontext *ctx );
+extern void r200_vtbl_update_scissor( GLcontext *ctx );
extern void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define FALLBACK( rmesa, bit, mode ) do { \
if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \
__FUNCTION__, bit, mode ); \
- r200Fallback( rmesa->glCtx, bit, mode ); \
+ r200Fallback( rmesa->radeon.glCtx, bit, mode ); \
} while (0)
extern void r200LightingSpaceChange( GLcontext *ctx );
diff --git a/src/mesa/drivers/dri/r200/r200_state_init.c b/src/mesa/drivers/dri/r200/r200_state_init.c
index 9e4677eda4..7697306d88 100644
--- a/src/mesa/drivers/dri/r200/r200_state_init.c
+++ b/src/mesa/drivers/dri/r200/r200_state_init.c
@@ -43,40 +43,141 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "tnl/t_pipeline.h"
#include "swrast_setup/swrast_setup.h"
+#include "radeon_common.h"
+#include "radeon_mipmap_tree.h"
#include "r200_context.h"
#include "r200_ioctl.h"
#include "r200_state.h"
#include "r200_tcl.h"
#include "r200_tex.h"
#include "r200_swtcl.h"
+#include "radeon_queryobj.h"
#include "xmlpool.h"
+/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
+ * 1.3 cmdbuffers allow all previous state to be updated as well as
+ * the tcl scalar and vector areas.
+ */
+static struct {
+ int start;
+ int len;
+ const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+ {RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
+ {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
+ {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
+ {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
+ {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
+ {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
+ {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
+ {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
+ {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
+ {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
+ {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
+ {RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
+ {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
+ {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
+ {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
+ {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
+ {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
+ {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
+ {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
+ {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
+ {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
+ "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
+ {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
+ {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
+ {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
+ {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
+ {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
+ {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
+ {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
+ {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
+ {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
+ {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
+ {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
+ {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
+ {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
+ {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
+ {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
+ {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
+ {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
+ {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
+ {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
+ {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
+ {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
+ {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
+ {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
+ {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
+ {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
+ {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
+ {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
+ {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
+ {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1,
+ "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
+ {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
+ {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
+ {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
+ {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
+ {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
+ {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
+ {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
+ {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
+ {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
+ {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
+ {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
+ "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
+ {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */
+ {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
+ {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
+ {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
+ {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
+ {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
+ {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
+ {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
+ {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
+ {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
+ {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
+ {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
+ {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
+ {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
+ {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
+ {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
+ {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
+ {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
+ {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
+ {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
+ {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
+ {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
+ {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
+ {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
+ {R200_PP_TXCBLEND_8, 32, "R200_PP_AFS_0"}, /* 85 */
+ {R200_PP_TXCBLEND_0, 32, "R200_PP_AFS_1"},
+ {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
+ {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
+ {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
+ {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
+ {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
+ {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
+ {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
+ {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
+};
+
/* =============================================================
* State initialization
*/
-
-void r200PrintDirty( r200ContextPtr rmesa, const char *msg )
+static int cmdpkt( r200ContextPtr rmesa, int id )
{
- struct r200_state_atom *l;
-
- fprintf(stderr, msg);
- fprintf(stderr, ": ");
+ drm_radeon_cmd_header_t h;
- foreach(l, &rmesa->hw.atomlist) {
- if (l->dirty || rmesa->hw.all_dirty)
- fprintf(stderr, "%s, ", l->name);
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ return CP_PACKET0(packet[id].start, packet[id].len - 1);
+ } else {
+ h.i = 0;
+ h.packet.cmd_type = RADEON_CMD_PACKET;
+ h.packet.packet_id = id;
}
-
- fprintf(stderr, "\n");
-}
-
-static int cmdpkt( int id )
-{
- drm_radeon_cmd_header_t h;
- h.i = 0;
- h.packet.cmd_type = RADEON_CMD_PACKET;
- h.packet.packet_id = id;
return h.i;
}
@@ -126,151 +227,607 @@ static int cmdscl2( int offset, int stride, int count )
return h.i;
}
-#define CHECK( NM, FLAG ) \
-static GLboolean check_##NM( GLcontext *ctx, int idx ) \
+/**
+ * Check functions are used to check if state is active.
+ * If it is active check function returns maximum emit size.
+ */
+#define CHECK( NM, FLAG, ADD ) \
+static int check_##NM( GLcontext *ctx, struct radeon_state_atom *atom) \
{ \
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
- (void) idx; \
(void) rmesa; \
- return FLAG; \
+ return (FLAG) ? atom->cmd_size + (ADD) : 0; \
}
-#define TCL_CHECK( NM, FLAG ) \
-static GLboolean check_##NM( GLcontext *ctx, int idx ) \
-{ \
- r200ContextPtr rmesa = R200_CONTEXT(ctx); \
- (void) idx; \
- return !rmesa->TclFallback && !ctx->VertexProgram._Enabled && (FLAG); \
+#define TCL_CHECK( NM, FLAG, ADD ) \
+static int check_##NM( GLcontext *ctx, struct radeon_state_atom *atom) \
+{ \
+ r200ContextPtr rmesa = R200_CONTEXT(ctx); \
+ return (!rmesa->radeon.TclFallback && !ctx->VertexProgram._Enabled && (FLAG)) ? atom->cmd_size + (ADD) : 0; \
}
-#define TCL_OR_VP_CHECK( NM, FLAG ) \
-static GLboolean check_##NM( GLcontext *ctx, int idx ) \
+#define TCL_OR_VP_CHECK( NM, FLAG, ADD ) \
+static int check_##NM( GLcontext *ctx, struct radeon_state_atom *atom ) \
{ \
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
- (void) idx; \
- return !rmesa->TclFallback && (FLAG); \
+ return (!rmesa->radeon.TclFallback && (FLAG)) ? atom->cmd_size + (ADD) : 0; \
}
-#define VP_CHECK( NM, FLAG ) \
-static GLboolean check_##NM( GLcontext *ctx, int idx ) \
-{ \
- r200ContextPtr rmesa = R200_CONTEXT(ctx); \
- (void) idx; \
- return !rmesa->TclFallback && ctx->VertexProgram._Enabled && (FLAG); \
+#define VP_CHECK( NM, FLAG, ADD ) \
+static int check_##NM( GLcontext *ctx, struct radeon_state_atom *atom ) \
+{ \
+ r200ContextPtr rmesa = R200_CONTEXT(ctx); \
+ (void) atom; \
+ return (!rmesa->radeon.TclFallback && ctx->VertexProgram._Enabled && (FLAG)) ? atom->cmd_size + (ADD) : 0; \
+}
+
+CHECK( always, GL_TRUE, 0 )
+CHECK( always_add4, GL_TRUE, 4 )
+CHECK( never, GL_FALSE, 0 )
+CHECK( tex_any, ctx->Texture._EnabledUnits, 0 )
+CHECK( tf, (ctx->Texture._EnabledUnits && !ctx->ATIFragmentShader._Enabled), 0 );
+CHECK( pix_zero, !ctx->ATIFragmentShader._Enabled, 0 )
+ CHECK( texenv, (rmesa->state.envneeded & (1 << (atom->idx)) && !ctx->ATIFragmentShader._Enabled), 0 )
+CHECK( afs_pass1, (ctx->ATIFragmentShader._Enabled && (ctx->ATIFragmentShader.Current->NumPasses > 1)), 0 )
+CHECK( afs, ctx->ATIFragmentShader._Enabled, 0 )
+CHECK( tex_cube, rmesa->state.texture.unit[atom->idx].unitneeded & TEXTURE_CUBE_BIT, 3 + 3*5 - CUBE_STATE_SIZE )
+CHECK( tex_cube_cs, rmesa->state.texture.unit[atom->idx].unitneeded & TEXTURE_CUBE_BIT, 2 + 4*5 - CUBE_STATE_SIZE )
+TCL_CHECK( tcl_fog, ctx->Fog.Enabled, 0 )
+TCL_CHECK( tcl_fog_add4, ctx->Fog.Enabled, 4 )
+TCL_CHECK( tcl, GL_TRUE, 0 )
+TCL_CHECK( tcl_add8, GL_TRUE, 8 )
+TCL_CHECK( tcl_add4, GL_TRUE, 4 )
+TCL_CHECK( tcl_tex, rmesa->state.texture.unit[atom->idx].unitneeded, 0 )
+TCL_CHECK( tcl_lighting, ctx->Light.Enabled, 0 )
+TCL_CHECK( tcl_light, ctx->Light.Enabled && ctx->Light.Light[atom->idx].Enabled, 0 )
+TCL_CHECK( tcl_tex_add4, rmesa->state.texture.unit[atom->idx].unitneeded, 4 )
+TCL_CHECK( tcl_lighting_add4, ctx->Light.Enabled, 4 )
+TCL_CHECK( tcl_lighting_add6, ctx->Light.Enabled, 6 )
+TCL_CHECK( tcl_light_add8, ctx->Light.Enabled && ctx->Light.Light[atom->idx].Enabled, 8 )
+TCL_OR_VP_CHECK( tcl_ucp, (ctx->Transform.ClipPlanesEnabled & (1 << (atom->idx))), 0 )
+TCL_OR_VP_CHECK( tcl_ucp_add4, (ctx->Transform.ClipPlanesEnabled & (1 << (atom->idx))), 4 )
+TCL_OR_VP_CHECK( tcl_or_vp, GL_TRUE, 0 )
+TCL_OR_VP_CHECK( tcl_or_vp_add2, GL_TRUE, 2 )
+VP_CHECK( tcl_vp, GL_TRUE, 0 )
+VP_CHECK( tcl_vp_add4, GL_TRUE, 4 )
+VP_CHECK( tcl_vp_size, ctx->VertexProgram.Current->Base.NumNativeInstructions > 64, 0 )
+VP_CHECK( tcl_vpp_size, ctx->VertexProgram.Current->Base.NumNativeParameters > 96, 0 )
+VP_CHECK( tcl_vp_size_add4, ctx->VertexProgram.Current->Base.NumNativeInstructions > 64, 4 )
+VP_CHECK( tcl_vpp_size_add4, ctx->VertexProgram.Current->Base.NumNativeParameters > 96, 4 )
+
+#define OUT_VEC(hdr, data) do { \
+ drm_radeon_cmd_header_t h; \
+ h.i = hdr; \
+ OUT_BATCH(CP_PACKET0(RADEON_SE_TCL_STATE_FLUSH, 0)); \
+ OUT_BATCH(0); \
+ OUT_BATCH(CP_PACKET0(R200_SE_TCL_VECTOR_INDX_REG, 0)); \
+ OUT_BATCH(h.vectors.offset | (h.vectors.stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); \
+ OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_VECTOR_DATA_REG, h.vectors.count - 1)); \
+ OUT_BATCH_TABLE((data), h.vectors.count); \
+ } while(0)
+
+#define OUT_VECLINEAR(hdr, data) do { \
+ drm_radeon_cmd_header_t h; \
+ uint32_t _start, _sz; \
+ h.i = hdr; \
+ _start = h.veclinear.addr_lo | (h.veclinear.addr_hi << 8); \
+ _sz = h.veclinear.count * 4; \
+ if (r200->radeon.radeonScreen->kernel_mm && _sz) { \
+ BEGIN_BATCH_NO_AUTOSTATE(dwords); \
+ OUT_BATCH(CP_PACKET0(RADEON_SE_TCL_STATE_FLUSH, 0)); \
+ OUT_BATCH(0); \
+ OUT_BATCH(CP_PACKET0(R200_SE_TCL_VECTOR_INDX_REG, 0)); \
+ OUT_BATCH(_start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); \
+ OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_VECTOR_DATA_REG, _sz - 1)); \
+ OUT_BATCH_TABLE((data), _sz); \
+ END_BATCH(); \
+ } \
+ } while(0)
+
+#define OUT_SCL(hdr, data) do { \
+ drm_radeon_cmd_header_t h; \
+ h.i = hdr; \
+ OUT_BATCH(CP_PACKET0(R200_SE_TCL_SCALAR_INDX_REG, 0)); \
+ OUT_BATCH((h.scalars.offset) | (h.scalars.stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); \
+ OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_SCALAR_DATA_REG, h.scalars.count - 1)); \
+ OUT_BATCH_TABLE((data), h.scalars.count); \
+ } while(0)
+
+#define OUT_SCL2(hdr, data) do { \
+ drm_radeon_cmd_header_t h; \
+ h.i = hdr; \
+ OUT_BATCH(CP_PACKET0(R200_SE_TCL_SCALAR_INDX_REG, 0)); \
+ OUT_BATCH((h.scalars.offset + 0x100) | (h.scalars.stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); \
+ OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_SCALAR_DATA_REG, h.scalars.count - 1)); \
+ OUT_BATCH_TABLE((data), h.scalars.count); \
+ } while(0)
+static int check_rrb(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrb;
+ rrb = radeon_get_colorbuffer(&r200->radeon);
+ if (!rrb || !rrb->bo)
+ return 0;
+ return atom->cmd_size;
+}
+
+static void mtl_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_VEC(atom->cmd[MTL_CMD_0], (atom->cmd+1));
+ OUT_SCL2(atom->cmd[MTL_CMD_1], (atom->cmd + 18));
+ END_BATCH();
}
+static void lit_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_VEC(atom->cmd[LIT_CMD_0], atom->cmd+1);
+ OUT_VEC(atom->cmd[LIT_CMD_1], atom->cmd+LIT_CMD_1+1);
+ END_BATCH();
+}
-CHECK( always, GL_TRUE )
-CHECK( never, GL_FALSE )
-CHECK( tex_any, ctx->Texture._EnabledUnits )
-CHECK( tf, (ctx->Texture._EnabledUnits && !ctx->ATIFragmentShader._Enabled) );
-CHECK( tex_pair, (rmesa->state.texture.unit[idx].unitneeded | rmesa->state.texture.unit[idx & ~1].unitneeded) )
-CHECK( tex, rmesa->state.texture.unit[idx].unitneeded )
-CHECK( pix_zero, !ctx->ATIFragmentShader._Enabled )
-CHECK( texenv, (rmesa->state.envneeded & (1 << idx) && !ctx->ATIFragmentShader._Enabled) )
-CHECK( afs_pass1, (ctx->ATIFragmentShader._Enabled && (ctx->ATIFragmentShader.Current->NumPasses > 1)) )
-CHECK( afs, ctx->ATIFragmentShader._Enabled )
-CHECK( tex_cube, rmesa->state.texture.unit[idx].unitneeded & TEXTURE_CUBE_BIT )
-TCL_CHECK( tcl_fog, ctx->Fog.Enabled )
-TCL_CHECK( tcl, GL_TRUE )
-TCL_CHECK( tcl_tex, rmesa->state.texture.unit[idx].unitneeded )
-TCL_CHECK( tcl_lighting, ctx->Light.Enabled )
-TCL_CHECK( tcl_light, ctx->Light.Enabled && ctx->Light.Light[idx].Enabled )
-TCL_OR_VP_CHECK( tcl_ucp, (ctx->Transform.ClipPlanesEnabled & (1 << idx)) )
-TCL_OR_VP_CHECK( tcl_or_vp, GL_TRUE )
-VP_CHECK( tcl_vp, GL_TRUE )
-VP_CHECK( tcl_vp_size, ctx->VertexProgram.Current->Base.NumNativeInstructions > 64 )
-VP_CHECK( tcl_vpp_size, ctx->VertexProgram.Current->Base.NumNativeParameters > 96 )
+static void ptp_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_VEC(atom->cmd[PTP_CMD_0], atom->cmd+1);
+ OUT_VEC(atom->cmd[PTP_CMD_1], atom->cmd+PTP_CMD_1+1);
+ END_BATCH();
+}
+static void veclinear_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
-/* Initialize the context's hardware state.
- */
-void r200InitState( r200ContextPtr rmesa )
+ OUT_VECLINEAR(atom->cmd[0], atom->cmd+1);
+}
+
+static void scl_emit(GLcontext *ctx, struct radeon_state_atom *atom)
{
- GLcontext *ctx = rmesa->glCtx;
- GLuint color_fmt, depth_fmt, i;
- GLint drawPitch, drawOffset;
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
- switch ( rmesa->r200Screen->cpp ) {
- case 2:
- color_fmt = R200_COLOR_FORMAT_RGB565;
- break;
- case 4:
- color_fmt = R200_COLOR_FORMAT_ARGB8888;
- break;
- default:
- fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" );
- exit( -1 );
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_SCL(atom->cmd[0], atom->cmd+1);
+ END_BATCH();
+}
+
+
+static void vec_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_VEC(atom->cmd[0], atom->cmd+1);
+ END_BATCH();
+}
+
+static void ctx_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ struct radeon_renderbuffer *rrb;
+ uint32_t cbpitch;
+ uint32_t zbpitch, depth_fmt;
+ uint32_t dwords = atom->check(ctx, atom);
+
+ /* output the first 7 bytes of context */
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(atom->cmd, 5);
+
+ rrb = radeon_get_depthbuffer(&r200->radeon);
+ if (!rrb) {
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ } else {
+ zbpitch = (rrb->pitch / rrb->cpp);
+ if (r200->using_hyperz)
+ zbpitch |= RADEON_DEPTH_HYPERZ;
+ OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_BATCH(zbpitch);
+ if (rrb->cpp == 4)
+ depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+ else
+ depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+ atom->cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_DEPTH_FORMAT_MASK;
+ atom->cmd[CTX_RB3D_ZSTENCILCNTL] |= depth_fmt;
+ }
+
+ OUT_BATCH(atom->cmd[CTX_RB3D_ZSTENCILCNTL]);
+ OUT_BATCH(atom->cmd[CTX_CMD_1]);
+ OUT_BATCH(atom->cmd[CTX_PP_CNTL]);
+
+ rrb = radeon_get_colorbuffer(&r200->radeon);
+ if (!rrb || !rrb->bo) {
+ OUT_BATCH(atom->cmd[CTX_RB3D_CNTL]);
+ OUT_BATCH(atom->cmd[CTX_RB3D_COLOROFFSET]);
+ } else {
+ atom->cmd[CTX_RB3D_CNTL] &= ~(0xf << 10);
+ if (rrb->cpp == 4)
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB8888;
+ else
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_RGB565;
+
+ OUT_BATCH(atom->cmd[CTX_RB3D_CNTL]);
+ OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
}
- rmesa->state.color.clear = 0x00000000;
+ OUT_BATCH(atom->cmd[CTX_CMD_2]);
- switch ( ctx->Visual.depthBits ) {
- case 16:
- rmesa->state.depth.clear = 0x0000ffff;
- rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff;
- depth_fmt = R200_DEPTH_FORMAT_16BIT_INT_Z;
- rmesa->state.stencil.clear = 0x00000000;
- break;
- case 24:
- rmesa->state.depth.clear = 0x00ffffff;
- rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff;
- depth_fmt = R200_DEPTH_FORMAT_24BIT_INT_Z;
- rmesa->state.stencil.clear = 0xffff0000;
- break;
- default:
- fprintf( stderr, "Error: Unsupported depth %d... exiting\n",
- ctx->Visual.depthBits );
- exit( -1 );
+ if (!rrb || !rrb->bo) {
+ OUT_BATCH(atom->cmd[CTX_RB3D_COLORPITCH]);
+ } else {
+ cbpitch = (rrb->pitch / rrb->cpp);
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+ cbpitch |= R200_COLOR_TILE_ENABLE;
+ OUT_BATCH(cbpitch);
+ }
+
+ if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM)
+ OUT_BATCH_TABLE((atom->cmd + 14), 4);
+
+ END_BATCH();
+}
+
+static int check_always_ctx( GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrb, *drb;
+ uint32_t dwords;
+
+ rrb = radeon_get_colorbuffer(&r200->radeon);
+ if (!rrb || !rrb->bo) {
+ return 0;
}
- /* Only have hw stencil when depth buffer is 24 bits deep */
- rmesa->state.stencil.hwBuffer = ( ctx->Visual.stencilBits > 0 &&
- ctx->Visual.depthBits == 24 );
+ drb = radeon_get_depthbuffer(&r200->radeon);
- rmesa->Fallback = 0;
+ dwords = 10;
+ if (drb)
+ dwords += 6;
+ if (rrb)
+ dwords += 8;
+ if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM)
+ dwords += 4;
- if ( ctx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
- drawOffset = rmesa->r200Screen->backOffset;
- drawPitch = rmesa->r200Screen->backPitch;
- } else {
- drawOffset = rmesa->r200Screen->frontOffset;
- drawPitch = rmesa->r200Screen->frontPitch;
+
+ return dwords;
+}
+
+static void ctx_emit_cs(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ struct radeon_renderbuffer *rrb, *drb;
+ uint32_t cbpitch = 0;
+ uint32_t zbpitch = 0;
+ uint32_t dwords = atom->check(ctx, atom);
+ uint32_t depth_fmt;
+
+ rrb = radeon_get_colorbuffer(&r200->radeon);
+ if (!rrb || !rrb->bo) {
+ return;
}
-#if 000
- if ( ctx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
- rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset;
- rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch;
+
+ atom->cmd[CTX_RB3D_CNTL] &= ~(0xf << 10);
+ if (rrb->cpp == 4)
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB8888;
+ else switch (rrb->base._ActualFormat) {
+ case GL_RGB5:
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_RGB565;
+ break;
+ case GL_RGBA4:
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB4444;
+ break;
+ case GL_RGB5_A1:
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB1555;
+ break;
+ }
+
+ cbpitch = (rrb->pitch / rrb->cpp);
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+ cbpitch |= R200_COLOR_TILE_ENABLE;
+
+ drb = radeon_get_depthbuffer(&r200->radeon);
+ if (drb) {
+ zbpitch = (drb->pitch / drb->cpp);
+ if (drb->cpp == 4)
+ depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+ else
+ depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+ atom->cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_DEPTH_FORMAT_MASK;
+ atom->cmd[CTX_RB3D_ZSTENCILCNTL] |= depth_fmt;
+ }
+
+ /* output the first 7 bytes of context */
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+
+ /* In the CS case we need to split this up */
+ OUT_BATCH(CP_PACKET0(packet[0].start, 3));
+ OUT_BATCH_TABLE((atom->cmd + 1), 4);
+
+ if (drb) {
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHOFFSET, 0));
+ OUT_BATCH_RELOC(0, drb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHPITCH, 0));
+ OUT_BATCH(zbpitch);
+ }
+
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZSTENCILCNTL, 0));
+ OUT_BATCH(atom->cmd[CTX_RB3D_ZSTENCILCNTL]);
+ OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 1));
+ OUT_BATCH(atom->cmd[CTX_PP_CNTL]);
+ OUT_BATCH(atom->cmd[CTX_RB3D_CNTL]);
+
+
+ if (rrb) {
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLOROFFSET, 0));
+ OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
+ OUT_BATCH_RELOC(cbpitch, rrb->bo, cbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ }
+
+ if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM) {
+ OUT_BATCH_TABLE((atom->cmd + 14), 4);
+ }
+
+ END_BATCH();
+}
+
+static int get_tex_size(GLcontext* ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ uint32_t dwords = atom->cmd_size + 2;
+ int i = atom->idx;
+ radeonTexObj *t = r200->state.texture.unit[i].texobj;
+ if (!(t && t->mt && !t->image_override))
+ dwords -= 2;
+
+ return dwords;
+}
+
+static int check_tex_pair(GLcontext* ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ /** XOR is bit flip operation so use it for finding pair */
+ if (!(r200->state.texture.unit[atom->idx].unitneeded | r200->state.texture.unit[atom->idx ^ 1].unitneeded))
+ return 0;
+
+ return get_tex_size(ctx, atom);
+}
+
+static int check_tex(GLcontext* ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ if (!(r200->state.texture.unit[atom->idx].unitneeded))
+ return 0;
+
+ return get_tex_size(ctx, atom);
+}
+
+
+static void tex_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+ int i = atom->idx;
+ radeonTexObj *t = r200->state.texture.unit[i].texobj;
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ /* is this ok even with drm older than 1.18? */
+ OUT_BATCH_TABLE(atom->cmd, 10);
+
+ if (t && t->mt && !t->image_override) {
+ OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ } else if (!t) {
+ /* workaround for old CS mechanism */
+ OUT_BATCH(r200->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]);
} else {
- rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset;
- rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch;
+ OUT_BATCH(t->override_offset);
}
- rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset;
- rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch;
-#endif
+ END_BATCH();
+}
+
+static int get_tex_mm_size(GLcontext* ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ uint32_t dwords = atom->cmd_size + 2;
+ int hastexture = 1;
+ int i = atom->idx;
+ radeonTexObj *t = r200->state.texture.unit[i].texobj;
+ if (!t)
+ hastexture = 0;
+ else {
+ if (!t->mt && !t->bo)
+ hastexture = 0;
+ }
+
+ if (!hastexture)
+ dwords -= 4;
+ return dwords;
+}
+
+static int check_tex_pair_mm(GLcontext* ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ /** XOR is bit flip operation so use it for finding pair */
+ if (!(r200->state.texture.unit[atom->idx].unitneeded | r200->state.texture.unit[atom->idx ^ 1].unitneeded))
+ return 0;
+
+ return get_tex_mm_size(ctx, atom);
+}
- rmesa->hw.max_state_size = 0;
+static int check_tex_mm(GLcontext* ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ if (!(r200->state.texture.unit[atom->idx].unitneeded))
+ return 0;
+
+ return get_tex_mm_size(ctx, atom);
+}
+
+
+static void tex_emit_mm(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+ int i = atom->idx;
+ radeonTexObj *t = r200->state.texture.unit[i].texobj;
+ if (!r200->state.texture.unit[i].unitneeded)
+ dwords -= 4;
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+
+ OUT_BATCH(CP_PACKET0(R200_PP_TXFILTER_0 + (32 * i), 7));
+ OUT_BATCH_TABLE((atom->cmd + 1), 8);
+
+ if (dwords > atom->cmd_size) {
+ OUT_BATCH(CP_PACKET0(R200_PP_TXOFFSET_0 + (24 * i), 0));
+ if (t->mt && !t->image_override) {
+ OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ } else {
+ if (t->bo)
+ OUT_BATCH_RELOC(t->tile_bits, t->bo, 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ }
+ }
+ END_BATCH();
+}
+
+
+static void cube_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+ int i = atom->idx, j;
+ radeonTexObj *t = r200->state.texture.unit[i].texobj;
+ radeon_mipmap_level *lvl;
+
+ if (!(t && !t->image_override))
+ dwords = 2;
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ /* XXX that size won't really match with image_override... */
+ OUT_BATCH_TABLE(atom->cmd, 2);
+
+ if (t && !t->image_override) {
+ lvl = &t->mt->levels[0];
+ OUT_BATCH_TABLE((atom->cmd + 2), 1);
+ for (j = 1; j <= 5; j++) {
+ OUT_BATCH_RELOC(lvl->faces[j].offset, t->mt->bo, lvl->faces[j].offset,
+ RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ }
+ }
+ END_BATCH();
+}
+
+static void cube_emit_cs(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r200ContextPtr r200 = R200_CONTEXT(ctx);
+ BATCH_LOCALS(&r200->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+ int i = atom->idx, j;
+ radeonTexObj *t = r200->state.texture.unit[i].texobj;
+ radeon_mipmap_level *lvl;
+ if (!(t && !t->image_override))
+ dwords = 2;
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(atom->cmd, 2);
+
+ if (t && !t->image_override) {
+ lvl = &t->mt->levels[0];
+ for (j = 1; j <= 5; j++) {
+ OUT_BATCH(CP_PACKET0(R200_PP_CUBIC_OFFSET_F1_0 + (24*i) + (4 * (j-1)), 0));
+ OUT_BATCH_RELOC(lvl->faces[j].offset, t->mt->bo, lvl->faces[j].offset,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ }
+ }
+ END_BATCH();
+}
+
+/* Initialize the context's hardware state.
+ */
+void r200InitState( r200ContextPtr rmesa )
+{
+ GLcontext *ctx = rmesa->radeon.glCtx;
+ GLuint i;
+
+ rmesa->radeon.state.color.clear = 0x00000000;
+
+ switch ( ctx->Visual.depthBits ) {
+ case 16:
+ rmesa->radeon.state.depth.clear = 0x0000ffff;
+ rmesa->radeon.state.stencil.clear = 0x00000000;
+ break;
+ case 24:
+ default:
+ rmesa->radeon.state.depth.clear = 0x00ffffff;
+ rmesa->radeon.state.stencil.clear = 0xffff0000;
+ break;
+ }
+
+ rmesa->radeon.Fallback = 0;
+
+ rmesa->radeon.hw.max_state_size = 0;
#define ALLOC_STATE( ATOM, CHK, SZ, NM, IDX ) \
do { \
rmesa->hw.ATOM.cmd_size = SZ; \
- rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int)); \
- rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int)); \
+ rmesa->hw.ATOM.cmd = (GLuint *)CALLOC(SZ * sizeof(int)); \
+ rmesa->hw.ATOM.lastcmd = (GLuint *)CALLOC(SZ * sizeof(int)); \
rmesa->hw.ATOM.name = NM; \
rmesa->hw.ATOM.idx = IDX; \
- rmesa->hw.ATOM.check = check_##CHK; \
+ if (check_##CHK != check_never) { \
+ rmesa->hw.ATOM.check = check_##CHK; \
+ rmesa->radeon.hw.max_state_size += SZ * sizeof(int); \
+ } else { \
+ rmesa->hw.ATOM.check = NULL; \
+ } \
rmesa->hw.ATOM.dirty = GL_FALSE; \
- rmesa->hw.max_state_size += SZ * sizeof(int); \
} while (0)
/* Allocate state buffers:
*/
- if (rmesa->r200Screen->drmSupportsBlendColor)
- ALLOC_STATE( ctx, always, CTX_STATE_SIZE_NEWDRM, "CTX/context", 0 );
+ if (rmesa->radeon.radeonScreen->drmSupportsBlendColor)
+ ALLOC_STATE( ctx, always_add4, CTX_STATE_SIZE_NEWDRM, "CTX/context", 0 );
+ else
+ ALLOC_STATE( ctx, always_add4, CTX_STATE_SIZE_OLDDRM, "CTX/context", 0 );
+
+ if (rmesa->radeon.radeonScreen->kernel_mm)
+ {
+ rmesa->hw.ctx.emit = ctx_emit_cs;
+ rmesa->hw.ctx.check = check_always_ctx;
+ }
else
- ALLOC_STATE( ctx, always, CTX_STATE_SIZE_OLDDRM, "CTX/context", 0 );
+ {
+ rmesa->hw.ctx.emit = ctx_emit;
+ }
ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 );
ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 );
ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 );
@@ -282,52 +839,75 @@ void r200InitState( r200ContextPtr rmesa )
ALLOC_STATE( cst, always, CST_STATE_SIZE, "CST/constant", 0 );
ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 );
ALLOC_STATE( tf, tf, TF_STATE_SIZE, "TF/tfactor", 0 );
- if (rmesa->r200Screen->drmSupportsFragShader) {
- if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200) {
- /* make sure texture units 0/1 are emitted pair-wise for r200 t0 hang workaround */
- ALLOC_STATE( tex[0], tex_pair, TEX_STATE_SIZE_NEWDRM, "TEX/tex-0", 0 );
- ALLOC_STATE( tex[1], tex_pair, TEX_STATE_SIZE_NEWDRM, "TEX/tex-1", 1 );
- ALLOC_STATE( tam, tex_any, TAM_STATE_SIZE, "TAM/tam", 0 );
+ {
+ int state_size = TEX_STATE_SIZE_NEWDRM;
+ if (!rmesa->radeon.radeonScreen->drmSupportsFragShader) {
+ state_size = TEX_STATE_SIZE_OLDDRM;
}
- else {
- ALLOC_STATE( tex[0], tex, TEX_STATE_SIZE_NEWDRM, "TEX/tex-0", 0 );
- ALLOC_STATE( tex[1], tex, TEX_STATE_SIZE_NEWDRM, "TEX/tex-1", 1 );
- ALLOC_STATE( tam, never, TAM_STATE_SIZE, "TAM/tam", 0 );
+ if (rmesa->radeon.radeonScreen->drmSupportsFragShader) {
+ if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) {
+ /* make sure texture units 0/1 are emitted pair-wise for r200 t0 hang workaround */
+ ALLOC_STATE( tex[0], tex_pair_mm, state_size, "TEX/tex-0", 0 );
+ ALLOC_STATE( tex[1], tex_pair_mm, state_size, "TEX/tex-1", 1 );
+ ALLOC_STATE( tam, tex_any, TAM_STATE_SIZE, "TAM/tam", 0 );
+ }
+ else {
+ ALLOC_STATE( tex[0], tex_mm, state_size, "TEX/tex-0", 0 );
+ ALLOC_STATE( tex[1], tex_mm, state_size, "TEX/tex-1", 1 );
+ ALLOC_STATE( tam, never, TAM_STATE_SIZE, "TAM/tam", 0 );
+ }
+ ALLOC_STATE( tex[2], tex_mm, state_size, "TEX/tex-2", 2 );
+ ALLOC_STATE( tex[3], tex_mm, state_size, "TEX/tex-3", 3 );
+ ALLOC_STATE( tex[4], tex_mm, state_size, "TEX/tex-4", 4 );
+ ALLOC_STATE( tex[5], tex_mm, state_size, "TEX/tex-5", 5 );
+ if (!rmesa->radeon.radeonScreen->kernel_mm)
+ {
+ if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) {
+ rmesa->hw.tex[0].check = check_tex_pair;
+ rmesa->hw.tex[1].check = check_tex_pair;
+ } else {
+ rmesa->hw.tex[0].check = check_tex;
+ rmesa->hw.tex[1].check = check_tex;
+ }
+ rmesa->hw.tex[2].check = check_tex;
+ rmesa->hw.tex[3].check = check_tex;
+ rmesa->hw.tex[4].check = check_tex;
+ rmesa->hw.tex[5].check = check_tex;
+ }
+ if (rmesa->radeon.radeonScreen->drmSupportsFragShader) {
+ ALLOC_STATE( atf, afs, ATF_STATE_SIZE, "ATF/tfactor", 0 );
+ ALLOC_STATE( afs[0], afs_pass1, AFS_STATE_SIZE, "AFS/afsinst-0", 0 );
+ ALLOC_STATE( afs[1], afs, AFS_STATE_SIZE, "AFS/afsinst-1", 1 );
+ } else {
+ ALLOC_STATE( atf, never, ATF_STATE_SIZE, "ATF/tfactor", 0 );
+ ALLOC_STATE( afs[0], never, AFS_STATE_SIZE, "AFS/afsinst-0", 0 );
+ ALLOC_STATE( afs[1], never, AFS_STATE_SIZE, "AFS/afsinst-1", 1 );
+ }
}
- ALLOC_STATE( tex[2], tex, TEX_STATE_SIZE_NEWDRM, "TEX/tex-2", 2 );
- ALLOC_STATE( tex[3], tex, TEX_STATE_SIZE_NEWDRM, "TEX/tex-3", 3 );
- ALLOC_STATE( tex[4], tex, TEX_STATE_SIZE_NEWDRM, "TEX/tex-4", 4 );
- ALLOC_STATE( tex[5], tex, TEX_STATE_SIZE_NEWDRM, "TEX/tex-5", 5 );
- ALLOC_STATE( atf, afs, ATF_STATE_SIZE, "ATF/tfactor", 0 );
- ALLOC_STATE( afs[0], afs_pass1, AFS_STATE_SIZE, "AFS/afsinst-0", 0 );
- ALLOC_STATE( afs[1], afs, AFS_STATE_SIZE, "AFS/afsinst-1", 1 );
}
- else {
- if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200) {
- ALLOC_STATE( tex[0], tex_pair, TEX_STATE_SIZE_OLDDRM, "TEX/tex-0", 0 );
- ALLOC_STATE( tex[1], tex_pair, TEX_STATE_SIZE_OLDDRM, "TEX/tex-1", 1 );
- ALLOC_STATE( tam, tex_any, TAM_STATE_SIZE, "TAM/tam", 0 );
- }
- else {
- ALLOC_STATE( tex[0], tex, TEX_STATE_SIZE_OLDDRM, "TEX/tex-0", 0 );
- ALLOC_STATE( tex[1], tex, TEX_STATE_SIZE_OLDDRM, "TEX/tex-1", 1 );
- ALLOC_STATE( tam, never, TAM_STATE_SIZE, "TAM/tam", 0 );
- }
- ALLOC_STATE( tex[2], tex, TEX_STATE_SIZE_OLDDRM, "TEX/tex-2", 2 );
- ALLOC_STATE( tex[3], tex, TEX_STATE_SIZE_OLDDRM, "TEX/tex-3", 3 );
- ALLOC_STATE( tex[4], tex, TEX_STATE_SIZE_OLDDRM, "TEX/tex-4", 4 );
- ALLOC_STATE( tex[5], tex, TEX_STATE_SIZE_OLDDRM, "TEX/tex-5", 5 );
- ALLOC_STATE( atf, never, ATF_STATE_SIZE, "TF/tfactor", 0 );
- ALLOC_STATE( afs[0], never, AFS_STATE_SIZE, "AFS/afsinst-0", 0 );
- ALLOC_STATE( afs[1], never, AFS_STATE_SIZE, "AFS/afsinst-1", 1 );
- }
- if (rmesa->r200Screen->drmSupportsCubeMapsR200) {
+ /* polygon stipple is done with irq for non-kms */
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ ALLOC_STATE( stp, always, STP_STATE_SIZE, "STP/stp", 0 );
+ }
+
+ for (i = 0; i < 6; i++)
+ if (rmesa->radeon.radeonScreen->kernel_mm)
+ rmesa->hw.tex[i].emit = tex_emit_mm;
+ else
+ rmesa->hw.tex[i].emit = tex_emit;
+ if (rmesa->radeon.radeonScreen->drmSupportsCubeMapsR200) {
ALLOC_STATE( cube[0], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-0", 0 );
ALLOC_STATE( cube[1], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-1", 1 );
ALLOC_STATE( cube[2], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-2", 2 );
ALLOC_STATE( cube[3], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-3", 3 );
ALLOC_STATE( cube[4], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-4", 4 );
ALLOC_STATE( cube[5], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-5", 5 );
+ for (i = 0; i < 6; i++)
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ rmesa->hw.cube[i].emit = cube_emit_cs;
+ rmesa->hw.cube[i].check = check_tex_cube_cs;
+ } else
+ rmesa->hw.cube[i].emit = cube_emit;
}
else {
ALLOC_STATE( cube[0], never, CUBE_STATE_SIZE, "CUBE/tex-0", 0 );
@@ -337,12 +917,20 @@ void r200InitState( r200ContextPtr rmesa )
ALLOC_STATE( cube[4], never, CUBE_STATE_SIZE, "CUBE/tex-4", 4 );
ALLOC_STATE( cube[5], never, CUBE_STATE_SIZE, "CUBE/tex-5", 5 );
}
- if (rmesa->r200Screen->drmSupportsVertexProgram) {
+
+ if (rmesa->radeon.radeonScreen->drmSupportsVertexProgram) {
ALLOC_STATE( pvs, tcl_vp, PVS_STATE_SIZE, "PVS/pvscntl", 0 );
- ALLOC_STATE( vpi[0], tcl_vp, VPI_STATE_SIZE, "VP/vertexprog-0", 0 );
- ALLOC_STATE( vpi[1], tcl_vp_size, VPI_STATE_SIZE, "VP/vertexprog-1", 1 );
- ALLOC_STATE( vpp[0], tcl_vp, VPP_STATE_SIZE, "VPP/vertexparam-0", 0 );
- ALLOC_STATE( vpp[1], tcl_vpp_size, VPP_STATE_SIZE, "VPP/vertexparam-1", 1 );
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ ALLOC_STATE( vpi[0], tcl_vp_add4, VPI_STATE_SIZE, "VP/vertexprog-0", 0 );
+ ALLOC_STATE( vpi[1], tcl_vp_size_add4, VPI_STATE_SIZE, "VP/vertexprog-1", 1 );
+ ALLOC_STATE( vpp[0], tcl_vp_add4, VPP_STATE_SIZE, "VPP/vertexparam-0", 0 );
+ ALLOC_STATE( vpp[1], tcl_vpp_size_add4, VPP_STATE_SIZE, "VPP/vertexparam-1", 1 );
+ } else {
+ ALLOC_STATE( vpi[0], tcl_vp, VPI_STATE_SIZE, "VP/vertexprog-0", 0 );
+ ALLOC_STATE( vpi[1], tcl_vp_size, VPI_STATE_SIZE, "VP/vertexprog-1", 1 );
+ ALLOC_STATE( vpp[0], tcl_vp, VPP_STATE_SIZE, "VPP/vertexparam-0", 0 );
+ ALLOC_STATE( vpp[1], tcl_vpp_size, VPP_STATE_SIZE, "VPP/vertexparam-1", 1 );
+ }
}
else {
ALLOC_STATE( pvs, never, PVS_STATE_SIZE, "PVS/pvscntl", 0 );
@@ -355,50 +943,87 @@ void r200InitState( r200ContextPtr rmesa )
ALLOC_STATE( tcl, tcl_or_vp, TCL_STATE_SIZE, "TCL/tcl", 0 );
ALLOC_STATE( msl, tcl, MSL_STATE_SIZE, "MSL/matrix-select", 0 );
ALLOC_STATE( tcg, tcl, TCG_STATE_SIZE, "TCG/texcoordgen", 0 );
- ALLOC_STATE( mtl[0], tcl_lighting, MTL_STATE_SIZE, "MTL0/material0", 0 );
- ALLOC_STATE( mtl[1], tcl_lighting, MTL_STATE_SIZE, "MTL1/material1", 1 );
- ALLOC_STATE( grd, tcl_or_vp, GRD_STATE_SIZE, "GRD/guard-band", 0 );
- ALLOC_STATE( fog, tcl_fog, FOG_STATE_SIZE, "FOG/fog", 0 );
- ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 0 );
- ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 0 );
- ALLOC_STATE( mat[R200_MTX_MV], tcl, MAT_STATE_SIZE, "MAT/modelview", 0 );
- ALLOC_STATE( mat[R200_MTX_IMV], tcl, MAT_STATE_SIZE, "MAT/it-modelview", 0 );
- ALLOC_STATE( mat[R200_MTX_MVP], tcl, MAT_STATE_SIZE, "MAT/modelproject", 0 );
- ALLOC_STATE( mat[R200_MTX_TEX0], tcl_tex, MAT_STATE_SIZE, "MAT/texmat0", 0 );
- ALLOC_STATE( mat[R200_MTX_TEX1], tcl_tex, MAT_STATE_SIZE, "MAT/texmat1", 1 );
- ALLOC_STATE( mat[R200_MTX_TEX2], tcl_tex, MAT_STATE_SIZE, "MAT/texmat2", 2 );
- ALLOC_STATE( mat[R200_MTX_TEX3], tcl_tex, MAT_STATE_SIZE, "MAT/texmat3", 3 );
- ALLOC_STATE( mat[R200_MTX_TEX4], tcl_tex, MAT_STATE_SIZE, "MAT/texmat4", 4 );
- ALLOC_STATE( mat[R200_MTX_TEX5], tcl_tex, MAT_STATE_SIZE, "MAT/texmat5", 5 );
- ALLOC_STATE( ucp[0], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-0", 0 );
- ALLOC_STATE( ucp[1], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
- ALLOC_STATE( ucp[2], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-2", 2 );
- ALLOC_STATE( ucp[3], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-3", 3 );
- ALLOC_STATE( ucp[4], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-4", 4 );
- ALLOC_STATE( ucp[5], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-5", 5 );
- ALLOC_STATE( lit[0], tcl_light, LIT_STATE_SIZE, "LIT/light-0", 0 );
- ALLOC_STATE( lit[1], tcl_light, LIT_STATE_SIZE, "LIT/light-1", 1 );
- ALLOC_STATE( lit[2], tcl_light, LIT_STATE_SIZE, "LIT/light-2", 2 );
- ALLOC_STATE( lit[3], tcl_light, LIT_STATE_SIZE, "LIT/light-3", 3 );
- ALLOC_STATE( lit[4], tcl_light, LIT_STATE_SIZE, "LIT/light-4", 4 );
- ALLOC_STATE( lit[5], tcl_light, LIT_STATE_SIZE, "LIT/light-5", 5 );
- ALLOC_STATE( lit[6], tcl_light, LIT_STATE_SIZE, "LIT/light-6", 6 );
- ALLOC_STATE( lit[7], tcl_light, LIT_STATE_SIZE, "LIT/light-7", 7 );
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ ALLOC_STATE( mtl[0], tcl_lighting_add6, MTL_STATE_SIZE, "MTL0/material0", 0 );
+ ALLOC_STATE( mtl[1], tcl_lighting_add6, MTL_STATE_SIZE, "MTL1/material1", 1 );
+ ALLOC_STATE( grd, tcl_or_vp_add2, GRD_STATE_SIZE, "GRD/guard-band", 0 );
+ ALLOC_STATE( fog, tcl_fog_add4, FOG_STATE_SIZE, "FOG/fog", 0 );
+ ALLOC_STATE( glt, tcl_lighting_add4, GLT_STATE_SIZE, "GLT/light-global", 0 );
+ ALLOC_STATE( eye, tcl_lighting_add4, EYE_STATE_SIZE, "EYE/eye-vector", 0 );
+ ALLOC_STATE( mat[R200_MTX_MV], tcl_add4, MAT_STATE_SIZE, "MAT/modelview", 0 );
+ ALLOC_STATE( mat[R200_MTX_IMV], tcl_add4, MAT_STATE_SIZE, "MAT/it-modelview", 0 );
+ ALLOC_STATE( mat[R200_MTX_MVP], tcl_add4, MAT_STATE_SIZE, "MAT/modelproject", 0 );
+ ALLOC_STATE( mat[R200_MTX_TEX0], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat0", 0 );
+ ALLOC_STATE( mat[R200_MTX_TEX1], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat1", 1 );
+ ALLOC_STATE( mat[R200_MTX_TEX2], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat2", 2 );
+ ALLOC_STATE( mat[R200_MTX_TEX3], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat3", 3 );
+ ALLOC_STATE( mat[R200_MTX_TEX4], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat4", 4 );
+ ALLOC_STATE( mat[R200_MTX_TEX5], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat5", 5 );
+ ALLOC_STATE( ucp[0], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-0", 0 );
+ ALLOC_STATE( ucp[1], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
+ ALLOC_STATE( ucp[2], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-2", 2 );
+ ALLOC_STATE( ucp[3], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-3", 3 );
+ ALLOC_STATE( ucp[4], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-4", 4 );
+ ALLOC_STATE( ucp[5], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-5", 5 );
+ ALLOC_STATE( lit[0], tcl_light_add8, LIT_STATE_SIZE, "LIT/light-0", 0 );
+ ALLOC_STATE( lit[1], tcl_light_add8, LIT_STATE_SIZE, "LIT/light-1", 1 );
+ ALLOC_STATE( lit[2], tcl_light_add8, LIT_STATE_SIZE, "LIT/light-2", 2 );
+ ALLOC_STATE( lit[3], tcl_light_add8, LIT_STATE_SIZE, "LIT/light-3", 3 );
+ ALLOC_STATE( lit[4], tcl_light_add8, LIT_STATE_SIZE, "LIT/light-4", 4 );
+ ALLOC_STATE( lit[5], tcl_light_add8, LIT_STATE_SIZE, "LIT/light-5", 5 );
+ ALLOC_STATE( lit[6], tcl_light_add8, LIT_STATE_SIZE, "LIT/light-6", 6 );
+ ALLOC_STATE( lit[7], tcl_light_add8, LIT_STATE_SIZE, "LIT/light-7", 7 );
+ ALLOC_STATE( sci, rrb, SCI_STATE_SIZE, "SCI/scissor", 0 );
+ } else {
+ ALLOC_STATE( mtl[0], tcl_lighting, MTL_STATE_SIZE, "MTL0/material0", 0 );
+ ALLOC_STATE( mtl[1], tcl_lighting, MTL_STATE_SIZE, "MTL1/material1", 1 );
+ ALLOC_STATE( grd, tcl_or_vp, GRD_STATE_SIZE, "GRD/guard-band", 0 );
+ ALLOC_STATE( fog, tcl_fog, FOG_STATE_SIZE, "FOG/fog", 0 );
+ ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 0 );
+ ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 0 );
+ ALLOC_STATE( mat[R200_MTX_MV], tcl, MAT_STATE_SIZE, "MAT/modelview", 0 );
+ ALLOC_STATE( mat[R200_MTX_IMV], tcl, MAT_STATE_SIZE, "MAT/it-modelview", 0 );
+ ALLOC_STATE( mat[R200_MTX_MVP], tcl, MAT_STATE_SIZE, "MAT/modelproject", 0 );
+ ALLOC_STATE( mat[R200_MTX_TEX0], tcl_tex, MAT_STATE_SIZE, "MAT/texmat0", 0 );
+ ALLOC_STATE( mat[R200_MTX_TEX1], tcl_tex, MAT_STATE_SIZE, "MAT/texmat1", 1 );
+ ALLOC_STATE( mat[R200_MTX_TEX2], tcl_tex, MAT_STATE_SIZE, "MAT/texmat2", 2 );
+ ALLOC_STATE( mat[R200_MTX_TEX3], tcl_tex, MAT_STATE_SIZE, "MAT/texmat3", 3 );
+ ALLOC_STATE( mat[R200_MTX_TEX4], tcl_tex, MAT_STATE_SIZE, "MAT/texmat4", 4 );
+ ALLOC_STATE( mat[R200_MTX_TEX5], tcl_tex, MAT_STATE_SIZE, "MAT/texmat5", 5 );
+ ALLOC_STATE( ucp[0], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-0", 0 );
+ ALLOC_STATE( ucp[1], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
+ ALLOC_STATE( ucp[2], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-2", 2 );
+ ALLOC_STATE( ucp[3], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-3", 3 );
+ ALLOC_STATE( ucp[4], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-4", 4 );
+ ALLOC_STATE( ucp[5], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-5", 5 );
+ ALLOC_STATE( lit[0], tcl_light, LIT_STATE_SIZE, "LIT/light-0", 0 );
+ ALLOC_STATE( lit[1], tcl_light, LIT_STATE_SIZE, "LIT/light-1", 1 );
+ ALLOC_STATE( lit[2], tcl_light, LIT_STATE_SIZE, "LIT/light-2", 2 );
+ ALLOC_STATE( lit[3], tcl_light, LIT_STATE_SIZE, "LIT/light-3", 3 );
+ ALLOC_STATE( lit[4], tcl_light, LIT_STATE_SIZE, "LIT/light-4", 4 );
+ ALLOC_STATE( lit[5], tcl_light, LIT_STATE_SIZE, "LIT/light-5", 5 );
+ ALLOC_STATE( lit[6], tcl_light, LIT_STATE_SIZE, "LIT/light-6", 6 );
+ ALLOC_STATE( lit[7], tcl_light, LIT_STATE_SIZE, "LIT/light-7", 7 );
+ ALLOC_STATE( sci, never, SCI_STATE_SIZE, "SCI/scissor", 0 );
+ }
ALLOC_STATE( pix[0], pix_zero, PIX_STATE_SIZE, "PIX/pixstage-0", 0 );
ALLOC_STATE( pix[1], texenv, PIX_STATE_SIZE, "PIX/pixstage-1", 1 );
ALLOC_STATE( pix[2], texenv, PIX_STATE_SIZE, "PIX/pixstage-2", 2 );
ALLOC_STATE( pix[3], texenv, PIX_STATE_SIZE, "PIX/pixstage-3", 3 );
ALLOC_STATE( pix[4], texenv, PIX_STATE_SIZE, "PIX/pixstage-4", 4 );
ALLOC_STATE( pix[5], texenv, PIX_STATE_SIZE, "PIX/pixstage-5", 5 );
- if (rmesa->r200Screen->drmSupportsTriPerf) {
+ if (rmesa->radeon.radeonScreen->drmSupportsTriPerf) {
ALLOC_STATE( prf, always, PRF_STATE_SIZE, "PRF/performance-tri", 0 );
}
else {
ALLOC_STATE( prf, never, PRF_STATE_SIZE, "PRF/performance-tri", 0 );
}
- if (rmesa->r200Screen->drmSupportsPointSprites) {
+ if (rmesa->radeon.radeonScreen->drmSupportsPointSprites) {
ALLOC_STATE( spr, always, SPR_STATE_SIZE, "SPR/pointsprite", 0 );
- ALLOC_STATE( ptp, tcl, PTP_STATE_SIZE, "PTP/pointparams", 0 );
+ if (rmesa->radeon.radeonScreen->kernel_mm)
+ ALLOC_STATE( ptp, tcl_add8, PTP_STATE_SIZE, "PTP/pointparams", 0 );
+ else
+ ALLOC_STATE( ptp, tcl, PTP_STATE_SIZE, "PTP/pointparams", 0 );
}
else {
ALLOC_STATE (spr, never, SPR_STATE_SIZE, "SPR/pointsprite", 0 );
@@ -409,87 +1034,125 @@ void r200InitState( r200ContextPtr rmesa )
/* Fill in the packet headers:
*/
- rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(RADEON_EMIT_PP_MISC);
- rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(RADEON_EMIT_PP_CNTL);
- rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(RADEON_EMIT_RB3D_COLORPITCH);
- if (rmesa->r200Screen->drmSupportsBlendColor)
- rmesa->hw.ctx.cmd[CTX_CMD_3] = cmdpkt(R200_EMIT_RB3D_BLENDCOLOR);
- rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(RADEON_EMIT_RE_LINE_PATTERN);
- rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(RADEON_EMIT_SE_LINE_WIDTH);
- rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(RADEON_EMIT_RB3D_STENCILREFMASK);
- rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(RADEON_EMIT_SE_VPORT_XSCALE);
- rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(RADEON_EMIT_SE_CNTL);
- rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(RADEON_EMIT_RE_MISC);
- rmesa->hw.cst.cmd[CST_CMD_0] = cmdpkt(R200_EMIT_PP_CNTL_X);
- rmesa->hw.cst.cmd[CST_CMD_1] = cmdpkt(R200_EMIT_RB3D_DEPTHXY_OFFSET);
- rmesa->hw.cst.cmd[CST_CMD_2] = cmdpkt(R200_EMIT_RE_AUX_SCISSOR_CNTL);
- rmesa->hw.cst.cmd[CST_CMD_3] = cmdpkt(R200_EMIT_RE_SCISSOR_TL_0);
- rmesa->hw.cst.cmd[CST_CMD_4] = cmdpkt(R200_EMIT_SE_VAP_CNTL_STATUS);
- rmesa->hw.cst.cmd[CST_CMD_5] = cmdpkt(R200_EMIT_RE_POINTSIZE);
- rmesa->hw.cst.cmd[CST_CMD_6] = cmdpkt(R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0);
- rmesa->hw.tam.cmd[TAM_CMD_0] = cmdpkt(R200_EMIT_PP_TAM_DEBUG3);
- rmesa->hw.tf.cmd[TF_CMD_0] = cmdpkt(R200_EMIT_TFACTOR_0);
- if (rmesa->r200Screen->drmSupportsFragShader) {
- rmesa->hw.atf.cmd[ATF_CMD_0] = cmdpkt(R200_EMIT_ATF_TFACTOR);
- rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCTLALL_0);
- rmesa->hw.tex[0].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_0);
- rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCTLALL_1);
- rmesa->hw.tex[1].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_1);
- rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCTLALL_2);
- rmesa->hw.tex[2].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_2);
- rmesa->hw.tex[3].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCTLALL_3);
- rmesa->hw.tex[3].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_3);
- rmesa->hw.tex[4].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCTLALL_4);
- rmesa->hw.tex[4].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_4);
- rmesa->hw.tex[5].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCTLALL_5);
- rmesa->hw.tex[5].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_5);
+ rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_MISC);
+ rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CNTL);
+ rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(rmesa, RADEON_EMIT_RB3D_COLORPITCH);
+ if (rmesa->radeon.radeonScreen->drmSupportsBlendColor)
+ rmesa->hw.ctx.cmd[CTX_CMD_3] = cmdpkt(rmesa, R200_EMIT_RB3D_BLENDCOLOR);
+ rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_LINE_PATTERN);
+ rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_SE_LINE_WIDTH);
+ rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RB3D_STENCILREFMASK);
+ rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_VPORT_XSCALE);
+ rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_CNTL);
+ rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_MISC);
+ rmesa->hw.cst.cmd[CST_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CNTL_X);
+ rmesa->hw.cst.cmd[CST_CMD_1] = cmdpkt(rmesa, R200_EMIT_RB3D_DEPTHXY_OFFSET);
+ rmesa->hw.cst.cmd[CST_CMD_2] = cmdpkt(rmesa, R200_EMIT_RE_AUX_SCISSOR_CNTL);
+ rmesa->hw.cst.cmd[CST_CMD_3] = cmdpkt(rmesa, R200_EMIT_RE_SCISSOR_TL_0);
+ rmesa->hw.cst.cmd[CST_CMD_4] = cmdpkt(rmesa, R200_EMIT_SE_VAP_CNTL_STATUS);
+ rmesa->hw.cst.cmd[CST_CMD_5] = cmdpkt(rmesa, R200_EMIT_RE_POINTSIZE);
+ rmesa->hw.cst.cmd[CST_CMD_6] = cmdpkt(rmesa, R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0);
+ rmesa->hw.tam.cmd[TAM_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TAM_DEBUG3);
+ rmesa->hw.tf.cmd[TF_CMD_0] = cmdpkt(rmesa, R200_EMIT_TFACTOR_0);
+ if (rmesa->radeon.radeonScreen->drmSupportsFragShader) {
+ rmesa->hw.atf.cmd[ATF_CMD_0] = cmdpkt(rmesa, R200_EMIT_ATF_TFACTOR);
+ rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_0);
+ rmesa->hw.tex[0].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_0);
+ rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_1);
+ rmesa->hw.tex[1].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_1);
+ rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_2);
+ rmesa->hw.tex[2].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_2);
+ rmesa->hw.tex[3].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_3);
+ rmesa->hw.tex[3].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_3);
+ rmesa->hw.tex[4].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_4);
+ rmesa->hw.tex[4].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_4);
+ rmesa->hw.tex[5].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_5);
+ rmesa->hw.tex[5].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_5);
} else {
- rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_0);
- rmesa->hw.tex[0].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_0);
- rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_1);
- rmesa->hw.tex[1].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_1);
- rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_2);
- rmesa->hw.tex[2].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_2);
- rmesa->hw.tex[3].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_3);
- rmesa->hw.tex[3].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_3);
- rmesa->hw.tex[4].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_4);
- rmesa->hw.tex[4].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_4);
- rmesa->hw.tex[5].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_5);
- rmesa->hw.tex[5].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(R200_EMIT_PP_TXOFFSET_5);
- }
- rmesa->hw.afs[0].cmd[AFS_CMD_0] = cmdpkt(R200_EMIT_PP_AFS_0);
- rmesa->hw.afs[1].cmd[AFS_CMD_0] = cmdpkt(R200_EMIT_PP_AFS_1);
- rmesa->hw.pvs.cmd[PVS_CMD_0] = cmdpkt(R200_EMIT_VAP_PVS_CNTL);
- rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_0);
- rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_0);
- rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_1);
- rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_1);
- rmesa->hw.cube[2].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_2);
- rmesa->hw.cube[2].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_2);
- rmesa->hw.cube[3].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_3);
- rmesa->hw.cube[3].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_3);
- rmesa->hw.cube[4].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_4);
- rmesa->hw.cube[4].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_4);
- rmesa->hw.cube[5].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_5);
- rmesa->hw.cube[5].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_5);
- rmesa->hw.pix[0].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_0);
- rmesa->hw.pix[1].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_1);
- rmesa->hw.pix[2].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_2);
- rmesa->hw.pix[3].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_3);
- rmesa->hw.pix[4].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_4);
- rmesa->hw.pix[5].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_5);
- rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR);
- rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(R200_EMIT_TCL_LIGHT_MODEL_CTL_0);
- rmesa->hw.tcl.cmd[TCL_CMD_1] = cmdpkt(R200_EMIT_TCL_UCP_VERT_BLEND_CTL);
- rmesa->hw.tcg.cmd[TCG_CMD_0] = cmdpkt(R200_EMIT_TEX_PROC_CTL_2);
- rmesa->hw.msl.cmd[MSL_CMD_0] = cmdpkt(R200_EMIT_MATRIX_SELECT_0);
- rmesa->hw.vap.cmd[VAP_CMD_0] = cmdpkt(R200_EMIT_VAP_CTL);
- rmesa->hw.vtx.cmd[VTX_CMD_0] = cmdpkt(R200_EMIT_VTX_FMT_0);
- rmesa->hw.vtx.cmd[VTX_CMD_1] = cmdpkt(R200_EMIT_OUTPUT_VTX_COMP_SEL);
- rmesa->hw.vtx.cmd[VTX_CMD_2] = cmdpkt(R200_EMIT_SE_VTX_STATE_CNTL);
- rmesa->hw.vte.cmd[VTE_CMD_0] = cmdpkt(R200_EMIT_VTE_CNTL);
- rmesa->hw.prf.cmd[PRF_CMD_0] = cmdpkt(R200_EMIT_PP_TRI_PERF_CNTL);
- rmesa->hw.spr.cmd[SPR_CMD_0] = cmdpkt(R200_EMIT_TCL_POINT_SPRITE_CNTL);
+ rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXFILTER_0);
+ rmesa->hw.tex[0].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_0);
+ rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXFILTER_1);
+ rmesa->hw.tex[1].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_1);
+ rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXFILTER_2);
+ rmesa->hw.tex[2].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_2);
+ rmesa->hw.tex[3].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXFILTER_3);
+ rmesa->hw.tex[3].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_3);
+ rmesa->hw.tex[4].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXFILTER_4);
+ rmesa->hw.tex[4].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_4);
+ rmesa->hw.tex[5].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXFILTER_5);
+ rmesa->hw.tex[5].cmd[TEX_CMD_1_OLDDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_5);
+ }
+ rmesa->hw.afs[0].cmd[AFS_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_AFS_0);
+ rmesa->hw.afs[1].cmd[AFS_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_AFS_1);
+ rmesa->hw.pvs.cmd[PVS_CMD_0] = cmdpkt(rmesa, R200_EMIT_VAP_PVS_CNTL);
+ rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_0);
+ rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_0);
+ rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_1);
+ rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_1);
+ rmesa->hw.cube[2].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_2);
+ rmesa->hw.cube[2].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_2);
+ rmesa->hw.cube[3].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_3);
+ rmesa->hw.cube[3].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_3);
+ rmesa->hw.cube[4].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_4);
+ rmesa->hw.cube[4].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_4);
+ rmesa->hw.cube[5].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_5);
+ rmesa->hw.cube[5].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_5);
+ rmesa->hw.pix[0].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_0);
+ rmesa->hw.pix[1].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_1);
+ rmesa->hw.pix[2].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_2);
+ rmesa->hw.pix[3].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_3);
+ rmesa->hw.pix[4].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_4);
+ rmesa->hw.pix[5].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_5);
+ rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_ZBIAS_FACTOR);
+ rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(rmesa, R200_EMIT_TCL_LIGHT_MODEL_CTL_0);
+ rmesa->hw.tcl.cmd[TCL_CMD_1] = cmdpkt(rmesa, R200_EMIT_TCL_UCP_VERT_BLEND_CTL);
+ rmesa->hw.tcg.cmd[TCG_CMD_0] = cmdpkt(rmesa, R200_EMIT_TEX_PROC_CTL_2);
+ rmesa->hw.msl.cmd[MSL_CMD_0] = cmdpkt(rmesa, R200_EMIT_MATRIX_SELECT_0);
+ rmesa->hw.vap.cmd[VAP_CMD_0] = cmdpkt(rmesa, R200_EMIT_VAP_CTL);
+ rmesa->hw.vtx.cmd[VTX_CMD_0] = cmdpkt(rmesa, R200_EMIT_VTX_FMT_0);
+ rmesa->hw.vtx.cmd[VTX_CMD_1] = cmdpkt(rmesa, R200_EMIT_OUTPUT_VTX_COMP_SEL);
+ rmesa->hw.vtx.cmd[VTX_CMD_2] = cmdpkt(rmesa, R200_EMIT_SE_VTX_STATE_CNTL);
+ rmesa->hw.vte.cmd[VTE_CMD_0] = cmdpkt(rmesa, R200_EMIT_VTE_CNTL);
+ rmesa->hw.prf.cmd[PRF_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TRI_PERF_CNTL);
+ rmesa->hw.spr.cmd[SPR_CMD_0] = cmdpkt(rmesa, R200_EMIT_TCL_POINT_SPRITE_CNTL);
+
+ rmesa->hw.sci.cmd[SCI_CMD_0] = CP_PACKET0(R200_RE_AUX_SCISSOR_CNTL, 0);
+ rmesa->hw.sci.cmd[SCI_CMD_1] = CP_PACKET0(R200_RE_TOP_LEFT, 0);
+ rmesa->hw.sci.cmd[SCI_CMD_2] = CP_PACKET0(R200_RE_WIDTH_HEIGHT, 0);
+
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+
+ rmesa->hw.stp.cmd[STP_CMD_0] = CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0);
+ rmesa->hw.stp.cmd[STP_DATA_0] = 0;
+ rmesa->hw.stp.cmd[STP_CMD_1] = CP_PACKET0_ONE(RADEON_RE_STIPPLE_DATA, 31);
+
+ rmesa->hw.mtl[0].emit = mtl_emit;
+ rmesa->hw.mtl[1].emit = mtl_emit;
+
+ rmesa->hw.vpi[0].emit = veclinear_emit;
+ rmesa->hw.vpi[1].emit = veclinear_emit;
+ rmesa->hw.vpp[0].emit = veclinear_emit;
+ rmesa->hw.vpp[1].emit = veclinear_emit;
+
+ rmesa->hw.grd.emit = scl_emit;
+ rmesa->hw.fog.emit = vec_emit;
+ rmesa->hw.glt.emit = vec_emit;
+ rmesa->hw.eye.emit = vec_emit;
+
+ for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++)
+ rmesa->hw.mat[i].emit = vec_emit;
+
+ for (i = 0; i < 8; i++)
+ rmesa->hw.lit[i].emit = lit_emit;
+
+ for (i = 0; i < 6; i++)
+ rmesa->hw.ucp[i].emit = vec_emit;
+
+ rmesa->hw.ptp.emit = ptp_emit;
+ }
+
+
+
rmesa->hw.mtl[0].cmd[MTL_CMD_0] =
cmdvec( R200_VS_MAT_0_EMISS, 1, 16 );
rmesa->hw.mtl[0].cmd[MTL_CMD_1] =
@@ -567,7 +1230,7 @@ void r200InitState( r200ContextPtr rmesa )
(R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
(R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT));
- if (rmesa->r200Screen->drmSupportsBlendColor) {
+ if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) {
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = 0x00000000;
rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP |
(R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
@@ -578,18 +1241,17 @@ void r200InitState( r200ContextPtr rmesa )
}
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] =
- rmesa->r200Screen->depthOffset + rmesa->r200Screen->fbLocation;
+ rmesa->radeon.radeonScreen->depthOffset + rmesa->radeon.radeonScreen->fbLocation;
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] =
- ((rmesa->r200Screen->depthPitch &
+ ((rmesa->radeon.radeonScreen->depthPitch &
R200_DEPTHPITCH_MASK) |
R200_DEPTH_ENDIAN_NO_SWAP);
if (rmesa->using_hyperz)
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] |= R200_DEPTH_HYPERZ;
- rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (depth_fmt |
- R200_Z_TEST_LESS |
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (R200_Z_TEST_LESS |
R200_STENCIL_TEST_ALWAYS |
R200_STENCIL_FAIL_KEEP |
R200_STENCIL_ZPASS_KEEP |
@@ -599,15 +1261,14 @@ void r200InitState( r200ContextPtr rmesa )
if (rmesa->using_hyperz) {
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_COMPRESSION_ENABLE |
R200_Z_DECOMPRESSION_ENABLE;
-/* if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200)
+/* if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200)
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_HIERARCHY_ENABLE;*/
}
rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (R200_ANTI_ALIAS_NONE
| R200_TEX_BLEND_0_ENABLE);
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = color_fmt;
- switch ( driQueryOptioni( &rmesa->optionCache, "dither_mode" ) ) {
+ switch ( driQueryOptioni( &rmesa->radeon.optionCache, "dither_mode" ) ) {
case DRI_CONF_DITHER_XERRORDIFFRESET:
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_INIT;
break;
@@ -615,41 +1276,19 @@ void r200InitState( r200ContextPtr rmesa )
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_SCALE_DITHER_ENABLE;
break;
}
- if ( driQueryOptioni( &rmesa->optionCache, "round_mode" ) ==
+ if ( driQueryOptioni( &rmesa->radeon.optionCache, "round_mode" ) ==
DRI_CONF_ROUND_ROUND )
- rmesa->state.color.roundEnable = R200_ROUND_ENABLE;
+ rmesa->radeon.state.color.roundEnable = R200_ROUND_ENABLE;
else
- rmesa->state.color.roundEnable = 0;
- if ( driQueryOptioni (&rmesa->optionCache, "color_reduction" ) ==
+ rmesa->radeon.state.color.roundEnable = 0;
+ if ( driQueryOptioni (&rmesa->radeon.optionCache, "color_reduction" ) ==
DRI_CONF_COLOR_REDUCTION_DITHER )
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE;
else
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
-
-#if 000
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
- rmesa->r200Screen->fbLocation)
- & R200_COLOROFFSET_MASK);
-
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((rmesa->state.color.drawPitch &
- R200_COLORPITCH_MASK) |
- R200_COLOR_ENDIAN_NO_SWAP);
-#else
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((drawOffset +
- rmesa->r200Screen->fbLocation)
- & R200_COLOROFFSET_MASK);
-
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((drawPitch &
- R200_COLORPITCH_MASK) |
- R200_COLOR_ENDIAN_NO_SWAP);
-#endif
- /* (fixed size) sarea is initialized to zero afaics so can omit version check. Phew! */
- if (rmesa->sarea->tiling_enabled) {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
- }
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;
rmesa->hw.prf.cmd[PRF_PP_TRI_PERF] = R200_TRI_CUTOFF_MASK - R200_TRI_CUTOFF_MASK *
- driQueryOptionf (&rmesa->optionCache,"texture_blend_quality");
+ driQueryOptionf (&rmesa->radeon.optionCache,"texture_blend_quality");
rmesa->hw.prf.cmd[PRF_PP_PERF_CNTL] = 0;
rmesa->hw.set.cmd[SET_SE_CNTL] = (R200_FFACE_CULL_CCW |
@@ -704,7 +1343,7 @@ void r200InitState( r200ContextPtr rmesa )
R200_VC_NO_SWAP;
#endif
- if (!(rmesa->r200Screen->chip_flags & RADEON_CHIPSET_TCL)) {
+ if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
/* Bypass TCL */
rmesa->hw.cst.cmd[CST_SE_VAP_CNTL_STATUS] |= (1<<8);
}
@@ -743,28 +1382,28 @@ void r200InitState( r200ContextPtr rmesa )
rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT_X] =
(/* R200_TEXCOORD_PROJ | */
0x100000); /* Small default bias */
- if (rmesa->r200Screen->drmSupportsFragShader) {
+ if (rmesa->radeon.radeonScreen->drmSupportsFragShader) {
rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET_NEWDRM] =
- rmesa->r200Screen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.tex[i].cmd[TEX_PP_CUBIC_FACES] = 0;
rmesa->hw.tex[i].cmd[TEX_PP_TXMULTI_CTL] = 0;
}
else {
rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET_OLDDRM] =
- rmesa->r200Screen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
}
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_FACES] = 0;
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F1] =
- rmesa->r200Screen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F2] =
- rmesa->r200Screen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F3] =
- rmesa->r200Screen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F4] =
- rmesa->r200Screen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F5] =
- rmesa->r200Screen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.pix[i].cmd[PIX_PP_TXCBLEND] =
(R200_TXC_ARG_A_ZERO |
@@ -967,5 +1606,13 @@ void r200InitState( r200ContextPtr rmesa )
r200LightingSpaceChange( ctx );
- rmesa->hw.all_dirty = GL_TRUE;
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ radeon_init_query_stateobj(&rmesa->radeon, R200_QUERYOBJ_CMDSIZE);
+ rmesa->radeon.query.queryobj.cmd[R200_QUERYOBJ_CMD_0] = CP_PACKET0(RADEON_RB3D_ZPASS_DATA, 0);
+ rmesa->radeon.query.queryobj.cmd[R200_QUERYOBJ_DATA_0] = 0;
+ }
+
+ rmesa->radeon.hw.all_dirty = GL_TRUE;
+
+ rcommonInitCmdBuf(&rmesa->radeon);
}
diff --git a/src/mesa/drivers/dri/r200/r200_swtcl.c b/src/mesa/drivers/dri/r200/r200_swtcl.c
index b25f028244..240fb45078 100644
--- a/src/mesa/drivers/dri/r200/r200_swtcl.c
+++ b/src/mesa/drivers/dri/r200/r200_swtcl.c
@@ -39,6 +39,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/image.h"
#include "main/imports.h"
#include "main/macros.h"
+#include "main/simple_list.h"
#include "swrast/s_context.h"
#include "swrast/s_fog.h"
@@ -55,27 +56,24 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r200_tcl.h"
-static void flush_last_swtcl_prim( r200ContextPtr rmesa );
-
-
/***********************************************************************
- * Initialization
+ * Initialization
***********************************************************************/
#define EMIT_ATTR( ATTR, STYLE, F0 ) \
do { \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = (ATTR); \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = (STYLE); \
- rmesa->swtcl.vertex_attr_count++; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = (ATTR); \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = (STYLE); \
+ rmesa->radeon.swtcl.vertex_attr_count++; \
fmt_0 |= F0; \
} while (0)
#define EMIT_PAD( N ) \
do { \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = 0; \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = EMIT_PAD; \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].offset = (N); \
- rmesa->swtcl.vertex_attr_count++; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = 0; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = EMIT_PAD; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].offset = (N); \
+ rmesa->radeon.swtcl.vertex_attr_count++; \
} while (0)
static void r200SetVertexFormat( GLcontext *ctx )
@@ -100,7 +98,7 @@ static void r200SetVertexFormat( GLcontext *ctx )
}
assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL );
- rmesa->swtcl.vertex_attr_count = 0;
+ rmesa->radeon.swtcl.vertex_attr_count = 0;
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
* build up a hardware vertex.
@@ -121,7 +119,7 @@ static void r200SetVertexFormat( GLcontext *ctx )
}
rmesa->swtcl.coloroffset = offset;
-#if MESA_LITTLE_ENDIAN
+#if MESA_LITTLE_ENDIAN
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
#else
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
@@ -132,7 +130,7 @@ static void r200SetVertexFormat( GLcontext *ctx )
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
-#if MESA_LITTLE_ENDIAN
+#if MESA_LITTLE_ENDIAN
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
rmesa->swtcl.specoffset = offset;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
@@ -185,7 +183,7 @@ static void r200SetVertexFormat( GLcontext *ctx )
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA;
}
- if (!RENDERINPUTS_EQUAL( rmesa->tnl_index_bitset, index_bitset ) ||
+ if (!RENDERINPUTS_EQUAL( rmesa->radeon.tnl_index_bitset, index_bitset ) ||
(rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) ||
(rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
R200_NEWPRIM(rmesa);
@@ -193,26 +191,42 @@ static void r200SetVertexFormat( GLcontext *ctx )
rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
- rmesa->swtcl.vertex_size =
+ rmesa->radeon.swtcl.vertex_size =
_tnl_install_attrs( ctx,
- rmesa->swtcl.vertex_attrs,
- rmesa->swtcl.vertex_attr_count,
+ rmesa->radeon.swtcl.vertex_attrs,
+ rmesa->radeon.swtcl.vertex_attr_count,
NULL, 0 );
- rmesa->swtcl.vertex_size /= 4;
- RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset );
+ rmesa->radeon.swtcl.vertex_size /= 4;
+ RENDERINPUTS_COPY( rmesa->radeon.tnl_index_bitset, index_bitset );
+ }
+}
+
+static void r200_predict_emit_size( r200ContextPtr rmesa )
+{
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s\n", __func__);
+ const int vertex_array_size = 7;
+ const int prim_size = 3;
+ if (!rmesa->radeon.swtcl.emit_prediction) {
+ const int state_size = radeonCountStateEmitSize(&rmesa->radeon);
+ if (rcommonEnsureCmdBufSpace(&rmesa->radeon,
+ state_size +
+ vertex_array_size + prim_size,
+ __FUNCTION__))
+ rmesa->radeon.swtcl.emit_prediction = radeonCountStateEmitSize(&rmesa->radeon);
+ else
+ rmesa->radeon.swtcl.emit_prediction = state_size;
+ rmesa->radeon.swtcl.emit_prediction += vertex_array_size + prim_size
+ + rmesa->radeon.cmdbuf.cs->cdw;
}
}
static void r200RenderStart( GLcontext *ctx )
{
- r200ContextPtr rmesa = R200_CONTEXT( ctx );
-
r200SetVertexFormat( ctx );
-
- if (rmesa->dma.flush != 0 &&
- rmesa->dma.flush != flush_last_swtcl_prim)
- rmesa->dma.flush( rmesa );
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s\n", __func__);
}
@@ -232,7 +246,7 @@ void r200ChooseVertexState( GLcontext *ctx )
* rasterization fallback. As this function will be called again when we
* leave a rasterization fallback, we can just skip it for now.
*/
- if (rmesa->Fallback != 0)
+ if (rmesa->radeon.Fallback != 0)
return;
vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
@@ -273,78 +287,32 @@ void r200ChooseVertexState( GLcontext *ctx )
}
}
-
-/* Flush vertices in the current dma region.
- */
-static void flush_last_swtcl_prim( r200ContextPtr rmesa )
-{
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- rmesa->dma.flush = NULL;
-
- if (rmesa->dma.current.buf) {
- struct r200_dma_region *current = &rmesa->dma.current;
- GLuint current_offset = (rmesa->r200Screen->gart_buffer_offset +
- current->buf->buf->idx * RADEON_BUFFER_SIZE +
- current->start);
-
- assert (!(rmesa->swtcl.hw_primitive & R200_VF_PRIM_WALK_IND));
-
- assert (current->start +
- rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
- current->ptr);
-
- if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
- r200EnsureCmdBufSpace( rmesa, VERT_AOS_BUFSZ +
- rmesa->hw.max_state_size + VBUF_BUFSZ );
- r200EmitVertexAOS( rmesa,
- rmesa->swtcl.vertex_size,
- current_offset);
-
- r200EmitVbufPrim( rmesa,
- rmesa->swtcl.hw_primitive,
- rmesa->swtcl.numverts);
- }
-
- rmesa->swtcl.numverts = 0;
- current->start = current->ptr;
- }
-}
-
-
-/* Alloc space in the current dma region.
- */
-static INLINE void *
-r200AllocDmaLowVerts( r200ContextPtr rmesa, int nverts, int vsize )
+void r200_swtcl_flush(GLcontext *ctx, uint32_t current_offset)
{
- GLuint bytes = vsize * nverts;
+ r200ContextPtr rmesa = R200_CONTEXT(ctx);
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s\n", __func__);
- if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
- r200RefillCurrentDmaRegion( rmesa );
- if (!rmesa->dma.flush) {
- rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
- rmesa->dma.flush = flush_last_swtcl_prim;
- }
+ radeonEmitState(&rmesa->radeon);
+ r200EmitVertexAOS( rmesa,
+ rmesa->radeon.swtcl.vertex_size,
+ first_elem(&rmesa->radeon.dma.reserved)->bo,
+ current_offset);
- ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
- ASSERT( rmesa->dma.flush == flush_last_swtcl_prim );
- ASSERT( rmesa->dma.current.start +
- rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
- rmesa->dma.current.ptr );
+ r200EmitVbufPrim( rmesa,
+ rmesa->radeon.swtcl.hw_primitive,
+ rmesa->radeon.swtcl.numverts);
+ if ( rmesa->radeon.swtcl.emit_prediction < rmesa->radeon.cmdbuf.cs->cdw )
+ WARN_ONCE("Rendering was %d commands larger than predicted size."
+ " We might overflow command buffer.\n",
+ rmesa->radeon.cmdbuf.cs->cdw - rmesa->radeon.swtcl.emit_prediction );
- {
- GLubyte *head = (GLubyte *) (rmesa->dma.current.address + rmesa->dma.current.ptr);
- rmesa->dma.current.ptr += bytes;
- rmesa->swtcl.numverts += nverts;
- return head;
- }
+ rmesa->radeon.swtcl.emit_prediction = 0;
}
-
/**************************************************************************/
@@ -389,17 +357,27 @@ static void r200ResetLineStipple( GLcontext *ctx );
#define HAVE_POLYGONS 1
#define HAVE_ELTS 0
+static void* r200_alloc_verts( r200ContextPtr rmesa, GLuint n, GLuint size)
+{
+ void *rv;
+ do {
+ r200_predict_emit_size( rmesa );
+ rv = rcommonAllocDmaLowVerts( &rmesa->radeon, n, size * 4 );
+ } while(!rv);
+ return rv;
+}
+
#undef LOCAL_VARS
#undef ALLOC_VERTS
#define CTX_ARG r200ContextPtr rmesa
-#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
-#define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
+#define GET_VERTEX_DWORDS() rmesa->radeon.swtcl.vertex_size
+#define ALLOC_VERTS( n, size ) r200_alloc_verts(rmesa, n, size)
#define LOCAL_VARS \
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
- const char *r200verts = (char *)rmesa->swtcl.verts;
-#define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int)))
-#define VERTEX r200Vertex
-#define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
+ const char *r200verts = (char *)rmesa->radeon.swtcl.verts;
+#define VERT(x) (radeonVertex *)(r200verts + ((x) * vertsize * sizeof(int)))
+#define VERTEX radeonVertex
+#define DO_DEBUG_VERTS (1 && (R200_DEBUG & RADEON_VERTS))
#undef TAG
#define TAG(x) r200_##x
@@ -456,11 +434,11 @@ static struct {
#define VERT_Y(_v) _v->v.y
#define VERT_Z(_v) _v->v.z
#define AREA_IS_CCW( a ) (a < 0)
-#define GET_VERTEX(e) (rmesa->swtcl.verts + (e*rmesa->swtcl.vertex_size*sizeof(int)))
+#define GET_VERTEX(e) (rmesa->radeon.swtcl.verts + (e*rmesa->radeon.swtcl.vertex_size*sizeof(int)))
#define VERT_SET_RGBA( v, c ) \
do { \
- r200_color_t *color = (r200_color_t *)&((v)->ui[coloroffset]); \
+ radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]); \
UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
@@ -472,7 +450,7 @@ do { \
#define VERT_SET_SPEC( v, c ) \
do { \
if (specoffset) { \
- r200_color_t *spec = (r200_color_t *)&((v)->ui[specoffset]); \
+ radeon_color_t *spec = (radeon_color_t *)&((v)->ui[specoffset]); \
UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
@@ -481,8 +459,8 @@ do { \
#define VERT_COPY_SPEC( v0, v1 ) \
do { \
if (specoffset) { \
- r200_color_t *spec0 = (r200_color_t *)&((v0)->ui[specoffset]); \
- r200_color_t *spec1 = (r200_color_t *)&((v1)->ui[specoffset]); \
+ radeon_color_t *spec0 = (radeon_color_t *)&((v0)->ui[specoffset]); \
+ radeon_color_t *spec1 = (radeon_color_t *)&((v1)->ui[specoffset]); \
spec0->red = spec1->red; \
spec0->green = spec1->green; \
spec0->blue = spec1->blue; \
@@ -503,7 +481,7 @@ do { \
#define LOCAL_VARS(n) \
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
- GLuint color[n], spec[n]; \
+ GLuint color[n] = {0}, spec[n] = {0}; \
GLuint coloroffset = rmesa->swtcl.coloroffset; \
GLuint specoffset = rmesa->swtcl.specoffset; \
(void) color; (void) spec; (void) coloroffset; (void) specoffset;
@@ -513,7 +491,7 @@ do { \
***********************************************************************/
#define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) )
-#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
+#define RENDER_PRIMITIVE rmesa->radeon.swtcl.render_primitive
#undef TAG
#define TAG(x) x
#include "tnl_dd/t_dd_unfilled.h"
@@ -569,8 +547,8 @@ static void init_rast_tab( void )
#undef LOCAL_VARS
#define LOCAL_VARS \
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
- const GLuint vertsize = rmesa->swtcl.vertex_size; \
- const char *r200verts = (char *)rmesa->swtcl.verts; \
+ const GLuint vertsize = rmesa->radeon.swtcl.vertex_size; \
+ const char *r200verts = (char *)rmesa->radeon.swtcl.verts; \
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
const GLboolean stipple = ctx->Line.StippleFlag; \
(void) elt; (void) stipple;
@@ -599,13 +577,13 @@ void r200ChooseRenderState( GLcontext *ctx )
GLuint index = 0;
GLuint flags = ctx->_TriangleCaps;
- if (!rmesa->TclFallback || rmesa->Fallback)
+ if (!rmesa->radeon.TclFallback || rmesa->radeon.Fallback)
return;
if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R200_TWOSIDE_BIT;
if (flags & DD_TRI_UNFILLED) index |= R200_UNFILLED_BIT;
- if (index != rmesa->swtcl.RenderIndex) {
+ if (index != rmesa->radeon.swtcl.RenderIndex) {
tnl->Driver.Render.Points = rast_tab[index].points;
tnl->Driver.Render.Line = rast_tab[index].line;
tnl->Driver.Render.ClippedLine = rast_tab[index].line;
@@ -622,7 +600,7 @@ void r200ChooseRenderState( GLcontext *ctx )
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
}
- rmesa->swtcl.RenderIndex = index;
+ rmesa->radeon.swtcl.RenderIndex = index;
}
}
@@ -636,7 +614,7 @@ static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- if (rmesa->swtcl.hw_primitive != hwprim) {
+ if (rmesa->radeon.swtcl.hw_primitive != hwprim) {
/* need to disable perspective-correct texturing for point sprites */
if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) {
if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) {
@@ -649,15 +627,15 @@ static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE;
}
R200_NEWPRIM( rmesa );
- rmesa->swtcl.hw_primitive = hwprim;
+ rmesa->radeon.swtcl.hw_primitive = hwprim;
}
}
static void r200RenderPrimitive( GLcontext *ctx, GLenum prim )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- rmesa->swtcl.render_primitive = prim;
- if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED))
+ rmesa->radeon.swtcl.render_primitive = prim;
+ if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED))
r200RasterPrimitive( ctx, reduced_hw_prim(ctx, prim) );
}
@@ -701,23 +679,23 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
- GLuint oldfallback = rmesa->Fallback;
+ GLuint oldfallback = rmesa->radeon.Fallback;
if (mode) {
- rmesa->Fallback |= bit;
+ rmesa->radeon.Fallback |= bit;
if (oldfallback == 0) {
- R200_FIREVERTICES( rmesa );
+ radeon_firevertices(&rmesa->radeon);
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE );
_swsetup_Wakeup( ctx );
- rmesa->swtcl.RenderIndex = ~0;
- if (R200_DEBUG & DEBUG_FALLBACKS) {
+ rmesa->radeon.swtcl.RenderIndex = ~0;
+ if (R200_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n",
bit, getFallbackString(bit));
}
}
}
else {
- rmesa->Fallback &= ~bit;
+ rmesa->radeon.Fallback &= ~bit;
if (oldfallback == bit) {
_swrast_flush( ctx );
@@ -731,18 +709,18 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE );
- if (rmesa->TclFallback) {
- /* These are already done if rmesa->TclFallback goes to
+ if (rmesa->radeon.TclFallback) {
+ /* These are already done if rmesa->radeon.TclFallback goes to
* zero above. But not if it doesn't (R200_NO_TCL for
* example?)
*/
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
- RENDERINPUTS_ZERO( rmesa->tnl_index_bitset );
+ RENDERINPUTS_ZERO( rmesa->radeon.tnl_index_bitset );
r200ChooseVertexState( ctx );
r200ChooseRenderState( ctx );
}
- if (R200_DEBUG & DEBUG_FALLBACKS) {
+ if (R200_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "R200 end rasterization fallback: 0x%x %s\n",
bit, getFallbackString(bit));
}
@@ -755,7 +733,7 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
/**
* Cope with depth operations by drawing individual pixels as points.
- *
+ *
* \todo
* The way the vertex state is set in this routine is hokey. It seems to
* work, but it's very hackish. This whole routine is pretty hackish. If
@@ -770,14 +748,14 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
const GLubyte *bitmap )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- const GLfloat *rc = ctx->Current.RasterColor;
+ const GLfloat *rc = ctx->Current.RasterColor;
GLint row, col;
- r200Vertex vert;
+ radeonVertex vert;
GLuint orig_vte;
GLuint h;
- /* Turn off tcl.
+ /* Turn off tcl.
*/
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 1 );
@@ -794,7 +772,7 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
vte |= R200_VTX_W0_FMT;
vap &= ~R200_VAP_FORCE_W_TO_ONE;
- rmesa->swtcl.vertex_size = 5;
+ rmesa->radeon.swtcl.vertex_size = 5;
if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0)
|| (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
@@ -828,7 +806,7 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
R200_VPORT_Z_SCALE_ENA |
R200_VPORT_X_OFFSET_ENA |
R200_VPORT_Y_OFFSET_ENA |
- R200_VPORT_Z_OFFSET_ENA);
+ R200_VPORT_Z_OFFSET_ENA);
/* Turn off other stuff: Stipple?, texture?, blending?, etc.
*/
@@ -871,16 +849,16 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
/* Update window height
*/
- LOCK_HARDWARE( rmesa );
- UNLOCK_HARDWARE( rmesa );
- h = rmesa->dri.drawable->h + rmesa->dri.drawable->y;
- px += rmesa->dri.drawable->x;
+ LOCK_HARDWARE( &rmesa->radeon );
+ UNLOCK_HARDWARE( &rmesa->radeon );
+ h = radeon_get_drawable(&rmesa->radeon)->h + radeon_get_drawable(&rmesa->radeon)->y;
+ px += radeon_get_drawable(&rmesa->radeon)->x;
/* Clipping handled by existing mechansims in r200_ioctl.c?
*/
for (row=0; row<height; row++) {
- const GLubyte *src = (const GLubyte *)
- _mesa_image_address2d(unpack, bitmap, width, height,
+ const GLubyte *src = (const GLubyte *)
+ _mesa_image_address2d(unpack, bitmap, width, height,
GL_COLOR_INDEX, GL_BITMAP, row, 0 );
if (unpack->LsbFirst) {
@@ -929,7 +907,7 @@ r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
/* Need to restore vertexformat?
*/
- if (rmesa->TclFallback)
+ if (rmesa->radeon.TclFallback)
r200ChooseVertexState( ctx );
}
@@ -949,6 +927,7 @@ void r200InitSwtcl( GLcontext *ctx )
init_rast_tab();
firsttime = 0;
}
+ rmesa->radeon.swtcl.emit_prediction = 0;
tnl->Driver.Render.Start = r200RenderStart;
tnl->Driver.Render.Finish = r200RenderFinish;
@@ -959,20 +938,12 @@ void r200InitSwtcl( GLcontext *ctx )
tnl->Driver.Render.Interp = _tnl_interp;
/* FIXME: what are these numbers? */
- _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
+ _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
36 * sizeof(GLfloat) );
-
- rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
- rmesa->swtcl.RenderIndex = ~0;
- rmesa->swtcl.render_primitive = GL_TRIANGLES;
- rmesa->swtcl.hw_primitive = 0;
-}
-
-void r200DestroySwtcl( GLcontext *ctx )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if (rmesa->swtcl.indexed_verts.buf)
- r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ );
+ rmesa->radeon.swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
+ rmesa->radeon.swtcl.RenderIndex = ~0;
+ rmesa->radeon.swtcl.render_primitive = GL_TRIANGLES;
+ rmesa->radeon.swtcl.hw_primitive = 0;
}
+
diff --git a/src/mesa/drivers/dri/r200/r200_swtcl.h b/src/mesa/drivers/dri/r200/r200_swtcl.h
index 8c29fd0c99..b0905879d7 100644
--- a/src/mesa/drivers/dri/r200/r200_swtcl.h
+++ b/src/mesa/drivers/dri/r200/r200_swtcl.h
@@ -39,7 +39,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r200_context.h"
extern void r200InitSwtcl( GLcontext *ctx );
-extern void r200DestroySwtcl( GLcontext *ctx );
extern void r200ChooseRenderState( GLcontext *ctx );
extern void r200ChooseVertexState( GLcontext *ctx );
@@ -52,15 +51,11 @@ extern void r200BuildVertices( GLcontext *ctx, GLuint start, GLuint count,
extern void r200PrintSetupFlags(char *msg, GLuint flags );
-extern void r200_emit_indexed_verts( GLcontext *ctx,
- GLuint start,
- GLuint count );
-
extern void r200_translate_vertex( GLcontext *ctx,
- const r200Vertex *src,
+ const radeonVertex *src,
SWvertex *dst );
-extern void r200_print_vertex( GLcontext *ctx, const r200Vertex *v );
+extern void r200_print_vertex( GLcontext *ctx, const radeonVertex *v );
extern void r200_import_float_colors( GLcontext *ctx );
extern void r200_import_float_spec_colors( GLcontext *ctx );
@@ -70,5 +65,5 @@ extern void r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap );
-
+void r200_swtcl_flush(GLcontext *ctx, uint32_t current_offset);
#endif
diff --git a/src/mesa/drivers/dri/r200/r200_tcl.c b/src/mesa/drivers/dri/r200/r200_tcl.c
index 99aecfe1e9..c702910ef2 100644
--- a/src/mesa/drivers/dri/r200/r200_tcl.c
+++ b/src/mesa/drivers/dri/r200/r200_tcl.c
@@ -51,6 +51,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r200_swtcl.h"
#include "r200_maos.h"
+#include "radeon_common_context.h"
+
#define HAVE_POINTS 1
@@ -109,7 +111,7 @@ static GLboolean discrete_prim[0x10] = {
#define ELT_INIT(prim, hw_prim) \
r200TclPrimitive( ctx, prim, hw_prim | R200_VF_PRIM_WALK_IND )
-#define GET_MESA_ELTS() rmesa->tcl.Elts
+#define GET_MESA_ELTS() TNL_CONTEXT(ctx)->vb.Elts
/* Don't really know how many elts will fit in what's left of cmdbuf,
@@ -123,7 +125,7 @@ static GLboolean discrete_prim[0x10] = {
#define RESET_STIPPLE() do { \
R200_STATECHANGE( rmesa, lin ); \
- r200EmitState( rmesa ); \
+ radeonEmitState(&rmesa->radeon); \
} while (0)
#define AUTO_STIPPLE( mode ) do { \
@@ -134,7 +136,7 @@ static GLboolean discrete_prim[0x10] = {
else \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
~R200_LINE_PATTERN_AUTO_RESET; \
- r200EmitState( rmesa ); \
+ radeonEmitState(&rmesa->radeon); \
} while (0)
@@ -142,27 +144,24 @@ static GLboolean discrete_prim[0x10] = {
static GLushort *r200AllocElts( r200ContextPtr rmesa, GLuint nr )
{
- if (rmesa->dma.flush == r200FlushElts &&
- rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) {
+ if (rmesa->radeon.dma.flush == r200FlushElts &&
+ rmesa->tcl.elt_used + nr*2 < R200_ELT_BUF_SZ) {
- GLushort *dest = (GLushort *)(rmesa->store.cmd_buf +
- rmesa->store.cmd_used);
+ GLushort *dest = (GLushort *)(rmesa->radeon.tcl.elt_dma_bo->ptr +
+ rmesa->radeon.tcl.elt_dma_offset + rmesa->tcl.elt_used);
- rmesa->store.cmd_used += nr*2;
+ rmesa->tcl.elt_used += nr*2;
return dest;
}
else {
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
-
- r200EnsureCmdBufSpace( rmesa, AOS_BUFSZ(rmesa->tcl.nr_aos_components) +
- rmesa->hw.max_state_size + ELTS_BUFSZ(nr) );
+ if (rmesa->radeon.dma.flush)
+ rmesa->radeon.dma.flush( rmesa->radeon.glCtx );
r200EmitAOS( rmesa,
- rmesa->tcl.aos_components,
- rmesa->tcl.nr_aos_components, 0 );
+ rmesa->radeon.tcl.aos_count, 0 );
+ r200EmitMaxVtxIndex(rmesa, rmesa->radeon.tcl.aos[0].count);
return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr );
}
}
@@ -188,13 +187,11 @@ static void r200EmitPrim( GLcontext *ctx,
r200ContextPtr rmesa = R200_CONTEXT( ctx );
r200TclPrimitive( ctx, prim, hwprim );
- r200EnsureCmdBufSpace( rmesa, AOS_BUFSZ(rmesa->tcl.nr_aos_components) +
- rmesa->hw.max_state_size + VBUF_BUFSZ );
+ // fprintf(stderr,"Emit prim %d\n", rmesa->radeon.tcl.aos_count);
r200EmitAOS( rmesa,
- rmesa->tcl.aos_components,
- rmesa->tcl.nr_aos_components,
- start );
+ rmesa->radeon.tcl.aos_count,
+ start );
/* Why couldn't this packet have taken an offset param?
*/
@@ -207,6 +204,7 @@ static void r200EmitPrim( GLcontext *ctx,
r200EmitPrim( ctx, prim, hwprim, start, count ); \
(void) rmesa; } while (0)
+#define MAX_CONVERSION_SIZE 40
/* Try & join small primitives
*/
#if 0
@@ -369,6 +367,66 @@ r200ComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord )
}
}
+/**
+ * Predict total emit size for next rendering operation so there is no flush in middle of rendering
+ * Prediction has to aim towards the best possible value that is worse than worst case scenario
+ */
+static GLuint r200EnsureEmitSize( GLcontext * ctx , GLubyte* vimap_rev )
+{
+ r200ContextPtr rmesa = R200_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint space_required;
+ GLuint state_size;
+ GLuint nr_aos = 0;
+ int i;
+ /* predict number of aos to emit */
+ for (i = 0; i < 15; ++i)
+ {
+ if (vimap_rev[i] != 255)
+ {
+ ++nr_aos;
+ }
+ }
+
+ {
+ /* count the prediction for state size */
+ space_required = 0;
+ state_size = radeonCountStateEmitSize( &rmesa->radeon );
+ /* vtx may be changed in r200EmitArrays so account for it if not dirty */
+ if (!rmesa->hw.vtx.dirty)
+ state_size += rmesa->hw.vtx.check(rmesa->radeon.glCtx, &rmesa->hw.vtx);
+ /* predict size for elements */
+ for (i = 0; i < VB->PrimitiveCount; ++i)
+ {
+ if (!VB->Primitive[i].count)
+ continue;
+ /* If primitive.count is less than MAX_CONVERSION_SIZE
+ rendering code may decide convert to elts.
+ In that case we have to make pessimistic prediction.
+ and use larger of 2 paths. */
+ const GLuint elts = ELTS_BUFSZ(nr_aos);
+ const GLuint index = INDEX_BUFSZ;
+ const GLuint vbuf = VBUF_BUFSZ;
+ if ( (!VB->Elts && VB->Primitive[i].count >= MAX_CONVERSION_SIZE)
+ || vbuf > index + elts)
+ space_required += vbuf;
+ else
+ space_required += index + elts;
+ space_required += AOS_BUFSZ(nr_aos);
+ }
+ }
+
+ radeon_print(RADEON_RENDER,RADEON_VERBOSE,
+ "%s space %u, aos %d\n",
+ __func__, space_required, AOS_BUFSZ(nr_aos) );
+ /* flush the buffer in case we need more than is left. */
+ if (rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required + state_size, __FUNCTION__))
+ return space_required + radeonCountStateEmitSize( &rmesa->radeon );
+ else
+ return space_required + state_size;
+}
+
/**********************************************************************/
/* Render pipeline stage */
@@ -394,19 +452,19 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx,
/* TODO: separate this from the swtnl pipeline
*/
- if (rmesa->TclFallback)
+ if (rmesa->radeon.TclFallback)
return GL_TRUE; /* fallback to software t&l */
- if (R200_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ radeon_print(RADEON_RENDER, RADEON_NORMAL, "%s\n", __FUNCTION__);
if (VB->Count == 0)
return GL_FALSE;
/* Validate state:
*/
- if (rmesa->NewGLState)
- r200ValidateState( ctx );
+ if (rmesa->radeon.NewGLState)
+ if (!r200ValidateState( ctx ))
+ return GL_TRUE; /* fallback to sw t&l */
if (!ctx->VertexProgram._Enabled) {
/* NOTE: inputs != tnl->render_inputs - these are the untransformed
@@ -481,11 +539,11 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx,
/* Do the actual work:
*/
- r200ReleaseArrays( ctx, ~0 /* stage->changed_inputs */ );
+ radeonReleaseArrays( ctx, ~0 /* stage->changed_inputs */ );
+ GLuint emit_end = r200EnsureEmitSize( ctx, vimap_rev )
+ + rmesa->radeon.cmdbuf.cs->cdw;
r200EmitArrays( ctx, vimap_rev );
- rmesa->tcl.Elts = VB->Elts;
-
for (i = 0 ; i < VB->PrimitiveCount ; i++)
{
GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
@@ -495,11 +553,14 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx,
if (!length)
continue;
- if (rmesa->tcl.Elts)
+ if (VB->Elts)
r200EmitEltPrimitive( ctx, start, start+length, prim );
else
r200EmitPrimitive( ctx, start, start+length, prim );
}
+ if ( emit_end < rmesa->radeon.cmdbuf.cs->cdw )
+ WARN_ONCE("Rendering was %d commands larger than predicted size."
+ " We might overflow command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end);
return GL_FALSE; /* finished the pipe */
}
@@ -545,7 +606,7 @@ static void transition_to_swtnl( GLcontext *ctx )
tnl->Driver.NotifyMaterialChange =
_mesa_validate_all_lighting_tables;
- r200ReleaseArrays( ctx, ~0 );
+ radeonReleaseArrays( ctx, ~0 );
/* Still using the D3D based hardware-rasterizer from the radeon;
* need to put the card into D3D mode to make it work:
@@ -565,15 +626,11 @@ static void transition_to_hwtnl( GLcontext *ctx )
tnl->Driver.NotifyMaterialChange = r200UpdateMaterial;
- if ( rmesa->dma.flush )
- rmesa->dma.flush( rmesa );
+ if ( rmesa->radeon.dma.flush )
+ rmesa->radeon.dma.flush( rmesa->radeon.glCtx );
- rmesa->dma.flush = NULL;
+ rmesa->radeon.dma.flush = NULL;
- if (rmesa->swtcl.indexed_verts.buf)
- r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts,
- __FUNCTION__ );
-
R200_STATECHANGE( rmesa, vap );
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE;
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_FORCE_W_TO_ONE;
@@ -594,7 +651,7 @@ static void transition_to_hwtnl( GLcontext *ctx )
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT);
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT;
- if (R200_DEBUG & DEBUG_FALLBACKS)
+ if (R200_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "R200 end tcl fallback\n");
}
@@ -631,21 +688,21 @@ static char *getFallbackString(GLuint bit)
void r200TclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- GLuint oldfallback = rmesa->TclFallback;
+ GLuint oldfallback = rmesa->radeon.TclFallback;
if (mode) {
- rmesa->TclFallback |= bit;
+ rmesa->radeon.TclFallback |= bit;
if (oldfallback == 0) {
- if (R200_DEBUG & DEBUG_FALLBACKS)
+ if (R200_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "R200 begin tcl fallback %s\n",
getFallbackString( bit ));
transition_to_swtnl( ctx );
}
}
else {
- rmesa->TclFallback &= ~bit;
+ rmesa->radeon.TclFallback &= ~bit;
if (oldfallback == bit) {
- if (R200_DEBUG & DEBUG_FALLBACKS)
+ if (R200_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "R200 end tcl fallback %s\n",
getFallbackString( bit ));
transition_to_hwtnl( ctx );
diff --git a/src/mesa/drivers/dri/r200/r200_tex.c b/src/mesa/drivers/dri/r200/r200_tex.c
index 5a4db33f44..36d9e37d87 100644
--- a/src/mesa/drivers/dri/r200/r200_tex.c
+++ b/src/mesa/drivers/dri/r200/r200_tex.c
@@ -43,8 +43,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/teximage.h"
#include "main/texobj.h"
-#include "texmem.h"
-
+#include "radeon_mipmap_tree.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
@@ -63,10 +62,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* \param twrap Wrap mode for the \a t texture coordinate
*/
-static void r200SetTexWrap( r200TexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap )
+static void r200SetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap )
{
GLboolean is_clamp = GL_FALSE;
GLboolean is_clamp_to_border = GL_FALSE;
+ struct gl_texture_object *tObj = &t->base;
t->pp_txfilter &= ~(R200_CLAMP_S_MASK | R200_CLAMP_T_MASK | R200_BORDER_MODE_D3D);
@@ -103,7 +103,7 @@ static void r200SetTexWrap( r200TexObjPtr t, GLenum swrap, GLenum twrap, GLenum
_mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
}
- if (t->base.tObj->Target != GL_TEXTURE_1D) {
+ if (tObj->Target != GL_TEXTURE_1D) {
switch ( twrap ) {
case GL_REPEAT:
t->pp_txfilter |= R200_CLAMP_T_WRAP;
@@ -180,7 +180,7 @@ static void r200SetTexWrap( r200TexObjPtr t, GLenum swrap, GLenum twrap, GLenum
t->border_fallback = (is_clamp && is_clamp_to_border);
}
-static void r200SetTexMaxAnisotropy( r200TexObjPtr t, GLfloat max )
+static void r200SetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max )
{
t->pp_txfilter &= ~R200_MAX_ANISO_MASK;
@@ -205,10 +205,13 @@ static void r200SetTexMaxAnisotropy( r200TexObjPtr t, GLfloat max )
* \param magf Texture magnification mode
*/
-static void r200SetTexFilter( r200TexObjPtr t, GLenum minf, GLenum magf )
+static void r200SetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf )
{
GLuint anisotropy = (t->pp_txfilter & R200_MAX_ANISO_MASK);
+ /* Force revalidation to account for switches from/to mipmapping. */
+ t->validated = GL_FALSE;
+
t->pp_txfilter &= ~(R200_MIN_FILTER_MASK | R200_MAG_FILTER_MASK);
t->pp_txformat_x &= ~R200_VOLUME_FILTER_MASK;
@@ -267,696 +270,16 @@ static void r200SetTexFilter( r200TexObjPtr t, GLenum minf, GLenum magf )
}
}
-static void r200SetTexBorderColor( r200TexObjPtr t, GLubyte c[4] )
-{
- t->pp_border_color = r200PackColor( 4, c[0], c[1], c[2], c[3] );
-}
-
-
-/**
- * Allocate space for and load the mesa images into the texture memory block.
- * This will happen before drawing with a new texture, or drawing with a
- * texture after it was swapped out or teximaged again.
- */
-
-static r200TexObjPtr r200AllocTexObj( struct gl_texture_object *texObj )
-{
- r200TexObjPtr t;
-
- t = CALLOC_STRUCT( r200_tex_obj );
- texObj->DriverData = t;
- if ( t != NULL ) {
- if ( R200_DEBUG & DEBUG_TEXTURE ) {
- fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)texObj,
- (void *)t );
- }
-
- /* Initialize non-image-dependent parts of the state:
- */
- t->base.tObj = texObj;
- t->border_fallback = GL_FALSE;
-
- make_empty_list( & t->base );
-
- r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
- r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
- r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
- r200SetTexBorderColor( t, texObj->_BorderChan );
- }
-
- return t;
-}
-
-/* try to find a format which will only need a memcopy */
-static const struct gl_texture_format *
-r200Choose8888TexFormat( GLenum srcFormat, GLenum srcType )
-{
- const GLuint ui = 1;
- const GLubyte littleEndian = *((const GLubyte *) &ui);
-
- if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
- (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
- (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
- (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) {
- return &_mesa_texformat_rgba8888;
- }
- else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
- (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
- (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
- (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) {
- return &_mesa_texformat_rgba8888_rev;
- }
- else return _dri_texformat_argb8888;
-}
-
-static const struct gl_texture_format *
-r200ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
- GLenum format, GLenum type )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- const GLboolean do32bpt =
- ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
- const GLboolean force16bpt =
- ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
- (void) format;
-
- switch ( internalFormat ) {
- case 4:
- case GL_RGBA:
- case GL_COMPRESSED_RGBA:
- switch ( type ) {
- case GL_UNSIGNED_INT_10_10_10_2:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_argb1555;
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return _dri_texformat_argb4444;
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return _dri_texformat_argb1555;
- default:
- return do32bpt ?
- r200Choose8888TexFormat(format, type) : _dri_texformat_argb4444;
- }
-
- case 3:
- case GL_RGB:
- case GL_COMPRESSED_RGB:
- switch ( type ) {
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return _dri_texformat_argb4444;
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return _dri_texformat_argb1555;
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- return _dri_texformat_rgb565;
- default:
- return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
- }
-
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- return !force16bpt ?
- r200Choose8888TexFormat(format, type) : _dri_texformat_argb4444;
-
- case GL_RGBA4:
- case GL_RGBA2:
- return _dri_texformat_argb4444;
-
- case GL_RGB5_A1:
- return _dri_texformat_argb1555;
-
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- return !force16bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
-
- case GL_RGB5:
- case GL_RGB4:
- case GL_R3_G3_B2:
- return _dri_texformat_rgb565;
-
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- case GL_ALPHA12:
- case GL_ALPHA16:
- case GL_COMPRESSED_ALPHA:
- /* can't use a8 format since interpreting hw I8 as a8 would result
- in wrong rgb values (same as alpha value instead of 0). */
- return _dri_texformat_al88;
-
- case 1:
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- case GL_COMPRESSED_LUMINANCE:
- return _dri_texformat_l8;
-
- case 2:
- 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:
- case GL_COMPRESSED_LUMINANCE_ALPHA:
- return _dri_texformat_al88;
-
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- case GL_COMPRESSED_INTENSITY:
- return _dri_texformat_i8;
-
- case GL_YCBCR_MESA:
- if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
- type == GL_UNSIGNED_BYTE)
- return &_mesa_texformat_ycbcr;
- else
- return &_mesa_texformat_ycbcr_rev;
-
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- return &_mesa_texformat_rgb_dxt1;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- return &_mesa_texformat_rgba_dxt1;
-
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- return &_mesa_texformat_rgba_dxt3;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- return &_mesa_texformat_rgba_dxt5;
-
- default:
- _mesa_problem(ctx,
- "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
- (int) internalFormat);
- return NULL;
- }
-
- return NULL; /* never get here */
-}
-
-
-static GLboolean
-r200ValidateClientStorage( GLcontext *ctx, GLenum target,
- GLint internalFormat,
- GLint srcWidth, GLint srcHeight,
- GLenum format, GLenum type, const void *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf(stderr, "intformat %s format %s type %s\n",
- _mesa_lookup_enum_by_nr( internalFormat ),
- _mesa_lookup_enum_by_nr( format ),
- _mesa_lookup_enum_by_nr( type ));
-
- if (!ctx->Unpack.ClientStorage)
- return 0;
-
- if (ctx->_ImageTransferState ||
- texImage->IsCompressed ||
- texObj->GenerateMipmap)
- return 0;
-
-
- /* This list is incomplete, may be different on ppc???
- */
- switch ( internalFormat ) {
- case GL_RGBA:
- if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
- texImage->TexFormat = _dri_texformat_argb8888;
- }
- else
- return 0;
- break;
-
- case GL_RGB:
- if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
- texImage->TexFormat = _dri_texformat_rgb565;
- }
- else
- return 0;
- break;
-
- case GL_YCBCR_MESA:
- if ( format == GL_YCBCR_MESA &&
- type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
- texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
- }
- else if ( format == GL_YCBCR_MESA &&
- (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
- type == GL_UNSIGNED_BYTE)) {
- texImage->TexFormat = &_mesa_texformat_ycbcr;
- }
- else
- return 0;
- break;
-
- default:
- return 0;
- }
-
- /* Could deal with these packing issues, but currently don't:
- */
- if (packing->SkipPixels ||
- packing->SkipRows ||
- packing->SwapBytes ||
- packing->LsbFirst) {
- return 0;
- }
-
- {
- GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
- format, type);
-
-
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf(stderr, "%s: srcRowStride %d/%x\n",
- __FUNCTION__, srcRowStride, srcRowStride);
-
- /* Could check this later in upload, pitch restrictions could be
- * relaxed, but would need to store the image pitch somewhere,
- * as packing details might change before image is uploaded:
- */
- if (!r200IsGartMemory( rmesa, pixels, srcHeight * srcRowStride ) ||
- (srcRowStride & 63))
- return 0;
-
-
- /* Have validated that _mesa_transfer_teximage would be a straight
- * memcpy at this point. NOTE: future calls to TexSubImage will
- * overwrite the client data. This is explicitly mentioned in the
- * extension spec.
- */
- texImage->Data = (void *)pixels;
- texImage->IsClientData = GL_TRUE;
- texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes;
-
- return 1;
- }
-}
-
-
-static void r200TexImage1D( GLcontext *ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint border,
- GLenum format, GLenum type, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
+static void r200SetTexBorderColor( radeonTexObjPtr t, const GLfloat color[4] )
{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
-
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) r200AllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
- return;
- }
- }
-
- /* Note, this will call ChooseTextureFormat */
- _mesa_store_teximage1d(ctx, target, level, internalFormat,
- width, border, format, type, pixels,
- &ctx->Unpack, texObj, texImage);
-
- t->dirty_images[0] |= (1 << level);
-}
-
-
-static void r200TexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset,
- GLsizei width,
- GLenum format, GLenum type,
- const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
-
- assert( t ); /* this _should_ be true */
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) r200AllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
- return;
- }
- }
-
- _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
- format, type, pixels, packing, texObj,
- texImage);
-
- t->dirty_images[0] |= (1 << level);
+ GLubyte c[4];
+ CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
+ t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
}
-
-static void r200TexImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLenum format, GLenum type, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- if ( t != NULL ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) r200AllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
- return;
- }
- }
-
- texImage->IsClientData = GL_FALSE;
-
- if (r200ValidateClientStorage( ctx, target,
- internalFormat,
- width, height,
- format, type, pixels,
- packing, texObj, texImage)) {
- if (R200_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
- }
- else {
- if (R200_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
-
- /* Normal path: copy (to cached memory) and eventually upload
- * via another copy to GART memory and then a blit... Could
- * eliminate one copy by going straight to (permanent) GART.
- *
- * Note, this will call r200ChooseTextureFormat.
- */
- _mesa_store_teximage2d(ctx, target, level, internalFormat,
- width, height, border, format, type, pixels,
- &ctx->Unpack, texObj, texImage);
-
- t->dirty_images[face] |= (1 << level);
- }
-}
-
-
-static void r200TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- assert( t ); /* this _should_ be true */
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) r200AllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
- return;
- }
- }
-
- _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
- height, format, type, pixels, packing, texObj,
- texImage);
-
- t->dirty_images[face] |= (1 << level);
-}
-
-
-static void r200CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLsizei imageSize, const GLvoid *data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- if ( t != NULL ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) r200AllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
- return;
- }
- }
-
- texImage->IsClientData = GL_FALSE;
-/* can't call this, different parameters. Would never evaluate to true anyway currently
- if (r200ValidateClientStorage( ctx, target,
- internalFormat,
- width, height,
- format, type, pixels,
- packing, texObj, texImage)) {
- if (R200_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
- }
- else */{
- if (R200_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
-
- /* Normal path: copy (to cached memory) and eventually upload
- * via another copy to GART memory and then a blit... Could
- * eliminate one copy by going straight to (permanent) GART.
- *
- * Note, this will call r200ChooseTextureFormat.
- */
- _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
- height, border, imageSize, data, texObj, texImage);
-
- t->dirty_images[face] |= (1 << level);
- }
-}
-
-
-static void r200CompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format,
- GLsizei imageSize, const GLvoid *data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- assert( t ); /* this _should_ be true */
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) r200AllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
- return;
- }
- }
-
- _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
- height, format, imageSize, data, texObj, texImage);
-
- t->dirty_images[face] |= (1 << level);
-}
-
-
-#if ENABLE_HW_3D_TEXTURE
-static void r200TexImage3D( GLcontext *ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint depth,
- GLint border,
- GLenum format, GLenum type, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
-
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) r200AllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
- return;
- }
- }
-
- texImage->IsClientData = GL_FALSE;
-
-#if 0
- if (r200ValidateClientStorage( ctx, target,
- internalFormat,
- width, height,
- format, type, pixels,
- packing, texObj, texImage)) {
- if (R200_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
- }
- else
-#endif
- {
- if (R200_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
-
- /* Normal path: copy (to cached memory) and eventually upload
- * via another copy to GART memory and then a blit... Could
- * eliminate one copy by going straight to (permanent) GART.
- *
- * Note, this will call r200ChooseTextureFormat.
- */
- _mesa_store_teximage3d(ctx, target, level, internalFormat,
- width, height, depth, border,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage);
-
- t->dirty_images[0] |= (1 << level);
- }
-}
-#endif
-
-
-#if ENABLE_HW_3D_TEXTURE
-static void
-r200TexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type,
- const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
-
-/* fprintf(stderr, "%s\n", __FUNCTION__); */
-
- assert( t ); /* this _should_ be true */
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) r200AllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
- return;
- }
- texObj->DriverData = t;
- }
-
- _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
- width, height, depth,
- format, type, pixels, packing, texObj, texImage);
-
- t->dirty_images[0] |= (1 << level);
-}
-#endif
-
-
-
static void r200TexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
@@ -964,7 +287,7 @@ static void r200TexEnv( GLcontext *ctx, GLenum target,
GLuint unit = ctx->Texture.CurrentUnit;
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- if ( R200_DEBUG & DEBUG_STATE ) {
+ if ( R200_DEBUG & RADEON_STATE ) {
fprintf( stderr, "%s( %s )\n",
__FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
}
@@ -978,7 +301,7 @@ static void r200TexEnv( GLcontext *ctx, GLenum target,
GLubyte c[4];
GLuint envColor;
UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
- envColor = r200PackColor( 4, c[0], c[1], c[2], c[3] );
+ envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) {
R200_STATECHANGE( rmesa, tf );
rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor;
@@ -997,7 +320,7 @@ static void r200TexEnv( GLcontext *ctx, GLenum target,
* NOTE: Add a small bias to the bias for conform mipsel.c test.
*/
bias = *param + .01;
- min = driQueryOptionb (&rmesa->optionCache, "no_neg_lod_bias") ?
+ min = driQueryOptionb (&rmesa->radeon.optionCache, "no_neg_lod_bias") ?
0.0 : -16.0;
bias = CLAMP( bias, min, 16.0 );
b = (int)(bias * fixed_one) & R200_LOD_BIAS_MASK;
@@ -1034,9 +357,9 @@ static void r200TexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj,
GLenum pname, const GLfloat *params )
{
- r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
+ radeonTexObj* t = radeon_tex_obj(texObj);
- if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
+ if ( R200_DEBUG & (RADEON_STATE|RADEON_TEXTURE) ) {
fprintf( stderr, "%s( %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr( pname ) );
}
@@ -1056,7 +379,7 @@ static void r200TexParameter( GLcontext *ctx, GLenum target,
break;
case GL_TEXTURE_BORDER_COLOR:
- r200SetTexBorderColor( t, texObj->_BorderChan );
+ r200SetTexBorderColor( t, texObj->BorderColor );
break;
case GL_TEXTURE_BASE_LEVEL:
@@ -1068,59 +391,46 @@ static void r200TexParameter( GLcontext *ctx, GLenum target,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
- driSwapOutTextureObject( (driTextureObject *) t );
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = 0;
+ t->validated = GL_FALSE;
+ }
break;
default:
return;
}
-
- /* Mark this texobj as dirty (one bit per tex unit)
- */
- t->dirty_state = TEX_ALL;
}
-
-static void r200BindTexture( GLcontext *ctx, GLenum target,
- struct gl_texture_object *texObj )
-{
- if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
- fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *)texObj,
- ctx->Texture.CurrentUnit );
- }
-
- if ( (target == GL_TEXTURE_1D)
- || (target == GL_TEXTURE_2D)
-#if ENABLE_HW_3D_TEXTURE
- || (target == GL_TEXTURE_3D)
-#endif
- || (target == GL_TEXTURE_CUBE_MAP)
- || (target == GL_TEXTURE_RECTANGLE_NV) ) {
- assert( texObj->DriverData != NULL );
- }
-}
-
-
-static void r200DeleteTexture( GLcontext *ctx,
- struct gl_texture_object *texObj )
+static void r200DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
-
- if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
- fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
- _mesa_lookup_enum_by_nr( texObj->Target ) );
+ radeonTexObj* t = radeon_tex_obj(texObj);
+
+ if (RADEON_DEBUG & (RADEON_STATE | RADEON_TEXTURE)) {
+ fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
+ (void *)texObj,
+ _mesa_lookup_enum_by_nr(texObj->Target));
+ }
+
+ if (rmesa) {
+ int i;
+ radeon_firevertices(&rmesa->radeon);
+ for ( i = 0 ; i < rmesa->radeon.glCtx->Const.MaxTextureUnits ; i++ ) {
+ if ( t == rmesa->state.texture.unit[i].texobj ) {
+ rmesa->state.texture.unit[i].texobj = NULL;
+ rmesa->hw.tex[i].dirty = GL_FALSE;
+ rmesa->hw.cube[i].dirty = GL_FALSE;
+ }
+ }
}
-
- if ( t != NULL ) {
- if ( rmesa ) {
- R200_FIREVERTICES( rmesa );
- }
-
- driDestroyTextureObject( t );
+
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = 0;
}
- /* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, texObj);
}
@@ -1150,46 +460,59 @@ static void r200TexGen( GLcontext *ctx,
* Called via ctx->Driver.NewTextureObject.
* Note: this function will be called during context creation to
* allocate the default texture objects.
- * Note: we could use containment here to 'derive' the driver-specific
- * texture object from the core mesa gl_texture_object. Not done at this time.
* Fixup MaxAnisotropy according to user preference.
*/
-static struct gl_texture_object *
-r200NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
+static struct gl_texture_object *r200NewTextureObject(GLcontext * ctx,
+ GLuint name,
+ GLenum target)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- struct gl_texture_object *obj;
- obj = _mesa_new_texture_object(ctx, name, target);
- if (!obj)
- return NULL;
- obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
- r200AllocTexObj( obj );
- return obj;
+ radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj);
+
+
+ if (RADEON_DEBUG & (RADEON_STATE | RADEON_TEXTURE)) {
+ fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
+ t, _mesa_lookup_enum_by_nr(target));
+ }
+
+ _mesa_initialize_texture_object(&t->base, name, target);
+ t->base.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
+
+ /* Initialize hardware state */
+ r200SetTexWrap( t, t->base.WrapS, t->base.WrapT, t->base.WrapR );
+ r200SetTexMaxAnisotropy( t, t->base.MaxAnisotropy );
+ r200SetTexFilter(t, t->base.MinFilter, t->base.MagFilter);
+ r200SetTexBorderColor(t, t->base.BorderColor);
+
+ return &t->base;
}
+
void r200InitTextureFuncs( struct dd_function_table *functions )
{
/* Note: we only plug in the functions we implement in the driver
* since _mesa_init_driver_functions() was already called.
*/
- functions->ChooseTextureFormat = r200ChooseTextureFormat;
- functions->TexImage1D = r200TexImage1D;
- functions->TexImage2D = r200TexImage2D;
+ functions->ChooseTextureFormat = radeonChooseTextureFormat_mesa;
+ functions->TexImage1D = radeonTexImage1D;
+ functions->TexImage2D = radeonTexImage2D;
#if ENABLE_HW_3D_TEXTURE
- functions->TexImage3D = r200TexImage3D;
+ functions->TexImage3D = radeonTexImage3D;
#else
functions->TexImage3D = _mesa_store_teximage3d;
#endif
- functions->TexSubImage1D = r200TexSubImage1D;
- functions->TexSubImage2D = r200TexSubImage2D;
+ functions->TexSubImage1D = radeonTexSubImage1D;
+ functions->TexSubImage2D = radeonTexSubImage2D;
#if ENABLE_HW_3D_TEXTURE
- functions->TexSubImage3D = r200TexSubImage3D;
+ functions->TexSubImage3D = radeonTexSubImage3D;
#else
functions->TexSubImage3D = _mesa_store_texsubimage3d;
#endif
+ functions->GetTexImage = radeonGetTexImage;
+ functions->GetCompressedTexImage = radeonGetCompressedTexImage;
functions->NewTextureObject = r200NewTextureObject;
- functions->BindTexture = r200BindTexture;
+ // functions->BindTexture = r200BindTexture;
functions->DeleteTexture = r200DeleteTexture;
functions->IsTextureResident = driIsTextureResident;
@@ -1197,22 +520,16 @@ void r200InitTextureFuncs( struct dd_function_table *functions )
functions->TexParameter = r200TexParameter;
functions->TexGen = r200TexGen;
- functions->CompressedTexImage2D = r200CompressedTexImage2D;
- functions->CompressedTexSubImage2D = r200CompressedTexSubImage2D;
+ functions->CompressedTexImage2D = radeonCompressedTexImage2D;
+ functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
- driInitTextureFormats();
+ functions->GenerateMipmap = radeonGenerateMipmap;
-#if 000
- /* moved or obsolete code */
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- driInitTextureObjects( ctx, & rmesa->swapped,
- DRI_TEXMGR_DO_TEXTURE_1D
- | DRI_TEXMGR_DO_TEXTURE_2D );
+ functions->NewTextureImage = radeonNewTextureImage;
+ functions->FreeTexImageData = radeonFreeTexImageData;
+ functions->MapTexture = radeonMapTexture;
+ functions->UnmapTexture = radeonUnmapTexture;
+
+ driInitTextureFormats();
- /* Hack: r200NewTextureObject is not yet installed when the
- * default textures are created. Therefore set MaxAnisotropy of the
- * default 2D texture now. */
- ctx->Shared->Default2D->MaxAnisotropy = driQueryOptionf (&rmesa->optionCache,
- "def_max_anisotropy");
-#endif
}
diff --git a/src/mesa/drivers/dri/r200/r200_tex.h b/src/mesa/drivers/dri/r200/r200_tex.h
index 10ff8e8a66..e122de6e5e 100644
--- a/src/mesa/drivers/dri/r200/r200_tex.h
+++ b/src/mesa/drivers/dri/r200/r200_tex.h
@@ -35,15 +35,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef __R200_TEX_H__
#define __R200_TEX_H__
+extern void r200SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv);
+extern void r200SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format,
+ __DRIdrawable *dPriv);
extern void r200SetTexOffset(__DRIcontext *pDRICtx, GLint texname,
unsigned long long offset, GLint depth,
GLuint pitch);
extern void r200UpdateTextureState( GLcontext *ctx );
-extern int r200UploadTexImages( r200ContextPtr rmesa, r200TexObjPtr t, GLuint face );
+extern int r200UploadTexImages( r200ContextPtr rmesa, radeonTexObjPtr t, GLuint face );
-extern void r200DestroyTexObj( r200ContextPtr rmesa, r200TexObjPtr t );
+extern void r200DestroyTexObj( r200ContextPtr rmesa, radeonTexObjPtr t );
extern void r200InitTextureFuncs( struct dd_function_table *functions );
diff --git a/src/mesa/drivers/dri/r200/r200_texmem.c b/src/mesa/drivers/dri/r200/r200_texmem.c
deleted file mode 100644
index 3b81ac0c80..0000000000
--- a/src/mesa/drivers/dri/r200/r200_texmem.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/**************************************************************************
-
-Copyright (C) Tungsten Graphics 2002. All Rights Reserved.
-The Weather Channel, Inc. funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86
-license. This notice must be preserved.
-
-Permission is hereby granted, free of charge, to 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 ATI, VA LINUX SYSTEMS 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:
- * Kevin E. Martin <martin@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
- */
-
-#include <errno.h>
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/colormac.h"
-#include "main/macros.h"
-#include "r200_context.h"
-#include "r200_ioctl.h"
-#include "r200_tex.h"
-#include "radeon_reg.h"
-
-#include <unistd.h> /* for usleep() */
-
-
-/**
- * Destroy any device-dependent state associated with the texture. This may
- * include NULLing out hardware state that points to the texture.
- */
-void
-r200DestroyTexObj( r200ContextPtr rmesa, r200TexObjPtr t )
-{
- if ( R200_DEBUG & DEBUG_TEXTURE ) {
- fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__,
- (void *)t, (void *)t->base.tObj );
- }
-
- if ( rmesa != NULL ) {
- unsigned i;
-
-
- for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ ) {
- if ( t == rmesa->state.texture.unit[i].texobj ) {
- rmesa->state.texture.unit[i].texobj = NULL;
- rmesa->hw.tex[i].dirty = GL_FALSE;
- rmesa->hw.cube[i].dirty = GL_FALSE;
- }
- }
- }
-}
-
-
-/* ------------------------------------------------------------
- * Texture image conversions
- */
-
-
-static void r200UploadGARTClientSubImage( r200ContextPtr rmesa,
- r200TexObjPtr t,
- struct gl_texture_image *texImage,
- GLint hwlevel,
- GLint x, GLint y,
- GLint width, GLint height )
-{
- const struct gl_texture_format *texFormat = texImage->TexFormat;
- GLuint srcPitch, dstPitch;
- int blit_format;
- int srcOffset;
-
- /*
- * XXX it appears that we always upload the full image, not a subimage.
- * I.e. x==0, y==0, width=texWidth, height=texWidth. If this is ever
- * changed, the src pitch will have to change.
- */
- switch ( texFormat->TexelBytes ) {
- case 1:
- blit_format = R200_CP_COLOR_FORMAT_CI8;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 2:
- blit_format = R200_CP_COLOR_FORMAT_RGB565;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 4:
- blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- default:
- return;
- }
-
- t->image[0][hwlevel].data = texImage->Data;
- srcOffset = r200GartOffsetFromVirtual( rmesa, texImage->Data );
-
- assert( srcOffset != ~0 );
-
- /* Don't currently need to cope with small pitches?
- */
- width = texImage->Width;
- height = texImage->Height;
-
- r200EmitWait( rmesa, RADEON_WAIT_3D );
-
- r200EmitBlit( rmesa, blit_format,
- srcPitch,
- srcOffset,
- dstPitch,
- t->bufAddr,
- x,
- y,
- t->image[0][hwlevel].x + x,
- t->image[0][hwlevel].y + y,
- width,
- height );
-
- r200EmitWait( rmesa, RADEON_WAIT_2D );
-}
-
-static void r200UploadRectSubImage( r200ContextPtr rmesa,
- r200TexObjPtr t,
- struct gl_texture_image *texImage,
- GLint x, GLint y,
- GLint width, GLint height )
-{
- const struct gl_texture_format *texFormat = texImage->TexFormat;
- int blit_format, dstPitch, done;
-
- switch ( texFormat->TexelBytes ) {
- case 1:
- blit_format = R200_CP_COLOR_FORMAT_CI8;
- break;
- case 2:
- blit_format = R200_CP_COLOR_FORMAT_RGB565;
- break;
- case 4:
- blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
- break;
- default:
- return;
- }
-
- t->image[0][0].data = texImage->Data;
-
- /* Currently don't need to cope with small pitches.
- */
- width = texImage->Width;
- height = texImage->Height;
- dstPitch = t->pp_txpitch + 32;
-
- if (rmesa->prefer_gart_client_texturing && texImage->IsClientData) {
- /* In this case, could also use GART texturing. This is
- * currently disabled, but has been tested & works.
- */
- if ( !t->image_override )
- t->pp_txoffset = r200GartOffsetFromVirtual( rmesa, texImage->Data );
- t->pp_txpitch = texImage->RowStride * texFormat->TexelBytes - 32;
-
- if (R200_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "Using GART texturing for rectangular client texture\n");
-
- /* Release FB memory allocated for this image:
- */
- /* FIXME This may not be correct as driSwapOutTextureObject sets
- * FIXME dirty_images. It may be fine, though.
- */
- if ( t->base.memBlock ) {
- driSwapOutTextureObject( (driTextureObject *) t );
- }
- }
- else if (texImage->IsClientData) {
- /* Data already in GART memory, with usable pitch.
- */
- GLuint srcPitch;
- srcPitch = texImage->RowStride * texFormat->TexelBytes;
- r200EmitBlit( rmesa,
- blit_format,
- srcPitch,
- r200GartOffsetFromVirtual( rmesa, texImage->Data ),
- dstPitch, t->bufAddr,
- 0, 0,
- 0, 0,
- width, height );
- }
- else {
- /* Data not in GART memory, or bad pitch.
- */
- for (done = 0; done < height ; ) {
- struct r200_dma_region region;
- int lines = MIN2( height - done, RADEON_BUFFER_SIZE / dstPitch );
- int src_pitch;
- char *tex;
-
- src_pitch = texImage->RowStride * texFormat->TexelBytes;
-
- tex = (char *)texImage->Data + done * src_pitch;
-
- memset(&region, 0, sizeof(region));
- r200AllocDmaRegion( rmesa, &region, lines * dstPitch, 1024 );
-
- /* Copy texdata to dma:
- */
- if (0)
- fprintf(stderr, "%s: src_pitch %d dst_pitch %d\n",
- __FUNCTION__, src_pitch, dstPitch);
-
- if (src_pitch == dstPitch) {
- memcpy( region.address + region.start, tex, lines * src_pitch );
- }
- else {
- char *buf = region.address + region.start;
- int i;
- for (i = 0 ; i < lines ; i++) {
- memcpy( buf, tex, src_pitch );
- buf += dstPitch;
- tex += src_pitch;
- }
- }
-
- r200EmitWait( rmesa, RADEON_WAIT_3D );
-
- /* Blit to framebuffer
- */
- r200EmitBlit( rmesa,
- blit_format,
- dstPitch, GET_START( &region ),
- dstPitch | (t->tile_bits >> 16),
- t->bufAddr,
- 0, 0,
- 0, done,
- width, lines );
-
- r200EmitWait( rmesa, RADEON_WAIT_2D );
-
- r200ReleaseDmaRegion( rmesa, &region, __FUNCTION__ );
- done += lines;
- }
- }
-}
-
-
-/**
- * Upload the texture image associated with texture \a t at the specified
- * level at the address relative to \a start.
- */
-static void uploadSubImage( r200ContextPtr rmesa, r200TexObjPtr t,
- GLint hwlevel,
- GLint x, GLint y, GLint width, GLint height,
- GLuint face )
-{
- struct gl_texture_image *texImage = NULL;
- GLuint offset;
- GLint imageWidth, imageHeight;
- GLint ret;
- drm_radeon_texture_t tex;
- drm_radeon_tex_image_t tmp;
- const int level = hwlevel + t->base.firstLevel;
-
- if ( R200_DEBUG & DEBUG_TEXTURE ) {
- fprintf( stderr, "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n",
- __FUNCTION__, (void *)t, (void *)t->base.tObj,
- level, width, height, face );
- }
-
- ASSERT(face < 6);
-
- /* Ensure we have a valid texture to upload */
- if ( ( hwlevel < 0 ) || ( hwlevel >= RADEON_MAX_TEXTURE_LEVELS ) ) {
- _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
- return;
- }
-
- texImage = t->base.tObj->Image[face][level];
-
- if ( !texImage ) {
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level );
- return;
- }
- if ( !texImage->Data ) {
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ );
- return;
- }
-
-
- if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- assert(level == 0);
- assert(hwlevel == 0);
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__);
- r200UploadRectSubImage( rmesa, t, texImage, x, y, width, height );
- return;
- }
- else if (texImage->IsClientData) {
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is in GART client storage\n",
- __FUNCTION__);
- r200UploadGARTClientSubImage( rmesa, t, texImage, hwlevel,
- x, y, width, height );
- return;
- }
- else if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is in normal memory\n",
- __FUNCTION__);
-
-
- imageWidth = texImage->Width;
- imageHeight = texImage->Height;
-
- offset = t->bufAddr + t->base.totalSize / 6 * face;
-
- if ( R200_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
- GLint imageX = 0;
- GLint imageY = 0;
- GLint blitX = t->image[face][hwlevel].x;
- GLint blitY = t->image[face][hwlevel].y;
- GLint blitWidth = t->image[face][hwlevel].width;
- GLint blitHeight = t->image[face][hwlevel].height;
- fprintf( stderr, " upload image: %d,%d at %d,%d\n",
- imageWidth, imageHeight, imageX, imageY );
- fprintf( stderr, " upload blit: %d,%d at %d,%d\n",
- blitWidth, blitHeight, blitX, blitY );
- fprintf( stderr, " blit ofs: 0x%07x level: %d/%d\n",
- (GLuint)offset, hwlevel, level );
- }
-
- t->image[face][hwlevel].data = texImage->Data;
-
- /* Init the DRM_RADEON_TEXTURE command / drm_radeon_texture_t struct.
- * NOTE: we're always use a 1KB-wide blit and I8 texture format.
- * We used to use 1, 2 and 4-byte texels and used to use the texture
- * width to dictate the blit width - but that won't work for compressed
- * textures. (Brian)
- * NOTE: can't do that with texture tiling. (sroland)
- */
- tex.offset = offset;
- tex.image = &tmp;
- /* copy (x,y,width,height,data) */
- memcpy( &tmp, &t->image[face][hwlevel], sizeof(tmp) );
-
- if (texImage->TexFormat->TexelBytes) {
- /* use multi-byte upload scheme */
- tex.height = imageHeight;
- tex.width = imageWidth;
- tex.format = t->pp_txformat & R200_TXFORMAT_FORMAT_MASK;
- if (tex.format == R200_TXFORMAT_ABGR8888) {
- /* drm will refuse abgr8888 textures. */
- tex.format = R200_TXFORMAT_ARGB8888;
- }
- tex.pitch = MAX2((texImage->Width * texImage->TexFormat->TexelBytes) / 64, 1);
- tex.offset += tmp.x & ~1023;
- tmp.x = tmp.x % 1024;
- if (t->tile_bits & R200_TXO_MICRO_TILE) {
- /* need something like "tiled coordinates" ? */
- tmp.y = tmp.x / (tex.pitch * 128) * 2;
- tmp.x = tmp.x % (tex.pitch * 128) / 2 / texImage->TexFormat->TexelBytes;
- tex.pitch |= RADEON_DST_TILE_MICRO >> 22;
- }
- else {
- tmp.x = tmp.x >> (texImage->TexFormat->TexelBytes >> 1);
- }
- if ((t->tile_bits & R200_TXO_MACRO_TILE) &&
- (texImage->Width * texImage->TexFormat->TexelBytes >= 256) &&
- ((!(t->tile_bits & R200_TXO_MICRO_TILE) && (texImage->Height >= 8)) ||
- (texImage->Height >= 16))) {
- /* weird: R200 disables macro tiling if mip width is smaller than 256 bytes,
- OR if height is smaller than 8 automatically, but if micro tiling is active
- the limit is height 16 instead ? */
- tex.pitch |= RADEON_DST_TILE_MACRO >> 22;
- }
- }
- else {
- /* In case of for instance 8x8 texture (2x2 dxt blocks), padding after the first two blocks is
- needed (only with dxt1 since 2 dxt3/dxt5 blocks already use 32 Byte). */
- /* set tex.height to 1/4 since 1 "macropixel" (dxt-block) has 4 real pixels. Needed
- so the kernel module reads the right amount of data. */
- tex.format = R200_TXFORMAT_I8; /* any 1-byte texel format */
- tex.pitch = (BLIT_WIDTH_BYTES / 64);
- tex.height = (imageHeight + 3) / 4;
- tex.width = (imageWidth + 3) / 4;
- switch (t->pp_txformat & R200_TXFORMAT_FORMAT_MASK) {
- case R200_TXFORMAT_DXT1:
- tex.width *= 8;
- break;
- case R200_TXFORMAT_DXT23:
- case R200_TXFORMAT_DXT45:
- tex.width *= 16;
- break;
- default:
- fprintf(stderr, "unknown compressed tex format in uploadSubImage\n");
- }
- }
-
- LOCK_HARDWARE( rmesa );
- do {
- ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
- &tex, sizeof(drm_radeon_texture_t) );
- if (ret) {
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n");
- usleep(1);
- }
- } while ( ret == -EAGAIN );
-
- UNLOCK_HARDWARE( rmesa );
-
- if ( ret ) {
- fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
- fprintf( stderr, " offset=0x%08x\n",
- offset );
- fprintf( stderr, " image width=%d height=%d\n",
- imageWidth, imageHeight );
- fprintf( stderr, " blit width=%d height=%d data=%p\n",
- t->image[face][hwlevel].width, t->image[face][hwlevel].height,
- t->image[face][hwlevel].data );
- exit( 1 );
- }
-}
-
-
-/**
- * Upload the texture images associated with texture \a t. This might
- * require the allocation of texture memory.
- *
- * \param rmesa Context pointer
- * \param t Texture to be uploaded
- * \param face Cube map face to be uploaded. Zero for non-cube maps.
- */
-
-int r200UploadTexImages( r200ContextPtr rmesa, r200TexObjPtr t, GLuint face )
-{
- const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
-
- if ( R200_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
- fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
- (void *)rmesa->glCtx, (void *)t->base.tObj, t->base.totalSize,
- t->base.firstLevel, t->base.lastLevel );
- }
-
- if ( !t || t->base.totalSize == 0 || t->image_override )
- return 0;
-
- if (R200_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "%s: Syncing\n", __FUNCTION__ );
- r200Finish( rmesa->glCtx );
- }
-
- LOCK_HARDWARE( rmesa );
-
- if ( t->base.memBlock == NULL ) {
- int heap;
-
- heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps,
- (driTextureObject *) t );
- if ( heap == -1 ) {
- UNLOCK_HARDWARE( rmesa );
- return -1;
- }
-
- /* Set the base offset of the texture image */
- t->bufAddr = rmesa->r200Screen->texOffset[heap]
- + t->base.memBlock->ofs;
- t->pp_txoffset = t->bufAddr;
-
- if (!(t->base.tObj->Image[0][0]->IsClientData)) {
- /* hope it's safe to add that here... */
- t->pp_txoffset |= t->tile_bits;
- }
-
- /* Mark this texobj as dirty on all units:
- */
- t->dirty_state = TEX_ALL;
- }
-
- /* Let the world know we've used this memory recently.
- */
- driUpdateTextureLRU( (driTextureObject *) t );
- UNLOCK_HARDWARE( rmesa );
-
- /* Upload any images that are new */
- if (t->base.dirty_images[face]) {
- int i;
- for ( i = 0 ; i < numLevels ; i++ ) {
- if ( (t->base.dirty_images[face] & (1 << (i+t->base.firstLevel))) != 0 ) {
- uploadSubImage( rmesa, t, i, 0, 0, t->image[face][i].width,
- t->image[face][i].height, face );
- }
- }
- t->base.dirty_images[face] = 0;
- }
-
-
- if (R200_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "%s: Syncing\n", __FUNCTION__ );
- r200Finish( rmesa->glCtx );
- }
-
- return 0;
-}
diff --git a/src/mesa/drivers/dri/r200/r200_texstate.c b/src/mesa/drivers/dri/r200/r200_texstate.c
index 3f9a2f4ac1..c94834752e 100644
--- a/src/mesa/drivers/dri/r200/r200_texstate.c
+++ b/src/mesa/drivers/dri/r200/r200_texstate.c
@@ -37,9 +37,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/context.h"
#include "main/macros.h"
#include "main/texformat.h"
+#include "main/teximage.h"
#include "main/texobj.h"
#include "main/enums.h"
+#include "radeon_common.h"
+#include "radeon_mipmap_tree.h"
#include "r200_context.h"
#include "r200_state.h"
#include "r200_ioctl.h"
@@ -139,257 +142,6 @@ static const struct tx_table tx_table_le[] =
#undef _ALPHA
#undef _INVALID
-/**
- * This function computes the number of bytes of storage needed for
- * the given texture object (all mipmap levels, all cube faces).
- * The \c image[face][level].x/y/width/height parameters for upload/blitting
- * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
- * too.
- *
- * \param rmesa Context pointer
- * \param tObj GL texture object whose images are to be posted to
- * hardware state.
- */
-static void r200SetTexImages( r200ContextPtr rmesa,
- struct gl_texture_object *tObj )
-{
- r200TexObjPtr t = (r200TexObjPtr)tObj->DriverData;
- const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
- GLint curOffset, blitWidth;
- GLint i, texelBytes;
- GLint numLevels;
- GLint log2Width, log2Height, log2Depth;
-
- /* Set the hardware texture format
- */
- if ( !t->image_override ) {
- if ( VALID_FORMAT( baseImage->TexFormat->MesaFormat ) ) {
- const struct tx_table *table = _mesa_little_endian() ? tx_table_le :
- tx_table_be;
-
- t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK |
- R200_TXFORMAT_ALPHA_IN_MAP);
- t->pp_txfilter &= ~R200_YUV_TO_RGB;
-
- t->pp_txformat |= table[ baseImage->TexFormat->MesaFormat ].format;
- t->pp_txfilter |= table[ baseImage->TexFormat->MesaFormat ].filter;
- }
- else {
- _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
- return;
- }
- }
-
- texelBytes = baseImage->TexFormat->TexelBytes;
-
- /* Compute which mipmap levels we really want to send to the hardware.
- */
-
- driCalculateTextureFirstLastLevel( (driTextureObject *) t );
- log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
- log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
- log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
-
- numLevels = t->base.lastLevel - t->base.firstLevel + 1;
-
- assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
-
- /* Calculate mipmap offsets and dimensions for blitting (uploading)
- * The idea is that we lay out the mipmap levels within a block of
- * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
- */
- curOffset = 0;
- blitWidth = BLIT_WIDTH_BYTES;
- t->tile_bits = 0;
-
- /* figure out if this texture is suitable for tiling. */
- if (texelBytes) {
- if (rmesa->texmicrotile && (tObj->Target != GL_TEXTURE_RECTANGLE_NV) &&
- /* texrect might be able to use micro tiling too in theory? */
- (baseImage->Height > 1)) {
- /* allow 32 (bytes) x 1 mip (which will use two times the space
- the non-tiled version would use) max if base texture is large enough */
- if ((numLevels == 1) ||
- (((baseImage->Width * texelBytes / baseImage->Height) <= 32) &&
- (baseImage->Width * texelBytes > 64)) ||
- ((baseImage->Width * texelBytes / baseImage->Height) <= 16)) {
- t->tile_bits |= R200_TXO_MICRO_TILE;
- }
- }
- if (tObj->Target != GL_TEXTURE_RECTANGLE_NV) {
- /* we can set macro tiling even for small textures, they will be untiled anyway */
- t->tile_bits |= R200_TXO_MACRO_TILE;
- }
- }
-
- for (i = 0; i < numLevels; i++) {
- const struct gl_texture_image *texImage;
- GLuint size;
-
- texImage = tObj->Image[0][i + t->base.firstLevel];
- if ( !texImage )
- break;
-
- /* find image size in bytes */
- if (texImage->IsCompressed) {
- /* need to calculate the size AFTER padding even though the texture is
- submitted without padding.
- Only handle pot textures currently - don't know if npot is even possible,
- size calculation would certainly need (trivial) adjustments.
- Align (and later pad) to 32byte, not sure what that 64byte blit width is
- good for? */
- if ((t->pp_txformat & R200_TXFORMAT_FORMAT_MASK) == R200_TXFORMAT_DXT1) {
- /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
- if ((texImage->Width + 3) < 8) /* width one block */
- size = texImage->CompressedSize * 4;
- else if ((texImage->Width + 3) < 16)
- size = texImage->CompressedSize * 2;
- else size = texImage->CompressedSize;
- }
- else /* DXT3/5, 16 bytes per block */
- if ((texImage->Width + 3) < 8)
- size = texImage->CompressedSize * 2;
- else size = texImage->CompressedSize;
- }
- else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- size = ((texImage->Width * texelBytes + 63) & ~63) * texImage->Height;
- }
- else if (t->tile_bits & R200_TXO_MICRO_TILE) {
- /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
- though the actual offset may be different (if texture is less than
- 32 bytes width) to the untiled case */
- int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
- size = (w * ((texImage->Height + 1) / 2)) * texImage->Depth;
- blitWidth = MAX2(texImage->Width, 64 / texelBytes);
- }
- else {
- int w = (texImage->Width * texelBytes + 31) & ~31;
- size = w * texImage->Height * texImage->Depth;
- blitWidth = MAX2(texImage->Width, 64 / texelBytes);
- }
- assert(size > 0);
-
- /* Align to 32-byte offset. It is faster to do this unconditionally
- * (no branch penalty).
- */
-
- curOffset = (curOffset + 0x1f) & ~0x1f;
-
- if (texelBytes) {
- t->image[0][i].x = curOffset; /* fix x and y coords up later together with offset */
- t->image[0][i].y = 0;
- t->image[0][i].width = MIN2(size / texelBytes, blitWidth);
- t->image[0][i].height = (size / texelBytes) / t->image[0][i].width;
- }
- else {
- t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
- t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
- t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES);
- t->image[0][i].height = size / t->image[0][i].width;
- }
-
-#if 0
- /* for debugging only and only applicable to non-rectangle targets */
- assert(size % t->image[0][i].width == 0);
- assert(t->image[0][i].x == 0
- || (size < BLIT_WIDTH_BYTES && t->image[0][i].height == 1));
-#endif
-
- if (0)
- fprintf(stderr,
- "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
- i, texImage->Width, texImage->Height,
- t->image[0][i].x, t->image[0][i].y,
- t->image[0][i].width, t->image[0][i].height, size, curOffset);
-
- curOffset += size;
-
- }
-
- /* Align the total size of texture memory block.
- */
- t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
-
- /* Setup remaining cube face blits, if needed */
- if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
- const GLuint faceSize = t->base.totalSize;
- GLuint face;
- /* reuse face 0 x/y/width/height - just update the offset when uploading */
- for (face = 1; face < 6; face++) {
- for (i = 0; i < numLevels; i++) {
- t->image[face][i].x = t->image[0][i].x;
- t->image[face][i].y = t->image[0][i].y;
- t->image[face][i].width = t->image[0][i].width;
- t->image[face][i].height = t->image[0][i].height;
- }
- }
- t->base.totalSize = 6 * faceSize; /* total texmem needed */
- }
-
-
- /* Hardware state:
- */
- t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
- t->pp_txfilter |= (numLevels - 1) << R200_MAX_MIP_LEVEL_SHIFT;
-
- t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
- R200_TXFORMAT_HEIGHT_MASK |
- R200_TXFORMAT_CUBIC_MAP_ENABLE |
- R200_TXFORMAT_F5_WIDTH_MASK |
- R200_TXFORMAT_F5_HEIGHT_MASK);
- t->pp_txformat |= ((log2Width << R200_TXFORMAT_WIDTH_SHIFT) |
- (log2Height << R200_TXFORMAT_HEIGHT_SHIFT));
-
- t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK);
- if (tObj->Target == GL_TEXTURE_3D) {
- t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
- t->pp_txformat_x |= R200_TEXCOORD_VOLUME;
- }
- else if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
- ASSERT(log2Width == log2Height);
- t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) |
- (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) |
-/* don't think we need this bit, if it exists at all - fglrx does not set it */
- (R200_TXFORMAT_CUBIC_MAP_ENABLE));
- t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV;
- t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
- (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
- (log2Width << R200_FACE_WIDTH_2_SHIFT) |
- (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
- (log2Width << R200_FACE_WIDTH_3_SHIFT) |
- (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
- (log2Width << R200_FACE_WIDTH_4_SHIFT) |
- (log2Height << R200_FACE_HEIGHT_4_SHIFT));
- }
- else {
- /* If we don't in fact send enough texture coordinates, q will be 1,
- * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
- */
- t->pp_txformat_x |= R200_TEXCOORD_PROJ;
- }
-
- t->pp_txsize = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << 0) |
- ((tObj->Image[0][t->base.firstLevel]->Height - 1) << 16));
-
- /* Only need to round to nearest 32 for textures, but the blitter
- * requires 64-byte aligned pitches, and we may/may not need the
- * blitter. NPOT only!
- */
- if ( !t->image_override ) {
- if (baseImage->IsCompressed)
- t->pp_txpitch = (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
- else
- t->pp_txpitch = ((tObj->Image[0][t->base.firstLevel]->Width * texelBytes) + 63) & ~(63);
- t->pp_txpitch -= 32;
- }
-
- t->dirty_state = TEX_ALL;
-
- /* FYI: r200UploadTexImages( rmesa, t ) used to be called here */
-}
-
-
-
/* ================================================================
* Texture combine functions
*/
@@ -569,7 +321,7 @@ static GLboolean r200UpdateTextureEnv( GLcontext *ctx, int unit, int slot, GLuin
assert( (texUnit->_ReallyEnabled == 0)
|| (texUnit->_Current != NULL) );
- if ( R200_DEBUG & DEBUG_TEXTURE ) {
+ if ( R200_DEBUG & RADEON_TEXTURE ) {
fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit );
}
@@ -981,20 +733,19 @@ void r200SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
{
r200ContextPtr rmesa = pDRICtx->driverPrivate;
struct gl_texture_object *tObj =
- _mesa_lookup_texture(rmesa->glCtx, texname);
- r200TexObjPtr t;
+ _mesa_lookup_texture(rmesa->radeon.glCtx, texname);
+ radeonTexObjPtr t = radeon_tex_obj(tObj);
if (!tObj)
return;
- t = (r200TexObjPtr) tObj->DriverData;
-
t->image_override = GL_TRUE;
if (!offset)
return;
- t->pp_txoffset = offset;
+ t->bo = NULL;
+ t->override_offset = offset;
t->pp_txpitch = pitch - 32;
switch (depth) {
@@ -1014,6 +765,125 @@ void r200SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
}
}
+void r200SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format,
+ __DRIdrawable *dPriv)
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ struct radeon_renderbuffer *rb;
+ radeon_texture_image *rImage;
+ radeonContextPtr radeon;
+ r200ContextPtr rmesa;
+ struct radeon_framebuffer *rfb;
+ radeonTexObjPtr t;
+ uint32_t pitch_val;
+ uint32_t internalFormat, type, format;
+
+ type = GL_BGRA;
+ format = GL_UNSIGNED_BYTE;
+ internalFormat = (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT ? 3 : 4);
+
+ radeon = pDRICtx->driverPrivate;
+ rmesa = pDRICtx->driverPrivate;
+
+ rfb = dPriv->driverPrivate;
+ texUnit = &radeon->glCtx->Texture.Unit[radeon->glCtx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(radeon->glCtx, texUnit, target);
+ texImage = _mesa_get_tex_image(radeon->glCtx, texObj, target, 0);
+
+ rImage = get_radeon_texture_image(texImage);
+ t = radeon_tex_obj(texObj);
+ if (t == NULL) {
+ return;
+ }
+
+ radeon_update_renderbuffers(pDRICtx, dPriv);
+ /* back & depth buffer are useless free them right away */
+ rb = (void*)rfb->base.Attachment[BUFFER_DEPTH].Renderbuffer;
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
+ rb = (void*)rfb->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
+ rb = rfb->color_rb[0];
+ if (rb->bo == NULL) {
+ /* Failed to BO for the buffer */
+ return;
+ }
+
+ _mesa_lock_texture(radeon->glCtx, texObj);
+ if (t->bo) {
+ radeon_bo_unref(t->bo);
+ t->bo = NULL;
+ }
+ if (rImage->bo) {
+ radeon_bo_unref(rImage->bo);
+ rImage->bo = NULL;
+ }
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = NULL;
+ }
+ if (rImage->mt) {
+ radeon_miptree_unreference(rImage->mt);
+ rImage->mt = NULL;
+ }
+ _mesa_init_teximage_fields(radeon->glCtx, target, texImage,
+ rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
+ texImage->RowStride = rb->pitch / rb->cpp;
+ texImage->TexFormat = radeonChooseTextureFormat(radeon->glCtx,
+ internalFormat,
+ type, format, 0);
+ rImage->bo = rb->bo;
+ radeon_bo_ref(rImage->bo);
+ t->bo = rb->bo;
+ radeon_bo_ref(t->bo);
+ t->tile_bits = 0;
+ t->image_override = GL_TRUE;
+ t->override_offset = 0;
+ t->pp_txpitch &= (1 << 13) -1;
+ pitch_val = rb->pitch;
+ switch (rb->cpp) {
+ case 4:
+ if (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT)
+ t->pp_txformat = tx_table_le[MESA_FORMAT_RGB888].format;
+ else
+ t->pp_txformat = tx_table_le[MESA_FORMAT_ARGB8888].format;
+ t->pp_txfilter |= tx_table_le[MESA_FORMAT_ARGB8888].filter;
+ break;
+ case 3:
+ default:
+ t->pp_txformat = tx_table_le[MESA_FORMAT_RGB888].format;
+ t->pp_txfilter |= tx_table_le[MESA_FORMAT_RGB888].filter;
+ break;
+ case 2:
+ t->pp_txformat = tx_table_le[MESA_FORMAT_RGB565].format;
+ t->pp_txfilter |= tx_table_le[MESA_FORMAT_RGB565].filter;
+ break;
+ }
+ t->pp_txsize = ((rb->base.Width - 1) << RADEON_TEX_USIZE_SHIFT)
+ | ((rb->base.Height - 1) << RADEON_TEX_VSIZE_SHIFT);
+ t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
+ t->pp_txpitch = pitch_val;
+ t->pp_txpitch -= 32;
+
+ t->validated = GL_TRUE;
+ _mesa_unlock_texture(radeon->glCtx, texObj);
+ return;
+}
+
+
+void r200SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
+{
+ r200SetTexBuffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
+}
+
+
#define REF_COLOR 1
#define REF_ALPHA 2
@@ -1207,12 +1077,43 @@ static GLboolean r200UpdateAllTexEnv( GLcontext *ctx )
R200_VOLUME_FILTER_MASK)
+static void disable_tex_obj_state( r200ContextPtr rmesa,
+ int unit )
+{
+
+ R200_STATECHANGE( rmesa, vtx );
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
+
+ R200_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_0_ENABLE << unit);
+ if (rmesa->radeon.TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) {
+ TCL_FALLBACK( rmesa->radeon.glCtx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
+ }
+
+ /* Actually want to keep all units less than max active texture
+ * enabled, right? Fix this for >2 texunits.
+ */
+
+ {
+ GLuint tmp = rmesa->TexGenEnabled;
+
+ rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
+ rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
+ rmesa->TexGenNeedNormals[unit] = GL_FALSE;
+ rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
+
+ if (tmp != rmesa->TexGenEnabled) {
+ rmesa->recheck_texgen[unit] = GL_TRUE;
+ rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
+ }
+ }
+}
static void import_tex_obj_state( r200ContextPtr rmesa,
int unit,
- r200TexObjPtr texobj )
+ radeonTexObjPtr texobj )
{
/* do not use RADEON_DB_STATE to avoid stale texture caches */
- int *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0];
+ GLuint *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0];
R200_STATECHANGE( rmesa, tex[unit] );
@@ -1225,36 +1126,21 @@ static void import_tex_obj_state( r200ContextPtr rmesa,
cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */
cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */
cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
- if (rmesa->r200Screen->drmSupportsFragShader) {
- cmd[TEX_PP_TXOFFSET_NEWDRM] = texobj->pp_txoffset;
- }
- else {
- cmd[TEX_PP_TXOFFSET_OLDDRM] = texobj->pp_txoffset;
- }
- if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) {
- int *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0];
- GLuint bytesPerFace = texobj->base.totalSize / 6;
- ASSERT(texobj->base.totalSize % 6 == 0);
+ if (texobj->base.Target == GL_TEXTURE_CUBE_MAP) {
+ GLuint *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0];
R200_STATECHANGE( rmesa, cube[unit] );
cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
- if (rmesa->r200Screen->drmSupportsFragShader) {
+ if (rmesa->radeon.radeonScreen->drmSupportsFragShader) {
/* that value is submitted twice. could change cube atom
to not include that command when new drm is used */
cmd[TEX_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
}
- cube_cmd[CUBE_PP_CUBIC_OFFSET_F1] = texobj->pp_txoffset + 1 * bytesPerFace;
- cube_cmd[CUBE_PP_CUBIC_OFFSET_F2] = texobj->pp_txoffset + 2 * bytesPerFace;
- cube_cmd[CUBE_PP_CUBIC_OFFSET_F3] = texobj->pp_txoffset + 3 * bytesPerFace;
- cube_cmd[CUBE_PP_CUBIC_OFFSET_F4] = texobj->pp_txoffset + 4 * bytesPerFace;
- cube_cmd[CUBE_PP_CUBIC_OFFSET_F5] = texobj->pp_txoffset + 5 * bytesPerFace;
}
- texobj->dirty_state &= ~(1<<unit);
}
-
static void set_texgen_matrix( r200ContextPtr rmesa,
GLuint unit,
const GLfloat *s_plane,
@@ -1366,37 +1252,36 @@ static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
if (texUnit->TexGenEnabled & S_BIT) {
- mode = texUnit->GenModeS;
+ mode = texUnit->GenS.Mode;
} else {
tgcm |= R200_TEXGEN_COMP_S << (unit * 4);
}
if (texUnit->TexGenEnabled & T_BIT) {
- if (texUnit->GenModeT != mode)
+ if (texUnit->GenT.Mode != mode)
mixed_fallback = GL_TRUE;
} else {
tgcm |= R200_TEXGEN_COMP_T << (unit * 4);
}
-
if (texUnit->TexGenEnabled & R_BIT) {
- if (texUnit->GenModeR != mode)
+ if (texUnit->GenR.Mode != mode)
mixed_fallback = GL_TRUE;
} else {
tgcm |= R200_TEXGEN_COMP_R << (unit * 4);
}
if (texUnit->TexGenEnabled & Q_BIT) {
- if (texUnit->GenModeQ != mode)
+ if (texUnit->GenQ.Mode != mode)
mixed_fallback = GL_TRUE;
} else {
tgcm |= R200_TEXGEN_COMP_Q << (unit * 4);
}
if (mixed_fallback) {
- if (R200_DEBUG & DEBUG_FALLBACKS)
+ if (R200_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
- texUnit->TexGenEnabled, texUnit->GenModeS, texUnit->GenModeT,
- texUnit->GenModeR, texUnit->GenModeQ);
+ texUnit->TexGenEnabled, texUnit->GenS.Mode, texUnit->GenT.Mode,
+ texUnit->GenR.Mode, texUnit->GenQ.Mode);
return GL_FALSE;
}
@@ -1414,10 +1299,12 @@ static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
switch (mode) {
case GL_OBJECT_LINEAR: {
GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
- texUnit->ObjectPlaneS, texUnit->ObjectPlaneT,
- texUnit->ObjectPlaneR, texUnit->ObjectPlaneQ );
+ texUnit->GenS.ObjectPlane,
+ texUnit->GenT.ObjectPlane,
+ texUnit->GenR.ObjectPlane,
+ texUnit->GenQ.ObjectPlane );
if (needtgenable & (S_BIT | T_BIT)) {
- if (R200_DEBUG & DEBUG_FALLBACKS)
+ if (R200_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "fallback mixed texgen / obj plane, 0x%x\n",
texUnit->TexGenEnabled);
return GL_FALSE;
@@ -1431,19 +1318,21 @@ static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
tgi |= R200_TEXGEN_INPUT_OBJ << inputshift;
set_texgen_matrix( rmesa, unit,
- (texUnit->TexGenEnabled & S_BIT) ? texUnit->ObjectPlaneS : I,
- (texUnit->TexGenEnabled & T_BIT) ? texUnit->ObjectPlaneT : I + 4,
- (texUnit->TexGenEnabled & R_BIT) ? texUnit->ObjectPlaneR : I + 8,
- (texUnit->TexGenEnabled & Q_BIT) ? texUnit->ObjectPlaneQ : I + 12);
+ (texUnit->TexGenEnabled & S_BIT) ? texUnit->GenS.ObjectPlane : I,
+ (texUnit->TexGenEnabled & T_BIT) ? texUnit->GenT.ObjectPlane : I + 4,
+ (texUnit->TexGenEnabled & R_BIT) ? texUnit->GenR.ObjectPlane : I + 8,
+ (texUnit->TexGenEnabled & Q_BIT) ? texUnit->GenQ.ObjectPlane : I + 12);
}
break;
case GL_EYE_LINEAR: {
GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
- texUnit->EyePlaneS, texUnit->EyePlaneT,
- texUnit->EyePlaneR, texUnit->EyePlaneQ );
+ texUnit->GenS.EyePlane,
+ texUnit->GenT.EyePlane,
+ texUnit->GenR.EyePlane,
+ texUnit->GenQ.EyePlane );
if (needtgenable & (S_BIT | T_BIT)) {
- if (R200_DEBUG & DEBUG_FALLBACKS)
+ if (R200_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "fallback mixed texgen / eye plane, 0x%x\n",
texUnit->TexGenEnabled);
return GL_FALSE;
@@ -1456,10 +1345,10 @@ static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
}
tgi |= R200_TEXGEN_INPUT_EYE << inputshift;
set_texgen_matrix( rmesa, unit,
- (texUnit->TexGenEnabled & S_BIT) ? texUnit->EyePlaneS : I,
- (texUnit->TexGenEnabled & T_BIT) ? texUnit->EyePlaneT : I + 4,
- (texUnit->TexGenEnabled & R_BIT) ? texUnit->EyePlaneR : I + 8,
- (texUnit->TexGenEnabled & Q_BIT) ? texUnit->EyePlaneQ : I + 12);
+ (texUnit->TexGenEnabled & S_BIT) ? texUnit->GenS.EyePlane : I,
+ (texUnit->TexGenEnabled & T_BIT) ? texUnit->GenT.EyePlane : I + 4,
+ (texUnit->TexGenEnabled & R_BIT) ? texUnit->GenR.EyePlane : I + 8,
+ (texUnit->TexGenEnabled & Q_BIT) ? texUnit->GenQ.EyePlane : I + 12);
}
break;
@@ -1493,9 +1382,9 @@ static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
default:
/* Unsupported mode, fallback:
*/
- if (R200_DEBUG & DEBUG_FALLBACKS)
+ if (R200_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "fallback unsupported texgen, %d\n",
- texUnit->GenModeS);
+ texUnit->GenS.Mode);
return GL_FALSE;
}
@@ -1513,52 +1402,6 @@ static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
return GL_TRUE;
}
-
-static void disable_tex( GLcontext *ctx, int unit )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit)) {
- /* Texture unit disabled */
- if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
- /* The old texture is no longer bound to this texture unit.
- * Mark it as such.
- */
-
- rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
- rmesa->state.texture.unit[unit].texobj = NULL;
- }
-
- R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_0_ENABLE << unit);
-
- R200_STATECHANGE( rmesa, vtx );
- rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
-
- if (rmesa->TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) {
- TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
- }
-
- /* Actually want to keep all units less than max active texture
- * enabled, right? Fix this for >2 texunits.
- */
-
- {
- GLuint tmp = rmesa->TexGenEnabled;
-
- rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
- rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
- rmesa->TexGenNeedNormals[unit] = GL_FALSE;
- rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
-
- if (tmp != rmesa->TexGenEnabled) {
- rmesa->recheck_texgen[unit] = GL_TRUE;
- rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
- }
- }
- }
-}
-
void set_re_cntl_d3d( GLcontext *ctx, int unit, GLboolean use_d3d )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
@@ -1575,237 +1418,169 @@ void set_re_cntl_d3d( GLcontext *ctx, int unit, GLboolean use_d3d )
}
}
-static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
+/**
+ * Compute the cached hardware register values for the given texture object.
+ *
+ * \param rmesa Context pointer
+ * \param t the r300 texture object
+ */
+static void setup_hardware_state(r200ContextPtr rmesa, radeonTexObj *t)
{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
-
- /* Need to load the 2d images associated with this unit.
- */
- if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
- t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
- t->base.dirty_images[0] = ~0;
+ int firstlevel = t->mt ? t->mt->firstLevel : 0;
+ const struct gl_texture_image *firstImage = t->base.Image[0][firstlevel];
+ GLint log2Width, log2Height, log2Depth, texelBytes;
+
+ if ( t->bo ) {
+ return;
}
- ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
+ log2Width = firstImage->WidthLog2;
+ log2Height = firstImage->HeightLog2;
+ log2Depth = firstImage->DepthLog2;
+ texelBytes = firstImage->TexFormat->TexelBytes;
- if ( t->base.dirty_images[0] ) {
- R200_FIREVERTICES( rmesa );
- r200SetTexImages( rmesa, tObj );
- r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
- if ( !t->base.memBlock && !t->image_override )
- return GL_FALSE;
- }
- set_re_cntl_d3d( ctx, unit, GL_FALSE );
-
- return GL_TRUE;
-}
-
-#if ENABLE_HW_3D_TEXTURE
-static GLboolean enable_tex_3d( GLcontext *ctx, int unit )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
-
- /* Need to load the 3d images associated with this unit.
- */
- if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
- t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
- t->base.dirty_images[0] = ~0;
+ if (!t->image_override) {
+ if (VALID_FORMAT(firstImage->TexFormat->MesaFormat)) {
+ const struct tx_table *table = _mesa_little_endian() ? tx_table_le :
+ tx_table_be;
+
+ t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK |
+ R200_TXFORMAT_ALPHA_IN_MAP);
+ t->pp_txfilter &= ~R200_YUV_TO_RGB;
+
+ t->pp_txformat |= table[ firstImage->TexFormat->MesaFormat ].format;
+ t->pp_txfilter |= table[ firstImage->TexFormat->MesaFormat ].filter;
+ } else {
+ _mesa_problem(NULL, "unexpected texture format in %s",
+ __FUNCTION__);
+ return;
+ }
}
+
+ t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
+ t->pp_txfilter |= (t->mt->lastLevel - t->mt->firstLevel) << R200_MAX_MIP_LEVEL_SHIFT;
+
+ t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
+ R200_TXFORMAT_HEIGHT_MASK |
+ R200_TXFORMAT_CUBIC_MAP_ENABLE |
+ R200_TXFORMAT_F5_WIDTH_MASK |
+ R200_TXFORMAT_F5_HEIGHT_MASK);
+ t->pp_txformat |= ((log2Width << R200_TXFORMAT_WIDTH_SHIFT) |
+ (log2Height << R200_TXFORMAT_HEIGHT_SHIFT));
+
+ t->tile_bits = 0;
+
+ t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK);
+ if (t->base.Target == GL_TEXTURE_3D) {
+ t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
+ t->pp_txformat_x |= R200_TEXCOORD_VOLUME;
- ASSERT(tObj->Target == GL_TEXTURE_3D);
-
- /* R100 & R200 do not support mipmaps for 3D textures.
- */
- if ( (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR) ) {
- return GL_FALSE;
}
-
- if ( t->base.dirty_images[0] ) {
- R200_FIREVERTICES( rmesa );
- r200SetTexImages( rmesa, tObj );
- r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
- if ( !t->base.memBlock )
- return GL_FALSE;
+ else if (t->base.Target == GL_TEXTURE_CUBE_MAP) {
+ ASSERT(log2Width == log2Height);
+ t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) |
+ (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) |
+ /* don't think we need this bit, if it exists at all - fglrx does not set it */
+ (R200_TXFORMAT_CUBIC_MAP_ENABLE));
+ t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV;
+ t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
+ (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
+ (log2Width << R200_FACE_WIDTH_2_SHIFT) |
+ (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
+ (log2Width << R200_FACE_WIDTH_3_SHIFT) |
+ (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
+ (log2Width << R200_FACE_WIDTH_4_SHIFT) |
+ (log2Height << R200_FACE_HEIGHT_4_SHIFT));
}
-
- set_re_cntl_d3d( ctx, unit, GL_TRUE );
-
- return GL_TRUE;
-}
-#endif
-
-static GLboolean enable_tex_cube( GLcontext *ctx, int unit )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
- GLuint face;
-
- /* Need to load the 2d images associated with this unit.
- */
- if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
- t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
- for (face = 0; face < 6; face++)
- t->base.dirty_images[face] = ~0;
+ else {
+ /* If we don't in fact send enough texture coordinates, q will be 1,
+ * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
+ */
+ t->pp_txformat_x |= R200_TEXCOORD_PROJ;
}
- ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
+ t->pp_txsize = (((firstImage->Width - 1) << R200_PP_TX_WIDTHMASK_SHIFT)
+ | ((firstImage->Height - 1) << R200_PP_TX_HEIGHTMASK_SHIFT));
- if ( t->base.dirty_images[0] || t->base.dirty_images[1] ||
- t->base.dirty_images[2] || t->base.dirty_images[3] ||
- t->base.dirty_images[4] || t->base.dirty_images[5] ) {
- /* flush */
- R200_FIREVERTICES( rmesa );
- /* layout memory space, once for all faces */
- r200SetTexImages( rmesa, tObj );
- }
-
- /* upload (per face) */
- for (face = 0; face < 6; face++) {
- if (t->base.dirty_images[face]) {
- r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, face );
- }
- }
-
- if ( !t->base.memBlock ) {
- /* texmem alloc failed, use s/w fallback */
- return GL_FALSE;
+ if ( !t->image_override ) {
+ if (firstImage->IsCompressed)
+ t->pp_txpitch = (firstImage->Width + 63) & ~(63);
+ else
+ t->pp_txpitch = ((firstImage->Width * texelBytes) + 63) & ~(63);
+ t->pp_txpitch -= 32;
}
- set_re_cntl_d3d( ctx, unit, GL_TRUE );
-
- return GL_TRUE;
-}
-
-static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
-
- if (!(t->pp_txformat & R200_TXFORMAT_NON_POWER2)) {
+ if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
- t->base.dirty_images[0] = ~0;
- }
-
- ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
-
- if ( t->base.dirty_images[0] ) {
- R200_FIREVERTICES( rmesa );
- r200SetTexImages( rmesa, tObj );
- r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
- if ( !t->base.memBlock &&
- !t->image_override &&
- !rmesa->prefer_gart_client_texturing )
- return GL_FALSE;
}
- set_re_cntl_d3d( ctx, unit, GL_FALSE );
-
- return GL_TRUE;
}
-
-static GLboolean update_tex_common( GLcontext *ctx, int unit )
+static GLboolean r200_validate_texture(GLcontext *ctx, struct gl_texture_object *texObj, int unit)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
-
- /* Fallback if there's a texture border */
- if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 )
- return GL_FALSE;
-
- /* Update state if this is a different texture object to last
- * time.
- */
- if ( rmesa->state.texture.unit[unit].texobj != t ) {
- if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
- /* The old texture is no longer bound to this texture unit.
- * Mark it as such.
- */
+ radeonTexObj *t = radeon_tex_obj(texObj);
- rmesa->state.texture.unit[unit].texobj->base.bound &=
- ~(1UL << unit);
- }
-
- rmesa->state.texture.unit[unit].texobj = t;
- t->base.bound |= (1UL << unit);
- t->dirty_state |= 1<<unit;
- driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
- }
-
-
- /* Newly enabled?
- */
- if ( 1|| !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit))) {
- R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << unit;
-
- R200_STATECHANGE( rmesa, vtx );
- rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
- rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3);
+ if (!radeon_validate_texture_miptree(ctx, texObj))
+ return GL_FALSE;
- rmesa->recheck_texgen[unit] = GL_TRUE;
- }
+ r200_validate_texgen(ctx, unit);
+ /* Configure the hardware registers (more precisely, the cached version
+ * of the hardware registers). */
+ setup_hardware_state(rmesa, t);
+
+ if (texObj->Target == GL_TEXTURE_RECTANGLE_NV ||
+ texObj->Target == GL_TEXTURE_2D ||
+ texObj->Target == GL_TEXTURE_1D)
+ set_re_cntl_d3d( ctx, unit, GL_FALSE );
+ else
+ set_re_cntl_d3d( ctx, unit, GL_TRUE );
+ R200_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << unit;
+
+ R200_STATECHANGE( rmesa, vtx );
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3);
- if (t->dirty_state & (1<<unit)) {
- import_tex_obj_state( rmesa, unit, t );
- }
+ rmesa->recheck_texgen[unit] = GL_TRUE;
+ import_tex_obj_state( rmesa, unit, t );
if (rmesa->recheck_texgen[unit]) {
GLboolean fallback = !r200_validate_texgen( ctx, unit );
TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
rmesa->recheck_texgen[unit] = 0;
- rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+ rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
}
- FALLBACK( rmesa, R200_FALLBACK_BORDER_MODE, t->border_fallback );
- return !t->border_fallback;
-}
+ t->validated = GL_TRUE;
+ FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
+ return !t->border_fallback;
+}
-static GLboolean r200UpdateTextureUnit( GLcontext *ctx, int unit )
+static GLboolean r200UpdateTextureUnit(GLcontext *ctx, int unit)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint unitneeded = rmesa->state.texture.unit[unit].unitneeded;
- if ( unitneeded & (TEXTURE_RECT_BIT) ) {
- return (enable_tex_rect( ctx, unit ) &&
- update_tex_common( ctx, unit ));
- }
- else if ( unitneeded & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
- return (enable_tex_2d( ctx, unit ) &&
- update_tex_common( ctx, unit ));
- }
-#if ENABLE_HW_3D_TEXTURE
- else if ( unitneeded & (TEXTURE_3D_BIT) ) {
- return (enable_tex_3d( ctx, unit ) &&
- update_tex_common( ctx, unit ));
- }
-#endif
- else if ( unitneeded & (TEXTURE_CUBE_BIT) ) {
- return (enable_tex_cube( ctx, unit ) &&
- update_tex_common( ctx, unit ));
- }
- else if ( unitneeded ) {
- return GL_FALSE;
- }
- else {
- disable_tex( ctx, unit );
- return GL_TRUE;
+ if (!unitneeded) {
+ /* disable the unit */
+ disable_tex_obj_state(rmesa, unit);
+ return GL_TRUE;
}
+
+ if (!r200_validate_texture(ctx, ctx->Texture.Unit[unit]._Current, unit)) {
+ _mesa_warning(ctx,
+ "failed to validate texture for unit %d.\n",
+ unit);
+ rmesa->state.texture.unit[unit].texobj = NULL;
+ return GL_FALSE;
+ }
+
+ rmesa->state.texture.unit[unit].texobj = radeon_tex_obj(ctx->Texture.Unit[unit]._Current);
+ return GL_TRUE;
}
@@ -1846,11 +1621,11 @@ void r200UpdateTextureState( GLcontext *ctx )
FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok );
- if (rmesa->TclFallback)
+ if (rmesa->radeon.TclFallback)
r200ChooseVertexState( ctx );
- if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200) {
+ if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) {
/*
* T0 hang workaround -------------
@@ -1863,7 +1638,7 @@ void r200UpdateTextureState( GLcontext *ctx )
R200_STATECHANGE(rmesa, tex[1]);
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE;
if (!(rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_1_ENABLE))
- rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
+ rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= R200_TXFORMAT_LOOKUP_DISABLE;
}
else if (!ctx->ATIFragmentShader._Enabled) {
diff --git a/src/mesa/drivers/dri/r200/r200_vertprog.c b/src/mesa/drivers/dri/r200/r200_vertprog.c
index 562992fbb5..11405d7cae 100644
--- a/src/mesa/drivers/dri/r200/r200_vertprog.c
+++ b/src/mesa/drivers/dri/r200/r200_vertprog.c
@@ -202,7 +202,7 @@ static unsigned long t_dst(struct prog_dst_register *dst)
}
}
-static unsigned long t_src_class(enum register_file file)
+static unsigned long t_src_class(gl_register_file file)
{
switch(file){
@@ -290,7 +290,7 @@ static unsigned long t_src(struct r200_vertex_program *vp, struct prog_src_regis
t_swizzle(GET_SWZ(src->Swizzle, 2)),
t_swizzle(GET_SWZ(src->Swizzle, 3)),
t_src_class(src->File),
- src->NegateBase) | (src->RelAddr << 4);
+ src->Negate) | (src->RelAddr << 4);
}
static unsigned long t_src_scalar(struct r200_vertex_program *vp, struct prog_src_register *src)
@@ -302,7 +302,7 @@ static unsigned long t_src_scalar(struct r200_vertex_program *vp, struct prog_sr
t_swizzle(GET_SWZ(src->Swizzle, 0)),
t_swizzle(GET_SWZ(src->Swizzle, 0)),
t_src_class(src->File),
- src->NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src->RelAddr << 4);
+ src->Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src->RelAddr << 4);
}
static unsigned long t_opcode(enum prog_opcode opcode)
@@ -423,7 +423,7 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
~(VERT_BIT_POS | VERT_BIT_NORMAL | VERT_BIT_COLOR0 | VERT_BIT_COLOR1 |
VERT_BIT_FOG | VERT_BIT_TEX0 | VERT_BIT_TEX1 | VERT_BIT_TEX2 |
VERT_BIT_TEX3 | VERT_BIT_TEX4 | VERT_BIT_TEX5)) != 0) {
- if (R200_DEBUG & DEBUG_FALLBACKS) {
+ if (R200_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "can't handle vert prog inputs 0x%x\n",
mesa_vp->Base.InputsRead);
}
@@ -436,7 +436,7 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
(1 << VERT_RESULT_FOGC) | (1 << VERT_RESULT_TEX0) | (1 << VERT_RESULT_TEX1) |
(1 << VERT_RESULT_TEX2) | (1 << VERT_RESULT_TEX3) | (1 << VERT_RESULT_TEX4) |
(1 << VERT_RESULT_TEX5) | (1 << VERT_RESULT_PSIZ))) != 0) {
- if (R200_DEBUG & DEBUG_FALLBACKS) {
+ if (R200_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "can't handle vert prog outputs 0x%x\n",
mesa_vp->Base.OutputsWritten);
}
@@ -551,7 +551,7 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
if (mesa_vp->Base.InputsRead & (1 << i)) {
array_count++;
if (array_count > 12) {
- if (R200_DEBUG & DEBUG_FALLBACKS) {
+ if (R200_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "more than 12 attribs used in vert prog\n");
}
return GL_FALSE;
@@ -571,13 +571,13 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
}
if (!(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_HPOS))) {
- if (R200_DEBUG & DEBUG_FALLBACKS) {
+ if (R200_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "can't handle vert prog without position output\n");
}
return GL_FALSE;
}
if (free_inputs & 1) {
- if (R200_DEBUG & DEBUG_FALLBACKS) {
+ if (R200_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "can't handle vert prog without position input\n");
}
return GL_FALSE;
@@ -700,7 +700,7 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
SWIZZLE_ZERO,
t_src_class(src[0].File),
- src[0].NegateBase) | (src[0].RelAddr << 4);
+ src[0].Negate) | (src[0].RelAddr << 4);
o_inst->src1 = UNUSED_SRC_0;
o_inst->src2 = UNUSED_SRC_0;
}
@@ -712,12 +712,12 @@ static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_verte
t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO,
t_src_class(src[0].File),
- src[0].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+ src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
SWIZZLE_ZERO, SWIZZLE_ZERO,
t_swizzle(GET_SWZ(src[1].Swizzle, 0)), SWIZZLE_ZERO,
t_src_class(src[1].File),
- src[1].NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
+ src[1].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
o_inst->src2 = UNUSED_SRC_1;
o_inst++;
@@ -766,11 +766,11 @@ if ((o_inst - vp->instr) == 31) {
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X,
t_src_class(src[1].File),
- src[1].NegateBase) | (src[1].RelAddr << 4);
+ src[1].Negate) | (src[1].RelAddr << 4);
o_inst->src2 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y,
t_src_class(src[1].File),
- src[1].NegateBase) | (src[1].RelAddr << 4);
+ src[1].Negate) | (src[1].RelAddr << 4);
}
else {
o_inst->src1 = t_src(vp, &src[1]);
@@ -792,7 +792,7 @@ else {
t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
SWIZZLE_ZERO,
t_src_class(src[0].File),
- src[0].NegateBase) | (src[0].RelAddr << 4);
+ src[0].Negate) | (src[0].RelAddr << 4);
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
@@ -800,7 +800,7 @@ else {
t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
SWIZZLE_ZERO,
t_src_class(src[1].File),
- src[1].NegateBase) | (src[1].RelAddr << 4);
+ src[1].Negate) | (src[1].RelAddr << 4);
o_inst->src2 = UNUSED_SRC_1;
goto next;
@@ -815,7 +815,7 @@ else {
t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
VSF_IN_COMPONENT_ONE,
t_src_class(src[0].File),
- src[0].NegateBase) | (src[0].RelAddr << 4);
+ src[0].Negate) | (src[0].RelAddr << 4);
o_inst->src1 = t_src(vp, &src[1]);
o_inst->src2 = UNUSED_SRC_1;
goto next;
@@ -831,7 +831,7 @@ else {
t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
t_swizzle(GET_SWZ(src[1].Swizzle, 3)),
t_src_class(src[1].File),
- (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
+ (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
o_inst->src2 = UNUSED_SRC_1;
goto next;
@@ -846,7 +846,7 @@ else {
t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
t_swizzle(GET_SWZ(src[0].Swizzle, 3)),
t_src_class(src[0].File),
- (!src[0].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
+ (!src[0].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4);
o_inst->src2 = UNUSED_SRC_1;
goto next;
@@ -874,7 +874,7 @@ else {
VSF_IN_COMPONENT_W,
VSF_IN_CLASS_TMP,
/* Not 100% sure about this */
- (!src[0].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
+ (!src[0].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/);
o_inst->src2 = UNUSED_SRC_0;
u_temp_i--;
@@ -899,7 +899,7 @@ else {
t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x
t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
t_src_class(src[0].File),
- src[0].NegateBase) | (src[0].RelAddr << 4);
+ src[0].Negate) | (src[0].RelAddr << 4);
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]),
t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z
@@ -907,7 +907,7 @@ else {
t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y
t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w
t_src_class(src[1].File),
- src[1].NegateBase) | (src[1].RelAddr << 4);
+ src[1].Negate) | (src[1].RelAddr << 4);
o_inst->src2 = UNUSED_SRC_1;
o_inst++;
@@ -922,7 +922,7 @@ else {
t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x
t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w
t_src_class(src[1].File),
- (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
+ (!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4);
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]),
t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z
@@ -930,7 +930,7 @@ else {
t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y
t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w
t_src_class(src[0].File),
- src[0].NegateBase) | (src[0].RelAddr << 4);
+ src[0].Negate) | (src[0].RelAddr << 4);
o_inst->src2 = MAKE_VSF_SOURCE(u_temp_i+1,
VSF_IN_COMPONENT_X,
@@ -1070,7 +1070,7 @@ else {
mesa_vp->Base.NumTemporaries + u_temp_used;
}
if ((mesa_vp->Base.NumTemporaries + u_temp_used) > R200_VSF_MAX_TEMPS) {
- if (R200_DEBUG & DEBUG_FALLBACKS) {
+ if (R200_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "Ran out of temps, num temps %d, us %d\n", mesa_vp->Base.NumTemporaries, u_temp_used);
}
return GL_FALSE;
@@ -1078,7 +1078,7 @@ else {
u_temp_i = R200_VSF_MAX_TEMPS - 1;
if(o_inst - vp->instr >= R200_VSF_MAX_INST) {
mesa_vp->Base.NumNativeInstructions = 129;
- if (R200_DEBUG & DEBUG_FALLBACKS) {
+ if (R200_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "more than 128 native instructions\n");
}
return GL_FALSE;
@@ -1110,9 +1110,9 @@ void r200SetupVertexProg( GLcontext *ctx ) {
}
/* could optimize setting up vertex progs away for non-tcl hw */
fallback = !(vp->native && r200VertexProgUpdateParams(ctx, vp) &&
- rmesa->r200Screen->drmSupportsVertexProgram);
+ rmesa->radeon.radeonScreen->drmSupportsVertexProgram);
TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, fallback);
- if (rmesa->TclFallback) return;
+ if (rmesa->radeon.TclFallback) return;
R200_STATECHANGE( rmesa, vap );
/* FIXME: fglrx sets R200_VAP_SINGLE_BUF_STATE_ENABLE too. Do we need it?
diff --git a/src/mesa/drivers/dri/r200/radeon_bo_legacy.c b/src/mesa/drivers/dri/r200/radeon_bo_legacy.c
new file mode 120000
index 0000000000..79ad050e6b
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_bo_legacy.c
@@ -0,0 +1 @@
+../radeon/radeon_bo_legacy.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_bo_legacy.h b/src/mesa/drivers/dri/r200/radeon_bo_legacy.h
new file mode 120000
index 0000000000..83b0f7ffab
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_bo_legacy.h
@@ -0,0 +1 @@
+../radeon/radeon_bo_legacy.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_bocs_wrapper.h b/src/mesa/drivers/dri/r200/radeon_bocs_wrapper.h
new file mode 120000
index 0000000000..ca894b2443
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_bocs_wrapper.h
@@ -0,0 +1 @@
+../radeon/radeon_bocs_wrapper.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_chipset.h b/src/mesa/drivers/dri/r200/radeon_chipset.h
new file mode 120000
index 0000000000..eba99001ff
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_chipset.h
@@ -0,0 +1 @@
+../radeon/radeon_chipset.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_cmdbuf.h b/src/mesa/drivers/dri/r200/radeon_cmdbuf.h
new file mode 120000
index 0000000000..a799e1dc6d
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_cmdbuf.h
@@ -0,0 +1 @@
+../radeon/radeon_cmdbuf.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_common.c b/src/mesa/drivers/dri/r200/radeon_common.c
new file mode 120000
index 0000000000..67b19ba940
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_common.c
@@ -0,0 +1 @@
+../radeon/radeon_common.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_common.h b/src/mesa/drivers/dri/r200/radeon_common.h
new file mode 120000
index 0000000000..5bcb696a9f
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_common.h
@@ -0,0 +1 @@
+../radeon/radeon_common.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_common_context.c b/src/mesa/drivers/dri/r200/radeon_common_context.c
new file mode 120000
index 0000000000..86800f3819
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_common_context.c
@@ -0,0 +1 @@
+../radeon/radeon_common_context.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_common_context.h b/src/mesa/drivers/dri/r200/radeon_common_context.h
new file mode 120000
index 0000000000..4d66312550
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_common_context.h
@@ -0,0 +1 @@
+../radeon/radeon_common_context.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_cs_legacy.c b/src/mesa/drivers/dri/r200/radeon_cs_legacy.c
new file mode 120000
index 0000000000..006720f8a4
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_cs_legacy.c
@@ -0,0 +1 @@
+../radeon/radeon_cs_legacy.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_cs_legacy.h b/src/mesa/drivers/dri/r200/radeon_cs_legacy.h
new file mode 120000
index 0000000000..a5f95e0a3d
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_cs_legacy.h
@@ -0,0 +1 @@
+../radeon/radeon_cs_legacy.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_cs_space_drm.c b/src/mesa/drivers/dri/r200/radeon_cs_space_drm.c
new file mode 120000
index 0000000000..c248ea7d1a
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_cs_space_drm.c
@@ -0,0 +1 @@
+../radeon/radeon_cs_space_drm.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_debug.c b/src/mesa/drivers/dri/r200/radeon_debug.c
new file mode 120000
index 0000000000..c98c2e074c
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_debug.c
@@ -0,0 +1 @@
+../radeon/radeon_debug.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_debug.h b/src/mesa/drivers/dri/r200/radeon_debug.h
new file mode 120000
index 0000000000..bd8aa28e89
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_debug.h
@@ -0,0 +1 @@
+../radeon/radeon_debug.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_dma.c b/src/mesa/drivers/dri/r200/radeon_dma.c
new file mode 120000
index 0000000000..43be000625
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_dma.c
@@ -0,0 +1 @@
+../radeon/radeon_dma.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_dma.h b/src/mesa/drivers/dri/r200/radeon_dma.h
new file mode 120000
index 0000000000..82e50634e3
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_dma.h
@@ -0,0 +1 @@
+../radeon/radeon_dma.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_fbo.c b/src/mesa/drivers/dri/r200/radeon_fbo.c
new file mode 120000
index 0000000000..0d738d8d78
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_fbo.c
@@ -0,0 +1 @@
+../radeon/radeon_fbo.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_lock.c b/src/mesa/drivers/dri/r200/radeon_lock.c
new file mode 120000
index 0000000000..af4108a8e3
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_lock.c
@@ -0,0 +1 @@
+../radeon/radeon_lock.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_lock.h b/src/mesa/drivers/dri/r200/radeon_lock.h
new file mode 120000
index 0000000000..64bdf94ee7
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_lock.h
@@ -0,0 +1 @@
+../radeon/radeon_lock.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_mipmap_tree.c b/src/mesa/drivers/dri/r200/radeon_mipmap_tree.c
new file mode 120000
index 0000000000..31c0cfbe94
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_mipmap_tree.c
@@ -0,0 +1 @@
+../radeon/radeon_mipmap_tree.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_mipmap_tree.h b/src/mesa/drivers/dri/r200/radeon_mipmap_tree.h
new file mode 120000
index 0000000000..254d50cf8c
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_mipmap_tree.h
@@ -0,0 +1 @@
+../radeon/radeon_mipmap_tree.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_queryobj.c b/src/mesa/drivers/dri/r200/radeon_queryobj.c
new file mode 120000
index 0000000000..1d6ebc1c48
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_queryobj.c
@@ -0,0 +1 @@
+../radeon/radeon_queryobj.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_queryobj.h b/src/mesa/drivers/dri/r200/radeon_queryobj.h
new file mode 120000
index 0000000000..8f6f842b0a
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_queryobj.h
@@ -0,0 +1 @@
+../radeon/radeon_queryobj.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_screen.c b/src/mesa/drivers/dri/r200/radeon_screen.c
new file mode 120000
index 0000000000..86161118dd
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_screen.c
@@ -0,0 +1 @@
+../radeon/radeon_screen.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_screen.h b/src/mesa/drivers/dri/r200/radeon_screen.h
new file mode 120000
index 0000000000..23bb6bd459
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_screen.h
@@ -0,0 +1 @@
+../radeon/radeon_screen.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_span.c b/src/mesa/drivers/dri/r200/radeon_span.c
new file mode 120000
index 0000000000..232868c4c9
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_span.c
@@ -0,0 +1 @@
+../radeon/radeon_span.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_span.h b/src/mesa/drivers/dri/r200/radeon_span.h
new file mode 120000
index 0000000000..f9d634508c
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_span.h
@@ -0,0 +1 @@
+../radeon/radeon_span.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_texture.c b/src/mesa/drivers/dri/r200/radeon_texture.c
new file mode 120000
index 0000000000..a822710915
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_texture.c
@@ -0,0 +1 @@
+../radeon/radeon_texture.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/radeon_texture.h b/src/mesa/drivers/dri/r200/radeon_texture.h
new file mode 120000
index 0000000000..17fac3d5ea
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/radeon_texture.h
@@ -0,0 +1 @@
+../radeon/radeon_texture.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/server/radeon.h b/src/mesa/drivers/dri/r200/server/radeon.h
new file mode 120000
index 0000000000..81274a54f1
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/server/radeon.h
@@ -0,0 +1 @@
+../../radeon/server/radeon.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/server/radeon_dri.c b/src/mesa/drivers/dri/r200/server/radeon_dri.c
new file mode 120000
index 0000000000..d05847d650
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/server/radeon_dri.c
@@ -0,0 +1 @@
+../../radeon/server/radeon_dri.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/server/radeon_dri.h b/src/mesa/drivers/dri/r200/server/radeon_dri.h
new file mode 120000
index 0000000000..27c591d3c9
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/server/radeon_dri.h
@@ -0,0 +1 @@
+../../radeon/server/radeon_dri.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/server/radeon_egl.c b/src/mesa/drivers/dri/r200/server/radeon_egl.c
new file mode 120000
index 0000000000..d7735a7643
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/server/radeon_egl.c
@@ -0,0 +1 @@
+../../radeon/server/radeon_egl.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/server/radeon_macros.h b/src/mesa/drivers/dri/r200/server/radeon_macros.h
new file mode 120000
index 0000000000..c56cd735b8
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/server/radeon_macros.h
@@ -0,0 +1 @@
+../../radeon/server/radeon_macros.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r200/server/radeon_reg.h b/src/mesa/drivers/dri/r200/server/radeon_reg.h
new file mode 120000
index 0000000000..e2349dcb68
--- /dev/null
+++ b/src/mesa/drivers/dri/r200/server/radeon_reg.h
@@ -0,0 +1 @@
+../../radeon/server/radeon_reg.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/.gitignore b/src/mesa/drivers/dri/r300/.gitignore
deleted file mode 100644
index 3689a6a78e..0000000000
--- a/src/mesa/drivers/dri/r300/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-radeon_chipset.h
-radeon_screen.[ch]
-radeon_span.h
-server
diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile
index 6ca934204f..5d8d6f6658 100644
--- a/src/mesa/drivers/dri/r300/Makefile
+++ b/src/mesa/drivers/dri/r300/Makefile
@@ -3,6 +3,8 @@
TOP = ../../../../..
include $(TOP)/configs/current
+CFLAGS += $(RADEON_CFLAGS)
+
LIBNAME = r300_dri.so
MINIGLX_SOURCES = server/radeon_dri.c
@@ -11,6 +13,10 @@ ifeq ($(USING_EGL), 1)
EGL_SOURCES = server/radeon_egl.c
endif
+ifeq ($(RADEON_LDFLAGS),)
+CS_SOURCES = radeon_cs_space_drm.c
+endif
+
COMMON_SOURCES = \
../../common/driverfuncs.c \
../common/mm.c \
@@ -20,67 +26,59 @@ COMMON_SOURCES = \
../common/xmlconfig.c \
../common/dri_util.c
+RADEON_COMMON_SOURCES = \
+ radeon_bo_legacy.c \
+ radeon_buffer_objects.c \
+ radeon_common_context.c \
+ radeon_common.c \
+ radeon_cs_legacy.c \
+ radeon_dma.c \
+ radeon_debug.c \
+ radeon_fbo.c \
+ radeon_lock.c \
+ radeon_mipmap_tree.c \
+ radeon_span.c \
+ radeon_queryobj.c \
+ radeon_texture.c
+
DRIVER_SOURCES = \
radeon_screen.c \
- radeon_context.c \
- radeon_ioctl.c \
- radeon_lock.c \
- radeon_span.c \
- radeon_state.c \
- r300_mem.c \
r300_context.c \
+ r300_draw.c \
r300_ioctl.c \
r300_cmdbuf.c \
r300_state.c \
r300_render.c \
- r300_texmem.c \
r300_tex.c \
r300_texstate.c \
- radeon_program.c \
- radeon_program_alu.c \
- radeon_program_pair.c \
- radeon_nqssadce.c \
r300_vertprog.c \
- r300_fragprog.c \
- r300_fragprog_swizzle.c \
- r300_fragprog_emit.c \
- r500_fragprog.c \
- r500_fragprog_emit.c \
+ r300_fragprog_common.c \
r300_shader.c \
r300_emit.c \
r300_swtcl.c \
- $(EGL_SOURCES)
+ $(RADEON_COMMON_SOURCES) \
+ $(EGL_SOURCES) \
+ $(CS_SOURCES)
C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES)
DRIVER_DEFINES = -DCOMPILE_R300 -DR200_MERGED=0 \
- -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R300
-
-SYMLINKS = \
- server/radeon_dri.c \
- server/radeon_dri.h \
- server/radeon.h \
- server/radeon_macros.h \
- server/radeon_reg.h \
- server/radeon_egl.c
-
-COMMON_SYMLINKS = \
- radeon_chipset.h \
- radeon_screen.c \
- radeon_screen.h \
- radeon_span.h
+ -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R300 \
+# -DRADEON_BO_TRACK \
+ -Wall
+
+DRI_LIB_DEPS += $(RADEON_LDFLAGS)
+
+PIPE_DRIVERS = compiler/libr300compiler.a
##### TARGETS #####
include ../Makefile.template
-server:
- mkdir -p server
-
-$(SYMLINKS): server
- @[ -e $@ ] || ln -sf ../../radeon/$@ server/
+symlinks:
-$(COMMON_SYMLINKS):
- @[ -e $@ ] || ln -sf ../radeon/$@ ./
+# Mark the archive phony so that we always check for recompilation
+.PHONY : compiler/libr300compiler.a
-symlinks: $(SYMLINKS) $(COMMON_SYMLINKS)
+compiler/libr300compiler.a:
+ cd compiler && $(MAKE)
diff --git a/src/mesa/drivers/dri/r300/compiler/Makefile b/src/mesa/drivers/dri/r300/compiler/Makefile
new file mode 100644
index 0000000000..d973844192
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/Makefile
@@ -0,0 +1,75 @@
+# src/mesa/drivers/dri/r300/compiler/Makefile
+
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = r300compiler
+
+C_SOURCES = \
+ radeon_code.c \
+ radeon_compiler.c \
+ radeon_nqssadce.c \
+ radeon_program.c \
+ radeon_program_alu.c \
+ radeon_program_pair.c \
+ r3xx_fragprog.c \
+ r300_fragprog.c \
+ r300_fragprog_swizzle.c \
+ r300_fragprog_emit.c \
+ r500_fragprog.c \
+ r500_fragprog_emit.c \
+ r3xx_vertprog.c \
+ r3xx_vertprog_dump.c \
+ \
+ memory_pool.c
+
+
+### Basic defines ###
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(CPP_SOURCES:.cpp=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+INCLUDES = \
+ -I. \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+
+
+##### TARGETS #####
+
+default: depend lib$(LIBNAME).a
+
+lib$(LIBNAME).a: $(OBJECTS) Makefile $(TOP)/configs/current
+ $(MKLIB) -o $(LIBNAME) -static $(OBJECTS)
+
+depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+ rm -f depend
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) 2> /dev/null
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+# Remove .o and backup files
+clean:
+ rm -f $(OBJECTS) lib$(LIBNAME).a depend depend.bak
+
+# Dummy target
+install:
+ @echo -n ""
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(LIBRARY_DEFINES) $< -o $@
+
+.cpp.o:
+ $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(LIBRARY_DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(LIBRARY_DEFINES) $< -o $@
+
+
+sinclude depend
diff --git a/src/mesa/drivers/dri/r300/compiler/memory_pool.c b/src/mesa/drivers/dri/r300/compiler/memory_pool.c
new file mode 100644
index 0000000000..37aa2b6579
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/memory_pool.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "memory_pool.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define POOL_LARGE_ALLOC 4096
+#define POOL_ALIGN 4
+
+
+struct memory_block {
+ struct memory_block * next;
+};
+
+void memory_pool_init(struct memory_pool * pool)
+{
+ memset(pool, 0, sizeof(struct memory_pool));
+}
+
+
+void memory_pool_destroy(struct memory_pool * pool)
+{
+ while(pool->blocks) {
+ struct memory_block * block = pool->blocks;
+ pool->blocks = block->next;
+ free(block);
+ }
+}
+
+static void refill_pool(struct memory_pool * pool)
+{
+ unsigned int blocksize = pool->total_allocated;
+ struct memory_block * newblock;
+
+ if (!blocksize)
+ blocksize = 2*POOL_LARGE_ALLOC;
+
+ newblock = (struct memory_block*)malloc(blocksize);
+ newblock->next = pool->blocks;
+ pool->blocks = newblock;
+
+ pool->head = (unsigned char*)(newblock + 1);
+ pool->end = ((unsigned char*)newblock) + blocksize;
+ pool->total_allocated += blocksize;
+}
+
+
+void * memory_pool_malloc(struct memory_pool * pool, unsigned int bytes)
+{
+ if (bytes < POOL_LARGE_ALLOC) {
+ if (pool->head + bytes > pool->end)
+ refill_pool(pool);
+
+ assert(pool->head + bytes <= pool->end);
+
+ void * ptr = pool->head;
+
+ pool->head += bytes;
+ pool->head = (unsigned char*)(((unsigned long)pool->head + POOL_ALIGN - 1) & ~(POOL_ALIGN - 1));
+
+ return ptr;
+ } else {
+ struct memory_block * block = (struct memory_block*)malloc(bytes + sizeof(struct memory_block));
+
+ block->next = pool->blocks;
+ pool->blocks = block;
+
+ return (block + 1);
+ }
+}
+
+
diff --git a/src/mesa/drivers/dri/r300/compiler/memory_pool.h b/src/mesa/drivers/dri/r300/compiler/memory_pool.h
new file mode 100644
index 0000000000..ce23c319ad
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/memory_pool.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef MEMORY_POOL_H
+#define MEMORY_POOL_H
+
+struct memory_block;
+
+/**
+ * Provides a pool of memory that can quickly be allocated from, at the
+ * cost of being unable to explicitly free one of the allocated blocks.
+ * Instead, the entire pool can be freed at once.
+ *
+ * The idea is to allow one to quickly allocate a flexible amount of
+ * memory during operations like shader compilation while avoiding
+ * reference counting headaches.
+ */
+struct memory_pool {
+ unsigned char * head;
+ unsigned char * end;
+ unsigned int total_allocated;
+ struct memory_block * blocks;
+};
+
+
+void memory_pool_init(struct memory_pool * pool);
+void memory_pool_destroy(struct memory_pool * pool);
+void * memory_pool_malloc(struct memory_pool * pool, unsigned int bytes);
+
+#endif /* MEMORY_POOL_H */
diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
new file mode 100644
index 0000000000..6c9fba4914
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2005 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "r300_fragprog.h"
+
+#include "shader/prog_parameter.h"
+
+#include "../r300_reg.h"
+
+static struct prog_src_register shadow_ambient(struct radeon_compiler * c, int tmu)
+{
+ struct prog_src_register reg = { 0, };
+
+ reg.File = PROGRAM_STATE_VAR;
+ reg.Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_SHADOW_AMBIENT, tmu);
+ reg.Swizzle = SWIZZLE_WWWW;
+ return reg;
+}
+
+/**
+ * Transform TEX, TXP, TXB, and KIL instructions in the following way:
+ * - premultiply texture coordinates for RECT
+ * - extract operand swizzles
+ * - introduce a temporary register when write masks are needed
+ */
+GLboolean r300_transform_TEX(
+ struct radeon_compiler * c,
+ struct rc_instruction* inst,
+ void* data)
+{
+ struct r300_fragment_program_compiler *compiler =
+ (struct r300_fragment_program_compiler*)data;
+
+ if (inst->I.Opcode != OPCODE_TEX &&
+ inst->I.Opcode != OPCODE_TXB &&
+ inst->I.Opcode != OPCODE_TXP &&
+ inst->I.Opcode != OPCODE_KIL)
+ return GL_FALSE;
+
+ /* ARB_shadow & EXT_shadow_funcs */
+ if (inst->I.Opcode != OPCODE_KIL &&
+ c->Program.ShadowSamplers & (1 << inst->I.TexSrcUnit)) {
+ GLuint comparefunc = GL_NEVER + compiler->state.unit[inst->I.TexSrcUnit].texture_compare_func;
+
+ if (comparefunc == GL_NEVER || comparefunc == GL_ALWAYS) {
+ inst->I.Opcode = OPCODE_MOV;
+
+ if (comparefunc == GL_ALWAYS) {
+ inst->I.SrcReg[0].File = PROGRAM_BUILTIN;
+ inst->I.SrcReg[0].Swizzle = SWIZZLE_1111;
+ } else {
+ inst->I.SrcReg[0] = shadow_ambient(c, inst->I.TexSrcUnit);
+ }
+
+ return GL_TRUE;
+ } else {
+ GLuint comparefunc = GL_NEVER + compiler->state.unit[inst->I.TexSrcUnit].texture_compare_func;
+ GLuint depthmode = compiler->state.unit[inst->I.TexSrcUnit].depth_texture_mode;
+ struct rc_instruction * inst_rcp = rc_insert_new_instruction(c, inst);
+ struct rc_instruction * inst_mad = rc_insert_new_instruction(c, inst_rcp);
+ struct rc_instruction * inst_cmp = rc_insert_new_instruction(c, inst_mad);
+ int pass, fail;
+
+ inst_rcp->I.Opcode = OPCODE_RCP;
+ inst_rcp->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_rcp->I.DstReg.Index = rc_find_free_temporary(c);
+ inst_rcp->I.DstReg.WriteMask = WRITEMASK_W;
+ inst_rcp->I.SrcReg[0] = inst->I.SrcReg[0];
+ inst_rcp->I.SrcReg[0].Swizzle = SWIZZLE_WWWW;
+
+ inst_cmp->I.DstReg = inst->I.DstReg;
+ inst->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst->I.DstReg.Index = rc_find_free_temporary(c);
+ inst->I.DstReg.WriteMask = WRITEMASK_XYZW;
+
+ inst_mad->I.Opcode = OPCODE_MAD;
+ inst_mad->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_mad->I.DstReg.Index = rc_find_free_temporary(c);
+ inst_mad->I.SrcReg[0] = inst->I.SrcReg[0];
+ inst_mad->I.SrcReg[0].Swizzle = SWIZZLE_ZZZZ;
+ inst_mad->I.SrcReg[1].File = PROGRAM_TEMPORARY;
+ inst_mad->I.SrcReg[1].Index = inst_rcp->I.DstReg.Index;
+ inst_mad->I.SrcReg[1].Swizzle = SWIZZLE_WWWW;
+ inst_mad->I.SrcReg[2].File = PROGRAM_TEMPORARY;
+ inst_mad->I.SrcReg[2].Index = inst->I.DstReg.Index;
+ if (depthmode == 0) /* GL_LUMINANCE */
+ inst_mad->I.SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z);
+ else if (depthmode == 2) /* GL_ALPHA */
+ inst_mad->I.SrcReg[2].Swizzle = SWIZZLE_WWWW;
+
+ /* Recall that SrcReg[0] is tex, SrcReg[2] is r and:
+ * r < tex <=> -tex+r < 0
+ * r >= tex <=> not (-tex+r < 0 */
+ if (comparefunc == GL_LESS || comparefunc == GL_GEQUAL)
+ inst_mad->I.SrcReg[2].Negate = inst_mad->I.SrcReg[2].Negate ^ NEGATE_XYZW;
+ else
+ inst_mad->I.SrcReg[0].Negate = inst_mad->I.SrcReg[0].Negate ^ NEGATE_XYZW;
+
+ inst_cmp->I.Opcode = OPCODE_CMP;
+ /* DstReg has been filled out above */
+ inst_cmp->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst_cmp->I.SrcReg[0].Index = inst_mad->I.DstReg.Index;
+
+ if (comparefunc == GL_LESS || comparefunc == GL_GREATER) {
+ pass = 1;
+ fail = 2;
+ } else {
+ pass = 2;
+ fail = 1;
+ }
+
+ inst_cmp->I.SrcReg[pass].File = PROGRAM_BUILTIN;
+ inst_cmp->I.SrcReg[pass].Swizzle = SWIZZLE_1111;
+ inst_cmp->I.SrcReg[fail] = shadow_ambient(c, inst->I.TexSrcUnit);
+ }
+ }
+
+ /* Hardware uses [0..1]x[0..1] range for rectangle textures
+ * instead of [0..Width]x[0..Height].
+ * Add a scaling instruction.
+ */
+ if (inst->I.Opcode != OPCODE_KIL && inst->I.TexSrcTarget == TEXTURE_RECT_INDEX) {
+ struct rc_instruction * inst_mul = rc_insert_new_instruction(c, inst->Prev);
+
+ inst_mul->I.Opcode = OPCODE_MUL;
+ inst_mul->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_mul->I.DstReg.Index = rc_find_free_temporary(c);
+ inst_mul->I.SrcReg[0] = inst->I.SrcReg[0];
+ inst_mul->I.SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst_mul->I.SrcReg[1].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_TEXRECT_FACTOR, inst->I.TexSrcUnit);
+
+ reset_srcreg(&inst->I.SrcReg[0]);
+ inst->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->I.SrcReg[0].Index = inst_mul->I.DstReg.Index;
+ }
+
+ /* Cannot write texture to output registers or with masks */
+ if (inst->I.Opcode != OPCODE_KIL &&
+ (inst->I.DstReg.File != PROGRAM_TEMPORARY || inst->I.DstReg.WriteMask != WRITEMASK_XYZW)) {
+ struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst);
+
+ inst_mov->I.Opcode = OPCODE_MOV;
+ inst_mov->I.DstReg = inst->I.DstReg;
+ inst_mov->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst_mov->I.SrcReg[0].Index = rc_find_free_temporary(c);
+
+ inst->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst->I.DstReg.Index = inst_mov->I.SrcReg[0].Index;
+ inst->I.DstReg.WriteMask = WRITEMASK_XYZW;
+ }
+
+
+ /* Cannot read texture coordinate from constants file */
+ if (inst->I.SrcReg[0].File != PROGRAM_TEMPORARY && inst->I.SrcReg[0].File != PROGRAM_INPUT) {
+ struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst->Prev);
+
+ inst_mov->I.Opcode = OPCODE_MOV;
+ inst_mov->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_mov->I.DstReg.Index = rc_find_free_temporary(c);
+ inst_mov->I.SrcReg[0] = inst->I.SrcReg[0];
+
+ reset_srcreg(&inst->I.SrcReg[0]);
+ inst->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->I.SrcReg[0].Index = inst_mov->I.DstReg.Index;
+ }
+
+ return GL_TRUE;
+}
+
+/* just some random things... */
+void r300FragmentProgramDump(struct rX00_fragment_program_code *c)
+{
+ struct r300_fragment_program_code *code = &c->code.r300;
+ int n, i, j;
+ static int pc = 0;
+
+ fprintf(stderr, "pc=%d*************************************\n", pc++);
+
+ fprintf(stderr, "Hardware program\n");
+ fprintf(stderr, "----------------\n");
+
+ 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;
+ 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,
+ alu_offset, tex_offset, alu_end, tex_end, code_addr);
+
+ if (n > 0 || (code->config & R300_PFS_CNTL_FIRST_NODE_HAS_TEX)) {
+ fprintf(stderr, " TEX:\n");
+ for (i = tex_offset;
+ i <= tex_offset + tex_end;
+ ++i) {
+ const char *instr;
+
+ switch ((code->tex.
+ inst[i] >> R300_TEX_INST_SHIFT) &
+ 15) {
+ case R300_TEX_OP_LD:
+ instr = "TEX";
+ break;
+ case R300_TEX_OP_KIL:
+ instr = "KIL";
+ break;
+ case R300_TEX_OP_TXP:
+ instr = "TXP";
+ break;
+ case R300_TEX_OP_TXB:
+ instr = "TXB";
+ break;
+ default:
+ instr = "UNKNOWN";
+ }
+
+ fprintf(stderr,
+ " %s t%i, %c%i, texture[%i] (%08x)\n",
+ instr,
+ (code->tex.
+ inst[i] >> R300_DST_ADDR_SHIFT) & 31,
+ 't',
+ (code->tex.
+ inst[i] >> R300_SRC_ADDR_SHIFT) & 31,
+ (code->tex.
+ inst[i] & R300_TEX_ID_MASK) >>
+ R300_TEX_ID_SHIFT,
+ code->tex.inst[i]);
+ }
+ }
+
+ for (i = alu_offset;
+ i <= alu_offset + alu_end; ++i) {
+ char srcc[3][10], dstc[20];
+ char srca[3][10], dsta[20];
+ char argc[3][20];
+ char arga[3][20];
+ char flags[5], tmp[10];
+
+ 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);
+
+ sprintf(srcc[j], "%c%i",
+ (regc & 32) ? 'c' : 't', regc & 31);
+ sprintf(srca[j], "%c%i",
+ (rega & 32) ? 'c' : 't', rega & 31);
+ }
+
+ dstc[0] = 0;
+ sprintf(flags, "%s%s%s",
+ (code->alu.inst[i].
+ rgb_addr & R300_ALU_DSTC_REG_X) ? "x" : "",
+ (code->alu.inst[i].
+ rgb_addr & R300_ALU_DSTC_REG_Y) ? "y" : "",
+ (code->alu.inst[i].
+ rgb_addr & R300_ALU_DSTC_REG_Z) ? "z" : "");
+ if (flags[0] != 0) {
+ sprintf(dstc, "t%i.%s ",
+ (code->alu.inst[i].
+ rgb_addr >> R300_ALU_DSTC_SHIFT) & 31,
+ flags);
+ }
+ sprintf(flags, "%s%s%s",
+ (code->alu.inst[i].
+ rgb_addr & R300_ALU_DSTC_OUTPUT_X) ? "x" : "",
+ (code->alu.inst[i].
+ rgb_addr & R300_ALU_DSTC_OUTPUT_Y) ? "y" : "",
+ (code->alu.inst[i].
+ rgb_addr & R300_ALU_DSTC_OUTPUT_Z) ? "z" : "");
+ if (flags[0] != 0) {
+ sprintf(tmp, "o%i.%s",
+ (code->alu.inst[i].
+ rgb_addr >> R300_ALU_DSTC_SHIFT) & 31,
+ flags);
+ strcat(dstc, tmp);
+ }
+
+ dsta[0] = 0;
+ if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_REG) {
+ sprintf(dsta, "t%i.w ",
+ (code->alu.inst[i].
+ alpha_addr >> R300_ALU_DSTA_SHIFT) & 31);
+ }
+ if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_OUTPUT) {
+ sprintf(tmp, "o%i.w ",
+ (code->alu.inst[i].
+ alpha_addr >> R300_ALU_DSTA_SHIFT) & 31);
+ strcat(dsta, tmp);
+ }
+ if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_DEPTH) {
+ strcat(dsta, "Z");
+ }
+
+ fprintf(stderr,
+ "%3i: xyz: %3s %3s %3s -> %-20s (%08x)\n"
+ " w: %3s %3s %3s -> %-20s (%08x)\n", i,
+ srcc[0], srcc[1], srcc[2], dstc,
+ code->alu.inst[i].rgb_addr, srca[0], srca[1],
+ srca[2], dsta, code->alu.inst[i].alpha_addr);
+
+ for (j = 0; j < 3; ++j) {
+ int regc = code->alu.inst[i].rgb_inst >> (j * 7);
+ int rega = code->alu.inst[i].alpha_inst >> (j * 7);
+ int d;
+ char buf[20];
+
+ d = regc & 31;
+ if (d < 12) {
+ switch (d % 4) {
+ case R300_ALU_ARGC_SRC0C_XYZ:
+ sprintf(buf, "%s.xyz",
+ srcc[d / 4]);
+ break;
+ case R300_ALU_ARGC_SRC0C_XXX:
+ sprintf(buf, "%s.xxx",
+ srcc[d / 4]);
+ break;
+ case R300_ALU_ARGC_SRC0C_YYY:
+ sprintf(buf, "%s.yyy",
+ srcc[d / 4]);
+ break;
+ case R300_ALU_ARGC_SRC0C_ZZZ:
+ sprintf(buf, "%s.zzz",
+ srcc[d / 4]);
+ break;
+ }
+ } else if (d < 15) {
+ sprintf(buf, "%s.www", srca[d - 12]);
+ } else if (d == 20) {
+ sprintf(buf, "0.0");
+ } else if (d == 21) {
+ sprintf(buf, "1.0");
+ } else if (d == 22) {
+ sprintf(buf, "0.5");
+ } else if (d >= 23 && d < 32) {
+ d -= 23;
+ switch (d / 3) {
+ case 0:
+ sprintf(buf, "%s.yzx",
+ srcc[d % 3]);
+ break;
+ case 1:
+ sprintf(buf, "%s.zxy",
+ srcc[d % 3]);
+ break;
+ case 2:
+ sprintf(buf, "%s.Wzy",
+ srcc[d % 3]);
+ break;
+ }
+ } else {
+ sprintf(buf, "%i", d);
+ }
+
+ sprintf(argc[j], "%s%s%s%s",
+ (regc & 32) ? "-" : "",
+ (regc & 64) ? "|" : "",
+ buf, (regc & 64) ? "|" : "");
+
+ d = rega & 31;
+ if (d < 9) {
+ sprintf(buf, "%s.%c", srcc[d / 3],
+ 'x' + (char)(d % 3));
+ } else if (d < 12) {
+ sprintf(buf, "%s.w", srca[d - 9]);
+ } else if (d == 16) {
+ sprintf(buf, "0.0");
+ } else if (d == 17) {
+ sprintf(buf, "1.0");
+ } else if (d == 18) {
+ sprintf(buf, "0.5");
+ } else {
+ sprintf(buf, "%i", d);
+ }
+
+ sprintf(arga[j], "%s%s%s%s",
+ (rega & 32) ? "-" : "",
+ (rega & 64) ? "|" : "",
+ buf, (rega & 64) ? "|" : "");
+ }
+
+ fprintf(stderr, " xyz: %8s %8s %8s op: %08x\n"
+ " w: %8s %8s %8s op: %08x\n",
+ argc[0], argc[1], argc[2],
+ code->alu.inst[i].rgb_inst, arga[0], arga[1],
+ arga[2], code->alu.inst[i].alpha_inst);
+ }
+ }
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.h b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.h
new file mode 100644
index 0000000000..0ac46dbd9c
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * Authors:
+ * Ben Skeggs <darktama@iinet.net.au>
+ * Jerome Glisse <j.glisse@gmail.com>
+ */
+#ifndef __R300_FRAGPROG_H_
+#define __R300_FRAGPROG_H_
+
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+
+#include "radeon_compiler.h"
+#include "radeon_program.h"
+
+
+extern void r300BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler);
+
+extern void r300FragmentProgramDump(struct rX00_fragment_program_code *c);
+
+extern GLboolean r300_transform_TEX(struct radeon_compiler * c, struct rc_instruction* inst, void* data);
+
+#endif
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
index 9f0b7e3534..305dc074ee 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog_emit.c
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
@@ -40,57 +40,43 @@
#include "r300_fragprog.h"
+#include "../r300_reg.h"
+
#include "radeon_program_pair.h"
#include "r300_fragprog_swizzle.h"
-#include "r300_reg.h"
+struct r300_emit_state {
+ struct r300_fragment_program_compiler * compiler;
+
+ unsigned current_node : 2;
+ unsigned node_first_tex : 8;
+ unsigned node_first_alu : 8;
+ uint32_t node_flags;
+};
+
#define PROG_CODE \
- struct r300_fragment_program_compiler *c = (struct r300_fragment_program_compiler*)data; \
- struct r300_fragment_program_code *code = c->code
+ struct r300_emit_state * emit = (struct r300_emit_state*)data; \
+ struct r300_fragment_program_compiler *c = emit->compiler; \
+ struct r300_fragment_program_code *code = &c->code->code.r300
#define error(fmt, args...) do { \
- fprintf(stderr, "%s::%s(): " fmt "\n", \
+ rc_error(&c->Base, "%s::%s(): " fmt "\n", \
__FILE__, __FUNCTION__, ##args); \
} while(0)
-static GLboolean emit_const(void* data, GLuint file, GLuint index, GLuint *hwindex)
-{
- PROG_CODE;
-
- for (*hwindex = 0; *hwindex < code->const_nr; ++*hwindex) {
- if (code->constant[*hwindex].File == file &&
- code->constant[*hwindex].Index == index)
- break;
- }
-
- if (*hwindex >= code->const_nr) {
- if (*hwindex >= PFS_NUM_CONST_REGS) {
- error("Out of hw constants!\n");
- return GL_FALSE;
- }
-
- code->const_nr++;
- code->constant[*hwindex].File = file;
- code->constant[*hwindex].Index = index;
- }
-
- return GL_TRUE;
-}
-
-
/**
* Mark a temporary register as used.
*/
static void use_temporary(struct r300_fragment_program_code *code, GLuint index)
{
- if (index > code->max_temp_idx)
- code->max_temp_idx = index;
+ if (index > code->pixsize)
+ code->pixsize = index;
}
-static GLuint translate_rgb_opcode(GLuint opcode)
+static GLuint translate_rgb_opcode(struct r300_fragment_program_compiler * c, GLuint opcode)
{
switch(opcode) {
case OPCODE_CMP: return R300_ALU_OUTC_CMP;
@@ -109,7 +95,7 @@ static GLuint translate_rgb_opcode(GLuint opcode)
}
}
-static GLuint translate_alpha_opcode(GLuint opcode)
+static GLuint translate_alpha_opcode(struct r300_fragment_program_compiler * c, GLuint opcode)
{
switch(opcode) {
case OPCODE_CMP: return R300_ALU_OUTA_CMP;
@@ -138,70 +124,69 @@ static GLboolean emit_alu(void* data, struct radeon_pair_instruction* inst)
{
PROG_CODE;
- if (code->alu.length >= PFS_MAX_ALU_INST) {
+ if (code->alu.length >= R300_PFS_MAX_ALU_INST) {
error("Too many ALU instructions");
return GL_FALSE;
}
int ip = code->alu.length++;
int j;
- code->node[code->cur_node].alu_end++;
- code->alu.inst[ip].inst0 = translate_rgb_opcode(inst->RGB.Opcode);
- code->alu.inst[ip].inst2 = translate_alpha_opcode(inst->Alpha.Opcode);
+ code->alu.inst[ip].rgb_inst = translate_rgb_opcode(c, inst->RGB.Opcode);
+ code->alu.inst[ip].alpha_inst = translate_alpha_opcode(c, inst->Alpha.Opcode);
for(j = 0; j < 3; ++j) {
GLuint src = inst->RGB.Src[j].Index | (inst->RGB.Src[j].Constant << 5);
if (!inst->RGB.Src[j].Constant)
use_temporary(code, inst->RGB.Src[j].Index);
- code->alu.inst[ip].inst1 |= src << (6*j);
+ code->alu.inst[ip].rgb_addr |= src << (6*j);
src = inst->Alpha.Src[j].Index | (inst->Alpha.Src[j].Constant << 5);
if (!inst->Alpha.Src[j].Constant)
use_temporary(code, inst->Alpha.Src[j].Index);
- code->alu.inst[ip].inst3 |= src << (6*j);
+ code->alu.inst[ip].alpha_addr |= src << (6*j);
GLuint arg = r300FPTranslateRGBSwizzle(inst->RGB.Arg[j].Source, inst->RGB.Arg[j].Swizzle);
arg |= inst->RGB.Arg[j].Abs << 6;
arg |= inst->RGB.Arg[j].Negate << 5;
- code->alu.inst[ip].inst0 |= arg << (7*j);
+ code->alu.inst[ip].rgb_inst |= arg << (7*j);
arg = r300FPTranslateAlphaSwizzle(inst->Alpha.Arg[j].Source, inst->Alpha.Arg[j].Swizzle);
arg |= inst->Alpha.Arg[j].Abs << 6;
arg |= inst->Alpha.Arg[j].Negate << 5;
- code->alu.inst[ip].inst2 |= arg << (7*j);
+ code->alu.inst[ip].alpha_inst |= arg << (7*j);
}
if (inst->RGB.Saturate)
- code->alu.inst[ip].inst0 |= R300_ALU_OUTC_CLAMP;
+ code->alu.inst[ip].rgb_inst |= R300_ALU_OUTC_CLAMP;
if (inst->Alpha.Saturate)
- code->alu.inst[ip].inst2 |= R300_ALU_OUTA_CLAMP;
+ code->alu.inst[ip].alpha_inst |= R300_ALU_OUTA_CLAMP;
if (inst->RGB.WriteMask) {
use_temporary(code, inst->RGB.DestIndex);
- code->alu.inst[ip].inst1 |=
+ code->alu.inst[ip].rgb_addr |=
(inst->RGB.DestIndex << R300_ALU_DSTC_SHIFT) |
(inst->RGB.WriteMask << R300_ALU_DSTC_REG_MASK_SHIFT);
}
if (inst->RGB.OutputWriteMask) {
- code->alu.inst[ip].inst1 |= (inst->RGB.OutputWriteMask << R300_ALU_DSTC_OUTPUT_MASK_SHIFT);
- code->node[code->cur_node].flags |= R300_RGBA_OUT;
+ code->alu.inst[ip].rgb_addr |= (inst->RGB.OutputWriteMask << R300_ALU_DSTC_OUTPUT_MASK_SHIFT);
+ emit->node_flags |= R300_RGBA_OUT;
}
if (inst->Alpha.WriteMask) {
use_temporary(code, inst->Alpha.DestIndex);
- code->alu.inst[ip].inst3 |=
+ code->alu.inst[ip].alpha_addr |=
(inst->Alpha.DestIndex << R300_ALU_DSTA_SHIFT) |
R300_ALU_DSTA_REG;
}
if (inst->Alpha.OutputWriteMask) {
- code->alu.inst[ip].inst3 |= R300_ALU_DSTA_OUTPUT;
- code->node[code->cur_node].flags |= R300_RGBA_OUT;
+ code->alu.inst[ip].alpha_addr |= R300_ALU_DSTA_OUTPUT;
+ emit->node_flags |= R300_RGBA_OUT;
}
if (inst->Alpha.DepthWriteMask) {
- code->alu.inst[ip].inst3 |= R300_ALU_DSTA_DEPTH;
- code->node[code->cur_node].flags |= R300_W_OUT;
- c->fp->WritesDepth = GL_TRUE;
+ code->alu.inst[ip].alpha_addr |= R300_ALU_DSTA_DEPTH;
+ emit->node_flags |= R300_W_OUT;
+ c->code->writes_depth = GL_TRUE;
}
return GL_TRUE;
@@ -211,31 +196,50 @@ static GLboolean emit_alu(void* data, struct radeon_pair_instruction* inst)
/**
* Finish the current node without advancing to the next one.
*/
-static GLboolean finish_node(struct r300_fragment_program_compiler *c)
+static GLboolean finish_node(struct r300_emit_state * emit)
{
- struct r300_fragment_program_code *code = c->code;
- struct r300_fragment_program_node *node = &code->node[code->cur_node];
+ struct r300_fragment_program_compiler * c = emit->compiler;
+ struct r300_fragment_program_code *code = &emit->compiler->code->code.r300;
- if (node->alu_end < 0) {
+ if (code->alu.length == emit->node_first_alu) {
/* Generate a single NOP for this node */
struct radeon_pair_instruction inst;
_mesa_bzero(&inst, sizeof(inst));
- if (!emit_alu(c, &inst))
+ if (!emit_alu(emit, &inst))
return GL_FALSE;
}
- if (node->tex_end < 0) {
- if (code->cur_node == 0) {
- node->tex_end = 0;
- } else {
- error("Node %i has no TEX instructions", code->cur_node);
+ unsigned alu_offset = emit->node_first_alu;
+ unsigned alu_end = code->alu.length - alu_offset - 1;
+ unsigned tex_offset = emit->node_first_tex;
+ unsigned tex_end = code->tex.length - tex_offset - 1;
+
+ if (code->tex.length == emit->node_first_tex) {
+ if (emit->current_node > 0) {
+ error("Node %i has no TEX instructions", emit->current_node);
return GL_FALSE;
}
+
+ tex_end = 0;
} else {
- if (code->cur_node == 0)
- code->first_node_has_tex = 1;
+ if (emit->current_node == 0)
+ code->config |= R300_PFS_CNTL_FIRST_NODE_HAS_TEX;
}
+ /* Write the config register.
+ * Note: The order in which the words for each node are written
+ * is not correct here and needs to be fixed up once we're entirely
+ * done
+ *
+ * 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;
+
return GL_TRUE;
}
@@ -248,64 +252,61 @@ static GLboolean begin_tex(void* data)
{
PROG_CODE;
- if (code->cur_node == 0) {
- if (code->node[0].alu_end < 0 &&
- code->node[0].tex_end < 0)
- return GL_TRUE;
+ if (code->alu.length == emit->node_first_alu &&
+ code->tex.length == emit->node_first_tex) {
+ return GL_TRUE;
}
- if (code->cur_node == 3) {
+ if (emit->current_node == 3) {
error("Too many texture indirections");
return GL_FALSE;
}
- if (!finish_node(c))
+ if (!finish_node(emit))
return GL_FALSE;
- struct r300_fragment_program_node *node = &code->node[++code->cur_node];
- node->alu_offset = code->alu.length;
- node->alu_end = -1;
- node->tex_offset = code->tex.length;
- node->tex_end = -1;
+ emit->current_node++;
+ emit->node_first_tex = code->tex.length;
+ emit->node_first_alu = code->alu.length;
+ emit->node_flags = 0;
return GL_TRUE;
}
-static GLboolean emit_tex(void* data, struct prog_instruction* inst)
+static GLboolean emit_tex(void* data, struct radeon_pair_texture_instruction* inst)
{
PROG_CODE;
- if (code->tex.length >= PFS_MAX_TEX_INST) {
+ if (code->tex.length >= R300_PFS_MAX_TEX_INST) {
error("Too many TEX instructions");
return GL_FALSE;
}
GLuint unit = inst->TexSrcUnit;
- GLuint dest = inst->DstReg.Index;
+ GLuint dest = inst->DestIndex;
GLuint opcode;
switch(inst->Opcode) {
- case OPCODE_KIL: opcode = R300_TEX_OP_KIL; break;
- case OPCODE_TEX: opcode = R300_TEX_OP_LD; break;
- case OPCODE_TXB: opcode = R300_TEX_OP_TXB; break;
- case OPCODE_TXP: opcode = R300_TEX_OP_TXP; break;
+ case RADEON_OPCODE_KIL: opcode = R300_TEX_OP_KIL; break;
+ case RADEON_OPCODE_TEX: opcode = R300_TEX_OP_LD; break;
+ case RADEON_OPCODE_TXB: opcode = R300_TEX_OP_TXB; break;
+ case RADEON_OPCODE_TXP: opcode = R300_TEX_OP_TXP; break;
default:
error("Unknown texture opcode %i", inst->Opcode);
return GL_FALSE;
}
- if (inst->Opcode == OPCODE_KIL) {
+ if (inst->Opcode == RADEON_OPCODE_KIL) {
unit = 0;
dest = 0;
} else {
use_temporary(code, dest);
}
- use_temporary(code, inst->SrcReg[0].Index);
+ use_temporary(code, inst->SrcIndex);
- code->node[code->cur_node].tex_end++;
code->tex.inst[code->tex.length++] =
- (inst->SrcReg[0].Index << R300_SRC_ADDR_SHIFT) |
+ (inst->SrcIndex << R300_SRC_ADDR_SHIFT) |
(dest << R300_DST_ADDR_SHIFT) |
(unit << R300_TEX_ID_SHIFT) |
(opcode << R300_TEX_INST_SHIFT);
@@ -314,31 +315,46 @@ static GLboolean emit_tex(void* data, struct prog_instruction* inst)
static const struct radeon_pair_handler pair_handler = {
- .EmitConst = &emit_const,
.EmitPaired = &emit_alu,
.EmitTex = &emit_tex,
.BeginTexBlock = &begin_tex,
- .MaxHwTemps = PFS_NUM_TEMP_REGS
+ .MaxHwTemps = R300_PFS_NUM_TEMP_REGS
};
/**
* Final compilation step: Turn the intermediate radeon_program into
* machine-readable instructions.
*/
-GLboolean r300FragmentProgramEmit(struct r300_fragment_program_compiler *compiler)
+void r300BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler)
{
- struct r300_fragment_program_code *code = compiler->code;
-
- _mesa_bzero(code, sizeof(struct r300_fragment_program_code));
- code->node[0].alu_end = -1;
- code->node[0].tex_end = -1;
+ struct r300_emit_state emit;
+ struct r300_fragment_program_code *code = &compiler->code->code.r300;
- if (!radeonPairProgram(compiler->r300->radeon.glCtx, compiler->program, &pair_handler, compiler))
- return GL_FALSE;
+ memset(&emit, 0, sizeof(emit));
+ emit.compiler = compiler;
- if (!finish_node(compiler))
- return GL_FALSE;
+ _mesa_bzero(code, sizeof(struct r300_fragment_program_code));
- return GL_TRUE;
+ radeonPairProgram(compiler, &pair_handler, &emit);
+ if (compiler->Base.Error)
+ return;
+
+ /* Finish the program */
+ finish_node(&emit);
+
+ code->config |= emit.current_node; /* FIRST_NODE_HAS_TEX set by finish_node */
+ 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);
+
+ if (emit.current_node < 3) {
+ int shift = 3 - emit.current_node;
+ int i;
+ for(i = 0; i <= emit.current_node; ++i)
+ code->code_addr[shift + i] = code->code_addr[i];
+ for(i = 0; i < shift; ++i)
+ code->code_addr[i] = 0;
+ }
}
-
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_swizzle.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c
index a86d2bd471..1b14cc3888 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog_swizzle.c
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c
@@ -33,8 +33,9 @@
#include "r300_fragprog_swizzle.h"
-#include "r300_reg.h"
+#include "../r300_reg.h"
#include "radeon_nqssadce.h"
+#include "radeon_compiler.h"
#define MAKE_SWZ3(x, y, z) (MAKE_SWIZZLE4(SWIZZLE_##x, SWIZZLE_##y, SWIZZLE_##z, SWIZZLE_ZERO))
@@ -92,7 +93,7 @@ static const struct swizzle_data* lookup_native_swizzle(GLuint swizzle)
GLboolean r300FPIsNativeSwizzle(GLuint opcode, struct prog_src_register reg)
{
if (reg.Abs)
- reg.NegateBase = 0;
+ reg.Negate = NEGATE_NONE;
if (opcode == OPCODE_KIL ||
opcode == OPCODE_TEX ||
@@ -100,7 +101,7 @@ GLboolean r300FPIsNativeSwizzle(GLuint opcode, struct prog_src_register reg)
opcode == OPCODE_TXP) {
int j;
- if (reg.Abs || reg.NegateBase != (15*reg.NegateAbs))
+ if (reg.Abs || reg.Negate)
return GL_FALSE;
for(j = 0; j < 4; ++j) {
@@ -121,7 +122,7 @@ GLboolean r300FPIsNativeSwizzle(GLuint opcode, struct prog_src_register reg)
if (GET_SWZ(reg.Swizzle, j) != SWIZZLE_NIL)
relevant |= 1 << j;
- if ((reg.NegateBase & relevant) && (reg.NegateBase & relevant) != relevant)
+ if ((reg.Negate & relevant) && ((reg.Negate & relevant) != relevant))
return GL_FALSE;
if (!lookup_native_swizzle(reg.Swizzle))
@@ -137,13 +138,12 @@ GLboolean r300FPIsNativeSwizzle(GLuint opcode, struct prog_src_register reg)
void r300FPBuildSwizzle(struct nqssadce_state *s, struct prog_dst_register dst, struct prog_src_register src)
{
if (src.Abs)
- src.NegateBase = 0;
+ src.Negate = NEGATE_NONE;
while(dst.WriteMask) {
const struct swizzle_data *best_swizzle = 0;
GLuint best_matchcount = 0;
GLuint best_matchmask = 0;
- GLboolean rgbnegate;
int i, comp;
for(i = 0; i < num_native_swizzles; ++i) {
@@ -157,6 +157,11 @@ void r300FPBuildSwizzle(struct nqssadce_state *s, struct prog_dst_register dst,
if (swz == SWIZZLE_NIL)
continue;
if (swz == GET_SWZ(sd->hash, comp)) {
+ /* check if the negate bit of current component
+ * is the same for already matched components */
+ if (matchmask && (!!(src.Negate & matchmask) != !!(src.Negate & (1 << comp))))
+ continue;
+
matchcount++;
matchmask |= 1 << comp;
}
@@ -170,24 +175,15 @@ void r300FPBuildSwizzle(struct nqssadce_state *s, struct prog_dst_register dst,
}
}
- if ((src.NegateBase & best_matchmask) != 0) {
- best_matchmask &= src.NegateBase;
- rgbnegate = !src.NegateAbs;
- } else {
- rgbnegate = src.NegateAbs;
- }
-
- struct prog_instruction *inst;
-
- _mesa_insert_instructions(s->Program, s->IP, 1);
- inst = s->Program->Instructions + s->IP++;
- inst->Opcode = OPCODE_MOV;
- inst->DstReg = dst;
- inst->DstReg.WriteMask &= (best_matchmask | WRITEMASK_W);
- inst->SrcReg[0] = src;
+ struct rc_instruction *inst = rc_insert_new_instruction(s->Compiler, s->IP->Prev);
+ inst->I.Opcode = OPCODE_MOV;
+ inst->I.DstReg = dst;
+ inst->I.DstReg.WriteMask &= (best_matchmask | WRITEMASK_W);
+ inst->I.SrcReg[0] = src;
+ inst->I.SrcReg[0].Negate = (best_matchmask & src.Negate) ? NEGATE_XYZW : NEGATE_NONE;
/* Note: We rely on NqSSA/DCE to set unused swizzle components to NIL */
- dst.WriteMask &= ~inst->DstReg.WriteMask;
+ dst.WriteMask &= ~inst->I.DstReg.WriteMask;
}
}
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_swizzle.h b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.h
index 231bf4eef5..231bf4eef5 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog_swizzle.h
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.h
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
new file mode 100644
index 0000000000..76c3a7ecfd
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "radeon_compiler.h"
+
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+
+#include "radeon_nqssadce.h"
+#include "radeon_program_alu.h"
+#include "r300_fragprog.h"
+#include "r300_fragprog_swizzle.h"
+#include "r500_fragprog.h"
+
+
+static void nqssadce_init(struct nqssadce_state* s)
+{
+ struct r300_fragment_program_compiler * c = s->UserData;
+ s->Outputs[c->OutputColor].Sourced = WRITEMASK_XYZW;
+ s->Outputs[c->OutputDepth].Sourced = WRITEMASK_W;
+}
+
+static void rewrite_depth_out(struct r300_fragment_program_compiler * c)
+{
+ struct rc_instruction *rci;
+
+ for (rci = c->Base.Program.Instructions.Next; rci != &c->Base.Program.Instructions; rci = rci->Next) {
+ struct prog_instruction * inst = &rci->I;
+
+ if (inst->DstReg.File != PROGRAM_OUTPUT || inst->DstReg.Index != c->OutputDepth)
+ continue;
+
+ if (inst->DstReg.WriteMask & WRITEMASK_Z) {
+ inst->DstReg.WriteMask = WRITEMASK_W;
+ } else {
+ inst->DstReg.WriteMask = 0;
+ continue;
+ }
+
+ switch (inst->Opcode) {
+ case OPCODE_FRC:
+ case OPCODE_MOV:
+ inst->SrcReg[0] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[0]);
+ break;
+ case OPCODE_ADD:
+ case OPCODE_MAX:
+ case OPCODE_MIN:
+ case OPCODE_MUL:
+ inst->SrcReg[0] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[0]);
+ inst->SrcReg[1] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[1]);
+ break;
+ case OPCODE_CMP:
+ case OPCODE_MAD:
+ inst->SrcReg[0] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[0]);
+ inst->SrcReg[1] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[1]);
+ inst->SrcReg[2] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[2]);
+ break;
+ default:
+ // Scalar instructions needn't be reswizzled
+ break;
+ }
+ }
+}
+
+void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
+{
+ rewrite_depth_out(c);
+
+ if (c->is_r500) {
+ struct radeon_program_transformation transformations[] = {
+ { &r500_transform_TEX, c },
+ { &radeonTransformALU, 0 },
+ { &radeonTransformDeriv, 0 },
+ { &radeonTransformTrigScale, 0 }
+ };
+ radeonLocalTransform(&c->Base, 4, transformations);
+ } else {
+ struct radeon_program_transformation transformations[] = {
+ { &r300_transform_TEX, c },
+ { &radeonTransformALU, 0 },
+ { &radeonTransformTrigSimple, 0 }
+ };
+ radeonLocalTransform(&c->Base, 3, transformations);
+ }
+
+ if (c->Base.Debug) {
+ _mesa_printf("Fragment Program: After native rewrite:\n");
+ rc_print_program(&c->Base.Program);
+ fflush(stderr);
+ }
+
+ if (c->is_r500) {
+ struct radeon_nqssadce_descr nqssadce = {
+ .Init = &nqssadce_init,
+ .IsNativeSwizzle = &r500FPIsNativeSwizzle,
+ .BuildSwizzle = &r500FPBuildSwizzle
+ };
+ radeonNqssaDce(&c->Base, &nqssadce, c);
+ } else {
+ struct radeon_nqssadce_descr nqssadce = {
+ .Init = &nqssadce_init,
+ .IsNativeSwizzle = &r300FPIsNativeSwizzle,
+ .BuildSwizzle = &r300FPBuildSwizzle
+ };
+ radeonNqssaDce(&c->Base, &nqssadce, c);
+ }
+
+ if (c->Base.Debug) {
+ _mesa_printf("Compiler: after NqSSA-DCE:\n");
+ rc_print_program(&c->Base.Program);
+ fflush(stderr);
+ }
+
+ if (c->is_r500) {
+ r500BuildFragmentProgramHwCode(c);
+ } else {
+ r300BuildFragmentProgramHwCode(c);
+ }
+
+ rc_constants_copy(&c->code->constants, &c->Base.Program.Constants);
+
+ if (c->Base.Debug) {
+ if (c->is_r500) {
+ r500FragmentProgramDump(c->code);
+ } else {
+ r300FragmentProgramDump(c->code);
+ }
+ }
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
new file mode 100644
index 0000000000..93a516105e
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
@@ -0,0 +1,655 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "radeon_compiler.h"
+
+#include "../r300_reg.h"
+
+#include "radeon_nqssadce.h"
+#include "radeon_program.h"
+#include "radeon_program_alu.h"
+
+#include "shader/prog_print.h"
+
+
+/*
+ * Take an already-setup and valid source then swizzle it appropriately to
+ * obtain a constant ZERO or ONE source.
+ */
+#define __CONST(x, y) \
+ (PVS_SRC_OPERAND(t_src_index(vp, &vpi->SrcReg[x]), \
+ t_swizzle(y), \
+ t_swizzle(y), \
+ t_swizzle(y), \
+ t_swizzle(y), \
+ t_src_class(vpi->SrcReg[x].File), \
+ NEGATE_NONE) | (vpi->SrcReg[x].RelAddr << 4))
+
+
+static unsigned long t_dst_mask(GLuint mask)
+{
+ /* WRITEMASK_* is equivalent to VSF_FLAG_* */
+ return mask & WRITEMASK_XYZW;
+}
+
+static unsigned long t_dst_class(gl_register_file file)
+{
+
+ switch (file) {
+ case PROGRAM_TEMPORARY:
+ return PVS_DST_REG_TEMPORARY;
+ case PROGRAM_OUTPUT:
+ return PVS_DST_REG_OUT;
+ case PROGRAM_ADDRESS:
+ return PVS_DST_REG_A0;
+ /*
+ case PROGRAM_INPUT:
+ case PROGRAM_LOCAL_PARAM:
+ case PROGRAM_ENV_PARAM:
+ case PROGRAM_NAMED_PARAM:
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_WRITE_ONLY:
+ case PROGRAM_ADDRESS:
+ */
+ default:
+ fprintf(stderr, "problem in %s", __FUNCTION__);
+ _mesa_exit(-1);
+ return -1;
+ }
+}
+
+static unsigned long t_dst_index(struct r300_vertex_program_code *vp,
+ struct prog_dst_register *dst)
+{
+ if (dst->File == PROGRAM_OUTPUT)
+ return vp->outputs[dst->Index];
+
+ return dst->Index;
+}
+
+static unsigned long t_src_class(gl_register_file file)
+{
+ switch (file) {
+ case PROGRAM_TEMPORARY:
+ return PVS_SRC_REG_TEMPORARY;
+ case PROGRAM_INPUT:
+ return PVS_SRC_REG_INPUT;
+ case PROGRAM_LOCAL_PARAM:
+ case PROGRAM_ENV_PARAM:
+ case PROGRAM_NAMED_PARAM:
+ case PROGRAM_CONSTANT:
+ case PROGRAM_STATE_VAR:
+ return PVS_SRC_REG_CONSTANT;
+ /*
+ case PROGRAM_OUTPUT:
+ case PROGRAM_WRITE_ONLY:
+ case PROGRAM_ADDRESS:
+ */
+ default:
+ fprintf(stderr, "problem in %s", __FUNCTION__);
+ _mesa_exit(-1);
+ return -1;
+ }
+}
+
+static GLboolean t_src_conflict(struct prog_src_register a, struct prog_src_register b)
+{
+ unsigned long aclass = t_src_class(a.File);
+ unsigned long bclass = t_src_class(b.File);
+
+ if (aclass != bclass)
+ return GL_FALSE;
+ if (aclass == PVS_SRC_REG_TEMPORARY)
+ return GL_FALSE;
+
+ if (a.RelAddr || b.RelAddr)
+ return GL_TRUE;
+ if (a.Index != b.Index)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+static INLINE unsigned long t_swizzle(GLubyte swizzle)
+{
+ /* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */
+ return swizzle;
+}
+
+static unsigned long t_src_index(struct r300_vertex_program_code *vp,
+ struct prog_src_register *src)
+{
+ if (src->File == PROGRAM_INPUT) {
+ assert(vp->inputs[src->Index] != -1);
+ return vp->inputs[src->Index];
+ } else {
+ if (src->Index < 0) {
+ fprintf(stderr,
+ "negative offsets for indirect addressing do not work.\n");
+ return 0;
+ }
+ return src->Index;
+ }
+}
+
+/* these two functions should probably be merged... */
+
+static unsigned long t_src(struct r300_vertex_program_code *vp,
+ struct prog_src_register *src)
+{
+ /* src->Negate uses the NEGATE_ flags from program_instruction.h,
+ * which equal our VSF_FLAGS_ values, so it's safe to just pass it here.
+ */
+ return PVS_SRC_OPERAND(t_src_index(vp, src),
+ t_swizzle(GET_SWZ(src->Swizzle, 0)),
+ t_swizzle(GET_SWZ(src->Swizzle, 1)),
+ t_swizzle(GET_SWZ(src->Swizzle, 2)),
+ t_swizzle(GET_SWZ(src->Swizzle, 3)),
+ t_src_class(src->File),
+ src->Negate) | (src->RelAddr << 4);
+}
+
+static unsigned long t_src_scalar(struct r300_vertex_program_code *vp,
+ struct prog_src_register *src)
+{
+ /* src->Negate uses the NEGATE_ flags from program_instruction.h,
+ * which equal our VSF_FLAGS_ values, so it's safe to just pass it here.
+ */
+ return PVS_SRC_OPERAND(t_src_index(vp, src),
+ t_swizzle(GET_SWZ(src->Swizzle, 0)),
+ t_swizzle(GET_SWZ(src->Swizzle, 0)),
+ t_swizzle(GET_SWZ(src->Swizzle, 0)),
+ t_swizzle(GET_SWZ(src->Swizzle, 0)),
+ t_src_class(src->File),
+ src->Negate ? NEGATE_XYZW : NEGATE_NONE) |
+ (src->RelAddr << 4);
+}
+
+static GLboolean valid_dst(struct r300_vertex_program_code *vp,
+ struct prog_dst_register *dst)
+{
+ if (dst->File == PROGRAM_OUTPUT && vp->outputs[dst->Index] == -1) {
+ return GL_FALSE;
+ } else if (dst->File == PROGRAM_ADDRESS) {
+ assert(dst->Index == 0);
+ }
+
+ return GL_TRUE;
+}
+
+static void ei_vector1(struct r300_vertex_program_code *vp,
+ GLuint hw_opcode,
+ struct prog_instruction *vpi,
+ GLuint * inst)
+{
+ inst[0] = PVS_OP_DST_OPERAND(hw_opcode,
+ GL_FALSE,
+ GL_FALSE,
+ t_dst_index(vp, &vpi->DstReg),
+ t_dst_mask(vpi->DstReg.WriteMask),
+ t_dst_class(vpi->DstReg.File));
+ inst[1] = t_src(vp, &vpi->SrcReg[0]);
+ inst[2] = __CONST(0, SWIZZLE_ZERO);
+ inst[3] = __CONST(0, SWIZZLE_ZERO);
+}
+
+static void ei_vector2(struct r300_vertex_program_code *vp,
+ GLuint hw_opcode,
+ struct prog_instruction *vpi,
+ GLuint * inst)
+{
+ inst[0] = PVS_OP_DST_OPERAND(hw_opcode,
+ GL_FALSE,
+ GL_FALSE,
+ t_dst_index(vp, &vpi->DstReg),
+ t_dst_mask(vpi->DstReg.WriteMask),
+ t_dst_class(vpi->DstReg.File));
+ inst[1] = t_src(vp, &vpi->SrcReg[0]);
+ inst[2] = t_src(vp, &vpi->SrcReg[1]);
+ inst[3] = __CONST(1, SWIZZLE_ZERO);
+}
+
+static void ei_math1(struct r300_vertex_program_code *vp,
+ GLuint hw_opcode,
+ struct prog_instruction *vpi,
+ GLuint * inst)
+{
+ inst[0] = PVS_OP_DST_OPERAND(hw_opcode,
+ GL_TRUE,
+ GL_FALSE,
+ t_dst_index(vp, &vpi->DstReg),
+ t_dst_mask(vpi->DstReg.WriteMask),
+ t_dst_class(vpi->DstReg.File));
+ inst[1] = t_src_scalar(vp, &vpi->SrcReg[0]);
+ inst[2] = __CONST(0, SWIZZLE_ZERO);
+ inst[3] = __CONST(0, SWIZZLE_ZERO);
+}
+
+static void ei_lit(struct r300_vertex_program_code *vp,
+ struct prog_instruction *vpi,
+ GLuint * inst)
+{
+ //LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W}
+
+ inst[0] = PVS_OP_DST_OPERAND(ME_LIGHT_COEFF_DX,
+ GL_TRUE,
+ GL_FALSE,
+ t_dst_index(vp, &vpi->DstReg),
+ t_dst_mask(vpi->DstReg.WriteMask),
+ t_dst_class(vpi->DstReg.File));
+ /* NOTE: Users swizzling might not work. */
+ inst[1] = PVS_SRC_OPERAND(t_src_index(vp, &vpi->SrcReg[0]), t_swizzle(GET_SWZ(vpi->SrcReg[0].Swizzle, 0)), // X
+ t_swizzle(GET_SWZ(vpi->SrcReg[0].Swizzle, 3)), // W
+ PVS_SRC_SELECT_FORCE_0, // Z
+ t_swizzle(GET_SWZ(vpi->SrcReg[0].Swizzle, 1)), // Y
+ t_src_class(vpi->SrcReg[0].File),
+ vpi->SrcReg[0].Negate ? NEGATE_XYZW : NEGATE_NONE) |
+ (vpi->SrcReg[0].RelAddr << 4);
+ inst[2] = PVS_SRC_OPERAND(t_src_index(vp, &vpi->SrcReg[0]), t_swizzle(GET_SWZ(vpi->SrcReg[0].Swizzle, 1)), // Y
+ t_swizzle(GET_SWZ(vpi->SrcReg[0].Swizzle, 3)), // W
+ PVS_SRC_SELECT_FORCE_0, // Z
+ t_swizzle(GET_SWZ(vpi->SrcReg[0].Swizzle, 0)), // X
+ t_src_class(vpi->SrcReg[0].File),
+ vpi->SrcReg[0].Negate ? NEGATE_XYZW : NEGATE_NONE) |
+ (vpi->SrcReg[0].RelAddr << 4);
+ inst[3] = PVS_SRC_OPERAND(t_src_index(vp, &vpi->SrcReg[0]), t_swizzle(GET_SWZ(vpi->SrcReg[0].Swizzle, 1)), // Y
+ t_swizzle(GET_SWZ(vpi->SrcReg[0].Swizzle, 0)), // X
+ PVS_SRC_SELECT_FORCE_0, // Z
+ t_swizzle(GET_SWZ(vpi->SrcReg[0].Swizzle, 3)), // W
+ t_src_class(vpi->SrcReg[0].File),
+ vpi->SrcReg[0].Negate ? NEGATE_XYZW : NEGATE_NONE) |
+ (vpi->SrcReg[0].RelAddr << 4);
+}
+
+static void ei_mad(struct r300_vertex_program_code *vp,
+ struct prog_instruction *vpi,
+ GLuint * inst)
+{
+ /* Remarks about hardware limitations of MAD
+ * (please preserve this comment, as this information is _NOT_
+ * in the documentation provided by AMD).
+ *
+ * As described in the documentation, MAD with three unique temporary
+ * source registers requires the use of the macro version.
+ *
+ * However (and this is not mentioned in the documentation), apparently
+ * the macro version is _NOT_ a full superset of the normal version.
+ * In particular, the macro version does not always work when relative
+ * addressing is used in the source operands.
+ *
+ * This limitation caused incorrect rendering in Sauerbraten's OpenGL
+ * assembly shader path when using medium quality animations
+ * (i.e. animations with matrix blending instead of quaternion blending).
+ *
+ * Unfortunately, I (nha) have been unable to extract a Piglit regression
+ * test for this issue - for some reason, it is possible to have vertex
+ * programs whose prefix is *exactly* the same as the prefix of the
+ * offending program in Sauerbraten up to the offending instruction
+ * without causing any trouble.
+ *
+ * Bottom line: Only use the macro version only when really necessary;
+ * according to AMD docs, this should improve performance by one clock
+ * as a nice side bonus.
+ */
+ if (vpi->SrcReg[0].File == PROGRAM_TEMPORARY &&
+ vpi->SrcReg[1].File == PROGRAM_TEMPORARY &&
+ vpi->SrcReg[2].File == PROGRAM_TEMPORARY &&
+ vpi->SrcReg[0].Index != vpi->SrcReg[1].Index &&
+ vpi->SrcReg[0].Index != vpi->SrcReg[2].Index &&
+ vpi->SrcReg[1].Index != vpi->SrcReg[2].Index) {
+ inst[0] = PVS_OP_DST_OPERAND(PVS_MACRO_OP_2CLK_MADD,
+ GL_FALSE,
+ GL_TRUE,
+ t_dst_index(vp, &vpi->DstReg),
+ t_dst_mask(vpi->DstReg.WriteMask),
+ t_dst_class(vpi->DstReg.File));
+ } else {
+ inst[0] = PVS_OP_DST_OPERAND(VE_MULTIPLY_ADD,
+ GL_FALSE,
+ GL_FALSE,
+ t_dst_index(vp, &vpi->DstReg),
+ t_dst_mask(vpi->DstReg.WriteMask),
+ t_dst_class(vpi->DstReg.File));
+ }
+ inst[1] = t_src(vp, &vpi->SrcReg[0]);
+ inst[2] = t_src(vp, &vpi->SrcReg[1]);
+ inst[3] = t_src(vp, &vpi->SrcReg[2]);
+}
+
+static void ei_pow(struct r300_vertex_program_code *vp,
+ struct prog_instruction *vpi,
+ GLuint * inst)
+{
+ inst[0] = PVS_OP_DST_OPERAND(ME_POWER_FUNC_FF,
+ GL_TRUE,
+ GL_FALSE,
+ t_dst_index(vp, &vpi->DstReg),
+ t_dst_mask(vpi->DstReg.WriteMask),
+ t_dst_class(vpi->DstReg.File));
+ inst[1] = t_src_scalar(vp, &vpi->SrcReg[0]);
+ inst[2] = __CONST(0, SWIZZLE_ZERO);
+ inst[3] = t_src_scalar(vp, &vpi->SrcReg[1]);
+}
+
+
+static void translate_vertex_program(struct r300_vertex_program_compiler * compiler)
+{
+ struct rc_instruction *rci;
+
+ compiler->code->pos_end = 0; /* Not supported yet */
+ compiler->code->length = 0;
+
+ compiler->SetHwInputOutput(compiler);
+
+ for(rci = compiler->Base.Program.Instructions.Next; rci != &compiler->Base.Program.Instructions; rci = rci->Next) {
+ struct prog_instruction *vpi = &rci->I;
+ GLuint *inst = compiler->code->body.d + compiler->code->length;
+
+ /* Skip instructions writing to non-existing destination */
+ if (!valid_dst(compiler->code, &vpi->DstReg))
+ continue;
+
+ if (compiler->code->length >= VSF_MAX_FRAGMENT_LENGTH) {
+ rc_error(&compiler->Base, "Vertex program has too many instructions\n");
+ return;
+ }
+
+ switch (vpi->Opcode) {
+ case OPCODE_ADD: ei_vector2(compiler->code, VE_ADD, vpi, inst); break;
+ case OPCODE_ARL: ei_vector1(compiler->code, VE_FLT2FIX_DX, vpi, inst); break;
+ case OPCODE_DP4: ei_vector2(compiler->code, VE_DOT_PRODUCT, vpi, inst); break;
+ case OPCODE_DST: ei_vector2(compiler->code, VE_DISTANCE_VECTOR, vpi, inst); break;
+ case OPCODE_EX2: ei_math1(compiler->code, ME_EXP_BASE2_FULL_DX, vpi, inst); break;
+ case OPCODE_EXP: ei_math1(compiler->code, ME_EXP_BASE2_DX, vpi, inst); break;
+ case OPCODE_FRC: ei_vector1(compiler->code, VE_FRACTION, vpi, inst); break;
+ case OPCODE_LG2: ei_math1(compiler->code, ME_LOG_BASE2_FULL_DX, vpi, inst); break;
+ case OPCODE_LIT: ei_lit(compiler->code, vpi, inst); break;
+ case OPCODE_LOG: ei_math1(compiler->code, ME_LOG_BASE2_DX, vpi, inst); break;
+ case OPCODE_MAD: ei_mad(compiler->code, vpi, inst); break;
+ case OPCODE_MAX: ei_vector2(compiler->code, VE_MAXIMUM, vpi, inst); break;
+ case OPCODE_MIN: ei_vector2(compiler->code, VE_MINIMUM, vpi, inst); break;
+ case OPCODE_MOV: ei_vector1(compiler->code, VE_ADD, vpi, inst); break;
+ case OPCODE_MUL: ei_vector2(compiler->code, VE_MULTIPLY, vpi, inst); break;
+ case OPCODE_POW: ei_pow(compiler->code, vpi, inst); break;
+ case OPCODE_RCP: ei_math1(compiler->code, ME_RECIP_DX, vpi, inst); break;
+ case OPCODE_RSQ: ei_math1(compiler->code, ME_RECIP_SQRT_DX, vpi, inst); break;
+ case OPCODE_SGE: ei_vector2(compiler->code, VE_SET_GREATER_THAN_EQUAL, vpi, inst); break;
+ case OPCODE_SLT: ei_vector2(compiler->code, VE_SET_LESS_THAN, vpi, inst); break;
+ default:
+ rc_error(&compiler->Base, "Unknown opcode %i\n", vpi->Opcode);
+ return;
+ }
+
+ compiler->code->length += 4;
+
+ if (compiler->Base.Error)
+ return;
+ }
+}
+
+struct temporary_allocation {
+ GLuint Allocated:1;
+ GLuint HwTemp:15;
+ struct rc_instruction * LastRead;
+};
+
+static void allocate_temporary_registers(struct r300_vertex_program_compiler * compiler)
+{
+ struct rc_instruction *inst;
+ GLuint num_orig_temps = 0;
+ GLboolean hwtemps[VSF_MAX_FRAGMENT_TEMPS];
+ struct temporary_allocation * ta;
+ GLuint i, j;
+
+ compiler->code->num_temporaries = 0;
+ memset(hwtemps, 0, sizeof(hwtemps));
+
+ /* Pass 1: Count original temporaries and allocate structures */
+ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) {
+ GLuint numsrcs = _mesa_num_inst_src_regs(inst->I.Opcode);
+ GLuint numdsts = _mesa_num_inst_dst_regs(inst->I.Opcode);
+
+ for (i = 0; i < numsrcs; ++i) {
+ if (inst->I.SrcReg[i].File == PROGRAM_TEMPORARY) {
+ if (inst->I.SrcReg[i].Index >= num_orig_temps)
+ num_orig_temps = inst->I.SrcReg[i].Index + 1;
+ }
+ }
+
+ if (numdsts) {
+ if (inst->I.DstReg.File == PROGRAM_TEMPORARY) {
+ if (inst->I.DstReg.Index >= num_orig_temps)
+ num_orig_temps = inst->I.DstReg.Index + 1;
+ }
+ }
+ }
+
+ ta = (struct temporary_allocation*)memory_pool_malloc(&compiler->Base.Pool,
+ sizeof(struct temporary_allocation) * num_orig_temps);
+ memset(ta, 0, sizeof(struct temporary_allocation) * num_orig_temps);
+
+ /* Pass 2: Determine original temporary lifetimes */
+ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) {
+ GLuint numsrcs = _mesa_num_inst_src_regs(inst->I.Opcode);
+
+ for (i = 0; i < numsrcs; ++i) {
+ if (inst->I.SrcReg[i].File == PROGRAM_TEMPORARY)
+ ta[inst->I.SrcReg[i].Index].LastRead = inst;
+ }
+ }
+
+ /* Pass 3: Register allocation */
+ for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) {
+ GLuint numsrcs = _mesa_num_inst_src_regs(inst->I.Opcode);
+ GLuint numdsts = _mesa_num_inst_dst_regs(inst->I.Opcode);
+
+ for (i = 0; i < numsrcs; ++i) {
+ if (inst->I.SrcReg[i].File == PROGRAM_TEMPORARY) {
+ GLuint orig = inst->I.SrcReg[i].Index;
+ inst->I.SrcReg[i].Index = ta[orig].HwTemp;
+
+ if (ta[orig].Allocated && inst == ta[orig].LastRead)
+ hwtemps[ta[orig].HwTemp] = GL_FALSE;
+ }
+ }
+
+ if (numdsts) {
+ if (inst->I.DstReg.File == PROGRAM_TEMPORARY) {
+ GLuint orig = inst->I.DstReg.Index;
+
+ if (!ta[orig].Allocated) {
+ for(j = 0; j < VSF_MAX_FRAGMENT_TEMPS; ++j) {
+ if (!hwtemps[j])
+ break;
+ }
+ if (j >= VSF_MAX_FRAGMENT_TEMPS) {
+ fprintf(stderr, "Out of hw temporaries\n");
+ } else {
+ ta[orig].Allocated = GL_TRUE;
+ ta[orig].HwTemp = j;
+ hwtemps[j] = GL_TRUE;
+
+ if (j >= compiler->code->num_temporaries)
+ compiler->code->num_temporaries = j + 1;
+ }
+ }
+
+ inst->I.DstReg.Index = ta[orig].HwTemp;
+ }
+ }
+ }
+}
+
+
+/**
+ * Vertex engine cannot read two inputs or two constants at the same time.
+ * Introduce intermediate MOVs to temporary registers to account for this.
+ */
+static GLboolean transform_source_conflicts(
+ struct radeon_compiler *c,
+ struct rc_instruction* inst,
+ void* unused)
+{
+ GLuint num_operands = _mesa_num_inst_src_regs(inst->I.Opcode);
+
+ if (num_operands == 3) {
+ if (t_src_conflict(inst->I.SrcReg[1], inst->I.SrcReg[2])
+ || t_src_conflict(inst->I.SrcReg[0], inst->I.SrcReg[2])) {
+ int tmpreg = rc_find_free_temporary(c);
+ struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst->Prev);
+ inst_mov->I.Opcode = OPCODE_MOV;
+ inst_mov->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_mov->I.DstReg.Index = tmpreg;
+ inst_mov->I.SrcReg[0] = inst->I.SrcReg[2];
+
+ reset_srcreg(&inst->I.SrcReg[2]);
+ inst->I.SrcReg[2].File = PROGRAM_TEMPORARY;
+ inst->I.SrcReg[2].Index = tmpreg;
+ }
+ }
+
+ if (num_operands >= 2) {
+ if (t_src_conflict(inst->I.SrcReg[1], inst->I.SrcReg[0])) {
+ int tmpreg = rc_find_free_temporary(c);
+ struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst->Prev);
+ inst_mov->I.Opcode = OPCODE_MOV;
+ inst_mov->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_mov->I.DstReg.Index = tmpreg;
+ inst_mov->I.SrcReg[0] = inst->I.SrcReg[1];
+
+ reset_srcreg(&inst->I.SrcReg[1]);
+ inst->I.SrcReg[1].File = PROGRAM_TEMPORARY;
+ inst->I.SrcReg[1].Index = tmpreg;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+static void addArtificialOutputs(struct r300_vertex_program_compiler * compiler)
+{
+ int i;
+
+ for(i = 0; i < 32; ++i) {
+ if ((compiler->RequiredOutputs & (1 << i)) &&
+ !(compiler->Base.Program.OutputsWritten & (1 << i))) {
+ struct rc_instruction * inst = rc_insert_new_instruction(&compiler->Base, compiler->Base.Program.Instructions.Prev);
+ inst->I.Opcode = OPCODE_MOV;
+
+ inst->I.DstReg.File = PROGRAM_OUTPUT;
+ inst->I.DstReg.Index = i;
+ inst->I.DstReg.WriteMask = WRITEMASK_XYZW;
+
+ inst->I.SrcReg[0].File = PROGRAM_CONSTANT;
+ inst->I.SrcReg[0].Index = 0;
+ inst->I.SrcReg[0].Swizzle = SWIZZLE_XYZW;
+
+ compiler->Base.Program.OutputsWritten |= 1 << i;
+ }
+ }
+}
+
+static void nqssadceInit(struct nqssadce_state* s)
+{
+ struct r300_vertex_program_compiler * compiler = s->UserData;
+ int i;
+
+ for(i = 0; i < VERT_RESULT_MAX; ++i) {
+ if (compiler->RequiredOutputs & (1 << i))
+ s->Outputs[i].Sourced = WRITEMASK_XYZW;
+ }
+}
+
+static GLboolean swizzleIsNative(GLuint opcode, struct prog_src_register reg)
+{
+ (void) opcode;
+ (void) reg;
+
+ return GL_TRUE;
+}
+
+
+
+void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
+{
+ addArtificialOutputs(compiler);
+
+ {
+ struct radeon_program_transformation transformations[] = {
+ { &r300_transform_vertex_alu, 0 },
+ };
+ radeonLocalTransform(&compiler->Base, 1, transformations);
+ }
+
+ if (compiler->Base.Debug) {
+ fprintf(stderr, "Vertex program after native rewrite:\n");
+ rc_print_program(&compiler->Base.Program);
+ fflush(stderr);
+ }
+
+ {
+ /* Note: This pass has to be done seperately from ALU rewrite,
+ * otherwise non-native ALU instructions with source conflits
+ * will not be treated properly.
+ */
+ struct radeon_program_transformation transformations[] = {
+ { &transform_source_conflicts, 0 },
+ };
+ radeonLocalTransform(&compiler->Base, 1, transformations);
+ }
+
+ if (compiler->Base.Debug) {
+ fprintf(stderr, "Vertex program after source conflict resolve:\n");
+ rc_print_program(&compiler->Base.Program);
+ fflush(stderr);
+ }
+
+ {
+ struct radeon_nqssadce_descr nqssadce = {
+ .Init = &nqssadceInit,
+ .IsNativeSwizzle = &swizzleIsNative,
+ .BuildSwizzle = NULL
+ };
+ radeonNqssaDce(&compiler->Base, &nqssadce, compiler);
+
+ /* We need this step for reusing temporary registers */
+ allocate_temporary_registers(compiler);
+
+ if (compiler->Base.Debug) {
+ fprintf(stderr, "Vertex program after NQSSADCE:\n");
+ rc_print_program(&compiler->Base.Program);
+ fflush(stderr);
+ }
+ }
+
+ translate_vertex_program(compiler);
+
+ rc_constants_copy(&compiler->code->constants, &compiler->Base.Program.Constants);
+
+ compiler->code->InputsRead = compiler->Base.Program.InputsRead;
+ compiler->code->OutputsWritten = compiler->Base.Program.OutputsWritten;
+
+ if (compiler->Base.Debug) {
+ fprintf(stderr, "Final vertex program code:\n");
+ r300_vertex_program_dump(compiler->code);
+ }
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog_dump.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog_dump.c
new file mode 100644
index 0000000000..980ef3eaea
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog_dump.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "radeon_code.h"
+
+#include <stdio.h>
+
+static char* r300_vs_ve_ops[] = {
+ /* R300 vector ops */
+ " VE_NO_OP",
+ " VE_DOT_PRODUCT",
+ " VE_MULTIPLY",
+ " VE_ADD",
+ " VE_MULTIPLY_ADD",
+ " VE_DISTANCE_FACTOR",
+ " VE_FRACTION",
+ " VE_MAXIMUM",
+ " VE_MINIMUM",
+ "VE_SET_GREATER_THAN_EQUAL",
+ " VE_SET_LESS_THAN",
+ " VE_MULTIPLYX2_ADD",
+ " VE_MULTIPLY_CLAMP",
+ " VE_FLT2FIX_DX",
+ " VE_FLT2FIX_DX_RND",
+ /* R500 vector ops */
+ " VE_PRED_SET_EQ_PUSH",
+ " VE_PRED_SET_GT_PUSH",
+ " VE_PRED_SET_GTE_PUSH",
+ " VE_PRED_SET_NEQ_PUSH",
+ " VE_COND_WRITE_EQ",
+ " VE_COND_WRITE_GT",
+ " VE_COND_WRITE_GTE",
+ " VE_COND_WRITE_NEQ",
+ " VE_SET_GREATER_THAN",
+ " VE_SET_EQUAL",
+ " VE_SET_NOT_EQUAL",
+ " (reserved)",
+ " (reserved)",
+ " (reserved)",
+};
+
+static char* r300_vs_me_ops[] = {
+ /* R300 math ops */
+ " ME_NO_OP",
+ " ME_EXP_BASE2_DX",
+ " ME_LOG_BASE2_DX",
+ " ME_EXP_BASEE_FF",
+ " ME_LIGHT_COEFF_DX",
+ " ME_POWER_FUNC_FF",
+ " ME_RECIP_DX",
+ " ME_RECIP_FF",
+ " ME_RECIP_SQRT_DX",
+ " ME_RECIP_SQRT_FF",
+ " ME_MULTIPLY",
+ " ME_EXP_BASE2_FULL_DX",
+ " ME_LOG_BASE2_FULL_DX",
+ " ME_POWER_FUNC_FF_CLAMP_B",
+ "ME_POWER_FUNC_FF_CLAMP_B1",
+ "ME_POWER_FUNC_FF_CLAMP_01",
+ " ME_SIN",
+ " ME_COS",
+ /* R500 math ops */
+ " ME_LOG_BASE2_IEEE",
+ " ME_RECIP_IEEE",
+ " ME_RECIP_SQRT_IEEE",
+ " ME_PRED_SET_EQ",
+ " ME_PRED_SET_GT",
+ " ME_PRED_SET_GTE",
+ " ME_PRED_SET_NEQ",
+ " ME_PRED_SET_CLR",
+ " ME_PRED_SET_INV",
+ " ME_PRED_SET_POP",
+ " ME_PRED_SET_RESTORE",
+ " (reserved)",
+ " (reserved)",
+ " (reserved)",
+};
+
+/* XXX refactor to avoid clashing symbols */
+static char* r300_vs_src_debug[] = {
+ "t",
+ "i",
+ "c",
+ "a",
+};
+
+static char* r300_vs_dst_debug[] = {
+ "t",
+ "a0",
+ "o",
+ "ox",
+ "a",
+ "i",
+ "u",
+ "u",
+};
+
+static char* r300_vs_swiz_debug[] = {
+ "X",
+ "Y",
+ "Z",
+ "W",
+ "0",
+ "1",
+ "U",
+ "U",
+};
+
+
+static void r300_vs_op_dump(uint32_t op)
+{
+ fprintf(stderr, " dst: %d%s op: ",
+ (op >> 13) & 0x7f, r300_vs_dst_debug[(op >> 8) & 0x7]);
+ if (op & 0x80) {
+ if (op & 0x1) {
+ fprintf(stderr, "PVS_MACRO_OP_2CLK_M2X_ADD\n");
+ } else {
+ fprintf(stderr, " PVS_MACRO_OP_2CLK_MADD\n");
+ }
+ } else if (op & 0x40) {
+ fprintf(stderr, "%s\n", r300_vs_me_ops[op & 0x1f]);
+ } else {
+ fprintf(stderr, "%s\n", r300_vs_ve_ops[op & 0x1f]);
+ }
+}
+
+static void r300_vs_src_dump(uint32_t src)
+{
+ fprintf(stderr, " reg: %d%s swiz: %s%s/%s%s/%s%s/%s%s\n",
+ (src >> 5) & 0x7f, r300_vs_src_debug[src & 0x3],
+ src & (1 << 25) ? "-" : " ",
+ r300_vs_swiz_debug[(src >> 13) & 0x7],
+ src & (1 << 26) ? "-" : " ",
+ r300_vs_swiz_debug[(src >> 16) & 0x7],
+ src & (1 << 27) ? "-" : " ",
+ r300_vs_swiz_debug[(src >> 19) & 0x7],
+ src & (1 << 28) ? "-" : " ",
+ r300_vs_swiz_debug[(src >> 22) & 0x7]);
+}
+
+void r300_vertex_program_dump(struct r300_vertex_program_code * vs)
+{
+ unsigned instrcount = vs->length / 4;
+ unsigned i;
+
+ for(i = 0; i < instrcount; i++) {
+ unsigned offset = i*4;
+ unsigned src;
+
+ fprintf(stderr, "%d: op: 0x%08x", i, vs->body.d[offset]);
+ r300_vs_op_dump(vs->body.d[offset]);
+
+ for(src = 0; src < 3; ++src) {
+ fprintf(stderr, " src%i: 0x%08x", src, vs->body.d[offset+1+src]);
+ r300_vs_src_dump(vs->body.d[offset+1+src]);
+ }
+ }
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c
new file mode 100644
index 0000000000..7e2faed690
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "r500_fragprog.h"
+
+#include "../r300_reg.h"
+
+static struct prog_src_register shadow_ambient(struct radeon_compiler * c, int tmu)
+{
+ struct prog_src_register reg = { 0, };
+
+ reg.File = PROGRAM_STATE_VAR;
+ reg.Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_SHADOW_AMBIENT, tmu);
+ reg.Swizzle = SWIZZLE_WWWW;
+ return reg;
+}
+
+/**
+ * Transform TEX, TXP, TXB, and KIL instructions in the following way:
+ * - implement texture compare (shadow extensions)
+ * - extract non-native source / destination operands
+ */
+GLboolean r500_transform_TEX(
+ struct radeon_compiler * c,
+ struct rc_instruction * inst,
+ void* data)
+{
+ struct r300_fragment_program_compiler *compiler =
+ (struct r300_fragment_program_compiler*)data;
+
+ if (inst->I.Opcode != OPCODE_TEX &&
+ inst->I.Opcode != OPCODE_TXB &&
+ inst->I.Opcode != OPCODE_TXP &&
+ inst->I.Opcode != OPCODE_KIL)
+ return GL_FALSE;
+
+ /* ARB_shadow & EXT_shadow_funcs */
+ if (inst->I.Opcode != OPCODE_KIL &&
+ c->Program.ShadowSamplers & (1 << inst->I.TexSrcUnit)) {
+ GLuint comparefunc = GL_NEVER + compiler->state.unit[inst->I.TexSrcUnit].texture_compare_func;
+
+ if (comparefunc == GL_NEVER || comparefunc == GL_ALWAYS) {
+ inst->I.Opcode = OPCODE_MOV;
+
+ if (comparefunc == GL_ALWAYS) {
+ inst->I.SrcReg[0].File = PROGRAM_BUILTIN;
+ inst->I.SrcReg[0].Swizzle = SWIZZLE_1111;
+ } else {
+ inst->I.SrcReg[0] = shadow_ambient(c, inst->I.TexSrcUnit);
+ }
+
+ return GL_TRUE;
+ } else {
+ GLuint comparefunc = GL_NEVER + compiler->state.unit[inst->I.TexSrcUnit].texture_compare_func;
+ GLuint depthmode = compiler->state.unit[inst->I.TexSrcUnit].depth_texture_mode;
+ struct rc_instruction * inst_rcp = rc_insert_new_instruction(c, inst);
+ struct rc_instruction * inst_mad = rc_insert_new_instruction(c, inst_rcp);
+ struct rc_instruction * inst_cmp = rc_insert_new_instruction(c, inst_mad);
+ int pass, fail;
+
+ inst_rcp->I.Opcode = OPCODE_RCP;
+ inst_rcp->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_rcp->I.DstReg.Index = rc_find_free_temporary(c);
+ inst_rcp->I.DstReg.WriteMask = WRITEMASK_W;
+ inst_rcp->I.SrcReg[0] = inst->I.SrcReg[0];
+ inst_rcp->I.SrcReg[0].Swizzle = SWIZZLE_WWWW;
+
+ inst_cmp->I.DstReg = inst->I.DstReg;
+ inst->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst->I.DstReg.Index = rc_find_free_temporary(c);
+ inst->I.DstReg.WriteMask = WRITEMASK_XYZW;
+
+ inst_mad->I.Opcode = OPCODE_MAD;
+ inst_mad->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_mad->I.DstReg.Index = rc_find_free_temporary(c);
+ inst_mad->I.SrcReg[0] = inst->I.SrcReg[0];
+ inst_mad->I.SrcReg[0].Swizzle = SWIZZLE_ZZZZ;
+ inst_mad->I.SrcReg[1].File = PROGRAM_TEMPORARY;
+ inst_mad->I.SrcReg[1].Index = inst_rcp->I.DstReg.Index;
+ inst_mad->I.SrcReg[1].Swizzle = SWIZZLE_WWWW;
+ inst_mad->I.SrcReg[2].File = PROGRAM_TEMPORARY;
+ inst_mad->I.SrcReg[2].Index = inst->I.DstReg.Index;
+ if (depthmode == 0) /* GL_LUMINANCE */
+ inst_mad->I.SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z);
+ else if (depthmode == 2) /* GL_ALPHA */
+ inst_mad->I.SrcReg[2].Swizzle = SWIZZLE_WWWW;
+
+ /* Recall that SrcReg[0] is tex, SrcReg[2] is r and:
+ * r < tex <=> -tex+r < 0
+ * r >= tex <=> not (-tex+r < 0 */
+ if (comparefunc == GL_LESS || comparefunc == GL_GEQUAL)
+ inst_mad->I.SrcReg[2].Negate = inst_mad->I.SrcReg[2].Negate ^ NEGATE_XYZW;
+ else
+ inst_mad->I.SrcReg[0].Negate = inst_mad->I.SrcReg[0].Negate ^ NEGATE_XYZW;
+
+ inst_cmp->I.Opcode = OPCODE_CMP;
+ /* DstReg has been filled out above */
+ inst_cmp->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst_cmp->I.SrcReg[0].Index = inst_mad->I.DstReg.Index;
+
+ if (comparefunc == GL_LESS || comparefunc == GL_GREATER) {
+ pass = 1;
+ fail = 2;
+ } else {
+ pass = 2;
+ fail = 1;
+ }
+
+ inst_cmp->I.SrcReg[pass].File = PROGRAM_BUILTIN;
+ inst_cmp->I.SrcReg[pass].Swizzle = SWIZZLE_1111;
+ inst_cmp->I.SrcReg[fail] = shadow_ambient(c, inst->I.TexSrcUnit);
+ }
+ }
+
+ /* Cannot write texture to output registers */
+ if (inst->I.Opcode != OPCODE_KIL && inst->I.DstReg.File != PROGRAM_TEMPORARY) {
+ struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst);
+
+ inst_mov->I.Opcode = OPCODE_MOV;
+ inst_mov->I.DstReg = inst->I.DstReg;
+ inst_mov->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst_mov->I.SrcReg[0].Index = rc_find_free_temporary(c);
+
+ inst->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst->I.DstReg.Index = inst_mov->I.SrcReg[0].Index;
+ inst->I.DstReg.WriteMask = WRITEMASK_XYZW;
+ }
+
+ /* Cannot read texture coordinate from constants file */
+ if (inst->I.SrcReg[0].File != PROGRAM_TEMPORARY && inst->I.SrcReg[0].File != PROGRAM_INPUT) {
+ struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst->Prev);
+
+ inst_mov->I.Opcode = OPCODE_MOV;
+ inst_mov->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_mov->I.DstReg.Index = rc_find_free_temporary(c);
+ inst_mov->I.SrcReg[0] = inst->I.SrcReg[0];
+
+ reset_srcreg(&inst->I.SrcReg[0]);
+ inst->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->I.SrcReg[0].Index = inst_mov->I.DstReg.Index;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean r500FPIsNativeSwizzle(GLuint opcode, struct prog_src_register reg)
+{
+ GLuint relevant;
+ int i;
+
+ if (opcode == OPCODE_TEX ||
+ opcode == OPCODE_TXB ||
+ opcode == OPCODE_TXP ||
+ opcode == OPCODE_KIL) {
+ if (reg.Abs)
+ return GL_FALSE;
+
+ if (opcode == OPCODE_KIL && (reg.Swizzle != SWIZZLE_NOOP || reg.Negate != NEGATE_NONE))
+ return GL_FALSE;
+
+ if (reg.Negate)
+ reg.Negate ^= NEGATE_XYZW;
+
+ for(i = 0; i < 4; ++i) {
+ GLuint swz = GET_SWZ(reg.Swizzle, i);
+ if (swz == SWIZZLE_NIL) {
+ reg.Negate &= ~(1 << i);
+ continue;
+ }
+ if (swz >= 4)
+ return GL_FALSE;
+ }
+
+ if (reg.Negate)
+ return GL_FALSE;
+
+ return GL_TRUE;
+ } else if (opcode == OPCODE_DDX || opcode == OPCODE_DDY) {
+ /* DDX/MDH and DDY/MDV explicitly ignore incoming swizzles;
+ * if it doesn't fit perfectly into a .xyzw case... */
+ if (reg.Swizzle == SWIZZLE_NOOP && !reg.Abs && !reg.Negate)
+ return GL_TRUE;
+
+ return GL_FALSE;
+ } else {
+ /* ALU instructions support almost everything */
+ if (reg.Abs)
+ return GL_TRUE;
+
+ relevant = 0;
+ for(i = 0; i < 3; ++i) {
+ GLuint swz = GET_SWZ(reg.Swizzle, i);
+ if (swz != SWIZZLE_NIL && swz != SWIZZLE_ZERO)
+ relevant |= 1 << i;
+ }
+ if ((reg.Negate & relevant) && ((reg.Negate & relevant) != relevant))
+ return GL_FALSE;
+
+ return GL_TRUE;
+ }
+}
+
+/**
+ * Implement a MOV with a potentially non-native swizzle.
+ *
+ * The only thing we *cannot* do in an ALU instruction is per-component
+ * negation. Therefore, we split the MOV into two instructions when necessary.
+ */
+void r500FPBuildSwizzle(struct nqssadce_state *s, struct prog_dst_register dst, struct prog_src_register src)
+{
+ GLuint negatebase[2] = { 0, 0 };
+ int i;
+
+ for(i = 0; i < 4; ++i) {
+ GLuint swz = GET_SWZ(src.Swizzle, i);
+ if (swz == SWIZZLE_NIL)
+ continue;
+ negatebase[GET_BIT(src.Negate, i)] |= 1 << i;
+ }
+
+ for(i = 0; i <= 1; ++i) {
+ if (!negatebase[i])
+ continue;
+
+ struct rc_instruction *inst = rc_insert_new_instruction(s->Compiler, s->IP->Prev);
+ inst->I.Opcode = OPCODE_MOV;
+ inst->I.DstReg = dst;
+ inst->I.DstReg.WriteMask = negatebase[i];
+ inst->I.SrcReg[0] = src;
+ inst->I.SrcReg[0].Negate = (i == 0) ? NEGATE_NONE : NEGATE_XYZW;
+ }
+}
+
+
+static char *toswiz(int swiz_val) {
+ switch(swiz_val) {
+ case 0: return "R";
+ case 1: return "G";
+ case 2: return "B";
+ case 3: return "A";
+ case 4: return "0";
+ case 5: return "1/2";
+ case 6: return "1";
+ case 7: return "U";
+ }
+ return NULL;
+}
+
+static char *toop(int op_val)
+{
+ char *str = NULL;
+ switch (op_val) {
+ case 0: str = "MAD"; break;
+ case 1: str = "DP3"; break;
+ case 2: str = "DP4"; break;
+ case 3: str = "D2A"; break;
+ case 4: str = "MIN"; break;
+ case 5: str = "MAX"; break;
+ case 6: str = "Reserved"; break;
+ case 7: str = "CND"; break;
+ case 8: str = "CMP"; break;
+ case 9: str = "FRC"; break;
+ case 10: str = "SOP"; break;
+ case 11: str = "MDH"; break;
+ case 12: str = "MDV"; break;
+ }
+ return str;
+}
+
+static char *to_alpha_op(int op_val)
+{
+ char *str = NULL;
+ switch (op_val) {
+ case 0: str = "MAD"; break;
+ case 1: str = "DP"; break;
+ case 2: str = "MIN"; break;
+ case 3: str = "MAX"; break;
+ case 4: str = "Reserved"; break;
+ case 5: str = "CND"; break;
+ case 6: str = "CMP"; break;
+ case 7: str = "FRC"; break;
+ case 8: str = "EX2"; break;
+ case 9: str = "LN2"; break;
+ case 10: str = "RCP"; break;
+ case 11: str = "RSQ"; break;
+ case 12: str = "SIN"; break;
+ case 13: str = "COS"; break;
+ case 14: str = "MDH"; break;
+ case 15: str = "MDV"; break;
+ }
+ return str;
+}
+
+static char *to_mask(int val)
+{
+ char *str = NULL;
+ switch(val) {
+ case 0: str = "NONE"; break;
+ case 1: str = "R"; break;
+ case 2: str = "G"; break;
+ case 3: str = "RG"; break;
+ case 4: str = "B"; break;
+ case 5: str = "RB"; break;
+ case 6: str = "GB"; break;
+ case 7: str = "RGB"; break;
+ case 8: str = "A"; break;
+ case 9: str = "AR"; break;
+ case 10: str = "AG"; break;
+ case 11: str = "ARG"; break;
+ case 12: str = "AB"; break;
+ case 13: str = "ARB"; break;
+ case 14: str = "AGB"; break;
+ case 15: str = "ARGB"; break;
+ }
+ return str;
+}
+
+static char *to_texop(int val)
+{
+ switch(val) {
+ case 0: return "NOP";
+ case 1: return "LD";
+ case 2: return "TEXKILL";
+ case 3: return "PROJ";
+ case 4: return "LODBIAS";
+ case 5: return "LOD";
+ case 6: return "DXDY";
+ }
+ return NULL;
+}
+
+void r500FragmentProgramDump(struct rX00_fragment_program_code *c)
+{
+ struct r500_fragment_program_code *code = &c->code.r500;
+ fprintf(stderr, "R500 Fragment Program:\n--------\n");
+
+ int n;
+ uint32_t inst;
+ uint32_t inst0;
+ char *str = NULL;
+
+ for (n = 0; n < code->inst_end+1; n++) {
+ inst0 = inst = code->inst[n].inst0;
+ fprintf(stderr,"%d\t0:CMN_INST 0x%08x:", n, inst);
+ switch(inst & 0x3) {
+ case R500_INST_TYPE_ALU: str = "ALU"; break;
+ case R500_INST_TYPE_OUT: str = "OUT"; break;
+ case R500_INST_TYPE_FC: str = "FC"; break;
+ case R500_INST_TYPE_TEX: str = "TEX"; break;
+ };
+ fprintf(stderr,"%s %s %s %s %s ", str,
+ inst & R500_INST_TEX_SEM_WAIT ? "TEX_WAIT" : "",
+ inst & R500_INST_LAST ? "LAST" : "",
+ inst & R500_INST_NOP ? "NOP" : "",
+ inst & R500_INST_ALU_WAIT ? "ALU WAIT" : "");
+ fprintf(stderr,"wmask: %s omask: %s\n", to_mask((inst >> 11) & 0xf),
+ to_mask((inst >> 15) & 0xf));
+
+ switch(inst0 & 0x3) {
+ case 0:
+ case 1:
+ fprintf(stderr,"\t1:RGB_ADDR 0x%08x:", code->inst[n].inst1);
+ inst = code->inst[n].inst1;
+
+ fprintf(stderr,"Addr0: %d%c, Addr1: %d%c, Addr2: %d%c, srcp:%d\n",
+ inst & 0xff, (inst & (1<<8)) ? 'c' : 't',
+ (inst >> 10) & 0xff, (inst & (1<<18)) ? 'c' : 't',
+ (inst >> 20) & 0xff, (inst & (1<<28)) ? 'c' : 't',
+ (inst >> 30));
+
+ fprintf(stderr,"\t2:ALPHA_ADDR 0x%08x:", code->inst[n].inst2);
+ inst = code->inst[n].inst2;
+ fprintf(stderr,"Addr0: %d%c, Addr1: %d%c, Addr2: %d%c, srcp:%d\n",
+ inst & 0xff, (inst & (1<<8)) ? 'c' : 't',
+ (inst >> 10) & 0xff, (inst & (1<<18)) ? 'c' : 't',
+ (inst >> 20) & 0xff, (inst & (1<<28)) ? 'c' : 't',
+ (inst >> 30));
+ fprintf(stderr,"\t3 RGB_INST: 0x%08x:", code->inst[n].inst3);
+ inst = code->inst[n].inst3;
+ fprintf(stderr,"rgb_A_src:%d %s/%s/%s %d rgb_B_src:%d %s/%s/%s %d\n",
+ (inst) & 0x3, toswiz((inst >> 2) & 0x7), toswiz((inst >> 5) & 0x7), toswiz((inst >> 8) & 0x7),
+ (inst >> 11) & 0x3,
+ (inst >> 13) & 0x3, toswiz((inst >> 15) & 0x7), toswiz((inst >> 18) & 0x7), toswiz((inst >> 21) & 0x7),
+ (inst >> 24) & 0x3);
+
+
+ fprintf(stderr,"\t4 ALPHA_INST:0x%08x:", code->inst[n].inst4);
+ inst = code->inst[n].inst4;
+ fprintf(stderr,"%s dest:%d%s alp_A_src:%d %s %d alp_B_src:%d %s %d w:%d\n", to_alpha_op(inst & 0xf),
+ (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"",
+ (inst >> 12) & 0x3, toswiz((inst >> 14) & 0x7), (inst >> 17) & 0x3,
+ (inst >> 19) & 0x3, toswiz((inst >> 21) & 0x7), (inst >> 24) & 0x3,
+ (inst >> 31) & 0x1);
+
+ fprintf(stderr,"\t5 RGBA_INST: 0x%08x:", code->inst[n].inst5);
+ inst = code->inst[n].inst5;
+ fprintf(stderr,"%s dest:%d%s rgb_C_src:%d %s/%s/%s %d alp_C_src:%d %s %d\n", toop(inst & 0xf),
+ (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"",
+ (inst >> 12) & 0x3, toswiz((inst >> 14) & 0x7), toswiz((inst >> 17) & 0x7), toswiz((inst >> 20) & 0x7),
+ (inst >> 23) & 0x3,
+ (inst >> 25) & 0x3, toswiz((inst >> 27) & 0x7), (inst >> 30) & 0x3);
+ break;
+ case 2:
+ break;
+ case 3:
+ inst = code->inst[n].inst1;
+ fprintf(stderr,"\t1:TEX_INST: 0x%08x: id: %d op:%s, %s, %s %s\n", inst, (inst >> 16) & 0xf,
+ to_texop((inst >> 22) & 0x7), (inst & (1<<25)) ? "ACQ" : "",
+ (inst & (1<<26)) ? "IGNUNC" : "", (inst & (1<<27)) ? "UNSCALED" : "SCALED");
+ inst = code->inst[n].inst2;
+ fprintf(stderr,"\t2:TEX_ADDR: 0x%08x: src: %d%s %s/%s/%s/%s dst: %d%s %s/%s/%s/%s\n", inst,
+ inst & 127, inst & (1<<7) ? "(rel)" : "",
+ toswiz((inst >> 8) & 0x3), toswiz((inst >> 10) & 0x3),
+ toswiz((inst >> 12) & 0x3), toswiz((inst >> 14) & 0x3),
+ (inst >> 16) & 127, inst & (1<<23) ? "(rel)" : "",
+ toswiz((inst >> 24) & 0x3), toswiz((inst >> 26) & 0x3),
+ toswiz((inst >> 28) & 0x3), toswiz((inst >> 30) & 0x3));
+
+ fprintf(stderr,"\t3:TEX_DXDY: 0x%08x\n", code->inst[n].inst3);
+ break;
+ }
+ fprintf(stderr,"\n");
+ }
+
+}
diff --git a/src/mesa/drivers/dri/r300/r500_fragprog.h b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h
index 1e45538f80..9091f65cd2 100644
--- a/src/mesa/drivers/dri/r300/r500_fragprog.h
+++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog.h
@@ -33,30 +33,23 @@
#ifndef __R500_FRAGPROG_H_
#define __R500_FRAGPROG_H_
-#include "main/glheader.h"
-#include "main/macros.h"
-#include "main/enums.h"
#include "shader/prog_parameter.h"
-#include "shader/prog_print.h"
-#include "shader/program.h"
#include "shader/prog_instruction.h"
-#include "r300_context.h"
-#include "r300_state.h"
-#include "radeon_program.h"
+#include "radeon_compiler.h"
+#include "radeon_nqssadce.h"
-struct r500_fragment_program;
+extern void r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler);
-extern void r500TranslateFragmentShader(r300ContextPtr r300,
- struct r500_fragment_program *fp);
+extern void r500FragmentProgramDump(struct rX00_fragment_program_code *c);
-struct r500_fragment_program_compiler {
- r300ContextPtr r300;
- struct r500_fragment_program *fp;
- struct r500_fragment_program_code *code;
- struct gl_program *program;
-};
+extern GLboolean r500FPIsNativeSwizzle(GLuint opcode, struct prog_src_register reg);
-extern GLboolean r500FragmentProgramEmit(struct r500_fragment_program_compiler *compiler);
+extern void r500FPBuildSwizzle(struct nqssadce_state *s, struct prog_dst_register dst, struct prog_src_register src);
+
+extern GLboolean r500_transform_TEX(
+ struct radeon_compiler * c,
+ struct rc_instruction * inst,
+ void* data);
#endif
diff --git a/src/mesa/drivers/dri/r300/r500_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
index 4631235f0d..d694725c9b 100644
--- a/src/mesa/drivers/dri/r300/r500_fragprog_emit.c
+++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
@@ -45,47 +45,22 @@
#include "r500_fragprog.h"
+#include "../r300_reg.h"
+
#include "radeon_program_pair.h"
#define PROG_CODE \
- struct r500_fragment_program_compiler *c = (struct r500_fragment_program_compiler*)data; \
- struct r500_fragment_program_code *code = c->code
+ struct r300_fragment_program_compiler *c = (struct r300_fragment_program_compiler*)data; \
+ struct r500_fragment_program_code *code = &c->code->code.r500
#define error(fmt, args...) do { \
- fprintf(stderr, "%s::%s(): " fmt "\n", \
+ rc_error(&c->Base, "%s::%s(): " fmt "\n", \
__FILE__, __FUNCTION__, ##args); \
} while(0)
-/**
- * Callback to register hardware constants.
- */
-static GLboolean emit_const(void *data, GLuint file, GLuint idx, GLuint *hwindex)
-{
- PROG_CODE;
-
- for (*hwindex = 0; *hwindex < code->const_nr; ++*hwindex) {
- if (code->constant[*hwindex].File == file &&
- code->constant[*hwindex].Index == idx)
- break;
- }
-
- if (*hwindex >= code->const_nr) {
- if (*hwindex >= PFS_NUM_CONST_REGS) {
- error("Out of hw constants!\n");
- return GL_FALSE;
- }
-
- code->const_nr++;
- code->constant[*hwindex].File = file;
- code->constant[*hwindex].Index = idx;
- }
-
- return GL_TRUE;
-}
-
-static GLuint translate_rgb_op(GLuint opcode)
+static GLuint translate_rgb_op(struct r300_fragment_program_compiler *c, GLuint opcode)
{
switch(opcode) {
case OPCODE_CMP: return R500_ALU_RGBA_OP_CMP;
@@ -106,7 +81,7 @@ static GLuint translate_rgb_op(GLuint opcode)
}
}
-static GLuint translate_alpha_op(GLuint opcode)
+static GLuint translate_alpha_op(struct r300_fragment_program_compiler *c, GLuint opcode)
{
switch(opcode) {
case OPCODE_CMP: return R500_ALPHA_OP_CMP;
@@ -189,8 +164,8 @@ static GLboolean emit_paired(void *data, struct radeon_pair_instruction *inst)
int ip = ++code->inst_end;
- code->inst[ip].inst5 = translate_rgb_op(inst->RGB.Opcode);
- code->inst[ip].inst4 = translate_alpha_op(inst->Alpha.Opcode);
+ code->inst[ip].inst5 = translate_rgb_op(c, inst->RGB.Opcode);
+ code->inst[ip].inst4 = translate_alpha_op(c, inst->Alpha.Opcode);
if (inst->RGB.OutputWriteMask || inst->Alpha.OutputWriteMask || inst->Alpha.DepthWriteMask)
code->inst[ip].inst0 = R500_INST_TYPE_OUT;
@@ -202,7 +177,7 @@ static GLboolean emit_paired(void *data, struct radeon_pair_instruction *inst)
code->inst[ip].inst0 |= (inst->RGB.OutputWriteMask << 15) | (inst->Alpha.OutputWriteMask << 18);
if (inst->Alpha.DepthWriteMask) {
code->inst[ip].inst4 |= R500_ALPHA_W_OMASK;
- c->fp->writes_depth = GL_TRUE;
+ c->code->writes_depth = GL_TRUE;
}
code->inst[ip].inst4 |= R500_ALPHA_ADDRD(inst->Alpha.DestIndex);
@@ -234,19 +209,19 @@ static GLboolean emit_paired(void *data, struct radeon_pair_instruction *inst)
return GL_TRUE;
}
-static GLuint translate_strq_swizzle(struct prog_src_register src)
+static GLuint translate_strq_swizzle(GLuint swizzle)
{
GLuint swiz = 0;
int i;
for (i = 0; i < 4; i++)
- swiz |= (GET_SWZ(src.Swizzle, i) & 0x3) << i*2;
+ swiz |= (GET_SWZ(swizzle, i) & 0x3) << i*2;
return swiz;
}
/**
* Emit a single TEX instruction
*/
-static GLboolean emit_tex(void *data, struct prog_instruction *inst)
+static GLboolean emit_tex(void *data, struct radeon_pair_texture_instruction *inst)
{
PROG_CODE;
@@ -258,7 +233,7 @@ static GLboolean emit_tex(void *data, struct prog_instruction *inst)
int ip = ++code->inst_end;
code->inst[ip].inst0 = R500_INST_TYPE_TEX
- | (inst->DstReg.WriteMask << 11)
+ | (inst->WriteMask << 11)
| R500_INST_TEX_SEM_WAIT;
code->inst[ip].inst1 = R500_TEX_ID(inst->TexSrcUnit)
| R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED;
@@ -267,25 +242,25 @@ static GLboolean emit_tex(void *data, struct prog_instruction *inst)
code->inst[ip].inst1 |= R500_TEX_UNSCALED;
switch (inst->Opcode) {
- case OPCODE_KIL:
+ case RADEON_OPCODE_KIL:
code->inst[ip].inst1 |= R500_TEX_INST_TEXKILL;
break;
- case OPCODE_TEX:
+ case RADEON_OPCODE_TEX:
code->inst[ip].inst1 |= R500_TEX_INST_LD;
break;
- case OPCODE_TXB:
+ case RADEON_OPCODE_TXB:
code->inst[ip].inst1 |= R500_TEX_INST_LODBIAS;
break;
- case OPCODE_TXP:
+ case RADEON_OPCODE_TXP:
code->inst[ip].inst1 |= R500_TEX_INST_PROJ;
break;
default:
error("emit_tex can't handle opcode %x\n", inst->Opcode);
}
- code->inst[ip].inst2 = R500_TEX_SRC_ADDR(inst->SrcReg[0].Index)
- | (translate_strq_swizzle(inst->SrcReg[0]) << 8)
- | R500_TEX_DST_ADDR(inst->DstReg.Index)
+ code->inst[ip].inst2 = R500_TEX_SRC_ADDR(inst->SrcIndex)
+ | (translate_strq_swizzle(inst->SrcSwizzle) << 8)
+ | R500_TEX_DST_ADDR(inst->DestIndex)
| R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G
| R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A;
@@ -293,35 +268,32 @@ static GLboolean emit_tex(void *data, struct prog_instruction *inst)
}
static const struct radeon_pair_handler pair_handler = {
- .EmitConst = emit_const,
.EmitPaired = emit_paired,
.EmitTex = emit_tex,
.MaxHwTemps = 128
};
-GLboolean r500FragmentProgramEmit(struct r500_fragment_program_compiler *compiler)
+void r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compiler)
{
- struct r500_fragment_program_code *code = compiler->code;
+ struct r500_fragment_program_code *code = &compiler->code->code.r500;
_mesa_bzero(code, sizeof(*code));
code->max_temp_idx = 1;
- code->inst_offset = 0;
code->inst_end = -1;
- if (!radeonPairProgram(compiler->r300->radeon.glCtx, compiler->program, &pair_handler, compiler))
- return GL_FALSE;
+ radeonPairProgram(compiler, &pair_handler, compiler);
+ if (compiler->Base.Error)
+ return;
if ((code->inst[code->inst_end].inst0 & R500_INST_TYPE_MASK) != R500_INST_TYPE_OUT) {
/* This may happen when dead-code elimination is disabled or
* when most of the fragment program logic is leading to a KIL */
if (code->inst_end >= 511) {
- error("Introducing fake OUT: Too many instructions");
- return GL_FALSE;
+ rc_error(&compiler->Base, "Introducing fake OUT: Too many instructions");
+ return;
}
int ip = ++code->inst_end;
code->inst[ip].inst0 = R500_INST_TYPE_OUT | R500_INST_TEX_SEM_WAIT;
}
-
- return GL_TRUE;
}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.c b/src/mesa/drivers/dri/r300/compiler/radeon_code.c
new file mode 100644
index 0000000000..c7923004df
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2009 Nicolai Haehnle.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "main/mtypes.h"
+#include "shader/prog_instruction.h"
+
+#include "radeon_code.h"
+
+void rc_constants_init(struct rc_constant_list * c)
+{
+ memset(c, 0, sizeof(*c));
+}
+
+/**
+ * Copy a constants structure, assuming that the destination structure
+ * is not initialized.
+ */
+void rc_constants_copy(struct rc_constant_list * dst, struct rc_constant_list * src)
+{
+ dst->Constants = malloc(sizeof(struct rc_constant) * src->Count);
+ memcpy(dst->Constants, src->Constants, sizeof(struct rc_constant) * src->Count);
+ dst->Count = src->Count;
+ dst->_Reserved = src->Count;
+}
+
+void rc_constants_destroy(struct rc_constant_list * c)
+{
+ free(c->Constants);
+ memset(c, 0, sizeof(*c));
+}
+
+unsigned rc_constants_add(struct rc_constant_list * c, struct rc_constant * constant)
+{
+ unsigned index = c->Count;
+
+ if (c->Count >= c->_Reserved) {
+ struct rc_constant * newlist;
+
+ c->_Reserved = c->_Reserved * 2;
+ if (!c->_Reserved)
+ c->_Reserved = 16;
+
+ newlist = malloc(sizeof(struct rc_constant) * c->_Reserved);
+ memcpy(newlist, c->Constants, sizeof(struct rc_constant) * c->Count);
+
+ free(c->Constants);
+ c->Constants = newlist;
+ }
+
+ c->Constants[index] = *constant;
+ c->Count++;
+
+ return index;
+}
+
+
+/**
+ * Add a state vector to the constant list, while trying to avoid duplicates.
+ */
+unsigned rc_constants_add_state(struct rc_constant_list * c, unsigned state0, unsigned state1)
+{
+ unsigned index;
+ struct rc_constant constant;
+
+ for(index = 0; index < c->Count; ++index) {
+ if (c->Constants[index].Type == RC_CONSTANT_STATE) {
+ if (c->Constants[index].u.State[0] == state0 &&
+ c->Constants[index].u.State[1] == state1)
+ return index;
+ }
+ }
+
+ memset(&constant, 0, sizeof(constant));
+ constant.Type = RC_CONSTANT_STATE;
+ constant.Size = 4;
+ constant.u.State[0] = state0;
+ constant.u.State[1] = state1;
+
+ return rc_constants_add(c, &constant);
+}
+
+
+/**
+ * Add an immediate vector to the constant list, while trying to avoid
+ * duplicates.
+ */
+unsigned rc_constants_add_immediate_vec4(struct rc_constant_list * c, const float * data)
+{
+ unsigned index;
+ struct rc_constant constant;
+
+ for(index = 0; index < c->Count; ++index) {
+ if (c->Constants[index].Type == RC_CONSTANT_IMMEDIATE) {
+ if (!memcmp(c->Constants[index].u.Immediate, data, sizeof(float)*4))
+ return index;
+ }
+ }
+
+ memset(&constant, 0, sizeof(constant));
+ constant.Type = RC_CONSTANT_IMMEDIATE;
+ constant.Size = 4;
+ memcpy(constant.u.Immediate, data, sizeof(float) * 4);
+
+ return rc_constants_add(c, &constant);
+}
+
+
+/**
+ * Add an immediate scalar to the constant list, while trying to avoid
+ * duplicates.
+ */
+unsigned rc_constants_add_immediate_scalar(struct rc_constant_list * c, float data, unsigned * swizzle)
+{
+ unsigned index;
+ int free_index = -1;
+ struct rc_constant constant;
+
+ for(index = 0; index < c->Count; ++index) {
+ if (c->Constants[index].Type == RC_CONSTANT_IMMEDIATE) {
+ for(unsigned comp = 0; comp < c->Constants[index].Size; ++comp) {
+ if (c->Constants[index].u.Immediate[comp] == data) {
+ *swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
+ return index;
+ }
+ }
+
+ if (c->Constants[index].Size < 4)
+ free_index = index;
+ }
+ }
+
+ if (free_index >= 0) {
+ unsigned comp = c->Constants[free_index].Size++;
+ c->Constants[free_index].u.Immediate[comp] = data;
+ *swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
+ return free_index;
+ }
+
+ memset(&constant, 0, sizeof(constant));
+ constant.Type = RC_CONSTANT_IMMEDIATE;
+ constant.Size = 1;
+ constant.u.Immediate[0] = data;
+ *swizzle = SWIZZLE_XXXX;
+
+ return rc_constants_add(c, &constant);
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
new file mode 100644
index 0000000000..3e88554ba1
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef RADEON_CODE_H
+#define RADEON_CODE_H
+
+#include <stdint.h>
+
+#define R300_PFS_MAX_ALU_INST 64
+#define R300_PFS_MAX_TEX_INST 32
+#define R300_PFS_MAX_TEX_INDIRECT 4
+#define R300_PFS_NUM_TEMP_REGS 32
+#define R300_PFS_NUM_CONST_REGS 32
+
+#define R500_PFS_MAX_INST 512
+#define R500_PFS_NUM_TEMP_REGS 128
+#define R500_PFS_NUM_CONST_REGS 256
+
+
+#define STATE_R300_WINDOW_DIMENSION (STATE_INTERNAL_DRIVER+0)
+
+enum {
+ /**
+ * External constants are constants whose meaning is unknown to this
+ * compiler. For example, a Mesa gl_program's constants are turned
+ * into external constants.
+ */
+ RC_CONSTANT_EXTERNAL = 0,
+
+ RC_CONSTANT_IMMEDIATE,
+
+ /**
+ * Constant referring to state that is known by this compiler,
+ * see RC_STATE_xxx, i.e. *not* arbitrary Mesa (or other) state.
+ */
+ RC_CONSTANT_STATE
+};
+
+enum {
+ RC_STATE_SHADOW_AMBIENT = 0,
+
+ RC_STATE_R300_WINDOW_DIMENSION,
+ RC_STATE_R300_TEXRECT_FACTOR
+};
+
+struct rc_constant {
+ unsigned Type:2; /**< RC_CONSTANT_xxx */
+ unsigned Size:3;
+
+ union {
+ unsigned External;
+ float Immediate[4];
+ unsigned State[2];
+ } u;
+};
+
+struct rc_constant_list {
+ struct rc_constant * Constants;
+ unsigned Count;
+
+ unsigned _Reserved;
+};
+
+void rc_constants_init(struct rc_constant_list * c);
+void rc_constants_copy(struct rc_constant_list * dst, struct rc_constant_list * src);
+void rc_constants_destroy(struct rc_constant_list * c);
+unsigned rc_constants_add(struct rc_constant_list * c, struct rc_constant * constant);
+unsigned rc_constants_add_state(struct rc_constant_list * c, unsigned state1, unsigned state2);
+unsigned rc_constants_add_immediate_vec4(struct rc_constant_list * c, const float * data);
+unsigned rc_constants_add_immediate_scalar(struct rc_constant_list * c, float data, unsigned * swizzle);
+
+/**
+ * Stores state that influences the compilation of a fragment program.
+ */
+struct r300_fragment_program_external_state {
+ struct {
+ /**
+ * If the sampler is used as a shadow sampler,
+ * this field is:
+ * 0 - GL_LUMINANCE
+ * 1 - GL_INTENSITY
+ * 2 - GL_ALPHA
+ * depending on the depth texture mode.
+ */
+ unsigned depth_texture_mode : 2;
+
+ /**
+ * If the sampler is used as a shadow sampler,
+ * this field is (texture_compare_func - GL_NEVER).
+ * [e.g. if compare function is GL_LEQUAL, this field is 3]
+ *
+ * Otherwise, this field is 0.
+ */
+ unsigned texture_compare_func : 3;
+ } unit[16];
+};
+
+
+
+struct r300_fragment_program_node {
+ int tex_offset; /**< first tex instruction */
+ int tex_end; /**< last tex instruction, relative to tex_offset */
+ int alu_offset; /**< first ALU instruction */
+ int alu_end; /**< last ALU instruction, relative to alu_offset */
+ int flags;
+};
+
+/**
+ * Stores an R300 fragment program in its compiled-to-hardware form.
+ */
+struct r300_fragment_program_code {
+ struct {
+ int length; /**< total # of texture instructions used */
+ uint32_t inst[R300_PFS_MAX_TEX_INST];
+ } tex;
+
+ struct {
+ 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];
+ } alu;
+
+ uint32_t config; /* US_CONFIG */
+ uint32_t pixsize; /* US_PIXSIZE */
+ uint32_t code_offset; /* US_CODE_OFFSET */
+ uint32_t code_addr[4]; /* US_CODE_ADDR */
+};
+
+
+struct r500_fragment_program_code {
+ struct {
+ uint32_t inst0;
+ uint32_t inst1;
+ uint32_t inst2;
+ uint32_t inst3;
+ uint32_t inst4;
+ uint32_t inst5;
+ } inst[R500_PFS_MAX_INST];
+
+ int inst_end; /* Number of instructions - 1; also, last instruction to be executed */
+
+ int max_temp_idx;
+};
+
+struct rX00_fragment_program_code {
+ union {
+ struct r300_fragment_program_code r300;
+ struct r500_fragment_program_code r500;
+ } code;
+
+ unsigned writes_depth:1;
+
+ struct rc_constant_list constants;
+};
+
+
+#define VSF_MAX_FRAGMENT_LENGTH (255*4)
+#define VSF_MAX_FRAGMENT_TEMPS (14)
+
+#define VSF_MAX_INPUTS 32
+#define VSF_MAX_OUTPUTS 32
+
+struct r300_vertex_program_code {
+ int length;
+ union {
+ uint32_t d[VSF_MAX_FRAGMENT_LENGTH];
+ float f[VSF_MAX_FRAGMENT_LENGTH];
+ } body;
+
+ int pos_end;
+ int num_temporaries; /* Number of temp vars used by program */
+ int inputs[VSF_MAX_INPUTS];
+ int outputs[VSF_MAX_OUTPUTS];
+
+ struct rc_constant_list constants;
+
+ uint32_t InputsRead;
+ uint32_t OutputsWritten;
+};
+
+void r300_vertex_program_dump(struct r300_vertex_program_code * vs);
+
+#endif /* RADEON_CODE_H */
+
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
new file mode 100644
index 0000000000..da950d5289
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "radeon_compiler.h"
+
+#include <stdarg.h>
+
+#include "radeon_program.h"
+
+
+void rc_init(struct radeon_compiler * c)
+{
+ memset(c, 0, sizeof(*c));
+
+ memory_pool_init(&c->Pool);
+ c->Program.Instructions.Prev = &c->Program.Instructions;
+ c->Program.Instructions.Next = &c->Program.Instructions;
+ c->Program.Instructions.I.Opcode = OPCODE_END;
+}
+
+void rc_destroy(struct radeon_compiler * c)
+{
+ rc_constants_destroy(&c->Program.Constants);
+ memory_pool_destroy(&c->Pool);
+ free(c->ErrorMsg);
+}
+
+void rc_debug(struct radeon_compiler * c, const char * fmt, ...)
+{
+ va_list ap;
+
+ if (!c->Debug)
+ return;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+void rc_error(struct radeon_compiler * c, const char * fmt, ...)
+{
+ va_list ap;
+
+ c->Error = GL_TRUE;
+
+ if (!c->ErrorMsg) {
+ /* Only remember the first error */
+ char buf[1024];
+ int written;
+
+ va_start(ap, fmt);
+ written = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ if (written < sizeof(buf)) {
+ c->ErrorMsg = strdup(buf);
+ } else {
+ c->ErrorMsg = malloc(written + 1);
+
+ va_start(ap, fmt);
+ vsnprintf(c->ErrorMsg, written + 1, fmt, ap);
+ va_end(ap);
+ }
+ }
+
+ if (c->Debug) {
+ fprintf(stderr, "r300compiler error: ");
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+}
+
+/**
+ * Rewrite the program such that everything that source the given input
+ * register will source new_input instead.
+ */
+void rc_move_input(struct radeon_compiler * c, unsigned input, struct prog_src_register new_input)
+{
+ struct rc_instruction * inst;
+
+ c->Program.InputsRead &= ~(1 << input);
+
+ for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
+ const unsigned numsrcs = _mesa_num_inst_src_regs(inst->I.Opcode);
+ unsigned i;
+
+ for(i = 0; i < numsrcs; ++i) {
+ if (inst->I.SrcReg[i].File == PROGRAM_INPUT && inst->I.SrcReg[i].Index == input) {
+ inst->I.SrcReg[i].File = new_input.File;
+ inst->I.SrcReg[i].Index = new_input.Index;
+ inst->I.SrcReg[i].Swizzle = combine_swizzles(new_input.Swizzle, inst->I.SrcReg[i].Swizzle);
+ if (!inst->I.SrcReg[i].Abs) {
+ inst->I.SrcReg[i].Negate ^= new_input.Negate;
+ inst->I.SrcReg[i].Abs = new_input.Abs;
+ }
+
+ c->Program.InputsRead |= 1 << new_input.Index;
+ }
+ }
+ }
+}
+
+
+/**
+ * Rewrite the program such that everything that writes into the given
+ * output register will instead write to new_output. The new_output
+ * writemask is honoured.
+ */
+void rc_move_output(struct radeon_compiler * c, unsigned output, unsigned new_output, unsigned writemask)
+{
+ struct rc_instruction * inst;
+
+ c->Program.OutputsWritten &= ~(1 << output);
+
+ for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
+ const unsigned numdsts = _mesa_num_inst_dst_regs(inst->I.Opcode);
+
+ if (numdsts) {
+ if (inst->I.DstReg.File == PROGRAM_OUTPUT && inst->I.DstReg.Index == output) {
+ inst->I.DstReg.Index = new_output;
+ inst->I.DstReg.WriteMask &= writemask;
+
+ c->Program.OutputsWritten |= 1 << new_output;
+ }
+ }
+ }
+}
+
+
+/**
+ * Rewrite the program such that a given output is duplicated.
+ */
+void rc_copy_output(struct radeon_compiler * c, unsigned output, unsigned dup_output)
+{
+ unsigned tempreg = rc_find_free_temporary(c);
+ struct rc_instruction * inst;
+
+ for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
+ const unsigned numdsts = _mesa_num_inst_dst_regs(inst->I.Opcode);
+
+ if (numdsts) {
+ if (inst->I.DstReg.File == PROGRAM_OUTPUT && inst->I.DstReg.Index == output) {
+ inst->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst->I.DstReg.Index = tempreg;
+ }
+ }
+ }
+
+ inst = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
+ inst->I.Opcode = OPCODE_MOV;
+ inst->I.DstReg.File = PROGRAM_OUTPUT;
+ inst->I.DstReg.Index = output;
+
+ inst->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->I.SrcReg[0].Index = tempreg;
+ inst->I.SrcReg[0].Swizzle = SWIZZLE_XYZW;
+
+ inst = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
+ inst->I.Opcode = OPCODE_MOV;
+ inst->I.DstReg.File = PROGRAM_OUTPUT;
+ inst->I.DstReg.Index = dup_output;
+
+ inst->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->I.SrcReg[0].Index = tempreg;
+ inst->I.SrcReg[0].Swizzle = SWIZZLE_XYZW;
+
+ c->Program.OutputsWritten |= 1 << dup_output;
+}
+
+
+/**
+ * Introduce standard code fragment to deal with fragment.position.
+ */
+void rc_transform_fragment_wpos(struct radeon_compiler * c, unsigned wpos, unsigned new_input)
+{
+ unsigned tempregi = rc_find_free_temporary(c);
+
+ c->Program.InputsRead &= ~(1 << wpos);
+ c->Program.InputsRead |= 1 << new_input;
+
+ /* perspective divide */
+ struct rc_instruction * inst_rcp = rc_insert_new_instruction(c, &c->Program.Instructions);
+ inst_rcp->I.Opcode = OPCODE_RCP;
+
+ inst_rcp->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_rcp->I.DstReg.Index = tempregi;
+ inst_rcp->I.DstReg.WriteMask = WRITEMASK_W;
+
+ inst_rcp->I.SrcReg[0].File = PROGRAM_INPUT;
+ inst_rcp->I.SrcReg[0].Index = new_input;
+ inst_rcp->I.SrcReg[0].Swizzle = SWIZZLE_WWWW;
+
+ struct rc_instruction * inst_mul = rc_insert_new_instruction(c, inst_rcp);
+ inst_mul->I.Opcode = OPCODE_MUL;
+
+ inst_mul->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_mul->I.DstReg.Index = tempregi;
+ inst_mul->I.DstReg.WriteMask = WRITEMASK_XYZ;
+
+ inst_mul->I.SrcReg[0].File = PROGRAM_INPUT;
+ inst_mul->I.SrcReg[0].Index = new_input;
+
+ inst_mul->I.SrcReg[1].File = PROGRAM_TEMPORARY;
+ inst_mul->I.SrcReg[1].Index = tempregi;
+ inst_mul->I.SrcReg[1].Swizzle = SWIZZLE_WWWW;
+
+ /* viewport transformation */
+ struct rc_instruction * inst_mad = rc_insert_new_instruction(c, inst_mul);
+ inst_mad->I.Opcode = OPCODE_MAD;
+
+ inst_mad->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst_mad->I.DstReg.Index = tempregi;
+ inst_mad->I.DstReg.WriteMask = WRITEMASK_XYZ;
+
+ inst_mad->I.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst_mad->I.SrcReg[0].Index = tempregi;
+ inst_mad->I.SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
+
+ inst_mad->I.SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst_mad->I.SrcReg[1].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_WINDOW_DIMENSION, 0);
+ inst_mad->I.SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
+
+ inst_mad->I.SrcReg[2].File = PROGRAM_STATE_VAR;
+ inst_mad->I.SrcReg[2].Index = inst_mad->I.SrcReg[1].Index;
+ inst_mad->I.SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
+
+ struct rc_instruction * inst;
+ for (inst = inst_mad->Next; inst != &c->Program.Instructions; inst = inst->Next) {
+ const unsigned numsrcs = _mesa_num_inst_src_regs(inst->I.Opcode);
+ unsigned i;
+
+ for(i = 0; i < numsrcs; i++) {
+ if (inst->I.SrcReg[i].File == PROGRAM_INPUT &&
+ inst->I.SrcReg[i].Index == wpos) {
+ inst->I.SrcReg[i].File = PROGRAM_TEMPORARY;
+ inst->I.SrcReg[i].Index = tempregi;
+ }
+ }
+ }
+}
+
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
new file mode 100644
index 0000000000..e63ab8840a
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef RADEON_COMPILER_H
+#define RADEON_COMPILER_H
+
+#include "main/mtypes.h"
+#include "shader/prog_instruction.h"
+
+#include "memory_pool.h"
+#include "radeon_code.h"
+
+
+struct rc_instruction {
+ struct rc_instruction * Prev;
+ struct rc_instruction * Next;
+ struct prog_instruction I;
+};
+
+struct rc_program {
+ /**
+ * Instructions.Next points to the first instruction,
+ * Instructions.Prev points to the last instruction.
+ */
+ struct rc_instruction Instructions;
+
+ /* Long term, we should probably remove InputsRead & OutputsWritten,
+ * since updating dependent state can be fragile, and they aren't
+ * actually used very often. */
+ uint32_t InputsRead;
+ uint32_t OutputsWritten;
+ uint32_t ShadowSamplers; /**< Texture units used for shadow sampling. */
+
+ struct rc_constant_list Constants;
+};
+
+struct radeon_compiler {
+ struct memory_pool Pool;
+ struct rc_program Program;
+ unsigned Debug:1;
+ unsigned Error:1;
+ char * ErrorMsg;
+};
+
+void rc_init(struct radeon_compiler * c);
+void rc_destroy(struct radeon_compiler * c);
+
+void rc_debug(struct radeon_compiler * c, const char * fmt, ...);
+void rc_error(struct radeon_compiler * c, const char * fmt, ...);
+
+void rc_mesa_to_rc_program(struct radeon_compiler * c, struct gl_program * program);
+
+void rc_calculate_inputs_outputs(struct radeon_compiler * c);
+
+void rc_move_input(struct radeon_compiler * c, unsigned input, struct prog_src_register new_input);
+void rc_move_output(struct radeon_compiler * c, unsigned output, unsigned new_output, unsigned writemask);
+void rc_copy_output(struct radeon_compiler * c, unsigned output, unsigned dup_output);
+void rc_transform_fragment_wpos(struct radeon_compiler * c, unsigned wpos, unsigned new_input);
+
+struct r300_fragment_program_compiler {
+ struct radeon_compiler Base;
+ struct rX00_fragment_program_code *code;
+ struct r300_fragment_program_external_state state;
+ unsigned is_r500;
+ unsigned OutputDepth;
+ unsigned OutputColor;
+
+ void * UserData;
+ void (*AllocateHwInputs)(
+ struct r300_fragment_program_compiler * c,
+ void (*allocate)(void * data, unsigned input, unsigned hwreg),
+ void * mydata);
+};
+
+void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c);
+
+
+struct r300_vertex_program_compiler {
+ struct radeon_compiler Base;
+ struct r300_vertex_program_code *code;
+ GLbitfield RequiredOutputs;
+
+ void * UserData;
+ void (*SetHwInputOutput)(struct r300_vertex_program_compiler * c);
+};
+
+void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* c);
+
+#endif /* RADEON_COMPILER_H */
diff --git a/src/mesa/drivers/dri/r300/radeon_nqssadce.c b/src/mesa/drivers/dri/r300/compiler/radeon_nqssadce.c
index 97ce016c99..aaaa50ad1f 100644
--- a/src/mesa/drivers/dri/r300/radeon_nqssadce.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_nqssadce.c
@@ -36,6 +36,8 @@
#include "radeon_nqssadce.h"
+#include "radeon_compiler.h"
+
/**
* Return the @ref register_state for the given register (or 0 for untracked
@@ -46,6 +48,7 @@ static struct register_state *get_reg_state(struct nqssadce_state* s, GLuint fil
switch(file) {
case PROGRAM_TEMPORARY: return &s->Temps[index];
case PROGRAM_OUTPUT: return &s->Outputs[index];
+ case PROGRAM_ADDRESS: return &s->Address;
default: return 0;
}
}
@@ -56,17 +59,17 @@ static struct register_state *get_reg_state(struct nqssadce_state* s, GLuint fil
*
* @note Works correctly only for X, Y, Z, W swizzles, not for constant swizzles.
*/
-static struct prog_src_register lmul_swizzle(GLuint swizzle, struct prog_src_register srcreg)
+struct prog_src_register lmul_swizzle(GLuint swizzle, struct prog_src_register srcreg)
{
struct prog_src_register tmp = srcreg;
int i;
tmp.Swizzle = 0;
- tmp.NegateBase = 0;
+ tmp.Negate = NEGATE_NONE;
for(i = 0; i < 4; ++i) {
GLuint swz = GET_SWZ(swizzle, i);
if (swz < 4) {
tmp.Swizzle |= GET_SWZ(srcreg.Swizzle, swz) << (i*3);
- tmp.NegateBase |= GET_BIT(srcreg.NegateBase, swz) << i;
+ tmp.Negate |= GET_BIT(srcreg.Negate, swz) << i;
} else {
tmp.Swizzle |= swz << (i*3);
}
@@ -75,9 +78,10 @@ static struct prog_src_register lmul_swizzle(GLuint swizzle, struct prog_src_reg
}
-static struct prog_instruction* track_used_srcreg(struct nqssadce_state* s,
- struct prog_instruction *inst, GLint src, GLuint sourced)
+static void track_used_srcreg(struct nqssadce_state* s,
+ GLint src, GLuint sourced)
{
+ struct prog_instruction * inst = &s->IP->I;
int i;
GLuint deswz_source = 0;
@@ -94,18 +98,16 @@ static struct prog_instruction* track_used_srcreg(struct nqssadce_state* s,
if (!s->Descr->IsNativeSwizzle(inst->Opcode, inst->SrcReg[src])) {
struct prog_dst_register dstreg = inst->DstReg;
dstreg.File = PROGRAM_TEMPORARY;
- dstreg.Index = _mesa_find_free_register(s->Program, PROGRAM_TEMPORARY);
+ dstreg.Index = rc_find_free_temporary(s->Compiler);
dstreg.WriteMask = sourced;
s->Descr->BuildSwizzle(s, dstreg, inst->SrcReg[src]);
- inst = s->Program->Instructions + s->IP;
inst->SrcReg[src].File = PROGRAM_TEMPORARY;
inst->SrcReg[src].Index = dstreg.Index;
inst->SrcReg[src].Swizzle = 0;
- inst->SrcReg[src].NegateBase = 0;
+ inst->SrcReg[src].Negate = NEGATE_NONE;
inst->SrcReg[src].Abs = 0;
- inst->SrcReg[src].NegateAbs = 0;
for(i = 0; i < 4; ++i) {
if (GET_BIT(sourced, i))
inst->SrcReg[src].Swizzle |= i << (3*i);
@@ -115,67 +117,38 @@ static struct prog_instruction* track_used_srcreg(struct nqssadce_state* s,
deswz_source = sourced;
}
- struct register_state *regstate = get_reg_state(s, inst->SrcReg[src].File, inst->SrcReg[src].Index);
- if (regstate)
- regstate->Sourced |= deswz_source & 0xf;
-
- return inst;
-}
+ struct register_state *regstate;
-
-static void rewrite_depth_out(struct prog_instruction *inst)
-{
- if (inst->DstReg.WriteMask & WRITEMASK_Z) {
- inst->DstReg.WriteMask = WRITEMASK_W;
+ if (inst->SrcReg[src].RelAddr) {
+ regstate = get_reg_state(s, PROGRAM_ADDRESS, 0);
+ if (regstate)
+ regstate->Sourced |= WRITEMASK_X;
} else {
- inst->DstReg.WriteMask = 0;
- return;
- }
-
- switch (inst->Opcode) {
- case OPCODE_FRC:
- case OPCODE_MOV:
- inst->SrcReg[0] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[0]);
- break;
- case OPCODE_ADD:
- case OPCODE_MAX:
- case OPCODE_MIN:
- case OPCODE_MUL:
- inst->SrcReg[0] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[0]);
- inst->SrcReg[1] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[1]);
- break;
- case OPCODE_CMP:
- case OPCODE_MAD:
- inst->SrcReg[0] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[0]);
- inst->SrcReg[1] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[1]);
- inst->SrcReg[2] = lmul_swizzle(SWIZZLE_ZZZZ, inst->SrcReg[2]);
- break;
- default:
- // Scalar instructions needn't be reswizzled
- break;
+ regstate = get_reg_state(s, inst->SrcReg[src].File, inst->SrcReg[src].Index);
+ if (regstate)
+ regstate->Sourced |= deswz_source & 0xf;
}
}
-static void unalias_srcregs(struct prog_instruction *inst, GLuint oldindex, GLuint newindex)
+static void unalias_srcregs(struct rc_instruction *inst, GLuint oldindex, GLuint newindex)
{
- int nsrc = _mesa_num_inst_src_regs(inst->Opcode);
+ int nsrc = _mesa_num_inst_src_regs(inst->I.Opcode);
int i;
for(i = 0; i < nsrc; ++i)
- if (inst->SrcReg[i].File == PROGRAM_TEMPORARY && inst->SrcReg[i].Index == oldindex)
- inst->SrcReg[i].Index = newindex;
+ if (inst->I.SrcReg[i].File == PROGRAM_TEMPORARY && inst->I.SrcReg[i].Index == oldindex)
+ inst->I.SrcReg[i].Index = newindex;
}
static void unalias_temporary(struct nqssadce_state* s, GLuint oldindex)
{
- GLuint newindex = _mesa_find_free_register(s->Program, PROGRAM_TEMPORARY);
- int ip;
- for(ip = 0; ip < s->IP; ++ip) {
- struct prog_instruction* inst = s->Program->Instructions + ip;
- if (inst->DstReg.File == PROGRAM_TEMPORARY && inst->DstReg.Index == oldindex)
- inst->DstReg.Index = newindex;
+ GLuint newindex = rc_find_free_temporary(s->Compiler);
+ struct rc_instruction * inst;
+ for(inst = s->Compiler->Program.Instructions.Next; inst != s->IP; inst = inst->Next) {
+ if (inst->I.DstReg.File == PROGRAM_TEMPORARY && inst->I.DstReg.Index == oldindex)
+ inst->I.DstReg.Index = newindex;
unalias_srcregs(inst, oldindex, newindex);
}
- unalias_srcregs(s->Program->Instructions + s->IP, oldindex, newindex);
+ unalias_srcregs(s->IP, oldindex, newindex);
}
@@ -184,20 +157,16 @@ static void unalias_temporary(struct nqssadce_state* s, GLuint oldindex)
*/
static void process_instruction(struct nqssadce_state* s)
{
- struct prog_instruction *inst = s->Program->Instructions + s->IP;
+ struct prog_instruction *inst = &s->IP->I;
+ GLuint WriteMask;
if (inst->Opcode == OPCODE_END)
return;
if (inst->Opcode != OPCODE_KIL) {
- if (s->Descr->RewriteDepthOut) {
- if (inst->DstReg.File == PROGRAM_OUTPUT && inst->DstReg.Index == FRAG_RESULT_DEPR)
- rewrite_depth_out(inst);
- }
-
struct register_state *regstate = get_reg_state(s, inst->DstReg.File, inst->DstReg.Index);
if (!regstate) {
- _mesa_problem(s->Ctx, "NqssaDce: bad destination register (%i[%i])\n",
+ rc_error(s->Compiler, "NqssaDce: bad destination register (%i[%i])\n",
inst->DstReg.File, inst->DstReg.Index);
return;
}
@@ -206,7 +175,9 @@ static void process_instruction(struct nqssadce_state* s)
regstate->Sourced &= ~inst->DstReg.WriteMask;
if (inst->DstReg.WriteMask == 0) {
- _mesa_delete_instructions(s->Program, s->IP, 1);
+ struct rc_instruction * inst_remove = s->IP;
+ s->IP = s->IP->Prev;
+ rc_remove_instruction(inst_remove);
return;
}
@@ -214,28 +185,30 @@ static void process_instruction(struct nqssadce_state* s)
unalias_temporary(s, inst->DstReg.Index);
}
- /* Attention: Due to swizzle emulation code, the following
- * might change the instruction stream under us, so we have
- * to be careful with the inst pointer. */
+ WriteMask = inst->DstReg.WriteMask;
+
switch (inst->Opcode) {
+ case OPCODE_ARL:
case OPCODE_DDX:
case OPCODE_DDY:
case OPCODE_FRC:
case OPCODE_MOV:
- inst = track_used_srcreg(s, inst, 0, inst->DstReg.WriteMask);
+ track_used_srcreg(s, 0, WriteMask);
break;
case OPCODE_ADD:
case OPCODE_MAX:
case OPCODE_MIN:
case OPCODE_MUL:
- inst = track_used_srcreg(s, inst, 0, inst->DstReg.WriteMask);
- inst = track_used_srcreg(s, inst, 1, inst->DstReg.WriteMask);
+ case OPCODE_SGE:
+ case OPCODE_SLT:
+ track_used_srcreg(s, 0, WriteMask);
+ track_used_srcreg(s, 1, WriteMask);
break;
case OPCODE_CMP:
case OPCODE_MAD:
- inst = track_used_srcreg(s, inst, 0, inst->DstReg.WriteMask);
- inst = track_used_srcreg(s, inst, 1, inst->DstReg.WriteMask);
- inst = track_used_srcreg(s, inst, 2, inst->DstReg.WriteMask);
+ track_used_srcreg(s, 0, WriteMask);
+ track_used_srcreg(s, 1, WriteMask);
+ track_used_srcreg(s, 2, WriteMask);
break;
case OPCODE_COS:
case OPCODE_EX2:
@@ -243,42 +216,79 @@ static void process_instruction(struct nqssadce_state* s)
case OPCODE_RCP:
case OPCODE_RSQ:
case OPCODE_SIN:
- inst = track_used_srcreg(s, inst, 0, 0x1);
+ track_used_srcreg(s, 0, 0x1);
break;
case OPCODE_DP3:
- inst = track_used_srcreg(s, inst, 0, 0x7);
- inst = track_used_srcreg(s, inst, 1, 0x7);
+ track_used_srcreg(s, 0, 0x7);
+ track_used_srcreg(s, 1, 0x7);
break;
case OPCODE_DP4:
- inst = track_used_srcreg(s, inst, 0, 0xf);
- inst = track_used_srcreg(s, inst, 1, 0xf);
+ track_used_srcreg(s, 0, 0xf);
+ track_used_srcreg(s, 1, 0xf);
break;
case OPCODE_KIL:
case OPCODE_TEX:
case OPCODE_TXB:
case OPCODE_TXP:
- inst = track_used_srcreg(s, inst, 0, 0xf);
+ track_used_srcreg(s, 0, 0xf);
+ break;
+ case OPCODE_DST:
+ track_used_srcreg(s, 0, 0x6);
+ track_used_srcreg(s, 1, 0xa);
+ break;
+ case OPCODE_EXP:
+ case OPCODE_LOG:
+ case OPCODE_POW:
+ track_used_srcreg(s, 0, 0x3);
+ break;
+ case OPCODE_LIT:
+ track_used_srcreg(s, 0, 0xb);
break;
default:
- _mesa_problem(s->Ctx, "NqssaDce: Unknown opcode %d\n", inst->Opcode);
+ rc_error(s->Compiler, "NqssaDce: Unknown opcode %d\n", inst->Opcode);
return;
}
+
+ s->IP = s->IP->Prev;
}
+void rc_calculate_inputs_outputs(struct radeon_compiler * c)
+{
+ struct rc_instruction *inst;
+
+ c->Program.InputsRead = 0;
+ c->Program.OutputsWritten = 0;
+
+ for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next)
+ {
+ int i;
+ int num_src_regs = _mesa_num_inst_src_regs(inst->I.Opcode);
+
+ for (i = 0; i < num_src_regs; ++i) {
+ if (inst->I.SrcReg[i].File == PROGRAM_INPUT)
+ c->Program.InputsRead |= 1 << inst->I.SrcReg[i].Index;
+ }
+
+ if (_mesa_num_inst_dst_regs(inst->I.Opcode)) {
+ if (inst->I.DstReg.File == PROGRAM_OUTPUT)
+ c->Program.OutputsWritten |= 1 << inst->I.DstReg.Index;
+ }
+ }
+}
-void radeonNqssaDce(GLcontext *ctx, struct gl_program *p, struct radeon_nqssadce_descr* descr)
+void radeonNqssaDce(struct radeon_compiler * c, struct radeon_nqssadce_descr* descr, void * data)
{
struct nqssadce_state s;
_mesa_bzero(&s, sizeof(s));
- s.Ctx = ctx;
- s.Program = p;
+ s.Compiler = c;
s.Descr = descr;
+ s.UserData = data;
s.Descr->Init(&s);
- s.IP = p->NumInstructions;
+ s.IP = c->Program.Instructions.Prev;
- while(s.IP > 0) {
- s.IP--;
+ while(s.IP != &c->Program.Instructions && !c->Error)
process_instruction(&s);
- }
+
+ rc_calculate_inputs_outputs(c);
}
diff --git a/src/mesa/drivers/dri/r300/radeon_nqssadce.h b/src/mesa/drivers/dri/r300/compiler/radeon_nqssadce.h
index a4f94abcb6..b3fc77a35a 100644
--- a/src/mesa/drivers/dri/r300/radeon_nqssadce.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_nqssadce.h
@@ -30,7 +30,6 @@
#include "radeon_program.h"
-
struct register_state {
/**
* Bitmask indicating which components of the register are sourced
@@ -44,20 +43,22 @@ struct register_state {
* read from, etc.
*/
struct nqssadce_state {
- GLcontext *Ctx;
- struct gl_program *Program;
+ struct radeon_compiler *Compiler;
struct radeon_nqssadce_descr *Descr;
/**
* All instructions after this instruction pointer have been dealt with.
*/
- int IP;
+ struct rc_instruction * IP;
/**
* Which registers are read by subsequent instructions?
*/
struct register_state Temps[MAX_PROGRAM_TEMPS];
struct register_state Outputs[VERT_RESULT_MAX];
+ struct register_state Address;
+
+ void * UserData;
};
@@ -82,15 +83,9 @@ struct radeon_nqssadce_descr {
* The transformation will work recursively on the emitted instruction(s).
*/
void (*BuildSwizzle)(struct nqssadce_state*, struct prog_dst_register dst, struct prog_src_register src);
-
- /**
- * Rewrite instructions that write to DEPR.z to write to DEPR.w
- * instead (rewriting is done *before* the WriteMask test).
- */
- GLboolean RewriteDepthOut;
- void *Data;
};
-void radeonNqssaDce(GLcontext *ctx, struct gl_program *p, struct radeon_nqssadce_descr* descr);
+void radeonNqssaDce(struct radeon_compiler * c, struct radeon_nqssadce_descr* descr, void * data);
+struct prog_src_register lmul_swizzle(GLuint swizzle, struct prog_src_register srcreg);
#endif /* __RADEON_PROGRAM_NQSSADCE_H_ */
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.c b/src/mesa/drivers/dri/r300/compiler/radeon_program.c
new file mode 100644
index 0000000000..bbbf0dd776
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "radeon_program.h"
+
+#include "radeon_compiler.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+
+/**
+ * Transform the given clause in the following way:
+ * 1. Replace it with an empty clause
+ * 2. For every instruction in the original clause, try the given
+ * transformations in order.
+ * 3. If one of the transformations returns GL_TRUE, assume that it
+ * has emitted the appropriate instruction(s) into the new clause;
+ * otherwise, copy the instruction verbatim.
+ *
+ * \note The transformation is currently not recursive; in other words,
+ * instructions emitted by transformations are not transformed.
+ *
+ * \note The transform is called 'local' because it can only look at
+ * one instruction at a time.
+ */
+void radeonLocalTransform(
+ struct radeon_compiler * c,
+ int num_transformations,
+ struct radeon_program_transformation* transformations)
+{
+ struct rc_instruction * inst = c->Program.Instructions.Next;
+
+ while(inst != &c->Program.Instructions) {
+ struct rc_instruction * current = inst;
+ int i;
+
+ inst = inst->Next;
+
+ for(i = 0; i < num_transformations; ++i) {
+ struct radeon_program_transformation* t = transformations + i;
+
+ if (t->function(c, current, t->userData))
+ break;
+ }
+ }
+}
+
+
+GLint rc_find_free_temporary(struct radeon_compiler * c)
+{
+ GLboolean used[MAX_PROGRAM_TEMPS];
+ GLuint i;
+
+ memset(used, 0, sizeof(used));
+
+ for (struct rc_instruction * rcinst = c->Program.Instructions.Next; rcinst != &c->Program.Instructions; rcinst = rcinst->Next) {
+ const struct prog_instruction *inst = &rcinst->I;
+ const GLuint nsrc = _mesa_num_inst_src_regs(inst->Opcode);
+ const GLuint ndst = _mesa_num_inst_dst_regs(inst->Opcode);
+ GLuint k;
+
+ for (k = 0; k < nsrc; k++) {
+ if (inst->SrcReg[k].File == PROGRAM_TEMPORARY)
+ used[inst->SrcReg[k].Index] = GL_TRUE;
+ }
+
+ if (ndst) {
+ if (inst->DstReg.File == PROGRAM_TEMPORARY)
+ used[inst->DstReg.Index] = GL_TRUE;
+ }
+ }
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (!used[i])
+ return i;
+ }
+
+ return -1;
+}
+
+
+struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c)
+{
+ struct rc_instruction * inst = memory_pool_malloc(&c->Pool, sizeof(struct rc_instruction));
+
+ inst->Prev = 0;
+ inst->Next = 0;
+
+ _mesa_init_instructions(&inst->I, 1);
+
+ return inst;
+}
+
+
+struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after)
+{
+ struct rc_instruction * inst = rc_alloc_instruction(c);
+
+ inst->Prev = after;
+ inst->Next = after->Next;
+
+ inst->Prev->Next = inst;
+ inst->Next->Prev = inst;
+
+ return inst;
+}
+
+void rc_remove_instruction(struct rc_instruction * inst)
+{
+ inst->Prev->Next = inst->Next;
+ inst->Next->Prev = inst->Prev;
+}
+
+
+void rc_mesa_to_rc_program(struct radeon_compiler * c, struct gl_program * program)
+{
+ struct prog_instruction *source;
+ unsigned int i;
+
+ for(source = program->Instructions; source->Opcode != OPCODE_END; ++source) {
+ struct rc_instruction * dest = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
+ dest->I = *source;
+ }
+
+ c->Program.ShadowSamplers = program->ShadowSamplers;
+ c->Program.InputsRead = program->InputsRead;
+ c->Program.OutputsWritten = program->OutputsWritten;
+
+ for(i = 0; i < program->Parameters->NumParameters; ++i) {
+ struct rc_constant constant;
+
+ constant.Type = RC_CONSTANT_EXTERNAL;
+ constant.Size = 4;
+ constant.u.External = i;
+
+ rc_constants_add(&c->Program.Constants, &constant);
+ }
+}
+
+
+/**
+ * Print program to stderr, default options.
+ */
+void rc_print_program(const struct rc_program *prog)
+{
+ GLuint indent = 0;
+ GLuint linenum = 1;
+ struct rc_instruction *inst;
+
+ fprintf(stderr, "# Radeon Compiler Program\n");
+
+ for(inst = prog->Instructions.Next; inst != &prog->Instructions; inst = inst->Next) {
+ fprintf(stderr, "%3d: ", linenum);
+
+ /* Massive hack: We rely on the fact that the printers do not actually
+ * use the gl_program argument (last argument) in debug mode */
+ indent = _mesa_fprint_instruction_opt(
+ stderr, &inst->I,
+ indent, PROG_PRINT_DEBUG, 0);
+
+ linenum++;
+ }
+}
diff --git a/src/mesa/drivers/dri/r300/radeon_program.h b/src/mesa/drivers/dri/r300/compiler/radeon_program.h
index b411f69bc8..561958608c 100644
--- a/src/mesa/drivers/dri/r300/radeon_program.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.h
@@ -34,12 +34,9 @@
#include "shader/program.h"
#include "shader/prog_instruction.h"
-
-enum {
- CLAUSE_MIXED = 0,
- CLAUSE_ALU,
- CLAUSE_TEX
-};
+struct radeon_compiler;
+struct rc_instruction;
+struct rc_program;
enum {
PROGRAM_BUILTIN = PROGRAM_FILE_MAX /**< not a real register, but a special swizzle constant */
@@ -52,18 +49,43 @@ enum {
#define SWIZZLE_0000 MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO)
#define SWIZZLE_1111 MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE)
-/**
- * Transformation context that is passed to local transformations.
- *
- * Care must be taken with some operations during transformation,
- * e.g. finding new temporary registers must use @ref radeonFindFreeTemporary
- */
-struct radeon_transform_context {
- GLcontext *Ctx;
- struct gl_program *Program;
- struct prog_instruction *OldInstructions;
- GLuint OldNumInstructions;
-};
+static inline GLuint get_swz(GLuint swz, GLuint idx)
+{
+ if (idx & 0x4)
+ return idx;
+ return GET_SWZ(swz, idx);
+}
+
+static inline GLuint combine_swizzles4(GLuint src, GLuint swz_x, GLuint swz_y, GLuint swz_z, GLuint swz_w)
+{
+ GLuint ret = 0;
+
+ ret |= get_swz(src, swz_x);
+ ret |= get_swz(src, swz_y) << 3;
+ ret |= get_swz(src, swz_z) << 6;
+ ret |= get_swz(src, swz_w) << 9;
+
+ return ret;
+}
+
+static inline GLuint combine_swizzles(GLuint src, GLuint swz)
+{
+ GLuint ret = 0;
+
+ ret |= get_swz(src, GET_SWZ(swz, SWIZZLE_X));
+ ret |= get_swz(src, GET_SWZ(swz, SWIZZLE_Y)) << 3;
+ ret |= get_swz(src, GET_SWZ(swz, SWIZZLE_Z)) << 6;
+ ret |= get_swz(src, GET_SWZ(swz, SWIZZLE_W)) << 9;
+
+ return ret;
+}
+
+static INLINE void reset_srcreg(struct prog_src_register* reg)
+{
+ _mesa_bzero(reg, sizeof(*reg));
+ reg->Swizzle = SWIZZLE_NOOP;
+}
+
/**
* A transformation that can be passed to \ref radeonLocalTransform.
@@ -77,23 +99,23 @@ struct radeon_transform_context {
*/
struct radeon_program_transformation {
GLboolean (*function)(
- struct radeon_transform_context*,
- struct prog_instruction*,
+ struct radeon_compiler*,
+ struct rc_instruction*,
void*);
void *userData;
};
void radeonLocalTransform(
- GLcontext* ctx,
- struct gl_program *program,
+ struct radeon_compiler *c,
int num_transformations,
struct radeon_program_transformation* transformations);
-/**
- * Find a usable free temporary register during program transformation
- */
-GLint radeonFindFreeTemporary(struct radeon_transform_context *ctx);
+GLint rc_find_free_temporary(struct radeon_compiler * c);
+
+struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c);
+struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after);
+void rc_remove_instruction(struct rc_instruction * inst);
-struct prog_instruction *radeonAppendInstructions(struct gl_program *program, int count);
+void rc_print_program(const struct rc_program *prog);
#endif
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
new file mode 100644
index 0000000000..8071899eaa
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
@@ -0,0 +1,695 @@
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/**
+ * @file
+ *
+ * Shareable transformations that transform "special" ALU instructions
+ * into ALU instructions that are supported by hardware.
+ *
+ */
+
+#include "radeon_program_alu.h"
+
+#include "radeon_compiler.h"
+
+
+static struct rc_instruction *emit1(
+ struct radeon_compiler * c, struct rc_instruction * after,
+ gl_inst_opcode Opcode, GLuint Saturate, struct prog_dst_register DstReg,
+ struct prog_src_register SrcReg)
+{
+ struct rc_instruction *fpi = rc_insert_new_instruction(c, after);
+
+ fpi->I.Opcode = Opcode;
+ fpi->I.SaturateMode = Saturate;
+ fpi->I.DstReg = DstReg;
+ fpi->I.SrcReg[0] = SrcReg;
+ return fpi;
+}
+
+static struct rc_instruction *emit2(
+ struct radeon_compiler * c, struct rc_instruction * after,
+ gl_inst_opcode Opcode, GLuint Saturate, struct prog_dst_register DstReg,
+ struct prog_src_register SrcReg0, struct prog_src_register SrcReg1)
+{
+ struct rc_instruction *fpi = rc_insert_new_instruction(c, after);
+
+ fpi->I.Opcode = Opcode;
+ fpi->I.SaturateMode = Saturate;
+ fpi->I.DstReg = DstReg;
+ fpi->I.SrcReg[0] = SrcReg0;
+ fpi->I.SrcReg[1] = SrcReg1;
+ return fpi;
+}
+
+static struct rc_instruction *emit3(
+ struct radeon_compiler * c, struct rc_instruction * after,
+ gl_inst_opcode Opcode, GLuint Saturate, struct prog_dst_register DstReg,
+ struct prog_src_register SrcReg0, struct prog_src_register SrcReg1,
+ struct prog_src_register SrcReg2)
+{
+ struct rc_instruction *fpi = rc_insert_new_instruction(c, after);
+
+ fpi->I.Opcode = Opcode;
+ fpi->I.SaturateMode = Saturate;
+ fpi->I.DstReg = DstReg;
+ fpi->I.SrcReg[0] = SrcReg0;
+ fpi->I.SrcReg[1] = SrcReg1;
+ fpi->I.SrcReg[2] = SrcReg2;
+ return fpi;
+}
+
+static struct prog_dst_register dstreg(int file, int index)
+{
+ struct prog_dst_register dst;
+ dst.File = file;
+ dst.Index = index;
+ dst.WriteMask = WRITEMASK_XYZW;
+ dst.CondMask = COND_TR;
+ dst.RelAddr = 0;
+ dst.CondSwizzle = SWIZZLE_NOOP;
+ dst.CondSrc = 0;
+ dst.pad = 0;
+ return dst;
+}
+
+static struct prog_dst_register dstregtmpmask(int index, int mask)
+{
+ struct prog_dst_register dst = {0};
+ dst.File = PROGRAM_TEMPORARY;
+ dst.Index = index;
+ dst.WriteMask = mask;
+ dst.RelAddr = 0;
+ dst.CondMask = COND_TR;
+ dst.CondSwizzle = SWIZZLE_NOOP;
+ dst.CondSrc = 0;
+ dst.pad = 0;
+ return dst;
+}
+
+static const struct prog_src_register builtin_zero = {
+ .File = PROGRAM_BUILTIN,
+ .Index = 0,
+ .Swizzle = SWIZZLE_0000
+};
+static const struct prog_src_register builtin_one = {
+ .File = PROGRAM_BUILTIN,
+ .Index = 0,
+ .Swizzle = SWIZZLE_1111
+};
+static const struct prog_src_register srcreg_undefined = {
+ .File = PROGRAM_UNDEFINED,
+ .Index = 0,
+ .Swizzle = SWIZZLE_NOOP
+};
+
+static struct prog_src_register srcreg(int file, int index)
+{
+ struct prog_src_register src = srcreg_undefined;
+ src.File = file;
+ src.Index = index;
+ return src;
+}
+
+static struct prog_src_register srcregswz(int file, int index, int swz)
+{
+ struct prog_src_register src = srcreg_undefined;
+ src.File = file;
+ src.Index = index;
+ src.Swizzle = swz;
+ return src;
+}
+
+static struct prog_src_register absolute(struct prog_src_register reg)
+{
+ struct prog_src_register newreg = reg;
+ newreg.Abs = 1;
+ newreg.Negate = NEGATE_NONE;
+ return newreg;
+}
+
+static struct prog_src_register negate(struct prog_src_register reg)
+{
+ struct prog_src_register newreg = reg;
+ newreg.Negate = newreg.Negate ^ NEGATE_XYZW;
+ return newreg;
+}
+
+static struct prog_src_register swizzle(struct prog_src_register reg, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+ struct prog_src_register swizzled = reg;
+ swizzled.Swizzle = MAKE_SWIZZLE4(
+ x >= 4 ? x : GET_SWZ(reg.Swizzle, x),
+ y >= 4 ? y : GET_SWZ(reg.Swizzle, y),
+ z >= 4 ? z : GET_SWZ(reg.Swizzle, z),
+ w >= 4 ? w : GET_SWZ(reg.Swizzle, w));
+ return swizzled;
+}
+
+static struct prog_src_register scalar(struct prog_src_register reg)
+{
+ return swizzle(reg, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
+}
+
+static void transform_ABS(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ struct prog_src_register src = inst->I.SrcReg[0];
+ src.Abs = 1;
+ src.Negate = NEGATE_NONE;
+ emit1(c, inst->Prev, OPCODE_MOV, inst->I.SaturateMode, inst->I.DstReg, src);
+ rc_remove_instruction(inst);
+}
+
+static void transform_DP3(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ struct prog_src_register src0 = inst->I.SrcReg[0];
+ struct prog_src_register src1 = inst->I.SrcReg[1];
+ src0.Negate &= ~NEGATE_W;
+ src0.Swizzle &= ~(7 << (3 * 3));
+ src0.Swizzle |= SWIZZLE_ZERO << (3 * 3);
+ src1.Negate &= ~NEGATE_W;
+ src1.Swizzle &= ~(7 << (3 * 3));
+ src1.Swizzle |= SWIZZLE_ZERO << (3 * 3);
+ emit2(c, inst->Prev, OPCODE_DP4, inst->I.SaturateMode, inst->I.DstReg, src0, src1);
+ rc_remove_instruction(inst);
+}
+
+static void transform_DPH(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ struct prog_src_register src0 = inst->I.SrcReg[0];
+ src0.Negate &= ~NEGATE_W;
+ src0.Swizzle &= ~(7 << (3 * 3));
+ src0.Swizzle |= SWIZZLE_ONE << (3 * 3);
+ emit2(c, inst->Prev, OPCODE_DP4, inst->I.SaturateMode, inst->I.DstReg, src0, inst->I.SrcReg[1]);
+ rc_remove_instruction(inst);
+}
+
+/**
+ * [1, src0.y*src1.y, src0.z, src1.w]
+ * So basically MUL with lotsa swizzling.
+ */
+static void transform_DST(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ emit2(c, inst->Prev, OPCODE_MUL, inst->I.SaturateMode, inst->I.DstReg,
+ swizzle(inst->I.SrcReg[0], SWIZZLE_ONE, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE),
+ swizzle(inst->I.SrcReg[1], SWIZZLE_ONE, SWIZZLE_Y, SWIZZLE_ONE, SWIZZLE_W));
+ rc_remove_instruction(inst);
+}
+
+static void transform_FLR(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ int tempreg = rc_find_free_temporary(c);
+ emit1(c, inst->Prev, OPCODE_FRC, 0, dstreg(PROGRAM_TEMPORARY, tempreg), inst->I.SrcReg[0]);
+ emit2(c, inst->Prev, OPCODE_ADD, inst->I.SaturateMode, inst->I.DstReg,
+ inst->I.SrcReg[0], negate(srcreg(PROGRAM_TEMPORARY, tempreg)));
+ rc_remove_instruction(inst);
+}
+
+/**
+ * Definition of LIT (from ARB_fragment_program):
+ *
+ * tmp = VectorLoad(op0);
+ * if (tmp.x < 0) tmp.x = 0;
+ * if (tmp.y < 0) tmp.y = 0;
+ * if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
+ * else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
+ * result.x = 1.0;
+ * result.y = tmp.x;
+ * result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
+ * result.w = 1.0;
+ *
+ * The longest path of computation is the one leading to result.z,
+ * consisting of 5 operations. This implementation of LIT takes
+ * 5 slots, if the subsequent optimization passes are clever enough
+ * to pair instructions correctly.
+ */
+static void transform_LIT(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ GLuint constant;
+ GLuint constant_swizzle;
+ GLuint temp;
+ struct prog_src_register srctemp;
+
+ constant = rc_constants_add_immediate_scalar(&c->Program.Constants, -127.999999, &constant_swizzle);
+
+ if (inst->I.DstReg.WriteMask != WRITEMASK_XYZW || inst->I.DstReg.File != PROGRAM_TEMPORARY) {
+ struct rc_instruction * inst_mov;
+
+ inst_mov = emit1(c, inst,
+ OPCODE_MOV, 0, inst->I.DstReg,
+ srcreg(PROGRAM_TEMPORARY, rc_find_free_temporary(c)));
+
+ inst->I.DstReg.File = PROGRAM_TEMPORARY;
+ inst->I.DstReg.Index = inst_mov->I.SrcReg[0].Index;
+ inst->I.DstReg.WriteMask = WRITEMASK_XYZW;
+ }
+
+ temp = inst->I.DstReg.Index;
+ srctemp = srcreg(PROGRAM_TEMPORARY, temp);
+
+ // tmp.x = max(0.0, Src.x);
+ // tmp.y = max(0.0, Src.y);
+ // tmp.w = clamp(Src.z, -128+eps, 128-eps);
+ emit2(c, inst->Prev, OPCODE_MAX, 0,
+ dstregtmpmask(temp, WRITEMASK_XYW),
+ inst->I.SrcReg[0],
+ swizzle(srcreg(PROGRAM_CONSTANT, constant),
+ SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO, constant_swizzle&3));
+ emit2(c, inst->Prev, OPCODE_MIN, 0,
+ dstregtmpmask(temp, WRITEMASK_Z),
+ swizzle(srctemp, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ negate(srcregswz(PROGRAM_CONSTANT, constant, constant_swizzle)));
+
+ // tmp.w = Pow(tmp.y, tmp.w)
+ emit1(c, inst->Prev, OPCODE_LG2, 0,
+ dstregtmpmask(temp, WRITEMASK_W),
+ swizzle(srctemp, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y));
+ emit2(c, inst->Prev, OPCODE_MUL, 0,
+ dstregtmpmask(temp, WRITEMASK_W),
+ swizzle(srctemp, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ swizzle(srctemp, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z));
+ emit1(c, inst->Prev, OPCODE_EX2, 0,
+ dstregtmpmask(temp, WRITEMASK_W),
+ swizzle(srctemp, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W));
+
+ // tmp.z = (tmp.x > 0) ? tmp.w : 0.0
+ emit3(c, inst->Prev, OPCODE_CMP, inst->I.SaturateMode,
+ dstregtmpmask(temp, WRITEMASK_Z),
+ negate(swizzle(srctemp, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)),
+ swizzle(srctemp, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ builtin_zero);
+
+ // tmp.x, tmp.y, tmp.w = 1.0, tmp.x, 1.0
+ emit1(c, inst->Prev, OPCODE_MOV, inst->I.SaturateMode,
+ dstregtmpmask(temp, WRITEMASK_XYW),
+ swizzle(srctemp, SWIZZLE_ONE, SWIZZLE_X, SWIZZLE_ONE, SWIZZLE_ONE));
+
+ rc_remove_instruction(inst);
+}
+
+static void transform_LRP(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ int tempreg = rc_find_free_temporary(c);
+
+ emit2(c, inst->Prev, OPCODE_ADD, 0,
+ dstreg(PROGRAM_TEMPORARY, tempreg),
+ inst->I.SrcReg[1], negate(inst->I.SrcReg[2]));
+ emit3(c, inst->Prev, OPCODE_MAD, inst->I.SaturateMode,
+ inst->I.DstReg,
+ inst->I.SrcReg[0], srcreg(PROGRAM_TEMPORARY, tempreg), inst->I.SrcReg[2]);
+
+ rc_remove_instruction(inst);
+}
+
+static void transform_POW(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ int tempreg = rc_find_free_temporary(c);
+ struct prog_dst_register tempdst = dstreg(PROGRAM_TEMPORARY, tempreg);
+ struct prog_src_register tempsrc = srcreg(PROGRAM_TEMPORARY, tempreg);
+ tempdst.WriteMask = WRITEMASK_W;
+ tempsrc.Swizzle = SWIZZLE_WWWW;
+
+ emit1(c, inst->Prev, OPCODE_LG2, 0, tempdst, scalar(inst->I.SrcReg[0]));
+ emit2(c, inst->Prev, OPCODE_MUL, 0, tempdst, tempsrc, scalar(inst->I.SrcReg[1]));
+ emit1(c, inst->Prev, OPCODE_EX2, inst->I.SaturateMode, inst->I.DstReg, tempsrc);
+
+ rc_remove_instruction(inst);
+}
+
+static void transform_RSQ(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ inst->I.SrcReg[0] = absolute(inst->I.SrcReg[0]);
+}
+
+static void transform_SGE(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ int tempreg = rc_find_free_temporary(c);
+
+ emit2(c, inst->Prev, OPCODE_ADD, 0, dstreg(PROGRAM_TEMPORARY, tempreg), inst->I.SrcReg[0], negate(inst->I.SrcReg[1]));
+ emit3(c, inst->Prev, OPCODE_CMP, inst->I.SaturateMode, inst->I.DstReg,
+ srcreg(PROGRAM_TEMPORARY, tempreg), builtin_zero, builtin_one);
+
+ rc_remove_instruction(inst);
+}
+
+static void transform_SLT(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ int tempreg = rc_find_free_temporary(c);
+
+ emit2(c, inst->Prev, OPCODE_ADD, 0, dstreg(PROGRAM_TEMPORARY, tempreg), inst->I.SrcReg[0], negate(inst->I.SrcReg[1]));
+ emit3(c, inst->Prev, OPCODE_CMP, inst->I.SaturateMode, inst->I.DstReg,
+ srcreg(PROGRAM_TEMPORARY, tempreg), builtin_one, builtin_zero);
+
+ rc_remove_instruction(inst);
+}
+
+static void transform_SUB(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ inst->I.Opcode = OPCODE_ADD;
+ inst->I.SrcReg[1] = negate(inst->I.SrcReg[1]);
+}
+
+static void transform_SWZ(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ inst->I.Opcode = OPCODE_MOV;
+}
+
+static void transform_XPD(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ int tempreg = rc_find_free_temporary(c);
+
+ emit2(c, inst->Prev, OPCODE_MUL, 0, dstreg(PROGRAM_TEMPORARY, tempreg),
+ swizzle(inst->I.SrcReg[0], SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, SWIZZLE_W),
+ swizzle(inst->I.SrcReg[1], SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, SWIZZLE_W));
+ emit3(c, inst->Prev, OPCODE_MAD, inst->I.SaturateMode, inst->I.DstReg,
+ swizzle(inst->I.SrcReg[0], SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, SWIZZLE_W),
+ swizzle(inst->I.SrcReg[1], SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, SWIZZLE_W),
+ negate(srcreg(PROGRAM_TEMPORARY, tempreg)));
+
+ rc_remove_instruction(inst);
+}
+
+
+/**
+ * Can be used as a transformation for @ref radeonClauseLocalTransform,
+ * no userData necessary.
+ *
+ * Eliminates the following ALU instructions:
+ * ABS, DPH, DST, FLR, LIT, LRP, POW, SGE, SLT, SUB, SWZ, XPD
+ * using:
+ * MOV, ADD, MUL, MAD, FRC, DP3, LG2, EX2, CMP
+ *
+ * Transforms RSQ to Radeon's native RSQ by explicitly setting
+ * absolute value.
+ *
+ * @note should be applicable to R300 and R500 fragment programs.
+ */
+GLboolean radeonTransformALU(
+ struct radeon_compiler * c,
+ struct rc_instruction* inst,
+ void* unused)
+{
+ switch(inst->I.Opcode) {
+ case OPCODE_ABS: transform_ABS(c, inst); return GL_TRUE;
+ case OPCODE_DPH: transform_DPH(c, inst); return GL_TRUE;
+ case OPCODE_DST: transform_DST(c, inst); return GL_TRUE;
+ case OPCODE_FLR: transform_FLR(c, inst); return GL_TRUE;
+ case OPCODE_LIT: transform_LIT(c, inst); return GL_TRUE;
+ case OPCODE_LRP: transform_LRP(c, inst); return GL_TRUE;
+ case OPCODE_POW: transform_POW(c, inst); return GL_TRUE;
+ case OPCODE_RSQ: transform_RSQ(c, inst); return GL_TRUE;
+ case OPCODE_SGE: transform_SGE(c, inst); return GL_TRUE;
+ case OPCODE_SLT: transform_SLT(c, inst); return GL_TRUE;
+ case OPCODE_SUB: transform_SUB(c, inst); return GL_TRUE;
+ case OPCODE_SWZ: transform_SWZ(c, inst); return GL_TRUE;
+ case OPCODE_XPD: transform_XPD(c, inst); return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+static void transform_r300_vertex_ABS(struct radeon_compiler* c,
+ struct rc_instruction* inst)
+{
+ /* Note: r500 can take absolute values, but r300 cannot. */
+ inst->I.Opcode = OPCODE_MAX;
+ inst->I.SrcReg[1] = inst->I.SrcReg[0];
+ inst->I.SrcReg[1].Negate ^= NEGATE_XYZW;
+}
+
+/**
+ * For use with radeonLocalTransform, this transforms non-native ALU
+ * instructions of the r300 up to r500 vertex engine.
+ */
+GLboolean r300_transform_vertex_alu(
+ struct radeon_compiler * c,
+ struct rc_instruction* inst,
+ void* unused)
+{
+ switch(inst->I.Opcode) {
+ case OPCODE_ABS: transform_r300_vertex_ABS(c, inst); return GL_TRUE;
+ case OPCODE_DP3: transform_DP3(c, inst); return GL_TRUE;
+ case OPCODE_DPH: transform_DPH(c, inst); return GL_TRUE;
+ case OPCODE_FLR: transform_FLR(c, inst); return GL_TRUE;
+ case OPCODE_LRP: transform_LRP(c, inst); return GL_TRUE;
+ case OPCODE_SUB: transform_SUB(c, inst); return GL_TRUE;
+ case OPCODE_SWZ: transform_SWZ(c, inst); return GL_TRUE;
+ case OPCODE_XPD: transform_XPD(c, inst); return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+static void sincos_constants(struct radeon_compiler* c, GLuint *constants)
+{
+ static const GLfloat SinCosConsts[2][4] = {
+ {
+ 1.273239545, // 4/PI
+ -0.405284735, // -4/(PI*PI)
+ 3.141592654, // PI
+ 0.2225 // weight
+ },
+ {
+ 0.75,
+ 0.5,
+ 0.159154943, // 1/(2*PI)
+ 6.283185307 // 2*PI
+ }
+ };
+ int i;
+
+ for(i = 0; i < 2; ++i)
+ constants[i] = rc_constants_add_immediate_vec4(&c->Program.Constants, SinCosConsts[i]);
+}
+
+/**
+ * Approximate sin(x), where x is clamped to (-pi/2, pi/2).
+ *
+ * MUL tmp.xy, src, { 4/PI, -4/(PI^2) }
+ * MAD tmp.x, tmp.y, |src|, tmp.x
+ * MAD tmp.y, tmp.x, |tmp.x|, -tmp.x
+ * MAD dest, tmp.y, weight, tmp.x
+ */
+static void sin_approx(
+ struct radeon_compiler* c, struct rc_instruction * after,
+ struct prog_dst_register dst, struct prog_src_register src, const GLuint* constants)
+{
+ GLuint tempreg = rc_find_free_temporary(c);
+
+ emit2(c, after->Prev, OPCODE_MUL, 0, dstregtmpmask(tempreg, WRITEMASK_XY),
+ swizzle(src, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ srcreg(PROGRAM_CONSTANT, constants[0]));
+ emit3(c, after->Prev, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_X),
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
+ absolute(swizzle(src, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)),
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X));
+ emit3(c, after->Prev, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_Y),
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ absolute(swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)),
+ negate(swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)));
+ emit3(c, after->Prev, OPCODE_MAD, 0, dst,
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[0]), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X));
+}
+
+/**
+ * Translate the trigonometric functions COS, SIN, and SCS
+ * using only the basic instructions
+ * MOV, ADD, MUL, MAD, FRC
+ */
+GLboolean radeonTransformTrigSimple(struct radeon_compiler* c,
+ struct rc_instruction* inst,
+ void* unused)
+{
+ if (inst->I.Opcode != OPCODE_COS &&
+ inst->I.Opcode != OPCODE_SIN &&
+ inst->I.Opcode != OPCODE_SCS)
+ return GL_FALSE;
+
+ GLuint constants[2];
+ GLuint tempreg = rc_find_free_temporary(c);
+
+ sincos_constants(c, constants);
+
+ if (inst->I.Opcode == OPCODE_COS) {
+ // MAD tmp.x, src, 1/(2*PI), 0.75
+ // FRC tmp.x, tmp.x
+ // MAD tmp.z, tmp.x, 2*PI, -PI
+ emit3(c, inst->Prev, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_W),
+ swizzle(inst->I.SrcReg[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X));
+ emit1(c, inst->Prev, OPCODE_FRC, 0, dstregtmpmask(tempreg, WRITEMASK_W),
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W));
+ emit3(c, inst->Prev, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_W),
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ negate(swizzle(srcreg(PROGRAM_CONSTANT, constants[0]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z)));
+
+ sin_approx(c, inst->Prev, inst->I.DstReg,
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ constants);
+ } else if (inst->I.Opcode == OPCODE_SIN) {
+ emit3(c, inst->Prev, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_W),
+ swizzle(inst->I.SrcReg[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y));
+ emit1(c, inst->Prev, OPCODE_FRC, 0, dstregtmpmask(tempreg, WRITEMASK_W),
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W));
+ emit3(c, inst->Prev, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_W),
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ negate(swizzle(srcreg(PROGRAM_CONSTANT, constants[0]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z)));
+
+ sin_approx(c, inst->Prev, inst->I.DstReg,
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ constants);
+ } else {
+ emit3(c, inst->Prev, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_XY),
+ swizzle(inst->I.SrcReg[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W));
+ emit1(c, inst->Prev, OPCODE_FRC, 0, dstregtmpmask(tempreg, WRITEMASK_XY),
+ srcreg(PROGRAM_TEMPORARY, tempreg));
+ emit3(c, inst->Prev, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_XY),
+ srcreg(PROGRAM_TEMPORARY, tempreg),
+ swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
+ negate(swizzle(srcreg(PROGRAM_CONSTANT, constants[0]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z)));
+
+ struct prog_dst_register dst = inst->I.DstReg;
+
+ dst.WriteMask = inst->I.DstReg.WriteMask & WRITEMASK_X;
+ sin_approx(c, inst->Prev, dst,
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ constants);
+
+ dst.WriteMask = inst->I.DstReg.WriteMask & WRITEMASK_Y;
+ sin_approx(c, inst->Prev, dst,
+ swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
+ constants);
+ }
+
+ rc_remove_instruction(inst);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Transform the trigonometric functions COS, SIN, and SCS
+ * to include pre-scaling by 1/(2*PI) and taking the fractional
+ * part, so that the input to COS and SIN is always in the range [0,1).
+ * SCS is replaced by one COS and one SIN instruction.
+ *
+ * @warning This transformation implicitly changes the semantics of SIN and COS!
+ */
+GLboolean radeonTransformTrigScale(struct radeon_compiler* c,
+ struct rc_instruction* inst,
+ void* unused)
+{
+ if (inst->I.Opcode != OPCODE_COS &&
+ inst->I.Opcode != OPCODE_SIN &&
+ inst->I.Opcode != OPCODE_SCS)
+ return GL_FALSE;
+
+ static const GLfloat RCP_2PI = 0.15915494309189535;
+ GLuint temp;
+ GLuint constant;
+ GLuint constant_swizzle;
+
+ temp = rc_find_free_temporary(c);
+ constant = rc_constants_add_immediate_scalar(&c->Program.Constants, RCP_2PI, &constant_swizzle);
+
+ emit2(c, inst->Prev, OPCODE_MUL, 0, dstregtmpmask(temp, WRITEMASK_W),
+ swizzle(inst->I.SrcReg[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ srcregswz(PROGRAM_CONSTANT, constant, constant_swizzle));
+ emit1(c, inst->Prev, OPCODE_FRC, 0, dstregtmpmask(temp, WRITEMASK_W),
+ srcreg(PROGRAM_TEMPORARY, temp));
+
+ if (inst->I.Opcode == OPCODE_COS) {
+ emit1(c, inst->Prev, OPCODE_COS, inst->I.SaturateMode, inst->I.DstReg,
+ srcregswz(PROGRAM_TEMPORARY, temp, SWIZZLE_WWWW));
+ } else if (inst->I.Opcode == OPCODE_SIN) {
+ emit1(c, inst->Prev, OPCODE_SIN, inst->I.SaturateMode,
+ inst->I.DstReg, srcregswz(PROGRAM_TEMPORARY, temp, SWIZZLE_WWWW));
+ } else if (inst->I.Opcode == OPCODE_SCS) {
+ struct prog_dst_register moddst = inst->I.DstReg;
+
+ if (inst->I.DstReg.WriteMask & WRITEMASK_X) {
+ moddst.WriteMask = WRITEMASK_X;
+ emit1(c, inst->Prev, OPCODE_COS, inst->I.SaturateMode, moddst,
+ srcregswz(PROGRAM_TEMPORARY, temp, SWIZZLE_WWWW));
+ }
+ if (inst->I.DstReg.WriteMask & WRITEMASK_Y) {
+ moddst.WriteMask = WRITEMASK_Y;
+ emit1(c, inst->Prev, OPCODE_SIN, inst->I.SaturateMode, moddst,
+ srcregswz(PROGRAM_TEMPORARY, temp, SWIZZLE_WWWW));
+ }
+ }
+
+ rc_remove_instruction(inst);
+
+ return GL_TRUE;
+}
+
+/**
+ * Rewrite DDX/DDY instructions to properly work with r5xx shaders.
+ * The r5xx MDH/MDV instruction provides per-quad partial derivatives.
+ * It takes the form A*B+C. A and C are set by setting src0. B should be -1.
+ *
+ * @warning This explicitly changes the form of DDX and DDY!
+ */
+
+GLboolean radeonTransformDeriv(struct radeon_compiler* c,
+ struct rc_instruction* inst,
+ void* unused)
+{
+ if (inst->I.Opcode != OPCODE_DDX && inst->I.Opcode != OPCODE_DDY)
+ return GL_FALSE;
+
+ inst->I.SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE);
+ inst->I.SrcReg[1].Negate = NEGATE_XYZW;
+
+ return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/r300/radeon_program_alu.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.h
index b45958115c..147efec6fc 100644
--- a/src/mesa/drivers/dri/r300/radeon_program_alu.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.h
@@ -31,23 +31,28 @@
#include "radeon_program.h"
GLboolean radeonTransformALU(
- struct radeon_transform_context *t,
- struct prog_instruction*,
+ struct radeon_compiler * c,
+ struct rc_instruction * inst,
+ void*);
+
+GLboolean r300_transform_vertex_alu(
+ struct radeon_compiler * c,
+ struct rc_instruction * inst,
void*);
GLboolean radeonTransformTrigSimple(
- struct radeon_transform_context *t,
- struct prog_instruction*,
+ struct radeon_compiler * c,
+ struct rc_instruction * inst,
void*);
GLboolean radeonTransformTrigScale(
- struct radeon_transform_context *t,
- struct prog_instruction*,
+ struct radeon_compiler * c,
+ struct rc_instruction * inst,
void*);
GLboolean radeonTransformDeriv(
- struct radeon_transform_context *t,
- struct prog_instruction*,
+ struct radeon_compiler * c,
+ struct rc_instruction * inst,
void*);
#endif /* __RADEON_PROGRAM_ALU_H_ */
diff --git a/src/mesa/drivers/dri/r300/radeon_program_pair.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
index 58bc0d5843..4c26db5d24 100644
--- a/src/mesa/drivers/dri/r300/radeon_program_pair.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
@@ -35,17 +35,19 @@
#include "radeon_program_pair.h"
-#include "radeon_context.h"
-
+#include "memory_pool.h"
+#include "radeon_compiler.h"
#include "shader/prog_print.h"
#define error(fmt, args...) do { \
- _mesa_problem(s->Ctx, "%s::%s(): " fmt "\n", \
+ rc_error(&s->Compiler->Base, "%s::%s(): " fmt "\n", \
__FILE__, __FUNCTION__, ##args); \
- s->Error = GL_TRUE; \
} while(0)
struct pair_state_instruction {
+ struct prog_instruction Instruction;
+ GLuint IP; /**< Position of this instruction in original program */
+
GLuint IsTex:1; /**< Is a texture instruction */
GLuint NeedRGB:1; /**< Needs the RGB ALU */
GLuint NeedAlpha:1; /**< Needs the Alpha ALU */
@@ -73,7 +75,7 @@ struct pair_state_instruction {
* Used to keep track of which instructions read a value.
*/
struct reg_value_reader {
- GLuint IP; /**< IP of the instruction that performs this access */
+ struct pair_state_instruction *Reader;
struct reg_value_reader *Next;
};
@@ -82,7 +84,7 @@ struct reg_value_reader {
* PROGRAM_TEMPORARY.
*/
struct reg_value {
- GLuint IP; /**< IP of the instruction that writes this value */
+ struct pair_state_instruction *Writer;
struct reg_value *Next; /**< Pointer to the next value to be written to the same PROGRAM_TEMPORARY component */
/**
@@ -116,11 +118,8 @@ struct pair_register_translation {
};
struct pair_state {
- GLcontext *Ctx;
- struct gl_program *Program;
+ struct r300_fragment_program_compiler * Compiler;
const struct radeon_pair_handler *Handler;
- GLboolean Error;
- GLboolean Debug;
GLboolean Verbose;
void *UserData;
@@ -130,11 +129,6 @@ struct pair_state {
struct pair_register_translation Inputs[FRAG_ATTRIB_MAX];
struct pair_register_translation Temps[MAX_PROGRAM_TEMPS];
- /**
- * Derived information about program instructions.
- */
- struct pair_state_instruction *Instructions;
-
struct {
GLuint RefCount; /**< # of times this occurs in an unscheduled SrcReg or DstReg */
} HwTemps[128];
@@ -147,14 +141,6 @@ struct pair_state {
struct pair_state_instruction *ReadyRGB;
struct pair_state_instruction *ReadyAlpha;
struct pair_state_instruction *ReadyTEX;
-
- /**
- * Pool of @ref reg_value structures for fast allocation.
- */
- struct reg_value *ValuePool;
- GLuint ValuePoolUsed;
- struct reg_value_reader *ReaderPool;
- GLuint ReaderPoolUsed;
};
@@ -183,7 +169,7 @@ static GLuint get_hw_reg(struct pair_state *s, GLuint file, GLuint index)
struct pair_register_translation *t = get_register(s, file, index);
if (!t) {
- _mesa_problem(s->Ctx, "get_hw_reg: %i[%i]\n", file, index);
+ error("get_hw_reg: %i[%i]\n", file, index);
return 0;
}
@@ -221,15 +207,13 @@ static void add_pairinst_to_list(struct pair_state_instruction **list, struct pa
}
/**
- * The instruction at the given IP has become ready. Link it into the ready
+ * The given instruction has become ready. Link it into the ready
* instructions.
*/
-static void instruction_ready(struct pair_state *s, int ip)
+static void instruction_ready(struct pair_state *s, struct pair_state_instruction *pairinst)
{
- struct pair_state_instruction *pairinst = s->Instructions + ip;
-
if (s->Verbose)
- _mesa_printf("instruction_ready(%i)\n", ip);
+ _mesa_printf("instruction_ready(%i)\n", pairinst->IP);
if (pairinst->IsTex)
add_pairinst_to_list(&s->ReadyTEX, pairinst);
@@ -255,8 +239,7 @@ static void final_rewrite(struct pair_state *s, struct prog_instruction *inst)
inst->SrcReg[2] = inst->SrcReg[1];
inst->SrcReg[1].File = PROGRAM_BUILTIN;
inst->SrcReg[1].Swizzle = SWIZZLE_1111;
- inst->SrcReg[1].NegateBase = 0;
- inst->SrcReg[1].NegateAbs = 0;
+ inst->SrcReg[1].Negate = NEGATE_NONE;
inst->Opcode = OPCODE_MAD;
break;
case OPCODE_CMP:
@@ -297,12 +280,12 @@ static void final_rewrite(struct pair_state *s, struct prog_instruction *inst)
* Classify an instruction according to which ALUs etc. it needs
*/
static void classify_instruction(struct pair_state *s,
- struct prog_instruction *inst, struct pair_state_instruction *pairinst)
+ struct pair_state_instruction *psi)
{
- pairinst->NeedRGB = (inst->DstReg.WriteMask & WRITEMASK_XYZ) ? 1 : 0;
- pairinst->NeedAlpha = (inst->DstReg.WriteMask & WRITEMASK_W) ? 1 : 0;
+ psi->NeedRGB = (psi->Instruction.DstReg.WriteMask & WRITEMASK_XYZ) ? 1 : 0;
+ psi->NeedAlpha = (psi->Instruction.DstReg.WriteMask & WRITEMASK_W) ? 1 : 0;
- switch(inst->Opcode) {
+ switch(psi->Instruction.Opcode) {
case OPCODE_ADD:
case OPCODE_CMP:
case OPCODE_DDX:
@@ -320,24 +303,24 @@ static void classify_instruction(struct pair_state *s,
case OPCODE_RCP:
case OPCODE_RSQ:
case OPCODE_SIN:
- pairinst->IsTranscendent = 1;
- pairinst->NeedAlpha = 1;
+ psi->IsTranscendent = 1;
+ psi->NeedAlpha = 1;
break;
case OPCODE_DP4:
- pairinst->NeedAlpha = 1;
+ psi->NeedAlpha = 1;
/* fall through */
case OPCODE_DP3:
- pairinst->NeedRGB = 1;
+ psi->NeedRGB = 1;
break;
case OPCODE_KIL:
case OPCODE_TEX:
case OPCODE_TXB:
case OPCODE_TXP:
case OPCODE_END:
- pairinst->IsTex = 1;
+ psi->IsTex = 1;
break;
default:
- error("Unknown opcode %d\n", inst->Opcode);
+ error("Unknown opcode %d\n", psi->Instruction.Opcode);
break;
}
}
@@ -349,30 +332,34 @@ static void classify_instruction(struct pair_state *s,
*/
static void scan_instructions(struct pair_state *s)
{
- struct prog_instruction *inst;
- struct pair_state_instruction *pairinst;
+ struct rc_instruction *source;
GLuint ip;
- for(inst = s->Program->Instructions, pairinst = s->Instructions, ip = 0;
- inst->Opcode != OPCODE_END;
- ++inst, ++pairinst, ++ip) {
- final_rewrite(s, inst);
- classify_instruction(s, inst, pairinst);
+ for(source = s->Compiler->Base.Program.Instructions.Next, ip = 0;
+ source != &s->Compiler->Base.Program.Instructions;
+ source = source->Next, ++ip) {
+ struct pair_state_instruction *pairinst = memory_pool_malloc(&s->Compiler->Base.Pool, sizeof(*pairinst));
+ memset(pairinst, 0, sizeof(struct pair_state_instruction));
- int nsrc = _mesa_num_inst_src_regs(inst->Opcode);
+ pairinst->Instruction = source->I;
+ pairinst->IP = ip;
+ final_rewrite(s, &pairinst->Instruction);
+ classify_instruction(s, pairinst);
+
+ int nsrc = _mesa_num_inst_src_regs(pairinst->Instruction.Opcode);
int j;
for(j = 0; j < nsrc; j++) {
struct pair_register_translation *t =
- get_register(s, inst->SrcReg[j].File, inst->SrcReg[j].Index);
+ get_register(s, pairinst->Instruction.SrcReg[j].File, pairinst->Instruction.SrcReg[j].Index);
if (!t)
continue;
t->RefCount++;
- if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
+ if (pairinst->Instruction.SrcReg[j].File == PROGRAM_TEMPORARY) {
int i;
for(i = 0; i < 4; ++i) {
- GLuint swz = GET_SWZ(inst->SrcReg[j].Swizzle, i);
+ GLuint swz = GET_SWZ(pairinst->Instruction.SrcReg[j].Swizzle, i);
if (swz >= 4)
continue; /* constant or NIL swizzle */
if (!t->Value[swz])
@@ -382,36 +369,37 @@ static void scan_instructions(struct pair_state *s)
* also rewrites the value. The code below adds
* a dependency for the DstReg, which is a superset
* of the SrcReg dependency. */
- if (inst->DstReg.File == PROGRAM_TEMPORARY &&
- inst->DstReg.Index == inst->SrcReg[j].Index &&
- GET_BIT(inst->DstReg.WriteMask, swz))
+ if (pairinst->Instruction.DstReg.File == PROGRAM_TEMPORARY &&
+ pairinst->Instruction.DstReg.Index == pairinst->Instruction.SrcReg[j].Index &&
+ GET_BIT(pairinst->Instruction.DstReg.WriteMask, swz))
continue;
- struct reg_value_reader* r = &s->ReaderPool[s->ReaderPoolUsed++];
+ struct reg_value_reader* r = memory_pool_malloc(&s->Compiler->Base.Pool, sizeof(*r));
pairinst->NumDependencies++;
t->Value[swz]->NumReaders++;
- r->IP = ip;
+ r->Reader = pairinst;
r->Next = t->Value[swz]->Readers;
t->Value[swz]->Readers = r;
}
}
}
- int ndst = _mesa_num_inst_dst_regs(inst->Opcode);
+ int ndst = _mesa_num_inst_dst_regs(pairinst->Instruction.Opcode);
if (ndst) {
struct pair_register_translation *t =
- get_register(s, inst->DstReg.File, inst->DstReg.Index);
+ get_register(s, pairinst->Instruction.DstReg.File, pairinst->Instruction.DstReg.Index);
if (t) {
t->RefCount++;
- if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ if (pairinst->Instruction.DstReg.File == PROGRAM_TEMPORARY) {
int j;
for(j = 0; j < 4; ++j) {
- if (!GET_BIT(inst->DstReg.WriteMask, j))
+ if (!GET_BIT(pairinst->Instruction.DstReg.WriteMask, j))
continue;
- struct reg_value* v = &s->ValuePool[s->ValuePoolUsed++];
- v->IP = ip;
+ struct reg_value* v = memory_pool_malloc(&s->Compiler->Base.Pool, sizeof(*v));
+ memset(v, 0, sizeof(struct reg_value));
+ v->Writer = pairinst;
if (t->Value[j]) {
pairinst->NumDependencies++;
t->Value[j]->Next = v;
@@ -427,7 +415,7 @@ static void scan_instructions(struct pair_state *s)
_mesa_printf("scan(%i): NumDeps = %i\n", ip, pairinst->NumDependencies);
if (!pairinst->NumDependencies)
- instruction_ready(s, ip);
+ instruction_ready(s, pairinst);
}
/* Clear the PROGRAM_TEMPORARY state */
@@ -439,70 +427,23 @@ static void scan_instructions(struct pair_state *s)
}
-/**
- * Reserve hardware temporary registers for the program inputs.
- *
- * @note This allocation is performed explicitly, because the order of inputs
- * is determined by the RS hardware.
- */
-static void allocate_input_registers(struct pair_state *s)
+static void decrement_dependencies(struct pair_state *s, struct pair_state_instruction *pairinst)
{
- GLuint InputsRead = s->Program->InputsRead;
- int i;
- GLuint hwindex = 0;
-
- /* Texcoords come first */
- for (i = 0; i < s->Ctx->Const.MaxTextureUnits; i++) {
- if (InputsRead & (FRAG_BIT_TEX0 << i))
- alloc_hw_reg(s, PROGRAM_INPUT, FRAG_ATTRIB_TEX0+i, hwindex++);
- }
- InputsRead &= ~FRAG_BITS_TEX_ANY;
-
- /* fragment position treated as a texcoord */
- if (InputsRead & FRAG_BIT_WPOS)
- alloc_hw_reg(s, PROGRAM_INPUT, FRAG_ATTRIB_WPOS, hwindex++);
- InputsRead &= ~FRAG_BIT_WPOS;
-
- /* Then primary colour */
- if (InputsRead & FRAG_BIT_COL0)
- alloc_hw_reg(s, PROGRAM_INPUT, FRAG_ATTRIB_COL0, hwindex++);
- InputsRead &= ~FRAG_BIT_COL0;
-
- /* Secondary color */
- if (InputsRead & FRAG_BIT_COL1)
- alloc_hw_reg(s, PROGRAM_INPUT, FRAG_ATTRIB_COL1, hwindex++);
- InputsRead &= ~FRAG_BIT_COL1;
-
- /* Fog coordinate */
- if (InputsRead & FRAG_BIT_FOGC)
- alloc_hw_reg(s, PROGRAM_INPUT, FRAG_ATTRIB_FOGC, hwindex++);
- InputsRead &= ~FRAG_BIT_FOGC;
-
- /* Anything else */
- if (InputsRead)
- error("Don't know how to handle inputs 0x%x\n", InputsRead);
-}
-
-
-static void decrement_dependencies(struct pair_state *s, int ip)
-{
- struct pair_state_instruction *pairinst = s->Instructions + ip;
ASSERT(pairinst->NumDependencies > 0);
if (!--pairinst->NumDependencies)
- instruction_ready(s, ip);
+ instruction_ready(s, pairinst);
}
/**
* Update the dependency tracking state based on what the instruction
* at the given IP does.
*/
-static void commit_instruction(struct pair_state *s, int ip)
+static void commit_instruction(struct pair_state *s, struct pair_state_instruction *pairinst)
{
- struct prog_instruction *inst = s->Program->Instructions + ip;
- struct pair_state_instruction *pairinst = s->Instructions + ip;
+ struct prog_instruction *inst = &pairinst->Instruction;
if (s->Verbose)
- _mesa_printf("commit_instruction(%i)\n", ip);
+ _mesa_printf("commit_instruction(%i)\n", pairinst->IP);
if (inst->DstReg.File == PROGRAM_TEMPORARY) {
struct pair_register_translation *t = &s->Temps[inst->DstReg.Index];
@@ -517,11 +458,11 @@ static void commit_instruction(struct pair_state *s, int ip)
if (t->Value[i]->NumReaders) {
struct reg_value_reader *r;
for(r = pairinst->Values[i]->Readers; r; r = r->Next)
- decrement_dependencies(s, r->IP);
+ decrement_dependencies(s, r->Reader);
} else if (t->Value[i]->Next) {
/* This happens when the only reader writes
* the register at the same time */
- decrement_dependencies(s, t->Value[i]->Next->IP);
+ decrement_dependencies(s, t->Value[i]->Next->Writer);
}
}
}
@@ -555,7 +496,7 @@ static void commit_instruction(struct pair_state *s, int ip)
if (!--t->Value[swz]->NumReaders) {
if (t->Value[swz]->Next)
- decrement_dependencies(s, t->Value[swz]->Next->IP);
+ decrement_dependencies(s, t->Value[swz]->Next->Writer);
}
}
}
@@ -586,35 +527,52 @@ static void emit_all_tex(struct pair_state *s)
// Allocate destination hardware registers in one block to avoid conflicts.
for(pairinst = readytex; pairinst; pairinst = pairinst->NextReady) {
- int ip = pairinst - s->Instructions;
- struct prog_instruction *inst = s->Program->Instructions + ip;
+ struct prog_instruction *inst = &pairinst->Instruction;
if (inst->Opcode != OPCODE_KIL)
get_hw_reg(s, inst->DstReg.File, inst->DstReg.Index);
}
- if (s->Debug)
+ if (s->Compiler->Base.Debug)
_mesa_printf(" BEGIN_TEX\n");
if (s->Handler->BeginTexBlock)
- s->Error = s->Error || !s->Handler->BeginTexBlock(s->UserData);
+ s->Compiler->Base.Error = s->Compiler->Base.Error || !s->Handler->BeginTexBlock(s->UserData);
for(pairinst = readytex; pairinst; pairinst = pairinst->NextReady) {
- int ip = pairinst - s->Instructions;
- struct prog_instruction *inst = s->Program->Instructions + ip;
- commit_instruction(s, ip);
+ struct prog_instruction *inst = &pairinst->Instruction;
+ commit_instruction(s, pairinst);
if (inst->Opcode != OPCODE_KIL)
inst->DstReg.Index = get_hw_reg(s, inst->DstReg.File, inst->DstReg.Index);
inst->SrcReg[0].Index = get_hw_reg(s, inst->SrcReg[0].File, inst->SrcReg[0].Index);
- if (s->Debug) {
+ if (s->Compiler->Base.Debug) {
_mesa_printf(" ");
_mesa_print_instruction(inst);
+ fflush(stderr);
+ }
+
+ struct radeon_pair_texture_instruction rpti;
+
+ switch(inst->Opcode) {
+ case OPCODE_TEX: rpti.Opcode = RADEON_OPCODE_TEX; break;
+ case OPCODE_TXB: rpti.Opcode = RADEON_OPCODE_TXB; break;
+ case OPCODE_TXP: rpti.Opcode = RADEON_OPCODE_TXP; break;
+ default:
+ case OPCODE_KIL: rpti.Opcode = RADEON_OPCODE_KIL; break;
}
- s->Error = s->Error || !s->Handler->EmitTex(s->UserData, inst);
+
+ rpti.DestIndex = inst->DstReg.Index;
+ rpti.WriteMask = inst->DstReg.WriteMask;
+ rpti.TexSrcUnit = inst->TexSrcUnit;
+ rpti.TexSrcTarget = inst->TexSrcTarget;
+ rpti.SrcIndex = inst->SrcReg[0].Index;
+ rpti.SrcSwizzle = inst->SrcReg[0].Swizzle;
+
+ s->Compiler->Base.Error = s->Compiler->Base.Error || !s->Handler->EmitTex(s->UserData, &rpti);
}
- if (s->Debug)
+ if (s->Compiler->Base.Debug)
_mesa_printf(" END_TEX\n");
}
@@ -637,7 +595,7 @@ static int alloc_pair_source(struct pair_state *s, struct radeon_pair_instructio
index = get_hw_reg(s, src.File, src.Index);
} else {
constant = 1;
- s->Error |= !s->Handler->EmitConst(s->UserData, src.File, src.Index, &index);
+ index = src.Index;
}
for(i = 0; i < 3; ++i) {
@@ -684,10 +642,12 @@ static int alloc_pair_source(struct pair_state *s, struct radeon_pair_instructio
* Fill the given ALU instruction's opcodes and source operands into the given pair,
* if possible.
*/
-static GLboolean fill_instruction_into_pair(struct pair_state *s, struct radeon_pair_instruction *pair, int ip)
+static GLboolean fill_instruction_into_pair(
+ struct pair_state *s,
+ struct radeon_pair_instruction *pair,
+ struct pair_state_instruction *pairinst)
{
- struct pair_state_instruction *pairinst = s->Instructions + ip;
- struct prog_instruction *inst = s->Program->Instructions + ip;
+ struct prog_instruction *inst = &pairinst->Instruction;
ASSERT(!pairinst->NeedRGB || pair->RGB.Opcode == OPCODE_NOP);
ASSERT(!pairinst->NeedAlpha || pair->Alpha.Opcode == OPCODE_NOP);
@@ -722,7 +682,6 @@ static GLboolean fill_instruction_into_pair(struct pair_state *s, struct radeon_
if (pairinst->NeedRGB && !pairinst->IsTranscendent) {
GLboolean srcrgb = GL_FALSE;
GLboolean srcalpha = GL_FALSE;
- GLuint negatebase = 0;
int j;
for(j = 0; j < 3; ++j) {
GLuint swz = GET_SWZ(inst->SrcReg[i].Swizzle, j);
@@ -730,8 +689,6 @@ static GLboolean fill_instruction_into_pair(struct pair_state *s, struct radeon_
srcrgb = GL_TRUE;
else if (swz < 4)
srcalpha = GL_TRUE;
- if (swz != SWIZZLE_NIL && GET_BIT(inst->SrcReg[i].NegateBase, j))
- negatebase = 1;
}
source = alloc_pair_source(s, pair, inst->SrcReg[i], srcrgb, srcalpha);
if (source < 0)
@@ -739,12 +696,11 @@ static GLboolean fill_instruction_into_pair(struct pair_state *s, struct radeon_
pair->RGB.Arg[i].Source = source;
pair->RGB.Arg[i].Swizzle = inst->SrcReg[i].Swizzle & 0x1ff;
pair->RGB.Arg[i].Abs = inst->SrcReg[i].Abs;
- pair->RGB.Arg[i].Negate = (negatebase & ~pair->RGB.Arg[i].Abs) ^ inst->SrcReg[i].NegateAbs;
+ pair->RGB.Arg[i].Negate = !!(inst->SrcReg[i].Negate & (NEGATE_X | NEGATE_Y | NEGATE_Z));
}
if (pairinst->NeedAlpha) {
GLboolean srcrgb = GL_FALSE;
GLboolean srcalpha = GL_FALSE;
- GLuint negatebase = GET_BIT(inst->SrcReg[i].NegateBase, pairinst->IsTranscendent ? 0 : 3);
GLuint swz = GET_SWZ(inst->SrcReg[i].Swizzle, pairinst->IsTranscendent ? 0 : 3);
if (swz < 3)
srcrgb = GL_TRUE;
@@ -756,7 +712,7 @@ static GLboolean fill_instruction_into_pair(struct pair_state *s, struct radeon_
pair->Alpha.Arg[i].Source = source;
pair->Alpha.Arg[i].Swizzle = swz;
pair->Alpha.Arg[i].Abs = inst->SrcReg[i].Abs;
- pair->Alpha.Arg[i].Negate = (negatebase & ~pair->RGB.Arg[i].Abs) ^ inst->SrcReg[i].NegateAbs;
+ pair->Alpha.Arg[i].Negate = !!(inst->SrcReg[i].Negate & NEGATE_W);
}
}
@@ -772,16 +728,18 @@ static GLboolean fill_instruction_into_pair(struct pair_state *s, struct radeon_
* we are absolutely certain that we're going to emit a certain
* instruction pairing.
*/
-static void fill_dest_into_pair(struct pair_state *s, struct radeon_pair_instruction *pair, int ip)
+static void fill_dest_into_pair(
+ struct pair_state *s,
+ struct radeon_pair_instruction *pair,
+ struct pair_state_instruction *pairinst)
{
- struct pair_state_instruction *pairinst = s->Instructions + ip;
- struct prog_instruction *inst = s->Program->Instructions + ip;
+ struct prog_instruction *inst = &pairinst->Instruction;
if (inst->DstReg.File == PROGRAM_OUTPUT) {
- if (inst->DstReg.Index == FRAG_RESULT_COLR) {
+ if (inst->DstReg.Index == s->Compiler->OutputColor) {
pair->RGB.OutputWriteMask |= inst->DstReg.WriteMask & WRITEMASK_XYZ;
pair->Alpha.OutputWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3);
- } else if (inst->DstReg.Index == FRAG_RESULT_DEPR) {
+ } else if (inst->DstReg.Index == s->Compiler->OutputDepth) {
pair->Alpha.DepthWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3);
}
} else {
@@ -808,24 +766,24 @@ static void fill_dest_into_pair(struct pair_state *s, struct radeon_pair_instruc
static void emit_alu(struct pair_state *s)
{
struct radeon_pair_instruction pair;
+ struct pair_state_instruction *psi;
if (s->ReadyFullALU || !(s->ReadyRGB && s->ReadyAlpha)) {
- int ip;
if (s->ReadyFullALU) {
- ip = s->ReadyFullALU - s->Instructions;
+ psi = s->ReadyFullALU;
s->ReadyFullALU = s->ReadyFullALU->NextReady;
} else if (s->ReadyRGB) {
- ip = s->ReadyRGB - s->Instructions;
+ psi = s->ReadyRGB;
s->ReadyRGB = s->ReadyRGB->NextReady;
} else {
- ip = s->ReadyAlpha - s->Instructions;
+ psi = s->ReadyAlpha;
s->ReadyAlpha = s->ReadyAlpha->NextReady;
}
_mesa_bzero(&pair, sizeof(pair));
- fill_instruction_into_pair(s, &pair, ip);
- fill_dest_into_pair(s, &pair, ip);
- commit_instruction(s, ip);
+ fill_instruction_into_pair(s, &pair, psi);
+ fill_dest_into_pair(s, &pair, psi);
+ commit_instruction(s, psi);
} else {
struct pair_state_instruction **prgb;
struct pair_state_instruction **palpha;
@@ -834,65 +792,65 @@ static void emit_alu(struct pair_state *s)
* many source slots; try all possible pairings if necessary */
for(prgb = &s->ReadyRGB; *prgb; prgb = &(*prgb)->NextReady) {
for(palpha = &s->ReadyAlpha; *palpha; palpha = &(*palpha)->NextReady) {
- int rgbip = *prgb - s->Instructions;
- int alphaip = *palpha - s->Instructions;
+ struct pair_state_instruction * psirgb = *prgb;
+ struct pair_state_instruction * psialpha = *palpha;
_mesa_bzero(&pair, sizeof(pair));
- fill_instruction_into_pair(s, &pair, rgbip);
- if (!fill_instruction_into_pair(s, &pair, alphaip))
+ fill_instruction_into_pair(s, &pair, psirgb);
+ if (!fill_instruction_into_pair(s, &pair, psialpha))
continue;
*prgb = (*prgb)->NextReady;
*palpha = (*palpha)->NextReady;
- fill_dest_into_pair(s, &pair, rgbip);
- fill_dest_into_pair(s, &pair, alphaip);
- commit_instruction(s, rgbip);
- commit_instruction(s, alphaip);
+ fill_dest_into_pair(s, &pair, psirgb);
+ fill_dest_into_pair(s, &pair, psialpha);
+ commit_instruction(s, psirgb);
+ commit_instruction(s, psialpha);
goto success;
}
}
/* No success in pairing; just take the first RGB instruction */
- int ip = s->ReadyRGB - s->Instructions;
+ psi = s->ReadyRGB;
s->ReadyRGB = s->ReadyRGB->NextReady;
+
_mesa_bzero(&pair, sizeof(pair));
- fill_instruction_into_pair(s, &pair, ip);
- fill_dest_into_pair(s, &pair, ip);
- commit_instruction(s, ip);
+ fill_instruction_into_pair(s, &pair, psi);
+ fill_dest_into_pair(s, &pair, psi);
+ commit_instruction(s, psi);
success: ;
}
- if (s->Debug)
+ if (s->Compiler->Base.Debug)
radeonPrintPairInstruction(&pair);
- s->Error = s->Error || !s->Handler->EmitPaired(s->UserData, &pair);
+ s->Compiler->Base.Error = s->Compiler->Base.Error || !s->Handler->EmitPaired(s->UserData, &pair);
}
+/* Callback function for assigning input registers to hardware registers */
+static void alloc_helper(void * data, unsigned input, unsigned hwreg)
+{
+ struct pair_state * s = data;
+ alloc_hw_reg(s, PROGRAM_INPUT, input, hwreg);
+}
-GLboolean radeonPairProgram(GLcontext *ctx, struct gl_program *program,
+void radeonPairProgram(
+ struct r300_fragment_program_compiler * compiler,
const struct radeon_pair_handler* handler, void *userdata)
{
struct pair_state s;
_mesa_bzero(&s, sizeof(s));
- s.Ctx = ctx;
- s.Program = program;
+ s.Compiler = compiler;
s.Handler = handler;
s.UserData = userdata;
- s.Debug = (RADEON_DEBUG & DEBUG_PIXEL) ? GL_TRUE : GL_FALSE;
- s.Verbose = GL_FALSE && s.Debug;
-
- s.Instructions = (struct pair_state_instruction*)_mesa_calloc(
- sizeof(struct pair_state_instruction)*s.Program->NumInstructions);
- s.ValuePool = (struct reg_value*)_mesa_calloc(sizeof(struct reg_value)*s.Program->NumInstructions*4);
- s.ReaderPool = (struct reg_value_reader*)_mesa_calloc(
- sizeof(struct reg_value_reader)*s.Program->NumInstructions*12);
+ s.Verbose = GL_FALSE && s.Compiler->Base.Debug;
- if (s.Debug)
+ if (s.Compiler->Base.Debug)
_mesa_printf("Emit paired program\n");
scan_instructions(&s);
- allocate_input_registers(&s);
+ s.Compiler->AllocateHwInputs(s.Compiler, &alloc_helper, &s);
- while(!s.Error &&
+ while(!s.Compiler->Base.Error &&
(s.ReadyTEX || s.ReadyRGB || s.ReadyAlpha || s.ReadyFullALU)) {
if (s.ReadyTEX)
emit_all_tex(&s);
@@ -901,14 +859,8 @@ GLboolean radeonPairProgram(GLcontext *ctx, struct gl_program *program,
emit_alu(&s);
}
- if (s.Debug)
+ if (s.Compiler->Base.Debug)
_mesa_printf(" END\n");
-
- _mesa_free(s.Instructions);
- _mesa_free(s.ValuePool);
- _mesa_free(s.ReaderPool);
-
- return !s.Error;
}
diff --git a/src/mesa/drivers/dri/r300/radeon_program_pair.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
index 4624a24629..ff76178551 100644
--- a/src/mesa/drivers/dri/r300/radeon_program_pair.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
@@ -30,6 +30,8 @@
#include "radeon_program.h"
+struct r300_fragment_program_compiler;
+
/**
* Represents a paired instruction, as found in R300 and R500
@@ -82,18 +84,32 @@ struct radeon_pair_instruction {
};
+enum {
+ RADEON_OPCODE_TEX = 0,
+ RADEON_OPCODE_TXB,
+ RADEON_OPCODE_TXP,
+ RADEON_OPCODE_KIL
+};
+
+struct radeon_pair_texture_instruction {
+ GLuint Opcode:2; /**< one of RADEON_OPCODE_xxx */
+
+ GLuint DestIndex:8;
+ GLuint WriteMask:4;
+
+ GLuint TexSrcUnit:5;
+ GLuint TexSrcTarget:3;
+
+ GLuint SrcIndex:8;
+ GLuint SrcSwizzle:12;
+};
+
+
/**
*
*/
struct radeon_pair_handler {
/**
- * Fill in the proper hardware index for the given constant register.
- *
- * @return GL_FALSE on error.
- */
- GLboolean (*EmitConst)(void*, GLuint file, GLuint index, GLuint *hwindex);
-
- /**
* Write a paired instruction to the hardware.
*
* @return GL_FALSE on error.
@@ -107,7 +123,7 @@ struct radeon_pair_handler {
*
* @return GL_FALSE on error.
*/
- GLboolean (*EmitTex)(void*, struct prog_instruction*);
+ GLboolean (*EmitTex)(void*, struct radeon_pair_texture_instruction*);
/**
* Called before a block of contiguous, independent texture
@@ -115,10 +131,11 @@ struct radeon_pair_handler {
*/
GLboolean (*BeginTexBlock)(void*);
- GLuint MaxHwTemps;
+ unsigned MaxHwTemps;
};
-GLboolean radeonPairProgram(GLcontext *ctx, struct gl_program *program,
+void radeonPairProgram(
+ struct r300_fragment_program_compiler * compiler,
const struct radeon_pair_handler*, void *userdata);
void radeonPrintPairInstruction(struct radeon_pair_instruction *inst);
diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
index c9e1dfe977..da5b7ba642 100644
--- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c
+++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
@@ -44,237 +44,425 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "drm.h"
#include "radeon_drm.h"
-#include "radeon_ioctl.h"
#include "r300_context.h"
#include "r300_ioctl.h"
#include "radeon_reg.h"
#include "r300_reg.h"
#include "r300_cmdbuf.h"
#include "r300_emit.h"
+#include "radeon_bocs_wrapper.h"
+#include "radeon_mipmap_tree.h"
#include "r300_state.h"
+#include "radeon_reg.h"
+#include "radeon_queryobj.h"
-// Set this to 1 for extremely verbose debugging of command buffers
-#define DEBUG_CMDBUF 0
-
-/**
- * Send the current command buffer via ioctl to the hardware.
+/** # of dwords reserved for additional instructions that may need to be written
+ * during flushing.
*/
-int r300FlushCmdBufLocked(r300ContextPtr r300, const char *caller)
-{
- int ret;
- int i;
- drm_radeon_cmd_buffer_t cmd;
- int start;
-
- if (r300->radeon.lost_context) {
- start = 0;
- r300->radeon.lost_context = GL_FALSE;
- } else
- start = r300->cmdbuf.count_reemit;
-
- if (RADEON_DEBUG & DEBUG_IOCTL) {
- fprintf(stderr, "%s from %s - %i cliprects\n",
- __FUNCTION__, caller, r300->radeon.numClipRects);
-
- if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_VERBOSE)
- for (i = start; i < r300->cmdbuf.count_used; ++i)
- fprintf(stderr, "%d: %08x\n", i,
- r300->cmdbuf.cmd_buf[i]);
- }
+#define SPACE_FOR_FLUSHING 4
- cmd.buf = (char *)(r300->cmdbuf.cmd_buf + start);
- cmd.bufsz = (r300->cmdbuf.count_used - start) * 4;
+static unsigned packet0_count(r300ContextPtr r300, uint32_t *pkt)
+{
+ if (r300->radeon.radeonScreen->kernel_mm) {
+ return ((((*pkt) >> 16) & 0x3FFF) + 1);
+ } else {
+ drm_r300_cmd_header_t *t = (drm_r300_cmd_header_t*)pkt;
+ return t->packet0.count;
+ }
+}
- if (r300->radeon.state.scissor.enabled) {
- cmd.nbox = r300->radeon.state.scissor.numClipRects;
- cmd.boxes =
- (drm_clip_rect_t *) r300->radeon.state.scissor.pClipRects;
- } else {
- cmd.nbox = r300->radeon.numClipRects;
- cmd.boxes = (drm_clip_rect_t *) r300->radeon.pClipRects;
- }
+#define vpu_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count)
+#define r500fp_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->r500fp.count)
- ret = drmCommandWrite(r300->radeon.dri.fd,
- DRM_RADEON_CMDBUF, &cmd, sizeof(cmd));
+int check_vpu(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ int cnt;
+ int extra = 1;
+ cnt = vpu_count(atom->cmd);
- if (RADEON_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "Syncing in %s (from %s)\n\n",
- __FUNCTION__, caller);
- radeonWaitForIdleLocked(&r300->radeon);
+ if (r300->radeon.radeonScreen->kernel_mm) {
+ extra = 5;
}
- r300->dma.nr_released_bufs = 0;
- r300->cmdbuf.count_used = 0;
- r300->cmdbuf.count_reemit = 0;
-
- return ret;
+ return cnt ? (cnt * 4) + extra : 0;
}
-int r300FlushCmdBuf(r300ContextPtr r300, const char *caller)
-{
- int ret;
-
- LOCK_HARDWARE(&r300->radeon);
- ret = r300FlushCmdBufLocked(r300, caller);
+void emit_vpu(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ BATCH_LOCALS(&r300->radeon);
+ drm_r300_cmd_header_t cmd;
+ uint32_t addr, ndw;
+
+ cmd.u = atom->cmd[0];
+ addr = (cmd.vpu.adrhi << 8) | cmd.vpu.adrlo;
+ ndw = atom->check(ctx, atom);
+
+ BEGIN_BATCH_NO_AUTOSTATE(ndw);
+
+ ndw -= 5;
+ OUT_BATCH_REGVAL(R300_VAP_PVS_VECTOR_INDX_REG, addr);
+ OUT_BATCH(CP_PACKET0(R300_VAP_PVS_UPLOAD_DATA, ndw-1) | RADEON_ONE_REG_WR);
+ OUT_BATCH_TABLE(&atom->cmd[1], ndw);
+ OUT_BATCH_REGVAL(R300_VAP_PVS_STATE_FLUSH_REG, 0);
+ END_BATCH();
+}
- UNLOCK_HARDWARE(&r300->radeon);
+void emit_r500fp(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ BATCH_LOCALS(&r300->radeon);
+ drm_r300_cmd_header_t cmd;
+ uint32_t addr, ndw, sz;
+ int type, clamp;
+
+ ndw = atom->check(ctx, atom);
+
+ cmd.u = atom->cmd[0];
+ sz = cmd.r500fp.count;
+ addr = ((cmd.r500fp.adrhi_flags & 1) << 8) | cmd.r500fp.adrlo;
+ type = !!(cmd.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
+ clamp = !!(cmd.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
+
+ addr |= (type << 16);
+ addr |= (clamp << 17);
+
+ BEGIN_BATCH_NO_AUTOSTATE(ndw);
+ OUT_BATCH(CP_PACKET0(R500_GA_US_VECTOR_INDEX, 0));
+ OUT_BATCH(addr);
+ ndw-=3;
+ OUT_BATCH(CP_PACKET0(R500_GA_US_VECTOR_DATA, ndw-1) | RADEON_ONE_REG_WR);
+ OUT_BATCH_TABLE(&atom->cmd[1], ndw);
+ END_BATCH();
+}
- if (ret) {
- fprintf(stderr, "drmRadeonCmdBuffer: %d\n", ret);
- _mesa_exit(ret);
+static int check_tex_offsets(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ int numtmus = packet0_count(r300, r300->hw.tex.offset.cmd);
+ int dw = 0, i;
+ if (atom->cmd[0] == CP_PACKET2) {
+ return dw;
}
-
- return ret;
+ for(i = 0; i < numtmus; ++i) {
+ radeonTexObj *t = r300->hw.textures[i];
+ if (!t && !r300->radeon.radeonScreen->kernel_mm) {
+ dw += 0;
+ } else if (t && t->image_override && !t->bo) {
+ if (!r300->radeon.radeonScreen->kernel_mm)
+ dw += 2;
+ } else
+ dw += 4;
+ }
+ return dw;
}
-static void r300PrintStateAtom(r300ContextPtr r300, struct r300_state_atom *state)
+static void emit_tex_offsets(GLcontext *ctx, struct radeon_state_atom * atom)
{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ BATCH_LOCALS(&r300->radeon);
+ int numtmus = packet0_count(r300, r300->hw.tex.offset.cmd);
int i;
- int dwords = (*state->check) (r300, state);
-
- fprintf(stderr, " emit %s %d/%d\n", state->name, dwords,
- state->cmd_size);
- if (RADEON_DEBUG & DEBUG_VERBOSE) {
- for (i = 0; i < dwords; i++) {
- fprintf(stderr, " %s[%d]: %08x\n",
- state->name, i, state->cmd[i]);
+ for(i = 0; i < numtmus; ++i) {
+ radeonTexObj *t = r300->hw.textures[i];
+ if (t && !t->image_override) {
+ BEGIN_BATCH_NO_AUTOSTATE(4);
+ OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+ OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ END_BATCH();
+ } else if (!t) {
+ /* Texture unit hasn't a texture bound.
+ * We assign the current color buffer as a fakery to make
+ * KIL work on KMS (without it, the CS checker will complain).
+ */
+ if (r300->radeon.radeonScreen->kernel_mm) {
+ struct radeon_renderbuffer *rrb = radeon_get_colorbuffer(&r300->radeon);
+ if (rrb && rrb->bo) {
+ BEGIN_BATCH_NO_AUTOSTATE(4);
+ OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+ OUT_BATCH_RELOC(0, rrb->bo, 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ END_BATCH();
+ }
+ }
+ } else { /* override cases */
+ if (t->bo) {
+ BEGIN_BATCH_NO_AUTOSTATE(4);
+ OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+ OUT_BATCH_RELOC(t->tile_bits, t->bo, 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ END_BATCH();
+ } else if (!r300->radeon.radeonScreen->kernel_mm) {
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+ OUT_BATCH(t->override_offset);
+ END_BATCH();
+ } else {
+ /* Texture unit hasn't a texture bound nothings to do */
+ }
}
}
}
-/**
- * Emit all atoms with a dirty field equal to dirty.
- *
- * The caller must have ensured that there is enough space in the command
- * buffer.
- */
-static INLINE void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty)
+void r300_emit_scissor(GLcontext *ctx)
{
- struct r300_state_atom *atom;
- uint32_t *dest;
- int dwords;
-
- dest = r300->cmdbuf.cmd_buf + r300->cmdbuf.count_used;
-
- /* Emit WAIT */
- *dest = cmdwait(R300_WAIT_3D | R300_WAIT_3D_CLEAN);
- dest++;
- r300->cmdbuf.count_used++;
-
- /* Emit cache flush */
- *dest = cmdpacket0(R300_TX_INVALTAGS, 1);
- dest++;
- r300->cmdbuf.count_used++;
-
- *dest = R300_TX_FLUSH;
- dest++;
- r300->cmdbuf.count_used++;
-
- /* Emit END3D */
- *dest = cmdpacify();
- dest++;
- r300->cmdbuf.count_used++;
-
- /* Emit actual atoms */
-
- foreach(atom, &r300->hw.atomlist) {
- if ((atom->dirty || r300->hw.all_dirty) == dirty) {
- dwords = (*atom->check) (r300, atom);
- if (dwords) {
- if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {
- r300PrintStateAtom(r300, atom);
- }
- memcpy(dest, atom->cmd, dwords * 4);
- dest += dwords;
- r300->cmdbuf.count_used += dwords;
- atom->dirty = GL_FALSE;
- } else {
- if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {
- fprintf(stderr, " skip state %s\n",
- atom->name);
- }
- }
- }
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ BATCH_LOCALS(&r300->radeon);
+ unsigned x1, y1, x2, y2;
+ struct radeon_renderbuffer *rrb;
+
+ if (!r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+ return;
+ }
+ rrb = radeon_get_colorbuffer(&r300->radeon);
+ if (!rrb || !rrb->bo) {
+ fprintf(stderr, "no rrb\n");
+ return;
}
+ if (r300->radeon.state.scissor.enabled) {
+ x1 = r300->radeon.state.scissor.rect.x1;
+ y1 = r300->radeon.state.scissor.rect.y1;
+ x2 = r300->radeon.state.scissor.rect.x2;
+ y2 = r300->radeon.state.scissor.rect.y2;
+ } else {
+ x1 = 0;
+ y1 = 0;
+ x2 = rrb->base.Width - 1;
+ y2 = rrb->base.Height - 1;
+ }
+ if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
+ x1 += R300_SCISSORS_OFFSET;
+ y1 += R300_SCISSORS_OFFSET;
+ x2 += R300_SCISSORS_OFFSET;
+ y2 += R300_SCISSORS_OFFSET;
+ }
+ BEGIN_BATCH_NO_AUTOSTATE(3);
+ OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL, 2);
+ OUT_BATCH((x1 << R300_SCISSORS_X_SHIFT)|(y1 << R300_SCISSORS_Y_SHIFT));
+ OUT_BATCH((x2 << R300_SCISSORS_X_SHIFT)|(y2 << R300_SCISSORS_Y_SHIFT));
+ END_BATCH();
+}
+static int check_cb_offset(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ uint32_t dw = 6 + 3 + 16;
+ if (r300->radeon.radeonScreen->kernel_mm)
+ dw += 2;
+ if (!r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+ dw -= 3 + 16;
+ }
+ return dw;
}
-/**
- * Copy dirty hardware state atoms into the command buffer.
- *
- * We also copy out clean state if we're at the start of a buffer. That makes
- * it easy to recover from lost contexts.
- */
-void r300EmitState(r300ContextPtr r300)
+static void emit_cb_offset(GLcontext *ctx, struct radeon_state_atom * atom)
{
- if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_PRIMS))
- fprintf(stderr, "%s\n", __FUNCTION__);
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ BATCH_LOCALS(&r300->radeon);
+ struct radeon_renderbuffer *rrb;
+ uint32_t cbpitch;
+ uint32_t offset = r300->radeon.state.color.draw_offset;
+ uint32_t dw = 6;
+ int i;
- if (r300->cmdbuf.count_used && !r300->hw.is_dirty
- && !r300->hw.all_dirty)
+ rrb = radeon_get_colorbuffer(&r300->radeon);
+ if (!rrb || !rrb->bo) {
+ fprintf(stderr, "no rrb\n");
return;
+ }
- /* To avoid going across the entire set of states multiple times, just check
- * for enough space for the case of emitting all state, and inline the
- * r300AllocCmdBuf code here without all the checks.
- */
- r300EnsureCmdBufSpace(r300, r300->hw.max_state_size, __FUNCTION__);
+ if (RADEON_DEBUG & RADEON_STATE)
+ fprintf(stderr,"rrb is %p %d %dx%d\n", rrb, offset, rrb->base.Width, rrb->base.Height);
+ cbpitch = (rrb->pitch / rrb->cpp);
+ if (rrb->cpp == 4)
+ cbpitch |= R300_COLOR_FORMAT_ARGB8888;
+ else switch (rrb->base._ActualFormat) {
+ case GL_RGB5:
+ cbpitch |= R300_COLOR_FORMAT_RGB565;
+ break;
+ case GL_RGBA4:
+ cbpitch |= R300_COLOR_FORMAT_ARGB4444;
+ break;
+ case GL_RGB5_A1:
+ cbpitch |= R300_COLOR_FORMAT_ARGB1555;
+ break;
+ }
- if (!r300->cmdbuf.count_used) {
- if (RADEON_DEBUG & DEBUG_STATE)
- fprintf(stderr, "Begin reemit state\n");
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+ cbpitch |= R300_COLOR_TILE_ENABLE;
+
+ if (r300->radeon.radeonScreen->kernel_mm)
+ dw += 2;
+ BEGIN_BATCH_NO_AUTOSTATE(dw);
+ OUT_BATCH_REGSEQ(R300_RB3D_COLOROFFSET0, 1);
+ OUT_BATCH_RELOC(offset, rrb->bo, offset, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_BATCH_REGSEQ(R300_RB3D_COLORPITCH0, 1);
+ if (!r300->radeon.radeonScreen->kernel_mm)
+ OUT_BATCH(cbpitch);
+ else
+ OUT_BATCH_RELOC(cbpitch, rrb->bo, cbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ END_BATCH();
+ if (r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+ if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+ BEGIN_BATCH_NO_AUTOSTATE(3);
+ OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL, 2);
+ OUT_BATCH(0);
+ OUT_BATCH(((rrb->base.Width - 1) << R300_SCISSORS_X_SHIFT) |
+ ((rrb->base.Height - 1) << R300_SCISSORS_Y_SHIFT));
+ END_BATCH();
+ BEGIN_BATCH_NO_AUTOSTATE(16);
+ for (i = 0; i < 4; i++) {
+ OUT_BATCH_REGSEQ(R300_SC_CLIPRECT_TL_0 + (i * 8), 2);
+ OUT_BATCH((0 << R300_CLIPRECT_X_SHIFT) | (0 << R300_CLIPRECT_Y_SHIFT));
+ OUT_BATCH(((rrb->base.Width - 1) << R300_CLIPRECT_X_SHIFT) | ((rrb->base.Height - 1) << R300_CLIPRECT_Y_SHIFT));
+ }
+ OUT_BATCH_REGSEQ(R300_SC_CLIP_RULE, 1);
+ OUT_BATCH(0xAAAA);
+ OUT_BATCH_REGSEQ(R300_SC_SCREENDOOR, 1);
+ OUT_BATCH(0xffffff);
+ END_BATCH();
+ } else {
+ BEGIN_BATCH_NO_AUTOSTATE(3);
+ OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL, 2);
+ OUT_BATCH((R300_SCISSORS_OFFSET << R300_SCISSORS_X_SHIFT) |
+ (R300_SCISSORS_OFFSET << R300_SCISSORS_Y_SHIFT));
+ OUT_BATCH(((rrb->base.Width + R300_SCISSORS_OFFSET - 1) << R300_SCISSORS_X_SHIFT) |
+ ((rrb->base.Height + R300_SCISSORS_OFFSET - 1) << R300_SCISSORS_Y_SHIFT));
+ END_BATCH();
+ BEGIN_BATCH_NO_AUTOSTATE(16);
+ for (i = 0; i < 4; i++) {
+ OUT_BATCH_REGSEQ(R300_SC_CLIPRECT_TL_0 + (i * 8), 2);
+ OUT_BATCH((R300_SCISSORS_OFFSET << R300_CLIPRECT_X_SHIFT) | (R300_SCISSORS_OFFSET << R300_CLIPRECT_Y_SHIFT));
+ OUT_BATCH(((R300_SCISSORS_OFFSET + rrb->base.Width - 1) << R300_CLIPRECT_X_SHIFT) |
+ ((R300_SCISSORS_OFFSET + rrb->base.Height - 1) << R300_CLIPRECT_Y_SHIFT));
+ }
+ OUT_BATCH_REGSEQ(R300_SC_CLIP_RULE, 1);
+ OUT_BATCH(0xAAAA);
+ OUT_BATCH_REGSEQ(R300_SC_SCREENDOOR, 1);
+ OUT_BATCH(0xffffff);
+ END_BATCH();
+ }
+ }
+}
- r300EmitAtoms(r300, GL_FALSE);
- r300->cmdbuf.count_reemit = r300->cmdbuf.count_used;
- }
+static int check_zb_offset(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ uint32_t dw;
+ dw = 6;
+ if (r300->radeon.radeonScreen->kernel_mm)
+ dw += 2;
+ return dw;
+}
- if (RADEON_DEBUG & DEBUG_STATE)
- fprintf(stderr, "Begin dirty state\n");
+static void emit_zb_offset(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ BATCH_LOCALS(&r300->radeon);
+ struct radeon_renderbuffer *rrb;
+ uint32_t zbpitch;
+ uint32_t dw = atom->check(ctx, atom);
+
+ rrb = radeon_get_depthbuffer(&r300->radeon);
+ if (!rrb)
+ return;
- r300EmitAtoms(r300, GL_TRUE);
+ zbpitch = (rrb->pitch / rrb->cpp);
+ if (!r300->radeon.radeonScreen->kernel_mm) {
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE) {
+ zbpitch |= R300_DEPTHMACROTILE_ENABLE;
+ }
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MICRO_TILE){
+ zbpitch |= R300_DEPTHMICROTILE_TILED;
+ }
+ }
- assert(r300->cmdbuf.count_used < r300->cmdbuf.size);
+ BEGIN_BATCH_NO_AUTOSTATE(dw);
+ OUT_BATCH_REGSEQ(R300_ZB_DEPTHOFFSET, 1);
+ OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_BATCH_REGSEQ(R300_ZB_DEPTHPITCH, 1);
+ if (!r300->radeon.radeonScreen->kernel_mm)
+ OUT_BATCH(zbpitch);
+ else
+ OUT_BATCH_RELOC(cbpitch, rrb->bo, zbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ END_BATCH();
+}
- r300->hw.is_dirty = GL_FALSE;
- r300->hw.all_dirty = GL_FALSE;
+static void emit_zstencil_format(GLcontext *ctx, struct radeon_state_atom * atom)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ BATCH_LOCALS(&r300->radeon);
+ struct radeon_renderbuffer *rrb;
+ uint32_t format = 0;
+
+ rrb = radeon_get_depthbuffer(&r300->radeon);
+ if (!rrb)
+ format = 0;
+ else {
+ if (rrb->cpp == 2)
+ format = R300_DEPTHFORMAT_16BIT_INT_Z;
+ else if (rrb->cpp == 4)
+ format = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
+ }
+
+ BEGIN_BATCH_NO_AUTOSTATE(atom->cmd_size);
+ OUT_BATCH(atom->cmd[0]);
+ atom->cmd[1] &= ~0xf;
+ atom->cmd[1] |= format;
+ OUT_BATCH(atom->cmd[1]);
+ OUT_BATCH(atom->cmd[2]);
+ OUT_BATCH(atom->cmd[3]);
+ OUT_BATCH(atom->cmd[4]);
+ END_BATCH();
}
-#define packet0_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->packet0.count)
-#define vpu_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count)
-#define r500fp_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->r500fp.count)
+static int check_never(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ return 0;
+}
-static int check_always(r300ContextPtr r300, struct r300_state_atom *atom)
+static int check_always(GLcontext *ctx, struct radeon_state_atom *atom)
{
return atom->cmd_size;
}
-static int check_variable(r300ContextPtr r300, struct r300_state_atom *atom)
+static int check_variable(GLcontext *ctx, struct radeon_state_atom *atom)
{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
int cnt;
- cnt = packet0_count(atom->cmd);
+ if (atom->cmd[0] == CP_PACKET2) {
+ return 0;
+ }
+ cnt = packet0_count(r300, atom->cmd);
return cnt ? cnt + 1 : 0;
}
-static int check_vpu(r300ContextPtr r300, struct r300_state_atom *atom)
+int check_r500fp(GLcontext *ctx, struct radeon_state_atom *atom)
{
int cnt;
- cnt = vpu_count(atom->cmd);
- return cnt ? (cnt * 4) + 1 : 0;
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ int extra = 1;
+ cnt = r500fp_count(atom->cmd);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ extra = 3;
+
+ return cnt ? (cnt * 6) + extra : 0;
}
-static int check_r500fp(r300ContextPtr r300, struct r300_state_atom *atom)
+int check_r500fp_const(GLcontext *ctx, struct radeon_state_atom *atom)
{
int cnt;
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ int extra = 1;
cnt = r500fp_count(atom->cmd);
- return cnt ? (cnt * 6) + 1 : 0;
-}
+ if (r300->radeon.radeonScreen->kernel_mm)
+ extra = 3;
-static int check_r500fp_const(r300ContextPtr r300, struct r300_state_atom *atom)
-{
- int cnt;
cnt = r500fp_count(atom->cmd);
- return cnt ? (cnt * 4) + 1 : 0;
+ return cnt ? (cnt * 4) + extra : 0;
}
#define ALLOC_STATE( ATOM, CHK, SZ, IDX ) \
@@ -285,8 +473,8 @@ static int check_r500fp_const(r300ContextPtr r300, struct r300_state_atom *atom)
r300->hw.ATOM.idx = (IDX); \
r300->hw.ATOM.check = check_##CHK; \
r300->hw.ATOM.dirty = GL_FALSE; \
- r300->hw.max_state_size += (SZ); \
- insert_at_tail(&r300->hw.atomlist, &r300->hw.ATOM); \
+ r300->radeon.hw.max_state_size += (SZ); \
+ insert_at_tail(&r300->radeon.hw.atomlist, &r300->hw.ATOM); \
} while (0)
/**
* Allocate memory for the command buffer and initialize the state atom
@@ -294,251 +482,310 @@ static int check_r500fp_const(r300ContextPtr r300, struct r300_state_atom *atom)
*/
void r300InitCmdBuf(r300ContextPtr r300)
{
- int size, mtu;
- int has_tcl = 1;
+ int mtu;
+ int has_tcl;
int is_r500 = 0;
- int i;
- if (!(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
- has_tcl = 0;
+ has_tcl = r300->options.hw_tcl_enabled;
if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
is_r500 = 1;
- r300->hw.max_state_size = 2 + 2; /* reserve extra space for WAIT_IDLE and tex cache flush */
+ r300->radeon.hw.max_state_size = 2 + 2; /* reserve extra space for WAIT_IDLE and tex cache flush */
mtu = r300->radeon.glCtx->Const.MaxTextureUnits;
- if (RADEON_DEBUG & DEBUG_TEXTURE) {
+ if (RADEON_DEBUG & RADEON_TEXTURE) {
fprintf(stderr, "Using %d maximum texture units..\n", mtu);
}
/* Setup the atom linked list */
- make_empty_list(&r300->hw.atomlist);
- r300->hw.atomlist.name = "atom-list";
+ make_empty_list(&r300->radeon.hw.atomlist);
+ r300->radeon.hw.atomlist.name = "atom-list";
/* Initialize state atoms */
ALLOC_STATE(vpt, always, R300_VPT_CMDSIZE, 0);
- r300->hw.vpt.cmd[R300_VPT_CMD_0] = cmdpacket0(R300_SE_VPORT_XSCALE, 6);
+ r300->hw.vpt.cmd[R300_VPT_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_SE_VPORT_XSCALE, 6);
ALLOC_STATE(vap_cntl, always, R300_VAP_CNTL_SIZE, 0);
- r300->hw.vap_cntl.cmd[R300_VAP_CNTL_FLUSH] = cmdpacket0(R300_VAP_PVS_STATE_FLUSH_REG, 1);
+ r300->hw.vap_cntl.cmd[R300_VAP_CNTL_FLUSH] = cmdpacket0(r300->radeon.radeonScreen, R300_VAP_PVS_STATE_FLUSH_REG, 1);
r300->hw.vap_cntl.cmd[R300_VAP_CNTL_FLUSH_1] = 0;
- r300->hw.vap_cntl.cmd[R300_VAP_CNTL_CMD] = cmdpacket0(R300_VAP_CNTL, 1);
- if (is_r500) {
+ r300->hw.vap_cntl.cmd[R300_VAP_CNTL_CMD] = cmdpacket0(r300->radeon.radeonScreen, R300_VAP_CNTL, 1);
+ if (is_r500 && !r300->radeon.radeonScreen->kernel_mm) {
ALLOC_STATE(vap_index_offset, always, 2, 0);
- r300->hw.vap_index_offset.cmd[0] = cmdpacket0(R500_VAP_INDEX_OFFSET, 1);
+ r300->hw.vap_index_offset.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R500_VAP_INDEX_OFFSET, 1);
r300->hw.vap_index_offset.cmd[1] = 0;
}
ALLOC_STATE(vte, always, 3, 0);
- r300->hw.vte.cmd[0] = cmdpacket0(R300_SE_VTE_CNTL, 2);
+ r300->hw.vte.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_SE_VTE_CNTL, 2);
ALLOC_STATE(vap_vf_max_vtx_indx, always, 3, 0);
- r300->hw.vap_vf_max_vtx_indx.cmd[0] = cmdpacket0(R300_VAP_VF_MAX_VTX_INDX, 2);
+ r300->hw.vap_vf_max_vtx_indx.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_VAP_VF_MAX_VTX_INDX, 2);
ALLOC_STATE(vap_cntl_status, always, 2, 0);
- r300->hw.vap_cntl_status.cmd[0] = cmdpacket0(R300_VAP_CNTL_STATUS, 1);
+ r300->hw.vap_cntl_status.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_VAP_CNTL_STATUS, 1);
ALLOC_STATE(vir[0], variable, R300_VIR_CMDSIZE, 0);
r300->hw.vir[0].cmd[R300_VIR_CMD_0] =
- cmdpacket0(R300_VAP_PROG_STREAM_CNTL_0, 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_VAP_PROG_STREAM_CNTL_0, 1);
ALLOC_STATE(vir[1], variable, R300_VIR_CMDSIZE, 1);
r300->hw.vir[1].cmd[R300_VIR_CMD_0] =
- cmdpacket0(R300_VAP_PROG_STREAM_CNTL_EXT_0, 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_VAP_PROG_STREAM_CNTL_EXT_0, 1);
ALLOC_STATE(vic, always, R300_VIC_CMDSIZE, 0);
- r300->hw.vic.cmd[R300_VIC_CMD_0] = cmdpacket0(R300_VAP_VTX_STATE_CNTL, 2);
+ r300->hw.vic.cmd[R300_VIC_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_VAP_VTX_STATE_CNTL, 2);
ALLOC_STATE(vap_psc_sgn_norm_cntl, always, 2, 0);
- r300->hw.vap_psc_sgn_norm_cntl.cmd[0] = cmdpacket0(R300_VAP_PSC_SGN_NORM_CNTL, SGN_NORM_ZERO_CLAMP_MINUS_ONE);
+ r300->hw.vap_psc_sgn_norm_cntl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_VAP_PSC_SGN_NORM_CNTL, SGN_NORM_ZERO_CLAMP_MINUS_ONE);
if (has_tcl) {
ALLOC_STATE(vap_clip_cntl, always, 2, 0);
- r300->hw.vap_clip_cntl.cmd[0] = cmdpacket0(R300_VAP_CLIP_CNTL, 1);
+ r300->hw.vap_clip_cntl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_VAP_CLIP_CNTL, 1);
ALLOC_STATE(vap_clip, always, 5, 0);
- r300->hw.vap_clip.cmd[0] = cmdpacket0(R300_VAP_GB_VERT_CLIP_ADJ, 4);
+ r300->hw.vap_clip.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_VAP_GB_VERT_CLIP_ADJ, 4);
ALLOC_STATE(vap_pvs_vtx_timeout_reg, always, 2, 0);
- r300->hw.vap_pvs_vtx_timeout_reg.cmd[0] = cmdpacket0(VAP_PVS_VTX_TIMEOUT_REG, 1);
+ r300->hw.vap_pvs_vtx_timeout_reg.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, VAP_PVS_VTX_TIMEOUT_REG, 1);
}
ALLOC_STATE(vof, always, R300_VOF_CMDSIZE, 0);
r300->hw.vof.cmd[R300_VOF_CMD_0] =
- cmdpacket0(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+ cmdpacket0(r300->radeon.radeonScreen, R300_VAP_OUTPUT_VTX_FMT_0, 2);
if (has_tcl) {
ALLOC_STATE(pvs, always, R300_PVS_CMDSIZE, 0);
r300->hw.pvs.cmd[R300_PVS_CMD_0] =
- cmdpacket0(R300_VAP_PVS_CODE_CNTL_0, 3);
+ cmdpacket0(r300->radeon.radeonScreen, R300_VAP_PVS_CODE_CNTL_0, 3);
}
ALLOC_STATE(gb_enable, always, 2, 0);
- r300->hw.gb_enable.cmd[0] = cmdpacket0(R300_GB_ENABLE, 1);
- ALLOC_STATE(gb_misc, always, R300_GB_MISC_CMDSIZE, 0);
- r300->hw.gb_misc.cmd[0] = cmdpacket0(R300_GB_MSPOS0, 5);
+ r300->hw.gb_enable.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GB_ENABLE, 1);
+ if (!r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+ ALLOC_STATE(gb_misc, always, R300_GB_MISC_CMDSIZE, 0);
+ } else {
+ ALLOC_STATE(gb_misc, never, R300_GB_MISC_CMDSIZE, 0);
+ }
+ r300->hw.gb_misc.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GB_MSPOS0, 3);
+ ALLOC_STATE(gb_misc2, always, R300_GB_MISC2_CMDSIZE, 0);
+ r300->hw.gb_misc2.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, 0x401C, 2);
ALLOC_STATE(txe, always, R300_TXE_CMDSIZE, 0);
- r300->hw.txe.cmd[R300_TXE_CMD_0] = cmdpacket0(R300_TX_ENABLE, 1);
+ r300->hw.txe.cmd[R300_TXE_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_TX_ENABLE, 1);
ALLOC_STATE(ga_point_s0, always, 5, 0);
- r300->hw.ga_point_s0.cmd[0] = cmdpacket0(R300_GA_POINT_S0, 4);
+ r300->hw.ga_point_s0.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_POINT_S0, 4);
ALLOC_STATE(ga_triangle_stipple, always, 2, 0);
- r300->hw.ga_triangle_stipple.cmd[0] = cmdpacket0(R300_GA_TRIANGLE_STIPPLE, 1);
+ r300->hw.ga_triangle_stipple.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_TRIANGLE_STIPPLE, 1);
ALLOC_STATE(ps, always, R300_PS_CMDSIZE, 0);
- r300->hw.ps.cmd[0] = cmdpacket0(R300_GA_POINT_SIZE, 1);
+ r300->hw.ps.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_POINT_SIZE, 1);
ALLOC_STATE(ga_point_minmax, always, 4, 0);
- r300->hw.ga_point_minmax.cmd[0] = cmdpacket0(R300_GA_POINT_MINMAX, 3);
+ r300->hw.ga_point_minmax.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_POINT_MINMAX, 3);
ALLOC_STATE(lcntl, always, 2, 0);
- r300->hw.lcntl.cmd[0] = cmdpacket0(R300_GA_LINE_CNTL, 1);
+ r300->hw.lcntl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_LINE_CNTL, 1);
ALLOC_STATE(ga_line_stipple, always, 4, 0);
- r300->hw.ga_line_stipple.cmd[0] = cmdpacket0(R300_GA_LINE_STIPPLE_VALUE, 3);
- ALLOC_STATE(shade, always, 5, 0);
- r300->hw.shade.cmd[0] = cmdpacket0(R300_GA_ENHANCE, 4);
+ r300->hw.ga_line_stipple.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_LINE_STIPPLE_VALUE, 3);
+ if (!r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+ ALLOC_STATE(shade, always, 2, 0);
+ } else {
+ ALLOC_STATE(shade, never, 2, 0);
+ }
+ r300->hw.shade.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_ENHANCE, 1);
+ ALLOC_STATE(shade2, always, 4, 0);
+ r300->hw.shade2.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, 0x4278, 3);
ALLOC_STATE(polygon_mode, always, 4, 0);
- r300->hw.polygon_mode.cmd[0] = cmdpacket0(R300_GA_POLY_MODE, 3);
+ r300->hw.polygon_mode.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_POLY_MODE, 3);
ALLOC_STATE(fogp, always, 3, 0);
- r300->hw.fogp.cmd[0] = cmdpacket0(R300_GA_FOG_SCALE, 2);
+ r300->hw.fogp.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_GA_FOG_SCALE, 2);
ALLOC_STATE(zbias_cntl, always, 2, 0);
- r300->hw.zbias_cntl.cmd[0] = cmdpacket0(R300_SU_TEX_WRAP, 1);
+ r300->hw.zbias_cntl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_SU_TEX_WRAP, 1);
ALLOC_STATE(zbs, always, R300_ZBS_CMDSIZE, 0);
r300->hw.zbs.cmd[R300_ZBS_CMD_0] =
- cmdpacket0(R300_SU_POLY_OFFSET_FRONT_SCALE, 4);
+ cmdpacket0(r300->radeon.radeonScreen, R300_SU_POLY_OFFSET_FRONT_SCALE, 4);
ALLOC_STATE(occlusion_cntl, always, 2, 0);
- r300->hw.occlusion_cntl.cmd[0] = cmdpacket0(R300_SU_POLY_OFFSET_ENABLE, 1);
+ r300->hw.occlusion_cntl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_SU_POLY_OFFSET_ENABLE, 1);
ALLOC_STATE(cul, always, R300_CUL_CMDSIZE, 0);
- r300->hw.cul.cmd[R300_CUL_CMD_0] = cmdpacket0(R300_SU_CULL_MODE, 1);
+ r300->hw.cul.cmd[R300_CUL_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_SU_CULL_MODE, 1);
ALLOC_STATE(su_depth_scale, always, 3, 0);
- r300->hw.su_depth_scale.cmd[0] = cmdpacket0(R300_SU_DEPTH_SCALE, 2);
+ r300->hw.su_depth_scale.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_SU_DEPTH_SCALE, 2);
ALLOC_STATE(rc, always, R300_RC_CMDSIZE, 0);
- r300->hw.rc.cmd[R300_RC_CMD_0] = cmdpacket0(R300_RS_COUNT, 2);
+ r300->hw.rc.cmd[R300_RC_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_RS_COUNT, 2);
if (is_r500) {
- ALLOC_STATE(ri, always, R500_RI_CMDSIZE, 0);
- r300->hw.ri.cmd[R300_RI_CMD_0] = cmdpacket0(R500_RS_IP_0, 16);
- for (i = 0; i < 8; i++) {
- r300->hw.ri.cmd[R300_RI_CMD_0 + i +1] =
- (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_S_SHIFT) |
- (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_T_SHIFT) |
- (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_R_SHIFT) |
- (R500_RS_IP_PTR_K1 << R500_RS_IP_TEX_PTR_Q_SHIFT);
- }
+ ALLOC_STATE(ri, variable, R500_RI_CMDSIZE, 0);
+ r300->hw.ri.cmd[R300_RI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R500_RS_IP_0, 16);
ALLOC_STATE(rr, variable, R300_RR_CMDSIZE, 0);
- r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R500_RS_INST_0, 1);
+ r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R500_RS_INST_0, 1);
} else {
- ALLOC_STATE(ri, always, R300_RI_CMDSIZE, 0);
- r300->hw.ri.cmd[R300_RI_CMD_0] = cmdpacket0(R300_RS_IP_0, 8);
+ ALLOC_STATE(ri, variable, R300_RI_CMDSIZE, 0);
+ r300->hw.ri.cmd[R300_RI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_RS_IP_0, 8);
ALLOC_STATE(rr, variable, R300_RR_CMDSIZE, 0);
- r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R300_RS_INST_0, 1);
+ r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_RS_INST_0, 1);
}
ALLOC_STATE(sc_hyperz, always, 3, 0);
- r300->hw.sc_hyperz.cmd[0] = cmdpacket0(R300_SC_HYPERZ, 2);
+ r300->hw.sc_hyperz.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_SC_HYPERZ, 2);
ALLOC_STATE(sc_screendoor, always, 2, 0);
- r300->hw.sc_screendoor.cmd[0] = cmdpacket0(R300_SC_SCREENDOOR, 1);
+ r300->hw.sc_screendoor.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_SC_SCREENDOOR, 1);
ALLOC_STATE(us_out_fmt, always, 6, 0);
- r300->hw.us_out_fmt.cmd[0] = cmdpacket0(R300_US_OUT_FMT, 5);
+ r300->hw.us_out_fmt.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_US_OUT_FMT, 5);
if (is_r500) {
ALLOC_STATE(fp, always, R500_FP_CMDSIZE, 0);
- r300->hw.fp.cmd[R500_FP_CMD_0] = cmdpacket0(R500_US_CONFIG, 2);
+ r300->hw.fp.cmd[R500_FP_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R500_US_CONFIG, 2);
r300->hw.fp.cmd[R500_FP_CNTL] = R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO;
- r300->hw.fp.cmd[R500_FP_CMD_1] = cmdpacket0(R500_US_CODE_ADDR, 3);
- r300->hw.fp.cmd[R500_FP_CMD_2] = cmdpacket0(R500_US_FC_CTRL, 1);
+ r300->hw.fp.cmd[R500_FP_CMD_1] = cmdpacket0(r300->radeon.radeonScreen, R500_US_CODE_ADDR, 3);
+ r300->hw.fp.cmd[R500_FP_CMD_2] = cmdpacket0(r300->radeon.radeonScreen, R500_US_FC_CTRL, 1);
r300->hw.fp.cmd[R500_FP_FC_CNTL] = 0; /* FIXME when we add flow control */
ALLOC_STATE(r500fp, r500fp, R500_FPI_CMDSIZE, 0);
- r300->hw.r500fp.cmd[R300_FPI_CMD_0] = cmdr500fp(0, 0, 0, 0);
+ r300->hw.r500fp.cmd[R300_FPI_CMD_0] =
+ cmdr500fp(r300->radeon.radeonScreen, 0, 0, 0, 0);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ r300->hw.r500fp.emit = emit_r500fp;
+
ALLOC_STATE(r500fp_const, r500fp_const, R500_FPP_CMDSIZE, 0);
- r300->hw.r500fp_const.cmd[R300_FPI_CMD_0] = cmdr500fp(0, 0, 1, 0);
+ r300->hw.r500fp_const.cmd[R300_FPI_CMD_0] =
+ cmdr500fp(r300->radeon.radeonScreen, 0, 0, 1, 0);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ r300->hw.r500fp_const.emit = emit_r500fp;
} else {
ALLOC_STATE(fp, always, R300_FP_CMDSIZE, 0);
- r300->hw.fp.cmd[R300_FP_CMD_0] = cmdpacket0(R300_US_CONFIG, 3);
- r300->hw.fp.cmd[R300_FP_CMD_1] = cmdpacket0(R300_US_CODE_ADDR_0, 4);
+ r300->hw.fp.cmd[R300_FP_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_US_CONFIG, 3);
+ r300->hw.fp.cmd[R300_FP_CMD_1] = cmdpacket0(r300->radeon.radeonScreen, R300_US_CODE_ADDR_0, 4);
+
ALLOC_STATE(fpt, variable, R300_FPT_CMDSIZE, 0);
- r300->hw.fpt.cmd[R300_FPT_CMD_0] = cmdpacket0(R300_US_TEX_INST_0, 0);
+ r300->hw.fpt.cmd[R300_FPT_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_US_TEX_INST_0, 0);
ALLOC_STATE(fpi[0], variable, R300_FPI_CMDSIZE, 0);
- r300->hw.fpi[0].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_US_ALU_RGB_INST_0, 1);
+ r300->hw.fpi[0].cmd[R300_FPI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_US_ALU_RGB_INST_0, 1);
ALLOC_STATE(fpi[1], variable, R300_FPI_CMDSIZE, 1);
- r300->hw.fpi[1].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_US_ALU_RGB_ADDR_0, 1);
+ r300->hw.fpi[1].cmd[R300_FPI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_US_ALU_RGB_ADDR_0, 1);
ALLOC_STATE(fpi[2], variable, R300_FPI_CMDSIZE, 2);
- r300->hw.fpi[2].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_US_ALU_ALPHA_INST_0, 1);
+ r300->hw.fpi[2].cmd[R300_FPI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_US_ALU_ALPHA_INST_0, 1);
ALLOC_STATE(fpi[3], variable, R300_FPI_CMDSIZE, 3);
- r300->hw.fpi[3].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_US_ALU_ALPHA_ADDR_0, 1);
+ r300->hw.fpi[3].cmd[R300_FPI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_US_ALU_ALPHA_ADDR_0, 1);
ALLOC_STATE(fpp, variable, R300_FPP_CMDSIZE, 0);
- r300->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(R300_PFS_PARAM_0_X, 0);
+ r300->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_PFS_PARAM_0_X, 0);
}
ALLOC_STATE(fogs, always, R300_FOGS_CMDSIZE, 0);
- r300->hw.fogs.cmd[R300_FOGS_CMD_0] = cmdpacket0(R300_FG_FOG_BLEND, 1);
+ r300->hw.fogs.cmd[R300_FOGS_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_FG_FOG_BLEND, 1);
ALLOC_STATE(fogc, always, R300_FOGC_CMDSIZE, 0);
- r300->hw.fogc.cmd[R300_FOGC_CMD_0] = cmdpacket0(R300_FG_FOG_COLOR_R, 3);
+ r300->hw.fogc.cmd[R300_FOGC_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_FG_FOG_COLOR_R, 3);
ALLOC_STATE(at, always, R300_AT_CMDSIZE, 0);
- r300->hw.at.cmd[R300_AT_CMD_0] = cmdpacket0(R300_FG_ALPHA_FUNC, 2);
+ r300->hw.at.cmd[R300_AT_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_FG_ALPHA_FUNC, 2);
ALLOC_STATE(fg_depth_src, always, 2, 0);
- r300->hw.fg_depth_src.cmd[0] = cmdpacket0(R300_FG_DEPTH_SRC, 1);
+ r300->hw.fg_depth_src.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_FG_DEPTH_SRC, 1);
ALLOC_STATE(rb3d_cctl, always, 2, 0);
- r300->hw.rb3d_cctl.cmd[0] = cmdpacket0(R300_RB3D_CCTL, 1);
+ r300->hw.rb3d_cctl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_RB3D_CCTL, 1);
ALLOC_STATE(bld, always, R300_BLD_CMDSIZE, 0);
- r300->hw.bld.cmd[R300_BLD_CMD_0] = cmdpacket0(R300_RB3D_CBLEND, 2);
+ r300->hw.bld.cmd[R300_BLD_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_RB3D_CBLEND, 2);
ALLOC_STATE(cmk, always, R300_CMK_CMDSIZE, 0);
- r300->hw.cmk.cmd[R300_CMK_CMD_0] = cmdpacket0(RB3D_COLOR_CHANNEL_MASK, 1);
+ r300->hw.cmk.cmd[R300_CMK_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, RB3D_COLOR_CHANNEL_MASK, 1);
if (is_r500) {
ALLOC_STATE(blend_color, always, 3, 0);
- r300->hw.blend_color.cmd[0] = cmdpacket0(R500_RB3D_CONSTANT_COLOR_AR, 2);
+ r300->hw.blend_color.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R500_RB3D_CONSTANT_COLOR_AR, 2);
} else {
ALLOC_STATE(blend_color, always, 2, 0);
- r300->hw.blend_color.cmd[0] = cmdpacket0(R300_RB3D_BLEND_COLOR, 1);
+ r300->hw.blend_color.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_RB3D_BLEND_COLOR, 1);
}
ALLOC_STATE(rop, always, 2, 0);
- r300->hw.rop.cmd[0] = cmdpacket0(R300_RB3D_ROPCNTL, 1);
- ALLOC_STATE(cb, always, R300_CB_CMDSIZE, 0);
- r300->hw.cb.cmd[R300_CB_CMD_0] = cmdpacket0(R300_RB3D_COLOROFFSET0, 1);
- r300->hw.cb.cmd[R300_CB_CMD_1] = cmdpacket0(R300_RB3D_COLORPITCH0, 1);
+ r300->hw.rop.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_RB3D_ROPCNTL, 1);
+ ALLOC_STATE(cb, cb_offset, R300_CB_CMDSIZE, 0);
+ r300->hw.cb.emit = &emit_cb_offset;
ALLOC_STATE(rb3d_dither_ctl, always, 10, 0);
- r300->hw.rb3d_dither_ctl.cmd[0] = cmdpacket0(R300_RB3D_DITHER_CTL, 9);
+ r300->hw.rb3d_dither_ctl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_RB3D_DITHER_CTL, 9);
ALLOC_STATE(rb3d_aaresolve_ctl, always, 2, 0);
- r300->hw.rb3d_aaresolve_ctl.cmd[0] = cmdpacket0(R300_RB3D_AARESOLVE_CTL, 1);
- ALLOC_STATE(rb3d_discard_src_pixel_lte_threshold, always, 3, 0);
- r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[0] = cmdpacket0(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 2);
+ r300->hw.rb3d_aaresolve_ctl.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_RB3D_AARESOLVE_CTL, 1);
+ if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV350) {
+ ALLOC_STATE(rb3d_discard_src_pixel_lte_threshold, always, 3, 0);
+ } else {
+ ALLOC_STATE(rb3d_discard_src_pixel_lte_threshold, never, 3, 0);
+ }
+ r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 2);
ALLOC_STATE(zs, always, R300_ZS_CMDSIZE, 0);
r300->hw.zs.cmd[R300_ZS_CMD_0] =
- cmdpacket0(R300_ZB_CNTL, 3);
+ cmdpacket0(r300->radeon.radeonScreen, R300_ZB_CNTL, 3);
+ if (is_r500) {
+ if (r300->radeon.radeonScreen->kernel_mm)
+ ALLOC_STATE(zsb, always, R300_ZSB_CMDSIZE, 0);
+ else
+ ALLOC_STATE(zsb, never, R300_ZSB_CMDSIZE, 0);
+ r300->hw.zsb.cmd[R300_ZSB_CMD_0] =
+ cmdpacket0(r300->radeon.radeonScreen, R500_ZB_STENCILREFMASK_BF, 1);
+ }
+
ALLOC_STATE(zstencil_format, always, 5, 0);
r300->hw.zstencil_format.cmd[0] =
- cmdpacket0(R300_ZB_FORMAT, 4);
- ALLOC_STATE(zb, always, R300_ZB_CMDSIZE, 0);
- r300->hw.zb.cmd[R300_ZB_CMD_0] = cmdpacket0(R300_ZB_DEPTHOFFSET, 2);
+ cmdpacket0(r300->radeon.radeonScreen, R300_ZB_FORMAT, 4);
+ r300->hw.zstencil_format.emit = emit_zstencil_format;
+
+ ALLOC_STATE(zb, zb_offset, R300_ZB_CMDSIZE, 0);
+ r300->hw.zb.emit = emit_zb_offset;
ALLOC_STATE(zb_depthclearvalue, always, 2, 0);
- r300->hw.zb_depthclearvalue.cmd[0] = cmdpacket0(R300_ZB_DEPTHCLEARVALUE, 1);
- ALLOC_STATE(unk4F30, always, 3, 0);
- r300->hw.unk4F30.cmd[0] = cmdpacket0(0x4F30, 2);
+ r300->hw.zb_depthclearvalue.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_DEPTHCLEARVALUE, 1);
+ ALLOC_STATE(zb_zmask, always, 3, 0);
+ r300->hw.zb_zmask.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_ZMASK_OFFSET, 2);
ALLOC_STATE(zb_hiz_offset, always, 2, 0);
- r300->hw.zb_hiz_offset.cmd[0] = cmdpacket0(R300_ZB_HIZ_OFFSET, 1);
+ r300->hw.zb_hiz_offset.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_HIZ_OFFSET, 1);
ALLOC_STATE(zb_hiz_pitch, always, 2, 0);
- r300->hw.zb_hiz_pitch.cmd[0] = cmdpacket0(R300_ZB_HIZ_PITCH, 1);
+ r300->hw.zb_hiz_pitch.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_HIZ_PITCH, 1);
/* VPU only on TCL */
if (has_tcl) {
- int i;
+ int i;
+ if (r300->radeon.radeonScreen->kernel_mm) {
+ ALLOC_STATE(vap_flush, always, 10, 0);
+ /* flush processing vertices */
+ r300->hw.vap_flush.cmd[0] = cmdpacket0(r300->radeon.radeonScreen, R300_SC_SCREENDOOR, 1);
+ r300->hw.vap_flush.cmd[1] = 0;
+ r300->hw.vap_flush.cmd[2] = cmdpacket0(r300->radeon.radeonScreen, R300_RB3D_DSTCACHE_CTLSTAT, 1);
+ r300->hw.vap_flush.cmd[3] = R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D;
+ r300->hw.vap_flush.cmd[4] = cmdpacket0(r300->radeon.radeonScreen, RADEON_WAIT_UNTIL, 1);
+ r300->hw.vap_flush.cmd[5] = RADEON_WAIT_3D_IDLECLEAN;
+ r300->hw.vap_flush.cmd[6] = cmdpacket0(r300->radeon.radeonScreen, R300_SC_SCREENDOOR, 1);
+ r300->hw.vap_flush.cmd[7] = 0xffffff;
+ r300->hw.vap_flush.cmd[8] = cmdpacket0(r300->radeon.radeonScreen, R300_VAP_PVS_STATE_FLUSH_REG, 1);
+ r300->hw.vap_flush.cmd[9] = 0;
+ } else {
+ ALLOC_STATE(vap_flush, never, 10, 0);
+ }
+
+
ALLOC_STATE(vpi, vpu, R300_VPI_CMDSIZE, 0);
- r300->hw.vpi.cmd[R300_VPI_CMD_0] =
- cmdvpu(R300_PVS_CODE_START, 0);
+ r300->hw.vpi.cmd[0] =
+ cmdvpu(r300->radeon.radeonScreen, R300_PVS_CODE_START, 0);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ r300->hw.vpi.emit = emit_vpu;
if (is_r500) {
- ALLOC_STATE(vpp, vpu, R300_VPP_CMDSIZE, 0);
- r300->hw.vpp.cmd[R300_VPP_CMD_0] =
- cmdvpu(R500_PVS_CONST_START, 0);
-
- ALLOC_STATE(vps, vpu, R300_VPS_CMDSIZE, 0);
- r300->hw.vps.cmd[R300_VPS_CMD_0] =
- cmdvpu(R500_POINT_VPORT_SCALE_OFFSET, 1);
+ ALLOC_STATE(vpp, vpu, R300_VPP_CMDSIZE, 0);
+ r300->hw.vpp.cmd[0] =
+ cmdvpu(r300->radeon.radeonScreen, R500_PVS_CONST_START, 0);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ r300->hw.vpp.emit = emit_vpu;
+
+ ALLOC_STATE(vps, vpu, R300_VPS_CMDSIZE, 0);
+ r300->hw.vps.cmd[0] =
+ cmdvpu(r300->radeon.radeonScreen, R500_POINT_VPORT_SCALE_OFFSET, 1);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ r300->hw.vps.emit = emit_vpu;
for (i = 0; i < 6; i++) {
ALLOC_STATE(vpucp[i], vpu, R300_VPUCP_CMDSIZE, 0);
- r300->hw.vpucp[i].cmd[R300_VPUCP_CMD_0] =
- cmdvpu(R500_PVS_UCP_START + i, 1);
+ r300->hw.vpucp[i].cmd[0] =
+ cmdvpu(r300->radeon.radeonScreen,
+ R500_PVS_UCP_START + i, 1);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ r300->hw.vpucp[i].emit = emit_vpu;
}
} else {
- ALLOC_STATE(vpp, vpu, R300_VPP_CMDSIZE, 0);
- r300->hw.vpp.cmd[R300_VPP_CMD_0] =
- cmdvpu(R300_PVS_CONST_START, 0);
-
- ALLOC_STATE(vps, vpu, R300_VPS_CMDSIZE, 0);
- r300->hw.vps.cmd[R300_VPS_CMD_0] =
- cmdvpu(R300_POINT_VPORT_SCALE_OFFSET, 1);
+ ALLOC_STATE(vpp, vpu, R300_VPP_CMDSIZE, 0);
+ r300->hw.vpp.cmd[0] =
+ cmdvpu(r300->radeon.radeonScreen, R300_PVS_CONST_START, 0);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ r300->hw.vpp.emit = emit_vpu;
+
+ ALLOC_STATE(vps, vpu, R300_VPS_CMDSIZE, 0);
+ r300->hw.vps.cmd[0] =
+ cmdvpu(r300->radeon.radeonScreen, R300_POINT_VPORT_SCALE_OFFSET, 1);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ r300->hw.vps.emit = emit_vpu;
for (i = 0; i < 6; i++) {
ALLOC_STATE(vpucp[i], vpu, R300_VPUCP_CMDSIZE, 0);
- r300->hw.vpucp[i].cmd[R300_VPUCP_CMD_0] =
- cmdvpu(R300_PVS_UCP_START + i, 1);
+ r300->hw.vpucp[i].cmd[0] =
+ cmdvpu(r300->radeon.radeonScreen,
+ R300_PVS_UCP_START + i, 1);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ r300->hw.vpucp[i].emit = emit_vpu;
}
}
}
@@ -546,130 +793,48 @@ void r300InitCmdBuf(r300ContextPtr r300)
/* Textures */
ALLOC_STATE(tex.filter, variable, mtu + 1, 0);
r300->hw.tex.filter.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_FILTER0_0, 0);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_FILTER0_0, 0);
ALLOC_STATE(tex.filter_1, variable, mtu + 1, 0);
r300->hw.tex.filter_1.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_FILTER1_0, 0);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_FILTER1_0, 0);
ALLOC_STATE(tex.size, variable, mtu + 1, 0);
- r300->hw.tex.size.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_SIZE_0, 0);
+ r300->hw.tex.size.cmd[R300_TEX_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_TX_SIZE_0, 0);
ALLOC_STATE(tex.format, variable, mtu + 1, 0);
r300->hw.tex.format.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_FORMAT_0, 0);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_FORMAT_0, 0);
ALLOC_STATE(tex.pitch, variable, mtu + 1, 0);
- r300->hw.tex.pitch.cmd[R300_TEX_CMD_0] = cmdpacket0(R300_TX_FORMAT2_0, 0);
+ r300->hw.tex.pitch.cmd[R300_TEX_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_TX_FORMAT2_0, 0);
- ALLOC_STATE(tex.offset, variable, mtu + 1, 0);
+ ALLOC_STATE(tex.offset, tex_offsets, 1, 0);
r300->hw.tex.offset.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_OFFSET_0, 0);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_OFFSET_0, 0);
+ r300->hw.tex.offset.emit = &emit_tex_offsets;
ALLOC_STATE(tex.chroma_key, variable, mtu + 1, 0);
r300->hw.tex.chroma_key.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_CHROMA_KEY_0, 0);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_CHROMA_KEY_0, 0);
ALLOC_STATE(tex.border_color, variable, mtu + 1, 0);
r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_BORDER_COLOR_0, 0);
-
- r300->hw.is_dirty = GL_TRUE;
- r300->hw.all_dirty = GL_TRUE;
-
- /* Initialize command buffer */
- size =
- 256 * driQueryOptioni(&r300->radeon.optionCache,
- "command_buffer_size");
- if (size < 2 * r300->hw.max_state_size) {
- size = 2 * r300->hw.max_state_size + 65535;
- }
- if (size > 64 * 256)
- size = 64 * 256;
-
- if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA)) {
- fprintf(stderr, "sizeof(drm_r300_cmd_header_t)=%zd\n",
- sizeof(drm_r300_cmd_header_t));
- fprintf(stderr, "sizeof(drm_radeon_cmd_buffer_t)=%zd\n",
- sizeof(drm_radeon_cmd_buffer_t));
- fprintf(stderr,
- "Allocating %d bytes command buffer (max state is %d bytes)\n",
- size * 4, r300->hw.max_state_size * 4);
- }
-
- r300->cmdbuf.size = size;
- r300->cmdbuf.cmd_buf = (uint32_t *) CALLOC(size * 4);
- r300->cmdbuf.count_used = 0;
- r300->cmdbuf.count_reemit = 0;
-}
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_BORDER_COLOR_0, 0);
-/**
- * Destroy the command buffer and state atoms.
- */
-void r300DestroyCmdBuf(r300ContextPtr r300)
-{
- struct r300_state_atom *atom;
-
- FREE(r300->cmdbuf.cmd_buf);
-
- foreach(atom, &r300->hw.atomlist) {
- FREE(atom->cmd);
+ radeon_init_query_stateobj(&r300->radeon, R300_QUERYOBJ_CMDSIZE);
+ if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) {
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, RV530_FG_ZBREG_DEST, 1);
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_DATA_0] = RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL;
+ } else {
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_SU_REG_DEST, 1);
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_DATA_0] = R300_RASTER_PIPE_SELECT_ALL;
}
-}
-
-void r300EmitBlit(r300ContextPtr rmesa,
- GLuint color_fmt,
- GLuint src_pitch,
- GLuint src_offset,
- GLuint dst_pitch,
- GLuint dst_offset,
- GLint srcx, GLint srcy,
- GLint dstx, GLint dsty, GLuint w, GLuint h)
-{
- drm_r300_cmd_header_t *cmd;
-
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr,
- "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
- __FUNCTION__, src_pitch, src_offset, srcx, srcy,
- dst_pitch, dst_offset, dstx, dsty, w, h);
-
- assert((src_pitch & 63) == 0);
- assert((dst_pitch & 63) == 0);
- assert((src_offset & 1023) == 0);
- assert((dst_offset & 1023) == 0);
- assert(w < (1 << 16));
- assert(h < (1 << 16));
-
- cmd = (drm_r300_cmd_header_t *) r300AllocCmdBuf(rmesa, 8, __FUNCTION__);
-
- cmd[0].header.cmd_type = R300_CMD_PACKET3;
- cmd[0].header.pad0 = R300_CMD_PACKET3_RAW;
- cmd[1].u = R300_CP_CMD_BITBLT_MULTI | (5 << 16);
- cmd[2].u = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
- RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_NONE |
- (color_fmt << 8) |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_S |
- RADEON_DP_SRC_SOURCE_MEMORY |
- RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
-
- cmd[3].u = ((src_pitch / 64) << 22) | (src_offset >> 10);
- cmd[4].u = ((dst_pitch / 64) << 22) | (dst_offset >> 10);
- cmd[5].u = (srcx << 16) | srcy;
- cmd[6].u = (dstx << 16) | dsty; /* dst */
- cmd[7].u = (w << 16) | h;
-}
-
-void r300EmitWait(r300ContextPtr rmesa, GLuint flags)
-{
- drm_r300_cmd_header_t *cmd;
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_CMD_1] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_ZPASS_DATA, 1);
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_DATA_1] = 0;
- assert(!(flags & ~(R300_WAIT_2D | R300_WAIT_3D)));
+ r300->radeon.hw.is_dirty = GL_TRUE;
+ r300->radeon.hw.all_dirty = GL_TRUE;
- cmd = (drm_r300_cmd_header_t *) r300AllocCmdBuf(rmesa, 1, __FUNCTION__);
- cmd[0].u = 0;
- cmd[0].wait.cmd_type = R300_CMD_WAIT;
- cmd[0].wait.flags = flags;
+ rcommonInitCmdBuf(&r300->radeon);
}
diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.h b/src/mesa/drivers/dri/r300/r300_cmdbuf.h
index a8eaa580bd..1b703e518a 100644
--- a/src/mesa/drivers/dri/r300/r300_cmdbuf.h
+++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.h
@@ -38,79 +38,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_context.h"
-extern int r300FlushCmdBufLocked(r300ContextPtr r300, const char *caller);
-extern int r300FlushCmdBuf(r300ContextPtr r300, const char *caller);
-
-extern void r300EmitState(r300ContextPtr r300);
+#define CACHE_FLUSH_BUFSZ (4*2)
+#define PRE_EMIT_STATE_BUFSZ (2+2)
+#define AOS_BUFSZ(nr) (3+(nr >>1)*3 + (nr&1)*2 + (nr*2))
+#define FIREAOS_BUFSZ (3)
+#define SCISSORS_BUFSZ (3)
extern void r300InitCmdBuf(r300ContextPtr r300);
-extern void r300DestroyCmdBuf(r300ContextPtr r300);
-
-/**
- * Make sure that enough space is available in the command buffer
- * by flushing if necessary.
- *
- * \param dwords The number of dwords we need to be free on the command buffer
- */
-static INLINE void r300EnsureCmdBufSpace(r300ContextPtr r300,
- int dwords, const char *caller)
-{
- assert(dwords < r300->cmdbuf.size);
-
- if (r300->cmdbuf.count_used + dwords > r300->cmdbuf.size)
- r300FlushCmdBuf(r300, caller);
-}
-
-/**
- * Allocate the given number of dwords in the command buffer and return
- * a pointer to the allocated area.
- * When necessary, these functions cause a flush. r300AllocCmdBuf() also
- * causes state reemission after a flush. This is necessary to ensure
- * correct hardware state after an unlock.
- */
-static INLINE uint32_t *r300RawAllocCmdBuf(r300ContextPtr r300,
- int dwords, const char *caller)
-{
- uint32_t *ptr;
-
- r300EnsureCmdBufSpace(r300, dwords, caller);
-
- ptr = &r300->cmdbuf.cmd_buf[r300->cmdbuf.count_used];
- r300->cmdbuf.count_used += dwords;
- return ptr;
-}
-
-static INLINE uint32_t *r300AllocCmdBuf(r300ContextPtr r300,
- int dwords, const char *caller)
-{
- uint32_t *ptr;
-
- r300EnsureCmdBufSpace(r300, dwords, caller);
-
- if (!r300->cmdbuf.count_used) {
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr,
- "Reemit state after flush (from %s)\n", caller);
- r300EmitState(r300);
- }
-
- ptr = &r300->cmdbuf.cmd_buf[r300->cmdbuf.count_used];
- r300->cmdbuf.count_used += dwords;
- return ptr;
-}
+void r300_emit_scissor(GLcontext *ctx);
-extern void r300EmitBlit(r300ContextPtr rmesa,
- GLuint color_fmt,
- GLuint src_pitch,
- GLuint src_offset,
- GLuint dst_pitch,
- GLuint dst_offset,
- GLint srcx, GLint srcy,
- GLint dstx, GLint dsty, GLuint w, GLuint h);
+void emit_vpu(GLcontext *ctx, struct radeon_state_atom * atom);
+int check_vpu(GLcontext *ctx, struct radeon_state_atom *atom);
-extern void r300EmitWait(r300ContextPtr rmesa, GLuint flags);
-extern void r300EmitLOAD_VBPNTR(r300ContextPtr rmesa, int start);
-extern void r300EmitVertexShader(r300ContextPtr rmesa);
-extern void r300EmitPixelShader(r300ContextPtr rmesa);
+void emit_r500fp(GLcontext *ctx, struct radeon_state_atom * atom);
+int check_r500fp(GLcontext *ctx, struct radeon_state_atom *atom);
+int check_r500fp_const(GLcontext *ctx, struct radeon_state_atom *atom);
#endif /* __R300_CMDBUF_H__ */
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index 37436275e3..6fcf209af6 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -44,6 +44,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/extensions.h"
#include "main/state.h"
#include "main/bufferobj.h"
+#include "main/texobj.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
@@ -55,70 +56,68 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "drivers/common/driverfuncs.h"
-#include "radeon_ioctl.h"
-#include "radeon_span.h"
#include "r300_context.h"
+#include "radeon_context.h"
+#include "radeon_span.h"
#include "r300_cmdbuf.h"
#include "r300_state.h"
#include "r300_ioctl.h"
#include "r300_tex.h"
#include "r300_emit.h"
#include "r300_swtcl.h"
-
-#ifdef USER_BUFFERS
-#include "r300_mem.h"
-#endif
+#include "radeon_bocs_wrapper.h"
+#include "radeon_buffer_objects.h"
+#include "radeon_queryobj.h"
#include "vblank.h"
#include "utils.h"
#include "xmlpool.h" /* for symbolic values of enum-type options */
-/* hw_tcl_on derives from future_hw_tcl_on when its safe to change it. */
-int future_hw_tcl_on = 1;
-int hw_tcl_on = 1;
-
-#define need_GL_EXT_stencil_two_side
-#define need_GL_ARB_multisample
+#define need_GL_VERSION_2_0
+#define need_GL_ARB_occlusion_query
#define need_GL_ARB_point_parameters
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
#define need_GL_ARB_vertex_program
-#define need_GL_EXT_blend_minmax
-//#define need_GL_EXT_fog_coord
-#define need_GL_EXT_multi_draw_arrays
-#define need_GL_EXT_secondary_color
#define need_GL_EXT_blend_equation_separate
#define need_GL_EXT_blend_func_separate
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_framebuffer_blit
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_fog_coord
#define need_GL_EXT_gpu_program_parameters
+#define need_GL_EXT_provoking_vertex
+#define need_GL_EXT_secondary_color
+#define need_GL_EXT_stencil_two_side
+#define need_GL_ATI_separate_stencil
#define need_GL_NV_vertex_program
+
#include "extension_helper.h"
+
const struct dri_extension card_extensions[] = {
/* *INDENT-OFF* */
{"GL_ARB_depth_texture", NULL},
{"GL_ARB_fragment_program", NULL},
- {"GL_ARB_multisample", GL_ARB_multisample_functions},
+ {"GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions},
{"GL_ARB_multitexture", NULL},
{"GL_ARB_point_parameters", GL_ARB_point_parameters_functions},
{"GL_ARB_shadow", NULL},
{"GL_ARB_shadow_ambient", NULL},
{"GL_ARB_texture_border_clamp", NULL},
- {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions},
{"GL_ARB_texture_cube_map", NULL},
{"GL_ARB_texture_env_add", NULL},
{"GL_ARB_texture_env_combine", NULL},
{"GL_ARB_texture_env_crossbar", NULL},
{"GL_ARB_texture_env_dot3", NULL},
{"GL_ARB_texture_mirrored_repeat", NULL},
- {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
{"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
{"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions},
{"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions},
{"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
{"GL_EXT_blend_subtract", NULL},
-// {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
- {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
+ {"GL_EXT_packed_depth_stencil", NULL},
+ {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
{"GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions},
+ {"GL_EXT_provoking_vertex", GL_EXT_provoking_vertex_functions },
{"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
{"GL_EXT_shadow_funcs", NULL},
{"GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions},
@@ -130,6 +129,9 @@ const struct dri_extension card_extensions[] = {
{"GL_EXT_texture_lod_bias", NULL},
{"GL_EXT_texture_mirror_clamp", NULL},
{"GL_EXT_texture_rectangle", NULL},
+ {"GL_EXT_texture_sRGB", NULL},
+ {"GL_EXT_vertex_array_bgra", NULL},
+ {"GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions},
{"GL_ATI_texture_env_combine3", NULL},
{"GL_ATI_texture_mirror_once", NULL},
{"GL_MESA_pack_invert", NULL},
@@ -142,15 +144,22 @@ const struct dri_extension card_extensions[] = {
/* *INDENT-ON* */
};
-extern struct tnl_pipeline_stage _r300_render_stage;
-extern const struct tnl_pipeline_stage _r300_tcl_stage;
-static const struct tnl_pipeline_stage *r300_pipeline[] = {
+const struct dri_extension mm_extensions[] = {
+ { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
+ { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+ { NULL, NULL }
+};
- /* Try and go straight to t&l
- */
- &_r300_tcl_stage,
+/**
+ * The GL 2.0 functions are needed to make display lists work with
+ * functions added by GL_ATI_separate_stencil.
+ */
+const struct dri_extension gl_20_extension[] = {
+ {"GL_VERSION_2_0", GL_VERSION_2_0_functions },
+};
+static const struct tnl_pipeline_stage *r300_pipeline[] = {
/* Catch any t&l fallbacks
*/
&_tnl_vertex_transform_stage,
@@ -159,133 +168,187 @@ static const struct tnl_pipeline_stage *r300_pipeline[] = {
&_tnl_fog_coordinate_stage,
&_tnl_texgen_stage,
&_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
&_tnl_vertex_program_stage,
-
- /* Try again to go to tcl?
- * - no good for asymmetric-twoside (do with multipass)
- * - no good for asymmetric-unfilled (do with multipass)
- * - good for material
- * - good for texgen
- * - need to manipulate a bit of state
- *
- * - worth it/not worth it?
- */
-
- /* Else do them here.
- */
- &_r300_render_stage,
- &_tnl_render_stage, /* FALLBACK */
+ &_tnl_render_stage,
0,
};
-/* Create the device specific rendering context.
- */
-GLboolean r300CreateContext(const __GLcontextModes * glVisual,
- __DRIcontextPrivate * driContextPriv,
- void *sharedContextPrivate)
+static void r300_get_lock(radeonContextPtr rmesa)
{
- __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
- radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
- struct dd_function_table functions;
- r300ContextPtr r300;
- GLcontext *ctx;
- int tcl_mode, i;
-
- assert(glVisual);
- assert(driContextPriv);
- assert(screen);
+ drm_radeon_sarea_t *sarea = rmesa->sarea;
- /* Allocate the R300 context */
- r300 = (r300ContextPtr) CALLOC(sizeof(*r300));
- if (!r300)
- return GL_FALSE;
+ if (sarea->ctx_owner != rmesa->dri.hwContext) {
+ sarea->ctx_owner = rmesa->dri.hwContext;
+ if (!rmesa->radeonScreen->kernel_mm)
+ radeon_bo_legacy_texture_age(rmesa->radeonScreen->bom);
+ }
+}
- if (!(screen->chip_flags & RADEON_CHIPSET_TCL))
- hw_tcl_on = future_hw_tcl_on = 0;
+static void r300_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
+{
+ /* please flush pipe do all pending work */
+ radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+ R300_SC_SCREENDOOR, 1));
+ radeon_cs_write_dword(cs, 0x0);
+ radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+ R300_SC_SCREENDOOR, 1));
+ radeon_cs_write_dword(cs, 0x00FFFFFF);
+ radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+ R300_SC_HYPERZ, 1));
+ radeon_cs_write_dword(cs, 0x0);
+ radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+ R300_US_CONFIG, 1));
+ radeon_cs_write_dword(cs, 0x0);
+ radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+ R300_ZB_CNTL, 1));
+ radeon_cs_write_dword(cs, 0x0);
+ radeon_cs_write_dword(cs, cmdwait(rmesa->radeonScreen, R300_WAIT_3D));
+ radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+ R300_RB3D_DSTCACHE_CTLSTAT, 1));
+ radeon_cs_write_dword(cs, R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
+ radeon_cs_write_dword(cs, cmdpacket0(rmesa->radeonScreen,
+ R300_ZB_ZCACHE_CTLSTAT, 1));
+ radeon_cs_write_dword(cs, R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE);
+ radeon_cs_write_dword(cs, cmdwait(rmesa->radeonScreen,
+ R300_WAIT_3D | R300_WAIT_3D_CLEAN));
+}
- /* Parse configuration files.
- * Do this here so that initialMaxAnisotropy is set before we create
- * the default textures.
- */
- driParseConfigFiles(&r300->radeon.optionCache, &screen->optionCache,
- screen->driScreen->myNum, "r300");
- r300->initialMaxAnisotropy = driQueryOptionf(&r300->radeon.optionCache,
- "def_max_anisotropy");
+static void r300_vtbl_pre_emit_atoms(radeonContextPtr radeon)
+{
+ BATCH_LOCALS(radeon);
- /* Init default driver functions then plug in our R300-specific functions
- * (the texture functions are especially important)
- */
- _mesa_init_driver_functions(&functions);
- r300InitIoctlFuncs(&functions);
- r300InitStateFuncs(&functions);
- r300InitTextureFuncs(&functions);
- r300InitShaderFuncs(&functions);
+ cp_wait(radeon, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ OUT_BATCH_REGVAL(R300_TX_INVALTAGS, R300_TX_FLUSH);
+ END_BATCH();
+ end_3d(radeon);
+}
-#ifdef USER_BUFFERS
- r300_mem_init(r300);
-#endif
+static void r300_fallback(GLcontext *ctx, GLuint bit, GLboolean mode)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ if (mode)
+ r300->radeon.Fallback |= bit;
+ else
+ r300->radeon.Fallback &= ~bit;
+}
- if (!radeonInitContext(&r300->radeon, &functions,
- glVisual, driContextPriv,
- sharedContextPrivate)) {
- FREE(r300);
- return GL_FALSE;
+static void r300_emit_query_finish(radeonContextPtr radeon)
+{
+ r300ContextPtr r300 = (r300ContextPtr)radeon;
+ struct radeon_query_object *query = radeon->query.current;
+ BATCH_LOCALS(radeon);
+
+ BEGIN_BATCH_NO_AUTOSTATE(3 * 2 *r300->radeon.radeonScreen->num_gb_pipes + 2);
+ switch (r300->radeon.radeonScreen->num_gb_pipes) {
+ case 4:
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset+3*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+ case 3:
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_2);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset+2*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+ case 2:
+ if (r300->radeon.radeonScreen->chip_family <= CHIP_FAMILY_RV380) {
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
+ } else {
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_1);
+ }
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset+1*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+ case 1:
+ default:
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_0);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ break;
}
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL);
+ END_BATCH();
+ query->curr_offset += r300->radeon.radeonScreen->num_gb_pipes * sizeof(uint32_t);
+ assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+ query->emitted_begin = GL_FALSE;
+}
- /* Init r300 context data */
- r300->dma.buf0_address =
- r300->radeon.radeonScreen->buffers->list[0].address;
-
- (void)memset(r300->texture_heaps, 0, sizeof(r300->texture_heaps));
- make_empty_list(&r300->swapped);
-
- r300->nr_heaps = 1 /* screen->numTexHeaps */ ;
- assert(r300->nr_heaps < RADEON_NR_TEX_HEAPS);
- for (i = 0; i < r300->nr_heaps; i++) {
- /* *INDENT-OFF* */
- r300->texture_heaps[i] = driCreateTextureHeap(i, r300,
- screen->
- texSize[i], 12,
- RADEON_NR_TEX_REGIONS,
- (drmTextureRegionPtr)
- r300->radeon.sarea->
- tex_list[i],
- &r300->radeon.sarea->
- tex_age[i],
- &r300->swapped,
- sizeof
- (r300TexObj),
- (destroy_texture_object_t
- *)
- r300DestroyTexObj);
- /* *INDENT-ON* */
- }
- r300->texture_depth = driQueryOptioni(&r300->radeon.optionCache,
- "texture_depth");
- if (r300->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
- r300->texture_depth = (screen->cpp == 4) ?
- DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
-
- /* Set the maximum texture size small enough that we can guarentee that
- * all texture units can bind a maximal texture and have them both in
- * texturable memory at once.
- */
+static void rv530_emit_query_finish_single_z(radeonContextPtr radeon)
+{
+ BATCH_LOCALS(radeon);
+ struct radeon_query_object *query = radeon->query.current;
+
+ BEGIN_BATCH_NO_AUTOSTATE(8);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
+ END_BATCH();
+
+ query->curr_offset += sizeof(uint32_t);
+ assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+ query->emitted_begin = GL_FALSE;
+}
- ctx = r300->radeon.glCtx;
+static void rv530_emit_query_finish_double_z(radeonContextPtr radeon)
+{
+ BATCH_LOCALS(radeon);
+ struct radeon_query_object *query = radeon->query.current;
+
+ BEGIN_BATCH_NO_AUTOSTATE(14);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
+ END_BATCH();
+
+ query->curr_offset += 2 * sizeof(uint32_t);
+ assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+ query->emitted_begin = GL_FALSE;
+}
+
+static void r300_init_vtbl(radeonContextPtr radeon)
+{
+ radeon->vtbl.get_lock = r300_get_lock;
+ radeon->vtbl.update_viewport_offset = r300UpdateViewportOffset;
+ radeon->vtbl.emit_cs_header = r300_vtbl_emit_cs_header;
+ radeon->vtbl.swtcl_flush = r300_swtcl_flush;
+ radeon->vtbl.pre_emit_atoms = r300_vtbl_pre_emit_atoms;
+ radeon->vtbl.fallback = r300_fallback;
+ if (radeon->radeonScreen->chip_family == CHIP_FAMILY_RV530) {
+ if (radeon->radeonScreen->num_z_pipes == 2)
+ radeon->vtbl.emit_query_finish = rv530_emit_query_finish_double_z;
+ else
+ radeon->vtbl.emit_query_finish = rv530_emit_query_finish_single_z;
+ } else
+ radeon->vtbl.emit_query_finish = r300_emit_query_finish;
+}
+
+static void r300InitConstValues(GLcontext *ctx, radeonScreenPtr screen)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
ctx->Const.MaxTextureImageUnits =
driQueryOptioni(&r300->radeon.optionCache, "texture_image_units");
ctx->Const.MaxTextureCoordUnits =
driQueryOptioni(&r300->radeon.optionCache, "texture_coord_units");
- ctx->Const.MaxTextureUnits =
- MIN2(ctx->Const.MaxTextureImageUnits,
+ ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureImageUnits,
ctx->Const.MaxTextureCoordUnits);
+
ctx->Const.MaxTextureMaxAnisotropy = 16.0;
ctx->Const.MaxTextureLodBias = 16.0;
if (screen->chip_family >= CHIP_FAMILY_RV515) {
- ctx->Const.MaxTextureLevels = 13;
- ctx->Const.MaxTextureRectSize = 4096;
+ ctx->Const.MaxTextureLevels = 13;
+ ctx->Const.MaxCubeTextureLevels = 13;
+ ctx->Const.MaxTextureRectSize = 4096;
+ }
+ else {
+ ctx->Const.MaxTextureLevels = 12;
+ ctx->Const.MaxCubeTextureLevels = 12;
+ ctx->Const.MaxTextureRectSize = 2048;
}
ctx->Const.MinPointSize = 1.0;
@@ -298,253 +361,173 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
ctx->Const.MaxLineWidth = R300_LINESIZE_MAX;
ctx->Const.MaxLineWidthAA = R300_LINESIZE_MAX;
-#ifdef USER_BUFFERS
- /* Needs further modifications */
-#if 0
- ctx->Const.MaxArrayLockSize =
- ( /*512 */ RADEON_BUFFER_SIZE * 16 * 1024) / (4 * 4);
-#endif
-#endif
-
- /* Initialize the software rasterizer and helper modules.
- */
- _swrast_CreateContext(ctx);
- _vbo_CreateContext(ctx);
- _tnl_CreateContext(ctx);
- _swsetup_CreateContext(ctx);
- _swsetup_Wakeup(ctx);
- _ae_create_context(ctx);
-
- /* Install the customized pipeline:
- */
- _tnl_destroy_pipeline(ctx);
- _tnl_install_pipeline(ctx, r300_pipeline);
-
- /* Try and keep materials and vertices separate:
- */
-/* _tnl_isolate_materials(ctx, GL_TRUE); */
-
- /* Configure swrast and TNL to match hardware characteristics:
- */
- _swrast_allow_pixel_fog(ctx, GL_FALSE);
- _swrast_allow_vertex_fog(ctx, GL_TRUE);
- _tnl_allow_pixel_fog(ctx, GL_FALSE);
- _tnl_allow_vertex_fog(ctx, GL_TRUE);
+ ctx->Const.MaxDrawBuffers = 1;
/* currently bogus data */
- if (screen->chip_flags & RADEON_CHIPSET_TCL) {
- ctx->Const.VertexProgram.MaxInstructions = VSF_MAX_FRAGMENT_LENGTH / 4;
- ctx->Const.VertexProgram.MaxNativeInstructions =
- VSF_MAX_FRAGMENT_LENGTH / 4;
+ if (r300->options.hw_tcl_enabled) {
+ ctx->Const.VertexProgram.MaxNativeInstructions = VSF_MAX_FRAGMENT_LENGTH / 4;
+ ctx->Const.VertexProgram.MaxNativeAluInstructions = VSF_MAX_FRAGMENT_LENGTH / 4;
ctx->Const.VertexProgram.MaxNativeAttribs = 16; /* r420 */
- ctx->Const.VertexProgram.MaxTemps = 32;
- ctx->Const.VertexProgram.MaxNativeTemps =
- /*VSF_MAX_FRAGMENT_TEMPS */ 32;
+ ctx->Const.VertexProgram.MaxNativeTemps = 32;
ctx->Const.VertexProgram.MaxNativeParameters = 256; /* r420 */
ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
}
- ctx->Const.FragmentProgram.MaxNativeTemps = PFS_NUM_TEMP_REGS;
- ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* copy i915... */
- ctx->Const.FragmentProgram.MaxNativeParameters = PFS_NUM_CONST_REGS;
- ctx->Const.FragmentProgram.MaxNativeAluInstructions = PFS_MAX_ALU_INST;
- ctx->Const.FragmentProgram.MaxNativeTexInstructions = PFS_MAX_TEX_INST;
- ctx->Const.FragmentProgram.MaxNativeInstructions =
- PFS_MAX_ALU_INST + PFS_MAX_TEX_INST;
- ctx->Const.FragmentProgram.MaxNativeTexIndirections =
- PFS_MAX_TEX_INDIRECT;
- ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* and these are?? */
- ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
- ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+ if (screen->chip_family >= CHIP_FAMILY_RV515) {
+ ctx->Const.FragmentProgram.MaxNativeTemps = R500_PFS_NUM_TEMP_REGS;
+ ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* copy i915... */
+ ctx->Const.FragmentProgram.MaxNativeParameters = R500_PFS_NUM_CONST_REGS;
+ ctx->Const.FragmentProgram.MaxNativeAluInstructions = R500_PFS_MAX_INST;
+ ctx->Const.FragmentProgram.MaxNativeTexInstructions = R500_PFS_MAX_INST;
+ ctx->Const.FragmentProgram.MaxNativeInstructions = R500_PFS_MAX_INST;
+ ctx->Const.FragmentProgram.MaxNativeTexIndirections = R500_PFS_MAX_INST;
+ ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0;
+ } else {
+ ctx->Const.FragmentProgram.MaxNativeTemps = R300_PFS_NUM_TEMP_REGS;
+ ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* copy i915... */
+ ctx->Const.FragmentProgram.MaxNativeParameters = R300_PFS_NUM_CONST_REGS;
+ ctx->Const.FragmentProgram.MaxNativeAluInstructions = R300_PFS_MAX_ALU_INST;
+ ctx->Const.FragmentProgram.MaxNativeTexInstructions = R300_PFS_MAX_TEX_INST;
+ ctx->Const.FragmentProgram.MaxNativeInstructions = R300_PFS_MAX_ALU_INST + R300_PFS_MAX_TEX_INST;
+ ctx->Const.FragmentProgram.MaxNativeTexIndirections = R300_PFS_MAX_TEX_INDIRECT;
+ ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0;
+ }
- driInitExtensions(ctx, card_extensions, GL_TRUE);
+}
- if (driQueryOptionb
- (&r300->radeon.optionCache, "disable_stencil_two_side"))
- _mesa_disable_extension(ctx, "GL_EXT_stencil_two_side");
+static void r300ParseOptions(r300ContextPtr r300, radeonScreenPtr screen)
+{
+ struct r300_options options = { 0 };
- if (r300->radeon.glCtx->Mesa_DXTn
- && !driQueryOptionb(&r300->radeon.optionCache, "disable_s3tc")) {
- _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
- _mesa_enable_extension(ctx, "GL_S3_s3tc");
- } else
- if (driQueryOptionb(&r300->radeon.optionCache, "force_s3tc_enable"))
- {
- _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
- }
+ driParseConfigFiles(&r300->radeon.optionCache, &screen->optionCache,
+ screen->driScreen->myNum, "r300");
- r300->disable_lowimpact_fallback =
- driQueryOptionb(&r300->radeon.optionCache,
- "disable_lowimpact_fallback");
+ r300->radeon.initialMaxAnisotropy = driQueryOptionf(&r300->radeon.optionCache, "def_max_anisotropy");
- radeonInitSpanFuncs(ctx);
- r300InitCmdBuf(r300);
- r300InitState(r300);
- if (!(screen->chip_flags & RADEON_CHIPSET_TCL))
- r300InitSwtcl(ctx);
+ options.stencil_two_side_disabled = driQueryOptionb(&r300->radeon.optionCache, "disable_stencil_two_side");
+ options.s3tc_force_enabled = driQueryOptionb(&r300->radeon.optionCache, "force_s3tc_enable");
+ options.s3tc_force_disabled = driQueryOptionb(&r300->radeon.optionCache, "disable_s3tc");
- TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+ if (!(screen->chip_flags & RADEON_CHIPSET_TCL) || driQueryOptioni(&r300->radeon.optionCache, "tcl_mode") == DRI_CONF_TCL_SW)
+ options.hw_tcl_enabled = 0;
+ else
+ options.hw_tcl_enabled = 1;
- tcl_mode = driQueryOptioni(&r300->radeon.optionCache, "tcl_mode");
- if (driQueryOptionb(&r300->radeon.optionCache, "no_rast")) {
- fprintf(stderr, "disabling 3D acceleration\n");
-#if R200_MERGED
- FALLBACK(&r300->radeon, RADEON_FALLBACK_DISABLE, 1);
-#endif
- }
- if (tcl_mode == DRI_CONF_TCL_SW ||
- !(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
- if (r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
- r300->radeon.radeonScreen->chip_flags &=
- ~RADEON_CHIPSET_TCL;
- fprintf(stderr, "Disabling HW TCL support\n");
- }
- TCL_FALLBACK(r300->radeon.glCtx,
- RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
- }
+ options.conformance_mode = !driQueryOptionb(&r300->radeon.optionCache, "disable_lowimpact_fallback");
- return GL_TRUE;
+ r300->options = options;
}
-static void r300FreeGartAllocations(r300ContextPtr r300)
+static void r300InitGLExtensions(GLcontext *ctx)
{
- int i, ret, tries = 0, done_age, in_use = 0;
- drm_radeon_mem_free_t memfree;
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
- memfree.region = RADEON_MEM_REGION_GART;
+ driInitExtensions(ctx, card_extensions, GL_TRUE);
+ if (r300->radeon.radeonScreen->kernel_mm)
+ driInitExtensions(ctx, mm_extensions, GL_FALSE);
-#ifdef USER_BUFFERS
- for (i = r300->rmm->u_last; i > 0; i--) {
- if (r300->rmm->u_list[i].ptr == NULL) {
- continue;
- }
+ if (r300->options.stencil_two_side_disabled)
+ _mesa_disable_extension(ctx, "GL_EXT_stencil_two_side");
- /* check whether this buffer is still in use */
- if (r300->rmm->u_list[i].pending) {
- in_use++;
- }
+ if (r300->options.s3tc_force_enabled) {
+ _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+ _mesa_enable_extension(ctx, "GL_S3_s3tc");
+ } else if (r300->options.s3tc_force_disabled) {
+ _mesa_disable_extension(ctx, "GL_EXT_texture_compression_s3tc");
}
- /* Cannot flush/lock if no context exists. */
- if (in_use)
- r300FlushCmdBuf(r300, __FUNCTION__);
- done_age = radeonGetAge((radeonContextPtr) r300);
+ if (!r300->radeon.radeonScreen->drmSupportsOcclusionQueries) {
+ _mesa_disable_extension(ctx, "GL_ARB_occlusion_query");
+ }
+}
- for (i = r300->rmm->u_last; i > 0; i--) {
- if (r300->rmm->u_list[i].ptr == NULL) {
- continue;
- }
+/* Create the device specific rendering context.
+ */
+GLboolean r300CreateContext(const __GLcontextModes * glVisual,
+ __DRIcontextPrivate * driContextPriv,
+ void *sharedContextPrivate)
+{
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
+ struct dd_function_table functions;
+ r300ContextPtr r300;
+ GLcontext *ctx;
- /* check whether this buffer is still in use */
- if (!r300->rmm->u_list[i].pending) {
- continue;
- }
+ assert(glVisual);
+ assert(driContextPriv);
+ assert(screen);
- assert(r300->rmm->u_list[i].h_pending == 0);
+ r300 = (r300ContextPtr) CALLOC(sizeof(*r300));
+ if (!r300)
+ return GL_FALSE;
- tries = 0;
- while (r300->rmm->u_list[i].age > done_age && tries++ < 1000) {
- usleep(10);
- done_age = radeonGetAge((radeonContextPtr) r300);
- }
- if (tries >= 1000) {
- WARN_ONCE("Failed to idle region!");
- }
+ r300ParseOptions(r300, screen);
- memfree.region_offset = (char *)r300->rmm->u_list[i].ptr -
- (char *)r300->radeon.radeonScreen->gartTextures.map;
+ r300->radeon.radeonScreen = screen;
+ r300_init_vtbl(&r300->radeon);
- ret = drmCommandWrite(r300->radeon.radeonScreen->driScreen->fd,
- DRM_RADEON_FREE, &memfree,
- sizeof(memfree));
- if (ret) {
- fprintf(stderr, "Failed to free at %p\nret = %s\n",
- r300->rmm->u_list[i].ptr, strerror(-ret));
- } else {
- if (i == r300->rmm->u_last)
- r300->rmm->u_last--;
+ _mesa_init_driver_functions(&functions);
+ r300InitIoctlFuncs(&functions);
+ r300InitStateFuncs(&functions);
+ r300InitTextureFuncs(&functions);
+ r300InitShaderFuncs(&functions);
+ radeonInitQueryObjFunctions(&functions);
+ radeonInitBufferObjectFuncs(&functions);
- r300->rmm->u_list[i].pending = 0;
- r300->rmm->u_list[i].ptr = NULL;
- }
+ if (!radeonInitContext(&r300->radeon, &functions,
+ glVisual, driContextPriv,
+ sharedContextPrivate)) {
+ FREE(r300);
+ return GL_FALSE;
}
- r300->rmm->u_head = i;
-#endif /* USER_BUFFERS */
-}
-/* Destroy the device specific context.
- */
-void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
-{
- GET_CURRENT_CONTEXT(ctx);
- r300ContextPtr r300 = (r300ContextPtr) driContextPriv->driverPrivate;
- radeonContextPtr radeon = (radeonContextPtr) r300;
- radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
+ ctx = r300->radeon.glCtx;
- if (RADEON_DEBUG & DEBUG_DRI) {
- fprintf(stderr, "Destroying context !\n");
- }
+ r300->fallback = 0;
+ if (r300->options.hw_tcl_enabled)
+ ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
- /* check if we're deleting the currently bound context */
- if (&r300->radeon == current) {
- radeonFlush(r300->radeon.glCtx);
- _mesa_make_current(NULL, NULL, NULL);
- }
+ ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
- /* Free r300 context resources */
- assert(r300); /* should never be null */
-
- if (r300) {
- GLboolean release_texture_heaps;
-
- release_texture_heaps =
- (r300->radeon.glCtx->Shared->RefCount == 1);
- _swsetup_DestroyContext(r300->radeon.glCtx);
- _tnl_DestroyContext(r300->radeon.glCtx);
- _vbo_DestroyContext(r300->radeon.glCtx);
- _swrast_DestroyContext(r300->radeon.glCtx);
-
- if (r300->dma.current.buf) {
- r300ReleaseDmaRegion(r300, &r300->dma.current,
- __FUNCTION__);
-#ifndef USER_BUFFERS
- r300FlushCmdBuf(r300, __FUNCTION__);
-#endif
- }
- r300FreeGartAllocations(r300);
- r300DestroyCmdBuf(r300);
+ r300InitConstValues(ctx, screen);
- if (radeon->state.scissor.pClipRects) {
- FREE(radeon->state.scissor.pClipRects);
- radeon->state.scissor.pClipRects = NULL;
- }
+ _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
- if (release_texture_heaps) {
- /* This share group is about to go away, free our private
- * texture object data.
- */
- int i;
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext(ctx);
+ _vbo_CreateContext(ctx);
+ _tnl_CreateContext(ctx);
+ _swsetup_CreateContext(ctx);
+ _swsetup_Wakeup(ctx);
- for (i = 0; i < r300->nr_heaps; i++) {
- driDestroyTextureHeap(r300->texture_heaps[i]);
- r300->texture_heaps[i] = NULL;
- }
+ /* Install the customized pipeline:
+ */
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, r300_pipeline);
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
- assert(is_empty_list(&r300->swapped));
- }
+ /* Configure swrast and TNL to match hardware characteristics:
+ */
+ _swrast_allow_pixel_fog(ctx, GL_FALSE);
+ _swrast_allow_vertex_fog(ctx, GL_TRUE);
+ _tnl_allow_pixel_fog(ctx, GL_FALSE);
+ _tnl_allow_vertex_fog(ctx, GL_TRUE);
- radeonCleanupContext(&r300->radeon);
+ if (r300->options.hw_tcl_enabled) {
+ r300InitDraw(ctx);
+ } else {
+ r300InitSwtcl(ctx);
+ }
-#ifdef USER_BUFFERS
- /* the memory manager might be accessed when Mesa frees the shared
- * state, so don't destroy it earlier
- */
- r300_mem_destroy(r300);
-#endif
+ radeon_fbo_init(&r300->radeon);
+ radeonInitSpanFuncs( ctx );
+ r300InitCmdBuf(r300);
+ r300InitState(r300);
+ r300InitShaderFunctions(r300);
- /* free the option cache */
- driDestroyOptionCache(&r300->radeon.optionCache);
+ r300InitGLExtensions(ctx);
- FREE(r300);
- }
+ return GL_TRUE;
}
+
diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h
index c15e9fa300..518d5cdbf4 100644
--- a/src/mesa/drivers/dri/r300/r300_context.h
+++ b/src/mesa/drivers/dri/r300/r300_context.h
@@ -37,212 +37,29 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef __R300_CONTEXT_H__
#define __R300_CONTEXT_H__
-#include "tnl/t_vertex.h"
#include "drm.h"
#include "radeon_drm.h"
#include "dri_util.h"
-#include "texmem.h"
+#include "radeon_common.h"
-#include "main/macros.h"
#include "main/mtypes.h"
-#include "main/colormac.h"
-
-#define USER_BUFFERS
+#include "shader/prog_instruction.h"
+#include "compiler/radeon_code.h"
struct r300_context;
typedef struct r300_context r300ContextRec;
typedef struct r300_context *r300ContextPtr;
-#include "radeon_lock.h"
-#include "main/mm.h"
-
-/* From http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Variadic-Macros.html .
- I suppose we could inline this and use macro to fetch out __LINE__ and stuff in case we run into trouble
- with other compilers ... GLUE!
-*/
-#define WARN_ONCE(a, ...) { \
- static int warn##__LINE__=1; \
- if(warn##__LINE__){ \
- fprintf(stderr, "*********************************WARN_ONCE*********************************\n"); \
- fprintf(stderr, "File %s function %s line %d\n", \
- __FILE__, __FUNCTION__, __LINE__); \
- fprintf(stderr, a, ## __VA_ARGS__);\
- fprintf(stderr, "***************************************************************************\n"); \
- warn##__LINE__=0;\
- } \
- }
#include "r300_vertprog.h"
-#include "r500_fragprog.h"
-
-/**
- * This function takes a float and packs it into a uint32_t
- */
-static INLINE uint32_t r300PackFloat32(float fl)
-{
- union {
- float fl;
- uint32_t u;
- } u;
-
- u.fl = fl;
- return u.u;
-}
-
-/* This is probably wrong for some values, I need to test this
- * some more. Range checking would be a good idea also..
- *
- * But it works for most things. I'll fix it later if someone
- * else with a better clue doesn't
- */
-static INLINE uint32_t r300PackFloat24(float f)
-{
- float mantissa;
- int exponent;
- uint32_t float24 = 0;
-
- if (f == 0.0)
- return 0;
-
- mantissa = frexpf(f, &exponent);
-
- /* Handle -ve */
- if (mantissa < 0) {
- float24 |= (1 << 23);
- mantissa = mantissa * -1.0;
- }
- /* Handle exponent, bias of 63 */
- exponent += 62;
- float24 |= (exponent << 16);
- /* Kill 7 LSB of mantissa */
- float24 |= (r300PackFloat32(mantissa) & 0x7FFFFF) >> 7;
-
- return float24;
-}
-
-/************ DMA BUFFERS **************/
-
-/* Need refcounting on dma buffers:
- */
-struct r300_dma_buffer {
- int refcount; /**< the number of retained regions in buf */
- drmBufPtr buf;
- int id;
-};
-#undef GET_START
-#ifdef USER_BUFFERS
-#define GET_START(rvb) (r300GartOffsetFromVirtual(rmesa, (rvb)->address+(rvb)->start))
-#else
-#define GET_START(rvb) (rmesa->radeon.radeonScreen->gart_buffer_offset + \
- (rvb)->address - rmesa->dma.buf0_address + \
- (rvb)->start)
-#endif
-/* A retained region, eg vertices for indexed vertices.
- */
-struct r300_dma_region {
- struct r300_dma_buffer *buf;
- char *address; /* == buf->address */
- int start, end, ptr; /* offsets from start of buf */
-
- int aos_offset; /* address in GART memory */
- int aos_stride; /* distance between elements, in dwords */
- int aos_size; /* number of components (1-4) */
-};
-
-struct r300_dma {
- /* Active dma region. Allocations for vertices and retained
- * regions come from here. Also used for emitting random vertices,
- * these may be flushed by calling flush_current();
- */
- struct r300_dma_region current;
-
- void (*flush) (r300ContextPtr);
-
- char *buf0_address; /* start of buf[0], for index calcs */
-
- /* Number of "in-flight" DMA buffers, i.e. the number of buffers
- * for which a DISCARD command is currently queued in the command buffer.
- */
- GLuint nr_released_bufs;
-};
-
- /* Texture related */
-typedef struct r300_tex_obj r300TexObj, *r300TexObjPtr;
-
-/* Texture object in locally shared texture space.
- */
-struct r300_tex_obj {
- driTextureObject base;
-
- GLuint bufAddr; /* Offset to start of locally
- shared texture block */
-
- drm_radeon_tex_image_t image[6][RADEON_MAX_TEXTURE_LEVELS];
- /* Six, for the cube faces */
-
- GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
-
- GLuint pitch; /* this isn't sent to hardware just used in calculations */
- /* hardware register values */
- /* Note that R200 has 8 registers per texture and R300 only 7 */
- GLuint filter;
- GLuint filter_1;
- GLuint pitch_reg;
- GLuint size; /* npot only */
- GLuint format;
- GLuint offset; /* Image location in the card's address space.
- All cube faces follow. */
- GLuint unknown4;
- GLuint unknown5;
- /* end hardware registers */
-
- /* registers computed by r200 code - keep them here to
- compare against what is actually written.
-
- to be removed later.. */
- GLuint pp_border_color;
- GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */
- GLuint format_x;
-
- GLboolean border_fallback;
-
- GLuint tile_bits; /* hw texture tile bits used on this texture */
-};
-
-struct r300_texture_env_state {
- r300TexObjPtr texobj;
- GLenum format;
- GLenum envMode;
-};
/* The blit width for texture uploads
*/
#define R300_BLIT_WIDTH_BYTES 1024
#define R300_MAX_TEXTURE_UNITS 8
-struct r300_texture_state {
- struct r300_texture_env_state unit[R300_MAX_TEXTURE_UNITS];
- int tc_count; /* number of incoming texture coordinates from VAP */
-};
-/**
- * A block of hardware state.
- *
- * When check returns non-zero, the returned number of dwords must be
- * copied verbatim into the command buffer in order to update a state atom
- * when it is dirty.
- */
-struct r300_state_atom {
- struct r300_state_atom *next, *prev;
- const char *name; /* for debug */
- int cmd_size; /* maximum size in dwords */
- GLuint idx; /* index in an array (e.g. textures) */
- uint32_t *cmd;
- GLboolean dirty;
-
- int (*check) (r300ContextPtr, struct r300_state_atom * atom);
-};
#define R300_VPT_CMD_0 0
#define R300_VPT_XSCALE 1
@@ -284,9 +101,11 @@ struct r300_state_atom {
#define R300_GB_MISC_MSPOS_0 1
#define R300_GB_MISC_MSPOS_1 2
#define R300_GB_MISC_TILE_CONFIG 3
-#define R300_GB_MISC_SELECT 4
-#define R300_GB_MISC_AA_CONFIG 5
-#define R300_GB_MISC_CMDSIZE 6
+#define R300_GB_MISC_CMDSIZE 4
+#define R300_GB_MISC2_CMD_0 0
+#define R300_GB_MISC2_SELECT 1
+#define R300_GB_MISC2_AA_CONFIG 2
+#define R300_GB_MISC2_CMDSIZE 3
#define R300_TXE_CMD_0 0
#define R300_TXE_ENABLE 1
@@ -415,6 +234,10 @@ struct r300_state_atom {
#define R300_ZS_CNTL_2 3
#define R300_ZS_CMDSIZE 4
+#define R300_ZSB_CMD_0 0
+#define R300_ZSB_CNTL_0 1
+#define R300_ZSB_CMDSIZE 2
+
#define R300_ZB_CMD_0 0
#define R300_ZB_OFFSET 1
#define R300_ZB_PITCH 2
@@ -455,423 +278,181 @@ struct r300_state_atom {
#define R300_TEX_CMDSIZE (MAX_TEXTURE_UNITS+1)
*/
+#define R300_QUERYOBJ_CMD_0 0
+#define R300_QUERYOBJ_DATA_0 1
+#define R300_QUERYOBJ_CMD_1 2
+#define R300_QUERYOBJ_DATA_1 3
+#define R300_QUERYOBJ_CMDSIZE 4
+
/**
* Cache for hardware register state.
*/
struct r300_hw_state {
- struct r300_state_atom atomlist;
-
- GLboolean is_dirty;
- GLboolean all_dirty;
- int max_state_size; /* in dwords */
-
- struct r300_state_atom vpt; /* viewport (1D98) */
- struct r300_state_atom vap_cntl;
- struct r300_state_atom vap_index_offset; /* 0x208c r5xx only */
- struct r300_state_atom vof; /* VAP output format register 0x2090 */
- struct r300_state_atom vte; /* (20B0) */
- struct r300_state_atom vap_vf_max_vtx_indx; /* Maximum Vertex Indx Clamp (2134) */
- struct r300_state_atom vap_cntl_status;
- struct r300_state_atom vir[2]; /* vap input route (2150/21E0) */
- struct r300_state_atom vic; /* vap input control (2180) */
- struct r300_state_atom vap_psc_sgn_norm_cntl; /* Programmable Stream Control Signed Normalize Control (21DC) */
- struct r300_state_atom vap_clip_cntl;
- struct r300_state_atom vap_clip;
- struct r300_state_atom vap_pvs_vtx_timeout_reg; /* Vertex timeout register (2288) */
- struct r300_state_atom pvs; /* pvs_cntl (22D0) */
- struct r300_state_atom gb_enable; /* (4008) */
- struct r300_state_atom gb_misc; /* Multisampling position shifts ? (4010) */
- struct r300_state_atom ga_point_s0; /* S Texture Coordinate of Vertex 0 for Point texture stuffing (LLC) (4200) */
- struct r300_state_atom ga_triangle_stipple; /* (4214) */
- struct r300_state_atom ps; /* pointsize (421C) */
- struct r300_state_atom ga_point_minmax; /* (4230) */
- struct r300_state_atom lcntl; /* line control */
- struct r300_state_atom ga_line_stipple; /* (4260) */
- struct r300_state_atom shade;
- struct r300_state_atom polygon_mode;
- struct r300_state_atom fogp; /* fog parameters (4294) */
- struct r300_state_atom ga_soft_reset; /* (429C) */
- struct r300_state_atom zbias_cntl;
- struct r300_state_atom zbs; /* zbias (42A4) */
- struct r300_state_atom occlusion_cntl;
- struct r300_state_atom cul; /* cull cntl (42B8) */
- struct r300_state_atom su_depth_scale; /* (42C0) */
- struct r300_state_atom rc; /* rs control (4300) */
- struct r300_state_atom ri; /* rs interpolators (4310) */
- struct r300_state_atom rr; /* rs route (4330) */
- struct r300_state_atom sc_hyperz; /* (43A4) */
- struct r300_state_atom sc_screendoor; /* (43E8) */
- struct r300_state_atom fp; /* fragment program cntl + nodes (4600) */
- struct r300_state_atom fpt; /* texi - (4620) */
- struct r300_state_atom us_out_fmt; /* (46A4) */
- struct r300_state_atom r500fp; /* r500 fp instructions */
- struct r300_state_atom r500fp_const; /* r500 fp constants */
- struct r300_state_atom fpi[4]; /* fp instructions (46C0/47C0/48C0/49C0) */
- struct r300_state_atom fogs; /* fog state (4BC0) */
- struct r300_state_atom fogc; /* fog color (4BC8) */
- struct r300_state_atom at; /* alpha test (4BD4) */
- struct r300_state_atom fg_depth_src; /* (4BD8) */
- struct r300_state_atom fpp; /* 0x4C00 and following */
- struct r300_state_atom rb3d_cctl; /* (4E00) */
- struct r300_state_atom bld; /* blending (4E04) */
- struct r300_state_atom cmk; /* colormask (4E0C) */
- struct r300_state_atom blend_color; /* constant blend color */
- struct r300_state_atom rop; /* ropcntl */
- struct r300_state_atom cb; /* colorbuffer (4E28) */
- struct r300_state_atom rb3d_dither_ctl; /* (4E50) */
- struct r300_state_atom rb3d_aaresolve_ctl; /* (4E88) */
- struct r300_state_atom rb3d_discard_src_pixel_lte_threshold; /* (4E88) I saw it only written on RV350 hardware.. */
- struct r300_state_atom zs; /* zstencil control (4F00) */
- struct r300_state_atom zstencil_format;
- struct r300_state_atom zb; /* z buffer (4F20) */
- struct r300_state_atom zb_depthclearvalue; /* (4F28) */
- struct r300_state_atom unk4F30; /* (4F30) */
- struct r300_state_atom zb_hiz_offset; /* (4F44) */
- struct r300_state_atom zb_hiz_pitch; /* (4F54) */
-
- struct r300_state_atom vpi; /* vp instructions */
- struct r300_state_atom vpp; /* vp parameters */
- struct r300_state_atom vps; /* vertex point size (?) */
- struct r300_state_atom vpucp[6]; /* vp user clip plane - 6 */
+ struct radeon_state_atom vpt; /* viewport (1D98) */
+ struct radeon_state_atom vap_cntl;
+ struct radeon_state_atom vap_index_offset; /* 0x208c r5xx only */
+ struct radeon_state_atom vof; /* VAP output format register 0x2090 */
+ struct radeon_state_atom vte; /* (20B0) */
+ struct radeon_state_atom vap_vf_max_vtx_indx; /* Maximum Vertex Indx Clamp (2134) */
+ struct radeon_state_atom vap_cntl_status;
+ struct radeon_state_atom vir[2]; /* vap input route (2150/21E0) */
+ struct radeon_state_atom vic; /* vap input control (2180) */
+ struct radeon_state_atom vap_psc_sgn_norm_cntl; /* Programmable Stream Control Signed Normalize Control (21DC) */
+ struct radeon_state_atom vap_clip_cntl;
+ struct radeon_state_atom vap_clip;
+ struct radeon_state_atom vap_pvs_vtx_timeout_reg; /* Vertex timeout register (2288) */
+ struct radeon_state_atom pvs; /* pvs_cntl (22D0) */
+ struct radeon_state_atom gb_enable; /* (4008) */
+ struct radeon_state_atom gb_misc; /* Multisampling position shifts ? (4010) */
+ struct radeon_state_atom gb_misc2; /* Multisampling position shifts ? (4010) */
+ struct radeon_state_atom ga_point_s0; /* S Texture Coordinate of Vertex 0 for Point texture stuffing (LLC) (4200) */
+ struct radeon_state_atom ga_triangle_stipple; /* (4214) */
+ struct radeon_state_atom ps; /* pointsize (421C) */
+ struct radeon_state_atom ga_point_minmax; /* (4230) */
+ struct radeon_state_atom lcntl; /* line control */
+ struct radeon_state_atom ga_line_stipple; /* (4260) */
+ struct radeon_state_atom shade;
+ struct radeon_state_atom shade2;
+ struct radeon_state_atom polygon_mode;
+ struct radeon_state_atom fogp; /* fog parameters (4294) */
+ struct radeon_state_atom ga_soft_reset; /* (429C) */
+ struct radeon_state_atom zbias_cntl;
+ struct radeon_state_atom zbs; /* zbias (42A4) */
+ struct radeon_state_atom occlusion_cntl;
+ struct radeon_state_atom cul; /* cull cntl (42B8) */
+ struct radeon_state_atom su_depth_scale; /* (42C0) */
+ struct radeon_state_atom rc; /* rs control (4300) */
+ struct radeon_state_atom ri; /* rs interpolators (4310) */
+ struct radeon_state_atom rr; /* rs route (4330) */
+ struct radeon_state_atom sc_hyperz; /* (43A4) */
+ struct radeon_state_atom sc_screendoor; /* (43E8) */
+ struct radeon_state_atom fp; /* fragment program cntl + nodes (4600) */
+ struct radeon_state_atom fpt; /* texi - (4620) */
+ struct radeon_state_atom us_out_fmt; /* (46A4) */
+ struct radeon_state_atom r500fp; /* r500 fp instructions */
+ struct radeon_state_atom r500fp_const; /* r500 fp constants */
+ struct radeon_state_atom fpi[4]; /* fp instructions (46C0/47C0/48C0/49C0) */
+ struct radeon_state_atom fogs; /* fog state (4BC0) */
+ struct radeon_state_atom fogc; /* fog color (4BC8) */
+ struct radeon_state_atom at; /* alpha test (4BD4) */
+ struct radeon_state_atom fg_depth_src; /* (4BD8) */
+ struct radeon_state_atom fpp; /* 0x4C00 and following */
+ struct radeon_state_atom rb3d_cctl; /* (4E00) */
+ struct radeon_state_atom bld; /* blending (4E04) */
+ struct radeon_state_atom cmk; /* colormask (4E0C) */
+ struct radeon_state_atom blend_color; /* constant blend color */
+ struct radeon_state_atom rop; /* ropcntl */
+ struct radeon_state_atom cb; /* colorbuffer (4E28) */
+ struct radeon_state_atom rb3d_dither_ctl; /* (4E50) */
+ struct radeon_state_atom rb3d_aaresolve_ctl; /* (4E88) */
+ struct radeon_state_atom rb3d_discard_src_pixel_lte_threshold; /* (4E88) I saw it only written on RV350 hardware.. */
+ struct radeon_state_atom zs; /* zstencil control (4F00) */
+ struct radeon_state_atom zsb; /* zstencil bf */
+ struct radeon_state_atom zstencil_format;
+ struct radeon_state_atom zb; /* z buffer (4F20) */
+ struct radeon_state_atom zb_depthclearvalue; /* (4F28) */
+ struct radeon_state_atom zb_zmask; /* (4F30) */
+ struct radeon_state_atom zb_hiz_offset; /* (4F44) */
+ struct radeon_state_atom zb_hiz_pitch; /* (4F54) */
+
+ struct radeon_state_atom vap_flush;
+ struct radeon_state_atom vpi; /* vp instructions */
+ struct radeon_state_atom vpp; /* vp parameters */
+ struct radeon_state_atom vps; /* vertex point size (?) */
+ struct radeon_state_atom vpucp[6]; /* vp user clip plane - 6 */
/* 8 texture units */
/* the state is grouped by function and not by
texture unit. This makes single unit updates
really awkward - we are much better off
updating the whole thing at once */
struct {
- struct r300_state_atom filter;
- struct r300_state_atom filter_1;
- struct r300_state_atom size;
- struct r300_state_atom format;
- struct r300_state_atom pitch;
- struct r300_state_atom offset;
- struct r300_state_atom chroma_key;
- struct r300_state_atom border_color;
+ struct radeon_state_atom filter;
+ struct radeon_state_atom filter_1;
+ struct radeon_state_atom size;
+ struct radeon_state_atom format;
+ struct radeon_state_atom pitch;
+ struct radeon_state_atom offset;
+ struct radeon_state_atom chroma_key;
+ struct radeon_state_atom border_color;
} tex;
- struct r300_state_atom txe; /* tex enable (4104) */
-};
-
-/**
- * This structure holds the command buffer while it is being constructed.
- *
- * The first batch of commands in the buffer is always the state that needs
- * to be re-emitted when the context is lost. This batch can be skipped
- * otherwise.
- */
-struct r300_cmdbuf {
- int size; /* DWORDs allocated for buffer */
- uint32_t *cmd_buf;
- int count_used; /* DWORDs filled so far */
- int count_reemit; /* size of re-emission batch */
+ struct radeon_state_atom txe; /* tex enable (4104) */
+ radeonTexObj *textures[R300_MAX_TEXTURE_UNITS];
};
/**
* State cache
*/
-struct r300_depthbuffer_state {
- GLfloat scale;
-};
-
-struct r300_stencilbuffer_state {
- GLboolean hw_stencil;
-};
-
/* Vertex shader state */
-/* Perhaps more if we store programs in vmem? */
-/* drm_r300_cmd_header_t->vpu->count is unsigned char */
-#define VSF_MAX_FRAGMENT_LENGTH (255*4)
-
-/* Can be tested with colormat currently. */
-#define VSF_MAX_FRAGMENT_TEMPS (14)
-
-#define STATE_R300_WINDOW_DIMENSION (STATE_INTERNAL_DRIVER+0)
-#define STATE_R300_TEXRECT_FACTOR (STATE_INTERNAL_DRIVER+1)
-
-struct r300_vertex_shader_fragment {
- int length;
- union {
- GLuint d[VSF_MAX_FRAGMENT_LENGTH];
- float f[VSF_MAX_FRAGMENT_LENGTH];
- GLuint i[VSF_MAX_FRAGMENT_LENGTH];
- } body;
-};
-
-struct r300_vertex_shader_state {
- struct r300_vertex_shader_fragment program;
-};
-
-extern int hw_tcl_on;
-
#define COLOR_IS_RGBA
#define TAG(x) r300##x
#include "tnl_dd/t_dd_vertex.h"
#undef TAG
-//#define CURRENT_VERTEX_SHADER(ctx) (ctx->VertexProgram._Current)
-#define CURRENT_VERTEX_SHADER(ctx) (R300_CONTEXT(ctx)->selected_vp)
-
-/* Should but doesnt work */
-//#define CURRENT_VERTEX_SHADER(ctx) (R300_CONTEXT(ctx)->curr_vp)
-
-/* r300_vertex_shader_state and r300_vertex_program should probably be merged together someday.
- * Keeping them them seperate for now should ensure fixed pipeline keeps functioning properly.
- */
-
struct r300_vertex_program_key {
- GLuint InputsRead;
- GLuint OutputsWritten;
- GLuint OutputsAdded;
+ GLbitfield FpReads;
+ GLuint FogAttr;
+ GLuint WPosAttr;
};
struct r300_vertex_program {
+ struct gl_vertex_program *Base;
struct r300_vertex_program *next;
+
struct r300_vertex_program_key key;
- int translated;
-
- struct r300_vertex_shader_fragment program;
-
- int pos_end;
- int num_temporaries; /* Number of temp vars used by program */
- int wpos_idx;
- int inputs[VERT_ATTRIB_MAX];
- int outputs[VERT_RESULT_MAX];
- int native;
- int ref_count;
- int use_ref_count;
+ struct r300_vertex_program_code code;
+
+ GLboolean error;
};
struct r300_vertex_program_cont {
- struct gl_vertex_program mesa_program; /* Must be first */
- struct r300_vertex_shader_fragment params;
+ /* This is the unmodified vertex program mesa provided us with.
+ * We need to keep it unchanged because we may need to create another
+ * hw specific vertex program based on this.
+ */
+ struct gl_vertex_program mesa_program;
+ /* This is the list of hw specific vertex programs derived from mesa_program */
struct r300_vertex_program *progs;
};
-#define PFS_MAX_ALU_INST 64
-#define PFS_MAX_TEX_INST 64
-#define PFS_MAX_TEX_INDIRECT 4
-#define PFS_NUM_TEMP_REGS 32
-#define PFS_NUM_CONST_REGS 16
-
-struct r300_pfs_compile_state;
-
-
-/**
- * Stores state that influences the compilation of a fragment program.
- */
-struct r300_fragment_program_external_state {
- struct {
- /**
- * If the sampler is used as a shadow sampler,
- * this field is:
- * 0 - GL_LUMINANCE
- * 1 - GL_INTENSITY
- * 2 - GL_ALPHA
- * depending on the depth texture mode.
- */
- GLuint depth_texture_mode : 2;
-
- /**
- * If the sampler is used as a shadow sampler,
- * this field is (texture_compare_func - GL_NEVER).
- * [e.g. if compare function is GL_LEQUAL, this field is 3]
- *
- * Otherwise, this field is 0.
- */
- GLuint texture_compare_func : 3;
- } unit[16];
-};
-
-
-struct r300_fragment_program_node {
- int tex_offset; /**< first tex instruction */
- int tex_end; /**< last tex instruction, relative to tex_offset */
- int alu_offset; /**< first ALU instruction */
- int alu_end; /**< last ALU instruction, relative to alu_offset */
- int flags;
-};
-
-/**
- * Stores an R300 fragment program in its compiled-to-hardware form.
- */
-struct r300_fragment_program_code {
- struct {
- int length; /**< total # of texture instructions used */
- GLuint inst[PFS_MAX_TEX_INST];
- } tex;
-
- struct {
- int length; /**< total # of ALU instructions used */
- struct {
- GLuint inst0;
- GLuint inst1;
- GLuint inst2;
- GLuint inst3;
- } inst[PFS_MAX_ALU_INST];
- } alu;
-
- struct r300_fragment_program_node node[4];
- int cur_node;
- int first_node_has_tex;
-
- /**
- * Remember which program register a given hardware constant
- * belongs to.
- */
- struct prog_src_register constant[PFS_NUM_CONST_REGS];
- int const_nr;
-
- int max_temp_idx;
-};
/**
- * Store everything about a fragment program that is needed
- * to render with that program.
- */
+* Store everything about a fragment program that is needed
+* to render with that program.
+*/
struct r300_fragment_program {
- struct gl_fragment_program mesa_program;
-
- GLboolean translated;
GLboolean error;
-
+ struct r300_fragment_program *next;
struct r300_fragment_program_external_state state;
- struct r300_fragment_program_code code;
- GLboolean WritesDepth;
- GLuint optimization;
-};
-
-struct r500_pfs_compile_state;
+ struct rX00_fragment_program_code code;
+ GLbitfield InputsRead;
-struct r500_fragment_program_external_state {
- struct {
- /**
- * If the sampler is used as a shadow sampler,
- * this field is:
- * 0 - GL_LUMINANCE
- * 1 - GL_INTENSITY
- * 2 - GL_ALPHA
- * depending on the depth texture mode.
- */
- GLuint depth_texture_mode : 2;
-
- /**
- * If the sampler is used as a shadow sampler,
- * this field is (texture_compare_func - GL_NEVER).
- * [e.g. if compare function is GL_LEQUAL, this field is 3]
- *
- * Otherwise, this field is 0.
- */
- GLuint texture_compare_func : 3;
- } unit[16];
+ /* attribute that we are sending the WPOS in */
+ gl_frag_attrib wpos_attr;
+ /* attribute that we are sending the fog coordinate in */
+ gl_frag_attrib fog_attr;
};
-struct r500_fragment_program_code {
- struct {
- GLuint inst0;
- GLuint inst1;
- GLuint inst2;
- GLuint inst3;
- GLuint inst4;
- GLuint inst5;
- } inst[512];
-
- int inst_offset;
- int inst_end;
-
- /**
- * Remember which program register a given hardware constant
- * belongs to.
+struct r300_fragment_program_cont {
+ /* This is the unmodified fragment program mesa provided us with.
+ * We need to keep it unchanged because we may need to create another
+ * hw specific fragment program based on this.
*/
- struct prog_src_register constant[PFS_NUM_CONST_REGS];
- int const_nr;
-
- int max_temp_idx;
+ struct gl_fragment_program Base;
+ /* This is the list of hw specific fragment programs derived from Base */
+ struct r300_fragment_program *progs;
};
-struct r500_fragment_program {
- struct gl_fragment_program mesa_program;
-
- GLcontext *ctx;
- GLboolean translated;
- GLboolean error;
-
- struct r500_fragment_program_external_state state;
- struct r500_fragment_program_code code;
-
- GLboolean writes_depth;
-
- GLuint optimization;
-};
#define R300_MAX_AOS_ARRAYS 16
-#define REG_COORDS 0
-#define REG_COLOR0 1
-#define REG_TEX0 2
-
-struct r300_state {
- struct r300_depthbuffer_state depth;
- struct r300_texture_state texture;
- int sw_tcl_inputs[VERT_ATTRIB_MAX];
- struct r300_vertex_shader_state vertex_shader;
- struct r300_dma_region aos[R300_MAX_AOS_ARRAYS];
- int aos_count;
-
- GLuint *Elts;
- struct r300_dma_region elt_dma;
-
- struct r300_dma_region swtcl_dma;
- DECLARE_RENDERINPUTS(render_inputs_bitset); /* actual render inputs that R300 was configured for.
- They are the same as tnl->render_inputs for fixed pipeline */
-
- struct r300_stencilbuffer_state stencil;
-
-};
-
-#define R300_FALLBACK_NONE 0
-#define R300_FALLBACK_TCL 1
-#define R300_FALLBACK_RAST 2
/* r300_swtcl.c
*/
struct r300_swtcl_info {
- GLuint RenderIndex;
-
- /**
- * Size of a hardware vertex. This is calculated when \c ::vertex_attrs is
- * installed in the Mesa state vector.
- */
- GLuint vertex_size;
-
- /**
- * Attributes instructing the Mesa TCL pipeline where / how to put vertex
- * data in the hardware buffer.
- */
- struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
-
- /**
- * Number of elements of \c ::vertex_attrs that are actually used.
- */
- GLuint vertex_attr_count;
-
- /**
- * Cached pointer to the buffer where Mesa will store vertex data.
- */
- GLubyte *verts;
-
- /* Fallback rasterization functions
- */
- // r200_point_func draw_point;
- // r200_line_func draw_line;
- // r200_tri_func draw_tri;
-
- GLuint hw_primitive;
- GLenum render_primitive;
- GLuint numverts;
-
- /**
+ /*
* Offset of the 4UB color data within a hardware (swtcl) vertex.
*/
GLuint coloroffset;
@@ -880,13 +461,43 @@ struct r300_swtcl_info {
* Offset of the 3UB specular color data within a hardware (swtcl) vertex.
*/
GLuint specoffset;
+};
- /**
- * Should Mesa project vertex data or will the hardware do it?
- */
- GLboolean needproj;
+struct r300_vtable {
+ void (* SetupRSUnit)(GLcontext *ctx);
+ void (* SetupFragmentShaderTextures)(GLcontext *ctx, int *tmu_mappings);
+ void (* SetupPixelShader)(GLcontext *ctx);
+};
- struct r300_dma_region indexed_verts;
+struct r300_vertex_buffer {
+ struct vertex_attribute {
+ /* generic */
+ GLubyte element;
+ GLuint stride;
+ GLuint dwords;
+ GLubyte size; /* number of components */
+ GLboolean is_named_bo;
+ struct radeon_bo *bo;
+ GLint bo_offset;
+
+ /* hw specific */
+ uint32_t data_type:4;
+ uint32_t dst_loc:5;
+ uint32_t _signed:1;
+ uint32_t normalize:1;
+ uint32_t swizzle:12;
+ uint32_t write_mask:4;
+ } attribs[VERT_ATTRIB_MAX];
+
+ GLubyte num_attribs;
+};
+
+struct r300_index_buffer {
+ struct radeon_bo *bo;
+ int bo_offset;
+
+ GLboolean is_32bit;
+ GLuint count;
};
@@ -896,46 +507,33 @@ struct r300_swtcl_info {
struct r300_context {
struct radeon_context radeon; /* parent class, must be first */
+ struct r300_vtable vtbl;
+
struct r300_hw_state hw;
- struct r300_cmdbuf cmdbuf;
- struct r300_state state;
- struct gl_vertex_program *curr_vp;
+
struct r300_vertex_program *selected_vp;
+ struct r300_fragment_program *selected_fp;
/* Vertex buffers
*/
- struct r300_dma dma;
- GLboolean save_on_next_unlock;
- GLuint NewGLState;
-
- /* Texture object bookkeeping
- */
- unsigned nr_heaps;
- driTexHeap *texture_heaps[RADEON_NR_TEX_HEAPS];
- driTextureObject swapped;
- int texture_depth;
- float initialMaxAnisotropy;
-
- /* Clientdata textures;
- */
- GLuint prefer_gart_client_texturing;
-
-#ifdef USER_BUFFERS
- struct r300_memory_manager *rmm;
-#endif
-
GLvector4f dummy_attrib[_TNL_ATTRIB_MAX];
GLvector4f *temp_attrib[_TNL_ATTRIB_MAX];
- GLboolean disable_lowimpact_fallback;
+ struct r300_options {
+ uint32_t conformance_mode:1;
+ uint32_t hw_tcl_enabled:1;
+ uint32_t s3tc_force_enabled:1;
+ uint32_t s3tc_force_disabled:1;
+ uint32_t stencil_two_side_disabled:1;
+ } options;
- DECLARE_RENDERINPUTS(tnl_index_bitset); /* index of bits for last tnl_install_attrs */
struct r300_swtcl_info swtcl;
-};
+ struct r300_vertex_buffer vbuf;
+ struct r300_index_buffer ind_buf;
-struct r300_buffer_object {
- struct gl_buffer_object mesa_obj;
- int id;
+ uint32_t fallback;
+
+ DECLARE_RENDERINPUTS(render_inputs_bitset);
};
#define R300_CONTEXT(ctx) ((r300ContextPtr)(ctx->DriverCtx))
@@ -945,15 +543,13 @@ extern GLboolean r300CreateContext(const __GLcontextModes * glVisual,
__DRIcontextPrivate * driContextPriv,
void *sharedContextPrivate);
-extern void r300SelectVertexShader(r300ContextPtr r300);
extern void r300InitShaderFuncs(struct dd_function_table *functions);
-extern int r300VertexProgUpdateParams(GLcontext * ctx,
- struct r300_vertex_program_cont *vp,
- float *dst);
-
-#define RADEON_D_CAPTURE 0
-#define RADEON_D_PLAYBACK 1
-#define RADEON_D_PLAYBACK_RAW 2
-#define RADEON_D_T 3
+
+extern void r300InitShaderFunctions(r300ContextPtr r300);
+
+extern void r300InitDraw(GLcontext *ctx);
+
+#define r300PackFloat32 radeonPackFloat32
+#define r300PackFloat24 radeonPackFloat24
#endif /* __R300_CONTEXT_H__ */
diff --git a/src/mesa/drivers/dri/r300/r300_draw.c b/src/mesa/drivers/dri/r300/r300_draw.c
new file mode 100644
index 0000000000..e9968f9ffe
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_draw.c
@@ -0,0 +1,718 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Maciej Cencora
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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 THE AUTHOR(S) AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <stdlib.h>
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/state.h"
+#include "main/api_validate.h"
+#include "main/enums.h"
+#include "main/simple_list.h"
+
+#include "r300_reg.h"
+#include "r300_context.h"
+#include "r300_emit.h"
+#include "r300_render.h"
+#include "r300_state.h"
+#include "r300_tex.h"
+#include "r300_cmdbuf.h"
+
+#include "radeon_buffer_objects.h"
+#include "radeon_common_context.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_vp_build.h"
+#include "vbo/vbo_context.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+
+
+static int getTypeSize(GLenum type)
+{
+ switch (type) {
+ case GL_DOUBLE:
+ return sizeof(GLdouble);
+ case GL_FLOAT:
+ return sizeof(GLfloat);
+ case GL_INT:
+ return sizeof(GLint);
+ case GL_UNSIGNED_INT:
+ return sizeof(GLuint);
+ case GL_SHORT:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GL_BYTE:
+ return sizeof(GLbyte);
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static void r300FixupIndexBuffer(GLcontext *ctx, const struct _mesa_index_buffer *mesa_ind_buf)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ GLvoid *src_ptr;
+ GLuint *out;
+ int i;
+ GLboolean mapped_named_bo = GL_FALSE;
+
+ if (mesa_ind_buf->obj->Name && !mesa_ind_buf->obj->Pointer) {
+ ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY_ARB, mesa_ind_buf->obj);
+ mapped_named_bo = GL_TRUE;
+ assert(mesa_ind_buf->obj->Pointer != NULL);
+ }
+ src_ptr = ADD_POINTERS(mesa_ind_buf->obj->Pointer, mesa_ind_buf->ptr);
+
+ radeon_print(RADEON_FALLBACKS, RADEON_IMPORTANT,
+ "%s: Fixing index buffer format. type %d\n",
+ __func__, mesa_ind_buf->type);
+
+ if (mesa_ind_buf->type == GL_UNSIGNED_BYTE) {
+ GLuint size = sizeof(GLushort) * ((mesa_ind_buf->count + 1) & ~1);
+ GLubyte *in = (GLubyte *)src_ptr;
+
+ radeonAllocDmaRegion(&r300->radeon, &r300->ind_buf.bo, &r300->ind_buf.bo_offset, size, 4);
+
+ assert(r300->ind_buf.bo->ptr != NULL);
+ out = (GLuint *)ADD_POINTERS(r300->ind_buf.bo->ptr, r300->ind_buf.bo_offset);
+
+ for (i = 0; i + 1 < mesa_ind_buf->count; i += 2) {
+ *out++ = in[i] | in[i + 1] << 16;
+ }
+
+ if (i < mesa_ind_buf->count) {
+ *out++ = in[i];
+ }
+
+#if MESA_BIG_ENDIAN
+ } else { /* if (mesa_ind_buf->type == GL_UNSIGNED_SHORT) */
+ GLushort *in = (GLushort *)src_ptr;
+ GLuint size = sizeof(GLushort) * ((mesa_ind_buf->count + 1) & ~1);
+
+ radeonAllocDmaRegion(&r300->radeon, &r300->ind_buf.bo,
+ &r300->ind_buf.bo_offset, size, 4);
+
+ assert(r300->ind_buf.bo->ptr != NULL);
+ out = (GLuint *)ADD_POINTERS(r300->ind_buf.bo->ptr, r300->ind_buf.bo_offset);
+
+ for (i = 0; i + 1 < mesa_ind_buf->count; i += 2) {
+ *out++ = in[i] | in[i + 1] << 16;
+ }
+
+ if (i < mesa_ind_buf->count) {
+ *out++ = in[i];
+ }
+#endif
+ }
+
+ r300->ind_buf.is_32bit = GL_FALSE;
+ r300->ind_buf.count = mesa_ind_buf->count;
+
+ if (mapped_named_bo) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, mesa_ind_buf->obj);
+ }
+}
+
+
+static void r300SetupIndexBuffer(GLcontext *ctx, const struct _mesa_index_buffer *mesa_ind_buf)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+
+ if (!mesa_ind_buf) {
+ r300->ind_buf.bo = NULL;
+ return;
+ }
+ radeon_print(RADEON_RENDER, RADEON_TRACE, "%s\n", __func__);
+
+#if MESA_BIG_ENDIAN
+ if (mesa_ind_buf->type == GL_UNSIGNED_INT) {
+#else
+ if (mesa_ind_buf->type != GL_UNSIGNED_BYTE) {
+#endif
+ const GLvoid *src_ptr;
+ GLvoid *dst_ptr;
+ GLboolean mapped_named_bo = GL_FALSE;
+
+ if (mesa_ind_buf->obj->Name && !mesa_ind_buf->obj->Pointer) {
+ ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY_ARB, mesa_ind_buf->obj);
+ assert(mesa_ind_buf->obj->Pointer != NULL);
+ mapped_named_bo = GL_TRUE;
+ }
+
+ src_ptr = ADD_POINTERS(mesa_ind_buf->obj->Pointer, mesa_ind_buf->ptr);
+
+ const GLuint size = mesa_ind_buf->count * getTypeSize(mesa_ind_buf->type);
+
+ radeonAllocDmaRegion(&r300->radeon, &r300->ind_buf.bo, &r300->ind_buf.bo_offset, size, 4);
+
+ assert(r300->ind_buf.bo->ptr != NULL);
+ dst_ptr = ADD_POINTERS(r300->ind_buf.bo->ptr, r300->ind_buf.bo_offset);
+ _mesa_memcpy(dst_ptr, src_ptr, size);
+
+ r300->ind_buf.is_32bit = (mesa_ind_buf->type == GL_UNSIGNED_INT);
+ r300->ind_buf.count = mesa_ind_buf->count;
+
+ if (mapped_named_bo) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, mesa_ind_buf->obj);
+ }
+ } else {
+ r300FixupIndexBuffer(ctx, mesa_ind_buf);
+ }
+}
+
+#define CONVERT( TYPE, MACRO ) do { \
+ GLuint i, j, sz; \
+ sz = input->Size; \
+ if (input->Normalized) { \
+ for (i = 0; i < count; i++) { \
+ const TYPE *in = (TYPE *)src_ptr; \
+ for (j = 0; j < sz; j++) { \
+ *dst_ptr++ = MACRO(*in); \
+ in++; \
+ } \
+ src_ptr += stride; \
+ } \
+ } else { \
+ for (i = 0; i < count; i++) { \
+ const TYPE *in = (TYPE *)src_ptr; \
+ for (j = 0; j < sz; j++) { \
+ *dst_ptr++ = (GLfloat)(*in); \
+ in++; \
+ } \
+ src_ptr += stride; \
+ } \
+ } \
+} while (0)
+
+/**
+ * Convert attribute data type to float
+ * If the attribute uses named buffer object replace the bo with newly allocated bo
+ */
+static void r300ConvertAttrib(GLcontext *ctx, int count, const struct gl_client_array *input, struct vertex_attribute *attr)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ const GLvoid *src_ptr;
+ GLboolean mapped_named_bo = GL_FALSE;
+ GLfloat *dst_ptr;
+ GLuint stride;
+
+ stride = (input->StrideB == 0) ? getTypeSize(input->Type) * input->Size : input->StrideB;
+
+ /* Convert value for first element only */
+ if (input->StrideB == 0)
+ count = 1;
+
+ if (input->BufferObj->Name) {
+ if (!input->BufferObj->Pointer) {
+ ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY_ARB, input->BufferObj);
+ mapped_named_bo = GL_TRUE;
+ }
+
+ src_ptr = ADD_POINTERS(input->BufferObj->Pointer, input->Ptr);
+ } else {
+ src_ptr = input->Ptr;
+ }
+
+ radeonAllocDmaRegion(&r300->radeon, &attr->bo, &attr->bo_offset, sizeof(GLfloat) * input->Size * count, 32);
+ dst_ptr = (GLfloat *)ADD_POINTERS(attr->bo->ptr, attr->bo_offset);
+
+ radeon_print(RADEON_FALLBACKS, RADEON_IMPORTANT,
+ "%s: Converting vertex attributes, attribute data format %x,"
+ "stride %d, components %d\n"
+ , __FUNCTION__, input->Type
+ , stride, input->Size);
+
+ assert(src_ptr != NULL);
+
+ switch (input->Type) {
+ case GL_DOUBLE:
+ CONVERT(GLdouble, (GLfloat));
+ break;
+ case GL_UNSIGNED_INT:
+ CONVERT(GLuint, UINT_TO_FLOAT);
+ break;
+ case GL_INT:
+ CONVERT(GLint, INT_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CONVERT(GLushort, USHORT_TO_FLOAT);
+ break;
+ case GL_SHORT:
+ CONVERT(GLshort, SHORT_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_BYTE:
+ assert(input->Format != GL_BGRA);
+ CONVERT(GLubyte, UBYTE_TO_FLOAT);
+ break;
+ case GL_BYTE:
+ CONVERT(GLbyte, BYTE_TO_FLOAT);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (mapped_named_bo) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, input->BufferObj);
+ }
+}
+
+static void r300AlignDataToDword(GLcontext *ctx, const struct gl_client_array *input, int count, struct vertex_attribute *attr)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ const int dst_stride = (input->StrideB + 3) & ~3;
+ const int size = getTypeSize(input->Type) * input->Size * count;
+ GLboolean mapped_named_bo = GL_FALSE;
+
+ radeonAllocDmaRegion(&r300->radeon, &attr->bo, &attr->bo_offset, size, 32);
+
+ if (!input->BufferObj->Pointer) {
+ ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY_ARB, input->BufferObj);
+ mapped_named_bo = GL_TRUE;
+ }
+
+ radeon_print(RADEON_FALLBACKS, RADEON_IMPORTANT, "%s. Vertex alignment doesn't match hw requirements.\n", __func__);
+
+ {
+ GLvoid *src_ptr = ADD_POINTERS(input->BufferObj->Pointer, input->Ptr);
+ GLvoid *dst_ptr = ADD_POINTERS(attr->bo->ptr, attr->bo_offset);
+ int i;
+
+ for (i = 0; i < count; ++i) {
+ _mesa_memcpy(dst_ptr, src_ptr, input->StrideB);
+ src_ptr += input->StrideB;
+ dst_ptr += dst_stride;
+ }
+ }
+
+ if (mapped_named_bo) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, input->BufferObj);
+ }
+
+ attr->stride = dst_stride;
+}
+
+static void r300TranslateAttrib(GLcontext *ctx, GLuint attr, int count, const struct gl_client_array *input)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ struct r300_vertex_buffer *vbuf = &r300->vbuf;
+ struct vertex_attribute r300_attr;
+ GLenum type;
+ GLuint stride;
+
+ radeon_print(RADEON_RENDER, RADEON_TRACE, "%s\n", __func__);
+ stride = (input->StrideB == 0) ? getTypeSize(input->Type) * input->Size : input->StrideB;
+
+ if (input->Type == GL_DOUBLE || input->Type == GL_UNSIGNED_INT || input->Type == GL_INT ||
+#if MESA_BIG_ENDIAN
+ getTypeSize(input->Type) != 4 ||
+#endif
+ stride < 4) {
+
+ type = GL_FLOAT;
+
+ if (input->StrideB == 0) {
+ r300_attr.stride = 0;
+ } else {
+ r300_attr.stride = sizeof(GLfloat) * input->Size;
+ }
+ r300_attr.dwords = input->Size;
+ r300_attr.is_named_bo = GL_FALSE;
+ } else {
+ type = input->Type;
+ r300_attr.dwords = (getTypeSize(type) * input->Size + 3)/ 4;
+ if (!input->BufferObj->Name) {
+
+ if (input->StrideB == 0) {
+ r300_attr.stride = 0;
+ } else {
+ r300_attr.stride = (getTypeSize(type) * input->Size + 3) & ~3;
+ }
+
+ r300_attr.is_named_bo = GL_FALSE;
+ }
+ }
+
+ r300_attr.size = input->Size;
+ r300_attr.element = attr;
+ r300_attr.dst_loc = vbuf->num_attribs;
+
+ switch (type) {
+ case GL_FLOAT:
+ switch (input->Size) {
+ case 1: r300_attr.data_type = R300_DATA_TYPE_FLOAT_1; break;
+ case 2: r300_attr.data_type = R300_DATA_TYPE_FLOAT_2; break;
+ case 3: r300_attr.data_type = R300_DATA_TYPE_FLOAT_3; break;
+ case 4: r300_attr.data_type = R300_DATA_TYPE_FLOAT_4; break;
+ }
+ r300_attr._signed = 0;
+ r300_attr.normalize = 0;
+ break;
+ case GL_SHORT:
+ r300_attr._signed = 1;
+ r300_attr.normalize = input->Normalized;
+ switch (input->Size) {
+ case 1:
+ case 2:
+ r300_attr.data_type = R300_DATA_TYPE_SHORT_2;
+ break;
+ case 3:
+ case 4:
+ r300_attr.data_type = R300_DATA_TYPE_SHORT_4;
+ break;
+ }
+ break;
+ case GL_BYTE:
+ r300_attr._signed = 1;
+ r300_attr.normalize = input->Normalized;
+ r300_attr.data_type = R300_DATA_TYPE_BYTE;
+ break;
+ case GL_UNSIGNED_SHORT:
+ r300_attr._signed = 0;
+ r300_attr.normalize = input->Normalized;
+ switch (input->Size) {
+ case 1:
+ case 2:
+ r300_attr.data_type = R300_DATA_TYPE_SHORT_2;
+ break;
+ case 3:
+ case 4:
+ r300_attr.data_type = R300_DATA_TYPE_SHORT_4;
+ break;
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ r300_attr._signed = 0;
+ r300_attr.normalize = input->Normalized;
+ if (input->Format == GL_BGRA)
+ r300_attr.data_type = R300_DATA_TYPE_D3DCOLOR;
+ else
+ r300_attr.data_type = R300_DATA_TYPE_BYTE;
+ break;
+
+ default:
+ case GL_DOUBLE:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ assert(0);
+ break;
+ }
+
+ switch (input->Size) {
+ case 4:
+ r300_attr.swizzle = SWIZZLE_XYZW;
+ break;
+ case 3:
+ r300_attr.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
+ break;
+ case 2:
+ r300_attr.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE);
+ break;
+ case 1:
+ r300_attr.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ONE);
+ break;
+ }
+
+ r300_attr.write_mask = MASK_XYZW;
+
+ vbuf->attribs[vbuf->num_attribs] = r300_attr;
+ ++vbuf->num_attribs;
+}
+
+static void r300SetVertexFormat(GLcontext *ctx, const struct gl_client_array *arrays[], int count)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ struct r300_vertex_buffer *vbuf = &r300->vbuf;
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s\n", __func__);
+ {
+ int i, tmp;
+
+ tmp = r300->selected_vp->code.InputsRead;
+ i = 0;
+ vbuf->num_attribs = 0;
+ while (tmp) {
+ /* find first enabled bit */
+ while (!(tmp & 1)) {
+ tmp >>= 1;
+ ++i;
+ }
+
+ r300TranslateAttrib(ctx, i, count, arrays[i]);
+
+ tmp >>= 1;
+ ++i;
+ }
+ }
+
+ r300SwitchFallback(ctx, R300_FALLBACK_AOS_LIMIT, vbuf->num_attribs > R300_MAX_AOS_ARRAYS);
+ if (r300->fallback)
+ return;
+}
+
+static void r300AllocDmaRegions(GLcontext *ctx, const struct gl_client_array *input[], int count)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ struct r300_vertex_buffer *vbuf = &r300->vbuf;
+ GLuint stride;
+ int ret;
+ int i, index;
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE,
+ "%s: count %d num_attribs %d\n",
+ __func__, count, vbuf->num_attribs);
+
+ for (index = 0; index < vbuf->num_attribs; index++) {
+ struct radeon_aos *aos = &r300->radeon.tcl.aos[index];
+ i = vbuf->attribs[index].element;
+
+ stride = (input[i]->StrideB == 0) ? getTypeSize(input[i]->Type) * input[i]->Size : input[i]->StrideB;
+
+ if (input[i]->Type == GL_DOUBLE || input[i]->Type == GL_UNSIGNED_INT || input[i]->Type == GL_INT ||
+#if MESA_BIG_ENDIAN
+ getTypeSize(input[i]->Type) != 4 ||
+#endif
+ stride < 4) {
+
+ r300ConvertAttrib(ctx, count, input[i], &vbuf->attribs[index]);
+ } else {
+ if (input[i]->BufferObj->Name) {
+ if (stride % 4 != 0) {
+ assert(((intptr_t) input[i]->Ptr) % input[i]->StrideB == 0);
+ r300AlignDataToDword(ctx, input[i], count, &vbuf->attribs[index]);
+ vbuf->attribs[index].is_named_bo = GL_FALSE;
+ } else {
+ vbuf->attribs[index].stride = input[i]->StrideB;
+ vbuf->attribs[index].bo_offset = (intptr_t) input[i]->Ptr;
+ vbuf->attribs[index].bo = get_radeon_buffer_object(input[i]->BufferObj)->bo;
+ vbuf->attribs[index].is_named_bo = GL_TRUE;
+ }
+ } else {
+
+ int size;
+ int local_count = count;
+ uint32_t *dst;
+
+ if (input[i]->StrideB == 0) {
+ size = getTypeSize(input[i]->Type) * input[i]->Size;
+ local_count = 1;
+ } else {
+ size = getTypeSize(input[i]->Type) * input[i]->Size * local_count;
+ }
+
+ radeonAllocDmaRegion(&r300->radeon, &vbuf->attribs[index].bo, &vbuf->attribs[index].bo_offset, size, 32);
+ assert(vbuf->attribs[index].bo->ptr != NULL);
+ dst = (uint32_t *)ADD_POINTERS(vbuf->attribs[index].bo->ptr, vbuf->attribs[index].bo_offset);
+ switch (vbuf->attribs[index].dwords) {
+ case 1: radeonEmitVec4(dst, input[i]->Ptr, input[i]->StrideB, local_count); break;
+ case 2: radeonEmitVec8(dst, input[i]->Ptr, input[i]->StrideB, local_count); break;
+ case 3: radeonEmitVec12(dst, input[i]->Ptr, input[i]->StrideB, local_count); break;
+ case 4: radeonEmitVec16(dst, input[i]->Ptr, input[i]->StrideB, local_count); break;
+ default: assert(0); break;
+ }
+
+ }
+ }
+
+ aos->count = vbuf->attribs[index].stride == 0 ? 1 : count;
+ aos->stride = vbuf->attribs[index].stride / sizeof(float);
+ aos->components = vbuf->attribs[index].dwords;
+ aos->bo = vbuf->attribs[index].bo;
+ aos->offset = vbuf->attribs[index].bo_offset;
+
+ if (vbuf->attribs[index].is_named_bo) {
+ radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs, r300->vbuf.attribs[index].bo, RADEON_GEM_DOMAIN_GTT, 0);
+ }
+ }
+
+ r300->radeon.tcl.aos_count = vbuf->num_attribs;
+ ret = radeon_cs_space_check_with_bo(r300->radeon.cmdbuf.cs, first_elem(&r300->radeon.dma.reserved)->bo, RADEON_GEM_DOMAIN_GTT, 0);
+ r300SwitchFallback(ctx, R300_FALLBACK_INVALID_BUFFERS, ret);
+
+}
+
+static void r300FreeData(GLcontext *ctx)
+{
+ /* Need to zero tcl.aos[n].bo and tcl.elt_dma_bo
+ * to prevent double unref in radeonReleaseArrays
+ * called during context destroy
+ */
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s\n", __func__);
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ {
+ int i;
+
+ for (i = 0; i < r300->vbuf.num_attribs; i++) {
+ if (!r300->vbuf.attribs[i].is_named_bo) {
+ radeon_bo_unref(r300->vbuf.attribs[i].bo);
+ }
+ r300->radeon.tcl.aos[i].bo = NULL;
+ }
+ }
+
+ {
+ if (r300->ind_buf.bo != NULL) {
+ radeon_bo_unref(r300->ind_buf.bo);
+ }
+ }
+}
+
+static GLuint r300PredictTryDrawPrimsSize(GLcontext *ctx, GLuint nr_prims)
+{
+ struct r300_context *r300 = R300_CONTEXT(ctx);
+ struct r300_vertex_buffer *vbuf = &r300->vbuf;
+ GLboolean flushed;
+ GLuint dwords;
+ GLuint state_size;
+
+ dwords = 2*CACHE_FLUSH_BUFSZ;
+ dwords += PRE_EMIT_STATE_BUFSZ;
+ dwords += (AOS_BUFSZ(vbuf->num_attribs)
+ + SCISSORS_BUFSZ*2
+ + FIREAOS_BUFSZ )*nr_prims;
+
+ state_size = radeonCountStateEmitSize(&r300->radeon);
+ flushed = rcommonEnsureCmdBufSpace(&r300->radeon,
+ dwords + state_size,
+ __FUNCTION__);
+ if (flushed)
+ dwords += radeonCountStateEmitSize(&r300->radeon);
+ else
+ dwords += state_size;
+
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s: total prediction size is %d.\n", __FUNCTION__, dwords);
+ return dwords;
+}
+
+static GLboolean r300TryDrawPrims(GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index )
+{
+ struct r300_context *r300 = R300_CONTEXT(ctx);
+ GLuint i;
+
+ radeon_print(RADEON_RENDER, RADEON_NORMAL, "%s: %u (%d-%d) cs begin at %d\n",
+ __FUNCTION__, nr_prims, min_index, max_index, r300->radeon.cmdbuf.cs->cdw );
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (r300->options.hw_tcl_enabled)
+ _tnl_UpdateFixedFunctionProgram(ctx);
+
+ r300UpdateShaders(r300);
+
+ r300SwitchFallback(ctx, R300_FALLBACK_INVALID_BUFFERS, !r300ValidateBuffers(ctx));
+
+ r300SetVertexFormat(ctx, arrays, max_index + 1);
+
+ if (r300->fallback)
+ return GL_FALSE;
+
+ r300SetupVAP(ctx, r300->selected_vp->code.InputsRead, r300->selected_vp->code.OutputsWritten);
+
+ r300UpdateShaderStates(r300);
+
+ /* ensure we have the cmd buf space in advance to cover
+ * the state + DMA AOS pointers */
+ GLuint emit_end = r300PredictTryDrawPrimsSize(ctx, nr_prims)
+ + r300->radeon.cmdbuf.cs->cdw;
+
+ r300SetupIndexBuffer(ctx, ib);
+
+ r300AllocDmaRegions(ctx, arrays, max_index + 1);
+
+ if (r300->fallback)
+ return GL_FALSE;
+
+ r300EmitCacheFlush(r300);
+ radeonEmitState(&r300->radeon);
+
+ for (i = 0; i < nr_prims; ++i) {
+ r300RunRenderPrimitive(ctx, prim[i].start, prim[i].start + prim[i].count, prim[i].mode);
+ }
+
+ r300EmitCacheFlush(r300);
+
+ r300FreeData(ctx);
+
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s: %u (%d-%d) cs ending at %d\n",
+ __FUNCTION__, nr_prims, min_index, max_index, r300->radeon.cmdbuf.cs->cdw );
+
+ if (emit_end < r300->radeon.cmdbuf.cs->cdw)
+ WARN_ONCE("Rendering was %d commands larger than predicted size."
+ " We might overflow command buffer.\n", r300->radeon.cmdbuf.cs->cdw - emit_end);
+
+ return GL_TRUE;
+}
+
+static void r300DrawPrims(GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index)
+{
+ GLboolean retval;
+
+ /* This check should get folded into just the places that
+ * min/max index are really needed.
+ */
+ if (!index_bounds_valid) {
+ vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+ }
+
+ if (min_index) {
+ radeon_print(RADEON_FALLBACKS, RADEON_IMPORTANT,
+ "%s: Rebasing primitives. %p nr_prims %d min_index %u max_index %u\n",
+ __func__, prim, nr_prims, min_index, max_index);
+ vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index, max_index, r300DrawPrims );
+ return;
+ }
+
+ /* Make an attempt at drawing */
+ retval = r300TryDrawPrims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
+
+ /* If failed run tnl pipeline - it should take care of fallbacks */
+ if (!retval)
+ _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
+}
+
+void r300InitDraw(GLcontext *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+
+ vbo->draw_prims = r300DrawPrims;
+}
diff --git a/src/mesa/drivers/dri/r300/r300_emit.c b/src/mesa/drivers/dri/r300/r300_emit.c
index 80bd3389ae..07e6223087 100644
--- a/src/mesa/drivers/dri/r300/r300_emit.c
+++ b/src/mesa/drivers/dri/r300/r300_emit.c
@@ -31,6 +31,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* \file
*
* \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Maciej Cencora <m.cencora@gmail.com>
*/
#include "main/glheader.h"
@@ -46,222 +47,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "tnl/t_context.h"
#include "r300_context.h"
-#include "radeon_ioctl.h"
#include "r300_state.h"
#include "r300_emit.h"
#include "r300_ioctl.h"
-
-#ifdef USER_BUFFERS
-#include "r300_mem.h"
-#endif
-
-#if SWIZZLE_X != R300_INPUT_ROUTE_SELECT_X || \
- SWIZZLE_Y != R300_INPUT_ROUTE_SELECT_Y || \
- SWIZZLE_Z != R300_INPUT_ROUTE_SELECT_Z || \
- SWIZZLE_W != R300_INPUT_ROUTE_SELECT_W || \
- SWIZZLE_ZERO != R300_INPUT_ROUTE_SELECT_ZERO || \
- SWIZZLE_ONE != R300_INPUT_ROUTE_SELECT_ONE
-#error Cannot change these!
-#endif
-
-#define DEBUG_ALL DEBUG_VERTS
-
-#if defined(USE_X86_ASM)
-#define COPY_DWORDS( dst, src, nr ) \
-do { \
- int __tmp; \
- __asm__ __volatile__( "rep ; movsl" \
- : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
- : "0" (nr), \
- "D" ((long)dst), \
- "S" ((long)src) ); \
-} while (0)
-#else
-#define COPY_DWORDS( dst, src, nr ) \
-do { \
- int j; \
- for ( j = 0 ; j < nr ; j++ ) \
- dst[j] = ((int *)src)[j]; \
- dst += nr; \
-} while (0)
-#endif
-
-static void r300EmitVec4(GLcontext * ctx, struct r300_dma_region *rvb,
- GLvoid * data, int stride, int count)
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d out %p data %p\n",
- __FUNCTION__, count, stride, (void *)out, (void *)data);
-
- if (stride == 4)
- COPY_DWORDS(out, data, count);
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out++;
- data += stride;
- }
-}
-
-static void r300EmitVec8(GLcontext * ctx, struct r300_dma_region *rvb,
- GLvoid * data, int stride, int count)
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d out %p data %p\n",
- __FUNCTION__, count, stride, (void *)out, (void *)data);
-
- if (stride == 8)
- COPY_DWORDS(out, data, count * 2);
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out[1] = *(int *)(data + 4);
- out += 2;
- data += stride;
- }
-}
-
-static void r300EmitVec12(GLcontext * ctx, struct r300_dma_region *rvb,
- GLvoid * data, int stride, int count)
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d out %p data %p\n",
- __FUNCTION__, count, stride, (void *)out, (void *)data);
-
- if (stride == 12)
- COPY_DWORDS(out, data, count * 3);
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out[1] = *(int *)(data + 4);
- out[2] = *(int *)(data + 8);
- out += 3;
- data += stride;
- }
-}
-
-static void r300EmitVec16(GLcontext * ctx, struct r300_dma_region *rvb,
- GLvoid * data, int stride, int count)
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d out %p data %p\n",
- __FUNCTION__, count, stride, (void *)out, (void *)data);
-
- if (stride == 16)
- COPY_DWORDS(out, data, count * 4);
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out[1] = *(int *)(data + 4);
- out[2] = *(int *)(data + 8);
- out[3] = *(int *)(data + 12);
- out += 4;
- data += stride;
- }
-}
-
-static void r300EmitVec(GLcontext * ctx, struct r300_dma_region *rvb,
- GLvoid * data, int size, int stride, int count)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
-
- if (stride == 0) {
- r300AllocDmaRegion(rmesa, rvb, size * 4, 4);
- count = 1;
- rvb->aos_offset = GET_START(rvb);
- rvb->aos_stride = 0;
- } else {
- r300AllocDmaRegion(rmesa, rvb, size * count * 4, 4);
- rvb->aos_offset = GET_START(rvb);
- rvb->aos_stride = size;
- }
-
- switch (size) {
- case 1:
- r300EmitVec4(ctx, rvb, data, stride, count);
- break;
- case 2:
- r300EmitVec8(ctx, rvb, data, stride, count);
- break;
- case 3:
- r300EmitVec12(ctx, rvb, data, stride, count);
- break;
- case 4:
- r300EmitVec16(ctx, rvb, data, stride, count);
- break;
- default:
- assert(0);
- break;
- }
-}
-
-#define DW_SIZE(x) ((inputs[tab[(x)]] << R300_DST_VEC_LOC_SHIFT) | \
- (attribptr[tab[(x)]]->size - 1) << R300_DATA_TYPE_0_SHIFT)
-
-GLuint r300VAPInputRoute0(uint32_t * dst, GLvector4f ** attribptr,
- int *inputs, GLint * tab, GLuint nr)
-{
- GLuint i, dw;
-
- /* type, inputs, stop bit, size */
- for (i = 0; i < nr; i += 2) {
- /* make sure input is valid, would lockup the gpu */
- assert(inputs[tab[i]] != -1);
- dw = (R300_SIGNED | DW_SIZE(i));
- if (i + 1 == nr) {
- dw |= R300_LAST_VEC << R300_DATA_TYPE_0_SHIFT;
- } else {
- assert(inputs[tab[i + 1]] != -1);
- dw |= (R300_SIGNED |
- DW_SIZE(i + 1)) << R300_DATA_TYPE_1_SHIFT;
- if (i + 2 == nr) {
- dw |= R300_LAST_VEC << R300_DATA_TYPE_1_SHIFT;
- }
- }
- dst[i >> 1] = dw;
- }
-
- return (nr + 1) >> 1;
-}
-
-static GLuint r300VAPInputRoute1Swizzle(int swizzle[4])
-{
- return (swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) |
- (swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) |
- (swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) |
- (swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT);
-}
-
-GLuint r300VAPInputRoute1(uint32_t * dst, int swizzle[][4], GLuint nr)
-{
- GLuint i, dw;
-
- for (i = 0; i < nr; i += 2) {
- dw = (r300VAPInputRoute1Swizzle(swizzle[i]) |
- ((R300_WRITE_ENA_X | R300_WRITE_ENA_Y |
- R300_WRITE_ENA_Z | R300_WRITE_ENA_W) << R300_WRITE_ENA_SHIFT)) << R300_SWIZZLE0_SHIFT;
- if (i + 1 < nr) {
- dw |= (r300VAPInputRoute1Swizzle(swizzle[i + 1]) |
- ((R300_WRITE_ENA_X | R300_WRITE_ENA_Y |
- R300_WRITE_ENA_Z | R300_WRITE_ENA_W) << R300_WRITE_ENA_SHIFT)) << R300_SWIZZLE1_SHIFT;
- }
- dst[i >> 1] = dw;
- }
-
- return (nr + 1) >> 1;
-}
+#include "r300_render.h"
+#include "r300_swtcl.h"
GLuint r300VAPInputCntl0(GLcontext * ctx, GLuint InputsRead)
{
@@ -272,7 +62,6 @@ GLuint r300VAPInputCntl0(GLcontext * ctx, GLuint InputsRead)
GLuint r300VAPInputCntl1(GLcontext * ctx, GLuint InputsRead)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
GLuint i, vic_1 = 0;
if (InputsRead & (1 << VERT_ATTRIB_POS))
@@ -284,276 +73,68 @@ GLuint r300VAPInputCntl1(GLcontext * ctx, GLuint InputsRead)
if (InputsRead & (1 << VERT_ATTRIB_COLOR0))
vic_1 |= R300_INPUT_CNTL_COLOR;
- rmesa->state.texture.tc_count = 0;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
if (InputsRead & (1 << (VERT_ATTRIB_TEX0 + i))) {
- rmesa->state.texture.tc_count++;
vic_1 |= R300_INPUT_CNTL_TC0 << i;
}
return vic_1;
}
-GLuint r300VAPOutputCntl0(GLcontext * ctx, GLuint OutputsWritten)
+GLuint r300VAPOutputCntl0(GLcontext * ctx, GLuint vp_writes)
{
GLuint ret = 0;
- if (OutputsWritten & (1 << VERT_RESULT_HPOS))
+ if (vp_writes & (1 << VERT_RESULT_HPOS))
ret |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
- if (OutputsWritten & (1 << VERT_RESULT_COL0))
+ if (vp_writes & (1 << VERT_RESULT_COL0))
ret |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT;
- if (OutputsWritten & (1 << VERT_RESULT_COL1))
+ if (vp_writes & (1 << VERT_RESULT_COL1))
ret |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT;
- if (OutputsWritten & (1 << VERT_RESULT_BFC0)
- || OutputsWritten & (1 << VERT_RESULT_BFC1))
- ret |=
- R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT |
- R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT |
- R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT;
+ /* Two sided lighting works only if all 4 colors are written */
+ if (vp_writes & (1 << VERT_RESULT_BFC0) || vp_writes & (1 << VERT_RESULT_BFC1))
+ ret |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT |
+ R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT;
-#if 0
- if (OutputsWritten & (1 << VERT_RESULT_FOGC)) ;
-#endif
-
- if (OutputsWritten & (1 << VERT_RESULT_PSIZ))
+ if (vp_writes & (1 << VERT_RESULT_PSIZ))
ret |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT;
return ret;
}
-GLuint r300VAPOutputCntl1(GLcontext * ctx, GLuint OutputsWritten)
+GLuint r300VAPOutputCntl1(GLcontext * ctx, GLuint vp_writes)
{
- GLuint i, ret = 0;
+ GLuint i, ret = 0, first_free_texcoord = 0;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (OutputsWritten & (1 << (VERT_RESULT_TEX0 + i))) {
- ret |= (4 << (3 * i));
- }
- }
-
- return ret;
-}
-
-/* Emit vertex data to GART memory
- * Route inputs to the vertex processor
- * This function should never return R300_FALLBACK_TCL when using software tcl.
- */
-int r300EmitArrays(GLcontext * ctx)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *vb = &tnl->vb;
- GLuint nr;
- GLuint count = vb->Count;
- GLuint i;
- GLuint InputsRead = 0, OutputsWritten = 0;
- int *inputs = NULL;
- int vir_inputs[VERT_ATTRIB_MAX];
- GLint tab[VERT_ATTRIB_MAX];
- int swizzle[VERT_ATTRIB_MAX][4];
- struct r300_vertex_program *prog =
- (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
-
- if (hw_tcl_on) {
- inputs = prog->inputs;
- InputsRead = prog->key.InputsRead;
- OutputsWritten = prog->key.OutputsWritten;
- } else {
- inputs = rmesa->state.sw_tcl_inputs;
-
- DECLARE_RENDERINPUTS(render_inputs_bitset);
- RENDERINPUTS_COPY(render_inputs_bitset, tnl->render_inputs_bitset);
-
- vb->AttribPtr[VERT_ATTRIB_POS] = vb->ClipPtr;
-
- assert(RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_POS));
- assert(RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_NORMAL) == 0);
- //assert(RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_COLOR0));
-
- if (RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_POS)) {
- InputsRead |= 1 << VERT_ATTRIB_POS;
- OutputsWritten |= 1 << VERT_RESULT_HPOS;
- }
-
- if (RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_COLOR0)) {
- InputsRead |= 1 << VERT_ATTRIB_COLOR0;
- OutputsWritten |= 1 << VERT_RESULT_COL0;
- }
-
- if (RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_COLOR1)) {
- InputsRead |= 1 << VERT_ATTRIB_COLOR1;
- OutputsWritten |= 1 << VERT_RESULT_COL1;
- }
-
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_TEX(i))) {
- InputsRead |= 1 << (VERT_ATTRIB_TEX0 + i);
- OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i);
- }
- }
-
- for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) {
- if (InputsRead & (1 << i)) {
- inputs[i] = nr++;
- } else {
- inputs[i] = -1;
- }
- }
-
- /* Fixed, apply to vir0 only */
- memcpy(vir_inputs, inputs, VERT_ATTRIB_MAX * sizeof(int));
- inputs = vir_inputs;
- if (InputsRead & VERT_ATTRIB_POS)
- inputs[VERT_ATTRIB_POS] = 0;
- if (InputsRead & (1 << VERT_ATTRIB_COLOR0))
- inputs[VERT_ATTRIB_COLOR0] = 2;
- if (InputsRead & (1 << VERT_ATTRIB_COLOR1))
- inputs[VERT_ATTRIB_COLOR1] = 3;
- for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++)
- if (InputsRead & (1 << i))
- inputs[i] = 6 + (i - VERT_ATTRIB_TEX0);
-
- RENDERINPUTS_COPY(rmesa->state.render_inputs_bitset, render_inputs_bitset);
- }
-
- assert(InputsRead);
- assert(OutputsWritten);
-
- for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) {
- if (InputsRead & (1 << i)) {
- tab[nr++] = i;
- }
- }
-
- if (nr > R300_MAX_AOS_ARRAYS) {
- return R300_FALLBACK_TCL;
- }
-
- for (i = 0; i < nr; i++) {
- int ci, fix, found = 0;
-
- swizzle[i][0] = SWIZZLE_ZERO;
- swizzle[i][1] = SWIZZLE_ZERO;
- swizzle[i][2] = SWIZZLE_ZERO;
- swizzle[i][3] = SWIZZLE_ONE;
-
- for (ci = 0; ci < vb->AttribPtr[tab[i]]->size; ci++) {
- swizzle[i][ci] = ci;
- }
-
- if (r300IsGartMemory(rmesa, vb->AttribPtr[tab[i]]->data, 4)) {
- if (vb->AttribPtr[tab[i]]->stride % 4) {
- return R300_FALLBACK_TCL;
- }
- rmesa->state.aos[i].address = (void *)(vb->AttribPtr[tab[i]]->data);
- rmesa->state.aos[i].start = 0;
- rmesa->state.aos[i].aos_offset = r300GartOffsetFromVirtual(rmesa, vb->AttribPtr[tab[i]]->data);
- rmesa->state.aos[i].aos_stride = vb->AttribPtr[tab[i]]->stride / 4;
- rmesa->state.aos[i].aos_size = vb->AttribPtr[tab[i]]->size;
- } else {
- r300EmitVec(ctx, &rmesa->state.aos[i],
- vb->AttribPtr[tab[i]]->data,
- vb->AttribPtr[tab[i]]->size,
- vb->AttribPtr[tab[i]]->stride, count);
- }
-
- rmesa->state.aos[i].aos_size = vb->AttribPtr[tab[i]]->size;
-
- for (fix = 0; fix <= 4 - vb->AttribPtr[tab[i]]->size; fix++) {
- if ((rmesa->state.aos[i].aos_offset - _mesa_sizeof_type(GL_FLOAT) * fix) % 4) {
- continue;
- }
- found = 1;
- break;
- }
-
- if (found) {
- if (fix > 0) {
- WARN_ONCE("Feeling lucky?\n");
- }
- rmesa->state.aos[i].aos_offset -= _mesa_sizeof_type(GL_FLOAT) * fix;
- for (ci = 0; ci < vb->AttribPtr[tab[i]]->size; ci++) {
- swizzle[i][ci] += fix;
- }
- } else {
- WARN_ONCE
- ("Cannot handle offset %x with stride %d, comp %d\n",
- rmesa->state.aos[i].aos_offset,
- rmesa->state.aos[i].aos_stride,
- vb->AttribPtr[tab[i]]->size);
- return R300_FALLBACK_TCL;
+ if (vp_writes & (1 << (VERT_RESULT_TEX0 + i))) {
+ ret |= (4 << (3 * first_free_texcoord));
+ ++first_free_texcoord;
}
}
- /* Setup INPUT_ROUTE. */
- R300_STATECHANGE(rmesa, vir[0]);
- ((drm_r300_cmd_header_t *) rmesa->hw.vir[0].cmd)->packet0.count =
- r300VAPInputRoute0(&rmesa->hw.vir[0].cmd[R300_VIR_CNTL_0],
- vb->AttribPtr, inputs, tab, nr);
- R300_STATECHANGE(rmesa, vir[1]);
- ((drm_r300_cmd_header_t *) rmesa->hw.vir[1].cmd)->packet0.count =
- r300VAPInputRoute1(&rmesa->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle,
- nr);
-
- /* Setup INPUT_CNTL. */
- R300_STATECHANGE(rmesa, vic);
- rmesa->hw.vic.cmd[R300_VIC_CNTL_0] = r300VAPInputCntl0(ctx, InputsRead);
- rmesa->hw.vic.cmd[R300_VIC_CNTL_1] = r300VAPInputCntl1(ctx, InputsRead);
-
- /* Setup OUTPUT_VTX_FMT. */
- R300_STATECHANGE(rmesa, vof);
- rmesa->hw.vof.cmd[R300_VOF_CNTL_0] =
- r300VAPOutputCntl0(ctx, OutputsWritten);
- rmesa->hw.vof.cmd[R300_VOF_CNTL_1] =
- r300VAPOutputCntl1(ctx, OutputsWritten);
-
- rmesa->state.aos_count = nr;
-
- return R300_FALLBACK_NONE;
-}
-
-#ifdef USER_BUFFERS
-void r300UseArrays(GLcontext * ctx)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- int i;
-
- if (rmesa->state.elt_dma.buf)
- r300_mem_use(rmesa, rmesa->state.elt_dma.buf->id);
-
- for (i = 0; i < rmesa->state.aos_count; i++) {
- if (rmesa->state.aos[i].buf)
- r300_mem_use(rmesa, rmesa->state.aos[i].buf->id);
+ if (first_free_texcoord > 8) {
+ fprintf(stderr, "\tout of free texcoords\n");
+ _mesa_exit(-1);
}
-}
-#endif
-void r300ReleaseArrays(GLcontext * ctx)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- int i;
-
- r300ReleaseDmaRegion(rmesa, &rmesa->state.elt_dma, __FUNCTION__);
- for (i = 0; i < rmesa->state.aos_count; i++) {
- r300ReleaseDmaRegion(rmesa, &rmesa->state.aos[i], __FUNCTION__);
- }
+ return ret;
}
void r300EmitCacheFlush(r300ContextPtr rmesa)
{
- int cmd_reserved = 0;
- int cmd_written = 0;
-
- drm_radeon_cmd_header_t *cmd = NULL;
-
- reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
- e32(R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
- R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
-
- reg_start(R300_ZB_ZCACHE_CTLSTAT, 0);
- e32(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
- R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
+ BATCH_LOCALS(&rmesa->radeon);
+
+ BEGIN_BATCH_NO_AUTOSTATE(4);
+ OUT_BATCH_REGVAL(R300_RB3D_DSTCACHE_CTLSTAT,
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
+ OUT_BATCH_REGVAL(R300_ZB_ZCACHE_CTLSTAT,
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
+ END_BATCH();
+ COMMIT_BATCH();
}
diff --git a/src/mesa/drivers/dri/r300/r300_emit.h b/src/mesa/drivers/dri/r300/r300_emit.h
index 89d738339f..8e57e354d1 100644
--- a/src/mesa/drivers/dri/r300/r300_emit.h
+++ b/src/mesa/drivers/dri/r300/r300_emit.h
@@ -44,28 +44,31 @@
#include "r300_cmdbuf.h"
#include "radeon_reg.h"
-/* TODO: move these defines (and the ones from DRM) into r300_reg.h and sync up
- * with DRM */
-#define CP_PACKET0(reg, n) (RADEON_CP_PACKET0 | ((n)<<16) | ((reg)>>2))
-#define CP_PACKET3( pkt, n ) \
- (RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
-
-static INLINE uint32_t cmdpacket0(int reg, int count)
+static INLINE uint32_t cmdpacket0(struct radeon_screen *rscrn,
+ int reg, int count)
{
- drm_r300_cmd_header_t cmd;
-
- cmd.packet0.cmd_type = R300_CMD_PACKET0;
- cmd.packet0.count = count;
- cmd.packet0.reghi = ((unsigned int)reg & 0xFF00) >> 8;
- cmd.packet0.reglo = ((unsigned int)reg & 0x00FF);
-
- return cmd.u;
+ if (!rscrn->kernel_mm) {
+ drm_r300_cmd_header_t cmd;
+
+ cmd.u = 0;
+ cmd.packet0.cmd_type = R300_CMD_PACKET0;
+ cmd.packet0.count = count;
+ cmd.packet0.reghi = ((unsigned int)reg & 0xFF00) >> 8;
+ cmd.packet0.reglo = ((unsigned int)reg & 0x00FF);
+
+ return cmd.u;
+ }
+ if (count) {
+ return CP_PACKET0(reg, count - 1);
+ }
+ return CP_PACKET2;
}
-static INLINE uint32_t cmdvpu(int addr, int count)
+static INLINE uint32_t cmdvpu(struct radeon_screen *rscrn, int addr, int count)
{
drm_r300_cmd_header_t cmd;
+ cmd.u = 0;
cmd.vpu.cmd_type = R300_CMD_VPU;
cmd.vpu.count = count;
cmd.vpu.adrhi = ((unsigned int)addr & 0xFF00) >> 8;
@@ -74,10 +77,12 @@ static INLINE uint32_t cmdvpu(int addr, int count)
return cmd.u;
}
-static INLINE uint32_t cmdr500fp(int addr, int count, int type, int clamp)
+static INLINE uint32_t cmdr500fp(struct radeon_screen *rscrn,
+ int addr, int count, int type, int clamp)
{
drm_r300_cmd_header_t cmd;
+ cmd.u = 0;
cmd.r500fp.cmd_type = R300_CMD_R500FP;
cmd.r500fp.count = count;
cmd.r500fp.adrhi_flags = ((unsigned int)addr & 0x100) >> 8;
@@ -88,181 +93,137 @@ static INLINE uint32_t cmdr500fp(int addr, int count, int type, int clamp)
return cmd.u;
}
-static INLINE uint32_t cmdpacket3(int packet)
+static INLINE uint32_t cmdpacket3(struct radeon_screen *rscrn, int packet)
{
drm_r300_cmd_header_t cmd;
+ cmd.u = 0;
cmd.packet3.cmd_type = R300_CMD_PACKET3;
cmd.packet3.packet = packet;
return cmd.u;
}
-static INLINE uint32_t cmdcpdelay(unsigned short count)
+static INLINE uint32_t cmdcpdelay(struct radeon_screen *rscrn,
+ unsigned short count)
{
drm_r300_cmd_header_t cmd;
+ cmd.u = 0;
+
cmd.delay.cmd_type = R300_CMD_CP_DELAY;
cmd.delay.count = count;
return cmd.u;
}
-static INLINE uint32_t cmdwait(unsigned char flags)
+static INLINE uint32_t cmdwait(struct radeon_screen *rscrn,
+ unsigned char flags)
{
drm_r300_cmd_header_t cmd;
+ cmd.u = 0;
cmd.wait.cmd_type = R300_CMD_WAIT;
cmd.wait.flags = flags;
return cmd.u;
}
-static INLINE uint32_t cmdpacify(void)
+static INLINE uint32_t cmdpacify(struct radeon_screen *rscrn)
{
drm_r300_cmd_header_t cmd;
+ cmd.u = 0;
cmd.header.cmd_type = R300_CMD_END3D;
return cmd.u;
}
/**
- * Prepare to write a register value to register at address reg.
- * If num_extra > 0 then the following extra values are written
- * to registers with address +4, +8 and so on..
- */
-#define reg_start(reg, num_extra) \
- do { \
- int _n; \
- _n=(num_extra); \
- cmd = (drm_radeon_cmd_header_t*) \
- r300AllocCmdBuf(rmesa, \
- (_n+2), \
- __FUNCTION__); \
- cmd_reserved=_n+2; \
- cmd_written=1; \
- cmd[0].i=cmdpacket0((reg), _n+1); \
- } while (0);
-
-/**
- * Emit GLuint freestyle
+ * Write the header of a packet3 to the command buffer.
+ * Outputs 2 dwords and expects (num_extra+1) additional dwords afterwards.
*/
-#define e32(dword) \
- do { \
- if(cmd_written<cmd_reserved) { \
- cmd[cmd_written].i=(dword); \
- cmd_written++; \
- } else { \
- fprintf(stderr, \
- "e32 but no previous packet " \
- "declaration.\n" \
- "Aborting! in %s::%s at line %d, " \
- "cmd_written=%d cmd_reserved=%d\n", \
- __FILE__, __FUNCTION__, __LINE__, \
- cmd_written, cmd_reserved); \
- _mesa_exit(-1); \
- } \
+#define OUT_BATCH_PACKET3(packet, num_extra) do {\
+ if (!b_l_rmesa->radeonScreen->kernel_mm) { \
+ OUT_BATCH(cmdpacket3(b_l_rmesa->radeonScreen,\
+ R300_CMD_PACKET3_RAW)); \
+ } else b_l_rmesa->cmdbuf.cs->section_cdw++;\
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
} while(0)
-#define efloat(f) e32(r300PackFloat32(f))
-
-#define vsf_start_fragment(dest, length) \
- do { \
- int _n; \
- _n = (length); \
- cmd = (drm_radeon_cmd_header_t*) \
- r300AllocCmdBuf(rmesa, \
- (_n+1), \
- __FUNCTION__); \
- cmd_reserved = _n+2; \
- cmd_written =1; \
- cmd[0].i = cmdvpu((dest), _n/4); \
- } while (0);
-
-#define r500fp_start_fragment(dest, length) \
- do { \
- int _n; \
- _n = (length); \
- cmd = (drm_radeon_cmd_header_t*) \
- r300AllocCmdBuf(rmesa, \
- (_n+1), \
- __FUNCTION__); \
- cmd_reserved = _n+1; \
- cmd_written =1; \
- cmd[0].i = cmdr500fp((dest), _n/6, 0, 0); \
- } while (0);
-
-#define start_packet3(packet, count) \
- { \
- int _n; \
- GLuint _p; \
- _n = (count); \
- _p = (packet); \
- cmd = (drm_radeon_cmd_header_t*) \
- r300AllocCmdBuf(rmesa, \
- (_n+3), \
- __FUNCTION__); \
- cmd_reserved = _n+3; \
- cmd_written = 2; \
- if(_n > 0x3fff) { \
- fprintf(stderr,"Too big packet3 %08x: cannot " \
- "store %d dwords\n", \
- _p, _n); \
- _mesa_exit(-1); \
- } \
- cmd[0].i = cmdpacket3(R300_CMD_PACKET3_RAW); \
- cmd[1].i = _p | ((_n & 0x3fff)<<16); \
- }
-
/**
* Must be sent to switch to 2d commands
*/
-void static INLINE end_3d(r300ContextPtr rmesa)
+void static INLINE end_3d(radeonContextPtr radeon)
{
- drm_radeon_cmd_header_t *cmd = NULL;
+ BATCH_LOCALS(radeon);
- cmd =
- (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, 1, __FUNCTION__);
- cmd[0].header.cmd_type = R300_CMD_END3D;
+ if (!radeon->radeonScreen->kernel_mm) {
+ BEGIN_BATCH_NO_AUTOSTATE(1);
+ OUT_BATCH(cmdpacify(radeon->radeonScreen));
+ END_BATCH();
+ }
}
void static INLINE cp_delay(r300ContextPtr rmesa, unsigned short count)
{
- drm_radeon_cmd_header_t *cmd = NULL;
+ BATCH_LOCALS(&rmesa->radeon);
- cmd =
- (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, 1, __FUNCTION__);
- cmd[0].i = cmdcpdelay(count);
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ BEGIN_BATCH_NO_AUTOSTATE(1);
+ OUT_BATCH(cmdcpdelay(rmesa->radeon.radeonScreen, count));
+ END_BATCH();
+ }
}
-void static INLINE cp_wait(r300ContextPtr rmesa, unsigned char flags)
+void static INLINE cp_wait(radeonContextPtr radeon, unsigned char flags)
{
- drm_radeon_cmd_header_t *cmd = NULL;
-
- cmd =
- (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa, 1, __FUNCTION__);
- cmd[0].i = cmdwait(flags);
+ BATCH_LOCALS(radeon);
+ uint32_t wait_until;
+
+ if (!radeon->radeonScreen->kernel_mm) {
+ BEGIN_BATCH_NO_AUTOSTATE(1);
+ OUT_BATCH(cmdwait(radeon->radeonScreen, flags));
+ END_BATCH();
+ } else {
+ switch(flags) {
+ case R300_WAIT_2D:
+ wait_until = (1 << 14);
+ break;
+ case R300_WAIT_3D:
+ wait_until = (1 << 15);
+ break;
+ case R300_NEW_WAIT_2D_3D:
+ wait_until = (1 << 14) | (1 << 15);
+ break;
+ case R300_NEW_WAIT_2D_2D_CLEAN:
+ wait_until = (1 << 14) | (1 << 16) | (1 << 18);
+ break;
+ case R300_NEW_WAIT_3D_3D_CLEAN:
+ wait_until = (1 << 15) | (1 << 17) | (1 << 18);
+ break;
+ case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
+ wait_until = (1 << 14) | (1 << 16) | (1 << 18);
+ wait_until |= (1 << 15) | (1 << 17) | (1 << 18);
+ break;
+ default:
+ return;
+ }
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ OUT_BATCH(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+ OUT_BATCH(wait_until);
+ END_BATCH();
+ }
}
-extern int r300EmitArrays(GLcontext * ctx);
-
-#ifdef USER_BUFFERS
-void r300UseArrays(GLcontext * ctx);
-#endif
-
-extern void r300ReleaseArrays(GLcontext * ctx);
extern int r300PrimitiveType(r300ContextPtr rmesa, int prim);
extern int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim);
extern void r300EmitCacheFlush(r300ContextPtr rmesa);
-extern GLuint r300VAPInputRoute0(uint32_t * dst, GLvector4f ** attribptr,
- int *inputs, GLint * tab, GLuint nr);
-extern GLuint r300VAPInputRoute1(uint32_t * dst, int swizzle[][4], GLuint nr);
extern GLuint r300VAPInputCntl0(GLcontext * ctx, GLuint InputsRead);
extern GLuint r300VAPInputCntl1(GLcontext * ctx, GLuint InputsRead);
-extern GLuint r300VAPOutputCntl0(GLcontext * ctx, GLuint OutputsWritten);
-extern GLuint r300VAPOutputCntl1(GLcontext * ctx, GLuint OutputsWritten);
+extern GLuint r300VAPOutputCntl0(GLcontext * ctx, GLuint vp_writes);
+extern GLuint r300VAPOutputCntl1(GLcontext * ctx, GLuint vp_writes);
#endif
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog.c b/src/mesa/drivers/dri/r300/r300_fragprog.c
deleted file mode 100644
index 4ef7f2bd78..0000000000
--- a/src/mesa/drivers/dri/r300/r300_fragprog.c
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * Copyright (C) 2005 Ben Skeggs.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-/**
- * \file
- *
- * Fragment program compiler. Perform transformations on the intermediate
- * representation until the program is in a form where we can translate
- * it more or less directly into machine-readable form.
- *
- * \author Ben Skeggs <darktama@iinet.net.au>
- * \author Jerome Glisse <j.glisse@gmail.com>
- */
-
-#include "main/glheader.h"
-#include "main/macros.h"
-#include "main/enums.h"
-#include "shader/prog_instruction.h"
-#include "shader/prog_parameter.h"
-#include "shader/prog_print.h"
-
-#include "r300_context.h"
-#include "r300_fragprog.h"
-#include "r300_fragprog_swizzle.h"
-#include "r300_state.h"
-
-#include "radeon_nqssadce.h"
-#include "radeon_program_alu.h"
-
-
-static void reset_srcreg(struct prog_src_register* reg)
-{
- _mesa_bzero(reg, sizeof(*reg));
- reg->Swizzle = SWIZZLE_NOOP;
-}
-
-static struct prog_src_register shadow_ambient(struct gl_program *program, int tmu)
-{
- gl_state_index fail_value_tokens[STATE_LENGTH] = {
- STATE_INTERNAL, STATE_SHADOW_AMBIENT, 0, 0, 0
- };
- struct prog_src_register reg = { 0, };
-
- fail_value_tokens[2] = tmu;
- reg.File = PROGRAM_STATE_VAR;
- reg.Index = _mesa_add_state_reference(program->Parameters, fail_value_tokens);
- reg.Swizzle = SWIZZLE_WWWW;
- return reg;
-}
-
-/**
- * Transform TEX, TXP, TXB, and KIL instructions in the following way:
- * - premultiply texture coordinates for RECT
- * - extract operand swizzles
- * - introduce a temporary register when write masks are needed
- *
- * \todo If/when r5xx uses the radeon_program architecture, this can probably
- * be reused.
- */
-static GLboolean transform_TEX(
- struct radeon_transform_context *t,
- struct prog_instruction* orig_inst, void* data)
-{
- struct r300_fragment_program_compiler *compiler =
- (struct r300_fragment_program_compiler*)data;
- struct prog_instruction inst = *orig_inst;
- struct prog_instruction* tgt;
- GLboolean destredirect = GL_FALSE;
-
- if (inst.Opcode != OPCODE_TEX &&
- inst.Opcode != OPCODE_TXB &&
- inst.Opcode != OPCODE_TXP &&
- inst.Opcode != OPCODE_KIL)
- return GL_FALSE;
-
- if (inst.Opcode != OPCODE_KIL &&
- t->Program->ShadowSamplers & (1 << inst.TexSrcUnit)) {
- GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
-
- if (comparefunc == GL_NEVER || comparefunc == GL_ALWAYS) {
- tgt = radeonAppendInstructions(t->Program, 1);
-
- tgt->Opcode = OPCODE_MOV;
- tgt->DstReg = inst.DstReg;
- if (comparefunc == GL_ALWAYS) {
- tgt->SrcReg[0].File = PROGRAM_BUILTIN;
- tgt->SrcReg[0].Swizzle = SWIZZLE_1111;
- } else {
- tgt->SrcReg[0] = shadow_ambient(t->Program, inst.TexSrcUnit);
- }
- return GL_TRUE;
- }
-
- inst.DstReg.File = PROGRAM_TEMPORARY;
- inst.DstReg.Index = radeonFindFreeTemporary(t);
- inst.DstReg.WriteMask = WRITEMASK_XYZW;
- }
-
-
- /* Hardware uses [0..1]x[0..1] range for rectangle textures
- * instead of [0..Width]x[0..Height].
- * Add a scaling instruction.
- */
- if (inst.Opcode != OPCODE_KIL && inst.TexSrcTarget == TEXTURE_RECT_INDEX) {
- gl_state_index tokens[STATE_LENGTH] = {
- STATE_INTERNAL, STATE_R300_TEXRECT_FACTOR, 0, 0,
- 0
- };
-
- int tempreg = radeonFindFreeTemporary(t);
- int factor_index;
-
- tokens[2] = inst.TexSrcUnit;
- factor_index = _mesa_add_state_reference(t->Program->Parameters, tokens);
-
- tgt = radeonAppendInstructions(t->Program, 1);
-
- tgt->Opcode = OPCODE_MUL;
- tgt->DstReg.File = PROGRAM_TEMPORARY;
- tgt->DstReg.Index = tempreg;
- tgt->SrcReg[0] = inst.SrcReg[0];
- tgt->SrcReg[1].File = PROGRAM_STATE_VAR;
- tgt->SrcReg[1].Index = factor_index;
-
- reset_srcreg(&inst.SrcReg[0]);
- inst.SrcReg[0].File = PROGRAM_TEMPORARY;
- inst.SrcReg[0].Index = tempreg;
- }
-
- if (inst.Opcode != OPCODE_KIL) {
- if (inst.DstReg.File != PROGRAM_TEMPORARY ||
- inst.DstReg.WriteMask != WRITEMASK_XYZW) {
- int tempreg = radeonFindFreeTemporary(t);
-
- inst.DstReg.File = PROGRAM_TEMPORARY;
- inst.DstReg.Index = tempreg;
- inst.DstReg.WriteMask = WRITEMASK_XYZW;
- destredirect = GL_TRUE;
- }
- }
-
- tgt = radeonAppendInstructions(t->Program, 1);
- _mesa_copy_instructions(tgt, &inst, 1);
-
- if (inst.Opcode != OPCODE_KIL &&
- t->Program->ShadowSamplers & (1 << inst.TexSrcUnit)) {
- GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
- GLuint depthmode = compiler->fp->state.unit[inst.TexSrcUnit].depth_texture_mode;
- int rcptemp = radeonFindFreeTemporary(t);
- int pass, fail;
-
- tgt = radeonAppendInstructions(t->Program, 3);
-
- tgt[0].Opcode = OPCODE_RCP;
- tgt[0].DstReg.File = PROGRAM_TEMPORARY;
- tgt[0].DstReg.Index = rcptemp;
- tgt[0].DstReg.WriteMask = WRITEMASK_W;
- tgt[0].SrcReg[0] = inst.SrcReg[0];
- tgt[0].SrcReg[0].Swizzle = SWIZZLE_WWWW;
-
- tgt[1].Opcode = OPCODE_MAD;
- tgt[1].DstReg = inst.DstReg;
- tgt[1].DstReg.WriteMask = orig_inst->DstReg.WriteMask;
- tgt[1].SrcReg[0] = inst.SrcReg[0];
- tgt[1].SrcReg[0].Swizzle = SWIZZLE_ZZZZ;
- tgt[1].SrcReg[1].File = PROGRAM_TEMPORARY;
- tgt[1].SrcReg[1].Index = rcptemp;
- tgt[1].SrcReg[1].Swizzle = SWIZZLE_WWWW;
- tgt[1].SrcReg[2].File = PROGRAM_TEMPORARY;
- tgt[1].SrcReg[2].Index = inst.DstReg.Index;
- if (depthmode == 0) /* GL_LUMINANCE */
- tgt[1].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z);
- else if (depthmode == 2) /* GL_ALPHA */
- tgt[1].SrcReg[2].Swizzle = SWIZZLE_WWWW;
-
- /* Recall that SrcReg[0] is tex, SrcReg[2] is r and:
- * r < tex <=> -tex+r < 0
- * r >= tex <=> not (-tex+r < 0 */
- if (comparefunc == GL_LESS || comparefunc == GL_GEQUAL)
- tgt[1].SrcReg[2].NegateBase = tgt[0].SrcReg[2].NegateBase ^ NEGATE_XYZW;
- else
- tgt[1].SrcReg[0].NegateBase = tgt[0].SrcReg[0].NegateBase ^ NEGATE_XYZW;
-
- tgt[2].Opcode = OPCODE_CMP;
- tgt[2].DstReg = orig_inst->DstReg;
- tgt[2].SrcReg[0].File = PROGRAM_TEMPORARY;
- tgt[2].SrcReg[0].Index = tgt[1].DstReg.Index;
-
- if (comparefunc == GL_LESS || comparefunc == GL_GREATER) {
- pass = 1;
- fail = 2;
- } else {
- pass = 2;
- fail = 1;
- }
-
- tgt[2].SrcReg[pass].File = PROGRAM_BUILTIN;
- tgt[2].SrcReg[pass].Swizzle = SWIZZLE_1111;
- tgt[2].SrcReg[fail] = shadow_ambient(t->Program, inst.TexSrcUnit);
- } else if (destredirect) {
- tgt = radeonAppendInstructions(t->Program, 1);
-
- tgt->Opcode = OPCODE_MOV;
- tgt->DstReg = orig_inst->DstReg;
- tgt->SrcReg[0].File = PROGRAM_TEMPORARY;
- tgt->SrcReg[0].Index = inst.DstReg.Index;
- }
-
- return GL_TRUE;
-}
-
-
-static void update_params(r300ContextPtr r300, struct r300_fragment_program *fp)
-{
- struct gl_fragment_program *mp = &fp->mesa_program;
-
- /* Ask Mesa nicely to fill in ParameterValues for us */
- if (mp->Base.Parameters)
- _mesa_load_state_parameters(r300->radeon.glCtx, mp->Base.Parameters);
-}
-
-
-/**
- * Transform the program to support fragment.position.
- *
- * Introduce a small fragment at the start of the program that will be
- * the only code that directly reads the FRAG_ATTRIB_WPOS input.
- * All other code pieces that reference that input will be rewritten
- * to read from a newly allocated temporary.
- *
- * \todo if/when r5xx supports the radeon_program architecture, this is a
- * likely candidate for code sharing.
- */
-static void insert_WPOS_trailer(struct r300_fragment_program_compiler *compiler)
-{
- GLuint InputsRead = compiler->fp->mesa_program.Base.InputsRead;
-
- if (!(InputsRead & FRAG_BIT_WPOS))
- return;
-
- static gl_state_index tokens[STATE_LENGTH] = {
- STATE_INTERNAL, STATE_R300_WINDOW_DIMENSION, 0, 0, 0
- };
- struct prog_instruction *fpi;
- GLuint window_index;
- int i = 0;
- GLuint tempregi = _mesa_find_free_register(compiler->program, PROGRAM_TEMPORARY);
-
- _mesa_insert_instructions(compiler->program, 0, 3);
- fpi = compiler->program->Instructions;
-
- /* perspective divide */
- fpi[i].Opcode = OPCODE_RCP;
-
- fpi[i].DstReg.File = PROGRAM_TEMPORARY;
- fpi[i].DstReg.Index = tempregi;
- fpi[i].DstReg.WriteMask = WRITEMASK_W;
- fpi[i].DstReg.CondMask = COND_TR;
-
- fpi[i].SrcReg[0].File = PROGRAM_INPUT;
- fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
- fpi[i].SrcReg[0].Swizzle = SWIZZLE_WWWW;
- i++;
-
- fpi[i].Opcode = OPCODE_MUL;
-
- fpi[i].DstReg.File = PROGRAM_TEMPORARY;
- fpi[i].DstReg.Index = tempregi;
- fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
- fpi[i].DstReg.CondMask = COND_TR;
-
- fpi[i].SrcReg[0].File = PROGRAM_INPUT;
- fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
- fpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
-
- fpi[i].SrcReg[1].File = PROGRAM_TEMPORARY;
- fpi[i].SrcReg[1].Index = tempregi;
- fpi[i].SrcReg[1].Swizzle = SWIZZLE_WWWW;
- i++;
-
- /* viewport transformation */
- window_index = _mesa_add_state_reference(compiler->program->Parameters, tokens);
-
- fpi[i].Opcode = OPCODE_MAD;
-
- fpi[i].DstReg.File = PROGRAM_TEMPORARY;
- fpi[i].DstReg.Index = tempregi;
- fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
- fpi[i].DstReg.CondMask = COND_TR;
-
- fpi[i].SrcReg[0].File = PROGRAM_TEMPORARY;
- fpi[i].SrcReg[0].Index = tempregi;
- fpi[i].SrcReg[0].Swizzle =
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
-
- fpi[i].SrcReg[1].File = PROGRAM_STATE_VAR;
- fpi[i].SrcReg[1].Index = window_index;
- fpi[i].SrcReg[1].Swizzle =
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
-
- fpi[i].SrcReg[2].File = PROGRAM_STATE_VAR;
- fpi[i].SrcReg[2].Index = window_index;
- fpi[i].SrcReg[2].Swizzle =
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
- i++;
-
- for (; i < compiler->program->NumInstructions; ++i) {
- int reg;
- for (reg = 0; reg < 3; reg++) {
- if (fpi[i].SrcReg[reg].File == PROGRAM_INPUT &&
- fpi[i].SrcReg[reg].Index == FRAG_ATTRIB_WPOS) {
- fpi[i].SrcReg[reg].File = PROGRAM_TEMPORARY;
- fpi[i].SrcReg[reg].Index = tempregi;
- }
- }
- }
-}
-
-
-static void nqssadce_init(struct nqssadce_state* s)
-{
- s->Outputs[FRAG_RESULT_COLR].Sourced = WRITEMASK_XYZW;
- s->Outputs[FRAG_RESULT_DEPR].Sourced = WRITEMASK_W;
-}
-
-
-static GLuint build_dtm(GLuint depthmode)
-{
- switch(depthmode) {
- default:
- case GL_LUMINANCE: return 0;
- case GL_INTENSITY: return 1;
- case GL_ALPHA: return 2;
- }
-}
-
-static GLuint build_func(GLuint comparefunc)
-{
- return comparefunc - GL_NEVER;
-}
-
-
-/**
- * Collect all external state that is relevant for compiling the given
- * fragment program.
- */
-static void build_state(
- r300ContextPtr r300,
- struct r300_fragment_program *fp,
- struct r300_fragment_program_external_state *state)
-{
- int unit;
-
- _mesa_bzero(state, sizeof(*state));
-
- for(unit = 0; unit < 16; ++unit) {
- if (fp->mesa_program.Base.ShadowSamplers & (1 << unit)) {
- struct gl_texture_object* tex = r300->radeon.glCtx->Texture.Unit[unit]._Current;
-
- state->unit[unit].depth_texture_mode = build_dtm(tex->DepthMode);
- state->unit[unit].texture_compare_func = build_func(tex->CompareFunc);
- }
- }
-}
-
-
-void r300TranslateFragmentShader(r300ContextPtr r300,
- struct r300_fragment_program *fp)
-{
- struct r300_fragment_program_external_state state;
-
- build_state(r300, fp, &state);
- if (_mesa_memcmp(&fp->state, &state, sizeof(state))) {
- /* TODO: cache compiled programs */
- fp->translated = GL_FALSE;
- _mesa_memcpy(&fp->state, &state, sizeof(state));
- }
-
- if (!fp->translated) {
- struct r300_fragment_program_compiler compiler;
-
- compiler.r300 = r300;
- compiler.fp = fp;
- compiler.code = &fp->code;
- compiler.program = _mesa_clone_program(r300->radeon.glCtx, &fp->mesa_program.Base);
-
- if (RADEON_DEBUG & DEBUG_PIXEL) {
- _mesa_printf("Fragment Program: Initial program:\n");
- _mesa_print_program(compiler.program);
- }
-
- insert_WPOS_trailer(&compiler);
-
- struct radeon_program_transformation transformations[] = {
- { &transform_TEX, &compiler },
- { &radeonTransformALU, 0 },
- { &radeonTransformTrigSimple, 0 }
- };
- radeonLocalTransform(
- r300->radeon.glCtx,
- compiler.program,
- 3, transformations);
-
- if (RADEON_DEBUG & DEBUG_PIXEL) {
- _mesa_printf("Fragment Program: After native rewrite:\n");
- _mesa_print_program(compiler.program);
- }
-
- struct radeon_nqssadce_descr nqssadce = {
- .Init = &nqssadce_init,
- .IsNativeSwizzle = &r300FPIsNativeSwizzle,
- .BuildSwizzle = &r300FPBuildSwizzle,
- .RewriteDepthOut = GL_TRUE
- };
- radeonNqssaDce(r300->radeon.glCtx, compiler.program, &nqssadce);
-
- if (RADEON_DEBUG & DEBUG_PIXEL) {
- _mesa_printf("Compiler: after NqSSA-DCE:\n");
- _mesa_print_program(compiler.program);
- }
-
- if (!r300FragmentProgramEmit(&compiler))
- fp->error = GL_TRUE;
-
- /* Subtle: Rescue any parameters that have been added during transformations */
- _mesa_free_parameter_list(fp->mesa_program.Base.Parameters);
- fp->mesa_program.Base.Parameters = compiler.program->Parameters;
- compiler.program->Parameters = 0;
-
- _mesa_reference_program(r300->radeon.glCtx, &compiler.program, NULL);
-
- if (!fp->error)
- fp->translated = GL_TRUE;
- if (fp->error || (RADEON_DEBUG & DEBUG_PIXEL))
- r300FragmentProgramDump(fp, &fp->code);
- r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM);
- }
-
- update_params(r300, fp);
-}
-
-/* just some random things... */
-void r300FragmentProgramDump(
- struct r300_fragment_program *fp,
- struct r300_fragment_program_code *code)
-{
- int n, i, j;
- static int pc = 0;
-
- fprintf(stderr, "pc=%d*************************************\n", pc++);
-
- fprintf(stderr, "Hardware program\n");
- fprintf(stderr, "----------------\n");
-
- for (n = 0; n < (code->cur_node + 1); n++) {
- fprintf(stderr, "NODE %d: alu_offset: %d, tex_offset: %d, "
- "alu_end: %d, tex_end: %d, flags: %08x\n", n,
- code->node[n].alu_offset,
- code->node[n].tex_offset,
- code->node[n].alu_end, code->node[n].tex_end,
- code->node[n].flags);
-
- if (n > 0 || code->first_node_has_tex) {
- fprintf(stderr, " TEX:\n");
- for (i = code->node[n].tex_offset;
- i <= code->node[n].tex_offset + code->node[n].tex_end;
- ++i) {
- const char *instr;
-
- switch ((code->tex.
- inst[i] >> R300_TEX_INST_SHIFT) &
- 15) {
- case R300_TEX_OP_LD:
- instr = "TEX";
- break;
- case R300_TEX_OP_KIL:
- instr = "KIL";
- break;
- case R300_TEX_OP_TXP:
- instr = "TXP";
- break;
- case R300_TEX_OP_TXB:
- instr = "TXB";
- break;
- default:
- instr = "UNKNOWN";
- }
-
- fprintf(stderr,
- " %s t%i, %c%i, texture[%i] (%08x)\n",
- instr,
- (code->tex.
- inst[i] >> R300_DST_ADDR_SHIFT) & 31,
- 't',
- (code->tex.
- inst[i] >> R300_SRC_ADDR_SHIFT) & 31,
- (code->tex.
- inst[i] & R300_TEX_ID_MASK) >>
- R300_TEX_ID_SHIFT,
- code->tex.inst[i]);
- }
- }
-
- for (i = code->node[n].alu_offset;
- i <= code->node[n].alu_offset + code->node[n].alu_end; ++i) {
- char srcc[3][10], dstc[20];
- char srca[3][10], dsta[20];
- char argc[3][20];
- char arga[3][20];
- char flags[5], tmp[10];
-
- for (j = 0; j < 3; ++j) {
- int regc = code->alu.inst[i].inst1 >> (j * 6);
- int rega = code->alu.inst[i].inst3 >> (j * 6);
-
- sprintf(srcc[j], "%c%i",
- (regc & 32) ? 'c' : 't', regc & 31);
- sprintf(srca[j], "%c%i",
- (rega & 32) ? 'c' : 't', rega & 31);
- }
-
- dstc[0] = 0;
- sprintf(flags, "%s%s%s",
- (code->alu.inst[i].
- inst1 & R300_ALU_DSTC_REG_X) ? "x" : "",
- (code->alu.inst[i].
- inst1 & R300_ALU_DSTC_REG_Y) ? "y" : "",
- (code->alu.inst[i].
- inst1 & R300_ALU_DSTC_REG_Z) ? "z" : "");
- if (flags[0] != 0) {
- sprintf(dstc, "t%i.%s ",
- (code->alu.inst[i].
- inst1 >> R300_ALU_DSTC_SHIFT) & 31,
- flags);
- }
- sprintf(flags, "%s%s%s",
- (code->alu.inst[i].
- inst1 & R300_ALU_DSTC_OUTPUT_X) ? "x" : "",
- (code->alu.inst[i].
- inst1 & R300_ALU_DSTC_OUTPUT_Y) ? "y" : "",
- (code->alu.inst[i].
- inst1 & R300_ALU_DSTC_OUTPUT_Z) ? "z" : "");
- if (flags[0] != 0) {
- sprintf(tmp, "o%i.%s",
- (code->alu.inst[i].
- inst1 >> R300_ALU_DSTC_SHIFT) & 31,
- flags);
- strcat(dstc, tmp);
- }
-
- dsta[0] = 0;
- if (code->alu.inst[i].inst3 & R300_ALU_DSTA_REG) {
- sprintf(dsta, "t%i.w ",
- (code->alu.inst[i].
- inst3 >> R300_ALU_DSTA_SHIFT) & 31);
- }
- if (code->alu.inst[i].inst3 & R300_ALU_DSTA_OUTPUT) {
- sprintf(tmp, "o%i.w ",
- (code->alu.inst[i].
- inst3 >> R300_ALU_DSTA_SHIFT) & 31);
- strcat(dsta, tmp);
- }
- if (code->alu.inst[i].inst3 & R300_ALU_DSTA_DEPTH) {
- strcat(dsta, "Z");
- }
-
- fprintf(stderr,
- "%3i: xyz: %3s %3s %3s -> %-20s (%08x)\n"
- " w: %3s %3s %3s -> %-20s (%08x)\n", i,
- srcc[0], srcc[1], srcc[2], dstc,
- code->alu.inst[i].inst1, srca[0], srca[1],
- srca[2], dsta, code->alu.inst[i].inst3);
-
- for (j = 0; j < 3; ++j) {
- int regc = code->alu.inst[i].inst0 >> (j * 7);
- int rega = code->alu.inst[i].inst2 >> (j * 7);
- int d;
- char buf[20];
-
- d = regc & 31;
- if (d < 12) {
- switch (d % 4) {
- case R300_ALU_ARGC_SRC0C_XYZ:
- sprintf(buf, "%s.xyz",
- srcc[d / 4]);
- break;
- case R300_ALU_ARGC_SRC0C_XXX:
- sprintf(buf, "%s.xxx",
- srcc[d / 4]);
- break;
- case R300_ALU_ARGC_SRC0C_YYY:
- sprintf(buf, "%s.yyy",
- srcc[d / 4]);
- break;
- case R300_ALU_ARGC_SRC0C_ZZZ:
- sprintf(buf, "%s.zzz",
- srcc[d / 4]);
- break;
- }
- } else if (d < 15) {
- sprintf(buf, "%s.www", srca[d - 12]);
- } else if (d == 20) {
- sprintf(buf, "0.0");
- } else if (d == 21) {
- sprintf(buf, "1.0");
- } else if (d == 22) {
- sprintf(buf, "0.5");
- } else if (d >= 23 && d < 32) {
- d -= 23;
- switch (d / 3) {
- case 0:
- sprintf(buf, "%s.yzx",
- srcc[d % 3]);
- break;
- case 1:
- sprintf(buf, "%s.zxy",
- srcc[d % 3]);
- break;
- case 2:
- sprintf(buf, "%s.Wzy",
- srcc[d % 3]);
- break;
- }
- } else {
- sprintf(buf, "%i", d);
- }
-
- sprintf(argc[j], "%s%s%s%s",
- (regc & 32) ? "-" : "",
- (regc & 64) ? "|" : "",
- buf, (regc & 64) ? "|" : "");
-
- d = rega & 31;
- if (d < 9) {
- sprintf(buf, "%s.%c", srcc[d / 3],
- 'x' + (char)(d % 3));
- } else if (d < 12) {
- sprintf(buf, "%s.w", srca[d - 9]);
- } else if (d == 16) {
- sprintf(buf, "0.0");
- } else if (d == 17) {
- sprintf(buf, "1.0");
- } else if (d == 18) {
- sprintf(buf, "0.5");
- } else {
- sprintf(buf, "%i", d);
- }
-
- sprintf(arga[j], "%s%s%s%s",
- (rega & 32) ? "-" : "",
- (rega & 64) ? "|" : "",
- buf, (rega & 64) ? "|" : "");
- }
-
- fprintf(stderr, " xyz: %8s %8s %8s op: %08x\n"
- " w: %8s %8s %8s op: %08x\n",
- argc[0], argc[1], argc[2],
- code->alu.inst[i].inst0, arga[0], arga[1],
- arga[2], code->alu.inst[i].inst2);
- }
- }
-}
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog.h b/src/mesa/drivers/dri/r300/r300_fragprog.h
deleted file mode 100644
index 94fb554fb3..0000000000
--- a/src/mesa/drivers/dri/r300/r300_fragprog.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2005 Ben Skeggs.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-/*
- * Authors:
- * Ben Skeggs <darktama@iinet.net.au>
- * Jerome Glisse <j.glisse@gmail.com>
- */
-#ifndef __R300_FRAGPROG_H_
-#define __R300_FRAGPROG_H_
-
-#include "main/glheader.h"
-#include "main/macros.h"
-#include "main/enums.h"
-#include "shader/program.h"
-#include "shader/prog_instruction.h"
-
-#include "r300_context.h"
-#include "radeon_program.h"
-
-#define DRI_CONF_FP_OPTIMIZATION_SPEED 0
-#define DRI_CONF_FP_OPTIMIZATION_QUALITY 1
-
-#if 1
-
-/**
- * Fragment program helper macros
- */
-
-/* Produce unshifted source selectors */
-#define FP_TMP(idx) (idx)
-#define FP_CONST(idx) ((idx) | (1 << 5))
-
-/* Produce source/dest selector dword */
-#define FP_SELC_MASK_NO 0
-#define FP_SELC_MASK_X 1
-#define FP_SELC_MASK_Y 2
-#define FP_SELC_MASK_XY 3
-#define FP_SELC_MASK_Z 4
-#define FP_SELC_MASK_XZ 5
-#define FP_SELC_MASK_YZ 6
-#define FP_SELC_MASK_XYZ 7
-
-#define FP_SELC(destidx,regmask,outmask,src0,src1,src2) \
- (((destidx) << R300_ALU_DSTC_SHIFT) | \
- (FP_SELC_MASK_##regmask << 23) | \
- (FP_SELC_MASK_##outmask << 26) | \
- ((src0) << R300_ALU_SRC0C_SHIFT) | \
- ((src1) << R300_ALU_SRC1C_SHIFT) | \
- ((src2) << R300_ALU_SRC2C_SHIFT))
-
-#define FP_SELA_MASK_NO 0
-#define FP_SELA_MASK_W 1
-
-#define FP_SELA(destidx,regmask,outmask,src0,src1,src2) \
- (((destidx) << R300_ALU_DSTA_SHIFT) | \
- (FP_SELA_MASK_##regmask << 23) | \
- (FP_SELA_MASK_##outmask << 24) | \
- ((src0) << R300_ALU_SRC0A_SHIFT) | \
- ((src1) << R300_ALU_SRC1A_SHIFT) | \
- ((src2) << R300_ALU_SRC2A_SHIFT))
-
-/* Produce unshifted argument selectors */
-#define FP_ARGC(source) R300_ALU_ARGC_##source
-#define FP_ARGA(source) R300_ALU_ARGA_##source
-#define FP_ABS(arg) ((arg) | (1 << 6))
-#define FP_NEG(arg) ((arg) ^ (1 << 5))
-
-/* Produce instruction dword */
-#define FP_INSTRC(opcode,arg0,arg1,arg2) \
- (R300_ALU_OUTC_##opcode | \
- ((arg0) << R300_ALU_ARG0C_SHIFT) | \
- ((arg1) << R300_ALU_ARG1C_SHIFT) | \
- ((arg2) << R300_ALU_ARG2C_SHIFT))
-
-#define FP_INSTRA(opcode,arg0,arg1,arg2) \
- (R300_ALU_OUTA_##opcode | \
- ((arg0) << R300_ALU_ARG0A_SHIFT) | \
- ((arg1) << R300_ALU_ARG1A_SHIFT) | \
- ((arg2) << R300_ALU_ARG2A_SHIFT))
-
-#endif
-
-struct r300_fragment_program;
-
-extern void r300TranslateFragmentShader(r300ContextPtr r300,
- struct r300_fragment_program *fp);
-
-
-/**
- * Used internally by the r300 fragment program code to store compile-time
- * only data.
- */
-struct r300_fragment_program_compiler {
- r300ContextPtr r300;
- struct r300_fragment_program *fp;
- struct r300_fragment_program_code *code;
- struct gl_program *program;
-};
-
-extern GLboolean r300FragmentProgramEmit(struct r300_fragment_program_compiler *compiler);
-
-
-extern void r300FragmentProgramDump(
- struct r300_fragment_program *fp,
- struct r300_fragment_program_code *code);
-
-#endif
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_common.c b/src/mesa/drivers/dri/r300/r300_fragprog_common.c
new file mode 100644
index 0000000000..469c278b51
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_fragprog_common.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/**
+ * \file
+ *
+ * Fragment program compiler. Perform transformations on the intermediate
+ * representation until the program is in a form where we can translate
+ * it more or less directly into machine-readable form.
+ *
+ * \author Ben Skeggs <darktama@iinet.net.au>
+ * \author Jerome Glisse <j.glisse@gmail.com>
+ */
+
+#include "r300_fragprog_common.h"
+
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "compiler/radeon_compiler.h"
+
+#include "r300_state.h"
+
+
+static GLuint build_dtm(GLuint depthmode)
+{
+ switch(depthmode) {
+ default:
+ case GL_LUMINANCE: return 0;
+ case GL_INTENSITY: return 1;
+ case GL_ALPHA: return 2;
+ }
+}
+
+static GLuint build_func(GLuint comparefunc)
+{
+ return comparefunc - GL_NEVER;
+}
+
+/**
+ * Collect all external state that is relevant for compiling the given
+ * fragment program.
+ */
+static void build_state(
+ r300ContextPtr r300,
+ struct gl_fragment_program *fp,
+ struct r300_fragment_program_external_state *state)
+{
+ int unit;
+
+ _mesa_bzero(state, sizeof(*state));
+
+ for(unit = 0; unit < 16; ++unit) {
+ if (fp->Base.ShadowSamplers & (1 << unit)) {
+ struct gl_texture_object* tex = r300->radeon.glCtx->Texture.Unit[unit]._Current;
+
+ state->unit[unit].depth_texture_mode = build_dtm(tex->DepthMode);
+ state->unit[unit].texture_compare_func = build_func(tex->CompareFunc);
+ }
+ }
+}
+
+
+/**
+ * Transform the program to support fragment.position.
+ *
+ * Introduce a small fragment at the start of the program that will be
+ * the only code that directly reads the FRAG_ATTRIB_WPOS input.
+ * All other code pieces that reference that input will be rewritten
+ * to read from a newly allocated temporary.
+ *
+ */
+static void insert_WPOS_trailer(struct r300_fragment_program_compiler *compiler, struct r300_fragment_program * fp)
+{
+ int i;
+
+ if (!(compiler->Base.Program.InputsRead & FRAG_BIT_WPOS)) {
+ fp->wpos_attr = FRAG_ATTRIB_MAX;
+ return;
+ }
+
+ for (i = FRAG_ATTRIB_TEX0; i <= FRAG_ATTRIB_TEX7; ++i)
+ {
+ if (!(compiler->Base.Program.InputsRead & (1 << i))) {
+ fp->wpos_attr = i;
+ break;
+ }
+ }
+
+ rc_transform_fragment_wpos(&compiler->Base, FRAG_ATTRIB_WPOS, fp->wpos_attr);
+}
+
+/**
+ * Rewrite fragment.fogcoord to use a texture coordinate slot.
+ * Note that fogcoord is forced into an X001 pattern, and this enforcement
+ * is done here.
+ *
+ * See also the counterpart rewriting for vertex programs.
+ */
+static void rewriteFog(struct r300_fragment_program_compiler *compiler, struct r300_fragment_program * fp)
+{
+ struct prog_src_register src;
+ int i;
+
+ if (!(compiler->Base.Program.InputsRead & FRAG_BIT_FOGC)) {
+ fp->fog_attr = FRAG_ATTRIB_MAX;
+ return;
+ }
+
+ for (i = FRAG_ATTRIB_TEX0; i <= FRAG_ATTRIB_TEX7; ++i)
+ {
+ if (!(compiler->Base.Program.InputsRead & (1 << i))) {
+ fp->fog_attr = i;
+ break;
+ }
+ }
+
+ memset(&src, 0, sizeof(src));
+ src.File = PROGRAM_INPUT;
+ src.Index = fp->fog_attr;
+ src.Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ONE);
+ rc_move_input(&compiler->Base, FRAG_ATTRIB_FOGC, src);
+}
+
+
+/**
+ * Reserve hardware temporary registers for the program inputs.
+ *
+ * @note This allocation is performed explicitly, because the order of inputs
+ * is determined by the RS hardware.
+ */
+static void allocate_hw_inputs(
+ struct r300_fragment_program_compiler * c,
+ void (*allocate)(void * data, unsigned input, unsigned hwreg),
+ void * mydata)
+{
+ GLuint InputsRead = c->Base.Program.InputsRead;
+ int i;
+ GLuint hwindex = 0;
+
+ /* Primary colour */
+ if (InputsRead & FRAG_BIT_COL0)
+ allocate(mydata, FRAG_ATTRIB_COL0, hwindex++);
+ InputsRead &= ~FRAG_BIT_COL0;
+
+ /* Secondary color */
+ if (InputsRead & FRAG_BIT_COL1)
+ allocate(mydata, FRAG_ATTRIB_COL1, hwindex++);
+ InputsRead &= ~FRAG_BIT_COL1;
+
+ /* Texcoords */
+ for (i = 0; i < 8; i++) {
+ if (InputsRead & (FRAG_BIT_TEX0 << i))
+ allocate(mydata, FRAG_ATTRIB_TEX0+i, hwindex++);
+ }
+ InputsRead &= ~FRAG_BITS_TEX_ANY;
+
+ /* Fogcoords treated as a texcoord */
+ if (InputsRead & FRAG_BIT_FOGC)
+ allocate(mydata, FRAG_ATTRIB_FOGC, hwindex++);
+ InputsRead &= ~FRAG_BIT_FOGC;
+
+ /* fragment position treated as a texcoord */
+ if (InputsRead & FRAG_BIT_WPOS)
+ allocate(mydata, FRAG_ATTRIB_WPOS, hwindex++);
+ InputsRead &= ~FRAG_BIT_WPOS;
+
+ /* Anything else */
+ if (InputsRead)
+ rc_error(&c->Base, "Don't know how to handle inputs 0x%x\n", InputsRead);
+}
+
+
+static void translate_fragment_program(GLcontext *ctx, struct r300_fragment_program_cont *cont, struct r300_fragment_program *fp)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ struct r300_fragment_program_compiler compiler;
+
+ rc_init(&compiler.Base);
+ compiler.Base.Debug = (RADEON_DEBUG & RADEON_PIXEL) ? GL_TRUE : GL_FALSE;
+
+ compiler.code = &fp->code;
+ compiler.state = fp->state;
+ compiler.is_r500 = (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) ? GL_TRUE : GL_FALSE;
+ compiler.OutputDepth = FRAG_RESULT_DEPTH;
+ compiler.OutputColor = FRAG_RESULT_COLOR;
+ compiler.AllocateHwInputs = &allocate_hw_inputs;
+
+ if (compiler.Base.Debug) {
+ fflush(stderr);
+ _mesa_printf("Fragment Program: Initial program:\n");
+ _mesa_print_program(&cont->Base.Base);
+ fflush(stderr);
+ }
+
+ rc_mesa_to_rc_program(&compiler.Base, &cont->Base.Base);
+
+ insert_WPOS_trailer(&compiler, fp);
+
+ rewriteFog(&compiler, fp);
+
+ r3xx_compile_fragment_program(&compiler);
+ fp->error = compiler.Base.Error;
+
+ fp->InputsRead = compiler.Base.Program.InputsRead;
+
+ rc_destroy(&compiler.Base);
+}
+
+struct r300_fragment_program *r300SelectAndTranslateFragmentShader(GLcontext *ctx)
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ struct r300_fragment_program_cont *fp_list;
+ struct r300_fragment_program *fp;
+ struct r300_fragment_program_external_state state;
+
+ fp_list = (struct r300_fragment_program_cont *)ctx->FragmentProgram._Current;
+ build_state(r300, ctx->FragmentProgram._Current, &state);
+
+ fp = fp_list->progs;
+ while (fp) {
+ if (_mesa_memcmp(&fp->state, &state, sizeof(state)) == 0) {
+ return r300->selected_fp = fp;
+ }
+ fp = fp->next;
+ }
+
+ fp = _mesa_calloc(sizeof(struct r300_fragment_program));
+
+ fp->state = state;
+
+ fp->next = fp_list->progs;
+ fp_list->progs = fp;
+
+ translate_fragment_program(ctx, fp_list, fp);
+
+ return r300->selected_fp = fp;
+}
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_common.h b/src/mesa/drivers/dri/r300/r300_fragprog_common.h
new file mode 100644
index 0000000000..3d64c08cee
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_fragprog_common.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __R300_FRAGPROG_COMMON_H_
+#define __R300_FRAGPROG_COMMON_H_
+
+#include "main/mtypes.h"
+
+#include "r300_context.h"
+
+struct r300_fragment_program *r300SelectAndTranslateFragmentShader(GLcontext *ctx);
+
+#endif
diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.c b/src/mesa/drivers/dri/r300/r300_ioctl.c
index ee85e229f0..5cb04e2bb6 100644
--- a/src/mesa/drivers/dri/r300/r300_ioctl.c
+++ b/src/mesa/drivers/dri/r300/r300_ioctl.c
@@ -44,82 +44,160 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/imports.h"
#include "main/macros.h"
#include "main/context.h"
+#include "main/simple_list.h"
#include "swrast/swrast.h"
+#include "radeon_common.h"
+#include "radeon_lock.h"
#include "r300_context.h"
-#include "radeon_ioctl.h"
#include "r300_ioctl.h"
#include "r300_cmdbuf.h"
#include "r300_state.h"
#include "r300_vertprog.h"
#include "radeon_reg.h"
#include "r300_emit.h"
-#include "r300_fragprog.h"
+#include "r300_context.h"
#include "vblank.h"
+#define R200_3D_DRAW_IMMD_2 0xC0003500
+
#define CLEARBUFFER_COLOR 0x1
#define CLEARBUFFER_DEPTH 0x2
#define CLEARBUFFER_STENCIL 0x4
-static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
-{
- GLcontext *ctx = r300->radeon.glCtx;
- __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
- GLuint cboffset, cbpitch;
- drm_r300_cmd_header_t *cmd2;
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
- r300ContextPtr rmesa = r300;
+#if 1
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s: %s buffer (%i,%i %ix%i)\n",
- __FUNCTION__, buffer ? "back" : "front",
- dPriv->x, dPriv->y, dPriv->w, dPriv->h);
+/**
+ * Fragment program helper macros
+ */
- if (buffer) {
- cboffset = r300->radeon.radeonScreen->backOffset;
- cbpitch = r300->radeon.radeonScreen->backPitch;
- } else {
- cboffset = r300->radeon.radeonScreen->frontOffset;
- cbpitch = r300->radeon.radeonScreen->frontPitch;
- }
+/* Produce unshifted source selectors */
+#define FP_TMP(idx) (idx)
+#define FP_CONST(idx) ((idx) | (1 << 5))
+
+/* Produce source/dest selector dword */
+#define FP_SELC_MASK_NO 0
+#define FP_SELC_MASK_X 1
+#define FP_SELC_MASK_Y 2
+#define FP_SELC_MASK_XY 3
+#define FP_SELC_MASK_Z 4
+#define FP_SELC_MASK_XZ 5
+#define FP_SELC_MASK_YZ 6
+#define FP_SELC_MASK_XYZ 7
+
+#define FP_SELC(destidx,regmask,outmask,src0,src1,src2) \
+ (((destidx) << R300_ALU_DSTC_SHIFT) | \
+ (FP_SELC_MASK_##regmask << 23) | \
+ (FP_SELC_MASK_##outmask << 26) | \
+ ((src0) << R300_ALU_SRC0C_SHIFT) | \
+ ((src1) << R300_ALU_SRC1C_SHIFT) | \
+ ((src2) << R300_ALU_SRC2C_SHIFT))
+
+#define FP_SELA_MASK_NO 0
+#define FP_SELA_MASK_W 1
+
+#define FP_SELA(destidx,regmask,outmask,src0,src1,src2) \
+ (((destidx) << R300_ALU_DSTA_SHIFT) | \
+ (FP_SELA_MASK_##regmask << 23) | \
+ (FP_SELA_MASK_##outmask << 24) | \
+ ((src0) << R300_ALU_SRC0A_SHIFT) | \
+ ((src1) << R300_ALU_SRC1A_SHIFT) | \
+ ((src2) << R300_ALU_SRC2A_SHIFT))
+
+/* Produce unshifted argument selectors */
+#define FP_ARGC(source) R300_ALU_ARGC_##source
+#define FP_ARGA(source) R300_ALU_ARGA_##source
+#define FP_ABS(arg) ((arg) | (1 << 6))
+#define FP_NEG(arg) ((arg) ^ (1 << 5))
+
+/* Produce instruction dword */
+#define FP_INSTRC(opcode,arg0,arg1,arg2) \
+ (R300_ALU_OUTC_##opcode | \
+ ((arg0) << R300_ALU_ARG0C_SHIFT) | \
+ ((arg1) << R300_ALU_ARG1C_SHIFT) | \
+ ((arg2) << R300_ALU_ARG2C_SHIFT))
+
+#define FP_INSTRA(opcode,arg0,arg1,arg2) \
+ (R300_ALU_OUTA_##opcode | \
+ ((arg0) << R300_ALU_ARG0A_SHIFT) | \
+ ((arg1) << R300_ALU_ARG1A_SHIFT) | \
+ ((arg2) << R300_ALU_ARG2A_SHIFT))
- cboffset += r300->radeon.radeonScreen->fbLocation;
+#endif
- cp_wait(r300, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
- end_3d(rmesa);
+static void r300EmitClearState(GLcontext * ctx);
- R300_STATECHANGE(r300, cb);
- reg_start(R300_RB3D_COLOROFFSET0, 0);
- e32(cboffset);
+static void r300ClearBuffer(r300ContextPtr r300, int flags,
+ struct radeon_renderbuffer *rrb,
+ struct radeon_renderbuffer *rrbd)
+{
+ BATCH_LOCALS(&r300->radeon);
+ GLcontext *ctx = r300->radeon.glCtx;
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&r300->radeon);
+ GLuint cbpitch = 0;
+ r300ContextPtr rmesa = r300;
- if (r300->radeon.radeonScreen->cpp == 4)
- cbpitch |= R300_COLOR_FORMAT_ARGB8888;
- else
- cbpitch |= R300_COLOR_FORMAT_RGB565;
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s: buffer %p (%i,%i %ix%i)\n",
+ __FUNCTION__, rrb, dPriv->x, dPriv->y,
+ dPriv->w, dPriv->h);
- if (r300->radeon.sarea->tiling_enabled)
- cbpitch |= R300_COLOR_TILE_ENABLE;
+ if (rrb) {
+ cbpitch = (rrb->pitch / rrb->cpp);
+ if (rrb->cpp == 4)
+ cbpitch |= R300_COLOR_FORMAT_ARGB8888;
+ else
+ cbpitch |= R300_COLOR_FORMAT_RGB565;
- reg_start(R300_RB3D_COLORPITCH0, 0);
- e32(cbpitch);
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE){
+ cbpitch |= R300_COLOR_TILE_ENABLE;
+ }
+ }
- R300_STATECHANGE(r300, cmk);
- reg_start(RB3D_COLOR_CHANNEL_MASK, 0);
+ /* TODO in bufmgr */
+ cp_wait(&r300->radeon, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
+ end_3d(&rmesa->radeon);
if (flags & CLEARBUFFER_COLOR) {
- e32((ctx->Color.ColorMask[BCOMP] ? RB3D_COLOR_CHANNEL_MASK_BLUE_MASK0 : 0) |
- (ctx->Color.ColorMask[GCOMP] ? RB3D_COLOR_CHANNEL_MASK_GREEN_MASK0 : 0) |
- (ctx->Color.ColorMask[RCOMP] ? RB3D_COLOR_CHANNEL_MASK_RED_MASK0 : 0) |
- (ctx->Color.ColorMask[ACOMP] ? RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK0 : 0));
+ assert(rrb != 0);
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ OUT_BATCH_REGSEQ(R300_RB3D_COLOROFFSET0, 1);
+ OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_BATCH_REGVAL(R300_RB3D_COLORPITCH0, cbpitch);
+ END_BATCH();
+ }
+#if 1
+ if (flags & (CLEARBUFFER_DEPTH | CLEARBUFFER_STENCIL)) {
+ uint32_t zbpitch = (rrbd->pitch / rrbd->cpp);
+ if (rrbd->bo->flags & RADEON_BO_FLAGS_MACRO_TILE){
+ zbpitch |= R300_DEPTHMACROTILE_ENABLE;
+ }
+ if (rrbd->bo->flags & RADEON_BO_FLAGS_MICRO_TILE){
+ zbpitch |= R300_DEPTHMICROTILE_TILED;
+ }
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ OUT_BATCH_REGSEQ(R300_ZB_DEPTHOFFSET, 1);
+ OUT_BATCH_RELOC(0, rrbd->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_BATCH_REGSEQ(R300_ZB_DEPTHPITCH, 1);
+ if (!r300->radeon.radeonScreen->kernel_mm)
+ OUT_BATCH(zbpitch);
+ else
+ OUT_BATCH_RELOC(zbpitch, rrbd->bo, zbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ END_BATCH();
+ }
+#endif
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ OUT_BATCH_REGSEQ(RB3D_COLOR_CHANNEL_MASK, 1);
+ if (flags & CLEARBUFFER_COLOR) {
+ OUT_BATCH((ctx->Color.ColorMask[BCOMP] ? RB3D_COLOR_CHANNEL_MASK_BLUE_MASK0 : 0) |
+ (ctx->Color.ColorMask[GCOMP] ? RB3D_COLOR_CHANNEL_MASK_GREEN_MASK0 : 0) |
+ (ctx->Color.ColorMask[RCOMP] ? RB3D_COLOR_CHANNEL_MASK_RED_MASK0 : 0) |
+ (ctx->Color.ColorMask[ACOMP] ? RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK0 : 0));
} else {
- e32(0x0);
+ OUT_BATCH(0);
}
- R300_STATECHANGE(r300, zs);
- reg_start(R300_ZB_CNTL, 2);
{
uint32_t t1, t2;
@@ -146,73 +224,92 @@ static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
R300_S_FRONT_ZFAIL_OP_SHIFT);
}
- e32(t1);
- e32(t2);
- e32(((ctx->Stencil.WriteMask[0] & R300_STENCILREF_MASK) << R300_STENCILWRITEMASK_SHIFT) |
- (ctx->Stencil.Clear & R300_STENCILREF_MASK));
+ OUT_BATCH_REGSEQ(R300_ZB_CNTL, 3);
+ OUT_BATCH(t1);
+ OUT_BATCH(t2);
+ OUT_BATCH(((ctx->Stencil.WriteMask[0] & R300_STENCILREF_MASK) <<
+ R300_STENCILWRITEMASK_SHIFT) |
+ (ctx->Stencil.Clear & R300_STENCILREF_MASK));
+ END_BATCH();
}
- cmd2 = (drm_r300_cmd_header_t *) r300AllocCmdBuf(r300, 9, __FUNCTION__);
- cmd2[0].packet3.cmd_type = R300_CMD_PACKET3;
- cmd2[0].packet3.packet = R300_CMD_PACKET3_CLEAR;
- cmd2[1].u = r300PackFloat32(dPriv->w / 2.0);
- cmd2[2].u = r300PackFloat32(dPriv->h / 2.0);
- cmd2[3].u = r300PackFloat32(ctx->Depth.Clear);
- cmd2[4].u = r300PackFloat32(1.0);
- cmd2[5].u = r300PackFloat32(ctx->Color.ClearColor[0]);
- cmd2[6].u = r300PackFloat32(ctx->Color.ClearColor[1]);
- cmd2[7].u = r300PackFloat32(ctx->Color.ClearColor[2]);
- cmd2[8].u = r300PackFloat32(ctx->Color.ClearColor[3]);
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ BEGIN_BATCH_NO_AUTOSTATE(9);
+ OUT_BATCH(cmdpacket3(r300->radeon.radeonScreen, R300_CMD_PACKET3_CLEAR));
+ OUT_BATCH_FLOAT32(dPriv->w / 2.0);
+ OUT_BATCH_FLOAT32(dPriv->h / 2.0);
+ OUT_BATCH_FLOAT32(ctx->Depth.Clear);
+ OUT_BATCH_FLOAT32(1.0);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[0]);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[1]);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[2]);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[3]);
+ END_BATCH();
+ } else {
+ OUT_BATCH(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
+ OUT_BATCH(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
+ (1 << R300_PRIM_NUM_VERTICES_SHIFT));
+ OUT_BATCH_FLOAT32(dPriv->w / 2.0);
+ OUT_BATCH_FLOAT32(dPriv->h / 2.0);
+ OUT_BATCH_FLOAT32(ctx->Depth.Clear);
+ OUT_BATCH_FLOAT32(1.0);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[0]);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[1]);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[2]);
+ OUT_BATCH_FLOAT32(ctx->Color.ClearColor[3]);
+ }
r300EmitCacheFlush(rmesa);
- cp_wait(rmesa, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
+ cp_wait(&r300->radeon, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
+
+ R300_STATECHANGE(r300, cb);
+ R300_STATECHANGE(r300, cmk);
+ R300_STATECHANGE(r300, zs);
}
static void r300EmitClearState(GLcontext * ctx)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
- r300ContextPtr rmesa = r300;
- __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
+ BATCH_LOCALS(&r300->radeon);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&r300->radeon);
int i;
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
- int has_tcl = 1;
+ int has_tcl;
int is_r500 = 0;
GLuint vap_cntl;
- if (!(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
- has_tcl = 0;
+ has_tcl = r300->options.hw_tcl_enabled;
- if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
- is_r500 = 1;
+ if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
+ is_r500 = 1;
-
- /* FIXME: the values written to R300_VAP_INPUT_ROUTE_0_0 and
- * R300_VAP_INPUT_ROUTE_0_1 are in fact known, however, the values are
- * quite complex; see the functions in r300_emit.c.
+ /* State atom dirty tracking is a little subtle here.
+ *
+ * On the one hand, we need to make sure base state is emitted
+ * here if we start with an empty batch buffer, otherwise clear
+ * works incorrectly with multiple processes. Therefore, the first
+ * BEGIN_BATCH cannot be a BEGIN_BATCH_NO_AUTOSTATE.
+ *
+ * On the other hand, implicit state emission clears the state atom
+ * dirty bits, so we have to call R300_STATECHANGE later than the
+ * first BEGIN_BATCH.
*
- * I believe it would be a good idea to extend the functions in
- * r300_emit.c so that they can be used to setup the default values for
- * these registers, as well as the actual values used for rendering.
+ * The final trickiness is that, because we change state, we need
+ * to ensure that any stored swtcl primitives are flushed properly
+ * before we start changing state. See the R300_NEWPRIM in r300Clear
+ * for this.
*/
- R300_STATECHANGE(r300, vir[0]);
- reg_start(R300_VAP_PROG_STREAM_CNTL_0, 0);
+ BEGIN_BATCH(31);
+ OUT_BATCH_REGSEQ(R300_VAP_PROG_STREAM_CNTL_0, 1);
if (!has_tcl)
- e32(((((0 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_0_SHIFT) |
+ OUT_BATCH(((((0 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_0_SHIFT) |
((R300_LAST_VEC | (2 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT)));
else
- e32(((((0 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_0_SHIFT) |
+ OUT_BATCH(((((0 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_0_SHIFT) |
((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT)));
- /* disable fog */
- R300_STATECHANGE(r300, fogs);
- reg_start(R300_FG_FOG_BLEND, 0);
- e32(0x0);
-
- R300_STATECHANGE(r300, vir[1]);
- reg_start(R300_VAP_PROG_STREAM_CNTL_EXT_0, 0);
- e32(((((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
+ OUT_BATCH_REGVAL(R300_FG_FOG_BLEND, 0);
+ OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_EXT_0,
+ ((((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
(R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) |
(R300_SWIZZLE_SELECT_Z << R300_SWIZZLE_SELECT_Z_SHIFT) |
(R300_SWIZZLE_SELECT_W << R300_SWIZZLE_SELECT_W_SHIFT) |
@@ -226,619 +323,460 @@ static void r300EmitClearState(GLcontext * ctx)
<< R300_SWIZZLE1_SHIFT)));
/* R300_VAP_INPUT_CNTL_0, R300_VAP_INPUT_CNTL_1 */
- R300_STATECHANGE(r300, vic);
- reg_start(R300_VAP_VTX_STATE_CNTL, 1);
- e32((R300_SEL_USER_COLOR_0 << R300_COLOR_0_ASSEMBLY_SHIFT));
- e32(R300_INPUT_CNTL_POS | R300_INPUT_CNTL_COLOR | R300_INPUT_CNTL_TC0);
+ OUT_BATCH_REGSEQ(R300_VAP_VTX_STATE_CNTL, 2);
+ OUT_BATCH((R300_SEL_USER_COLOR_0 << R300_COLOR_0_ASSEMBLY_SHIFT));
+ OUT_BATCH(R300_INPUT_CNTL_POS | R300_INPUT_CNTL_COLOR | R300_INPUT_CNTL_TC0);
- R300_STATECHANGE(r300, vte);
/* comes from fglrx startup of clear */
- reg_start(R300_SE_VTE_CNTL, 1);
- e32(R300_VTX_W0_FMT | R300_VPORT_X_SCALE_ENA |
- R300_VPORT_X_OFFSET_ENA | R300_VPORT_Y_SCALE_ENA |
- R300_VPORT_Y_OFFSET_ENA | R300_VPORT_Z_SCALE_ENA |
- R300_VPORT_Z_OFFSET_ENA);
- e32(0x8);
+ OUT_BATCH_REGSEQ(R300_SE_VTE_CNTL, 2);
+ OUT_BATCH(R300_VTX_W0_FMT | R300_VPORT_X_SCALE_ENA |
+ R300_VPORT_X_OFFSET_ENA | R300_VPORT_Y_SCALE_ENA |
+ R300_VPORT_Y_OFFSET_ENA | R300_VPORT_Z_SCALE_ENA |
+ R300_VPORT_Z_OFFSET_ENA);
+ OUT_BATCH(0x8);
- reg_start(R300_VAP_PSC_SGN_NORM_CNTL, 0);
- e32(0xaaaaaaaa);
+ OUT_BATCH_REGVAL(R300_VAP_PSC_SGN_NORM_CNTL, 0xaaaaaaaa);
- R300_STATECHANGE(r300, vof);
- reg_start(R300_VAP_OUTPUT_VTX_FMT_0, 1);
- e32(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
- R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT);
- e32(0x0); /* no textures */
+ OUT_BATCH_REGSEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+ OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
+ R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT);
+ OUT_BATCH(0); /* no textures */
- R300_STATECHANGE(r300, txe);
- reg_start(R300_TX_ENABLE, 0);
- e32(0x0);
+ OUT_BATCH_REGVAL(R300_TX_ENABLE, 0);
- R300_STATECHANGE(r300, vpt);
- reg_start(R300_SE_VPORT_XSCALE, 5);
- efloat(1.0);
- efloat(dPriv->x);
- efloat(1.0);
- efloat(dPriv->y);
- efloat(1.0);
- efloat(0.0);
+ OUT_BATCH_REGSEQ(R300_SE_VPORT_XSCALE, 6);
+ OUT_BATCH_FLOAT32(1.0);
+ OUT_BATCH_FLOAT32(dPriv->x);
+ OUT_BATCH_FLOAT32(1.0);
+ OUT_BATCH_FLOAT32(dPriv->y);
+ OUT_BATCH_FLOAT32(1.0);
+ OUT_BATCH_FLOAT32(0.0);
- R300_STATECHANGE(r300, at);
- reg_start(R300_FG_ALPHA_FUNC, 0);
- e32(0x0);
+ OUT_BATCH_REGVAL(R300_FG_ALPHA_FUNC, 0);
+
+ OUT_BATCH_REGSEQ(R300_RB3D_CBLEND, 2);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ END_BATCH();
+ R300_STATECHANGE(r300, vir[0]);
+ R300_STATECHANGE(r300, fogs);
+ R300_STATECHANGE(r300, vir[1]);
+ R300_STATECHANGE(r300, vic);
+ R300_STATECHANGE(r300, vte);
+ R300_STATECHANGE(r300, vof);
+ R300_STATECHANGE(r300, txe);
+ R300_STATECHANGE(r300, vpt);
+ R300_STATECHANGE(r300, at);
R300_STATECHANGE(r300, bld);
- reg_start(R300_RB3D_CBLEND, 1);
- e32(0x0);
- e32(0x0);
+ R300_STATECHANGE(r300, ps);
if (has_tcl) {
- R300_STATECHANGE(r300, vap_clip_cntl);
- reg_start(R300_VAP_CLIP_CNTL, 0);
- e32(R300_PS_UCP_MODE_CLIP_AS_TRIFAN | R300_CLIP_DISABLE);
+ R300_STATECHANGE(r300, vap_clip_cntl);
+
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ OUT_BATCH_REGVAL(R300_VAP_CLIP_CNTL, R300_PS_UCP_MODE_CLIP_AS_TRIFAN | R300_CLIP_DISABLE);
+ END_BATCH();
}
- R300_STATECHANGE(r300, ps);
- reg_start(R300_GA_POINT_SIZE, 0);
- e32(((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) |
- ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT));
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ OUT_BATCH_REGVAL(R300_GA_POINT_SIZE,
+ ((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) |
+ ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT));
+ END_BATCH();
if (!is_r500) {
R300_STATECHANGE(r300, ri);
- reg_start(R300_RS_IP_0, 7);
- for (i = 0; i < 8; ++i) {
- e32(R300_RS_SEL_T(1) | R300_RS_SEL_R(2) | R300_RS_SEL_Q(3));
- }
-
R300_STATECHANGE(r300, rc);
- /* The second constant is needed to get glxgears display anything .. */
- reg_start(R300_RS_COUNT, 1);
- e32((1 << R300_IC_COUNT_SHIFT) | R300_HIRES_EN);
- e32(0x0);
-
R300_STATECHANGE(r300, rr);
- reg_start(R300_RS_INST_0, 0);
- e32(R300_RS_INST_COL_CN_WRITE);
+
+ BEGIN_BATCH(14);
+ OUT_BATCH_REGSEQ(R300_RS_IP_0, 8);
+ for (i = 0; i < 8; ++i)
+ OUT_BATCH(R300_RS_SEL_T(1) | R300_RS_SEL_R(2) | R300_RS_SEL_Q(3));
+
+ OUT_BATCH_REGSEQ(R300_RS_COUNT, 2);
+ OUT_BATCH((1 << R300_IC_COUNT_SHIFT) | R300_HIRES_EN);
+ OUT_BATCH(0x0);
+
+ OUT_BATCH_REGVAL(R300_RS_INST_0, R300_RS_INST_COL_CN_WRITE);
+ END_BATCH();
} else {
R300_STATECHANGE(r300, ri);
- reg_start(R500_RS_IP_0, 7);
+ R300_STATECHANGE(r300, rc);
+ R300_STATECHANGE(r300, rr);
+
+ BEGIN_BATCH(14);
+ OUT_BATCH_REGSEQ(R500_RS_IP_0, 8);
for (i = 0; i < 8; ++i) {
- e32((R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_S_SHIFT) |
- (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_T_SHIFT) |
- (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_R_SHIFT) |
- (R500_RS_IP_PTR_K1 << R500_RS_IP_TEX_PTR_Q_SHIFT));
+ OUT_BATCH((R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_S_SHIFT) |
+ (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_T_SHIFT) |
+ (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_R_SHIFT) |
+ (R500_RS_IP_PTR_K1 << R500_RS_IP_TEX_PTR_Q_SHIFT));
}
- R300_STATECHANGE(r300, rc);
- /* The second constant is needed to get glxgears display anything .. */
- reg_start(R300_RS_COUNT, 1);
- e32((1 << R300_IC_COUNT_SHIFT) | R300_HIRES_EN);
- e32(0x0);
-
- R300_STATECHANGE(r300, rr);
- reg_start(R500_RS_INST_0, 0);
- e32(R500_RS_INST_COL_CN_WRITE);
+ OUT_BATCH_REGSEQ(R300_RS_COUNT, 2);
+ OUT_BATCH((1 << R300_IC_COUNT_SHIFT) | R300_HIRES_EN);
+ OUT_BATCH(0x0);
+ OUT_BATCH_REGVAL(R500_RS_INST_0, R500_RS_INST_COL_CN_WRITE);
+ END_BATCH();
}
if (!is_r500) {
R300_STATECHANGE(r300, fp);
- reg_start(R300_US_CONFIG, 2);
- e32(0x0);
- e32(0x0);
- e32(0x0);
- reg_start(R300_US_CODE_ADDR_0, 3);
- e32(0x0);
- e32(0x0);
- e32(0x0);
- e32(R300_RGBA_OUT);
-
R300_STATECHANGE(r300, fpi[0]);
R300_STATECHANGE(r300, fpi[1]);
R300_STATECHANGE(r300, fpi[2]);
R300_STATECHANGE(r300, fpi[3]);
- reg_start(R300_US_ALU_RGB_INST_0, 0);
- e32(FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)));
-
- reg_start(R300_US_ALU_RGB_ADDR_0, 0);
- e32(FP_SELC(0, NO, XYZ, FP_TMP(0), 0, 0));
-
- reg_start(R300_US_ALU_ALPHA_INST_0, 0);
- e32(FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)));
-
- reg_start(R300_US_ALU_ALPHA_ADDR_0, 0);
- e32(FP_SELA(0, NO, W, FP_TMP(0), 0, 0));
+ BEGIN_BATCH(17);
+ OUT_BATCH_REGSEQ(R300_US_CONFIG, 3);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ OUT_BATCH_REGSEQ(R300_US_CODE_ADDR_0, 4);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ OUT_BATCH(0x0);
+ OUT_BATCH(R300_RGBA_OUT);
+
+ OUT_BATCH_REGVAL(R300_US_ALU_RGB_INST_0,
+ FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)));
+ OUT_BATCH_REGVAL(R300_US_ALU_RGB_ADDR_0,
+ FP_SELC(0, NO, XYZ, FP_TMP(0), 0, 0));
+ OUT_BATCH_REGVAL(R300_US_ALU_ALPHA_INST_0,
+ FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)));
+ OUT_BATCH_REGVAL(R300_US_ALU_ALPHA_ADDR_0,
+ FP_SELA(0, NO, W, FP_TMP(0), 0, 0));
+ END_BATCH();
} else {
- R300_STATECHANGE(r300, fp);
- reg_start(R500_US_CONFIG, 1);
- e32(R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
- e32(0x0);
- reg_start(R500_US_CODE_ADDR, 2);
- e32(R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(1));
- e32(R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(1));
- e32(R500_US_CODE_OFFSET_ADDR(0));
+ struct radeon_state_atom r500fp;
+ uint32_t _cmd[10];
+ R300_STATECHANGE(r300, fp);
R300_STATECHANGE(r300, r500fp);
- r500fp_start_fragment(0, 6);
-
- e32(R500_INST_TYPE_OUT |
- R500_INST_TEX_SEM_WAIT |
- R500_INST_LAST |
- R500_INST_RGB_OMASK_R |
- R500_INST_RGB_OMASK_G |
- R500_INST_RGB_OMASK_B |
- R500_INST_ALPHA_OMASK |
- R500_INST_RGB_CLAMP |
- R500_INST_ALPHA_CLAMP);
-
- e32(R500_RGB_ADDR0(0) |
- R500_RGB_ADDR1(0) |
- R500_RGB_ADDR1_CONST |
- R500_RGB_ADDR2(0) |
- R500_RGB_ADDR2_CONST);
-
- e32(R500_ALPHA_ADDR0(0) |
- R500_ALPHA_ADDR1(0) |
- R500_ALPHA_ADDR1_CONST |
- R500_ALPHA_ADDR2(0) |
- R500_ALPHA_ADDR2_CONST);
-
- e32(R500_ALU_RGB_SEL_A_SRC0 |
- R500_ALU_RGB_R_SWIZ_A_R |
- R500_ALU_RGB_G_SWIZ_A_G |
- R500_ALU_RGB_B_SWIZ_A_B |
- R500_ALU_RGB_SEL_B_SRC0 |
- R500_ALU_RGB_R_SWIZ_B_R |
- R500_ALU_RGB_B_SWIZ_B_G |
- R500_ALU_RGB_G_SWIZ_B_B);
-
- e32(R500_ALPHA_OP_CMP |
- R500_ALPHA_SWIZ_A_A |
- R500_ALPHA_SWIZ_B_A);
-
- e32(R500_ALU_RGBA_OP_CMP |
- R500_ALU_RGBA_R_SWIZ_0 |
- R500_ALU_RGBA_G_SWIZ_0 |
- R500_ALU_RGBA_B_SWIZ_0 |
- R500_ALU_RGBA_A_SWIZ_0);
+
+ BEGIN_BATCH(7);
+ OUT_BATCH_REGSEQ(R500_US_CONFIG, 2);
+ OUT_BATCH(R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
+ OUT_BATCH(0x0);
+ OUT_BATCH_REGSEQ(R500_US_CODE_ADDR, 3);
+ OUT_BATCH(R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(1));
+ OUT_BATCH(R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(1));
+ OUT_BATCH(R500_US_CODE_OFFSET_ADDR(0));
+ END_BATCH();
+
+ r500fp.check = check_r500fp;
+ r500fp.cmd = _cmd;
+ r500fp.cmd[0] = cmdr500fp(r300->radeon.radeonScreen, 0, 1, 0, 0);
+ r500fp.cmd[1] = R500_INST_TYPE_OUT |
+ R500_INST_TEX_SEM_WAIT |
+ R500_INST_LAST |
+ R500_INST_RGB_OMASK_R |
+ R500_INST_RGB_OMASK_G |
+ R500_INST_RGB_OMASK_B |
+ R500_INST_ALPHA_OMASK |
+ R500_INST_RGB_CLAMP |
+ R500_INST_ALPHA_CLAMP;
+ r500fp.cmd[2] = R500_RGB_ADDR0(0) |
+ R500_RGB_ADDR1(0) |
+ R500_RGB_ADDR1_CONST |
+ R500_RGB_ADDR2(0) |
+ R500_RGB_ADDR2_CONST;
+ r500fp.cmd[3] = R500_ALPHA_ADDR0(0) |
+ R500_ALPHA_ADDR1(0) |
+ R500_ALPHA_ADDR1_CONST |
+ R500_ALPHA_ADDR2(0) |
+ R500_ALPHA_ADDR2_CONST;
+ r500fp.cmd[4] = R500_ALU_RGB_SEL_A_SRC0 |
+ R500_ALU_RGB_R_SWIZ_A_R |
+ R500_ALU_RGB_G_SWIZ_A_G |
+ R500_ALU_RGB_B_SWIZ_A_B |
+ R500_ALU_RGB_SEL_B_SRC0 |
+ R500_ALU_RGB_R_SWIZ_B_R |
+ R500_ALU_RGB_B_SWIZ_B_G |
+ R500_ALU_RGB_G_SWIZ_B_B;
+ r500fp.cmd[5] = R500_ALPHA_OP_CMP |
+ R500_ALPHA_SWIZ_A_A |
+ R500_ALPHA_SWIZ_B_A;
+ r500fp.cmd[6] = R500_ALU_RGBA_OP_CMP |
+ R500_ALU_RGBA_R_SWIZ_0 |
+ R500_ALU_RGBA_G_SWIZ_0 |
+ R500_ALU_RGBA_B_SWIZ_0 |
+ R500_ALU_RGBA_A_SWIZ_0;
+
+ r500fp.cmd[7] = 0;
+ if (r300->radeon.radeonScreen->kernel_mm) {
+ emit_r500fp(ctx, &r500fp);
+ } else {
+ int dwords = r500fp.check(ctx,&r500fp);
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(r500fp.cmd, dwords);
+ END_BATCH();
+ }
+
}
- reg_start(R300_VAP_PVS_STATE_FLUSH_REG, 0);
- e32(0x00000000);
+ BEGIN_BATCH(2);
+ OUT_BATCH_REGVAL(R300_VAP_PVS_STATE_FLUSH_REG, 0);
+ END_BATCH();
+
if (has_tcl) {
- vap_cntl = ((10 << R300_PVS_NUM_SLOTS_SHIFT) |
+ vap_cntl = ((10 << R300_PVS_NUM_SLOTS_SHIFT) |
(5 << R300_PVS_NUM_CNTLRS_SHIFT) |
(12 << R300_VF_MAX_VTX_NUM_SHIFT));
- if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
- vap_cntl |= R500_TCL_STATE_OPTIMIZATION;
- } else
- vap_cntl = ((10 << R300_PVS_NUM_SLOTS_SHIFT) |
+ if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
+ vap_cntl |= R500_TCL_STATE_OPTIMIZATION;
+ } else {
+ vap_cntl = ((10 << R300_PVS_NUM_SLOTS_SHIFT) |
(5 << R300_PVS_NUM_CNTLRS_SHIFT) |
(5 << R300_VF_MAX_VTX_NUM_SHIFT));
+ }
if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV515)
- vap_cntl |= (2 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (2 << R300_PVS_NUM_FPUS_SHIFT);
else if ((r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) ||
(r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV560) ||
(r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV570))
- vap_cntl |= (5 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (5 << R300_PVS_NUM_FPUS_SHIFT);
else if ((r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV410) ||
(r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R420))
- vap_cntl |= (6 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (6 << R300_PVS_NUM_FPUS_SHIFT);
else if ((r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R520) ||
(r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R580))
- vap_cntl |= (8 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (8 << R300_PVS_NUM_FPUS_SHIFT);
else
- vap_cntl |= (4 << R300_PVS_NUM_FPUS_SHIFT);
+ vap_cntl |= (4 << R300_PVS_NUM_FPUS_SHIFT);
- R300_STATECHANGE(rmesa, vap_cntl);
- reg_start(R300_VAP_CNTL, 0);
- e32(vap_cntl);
+ R300_STATECHANGE(r300, vap_cntl);
+
+ BEGIN_BATCH(2);
+ OUT_BATCH_REGVAL(R300_VAP_CNTL, vap_cntl);
+ END_BATCH();
if (has_tcl) {
+ struct radeon_state_atom vpu;
+ uint32_t _cmd[10];
R300_STATECHANGE(r300, pvs);
- reg_start(R300_VAP_PVS_CODE_CNTL_0, 2);
-
- e32((0 << R300_PVS_FIRST_INST_SHIFT) |
- (0 << R300_PVS_XYZW_VALID_INST_SHIFT) |
- (1 << R300_PVS_LAST_INST_SHIFT));
- e32((0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) |
- (0 << R300_PVS_MAX_CONST_ADDR_SHIFT));
- e32(1 << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
-
+ R300_STATECHANGE(r300, vap_flush);
R300_STATECHANGE(r300, vpi);
- vsf_start_fragment(0x0, 8);
- e32(PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, 0, 0xf, PVS_DST_REG_OUT));
- e32(PVS_SRC_OPERAND(0, PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y, PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
- e32(PVS_SRC_OPERAND(0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
- e32(0x0);
+ BEGIN_BATCH(4);
+ OUT_BATCH_REGSEQ(R300_VAP_PVS_CODE_CNTL_0, 3);
+ OUT_BATCH((0 << R300_PVS_FIRST_INST_SHIFT) |
+ (0 << R300_PVS_XYZW_VALID_INST_SHIFT) |
+ (1 << R300_PVS_LAST_INST_SHIFT));
+ OUT_BATCH((0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) |
+ (0 << R300_PVS_MAX_CONST_ADDR_SHIFT));
+ OUT_BATCH(1 << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
+ END_BATCH();
+
+ vpu.check = check_vpu;
+ vpu.cmd = _cmd;
+ vpu.cmd[0] = cmdvpu(r300->radeon.radeonScreen, 0, 2);
+
+ vpu.cmd[1] = PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE,
+ 0, 0xf, PVS_DST_REG_OUT);
+ vpu.cmd[2] = PVS_SRC_OPERAND(0, PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y,
+ PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W,
+ PVS_SRC_REG_INPUT, NEGATE_NONE);
+ vpu.cmd[3] = PVS_SRC_OPERAND(0, PVS_SRC_SELECT_FORCE_0,
+ PVS_SRC_SELECT_FORCE_0,
+ PVS_SRC_SELECT_FORCE_0,
+ PVS_SRC_SELECT_FORCE_0,
+ PVS_SRC_REG_INPUT, NEGATE_NONE);
+ vpu.cmd[4] = 0x0;
+
+ vpu.cmd[5] = PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, 1, 0xf,
+ PVS_DST_REG_OUT);
+ vpu.cmd[6] = PVS_SRC_OPERAND(1, PVS_SRC_SELECT_X,
+ PVS_SRC_SELECT_Y, PVS_SRC_SELECT_Z,
+ PVS_SRC_SELECT_W, PVS_SRC_REG_INPUT,
+ NEGATE_NONE);
+ vpu.cmd[7] = PVS_SRC_OPERAND(1, PVS_SRC_SELECT_FORCE_0,
+ PVS_SRC_SELECT_FORCE_0,
+ PVS_SRC_SELECT_FORCE_0,
+ PVS_SRC_SELECT_FORCE_0,
+ PVS_SRC_REG_INPUT, NEGATE_NONE);
+ vpu.cmd[8] = 0x0;
+
+ if (r300->radeon.radeonScreen->kernel_mm) {
+ int dwords = r300->hw.vap_flush.check(ctx,&r300->hw.vap_flush);
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(r300->hw.vap_flush.cmd, dwords);
+ END_BATCH();
+ emit_vpu(ctx, &vpu);
+ } else {
+ int dwords = vpu.check(ctx,&vpu);
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(vpu.cmd, dwords);
+ END_BATCH();
+ }
- e32(PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, 1, 0xf, PVS_DST_REG_OUT));
- e32(PVS_SRC_OPERAND(1, PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y, PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
- e32(PVS_SRC_OPERAND(1, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_SELECT_FORCE_0, PVS_SRC_REG_INPUT, VSF_FLAG_NONE));
- e32(0x0);
}
}
-/**
- * Buffer clear
- */
-static void r300Clear(GLcontext * ctx, GLbitfield mask)
+static int r300KernelClear(GLcontext *ctx, GLuint flags)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
- int flags = 0;
- int bits = 0;
- int swapped;
-
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "r300Clear\n");
-
- {
- LOCK_HARDWARE(&r300->radeon);
- UNLOCK_HARDWARE(&r300->radeon);
- if (dPriv->numClipRects == 0)
- return;
- }
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&r300->radeon);
+ struct radeon_framebuffer *rfb = dPriv->driverPrivate;
+ struct radeon_renderbuffer *rrb;
+ struct radeon_renderbuffer *rrbd;
+ int bits = 0, ret;
- if (mask & BUFFER_BIT_FRONT_LEFT) {
- flags |= BUFFER_BIT_FRONT_LEFT;
- mask &= ~BUFFER_BIT_FRONT_LEFT;
- }
+ /* Make sure it fits there. */
+ radeon_cs_space_reset_bos(r300->radeon.cmdbuf.cs);
- if (mask & BUFFER_BIT_BACK_LEFT) {
- flags |= BUFFER_BIT_BACK_LEFT;
- mask &= ~BUFFER_BIT_BACK_LEFT;
+ if (flags & BUFFER_BIT_COLOR0) {
+ rrb = radeon_get_renderbuffer(&rfb->base, BUFFER_COLOR0);
+ radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs,
+ rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM);
}
- if (mask & BUFFER_BIT_DEPTH) {
- bits |= CLEARBUFFER_DEPTH;
- mask &= ~BUFFER_BIT_DEPTH;
+ if (flags & BUFFER_BIT_FRONT_LEFT) {
+ rrb = radeon_get_renderbuffer(&rfb->base, BUFFER_FRONT_LEFT);
+ radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs,
+ rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM);
}
- if ((mask & BUFFER_BIT_STENCIL) && r300->state.stencil.hw_stencil) {
- bits |= CLEARBUFFER_STENCIL;
- mask &= ~BUFFER_BIT_STENCIL;
+ if (flags & BUFFER_BIT_BACK_LEFT) {
+ rrb = radeon_get_renderbuffer(&rfb->base, BUFFER_BACK_LEFT);
+ radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs,
+ rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM);
}
- if (mask) {
- if (RADEON_DEBUG & DEBUG_FALLBACKS)
- fprintf(stderr, "%s: swrast clear, mask: %x\n",
- __FUNCTION__, mask);
- _swrast_Clear(ctx, mask);
+ rrbd = radeon_get_renderbuffer(&rfb->base, BUFFER_DEPTH);
+ if (rrbd) {
+ radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs,
+ rrbd->bo, 0, RADEON_GEM_DOMAIN_VRAM);
}
- swapped = r300->radeon.sarea->pfCurrentPage == 1;
+ ret = radeon_cs_space_check(r300->radeon.cmdbuf.cs);
+ if (ret)
+ return -1;
- /* Make sure it fits there. */
- r300EnsureCmdBufSpace(r300, 421 * 3, __FUNCTION__);
+ rcommonEnsureCmdBufSpace(&r300->radeon, 421 * 3, __FUNCTION__);
if (flags || bits)
r300EmitClearState(ctx);
+ rrbd = radeon_get_renderbuffer(&rfb->base, BUFFER_DEPTH);
+ if (rrbd && (flags & BUFFER_BIT_DEPTH))
+ bits |= CLEARBUFFER_DEPTH;
+
+ if (rrbd && (flags & BUFFER_BIT_STENCIL))
+ bits |= CLEARBUFFER_STENCIL;
+
+ if (flags & BUFFER_BIT_COLOR0) {
+ rrb = radeon_get_renderbuffer(&rfb->base, BUFFER_COLOR0);
+ r300ClearBuffer(r300, CLEARBUFFER_COLOR, rrb, NULL);
+ bits = 0;
+ }
+
if (flags & BUFFER_BIT_FRONT_LEFT) {
- r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped);
+ rrb = radeon_get_renderbuffer(&rfb->base, BUFFER_FRONT_LEFT);
+ r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, rrb, rrbd);
bits = 0;
}
if (flags & BUFFER_BIT_BACK_LEFT) {
- r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped ^ 1);
+ rrb = radeon_get_renderbuffer(&rfb->base, BUFFER_BACK_LEFT);
+ r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, rrb, rrbd);
bits = 0;
}
if (bits)
- r300ClearBuffer(r300, bits, 0);
-
-}
-
-void r300Flush(GLcontext * ctx)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ r300ClearBuffer(r300, bits, NULL, rrbd);
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
-
- if (rmesa->cmdbuf.count_used > rmesa->cmdbuf.count_reemit)
- r300FlushCmdBuf(rmesa, __FUNCTION__);
+ COMMIT_BATCH();
+ return 0;
}
-#ifdef USER_BUFFERS
-#include "r300_mem.h"
-
-void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size)
+/**
+ * Buffer clear
+ */
+static void r300Clear(GLcontext * ctx, GLbitfield mask)
{
- struct r300_dma_buffer *dmabuf;
- size = MAX2(size, RADEON_BUFFER_SIZE * 16);
-
- if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
- fprintf(stderr, "%s\n", __FUNCTION__);
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&r300->radeon);
+ const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
+ GLbitfield swrast_mask = 0, tri_mask = 0;
+ int i, ret;
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
- if (rmesa->dma.flush) {
- rmesa->dma.flush(rmesa);
- }
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "r300Clear\n");
- if (rmesa->dma.current.buf) {
-#ifdef USER_BUFFERS
- r300_mem_use(rmesa, rmesa->dma.current.buf->id);
-#endif
- r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
+ if (!r300->radeon.radeonScreen->driScreen->dri2.enabled) {
+ LOCK_HARDWARE(&r300->radeon);
+ UNLOCK_HARDWARE(&r300->radeon);
+ if (dPriv->numClipRects == 0)
+ return;
}
- if (rmesa->dma.nr_released_bufs > 4)
- r300FlushCmdBuf(rmesa, __FUNCTION__);
- dmabuf = CALLOC_STRUCT(r300_dma_buffer);
- dmabuf->buf = (void *)1; /* hack */
- dmabuf->refcount = 1;
-
- dmabuf->id = r300_mem_alloc(rmesa, 4, size);
- if (dmabuf->id == 0) {
- LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
-
- r300FlushCmdBufLocked(rmesa, __FUNCTION__);
- radeonWaitForIdleLocked(&rmesa->radeon);
+ /* Flush swtcl vertices if necessary, because we will change hardware
+ * state during clear. See also the state-related comment in
+ * r300EmitClearState.
+ */
+ R300_NEWPRIM(r300);
- dmabuf->id = r300_mem_alloc(rmesa, 4, size);
+ if (colorMask == ~0)
+ tri_mask |= (mask & BUFFER_BITS_COLOR);
+ else
+ tri_mask |= (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT));
- UNLOCK_HARDWARE(&rmesa->radeon);
- if (dmabuf->id == 0) {
- fprintf(stderr,
- "Error: Could not get dma buffer... exiting\n");
- _mesa_exit(-1);
- }
+ /* HW stencil */
+ if (mask & BUFFER_BIT_STENCIL) {
+ tri_mask |= BUFFER_BIT_STENCIL;
}
- rmesa->dma.current.buf = dmabuf;
- rmesa->dma.current.address = r300_mem_ptr(rmesa, dmabuf->id);
- rmesa->dma.current.end = size;
- rmesa->dma.current.start = 0;
- rmesa->dma.current.ptr = 0;
-}
-
-void r300ReleaseDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region, const char *caller)
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (!region->buf)
- return;
-
- if (rmesa->dma.flush)
- rmesa->dma.flush(rmesa);
-
- if (--region->buf->refcount == 0) {
- r300_mem_free(rmesa, region->buf->id);
- FREE(region->buf);
- rmesa->dma.nr_released_bufs++;
+ /* HW depth */
+ if (mask & BUFFER_BIT_DEPTH) {
+ tri_mask |= BUFFER_BIT_DEPTH;
}
- region->buf = 0;
- region->start = 0;
-}
-
-/* Allocates a region from rmesa->dma.current. If there isn't enough
- * space in current, grab a new buffer (and discard what was left of current)
- */
-void r300AllocDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region,
- int bytes, int alignment)
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
-
- if (rmesa->dma.flush)
- rmesa->dma.flush(rmesa);
-
- if (region->buf)
- r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
-
- alignment--;
- rmesa->dma.current.start = rmesa->dma.current.ptr =
- (rmesa->dma.current.ptr + alignment) & ~alignment;
-
- if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
- r300RefillCurrentDmaRegion(rmesa, (bytes + 0x7) & ~0x7);
-
- region->start = rmesa->dma.current.start;
- region->ptr = rmesa->dma.current.start;
- region->end = rmesa->dma.current.start + bytes;
- region->address = rmesa->dma.current.address;
- region->buf = rmesa->dma.current.buf;
- region->buf->refcount++;
-
- rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
- rmesa->dma.current.start =
- rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
-
- assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
-}
+ /* If we're doing a tri pass for depth/stencil, include a likely color
+ * buffer with it.
+ */
-#else
-static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa)
-{
- struct r300_dma_buffer *dmabuf;
- int fd = rmesa->radeon.dri.fd;
- int index = 0;
- int size = 0;
- drmDMAReq dma;
- int ret;
-
- if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (rmesa->dma.flush) {
- rmesa->dma.flush(rmesa);
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ GLuint bufBit = 1 << i;
+ if ((tri_mask) & bufBit) {
+ if (!fb->Attachment[i].Renderbuffer->ClassID) {
+ tri_mask &= ~bufBit;
+ swrast_mask |= bufBit;
+ }
+ }
}
- if (rmesa->dma.current.buf)
- r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
-
- if (rmesa->dma.nr_released_bufs > 4)
- r300FlushCmdBuf(rmesa, __FUNCTION__);
-
- dma.context = rmesa->radeon.dri.hwContext;
- dma.send_count = 0;
- dma.send_list = NULL;
- dma.send_sizes = NULL;
- dma.flags = 0;
- dma.request_count = 1;
- dma.request_size = RADEON_BUFFER_SIZE;
- dma.request_list = &index;
- dma.request_sizes = &size;
- dma.granted_count = 0;
-
- LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
-
- ret = drmDMA(fd, &dma);
-
- if (ret != 0) {
- /* Try to release some buffers and wait until we can't get any more */
- if (rmesa->dma.nr_released_bufs) {
- r300FlushCmdBufLocked(rmesa, __FUNCTION__);
- }
-
- if (RADEON_DEBUG & DEBUG_DMA)
- fprintf(stderr, "Waiting for buffers\n");
-
- radeonWaitForIdleLocked(&rmesa->radeon);
- ret = drmDMA(fd, &dma);
-
- if (ret != 0) {
- UNLOCK_HARDWARE(&rmesa->radeon);
- fprintf(stderr,
- "Error: Could not get dma buffer... exiting\n");
- _mesa_exit(-1);
+ /* SW fallback clearing */
+ swrast_mask = mask & ~tri_mask;
+
+ ret = 0;
+ if (tri_mask) {
+ if (r300->radeon.radeonScreen->kernel_mm)
+ radeonUserClear(ctx, tri_mask);
+ else {
+ /* if kernel clear fails due to size restraints fallback */
+ ret = r300KernelClear(ctx, tri_mask);
+ if (ret < 0)
+ swrast_mask |= tri_mask;
}
}
- UNLOCK_HARDWARE(&rmesa->radeon);
-
- if (RADEON_DEBUG & DEBUG_DMA)
- fprintf(stderr, "Allocated buffer %d\n", index);
-
- dmabuf = CALLOC_STRUCT(r300_dma_buffer);
- dmabuf->buf = &rmesa->radeon.radeonScreen->buffers->list[index];
- dmabuf->refcount = 1;
-
- rmesa->dma.current.buf = dmabuf;
- rmesa->dma.current.address = dmabuf->buf->address;
- rmesa->dma.current.end = dmabuf->buf->total;
- rmesa->dma.current.start = 0;
- rmesa->dma.current.ptr = 0;
-}
-
-void r300ReleaseDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region, const char *caller)
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (!region->buf)
- return;
-
- if (rmesa->dma.flush)
- rmesa->dma.flush(rmesa);
-
- if (--region->buf->refcount == 0) {
- drm_radeon_cmd_header_t *cmd;
-
- if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
- fprintf(stderr, "%s -- DISCARD BUF %d\n",
- __FUNCTION__, region->buf->buf->idx);
- cmd =
- (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa,
- sizeof
- (*cmd) / 4,
- __FUNCTION__);
- cmd->dma.cmd_type = R300_CMD_DMA_DISCARD;
- cmd->dma.buf_idx = region->buf->buf->idx;
-
- FREE(region->buf);
- rmesa->dma.nr_released_bufs++;
+ if (swrast_mask) {
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
+ fprintf(stderr, "%s: swrast clear, mask: %x\n",
+ __FUNCTION__, swrast_mask);
+ _swrast_Clear(ctx, swrast_mask);
}
-
- region->buf = 0;
- region->start = 0;
-}
-
-/* Allocates a region from rmesa->dma.current. If there isn't enough
- * space in current, grab a new buffer (and discard what was left of current)
- */
-void r300AllocDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region,
- int bytes, int alignment)
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
-
- if (rmesa->dma.flush)
- rmesa->dma.flush(rmesa);
-
- if (region->buf)
- r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
-
- alignment--;
- rmesa->dma.current.start = rmesa->dma.current.ptr =
- (rmesa->dma.current.ptr + alignment) & ~alignment;
-
- if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
- r300RefillCurrentDmaRegion(rmesa);
-
- region->start = rmesa->dma.current.start;
- region->ptr = rmesa->dma.current.start;
- region->end = rmesa->dma.current.start + bytes;
- region->address = rmesa->dma.current.address;
- region->buf = rmesa->dma.current.buf;
- region->buf->refcount++;
-
- rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
- rmesa->dma.current.start =
- rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
-
- assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
-}
-
-#endif
-
-GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer,
- GLint size)
-{
- int offset =
- (char *)pointer -
- (char *)rmesa->radeon.radeonScreen->gartTextures.map;
- int valid = (size >= 0 && offset >= 0
- && offset + size <
- rmesa->radeon.radeonScreen->gartTextures.size);
-
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "r300IsGartMemory( %p ) : %d\n", pointer,
- valid);
-
- return valid;
-}
-
-GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, const GLvoid * pointer)
-{
- int offset =
- (char *)pointer -
- (char *)rmesa->radeon.radeonScreen->gartTextures.map;
-
- //fprintf(stderr, "offset=%08x\n", offset);
-
- if (offset < 0
- || offset > rmesa->radeon.radeonScreen->gartTextures.size)
- return ~0;
- else
- return rmesa->radeon.radeonScreen->gart_texture_offset + offset;
}
void r300InitIoctlFuncs(struct dd_function_table *functions)
{
functions->Clear = r300Clear;
functions->Finish = radeonFinish;
- functions->Flush = r300Flush;
+ functions->Flush = radeonFlush;
}
diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.h b/src/mesa/drivers/dri/r300/r300_ioctl.h
index e1143fb6c3..3abfa71a6e 100644
--- a/src/mesa/drivers/dri/r300/r300_ioctl.h
+++ b/src/mesa/drivers/dri/r300/r300_ioctl.h
@@ -39,22 +39,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_context.h"
#include "radeon_drm.h"
-extern GLboolean r300IsGartMemory(r300ContextPtr rmesa,
- const GLvoid * pointer, GLint size);
-
-extern GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa,
- const GLvoid * pointer);
-
-extern void r300Flush(GLcontext * ctx);
-
-extern void r300ReleaseDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region,
- const char *caller);
-extern void r300AllocDmaRegion(r300ContextPtr rmesa,
- struct r300_dma_region *region, int bytes,
- int alignment);
-
extern void r300InitIoctlFuncs(struct dd_function_table *functions);
-extern void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size);
#endif /* __R300_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/r300/r300_mem.c b/src/mesa/drivers/dri/r300/r300_mem.c
deleted file mode 100644
index f8f9d4fcdf..0000000000
--- a/src/mesa/drivers/dri/r300/r300_mem.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * Copyright (C) 2005 Aapo Tahkola.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-/**
- * \file
- *
- * \author Aapo Tahkola <aet@rasterburn.org>
- */
-
-#include <unistd.h>
-
-#include "r300_context.h"
-#include "r300_cmdbuf.h"
-#include "r300_ioctl.h"
-#include "r300_mem.h"
-#include "radeon_ioctl.h"
-
-#ifdef USER_BUFFERS
-
-static void resize_u_list(r300ContextPtr rmesa)
-{
- void *temp;
- int nsize;
-
- temp = rmesa->rmm->u_list;
- nsize = rmesa->rmm->u_size * 2;
-
- rmesa->rmm->u_list = _mesa_malloc(nsize * sizeof(*rmesa->rmm->u_list));
- _mesa_memset(rmesa->rmm->u_list, 0,
- nsize * sizeof(*rmesa->rmm->u_list));
-
- if (temp) {
- r300FlushCmdBuf(rmesa, __FUNCTION__);
-
- _mesa_memcpy(rmesa->rmm->u_list, temp,
- rmesa->rmm->u_size * sizeof(*rmesa->rmm->u_list));
- _mesa_free(temp);
- }
-
- rmesa->rmm->u_size = nsize;
-}
-
-void r300_mem_init(r300ContextPtr rmesa)
-{
- rmesa->rmm = malloc(sizeof(struct r300_memory_manager));
- memset(rmesa->rmm, 0, sizeof(struct r300_memory_manager));
-
- rmesa->rmm->u_size = 128;
- resize_u_list(rmesa);
-}
-
-void r300_mem_destroy(r300ContextPtr rmesa)
-{
- _mesa_free(rmesa->rmm->u_list);
- rmesa->rmm->u_list = NULL;
-
- _mesa_free(rmesa->rmm);
- rmesa->rmm = NULL;
-}
-
-void *r300_mem_ptr(r300ContextPtr rmesa, int id)
-{
- assert(id <= rmesa->rmm->u_last);
- return rmesa->rmm->u_list[id].ptr;
-}
-
-int r300_mem_find(r300ContextPtr rmesa, void *ptr)
-{
- int i;
-
- for (i = 1; i < rmesa->rmm->u_size + 1; i++)
- if (rmesa->rmm->u_list[i].ptr &&
- ptr >= rmesa->rmm->u_list[i].ptr &&
- ptr <
- rmesa->rmm->u_list[i].ptr + rmesa->rmm->u_list[i].size)
- break;
-
- if (i < rmesa->rmm->u_size + 1)
- return i;
-
- fprintf(stderr, "%p failed\n", ptr);
- return 0;
-}
-
-//#define MM_DEBUG
-int r300_mem_alloc(r300ContextPtr rmesa, int alignment, int size)
-{
- drm_radeon_mem_alloc_t alloc;
- int offset = 0, ret;
- int i, free = -1;
- int done_age;
- drm_radeon_mem_free_t memfree;
- int tries = 0;
- static int bytes_wasted = 0, allocated = 0;
-
- if (size < 4096)
- bytes_wasted += 4096 - size;
-
- allocated += size;
-
-#if 0
- static int t = 0;
- if (t != time(NULL)) {
- t = time(NULL);
- fprintf(stderr, "slots used %d, wasted %d kb, allocated %d\n",
- rmesa->rmm->u_last, bytes_wasted / 1024,
- allocated / 1024);
- }
-#endif
-
- memfree.region = RADEON_MEM_REGION_GART;
-
- again:
-
- done_age = radeonGetAge((radeonContextPtr) rmesa);
-
- if (rmesa->rmm->u_last + 1 >= rmesa->rmm->u_size)
- resize_u_list(rmesa);
-
- for (i = rmesa->rmm->u_last + 1; i > 0; i--) {
- if (rmesa->rmm->u_list[i].ptr == NULL) {
- free = i;
- continue;
- }
-
- if (rmesa->rmm->u_list[i].h_pending == 0 &&
- rmesa->rmm->u_list[i].pending
- && rmesa->rmm->u_list[i].age <= done_age) {
- memfree.region_offset =
- (char *)rmesa->rmm->u_list[i].ptr -
- (char *)rmesa->radeon.radeonScreen->gartTextures.
- map;
-
- ret =
- drmCommandWrite(rmesa->radeon.radeonScreen->
- driScreen->fd, DRM_RADEON_FREE,
- &memfree, sizeof(memfree));
-
- if (ret) {
- fprintf(stderr, "Failed to free at %p\n",
- rmesa->rmm->u_list[i].ptr);
- fprintf(stderr, "ret = %s\n", strerror(-ret));
- exit(1);
- } else {
-#ifdef MM_DEBUG
- fprintf(stderr, "really freed %d at age %x\n",
- i,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
- if (i == rmesa->rmm->u_last)
- rmesa->rmm->u_last--;
-
- if (rmesa->rmm->u_list[i].size < 4096)
- bytes_wasted -=
- 4096 - rmesa->rmm->u_list[i].size;
-
- allocated -= rmesa->rmm->u_list[i].size;
- rmesa->rmm->u_list[i].pending = 0;
- rmesa->rmm->u_list[i].ptr = NULL;
- free = i;
- }
- }
- }
- rmesa->rmm->u_head = i;
-
- if (free == -1) {
- WARN_ONCE("Ran out of slots!\n");
- //usleep(100);
- r300FlushCmdBuf(rmesa, __FUNCTION__);
- tries++;
- if (tries > 100) {
- WARN_ONCE("Ran out of slots!\n");
- exit(1);
- }
- goto again;
- }
-
- alloc.region = RADEON_MEM_REGION_GART;
- alloc.alignment = alignment;
- alloc.size = size;
- alloc.region_offset = &offset;
-
- ret =
- drmCommandWriteRead(rmesa->radeon.dri.fd, DRM_RADEON_ALLOC, &alloc,
- sizeof(alloc));
- if (ret) {
-#if 0
- WARN_ONCE("Ran out of mem!\n");
- r300FlushCmdBuf(rmesa, __FUNCTION__);
- //usleep(100);
- tries2++;
- tries = 0;
- if (tries2 > 100) {
- WARN_ONCE("Ran out of GART memory!\n");
- exit(1);
- }
- goto again;
-#else
- WARN_ONCE
- ("Ran out of GART memory (for %d)!\nPlease consider adjusting GARTSize option.\n",
- size);
- return 0;
-#endif
- }
-
- i = free;
-
- if (i > rmesa->rmm->u_last)
- rmesa->rmm->u_last = i;
-
- rmesa->rmm->u_list[i].ptr =
- ((GLubyte *) rmesa->radeon.radeonScreen->gartTextures.map) + offset;
- rmesa->rmm->u_list[i].size = size;
- rmesa->rmm->u_list[i].age = 0;
- //fprintf(stderr, "alloc %p at id %d\n", rmesa->rmm->u_list[i].ptr, i);
-
-#ifdef MM_DEBUG
- fprintf(stderr, "allocated %d at age %x\n", i,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
-
- return i;
-}
-
-void r300_mem_use(r300ContextPtr rmesa, int id)
-{
- uint64_t ull;
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
- drm_r300_cmd_header_t *cmd;
-
- assert(id <= rmesa->rmm->u_last);
-
- if (id == 0)
- return;
-
- cmd =
- (drm_r300_cmd_header_t *) r300AllocCmdBuf(rmesa,
- 2 + sizeof(ull) / 4,
- __FUNCTION__);
- cmd[0].scratch.cmd_type = R300_CMD_SCRATCH;
- cmd[0].scratch.reg = R300_MEM_SCRATCH;
- cmd[0].scratch.n_bufs = 1;
- cmd[0].scratch.flags = 0;
- cmd++;
-
- ull = (uint64_t) (intptr_t) & rmesa->rmm->u_list[id].age;
- _mesa_memcpy(cmd, &ull, sizeof(ull));
- cmd += sizeof(ull) / 4;
-
- cmd[0].u = /*id */ 0;
-
- LOCK_HARDWARE(&rmesa->radeon); /* Protect from DRM. */
- rmesa->rmm->u_list[id].h_pending++;
- UNLOCK_HARDWARE(&rmesa->radeon);
-}
-
-unsigned long r300_mem_offset(r300ContextPtr rmesa, int id)
-{
- unsigned long offset;
-
- assert(id <= rmesa->rmm->u_last);
-
- offset = (char *)rmesa->rmm->u_list[id].ptr -
- (char *)rmesa->radeon.radeonScreen->gartTextures.map;
- offset += rmesa->radeon.radeonScreen->gart_texture_offset;
-
- return offset;
-}
-
-void *r300_mem_map(r300ContextPtr rmesa, int id, int access)
-{
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
- void *ptr;
- int tries = 0;
-
- assert(id <= rmesa->rmm->u_last);
-
- if (access == R300_MEM_R) {
-
- if (rmesa->rmm->u_list[id].mapped == 1)
- WARN_ONCE("buffer %d already mapped\n", id);
-
- rmesa->rmm->u_list[id].mapped = 1;
- ptr = r300_mem_ptr(rmesa, id);
-
- return ptr;
- }
-
- if (rmesa->rmm->u_list[id].h_pending)
- r300FlushCmdBuf(rmesa, __FUNCTION__);
-
- if (rmesa->rmm->u_list[id].h_pending) {
- return NULL;
- }
-
- while (rmesa->rmm->u_list[id].age >
- radeonGetAge((radeonContextPtr) rmesa) && tries++ < 1000)
- usleep(10);
-
- if (tries >= 1000) {
- fprintf(stderr, "Idling failed (%x vs %x)\n",
- rmesa->rmm->u_list[id].age,
- radeonGetAge((radeonContextPtr) rmesa));
- return NULL;
- }
-
- if (rmesa->rmm->u_list[id].mapped == 1)
- WARN_ONCE("buffer %d already mapped\n", id);
-
- rmesa->rmm->u_list[id].mapped = 1;
- ptr = r300_mem_ptr(rmesa, id);
-
- return ptr;
-}
-
-void r300_mem_unmap(r300ContextPtr rmesa, int id)
-{
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
-
- assert(id <= rmesa->rmm->u_last);
-
- if (rmesa->rmm->u_list[id].mapped == 0)
- WARN_ONCE("buffer %d not mapped\n", id);
-
- rmesa->rmm->u_list[id].mapped = 0;
-}
-
-void r300_mem_free(r300ContextPtr rmesa, int id)
-{
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id,
- radeonGetAge((radeonContextPtr) rmesa));
-#endif
-
- assert(id <= rmesa->rmm->u_last);
-
- if (id == 0)
- return;
-
- if (rmesa->rmm->u_list[id].ptr == NULL) {
- WARN_ONCE("Not allocated!\n");
- return;
- }
-
- if (rmesa->rmm->u_list[id].pending) {
- WARN_ONCE("%p already pended!\n", rmesa->rmm->u_list[id].ptr);
- return;
- }
-
- rmesa->rmm->u_list[id].pending = 1;
-}
-#endif
diff --git a/src/mesa/drivers/dri/r300/r300_mem.h b/src/mesa/drivers/dri/r300/r300_mem.h
deleted file mode 100644
index 625a7f6d8d..0000000000
--- a/src/mesa/drivers/dri/r300/r300_mem.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef __R300_MEM_H__
-#define __R300_MEM_H__
-
-//#define R300_MEM_PDL 0
-#define R300_MEM_UL 1
-
-#define R300_MEM_R 1
-#define R300_MEM_W 2
-#define R300_MEM_RW (R300_MEM_R | R300_MEM_W)
-
-#define R300_MEM_SCRATCH 2
-
-struct r300_memory_manager {
- struct {
- void *ptr;
- uint32_t size;
- uint32_t age;
- uint32_t h_pending;
- int pending;
- int mapped;
- } *u_list;
- int u_head, u_size, u_last;
-
-};
-
-extern void r300_mem_init(r300ContextPtr rmesa);
-extern void r300_mem_destroy(r300ContextPtr rmesa);
-extern void *r300_mem_ptr(r300ContextPtr rmesa, int id);
-extern int r300_mem_find(r300ContextPtr rmesa, void *ptr);
-extern int r300_mem_alloc(r300ContextPtr rmesa, int alignment, int size);
-extern void r300_mem_use(r300ContextPtr rmesa, int id);
-extern unsigned long r300_mem_offset(r300ContextPtr rmesa, int id);
-extern void *r300_mem_map(r300ContextPtr rmesa, int id, int access);
-extern void r300_mem_unmap(r300ContextPtr rmesa, int id);
-extern void r300_mem_free(r300ContextPtr rmesa, int id);
-
-#endif
diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h
index 7c6485ef60..b9ccd098dc 100644
--- a/src/mesa/drivers/dri/r300/r300_reg.h
+++ b/src/mesa/drivers/dri/r300/r300_reg.h
@@ -656,7 +656,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_GB_FOG_SELECT_C3A (3 << 0)
# define R300_GB_FOG_SELECT_1_1_W (4 << 0)
# define R300_GB_FOG_SELECT_Z (5 << 0)
-# define R300_GB_DEPTH_SELECT_Z (0 << 3
+# define R300_GB_DEPTH_SELECT_Z (0 << 3)
# define R300_GB_DEPTH_SELECT_1_1_W (1 << 3)
# define R300_GB_W_SELECT_1_W (0 << 4)
# define R300_GB_W_SELECT_1 (1 << 4)
@@ -730,8 +730,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R500_RS_IP_TEX_PTR_Q_SHIFT 18
#define R500_RS_IP_COL_PTR_SHIFT 24
#define R500_RS_IP_COL_FMT_SHIFT 27
-# define R500_RS_COL_PTR(x) (x << 24)
-# define R500_RS_COL_FMT(x) (x << 27)
+# define R500_RS_COL_PTR(x) ((x) << 24)
+# define R500_RS_COL_FMT(x) ((x) << 27)
/* gap */
#define R500_RS_IP_OFFSET_DIS (0 << 31)
#define R500_RS_IP_OFFSET_EN (1 << 31)
@@ -1022,15 +1022,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
R300_GA_COLOR_CONTROL_RGB0_SHADING_GOURAUD | R300_GA_COLOR_CONTROL_ALPHA0_SHADING_GOURAUD | \
R300_GA_COLOR_CONTROL_RGB1_SHADING_GOURAUD | R300_GA_COLOR_CONTROL_ALPHA1_SHADING_GOURAUD | \
R300_GA_COLOR_CONTROL_RGB2_SHADING_GOURAUD | R300_GA_COLOR_CONTROL_ALPHA2_SHADING_GOURAUD | \
- R300_GA_COLOR_CONTROL_RGB3_SHADING_GOURAUD | R300_GA_COLOR_CONTROL_ALPHA3_SHADING_GOURAUD | \
- R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST )
+ R300_GA_COLOR_CONTROL_RGB3_SHADING_GOURAUD | R300_GA_COLOR_CONTROL_ALPHA3_SHADING_GOURAUD)
/** TODO: might be candidate for removal, the GOURAUD stuff also looks buggy to me */
# define R300_RE_SHADE_MODEL_FLAT ( \
R300_GA_COLOR_CONTROL_RGB0_SHADING_FLAT | R300_GA_COLOR_CONTROL_ALPHA0_SHADING_FLAT | \
R300_GA_COLOR_CONTROL_RGB1_SHADING_FLAT | R300_GA_COLOR_CONTROL_ALPHA1_SHADING_GOURAUD | \
R300_GA_COLOR_CONTROL_RGB2_SHADING_FLAT | R300_GA_COLOR_CONTROL_ALPHA2_SHADING_FLAT | \
- R300_GA_COLOR_CONTROL_RGB3_SHADING_FLAT | R300_GA_COLOR_CONTROL_ALPHA3_SHADING_GOURAUD | \
- R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST )
+ R300_GA_COLOR_CONTROL_RGB3_SHADING_FLAT | R300_GA_COLOR_CONTROL_ALPHA3_SHADING_GOURAUD)
/* Specifies red & green components of fill color -- S312 format -- Backwards comp. */
#define R300_GA_SOLID_RG 0x427c
@@ -1128,6 +1126,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* SU Depth Offset value */
#define R300_SU_DEPTH_OFFSET 0x42c4
+#define R300_SU_REG_DEST 0x42c8
+# define R300_RASTER_PIPE_SELECT_0 (1 << 0)
+# define R300_RASTER_PIPE_SELECT_1 (1 << 1)
+# define R300_RASTER_PIPE_SELECT_2 (1 << 2)
+# define R300_RASTER_PIPE_SELECT_3 (1 << 3)
+# define R300_RASTER_PIPE_SELECT_ALL 0xf
+
/* BEGIN: Rasterization / Interpolators - many guesses */
@@ -1172,9 +1177,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R300_RS_IP_3 0x431C
# define R300_RS_INTERP_SRC_SHIFT 2 /* TODO: check for removal */
# define R300_RS_INTERP_SRC_MASK (7 << 2) /* TODO: check for removal */
-# define R300_RS_TEX_PTR(x) (x << 0)
-# define R300_RS_COL_PTR(x) (x << 6)
-# define R300_RS_COL_FMT(x) (x << 9)
+# define R300_RS_TEX_PTR(x) ((x) << 0)
+# define R300_RS_COL_PTR(x) ((x) << 6)
+# define R300_RS_COL_FMT(x) ((x) << 9)
# define R300_RS_COL_FMT_RGBA 0
# define R300_RS_COL_FMT_RGB0 1
# define R300_RS_COL_FMT_RGB1 2
@@ -1184,10 +1189,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_RS_COL_FMT_111A 8
# define R300_RS_COL_FMT_1110 9
# define R300_RS_COL_FMT_1111 10
-# define R300_RS_SEL_S(x) (x << 13)
-# define R300_RS_SEL_T(x) (x << 16)
-# define R300_RS_SEL_R(x) (x << 19)
-# define R300_RS_SEL_Q(x) (x << 22)
+# define R300_RS_SEL_S(x) ((x) << 13)
+# define R300_RS_SEL_T(x) ((x) << 16)
+# define R300_RS_SEL_R(x) ((x) << 19)
+# define R300_RS_SEL_Q(x) ((x) << 22)
# define R300_RS_SEL_C0 0
# define R300_RS_SEL_C1 1
# define R300_RS_SEL_C2 2
@@ -1224,6 +1229,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R500_RS_INST_COL_ADDR_SHIFT 18
#define R500_RS_INST_TEX_ADJ (1 << 25)
#define R500_RS_INST_W_CN (1 << 26)
+#define R500_RS_INST_TEX_ID(x) ((x) << R500_RS_INST_TEX_ID_SHIFT)
+#define R500_RS_INST_TEX_ADDR(x) ((x) << R500_RS_INST_TEX_ADDR_SHIFT)
+#define R500_RS_INST_COL_ID(x) ((x) << R500_RS_INST_COL_ID_SHIFT)
+#define R500_RS_INST_COL_ADDR(x) ((x) << R500_RS_INST_COL_ADDR_SHIFT)
/* These DWORDs control how vertex data is routed into fragment program
* registers, after interpolators.
@@ -1239,9 +1248,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_RS_INST_TEX_ID(x) ((x) << 0)
# define R300_RS_INST_TEX_CN_WRITE (1 << 3)
# define R300_RS_INST_TEX_ADDR_SHIFT 6
+# define R300_RS_INST_TEX_ADDR(x) ((x) << R300_RS_INST_TEX_ADDR_SHIFT)
# define R300_RS_INST_COL_ID(x) ((x) << 11)
# define R300_RS_INST_COL_CN_WRITE (1 << 14)
# define R300_RS_INST_COL_ADDR_SHIFT 17
+# define R300_RS_INST_COL_ADDR(x) ((x) << R300_RS_INST_COL_ADDR_SHIFT)
# define R300_RS_INST_TEX_ADJ (1 << 22)
# define R300_RS_COL_BIAS_UNUSED_SHIFT 23
@@ -1461,6 +1472,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_TX_FORMAT_3D (1 << 25)
# define R300_TX_FORMAT_CUBIC_MAP (2 << 25)
+# define R300_TX_FORMAT_GAMMA (1 << 21)
+
/* gap */
/* Floating point formats */
/* Note - hardware supports both 16 and 32 bit floating point */
@@ -1525,6 +1538,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R500_SEL_FILTER4_TC3 (3 << 18)
#define R300_TX_OFFSET_0 0x4540
+#define R300_TX_OFFSET_1 0x4544
+#define R300_TX_OFFSET_2 0x4548
+#define R300_TX_OFFSET_3 0x454C
+#define R300_TX_OFFSET_4 0x4550
+#define R300_TX_OFFSET_5 0x4554
+#define R300_TX_OFFSET_6 0x4558
+#define R300_TX_OFFSET_7 0x455C
/* BEGIN: Guess from R200 */
# define R300_TXO_ENDIAN_NO_SWAP (0 << 0)
# define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0)
@@ -1999,6 +2019,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R500_FG_ALPHA_VALUE 0x4be0
# define R500_FG_ALPHA_VALUE_MASK 0x0000ffff
+#define RV530_FG_ZBREG_DEST 0x4be8
+# define RV530_FG_ZBREG_DEST_PIPE_SELECT_0 (1 << 0)
+# define RV530_FG_ZBREG_DEST_PIPE_SELECT_1 (1 << 1)
+# define RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL (3 << 0)
+
/* gap */
/* Fragment program parameters in 7.16 floating point */
@@ -2288,6 +2313,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_Z_WRITE_ENABLE (1 << 2)
# define R300_Z_SIGNED_COMPARE (1 << 3)
# define R300_STENCIL_FRONT_BACK (1 << 4)
+# define R400_ZSIGNED_MAGNITUDE (1 << 5)
+# define R500_STENCIL_REFMASK_FRONT_BACK (1 << 6)
#define R300_ZB_ZSTENCILCNTL 0x4f04
/* functions */
@@ -2419,6 +2446,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* Z Buffer Clear Value */
#define R300_ZB_DEPTHCLEARVALUE 0x4f28
+#define R300_ZB_ZMASK_OFFSET 0x4f30
+#define R300_ZB_ZMASK_PITCH 0x4f34
+#define R300_ZB_ZMASK_WRINDEX 0x4f38
+#define R300_ZB_ZMASK_DWORD 0x4f3c
+#define R300_ZB_ZMASK_RDINDEX 0x4f40
+
/* Hierarchical Z Memory Offset */
#define R300_ZB_HIZ_OFFSET 0x4f44
@@ -2646,6 +2679,24 @@ enum {
PVS_SRC_ADDR_MODE_1_SHIFT = 32,
};
+
+#define PVS_OP_DST_OPERAND(opcode, math_inst, macro_inst, reg_index, reg_writemask, reg_class) \
+ (((opcode & PVS_DST_OPCODE_MASK) << PVS_DST_OPCODE_SHIFT) \
+ | ((math_inst & PVS_DST_MATH_INST_MASK) << PVS_DST_MATH_INST_SHIFT) \
+ | ((macro_inst & PVS_DST_MACRO_INST_MASK) << PVS_DST_MACRO_INST_SHIFT) \
+ | ((reg_index & PVS_DST_OFFSET_MASK) << PVS_DST_OFFSET_SHIFT) \
+ | ((reg_writemask & 0xf) << PVS_DST_WE_X_SHIFT) /* X Y Z W */ \
+ | ((reg_class & PVS_DST_REG_TYPE_MASK) << PVS_DST_REG_TYPE_SHIFT))
+
+#define PVS_SRC_OPERAND(in_reg_index, comp_x, comp_y, comp_z, comp_w, reg_class, negate) \
+ (((in_reg_index & PVS_SRC_OFFSET_MASK) << PVS_SRC_OFFSET_SHIFT) \
+ | ((comp_x & PVS_SRC_SWIZZLE_X_MASK) << PVS_SRC_SWIZZLE_X_SHIFT) \
+ | ((comp_y & PVS_SRC_SWIZZLE_Y_MASK) << PVS_SRC_SWIZZLE_Y_SHIFT) \
+ | ((comp_z & PVS_SRC_SWIZZLE_Z_MASK) << PVS_SRC_SWIZZLE_Z_SHIFT) \
+ | ((comp_w & PVS_SRC_SWIZZLE_W_MASK) << PVS_SRC_SWIZZLE_W_SHIFT) \
+ | ((negate & 0xf) << PVS_SRC_MODIFIER_X_SHIFT) /* X Y Z W */ \
+ | ((reg_class & PVS_SRC_REG_TYPE_MASK) << PVS_SRC_REG_TYPE_SHIFT))
+
/*\}*/
/* BEGIN: Packet 3 commands */
@@ -2705,7 +2756,7 @@ enum {
# define R500_ALPHA_OP_COS 13
# define R500_ALPHA_OP_MDH 14
# define R500_ALPHA_OP_MDV 15
-# define R500_ALPHA_ADDRD(x) (x << 4)
+# define R500_ALPHA_ADDRD(x) ((x) << 4)
# define R500_ALPHA_ADDRD_REL (1 << 11)
# define R500_ALPHA_SEL_A_SHIFT 12
# define R500_ALPHA_SEL_A_SRC0 (0 << 12)
@@ -2749,16 +2800,16 @@ enum {
# define R500_ALPHA_OMOD_DIV_4 (5 << 26)
# define R500_ALPHA_OMOD_DIV_8 (6 << 26)
# define R500_ALPHA_OMOD_DISABLE (7 << 26)
-# define R500_ALPHA_TARGET(x) (x << 29)
+# define R500_ALPHA_TARGET(x) ((x) << 29)
# define R500_ALPHA_W_OMASK (1 << 31)
#define R500_US_ALU_ALPHA_ADDR_0 0x9800
-# define R500_ALPHA_ADDR0(x) (x << 0)
+# define R500_ALPHA_ADDR0(x) ((x) << 0)
# define R500_ALPHA_ADDR0_CONST (1 << 8)
# define R500_ALPHA_ADDR0_REL (1 << 9)
-# define R500_ALPHA_ADDR1(x) (x << 10)
+# define R500_ALPHA_ADDR1(x) ((x) << 10)
# define R500_ALPHA_ADDR1_CONST (1 << 18)
# define R500_ALPHA_ADDR1_REL (1 << 19)
-# define R500_ALPHA_ADDR2(x) (x << 20)
+# define R500_ALPHA_ADDR2(x) ((x) << 20)
# define R500_ALPHA_ADDR2_CONST (1 << 28)
# define R500_ALPHA_ADDR2_REL (1 << 29)
# define R500_ALPHA_SRCP_OP_1_MINUS_2A0 (0 << 30)
@@ -2779,7 +2830,7 @@ enum {
# define R500_ALU_RGBA_OP_SOP (10 << 0)
# define R500_ALU_RGBA_OP_MDH (11 << 0)
# define R500_ALU_RGBA_OP_MDV (12 << 0)
-# define R500_ALU_RGBA_ADDRD(x) (x << 4)
+# define R500_ALU_RGBA_ADDRD(x) ((x) << 4)
# define R500_ALU_RGBA_ADDRD_REL (1 << 11)
# define R500_ALU_RGBA_SEL_C_SHIFT 12
# define R500_ALU_RGBA_SEL_C_SRC0 (0 << 12)
@@ -2906,16 +2957,16 @@ enum {
# define R500_ALU_RGB_OMOD_DIV_4 (5 << 26)
# define R500_ALU_RGB_OMOD_DIV_8 (6 << 26)
# define R500_ALU_RGB_OMOD_DISABLE (7 << 26)
-# define R500_ALU_RGB_TARGET(x) (x << 29)
+# define R500_ALU_RGB_TARGET(x) ((x) << 29)
# define R500_ALU_RGB_WMASK (1 << 31)
#define R500_US_ALU_RGB_ADDR_0 0x9000
-# define R500_RGB_ADDR0(x) (x << 0)
+# define R500_RGB_ADDR0(x) ((x) << 0)
# define R500_RGB_ADDR0_CONST (1 << 8)
# define R500_RGB_ADDR0_REL (1 << 9)
-# define R500_RGB_ADDR1(x) (x << 10)
+# define R500_RGB_ADDR1(x) ((x) << 10)
# define R500_RGB_ADDR1_CONST (1 << 18)
# define R500_RGB_ADDR1_REL (1 << 19)
-# define R500_RGB_ADDR2(x) (x << 20)
+# define R500_RGB_ADDR2(x) ((x) << 20)
# define R500_RGB_ADDR2_CONST (1 << 28)
# define R500_RGB_ADDR2_REL (1 << 29)
# define R500_RGB_SRCP_OP_1_MINUS_2RGB0 (0 << 30)
@@ -2970,19 +3021,19 @@ enum {
/* note that these are 8 bit lengths, despite the offsets, at least for R500 */
#define R500_US_CODE_ADDR 0x4630
-# define R500_US_CODE_START_ADDR(x) (x << 0)
-# define R500_US_CODE_END_ADDR(x) (x << 16)
+# define R500_US_CODE_START_ADDR(x) ((x) << 0)
+# define R500_US_CODE_END_ADDR(x) ((x) << 16)
#define R500_US_CODE_OFFSET 0x4638
-# define R500_US_CODE_OFFSET_ADDR(x) (x << 0)
+# define R500_US_CODE_OFFSET_ADDR(x) ((x) << 0)
#define R500_US_CODE_RANGE 0x4634
-# define R500_US_CODE_RANGE_ADDR(x) (x << 0)
-# define R500_US_CODE_RANGE_SIZE(x) (x << 16)
+# define R500_US_CODE_RANGE_ADDR(x) ((x) << 0)
+# define R500_US_CODE_RANGE_SIZE(x) ((x) << 16)
#define R500_US_CONFIG 0x4600
# define R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO (1 << 1)
#define R500_US_FC_ADDR_0 0xa000
-# define R500_FC_BOOL_ADDR(x) (x << 0)
-# define R500_FC_INT_ADDR(x) (x << 8)
-# define R500_FC_JUMP_ADDR(x) (x << 16)
+# define R500_FC_BOOL_ADDR(x) ((x) << 0)
+# define R500_FC_INT_ADDR(x) ((x) << 8)
+# define R500_FC_JUMP_ADDR(x) ((x) << 16)
# define R500_FC_JUMP_GLOBAL (1 << 31)
#define R500_US_FC_BOOL_CONST 0x4620
# define R500_FC_KBOOL(x) (x)
@@ -3003,8 +3054,8 @@ enum {
# define R500_FC_A_OP_NONE (0 << 6)
# define R500_FC_A_OP_POP (1 << 6)
# define R500_FC_A_OP_PUSH (2 << 6)
-# define R500_FC_JUMP_FUNC(x) (x << 8)
-# define R500_FC_B_POP_CNT(x) (x << 16)
+# define R500_FC_JUMP_FUNC(x) ((x) << 8)
+# define R500_FC_B_POP_CNT(x) ((x) << 16)
# define R500_FC_B_OP0_NONE (0 << 24)
# define R500_FC_B_OP0_DECR (1 << 24)
# define R500_FC_B_OP0_INCR (2 << 24)
@@ -3013,14 +3064,14 @@ enum {
# define R500_FC_B_OP1_INCR (2 << 26)
# define R500_FC_IGNORE_UNCOVERED (1 << 28)
#define R500_US_FC_INT_CONST_0 0x4c00
-# define R500_FC_INT_CONST_KR(x) (x << 0)
-# define R500_FC_INT_CONST_KG(x) (x << 8)
-# define R500_FC_INT_CONST_KB(x) (x << 16)
+# define R500_FC_INT_CONST_KR(x) ((x) << 0)
+# define R500_FC_INT_CONST_KG(x) ((x) << 8)
+# define R500_FC_INT_CONST_KB(x) ((x) << 16)
/* _0 through _15 */
#define R500_US_FORMAT0_0 0x4640
-# define R500_FORMAT_TXWIDTH(x) (x << 0)
-# define R500_FORMAT_TXHEIGHT(x) (x << 11)
-# define R500_FORMAT_TXDEPTH(x) (x << 22)
+# define R500_FORMAT_TXWIDTH(x) ((x) << 0)
+# define R500_FORMAT_TXHEIGHT(x) ((x) << 11)
+# define R500_FORMAT_TXDEPTH(x) ((x) << 22)
/* _0 through _3 */
#define R500_US_OUT_FMT_0 0x46a4
# define R500_OUT_FMT_C4_8 (0 << 0)
@@ -3061,12 +3112,12 @@ enum {
# define R500_C3_SEL_R (1 << 14)
# define R500_C3_SEL_G (2 << 14)
# define R500_C3_SEL_B (3 << 14)
-# define R500_OUT_SIGN(x) (x << 16)
+# define R500_OUT_SIGN(x) ((x) << 16)
# define R500_ROUND_ADJ (1 << 20)
#define R500_US_PIXSIZE 0x4604
# define R500_PIX_SIZE(x) (x)
#define R500_US_TEX_ADDR_0 0x9800
-# define R500_TEX_SRC_ADDR(x) (x << 0)
+# define R500_TEX_SRC_ADDR(x) ((x) << 0)
# define R500_TEX_SRC_ADDR_REL (1 << 7)
# define R500_TEX_SRC_S_SWIZ_R (0 << 8)
# define R500_TEX_SRC_S_SWIZ_G (1 << 8)
@@ -3084,7 +3135,7 @@ enum {
# define R500_TEX_SRC_Q_SWIZ_G (1 << 14)
# define R500_TEX_SRC_Q_SWIZ_B (2 << 14)
# define R500_TEX_SRC_Q_SWIZ_A (3 << 14)
-# define R500_TEX_DST_ADDR(x) (x << 16)
+# define R500_TEX_DST_ADDR(x) ((x) << 16)
# define R500_TEX_DST_ADDR_REL (1 << 23)
# define R500_TEX_DST_R_SWIZ_R (0 << 24)
# define R500_TEX_DST_R_SWIZ_G (1 << 24)
@@ -3103,7 +3154,7 @@ enum {
# define R500_TEX_DST_A_SWIZ_B (2 << 30)
# define R500_TEX_DST_A_SWIZ_A (3 << 30)
#define R500_US_TEX_ADDR_DXDY_0 0xa000
-# define R500_DX_ADDR(x) (x << 0)
+# define R500_DX_ADDR(x) ((x) << 0)
# define R500_DX_ADDR_REL (1 << 7)
# define R500_DX_S_SWIZ_R (0 << 8)
# define R500_DX_S_SWIZ_G (1 << 8)
@@ -3121,7 +3172,7 @@ enum {
# define R500_DX_Q_SWIZ_G (1 << 14)
# define R500_DX_Q_SWIZ_B (2 << 14)
# define R500_DX_Q_SWIZ_A (3 << 14)
-# define R500_DY_ADDR(x) (x << 16)
+# define R500_DY_ADDR(x) ((x) << 16)
# define R500_DY_ADDR_REL (1 << 17)
# define R500_DY_S_SWIZ_R (0 << 24)
# define R500_DY_S_SWIZ_G (1 << 24)
@@ -3140,7 +3191,7 @@ enum {
# define R500_DY_Q_SWIZ_B (2 << 30)
# define R500_DY_Q_SWIZ_A (3 << 30)
#define R500_US_TEX_INST_0 0x9000
-# define R500_TEX_ID(x) (x << 16)
+# define R500_TEX_ID(x) ((x) << 16)
# define R500_TEX_INST_NOP (0 << 22)
# define R500_TEX_INST_LD (1 << 22)
# define R500_TEX_INST_TEXKILL (2 << 22)
@@ -3159,6 +3210,9 @@ enum {
# define R300_W_SRC_RAS (1 << 2)
+/* Packet0 field ordering to write all values to the same reg */
+#define RADEON_ONE_REG_WR (1 << 15)
+
/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
* Two parameter dwords:
* 0. VAP_VTX_FMT: The first parameter is not written to hardware
diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c
index f9266e44c1..b5ddfdc9f8 100644
--- a/src/mesa/drivers/dri/r300/r300_render.c
+++ b/src/mesa/drivers/dri/r300/r300_render.c
@@ -50,6 +50,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
* no bugs...
*/
+#include "r300_render.h"
+
#include "main/glheader.h"
#include "main/state.h"
#include "main/imports.h"
@@ -62,20 +64,19 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "vbo/vbo.h"
+#include "vbo/vbo_split.h"
#include "tnl/tnl.h"
#include "tnl/t_vp_build.h"
#include "radeon_reg.h"
#include "radeon_macros.h"
-#include "radeon_ioctl.h"
-#include "radeon_state.h"
#include "r300_context.h"
#include "r300_ioctl.h"
#include "r300_state.h"
#include "r300_reg.h"
#include "r300_tex.h"
#include "r300_emit.h"
-#include "r300_fragprog.h"
-extern int future_hw_tcl_on;
+#include "r300_fragprog_common.h"
+#include "r300_swtcl.h"
/**
* \brief Convert a OpenGL primitive type into a R300 primitive type.
@@ -172,96 +173,167 @@ int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim)
return num_verts - verts_off;
}
-static void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts)
+static void r300FireEB(r300ContextPtr rmesa, int vertex_count, int type, int offset)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct r300_dma_region *rvb = &rmesa->state.elt_dma;
- void *out;
-
- if (r300IsGartMemory(rmesa, elts, n_elts * 4)) {
- rvb->address = rmesa->radeon.radeonScreen->gartTextures.map;
- rvb->start = ((char *)elts) - rvb->address;
- rvb->aos_offset =
- rmesa->radeon.radeonScreen->gart_texture_offset +
- rvb->start;
- return;
- } else if (r300IsGartMemory(rmesa, elts, 1)) {
- WARN_ONCE("Pointer not within GART memory!\n");
- _mesa_exit(-1);
+ BATCH_LOCALS(&rmesa->radeon);
+ int size;
+
+ /* offset is in indices */
+ BEGIN_BATCH(10);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0);
+ if (rmesa->ind_buf.is_32bit) {
+ /* convert to bytes */
+ offset *= 4;
+ size = vertex_count;
+ OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
+ (vertex_count << 16) | type |
+ R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
+ } else {
+ /* convert to bytes */
+ offset *= 2;
+ size = (vertex_count + 1) >> 1;
+ OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
+ (vertex_count << 16) | type);
}
- r300AllocDmaRegion(rmesa, rvb, n_elts * 4, 4);
- rvb->aos_offset = GET_START(rvb);
-
- out = rvb->address + rvb->start;
- memcpy(out, elts, n_elts * 4);
-}
-
-static void r300FireEB(r300ContextPtr rmesa, unsigned long addr,
- int vertex_count, int type)
-{
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
-
- start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0), 0);
- e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count << 16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
-
- start_packet3(CP_PACKET3(R300_PACKET3_INDX_BUFFER, 2), 2);
- e32(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
- (R300_VAP_PORT_IDX0 >> 2));
- e32(addr);
- e32(vertex_count);
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
+ OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
+ (R300_VAP_PORT_IDX0 >> 2));
+ OUT_BATCH_RELOC(0, rmesa->ind_buf.bo, rmesa->ind_buf.bo_offset + offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ OUT_BATCH(size);
+ } else {
+ OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
+ OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
+ (R300_VAP_PORT_IDX0 >> 2));
+ OUT_BATCH(rmesa->ind_buf.bo_offset + offset);
+ OUT_BATCH(size);
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->ind_buf.bo, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ }
+ END_BATCH();
}
static void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset)
{
+ BATCH_LOCALS(&rmesa->radeon);
+ uint32_t voffset;
int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
int i;
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
- if (RADEON_DEBUG & DEBUG_VERTS)
+ if (RADEON_DEBUG & RADEON_VERTS)
fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr,
offset);
- start_packet3(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1), sz - 1);
- e32(nr);
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ BEGIN_BATCH(sz+2+(nr * 2));
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1);
+ OUT_BATCH(nr);
+
+ for (i = 0; i + 1 < nr; i += 2) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
+ (rmesa->radeon.tcl.aos[i].stride << 8) |
+ (rmesa->radeon.tcl.aos[i + 1].components << 16) |
+ (rmesa->radeon.tcl.aos[i + 1].stride << 24));
+
+ voffset = rmesa->radeon.tcl.aos[i + 0].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
+ OUT_BATCH_RELOC(voffset,
+ rmesa->radeon.tcl.aos[i].bo,
+ voffset,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ voffset = rmesa->radeon.tcl.aos[i + 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
+ OUT_BATCH_RELOC(voffset,
+ rmesa->radeon.tcl.aos[i+1].bo,
+ voffset,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ }
- for (i = 0; i + 1 < nr; i += 2) {
- e32((rmesa->state.aos[i].aos_size << 0) |
- (rmesa->state.aos[i].aos_stride << 8) |
- (rmesa->state.aos[i + 1].aos_size << 16) |
- (rmesa->state.aos[i + 1].aos_stride << 24));
+ if (nr & 1) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
+ (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
+ voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
+ OUT_BATCH_RELOC(voffset,
+ rmesa->radeon.tcl.aos[nr - 1].bo,
+ voffset,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ }
+ END_BATCH();
+ } else {
- e32(rmesa->state.aos[i].aos_offset + offset * 4 * rmesa->state.aos[i].aos_stride);
- e32(rmesa->state.aos[i + 1].aos_offset + offset * 4 * rmesa->state.aos[i + 1].aos_stride);
- }
+ BEGIN_BATCH(sz+2+(nr * 2));
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1);
+ OUT_BATCH(nr);
+
+ for (i = 0; i + 1 < nr; i += 2) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
+ (rmesa->radeon.tcl.aos[i].stride << 8) |
+ (rmesa->radeon.tcl.aos[i + 1].components << 16) |
+ (rmesa->radeon.tcl.aos[i + 1].stride << 24));
+
+ voffset = rmesa->radeon.tcl.aos[i + 0].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
+ OUT_BATCH(voffset);
+ voffset = rmesa->radeon.tcl.aos[i + 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
+ OUT_BATCH(voffset);
+ }
- if (nr & 1) {
- e32((rmesa->state.aos[nr - 1].aos_size << 0) |
- (rmesa->state.aos[nr - 1].aos_stride << 8));
- e32(rmesa->state.aos[nr - 1].aos_offset + offset * 4 * rmesa->state.aos[nr - 1].aos_stride);
+ if (nr & 1) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
+ (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
+ voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
+ OUT_BATCH(voffset);
+ }
+ for (i = 0; i + 1 < nr; i += 2) {
+ voffset = rmesa->radeon.tcl.aos[i + 0].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.aos[i+0].bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ voffset = rmesa->radeon.tcl.aos[i + 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.aos[i+1].bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ }
+ if (nr & 1) {
+ voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.aos[nr-1].bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ }
+ END_BATCH();
}
+
}
static void r300FireAOS(r300ContextPtr rmesa, int vertex_count, int type)
{
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
+ BATCH_LOCALS(&rmesa->radeon);
- start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0), 0);
- e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16) | type);
+ r300_emit_scissor(rmesa->radeon.glCtx);
+ BEGIN_BATCH(3);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
+ OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16) | type);
+ END_BATCH();
}
-static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx,
- int start, int end, int prim)
+void r300RunRenderPrimitive(GLcontext * ctx, int start, int end, int prim)
{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ BATCH_LOCALS(&rmesa->radeon);
int type, num_verts;
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *vb = &tnl->vb;
type = r300PrimitiveType(rmesa, prim);
num_verts = r300NumVerts(rmesa, end - start, prim);
@@ -269,190 +341,161 @@ static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx,
if (type < 0 || num_verts <= 0)
return;
- if (vb->Elts) {
- if (num_verts > 65535) {
- /* not implemented yet */
- WARN_ONCE("Too many elts\n");
+ if (rmesa->ind_buf.bo) {
+ GLuint first, incr, offset = 0;
+
+ if (!split_prim_inplace(prim & PRIM_MODE_MASK, &first, &incr) &&
+ num_verts > 65500) {
+ WARN_ONCE("Fixme: can't handle spliting prim %d\n", prim);
return;
}
- /* Note: The following is incorrect, but it's the best I can do
- * without a major refactoring of how DMA memory is handled.
- * The problem: Ensuring that both vertex arrays *and* index
- * arrays are at the right position, and then ensuring that
- * the LOAD_VBPNTR, DRAW_INDX and INDX_BUFFER packets are emitted
- * at once.
- *
- * So why is the following incorrect? Well, it seems like
- * allocating the index array might actually evict the vertex
- * arrays. *sigh*
- */
- r300EmitElts(ctx, vb->Elts, num_verts);
- r300EmitAOS(rmesa, rmesa->state.aos_count, start);
- r300FireEB(rmesa, rmesa->state.elt_dma.aos_offset, num_verts, type);
- } else {
- r300EmitAOS(rmesa, rmesa->state.aos_count, start);
- r300FireAOS(rmesa, num_verts, type);
- }
-}
-static GLboolean r300RunRender(GLcontext * ctx,
- struct tnl_pipeline_stage *stage)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- int i;
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *vb = &tnl->vb;
-
-
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
- r300UpdateShaders(rmesa);
- if (r300EmitArrays(ctx))
- return GL_TRUE;
-
- r300UpdateShaderStates(rmesa);
-
- r300EmitCacheFlush(rmesa);
- r300EmitState(rmesa);
-
- for (i = 0; i < vb->PrimitiveCount; i++) {
- GLuint prim = _tnl_translate_prim(&vb->Primitive[i]);
- GLuint start = vb->Primitive[i].start;
- GLuint end = vb->Primitive[i].start + vb->Primitive[i].count;
- r300RunRenderPrimitive(rmesa, ctx, start, end, prim);
- }
-
- r300EmitCacheFlush(rmesa);
+ r300EmitAOS(rmesa, rmesa->radeon.tcl.aos_count, 0);
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ OUT_BATCH_REGSEQ(R300_VAP_VF_MAX_VTX_INDX, 1);
+ OUT_BATCH(rmesa->radeon.tcl.aos[0].count);
+ END_BATCH();
+ }
-#ifdef USER_BUFFERS
- r300UseArrays(ctx);
-#endif
+ r300_emit_scissor(rmesa->radeon.glCtx);
+ while (num_verts > 0) {
+ int nr;
+ int align;
+
+ nr = MIN2(num_verts, 65535);
+ nr -= (nr - first) % incr;
+
+ /* get alignment for IB correct */
+ if (nr != num_verts) {
+ do {
+ align = nr * (rmesa->ind_buf.is_32bit ? 4 : 2);
+ if (align % 4)
+ nr -= incr;
+ } while(align % 4);
+ if (nr <= 0) {
+ WARN_ONCE("did the impossible happen? we never aligned nr to dword\n");
+ return;
+ }
+
+ }
+ r300FireEB(rmesa, nr, type, offset);
- r300ReleaseArrays(ctx);
+ num_verts -= nr;
+ offset += nr;
+ }
- return GL_FALSE;
-}
+ } else {
+ GLuint first, incr, offset = 0;
-#define FALLBACK_IF(expr) \
- do { \
- if (expr) { \
- if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
- WARN_ONCE("Software fallback:%s\n", \
- #expr); \
- return R300_FALLBACK_RAST; \
- } \
- } while(0)
-
-static int r300Fallback(GLcontext * ctx)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- /* Do we need to use new-style shaders?
- * Also is there a better way to do this? */
- if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
- struct r500_fragment_program *fp = (struct r500_fragment_program *)
- (char *)ctx->FragmentProgram._Current;
- if (fp) {
- if (!fp->translated) {
- r500TranslateFragmentShader(r300, fp);
- FALLBACK_IF(!fp->translated);
- }
+ if (!split_prim_inplace(prim & PRIM_MODE_MASK, &first, &incr) &&
+ num_verts > 65535) {
+ WARN_ONCE("Fixme: can't handle spliting prim %d\n", prim);
+ return;
}
- } else {
- struct r300_fragment_program *fp = (struct r300_fragment_program *)
- (char *)ctx->FragmentProgram._Current;
- if (fp) {
- if (!fp->translated) {
- r300TranslateFragmentShader(r300, fp);
- FALLBACK_IF(!fp->translated);
- }
+ r300_emit_scissor(rmesa->radeon.glCtx);
+ while (num_verts > 0) {
+ int nr;
+ nr = MIN2(num_verts, 65535);
+ nr -= (nr - first) % incr;
+ r300EmitAOS(rmesa, rmesa->radeon.tcl.aos_count, start + offset);
+ r300FireAOS(rmesa, nr, type);
+ num_verts -= nr;
+ offset += nr;
}
}
-
- FALLBACK_IF(ctx->RenderMode != GL_RENDER);
-
- FALLBACK_IF(ctx->Stencil._TestTwoSide
- && (ctx->Stencil.Ref[0] != ctx->Stencil.Ref[1]
- || ctx->Stencil.ValueMask[0] !=
- ctx->Stencil.ValueMask[1]
- || ctx->Stencil.WriteMask[0] !=
- ctx->Stencil.WriteMask[1]));
-
- if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
- FALLBACK_IF(ctx->Point.PointSprite);
-
- if (!r300->disable_lowimpact_fallback) {
- FALLBACK_IF(ctx->Polygon.StippleFlag);
- FALLBACK_IF(ctx->Multisample._Enabled);
- FALLBACK_IF(ctx->Line.StippleFlag);
- FALLBACK_IF(ctx->Line.SmoothFlag);
- FALLBACK_IF(ctx->Point.SmoothFlag);
- }
-
- return R300_FALLBACK_NONE;
+ COMMIT_BATCH();
}
-static GLboolean r300RunNonTCLRender(GLcontext * ctx,
- struct tnl_pipeline_stage *stage)
+static const char *getFallbackString(uint32_t bit)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
-
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (r300Fallback(ctx) >= R300_FALLBACK_RAST)
- return GL_TRUE;
-
- if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
- return GL_TRUE;
-
- return r300RunRender(ctx, stage);
+ switch (bit) {
+ case R300_FALLBACK_VERTEX_PROGRAM :
+ return "vertex program";
+ case R300_FALLBACK_LINE_SMOOTH:
+ return "smooth lines";
+ case R300_FALLBACK_POINT_SMOOTH:
+ return "smooth points";
+ case R300_FALLBACK_POLYGON_SMOOTH:
+ return "smooth polygons";
+ case R300_FALLBACK_LINE_STIPPLE:
+ return "line stipple";
+ case R300_FALLBACK_POLYGON_STIPPLE:
+ return "polygon stipple";
+ case R300_FALLBACK_STENCIL_TWOSIDE:
+ return "two-sided stencil";
+ case R300_FALLBACK_RENDER_MODE:
+ return "render mode != GL_RENDER";
+ case R300_FALLBACK_FRAGMENT_PROGRAM:
+ return "fragment program";
+ case R300_FALLBACK_AOS_LIMIT:
+ return "aos limit";
+ case R300_FALLBACK_INVALID_BUFFERS:
+ return "invalid buffers";
+ default:
+ return "unknown";
+ }
}
-static GLboolean r300RunTCLRender(GLcontext * ctx,
- struct tnl_pipeline_stage *stage)
+void r300SwitchFallback(GLcontext *ctx, uint32_t bit, GLboolean mode)
{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct r300_vertex_program *vp;
+ uint32_t old_fallback = rmesa->fallback;
+ static uint32_t fallback_warn = 0;
+
+ if (mode) {
+ if ((fallback_warn & bit) == 0) {
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
+ _mesa_fprintf(stderr, "WARNING! Falling back to software for %s\n", getFallbackString(bit));
+ fallback_warn |= bit;
+ }
+ rmesa->fallback |= bit;
+
+ /* update only if we change from no tcl fallbacks to some tcl fallbacks */
+ if (rmesa->options.hw_tcl_enabled) {
+ if (((old_fallback & R300_TCL_FALLBACK_MASK) == 0) &&
+ ((bit & R300_TCL_FALLBACK_MASK) > 0)) {
+ R300_STATECHANGE(rmesa, vap_cntl_status);
+ rmesa->hw.vap_cntl_status.cmd[1] |= R300_VAP_TCL_BYPASS;
+ }
+ }
- hw_tcl_on = future_hw_tcl_on;
+ /* update only if we change from no raster fallbacks to some raster fallbacks */
+ if (((old_fallback & R300_RASTER_FALLBACK_MASK) == 0) &&
+ ((bit & R300_RASTER_FALLBACK_MASK) > 0)) {
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ radeon_firevertices(&rmesa->radeon);
+ rmesa->radeon.swtcl.RenderIndex = ~0;
+ _swsetup_Wakeup( ctx );
+ }
+ } else {
+ rmesa->fallback &= ~bit;
- if (hw_tcl_on == GL_FALSE)
- return GL_TRUE;
+ /* update only if we have disabled all tcl fallbacks */
+ if (rmesa->options.hw_tcl_enabled) {
+ if ((old_fallback & R300_RASTER_FALLBACK_MASK) == bit) {
+ R300_STATECHANGE(rmesa, vap_cntl_status);
+ rmesa->hw.vap_cntl_status.cmd[1] &= ~R300_VAP_TCL_BYPASS;
+ }
+ }
- if (r300Fallback(ctx) >= R300_FALLBACK_TCL) {
- hw_tcl_on = GL_FALSE;
- return GL_TRUE;
- }
+ /* update only if we have disabled all raster fallbacks */
+ if ((old_fallback & R300_RASTER_FALLBACK_MASK) == bit) {
+ _swrast_flush( ctx );
- r300UpdateShaders(rmesa);
+ tnl->Driver.Render.Start = r300RenderStart;
+ tnl->Driver.Render.Finish = r300RenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = r300RenderPrimitive;
+ tnl->Driver.Render.ResetLineStipple = r300ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+ tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+ tnl->Driver.Render.Interp = _tnl_interp;
- vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
- if (vp->native == GL_FALSE) {
- hw_tcl_on = GL_FALSE;
- return GL_TRUE;
+ _tnl_invalidate_vertex_state( ctx, ~0 );
+ _tnl_invalidate_vertices( ctx, ~0 );
+ }
}
- return r300RunRender(ctx, stage);
}
-
-const struct tnl_pipeline_stage _r300_render_stage = {
- "r300 Hardware Rasterization",
- NULL,
- NULL,
- NULL,
- NULL,
- r300RunNonTCLRender
-};
-
-const struct tnl_pipeline_stage _r300_tcl_stage = {
- "r300 Hardware Transform, Clipping and Lighting",
- NULL,
- NULL,
- NULL,
- NULL,
- r300RunTCLRender
-};
diff --git a/src/mesa/drivers/dri/r300/r300_render.h b/src/mesa/drivers/dri/r300/r300_render.h
new file mode 100644
index 0000000000..ec785474a6
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_render.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __R300_RENDER_H__
+#define __R300_RENDER_H__
+
+#include "main/mtypes.h"
+
+#define R300_FALLBACK_VERTEX_PROGRAM (1 << 0)
+#define R300_TCL_FALLBACK_MASK 0x0000ffff
+
+#define R300_FALLBACK_LINE_SMOOTH (1 << 16)
+#define R300_FALLBACK_POINT_SMOOTH (1 << 17)
+#define R300_FALLBACK_POLYGON_SMOOTH (1 << 18)
+#define R300_FALLBACK_LINE_STIPPLE (1 << 19)
+#define R300_FALLBACK_POLYGON_STIPPLE (1 << 20)
+#define R300_FALLBACK_STENCIL_TWOSIDE (1 << 21)
+#define R300_FALLBACK_RENDER_MODE (1 << 22)
+#define R300_FALLBACK_FRAGMENT_PROGRAM (1 << 23)
+#define R300_FALLBACK_AOS_LIMIT (1 << 30)
+#define R300_FALLBACK_INVALID_BUFFERS (1 << 31)
+#define R300_RASTER_FALLBACK_MASK 0xffff0000
+
+#define MASK_XYZW (R300_WRITE_ENA_X | R300_WRITE_ENA_Y | R300_WRITE_ENA_Z | R300_WRITE_ENA_W)
+#define MASK_X R300_WRITE_ENA_X
+#define MASK_Y R300_WRITE_ENA_Y
+#define MASK_Z R300_WRITE_ENA_Z
+#define MASK_W R300_WRITE_ENA_W
+
+#if SWIZZLE_X != R300_INPUT_ROUTE_SELECT_X || \
+ SWIZZLE_Y != R300_INPUT_ROUTE_SELECT_Y || \
+ SWIZZLE_Z != R300_INPUT_ROUTE_SELECT_Z || \
+ SWIZZLE_W != R300_INPUT_ROUTE_SELECT_W || \
+ SWIZZLE_ZERO != R300_INPUT_ROUTE_SELECT_ZERO || \
+ SWIZZLE_ONE != R300_INPUT_ROUTE_SELECT_ONE
+#error Cannot change these!
+#endif
+
+extern const struct tnl_pipeline_stage _r300_render_stage;
+
+extern void r300SwitchFallback(GLcontext *ctx, uint32_t bit, GLboolean mode);
+
+extern void r300RunRenderPrimitive(GLcontext * ctx, int start, int end, int prim);
+
+#endif
diff --git a/src/mesa/drivers/dri/r300/r300_shader.c b/src/mesa/drivers/dri/r300/r300_shader.c
index f30fd986e0..a4f9db13ec 100644
--- a/src/mesa/drivers/dri/r300/r300_shader.c
+++ b/src/mesa/drivers/dri/r300/r300_shader.c
@@ -1,47 +1,79 @@
+/*
+ * Copyright 2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
#include "main/glheader.h"
#include "shader/program.h"
#include "tnl/tnl.h"
#include "r300_context.h"
-#include "r300_fragprog.h"
+#include "r300_fragprog_common.h"
+
+static void freeFragProgCache(GLcontext *ctx, struct r300_fragment_program_cont *cache)
+{
+ struct r300_fragment_program *tmp, *fp = cache->progs;
+
+ while (fp) {
+ tmp = fp->next;
+ rc_constants_destroy(&fp->code.constants);
+ _mesa_free(fp);
+ fp = tmp;
+ }
+}
+
+static void freeVertProgCache(GLcontext *ctx, struct r300_vertex_program_cont *cache)
+{
+ struct r300_vertex_program *tmp, *vp = cache->progs;
+
+ while (vp) {
+ tmp = vp->next;
+ rc_constants_destroy(&vp->code.constants);
+ _mesa_reference_vertprog(ctx, &vp->Base, NULL);
+ _mesa_free(vp);
+ vp = tmp;
+ }
+}
static struct gl_program *r300NewProgram(GLcontext * ctx, GLenum target,
GLuint id)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct r300_vertex_program_cont *vp;
- struct r300_fragment_program *r300_fp;
- struct r500_fragment_program *r500_fp;
+ struct r300_fragment_program_cont *fp;
switch (target) {
case GL_VERTEX_STATE_PROGRAM_NV:
case GL_VERTEX_PROGRAM_ARB:
vp = CALLOC_STRUCT(r300_vertex_program_cont);
- return _mesa_init_vertex_program(ctx, &vp->mesa_program,
- target, id);
- case GL_FRAGMENT_PROGRAM_ARB:
- if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
- r500_fp = CALLOC_STRUCT(r500_fragment_program);
- r500_fp->ctx = ctx;
- return _mesa_init_fragment_program(ctx, &r500_fp->mesa_program,
- target, id);
- } else {
- r300_fp = CALLOC_STRUCT(r300_fragment_program);
- return _mesa_init_fragment_program(ctx, &r300_fp->mesa_program,
- target, id);
- }
+ return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id);
case GL_FRAGMENT_PROGRAM_NV:
- if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
- r500_fp = CALLOC_STRUCT(r500_fragment_program);
- return _mesa_init_fragment_program(ctx, &r500_fp->mesa_program,
- target, id);
- } else {
- r300_fp = CALLOC_STRUCT(r300_fragment_program);
- return _mesa_init_fragment_program(ctx, &r300_fp->mesa_program,
- target, id);
- }
+ case GL_FRAGMENT_PROGRAM_ARB:
+ fp = CALLOC_STRUCT(r300_fragment_program_cont);
+ return _mesa_init_fragment_program(ctx, &fp->Base, target, id);
+
default:
_mesa_problem(ctx, "Bad target in r300NewProgram");
}
@@ -51,26 +83,35 @@ static struct gl_program *r300NewProgram(GLcontext * ctx, GLenum target,
static void r300DeleteProgram(GLcontext * ctx, struct gl_program *prog)
{
+ struct r300_vertex_program_cont *vp = (struct r300_vertex_program_cont *)prog;
+ struct r300_fragment_program_cont *fp = (struct r300_fragment_program_cont *)prog;
+
+ switch (prog->Target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ freeVertProgCache(ctx, vp);
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ freeFragProgCache(ctx, fp);
+ break;
+ }
+
_mesa_delete_program(ctx, prog);
}
static void
r300ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct r300_vertex_program_cont *vp = (void *)prog;
- struct r300_fragment_program *r300_fp = (struct r300_fragment_program *)prog;
- struct r500_fragment_program *r500_fp = (struct r500_fragment_program *)prog;
+ struct r300_vertex_program_cont *vp = (struct r300_vertex_program_cont *)prog;
+ struct r300_fragment_program_cont *fp = (struct r300_fragment_program_cont *)prog;
switch (target) {
case GL_VERTEX_PROGRAM_ARB:
+ freeVertProgCache(ctx, vp);
vp->progs = NULL;
break;
case GL_FRAGMENT_PROGRAM_ARB:
- if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
- r500_fp->translated = GL_FALSE;
- else
- r300_fp->translated = GL_FALSE;
+ freeFragProgCache(ctx, fp);
+ fp->progs = NULL;
break;
}
@@ -81,7 +122,15 @@ r300ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog)
static GLboolean
r300IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
{
- return GL_TRUE;
+ if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ struct r300_fragment_program *fp = r300SelectAndTranslateFragmentShader(ctx);
+
+ return !fp->error;
+ } else {
+ struct r300_vertex_program *vp = r300SelectAndTranslateVertexShader(ctx);
+
+ return !vp->error;
+ }
}
void r300InitShaderFuncs(struct dd_function_table *functions)
diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c
index a63dbac343..3060f49aaf 100644
--- a/src/mesa/drivers/dri/r300/r300_state.c
+++ b/src/mesa/drivers/dri/r300/r300_state.c
@@ -42,6 +42,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/macros.h"
#include "main/context.h"
#include "main/dd.h"
+#include "main/framebuffer.h"
#include "main/simple_list.h"
#include "main/api_arrayelt.h"
#include "main/texformat.h"
@@ -52,22 +53,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "shader/prog_statevars.h"
#include "vbo/vbo.h"
#include "tnl/tnl.h"
+#include "tnl/t_vp_build.h"
-#include "radeon_ioctl.h"
-#include "radeon_state.h"
#include "r300_context.h"
#include "r300_ioctl.h"
#include "r300_state.h"
#include "r300_reg.h"
#include "r300_emit.h"
-#include "r300_fragprog.h"
#include "r300_tex.h"
+#include "r300_fragprog_common.h"
+#include "r300_render.h"
+#include "r300_vertprog.h"
#include "drirenderbuffer.h"
-extern int future_hw_tcl_on;
-extern void _tnl_UpdateFixedFunctionProgram(GLcontext * ctx);
-
static void r300BlendColor(GLcontext * ctx, const GLfloat cf[4])
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
@@ -366,12 +365,13 @@ static void r300ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
GLint *ip;
/* no VAP UCP on non-TCL chipsets */
- if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
+ if (!rmesa->options.hw_tcl_enabled)
return;
p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
ip = (GLint *)ctx->Transform._ClipUserPlane[p];
+ R300_STATECHANGE( rmesa, vap_flush );
R300_STATECHANGE( rmesa, vpucp[p] );
rmesa->hw.vpucp[p].cmd[R300_VPUCP_X] = ip[0];
rmesa->hw.vpucp[p].cmd[R300_VPUCP_Y] = ip[1];
@@ -385,7 +385,7 @@ static void r300SetClipPlaneState(GLcontext * ctx, GLenum cap, GLboolean state)
GLuint p;
/* no VAP UCP on non-TCL chipsets */
- if (!(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
+ if (!r300->options.hw_tcl_enabled)
return;
p = cap - GL_CLIP_PLANE0;
@@ -433,6 +433,10 @@ static void r300UpdateCulling(GLcontext * ctx)
break;
}
+ /* Winding is inverted when rendering to FBO */
+ if (ctx->DrawBuffer && ctx->DrawBuffer->Name)
+ val ^= R300_FRONT_FACE_CW;
+
R300_STATECHANGE(r300, cul);
r300->hw.cul.cmd[R300_CUL_CULL] = val;
}
@@ -453,26 +457,22 @@ static GLboolean current_fragment_program_writes_depth(GLcontext* ctx)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
- if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
- struct r300_fragment_program *fp = (struct r300_fragment_program *)
- (char *)ctx->FragmentProgram._Current;
- return (fp && fp->WritesDepth);
- } else {
- struct r500_fragment_program* fp =
- (struct r500_fragment_program*)(char*)
- ctx->FragmentProgram._Current;
- return (fp && fp->writes_depth);
- }
+ return ctx->FragmentProgram._Current && r300->selected_fp->code.writes_depth;
}
static void r300SetEarlyZState(GLcontext * ctx)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
GLuint topZ = R300_ZTOP_ENABLE;
+ GLuint w_fmt, fgdepthsrc;
if (ctx->Color.AlphaEnabled && ctx->Color.AlphaFunc != GL_ALWAYS)
topZ = R300_ZTOP_DISABLE;
- if (current_fragment_program_writes_depth(ctx))
+ else if (current_fragment_program_writes_depth(ctx))
+ topZ = R300_ZTOP_DISABLE;
+ else if (ctx->FragmentProgram._Current && ctx->FragmentProgram._Current->UsesKill)
+ topZ = R300_ZTOP_DISABLE;
+ else if (r300->radeon.query.current)
topZ = R300_ZTOP_DISABLE;
if (topZ != r300->hw.zstencil_format.cmd[2]) {
@@ -483,6 +483,26 @@ static void r300SetEarlyZState(GLcontext * ctx)
R300_STATECHANGE(r300, zstencil_format);
r300->hw.zstencil_format.cmd[2] = topZ;
}
+
+ /* w_fmt value is set to get best performance
+ * see p.130 R5xx 3D acceleration guide v1.3 */
+ if (current_fragment_program_writes_depth(ctx)) {
+ fgdepthsrc = R300_FG_DEPTH_SRC_SHADER;
+ w_fmt = R300_W_FMT_W24 | R300_W_SRC_US;
+ } else {
+ fgdepthsrc = R300_FG_DEPTH_SRC_SCAN;
+ w_fmt = R300_W_FMT_W0 | R300_W_SRC_US;
+ }
+
+ if (w_fmt != r300->hw.us_out_fmt.cmd[5]) {
+ R300_STATECHANGE(r300, us_out_fmt);
+ r300->hw.us_out_fmt.cmd[5] = w_fmt;
+ }
+
+ if (fgdepthsrc != r300->hw.fg_depth_src.cmd[1]) {
+ R300_STATECHANGE(r300, fg_depth_src);
+ r300->hw.fg_depth_src.cmd[1] = fgdepthsrc;
+ }
}
static void r300SetAlphaState(GLcontext * ctx)
@@ -533,8 +553,6 @@ static void r300SetAlphaState(GLcontext * ctx)
R300_STATECHANGE(r300, at);
r300->hw.at.cmd[R300_AT_ALPHA_TEST] = pp_misc;
r300->hw.at.cmd[R300_AT_UNKNOWN] = 0;
-
- r300SetEarlyZState(ctx);
}
static void r300AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
@@ -572,7 +590,9 @@ static void r300SetDepthState(GLcontext * ctx)
r300ContextPtr r300 = R300_CONTEXT(ctx);
R300_STATECHANGE(r300, zs);
- r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_STENCIL_ENABLE|R300_STENCIL_FRONT_BACK;
+ r300->hw.zs.cmd[R300_ZS_CNTL_0] &= (R300_STENCIL_ENABLE |
+ R300_STENCIL_FRONT_BACK |
+ R500_STENCIL_REFMASK_FRONT_BACK);
r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_Z_FUNC_SHIFT);
if (ctx->Depth.Test) {
@@ -582,15 +602,40 @@ static void r300SetDepthState(GLcontext * ctx)
r300->hw.zs.cmd[R300_ZS_CNTL_1] |=
translate_func(ctx->Depth.Func) << R300_Z_FUNC_SHIFT;
}
+}
- r300SetEarlyZState(ctx);
+static void r300CatchStencilFallback(GLcontext *ctx)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ const unsigned back = ctx->Stencil._BackFace;
+
+ if (rmesa->radeon.radeonScreen->kernel_mm &&
+ (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)) {
+ r300SwitchFallback(ctx, R300_FALLBACK_STENCIL_TWOSIDE, GL_FALSE);
+ } else if (ctx->Stencil._Enabled &&
+ (ctx->Stencil.Ref[0] != ctx->Stencil.Ref[back]
+ || ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[back]
+ || ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[back])) {
+ r300SwitchFallback(ctx, R300_FALLBACK_STENCIL_TWOSIDE, GL_TRUE);
+ } else {
+ r300SwitchFallback(ctx, R300_FALLBACK_STENCIL_TWOSIDE, GL_FALSE);
+ }
}
static void r300SetStencilState(GLcontext * ctx, GLboolean state)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
+ GLboolean hw_stencil = GL_FALSE;
+
+ r300CatchStencilFallback(ctx);
- if (r300->state.stencil.hw_stencil) {
+ if (ctx->DrawBuffer) {
+ struct radeon_renderbuffer *rrbStencil
+ = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
+ hw_stencil = (rrbStencil && rrbStencil->bo);
+ }
+
+ if (hw_stencil) {
R300_STATECHANGE(r300, zs);
if (state) {
r300->hw.zs.cmd[R300_ZS_CNTL_0] |=
@@ -599,10 +644,6 @@ static void r300SetStencilState(GLcontext * ctx, GLboolean state)
r300->hw.zs.cmd[R300_ZS_CNTL_0] &=
~R300_STENCIL_ENABLE;
}
- } else {
-#if R200_MERGED
- FALLBACK(&r300->radeon, RADEON_FALLBACK_STENCIL, state);
-#endif
}
}
@@ -730,139 +771,17 @@ static void r300ColorMask(GLcontext * ctx,
}
/* =============================================================
- * Fog
- */
-static void r300Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- union {
- int i;
- float f;
- } fogScale, fogStart;
-
- (void)param;
-
- fogScale.i = r300->hw.fogp.cmd[R300_FOGP_SCALE];
- fogStart.i = r300->hw.fogp.cmd[R300_FOGP_START];
-
- switch (pname) {
- case GL_FOG_MODE:
- switch (ctx->Fog.Mode) {
- case GL_LINEAR:
- R300_STATECHANGE(r300, fogs);
- r300->hw.fogs.cmd[R300_FOGS_STATE] =
- (r300->hw.fogs.
- cmd[R300_FOGS_STATE] & ~R300_FG_FOG_BLEND_FN_MASK) |
- R300_FG_FOG_BLEND_FN_LINEAR;
-
- if (ctx->Fog.Start == ctx->Fog.End) {
- fogScale.f = -1.0;
- fogStart.f = 1.0;
- } else {
- fogScale.f =
- 1.0 / (ctx->Fog.End - ctx->Fog.Start);
- fogStart.f =
- -ctx->Fog.Start / (ctx->Fog.End -
- ctx->Fog.Start);
- }
- break;
- case GL_EXP:
- R300_STATECHANGE(r300, fogs);
- r300->hw.fogs.cmd[R300_FOGS_STATE] =
- (r300->hw.fogs.
- cmd[R300_FOGS_STATE] & ~R300_FG_FOG_BLEND_FN_MASK) |
- R300_FG_FOG_BLEND_FN_EXP;
- fogScale.f = 0.0933 * ctx->Fog.Density;
- fogStart.f = 0.0;
- break;
- case GL_EXP2:
- R300_STATECHANGE(r300, fogs);
- r300->hw.fogs.cmd[R300_FOGS_STATE] =
- (r300->hw.fogs.
- cmd[R300_FOGS_STATE] & ~R300_FG_FOG_BLEND_FN_MASK) |
- R300_FG_FOG_BLEND_FN_EXP2;
- fogScale.f = 0.3 * ctx->Fog.Density;
- fogStart.f = 0.0;
- default:
- return;
- }
- break;
- case GL_FOG_DENSITY:
- switch (ctx->Fog.Mode) {
- case GL_EXP:
- fogScale.f = 0.0933 * ctx->Fog.Density;
- fogStart.f = 0.0;
- break;
- case GL_EXP2:
- fogScale.f = 0.3 * ctx->Fog.Density;
- fogStart.f = 0.0;
- default:
- break;
- }
- break;
- case GL_FOG_START:
- case GL_FOG_END:
- if (ctx->Fog.Mode == GL_LINEAR) {
- if (ctx->Fog.Start == ctx->Fog.End) {
- fogScale.f = -1.0;
- fogStart.f = 1.0;
- } else {
- fogScale.f =
- 1.0 / (ctx->Fog.End - ctx->Fog.Start);
- fogStart.f =
- -ctx->Fog.Start / (ctx->Fog.End -
- ctx->Fog.Start);
- }
- }
- break;
- case GL_FOG_COLOR:
- R300_STATECHANGE(r300, fogc);
- r300->hw.fogc.cmd[R300_FOGC_R] =
- (GLuint) (ctx->Fog.Color[0] * 1023.0F) & 0x3FF;
- r300->hw.fogc.cmd[R300_FOGC_G] =
- (GLuint) (ctx->Fog.Color[1] * 1023.0F) & 0x3FF;
- r300->hw.fogc.cmd[R300_FOGC_B] =
- (GLuint) (ctx->Fog.Color[2] * 1023.0F) & 0x3FF;
- break;
- case GL_FOG_COORD_SRC:
- break;
- default:
- return;
- }
-
- if (fogScale.i != r300->hw.fogp.cmd[R300_FOGP_SCALE] ||
- fogStart.i != r300->hw.fogp.cmd[R300_FOGP_START]) {
- R300_STATECHANGE(r300, fogp);
- r300->hw.fogp.cmd[R300_FOGP_SCALE] = fogScale.i;
- r300->hw.fogp.cmd[R300_FOGP_START] = fogStart.i;
- }
-}
-
-static void r300SetFogState(GLcontext * ctx, GLboolean state)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
-
- R300_STATECHANGE(r300, fogs);
- if (state) {
- r300->hw.fogs.cmd[R300_FOGS_STATE] |= R300_FG_FOG_BLEND_ENABLE;
-
- r300Fogfv(ctx, GL_FOG_MODE, NULL);
- r300Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density);
- r300Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start);
- r300Fogfv(ctx, GL_FOG_END, &ctx->Fog.End);
- r300Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color);
- } else {
- r300->hw.fogs.cmd[R300_FOGS_STATE] &= ~R300_FG_FOG_BLEND_ENABLE;
- }
-}
-
-/* =============================================================
* Point state
*/
static void r300PointSize(GLcontext * ctx, GLfloat size)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
- /* same size limits for AA, non-AA points */
+
+ /* We need to clamp to user defined range here, because
+ * the HW clamping happens only for per vertex point size. */
+ size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
+
+ /* same size limits for AA, non-AA points */
size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
R300_STATECHANGE(r300, ps);
@@ -955,35 +874,33 @@ static void r300ShadeModel(GLcontext * ctx, GLenum mode)
R300_STATECHANGE(rmesa, shade);
rmesa->hw.shade.cmd[1] = 0x00000002;
+ R300_STATECHANGE(rmesa, shade2);
switch (mode) {
case GL_FLAT:
- rmesa->hw.shade.cmd[2] = R300_RE_SHADE_MODEL_FLAT;
+ rmesa->hw.shade2.cmd[1] = R300_RE_SHADE_MODEL_FLAT;
break;
case GL_SMOOTH:
- rmesa->hw.shade.cmd[2] = R300_RE_SHADE_MODEL_SMOOTH;
+ rmesa->hw.shade2.cmd[1] = R300_RE_SHADE_MODEL_SMOOTH;
break;
default:
return;
}
- rmesa->hw.shade.cmd[3] = 0x00000000;
- rmesa->hw.shade.cmd[4] = 0x00000000;
+ rmesa->hw.shade2.cmd[2] = 0x00000000;
+ rmesa->hw.shade2.cmd[3] = 0x00000000;
}
static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face,
GLenum func, GLint ref, GLuint mask)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- GLuint refmask =
- (((ctx->Stencil.
- Ref[0] & 0xff) << R300_STENCILREF_SHIFT) | ((ctx->
- Stencil.
- ValueMask
- [0] &
- 0xff)
- <<
- R300_STENCILMASK_SHIFT));
-
+ GLuint refmask;
GLuint flag;
+ const unsigned back = ctx->Stencil._BackFace;
+
+ r300CatchStencilFallback(ctx);
+
+ refmask = ((ctx->Stencil.Ref[0] & 0xff) << R300_STENCILREF_SHIFT)
+ | ((ctx->Stencil.ValueMask[0] & 0xff) << R300_STENCILMASK_SHIFT);
R300_STATECHANGE(rmesa, zs);
rmesa->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_STENCIL_FRONT_BACK;
@@ -1000,17 +917,31 @@ static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face,
rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
(flag << R300_S_FRONT_FUNC_SHIFT);
- if (ctx->Stencil._TestTwoSide)
- flag = translate_func(ctx->Stencil.Function[1]);
+ flag = translate_func(ctx->Stencil.Function[back]);
rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
(flag << R300_S_BACK_FUNC_SHIFT);
rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= refmask;
+
+ if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_0] |= R500_STENCIL_REFMASK_FRONT_BACK;
+ R300_STATECHANGE(rmesa, zsb);
+ refmask = ((ctx->Stencil.Ref[back] & 0xff) << R300_STENCILREF_SHIFT)
+ | ((ctx->Stencil.ValueMask[back] & 0xff) << R300_STENCILMASK_SHIFT);
+
+ rmesa->hw.zsb.cmd[R300_ZSB_CNTL_0] &=
+ ~((R300_STENCILREF_MASK << R300_STENCILREF_SHIFT) |
+ (R300_STENCILREF_MASK << R300_STENCILMASK_SHIFT));
+ rmesa->hw.zsb.cmd[R300_ZSB_CNTL_0] |= refmask;
+ }
}
static void r300StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ const unsigned back = ctx->Stencil._BackFace;
+
+ r300CatchStencilFallback(ctx);
R300_STATECHANGE(rmesa, zs);
rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &=
@@ -1020,12 +951,22 @@ static void r300StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask)
(ctx->Stencil.
WriteMask[0] & R300_STENCILREF_MASK) <<
R300_STENCILWRITEMASK_SHIFT;
+ if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+ R300_STATECHANGE(rmesa, zsb);
+ rmesa->hw.zsb.cmd[R300_ZSB_CNTL_0] |=
+ (ctx->Stencil.
+ WriteMask[back] & R300_STENCILREF_MASK) <<
+ R300_STENCILWRITEMASK_SHIFT;
+ }
}
static void r300StencilOpSeparate(GLcontext * ctx, GLenum face,
GLenum fail, GLenum zfail, GLenum zpass)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ const unsigned back = ctx->Stencil._BackFace;
+
+ r300CatchStencilFallback(ctx);
R300_STATECHANGE(rmesa, zs);
/* It is easier to mask what's left.. */
@@ -1042,51 +983,45 @@ static void r300StencilOpSeparate(GLcontext * ctx, GLenum face,
| (translate_stencil_op(ctx->Stencil.ZPassFunc[0]) <<
R300_S_FRONT_ZPASS_OP_SHIFT);
- if (ctx->Stencil._TestTwoSide) {
- rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
- (translate_stencil_op(ctx->Stencil.FailFunc[1]) <<
- R300_S_BACK_SFAIL_OP_SHIFT)
- | (translate_stencil_op(ctx->Stencil.ZFailFunc[1]) <<
- R300_S_BACK_ZFAIL_OP_SHIFT)
- | (translate_stencil_op(ctx->Stencil.ZPassFunc[1]) <<
- R300_S_BACK_ZPASS_OP_SHIFT);
- } else {
- rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
- (translate_stencil_op(ctx->Stencil.FailFunc[0]) <<
- R300_S_BACK_SFAIL_OP_SHIFT)
- | (translate_stencil_op(ctx->Stencil.ZFailFunc[0]) <<
- R300_S_BACK_ZFAIL_OP_SHIFT)
- | (translate_stencil_op(ctx->Stencil.ZPassFunc[0]) <<
- R300_S_BACK_ZPASS_OP_SHIFT);
- }
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+ (translate_stencil_op(ctx->Stencil.FailFunc[back]) <<
+ R300_S_BACK_SFAIL_OP_SHIFT)
+ | (translate_stencil_op(ctx->Stencil.ZFailFunc[back]) <<
+ R300_S_BACK_ZFAIL_OP_SHIFT)
+ | (translate_stencil_op(ctx->Stencil.ZPassFunc[back]) <<
+ R300_S_BACK_ZPASS_OP_SHIFT);
}
/* =============================================================
* Window position and viewport transformation
*/
-/*
- * To correctly position primitives:
- */
-#define SUBPIXEL_X 0.125
-#define SUBPIXEL_Y 0.125
-
static void r300UpdateWindow(GLcontext * ctx)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
const GLfloat *v = ctx->Viewport._WindowMap.m;
+ const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+ const GLboolean render_to_fbo = (ctx->DrawBuffer->Name != 0);
+ GLfloat y_scale, y_bias;
+
+ if (render_to_fbo) {
+ y_scale = 1.0;
+ y_bias = 0;
+ } else {
+ y_scale = -1.0;
+ y_bias = yoffset;
+ }
GLfloat sx = v[MAT_SX];
- GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
- GLfloat sy = -v[MAT_SY];
- GLfloat ty = (-v[MAT_TY]) + yoffset + SUBPIXEL_Y;
- GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
- GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
+ GLfloat tx = v[MAT_TX] + xoffset;
+ GLfloat sy = v[MAT_SY] * y_scale;
+ GLfloat ty = (v[MAT_TY] * y_scale) + y_bias;
+ GLfloat sz = v[MAT_SZ] * depthScale;
+ GLfloat tz = v[MAT_TZ] * depthScale;
- R300_FIREVERTICES(rmesa);
R300_STATECHANGE(rmesa, vpt);
rmesa->hw.vpt.cmd[R300_VPT_XSCALE] = r300PackFloat32(sx);
@@ -1105,6 +1040,8 @@ static void r300Viewport(GLcontext * ctx, GLint x, GLint y,
* values, or keep the originals hanging around.
*/
r300UpdateWindow(ctx);
+
+ radeon_viewport(ctx, x, y, width, height);
}
static void r300DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
@@ -1115,13 +1052,13 @@ static void r300DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
void r300UpdateViewportOffset(GLcontext * ctx)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = ((radeonContextPtr) rmesa)->dri.drawable;
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
GLfloat xoffset = (GLfloat) dPriv->x;
GLfloat yoffset = (GLfloat) dPriv->y + dPriv->h;
const GLfloat *v = ctx->Viewport._WindowMap.m;
- GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
- GLfloat ty = (-v[MAT_TY]) + yoffset + SUBPIXEL_Y;
+ GLfloat tx = v[MAT_TX] + xoffset;
+ GLfloat ty = (-v[MAT_TY]) + yoffset;
if (rmesa->hw.vpt.cmd[R300_VPT_XOFFSET] != r300PackFloat32(tx) ||
rmesa->hw.vpt.cmd[R300_VPT_YOFFSET] != r300PackFloat32(ty)) {
@@ -1138,138 +1075,26 @@ void r300UpdateViewportOffset(GLcontext * ctx)
}
/**
- * Tell the card where to render (offset, pitch).
- * Effected by glDrawBuffer, etc
- */
-void r300UpdateDrawBuffer(GLcontext * ctx)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- r300ContextPtr r300 = rmesa;
- struct gl_framebuffer *fb = ctx->DrawBuffer;
- driRenderbuffer *drb;
-
- if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
- /* draw to front */
- drb =
- (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].
- Renderbuffer;
- } else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
- /* draw to back */
- drb =
- (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].
- Renderbuffer;
- } else {
- /* drawing to multiple buffers, or none */
- return;
- }
-
- assert(drb);
- assert(drb->flippedPitch);
-
- R300_STATECHANGE(rmesa, cb);
-
- r300->hw.cb.cmd[R300_CB_OFFSET] = drb->flippedOffset + //r300->radeon.state.color.drawOffset +
- r300->radeon.radeonScreen->fbLocation;
- r300->hw.cb.cmd[R300_CB_PITCH] = drb->flippedPitch; //r300->radeon.state.color.drawPitch;
-
- if (r300->radeon.radeonScreen->cpp == 4)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888;
- else
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565;
-
- if (r300->radeon.sarea->tiling_enabled)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE;
-#if 0
- R200_STATECHANGE(rmesa, ctx);
-
- /* Note: we used the (possibly) page-flipped values */
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
- = ((drb->flippedOffset + rmesa->r200Screen->fbLocation)
- & R200_COLOROFFSET_MASK);
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
-
- if (rmesa->sarea->tiling_enabled) {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |=
- R200_COLOR_TILE_ENABLE;
- }
-#endif
-}
-
-static void
-r300FetchStateParameter(GLcontext * ctx,
- const gl_state_index state[STATE_LENGTH],
- GLfloat * value)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
-
- switch (state[0]) {
- case STATE_INTERNAL:
- switch (state[1]) {
- case STATE_R300_WINDOW_DIMENSION:
- value[0] = r300->radeon.dri.drawable->w * 0.5f; /* width*0.5 */
- value[1] = r300->radeon.dri.drawable->h * 0.5f; /* height*0.5 */
- value[2] = 0.5F; /* for moving range [-1 1] -> [0 1] */
- value[3] = 1.0F; /* not used */
- break;
-
- case STATE_R300_TEXRECT_FACTOR:{
- struct gl_texture_object *t =
- ctx->Texture.Unit[state[2]].CurrentRect;
-
- if (t && t->Image[0][t->BaseLevel]) {
- struct gl_texture_image *image =
- t->Image[0][t->BaseLevel];
- value[0] = 1.0 / image->Width2;
- value[1] = 1.0 / image->Height2;
- } else {
- value[0] = 1.0;
- value[1] = 1.0;
- }
- value[2] = 1.0;
- value[3] = 1.0;
- break;
- }
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-}
-
-/**
* Update R300's own internal state parameters.
* For now just STATE_R300_WINDOW_DIMENSION
*/
-void r300UpdateStateParameters(GLcontext * ctx, GLuint new_state)
+static void r300UpdateStateParameters(GLcontext * ctx, GLuint new_state)
{
- struct r300_fragment_program *fp;
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct gl_program_parameter_list *paramList;
- GLuint i;
- if (!(new_state & (_NEW_BUFFERS | _NEW_PROGRAM)))
+ if (!(new_state & (_NEW_BUFFERS | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)))
return;
- fp = (struct r300_fragment_program *)ctx->FragmentProgram._Current;
- if (!fp)
+ if (!ctx->FragmentProgram._Current || !rmesa->selected_fp)
return;
- paramList = fp->mesa_program.Base.Parameters;
+ paramList = ctx->FragmentProgram._Current->Base.Parameters;
if (!paramList)
return;
- for (i = 0; i < paramList->NumParameters; i++) {
- if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
- r300FetchStateParameter(ctx,
- paramList->Parameters[i].
- StateIndexes,
- paramList->ParameterValues[i]);
- }
- }
+ _mesa_load_state_parameters(ctx, paramList);
}
/* =============================================================
@@ -1376,9 +1201,7 @@ static void r300SetupFragmentShaderTextures(GLcontext *ctx, int *tmu_mappings)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
int i;
- struct r300_fragment_program *fp = (struct r300_fragment_program *)
- (char *)ctx->FragmentProgram._Current;
- struct r300_fragment_program_code *code = &fp->code;
+ struct r300_fragment_program_code *code = &r300->selected_fp->code.code.r300;
R300_STATECHANGE(r300, fpt);
@@ -1412,15 +1235,15 @@ static void r300SetupFragmentShaderTextures(GLcontext *ctx, int *tmu_mappings)
}
r300->hw.fpt.cmd[R300_FPT_CMD_0] =
- cmdpacket0(R300_US_TEX_INST_0, code->tex.length);
+ cmdpacket0(r300->radeon.radeonScreen,
+ R300_US_TEX_INST_0, code->tex.length);
}
static void r500SetupFragmentShaderTextures(GLcontext *ctx, int *tmu_mappings)
{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
int i;
- struct r500_fragment_program *fp = (struct r500_fragment_program *)
- (char *)ctx->FragmentProgram._Current;
- struct r500_fragment_program_code *code = &fp->code;
+ struct r500_fragment_program_code *code = &r300->selected_fp->code.code.r500;
/* find all the texture instructions and relocate the texture units */
for (i = 0; i < code->inst_end + 1; i++) {
@@ -1460,16 +1283,15 @@ static GLuint translate_lod_bias(GLfloat bias)
return (((GLuint)b) << R300_LOD_BIAS_SHIFT) & R300_LOD_BIAS_MASK;
}
+
static void r300SetupTextures(GLcontext * ctx)
{
int i, mtu;
- struct r300_tex_obj *t;
+ struct radeon_tex_obj *t;
r300ContextPtr r300 = R300_CONTEXT(ctx);
int hw_tmu = 0;
int last_hw_tmu = -1; /* -1 translates into no setup costs for fields */
int tmu_mappings[R300_MAX_TEXTURE_UNITS] = { -1, };
- struct r300_fragment_program *fp = (struct r300_fragment_program *)
- (char *)ctx->FragmentProgram._Current;
R300_STATECHANGE(r300, txe);
R300_STATECHANGE(r300, tex.filter);
@@ -1484,7 +1306,7 @@ static void r300SetupTextures(GLcontext * ctx)
r300->hw.txe.cmd[R300_TXE_ENABLE] = 0x0;
mtu = r300->radeon.glCtx->Const.MaxTextureUnits;
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr, "mtu=%d\n", mtu);
if (mtu > R300_MAX_TEXTURE_UNITS) {
@@ -1497,24 +1319,19 @@ static void r300SetupTextures(GLcontext * ctx)
/* We cannot let disabled tmu offsets pass DRM */
for (i = 0; i < mtu; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled) {
-
-#if 0 /* Enables old behaviour */
- hw_tmu = i;
-#endif
tmu_mappings[i] = hw_tmu;
- t = r300->state.texture.unit[i].texobj;
- /* XXX questionable fix for bug 9170: */
+ t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
if (!t)
continue;
- if ((t->format & 0xffffff00) == 0xffffff00) {
+ if ((t->pp_txformat & 0xffffff00) == 0xffffff00) {
WARN_ONCE
("unknown texture format (entry %x) encountered. Help me !\n",
- t->format & 0xff);
+ t->pp_txformat & 0xff);
}
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr,
"Activating texture unit %d\n", i);
@@ -1522,29 +1339,28 @@ static void r300SetupTextures(GLcontext * ctx)
r300->hw.tex.filter.cmd[R300_TEX_VALUE_0 +
hw_tmu] =
- gen_fixed_filter(t->filter) | (hw_tmu << 28);
+ gen_fixed_filter(t->pp_txfilter) | (hw_tmu << 28);
/* Note: There is a LOD bias per texture unit and a LOD bias
* per texture object. We add them here to get the correct behaviour.
* (The per-texture object LOD bias was introduced in OpenGL 1.4
* and is not present in the EXT_texture_object extension).
*/
r300->hw.tex.filter_1.cmd[R300_TEX_VALUE_0 + hw_tmu] =
- t->filter_1 |
- translate_lod_bias(ctx->Texture.Unit[i].LodBias + t->base.tObj->LodBias);
+ t->pp_txfilter_1 |
+ translate_lod_bias(ctx->Texture.Unit[i].LodBias + t->base.LodBias);
r300->hw.tex.size.cmd[R300_TEX_VALUE_0 + hw_tmu] =
- t->size;
+ t->pp_txsize;
r300->hw.tex.format.cmd[R300_TEX_VALUE_0 +
- hw_tmu] = t->format;
+ hw_tmu] = t->pp_txformat;
r300->hw.tex.pitch.cmd[R300_TEX_VALUE_0 + hw_tmu] =
- t->pitch_reg;
- r300->hw.tex.offset.cmd[R300_TEX_VALUE_0 +
- hw_tmu] = t->offset;
+ t->pp_txpitch;
+ r300->hw.textures[hw_tmu] = t;
- if (t->offset & R300_TXO_MACRO_TILE) {
+ if (t->tile_bits & R300_TXO_MACRO_TILE) {
WARN_ONCE("macro tiling enabled!\n");
}
- if (t->offset & R300_TXO_MICRO_TILE) {
+ if (t->tile_bits & R300_TXO_MICRO_TILE) {
WARN_ONCE("micro tiling enabled!\n");
}
@@ -1560,40 +1376,48 @@ static void r300SetupTextures(GLcontext * ctx)
}
}
+ /* R3xx and R4xx chips require that the texture unit corresponding to
+ * KIL instructions is really enabled.
+ *
+ * We do some fakery here and in the state atom emit logic to enable
+ * the texture without tripping up the CS checker in the kernel.
+ */
+ if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
+ if (ctx->FragmentProgram._Current->UsesKill && last_hw_tmu < 0) {
+ last_hw_tmu++;
+
+ r300->hw.txe.cmd[R300_TXE_ENABLE] |= 1;
+
+ r300->hw.tex.border_color.cmd[R300_TEX_VALUE_0] = 0;
+ r300->hw.tex.chroma_key.cmd[R300_TEX_VALUE_0] = 0;
+ r300->hw.tex.filter.cmd[R300_TEX_VALUE_0] = 0;
+ r300->hw.tex.filter_1.cmd[R300_TEX_VALUE_0] = 0;
+ r300->hw.tex.size.cmd[R300_TEX_VALUE_0] = 0; /* 1x1 texture */
+ r300->hw.tex.format.cmd[R300_TEX_VALUE_0] = 0; /* A8 format */
+ r300->hw.tex.pitch.cmd[R300_TEX_VALUE_0] = 0;
+ }
+ }
+
r300->hw.tex.filter.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_FILTER0_0, last_hw_tmu + 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_FILTER0_0, last_hw_tmu + 1);
r300->hw.tex.filter_1.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_FILTER1_0, last_hw_tmu + 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_FILTER1_0, last_hw_tmu + 1);
r300->hw.tex.size.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_SIZE_0, last_hw_tmu + 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_SIZE_0, last_hw_tmu + 1);
r300->hw.tex.format.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_FORMAT_0, last_hw_tmu + 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_FORMAT_0, last_hw_tmu + 1);
r300->hw.tex.pitch.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_FORMAT2_0, last_hw_tmu + 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_FORMAT2_0, last_hw_tmu + 1);
r300->hw.tex.offset.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_OFFSET_0, last_hw_tmu + 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_OFFSET_0, last_hw_tmu + 1);
r300->hw.tex.chroma_key.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_CHROMA_KEY_0, last_hw_tmu + 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_CHROMA_KEY_0, last_hw_tmu + 1);
r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_BORDER_COLOR_0, last_hw_tmu + 1);
+ cmdpacket0(r300->radeon.radeonScreen, R300_TX_BORDER_COLOR_0, last_hw_tmu + 1);
- if (!fp) /* should only happenen once, just after context is created */
- return;
-
- if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
- if (fp->mesa_program.UsesKill && last_hw_tmu < 0) {
- // The KILL operation requires the first texture unit
- // to be enabled.
- r300->hw.txe.cmd[R300_TXE_ENABLE] |= 1;
- r300->hw.tex.filter.cmd[R300_TEX_VALUE_0] = 0;
- r300->hw.tex.filter.cmd[R300_TEX_CMD_0] =
- cmdpacket0(R300_TX_FILTER0_0, 1);
- }
- r300SetupFragmentShaderTextures(ctx, tmu_mappings);
- } else
- r500SetupFragmentShaderTextures(ctx, tmu_mappings);
+ r300->vtbl.SetupFragmentShaderTextures(ctx, tmu_mappings);
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr, "TX_ENABLE: %08x last_hw_tmu=%d\n",
r300->hw.txe.cmd[R300_TXE_ENABLE], last_hw_tmu);
}
@@ -1610,124 +1434,44 @@ union r300_outputs_written {
static void r300SetupRSUnit(GLcontext * ctx)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
- /* I'm still unsure if these are needed */
- GLuint interp_col[8];
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
union r300_outputs_written OutputsWritten;
GLuint InputsRead;
int fp_reg, high_rr;
- int col_interp_nr;
- int rs_tex_count = 0, rs_col_count = 0;
- int i, count;
+ int col_ip, tex_ip;
+ int rs_tex_count = 0;
+ int i, col_fmt, hw_tcl_on;
- memset(interp_col, 0, sizeof(interp_col));
+ hw_tcl_on = r300->options.hw_tcl_enabled;
if (hw_tcl_on)
- OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten;
+ OutputsWritten.vp_outputs = r300->selected_vp->code.OutputsWritten;
else
- RENDERINPUTS_COPY(OutputsWritten.index_bitset, r300->state.render_inputs_bitset);
+ RENDERINPUTS_COPY(OutputsWritten.index_bitset, r300->render_inputs_bitset);
- if (ctx->FragmentProgram._Current)
- InputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
- else {
- fprintf(stderr, "No ctx->FragmentProgram._Current!!\n");
- return; /* This should only ever happen once.. */
- }
+ InputsRead = r300->selected_fp->InputsRead;
R300_STATECHANGE(r300, ri);
R300_STATECHANGE(r300, rc);
R300_STATECHANGE(r300, rr);
- fp_reg = col_interp_nr = high_rr = 0;
-
- r300->hw.rr.cmd[R300_RR_INST_1] = 0;
-
- if (InputsRead & FRAG_BIT_WPOS) {
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
- if (!(InputsRead & (FRAG_BIT_TEX0 << i)))
- break;
-
- if (i == ctx->Const.MaxTextureUnits) {
- fprintf(stderr, "\tno free texcoord found...\n");
- _mesa_exit(-1);
- }
-
- InputsRead |= (FRAG_BIT_TEX0 << i);
- InputsRead &= ~FRAG_BIT_WPOS;
- }
-
- if (InputsRead & FRAG_BIT_COL0) {
- count = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->size;
- interp_col[0] |= R300_RS_COL_PTR(rs_col_count);
- if (count == 3)
- interp_col[0] |= R300_RS_COL_FMT(R300_RS_COL_FMT_RGB1);
- rs_col_count += count;
- }
- else
- interp_col[0] = R300_RS_COL_FMT(R300_RS_COL_FMT_0001);
-
- if (InputsRead & FRAG_BIT_COL1) {
- count = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->size;
- if (count == 3)
- interp_col[1] |= R300_RS_COL_FMT(R300_RS_COL_FMT_RGB0);
- interp_col[1] |= R300_RS_COL_PTR(1);
- rs_col_count += count;
- }
-
- if (InputsRead & FRAG_BIT_FOGC) {
- /* XXX FIX THIS
- * Just turn off the bit for now.
- * Need to do something similar to the color/texcoord inputs.
- */
- InputsRead &= ~FRAG_BIT_FOGC;
- }
+ fp_reg = col_ip = tex_ip = col_fmt = 0;
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- int swiz;
+ r300->hw.rc.cmd[1] = 0;
+ r300->hw.rc.cmd[2] = 0;
+ for (i=0; i<R300_RR_CMDSIZE-1; ++i)
+ r300->hw.rr.cmd[R300_RR_INST_0 + i] = 0;
- /* with TCL we always seem to route 4 components */
- if (hw_tcl_on)
- count = 4;
- else
- count = VB->AttribPtr[_TNL_ATTRIB_TEX(i)]->size;
+ for (i=0; i<R300_RI_CMDSIZE-1; ++i)
+ r300->hw.ri.cmd[R300_RI_INTERP_0 + i] = 0;
- r300->hw.ri.cmd[R300_RI_INTERP_0 + i] = interp_col[i] | rs_tex_count;
- switch(count) {
- case 4: swiz = R300_RS_SEL_S(0) | R300_RS_SEL_T(1) | R300_RS_SEL_R(2) | R300_RS_SEL_Q(3); break;
- case 3: swiz = R300_RS_SEL_S(0) | R300_RS_SEL_T(1) | R300_RS_SEL_R(2) | R300_RS_SEL_Q(R300_RS_SEL_K1); break;
- default:
- case 1:
- case 2: swiz = R300_RS_SEL_S(0) | R300_RS_SEL_T(1) | R300_RS_SEL_R(R300_RS_SEL_K0) | R300_RS_SEL_Q(R300_RS_SEL_K1); break;
- };
-
- r300->hw.ri.cmd[R300_RI_INTERP_0 + i] |= swiz;
-
- r300->hw.rr.cmd[R300_RR_INST_0 + fp_reg] = 0;
- if (InputsRead & (FRAG_BIT_TEX0 << i)) {
-
- rs_tex_count += count;
-
- //assert(r300->state.texture.tc_count != 0);
- r300->hw.rr.cmd[R300_RR_INST_0 + fp_reg] |= R300_RS_INST_TEX_CN_WRITE | i /* source INTERP */
- | (fp_reg << R300_RS_INST_TEX_ADDR_SHIFT);
- high_rr = fp_reg;
-
- /* Passing invalid data here can lock the GPU. */
- if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_TEX0 + i, _TNL_ATTRIB_TEX(i))) {
- InputsRead &= ~(FRAG_BIT_TEX0 << i);
- fp_reg++;
- } else {
- WARN_ONCE("fragprog wants coords for tex%d, vp doesn't provide them!\n", i);
- }
- }
- }
if (InputsRead & FRAG_BIT_COL0) {
if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_COL0, _TNL_ATTRIB_COLOR0)) {
- r300->hw.rr.cmd[R300_RR_INST_0] |= R300_RS_INST_COL_ID(0) | R300_RS_INST_COL_CN_WRITE | (fp_reg++ << R300_RS_INST_COL_ADDR_SHIFT);
+ r300->hw.ri.cmd[R300_RI_INTERP_0 + col_ip] = R300_RS_COL_PTR(col_ip) | R300_RS_COL_FMT(R300_RS_COL_FMT_RGBA);
+ r300->hw.rr.cmd[R300_RR_INST_0 + col_ip] = R300_RS_INST_COL_ID(col_ip) | R300_RS_INST_COL_CN_WRITE | R300_RS_INST_COL_ADDR(fp_reg);
InputsRead &= ~FRAG_BIT_COL0;
- col_interp_nr++;
+ ++col_ip;
+ ++fp_reg;
} else {
WARN_ONCE("fragprog wants col0, vp doesn't provide it\n");
}
@@ -1735,29 +1479,47 @@ static void r300SetupRSUnit(GLcontext * ctx)
if (InputsRead & FRAG_BIT_COL1) {
if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_COL1, _TNL_ATTRIB_COLOR1)) {
- r300->hw.rr.cmd[R300_RR_INST_1] |= R300_RS_INST_COL_ID(1) | R300_RS_INST_COL_CN_WRITE | (fp_reg++ << R300_RS_INST_COL_ADDR_SHIFT);
+ r300->hw.ri.cmd[R300_RI_INTERP_0 + col_ip] = R300_RS_COL_PTR(col_ip) | R300_RS_COL_FMT(R300_RS_COL_FMT_RGBA);
+ r300->hw.rr.cmd[R300_RR_INST_0 + col_ip] = R300_RS_INST_COL_ID(col_ip) | R300_RS_INST_COL_CN_WRITE | R300_RS_INST_COL_ADDR(fp_reg);
InputsRead &= ~FRAG_BIT_COL1;
- if (high_rr < 1)
- high_rr = 1;
- col_interp_nr++;
+ ++col_ip;
+ ++fp_reg;
} else {
WARN_ONCE("fragprog wants col1, vp doesn't provide it\n");
}
}
- /* Need at least one. This might still lock as the values are undefined... */
- if (rs_tex_count == 0 && col_interp_nr == 0) {
- r300->hw.rr.cmd[R300_RR_INST_0] |= R300_RS_INST_COL_ID(0) | R300_RS_INST_COL_CN_WRITE | (fp_reg++ << R300_RS_INST_COL_ADDR_SHIFT);
- col_interp_nr++;
+ /* We always route 4 texcoord components */
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ if (! ( InputsRead & FRAG_BIT_TEX(i) ) )
+ continue;
+
+ if (!R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_TEX0 + i, _TNL_ATTRIB_TEX(i))) {
+ WARN_ONCE("fragprog wants coords for tex%d, vp doesn't provide them!\n", i);
+ continue;
+ }
+
+ r300->hw.ri.cmd[R300_RI_INTERP_0 + tex_ip] |= R300_RS_SEL_S(0) | R300_RS_SEL_T(1) | R300_RS_SEL_R(2) | R300_RS_SEL_Q(3) | R300_RS_TEX_PTR(rs_tex_count);
+ r300->hw.rr.cmd[R300_RR_INST_0 + tex_ip] |= R300_RS_INST_TEX_ID(tex_ip) | R300_RS_INST_TEX_CN_WRITE | R300_RS_INST_TEX_ADDR(fp_reg);
+ InputsRead &= ~(FRAG_BIT_TEX0 << i);
+ rs_tex_count += 4;
+ ++tex_ip;
+ ++fp_reg;
}
- r300->hw.rc.cmd[1] = 0 | (rs_tex_count << R300_IT_COUNT_SHIFT)
- | (col_interp_nr << R300_IC_COUNT_SHIFT)
- | R300_HIRES_EN;
+ /* Setup default color if no color or tex was set */
+ if (rs_tex_count == 0 && col_ip == 0) {
+ r300->hw.rr.cmd[R300_RR_INST_0] = R300_RS_INST_COL_ID(0) | R300_RS_INST_COL_ADDR(0);
+ r300->hw.ri.cmd[R300_RI_INTERP_0] = R300_RS_COL_PTR(0) | R300_RS_COL_FMT(R300_RS_COL_FMT_0001);
+ ++col_ip;
+ }
+
+ high_rr = (col_ip > tex_ip) ? col_ip : tex_ip;
+ r300->hw.rc.cmd[1] |= (rs_tex_count << R300_IT_COUNT_SHIFT) | (col_ip << R300_IC_COUNT_SHIFT) | R300_HIRES_EN;
+ r300->hw.rc.cmd[2] |= high_rr - 1;
- assert(high_rr >= 0);
- r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R300_RS_INST_0, high_rr + 1);
- r300->hw.rc.cmd[2] = high_rr;
+ r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_RS_INST_0, high_rr);
+ r300->hw.ri.cmd[R300_RI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_RS_IP_0, high_rr);
if (InputsRead)
WARN_ONCE("Don't know how to satisfy InputsRead=0x%08x\n", InputsRead);
@@ -1766,128 +1528,44 @@ static void r300SetupRSUnit(GLcontext * ctx)
static void r500SetupRSUnit(GLcontext * ctx)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
- /* I'm still unsure if these are needed */
- GLuint interp_col[8];
union r300_outputs_written OutputsWritten;
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
GLuint InputsRead;
int fp_reg, high_rr;
- int rs_col_count = 0;
- int in_texcoords, col_interp_nr;
- int i, count;
+ int col_ip, tex_ip;
+ int rs_tex_count = 0;
+ int i, col_fmt, hw_tcl_on;
+
+ hw_tcl_on = r300->options.hw_tcl_enabled;
- memset(interp_col, 0, sizeof(interp_col));
if (hw_tcl_on)
- OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten;
+ OutputsWritten.vp_outputs = r300->selected_vp->code.OutputsWritten;
else
- RENDERINPUTS_COPY(OutputsWritten.index_bitset, r300->state.render_inputs_bitset);
+ RENDERINPUTS_COPY(OutputsWritten.index_bitset, r300->render_inputs_bitset);
- if (ctx->FragmentProgram._Current)
- InputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
- else {
- fprintf(stderr, "No ctx->FragmentProgram._Current!!\n");
- return; /* This should only ever happen once.. */
- }
+ InputsRead = r300->selected_fp->InputsRead;
R300_STATECHANGE(r300, ri);
R300_STATECHANGE(r300, rc);
R300_STATECHANGE(r300, rr);
- fp_reg = col_interp_nr = high_rr = in_texcoords = 0;
-
- r300->hw.rr.cmd[R300_RR_INST_1] = 0;
+ fp_reg = col_ip = tex_ip = col_fmt = 0;
- if (InputsRead & FRAG_BIT_WPOS) {
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
- if (!(InputsRead & (FRAG_BIT_TEX0 << i)))
- break;
+ r300->hw.rc.cmd[1] = 0;
+ r300->hw.rc.cmd[2] = 0;
+ for (i=0; i<R300_RR_CMDSIZE-1; ++i)
+ r300->hw.rr.cmd[R300_RR_INST_0 + i] = 0;
- if (i == ctx->Const.MaxTextureUnits) {
- fprintf(stderr, "\tno free texcoord found...\n");
- _mesa_exit(-1);
- }
+ for (i=0; i<R500_RI_CMDSIZE-1; ++i)
+ r300->hw.ri.cmd[R300_RI_INTERP_0 + i] = 0;
- InputsRead |= (FRAG_BIT_TEX0 << i);
- InputsRead &= ~FRAG_BIT_WPOS;
- }
-
- if (InputsRead & FRAG_BIT_COL0) {
- count = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->size;
- interp_col[0] |= R500_RS_COL_PTR(rs_col_count);
- if (count == 3)
- interp_col[0] |= R500_RS_COL_FMT(R300_RS_COL_FMT_RGB1);
- rs_col_count += count;
- }
- else
- interp_col[0] = R500_RS_COL_FMT(R300_RS_COL_FMT_0001);
-
- if (InputsRead & FRAG_BIT_COL1) {
- count = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->size;
- interp_col[1] |= R500_RS_COL_PTR(1);
- if (count == 3)
- interp_col[1] |= R500_RS_COL_FMT(R300_RS_COL_FMT_RGB0);
- rs_col_count += count;
- }
-
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- GLuint swiz = 0;
-
- /* with TCL we always seem to route 4 components */
- if (InputsRead & (FRAG_BIT_TEX0 << i)) {
-
- if (hw_tcl_on)
- count = 4;
- else
- count = VB->AttribPtr[_TNL_ATTRIB_TEX(i)]->size;
-
- /* always have on texcoord */
- swiz |= in_texcoords++ << R500_RS_IP_TEX_PTR_S_SHIFT;
- if (count >= 2)
- swiz |= in_texcoords++ << R500_RS_IP_TEX_PTR_T_SHIFT;
- else
- swiz |= R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_T_SHIFT;
-
- if (count >= 3)
- swiz |= in_texcoords++ << R500_RS_IP_TEX_PTR_R_SHIFT;
- else
- swiz |= R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_R_SHIFT;
-
- if (count == 4)
- swiz |= in_texcoords++ << R500_RS_IP_TEX_PTR_Q_SHIFT;
- else
- swiz |= R500_RS_IP_PTR_K1 << R500_RS_IP_TEX_PTR_Q_SHIFT;
-
- } else
- swiz = (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_S_SHIFT) |
- (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_T_SHIFT) |
- (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_R_SHIFT) |
- (R500_RS_IP_PTR_K1 << R500_RS_IP_TEX_PTR_Q_SHIFT);
-
- r300->hw.ri.cmd[R300_RI_INTERP_0 + i] = interp_col[i] | swiz;
-
- r300->hw.rr.cmd[R300_RR_INST_0 + fp_reg] = 0;
- if (InputsRead & (FRAG_BIT_TEX0 << i)) {
- //assert(r300->state.texture.tc_count != 0);
- r300->hw.rr.cmd[R300_RR_INST_0 + fp_reg] |= R500_RS_INST_TEX_CN_WRITE | i /* source INTERP */
- | (fp_reg << R500_RS_INST_TEX_ADDR_SHIFT);
- high_rr = fp_reg;
-
- /* Passing invalid data here can lock the GPU. */
- if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_TEX0 + i, _TNL_ATTRIB_TEX(i))) {
- InputsRead &= ~(FRAG_BIT_TEX0 << i);
- fp_reg++;
- } else {
- WARN_ONCE("fragprog wants coords for tex%d, vp doesn't provide them!\n", i);
- }
- }
- }
if (InputsRead & FRAG_BIT_COL0) {
if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_COL0, _TNL_ATTRIB_COLOR0)) {
- r300->hw.rr.cmd[R300_RR_INST_0] |= R500_RS_INST_COL_CN_WRITE | (fp_reg++ << R500_RS_INST_COL_ADDR_SHIFT);
+ r300->hw.ri.cmd[R300_RI_INTERP_0 + col_ip] = R500_RS_COL_PTR(col_ip) | R500_RS_COL_FMT(R300_RS_COL_FMT_RGBA);
+ r300->hw.rr.cmd[R300_RR_INST_0 + col_ip] = R500_RS_INST_COL_ID(col_ip) | R500_RS_INST_COL_CN_WRITE | R500_RS_INST_COL_ADDR(fp_reg);
InputsRead &= ~FRAG_BIT_COL0;
- col_interp_nr++;
+ ++col_ip;
+ ++fp_reg;
} else {
WARN_ONCE("fragprog wants col0, vp doesn't provide it\n");
}
@@ -1895,86 +1573,59 @@ static void r500SetupRSUnit(GLcontext * ctx)
if (InputsRead & FRAG_BIT_COL1) {
if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_COL1, _TNL_ATTRIB_COLOR1)) {
- r300->hw.rr.cmd[R300_RR_INST_1] |= (1 << 12) | R500_RS_INST_COL_CN_WRITE | (fp_reg++ << R500_RS_INST_COL_ADDR_SHIFT);
+ r300->hw.ri.cmd[R300_RI_INTERP_0 + col_ip] = R500_RS_COL_PTR(col_ip) | R500_RS_COL_FMT(R300_RS_COL_FMT_RGBA);
+ r300->hw.rr.cmd[R300_RR_INST_0 + col_ip] = R500_RS_INST_COL_ID(col_ip) | R500_RS_INST_COL_CN_WRITE | R500_RS_INST_COL_ADDR(fp_reg);
InputsRead &= ~FRAG_BIT_COL1;
- if (high_rr < 1)
- high_rr = 1;
- col_interp_nr++;
+ ++col_ip;
+ ++fp_reg;
} else {
WARN_ONCE("fragprog wants col1, vp doesn't provide it\n");
}
}
- /* Need at least one. This might still lock as the values are undefined... */
- if (in_texcoords == 0 && col_interp_nr == 0) {
- r300->hw.rr.cmd[R300_RR_INST_0] |= 0 | R500_RS_INST_COL_CN_WRITE | (fp_reg++ << R500_RS_INST_COL_ADDR_SHIFT);
- col_interp_nr++;
- }
-
- r300->hw.rc.cmd[1] = 0 | (in_texcoords << R300_IT_COUNT_SHIFT)
- | (col_interp_nr << R300_IC_COUNT_SHIFT)
- | R300_HIRES_EN;
-
- assert(high_rr >= 0);
- r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R500_RS_INST_0, high_rr + 1);
- r300->hw.rc.cmd[2] = 0xC0 | high_rr;
-
- if (InputsRead)
- WARN_ONCE("Don't know how to satisfy InputsRead=0x%08x\n", InputsRead);
-}
-
-
-
+ /* We always route 4 texcoord components */
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ if (! ( InputsRead & FRAG_BIT_TEX(i) ) )
+ continue;
-#define bump_vpu_count(ptr, new_count) do{\
- drm_r300_cmd_header_t* _p=((drm_r300_cmd_header_t*)(ptr));\
- int _nc=(new_count)/4; \
- assert(_nc < 256); \
- if(_nc>_p->vpu.count)_p->vpu.count=_nc;\
- }while(0)
+ if (!R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_TEX0 + i, _TNL_ATTRIB_TEX(i))) {
+ WARN_ONCE("fragprog wants coords for tex%d, vp doesn't provide them!\n", i);
+ continue;
+ }
-static INLINE void r300SetupVertexProgramFragment(r300ContextPtr r300, int dest, struct r300_vertex_shader_fragment *vsf)
-{
- int i;
+ r300->hw.ri.cmd[R300_RI_INTERP_0 + tex_ip] |= ((rs_tex_count + 0) << R500_RS_IP_TEX_PTR_S_SHIFT) |
+ ((rs_tex_count + 1) << R500_RS_IP_TEX_PTR_T_SHIFT) |
+ ((rs_tex_count + 2) << R500_RS_IP_TEX_PTR_R_SHIFT) |
+ ((rs_tex_count + 3) << R500_RS_IP_TEX_PTR_Q_SHIFT);
- if (vsf->length == 0)
- return;
+ r300->hw.rr.cmd[R300_RR_INST_0 + tex_ip] |= R500_RS_INST_TEX_ID(tex_ip) | R500_RS_INST_TEX_CN_WRITE | R500_RS_INST_TEX_ADDR(fp_reg);
+ InputsRead &= ~(FRAG_BIT_TEX0 << i);
+ rs_tex_count += 4;
+ ++tex_ip;
+ ++fp_reg;
+ }
- if (vsf->length & 0x3) {
- fprintf(stderr, "VERTEX_SHADER_FRAGMENT must have length divisible by 4\n");
- _mesa_exit(-1);
+ /* Setup default color if no color or tex was set */
+ if (rs_tex_count == 0 && col_ip == 0) {
+ r300->hw.rr.cmd[R300_RR_INST_0] = R500_RS_INST_COL_ID(0) | R500_RS_INST_COL_ADDR(0);
+ r300->hw.ri.cmd[R300_RI_INTERP_0] = R500_RS_COL_PTR(0) | R500_RS_COL_FMT(R300_RS_COL_FMT_0001);
+ ++col_ip;
}
- switch ((dest >> 8) & 0xf) {
- case 0:
- R300_STATECHANGE(r300, vpi);
- for (i = 0; i < vsf->length; i++)
- r300->hw.vpi.cmd[R300_VPI_INSTR_0 + i + 4 * (dest & 0xff)] = (vsf->body.d[i]);
- bump_vpu_count(r300->hw.vpi.cmd, vsf->length + 4 * (dest & 0xff));
- break;
+ high_rr = (col_ip > tex_ip) ? col_ip : tex_ip;
+ r300->hw.rc.cmd[1] = (rs_tex_count << R300_IT_COUNT_SHIFT) | (col_ip << R300_IC_COUNT_SHIFT) | R300_HIRES_EN;
+ r300->hw.rc.cmd[2] = 0xC0 | (high_rr - 1);
- case 2:
- R300_STATECHANGE(r300, vpp);
- for (i = 0; i < vsf->length; i++)
- r300->hw.vpp.cmd[R300_VPP_PARAM_0 + i + 4 * (dest & 0xff)] = (vsf->body.d[i]);
- bump_vpu_count(r300->hw.vpp.cmd, vsf->length + 4 * (dest & 0xff));
- break;
- case 4:
- R300_STATECHANGE(r300, vps);
- for (i = 0; i < vsf->length; i++)
- r300->hw.vps.cmd[1 + i + 4 * (dest & 0xff)] = (vsf->body.d[i]);
- bump_vpu_count(r300->hw.vps.cmd, vsf->length + 4 * (dest & 0xff));
- break;
- default:
- fprintf(stderr, "%s:%s don't know how to handle dest %04x\n", __FILE__, __FUNCTION__, dest);
- _mesa_exit(-1);
- }
+ r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R500_RS_INST_0, high_rr);
+ r300->hw.ri.cmd[R300_RI_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R500_RS_IP_0, high_rr);
+
+ if (InputsRead)
+ WARN_ONCE("Don't know how to satisfy InputsRead=0x%08x\n", InputsRead);
}
#define MIN3(a, b, c) ((a) < (b) ? MIN2(a, c) : MIN2(b, c))
-
-static void r300VapCntl(r300ContextPtr rmesa, GLuint input_count,
+void r300VapCntl(r300ContextPtr rmesa, GLuint input_count,
GLuint output_count, GLuint temp_count)
{
int vtx_mem_size;
@@ -1998,7 +1649,7 @@ static void r300VapCntl(r300ContextPtr rmesa, GLuint input_count,
pvs_num_cntrls = MIN2(6, vtx_mem_size/temp_count);
R300_STATECHANGE(rmesa, vap_cntl);
- if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
+ if (rmesa->options.hw_tcl_enabled) {
rmesa->hw.vap_cntl.cmd[R300_VAP_CNTL_INSTR] =
(pvs_num_slots << R300_PVS_NUM_SLOTS_SHIFT) |
(pvs_num_cntrls << R300_PVS_NUM_CNTLRS_SHIFT) |
@@ -2028,114 +1679,6 @@ static void r300VapCntl(r300ContextPtr rmesa, GLuint input_count,
}
-static void r300SetupDefaultVertexProgram(r300ContextPtr rmesa)
-{
- struct r300_vertex_shader_state *prog = &(rmesa->state.vertex_shader);
- GLuint o_reg = 0;
- GLuint i_reg = 0;
- int i;
- int inst_count = 0;
- int param_count = 0;
- int program_end = 0;
-
- for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_MAX; i++) {
- if (rmesa->state.sw_tcl_inputs[i] != -1) {
- prog->program.body.i[program_end + 0] = PVS_OP_DST_OPERAND(VE_MULTIPLY, GL_FALSE, GL_FALSE, o_reg++, VSF_FLAG_ALL, PVS_DST_REG_OUT);
- prog->program.body.i[program_end + 1] = PVS_SRC_OPERAND(rmesa->state.sw_tcl_inputs[i], PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y, PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W, PVS_SRC_REG_INPUT, VSF_FLAG_NONE);
- prog->program.body.i[program_end + 2] = PVS_SRC_OPERAND(rmesa->state.sw_tcl_inputs[i], PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_REG_INPUT, VSF_FLAG_NONE);
- prog->program.body.i[program_end + 3] = PVS_SRC_OPERAND(rmesa->state.sw_tcl_inputs[i], PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_REG_INPUT, VSF_FLAG_NONE);
- program_end += 4;
- i_reg++;
- }
- }
-
- prog->program.length = program_end;
-
- r300SetupVertexProgramFragment(rmesa, R300_PVS_CODE_START,
- &(prog->program));
- inst_count = (prog->program.length / 4) - 1;
-
- r300VapCntl(rmesa, i_reg, o_reg, 0);
-
- R300_STATECHANGE(rmesa, pvs);
- rmesa->hw.pvs.cmd[R300_PVS_CNTL_1] =
- (0 << R300_PVS_FIRST_INST_SHIFT) |
- (inst_count << R300_PVS_XYZW_VALID_INST_SHIFT) |
- (inst_count << R300_PVS_LAST_INST_SHIFT);
- rmesa->hw.pvs.cmd[R300_PVS_CNTL_2] =
- (0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) |
- (param_count << R300_PVS_MAX_CONST_ADDR_SHIFT);
- rmesa->hw.pvs.cmd[R300_PVS_CNTL_3] =
- (inst_count << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
-}
-
-static int bit_count (int x)
-{
- x = ((x & 0xaaaaaaaaU) >> 1) + (x & 0x55555555U);
- x = ((x & 0xccccccccU) >> 2) + (x & 0x33333333U);
- x = (x >> 16) + (x & 0xffff);
- x = ((x & 0xf0f0) >> 4) + (x & 0x0f0f);
- return (x >> 8) + (x & 0x00ff);
-}
-
-static void r300SetupRealVertexProgram(r300ContextPtr rmesa)
-{
- GLcontext *ctx = rmesa->radeon.glCtx;
- struct r300_vertex_program *prog = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
- int inst_count = 0;
- int param_count = 0;
-
- /* FIXME: r300SetupVertexProgramFragment */
- R300_STATECHANGE(rmesa, vpp);
- param_count =
- r300VertexProgUpdateParams(ctx,
- (struct r300_vertex_program_cont *)
- ctx->VertexProgram._Current,
- (float *)&rmesa->hw.vpp.
- cmd[R300_VPP_PARAM_0]);
- bump_vpu_count(rmesa->hw.vpp.cmd, param_count);
- param_count /= 4;
-
- r300SetupVertexProgramFragment(rmesa, R300_PVS_CODE_START, &(prog->program));
- inst_count = (prog->program.length / 4) - 1;
-
- r300VapCntl(rmesa, bit_count(prog->key.InputsRead),
- bit_count(prog->key.OutputsWritten), prog->num_temporaries);
-
- R300_STATECHANGE(rmesa, pvs);
- rmesa->hw.pvs.cmd[R300_PVS_CNTL_1] =
- (0 << R300_PVS_FIRST_INST_SHIFT) |
- (inst_count << R300_PVS_XYZW_VALID_INST_SHIFT) |
- (inst_count << R300_PVS_LAST_INST_SHIFT);
- rmesa->hw.pvs.cmd[R300_PVS_CNTL_2] =
- (0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) |
- (param_count << R300_PVS_MAX_CONST_ADDR_SHIFT);
- rmesa->hw.pvs.cmd[R300_PVS_CNTL_3] =
- (inst_count << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
-}
-
-static void r300SetupVertexProgram(r300ContextPtr rmesa)
-{
- GLcontext *ctx = rmesa->radeon.glCtx;
-
- /* Reset state, in case we don't use something */
- ((drm_r300_cmd_header_t *) rmesa->hw.vpp.cmd)->vpu.count = 0;
- ((drm_r300_cmd_header_t *) rmesa->hw.vpi.cmd)->vpu.count = 0;
- ((drm_r300_cmd_header_t *) rmesa->hw.vps.cmd)->vpu.count = 0;
-
- /* Not sure why this doesnt work...
- 0x400 area might have something to do with pixel shaders as it appears right after pfs programming.
- 0x406 is set to { 0.0, 0.0, 1.0, 0.0 } most of the time but should change with smooth points and in other rare cases. */
- //setup_vertex_shader_fragment(rmesa, 0x406, &unk4);
- if (hw_tcl_on && ((struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx))->translated) {
- r300SetupRealVertexProgram(rmesa);
- } else {
- /* FIXME: This needs to be replaced by vertex shader generation code. */
- r300SetupDefaultVertexProgram(rmesa);
- }
-
-}
-
/**
* Enable/Disable states.
*
@@ -2143,20 +1686,13 @@ static void r300SetupVertexProgram(r300ContextPtr rmesa)
*/
static void r300Enable(GLcontext * ctx, GLenum cap, GLboolean state)
{
- if (RADEON_DEBUG & DEBUG_STATE)
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr, "%s( %s = %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(cap),
state ? "GL_TRUE" : "GL_FALSE");
switch (cap) {
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- /* empty */
- break;
- case GL_FOG:
- r300SetFogState(ctx, state);
- break;
case GL_ALPHA_TEST:
r300SetAlphaState(ctx);
break;
@@ -2174,22 +1710,46 @@ static void r300Enable(GLcontext * ctx, GLenum cap, GLboolean state)
case GL_CLIP_PLANE5:
r300SetClipPlaneState(ctx, cap, state);
break;
+ case GL_CULL_FACE:
+ r300UpdateCulling(ctx);
+ break;
case GL_DEPTH_TEST:
r300SetDepthState(ctx);
break;
- case GL_STENCIL_TEST:
- r300SetStencilState(ctx, state);
+ case GL_LINE_SMOOTH:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_LINE_SMOOTH, ctx->Line.SmoothFlag);
break;
- case GL_CULL_FACE:
- r300UpdateCulling(ctx);
+ case GL_LINE_STIPPLE:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_LINE_STIPPLE, ctx->Line.StippleFlag);
+ break;
+ case GL_POINT_SMOOTH:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_POINT_SMOOTH, ctx->Point.SmoothFlag);
+ break;
+ case GL_POLYGON_SMOOTH:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_POLYGON_SMOOTH, ctx->Polygon.SmoothFlag);
+ break;
+ case GL_POLYGON_STIPPLE:
+ if (rmesa->options.conformance_mode)
+ r300SwitchFallback(ctx, R300_FALLBACK_POLYGON_STIPPLE, ctx->Polygon.StippleFlag);
break;
case GL_POLYGON_OFFSET_POINT:
case GL_POLYGON_OFFSET_LINE:
case GL_POLYGON_OFFSET_FILL:
r300SetPolygonOffsetState(ctx, state);
break;
+ case GL_SCISSOR_TEST:
+ radeon_firevertices(&rmesa->radeon);
+ rmesa->radeon.state.scissor.enabled = state;
+ radeonUpdateScissor( ctx );
+ break;
+ case GL_STENCIL_TEST:
+ r300SetStencilState(ctx, state);
+ break;
default:
- radeonEnable(ctx, cap, state);
break;
}
}
@@ -2200,15 +1760,14 @@ static void r300Enable(GLcontext * ctx, GLenum cap, GLboolean state)
static void r300ResetHwState(r300ContextPtr r300)
{
GLcontext *ctx = r300->radeon.glCtx;
- int has_tcl = 1;
+ int has_tcl;
- if (!(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
- has_tcl = 0;
+ has_tcl = r300->options.hw_tcl_enabled;
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr, "%s\n", __FUNCTION__);
- r300UpdateWindow(ctx);
+ radeon_firevertices(&r300->radeon);
r300ColorMask(ctx,
ctx->Color.ColorMask[RCOMP],
@@ -2220,7 +1779,7 @@ static void r300ResetHwState(r300ContextPtr r300)
r300DepthFunc(ctx, ctx->Depth.Func);
/* stencil */
- r300Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
+ r300Enable(ctx, GL_STENCIL_TEST, ctx->Stencil._Enabled);
r300StencilMaskSeparate(ctx, 0, ctx->Stencil.WriteMask[0]);
r300StencilFuncSeparate(ctx, 0, ctx->Stencil.Function[0],
ctx->Stencil.Ref[0], ctx->Stencil.ValueMask[0]);
@@ -2230,8 +1789,6 @@ static void r300ResetHwState(r300ContextPtr r300)
r300UpdateCulling(ctx);
- r300UpdateTextureState(ctx);
-
r300SetBlendState(ctx);
r300SetLogicOpState(ctx);
@@ -2309,11 +1866,9 @@ static void r300ResetHwState(r300ContextPtr r300)
break;
}
- /* XXX: set to 0 when fog is disabled? */
- r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = R300_GB_FOG_SELECT_1_1_W;
-
/* XXX: Enable anti-aliasing? */
- r300->hw.gb_misc.cmd[R300_GB_MISC_AA_CONFIG] = GB_AA_CONFIG_AA_DISABLE;
+ r300->hw.gb_misc2.cmd[R300_GB_MISC2_AA_CONFIG] = GB_AA_CONFIG_AA_DISABLE;
+ r300->hw.gb_misc2.cmd[R300_GB_MISC2_SELECT] = 0;
r300->hw.ga_point_s0.cmd[1] = r300PackFloat32(0.0);
r300->hw.ga_point_s0.cmd[2] = r300PackFloat32(0.0);
@@ -2362,36 +1917,16 @@ static void r300ResetHwState(r300ContextPtr r300)
R500_C0_SEL_B | R500_C1_SEL_G | R500_C2_SEL_R | R500_C3_SEL_A;
r300->hw.us_out_fmt.cmd[4] = R500_OUT_FMT_UNUSED |
R500_C0_SEL_B | R500_C1_SEL_G | R500_C2_SEL_R | R500_C3_SEL_A;
- r300->hw.us_out_fmt.cmd[5] = R300_W_FMT_W24;
+ r300->hw.us_out_fmt.cmd[5] = R300_W_FMT_W0 | R300_W_SRC_US;
- r300Enable(ctx, GL_FOG, ctx->Fog.Enabled);
- r300Fogfv(ctx, GL_FOG_MODE, NULL);
- r300Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density);
- r300Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start);
- r300Fogfv(ctx, GL_FOG_END, &ctx->Fog.End);
- r300Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color);
- r300Fogfv(ctx, GL_FOG_COORDINATE_SOURCE_EXT, NULL);
-
- r300->hw.fg_depth_src.cmd[1] = 0;
+ /* disable fog unit */
+ r300->hw.fogs.cmd[R300_FOGS_STATE] = 0;
+ r300->hw.fg_depth_src.cmd[1] = R300_FG_DEPTH_SRC_SCAN;
r300->hw.rb3d_cctl.cmd[1] = 0;
r300BlendColor(ctx, ctx->Color.BlendColor);
- /* Again, r300ClearBuffer uses this */
- r300->hw.cb.cmd[R300_CB_OFFSET] =
- r300->radeon.state.color.drawOffset +
- r300->radeon.radeonScreen->fbLocation;
- r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.state.color.drawPitch;
-
- if (r300->radeon.radeonScreen->cpp == 4)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888;
- else
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565;
-
- if (r300->radeon.sarea->tiling_enabled)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE;
-
r300->hw.rb3d_dither_ctl.cmd[1] = 0;
r300->hw.rb3d_dither_ctl.cmd[2] = 0;
r300->hw.rb3d_dither_ctl.cmd[3] = 0;
@@ -2404,44 +1939,18 @@ static void r300ResetHwState(r300ContextPtr r300)
r300->hw.rb3d_aaresolve_ctl.cmd[1] = 0;
- r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[1] = 0x00000000;
- r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[2] = 0xffffffff;
-
- r300->hw.zb.cmd[R300_ZB_OFFSET] =
- r300->radeon.radeonScreen->depthOffset +
- r300->radeon.radeonScreen->fbLocation;
- r300->hw.zb.cmd[R300_ZB_PITCH] = r300->radeon.radeonScreen->depthPitch;
-
- if (r300->radeon.sarea->tiling_enabled) {
- /* XXX: Turn off when clearing buffers ? */
- r300->hw.zb.cmd[R300_ZB_PITCH] |= R300_DEPTHMACROTILE_ENABLE;
-
- if (ctx->Visual.depthBits == 24)
- r300->hw.zb.cmd[R300_ZB_PITCH] |=
- R300_DEPTHMICROTILE_TILED;
- }
+ r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[1] = 0x00000000;
+ r300->hw.rb3d_discard_src_pixel_lte_threshold.cmd[2] = 0xffffffff;
r300->hw.zb_depthclearvalue.cmd[1] = 0;
- switch (ctx->Visual.depthBits) {
- case 16:
- r300->hw.zstencil_format.cmd[1] = R300_DEPTHFORMAT_16BIT_INT_Z;
- break;
- case 24:
- r300->hw.zstencil_format.cmd[1] = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
- break;
- default:
- fprintf(stderr, "Error: Unsupported depth %d... exiting\n", ctx->Visual.depthBits);
- _mesa_exit(-1);
- }
-
r300->hw.zstencil_format.cmd[2] = R300_ZTOP_DISABLE;
r300->hw.zstencil_format.cmd[3] = 0x00000003;
r300->hw.zstencil_format.cmd[4] = 0x00000000;
r300SetEarlyZState(ctx);
- r300->hw.unk4F30.cmd[1] = 0;
- r300->hw.unk4F30.cmd[2] = 0;
+ r300->hw.zb_zmask.cmd[1] = 0;
+ r300->hw.zb_zmask.cmd[2] = 0;
r300->hw.zb_hiz_offset.cmd[1] = 0;
@@ -2455,135 +1964,151 @@ static void r300ResetHwState(r300ContextPtr r300)
r300->hw.vps.cmd[R300_VPS_ZERO_3] = 0;
}
- r300->hw.all_dirty = GL_TRUE;
+ r300->radeon.hw.all_dirty = GL_TRUE;
}
void r300UpdateShaders(r300ContextPtr rmesa)
{
- GLcontext *ctx;
- struct r300_vertex_program *vp;
- int i;
+ GLcontext *ctx = rmesa->radeon.glCtx;
- ctx = rmesa->radeon.glCtx;
+ /* should only happenen once, just after context is created */
+ /* TODO: shouldn't we fallback to sw here? */
+ if (!ctx->FragmentProgram._Current) {
+ _mesa_fprintf(stderr, "No ctx->FragmentProgram._Current!!\n");
+ return;
+ }
- if (rmesa->NewGLState && hw_tcl_on) {
- rmesa->NewGLState = 0;
+ {
+ struct r300_fragment_program *fp;
- for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
- rmesa->temp_attrib[i] =
- TNL_CONTEXT(ctx)->vb.AttribPtr[i];
- TNL_CONTEXT(ctx)->vb.AttribPtr[i] =
- &rmesa->dummy_attrib[i];
- }
+ fp = r300SelectAndTranslateFragmentShader(ctx);
+
+ r300SwitchFallback(ctx, R300_FALLBACK_FRAGMENT_PROGRAM, fp->error);
+ }
- _tnl_UpdateFixedFunctionProgram(ctx);
+ if (rmesa->options.hw_tcl_enabled) {
+ struct r300_vertex_program *vp;
- for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
- TNL_CONTEXT(ctx)->vb.AttribPtr[i] =
- rmesa->temp_attrib[i];
- }
+ if (rmesa->radeon.NewGLState) {
+ int i;
+ for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
+ rmesa->temp_attrib[i] =
+ TNL_CONTEXT(ctx)->vb.AttribPtr[i];
+ TNL_CONTEXT(ctx)->vb.AttribPtr[i] =
+ &rmesa->dummy_attrib[i];
+ }
- r300SelectVertexShader(rmesa);
- vp = (struct r300_vertex_program *)
- CURRENT_VERTEX_SHADER(ctx);
- /*if (vp->translated == GL_FALSE)
- r300TranslateVertexShader(vp); */
- if (vp->translated == GL_FALSE) {
- fprintf(stderr, "Failing back to sw-tcl\n");
- hw_tcl_on = future_hw_tcl_on = 0;
- r300ResetHwState(rmesa);
-
- r300UpdateStateParameters(ctx, _NEW_PROGRAM);
- return;
+ _tnl_UpdateFixedFunctionProgram(ctx);
+
+ for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
+ TNL_CONTEXT(ctx)->vb.AttribPtr[i] =
+ rmesa->temp_attrib[i];
+ }
}
+
+ vp = r300SelectAndTranslateVertexShader(ctx);
+
+ r300SwitchFallback(ctx, R300_FALLBACK_VERTEX_PROGRAM, vp->error);
}
- r300UpdateStateParameters(ctx, _NEW_PROGRAM);
+
+ r300UpdateStateParameters(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ rmesa->radeon.NewGLState = 0;
}
-static const GLfloat *get_fragmentprogram_constant(GLcontext *ctx,
- struct gl_program *program, struct prog_src_register srcreg)
+static const GLfloat *get_fragmentprogram_constant(GLcontext *ctx, GLuint index, GLfloat * buffer)
{
static const GLfloat dummy[4] = { 0, 0, 0, 0 };
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct rc_constant * rcc = &rmesa->selected_fp->code.constants.Constants[index];
+
+ switch(rcc->Type) {
+ case RC_CONSTANT_EXTERNAL:
+ return ctx->FragmentProgram._Current->Base.Parameters->ParameterValues[rcc->u.External];
+ case RC_CONSTANT_IMMEDIATE:
+ return rcc->u.Immediate;
+ case RC_CONSTANT_STATE:
+ switch(rcc->u.State[0]) {
+ case RC_STATE_SHADOW_AMBIENT: {
+ const int unit = (int) rcc->u.State[1];
+ const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
+ if (texObj) {
+ buffer[0] =
+ buffer[1] =
+ buffer[2] =
+ buffer[3] = texObj->CompareFailValue;
+ }
+ return buffer;
+ }
- switch(srcreg.File) {
- case PROGRAM_LOCAL_PARAM:
- return program->LocalParams[srcreg.Index];
- case PROGRAM_ENV_PARAM:
- return ctx->FragmentProgram.Parameters[srcreg.Index];
- case PROGRAM_STATE_VAR:
- case PROGRAM_NAMED_PARAM:
- case PROGRAM_CONSTANT:
- return program->Parameters->ParameterValues[srcreg.Index];
- default:
- _mesa_problem(ctx, "get_fragmentprogram_constant: Unknown\n");
- return dummy;
+ case RC_STATE_R300_WINDOW_DIMENSION: {
+ __DRIdrawablePrivate * drawable = radeon_get_drawable(&rmesa->radeon);
+ buffer[0] = drawable->w * 0.5f; /* width*0.5 */
+ buffer[1] = drawable->h * 0.5f; /* height*0.5 */
+ buffer[2] = 0.5F; /* for moving range [-1 1] -> [0 1] */
+ buffer[3] = 1.0F; /* not used */
+ return buffer;
+ }
+
+ case RC_STATE_R300_TEXRECT_FACTOR: {
+ struct gl_texture_object *t =
+ ctx->Texture.Unit[rcc->u.State[1]].CurrentTex[TEXTURE_RECT_INDEX];
+
+ if (t && t->Image[0][t->BaseLevel]) {
+ struct gl_texture_image *image =
+ t->Image[0][t->BaseLevel];
+ buffer[0] = 1.0 / image->Width2;
+ buffer[1] = 1.0 / image->Height2;
+ } else {
+ buffer[0] = 1.0;
+ buffer[1] = 1.0;
+ }
+ buffer[2] = 1.0;
+ buffer[3] = 1.0;
+ return buffer;
+ }
+ }
}
+
+ return dummy;
}
-static void r300SetupPixelShader(r300ContextPtr rmesa)
+static void r300SetupPixelShader(GLcontext *ctx)
{
- GLcontext *ctx = rmesa->radeon.glCtx;
- struct r300_fragment_program *fp = (struct r300_fragment_program *)
- (char *)ctx->FragmentProgram._Current;
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct r300_fragment_program *fp = rmesa->selected_fp;
struct r300_fragment_program_code *code;
- int i, k;
-
- if (!fp) /* should only happenen once, just after context is created */
- return;
-
- r300TranslateFragmentShader(rmesa, fp);
- if (!fp->translated) {
- fprintf(stderr, "%s: No valid fragment shader, exiting\n",
- __FUNCTION__);
- return;
- }
- code = &fp->code;
+ int i;
- r300SetupTextures(ctx);
+ code = &fp->code.code.r300;
R300_STATECHANGE(rmesa, fpi[0]);
R300_STATECHANGE(rmesa, fpi[1]);
R300_STATECHANGE(rmesa, fpi[2]);
R300_STATECHANGE(rmesa, fpi[3]);
- rmesa->hw.fpi[0].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_US_ALU_RGB_INST_0, code->alu.length);
- rmesa->hw.fpi[1].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_US_ALU_RGB_ADDR_0, code->alu.length);
- rmesa->hw.fpi[2].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_US_ALU_ALPHA_INST_0, code->alu.length);
- rmesa->hw.fpi[3].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_US_ALU_ALPHA_ADDR_0, code->alu.length);
+ rmesa->hw.fpi[0].cmd[R300_FPI_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R300_US_ALU_RGB_INST_0, code->alu.length);
+ rmesa->hw.fpi[1].cmd[R300_FPI_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R300_US_ALU_RGB_ADDR_0, code->alu.length);
+ rmesa->hw.fpi[2].cmd[R300_FPI_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R300_US_ALU_ALPHA_INST_0, code->alu.length);
+ rmesa->hw.fpi[3].cmd[R300_FPI_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R300_US_ALU_ALPHA_ADDR_0, code->alu.length);
for (i = 0; i < code->alu.length; i++) {
- rmesa->hw.fpi[0].cmd[R300_FPI_INSTR_0 + i] = code->alu.inst[i].inst0;
- rmesa->hw.fpi[1].cmd[R300_FPI_INSTR_0 + i] = code->alu.inst[i].inst1;
- rmesa->hw.fpi[2].cmd[R300_FPI_INSTR_0 + i] = code->alu.inst[i].inst2;
- rmesa->hw.fpi[3].cmd[R300_FPI_INSTR_0 + i] = code->alu.inst[i].inst3;
+ rmesa->hw.fpi[0].cmd[R300_FPI_INSTR_0 + i] = code->alu.inst[i].rgb_inst;
+ rmesa->hw.fpi[1].cmd[R300_FPI_INSTR_0 + i] = code->alu.inst[i].rgb_addr;
+ rmesa->hw.fpi[2].cmd[R300_FPI_INSTR_0 + i] = code->alu.inst[i].alpha_inst;
+ rmesa->hw.fpi[3].cmd[R300_FPI_INSTR_0 + i] = code->alu.inst[i].alpha_addr;
}
R300_STATECHANGE(rmesa, fp);
- rmesa->hw.fp.cmd[R300_FP_CNTL0] = code->cur_node | (code->first_node_has_tex << 3);
- rmesa->hw.fp.cmd[R300_FP_CNTL1] = code->max_temp_idx;
- rmesa->hw.fp.cmd[R300_FP_CNTL2] =
- (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);
- /* I just want to say, the way these nodes are stored.. weird.. */
- for (i = 0, k = (4 - (code->cur_node + 1)); i < 4; i++, k++) {
- if (i < (code->cur_node + 1)) {
- rmesa->hw.fp.cmd[R300_FP_NODE0 + k] =
- (code->node[i].alu_offset << R300_ALU_START_SHIFT) |
- (code->node[i].alu_end << R300_ALU_SIZE_SHIFT) |
- (code->node[i].tex_offset << R300_TEX_START_SHIFT) |
- (code->node[i].tex_end << R300_TEX_SIZE_SHIFT) |
- code->node[i].flags;
- } else {
- rmesa->hw.fp.cmd[R300_FP_NODE0 + (3 - i)] = 0;
- }
- }
+ rmesa->hw.fp.cmd[R300_FP_CNTL0] = code->config;
+ rmesa->hw.fp.cmd[R300_FP_CNTL1] = code->pixsize;
+ rmesa->hw.fp.cmd[R300_FP_CNTL2] = code->code_offset;
+ for (i = 0; i < 4; i++)
+ rmesa->hw.fp.cmd[R300_FP_NODE0 + i] = code->code_addr[i];
R300_STATECHANGE(rmesa, fpp);
- rmesa->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(R300_PFS_PARAM_0_X, code->const_nr * 4);
- for (i = 0; i < code->const_nr; i++) {
- const GLfloat *constant = get_fragmentprogram_constant(ctx,
- &fp->mesa_program.Base, code->constant[i]);
+ rmesa->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R300_PFS_PARAM_0_X, fp->code.constants.Count * 4);
+ for (i = 0; i < fp->code.constants.Count; i++) {
+ GLfloat buffer[4];
+ const GLfloat *constant = get_fragmentprogram_constant(ctx, i, buffer);
rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 0] = r300PackFloat24(constant[0]);
rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 1] = r300PackFloat24(constant[1]);
rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 2] = r300PackFloat24(constant[2]);
@@ -2605,51 +2130,29 @@ static void r300SetupPixelShader(r300ContextPtr rmesa)
if(_nc>_p->r500fp.count)_p->r500fp.count=_nc;\
} while(0)
-static void r500SetupPixelShader(r300ContextPtr rmesa)
+static void r500SetupPixelShader(GLcontext *ctx)
{
- GLcontext *ctx = rmesa->radeon.glCtx;
- struct r500_fragment_program *fp = (struct r500_fragment_program *)
- (char *)ctx->FragmentProgram._Current;
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct r300_fragment_program *fp = rmesa->selected_fp;
int i;
struct r500_fragment_program_code *code;
- if (!fp) /* should only happenen once, just after context is created */
- return;
-
((drm_r300_cmd_header_t *) rmesa->hw.r500fp.cmd)->r500fp.count = 0;
((drm_r300_cmd_header_t *) rmesa->hw.r500fp_const.cmd)->r500fp.count = 0;
- r500TranslateFragmentShader(rmesa, fp);
- if (!fp->translated) {
- fprintf(stderr, "%s: No valid fragment shader, exiting\n",
- __FUNCTION__);
- return;
- }
- code = &fp->code;
-
- if (fp->mesa_program.FogOption != GL_NONE) {
- /* Enable HW fog. Try not to squish GL context.
- * (Anybody sane remembered to set glFog() opts first!) */
- r300SetFogState(ctx, GL_TRUE);
- ctx->Fog.Mode = fp->mesa_program.FogOption;
- r300Fogfv(ctx, GL_FOG_MODE, NULL);
- } else
- /* Make sure HW is matching GL context. */
- r300SetFogState(ctx, ctx->Fog.Enabled);
-
- r300SetupTextures(ctx);
+ code = &fp->code.code.r500;
R300_STATECHANGE(rmesa, fp);
rmesa->hw.fp.cmd[R500_FP_PIXSIZE] = code->max_temp_idx;
rmesa->hw.fp.cmd[R500_FP_CODE_ADDR] =
- R500_US_CODE_START_ADDR(code->inst_offset) |
+ R500_US_CODE_START_ADDR(0) |
R500_US_CODE_END_ADDR(code->inst_end);
rmesa->hw.fp.cmd[R500_FP_CODE_RANGE] =
- R500_US_CODE_RANGE_ADDR(code->inst_offset) |
+ R500_US_CODE_RANGE_ADDR(0) |
R500_US_CODE_RANGE_SIZE(code->inst_end);
rmesa->hw.fp.cmd[R500_FP_CODE_OFFSET] =
- R500_US_CODE_OFFSET_ADDR(0); /* FIXME when we add flow control */
+ R500_US_CODE_OFFSET_ADDR(0);
R300_STATECHANGE(rmesa, r500fp);
/* Emit our shader... */
@@ -2665,16 +2168,73 @@ static void r500SetupPixelShader(r300ContextPtr rmesa)
bump_r500fp_count(rmesa->hw.r500fp.cmd, (code->inst_end + 1) * 6);
R300_STATECHANGE(rmesa, r500fp_const);
- for (i = 0; i < code->const_nr; i++) {
- const GLfloat *constant = get_fragmentprogram_constant(ctx,
- &fp->mesa_program.Base, code->constant[i]);
+ for (i = 0; i < fp->code.constants.Count; i++) {
+ GLfloat buffer[4];
+ const GLfloat *constant = get_fragmentprogram_constant(ctx, i, buffer);
rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 0] = r300PackFloat32(constant[0]);
rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 1] = r300PackFloat32(constant[1]);
rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 2] = r300PackFloat32(constant[2]);
rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 3] = r300PackFloat32(constant[3]);
}
- bump_r500fp_const_count(rmesa->hw.r500fp_const.cmd, code->const_nr * 4);
+ bump_r500fp_const_count(rmesa->hw.r500fp_const.cmd, fp->code.constants.Count * 4);
+}
+
+void r300SetupVAP(GLcontext *ctx, GLuint InputsRead, GLuint OutputsWritten)
+{
+ r300ContextPtr rmesa = R300_CONTEXT( ctx );
+ struct vertex_attribute *attrs = rmesa->vbuf.attribs;
+ int i, j, reg_count;
+ uint32_t *vir0 = &rmesa->hw.vir[0].cmd[1];
+ uint32_t *vir1 = &rmesa->hw.vir[1].cmd[1];
+
+ for (i = 0; i < R300_VIR_CMDSIZE-1; ++i)
+ vir0[i] = vir1[i] = 0;
+
+ for (i = 0, j = 0; i < rmesa->vbuf.num_attribs; ++i) {
+ int tmp;
+
+ tmp = attrs[i].data_type | (attrs[i].dst_loc << R300_DST_VEC_LOC_SHIFT);
+ if (attrs[i]._signed)
+ tmp |= R300_SIGNED;
+ if (attrs[i].normalize)
+ tmp |= R300_NORMALIZE;
+
+ if (i % 2 == 0) {
+ vir0[j] = tmp << R300_DATA_TYPE_0_SHIFT;
+ vir1[j] = attrs[i].swizzle | (attrs[i].write_mask << R300_WRITE_ENA_SHIFT);
+ } else {
+ vir0[j] |= tmp << R300_DATA_TYPE_1_SHIFT;
+ vir1[j] |= (attrs[i].swizzle | (attrs[i].write_mask << R300_WRITE_ENA_SHIFT)) << R300_SWIZZLE1_SHIFT;
+ ++j;
+ }
+ }
+ reg_count = (rmesa->vbuf.num_attribs + 1) >> 1;
+ if (rmesa->vbuf.num_attribs % 2 != 0) {
+ vir0[reg_count-1] |= R300_LAST_VEC << R300_DATA_TYPE_0_SHIFT;
+ } else {
+ vir0[reg_count-1] |= R300_LAST_VEC << R300_DATA_TYPE_1_SHIFT;
+ }
+
+ R300_STATECHANGE(rmesa, vir[0]);
+ R300_STATECHANGE(rmesa, vir[1]);
+ R300_STATECHANGE(rmesa, vof);
+ R300_STATECHANGE(rmesa, vic);
+
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ rmesa->hw.vir[0].cmd[0] &= 0xC000FFFF;
+ rmesa->hw.vir[1].cmd[0] &= 0xC000FFFF;
+ rmesa->hw.vir[0].cmd[0] |= (reg_count & 0x3FFF) << 16;
+ rmesa->hw.vir[1].cmd[0] |= (reg_count & 0x3FFF) << 16;
+ } else {
+ ((drm_r300_cmd_header_t *) rmesa->hw.vir[0].cmd)->packet0.count = reg_count;
+ ((drm_r300_cmd_header_t *) rmesa->hw.vir[1].cmd)->packet0.count = reg_count;
+ }
+
+ rmesa->hw.vic.cmd[R300_VIC_CNTL_0] = r300VAPInputCntl0(ctx, InputsRead);
+ rmesa->hw.vic.cmd[R300_VIC_CNTL_1] = r300VAPInputCntl1(ctx, InputsRead);
+ rmesa->hw.vof.cmd[R300_VOF_CNTL_0] = r300VAPOutputCntl0(ctx, OutputsWritten);
+ rmesa->hw.vof.cmd[R300_VOF_CNTL_1] = r300VAPOutputCntl1(ctx, OutputsWritten);
}
void r300UpdateShaderStates(r300ContextPtr rmesa)
@@ -2682,30 +2242,21 @@ void r300UpdateShaderStates(r300ContextPtr rmesa)
GLcontext *ctx;
ctx = rmesa->radeon.glCtx;
- r300UpdateTextureState(ctx);
+ /* should only happenen once, just after context is created */
+ if (!ctx->FragmentProgram._Current)
+ return;
+
r300SetEarlyZState(ctx);
- GLuint fgdepthsrc = R300_FG_DEPTH_SRC_SCAN;
- if (current_fragment_program_writes_depth(ctx))
- fgdepthsrc = R300_FG_DEPTH_SRC_SHADER;
- if (fgdepthsrc != rmesa->hw.fg_depth_src.cmd[1]) {
- R300_STATECHANGE(rmesa, fg_depth_src);
- rmesa->hw.fg_depth_src.cmd[1] = fgdepthsrc;
- }
+ r300SetupTextures(ctx);
- if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
- r500SetupPixelShader(rmesa);
- else
- r300SetupPixelShader(rmesa);
+ rmesa->vtbl.SetupPixelShader(ctx);
- if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
- r500SetupRSUnit(ctx);
- else
- r300SetupRSUnit(ctx);
+ rmesa->vtbl.SetupRSUnit(ctx);
- if ((rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
+ if (rmesa->options.hw_tcl_enabled) {
r300SetupVertexProgram(rmesa);
-
+ }
}
/**
@@ -2719,15 +2270,25 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state)
_swsetup_InvalidateState(ctx, new_state);
_vbo_InvalidateState(ctx, new_state);
_tnl_InvalidateState(ctx, new_state);
- _ae_invalidate_state(ctx, new_state);
- if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
- r300UpdateDrawBuffer(ctx);
+ if (new_state & _NEW_BUFFERS) {
+ _mesa_update_framebuffer(ctx);
+ /* this updates the DrawBuffer's Width/Height if it's a FBO */
+ _mesa_update_draw_buffer_bounds(ctx);
+
+ R300_STATECHANGE(r300, cb);
+ R300_STATECHANGE(r300, zb);
}
- r300UpdateStateParameters(ctx, new_state);
+ if (new_state & (_NEW_LIGHT)) {
+ R300_STATECHANGE(r300, shade2);
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION)
+ r300->hw.shade2.cmd[1] |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST;
+ else
+ r300->hw.shade2.cmd[1] &= ~R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST;
+ }
- r300->NewGLState |= new_state;
+ r300->radeon.NewGLState |= new_state;
}
/**
@@ -2737,58 +2298,12 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state)
*/
void r300InitState(r300ContextPtr r300)
{
- GLcontext *ctx = r300->radeon.glCtx;
- GLuint depth_fmt;
-
- radeonInitState(&r300->radeon);
-
- switch (ctx->Visual.depthBits) {
- case 16:
- r300->state.depth.scale = 1.0 / (GLfloat) 0xffff;
- depth_fmt = R300_DEPTHFORMAT_16BIT_INT_Z;
- break;
- case 24:
- r300->state.depth.scale = 1.0 / (GLfloat) 0xffffff;
- depth_fmt = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL;
- break;
- default:
- fprintf(stderr, "Error: Unsupported depth %d... exiting\n",
- ctx->Visual.depthBits);
- _mesa_exit(-1);
- }
-
- /* Only have hw stencil when depth buffer is 24 bits deep */
- r300->state.stencil.hw_stencil = (ctx->Visual.stencilBits > 0 &&
- ctx->Visual.depthBits == 24);
-
- memset(&(r300->state.texture), 0, sizeof(r300->state.texture));
-
r300ResetHwState(r300);
}
static void r300RenderMode(GLcontext * ctx, GLenum mode)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- (void)rmesa;
- (void)mode;
-}
-
-void r300UpdateClipPlanes( GLcontext *ctx )
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- GLuint p;
-
- for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
- if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
- GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
-
- R300_STATECHANGE( rmesa, vpucp[p] );
- rmesa->hw.vpucp[p].cmd[R300_VPUCP_X] = ip[0];
- rmesa->hw.vpucp[p].cmd[R300_VPUCP_Y] = ip[1];
- rmesa->hw.vpucp[p].cmd[R300_VPUCP_Z] = ip[2];
- rmesa->hw.vpucp[p].cmd[R300_VPUCP_W] = ip[3];
- }
- }
+ r300SwitchFallback(ctx, R300_FALLBACK_RENDER_MODE, ctx->RenderMode != GL_RENDER);
}
/**
@@ -2796,7 +2311,6 @@ void r300UpdateClipPlanes( GLcontext *ctx )
*/
void r300InitStateFuncs(struct dd_function_table *functions)
{
- radeonInitStateFuncs(functions);
functions->UpdateState = r300InvalidateState;
functions->AlphaFunc = r300AlphaFunc;
@@ -2808,7 +2322,6 @@ void r300InitStateFuncs(struct dd_function_table *functions)
functions->DepthFunc = r300DepthFunc;
functions->DepthMask = r300DepthMask;
functions->CullFace = r300CullFace;
- functions->Fogfv = r300Fogfv;
functions->FrontFace = r300FrontFace;
functions->ShadeModel = r300ShadeModel;
functions->LogicOpcode = r300LogicOpcode;
@@ -2833,4 +2346,21 @@ void r300InitStateFuncs(struct dd_function_table *functions)
functions->RenderMode = r300RenderMode;
functions->ClipPlane = r300ClipPlane;
+ functions->Scissor = radeonScissor;
+
+ functions->DrawBuffer = radeonDrawBuffer;
+ functions->ReadBuffer = radeonReadBuffer;
+}
+
+void r300InitShaderFunctions(r300ContextPtr r300)
+{
+ if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+ r300->vtbl.SetupRSUnit = r500SetupRSUnit;
+ r300->vtbl.SetupPixelShader = r500SetupPixelShader;
+ r300->vtbl.SetupFragmentShaderTextures = r500SetupFragmentShaderTextures;
+ } else {
+ r300->vtbl.SetupRSUnit = r300SetupRSUnit;
+ r300->vtbl.SetupPixelShader = r300SetupPixelShader;
+ r300->vtbl.SetupFragmentShaderTextures = r300SetupFragmentShaderTextures;
+ }
}
diff --git a/src/mesa/drivers/dri/r300/r300_state.h b/src/mesa/drivers/dri/r300/r300_state.h
index 0589ab7cad..d46bf9f179 100644
--- a/src/mesa/drivers/dri/r300/r300_state.h
+++ b/src/mesa/drivers/dri/r300/r300_state.h
@@ -39,42 +39,24 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R300_NEWPRIM( rmesa ) \
do { \
- if ( rmesa->dma.flush ) \
- rmesa->dma.flush( rmesa ); \
+ if ( rmesa->radeon.dma.flush ) \
+ rmesa->radeon.dma.flush( rmesa->radeon.glCtx ); \
} while (0)
#define R300_STATECHANGE(r300, atom) \
do { \
R300_NEWPRIM(r300); \
r300->hw.atom.dirty = GL_TRUE; \
- r300->hw.is_dirty = GL_TRUE; \
+ r300->radeon.hw.is_dirty = GL_TRUE; \
} while(0)
-#define R300_PRINT_STATE(r300, atom) \
- r300PrintStateAtom(r300, &r300->hw.atom)
-
-/* Fire the buffered vertices no matter what.
- TODO: This has not been implemented yet
- */
-#define R300_FIREVERTICES( r300 ) \
-do { \
- \
- if ( (r300)->cmdbuf.count_used || (r300)->dma.flush ) { \
- r300Flush( (r300)->radeon.glCtx ); \
- } \
- \
-} while (0)
-
-// r300_state.c
-extern int future_hw_tcl_on;
-void _tnl_UpdateFixedFunctionProgram (GLcontext * ctx);
void r300UpdateViewportOffset (GLcontext * ctx);
void r300UpdateDrawBuffer (GLcontext * ctx);
-void r300UpdateStateParameters (GLcontext * ctx, GLuint new_state);
void r300UpdateShaders (r300ContextPtr rmesa);
void r300UpdateShaderStates (r300ContextPtr rmesa);
void r300InitState (r300ContextPtr r300);
-void r300UpdateClipPlanes (GLcontext * ctx);
void r300InitStateFuncs (struct dd_function_table *functions);
+void r300VapCntl(r300ContextPtr rmesa, GLuint input_count, GLuint output_count, GLuint temp_count);
+void r300SetupVAP(GLcontext *ctx, GLuint InputsRead, GLuint OutputsWritten);
#endif /* __R300_STATE_H__ */
diff --git a/src/mesa/drivers/dri/r300/r300_swtcl.c b/src/mesa/drivers/dri/r300/r300_swtcl.c
index b6e7ce1a1a..ee2c71e1a7 100644
--- a/src/mesa/drivers/dri/r300/r300_swtcl.c
+++ b/src/mesa/drivers/dri/r300/r300_swtcl.c
@@ -28,303 +28,264 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
* Authors:
* Dave Airlie <airlied@linux.ie>
+ * Maciej Cencora <m.cencora@gmail.com>
*/
-/* derived from r200 swtcl path */
-
-
-
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "main/colormac.h"
-#include "main/enums.h"
-#include "main/image.h"
-#include "main/imports.h"
-#include "main/light.h"
-#include "main/macros.h"
-
-#include "swrast/s_context.h"
-#include "swrast/s_fog.h"
-#include "swrast_setup/swrast_setup.h"
-#include "math/m_translate.h"
#include "tnl/tnl.h"
-#include "tnl/t_context.h"
#include "tnl/t_pipeline.h"
-#include "r300_context.h"
-#include "r300_swtcl.h"
#include "r300_state.h"
-#include "r300_ioctl.h"
+#include "r300_swtcl.h"
#include "r300_emit.h"
-#include "r300_mem.h"
+#include "r300_tex.h"
+#include "r300_render.h"
+#include "main/simple_list.h"
-static void flush_last_swtcl_prim( r300ContextPtr rmesa );
-
-
-void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, GLuint offset);
-void r300EmitVbufPrim(r300ContextPtr rmesa, GLuint primitive, GLuint vertex_nr);
#define EMIT_ATTR( ATTR, STYLE ) \
do { \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = (ATTR); \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = (STYLE); \
- rmesa->swtcl.vertex_attr_count++; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = (ATTR); \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = (STYLE); \
+ rmesa->radeon.swtcl.vertex_attr_count++; \
} while (0)
#define EMIT_PAD( N ) \
do { \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = 0; \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = EMIT_PAD; \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].offset = (N); \
- rmesa->swtcl.vertex_attr_count++; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = 0; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = EMIT_PAD; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].offset = (N); \
+ rmesa->radeon.swtcl.vertex_attr_count++; \
+} while (0)
+
+#define ADD_ATTR(_attr, _format, _dst_loc, _swizzle, _write_mask, _normalize) \
+do { \
+ attrs[num_attrs].element = (_attr); \
+ attrs[num_attrs].data_type = (_format); \
+ attrs[num_attrs].dst_loc = (_dst_loc); \
+ attrs[num_attrs].swizzle = (_swizzle); \
+ attrs[num_attrs].write_mask = (_write_mask); \
+ attrs[num_attrs]._signed = 0; \
+ attrs[num_attrs].normalize = (_normalize); \
+ ++num_attrs; \
} while (0)
-static void r300SetVertexFormat( GLcontext *ctx )
+void r300ChooseSwtclVertexFormat(GLcontext *ctx, GLuint *_InputsRead, GLuint *_OutputsWritten)
{
r300ContextPtr rmesa = R300_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- DECLARE_RENDERINPUTS(index_bitset);
- GLuint InputsRead = 0, OutputsWritten = 0;
- int vap_fmt_0 = 0;
- int vap_vte_cntl = 0;
- int offset = 0;
- int vte = 0;
- GLint inputs[VERT_ATTRIB_MAX];
- GLint tab[VERT_ATTRIB_MAX];
- int swizzle[VERT_ATTRIB_MAX][4];
- GLuint i, nr;
- GLuint sz, vap_fmt_1 = 0;
-
- DECLARE_RENDERINPUTS(render_inputs_bitset);
- RENDERINPUTS_COPY(render_inputs_bitset, tnl->render_inputs_bitset);
- RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
- RENDERINPUTS_COPY(rmesa->state.render_inputs_bitset, render_inputs_bitset);
-
- vte = rmesa->hw.vte.cmd[1];
- vte &= ~(R300_VTX_XY_FMT | R300_VTX_Z_FMT | R300_VTX_W0_FMT);
- /* Important:
- */
- if ( VB->NdcPtr != NULL ) {
- VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
- vte |= R300_VTX_XY_FMT | R300_VTX_Z_FMT;
- }
- else {
- VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr;
- vte |= R300_VTX_W0_FMT;
+ int first_free_tex = 0;
+ GLuint InputsRead = 0;
+ GLuint OutputsWritten = 0;
+ int num_attrs = 0;
+ GLuint fp_reads = rmesa->selected_fp->InputsRead;
+ struct vertex_attribute *attrs = rmesa->vbuf.attribs;
+
+ radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s\n", __func__);
+ rmesa->swtcl.coloroffset = rmesa->swtcl.specoffset = 0;
+ rmesa->radeon.swtcl.vertex_attr_count = 0;
+
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s\n", __func__);
+
+ /* We always want non Ndc coords format */
+ VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr;
+
+ /* Always write position vector */
+ InputsRead |= 1 << VERT_ATTRIB_POS;
+ OutputsWritten |= 1 << VERT_RESULT_HPOS;
+ EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F );
+ ADD_ATTR(VERT_ATTRIB_POS, R300_DATA_TYPE_FLOAT_4, SWTCL_OVM_POS, SWIZZLE_XYZW, MASK_XYZW, 0);
+ rmesa->swtcl.coloroffset = 4;
+
+ if (fp_reads & FRAG_BIT_COL0) {
+ InputsRead |= 1 << VERT_ATTRIB_COLOR0;
+ OutputsWritten |= 1 << VERT_RESULT_COL0;
+#if MESA_LITTLE_ENDIAN
+ EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA );
+ ADD_ATTR(VERT_ATTRIB_COLOR0, R300_DATA_TYPE_BYTE, SWTCL_OVM_COLOR0, SWIZZLE_XYZW, MASK_XYZW, 1);
+#else
+ EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR );
+ ADD_ATTR(VERT_ATTRIB_COLOR0, R300_DATA_TYPE_BYTE, SWTCL_OVM_COLOR0, SWIZZLE_XYZW, MASK_XYZW, 1);
+#endif
}
- assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL );
- rmesa->swtcl.vertex_attr_count = 0;
+ if (fp_reads & FRAG_BIT_COL1) {
+ GLuint swiz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
+ InputsRead |= 1 << VERT_ATTRIB_COLOR1;
+ OutputsWritten |= 1 << VERT_RESULT_COL1;
+#if MESA_LITTLE_ENDIAN
+ EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_4UB_4F_RGBA );
+ ADD_ATTR(VERT_ATTRIB_COLOR1, R300_DATA_TYPE_BYTE, SWTCL_OVM_COLOR1, swiz, MASK_XYZW, 1);
+#else
+ EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_4UB_4F_ABGR );
+ ADD_ATTR(VERT_ATTRIB_COLOR1, R300_DATA_TYPE_BYTE, SWTCL_OVM_COLOR1, swiz, MASK_XYZW, 1);
+#endif
+ rmesa->swtcl.specoffset = rmesa->swtcl.coloroffset + 1;
+ }
- /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
- * build up a hardware vertex.
- */
- if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POS)) {
- sz = VB->AttribPtr[VERT_ATTRIB_POS]->size;
- InputsRead |= 1 << VERT_ATTRIB_POS;
- OutputsWritten |= 1 << VERT_RESULT_HPOS;
- EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_1F + sz - 1 );
- offset = sz;
- } else {
- offset = 4;
- EMIT_PAD(4 * sizeof(float));
+ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
+ VB->AttribPtr[VERT_ATTRIB_GENERIC0] = VB->ColorPtr[1];
+ OutputsWritten |= 1 << VERT_RESULT_BFC0;
+#if MESA_LITTLE_ENDIAN
+ EMIT_ATTR( _TNL_ATTRIB_GENERIC0, EMIT_4UB_4F_RGBA );
+ ADD_ATTR(VERT_ATTRIB_GENERIC0, R300_DATA_TYPE_BYTE, SWTCL_OVM_COLOR2, SWIZZLE_XYZW, MASK_XYZW, 1);
+#else
+ EMIT_ATTR( _TNL_ATTRIB_GENERIC0, EMIT_4UB_4F_ABGR );
+ ADD_ATTR(VERT_ATTRIB_GENERIC0, R300_DATA_TYPE_BYTE, SWTCL_OVM_COLOR2, SWIZZLE_XYZW, MASK_XYZW, 1);
+#endif
+ if (fp_reads & FRAG_BIT_COL1) {
+ VB->AttribPtr[VERT_ATTRIB_GENERIC1] = VB->SecondaryColorPtr[1];
+ GLuint swiz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
+ OutputsWritten |= 1 << VERT_RESULT_BFC1;
+#if MESA_LITTLE_ENDIAN
+ EMIT_ATTR( _TNL_ATTRIB_GENERIC1, EMIT_4UB_4F_RGBA );
+ ADD_ATTR(VERT_ATTRIB_GENERIC1, R300_DATA_TYPE_BYTE, SWTCL_OVM_COLOR3, swiz, MASK_XYZW, 1);
+#else
+ EMIT_ATTR( _TNL_ATTRIB_GENERIC1, EMIT_4UB_4F_ABGR );
+ ADD_ATTR(VERT_ATTRIB_GENERIC1, R300_DATA_TYPE_BYTE, SWTCL_OVM_COLOR3, swiz, MASK_XYZW, 1);
+#endif
+ }
}
- if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) {
+ if (RENDERINPUTS_TEST(tnl->render_inputs_bitset, _TNL_ATTRIB_POINTSIZE )) {
+ GLuint swiz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO);
+ InputsRead |= 1 << VERT_ATTRIB_POINT_SIZE;
+ OutputsWritten |= 1 << VERT_RESULT_PSIZ;
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F );
- vap_fmt_0 |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT;
- offset += 1;
+ ADD_ATTR(VERT_ATTRIB_POINT_SIZE, R300_DATA_TYPE_FLOAT_1, SWTCL_OVM_POINT_SIZE, swiz, MASK_X, 0);
}
- if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR0)) {
- sz = VB->AttribPtr[VERT_ATTRIB_COLOR0]->size;
- rmesa->swtcl.coloroffset = offset;
- InputsRead |= 1 << VERT_ATTRIB_COLOR0;
- OutputsWritten |= 1 << VERT_RESULT_COL0;
- EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_1F + sz - 1 );
- offset += sz;
+ if (rmesa->selected_fp->wpos_attr != FRAG_ATTRIB_MAX) {
+ int tex_id = rmesa->selected_fp->wpos_attr - FRAG_ATTRIB_TEX0;
+
+ VB->AttribPtr[VERT_ATTRIB_TEX0 + tex_id] = VB->AttribPtr[VERT_ATTRIB_POS];
+ VB->TexCoordPtr[tex_id] = VB->AttribPtr[VERT_ATTRIB_POS];
+ RENDERINPUTS_SET(tnl->render_inputs_bitset, _TNL_ATTRIB_TEX0 + tex_id);
}
- rmesa->swtcl.specoffset = 0;
- if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
- sz = VB->AttribPtr[VERT_ATTRIB_COLOR1]->size;
- rmesa->swtcl.specoffset = offset;
- EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_1F + sz - 1 );
- InputsRead |= 1 << VERT_ATTRIB_COLOR1;
- OutputsWritten |= 1 << VERT_RESULT_COL1;
+ if (rmesa->selected_fp->fog_attr != FRAG_ATTRIB_MAX) {
+ int tex_id = rmesa->selected_fp->fog_attr - FRAG_ATTRIB_TEX0;
+
+ VB->AttribPtr[VERT_ATTRIB_TEX0 + tex_id] = VB->AttribPtr[VERT_ATTRIB_FOG];
+ VB->TexCoordPtr[tex_id] = VB->AttribPtr[VERT_ATTRIB_FOG];
+ RENDERINPUTS_SET(tnl->render_inputs_bitset, _TNL_ATTRIB_TEX0 + tex_id);
}
- if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
+ /**
+ * Sending only one texcoord component may lead to lock up,
+ * so for all textures always output 4 texcoord components to RS.
+ */
+ {
int i;
-
+ GLuint swiz, format, hw_format;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
- sz = VB->TexCoordPtr[i]->size;
+ if (fp_reads & FRAG_BIT_TEX(i)) {
+ switch (VB->TexCoordPtr[i]->size) {
+ case 1:
+ format = EMIT_1F;
+ hw_format = R300_DATA_TYPE_FLOAT_1;
+ swiz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ONE);
+ break;
+ case 2:
+ format = EMIT_2F;
+ hw_format = R300_DATA_TYPE_FLOAT_2;
+ swiz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE);
+ break;
+ case 3:
+ format = EMIT_3F;
+ hw_format = R300_DATA_TYPE_FLOAT_3;
+ swiz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
+ break;
+ case 4:
+ format = EMIT_4F;
+ hw_format = R300_DATA_TYPE_FLOAT_4;
+ swiz = SWIZZLE_XYZW;
+ break;
+ default:
+ continue;
+ }
InputsRead |= 1 << (VERT_ATTRIB_TEX0 + i);
OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i);
- EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_1F + sz - 1 );
- vap_fmt_1 |= sz << (3 * i);
+ EMIT_ATTR(_TNL_ATTRIB_TEX(i), format);
+ ADD_ATTR(VERT_ATTRIB_TEX0 + i, hw_format, SWTCL_OVM_TEX(first_free_tex), swiz, MASK_XYZW, 0);
+ ++first_free_tex;
}
}
}
- for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) {
- if (InputsRead & (1 << i)) {
- inputs[i] = nr++;
- } else {
- inputs[i] = -1;
- }
- }
-
- /* Fixed, apply to vir0 only */
- if (InputsRead & (1 << VERT_ATTRIB_POS))
- inputs[VERT_ATTRIB_POS] = 0;
- if (InputsRead & (1 << VERT_ATTRIB_COLOR0))
- inputs[VERT_ATTRIB_COLOR0] = 2;
- if (InputsRead & (1 << VERT_ATTRIB_COLOR1))
- inputs[VERT_ATTRIB_COLOR1] = 3;
- for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++)
- if (InputsRead & (1 << i))
- inputs[i] = 6 + (i - VERT_ATTRIB_TEX0);
-
- for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) {
- if (InputsRead & (1 << i)) {
- tab[nr++] = i;
- }
- }
-
- for (i = 0; i < nr; i++) {
- int ci;
-
- swizzle[i][0] = SWIZZLE_ZERO;
- swizzle[i][1] = SWIZZLE_ZERO;
- swizzle[i][2] = SWIZZLE_ZERO;
- swizzle[i][3] = SWIZZLE_ONE;
-
- for (ci = 0; ci < VB->AttribPtr[tab[i]]->size; ci++) {
- swizzle[i][ci] = ci;
- }
+ if (first_free_tex >= ctx->Const.MaxTextureUnits) {
+ fprintf(stderr, "\tout of free texcoords to write fog coordinate\n");
+ _mesa_exit(-1);
}
R300_NEWPRIM(rmesa);
- R300_STATECHANGE(rmesa, vir[0]);
- ((drm_r300_cmd_header_t *) rmesa->hw.vir[0].cmd)->packet0.count =
- r300VAPInputRoute0(&rmesa->hw.vir[0].cmd[R300_VIR_CNTL_0],
- VB->AttribPtr, inputs, tab, nr);
- R300_STATECHANGE(rmesa, vir[1]);
- ((drm_r300_cmd_header_t *) rmesa->hw.vir[1].cmd)->packet0.count =
- r300VAPInputRoute1(&rmesa->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle,
- nr);
-
- R300_STATECHANGE(rmesa, vic);
- rmesa->hw.vic.cmd[R300_VIC_CNTL_0] = r300VAPInputCntl0(ctx, InputsRead);
- rmesa->hw.vic.cmd[R300_VIC_CNTL_1] = r300VAPInputCntl1(ctx, InputsRead);
-
- R300_STATECHANGE(rmesa, vof);
- rmesa->hw.vof.cmd[R300_VOF_CNTL_0] = r300VAPOutputCntl0(ctx, OutputsWritten);
- rmesa->hw.vof.cmd[R300_VOF_CNTL_1] = vap_fmt_1;
-
- rmesa->swtcl.vertex_size =
- _tnl_install_attrs( ctx,
- rmesa->swtcl.vertex_attrs,
- rmesa->swtcl.vertex_attr_count,
- NULL, 0 );
-
- rmesa->swtcl.vertex_size /= 4;
+ rmesa->vbuf.num_attribs = num_attrs;
+ *_InputsRead = InputsRead;
+ *_OutputsWritten = OutputsWritten;
- RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset );
-
-
- R300_STATECHANGE(rmesa, vte);
- rmesa->hw.vte.cmd[1] = vte;
- rmesa->hw.vte.cmd[2] = rmesa->swtcl.vertex_size;
-}
-
-
-/* Flush vertices in the current dma region.
- */
-static void flush_last_swtcl_prim( r300ContextPtr rmesa )
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- rmesa->dma.flush = NULL;
-
- if (rmesa->dma.current.buf) {
- struct r300_dma_region *current = &rmesa->dma.current;
- GLuint current_offset = GET_START(current);
-
- assert (current->start +
- rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
- current->ptr);
-
- if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
-
- r300EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size + (12*sizeof(int)), __FUNCTION__);
-
- r300EmitState(rmesa);
-
- r300EmitVertexAOS( rmesa,
- rmesa->swtcl.vertex_size,
- current_offset);
-
- r300EmitVbufPrim( rmesa,
- rmesa->swtcl.hw_primitive,
- rmesa->swtcl.numverts);
-
- r300EmitCacheFlush(rmesa);
- }
-
- rmesa->swtcl.numverts = 0;
- current->start = current->ptr;
- }
+ RENDERINPUTS_COPY(rmesa->render_inputs_bitset, tnl->render_inputs_bitset);
}
-/* Alloc space in the current dma region.
- */
-static void *
-r300AllocDmaLowVerts( r300ContextPtr rmesa, int nverts, int vsize )
+static void r300PrepareVertices(GLcontext *ctx)
{
- GLuint bytes = vsize * nverts;
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ GLuint InputsRead, OutputsWritten;
+ radeon_print(RADEON_SWRENDER, RADEON_TRACE, "%s\n", __func__);
- if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
- r300RefillCurrentDmaRegion( rmesa, bytes);
+ r300ChooseSwtclVertexFormat(ctx, &InputsRead, &OutputsWritten);
+ r300SetupVAP(ctx, InputsRead, OutputsWritten);
- if (!rmesa->dma.flush) {
- rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
- rmesa->dma.flush = flush_last_swtcl_prim;
- }
+ rmesa->radeon.swtcl.vertex_size =
+ _tnl_install_attrs( ctx,
+ rmesa->radeon.swtcl.vertex_attrs,
+ rmesa->radeon.swtcl.vertex_attr_count,
+ NULL, 0 );
- ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
- ASSERT( rmesa->dma.flush == flush_last_swtcl_prim );
- ASSERT( rmesa->dma.current.start +
- rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
- rmesa->dma.current.ptr );
+ rmesa->radeon.swtcl.vertex_size /= 4;
+}
- {
- GLubyte *head = (GLubyte *) (rmesa->dma.current.address + rmesa->dma.current.ptr);
- rmesa->dma.current.ptr += bytes;
- rmesa->swtcl.numverts += nverts;
- return head;
+static void r300_predict_emit_size( r300ContextPtr rmesa )
+{
+ if (!rmesa->radeon.swtcl.emit_prediction) {
+ const int vertex_size = 7;
+ const int prim_size = 3;
+ const int cache_flush_size = 4;
+ const int pre_emit_state = 4;
+ const int scissor_size = 3;
+ const int state_size = radeonCountStateEmitSize(&rmesa->radeon);
+
+ if (rcommonEnsureCmdBufSpace(&rmesa->radeon,
+ state_size + pre_emit_state + scissor_size
+ + vertex_size + prim_size + cache_flush_size * 2,
+ __FUNCTION__))
+ rmesa->radeon.swtcl.emit_prediction = radeonCountStateEmitSize(&rmesa->radeon);
+ else
+ rmesa->radeon.swtcl.emit_prediction = state_size;
+
+ rmesa->radeon.swtcl.emit_prediction += rmesa->radeon.cmdbuf.cs->cdw
+ + vertex_size + scissor_size + prim_size + cache_flush_size * 2 + pre_emit_state;
+ radeon_print(RADEON_SWRENDER, RADEON_VERBOSE,
+ "%s, size %d\n",
+ __func__, rmesa->radeon.cmdbuf.cs->cdw
+ + vertex_size + scissor_size + prim_size + cache_flush_size * 2 + pre_emit_state);
}
}
+
static GLuint reduced_prim[] = {
- GL_POINTS,
- GL_LINES,
- GL_LINES,
- GL_LINES,
- GL_TRIANGLES,
- GL_TRIANGLES,
- GL_TRIANGLES,
- GL_TRIANGLES,
- GL_TRIANGLES,
- GL_TRIANGLES,
+ GL_POINTS,
+ GL_LINES,
+ GL_LINES,
+ GL_LINES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
};
static void r300RasterPrimitive( GLcontext *ctx, GLuint prim );
-static void r300RenderPrimitive( GLcontext *ctx, GLenum prim );
-//static void r300ResetLineStipple( GLcontext *ctx );
/***********************************************************************
* Emit primitives as inline vertices *
@@ -343,18 +304,26 @@ static void r300RenderPrimitive( GLcontext *ctx, GLenum prim );
#define HAVE_POLYGONS 1
#define HAVE_ELTS 1
+static void* r300_alloc_verts(r300ContextPtr rmesa, GLuint n, GLuint size)
+{
+ void *rv;
+ do {
+ r300_predict_emit_size( rmesa );
+ rv = rcommonAllocDmaLowVerts( &rmesa->radeon, n, size * 4 );
+ } while (!rv);
+ return rv;
+}
+
#undef LOCAL_VARS
#undef ALLOC_VERTS
#define CTX_ARG r300ContextPtr rmesa
-#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
-#define ALLOC_VERTS( n, size ) r300AllocDmaLowVerts( rmesa, n, size * 4 )
+#define GET_VERTEX_DWORDS() rmesa->radeon.swtcl.vertex_size
+#define ALLOC_VERTS( n, size ) r300_alloc_verts(rmesa, n, size);
#define LOCAL_VARS \
r300ContextPtr rmesa = R300_CONTEXT(ctx); \
- const char *r300verts = (char *)rmesa->swtcl.verts;
+ const char *r300verts = (char *)rmesa->radeon.swtcl.verts;
#define VERT(x) (r300Vertex *)(r300verts + ((x) * vertsize * sizeof(int)))
-#define VERTEX r300Vertex
-#define DO_DEBUG_VERTS (1 && (RADEON_DEBUG & DEBUG_VERTS))
-#define PRINT_VERTEX(x)
+#define VERTEX r300Vertex
#undef TAG
#define TAG(x) r300_##x
#include "tnl_dd/t_dd_triemit.h"
@@ -374,9 +343,8 @@ static void r300RenderPrimitive( GLcontext *ctx, GLenum prim );
* Build render functions from dd templates *
***********************************************************************/
-#define R300_TWOSIDE_BIT 0x01
-#define R300_UNFILLED_BIT 0x02
-#define R300_MAX_TRIFUNC 0x04
+#define R300_UNFILLED_BIT 0x01
+#define R300_MAX_TRIFUNC 0x02
static struct {
tnl_points_func points;
@@ -387,9 +355,9 @@ static struct {
#define DO_FALLBACK 0
#define DO_UNFILLED (IND & R300_UNFILLED_BIT)
-#define DO_TWOSIDE (IND & R300_TWOSIDE_BIT)
+#define DO_TWOSIDE 0
#define DO_FLAT 0
-#define DO_OFFSET 0
+#define DO_OFFSET 0
#define DO_TRI 1
#define DO_QUAD 1
#define DO_LINE 1
@@ -409,33 +377,39 @@ static struct {
#define VERT_Y(_v) _v->v.y
#define VERT_Z(_v) _v->v.z
#define AREA_IS_CCW( a ) (a < 0)
-#define GET_VERTEX(e) (rmesa->swtcl.verts + (e*rmesa->swtcl.vertex_size*sizeof(int)))
-
-/* Only used to pull back colors into vertices (ie, we know color is
- * floating point).
- */
-#define R300_COLOR( dst, src ) \
-do { \
- UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \
- UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \
- UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \
- UNCLAMPED_FLOAT_TO_UBYTE((dst)[3], (src)[3]); \
+#define GET_VERTEX(e) (rmesa->radeon.swtcl.verts + (e*rmesa->radeon.swtcl.vertex_size*sizeof(int)))
+
+#define VERT_SET_RGBA( v, c ) \
+do { \
+ r300_color_t *color = (r300_color_t *)&((v)->ui[coloroffset]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
} while (0)
-#define VERT_SET_RGBA( v, c ) if (coloroffset) R300_COLOR( v->ub4[coloroffset], c )
-#define VERT_COPY_RGBA( v0, v1 ) if (coloroffset) v0->ui[coloroffset] = v1->ui[coloroffset]
-#define VERT_SAVE_RGBA( idx ) if (coloroffset) color[idx] = v[idx]->ui[coloroffset]
-#define VERT_RESTORE_RGBA( idx ) if (coloroffset) v[idx]->ui[coloroffset] = color[idx]
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
+
+#define VERT_SET_SPEC( v0, c ) \
+do { \
+ if (specoffset) { \
+ UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
+ } \
+} while (0)
-#define R300_SPEC( dst, src ) \
-do { \
- UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \
- UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \
- UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \
+#define VERT_COPY_SPEC( v0, v1 ) \
+do { \
+ if (specoffset) { \
+ v0->v.specular.red = v1->v.specular.red; \
+ v0->v.specular.green = v1->v.specular.green; \
+ v0->v.specular.blue = v1->v.specular.blue; \
+ } \
} while (0)
-#define VERT_SET_SPEC( v, c ) if (specoffset) R300_SPEC( v->ub4[specoffset], c )
-#define VERT_COPY_SPEC( v0, v1 ) if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
+#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
@@ -445,7 +419,7 @@ do { \
#define LOCAL_VARS(n) \
r300ContextPtr rmesa = R300_CONTEXT(ctx); \
- GLuint color[n], spec[n]; \
+ GLuint color[n] = { 0, }, spec[n] = { 0, }; \
GLuint coloroffset = rmesa->swtcl.coloroffset; \
GLuint specoffset = rmesa->swtcl.specoffset; \
(void) color; (void) spec; (void) coloroffset; (void) specoffset;
@@ -455,7 +429,7 @@ do { \
***********************************************************************/
#define RASTERIZE(x) r300RasterPrimitive( ctx, reduced_prim[x] )
-#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
+#define RENDER_PRIMITIVE rmesa->radeon.swtcl.render_primitive
#undef TAG
#define TAG(x) x
#include "tnl_dd/t_dd_unfilled.h"
@@ -471,26 +445,15 @@ do { \
#define TAG(x) x
#include "tnl_dd/t_dd_tritmp.h"
-#define IND (R300_TWOSIDE_BIT)
-#define TAG(x) x##_twoside
-#include "tnl_dd/t_dd_tritmp.h"
-
#define IND (R300_UNFILLED_BIT)
#define TAG(x) x##_unfilled
#include "tnl_dd/t_dd_tritmp.h"
-#define IND (R300_TWOSIDE_BIT|R300_UNFILLED_BIT)
-#define TAG(x) x##_twoside_unfilled
-#include "tnl_dd/t_dd_tritmp.h"
-
-
static void init_rast_tab( void )
{
init();
- init_twoside();
init_unfilled();
- init_twoside_unfilled();
}
/**********************************************************************/
@@ -512,8 +475,8 @@ static void init_rast_tab( void )
#undef LOCAL_VARS
#define LOCAL_VARS \
r300ContextPtr rmesa = R300_CONTEXT(ctx); \
- const GLuint vertsize = rmesa->swtcl.vertex_size; \
- const char *r300verts = (char *)rmesa->swtcl.verts; \
+ const GLuint vertsize = rmesa->radeon.swtcl.vertex_size; \
+ const char *r300verts = (char *)rmesa->radeon.swtcl.verts; \
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
const GLboolean stipple = ctx->Line.StippleFlag; \
(void) elt; (void) stipple;
@@ -541,11 +504,11 @@ static void r300ChooseRenderState( GLcontext *ctx )
r300ContextPtr rmesa = R300_CONTEXT(ctx);
GLuint index = 0;
GLuint flags = ctx->_TriangleCaps;
+ radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s\n", __func__);
- if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R300_TWOSIDE_BIT;
if (flags & DD_TRI_UNFILLED) index |= R300_UNFILLED_BIT;
- if (index != rmesa->swtcl.RenderIndex) {
+ if (index != rmesa->radeon.swtcl.RenderIndex) {
tnl->Driver.Render.Points = rast_tab[index].points;
tnl->Driver.Render.Line = rast_tab[index].line;
tnl->Driver.Render.ClippedLine = rast_tab[index].line;
@@ -562,62 +525,64 @@ static void r300ChooseRenderState( GLcontext *ctx )
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
}
- rmesa->swtcl.RenderIndex = index;
+ rmesa->radeon.swtcl.RenderIndex = index;
}
}
-
-static void r300RenderStart(GLcontext *ctx)
+void r300RenderStart(GLcontext *ctx)
{
- r300ContextPtr rmesa = R300_CONTEXT( ctx );
- // fprintf(stderr, "%s\n", __FUNCTION__);
+ radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s\n", __func__);
+ r300ContextPtr rmesa = R300_CONTEXT( ctx );
- r300ChooseRenderState(ctx);
- r300SetVertexFormat(ctx);
+ r300ChooseRenderState(ctx);
r300UpdateShaders(rmesa);
+
+ r300PrepareVertices(ctx);
+
+ r300ValidateBuffers(ctx);
+
r300UpdateShaderStates(rmesa);
- r300EmitCacheFlush(rmesa);
-
- if (rmesa->dma.flush != 0 &&
- rmesa->dma.flush != flush_last_swtcl_prim)
- rmesa->dma.flush( rmesa );
+ /* investigate if we can put back flush optimisation if needed */
+ if (rmesa->radeon.dma.flush != NULL) {
+ rmesa->radeon.dma.flush(ctx);
+ }
}
-static void r300RenderFinish(GLcontext *ctx)
+void r300RenderFinish(GLcontext *ctx)
{
}
static void r300RasterPrimitive( GLcontext *ctx, GLuint hwprim )
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
-
- if (rmesa->swtcl.hw_primitive != hwprim) {
- R300_NEWPRIM( rmesa );
- rmesa->swtcl.hw_primitive = hwprim;
+ radeon_print(RADEON_SWRENDER, RADEON_TRACE, "%s\n", __func__);
+
+ if (rmesa->radeon.swtcl.hw_primitive != hwprim) {
+ R300_NEWPRIM( rmesa );
+ rmesa->radeon.swtcl.hw_primitive = hwprim;
}
}
-static void r300RenderPrimitive(GLcontext *ctx, GLenum prim)
+void r300RenderPrimitive(GLcontext *ctx, GLenum prim)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- rmesa->swtcl.render_primitive = prim;
+ rmesa->radeon.swtcl.render_primitive = prim;
+ radeon_print(RADEON_SWRENDER, RADEON_TRACE, "%s\n", __func__);
if ((prim == GL_TRIANGLES) && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
- return;
+ return;
r300RasterPrimitive( ctx, reduced_prim[prim] );
- // fprintf(stderr, "%s\n", __FUNCTION__);
-
}
-static void r300ResetLineStipple(GLcontext *ctx)
+void r300ResetLineStipple(GLcontext *ctx)
{
-
-
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s\n", __func__);
}
void r300InitSwtcl(GLcontext *ctx)
@@ -625,12 +590,14 @@ void r300InitSwtcl(GLcontext *ctx)
TNLcontext *tnl = TNL_CONTEXT(ctx);
r300ContextPtr rmesa = R300_CONTEXT(ctx);
static int firsttime = 1;
-
+ radeon_print(RADEON_SWRENDER, RADEON_NORMAL, "%s\n", __func__);
+
if (firsttime) {
init_rast_tab();
firsttime = 0;
}
-
+ rmesa->radeon.swtcl.emit_prediction = 0;
+
tnl->Driver.Render.Start = r300RenderStart;
tnl->Driver.Render.Finish = r300RenderFinish;
tnl->Driver.Render.PrimitiveNotify = r300RenderPrimitive;
@@ -638,60 +605,80 @@ void r300InitSwtcl(GLcontext *ctx)
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.Interp = _tnl_interp;
-
+
/* FIXME: what are these numbers? */
- _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
+ _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
48 * sizeof(GLfloat) );
-
- rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
- rmesa->swtcl.RenderIndex = ~0;
- rmesa->swtcl.render_primitive = GL_TRIANGLES;
- rmesa->swtcl.hw_primitive = 0;
+
+ rmesa->radeon.swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
+ rmesa->radeon.swtcl.RenderIndex = ~0;
+ rmesa->radeon.swtcl.render_primitive = GL_TRIANGLES;
+ rmesa->radeon.swtcl.hw_primitive = 0;
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
- RENDERINPUTS_ZERO( rmesa->tnl_index_bitset );
_tnl_need_projected_coords( ctx, GL_FALSE );
- r300ChooseRenderState(ctx);
-
- _mesa_validate_all_lighting_tables( ctx );
-
- tnl->Driver.NotifyMaterialChange =
- _mesa_validate_all_lighting_tables;
}
void r300DestroySwtcl(GLcontext *ctx)
{
}
-void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, GLuint offset)
+static void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, struct radeon_bo *bo, GLuint offset)
{
- int cmd_reserved = 0;
- int cmd_written = 0;
-
- drm_radeon_cmd_header_t *cmd = NULL;
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s: vertex_size %d, offset 0x%x \n",
- __FUNCTION__, vertex_size, offset);
-
- start_packet3(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, 2), 2);
- e32(1);
- e32(vertex_size | (vertex_size << 8));
- e32(offset);
+ BATCH_LOCALS(&rmesa->radeon);
+
+ radeon_print(RADEON_SWRENDER, RADEON_TRACE,
+ "%s: vertex_size %d, offset 0x%x \n",
+ __FUNCTION__, vertex_size, offset);
+
+ BEGIN_BATCH(7);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, 2);
+ OUT_BATCH(1);
+ OUT_BATCH(vertex_size | (vertex_size << 8));
+ OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ END_BATCH();
}
-void r300EmitVbufPrim(r300ContextPtr rmesa, GLuint primitive, GLuint vertex_nr)
+static void r300EmitVbufPrim(r300ContextPtr rmesa, GLuint primitive, GLuint vertex_nr)
{
-
- int cmd_reserved = 0;
- int cmd_written = 0;
+ BATCH_LOCALS(&rmesa->radeon);
int type, num_verts;
- drm_radeon_cmd_header_t *cmd = NULL;
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s\n", __func__);
type = r300PrimitiveType(rmesa, primitive);
num_verts = r300NumVerts(rmesa, vertex_nr, primitive);
-
- start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0), 0);
- e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (num_verts << 16) | type);
+
+ BEGIN_BATCH(3);
+ OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
+ OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (num_verts << 16) | type);
+ END_BATCH();
+}
+
+void r300_swtcl_flush(GLcontext *ctx, uint32_t current_offset)
+{
+ radeon_print(RADEON_SWRENDER, RADEON_TRACE, "%s\n", __func__);
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+
+ r300EmitCacheFlush(rmesa);
+
+ radeonEmitState(&rmesa->radeon);
+ r300_emit_scissor(ctx);
+ r300EmitVertexAOS(rmesa,
+ rmesa->radeon.swtcl.vertex_size,
+ first_elem(&rmesa->radeon.dma.reserved)->bo,
+ current_offset);
+
+ r300EmitVbufPrim(rmesa,
+ rmesa->radeon.swtcl.hw_primitive,
+ rmesa->radeon.swtcl.numverts);
+ r300EmitCacheFlush(rmesa);
+ if ( rmesa->radeon.swtcl.emit_prediction < rmesa->radeon.cmdbuf.cs->cdw )
+ WARN_ONCE("Rendering was %d commands larger than predicted size."
+ " We might overflow command buffer.\n",
+ rmesa->radeon.cmdbuf.cs->cdw - rmesa->radeon.swtcl.emit_prediction );
+ rmesa->radeon.swtcl.emit_prediction = 0;
+ COMMIT_BATCH();
}
diff --git a/src/mesa/drivers/dri/r300/r300_swtcl.h b/src/mesa/drivers/dri/r300/r300_swtcl.h
index 55df53c1ad..c271d26546 100644
--- a/src/mesa/drivers/dri/r300/r300_swtcl.h
+++ b/src/mesa/drivers/dri/r300/r300_swtcl.h
@@ -39,7 +39,27 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "swrast/swrast.h"
#include "r300_context.h"
+/*
+ * Here are definitions of OVM locations of vertex attributes for non TCL hw
+ */
+#define SWTCL_OVM_POS 0
+#define SWTCL_OVM_COLOR0 2
+#define SWTCL_OVM_COLOR1 3
+#define SWTCL_OVM_COLOR2 4
+#define SWTCL_OVM_COLOR3 5
+#define SWTCL_OVM_TEX(n) ((n) + 6)
+#define SWTCL_OVM_POINT_SIZE 15
+
+extern void r300ChooseSwtclVertexFormat(GLcontext *ctx, GLuint *InputsRead, GLuint *OutputsWritten);
+
extern void r300InitSwtcl( GLcontext *ctx );
extern void r300DestroySwtcl( GLcontext *ctx );
+extern void r300RenderStart(GLcontext *ctx);
+extern void r300RenderFinish(GLcontext *ctx);
+extern void r300RenderPrimitive(GLcontext *ctx, GLenum prim);
+extern void r300ResetLineStipple(GLcontext *ctx);
+
+extern void r300_swtcl_flush(GLcontext *ctx, uint32_t current_offset);
+
#endif
diff --git a/src/mesa/drivers/dri/r300/r300_tex.c b/src/mesa/drivers/dri/r300/r300_tex.c
index 8ab382c83c..433e5a87d4 100644
--- a/src/mesa/drivers/dri/r300/r300_tex.c
+++ b/src/mesa/drivers/dri/r300/r300_tex.c
@@ -38,6 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/context.h"
#include "main/enums.h"
#include "main/image.h"
+#include "main/mipmap.h"
#include "main/simple_list.h"
#include "main/texformat.h"
#include "main/texstore.h"
@@ -49,6 +50,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_context.h"
#include "r300_state.h"
#include "r300_ioctl.h"
+#include "radeon_mipmap_tree.h"
#include "r300_tex.h"
#include "xmlpool.h"
@@ -77,20 +79,20 @@ static unsigned int translate_wrap_mode(GLenum wrapmode)
*
* \param t Texture object whose wrap modes are to be set
*/
-static void r300UpdateTexWrap(r300TexObjPtr t)
+static void r300UpdateTexWrap(radeonTexObjPtr t)
{
- struct gl_texture_object *tObj = t->base.tObj;
+ struct gl_texture_object *tObj = &t->base;
- t->filter &=
+ t->pp_txfilter &=
~(R300_TX_WRAP_S_MASK | R300_TX_WRAP_T_MASK | R300_TX_WRAP_R_MASK);
- t->filter |= translate_wrap_mode(tObj->WrapS) << R300_TX_WRAP_S_SHIFT;
+ t->pp_txfilter |= translate_wrap_mode(tObj->WrapS) << R300_TX_WRAP_S_SHIFT;
if (tObj->Target != GL_TEXTURE_1D) {
- t->filter |= translate_wrap_mode(tObj->WrapT) << R300_TX_WRAP_T_SHIFT;
+ t->pp_txfilter |= translate_wrap_mode(tObj->WrapT) << R300_TX_WRAP_T_SHIFT;
if (tObj->Target == GL_TEXTURE_3D)
- t->filter |= translate_wrap_mode(tObj->WrapR) << R300_TX_WRAP_R_SHIFT;
+ t->pp_txfilter |= translate_wrap_mode(tObj->WrapR) << R300_TX_WRAP_R_SHIFT;
}
}
@@ -117,10 +119,13 @@ static GLuint aniso_filter(GLfloat anisotropy)
* \param magf Texture magnification mode
* \param anisotropy Maximum anisotropy level
*/
-static void r300SetTexFilter(r300TexObjPtr t, GLenum minf, GLenum magf, GLfloat anisotropy)
+static void r300SetTexFilter(radeonTexObjPtr t, GLenum minf, GLenum magf, GLfloat anisotropy)
{
- t->filter &= ~(R300_TX_MIN_FILTER_MASK | R300_TX_MIN_FILTER_MIP_MASK | R300_TX_MAG_FILTER_MASK | R300_TX_MAX_ANISO_MASK);
- t->filter_1 &= ~R300_EDGE_ANISO_EDGE_ONLY;
+ /* Force revalidation to account for switches from/to mipmapping. */
+ t->validated = GL_FALSE;
+
+ t->pp_txfilter &= ~(R300_TX_MIN_FILTER_MASK | R300_TX_MIN_FILTER_MIP_MASK | R300_TX_MAG_FILTER_MASK | R300_TX_MAX_ANISO_MASK);
+ t->pp_txfilter_1 &= ~R300_EDGE_ANISO_EDGE_ONLY;
/* Note that EXT_texture_filter_anisotropic is extremely vague about
* how anisotropic filtering interacts with the "normal" filter modes.
@@ -128,33 +133,33 @@ static void r300SetTexFilter(r300TexObjPtr t, GLenum minf, GLenum magf, GLfloat
* filter settings completely. This includes driconf's settings.
*/
if (anisotropy >= 2.0 && (minf != GL_NEAREST) && (magf != GL_NEAREST)) {
- t->filter |= R300_TX_MAG_FILTER_ANISO
+ t->pp_txfilter |= R300_TX_MAG_FILTER_ANISO
| R300_TX_MIN_FILTER_ANISO
| R300_TX_MIN_FILTER_MIP_LINEAR
| aniso_filter(anisotropy);
- if (RADEON_DEBUG & DEBUG_TEXTURE)
+ if (RADEON_DEBUG & RADEON_TEXTURE)
fprintf(stderr, "Using maximum anisotropy of %f\n", anisotropy);
return;
}
switch (minf) {
case GL_NEAREST:
- t->filter |= R300_TX_MIN_FILTER_NEAREST;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_NEAREST;
break;
case GL_LINEAR:
- t->filter |= R300_TX_MIN_FILTER_LINEAR;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_LINEAR;
break;
case GL_NEAREST_MIPMAP_NEAREST:
- t->filter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_NEAREST;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
- t->filter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_LINEAR;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_LINEAR;
break;
case GL_LINEAR_MIPMAP_NEAREST:
- t->filter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_NEAREST;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_NEAREST;
break;
case GL_LINEAR_MIPMAP_LINEAR:
- t->filter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_LINEAR;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_LINEAR;
break;
}
@@ -163,743 +168,25 @@ static void r300SetTexFilter(r300TexObjPtr t, GLenum minf, GLenum magf, GLfloat
*/
switch (magf) {
case GL_NEAREST:
- t->filter |= R300_TX_MAG_FILTER_NEAREST;
+ t->pp_txfilter |= R300_TX_MAG_FILTER_NEAREST;
break;
case GL_LINEAR:
- t->filter |= R300_TX_MAG_FILTER_LINEAR;
+ t->pp_txfilter |= R300_TX_MAG_FILTER_LINEAR;
break;
}
}
-static void r300SetTexBorderColor(r300TexObjPtr t, GLubyte c[4])
+static void r300SetTexBorderColor(radeonTexObjPtr t, const GLfloat color[4])
{
+ GLubyte c[4];
+ CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
t->pp_border_color = PACK_COLOR_8888(c[3], c[0], c[1], c[2]);
}
/**
- * Allocate space for and load the mesa images into the texture memory block.
- * This will happen before drawing with a new texture, or drawing with a
- * texture after it was swapped out or teximaged again.
- */
-
-static r300TexObjPtr r300AllocTexObj(struct gl_texture_object *texObj)
-{
- r300TexObjPtr t;
-
- t = CALLOC_STRUCT(r300_tex_obj);
- texObj->DriverData = t;
- if (t != NULL) {
- if (RADEON_DEBUG & DEBUG_TEXTURE) {
- fprintf(stderr, "%s( %p, %p )\n", __FUNCTION__,
- (void *)texObj, (void *)t);
- }
-
- /* Initialize non-image-dependent parts of the state:
- */
- t->base.tObj = texObj;
- t->border_fallback = GL_FALSE;
-
- make_empty_list(&t->base);
-
- r300UpdateTexWrap(t);
- r300SetTexFilter(t, texObj->MinFilter, texObj->MagFilter, texObj->MaxAnisotropy);
- r300SetTexBorderColor(t, texObj->_BorderChan);
- }
-
- return t;
-}
-
-/* try to find a format which will only need a memcopy */
-static const struct gl_texture_format *r300Choose8888TexFormat(GLenum srcFormat,
- GLenum srcType)
-{
- const GLuint ui = 1;
- const GLubyte littleEndian = *((const GLubyte *)&ui);
-
- if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
- (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
- (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
- (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) {
- return &_mesa_texformat_rgba8888;
- } else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
- (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
- (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
- (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) {
- return &_mesa_texformat_rgba8888_rev;
- } else if (srcFormat == GL_BGRA && ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
- srcType == GL_UNSIGNED_INT_8_8_8_8)) {
- return &_mesa_texformat_argb8888_rev;
- } else if (srcFormat == GL_BGRA && ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
- srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
- return &_mesa_texformat_argb8888;
- } else
- return _dri_texformat_argb8888;
-}
-
-static const struct gl_texture_format *r300ChooseTextureFormat(GLcontext * ctx,
- GLint
- internalFormat,
- GLenum format,
- GLenum type)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- const GLboolean do32bpt =
- (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32);
- const GLboolean force16bpt =
- (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16);
- (void)format;
-
-#if 0
- fprintf(stderr, "InternalFormat=%s(%d) type=%s format=%s\n",
- _mesa_lookup_enum_by_nr(internalFormat), internalFormat,
- _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
- fprintf(stderr, "do32bpt=%d force16bpt=%d\n", do32bpt, force16bpt);
-#endif
-
- switch (internalFormat) {
- case 4:
- case GL_RGBA:
- case GL_COMPRESSED_RGBA:
- switch (type) {
- case GL_UNSIGNED_INT_10_10_10_2:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- return do32bpt ? _dri_texformat_argb8888 :
- _dri_texformat_argb1555;
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return _dri_texformat_argb4444;
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return _dri_texformat_argb1555;
- default:
- return do32bpt ? r300Choose8888TexFormat(format, type) :
- _dri_texformat_argb4444;
- }
-
- case 3:
- case GL_RGB:
- case GL_COMPRESSED_RGB:
- switch (type) {
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return _dri_texformat_argb4444;
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return _dri_texformat_argb1555;
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- return _dri_texformat_rgb565;
- default:
- return do32bpt ? _dri_texformat_argb8888 :
- _dri_texformat_rgb565;
- }
-
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- return !force16bpt ?
- r300Choose8888TexFormat(format,
- type) : _dri_texformat_argb4444;
-
- case GL_RGBA4:
- case GL_RGBA2:
- return _dri_texformat_argb4444;
-
- case GL_RGB5_A1:
- return _dri_texformat_argb1555;
-
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- return !force16bpt ? _dri_texformat_argb8888 :
- _dri_texformat_rgb565;
-
- case GL_RGB5:
- case GL_RGB4:
- case GL_R3_G3_B2:
- return _dri_texformat_rgb565;
-
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- case GL_ALPHA12:
- case GL_ALPHA16:
- case GL_COMPRESSED_ALPHA:
- return _dri_texformat_a8;
-
- case 1:
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- case GL_COMPRESSED_LUMINANCE:
- return _dri_texformat_l8;
-
- case 2:
- 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:
- case GL_COMPRESSED_LUMINANCE_ALPHA:
- return _dri_texformat_al88;
-
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- case GL_COMPRESSED_INTENSITY:
- return _dri_texformat_i8;
-
- case GL_YCBCR_MESA:
- if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
- type == GL_UNSIGNED_BYTE)
- return &_mesa_texformat_ycbcr;
- else
- return &_mesa_texformat_ycbcr_rev;
-
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- return &_mesa_texformat_rgb_dxt1;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- return &_mesa_texformat_rgba_dxt1;
-
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- return &_mesa_texformat_rgba_dxt3;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- return &_mesa_texformat_rgba_dxt5;
-
- case GL_ALPHA16F_ARB:
- return &_mesa_texformat_alpha_float16;
- case GL_ALPHA32F_ARB:
- return &_mesa_texformat_alpha_float32;
- case GL_LUMINANCE16F_ARB:
- return &_mesa_texformat_luminance_float16;
- case GL_LUMINANCE32F_ARB:
- return &_mesa_texformat_luminance_float32;
- case GL_LUMINANCE_ALPHA16F_ARB:
- return &_mesa_texformat_luminance_alpha_float16;
- case GL_LUMINANCE_ALPHA32F_ARB:
- return &_mesa_texformat_luminance_alpha_float32;
- case GL_INTENSITY16F_ARB:
- return &_mesa_texformat_intensity_float16;
- case GL_INTENSITY32F_ARB:
- return &_mesa_texformat_intensity_float32;
- case GL_RGB16F_ARB:
- return &_mesa_texformat_rgba_float16;
- case GL_RGB32F_ARB:
- return &_mesa_texformat_rgba_float32;
- case GL_RGBA16F_ARB:
- return &_mesa_texformat_rgba_float16;
- case GL_RGBA32F_ARB:
- return &_mesa_texformat_rgba_float32;
-
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
-#if 0
- switch (type) {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT:
- return &_mesa_texformat_z16;
- case GL_UNSIGNED_INT:
- return &_mesa_texformat_z32;
- case GL_UNSIGNED_INT_24_8_EXT:
- default:
- return &_mesa_texformat_z24_s8;
- }
-#else
- return &_mesa_texformat_z16;
-#endif
-
- default:
- _mesa_problem(ctx,
- "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
- (int)internalFormat);
- return NULL;
- }
-
- return NULL; /* never get here */
-}
-
-static GLboolean
-r300ValidateClientStorage(GLcontext * ctx, GLenum target,
- GLint internalFormat,
- GLint srcWidth, GLint srcHeight,
- GLenum format, GLenum type, const void *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "intformat %s format %s type %s\n",
- _mesa_lookup_enum_by_nr(internalFormat),
- _mesa_lookup_enum_by_nr(format),
- _mesa_lookup_enum_by_nr(type));
-
- if (!ctx->Unpack.ClientStorage)
- return 0;
-
- if (ctx->_ImageTransferState ||
- texImage->IsCompressed || texObj->GenerateMipmap)
- return 0;
-
- /* This list is incomplete, may be different on ppc???
- */
- switch (internalFormat) {
- case GL_RGBA:
- if (format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
- texImage->TexFormat = _dri_texformat_argb8888;
- } else
- return 0;
- break;
-
- case GL_RGB:
- if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
- texImage->TexFormat = _dri_texformat_rgb565;
- } else
- return 0;
- break;
-
- case GL_YCBCR_MESA:
- if (format == GL_YCBCR_MESA &&
- type == GL_UNSIGNED_SHORT_8_8_REV_APPLE) {
- texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
- } else if (format == GL_YCBCR_MESA &&
- (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
- type == GL_UNSIGNED_BYTE)) {
- texImage->TexFormat = &_mesa_texformat_ycbcr;
- } else
- return 0;
- break;
-
- default:
- return 0;
- }
-
- /* Could deal with these packing issues, but currently don't:
- */
- if (packing->SkipPixels ||
- packing->SkipRows || packing->SwapBytes || packing->LsbFirst) {
- return 0;
- }
-
- GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
- format, type);
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: srcRowStride %d/%x\n",
- __FUNCTION__, srcRowStride, srcRowStride);
-
- /* Could check this later in upload, pitch restrictions could be
- * relaxed, but would need to store the image pitch somewhere,
- * as packing details might change before image is uploaded:
- */
- if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride)
- || (srcRowStride & 63))
- return 0;
-
- /* Have validated that _mesa_transfer_teximage would be a straight
- * memcpy at this point. NOTE: future calls to TexSubImage will
- * overwrite the client data. This is explicitly mentioned in the
- * extension spec.
- */
- texImage->Data = (void *)pixels;
- texImage->IsClientData = GL_TRUE;
- texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes;
-
- return 1;
-}
-
-static void r300TexImage1D(GLcontext * ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint border,
- GLenum format, GLenum type, const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
-
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
- return;
- }
- }
-
- /* Note, this will call ChooseTextureFormat */
- _mesa_store_teximage1d(ctx, target, level, internalFormat,
- width, border, format, type, pixels,
- &ctx->Unpack, texObj, texImage);
-
- t->dirty_images[0] |= (1 << level);
-}
-
-static void r300TexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
- GLint xoffset,
- GLsizei width,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
-
- assert(t); /* this _should_ be true */
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
- return;
- }
- }
-
- _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
- format, type, pixels, packing, texObj,
- texImage);
-
- t->dirty_images[0] |= (1 << level);
-}
-
-static void r300TexImage2D(GLcontext * ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLenum format, GLenum type, const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face =
- (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- if (t != NULL) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
- return;
- }
- }
-
- texImage->IsClientData = GL_FALSE;
-
- if (r300ValidateClientStorage(ctx, target,
- internalFormat,
- width, height,
- format, type, pixels,
- packing, texObj, texImage)) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using client storage\n",
- __FUNCTION__);
- } else {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using normal storage\n",
- __FUNCTION__);
-
- /* Normal path: copy (to cached memory) and eventually upload
- * via another copy to GART memory and then a blit... Could
- * eliminate one copy by going straight to (permanent) GART.
- *
- * Note, this will call r300ChooseTextureFormat.
- */
- _mesa_store_teximage2d(ctx, target, level, internalFormat,
- width, height, border, format, type,
- pixels, &ctx->Unpack, texObj, texImage);
-
- t->dirty_images[face] |= (1 << level);
- }
-}
-
-static void r300TexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face =
- (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- assert(t); /* this _should_ be true */
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
- return;
- }
- }
-
- _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
- height, format, type, pixels, packing, texObj,
- texImage);
-
- t->dirty_images[face] |= (1 << level);
-}
-
-static void r300CompressedTexImage2D(GLcontext * ctx, GLenum target,
- GLint level, GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLsizei imageSize, const GLvoid * data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face =
- (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- if (t != NULL) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "glCompressedTexImage2D");
- return;
- }
- }
-
- texImage->IsClientData = GL_FALSE;
-
- /* can't call this, different parameters. Would never evaluate to true anyway currently */
-#if 0
- if (r300ValidateClientStorage(ctx, target,
- internalFormat,
- width, height,
- format, type, pixels,
- packing, texObj, texImage)) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using client storage\n",
- __FUNCTION__);
- } else
-#endif
- {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using normal storage\n",
- __FUNCTION__);
-
- /* Normal path: copy (to cached memory) and eventually upload
- * via another copy to GART memory and then a blit... Could
- * eliminate one copy by going straight to (permanent) GART.
- *
- * Note, this will call r300ChooseTextureFormat.
- */
- _mesa_store_compressed_teximage2d(ctx, target, level,
- internalFormat, width, height,
- border, imageSize, data,
- texObj, texImage);
-
- t->dirty_images[face] |= (1 << level);
- }
-}
-
-static void r300CompressedTexSubImage2D(GLcontext * ctx, GLenum target,
- GLint level, GLint xoffset,
- GLint yoffset, GLsizei width,
- GLsizei height, GLenum format,
- GLsizei imageSize, const GLvoid * data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face =
- (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- assert(t); /* this _should_ be true */
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "glCompressedTexSubImage3D");
- return;
- }
- }
-
- _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset,
- yoffset, width, height, format,
- imageSize, data, texObj, texImage);
-
- t->dirty_images[face] |= (1 << level);
-}
-
-static void r300TexImage3D(GLcontext * ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint depth,
- GLint border,
- GLenum format, GLenum type, const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
-
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
- return;
- }
- }
-
- texImage->IsClientData = GL_FALSE;
-
-#if 0
- if (r300ValidateClientStorage(ctx, target,
- internalFormat,
- width, height,
- format, type, pixels,
- packing, texObj, texImage)) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using client storage\n",
- __FUNCTION__);
- } else
-#endif
- {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: Using normal storage\n",
- __FUNCTION__);
-
- /* Normal path: copy (to cached memory) and eventually upload
- * via another copy to GART memory and then a blit... Could
- * eliminate one copy by going straight to (permanent) GART.
- *
- * Note, this will call r300ChooseTextureFormat.
- */
- _mesa_store_teximage3d(ctx, target, level, internalFormat,
- width, height, depth, border,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage);
-
- t->dirty_images[0] |= (1 << level);
- }
-}
-
-static void
-r300TexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
-
-/* fprintf(stderr, "%s\n", __FUNCTION__); */
-
- assert(t); /* this _should_ be true */
- if (t) {
- driSwapOutTextureObject(t);
- } else {
- t = (driTextureObject *) r300AllocTexObj(texObj);
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
- return;
- }
- texObj->DriverData = t;
- }
-
- _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
- width, height, depth,
- format, type, pixels, packing, texObj,
- texImage);
-
- t->dirty_images[0] |= (1 << level);
-}
-
-/**
* Changes variables and flags for a state update, which will happen at the
* next UpdateTextureState
*/
@@ -908,9 +195,9 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
struct gl_texture_object *texObj,
GLenum pname, const GLfloat * params)
{
- r300TexObjPtr t = (r300TexObjPtr) texObj->DriverData;
+ radeonTexObj* t = radeon_tex_obj(texObj);
- if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
+ if (RADEON_DEBUG & (RADEON_STATE | RADEON_TEXTURE)) {
fprintf(stderr, "%s( %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(pname));
}
@@ -929,7 +216,7 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
break;
case GL_TEXTURE_BORDER_COLOR:
- r300SetTexBorderColor(t, texObj->_BorderChan);
+ r300SetTexBorderColor(t, texObj->BorderColor);
break;
case GL_TEXTURE_BASE_LEVEL:
@@ -941,7 +228,11 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
- driSwapOutTextureObject((driTextureObject *) t);
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = 0;
+ t->validated = GL_FALSE;
+ }
break;
case GL_DEPTH_TEXTURE_MODE:
@@ -964,42 +255,35 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
}
}
-static void r300BindTexture(GLcontext * ctx, GLenum target,
- struct gl_texture_object *texObj)
-{
- if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
- fprintf(stderr, "%s( %p ) unit=%d\n", __FUNCTION__,
- (void *)texObj, ctx->Texture.CurrentUnit);
- }
-
- if ((target == GL_TEXTURE_1D)
- || (target == GL_TEXTURE_2D)
- || (target == GL_TEXTURE_3D)
- || (target == GL_TEXTURE_CUBE_MAP)
- || (target == GL_TEXTURE_RECTANGLE_NV)) {
- assert(texObj->DriverData != NULL);
- }
-}
-
static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- driTextureObject *t = (driTextureObject *) texObj->DriverData;
+ radeonTexObj* t = radeon_tex_obj(texObj);
- if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
+ if (RADEON_DEBUG & (RADEON_STATE | RADEON_TEXTURE)) {
fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
(void *)texObj,
_mesa_lookup_enum_by_nr(texObj->Target));
}
- if (t != NULL) {
- if (rmesa) {
- R300_FIREVERTICES(rmesa);
- }
+ if (rmesa) {
+ int i;
+ radeon_firevertices(&rmesa->radeon);
+
+ for(i = 0; i < R300_MAX_TEXTURE_UNITS; ++i)
+ if (rmesa->hw.textures[i] == t)
+ rmesa->hw.textures[i] = 0;
+ }
- driDestroyTextureObject(t);
+ if (t->bo) {
+ radeon_bo_unref(t->bo);
+ t->bo = NULL;
+ }
+
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = 0;
}
- /* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, texObj);
}
@@ -1008,8 +292,6 @@ static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
* Called via ctx->Driver.NewTextureObject.
* Note: this function will be called during context creation to
* allocate the default texture objects.
- * Note: we could use containment here to 'derive' the driver-specific
- * texture object from the core mesa gl_texture_object. Not done at this time.
* Fixup MaxAnisotropy according to user preference.
*/
static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx,
@@ -1017,14 +299,23 @@ static struct gl_texture_object *r300NewTextureObject(GLcontext * ctx,
GLenum target)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct gl_texture_object *obj;
- obj = _mesa_new_texture_object(ctx, name, target);
- if (!obj)
- return NULL;
- obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
+ radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj);
+
- r300AllocTexObj(obj);
- return obj;
+ if (RADEON_DEBUG & (RADEON_STATE | RADEON_TEXTURE)) {
+ fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
+ t, _mesa_lookup_enum_by_nr(target));
+ }
+
+ _mesa_initialize_texture_object(&t->base, name, target);
+ t->base.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
+
+ /* Initialize hardware state */
+ r300UpdateTexWrap(t);
+ r300SetTexFilter(t, t->base.MinFilter, t->base.MagFilter, t->base.MaxAnisotropy);
+ r300SetTexBorderColor(t, t->base.BorderColor);
+
+ return &t->base;
}
void r300InitTextureFuncs(struct dd_function_table *functions)
@@ -1032,22 +323,30 @@ void r300InitTextureFuncs(struct dd_function_table *functions)
/* Note: we only plug in the functions we implement in the driver
* since _mesa_init_driver_functions() was already called.
*/
- functions->ChooseTextureFormat = r300ChooseTextureFormat;
- functions->TexImage1D = r300TexImage1D;
- functions->TexImage2D = r300TexImage2D;
- functions->TexImage3D = r300TexImage3D;
- functions->TexSubImage1D = r300TexSubImage1D;
- functions->TexSubImage2D = r300TexSubImage2D;
- functions->TexSubImage3D = r300TexSubImage3D;
+ functions->NewTextureImage = radeonNewTextureImage;
+ functions->FreeTexImageData = radeonFreeTexImageData;
+ functions->MapTexture = radeonMapTexture;
+ functions->UnmapTexture = radeonUnmapTexture;
+
+ functions->ChooseTextureFormat = radeonChooseTextureFormat_mesa;
+ functions->TexImage1D = radeonTexImage1D;
+ functions->TexImage2D = radeonTexImage2D;
+ functions->TexImage3D = radeonTexImage3D;
+ functions->TexSubImage1D = radeonTexSubImage1D;
+ functions->TexSubImage2D = radeonTexSubImage2D;
+ functions->TexSubImage3D = radeonTexSubImage3D;
+ functions->GetTexImage = radeonGetTexImage;
+ functions->GetCompressedTexImage = radeonGetCompressedTexImage;
functions->NewTextureObject = r300NewTextureObject;
- functions->BindTexture = r300BindTexture;
functions->DeleteTexture = r300DeleteTexture;
functions->IsTextureResident = driIsTextureResident;
functions->TexParameter = r300TexParameter;
- functions->CompressedTexImage2D = r300CompressedTexImage2D;
- functions->CompressedTexSubImage2D = r300CompressedTexSubImage2D;
+ functions->CompressedTexImage2D = radeonCompressedTexImage2D;
+ functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
+
+ functions->GenerateMipmap = radeonGenerateMipmap;
driInitTextureFormats();
}
diff --git a/src/mesa/drivers/dri/r300/r300_tex.h b/src/mesa/drivers/dri/r300/r300_tex.h
index b86d45bfe0..8a653ea2d1 100644
--- a/src/mesa/drivers/dri/r300/r300_tex.h
+++ b/src/mesa/drivers/dri/r300/r300_tex.h
@@ -37,16 +37,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
extern void r300SetDepthTexMode(struct gl_texture_object *tObj);
+extern void r300SetTexBuffer(__DRIcontext *pDRICtx, GLint target,
+ __DRIdrawable *dPriv);
+
+extern void r300SetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
+ GLint format, __DRIdrawable *dPriv);
+
extern void r300SetTexOffset(__DRIcontext *pDRICtx, GLint texname,
unsigned long long offset, GLint depth,
GLuint pitch);
-extern void r300UpdateTextureState(GLcontext * ctx);
-
-extern int r300UploadTexImages(r300ContextPtr rmesa, r300TexObjPtr t,
- GLuint face);
-
-extern void r300DestroyTexObj(r300ContextPtr rmesa, r300TexObjPtr t);
+extern GLboolean r300ValidateBuffers(GLcontext * ctx);
extern void r300InitTextureFuncs(struct dd_function_table *functions);
diff --git a/src/mesa/drivers/dri/r300/r300_texmem.c b/src/mesa/drivers/dri/r300/r300_texmem.c
deleted file mode 100644
index b03eefaa7c..0000000000
--- a/src/mesa/drivers/dri/r300/r300_texmem.c
+++ /dev/null
@@ -1,567 +0,0 @@
-/**************************************************************************
-
-Copyright (C) Tungsten Graphics 2002. All Rights Reserved.
-The Weather Channel, Inc. funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86
-license. This notice must be preserved.
-
-Permission is hereby granted, free of charge, to 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 ATI, VA LINUX SYSTEMS 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.
-
-**************************************************************************/
-
-/**
- * \file
- *
- * \author Gareth Hughes <gareth@valinux.com>
- *
- * \author Kevin E. Martin <martin@valinux.com>
- */
-
-#include <errno.h>
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/colormac.h"
-#include "main/macros.h"
-#include "main/simple_list.h"
-#include "radeon_reg.h" /* gets definition for usleep */
-#include "r300_context.h"
-#include "r300_state.h"
-#include "r300_cmdbuf.h"
-#include "radeon_ioctl.h"
-#include "r300_tex.h"
-#include "r300_ioctl.h"
-#include <unistd.h> /* for usleep() */
-
-#ifdef USER_BUFFERS
-#include "r300_mem.h"
-#endif
-
-/**
- * Destroy any device-dependent state associated with the texture. This may
- * include NULLing out hardware state that points to the texture.
- */
-void r300DestroyTexObj(r300ContextPtr rmesa, r300TexObjPtr t)
-{
- int i;
-
- if (RADEON_DEBUG & DEBUG_TEXTURE) {
- fprintf(stderr, "%s( %p, %p )\n", __FUNCTION__,
- (void *)t, (void *)t->base.tObj);
- }
-
- for (i = 0; i < rmesa->radeon.glCtx->Const.MaxTextureUnits; i++) {
- if (rmesa->state.texture.unit[i].texobj == t) {
- rmesa->state.texture.unit[i].texobj = NULL;
- }
- }
-}
-
-/* ------------------------------------------------------------
- * Texture image conversions
- */
-
-static void r300UploadGARTClientSubImage(r300ContextPtr rmesa,
- r300TexObjPtr t,
- struct gl_texture_image *texImage,
- GLint hwlevel,
- GLint x, GLint y,
- GLint width, GLint height)
-{
- const struct gl_texture_format *texFormat = texImage->TexFormat;
- GLuint srcPitch, dstPitch;
- int blit_format;
- int srcOffset;
-
- /*
- * XXX it appears that we always upload the full image, not a subimage.
- * I.e. x==0, y==0, width=texWidth, height=texWidth. If this is ever
- * changed, the src pitch will have to change.
- */
- switch (texFormat->TexelBytes) {
- case 1:
- blit_format = R300_CP_COLOR_FORMAT_CI8;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 2:
- blit_format = R300_CP_COLOR_FORMAT_RGB565;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 4:
- blit_format = R300_CP_COLOR_FORMAT_ARGB8888;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 8:
- case 16:
- blit_format = R300_CP_COLOR_FORMAT_CI8;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- default:
- return;
- }
-
- t->image[0][hwlevel].data = texImage->Data;
- srcOffset = r300GartOffsetFromVirtual(rmesa, texImage->Data);
-
- assert(srcOffset != ~0);
-
- /* Don't currently need to cope with small pitches?
- */
- width = texImage->Width;
- height = texImage->Height;
-
- if (texFormat->TexelBytes > 4) {
- width *= texFormat->TexelBytes;
- }
-
- r300EmitWait(rmesa, R300_WAIT_3D);
-
- r300EmitBlit(rmesa, blit_format,
- srcPitch,
- srcOffset,
- dstPitch,
- t->bufAddr,
- x,
- y,
- t->image[0][hwlevel].x + x,
- t->image[0][hwlevel].y + y, width, height);
-
- r300EmitWait(rmesa, R300_WAIT_2D);
-}
-
-static void r300UploadRectSubImage(r300ContextPtr rmesa,
- r300TexObjPtr t,
- struct gl_texture_image *texImage,
- GLint x, GLint y, GLint width, GLint height)
-{
- const struct gl_texture_format *texFormat = texImage->TexFormat;
- int blit_format, dstPitch, done;
-
- switch (texFormat->TexelBytes) {
- case 1:
- blit_format = R300_CP_COLOR_FORMAT_CI8;
- break;
- case 2:
- blit_format = R300_CP_COLOR_FORMAT_RGB565;
- break;
- case 4:
- blit_format = R300_CP_COLOR_FORMAT_ARGB8888;
- break;
- case 8:
- case 16:
- blit_format = R300_CP_COLOR_FORMAT_CI8;
- break;
- default:
- return;
- }
-
- t->image[0][0].data = texImage->Data;
-
- /* Currently don't need to cope with small pitches.
- */
- width = texImage->Width;
- height = texImage->Height;
- dstPitch = t->pitch;
-
- if (texFormat->TexelBytes > 4) {
- width *= texFormat->TexelBytes;
- }
-
- if (rmesa->prefer_gart_client_texturing && texImage->IsClientData) {
- /* In this case, could also use GART texturing. This is
- * currently disabled, but has been tested & works.
- */
- t->offset = r300GartOffsetFromVirtual(rmesa, texImage->Data);
- t->pitch = texImage->RowStride * texFormat->TexelBytes - 32;
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "Using GART texturing for rectangular client texture\n");
-
- /* Release FB memory allocated for this image:
- */
- /* FIXME This may not be correct as driSwapOutTextureObject sets
- * FIXME dirty_images. It may be fine, though.
- */
- if (t->base.memBlock) {
- driSwapOutTextureObject((driTextureObject *) t);
- }
- } else if (texImage->IsClientData) {
- /* Data already in GART memory, with usable pitch.
- */
- GLuint srcPitch;
- srcPitch = texImage->RowStride * texFormat->TexelBytes;
- r300EmitBlit(rmesa,
- blit_format,
- srcPitch,
- r300GartOffsetFromVirtual(rmesa, texImage->Data),
- dstPitch, t->bufAddr, 0, 0, 0, 0, width, height);
- } else {
- /* Data not in GART memory, or bad pitch.
- */
- for (done = 0; done < height;) {
- struct r300_dma_region region;
- int lines =
- MIN2(height - done, RADEON_BUFFER_SIZE / dstPitch);
- int src_pitch;
- char *tex;
-
- src_pitch = texImage->RowStride * texFormat->TexelBytes;
-
- tex = (char *)texImage->Data + done * src_pitch;
-
- memset(&region, 0, sizeof(region));
- r300AllocDmaRegion(rmesa, &region, lines * dstPitch,
- 1024);
-
- /* Copy texdata to dma:
- */
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "%s: src_pitch %d dst_pitch %d\n",
- __FUNCTION__, src_pitch, dstPitch);
-
- if (src_pitch == dstPitch) {
- memcpy(region.address + region.start, tex,
- lines * src_pitch);
- } else {
- char *buf = region.address + region.start;
- int i;
- for (i = 0; i < lines; i++) {
- memcpy(buf, tex, src_pitch);
- buf += dstPitch;
- tex += src_pitch;
- }
- }
-
- r300EmitWait(rmesa, R300_WAIT_3D);
-
- /* Blit to framebuffer
- */
- r300EmitBlit(rmesa,
- blit_format,
- dstPitch, GET_START(&region),
- dstPitch | (t->tile_bits >> 16),
- t->bufAddr, 0, 0, 0, done, width, lines);
-
- r300EmitWait(rmesa, R300_WAIT_2D);
-#ifdef USER_BUFFERS
- r300_mem_use(rmesa, region.buf->id);
-#endif
-
- r300ReleaseDmaRegion(rmesa, &region, __FUNCTION__);
- done += lines;
- }
- }
-}
-
-/**
- * Upload the texture image associated with texture \a t at the specified
- * level at the address relative to \a start.
- */
-static void r300UploadSubImage(r300ContextPtr rmesa, r300TexObjPtr t,
- GLint hwlevel,
- GLint x, GLint y, GLint width, GLint height,
- GLuint face)
-{
- struct gl_texture_image *texImage = NULL;
- GLuint offset;
- GLint imageWidth, imageHeight;
- GLint ret;
- drm_radeon_texture_t tex;
- drm_radeon_tex_image_t tmp;
- const int level = hwlevel + t->base.firstLevel;
-
- if (RADEON_DEBUG & DEBUG_TEXTURE) {
- fprintf(stderr,
- "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n",
- __FUNCTION__, (void *)t, (void *)t->base.tObj, level,
- width, height, face);
- }
-
- ASSERT(face < 6);
-
- /* Ensure we have a valid texture to upload */
- if ((hwlevel < 0) || (hwlevel >= RADEON_MAX_TEXTURE_LEVELS)) {
- _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
- return;
- }
-
- texImage = t->base.tObj->Image[face][level];
-
- if (!texImage) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: texImage %d is NULL!\n",
- __FUNCTION__, level);
- return;
- }
- if (!texImage->Data) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: image data is NULL!\n",
- __FUNCTION__);
- return;
- }
-
- if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- assert(level == 0);
- assert(hwlevel == 0);
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: image data is rectangular\n",
- __FUNCTION__);
- r300UploadRectSubImage(rmesa, t, texImage, x, y, width, height);
- return;
- } else if (texImage->IsClientData) {
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "%s: image data is in GART client storage\n",
- __FUNCTION__);
- r300UploadGARTClientSubImage(rmesa, t, texImage, hwlevel, x, y,
- width, height);
- return;
- } else if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "%s: image data is in normal memory\n",
- __FUNCTION__);
-
- imageWidth = texImage->Width;
- imageHeight = texImage->Height;
-
- offset = t->bufAddr;
-
- if (RADEON_DEBUG & (DEBUG_TEXTURE | DEBUG_IOCTL)) {
- GLint imageX = 0;
- GLint imageY = 0;
- GLint blitX = t->image[face][hwlevel].x;
- GLint blitY = t->image[face][hwlevel].y;
- GLint blitWidth = t->image[face][hwlevel].width;
- GLint blitHeight = t->image[face][hwlevel].height;
- fprintf(stderr, " upload image: %d,%d at %d,%d\n",
- imageWidth, imageHeight, imageX, imageY);
- fprintf(stderr, " upload blit: %d,%d at %d,%d\n",
- blitWidth, blitHeight, blitX, blitY);
- fprintf(stderr, " blit ofs: 0x%07x level: %d/%d\n",
- (GLuint) offset, hwlevel, level);
- }
-
- t->image[face][hwlevel].data = texImage->Data;
-
- /* Init the DRM_RADEON_TEXTURE command / drm_radeon_texture_t struct.
- * NOTE: we're always use a 1KB-wide blit and I8 texture format.
- * We used to use 1, 2 and 4-byte texels and used to use the texture
- * width to dictate the blit width - but that won't work for compressed
- * textures. (Brian)
- * NOTE: can't do that with texture tiling. (sroland)
- */
- tex.offset = offset;
- tex.image = &tmp;
- /* copy (x,y,width,height,data) */
- memcpy(&tmp, &t->image[face][hwlevel], sizeof(tmp));
-
- if (texImage->TexFormat->TexelBytes > 4) {
- const int log2TexelBytes =
- (3 + (texImage->TexFormat->TexelBytes >> 4));
- tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */
- tex.pitch =
- MAX2((texImage->Width * texImage->TexFormat->TexelBytes) /
- 64, 1);
- tex.height = imageHeight;
- tex.width = imageWidth << log2TexelBytes;
- tex.offset += (tmp.x << log2TexelBytes) & ~1023;
- tmp.x = tmp.x % (1024 >> log2TexelBytes);
- tmp.width = tmp.width << log2TexelBytes;
- } else if (texImage->TexFormat->TexelBytes) {
- /* use multi-byte upload scheme */
- tex.height = imageHeight;
- tex.width = imageWidth;
- switch (texImage->TexFormat->TexelBytes) {
- case 1:
- tex.format = RADEON_TXFORMAT_I8;
- break;
- case 2:
- tex.format = RADEON_TXFORMAT_AI88;
- break;
- case 4:
- tex.format = RADEON_TXFORMAT_ARGB8888;
- break;
- }
- tex.pitch =
- MAX2((texImage->Width * texImage->TexFormat->TexelBytes) /
- 64, 1);
- tex.offset += tmp.x & ~1023;
- tmp.x = tmp.x % 1024;
-
- if (t->tile_bits & R300_TXO_MICRO_TILE) {
- /* need something like "tiled coordinates" ? */
- tmp.y = tmp.x / (tex.pitch * 128) * 2;
- tmp.x =
- tmp.x % (tex.pitch * 128) / 2 /
- texImage->TexFormat->TexelBytes;
- tex.pitch |= RADEON_DST_TILE_MICRO >> 22;
- } else {
- tmp.x = tmp.x >> (texImage->TexFormat->TexelBytes >> 1);
- }
-#if 1
- if ((t->tile_bits & R300_TXO_MACRO_TILE) &&
- (texImage->Width * texImage->TexFormat->TexelBytes >= 256)
- && ((!(t->tile_bits & R300_TXO_MICRO_TILE)
- && (texImage->Height >= 8))
- || (texImage->Height >= 16))) {
- /* weird: R200 disables macro tiling if mip width is smaller than 256 bytes,
- OR if height is smaller than 8 automatically, but if micro tiling is active
- the limit is height 16 instead ? */
- tex.pitch |= RADEON_DST_TILE_MACRO >> 22;
- }
-#endif
- } else {
- /* In case of for instance 8x8 texture (2x2 dxt blocks),
- padding after the first two blocks is needed (only
- with dxt1 since 2 dxt3/dxt5 blocks already use 32 Byte). */
- /* set tex.height to 1/4 since 1 "macropixel" (dxt-block)
- has 4 real pixels. Needed so the kernel module reads
- the right amount of data. */
- tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */
- tex.pitch = (R300_BLIT_WIDTH_BYTES / 64);
- tex.height = (imageHeight + 3) / 4;
- tex.width = (imageWidth + 3) / 4;
- if ((t->format & R300_TX_FORMAT_DXT1) == R300_TX_FORMAT_DXT1) {
- tex.width *= 8;
- } else {
- tex.width *= 16;
- }
- }
-
- LOCK_HARDWARE(&rmesa->radeon);
- do {
- ret =
- drmCommandWriteRead(rmesa->radeon.dri.fd,
- DRM_RADEON_TEXTURE, &tex,
- sizeof(drm_radeon_texture_t));
- if (ret) {
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr,
- "DRM_RADEON_TEXTURE: again!\n");
- usleep(1);
- }
- } while (ret == -EAGAIN);
-
- UNLOCK_HARDWARE(&rmesa->radeon);
-
- if (ret) {
- fprintf(stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret);
- fprintf(stderr, " offset=0x%08x\n", offset);
- fprintf(stderr, " image width=%d height=%d\n",
- imageWidth, imageHeight);
- fprintf(stderr, " blit width=%d height=%d data=%p\n",
- t->image[face][hwlevel].width,
- t->image[face][hwlevel].height,
- t->image[face][hwlevel].data);
- _mesa_exit(-1);
- }
-}
-
-/**
- * Upload the texture images associated with texture \a t. This might
- * require the allocation of texture memory.
- *
- * \param rmesa Context pointer
- * \param t Texture to be uploaded
- * \param face Cube map face to be uploaded. Zero for non-cube maps.
- */
-
-int r300UploadTexImages(r300ContextPtr rmesa, r300TexObjPtr t, GLuint face)
-{
- const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
-
- if (t->image_override)
- return 0;
-
- if (RADEON_DEBUG & (DEBUG_TEXTURE | DEBUG_IOCTL)) {
- fprintf(stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
- (void *)rmesa->radeon.glCtx, (void *)t->base.tObj,
- t->base.totalSize, t->base.firstLevel,
- t->base.lastLevel);
- }
-
- if (t->base.totalSize == 0)
- return 0;
-
- if (RADEON_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
- radeonFinish(rmesa->radeon.glCtx);
- }
-
- LOCK_HARDWARE(&rmesa->radeon);
-
- if (t->base.memBlock == NULL) {
- int heap;
-
- heap = driAllocateTexture(rmesa->texture_heaps, rmesa->nr_heaps,
- (driTextureObject *) t);
- if (heap == -1) {
- UNLOCK_HARDWARE(&rmesa->radeon);
- return -1;
- }
-
- /* Set the base offset of the texture image */
- t->bufAddr = rmesa->radeon.radeonScreen->texOffset[heap]
- + t->base.memBlock->ofs;
- t->offset = t->bufAddr;
-
- if (!(t->base.tObj->Image[0][0]->IsClientData)) {
- /* hope it's safe to add that here... */
- t->offset |= t->tile_bits;
- }
- }
-
- /* Let the world know we've used this memory recently.
- */
- driUpdateTextureLRU((driTextureObject *) t);
- UNLOCK_HARDWARE(&rmesa->radeon);
-
- /* Upload any images that are new */
- if (t->base.dirty_images[face]) {
- int i;
- for (i = 0; i < numLevels; i++) {
- if ((t->base.
- dirty_images[face] & (1 <<
- (i + t->base.firstLevel))) !=
- 0) {
- r300UploadSubImage(rmesa, t, i, 0, 0,
- t->image[face][i].width,
- t->image[face][i].height,
- face);
- }
- }
- t->base.dirty_images[face] = 0;
- }
-
- if (RADEON_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
- radeonFinish(rmesa->radeon.glCtx);
- }
-
- return 0;
-}
diff --git a/src/mesa/drivers/dri/r300/r300_texstate.c b/src/mesa/drivers/dri/r300/r300_texstate.c
index e2329f04ec..f030451b28 100644
--- a/src/mesa/drivers/dri/r300/r300_texstate.c
+++ b/src/mesa/drivers/dri/r300/r300_texstate.c
@@ -43,11 +43,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/teximage.h"
#include "main/texobj.h"
#include "main/enums.h"
+#include "main/simple_list.h"
#include "r300_context.h"
#include "r300_state.h"
#include "r300_ioctl.h"
-#include "radeon_ioctl.h"
+#include "radeon_mipmap_tree.h"
#include "r300_tex.h"
#include "r300_reg.h"
@@ -117,7 +118,12 @@ static const struct tx_table {
_ASSIGN(INTENSITY_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, X, FL_I16)),
_ASSIGN(Z16, R300_EASY_TX_FORMAT(X, X, X, X, X16)),
_ASSIGN(Z24_S8, R300_EASY_TX_FORMAT(X, X, X, X, X24_Y8)),
+ _ASSIGN(S8_Z24, R300_EASY_TX_FORMAT(Y, Y, Y, Y, X24_Y8)),
_ASSIGN(Z32, R300_EASY_TX_FORMAT(X, X, X, X, X32)),
+ /* EXT_texture_sRGB */
+ _ASSIGN(SRGBA8, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8) | R300_TX_FORMAT_GAMMA),
+ _ASSIGN(SLA8, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8) | R300_TX_FORMAT_GAMMA),
+ _ASSIGN(SL8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8) | R300_TX_FORMAT_GAMMA),
/* *INDENT-ON* */
};
@@ -143,13 +149,12 @@ void r300SetDepthTexMode(struct gl_texture_object *tObj)
},
};
const GLuint *format;
- r300TexObjPtr t;
+ radeonTexObjPtr t;
if (!tObj)
return;
- t = (r300TexObjPtr) tObj->DriverData;
-
+ t = radeon_tex_obj(tObj);
switch (tObj->Image[0][tObj->BaseLevel]->TexFormat->MesaFormat) {
case MESA_FORMAT_Z16:
@@ -171,13 +176,13 @@ void r300SetDepthTexMode(struct gl_texture_object *tObj)
switch (tObj->DepthMode) {
case GL_LUMINANCE:
- t->format = format[0];
+ t->pp_txformat = format[0];
break;
case GL_INTENSITY:
- t->format = format[1];
+ t->pp_txformat = format[1];
break;
case GL_ALPHA:
- t->format = format[2];
+ t->pp_txformat = format[2];
break;
default:
/* Error...which should have already been caught by higher
@@ -190,479 +195,307 @@ void r300SetDepthTexMode(struct gl_texture_object *tObj)
/**
- * Compute sizes and fill in offset and blit information for the given
- * image (determined by \p face and \p level).
- *
- * \param curOffset points to the offset at which the image is to be stored
- * and is updated by this function according to the size of the image.
- */
-static void compute_tex_image_offset(
- struct gl_texture_object *tObj,
- GLuint face,
- GLint level,
- GLint* curOffset)
-{
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
- const struct gl_texture_image* texImage;
- GLuint blitWidth = R300_BLIT_WIDTH_BYTES;
- GLuint texelBytes;
- GLuint size;
-
- texImage = tObj->Image[0][level + t->base.firstLevel];
- if (!texImage)
- return;
-
- texelBytes = texImage->TexFormat->TexelBytes;
-
- /* find image size in bytes */
- if (texImage->IsCompressed) {
- if ((t->format & R300_TX_FORMAT_DXT1) ==
- R300_TX_FORMAT_DXT1) {
- // fprintf(stderr,"DXT 1 %d %08X\n", texImage->Width, t->format);
- if ((texImage->Width + 3) < 8) /* width one block */
- size = texImage->CompressedSize * 4;
- else if ((texImage->Width + 3) < 16)
- size = texImage->CompressedSize * 2;
- else
- size = texImage->CompressedSize;
- } else {
- /* DXT3/5, 16 bytes per block */
- WARN_ONCE
- ("DXT 3/5 suffers from multitexturing problems!\n");
- // fprintf(stderr,"DXT 3/5 %d\n", texImage->Width);
- if ((texImage->Width + 3) < 8)
- size = texImage->CompressedSize * 2;
- else
- size = texImage->CompressedSize;
- }
- } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- size =
- ((texImage->Width * texelBytes +
- 63) & ~63) * texImage->Height;
- blitWidth = 64 / texelBytes;
- } else if (t->tile_bits & R300_TXO_MICRO_TILE) {
- /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
- though the actual offset may be different (if texture is less than
- 32 bytes width) to the untiled case */
- int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
- size =
- (w * ((texImage->Height + 1) / 2)) *
- texImage->Depth;
- blitWidth = MAX2(texImage->Width, 64 / texelBytes);
- } else {
- int w = (texImage->Width * texelBytes + 31) & ~31;
- size = w * texImage->Height * texImage->Depth;
- blitWidth = MAX2(texImage->Width, 64 / texelBytes);
- }
- assert(size > 0);
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n",
- texImage->Width, texImage->Height,
- texImage->Depth,
- texImage->TexFormat->TexelBytes,
- texImage->InternalFormat);
-
- /* All images are aligned to a 32-byte offset */
- *curOffset = (*curOffset + 0x1f) & ~0x1f;
-
- if (texelBytes) {
- /* fix x and y coords up later together with offset */
- t->image[face][level].x = *curOffset;
- t->image[face][level].y = 0;
- t->image[face][level].width =
- MIN2(size / texelBytes, blitWidth);
- t->image[face][level].height =
- (size / texelBytes) / t->image[face][level].width;
- } else {
- t->image[face][level].x = *curOffset % R300_BLIT_WIDTH_BYTES;
- t->image[face][level].y = *curOffset / R300_BLIT_WIDTH_BYTES;
- t->image[face][level].width =
- MIN2(size, R300_BLIT_WIDTH_BYTES);
- t->image[face][level].height = size / t->image[face][level].width;
- }
-
- if (RADEON_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "level %d, face %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
- level, face, texImage->Width, texImage->Height,
- t->image[face][level].x, t->image[face][level].y,
- t->image[face][level].width, t->image[face][level].height,
- size, *curOffset);
-
- *curOffset += size;
-}
-
-
-
-/**
- * This function computes the number of bytes of storage needed for
- * the given texture object (all mipmap levels, all cube faces).
- * The \c image[face][level].x/y/width/height parameters for upload/blitting
- * are computed here. \c filter, \c format, etc. will be set here
- * too.
+ * Compute the cached hardware register values for the given texture object.
*
* \param rmesa Context pointer
- * \param tObj GL texture object whose images are to be posted to
- * hardware state.
+ * \param t the r300 texture object
*/
-static void r300SetTexImages(r300ContextPtr rmesa,
- struct gl_texture_object *tObj)
+static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
{
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
- const struct gl_texture_image *baseImage =
- tObj->Image[0][tObj->BaseLevel];
- GLint curOffset;
- GLint i, texelBytes;
- GLint numLevels;
- GLint log2Width, log2Height, log2Depth;
-
- /* Set the hardware texture format
- */
+ const struct gl_texture_image *firstImage;
+ int firstlevel = t->mt ? t->mt->firstLevel : 0;
+
+ firstImage = t->base.Image[0][firstlevel];
+
if (!t->image_override
- && VALID_FORMAT(baseImage->TexFormat->MesaFormat)) {
- if (baseImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
- r300SetDepthTexMode(tObj);
+ && VALID_FORMAT(firstImage->TexFormat->MesaFormat)) {
+ if (firstImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
+ r300SetDepthTexMode(&t->base);
} else {
- t->format = tx_table[baseImage->TexFormat->MesaFormat].format;
+ t->pp_txformat = tx_table[firstImage->TexFormat->MesaFormat].format;
}
- t->filter |= tx_table[baseImage->TexFormat->MesaFormat].filter;
+ t->pp_txfilter |= tx_table[firstImage->TexFormat->MesaFormat].filter;
} else if (!t->image_override) {
_mesa_problem(NULL, "unexpected texture format in %s",
__FUNCTION__);
return;
}
- texelBytes = baseImage->TexFormat->TexelBytes;
-
- /* Compute which mipmap levels we really want to send to the hardware.
- */
- driCalculateTextureFirstLastLevel((driTextureObject *) t);
- log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
- log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
- log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
-
- numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+ if (t->image_override && t->bo)
+ return;
- assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
+ t->pp_txsize = (((firstImage->Width - 1) << R300_TX_WIDTHMASK_SHIFT)
+ | ((firstImage->Height - 1) << R300_TX_HEIGHTMASK_SHIFT)
+ | ((firstImage->DepthLog2) << R300_TX_DEPTHMASK_SHIFT)
+ | ((t->mt->lastLevel - t->mt->firstLevel) << R300_TX_MAX_MIP_LEVEL_SHIFT));
- /* Calculate mipmap offsets and dimensions for blitting (uploading)
- * The idea is that we lay out the mipmap levels within a block of
- * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
- */
t->tile_bits = 0;
- /* figure out if this texture is suitable for tiling. */
-#if 0 /* Disabled for now */
- if (texelBytes) {
- if ((tObj->Target != GL_TEXTURE_RECTANGLE_NV) &&
- /* texrect might be able to use micro tiling too in theory? */
- (baseImage->Height > 1)) {
-
- /* allow 32 (bytes) x 1 mip (which will use two times the space
- the non-tiled version would use) max if base texture is large enough */
- if ((numLevels == 1) ||
- (((baseImage->Width * texelBytes /
- baseImage->Height) <= 32)
- && (baseImage->Width * texelBytes > 64))
- ||
- ((baseImage->Width * texelBytes /
- baseImage->Height) <= 16)) {
- t->tile_bits |= R300_TXO_MICRO_TILE;
- }
- }
-
- if (tObj->Target != GL_TEXTURE_RECTANGLE_NV) {
- /* we can set macro tiling even for small textures, they will be untiled anyway */
- t->tile_bits |= R300_TXO_MACRO_TILE;
- }
- }
-#endif
+ if (t->base.Target == GL_TEXTURE_CUBE_MAP)
+ t->pp_txformat |= R300_TX_FORMAT_CUBIC_MAP;
+ if (t->base.Target == GL_TEXTURE_3D)
+ t->pp_txformat |= R300_TX_FORMAT_3D;
- curOffset = 0;
- if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
- ASSERT(log2Width == log2Height);
- t->format |= R300_TX_FORMAT_CUBIC_MAP;
-
- for(i = 0; i < numLevels; i++) {
- GLuint face;
- for(face = 0; face < 6; face++)
- compute_tex_image_offset(tObj, face, i, &curOffset);
- }
- } else {
- if (tObj->Target == GL_TEXTURE_3D)
- t->format |= R300_TX_FORMAT_3D;
-
- for (i = 0; i < numLevels; i++)
- compute_tex_image_offset(tObj, 0, i, &curOffset);
- }
-
- /* Align the total size of texture memory block.
- */
- t->base.totalSize =
- (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
-
- t->size =
- (((tObj->Image[0][t->base.firstLevel]->Width -
- 1) << R300_TX_WIDTHMASK_SHIFT)
- | ((tObj->Image[0][t->base.firstLevel]->Height - 1) <<
- R300_TX_HEIGHTMASK_SHIFT)
- | ((tObj->Image[0][t->base.firstLevel]->DepthLog2) <<
- R300_TX_DEPTHMASK_SHIFT))
- | ((numLevels - 1) << R300_TX_MAX_MIP_LEVEL_SHIFT);
-
- t->pitch = 0;
-
- /* Only need to round to nearest 32 for textures, but the blitter
- * requires 64-byte aligned pitches, and we may/may not need the
- * blitter. NPOT only!
- */
- if (baseImage->IsCompressed) {
- t->pitch |=
- (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
- } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- unsigned int align = (64 / texelBytes) - 1;
- t->pitch |= ((tObj->Image[0][t->base.firstLevel]->Width *
- texelBytes) + 63) & ~(63);
- t->size |= R300_TX_SIZE_TXPITCH_EN;
+ if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
+ unsigned int align = (64 / t->mt->bpp) - 1;
+ t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
if (!t->image_override)
- t->pitch_reg =
- (((tObj->Image[0][t->base.firstLevel]->Width) +
- align) & ~align) - 1;
- } else {
- t->pitch |=
- ((tObj->Image[0][t->base.firstLevel]->Width *
- texelBytes) + 63) & ~(63);
+ t->pp_txpitch = ((firstImage->Width + align) & ~align) - 1;
}
if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
- if (tObj->Image[0][t->base.firstLevel]->Width > 2048)
- t->pitch_reg |= R500_TXWIDTH_BIT11;
- if (tObj->Image[0][t->base.firstLevel]->Height > 2048)
- t->pitch_reg |= R500_TXHEIGHT_BIT11;
+ if (firstImage->Width > 2048)
+ t->pp_txpitch |= R500_TXWIDTH_BIT11;
+ if (firstImage->Height > 2048)
+ t->pp_txpitch |= R500_TXHEIGHT_BIT11;
}
}
-/* ================================================================
- * Texture unit state management
+/**
+ * Ensure the given texture is ready for rendering.
+ *
+ * Mostly this means populating the texture object's mipmap tree.
*/
-
-static GLboolean r300EnableTexture2D(GLcontext * ctx, int unit)
+static GLboolean r300_validate_texture(GLcontext * ctx, struct gl_texture_object *texObj)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
-
- ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
+ radeonTexObj *t = radeon_tex_obj(texObj);
- if (t->base.dirty_images[0]) {
- R300_FIREVERTICES(rmesa);
+ if (!radeon_validate_texture_miptree(ctx, texObj))
+ return GL_FALSE;
- r300SetTexImages(rmesa, tObj);
- r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
- if (!t->base.memBlock && !t->image_override)
- return GL_FALSE;
- }
+ /* Configure the hardware registers (more precisely, the cached version
+ * of the hardware registers). */
+ setup_hardware_state(rmesa, t);
+ t->validated = GL_TRUE;
return GL_TRUE;
}
-static GLboolean r300EnableTexture3D(GLcontext * ctx, int unit)
+/**
+ * Ensure all enabled and complete textures are uploaded along with any buffers being used.
+ */
+GLboolean r300ValidateBuffers(GLcontext * ctx)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
+ struct radeon_renderbuffer *rrb;
+ int i;
+ int ret;
- ASSERT(tObj->Target == GL_TEXTURE_3D);
+ radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
- /* r300 does not support mipmaps for 3D textures. */
- if ((tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR)) {
- return GL_FALSE;
+ rrb = radeon_get_colorbuffer(&rmesa->radeon);
+ /* color buffer */
+ if (rrb && rrb->bo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+ rrb->bo, 0,
+ RADEON_GEM_DOMAIN_VRAM);
}
- if (t->base.dirty_images[0]) {
- R300_FIREVERTICES(rmesa);
- r300SetTexImages(rmesa, tObj);
- r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
- if (!t->base.memBlock)
- return GL_FALSE;
+ /* depth buffer */
+ rrb = radeon_get_depthbuffer(&rmesa->radeon);
+ if (rrb && rrb->bo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+ rrb->bo, 0,
+ RADEON_GEM_DOMAIN_VRAM);
}
+
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
+ radeonTexObj *t;
- return GL_TRUE;
-}
-
-static GLboolean r300EnableTextureCube(GLcontext * ctx, int unit)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
- GLuint face;
-
- ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
-
- if (t->base.dirty_images[0] || t->base.dirty_images[1] ||
- t->base.dirty_images[2] || t->base.dirty_images[3] ||
- t->base.dirty_images[4] || t->base.dirty_images[5]) {
- /* flush */
- R300_FIREVERTICES(rmesa);
- /* layout memory space, once for all faces */
- r300SetTexImages(rmesa, tObj);
- }
+ if (!ctx->Texture.Unit[i]._ReallyEnabled)
+ continue;
- /* upload (per face) */
- for (face = 0; face < 6; face++) {
- if (t->base.dirty_images[face]) {
- r300UploadTexImages(rmesa,
- (r300TexObjPtr) tObj->DriverData,
- face);
+ if (!r300_validate_texture(ctx, ctx->Texture.Unit[i]._Current)) {
+ _mesa_warning(ctx,
+ "failed to validate texture for unit %d.\n",
+ i);
}
+ t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
+ if (t->image_override && t->bo)
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+ t->bo,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+ else if (t->mt->bo)
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+ t->mt->bo,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
}
- if (!t->base.memBlock) {
- /* texmem alloc failed, use s/w fallback */
+ ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, first_elem(&rmesa->radeon.dma.reserved)->bo, RADEON_GEM_DOMAIN_GTT, 0);
+ if (ret)
return GL_FALSE;
- }
-
return GL_TRUE;
}
-static GLboolean r300EnableTextureRect(GLcontext * ctx, int unit)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
-
- ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
-
- if (t->base.dirty_images[0]) {
- R300_FIREVERTICES(rmesa);
-
- r300SetTexImages(rmesa, tObj);
- r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
- if (!t->base.memBlock && !t->image_override &&
- !rmesa->prefer_gart_client_texturing)
- return GL_FALSE;
- }
-
- return GL_TRUE;
-}
-
-static GLboolean r300UpdateTexture(GLcontext * ctx, int unit)
-{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
-
- /* Fallback if there's a texture border */
- if (tObj->Image[0][tObj->BaseLevel]->Border > 0)
- return GL_FALSE;
-
- /* Update state if this is a different texture object to last
- * time.
- */
- if (rmesa->state.texture.unit[unit].texobj != t) {
- if (rmesa->state.texture.unit[unit].texobj != NULL) {
- /* The old texture is no longer bound to this texture unit.
- * Mark it as such.
- */
-
- rmesa->state.texture.unit[unit].texobj->base.bound &=
- ~(1 << unit);
- }
-
- rmesa->state.texture.unit[unit].texobj = t;
- t->base.bound |= (1 << unit);
- driUpdateTextureLRU((driTextureObject *) t); /* XXX: should be locked! */
- }
-
- return !t->border_fallback;
-}
-
void r300SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
unsigned long long offset, GLint depth, GLuint pitch)
{
r300ContextPtr rmesa = pDRICtx->driverPrivate;
struct gl_texture_object *tObj =
_mesa_lookup_texture(rmesa->radeon.glCtx, texname);
- r300TexObjPtr t;
+ radeonTexObjPtr t = radeon_tex_obj(tObj);
uint32_t pitch_val;
if (!tObj)
return;
- t = (r300TexObjPtr) tObj->DriverData;
-
t->image_override = GL_TRUE;
if (!offset)
return;
- t->offset = offset;
- t->pitch_reg &= (1 << 13) -1;
+ t->bo = NULL;
+ t->override_offset = offset;
+ t->pp_txpitch &= (1 << 13) -1;
pitch_val = pitch;
switch (depth) {
case 32:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
- t->filter |= tx_table[2].filter;
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
+ t->pp_txfilter |= tx_table[2].filter;
pitch_val /= 4;
break;
case 24:
default:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
- t->filter |= tx_table[4].filter;
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
+ t->pp_txfilter |= tx_table[4].filter;
pitch_val /= 4;
break;
case 16:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
- t->filter |= tx_table[5].filter;
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
+ t->pp_txfilter |= tx_table[5].filter;
pitch_val /= 2;
break;
}
pitch_val--;
- t->pitch_reg |= pitch_val;
+ t->pp_txpitch |= pitch_val;
}
-static GLboolean r300UpdateTextureUnit(GLcontext * ctx, int unit)
+void r300SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format, __DRIdrawable *dPriv)
{
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
-
- if (texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT)) {
- return (r300EnableTextureRect(ctx, unit) &&
- r300UpdateTexture(ctx, unit));
- } else if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
- return (r300EnableTexture2D(ctx, unit) &&
- r300UpdateTexture(ctx, unit));
- } else if (texUnit->_ReallyEnabled & (TEXTURE_3D_BIT)) {
- return (r300EnableTexture3D(ctx, unit) &&
- r300UpdateTexture(ctx, unit));
- } else if (texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT)) {
- return (r300EnableTextureCube(ctx, unit) &&
- r300UpdateTexture(ctx, unit));
- } else if (texUnit->_ReallyEnabled) {
- return GL_FALSE;
- } else {
- return GL_TRUE;
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ struct radeon_renderbuffer *rb;
+ radeon_texture_image *rImage;
+ radeonContextPtr radeon;
+ r300ContextPtr rmesa;
+ struct radeon_framebuffer *rfb;
+ radeonTexObjPtr t;
+ uint32_t pitch_val;
+ uint32_t internalFormat, type, format;
+
+ type = GL_BGRA;
+ format = GL_UNSIGNED_BYTE;
+ internalFormat = (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT ? 3 : 4);
+
+ radeon = pDRICtx->driverPrivate;
+ rmesa = pDRICtx->driverPrivate;
+
+ rfb = dPriv->driverPrivate;
+ texUnit = &radeon->glCtx->Texture.Unit[radeon->glCtx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(radeon->glCtx, texUnit, target);
+ texImage = _mesa_get_tex_image(radeon->glCtx, texObj, target, 0);
+
+ rImage = get_radeon_texture_image(texImage);
+ t = radeon_tex_obj(texObj);
+ if (t == NULL) {
+ return;
+ }
+
+ radeon_update_renderbuffers(pDRICtx, dPriv);
+ /* back & depth buffer are useless free them right away */
+ rb = (void*)rfb->base.Attachment[BUFFER_DEPTH].Renderbuffer;
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
+ rb = (void*)rfb->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
}
+ rb = rfb->color_rb[0];
+ if (rb->bo == NULL) {
+ /* Failed to BO for the buffer */
+ return;
+ }
+
+ _mesa_lock_texture(radeon->glCtx, texObj);
+ if (t->bo) {
+ radeon_bo_unref(t->bo);
+ t->bo = NULL;
+ }
+ if (rImage->bo) {
+ radeon_bo_unref(rImage->bo);
+ rImage->bo = NULL;
+ }
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = NULL;
+ }
+ if (rImage->mt) {
+ radeon_miptree_unreference(rImage->mt);
+ rImage->mt = NULL;
+ }
+ _mesa_init_teximage_fields(radeon->glCtx, target, texImage,
+ rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
+ texImage->RowStride = rb->pitch / rb->cpp;
+ texImage->TexFormat = radeonChooseTextureFormat(radeon->glCtx,
+ internalFormat,
+ type, format, 0);
+ rImage->bo = rb->bo;
+ radeon_bo_ref(rImage->bo);
+ t->bo = rb->bo;
+ radeon_bo_ref(t->bo);
+ t->tile_bits = 0;
+ t->image_override = GL_TRUE;
+ t->override_offset = 0;
+ t->pp_txpitch &= (1 << 13) -1;
+ pitch_val = rb->pitch;
+ switch (rb->cpp) {
+ case 4:
+ if (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT)
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
+ else
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
+ t->pp_txfilter |= tx_table[2].filter;
+ pitch_val /= 4;
+ break;
+ case 3:
+ default:
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
+ t->pp_txfilter |= tx_table[4].filter;
+ pitch_val /= 4;
+ break;
+ case 2:
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
+ t->pp_txfilter |= tx_table[5].filter;
+ pitch_val /= 2;
+ break;
+ }
+ pitch_val--;
+ t->pp_txsize = ((rb->base.Width - 1) << R300_TX_WIDTHMASK_SHIFT) |
+ ((rb->base.Height - 1) << R300_TX_HEIGHTMASK_SHIFT);
+ t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
+ t->pp_txpitch |= pitch_val;
+
+ if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+ if (rb->base.Width > 2048)
+ t->pp_txpitch |= R500_TXWIDTH_BIT11;
+ if (rb->base.Height > 2048)
+ t->pp_txpitch |= R500_TXHEIGHT_BIT11;
+ }
+ t->validated = GL_TRUE;
+ _mesa_unlock_texture(radeon->glCtx, texObj);
+ return;
}
-void r300UpdateTextureState(GLcontext * ctx)
+void r300SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
{
- int i;
-
- for (i = 0; i < 8; i++) {
- if (!r300UpdateTextureUnit(ctx, i)) {
- _mesa_warning(ctx,
- "failed to update texture state for unit %d.\n",
- i);
- }
- }
+ r300SetTexBuffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
}
diff --git a/src/mesa/drivers/dri/r300/r300_vertprog.c b/src/mesa/drivers/dri/r300/r300_vertprog.c
index c4e325e6a7..dd0f27f9cb 100644
--- a/src/mesa/drivers/dri/r300/r300_vertprog.c
+++ b/src/mesa/drivers/dri/r300/r300_vertprog.c
@@ -32,1450 +32,327 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/macros.h"
#include "main/enums.h"
#include "shader/program.h"
+#include "shader/programopt.h"
#include "shader/prog_instruction.h"
+#include "shader/prog_optimize.h"
#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
#include "shader/prog_statevars.h"
#include "tnl/tnl.h"
+#include "compiler/radeon_compiler.h"
+#include "compiler/radeon_nqssadce.h"
#include "r300_context.h"
+#include "r300_state.h"
-/* TODO: Get rid of t_src_class call */
-#define CMP_SRCS(a, b) ((a.RelAddr != b.RelAddr) || (a.Index != b.Index && \
- ((t_src_class(a.File) == PVS_SRC_REG_CONSTANT && \
- t_src_class(b.File) == PVS_SRC_REG_CONSTANT) || \
- (t_src_class(a.File) == PVS_SRC_REG_INPUT && \
- t_src_class(b.File) == PVS_SRC_REG_INPUT)))) \
-
-/*
- * Take an already-setup and valid source then swizzle it appropriately to
- * obtain a constant ZERO or ONE source.
+/**
+ * Write parameter array for the given vertex program into dst.
+ * Return the total number of components written.
*/
-#define __CONST(x, y) \
- (PVS_SRC_OPERAND(t_src_index(vp, &src[x]), \
- t_swizzle(y), \
- t_swizzle(y), \
- t_swizzle(y), \
- t_swizzle(y), \
- t_src_class(src[x].File), \
- VSF_FLAG_NONE) | (src[x].RelAddr << 4))
-
-#define FREE_TEMPS() \
- do { \
- int u_temp_used = (VSF_MAX_FRAGMENT_TEMPS - 1) - u_temp_i; \
- if((vp->num_temporaries + u_temp_used) > VSF_MAX_FRAGMENT_TEMPS) { \
- WARN_ONCE("Ran out of temps, num temps %d, us %d\n", vp->num_temporaries, u_temp_used); \
- vp->native = GL_FALSE; \
- } \
- u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \
- } while (0)
-
-int r300VertexProgUpdateParams(GLcontext * ctx,
- struct r300_vertex_program_cont *vp, float *dst)
+static int r300VertexProgUpdateParams(GLcontext * ctx, struct r300_vertex_program *vp, float *dst)
{
- int pi;
- struct gl_vertex_program *mesa_vp = &vp->mesa_program;
- float *dst_o = dst;
- struct gl_program_parameter_list *paramList;
+ int i;
- if (mesa_vp->IsNVProgram) {
+ if (vp->Base->IsNVProgram) {
_mesa_load_tracked_matrices(ctx);
-
- for (pi = 0; pi < MAX_NV_VERTEX_PROGRAM_PARAMS; pi++) {
- *dst++ = ctx->VertexProgram.Parameters[pi][0];
- *dst++ = ctx->VertexProgram.Parameters[pi][1];
- *dst++ = ctx->VertexProgram.Parameters[pi][2];
- *dst++ = ctx->VertexProgram.Parameters[pi][3];
+ } else {
+ if (vp->Base->Base.Parameters) {
+ _mesa_load_state_parameters(ctx, vp->Base->Base.Parameters);
}
- return dst - dst_o;
}
- assert(mesa_vp->Base.Parameters);
- _mesa_load_state_parameters(ctx, mesa_vp->Base.Parameters);
-
- if (mesa_vp->Base.Parameters->NumParameters * 4 >
- VSF_MAX_FRAGMENT_LENGTH) {
+ if (vp->code.constants.Count * 4 > VSF_MAX_FRAGMENT_LENGTH) {
+ /* Should have checked this earlier... */
fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__);
_mesa_exit(-1);
}
- paramList = mesa_vp->Base.Parameters;
- for (pi = 0; pi < paramList->NumParameters; pi++) {
- switch (paramList->Parameters[pi].Type) {
- case PROGRAM_STATE_VAR:
- case PROGRAM_NAMED_PARAM:
- //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
- case PROGRAM_CONSTANT:
- *dst++ = paramList->ParameterValues[pi][0];
- *dst++ = paramList->ParameterValues[pi][1];
- *dst++ = paramList->ParameterValues[pi][2];
- *dst++ = paramList->ParameterValues[pi][3];
- break;
- default:
- _mesa_problem(NULL, "Bad param type in %s",
- __FUNCTION__);
- }
-
- }
-
- return dst - dst_o;
-}
-
-static unsigned long t_dst_mask(GLuint mask)
-{
- /* WRITEMASK_* is equivalent to VSF_FLAG_* */
- return mask & VSF_FLAG_ALL;
-}
-
-static unsigned long t_dst_class(enum register_file file)
-{
-
- switch (file) {
- case PROGRAM_TEMPORARY:
- return PVS_DST_REG_TEMPORARY;
- case PROGRAM_OUTPUT:
- return PVS_DST_REG_OUT;
- case PROGRAM_ADDRESS:
- return PVS_DST_REG_A0;
- /*
- case PROGRAM_INPUT:
- case PROGRAM_LOCAL_PARAM:
- case PROGRAM_ENV_PARAM:
- case PROGRAM_NAMED_PARAM:
- case PROGRAM_STATE_VAR:
- case PROGRAM_WRITE_ONLY:
- case PROGRAM_ADDRESS:
- */
- default:
- fprintf(stderr, "problem in %s", __FUNCTION__);
- _mesa_exit(-1);
- return -1;
- }
-}
-
-static unsigned long t_dst_index(struct r300_vertex_program *vp,
- struct prog_dst_register *dst)
-{
- if (dst->File == PROGRAM_OUTPUT)
- return vp->outputs[dst->Index];
-
- return dst->Index;
-}
-
-static unsigned long t_src_class(enum register_file file)
-{
- switch (file) {
- case PROGRAM_TEMPORARY:
- return PVS_SRC_REG_TEMPORARY;
- case PROGRAM_INPUT:
- return PVS_SRC_REG_INPUT;
- case PROGRAM_LOCAL_PARAM:
- case PROGRAM_ENV_PARAM:
- case PROGRAM_NAMED_PARAM:
- case PROGRAM_CONSTANT:
- case PROGRAM_STATE_VAR:
- return PVS_SRC_REG_CONSTANT;
- /*
- case PROGRAM_OUTPUT:
- case PROGRAM_WRITE_ONLY:
- case PROGRAM_ADDRESS:
- */
- default:
- fprintf(stderr, "problem in %s", __FUNCTION__);
- _mesa_exit(-1);
- return -1;
- }
-}
+ for(i = 0; i < vp->code.constants.Count; ++i) {
+ const float * src = 0;
+ const struct rc_constant * constant = &vp->code.constants.Constants[i];
-static INLINE unsigned long t_swizzle(GLubyte swizzle)
-{
-/* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */
- return swizzle;
-}
+ switch(constant->Type) {
+ case RC_CONSTANT_EXTERNAL:
+ if (vp->Base->IsNVProgram) {
+ src = ctx->VertexProgram.Parameters[constant->u.External];
+ } else {
+ src = vp->Base->Base.Parameters->ParameterValues[constant->u.External];
+ }
+ break;
-#if 0
-static void vp_dump_inputs(struct r300_vertex_program *vp, char *caller)
-{
- int i;
+ case RC_CONSTANT_IMMEDIATE:
+ src = constant->u.Immediate;
+ break;
+ }
- if (vp == NULL) {
- fprintf(stderr, "vp null in call to %s from %s\n", __FUNCTION__,
- caller);
- return;
+ dst[4*i] = src[0];
+ dst[4*i + 1] = src[1];
+ dst[4*i + 2] = src[2];
+ dst[4*i + 3] = src[3];
}
- fprintf(stderr, "%s:<", caller);
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
- fprintf(stderr, "%d ", vp->inputs[i]);
- fprintf(stderr, ">\n");
-
+ return 4 * vp->code.constants.Count;
}
-#endif
-static unsigned long t_src_index(struct r300_vertex_program *vp,
- struct prog_src_register *src)
+static GLbitfield compute_required_outputs(struct gl_vertex_program * vp, GLbitfield fpreads)
{
+ GLbitfield outputs = 0;
int i;
- int max_reg = -1;
- if (src->File == PROGRAM_INPUT) {
- if (vp->inputs[src->Index] != -1)
- return vp->inputs[src->Index];
-
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
- if (vp->inputs[i] > max_reg)
- max_reg = vp->inputs[i];
-
- vp->inputs[src->Index] = max_reg + 1;
-
- //vp_dump_inputs(vp, __FUNCTION__);
-
- return vp->inputs[src->Index];
- } else {
- if (src->Index < 0) {
- fprintf(stderr,
- "negative offsets for indirect addressing do not work.\n");
- return 0;
- }
- return src->Index;
- }
-}
-
-/* these two functions should probably be merged... */
-
-static unsigned long t_src(struct r300_vertex_program *vp,
- struct prog_src_register *src)
-{
- /* src->NegateBase uses the NEGATE_ flags from program_instruction.h,
- * which equal our VSF_FLAGS_ values, so it's safe to just pass it here.
- */
- return PVS_SRC_OPERAND(t_src_index(vp, src),
- t_swizzle(GET_SWZ(src->Swizzle, 0)),
- t_swizzle(GET_SWZ(src->Swizzle, 1)),
- t_swizzle(GET_SWZ(src->Swizzle, 2)),
- t_swizzle(GET_SWZ(src->Swizzle, 3)),
- t_src_class(src->File),
- src->NegateBase) | (src->RelAddr << 4);
-}
+#define ADD_OUTPUT(fp_attr, vp_result) \
+ do { \
+ if (fpreads & (1 << (fp_attr))) \
+ outputs |= (1 << (vp_result)); \
+ } while (0)
-static unsigned long t_src_scalar(struct r300_vertex_program *vp,
- struct prog_src_register *src)
-{
- /* src->NegateBase uses the NEGATE_ flags from program_instruction.h,
- * which equal our VSF_FLAGS_ values, so it's safe to just pass it here.
- */
- return PVS_SRC_OPERAND(t_src_index(vp, src),
- t_swizzle(GET_SWZ(src->Swizzle, 0)),
- t_swizzle(GET_SWZ(src->Swizzle, 0)),
- t_swizzle(GET_SWZ(src->Swizzle, 0)),
- t_swizzle(GET_SWZ(src->Swizzle, 0)),
- t_src_class(src->File),
- src->
- NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src->RelAddr << 4);
-}
+ ADD_OUTPUT(FRAG_ATTRIB_COL0, VERT_RESULT_COL0);
+ ADD_OUTPUT(FRAG_ATTRIB_COL1, VERT_RESULT_COL1);
-static GLboolean valid_dst(struct r300_vertex_program *vp,
- struct prog_dst_register *dst)
-{
- if (dst->File == PROGRAM_OUTPUT && vp->outputs[dst->Index] == -1) {
- return GL_FALSE;
- } else if (dst->File == PROGRAM_ADDRESS) {
- assert(dst->Index == 0);
+ for (i = 0; i <= 7; ++i) {
+ ADD_OUTPUT(FRAG_ATTRIB_TEX0 + i, VERT_RESULT_TEX0 + i);
}
- return GL_TRUE;
-}
-
-static GLuint *r300TranslateOpcodeABS(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- //MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W
-
- inst[0] = PVS_OP_DST_OPERAND(VE_MAXIMUM,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]),
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 3)),
- t_src_class(src[0].File),
- (!src[0].
- NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[0].RelAddr << 4);
- inst[3] = 0;
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeADD(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_ADD,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeARL(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_FLT2FIX_DX,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeDP3(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO}
-
- inst[0] = PVS_OP_DST_OPERAND(VE_DOT_PRODUCT,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]),
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
- SWIZZLE_ZERO,
- t_src_class(src[0].File),
- src[0].
- NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE) |
- (src[0].RelAddr << 4);
- inst[2] =
- PVS_SRC_OPERAND(t_src_index(vp, &src[1]),
- t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
- t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
- t_swizzle(GET_SWZ(src[1].Swizzle, 2)), SWIZZLE_ZERO,
- t_src_class(src[1].File),
- src[1].
- NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE) |
- (src[1].RelAddr << 4);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeDP4(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_DOT_PRODUCT,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeDPH(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W}
- inst[0] = PVS_OP_DST_OPERAND(VE_DOT_PRODUCT,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]),
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 1)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 2)),
- PVS_SRC_SELECT_FORCE_1,
- t_src_class(src[0].File),
- src[0].
- NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE) |
- (src[0].RelAddr << 4);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeDST(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_DISTANCE_VECTOR,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeEX2(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(ME_EXP_BASE2_FULL_DX,
- GL_TRUE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src_scalar(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeEXP(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(ME_EXP_BASE2_DX,
- GL_TRUE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src_scalar(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeFLR(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3],
- int *u_temp_i)
-{
- /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W}
- ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */
-
- inst[0] = PVS_OP_DST_OPERAND(VE_FRACTION,
- GL_FALSE,
- GL_FALSE,
- *u_temp_i,
- t_dst_mask(vpi->DstReg.WriteMask),
- PVS_DST_REG_TEMPORARY);
- inst[1] = t_src(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
- inst += 4;
-
- inst[0] = PVS_OP_DST_OPERAND(VE_ADD,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = PVS_SRC_OPERAND(*u_temp_i,
- PVS_SRC_SELECT_X,
- PVS_SRC_SELECT_Y,
- PVS_SRC_SELECT_Z,
- PVS_SRC_SELECT_W, PVS_SRC_REG_TEMPORARY,
- /* Not 100% sure about this */
- (!src[0].
- NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE
- /*VSF_FLAG_ALL */ );
- inst[3] = __CONST(0, SWIZZLE_ZERO);
- (*u_temp_i)--;
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeFRC(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_FRACTION,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeLG2(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- // LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X}
-
- inst[0] = PVS_OP_DST_OPERAND(ME_LOG_BASE2_FULL_DX,
- GL_TRUE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]),
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)),
- t_src_class(src[0].File),
- src[0].
- NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[0].RelAddr << 4);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeLIT(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- //LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W}
-
- inst[0] = PVS_OP_DST_OPERAND(ME_LIGHT_COEFF_DX,
- GL_TRUE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- /* NOTE: Users swizzling might not work. */
- inst[1] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // X
- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // W
- PVS_SRC_SELECT_FORCE_0, // Z
- t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // Y
- t_src_class(src[0].File),
- src[0].
- NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[0].RelAddr << 4);
- inst[2] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // Y
- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // W
- PVS_SRC_SELECT_FORCE_0, // Z
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // X
- t_src_class(src[0].File),
- src[0].
- NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[0].RelAddr << 4);
- inst[3] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // Y
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // X
- PVS_SRC_SELECT_FORCE_0, // Z
- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // W
- t_src_class(src[0].File),
- src[0].
- NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[0].RelAddr << 4);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeLOG(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(ME_LOG_BASE2_DX,
- GL_TRUE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src_scalar(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeMAD(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(PVS_MACRO_OP_2CLK_MADD,
- GL_FALSE,
- GL_TRUE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = t_src(vp, &src[2]);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeMAX(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_MAXIMUM,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeMIN(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_MINIMUM,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeMOV(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- //ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
-
- inst[0] = PVS_OP_DST_OPERAND(VE_ADD,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeMUL(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_MULTIPLY,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodePOW(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(ME_POWER_FUNC_FF,
- GL_TRUE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src_scalar(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = t_src_scalar(vp, &src[1]);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeRCP(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(ME_RECIP_DX,
- GL_TRUE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src_scalar(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeRSQ(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(ME_RECIP_SQRT_DX,
- GL_TRUE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src_scalar(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
-}
-
-static GLuint *r300TranslateOpcodeSGE(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_SET_GREATER_THAN_EQUAL,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
+#undef ADD_OUTPUT
-static GLuint *r300TranslateOpcodeSLT(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- inst[0] = PVS_OP_DST_OPERAND(VE_SET_LESS_THAN,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = t_src(vp, &src[1]);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
-
- return inst;
-}
+ if ((fpreads & (1 << FRAG_ATTRIB_COL0)) &&
+ (vp->Base.OutputsWritten & (1 << VERT_RESULT_BFC0)))
+ outputs |= 1 << VERT_RESULT_BFC0;
+ if ((fpreads & (1 << FRAG_ATTRIB_COL1)) &&
+ (vp->Base.OutputsWritten & (1 << VERT_RESULT_BFC1)))
+ outputs |= 1 << VERT_RESULT_BFC1;
-static GLuint *r300TranslateOpcodeSUB(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- //ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W
-
-#if 0
- inst[0] = PVS_OP_DST_OPERAND(VE_ADD,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = PVS_SRC_OPERAND(t_src_index(vp, &src[1]),
- t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
- t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
- t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
- t_swizzle(GET_SWZ(src[1].Swizzle, 3)),
- t_src_class(src[1].File),
- (!src[1].
- NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[1].RelAddr << 4);
- inst[3] = 0;
-#else
- inst[0] =
- PVS_OP_DST_OPERAND(VE_MULTIPLY_ADD,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ONE);
- inst[3] = PVS_SRC_OPERAND(t_src_index(vp, &src[1]),
- t_swizzle(GET_SWZ(src[1].Swizzle, 0)),
- t_swizzle(GET_SWZ(src[1].Swizzle, 1)),
- t_swizzle(GET_SWZ(src[1].Swizzle, 2)),
- t_swizzle(GET_SWZ(src[1].Swizzle, 3)),
- t_src_class(src[1].File),
- (!src[1].
- NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[1].RelAddr << 4);
-#endif
-
- return inst;
-}
+ outputs |= 1 << VERT_RESULT_HPOS;
+ if (vp->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ))
+ outputs |= 1 << VERT_RESULT_PSIZ;
-static GLuint *r300TranslateOpcodeSWZ(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3])
-{
- //ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO}
-
- inst[0] = PVS_OP_DST_OPERAND(VE_ADD,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = t_src(vp, &src[0]);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
-
- return inst;
+ return outputs;
}
-static GLuint *r300TranslateOpcodeXPD(struct r300_vertex_program *vp,
- struct prog_instruction *vpi,
- GLuint * inst,
- struct prog_src_register src[3],
- int *u_temp_i)
-{
- /* mul r0, r1.yzxw, r2.zxyw
- mad r0, -r2.yzxw, r1.zxyw, r0
- */
-
- inst[0] = PVS_OP_DST_OPERAND(VE_MULTIPLY_ADD,
- GL_FALSE,
- GL_FALSE,
- *u_temp_i,
- t_dst_mask(vpi->DstReg.WriteMask),
- PVS_DST_REG_TEMPORARY);
- inst[1] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // Y
- t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // Z
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // X
- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // W
- t_src_class(src[0].File),
- src[0].
- NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[0].RelAddr << 4);
- inst[2] = PVS_SRC_OPERAND(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // Z
- t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // X
- t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // Y
- t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // W
- t_src_class(src[1].File),
- src[1].
- NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[1].RelAddr << 4);
- inst[3] = __CONST(1, SWIZZLE_ZERO);
- inst += 4;
-
- inst[0] = PVS_OP_DST_OPERAND(VE_MULTIPLY_ADD,
- GL_FALSE,
- GL_FALSE,
- t_dst_index(vp, &vpi->DstReg),
- t_dst_mask(vpi->DstReg.WriteMask),
- t_dst_class(vpi->DstReg.File));
- inst[1] = PVS_SRC_OPERAND(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // Y
- t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // Z
- t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // X
- t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // W
- t_src_class(src[1].File),
- (!src[1].
- NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[1].RelAddr << 4);
- inst[2] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // Z
- t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // X
- t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // Y
- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // W
- t_src_class(src[0].File),
- src[0].
- NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) |
- (src[0].RelAddr << 4);
- inst[3] =
- PVS_SRC_OPERAND(*u_temp_i, PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y,
- PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W,
- PVS_SRC_REG_TEMPORARY, VSF_FLAG_NONE);
-
- (*u_temp_i)--;
-
- return inst;
-}
-static void t_inputs_outputs(struct r300_vertex_program *vp)
+static void t_inputs_outputs(struct r300_vertex_program_compiler * c)
{
int i;
- int cur_reg = 0;
+ int cur_reg;
+ GLuint OutputsWritten, InputsRead;
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
- vp->inputs[i] = -1;
+ OutputsWritten = c->Base.Program.OutputsWritten;
+ InputsRead = c->Base.Program.InputsRead;
+ cur_reg = -1;
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ if (InputsRead & (1 << i))
+ c->code->inputs[i] = ++cur_reg;
+ else
+ c->code->inputs[i] = -1;
+ }
+
+ cur_reg = 0;
for (i = 0; i < VERT_RESULT_MAX; i++)
- vp->outputs[i] = -1;
+ c->code->outputs[i] = -1;
- assert(vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS));
+ assert(OutputsWritten & (1 << VERT_RESULT_HPOS));
- if (vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)) {
- vp->outputs[VERT_RESULT_HPOS] = cur_reg++;
+ if (OutputsWritten & (1 << VERT_RESULT_HPOS)) {
+ c->code->outputs[VERT_RESULT_HPOS] = cur_reg++;
}
- if (vp->key.OutputsWritten & (1 << VERT_RESULT_PSIZ)) {
- vp->outputs[VERT_RESULT_PSIZ] = cur_reg++;
+ if (OutputsWritten & (1 << VERT_RESULT_PSIZ)) {
+ c->code->outputs[VERT_RESULT_PSIZ] = cur_reg++;
}
- if (vp->key.OutputsWritten & (1 << VERT_RESULT_COL0)) {
- vp->outputs[VERT_RESULT_COL0] = cur_reg++;
+ /* If we're writing back facing colors we need to send
+ * four colors to make front/back face colors selection work.
+ * If the vertex program doesn't write all 4 colors, lets
+ * pretend it does by skipping output index reg so the colors
+ * get written into appropriate output vectors.
+ */
+ if (OutputsWritten & (1 << VERT_RESULT_COL0)) {
+ c->code->outputs[VERT_RESULT_COL0] = cur_reg++;
+ } else if (OutputsWritten & (1 << VERT_RESULT_BFC0) ||
+ OutputsWritten & (1 << VERT_RESULT_BFC1)) {
+ cur_reg++;
}
- if (vp->key.OutputsWritten & (1 << VERT_RESULT_COL1)) {
- vp->outputs[VERT_RESULT_COL1] =
- vp->outputs[VERT_RESULT_COL0] + 1;
- cur_reg = vp->outputs[VERT_RESULT_COL1] + 1;
+ if (OutputsWritten & (1 << VERT_RESULT_COL1)) {
+ c->code->outputs[VERT_RESULT_COL1] = cur_reg++;
+ } else if (OutputsWritten & (1 << VERT_RESULT_BFC0) ||
+ OutputsWritten & (1 << VERT_RESULT_BFC1)) {
+ cur_reg++;
}
- if (vp->key.OutputsWritten & (1 << VERT_RESULT_BFC0)) {
- vp->outputs[VERT_RESULT_BFC0] =
- vp->outputs[VERT_RESULT_COL0] + 2;
- cur_reg = vp->outputs[VERT_RESULT_BFC0] + 2;
+ if (OutputsWritten & (1 << VERT_RESULT_BFC0)) {
+ c->code->outputs[VERT_RESULT_BFC0] = cur_reg++;
+ } else if (OutputsWritten & (1 << VERT_RESULT_BFC1)) {
+ cur_reg++;
}
- if (vp->key.OutputsWritten & (1 << VERT_RESULT_BFC1)) {
- vp->outputs[VERT_RESULT_BFC1] =
- vp->outputs[VERT_RESULT_COL0] + 3;
- cur_reg = vp->outputs[VERT_RESULT_BFC1] + 1;
+ if (OutputsWritten & (1 << VERT_RESULT_BFC1)) {
+ c->code->outputs[VERT_RESULT_BFC1] = cur_reg++;
+ } else if (OutputsWritten & (1 << VERT_RESULT_BFC0)) {
+ cur_reg++;
}
-#if 0
- if (vp->key.OutputsWritten & (1 << VERT_RESULT_FOGC)) {
- vp->outputs[VERT_RESULT_FOGC] = cur_reg++;
- }
-#endif
for (i = VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++) {
- if (vp->key.OutputsWritten & (1 << i)) {
- vp->outputs[i] = cur_reg++;
- }
- }
-}
-
-static void r300TranslateVertexShader(struct r300_vertex_program *vp,
- struct prog_instruction *vpi)
-{
- int i;
- GLuint *inst;
- unsigned long num_operands;
- /* Initial value should be last tmp reg that hw supports.
- Strangely enough r300 doesnt mind even though these would be out of range.
- Smart enough to realize that it doesnt need it? */
- int u_temp_i = VSF_MAX_FRAGMENT_TEMPS - 1;
- struct prog_src_register src[3];
-
- vp->pos_end = 0; /* Not supported yet */
- vp->program.length = 0;
- /*vp->num_temporaries=mesa_vp->Base.NumTemporaries; */
- vp->translated = GL_TRUE;
- vp->native = GL_TRUE;
-
- t_inputs_outputs(vp);
-
- for (inst = vp->program.body.i; vpi->Opcode != OPCODE_END;
- vpi++, inst += 4) {
-
- FREE_TEMPS();
-
- if (!valid_dst(vp, &vpi->DstReg)) {
- /* redirect result to unused temp */
- vpi->DstReg.File = PROGRAM_TEMPORARY;
- vpi->DstReg.Index = u_temp_i;
- }
-
- num_operands = _mesa_num_inst_src_regs(vpi->Opcode);
-
- /* copy the sources (src) from mesa into a local variable... is this needed? */
- for (i = 0; i < num_operands; i++) {
- src[i] = vpi->SrcReg[i];
- }
-
- if (num_operands == 3) { /* TODO: scalars */
- if (CMP_SRCS(src[1], src[2])
- || CMP_SRCS(src[0], src[2])) {
- inst[0] = PVS_OP_DST_OPERAND(VE_ADD,
- GL_FALSE,
- GL_FALSE,
- u_temp_i,
- VSF_FLAG_ALL,
- PVS_DST_REG_TEMPORARY);
- inst[1] =
- PVS_SRC_OPERAND(t_src_index(vp, &src[2]),
- SWIZZLE_X,
- SWIZZLE_Y,
- SWIZZLE_Z,
- SWIZZLE_W,
- t_src_class(src[2].File),
- VSF_FLAG_NONE) | (src[2].
- RelAddr <<
- 4);
- inst[2] = __CONST(2, SWIZZLE_ZERO);
- inst[3] = __CONST(2, SWIZZLE_ZERO);
- inst += 4;
-
- src[2].File = PROGRAM_TEMPORARY;
- src[2].Index = u_temp_i;
- src[2].RelAddr = 0;
- u_temp_i--;
- }
- }
-
- if (num_operands >= 2) {
- if (CMP_SRCS(src[1], src[0])) {
- inst[0] = PVS_OP_DST_OPERAND(VE_ADD,
- GL_FALSE,
- GL_FALSE,
- u_temp_i,
- VSF_FLAG_ALL,
- PVS_DST_REG_TEMPORARY);
- inst[1] =
- PVS_SRC_OPERAND(t_src_index(vp, &src[0]),
- SWIZZLE_X,
- SWIZZLE_Y,
- SWIZZLE_Z,
- SWIZZLE_W,
- t_src_class(src[0].File),
- VSF_FLAG_NONE) | (src[0].
- RelAddr <<
- 4);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
- inst += 4;
-
- src[0].File = PROGRAM_TEMPORARY;
- src[0].Index = u_temp_i;
- src[0].RelAddr = 0;
- u_temp_i--;
- }
- }
-
- switch (vpi->Opcode) {
- case OPCODE_ABS:
- inst = r300TranslateOpcodeABS(vp, vpi, inst, src);
- break;
- case OPCODE_ADD:
- inst = r300TranslateOpcodeADD(vp, vpi, inst, src);
- break;
- case OPCODE_ARL:
- inst = r300TranslateOpcodeARL(vp, vpi, inst, src);
- break;
- case OPCODE_DP3:
- inst = r300TranslateOpcodeDP3(vp, vpi, inst, src);
- break;
- case OPCODE_DP4:
- inst = r300TranslateOpcodeDP4(vp, vpi, inst, src);
- break;
- case OPCODE_DPH:
- inst = r300TranslateOpcodeDPH(vp, vpi, inst, src);
- break;
- case OPCODE_DST:
- inst = r300TranslateOpcodeDST(vp, vpi, inst, src);
- break;
- case OPCODE_EX2:
- inst = r300TranslateOpcodeEX2(vp, vpi, inst, src);
- break;
- case OPCODE_EXP:
- inst = r300TranslateOpcodeEXP(vp, vpi, inst, src);
- break;
- case OPCODE_FLR:
- inst = r300TranslateOpcodeFLR(vp, vpi, inst, src, /* FIXME */
- &u_temp_i);
- break;
- case OPCODE_FRC:
- inst = r300TranslateOpcodeFRC(vp, vpi, inst, src);
- break;
- case OPCODE_LG2:
- inst = r300TranslateOpcodeLG2(vp, vpi, inst, src);
- break;
- case OPCODE_LIT:
- inst = r300TranslateOpcodeLIT(vp, vpi, inst, src);
- break;
- case OPCODE_LOG:
- inst = r300TranslateOpcodeLOG(vp, vpi, inst, src);
- break;
- case OPCODE_MAD:
- inst = r300TranslateOpcodeMAD(vp, vpi, inst, src);
- break;
- case OPCODE_MAX:
- inst = r300TranslateOpcodeMAX(vp, vpi, inst, src);
- break;
- case OPCODE_MIN:
- inst = r300TranslateOpcodeMIN(vp, vpi, inst, src);
- break;
- case OPCODE_MOV:
- inst = r300TranslateOpcodeMOV(vp, vpi, inst, src);
- break;
- case OPCODE_MUL:
- inst = r300TranslateOpcodeMUL(vp, vpi, inst, src);
- break;
- case OPCODE_POW:
- inst = r300TranslateOpcodePOW(vp, vpi, inst, src);
- break;
- case OPCODE_RCP:
- inst = r300TranslateOpcodeRCP(vp, vpi, inst, src);
- break;
- case OPCODE_RSQ:
- inst = r300TranslateOpcodeRSQ(vp, vpi, inst, src);
- break;
- case OPCODE_SGE:
- inst = r300TranslateOpcodeSGE(vp, vpi, inst, src);
- break;
- case OPCODE_SLT:
- inst = r300TranslateOpcodeSLT(vp, vpi, inst, src);
- break;
- case OPCODE_SUB:
- inst = r300TranslateOpcodeSUB(vp, vpi, inst, src);
- break;
- case OPCODE_SWZ:
- inst = r300TranslateOpcodeSWZ(vp, vpi, inst, src);
- break;
- case OPCODE_XPD:
- inst = r300TranslateOpcodeXPD(vp, vpi, inst, src, /* FIXME */
- &u_temp_i);
- break;
- default:
- assert(0);
- break;
- }
- }
-
- /* Some outputs may be artificially added, to match the inputs
- of the fragment program. Blank the outputs here. */
- for (i = 0; i < VERT_RESULT_MAX; i++) {
- if (vp->key.OutputsAdded & (1 << i)) {
- inst[0] = PVS_OP_DST_OPERAND(VE_ADD,
- GL_FALSE,
- GL_FALSE,
- vp->outputs[i],
- VSF_FLAG_ALL,
- PVS_DST_REG_OUT);
- inst[1] = __CONST(0, SWIZZLE_ZERO);
- inst[2] = __CONST(0, SWIZZLE_ZERO);
- inst[3] = __CONST(0, SWIZZLE_ZERO);
- inst += 4;
+ if (OutputsWritten & (1 << i)) {
+ c->code->outputs[i] = cur_reg++;
}
}
- vp->program.length = (inst - vp->program.body.i);
- if (vp->program.length >= VSF_MAX_FRAGMENT_LENGTH) {
- vp->program.length = 0;
- vp->native = GL_FALSE;
+ if (OutputsWritten & (1 << VERT_RESULT_FOGC)) {
+ c->code->outputs[VERT_RESULT_FOGC] = cur_reg++;
}
-#if 0
- fprintf(stderr, "hw program:\n");
- for (i = 0; i < vp->program.length; i++)
- fprintf(stderr, "%08x\n", vp->program.body.d[i]);
-#endif
}
-/* DP4 version seems to trigger some hw peculiarity */
-//#define PREFER_DP4
-static void position_invariant(struct gl_program *prog)
+static struct r300_vertex_program *build_program(GLcontext *ctx,
+ struct r300_vertex_program_key *wanted_key,
+ const struct gl_vertex_program *mesa_vp)
{
- struct prog_instruction *vpi;
- struct gl_program_parameter_list *paramList;
- int i;
-
- gl_state_index tokens[STATE_LENGTH] = { STATE_MVP_MATRIX, 0, 0, 0, 0 };
-
- /* tokens[4] = matrix modifier */
-#ifdef PREFER_DP4
- tokens[4] = 0; /* not transposed or inverted */
-#else
- tokens[4] = STATE_MATRIX_TRANSPOSE;
-#endif
- paramList = prog->Parameters;
-
- vpi = _mesa_alloc_instructions(prog->NumInstructions + 4);
- _mesa_init_instructions(vpi, prog->NumInstructions + 4);
-
- for (i = 0; i < 4; i++) {
- GLint idx;
- tokens[2] = tokens[3] = i; /* matrix row[i]..row[i] */
- idx = _mesa_add_state_reference(paramList, tokens);
-#ifdef PREFER_DP4
- vpi[i].Opcode = OPCODE_DP4;
- vpi[i].StringPos = 0;
- vpi[i].Data = 0;
-
- vpi[i].DstReg.File = PROGRAM_OUTPUT;
- vpi[i].DstReg.Index = VERT_RESULT_HPOS;
- vpi[i].DstReg.WriteMask = 1 << i;
- vpi[i].DstReg.CondMask = COND_TR;
-
- vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR;
- vpi[i].SrcReg[0].Index = idx;
- vpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
-
- vpi[i].SrcReg[1].File = PROGRAM_INPUT;
- vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS;
- vpi[i].SrcReg[1].Swizzle = SWIZZLE_XYZW;
-#else
- if (i == 0)
- vpi[i].Opcode = OPCODE_MUL;
- else
- vpi[i].Opcode = OPCODE_MAD;
-
- vpi[i].StringPos = 0;
- vpi[i].Data = 0;
-
- if (i == 3)
- vpi[i].DstReg.File = PROGRAM_OUTPUT;
- else
- vpi[i].DstReg.File = PROGRAM_TEMPORARY;
- vpi[i].DstReg.Index = 0;
- vpi[i].DstReg.WriteMask = 0xf;
- vpi[i].DstReg.CondMask = COND_TR;
-
- vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR;
- vpi[i].SrcReg[0].Index = idx;
- vpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
-
- vpi[i].SrcReg[1].File = PROGRAM_INPUT;
- vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS;
- vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(i, i, i, i);
-
- if (i > 0) {
- vpi[i].SrcReg[2].File = PROGRAM_TEMPORARY;
- vpi[i].SrcReg[2].Index = 0;
- vpi[i].SrcReg[2].Swizzle = SWIZZLE_XYZW;
- }
-#endif
- }
-
- _mesa_copy_instructions(&vpi[i], prog->Instructions,
- prog->NumInstructions);
-
- free(prog->Instructions);
-
- prog->Instructions = vpi;
-
- prog->NumInstructions += 4;
- vpi = &prog->Instructions[prog->NumInstructions - 1];
-
- assert(vpi->Opcode == OPCODE_END);
-}
+ struct r300_vertex_program *vp;
+ struct r300_vertex_program_compiler compiler;
-static void insert_wpos(struct r300_vertex_program *vp, struct gl_program *prog,
- GLuint temp_index)
-{
- struct prog_instruction *vpi;
- struct prog_instruction *vpi_insert;
- int i = 0;
+ vp = _mesa_calloc(sizeof(*vp));
+ vp->Base = (struct gl_vertex_program *) _mesa_clone_program(ctx, &mesa_vp->Base);
+ _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key));
- vpi = _mesa_alloc_instructions(prog->NumInstructions + 2);
- _mesa_init_instructions(vpi, prog->NumInstructions + 2);
- /* all but END */
- _mesa_copy_instructions(vpi, prog->Instructions,
- prog->NumInstructions - 1);
- /* END */
- _mesa_copy_instructions(&vpi[prog->NumInstructions + 1],
- &prog->Instructions[prog->NumInstructions - 1],
- 1);
- vpi_insert = &vpi[prog->NumInstructions - 1];
+ rc_init(&compiler.Base);
+ compiler.Base.Debug = (RADEON_DEBUG & RADEON_VERTS) ? GL_TRUE : GL_FALSE;
- vpi_insert[i].Opcode = OPCODE_MOV;
+ compiler.code = &vp->code;
+ compiler.RequiredOutputs = compute_required_outputs(vp->Base, vp->key.FpReads);
+ compiler.SetHwInputOutput = &t_inputs_outputs;
- vpi_insert[i].DstReg.File = PROGRAM_OUTPUT;
- vpi_insert[i].DstReg.Index = VERT_RESULT_HPOS;
- vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW;
- vpi_insert[i].DstReg.CondMask = COND_TR;
+ if (compiler.Base.Debug) {
+ fprintf(stderr, "Initial vertex program:\n");
+ _mesa_print_program(&vp->Base->Base);
+ fflush(stderr);
+ }
- vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY;
- vpi_insert[i].SrcReg[0].Index = temp_index;
- vpi_insert[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
- i++;
+ if (mesa_vp->IsPositionInvariant) {
+ _mesa_insert_mvp_code(ctx, vp->Base);
+ }
- vpi_insert[i].Opcode = OPCODE_MOV;
+ rc_mesa_to_rc_program(&compiler.Base, &vp->Base->Base);
- vpi_insert[i].DstReg.File = PROGRAM_OUTPUT;
- vpi_insert[i].DstReg.Index = VERT_RESULT_TEX0 + vp->wpos_idx;
- vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW;
- vpi_insert[i].DstReg.CondMask = COND_TR;
+ rc_move_output(&compiler.Base, VERT_RESULT_PSIZ, VERT_RESULT_PSIZ, WRITEMASK_X);
- vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY;
- vpi_insert[i].SrcReg[0].Index = temp_index;
- vpi_insert[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
- i++;
+ if (vp->key.WPosAttr != FRAG_ATTRIB_MAX) {
+ rc_copy_output(&compiler.Base,
+ VERT_RESULT_HPOS,
+ vp->key.WPosAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0);
+ }
- free(prog->Instructions);
+ if (vp->key.FogAttr != FRAG_ATTRIB_MAX) {
+ rc_move_output(&compiler.Base,
+ VERT_RESULT_FOGC,
+ vp->key.FogAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0, WRITEMASK_X);
+ }
- prog->Instructions = vpi;
+ r3xx_compile_vertex_program(&compiler);
+ vp->error = compiler.Base.Error;
- prog->NumInstructions += i;
- vpi = &prog->Instructions[prog->NumInstructions - 1];
+ vp->Base->Base.InputsRead = vp->code.InputsRead;
+ vp->Base->Base.OutputsWritten = vp->code.OutputsWritten;
- assert(vpi->Opcode == OPCODE_END);
-}
+ rc_destroy(&compiler.Base);
-static void pos_as_texcoord(struct r300_vertex_program *vp,
- struct gl_program *prog)
-{
- struct prog_instruction *vpi;
- GLuint tempregi = prog->NumTemporaries;
- /* should do something else if no temps left... */
- prog->NumTemporaries++;
-
- for (vpi = prog->Instructions; vpi->Opcode != OPCODE_END; vpi++) {
- if (vpi->DstReg.File == PROGRAM_OUTPUT
- && vpi->DstReg.Index == VERT_RESULT_HPOS) {
- vpi->DstReg.File = PROGRAM_TEMPORARY;
- vpi->DstReg.Index = tempregi;
- }
- }
- insert_wpos(vp, prog, tempregi);
+ return vp;
}
-static struct r300_vertex_program *build_program(struct r300_vertex_program_key
- *wanted_key, struct gl_vertex_program
- *mesa_vp, GLint wpos_idx)
+struct r300_vertex_program * r300SelectAndTranslateVertexShader(GLcontext *ctx)
{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ struct r300_vertex_program_key wanted_key = { 0 };
+ struct r300_vertex_program_cont *vpc;
struct r300_vertex_program *vp;
- vp = _mesa_calloc(sizeof(*vp));
- _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key));
- vp->wpos_idx = wpos_idx;
-
- if (mesa_vp->IsPositionInvariant) {
- position_invariant(&mesa_vp->Base);
- }
+ vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current;
+ wanted_key.FpReads = r300->selected_fp->InputsRead;
+ wanted_key.FogAttr = r300->selected_fp->fog_attr;
+ wanted_key.WPosAttr = r300->selected_fp->wpos_attr;
- if (wpos_idx > -1) {
- pos_as_texcoord(vp, &mesa_vp->Base);
+ for (vp = vpc->progs; vp; vp = vp->next) {
+ if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key))
+ == 0) {
+ return r300->selected_vp = vp;
+ }
}
- assert(mesa_vp->Base.NumInstructions);
- vp->num_temporaries = mesa_vp->Base.NumTemporaries;
- r300TranslateVertexShader(vp, mesa_vp->Base.Instructions);
+ vp = build_program(ctx, &wanted_key, &vpc->mesa_program);
+ vp->next = vpc->progs;
+ vpc->progs = vp;
- return vp;
+ return r300->selected_vp = vp;
}
-static void add_outputs(struct r300_vertex_program_key *key, GLint vert)
+#define bump_vpu_count(ptr, new_count) do { \
+ drm_r300_cmd_header_t* _p=((drm_r300_cmd_header_t*)(ptr)); \
+ int _nc=(new_count)/4; \
+ assert(_nc < 256); \
+ if(_nc>_p->vpu.count)_p->vpu.count=_nc; \
+ } while(0)
+
+static void r300EmitVertexProgram(r300ContextPtr r300, int dest, struct r300_vertex_program_code *code)
{
- if (key->OutputsWritten & (1 << vert))
- return;
+ int i;
- key->OutputsWritten |= 1 << vert;
- key->OutputsAdded |= 1 << vert;
-}
+ assert((code->length > 0) && (code->length % 4 == 0));
-void r300SelectVertexShader(r300ContextPtr r300)
-{
- GLcontext *ctx = ctx = r300->radeon.glCtx;
- GLuint InputsRead;
- struct r300_vertex_program_key wanted_key = { 0 };
- GLint i;
- struct r300_vertex_program_cont *vpc;
- struct r300_vertex_program *vp;
- GLint wpos_idx;
+ R300_STATECHANGE( r300, vap_flush );
- vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current;
- wanted_key.InputsRead = vpc->mesa_program.Base.InputsRead;
- wanted_key.OutputsWritten = vpc->mesa_program.Base.OutputsWritten;
- InputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
-
- wpos_idx = -1;
- if (InputsRead & FRAG_BIT_WPOS) {
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
- if (!(InputsRead & (FRAG_BIT_TEX0 << i)))
- break;
-
- if (i == ctx->Const.MaxTextureUnits) {
- fprintf(stderr, "\tno free texcoord found\n");
+ switch ((dest >> 8) & 0xf) {
+ case 0:
+ R300_STATECHANGE(r300, vpi);
+ for (i = 0; i < code->length; i++)
+ r300->hw.vpi.cmd[R300_VPI_INSTR_0 + i + 4 * (dest & 0xff)] = (code->body.d[i]);
+ bump_vpu_count(r300->hw.vpi.cmd, code->length + 4 * (dest & 0xff));
+ break;
+ case 2:
+ R300_STATECHANGE(r300, vpp);
+ for (i = 0; i < code->length; i++)
+ r300->hw.vpp.cmd[R300_VPP_PARAM_0 + i + 4 * (dest & 0xff)] = (code->body.d[i]);
+ bump_vpu_count(r300->hw.vpp.cmd, code->length + 4 * (dest & 0xff));
+ break;
+ case 4:
+ R300_STATECHANGE(r300, vps);
+ for (i = 0; i < code->length; i++)
+ r300->hw.vps.cmd[1 + i + 4 * (dest & 0xff)] = (code->body.d[i]);
+ bump_vpu_count(r300->hw.vps.cmd, code->length + 4 * (dest & 0xff));
+ break;
+ default:
+ fprintf(stderr, "%s:%s don't know how to handle dest %04x\n", __FILE__, __FUNCTION__, dest);
_mesa_exit(-1);
- }
-
- wanted_key.OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i);
- wpos_idx = i;
}
+}
- add_outputs(&wanted_key, VERT_RESULT_HPOS);
+void r300SetupVertexProgram(r300ContextPtr rmesa)
+{
+ GLcontext *ctx = rmesa->radeon.glCtx;
+ struct r300_vertex_program *prog = rmesa->selected_vp;
+ int inst_count = 0;
+ int param_count = 0;
- if (InputsRead & FRAG_BIT_COL0) {
- add_outputs(&wanted_key, VERT_RESULT_COL0);
- }
+ /* Reset state, in case we don't use something */
+ ((drm_r300_cmd_header_t *) rmesa->hw.vpp.cmd)->vpu.count = 0;
+ ((drm_r300_cmd_header_t *) rmesa->hw.vpi.cmd)->vpu.count = 0;
+ ((drm_r300_cmd_header_t *) rmesa->hw.vps.cmd)->vpu.count = 0;
- if (InputsRead & FRAG_BIT_COL1) {
- add_outputs(&wanted_key, VERT_RESULT_COL1);
- }
+ R300_STATECHANGE(rmesa, vap_flush);
+ R300_STATECHANGE(rmesa, vpp);
+ param_count = r300VertexProgUpdateParams(ctx, prog, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]);
+ bump_vpu_count(rmesa->hw.vpp.cmd, param_count);
+ param_count /= 4;
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (InputsRead & (FRAG_BIT_TEX0 << i)) {
- add_outputs(&wanted_key, VERT_RESULT_TEX0 + i);
- }
- }
+ r300EmitVertexProgram(rmesa, R300_PVS_CODE_START, &(prog->code));
+ inst_count = (prog->code.length / 4) - 1;
- if (vpc->mesa_program.IsPositionInvariant) {
- /* we wan't position don't we ? */
- wanted_key.InputsRead |= (1 << VERT_ATTRIB_POS);
- }
+ r300VapCntl(rmesa, _mesa_bitcount(prog->code.InputsRead),
+ _mesa_bitcount(prog->code.OutputsWritten), prog->code.num_temporaries);
- for (vp = vpc->progs; vp; vp = vp->next)
- if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key))
- == 0) {
- r300->selected_vp = vp;
- return;
- }
- //_mesa_print_program(&vpc->mesa_program.Base);
+ R300_STATECHANGE(rmesa, pvs);
+ rmesa->hw.pvs.cmd[R300_PVS_CNTL_1] = (0 << R300_PVS_FIRST_INST_SHIFT) | (inst_count << R300_PVS_XYZW_VALID_INST_SHIFT) |
+ (inst_count << R300_PVS_LAST_INST_SHIFT);
- vp = build_program(&wanted_key, &vpc->mesa_program, wpos_idx);
- vp->next = vpc->progs;
- vpc->progs = vp;
- r300->selected_vp = vp;
+ rmesa->hw.pvs.cmd[R300_PVS_CNTL_2] = (0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) | (param_count << R300_PVS_MAX_CONST_ADDR_SHIFT);
+ rmesa->hw.pvs.cmd[R300_PVS_CNTL_3] = (inst_count << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
}
diff --git a/src/mesa/drivers/dri/r300/r300_vertprog.h b/src/mesa/drivers/dri/r300/r300_vertprog.h
index 2f35f02bc8..ccec896be4 100644
--- a/src/mesa/drivers/dri/r300/r300_vertprog.h
+++ b/src/mesa/drivers/dri/r300/r300_vertprog.h
@@ -3,33 +3,9 @@
#include "r300_reg.h"
-#define PVS_OP_DST_OPERAND(opcode, math_inst, macro_inst, reg_index, reg_writemask, reg_class) \
- (((opcode & PVS_DST_OPCODE_MASK) << PVS_DST_OPCODE_SHIFT) \
- | ((math_inst & PVS_DST_MATH_INST_MASK) << PVS_DST_MATH_INST_SHIFT) \
- | ((macro_inst & PVS_DST_MACRO_INST_MASK) << PVS_DST_MACRO_INST_SHIFT) \
- | ((reg_index & PVS_DST_OFFSET_MASK) << PVS_DST_OFFSET_SHIFT) \
- | ((reg_writemask & 0xf) << PVS_DST_WE_X_SHIFT) /* X Y Z W */ \
- | ((reg_class & PVS_DST_REG_TYPE_MASK) << PVS_DST_REG_TYPE_SHIFT))
-#define PVS_SRC_OPERAND(in_reg_index, comp_x, comp_y, comp_z, comp_w, reg_class, negate) \
- (((in_reg_index & PVS_SRC_OFFSET_MASK) << PVS_SRC_OFFSET_SHIFT) \
- | ((comp_x & PVS_SRC_SWIZZLE_X_MASK) << PVS_SRC_SWIZZLE_X_SHIFT) \
- | ((comp_y & PVS_SRC_SWIZZLE_Y_MASK) << PVS_SRC_SWIZZLE_Y_SHIFT) \
- | ((comp_z & PVS_SRC_SWIZZLE_Z_MASK) << PVS_SRC_SWIZZLE_Z_SHIFT) \
- | ((comp_w & PVS_SRC_SWIZZLE_W_MASK) << PVS_SRC_SWIZZLE_W_SHIFT) \
- | ((negate & 0xf) << PVS_SRC_MODIFIER_X_SHIFT) /* X Y Z W */ \
- | ((reg_class & PVS_SRC_REG_TYPE_MASK) << PVS_SRC_REG_TYPE_SHIFT))
+void r300SetupVertexProgram(r300ContextPtr rmesa);
-#if 1
-
-#define VSF_FLAG_X 1
-#define VSF_FLAG_Y 2
-#define VSF_FLAG_Z 4
-#define VSF_FLAG_W 8
-#define VSF_FLAG_XYZ (VSF_FLAG_X | VSF_FLAG_Y | VSF_FLAG_Z)
-#define VSF_FLAG_ALL 0xf
-#define VSF_FLAG_NONE 0
-
-#endif
+struct r300_vertex_program * r300SelectAndTranslateVertexShader(GLcontext *ctx);
#endif
diff --git a/src/mesa/drivers/dri/r300/r500_fragprog.c b/src/mesa/drivers/dri/r300/r500_fragprog.c
deleted file mode 100644
index 75dae86fa8..0000000000
--- a/src/mesa/drivers/dri/r300/r500_fragprog.c
+++ /dev/null
@@ -1,700 +0,0 @@
-/*
- * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "r500_fragprog.h"
-
-#include "radeon_nqssadce.h"
-#include "radeon_program_alu.h"
-
-
-static struct prog_src_register shadow_ambient(struct gl_program *program, int tmu)
-{
- gl_state_index fail_value_tokens[STATE_LENGTH] = {
- STATE_INTERNAL, STATE_SHADOW_AMBIENT, 0, 0, 0
- };
- struct prog_src_register reg = { 0, };
-
- fail_value_tokens[2] = tmu;
- reg.File = PROGRAM_STATE_VAR;
- reg.Index = _mesa_add_state_reference(program->Parameters, fail_value_tokens);
- reg.Swizzle = SWIZZLE_WWWW;
- return reg;
-}
-
-/**
- * Transform TEX, TXP, TXB, and KIL instructions in the following way:
- * - premultiply texture coordinates for RECT
- * - extract operand swizzles
- * - introduce a temporary register when write masks are needed
- *
- */
-static GLboolean transform_TEX(
- struct radeon_transform_context *t,
- struct prog_instruction* orig_inst, void* data)
-{
- struct r500_fragment_program_compiler *compiler =
- (struct r500_fragment_program_compiler*)data;
- struct prog_instruction inst = *orig_inst;
- struct prog_instruction* tgt;
- GLboolean destredirect = GL_FALSE;
-
- if (inst.Opcode != OPCODE_TEX &&
- inst.Opcode != OPCODE_TXB &&
- inst.Opcode != OPCODE_TXP &&
- inst.Opcode != OPCODE_KIL)
- return GL_FALSE;
-
- /* ARB_shadow & EXT_shadow_funcs */
- if (inst.Opcode != OPCODE_KIL &&
- t->Program->ShadowSamplers & (1 << inst.TexSrcUnit)) {
- GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
-
- if (comparefunc == GL_NEVER || comparefunc == GL_ALWAYS) {
- tgt = radeonAppendInstructions(t->Program, 1);
-
- tgt->Opcode = OPCODE_MOV;
- tgt->DstReg = inst.DstReg;
- if (comparefunc == GL_ALWAYS) {
- tgt->SrcReg[0].File = PROGRAM_BUILTIN;
- tgt->SrcReg[0].Swizzle = SWIZZLE_1111;
- } else {
- tgt->SrcReg[0] = shadow_ambient(t->Program, inst.TexSrcUnit);
- }
- return GL_TRUE;
- }
-
- inst.DstReg.File = PROGRAM_TEMPORARY;
- inst.DstReg.Index = radeonFindFreeTemporary(t);
- inst.DstReg.WriteMask = WRITEMASK_XYZW;
- } else if (inst.Opcode != OPCODE_KIL && inst.DstReg.File != PROGRAM_TEMPORARY) {
- int tempreg = radeonFindFreeTemporary(t);
-
- inst.DstReg.File = PROGRAM_TEMPORARY;
- inst.DstReg.Index = tempreg;
- inst.DstReg.WriteMask = WRITEMASK_XYZW;
- destredirect = GL_TRUE;
- }
-
- tgt = radeonAppendInstructions(t->Program, 1);
- _mesa_copy_instructions(tgt, &inst, 1);
-
- if (inst.Opcode != OPCODE_KIL &&
- t->Program->ShadowSamplers & (1 << inst.TexSrcUnit)) {
- GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
- GLuint depthmode = compiler->fp->state.unit[inst.TexSrcUnit].depth_texture_mode;
- int rcptemp = radeonFindFreeTemporary(t);
- int pass, fail;
-
- tgt = radeonAppendInstructions(t->Program, 3);
-
- tgt[0].Opcode = OPCODE_RCP;
- tgt[0].DstReg.File = PROGRAM_TEMPORARY;
- tgt[0].DstReg.Index = rcptemp;
- tgt[0].DstReg.WriteMask = WRITEMASK_W;
- tgt[0].SrcReg[0] = inst.SrcReg[0];
- tgt[0].SrcReg[0].Swizzle = SWIZZLE_WWWW;
-
- tgt[1].Opcode = OPCODE_MAD;
- tgt[1].DstReg = inst.DstReg;
- tgt[1].DstReg.WriteMask = orig_inst->DstReg.WriteMask;
- tgt[1].SrcReg[0] = inst.SrcReg[0];
- tgt[1].SrcReg[0].Swizzle = SWIZZLE_ZZZZ;
- tgt[1].SrcReg[1].File = PROGRAM_TEMPORARY;
- tgt[1].SrcReg[1].Index = rcptemp;
- tgt[1].SrcReg[1].Swizzle = SWIZZLE_WWWW;
- tgt[1].SrcReg[2].File = PROGRAM_TEMPORARY;
- tgt[1].SrcReg[2].Index = inst.DstReg.Index;
- if (depthmode == 0) /* GL_LUMINANCE */
- tgt[1].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z);
- else if (depthmode == 2) /* GL_ALPHA */
- tgt[1].SrcReg[2].Swizzle = SWIZZLE_WWWW;
-
- /* Recall that SrcReg[0] is tex, SrcReg[2] is r and:
- * r < tex <=> -tex+r < 0
- * r >= tex <=> not (-tex+r < 0 */
- if (comparefunc == GL_LESS || comparefunc == GL_GEQUAL)
- tgt[1].SrcReg[2].NegateBase = tgt[0].SrcReg[2].NegateBase ^ NEGATE_XYZW;
- else
- tgt[1].SrcReg[0].NegateBase = tgt[0].SrcReg[0].NegateBase ^ NEGATE_XYZW;
-
- tgt[2].Opcode = OPCODE_CMP;
- tgt[2].DstReg = orig_inst->DstReg;
- tgt[2].SrcReg[0].File = PROGRAM_TEMPORARY;
- tgt[2].SrcReg[0].Index = tgt[1].DstReg.Index;
-
- if (comparefunc == GL_LESS || comparefunc == GL_GREATER) {
- pass = 1;
- fail = 2;
- } else {
- pass = 2;
- fail = 1;
- }
-
- tgt[2].SrcReg[pass].File = PROGRAM_BUILTIN;
- tgt[2].SrcReg[pass].Swizzle = SWIZZLE_1111;
- tgt[2].SrcReg[fail] = shadow_ambient(t->Program, inst.TexSrcUnit);
- } else if (destredirect) {
- tgt = radeonAppendInstructions(t->Program, 1);
-
- tgt->Opcode = OPCODE_MOV;
- tgt->DstReg = orig_inst->DstReg;
- tgt->SrcReg[0].File = PROGRAM_TEMPORARY;
- tgt->SrcReg[0].Index = inst.DstReg.Index;
- }
-
- return GL_TRUE;
-}
-
-
-static void update_params(r300ContextPtr r300, struct r500_fragment_program *fp)
-{
- struct gl_fragment_program *mp = &fp->mesa_program;
-
- /* Ask Mesa nicely to fill in ParameterValues for us */
- if (mp->Base.Parameters)
- _mesa_load_state_parameters(r300->radeon.glCtx, mp->Base.Parameters);
-}
-
-
-/**
- * Transform the program to support fragment.position.
- *
- * Introduce a small fragment at the start of the program that will be
- * the only code that directly reads the FRAG_ATTRIB_WPOS input.
- * All other code pieces that reference that input will be rewritten
- * to read from a newly allocated temporary.
- *
- * \todo if/when r5xx supports the radeon_program architecture, this is a
- * likely candidate for code sharing.
- */
-static void insert_WPOS_trailer(struct r500_fragment_program_compiler *compiler)
-{
- GLuint InputsRead = compiler->fp->mesa_program.Base.InputsRead;
-
- if (!(InputsRead & FRAG_BIT_WPOS))
- return;
-
- static gl_state_index tokens[STATE_LENGTH] = {
- STATE_INTERNAL, STATE_R300_WINDOW_DIMENSION, 0, 0, 0
- };
- struct prog_instruction *fpi;
- GLuint window_index;
- int i = 0;
- GLuint tempregi = _mesa_find_free_register(compiler->program, PROGRAM_TEMPORARY);
-
- _mesa_insert_instructions(compiler->program, 0, 3);
- fpi = compiler->program->Instructions;
-
- /* perspective divide */
- fpi[i].Opcode = OPCODE_RCP;
-
- fpi[i].DstReg.File = PROGRAM_TEMPORARY;
- fpi[i].DstReg.Index = tempregi;
- fpi[i].DstReg.WriteMask = WRITEMASK_W;
- fpi[i].DstReg.CondMask = COND_TR;
-
- fpi[i].SrcReg[0].File = PROGRAM_INPUT;
- fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
- fpi[i].SrcReg[0].Swizzle = SWIZZLE_WWWW;
- i++;
-
- fpi[i].Opcode = OPCODE_MUL;
-
- fpi[i].DstReg.File = PROGRAM_TEMPORARY;
- fpi[i].DstReg.Index = tempregi;
- fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
- fpi[i].DstReg.CondMask = COND_TR;
-
- fpi[i].SrcReg[0].File = PROGRAM_INPUT;
- fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
- fpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
-
- fpi[i].SrcReg[1].File = PROGRAM_TEMPORARY;
- fpi[i].SrcReg[1].Index = tempregi;
- fpi[i].SrcReg[1].Swizzle = SWIZZLE_WWWW;
- i++;
-
- /* viewport transformation */
- window_index = _mesa_add_state_reference(compiler->program->Parameters, tokens);
-
- fpi[i].Opcode = OPCODE_MAD;
-
- fpi[i].DstReg.File = PROGRAM_TEMPORARY;
- fpi[i].DstReg.Index = tempregi;
- fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
- fpi[i].DstReg.CondMask = COND_TR;
-
- fpi[i].SrcReg[0].File = PROGRAM_TEMPORARY;
- fpi[i].SrcReg[0].Index = tempregi;
- fpi[i].SrcReg[0].Swizzle =
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
-
- fpi[i].SrcReg[1].File = PROGRAM_STATE_VAR;
- fpi[i].SrcReg[1].Index = window_index;
- fpi[i].SrcReg[1].Swizzle =
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
-
- fpi[i].SrcReg[2].File = PROGRAM_STATE_VAR;
- fpi[i].SrcReg[2].Index = window_index;
- fpi[i].SrcReg[2].Swizzle =
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
- i++;
-
- for (; i < compiler->program->NumInstructions; ++i) {
- int reg;
- for (reg = 0; reg < 3; reg++) {
- if (fpi[i].SrcReg[reg].File == PROGRAM_INPUT &&
- fpi[i].SrcReg[reg].Index == FRAG_ATTRIB_WPOS) {
- fpi[i].SrcReg[reg].File = PROGRAM_TEMPORARY;
- fpi[i].SrcReg[reg].Index = tempregi;
- }
- }
- }
-}
-
-
-static void nqssadce_init(struct nqssadce_state* s)
-{
- s->Outputs[FRAG_RESULT_COLR].Sourced = WRITEMASK_XYZW;
- s->Outputs[FRAG_RESULT_DEPR].Sourced = WRITEMASK_W;
-}
-
-static GLboolean is_native_swizzle(GLuint opcode, struct prog_src_register reg)
-{
- GLuint relevant;
- int i;
-
- if (opcode == OPCODE_TEX ||
- opcode == OPCODE_TXB ||
- opcode == OPCODE_TXP ||
- opcode == OPCODE_KIL) {
- if (reg.Abs)
- return GL_FALSE;
-
- if (reg.NegateAbs)
- reg.NegateBase ^= 15;
-
- if (opcode == OPCODE_KIL) {
- if (reg.Swizzle != SWIZZLE_NOOP)
- return GL_FALSE;
- } else {
- for(i = 0; i < 4; ++i) {
- GLuint swz = GET_SWZ(reg.Swizzle, i);
- if (swz == SWIZZLE_NIL) {
- reg.NegateBase &= ~(1 << i);
- continue;
- }
- if (swz >= 4)
- return GL_FALSE;
- }
- }
-
- if (reg.NegateBase)
- return GL_FALSE;
-
- return GL_TRUE;
- } else if (opcode == OPCODE_DDX || opcode == OPCODE_DDY) {
- /* DDX/MDH and DDY/MDV explicitly ignore incoming swizzles;
- * if it doesn't fit perfectly into a .xyzw case... */
- if (reg.Swizzle == SWIZZLE_NOOP && !reg.Abs
- && !reg.NegateBase && !reg.NegateAbs)
- return GL_TRUE;
-
- return GL_FALSE;
- } else {
- /* ALU instructions support almost everything */
- if (reg.Abs)
- return GL_TRUE;
-
- relevant = 0;
- for(i = 0; i < 3; ++i) {
- GLuint swz = GET_SWZ(reg.Swizzle, i);
- if (swz != SWIZZLE_NIL && swz != SWIZZLE_ZERO)
- relevant |= 1 << i;
- }
- if ((reg.NegateBase & relevant) && ((reg.NegateBase & relevant) != relevant))
- return GL_FALSE;
-
- return GL_TRUE;
- }
-}
-
-/**
- * Implement a MOV with a potentially non-native swizzle.
- *
- * The only thing we *cannot* do in an ALU instruction is per-component
- * negation. Therefore, we split the MOV into two instructions when necessary.
- */
-static void nqssadce_build_swizzle(struct nqssadce_state *s,
- struct prog_dst_register dst, struct prog_src_register src)
-{
- struct prog_instruction *inst;
- GLuint negatebase[2] = { 0, 0 };
- int i;
-
- for(i = 0; i < 4; ++i) {
- GLuint swz = GET_SWZ(src.Swizzle, i);
- if (swz == SWIZZLE_NIL)
- continue;
- negatebase[GET_BIT(src.NegateBase, i)] |= 1 << i;
- }
-
- _mesa_insert_instructions(s->Program, s->IP, (negatebase[0] ? 1 : 0) + (negatebase[1] ? 1 : 0));
- inst = s->Program->Instructions + s->IP;
-
- for(i = 0; i <= 1; ++i) {
- if (!negatebase[i])
- continue;
-
- inst->Opcode = OPCODE_MOV;
- inst->DstReg = dst;
- inst->DstReg.WriteMask = negatebase[i];
- inst->SrcReg[0] = src;
- inst++;
- s->IP++;
- }
-}
-
-static GLuint build_dtm(GLuint depthmode)
-{
- switch(depthmode) {
- default:
- case GL_LUMINANCE: return 0;
- case GL_INTENSITY: return 1;
- case GL_ALPHA: return 2;
- }
-}
-
-static GLuint build_func(GLuint comparefunc)
-{
- return comparefunc - GL_NEVER;
-}
-
-
-/**
- * Collect all external state that is relevant for compiling the given
- * fragment program.
- */
-static void build_state(
- r300ContextPtr r300,
- struct r500_fragment_program *fp,
- struct r500_fragment_program_external_state *state)
-{
- int unit;
-
- _mesa_bzero(state, sizeof(*state));
-
- for(unit = 0; unit < 16; ++unit) {
- if (fp->mesa_program.Base.ShadowSamplers & (1 << unit)) {
- struct gl_texture_object* tex = r300->radeon.glCtx->Texture.Unit[unit]._Current;
-
- state->unit[unit].depth_texture_mode = build_dtm(tex->DepthMode);
- state->unit[unit].texture_compare_func = build_func(tex->CompareFunc);
- }
- }
-}
-
-static void dump_program(struct r500_fragment_program_code *code);
-
-void r500TranslateFragmentShader(r300ContextPtr r300,
- struct r500_fragment_program *fp)
-{
- struct r500_fragment_program_external_state state;
-
- build_state(r300, fp, &state);
- if (_mesa_memcmp(&fp->state, &state, sizeof(state))) {
- /* TODO: cache compiled programs */
- fp->translated = GL_FALSE;
- _mesa_memcpy(&fp->state, &state, sizeof(state));
- }
-
- if (!fp->translated) {
- struct r500_fragment_program_compiler compiler;
-
- compiler.r300 = r300;
- compiler.fp = fp;
- compiler.code = &fp->code;
- compiler.program = _mesa_clone_program(r300->radeon.glCtx, &fp->mesa_program.Base);
-
- if (RADEON_DEBUG & DEBUG_PIXEL) {
- _mesa_printf("Compiler: Initial program:\n");
- _mesa_print_program(compiler.program);
- }
-
- insert_WPOS_trailer(&compiler);
-
- struct radeon_program_transformation transformations[] = {
- { &transform_TEX, &compiler },
- { &radeonTransformALU, 0 },
- { &radeonTransformDeriv, 0 },
- { &radeonTransformTrigScale, 0 }
- };
- radeonLocalTransform(r300->radeon.glCtx, compiler.program,
- 4, transformations);
-
- if (RADEON_DEBUG & DEBUG_PIXEL) {
- _mesa_printf("Compiler: after native rewrite:\n");
- _mesa_print_program(compiler.program);
- }
-
- struct radeon_nqssadce_descr nqssadce = {
- .Init = &nqssadce_init,
- .IsNativeSwizzle = &is_native_swizzle,
- .BuildSwizzle = &nqssadce_build_swizzle,
- .RewriteDepthOut = GL_TRUE
- };
- radeonNqssaDce(r300->radeon.glCtx, compiler.program, &nqssadce);
-
- if (RADEON_DEBUG & DEBUG_PIXEL) {
- _mesa_printf("Compiler: after NqSSA-DCE:\n");
- _mesa_print_program(compiler.program);
- }
-
- fp->translated = r500FragmentProgramEmit(&compiler);
-
- /* Subtle: Rescue any parameters that have been added during transformations */
- _mesa_free_parameter_list(fp->mesa_program.Base.Parameters);
- fp->mesa_program.Base.Parameters = compiler.program->Parameters;
- compiler.program->Parameters = 0;
-
- _mesa_reference_program(r300->radeon.glCtx, &compiler.program, 0);
-
- r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM);
-
- if (RADEON_DEBUG & DEBUG_PIXEL) {
- if (fp->translated) {
- _mesa_printf("Machine-readable code:\n");
- dump_program(&fp->code);
- }
- }
-
- }
-
- update_params(r300, fp);
-
-}
-
-static char *toswiz(int swiz_val) {
- switch(swiz_val) {
- case 0: return "R";
- case 1: return "G";
- case 2: return "B";
- case 3: return "A";
- case 4: return "0";
- case 5: return "1/2";
- case 6: return "1";
- case 7: return "U";
- }
- return NULL;
-}
-
-static char *toop(int op_val)
-{
- char *str = NULL;
- switch (op_val) {
- case 0: str = "MAD"; break;
- case 1: str = "DP3"; break;
- case 2: str = "DP4"; break;
- case 3: str = "D2A"; break;
- case 4: str = "MIN"; break;
- case 5: str = "MAX"; break;
- case 6: str = "Reserved"; break;
- case 7: str = "CND"; break;
- case 8: str = "CMP"; break;
- case 9: str = "FRC"; break;
- case 10: str = "SOP"; break;
- case 11: str = "MDH"; break;
- case 12: str = "MDV"; break;
- }
- return str;
-}
-
-static char *to_alpha_op(int op_val)
-{
- char *str = NULL;
- switch (op_val) {
- case 0: str = "MAD"; break;
- case 1: str = "DP"; break;
- case 2: str = "MIN"; break;
- case 3: str = "MAX"; break;
- case 4: str = "Reserved"; break;
- case 5: str = "CND"; break;
- case 6: str = "CMP"; break;
- case 7: str = "FRC"; break;
- case 8: str = "EX2"; break;
- case 9: str = "LN2"; break;
- case 10: str = "RCP"; break;
- case 11: str = "RSQ"; break;
- case 12: str = "SIN"; break;
- case 13: str = "COS"; break;
- case 14: str = "MDH"; break;
- case 15: str = "MDV"; break;
- }
- return str;
-}
-
-static char *to_mask(int val)
-{
- char *str = NULL;
- switch(val) {
- case 0: str = "NONE"; break;
- case 1: str = "R"; break;
- case 2: str = "G"; break;
- case 3: str = "RG"; break;
- case 4: str = "B"; break;
- case 5: str = "RB"; break;
- case 6: str = "GB"; break;
- case 7: str = "RGB"; break;
- case 8: str = "A"; break;
- case 9: str = "AR"; break;
- case 10: str = "AG"; break;
- case 11: str = "ARG"; break;
- case 12: str = "AB"; break;
- case 13: str = "ARB"; break;
- case 14: str = "AGB"; break;
- case 15: str = "ARGB"; break;
- }
- return str;
-}
-
-static char *to_texop(int val)
-{
- switch(val) {
- case 0: return "NOP";
- case 1: return "LD";
- case 2: return "TEXKILL";
- case 3: return "PROJ";
- case 4: return "LODBIAS";
- case 5: return "LOD";
- case 6: return "DXDY";
- }
- return NULL;
-}
-
-static void dump_program(struct r500_fragment_program_code *code)
-{
-
- fprintf(stderr, "R500 Fragment Program:\n--------\n");
-
- int n;
- uint32_t inst;
- uint32_t inst0;
- char *str = NULL;
-
- if (code->const_nr) {
- fprintf(stderr, "--------\nConstants:\n");
- for (n = 0; n < code->const_nr; n++) {
- fprintf(stderr, "Constant %d: %i[%i]\n", n,
- code->constant[n].File, code->constant[n].Index);
- }
- fprintf(stderr, "--------\n");
- }
-
- for (n = 0; n < code->inst_end+1; n++) {
- inst0 = inst = code->inst[n].inst0;
- fprintf(stderr,"%d\t0:CMN_INST 0x%08x:", n, inst);
- switch(inst & 0x3) {
- case R500_INST_TYPE_ALU: str = "ALU"; break;
- case R500_INST_TYPE_OUT: str = "OUT"; break;
- case R500_INST_TYPE_FC: str = "FC"; break;
- case R500_INST_TYPE_TEX: str = "TEX"; break;
- };
- fprintf(stderr,"%s %s %s %s %s ", str,
- inst & R500_INST_TEX_SEM_WAIT ? "TEX_WAIT" : "",
- inst & R500_INST_LAST ? "LAST" : "",
- inst & R500_INST_NOP ? "NOP" : "",
- inst & R500_INST_ALU_WAIT ? "ALU WAIT" : "");
- fprintf(stderr,"wmask: %s omask: %s\n", to_mask((inst >> 11) & 0xf),
- to_mask((inst >> 15) & 0xf));
-
- switch(inst0 & 0x3) {
- case 0:
- case 1:
- fprintf(stderr,"\t1:RGB_ADDR 0x%08x:", code->inst[n].inst1);
- inst = code->inst[n].inst1;
-
- fprintf(stderr,"Addr0: %d%c, Addr1: %d%c, Addr2: %d%c, srcp:%d\n",
- inst & 0xff, (inst & (1<<8)) ? 'c' : 't',
- (inst >> 10) & 0xff, (inst & (1<<18)) ? 'c' : 't',
- (inst >> 20) & 0xff, (inst & (1<<28)) ? 'c' : 't',
- (inst >> 30));
-
- fprintf(stderr,"\t2:ALPHA_ADDR 0x%08x:", code->inst[n].inst2);
- inst = code->inst[n].inst2;
- fprintf(stderr,"Addr0: %d%c, Addr1: %d%c, Addr2: %d%c, srcp:%d\n",
- inst & 0xff, (inst & (1<<8)) ? 'c' : 't',
- (inst >> 10) & 0xff, (inst & (1<<18)) ? 'c' : 't',
- (inst >> 20) & 0xff, (inst & (1<<28)) ? 'c' : 't',
- (inst >> 30));
- fprintf(stderr,"\t3 RGB_INST: 0x%08x:", code->inst[n].inst3);
- inst = code->inst[n].inst3;
- fprintf(stderr,"rgb_A_src:%d %s/%s/%s %d rgb_B_src:%d %s/%s/%s %d\n",
- (inst) & 0x3, toswiz((inst >> 2) & 0x7), toswiz((inst >> 5) & 0x7), toswiz((inst >> 8) & 0x7),
- (inst >> 11) & 0x3,
- (inst >> 13) & 0x3, toswiz((inst >> 15) & 0x7), toswiz((inst >> 18) & 0x7), toswiz((inst >> 21) & 0x7),
- (inst >> 24) & 0x3);
-
-
- fprintf(stderr,"\t4 ALPHA_INST:0x%08x:", code->inst[n].inst4);
- inst = code->inst[n].inst4;
- fprintf(stderr,"%s dest:%d%s alp_A_src:%d %s %d alp_B_src:%d %s %d w:%d\n", to_alpha_op(inst & 0xf),
- (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"",
- (inst >> 12) & 0x3, toswiz((inst >> 14) & 0x7), (inst >> 17) & 0x3,
- (inst >> 19) & 0x3, toswiz((inst >> 21) & 0x7), (inst >> 24) & 0x3,
- (inst >> 31) & 0x1);
-
- fprintf(stderr,"\t5 RGBA_INST: 0x%08x:", code->inst[n].inst5);
- inst = code->inst[n].inst5;
- fprintf(stderr,"%s dest:%d%s rgb_C_src:%d %s/%s/%s %d alp_C_src:%d %s %d\n", toop(inst & 0xf),
- (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"",
- (inst >> 12) & 0x3, toswiz((inst >> 14) & 0x7), toswiz((inst >> 17) & 0x7), toswiz((inst >> 20) & 0x7),
- (inst >> 23) & 0x3,
- (inst >> 25) & 0x3, toswiz((inst >> 27) & 0x7), (inst >> 30) & 0x3);
- break;
- case 2:
- break;
- case 3:
- inst = code->inst[n].inst1;
- fprintf(stderr,"\t1:TEX_INST: 0x%08x: id: %d op:%s, %s, %s %s\n", inst, (inst >> 16) & 0xf,
- to_texop((inst >> 22) & 0x7), (inst & (1<<25)) ? "ACQ" : "",
- (inst & (1<<26)) ? "IGNUNC" : "", (inst & (1<<27)) ? "UNSCALED" : "SCALED");
- inst = code->inst[n].inst2;
- fprintf(stderr,"\t2:TEX_ADDR: 0x%08x: src: %d%s %s/%s/%s/%s dst: %d%s %s/%s/%s/%s\n", inst,
- inst & 127, inst & (1<<7) ? "(rel)" : "",
- toswiz((inst >> 8) & 0x3), toswiz((inst >> 10) & 0x3),
- toswiz((inst >> 12) & 0x3), toswiz((inst >> 14) & 0x3),
- (inst >> 16) & 127, inst & (1<<23) ? "(rel)" : "",
- toswiz((inst >> 24) & 0x3), toswiz((inst >> 26) & 0x3),
- toswiz((inst >> 28) & 0x3), toswiz((inst >> 30) & 0x3));
-
- fprintf(stderr,"\t3:TEX_DXDY: 0x%08x\n", code->inst[n].inst3);
- break;
- }
- fprintf(stderr,"\n");
- }
-
-}
diff --git a/src/mesa/drivers/dri/r300/radeon_bo_legacy.c b/src/mesa/drivers/dri/r300/radeon_bo_legacy.c
new file mode 120000
index 0000000000..79ad050e6b
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_bo_legacy.c
@@ -0,0 +1 @@
+../radeon/radeon_bo_legacy.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_bo_legacy.h b/src/mesa/drivers/dri/r300/radeon_bo_legacy.h
new file mode 120000
index 0000000000..83b0f7ffab
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_bo_legacy.h
@@ -0,0 +1 @@
+../radeon/radeon_bo_legacy.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_bocs_wrapper.h b/src/mesa/drivers/dri/r300/radeon_bocs_wrapper.h
new file mode 120000
index 0000000000..ca894b2443
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_bocs_wrapper.h
@@ -0,0 +1 @@
+../radeon/radeon_bocs_wrapper.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_buffer_objects.c b/src/mesa/drivers/dri/r300/radeon_buffer_objects.c
new file mode 120000
index 0000000000..f6a5f66470
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_buffer_objects.c
@@ -0,0 +1 @@
+../radeon/radeon_buffer_objects.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_buffer_objects.h b/src/mesa/drivers/dri/r300/radeon_buffer_objects.h
new file mode 120000
index 0000000000..2f134fd17b
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_buffer_objects.h
@@ -0,0 +1 @@
+../radeon/radeon_buffer_objects.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_chipset.h b/src/mesa/drivers/dri/r300/radeon_chipset.h
new file mode 120000
index 0000000000..eba99001ff
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_chipset.h
@@ -0,0 +1 @@
+../radeon/radeon_chipset.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_cmdbuf.h b/src/mesa/drivers/dri/r300/radeon_cmdbuf.h
new file mode 120000
index 0000000000..a799e1dc6d
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_cmdbuf.h
@@ -0,0 +1 @@
+../radeon/radeon_cmdbuf.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_common.c b/src/mesa/drivers/dri/r300/radeon_common.c
new file mode 120000
index 0000000000..67b19ba940
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_common.c
@@ -0,0 +1 @@
+../radeon/radeon_common.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_common.h b/src/mesa/drivers/dri/r300/radeon_common.h
new file mode 120000
index 0000000000..5bcb696a9f
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_common.h
@@ -0,0 +1 @@
+../radeon/radeon_common.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_common_context.c b/src/mesa/drivers/dri/r300/radeon_common_context.c
new file mode 120000
index 0000000000..86800f3819
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_common_context.c
@@ -0,0 +1 @@
+../radeon/radeon_common_context.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_common_context.h b/src/mesa/drivers/dri/r300/radeon_common_context.h
new file mode 120000
index 0000000000..4d66312550
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_common_context.h
@@ -0,0 +1 @@
+../radeon/radeon_common_context.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_context.c b/src/mesa/drivers/dri/r300/radeon_context.c
deleted file mode 100644
index 5267fe9a77..0000000000
--- a/src/mesa/drivers/dri/r300/radeon_context.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/**
- * \file radeon_context.c
- * Common context initialization.
- *
- * \author Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include <dlfcn.h>
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/state.h"
-#include "main/matrix.h"
-#include "main/framebuffer.h"
-
-#include "drivers/common/driverfuncs.h"
-#include "swrast/swrast.h"
-
-#include "radeon_screen.h"
-#include "radeon_ioctl.h"
-#include "radeon_macros.h"
-#include "radeon_reg.h"
-
-#include "radeon_state.h"
-#include "r300_state.h"
-
-#include "utils.h"
-#include "vblank.h"
-#include "xmlpool.h" /* for symbolic values of enum-type options */
-
-#define DRIVER_DATE "20060815"
-
-
-/* Return various strings for glGetString().
- */
-static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name)
-{
- radeonContextPtr radeon = RADEON_CONTEXT(ctx);
- static char buffer[128];
-
- switch (name) {
- case GL_VENDOR:
- if (IS_R300_CLASS(radeon->radeonScreen))
- return (GLubyte *) "DRI R300 Project";
- else
- return (GLubyte *) "Tungsten Graphics, Inc.";
-
- case GL_RENDERER:
- {
- unsigned offset;
- GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
- radeon->radeonScreen->AGPMode;
- const char* chipname;
-
- if (IS_R300_CLASS(radeon->radeonScreen))
- chipname = "R300";
- else
- chipname = "R200";
-
- offset = driGetRendererString(buffer, chipname, DRIVER_DATE,
- agp_mode);
-
- if (IS_R300_CLASS(radeon->radeonScreen)) {
- sprintf(&buffer[offset], " %sTCL",
- (radeon->radeonScreen->chip_flags & RADEON_CHIPSET_TCL)
- ? "" : "NO-");
- } else {
- sprintf(&buffer[offset], " %sTCL",
- !(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
- ? "" : "NO-");
- }
-
- return (GLubyte *) buffer;
- }
-
- default:
- return NULL;
- }
-}
-
-/* Initialize the driver's misc functions.
- */
-static void radeonInitDriverFuncs(struct dd_function_table *functions)
-{
- functions->GetString = radeonGetString;
-}
-
-
-/**
- * Create and initialize all common fields of the context,
- * including the Mesa context itself.
- */
-GLboolean radeonInitContext(radeonContextPtr radeon,
- struct dd_function_table* functions,
- const __GLcontextModes * glVisual,
- __DRIcontextPrivate * driContextPriv,
- void *sharedContextPrivate)
-{
- __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
- radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
- GLcontext* ctx;
- GLcontext* shareCtx;
- int fthrottle_mode;
-
- /* Fill in additional standard functions. */
- radeonInitDriverFuncs(functions);
-
- radeon->radeonScreen = screen;
- /* Allocate and initialize the Mesa context */
- if (sharedContextPrivate)
- shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx;
- else
- shareCtx = NULL;
- radeon->glCtx = _mesa_create_context(glVisual, shareCtx,
- functions, (void *)radeon);
- if (!radeon->glCtx)
- return GL_FALSE;
-
- ctx = radeon->glCtx;
- driContextPriv->driverPrivate = radeon;
-
- /* DRI fields */
- radeon->dri.context = driContextPriv;
- radeon->dri.screen = sPriv;
- radeon->dri.drawable = NULL;
- radeon->dri.readable = NULL;
- radeon->dri.hwContext = driContextPriv->hHWContext;
- radeon->dri.hwLock = &sPriv->pSAREA->lock;
- radeon->dri.fd = sPriv->fd;
- radeon->dri.drmMinor = sPriv->drm_version.minor;
-
- radeon->sarea = (drm_radeon_sarea_t *) ((GLubyte *) sPriv->pSAREA +
- screen->sarea_priv_offset);
-
- /* Setup IRQs */
- fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode");
- radeon->iw.irq_seq = -1;
- radeon->irqsEmitted = 0;
- radeon->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
- radeon->radeonScreen->irq);
-
- radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
-
- if (!radeon->do_irqs)
- fprintf(stderr,
- "IRQ's not enabled, falling back to %s: %d %d\n",
- radeon->do_usleeps ? "usleeps" : "busy waits",
- fthrottle_mode, radeon->radeonScreen->irq);
-
- (*sPriv->systemTime->getUST) (&radeon->swap_ust);
-
- return GL_TRUE;
-}
-
-
-/**
- * Cleanup common context fields.
- * Called by r200DestroyContext/r300DestroyContext
- */
-void radeonCleanupContext(radeonContextPtr radeon)
-{
- /* _mesa_destroy_context() might result in calls to functions that
- * depend on the DriverCtx, so don't set it to NULL before.
- *
- * radeon->glCtx->DriverCtx = NULL;
- */
-
- /* free the Mesa context */
- _mesa_destroy_context(radeon->glCtx);
-
- if (radeon->state.scissor.pClipRects) {
- FREE(radeon->state.scissor.pClipRects);
- radeon->state.scissor.pClipRects = 0;
- }
-}
-
-
-/**
- * Swap front and back buffer.
- */
-void radeonSwapBuffers(__DRIdrawablePrivate * dPriv)
-{
- if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
- radeonContextPtr radeon;
- GLcontext *ctx;
-
- radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
- ctx = radeon->glCtx;
-
- if (ctx->Visual.doubleBufferMode) {
- _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
- if (radeon->doPageFlip) {
- radeonPageFlip(dPriv);
- } else {
- radeonCopyBuffer(dPriv, NULL);
- }
- }
- } else {
- /* XXX this shouldn't be an error but we can't handle it for now */
- _mesa_problem(NULL, "%s: drawable has no context!",
- __FUNCTION__);
- }
-}
-
-void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
- int x, int y, int w, int h )
-{
- if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
- radeonContextPtr radeon;
- GLcontext *ctx;
-
- radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
- ctx = radeon->glCtx;
-
- if (ctx->Visual.doubleBufferMode) {
- drm_clip_rect_t rect;
- rect.x1 = x + dPriv->x;
- rect.y1 = (dPriv->h - y - h) + dPriv->y;
- rect.x2 = rect.x1 + w;
- rect.y2 = rect.y1 + h;
- _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
- radeonCopyBuffer(dPriv, &rect);
- }
- } else {
- /* XXX this shouldn't be an error but we can't handle it for now */
- _mesa_problem(NULL, "%s: drawable has no context!",
- __FUNCTION__);
- }
-}
-
-/* Force the context `c' to be the current context and associate with it
- * buffer `b'.
- */
-GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
- __DRIdrawablePrivate * driDrawPriv,
- __DRIdrawablePrivate * driReadPriv)
-{
- if (driContextPriv) {
- radeonContextPtr radeon =
- (radeonContextPtr) driContextPriv->driverPrivate;
-
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
- radeon->glCtx);
-
- if (radeon->dri.drawable != driDrawPriv) {
- if (driDrawPriv->swap_interval == (unsigned)-1) {
- driDrawPriv->vblFlags =
- (radeon->radeonScreen->irq != 0)
- ? driGetDefaultVBlankFlags(&radeon->
- optionCache)
- : VBLANK_FLAG_NO_IRQ;
-
- driDrawableInitVBlank(driDrawPriv);
- }
- }
-
- radeon->dri.readable = driReadPriv;
-
- if (radeon->dri.drawable != driDrawPriv ||
- radeon->lastStamp != driDrawPriv->lastStamp) {
- radeon->dri.drawable = driDrawPriv;
-
- radeonSetCliprects(radeon);
- r300UpdateViewportOffset(radeon->glCtx);
- }
-
- _mesa_make_current(radeon->glCtx,
- (GLframebuffer *) driDrawPriv->
- driverPrivate,
- (GLframebuffer *) driReadPriv->
- driverPrivate);
-
- _mesa_update_state(radeon->glCtx);
-
- radeonUpdatePageFlipping(radeon);
- } else {
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
- _mesa_make_current(0, 0, 0);
- }
-
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "End %s\n", __FUNCTION__);
- return GL_TRUE;
-}
-
-/* Force the context `c' to be unbound from its buffer.
- */
-GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv)
-{
- radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
-
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
- radeon->glCtx);
-
- return GL_TRUE;
-}
-
diff --git a/src/mesa/drivers/dri/r300/radeon_context.h b/src/mesa/drivers/dri/r300/radeon_context.h
index 47cbc22a72..250570f6b8 100644
--- a/src/mesa/drivers/dri/r300/radeon_context.h
+++ b/src/mesa/drivers/dri/r300/radeon_context.h
@@ -49,20 +49,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "drm.h"
#include "dri_util.h"
-struct radeon_context;
-typedef struct radeon_context radeonContextRec;
-typedef struct radeon_context *radeonContextPtr;
-
-/* Rasterizing fallbacks */
-/* See correponding strings in r200_swtcl.c */
-#define RADEON_FALLBACK_TEXTURE 0x0001
-#define RADEON_FALLBACK_DRAW_BUFFER 0x0002
-#define RADEON_FALLBACK_STENCIL 0x0004
-#define RADEON_FALLBACK_RENDER_MODE 0x0008
-#define RADEON_FALLBACK_BLEND_EQ 0x0010
-#define RADEON_FALLBACK_BLEND_FUNC 0x0020
-#define RADEON_FALLBACK_DISABLE 0x0040
-#define RADEON_FALLBACK_BORDER_MODE 0x0080
+#include "radeon_screen.h"
#if R200_MERGED
extern void radeonFallback(GLcontext * ctx, GLuint bit, GLboolean mode);
@@ -79,155 +66,11 @@ extern void radeonFallback(GLcontext * ctx, GLuint bit, GLboolean mode);
/* TCL fallbacks */
extern void radeonTclFallback(GLcontext * ctx, GLuint bit, GLboolean mode);
-#define RADEON_TCL_FALLBACK_RASTER 0x0001 /* rasterization */
-#define RADEON_TCL_FALLBACK_UNFILLED 0x0002 /* unfilled tris */
-#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE 0x0004 /* twoside tris */
-#define RADEON_TCL_FALLBACK_MATERIAL 0x0008 /* material in vb */
-#define RADEON_TCL_FALLBACK_TEXGEN_0 0x0010 /* texgen, unit 0 */
-#define RADEON_TCL_FALLBACK_TEXGEN_1 0x0020 /* texgen, unit 1 */
-#define RADEON_TCL_FALLBACK_TEXGEN_2 0x0040 /* texgen, unit 2 */
-#define RADEON_TCL_FALLBACK_TEXGEN_3 0x0080 /* texgen, unit 3 */
-#define RADEON_TCL_FALLBACK_TEXGEN_4 0x0100 /* texgen, unit 4 */
-#define RADEON_TCL_FALLBACK_TEXGEN_5 0x0200 /* texgen, unit 5 */
-#define RADEON_TCL_FALLBACK_TCL_DISABLE 0x0400 /* user disable */
-#define RADEON_TCL_FALLBACK_BITMAP 0x0800 /* draw bitmap with points */
-#define RADEON_TCL_FALLBACK_VERTEX_PROGRAM 0x1000 /* vertex program active */
-
#if R200_MERGED
#define TCL_FALLBACK( ctx, bit, mode ) radeonTclFallback( ctx, bit, mode )
#else
#define TCL_FALLBACK( ctx, bit, mode ) ;
#endif
-struct radeon_dri_mirror {
- __DRIcontextPrivate *context; /* DRI context */
- __DRIscreenPrivate *screen; /* DRI screen */
- /**
- * DRI drawable bound to this context for drawing.
- */
- __DRIdrawablePrivate *drawable;
-
- /**
- * DRI drawable bound to this context for reading.
- */
- __DRIdrawablePrivate *readable;
-
- drm_context_t hwContext;
- drm_hw_lock_t *hwLock;
- int fd;
- int drmMinor;
-};
-
-/**
- * Derived state for internal purposes.
- */
-struct radeon_scissor_state {
- drm_clip_rect_t rect;
- GLboolean enabled;
-
- GLuint numClipRects; /* Cliprects active */
- GLuint numAllocedClipRects; /* Cliprects available */
- drm_clip_rect_t *pClipRects;
-};
-
-struct radeon_colorbuffer_state {
- GLuint clear;
- GLint drawOffset, drawPitch;
-};
-
-struct radeon_state {
- struct radeon_colorbuffer_state color;
- struct radeon_scissor_state scissor;
-};
-
-/**
- * Common per-context variables shared by R200 and R300.
- * R200- and R300-specific code "derive" their own context from this
- * structure.
- */
-struct radeon_context {
- GLcontext *glCtx; /* Mesa context */
- radeonScreenPtr radeonScreen; /* Screen private DRI data */
-
- /* Fallback state */
- GLuint Fallback;
- GLuint TclFallback;
-
- /* Page flipping */
- GLuint doPageFlip;
-
- /* Drawable, cliprect and scissor information */
- GLuint numClipRects; /* Cliprects for the draw buffer */
- drm_clip_rect_t *pClipRects;
- unsigned int lastStamp;
- GLboolean lost_context;
- drm_radeon_sarea_t *sarea; /* Private SAREA data */
-
- /* Mirrors of some DRI state */
- struct radeon_dri_mirror dri;
-
- /* Busy waiting */
- GLuint do_usleeps;
- GLuint do_irqs;
- GLuint irqsEmitted;
- drm_radeon_irq_wait_t iw;
-
- /* buffer swap */
- int64_t swap_ust;
- int64_t swap_missed_ust;
-
- GLuint swap_count;
- GLuint swap_missed_count;
-
- /* Derived state */
- struct radeon_state state;
-
- /* Configuration cache
- */
- driOptionCache optionCache;
-};
-
-#define RADEON_CONTEXT(glctx) ((radeonContextPtr)(ctx->DriverCtx))
-
-extern void radeonSwapBuffers(__DRIdrawablePrivate * dPriv);
-extern void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
- int x, int y, int w, int h);
-extern GLboolean radeonInitContext(radeonContextPtr radeon,
- struct dd_function_table *functions,
- const __GLcontextModes * glVisual,
- __DRIcontextPrivate * driContextPriv,
- void *sharedContextPrivate);
-extern void radeonCleanupContext(radeonContextPtr radeon);
-extern GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
- __DRIdrawablePrivate * driDrawPriv,
- __DRIdrawablePrivate * driReadPriv);
-extern GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv);
-
-/* ================================================================
- * Debugging:
- */
-#define DO_DEBUG 1
-
-#if DO_DEBUG
-extern int RADEON_DEBUG;
-#else
-#define RADEON_DEBUG 0
-#endif
-
-#define DEBUG_TEXTURE 0x0001
-#define DEBUG_STATE 0x0002
-#define DEBUG_IOCTL 0x0004
-#define DEBUG_PRIMS 0x0008
-#define DEBUG_VERTS 0x0010
-#define DEBUG_FALLBACKS 0x0020
-#define DEBUG_VFMT 0x0040
-#define DEBUG_CODEGEN 0x0080
-#define DEBUG_VERBOSE 0x0100
-#define DEBUG_DRI 0x0200
-#define DEBUG_DMA 0x0400
-#define DEBUG_SANITY 0x0800
-#define DEBUG_SYNC 0x1000
-#define DEBUG_PIXEL 0x2000
-#define DEBUG_MEMORY 0x4000
#endif /* __RADEON_CONTEXT_H__ */
diff --git a/src/mesa/drivers/dri/r300/radeon_cs_legacy.c b/src/mesa/drivers/dri/r300/radeon_cs_legacy.c
new file mode 120000
index 0000000000..006720f8a4
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_cs_legacy.c
@@ -0,0 +1 @@
+../radeon/radeon_cs_legacy.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_cs_legacy.h b/src/mesa/drivers/dri/r300/radeon_cs_legacy.h
new file mode 120000
index 0000000000..a5f95e0a3d
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_cs_legacy.h
@@ -0,0 +1 @@
+../radeon/radeon_cs_legacy.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_cs_space_drm.c b/src/mesa/drivers/dri/r300/radeon_cs_space_drm.c
new file mode 120000
index 0000000000..c248ea7d1a
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_cs_space_drm.c
@@ -0,0 +1 @@
+../radeon/radeon_cs_space_drm.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_debug.c b/src/mesa/drivers/dri/r300/radeon_debug.c
new file mode 120000
index 0000000000..c98c2e074c
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_debug.c
@@ -0,0 +1 @@
+../radeon/radeon_debug.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_debug.h b/src/mesa/drivers/dri/r300/radeon_debug.h
new file mode 120000
index 0000000000..bd8aa28e89
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_debug.h
@@ -0,0 +1 @@
+../radeon/radeon_debug.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_dma.c b/src/mesa/drivers/dri/r300/radeon_dma.c
new file mode 120000
index 0000000000..43be000625
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_dma.c
@@ -0,0 +1 @@
+../radeon/radeon_dma.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_dma.h b/src/mesa/drivers/dri/r300/radeon_dma.h
new file mode 120000
index 0000000000..82e50634e3
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_dma.h
@@ -0,0 +1 @@
+../radeon/radeon_dma.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_fbo.c b/src/mesa/drivers/dri/r300/radeon_fbo.c
new file mode 120000
index 0000000000..0d738d8d78
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_fbo.c
@@ -0,0 +1 @@
+../radeon/radeon_fbo.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_ioctl.c b/src/mesa/drivers/dri/r300/radeon_ioctl.c
deleted file mode 100644
index 36502eb42d..0000000000
--- a/src/mesa/drivers/dri/r300/radeon_ioctl.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include <sched.h>
-#include <errno.h>
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/macros.h"
-#include "main/context.h"
-#include "swrast/swrast.h"
-#include "r300_context.h"
-#include "radeon_ioctl.h"
-#include "r300_ioctl.h"
-#include "r300_state.h"
-#include "radeon_reg.h"
-
-#include "drirenderbuffer.h"
-#include "vblank.h"
-
-static void radeonWaitForIdle(radeonContextPtr radeon);
-
-/* ================================================================
- * SwapBuffers with client-side throttling
- */
-
-static uint32_t radeonGetLastFrame(radeonContextPtr radeon)
-{
- drm_radeon_getparam_t gp;
- int ret;
- uint32_t frame;
-
- gp.param = RADEON_PARAM_LAST_FRAME;
- gp.value = (int *)&frame;
- ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_GETPARAM,
- &gp, sizeof(gp));
- if (ret) {
- fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__,
- ret);
- exit(1);
- }
-
- return frame;
-}
-
-uint32_t radeonGetAge(radeonContextPtr radeon)
-{
- drm_radeon_getparam_t gp;
- int ret;
- uint32_t age;
-
- gp.param = RADEON_PARAM_LAST_CLEAR;
- gp.value = (int *)&age;
- ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_GETPARAM,
- &gp, sizeof(gp));
- if (ret) {
- fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__,
- ret);
- exit(1);
- }
-
- return age;
-}
-
-static void radeonEmitIrqLocked(radeonContextPtr radeon)
-{
- drm_radeon_irq_emit_t ie;
- int ret;
-
- ie.irq_seq = &radeon->iw.irq_seq;
- ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_IRQ_EMIT,
- &ie, sizeof(ie));
- if (ret) {
- fprintf(stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__,
- ret);
- exit(1);
- }
-}
-
-static void radeonWaitIrq(radeonContextPtr radeon)
-{
- int ret;
-
- do {
- ret = drmCommandWrite(radeon->dri.fd, DRM_RADEON_IRQ_WAIT,
- &radeon->iw, sizeof(radeon->iw));
- } while (ret && (errno == EINTR || errno == EBUSY));
-
- if (ret) {
- fprintf(stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__,
- ret);
- exit(1);
- }
-}
-
-static void radeonWaitForFrameCompletion(radeonContextPtr radeon)
-{
- drm_radeon_sarea_t *sarea = radeon->sarea;
-
- if (radeon->do_irqs) {
- if (radeonGetLastFrame(radeon) < sarea->last_frame) {
- if (!radeon->irqsEmitted) {
- while (radeonGetLastFrame(radeon) <
- sarea->last_frame) ;
- } else {
- UNLOCK_HARDWARE(radeon);
- radeonWaitIrq(radeon);
- LOCK_HARDWARE(radeon);
- }
- radeon->irqsEmitted = 10;
- }
-
- if (radeon->irqsEmitted) {
- radeonEmitIrqLocked(radeon);
- radeon->irqsEmitted--;
- }
- } else {
- while (radeonGetLastFrame(radeon) < sarea->last_frame) {
- UNLOCK_HARDWARE(radeon);
- if (radeon->do_usleeps)
- DO_USLEEP(1);
- LOCK_HARDWARE(radeon);
- }
- }
-}
-
-/* Copy the back color buffer to the front color buffer.
- */
-void radeonCopyBuffer(__DRIdrawablePrivate * dPriv,
- const drm_clip_rect_t * rect)
-{
- radeonContextPtr radeon;
- GLint nbox, i, ret;
- GLboolean missed_target;
- int64_t ust;
- __DRIscreenPrivate *psp = dPriv->driScreenPriv;
-
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
-
- radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
-
- if (RADEON_DEBUG & DEBUG_IOCTL) {
- fprintf(stderr, "\n%s( %p )\n\n", __FUNCTION__,
- (void *)radeon->glCtx);
- }
-
- r300Flush(radeon->glCtx);
-
- LOCK_HARDWARE(radeon);
-
- /* Throttle the frame rate -- only allow one pending swap buffers
- * request at a time.
- */
- radeonWaitForFrameCompletion(radeon);
- if (!rect)
- {
- UNLOCK_HARDWARE(radeon);
- driWaitForVBlank(dPriv, &missed_target);
- LOCK_HARDWARE(radeon);
- }
-
- nbox = dPriv->numClipRects; /* must be in locked region */
-
- for (i = 0; i < nbox;) {
- GLint nr = MIN2(i + RADEON_NR_SAREA_CLIPRECTS, nbox);
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t *b = radeon->sarea->boxes;
- GLint n = 0;
-
- for ( ; i < nr ; i++ ) {
-
- *b = box[i];
-
- if (rect)
- {
- if (rect->x1 > b->x1)
- b->x1 = rect->x1;
- if (rect->y1 > b->y1)
- b->y1 = rect->y1;
- if (rect->x2 < b->x2)
- b->x2 = rect->x2;
- if (rect->y2 < b->y2)
- b->y2 = rect->y2;
-
- if (b->x1 >= b->x2 || b->y1 >= b->y2)
- continue;
- }
-
- b++;
- n++;
- }
- radeon->sarea->nbox = n;
-
- if (!n)
- continue;
-
- ret = drmCommandNone(radeon->dri.fd, DRM_RADEON_SWAP);
-
- if (ret) {
- fprintf(stderr, "DRM_RADEON_SWAP: return = %d\n",
- ret);
- UNLOCK_HARDWARE(radeon);
- exit(1);
- }
- }
-
- UNLOCK_HARDWARE(radeon);
- if (!rect)
- {
- ((r300ContextPtr)radeon)->hw.all_dirty = GL_TRUE;
-
- radeon->swap_count++;
- (*psp->systemTime->getUST) (&ust);
- if (missed_target) {
- radeon->swap_missed_count++;
- radeon->swap_missed_ust = ust - radeon->swap_ust;
- }
-
- radeon->swap_ust = ust;
-
- sched_yield();
- }
-}
-
-void radeonPageFlip(__DRIdrawablePrivate * dPriv)
-{
- radeonContextPtr radeon;
- GLint ret;
- GLboolean missed_target;
- __DRIscreenPrivate *psp = dPriv->driScreenPriv;
-
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
-
- radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
-
- if (RADEON_DEBUG & DEBUG_IOCTL) {
- fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__,
- radeon->sarea->pfCurrentPage);
- }
-
- r300Flush(radeon->glCtx);
- LOCK_HARDWARE(radeon);
-
- if (!dPriv->numClipRects) {
- UNLOCK_HARDWARE(radeon);
- usleep(10000); /* throttle invisible client 10ms */
- return;
- }
-
- /* Need to do this for the perf box placement:
- */
- {
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t *b = radeon->sarea->boxes;
- b[0] = box[0];
- radeon->sarea->nbox = 1;
- }
-
- /* Throttle the frame rate -- only allow a few pending swap buffers
- * request at a time.
- */
- radeonWaitForFrameCompletion(radeon);
- UNLOCK_HARDWARE(radeon);
- driWaitForVBlank(dPriv, &missed_target);
- if (missed_target) {
- radeon->swap_missed_count++;
- (void)(*psp->systemTime->getUST) (&radeon->swap_missed_ust);
- }
- LOCK_HARDWARE(radeon);
-
- ret = drmCommandNone(radeon->dri.fd, DRM_RADEON_FLIP);
-
- UNLOCK_HARDWARE(radeon);
-
- if (ret) {
- fprintf(stderr, "DRM_RADEON_FLIP: return = %d\n", ret);
- exit(1);
- }
-
- radeon->swap_count++;
- (void)(*psp->systemTime->getUST) (&radeon->swap_ust);
-
- driFlipRenderbuffers(radeon->glCtx->WinSysDrawBuffer,
- radeon->sarea->pfCurrentPage);
-
- if (radeon->sarea->pfCurrentPage == 1) {
- radeon->state.color.drawOffset = radeon->radeonScreen->frontOffset;
- radeon->state.color.drawPitch = radeon->radeonScreen->frontPitch;
- } else {
- radeon->state.color.drawOffset = radeon->radeonScreen->backOffset;
- radeon->state.color.drawPitch = radeon->radeonScreen->backPitch;
- }
-
- if (IS_R300_CLASS(radeon->radeonScreen)) {
- r300ContextPtr r300 = (r300ContextPtr)radeon;
- R300_STATECHANGE(r300, cb);
- r300->hw.cb.cmd[R300_CB_OFFSET] = r300->radeon.state.color.drawOffset +
- r300->radeon.radeonScreen->fbLocation;
- r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.state.color.drawPitch;
-
- if (r300->radeon.radeonScreen->cpp == 4)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_ARGB8888;
- else
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_FORMAT_RGB565;
-
- if (r300->radeon.sarea->tiling_enabled)
- r300->hw.cb.cmd[R300_CB_PITCH] |= R300_COLOR_TILE_ENABLE;
- }
-}
-
-void radeonWaitForIdleLocked(radeonContextPtr radeon)
-{
- int ret;
- int i = 0;
-
- do {
- ret = drmCommandNone(radeon->dri.fd, DRM_RADEON_CP_IDLE);
- if (ret)
- DO_USLEEP(1);
- } while (ret && ++i < 100);
-
- if (ret < 0) {
- UNLOCK_HARDWARE(radeon);
- fprintf(stderr, "Error: R300 timed out... exiting\n");
- exit(-1);
- }
-}
-
-static void radeonWaitForIdle(radeonContextPtr radeon)
-{
- LOCK_HARDWARE(radeon);
- radeonWaitForIdleLocked(radeon);
- UNLOCK_HARDWARE(radeon);
-}
-
-void radeonFlush(GLcontext * ctx)
-{
- radeonContextPtr radeon = RADEON_CONTEXT(ctx);
-
- if (IS_R300_CLASS(radeon->radeonScreen))
- r300Flush(ctx);
-}
-
-
-/* Make sure all commands have been sent to the hardware and have
- * completed processing.
- */
-void radeonFinish(GLcontext * ctx)
-{
- radeonContextPtr radeon = RADEON_CONTEXT(ctx);
-
- radeonFlush(ctx);
-
- if (radeon->do_irqs) {
- LOCK_HARDWARE(radeon);
- radeonEmitIrqLocked(radeon);
- UNLOCK_HARDWARE(radeon);
- radeonWaitIrq(radeon);
- } else
- radeonWaitForIdle(radeon);
-}
diff --git a/src/mesa/drivers/dri/r300/radeon_ioctl.h b/src/mesa/drivers/dri/r300/radeon_ioctl.h
deleted file mode 100644
index 3add775b82..0000000000
--- a/src/mesa/drivers/dri/r300/radeon_ioctl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#ifndef __RADEON_IOCTL_H__
-#define __RADEON_IOCTL_H__
-
-#include "main/simple_list.h"
-#include "radeon_dri.h"
-#include "radeon_lock.h"
-
-#include "xf86drm.h"
-#include "drm.h"
-#if 0
-#include "r200context.h"
-#endif
-#include "radeon_drm.h"
-
-extern void radeonCopyBuffer(__DRIdrawablePrivate * drawable,
- const drm_clip_rect_t * rect);
-extern void radeonPageFlip(__DRIdrawablePrivate * drawable);
-extern void radeonFlush(GLcontext * ctx);
-extern void radeonFinish(GLcontext * ctx);
-extern void radeonWaitForIdleLocked(radeonContextPtr radeon);
-extern uint32_t radeonGetAge(radeonContextPtr radeon);
-
-#endif /* __RADEON_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/r300/radeon_lock.c b/src/mesa/drivers/dri/r300/radeon_lock.c
index 4f47afd5dc..af4108a8e3 100644..120000
--- a/src/mesa/drivers/dri/r300/radeon_lock.c
+++ b/src/mesa/drivers/dri/r300/radeon_lock.c
@@ -1,137 +1 @@
-/**************************************************************************
-
-Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
- VA Linux Systems Inc., Fremont, California.
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Gareth Hughes <gareth@valinux.com>
- * Keith Whitwell <keith@tungstengraphics.com>
- * Kevin E. Martin <martin@valinux.com>
- */
-
-#include "radeon_lock.h"
-#include "radeon_ioctl.h"
-#include "radeon_state.h"
-#include "r300_context.h"
-#include "r300_state.h"
-
-#include "main/framebuffer.h"
-
-#include "drirenderbuffer.h"
-
-#if DEBUG_LOCKING
-char *prevLockFile = NULL;
-int prevLockLine = 0;
-#endif
-
-/* Turn on/off page flipping according to the flags in the sarea:
- */
-void radeonUpdatePageFlipping(radeonContextPtr rmesa)
-{
- int use_back;
-
- rmesa->doPageFlip = rmesa->sarea->pfState;
- if (rmesa->glCtx->WinSysDrawBuffer) {
- driFlipRenderbuffers(rmesa->glCtx->WinSysDrawBuffer,
- rmesa->sarea->pfCurrentPage);
- r300UpdateDrawBuffer(rmesa->glCtx);
- }
-
- use_back = rmesa->glCtx->DrawBuffer ?
- (rmesa->glCtx->DrawBuffer->_ColorDrawBufferIndexes[0] ==
- BUFFER_BACK_LEFT) : 1;
- use_back ^= (rmesa->sarea->pfCurrentPage == 1);
-
- if (use_back) {
- rmesa->state.color.drawOffset =
- rmesa->radeonScreen->backOffset;
- rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
- } else {
- rmesa->state.color.drawOffset =
- rmesa->radeonScreen->frontOffset;
- rmesa->state.color.drawPitch =
- rmesa->radeonScreen->frontPitch;
- }
-}
-
-/* Update the hardware state. This is called if another context has
- * grabbed the hardware lock, which includes the X server. This
- * function also updates the driver's window state after the X server
- * moves, resizes or restacks a window -- the change will be reflected
- * in the drawable position and clip rects. Since the X server grabs
- * the hardware lock when it changes the window state, this routine will
- * automatically be called after such a change.
- */
-void radeonGetLock(radeonContextPtr rmesa, GLuint flags)
-{
- __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
- __DRIdrawablePrivate *const readable = rmesa->dri.readable;
- __DRIscreenPrivate *sPriv = rmesa->dri.screen;
- drm_radeon_sarea_t *sarea = rmesa->sarea;
- r300ContextPtr r300 = (r300ContextPtr) rmesa;
-
- assert(drawable != NULL);
-
- drmGetLock(rmesa->dri.fd, rmesa->dri.hwContext, flags);
-
- /* The window might have moved, so we might need to get new clip
- * rects.
- *
- * NOTE: This releases and regrabs the hw lock to allow the X server
- * to respond to the DRI protocol request for new drawable info.
- * Since the hardware state depends on having the latest drawable
- * clip rects, all state checking must be done _after_ this call.
- */
- DRI_VALIDATE_DRAWABLE_INFO(sPriv, drawable);
- if (drawable != readable) {
- DRI_VALIDATE_DRAWABLE_INFO(sPriv, readable);
- }
-
- if (rmesa->lastStamp != drawable->lastStamp) {
- radeonUpdatePageFlipping(rmesa);
- radeonSetCliprects(rmesa);
- r300UpdateViewportOffset(rmesa->glCtx);
- driUpdateFramebufferSize(rmesa->glCtx, drawable);
- }
-
- if (sarea->ctx_owner != rmesa->dri.hwContext) {
- int i;
-
- sarea->ctx_owner = rmesa->dri.hwContext;
- for (i = 0; i < r300->nr_heaps; i++) {
- DRI_AGE_TEXTURES(r300->texture_heaps[i]);
- }
- }
-
- rmesa->lost_context = GL_TRUE;
-}
+../radeon/radeon_lock.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_lock.h b/src/mesa/drivers/dri/r300/radeon_lock.h
index a344837f47..64bdf94ee7 100644..120000
--- a/src/mesa/drivers/dri/r300/radeon_lock.h
+++ b/src/mesa/drivers/dri/r300/radeon_lock.h
@@ -1,115 +1 @@
-/**************************************************************************
-
-Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
- VA Linux Systems Inc., Fremont, California.
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Gareth Hughes <gareth@valinux.com>
- * Keith Whitwell <keith@tungstengraphics.com>
- * Kevin E. Martin <martin@valinux.com>
- */
-
-#ifndef __RADEON_LOCK_H__
-#define __RADEON_LOCK_H__
-
-#include "radeon_context.h"
-
-extern void radeonGetLock(radeonContextPtr rmesa, GLuint flags);
-extern void radeonUpdatePageFlipping(radeonContextPtr rmesa);
-
-/* Turn DEBUG_LOCKING on to find locking conflicts.
- */
-#define DEBUG_LOCKING 0
-
-#if DEBUG_LOCKING
-extern char *prevLockFile;
-extern int prevLockLine;
-
-#define DEBUG_LOCK() \
- do { \
- prevLockFile = (__FILE__); \
- prevLockLine = (__LINE__); \
- } while (0)
-
-#define DEBUG_RESET() \
- do { \
- prevLockFile = 0; \
- prevLockLine = 0; \
- } while (0)
-
-#define DEBUG_CHECK_LOCK() \
- do { \
- if (prevLockFile) { \
- fprintf(stderr, \
- "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
- prevLockFile, prevLockLine, __FILE__, __LINE__); \
- exit(1); \
- } \
- } while (0)
-
-#else
-
-#define DEBUG_LOCK()
-#define DEBUG_RESET()
-#define DEBUG_CHECK_LOCK()
-
-#endif
-
-/*
- * !!! We may want to separate locks from locks with validation. This
- * could be used to improve performance for those things commands that
- * do not do any drawing !!!
- */
-
-/* Lock the hardware and validate our state.
- */
-#define LOCK_HARDWARE( rmesa ) \
- do { \
- char __ret = 0; \
- DEBUG_CHECK_LOCK(); \
- DRM_CAS((rmesa)->dri.hwLock, (rmesa)->dri.hwContext, \
- (DRM_LOCK_HELD | (rmesa)->dri.hwContext), __ret); \
- if (__ret) \
- radeonGetLock((rmesa), 0); \
- DEBUG_LOCK(); \
- } while (0)
-
-#define UNLOCK_HARDWARE( rmesa ) \
- do { \
- DRM_UNLOCK((rmesa)->dri.fd, \
- (rmesa)->dri.hwLock, \
- (rmesa)->dri.hwContext); \
- DEBUG_RESET(); \
- } while (0)
-
-#endif /* __RADEON_LOCK_H__ */
+../radeon/radeon_lock.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_mipmap_tree.c b/src/mesa/drivers/dri/r300/radeon_mipmap_tree.c
new file mode 120000
index 0000000000..31c0cfbe94
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_mipmap_tree.c
@@ -0,0 +1 @@
+../radeon/radeon_mipmap_tree.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_mipmap_tree.h b/src/mesa/drivers/dri/r300/radeon_mipmap_tree.h
new file mode 120000
index 0000000000..254d50cf8c
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_mipmap_tree.h
@@ -0,0 +1 @@
+../radeon/radeon_mipmap_tree.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_program.c b/src/mesa/drivers/dri/r300/radeon_program.c
deleted file mode 100644
index da5e7aefce..0000000000
--- a/src/mesa/drivers/dri/r300/radeon_program.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2008 Nicolai Haehnle.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "radeon_program.h"
-
-#include "shader/prog_print.h"
-
-
-/**
- * Transform the given clause in the following way:
- * 1. Replace it with an empty clause
- * 2. For every instruction in the original clause, try the given
- * transformations in order.
- * 3. If one of the transformations returns GL_TRUE, assume that it
- * has emitted the appropriate instruction(s) into the new clause;
- * otherwise, copy the instruction verbatim.
- *
- * \note The transformation is currently not recursive; in other words,
- * instructions emitted by transformations are not transformed.
- *
- * \note The transform is called 'local' because it can only look at
- * one instruction at a time.
- */
-void radeonLocalTransform(
- GLcontext *Ctx,
- struct gl_program *program,
- int num_transformations,
- struct radeon_program_transformation* transformations)
-{
- struct radeon_transform_context ctx;
- int ip;
-
- ctx.Ctx = Ctx;
- ctx.Program = program;
- ctx.OldInstructions = program->Instructions;
- ctx.OldNumInstructions = program->NumInstructions;
-
- program->Instructions = 0;
- program->NumInstructions = 0;
-
- for(ip = 0; ip < ctx.OldNumInstructions; ++ip) {
- struct prog_instruction *instr = ctx.OldInstructions + ip;
- int i;
-
- for(i = 0; i < num_transformations; ++i) {
- struct radeon_program_transformation* t = transformations + i;
-
- if (t->function(&ctx, instr, t->userData))
- break;
- }
-
- if (i >= num_transformations) {
- struct prog_instruction* dest = radeonAppendInstructions(program, 1);
- _mesa_copy_instructions(dest, instr, 1);
- }
- }
-
- _mesa_free_instructions(ctx.OldInstructions, ctx.OldNumInstructions);
-}
-
-
-static void scan_instructions(GLboolean* used, const struct prog_instruction* insts, GLuint count)
-{
- GLuint i;
- for (i = 0; i < count; i++) {
- const struct prog_instruction *inst = insts + i;
- const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
- GLuint k;
-
- for (k = 0; k < n; k++) {
- if (inst->SrcReg[k].File == PROGRAM_TEMPORARY)
- used[inst->SrcReg[k].Index] = GL_TRUE;
- }
- }
-}
-
-GLint radeonFindFreeTemporary(struct radeon_transform_context *t)
-{
- GLboolean used[MAX_PROGRAM_TEMPS];
- GLuint i;
-
- _mesa_memset(used, 0, sizeof(used));
- scan_instructions(used, t->Program->Instructions, t->Program->NumInstructions);
- scan_instructions(used, t->OldInstructions, t->OldNumInstructions);
-
- for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
- if (!used[i])
- return i;
- }
-
- return -1;
-}
-
-
-/**
- * Append the given number of instructions to the program and return a
- * pointer to the first new instruction.
- */
-struct prog_instruction *radeonAppendInstructions(struct gl_program *program, int count)
-{
- int oldnum = program->NumInstructions;
- _mesa_insert_instructions(program, oldnum, count);
- return program->Instructions + oldnum;
-}
diff --git a/src/mesa/drivers/dri/r300/radeon_program_alu.c b/src/mesa/drivers/dri/r300/radeon_program_alu.c
deleted file mode 100644
index 1ef71e74dc..0000000000
--- a/src/mesa/drivers/dri/r300/radeon_program_alu.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright (C) 2008 Nicolai Haehnle.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-/**
- * @file
- *
- * Shareable transformations that transform "special" ALU instructions
- * into ALU instructions that are supported by hardware.
- *
- */
-
-#include "radeon_program_alu.h"
-
-#include "shader/prog_parameter.h"
-
-
-static struct prog_instruction *emit1(struct gl_program* p,
- gl_inst_opcode Opcode, GLuint Saturate, struct prog_dst_register DstReg,
- struct prog_src_register SrcReg)
-{
- struct prog_instruction *fpi = radeonAppendInstructions(p, 1);
-
- fpi->Opcode = Opcode;
- fpi->SaturateMode = Saturate;
- fpi->DstReg = DstReg;
- fpi->SrcReg[0] = SrcReg;
- return fpi;
-}
-
-static struct prog_instruction *emit2(struct gl_program* p,
- gl_inst_opcode Opcode, GLuint Saturate, struct prog_dst_register DstReg,
- struct prog_src_register SrcReg0, struct prog_src_register SrcReg1)
-{
- struct prog_instruction *fpi = radeonAppendInstructions(p, 1);
-
- fpi->Opcode = Opcode;
- fpi->SaturateMode = Saturate;
- fpi->DstReg = DstReg;
- fpi->SrcReg[0] = SrcReg0;
- fpi->SrcReg[1] = SrcReg1;
- return fpi;
-}
-
-static struct prog_instruction *emit3(struct gl_program* p,
- gl_inst_opcode Opcode, GLuint Saturate, struct prog_dst_register DstReg,
- struct prog_src_register SrcReg0, struct prog_src_register SrcReg1,
- struct prog_src_register SrcReg2)
-{
- struct prog_instruction *fpi = radeonAppendInstructions(p, 1);
-
- fpi->Opcode = Opcode;
- fpi->SaturateMode = Saturate;
- fpi->DstReg = DstReg;
- fpi->SrcReg[0] = SrcReg0;
- fpi->SrcReg[1] = SrcReg1;
- fpi->SrcReg[2] = SrcReg2;
- return fpi;
-}
-
-static void set_swizzle(struct prog_src_register *SrcReg, int coordinate, int swz)
-{
- SrcReg->Swizzle &= ~(7 << (3*coordinate));
- SrcReg->Swizzle |= swz << (3*coordinate);
-}
-
-static void set_negate_base(struct prog_src_register *SrcReg, int coordinate, int negate)
-{
- SrcReg->NegateBase &= ~(1 << coordinate);
- SrcReg->NegateBase |= (negate << coordinate);
-}
-
-static struct prog_dst_register dstreg(int file, int index)
-{
- struct prog_dst_register dst;
- dst.File = file;
- dst.Index = index;
- dst.WriteMask = WRITEMASK_XYZW;
- dst.CondMask = COND_TR;
- dst.CondSwizzle = SWIZZLE_NOOP;
- dst.CondSrc = 0;
- dst.pad = 0;
- return dst;
-}
-
-static struct prog_dst_register dstregtmpmask(int index, int mask)
-{
- struct prog_dst_register dst;
- dst.File = PROGRAM_TEMPORARY;
- dst.Index = index;
- dst.WriteMask = mask;
- dst.CondMask = COND_TR;
- dst.CondSwizzle = SWIZZLE_NOOP;
- dst.CondSrc = 0;
- dst.pad = 0;
- return dst;
-}
-
-static const struct prog_src_register builtin_zero = {
- .File = PROGRAM_BUILTIN,
- .Index = 0,
- .Swizzle = SWIZZLE_0000
-};
-static const struct prog_src_register builtin_one = {
- .File = PROGRAM_BUILTIN,
- .Index = 0,
- .Swizzle = SWIZZLE_1111
-};
-static const struct prog_src_register srcreg_undefined = {
- .File = PROGRAM_UNDEFINED,
- .Index = 0,
- .Swizzle = SWIZZLE_NOOP
-};
-
-static struct prog_src_register srcreg(int file, int index)
-{
- struct prog_src_register src = srcreg_undefined;
- src.File = file;
- src.Index = index;
- return src;
-}
-
-static struct prog_src_register srcregswz(int file, int index, int swz)
-{
- struct prog_src_register src = srcreg_undefined;
- src.File = file;
- src.Index = index;
- src.Swizzle = swz;
- return src;
-}
-
-static struct prog_src_register absolute(struct prog_src_register reg)
-{
- struct prog_src_register newreg = reg;
- newreg.Abs = 1;
- newreg.NegateBase = 0;
- newreg.NegateAbs = 0;
- return newreg;
-}
-
-static struct prog_src_register negate(struct prog_src_register reg)
-{
- struct prog_src_register newreg = reg;
- newreg.NegateAbs = !newreg.NegateAbs;
- return newreg;
-}
-
-static struct prog_src_register swizzle(struct prog_src_register reg, GLuint x, GLuint y, GLuint z, GLuint w)
-{
- struct prog_src_register swizzled = reg;
- swizzled.Swizzle = MAKE_SWIZZLE4(
- x >= 4 ? x : GET_SWZ(reg.Swizzle, x),
- y >= 4 ? y : GET_SWZ(reg.Swizzle, y),
- z >= 4 ? z : GET_SWZ(reg.Swizzle, z),
- w >= 4 ? w : GET_SWZ(reg.Swizzle, w));
- return swizzled;
-}
-
-static struct prog_src_register scalar(struct prog_src_register reg)
-{
- return swizzle(reg, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
-}
-
-static void transform_ABS(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- struct prog_src_register src = inst->SrcReg[0];
- src.Abs = 1;
- src.NegateBase = 0;
- src.NegateAbs = 0;
- emit1(t->Program, OPCODE_MOV, inst->SaturateMode, inst->DstReg, src);
-}
-
-static void transform_DPH(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- struct prog_src_register src0 = inst->SrcReg[0];
- if (src0.NegateAbs) {
- if (src0.Abs) {
- int tempreg = radeonFindFreeTemporary(t);
- emit1(t->Program, OPCODE_MOV, 0, dstreg(PROGRAM_TEMPORARY, tempreg), src0);
- src0 = srcreg(src0.File, src0.Index);
- } else {
- src0.NegateAbs = 0;
- src0.NegateBase ^= NEGATE_XYZW;
- }
- }
- set_swizzle(&src0, 3, SWIZZLE_ONE);
- set_negate_base(&src0, 3, 0);
- emit2(t->Program, OPCODE_DP4, inst->SaturateMode, inst->DstReg, src0, inst->SrcReg[1]);
-}
-
-/**
- * [1, src0.y*src1.y, src0.z, src1.w]
- * So basically MUL with lotsa swizzling.
- */
-static void transform_DST(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- emit2(t->Program, OPCODE_MUL, inst->SaturateMode, inst->DstReg,
- swizzle(inst->SrcReg[0], SWIZZLE_ONE, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE),
- swizzle(inst->SrcReg[1], SWIZZLE_ONE, SWIZZLE_Y, SWIZZLE_ONE, SWIZZLE_W));
-}
-
-static void transform_FLR(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- int tempreg = radeonFindFreeTemporary(t);
- emit1(t->Program, OPCODE_FRC, 0, dstreg(PROGRAM_TEMPORARY, tempreg), inst->SrcReg[0]);
- emit2(t->Program, OPCODE_ADD, inst->SaturateMode, inst->DstReg,
- inst->SrcReg[0], negate(srcreg(PROGRAM_TEMPORARY, tempreg)));
-}
-
-/**
- * Definition of LIT (from ARB_fragment_program):
- *
- * tmp = VectorLoad(op0);
- * if (tmp.x < 0) tmp.x = 0;
- * if (tmp.y < 0) tmp.y = 0;
- * if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
- * else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
- * result.x = 1.0;
- * result.y = tmp.x;
- * result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
- * result.w = 1.0;
- *
- * The longest path of computation is the one leading to result.z,
- * consisting of 5 operations. This implementation of LIT takes
- * 5 slots, if the subsequent optimization passes are clever enough
- * to pair instructions correctly.
- */
-static void transform_LIT(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- static const GLfloat LitConst[4] = { -127.999999 };
-
- GLuint constant;
- GLuint constant_swizzle;
- GLuint temp;
- int needTemporary = 0;
- struct prog_src_register srctemp;
-
- constant = _mesa_add_unnamed_constant(t->Program->Parameters, LitConst, 1, &constant_swizzle);
-
- if (inst->DstReg.WriteMask != WRITEMASK_XYZW) {
- needTemporary = 1;
- } else if (inst->DstReg.File != PROGRAM_TEMPORARY) {
- // LIT is typically followed by DP3/DP4, so there's no point
- // in creating special code for this case
- needTemporary = 1;
- }
-
- if (needTemporary) {
- temp = radeonFindFreeTemporary(t);
- } else {
- temp = inst->DstReg.Index;
- }
- srctemp = srcreg(PROGRAM_TEMPORARY, temp);
-
- // tmp.x = max(0.0, Src.x);
- // tmp.y = max(0.0, Src.y);
- // tmp.w = clamp(Src.z, -128+eps, 128-eps);
- emit2(t->Program, OPCODE_MAX, 0,
- dstregtmpmask(temp, WRITEMASK_XYW),
- inst->SrcReg[0],
- swizzle(srcreg(PROGRAM_CONSTANT, constant),
- SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO, constant_swizzle&3));
- emit2(t->Program, OPCODE_MIN, 0,
- dstregtmpmask(temp, WRITEMASK_Z),
- swizzle(srctemp, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- negate(srcregswz(PROGRAM_CONSTANT, constant, constant_swizzle)));
-
- // tmp.w = Pow(tmp.y, tmp.w)
- emit1(t->Program, OPCODE_LG2, 0,
- dstregtmpmask(temp, WRITEMASK_W),
- swizzle(srctemp, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y));
- emit2(t->Program, OPCODE_MUL, 0,
- dstregtmpmask(temp, WRITEMASK_W),
- swizzle(srctemp, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- swizzle(srctemp, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z));
- emit1(t->Program, OPCODE_EX2, 0,
- dstregtmpmask(temp, WRITEMASK_W),
- swizzle(srctemp, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W));
-
- // tmp.z = (tmp.x > 0) ? tmp.w : 0.0
- emit3(t->Program, OPCODE_CMP, inst->SaturateMode,
- dstregtmpmask(temp, WRITEMASK_Z),
- negate(swizzle(srctemp, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)),
- swizzle(srctemp, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- builtin_zero);
-
- // tmp.x, tmp.y, tmp.w = 1.0, tmp.x, 1.0
- emit1(t->Program, OPCODE_MOV, inst->SaturateMode,
- dstregtmpmask(temp, WRITEMASK_XYW),
- swizzle(srctemp, SWIZZLE_ONE, SWIZZLE_X, SWIZZLE_ONE, SWIZZLE_ONE));
-
- if (needTemporary)
- emit1(t->Program, OPCODE_MOV, 0, inst->DstReg, srctemp);
-}
-
-static void transform_LRP(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- int tempreg = radeonFindFreeTemporary(t);
-
- emit2(t->Program, OPCODE_ADD, 0,
- dstreg(PROGRAM_TEMPORARY, tempreg),
- inst->SrcReg[1], negate(inst->SrcReg[2]));
- emit3(t->Program, OPCODE_MAD, inst->SaturateMode,
- inst->DstReg,
- inst->SrcReg[0], srcreg(PROGRAM_TEMPORARY, tempreg), inst->SrcReg[2]);
-}
-
-static void transform_POW(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- int tempreg = radeonFindFreeTemporary(t);
- struct prog_dst_register tempdst = dstreg(PROGRAM_TEMPORARY, tempreg);
- struct prog_src_register tempsrc = srcreg(PROGRAM_TEMPORARY, tempreg);
- tempdst.WriteMask = WRITEMASK_W;
- tempsrc.Swizzle = SWIZZLE_WWWW;
-
- emit1(t->Program, OPCODE_LG2, 0, tempdst, scalar(inst->SrcReg[0]));
- emit2(t->Program, OPCODE_MUL, 0, tempdst, tempsrc, scalar(inst->SrcReg[1]));
- emit1(t->Program, OPCODE_EX2, inst->SaturateMode, inst->DstReg, tempsrc);
-}
-
-static void transform_RSQ(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- emit1(t->Program, OPCODE_RSQ, inst->SaturateMode, inst->DstReg, absolute(inst->SrcReg[0]));
-}
-
-static void transform_SGE(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- int tempreg = radeonFindFreeTemporary(t);
-
- emit2(t->Program, OPCODE_ADD, 0, dstreg(PROGRAM_TEMPORARY, tempreg), inst->SrcReg[0], negate(inst->SrcReg[1]));
- emit3(t->Program, OPCODE_CMP, inst->SaturateMode, inst->DstReg,
- srcreg(PROGRAM_TEMPORARY, tempreg), builtin_zero, builtin_one);
-}
-
-static void transform_SLT(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- int tempreg = radeonFindFreeTemporary(t);
-
- emit2(t->Program, OPCODE_ADD, 0, dstreg(PROGRAM_TEMPORARY, tempreg), inst->SrcReg[0], negate(inst->SrcReg[1]));
- emit3(t->Program, OPCODE_CMP, inst->SaturateMode, inst->DstReg,
- srcreg(PROGRAM_TEMPORARY, tempreg), builtin_one, builtin_zero);
-}
-
-static void transform_SUB(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- emit2(t->Program, OPCODE_ADD, inst->SaturateMode, inst->DstReg, inst->SrcReg[0], negate(inst->SrcReg[1]));
-}
-
-static void transform_SWZ(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- emit1(t->Program, OPCODE_MOV, inst->SaturateMode, inst->DstReg, inst->SrcReg[0]);
-}
-
-static void transform_XPD(struct radeon_transform_context* t,
- struct prog_instruction* inst)
-{
- int tempreg = radeonFindFreeTemporary(t);
-
- emit2(t->Program, OPCODE_MUL, 0, dstreg(PROGRAM_TEMPORARY, tempreg),
- swizzle(inst->SrcReg[0], SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, SWIZZLE_W),
- swizzle(inst->SrcReg[1], SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, SWIZZLE_W));
- emit3(t->Program, OPCODE_MAD, inst->SaturateMode, inst->DstReg,
- swizzle(inst->SrcReg[0], SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, SWIZZLE_W),
- swizzle(inst->SrcReg[1], SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, SWIZZLE_W),
- negate(srcreg(PROGRAM_TEMPORARY, tempreg)));
-}
-
-
-/**
- * Can be used as a transformation for @ref radeonClauseLocalTransform,
- * no userData necessary.
- *
- * Eliminates the following ALU instructions:
- * ABS, DPH, DST, FLR, LIT, LRP, POW, SGE, SLT, SUB, SWZ, XPD
- * using:
- * MOV, ADD, MUL, MAD, FRC, DP3, LG2, EX2, CMP
- *
- * Transforms RSQ to Radeon's native RSQ by explicitly setting
- * absolute value.
- *
- * @note should be applicable to R300 and R500 fragment programs.
- */
-GLboolean radeonTransformALU(struct radeon_transform_context* t,
- struct prog_instruction* inst,
- void* unused)
-{
- switch(inst->Opcode) {
- case OPCODE_ABS: transform_ABS(t, inst); return GL_TRUE;
- case OPCODE_DPH: transform_DPH(t, inst); return GL_TRUE;
- case OPCODE_DST: transform_DST(t, inst); return GL_TRUE;
- case OPCODE_FLR: transform_FLR(t, inst); return GL_TRUE;
- case OPCODE_LIT: transform_LIT(t, inst); return GL_TRUE;
- case OPCODE_LRP: transform_LRP(t, inst); return GL_TRUE;
- case OPCODE_POW: transform_POW(t, inst); return GL_TRUE;
- case OPCODE_RSQ: transform_RSQ(t, inst); return GL_TRUE;
- case OPCODE_SGE: transform_SGE(t, inst); return GL_TRUE;
- case OPCODE_SLT: transform_SLT(t, inst); return GL_TRUE;
- case OPCODE_SUB: transform_SUB(t, inst); return GL_TRUE;
- case OPCODE_SWZ: transform_SWZ(t, inst); return GL_TRUE;
- case OPCODE_XPD: transform_XPD(t, inst); return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-static void sincos_constants(struct radeon_transform_context* t, GLuint *constants)
-{
- static const GLfloat SinCosConsts[2][4] = {
- {
- 1.273239545, // 4/PI
- -0.405284735, // -4/(PI*PI)
- 3.141592654, // PI
- 0.2225 // weight
- },
- {
- 0.75,
- 0.5,
- 0.159154943, // 1/(2*PI)
- 6.283185307 // 2*PI
- }
- };
- int i;
-
- for(i = 0; i < 2; ++i) {
- GLuint swz;
- constants[i] = _mesa_add_unnamed_constant(t->Program->Parameters, SinCosConsts[i], 4, &swz);
- ASSERT(swz == SWIZZLE_NOOP);
- }
-}
-
-/**
- * Approximate sin(x), where x is clamped to (-pi/2, pi/2).
- *
- * MUL tmp.xy, src, { 4/PI, -4/(PI^2) }
- * MAD tmp.x, tmp.y, |src|, tmp.x
- * MAD tmp.y, tmp.x, |tmp.x|, -tmp.x
- * MAD dest, tmp.y, weight, tmp.x
- */
-static void sin_approx(struct radeon_transform_context* t,
- struct prog_dst_register dst, struct prog_src_register src, const GLuint* constants)
-{
- GLuint tempreg = radeonFindFreeTemporary(t);
-
- emit2(t->Program, OPCODE_MUL, 0, dstregtmpmask(tempreg, WRITEMASK_XY),
- swizzle(src, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
- srcreg(PROGRAM_CONSTANT, constants[0]));
- emit3(t->Program, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_X),
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
- absolute(swizzle(src, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)),
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X));
- emit3(t->Program, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_Y),
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
- absolute(swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)),
- negate(swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)));
- emit3(t->Program, OPCODE_MAD, 0, dst,
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[0]), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X));
-}
-
-/**
- * Translate the trigonometric functions COS, SIN, and SCS
- * using only the basic instructions
- * MOV, ADD, MUL, MAD, FRC
- */
-GLboolean radeonTransformTrigSimple(struct radeon_transform_context* t,
- struct prog_instruction* inst,
- void* unused)
-{
- if (inst->Opcode != OPCODE_COS &&
- inst->Opcode != OPCODE_SIN &&
- inst->Opcode != OPCODE_SCS)
- return GL_FALSE;
-
- GLuint constants[2];
- GLuint tempreg = radeonFindFreeTemporary(t);
-
- sincos_constants(t, constants);
-
- if (inst->Opcode == OPCODE_COS) {
- // MAD tmp.x, src, 1/(2*PI), 0.75
- // FRC tmp.x, tmp.x
- // MAD tmp.z, tmp.x, 2*PI, -PI
- emit3(t->Program, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_W),
- swizzle(inst->SrcReg[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X));
- emit1(t->Program, OPCODE_FRC, 0, dstregtmpmask(tempreg, WRITEMASK_W),
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W));
- emit3(t->Program, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_W),
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- negate(swizzle(srcreg(PROGRAM_CONSTANT, constants[0]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z)));
-
- sin_approx(t, inst->DstReg,
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- constants);
- } else if (inst->Opcode == OPCODE_SIN) {
- emit3(t->Program, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_W),
- swizzle(inst->SrcReg[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y));
- emit1(t->Program, OPCODE_FRC, 0, dstregtmpmask(tempreg, WRITEMASK_W),
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W));
- emit3(t->Program, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_W),
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- negate(swizzle(srcreg(PROGRAM_CONSTANT, constants[0]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z)));
-
- sin_approx(t, inst->DstReg,
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- constants);
- } else {
- emit3(t->Program, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_XY),
- swizzle(inst->SrcReg[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W));
- emit1(t->Program, OPCODE_FRC, 0, dstregtmpmask(tempreg, WRITEMASK_XY),
- srcreg(PROGRAM_TEMPORARY, tempreg));
- emit3(t->Program, OPCODE_MAD, 0, dstregtmpmask(tempreg, WRITEMASK_XY),
- srcreg(PROGRAM_TEMPORARY, tempreg),
- swizzle(srcreg(PROGRAM_CONSTANT, constants[1]), SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W),
- negate(swizzle(srcreg(PROGRAM_CONSTANT, constants[0]), SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z)));
-
- struct prog_dst_register dst = inst->DstReg;
-
- dst.WriteMask = inst->DstReg.WriteMask & WRITEMASK_X;
- sin_approx(t, dst,
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
- constants);
-
- dst.WriteMask = inst->DstReg.WriteMask & WRITEMASK_Y;
- sin_approx(t, dst,
- swizzle(srcreg(PROGRAM_TEMPORARY, tempreg), SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
- constants);
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Transform the trigonometric functions COS, SIN, and SCS
- * to include pre-scaling by 1/(2*PI) and taking the fractional
- * part, so that the input to COS and SIN is always in the range [0,1).
- * SCS is replaced by one COS and one SIN instruction.
- *
- * @warning This transformation implicitly changes the semantics of SIN and COS!
- */
-GLboolean radeonTransformTrigScale(struct radeon_transform_context* t,
- struct prog_instruction* inst,
- void* unused)
-{
- if (inst->Opcode != OPCODE_COS &&
- inst->Opcode != OPCODE_SIN &&
- inst->Opcode != OPCODE_SCS)
- return GL_FALSE;
-
- static const GLfloat RCP_2PI[] = { 0.15915494309189535 };
- GLuint temp;
- GLuint constant;
- GLuint constant_swizzle;
-
- temp = radeonFindFreeTemporary(t);
- constant = _mesa_add_unnamed_constant(t->Program->Parameters, RCP_2PI, 1, &constant_swizzle);
-
- emit2(t->Program, OPCODE_MUL, 0, dstregtmpmask(temp, WRITEMASK_W),
- swizzle(inst->SrcReg[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
- srcregswz(PROGRAM_CONSTANT, constant, constant_swizzle));
- emit1(t->Program, OPCODE_FRC, 0, dstregtmpmask(temp, WRITEMASK_W),
- srcreg(PROGRAM_TEMPORARY, temp));
-
- if (inst->Opcode == OPCODE_COS) {
- emit1(t->Program, OPCODE_COS, inst->SaturateMode, inst->DstReg,
- srcregswz(PROGRAM_TEMPORARY, temp, SWIZZLE_WWWW));
- } else if (inst->Opcode == OPCODE_SIN) {
- emit1(t->Program, OPCODE_SIN, inst->SaturateMode,
- inst->DstReg, srcregswz(PROGRAM_TEMPORARY, temp, SWIZZLE_WWWW));
- } else if (inst->Opcode == OPCODE_SCS) {
- struct prog_dst_register moddst = inst->DstReg;
-
- if (inst->DstReg.WriteMask & WRITEMASK_X) {
- moddst.WriteMask = WRITEMASK_X;
- emit1(t->Program, OPCODE_COS, inst->SaturateMode, moddst,
- srcregswz(PROGRAM_TEMPORARY, temp, SWIZZLE_WWWW));
- }
- if (inst->DstReg.WriteMask & WRITEMASK_Y) {
- moddst.WriteMask = WRITEMASK_Y;
- emit1(t->Program, OPCODE_SIN, inst->SaturateMode, moddst,
- srcregswz(PROGRAM_TEMPORARY, temp, SWIZZLE_WWWW));
- }
- }
-
- return GL_TRUE;
-}
-
-/**
- * Rewrite DDX/DDY instructions to properly work with r5xx shaders.
- * The r5xx MDH/MDV instruction provides per-quad partial derivatives.
- * It takes the form A*B+C. A and C are set by setting src0. B should be -1.
- *
- * @warning This explicitly changes the form of DDX and DDY!
- */
-
-GLboolean radeonTransformDeriv(struct radeon_transform_context* t,
- struct prog_instruction* inst,
- void* unused)
-{
- if (inst->Opcode != OPCODE_DDX && inst->Opcode != OPCODE_DDY)
- return GL_FALSE;
-
- struct prog_src_register B = inst->SrcReg[1];
-
- B.Swizzle = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE,
- SWIZZLE_ONE, SWIZZLE_ONE);
- B.NegateBase = NEGATE_XYZW;
-
- emit2(t->Program, inst->Opcode, inst->SaturateMode, inst->DstReg,
- inst->SrcReg[0], B);
-
- return GL_TRUE;
-}
diff --git a/src/mesa/drivers/dri/r300/radeon_queryobj.c b/src/mesa/drivers/dri/r300/radeon_queryobj.c
new file mode 120000
index 0000000000..1d6ebc1c48
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_queryobj.c
@@ -0,0 +1 @@
+../radeon/radeon_queryobj.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_queryobj.h b/src/mesa/drivers/dri/r300/radeon_queryobj.h
new file mode 120000
index 0000000000..8f6f842b0a
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_queryobj.h
@@ -0,0 +1 @@
+../radeon/radeon_queryobj.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_screen.c b/src/mesa/drivers/dri/r300/radeon_screen.c
new file mode 120000
index 0000000000..86161118dd
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_screen.c
@@ -0,0 +1 @@
+../radeon/radeon_screen.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_screen.h b/src/mesa/drivers/dri/r300/radeon_screen.h
new file mode 120000
index 0000000000..23bb6bd459
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_screen.h
@@ -0,0 +1 @@
+../radeon/radeon_screen.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_span.c b/src/mesa/drivers/dri/r300/radeon_span.c
index 16f9fb99e6..232868c4c9 100644..120000
--- a/src/mesa/drivers/dri/r300/radeon_span.c
+++ b/src/mesa/drivers/dri/r300/radeon_span.c
@@ -1,349 +1 @@
-/**************************************************************************
-
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
- VA Linux Systems Inc., Fremont, California.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Kevin E. Martin <martin@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- * Keith Whitwell <keith@tungstengraphics.com>
- *
- */
-
-#include "main/glheader.h"
-#include "swrast/swrast.h"
-
-#include "r300_state.h"
-#include "radeon_ioctl.h"
-#include "r300_ioctl.h"
-#include "radeon_span.h"
-
-#include "drirenderbuffer.h"
-
-#define DBG 0
-
-/*
- * Note that all information needed to access pixels in a renderbuffer
- * should be obtained through the gl_renderbuffer parameter, not per-context
- * information.
- */
-#define LOCAL_VARS \
- driRenderbuffer *drb = (driRenderbuffer *) rb; \
- const __DRIdrawablePrivate *dPriv = drb->dPriv; \
- const GLuint bottom = dPriv->h - 1; \
- GLubyte *buf = (GLubyte *) drb->flippedData \
- + (dPriv->y * drb->flippedPitch + dPriv->x) * drb->cpp; \
- GLuint p; \
- (void) p;
-
-#define LOCAL_DEPTH_VARS \
- driRenderbuffer *drb = (driRenderbuffer *) rb; \
- const __DRIdrawablePrivate *dPriv = drb->dPriv; \
- const GLuint bottom = dPriv->h - 1; \
- GLuint xo = dPriv->x; \
- GLuint yo = dPriv->y; \
- GLubyte *buf = (GLubyte *) drb->Base.Data;
-
-#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
-
-#define Y_FLIP(Y) (bottom - (Y))
-
-#define HW_LOCK()
-
-#define HW_UNLOCK()
-
-/* ================================================================
- * Color buffer
- */
-
-/* 16 bit, RGB565 color spanline and pixel functions
- */
-#define SPANTMP_PIXEL_FMT GL_RGB
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
-
-#define TAG(x) radeon##x##_RGB565
-#define TAG2(x,y) radeon##x##_RGB565##y
-#define GET_PTR(X,Y) (buf + ((Y) * drb->flippedPitch + (X)) * 2)
-#include "spantmp2.h"
-
-/* 32 bit, ARGB8888 color spanline and pixel functions
- */
-#define SPANTMP_PIXEL_FMT GL_BGRA
-#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
-
-#define TAG(x) radeon##x##_ARGB8888
-#define TAG2(x,y) radeon##x##_ARGB8888##y
-#define GET_PTR(X,Y) (buf + ((Y) * drb->flippedPitch + (X)) * 4)
-#include "spantmp2.h"
-
-/* ================================================================
- * Depth buffer
- */
-
-/* The Radeon family has depth tiling on all the time, so we have to convert
- * the x,y coordinates into the memory bus address (mba) in the same
- * manner as the engine. In each case, the linear block address (ba)
- * is calculated, and then wired with x and y to produce the final
- * memory address.
- * The chip will do address translation on its own if the surface registers
- * are set up correctly. It is not quite enough to get it working with hyperz
- * too...
- */
-
-static GLuint radeon_mba_z32(const driRenderbuffer * drb, GLint x, GLint y)
-{
- GLuint pitch = drb->pitch;
- if (drb->depthHasSurface) {
- return 4 * (x + y * pitch);
- } else {
- GLuint ba, address = 0; /* a[0..1] = 0 */
-
-#ifdef COMPILE_R300
- ba = (y / 8) * (pitch / 8) + (x / 8);
-#else
- ba = (y / 16) * (pitch / 16) + (x / 16);
-#endif
-
- address |= (x & 0x7) << 2; /* a[2..4] = x[0..2] */
- address |= (y & 0x3) << 5; /* a[5..6] = y[0..1] */
- address |= (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; /* a[7] = x[4] ^ y[2] */
- address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
-
- address |= (y & 0x8) << 7; /* a[10] = y[3] */
- address |= (((x & 0x8) << 1) ^ (y & 0x10)) << 7; /* a[11] = x[3] ^ y[4] */
- address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
-
- return address;
- }
-}
-
-static INLINE GLuint
-radeon_mba_z16(const driRenderbuffer * drb, GLint x, GLint y)
-{
- GLuint pitch = drb->pitch;
- if (drb->depthHasSurface) {
- return 2 * (x + y * pitch);
- } else {
- GLuint ba, address = 0; /* a[0] = 0 */
-
- ba = (y / 16) * (pitch / 32) + (x / 32);
-
- address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */
- address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */
- address |= (x & 0x8) << 4; /* a[7] = x[3] */
- address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
- address |= (y & 0x8) << 7; /* a[10] = y[3] */
- address |= ((x & 0x10) ^ (y & 0x10)) << 7; /* a[11] = x[4] ^ y[4] */
- address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
-
- return address;
- }
-}
-
-/* 16-bit depth buffer functions
- */
-#define VALUE_TYPE GLushort
-
-#define WRITE_DEPTH( _x, _y, d ) \
- *(GLushort *)(buf + radeon_mba_z16( drb, _x + xo, _y + yo )) = d;
-
-#define READ_DEPTH( d, _x, _y ) \
- d = *(GLushort *)(buf + radeon_mba_z16( drb, _x + xo, _y + yo ));
-
-#define TAG(x) radeon##x##_z16
-#include "depthtmp.h"
-
-/* 24 bit depth, 8 bit stencil depthbuffer functions
- *
- * Careful: It looks like the R300 uses ZZZS byte order while the R200
- * uses SZZZ for 24 bit depth, 8 bit stencil mode.
- */
-#define VALUE_TYPE GLuint
-
-#ifdef COMPILE_R300
-#define WRITE_DEPTH( _x, _y, d ) \
-do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
- tmp &= 0x000000ff; \
- tmp |= ((d << 8) & 0xffffff00); \
- *(GLuint *)(buf + offset) = tmp; \
-} while (0)
-#else
-#define WRITE_DEPTH( _x, _y, d ) \
-do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
- tmp &= 0xff000000; \
- tmp |= ((d) & 0x00ffffff); \
- *(GLuint *)(buf + offset) = tmp; \
-} while (0)
-#endif
-
-#ifdef COMPILE_R300
-#define READ_DEPTH( d, _x, _y ) \
- do { \
- d = (*(GLuint *)(buf + radeon_mba_z32( drb, _x + xo, \
- _y + yo )) & 0xffffff00) >> 8; \
- }while(0)
-#else
-#define READ_DEPTH( d, _x, _y ) \
- d = *(GLuint *)(buf + radeon_mba_z32( drb, _x + xo, \
- _y + yo )) & 0x00ffffff;
-#endif
-
-#define TAG(x) radeon##x##_z24_s8
-#include "depthtmp.h"
-
-/* ================================================================
- * Stencil buffer
- */
-
-/* 24 bit depth, 8 bit stencil depthbuffer functions
- */
-#ifdef COMPILE_R300
-#define WRITE_STENCIL( _x, _y, d ) \
-do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
- tmp &= 0xffffff00; \
- tmp |= (d) & 0xff; \
- *(GLuint *)(buf + offset) = tmp; \
-} while (0)
-#else
-#define WRITE_STENCIL( _x, _y, d ) \
-do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
- tmp &= 0x00ffffff; \
- tmp |= (((d) & 0xff) << 24); \
- *(GLuint *)(buf + offset) = tmp; \
-} while (0)
-#endif
-
-#ifdef COMPILE_R300
-#define READ_STENCIL( d, _x, _y ) \
-do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
- d = tmp & 0x000000ff; \
-} while (0)
-#else
-#define READ_STENCIL( d, _x, _y ) \
-do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
- d = (tmp & 0xff000000) >> 24; \
-} while (0)
-#endif
-
-#define TAG(x) radeon##x##_z24_s8
-#include "stenciltmp.h"
-
-/* Move locking out to get reasonable span performance (10x better
- * than doing this in HW_LOCK above). WaitForIdle() is the main
- * culprit.
- */
-
-static void radeonSpanRenderStart(GLcontext * ctx)
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-#ifdef COMPILE_R300
- r300ContextPtr r300 = (r300ContextPtr) rmesa;
- R300_FIREVERTICES(r300);
-#else
- RADEON_FIREVERTICES(rmesa);
-#endif
- LOCK_HARDWARE(rmesa);
- radeonWaitForIdleLocked(rmesa);
-
- /* Read the first pixel in the frame buffer. This should
- * be a noop, right? In fact without this conform fails as reading
- * from the framebuffer sometimes produces old results -- the
- * on-card read cache gets mixed up and doesn't notice that the
- * framebuffer has been updated.
- *
- * Note that we should probably be reading some otherwise unused
- * region of VRAM, otherwise we might get incorrect results when
- * reading pixels from the top left of the screen.
- *
- * I found this problem on an R420 with glean's texCube test.
- * Note that the R200 span code also *writes* the first pixel in the
- * framebuffer, but I've found this to be unnecessary.
- * -- Nicolai Hähnle, June 2008
- */
- {
- int p;
- driRenderbuffer *drb =
- (driRenderbuffer *) ctx->WinSysDrawBuffer->_ColorDrawBuffers[0];
- volatile int *buf =
- (volatile int *)(rmesa->dri.screen->pFB + drb->offset);
- p = *buf;
- }
-}
-
-static void radeonSpanRenderFinish(GLcontext * ctx)
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- _swrast_flush(ctx);
- UNLOCK_HARDWARE(rmesa);
-}
-
-void radeonInitSpanFuncs(GLcontext * ctx)
-{
- struct swrast_device_driver *swdd =
- _swrast_GetDeviceDriverReference(ctx);
- swdd->SpanRenderStart = radeonSpanRenderStart;
- swdd->SpanRenderFinish = radeonSpanRenderFinish;
-}
-
-/**
- * Plug in the Get/Put routines for the given driRenderbuffer.
- */
-void radeonSetSpanFunctions(driRenderbuffer * drb, const GLvisual * vis)
-{
- if (drb->Base.InternalFormat == GL_RGBA) {
- if (vis->redBits == 5 && vis->greenBits == 6
- && vis->blueBits == 5) {
- radeonInitPointers_RGB565(&drb->Base);
- } else {
- radeonInitPointers_ARGB8888(&drb->Base);
- }
- } else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
- radeonInitDepthPointers_z16(&drb->Base);
- } else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
- radeonInitDepthPointers_z24_s8(&drb->Base);
- } else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
- radeonInitStencilPointers_z24_s8(&drb->Base);
- }
-}
+../radeon/radeon_span.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_span.h b/src/mesa/drivers/dri/r300/radeon_span.h
new file mode 120000
index 0000000000..f9d634508c
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_span.h
@@ -0,0 +1 @@
+../radeon/radeon_span.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_state.c b/src/mesa/drivers/dri/r300/radeon_state.c
deleted file mode 100644
index c401da6c54..0000000000
--- a/src/mesa/drivers/dri/r300/radeon_state.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/**************************************************************************
-
-Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
-
-The Weather Channel (TM) funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86 license.
-This notice must be preserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/api_arrayelt.h"
-#include "main/enums.h"
-#include "main/framebuffer.h"
-#include "main/colormac.h"
-#include "main/light.h"
-
-#include "swrast/swrast.h"
-#include "vbo/vbo.h"
-#include "tnl/tnl.h"
-#include "tnl/t_pipeline.h"
-#include "swrast_setup/swrast_setup.h"
-
-#include "radeon_ioctl.h"
-#include "radeon_state.h"
-#include "r300_ioctl.h"
-
-
-/* =============================================================
- * Scissoring
- */
-
-static GLboolean intersect_rect(drm_clip_rect_t * out,
- drm_clip_rect_t * a, drm_clip_rect_t * b)
-{
- *out = *a;
- if (b->x1 > out->x1)
- out->x1 = b->x1;
- if (b->y1 > out->y1)
- out->y1 = b->y1;
- if (b->x2 < out->x2)
- out->x2 = b->x2;
- if (b->y2 < out->y2)
- out->y2 = b->y2;
- if (out->x1 >= out->x2)
- return GL_FALSE;
- if (out->y1 >= out->y2)
- return GL_FALSE;
- return GL_TRUE;
-}
-
-void radeonRecalcScissorRects(radeonContextPtr radeon)
-{
- drm_clip_rect_t *out;
- int i;
-
- /* Grow cliprect store?
- */
- if (radeon->state.scissor.numAllocedClipRects < radeon->numClipRects) {
- while (radeon->state.scissor.numAllocedClipRects <
- radeon->numClipRects) {
- radeon->state.scissor.numAllocedClipRects += 1; /* zero case */
- radeon->state.scissor.numAllocedClipRects *= 2;
- }
-
- if (radeon->state.scissor.pClipRects)
- FREE(radeon->state.scissor.pClipRects);
-
- radeon->state.scissor.pClipRects =
- MALLOC(radeon->state.scissor.numAllocedClipRects *
- sizeof(drm_clip_rect_t));
-
- if (radeon->state.scissor.pClipRects == NULL) {
- radeon->state.scissor.numAllocedClipRects = 0;
- return;
- }
- }
-
- out = radeon->state.scissor.pClipRects;
- radeon->state.scissor.numClipRects = 0;
-
- for (i = 0; i < radeon->numClipRects; i++) {
- if (intersect_rect(out,
- &radeon->pClipRects[i],
- &radeon->state.scissor.rect)) {
- radeon->state.scissor.numClipRects++;
- out++;
- }
- }
-}
-
-void radeonUpdateScissor(GLcontext* ctx)
-{
- radeonContextPtr radeon = RADEON_CONTEXT(ctx);
-
- if (radeon->dri.drawable) {
- __DRIdrawablePrivate *dPriv = radeon->dri.drawable;
- int x1 = dPriv->x + ctx->Scissor.X;
- int y1 = dPriv->y + dPriv->h - (ctx->Scissor.Y + ctx->Scissor.Height);
-
- radeon->state.scissor.rect.x1 = x1;
- radeon->state.scissor.rect.y1 = y1;
- radeon->state.scissor.rect.x2 = x1 + ctx->Scissor.Width;
- radeon->state.scissor.rect.y2 = y1 + ctx->Scissor.Height;
-
- radeonRecalcScissorRects(radeon);
- }
-}
-
-static void radeonScissor(GLcontext* ctx, GLint x, GLint y, GLsizei w, GLsizei h)
-{
- if (ctx->Scissor.Enabled) {
- /* We don't pipeline cliprect changes */
- r300Flush(ctx);
- radeonUpdateScissor(ctx);
- }
-}
-
-
-/**
- * Update cliprects and scissors.
- */
-void radeonSetCliprects(radeonContextPtr radeon)
-{
- __DRIdrawablePrivate *const drawable = radeon->dri.drawable;
- __DRIdrawablePrivate *const readable = radeon->dri.readable;
- GLframebuffer *const draw_fb = (GLframebuffer*)drawable->driverPrivate;
- GLframebuffer *const read_fb = (GLframebuffer*)readable->driverPrivate;
-
- if (draw_fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
- /* Can't ignore 2d windows if we are page flipping. */
- if (drawable->numBackClipRects == 0 || radeon->doPageFlip ||
- radeon->sarea->pfCurrentPage == 1) {
- radeon->numClipRects = drawable->numClipRects;
- radeon->pClipRects = drawable->pClipRects;
- } else {
- radeon->numClipRects = drawable->numBackClipRects;
- radeon->pClipRects = drawable->pBackClipRects;
- }
- } else {
- /* front buffer (or none, or multiple buffers */
- radeon->numClipRects = drawable->numClipRects;
- radeon->pClipRects = drawable->pClipRects;
- }
-
- if ((draw_fb->Width != drawable->w) ||
- (draw_fb->Height != drawable->h)) {
- _mesa_resize_framebuffer(radeon->glCtx, draw_fb,
- drawable->w, drawable->h);
- draw_fb->Initialized = GL_TRUE;
- }
-
- if (drawable != readable) {
- if ((read_fb->Width != readable->w) ||
- (read_fb->Height != readable->h)) {
- _mesa_resize_framebuffer(radeon->glCtx, read_fb,
- readable->w, readable->h);
- read_fb->Initialized = GL_TRUE;
- }
- }
-
- if (radeon->state.scissor.enabled)
- radeonRecalcScissorRects(radeon);
-
- radeon->lastStamp = drawable->lastStamp;
-}
-
-
-/**
- * Handle common enable bits.
- * Called as a fallback by r200Enable/r300Enable.
- */
-void radeonEnable(GLcontext* ctx, GLenum cap, GLboolean state)
-{
- radeonContextPtr radeon = RADEON_CONTEXT(ctx);
-
- switch(cap) {
- case GL_SCISSOR_TEST:
- /* We don't pipeline cliprect & scissor changes */
- r300Flush(ctx);
-
- radeon->state.scissor.enabled = state;
- radeonUpdateScissor(ctx);
- break;
-
- default:
- return;
- }
-}
-
-
-/**
- * Initialize default state.
- * This function is called once at context init time from
- * r200InitState/r300InitState
- */
-void radeonInitState(radeonContextPtr radeon)
-{
- radeon->Fallback = 0;
-
- if (radeon->glCtx->Visual.doubleBufferMode && radeon->sarea->pfCurrentPage == 0) {
- radeon->state.color.drawOffset = radeon->radeonScreen->backOffset;
- radeon->state.color.drawPitch = radeon->radeonScreen->backPitch;
- } else {
- radeon->state.color.drawOffset = radeon->radeonScreen->frontOffset;
- radeon->state.color.drawPitch = radeon->radeonScreen->frontPitch;
- }
-}
-
-
-/**
- * Initialize common state functions.
- * Called by r200InitStateFuncs/r300InitStateFuncs
- */
-void radeonInitStateFuncs(struct dd_function_table *functions)
-{
- functions->Scissor = radeonScissor;
-}
diff --git a/src/mesa/drivers/dri/r300/radeon_texture.c b/src/mesa/drivers/dri/r300/radeon_texture.c
new file mode 120000
index 0000000000..a822710915
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_texture.c
@@ -0,0 +1 @@
+../radeon/radeon_texture.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_texture.h b/src/mesa/drivers/dri/r300/radeon_texture.h
new file mode 120000
index 0000000000..17fac3d5ea
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/radeon_texture.h
@@ -0,0 +1 @@
+../radeon/radeon_texture.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/server/radeon.h b/src/mesa/drivers/dri/r300/server/radeon.h
new file mode 120000
index 0000000000..81274a54f1
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/server/radeon.h
@@ -0,0 +1 @@
+../../radeon/server/radeon.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/server/radeon_dri.c b/src/mesa/drivers/dri/r300/server/radeon_dri.c
new file mode 120000
index 0000000000..d05847d650
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/server/radeon_dri.c
@@ -0,0 +1 @@
+../../radeon/server/radeon_dri.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/server/radeon_dri.h b/src/mesa/drivers/dri/r300/server/radeon_dri.h
new file mode 120000
index 0000000000..27c591d3c9
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/server/radeon_dri.h
@@ -0,0 +1 @@
+../../radeon/server/radeon_dri.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/server/radeon_egl.c b/src/mesa/drivers/dri/r300/server/radeon_egl.c
new file mode 120000
index 0000000000..d7735a7643
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/server/radeon_egl.c
@@ -0,0 +1 @@
+../../radeon/server/radeon_egl.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/server/radeon_macros.h b/src/mesa/drivers/dri/r300/server/radeon_macros.h
new file mode 120000
index 0000000000..c56cd735b8
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/server/radeon_macros.h
@@ -0,0 +1 @@
+../../radeon/server/radeon_macros.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/server/radeon_reg.h b/src/mesa/drivers/dri/r300/server/radeon_reg.h
new file mode 120000
index 0000000000..e2349dcb68
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/server/radeon_reg.h
@@ -0,0 +1 @@
+../../radeon/server/radeon_reg.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/Lindent b/src/mesa/drivers/dri/r600/Lindent
new file mode 100755
index 0000000000..7d8d8896e3
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/Lindent
@@ -0,0 +1,2 @@
+#!/bin/sh
+indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs "$@"
diff --git a/src/mesa/drivers/dri/r600/Makefile b/src/mesa/drivers/dri/r600/Makefile
new file mode 100644
index 0000000000..d925a2dfe3
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/Makefile
@@ -0,0 +1,79 @@
+# src/mesa/drivers/dri/r300/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+CFLAGS += $(RADEON_CFLAGS)
+
+LIBNAME = r600_dri.so
+
+MINIGLX_SOURCES = server/radeon_dri.c
+
+ifeq ($(USING_EGL), 1)
+EGL_SOURCES = server/radeon_egl.c
+endif
+
+ifeq ($(RADEON_LDFLAGS),)
+CS_SOURCES = radeon_cs_space_drm.c
+endif
+
+COMMON_SOURCES = \
+ ../../common/driverfuncs.c \
+ ../common/mm.c \
+ ../common/utils.c \
+ ../common/texmem.c \
+ ../common/vblank.c \
+ ../common/xmlconfig.c \
+ ../common/dri_util.c
+
+RADEON_COMMON_SOURCES = \
+ radeon_bo_legacy.c \
+ radeon_common_context.c \
+ radeon_common.c \
+ radeon_cs_legacy.c \
+ radeon_dma.c \
+ radeon_debug.c \
+ radeon_fbo.c \
+ radeon_lock.c \
+ radeon_mipmap_tree.c \
+ radeon_span.c \
+ radeon_texture.c \
+ radeon_queryobj.c
+
+DRIVER_SOURCES = \
+ radeon_screen.c \
+ r600_context.c \
+ r600_cmdbuf.c \
+ r600_emit.c \
+ r700_assembler.c \
+ r700_fragprog.c \
+ r700_vertprog.c \
+ r700_shader.c \
+ r700_shaderinst.c \
+ r700_ioctl.c \
+ r700_oglprog.c \
+ r700_chip.c \
+ r700_state.c \
+ r700_clear.c \
+ r700_render.c \
+ r600_tex.c \
+ r600_texstate.c \
+ r700_debug.c \
+ $(RADEON_COMMON_SOURCES) \
+ $(EGL_SOURCES) \
+ $(CS_SOURCES)
+
+C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES)
+
+DRIVER_DEFINES = -DCOMPILE_R600 -DR200_MERGED=0 \
+ -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R600 \
+# -DRADEON_BO_TRACK \
+ -Wall
+
+DRI_LIB_DEPS += $(RADEON_LDFLAGS)
+
+##### TARGETS #####
+
+include ../Makefile.template
+
+symlinks:
diff --git a/src/mesa/drivers/dri/r600/defaultendian.h b/src/mesa/drivers/dri/r600/defaultendian.h
new file mode 100644
index 0000000000..32caf32cd2
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/defaultendian.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+
+#ifndef _DEFINEENDIAN_H_
+#define _DEFINEENDIAN_H_
+
+//We have to choose a reg bits orientation if there is no compile flag for it.
+#if defined(LITTLEENDIAN_CPU)
+#elif defined(BIGENDIAN_CPU)
+#else
+#define LITTLEENDIAN_CPU
+#endif
+
+#endif //_DEFINEENDIAN_H_
diff --git a/src/mesa/drivers/dri/r600/r600_cmdbuf.c b/src/mesa/drivers/dri/r600/r600_cmdbuf.c
new file mode 100644
index 0000000000..3cfe03a45f
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_cmdbuf.c
@@ -0,0 +1,514 @@
+/*
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/**
+ * Mostly coppied from \radeon\radeon_cs_legacy.c
+ */
+
+#include <errno.h>
+
+#include "main/glheader.h"
+#include "main/state.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "main/simple_list.h"
+#include "swrast/swrast.h"
+
+#include "drm.h"
+#include "radeon_drm.h"
+
+#include "r600_context.h"
+#include "radeon_reg.h"
+#include "r600_cmdbuf.h"
+#include "r600_emit.h"
+#include "radeon_bocs_wrapper.h"
+#include "radeon_mipmap_tree.h"
+#include "radeon_reg.h"
+
+
+
+static struct radeon_cs * r600_cs_create(struct radeon_cs_manager *csm,
+ uint32_t ndw)
+{
+ struct radeon_cs *cs;
+
+ cs = (struct radeon_cs*)calloc(1, sizeof(struct radeon_cs));
+ if (cs == NULL) {
+ return NULL;
+ }
+ cs->csm = csm;
+ cs->ndw = (ndw + 0x3FF) & (~0x3FF);
+ cs->packets = (uint32_t*)malloc(4*cs->ndw);
+ if (cs->packets == NULL) {
+ free(cs);
+ return NULL;
+ }
+ cs->relocs_total_size = 0;
+ return cs;
+}
+
+static int r600_cs_write_reloc(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t read_domain,
+ uint32_t write_domain,
+ uint32_t flags)
+{
+ struct r600_cs_reloc_legacy *relocs;
+ int i;
+
+ relocs = (struct r600_cs_reloc_legacy *)cs->relocs;
+ /* check domains */
+ if ((read_domain && write_domain) || (!read_domain && !write_domain)) {
+ /* in one CS a bo can only be in read or write domain but not
+ * in read & write domain at the same sime
+ */
+ return -EINVAL;
+ }
+ if (read_domain == RADEON_GEM_DOMAIN_CPU) {
+ return -EINVAL;
+ }
+ if (write_domain == RADEON_GEM_DOMAIN_CPU) {
+ return -EINVAL;
+ }
+ /* check if bo is already referenced */
+ for(i = 0; i < cs->crelocs; i++) {
+ uint32_t *indices;
+ uint32_t *reloc_indices;
+
+ if (relocs[i].base.bo->handle == bo->handle) {
+ /* Check domains must be in read or write. As we check already
+ * checked that in argument one of the read or write domain was
+ * set we only need to check that if previous reloc as the read
+ * domain set then the read_domain should also be set for this
+ * new relocation.
+ */
+ if (relocs[i].base.read_domain && !read_domain) {
+ return -EINVAL;
+ }
+ if (relocs[i].base.write_domain && !write_domain) {
+ return -EINVAL;
+ }
+ relocs[i].base.read_domain |= read_domain;
+ relocs[i].base.write_domain |= write_domain;
+ /* save indice */
+ relocs[i].cindices++;
+ indices = (uint32_t*)realloc(relocs[i].indices,
+ relocs[i].cindices * 4);
+ reloc_indices = (uint32_t*)realloc(relocs[i].reloc_indices,
+ relocs[i].cindices * 4);
+ if ( (indices == NULL) || (reloc_indices == NULL) ) {
+ relocs[i].cindices -= 1;
+ return -ENOMEM;
+ }
+ relocs[i].indices = indices;
+ relocs[i].reloc_indices = reloc_indices;
+ relocs[i].indices[relocs[i].cindices - 1] = cs->cdw;
+ relocs[i].reloc_indices[relocs[i].cindices - 1] = cs->cdw;
+ cs->section_cdw += 2;
+ cs->cdw += 2;
+
+ return 0;
+ }
+ }
+ /* add bo to reloc */
+ relocs = (struct r600_cs_reloc_legacy*)
+ realloc(cs->relocs,
+ sizeof(struct r600_cs_reloc_legacy) * (cs->crelocs + 1));
+ if (relocs == NULL) {
+ return -ENOMEM;
+ }
+ cs->relocs = relocs;
+ relocs[cs->crelocs].base.bo = bo;
+ relocs[cs->crelocs].base.read_domain = read_domain;
+ relocs[cs->crelocs].base.write_domain = write_domain;
+ relocs[cs->crelocs].base.flags = flags;
+ relocs[cs->crelocs].indices = (uint32_t*)malloc(4);
+ relocs[cs->crelocs].reloc_indices = (uint32_t*)malloc(4);
+ if ( (relocs[cs->crelocs].indices == NULL) || (relocs[cs->crelocs].reloc_indices == NULL) )
+ {
+ return -ENOMEM;
+ }
+
+ relocs[cs->crelocs].indices[0] = cs->cdw;
+ relocs[cs->crelocs].reloc_indices[0] = cs->cdw;
+ cs->section_cdw += 2;
+ cs->cdw += 2;
+ relocs[cs->crelocs].cindices = 1;
+ cs->relocs_total_size += radeon_bo_legacy_relocs_size(bo);
+ cs->crelocs++;
+
+ radeon_bo_ref(bo);
+
+ return 0;
+}
+
+static int r600_cs_begin(struct radeon_cs *cs,
+ uint32_t ndw,
+ const char *file,
+ const char *func,
+ int line)
+{
+ if (cs->section) {
+ fprintf(stderr, "CS already in a section(%s,%s,%d)\n",
+ cs->section_file, cs->section_func, cs->section_line);
+ fprintf(stderr, "CS can't start section(%s,%s,%d)\n",
+ file, func, line);
+ return -EPIPE;
+ }
+
+ cs->section = 1;
+ cs->section_ndw = ndw;
+ cs->section_cdw = 0;
+ cs->section_file = file;
+ cs->section_func = func;
+ cs->section_line = line;
+
+ if (cs->cdw + ndw > cs->ndw) {
+ uint32_t tmp, *ptr;
+ int num = (ndw > 0x400) ? ndw : 0x400;
+
+ tmp = (cs->cdw + num + 0x3FF) & (~0x3FF);
+ ptr = (uint32_t*)realloc(cs->packets, 4 * tmp);
+ if (ptr == NULL) {
+ return -ENOMEM;
+ }
+ cs->packets = ptr;
+ cs->ndw = tmp;
+ }
+
+ return 0;
+}
+
+static int r600_cs_end(struct radeon_cs *cs,
+ const char *file,
+ const char *func,
+ int line)
+
+{
+ if (!cs->section) {
+ fprintf(stderr, "CS no section to end at (%s,%s,%d)\n",
+ file, func, line);
+ return -EPIPE;
+ }
+ cs->section = 0;
+
+ if ( cs->section_ndw != cs->section_cdw ) {
+ fprintf(stderr, "CS section size missmatch start at (%s,%s,%d) %d vs %d\n",
+ cs->section_file, cs->section_func, cs->section_line, cs->section_ndw, cs->section_cdw);
+ fprintf(stderr, "cs->section_ndw = %d, cs->cdw = %d, cs->section_cdw = %d \n",
+ cs->section_ndw, cs->cdw, cs->section_cdw);
+ fprintf(stderr, "CS section end at (%s,%s,%d)\n",
+ file, func, line);
+ return -EPIPE;
+ }
+
+ if (cs->cdw > cs->ndw) {
+ fprintf(stderr, "CS section overflow at (%s,%s,%d) cdw %d ndw %d\n",
+ cs->section_file, cs->section_func, cs->section_line,cs->cdw,cs->ndw);
+ fprintf(stderr, "CS section end at (%s,%s,%d)\n",
+ file, func, line);
+ assert(0);
+ }
+
+ return 0;
+}
+
+static int r600_cs_process_relocs(struct radeon_cs *cs,
+ uint32_t * reloc_chunk,
+ uint32_t * length_dw_reloc_chunk)
+{
+ struct r600_cs_manager_legacy *csm = (struct r600_cs_manager_legacy*)cs->csm;
+ struct r600_cs_reloc_legacy *relocs;
+ int i, j, r;
+
+ uint32_t offset_dw = 0;
+
+ csm = (struct r600_cs_manager_legacy*)cs->csm;
+ relocs = (struct r600_cs_reloc_legacy *)cs->relocs;
+restart:
+ for (i = 0; i < cs->crelocs; i++) {
+ uint32_t soffset, eoffset, asicoffset;
+
+ r = radeon_bo_legacy_validate(relocs[i].base.bo,
+ &soffset, &eoffset);
+ if (r == -EAGAIN) {
+ goto restart;
+ }
+ if (r) {
+ fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n",
+ relocs[i].base.bo, soffset, eoffset);
+ return r;
+ }
+ asicoffset = soffset;
+
+ for (j = 0; j < relocs[i].cindices; j++) {
+ if (asicoffset >= eoffset) {
+ /* radeon_bo_debug(relocs[i].base.bo, 12); */
+ fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n",
+ relocs[i].base.bo, soffset, eoffset);
+ fprintf(stderr, "above end: %p 0x%08X 0x%08X\n",
+ relocs[i].base.bo,
+ cs->packets[relocs[i].indices[j]],
+ eoffset);
+ exit(0);
+ return -EINVAL;
+ }
+ /* pkt3 nop header in ib chunk */
+ cs->packets[relocs[i].reloc_indices[j]] = 0xC0001000;
+ /* reloc index in ib chunk */
+ cs->packets[relocs[i].reloc_indices[j] + 1] = offset_dw;
+ }
+
+ /* asic offset in reloc chunk */ /* see alex drm r600_nomm_relocate */
+ reloc_chunk[offset_dw] = asicoffset;
+ reloc_chunk[offset_dw + 3] = 0;
+
+ offset_dw += 4;
+ }
+
+ *length_dw_reloc_chunk = offset_dw;
+
+ return 0;
+}
+
+static int r600_cs_set_age(struct radeon_cs *cs) /* -------------- */
+{
+ struct r600_cs_manager_legacy *csm = (struct r600_cs_manager_legacy*)cs->csm;
+ struct r600_cs_reloc_legacy *relocs;
+ int i;
+
+ relocs = (struct r600_cs_reloc_legacy *)cs->relocs;
+ for (i = 0; i < cs->crelocs; i++) {
+ radeon_bo_legacy_pending(relocs[i].base.bo, csm->pending_age);
+ radeon_bo_unref(relocs[i].base.bo);
+ }
+ return 0;
+}
+
+#if 0
+static void dump_cmdbuf(struct radeon_cs *cs)
+{
+ int i;
+ fprintf(stderr,"--start--\n");
+ for (i = 0; i < cs->cdw; i++){
+ fprintf(stderr,"0x%08x\n", cs->packets[i]);
+ }
+ fprintf(stderr,"--end--\n");
+
+}
+#endif
+
+static int r600_cs_emit(struct radeon_cs *cs)
+{
+ struct r600_cs_manager_legacy *csm = (struct r600_cs_manager_legacy*)cs->csm;
+ struct drm_radeon_cs cs_cmd;
+ struct drm_radeon_cs_chunk cs_chunk[2];
+ uint32_t length_dw_reloc_chunk;
+ uint64_t chunk_ptrs[2];
+ uint32_t *reloc_chunk;
+ int r;
+ int retry = 0;
+
+ /* TODO : put chip level things here if need. */
+ /* csm->ctx->vtbl.emit_cs_header(cs, csm->ctx); */
+
+ csm->pending_count = 1;
+
+ reloc_chunk = (uint32_t*)calloc(1, cs->crelocs * 4 * 4);
+
+ r = r600_cs_process_relocs(cs, reloc_chunk, &length_dw_reloc_chunk);
+ if (r) {
+ free(reloc_chunk);
+ return 0;
+ }
+
+ /* raw ib chunk */
+ cs_chunk[0].chunk_id = RADEON_CHUNK_ID_IB;
+ cs_chunk[0].length_dw = cs->cdw;
+ cs_chunk[0].chunk_data = (unsigned long)(cs->packets);
+
+ /* reloc chaunk */
+ cs_chunk[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
+ cs_chunk[1].length_dw = length_dw_reloc_chunk;
+ cs_chunk[1].chunk_data = (unsigned long)reloc_chunk;
+
+ chunk_ptrs[0] = (uint64_t)(unsigned long)&(cs_chunk[0]);
+ chunk_ptrs[1] = (uint64_t)(unsigned long)&(cs_chunk[1]);
+
+ cs_cmd.num_chunks = 2;
+ /* cs_cmd.cs_id = 0; */
+ cs_cmd.chunks = (uint64_t)(unsigned long)chunk_ptrs;
+
+ //dump_cmdbuf(cs);
+
+ do
+ {
+ r = drmCommandWriteRead(cs->csm->fd, DRM_RADEON_CS, &cs_cmd, sizeof(cs_cmd));
+ retry++;
+ } while (r == -EAGAIN && retry < 1000);
+
+ if (r) {
+ free(reloc_chunk);
+ return r;
+ }
+
+ csm->pending_age = cs_cmd.cs_id;
+
+ r600_cs_set_age(cs);
+
+ cs->csm->read_used = 0;
+ cs->csm->vram_write_used = 0;
+ cs->csm->gart_write_used = 0;
+
+ free(reloc_chunk);
+
+ return 0;
+}
+
+static void inline r600_cs_free_reloc(void *relocs_p, int crelocs)
+{
+ struct r600_cs_reloc_legacy *relocs = relocs_p;
+ int i;
+ if (!relocs_p)
+ return;
+ for (i = 0; i < crelocs; i++)
+ {
+ free(relocs[i].indices);
+ free(relocs[i].reloc_indices);
+ }
+}
+
+static int r600_cs_destroy(struct radeon_cs *cs)
+{
+ r600_cs_free_reloc(cs->relocs, cs->crelocs);
+ free(cs->relocs);
+ free(cs->packets);
+ free(cs);
+ return 0;
+}
+
+static int r600_cs_erase(struct radeon_cs *cs)
+{
+ r600_cs_free_reloc(cs->relocs, cs->crelocs);
+ free(cs->relocs);
+ cs->relocs_total_size = 0;
+ cs->relocs = NULL;
+ cs->crelocs = 0;
+ cs->cdw = 0;
+ cs->section = 0;
+ return 0;
+}
+
+static int r600_cs_need_flush(struct radeon_cs *cs)
+{
+ /* this function used to flush when the BO usage got to
+ * a certain size, now the higher levels handle this better */
+ return 0;
+}
+
+static void r600_cs_print(struct radeon_cs *cs, FILE *file)
+{
+}
+
+static struct radeon_cs_funcs r600_cs_funcs = {
+ r600_cs_create,
+ r600_cs_write_reloc,
+ r600_cs_begin,
+ r600_cs_end,
+ r600_cs_emit,
+ r600_cs_destroy,
+ r600_cs_erase,
+ r600_cs_need_flush,
+ r600_cs_print
+};
+
+struct radeon_cs_manager * r600_radeon_cs_manager_legacy_ctor(struct radeon_context *ctx)
+{
+ struct r600_cs_manager_legacy *csm;
+
+ csm = (struct r600_cs_manager_legacy*)
+ calloc(1, sizeof(struct r600_cs_manager_legacy));
+ if (csm == NULL) {
+ return NULL;
+ }
+ csm->base.funcs = &r600_cs_funcs;
+ csm->base.fd = ctx->dri.fd;
+ csm->ctx = ctx;
+ csm->pending_age = 1;
+ return (struct radeon_cs_manager*)csm;
+}
+
+void r600InitCmdBuf(context_t *r600) /* from rcommonInitCmdBuf */
+{
+ radeonContextPtr rmesa = &r600->radeon;
+ GLuint size;
+
+ r600InitAtoms(r600);
+
+ /* Initialize command buffer */
+ size = 256 * driQueryOptioni(&rmesa->optionCache,
+ "command_buffer_size");
+ if (size < 2 * rmesa->hw.max_state_size) {
+ size = 2 * rmesa->hw.max_state_size + 65535;
+ }
+ if (size > 64 * 256)
+ size = 64 * 256;
+
+ if (rmesa->radeonScreen->kernel_mm) {
+ int fd = rmesa->radeonScreen->driScreen->fd;
+ rmesa->cmdbuf.csm = radeon_cs_manager_gem_ctor(fd);
+ } else {
+ rmesa->cmdbuf.csm = r600_radeon_cs_manager_legacy_ctor(rmesa);
+ }
+ if (rmesa->cmdbuf.csm == NULL) {
+ /* FIXME: fatal error */
+ return;
+ }
+ rmesa->cmdbuf.cs = radeon_cs_create(rmesa->cmdbuf.csm, size);
+ assert(rmesa->cmdbuf.cs != NULL);
+ rmesa->cmdbuf.size = size;
+
+ radeon_cs_space_set_flush(rmesa->cmdbuf.cs,
+ (void (*)(void *))rmesa->glCtx->Driver.Flush, rmesa->glCtx);
+
+ if (!rmesa->radeonScreen->kernel_mm) {
+ radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM, rmesa->radeonScreen->texSize[0]);
+ radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT, rmesa->radeonScreen->gartTextures.size);
+ } else {
+ struct drm_radeon_gem_info mminfo;
+
+ if (!drmCommandWriteRead(rmesa->dri.fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
+ {
+ radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM, mminfo.vram_visible);
+ radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT, mminfo.gart_size);
+ }
+ }
+}
+
diff --git a/src/mesa/drivers/dri/r600/r600_cmdbuf.h b/src/mesa/drivers/dri/r600/r600_cmdbuf.h
new file mode 100644
index 0000000000..eba43d37b6
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_cmdbuf.h
@@ -0,0 +1,212 @@
+/*
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/**
+ * \file
+ *
+ * \author Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+#ifndef __R600_CMDBUF_H__
+#define __R600_CMDBUF_H__
+
+#include "r600_context.h"
+#include "r600_emit.h"
+
+#define RADEON_CP_PACKET3_NOP 0xC0001000
+#define RADEON_CP_PACKET3_NEXT_CHAR 0xC0001900
+#define RADEON_CP_PACKET3_PLY_NEXTSCAN 0xC0001D00
+#define RADEON_CP_PACKET3_SET_SCISSORS 0xC0001E00
+#define RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300
+#define RADEON_CP_PACKET3_LOAD_MICROCODE 0xC0002400
+#define RADEON_CP_PACKET3_WAIT_FOR_IDLE 0xC0002600
+#define RADEON_CP_PACKET3_3D_DRAW_VBUF 0xC0002800
+#define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900
+#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00
+#define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00
+#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00
+#define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100
+#define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200
+#define RADEON_CP_PACKET3_CNTL_SMALLTEXT 0xC0009300
+#define RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400
+#define RADEON_CP_PACKET3_CNTL_POLYLINE 0xC0009500
+#define RADEON_CP_PACKET3_CNTL_POLYSCANLINES 0xC0009800
+#define RADEON_CP_PACKET3_CNTL_PAINT_MULTI 0xC0009A00
+#define RADEON_CP_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00
+#define RADEON_CP_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00
+
+/* r6xx/r7xx packet 3 type offsets */
+#define R600_SET_CONFIG_REG_OFFSET 0x00008000
+#define R600_SET_CONFIG_REG_END 0x0000ac00
+#define R600_SET_CONTEXT_REG_OFFSET 0x00028000
+#define R600_SET_CONTEXT_REG_END 0x00029000
+#define R600_SET_ALU_CONST_OFFSET 0x00030000
+#define R600_SET_ALU_CONST_END 0x00032000
+#define R600_SET_RESOURCE_OFFSET 0x00038000
+#define R600_SET_RESOURCE_END 0x0003c000
+#define R600_SET_SAMPLER_OFFSET 0x0003c000
+#define R600_SET_SAMPLER_END 0x0003cff0
+#define R600_SET_CTL_CONST_OFFSET 0x0003cff0
+#define R600_SET_CTL_CONST_END 0x0003e200
+#define R600_SET_LOOP_CONST_OFFSET 0x0003e200
+#define R600_SET_LOOP_CONST_END 0x0003e380
+#define R600_SET_BOOL_CONST_OFFSET 0x0003e380
+#define R600_SET_BOOL_CONST_END 0x00040000
+
+/* r6xx/r7xx packet 3 types */
+#define R600_IT_INDIRECT_BUFFER_END 0x00001700
+#define R600_IT_SET_PREDICATION 0x00002000
+#define R600_IT_REG_RMW 0x00002100
+#define R600_IT_COND_EXEC 0x00002200
+#define R600_IT_PRED_EXEC 0x00002300
+#define R600_IT_START_3D_CMDBUF 0x00002400
+#define R600_IT_DRAW_INDEX_2 0x00002700
+#define R600_IT_CONTEXT_CONTROL 0x00002800
+#define R600_IT_DRAW_INDEX_IMMD_BE 0x00002900
+#define R600_IT_INDEX_TYPE 0x00002A00
+#define R600_IT_DRAW_INDEX 0x00002B00
+#define R600_IT_DRAW_INDEX_AUTO 0x00002D00
+#define R600_IT_DRAW_INDEX_IMMD 0x00002E00
+#define R600_IT_NUM_INSTANCES 0x00002F00
+#define R600_IT_STRMOUT_BUFFER_UPDATE 0x00003400
+#define R600_IT_INDIRECT_BUFFER_MP 0x00003800
+#define R600_IT_MEM_SEMAPHORE 0x00003900
+#define R600_IT_MPEG_INDEX 0x00003A00
+#define R600_IT_WAIT_REG_MEM 0x00003C00
+#define R600_IT_MEM_WRITE 0x00003D00
+#define R600_IT_INDIRECT_BUFFER 0x00003200
+#define R600_IT_CP_INTERRUPT 0x00004000
+#define R600_IT_SURFACE_SYNC 0x00004300
+#define R600_IT_ME_INITIALIZE 0x00004400
+#define R600_IT_COND_WRITE 0x00004500
+#define R600_IT_EVENT_WRITE 0x00004600
+#define R600_IT_EVENT_WRITE_EOP 0x00004700
+#define R600_IT_ONE_REG_WRITE 0x00005700
+#define R600_IT_SET_CONFIG_REG 0x00006800
+#define R600_IT_SET_CONTEXT_REG 0x00006900
+#define R600_IT_SET_ALU_CONST 0x00006A00
+#define R600_IT_SET_BOOL_CONST 0x00006B00
+#define R600_IT_SET_LOOP_CONST 0x00006C00
+#define R600_IT_SET_RESOURCE 0x00006D00
+#define R600_IT_SET_SAMPLER 0x00006E00
+#define R600_IT_SET_CTL_CONST 0x00006F00
+#define R600_IT_SURFACE_BASE_UPDATE 0x00007300
+
+struct r600_cs_manager_legacy
+{
+ struct radeon_cs_manager base;
+ struct radeon_context *ctx;
+ /* hack for scratch stuff */
+ uint32_t pending_age;
+ uint32_t pending_count;
+};
+
+struct r600_cs_reloc_legacy {
+ struct radeon_cs_reloc base;
+ uint32_t cindices;
+ uint32_t *indices;
+ uint32_t *reloc_indices;
+};
+
+struct radeon_cs_manager * r600_radeon_cs_manager_legacy_ctor(struct radeon_context *ctx);
+
+/**
+ * Write one dword to the command buffer.
+ */
+#define R600_OUT_BATCH(data) \
+do { \
+ radeon_cs_write_dword(b_l_rmesa->cmdbuf.cs, data); \
+} while(0)
+
+/**
+ * Write n dwords from ptr to the command buffer.
+ */
+#define R600_OUT_BATCH_TABLE(ptr,n) \
+do { \
+ radeon_cs_write_table(b_l_rmesa->cmdbuf.cs, ptr, n); \
+} while(0)
+
+/**
+ * Write a relocated dword to the command buffer.
+ */
+#define R600_OUT_BATCH_RELOC(data, bo, offset, rd, wd, flags) \
+ do { \
+ if (0 && offset) { \
+ fprintf(stderr, "(%s:%s:%d) offset : %d\n", \
+ __FILE__, __FUNCTION__, __LINE__, offset); \
+ } \
+ radeon_cs_write_reloc(b_l_rmesa->cmdbuf.cs, \
+ bo, rd, wd, flags); \
+ } while(0)
+
+/* R600/R700 */
+#define R600_OUT_BATCH_REGS(reg, num) \
+do { \
+ if ((reg) >= R600_SET_CONFIG_REG_OFFSET && (reg) < R600_SET_CONFIG_REG_END) { \
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CONFIG_REG, (num))); \
+ R600_OUT_BATCH(((reg) - R600_SET_CONFIG_REG_OFFSET) >> 2); \
+ } else if ((reg) >= R600_SET_CONTEXT_REG_OFFSET && (reg) < R600_SET_CONTEXT_REG_END) { \
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CONTEXT_REG, (num))); \
+ R600_OUT_BATCH(((reg) - R600_SET_CONTEXT_REG_OFFSET) >> 2); \
+ } else if ((reg) >= R600_SET_ALU_CONST_OFFSET && (reg) < R600_SET_ALU_CONST_END) { \
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_ALU_CONST, (num))); \
+ R600_OUT_BATCH(((reg) - R600_SET_ALU_CONST_OFFSET) >> 2); \
+ } else if ((reg) >= R600_SET_RESOURCE_OFFSET && (reg) < R600_SET_RESOURCE_END) { \
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_RESOURCE, (num))); \
+ R600_OUT_BATCH(((reg) - R600_SET_RESOURCE_OFFSET) >> 2); \
+ } else if ((reg) >= R600_SET_SAMPLER_OFFSET && (reg) < R600_SET_SAMPLER_END) { \
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_SAMPLER, (num))); \
+ R600_OUT_BATCH(((reg) - R600_SET_SAMPLER_OFFSET) >> 2); \
+ } else if ((reg) >= R600_SET_CTL_CONST_OFFSET && (reg) < R600_SET_CTL_CONST_END) { \
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, (num))); \
+ R600_OUT_BATCH(((reg) - R600_SET_CTL_CONST_OFFSET) >> 2); \
+ } else if ((reg) >= R600_SET_LOOP_CONST_OFFSET && (reg) < R600_SET_LOOP_CONST_END) { \
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_LOOP_CONST, (num))); \
+ R600_OUT_BATCH(((reg) - R600_SET_LOOP_CONST_OFFSET) >> 2); \
+ } else if ((reg) >= R600_SET_BOOL_CONST_OFFSET && (reg) < R600_SET_BOOL_CONST_END) { \
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_BOOL_CONST, (num))); \
+ R600_OUT_BATCH(((reg) - R600_SET_BOOL_CONST_OFFSET) >> 2); \
+ } else { \
+ R600_OUT_BATCH(CP_PACKET0((reg), (num))); \
+ } \
+} while (0)
+
+/** Single register write to command buffer; requires 3 dwords for most things. */
+#define R600_OUT_BATCH_REGVAL(reg, val) \
+ R600_OUT_BATCH_REGS((reg), 1); \
+ R600_OUT_BATCH((val))
+
+/** Continuous register range write to command buffer; requires 1 dword,
+ * expects count dwords afterwards for register contents. */
+#define R600_OUT_BATCH_REGSEQ(reg, count) \
+ R600_OUT_BATCH_REGS((reg), (count))
+
+extern void r600InitCmdBuf(context_t *r600);
+
+#endif /* __R600_CMDBUF_H__ */
diff --git a/src/mesa/drivers/dri/r600/r600_context.c b/src/mesa/drivers/dri/r600/r600_context.c
new file mode 100644
index 0000000000..07a7bcf11f
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_context.c
@@ -0,0 +1,396 @@
+/*
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/**
+ * \file
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * \author Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+#include "main/glheader.h"
+#include "main/api_arrayelt.h"
+#include "main/context.h"
+#include "main/simple_list.h"
+#include "main/imports.h"
+#include "main/matrix.h"
+#include "main/extensions.h"
+#include "main/state.h"
+#include "main/bufferobj.h"
+#include "main/texobj.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "vbo/vbo.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_vp_build.h"
+
+#include "drivers/common/driverfuncs.h"
+
+#include "radeon_debug.h"
+#include "r600_context.h"
+#include "radeon_common_context.h"
+#include "radeon_span.h"
+#include "r600_cmdbuf.h"
+#include "r600_emit.h"
+#include "radeon_bocs_wrapper.h"
+
+#include "r700_state.h"
+#include "r700_ioctl.h"
+
+
+#include "vblank.h"
+#include "utils.h"
+#include "xmlpool.h" /* for symbolic values of enum-type options */
+
+/* hw_tcl_on derives from future_hw_tcl_on when its safe to change it. */
+int future_hw_tcl_on = 1;
+int hw_tcl_on = 1;
+
+#define need_GL_VERSION_2_0
+#define need_GL_ARB_point_parameters
+#define need_GL_ARB_vertex_program
+#define need_GL_EXT_blend_equation_separate
+#define need_GL_EXT_blend_func_separate
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_gpu_program_parameters
+#define need_GL_EXT_provoking_vertex
+#define need_GL_EXT_secondary_color
+#define need_GL_EXT_stencil_two_side
+#define need_GL_ATI_separate_stencil
+#define need_GL_NV_vertex_program
+
+#include "extension_helper.h"
+
+extern const struct tnl_pipeline_stage *r700_pipeline[];
+
+const struct dri_extension card_extensions[] = {
+ /* *INDENT-OFF* */
+ {"GL_ARB_depth_texture", NULL},
+ {"GL_ARB_fragment_program", NULL},
+ {"GL_ARB_multitexture", NULL},
+ {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions},
+ {"GL_ARB_shadow", NULL},
+ {"GL_ARB_shadow_ambient", NULL},
+ {"GL_ARB_texture_border_clamp", NULL},
+ {"GL_ARB_texture_cube_map", NULL},
+ {"GL_ARB_texture_env_add", NULL},
+ {"GL_ARB_texture_env_combine", NULL},
+ {"GL_ARB_texture_env_crossbar", NULL},
+ {"GL_ARB_texture_env_dot3", NULL},
+ {"GL_ARB_texture_mirrored_repeat", NULL},
+ {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
+ {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions},
+ {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions},
+ {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
+ {"GL_EXT_blend_subtract", NULL},
+ {"GL_EXT_packed_depth_stencil", NULL},
+ {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
+ {"GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions},
+ {"GL_EXT_provoking_vertex", GL_EXT_provoking_vertex_functions },
+ {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
+ {"GL_EXT_shadow_funcs", NULL},
+ {"GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions},
+ {"GL_EXT_stencil_wrap", NULL},
+ {"GL_EXT_texture_edge_clamp", NULL},
+ {"GL_EXT_texture_env_combine", NULL},
+ {"GL_EXT_texture_env_dot3", NULL},
+ {"GL_EXT_texture_filter_anisotropic", NULL},
+ {"GL_EXT_texture_lod_bias", NULL},
+ {"GL_EXT_texture_mirror_clamp", NULL},
+ {"GL_EXT_texture_rectangle", NULL},
+ {"GL_EXT_texture_sRGB", NULL},
+ {"GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions},
+ {"GL_ATI_texture_env_combine3", NULL},
+ {"GL_ATI_texture_mirror_once", NULL},
+ {"GL_MESA_pack_invert", NULL},
+ {"GL_MESA_ycbcr_texture", NULL},
+ {"GL_MESAX_texture_float", NULL},
+ {"GL_NV_blend_square", NULL},
+ {"GL_NV_vertex_program", GL_NV_vertex_program_functions},
+ {"GL_SGIS_generate_mipmap", NULL},
+ {NULL, NULL}
+ /* *INDENT-ON* */
+};
+
+
+const struct dri_extension mm_extensions[] = {
+ { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+ { NULL, NULL }
+};
+
+/**
+ * The GL 2.0 functions are needed to make display lists work with
+ * functions added by GL_ATI_separate_stencil.
+ */
+const struct dri_extension gl_20_extension[] = {
+ {"GL_VERSION_2_0", GL_VERSION_2_0_functions },
+};
+
+
+static void r600RunPipeline(GLcontext * ctx)
+{
+ _mesa_lock_context_textures(ctx);
+
+ if (ctx->NewState)
+ _mesa_update_state_locked(ctx);
+
+ _tnl_run_pipeline(ctx);
+ _mesa_unlock_context_textures(ctx);
+}
+
+static void r600_get_lock(radeonContextPtr rmesa)
+{
+ drm_radeon_sarea_t *sarea = rmesa->sarea;
+
+ if (sarea->ctx_owner != rmesa->dri.hwContext) {
+ sarea->ctx_owner = rmesa->dri.hwContext;
+ if (!rmesa->radeonScreen->kernel_mm)
+ radeon_bo_legacy_texture_age(rmesa->radeonScreen->bom);
+ }
+}
+
+static void r600_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
+{
+ /* please flush pipe do all pending work */
+ /* to be enabled */
+}
+
+static void r600_vtbl_pre_emit_atoms(radeonContextPtr radeon)
+{
+ r700Start3D((context_t *)radeon);
+}
+
+static void r600_fallback(GLcontext *ctx, GLuint bit, GLboolean mode)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ if (mode)
+ context->radeon.Fallback |= bit;
+ else
+ context->radeon.Fallback &= ~bit;
+}
+
+static void r600_init_vtbl(radeonContextPtr radeon)
+{
+ radeon->vtbl.get_lock = r600_get_lock;
+ radeon->vtbl.update_viewport_offset = r700UpdateViewportOffset;
+ radeon->vtbl.emit_cs_header = r600_vtbl_emit_cs_header;
+ radeon->vtbl.swtcl_flush = NULL;
+ radeon->vtbl.pre_emit_atoms = r600_vtbl_pre_emit_atoms;
+ radeon->vtbl.fallback = r600_fallback;
+}
+
+/* Create the device specific rendering context.
+ */
+GLboolean r600CreateContext(const __GLcontextModes * glVisual,
+ __DRIcontextPrivate * driContextPriv,
+ void *sharedContextPrivate)
+{
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
+ struct dd_function_table functions;
+ context_t *r600;
+ GLcontext *ctx;
+
+ assert(glVisual);
+ assert(driContextPriv);
+ assert(screen);
+
+ /* Allocate the R600 context */
+ r600 = (context_t*) CALLOC(sizeof(*r600));
+ if (!r600) {
+ radeon_error("Failed to allocate memory for context.\n");
+ return GL_FALSE;
+ }
+
+ if (!(screen->chip_flags & RADEON_CHIPSET_TCL))
+ hw_tcl_on = future_hw_tcl_on = 0;
+
+ r600_init_vtbl(&r600->radeon);
+ /* Parse configuration files.
+ * Do this here so that initialMaxAnisotropy is set before we create
+ * the default textures.
+ */
+ driParseConfigFiles(&r600->radeon.optionCache, &screen->optionCache,
+ screen->driScreen->myNum, "r600");
+
+ r600->radeon.initialMaxAnisotropy = driQueryOptionf(&r600->radeon.optionCache,
+ "def_max_anisotropy");
+
+ /* Init default driver functions then plug in our R600-specific functions
+ * (the texture functions are especially important)
+ */
+ _mesa_init_driver_functions(&functions);
+
+ r700InitStateFuncs(&functions);
+ r600InitTextureFuncs(&functions);
+ r700InitShaderFuncs(&functions);
+ r700InitIoctlFuncs(&functions);
+
+ if (!radeonInitContext(&r600->radeon, &functions,
+ glVisual, driContextPriv,
+ sharedContextPrivate)) {
+ radeon_error("Initializing context failed.\n");
+ FREE(r600);
+ return GL_FALSE;
+ }
+
+ /* Init r600 context data */
+ /* Set the maximum texture size small enough that we can guarentee that
+ * all texture units can bind a maximal texture and have them both in
+ * texturable memory at once.
+ */
+
+ ctx = r600->radeon.glCtx;
+
+ ctx->Const.MaxTextureImageUnits =
+ driQueryOptioni(&r600->radeon.optionCache, "texture_image_units");
+ ctx->Const.MaxTextureCoordUnits =
+ driQueryOptioni(&r600->radeon.optionCache, "texture_coord_units");
+ ctx->Const.MaxTextureUnits =
+ MIN2(ctx->Const.MaxTextureImageUnits,
+ ctx->Const.MaxTextureCoordUnits);
+ ctx->Const.MaxTextureMaxAnisotropy = 16.0;
+ ctx->Const.MaxTextureLodBias = 16.0;
+
+ ctx->Const.MaxTextureLevels = 13;
+ ctx->Const.MaxTextureRectSize = 4096;
+
+ ctx->Const.MinPointSize = 0x0001 / 8.0;
+ ctx->Const.MinPointSizeAA = 0x0001 / 8.0;
+ ctx->Const.MaxPointSize = 0xffff / 8.0;
+ ctx->Const.MaxPointSizeAA = 0xffff / 8.0;
+
+ ctx->Const.MinLineWidth = 0x0001 / 8.0;
+ ctx->Const.MinLineWidthAA = 0x0001 / 8.0;
+ ctx->Const.MaxLineWidth = 0xffff / 8.0;
+ ctx->Const.MaxLineWidthAA = 0xffff / 8.0;
+
+ /* Needs further modifications */
+#if 0
+ ctx->Const.MaxArrayLockSize =
+ ( /*512 */ RADEON_BUFFER_SIZE * 16 * 1024) / (4 * 4);
+#endif
+
+ ctx->Const.MaxDrawBuffers = 1;
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext(ctx);
+ _vbo_CreateContext(ctx);
+ _tnl_CreateContext(ctx);
+ _swsetup_CreateContext(ctx);
+ _swsetup_Wakeup(ctx);
+ _ae_create_context(ctx);
+
+ /* Install the customized pipeline:
+ */
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, r700_pipeline);
+
+ /* Try and keep materials and vertices separate:
+ */
+/* _tnl_isolate_materials(ctx, GL_TRUE); */
+
+ /* Configure swrast and TNL to match hardware characteristics:
+ */
+ _swrast_allow_pixel_fog(ctx, GL_FALSE);
+ _swrast_allow_vertex_fog(ctx, GL_TRUE);
+ _tnl_allow_pixel_fog(ctx, GL_FALSE);
+ _tnl_allow_vertex_fog(ctx, GL_TRUE);
+
+ /* currently bogus data */
+ ctx->Const.VertexProgram.MaxInstructions = VSF_MAX_FRAGMENT_LENGTH / 4;
+ ctx->Const.VertexProgram.MaxNativeInstructions =
+ VSF_MAX_FRAGMENT_LENGTH / 4;
+ ctx->Const.VertexProgram.MaxNativeAttribs = 16; /* r420 */
+ ctx->Const.VertexProgram.MaxTemps = 32;
+ ctx->Const.VertexProgram.MaxNativeTemps =
+ /*VSF_MAX_FRAGMENT_TEMPS */ 32;
+ ctx->Const.VertexProgram.MaxNativeParameters = 256; /* r420 */
+ ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
+
+ ctx->Const.FragmentProgram.MaxNativeTemps = PFS_NUM_TEMP_REGS;
+ ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* copy i915... */
+ ctx->Const.FragmentProgram.MaxNativeParameters = PFS_NUM_CONST_REGS;
+ ctx->Const.FragmentProgram.MaxNativeAluInstructions = PFS_MAX_ALU_INST;
+ ctx->Const.FragmentProgram.MaxNativeTexInstructions = PFS_MAX_TEX_INST;
+ ctx->Const.FragmentProgram.MaxNativeInstructions =
+ PFS_MAX_ALU_INST + PFS_MAX_TEX_INST;
+ ctx->Const.FragmentProgram.MaxNativeTexIndirections =
+ PFS_MAX_TEX_INDIRECT;
+ ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* and these are?? */
+ ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
+ ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+
+ radeon_init_debug();
+
+ driInitExtensions(ctx, card_extensions, GL_TRUE);
+ if (r600->radeon.radeonScreen->kernel_mm)
+ driInitExtensions(ctx, mm_extensions, GL_FALSE);
+
+ if (driQueryOptionb
+ (&r600->radeon.optionCache, "disable_stencil_two_side"))
+ _mesa_disable_extension(ctx, "GL_EXT_stencil_two_side");
+
+ if (r600->radeon.glCtx->Mesa_DXTn
+ && !driQueryOptionb(&r600->radeon.optionCache, "disable_s3tc")) {
+ _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+ _mesa_enable_extension(ctx, "GL_S3_s3tc");
+ } else
+ if (driQueryOptionb(&r600->radeon.optionCache, "force_s3tc_enable"))
+ {
+ _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+ }
+
+ radeon_fbo_init(&r600->radeon);
+ radeonInitSpanFuncs( ctx );
+
+ r600InitCmdBuf(r600);
+
+ r700InitState(r600->radeon.glCtx);
+
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = r600RunPipeline;
+
+ if (driQueryOptionb(&r600->radeon.optionCache, "no_rast")) {
+ radeon_warning("disabling 3D acceleration\n");
+#if R200_MERGED
+ FALLBACK(&r600->radeon, RADEON_FALLBACK_DISABLE, 1);
+#endif
+ }
+
+ return GL_TRUE;
+}
+
+
diff --git a/src/mesa/drivers/dri/r600/r600_context.h b/src/mesa/drivers/dri/r600/r600_context.h
new file mode 100644
index 0000000000..c59df7505a
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_context.h
@@ -0,0 +1,208 @@
+/*
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/**
+ * \file
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+#ifndef __R600_CONTEXT_H__
+#define __R600_CONTEXT_H__
+
+#include "tnl/t_vertex.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "dri_util.h"
+#include "texmem.h"
+#include "radeon_common.h"
+
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/colormac.h"
+
+#include "r700_chip.h"
+#include "r600_tex.h"
+#include "r700_oglprog.h"
+#include "r700_vertprog.h"
+
+struct r600_context;
+typedef struct r600_context context_t;
+
+#include "main/mm.h"
+
+/************ DMA BUFFERS **************/
+
+/* The blit width for texture uploads
+ */
+#define R600_BLIT_WIDTH_BYTES 1024
+#define R600_MAX_TEXTURE_UNITS 8
+
+struct r600_texture_state {
+ int tc_count; /* number of incoming texture coordinates from VAP */
+};
+
+/* Perhaps more if we store programs in vmem? */
+/* drm_r600_cmd_header_t->vpu->count is unsigned char */
+#define VSF_MAX_FRAGMENT_LENGTH (255*4)
+
+/* Can be tested with colormat currently. */
+#define VSF_MAX_FRAGMENT_TEMPS (14)
+
+#define STATE_R600_WINDOW_DIMENSION (STATE_INTERNAL_DRIVER+0)
+#define STATE_R600_TEXRECT_FACTOR (STATE_INTERNAL_DRIVER+1)
+
+extern int hw_tcl_on;
+
+#define COLOR_IS_RGBA
+#define TAG(x) r600##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+#define PFS_MAX_ALU_INST 64
+#define PFS_MAX_TEX_INST 64
+#define PFS_MAX_TEX_INDIRECT 4
+#define PFS_NUM_TEMP_REGS 32
+#define PFS_NUM_CONST_REGS 16
+
+#define R600_MAX_AOS_ARRAYS 16
+
+#define REG_COORDS 0
+#define REG_COLOR0 1
+#define REG_TEX0 2
+
+#define R600_FALLBACK_NONE 0
+#define R600_FALLBACK_TCL 1
+#define R600_FALLBACK_RAST 2
+
+enum
+{
+ NO_SHIFT = 0,
+ LEFT_SHIFT = 1,
+ RIGHT_SHIFT = 2,
+};
+
+struct r600_hw_state {
+ struct radeon_state_atom sq;
+ struct radeon_state_atom db;
+ struct radeon_state_atom stencil;
+ struct radeon_state_atom db_target;
+ struct radeon_state_atom sc;
+ struct radeon_state_atom scissor;
+ struct radeon_state_atom aa;
+ struct radeon_state_atom cl;
+ struct radeon_state_atom gb;
+ struct radeon_state_atom ucp;
+ struct radeon_state_atom su;
+ struct radeon_state_atom poly;
+ struct radeon_state_atom cb;
+ struct radeon_state_atom clrcmp;
+ struct radeon_state_atom blnd;
+ struct radeon_state_atom blnd_clr;
+ struct radeon_state_atom cb_target;
+ struct radeon_state_atom sx;
+ struct radeon_state_atom vgt;
+ struct radeon_state_atom spi;
+ struct radeon_state_atom vpt;
+
+ struct radeon_state_atom fs;
+ struct radeon_state_atom vs;
+ struct radeon_state_atom ps;
+
+ struct radeon_state_atom vs_consts;
+ struct radeon_state_atom ps_consts;
+
+ struct radeon_state_atom vtx;
+ struct radeon_state_atom tx;
+ struct radeon_state_atom tx_smplr;
+ struct radeon_state_atom tx_brdr_clr;
+};
+
+/**
+ * \brief R600 context structure.
+ */
+struct r600_context {
+ struct radeon_context radeon; /* parent class, must be first */
+
+ /* ------ */
+ R700_CHIP_CONTEXT hw;
+
+ struct r600_hw_state atoms;
+
+ struct r700_vertex_program *selected_vp;
+
+ /* Vertex buffers
+ */
+ GLvector4f dummy_attrib[_TNL_ATTRIB_MAX];
+ GLvector4f *temp_attrib[_TNL_ATTRIB_MAX];
+
+};
+
+#define R700_CONTEXT(ctx) ((context_t *)(ctx->DriverCtx))
+#define GL_CONTEXT(context) ((GLcontext *)(context->radeon.glCtx))
+
+extern GLboolean r600CreateContext(const __GLcontextModes * glVisual,
+ __DRIcontextPrivate * driContextPriv,
+ void *sharedContextPrivate);
+
+#define R700_CONTEXT_STATES(context) ((R700_CHIP_CONTEXT *)(&context->hw))
+
+#define R600_NEWPRIM( rmesa ) \
+do { \
+ if ( rmesa->radeon.dma.flush ) \
+ rmesa->radeon.dma.flush( rmesa->radeon.glCtx ); \
+} while (0)
+
+#define R600_STATECHANGE(r600, ATOM) \
+do { \
+ R600_NEWPRIM(r600); \
+ r600->atoms.ATOM.dirty = GL_TRUE; \
+ r600->radeon.hw.is_dirty = GL_TRUE; \
+} while(0)
+
+extern GLboolean r700SyncSurf(context_t *context,
+ struct radeon_bo *pbo,
+ uint32_t read_domain,
+ uint32_t write_domain,
+ uint32_t sync_type);
+
+extern void r700SetupStreams(GLcontext * ctx);
+extern void r700Start3D(context_t *context);
+extern void r600InitAtoms(context_t *context);
+
+#define RADEON_D_CAPTURE 0
+#define RADEON_D_PLAYBACK 1
+#define RADEON_D_PLAYBACK_RAW 2
+#define RADEON_D_T 3
+
+#define r600PackFloat32 radeonPackFloat32
+#define r600PackFloat24 radeonPackFloat24
+
+#endif /* __R600_CONTEXT_H__ */
diff --git a/src/mesa/drivers/dri/r600/r600_emit.c b/src/mesa/drivers/dri/r600/r600_emit.c
new file mode 100644
index 0000000000..5c250c2418
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_emit.c
@@ -0,0 +1,117 @@
+/**************************************************************************
+
+Copyright 2008, 2009 Advanced Micro Devices Inc. (AMD)
+
+Copyright (C) Advanced Micro Devices Inc. (AMD) 2009. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/colormac.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/image.h"
+
+#include "swrast_setup/swrast_setup.h"
+#include "math/m_translate.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+#include "r600_context.h"
+#include "r600_emit.h"
+
+void r600EmitCacheFlush(context_t *rmesa)
+{
+}
+
+GLboolean r600EmitShader(GLcontext * ctx,
+ void ** shaderbo,
+ GLvoid * data,
+ int sizeinDWORD,
+ char * szShaderUsage)
+{
+ radeonContextPtr radeonctx = RADEON_CONTEXT(ctx);
+ struct radeon_bo * pbo;
+ uint32_t *out;
+shader_again_alloc:
+ pbo = radeon_bo_open(radeonctx->radeonScreen->bom,
+ 0,
+ sizeinDWORD * 4,
+ 256,
+ RADEON_GEM_DOMAIN_GTT,
+ 0);
+
+ radeon_print(RADEON_SHADER, RADEON_NORMAL, "%s %p size %d: %s\n", __func__, pbo, sizeinDWORD, szShaderUsage);
+
+ if (!pbo) {
+ radeon_print(RADEON_MEMORY | RADEON_CS, RADEON_IMPORTANT, "No memory for buffer object. Flushing command buffer.\n");
+ rcommonFlushCmdBuf(radeonctx, __FUNCTION__);
+ goto shader_again_alloc;
+ }
+
+ radeon_cs_space_add_persistent_bo(radeonctx->cmdbuf.cs,
+ pbo,
+ RADEON_GEM_DOMAIN_GTT, 0);
+
+ if (radeon_cs_space_check_with_bo(radeonctx->cmdbuf.cs,
+ pbo,
+ RADEON_GEM_DOMAIN_GTT, 0)) {
+ radeon_error("failure to revalidate BOs - badness\n");
+ return GL_FALSE;
+ }
+
+ radeon_bo_map(pbo, 1);
+
+ out = (uint32_t*)(pbo->ptr);
+
+ memcpy(out, data, sizeinDWORD * 4);
+
+ radeon_bo_unmap(pbo);
+
+ *shaderbo = (void*)pbo;
+
+ return GL_TRUE;
+}
+
+GLboolean r600DeleteShader(GLcontext * ctx,
+ void * shaderbo)
+{
+ struct radeon_bo * pbo = (struct radeon_bo *)shaderbo;
+
+ radeon_print(RADEON_SHADER, RADEON_NORMAL, "%s: %p\n", __func__, pbo);
+
+ if (pbo) {
+ if (pbo->ptr)
+ radeon_bo_unmap(pbo);
+ radeon_bo_unref(pbo); /* when bo->cref <= 0, bo will be bo_free */
+ }
+
+ return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/r300/radeon_state.h b/src/mesa/drivers/dri/r600/r600_emit.h
index 821cb40c7e..661774d11e 100644
--- a/src/mesa/drivers/dri/r300/radeon_state.h
+++ b/src/mesa/drivers/dri/r600/r600_emit.h
@@ -1,5 +1,8 @@
-/*
-Copyright (C) 2004 Nicolai Haehnle. All Rights Reserved.
+/**************************************************************************
+
+Copyright 2008, 2009 Advanced Micro Devices Inc. (AMD)
+
+Copyright (C) Advanced Micro Devices Inc. (AMD) 2009. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -25,19 +28,28 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
* Authors:
- * Nicolai Haehnle <prefect_@gmx.net>
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
*/
-#ifndef __RADEON_STATE_H__
-#define __RADEON_STATE_H__
-extern void radeonRecalcScissorRects(radeonContextPtr radeon);
-extern void radeonSetCliprects(radeonContextPtr radeon);
-extern void radeonUpdateScissor(GLcontext* ctx);
+#ifndef __R600_EMIT_H__
+#define __R600_EMIT_H__
+
+#include "main/glheader.h"
+#include "r600_context.h"
+#include "r600_cmdbuf.h"
+#include "radeon_reg.h"
+
+void r600EmitCacheFlush(context_t *rmesa);
-extern void radeonEnable(GLcontext* ctx, GLenum cap, GLboolean state);
+extern GLboolean r600EmitShader(GLcontext * ctx,
+ void ** shaderbo,
+ GLvoid * data,
+ int sizeinDWORD,
+ char * szShaderUsage);
-extern void radeonInitState(radeonContextPtr radeon);
-extern void radeonInitStateFuncs(struct dd_function_table* functions);
+extern GLboolean r600DeleteShader(GLcontext * ctx,
+ void * shaderbo);
#endif
diff --git a/src/mesa/drivers/dri/r600/r600_reg.h b/src/mesa/drivers/dri/r600/r600_reg.h
new file mode 100644
index 0000000000..ffe5ee4f74
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_reg.h
@@ -0,0 +1,121 @@
+/*
+ * RadeonHD R6xx, R7xx Register documentation
+ *
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2008-2009 Matthias Hopf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _R600_REG_H_
+#define _R600_REG_H_
+
+/*
+ * Register definitions
+ */
+
+#include "r600_reg_auto_r6xx.h"
+#include "r600_reg_r6xx.h"
+#include "r600_reg_r7xx.h"
+
+
+/* SET_*_REG offsets + ends */
+enum
+{
+ SET_CONFIG_REG_offset = 0x00008000,
+ SET_CONFIG_REG_end = 0x0000ac00,
+ SET_CONTEXT_REG_offset = 0x00028000,
+ SET_CONTEXT_REG_end = 0x00029000,
+ SET_ALU_CONST_offset = 0x00030000,
+ SET_ALU_CONST_end = 0x00032000,
+ SET_RESOURCE_offset = 0x00038000,
+ SET_RESOURCE_end = 0x0003c000,
+ SET_SAMPLER_offset = 0x0003c000,
+ SET_SAMPLER_end = 0x0003cff0,
+ SET_CTL_CONST_offset = 0x0003cff0,
+ SET_CTL_CONST_end = 0x0003e200,
+ SET_LOOP_CONST_offset = 0x0003e200,
+ SET_LOOP_CONST_end = 0x0003e380,
+ SET_BOOL_CONST_offset = 0x0003e380,
+ SET_BOOL_CONST_end = 0x00040000,
+};
+
+/* packet3 IT_SURFACE_BASE_UPDATE bits */
+enum
+{
+ DEPTH_BASE = (1 << 0),
+ COLOR0_BASE = (1 << 1),
+ COLOR1_BASE = (1 << 2),
+ COLOR2_BASE = (1 << 3),
+ COLOR3_BASE = (1 << 4),
+ COLOR4_BASE = (1 << 5),
+ COLOR5_BASE = (1 << 6),
+ COLOR6_BASE = (1 << 7),
+ COLOR7_BASE = (1 << 8),
+ STRMOUT_BASE0 = (1 << 9),
+ STRMOUT_BASE1 = (1 << 10),
+ STRMOUT_BASE2 = (1 << 11),
+ STRMOUT_BASE3 = (1 << 12),
+ COHER_BASE0 = (1 << 13),
+ COHER_BASE1 = (1 << 14),
+};
+
+/* Packet3 commands */
+enum
+{
+ IT_NOP = 0x10,
+ IT_INDIRECT_BUFFER_END = 0x17,
+ IT_SET_PREDICATION = 0x20,
+ IT_REG_RMW = 0x21,
+ IT_COND_EXEC = 0x22,
+ IT_PRED_EXEC = 0x23,
+ IT_START_3D_CMDBUF = 0x24,
+ IT_DRAW_INDEX_2 = 0x27,
+ IT_CONTEXT_CONTROL = 0x28,
+ IT_DRAW_INDEX_IMMD_BE = 0x29,
+ IT_INDEX_TYPE = 0x2A,
+ IT_DRAW_INDEX = 0x2B,
+ IT_DRAW_INDEX_AUTO = 0x2D,
+ IT_DRAW_INDEX_IMMD = 0x2E,
+ IT_NUM_INSTANCES = 0x2F,
+ IT_STRMOUT_BUFFER_UPDATE = 0x34,
+ IT_INDIRECT_BUFFER_MP = 0x38,
+ IT_MEM_SEMAPHORE = 0x39,
+ IT_MPEG_INDEX = 0x3A,
+ IT_WAIT_REG_MEM = 0x3C,
+ IT_MEM_WRITE = 0x3D,
+ IT_INDIRECT_BUFFER = 0x32,
+ IT_CP_INTERRUPT = 0x40,
+ IT_SURFACE_SYNC = 0x43,
+ IT_ME_INITIALIZE = 0x44,
+ IT_COND_WRITE = 0x45,
+ IT_EVENT_WRITE = 0x46,
+ IT_EVENT_WRITE_EOP = 0x47,
+ IT_ONE_REG_WRITE = 0x57,
+ IT_SET_CONFIG_REG = 0x68,
+ IT_SET_CONTEXT_REG = 0x69,
+ IT_SET_ALU_CONST = 0x6A,
+ IT_SET_BOOL_CONST = 0x6B,
+ IT_SET_LOOP_CONST = 0x6C,
+ IT_SET_RESOURCE = 0x6D,
+ IT_SET_SAMPLER = 0x6E,
+ IT_SET_CTL_CONST = 0x6F,
+ IT_SURFACE_BASE_UPDATE = 0x73,
+};
+
+#endif
diff --git a/src/mesa/drivers/dri/r600/r600_reg_auto_r6xx.h b/src/mesa/drivers/dri/r600/r600_reg_auto_r6xx.h
new file mode 100644
index 0000000000..9d5aa3c7e4
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_reg_auto_r6xx.h
@@ -0,0 +1,3087 @@
+/*
+ * RadeonHD R6xx, R7xx Register documentation
+ *
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2008-2009 Matthias Hopf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _AUTOREGS
+#define _AUTOREGS
+
+enum {
+
+ VGT_VTX_VECT_EJECT_REG = 0x000088b0,
+ PRIM_COUNT_mask = 0x3ff << 0,
+ PRIM_COUNT_shift = 0,
+ VGT_LAST_COPY_STATE = 0x000088c0,
+ SRC_STATE_ID_mask = 0x07 << 0,
+ SRC_STATE_ID_shift = 0,
+ DST_STATE_ID_mask = 0x07 << 16,
+ DST_STATE_ID_shift = 16,
+ VGT_CACHE_INVALIDATION = 0x000088c4,
+ CACHE_INVALIDATION_mask = 0x03 << 0,
+ CACHE_INVALIDATION_shift = 0,
+ VC_ONLY = 0x00,
+ TC_ONLY = 0x01,
+ VC_AND_TC = 0x02,
+ VS_NO_EXTRA_BUFFER_bit = 1 << 5,
+ VGT_GS_PER_ES = 0x000088c8,
+ VGT_ES_PER_GS = 0x000088cc,
+ VGT_GS_VERTEX_REUSE = 0x000088d4,
+ VERT_REUSE_mask = 0x1f << 0,
+ VERT_REUSE_shift = 0,
+ VGT_MC_LAT_CNTL = 0x000088d8,
+ MC_TIME_STAMP_RES_mask = 0x03 << 0,
+ MC_TIME_STAMP_RES_shift = 0,
+ X_0_992_MAX_LATENCY = 0x00,
+ X_0_496_MAX_LATENCY = 0x01,
+ X_0_248_MAX_LATENCY = 0x02,
+ X_0_124_MAX_LATENCY = 0x03,
+ VGT_GS_PER_VS = 0x000088e8,
+ GS_PER_VS_mask = 0x0f << 0,
+ GS_PER_VS_shift = 0,
+ VGT_CNTL_STATUS = 0x000088f0,
+ VGT_OUT_INDX_BUSY_bit = 1 << 0,
+ VGT_OUT_BUSY_bit = 1 << 1,
+ VGT_PT_BUSY_bit = 1 << 2,
+ VGT_TE_BUSY_bit = 1 << 3,
+ VGT_VR_BUSY_bit = 1 << 4,
+ VGT_GRP_BUSY_bit = 1 << 5,
+ VGT_DMA_REQ_BUSY_bit = 1 << 6,
+ VGT_DMA_BUSY_bit = 1 << 7,
+ VGT_GS_BUSY_bit = 1 << 8,
+ VGT_BUSY_bit = 1 << 9,
+ VGT_PRIMITIVE_TYPE = 0x00008958,
+ VGT_PRIMITIVE_TYPE__PRIM_TYPE_mask = 0x3f << 0,
+ VGT_PRIMITIVE_TYPE__PRIM_TYPE_shift = 0,
+ DI_PT_NONE = 0x00,
+ DI_PT_POINTLIST = 0x01,
+ DI_PT_LINELIST = 0x02,
+ DI_PT_LINESTRIP = 0x03,
+ DI_PT_TRILIST = 0x04,
+ DI_PT_TRIFAN = 0x05,
+ DI_PT_TRISTRIP = 0x06,
+ DI_PT_UNUSED_0 = 0x07,
+ DI_PT_UNUSED_1 = 0x08,
+ DI_PT_UNUSED_2 = 0x09,
+ DI_PT_LINELIST_ADJ = 0x0a,
+ DI_PT_LINESTRIP_ADJ = 0x0b,
+ DI_PT_TRILIST_ADJ = 0x0c,
+ DI_PT_TRISTRIP_ADJ = 0x0d,
+ DI_PT_UNUSED_3 = 0x0e,
+ DI_PT_UNUSED_4 = 0x0f,
+ DI_PT_TRI_WITH_WFLAGS = 0x10,
+ DI_PT_RECTLIST = 0x11,
+ DI_PT_LINELOOP = 0x12,
+ DI_PT_QUADLIST = 0x13,
+ DI_PT_QUADSTRIP = 0x14,
+ DI_PT_POLYGON = 0x15,
+ DI_PT_2D_COPY_RECT_LIST_V0 = 0x16,
+ DI_PT_2D_COPY_RECT_LIST_V1 = 0x17,
+ DI_PT_2D_COPY_RECT_LIST_V2 = 0x18,
+ DI_PT_2D_COPY_RECT_LIST_V3 = 0x19,
+ DI_PT_2D_FILL_RECT_LIST = 0x1a,
+ DI_PT_2D_LINE_STRIP = 0x1b,
+ DI_PT_2D_TRI_STRIP = 0x1c,
+ VGT_INDEX_TYPE = 0x0000895c,
+ INDEX_TYPE_mask = 0x03 << 0,
+ INDEX_TYPE_shift = 0,
+ DI_INDEX_SIZE_16_BIT = 0x00,
+ DI_INDEX_SIZE_32_BIT = 0x01,
+ VGT_STRMOUT_BUFFER_FILLED_SIZE_0 = 0x00008960,
+ VGT_STRMOUT_BUFFER_FILLED_SIZE_1 = 0x00008964,
+ VGT_STRMOUT_BUFFER_FILLED_SIZE_2 = 0x00008968,
+ VGT_STRMOUT_BUFFER_FILLED_SIZE_3 = 0x0000896c,
+ VGT_NUM_INDICES = 0x00008970,
+ VGT_NUM_INSTANCES = 0x00008974,
+ PA_CL_CNTL_STATUS = 0x00008a10,
+ CL_BUSY_bit = 1 << 31,
+ PA_CL_ENHANCE = 0x00008a14,
+ CLIP_VTX_REORDER_ENA_bit = 1 << 0,
+ NUM_CLIP_SEQ_mask = 0x03 << 1,
+ NUM_CLIP_SEQ_shift = 1,
+ CLIPPED_PRIM_SEQ_STALL_bit = 1 << 3,
+ VE_NAN_PROC_DISABLE_bit = 1 << 4,
+ PA_SU_CNTL_STATUS = 0x00008a50,
+ SU_BUSY_bit = 1 << 31,
+ PA_SC_LINE_STIPPLE_STATE = 0x00008b10,
+ CURRENT_PTR_mask = 0x0f << 0,
+ CURRENT_PTR_shift = 0,
+ CURRENT_COUNT_mask = 0xff << 8,
+ CURRENT_COUNT_shift = 8,
+ PA_SC_MULTI_CHIP_CNTL = 0x00008b20,
+ LOG2_NUM_CHIPS_mask = 0x07 << 0,
+ LOG2_NUM_CHIPS_shift = 0,
+ MULTI_CHIP_TILE_SIZE_mask = 0x03 << 3,
+ MULTI_CHIP_TILE_SIZE_shift = 3,
+ X_16_X_16_PIXEL_TILE_PER_CHIP = 0x00,
+ X_32_X_32_PIXEL_TILE_PER_CHIP = 0x01,
+ X_64_X_64_PIXEL_TILE_PER_CHIP = 0x02,
+ X_128X128_PIXEL_TILE_PER_CHIP = 0x03,
+ CHIP_TILE_X_LOC_mask = 0x07 << 5,
+ CHIP_TILE_X_LOC_shift = 5,
+ CHIP_TILE_Y_LOC_mask = 0x07 << 8,
+ CHIP_TILE_Y_LOC_shift = 8,
+ CHIP_SUPER_TILE_B_bit = 1 << 11,
+ PA_SC_AA_SAMPLE_LOCS_2S = 0x00008b40,
+ S0_X_mask = 0x0f << 0,
+ S0_X_shift = 0,
+ S0_Y_mask = 0x0f << 4,
+ S0_Y_shift = 4,
+ S1_X_mask = 0x0f << 8,
+ S1_X_shift = 8,
+ S1_Y_mask = 0x0f << 12,
+ S1_Y_shift = 12,
+ PA_SC_AA_SAMPLE_LOCS_4S = 0x00008b44,
+/* S0_X_mask = 0x0f << 0, */
+/* S0_X_shift = 0, */
+/* S0_Y_mask = 0x0f << 4, */
+/* S0_Y_shift = 4, */
+/* S1_X_mask = 0x0f << 8, */
+/* S1_X_shift = 8, */
+/* S1_Y_mask = 0x0f << 12, */
+/* S1_Y_shift = 12, */
+ S2_X_mask = 0x0f << 16,
+ S2_X_shift = 16,
+ S2_Y_mask = 0x0f << 20,
+ S2_Y_shift = 20,
+ S3_X_mask = 0x0f << 24,
+ S3_X_shift = 24,
+ S3_Y_mask = 0x0f << 28,
+ S3_Y_shift = 28,
+ PA_SC_AA_SAMPLE_LOCS_8S_WD0 = 0x00008b48,
+/* S0_X_mask = 0x0f << 0, */
+/* S0_X_shift = 0, */
+/* S0_Y_mask = 0x0f << 4, */
+/* S0_Y_shift = 4, */
+/* S1_X_mask = 0x0f << 8, */
+/* S1_X_shift = 8, */
+/* S1_Y_mask = 0x0f << 12, */
+/* S1_Y_shift = 12, */
+/* S2_X_mask = 0x0f << 16, */
+/* S2_X_shift = 16, */
+/* S2_Y_mask = 0x0f << 20, */
+/* S2_Y_shift = 20, */
+/* S3_X_mask = 0x0f << 24, */
+/* S3_X_shift = 24, */
+/* S3_Y_mask = 0x0f << 28, */
+/* S3_Y_shift = 28, */
+ PA_SC_AA_SAMPLE_LOCS_8S_WD1 = 0x00008b4c,
+ S4_X_mask = 0x0f << 0,
+ S4_X_shift = 0,
+ S4_Y_mask = 0x0f << 4,
+ S4_Y_shift = 4,
+ S5_X_mask = 0x0f << 8,
+ S5_X_shift = 8,
+ S5_Y_mask = 0x0f << 12,
+ S5_Y_shift = 12,
+ S6_X_mask = 0x0f << 16,
+ S6_X_shift = 16,
+ S6_Y_mask = 0x0f << 20,
+ S6_Y_shift = 20,
+ S7_X_mask = 0x0f << 24,
+ S7_X_shift = 24,
+ S7_Y_mask = 0x0f << 28,
+ S7_Y_shift = 28,
+ PA_SC_CNTL_STATUS = 0x00008be0,
+ MPASS_OVERFLOW_bit = 1 << 30,
+ PA_SC_ENHANCE = 0x00008bf0,
+ FORCE_EOV_MAX_CLK_CNT_mask = 0xfff << 0,
+ FORCE_EOV_MAX_CLK_CNT_shift = 0,
+ FORCE_EOV_MAX_TILE_CNT_mask = 0xfff << 12,
+ FORCE_EOV_MAX_TILE_CNT_shift = 12,
+ SQ_CONFIG = 0x00008c00,
+ VC_ENABLE_bit = 1 << 0,
+ EXPORT_SRC_C_bit = 1 << 1,
+ DX9_CONSTS_bit = 1 << 2,
+ ALU_INST_PREFER_VECTOR_bit = 1 << 3,
+ SQ_CONFIG__DX10_CLAMP_bit = 1 << 4,
+ ALU_PREFER_ONE_WATERFALL_bit = 1 << 5,
+ ALU_MAX_ONE_WATERFALL_bit = 1 << 6,
+ CLAUSE_SEQ_PRIO_mask = 0x03 << 8,
+ CLAUSE_SEQ_PRIO_shift = 8,
+ SQ_CL_PRIO_RND_ROBIN = 0x00,
+ SQ_CL_PRIO_MACRO_SEQ = 0x01,
+ SQ_CL_PRIO_NONE = 0x02,
+ PS_PRIO_mask = 0x03 << 24,
+ PS_PRIO_shift = 24,
+ VS_PRIO_mask = 0x03 << 26,
+ VS_PRIO_shift = 26,
+ GS_PRIO_mask = 0x03 << 28,
+ GS_PRIO_shift = 28,
+ ES_PRIO_mask = 0x03 << 30,
+ ES_PRIO_shift = 30,
+ SQ_GPR_RESOURCE_MGMT_1 = 0x00008c04,
+ NUM_PS_GPRS_mask = 0xff << 0,
+ NUM_PS_GPRS_shift = 0,
+ NUM_VS_GPRS_mask = 0xff << 16,
+ NUM_VS_GPRS_shift = 16,
+ NUM_CLAUSE_TEMP_GPRS_mask = 0x0f << 28,
+ NUM_CLAUSE_TEMP_GPRS_shift = 28,
+ SQ_GPR_RESOURCE_MGMT_2 = 0x00008c08,
+ NUM_GS_GPRS_mask = 0xff << 0,
+ NUM_GS_GPRS_shift = 0,
+ NUM_ES_GPRS_mask = 0xff << 16,
+ NUM_ES_GPRS_shift = 16,
+ SQ_THREAD_RESOURCE_MGMT = 0x00008c0c,
+ NUM_PS_THREADS_mask = 0xff << 0,
+ NUM_PS_THREADS_shift = 0,
+ NUM_VS_THREADS_mask = 0xff << 8,
+ NUM_VS_THREADS_shift = 8,
+ NUM_GS_THREADS_mask = 0xff << 16,
+ NUM_GS_THREADS_shift = 16,
+ NUM_ES_THREADS_mask = 0xff << 24,
+ NUM_ES_THREADS_shift = 24,
+ SQ_STACK_RESOURCE_MGMT_1 = 0x00008c10,
+ NUM_PS_STACK_ENTRIES_mask = 0xfff << 0,
+ NUM_PS_STACK_ENTRIES_shift = 0,
+ NUM_VS_STACK_ENTRIES_mask = 0xfff << 16,
+ NUM_VS_STACK_ENTRIES_shift = 16,
+ SQ_STACK_RESOURCE_MGMT_2 = 0x00008c14,
+ NUM_GS_STACK_ENTRIES_mask = 0xfff << 0,
+ NUM_GS_STACK_ENTRIES_shift = 0,
+ NUM_ES_STACK_ENTRIES_mask = 0xfff << 16,
+ NUM_ES_STACK_ENTRIES_shift = 16,
+ SQ_ESGS_RING_BASE = 0x00008c40,
+ SQ_ESGS_RING_SIZE = 0x00008c44,
+ SQ_GSVS_RING_BASE = 0x00008c48,
+ SQ_GSVS_RING_SIZE = 0x00008c4c,
+ SQ_ESTMP_RING_BASE = 0x00008c50,
+ SQ_ESTMP_RING_SIZE = 0x00008c54,
+ SQ_GSTMP_RING_BASE = 0x00008c58,
+ SQ_GSTMP_RING_SIZE = 0x00008c5c,
+ SQ_VSTMP_RING_BASE = 0x00008c60,
+ SQ_VSTMP_RING_SIZE = 0x00008c64,
+ SQ_PSTMP_RING_BASE = 0x00008c68,
+ SQ_PSTMP_RING_SIZE = 0x00008c6c,
+ SQ_FBUF_RING_BASE = 0x00008c70,
+ SQ_FBUF_RING_SIZE = 0x00008c74,
+ SQ_REDUC_RING_BASE = 0x00008c78,
+ SQ_REDUC_RING_SIZE = 0x00008c7c,
+ SQ_ALU_WORD1_OP3 = 0x00008dfc,
+ SRC2_SEL_mask = 0x1ff << 0,
+ SRC2_SEL_shift = 0,
+ SQ_ALU_SRC_0 = 0xf8,
+ SQ_ALU_SRC_1 = 0xf9,
+ SQ_ALU_SRC_1_INT = 0xfa,
+ SQ_ALU_SRC_M_1_INT = 0xfb,
+ SQ_ALU_SRC_0_5 = 0xfc,
+ SQ_ALU_SRC_LITERAL = 0xfd,
+ SQ_ALU_SRC_PV = 0xfe,
+ SQ_ALU_SRC_PS = 0xff,
+ SRC2_REL_bit = 1 << 9,
+ SRC2_CHAN_mask = 0x03 << 10,
+ SRC2_CHAN_shift = 10,
+ SQ_CHAN_X = 0x00,
+ SQ_CHAN_Y = 0x01,
+ SQ_CHAN_Z = 0x02,
+ SQ_CHAN_W = 0x03,
+ SRC2_NEG_bit = 1 << 12,
+ SQ_ALU_WORD1_OP3__ALU_INST_mask = 0x1f << 13,
+ SQ_ALU_WORD1_OP3__ALU_INST_shift = 13,
+ SQ_OP3_INST_MUL_LIT = 0x0c,
+ SQ_OP3_INST_MUL_LIT_M2 = 0x0d,
+ SQ_OP3_INST_MUL_LIT_M4 = 0x0e,
+ SQ_OP3_INST_MUL_LIT_D2 = 0x0f,
+ SQ_OP3_INST_MULADD = 0x10,
+ SQ_OP3_INST_MULADD_M2 = 0x11,
+ SQ_OP3_INST_MULADD_M4 = 0x12,
+ SQ_OP3_INST_MULADD_D2 = 0x13,
+ SQ_OP3_INST_MULADD_IEEE = 0x14,
+ SQ_OP3_INST_MULADD_IEEE_M2 = 0x15,
+ SQ_OP3_INST_MULADD_IEEE_M4 = 0x16,
+ SQ_OP3_INST_MULADD_IEEE_D2 = 0x17,
+ SQ_OP3_INST_CNDE = 0x18,
+ SQ_OP3_INST_CNDGT = 0x19,
+ SQ_OP3_INST_CNDGE = 0x1a,
+ SQ_OP3_INST_CNDE_INT = 0x1c,
+ SQ_OP3_INST_CNDGT_INT = 0x1d,
+ SQ_OP3_INST_CNDGE_INT = 0x1e,
+ SQ_TEX_WORD2 = 0x00008dfc,
+ OFFSET_X_mask = 0x1f << 0,
+ OFFSET_X_shift = 0,
+ OFFSET_Y_mask = 0x1f << 5,
+ OFFSET_Y_shift = 5,
+ OFFSET_Z_mask = 0x1f << 10,
+ OFFSET_Z_shift = 10,
+ SAMPLER_ID_mask = 0x1f << 15,
+ SAMPLER_ID_shift = 15,
+ SQ_TEX_WORD2__SRC_SEL_X_mask = 0x07 << 20,
+ SQ_TEX_WORD2__SRC_SEL_X_shift = 20,
+ SQ_SEL_X = 0x00,
+ SQ_SEL_Y = 0x01,
+ SQ_SEL_Z = 0x02,
+ SQ_SEL_W = 0x03,
+ SQ_SEL_0 = 0x04,
+ SQ_SEL_1 = 0x05,
+ SRC_SEL_Y_mask = 0x07 << 23,
+ SRC_SEL_Y_shift = 23,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+ SRC_SEL_Z_mask = 0x07 << 26,
+ SRC_SEL_Z_shift = 26,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+ SRC_SEL_W_mask = 0x07 << 29,
+ SRC_SEL_W_shift = 29,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+ SQ_CF_ALLOC_EXPORT_WORD1 = 0x00008dfc,
+ BURST_COUNT_mask = 0x0f << 17,
+ BURST_COUNT_shift = 17,
+ END_OF_PROGRAM_bit = 1 << 21,
+ VALID_PIXEL_MODE_bit = 1 << 22,
+ SQ_CF_ALLOC_EXPORT_WORD1__CF_INST_mask = 0x7f << 23,
+ SQ_CF_ALLOC_EXPORT_WORD1__CF_INST_shift = 23,
+ SQ_CF_INST_MEM_STREAM0 = 0x20,
+ SQ_CF_INST_MEM_STREAM1 = 0x21,
+ SQ_CF_INST_MEM_STREAM2 = 0x22,
+ SQ_CF_INST_MEM_STREAM3 = 0x23,
+ SQ_CF_INST_MEM_SCRATCH = 0x24,
+ SQ_CF_INST_MEM_REDUCTION = 0x25,
+ SQ_CF_INST_MEM_RING = 0x26,
+ SQ_CF_INST_EXPORT = 0x27,
+ SQ_CF_INST_EXPORT_DONE = 0x28,
+ WHOLE_QUAD_MODE_bit = 1 << 30,
+ BARRIER_bit = 1 << 31,
+ SQ_CF_ALU_WORD1 = 0x00008dfc,
+ KCACHE_MODE1_mask = 0x03 << 0,
+ KCACHE_MODE1_shift = 0,
+ SQ_CF_KCACHE_NOP = 0x00,
+ SQ_CF_KCACHE_LOCK_1 = 0x01,
+ SQ_CF_KCACHE_LOCK_2 = 0x02,
+ SQ_CF_KCACHE_LOCK_LOOP_INDEX = 0x03,
+ KCACHE_ADDR0_mask = 0xff << 2,
+ KCACHE_ADDR0_shift = 2,
+ KCACHE_ADDR1_mask = 0xff << 10,
+ KCACHE_ADDR1_shift = 10,
+ SQ_CF_ALU_WORD1__COUNT_mask = 0x7f << 18,
+ SQ_CF_ALU_WORD1__COUNT_shift = 18,
+ SQ_CF_ALU_WORD1__ALT_CONST_bit = 1 << 25,
+ SQ_CF_ALU_WORD1__CF_INST_mask = 0x0f << 26,
+ SQ_CF_ALU_WORD1__CF_INST_shift = 26,
+ SQ_CF_INST_ALU = 0x08,
+ SQ_CF_INST_ALU_PUSH_BEFORE = 0x09,
+ SQ_CF_INST_ALU_POP_AFTER = 0x0a,
+ SQ_CF_INST_ALU_POP2_AFTER = 0x0b,
+ SQ_CF_INST_ALU_CONTINUE = 0x0d,
+ SQ_CF_INST_ALU_BREAK = 0x0e,
+ SQ_CF_INST_ALU_ELSE_AFTER = 0x0f,
+/* WHOLE_QUAD_MODE_bit = 1 << 30, */
+/* BARRIER_bit = 1 << 31, */
+ SQ_TEX_WORD1 = 0x00008dfc,
+ SQ_TEX_WORD1__DST_GPR_mask = 0x7f << 0,
+ SQ_TEX_WORD1__DST_GPR_shift = 0,
+ SQ_TEX_WORD1__DST_REL_bit = 1 << 7,
+ SQ_TEX_WORD1__DST_SEL_X_mask = 0x07 << 9,
+ SQ_TEX_WORD1__DST_SEL_X_shift = 9,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+ SQ_SEL_MASK = 0x07,
+ SQ_TEX_WORD1__DST_SEL_Y_mask = 0x07 << 12,
+ SQ_TEX_WORD1__DST_SEL_Y_shift = 12,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SQ_TEX_WORD1__DST_SEL_Z_mask = 0x07 << 15,
+ SQ_TEX_WORD1__DST_SEL_Z_shift = 15,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SQ_TEX_WORD1__DST_SEL_W_mask = 0x07 << 18,
+ SQ_TEX_WORD1__DST_SEL_W_shift = 18,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SQ_TEX_WORD1__LOD_BIAS_mask = 0x7f << 21,
+ SQ_TEX_WORD1__LOD_BIAS_shift = 21,
+ COORD_TYPE_X_bit = 1 << 28,
+ COORD_TYPE_Y_bit = 1 << 29,
+ COORD_TYPE_Z_bit = 1 << 30,
+ COORD_TYPE_W_bit = 1 << 31,
+ SQ_VTX_WORD0 = 0x00008dfc,
+ VTX_INST_mask = 0x1f << 0,
+ VTX_INST_shift = 0,
+ SQ_VTX_INST_FETCH = 0x00,
+ SQ_VTX_INST_SEMANTIC = 0x01,
+ FETCH_TYPE_mask = 0x03 << 5,
+ FETCH_TYPE_shift = 5,
+ SQ_VTX_FETCH_VERTEX_DATA = 0x00,
+ SQ_VTX_FETCH_INSTANCE_DATA = 0x01,
+ SQ_VTX_FETCH_NO_INDEX_OFFSET = 0x02,
+ FETCH_WHOLE_QUAD_bit = 1 << 7,
+ BUFFER_ID_mask = 0xff << 8,
+ BUFFER_ID_shift = 8,
+ SRC_GPR_mask = 0x7f << 16,
+ SRC_GPR_shift = 16,
+ SRC_REL_bit = 1 << 23,
+ SQ_VTX_WORD0__SRC_SEL_X_mask = 0x03 << 24,
+ SQ_VTX_WORD0__SRC_SEL_X_shift = 24,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+ MEGA_FETCH_COUNT_mask = 0x3f << 26,
+ MEGA_FETCH_COUNT_shift = 26,
+ SQ_CF_ALLOC_EXPORT_WORD1_SWIZ = 0x00008dfc,
+ SEL_X_mask = 0x07 << 0,
+ SEL_X_shift = 0,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SEL_Y_mask = 0x07 << 3,
+ SEL_Y_shift = 3,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SEL_Z_mask = 0x07 << 6,
+ SEL_Z_shift = 6,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SEL_W_mask = 0x07 << 9,
+ SEL_W_shift = 9,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SQ_ALU_WORD1 = 0x00008dfc,
+ ENCODING_mask = 0x07 << 15,
+ ENCODING_shift = 15,
+ BANK_SWIZZLE_mask = 0x07 << 18,
+ BANK_SWIZZLE_shift = 18,
+ SQ_ALU_VEC_012 = 0x00,
+ SQ_ALU_VEC_021 = 0x01,
+ SQ_ALU_VEC_120 = 0x02,
+ SQ_ALU_VEC_102 = 0x03,
+ SQ_ALU_VEC_201 = 0x04,
+ SQ_ALU_VEC_210 = 0x05,
+ SQ_ALU_WORD1__DST_GPR_mask = 0x7f << 21,
+ SQ_ALU_WORD1__DST_GPR_shift = 21,
+ SQ_ALU_WORD1__DST_REL_bit = 1 << 28,
+ DST_CHAN_mask = 0x03 << 29,
+ DST_CHAN_shift = 29,
+ CHAN_X = 0x00,
+ CHAN_Y = 0x01,
+ CHAN_Z = 0x02,
+ CHAN_W = 0x03,
+ SQ_ALU_WORD1__CLAMP_bit = 1 << 31,
+ SQ_CF_ALU_WORD0 = 0x00008dfc,
+ SQ_CF_ALU_WORD0__ADDR_mask = 0x3fffff << 0,
+ SQ_CF_ALU_WORD0__ADDR_shift = 0,
+ KCACHE_BANK0_mask = 0x0f << 22,
+ KCACHE_BANK0_shift = 22,
+ KCACHE_BANK1_mask = 0x0f << 26,
+ KCACHE_BANK1_shift = 26,
+ KCACHE_MODE0_mask = 0x03 << 30,
+ KCACHE_MODE0_shift = 30,
+/* SQ_CF_KCACHE_NOP = 0x00, */
+/* SQ_CF_KCACHE_LOCK_1 = 0x01, */
+/* SQ_CF_KCACHE_LOCK_2 = 0x02, */
+/* SQ_CF_KCACHE_LOCK_LOOP_INDEX = 0x03, */
+ SQ_VTX_WORD2 = 0x00008dfc,
+ SQ_VTX_WORD2__OFFSET_mask = 0xffff << 0,
+ SQ_VTX_WORD2__OFFSET_shift = 0,
+ SQ_VTX_WORD2__ENDIAN_SWAP_mask = 0x03 << 16,
+ SQ_VTX_WORD2__ENDIAN_SWAP_shift = 16,
+ SQ_ENDIAN_NONE = 0x00,
+ SQ_ENDIAN_8IN16 = 0x01,
+ SQ_ENDIAN_8IN32 = 0x02,
+ CONST_BUF_NO_STRIDE_bit = 1 << 18,
+ MEGA_FETCH_bit = 1 << 19,
+ SQ_VTX_WORD2__ALT_CONST_bit = 1 << 20,
+ SQ_ALU_WORD1_OP2_V2 = 0x00008dfc,
+ SRC0_ABS_bit = 1 << 0,
+ SRC1_ABS_bit = 1 << 1,
+ UPDATE_EXECUTE_MASK_bit = 1 << 2,
+ UPDATE_PRED_bit = 1 << 3,
+ WRITE_MASK_bit = 1 << 4,
+ SQ_ALU_WORD1_OP2_V2__OMOD_mask = 0x03 << 5,
+ SQ_ALU_WORD1_OP2_V2__OMOD_shift = 5,
+ SQ_ALU_OMOD_OFF = 0x00,
+ SQ_ALU_OMOD_M2 = 0x01,
+ SQ_ALU_OMOD_M4 = 0x02,
+ SQ_ALU_OMOD_D2 = 0x03,
+ SQ_ALU_WORD1_OP2_V2__ALU_INST_mask = 0x7ff << 7,
+ SQ_ALU_WORD1_OP2_V2__ALU_INST_shift = 7,
+ SQ_OP2_INST_ADD = 0x00,
+ SQ_OP2_INST_MUL = 0x01,
+ SQ_OP2_INST_MUL_IEEE = 0x02,
+ SQ_OP2_INST_MAX = 0x03,
+ SQ_OP2_INST_MIN = 0x04,
+ SQ_OP2_INST_MAX_DX10 = 0x05,
+ SQ_OP2_INST_MIN_DX10 = 0x06,
+ SQ_OP2_INST_SETE = 0x08,
+ SQ_OP2_INST_SETGT = 0x09,
+ SQ_OP2_INST_SETGE = 0x0a,
+ SQ_OP2_INST_SETNE = 0x0b,
+ SQ_OP2_INST_SETE_DX10 = 0x0c,
+ SQ_OP2_INST_SETGT_DX10 = 0x0d,
+ SQ_OP2_INST_SETGE_DX10 = 0x0e,
+ SQ_OP2_INST_SETNE_DX10 = 0x0f,
+ SQ_OP2_INST_FRACT = 0x10,
+ SQ_OP2_INST_TRUNC = 0x11,
+ SQ_OP2_INST_CEIL = 0x12,
+ SQ_OP2_INST_RNDNE = 0x13,
+ SQ_OP2_INST_FLOOR = 0x14,
+ SQ_OP2_INST_MOVA = 0x15,
+ SQ_OP2_INST_MOVA_FLOOR = 0x16,
+ SQ_OP2_INST_MOVA_INT = 0x18,
+ SQ_OP2_INST_MOV = 0x19,
+ SQ_OP2_INST_NOP = 0x1a,
+ SQ_OP2_INST_PRED_SETGT_UINT = 0x1e,
+ SQ_OP2_INST_PRED_SETGE_UINT = 0x1f,
+ SQ_OP2_INST_PRED_SETE = 0x20,
+ SQ_OP2_INST_PRED_SETGT = 0x21,
+ SQ_OP2_INST_PRED_SETGE = 0x22,
+ SQ_OP2_INST_PRED_SETNE = 0x23,
+ SQ_OP2_INST_PRED_SET_INV = 0x24,
+ SQ_OP2_INST_PRED_SET_POP = 0x25,
+ SQ_OP2_INST_PRED_SET_CLR = 0x26,
+ SQ_OP2_INST_PRED_SET_RESTORE = 0x27,
+ SQ_OP2_INST_PRED_SETE_PUSH = 0x28,
+ SQ_OP2_INST_PRED_SETGT_PUSH = 0x29,
+ SQ_OP2_INST_PRED_SETGE_PUSH = 0x2a,
+ SQ_OP2_INST_PRED_SETNE_PUSH = 0x2b,
+ SQ_OP2_INST_KILLE = 0x2c,
+ SQ_OP2_INST_KILLGT = 0x2d,
+ SQ_OP2_INST_KILLGE = 0x2e,
+ SQ_OP2_INST_KILLNE = 0x2f,
+ SQ_OP2_INST_AND_INT = 0x30,
+ SQ_OP2_INST_OR_INT = 0x31,
+ SQ_OP2_INST_XOR_INT = 0x32,
+ SQ_OP2_INST_NOT_INT = 0x33,
+ SQ_OP2_INST_ADD_INT = 0x34,
+ SQ_OP2_INST_SUB_INT = 0x35,
+ SQ_OP2_INST_MAX_INT = 0x36,
+ SQ_OP2_INST_MIN_INT = 0x37,
+ SQ_OP2_INST_MAX_UINT = 0x38,
+ SQ_OP2_INST_MIN_UINT = 0x39,
+ SQ_OP2_INST_SETE_INT = 0x3a,
+ SQ_OP2_INST_SETGT_INT = 0x3b,
+ SQ_OP2_INST_SETGE_INT = 0x3c,
+ SQ_OP2_INST_SETNE_INT = 0x3d,
+ SQ_OP2_INST_SETGT_UINT = 0x3e,
+ SQ_OP2_INST_SETGE_UINT = 0x3f,
+ SQ_OP2_INST_KILLGT_UINT = 0x40,
+ SQ_OP2_INST_KILLGE_UINT = 0x41,
+ SQ_OP2_INST_PRED_SETE_INT = 0x42,
+ SQ_OP2_INST_PRED_SETGT_INT = 0x43,
+ SQ_OP2_INST_PRED_SETGE_INT = 0x44,
+ SQ_OP2_INST_PRED_SETNE_INT = 0x45,
+ SQ_OP2_INST_KILLE_INT = 0x46,
+ SQ_OP2_INST_KILLGT_INT = 0x47,
+ SQ_OP2_INST_KILLGE_INT = 0x48,
+ SQ_OP2_INST_KILLNE_INT = 0x49,
+ SQ_OP2_INST_PRED_SETE_PUSH_INT = 0x4a,
+ SQ_OP2_INST_PRED_SETGT_PUSH_INT = 0x4b,
+ SQ_OP2_INST_PRED_SETGE_PUSH_INT = 0x4c,
+ SQ_OP2_INST_PRED_SETNE_PUSH_INT = 0x4d,
+ SQ_OP2_INST_PRED_SETLT_PUSH_INT = 0x4e,
+ SQ_OP2_INST_PRED_SETLE_PUSH_INT = 0x4f,
+ SQ_OP2_INST_DOT4 = 0x50,
+ SQ_OP2_INST_DOT4_IEEE = 0x51,
+ SQ_OP2_INST_CUBE = 0x52,
+ SQ_OP2_INST_MAX4 = 0x53,
+ SQ_OP2_INST_MOVA_GPR_INT = 0x60,
+ SQ_OP2_INST_EXP_IEEE = 0x61,
+ SQ_OP2_INST_LOG_CLAMPED = 0x62,
+ SQ_OP2_INST_LOG_IEEE = 0x63,
+ SQ_OP2_INST_RECIP_CLAMPED = 0x64,
+ SQ_OP2_INST_RECIP_FF = 0x65,
+ SQ_OP2_INST_RECIP_IEEE = 0x66,
+ SQ_OP2_INST_RECIPSQRT_CLAMPED = 0x67,
+ SQ_OP2_INST_RECIPSQRT_FF = 0x68,
+ SQ_OP2_INST_RECIPSQRT_IEEE = 0x69,
+ SQ_OP2_INST_SQRT_IEEE = 0x6a,
+ SQ_OP2_INST_FLT_TO_INT = 0x6b,
+ SQ_OP2_INST_INT_TO_FLT = 0x6c,
+ SQ_OP2_INST_UINT_TO_FLT = 0x6d,
+ SQ_OP2_INST_SIN = 0x6e,
+ SQ_OP2_INST_COS = 0x6f,
+ SQ_OP2_INST_ASHR_INT = 0x70,
+ SQ_OP2_INST_LSHR_INT = 0x71,
+ SQ_OP2_INST_LSHL_INT = 0x72,
+ SQ_OP2_INST_MULLO_INT = 0x73,
+ SQ_OP2_INST_MULHI_INT = 0x74,
+ SQ_OP2_INST_MULLO_UINT = 0x75,
+ SQ_OP2_INST_MULHI_UINT = 0x76,
+ SQ_OP2_INST_RECIP_INT = 0x77,
+ SQ_OP2_INST_RECIP_UINT = 0x78,
+ SQ_OP2_INST_FLT_TO_UINT = 0x79,
+ SQ_CF_ALLOC_EXPORT_WORD1_BUF = 0x00008dfc,
+ ARRAY_SIZE_mask = 0xfff << 0,
+ ARRAY_SIZE_shift = 0,
+ COMP_MASK_mask = 0x0f << 12,
+ COMP_MASK_shift = 12,
+ SQ_CF_WORD0 = 0x00008dfc,
+ SQ_CF_ALLOC_EXPORT_WORD0 = 0x00008dfc,
+ ARRAY_BASE_mask = 0x1fff << 0,
+ ARRAY_BASE_shift = 0,
+ SQ_CF_ALLOC_EXPORT_WORD0__TYPE_mask = 0x03 << 13,
+ SQ_CF_ALLOC_EXPORT_WORD0__TYPE_shift = 13,
+ SQ_EXPORT_PIXEL = 0x00,
+ SQ_EXPORT_POS = 0x01,
+ SQ_EXPORT_PARAM = 0x02,
+ X_UNUSED_FOR_SX_EXPORTS = 0x03,
+ RW_GPR_mask = 0x7f << 15,
+ RW_GPR_shift = 15,
+ RW_REL_bit = 1 << 22,
+ INDEX_GPR_mask = 0x7f << 23,
+ INDEX_GPR_shift = 23,
+ ELEM_SIZE_mask = 0x03 << 30,
+ ELEM_SIZE_shift = 30,
+ SQ_VTX_WORD1 = 0x00008dfc,
+ SQ_VTX_WORD1__DST_SEL_X_mask = 0x07 << 9,
+ SQ_VTX_WORD1__DST_SEL_X_shift = 9,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SQ_VTX_WORD1__DST_SEL_Y_mask = 0x07 << 12,
+ SQ_VTX_WORD1__DST_SEL_Y_shift = 12,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SQ_VTX_WORD1__DST_SEL_Z_mask = 0x07 << 15,
+ SQ_VTX_WORD1__DST_SEL_Z_shift = 15,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ SQ_VTX_WORD1__DST_SEL_W_mask = 0x07 << 18,
+ SQ_VTX_WORD1__DST_SEL_W_shift = 18,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+/* SQ_SEL_MASK = 0x07, */
+ USE_CONST_FIELDS_bit = 1 << 21,
+ SQ_VTX_WORD1__DATA_FORMAT_mask = 0x3f << 22,
+ SQ_VTX_WORD1__DATA_FORMAT_shift = 22,
+ SQ_VTX_WORD1__NUM_FORMAT_ALL_mask = 0x03 << 28,
+ SQ_VTX_WORD1__NUM_FORMAT_ALL_shift = 28,
+ SQ_NUM_FORMAT_NORM = 0x00,
+ SQ_NUM_FORMAT_INT = 0x01,
+ SQ_NUM_FORMAT_SCALED = 0x02,
+ SQ_VTX_WORD1__FORMAT_COMP_ALL_bit = 1 << 30,
+ SQ_VTX_WORD1__SRF_MODE_ALL_bit = 1 << 31,
+ SQ_ALU_WORD1_OP2 = 0x00008dfc,
+/* SRC0_ABS_bit = 1 << 0, */
+/* SRC1_ABS_bit = 1 << 1, */
+/* UPDATE_EXECUTE_MASK_bit = 1 << 2, */
+/* UPDATE_PRED_bit = 1 << 3, */
+/* WRITE_MASK_bit = 1 << 4, */
+ FOG_MERGE_bit = 1 << 5,
+ SQ_ALU_WORD1_OP2__OMOD_mask = 0x03 << 6,
+ SQ_ALU_WORD1_OP2__OMOD_shift = 6,
+/* SQ_ALU_OMOD_OFF = 0x00, */
+/* SQ_ALU_OMOD_M2 = 0x01, */
+/* SQ_ALU_OMOD_M4 = 0x02, */
+/* SQ_ALU_OMOD_D2 = 0x03, */
+ SQ_ALU_WORD1_OP2__ALU_INST_mask = 0x3ff << 8,
+ SQ_ALU_WORD1_OP2__ALU_INST_shift = 8,
+/* SQ_OP2_INST_ADD = 0x00, */
+/* SQ_OP2_INST_MUL = 0x01, */
+/* SQ_OP2_INST_MUL_IEEE = 0x02, */
+/* SQ_OP2_INST_MAX = 0x03, */
+/* SQ_OP2_INST_MIN = 0x04, */
+/* SQ_OP2_INST_MAX_DX10 = 0x05, */
+/* SQ_OP2_INST_MIN_DX10 = 0x06, */
+/* SQ_OP2_INST_SETE = 0x08, */
+/* SQ_OP2_INST_SETGT = 0x09, */
+/* SQ_OP2_INST_SETGE = 0x0a, */
+/* SQ_OP2_INST_SETNE = 0x0b, */
+/* SQ_OP2_INST_SETE_DX10 = 0x0c, */
+/* SQ_OP2_INST_SETGT_DX10 = 0x0d, */
+/* SQ_OP2_INST_SETGE_DX10 = 0x0e, */
+/* SQ_OP2_INST_SETNE_DX10 = 0x0f, */
+/* SQ_OP2_INST_FRACT = 0x10, */
+/* SQ_OP2_INST_TRUNC = 0x11, */
+/* SQ_OP2_INST_CEIL = 0x12, */
+/* SQ_OP2_INST_RNDNE = 0x13, */
+/* SQ_OP2_INST_FLOOR = 0x14, */
+/* SQ_OP2_INST_MOVA = 0x15, */
+/* SQ_OP2_INST_MOVA_FLOOR = 0x16, */
+/* SQ_OP2_INST_MOVA_INT = 0x18, */
+/* SQ_OP2_INST_MOV = 0x19, */
+/* SQ_OP2_INST_NOP = 0x1a, */
+/* SQ_OP2_INST_PRED_SETGT_UINT = 0x1e, */
+/* SQ_OP2_INST_PRED_SETGE_UINT = 0x1f, */
+/* SQ_OP2_INST_PRED_SETE = 0x20, */
+/* SQ_OP2_INST_PRED_SETGT = 0x21, */
+/* SQ_OP2_INST_PRED_SETGE = 0x22, */
+/* SQ_OP2_INST_PRED_SETNE = 0x23, */
+/* SQ_OP2_INST_PRED_SET_INV = 0x24, */
+/* SQ_OP2_INST_PRED_SET_POP = 0x25, */
+/* SQ_OP2_INST_PRED_SET_CLR = 0x26, */
+/* SQ_OP2_INST_PRED_SET_RESTORE = 0x27, */
+/* SQ_OP2_INST_PRED_SETE_PUSH = 0x28, */
+/* SQ_OP2_INST_PRED_SETGT_PUSH = 0x29, */
+/* SQ_OP2_INST_PRED_SETGE_PUSH = 0x2a, */
+/* SQ_OP2_INST_PRED_SETNE_PUSH = 0x2b, */
+/* SQ_OP2_INST_KILLE = 0x2c, */
+/* SQ_OP2_INST_KILLGT = 0x2d, */
+/* SQ_OP2_INST_KILLGE = 0x2e, */
+/* SQ_OP2_INST_KILLNE = 0x2f, */
+/* SQ_OP2_INST_AND_INT = 0x30, */
+/* SQ_OP2_INST_OR_INT = 0x31, */
+/* SQ_OP2_INST_XOR_INT = 0x32, */
+/* SQ_OP2_INST_NOT_INT = 0x33, */
+/* SQ_OP2_INST_ADD_INT = 0x34, */
+/* SQ_OP2_INST_SUB_INT = 0x35, */
+/* SQ_OP2_INST_MAX_INT = 0x36, */
+/* SQ_OP2_INST_MIN_INT = 0x37, */
+/* SQ_OP2_INST_MAX_UINT = 0x38, */
+/* SQ_OP2_INST_MIN_UINT = 0x39, */
+/* SQ_OP2_INST_SETE_INT = 0x3a, */
+/* SQ_OP2_INST_SETGT_INT = 0x3b, */
+/* SQ_OP2_INST_SETGE_INT = 0x3c, */
+/* SQ_OP2_INST_SETNE_INT = 0x3d, */
+/* SQ_OP2_INST_SETGT_UINT = 0x3e, */
+/* SQ_OP2_INST_SETGE_UINT = 0x3f, */
+/* SQ_OP2_INST_KILLGT_UINT = 0x40, */
+/* SQ_OP2_INST_KILLGE_UINT = 0x41, */
+/* SQ_OP2_INST_PRED_SETE_INT = 0x42, */
+/* SQ_OP2_INST_PRED_SETGT_INT = 0x43, */
+/* SQ_OP2_INST_PRED_SETGE_INT = 0x44, */
+/* SQ_OP2_INST_PRED_SETNE_INT = 0x45, */
+/* SQ_OP2_INST_KILLE_INT = 0x46, */
+/* SQ_OP2_INST_KILLGT_INT = 0x47, */
+/* SQ_OP2_INST_KILLGE_INT = 0x48, */
+/* SQ_OP2_INST_KILLNE_INT = 0x49, */
+/* SQ_OP2_INST_PRED_SETE_PUSH_INT = 0x4a, */
+/* SQ_OP2_INST_PRED_SETGT_PUSH_INT = 0x4b, */
+/* SQ_OP2_INST_PRED_SETGE_PUSH_INT = 0x4c, */
+/* SQ_OP2_INST_PRED_SETNE_PUSH_INT = 0x4d, */
+/* SQ_OP2_INST_PRED_SETLT_PUSH_INT = 0x4e, */
+/* SQ_OP2_INST_PRED_SETLE_PUSH_INT = 0x4f, */
+/* SQ_OP2_INST_DOT4 = 0x50, */
+/* SQ_OP2_INST_DOT4_IEEE = 0x51, */
+/* SQ_OP2_INST_CUBE = 0x52, */
+/* SQ_OP2_INST_MAX4 = 0x53, */
+/* SQ_OP2_INST_MOVA_GPR_INT = 0x60, */
+/* SQ_OP2_INST_EXP_IEEE = 0x61, */
+/* SQ_OP2_INST_LOG_CLAMPED = 0x62, */
+/* SQ_OP2_INST_LOG_IEEE = 0x63, */
+/* SQ_OP2_INST_RECIP_CLAMPED = 0x64, */
+/* SQ_OP2_INST_RECIP_FF = 0x65, */
+/* SQ_OP2_INST_RECIP_IEEE = 0x66, */
+/* SQ_OP2_INST_RECIPSQRT_CLAMPED = 0x67, */
+/* SQ_OP2_INST_RECIPSQRT_FF = 0x68, */
+/* SQ_OP2_INST_RECIPSQRT_IEEE = 0x69, */
+/* SQ_OP2_INST_SQRT_IEEE = 0x6a, */
+/* SQ_OP2_INST_FLT_TO_INT = 0x6b, */
+/* SQ_OP2_INST_INT_TO_FLT = 0x6c, */
+/* SQ_OP2_INST_UINT_TO_FLT = 0x6d, */
+/* SQ_OP2_INST_SIN = 0x6e, */
+/* SQ_OP2_INST_COS = 0x6f, */
+/* SQ_OP2_INST_ASHR_INT = 0x70, */
+/* SQ_OP2_INST_LSHR_INT = 0x71, */
+/* SQ_OP2_INST_LSHL_INT = 0x72, */
+/* SQ_OP2_INST_MULLO_INT = 0x73, */
+/* SQ_OP2_INST_MULHI_INT = 0x74, */
+/* SQ_OP2_INST_MULLO_UINT = 0x75, */
+/* SQ_OP2_INST_MULHI_UINT = 0x76, */
+/* SQ_OP2_INST_RECIP_INT = 0x77, */
+/* SQ_OP2_INST_RECIP_UINT = 0x78, */
+/* SQ_OP2_INST_FLT_TO_UINT = 0x79, */
+ SQ_CF_WORD1 = 0x00008dfc,
+ POP_COUNT_mask = 0x07 << 0,
+ POP_COUNT_shift = 0,
+ CF_CONST_mask = 0x1f << 3,
+ CF_CONST_shift = 3,
+ COND_mask = 0x03 << 8,
+ COND_shift = 8,
+ SQ_CF_COND_ACTIVE = 0x00,
+ SQ_CF_COND_FALSE = 0x01,
+ SQ_CF_COND_BOOL = 0x02,
+ SQ_CF_COND_NOT_BOOL = 0x03,
+ SQ_CF_WORD1__COUNT_mask = 0x07 << 10,
+ SQ_CF_WORD1__COUNT_shift = 10,
+ CALL_COUNT_mask = 0x3f << 13,
+ CALL_COUNT_shift = 13,
+ COUNT_3_bit = 1 << 19,
+/* END_OF_PROGRAM_bit = 1 << 21, */
+/* VALID_PIXEL_MODE_bit = 1 << 22, */
+ SQ_CF_WORD1__CF_INST_mask = 0x7f << 23,
+ SQ_CF_WORD1__CF_INST_shift = 23,
+ SQ_CF_INST_NOP = 0x00,
+ SQ_CF_INST_TEX = 0x01,
+ SQ_CF_INST_VTX = 0x02,
+ SQ_CF_INST_VTX_TC = 0x03,
+ SQ_CF_INST_LOOP_START = 0x04,
+ SQ_CF_INST_LOOP_END = 0x05,
+ SQ_CF_INST_LOOP_START_DX10 = 0x06,
+ SQ_CF_INST_LOOP_START_NO_AL = 0x07,
+ SQ_CF_INST_LOOP_CONTINUE = 0x08,
+ SQ_CF_INST_LOOP_BREAK = 0x09,
+ SQ_CF_INST_JUMP = 0x0a,
+ SQ_CF_INST_PUSH = 0x0b,
+ SQ_CF_INST_PUSH_ELSE = 0x0c,
+ SQ_CF_INST_ELSE = 0x0d,
+ SQ_CF_INST_POP = 0x0e,
+ SQ_CF_INST_POP_JUMP = 0x0f,
+ SQ_CF_INST_POP_PUSH = 0x10,
+ SQ_CF_INST_POP_PUSH_ELSE = 0x11,
+ SQ_CF_INST_CALL = 0x12,
+ SQ_CF_INST_CALL_FS = 0x13,
+ SQ_CF_INST_RETURN = 0x14,
+ SQ_CF_INST_EMIT_VERTEX = 0x15,
+ SQ_CF_INST_EMIT_CUT_VERTEX = 0x16,
+ SQ_CF_INST_CUT_VERTEX = 0x17,
+ SQ_CF_INST_KILL = 0x18,
+/* WHOLE_QUAD_MODE_bit = 1 << 30, */
+/* BARRIER_bit = 1 << 31, */
+ SQ_VTX_WORD1_SEM = 0x00008dfc,
+ SEMANTIC_ID_mask = 0xff << 0,
+ SEMANTIC_ID_shift = 0,
+ SQ_TEX_WORD0 = 0x00008dfc,
+ TEX_INST_mask = 0x1f << 0,
+ TEX_INST_shift = 0,
+ SQ_TEX_INST_VTX_FETCH = 0x00,
+ SQ_TEX_INST_VTX_SEMANTIC = 0x01,
+ SQ_TEX_INST_LD = 0x03,
+ SQ_TEX_INST_GET_TEXTURE_RESINFO = 0x04,
+ SQ_TEX_INST_GET_NUMBER_OF_SAMPLES = 0x05,
+ SQ_TEX_INST_GET_LOD = 0x06,
+ SQ_TEX_INST_GET_GRADIENTS_H = 0x07,
+ SQ_TEX_INST_GET_GRADIENTS_V = 0x08,
+ SQ_TEX_INST_GET_LERP = 0x09,
+ SQ_TEX_INST_RESERVED_10 = 0x0a,
+ SQ_TEX_INST_SET_GRADIENTS_H = 0x0b,
+ SQ_TEX_INST_SET_GRADIENTS_V = 0x0c,
+ SQ_TEX_INST_PASS = 0x0d,
+ X_Z_SET_INDEX_FOR_ARRAY_OF_CUBEMAPS = 0x0e,
+ SQ_TEX_INST_SAMPLE = 0x10,
+ SQ_TEX_INST_SAMPLE_L = 0x11,
+ SQ_TEX_INST_SAMPLE_LB = 0x12,
+ SQ_TEX_INST_SAMPLE_LZ = 0x13,
+ SQ_TEX_INST_SAMPLE_G = 0x14,
+ SQ_TEX_INST_SAMPLE_G_L = 0x15,
+ SQ_TEX_INST_SAMPLE_G_LB = 0x16,
+ SQ_TEX_INST_SAMPLE_G_LZ = 0x17,
+ SQ_TEX_INST_SAMPLE_C = 0x18,
+ SQ_TEX_INST_SAMPLE_C_L = 0x19,
+ SQ_TEX_INST_SAMPLE_C_LB = 0x1a,
+ SQ_TEX_INST_SAMPLE_C_LZ = 0x1b,
+ SQ_TEX_INST_SAMPLE_C_G = 0x1c,
+ SQ_TEX_INST_SAMPLE_C_G_L = 0x1d,
+ SQ_TEX_INST_SAMPLE_C_G_LB = 0x1e,
+ SQ_TEX_INST_SAMPLE_C_G_LZ = 0x1f,
+ BC_FRAC_MODE_bit = 1 << 5,
+/* FETCH_WHOLE_QUAD_bit = 1 << 7, */
+ RESOURCE_ID_mask = 0xff << 8,
+ RESOURCE_ID_shift = 8,
+/* SRC_GPR_mask = 0x7f << 16, */
+/* SRC_GPR_shift = 16, */
+/* SRC_REL_bit = 1 << 23, */
+ SQ_TEX_WORD0__ALT_CONST_bit = 1 << 24,
+ SQ_VTX_WORD1_GPR = 0x00008dfc,
+ SQ_VTX_WORD1_GPR__DST_GPR_mask = 0x7f << 0,
+ SQ_VTX_WORD1_GPR__DST_GPR_shift = 0,
+ SQ_VTX_WORD1_GPR__DST_REL_bit = 1 << 7,
+ SQ_ALU_WORD0 = 0x00008dfc,
+ SRC0_SEL_mask = 0x1ff << 0,
+ SRC0_SEL_shift = 0,
+/* SQ_ALU_SRC_0 = 0xf8, */
+/* SQ_ALU_SRC_1 = 0xf9, */
+/* SQ_ALU_SRC_1_INT = 0xfa, */
+/* SQ_ALU_SRC_M_1_INT = 0xfb, */
+/* SQ_ALU_SRC_0_5 = 0xfc, */
+/* SQ_ALU_SRC_LITERAL = 0xfd, */
+/* SQ_ALU_SRC_PV = 0xfe, */
+/* SQ_ALU_SRC_PS = 0xff, */
+ SRC0_REL_bit = 1 << 9,
+ SRC0_CHAN_mask = 0x03 << 10,
+ SRC0_CHAN_shift = 10,
+/* SQ_CHAN_X = 0x00, */
+/* SQ_CHAN_Y = 0x01, */
+/* SQ_CHAN_Z = 0x02, */
+/* SQ_CHAN_W = 0x03, */
+ SRC0_NEG_bit = 1 << 12,
+ SRC1_SEL_mask = 0x1ff << 13,
+ SRC1_SEL_shift = 13,
+/* SQ_ALU_SRC_0 = 0xf8, */
+/* SQ_ALU_SRC_1 = 0xf9, */
+/* SQ_ALU_SRC_1_INT = 0xfa, */
+/* SQ_ALU_SRC_M_1_INT = 0xfb, */
+/* SQ_ALU_SRC_0_5 = 0xfc, */
+/* SQ_ALU_SRC_LITERAL = 0xfd, */
+/* SQ_ALU_SRC_PV = 0xfe, */
+/* SQ_ALU_SRC_PS = 0xff, */
+ SRC1_REL_bit = 1 << 22,
+ SRC1_CHAN_mask = 0x03 << 23,
+ SRC1_CHAN_shift = 23,
+/* SQ_CHAN_X = 0x00, */
+/* SQ_CHAN_Y = 0x01, */
+/* SQ_CHAN_Z = 0x02, */
+/* SQ_CHAN_W = 0x03, */
+ SRC1_NEG_bit = 1 << 25,
+ INDEX_MODE_mask = 0x07 << 26,
+ INDEX_MODE_shift = 26,
+ SQ_INDEX_AR_X = 0x00,
+ SQ_INDEX_AR_Y = 0x01,
+ SQ_INDEX_AR_Z = 0x02,
+ SQ_INDEX_AR_W = 0x03,
+ SQ_INDEX_LOOP = 0x04,
+ PRED_SEL_mask = 0x03 << 29,
+ PRED_SEL_shift = 29,
+ SQ_PRED_SEL_OFF = 0x00,
+ SQ_PRED_SEL_ZERO = 0x02,
+ SQ_PRED_SEL_ONE = 0x03,
+ LAST_bit = 1 << 31,
+ SX_EXPORT_BUFFER_SIZES = 0x0000900c,
+ COLOR_BUFFER_SIZE_mask = 0xff << 0,
+ COLOR_BUFFER_SIZE_shift = 0,
+ POSITION_BUFFER_SIZE_mask = 0xff << 8,
+ POSITION_BUFFER_SIZE_shift = 8,
+ SMX_BUFFER_SIZE_mask = 0xff << 16,
+ SMX_BUFFER_SIZE_shift = 16,
+ SX_MEMORY_EXPORT_BASE = 0x00009010,
+ SX_MEMORY_EXPORT_SIZE = 0x00009014,
+ SPI_CONFIG_CNTL = 0x00009100,
+ GPR_WRITE_PRIORITY_mask = 0x1f << 0,
+ GPR_WRITE_PRIORITY_shift = 0,
+ X_PRIORITY_ORDER = 0x00,
+ X_PRIORITY_ORDER_VS = 0x01,
+ DISABLE_INTERP_1_bit = 1 << 5,
+ DEBUG_THREAD_TYPE_SEL_mask = 0x03 << 6,
+ DEBUG_THREAD_TYPE_SEL_shift = 6,
+ DEBUG_GROUP_SEL_mask = 0x1f << 8,
+ DEBUG_GROUP_SEL_shift = 8,
+ DEBUG_GRBM_OVERRIDE_bit = 1 << 13,
+ SPI_CONFIG_CNTL_1 = 0x0000913c,
+ VTX_DONE_DELAY_mask = 0x0f << 0,
+ VTX_DONE_DELAY_shift = 0,
+ X_DELAY_10_CLKS = 0x00,
+ X_DELAY_11_CLKS = 0x01,
+ X_DELAY_12_CLKS = 0x02,
+ X_DELAY_13_CLKS = 0x03,
+ X_DELAY_14_CLKS = 0x04,
+ X_DELAY_15_CLKS = 0x05,
+ X_DELAY_16_CLKS = 0x06,
+ X_DELAY_17_CLKS = 0x07,
+ X_DELAY_2_CLKS = 0x08,
+ X_DELAY_3_CLKS = 0x09,
+ X_DELAY_4_CLKS = 0x0a,
+ X_DELAY_5_CLKS = 0x0b,
+ X_DELAY_6_CLKS = 0x0c,
+ X_DELAY_7_CLKS = 0x0d,
+ X_DELAY_8_CLKS = 0x0e,
+ X_DELAY_9_CLKS = 0x0f,
+ INTERP_ONE_PRIM_PER_ROW_bit = 1 << 4,
+ TD_FILTER4 = 0x00009400,
+ WEIGHT_1_mask = 0x7ff << 0,
+ WEIGHT_1_shift = 0,
+ WEIGHT_0_mask = 0x7ff << 11,
+ WEIGHT_0_shift = 11,
+ WEIGHT_PAIR_bit = 1 << 22,
+ PHASE_mask = 0x0f << 23,
+ PHASE_shift = 23,
+ DIRECTION_bit = 1 << 27,
+ TD_FILTER4_1 = 0x00009404,
+ TD_FILTER4_1_num = 35,
+/* WEIGHT_1_mask = 0x7ff << 0, */
+/* WEIGHT_1_shift = 0, */
+/* WEIGHT_0_mask = 0x7ff << 11, */
+/* WEIGHT_0_shift = 11, */
+ TD_CNTL = 0x00009490,
+ SYNC_PHASE_SH_mask = 0x03 << 0,
+ SYNC_PHASE_SH_shift = 0,
+ SYNC_PHASE_VC_SMX_mask = 0x03 << 4,
+ SYNC_PHASE_VC_SMX_shift = 4,
+ TD0_CNTL = 0x00009494,
+ TD0_CNTL_num = 4,
+ ID_OVERRIDE_mask = 0x03 << 28,
+ ID_OVERRIDE_shift = 28,
+ TD0_STATUS = 0x000094a4,
+ TD0_STATUS_num = 4,
+ BUSY_bit = 1 << 31,
+ TA_CNTL = 0x00009504,
+ GRADIENT_CREDIT_mask = 0x1f << 0,
+ GRADIENT_CREDIT_shift = 0,
+ WALKER_CREDIT_mask = 0x1f << 8,
+ WALKER_CREDIT_shift = 8,
+ ALIGNER_CREDIT_mask = 0x1f << 16,
+ ALIGNER_CREDIT_shift = 16,
+ TD_FIFO_CREDIT_mask = 0x3ff << 22,
+ TD_FIFO_CREDIT_shift = 22,
+ TA_CNTL_AUX = 0x00009508,
+ DISABLE_CUBE_WRAP_bit = 1 << 0,
+ SYNC_GRADIENT_bit = 1 << 24,
+ SYNC_WALKER_bit = 1 << 25,
+ SYNC_ALIGNER_bit = 1 << 26,
+ BILINEAR_PRECISION_bit = 1 << 31,
+ TA0_CNTL = 0x00009510,
+/* ID_OVERRIDE_mask = 0x03 << 28, */
+/* ID_OVERRIDE_shift = 28, */
+ TA1_CNTL = 0x00009514,
+/* ID_OVERRIDE_mask = 0x03 << 28, */
+/* ID_OVERRIDE_shift = 28, */
+ TA2_CNTL = 0x00009518,
+/* ID_OVERRIDE_mask = 0x03 << 28, */
+/* ID_OVERRIDE_shift = 28, */
+ TA3_CNTL = 0x0000951c,
+/* ID_OVERRIDE_mask = 0x03 << 28, */
+/* ID_OVERRIDE_shift = 28, */
+ TA0_STATUS = 0x00009520,
+ FG_PFIFO_EMPTYB_bit = 1 << 12,
+ FG_LFIFO_EMPTYB_bit = 1 << 13,
+ FG_SFIFO_EMPTYB_bit = 1 << 14,
+ FL_PFIFO_EMPTYB_bit = 1 << 16,
+ FL_LFIFO_EMPTYB_bit = 1 << 17,
+ FL_SFIFO_EMPTYB_bit = 1 << 18,
+ FA_PFIFO_EMPTYB_bit = 1 << 20,
+ FA_LFIFO_EMPTYB_bit = 1 << 21,
+ FA_SFIFO_EMPTYB_bit = 1 << 22,
+ IN_BUSY_bit = 1 << 24,
+ FG_BUSY_bit = 1 << 25,
+ FL_BUSY_bit = 1 << 27,
+ TA_BUSY_bit = 1 << 28,
+ FA_BUSY_bit = 1 << 29,
+ AL_BUSY_bit = 1 << 30,
+/* BUSY_bit = 1 << 31, */
+ TA1_STATUS = 0x00009524,
+/* FG_PFIFO_EMPTYB_bit = 1 << 12, */
+/* FG_LFIFO_EMPTYB_bit = 1 << 13, */
+/* FG_SFIFO_EMPTYB_bit = 1 << 14, */
+/* FL_PFIFO_EMPTYB_bit = 1 << 16, */
+/* FL_LFIFO_EMPTYB_bit = 1 << 17, */
+/* FL_SFIFO_EMPTYB_bit = 1 << 18, */
+/* FA_PFIFO_EMPTYB_bit = 1 << 20, */
+/* FA_LFIFO_EMPTYB_bit = 1 << 21, */
+/* FA_SFIFO_EMPTYB_bit = 1 << 22, */
+/* IN_BUSY_bit = 1 << 24, */
+/* FG_BUSY_bit = 1 << 25, */
+/* FL_BUSY_bit = 1 << 27, */
+/* TA_BUSY_bit = 1 << 28, */
+/* FA_BUSY_bit = 1 << 29, */
+/* AL_BUSY_bit = 1 << 30, */
+/* BUSY_bit = 1 << 31, */
+ TA2_STATUS = 0x00009528,
+/* FG_PFIFO_EMPTYB_bit = 1 << 12, */
+/* FG_LFIFO_EMPTYB_bit = 1 << 13, */
+/* FG_SFIFO_EMPTYB_bit = 1 << 14, */
+/* FL_PFIFO_EMPTYB_bit = 1 << 16, */
+/* FL_LFIFO_EMPTYB_bit = 1 << 17, */
+/* FL_SFIFO_EMPTYB_bit = 1 << 18, */
+/* FA_PFIFO_EMPTYB_bit = 1 << 20, */
+/* FA_LFIFO_EMPTYB_bit = 1 << 21, */
+/* FA_SFIFO_EMPTYB_bit = 1 << 22, */
+/* IN_BUSY_bit = 1 << 24, */
+/* FG_BUSY_bit = 1 << 25, */
+/* FL_BUSY_bit = 1 << 27, */
+/* TA_BUSY_bit = 1 << 28, */
+/* FA_BUSY_bit = 1 << 29, */
+/* AL_BUSY_bit = 1 << 30, */
+/* BUSY_bit = 1 << 31, */
+ TA3_STATUS = 0x0000952c,
+/* FG_PFIFO_EMPTYB_bit = 1 << 12, */
+/* FG_LFIFO_EMPTYB_bit = 1 << 13, */
+/* FG_SFIFO_EMPTYB_bit = 1 << 14, */
+/* FL_PFIFO_EMPTYB_bit = 1 << 16, */
+/* FL_LFIFO_EMPTYB_bit = 1 << 17, */
+/* FL_SFIFO_EMPTYB_bit = 1 << 18, */
+/* FA_PFIFO_EMPTYB_bit = 1 << 20, */
+/* FA_LFIFO_EMPTYB_bit = 1 << 21, */
+/* FA_SFIFO_EMPTYB_bit = 1 << 22, */
+/* IN_BUSY_bit = 1 << 24, */
+/* FG_BUSY_bit = 1 << 25, */
+/* FL_BUSY_bit = 1 << 27, */
+/* TA_BUSY_bit = 1 << 28, */
+/* FA_BUSY_bit = 1 << 29, */
+/* AL_BUSY_bit = 1 << 30, */
+/* BUSY_bit = 1 << 31, */
+ TC_STATUS = 0x00009600,
+ TC_BUSY_bit = 1 << 0,
+ TC_INVALIDATE = 0x00009604,
+ START_bit = 1 << 0,
+ TC_CNTL = 0x00009608,
+ FORCE_HIT_bit = 1 << 0,
+ FORCE_MISS_bit = 1 << 1,
+ L2_SIZE_mask = 0x0f << 5,
+ L2_SIZE_shift = 5,
+ _256K = 0x00,
+ _224K = 0x01,
+ _192K = 0x02,
+ _160K = 0x03,
+ _128K = 0x04,
+ _96K = 0x05,
+ _64K = 0x06,
+ _32K = 0x07,
+ L2_DISABLE_LATE_HIT_bit = 1 << 9,
+ DISABLE_VERT_PERF_bit = 1 << 10,
+ DISABLE_INVAL_BUSY_bit = 1 << 11,
+ DISABLE_INVAL_SAME_SURFACE_bit = 1 << 12,
+ PARTITION_MODE_mask = 0x03 << 13,
+ PARTITION_MODE_shift = 13,
+ X_VERTEX = 0x00,
+ MISS_ARB_MODE_bit = 1 << 15,
+ HIT_ARB_MODE_bit = 1 << 16,
+ DISABLE_WRITE_DELAY_bit = 1 << 17,
+ HIT_FIFO_DEPTH_bit = 1 << 18,
+ VC_CNTL = 0x00009700,
+ L2_INVALIDATE_bit = 1 << 0,
+ RESERVED_bit = 1 << 1,
+ CC_FORCE_MISS_bit = 1 << 2,
+ MI_CHAN_SEL_mask = 0x03 << 3,
+ MI_CHAN_SEL_shift = 3,
+ X_MC0_USES_CH_0_1 = 0x00,
+ X_MC0_USES_CH_0_3 = 0x01,
+ X_VC_MC0_IS_ACTIVE = 0x02,
+ X_VC_MC1_IS_DISABLED = 0x03,
+ MI_STEER_DISABLE_bit = 1 << 5,
+ MI_CREDIT_CTR_mask = 0x0f << 6,
+ MI_CREDIT_CTR_shift = 6,
+ MI_CREDIT_WE_bit = 1 << 10,
+ MI_REQ_STALL_THLD_mask = 0x07 << 11,
+ MI_REQ_STALL_THLD_shift = 11,
+ X_LATENCY_EXCEEDS_399_CLOCKS = 0x00,
+ X_LATENCY_EXCEEDS_415_CLOCKS = 0x01,
+ X_LATENCY_EXCEEDS_431_CLOCKS = 0x02,
+ X_LATENCY_EXCEEDS_447_CLOCKS = 0x03,
+ X_LATENCY_EXCEEDS_463_CLOCKS = 0x04,
+ X_LATENCY_EXCEEDS_479_CLOCKS = 0x05,
+ X_LATENCY_EXCEEDS_495_CLOCKS = 0x06,
+ X_LATENCY_EXCEEDS_511_CLOCKS = 0x07,
+ VC_CNTL__MI_TIMESTAMP_RES_mask = 0x1f << 14,
+ VC_CNTL__MI_TIMESTAMP_RES_shift = 14,
+ X_1X_SYSTEM_CLOCK = 0x00,
+ X_2X_SYSTEM_CLOCK = 0x01,
+ X_4X_SYSTEM_CLOCK = 0x02,
+ X_8X_SYSTEM_CLOCK = 0x03,
+ X_16X_SYSTEM_CLOCK = 0x04,
+ X_32X_SYSTEM_CLOCK = 0x05,
+ X_64X_SYSTEM_CLOCK = 0x06,
+ X_128X_SYSTEM_CLOCK = 0x07,
+ X_256X_SYSTEM_CLOCK = 0x08,
+ X_512X_SYSTEM_CLOCK = 0x09,
+ X_1024X_SYSTEM_CLOCK = 0x0a,
+ X_2048X_SYSTEM_CLOCK = 0x0b,
+ X_4092X_SYSTEM_CLOCK = 0x0c,
+ X_8192X_SYSTEM_CLOCK = 0x0d,
+ X_16384X_SYSTEM_CLOCK = 0x0e,
+ X_32768X_SYSTEM_CLOCK = 0x0f,
+ VC_CNTL_STATUS = 0x00009704,
+ RP_BUSY_bit = 1 << 0,
+ RG_BUSY_bit = 1 << 1,
+ VC_BUSY_bit = 1 << 2,
+ CLAMP_DETECT_bit = 1 << 3,
+ VC_CONFIG = 0x00009718,
+ WRITE_DIS_bit = 1 << 0,
+ GPR_DATA_PHASE_ADJ_mask = 0x07 << 1,
+ GPR_DATA_PHASE_ADJ_shift = 1,
+ X_LATENCY_BASE_0_CYCLES = 0x00,
+ X_LATENCY_BASE_1_CYCLES = 0x01,
+ X_LATENCY_BASE_2_CYCLES = 0x02,
+ X_LATENCY_BASE_3_CYCLES = 0x03,
+ TD_SIMD_SYNC_ADJ_mask = 0x07 << 4,
+ TD_SIMD_SYNC_ADJ_shift = 4,
+ X_0_CYCLES_DELAY = 0x00,
+ X_1_CYCLES_DELAY = 0x01,
+ X_2_CYCLES_DELAY = 0x02,
+ X_3_CYCLES_DELAY = 0x03,
+ X_4_CYCLES_DELAY = 0x04,
+ X_5_CYCLES_DELAY = 0x05,
+ X_6_CYCLES_DELAY = 0x06,
+ X_7_CYCLES_DELAY = 0x07,
+ SMX_DC_CTL0 = 0x0000a020,
+ WR_GATHER_STREAM0_bit = 1 << 0,
+ WR_GATHER_STREAM1_bit = 1 << 1,
+ WR_GATHER_STREAM2_bit = 1 << 2,
+ WR_GATHER_STREAM3_bit = 1 << 3,
+ WR_GATHER_SCRATCH_bit = 1 << 4,
+ WR_GATHER_REDUC_BUF_bit = 1 << 5,
+ WR_GATHER_RING_BUF_bit = 1 << 6,
+ WR_GATHER_F_BUF_bit = 1 << 7,
+ DISABLE_CACHES_bit = 1 << 8,
+ AUTO_FLUSH_INVAL_EN_bit = 1 << 10,
+ AUTO_FLUSH_EN_bit = 1 << 11,
+ AUTO_FLUSH_CNT_mask = 0xffff << 12,
+ AUTO_FLUSH_CNT_shift = 12,
+ MC_RD_STALL_FACTOR_mask = 0x03 << 28,
+ MC_RD_STALL_FACTOR_shift = 28,
+ MC_WR_STALL_FACTOR_mask = 0x03 << 30,
+ MC_WR_STALL_FACTOR_shift = 30,
+ SMX_DC_CTL1 = 0x0000a024,
+ OP_FIFO_SKID_mask = 0x7f << 0,
+ OP_FIFO_SKID_shift = 0,
+ CACHE_LINE_SIZE_bit = 1 << 8,
+ MULTI_FLUSH_MODE_bit = 1 << 9,
+ MULTI_FLUSH_REQ_ABORT_IDX_FIFO_SKID_mask = 0x0f << 10,
+ MULTI_FLUSH_REQ_ABORT_IDX_FIFO_SKID_shift = 10,
+ DISABLE_WR_GATHER_RD_HIT_FORCE_EVICT_bit = 1 << 16,
+ DISABLE_WR_GATHER_RD_HIT_COMP_VLDS_CHECK_bit = 1 << 17,
+ DISABLE_FLUSH_ES_ALSO_INVALS_bit = 1 << 18,
+ DISABLE_FLUSH_GS_ALSO_INVALS_bit = 1 << 19,
+ SMX_DC_CTL2 = 0x0000a028,
+ INVALIDATE_CACHES_bit = 1 << 0,
+ CACHES_INVALID_bit = 1 << 1,
+ CACHES_DIRTY_bit = 1 << 2,
+ FLUSH_ALL_bit = 1 << 4,
+ FLUSH_GS_THREADS_bit = 1 << 8,
+ FLUSH_ES_THREADS_bit = 1 << 9,
+ SMX_DC_MC_INTF_CTL = 0x0000a02c,
+ MC_RD_REQ_CRED_mask = 0xff << 0,
+ MC_RD_REQ_CRED_shift = 0,
+ MC_WR_REQ_CRED_mask = 0xff << 16,
+ MC_WR_REQ_CRED_shift = 16,
+ TD_PS_SAMPLER0_BORDER_RED = 0x0000a400,
+ TD_PS_SAMPLER0_BORDER_RED_num = 18,
+ TD_PS_SAMPLER0_BORDER_RED_offset = 16,
+ TD_PS_SAMPLER0_BORDER_GREEN = 0x0000a404,
+ TD_PS_SAMPLER0_BORDER_GREEN_num = 18,
+ TD_PS_SAMPLER0_BORDER_GREEN_offset = 16,
+ TD_PS_SAMPLER0_BORDER_BLUE = 0x0000a408,
+ TD_PS_SAMPLER0_BORDER_BLUE_num = 18,
+ TD_PS_SAMPLER0_BORDER_BLUE_offset = 16,
+ TD_PS_SAMPLER0_BORDER_ALPHA = 0x0000a40c,
+ TD_PS_SAMPLER0_BORDER_ALPHA_num = 18,
+ TD_PS_SAMPLER0_BORDER_ALPHA_offset = 16,
+ TD_VS_SAMPLER0_BORDER_RED = 0x0000a600,
+ TD_VS_SAMPLER0_BORDER_RED_num = 18,
+ TD_VS_SAMPLER0_BORDER_RED_offset = 16,
+ TD_VS_SAMPLER0_BORDER_GREEN = 0x0000a604,
+ TD_VS_SAMPLER0_BORDER_GREEN_num = 18,
+ TD_VS_SAMPLER0_BORDER_GREEN_offset = 16,
+ TD_VS_SAMPLER0_BORDER_BLUE = 0x0000a608,
+ TD_VS_SAMPLER0_BORDER_BLUE_num = 18,
+ TD_VS_SAMPLER0_BORDER_BLUE_offset = 16,
+ TD_VS_SAMPLER0_BORDER_ALPHA = 0x0000a60c,
+ TD_VS_SAMPLER0_BORDER_ALPHA_num = 18,
+ TD_VS_SAMPLER0_BORDER_ALPHA_offset = 16,
+ TD_GS_SAMPLER0_BORDER_RED = 0x0000a800,
+ TD_GS_SAMPLER0_BORDER_RED_num = 18,
+ TD_GS_SAMPLER0_BORDER_RED_offset = 16,
+ TD_GS_SAMPLER0_BORDER_GREEN = 0x0000a804,
+ TD_GS_SAMPLER0_BORDER_GREEN_num = 18,
+ TD_GS_SAMPLER0_BORDER_GREEN_offset = 16,
+ TD_GS_SAMPLER0_BORDER_BLUE = 0x0000a808,
+ TD_GS_SAMPLER0_BORDER_BLUE_num = 18,
+ TD_GS_SAMPLER0_BORDER_BLUE_offset = 16,
+ TD_GS_SAMPLER0_BORDER_ALPHA = 0x0000a80c,
+ TD_GS_SAMPLER0_BORDER_ALPHA_num = 18,
+ TD_GS_SAMPLER0_BORDER_ALPHA_offset = 16,
+ TD_PS_SAMPLER0_CLEARTYPE_KERNEL = 0x0000aa00,
+ TD_PS_SAMPLER0_CLEARTYPE_KERNEL_num = 18,
+ TD_PS_SAMPLER0_CLEARTYPE_KERNEL__WIDTH_mask = 0x07 << 0,
+ TD_PS_SAMPLER0_CLEARTYPE_KERNEL__WIDTH_shift = 0,
+ TD_PS_SAMPLER0_CLEARTYPE_KERNEL__HEIGHT_mask = 0x07 << 3,
+ TD_PS_SAMPLER0_CLEARTYPE_KERNEL__HEIGHT_shift = 3,
+ DB_DEPTH_SIZE = 0x00028000,
+ PITCH_TILE_MAX_mask = 0x3ff << 0,
+ PITCH_TILE_MAX_shift = 0,
+ SLICE_TILE_MAX_mask = 0xfffff << 10,
+ SLICE_TILE_MAX_shift = 10,
+ DB_DEPTH_VIEW = 0x00028004,
+ SLICE_START_mask = 0x7ff << 0,
+ SLICE_START_shift = 0,
+ SLICE_MAX_mask = 0x7ff << 13,
+ SLICE_MAX_shift = 13,
+ DB_DEPTH_BASE = 0x0002800c,
+ DB_DEPTH_INFO = 0x00028010,
+ DB_DEPTH_INFO__FORMAT_mask = 0x07 << 0,
+ DB_DEPTH_INFO__FORMAT_shift = 0,
+ DEPTH_INVALID = 0x00,
+ DEPTH_16 = 0x01,
+ DEPTH_X8_24 = 0x02,
+ DEPTH_8_24 = 0x03,
+ DEPTH_X8_24_FLOAT = 0x04,
+ DEPTH_8_24_FLOAT = 0x05,
+ DEPTH_32_FLOAT = 0x06,
+ DEPTH_X24_8_32_FLOAT = 0x07,
+ DB_DEPTH_INFO__READ_SIZE_bit = 1 << 3,
+ DB_DEPTH_INFO__ARRAY_MODE_mask = 0x0f << 15,
+ DB_DEPTH_INFO__ARRAY_MODE_shift = 15,
+ ARRAY_2D_TILED_THIN1 = 0x04,
+ TILE_SURFACE_ENABLE_bit = 1 << 25,
+ TILE_COMPACT_bit = 1 << 26,
+ ZRANGE_PRECISION_bit = 1 << 31,
+ DB_HTILE_DATA_BASE = 0x00028014,
+ DB_STENCIL_CLEAR = 0x00028028,
+ DB_STENCIL_CLEAR__CLEAR_mask = 0xff << 0,
+ DB_STENCIL_CLEAR__CLEAR_shift = 0,
+ MIN_mask = 0xff << 16,
+ MIN_shift = 16,
+ DB_DEPTH_CLEAR = 0x0002802c,
+ PA_SC_SCREEN_SCISSOR_TL = 0x00028030,
+ PA_SC_SCREEN_SCISSOR_TL__TL_X_mask = 0x7fff << 0,
+ PA_SC_SCREEN_SCISSOR_TL__TL_X_shift = 0,
+ PA_SC_SCREEN_SCISSOR_TL__TL_Y_mask = 0x7fff << 16,
+ PA_SC_SCREEN_SCISSOR_TL__TL_Y_shift = 16,
+ PA_SC_SCREEN_SCISSOR_BR = 0x00028034,
+ PA_SC_SCREEN_SCISSOR_BR__BR_X_mask = 0x7fff << 0,
+ PA_SC_SCREEN_SCISSOR_BR__BR_X_shift = 0,
+ PA_SC_SCREEN_SCISSOR_BR__BR_Y_mask = 0x7fff << 16,
+ PA_SC_SCREEN_SCISSOR_BR__BR_Y_shift = 16,
+ CB_COLOR0_BASE = 0x00028040,
+ CB_COLOR0_BASE_num = 8,
+ CB_COLOR0_SIZE = 0x00028060,
+ CB_COLOR0_SIZE_num = 8,
+/* PITCH_TILE_MAX_mask = 0x3ff << 0, */
+/* PITCH_TILE_MAX_shift = 0, */
+/* SLICE_TILE_MAX_mask = 0xfffff << 10, */
+/* SLICE_TILE_MAX_shift = 10, */
+ CB_COLOR0_VIEW = 0x00028080,
+ CB_COLOR0_VIEW_num = 8,
+/* SLICE_START_mask = 0x7ff << 0, */
+/* SLICE_START_shift = 0, */
+/* SLICE_MAX_mask = 0x7ff << 13, */
+/* SLICE_MAX_shift = 13, */
+ CB_COLOR0_INFO = 0x000280a0,
+ CB_COLOR0_INFO_num = 8,
+ ENDIAN_mask = 0x03 << 0,
+ ENDIAN_shift = 0,
+ ENDIAN_NONE = 0x00,
+ ENDIAN_8IN16 = 0x01,
+ ENDIAN_8IN32 = 0x02,
+ ENDIAN_8IN64 = 0x03,
+ CB_COLOR0_INFO__FORMAT_mask = 0x3f << 2,
+ CB_COLOR0_INFO__FORMAT_shift = 2,
+ COLOR_INVALID = 0x00,
+ COLOR_8 = 0x01,
+ COLOR_4_4 = 0x02,
+ COLOR_3_3_2 = 0x03,
+ COLOR_16 = 0x05,
+ COLOR_16_FLOAT = 0x06,
+ COLOR_8_8 = 0x07,
+ COLOR_5_6_5 = 0x08,
+ COLOR_6_5_5 = 0x09,
+ COLOR_1_5_5_5 = 0x0a,
+ COLOR_4_4_4_4 = 0x0b,
+ COLOR_5_5_5_1 = 0x0c,
+ COLOR_32 = 0x0d,
+ COLOR_32_FLOAT = 0x0e,
+ COLOR_16_16 = 0x0f,
+ COLOR_16_16_FLOAT = 0x10,
+ COLOR_8_24 = 0x11,
+ COLOR_8_24_FLOAT = 0x12,
+ COLOR_24_8 = 0x13,
+ COLOR_24_8_FLOAT = 0x14,
+ COLOR_10_11_11 = 0x15,
+ COLOR_10_11_11_FLOAT = 0x16,
+ COLOR_11_11_10 = 0x17,
+ COLOR_11_11_10_FLOAT = 0x18,
+ COLOR_2_10_10_10 = 0x19,
+ COLOR_8_8_8_8 = 0x1a,
+ COLOR_10_10_10_2 = 0x1b,
+ COLOR_X24_8_32_FLOAT = 0x1c,
+ COLOR_32_32 = 0x1d,
+ COLOR_32_32_FLOAT = 0x1e,
+ COLOR_16_16_16_16 = 0x1f,
+ COLOR_16_16_16_16_FLOAT = 0x20,
+ COLOR_32_32_32_32 = 0x22,
+ COLOR_32_32_32_32_FLOAT = 0x23,
+ CB_COLOR0_INFO__ARRAY_MODE_mask = 0x0f << 8,
+ CB_COLOR0_INFO__ARRAY_MODE_shift = 8,
+ ARRAY_LINEAR_GENERAL = 0x00,
+ ARRAY_LINEAR_ALIGNED = 0x01,
+/* ARRAY_2D_TILED_THIN1 = 0x04, */
+ NUMBER_TYPE_mask = 0x07 << 12,
+ NUMBER_TYPE_shift = 12,
+ NUMBER_UNORM = 0x00,
+ NUMBER_SNORM = 0x01,
+ NUMBER_USCALED = 0x02,
+ NUMBER_SSCALED = 0x03,
+ NUMBER_UINT = 0x04,
+ NUMBER_SINT = 0x05,
+ NUMBER_SRGB = 0x06,
+ NUMBER_FLOAT = 0x07,
+ CB_COLOR0_INFO__READ_SIZE_bit = 1 << 15,
+ COMP_SWAP_mask = 0x03 << 16,
+ COMP_SWAP_shift = 16,
+ SWAP_STD = 0x00,
+ SWAP_ALT = 0x01,
+ SWAP_STD_REV = 0x02,
+ SWAP_ALT_REV = 0x03,
+ CB_COLOR0_INFO__TILE_MODE_mask = 0x03 << 18,
+ CB_COLOR0_INFO__TILE_MODE_shift = 18,
+ TILE_DISABLE = 0x00,
+ TILE_CLEAR_ENABLE = 0x01,
+ TILE_FRAG_ENABLE = 0x02,
+ BLEND_CLAMP_bit = 1 << 20,
+ CLEAR_COLOR_bit = 1 << 21,
+ BLEND_BYPASS_bit = 1 << 22,
+ BLEND_FLOAT32_bit = 1 << 23,
+ SIMPLE_FLOAT_bit = 1 << 24,
+ CB_COLOR0_INFO__ROUND_MODE_bit = 1 << 25,
+/* TILE_COMPACT_bit = 1 << 26, */
+ SOURCE_FORMAT_bit = 1 << 27,
+ CB_COLOR0_TILE = 0x000280c0,
+ CB_COLOR0_TILE_num = 8,
+ CB_COLOR0_FRAG = 0x000280e0,
+ CB_COLOR0_FRAG_num = 8,
+ CB_COLOR0_MASK = 0x00028100,
+ CB_COLOR0_MASK_num = 8,
+ CMASK_BLOCK_MAX_mask = 0xfff << 0,
+ CMASK_BLOCK_MAX_shift = 0,
+ FMASK_TILE_MAX_mask = 0xfffff << 12,
+ FMASK_TILE_MAX_shift = 12,
+ CB_CLEAR_RED = 0x00028120,
+ CB_CLEAR_GREEN = 0x00028124,
+ CB_CLEAR_BLUE = 0x00028128,
+ CB_CLEAR_ALPHA = 0x0002812c,
+ SQ_ALU_CONST_BUFFER_SIZE_PS_0 = 0x00028140,
+ SQ_ALU_CONST_BUFFER_SIZE_PS_0_num = 16,
+ SQ_ALU_CONST_BUFFER_SIZE_PS_0__DATA_mask = 0x1ff << 0,
+ SQ_ALU_CONST_BUFFER_SIZE_PS_0__DATA_shift = 0,
+ SQ_ALU_CONST_BUFFER_SIZE_VS_0 = 0x00028180,
+ SQ_ALU_CONST_BUFFER_SIZE_VS_0_num = 16,
+ SQ_ALU_CONST_BUFFER_SIZE_VS_0__DATA_mask = 0x1ff << 0,
+ SQ_ALU_CONST_BUFFER_SIZE_VS_0__DATA_shift = 0,
+ SQ_ALU_CONST_BUFFER_SIZE_GS_0 = 0x000281c0,
+ SQ_ALU_CONST_BUFFER_SIZE_GS_0_num = 16,
+ SQ_ALU_CONST_BUFFER_SIZE_GS_0__DATA_mask = 0x1ff << 0,
+ SQ_ALU_CONST_BUFFER_SIZE_GS_0__DATA_shift = 0,
+ PA_SC_WINDOW_OFFSET = 0x00028200,
+ WINDOW_X_OFFSET_mask = 0x7fff << 0,
+ WINDOW_X_OFFSET_shift = 0,
+ WINDOW_Y_OFFSET_mask = 0x7fff << 16,
+ WINDOW_Y_OFFSET_shift = 16,
+ PA_SC_WINDOW_SCISSOR_TL = 0x00028204,
+ PA_SC_WINDOW_SCISSOR_TL__TL_X_mask = 0x3fff << 0,
+ PA_SC_WINDOW_SCISSOR_TL__TL_X_shift = 0,
+ PA_SC_WINDOW_SCISSOR_TL__TL_Y_mask = 0x3fff << 16,
+ PA_SC_WINDOW_SCISSOR_TL__TL_Y_shift = 16,
+ WINDOW_OFFSET_DISABLE_bit = 1 << 31,
+ PA_SC_WINDOW_SCISSOR_BR = 0x00028208,
+ PA_SC_WINDOW_SCISSOR_BR__BR_X_mask = 0x3fff << 0,
+ PA_SC_WINDOW_SCISSOR_BR__BR_X_shift = 0,
+ PA_SC_WINDOW_SCISSOR_BR__BR_Y_mask = 0x3fff << 16,
+ PA_SC_WINDOW_SCISSOR_BR__BR_Y_shift = 16,
+ PA_SC_CLIPRECT_RULE = 0x0002820c,
+ CLIP_RULE_mask = 0xffff << 0,
+ CLIP_RULE_shift = 0,
+ PA_SC_CLIPRECT_0_TL = 0x00028210,
+ PA_SC_CLIPRECT_0_TL_num = 4,
+ PA_SC_CLIPRECT_0_TL_offset = 8,
+ PA_SC_CLIPRECT_0_TL__TL_X_mask = 0x3fff << 0,
+ PA_SC_CLIPRECT_0_TL__TL_X_shift = 0,
+ PA_SC_CLIPRECT_0_TL__TL_Y_mask = 0x3fff << 16,
+ PA_SC_CLIPRECT_0_TL__TL_Y_shift = 16,
+ PA_SC_CLIPRECT_0_BR = 0x00028214,
+ PA_SC_CLIPRECT_0_BR_num = 4,
+ PA_SC_CLIPRECT_0_BR_offset = 8,
+ PA_SC_CLIPRECT_0_BR__BR_X_mask = 0x3fff << 0,
+ PA_SC_CLIPRECT_0_BR__BR_X_shift = 0,
+ PA_SC_CLIPRECT_0_BR__BR_Y_mask = 0x3fff << 16,
+ PA_SC_CLIPRECT_0_BR__BR_Y_shift = 16,
+ CB_TARGET_MASK = 0x00028238,
+ TARGET0_ENABLE_mask = 0x0f << 0,
+ TARGET0_ENABLE_shift = 0,
+ TARGET1_ENABLE_mask = 0x0f << 4,
+ TARGET1_ENABLE_shift = 4,
+ TARGET2_ENABLE_mask = 0x0f << 8,
+ TARGET2_ENABLE_shift = 8,
+ TARGET3_ENABLE_mask = 0x0f << 12,
+ TARGET3_ENABLE_shift = 12,
+ TARGET4_ENABLE_mask = 0x0f << 16,
+ TARGET4_ENABLE_shift = 16,
+ TARGET5_ENABLE_mask = 0x0f << 20,
+ TARGET5_ENABLE_shift = 20,
+ TARGET6_ENABLE_mask = 0x0f << 24,
+ TARGET6_ENABLE_shift = 24,
+ TARGET7_ENABLE_mask = 0x0f << 28,
+ TARGET7_ENABLE_shift = 28,
+ CB_SHADER_MASK = 0x0002823c,
+ OUTPUT0_ENABLE_mask = 0x0f << 0,
+ OUTPUT0_ENABLE_shift = 0,
+ OUTPUT1_ENABLE_mask = 0x0f << 4,
+ OUTPUT1_ENABLE_shift = 4,
+ OUTPUT2_ENABLE_mask = 0x0f << 8,
+ OUTPUT2_ENABLE_shift = 8,
+ OUTPUT3_ENABLE_mask = 0x0f << 12,
+ OUTPUT3_ENABLE_shift = 12,
+ OUTPUT4_ENABLE_mask = 0x0f << 16,
+ OUTPUT4_ENABLE_shift = 16,
+ OUTPUT5_ENABLE_mask = 0x0f << 20,
+ OUTPUT5_ENABLE_shift = 20,
+ OUTPUT6_ENABLE_mask = 0x0f << 24,
+ OUTPUT6_ENABLE_shift = 24,
+ OUTPUT7_ENABLE_mask = 0x0f << 28,
+ OUTPUT7_ENABLE_shift = 28,
+ PA_SC_GENERIC_SCISSOR_TL = 0x00028240,
+ PA_SC_GENERIC_SCISSOR_TL__TL_X_mask = 0x3fff << 0,
+ PA_SC_GENERIC_SCISSOR_TL__TL_X_shift = 0,
+ PA_SC_GENERIC_SCISSOR_TL__TL_Y_mask = 0x3fff << 16,
+ PA_SC_GENERIC_SCISSOR_TL__TL_Y_shift = 16,
+/* WINDOW_OFFSET_DISABLE_bit = 1 << 31, */
+ PA_SC_GENERIC_SCISSOR_BR = 0x00028244,
+ PA_SC_GENERIC_SCISSOR_BR__BR_X_mask = 0x3fff << 0,
+ PA_SC_GENERIC_SCISSOR_BR__BR_X_shift = 0,
+ PA_SC_GENERIC_SCISSOR_BR__BR_Y_mask = 0x3fff << 16,
+ PA_SC_GENERIC_SCISSOR_BR__BR_Y_shift = 16,
+ PA_SC_VPORT_SCISSOR_0_TL = 0x00028250,
+ PA_SC_VPORT_SCISSOR_0_TL_num = 16,
+ PA_SC_VPORT_SCISSOR_0_TL_offset = 8,
+ PA_SC_VPORT_SCISSOR_0_TL__TL_X_mask = 0x3fff << 0,
+ PA_SC_VPORT_SCISSOR_0_TL__TL_X_shift = 0,
+ PA_SC_VPORT_SCISSOR_0_TL__TL_Y_mask = 0x3fff << 16,
+ PA_SC_VPORT_SCISSOR_0_TL__TL_Y_shift = 16,
+/* WINDOW_OFFSET_DISABLE_bit = 1 << 31, */
+ PA_SC_VPORT_SCISSOR_0_BR = 0x00028254,
+ PA_SC_VPORT_SCISSOR_0_BR_num = 16,
+ PA_SC_VPORT_SCISSOR_0_BR_offset = 8,
+ PA_SC_VPORT_SCISSOR_0_BR__BR_X_mask = 0x3fff << 0,
+ PA_SC_VPORT_SCISSOR_0_BR__BR_X_shift = 0,
+ PA_SC_VPORT_SCISSOR_0_BR__BR_Y_mask = 0x3fff << 16,
+ PA_SC_VPORT_SCISSOR_0_BR__BR_Y_shift = 16,
+ PA_SC_VPORT_ZMIN_0 = 0x000282d0,
+ PA_SC_VPORT_ZMIN_0_num = 16,
+ PA_SC_VPORT_ZMIN_0_offset = 8,
+ PA_SC_VPORT_ZMAX_0 = 0x000282d4,
+ PA_SC_VPORT_ZMAX_0_num = 16,
+ PA_SC_VPORT_ZMAX_0_offset = 8,
+ SX_MISC = 0x00028350,
+ MULTIPASS_bit = 1 << 0,
+ SQ_VTX_SEMANTIC_0 = 0x00028380,
+ SQ_VTX_SEMANTIC_0_num = 32,
+/* SEMANTIC_ID_mask = 0xff << 0, */
+/* SEMANTIC_ID_shift = 0, */
+ VGT_MAX_VTX_INDX = 0x00028400,
+ VGT_MIN_VTX_INDX = 0x00028404,
+ VGT_INDX_OFFSET = 0x00028408,
+ VGT_MULTI_PRIM_IB_RESET_INDX = 0x0002840c,
+ SX_ALPHA_TEST_CONTROL = 0x00028410,
+ ALPHA_FUNC_mask = 0x07 << 0,
+ ALPHA_FUNC_shift = 0,
+ REF_NEVER = 0x00,
+ REF_LESS = 0x01,
+ REF_EQUAL = 0x02,
+ REF_LEQUAL = 0x03,
+ REF_GREATER = 0x04,
+ REF_NOTEQUAL = 0x05,
+ REF_GEQUAL = 0x06,
+ REF_ALWAYS = 0x07,
+ ALPHA_TEST_ENABLE_bit = 1 << 3,
+ ALPHA_TEST_BYPASS_bit = 1 << 8,
+ CB_BLEND_RED = 0x00028414,
+ CB_BLEND_GREEN = 0x00028418,
+ CB_BLEND_BLUE = 0x0002841c,
+ CB_BLEND_ALPHA = 0x00028420,
+ CB_FOG_RED = 0x00028424,
+ CB_FOG_GREEN = 0x00028428,
+ CB_FOG_BLUE = 0x0002842c,
+ DB_STENCILREFMASK = 0x00028430,
+ STENCILREF_mask = 0xff << 0,
+ STENCILREF_shift = 0,
+ STENCILMASK_mask = 0xff << 8,
+ STENCILMASK_shift = 8,
+ STENCILWRITEMASK_mask = 0xff << 16,
+ STENCILWRITEMASK_shift = 16,
+ DB_STENCILREFMASK_BF = 0x00028434,
+ STENCILREF_BF_mask = 0xff << 0,
+ STENCILREF_BF_shift = 0,
+ STENCILMASK_BF_mask = 0xff << 8,
+ STENCILMASK_BF_shift = 8,
+ STENCILWRITEMASK_BF_mask = 0xff << 16,
+ STENCILWRITEMASK_BF_shift = 16,
+ SX_ALPHA_REF = 0x00028438,
+ PA_CL_VPORT_XSCALE_0 = 0x0002843c,
+ PA_CL_VPORT_XSCALE_0_num = 16,
+ PA_CL_VPORT_XSCALE_0_offset = 24,
+ PA_CL_VPORT_XOFFSET_0 = 0x00028440,
+ PA_CL_VPORT_XOFFSET_0_num = 16,
+ PA_CL_VPORT_XOFFSET_0_offset = 24,
+ PA_CL_VPORT_YSCALE_0 = 0x00028444,
+ PA_CL_VPORT_YSCALE_0_num = 16,
+ PA_CL_VPORT_YSCALE_0_offset = 24,
+ PA_CL_VPORT_YOFFSET_0 = 0x00028448,
+ PA_CL_VPORT_YOFFSET_0_num = 16,
+ PA_CL_VPORT_YOFFSET_0_offset = 24,
+ PA_CL_VPORT_ZSCALE_0 = 0x0002844c,
+ PA_CL_VPORT_ZSCALE_0_num = 16,
+ PA_CL_VPORT_ZSCALE_0_offset = 24,
+ PA_CL_VPORT_ZOFFSET_0 = 0x00028450,
+ PA_CL_VPORT_ZOFFSET_0_num = 16,
+ PA_CL_VPORT_ZOFFSET_0_offset = 24,
+ SPI_VS_OUT_ID_0 = 0x00028614,
+ SPI_VS_OUT_ID_0_num = 10,
+ SEMANTIC_0_mask = 0xff << 0,
+ SEMANTIC_0_shift = 0,
+ SEMANTIC_1_mask = 0xff << 8,
+ SEMANTIC_1_shift = 8,
+ SEMANTIC_2_mask = 0xff << 16,
+ SEMANTIC_2_shift = 16,
+ SEMANTIC_3_mask = 0xff << 24,
+ SEMANTIC_3_shift = 24,
+ SPI_PS_INPUT_CNTL_0 = 0x00028644,
+ SPI_PS_INPUT_CNTL_0_num = 32,
+ SEMANTIC_mask = 0xff << 0,
+ SEMANTIC_shift = 0,
+ DEFAULT_VAL_mask = 0x03 << 8,
+ DEFAULT_VAL_shift = 8,
+ X_0_0F = 0x00,
+ FLAT_SHADE_bit = 1 << 10,
+ SEL_CENTROID_bit = 1 << 11,
+ SEL_LINEAR_bit = 1 << 12,
+ CYL_WRAP_mask = 0x0f << 13,
+ CYL_WRAP_shift = 13,
+ PT_SPRITE_TEX_bit = 1 << 17,
+ SEL_SAMPLE_bit = 1 << 18,
+ SPI_VS_OUT_CONFIG = 0x000286c4,
+ VS_PER_COMPONENT_bit = 1 << 0,
+ VS_EXPORT_COUNT_mask = 0x1f << 1,
+ VS_EXPORT_COUNT_shift = 1,
+ VS_EXPORTS_FOG_bit = 1 << 8,
+ VS_OUT_FOG_VEC_ADDR_mask = 0x1f << 9,
+ VS_OUT_FOG_VEC_ADDR_shift = 9,
+ SPI_PS_IN_CONTROL_0 = 0x000286cc,
+ NUM_INTERP_mask = 0x3f << 0,
+ NUM_INTERP_shift = 0,
+ POSITION_ENA_bit = 1 << 8,
+ POSITION_CENTROID_bit = 1 << 9,
+ POSITION_ADDR_mask = 0x1f << 10,
+ POSITION_ADDR_shift = 10,
+ PARAM_GEN_mask = 0x0f << 15,
+ PARAM_GEN_shift = 15,
+ PARAM_GEN_ADDR_mask = 0x7f << 19,
+ PARAM_GEN_ADDR_shift = 19,
+ BARYC_SAMPLE_CNTL_mask = 0x03 << 26,
+ BARYC_SAMPLE_CNTL_shift = 26,
+ CENTROIDS_ONLY = 0x00,
+ CENTERS_ONLY = 0x01,
+ CENTROIDS_AND_CENTERS = 0x02,
+ UNDEF = 0x03,
+ PERSP_GRADIENT_ENA_bit = 1 << 28,
+ LINEAR_GRADIENT_ENA_bit = 1 << 29,
+ POSITION_SAMPLE_bit = 1 << 30,
+ BARYC_AT_SAMPLE_ENA_bit = 1 << 31,
+ SPI_PS_IN_CONTROL_1 = 0x000286d0,
+ GEN_INDEX_PIX_bit = 1 << 0,
+ GEN_INDEX_PIX_ADDR_mask = 0x7f << 1,
+ GEN_INDEX_PIX_ADDR_shift = 1,
+ FRONT_FACE_ENA_bit = 1 << 8,
+ FRONT_FACE_CHAN_mask = 0x03 << 9,
+ FRONT_FACE_CHAN_shift = 9,
+ FRONT_FACE_ALL_BITS_bit = 1 << 11,
+ FRONT_FACE_ADDR_mask = 0x1f << 12,
+ FRONT_FACE_ADDR_shift = 12,
+ FOG_ADDR_mask = 0x7f << 17,
+ FOG_ADDR_shift = 17,
+ FIXED_PT_POSITION_ENA_bit = 1 << 24,
+ FIXED_PT_POSITION_ADDR_mask = 0x1f << 25,
+ FIXED_PT_POSITION_ADDR_shift = 25,
+ SPI_INTERP_CONTROL_0 = 0x000286d4,
+ FLAT_SHADE_ENA_bit = 1 << 0,
+ PNT_SPRITE_ENA_bit = 1 << 1,
+ PNT_SPRITE_OVRD_X_mask = 0x07 << 2,
+ PNT_SPRITE_OVRD_X_shift = 2,
+ SPI_PNT_SPRITE_SEL_0 = 0x00,
+ SPI_PNT_SPRITE_SEL_1 = 0x01,
+ SPI_PNT_SPRITE_SEL_S = 0x02,
+ SPI_PNT_SPRITE_SEL_T = 0x03,
+ SPI_PNT_SPRITE_SEL_NONE = 0x04,
+ PNT_SPRITE_OVRD_Y_mask = 0x07 << 5,
+ PNT_SPRITE_OVRD_Y_shift = 5,
+/* SPI_PNT_SPRITE_SEL_0 = 0x00, */
+/* SPI_PNT_SPRITE_SEL_1 = 0x01, */
+/* SPI_PNT_SPRITE_SEL_S = 0x02, */
+/* SPI_PNT_SPRITE_SEL_T = 0x03, */
+/* SPI_PNT_SPRITE_SEL_NONE = 0x04, */
+ PNT_SPRITE_OVRD_Z_mask = 0x07 << 8,
+ PNT_SPRITE_OVRD_Z_shift = 8,
+/* SPI_PNT_SPRITE_SEL_0 = 0x00, */
+/* SPI_PNT_SPRITE_SEL_1 = 0x01, */
+/* SPI_PNT_SPRITE_SEL_S = 0x02, */
+/* SPI_PNT_SPRITE_SEL_T = 0x03, */
+/* SPI_PNT_SPRITE_SEL_NONE = 0x04, */
+ PNT_SPRITE_OVRD_W_mask = 0x07 << 11,
+ PNT_SPRITE_OVRD_W_shift = 11,
+/* SPI_PNT_SPRITE_SEL_0 = 0x00, */
+/* SPI_PNT_SPRITE_SEL_1 = 0x01, */
+/* SPI_PNT_SPRITE_SEL_S = 0x02, */
+/* SPI_PNT_SPRITE_SEL_T = 0x03, */
+/* SPI_PNT_SPRITE_SEL_NONE = 0x04, */
+ PNT_SPRITE_TOP_1_bit = 1 << 14,
+ SPI_INPUT_Z = 0x000286d8,
+ PROVIDE_Z_TO_SPI_bit = 1 << 0,
+ SPI_FOG_CNTL = 0x000286dc,
+ PASS_FOG_THROUGH_PS_bit = 1 << 0,
+ PIXEL_FOG_FUNC_mask = 0x03 << 1,
+ PIXEL_FOG_FUNC_shift = 1,
+ SPI_FOG_NONE = 0x00,
+ SPI_FOG_EXP = 0x01,
+ SPI_FOG_EXP2 = 0x02,
+ SPI_FOG_LINEAR = 0x03,
+ PIXEL_FOG_SRC_SEL_bit = 1 << 3,
+ VS_FOG_CLAMP_DISABLE_bit = 1 << 4,
+ SPI_FOG_FUNC_SCALE = 0x000286e0,
+ SPI_FOG_FUNC_BIAS = 0x000286e4,
+ CB_BLEND0_CONTROL = 0x00028780,
+ CB_BLEND0_CONTROL_num = 8,
+ COLOR_SRCBLEND_mask = 0x1f << 0,
+ COLOR_SRCBLEND_shift = 0,
+ COLOR_COMB_FCN_mask = 0x07 << 5,
+ COLOR_COMB_FCN_shift = 5,
+ COLOR_DESTBLEND_mask = 0x1f << 8,
+ COLOR_DESTBLEND_shift = 8,
+ OPACITY_WEIGHT_bit = 1 << 13,
+ ALPHA_SRCBLEND_mask = 0x1f << 16,
+ ALPHA_SRCBLEND_shift = 16,
+ ALPHA_COMB_FCN_mask = 0x07 << 21,
+ ALPHA_COMB_FCN_shift = 21,
+ ALPHA_DESTBLEND_mask = 0x1f << 24,
+ ALPHA_DESTBLEND_shift = 24,
+ SEPARATE_ALPHA_BLEND_bit = 1 << 29,
+ VGT_DMA_BASE_HI = 0x000287e4,
+ VGT_DMA_BASE_HI__BASE_ADDR_mask = 0xff << 0,
+ VGT_DMA_BASE_HI__BASE_ADDR_shift = 0,
+ VGT_DMA_BASE = 0x000287e8,
+ VGT_DRAW_INITIATOR = 0x000287f0,
+ SOURCE_SELECT_mask = 0x03 << 0,
+ SOURCE_SELECT_shift = 0,
+ DI_SRC_SEL_DMA = 0x00,
+ DI_SRC_SEL_IMMEDIATE = 0x01,
+ DI_SRC_SEL_AUTO_INDEX = 0x02,
+ DI_SRC_SEL_RESERVED = 0x03,
+ MAJOR_MODE_mask = 0x03 << 2,
+ MAJOR_MODE_shift = 2,
+ DI_MAJOR_MODE_0 = 0x00,
+ DI_MAJOR_MODE_1 = 0x01,
+ SPRITE_EN_bit = 1 << 4,
+ NOT_EOP_bit = 1 << 5,
+ USE_OPAQUE_bit = 1 << 6,
+ VGT_IMMED_DATA = 0x000287f4,
+ VGT_EVENT_ADDRESS_REG = 0x000287f8,
+ ADDRESS_LOW_mask = 0xfffffff << 0,
+ ADDRESS_LOW_shift = 0,
+ DB_DEPTH_CONTROL = 0x00028800,
+ STENCIL_ENABLE_bit = 1 << 0,
+ Z_ENABLE_bit = 1 << 1,
+ Z_WRITE_ENABLE_bit = 1 << 2,
+ ZFUNC_mask = 0x07 << 4,
+ ZFUNC_shift = 4,
+ FRAG_NEVER = 0x00,
+ FRAG_LESS = 0x01,
+ FRAG_EQUAL = 0x02,
+ FRAG_LEQUAL = 0x03,
+ FRAG_GREATER = 0x04,
+ FRAG_NOTEQUAL = 0x05,
+ FRAG_GEQUAL = 0x06,
+ FRAG_ALWAYS = 0x07,
+ BACKFACE_ENABLE_bit = 1 << 7,
+ STENCILFUNC_mask = 0x07 << 8,
+ STENCILFUNC_shift = 8,
+/* REF_NEVER = 0x00, */
+/* REF_LESS = 0x01, */
+/* REF_EQUAL = 0x02, */
+/* REF_LEQUAL = 0x03, */
+/* REF_GREATER = 0x04, */
+/* REF_NOTEQUAL = 0x05, */
+/* REF_GEQUAL = 0x06, */
+/* REF_ALWAYS = 0x07, */
+ STENCILFAIL_mask = 0x07 << 11,
+ STENCILFAIL_shift = 11,
+ STENCIL_KEEP = 0x00,
+ STENCIL_ZERO = 0x01,
+ STENCIL_REPLACE = 0x02,
+ STENCIL_INCR_CLAMP = 0x03,
+ STENCIL_DECR_CLAMP = 0x04,
+ STENCIL_INVERT = 0x05,
+ STENCIL_INCR_WRAP = 0x06,
+ STENCIL_DECR_WRAP = 0x07,
+ STENCILZPASS_mask = 0x07 << 14,
+ STENCILZPASS_shift = 14,
+/* STENCIL_KEEP = 0x00, */
+/* STENCIL_ZERO = 0x01, */
+/* STENCIL_REPLACE = 0x02, */
+/* STENCIL_INCR_CLAMP = 0x03, */
+/* STENCIL_DECR_CLAMP = 0x04, */
+/* STENCIL_INVERT = 0x05, */
+/* STENCIL_INCR_WRAP = 0x06, */
+/* STENCIL_DECR_WRAP = 0x07, */
+ STENCILZFAIL_mask = 0x07 << 17,
+ STENCILZFAIL_shift = 17,
+/* STENCIL_KEEP = 0x00, */
+/* STENCIL_ZERO = 0x01, */
+/* STENCIL_REPLACE = 0x02, */
+/* STENCIL_INCR_CLAMP = 0x03, */
+/* STENCIL_DECR_CLAMP = 0x04, */
+/* STENCIL_INVERT = 0x05, */
+/* STENCIL_INCR_WRAP = 0x06, */
+/* STENCIL_DECR_WRAP = 0x07, */
+ STENCILFUNC_BF_mask = 0x07 << 20,
+ STENCILFUNC_BF_shift = 20,
+/* REF_NEVER = 0x00, */
+/* REF_LESS = 0x01, */
+/* REF_EQUAL = 0x02, */
+/* REF_LEQUAL = 0x03, */
+/* REF_GREATER = 0x04, */
+/* REF_NOTEQUAL = 0x05, */
+/* REF_GEQUAL = 0x06, */
+/* REF_ALWAYS = 0x07, */
+ STENCILFAIL_BF_mask = 0x07 << 23,
+ STENCILFAIL_BF_shift = 23,
+/* STENCIL_KEEP = 0x00, */
+/* STENCIL_ZERO = 0x01, */
+/* STENCIL_REPLACE = 0x02, */
+/* STENCIL_INCR_CLAMP = 0x03, */
+/* STENCIL_DECR_CLAMP = 0x04, */
+/* STENCIL_INVERT = 0x05, */
+/* STENCIL_INCR_WRAP = 0x06, */
+/* STENCIL_DECR_WRAP = 0x07, */
+ STENCILZPASS_BF_mask = 0x07 << 26,
+ STENCILZPASS_BF_shift = 26,
+/* STENCIL_KEEP = 0x00, */
+/* STENCIL_ZERO = 0x01, */
+/* STENCIL_REPLACE = 0x02, */
+/* STENCIL_INCR_CLAMP = 0x03, */
+/* STENCIL_DECR_CLAMP = 0x04, */
+/* STENCIL_INVERT = 0x05, */
+/* STENCIL_INCR_WRAP = 0x06, */
+/* STENCIL_DECR_WRAP = 0x07, */
+ STENCILZFAIL_BF_mask = 0x07 << 29,
+ STENCILZFAIL_BF_shift = 29,
+/* STENCIL_KEEP = 0x00, */
+/* STENCIL_ZERO = 0x01, */
+/* STENCIL_REPLACE = 0x02, */
+/* STENCIL_INCR_CLAMP = 0x03, */
+/* STENCIL_DECR_CLAMP = 0x04, */
+/* STENCIL_INVERT = 0x05, */
+/* STENCIL_INCR_WRAP = 0x06, */
+/* STENCIL_DECR_WRAP = 0x07, */
+ CB_BLEND_CONTROL = 0x00028804,
+/* COLOR_SRCBLEND_mask = 0x1f << 0, */
+/* COLOR_SRCBLEND_shift = 0, */
+ BLEND_ZERO = 0x00,
+ BLEND_ONE = 0x01,
+ BLEND_SRC_COLOR = 0x02,
+ BLEND_ONE_MINUS_SRC_COLOR = 0x03,
+ BLEND_SRC_ALPHA = 0x04,
+ BLEND_ONE_MINUS_SRC_ALPHA = 0x05,
+ BLEND_DST_ALPHA = 0x06,
+ BLEND_ONE_MINUS_DST_ALPHA = 0x07,
+ BLEND_DST_COLOR = 0x08,
+ BLEND_ONE_MINUS_DST_COLOR = 0x09,
+ BLEND_SRC_ALPHA_SATURATE = 0x0a,
+ BLEND_BOTH_SRC_ALPHA = 0x0b,
+ BLEND_BOTH_INV_SRC_ALPHA = 0x0c,
+ BLEND_CONSTANT_COLOR = 0x0d,
+ BLEND_ONE_MINUS_CONSTANT_COLOR = 0x0e,
+ BLEND_SRC1_COLOR = 0x0f,
+ BLEND_INV_SRC1_COLOR = 0x10,
+ BLEND_SRC1_ALPHA = 0x11,
+ BLEND_INV_SRC1_ALPHA = 0x12,
+ BLEND_CONSTANT_ALPHA = 0x13,
+ BLEND_ONE_MINUS_CONSTANT_ALPHA = 0x14,
+/* COLOR_COMB_FCN_mask = 0x07 << 5, */
+/* COLOR_COMB_FCN_shift = 5, */
+ COMB_DST_PLUS_SRC = 0x00,
+ COMB_SRC_MINUS_DST = 0x01,
+ COMB_MIN_DST_SRC = 0x02,
+ COMB_MAX_DST_SRC = 0x03,
+ COMB_DST_MINUS_SRC = 0x04,
+/* COLOR_DESTBLEND_mask = 0x1f << 8, */
+/* COLOR_DESTBLEND_shift = 8, */
+/* BLEND_ZERO = 0x00, */
+/* BLEND_ONE = 0x01, */
+/* BLEND_SRC_COLOR = 0x02, */
+/* BLEND_ONE_MINUS_SRC_COLOR = 0x03, */
+/* BLEND_SRC_ALPHA = 0x04, */
+/* BLEND_ONE_MINUS_SRC_ALPHA = 0x05, */
+/* BLEND_DST_ALPHA = 0x06, */
+/* BLEND_ONE_MINUS_DST_ALPHA = 0x07, */
+/* BLEND_DST_COLOR = 0x08, */
+/* BLEND_ONE_MINUS_DST_COLOR = 0x09, */
+/* BLEND_SRC_ALPHA_SATURATE = 0x0a, */
+/* BLEND_BOTH_SRC_ALPHA = 0x0b, */
+/* BLEND_BOTH_INV_SRC_ALPHA = 0x0c, */
+/* BLEND_CONSTANT_COLOR = 0x0d, */
+/* BLEND_ONE_MINUS_CONSTANT_COLOR = 0x0e, */
+/* BLEND_SRC1_COLOR = 0x0f, */
+/* BLEND_INV_SRC1_COLOR = 0x10, */
+/* BLEND_SRC1_ALPHA = 0x11, */
+/* BLEND_INV_SRC1_ALPHA = 0x12, */
+/* BLEND_CONSTANT_ALPHA = 0x13, */
+/* BLEND_ONE_MINUS_CONSTANT_ALPHA = 0x14, */
+/* OPACITY_WEIGHT_bit = 1 << 13, */
+/* ALPHA_SRCBLEND_mask = 0x1f << 16, */
+/* ALPHA_SRCBLEND_shift = 16, */
+/* BLEND_ZERO = 0x00, */
+/* BLEND_ONE = 0x01, */
+/* BLEND_SRC_COLOR = 0x02, */
+/* BLEND_ONE_MINUS_SRC_COLOR = 0x03, */
+/* BLEND_SRC_ALPHA = 0x04, */
+/* BLEND_ONE_MINUS_SRC_ALPHA = 0x05, */
+/* BLEND_DST_ALPHA = 0x06, */
+/* BLEND_ONE_MINUS_DST_ALPHA = 0x07, */
+/* BLEND_DST_COLOR = 0x08, */
+/* BLEND_ONE_MINUS_DST_COLOR = 0x09, */
+/* BLEND_SRC_ALPHA_SATURATE = 0x0a, */
+/* BLEND_BOTH_SRC_ALPHA = 0x0b, */
+/* BLEND_BOTH_INV_SRC_ALPHA = 0x0c, */
+/* BLEND_CONSTANT_COLOR = 0x0d, */
+/* BLEND_ONE_MINUS_CONSTANT_COLOR = 0x0e, */
+/* BLEND_SRC1_COLOR = 0x0f, */
+/* BLEND_INV_SRC1_COLOR = 0x10, */
+/* BLEND_SRC1_ALPHA = 0x11, */
+/* BLEND_INV_SRC1_ALPHA = 0x12, */
+/* BLEND_CONSTANT_ALPHA = 0x13, */
+/* BLEND_ONE_MINUS_CONSTANT_ALPHA = 0x14, */
+/* ALPHA_COMB_FCN_mask = 0x07 << 21, */
+/* ALPHA_COMB_FCN_shift = 21, */
+/* COMB_DST_PLUS_SRC = 0x00, */
+/* COMB_SRC_MINUS_DST = 0x01, */
+/* COMB_MIN_DST_SRC = 0x02, */
+/* COMB_MAX_DST_SRC = 0x03, */
+/* COMB_DST_MINUS_SRC = 0x04, */
+/* ALPHA_DESTBLEND_mask = 0x1f << 24, */
+/* ALPHA_DESTBLEND_shift = 24, */
+/* BLEND_ZERO = 0x00, */
+/* BLEND_ONE = 0x01, */
+/* BLEND_SRC_COLOR = 0x02, */
+/* BLEND_ONE_MINUS_SRC_COLOR = 0x03, */
+/* BLEND_SRC_ALPHA = 0x04, */
+/* BLEND_ONE_MINUS_SRC_ALPHA = 0x05, */
+/* BLEND_DST_ALPHA = 0x06, */
+/* BLEND_ONE_MINUS_DST_ALPHA = 0x07, */
+/* BLEND_DST_COLOR = 0x08, */
+/* BLEND_ONE_MINUS_DST_COLOR = 0x09, */
+/* BLEND_SRC_ALPHA_SATURATE = 0x0a, */
+/* BLEND_BOTH_SRC_ALPHA = 0x0b, */
+/* BLEND_BOTH_INV_SRC_ALPHA = 0x0c, */
+/* BLEND_CONSTANT_COLOR = 0x0d, */
+/* BLEND_ONE_MINUS_CONSTANT_COLOR = 0x0e, */
+/* BLEND_SRC1_COLOR = 0x0f, */
+/* BLEND_INV_SRC1_COLOR = 0x10, */
+/* BLEND_SRC1_ALPHA = 0x11, */
+/* BLEND_INV_SRC1_ALPHA = 0x12, */
+/* BLEND_CONSTANT_ALPHA = 0x13, */
+/* BLEND_ONE_MINUS_CONSTANT_ALPHA = 0x14, */
+/* SEPARATE_ALPHA_BLEND_bit = 1 << 29, */
+ CB_COLOR_CONTROL = 0x00028808,
+ FOG_ENABLE_bit = 1 << 0,
+ MULTIWRITE_ENABLE_bit = 1 << 1,
+ DITHER_ENABLE_bit = 1 << 2,
+ DEGAMMA_ENABLE_bit = 1 << 3,
+ SPECIAL_OP_mask = 0x07 << 4,
+ SPECIAL_OP_shift = 4,
+ SPECIAL_NORMAL = 0x00,
+ SPECIAL_DISABLE = 0x01,
+ SPECIAL_FAST_CLEAR = 0x02,
+ SPECIAL_FORCE_CLEAR = 0x03,
+ SPECIAL_EXPAND_COLOR = 0x04,
+ SPECIAL_EXPAND_TEXTURE = 0x05,
+ SPECIAL_EXPAND_SAMPLES = 0x06,
+ SPECIAL_RESOLVE_BOX = 0x07,
+ PER_MRT_BLEND_bit = 1 << 7,
+ TARGET_BLEND_ENABLE_mask = 0xff << 8,
+ TARGET_BLEND_ENABLE_shift = 8,
+ ROP3_mask = 0xff << 16,
+ ROP3_shift = 16,
+ DB_SHADER_CONTROL = 0x0002880c,
+ Z_EXPORT_ENABLE_bit = 1 << 0,
+ STENCIL_REF_EXPORT_ENABLE_bit = 1 << 1,
+ Z_ORDER_mask = 0x03 << 4,
+ Z_ORDER_shift = 4,
+ LATE_Z = 0x00,
+ EARLY_Z_THEN_LATE_Z = 0x01,
+ RE_Z = 0x02,
+ EARLY_Z_THEN_RE_Z = 0x03,
+ KILL_ENABLE_bit = 1 << 6,
+ COVERAGE_TO_MASK_ENABLE_bit = 1 << 7,
+ MASK_EXPORT_ENABLE_bit = 1 << 8,
+ DUAL_EXPORT_ENABLE_bit = 1 << 9,
+ EXEC_ON_HIER_FAIL_bit = 1 << 10,
+ EXEC_ON_NOOP_bit = 1 << 11,
+ PA_CL_CLIP_CNTL = 0x00028810,
+ UCP_ENA_0_bit = 1 << 0,
+ UCP_ENA_1_bit = 1 << 1,
+ UCP_ENA_2_bit = 1 << 2,
+ UCP_ENA_3_bit = 1 << 3,
+ UCP_ENA_4_bit = 1 << 4,
+ UCP_ENA_5_bit = 1 << 5,
+ PS_UCP_Y_SCALE_NEG_bit = 1 << 13,
+ PS_UCP_MODE_mask = 0x03 << 14,
+ PS_UCP_MODE_shift = 14,
+ CLIP_DISABLE_bit = 1 << 16,
+ UCP_CULL_ONLY_ENA_bit = 1 << 17,
+ BOUNDARY_EDGE_FLAG_ENA_bit = 1 << 18,
+ DX_CLIP_SPACE_DEF_bit = 1 << 19,
+ DIS_CLIP_ERR_DETECT_bit = 1 << 20,
+ VTX_KILL_OR_bit = 1 << 21,
+ DX_LINEAR_ATTR_CLIP_ENA_bit = 1 << 24,
+ VTE_VPORT_PROVOKE_DISABLE_bit = 1 << 25,
+ ZCLIP_NEAR_DISABLE_bit = 1 << 26,
+ ZCLIP_FAR_DISABLE_bit = 1 << 27,
+ PA_SU_SC_MODE_CNTL = 0x00028814,
+ CULL_FRONT_bit = 1 << 0,
+ CULL_BACK_bit = 1 << 1,
+ FACE_bit = 1 << 2,
+ POLY_MODE_mask = 0x03 << 3,
+ POLY_MODE_shift = 3,
+ X_DISABLE_POLY_MODE = 0x00,
+ X_DUAL_MODE = 0x01,
+ POLYMODE_FRONT_PTYPE_mask = 0x07 << 5,
+ POLYMODE_FRONT_PTYPE_shift = 5,
+ X_DRAW_POINTS = 0x00,
+ X_DRAW_LINES = 0x01,
+ X_DRAW_TRIANGLES = 0x02,
+ POLYMODE_BACK_PTYPE_mask = 0x07 << 8,
+ POLYMODE_BACK_PTYPE_shift = 8,
+/* X_DRAW_POINTS = 0x00, */
+/* X_DRAW_LINES = 0x01, */
+/* X_DRAW_TRIANGLES = 0x02, */
+ POLY_OFFSET_FRONT_ENABLE_bit = 1 << 11,
+ POLY_OFFSET_BACK_ENABLE_bit = 1 << 12,
+ POLY_OFFSET_PARA_ENABLE_bit = 1 << 13,
+ VTX_WINDOW_OFFSET_ENABLE_bit = 1 << 16,
+ PROVOKING_VTX_LAST_bit = 1 << 19,
+ PERSP_CORR_DIS_bit = 1 << 20,
+ MULTI_PRIM_IB_ENA_bit = 1 << 21,
+ PA_CL_VTE_CNTL = 0x00028818,
+ VPORT_X_SCALE_ENA_bit = 1 << 0,
+ VPORT_X_OFFSET_ENA_bit = 1 << 1,
+ VPORT_Y_SCALE_ENA_bit = 1 << 2,
+ VPORT_Y_OFFSET_ENA_bit = 1 << 3,
+ VPORT_Z_SCALE_ENA_bit = 1 << 4,
+ VPORT_Z_OFFSET_ENA_bit = 1 << 5,
+ VTX_XY_FMT_bit = 1 << 8,
+ VTX_Z_FMT_bit = 1 << 9,
+ VTX_W0_FMT_bit = 1 << 10,
+ PERFCOUNTER_REF_bit = 1 << 11,
+ PA_CL_VS_OUT_CNTL = 0x0002881c,
+ CLIP_DIST_ENA_0_bit = 1 << 0,
+ CLIP_DIST_ENA_1_bit = 1 << 1,
+ CLIP_DIST_ENA_2_bit = 1 << 2,
+ CLIP_DIST_ENA_3_bit = 1 << 3,
+ CLIP_DIST_ENA_4_bit = 1 << 4,
+ CLIP_DIST_ENA_5_bit = 1 << 5,
+ CLIP_DIST_ENA_6_bit = 1 << 6,
+ CLIP_DIST_ENA_7_bit = 1 << 7,
+ CULL_DIST_ENA_0_bit = 1 << 8,
+ CULL_DIST_ENA_1_bit = 1 << 9,
+ CULL_DIST_ENA_2_bit = 1 << 10,
+ CULL_DIST_ENA_3_bit = 1 << 11,
+ CULL_DIST_ENA_4_bit = 1 << 12,
+ CULL_DIST_ENA_5_bit = 1 << 13,
+ CULL_DIST_ENA_6_bit = 1 << 14,
+ CULL_DIST_ENA_7_bit = 1 << 15,
+ USE_VTX_POINT_SIZE_bit = 1 << 16,
+ USE_VTX_EDGE_FLAG_bit = 1 << 17,
+ USE_VTX_RENDER_TARGET_INDX_bit = 1 << 18,
+ USE_VTX_VIEWPORT_INDX_bit = 1 << 19,
+ USE_VTX_KILL_FLAG_bit = 1 << 20,
+ VS_OUT_MISC_VEC_ENA_bit = 1 << 21,
+ VS_OUT_CCDIST0_VEC_ENA_bit = 1 << 22,
+ VS_OUT_CCDIST1_VEC_ENA_bit = 1 << 23,
+ PA_CL_NANINF_CNTL = 0x00028820,
+ VTE_XY_INF_DISCARD_bit = 1 << 0,
+ VTE_Z_INF_DISCARD_bit = 1 << 1,
+ VTE_W_INF_DISCARD_bit = 1 << 2,
+ VTE_0XNANINF_IS_0_bit = 1 << 3,
+ VTE_XY_NAN_RETAIN_bit = 1 << 4,
+ VTE_Z_NAN_RETAIN_bit = 1 << 5,
+ VTE_W_NAN_RETAIN_bit = 1 << 6,
+ VTE_W_RECIP_NAN_IS_0_bit = 1 << 7,
+ VS_XY_NAN_TO_INF_bit = 1 << 8,
+ VS_XY_INF_RETAIN_bit = 1 << 9,
+ VS_Z_NAN_TO_INF_bit = 1 << 10,
+ VS_Z_INF_RETAIN_bit = 1 << 11,
+ VS_W_NAN_TO_INF_bit = 1 << 12,
+ VS_W_INF_RETAIN_bit = 1 << 13,
+ VS_CLIP_DIST_INF_DISCARD_bit = 1 << 14,
+ VTE_NO_OUTPUT_NEG_0_bit = 1 << 20,
+ SQ_PGM_START_PS = 0x00028840,
+ SQ_PGM_RESOURCES_PS = 0x00028850,
+ NUM_GPRS_mask = 0xff << 0,
+ NUM_GPRS_shift = 0,
+ STACK_SIZE_mask = 0xff << 8,
+ STACK_SIZE_shift = 8,
+ SQ_PGM_RESOURCES_PS__DX10_CLAMP_bit = 1 << 21,
+ FETCH_CACHE_LINES_mask = 0x07 << 24,
+ FETCH_CACHE_LINES_shift = 24,
+ UNCACHED_FIRST_INST_bit = 1 << 28,
+ CLAMP_CONSTS_bit = 1 << 31,
+ SQ_PGM_EXPORTS_PS = 0x00028854,
+ EXPORT_MODE_mask = 0x1f << 0,
+ EXPORT_MODE_shift = 0,
+ SQ_PGM_START_VS = 0x00028858,
+ SQ_PGM_RESOURCES_VS = 0x00028868,
+/* NUM_GPRS_mask = 0xff << 0, */
+/* NUM_GPRS_shift = 0, */
+/* STACK_SIZE_mask = 0xff << 8, */
+/* STACK_SIZE_shift = 8, */
+ SQ_PGM_RESOURCES_VS__DX10_CLAMP_bit = 1 << 21,
+/* FETCH_CACHE_LINES_mask = 0x07 << 24, */
+/* FETCH_CACHE_LINES_shift = 24, */
+/* UNCACHED_FIRST_INST_bit = 1 << 28, */
+ SQ_PGM_START_GS = 0x0002886c,
+ SQ_PGM_RESOURCES_GS = 0x0002887c,
+/* NUM_GPRS_mask = 0xff << 0, */
+/* NUM_GPRS_shift = 0, */
+/* STACK_SIZE_mask = 0xff << 8, */
+/* STACK_SIZE_shift = 8, */
+ SQ_PGM_RESOURCES_GS__DX10_CLAMP_bit = 1 << 21,
+/* FETCH_CACHE_LINES_mask = 0x07 << 24, */
+/* FETCH_CACHE_LINES_shift = 24, */
+/* UNCACHED_FIRST_INST_bit = 1 << 28, */
+ SQ_PGM_START_ES = 0x00028880,
+ SQ_PGM_RESOURCES_ES = 0x00028890,
+/* NUM_GPRS_mask = 0xff << 0, */
+/* NUM_GPRS_shift = 0, */
+/* STACK_SIZE_mask = 0xff << 8, */
+/* STACK_SIZE_shift = 8, */
+ SQ_PGM_RESOURCES_ES__DX10_CLAMP_bit = 1 << 21,
+/* FETCH_CACHE_LINES_mask = 0x07 << 24, */
+/* FETCH_CACHE_LINES_shift = 24, */
+/* UNCACHED_FIRST_INST_bit = 1 << 28, */
+ SQ_PGM_START_FS = 0x00028894,
+ SQ_PGM_RESOURCES_FS = 0x000288a4,
+/* NUM_GPRS_mask = 0xff << 0, */
+/* NUM_GPRS_shift = 0, */
+/* STACK_SIZE_mask = 0xff << 8, */
+/* STACK_SIZE_shift = 8, */
+ SQ_PGM_RESOURCES_FS__DX10_CLAMP_bit = 1 << 21,
+ SQ_ESGS_RING_ITEMSIZE = 0x000288a8,
+ ITEMSIZE_mask = 0x7fff << 0,
+ ITEMSIZE_shift = 0,
+ SQ_GSVS_RING_ITEMSIZE = 0x000288ac,
+/* ITEMSIZE_mask = 0x7fff << 0, */
+/* ITEMSIZE_shift = 0, */
+ SQ_ESTMP_RING_ITEMSIZE = 0x000288b0,
+/* ITEMSIZE_mask = 0x7fff << 0, */
+/* ITEMSIZE_shift = 0, */
+ SQ_GSTMP_RING_ITEMSIZE = 0x000288b4,
+/* ITEMSIZE_mask = 0x7fff << 0, */
+/* ITEMSIZE_shift = 0, */
+ SQ_VSTMP_RING_ITEMSIZE = 0x000288b8,
+/* ITEMSIZE_mask = 0x7fff << 0, */
+/* ITEMSIZE_shift = 0, */
+ SQ_PSTMP_RING_ITEMSIZE = 0x000288bc,
+/* ITEMSIZE_mask = 0x7fff << 0, */
+/* ITEMSIZE_shift = 0, */
+ SQ_FBUF_RING_ITEMSIZE = 0x000288c0,
+/* ITEMSIZE_mask = 0x7fff << 0, */
+/* ITEMSIZE_shift = 0, */
+ SQ_REDUC_RING_ITEMSIZE = 0x000288c4,
+/* ITEMSIZE_mask = 0x7fff << 0, */
+/* ITEMSIZE_shift = 0, */
+ SQ_GS_VERT_ITEMSIZE = 0x000288c8,
+/* ITEMSIZE_mask = 0x7fff << 0, */
+/* ITEMSIZE_shift = 0, */
+ SQ_PGM_CF_OFFSET_PS = 0x000288cc,
+ PGM_CF_OFFSET_mask = 0xfffff << 0,
+ PGM_CF_OFFSET_shift = 0,
+ SQ_PGM_CF_OFFSET_VS = 0x000288d0,
+/* PGM_CF_OFFSET_mask = 0xfffff << 0, */
+/* PGM_CF_OFFSET_shift = 0, */
+ SQ_PGM_CF_OFFSET_GS = 0x000288d4,
+/* PGM_CF_OFFSET_mask = 0xfffff << 0, */
+/* PGM_CF_OFFSET_shift = 0, */
+ SQ_PGM_CF_OFFSET_ES = 0x000288d8,
+/* PGM_CF_OFFSET_mask = 0xfffff << 0, */
+/* PGM_CF_OFFSET_shift = 0, */
+ SQ_PGM_CF_OFFSET_FS = 0x000288dc,
+/* PGM_CF_OFFSET_mask = 0xfffff << 0, */
+/* PGM_CF_OFFSET_shift = 0, */
+ SQ_VTX_SEMANTIC_CLEAR = 0x000288e0,
+ SQ_ALU_CONST_CACHE_PS_0 = 0x00028940,
+ SQ_ALU_CONST_CACHE_PS_0_num = 16,
+ SQ_ALU_CONST_CACHE_VS_0 = 0x00028980,
+ SQ_ALU_CONST_CACHE_VS_0_num = 16,
+ SQ_ALU_CONST_CACHE_GS_0 = 0x000289c0,
+ SQ_ALU_CONST_CACHE_GS_0_num = 16,
+ PA_SU_POINT_SIZE = 0x00028a00,
+ PA_SU_POINT_SIZE__HEIGHT_mask = 0xffff << 0,
+ PA_SU_POINT_SIZE__HEIGHT_shift = 0,
+ PA_SU_POINT_SIZE__WIDTH_mask = 0xffff << 16,
+ PA_SU_POINT_SIZE__WIDTH_shift = 16,
+ PA_SU_POINT_MINMAX = 0x00028a04,
+ MIN_SIZE_mask = 0xffff << 0,
+ MIN_SIZE_shift = 0,
+ MAX_SIZE_mask = 0xffff << 16,
+ MAX_SIZE_shift = 16,
+ PA_SU_LINE_CNTL = 0x00028a08,
+ PA_SU_LINE_CNTL__WIDTH_mask = 0xffff << 0,
+ PA_SU_LINE_CNTL__WIDTH_shift = 0,
+ PA_SC_LINE_STIPPLE = 0x00028a0c,
+ LINE_PATTERN_mask = 0xffff << 0,
+ LINE_PATTERN_shift = 0,
+ REPEAT_COUNT_mask = 0xff << 16,
+ REPEAT_COUNT_shift = 16,
+ PATTERN_BIT_ORDER_bit = 1 << 28,
+ AUTO_RESET_CNTL_mask = 0x03 << 29,
+ AUTO_RESET_CNTL_shift = 29,
+ VGT_OUTPUT_PATH_CNTL = 0x00028a10,
+ PATH_SELECT_mask = 0x03 << 0,
+ PATH_SELECT_shift = 0,
+ VGT_OUTPATH_VTX_REUSE = 0x00,
+ VGT_OUTPATH_TESS_EN = 0x01,
+ VGT_OUTPATH_PASSTHRU = 0x02,
+ VGT_OUTPATH_GS_BLOCK = 0x03,
+ VGT_HOS_CNTL = 0x00028a14,
+ TESS_MODE_mask = 0x03 << 0,
+ TESS_MODE_shift = 0,
+ VGT_HOS_MAX_TESS_LEVEL = 0x00028a18,
+ VGT_HOS_MIN_TESS_LEVEL = 0x00028a1c,
+ VGT_HOS_REUSE_DEPTH = 0x00028a20,
+ REUSE_DEPTH_mask = 0xff << 0,
+ REUSE_DEPTH_shift = 0,
+ VGT_GROUP_PRIM_TYPE = 0x00028a24,
+ VGT_GROUP_PRIM_TYPE__PRIM_TYPE_mask = 0x1f << 0,
+ VGT_GROUP_PRIM_TYPE__PRIM_TYPE_shift = 0,
+ VGT_GRP_3D_POINT = 0x00,
+ VGT_GRP_3D_LINE = 0x01,
+ VGT_GRP_3D_TRI = 0x02,
+ VGT_GRP_3D_RECT = 0x03,
+ VGT_GRP_3D_QUAD = 0x04,
+ VGT_GRP_2D_COPY_RECT_V0 = 0x05,
+ VGT_GRP_2D_COPY_RECT_V1 = 0x06,
+ VGT_GRP_2D_COPY_RECT_V2 = 0x07,
+ VGT_GRP_2D_COPY_RECT_V3 = 0x08,
+ VGT_GRP_2D_FILL_RECT = 0x09,
+ VGT_GRP_2D_LINE = 0x0a,
+ VGT_GRP_2D_TRI = 0x0b,
+ VGT_GRP_PRIM_INDEX_LINE = 0x0c,
+ VGT_GRP_PRIM_INDEX_TRI = 0x0d,
+ VGT_GRP_PRIM_INDEX_QUAD = 0x0e,
+ VGT_GRP_3D_LINE_ADJ = 0x0f,
+ VGT_GRP_3D_TRI_ADJ = 0x10,
+ RETAIN_ORDER_bit = 1 << 14,
+ RETAIN_QUADS_bit = 1 << 15,
+ PRIM_ORDER_mask = 0x07 << 16,
+ PRIM_ORDER_shift = 16,
+ VGT_GRP_LIST = 0x00,
+ VGT_GRP_STRIP = 0x01,
+ VGT_GRP_FAN = 0x02,
+ VGT_GRP_LOOP = 0x03,
+ VGT_GRP_POLYGON = 0x04,
+ VGT_GROUP_FIRST_DECR = 0x00028a28,
+ FIRST_DECR_mask = 0x0f << 0,
+ FIRST_DECR_shift = 0,
+ VGT_GROUP_DECR = 0x00028a2c,
+ DECR_mask = 0x0f << 0,
+ DECR_shift = 0,
+ VGT_GROUP_VECT_0_CNTL = 0x00028a30,
+ COMP_X_EN_bit = 1 << 0,
+ COMP_Y_EN_bit = 1 << 1,
+ COMP_Z_EN_bit = 1 << 2,
+ COMP_W_EN_bit = 1 << 3,
+ VGT_GROUP_VECT_0_CNTL__STRIDE_mask = 0xff << 8,
+ VGT_GROUP_VECT_0_CNTL__STRIDE_shift = 8,
+ SHIFT_mask = 0xff << 16,
+ SHIFT_shift = 16,
+ VGT_GROUP_VECT_1_CNTL = 0x00028a34,
+/* COMP_X_EN_bit = 1 << 0, */
+/* COMP_Y_EN_bit = 1 << 1, */
+/* COMP_Z_EN_bit = 1 << 2, */
+/* COMP_W_EN_bit = 1 << 3, */
+ VGT_GROUP_VECT_1_CNTL__STRIDE_mask = 0xff << 8,
+ VGT_GROUP_VECT_1_CNTL__STRIDE_shift = 8,
+/* SHIFT_mask = 0xff << 16, */
+/* SHIFT_shift = 16, */
+ VGT_GROUP_VECT_0_FMT_CNTL = 0x00028a38,
+ X_CONV_mask = 0x0f << 0,
+ X_CONV_shift = 0,
+ VGT_GRP_INDEX_16 = 0x00,
+ VGT_GRP_INDEX_32 = 0x01,
+ VGT_GRP_UINT_16 = 0x02,
+ VGT_GRP_UINT_32 = 0x03,
+ VGT_GRP_SINT_16 = 0x04,
+ VGT_GRP_SINT_32 = 0x05,
+ VGT_GRP_FLOAT_32 = 0x06,
+ VGT_GRP_AUTO_PRIM = 0x07,
+ VGT_GRP_FIX_1_23_TO_FLOAT = 0x08,
+ X_OFFSET_mask = 0x0f << 4,
+ X_OFFSET_shift = 4,
+ Y_CONV_mask = 0x0f << 8,
+ Y_CONV_shift = 8,
+/* VGT_GRP_INDEX_16 = 0x00, */
+/* VGT_GRP_INDEX_32 = 0x01, */
+/* VGT_GRP_UINT_16 = 0x02, */
+/* VGT_GRP_UINT_32 = 0x03, */
+/* VGT_GRP_SINT_16 = 0x04, */
+/* VGT_GRP_SINT_32 = 0x05, */
+/* VGT_GRP_FLOAT_32 = 0x06, */
+/* VGT_GRP_AUTO_PRIM = 0x07, */
+/* VGT_GRP_FIX_1_23_TO_FLOAT = 0x08, */
+ Y_OFFSET_mask = 0x0f << 12,
+ Y_OFFSET_shift = 12,
+ Z_CONV_mask = 0x0f << 16,
+ Z_CONV_shift = 16,
+/* VGT_GRP_INDEX_16 = 0x00, */
+/* VGT_GRP_INDEX_32 = 0x01, */
+/* VGT_GRP_UINT_16 = 0x02, */
+/* VGT_GRP_UINT_32 = 0x03, */
+/* VGT_GRP_SINT_16 = 0x04, */
+/* VGT_GRP_SINT_32 = 0x05, */
+/* VGT_GRP_FLOAT_32 = 0x06, */
+/* VGT_GRP_AUTO_PRIM = 0x07, */
+/* VGT_GRP_FIX_1_23_TO_FLOAT = 0x08, */
+ Z_OFFSET_mask = 0x0f << 20,
+ Z_OFFSET_shift = 20,
+ W_CONV_mask = 0x0f << 24,
+ W_CONV_shift = 24,
+/* VGT_GRP_INDEX_16 = 0x00, */
+/* VGT_GRP_INDEX_32 = 0x01, */
+/* VGT_GRP_UINT_16 = 0x02, */
+/* VGT_GRP_UINT_32 = 0x03, */
+/* VGT_GRP_SINT_16 = 0x04, */
+/* VGT_GRP_SINT_32 = 0x05, */
+/* VGT_GRP_FLOAT_32 = 0x06, */
+/* VGT_GRP_AUTO_PRIM = 0x07, */
+/* VGT_GRP_FIX_1_23_TO_FLOAT = 0x08, */
+ W_OFFSET_mask = 0x0f << 28,
+ W_OFFSET_shift = 28,
+ VGT_GROUP_VECT_1_FMT_CNTL = 0x00028a3c,
+/* X_CONV_mask = 0x0f << 0, */
+/* X_CONV_shift = 0, */
+/* VGT_GRP_INDEX_16 = 0x00, */
+/* VGT_GRP_INDEX_32 = 0x01, */
+/* VGT_GRP_UINT_16 = 0x02, */
+/* VGT_GRP_UINT_32 = 0x03, */
+/* VGT_GRP_SINT_16 = 0x04, */
+/* VGT_GRP_SINT_32 = 0x05, */
+/* VGT_GRP_FLOAT_32 = 0x06, */
+/* VGT_GRP_AUTO_PRIM = 0x07, */
+/* VGT_GRP_FIX_1_23_TO_FLOAT = 0x08, */
+/* X_OFFSET_mask = 0x0f << 4, */
+/* X_OFFSET_shift = 4, */
+/* Y_CONV_mask = 0x0f << 8, */
+/* Y_CONV_shift = 8, */
+/* VGT_GRP_INDEX_16 = 0x00, */
+/* VGT_GRP_INDEX_32 = 0x01, */
+/* VGT_GRP_UINT_16 = 0x02, */
+/* VGT_GRP_UINT_32 = 0x03, */
+/* VGT_GRP_SINT_16 = 0x04, */
+/* VGT_GRP_SINT_32 = 0x05, */
+/* VGT_GRP_FLOAT_32 = 0x06, */
+/* VGT_GRP_AUTO_PRIM = 0x07, */
+/* VGT_GRP_FIX_1_23_TO_FLOAT = 0x08, */
+/* Y_OFFSET_mask = 0x0f << 12, */
+/* Y_OFFSET_shift = 12, */
+/* Z_CONV_mask = 0x0f << 16, */
+/* Z_CONV_shift = 16, */
+/* VGT_GRP_INDEX_16 = 0x00, */
+/* VGT_GRP_INDEX_32 = 0x01, */
+/* VGT_GRP_UINT_16 = 0x02, */
+/* VGT_GRP_UINT_32 = 0x03, */
+/* VGT_GRP_SINT_16 = 0x04, */
+/* VGT_GRP_SINT_32 = 0x05, */
+/* VGT_GRP_FLOAT_32 = 0x06, */
+/* VGT_GRP_AUTO_PRIM = 0x07, */
+/* VGT_GRP_FIX_1_23_TO_FLOAT = 0x08, */
+/* Z_OFFSET_mask = 0x0f << 20, */
+/* Z_OFFSET_shift = 20, */
+/* W_CONV_mask = 0x0f << 24, */
+/* W_CONV_shift = 24, */
+/* VGT_GRP_INDEX_16 = 0x00, */
+/* VGT_GRP_INDEX_32 = 0x01, */
+/* VGT_GRP_UINT_16 = 0x02, */
+/* VGT_GRP_UINT_32 = 0x03, */
+/* VGT_GRP_SINT_16 = 0x04, */
+/* VGT_GRP_SINT_32 = 0x05, */
+/* VGT_GRP_FLOAT_32 = 0x06, */
+/* VGT_GRP_AUTO_PRIM = 0x07, */
+/* VGT_GRP_FIX_1_23_TO_FLOAT = 0x08, */
+/* W_OFFSET_mask = 0x0f << 28, */
+/* W_OFFSET_shift = 28, */
+ VGT_GS_MODE = 0x00028a40,
+ MODE_mask = 0x03 << 0,
+ MODE_shift = 0,
+ GS_OFF = 0x00,
+ GS_SCENARIO_A = 0x01,
+ GS_SCENARIO_B = 0x02,
+ GS_SCENARIO_G = 0x03,
+ ES_PASSTHRU_bit = 1 << 2,
+ CUT_MODE_mask = 0x03 << 3,
+ CUT_MODE_shift = 3,
+ GS_CUT_1024 = 0x00,
+ GS_CUT_512 = 0x01,
+ GS_CUT_256 = 0x02,
+ GS_CUT_128 = 0x03,
+ PA_SC_MPASS_PS_CNTL = 0x00028a48,
+ MPASS_PIX_VEC_PER_PASS_mask = 0xfffff << 0,
+ MPASS_PIX_VEC_PER_PASS_shift = 0,
+ MPASS_PS_ENA_bit = 1 << 31,
+ PA_SC_MODE_CNTL = 0x00028a4c,
+ MSAA_ENABLE_bit = 1 << 0,
+ CLIPRECT_ENABLE_bit = 1 << 1,
+ LINE_STIPPLE_ENABLE_bit = 1 << 2,
+ MULTI_CHIP_PRIM_DISCARD_ENAB_bit = 1 << 3,
+ WALK_ORDER_ENABLE_bit = 1 << 4,
+ HALVE_DETAIL_SAMPLE_PERF_bit = 1 << 5,
+ WALK_SIZE_bit = 1 << 6,
+ WALK_ALIGNMENT_bit = 1 << 7,
+ WALK_ALIGN8_PRIM_FITS_ST_bit = 1 << 8,
+ TILE_COVER_NO_SCISSOR_bit = 1 << 9,
+ KILL_PIX_POST_HI_Z_bit = 1 << 10,
+ KILL_PIX_POST_DETAIL_MASK_bit = 1 << 11,
+ MULTI_CHIP_SUPERTILE_ENABLE_bit = 1 << 12,
+ TILE_COVER_DISABLE_bit = 1 << 13,
+ FORCE_EOV_CNTDWN_ENABLE_bit = 1 << 14,
+ FORCE_EOV_TILE_ENABLE_bit = 1 << 15,
+ FORCE_EOV_REZ_ENABLE_bit = 1 << 16,
+ PS_ITER_SAMPLE_bit = 1 << 17,
+ VGT_ENHANCE = 0x00028a50,
+ VGT_ENHANCE__MI_TIMESTAMP_RES_mask = 0x03 << 0,
+ VGT_ENHANCE__MI_TIMESTAMP_RES_shift = 0,
+ X_0_992_CLOCKS_LATENCY_RANGE_IN_STEPS_OF_32 = 0x00,
+ X_0_496_CLOCKS_LATENCY_RANGE_IN_STEPS_OF_16 = 0x01,
+ X_0_248_CLOCKS_LATENCY_RANGE_IN_STEPS_OF_8 = 0x02,
+ X_0_124_CLOCKS_LATENCY_RANGE_IN_STEPS_OF_4 = 0x03,
+ MISC_mask = 0x3fffffff << 2,
+ MISC_shift = 2,
+ VGT_GS_OUT_PRIM_TYPE = 0x00028a6c,
+ OUTPRIM_TYPE_mask = 0x3f << 0,
+ OUTPRIM_TYPE_shift = 0,
+ POINTLIST = 0x00,
+ LINESTRIP = 0x01,
+ TRISTRIP = 0x02,
+ VGT_DMA_SIZE = 0x00028a74,
+ VGT_DMA_INDEX_TYPE = 0x00028a7c,
+/* INDEX_TYPE_mask = 0x03 << 0, */
+/* INDEX_TYPE_shift = 0, */
+ VGT_INDEX_16 = 0x00,
+ VGT_INDEX_32 = 0x01,
+ SWAP_MODE_mask = 0x03 << 2,
+ SWAP_MODE_shift = 2,
+ VGT_DMA_SWAP_NONE = 0x00,
+ VGT_DMA_SWAP_16_BIT = 0x01,
+ VGT_DMA_SWAP_32_BIT = 0x02,
+ VGT_DMA_SWAP_WORD = 0x03,
+ VGT_PRIMITIVEID_EN = 0x00028a84,
+ PRIMITIVEID_EN_bit = 1 << 0,
+ VGT_DMA_NUM_INSTANCES = 0x00028a88,
+ VGT_EVENT_INITIATOR = 0x00028a90,
+ EVENT_TYPE_mask = 0x3f << 0,
+ EVENT_TYPE_shift = 0,
+ CACHE_FLUSH_TS = 0x04,
+ CONTEXT_DONE = 0x05,
+ CACHE_FLUSH = 0x06,
+ VIZQUERY_START = 0x07,
+ VIZQUERY_END = 0x08,
+ SC_WAIT_WC = 0x09,
+ MPASS_PS_CP_REFETCH = 0x0a,
+ MPASS_PS_RST_START = 0x0b,
+ MPASS_PS_INCR_START = 0x0c,
+ RST_PIX_CNT = 0x0d,
+ RST_VTX_CNT = 0x0e,
+ VS_PARTIAL_FLUSH = 0x0f,
+ PS_PARTIAL_FLUSH = 0x10,
+ CACHE_FLUSH_AND_INV_TS_EVENT = 0x14,
+ ZPASS_DONE = 0x15,
+ CACHE_FLUSH_AND_INV_EVENT = 0x16,
+ PERFCOUNTER_START = 0x17,
+ PERFCOUNTER_STOP = 0x18,
+ PIPELINESTAT_START = 0x19,
+ PIPELINESTAT_STOP = 0x1a,
+ PERFCOUNTER_SAMPLE = 0x1b,
+ FLUSH_ES_OUTPUT = 0x1c,
+ FLUSH_GS_OUTPUT = 0x1d,
+ SAMPLE_PIPELINESTAT = 0x1e,
+ SO_VGTSTREAMOUT_FLUSH = 0x1f,
+ SAMPLE_STREAMOUTSTATS = 0x20,
+ RESET_VTX_CNT = 0x21,
+ BLOCK_CONTEXT_DONE = 0x22,
+ CR_CONTEXT_DONE = 0x23,
+ VGT_FLUSH = 0x24,
+ CR_DONE_TS = 0x25,
+ SQ_NON_EVENT = 0x26,
+ SC_SEND_DB_VPZ = 0x27,
+ BOTTOM_OF_PIPE_TS = 0x28,
+ DB_CACHE_FLUSH_AND_INV = 0x2a,
+ ADDRESS_HI_mask = 0xff << 19,
+ ADDRESS_HI_shift = 19,
+ EXTENDED_EVENT_bit = 1 << 27,
+ VGT_MULTI_PRIM_IB_RESET_EN = 0x00028a94,
+ RESET_EN_bit = 1 << 0,
+ VGT_INSTANCE_STEP_RATE_0 = 0x00028aa0,
+ VGT_INSTANCE_STEP_RATE_1 = 0x00028aa4,
+ VGT_STRMOUT_EN = 0x00028ab0,
+ STREAMOUT_bit = 1 << 0,
+ VGT_REUSE_OFF = 0x00028ab4,
+ REUSE_OFF_bit = 1 << 0,
+ VGT_VTX_CNT_EN = 0x00028ab8,
+ VTX_CNT_EN_bit = 1 << 0,
+ VGT_STRMOUT_BUFFER_SIZE_0 = 0x00028ad0,
+ VGT_STRMOUT_VTX_STRIDE_0 = 0x00028ad4,
+ VGT_STRMOUT_VTX_STRIDE_0__STRIDE_mask = 0x3ff << 0,
+ VGT_STRMOUT_VTX_STRIDE_0__STRIDE_shift = 0,
+ VGT_STRMOUT_BUFFER_BASE_0 = 0x00028ad8,
+ VGT_STRMOUT_BUFFER_OFFSET_0 = 0x00028adc,
+ VGT_STRMOUT_BUFFER_SIZE_1 = 0x00028ae0,
+ VGT_STRMOUT_VTX_STRIDE_1 = 0x00028ae4,
+ VGT_STRMOUT_VTX_STRIDE_1__STRIDE_mask = 0x3ff << 0,
+ VGT_STRMOUT_VTX_STRIDE_1__STRIDE_shift = 0,
+ VGT_STRMOUT_BUFFER_BASE_1 = 0x00028ae8,
+ VGT_STRMOUT_BUFFER_OFFSET_1 = 0x00028aec,
+ VGT_STRMOUT_BUFFER_SIZE_2 = 0x00028af0,
+ VGT_STRMOUT_VTX_STRIDE_2 = 0x00028af4,
+ VGT_STRMOUT_VTX_STRIDE_2__STRIDE_mask = 0x3ff << 0,
+ VGT_STRMOUT_VTX_STRIDE_2__STRIDE_shift = 0,
+ VGT_STRMOUT_BUFFER_BASE_2 = 0x00028af8,
+ VGT_STRMOUT_BUFFER_OFFSET_2 = 0x00028afc,
+ VGT_STRMOUT_BUFFER_SIZE_3 = 0x00028b00,
+ VGT_STRMOUT_VTX_STRIDE_3 = 0x00028b04,
+ VGT_STRMOUT_VTX_STRIDE_3__STRIDE_mask = 0x3ff << 0,
+ VGT_STRMOUT_VTX_STRIDE_3__STRIDE_shift = 0,
+ VGT_STRMOUT_BUFFER_BASE_3 = 0x00028b08,
+ VGT_STRMOUT_BUFFER_OFFSET_3 = 0x00028b0c,
+ VGT_STRMOUT_BASE_OFFSET_0 = 0x00028b10,
+ VGT_STRMOUT_BASE_OFFSET_1 = 0x00028b14,
+ VGT_STRMOUT_BASE_OFFSET_2 = 0x00028b18,
+ VGT_STRMOUT_BASE_OFFSET_3 = 0x00028b1c,
+ VGT_STRMOUT_BUFFER_EN = 0x00028b20,
+ BUFFER_0_EN_bit = 1 << 0,
+ BUFFER_1_EN_bit = 1 << 1,
+ BUFFER_2_EN_bit = 1 << 2,
+ BUFFER_3_EN_bit = 1 << 3,
+ VGT_STRMOUT_DRAW_OPAQUE_OFFSET = 0x00028b28,
+ VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE = 0x00028b2c,
+ VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE = 0x00028b30,
+ VGT_STRMOUT_BASE_OFFSET_HI_0 = 0x00028b44,
+ VGT_STRMOUT_BASE_OFFSET_HI_0__BASE_OFFSET_mask = 0x3f << 0,
+ VGT_STRMOUT_BASE_OFFSET_HI_0__BASE_OFFSET_shift = 0,
+ VGT_STRMOUT_BASE_OFFSET_HI_1 = 0x00028b48,
+ VGT_STRMOUT_BASE_OFFSET_HI_1__BASE_OFFSET_mask = 0x3f << 0,
+ VGT_STRMOUT_BASE_OFFSET_HI_1__BASE_OFFSET_shift = 0,
+ VGT_STRMOUT_BASE_OFFSET_HI_2 = 0x00028b4c,
+ VGT_STRMOUT_BASE_OFFSET_HI_2__BASE_OFFSET_mask = 0x3f << 0,
+ VGT_STRMOUT_BASE_OFFSET_HI_2__BASE_OFFSET_shift = 0,
+ VGT_STRMOUT_BASE_OFFSET_HI_3 = 0x00028b50,
+ VGT_STRMOUT_BASE_OFFSET_HI_3__BASE_OFFSET_mask = 0x3f << 0,
+ VGT_STRMOUT_BASE_OFFSET_HI_3__BASE_OFFSET_shift = 0,
+ PA_SC_LINE_CNTL = 0x00028c00,
+ BRES_CNTL_mask = 0xff << 0,
+ BRES_CNTL_shift = 0,
+ USE_BRES_CNTL_bit = 1 << 8,
+ EXPAND_LINE_WIDTH_bit = 1 << 9,
+ LAST_PIXEL_bit = 1 << 10,
+ PA_SC_AA_CONFIG = 0x00028c04,
+ MSAA_NUM_SAMPLES_mask = 0x03 << 0,
+ MSAA_NUM_SAMPLES_shift = 0,
+ AA_MASK_CENTROID_DTMN_bit = 1 << 4,
+ MAX_SAMPLE_DIST_mask = 0x0f << 13,
+ MAX_SAMPLE_DIST_shift = 13,
+ PA_SU_VTX_CNTL = 0x00028c08,
+ PIX_CENTER_bit = 1 << 0,
+ PA_SU_VTX_CNTL__ROUND_MODE_mask = 0x03 << 1,
+ PA_SU_VTX_CNTL__ROUND_MODE_shift = 1,
+ X_TRUNCATE = 0x00,
+ X_ROUND = 0x01,
+ X_ROUND_TO_EVEN = 0x02,
+ X_ROUND_TO_ODD = 0x03,
+ QUANT_MODE_mask = 0x07 << 3,
+ QUANT_MODE_shift = 3,
+ X_1_16TH = 0x00,
+ X_1_8TH = 0x01,
+ X_1_4TH = 0x02,
+ X_1_2 = 0x03,
+ X_1 = 0x04,
+ X_1_256TH = 0x05,
+ PA_CL_GB_VERT_CLIP_ADJ = 0x00028c0c,
+ PA_CL_GB_VERT_DISC_ADJ = 0x00028c10,
+ PA_CL_GB_HORZ_CLIP_ADJ = 0x00028c14,
+ PA_CL_GB_HORZ_DISC_ADJ = 0x00028c18,
+ PA_SC_AA_SAMPLE_LOCS_MCTX = 0x00028c1c,
+/* S0_X_mask = 0x0f << 0, */
+/* S0_X_shift = 0, */
+/* S0_Y_mask = 0x0f << 4, */
+/* S0_Y_shift = 4, */
+/* S1_X_mask = 0x0f << 8, */
+/* S1_X_shift = 8, */
+/* S1_Y_mask = 0x0f << 12, */
+/* S1_Y_shift = 12, */
+/* S2_X_mask = 0x0f << 16, */
+/* S2_X_shift = 16, */
+/* S2_Y_mask = 0x0f << 20, */
+/* S2_Y_shift = 20, */
+/* S3_X_mask = 0x0f << 24, */
+/* S3_X_shift = 24, */
+/* S3_Y_mask = 0x0f << 28, */
+/* S3_Y_shift = 28, */
+ PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX = 0x00028c20,
+/* S4_X_mask = 0x0f << 0, */
+/* S4_X_shift = 0, */
+/* S4_Y_mask = 0x0f << 4, */
+/* S4_Y_shift = 4, */
+/* S5_X_mask = 0x0f << 8, */
+/* S5_X_shift = 8, */
+/* S5_Y_mask = 0x0f << 12, */
+/* S5_Y_shift = 12, */
+/* S6_X_mask = 0x0f << 16, */
+/* S6_X_shift = 16, */
+/* S6_Y_mask = 0x0f << 20, */
+/* S6_Y_shift = 20, */
+/* S7_X_mask = 0x0f << 24, */
+/* S7_X_shift = 24, */
+/* S7_Y_mask = 0x0f << 28, */
+/* S7_Y_shift = 28, */
+ CB_CLRCMP_CONTROL = 0x00028c30,
+ CLRCMP_FCN_SRC_mask = 0x07 << 0,
+ CLRCMP_FCN_SRC_shift = 0,
+ CLRCMP_DRAW_ALWAYS = 0x00,
+ CLRCMP_DRAW_NEVER = 0x01,
+ CLRCMP_DRAW_ON_NEQ = 0x04,
+ CLRCMP_DRAW_ON_EQ = 0x05,
+ CLRCMP_FCN_DST_mask = 0x07 << 8,
+ CLRCMP_FCN_DST_shift = 8,
+/* CLRCMP_DRAW_ALWAYS = 0x00, */
+/* CLRCMP_DRAW_NEVER = 0x01, */
+/* CLRCMP_DRAW_ON_NEQ = 0x04, */
+/* CLRCMP_DRAW_ON_EQ = 0x05, */
+ CLRCMP_FCN_SEL_mask = 0x03 << 24,
+ CLRCMP_FCN_SEL_shift = 24,
+ CLRCMP_SEL_DST = 0x00,
+ CLRCMP_SEL_SRC = 0x01,
+ CLRCMP_SEL_AND = 0x02,
+ CB_CLRCMP_SRC = 0x00028c34,
+ CB_CLRCMP_DST = 0x00028c38,
+ CB_CLRCMP_MSK = 0x00028c3c,
+ PA_SC_AA_MASK = 0x00028c48,
+ VGT_VERTEX_REUSE_BLOCK_CNTL = 0x00028c58,
+ VTX_REUSE_DEPTH_mask = 0xff << 0,
+ VTX_REUSE_DEPTH_shift = 0,
+ VGT_OUT_DEALLOC_CNTL = 0x00028c5c,
+ DEALLOC_DIST_mask = 0x7f << 0,
+ DEALLOC_DIST_shift = 0,
+ DB_RENDER_CONTROL = 0x00028d0c,
+ DEPTH_CLEAR_ENABLE_bit = 1 << 0,
+ STENCIL_CLEAR_ENABLE_bit = 1 << 1,
+ DEPTH_COPY_bit = 1 << 2,
+ STENCIL_COPY_bit = 1 << 3,
+ RESUMMARIZE_ENABLE_bit = 1 << 4,
+ STENCIL_COMPRESS_DISABLE_bit = 1 << 5,
+ DEPTH_COMPRESS_DISABLE_bit = 1 << 6,
+ COPY_CENTROID_bit = 1 << 7,
+ COPY_SAMPLE_mask = 0x07 << 8,
+ COPY_SAMPLE_shift = 8,
+ ZPASS_INCREMENT_DISABLE_bit = 1 << 11,
+ DB_RENDER_OVERRIDE = 0x00028d10,
+ FORCE_HIZ_ENABLE_mask = 0x03 << 0,
+ FORCE_HIZ_ENABLE_shift = 0,
+ FORCE_OFF = 0x00,
+ FORCE_ENABLE = 0x01,
+ FORCE_DISABLE = 0x02,
+ FORCE_RESERVED = 0x03,
+ FORCE_HIS_ENABLE0_mask = 0x03 << 2,
+ FORCE_HIS_ENABLE0_shift = 2,
+/* FORCE_OFF = 0x00, */
+/* FORCE_ENABLE = 0x01, */
+/* FORCE_DISABLE = 0x02, */
+/* FORCE_RESERVED = 0x03, */
+ FORCE_HIS_ENABLE1_mask = 0x03 << 4,
+ FORCE_HIS_ENABLE1_shift = 4,
+/* FORCE_OFF = 0x00, */
+/* FORCE_ENABLE = 0x01, */
+/* FORCE_DISABLE = 0x02, */
+/* FORCE_RESERVED = 0x03, */
+ FORCE_SHADER_Z_ORDER_bit = 1 << 6,
+ FAST_Z_DISABLE_bit = 1 << 7,
+ FAST_STENCIL_DISABLE_bit = 1 << 8,
+ NOOP_CULL_DISABLE_bit = 1 << 9,
+ FORCE_COLOR_KILL_bit = 1 << 10,
+ FORCE_Z_READ_bit = 1 << 11,
+ FORCE_STENCIL_READ_bit = 1 << 12,
+ FORCE_FULL_Z_RANGE_mask = 0x03 << 13,
+ FORCE_FULL_Z_RANGE_shift = 13,
+/* FORCE_OFF = 0x00, */
+/* FORCE_ENABLE = 0x01, */
+/* FORCE_DISABLE = 0x02, */
+/* FORCE_RESERVED = 0x03, */
+ FORCE_QC_SMASK_CONFLICT_bit = 1 << 15,
+ DISABLE_VIEWPORT_CLAMP_bit = 1 << 16,
+ IGNORE_SC_ZRANGE_bit = 1 << 17,
+ DB_HTILE_SURFACE = 0x00028d24,
+ HTILE_WIDTH_bit = 1 << 0,
+ HTILE_HEIGHT_bit = 1 << 1,
+ LINEAR_bit = 1 << 2,
+ FULL_CACHE_bit = 1 << 3,
+ HTILE_USES_PRELOAD_WIN_bit = 1 << 4,
+ PRELOAD_bit = 1 << 5,
+ PREFETCH_WIDTH_mask = 0x3f << 6,
+ PREFETCH_WIDTH_shift = 6,
+ PREFETCH_HEIGHT_mask = 0x3f << 12,
+ PREFETCH_HEIGHT_shift = 12,
+ DB_SRESULTS_COMPARE_STATE1 = 0x00028d2c,
+ COMPAREFUNC1_mask = 0x07 << 0,
+ COMPAREFUNC1_shift = 0,
+/* REF_NEVER = 0x00, */
+/* REF_LESS = 0x01, */
+/* REF_EQUAL = 0x02, */
+/* REF_LEQUAL = 0x03, */
+/* REF_GREATER = 0x04, */
+/* REF_NOTEQUAL = 0x05, */
+/* REF_GEQUAL = 0x06, */
+/* REF_ALWAYS = 0x07, */
+ COMPAREVALUE1_mask = 0xff << 4,
+ COMPAREVALUE1_shift = 4,
+ COMPAREMASK1_mask = 0xff << 12,
+ COMPAREMASK1_shift = 12,
+ ENABLE1_bit = 1 << 24,
+ DB_PRELOAD_CONTROL = 0x00028d30,
+ START_X_mask = 0xff << 0,
+ START_X_shift = 0,
+ START_Y_mask = 0xff << 8,
+ START_Y_shift = 8,
+ MAX_X_mask = 0xff << 16,
+ MAX_X_shift = 16,
+ MAX_Y_mask = 0xff << 24,
+ MAX_Y_shift = 24,
+ DB_PREFETCH_LIMIT = 0x00028d34,
+ DEPTH_HEIGHT_TILE_MAX_mask = 0x3ff << 0,
+ DEPTH_HEIGHT_TILE_MAX_shift = 0,
+ PA_SU_POLY_OFFSET_DB_FMT_CNTL = 0x00028df8,
+ POLY_OFFSET_NEG_NUM_DB_BITS_mask = 0xff << 0,
+ POLY_OFFSET_NEG_NUM_DB_BITS_shift = 0,
+ POLY_OFFSET_DB_IS_FLOAT_FMT_bit = 1 << 8,
+ PA_SU_POLY_OFFSET_CLAMP = 0x00028dfc,
+ PA_SU_POLY_OFFSET_FRONT_SCALE = 0x00028e00,
+ PA_SU_POLY_OFFSET_FRONT_OFFSET = 0x00028e04,
+ PA_SU_POLY_OFFSET_BACK_SCALE = 0x00028e08,
+ PA_SU_POLY_OFFSET_BACK_OFFSET = 0x00028e0c,
+ PA_CL_POINT_X_RAD = 0x00028e10,
+ PA_CL_POINT_Y_RAD = 0x00028e14,
+ PA_CL_POINT_SIZE = 0x00028e18,
+ PA_CL_POINT_CULL_RAD = 0x00028e1c,
+ PA_CL_UCP_0_X = 0x00028e20,
+ PA_CL_UCP_0_X_num = 6,
+ PA_CL_UCP_0_X_offset = 16,
+ PA_CL_UCP_0_Y = 0x00028e24,
+ PA_CL_UCP_0_Y_num = 6,
+ PA_CL_UCP_0_Y_offset = 16,
+ PA_CL_UCP_0_Z = 0x00028e28,
+ PA_CL_UCP_0_Z_num = 6,
+ PA_CL_UCP_0_Z_offset = 16,
+ SQ_ALU_CONSTANT0_0 = 0x00030000,
+ SQ_ALU_CONSTANT1_0 = 0x00030004,
+ SQ_ALU_CONSTANT2_0 = 0x00030008,
+ SQ_ALU_CONSTANT3_0 = 0x0003000c,
+ SQ_VTX_CONSTANT_WORD0_0 = 0x00038000,
+ SQ_TEX_RESOURCE_WORD0_0 = 0x00038000,
+ DIM_mask = 0x07 << 0,
+ DIM_shift = 0,
+ SQ_TEX_DIM_1D = 0x00,
+ SQ_TEX_DIM_2D = 0x01,
+ SQ_TEX_DIM_3D = 0x02,
+ SQ_TEX_DIM_CUBEMAP = 0x03,
+ SQ_TEX_DIM_1D_ARRAY = 0x04,
+ SQ_TEX_DIM_2D_ARRAY = 0x05,
+ SQ_TEX_DIM_2D_MSAA = 0x06,
+ SQ_TEX_DIM_2D_ARRAY_MSAA = 0x07,
+ SQ_TEX_RESOURCE_WORD0_0__TILE_MODE_mask = 0x0f << 3,
+ SQ_TEX_RESOURCE_WORD0_0__TILE_MODE_shift = 3,
+ TILE_TYPE_bit = 1 << 7,
+ PITCH_mask = 0x7ff << 8,
+ PITCH_shift = 8,
+ TEX_WIDTH_mask = 0x1fff << 19,
+ TEX_WIDTH_shift = 19,
+ SQ_VTX_CONSTANT_WORD1_0 = 0x00038004,
+ SQ_TEX_RESOURCE_WORD1_0 = 0x00038004,
+ TEX_HEIGHT_mask = 0x1fff << 0,
+ TEX_HEIGHT_shift = 0,
+ TEX_DEPTH_mask = 0x1fff << 13,
+ TEX_DEPTH_shift = 13,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask = 0x3f << 26,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift = 26,
+ SQ_VTX_CONSTANT_WORD2_0 = 0x00038008,
+ BASE_ADDRESS_HI_mask = 0xff << 0,
+ BASE_ADDRESS_HI_shift = 0,
+ SQ_VTX_CONSTANT_WORD2_0__STRIDE_mask = 0x7ff << 8,
+ SQ_VTX_CONSTANT_WORD2_0__STRIDE_shift = 8,
+ SQ_VTX_CONSTANT_WORD2_0__CLAMP_X_bit = 1 << 19,
+ SQ_VTX_CONSTANT_WORD2_0__DATA_FORMAT_mask = 0x3f << 20,
+ SQ_VTX_CONSTANT_WORD2_0__DATA_FORMAT_shift = 20,
+ SQ_VTX_CONSTANT_WORD2_0__NUM_FORMAT_ALL_mask = 0x03 << 26,
+ SQ_VTX_CONSTANT_WORD2_0__NUM_FORMAT_ALL_shift = 26,
+/* SQ_NUM_FORMAT_NORM = 0x00, */
+/* SQ_NUM_FORMAT_INT = 0x01, */
+/* SQ_NUM_FORMAT_SCALED = 0x02, */
+ SQ_VTX_CONSTANT_WORD2_0__FORMAT_COMP_ALL_bit = 1 << 28,
+ SQ_VTX_CONSTANT_WORD2_0__SRF_MODE_ALL_bit = 1 << 29,
+ SQ_VTX_CONSTANT_WORD2_0__ENDIAN_SWAP_mask = 0x03 << 30,
+ SQ_VTX_CONSTANT_WORD2_0__ENDIAN_SWAP_shift = 30,
+/* SQ_ENDIAN_NONE = 0x00, */
+/* SQ_ENDIAN_8IN16 = 0x01, */
+/* SQ_ENDIAN_8IN32 = 0x02, */
+ SQ_TEX_RESOURCE_WORD2_0 = 0x00038008,
+ SQ_VTX_CONSTANT_WORD3_0 = 0x0003800c,
+ MEM_REQUEST_SIZE_mask = 0x03 << 0,
+ MEM_REQUEST_SIZE_shift = 0,
+ SQ_TEX_RESOURCE_WORD3_0 = 0x0003800c,
+ SQ_TEX_RESOURCE_WORD4_0 = 0x00038010,
+ FORMAT_COMP_X_mask = 0x03 << 0,
+ FORMAT_COMP_X_shift = 0,
+ SQ_FORMAT_COMP_UNSIGNED = 0x00,
+ SQ_FORMAT_COMP_SIGNED = 0x01,
+ SQ_FORMAT_COMP_UNSIGNED_BIASED = 0x02,
+ FORMAT_COMP_Y_mask = 0x03 << 2,
+ FORMAT_COMP_Y_shift = 2,
+/* SQ_FORMAT_COMP_UNSIGNED = 0x00, */
+/* SQ_FORMAT_COMP_SIGNED = 0x01, */
+/* SQ_FORMAT_COMP_UNSIGNED_BIASED = 0x02, */
+ FORMAT_COMP_Z_mask = 0x03 << 4,
+ FORMAT_COMP_Z_shift = 4,
+/* SQ_FORMAT_COMP_UNSIGNED = 0x00, */
+/* SQ_FORMAT_COMP_SIGNED = 0x01, */
+/* SQ_FORMAT_COMP_UNSIGNED_BIASED = 0x02, */
+ FORMAT_COMP_W_mask = 0x03 << 6,
+ FORMAT_COMP_W_shift = 6,
+/* SQ_FORMAT_COMP_UNSIGNED = 0x00, */
+/* SQ_FORMAT_COMP_SIGNED = 0x01, */
+/* SQ_FORMAT_COMP_UNSIGNED_BIASED = 0x02, */
+ SQ_TEX_RESOURCE_WORD4_0__NUM_FORMAT_ALL_mask = 0x03 << 8,
+ SQ_TEX_RESOURCE_WORD4_0__NUM_FORMAT_ALL_shift = 8,
+/* SQ_NUM_FORMAT_NORM = 0x00, */
+/* SQ_NUM_FORMAT_INT = 0x01, */
+/* SQ_NUM_FORMAT_SCALED = 0x02, */
+ SQ_TEX_RESOURCE_WORD4_0__SRF_MODE_ALL_bit = 1 << 10,
+ SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit = 1 << 11,
+ SQ_TEX_RESOURCE_WORD4_0__ENDIAN_SWAP_mask = 0x03 << 12,
+ SQ_TEX_RESOURCE_WORD4_0__ENDIAN_SWAP_shift = 12,
+/* SQ_ENDIAN_NONE = 0x00, */
+/* SQ_ENDIAN_8IN16 = 0x01, */
+/* SQ_ENDIAN_8IN32 = 0x02, */
+ REQUEST_SIZE_mask = 0x03 << 14,
+ REQUEST_SIZE_shift = 14,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask = 0x07 << 16,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift = 16,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask = 0x07 << 19,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift = 19,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask = 0x07 << 22,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift = 22,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask = 0x07 << 25,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift = 25,
+/* SQ_SEL_X = 0x00, */
+/* SQ_SEL_Y = 0x01, */
+/* SQ_SEL_Z = 0x02, */
+/* SQ_SEL_W = 0x03, */
+/* SQ_SEL_0 = 0x04, */
+/* SQ_SEL_1 = 0x05, */
+ BASE_LEVEL_mask = 0x0f << 28,
+ BASE_LEVEL_shift = 28,
+ SQ_TEX_RESOURCE_WORD5_0 = 0x00038014,
+ LAST_LEVEL_mask = 0x0f << 0,
+ LAST_LEVEL_shift = 0,
+ BASE_ARRAY_mask = 0x1fff << 4,
+ BASE_ARRAY_shift = 4,
+ LAST_ARRAY_mask = 0x1fff << 17,
+ LAST_ARRAY_shift = 17,
+ SQ_TEX_RESOURCE_WORD6_0 = 0x00038018,
+ MPEG_CLAMP_mask = 0x03 << 0,
+ MPEG_CLAMP_shift = 0,
+ SQ_TEX_MPEG_CLAMP_OFF = 0x00,
+ SQ_TEX_MPEG_9 = 0x01,
+ SQ_TEX_MPEG_10 = 0x02,
+ PERF_MODULATION_mask = 0x07 << 5,
+ PERF_MODULATION_shift = 5,
+ INTERLACED_bit = 1 << 8,
+ SQ_TEX_RESOURCE_WORD6_0__TYPE_mask = 0x03 << 30,
+ SQ_TEX_RESOURCE_WORD6_0__TYPE_shift = 30,
+ SQ_TEX_VTX_INVALID_TEXTURE = 0x00,
+ SQ_TEX_VTX_INVALID_BUFFER = 0x01,
+ SQ_TEX_VTX_VALID_TEXTURE = 0x02,
+ SQ_TEX_VTX_VALID_BUFFER = 0x03,
+ SQ_VTX_CONSTANT_WORD6_0 = 0x00038018,
+ SQ_VTX_CONSTANT_WORD6_0__TYPE_mask = 0x03 << 30,
+ SQ_VTX_CONSTANT_WORD6_0__TYPE_shift = 30,
+/* SQ_TEX_VTX_INVALID_TEXTURE = 0x00, */
+/* SQ_TEX_VTX_INVALID_BUFFER = 0x01, */
+/* SQ_TEX_VTX_VALID_TEXTURE = 0x02, */
+/* SQ_TEX_VTX_VALID_BUFFER = 0x03, */
+ SQ_TEX_SAMPLER_WORD0_0 = 0x0003c000,
+ SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask = 0x07 << 0,
+ SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift = 0,
+ SQ_TEX_WRAP = 0x00,
+ SQ_TEX_MIRROR = 0x01,
+ SQ_TEX_CLAMP_LAST_TEXEL = 0x02,
+ SQ_TEX_MIRROR_ONCE_LAST_TEXEL = 0x03,
+ SQ_TEX_CLAMP_HALF_BORDER = 0x04,
+ SQ_TEX_MIRROR_ONCE_HALF_BORDER = 0x05,
+ SQ_TEX_CLAMP_BORDER = 0x06,
+ SQ_TEX_MIRROR_ONCE_BORDER = 0x07,
+ CLAMP_Y_mask = 0x07 << 3,
+ CLAMP_Y_shift = 3,
+/* SQ_TEX_WRAP = 0x00, */
+/* SQ_TEX_MIRROR = 0x01, */
+/* SQ_TEX_CLAMP_LAST_TEXEL = 0x02, */
+/* SQ_TEX_MIRROR_ONCE_LAST_TEXEL = 0x03, */
+/* SQ_TEX_CLAMP_HALF_BORDER = 0x04, */
+/* SQ_TEX_MIRROR_ONCE_HALF_BORDER = 0x05, */
+/* SQ_TEX_CLAMP_BORDER = 0x06, */
+/* SQ_TEX_MIRROR_ONCE_BORDER = 0x07, */
+ CLAMP_Z_mask = 0x07 << 6,
+ CLAMP_Z_shift = 6,
+/* SQ_TEX_WRAP = 0x00, */
+/* SQ_TEX_MIRROR = 0x01, */
+/* SQ_TEX_CLAMP_LAST_TEXEL = 0x02, */
+/* SQ_TEX_MIRROR_ONCE_LAST_TEXEL = 0x03, */
+/* SQ_TEX_CLAMP_HALF_BORDER = 0x04, */
+/* SQ_TEX_MIRROR_ONCE_HALF_BORDER = 0x05, */
+/* SQ_TEX_CLAMP_BORDER = 0x06, */
+/* SQ_TEX_MIRROR_ONCE_BORDER = 0x07, */
+ XY_MAG_FILTER_mask = 0x07 << 9,
+ XY_MAG_FILTER_shift = 9,
+ SQ_TEX_XY_FILTER_POINT = 0x00,
+ SQ_TEX_XY_FILTER_BILINEAR = 0x01,
+ SQ_TEX_XY_FILTER_BICUBIC = 0x02,
+ XY_MIN_FILTER_mask = 0x07 << 12,
+ XY_MIN_FILTER_shift = 12,
+/* SQ_TEX_XY_FILTER_POINT = 0x00, */
+/* SQ_TEX_XY_FILTER_BILINEAR = 0x01, */
+/* SQ_TEX_XY_FILTER_BICUBIC = 0x02, */
+ Z_FILTER_mask = 0x03 << 15,
+ Z_FILTER_shift = 15,
+ SQ_TEX_Z_FILTER_NONE = 0x00,
+ SQ_TEX_Z_FILTER_POINT = 0x01,
+ SQ_TEX_Z_FILTER_LINEAR = 0x02,
+ MIP_FILTER_mask = 0x03 << 17,
+ MIP_FILTER_shift = 17,
+/* SQ_TEX_Z_FILTER_NONE = 0x00, */
+/* SQ_TEX_Z_FILTER_POINT = 0x01, */
+/* SQ_TEX_Z_FILTER_LINEAR = 0x02, */
+ BORDER_COLOR_TYPE_mask = 0x03 << 22,
+ BORDER_COLOR_TYPE_shift = 22,
+ SQ_TEX_BORDER_COLOR_TRANS_BLACK = 0x00,
+ SQ_TEX_BORDER_COLOR_OPAQUE_BLACK = 0x01,
+ SQ_TEX_BORDER_COLOR_OPAQUE_WHITE = 0x02,
+ SQ_TEX_BORDER_COLOR_REGISTER = 0x03,
+ POINT_SAMPLING_CLAMP_bit = 1 << 24,
+ TEX_ARRAY_OVERRIDE_bit = 1 << 25,
+ DEPTH_COMPARE_FUNCTION_mask = 0x07 << 26,
+ DEPTH_COMPARE_FUNCTION_shift = 26,
+ SQ_TEX_DEPTH_COMPARE_NEVER = 0x00,
+ SQ_TEX_DEPTH_COMPARE_LESS = 0x01,
+ SQ_TEX_DEPTH_COMPARE_EQUAL = 0x02,
+ SQ_TEX_DEPTH_COMPARE_LESSEQUAL = 0x03,
+ SQ_TEX_DEPTH_COMPARE_GREATER = 0x04,
+ SQ_TEX_DEPTH_COMPARE_NOTEQUAL = 0x05,
+ SQ_TEX_DEPTH_COMPARE_GREATEREQUAL = 0x06,
+ SQ_TEX_DEPTH_COMPARE_ALWAYS = 0x07,
+ CHROMA_KEY_mask = 0x03 << 29,
+ CHROMA_KEY_shift = 29,
+ SQ_TEX_CHROMA_KEY_DISABLED = 0x00,
+ SQ_TEX_CHROMA_KEY_KILL = 0x01,
+ SQ_TEX_CHROMA_KEY_BLEND = 0x02,
+ LOD_USES_MINOR_AXIS_bit = 1 << 31,
+ SQ_TEX_SAMPLER_WORD1_0 = 0x0003c004,
+ MIN_LOD_mask = 0x3ff << 0,
+ MIN_LOD_shift = 0,
+ MAX_LOD_mask = 0x3ff << 10,
+ MAX_LOD_shift = 10,
+ SQ_TEX_SAMPLER_WORD1_0__LOD_BIAS_mask = 0xfff << 20,
+ SQ_TEX_SAMPLER_WORD1_0__LOD_BIAS_shift = 20,
+ SQ_TEX_SAMPLER_WORD2_0 = 0x0003c008,
+ LOD_BIAS_SEC_mask = 0xfff << 0,
+ LOD_BIAS_SEC_shift = 0,
+ MC_COORD_TRUNCATE_bit = 1 << 12,
+ SQ_TEX_SAMPLER_WORD2_0__FORCE_DEGAMMA_bit = 1 << 13,
+ HIGH_PRECISION_FILTER_bit = 1 << 14,
+ PERF_MIP_mask = 0x07 << 15,
+ PERF_MIP_shift = 15,
+ PERF_Z_mask = 0x03 << 18,
+ PERF_Z_shift = 18,
+ FETCH_4_bit = 1 << 26,
+ SAMPLE_IS_PCF_bit = 1 << 27,
+ SQ_TEX_SAMPLER_WORD2_0__TYPE_bit = 1 << 31,
+ SQ_VTX_BASE_VTX_LOC = 0x0003cff0,
+ SQ_VTX_START_INST_LOC = 0x0003cff4,
+ SQ_LOOP_CONST_DX10_0 = 0x0003e200,
+ SQ_LOOP_CONST_0 = 0x0003e200,
+ SQ_LOOP_CONST_0__COUNT_mask = 0xfff << 0,
+ SQ_LOOP_CONST_0__COUNT_shift = 0,
+ INIT_mask = 0xfff << 12,
+ INIT_shift = 12,
+ INC_mask = 0xff << 24,
+ INC_shift = 24,
+ SQ_BOOL_CONST_0 = 0x0003e380,
+ SQ_BOOL_CONST_0_num = 3,
+
+} ;
+
+#endif /* _AUTOREGS */
+
diff --git a/src/mesa/drivers/dri/r600/r600_reg_r6xx.h b/src/mesa/drivers/dri/r600/r600_reg_r6xx.h
new file mode 100644
index 0000000000..f7702c46de
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_reg_r6xx.h
@@ -0,0 +1,492 @@
+/*
+ * RadeonHD R6xx, R7xx Register documentation
+ *
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2008-2009 Matthias Hopf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _R600_REG_R6xx_H_
+#define _R600_REG_R6xx_H_
+
+/*
+ * Registers for R6xx chips that are not documented yet
+ */
+
+enum {
+
+ MM_INDEX = 0x0000,
+ MM_DATA = 0x0004,
+
+ SRBM_STATUS = 0x0e50,
+ RLC_RQ_PENDING_bit = 1 << 3,
+ RCU_RQ_PENDING_bit = 1 << 4,
+ GRBM_RQ_PENDING_bit = 1 << 5,
+ HI_RQ_PENDING_bit = 1 << 6,
+ IO_EXTERN_SIGNAL_bit = 1 << 7,
+ VMC_BUSY_bit = 1 << 8,
+ MCB_BUSY_bit = 1 << 9,
+ MCDZ_BUSY_bit = 1 << 10,
+ MCDY_BUSY_bit = 1 << 11,
+ MCDX_BUSY_bit = 1 << 12,
+ MCDW_BUSY_bit = 1 << 13,
+ SEM_BUSY_bit = 1 << 14,
+ SRBM_STATUS__RLC_BUSY_bit = 1 << 15,
+ PDMA_BUSY_bit = 1 << 16,
+ IH_BUSY_bit = 1 << 17,
+ CSC_BUSY_bit = 1 << 20,
+ CMC7_BUSY_bit = 1 << 21,
+ CMC6_BUSY_bit = 1 << 22,
+ CMC5_BUSY_bit = 1 << 23,
+ CMC4_BUSY_bit = 1 << 24,
+ CMC3_BUSY_bit = 1 << 25,
+ CMC2_BUSY_bit = 1 << 26,
+ CMC1_BUSY_bit = 1 << 27,
+ CMC0_BUSY_bit = 1 << 28,
+ BIF_BUSY_bit = 1 << 29,
+ IDCT_BUSY_bit = 1 << 30,
+
+ SRBM_READ_ERROR = 0x0e98,
+ READ_ADDRESS_mask = 0xffff << 2,
+ READ_ADDRESS_shift = 2,
+ READ_REQUESTER_HI_bit = 1 << 24,
+ READ_REQUESTER_GRBM_bit = 1 << 25,
+ READ_REQUESTER_RCU_bit = 1 << 26,
+ READ_REQUESTER_RLC_bit = 1 << 27,
+ READ_ERROR_bit = 1 << 31,
+
+ SRBM_INT_STATUS = 0x0ea4,
+ RDERR_INT_STAT_bit = 1 << 0,
+ GFX_CNTX_SWITCH_INT_STAT_bit = 1 << 1,
+ SRBM_INT_ACK = 0x0ea8,
+ RDERR_INT_ACK_bit = 1 << 0,
+ GFX_CNTX_SWITCH_INT_ACK_bit = 1 << 1,
+
+ R6XX_MC_VM_FB_LOCATION = 0x2180,
+
+ VENDOR_DEVICE_ID = 0x4000,
+
+ D1GRPH_PRIMARY_SURFACE_ADDRESS = 0x6110,
+ D1GRPH_PITCH = 0x6120,
+ D1GRPH_Y_END = 0x6138,
+
+ GRBM_STATUS = 0x8010,
+ CMDFIFO_AVAIL_mask = 0x1f << 0,
+ CMDFIFO_AVAIL_shift = 0,
+ SRBM_RQ_PENDING_bit = 1 << 5,
+ CP_RQ_PENDING_bit = 1 << 6,
+ CF_RQ_PENDING_bit = 1 << 7,
+ PF_RQ_PENDING_bit = 1 << 8,
+ GRBM_EE_BUSY_bit = 1 << 10,
+ GRBM_STATUS__VC_BUSY_bit = 1 << 11,
+ DB03_CLEAN_bit = 1 << 12,
+ CB03_CLEAN_bit = 1 << 13,
+ VGT_BUSY_NO_DMA_bit = 1 << 16,
+ GRBM_STATUS__VGT_BUSY_bit = 1 << 17,
+ TA03_BUSY_bit = 1 << 18,
+ GRBM_STATUS__TC_BUSY_bit = 1 << 19,
+ SX_BUSY_bit = 1 << 20,
+ SH_BUSY_bit = 1 << 21,
+ SPI03_BUSY_bit = 1 << 22,
+ SMX_BUSY_bit = 1 << 23,
+ SC_BUSY_bit = 1 << 24,
+ PA_BUSY_bit = 1 << 25,
+ DB03_BUSY_bit = 1 << 26,
+ CR_BUSY_bit = 1 << 27,
+ CP_COHERENCY_BUSY_bit = 1 << 28,
+ GRBM_STATUS__CP_BUSY_bit = 1 << 29,
+ CB03_BUSY_bit = 1 << 30,
+ GUI_ACTIVE_bit = 1 << 31,
+ GRBM_STATUS2 = 0x8014,
+ CR_CLEAN_bit = 1 << 0,
+ SMX_CLEAN_bit = 1 << 1,
+ SPI0_BUSY_bit = 1 << 8,
+ SPI1_BUSY_bit = 1 << 9,
+ SPI2_BUSY_bit = 1 << 10,
+ SPI3_BUSY_bit = 1 << 11,
+ TA0_BUSY_bit = 1 << 12,
+ TA1_BUSY_bit = 1 << 13,
+ TA2_BUSY_bit = 1 << 14,
+ TA3_BUSY_bit = 1 << 15,
+ DB0_BUSY_bit = 1 << 16,
+ DB1_BUSY_bit = 1 << 17,
+ DB2_BUSY_bit = 1 << 18,
+ DB3_BUSY_bit = 1 << 19,
+ CB0_BUSY_bit = 1 << 20,
+ CB1_BUSY_bit = 1 << 21,
+ CB2_BUSY_bit = 1 << 22,
+ CB3_BUSY_bit = 1 << 23,
+ GRBM_SOFT_RESET = 0x8020,
+ SOFT_RESET_CP_bit = 1 << 0,
+ SOFT_RESET_CB_bit = 1 << 1,
+ SOFT_RESET_CR_bit = 1 << 2,
+ SOFT_RESET_DB_bit = 1 << 3,
+ SOFT_RESET_PA_bit = 1 << 5,
+ SOFT_RESET_SC_bit = 1 << 6,
+ SOFT_RESET_SMX_bit = 1 << 7,
+ SOFT_RESET_SPI_bit = 1 << 8,
+ SOFT_RESET_SH_bit = 1 << 9,
+ SOFT_RESET_SX_bit = 1 << 10,
+ SOFT_RESET_TC_bit = 1 << 11,
+ SOFT_RESET_TA_bit = 1 << 12,
+ SOFT_RESET_VC_bit = 1 << 13,
+ SOFT_RESET_VGT_bit = 1 << 14,
+ SOFT_RESET_GRBM_GCA_bit = 1 << 15,
+
+ WAIT_UNTIL = 0x8040,
+ WAIT_CP_DMA_IDLE_bit = 1 << 8,
+ WAIT_CMDFIFO_bit = 1 << 10,
+ WAIT_2D_IDLE_bit = 1 << 14,
+ WAIT_3D_IDLE_bit = 1 << 15,
+ WAIT_2D_IDLECLEAN_bit = 1 << 16,
+ WAIT_3D_IDLECLEAN_bit = 1 << 17,
+ WAIT_EXTERN_SIG_bit = 1 << 19,
+ CMDFIFO_ENTRIES_mask = 0x1f << 20,
+ CMDFIFO_ENTRIES_shift = 20,
+
+ GRBM_READ_ERROR = 0x8058,
+/* READ_ADDRESS_mask = 0xffff << 2, */
+/* READ_ADDRESS_shift = 2, */
+ READ_REQUESTER_SRBM_bit = 1 << 28,
+ READ_REQUESTER_CP_bit = 1 << 29,
+ READ_REQUESTER_WU_POLL_bit = 1 << 30,
+/* READ_ERROR_bit = 1 << 31, */
+
+ SCRATCH_REG0 = 0x8500,
+ SCRATCH_REG1 = 0x8504,
+ SCRATCH_REG2 = 0x8508,
+ SCRATCH_REG3 = 0x850c,
+ SCRATCH_REG4 = 0x8510,
+ SCRATCH_REG5 = 0x8514,
+ SCRATCH_REG6 = 0x8518,
+ SCRATCH_REG7 = 0x851c,
+ SCRATCH_UMSK = 0x8540,
+ SCRATCH_ADDR = 0x8544,
+
+ CP_COHER_CNTL = 0x85f0,
+ DEST_BASE_0_ENA_bit = 1 << 0,
+ DEST_BASE_1_ENA_bit = 1 << 1,
+ SO0_DEST_BASE_ENA_bit = 1 << 2,
+ SO1_DEST_BASE_ENA_bit = 1 << 3,
+ SO2_DEST_BASE_ENA_bit = 1 << 4,
+ SO3_DEST_BASE_ENA_bit = 1 << 5,
+ CB0_DEST_BASE_ENA_bit = 1 << 6,
+ CB1_DEST_BASE_ENA_bit = 1 << 7,
+ CB2_DEST_BASE_ENA_bit = 1 << 8,
+ CB3_DEST_BASE_ENA_bit = 1 << 9,
+ CB4_DEST_BASE_ENA_bit = 1 << 10,
+ CB5_DEST_BASE_ENA_bit = 1 << 11,
+ CB6_DEST_BASE_ENA_bit = 1 << 12,
+ CB7_DEST_BASE_ENA_bit = 1 << 13,
+ DB_DEST_BASE_ENA_bit = 1 << 14,
+ CR_DEST_BASE_ENA_bit = 1 << 15,
+ TC_ACTION_ENA_bit = 1 << 23,
+ VC_ACTION_ENA_bit = 1 << 24,
+ CB_ACTION_ENA_bit = 1 << 25,
+ DB_ACTION_ENA_bit = 1 << 26,
+ SH_ACTION_ENA_bit = 1 << 27,
+ SMX_ACTION_ENA_bit = 1 << 28,
+ CR0_ACTION_ENA_bit = 1 << 29,
+ CR1_ACTION_ENA_bit = 1 << 30,
+ CR2_ACTION_ENA_bit = 1 << 31,
+ CP_COHER_SIZE = 0x85f4,
+ CP_COHER_BASE = 0x85f8,
+ CP_COHER_STATUS = 0x85fc,
+ MATCHING_GFX_CNTX_mask = 0xff << 0,
+ MATCHING_GFX_CNTX_shift = 0,
+ MATCHING_CR_CNTX_mask = 0xffff << 8,
+ MATCHING_CR_CNTX_shift = 8,
+ STATUS_bit = 1 << 31,
+
+ CP_STALLED_STAT1 = 0x8674,
+ RBIU_TO_DMA_NOT_RDY_TO_RCV_bit = 1 << 0,
+ RBIU_TO_IBS_NOT_RDY_TO_RCV_bit = 1 << 1,
+ RBIU_TO_SEM_NOT_RDY_TO_RCV_bit = 1 << 2,
+ RBIU_TO_2DREGS_NOT_RDY_TO_RCV_bit = 1 << 3,
+ RBIU_TO_MEMWR_NOT_RDY_TO_RCV_bit = 1 << 4,
+ RBIU_TO_MEMRD_NOT_RDY_TO_RCV_bit = 1 << 5,
+ RBIU_TO_EOPD_NOT_RDY_TO_RCV_bit = 1 << 6,
+ RBIU_TO_RECT_NOT_RDY_TO_RCV_bit = 1 << 7,
+ RBIU_TO_STRMO_NOT_RDY_TO_RCV_bit = 1 << 8,
+ RBIU_TO_PSTAT_NOT_RDY_TO_RCV_bit = 1 << 9,
+ MIU_WAITING_ON_RDREQ_FREE_bit = 1 << 16,
+ MIU_WAITING_ON_WRREQ_FREE_bit = 1 << 17,
+ MIU_NEEDS_AVAIL_WRREQ_PHASE_bit = 1 << 18,
+ RCIU_WAITING_ON_GRBM_FREE_bit = 1 << 24,
+ RCIU_WAITING_ON_VGT_FREE_bit = 1 << 25,
+ RCIU_STALLED_ON_ME_READ_bit = 1 << 26,
+ RCIU_STALLED_ON_DMA_READ_bit = 1 << 27,
+ RCIU_HALTED_BY_REG_VIOLATION_bit = 1 << 28,
+ CP_STALLED_STAT2 = 0x8678,
+ PFP_TO_CSF_NOT_RDY_TO_RCV_bit = 1 << 0,
+ PFP_TO_MEQ_NOT_RDY_TO_RCV_bit = 1 << 1,
+ PFP_TO_VGT_NOT_RDY_TO_RCV_bit = 1 << 2,
+ PFP_HALTED_BY_INSTR_VIOLATION_bit = 1 << 3,
+ MULTIPASS_IB_PENDING_IN_PFP_bit = 1 << 4,
+ ME_BRUSH_WC_NOT_RDY_TO_RCV_bit = 1 << 8,
+ ME_STALLED_ON_BRUSH_LOGIC_bit = 1 << 9,
+ CR_CNTX_NOT_AVAIL_TO_ME_bit = 1 << 10,
+ GFX_CNTX_NOT_AVAIL_TO_ME_bit = 1 << 11,
+ ME_RCIU_NOT_RDY_TO_RCV_bit = 1 << 12,
+ ME_TO_CONST_NOT_RDY_TO_RCV_bit = 1 << 13,
+ ME_WAITING_DATA_FROM_PFP_bit = 1 << 14,
+ ME_WAITING_ON_PARTIAL_FLUSH_bit = 1 << 15,
+ RECT_FIFO_NEEDS_CR_RECT_DONE_bit = 1 << 16,
+ RECT_FIFO_NEEDS_WR_CONFIRM_bit = 1 << 17,
+ EOPD_FIFO_NEEDS_SC_EOP_DONE_bit = 1 << 18,
+ EOPD_FIFO_NEEDS_SMX_EOP_DONE_bit = 1 << 19,
+ EOPD_FIFO_NEEDS_WR_CONFIRM_bit = 1 << 20,
+ EOPD_FIFO_NEEDS_SIGNAL_SEM_bit = 1 << 21,
+ SO_NUMPRIM_FIFO_NEEDS_SOADDR_bit = 1 << 22,
+ SO_NUMPRIM_FIFO_NEEDS_NUMPRIM_bit = 1 << 23,
+ PIPE_STATS_FIFO_NEEDS_SAMPLE_bit = 1 << 24,
+ SURF_SYNC_NEEDS_IDLE_CNTXS_bit = 1 << 30,
+ SURF_SYNC_NEEDS_ALL_CLEAN_bit = 1 << 31,
+ CP_BUSY_STAT = 0x867c,
+ REG_BUS_FIFO_BUSY_bit = 1 << 0,
+ RING_FETCHING_DATA_bit = 1 << 1,
+ INDR1_FETCHING_DATA_bit = 1 << 2,
+ INDR2_FETCHING_DATA_bit = 1 << 3,
+ STATE_FETCHING_DATA_bit = 1 << 4,
+ PRED_FETCHING_DATA_bit = 1 << 5,
+ COHER_CNTR_NEQ_ZERO_bit = 1 << 6,
+ PFP_PARSING_PACKETS_bit = 1 << 7,
+ ME_PARSING_PACKETS_bit = 1 << 8,
+ RCIU_PFP_BUSY_bit = 1 << 9,
+ RCIU_ME_BUSY_bit = 1 << 10,
+ OUTSTANDING_READ_TAGS_bit = 1 << 11,
+ SEM_CMDFIFO_NOT_EMPTY_bit = 1 << 12,
+ SEM_FAILED_AND_HOLDING_bit = 1 << 13,
+ SEM_POLLING_FOR_PASS_bit = 1 << 14,
+ _3D_BUSY_bit = 1 << 15,
+ _2D_BUSY_bit = 1 << 16,
+ CP_STAT = 0x8680,
+ CSF_RING_BUSY_bit = 1 << 0,
+ CSF_WPTR_POLL_BUSY_bit = 1 << 1,
+ CSF_INDIRECT1_BUSY_bit = 1 << 2,
+ CSF_INDIRECT2_BUSY_bit = 1 << 3,
+ CSF_STATE_BUSY_bit = 1 << 4,
+ CSF_PREDICATE_BUSY_bit = 1 << 5,
+ CSF_BUSY_bit = 1 << 6,
+ MIU_RDREQ_BUSY_bit = 1 << 7,
+ MIU_WRREQ_BUSY_bit = 1 << 8,
+ ROQ_RING_BUSY_bit = 1 << 9,
+ ROQ_INDIRECT1_BUSY_bit = 1 << 10,
+ ROQ_INDIRECT2_BUSY_bit = 1 << 11,
+ ROQ_STATE_BUSY_bit = 1 << 12,
+ ROQ_PREDICATE_BUSY_bit = 1 << 13,
+ ROQ_ALIGN_BUSY_bit = 1 << 14,
+ PFP_BUSY_bit = 1 << 15,
+ MEQ_BUSY_bit = 1 << 16,
+ ME_BUSY_bit = 1 << 17,
+ QUERY_BUSY_bit = 1 << 18,
+ SEMAPHORE_BUSY_bit = 1 << 19,
+ INTERRUPT_BUSY_bit = 1 << 20,
+ SURFACE_SYNC_BUSY_bit = 1 << 21,
+ DMA_BUSY_bit = 1 << 22,
+ RCIU_BUSY_bit = 1 << 23,
+ CP_STAT__CP_BUSY_bit = 1 << 31,
+
+ CP_ME_CNTL = 0x86d8,
+ ME_STATMUX_mask = 0xff << 0,
+ ME_STATMUX_shift = 0,
+ ME_HALT_bit = 1 << 28,
+ CP_ME_STATUS = 0x86dc,
+
+ CP_RB_RPTR = 0x8700,
+ RB_RPTR_mask = 0xfffff << 0,
+ RB_RPTR_shift = 0,
+ CP_RB_WPTR_DELAY = 0x8704,
+ PRE_WRITE_TIMER_mask = 0xfffffff << 0,
+ PRE_WRITE_TIMER_shift = 0,
+ PRE_WRITE_LIMIT_mask = 0x0f << 28,
+ PRE_WRITE_LIMIT_shift = 28,
+
+ CP_ROQ_RB_STAT = 0x8780,
+ ROQ_RPTR_PRIMARY_mask = 0x3ff << 0,
+ ROQ_RPTR_PRIMARY_shift = 0,
+ ROQ_WPTR_PRIMARY_mask = 0x3ff << 16,
+ ROQ_WPTR_PRIMARY_shift = 16,
+ CP_ROQ_IB1_STAT = 0x8784,
+ ROQ_RPTR_INDIRECT1_mask = 0x3ff << 0,
+ ROQ_RPTR_INDIRECT1_shift = 0,
+ ROQ_WPTR_INDIRECT1_mask = 0x3ff << 16,
+ ROQ_WPTR_INDIRECT1_shift = 16,
+ CP_ROQ_IB2_STAT = 0x8788,
+ ROQ_RPTR_INDIRECT2_mask = 0x3ff << 0,
+ ROQ_RPTR_INDIRECT2_shift = 0,
+ ROQ_WPTR_INDIRECT2_mask = 0x3ff << 16,
+ ROQ_WPTR_INDIRECT2_shift = 16,
+
+ CP_MEQ_STAT = 0x8794,
+ MEQ_RPTR_mask = 0x3ff << 0,
+ MEQ_RPTR_shift = 0,
+ MEQ_WPTR_mask = 0x3ff << 16,
+ MEQ_WPTR_shift = 16,
+
+ CC_GC_SHADER_PIPE_CONFIG = 0x8950,
+ INACTIVE_QD_PIPES_mask = 0xff << 8,
+ INACTIVE_QD_PIPES_shift = 8,
+ R6XX_MAX_QD_PIPES = 8,
+ INACTIVE_SIMDS_mask = 0xff << 16,
+ INACTIVE_SIMDS_shift = 16,
+ R6XX_MAX_SIMDS = 8,
+ GC_USER_SHADER_PIPE_CONFIG = 0x8954,
+
+ VC_ENHANCE = 0x9714,
+ DB_DEBUG = 0x9830,
+ PREZ_MUST_WAIT_FOR_POSTZ_DONE = 1 << 31,
+
+ DB_WATERMARKS = 0x00009838,
+ DEPTH_FREE_mask = 0x1f << 0,
+ DEPTH_FREE_shift = 0,
+ DEPTH_FLUSH_mask = 0x3f << 5,
+ DEPTH_FLUSH_shift = 5,
+ FORCE_SUMMARIZE_mask = 0x0f << 11,
+ FORCE_SUMMARIZE_shift = 11,
+ DEPTH_PENDING_FREE_mask = 0x1f << 15,
+ DEPTH_PENDING_FREE_shift = 15,
+ DEPTH_CACHELINE_FREE_mask = 0x1f << 20,
+ DEPTH_CACHELINE_FREE_shift = 20,
+ EARLY_Z_PANIC_DISABLE_bit = 1 << 25,
+ LATE_Z_PANIC_DISABLE_bit = 1 << 26,
+ RE_Z_PANIC_DISABLE_bit = 1 << 27,
+ DB_EXTRA_DEBUG_mask = 0x0f << 28,
+ DB_EXTRA_DEBUG_shift = 28,
+
+ CP_RB_BASE = 0xc100,
+ CP_RB_CNTL = 0xc104,
+ RB_BUFSZ_mask = 0x3f << 0,
+ CP_RB_WPTR = 0xc114,
+ RB_WPTR_mask = 0xfffff << 0,
+ RB_WPTR_shift = 0,
+ CP_RB_RPTR_WR = 0xc108,
+ RB_RPTR_WR_mask = 0xfffff << 0,
+ RB_RPTR_WR_shift = 0,
+
+ CP_INT_STATUS = 0xc128,
+ DISABLE_CNTX_SWITCH_INT_STAT_bit = 1 << 0,
+ ENABLE_CNTX_SWITCH_INT_STAT_bit = 1 << 1,
+ SEM_SIGNAL_INT_STAT_bit = 1 << 18,
+ CNTX_BUSY_INT_STAT_bit = 1 << 19,
+ CNTX_EMPTY_INT_STAT_bit = 1 << 20,
+ WAITMEM_SEM_INT_STAT_bit = 1 << 21,
+ PRIV_INSTR_INT_STAT_bit = 1 << 22,
+ PRIV_REG_INT_STAT_bit = 1 << 23,
+ OPCODE_ERROR_INT_STAT_bit = 1 << 24,
+ SCRATCH_INT_STAT_bit = 1 << 25,
+ TIME_STAMP_INT_STAT_bit = 1 << 26,
+ RESERVED_BIT_ERROR_INT_STAT_bit = 1 << 27,
+ DMA_INT_STAT_bit = 1 << 28,
+ IB2_INT_STAT_bit = 1 << 29,
+ IB1_INT_STAT_bit = 1 << 30,
+ RB_INT_STAT_bit = 1 << 31,
+
+// SX_ALPHA_TEST_CONTROL = 0x00028410,
+ ALPHA_FUNC__REF_NEVER = 0,
+ ALPHA_FUNC__REF_ALWAYS = 7,
+// DB_SHADER_CONTROL = 0x0002880c,
+ Z_ORDER__EARLY_Z_THEN_LATE_Z = 2,
+// PA_SU_SC_MODE_CNTL = 0x00028814,
+// POLY_MODE_mask = 0x03 << 3,
+ POLY_MODE__TRIANGLES = 0, POLY_MODE__DUAL_MODE,
+// POLYMODE_FRONT_PTYPE_mask = 0x07 << 5,
+ POLYMODE_PTYPE__POINTS = 0, POLYMODE_PTYPE__LINES, POLYMODE_PTYPE__TRIANGLES,
+ PA_SC_AA_SAMPLE_LOCS_8S_WD1_M = 0x00028c20,
+ DB_SRESULTS_COMPARE_STATE0 = 0x00028d28, /* See autoregs: DB_SRESULTS_COMPARE_STATE1 */
+// DB_SRESULTS_COMPARE_STATE1 = 0x00028d2c,
+ DB_ALPHA_TO_MASK = 0x00028d44,
+ ALPHA_TO_MASK_ENABLE = 1 << 0,
+ ALPHA_TO_MASK_OFFSET0_mask = 0x03 << 8,
+ ALPHA_TO_MASK_OFFSET0_shift = 8,
+ ALPHA_TO_MASK_OFFSET1_mask = 0x03 << 8,
+ ALPHA_TO_MASK_OFFSET1_shift = 10,
+ ALPHA_TO_MASK_OFFSET2_mask = 0x03 << 8,
+ ALPHA_TO_MASK_OFFSET2_shift = 12,
+ ALPHA_TO_MASK_OFFSET3_mask = 0x03 << 8,
+ ALPHA_TO_MASK_OFFSET3_shift = 14,
+
+// SQ_VTX_CONSTANT_WORD2_0 = 0x00038008,
+// SQ_VTX_CONSTANT_WORD2_0__DATA_FORMAT_mask = 0x3f << 20,
+ FMT_INVALID=0, FMT_8, FMT_4_4, FMT_3_3_2,
+ FMT_16=5, FMT_16_FLOAT, FMT_8_8,
+ FMT_5_6_5, FMT_6_5_5, FMT_1_5_5_5, FMT_4_4_4_4,
+ FMT_5_5_5_1, FMT_32, FMT_32_FLOAT, FMT_16_16,
+ FMT_16_16_FLOAT=16, FMT_8_24, FMT_8_24_FLOAT, FMT_24_8,
+ FMT_24_8_FLOAT, FMT_10_11_11, FMT_10_11_11_FLOAT, FMT_11_11_10,
+ FMT_11_11_10_FLOAT, FMT_2_10_10_10, FMT_8_8_8_8, FMT_10_10_10_2,
+ FMT_X24_8_32_FLOAT, FMT_32_32, FMT_32_32_FLOAT, FMT_16_16_16_16,
+ FMT_16_16_16_16_FLOAT=32, FMT_32_32_32_32=34, FMT_32_32_32_32_FLOAT,
+ FMT_1 = 37, FMT_GB_GR=39,
+ FMT_BG_RG, FMT_32_AS_8, FMT_32_AS_8_8, FMT_5_9_9_9_SHAREDEXP,
+ FMT_8_8_8, FMT_16_16_16, FMT_16_16_16_FLOAT, FMT_32_32_32,
+ FMT_32_32_32_FLOAT=48,
+
+// High level register file lengths
+ SQ_ALU_CONSTANT = SQ_ALU_CONSTANT0_0, /* 256 PS, 256 VS */
+ SQ_ALU_CONSTANT_ps_num = 256,
+ SQ_ALU_CONSTANT_vs_num = 256,
+ SQ_ALU_CONSTANT_all_num = 512,
+ SQ_ALU_CONSTANT_offset = 16,
+ SQ_ALU_CONSTANT_ps = 0,
+ SQ_ALU_CONSTANT_vs = SQ_ALU_CONSTANT_ps + SQ_ALU_CONSTANT_ps_num,
+ SQ_TEX_RESOURCE = SQ_TEX_RESOURCE_WORD0_0, /* 160 PS, 160 VS, 16 FS, 160 GS */
+ SQ_TEX_RESOURCE_ps_num = 160,
+ SQ_TEX_RESOURCE_vs_num = 160,
+ SQ_TEX_RESOURCE_fs_num = 16,
+ SQ_TEX_RESOURCE_gs_num = 160,
+ SQ_TEX_RESOURCE_all_num = 496,
+ SQ_TEX_RESOURCE_offset = 28,
+ SQ_TEX_RESOURCE_ps = 0,
+ SQ_TEX_RESOURCE_vs = SQ_TEX_RESOURCE_ps + SQ_TEX_RESOURCE_ps_num,
+ SQ_TEX_RESOURCE_fs = SQ_TEX_RESOURCE_vs + SQ_TEX_RESOURCE_vs_num,
+ SQ_TEX_RESOURCE_gs = SQ_TEX_RESOURCE_fs + SQ_TEX_RESOURCE_fs_num,
+ SQ_VTX_RESOURCE = SQ_VTX_CONSTANT_WORD0_0, /* 160 PS, 160 VS, 16 FS, 160 GS */
+ SQ_VTX_RESOURCE_ps_num = 160,
+ SQ_VTX_RESOURCE_vs_num = 160,
+ SQ_VTX_RESOURCE_fs_num = 16,
+ SQ_VTX_RESOURCE_gs_num = 160,
+ SQ_VTX_RESOURCE_all_num = 496,
+ SQ_VTX_RESOURCE_offset = 28,
+ SQ_VTX_RESOURCE_ps = 0,
+ SQ_VTX_RESOURCE_vs = SQ_VTX_RESOURCE_ps + SQ_VTX_RESOURCE_ps_num,
+ SQ_VTX_RESOURCE_fs = SQ_VTX_RESOURCE_vs + SQ_VTX_RESOURCE_vs_num,
+ SQ_VTX_RESOURCE_gs = SQ_VTX_RESOURCE_fs + SQ_VTX_RESOURCE_fs_num,
+ SQ_TEX_SAMPLER_WORD = SQ_TEX_SAMPLER_WORD0_0, /* 18 per PS, VS, GS */
+ SQ_TEX_SAMPLER_WORD_ps_num = 18,
+ SQ_TEX_SAMPLER_WORD_vs_num = 18,
+ SQ_TEX_SAMPLER_WORD_gs_num = 18,
+ SQ_TEX_SAMPLER_WORD_all_num = 54,
+ SQ_TEX_SAMPLER_WORD_offset = 12,
+ SQ_TEX_SAMPLER_WORD_ps = 0,
+ SQ_TEX_SAMPLER_WORD_vs = SQ_TEX_SAMPLER_WORD_ps + SQ_TEX_SAMPLER_WORD_ps_num,
+ SQ_TEX_SAMPLER_WORD_gs = SQ_TEX_SAMPLER_WORD_vs + SQ_TEX_SAMPLER_WORD_vs_num,
+ SQ_LOOP_CONST = SQ_LOOP_CONST_0, /* 32 per PS, VS, GS */
+ SQ_LOOP_CONST_ps_num = 32,
+ SQ_LOOP_CONST_vs_num = 32,
+ SQ_LOOP_CONST_gs_num = 32,
+ SQ_LOOP_CONST_all_num = 96,
+ SQ_LOOP_CONST_offset = 4,
+ SQ_LOOP_CONST_ps = 0,
+ SQ_LOOP_CONST_vs = SQ_LOOP_CONST_ps + SQ_LOOP_CONST_ps_num,
+ SQ_LOOP_CONST_gs = SQ_LOOP_CONST_vs + SQ_LOOP_CONST_vs_num,
+} ;
+
+
+#endif
diff --git a/src/mesa/drivers/dri/r600/r600_reg_r7xx.h b/src/mesa/drivers/dri/r600/r600_reg_r7xx.h
new file mode 100644
index 0000000000..e5c01c861a
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_reg_r7xx.h
@@ -0,0 +1,149 @@
+/*
+ * RadeonHD R6xx, R7xx Register documentation
+ *
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2008-2009 Matthias Hopf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _R600_REG_R7xx_H_
+#define _R600_REG_R7xx_H_
+
+/*
+ * Register update for R7xx chips
+ */
+
+enum {
+
+ R7XX_MC_VM_FB_LOCATION = 0x00002024,
+
+// GRBM_STATUS = 0x00008010,
+ R7XX_TA_BUSY_bit = 1 << 14,
+
+ R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ = 0x00008d8c,
+ RING0_OFFSET_mask = 0xff << 0,
+ RING0_OFFSET_shift = 0,
+ ISOLATE_ES_ENABLE_bit = 1 << 12,
+ ISOLATE_GS_ENABLE_bit = 1 << 13,
+ VS_PC_LIMIT_ENABLE_bit = 1 << 14,
+
+// SQ_ALU_WORD0 = 0x00008dfc,
+// SRC0_SEL_mask = 0x1ff << 0,
+// SRC1_SEL_mask = 0x1ff << 13,
+ R7xx_SQ_ALU_SRC_1_DBL_L = 0xf4,
+ R7xx_SQ_ALU_SRC_1_DBL_M = 0xf5,
+ R7xx_SQ_ALU_SRC_0_5_DBL_L = 0xf6,
+ R7xx_SQ_ALU_SRC_0_5_DBL_M = 0xf7,
+// INDEX_MODE_mask = 0x07 << 26,
+ R7xx_SQ_INDEX_GLOBAL = 0x05,
+ R7xx_SQ_INDEX_GLOBAL_AR_X = 0x06,
+ R6xx_SQ_ALU_WORD1_OP2 = 0x00008dfc,
+ R7xx_SQ_ALU_WORD1_OP2_V2 = 0x00008dfc,
+ R6xx_FOG_MERGE_bit = 1 << 5,
+ R6xx_OMOD_mask = 0x03 << 6,
+ R7xx_OMOD_mask = 0x03 << 5,
+ R6xx_OMOD_shift = 6,
+ R7xx_OMOD_shift = 5,
+ R6xx_SQ_ALU_WORD1_OP2__ALU_INST_mask = 0x3ff << 8,
+ R7xx_SQ_ALU_WORD1_OP2_V2__ALU_INST_mask = 0x7ff << 7,
+ R6xx_SQ_ALU_WORD1_OP2__ALU_INST_shift = 8,
+ R7xx_SQ_ALU_WORD1_OP2_V2__ALU_INST_shift = 7,
+ R7xx_SQ_OP2_INST_FREXP_64 = 0x07,
+ R7xx_SQ_OP2_INST_ADD_64 = 0x17,
+ R7xx_SQ_OP2_INST_MUL_64 = 0x1b,
+ R7xx_SQ_OP2_INST_FLT64_TO_FLT32 = 0x1c,
+ R7xx_SQ_OP2_INST_FLT32_TO_FLT64 = 0x1d,
+ R7xx_SQ_OP2_INST_LDEXP_64 = 0x7a,
+ R7xx_SQ_OP2_INST_FRACT_64 = 0x7b,
+ R7xx_SQ_OP2_INST_PRED_SETGT_64 = 0x7c,
+ R7xx_SQ_OP2_INST_PRED_SETE_64 = 0x7d,
+ R7xx_SQ_OP2_INST_PRED_SETGE_64 = 0x7e,
+// SQ_ALU_WORD1_OP3 = 0x00008dfc,
+// SRC2_SEL_mask = 0x1ff << 0,
+// R7xx_SQ_ALU_SRC_1_DBL_L = 0xf4,
+// R7xx_SQ_ALU_SRC_1_DBL_M = 0xf5,
+// R7xx_SQ_ALU_SRC_0_5_DBL_L = 0xf6,
+// R7xx_SQ_ALU_SRC_0_5_DBL_M = 0xf7,
+// SQ_ALU_WORD1_OP3__ALU_INST_mask = 0x1f << 13,
+ R7xx_SQ_OP3_INST_MULADD_64 = 0x08,
+ R7xx_SQ_OP3_INST_MULADD_64_M2 = 0x09,
+ R7xx_SQ_OP3_INST_MULADD_64_M4 = 0x0a,
+ R7xx_SQ_OP3_INST_MULADD_64_D2 = 0x0b,
+// SQ_CF_ALU_WORD1 = 0x00008dfc,
+ R6xx_USES_WATERFALL_bit = 1 << 25,
+ R7xx_SQ_CF_ALU_WORD1__ALT_CONST_bit = 1 << 25,
+// SQ_CF_ALLOC_EXPORT_WORD0 = 0x00008dfc,
+// ARRAY_BASE_mask = 0x1fff << 0,
+// TYPE_mask = 0x03 << 13,
+// SQ_EXPORT_PARAM = 0x02,
+// X_UNUSED_FOR_SX_EXPORTS = 0x03,
+// ELEM_SIZE_mask = 0x03 << 30,
+// SQ_CF_ALLOC_EXPORT_WORD1 = 0x00008dfc,
+// SQ_CF_ALLOC_EXPORT_WORD1__CF_INST_mask = 0x7f << 23,
+ R7xx_SQ_CF_INST_MEM_EXPORT = 0x3a,
+// SQ_CF_WORD1 = 0x00008dfc,
+// SQ_CF_WORD1__COUNT_mask = 0x07 << 10,
+ R7xx_COUNT_3_bit = 1 << 19,
+// SQ_CF_WORD1__CF_INST_mask = 0x7f << 23,
+ R7xx_SQ_CF_INST_END_PROGRAM = 0x19,
+ R7xx_SQ_CF_INST_WAIT_ACK = 0x1a,
+ R7xx_SQ_CF_INST_TEX_ACK = 0x1b,
+ R7xx_SQ_CF_INST_VTX_ACK = 0x1c,
+ R7xx_SQ_CF_INST_VTX_TC_ACK = 0x1d,
+// SQ_VTX_WORD0 = 0x00008dfc,
+// VTX_INST_mask = 0x1f << 0,
+ R7xx_SQ_VTX_INST_MEM = 0x02,
+// SQ_VTX_WORD2 = 0x00008dfc,
+ R7xx_SQ_VTX_WORD2__ALT_CONST_bit = 1 << 20,
+
+// SQ_TEX_WORD0 = 0x00008dfc,
+// TEX_INST_mask = 0x1f << 0,
+ R7xx_X_MEMORY_READ = 0x02,
+ R7xx_SQ_TEX_INST_KEEP_GRADIENTS = 0x0a,
+ R7xx_X_FETCH4_LOAD4_INSTRUCTION_FOR_DX10_1 = 0x0f,
+ R7xx_SQ_TEX_WORD0__ALT_CONST_bit = 1 << 24,
+
+ R7xx_PA_SC_EDGERULE = 0x00028230,
+ R7xx_SPI_THREAD_GROUPING = 0x000286c8,
+ PS_GROUPING_mask = 0x1f << 0,
+ PS_GROUPING_shift = 0,
+ VS_GROUPING_mask = 0x1f << 8,
+ VS_GROUPING_shift = 8,
+ GS_GROUPING_mask = 0x1f << 16,
+ GS_GROUPING_shift = 16,
+ ES_GROUPING_mask = 0x1f << 24,
+ ES_GROUPING_shift = 24,
+ R7xx_CB_SHADER_CONTROL = 0x000287a0,
+ RT0_ENABLE_bit = 1 << 0,
+ RT1_ENABLE_bit = 1 << 1,
+ RT2_ENABLE_bit = 1 << 2,
+ RT3_ENABLE_bit = 1 << 3,
+ RT4_ENABLE_bit = 1 << 4,
+ RT5_ENABLE_bit = 1 << 5,
+ RT6_ENABLE_bit = 1 << 6,
+ RT7_ENABLE_bit = 1 << 7,
+// DB_ALPHA_TO_MASK = 0x00028d44,
+ R7xx_OFFSET_ROUND_bit = 1 << 16,
+// SQ_TEX_SAMPLER_MISC_0 = 0x0003d03c,
+ R7xx_TRUNCATE_COORD_bit = 1 << 9,
+ R7xx_DISABLE_CUBE_WRAP_bit = 1 << 10,
+
+} ;
+
+#endif /* _R600_REG_R7xx_H_ */
diff --git a/src/mesa/drivers/dri/r600/r600_tex.c b/src/mesa/drivers/dri/r600/r600_tex.c
new file mode 100644
index 0000000000..d105b90cd1
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_tex.c
@@ -0,0 +1,440 @@
+/*
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/**
+ * \file
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/image.h"
+#include "main/mipmap.h"
+#include "main/simple_list.h"
+#include "main/texformat.h"
+#include "main/texstore.h"
+#include "main/teximage.h"
+#include "main/texobj.h"
+
+#include "texmem.h"
+
+#include "r600_context.h"
+#include "r700_state.h"
+#include "radeon_mipmap_tree.h"
+#include "r600_tex.h"
+
+#include "xmlpool.h"
+
+
+static unsigned int translate_wrap_mode(GLenum wrapmode)
+{
+ switch(wrapmode) {
+ case GL_REPEAT: return SQ_TEX_WRAP;
+ case GL_CLAMP: return SQ_TEX_CLAMP_HALF_BORDER;
+ case GL_CLAMP_TO_EDGE: return SQ_TEX_CLAMP_LAST_TEXEL;
+ case GL_CLAMP_TO_BORDER: return SQ_TEX_CLAMP_BORDER;
+ case GL_MIRRORED_REPEAT: return SQ_TEX_MIRROR;
+ case GL_MIRROR_CLAMP_EXT: return SQ_TEX_MIRROR_ONCE_HALF_BORDER;
+ case GL_MIRROR_CLAMP_TO_EDGE_EXT: return SQ_TEX_MIRROR_ONCE_LAST_TEXEL;
+ case GL_MIRROR_CLAMP_TO_BORDER_EXT: return SQ_TEX_MIRROR_ONCE_BORDER;
+ default:
+ radeon_error("bad wrap mode in %s", __FUNCTION__);
+ return 0;
+ }
+}
+
+
+/**
+ * Update the cached hardware registers based on the current texture wrap modes.
+ *
+ * \param t Texture object whose wrap modes are to be set
+ */
+static void r600UpdateTexWrap(radeonTexObjPtr t)
+{
+ struct gl_texture_object *tObj = &t->base;
+
+ SETfield(t->SQ_TEX_SAMPLER0, translate_wrap_mode(tObj->WrapS),
+ SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift, SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask);
+
+ if (tObj->Target != GL_TEXTURE_1D) {
+ SETfield(t->SQ_TEX_SAMPLER0, translate_wrap_mode(tObj->WrapT),
+ CLAMP_Y_shift, CLAMP_Y_mask);
+
+ if (tObj->Target == GL_TEXTURE_3D)
+ SETfield(t->SQ_TEX_SAMPLER0, translate_wrap_mode(tObj->WrapR),
+ CLAMP_Z_shift, CLAMP_Z_mask);
+ }
+}
+
+static void r600SetTexDefaultState(radeonTexObjPtr t)
+{
+ /* Init text object to default states. */
+ t->SQ_TEX_RESOURCE0 = 0;
+ SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_2D, DIM_shift, DIM_mask);
+ SETfield(t->SQ_TEX_RESOURCE0, ARRAY_LINEAR_GENERAL,
+ SQ_TEX_RESOURCE_WORD0_0__TILE_MODE_shift, SQ_TEX_RESOURCE_WORD0_0__TILE_MODE_mask);
+ CLEARbit(t->SQ_TEX_RESOURCE0, TILE_TYPE_bit);
+
+ t->SQ_TEX_RESOURCE1 = 0;
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ t->SQ_TEX_RESOURCE2 = 0;
+ t->SQ_TEX_RESOURCE3 = 0;
+
+ t->SQ_TEX_RESOURCE4 = 0;
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+ FORMAT_COMP_X_shift, FORMAT_COMP_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+ FORMAT_COMP_Y_shift, FORMAT_COMP_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+ FORMAT_COMP_Z_shift, FORMAT_COMP_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+ FORMAT_COMP_W_shift, FORMAT_COMP_W_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_NUM_FORMAT_NORM,
+ SQ_TEX_RESOURCE_WORD4_0__NUM_FORMAT_ALL_shift, SQ_TEX_RESOURCE_WORD4_0__NUM_FORMAT_ALL_mask);
+ CLEARbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__SRF_MODE_ALL_bit);
+ CLEARbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_ENDIAN_NONE,
+ SQ_TEX_RESOURCE_WORD4_0__ENDIAN_SWAP_shift, SQ_TEX_RESOURCE_WORD4_0__ENDIAN_SWAP_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, 1, REQUEST_SIZE_shift, REQUEST_SIZE_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, 0, BASE_LEVEL_shift, BASE_LEVEL_mask); /* mip-maps */
+
+ t->SQ_TEX_RESOURCE5 = 0;
+ t->SQ_TEX_RESOURCE6 = 0;
+
+ SETfield(t->SQ_TEX_RESOURCE6, SQ_TEX_VTX_VALID_TEXTURE,
+ SQ_TEX_RESOURCE_WORD6_0__TYPE_shift, SQ_TEX_RESOURCE_WORD6_0__TYPE_mask);
+
+ /* Initialize sampler registers */
+ t->SQ_TEX_SAMPLER0 = 0;
+ SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_WRAP, SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift,
+ SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_WRAP, CLAMP_Y_shift, CLAMP_Y_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_WRAP, CLAMP_Z_shift, CLAMP_Z_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_XY_FILTER_POINT, XY_MAG_FILTER_shift, XY_MAG_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_XY_FILTER_POINT, XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_Z_FILTER_NONE, Z_FILTER_shift, Z_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_Z_FILTER_NONE, MIP_FILTER_shift, MIP_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_BORDER_COLOR_TRANS_BLACK, BORDER_COLOR_TYPE_shift, BORDER_COLOR_TYPE_mask);
+
+ t->SQ_TEX_SAMPLER1 = 0;
+ SETfield(t->SQ_TEX_SAMPLER1, 0x3ff, MAX_LOD_shift, MAX_LOD_mask);
+
+ t->SQ_TEX_SAMPLER2 = 0;
+ SETbit(t->SQ_TEX_SAMPLER2, SQ_TEX_SAMPLER_WORD2_0__TYPE_bit);
+}
+
+
+#if 0
+static GLuint aniso_filter(GLfloat anisotropy)
+{
+ if (anisotropy >= 16.0) {
+ return R300_TX_MAX_ANISO_16_TO_1;
+ } else if (anisotropy >= 8.0) {
+ return R300_TX_MAX_ANISO_8_TO_1;
+ } else if (anisotropy >= 4.0) {
+ return R300_TX_MAX_ANISO_4_TO_1;
+ } else if (anisotropy >= 2.0) {
+ return R300_TX_MAX_ANISO_2_TO_1;
+ } else {
+ return R300_TX_MAX_ANISO_1_TO_1;
+ }
+ return 0;
+}
+#endif
+
+/**
+ * Set the texture magnification and minification modes.
+ *
+ * \param t Texture whose filter modes are to be set
+ * \param minf Texture minification mode
+ * \param magf Texture magnification mode
+ * \param anisotropy Maximum anisotropy level
+ */
+static void r600SetTexFilter(radeonTexObjPtr t, GLenum minf, GLenum magf, GLfloat anisotropy)
+{
+ /* Force revalidation to account for switches from/to mipmapping. */
+ t->validated = GL_FALSE;
+
+ /* Note that EXT_texture_filter_anisotropic is extremely vague about
+ * how anisotropic filtering interacts with the "normal" filter modes.
+ * When anisotropic filtering is enabled, we override min and mag
+ * filter settings completely. This includes driconf's settings.
+ */
+ if (anisotropy >= 2.0 && (minf != GL_NEAREST) && (magf != GL_NEAREST)) {
+ /*t->pp_txfilter |= R300_TX_MAG_FILTER_ANISO
+ | R300_TX_MIN_FILTER_ANISO
+ | R300_TX_MIN_FILTER_MIP_LINEAR
+ | aniso_filter(anisotropy);*/
+ radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "Using maximum anisotropy of %f\n", anisotropy);
+ return;
+ }
+
+ switch (minf) {
+ case GL_NEAREST:
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
+ XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_None,
+ MIP_FILTER_shift, MIP_FILTER_mask);
+ break;
+ case GL_LINEAR:
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
+ XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_None,
+ MIP_FILTER_shift, MIP_FILTER_mask);
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
+ XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Point,
+ MIP_FILTER_shift, MIP_FILTER_mask);
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
+ XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Linear,
+ MIP_FILTER_shift, MIP_FILTER_mask);
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
+ XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Point,
+ MIP_FILTER_shift, MIP_FILTER_mask);
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
+ XY_MIN_FILTER_shift, XY_MIN_FILTER_mask);
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Linear,
+ MIP_FILTER_shift, MIP_FILTER_mask);
+ break;
+ }
+
+ /* Note we don't have 3D mipmaps so only use the mag filter setting
+ * to set the 3D texture filter mode.
+ */
+ switch (magf) {
+ case GL_NEAREST:
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
+ XY_MAG_FILTER_shift, XY_MAG_FILTER_mask);
+ break;
+ case GL_LINEAR:
+ SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
+ XY_MAG_FILTER_shift, XY_MAG_FILTER_mask);
+ break;
+ }
+}
+
+static void r600SetTexBorderColor(radeonTexObjPtr t, const GLfloat color[4])
+{
+ t->TD_PS_SAMPLER0_BORDER_ALPHA = *((uint32_t*)&(color[3]));
+ t->TD_PS_SAMPLER0_BORDER_RED = *((uint32_t*)&(color[2]));
+ t->TD_PS_SAMPLER0_BORDER_GREEN = *((uint32_t*)&(color[1]));
+ t->TD_PS_SAMPLER0_BORDER_BLUE = *((uint32_t*)&(color[0]));
+ SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_BORDER_COLOR_REGISTER,
+ BORDER_COLOR_TYPE_shift, BORDER_COLOR_TYPE_mask);
+}
+
+/**
+ * Changes variables and flags for a state update, which will happen at the
+ * next UpdateTextureState
+ */
+
+static void r600TexParameter(GLcontext * ctx, GLenum target,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat * params)
+{
+ radeonTexObj* t = radeon_tex_obj(texObj);
+
+ radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_VERBOSE,
+ "%s( %s )\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(pname));
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ r600SetTexFilter(t, texObj->MinFilter, texObj->MagFilter, texObj->MaxAnisotropy);
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ r600UpdateTexWrap(t);
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ r600SetTexBorderColor(t, texObj->BorderColor);
+ break;
+
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ /* This isn't the most efficient solution but there doesn't appear to
+ * be a nice alternative. Since there's no LOD clamping,
+ * we just have to rely on loading the right subset of mipmap levels
+ * to simulate a clamped LOD.
+ */
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = 0;
+ t->validated = GL_FALSE;
+ }
+ break;
+
+ case GL_DEPTH_TEXTURE_MODE:
+ if (!texObj->Image[0][texObj->BaseLevel])
+ return;
+ if (texObj->Image[0][texObj->BaseLevel]->TexFormat->BaseFormat
+ == GL_DEPTH_COMPONENT) {
+ r600SetDepthTexMode(texObj);
+ break;
+ } else {
+ /* If the texture isn't a depth texture, changing this
+ * state won't cause any changes to the hardware.
+ * Don't force a flush of texture state.
+ */
+ return;
+ }
+
+ default:
+ return;
+ }
+}
+
+static void r600DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
+{
+ context_t* rmesa = R700_CONTEXT(ctx);
+ radeonTexObj* t = radeon_tex_obj(texObj);
+
+ radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_NORMAL,
+ "%s( %p (target = %s) )\n", __FUNCTION__,
+ (void *)texObj,
+ _mesa_lookup_enum_by_nr(texObj->Target));
+
+ if (rmesa) {
+ int i;
+ radeon_firevertices(&rmesa->radeon);
+
+ for(i = 0; i < R700_MAX_TEXTURE_UNITS; ++i)
+ if (rmesa->hw.textures[i] == t)
+ rmesa->hw.textures[i] = 0;
+ }
+
+ if (t->bo) {
+ radeon_bo_unref(t->bo);
+ t->bo = NULL;
+ }
+
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = 0;
+ }
+ _mesa_delete_texture_object(ctx, texObj);
+}
+
+/**
+ * Allocate a new texture object.
+ * Called via ctx->Driver.NewTextureObject.
+ * Note: this function will be called during context creation to
+ * allocate the default texture objects.
+ * Fixup MaxAnisotropy according to user preference.
+ */
+static struct gl_texture_object *r600NewTextureObject(GLcontext * ctx,
+ GLuint name,
+ GLenum target)
+{
+ context_t* rmesa = R700_CONTEXT(ctx);
+ radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj);
+
+
+ radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_NORMAL,
+ "%s( %p (target = %s) )\n", __FUNCTION__,
+ t, _mesa_lookup_enum_by_nr(target));
+
+ _mesa_initialize_texture_object(&t->base, name, target);
+ t->base.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
+
+ /* Initialize hardware state */
+ r600SetTexDefaultState(t);
+ r600UpdateTexWrap(t);
+ r600SetTexFilter(t, t->base.MinFilter, t->base.MagFilter, t->base.MaxAnisotropy);
+ r600SetTexBorderColor(t, t->base.BorderColor);
+
+ return &t->base;
+}
+
+void r600InitTextureFuncs(struct dd_function_table *functions)
+{
+ /* Note: we only plug in the functions we implement in the driver
+ * since _mesa_init_driver_functions() was already called.
+ */
+ functions->NewTextureImage = radeonNewTextureImage;
+ functions->FreeTexImageData = radeonFreeTexImageData;
+ functions->MapTexture = radeonMapTexture;
+ functions->UnmapTexture = radeonUnmapTexture;
+
+ functions->ChooseTextureFormat = radeonChooseTextureFormat_mesa;
+ functions->TexImage1D = radeonTexImage1D;
+ functions->TexImage2D = radeonTexImage2D;
+ functions->TexImage3D = radeonTexImage3D;
+ functions->TexSubImage1D = radeonTexSubImage1D;
+ functions->TexSubImage2D = radeonTexSubImage2D;
+ functions->TexSubImage3D = radeonTexSubImage3D;
+ functions->GetTexImage = radeonGetTexImage;
+ functions->GetCompressedTexImage = radeonGetCompressedTexImage;
+ functions->NewTextureObject = r600NewTextureObject;
+ functions->DeleteTexture = r600DeleteTexture;
+ functions->IsTextureResident = driIsTextureResident;
+
+ functions->TexParameter = r600TexParameter;
+
+ functions->CompressedTexImage2D = radeonCompressedTexImage2D;
+ functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
+
+ functions->GenerateMipmap = radeonGenerateMipmap;
+
+ driInitTextureFormats();
+}
diff --git a/src/mesa/drivers/dri/r200/r200_span.h b/src/mesa/drivers/dri/r600/r600_tex.h
index bae5644309..fb0e1a023e 100644
--- a/src/mesa/drivers/dri/r200/r200_span.h
+++ b/src/mesa/drivers/dri/r600/r600_tex.h
@@ -32,14 +32,32 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* Keith Whitwell <keith@tungstengraphics.com>
*/
-#ifndef __R200_SPAN_H__
-#define __R200_SPAN_H__
+#ifndef __r600_TEX_H__
+#define __r600_TEX_H__
-#include "drirenderbuffer.h"
+/* TODO : review this after texture load code. */
+#define R700_BLIT_WIDTH_BYTES 1024
+/* The BASE_ADDRESS and MIP_ADDRESS fields are 256-byte-aligned */
+#define R700_TEXTURE_ALIGNMENT_MASK 0x255
+/* Texel pitch is 8 alignment. */
+#define R700_TEXEL_PITCH_ALIGNMENT_MASK 0x7
-extern void r200InitSpanFuncs( GLcontext *ctx );
+#define R700_MAX_TEXTURE_UNITS 8 /* TODO : should be 16, lets make it work, review later */
-extern void
-radeonSetSpanFunctions(driRenderbuffer *rb, const GLvisual *vis);
+extern void r600SetDepthTexMode(struct gl_texture_object *tObj);
-#endif
+extern void r600SetTexBuffer(__DRIcontext *pDRICtx, GLint target,
+ __DRIdrawable *dPriv);
+
+extern void r600SetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
+ GLint format, __DRIdrawable *dPriv);
+
+extern void r600SetTexOffset(__DRIcontext *pDRICtx, GLint texname,
+ unsigned long long offset, GLint depth,
+ GLuint pitch);
+
+extern GLboolean r600ValidateBuffers(GLcontext * ctx);
+
+extern void r600InitTextureFuncs(struct dd_function_table *functions);
+
+#endif /* __r600_TEX_H__ */
diff --git a/src/mesa/drivers/dri/r600/r600_texstate.c b/src/mesa/drivers/dri/r600/r600_texstate.c
new file mode 100644
index 0000000000..7d7e77d355
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r600_texstate.c
@@ -0,0 +1,1003 @@
+/*
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/**
+ * \file
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * \todo Enable R300 texture tiling code?
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "main/teximage.h"
+#include "main/texobj.h"
+#include "main/enums.h"
+#include "main/simple_list.h"
+
+#include "r600_context.h"
+#include "r700_state.h"
+#include "radeon_mipmap_tree.h"
+#include "r600_tex.h"
+#include "r700_fragprog.h"
+#include "r700_vertprog.h"
+
+void r600UpdateTextureState(GLcontext * ctx);
+
+void r600UpdateTextureState(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ struct gl_texture_unit *texUnit;
+ struct radeon_tex_obj *t;
+ GLuint unit;
+
+ R600_STATECHANGE(context, tx);
+ R600_STATECHANGE(context, tx_smplr);
+ R600_STATECHANGE(context, tx_brdr_clr);
+
+ for (unit = 0; unit < R700_MAX_TEXTURE_UNITS; unit++) {
+ texUnit = &ctx->Texture.Unit[unit];
+ t = radeon_tex_obj(ctx->Texture.Unit[unit]._Current);
+ r700->textures[unit] = NULL;
+ if (texUnit->_ReallyEnabled) {
+ if (!t)
+ continue;
+ r700->textures[unit] = t;
+ }
+ }
+}
+
+static GLboolean r600GetTexFormat(struct gl_texture_object *tObj, GLuint mesa_format)
+{
+ radeonTexObj *t = radeon_tex_obj(tObj);
+
+ CLEARfield(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ CLEARfield(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ CLEARfield(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ CLEARfield(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+
+ switch (mesa_format) /* This is mesa format. */
+ {
+ case MESA_FORMAT_RGBA8888:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_RGBA8888_REV:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_ARGB8888:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_ARGB8888_REV:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_RGB888:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_RGB565:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_5_6_5,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_RGB565_REV:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_5_6_5,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_ARGB4444:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_4_4_4_4,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_ARGB4444_REV:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_4_4_4_4,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_ARGB1555:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_1_5_5_5,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_ARGB1555_REV:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_1_5_5_5,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_AL88:
+ case MESA_FORMAT_AL88_REV: /* TODO : Check this. */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_RGB332:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_3_3_2,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_A8: /* ZERO, ZERO, ZERO, X */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_L8: /* X, X, X, ONE */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_I8: /* X, X, X, X */
+ case MESA_FORMAT_CI8:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ /* YUV422 TODO conversion */ /* X, Y, Z, ONE, G8R8_G8B8 */
+ /*
+ case MESA_FORMAT_YCBCR:
+ t->SQ_TEX_RESOURCE1.bitfields.DATA_FORMAT = ;
+ break;
+ */
+ /* VUY422 TODO conversion */ /* X, Y, Z, ONE, G8R8_G8B8 */
+ /*
+ case MESA_FORMAT_YCBCR_REV:
+ t->SQ_TEX_RESOURCE1.bitfields.DATA_FORMAT = ;
+ break;
+ */
+ case MESA_FORMAT_RGB_DXT1: /* not supported yet */
+
+ break;
+ case MESA_FORMAT_RGBA_DXT1: /* not supported yet */
+
+ break;
+ case MESA_FORMAT_RGBA_DXT3: /* not supported yet */
+
+ break;
+ case MESA_FORMAT_RGBA_DXT5: /* not supported yet */
+
+ break;
+ case MESA_FORMAT_RGBA_FLOAT32:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_32_32_32_32_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_RGBA_FLOAT16:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_16_16_16_16_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_RGB_FLOAT32: /* X, Y, Z, ONE */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_32_32_32_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_RGB_FLOAT16:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_16_16_16_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_ALPHA_FLOAT32: /* ZERO, ZERO, ZERO, X */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_32_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_ALPHA_FLOAT16: /* ZERO, ZERO, ZERO, X */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_16_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_LUMINANCE_FLOAT32: /* X, X, X, ONE */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_32_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_LUMINANCE_FLOAT16: /* X, X, X, ONE */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_16_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_32_32_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_16_16_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_INTENSITY_FLOAT32: /* X, X, X, X */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_32_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_INTENSITY_FLOAT16: /* X, X, X, X */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_16_FLOAT,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case MESA_FORMAT_Z16:
+ case MESA_FORMAT_Z24_S8:
+ case MESA_FORMAT_Z32:
+ switch (mesa_format) {
+ case MESA_FORMAT_Z16:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_16,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+ break;
+ case MESA_FORMAT_Z24_S8:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_24_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+ break;
+ case MESA_FORMAT_Z32:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_32,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+ break;
+ };
+ switch (tObj->DepthMode) {
+ case GL_LUMINANCE: /* X, X, X, ONE */
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case GL_INTENSITY: /* X, X, X, X */
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ case GL_ALPHA: /* ZERO, ZERO, ZERO, X */
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ break;
+ default:
+ return GL_FALSE;
+ }
+ break;
+ /* EXT_texture_sRGB */
+ case MESA_FORMAT_SRGBA8:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ SETbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
+ break;
+ case MESA_FORMAT_SLA8:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ SETbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
+ break;
+ case MESA_FORMAT_SL8: /* X, X, X, ONE */
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ SETbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
+ break;
+ default:
+ /* Not supported format */
+ return GL_FALSE;
+ };
+
+ return GL_TRUE;
+}
+
+void r600SetDepthTexMode(struct gl_texture_object *tObj)
+{
+ radeonTexObjPtr t;
+
+ if (!tObj)
+ return;
+
+ t = radeon_tex_obj(tObj);
+
+ r600GetTexFormat(tObj, tObj->Image[0][tObj->BaseLevel]->TexFormat->MesaFormat);
+
+}
+
+/**
+ * Compute the cached hardware register values for the given texture object.
+ *
+ * \param rmesa Context pointer
+ * \param t the r300 texture object
+ */
+static void setup_hardware_state(context_t *rmesa, struct gl_texture_object *texObj)
+{
+ radeonTexObj *t = radeon_tex_obj(texObj);
+ const struct gl_texture_image *firstImage;
+ int firstlevel = t->mt ? t->mt->firstLevel : 0;
+ GLuint uTexelPitch, row_align;
+
+ if (rmesa->radeon.radeonScreen->driScreen->dri2.enabled &&
+ t->image_override &&
+ t->bo)
+ return;
+
+ firstImage = t->base.Image[0][firstlevel];
+
+ if (!t->image_override) {
+ if (!r600GetTexFormat(texObj, firstImage->TexFormat->MesaFormat)) {
+ radeon_error("unexpected texture format in %s\n",
+ __FUNCTION__);
+ return;
+ }
+ }
+
+ switch (texObj->Target) {
+ case GL_TEXTURE_1D:
+ SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_1D, DIM_shift, DIM_mask);
+ SETfield(t->SQ_TEX_RESOURCE1, 0, TEX_DEPTH_shift, TEX_DEPTH_mask);
+ break;
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE_NV:
+ SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_2D, DIM_shift, DIM_mask);
+ SETfield(t->SQ_TEX_RESOURCE1, 0, TEX_DEPTH_shift, TEX_DEPTH_mask);
+ break;
+ case GL_TEXTURE_3D:
+ SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_3D, DIM_shift, DIM_mask);
+ SETfield(t->SQ_TEX_RESOURCE1, firstImage->Depth - 1, // ???
+ TEX_DEPTH_shift, TEX_DEPTH_mask);
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_CUBEMAP, DIM_shift, DIM_mask);
+ SETfield(t->SQ_TEX_RESOURCE1, 0, TEX_DEPTH_shift, TEX_DEPTH_mask);
+ break;
+ default:
+ radeon_error("unexpected texture target type in %s\n", __FUNCTION__);
+ return;
+ }
+
+ row_align = rmesa->radeon.texture_row_align - 1;
+ uTexelPitch = ((firstImage->Width * t->mt->bpp + row_align) & ~row_align) / t->mt->bpp;
+ uTexelPitch = (uTexelPitch + R700_TEXEL_PITCH_ALIGNMENT_MASK)
+ & ~R700_TEXEL_PITCH_ALIGNMENT_MASK;
+
+ /* min pitch is 8 */
+ if (uTexelPitch < 8)
+ uTexelPitch = 8;
+
+ SETfield(t->SQ_TEX_RESOURCE0, (uTexelPitch/8)-1, PITCH_shift, PITCH_mask);
+ SETfield(t->SQ_TEX_RESOURCE0, firstImage->Width - 1,
+ TEX_WIDTH_shift, TEX_WIDTH_mask);
+ SETfield(t->SQ_TEX_RESOURCE1, firstImage->Height - 1,
+ TEX_HEIGHT_shift, TEX_HEIGHT_mask);
+
+ if ((t->mt->lastLevel - t->mt->firstLevel) > 0) {
+ t->SQ_TEX_RESOURCE3 = t->mt->levels[0].size / 256;
+ SETfield(t->SQ_TEX_RESOURCE4, t->mt->firstLevel, BASE_LEVEL_shift, BASE_LEVEL_mask);
+ SETfield(t->SQ_TEX_RESOURCE5, t->mt->lastLevel, LAST_LEVEL_shift, LAST_LEVEL_mask);
+ }
+}
+
+/**
+ * Ensure the given texture is ready for rendering.
+ *
+ * Mostly this means populating the texture object's mipmap tree.
+ */
+static GLboolean r600_validate_texture(GLcontext * ctx, struct gl_texture_object *texObj)
+{
+ context_t *rmesa = R700_CONTEXT(ctx);
+ radeonTexObj *t = radeon_tex_obj(texObj);
+
+ if (!radeon_validate_texture_miptree(ctx, texObj))
+ return GL_FALSE;
+
+ /* Configure the hardware registers (more precisely, the cached version
+ * of the hardware registers). */
+ setup_hardware_state(rmesa, texObj);
+
+ t->validated = GL_TRUE;
+ return GL_TRUE;
+}
+
+/**
+ * Ensure all enabled and complete textures are uploaded along with any buffers being used.
+ */
+GLboolean r600ValidateBuffers(GLcontext * ctx)
+{
+ context_t *rmesa = R700_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrb;
+ struct radeon_bo *pbo;
+ int i;
+ int ret;
+
+ radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
+
+ rrb = radeon_get_colorbuffer(&rmesa->radeon);
+ /* color buffer */
+ if (rrb && rrb->bo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+ rrb->bo, 0,
+ RADEON_GEM_DOMAIN_VRAM);
+ }
+
+ /* depth buffer */
+ rrb = radeon_get_depthbuffer(&rmesa->radeon);
+ if (rrb && rrb->bo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+ rrb->bo, 0,
+ RADEON_GEM_DOMAIN_VRAM);
+ }
+
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
+ radeonTexObj *t;
+
+ if (!ctx->Texture.Unit[i]._ReallyEnabled)
+ continue;
+
+ if (!r600_validate_texture(ctx, ctx->Texture.Unit[i]._Current)) {
+ radeon_warning("failed to validate texture for unit %d.\n", i);
+ }
+ t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
+ if (t->image_override && t->bo)
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+ t->bo,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+ else if (t->mt->bo)
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+ t->mt->bo,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+ }
+
+ pbo = (struct radeon_bo *)r700GetActiveFpShaderBo(ctx);
+ if (pbo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, pbo,
+ RADEON_GEM_DOMAIN_GTT, 0);
+ }
+
+ pbo = (struct radeon_bo *)r700GetActiveVpShaderBo(ctx);
+ if (pbo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, pbo,
+ RADEON_GEM_DOMAIN_GTT, 0);
+ }
+
+ ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, first_elem(&rmesa->radeon.dma.reserved)->bo, RADEON_GEM_DOMAIN_GTT, 0);
+ if (ret)
+ return GL_FALSE;
+ return GL_TRUE;
+}
+
+void r600SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
+ unsigned long long offset, GLint depth, GLuint pitch)
+{
+ context_t *rmesa = pDRICtx->driverPrivate;
+ struct gl_texture_object *tObj =
+ _mesa_lookup_texture(rmesa->radeon.glCtx, texname);
+ radeonTexObjPtr t = radeon_tex_obj(tObj);
+ uint32_t pitch_val, size;
+
+ if (!tObj)
+ return;
+
+ t->image_override = GL_TRUE;
+
+ if (!offset)
+ return;
+
+ size = pitch;//h * w * (depth / 8);
+ if (t->bo) {
+ radeon_bo_unref(t->bo);
+ t->bo = NULL;
+ }
+ t->bo = radeon_legacy_bo_alloc_fake(rmesa->radeon.radeonScreen->bom, size, offset);
+ t->override_offset = offset;
+ pitch_val = pitch;
+ switch (depth) {
+ case 32:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ pitch_val /= 4;
+ break;
+ case 24:
+ default:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ pitch_val /= 4;
+ break;
+ case 16:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_5_6_5,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ pitch_val /= 2;
+ break;
+ }
+
+ pitch_val = (pitch_val + R700_TEXEL_PITCH_ALIGNMENT_MASK)
+ & ~R700_TEXEL_PITCH_ALIGNMENT_MASK;
+
+ /* min pitch is 8 */
+ if (pitch_val < 8)
+ pitch_val = 8;
+
+ SETfield(t->SQ_TEX_RESOURCE0, (pitch_val/8)-1, PITCH_shift, PITCH_mask);
+}
+
+void r600SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format, __DRIdrawable *dPriv)
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ struct radeon_renderbuffer *rb;
+ radeon_texture_image *rImage;
+ radeonContextPtr radeon;
+ context_t *rmesa;
+ struct radeon_framebuffer *rfb;
+ radeonTexObjPtr t;
+ uint32_t pitch_val;
+ uint32_t internalFormat, type, format;
+
+ type = GL_BGRA;
+ format = GL_UNSIGNED_BYTE;
+ internalFormat = (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT ? 3 : 4);
+
+ radeon = pDRICtx->driverPrivate;
+ rmesa = pDRICtx->driverPrivate;
+
+ rfb = dPriv->driverPrivate;
+ texUnit = &radeon->glCtx->Texture.Unit[radeon->glCtx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(radeon->glCtx, texUnit, target);
+ texImage = _mesa_get_tex_image(radeon->glCtx, texObj, target, 0);
+
+ rImage = get_radeon_texture_image(texImage);
+ t = radeon_tex_obj(texObj);
+ if (t == NULL) {
+ return;
+ }
+
+ radeon_update_renderbuffers(pDRICtx, dPriv);
+ /* back & depth buffer are useless free them right away */
+ rb = (void*)rfb->base.Attachment[BUFFER_DEPTH].Renderbuffer;
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
+ rb = (void*)rfb->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
+ rb = rfb->color_rb[0];
+ if (rb->bo == NULL) {
+ /* Failed to BO for the buffer */
+ return;
+ }
+
+ _mesa_lock_texture(radeon->glCtx, texObj);
+ if (t->bo) {
+ radeon_bo_unref(t->bo);
+ t->bo = NULL;
+ }
+ if (rImage->bo) {
+ radeon_bo_unref(rImage->bo);
+ rImage->bo = NULL;
+ }
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = NULL;
+ }
+ if (rImage->mt) {
+ radeon_miptree_unreference(rImage->mt);
+ rImage->mt = NULL;
+ }
+ _mesa_init_teximage_fields(radeon->glCtx, target, texImage,
+ rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
+ texImage->RowStride = rb->pitch / rb->cpp;
+ texImage->TexFormat = radeonChooseTextureFormat(radeon->glCtx,
+ internalFormat,
+ type, format, 0);
+ rImage->bo = rb->bo;
+ radeon_bo_ref(rImage->bo);
+ t->bo = rb->bo;
+ radeon_bo_ref(t->bo);
+ t->image_override = GL_TRUE;
+ t->override_offset = 0;
+ pitch_val = rb->pitch;
+ switch (rb->cpp) {
+ case 4:
+ if (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT) {
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ } else {
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ }
+ pitch_val /= 4;
+ break;
+ case 3:
+ default:
+ // FMT_8_8_8 ???
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_8_8_8_8,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ pitch_val /= 4;
+ break;
+ case 2:
+ SETfield(t->SQ_TEX_RESOURCE1, FMT_5_6_5,
+ SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_shift, SQ_TEX_RESOURCE_WORD1_0__DATA_FORMAT_mask);
+
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+ SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+ SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+ pitch_val /= 2;
+ break;
+ }
+
+ pitch_val = (pitch_val + R700_TEXEL_PITCH_ALIGNMENT_MASK)
+ & ~R700_TEXEL_PITCH_ALIGNMENT_MASK;
+
+ /* min pitch is 8 */
+ if (pitch_val < 8)
+ pitch_val = 8;
+
+ SETfield(t->SQ_TEX_RESOURCE0, (pitch_val/8)-1, PITCH_shift, PITCH_mask);
+ SETfield(t->SQ_TEX_RESOURCE0, rb->base.Width - 1,
+ TEX_WIDTH_shift, TEX_WIDTH_mask);
+ SETfield(t->SQ_TEX_RESOURCE1, rb->base.Height - 1,
+ TEX_HEIGHT_shift, TEX_HEIGHT_mask);
+
+ t->validated = GL_TRUE;
+ _mesa_unlock_texture(radeon->glCtx, texObj);
+ return;
+}
+
+void r600SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
+{
+ r600SetTexBuffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
+}
diff --git a/src/mesa/drivers/dri/r600/r700_assembler.c b/src/mesa/drivers/dri/r600/r700_assembler.c
new file mode 100644
index 0000000000..fda6692725
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_assembler.c
@@ -0,0 +1,4118 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "main/mtypes.h"
+#include "main/imports.h"
+
+#include "radeon_debug.h"
+#include "r600_context.h"
+
+#include "r700_assembler.h"
+
+BITS addrmode_PVSDST(PVSDST * pPVSDST)
+{
+ return pPVSDST->addrmode0 | ((BITS)pPVSDST->addrmode1 << 1);
+}
+
+void setaddrmode_PVSDST(PVSDST * pPVSDST, BITS addrmode)
+{
+ pPVSDST->addrmode0 = addrmode & 1;
+ pPVSDST->addrmode1 = (addrmode >> 1) & 1;
+}
+
+void nomask_PVSDST(PVSDST * pPVSDST)
+{
+ pPVSDST->writex = pPVSDST->writey = pPVSDST->writez = pPVSDST->writew = 1;
+}
+
+BITS addrmode_PVSSRC(PVSSRC* pPVSSRC)
+{
+ return pPVSSRC->addrmode0 | ((BITS)pPVSSRC->addrmode1 << 1);
+}
+
+void setaddrmode_PVSSRC(PVSSRC* pPVSSRC, BITS addrmode)
+{
+ pPVSSRC->addrmode0 = addrmode & 1;
+ pPVSSRC->addrmode1 = (addrmode >> 1) & 1;
+}
+
+
+void setswizzle_PVSSRC(PVSSRC* pPVSSRC, BITS swz)
+{
+ pPVSSRC->swizzlex =
+ pPVSSRC->swizzley =
+ pPVSSRC->swizzlez =
+ pPVSSRC->swizzlew = swz;
+}
+
+void noswizzle_PVSSRC(PVSSRC* pPVSSRC)
+{
+ pPVSSRC->swizzlex = SQ_SEL_X;
+ pPVSSRC->swizzley = SQ_SEL_Y;
+ pPVSSRC->swizzlez = SQ_SEL_Z;
+ pPVSSRC->swizzlew = SQ_SEL_W;
+}
+
+void
+swizzleagain_PVSSRC(PVSSRC * pPVSSRC, BITS x, BITS y, BITS z, BITS w)
+{
+ switch (x)
+ {
+ case SQ_SEL_X: x = pPVSSRC->swizzlex;
+ break;
+ case SQ_SEL_Y: x = pPVSSRC->swizzley;
+ break;
+ case SQ_SEL_Z: x = pPVSSRC->swizzlez;
+ break;
+ case SQ_SEL_W: x = pPVSSRC->swizzlew;
+ break;
+ default:;
+ }
+
+ switch (y)
+ {
+ case SQ_SEL_X: y = pPVSSRC->swizzlex;
+ break;
+ case SQ_SEL_Y: y = pPVSSRC->swizzley;
+ break;
+ case SQ_SEL_Z: y = pPVSSRC->swizzlez;
+ break;
+ case SQ_SEL_W: y = pPVSSRC->swizzlew;
+ break;
+ default:;
+ }
+
+ switch (z)
+ {
+ case SQ_SEL_X: z = pPVSSRC->swizzlex;
+ break;
+ case SQ_SEL_Y: z = pPVSSRC->swizzley;
+ break;
+ case SQ_SEL_Z: z = pPVSSRC->swizzlez;
+ break;
+ case SQ_SEL_W: z = pPVSSRC->swizzlew;
+ break;
+ default:;
+ }
+
+ switch (w)
+ {
+ case SQ_SEL_X: w = pPVSSRC->swizzlex;
+ break;
+ case SQ_SEL_Y: w = pPVSSRC->swizzley;
+ break;
+ case SQ_SEL_Z: w = pPVSSRC->swizzlez;
+ break;
+ case SQ_SEL_W: w = pPVSSRC->swizzlew;
+ break;
+ default:;
+ }
+
+ pPVSSRC->swizzlex = x;
+ pPVSSRC->swizzley = y;
+ pPVSSRC->swizzlez = z;
+ pPVSSRC->swizzlew = w;
+}
+
+void neg_PVSSRC(PVSSRC* pPVSSRC)
+{
+ pPVSSRC->negx = 1;
+ pPVSSRC->negy = 1;
+ pPVSSRC->negz = 1;
+ pPVSSRC->negw = 1;
+}
+
+void noneg_PVSSRC(PVSSRC* pPVSSRC)
+{
+ pPVSSRC->negx = 0;
+ pPVSSRC->negy = 0;
+ pPVSSRC->negz = 0;
+ pPVSSRC->negw = 0;
+}
+
+// negate argument (for SUB instead of ADD and alike)
+void flipneg_PVSSRC(PVSSRC* pPVSSRC)
+{
+ pPVSSRC->negx = !pPVSSRC->negx;
+ pPVSSRC->negy = !pPVSSRC->negy;
+ pPVSSRC->negz = !pPVSSRC->negz;
+ pPVSSRC->negw = !pPVSSRC->negw;
+}
+
+void zerocomp_PVSSRC(PVSSRC* pPVSSRC, int c)
+{
+ switch (c)
+ {
+ case 0: pPVSSRC->swizzlex = SQ_SEL_0; pPVSSRC->negx = 0; break;
+ case 1: pPVSSRC->swizzley = SQ_SEL_0; pPVSSRC->negy = 0; break;
+ case 2: pPVSSRC->swizzlez = SQ_SEL_0; pPVSSRC->negz = 0; break;
+ case 3: pPVSSRC->swizzlew = SQ_SEL_0; pPVSSRC->negw = 0; break;
+ default:;
+ }
+}
+
+void onecomp_PVSSRC(PVSSRC* pPVSSRC, int c)
+{
+ switch (c)
+ {
+ case 0: pPVSSRC->swizzlex = SQ_SEL_1; pPVSSRC->negx = 0; break;
+ case 1: pPVSSRC->swizzley = SQ_SEL_1; pPVSSRC->negy = 0; break;
+ case 2: pPVSSRC->swizzlez = SQ_SEL_1; pPVSSRC->negz = 0; break;
+ case 3: pPVSSRC->swizzlew = SQ_SEL_1; pPVSSRC->negw = 0; break;
+ default:;
+ }
+}
+
+BITS is_misc_component_exported(VAP_OUT_VTX_FMT_0* pOutVTXFmt0)
+{
+ return (pOutVTXFmt0->point_size |
+ pOutVTXFmt0->edge_flag |
+ pOutVTXFmt0->rta_index |
+ pOutVTXFmt0->kill_flag |
+ pOutVTXFmt0->viewport_index);
+}
+
+BITS is_depth_component_exported(OUT_FRAGMENT_FMT_0* pFPOutFmt)
+{
+ return (pFPOutFmt->depth |
+ pFPOutFmt->stencil_ref |
+ pFPOutFmt->mask |
+ pFPOutFmt->coverage_to_mask);
+}
+
+GLboolean is_reduction_opcode(PVSDWORD* dest)
+{
+ if (dest->dst.op3 == 0)
+ {
+ if ( (dest->dst.opcode == SQ_OP2_INST_DOT4 || dest->dst.opcode == SQ_OP2_INST_DOT4_IEEE) )
+ {
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+GLuint GetSurfaceFormat(GLenum eType, GLuint nChannels, GLuint * pClient_size)
+{
+ GLuint format = FMT_INVALID;
+ GLuint uiElemSize = 0;
+
+ switch (eType)
+ {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ uiElemSize = 1;
+ switch(nChannels)
+ {
+ case 1:
+ format = FMT_8; break;
+ case 2:
+ format = FMT_8_8; break;
+ case 3:
+ format = FMT_8_8_8; break;
+ case 4:
+ format = FMT_8_8_8_8; break;
+ default:
+ break;
+ }
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ uiElemSize = 2;
+ switch(nChannels)
+ {
+ case 1:
+ format = FMT_16; break;
+ case 2:
+ format = FMT_16_16; break;
+ case 3:
+ format = FMT_16_16_16; break;
+ case 4:
+ format = FMT_16_16_16_16; break;
+ default:
+ break;
+ }
+ break;
+
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ uiElemSize = 4;
+ switch(nChannels)
+ {
+ case 1:
+ format = FMT_32; break;
+ case 2:
+ format = FMT_32_32; break;
+ case 3:
+ format = FMT_32_32_32; break;
+ case 4:
+ format = FMT_32_32_32_32; break;
+ default:
+ break;
+ }
+ break;
+
+ case GL_FLOAT:
+ uiElemSize = 4;
+ switch(nChannels)
+ {
+ case 1:
+ format = FMT_32_FLOAT; break;
+ case 2:
+ format = FMT_32_32_FLOAT; break;
+ case 3:
+ format = FMT_32_32_32_FLOAT; break;
+ case 4:
+ format = FMT_32_32_32_32_FLOAT; break;
+ default:
+ break;
+ }
+ break;
+ case GL_DOUBLE:
+ uiElemSize = 8;
+ switch(nChannels)
+ {
+ case 1:
+ format = FMT_32_FLOAT; break;
+ case 2:
+ format = FMT_32_32_FLOAT; break;
+ case 3:
+ format = FMT_32_32_32_FLOAT; break;
+ case 4:
+ format = FMT_32_32_32_32_FLOAT; break;
+ default:
+ break;
+ }
+ break;
+ default:
+ ;
+ //GL_ASSERT_NO_CASE();
+ }
+
+ if(NULL != pClient_size)
+ {
+ *pClient_size = uiElemSize * nChannels;
+ }
+
+ return(format);
+}
+
+unsigned int r700GetNumOperands(r700_AssemblerBase* pAsm)
+{
+ if(pAsm->D.dst.op3)
+ {
+ return 3;
+ }
+
+ switch (pAsm->D.dst.opcode)
+ {
+ case SQ_OP2_INST_ADD:
+ case SQ_OP2_INST_MUL:
+ case SQ_OP2_INST_MAX:
+ case SQ_OP2_INST_MIN:
+ //case SQ_OP2_INST_MAX_DX10:
+ //case SQ_OP2_INST_MIN_DX10:
+ case SQ_OP2_INST_SETGT:
+ case SQ_OP2_INST_SETGE:
+ case SQ_OP2_INST_PRED_SETE:
+ case SQ_OP2_INST_PRED_SETGT:
+ case SQ_OP2_INST_PRED_SETGE:
+ case SQ_OP2_INST_PRED_SETNE:
+ case SQ_OP2_INST_DOT4:
+ case SQ_OP2_INST_DOT4_IEEE:
+ return 2;
+
+ case SQ_OP2_INST_MOV:
+ case SQ_OP2_INST_FRACT:
+ case SQ_OP2_INST_FLOOR:
+ case SQ_OP2_INST_KILLGT:
+ case SQ_OP2_INST_EXP_IEEE:
+ case SQ_OP2_INST_LOG_CLAMPED:
+ case SQ_OP2_INST_LOG_IEEE:
+ case SQ_OP2_INST_RECIP_IEEE:
+ case SQ_OP2_INST_RECIPSQRT_IEEE:
+ case SQ_OP2_INST_FLT_TO_INT:
+ case SQ_OP2_INST_SIN:
+ case SQ_OP2_INST_COS:
+ return 1;
+
+ default: radeon_error(
+ "Need instruction operand number for %x.\n", pAsm->D.dst.opcode);
+ };
+
+ return 3;
+}
+
+int Init_r700_AssemblerBase(SHADER_PIPE_TYPE spt, r700_AssemblerBase* pAsm, R700_Shader* pShader)
+{
+ GLuint i;
+
+ Init_R700_Shader(pShader);
+ pAsm->pR700Shader = pShader;
+ pAsm->currentShaderType = spt;
+
+ pAsm->cf_last_export_ptr = NULL;
+
+ pAsm->cf_current_export_clause_ptr = NULL;
+ pAsm->cf_current_alu_clause_ptr = NULL;
+ pAsm->cf_current_tex_clause_ptr = NULL;
+ pAsm->cf_current_vtx_clause_ptr = NULL;
+ pAsm->cf_current_cf_clause_ptr = NULL;
+
+ // No clause has been created yet
+ pAsm->cf_current_clause_type = CF_EMPTY_CLAUSE;
+
+ pAsm->number_of_colorandz_exports = 0;
+ pAsm->number_of_exports = 0;
+ pAsm->number_of_export_opcodes = 0;
+
+
+ pAsm->D.bits = 0;
+ pAsm->S[0].bits = 0;
+ pAsm->S[1].bits = 0;
+ pAsm->S[2].bits = 0;
+
+ pAsm->uLastPosUpdate = 0;
+
+ *(BITS *) &pAsm->fp_stOutFmt0 = 0;
+
+ pAsm->uIIns = 0;
+ pAsm->uOIns = 0;
+ pAsm->number_used_registers = 0;
+ pAsm->uUsedConsts = 256;
+
+
+ // Fragment programs
+ pAsm->uBoolConsts = 0;
+ pAsm->uIntConsts = 0;
+ pAsm->uInsts = 0;
+ pAsm->uConsts = 0;
+
+ pAsm->FCSP = 0;
+ pAsm->fc_stack[0].type = FC_NONE;
+
+ pAsm->branch_depth = 0;
+ pAsm->max_branch_depth = 0;
+
+ pAsm->aArgSubst[0] =
+ pAsm->aArgSubst[1] =
+ pAsm->aArgSubst[2] =
+ pAsm->aArgSubst[3] = (-1);
+
+ pAsm->uOutputs = 0;
+
+ for (i=0; i<NUMBER_OF_OUTPUT_COLORS; i++)
+ {
+ pAsm->color_export_register_number[i] = (-1);
+ }
+
+
+ pAsm->depth_export_register_number = (-1);
+ pAsm->stencil_export_register_number = (-1);
+ pAsm->coverage_to_mask_export_register_number = (-1);
+ pAsm->mask_export_register_number = (-1);
+
+ pAsm->starting_export_register_number = 0;
+ pAsm->starting_vfetch_register_number = 0;
+ pAsm->starting_temp_register_number = 0;
+ pAsm->uFirstHelpReg = 0;
+
+
+ pAsm->input_position_is_used = GL_FALSE;
+ pAsm->input_normal_is_used = GL_FALSE;
+
+
+ for (i=0; i<NUMBER_OF_INPUT_COLORS; i++)
+ {
+ pAsm->input_color_is_used[ i ] = GL_FALSE;
+ }
+
+ for (i=0; i<NUMBER_OF_TEXTURE_UNITS; i++)
+ {
+ pAsm->input_texture_unit_is_used[ i ] = GL_FALSE;
+ }
+
+ for (i=0; i<VERT_ATTRIB_MAX; i++)
+ {
+ pAsm->vfetch_instruction_ptr_array[ i ] = NULL;
+ }
+
+ pAsm->number_of_inputs = 0;
+
+ return 0;
+}
+
+GLboolean IsTex(gl_inst_opcode Opcode)
+{
+ if( (OPCODE_TEX==Opcode) || (OPCODE_TXP==Opcode) || (OPCODE_TXB==Opcode) )
+ {
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+GLboolean IsAlu(gl_inst_opcode Opcode)
+{
+ //TODO : more for fc and ex for higher spec.
+ if( IsTex(Opcode) )
+ {
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+int check_current_clause(r700_AssemblerBase* pAsm,
+ CF_CLAUSE_TYPE new_clause_type)
+{
+ if (pAsm->cf_current_clause_type != new_clause_type)
+ { //Close last open clause
+ switch (pAsm->cf_current_clause_type)
+ {
+ case CF_ALU_CLAUSE:
+ if ( pAsm->cf_current_alu_clause_ptr != NULL)
+ {
+ pAsm->cf_current_alu_clause_ptr = NULL;
+ }
+ break;
+ case CF_VTX_CLAUSE:
+ if ( pAsm->cf_current_vtx_clause_ptr != NULL)
+ {
+ pAsm->cf_current_vtx_clause_ptr = NULL;
+ }
+ break;
+ case CF_TEX_CLAUSE:
+ if ( pAsm->cf_current_tex_clause_ptr != NULL)
+ {
+ pAsm->cf_current_tex_clause_ptr = NULL;
+ }
+ break;
+ case CF_EXPORT_CLAUSE:
+ if ( pAsm->cf_current_export_clause_ptr != NULL)
+ {
+ pAsm->cf_current_export_clause_ptr = NULL;
+ }
+ break;
+ case CF_OTHER_CLAUSE:
+ if ( pAsm->cf_current_cf_clause_ptr != NULL)
+ {
+ pAsm->cf_current_cf_clause_ptr = NULL;
+ }
+ break;
+ case CF_EMPTY_CLAUSE:
+ break;
+ default:
+ radeon_error(
+ "Unknown CF_CLAUSE_TYPE (%d) in check_current_clause. \n", (int) new_clause_type);
+ return GL_FALSE;
+ }
+
+ pAsm->cf_current_clause_type = CF_EMPTY_CLAUSE;
+
+ // Create new clause
+ switch (new_clause_type)
+ {
+ case CF_ALU_CLAUSE:
+ pAsm->cf_current_clause_type = CF_ALU_CLAUSE;
+ break;
+ case CF_VTX_CLAUSE:
+ pAsm->cf_current_clause_type = CF_VTX_CLAUSE;
+ break;
+ case CF_TEX_CLAUSE:
+ pAsm->cf_current_clause_type = CF_TEX_CLAUSE;
+ break;
+ case CF_EXPORT_CLAUSE:
+ {
+ R700ControlFlowSXClause* pR700ControlFlowSXClause
+ = (R700ControlFlowSXClause*) CALLOC_STRUCT(R700ControlFlowSXClause);
+
+ // Add new export instruction to control flow program
+ if (pR700ControlFlowSXClause != 0)
+ {
+ pAsm->cf_current_export_clause_ptr = pR700ControlFlowSXClause;
+ Init_R700ControlFlowSXClause(pR700ControlFlowSXClause);
+ AddCFInstruction( pAsm->pR700Shader,
+ (R700ControlFlowInstruction *)pR700ControlFlowSXClause );
+ }
+ else
+ {
+ radeon_error(
+ "Error allocating new EXPORT CF instruction in check_current_clause. \n");
+ return GL_FALSE;
+ }
+ pAsm->cf_current_clause_type = CF_EXPORT_CLAUSE;
+ }
+ break;
+ case CF_EMPTY_CLAUSE:
+ break;
+ case CF_OTHER_CLAUSE:
+ pAsm->cf_current_clause_type = CF_OTHER_CLAUSE;
+ break;
+ default:
+ radeon_error(
+ "Unknown CF_CLAUSE_TYPE (%d) in check_current_clause. \n", (int) new_clause_type);
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean add_vfetch_instruction(r700_AssemblerBase* pAsm,
+ R700VertexInstruction* vertex_instruction_ptr)
+{
+ if( GL_FALSE == check_current_clause(pAsm, CF_VTX_CLAUSE) )
+ {
+ return GL_FALSE;
+ }
+
+ if( pAsm->cf_current_vtx_clause_ptr == NULL ||
+ ( (pAsm->cf_current_vtx_clause_ptr != NULL) &&
+ (pAsm->cf_current_vtx_clause_ptr->m_Word1.f.count >= GetCFMaxInstructions(pAsm->cf_current_vtx_clause_ptr->m_ShaderInstType)-1)
+ ) )
+ {
+ // Create new Vfetch control flow instruction for this new clause
+ pAsm->cf_current_vtx_clause_ptr = (R700ControlFlowGenericClause*) CALLOC_STRUCT(R700ControlFlowGenericClause);
+
+ if (pAsm->cf_current_vtx_clause_ptr != NULL)
+ {
+ Init_R700ControlFlowGenericClause(pAsm->cf_current_vtx_clause_ptr);
+ AddCFInstruction( pAsm->pR700Shader,
+ (R700ControlFlowInstruction *)pAsm->cf_current_vtx_clause_ptr );
+ }
+ else
+ {
+ radeon_error("Could not allocate a new VFetch CF instruction.\n");
+ return GL_FALSE;
+ }
+
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.pop_count = 0x0;
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.cf_const = 0x0;
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.cond = SQ_CF_COND_ACTIVE;
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.count = 0x0;
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.end_of_program = 0x0;
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.cf_inst = SQ_CF_INST_VTX;
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.whole_quad_mode = 0x0;
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.barrier = 0x1;
+
+ LinkVertexInstruction(pAsm->cf_current_vtx_clause_ptr, vertex_instruction_ptr );
+ }
+ else
+ {
+ pAsm->cf_current_vtx_clause_ptr->m_Word1.f.count++;
+ }
+
+ AddVTXInstruction(pAsm->pR700Shader, vertex_instruction_ptr);
+
+ return GL_TRUE;
+}
+
+GLboolean add_tex_instruction(r700_AssemblerBase* pAsm,
+ R700TextureInstruction* tex_instruction_ptr)
+{
+ if ( GL_FALSE == check_current_clause(pAsm, CF_TEX_CLAUSE) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( pAsm->cf_current_tex_clause_ptr == NULL ||
+ ( (pAsm->cf_current_tex_clause_ptr != NULL) &&
+ (pAsm->cf_current_tex_clause_ptr->m_Word1.f.count >= GetCFMaxInstructions(pAsm->cf_current_tex_clause_ptr->m_ShaderInstType)-1)
+ ) )
+ {
+ // new tex cf instruction for this new clause
+ pAsm->cf_current_tex_clause_ptr = (R700ControlFlowGenericClause*) CALLOC_STRUCT(R700ControlFlowGenericClause);
+
+ if (pAsm->cf_current_tex_clause_ptr != NULL)
+ {
+ Init_R700ControlFlowGenericClause(pAsm->cf_current_tex_clause_ptr);
+ AddCFInstruction( pAsm->pR700Shader,
+ (R700ControlFlowInstruction *)pAsm->cf_current_tex_clause_ptr );
+ }
+ else
+ {
+ radeon_error("Could not allocate a new TEX CF instruction.\n");
+ return GL_FALSE;
+ }
+
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.pop_count = 0x0;
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.cf_const = 0x0;
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.cond = SQ_CF_COND_ACTIVE;
+
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.end_of_program = 0x0;
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.cf_inst = SQ_CF_INST_TEX;
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.whole_quad_mode = 0x0;
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.barrier = 0x0; //0x1;
+ }
+ else
+ {
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.count++;
+ }
+
+ // If this clause constains any TEX instruction that is dependent on a previous instruction,
+ // set the barrier bit
+ if( pAsm->pInstDeps[pAsm->uiCurInst].nDstDep > (-1) )
+ {
+ pAsm->cf_current_tex_clause_ptr->m_Word1.f.barrier = 0x1;
+ }
+
+ if(NULL == pAsm->cf_current_tex_clause_ptr->m_pLinkedTEXInstruction)
+ {
+ pAsm->cf_current_tex_clause_ptr->m_pLinkedTEXInstruction = tex_instruction_ptr;
+ tex_instruction_ptr->m_pLinkedGenericClause = pAsm->cf_current_tex_clause_ptr;
+ }
+
+ AddTEXInstruction(pAsm->pR700Shader, tex_instruction_ptr);
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_vfetch_instruction(r700_AssemblerBase* pAsm,
+ GLuint gl_client_id,
+ GLuint destination_register,
+ GLuint number_of_elements,
+ GLenum dataElementType,
+ VTX_FETCH_METHOD* pFetchMethod)
+{
+ GLuint client_size_inbyte;
+ GLuint data_format;
+ GLuint mega_fetch_count;
+ GLuint is_mega_fetch_flag;
+
+ R700VertexGenericFetch* vfetch_instruction_ptr;
+ R700VertexGenericFetch* assembled_vfetch_instruction_ptr = pAsm->vfetch_instruction_ptr_array[ gl_client_id ];
+
+ if (assembled_vfetch_instruction_ptr == NULL)
+ {
+ vfetch_instruction_ptr = (R700VertexGenericFetch*) CALLOC_STRUCT(R700VertexGenericFetch);
+ if (vfetch_instruction_ptr == NULL)
+ {
+ return GL_FALSE;
+ }
+ Init_R700VertexGenericFetch(vfetch_instruction_ptr);
+ }
+ else
+ {
+ vfetch_instruction_ptr = assembled_vfetch_instruction_ptr;
+ }
+
+ data_format = GetSurfaceFormat(dataElementType, number_of_elements, &client_size_inbyte);
+
+ if(GL_TRUE == pFetchMethod->bEnableMini) //More conditions here
+ {
+ //TODO : mini fetch
+ }
+ else
+ {
+ mega_fetch_count = MEGA_FETCH_BYTES - 1;
+ is_mega_fetch_flag = 0x1;
+ pFetchMethod->mega_fetch_remainder = MEGA_FETCH_BYTES - client_size_inbyte;
+ }
+
+ vfetch_instruction_ptr->m_Word0.f.vtx_inst = SQ_VTX_INST_FETCH;
+ vfetch_instruction_ptr->m_Word0.f.fetch_type = SQ_VTX_FETCH_VERTEX_DATA;
+ vfetch_instruction_ptr->m_Word0.f.fetch_whole_quad = 0x0;
+
+ vfetch_instruction_ptr->m_Word0.f.buffer_id = gl_client_id;
+ vfetch_instruction_ptr->m_Word0.f.src_gpr = 0x0;
+ vfetch_instruction_ptr->m_Word0.f.src_rel = SQ_ABSOLUTE;
+ vfetch_instruction_ptr->m_Word0.f.src_sel_x = SQ_SEL_X;
+ vfetch_instruction_ptr->m_Word0.f.mega_fetch_count = mega_fetch_count;
+
+ vfetch_instruction_ptr->m_Word1.f.dst_sel_x = (number_of_elements < 1) ? SQ_SEL_0 : SQ_SEL_X;
+ vfetch_instruction_ptr->m_Word1.f.dst_sel_y = (number_of_elements < 2) ? SQ_SEL_0 : SQ_SEL_Y;
+ vfetch_instruction_ptr->m_Word1.f.dst_sel_z = (number_of_elements < 3) ? SQ_SEL_0 : SQ_SEL_Z;
+ vfetch_instruction_ptr->m_Word1.f.dst_sel_w = (number_of_elements < 4) ? SQ_SEL_1 : SQ_SEL_W;
+
+ vfetch_instruction_ptr->m_Word1.f.use_const_fields = 1;
+
+ // Destination register
+ vfetch_instruction_ptr->m_Word1_GPR.f.dst_gpr = destination_register;
+ vfetch_instruction_ptr->m_Word1_GPR.f.dst_rel = SQ_ABSOLUTE;
+
+ vfetch_instruction_ptr->m_Word2.f.offset = 0;
+ vfetch_instruction_ptr->m_Word2.f.const_buf_no_stride = 0x0;
+
+ vfetch_instruction_ptr->m_Word2.f.mega_fetch = is_mega_fetch_flag;
+
+ if (assembled_vfetch_instruction_ptr == NULL)
+ {
+ if ( GL_FALSE == add_vfetch_instruction(pAsm, (R700VertexInstruction *)vfetch_instruction_ptr) )
+ {
+ return GL_FALSE;
+ }
+
+ if (pAsm->vfetch_instruction_ptr_array[ gl_client_id ] != NULL)
+ {
+ return GL_FALSE;
+ }
+ else
+ {
+ pAsm->vfetch_instruction_ptr_array[ gl_client_id ] = vfetch_instruction_ptr;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLuint gethelpr(r700_AssemblerBase* pAsm)
+{
+ GLuint r = pAsm->uHelpReg;
+ pAsm->uHelpReg++;
+ if (pAsm->uHelpReg > pAsm->number_used_registers)
+ {
+ pAsm->number_used_registers = pAsm->uHelpReg;
+ }
+ return r;
+}
+void resethelpr(r700_AssemblerBase* pAsm)
+{
+ pAsm->uHelpReg = pAsm->uFirstHelpReg;
+}
+
+void checkop_init(r700_AssemblerBase* pAsm)
+{
+ resethelpr(pAsm);
+ pAsm->aArgSubst[0] =
+ pAsm->aArgSubst[1] =
+ pAsm->aArgSubst[2] =
+ pAsm->aArgSubst[3] = -1;
+}
+
+GLboolean mov_temp(r700_AssemblerBase* pAsm, int src)
+{
+ GLuint tmp = gethelpr(pAsm);
+
+ //mov src to temp helper gpr.
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+
+ nomask_PVSDST(&(pAsm->D.dst));
+
+ if( GL_FALSE == assemble_src(pAsm, src, 0) )
+ {
+ return GL_FALSE;
+ }
+
+ noswizzle_PVSSRC(&(pAsm->S[0].src));
+ noneg_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->aArgSubst[1 + src] = tmp;
+
+ return GL_TRUE;
+}
+
+GLboolean checkop1(r700_AssemblerBase* pAsm)
+{
+ checkop_init(pAsm);
+ return GL_TRUE;
+}
+
+GLboolean checkop2(r700_AssemblerBase* pAsm)
+{
+ GLboolean bSrcConst[2];
+ struct prog_instruction *pILInst = &(pAsm->pILInst[pAsm->uiCurInst]);
+
+ checkop_init(pAsm);
+
+ if( (pILInst->SrcReg[0].File == PROGRAM_CONSTANT) ||
+ (pILInst->SrcReg[0].File == PROGRAM_LOCAL_PARAM) ||
+ (pILInst->SrcReg[0].File == PROGRAM_ENV_PARAM) ||
+ (pILInst->SrcReg[0].File == PROGRAM_STATE_VAR) )
+ {
+ bSrcConst[0] = GL_TRUE;
+ }
+ else
+ {
+ bSrcConst[0] = GL_FALSE;
+ }
+ if( (pILInst->SrcReg[1].File == PROGRAM_CONSTANT) ||
+ (pILInst->SrcReg[1].File == PROGRAM_LOCAL_PARAM) ||
+ (pILInst->SrcReg[1].File == PROGRAM_ENV_PARAM) ||
+ (pILInst->SrcReg[1].File == PROGRAM_STATE_VAR) )
+ {
+ bSrcConst[1] = GL_TRUE;
+ }
+ else
+ {
+ bSrcConst[1] = GL_FALSE;
+ }
+
+ if( (bSrcConst[0] == GL_TRUE) && (bSrcConst[1] == GL_TRUE) )
+ {
+ if(pILInst->SrcReg[0].Index != pILInst->SrcReg[1].Index)
+ {
+ if( GL_FALSE == mov_temp(pAsm, 1) )
+ {
+ return GL_FALSE;
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean checkop3(r700_AssemblerBase* pAsm)
+{
+ GLboolean bSrcConst[3];
+ struct prog_instruction *pILInst = &(pAsm->pILInst[pAsm->uiCurInst]);
+
+ checkop_init(pAsm);
+
+ if( (pILInst->SrcReg[0].File == PROGRAM_CONSTANT) ||
+ (pILInst->SrcReg[0].File == PROGRAM_LOCAL_PARAM) ||
+ (pILInst->SrcReg[0].File == PROGRAM_ENV_PARAM) ||
+ (pILInst->SrcReg[0].File == PROGRAM_STATE_VAR) )
+ {
+ bSrcConst[0] = GL_TRUE;
+ }
+ else
+ {
+ bSrcConst[0] = GL_FALSE;
+ }
+ if( (pILInst->SrcReg[1].File == PROGRAM_CONSTANT) ||
+ (pILInst->SrcReg[1].File == PROGRAM_LOCAL_PARAM) ||
+ (pILInst->SrcReg[1].File == PROGRAM_ENV_PARAM) ||
+ (pILInst->SrcReg[1].File == PROGRAM_STATE_VAR) )
+ {
+ bSrcConst[1] = GL_TRUE;
+ }
+ else
+ {
+ bSrcConst[1] = GL_FALSE;
+ }
+ if( (pILInst->SrcReg[2].File == PROGRAM_CONSTANT) ||
+ (pILInst->SrcReg[2].File == PROGRAM_LOCAL_PARAM) ||
+ (pILInst->SrcReg[2].File == PROGRAM_ENV_PARAM) ||
+ (pILInst->SrcReg[2].File == PROGRAM_STATE_VAR) )
+ {
+ bSrcConst[2] = GL_TRUE;
+ }
+ else
+ {
+ bSrcConst[2] = GL_FALSE;
+ }
+
+ if( (GL_TRUE == bSrcConst[0]) &&
+ (GL_TRUE == bSrcConst[1]) &&
+ (GL_TRUE == bSrcConst[2]) )
+ {
+ if( GL_FALSE == mov_temp(pAsm, 1) )
+ {
+ return GL_FALSE;
+ }
+ if( GL_FALSE == mov_temp(pAsm, 2) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+ }
+ else if( (GL_TRUE == bSrcConst[0]) &&
+ (GL_TRUE == bSrcConst[1]) )
+ {
+ if(pILInst->SrcReg[0].Index != pILInst->SrcReg[1].Index)
+ {
+ if( GL_FALSE == mov_temp(pAsm, 1) )
+ {
+ return 1;
+ }
+ }
+
+ return GL_TRUE;
+ }
+ else if ( (GL_TRUE == bSrcConst[0]) &&
+ (GL_TRUE == bSrcConst[2]) )
+ {
+ if(pILInst->SrcReg[0].Index != pILInst->SrcReg[2].Index)
+ {
+ if( GL_FALSE == mov_temp(pAsm, 2) )
+ {
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+ }
+ else if( (GL_TRUE == bSrcConst[1]) &&
+ (GL_TRUE == bSrcConst[2]) )
+ {
+ if(pILInst->SrcReg[1].Index != pILInst->SrcReg[2].Index)
+ {
+ if( GL_FALSE == mov_temp(pAsm, 2) )
+ {
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_src(r700_AssemblerBase *pAsm,
+ int src,
+ int fld)
+{
+ struct prog_instruction *pILInst = &(pAsm->pILInst[pAsm->uiCurInst]);
+
+ if (fld == -1)
+ {
+ fld = src;
+ }
+
+ if(pAsm->aArgSubst[1+src] >= 0)
+ {
+ setaddrmode_PVSSRC(&(pAsm->S[fld].src), ADDR_ABSOLUTE);
+ pAsm->S[fld].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[fld].src.reg = pAsm->aArgSubst[1+src];
+ }
+ else
+ {
+ switch (pILInst->SrcReg[src].File)
+ {
+ case PROGRAM_TEMPORARY:
+ setaddrmode_PVSSRC(&(pAsm->S[fld].src), ADDR_ABSOLUTE);
+ pAsm->S[fld].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[fld].src.reg = pILInst->SrcReg[src].Index + pAsm->starting_temp_register_number;
+ break;
+ case PROGRAM_CONSTANT:
+ case PROGRAM_LOCAL_PARAM:
+ case PROGRAM_ENV_PARAM:
+ case PROGRAM_STATE_VAR:
+ if (1 == pILInst->SrcReg[src].RelAddr)
+ {
+ setaddrmode_PVSSRC(&(pAsm->S[fld].src), ADDR_RELATIVE_A0);
+ }
+ else
+ {
+ setaddrmode_PVSSRC(&(pAsm->S[fld].src), ADDR_ABSOLUTE);
+ }
+
+ pAsm->S[fld].src.rtype = SRC_REG_CONSTANT;
+ pAsm->S[fld].src.reg = pILInst->SrcReg[src].Index;
+ break;
+ case PROGRAM_INPUT:
+ setaddrmode_PVSSRC(&(pAsm->S[fld].src), ADDR_ABSOLUTE);
+ pAsm->S[fld].src.rtype = SRC_REG_INPUT;
+ switch (pAsm->currentShaderType)
+ {
+ case SPT_FP:
+ pAsm->S[fld].src.reg = pAsm->uiFP_AttributeMap[pILInst->SrcReg[src].Index];
+ break;
+ case SPT_VP:
+ pAsm->S[fld].src.reg = pAsm->ucVP_AttributeMap[pILInst->SrcReg[src].Index];
+ break;
+ }
+ break;
+ default:
+ radeon_error("Invalid source argument type\n");
+ return GL_FALSE;
+ }
+ }
+
+ pAsm->S[fld].src.swizzlex = pILInst->SrcReg[src].Swizzle & 0x7;
+ pAsm->S[fld].src.swizzley = (pILInst->SrcReg[src].Swizzle >> 3) & 0x7;
+ pAsm->S[fld].src.swizzlez = (pILInst->SrcReg[src].Swizzle >> 6) & 0x7;
+ pAsm->S[fld].src.swizzlew = (pILInst->SrcReg[src].Swizzle >> 9) & 0x7;
+
+ pAsm->S[fld].src.negx = pILInst->SrcReg[src].Negate & 0x1;
+ pAsm->S[fld].src.negy = (pILInst->SrcReg[src].Negate >> 1) & 0x1;
+ pAsm->S[fld].src.negz = (pILInst->SrcReg[src].Negate >> 2) & 0x1;
+ pAsm->S[fld].src.negw = (pILInst->SrcReg[src].Negate >> 3) & 0x1;
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_dst(r700_AssemblerBase *pAsm)
+{
+ struct prog_instruction *pILInst = &(pAsm->pILInst[pAsm->uiCurInst]);
+ switch (pILInst->DstReg.File)
+ {
+ case PROGRAM_TEMPORARY:
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = pILInst->DstReg.Index + pAsm->starting_temp_register_number;
+ break;
+ case PROGRAM_ADDRESS:
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_A0;
+ pAsm->D.dst.reg = 0;
+ break;
+ case PROGRAM_OUTPUT:
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_OUT;
+ switch (pAsm->currentShaderType)
+ {
+ case SPT_FP:
+ pAsm->D.dst.reg = pAsm->uiFP_OutputMap[pILInst->DstReg.Index];
+ break;
+ case SPT_VP:
+ pAsm->D.dst.reg = pAsm->ucVP_OutputMap[pILInst->DstReg.Index];
+ break;
+ }
+ break;
+ default:
+ radeon_error("Invalid destination output argument type\n");
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.writex = pILInst->DstReg.WriteMask & 0x1;
+ pAsm->D.dst.writey = (pILInst->DstReg.WriteMask >> 1) & 0x1;
+ pAsm->D.dst.writez = (pILInst->DstReg.WriteMask >> 2) & 0x1;
+ pAsm->D.dst.writew = (pILInst->DstReg.WriteMask >> 3) & 0x1;
+
+ return GL_TRUE;
+}
+
+GLboolean tex_dst(r700_AssemblerBase *pAsm)
+{
+ struct prog_instruction *pILInst = &(pAsm->pILInst[pAsm->uiCurInst]);
+
+ if(PROGRAM_TEMPORARY == pILInst->DstReg.File)
+ {
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = pAsm->pILInst[pAsm->uiCurInst].DstReg.Index + pAsm->starting_temp_register_number;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ }
+ else if(PROGRAM_OUTPUT == pILInst->DstReg.File)
+ {
+ pAsm->D.dst.rtype = DST_REG_OUT;
+ switch (pAsm->currentShaderType)
+ {
+ case SPT_FP:
+ pAsm->D.dst.reg = pAsm->uiFP_OutputMap[pILInst->DstReg.Index];
+ break;
+ case SPT_VP:
+ pAsm->D.dst.reg = pAsm->ucVP_OutputMap[pILInst->DstReg.Index];
+ break;
+ }
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ }
+ else
+ {
+ radeon_error("Invalid destination output argument type\n");
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.writex = pILInst->DstReg.WriteMask & 0x1;
+ pAsm->D.dst.writey = (pILInst->DstReg.WriteMask >> 1) & 0x1;
+ pAsm->D.dst.writez = (pILInst->DstReg.WriteMask >> 2) & 0x1;
+ pAsm->D.dst.writew = (pILInst->DstReg.WriteMask >> 3) & 0x1;
+
+ return GL_TRUE;
+}
+
+GLboolean tex_src(r700_AssemblerBase *pAsm)
+{
+ struct prog_instruction *pILInst = &(pAsm->pILInst[pAsm->uiCurInst]);
+
+ GLboolean bValidTexCoord = GL_FALSE;
+
+ switch (pILInst->SrcReg[0].File) {
+ case PROGRAM_CONSTANT:
+ case PROGRAM_LOCAL_PARAM:
+ case PROGRAM_ENV_PARAM:
+ case PROGRAM_STATE_VAR:
+ bValidTexCoord = GL_TRUE;
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = pAsm->aArgSubst[1];
+ break;
+ case PROGRAM_TEMPORARY:
+ bValidTexCoord = GL_TRUE;
+ pAsm->S[0].src.reg = pILInst->SrcReg[0].Index +
+ pAsm->starting_temp_register_number;
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ break;
+ case PROGRAM_INPUT:
+ switch (pILInst->SrcReg[0].Index)
+ {
+ case FRAG_ATTRIB_COL0:
+ case FRAG_ATTRIB_COL1:
+ case FRAG_ATTRIB_TEX0:
+ case FRAG_ATTRIB_TEX1:
+ case FRAG_ATTRIB_TEX2:
+ case FRAG_ATTRIB_TEX3:
+ case FRAG_ATTRIB_TEX4:
+ case FRAG_ATTRIB_TEX5:
+ case FRAG_ATTRIB_TEX6:
+ case FRAG_ATTRIB_TEX7:
+ bValidTexCoord = GL_TRUE;
+ pAsm->S[0].src.reg =
+ pAsm->uiFP_AttributeMap[pILInst->SrcReg[0].Index];
+ pAsm->S[0].src.rtype = SRC_REG_INPUT;
+ break;
+ }
+ break;
+ }
+
+ if(GL_TRUE == bValidTexCoord)
+ {
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ }
+ else
+ {
+ radeon_error("Invalid source texcoord for TEX instruction\n");
+ return GL_FALSE;
+ }
+
+ pAsm->S[0].src.swizzlex = pILInst->SrcReg[0].Swizzle & 0x7;
+ pAsm->S[0].src.swizzley = (pILInst->SrcReg[0].Swizzle >> 3) & 0x7;
+ pAsm->S[0].src.swizzlez = (pILInst->SrcReg[0].Swizzle >> 6) & 0x7;
+ pAsm->S[0].src.swizzlew = (pILInst->SrcReg[0].Swizzle >> 9) & 0x7;
+
+ pAsm->S[0].src.negx = pILInst->SrcReg[0].Negate & 0x1;
+ pAsm->S[0].src.negy = (pILInst->SrcReg[0].Negate >> 1) & 0x1;
+ pAsm->S[0].src.negz = (pILInst->SrcReg[0].Negate >> 2) & 0x1;
+ pAsm->S[0].src.negw = (pILInst->SrcReg[0].Negate >> 3) & 0x1;
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm, GLboolean normalized)
+{
+ PVSSRC * texture_coordinate_source;
+ PVSSRC * texture_unit_source;
+
+ R700TextureInstruction* tex_instruction_ptr = (R700TextureInstruction*) CALLOC_STRUCT(R700TextureInstruction);
+ if (tex_instruction_ptr == NULL)
+ {
+ return GL_FALSE;
+ }
+ Init_R700TextureInstruction(tex_instruction_ptr);
+
+ texture_coordinate_source = &(pAsm->S[0].src);
+ texture_unit_source = &(pAsm->S[1].src);
+
+ tex_instruction_ptr->m_Word0.f.tex_inst = pAsm->D.dst.opcode;
+ tex_instruction_ptr->m_Word0.f.bc_frac_mode = 0x0;
+ tex_instruction_ptr->m_Word0.f.fetch_whole_quad = 0x0;
+
+ tex_instruction_ptr->m_Word0.f.resource_id = texture_unit_source->reg;
+
+ tex_instruction_ptr->m_Word1.f.lod_bias = 0x0;
+ if (normalized) {
+ tex_instruction_ptr->m_Word1.f.coord_type_x = SQ_TEX_NORMALIZED;
+ tex_instruction_ptr->m_Word1.f.coord_type_y = SQ_TEX_NORMALIZED;
+ tex_instruction_ptr->m_Word1.f.coord_type_z = SQ_TEX_NORMALIZED;
+ tex_instruction_ptr->m_Word1.f.coord_type_w = SQ_TEX_NORMALIZED;
+ } else {
+ /* XXX: UNNORMALIZED tex coords have limited wrap modes */
+ tex_instruction_ptr->m_Word1.f.coord_type_x = SQ_TEX_UNNORMALIZED;
+ tex_instruction_ptr->m_Word1.f.coord_type_y = SQ_TEX_UNNORMALIZED;
+ tex_instruction_ptr->m_Word1.f.coord_type_z = SQ_TEX_UNNORMALIZED;
+ tex_instruction_ptr->m_Word1.f.coord_type_w = SQ_TEX_UNNORMALIZED;
+ }
+
+ tex_instruction_ptr->m_Word2.f.offset_x = 0x0;
+ tex_instruction_ptr->m_Word2.f.offset_y = 0x0;
+ tex_instruction_ptr->m_Word2.f.offset_z = 0x0;
+
+ tex_instruction_ptr->m_Word2.f.sampler_id = texture_unit_source->reg;
+
+ // dst
+ if ( (pAsm->D.dst.rtype == DST_REG_TEMPORARY) ||
+ (pAsm->D.dst.rtype == DST_REG_OUT) )
+ {
+ tex_instruction_ptr->m_Word0.f.src_gpr = texture_coordinate_source->reg;
+ tex_instruction_ptr->m_Word0.f.src_rel = SQ_ABSOLUTE;
+
+ tex_instruction_ptr->m_Word1.f.dst_gpr = pAsm->D.dst.reg;
+ tex_instruction_ptr->m_Word1.f.dst_rel = SQ_ABSOLUTE;
+
+ tex_instruction_ptr->m_Word1.f.dst_sel_x = (pAsm->D.dst.writex ? texture_unit_source->swizzlex : SQ_SEL_MASK);
+ tex_instruction_ptr->m_Word1.f.dst_sel_y = (pAsm->D.dst.writey ? texture_unit_source->swizzley : SQ_SEL_MASK);
+ tex_instruction_ptr->m_Word1.f.dst_sel_z = (pAsm->D.dst.writez ? texture_unit_source->swizzlez : SQ_SEL_MASK);
+ tex_instruction_ptr->m_Word1.f.dst_sel_w = (pAsm->D.dst.writew ? texture_unit_source->swizzlew : SQ_SEL_MASK);
+
+
+ tex_instruction_ptr->m_Word2.f.src_sel_x = texture_coordinate_source->swizzlex;
+ tex_instruction_ptr->m_Word2.f.src_sel_y = texture_coordinate_source->swizzley;
+ tex_instruction_ptr->m_Word2.f.src_sel_z = texture_coordinate_source->swizzlez;
+ tex_instruction_ptr->m_Word2.f.src_sel_w = texture_coordinate_source->swizzlew;
+ }
+ else
+ {
+ radeon_error("Only temp destination registers supported for TEX dest regs.\n");
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == add_tex_instruction(pAsm, tex_instruction_ptr) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+void initialize(r700_AssemblerBase *pAsm)
+{
+ GLuint cycle, component;
+
+ for (cycle=0; cycle<NUMBER_OF_CYCLES; cycle++)
+ {
+ for (component=0; component<NUMBER_OF_COMPONENTS; component++)
+ {
+ pAsm->hw_gpr[cycle][component] = (-1);
+ }
+ }
+ for (component=0; component<NUMBER_OF_COMPONENTS; component++)
+ {
+ pAsm->hw_cfile_addr[component] = (-1);
+ pAsm->hw_cfile_chan[component] = (-1);
+ }
+}
+
+GLboolean assemble_alu_src(R700ALUInstruction* alu_instruction_ptr,
+ int source_index,
+ PVSSRC* pSource,
+ BITS scalar_channel_index)
+{
+ BITS src_sel;
+ BITS src_rel;
+ BITS src_chan;
+ BITS src_neg;
+
+ //--------------------------------------------------------------------------
+ // Source for operands src0, src1.
+ // Values [0,127] correspond to GPR[0..127].
+ // Values [256,511] correspond to cfile constants c[0..255].
+
+ //--------------------------------------------------------------------------
+ // Other special values are shown in the list below.
+
+ // 248 SQ_ALU_SRC_0: special constant 0.0.
+ // 249 SQ_ALU_SRC_1: special constant 1.0 float.
+
+ // 250 SQ_ALU_SRC_1_INT: special constant 1 integer.
+ // 251 SQ_ALU_SRC_M_1_INT: special constant -1 integer.
+
+ // 252 SQ_ALU_SRC_0_5: special constant 0.5 float.
+ // 253 SQ_ALU_SRC_LITERAL: literal constant.
+
+ // 254 SQ_ALU_SRC_PV: previous vector result.
+ // 255 SQ_ALU_SRC_PS: previous scalar result.
+ //--------------------------------------------------------------------------
+
+ BITS channel_swizzle;
+ switch (scalar_channel_index)
+ {
+ case 0: channel_swizzle = pSource->swizzlex; break;
+ case 1: channel_swizzle = pSource->swizzley; break;
+ case 2: channel_swizzle = pSource->swizzlez; break;
+ case 3: channel_swizzle = pSource->swizzlew; break;
+ default: channel_swizzle = SQ_SEL_MASK; break;
+ }
+
+ if(channel_swizzle == SQ_SEL_0)
+ {
+ src_sel = SQ_ALU_SRC_0;
+ }
+ else if (channel_swizzle == SQ_SEL_1)
+ {
+ src_sel = SQ_ALU_SRC_1;
+ }
+ else
+ {
+ if ( (pSource->rtype == SRC_REG_TEMPORARY) ||
+ (pSource->rtype == SRC_REG_INPUT)
+ )
+ {
+ src_sel = pSource->reg;
+ }
+ else if (pSource->rtype == SRC_REG_CONSTANT)
+ {
+ src_sel = pSource->reg + CFILE_REGISTER_OFFSET;
+ }
+ else
+ {
+ radeon_error("Source (%d) register type (%d) not one of TEMP, INPUT, or CONSTANT.\n",
+ source_index, pSource->rtype);
+ return GL_FALSE;
+ }
+ }
+
+ if( ADDR_ABSOLUTE == addrmode_PVSSRC(pSource) )
+ {
+ src_rel = SQ_ABSOLUTE;
+ }
+ else
+ {
+ src_rel = SQ_RELATIVE;
+ }
+
+ switch (channel_swizzle)
+ {
+ case SQ_SEL_X:
+ src_chan = SQ_CHAN_X;
+ break;
+ case SQ_SEL_Y:
+ src_chan = SQ_CHAN_Y;
+ break;
+ case SQ_SEL_Z:
+ src_chan = SQ_CHAN_Z;
+ break;
+ case SQ_SEL_W:
+ src_chan = SQ_CHAN_W;
+ break;
+ case SQ_SEL_0:
+ case SQ_SEL_1:
+ // Does not matter since src_sel controls
+ src_chan = SQ_CHAN_X;
+ break;
+ default:
+ radeon_error("Unknown source select value (%d) in assemble_alu_src().\n", channel_swizzle);
+ return GL_FALSE;
+ break;
+ }
+
+ switch (scalar_channel_index)
+ {
+ case 0: src_neg = pSource->negx; break;
+ case 1: src_neg = pSource->negy; break;
+ case 2: src_neg = pSource->negz; break;
+ case 3: src_neg = pSource->negw; break;
+ default: src_neg = 0; break;
+ }
+
+ switch (source_index)
+ {
+ case 0:
+ alu_instruction_ptr->m_Word0.f.src0_sel = src_sel;
+ alu_instruction_ptr->m_Word0.f.src0_rel = src_rel;
+ alu_instruction_ptr->m_Word0.f.src0_chan = src_chan;
+ alu_instruction_ptr->m_Word0.f.src0_neg = src_neg;
+ break;
+ case 1:
+ alu_instruction_ptr->m_Word0.f.src1_sel = src_sel;
+ alu_instruction_ptr->m_Word0.f.src1_rel = src_rel;
+ alu_instruction_ptr->m_Word0.f.src1_chan = src_chan;
+ alu_instruction_ptr->m_Word0.f.src1_neg = src_neg;
+ break;
+ case 2:
+ alu_instruction_ptr->m_Word1_OP3.f.src2_sel = src_sel;
+ alu_instruction_ptr->m_Word1_OP3.f.src2_rel = src_rel;
+ alu_instruction_ptr->m_Word1_OP3.f.src2_chan = src_chan;
+ alu_instruction_ptr->m_Word1_OP3.f.src2_neg = src_neg;
+ break;
+ default:
+ radeon_error("Only three sources allowed in ALU opcodes.\n");
+ return GL_FALSE;
+ break;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean add_alu_instruction(r700_AssemblerBase* pAsm,
+ R700ALUInstruction* alu_instruction_ptr,
+ GLuint contiguous_slots_needed)
+{
+ if( GL_FALSE == check_current_clause(pAsm, CF_ALU_CLAUSE) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( pAsm->cf_current_alu_clause_ptr == NULL ||
+ ( (pAsm->cf_current_alu_clause_ptr != NULL) &&
+ (pAsm->cf_current_alu_clause_ptr->m_Word1.f.count >= (GetCFMaxInstructions(pAsm->cf_current_alu_clause_ptr->m_ShaderInstType)-contiguous_slots_needed-1) )
+ ) )
+ {
+
+ //new cf inst for this clause
+ pAsm->cf_current_alu_clause_ptr = (R700ControlFlowALUClause*) CALLOC_STRUCT(R700ControlFlowALUClause);
+
+ // link the new cf to cf segment
+ if(NULL != pAsm->cf_current_alu_clause_ptr)
+ {
+ Init_R700ControlFlowALUClause(pAsm->cf_current_alu_clause_ptr);
+ AddCFInstruction( pAsm->pR700Shader,
+ (R700ControlFlowInstruction *)pAsm->cf_current_alu_clause_ptr );
+ }
+ else
+ {
+ radeon_error("Could not allocate a new ALU CF instruction.\n");
+ return GL_FALSE;
+ }
+
+ pAsm->cf_current_alu_clause_ptr->m_Word0.f.kcache_bank0 = 0x0;
+ pAsm->cf_current_alu_clause_ptr->m_Word0.f.kcache_bank1 = 0x0;
+ pAsm->cf_current_alu_clause_ptr->m_Word0.f.kcache_mode0 = SQ_CF_KCACHE_NOP;
+
+ pAsm->cf_current_alu_clause_ptr->m_Word1.f.kcache_mode1 = SQ_CF_KCACHE_NOP;
+ pAsm->cf_current_alu_clause_ptr->m_Word1.f.kcache_addr0 = 0x0;
+ pAsm->cf_current_alu_clause_ptr->m_Word1.f.kcache_addr1 = 0x0;
+
+ //cf_current_alu_clause_ptr->m_Word1.f.count = number_of_scalar_operations - 1;
+ pAsm->cf_current_alu_clause_ptr->m_Word1.f.count = 0x0;
+ pAsm->cf_current_alu_clause_ptr->m_Word1.f.cf_inst = SQ_CF_INST_ALU;
+
+ pAsm->cf_current_alu_clause_ptr->m_Word1.f.whole_quad_mode = 0x0;
+
+ pAsm->cf_current_alu_clause_ptr->m_Word1.f.barrier = 0x1;
+ }
+ else
+ {
+ pAsm->cf_current_alu_clause_ptr->m_Word1.f.count++;
+ }
+
+ // If this clause constains any instruction that is forward dependent on a TEX instruction,
+ // set the whole_quad_mode for this clause
+ if ( pAsm->pInstDeps[pAsm->uiCurInst].nDstDep > (-1) )
+ {
+ pAsm->cf_current_alu_clause_ptr->m_Word1.f.whole_quad_mode = 0x1;
+ }
+
+ if (pAsm->cf_current_alu_clause_ptr->m_Word1.f.count >= (GetCFMaxInstructions(pAsm->cf_current_alu_clause_ptr->m_ShaderInstType)-1) )
+ {
+ alu_instruction_ptr->m_Word0.f.last = 1;
+ }
+
+ if(NULL == pAsm->cf_current_alu_clause_ptr->m_pLinkedALUInstruction)
+ {
+ pAsm->cf_current_alu_clause_ptr->m_pLinkedALUInstruction = alu_instruction_ptr;
+ alu_instruction_ptr->m_pLinkedALUClause = pAsm->cf_current_alu_clause_ptr;
+ }
+
+ AddALUInstruction(pAsm->pR700Shader, alu_instruction_ptr);
+
+ return GL_TRUE;
+}
+
+void get_src_properties(R700ALUInstruction* alu_instruction_ptr,
+ int source_index,
+ BITS* psrc_sel,
+ BITS* psrc_rel,
+ BITS* psrc_chan,
+ BITS* psrc_neg)
+{
+ switch (source_index)
+ {
+ case 0:
+ *psrc_sel = alu_instruction_ptr->m_Word0.f.src0_sel ;
+ *psrc_rel = alu_instruction_ptr->m_Word0.f.src0_rel ;
+ *psrc_chan = alu_instruction_ptr->m_Word0.f.src0_chan;
+ *psrc_neg = alu_instruction_ptr->m_Word0.f.src0_neg ;
+ break;
+
+ case 1:
+ *psrc_sel = alu_instruction_ptr->m_Word0.f.src1_sel ;
+ *psrc_rel = alu_instruction_ptr->m_Word0.f.src1_rel ;
+ *psrc_chan = alu_instruction_ptr->m_Word0.f.src1_chan;
+ *psrc_neg = alu_instruction_ptr->m_Word0.f.src1_neg ;
+ break;
+
+ case 2:
+ *psrc_sel = alu_instruction_ptr->m_Word1_OP3.f.src2_sel;
+ *psrc_rel = alu_instruction_ptr->m_Word1_OP3.f.src2_rel;
+ *psrc_chan = alu_instruction_ptr->m_Word1_OP3.f.src2_chan;
+ *psrc_neg = alu_instruction_ptr->m_Word1_OP3.f.src2_neg;
+ break;
+ }
+}
+
+int is_cfile(BITS sel)
+{
+ if (sel > 255 && sel < 512)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+int is_const(BITS sel)
+{
+ if (is_cfile(sel))
+ {
+ return 1;
+ }
+ else if(sel >= SQ_ALU_SRC_0 && sel <= SQ_ALU_SRC_LITERAL)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+int is_gpr(BITS sel)
+{
+ if (sel >= 0 && sel < 128)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+const GLuint BANK_SWIZZLE_VEC[8] = {SQ_ALU_VEC_210, //000
+ SQ_ALU_VEC_120, //001
+ SQ_ALU_VEC_102, //010
+
+ SQ_ALU_VEC_201, //011
+ SQ_ALU_VEC_012, //100
+ SQ_ALU_VEC_021, //101
+
+ SQ_ALU_VEC_012, //110
+ SQ_ALU_VEC_012}; //111
+
+const GLuint BANK_SWIZZLE_SCL[8] = {SQ_ALU_SCL_210, //000
+ SQ_ALU_SCL_122, //001
+ SQ_ALU_SCL_122, //010
+
+ SQ_ALU_SCL_221, //011
+ SQ_ALU_SCL_212, //100
+ SQ_ALU_SCL_122, //101
+
+ SQ_ALU_SCL_122, //110
+ SQ_ALU_SCL_122}; //111
+
+GLboolean reserve_cfile(r700_AssemblerBase* pAsm,
+ GLuint sel,
+ GLuint chan)
+{
+ int res_match = (-1);
+ int res_empty = (-1);
+
+ GLint res;
+
+ for (res=3; res>=0; res--)
+ {
+ if(pAsm->hw_cfile_addr[ res] < 0)
+ {
+ res_empty = res;
+ }
+ else if( (pAsm->hw_cfile_addr[res] == (int)sel)
+ &&
+ (pAsm->hw_cfile_chan[ res ] == (int) chan) )
+ {
+ res_match = res;
+ }
+ }
+
+ if(res_match >= 0)
+ {
+ // Read for this scalar component already reserved, nothing to do here.
+ ;
+ }
+ else if(res_empty >= 0)
+ {
+ pAsm->hw_cfile_addr[ res_empty ] = sel;
+ pAsm->hw_cfile_chan[ res_empty ] = chan;
+ }
+ else
+ {
+ radeon_error("All cfile read ports are used, cannot reference C$sel, channel $chan.\n");
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+GLboolean reserve_gpr(r700_AssemblerBase* pAsm, GLuint sel, GLuint chan, GLuint cycle)
+{
+ if(pAsm->hw_gpr[cycle][chan] < 0)
+ {
+ pAsm->hw_gpr[cycle][chan] = sel;
+ }
+ else if(pAsm->hw_gpr[cycle][chan] != (int)sel)
+ {
+ radeon_error("Another scalar operation has already used GPR read port for given channel\n");
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean cycle_for_scalar_bank_swizzle(const int swiz, const int sel, GLuint* pCycle)
+{
+ switch (swiz)
+ {
+ case SQ_ALU_SCL_210:
+ {
+ int table[3] = {2, 1, 0};
+ *pCycle = table[sel];
+ return GL_TRUE;
+ }
+ break;
+ case SQ_ALU_SCL_122:
+ {
+ int table[3] = {1, 2, 2};
+ *pCycle = table[sel];
+ return GL_TRUE;
+ }
+ break;
+ case SQ_ALU_SCL_212:
+ {
+ int table[3] = {2, 1, 2};
+ *pCycle = table[sel];
+ return GL_TRUE;
+ }
+ break;
+ case SQ_ALU_SCL_221:
+ {
+ int table[3] = {2, 2, 1};
+ *pCycle = table[sel];
+ return GL_TRUE;
+ }
+ break;
+ default:
+ radeon_error("Bad Scalar bank swizzle value\n");
+ break;
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean cycle_for_vector_bank_swizzle(const int swiz, const int sel, GLuint* pCycle)
+{
+ switch (swiz)
+ {
+ case SQ_ALU_VEC_012:
+ {
+ int table[3] = {0, 1, 2};
+ *pCycle = table[sel];
+ }
+ break;
+ case SQ_ALU_VEC_021:
+ {
+ int table[3] = {0, 2, 1};
+ *pCycle = table[sel];
+ }
+ break;
+ case SQ_ALU_VEC_120:
+ {
+ int table[3] = {1, 2, 0};
+ *pCycle = table[sel];
+ }
+ break;
+ case SQ_ALU_VEC_102:
+ {
+ int table[3] = {1, 0, 2};
+ *pCycle = table[sel];
+ }
+ break;
+ case SQ_ALU_VEC_201:
+ {
+ int table[3] = {2, 0, 1};
+ *pCycle = table[sel];
+ }
+ break;
+ case SQ_ALU_VEC_210:
+ {
+ int table[3] = {2, 1, 0};
+ *pCycle = table[sel];
+ }
+ break;
+ default:
+ radeon_error("Bad Vec bank swizzle value\n");
+ return GL_FALSE;
+ break;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean check_scalar(r700_AssemblerBase* pAsm,
+ R700ALUInstruction* alu_instruction_ptr)
+{
+ GLuint cycle;
+ GLuint bank_swizzle;
+ GLuint const_count = 0;
+
+ BITS sel;
+ BITS chan;
+ BITS rel;
+ BITS neg;
+
+ GLuint src;
+
+ BITS src_sel [3] = {0,0,0};
+ BITS src_chan[3] = {0,0,0};
+ BITS src_rel [3] = {0,0,0};
+ BITS src_neg [3] = {0,0,0};
+
+ GLuint swizzle_key;
+
+ GLuint number_of_operands = r700GetNumOperands(pAsm);
+
+ for (src=0; src<number_of_operands; src++)
+ {
+ get_src_properties(alu_instruction_ptr,
+ src,
+ &(src_sel[src]),
+ &(src_rel[src]),
+ &(src_chan[src]),
+ &(src_neg[src]) );
+ }
+
+
+ swizzle_key = ( (is_const( src_sel[0] ) ? 4 : 0) +
+ (is_const( src_sel[1] ) ? 2 : 0) +
+ (is_const( src_sel[2] ) ? 1 : 0) );
+
+ alu_instruction_ptr->m_Word1.f.bank_swizzle = BANK_SWIZZLE_SCL[ swizzle_key ];
+
+ for (src=0; src<number_of_operands; src++)
+ {
+ sel = src_sel [src];
+ chan = src_chan[src];
+ rel = src_rel [src];
+ neg = src_neg [src];
+
+ if (is_const( sel ))
+ {
+ // Any constant, including literal and inline constants
+ const_count++;
+
+ if (is_cfile( sel ))
+ {
+ reserve_cfile(pAsm, sel, chan);
+ }
+
+ }
+ }
+
+ for (src=0; src<number_of_operands; src++)
+ {
+ sel = src_sel [src];
+ chan = src_chan[src];
+ rel = src_rel [src];
+ neg = src_neg [src];
+
+ if( is_gpr(sel) )
+ {
+ bank_swizzle = alu_instruction_ptr->m_Word1.f.bank_swizzle;
+
+ if( GL_FALSE == cycle_for_scalar_bank_swizzle(bank_swizzle, src, &cycle) )
+ {
+ return GL_FALSE;
+ }
+
+ if(cycle < const_count)
+ {
+ if( GL_FALSE == reserve_gpr(pAsm, sel, chan, cycle) )
+ {
+ return GL_FALSE;
+ }
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean check_vector(r700_AssemblerBase* pAsm,
+ R700ALUInstruction* alu_instruction_ptr)
+{
+ GLuint cycle;
+ GLuint bank_swizzle;
+ GLuint const_count = 0;
+
+ GLuint src;
+
+ BITS sel;
+ BITS chan;
+ BITS rel;
+ BITS neg;
+
+ BITS src_sel [3] = {0,0,0};
+ BITS src_chan[3] = {0,0,0};
+ BITS src_rel [3] = {0,0,0};
+ BITS src_neg [3] = {0,0,0};
+
+ GLuint swizzle_key;
+
+ GLuint number_of_operands = r700GetNumOperands(pAsm);
+
+ for (src=0; src<number_of_operands; src++)
+ {
+ get_src_properties(alu_instruction_ptr,
+ src,
+ &(src_sel[src]),
+ &(src_rel[src]),
+ &(src_chan[src]),
+ &(src_neg[src]) );
+ }
+
+
+ swizzle_key = ( (is_const( src_sel[0] ) ? 4 : 0) +
+ (is_const( src_sel[1] ) ? 2 : 0) +
+ (is_const( src_sel[2] ) ? 1 : 0)
+ );
+
+ alu_instruction_ptr->m_Word1.f.bank_swizzle = BANK_SWIZZLE_VEC[swizzle_key];
+
+ for (src=0; src<number_of_operands; src++)
+ {
+ sel = src_sel [src];
+ chan = src_chan[src];
+ rel = src_rel [src];
+ neg = src_neg [src];
+
+
+ bank_swizzle = alu_instruction_ptr->m_Word1.f.bank_swizzle;
+
+ if( is_gpr(sel) )
+ {
+ if( GL_FALSE == cycle_for_vector_bank_swizzle(bank_swizzle, src, &cycle) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( (src == 1) &&
+ (sel == src_sel[0]) &&
+ (chan == src_chan[0]) )
+ {
+ }
+ else
+ {
+ if( GL_FALSE == reserve_gpr(pAsm, sel, chan, cycle) )
+ {
+ return GL_FALSE;
+ }
+ }
+ }
+ else if( is_const(sel) )
+ {
+ const_count++;
+
+ if( is_cfile(sel) )
+ {
+ if( GL_FALSE == reserve_cfile(pAsm, sel, chan) )
+ {
+ return GL_FALSE;
+ }
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_alu_instruction(r700_AssemblerBase *pAsm)
+{
+ GLuint number_of_scalar_operations;
+ GLboolean is_single_scalar_operation;
+ GLuint scalar_channel_index;
+
+ PVSSRC * pcurrent_source;
+ int current_source_index;
+ GLuint contiguous_slots_needed;
+
+ GLuint uNumSrc = r700GetNumOperands(pAsm);
+ GLuint channel_swizzle, j;
+ GLuint chan_counter[4] = {0, 0, 0, 0};
+ PVSSRC * pSource[3];
+ GLboolean bSplitInst = GL_FALSE;
+
+ if (1 == pAsm->D.dst.math)
+ {
+ is_single_scalar_operation = GL_TRUE;
+ number_of_scalar_operations = 1;
+ }
+ else
+ {
+ is_single_scalar_operation = GL_FALSE;
+ number_of_scalar_operations = 4;
+
+ /* check read port, only very preliminary algorithm, not count in
+ src0/1 same comp case and prev slot repeat case; also not count relative
+ addressing. TODO: improve performance. */
+ for(j=0; j<uNumSrc; j++)
+ {
+ pSource[j] = &(pAsm->S[j].src);
+ }
+ for(scalar_channel_index=0; scalar_channel_index<4; scalar_channel_index++)
+ {
+ for(j=0; j<uNumSrc; j++)
+ {
+ switch (scalar_channel_index)
+ {
+ case 0: channel_swizzle = pSource[j]->swizzlex; break;
+ case 1: channel_swizzle = pSource[j]->swizzley; break;
+ case 2: channel_swizzle = pSource[j]->swizzlez; break;
+ case 3: channel_swizzle = pSource[j]->swizzlew; break;
+ default: channel_swizzle = SQ_SEL_MASK; break;
+ }
+ if ( ((pSource[j]->rtype == SRC_REG_TEMPORARY) ||
+ (pSource[j]->rtype == SRC_REG_INPUT))
+ && (channel_swizzle <= SQ_SEL_W) )
+ {
+ chan_counter[channel_swizzle]++;
+ }
+ }
+ }
+ if( (chan_counter[SQ_SEL_X] > 3)
+ || (chan_counter[SQ_SEL_Y] > 3)
+ || (chan_counter[SQ_SEL_Z] > 3)
+ || (chan_counter[SQ_SEL_W] > 3) ) /* each chan bank has only 3 ports. */
+ {
+ bSplitInst = GL_TRUE;
+ }
+ }
+
+ contiguous_slots_needed = 0;
+
+ if(GL_TRUE == is_reduction_opcode(&(pAsm->D)) )
+ {
+ contiguous_slots_needed = 4;
+ }
+
+ initialize(pAsm);
+
+ for (scalar_channel_index=0;
+ scalar_channel_index < number_of_scalar_operations;
+ scalar_channel_index++)
+ {
+ R700ALUInstruction* alu_instruction_ptr = (R700ALUInstruction*) CALLOC_STRUCT(R700ALUInstruction);
+ if (alu_instruction_ptr == NULL)
+ {
+ return GL_FALSE;
+ }
+ Init_R700ALUInstruction(alu_instruction_ptr);
+
+ //src 0
+ current_source_index = 0;
+ pcurrent_source = &(pAsm->S[0].src);
+
+ if (GL_FALSE == assemble_alu_src(alu_instruction_ptr,
+ current_source_index,
+ pcurrent_source,
+ scalar_channel_index) )
+ {
+ return GL_FALSE;
+ }
+
+ if (pAsm->D.dst.math == 0)
+ {
+ // Process source 1
+ current_source_index = 1;
+ pcurrent_source = &(pAsm->S[current_source_index].src);
+
+ if (GL_FALSE == assemble_alu_src(alu_instruction_ptr,
+ current_source_index,
+ pcurrent_source,
+ scalar_channel_index) )
+ {
+ return GL_FALSE;
+ }
+ }
+
+ //other bits
+ alu_instruction_ptr->m_Word0.f.index_mode = SQ_INDEX_LOOP;
+
+ if( (is_single_scalar_operation == GL_TRUE)
+ || (GL_TRUE == bSplitInst) )
+ {
+ alu_instruction_ptr->m_Word0.f.last = 1;
+ }
+ else
+ {
+ alu_instruction_ptr->m_Word0.f.last = (scalar_channel_index == 3) ? 1 : 0;
+ }
+
+ alu_instruction_ptr->m_Word0.f.pred_sel = 0x0;
+ alu_instruction_ptr->m_Word1_OP2.f.update_pred = 0x0;
+ alu_instruction_ptr->m_Word1_OP2.f.update_execute_mask = 0x0;
+
+ // dst
+ if( (pAsm->D.dst.rtype == DST_REG_TEMPORARY) ||
+ (pAsm->D.dst.rtype == DST_REG_OUT) )
+ {
+ alu_instruction_ptr->m_Word1.f.dst_gpr = pAsm->D.dst.reg;
+ }
+ else
+ {
+ radeon_error("Only temp destination registers supported for ALU dest regs.\n");
+ return GL_FALSE;
+ }
+
+ alu_instruction_ptr->m_Word1.f.dst_rel = SQ_ABSOLUTE; //D.rtype
+
+ if ( is_single_scalar_operation == GL_TRUE )
+ {
+ // Override scalar_channel_index since only one scalar value will be written
+ if(pAsm->D.dst.writex)
+ {
+ scalar_channel_index = 0;
+ }
+ else if(pAsm->D.dst.writey)
+ {
+ scalar_channel_index = 1;
+ }
+ else if(pAsm->D.dst.writez)
+ {
+ scalar_channel_index = 2;
+ }
+ else if(pAsm->D.dst.writew)
+ {
+ scalar_channel_index = 3;
+ }
+ }
+
+ alu_instruction_ptr->m_Word1.f.dst_chan = scalar_channel_index;
+
+ alu_instruction_ptr->m_Word1.f.clamp = pAsm->pILInst[pAsm->uiCurInst].SaturateMode;
+
+ if (pAsm->D.dst.op3)
+ {
+ //op3
+
+ alu_instruction_ptr->m_Word1_OP3.f.alu_inst = pAsm->D.dst.opcode;
+
+ //There's 3rd src for op3
+ current_source_index = 2;
+ pcurrent_source = &(pAsm->S[current_source_index].src);
+
+ if ( GL_FALSE == assemble_alu_src(alu_instruction_ptr,
+ current_source_index,
+ pcurrent_source,
+ scalar_channel_index) )
+ {
+ return GL_FALSE;
+ }
+ }
+ else
+ {
+ //op2
+ if (pAsm->bR6xx)
+ {
+ alu_instruction_ptr->m_Word1_OP2.f6.alu_inst = pAsm->D.dst.opcode;
+
+ alu_instruction_ptr->m_Word1_OP2.f6.src0_abs = 0x0;
+ alu_instruction_ptr->m_Word1_OP2.f6.src1_abs = 0x0;
+
+ //alu_instruction_ptr->m_Word1_OP2.f6.update_execute_mask = 0x0;
+ //alu_instruction_ptr->m_Word1_OP2.f6.update_pred = 0x0;
+ switch (scalar_channel_index)
+ {
+ case 0:
+ alu_instruction_ptr->m_Word1_OP2.f6.write_mask = pAsm->D.dst.writex;
+ break;
+ case 1:
+ alu_instruction_ptr->m_Word1_OP2.f6.write_mask = pAsm->D.dst.writey;
+ break;
+ case 2:
+ alu_instruction_ptr->m_Word1_OP2.f6.write_mask = pAsm->D.dst.writez;
+ break;
+ case 3:
+ alu_instruction_ptr->m_Word1_OP2.f6.write_mask = pAsm->D.dst.writew;
+ break;
+ default:
+ alu_instruction_ptr->m_Word1_OP2.f6.write_mask = 1; //SQ_SEL_MASK;
+ break;
+ }
+ alu_instruction_ptr->m_Word1_OP2.f6.omod = SQ_ALU_OMOD_OFF;
+ }
+ else
+ {
+ alu_instruction_ptr->m_Word1_OP2.f.alu_inst = pAsm->D.dst.opcode;
+
+ alu_instruction_ptr->m_Word1_OP2.f.src0_abs = 0x0;
+ alu_instruction_ptr->m_Word1_OP2.f.src1_abs = 0x0;
+
+ //alu_instruction_ptr->m_Word1_OP2.f.update_execute_mask = 0x0;
+ //alu_instruction_ptr->m_Word1_OP2.f.update_pred = 0x0;
+ switch (scalar_channel_index)
+ {
+ case 0:
+ alu_instruction_ptr->m_Word1_OP2.f.write_mask = pAsm->D.dst.writex;
+ break;
+ case 1:
+ alu_instruction_ptr->m_Word1_OP2.f.write_mask = pAsm->D.dst.writey;
+ break;
+ case 2:
+ alu_instruction_ptr->m_Word1_OP2.f.write_mask = pAsm->D.dst.writez;
+ break;
+ case 3:
+ alu_instruction_ptr->m_Word1_OP2.f.write_mask = pAsm->D.dst.writew;
+ break;
+ default:
+ alu_instruction_ptr->m_Word1_OP2.f.write_mask = 1; //SQ_SEL_MASK;
+ break;
+ }
+ alu_instruction_ptr->m_Word1_OP2.f.omod = SQ_ALU_OMOD_OFF;
+ }
+ }
+
+ if(GL_FALSE == add_alu_instruction(pAsm, alu_instruction_ptr, contiguous_slots_needed) )
+ {
+ return GL_FALSE;
+ }
+
+ /*
+ * Judge the type of current instruction, is it vector or scalar
+ * instruction.
+ */
+ if (is_single_scalar_operation)
+ {
+ if(GL_FALSE == check_scalar(pAsm, alu_instruction_ptr) )
+ {
+ return GL_FALSE;
+ }
+ }
+ else
+ {
+ if(GL_FALSE == check_vector(pAsm, alu_instruction_ptr) )
+ {
+ return 1;
+ }
+ }
+
+ contiguous_slots_needed = 0;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean next_ins(r700_AssemblerBase *pAsm)
+{
+ struct prog_instruction *pILInst = &(pAsm->pILInst[pAsm->uiCurInst]);
+
+ if( GL_TRUE == IsTex(pILInst->Opcode) &&
+ /* handle const moves to temp register */
+ !(pAsm->D.dst.opcode == SQ_OP2_INST_MOV) )
+ {
+ if (pILInst->TexSrcTarget == TEXTURE_RECT_INDEX) {
+ if( GL_FALSE == assemble_tex_instruction(pAsm, GL_FALSE) )
+ {
+ radeon_error("Error assembling TEX instruction\n");
+ return GL_FALSE;
+ }
+ } else {
+ if( GL_FALSE == assemble_tex_instruction(pAsm, GL_TRUE) )
+ {
+ radeon_error("Error assembling TEX instruction\n");
+ return GL_FALSE;
+ }
+ }
+ }
+ else
+ { //ALU
+ if( GL_FALSE == assemble_alu_instruction(pAsm) )
+ {
+ radeon_error("Error assembling ALU instruction\n");
+ return GL_FALSE;
+ }
+ }
+
+ if(pAsm->D.dst.rtype == DST_REG_OUT)
+ {
+ if(pAsm->D.dst.op3)
+ {
+ // There is no mask for OP3 instructions, so all channels are written
+ pAsm->pucOutMask[pAsm->D.dst.reg - pAsm->starting_export_register_number] = 0xF;
+ }
+ else
+ {
+ pAsm->pucOutMask[pAsm->D.dst.reg - pAsm->starting_export_register_number]
+ |= (unsigned char)pAsm->pILInst[pAsm->uiCurInst].DstReg.WriteMask;
+ }
+ }
+
+ //reset for next inst.
+ pAsm->D.bits = 0;
+ pAsm->S[0].bits = 0;
+ pAsm->S[1].bits = 0;
+ pAsm->S[2].bits = 0;
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_math_function(r700_AssemblerBase* pAsm, BITS opcode)
+{
+ BITS tmp;
+
+ checkop1(pAsm);
+
+ tmp = gethelpr(pAsm);
+
+ // opcode tmp.x, a.x
+ // MOV dst, tmp.x
+
+ pAsm->D.dst.opcode = opcode;
+ pAsm->D.dst.math = 1;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ pAsm->D.dst.writex = 1;
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ // Now replicate result to all necessary channels in destination
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = DST_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+
+ setswizzle_PVSSRC(&(pAsm->S[0].src), SQ_SEL_X);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_ABS(r700_AssemblerBase *pAsm)
+{
+ checkop1(pAsm);
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MAX;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->S[1].bits = pAsm->S[0].bits;
+ flipneg_PVSSRC(&(pAsm->S[1].src));
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_ADD(r700_AssemblerBase *pAsm)
+{
+ if( GL_FALSE == checkop2(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_ADD;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if(pAsm->pILInst[pAsm->uiCurInst].Opcode == OPCODE_SUB)
+ {
+ flipneg_PVSSRC(&(pAsm->S[1].src));
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_BAD(char *opcode_str)
+{
+ radeon_error("Not yet implemented instruction (%s)\n", opcode_str);
+ return GL_FALSE;
+}
+
+GLboolean assemble_CMP(r700_AssemblerBase *pAsm)
+{
+ int tmp;
+
+ if( GL_FALSE == checkop3(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP3_INST_CNDGE;
+ pAsm->D.dst.op3 = 1;
+
+ tmp = (-1);
+
+ if(0xF != pAsm->pILInst[pAsm->uiCurInst].DstReg.WriteMask)
+ {
+ //OP3 has no support for write mask
+ tmp = gethelpr(pAsm);
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+
+ nomask_PVSDST(&(pAsm->D.dst));
+ }
+ else
+ {
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 2, 1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, 2) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if (0xF != pAsm->pILInst[pAsm->uiCurInst].DstReg.WriteMask)
+ {
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ //tmp for source
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+
+ noneg_PVSSRC(&(pAsm->S[0].src));
+ noswizzle_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_COS(r700_AssemblerBase *pAsm)
+{
+ return assemble_math_function(pAsm, SQ_OP2_INST_COS);
+}
+
+GLboolean assemble_DOT(r700_AssemblerBase *pAsm)
+{
+ if( GL_FALSE == checkop2(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_DOT4;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if(OPCODE_DP3 == pAsm->pILInst[pAsm->uiCurInst].Opcode)
+ {
+ zerocomp_PVSSRC(&(pAsm->S[0].src), 3);
+ zerocomp_PVSSRC(&(pAsm->S[1].src), 3);
+ }
+ else if(pAsm->pILInst[pAsm->uiCurInst].Opcode == OPCODE_DPH)
+ {
+ onecomp_PVSSRC(&(pAsm->S[1].src), 3);
+ }
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_DST(r700_AssemblerBase *pAsm)
+{
+ if( GL_FALSE == checkop2(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MUL;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ onecomp_PVSSRC(&(pAsm->S[0].src), 0);
+ onecomp_PVSSRC(&(pAsm->S[0].src), 3);
+
+ onecomp_PVSSRC(&(pAsm->S[1].src), 0);
+ onecomp_PVSSRC(&(pAsm->S[1].src), 2);
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_EX2(r700_AssemblerBase *pAsm)
+{
+ return assemble_math_function(pAsm, SQ_OP2_INST_EXP_IEEE);
+}
+
+GLboolean assemble_FLR(r700_AssemblerBase *pAsm)
+{
+ checkop1(pAsm);
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_FLOOR;
+
+ if ( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_FLR_INT(r700_AssemblerBase *pAsm)
+{
+ return assemble_math_function(pAsm, SQ_OP2_INST_FLT_TO_INT);
+}
+
+GLboolean assemble_FRC(r700_AssemblerBase *pAsm)
+{
+ checkop1(pAsm);
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_FRACT;
+
+ if ( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_KIL(r700_AssemblerBase *pAsm)
+{
+ checkop1(pAsm);
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_KILLGT;
+
+ if ( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.writex = 0;
+ pAsm->D.dst.writey = 0;
+ pAsm->D.dst.writez = 0;
+ pAsm->D.dst.writew = 0;
+
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = 0;
+
+ setswizzle_PVSSRC(&(pAsm->S[0].src), SQ_SEL_0);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+
+ pAsm->S[1].src.rtype = SRC_REG_TEMPORARY;
+
+ if(PROGRAM_TEMPORARY == pAsm->pILInst[pAsm->uiCurInst].DstReg.File)
+ {
+ pAsm->S[1].src.reg = pAsm->pILInst[pAsm->uiCurInst].DstReg.Index + pAsm->starting_temp_register_number;
+ }
+ else
+ { //PROGRAM_OUTPUT
+ pAsm->S[1].src.reg = pAsm->uiFP_OutputMap[pAsm->pILInst[pAsm->uiCurInst].DstReg.Index];
+ }
+
+ setaddrmode_PVSSRC(&(pAsm->S[1].src), ADDR_ABSOLUTE);
+ noswizzle_PVSSRC(&(pAsm->S[1].src));
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->pR700Shader->killIsUsed = GL_TRUE;
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_LG2(r700_AssemblerBase *pAsm)
+{
+ return assemble_math_function(pAsm, SQ_OP2_INST_LOG_IEEE);
+}
+
+GLboolean assemble_LRP(r700_AssemblerBase *pAsm)
+{
+ BITS tmp;
+
+ if( GL_FALSE == checkop3(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ tmp = gethelpr(pAsm);
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_ADD;
+
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ nomask_PVSDST(&(pAsm->D.dst));
+
+
+ if( GL_FALSE == assemble_src(pAsm, 1, 0) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == assemble_src(pAsm, 2, 1) )
+ {
+ return GL_FALSE;
+ }
+
+ neg_PVSSRC(&(pAsm->S[1].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;
+ pAsm->D.dst.op3 = 1;
+
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ nomask_PVSDST(&(pAsm->D.dst));
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+ noswizzle_PVSSRC(&(pAsm->S[0].src));
+
+
+ if( GL_FALSE == assemble_src(pAsm, 0, 1) )
+ {
+ return GL_FALSE;
+ }
+ if( GL_FALSE == assemble_src(pAsm, 2, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+ noswizzle_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_MAD(struct r700_AssemblerBase *pAsm)
+{
+ int tmp, ii;
+ GLboolean bReplaceDst = GL_FALSE;
+ struct prog_instruction *pILInst = &(pAsm->pILInst[pAsm->uiCurInst]);
+
+ if( GL_FALSE == checkop3(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;
+ pAsm->D.dst.op3 = 1;
+
+ tmp = (-1);
+
+ if(PROGRAM_TEMPORARY == pILInst->DstReg.File)
+ { /* TODO : more investigation on MAD src and dst using same register */
+ for(ii=0; ii<3; ii++)
+ {
+ if( (PROGRAM_TEMPORARY == pILInst->SrcReg[ii].File)
+ && (pILInst->DstReg.Index == pILInst->SrcReg[ii].Index) )
+ {
+ bReplaceDst = GL_TRUE;
+ break;
+ }
+ }
+ }
+ if(0xF != pILInst->DstReg.WriteMask)
+ { /* OP3 has no support for write mask */
+ bReplaceDst = GL_TRUE;
+ }
+
+ if(GL_TRUE == bReplaceDst)
+ {
+ tmp = gethelpr(pAsm);
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+
+ nomask_PVSDST(&(pAsm->D.dst));
+ }
+ else
+ {
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 2, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if (GL_TRUE == bReplaceDst)
+ {
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ //tmp for source
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+
+ noneg_PVSSRC(&(pAsm->S[0].src));
+ noswizzle_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+/* LIT dst, src */
+GLboolean assemble_LIT(r700_AssemblerBase *pAsm)
+{
+ unsigned int dstReg;
+ unsigned int dstType;
+ unsigned int srcReg;
+ unsigned int srcType;
+ checkop1(pAsm);
+ int tmp = gethelpr(pAsm);
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+ dstReg = pAsm->D.dst.reg;
+ dstType = pAsm->D.dst.rtype;
+ srcReg = pAsm->S[0].src.reg;
+ srcType = pAsm->S[0].src.rtype;
+
+ /* dst.xw, <- 1.0 */
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+ pAsm->D.dst.rtype = dstType;
+ pAsm->D.dst.reg = dstReg;
+ pAsm->D.dst.writex = 1;
+ pAsm->D.dst.writey = 0;
+ pAsm->D.dst.writez = 0;
+ pAsm->D.dst.writew = 1;
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+ pAsm->S[0].src.swizzlex = SQ_SEL_1;
+ pAsm->S[0].src.swizzley = SQ_SEL_1;
+ pAsm->S[0].src.swizzlez = SQ_SEL_1;
+ pAsm->S[0].src.swizzlew = SQ_SEL_1;
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ /* dst.y = max(src.x, 0.0) */
+ pAsm->D.dst.opcode = SQ_OP2_INST_MAX;
+ pAsm->D.dst.rtype = dstType;
+ pAsm->D.dst.reg = dstReg;
+ pAsm->D.dst.writex = 0;
+ pAsm->D.dst.writey = 1;
+ pAsm->D.dst.writez = 0;
+ pAsm->D.dst.writew = 0;
+ pAsm->S[0].src.rtype = srcType;
+ pAsm->S[0].src.reg = srcReg;
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+ pAsm->S[0].src.swizzlex = SQ_SEL_X;
+ pAsm->S[0].src.swizzley = SQ_SEL_X;
+ pAsm->S[0].src.swizzlez = SQ_SEL_X;
+ pAsm->S[0].src.swizzlew = SQ_SEL_X;
+ pAsm->S[1].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[1].src.reg = tmp;
+ setaddrmode_PVSSRC(&(pAsm->S[1].src), ADDR_ABSOLUTE);
+ noneg_PVSSRC(&(pAsm->S[1].src));
+ pAsm->S[1].src.swizzlex = SQ_SEL_0;
+ pAsm->S[1].src.swizzley = SQ_SEL_0;
+ pAsm->S[1].src.swizzlez = SQ_SEL_0;
+ pAsm->S[1].src.swizzlew = SQ_SEL_0;
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ /* before: dst.w = log(src.y)
+ * after : dst.x = log(src.y)
+ * why change dest register is that dst.w has been initialized as 1 before
+ */
+ pAsm->D.dst.opcode = SQ_OP2_INST_LOG_CLAMPED;
+ pAsm->D.dst.math = 1;
+ pAsm->D.dst.rtype = dstType;
+ pAsm->D.dst.reg = dstReg;
+ pAsm->D.dst.writex = 1;
+ pAsm->D.dst.writey = 0;
+ pAsm->D.dst.writez = 0;
+ pAsm->D.dst.writew = 0;
+ pAsm->S[0].src.rtype = srcType;
+ pAsm->S[0].src.reg = srcReg;
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+ pAsm->S[0].src.swizzlex = SQ_SEL_Y;
+ pAsm->S[0].src.swizzley = SQ_SEL_Y;
+ pAsm->S[0].src.swizzlez = SQ_SEL_Y;
+ pAsm->S[0].src.swizzlew = SQ_SEL_Y;
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ /* before: tmp.x = amd MUL_LIT(src.w, dst.w, src.x ) */
+ /* after : tmp.x = amd MUL_LIT(src.w, dst.x, src.x ) */
+ pAsm->D.dst.opcode = SQ_OP3_INST_MUL_LIT;
+ pAsm->D.dst.op3 = 1;
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ pAsm->D.dst.writex = 1;
+ pAsm->D.dst.writey = 0;
+ pAsm->D.dst.writez = 0;
+ pAsm->D.dst.writew = 0;
+
+ pAsm->S[0].src.rtype = srcType;
+ pAsm->S[0].src.reg = srcReg;
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+ pAsm->S[0].src.swizzlex = SQ_SEL_W;
+ pAsm->S[0].src.swizzley = SQ_SEL_W;
+ pAsm->S[0].src.swizzlez = SQ_SEL_W;
+ pAsm->S[0].src.swizzlew = SQ_SEL_W;
+
+ pAsm->S[1].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[1].src.reg = dstReg;
+ setaddrmode_PVSSRC(&(pAsm->S[1].src), ADDR_ABSOLUTE);
+ noneg_PVSSRC(&(pAsm->S[1].src));
+ pAsm->S[1].src.swizzlex = SQ_SEL_X;
+ pAsm->S[1].src.swizzley = SQ_SEL_X;
+ pAsm->S[1].src.swizzlez = SQ_SEL_X;
+ pAsm->S[1].src.swizzlew = SQ_SEL_X;
+
+ pAsm->S[2].src.rtype = srcType;
+ pAsm->S[2].src.reg = srcReg;
+ setaddrmode_PVSSRC(&(pAsm->S[2].src), ADDR_ABSOLUTE);
+ noneg_PVSSRC(&(pAsm->S[2].src));
+ pAsm->S[2].src.swizzlex = SQ_SEL_X;
+ pAsm->S[2].src.swizzley = SQ_SEL_X;
+ pAsm->S[2].src.swizzlez = SQ_SEL_X;
+ pAsm->S[2].src.swizzlew = SQ_SEL_X;
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ /* dst.z = exp(tmp.x) */
+ pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+ pAsm->D.dst.math = 1;
+ pAsm->D.dst.rtype = dstType;
+ pAsm->D.dst.reg = dstReg;
+ pAsm->D.dst.writex = 0;
+ pAsm->D.dst.writey = 0;
+ pAsm->D.dst.writez = 1;
+ pAsm->D.dst.writew = 0;
+
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+ pAsm->S[0].src.swizzlex = SQ_SEL_X;
+ pAsm->S[0].src.swizzley = SQ_SEL_X;
+ pAsm->S[0].src.swizzlez = SQ_SEL_X;
+ pAsm->S[0].src.swizzlew = SQ_SEL_X;
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_MAX(r700_AssemblerBase *pAsm)
+{
+ if( GL_FALSE == checkop2(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MAX;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_MIN(r700_AssemblerBase *pAsm)
+{
+ if( GL_FALSE == checkop2(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MIN;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_MOV(r700_AssemblerBase *pAsm)
+{
+ checkop1(pAsm);
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ if (GL_FALSE == assemble_dst(pAsm))
+ {
+ return GL_FALSE;
+ }
+
+ if (GL_FALSE == assemble_src(pAsm, 0, -1))
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_MUL(r700_AssemblerBase *pAsm)
+{
+ if( GL_FALSE == checkop2(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MUL;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_POW(r700_AssemblerBase *pAsm)
+{
+ BITS tmp;
+
+ checkop1(pAsm);
+
+ tmp = gethelpr(pAsm);
+
+ // LG2 tmp.x, a.swizzle
+ pAsm->D.dst.opcode = SQ_OP2_INST_LOG_IEEE;
+ pAsm->D.dst.math = 1;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ nomask_PVSDST(&(pAsm->D.dst));
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ // MUL tmp.x, tmp.x, b.swizzle
+ pAsm->D.dst.opcode = SQ_OP2_INST_MUL;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ nomask_PVSDST(&(pAsm->D.dst));
+
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+ setswizzle_PVSSRC(&(pAsm->S[0].src), SQ_SEL_X);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ // EX2 dst.mask, tmp.x
+ // EX2 tmp.x, tmp.x
+ pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+ pAsm->D.dst.math = 1;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ nomask_PVSDST(&(pAsm->D.dst));
+
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+ setswizzle_PVSSRC(&(pAsm->S[0].src), SQ_SEL_X);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ // Now replicate result to all necessary channels in destination
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = DST_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+
+ setswizzle_PVSSRC(&(pAsm->S[0].src), SQ_SEL_X);
+ noneg_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_RCP(r700_AssemblerBase *pAsm)
+{
+ return assemble_math_function(pAsm, SQ_OP2_INST_RECIP_IEEE);
+}
+
+GLboolean assemble_RSQ(r700_AssemblerBase *pAsm)
+{
+ return assemble_math_function(pAsm, SQ_OP2_INST_RECIPSQRT_IEEE);
+}
+
+GLboolean assemble_SIN(r700_AssemblerBase *pAsm)
+{
+ return assemble_math_function(pAsm, SQ_OP2_INST_SIN);
+}
+
+GLboolean assemble_SCS(r700_AssemblerBase *pAsm)
+{
+ BITS tmp;
+
+ checkop1(pAsm);
+
+ tmp = gethelpr(pAsm);
+
+ // COS tmp.x, a.x
+ pAsm->D.dst.opcode = SQ_OP2_INST_COS;
+ pAsm->D.dst.math = 1;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ pAsm->D.dst.writex = 1;
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ // SIN tmp.y, a.x
+ pAsm->D.dst.opcode = SQ_OP2_INST_SIN;
+ pAsm->D.dst.math = 1;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ pAsm->D.dst.writey = 1;
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ // MOV dst.mask, tmp
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = DST_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+
+ noswizzle_PVSSRC(&(pAsm->S[0].src));
+ pAsm->S[0].src.swizzlez = SQ_SEL_0;
+ pAsm->S[0].src.swizzlew = SQ_SEL_0;
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_SGE(r700_AssemblerBase *pAsm)
+{
+ if( GL_FALSE == checkop2(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_SETGE;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_SLT(r700_AssemblerBase *pAsm)
+{
+ if( GL_FALSE == checkop2(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_SETGT;
+
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, 1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, 0) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_STP(r700_AssemblerBase *pAsm)
+{
+ return GL_TRUE;
+}
+
+GLboolean assemble_TEX(r700_AssemblerBase *pAsm)
+{
+ GLboolean src_const;
+
+ switch (pAsm->pILInst[pAsm->uiCurInst].SrcReg[0].File)
+ {
+ case PROGRAM_CONSTANT:
+ case PROGRAM_LOCAL_PARAM:
+ case PROGRAM_ENV_PARAM:
+ case PROGRAM_STATE_VAR:
+ src_const = GL_TRUE;
+ break;
+ case PROGRAM_TEMPORARY:
+ case PROGRAM_INPUT:
+ src_const = GL_FALSE;
+ break;
+ }
+
+ if (GL_TRUE == src_const)
+ {
+ if ( GL_FALSE == mov_temp(pAsm, 0) )
+ return GL_FALSE;
+ }
+
+ switch (pAsm->pILInst[pAsm->uiCurInst].Opcode)
+ {
+ case OPCODE_TEX:
+ pAsm->D.dst.opcode = SQ_TEX_INST_SAMPLE;
+ break;
+ case OPCODE_TXB:
+ radeon_error("do not support TXB yet\n");
+ return GL_FALSE;
+ break;
+ case OPCODE_TXP:
+ /* TODO : tex proj version : divid first 3 components by 4th */
+ pAsm->D.dst.opcode = SQ_TEX_INST_SAMPLE;
+ break;
+ default:
+ radeon_error("Internal error: bad texture op (not TEX)\n");
+ return GL_FALSE;
+ break;
+ }
+
+ // Set src1 to tex unit id
+ pAsm->S[1].src.reg = pAsm->pILInst[pAsm->uiCurInst].TexSrcUnit;
+ pAsm->S[1].src.rtype = SRC_REG_TEMPORARY;
+
+ //No sw info from mesa compiler, so hard code here.
+ pAsm->S[1].src.swizzlex = SQ_SEL_X;
+ pAsm->S[1].src.swizzley = SQ_SEL_Y;
+ pAsm->S[1].src.swizzlez = SQ_SEL_Z;
+ pAsm->S[1].src.swizzlew = SQ_SEL_W;
+
+ if( GL_FALSE == tex_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == tex_src(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ if ( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_XPD(r700_AssemblerBase *pAsm)
+{
+ BITS tmp;
+
+ if( GL_FALSE == checkop2(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ tmp = gethelpr(pAsm);
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MUL;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+ nomask_PVSDST(&(pAsm->D.dst));
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ swizzleagain_PVSSRC(&(pAsm->S[0].src), SQ_SEL_Z, SQ_SEL_X, SQ_SEL_Y, SQ_SEL_0);
+ swizzleagain_PVSSRC(&(pAsm->S[1].src), SQ_SEL_Y, SQ_SEL_Z, SQ_SEL_X, SQ_SEL_0);
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;
+ pAsm->D.dst.op3 = 1;
+
+ if(0xF != pAsm->pILInst[pAsm->uiCurInst].DstReg.WriteMask)
+ {
+ tmp = gethelpr(pAsm);
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = tmp;
+
+ nomask_PVSDST(&(pAsm->D.dst));
+ }
+ else
+ {
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == assemble_src(pAsm, 1, -1) )
+ {
+ return GL_FALSE;
+ }
+
+ swizzleagain_PVSSRC(&(pAsm->S[0].src), SQ_SEL_Y, SQ_SEL_Z, SQ_SEL_X, SQ_SEL_0);
+ swizzleagain_PVSSRC(&(pAsm->S[1].src), SQ_SEL_Z, SQ_SEL_X, SQ_SEL_Y, SQ_SEL_0);
+
+ // result1 + (neg) result0
+ setaddrmode_PVSSRC(&(pAsm->S[2].src),ADDR_ABSOLUTE);
+ pAsm->S[2].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[2].src.reg = tmp;
+
+ neg_PVSSRC(&(pAsm->S[2].src));
+ noswizzle_PVSSRC(&(pAsm->S[2].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+
+ if(0xF != pAsm->pILInst[pAsm->uiCurInst].DstReg.WriteMask)
+ {
+ if( GL_FALSE == assemble_dst(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ // Use tmp as source
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+ pAsm->S[0].src.reg = tmp;
+
+ noneg_PVSSRC(&(pAsm->S[0].src));
+ noswizzle_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean assemble_EXPORT(r700_AssemblerBase *pAsm)
+{
+ return GL_TRUE;
+}
+
+GLboolean assemble_IF(r700_AssemblerBase *pAsm)
+{
+ return GL_TRUE;
+}
+
+GLboolean assemble_ENDIF(r700_AssemblerBase *pAsm)
+{
+ return GL_TRUE;
+}
+
+GLboolean AssembleInstr(GLuint uiNumberInsts,
+ struct prog_instruction *pILInst,
+ r700_AssemblerBase *pR700AsmCode)
+{
+ GLuint i;
+
+ pR700AsmCode->pILInst = pILInst;
+ for(i=0; i<uiNumberInsts; i++)
+ {
+ pR700AsmCode->uiCurInst = i;
+
+ switch (pILInst[i].Opcode)
+ {
+ case OPCODE_ABS:
+ if ( GL_FALSE == assemble_ABS(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_ADD:
+ case OPCODE_SUB:
+ if ( GL_FALSE == assemble_ADD(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_ARL:
+ radeon_error("Not yet implemented instruction OPCODE_ARL \n");
+ //if ( GL_FALSE == assemble_BAD("ARL") )
+ return GL_FALSE;
+ break;
+ case OPCODE_ARR:
+ radeon_error("Not yet implemented instruction OPCODE_ARR \n");
+ //if ( GL_FALSE == assemble_BAD("ARR") )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_CMP:
+ if ( GL_FALSE == assemble_CMP(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_COS:
+ if ( GL_FALSE == assemble_COS(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_DP3:
+ case OPCODE_DP4:
+ case OPCODE_DPH:
+ if ( GL_FALSE == assemble_DOT(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_DST:
+ if ( GL_FALSE == assemble_DST(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_EX2:
+ if ( GL_FALSE == assemble_EX2(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_EXP:
+ radeon_error("Not yet implemented instruction OPCODE_EXP \n");
+ //if ( GL_FALSE == assemble_BAD("EXP") )
+ return GL_FALSE;
+ break; // approx of EX2
+
+ case OPCODE_FLR:
+ if ( GL_FALSE == assemble_FLR(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ //case OP_FLR_INT:
+ // if ( GL_FALSE == assemble_FLR_INT() )
+ // return GL_FALSE;
+ // break;
+
+ case OPCODE_FRC:
+ if ( GL_FALSE == assemble_FRC(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_KIL:
+ if ( GL_FALSE == assemble_KIL(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_LG2:
+ if ( GL_FALSE == assemble_LG2(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_LIT:
+ if ( GL_FALSE == assemble_LIT(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_LRP:
+ if ( GL_FALSE == assemble_LRP(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_LOG:
+ radeon_error("Not yet implemented instruction OPCODE_LOG \n");
+ //if ( GL_FALSE == assemble_BAD("LOG") )
+ return GL_FALSE;
+ break; // approx of LG2
+
+ case OPCODE_MAD:
+ if ( GL_FALSE == assemble_MAD(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_MAX:
+ if ( GL_FALSE == assemble_MAX(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_MIN:
+ if ( GL_FALSE == assemble_MIN(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_MOV:
+ if ( GL_FALSE == assemble_MOV(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_MUL:
+ if ( GL_FALSE == assemble_MUL(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_POW:
+ if ( GL_FALSE == assemble_POW(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_RCP:
+ if ( GL_FALSE == assemble_RCP(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_RSQ:
+ if ( GL_FALSE == assemble_RSQ(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_SIN:
+ if ( GL_FALSE == assemble_SIN(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_SCS:
+ if ( GL_FALSE == assemble_SCS(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_SGE:
+ if ( GL_FALSE == assemble_SGE(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_SLT:
+ if ( GL_FALSE == assemble_SLT(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ //case OP_STP:
+ // if ( GL_FALSE == assemble_STP(pR700AsmCode) )
+ // return GL_FALSE;
+ // break;
+
+ case OPCODE_SWZ:
+ if ( GL_FALSE == assemble_MOV(pR700AsmCode) )
+ {
+ return GL_FALSE;
+ }
+ else
+ {
+ if( (i+1)<uiNumberInsts )
+ {
+ if(OPCODE_END != pILInst[i+1].Opcode)
+ {
+ if( GL_TRUE == IsTex(pILInst[i+1].Opcode) )
+ {
+ pR700AsmCode->pInstDeps[i+1].nDstDep = i+1; //=1?
+ }
+ }
+ }
+ }
+ break;
+
+ case OPCODE_TEX:
+ case OPCODE_TXB:
+ case OPCODE_TXP:
+ if ( GL_FALSE == assemble_TEX(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_XPD:
+ if ( GL_FALSE == assemble_XPD(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ case OPCODE_IF :
+ if ( GL_FALSE == assemble_IF(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+ case OPCODE_ELSE :
+ radeon_error("Not yet implemented instruction OPCODE_ELSE \n");
+ //if ( GL_FALSE == assemble_BAD("ELSE") )
+ return GL_FALSE;
+ break;
+ case OPCODE_ENDIF:
+ if ( GL_FALSE == assemble_ENDIF(pR700AsmCode) )
+ return GL_FALSE;
+ break;
+
+ //case OPCODE_EXPORT:
+ // if ( GL_FALSE == assemble_EXPORT() )
+ // return GL_FALSE;
+ // break;
+
+ case OPCODE_END:
+ //pR700AsmCode->uiCurInst = i;
+ //This is to remaind that if in later exoort there is depth/stencil
+ //export, we need a mov to re-arrange DST channel, where using a
+ //psuedo inst, we will use this end inst to do it.
+ return GL_TRUE;
+
+ default:
+ radeon_error("internal: unknown instruction\n");
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean Process_Export(r700_AssemblerBase* pAsm,
+ GLuint type,
+ GLuint export_starting_index,
+ GLuint export_count,
+ GLuint starting_register_number,
+ GLboolean is_depth_export)
+{
+ unsigned char ucWriteMask;
+
+ check_current_clause(pAsm, CF_EMPTY_CLAUSE);
+ check_current_clause(pAsm, CF_EXPORT_CLAUSE); //alloc the cf_current_export_clause_ptr
+
+ pAsm->cf_current_export_clause_ptr->m_Word0.f.type = type;
+
+ switch (type)
+ {
+ case SQ_EXPORT_PIXEL:
+ if(GL_TRUE == is_depth_export)
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word0.f.array_base = SQ_CF_PIXEL_Z;
+ }
+ else
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word0.f.array_base = SQ_CF_PIXEL_MRT0 + export_starting_index;
+ }
+ break;
+
+ case SQ_EXPORT_POS:
+ pAsm->cf_current_export_clause_ptr->m_Word0.f.array_base = SQ_CF_POS_0 + export_starting_index;
+ break;
+
+ case SQ_EXPORT_PARAM:
+ pAsm->cf_current_export_clause_ptr->m_Word0.f.array_base = 0x0 + export_starting_index;
+ break;
+
+ default:
+ radeon_error("Unknown export type: %d\n", type);
+ return GL_FALSE;
+ break;
+ }
+
+ pAsm->cf_current_export_clause_ptr->m_Word0.f.rw_gpr = starting_register_number;
+
+ pAsm->cf_current_export_clause_ptr->m_Word0.f.rw_rel = SQ_ABSOLUTE;
+ pAsm->cf_current_export_clause_ptr->m_Word0.f.index_gpr = 0x0;
+ pAsm->cf_current_export_clause_ptr->m_Word0.f.elem_size = 0x3;
+
+ pAsm->cf_current_export_clause_ptr->m_Word1.f.burst_count = (export_count - 1);
+ pAsm->cf_current_export_clause_ptr->m_Word1.f.end_of_program = 0x0;
+ pAsm->cf_current_export_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+ pAsm->cf_current_export_clause_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT; // _DONE
+ pAsm->cf_current_export_clause_ptr->m_Word1.f.whole_quad_mode = 0x0;
+ pAsm->cf_current_export_clause_ptr->m_Word1.f.barrier = 0x1;
+
+ if (export_count == 1)
+ {
+ ucWriteMask = pAsm->pucOutMask[starting_register_number - pAsm->starting_export_register_number];
+ /* exports Z as a float into Red channel */
+ if (GL_TRUE == is_depth_export)
+ ucWriteMask = 0x1;
+
+ if( (ucWriteMask & 0x1) != 0)
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_x = SQ_SEL_X;
+ }
+ else
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_x = SQ_SEL_MASK;
+ }
+ if( ((ucWriteMask>>1) & 0x1) != 0)
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_y = SQ_SEL_Y;
+ }
+ else
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_y = SQ_SEL_MASK;
+ }
+ if( ((ucWriteMask>>2) & 0x1) != 0)
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_z = SQ_SEL_Z;
+ }
+ else
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_z = SQ_SEL_MASK;
+ }
+ if( ((ucWriteMask>>3) & 0x1) != 0)
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_w = SQ_SEL_W;
+ }
+ else
+ {
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_w = SQ_SEL_MASK;
+ }
+ }
+ else
+ {
+ // This should only be used if all components for all registers have been written
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_x = SQ_SEL_X;
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_y = SQ_SEL_Y;
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_z = SQ_SEL_Z;
+ pAsm->cf_current_export_clause_ptr->m_Word1_SWIZ.f.sel_w = SQ_SEL_W;
+ }
+
+ pAsm->cf_last_export_ptr = pAsm->cf_current_export_clause_ptr;
+
+ return GL_TRUE;
+}
+
+GLboolean Move_Depth_Exports_To_Correct_Channels(r700_AssemblerBase *pAsm, BITS depth_channel_select)
+{
+ gl_inst_opcode Opcode_save = pAsm->pILInst[pAsm->uiCurInst].Opcode; //Should be OPCODE_END
+ pAsm->pILInst[pAsm->uiCurInst].Opcode = OPCODE_MOV;
+
+ // MOV depth_export_register.hw_depth_channel, depth_export_register.depth_channel_select
+
+ pAsm->D.dst.opcode = SQ_OP2_INST_MOV;
+
+ setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
+ pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+ pAsm->D.dst.reg = pAsm->depth_export_register_number;
+
+ pAsm->D.dst.writex = 1; // depth goes in R channel for HW
+
+ setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+ pAsm->S[0].src.rtype = DST_REG_TEMPORARY;
+ pAsm->S[0].src.reg = pAsm->depth_export_register_number;
+
+ setswizzle_PVSSRC(&(pAsm->S[0].src), depth_channel_select);
+
+ noneg_PVSSRC(&(pAsm->S[0].src));
+
+ if( GL_FALSE == next_ins(pAsm) )
+ {
+ return GL_FALSE;
+ }
+
+ pAsm->pILInst[pAsm->uiCurInst].Opcode = Opcode_save;
+
+ return GL_TRUE;
+}
+
+GLboolean Process_Fragment_Exports(r700_AssemblerBase *pR700AsmCode,
+ GLbitfield OutputsWritten)
+{
+ unsigned int unBit;
+
+ if(pR700AsmCode->depth_export_register_number >= 0)
+ {
+ if( GL_FALSE == Move_Depth_Exports_To_Correct_Channels(pR700AsmCode, SQ_SEL_Z) ) // depth
+ {
+ return GL_FALSE;
+ }
+ }
+
+ unBit = 1 << FRAG_RESULT_COLOR;
+ if(OutputsWritten & unBit)
+ {
+ if( GL_FALSE == Process_Export(pR700AsmCode,
+ SQ_EXPORT_PIXEL,
+ 0,
+ 1,
+ pR700AsmCode->uiFP_OutputMap[FRAG_RESULT_COLOR],
+ GL_FALSE) )
+ {
+ return GL_FALSE;
+ }
+ }
+ unBit = 1 << FRAG_RESULT_DEPTH;
+ if(OutputsWritten & unBit)
+ {
+ if( GL_FALSE == Process_Export(pR700AsmCode,
+ SQ_EXPORT_PIXEL,
+ 0,
+ 1,
+ pR700AsmCode->uiFP_OutputMap[FRAG_RESULT_DEPTH],
+ GL_TRUE))
+ {
+ return GL_FALSE;
+ }
+ }
+
+ if(pR700AsmCode->cf_last_export_ptr != NULL)
+ {
+ pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;
+ pR700AsmCode->cf_last_export_ptr->m_Word1.f.end_of_program = 0x1;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean Process_Vertex_Exports(r700_AssemblerBase *pR700AsmCode,
+ GLbitfield OutputsWritten)
+{
+ unsigned int unBit;
+ unsigned int i;
+
+ GLuint export_starting_index = 0;
+ GLuint export_count = pR700AsmCode->number_of_exports;
+
+ unBit = 1 << VERT_RESULT_HPOS;
+ if(OutputsWritten & unBit)
+ {
+ if( GL_FALSE == Process_Export(pR700AsmCode,
+ SQ_EXPORT_POS,
+ export_starting_index,
+ 1,
+ pR700AsmCode->ucVP_OutputMap[VERT_RESULT_HPOS],
+ GL_FALSE) )
+ {
+ return GL_FALSE;
+ }
+
+ export_count--;
+
+ pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;
+ }
+
+ pR700AsmCode->number_of_exports = export_count;
+
+ unBit = 1 << VERT_RESULT_COL0;
+ if(OutputsWritten & unBit)
+ {
+ if( GL_FALSE == Process_Export(pR700AsmCode,
+ SQ_EXPORT_PARAM,
+ export_starting_index,
+ 1,
+ pR700AsmCode->ucVP_OutputMap[VERT_RESULT_COL0],
+ GL_FALSE) )
+ {
+ return GL_FALSE;
+ }
+
+ export_starting_index++;
+ }
+
+ unBit = 1 << VERT_RESULT_COL1;
+ if(OutputsWritten & unBit)
+ {
+ if( GL_FALSE == Process_Export(pR700AsmCode,
+ SQ_EXPORT_PARAM,
+ export_starting_index,
+ 1,
+ pR700AsmCode->ucVP_OutputMap[VERT_RESULT_COL1],
+ GL_FALSE) )
+ {
+ return GL_FALSE;
+ }
+
+ export_starting_index++;
+ }
+
+ unBit = 1 << VERT_RESULT_FOGC;
+ if(OutputsWritten & unBit)
+ {
+ if( GL_FALSE == Process_Export(pR700AsmCode,
+ SQ_EXPORT_PARAM,
+ export_starting_index,
+ 1,
+ pR700AsmCode->ucVP_OutputMap[VERT_RESULT_FOGC],
+ GL_FALSE) )
+ {
+ return GL_FALSE;
+ }
+
+ export_starting_index++;
+ }
+
+ for(i=0; i<8; i++)
+ {
+ unBit = 1 << (VERT_RESULT_TEX0 + i);
+ if(OutputsWritten & unBit)
+ {
+ if( GL_FALSE == Process_Export(pR700AsmCode,
+ SQ_EXPORT_PARAM,
+ export_starting_index,
+ 1,
+ pR700AsmCode->ucVP_OutputMap[VERT_RESULT_TEX0 + i],
+ GL_FALSE) )
+ {
+ return GL_FALSE;
+ }
+
+ export_starting_index++;
+ }
+ }
+
+ // At least one param should be exported
+ if (export_count)
+ {
+ pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;
+ }
+ else
+ {
+ if( GL_FALSE == Process_Export(pR700AsmCode,
+ SQ_EXPORT_PARAM,
+ 0,
+ 1,
+ pR700AsmCode->starting_export_register_number,
+ GL_FALSE) )
+ {
+ return GL_FALSE;
+ }
+
+ pR700AsmCode->cf_last_export_ptr->m_Word1_SWIZ.f.sel_x = SQ_SEL_0;
+ pR700AsmCode->cf_last_export_ptr->m_Word1_SWIZ.f.sel_y = SQ_SEL_0;
+ pR700AsmCode->cf_last_export_ptr->m_Word1_SWIZ.f.sel_z = SQ_SEL_0;
+ pR700AsmCode->cf_last_export_ptr->m_Word1_SWIZ.f.sel_w = SQ_SEL_1;
+ pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;
+ }
+
+ pR700AsmCode->cf_last_export_ptr->m_Word1.f.end_of_program = 0x1;
+
+ return GL_TRUE;
+}
+
+GLboolean Clean_Up_Assembler(r700_AssemblerBase *pR700AsmCode)
+{
+ FREE(pR700AsmCode->pucOutMask);
+ FREE(pR700AsmCode->pInstDeps);
+ return GL_TRUE;
+}
+
diff --git a/src/mesa/drivers/dri/r600/r700_assembler.h b/src/mesa/drivers/dri/r600/r700_assembler.h
new file mode 100644
index 0000000000..f9c4d849c6
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_assembler.h
@@ -0,0 +1,512 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _R700_ASSEMBLER_H_
+#define _R700_ASSEMBLER_H_
+
+#include "main/mtypes.h"
+#include "shader/prog_instruction.h"
+
+#include "r700_chip.h"
+#include "r700_shaderinst.h"
+#include "r700_shader.h"
+
+typedef enum SHADER_PIPE_TYPE
+{
+ SPT_VP = 0,
+ SPT_FP = 1
+} SHADER_PIPE_TYPE;
+
+typedef enum ConstantCycles
+{
+ NUMBER_OF_CYCLES = 3,
+ NUMBER_OF_COMPONENTS = 4
+} ConstantCycles;
+
+typedef enum HARDWARE_LIMIT_VALUES
+{
+ TEMPORARY_REGISTER_OFFSET = SQ_ALU_SRC_GPR_BASE,
+ MAX_TEMPORARY_REGISTERS = SQ_ALU_SRC_GPR_SIZE,
+ MAX_CONSTANT_REGISTERS = SQ_ALU_SRC_CFILE_SIZE,
+ CFILE_REGISTER_OFFSET = SQ_ALU_SRC_CFILE_BASE,
+ NUMBER_OF_INPUT_COLORS = 2,
+ NUMBER_OF_OUTPUT_COLORS = 8,
+ NUMBER_OF_TEXTURE_UNITS = 16,
+ MEGA_FETCH_BYTES = 32
+} HARDWARE_LIMIT_VALUES;
+
+typedef enum AddressMode
+{
+ ADDR_ABSOLUTE = 0,
+ ADDR_RELATIVE_A0 = 1,
+ ADDR_RELATIVE_FLI_0 = 2,
+ NUMBER_OF_ADDR_MOD = 3
+} AddressMode;
+
+typedef enum SrcRegisterType
+{
+ SRC_REG_TEMPORARY = 0,
+ SRC_REG_INPUT = 1,
+ SRC_REG_CONSTANT = 2,
+ SRC_REG_ALT_TEMPORARY = 3,
+ NUMBER_OF_SRC_REG_TYPE = 4
+} SrcRegisterType;
+
+typedef enum DstRegisterType
+{
+ DST_REG_TEMPORARY = 0,
+ DST_REG_A0 = 1,
+ DST_REG_OUT = 2,
+ DST_REG_OUT_X_REPL = 3,
+ DST_REG_ALT_TEMPORARY = 4,
+ DST_REG_INPUT = 5,
+ NUMBER_OF_DST_REG_TYPE = 6
+} DstRegisterType;
+
+typedef unsigned int BITS;
+
+typedef struct PVSDSTtag
+{
+ BITS opcode:8; //(:6) //@@@ really should be 10 bits for OP2
+ BITS math:1;
+ BITS predicated:1; //10 //8
+ BITS pred_inv :1; //11 //8
+
+ BITS rtype:3;
+ BITS reg:10; //24 //20
+
+ BITS writex:1;
+ BITS writey:1;
+ BITS writez:1;
+ BITS writew:1; //28
+
+ BITS op3:1; // 29 Represents *_OP3_* ALU opcode
+
+ BITS dualop:1; // 30 //26
+
+ BITS addrmode0:1; //31 //29
+ BITS addrmode1:1; //32
+} PVSDST;
+
+typedef struct PVSSRCtag
+{
+ BITS rtype:4;
+ BITS addrmode0:1;
+ BITS reg:10; //15 (8)
+ BITS swizzlex:3;
+ BITS swizzley:3;
+ BITS swizzlez:3;
+ BITS swizzlew:3; //27
+
+ BITS negx:1;
+ BITS negy:1;
+ BITS negz:1;
+ BITS negw:1; //31
+ //BITS addrsel:2;
+ BITS addrmode1:1; //32
+} PVSSRC;
+
+typedef struct PVSMATHtag
+{
+ BITS rtype:4;
+ BITS spare:1;
+ BITS reg:8;
+ BITS swizzlex:3;
+ BITS swizzley:3;
+ BITS dstoff:2; // 2 bits of dest offset into alt ram
+ BITS opcode:4;
+ BITS negx:1;
+ BITS negy:1;
+ BITS dstcomp:2; // select dest component
+ BITS spare2:3;
+} PVSMATH;
+
+typedef union PVSDWORDtag
+{
+ BITS bits;
+ PVSDST dst;
+ PVSSRC src;
+ PVSMATH math;
+ float f;
+} PVSDWORD;
+
+typedef struct VAP_OUT_VTX_FMT_0tag
+{
+ BITS pos:1; // 0
+ BITS misc:1;
+ BITS clip_dist0:1;
+ BITS clip_dist1:1;
+ BITS pos_param:1; // 4
+
+ BITS color0:1; // 5
+ BITS color1:1;
+ BITS color2:1;
+ BITS color3:1;
+ BITS color4:1;
+ BITS color5:1;
+ BITS color6:1;
+ BITS color7:1;
+
+ BITS normal:1;
+
+ BITS depth:1; // 14
+
+ BITS point_size:1; // 15
+ BITS edge_flag:1;
+ BITS rta_index:1; // shares same channel as kill_flag
+ BITS kill_flag:1;
+ BITS viewport_index:1; // 19
+
+ BITS resvd1:12; // 20
+} VAP_OUT_VTX_FMT_0;
+
+typedef struct VAP_OUT_VTX_FMT_1tag
+{
+ BITS tex0comp:3;
+ BITS tex1comp:3;
+ BITS tex2comp:3;
+ BITS tex3comp:3;
+ BITS tex4comp:3;
+ BITS tex5comp:3;
+ BITS tex6comp:3;
+ BITS tex7comp:3;
+
+ BITS resvd:8;
+} VAP_OUT_VTX_FMT_1;
+
+typedef struct VAP_OUT_VTX_FMT_2tag
+{
+ BITS tex8comp :3;
+ BITS tex9comp :3;
+ BITS tex10comp:3;
+ BITS tex11comp:3;
+ BITS tex12comp:3;
+ BITS tex13comp:3;
+ BITS tex14comp:3;
+ BITS tex15comp:3;
+
+ BITS resvd:8;
+} VAP_OUT_VTX_FMT_2;
+
+typedef struct OUT_FRAGMENT_FMT_0tag
+{
+ BITS color0:1;
+ BITS color1:1;
+ BITS color2:1;
+ BITS color3:1;
+ BITS color4:1;
+ BITS color5:1;
+ BITS color6:1;
+ BITS color7:1;
+
+ BITS depth:1;
+ BITS stencil_ref:1;
+ BITS coverage_to_mask:1;
+ BITS mask:1;
+
+ BITS resvd1:20;
+} OUT_FRAGMENT_FMT_0;
+
+typedef enum CF_CLAUSE_TYPE
+{
+ CF_EXPORT_CLAUSE,
+ CF_ALU_CLAUSE,
+ CF_TEX_CLAUSE,
+ CF_VTX_CLAUSE,
+ CF_OTHER_CLAUSE,
+ CF_EMPTY_CLAUSE,
+ NUMBER_CF_CLAUSE_TYPES
+} CF_CLAUSE_TYPE;
+
+enum
+{
+ MAX_BOOL_CONSTANTS = 32,
+ MAX_INT_CONSTANTS = 32,
+ MAX_FLOAT_CONSTANTS = 256,
+
+ FC_NONE = 0,
+ FC_IF = 1,
+ FC_LOOP = 2,
+ FC_REP = 3,
+
+ COND_NONE = 0,
+ COND_BOOL = 1,
+ COND_PRED = 2,
+ COND_ALU = 3,
+
+ SAFEDIST_TEX = 6, ///< safe distance for using result of texture lookup in alu or another tex lookup
+ SAFEDIST_ALU = 6 ///< the same for alu->fc
+};
+
+typedef struct FC_LEVEL
+{
+ unsigned int first; ///< first fc instruction on level (if, rep, loop)
+ unsigned int* mid; ///< middle instructions - else or all breaks on this level
+ unsigned int midLen;
+ unsigned int type;
+ unsigned int cond;
+ unsigned int inv;
+ unsigned int bpush; ///< 1 if first instruction does branch stack push
+ int id; ///< id of bool or int variable
+} FC_LEVEL;
+
+typedef struct VTX_FETCH_METHOD
+{
+ GLboolean bEnableMini;
+ GLuint mega_fetch_remainder;
+} VTX_FETCH_METHOD;
+
+typedef struct r700_AssemblerBase
+{
+ R700ControlFlowSXClause* cf_last_export_ptr;
+ R700ControlFlowSXClause* cf_current_export_clause_ptr;
+ R700ControlFlowALUClause* cf_current_alu_clause_ptr;
+ R700ControlFlowGenericClause* cf_current_tex_clause_ptr;
+ R700ControlFlowGenericClause* cf_current_vtx_clause_ptr;
+ R700ControlFlowGenericClause* cf_current_cf_clause_ptr;
+
+ //Result shader
+ R700_Shader * pR700Shader;
+
+ // No clause has been created yet
+ CF_CLAUSE_TYPE cf_current_clause_type;
+
+ GLuint number_of_exports;
+ GLuint number_of_colorandz_exports;
+ GLuint number_of_export_opcodes;
+
+ PVSDWORD D;
+ PVSDWORD S[3];
+
+ unsigned int uLastPosUpdate;
+
+ OUT_FRAGMENT_FMT_0 fp_stOutFmt0;
+
+ unsigned int uIIns;
+ unsigned int uOIns;
+ unsigned int number_used_registers;
+ unsigned int uUsedConsts;
+
+ // Fragment programs
+ unsigned int uiFP_AttributeMap[FRAG_ATTRIB_MAX];
+ unsigned int uiFP_OutputMap[FRAG_RESULT_MAX];
+ unsigned int uBoolConsts;
+ unsigned int uIntConsts;
+ unsigned int uInsts;
+ unsigned int uConsts;
+
+ // Vertex programs
+ unsigned char ucVP_AttributeMap[VERT_ATTRIB_MAX];
+ unsigned char ucVP_OutputMap[VERT_RESULT_MAX];
+
+ unsigned char * pucOutMask;
+
+ //-----------------------------------------------------------------------------------
+ // flow control members
+ //-----------------------------------------------------------------------------------
+ unsigned int FCSP;
+ FC_LEVEL fc_stack[32];
+
+ unsigned int branch_depth;
+ unsigned int max_branch_depth;
+
+ //-----------------------------------------------------------------------------------
+ // ArgSubst used in Assemble_Source() function
+ //-----------------------------------------------------------------------------------
+ int aArgSubst[4];
+
+ GLint hw_gpr[ NUMBER_OF_CYCLES ][ NUMBER_OF_COMPONENTS ];
+ GLint hw_cfile_addr[ NUMBER_OF_COMPONENTS ];
+ GLint hw_cfile_chan[ NUMBER_OF_COMPONENTS ];
+
+ GLuint uOutputs;
+
+ GLint color_export_register_number[NUMBER_OF_OUTPUT_COLORS];
+ GLint depth_export_register_number;
+
+ GLint stencil_export_register_number;
+ GLint coverage_to_mask_export_register_number;
+ GLint mask_export_register_number;
+
+ GLuint starting_export_register_number;
+ GLuint starting_vfetch_register_number;
+ GLuint starting_temp_register_number;
+ GLuint uHelpReg;
+ GLuint uFirstHelpReg;
+
+ GLboolean input_position_is_used;
+ GLboolean input_normal_is_used;
+
+ GLboolean input_color_is_used[NUMBER_OF_INPUT_COLORS];
+
+ GLboolean input_texture_unit_is_used[NUMBER_OF_TEXTURE_UNITS];
+
+ R700VertexGenericFetch* vfetch_instruction_ptr_array[VERT_ATTRIB_MAX];
+
+ GLuint number_of_inputs;
+
+ InstDeps *pInstDeps;
+
+ SHADER_PIPE_TYPE currentShaderType;
+ struct prog_instruction * pILInst;
+ GLuint uiCurInst;
+ GLboolean bR6xx;
+} r700_AssemblerBase;
+
+//Internal use
+BITS addrmode_PVSDST(PVSDST * pPVSDST);
+void setaddrmode_PVSDST(PVSDST * pPVSDST, BITS addrmode);
+void nomask_PVSDST(PVSDST * pPVSDST);
+BITS addrmode_PVSSRC(PVSSRC* pPVSSRC);
+void setaddrmode_PVSSRC(PVSSRC* pPVSSRC, BITS addrmode);
+void setswizzle_PVSSRC(PVSSRC* pPVSSRC, BITS swz);
+void noswizzle_PVSSRC(PVSSRC* pPVSSRC);
+void swizzleagain_PVSSRC(PVSSRC * pPVSSRC, BITS x, BITS y, BITS z, BITS w);
+void neg_PVSSRC(PVSSRC* pPVSSRC);
+void noneg_PVSSRC(PVSSRC* pPVSSRC);
+void flipneg_PVSSRC(PVSSRC* pPVSSRC);
+void zerocomp_PVSSRC(PVSSRC* pPVSSRC, int c);
+void onecomp_PVSSRC(PVSSRC* pPVSSRC, int c);
+BITS is_misc_component_exported(VAP_OUT_VTX_FMT_0* pOutVTXFmt0);
+BITS is_depth_component_exported(OUT_FRAGMENT_FMT_0* pFPOutFmt) ;
+GLboolean is_reduction_opcode(PVSDWORD * dest);
+GLuint GetSurfaceFormat(GLenum eType, GLuint nChannels, GLuint * pClient_size);
+
+unsigned int r700GetNumOperands(r700_AssemblerBase* pAsm);
+
+GLboolean IsTex(gl_inst_opcode Opcode);
+GLboolean IsAlu(gl_inst_opcode Opcode);
+int check_current_clause(r700_AssemblerBase* pAsm,
+ CF_CLAUSE_TYPE new_clause_type);
+GLboolean add_vfetch_instruction(r700_AssemblerBase* pAsm,
+ R700VertexInstruction* vertex_instruction_ptr);
+GLboolean add_tex_instruction(r700_AssemblerBase* pAsm,
+ R700TextureInstruction* tex_instruction_ptr);
+GLboolean assemble_vfetch_instruction(r700_AssemblerBase* pAsm,
+ GLuint gl_client_id,
+ GLuint destination_register,
+ GLuint number_of_elements,
+ GLenum dataElementType,
+ VTX_FETCH_METHOD* pFetchMethod);
+GLuint gethelpr(r700_AssemblerBase* pAsm);
+void resethelpr(r700_AssemblerBase* pAsm);
+void checkop_init(r700_AssemblerBase* pAsm);
+GLboolean mov_temp(r700_AssemblerBase* pAsm, int src);
+GLboolean checkop1(r700_AssemblerBase* pAsm);
+GLboolean checkop2(r700_AssemblerBase* pAsm);
+GLboolean checkop3(r700_AssemblerBase* pAsm);
+GLboolean assemble_src(r700_AssemblerBase *pAsm,
+ int src,
+ int fld);
+GLboolean assemble_dst(r700_AssemblerBase *pAsm);
+GLboolean tex_dst(r700_AssemblerBase *pAsm);
+GLboolean tex_src(r700_AssemblerBase *pAsm);
+GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm, GLboolean normalized);
+void initialize(r700_AssemblerBase *pAsm);
+GLboolean assemble_alu_src(R700ALUInstruction* alu_instruction_ptr,
+ int source_index,
+ PVSSRC* pSource,
+ BITS scalar_channel_index);
+GLboolean add_alu_instruction(r700_AssemblerBase* pAsm,
+ R700ALUInstruction* alu_instruction_ptr,
+ GLuint contiguous_slots_needed);
+void get_src_properties(R700ALUInstruction* alu_instruction_ptr,
+ int source_index,
+ BITS* psrc_sel,
+ BITS* psrc_rel,
+ BITS* psrc_chan,
+ BITS* psrc_neg);
+int is_cfile(BITS sel);
+int is_const(BITS sel);
+int is_gpr(BITS sel);
+GLboolean reserve_cfile(r700_AssemblerBase* pAsm,
+ GLuint sel,
+ GLuint chan);
+GLboolean reserve_gpr(r700_AssemblerBase* pAsm, GLuint sel, GLuint chan, GLuint cycle);
+GLboolean cycle_for_scalar_bank_swizzle(const int swiz, const int sel, GLuint* pCycle);
+GLboolean cycle_for_vector_bank_swizzle(const int swiz, const int sel, GLuint* pCycle);
+GLboolean check_scalar(r700_AssemblerBase* pAsm,
+ R700ALUInstruction* alu_instruction_ptr);
+GLboolean check_vector(r700_AssemblerBase* pAsm,
+ R700ALUInstruction* alu_instruction_ptr);
+GLboolean assemble_alu_instruction(r700_AssemblerBase *pAsm);
+GLboolean next_ins(r700_AssemblerBase *pAsm);
+GLboolean assemble_math_function(r700_AssemblerBase* pAsm, BITS opcode);
+GLboolean assemble_ABS(r700_AssemblerBase *pAsm);
+GLboolean assemble_ADD(r700_AssemblerBase *pAsm);
+GLboolean assemble_BAD(char *opcode_str);
+GLboolean assemble_CMP(r700_AssemblerBase *pAsm);
+GLboolean assemble_COS(r700_AssemblerBase *pAsm);
+GLboolean assemble_DOT(r700_AssemblerBase *pAsm);
+GLboolean assemble_DST(r700_AssemblerBase *pAsm);
+GLboolean assemble_EX2(r700_AssemblerBase *pAsm);
+GLboolean assemble_FLR(r700_AssemblerBase *pAsm);
+GLboolean assemble_FLR_INT(r700_AssemblerBase *pAsm);
+GLboolean assemble_FRC(r700_AssemblerBase *pAsm);
+GLboolean assemble_KIL(r700_AssemblerBase *pAsm);
+GLboolean assemble_LG2(r700_AssemblerBase *pAsm);
+GLboolean assemble_LRP(r700_AssemblerBase *pAsm);
+GLboolean assemble_MAD(r700_AssemblerBase *pAsm);
+GLboolean assemble_LIT(r700_AssemblerBase *pAsm);
+GLboolean assemble_MAX(r700_AssemblerBase *pAsm);
+GLboolean assemble_MIN(r700_AssemblerBase *pAsm);
+GLboolean assemble_MOV(r700_AssemblerBase *pAsm);
+GLboolean assemble_MUL(r700_AssemblerBase *pAsm);
+GLboolean assemble_POW(r700_AssemblerBase *pAsm);
+GLboolean assemble_RCP(r700_AssemblerBase *pAsm);
+GLboolean assemble_RSQ(r700_AssemblerBase *pAsm);
+GLboolean assemble_SIN(r700_AssemblerBase *pAsm);
+GLboolean assemble_SCS(r700_AssemblerBase *pAsm);
+GLboolean assemble_SGE(r700_AssemblerBase *pAsm);
+GLboolean assemble_SLT(r700_AssemblerBase *pAsm);
+GLboolean assemble_STP(r700_AssemblerBase *pAsm);
+GLboolean assemble_TEX(r700_AssemblerBase *pAsm);
+GLboolean assemble_XPD(r700_AssemblerBase *pAsm);
+GLboolean assemble_EXPORT(r700_AssemblerBase *pAsm);
+GLboolean assemble_IF(r700_AssemblerBase *pAsm);
+GLboolean assemble_ENDIF(r700_AssemblerBase *pAsm);
+
+GLboolean Process_Export(r700_AssemblerBase* pAsm,
+ GLuint type,
+ GLuint export_starting_index,
+ GLuint export_count,
+ GLuint starting_register_number,
+ GLboolean is_depth_export);
+GLboolean Move_Depth_Exports_To_Correct_Channels(r700_AssemblerBase *pAsm,
+ BITS depth_channel_select);
+
+
+//Interface
+GLboolean AssembleInstr(GLuint uiNumberInsts,
+ struct prog_instruction *pILInst,
+ r700_AssemblerBase *pR700AsmCode);
+GLboolean Process_Fragment_Exports(r700_AssemblerBase *pR700AsmCode, GLbitfield OutputsWritten);
+GLboolean Process_Vertex_Exports(r700_AssemblerBase *pR700AsmCode, GLbitfield OutputsWritten);
+
+int Init_r700_AssemblerBase(SHADER_PIPE_TYPE spt, r700_AssemblerBase* pAsm, R700_Shader* pShader);
+GLboolean Clean_Up_Assembler(r700_AssemblerBase *pR700AsmCode);
+
+#endif //_R700_ASSEMBLER_H_
diff --git a/src/mesa/drivers/dri/r600/r700_chip.c b/src/mesa/drivers/dri/r600/r700_chip.c
new file mode 100644
index 0000000000..1b56059197
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_chip.c
@@ -0,0 +1,1274 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#include "main/imports.h"
+#include "main/glheader.h"
+#include "main/simple_list.h"
+
+#include "r600_context.h"
+#include "r600_cmdbuf.h"
+
+#include "r700_state.h"
+#include "r600_tex.h"
+#include "r700_oglprog.h"
+#include "r700_fragprog.h"
+#include "r700_vertprog.h"
+#include "r700_ioctl.h"
+
+#include "radeon_mipmap_tree.h"
+
+static void r700SendTexState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ struct radeon_bo *bo = NULL;
+ unsigned int i;
+ BATCH_LOCALS(&context->radeon);
+
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ for (i = 0; i < R700_TEXTURE_NUMBERUNITS; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled) {
+ radeonTexObj *t = r700->textures[i];
+ if (t) {
+ if (!t->image_override)
+ bo = t->mt->bo;
+ else
+ bo = t->bo;
+ if (bo) {
+
+ r700SyncSurf(context, bo,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM,
+ 0, TC_ACTION_ENA_bit);
+
+ BEGIN_BATCH_NO_AUTOSTATE(9 + 4);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_RESOURCE, 7));
+ R600_OUT_BATCH(i * 7);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE0);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE1);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE2);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE3);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE4);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE5);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE6);
+ R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE2,
+ bo,
+ 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE3,
+ bo,
+ r700->textures[i]->SQ_TEX_RESOURCE3,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ END_BATCH();
+ COMMIT_BATCH();
+ }
+ }
+ }
+ }
+}
+
+static void r700SendTexSamplerState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ unsigned int i;
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ for (i = 0; i < R700_TEXTURE_NUMBERUNITS; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled) {
+ radeonTexObj *t = r700->textures[i];
+ if (t) {
+ BEGIN_BATCH_NO_AUTOSTATE(5);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_SAMPLER, 3));
+ R600_OUT_BATCH(i * 3);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_SAMPLER0);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_SAMPLER1);
+ R600_OUT_BATCH(r700->textures[i]->SQ_TEX_SAMPLER2);
+ END_BATCH();
+ COMMIT_BATCH();
+ }
+ }
+ }
+}
+
+static void r700SendTexBorderColorState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ unsigned int i;
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ for (i = 0; i < R700_TEXTURE_NUMBERUNITS; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled) {
+ radeonTexObj *t = r700->textures[i];
+ if (t) {
+ BEGIN_BATCH_NO_AUTOSTATE(2 + 4);
+ R600_OUT_BATCH_REGSEQ((TD_PS_SAMPLER0_BORDER_RED + (i * 16)), 4);
+ R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_RED);
+ R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_GREEN);
+ R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_BLUE);
+ R600_OUT_BATCH(r700->textures[i]->TD_PS_SAMPLER0_BORDER_ALPHA);
+ END_BATCH();
+ COMMIT_BATCH();
+ }
+ }
+ }
+}
+
+static void r700SetupVTXConstants(GLcontext * ctx,
+ unsigned int nStreamID,
+ void * pAos,
+ unsigned int size, /* number of elements in vector */
+ unsigned int stride,
+ unsigned int count) /* number of vectors in stream */
+{
+ context_t *context = R700_CONTEXT(ctx);
+ struct radeon_aos * paos = (struct radeon_aos *)pAos;
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ unsigned int uSQ_VTX_CONSTANT_WORD0_0;
+ unsigned int uSQ_VTX_CONSTANT_WORD1_0;
+ unsigned int uSQ_VTX_CONSTANT_WORD2_0 = 0;
+ unsigned int uSQ_VTX_CONSTANT_WORD3_0 = 0;
+ unsigned int uSQ_VTX_CONSTANT_WORD6_0 = 0;
+
+ if (!paos->bo)
+ return;
+
+ if ((context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV610) ||
+ (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV620) ||
+ (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RS780) ||
+ (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RS880) ||
+ (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV710))
+ r700SyncSurf(context, paos->bo, RADEON_GEM_DOMAIN_GTT, 0, TC_ACTION_ENA_bit);
+ else
+ r700SyncSurf(context, paos->bo, RADEON_GEM_DOMAIN_GTT, 0, VC_ACTION_ENA_bit);
+
+ uSQ_VTX_CONSTANT_WORD0_0 = paos->offset;
+ uSQ_VTX_CONSTANT_WORD1_0 = count * (size * 4) - 1;
+
+ SETfield(uSQ_VTX_CONSTANT_WORD2_0, 0, BASE_ADDRESS_HI_shift, BASE_ADDRESS_HI_mask); /* TODO */
+ SETfield(uSQ_VTX_CONSTANT_WORD2_0, stride, SQ_VTX_CONSTANT_WORD2_0__STRIDE_shift,
+ SQ_VTX_CONSTANT_WORD2_0__STRIDE_mask);
+ SETfield(uSQ_VTX_CONSTANT_WORD2_0, GetSurfaceFormat(GL_FLOAT, size, NULL),
+ SQ_VTX_CONSTANT_WORD2_0__DATA_FORMAT_shift,
+ SQ_VTX_CONSTANT_WORD2_0__DATA_FORMAT_mask); /* TODO : trace back api for initial data type, not only GL_FLOAT */
+ SETfield(uSQ_VTX_CONSTANT_WORD2_0, SQ_NUM_FORMAT_SCALED,
+ SQ_VTX_CONSTANT_WORD2_0__NUM_FORMAT_ALL_shift, SQ_VTX_CONSTANT_WORD2_0__NUM_FORMAT_ALL_mask);
+ SETbit(uSQ_VTX_CONSTANT_WORD2_0, SQ_VTX_CONSTANT_WORD2_0__FORMAT_COMP_ALL_bit);
+
+ SETfield(uSQ_VTX_CONSTANT_WORD3_0, 1, MEM_REQUEST_SIZE_shift, MEM_REQUEST_SIZE_mask);
+ SETfield(uSQ_VTX_CONSTANT_WORD6_0, SQ_TEX_VTX_VALID_BUFFER,
+ SQ_TEX_RESOURCE_WORD6_0__TYPE_shift, SQ_TEX_RESOURCE_WORD6_0__TYPE_mask);
+
+ BEGIN_BATCH_NO_AUTOSTATE(9 + 2);
+
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_RESOURCE, 7));
+ R600_OUT_BATCH((nStreamID + SQ_FETCH_RESOURCE_VS_OFFSET) * FETCH_RESOURCE_STRIDE);
+ R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD0_0);
+ R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD1_0);
+ R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD2_0);
+ R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD3_0);
+ R600_OUT_BATCH(0);
+ R600_OUT_BATCH(0);
+ R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD6_0);
+ R600_OUT_BATCH_RELOC(uSQ_VTX_CONSTANT_WORD0_0,
+ paos->bo,
+ uSQ_VTX_CONSTANT_WORD0_0,
+ RADEON_GEM_DOMAIN_GTT, 0, 0);
+ END_BATCH();
+ COMMIT_BATCH();
+
+}
+
+void r700SetupStreams(GLcontext *ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ struct r700_vertex_program *vp = context->selected_vp;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *vb = &tnl->vb;
+ unsigned int i, j = 0;
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ R600_STATECHANGE(context, vtx);
+
+ for(i=0; i<VERT_ATTRIB_MAX; i++) {
+ if(vp->mesa_program->Base.InputsRead & (1 << i)) {
+ rcommon_emit_vector(ctx,
+ &context->radeon.tcl.aos[j],
+ vb->AttribPtr[i]->data,
+ vb->AttribPtr[i]->size,
+ vb->AttribPtr[i]->stride,
+ vb->Count);
+ j++;
+ }
+ }
+ context->radeon.tcl.aos_count = j;
+}
+
+static void r700SendVTXState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ struct r700_vertex_program *vp = context->selected_vp;
+ unsigned int i, j = 0;
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ if (context->radeon.tcl.aos_count == 0)
+ return;
+
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, 1));
+ R600_OUT_BATCH(mmSQ_VTX_BASE_VTX_LOC - ASIC_CTL_CONST_BASE_INDEX);
+ R600_OUT_BATCH(0);
+
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, 1));
+ R600_OUT_BATCH(mmSQ_VTX_START_INST_LOC - ASIC_CTL_CONST_BASE_INDEX);
+ R600_OUT_BATCH(0);
+ END_BATCH();
+ COMMIT_BATCH();
+
+ for(i=0; i<VERT_ATTRIB_MAX; i++) {
+ if(vp->mesa_program->Base.InputsRead & (1 << i)) {
+ /* currently aos are packed */
+ r700SetupVTXConstants(ctx,
+ i,
+ (void*)(&context->radeon.tcl.aos[j]),
+ (unsigned int)context->radeon.tcl.aos[j].components,
+ (unsigned int)context->radeon.tcl.aos[j].stride * 4,
+ (unsigned int)context->radeon.tcl.aos[j].count);
+ j++;
+ }
+ }
+}
+
+static void r700SetRenderTarget(context_t *context, int id)
+{
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ struct radeon_renderbuffer *rrb;
+ unsigned int nPitchInPixel;
+
+ rrb = radeon_get_colorbuffer(&context->radeon);
+ if (!rrb || !rrb->bo) {
+ return;
+ }
+
+ R600_STATECHANGE(context, cb_target);
+
+ /* color buffer */
+ r700->render_target[id].CB_COLOR0_BASE.u32All = context->radeon.state.color.draw_offset;
+
+ nPitchInPixel = rrb->pitch/rrb->cpp;
+ SETfield(r700->render_target[id].CB_COLOR0_SIZE.u32All, (nPitchInPixel/8)-1,
+ PITCH_TILE_MAX_shift, PITCH_TILE_MAX_mask);
+ SETfield(r700->render_target[id].CB_COLOR0_SIZE.u32All, ( (nPitchInPixel * context->radeon.radeonScreen->driScreen->fbHeight)/64 )-1,
+ SLICE_TILE_MAX_shift, SLICE_TILE_MAX_mask);
+ r700->render_target[id].CB_COLOR0_BASE.u32All = 0;
+ SETfield(r700->render_target[id].CB_COLOR0_INFO.u32All, ENDIAN_NONE, ENDIAN_shift, ENDIAN_mask);
+ SETfield(r700->render_target[id].CB_COLOR0_INFO.u32All, ARRAY_LINEAR_GENERAL,
+ CB_COLOR0_INFO__ARRAY_MODE_shift, CB_COLOR0_INFO__ARRAY_MODE_mask);
+ if(4 == rrb->cpp)
+ {
+ SETfield(r700->render_target[id].CB_COLOR0_INFO.u32All, COLOR_8_8_8_8,
+ CB_COLOR0_INFO__FORMAT_shift, CB_COLOR0_INFO__FORMAT_mask);
+ SETfield(r700->render_target[id].CB_COLOR0_INFO.u32All, SWAP_ALT, COMP_SWAP_shift, COMP_SWAP_mask);
+ }
+ else
+ {
+ SETfield(r700->render_target[id].CB_COLOR0_INFO.u32All, COLOR_5_6_5,
+ CB_COLOR0_INFO__FORMAT_shift, CB_COLOR0_INFO__FORMAT_mask);
+ SETfield(r700->render_target[id].CB_COLOR0_INFO.u32All, SWAP_ALT_REV,
+ COMP_SWAP_shift, COMP_SWAP_mask);
+ }
+ SETbit(r700->render_target[id].CB_COLOR0_INFO.u32All, SOURCE_FORMAT_bit);
+ SETbit(r700->render_target[id].CB_COLOR0_INFO.u32All, BLEND_CLAMP_bit);
+ SETfield(r700->render_target[id].CB_COLOR0_INFO.u32All, NUMBER_UNORM, NUMBER_TYPE_shift, NUMBER_TYPE_mask);
+
+ r700->render_target[id].enabled = GL_TRUE;
+}
+
+static void r700SetDepthTarget(context_t *context)
+{
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ struct radeon_renderbuffer *rrb;
+ unsigned int nPitchInPixel;
+
+ rrb = radeon_get_depthbuffer(&context->radeon);
+ if (!rrb)
+ return;
+
+ R600_STATECHANGE(context, db_target);
+
+ /* depth buf */
+ r700->DB_DEPTH_SIZE.u32All = 0;
+ r700->DB_DEPTH_BASE.u32All = 0;
+ r700->DB_DEPTH_INFO.u32All = 0;
+ r700->DB_DEPTH_VIEW.u32All = 0;
+
+ nPitchInPixel = rrb->pitch/rrb->cpp;
+
+ SETfield(r700->DB_DEPTH_SIZE.u32All, (nPitchInPixel/8)-1,
+ PITCH_TILE_MAX_shift, PITCH_TILE_MAX_mask);
+ SETfield(r700->DB_DEPTH_SIZE.u32All, ( (nPitchInPixel * context->radeon.radeonScreen->driScreen->fbHeight)/64 )-1,
+ SLICE_TILE_MAX_shift, SLICE_TILE_MAX_mask); /* size in pixel / 64 - 1 */
+
+ if(4 == rrb->cpp)
+ {
+ SETfield(r700->DB_DEPTH_INFO.u32All, DEPTH_8_24,
+ DB_DEPTH_INFO__FORMAT_shift, DB_DEPTH_INFO__FORMAT_mask);
+ }
+ else
+ {
+ SETfield(r700->DB_DEPTH_INFO.u32All, DEPTH_16,
+ DB_DEPTH_INFO__FORMAT_shift, DB_DEPTH_INFO__FORMAT_mask);
+ }
+ SETfield(r700->DB_DEPTH_INFO.u32All, ARRAY_2D_TILED_THIN1,
+ DB_DEPTH_INFO__ARRAY_MODE_shift, DB_DEPTH_INFO__ARRAY_MODE_mask);
+ /* r700->DB_PREFETCH_LIMIT.bits.DEPTH_HEIGHT_TILE_MAX = (context->currentDraw->h >> 3) - 1; */ /* z buffer sie may much bigger than what need, so use actual used h. */
+}
+
+static void r700SendDepthTargetState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ struct radeon_renderbuffer *rrb;
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ rrb = radeon_get_depthbuffer(&context->radeon);
+ if (!rrb || !rrb->bo) {
+ fprintf(stderr, "no rrb\n");
+ return;
+ }
+
+ r700SetDepthTarget(context);
+
+ BEGIN_BATCH_NO_AUTOSTATE(8 + 2);
+ R600_OUT_BATCH_REGSEQ(DB_DEPTH_SIZE, 2);
+ R600_OUT_BATCH(r700->DB_DEPTH_SIZE.u32All);
+ R600_OUT_BATCH(r700->DB_DEPTH_VIEW.u32All);
+ R600_OUT_BATCH_REGSEQ(DB_DEPTH_BASE, 2);
+ R600_OUT_BATCH(r700->DB_DEPTH_BASE.u32All);
+ R600_OUT_BATCH(r700->DB_DEPTH_INFO.u32All);
+ R600_OUT_BATCH_RELOC(r700->DB_DEPTH_BASE.u32All,
+ rrb->bo,
+ r700->DB_DEPTH_BASE.u32All,
+ 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ END_BATCH();
+
+ if ((context->radeon.radeonScreen->chip_family > CHIP_FAMILY_R600) &&
+ (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)) {
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SURFACE_BASE_UPDATE, 0));
+ R600_OUT_BATCH(1 << 0);
+ END_BATCH();
+ }
+
+ COMMIT_BATCH();
+
+}
+
+static void r700SendRenderTargetState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ struct radeon_renderbuffer *rrb;
+ BATCH_LOCALS(&context->radeon);
+ int id = 0;
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ rrb = radeon_get_colorbuffer(&context->radeon);
+ if (!rrb || !rrb->bo) {
+ fprintf(stderr, "no rrb\n");
+ return;
+ }
+
+ r700SetRenderTarget(context, 0);
+
+ if (id > R700_MAX_RENDER_TARGETS)
+ return;
+
+ if (!r700->render_target[id].enabled)
+ return;
+
+ BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+ R600_OUT_BATCH_REGSEQ(CB_COLOR0_BASE + (4 * id), 1);
+ R600_OUT_BATCH(r700->render_target[id].CB_COLOR0_BASE.u32All);
+ R600_OUT_BATCH_RELOC(r700->render_target[id].CB_COLOR0_BASE.u32All,
+ rrb->bo,
+ r700->render_target[id].CB_COLOR0_BASE.u32All,
+ 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ END_BATCH();
+
+ if ((context->radeon.radeonScreen->chip_family > CHIP_FAMILY_R600) &&
+ (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)) {
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SURFACE_BASE_UPDATE, 0));
+ R600_OUT_BATCH((2 << id));
+ END_BATCH();
+ }
+
+ BEGIN_BATCH_NO_AUTOSTATE(18);
+ R600_OUT_BATCH_REGVAL(CB_COLOR0_SIZE + (4 * id), r700->render_target[id].CB_COLOR0_SIZE.u32All);
+ R600_OUT_BATCH_REGVAL(CB_COLOR0_VIEW + (4 * id), r700->render_target[id].CB_COLOR0_VIEW.u32All);
+ R600_OUT_BATCH_REGVAL(CB_COLOR0_INFO + (4 * id), r700->render_target[id].CB_COLOR0_INFO.u32All);
+ R600_OUT_BATCH_REGVAL(CB_COLOR0_TILE + (4 * id), r700->render_target[id].CB_COLOR0_TILE.u32All);
+ R600_OUT_BATCH_REGVAL(CB_COLOR0_FRAG + (4 * id), r700->render_target[id].CB_COLOR0_FRAG.u32All);
+ R600_OUT_BATCH_REGVAL(CB_COLOR0_MASK + (4 * id), r700->render_target[id].CB_COLOR0_MASK.u32All);
+ END_BATCH();
+
+ COMMIT_BATCH();
+
+}
+
+static void r700SendPSState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ struct radeon_bo * pbo;
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ pbo = (struct radeon_bo *)r700GetActiveFpShaderBo(GL_CONTEXT(context));
+
+ if (!pbo)
+ return;
+
+ r700SyncSurf(context, pbo, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit);
+
+ BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+ R600_OUT_BATCH_REGSEQ(SQ_PGM_START_PS, 1);
+ R600_OUT_BATCH(r700->ps.SQ_PGM_START_PS.u32All);
+ R600_OUT_BATCH_RELOC(r700->ps.SQ_PGM_START_PS.u32All,
+ pbo,
+ r700->ps.SQ_PGM_START_PS.u32All,
+ RADEON_GEM_DOMAIN_GTT, 0, 0);
+ END_BATCH();
+
+ BEGIN_BATCH_NO_AUTOSTATE(9);
+ R600_OUT_BATCH_REGVAL(SQ_PGM_RESOURCES_PS, r700->ps.SQ_PGM_RESOURCES_PS.u32All);
+ R600_OUT_BATCH_REGVAL(SQ_PGM_EXPORTS_PS, r700->ps.SQ_PGM_EXPORTS_PS.u32All);
+ R600_OUT_BATCH_REGVAL(SQ_PGM_CF_OFFSET_PS, r700->ps.SQ_PGM_CF_OFFSET_PS.u32All);
+ END_BATCH();
+
+ COMMIT_BATCH();
+
+}
+
+static void r700SendVSState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ struct radeon_bo * pbo;
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ pbo = (struct radeon_bo *)r700GetActiveVpShaderBo(GL_CONTEXT(context));
+
+ if (!pbo)
+ return;
+
+ r700SyncSurf(context, pbo, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit);
+
+ BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+ R600_OUT_BATCH_REGSEQ(SQ_PGM_START_VS, 1);
+ R600_OUT_BATCH(r700->vs.SQ_PGM_START_VS.u32All);
+ R600_OUT_BATCH_RELOC(r700->vs.SQ_PGM_START_VS.u32All,
+ pbo,
+ r700->vs.SQ_PGM_START_VS.u32All,
+ RADEON_GEM_DOMAIN_GTT, 0, 0);
+ END_BATCH();
+
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ R600_OUT_BATCH_REGVAL(SQ_PGM_RESOURCES_VS, r700->vs.SQ_PGM_RESOURCES_VS.u32All);
+ R600_OUT_BATCH_REGVAL(SQ_PGM_CF_OFFSET_VS, r700->vs.SQ_PGM_CF_OFFSET_VS.u32All);
+ END_BATCH();
+
+ COMMIT_BATCH();
+}
+
+static void r700SendFSState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ struct radeon_bo * pbo;
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ /* XXX fixme
+ * R6xx chips require a FS be emitted, even if it's not used.
+ * since we aren't using FS yet, just send the VS address to make
+ * the kernel command checker happy
+ */
+ pbo = (struct radeon_bo *)r700GetActiveVpShaderBo(GL_CONTEXT(context));
+ r700->fs.SQ_PGM_START_FS.u32All = r700->vs.SQ_PGM_START_VS.u32All;
+ r700->fs.SQ_PGM_RESOURCES_FS.u32All = 0;
+ r700->fs.SQ_PGM_CF_OFFSET_FS.u32All = 0;
+ /* XXX */
+
+ if (!pbo)
+ return;
+
+ r700SyncSurf(context, pbo, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit);
+
+ BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+ R600_OUT_BATCH_REGSEQ(SQ_PGM_START_FS, 1);
+ R600_OUT_BATCH(r700->fs.SQ_PGM_START_FS.u32All);
+ R600_OUT_BATCH_RELOC(r700->fs.SQ_PGM_START_FS.u32All,
+ pbo,
+ r700->fs.SQ_PGM_START_FS.u32All,
+ RADEON_GEM_DOMAIN_GTT, 0, 0);
+ END_BATCH();
+
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ R600_OUT_BATCH_REGVAL(SQ_PGM_RESOURCES_FS, r700->fs.SQ_PGM_RESOURCES_FS.u32All);
+ R600_OUT_BATCH_REGVAL(SQ_PGM_CF_OFFSET_FS, r700->fs.SQ_PGM_CF_OFFSET_FS.u32All);
+ END_BATCH();
+
+ COMMIT_BATCH();
+
+}
+
+static void r700SendViewportState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ int id = 0;
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ if (id > R700_MAX_VIEWPORTS)
+ return;
+
+ if (!r700->viewport[id].enabled)
+ return;
+
+ BEGIN_BATCH_NO_AUTOSTATE(16);
+ R600_OUT_BATCH_REGSEQ(PA_SC_VPORT_SCISSOR_0_TL + (8 * id), 2);
+ R600_OUT_BATCH(r700->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All);
+ R600_OUT_BATCH(r700->viewport[id].PA_SC_VPORT_SCISSOR_0_BR.u32All);
+ R600_OUT_BATCH_REGSEQ(PA_SC_VPORT_ZMIN_0 + (8 * id), 2);
+ R600_OUT_BATCH(r700->viewport[id].PA_SC_VPORT_ZMIN_0.u32All);
+ R600_OUT_BATCH(r700->viewport[id].PA_SC_VPORT_ZMAX_0.u32All);
+ R600_OUT_BATCH_REGSEQ(PA_CL_VPORT_XSCALE_0 + (24 * id), 6);
+ R600_OUT_BATCH(r700->viewport[id].PA_CL_VPORT_XSCALE.u32All);
+ R600_OUT_BATCH(r700->viewport[id].PA_CL_VPORT_XOFFSET.u32All);
+ R600_OUT_BATCH(r700->viewport[id].PA_CL_VPORT_YSCALE.u32All);
+ R600_OUT_BATCH(r700->viewport[id].PA_CL_VPORT_YOFFSET.u32All);
+ R600_OUT_BATCH(r700->viewport[id].PA_CL_VPORT_ZSCALE.u32All);
+ R600_OUT_BATCH(r700->viewport[id].PA_CL_VPORT_ZOFFSET.u32All);
+ END_BATCH();
+
+ COMMIT_BATCH();
+
+}
+
+static void r700SendSQConfig(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ BEGIN_BATCH_NO_AUTOSTATE(34);
+ R600_OUT_BATCH_REGSEQ(SQ_CONFIG, 6);
+ R600_OUT_BATCH(r700->sq_config.SQ_CONFIG.u32All);
+ R600_OUT_BATCH(r700->sq_config.SQ_GPR_RESOURCE_MGMT_1.u32All);
+ R600_OUT_BATCH(r700->sq_config.SQ_GPR_RESOURCE_MGMT_2.u32All);
+ R600_OUT_BATCH(r700->sq_config.SQ_THREAD_RESOURCE_MGMT.u32All);
+ R600_OUT_BATCH(r700->sq_config.SQ_STACK_RESOURCE_MGMT_1.u32All);
+ R600_OUT_BATCH(r700->sq_config.SQ_STACK_RESOURCE_MGMT_2.u32All);
+
+ R600_OUT_BATCH_REGVAL(TA_CNTL_AUX, r700->TA_CNTL_AUX.u32All);
+ R600_OUT_BATCH_REGVAL(VC_ENHANCE, r700->VC_ENHANCE.u32All);
+ R600_OUT_BATCH_REGVAL(R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, r700->SQ_DYN_GPR_CNTL_PS_FLUSH_REQ.u32All);
+ R600_OUT_BATCH_REGVAL(DB_DEBUG, r700->DB_DEBUG.u32All);
+ R600_OUT_BATCH_REGVAL(DB_WATERMARKS, r700->DB_WATERMARKS.u32All);
+
+ R600_OUT_BATCH_REGSEQ(SQ_ESGS_RING_ITEMSIZE, 9);
+ R600_OUT_BATCH(r700->SQ_ESGS_RING_ITEMSIZE.u32All);
+ R600_OUT_BATCH(r700->SQ_GSVS_RING_ITEMSIZE.u32All);
+ R600_OUT_BATCH(r700->SQ_ESTMP_RING_ITEMSIZE.u32All);
+ R600_OUT_BATCH(r700->SQ_GSTMP_RING_ITEMSIZE.u32All);
+ R600_OUT_BATCH(r700->SQ_VSTMP_RING_ITEMSIZE.u32All);
+ R600_OUT_BATCH(r700->SQ_PSTMP_RING_ITEMSIZE.u32All);
+ R600_OUT_BATCH(r700->SQ_FBUF_RING_ITEMSIZE.u32All);
+ R600_OUT_BATCH(r700->SQ_REDUC_RING_ITEMSIZE.u32All);
+ R600_OUT_BATCH(r700->SQ_GS_VERT_ITEMSIZE.u32All);
+ END_BATCH();
+
+ COMMIT_BATCH();
+}
+
+static void r700SendUCPState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ int i;
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ for (i = 0; i < R700_MAX_UCP; i++) {
+ if (r700->ucp[i].enabled) {
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ R600_OUT_BATCH_REGSEQ(PA_CL_UCP_0_X + (16 * i), 4);
+ R600_OUT_BATCH(r700->ucp[i].PA_CL_UCP_0_X.u32All);
+ R600_OUT_BATCH(r700->ucp[i].PA_CL_UCP_0_Y.u32All);
+ R600_OUT_BATCH(r700->ucp[i].PA_CL_UCP_0_Z.u32All);
+ R600_OUT_BATCH(r700->ucp[i].PA_CL_UCP_0_W.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+ }
+ }
+}
+
+static void r700SendSPIState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ unsigned int ui;
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ BEGIN_BATCH_NO_AUTOSTATE(59 + R700_MAX_SHADER_EXPORTS);
+
+ R600_OUT_BATCH_REGSEQ(SQ_VTX_SEMANTIC_0, 32);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_0.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_1.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_2.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_3.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_4.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_5.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_6.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_7.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_8.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_9.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_10.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_11.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_12.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_13.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_14.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_15.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_16.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_17.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_18.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_19.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_20.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_21.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_22.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_23.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_24.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_25.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_26.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_27.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_28.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_29.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_30.u32All);
+ R600_OUT_BATCH(r700->SQ_VTX_SEMANTIC_31.u32All);
+
+ R600_OUT_BATCH_REGSEQ(SPI_VS_OUT_ID_0, 10);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_0.u32All);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_1.u32All);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_2.u32All);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_3.u32All);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_4.u32All);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_5.u32All);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_6.u32All);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_7.u32All);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_8.u32All);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_ID_9.u32All);
+
+ R600_OUT_BATCH_REGSEQ(SPI_VS_OUT_CONFIG, 9);
+ R600_OUT_BATCH(r700->SPI_VS_OUT_CONFIG.u32All);
+ R600_OUT_BATCH(r700->SPI_THREAD_GROUPING.u32All);
+ R600_OUT_BATCH(r700->SPI_PS_IN_CONTROL_0.u32All);
+ R600_OUT_BATCH(r700->SPI_PS_IN_CONTROL_1.u32All);
+ R600_OUT_BATCH(r700->SPI_INTERP_CONTROL_0.u32All);
+ R600_OUT_BATCH(r700->SPI_INPUT_Z.u32All);
+ R600_OUT_BATCH(r700->SPI_FOG_CNTL.u32All);
+ R600_OUT_BATCH(r700->SPI_FOG_FUNC_SCALE.u32All);
+ R600_OUT_BATCH(r700->SPI_FOG_FUNC_BIAS.u32All);
+
+ R600_OUT_BATCH_REGSEQ(SPI_PS_INPUT_CNTL_0, R700_MAX_SHADER_EXPORTS);
+ for(ui = 0; ui < R700_MAX_SHADER_EXPORTS; ui++)
+ R600_OUT_BATCH(r700->SPI_PS_INPUT_CNTL[ui].u32All);
+
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendVGTState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ BEGIN_BATCH_NO_AUTOSTATE(41);
+
+ R600_OUT_BATCH_REGSEQ(VGT_MAX_VTX_INDX, 4);
+ R600_OUT_BATCH(r700->VGT_MAX_VTX_INDX.u32All);
+ R600_OUT_BATCH(r700->VGT_MIN_VTX_INDX.u32All);
+ R600_OUT_BATCH(r700->VGT_INDX_OFFSET.u32All);
+ R600_OUT_BATCH(r700->VGT_MULTI_PRIM_IB_RESET_INDX.u32All);
+
+ R600_OUT_BATCH_REGSEQ(VGT_OUTPUT_PATH_CNTL, 13);
+ R600_OUT_BATCH(r700->VGT_OUTPUT_PATH_CNTL.u32All);
+ R600_OUT_BATCH(r700->VGT_HOS_CNTL.u32All);
+ R600_OUT_BATCH(r700->VGT_HOS_MAX_TESS_LEVEL.u32All);
+ R600_OUT_BATCH(r700->VGT_HOS_MIN_TESS_LEVEL.u32All);
+ R600_OUT_BATCH(r700->VGT_HOS_REUSE_DEPTH.u32All);
+ R600_OUT_BATCH(r700->VGT_GROUP_PRIM_TYPE.u32All);
+ R600_OUT_BATCH(r700->VGT_GROUP_FIRST_DECR.u32All);
+ R600_OUT_BATCH(r700->VGT_GROUP_DECR.u32All);
+ R600_OUT_BATCH(r700->VGT_GROUP_VECT_0_CNTL.u32All);
+ R600_OUT_BATCH(r700->VGT_GROUP_VECT_1_CNTL.u32All);
+ R600_OUT_BATCH(r700->VGT_GROUP_VECT_0_FMT_CNTL.u32All);
+ R600_OUT_BATCH(r700->VGT_GROUP_VECT_1_FMT_CNTL.u32All);
+ R600_OUT_BATCH(r700->VGT_GS_MODE.u32All);
+
+ R600_OUT_BATCH_REGVAL(VGT_PRIMITIVEID_EN, r700->VGT_PRIMITIVEID_EN.u32All);
+ R600_OUT_BATCH_REGVAL(VGT_MULTI_PRIM_IB_RESET_EN, r700->VGT_MULTI_PRIM_IB_RESET_EN.u32All);
+ R600_OUT_BATCH_REGVAL(VGT_INSTANCE_STEP_RATE_0, r700->VGT_INSTANCE_STEP_RATE_0.u32All);
+ R600_OUT_BATCH_REGVAL(VGT_INSTANCE_STEP_RATE_1, r700->VGT_INSTANCE_STEP_RATE_1.u32All);
+
+ R600_OUT_BATCH_REGSEQ(VGT_STRMOUT_EN, 3);
+ R600_OUT_BATCH(r700->VGT_STRMOUT_EN.u32All);
+ R600_OUT_BATCH(r700->VGT_REUSE_OFF.u32All);
+ R600_OUT_BATCH(r700->VGT_VTX_CNT_EN.u32All);
+
+ R600_OUT_BATCH_REGVAL(VGT_STRMOUT_BUFFER_EN, r700->VGT_STRMOUT_BUFFER_EN.u32All);
+
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendSXState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ BEGIN_BATCH_NO_AUTOSTATE(9);
+ R600_OUT_BATCH_REGVAL(SX_MISC, r700->SX_MISC.u32All);
+ R600_OUT_BATCH_REGVAL(SX_ALPHA_TEST_CONTROL, r700->SX_ALPHA_TEST_CONTROL.u32All);
+ R600_OUT_BATCH_REGVAL(SX_ALPHA_REF, r700->SX_ALPHA_REF.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendDBState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ BEGIN_BATCH_NO_AUTOSTATE(23);
+ R600_OUT_BATCH_REGVAL(DB_HTILE_DATA_BASE, r700->DB_HTILE_DATA_BASE.u32All);
+
+ R600_OUT_BATCH_REGSEQ(DB_STENCIL_CLEAR, 2);
+ R600_OUT_BATCH(r700->DB_STENCIL_CLEAR.u32All);
+ R600_OUT_BATCH(r700->DB_DEPTH_CLEAR.u32All);
+
+ R600_OUT_BATCH_REGVAL(DB_DEPTH_CONTROL, r700->DB_DEPTH_CONTROL.u32All);
+ R600_OUT_BATCH_REGVAL(DB_SHADER_CONTROL, r700->DB_SHADER_CONTROL.u32All);
+
+ R600_OUT_BATCH_REGSEQ(DB_RENDER_CONTROL, 2);
+ R600_OUT_BATCH(r700->DB_RENDER_CONTROL.u32All);
+ R600_OUT_BATCH(r700->DB_RENDER_OVERRIDE.u32All);
+
+ R600_OUT_BATCH_REGVAL(DB_HTILE_SURFACE, r700->DB_HTILE_SURFACE.u32All);
+ R600_OUT_BATCH_REGVAL(DB_ALPHA_TO_MASK, r700->DB_ALPHA_TO_MASK.u32All);
+
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendStencilState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+
+ BEGIN_BATCH_NO_AUTOSTATE(4);
+ R600_OUT_BATCH_REGSEQ(DB_STENCILREFMASK, 2);
+ R600_OUT_BATCH(r700->DB_STENCILREFMASK.u32All);
+ R600_OUT_BATCH(r700->DB_STENCILREFMASK_BF.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendCBState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770) {
+ BEGIN_BATCH_NO_AUTOSTATE(11);
+ R600_OUT_BATCH_REGSEQ(CB_CLEAR_RED, 4);
+ R600_OUT_BATCH(r700->CB_CLEAR_RED_R6XX.u32All);
+ R600_OUT_BATCH(r700->CB_CLEAR_GREEN_R6XX.u32All);
+ R600_OUT_BATCH(r700->CB_CLEAR_BLUE_R6XX.u32All);
+ R600_OUT_BATCH(r700->CB_CLEAR_ALPHA_R6XX.u32All);
+ R600_OUT_BATCH_REGSEQ(CB_FOG_RED, 3);
+ R600_OUT_BATCH(r700->CB_FOG_RED_R6XX.u32All);
+ R600_OUT_BATCH(r700->CB_FOG_GREEN_R6XX.u32All);
+ R600_OUT_BATCH(r700->CB_FOG_BLUE_R6XX.u32All);
+ END_BATCH();
+ }
+
+ BEGIN_BATCH_NO_AUTOSTATE(7);
+ R600_OUT_BATCH_REGSEQ(CB_TARGET_MASK, 2);
+ R600_OUT_BATCH(r700->CB_TARGET_MASK.u32All);
+ R600_OUT_BATCH(r700->CB_SHADER_MASK.u32All);
+ R600_OUT_BATCH_REGVAL(R7xx_CB_SHADER_CONTROL, r700->CB_SHADER_CONTROL.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendCBCLRCMPState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ R600_OUT_BATCH_REGSEQ(CB_CLRCMP_CONTROL, 4);
+ R600_OUT_BATCH(r700->CB_CLRCMP_CONTROL.u32All);
+ R600_OUT_BATCH(r700->CB_CLRCMP_SRC.u32All);
+ R600_OUT_BATCH(r700->CB_CLRCMP_DST.u32All);
+ R600_OUT_BATCH(r700->CB_CLRCMP_MSK.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendCBBlendState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ unsigned int ui;
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770) {
+ BEGIN_BATCH_NO_AUTOSTATE(3);
+ R600_OUT_BATCH_REGVAL(CB_BLEND_CONTROL, r700->CB_BLEND_CONTROL.u32All);
+ END_BATCH();
+ }
+
+ BEGIN_BATCH_NO_AUTOSTATE(3);
+ R600_OUT_BATCH_REGVAL(CB_COLOR_CONTROL, r700->CB_COLOR_CONTROL.u32All);
+ END_BATCH();
+
+ if (context->radeon.radeonScreen->chip_family > CHIP_FAMILY_R600) {
+ for (ui = 0; ui < R700_MAX_RENDER_TARGETS; ui++) {
+ if (r700->render_target[ui].enabled) {
+ BEGIN_BATCH_NO_AUTOSTATE(3);
+ R600_OUT_BATCH_REGVAL(CB_BLEND0_CONTROL + (4 * ui),
+ r700->render_target[ui].CB_BLEND0_CONTROL.u32All);
+ END_BATCH();
+ }
+ }
+ }
+
+ COMMIT_BATCH();
+}
+
+static void r700SendCBBlendColorState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ R600_OUT_BATCH_REGSEQ(CB_BLEND_RED, 4);
+ R600_OUT_BATCH(r700->CB_BLEND_RED.u32All);
+ R600_OUT_BATCH(r700->CB_BLEND_GREEN.u32All);
+ R600_OUT_BATCH(r700->CB_BLEND_BLUE.u32All);
+ R600_OUT_BATCH(r700->CB_BLEND_ALPHA.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendSUState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+
+ BEGIN_BATCH_NO_AUTOSTATE(9);
+ R600_OUT_BATCH_REGVAL(PA_SU_SC_MODE_CNTL, r700->PA_SU_SC_MODE_CNTL.u32All);
+ R600_OUT_BATCH_REGSEQ(PA_SU_POINT_SIZE, 4);
+ R600_OUT_BATCH(r700->PA_SU_POINT_SIZE.u32All);
+ R600_OUT_BATCH(r700->PA_SU_POINT_MINMAX.u32All);
+ R600_OUT_BATCH(r700->PA_SU_LINE_CNTL.u32All);
+ R600_OUT_BATCH(r700->PA_SU_VTX_CNTL.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+
+}
+
+static void r700SendPolyState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+
+ BEGIN_BATCH_NO_AUTOSTATE(10);
+ R600_OUT_BATCH_REGSEQ(PA_SU_POLY_OFFSET_DB_FMT_CNTL, 2);
+ R600_OUT_BATCH(r700->PA_SU_POLY_OFFSET_DB_FMT_CNTL.u32All);
+ R600_OUT_BATCH(r700->PA_SU_POLY_OFFSET_CLAMP.u32All);
+ R600_OUT_BATCH_REGSEQ(PA_SU_POLY_OFFSET_FRONT_SCALE, 4);
+ R600_OUT_BATCH(r700->PA_SU_POLY_OFFSET_FRONT_SCALE.u32All);
+ R600_OUT_BATCH(r700->PA_SU_POLY_OFFSET_FRONT_OFFSET.u32All);
+ R600_OUT_BATCH(r700->PA_SU_POLY_OFFSET_BACK_SCALE.u32All);
+ R600_OUT_BATCH(r700->PA_SU_POLY_OFFSET_BACK_OFFSET.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+
+}
+
+static void r700SendCLState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ BEGIN_BATCH_NO_AUTOSTATE(12);
+ R600_OUT_BATCH_REGVAL(PA_CL_CLIP_CNTL, r700->PA_CL_CLIP_CNTL.u32All);
+ R600_OUT_BATCH_REGVAL(PA_CL_VTE_CNTL, r700->PA_CL_VTE_CNTL.u32All);
+ R600_OUT_BATCH_REGVAL(PA_CL_VS_OUT_CNTL, r700->PA_CL_VS_OUT_CNTL.u32All);
+ R600_OUT_BATCH_REGVAL(PA_CL_NANINF_CNTL, r700->PA_CL_NANINF_CNTL.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendGBState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ R600_OUT_BATCH_REGSEQ(PA_CL_GB_VERT_CLIP_ADJ, 4);
+ R600_OUT_BATCH(r700->PA_CL_GB_VERT_CLIP_ADJ.u32All);
+ R600_OUT_BATCH(r700->PA_CL_GB_VERT_DISC_ADJ.u32All);
+ R600_OUT_BATCH(r700->PA_CL_GB_HORZ_CLIP_ADJ.u32All);
+ R600_OUT_BATCH(r700->PA_CL_GB_HORZ_DISC_ADJ.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendScissorState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ BEGIN_BATCH_NO_AUTOSTATE(22);
+ R600_OUT_BATCH_REGSEQ(PA_SC_SCREEN_SCISSOR_TL, 2);
+ R600_OUT_BATCH(r700->PA_SC_SCREEN_SCISSOR_TL.u32All);
+ R600_OUT_BATCH(r700->PA_SC_SCREEN_SCISSOR_BR.u32All);
+
+ R600_OUT_BATCH_REGSEQ(PA_SC_WINDOW_OFFSET, 12);
+ R600_OUT_BATCH(r700->PA_SC_WINDOW_OFFSET.u32All);
+ R600_OUT_BATCH(r700->PA_SC_WINDOW_SCISSOR_TL.u32All);
+ R600_OUT_BATCH(r700->PA_SC_WINDOW_SCISSOR_BR.u32All);
+ R600_OUT_BATCH(r700->PA_SC_CLIPRECT_RULE.u32All);
+ R600_OUT_BATCH(r700->PA_SC_CLIPRECT_0_TL.u32All);
+ R600_OUT_BATCH(r700->PA_SC_CLIPRECT_0_BR.u32All);
+ R600_OUT_BATCH(r700->PA_SC_CLIPRECT_1_TL.u32All);
+ R600_OUT_BATCH(r700->PA_SC_CLIPRECT_1_BR.u32All);
+ R600_OUT_BATCH(r700->PA_SC_CLIPRECT_2_TL.u32All);
+ R600_OUT_BATCH(r700->PA_SC_CLIPRECT_2_BR.u32All);
+ R600_OUT_BATCH(r700->PA_SC_CLIPRECT_3_TL.u32All);
+ R600_OUT_BATCH(r700->PA_SC_CLIPRECT_3_BR.u32All);
+
+ R600_OUT_BATCH_REGSEQ(PA_SC_GENERIC_SCISSOR_TL, 2);
+ R600_OUT_BATCH(r700->PA_SC_GENERIC_SCISSOR_TL.u32All);
+ R600_OUT_BATCH(r700->PA_SC_GENERIC_SCISSOR_BR.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendSCState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ BEGIN_BATCH_NO_AUTOSTATE(15);
+ R600_OUT_BATCH_REGVAL(R7xx_PA_SC_EDGERULE, r700->PA_SC_EDGERULE.u32All);
+ R600_OUT_BATCH_REGVAL(PA_SC_LINE_STIPPLE, r700->PA_SC_LINE_STIPPLE.u32All);
+ R600_OUT_BATCH_REGVAL(PA_SC_MPASS_PS_CNTL, r700->PA_SC_MPASS_PS_CNTL.u32All);
+ R600_OUT_BATCH_REGVAL(PA_SC_MODE_CNTL, r700->PA_SC_MODE_CNTL.u32All);
+ R600_OUT_BATCH_REGVAL(PA_SC_LINE_CNTL, r700->PA_SC_LINE_CNTL.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendAAState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ BATCH_LOCALS(&context->radeon);
+
+ BEGIN_BATCH_NO_AUTOSTATE(12);
+ R600_OUT_BATCH_REGVAL(PA_SC_AA_CONFIG, r700->PA_SC_AA_CONFIG.u32All);
+ R600_OUT_BATCH_REGVAL(PA_SC_AA_SAMPLE_LOCS_MCTX, r700->PA_SC_AA_SAMPLE_LOCS_MCTX.u32All);
+ R600_OUT_BATCH_REGVAL(PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX, r700->PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX.u32All);
+ R600_OUT_BATCH_REGVAL(PA_SC_AA_MASK, r700->PA_SC_AA_MASK.u32All);
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendPSConsts(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ int i;
+ BATCH_LOCALS(&context->radeon);
+
+ if (r700->ps.num_consts == 0)
+ return;
+
+ BEGIN_BATCH_NO_AUTOSTATE(2 + (r700->ps.num_consts * 4));
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_ALU_CONST, (r700->ps.num_consts * 4)));
+ /* assembler map const from very beginning. */
+ R600_OUT_BATCH(SQ_ALU_CONSTANT_PS_OFFSET * 4);
+ for (i = 0; i < r700->ps.num_consts; i++) {
+ R600_OUT_BATCH(r700->ps.consts[i][0].u32All);
+ R600_OUT_BATCH(r700->ps.consts[i][1].u32All);
+ R600_OUT_BATCH(r700->ps.consts[i][2].u32All);
+ R600_OUT_BATCH(r700->ps.consts[i][3].u32All);
+ }
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static void r700SendVSConsts(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
+ int i;
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+ if (r700->vs.num_consts == 0)
+ return;
+
+ BEGIN_BATCH_NO_AUTOSTATE(2 + (r700->vs.num_consts * 4));
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_ALU_CONST, (r700->vs.num_consts * 4)));
+ /* assembler map const from very beginning. */
+ R600_OUT_BATCH(SQ_ALU_CONSTANT_VS_OFFSET * 4);
+ for (i = 0; i < r700->vs.num_consts; i++) {
+ R600_OUT_BATCH(r700->vs.consts[i][0].u32All);
+ R600_OUT_BATCH(r700->vs.consts[i][1].u32All);
+ R600_OUT_BATCH(r700->vs.consts[i][2].u32All);
+ R600_OUT_BATCH(r700->vs.consts[i][3].u32All);
+ }
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+static int check_always(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ return atom->cmd_size;
+}
+
+static int check_cb(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ int count = 7;
+
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+ count += 11;
+ radeon_print(RADEON_STATE, RADEON_TRACE, "%s %d\n", __func__, count);
+
+ return count;
+}
+
+static int check_blnd(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ unsigned int ui;
+ int count = 3;
+
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+ count += 3;
+
+ if (context->radeon.radeonScreen->chip_family > CHIP_FAMILY_R600) {
+ for (ui = 0; ui < R700_MAX_RENDER_TARGETS; ui++) {
+ if (r700->render_target[ui].enabled)
+ count += 3;
+ }
+ }
+ radeon_print(RADEON_STATE, RADEON_TRACE, "%s %d\n", __func__, count);
+
+ return count;
+}
+
+static int check_ucp(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ int i;
+ int count = 0;
+
+ for (i = 0; i < R700_MAX_UCP; i++) {
+ if (r700->ucp[i].enabled)
+ count += 6;
+ }
+ radeon_print(RADEON_STATE, RADEON_TRACE, "%s %d\n", __func__, count);
+ return count;
+}
+
+static int check_vtx(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ int count = context->radeon.tcl.aos_count * 18;
+
+ if (count)
+ count += 6;
+
+ radeon_print(RADEON_STATE, RADEON_TRACE, "%s %d\n", __func__, count);
+ return count;
+}
+
+static int check_tx(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ unsigned int i, count = 0;
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ for (i = 0; i < R700_TEXTURE_NUMBERUNITS; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled) {
+ radeonTexObj *t = r700->textures[i];
+ if (t)
+ count++;
+ }
+ }
+ radeon_print(RADEON_STATE, RADEON_TRACE, "%s %d\n", __func__, count);
+ return count * 31;
+}
+
+static int check_ps_consts(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ int count = r700->ps.num_consts * 4;
+
+ if (count)
+ count += 2;
+ radeon_print(RADEON_STATE, RADEON_TRACE, "%s %d\n", __func__, count);
+
+ return count;
+}
+
+static int check_vs_consts(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ int count = r700->vs.num_consts * 4;
+
+ if (count)
+ count += 2;
+ radeon_print(RADEON_STATE, RADEON_TRACE, "%s %d\n", __func__, count);
+
+ return count;
+}
+
+#define ALLOC_STATE( ATOM, CHK, SZ, EMIT ) \
+do { \
+ context->atoms.ATOM.cmd_size = (SZ); \
+ context->atoms.ATOM.cmd = NULL; \
+ context->atoms.ATOM.name = #ATOM; \
+ context->atoms.ATOM.idx = 0; \
+ context->atoms.ATOM.check = check_##CHK; \
+ context->atoms.ATOM.dirty = GL_FALSE; \
+ context->atoms.ATOM.emit = (EMIT); \
+ context->radeon.hw.max_state_size += (SZ); \
+ insert_at_tail(&context->radeon.hw.atomlist, &context->atoms.ATOM); \
+} while (0)
+
+void r600InitAtoms(context_t *context)
+{
+ radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %p\n", __func__, context);
+ context->radeon.hw.max_state_size = 10 + 5 + 14; /* start 3d, idle, cb/db flush */
+
+ /* Setup the atom linked list */
+ make_empty_list(&context->radeon.hw.atomlist);
+ context->radeon.hw.atomlist.name = "atom-list";
+
+ ALLOC_STATE(sq, always, 34, r700SendSQConfig);
+ ALLOC_STATE(db, always, 23, r700SendDBState);
+ ALLOC_STATE(stencil, always, 4, r700SendStencilState);
+ ALLOC_STATE(db_target, always, 12, r700SendDepthTargetState);
+ ALLOC_STATE(sc, always, 15, r700SendSCState);
+ ALLOC_STATE(scissor, always, 22, r700SendScissorState);
+ ALLOC_STATE(aa, always, 12, r700SendAAState);
+ ALLOC_STATE(cl, always, 12, r700SendCLState);
+ ALLOC_STATE(gb, always, 6, r700SendGBState);
+ ALLOC_STATE(ucp, ucp, (R700_MAX_UCP * 6), r700SendUCPState);
+ ALLOC_STATE(su, always, 9, r700SendSUState);
+ ALLOC_STATE(poly, always, 10, r700SendPolyState);
+ ALLOC_STATE(cb, cb, 18, r700SendCBState);
+ ALLOC_STATE(clrcmp, always, 6, r700SendCBCLRCMPState);
+ ALLOC_STATE(blnd, blnd, (6 + (R700_MAX_RENDER_TARGETS * 3)), r700SendCBBlendState);
+ ALLOC_STATE(blnd_clr, always, 6, r700SendCBBlendColorState);
+ ALLOC_STATE(cb_target, always, 25, r700SendRenderTargetState);
+ ALLOC_STATE(sx, always, 9, r700SendSXState);
+ ALLOC_STATE(vgt, always, 41, r700SendVGTState);
+ ALLOC_STATE(spi, always, (59 + R700_MAX_SHADER_EXPORTS), r700SendSPIState);
+ ALLOC_STATE(vpt, always, 16, r700SendViewportState);
+ ALLOC_STATE(fs, always, 18, r700SendFSState);
+ ALLOC_STATE(vs, always, 18, r700SendVSState);
+ ALLOC_STATE(ps, always, 21, r700SendPSState);
+ ALLOC_STATE(vs_consts, vs_consts, (2 + (R700_MAX_DX9_CONSTS * 4)), r700SendVSConsts);
+ ALLOC_STATE(ps_consts, ps_consts, (2 + (R700_MAX_DX9_CONSTS * 4)), r700SendPSConsts);
+ ALLOC_STATE(vtx, vtx, (6 + (VERT_ATTRIB_MAX * 18)), r700SendVTXState);
+ ALLOC_STATE(tx, tx, (R700_TEXTURE_NUMBERUNITS * 20), r700SendTexState);
+ ALLOC_STATE(tx_smplr, tx, (R700_TEXTURE_NUMBERUNITS * 5), r700SendTexSamplerState);
+ ALLOC_STATE(tx_brdr_clr, tx, (R700_TEXTURE_NUMBERUNITS * 6), r700SendTexBorderColorState);
+
+ context->radeon.hw.is_dirty = GL_TRUE;
+ context->radeon.hw.all_dirty = GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/r600/r700_chip.h b/src/mesa/drivers/dri/r600/r700_chip.h
new file mode 100644
index 0000000000..ae249e15fd
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_chip.h
@@ -0,0 +1,503 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _R700_CHIP_H_
+#define _R700_CHIP_H_
+
+#include "r600_context.h"
+
+#include "r600_reg.h"
+#include "r600_reg_auto_r6xx.h"
+#include "r600_reg_r6xx.h"
+#include "r600_reg_r7xx.h"
+
+#include "r700_chipoffset.h"
+
+#define SETfield(x, val, shift, mask) ( (x) = ((x) & ~(mask)) | ((val) << (shift)) ) /* u32All */
+#define CLEARfield(x, mask) ( (x) &= ~(mask) )
+#define SETbit(x, bit) ( (x) |= (bit) )
+#define CLEARbit(x, bit) ( (x) &= ~(bit) )
+
+#define R700_TEXTURE_NUMBERUNITS 16
+#define R700_MAX_RENDER_TARGETS 8
+#define R700_MAX_VIEWPORTS 16
+#define R700_MAX_SHADER_EXPORTS 32
+#define R700_MAX_UCP 6
+#define R700_MAX_DX9_CONSTS 256
+
+/* Enum not show in r600_*.h */
+
+#define FETCH_RESOURCE_STRIDE 7
+
+#define ASIC_CONFIG_BASE_INDEX 0x2000
+#define ASIC_CONTEXT_BASE_INDEX 0xA000
+#define ASIC_CTL_CONST_BASE_INDEX 0xF3FC
+
+
+enum
+{
+ SQ_ABSOLUTE = 0x00000000,
+ SQ_RELATIVE = 0x00000001,
+};
+
+enum
+{
+ SQ_ALU_SCL_210 = 0x00000000,
+ SQ_ALU_SCL_122 = 0x00000001,
+ SQ_ALU_SCL_212 = 0x00000002,
+ SQ_ALU_SCL_221 = 0x00000003,
+};
+
+enum
+{
+ SQ_TEX_UNNORMALIZED = 0x00000000,
+ SQ_TEX_NORMALIZED = 0x00000001,
+};
+
+enum
+{
+ SQ_CF_PIXEL_MRT0 = 0x00000000,
+ SQ_CF_PIXEL_MRT1 = 0x00000001,
+ SQ_CF_PIXEL_MRT2 = 0x00000002,
+ SQ_CF_PIXEL_MRT3 = 0x00000003,
+ SQ_CF_PIXEL_MRT4 = 0x00000004,
+ SQ_CF_PIXEL_MRT5 = 0x00000005,
+ SQ_CF_PIXEL_MRT6 = 0x00000006,
+ SQ_CF_PIXEL_MRT7 = 0x00000007,
+ SQ_CF_PIXEL_Z = 0x0000003d,
+};
+
+typedef enum ENUM_SQ_CF_ARRAY_BASE_POS {
+SQ_CF_POS_0 = 0x0000003c,
+SQ_CF_POS_1 = 0x0000003d,
+SQ_CF_POS_2 = 0x0000003e,
+SQ_CF_POS_3 = 0x0000003f,
+} ENUM_SQ_CF_ARRAY_BASE_POS;
+
+enum
+{
+ PGM_RESOURCES__PRIME_CACHE_ON_DRAW_bit = 23,
+};
+
+enum
+{
+ TEX_XYFilter_Point = 0x00000000,
+ TEX_XYFilter_Linear = 0x00000001,
+ TEX_XYFilter_Cubic = 0x00000002,
+ TEX_XYFilter_Cleartype = 0x00000003,
+
+ TEX_MipFilter_None = 0x00000000,
+ TEX_MipFilter_Point = 0x00000001,
+ TEX_MipFilter_Linear = 0x00000002,
+};
+
+enum
+{
+ SQ_EXPORT_WRITE = 0x00000000,
+ SQ_EXPORT_WRITE_IND = 0x00000001,
+ SQ_EXPORT_WRITE_ACK = 0x00000002,
+ SQ_EXPORT_WRITE_IND_ACK = 0x00000003,
+};
+
+/* --------------------------------- */
+
+enum
+{
+ R700_PM4_PACKET0_NOP = 0x00000000,
+ R700_PM4_PACKET1_NOP = 0x40000000,
+ R700_PM4_PACKET2_NOP = 0x80000000,
+ R700_PM4_PACKET3_NOP = 0xC0000000,
+};
+
+#define PM4_OPCODE_SET_INDEX_TYPE (R700_PM4_PACKET3_NOP | (IT_INDEX_TYPE << 8))
+
+#define PM4_OPCODE_DRAW_INDEX_AUTO (R700_PM4_PACKET3_NOP | (IT_DRAW_INDEX_AUTO << 8))
+#define PM4_OPCODE_DRAW_INDEX_IMMD (R700_PM4_PACKET3_NOP | (IT_DRAW_INDEX_IMMD << 8))
+#define PM4_OPCODE_WAIT_REG_MEM (R700_PM4_PACKET3_NOP | (IT_WAIT_REG_MEM << 8))
+#define PM4_OPCODE_SET_CONTEXT_REG (R700_PM4_PACKET3_NOP | (IT_SET_CONTEXT_REG << 8))
+#define PM4_OPCODE_SET_CONFIG_REG (R700_PM4_PACKET3_NOP | (IT_SET_CONFIG_REG << 8))
+#define PM4_OPCODE_SET_ALU_CONST (R700_PM4_PACKET3_NOP | (IT_SET_ALU_CONST << 8))
+#define PM4_OPCODE_SET_RESOURCE (R700_PM4_PACKET3_NOP | (IT_SET_RESOURCE << 8))
+#define PM4_OPCODE_SET_SAMPLER (R700_PM4_PACKET3_NOP | (IT_SET_SAMPLER << 8))
+#define PM4_OPCODE_CONTEXT_CONTROL (R700_PM4_PACKET3_NOP | (IT_CONTEXT_CONTROL << 8))
+
+union UINT_FLOAT
+{
+ unsigned int u32All;
+ float f32All;
+};
+
+#if 0
+typedef struct _TEXTURE_STATE_STRUCT
+{
+ union UINT_FLOAT SQ_TEX_RESOURCE0;
+ union UINT_FLOAT SQ_TEX_RESOURCE1;
+ union UINT_FLOAT SQ_TEX_RESOURCE2;
+ union UINT_FLOAT SQ_TEX_RESOURCE3;
+ union UINT_FLOAT SQ_TEX_RESOURCE4;
+ union UINT_FLOAT SQ_TEX_RESOURCE5;
+ union UINT_FLOAT SQ_TEX_RESOURCE6;
+ GLboolean enabled;
+} TEXTURE_STATE_STRUCT;
+
+typedef struct _SAMPLER_STATE_STRUCT
+{
+ union UINT_FLOAT SQ_TEX_SAMPLER0;
+ union UINT_FLOAT SQ_TEX_SAMPLER1;
+ union UINT_FLOAT SQ_TEX_SAMPLER2;
+ GLboolean enabled;
+} SAMPLER_STATE_STRUCT;
+
+typedef struct _R700_TEXTURE_STATES
+{
+ TEXTURE_STATE_STRUCT *textures[R700_TEXTURE_NUMBERUNITS];
+ SAMPLER_STATE_STRUCT *samplers[R700_TEXTURE_NUMBERUNITS];
+} R700_TEXTURE_STATES;
+#endif
+
+typedef struct _RENDER_TARGET_STATE_STRUCT
+{
+ union UINT_FLOAT CB_COLOR0_BASE; /* 0xA010 */
+ union UINT_FLOAT CB_COLOR0_SIZE; /* 0xA018 */
+ union UINT_FLOAT CB_COLOR0_VIEW; /* 0xA020 */
+ union UINT_FLOAT CB_COLOR0_INFO; /* 0xA028 */
+ union UINT_FLOAT CB_COLOR0_TILE; /* 0xA030 */
+ union UINT_FLOAT CB_COLOR0_FRAG; /* 0xA038 */
+ union UINT_FLOAT CB_COLOR0_MASK; /* 0xA040 */
+ union UINT_FLOAT CB_BLEND0_CONTROL; /* 0xA1E0 */
+ GLboolean enabled;
+ GLboolean dirty;
+} RENDER_TARGET_STATE_STRUCT;
+
+typedef struct _VIEWPORT_STATE_STRUCT
+{
+ union UINT_FLOAT PA_SC_VPORT_SCISSOR_0_TL; /* 0xA094 */
+ union UINT_FLOAT PA_SC_VPORT_SCISSOR_0_BR; /* 0xA095 */
+ union UINT_FLOAT PA_SC_VPORT_ZMIN_0; /* 0xA0B4 */
+ union UINT_FLOAT PA_SC_VPORT_ZMAX_0; /* 0xA0B5 */
+ union UINT_FLOAT PA_CL_VPORT_XSCALE; /* 0xA10F */
+ union UINT_FLOAT PA_CL_VPORT_XOFFSET; /* 0xA110 */
+ union UINT_FLOAT PA_CL_VPORT_YSCALE; /* 0xA111 */
+ union UINT_FLOAT PA_CL_VPORT_YOFFSET; /* 0xA112 */
+ union UINT_FLOAT PA_CL_VPORT_ZSCALE; /* 0xA113 */
+ union UINT_FLOAT PA_CL_VPORT_ZOFFSET; /* 0xA114 */
+ GLboolean enabled;
+ GLboolean dirty;
+} VIEWPORT_STATE_STRUCT;
+
+typedef struct _UCP_STATE_STRUCT
+{
+ union UINT_FLOAT PA_CL_UCP_0_X;
+ union UINT_FLOAT PA_CL_UCP_0_Y;
+ union UINT_FLOAT PA_CL_UCP_0_Z;
+ union UINT_FLOAT PA_CL_UCP_0_W;
+ GLboolean enabled;
+ GLboolean dirty;
+} UCP_STATE_STRUCT;
+
+typedef struct _PS_STATE_STRUCT
+{
+ union UINT_FLOAT SQ_PGM_START_PS ; /* 0xA210 */
+ union UINT_FLOAT SQ_PGM_RESOURCES_PS ; /* 0xA214 */
+ union UINT_FLOAT SQ_PGM_EXPORTS_PS ; /* 0xA215 */
+ union UINT_FLOAT SQ_PGM_CF_OFFSET_PS ; /* 0xA233 */
+ GLboolean dirty;
+ int num_consts;
+ union UINT_FLOAT consts[R700_MAX_DX9_CONSTS][4];
+} PS_STATE_STRUCT;
+
+typedef struct _VS_STATE_STRUCT
+{
+ union UINT_FLOAT SQ_PGM_START_VS ; /* 0xA216 */
+ union UINT_FLOAT SQ_PGM_RESOURCES_VS ; /* 0xA21A */
+ union UINT_FLOAT SQ_PGM_CF_OFFSET_VS ; /* 0xA234 */
+ GLboolean dirty;
+ int num_consts;
+ union UINT_FLOAT consts[R700_MAX_DX9_CONSTS][4];
+} VS_STATE_STRUCT;
+
+typedef struct _GS_STATE_STRUCT
+{
+ union UINT_FLOAT SQ_PGM_START_GS ; /* 0xA21B */
+ union UINT_FLOAT SQ_PGM_RESOURCES_GS ; /* 0xA21F */
+ union UINT_FLOAT SQ_PGM_CF_OFFSET_GS ; /* 0xA235 */
+ GLboolean dirty;
+} GS_STATE_STRUCT;
+
+typedef struct _ES_STATE_STRUCT
+{
+ union UINT_FLOAT SQ_PGM_START_ES ; /* 0xA220 */
+ union UINT_FLOAT SQ_PGM_RESOURCES_ES ; /* 0xA224 */
+ union UINT_FLOAT SQ_PGM_CF_OFFSET_ES ; /* 0xA236 */
+ GLboolean dirty;
+} ES_STATE_STRUCT;
+
+typedef struct _FS_STATE_STRUCT
+{
+ union UINT_FLOAT SQ_PGM_START_FS ; /* 0xA225 */
+ union UINT_FLOAT SQ_PGM_RESOURCES_FS ; /* 0xA229 */
+ union UINT_FLOAT SQ_PGM_CF_OFFSET_FS ; /* 0xA237 */
+ GLboolean dirty;
+} FS_STATE_STRUCT;
+
+typedef struct _SQ_CONFIG_STRUCT
+{
+ union UINT_FLOAT SQ_CONFIG ; /* 0x2300 */
+ union UINT_FLOAT SQ_GPR_RESOURCE_MGMT_1 ; /* 0x2301 */
+ union UINT_FLOAT SQ_GPR_RESOURCE_MGMT_2 ; /* 0x2302 */
+ union UINT_FLOAT SQ_THREAD_RESOURCE_MGMT ; /* 0x2303 */
+ union UINT_FLOAT SQ_STACK_RESOURCE_MGMT_1 ; /* 0x2304 */
+ union UINT_FLOAT SQ_STACK_RESOURCE_MGMT_2 ; /* 0x2305 */
+} SQ_CONFIG_STRUCT;
+
+typedef struct _R700_CHIP_CONTEXT
+{
+ // DB
+ union UINT_FLOAT DB_DEPTH_SIZE ; /* 0xA000 */
+ union UINT_FLOAT DB_DEPTH_VIEW ; /* 0xA001 */
+ union UINT_FLOAT DB_DEPTH_BASE ; /* 0xA003 */
+ union UINT_FLOAT DB_DEPTH_INFO ; /* 0xA004 */
+ GLboolean db_target_dirty;
+ union UINT_FLOAT DB_HTILE_DATA_BASE ; /* 0xA005 */
+ union UINT_FLOAT DB_STENCIL_CLEAR ; /* 0xA00A */
+ union UINT_FLOAT DB_DEPTH_CLEAR ; /* 0xA00B */
+ union UINT_FLOAT DB_STENCILREFMASK ; /* 0xA10C */
+ union UINT_FLOAT DB_STENCILREFMASK_BF ; /* 0xA10D */
+ union UINT_FLOAT DB_RENDER_CONTROL ; /* 0xA343 */
+ union UINT_FLOAT DB_RENDER_OVERRIDE ; /* 0xA344 */
+ union UINT_FLOAT DB_HTILE_SURFACE ; /* 0xA349 */
+ union UINT_FLOAT DB_ALPHA_TO_MASK ; /* 0xA351 */
+ union UINT_FLOAT DB_DEPTH_CONTROL ; /* 0xA200 */
+ union UINT_FLOAT DB_SHADER_CONTROL ; /* 0xA203 */
+ GLboolean db_dirty;
+
+ // SC
+ union UINT_FLOAT PA_SC_SCREEN_SCISSOR_TL ; /* 0xA00C */
+ union UINT_FLOAT PA_SC_SCREEN_SCISSOR_BR ; /* 0xA00D */
+ union UINT_FLOAT PA_SC_WINDOW_OFFSET ; /* 0xA080 */
+ union UINT_FLOAT PA_SC_WINDOW_SCISSOR_TL ; /* 0xA081 */
+ union UINT_FLOAT PA_SC_WINDOW_SCISSOR_BR ; /* 0xA082 */
+ union UINT_FLOAT PA_SC_CLIPRECT_RULE ; /* 0xA083 */
+ union UINT_FLOAT PA_SC_CLIPRECT_0_TL ; /* 0xA084 */
+ union UINT_FLOAT PA_SC_CLIPRECT_0_BR ; /* 0xA085 */
+ union UINT_FLOAT PA_SC_CLIPRECT_1_TL ; /* 0xA086 */
+ union UINT_FLOAT PA_SC_CLIPRECT_1_BR ; /* 0xA087 */
+ union UINT_FLOAT PA_SC_CLIPRECT_2_TL ; /* 0xA088 */
+ union UINT_FLOAT PA_SC_CLIPRECT_2_BR ; /* 0xA089 */
+ union UINT_FLOAT PA_SC_CLIPRECT_3_TL ; /* 0xA08A */
+ union UINT_FLOAT PA_SC_CLIPRECT_3_BR ; /* 0xA08B */
+ union UINT_FLOAT PA_SC_EDGERULE ; /* 0xA08C */
+ union UINT_FLOAT PA_SC_GENERIC_SCISSOR_TL ; /* 0xA090 */
+ union UINT_FLOAT PA_SC_GENERIC_SCISSOR_BR ; /* 0xA091 */
+ GLboolean scissor_dirty;
+
+ union UINT_FLOAT PA_SC_LINE_STIPPLE ; /* 0xA283 */
+ union UINT_FLOAT PA_SC_LINE_CNTL ; /* 0xA300 */
+ union UINT_FLOAT PA_SC_AA_CONFIG ; /* 0xA301 */
+ union UINT_FLOAT PA_SC_MPASS_PS_CNTL ; /* 0xA292 */
+ union UINT_FLOAT PA_SC_MODE_CNTL ; /* 0xA293 */
+ union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_MCTX ; /* 0xA307 */
+ union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX; /* 0xA308 */
+ union UINT_FLOAT PA_SC_AA_MASK ; /* 0xA312 */
+ GLboolean sc_dirty;
+
+ // CL
+ union UINT_FLOAT PA_CL_CLIP_CNTL ; /* 0xA204 */
+ union UINT_FLOAT PA_CL_VTE_CNTL ; /* 0xA206 */
+ union UINT_FLOAT PA_CL_VS_OUT_CNTL ; /* 0xA207 */
+ union UINT_FLOAT PA_CL_NANINF_CNTL ; /* 0xA208 */
+ union UINT_FLOAT PA_CL_GB_VERT_CLIP_ADJ ; /* 0xA303 */
+ union UINT_FLOAT PA_CL_GB_VERT_DISC_ADJ ; /* 0xA304 */
+ union UINT_FLOAT PA_CL_GB_HORZ_CLIP_ADJ ; /* 0xA305 */
+ union UINT_FLOAT PA_CL_GB_HORZ_DISC_ADJ ; /* 0xA306 */
+ GLboolean cl_dirty;
+
+ // SU
+ union UINT_FLOAT PA_SU_SC_MODE_CNTL ; /* 0xA205 */
+ union UINT_FLOAT PA_SU_POINT_SIZE ; /* 0xA280 */
+ union UINT_FLOAT PA_SU_POINT_MINMAX ; /* 0xA281 */
+ union UINT_FLOAT PA_SU_LINE_CNTL ; /* 0xA282 */
+ union UINT_FLOAT PA_SU_VTX_CNTL ; /* 0xA302 */
+ union UINT_FLOAT PA_SU_POLY_OFFSET_DB_FMT_CNTL; /* 0xA37E */
+ union UINT_FLOAT PA_SU_POLY_OFFSET_CLAMP ; /* 0xA37F */
+ union UINT_FLOAT PA_SU_POLY_OFFSET_FRONT_SCALE; /* 0xA380 */
+ union UINT_FLOAT PA_SU_POLY_OFFSET_FRONT_OFFSET; /* 0xA381 */
+ union UINT_FLOAT PA_SU_POLY_OFFSET_BACK_SCALE; /* 0xA382 */
+ union UINT_FLOAT PA_SU_POLY_OFFSET_BACK_OFFSET; /* 0xA383 */
+ GLboolean su_dirty;
+
+ VIEWPORT_STATE_STRUCT viewport[R700_MAX_VIEWPORTS];
+ UCP_STATE_STRUCT ucp[R700_MAX_UCP];
+
+ // CB
+ union UINT_FLOAT CB_CLEAR_RED_R6XX ; /* 0xA048 */
+ union UINT_FLOAT CB_CLEAR_GREEN_R6XX ; /* 0xA049 */
+ union UINT_FLOAT CB_CLEAR_BLUE_R6XX ; /* 0xA04A */
+ union UINT_FLOAT CB_CLEAR_ALPHA_R6XX ; /* 0xA04B */
+ union UINT_FLOAT CB_TARGET_MASK ; /* 0xA08E */
+ union UINT_FLOAT CB_SHADER_MASK ; /* 0xA08F */
+ union UINT_FLOAT CB_BLEND_RED ; /* 0xA105 */
+ union UINT_FLOAT CB_BLEND_GREEN ; /* 0xA106 */
+ union UINT_FLOAT CB_BLEND_BLUE ; /* 0xA107 */
+ union UINT_FLOAT CB_BLEND_ALPHA ; /* 0xA108 */
+ union UINT_FLOAT CB_FOG_RED_R6XX ; /* 0xA109 */
+ union UINT_FLOAT CB_FOG_GREEN_R6XX ; /* 0xA10A */
+ union UINT_FLOAT CB_FOG_BLUE_R6XX ; /* 0xA10B */
+ union UINT_FLOAT CB_SHADER_CONTROL ; /* 0xA1E8 */
+ union UINT_FLOAT CB_COLOR_CONTROL ; /* 0xA202 */
+ union UINT_FLOAT CB_CLRCMP_CONTROL ; /* 0xA30C */
+ union UINT_FLOAT CB_CLRCMP_SRC ; /* 0xA30D */
+ union UINT_FLOAT CB_CLRCMP_DST ; /* 0xA30E */
+ union UINT_FLOAT CB_CLRCMP_MSK ; /* 0xA30F */
+ union UINT_FLOAT CB_BLEND_CONTROL ; /* 0xABD0 */
+ GLboolean cb_dirty;
+ RENDER_TARGET_STATE_STRUCT render_target[R700_MAX_RENDER_TARGETS];
+
+ // SX
+ union UINT_FLOAT SX_MISC ; /* 0xA0D4 */
+ union UINT_FLOAT SX_ALPHA_TEST_CONTROL ; /* 0xA104 */
+ union UINT_FLOAT SX_ALPHA_REF ; /* 0xA10E */
+ GLboolean sx_dirty;
+
+ // VGT
+ union UINT_FLOAT VGT_MAX_VTX_INDX ; /* 0xA100 */
+ union UINT_FLOAT VGT_MIN_VTX_INDX ; /* 0xA101 */
+ union UINT_FLOAT VGT_INDX_OFFSET ; /* 0xA102 */
+ union UINT_FLOAT VGT_MULTI_PRIM_IB_RESET_INDX; /* 0xA103 */
+ union UINT_FLOAT VGT_OUTPUT_PATH_CNTL ; /* 0xA284 */
+ union UINT_FLOAT VGT_HOS_CNTL ; /* 0xA285 */
+ union UINT_FLOAT VGT_HOS_MAX_TESS_LEVEL ; /* 0xA286 */
+ union UINT_FLOAT VGT_HOS_MIN_TESS_LEVEL ; /* 0xA287 */
+ union UINT_FLOAT VGT_HOS_REUSE_DEPTH ; /* 0xA288 */
+ union UINT_FLOAT VGT_GROUP_PRIM_TYPE ; /* 0xA289 */
+ union UINT_FLOAT VGT_GROUP_FIRST_DECR ; /* 0xA28A */
+ union UINT_FLOAT VGT_GROUP_DECR ; /* 0xA28B */
+ union UINT_FLOAT VGT_GROUP_VECT_0_CNTL ; /* 0xA28C */
+ union UINT_FLOAT VGT_GROUP_VECT_1_CNTL ; /* 0xA28D */
+ union UINT_FLOAT VGT_GROUP_VECT_0_FMT_CNTL ; /* 0xA28E */
+ union UINT_FLOAT VGT_GROUP_VECT_1_FMT_CNTL ; /* 0xA28F */
+ union UINT_FLOAT VGT_GS_MODE ; /* 0xA290 */
+ union UINT_FLOAT VGT_PRIMITIVEID_EN ; /* 0xA2A1 */
+ union UINT_FLOAT VGT_MULTI_PRIM_IB_RESET_EN; /* 0xA2A5 */
+ union UINT_FLOAT VGT_INSTANCE_STEP_RATE_0 ; /* 0xA2A8 */
+ union UINT_FLOAT VGT_INSTANCE_STEP_RATE_1 ; /* 0xA2A9 */
+ union UINT_FLOAT VGT_STRMOUT_EN ; /* 0xA2AC */
+ union UINT_FLOAT VGT_REUSE_OFF ; /* 0xA2AD */
+ union UINT_FLOAT VGT_VTX_CNT_EN ; /* 0xA2AE */
+ union UINT_FLOAT VGT_STRMOUT_BUFFER_EN ; /* 0xA2C8 */
+ GLboolean vgt_dirty;
+
+ // SPI
+ union UINT_FLOAT SPI_VS_OUT_ID_0 ; /* 0xA185 */
+ union UINT_FLOAT SPI_VS_OUT_ID_1 ; /* 0xA186 */
+ union UINT_FLOAT SPI_VS_OUT_ID_2 ; /* 0xA187 */
+ union UINT_FLOAT SPI_VS_OUT_ID_3 ; /* 0xA188 */
+ union UINT_FLOAT SPI_VS_OUT_ID_4 ; /* 0xA189 */
+ union UINT_FLOAT SPI_VS_OUT_ID_5 ; /* 0xA18A */
+ union UINT_FLOAT SPI_VS_OUT_ID_6 ; /* 0xA18B */
+ union UINT_FLOAT SPI_VS_OUT_ID_7 ; /* 0xA18C */
+ union UINT_FLOAT SPI_VS_OUT_ID_8 ; /* 0xA18D */
+ union UINT_FLOAT SPI_VS_OUT_ID_9 ; /* 0xA18E */
+ union UINT_FLOAT SPI_VS_OUT_CONFIG ; /* 0xA1B1 */
+ union UINT_FLOAT SPI_THREAD_GROUPING ; /* 0xA1B2 */
+ union UINT_FLOAT SPI_PS_IN_CONTROL_0 ; /* 0xA1B3 */
+ union UINT_FLOAT SPI_PS_IN_CONTROL_1 ; /* 0xA1B4 */
+ union UINT_FLOAT SPI_INTERP_CONTROL_0 ; /* 0xA1B5 */
+ union UINT_FLOAT SPI_INPUT_Z ; /* 0xA1B6 */
+ union UINT_FLOAT SPI_FOG_CNTL ; /* 0xA1B7 */
+ union UINT_FLOAT SPI_FOG_FUNC_SCALE ; /* 0xA1B8 */
+ union UINT_FLOAT SPI_FOG_FUNC_BIAS ; /* 0xA1B9 */
+
+ union UINT_FLOAT SQ_VTX_SEMANTIC_0 ; /* 0xA0E0 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_1 ; /* 0xA0E1 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_2 ; /* 0xA0E2 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_3 ; /* 0xA0E3 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_4 ; /* 0xA0E4 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_5 ; /* 0xA0E5 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_6 ; /* 0xA0E6 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_7 ; /* 0xA0E7 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_8 ; /* 0xA0E8 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_9 ; /* 0xA0E9 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_10 ; /* 0xA0EA */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_11 ; /* 0xA0EB */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_12 ; /* 0xA0EC */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_13 ; /* 0xA0ED */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_14 ; /* 0xA0EE */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_15 ; /* 0xA0EF */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_16 ; /* 0xA0F0 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_17 ; /* 0xA0F1 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_18 ; /* 0xA0F2 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_19 ; /* 0xA0F3 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_20 ; /* 0xA0F4 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_21 ; /* 0xA0F5 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_22 ; /* 0xA0F6 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_23 ; /* 0xA0F7 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_24 ; /* 0xA0F8 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_25 ; /* 0xA0F9 */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_26 ; /* 0xA0FA */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_27 ; /* 0xA0FB */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_28 ; /* 0xA0FC */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_29 ; /* 0xA0FD */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_30 ; /* 0xA0FE */
+ union UINT_FLOAT SQ_VTX_SEMANTIC_31 ; /* 0xA0FF */
+ union UINT_FLOAT SPI_PS_INPUT_CNTL[R700_MAX_SHADER_EXPORTS];
+ GLboolean spi_dirty;
+
+ // shaders
+ PS_STATE_STRUCT ps;
+ VS_STATE_STRUCT vs;
+ GS_STATE_STRUCT gs;
+ ES_STATE_STRUCT es;
+ FS_STATE_STRUCT fs;
+
+ // SQ CONFIG
+ SQ_CONFIG_STRUCT sq_config;
+ // misc
+ union UINT_FLOAT TA_CNTL_AUX ; /* 0x2542 */
+ union UINT_FLOAT VC_ENHANCE ; /* 0x25C5 */
+ union UINT_FLOAT SQ_DYN_GPR_CNTL_PS_FLUSH_REQ; /* 0x2363 */
+ union UINT_FLOAT DB_DEBUG ; /* 0x260C */
+ union UINT_FLOAT DB_WATERMARKS ; /* 0x260E */
+ // SQ
+ union UINT_FLOAT SQ_ESGS_RING_ITEMSIZE ; /* 0xA22A */
+ union UINT_FLOAT SQ_GSVS_RING_ITEMSIZE ; /* 0xA22B */
+ union UINT_FLOAT SQ_ESTMP_RING_ITEMSIZE ; /* 0xA22C */
+ union UINT_FLOAT SQ_GSTMP_RING_ITEMSIZE ; /* 0xA22D */
+ union UINT_FLOAT SQ_VSTMP_RING_ITEMSIZE ; /* 0xA22E */
+ union UINT_FLOAT SQ_PSTMP_RING_ITEMSIZE ; /* 0xA22F */
+ union UINT_FLOAT SQ_FBUF_RING_ITEMSIZE ; /* 0xA230 */
+ union UINT_FLOAT SQ_REDUC_RING_ITEMSIZE ; /* 0xA231 */
+ union UINT_FLOAT SQ_GS_VERT_ITEMSIZE ; /* 0xA232 */
+ GLboolean sq_dirty;
+
+ radeonTexObj* textures[R700_TEXTURE_NUMBERUNITS];
+
+ GLboolean bEnablePerspective;
+
+} R700_CHIP_CONTEXT;
+
+#endif /* _R700_CHIP_H_ */
+
diff --git a/src/mesa/drivers/dri/r600/r700_chipoffset.h b/src/mesa/drivers/dri/r600/r700_chipoffset.h
new file mode 100644
index 0000000000..4d73fb99a7
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_chipoffset.h
@@ -0,0 +1,693 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#ifndef _R700_CHIPOFFSET_H_
+#define _R700_CHIPOFFSET_H_
+
+#define mmWAIT_UNTIL 0x2010
+#define mmSCRATCH_REG0 0x2140
+#define mmGUI_SCRATCH_REG0 0x2140
+#define mmSCRATCH_REG1 0x2141
+#define mmGUI_SCRATCH_REG1 0x2141
+#define mmSCRATCH_REG2 0x2142
+#define mmGUI_SCRATCH_REG2 0x2142
+#define mmSCRATCH_REG3 0x2143
+#define mmGUI_SCRATCH_REG3 0x2143
+#define mmSCRATCH_REG4 0x2144
+#define mmGUI_SCRATCH_REG4 0x2144
+#define mmSCRATCH_REG5 0x2145
+#define mmGUI_SCRATCH_REG5 0x2145
+#define mmSCRATCH_REG6 0x2146
+#define mmGUI_SCRATCH_REG6 0x2146
+#define mmSCRATCH_REG7 0x2147
+#define mmGUI_SCRATCH_REG7 0x2147
+
+#define mmCP_COHER_CNTL 0x217C
+#define mmCP_COHER_SIZE 0x217D
+#define mmCP_COHER_BASE 0x217E
+#define mmCP_COHER_STATUS 0x217F
+
+#define mmTA_CNTL_AUX 0x2542
+#define mmVC_ENHANCE 0x25C5
+#define mmSQ_DYN_GPR_CNTL_PS_FLUSH_REQ 0x2363
+#define mmDB_DEBUG 0x260C
+#define mmDB_WATERMARKS 0x260E
+
+#define mmPA_CL_VPORT_XSCALE 0xA10F
+#define mmPA_CL_VPORT_XOFFSET 0xA110
+#define mmPA_CL_VPORT_YSCALE 0xA111
+#define mmPA_CL_VPORT_YOFFSET 0xA112
+#define mmPA_CL_VPORT_ZSCALE 0xA113
+#define mmPA_CL_VPORT_ZOFFSET 0xA114
+#define mmPA_CL_VPORT_XSCALE_1 0xA115
+#define mmPA_CL_VPORT_XSCALE_2 0xA11B
+#define mmPA_CL_VPORT_XSCALE_3 0xA121
+#define mmPA_CL_VPORT_XSCALE_4 0xA127
+#define mmPA_CL_VPORT_XSCALE_5 0xA12D
+#define mmPA_CL_VPORT_XSCALE_6 0xA133
+#define mmPA_CL_VPORT_XSCALE_7 0xA139
+#define mmPA_CL_VPORT_XSCALE_8 0xA13F
+#define mmPA_CL_VPORT_XSCALE_9 0xA145
+#define mmPA_CL_VPORT_XSCALE_10 0xA14B
+#define mmPA_CL_VPORT_XSCALE_11 0xA151
+#define mmPA_CL_VPORT_XSCALE_12 0xA157
+#define mmPA_CL_VPORT_XSCALE_13 0xA15D
+#define mmPA_CL_VPORT_XSCALE_14 0xA163
+#define mmPA_CL_VPORT_XSCALE_15 0xA169
+#define mmPA_CL_VPORT_XOFFSET_1 0xA116
+#define mmPA_CL_VPORT_XOFFSET_2 0xA11C
+#define mmPA_CL_VPORT_XOFFSET_3 0xA122
+#define mmPA_CL_VPORT_XOFFSET_4 0xA128
+#define mmPA_CL_VPORT_XOFFSET_5 0xA12E
+#define mmPA_CL_VPORT_XOFFSET_6 0xA134
+#define mmPA_CL_VPORT_XOFFSET_7 0xA13A
+#define mmPA_CL_VPORT_XOFFSET_8 0xA140
+#define mmPA_CL_VPORT_XOFFSET_9 0xA146
+#define mmPA_CL_VPORT_XOFFSET_10 0xA14C
+#define mmPA_CL_VPORT_XOFFSET_11 0xA152
+#define mmPA_CL_VPORT_XOFFSET_12 0xA158
+#define mmPA_CL_VPORT_XOFFSET_13 0xA15E
+#define mmPA_CL_VPORT_XOFFSET_14 0xA164
+#define mmPA_CL_VPORT_XOFFSET_15 0xA16A
+#define mmPA_CL_VPORT_YSCALE_1 0xA117
+#define mmPA_CL_VPORT_YSCALE_2 0xA11D
+#define mmPA_CL_VPORT_YSCALE_3 0xA123
+#define mmPA_CL_VPORT_YSCALE_4 0xA129
+#define mmPA_CL_VPORT_YSCALE_5 0xA12F
+#define mmPA_CL_VPORT_YSCALE_6 0xA135
+#define mmPA_CL_VPORT_YSCALE_7 0xA13B
+#define mmPA_CL_VPORT_YSCALE_8 0xA141
+#define mmPA_CL_VPORT_YSCALE_9 0xA147
+#define mmPA_CL_VPORT_YSCALE_10 0xA14D
+#define mmPA_CL_VPORT_YSCALE_11 0xA153
+#define mmPA_CL_VPORT_YSCALE_12 0xA159
+#define mmPA_CL_VPORT_YSCALE_13 0xA15F
+#define mmPA_CL_VPORT_YSCALE_14 0xA165
+#define mmPA_CL_VPORT_YSCALE_15 0xA16B
+#define mmPA_CL_VPORT_YOFFSET_1 0xA118
+#define mmPA_CL_VPORT_YOFFSET_2 0xA11E
+#define mmPA_CL_VPORT_YOFFSET_3 0xA124
+#define mmPA_CL_VPORT_YOFFSET_4 0xA12A
+#define mmPA_CL_VPORT_YOFFSET_5 0xA130
+#define mmPA_CL_VPORT_YOFFSET_6 0xA136
+#define mmPA_CL_VPORT_YOFFSET_7 0xA13C
+#define mmPA_CL_VPORT_YOFFSET_8 0xA142
+#define mmPA_CL_VPORT_YOFFSET_9 0xA148
+#define mmPA_CL_VPORT_YOFFSET_10 0xA14E
+#define mmPA_CL_VPORT_YOFFSET_11 0xA154
+#define mmPA_CL_VPORT_YOFFSET_12 0xA15A
+#define mmPA_CL_VPORT_YOFFSET_13 0xA160
+#define mmPA_CL_VPORT_YOFFSET_14 0xA166
+#define mmPA_CL_VPORT_YOFFSET_15 0xA16C
+#define mmPA_CL_VPORT_ZSCALE_1 0xA119
+#define mmPA_CL_VPORT_ZSCALE_2 0xA11F
+#define mmPA_CL_VPORT_ZSCALE_3 0xA125
+#define mmPA_CL_VPORT_ZSCALE_4 0xA12B
+#define mmPA_CL_VPORT_ZSCALE_5 0xA131
+#define mmPA_CL_VPORT_ZSCALE_6 0xA137
+#define mmPA_CL_VPORT_ZSCALE_7 0xA13D
+#define mmPA_CL_VPORT_ZSCALE_8 0xA143
+#define mmPA_CL_VPORT_ZSCALE_9 0xA149
+#define mmPA_CL_VPORT_ZSCALE_10 0xA14F
+#define mmPA_CL_VPORT_ZSCALE_11 0xA155
+#define mmPA_CL_VPORT_ZSCALE_12 0xA15B
+#define mmPA_CL_VPORT_ZSCALE_13 0xA161
+#define mmPA_CL_VPORT_ZSCALE_14 0xA167
+#define mmPA_CL_VPORT_ZSCALE_15 0xA16D
+#define mmPA_CL_VPORT_ZOFFSET_1 0xA11A
+#define mmPA_CL_VPORT_ZOFFSET_2 0xA120
+#define mmPA_CL_VPORT_ZOFFSET_3 0xA126
+#define mmPA_CL_VPORT_ZOFFSET_4 0xA12C
+#define mmPA_CL_VPORT_ZOFFSET_5 0xA132
+#define mmPA_CL_VPORT_ZOFFSET_6 0xA138
+#define mmPA_CL_VPORT_ZOFFSET_7 0xA13E
+#define mmPA_CL_VPORT_ZOFFSET_8 0xA144
+#define mmPA_CL_VPORT_ZOFFSET_9 0xA14A
+#define mmPA_CL_VPORT_ZOFFSET_10 0xA150
+#define mmPA_CL_VPORT_ZOFFSET_11 0xA156
+#define mmPA_CL_VPORT_ZOFFSET_12 0xA15C
+#define mmPA_CL_VPORT_ZOFFSET_13 0xA162
+#define mmPA_CL_VPORT_ZOFFSET_14 0xA168
+#define mmPA_CL_VPORT_ZOFFSET_15 0xA16E
+#define mmPA_CL_VTE_CNTL 0xA206
+#define mmPA_CL_VS_OUT_CNTL 0xA207
+#define mmPA_CL_NANINF_CNTL 0xA208
+#define mmPA_CL_CLIP_CNTL 0xA204
+#define mmPA_CL_GB_VERT_CLIP_ADJ 0xA303
+#define mmPA_CL_GB_VERT_DISC_ADJ 0xA304
+#define mmPA_CL_GB_HORZ_CLIP_ADJ 0xA305
+#define mmPA_CL_GB_HORZ_DISC_ADJ 0xA306
+#define mmPA_CL_UCP_0_X 0xA388
+#define mmPA_CL_UCP_0_Y 0xA389
+#define mmPA_CL_UCP_0_Z 0xA38A
+#define mmPA_CL_UCP_0_W 0xA38B
+#define mmPA_CL_UCP_1_X 0xA38C
+#define mmPA_CL_UCP_1_Y 0xA38D
+#define mmPA_CL_UCP_1_Z 0xA38E
+#define mmPA_CL_UCP_1_W 0xA38F
+#define mmPA_CL_UCP_2_X 0xA390
+#define mmPA_CL_UCP_2_Y 0xA391
+#define mmPA_CL_UCP_2_Z 0xA392
+#define mmPA_CL_UCP_2_W 0xA393
+#define mmPA_CL_UCP_3_X 0xA394
+#define mmPA_CL_UCP_3_Y 0xA395
+#define mmPA_CL_UCP_3_Z 0xA396
+#define mmPA_CL_UCP_3_W 0xA397
+#define mmPA_CL_UCP_4_X 0xA398
+#define mmPA_CL_UCP_4_Y 0xA399
+#define mmPA_CL_UCP_4_Z 0xA39A
+#define mmPA_CL_UCP_4_W 0xA39B
+#define mmPA_CL_UCP_5_X 0xA39C
+#define mmPA_CL_UCP_5_Y 0xA39D
+#define mmPA_CL_UCP_5_Z 0xA39E
+#define mmPA_CL_UCP_5_W 0xA39F
+#define mmPA_CL_POINT_X_RAD 0xA384
+#define mmPA_CL_POINT_Y_RAD 0xA385
+#define mmPA_CL_POINT_SIZE 0xA386
+#define mmPA_CL_POINT_CULL_RAD 0xA387
+
+#define mmPA_SU_VTX_CNTL 0xA302
+#define mmPA_SU_POINT_SIZE 0xA280
+#define mmPA_SU_POINT_MINMAX 0xA281
+#define mmPA_SU_LINE_CNTL 0xA282
+#define mmPA_SU_SC_MODE_CNTL 0xA205
+#define mmPA_SU_POLY_OFFSET_DB_FMT_CNTL 0xA37E
+#define mmPA_SU_POLY_OFFSET_CLAMP 0xA37F
+#define mmPA_SU_POLY_OFFSET_FRONT_SCALE 0xA380
+#define mmPA_SU_POLY_OFFSET_FRONT_OFFSET 0xA381
+#define mmPA_SU_POLY_OFFSET_BACK_SCALE 0xA382
+#define mmPA_SU_POLY_OFFSET_BACK_OFFSET 0xA383
+
+#define mmPA_SC_WINDOW_OFFSET 0xA080
+#define mmPA_SC_AA_CONFIG 0xA301
+#define mmPA_SC_AA_MASK 0xA312
+#define mmPA_SC_AA_SAMPLE_LOCS_MCTX 0xA307
+#define mmPA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX 0xA308
+#define mmPA_SC_LINE_STIPPLE 0xA283
+#define mmPA_SC_LINE_CNTL 0xA300
+#define mmPA_SC_SCREEN_SCISSOR_TL 0xA00C
+#define mmPA_SC_SCREEN_SCISSOR_BR 0xA00D
+#define mmPA_SC_WINDOW_SCISSOR_TL 0xA081
+#define mmPA_SC_WINDOW_SCISSOR_BR 0xA082
+#define mmPA_SC_CLIPRECT_RULE 0xA083
+#define mmPA_SC_CLIPRECT_0_TL 0xA084
+#define mmPA_SC_CLIPRECT_0_BR 0xA085
+#define mmPA_SC_CLIPRECT_1_TL 0xA086
+#define mmPA_SC_CLIPRECT_1_BR 0xA087
+#define mmPA_SC_CLIPRECT_2_TL 0xA088
+#define mmPA_SC_CLIPRECT_2_BR 0xA089
+#define mmPA_SC_CLIPRECT_3_TL 0xA08A
+#define mmPA_SC_CLIPRECT_3_BR 0xA08B
+#define mmPA_SC_EDGERULE 0xA08C
+#define mmPA_SC_GENERIC_SCISSOR_TL 0xA090
+#define mmPA_SC_GENERIC_SCISSOR_BR 0xA091
+#define mmPA_SC_VPORT_SCISSOR_0_TL 0xA094
+#define mmPA_SC_VPORT_SCISSOR_1_TL 0xA096
+#define mmPA_SC_VPORT_SCISSOR_2_TL 0xA098
+#define mmPA_SC_VPORT_SCISSOR_3_TL 0xA09A
+#define mmPA_SC_VPORT_SCISSOR_4_TL 0xA09C
+#define mmPA_SC_VPORT_SCISSOR_5_TL 0xA09E
+#define mmPA_SC_VPORT_SCISSOR_6_TL 0xA0A0
+#define mmPA_SC_VPORT_SCISSOR_7_TL 0xA0A2
+#define mmPA_SC_VPORT_SCISSOR_8_TL 0xA0A4
+#define mmPA_SC_VPORT_SCISSOR_9_TL 0xA0A6
+#define mmPA_SC_VPORT_SCISSOR_10_TL 0xA0A8
+#define mmPA_SC_VPORT_SCISSOR_11_TL 0xA0AA
+#define mmPA_SC_VPORT_SCISSOR_12_TL 0xA0AC
+#define mmPA_SC_VPORT_SCISSOR_13_TL 0xA0AE
+#define mmPA_SC_VPORT_SCISSOR_14_TL 0xA0B0
+#define mmPA_SC_VPORT_SCISSOR_15_TL 0xA0B2
+#define mmPA_SC_VPORT_SCISSOR_0_BR 0xA095
+#define mmPA_SC_VPORT_SCISSOR_1_BR 0xA097
+#define mmPA_SC_VPORT_SCISSOR_2_BR 0xA099
+#define mmPA_SC_VPORT_SCISSOR_3_BR 0xA09B
+#define mmPA_SC_VPORT_SCISSOR_4_BR 0xA09D
+#define mmPA_SC_VPORT_SCISSOR_5_BR 0xA09F
+#define mmPA_SC_VPORT_SCISSOR_6_BR 0xA0A1
+#define mmPA_SC_VPORT_SCISSOR_7_BR 0xA0A3
+#define mmPA_SC_VPORT_SCISSOR_8_BR 0xA0A5
+#define mmPA_SC_VPORT_SCISSOR_9_BR 0xA0A7
+#define mmPA_SC_VPORT_SCISSOR_10_BR 0xA0A9
+#define mmPA_SC_VPORT_SCISSOR_11_BR 0xA0AB
+#define mmPA_SC_VPORT_SCISSOR_12_BR 0xA0AD
+#define mmPA_SC_VPORT_SCISSOR_13_BR 0xA0AF
+#define mmPA_SC_VPORT_SCISSOR_14_BR 0xA0B1
+#define mmPA_SC_VPORT_SCISSOR_15_BR 0xA0B3
+#define mmPA_SC_VPORT_ZMIN_0 0xA0B4
+#define mmPA_SC_VPORT_ZMIN_1 0xA0B6
+#define mmPA_SC_VPORT_ZMIN_2 0xA0B8
+#define mmPA_SC_VPORT_ZMIN_3 0xA0BA
+#define mmPA_SC_VPORT_ZMIN_4 0xA0BC
+#define mmPA_SC_VPORT_ZMIN_5 0xA0BE
+#define mmPA_SC_VPORT_ZMIN_6 0xA0C0
+#define mmPA_SC_VPORT_ZMIN_7 0xA0C2
+#define mmPA_SC_VPORT_ZMIN_8 0xA0C4
+#define mmPA_SC_VPORT_ZMIN_9 0xA0C6
+#define mmPA_SC_VPORT_ZMIN_10 0xA0C8
+#define mmPA_SC_VPORT_ZMIN_11 0xA0CA
+#define mmPA_SC_VPORT_ZMIN_12 0xA0CC
+#define mmPA_SC_VPORT_ZMIN_13 0xA0CE
+#define mmPA_SC_VPORT_ZMIN_14 0xA0D0
+#define mmPA_SC_VPORT_ZMIN_15 0xA0D2
+#define mmPA_SC_VPORT_ZMAX_0 0xA0B5
+#define mmPA_SC_VPORT_ZMAX_1 0xA0B7
+#define mmPA_SC_VPORT_ZMAX_2 0xA0B9
+#define mmPA_SC_VPORT_ZMAX_3 0xA0BB
+#define mmPA_SC_VPORT_ZMAX_4 0xA0BD
+#define mmPA_SC_VPORT_ZMAX_5 0xA0BF
+#define mmPA_SC_VPORT_ZMAX_6 0xA0C1
+#define mmPA_SC_VPORT_ZMAX_7 0xA0C3
+#define mmPA_SC_VPORT_ZMAX_8 0xA0C5
+#define mmPA_SC_VPORT_ZMAX_9 0xA0C7
+#define mmPA_SC_VPORT_ZMAX_10 0xA0C9
+#define mmPA_SC_VPORT_ZMAX_11 0xA0CB
+#define mmPA_SC_VPORT_ZMAX_12 0xA0CD
+#define mmPA_SC_VPORT_ZMAX_13 0xA0CF
+#define mmPA_SC_VPORT_ZMAX_14 0xA0D1
+#define mmPA_SC_VPORT_ZMAX_15 0xA0D3
+#define mmPA_SC_MODE_CNTL 0xA293
+#define mmPA_SC_MPASS_PS_CNTL 0xA292
+
+#define mmVGT_DRAW_INITIATOR 0xA1FC
+#define mmVGT_EVENT_INITIATOR 0xA2A4
+#define mmVGT_EVENT_ADDRESS_REG 0xA1FE
+#define mmVGT_DMA_BASE_HI 0xA1F9
+#define mmVGT_DMA_BASE 0xA1FA
+#define mmVGT_DMA_INDEX_TYPE 0xA29F
+#define mmVGT_DMA_NUM_INSTANCES 0xA2A2
+#define mmVGT_DMA_SIZE 0xA29D
+
+#define mmVGT_IMMED_DATA 0xA1FD
+#define mmVGT_INDEX_TYPE 0x2257
+#define mmVGT_NUM_INDICES 0x225C
+#define mmVGT_NUM_INSTANCES 0x225D
+#define mmVGT_PRIMITIVE_TYPE 0x2256
+#define mmVGT_PRIMITIVEID_EN 0xA2A1
+#define mmVGT_VTX_CNT_EN 0xA2AE
+#define mmVGT_REUSE_OFF 0xA2AD
+#define mmVGT_INSTANCE_STEP_RATE_0 0xA2A8
+#define mmVGT_INSTANCE_STEP_RATE_1 0xA2A9
+#define mmVGT_MAX_VTX_INDX 0xA100
+#define mmVGT_MIN_VTX_INDX 0xA101
+#define mmVGT_INDX_OFFSET 0xA102
+#define mmVGT_VERTEX_REUSE_BLOCK_CNTL 0xA316
+#define mmVGT_OUT_DEALLOC_CNTL 0xA317
+#define mmVGT_MULTI_PRIM_IB_RESET_INDX 0xA103
+#define mmVGT_MULTI_PRIM_IB_RESET_EN 0xA2A5
+#define mmVGT_ENHANCE 0xA294
+#define mmVGT_OUTPUT_PATH_CNTL 0xA284
+#define mmVGT_HOS_CNTL 0xA285
+#define mmVGT_HOS_MAX_TESS_LEVEL 0xA286
+#define mmVGT_HOS_MIN_TESS_LEVEL 0xA287
+#define mmVGT_HOS_REUSE_DEPTH 0xA288
+#define mmVGT_GROUP_PRIM_TYPE 0xA289
+#define mmVGT_GROUP_FIRST_DECR 0xA28A
+#define mmVGT_GROUP_DECR 0xA28B
+#define mmVGT_GROUP_VECT_0_CNTL 0xA28C
+#define mmVGT_GROUP_VECT_1_CNTL 0xA28D
+#define mmVGT_GROUP_VECT_0_FMT_CNTL 0xA28E
+#define mmVGT_GROUP_VECT_1_FMT_CNTL 0xA28F
+#define mmVGT_GS_MODE 0xA290
+#define mmVGT_GS_OUT_PRIM_TYPE 0xA29B
+
+#define mmVGT_STRMOUT_EN 0xA2AC
+#define mmVGT_STRMOUT_BUFFER_SIZE_0 0xA2B4
+#define mmVGT_STRMOUT_BUFFER_SIZE_1 0xA2B8
+#define mmVGT_STRMOUT_BUFFER_SIZE_2 0xA2BC
+#define mmVGT_STRMOUT_BUFFER_SIZE_3 0xA2C0
+#define mmVGT_STRMOUT_BUFFER_OFFSET_0 0xA2B7
+#define mmVGT_STRMOUT_BUFFER_OFFSET_1 0xA2BB
+#define mmVGT_STRMOUT_BUFFER_OFFSET_2 0xA2BF
+#define mmVGT_STRMOUT_BUFFER_OFFSET_3 0xA2C3
+#define mmVGT_STRMOUT_VTX_STRIDE_0 0xA2B5
+#define mmVGT_STRMOUT_VTX_STRIDE_1 0xA2B9
+#define mmVGT_STRMOUT_VTX_STRIDE_2 0xA2BD
+#define mmVGT_STRMOUT_VTX_STRIDE_3 0xA2C1
+#define mmVGT_STRMOUT_BUFFER_BASE_0 0xA2B6
+#define mmVGT_STRMOUT_BUFFER_BASE_1 0xA2BA
+#define mmVGT_STRMOUT_BUFFER_BASE_2 0xA2BE
+#define mmVGT_STRMOUT_BUFFER_BASE_3 0xA2C2
+#define mmVGT_STRMOUT_BUFFER_EN 0xA2C8
+#define mmVGT_STRMOUT_BASE_OFFSET_0 0xA2C4
+#define mmVGT_STRMOUT_BASE_OFFSET_1 0xA2C5
+#define mmVGT_STRMOUT_BASE_OFFSET_2 0xA2C6
+#define mmVGT_STRMOUT_BASE_OFFSET_3 0xA2C7
+#define mmVGT_STRMOUT_BASE_OFFSET_HI_0 0xA2D1
+#define mmVGT_STRMOUT_BASE_OFFSET_HI_1 0xA2D2
+#define mmVGT_STRMOUT_BASE_OFFSET_HI_2 0xA2D3
+#define mmVGT_STRMOUT_BASE_OFFSET_HI_3 0xA2D4
+#define mmVGT_STRMOUT_DRAW_OPAQUE_OFFSET 0xA2CA
+#define mmVGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE 0xA2CB
+#define mmVGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0xA2CC
+
+#define mmSQ_PGM_START_PS 0xA210
+#define mmSQ_PGM_CF_OFFSET_PS 0xA233
+#define mmSQ_PGM_RESOURCES_PS 0xA214
+#define mmSQ_PGM_EXPORTS_PS 0xA215
+#define mmSQ_PGM_START_VS 0xA216
+#define mmSQ_PGM_CF_OFFSET_VS 0xA234
+#define mmSQ_PGM_RESOURCES_VS 0xA21A
+#define mmSQ_PGM_START_GS 0xA21B
+#define mmSQ_PGM_CF_OFFSET_GS 0xA235
+#define mmSQ_PGM_RESOURCES_GS 0xA21F
+#define mmSQ_PGM_START_ES 0xA220
+#define mmSQ_PGM_CF_OFFSET_ES 0xA236
+#define mmSQ_PGM_RESOURCES_ES 0xA224
+#define mmSQ_PGM_START_FS 0xA225
+#define mmSQ_PGM_CF_OFFSET_FS 0xA237
+#define mmSQ_PGM_RESOURCES_FS 0xA229
+#define mmSQ_ESGS_RING_ITEMSIZE 0xA22A
+#define mmSQ_GSVS_RING_ITEMSIZE 0xA22B
+#define mmSQ_ESTMP_RING_ITEMSIZE 0xA22C
+#define mmSQ_GSTMP_RING_ITEMSIZE 0xA22D
+#define mmSQ_VSTMP_RING_ITEMSIZE 0xA22E
+#define mmSQ_PSTMP_RING_ITEMSIZE 0xA22F
+#define mmSQ_FBUF_RING_ITEMSIZE 0xA230
+#define mmSQ_REDUC_RING_ITEMSIZE 0xA231
+#define mmSQ_GS_VERT_ITEMSIZE 0xA232
+#define mmSQ_VTX_SEMANTIC_CLEAR 0xA238
+
+#define mmSQ_VTX_SEMANTIC_0 0xA0E0
+#define mmSQ_VTX_SEMANTIC_1 0xA0E1
+#define mmSQ_VTX_SEMANTIC_2 0xA0E2
+#define mmSQ_VTX_SEMANTIC_3 0xA0E3
+#define mmSQ_VTX_SEMANTIC_4 0xA0E4
+#define mmSQ_VTX_SEMANTIC_5 0xA0E5
+#define mmSQ_VTX_SEMANTIC_6 0xA0E6
+#define mmSQ_VTX_SEMANTIC_7 0xA0E7
+#define mmSQ_VTX_SEMANTIC_8 0xA0E8
+#define mmSQ_VTX_SEMANTIC_9 0xA0E9
+#define mmSQ_VTX_SEMANTIC_10 0xA0EA
+#define mmSQ_VTX_SEMANTIC_11 0xA0EB
+#define mmSQ_VTX_SEMANTIC_12 0xA0EC
+#define mmSQ_VTX_SEMANTIC_13 0xA0ED
+#define mmSQ_VTX_SEMANTIC_14 0xA0EE
+#define mmSQ_VTX_SEMANTIC_15 0xA0EF
+#define mmSQ_VTX_SEMANTIC_16 0xA0F0
+#define mmSQ_VTX_SEMANTIC_17 0xA0F1
+#define mmSQ_VTX_SEMANTIC_18 0xA0F2
+#define mmSQ_VTX_SEMANTIC_19 0xA0F3
+#define mmSQ_VTX_SEMANTIC_20 0xA0F4
+#define mmSQ_VTX_SEMANTIC_21 0xA0F5
+#define mmSQ_VTX_SEMANTIC_22 0xA0F6
+#define mmSQ_VTX_SEMANTIC_23 0xA0F7
+#define mmSQ_VTX_SEMANTIC_24 0xA0F8
+#define mmSQ_VTX_SEMANTIC_25 0xA0F9
+#define mmSQ_VTX_SEMANTIC_26 0xA0FA
+#define mmSQ_VTX_SEMANTIC_27 0xA0FB
+#define mmSQ_VTX_SEMANTIC_28 0xA0FC
+#define mmSQ_VTX_SEMANTIC_29 0xA0FD
+#define mmSQ_VTX_SEMANTIC_30 0xA0FE
+#define mmSQ_VTX_SEMANTIC_31 0xA0FF
+
+#define mmSQ_ALU_CONST_CACHE_PS_0 0xA250
+#define mmSQ_ALU_CONST_CACHE_PS_1 0xA251
+#define mmSQ_ALU_CONST_CACHE_PS_2 0xA252
+#define mmSQ_ALU_CONST_CACHE_PS_3 0xA253
+#define mmSQ_ALU_CONST_CACHE_PS_4 0xA254
+#define mmSQ_ALU_CONST_CACHE_PS_5 0xA255
+#define mmSQ_ALU_CONST_CACHE_PS_6 0xA256
+#define mmSQ_ALU_CONST_CACHE_PS_7 0xA257
+#define mmSQ_ALU_CONST_CACHE_PS_8 0xA258
+#define mmSQ_ALU_CONST_CACHE_PS_9 0xA259
+#define mmSQ_ALU_CONST_CACHE_PS_10 0xA25A
+#define mmSQ_ALU_CONST_CACHE_PS_11 0xA25B
+#define mmSQ_ALU_CONST_CACHE_PS_12 0xA25C
+#define mmSQ_ALU_CONST_CACHE_PS_13 0xA25D
+#define mmSQ_ALU_CONST_CACHE_PS_14 0xA25E
+#define mmSQ_ALU_CONST_CACHE_PS_15 0xA25F
+#define mmSQ_ALU_CONST_CACHE_VS_0 0xA260
+#define mmSQ_ALU_CONST_CACHE_VS_1 0xA261
+#define mmSQ_ALU_CONST_CACHE_VS_2 0xA262
+#define mmSQ_ALU_CONST_CACHE_VS_3 0xA263
+#define mmSQ_ALU_CONST_CACHE_VS_4 0xA264
+#define mmSQ_ALU_CONST_CACHE_VS_5 0xA265
+#define mmSQ_ALU_CONST_CACHE_VS_6 0xA266
+#define mmSQ_ALU_CONST_CACHE_VS_7 0xA267
+#define mmSQ_ALU_CONST_CACHE_VS_8 0xA268
+#define mmSQ_ALU_CONST_CACHE_VS_9 0xA269
+#define mmSQ_ALU_CONST_CACHE_VS_10 0xA26A
+#define mmSQ_ALU_CONST_CACHE_VS_11 0xA26B
+#define mmSQ_ALU_CONST_CACHE_VS_12 0xA26C
+#define mmSQ_ALU_CONST_CACHE_VS_13 0xA26D
+#define mmSQ_ALU_CONST_CACHE_VS_14 0xA26E
+#define mmSQ_ALU_CONST_CACHE_VS_15 0xA26F
+#define mmSQ_ALU_CONST_CACHE_GS_0 0xA270
+#define mmSQ_ALU_CONST_CACHE_GS_1 0xA271
+#define mmSQ_ALU_CONST_CACHE_GS_2 0xA272
+#define mmSQ_ALU_CONST_CACHE_GS_3 0xA273
+#define mmSQ_ALU_CONST_CACHE_GS_4 0xA274
+#define mmSQ_ALU_CONST_CACHE_GS_5 0xA275
+#define mmSQ_ALU_CONST_CACHE_GS_6 0xA276
+#define mmSQ_ALU_CONST_CACHE_GS_7 0xA277
+#define mmSQ_ALU_CONST_CACHE_GS_8 0xA278
+#define mmSQ_ALU_CONST_CACHE_GS_9 0xA279
+#define mmSQ_ALU_CONST_CACHE_GS_10 0xA27A
+#define mmSQ_ALU_CONST_CACHE_GS_11 0xA27B
+#define mmSQ_ALU_CONST_CACHE_GS_12 0xA27C
+#define mmSQ_ALU_CONST_CACHE_GS_13 0xA27D
+#define mmSQ_ALU_CONST_CACHE_GS_14 0xA27E
+#define mmSQ_ALU_CONST_CACHE_GS_15 0xA27F
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_0 0xA050
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_1 0xA051
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_2 0xA052
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_3 0xA053
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_4 0xA054
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_5 0xA055
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_6 0xA056
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_7 0xA057
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_8 0xA058
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_9 0xA059
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_10 0xA05A
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_11 0xA05B
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_12 0xA05C
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_13 0xA05D
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_14 0xA05E
+#define mmSQ_ALU_CONST_BUFFER_SIZE_PS_15 0xA05F
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_0 0xA060
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_1 0xA061
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_2 0xA062
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_3 0xA063
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_4 0xA064
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_5 0xA065
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_6 0xA066
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_7 0xA067
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_8 0xA068
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_9 0xA069
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_10 0xA06A
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_11 0xA06B
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_12 0xA06C
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_13 0xA06D
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_14 0xA06E
+#define mmSQ_ALU_CONST_BUFFER_SIZE_VS_15 0xA06F
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_0 0xA070
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_1 0xA071
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_2 0xA072
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_3 0xA073
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_4 0xA074
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_5 0xA075
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_6 0xA076
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_7 0xA077
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_8 0xA078
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_9 0xA079
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_10 0xA07A
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_11 0xA07B
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_12 0xA07C
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_13 0xA07D
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_14 0xA07E
+#define mmSQ_ALU_CONST_BUFFER_SIZE_GS_15 0xA07F
+
+#define mmSPI_VS_OUT_ID_0 0xA185
+#define mmSPI_VS_OUT_ID_1 0xA186
+#define mmSPI_VS_OUT_ID_2 0xA187
+#define mmSPI_VS_OUT_ID_3 0xA188
+#define mmSPI_VS_OUT_ID_4 0xA189
+#define mmSPI_VS_OUT_ID_5 0xA18A
+#define mmSPI_VS_OUT_ID_6 0xA18B
+#define mmSPI_VS_OUT_ID_7 0xA18C
+#define mmSPI_VS_OUT_ID_8 0xA18D
+#define mmSPI_VS_OUT_ID_9 0xA18E
+#define mmSPI_PS_INPUT_CNTL_0 0xA191
+#define mmSPI_PS_INPUT_CNTL_1 0xA192
+#define mmSPI_PS_INPUT_CNTL_2 0xA193
+#define mmSPI_PS_INPUT_CNTL_3 0xA194
+#define mmSPI_PS_INPUT_CNTL_4 0xA195
+#define mmSPI_PS_INPUT_CNTL_5 0xA196
+#define mmSPI_PS_INPUT_CNTL_6 0xA197
+#define mmSPI_PS_INPUT_CNTL_7 0xA198
+#define mmSPI_PS_INPUT_CNTL_8 0xA199
+#define mmSPI_PS_INPUT_CNTL_9 0xA19A
+#define mmSPI_PS_INPUT_CNTL_10 0xA19B
+#define mmSPI_PS_INPUT_CNTL_11 0xA19C
+#define mmSPI_PS_INPUT_CNTL_12 0xA19D
+#define mmSPI_PS_INPUT_CNTL_13 0xA19E
+#define mmSPI_PS_INPUT_CNTL_14 0xA19F
+#define mmSPI_PS_INPUT_CNTL_15 0xA1A0
+#define mmSPI_PS_INPUT_CNTL_16 0xA1A1
+#define mmSPI_PS_INPUT_CNTL_17 0xA1A2
+#define mmSPI_PS_INPUT_CNTL_18 0xA1A3
+#define mmSPI_PS_INPUT_CNTL_19 0xA1A4
+#define mmSPI_PS_INPUT_CNTL_20 0xA1A5
+#define mmSPI_PS_INPUT_CNTL_21 0xA1A6
+#define mmSPI_PS_INPUT_CNTL_22 0xA1A7
+#define mmSPI_PS_INPUT_CNTL_23 0xA1A8
+#define mmSPI_PS_INPUT_CNTL_24 0xA1A9
+#define mmSPI_PS_INPUT_CNTL_25 0xA1AA
+#define mmSPI_PS_INPUT_CNTL_26 0xA1AB
+#define mmSPI_PS_INPUT_CNTL_27 0xA1AC
+#define mmSPI_PS_INPUT_CNTL_28 0xA1AD
+#define mmSPI_PS_INPUT_CNTL_29 0xA1AE
+#define mmSPI_PS_INPUT_CNTL_30 0xA1AF
+#define mmSPI_PS_INPUT_CNTL_31 0xA1B0
+#define mmSPI_VS_OUT_CONFIG 0xA1B1
+#define mmSPI_THREAD_GROUPING 0xA1B2
+#define mmSPI_PS_IN_CONTROL_0 0xA1B3
+#define mmSPI_PS_IN_CONTROL_1 0xA1B4
+#define mmSPI_INTERP_CONTROL_0 0xA1B5
+#define mmSPI_INPUT_Z 0xA1B6
+#define mmSPI_FOG_CNTL 0xA1B7
+#define mmSPI_FOG_FUNC_SCALE 0xA1B8
+#define mmSPI_FOG_FUNC_BIAS 0xA1B9
+
+#define mmSX_MISC 0xA0D4
+#define mmSX_ALPHA_TEST_CONTROL 0xA104
+#define mmSX_ALPHA_REF 0xA10E
+
+#define mmDB_DEPTH_BASE 0xA003
+#define mmDB_DEPTH_INFO 0xA004
+#define mmDB_HTILE_DATA_BASE 0xA005
+#define mmDB_DEPTH_SIZE 0xA000
+#define mmDB_DEPTH_VIEW 0xA001
+#define mmDB_RENDER_CONTROL 0xA343
+#define mmDB_RENDER_OVERRIDE 0xA344
+#define mmDB_SHADER_CONTROL 0xA203
+#define mmDB_STENCIL_CLEAR 0xA00A
+#define mmDB_DEPTH_CLEAR 0xA00B
+#define mmDB_HTILE_SURFACE 0xA349
+#define mmDB_PRELOAD_CONTROL 0xA34C
+#define mmDB_PREFETCH_LIMIT 0xA34D
+#define mmDB_STENCILREFMASK 0xA10C
+#define mmDB_STENCILREFMASK_BF 0xA10D
+#define mmDB_SRESULTS_COMPARE_STATE0 0xA34A
+#define mmDB_SRESULTS_COMPARE_STATE1 0xA34B
+#define mmDB_DEPTH_CONTROL 0xA200
+#define mmDB_ALPHA_TO_MASK 0xA351
+
+#define mmCB_CLEAR_RED_R6XX 0xA048
+#define mmCB_CLEAR_GREEN_R6XX 0xA049
+#define mmCB_CLEAR_BLUE_R6XX 0xA04A
+#define mmCB_CLEAR_ALPHA_R6XX 0xA04B
+#define mmCB_BLEND_RED 0xA105
+#define mmCB_BLEND_GREEN 0xA106
+#define mmCB_BLEND_BLUE 0xA107
+#define mmCB_BLEND_ALPHA 0xA108
+#define mmCB_FOG_RED_R6XX 0xA109
+#define mmCB_FOG_GREEN_R6XX 0xA10A
+#define mmCB_FOG_BLUE_R6XX 0xA10B
+#define mmCB_BLEND_CONTROL 0xA201
+#define mmCB_COLOR_CONTROL 0xA202
+#define mmCB_BLEND0_CONTROL 0xA1E0
+#define mmCB_BLEND1_CONTROL 0xA1E1
+#define mmCB_BLEND2_CONTROL 0xA1E2
+#define mmCB_BLEND3_CONTROL 0xA1E3
+#define mmCB_BLEND4_CONTROL 0xA1E4
+#define mmCB_BLEND5_CONTROL 0xA1E5
+#define mmCB_BLEND6_CONTROL 0xA1E6
+#define mmCB_BLEND7_CONTROL 0xA1E7
+#define mmCB_CLRCMP_CONTROL 0xA30C
+#define mmCB_CLRCMP_SRC 0xA30D
+#define mmCB_CLRCMP_DST 0xA30E
+#define mmCB_CLRCMP_MSK 0xA30F
+#define mmCB_COLOR0_BASE 0xA010
+#define mmCB_COLOR1_BASE 0xA011
+#define mmCB_COLOR2_BASE 0xA012
+#define mmCB_COLOR3_BASE 0xA013
+#define mmCB_COLOR4_BASE 0xA014
+#define mmCB_COLOR5_BASE 0xA015
+#define mmCB_COLOR6_BASE 0xA016
+#define mmCB_COLOR7_BASE 0xA017
+#define mmCB_COLOR0_SIZE 0xA018
+#define mmCB_COLOR1_SIZE 0xA019
+#define mmCB_COLOR2_SIZE 0xA01A
+#define mmCB_COLOR3_SIZE 0xA01B
+#define mmCB_COLOR4_SIZE 0xA01C
+#define mmCB_COLOR5_SIZE 0xA01D
+#define mmCB_COLOR6_SIZE 0xA01E
+#define mmCB_COLOR7_SIZE 0xA01F
+#define mmCB_COLOR0_VIEW 0xA020
+#define mmCB_COLOR1_VIEW 0xA021
+#define mmCB_COLOR2_VIEW 0xA022
+#define mmCB_COLOR3_VIEW 0xA023
+#define mmCB_COLOR4_VIEW 0xA024
+#define mmCB_COLOR5_VIEW 0xA025
+#define mmCB_COLOR6_VIEW 0xA026
+#define mmCB_COLOR7_VIEW 0xA027
+#define mmCB_COLOR0_INFO 0xA028
+#define mmCB_COLOR1_INFO 0xA029
+#define mmCB_COLOR2_INFO 0xA02A
+#define mmCB_COLOR3_INFO 0xA02B
+#define mmCB_COLOR4_INFO 0xA02C
+#define mmCB_COLOR5_INFO 0xA02D
+#define mmCB_COLOR6_INFO 0xA02E
+#define mmCB_COLOR7_INFO 0xA02F
+#define mmCB_COLOR0_TILE 0xA030
+#define mmCB_COLOR1_TILE 0xA031
+#define mmCB_COLOR2_TILE 0xA032
+#define mmCB_COLOR3_TILE 0xA033
+#define mmCB_COLOR4_TILE 0xA034
+#define mmCB_COLOR5_TILE 0xA035
+#define mmCB_COLOR6_TILE 0xA036
+#define mmCB_COLOR7_TILE 0xA037
+#define mmCB_COLOR0_FRAG 0xA038
+#define mmCB_COLOR1_FRAG 0xA039
+#define mmCB_COLOR2_FRAG 0xA03A
+#define mmCB_COLOR3_FRAG 0xA03B
+#define mmCB_COLOR4_FRAG 0xA03C
+#define mmCB_COLOR5_FRAG 0xA03D
+#define mmCB_COLOR6_FRAG 0xA03E
+#define mmCB_COLOR7_FRAG 0xA03F
+#define mmCB_COLOR0_MASK 0xA040
+#define mmCB_COLOR1_MASK 0xA041
+#define mmCB_COLOR2_MASK 0xA042
+#define mmCB_COLOR3_MASK 0xA043
+#define mmCB_COLOR4_MASK 0xA044
+#define mmCB_COLOR5_MASK 0xA045
+#define mmCB_COLOR6_MASK 0xA046
+#define mmCB_COLOR7_MASK 0xA047
+#define mmCB_CLEAR_RED_R6XX 0xA048
+#define mmCB_CLEAR_GREEN_R6XX 0xA049
+#define mmCB_CLEAR_BLUE_R6XX 0xA04A
+#define mmCB_CLEAR_ALPHA_R6XX 0xA04B
+#define mmCB_TARGET_MASK 0xA08E
+#define mmCB_SHADER_MASK 0xA08F
+#define mmCB_SHADER_CONTROL 0xA1E8
+
+#define mmSQ_VTX_BASE_VTX_LOC 0xF3FC
+#define mmSQ_VTX_START_INST_LOC 0xF3FD
+
+#endif /* _R700_CHIPOFFSET_H_ */
+
diff --git a/src/mesa/drivers/dri/r600/r700_clear.c b/src/mesa/drivers/dri/r600/r700_clear.c
new file mode 100644
index 0000000000..c6546ab00c
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_clear.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/enums.h"
+#include "swrast/swrast.h"
+
+#include "radeon_lock.h"
+#include "r600_context.h"
+
+#include "r700_shaderinst.h"
+#include "r600_emit.h"
+#include "r700_clear.h"
+
+static GLboolean r700ClearFast(context_t *context, GLbitfield mask)
+{
+ /* TODO, fast clear need implementation */
+ return GL_FALSE;
+}
+
+void r700Clear(GLcontext * ctx, GLbitfield mask)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&context->radeon);
+ const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
+ GLbitfield swrast_mask = 0, tri_mask = 0;
+ int i;
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %x\n", __func__, mask);
+
+ if( GL_TRUE == r700ClearFast(context, mask) )
+ {
+ return;
+ }
+ if (!context->radeon.radeonScreen->driScreen->dri2.enabled) {
+ LOCK_HARDWARE(&context->radeon);
+ UNLOCK_HARDWARE(&context->radeon);
+ if (dPriv->numClipRects == 0)
+ return;
+ }
+
+ R600_NEWPRIM(context);
+
+ if (colorMask == ~0)
+ tri_mask |= (mask & BUFFER_BITS_COLOR);
+ else
+ tri_mask |= (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT));
+
+
+ /* HW stencil */
+ if (mask & BUFFER_BIT_STENCIL) {
+ tri_mask |= BUFFER_BIT_STENCIL;
+ }
+
+ /* HW depth */
+ if (mask & BUFFER_BIT_DEPTH) {
+ tri_mask |= BUFFER_BIT_DEPTH;
+ }
+
+ /* If we're doing a tri pass for depth/stencil, include a likely color
+ * buffer with it.
+ */
+
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ GLuint bufBit = 1 << i;
+ if ((tri_mask) & bufBit) {
+ if (!fb->Attachment[i].Renderbuffer->ClassID) {
+ tri_mask &= ~bufBit;
+ swrast_mask |= bufBit;
+ }
+ }
+ }
+
+ /* SW fallback clearing */
+ swrast_mask = mask & ~tri_mask;
+
+ if (tri_mask) {
+ radeonUserClear(ctx, tri_mask);
+ }
+
+ if (swrast_mask) {
+ radeon_print(RADEON_FALLBACKS, RADEON_IMPORTANT, "%s: swrast clear, mask: %x\n",
+ __FUNCTION__, swrast_mask);
+ _swrast_Clear(ctx, swrast_mask);
+ }
+
+}
+
+
diff --git a/src/mesa/drivers/dri/r600/r700_clear.h b/src/mesa/drivers/dri/r600/r700_clear.h
new file mode 100644
index 0000000000..bed1d3a90e
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_clear.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#ifndef __r700_CLEAR_H__
+#define __r700_CLEAR_H__
+
+extern void r700Clear(GLcontext * ctx, GLbitfield mask);
+
+#endif /* __r700_CLEAR_H__ */
diff --git a/src/mesa/drivers/dri/r600/r700_debug.c b/src/mesa/drivers/dri/r600/r700_debug.c
new file mode 100644
index 0000000000..cd1ba9eca3
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_debug.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#include "r700_debug.h"
+#include "radeon_debug.h"
+
+void DumpHwBinary(int type, void *addr, int size)
+{
+ int i;
+ unsigned int *pHw = (unsigned int *)addr;
+
+ return;
+
+ switch (type)
+ {
+ case DUMP_PIXEL_SHADER:
+ radeon_print(RADEON_SHADER, RADEON_TRACE, "Pixel Shader\n");
+ break;
+ case DUMP_VERTEX_SHADER:
+ radeon_print(RADEON_SHADER, RADEON_TRACE, "Vertex Shader\n");
+ break;
+ case DUMP_FETCH_SHADER:
+ radeon_print(RADEON_SHADER, RADEON_TRACE, "Fetch Shader\n");
+ break;
+ }
+
+ for (i = 0; i < size; i++)
+ {
+ radeon_print(RADEON_SHADER, RADEON_TRACE, "0x%08x,\t", *pHw);
+ if (i%4 == 3)
+ radeon_print(RADEON_SHADER, RADEON_TRACE, "0x%08x\n", *pHw);
+ pHw++;
+
+ }
+}
+
diff --git a/src/mesa/drivers/dri/r600/r700_debug.h b/src/mesa/drivers/dri/r600/r700_debug.h
new file mode 100644
index 0000000000..c0921bf610
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_debug.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#ifndef _R700_DEBUG_H_
+#define _R700_DEBUG_H_
+enum R700_DUMP_TYPE
+{
+ DUMP_VERTEX_SHADER = 0x1,
+ DUMP_PIXEL_SHADER = 0x2,
+ DUMP_FETCH_SHADER = 0x4,
+};
+
+extern void DumpHwBinary(int, void *, int);
+
+#endif /*_R700_DEBUG_H_*/
diff --git a/src/mesa/drivers/dri/r600/r700_driconf.h b/src/mesa/drivers/dri/r600/r700_driconf.h
new file mode 100644
index 0000000000..a9e2152344
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_driconf.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _R700_DRICONF_H_
+#define _R700_DRICONF_H_
+
+#define DRI_CONF_FP_OPTIMIZATION_SPEED 0
+#define DRI_CONF_FP_OPTIMIZATION_QUALITY 1
+
+#endif /* _R700_DRICONF_H_ */
diff --git a/src/mesa/drivers/dri/r600/r700_fragprog.c b/src/mesa/drivers/dri/r600/r700_fragprog.c
new file mode 100644
index 0000000000..78ce3ae436
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_fragprog.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "main/imports.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_statevars.h"
+
+#include "r600_context.h"
+#include "r600_cmdbuf.h"
+
+#include "r700_fragprog.h"
+
+#include "r700_debug.h"
+
+//TODO : Validate FP input with VP output.
+void Map_Fragment_Program(r700_AssemblerBase *pAsm,
+ struct gl_fragment_program *mesa_fp)
+{
+ unsigned int unBit;
+ unsigned int i;
+ GLuint ui;
+
+ pAsm->number_used_registers = 0;
+
+//Input mapping : mesa_fp->Base.InputsRead set the flag, set in
+ //The flags parsed in parse_attrib_binding. FRAG_ATTRIB_COLx, FRAG_ATTRIB_TEXx, ...
+ //MUST match order in Map_Vertex_Output
+ unBit = 1 << FRAG_ATTRIB_WPOS;
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ pAsm->uiFP_AttributeMap[FRAG_ATTRIB_WPOS] = pAsm->number_used_registers++;
+ }
+
+ unBit = 1 << FRAG_ATTRIB_COL0;
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ pAsm->uiFP_AttributeMap[FRAG_ATTRIB_COL0] = pAsm->number_used_registers++;
+ }
+
+ unBit = 1 << FRAG_ATTRIB_COL1;
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ pAsm->uiFP_AttributeMap[FRAG_ATTRIB_COL1] = pAsm->number_used_registers++;
+ }
+
+ unBit = 1 << FRAG_ATTRIB_FOGC;
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ pAsm->uiFP_AttributeMap[FRAG_ATTRIB_FOGC] = pAsm->number_used_registers++;
+ }
+
+ for(i=0; i<8; i++)
+ {
+ unBit = 1 << (FRAG_ATTRIB_TEX0 + i);
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ pAsm->uiFP_AttributeMap[FRAG_ATTRIB_TEX0 + i] = pAsm->number_used_registers++;
+ }
+ }
+
+/* Map temporary registers (GPRs) */
+ pAsm->starting_temp_register_number = pAsm->number_used_registers;
+
+ if(mesa_fp->Base.NumNativeTemporaries >= mesa_fp->Base.NumTemporaries)
+ {
+ pAsm->number_used_registers += mesa_fp->Base.NumNativeTemporaries;
+ }
+ else
+ {
+ pAsm->number_used_registers += mesa_fp->Base.NumTemporaries;
+ }
+
+/* Output mapping */
+ pAsm->number_of_exports = 0;
+ pAsm->number_of_colorandz_exports = 0; /* don't include stencil and mask out. */
+ pAsm->starting_export_register_number = pAsm->number_used_registers;
+ unBit = 1 << FRAG_RESULT_COLOR;
+ if(mesa_fp->Base.OutputsWritten & unBit)
+ {
+ pAsm->uiFP_OutputMap[FRAG_RESULT_COLOR] = pAsm->number_used_registers++;
+ pAsm->number_of_exports++;
+ pAsm->number_of_colorandz_exports++;
+ }
+ unBit = 1 << FRAG_RESULT_DEPTH;
+ if(mesa_fp->Base.OutputsWritten & unBit)
+ {
+ pAsm->depth_export_register_number = pAsm->number_used_registers;
+ pAsm->uiFP_OutputMap[FRAG_RESULT_DEPTH] = pAsm->number_used_registers++;
+ pAsm->number_of_exports++;
+ pAsm->number_of_colorandz_exports++;
+ pAsm->pR700Shader->depthIsExported = 1;
+ }
+
+ pAsm->pucOutMask = (unsigned char*) MALLOC(pAsm->number_of_exports);
+ for(ui=0; ui<pAsm->number_of_exports; ui++)
+ {
+ pAsm->pucOutMask[ui] = 0x0;
+ }
+
+ pAsm->uFirstHelpReg = pAsm->number_used_registers;
+}
+
+GLboolean Find_Instruction_Dependencies_fp(struct r700_fragment_program *fp,
+ struct gl_fragment_program *mesa_fp)
+{
+ GLuint i, j;
+ GLint * puiTEMPwrites;
+ struct prog_instruction * pILInst;
+ InstDeps *pInstDeps;
+ struct prog_instruction * texcoord_DepInst;
+ GLint nDepInstID;
+
+ puiTEMPwrites = (GLint*) MALLOC(sizeof(GLuint)*mesa_fp->Base.NumTemporaries);
+ for(i=0; i<mesa_fp->Base.NumTemporaries; i++)
+ {
+ puiTEMPwrites[i] = -1;
+ }
+
+ pInstDeps = (InstDeps*)MALLOC(sizeof(InstDeps)*mesa_fp->Base.NumInstructions);
+
+ for(i=0; i<mesa_fp->Base.NumInstructions; i++)
+ {
+ pInstDeps[i].nDstDep = -1;
+ pILInst = &(mesa_fp->Base.Instructions[i]);
+
+ //Dst
+ if(pILInst->DstReg.File == PROGRAM_TEMPORARY)
+ {
+ //Set lastwrite for the temp
+ puiTEMPwrites[pILInst->DstReg.Index] = i;
+ }
+
+ //Src
+ for(j=0; j<3; j++)
+ {
+ if(pILInst->SrcReg[j].File == PROGRAM_TEMPORARY)
+ {
+ //Set dep.
+ pInstDeps[i].nSrcDeps[j] = puiTEMPwrites[pILInst->SrcReg[j].Index];
+ }
+ else
+ {
+ pInstDeps[i].nSrcDeps[j] = -1;
+ }
+ }
+ }
+
+ fp->r700AsmCode.pInstDeps = pInstDeps;
+
+ FREE(puiTEMPwrites);
+
+ //Find dep for tex inst
+ for(i=0; i<mesa_fp->Base.NumInstructions; i++)
+ {
+ pILInst = &(mesa_fp->Base.Instructions[i]);
+
+ if(GL_TRUE == IsTex(pILInst->Opcode))
+ { //src0 is the tex coord register, src1 is texunit, src2 is textype
+ nDepInstID = pInstDeps[i].nSrcDeps[0];
+ if(nDepInstID >= 0)
+ {
+ texcoord_DepInst = &(mesa_fp->Base.Instructions[nDepInstID]);
+ if(GL_TRUE == IsAlu(texcoord_DepInst->Opcode) )
+ {
+ pInstDeps[nDepInstID].nDstDep = i;
+ pInstDeps[i].nDstDep = i;
+ }
+ else if(GL_TRUE == IsTex(texcoord_DepInst->Opcode) )
+ {
+ pInstDeps[i].nDstDep = i;
+ }
+ else
+ { //... other deps?
+ }
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean r700TranslateFragmentShader(struct r700_fragment_program *fp,
+ struct gl_fragment_program *mesa_fp)
+{
+ GLuint number_of_colors_exported;
+ GLboolean z_enabled = GL_FALSE;
+ GLuint unBit;
+
+ //Init_Program
+ Init_r700_AssemblerBase( SPT_FP, &(fp->r700AsmCode), &(fp->r700Shader) );
+ Map_Fragment_Program(&(fp->r700AsmCode), mesa_fp);
+
+ if( GL_FALSE == Find_Instruction_Dependencies_fp(fp, mesa_fp) )
+ {
+ return GL_FALSE;
+ }
+
+ if( GL_FALSE == AssembleInstr(mesa_fp->Base.NumInstructions,
+ &(mesa_fp->Base.Instructions[0]),
+ &(fp->r700AsmCode)) )
+ {
+ return GL_FALSE;
+ }
+
+ if(GL_FALSE == Process_Fragment_Exports(&(fp->r700AsmCode), mesa_fp->Base.OutputsWritten) )
+ {
+ return GL_FALSE;
+ }
+
+ fp->r700Shader.nRegs = (fp->r700AsmCode.number_used_registers == 0) ? 0
+ : (fp->r700AsmCode.number_used_registers - 1);
+
+ fp->r700Shader.nParamExports = fp->r700AsmCode.number_of_exports;
+
+ number_of_colors_exported = fp->r700AsmCode.number_of_colorandz_exports;
+
+ unBit = 1 << FRAG_RESULT_DEPTH;
+ if(mesa_fp->Base.OutputsWritten & unBit)
+ {
+ z_enabled = GL_TRUE;
+ number_of_colors_exported--;
+ }
+
+ fp->r700Shader.exportMode = number_of_colors_exported << 1 | z_enabled;
+
+ fp->translated = GL_TRUE;
+
+ return GL_TRUE;
+}
+
+void r700SelectFragmentShader(GLcontext *ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ struct r700_fragment_program *fp = (struct r700_fragment_program *)
+ (ctx->FragmentProgram._Current);
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+ {
+ fp->r700AsmCode.bR6xx = 1;
+ }
+
+ if (GL_FALSE == fp->translated)
+ r700TranslateFragmentShader(fp, &(fp->mesa_program));
+}
+
+void * r700GetActiveFpShaderBo(GLcontext * ctx)
+{
+ struct r700_fragment_program *fp = (struct r700_fragment_program *)
+ (ctx->FragmentProgram._Current);
+
+ return fp->shaderbo;
+}
+
+GLboolean r700SetupFragmentProgram(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ struct r700_fragment_program *fp = (struct r700_fragment_program *)
+ (ctx->FragmentProgram._Current);
+ r700_AssemblerBase *pAsm = &(fp->r700AsmCode);
+ struct gl_fragment_program *mesa_fp = &(fp->mesa_program);
+ struct gl_program_parameter_list *paramList;
+ unsigned int unNumParamData;
+ unsigned int ui, i;
+ unsigned int unNumOfReg;
+ unsigned int unBit;
+ GLuint exportCount;
+
+ if(GL_FALSE == fp->loaded)
+ {
+ if(fp->r700Shader.bNeedsAssembly == GL_TRUE)
+ {
+ Assemble( &(fp->r700Shader) );
+ }
+
+ /* Load fp to gpu */
+ r600EmitShader(ctx,
+ &(fp->shaderbo),
+ (GLvoid *)(fp->r700Shader.pProgram),
+ fp->r700Shader.uShaderBinaryDWORDSize,
+ "FS");
+
+ fp->loaded = GL_TRUE;
+ }
+
+ DumpHwBinary(DUMP_PIXEL_SHADER, (GLvoid *)(fp->r700Shader.pProgram),
+ fp->r700Shader.uShaderBinaryDWORDSize);
+
+ /* TODO : enable this after MemUse fixed *=
+ (context->chipobj.MemUse)(context, fp->shadercode.buf->id);
+ */
+
+ R600_STATECHANGE(context, ps);
+
+ r700->ps.SQ_PGM_RESOURCES_PS.u32All = 0;
+ SETbit(r700->ps.SQ_PGM_RESOURCES_PS.u32All, PGM_RESOURCES__PRIME_CACHE_ON_DRAW_bit);
+
+ r700->ps.SQ_PGM_START_PS.u32All = 0; /* set from buffer obj */
+
+ R600_STATECHANGE(context, spi);
+
+ unNumOfReg = fp->r700Shader.nRegs + 1;
+
+ ui = (r700->SPI_PS_IN_CONTROL_0.u32All & NUM_INTERP_mask) / (1 << NUM_INTERP_shift);
+
+ /* PS uses fragment.position */
+ if (mesa_fp->Base.InputsRead & (1 << FRAG_ATTRIB_WPOS))
+ {
+ ui += 1;
+ SETfield(r700->SPI_PS_IN_CONTROL_0.u32All, ui, NUM_INTERP_shift, NUM_INTERP_mask);
+ SETfield(r700->SPI_PS_IN_CONTROL_0.u32All, CENTERS_ONLY, BARYC_SAMPLE_CNTL_shift, BARYC_SAMPLE_CNTL_mask);
+ SETbit(r700->SPI_PS_IN_CONTROL_0.u32All, POSITION_ENA_bit);
+ SETbit(r700->SPI_INPUT_Z.u32All, PROVIDE_Z_TO_SPI_bit);
+ }
+
+ ui = (unNumOfReg < ui) ? ui : unNumOfReg;
+
+ SETfield(r700->ps.SQ_PGM_RESOURCES_PS.u32All, ui, NUM_GPRS_shift, NUM_GPRS_mask);
+
+ CLEARbit(r700->ps.SQ_PGM_RESOURCES_PS.u32All, UNCACHED_FIRST_INST_bit);
+
+ if(fp->r700Shader.uStackSize) /* we don't use branch for now, it should be zero. */
+ {
+ SETfield(r700->ps.SQ_PGM_RESOURCES_PS.u32All, fp->r700Shader.uStackSize,
+ STACK_SIZE_shift, STACK_SIZE_mask);
+ }
+
+ SETfield(r700->ps.SQ_PGM_EXPORTS_PS.u32All, fp->r700Shader.exportMode,
+ EXPORT_MODE_shift, EXPORT_MODE_mask);
+
+ R600_STATECHANGE(context, db);
+
+ if(fp->r700Shader.killIsUsed)
+ {
+ SETbit(r700->DB_SHADER_CONTROL.u32All, KILL_ENABLE_bit);
+ }
+ else
+ {
+ CLEARbit(r700->DB_SHADER_CONTROL.u32All, KILL_ENABLE_bit);
+ }
+
+ if(fp->r700Shader.depthIsExported)
+ {
+ SETbit(r700->DB_SHADER_CONTROL.u32All, Z_EXPORT_ENABLE_bit);
+ }
+ else
+ {
+ CLEARbit(r700->DB_SHADER_CONTROL.u32All, Z_EXPORT_ENABLE_bit);
+ }
+
+ // emit ps input map
+ unBit = 1 << FRAG_ATTRIB_WPOS;
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_WPOS];
+ 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);
+ }
+
+ unBit = 1 << FRAG_ATTRIB_COL0;
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_COL0];
+ 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);
+ }
+
+ unBit = 1 << FRAG_ATTRIB_COL1;
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_COL1];
+ 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);
+ }
+
+ unBit = 1 << FRAG_ATTRIB_FOGC;
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_FOGC];
+ 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);
+ }
+
+ for(i=0; i<8; i++)
+ {
+ unBit = 1 << (FRAG_ATTRIB_TEX0 + i);
+ if(mesa_fp->Base.InputsRead & unBit)
+ {
+ ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_TEX0 + i];
+ SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
+ SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui,
+ SEMANTIC_shift, SEMANTIC_mask);
+ CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+ }
+ }
+
+ R600_STATECHANGE(context, cb);
+ exportCount = (r700->ps.SQ_PGM_EXPORTS_PS.u32All & EXPORT_MODE_mask) / (1 << EXPORT_MODE_shift);
+ r700->CB_SHADER_CONTROL.u32All = (1 << exportCount) - 1;
+
+ /* sent out shader constants. */
+ paramList = fp->mesa_program.Base.Parameters;
+
+ if(NULL != paramList) {
+ _mesa_load_state_parameters(ctx, paramList);
+
+ if (paramList->NumParameters > R700_MAX_DX9_CONSTS)
+ return GL_FALSE;
+
+ R600_STATECHANGE(context, ps_consts);
+
+ r700->ps.num_consts = paramList->NumParameters;
+
+ unNumParamData = paramList->NumParameters;
+
+ for(ui=0; ui<unNumParamData; ui++) {
+ r700->ps.consts[ui][0].f32All = paramList->ParameterValues[ui][0];
+ r700->ps.consts[ui][1].f32All = paramList->ParameterValues[ui][1];
+ r700->ps.consts[ui][2].f32All = paramList->ParameterValues[ui][2];
+ r700->ps.consts[ui][3].f32All = paramList->ParameterValues[ui][3];
+ }
+ } else
+ r700->ps.num_consts = 0;
+
+ return GL_TRUE;
+}
+
diff --git a/src/mesa/drivers/dri/r600/r700_fragprog.h b/src/mesa/drivers/dri/r600/r700_fragprog.h
new file mode 100644
index 0000000000..cbb108d212
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_fragprog.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _R700_FRAGPROG_H_
+#define _R700_FRAGPROG_H_
+
+#include "r600_context.h"
+#include "r700_assembler.h"
+
+struct r700_fragment_program
+{
+ struct gl_fragment_program mesa_program;
+
+ r700_AssemblerBase r700AsmCode;
+ R700_Shader r700Shader;
+
+ GLboolean translated;
+ GLboolean loaded;
+ GLboolean error;
+
+ void * shaderbo;
+
+ GLboolean WritesDepth;
+ GLuint optimization;
+};
+
+/* Internal */
+void Map_Fragment_Program(r700_AssemblerBase *pAsm,
+ struct gl_fragment_program *mesa_fp);
+GLboolean Find_Instruction_Dependencies_fp(struct r700_fragment_program *fp,
+ struct gl_fragment_program *mesa_fp);
+
+GLboolean r700TranslateFragmentShader(struct r700_fragment_program *fp,
+ struct gl_fragment_program *mesa_vp);
+
+/* Interface */
+extern void r700SelectFragmentShader(GLcontext *ctx);
+
+extern GLboolean r700SetupFragmentProgram(GLcontext * ctx);
+
+extern void * r700GetActiveFpShaderBo(GLcontext * ctx);
+
+#endif /*_R700_FRAGPROG_H_*/
diff --git a/src/mesa/drivers/dri/r600/r700_ioctl.c b/src/mesa/drivers/dri/r600/r700_ioctl.c
new file mode 100644
index 0000000000..72a8978976
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_ioctl.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include <sched.h>
+#include <errno.h>
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "main/simple_list.h"
+#include "swrast/swrast.h"
+
+#include "radeon_common.h"
+#include "radeon_lock.h"
+#include "r600_context.h"
+
+#include "r700_ioctl.h"
+#include "r700_clear.h"
+
+
+void r700InitIoctlFuncs(struct dd_function_table *functions)
+{
+ functions->Clear = r700Clear;
+ functions->Finish = radeonFinish;
+ functions->Flush = radeonFlush;
+}
diff --git a/src/mesa/drivers/dri/r600/r700_ioctl.h b/src/mesa/drivers/dri/r600/r700_ioctl.h
new file mode 100644
index 0000000000..414dc3e23e
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_ioctl.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef __R700_IOCTL_H__
+#define __R700_IOCTL_H__
+
+#include "r600_context.h"
+#include "radeon_drm.h"
+
+extern void r700InitIoctlFuncs(struct dd_function_table *functions);
+
+#endif /* __R700_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/r600/r700_oglprog.c b/src/mesa/drivers/dri/r600/r700_oglprog.c
new file mode 100644
index 0000000000..5290ef31be
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_oglprog.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include <string.h>
+
+#include "main/glheader.h"
+#include "main/imports.h"
+
+#include "shader/program.h"
+#include "tnl/tnl.h"
+
+#include "r600_context.h"
+#include "r600_emit.h"
+
+#include "r700_oglprog.h"
+#include "r700_fragprog.h"
+#include "r700_vertprog.h"
+
+
+static struct gl_program *r700NewProgram(GLcontext * ctx,
+ GLenum target,
+ GLuint id)
+{
+ struct gl_program *pProgram = NULL;
+
+ struct r700_vertex_program_cont *vpc;
+ struct r700_fragment_program *fp;
+
+ radeon_print(RADEON_SHADER, RADEON_VERBOSE,
+ "%s %u, %u\n", __func__, target, id);
+
+ switch (target)
+ {
+ case GL_VERTEX_STATE_PROGRAM_NV:
+ case GL_VERTEX_PROGRAM_ARB:
+ vpc = CALLOC_STRUCT(r700_vertex_program_cont);
+ pProgram = _mesa_init_vertex_program(ctx,
+ &vpc->mesa_program,
+ target,
+ id);
+ break;
+ case GL_FRAGMENT_PROGRAM_NV:
+ case GL_FRAGMENT_PROGRAM_ARB:
+ fp = CALLOC_STRUCT(r700_fragment_program);
+ pProgram = _mesa_init_fragment_program(ctx,
+ &fp->mesa_program,
+ target,
+ id);
+ fp->translated = GL_FALSE;
+ fp->loaded = GL_FALSE;
+
+ fp->shaderbo = NULL;
+
+ break;
+ default:
+ _mesa_problem(ctx, "Bad target in r700NewProgram");
+ }
+
+ return pProgram;
+}
+
+static void r700DeleteProgram(GLcontext * ctx, struct gl_program *prog)
+{
+ struct r700_vertex_program_cont * vpc;
+ struct r700_vertex_program *vp, *tmp;
+ struct r700_fragment_program * fp;
+
+ radeon_print(RADEON_SHADER, RADEON_VERBOSE,
+ "%s %p\n", __func__, prog);
+
+ switch (prog->Target)
+ {
+ case GL_VERTEX_STATE_PROGRAM_NV:
+ case GL_VERTEX_PROGRAM_ARB:
+ vpc = (struct r700_vertex_program_cont*)prog;
+ vp = vpc->progs;
+ while (vp) {
+ tmp = vp->next;
+ /* Release DMA region */
+
+ r600DeleteShader(ctx, vp->shaderbo);
+
+ /* Clean up */
+ Clean_Up_Assembler(&(vp->r700AsmCode));
+ Clean_Up_Shader(&(vp->r700Shader));
+ _mesa_free(vp);
+ vp = tmp;
+ }
+ break;
+ case GL_FRAGMENT_PROGRAM_NV:
+ case GL_FRAGMENT_PROGRAM_ARB:
+ fp = (struct r700_fragment_program*)prog;
+ /* Release DMA region */
+
+ r600DeleteShader(ctx, fp->shaderbo);
+
+ /* Clean up */
+ Clean_Up_Assembler(&(fp->r700AsmCode));
+ Clean_Up_Shader(&(fp->r700Shader));
+ break;
+ default:
+ _mesa_problem(ctx, "Bad target in r700NewProgram");
+ }
+
+ _mesa_delete_program(ctx, prog);
+}
+
+static void
+r700ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog)
+{
+
+}
+
+static GLboolean r700IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
+{
+
+ return GL_TRUE;
+}
+
+void r700InitShaderFuncs(struct dd_function_table *functions)
+{
+ functions->NewProgram = r700NewProgram;
+ functions->DeleteProgram = r700DeleteProgram;
+ functions->ProgramStringNotify = r700ProgramStringNotify;
+ functions->IsProgramNative = r700IsProgramNative;
+}
diff --git a/src/mesa/drivers/dri/r600/r700_oglprog.h b/src/mesa/drivers/dri/r600/r700_oglprog.h
new file mode 100644
index 0000000000..fe2e9d1974
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_oglprog.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#ifndef _R700_OGLPROG_H_
+#define _R700_OGLPROG_H_
+#include "r600_context.h"
+
+extern void r700InitShaderFuncs(struct dd_function_table *functions);
+
+#endif /*_R700_OGLPROG_H_*/
diff --git a/src/mesa/drivers/dri/r600/r700_render.c b/src/mesa/drivers/dri/r600/r700_render.c
new file mode 100644
index 0000000000..b1c3648ca5
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_render.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ * CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#include "main/glheader.h"
+#include "main/state.h"
+#include "main/imports.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "main/dd.h"
+#include "main/simple_list.h"
+#include "main/api_arrayelt.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "vbo/vbo.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_vp_build.h"
+#include "tnl/t_context.h"
+#include "tnl/t_vertex.h"
+#include "tnl/t_pipeline.h"
+
+#include "r600_context.h"
+#include "r600_cmdbuf.h"
+
+#include "r600_tex.h"
+
+#include "r700_vertprog.h"
+#include "r700_fragprog.h"
+#include "r700_state.h"
+
+#include "radeon_common_context.h"
+
+void r700WaitForIdle(context_t *context);
+void r700WaitForIdleClean(context_t *context);
+GLboolean r700SendTextureState(context_t *context);
+static unsigned int r700PrimitiveType(int prim);
+void r600UpdateTextureState(GLcontext * ctx);
+GLboolean r700SyncSurf(context_t *context,
+ struct radeon_bo *pbo,
+ uint32_t read_domain,
+ uint32_t write_domain,
+ uint32_t sync_type);
+
+void r700WaitForIdle(context_t *context)
+{
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_RENDER | RADEON_STATE, RADEON_TRACE, "%s\n", __func__);
+ BEGIN_BATCH_NO_AUTOSTATE(3);
+
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
+ R600_OUT_BATCH(mmWAIT_UNTIL - ASIC_CONFIG_BASE_INDEX);
+ R600_OUT_BATCH(WAIT_3D_IDLE_bit);
+
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+void r700WaitForIdleClean(context_t *context)
+{
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_RENDER | RADEON_STATE, RADEON_TRACE, "%s\n", __func__);
+ BEGIN_BATCH_NO_AUTOSTATE(5);
+
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
+ R600_OUT_BATCH(CACHE_FLUSH_AND_INV_EVENT);
+
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
+ R600_OUT_BATCH(mmWAIT_UNTIL - ASIC_CONFIG_BASE_INDEX);
+ R600_OUT_BATCH(WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit);
+
+ END_BATCH();
+ COMMIT_BATCH();
+}
+
+void r700Start3D(context_t *context)
+{
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_RENDER | RADEON_STATE, RADEON_TRACE, "%s\n", __func__);
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+ {
+ BEGIN_BATCH_NO_AUTOSTATE(2);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_START_3D_CMDBUF, 0));
+ R600_OUT_BATCH(0);
+ END_BATCH();
+ }
+
+ BEGIN_BATCH_NO_AUTOSTATE(3);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_CONTEXT_CONTROL, 1));
+ R600_OUT_BATCH(0x80000000);
+ R600_OUT_BATCH(0x80000000);
+ END_BATCH();
+
+ COMMIT_BATCH();
+
+ r700WaitForIdleClean(context);
+}
+
+GLboolean r700SyncSurf(context_t *context,
+ struct radeon_bo *pbo,
+ uint32_t read_domain,
+ uint32_t write_domain,
+ uint32_t sync_type)
+{
+ BATCH_LOCALS(&context->radeon);
+ radeon_print(RADEON_RENDER | RADEON_STATE, RADEON_TRACE, "%s\n", __func__);
+ uint32_t cp_coher_size;
+
+ if (!pbo)
+ return GL_FALSE;
+
+ if (pbo->size == 0xffffffff)
+ cp_coher_size = 0xffffffff;
+ else
+ cp_coher_size = ((pbo->size + 255) >> 8);
+
+ BEGIN_BATCH_NO_AUTOSTATE(5 + 2);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SURFACE_SYNC, 3));
+ R600_OUT_BATCH(sync_type);
+ R600_OUT_BATCH(cp_coher_size);
+ R600_OUT_BATCH(0);
+ R600_OUT_BATCH(10);
+ R600_OUT_BATCH_RELOC(0,
+ pbo,
+ 0,
+ read_domain, write_domain, 0);
+ END_BATCH();
+ COMMIT_BATCH();
+
+ return GL_TRUE;
+}
+
+static unsigned int r700PrimitiveType(int prim)
+{
+ switch (prim & PRIM_MODE_MASK)
+ {
+ case GL_POINTS:
+ return DI_PT_POINTLIST;
+ break;
+ case GL_LINES:
+ return DI_PT_LINELIST;
+ break;
+ case GL_LINE_STRIP:
+ return DI_PT_LINESTRIP;
+ break;
+ case GL_LINE_LOOP:
+ return DI_PT_LINELOOP;
+ break;
+ case GL_TRIANGLES:
+ return DI_PT_TRILIST;
+ break;
+ case GL_TRIANGLE_STRIP:
+ return DI_PT_TRISTRIP;
+ break;
+ case GL_TRIANGLE_FAN:
+ return DI_PT_TRIFAN;
+ break;
+ case GL_QUADS:
+ return DI_PT_QUADLIST;
+ break;
+ case GL_QUAD_STRIP:
+ return DI_PT_QUADSTRIP;
+ break;
+ case GL_POLYGON:
+ return DI_PT_POLYGON;
+ break;
+ default:
+ assert(0);
+ return -1;
+ break;
+ }
+}
+
+static int r700NumVerts(int num_verts, int prim)
+{
+ int verts_off = 0;
+
+ switch (prim & PRIM_MODE_MASK) {
+ case GL_POINTS:
+ verts_off = 0;
+ break;
+ case GL_LINES:
+ verts_off = num_verts % 2;
+ break;
+ case GL_LINE_STRIP:
+ if (num_verts < 2)
+ verts_off = num_verts;
+ break;
+ case GL_LINE_LOOP:
+ if (num_verts < 2)
+ verts_off = num_verts;
+ break;
+ case GL_TRIANGLES:
+ verts_off = num_verts % 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ if (num_verts < 3)
+ verts_off = num_verts;
+ break;
+ case GL_TRIANGLE_FAN:
+ if (num_verts < 3)
+ verts_off = num_verts;
+ break;
+ case GL_QUADS:
+ verts_off = num_verts % 4;
+ break;
+ case GL_QUAD_STRIP:
+ if (num_verts < 4)
+ verts_off = num_verts;
+ else
+ verts_off = num_verts % 2;
+ break;
+ case GL_POLYGON:
+ if (num_verts < 3)
+ verts_off = num_verts;
+ break;
+ default:
+ assert(0);
+ return -1;
+ break;
+ }
+
+ return num_verts - verts_off;
+}
+
+static void r700RunRenderPrimitive(GLcontext * ctx, int start, int end, int prim)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ BATCH_LOCALS(&context->radeon);
+ int type, i, total_emit;
+ int num_indices;
+ uint32_t vgt_draw_initiator = 0;
+ uint32_t vgt_index_type = 0;
+ uint32_t vgt_primitive_type = 0;
+ uint32_t vgt_num_indices = 0;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *vb = &tnl->vb;
+
+ type = r700PrimitiveType(prim);
+ num_indices = r700NumVerts(end - start, prim);
+
+ radeon_print(RADEON_RENDER, RADEON_TRACE,
+ "%s type %x num_indices %d\n",
+ __func__, type, num_indices);
+
+ if (type < 0 || num_indices <= 0)
+ return;
+
+ total_emit = 3 /* VGT_PRIMITIVE_TYPE */
+ + 2 /* VGT_INDEX_TYPE */
+ + 2 /* NUM_INSTANCES */
+ + num_indices + 3; /* DRAW_INDEX_IMMD */
+
+ BEGIN_BATCH_NO_AUTOSTATE(total_emit);
+ // prim
+ SETfield(vgt_primitive_type, type,
+ VGT_PRIMITIVE_TYPE__PRIM_TYPE_shift, VGT_PRIMITIVE_TYPE__PRIM_TYPE_mask);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
+ R600_OUT_BATCH(mmVGT_PRIMITIVE_TYPE - ASIC_CONFIG_BASE_INDEX);
+ R600_OUT_BATCH(vgt_primitive_type);
+
+ // index type
+ SETfield(vgt_index_type, DI_INDEX_SIZE_32_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask);
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_INDEX_TYPE, 0));
+ R600_OUT_BATCH(vgt_index_type);
+
+ // num instances
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_NUM_INSTANCES, 0));
+ R600_OUT_BATCH(1);
+
+ // draw packet
+ vgt_num_indices = num_indices;
+ SETfield(vgt_draw_initiator, DI_SRC_SEL_IMMEDIATE, SOURCE_SELECT_shift, SOURCE_SELECT_mask);
+ SETfield(vgt_draw_initiator, DI_MAJOR_MODE_0, MAJOR_MODE_shift, MAJOR_MODE_mask);
+
+ R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX_IMMD, (num_indices + 1)));
+ R600_OUT_BATCH(vgt_num_indices);
+ R600_OUT_BATCH(vgt_draw_initiator);
+
+ for (i = start; i < (start + num_indices); i++) {
+ if(vb->Elts)
+ R600_OUT_BATCH(vb->Elts[i]);
+ else
+ R600_OUT_BATCH(i);
+ }
+ END_BATCH();
+ COMMIT_BATCH();
+
+}
+
+/* start 3d, idle, cb/db flush */
+#define PRE_EMIT_STATE_BUFSZ 10 + 5 + 14
+
+static GLuint r700PredictRenderSize(GLcontext* ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct r700_vertex_program *vp = context->selected_vp;
+ struct vertex_buffer *vb = &tnl->vb;
+ GLboolean flushed;
+ GLuint dwords, i;
+ GLuint state_size;
+ /* pre calculate aos count so state prediction works */
+ context->radeon.tcl.aos_count = _mesa_bitcount(vp->mesa_program->Base.InputsRead);
+
+ dwords = PRE_EMIT_STATE_BUFSZ;
+ for (i = 0; i < vb->PrimitiveCount; i++)
+ dwords += vb->Primitive[i].count + 10;
+ state_size = radeonCountStateEmitSize(&context->radeon);
+ flushed = rcommonEnsureCmdBufSpace(&context->radeon,
+ dwords + state_size, __FUNCTION__);
+
+ if (flushed)
+ dwords += radeonCountStateEmitSize(&context->radeon);
+ else
+ dwords += state_size;
+
+ radeon_print(RADEON_RENDER, RADEON_VERBOSE,
+ "%s: total prediction size is %d.\n", __FUNCTION__, dwords);
+ return dwords;
+}
+
+static GLboolean r700RunRender(GLcontext * ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ radeonContextPtr radeon = &context->radeon;
+ unsigned int i, id = 0;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *vb = &tnl->vb;
+ struct radeon_renderbuffer *rrb;
+
+ radeon_print(RADEON_RENDER, RADEON_NORMAL, "%s: cs begin at %d\n",
+ __func__, context->radeon.cmdbuf.cs->cdw);
+
+ /* always emit CB base to prevent
+ * lock ups on some chips.
+ */
+ R600_STATECHANGE(context, cb_target);
+ /* mark vtx as dirty since it changes per-draw */
+ R600_STATECHANGE(context, vtx);
+
+ r700SetScissor(context);
+ r700SetupVertexProgram(ctx);
+ r700SetupFragmentProgram(ctx);
+ r600UpdateTextureState(ctx);
+
+ GLuint emit_end = r700PredictRenderSize(ctx)
+ + context->radeon.cmdbuf.cs->cdw;
+ r700SetupStreams(ctx);
+
+ radeonEmitState(radeon);
+
+ radeon_debug_add_indent();
+ /* richard test code */
+ for (i = 0; i < vb->PrimitiveCount; i++) {
+ GLuint prim = _tnl_translate_prim(&vb->Primitive[i]);
+ GLuint start = vb->Primitive[i].start;
+ GLuint end = vb->Primitive[i].start + vb->Primitive[i].count;
+ r700RunRenderPrimitive(ctx, start, end, prim);
+ }
+ radeon_debug_remove_indent();
+
+ /* Flush render op cached for last several quads. */
+ r700WaitForIdleClean(context);
+
+ rrb = radeon_get_colorbuffer(&context->radeon);
+ if (rrb && rrb->bo)
+ r700SyncSurf(context, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM,
+ CB_ACTION_ENA_bit | (1 << (id + 6)));
+
+ rrb = radeon_get_depthbuffer(&context->radeon);
+ if (rrb && rrb->bo)
+ r700SyncSurf(context, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM,
+ DB_ACTION_ENA_bit | DB_DEST_BASE_ENA_bit);
+
+ radeonReleaseArrays(ctx, ~0);
+
+ radeon_print(RADEON_RENDER, RADEON_TRACE, "%s: cs end at %d\n",
+ __func__, context->radeon.cmdbuf.cs->cdw);
+
+ if ( emit_end < context->radeon.cmdbuf.cs->cdw )
+ WARN_ONCE("Rendering was %d commands larger than predicted size."
+ " We might overflow command buffer.\n", context->radeon.cmdbuf.cs->cdw - emit_end);
+
+ return GL_FALSE;
+}
+
+static GLboolean r700RunNonTCLRender(GLcontext * ctx,
+ struct tnl_pipeline_stage *stage) /* -------------------- */
+{
+ GLboolean bRet = GL_TRUE;
+
+ return bRet;
+}
+
+static GLboolean r700RunTCLRender(GLcontext * ctx, /*----------------------*/
+ struct tnl_pipeline_stage *stage)
+{
+ GLboolean bRet = GL_FALSE;
+
+ /* TODO : sw fallback */
+
+ /* Need shader bo's setup before bo check */
+ r700UpdateShaders(ctx);
+ /**
+
+ * Ensure all enabled and complete textures are uploaded along with any buffers being used.
+ */
+ if(!r600ValidateBuffers(ctx))
+ {
+ return GL_TRUE;
+ }
+
+ bRet = r700RunRender(ctx, stage);
+
+ return bRet;
+ //GL_FALSE will stop to do other pipe stage in _tnl_run_pipeline
+ //The render here DOES finish the whole pipe, so GL_FALSE should be returned for success.
+}
+
+const struct tnl_pipeline_stage _r700_render_stage = {
+ "r700 Hardware Rasterization",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ r700RunNonTCLRender
+};
+
+const struct tnl_pipeline_stage _r700_tcl_stage = {
+ "r700 Hardware Transform, Clipping and Lighting",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ r700RunTCLRender
+};
+
+const struct tnl_pipeline_stage *r700_pipeline[] =
+{
+ &_r700_tcl_stage,
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage,
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_vertex_program_stage,
+
+ &_r700_render_stage,
+ &_tnl_render_stage,
+ 0,
+};
+
+
diff --git a/src/mesa/drivers/dri/r600/r700_shader.c b/src/mesa/drivers/dri/r600/r700_shader.c
new file mode 100644
index 0000000000..b4fd51c137
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_shader.c
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "main/imports.h"
+
+#include "main/glheader.h"
+
+#include "r600_context.h"
+#include "r700_debug.h"
+
+#include "r700_shader.h"
+
+void r700ShaderInit(GLcontext * ctx)
+{
+}
+
+void AddInstToList(TypedShaderList * plstCFInstructions, R700ShaderInstruction * pInst)
+{
+ if(NULL == plstCFInstructions->pTail)
+ { //first
+ plstCFInstructions->pHead = pInst;
+ plstCFInstructions->pTail = pInst;
+ }
+ else
+ {
+ plstCFInstructions->pTail->pNextInst = pInst;
+ plstCFInstructions->pTail = pInst;
+ }
+ pInst->pNextInst = NULL;
+
+ plstCFInstructions->uNumOfNode++;
+}
+
+void Init_R700_Shader(R700_Shader * pShader)
+{
+ pShader->Type = R700_SHADER_INVALID;
+ pShader->pProgram = NULL;
+ pShader->bBinaryShader = GL_FALSE;
+ pShader->bFetchShaderRequired = GL_FALSE;
+ pShader->bNeedsAssembly = GL_FALSE;
+ pShader->bLinksDirty = GL_TRUE;
+ pShader->uShaderBinaryDWORDSize = 0;
+ pShader->nRegs = 0;
+ pShader->nParamExports = 0;
+ pShader->nMemExports = 0;
+ pShader->resource = 0;
+
+ pShader->exportMode = 0;
+ pShader->depthIsImported = GL_FALSE;
+
+ pShader->positionVectorIsExported = GL_FALSE;
+ pShader->miscVectorIsExported = GL_FALSE;
+ pShader->renderTargetArrayIndexIsExported = GL_FALSE;
+ pShader->ccDist0VectorIsExported = GL_FALSE;
+ pShader->ccDist1VectorIsExported = GL_FALSE;
+
+
+ pShader->depthIsExported = GL_FALSE;
+ pShader->stencilRefIsExported = GL_FALSE;
+ pShader->coverageToMaskIsExported = GL_FALSE;
+ pShader->maskIsExported = GL_FALSE;
+ pShader->killIsUsed = GL_FALSE;
+
+ pShader->uCFOffset = 0;
+ pShader->uStackSize = 0;
+ pShader->uMaxCallDepth = 0;
+
+ pShader->bSurfAllocated = GL_FALSE;
+
+ pShader->lstCFInstructions.pHead=NULL;
+ pShader->lstCFInstructions.pTail=NULL;
+ pShader->lstCFInstructions.uNumOfNode=0;
+ pShader->lstALUInstructions.pHead=NULL;
+ pShader->lstALUInstructions.pTail=NULL;
+ pShader->lstALUInstructions.uNumOfNode=0;
+ pShader->lstTEXInstructions.pHead=NULL;
+ pShader->lstTEXInstructions.pTail=NULL;
+ pShader->lstTEXInstructions.uNumOfNode=0;
+ pShader->lstVTXInstructions.pHead=NULL;
+ pShader->lstVTXInstructions.pTail=NULL;
+ pShader->lstVTXInstructions.uNumOfNode=0;
+}
+
+void AddCFInstruction(R700_Shader *pShader, R700ControlFlowInstruction *pCFInst)
+{
+ R700ControlFlowSXClause* pSXClause;
+ R700ControlFlowSMXClause* pSMXClause;
+
+ pCFInst->m_uIndex = pShader->lstCFInstructions.uNumOfNode;
+ AddInstToList(&(pShader->lstCFInstructions),
+ (R700ShaderInstruction*)pCFInst);
+ pShader->uShaderBinaryDWORDSize += GetInstructionSize(pCFInst->m_ShaderInstType);
+
+ pSXClause = NULL;
+ pSMXClause = NULL;
+ switch (pCFInst->m_ShaderInstType)
+ {
+ case SIT_CF_ALL_EXP_SX:
+ pSXClause = (R700ControlFlowSXClause*)pCFInst;
+ break;
+ case SIT_CF_ALL_EXP_SMX:
+ pSMXClause = (R700ControlFlowSMXClause*)pCFInst;
+ break;
+ default:
+ break;
+ };
+
+ if((pSXClause != NULL) && (pSXClause->m_Word0.f.type == SQ_EXPORT_PARAM))
+ {
+ pShader->nParamExports += pSXClause->m_Word1.f.burst_count + 1;
+ }
+ else if ((pSMXClause != NULL) && (pSMXClause->m_Word1.f.cf_inst == SQ_CF_INST_MEM_RING) &&
+ (pSMXClause->m_Word0.f.type == SQ_EXPORT_WRITE || pSMXClause->m_Word0.f.type == SQ_EXPORT_WRITE_IND))
+ {
+ pShader->nMemExports += pSMXClause->m_Word1.f.burst_count + 1;
+ }
+
+ pShader->bLinksDirty = GL_TRUE;
+ pShader->bNeedsAssembly = GL_TRUE;
+
+ pCFInst->useCount++;
+}
+
+void AddVTXInstruction(R700_Shader *pShader, R700VertexInstruction *pVTXInst)
+{
+ pVTXInst->m_uIndex = pShader->lstVTXInstructions.uNumOfNode;
+ AddInstToList(&(pShader->lstVTXInstructions),
+ (R700ShaderInstruction*)pVTXInst);
+ pShader->uShaderBinaryDWORDSize += GetInstructionSize(pVTXInst->m_ShaderInstType);
+
+ if(pVTXInst->m_ShaderInstType == SIT_VTX_GENERIC)
+ {
+ R700VertexGenericFetch* pVTXGenericClause = (R700VertexGenericFetch*)pVTXInst;
+ pShader->nRegs = (pShader->nRegs < pVTXGenericClause->m_Word1_GPR.f.dst_gpr) ? pVTXGenericClause->m_Word1_GPR.f.dst_gpr : pShader->nRegs;
+ }
+
+ pShader->bLinksDirty = GL_TRUE;
+ pShader->bNeedsAssembly = GL_TRUE;
+
+ pVTXInst->useCount++;
+}
+
+void AddTEXInstruction(R700_Shader *pShader, R700TextureInstruction *pTEXInst)
+{
+ pTEXInst->m_uIndex = pShader->lstTEXInstructions.uNumOfNode;
+ AddInstToList(&(pShader->lstTEXInstructions),
+ (R700ShaderInstruction*)pTEXInst);
+ pShader->uShaderBinaryDWORDSize += GetInstructionSize(pTEXInst->m_ShaderInstType);
+
+ pShader->nRegs = (pShader->nRegs < pTEXInst->m_Word1.f.dst_gpr) ? pTEXInst->m_Word1.f.dst_gpr : pShader->nRegs;
+
+ pShader->bLinksDirty = GL_TRUE;
+ pShader->bNeedsAssembly = GL_TRUE;
+
+ pTEXInst->useCount++;
+}
+
+void AddALUInstruction(R700_Shader *pShader, R700ALUInstruction *pALUInst)
+{
+ pALUInst->m_uIndex = pShader->lstALUInstructions.uNumOfNode;
+ AddInstToList(&(pShader->lstALUInstructions),
+ (R700ShaderInstruction*)pALUInst);
+ pShader->uShaderBinaryDWORDSize += GetInstructionSize(pALUInst->m_ShaderInstType);
+
+ pShader->nRegs = (pShader->nRegs < pALUInst->m_Word1.f.dst_gpr) ? pALUInst->m_Word1.f.dst_gpr : pShader->nRegs;
+
+ pShader->bLinksDirty = GL_TRUE;
+ pShader->bNeedsAssembly = GL_TRUE;
+
+ pALUInst->useCount++;
+}
+
+void ResolveLinks(R700_Shader *pShader)
+{
+ GLuint uiSize;
+ R700ShaderInstruction *pInst;
+ R700ALUInstruction *pALUinst;
+ R700TextureInstruction *pTEXinst;
+ R700VertexInstruction *pVTXinst;
+
+ GLuint vtxOffset;
+
+ GLuint cfOffset = 0x0;
+
+ GLuint aluOffset = cfOffset + pShader->lstCFInstructions.uNumOfNode * GetInstructionSize(SIT_CF);
+
+ GLuint texOffset = aluOffset; // + m_lstALUInstructions.size() * R700ALUInstruction::SIZE,
+
+ pInst = pShader->lstALUInstructions.pHead;
+ while(NULL != pInst)
+ {
+ texOffset += GetInstructionSize(pInst->m_ShaderInstType);
+
+ pInst = pInst->pNextInst;
+ };
+
+ vtxOffset = texOffset + pShader->lstTEXInstructions.uNumOfNode * GetInstructionSize(SIT_TEX);
+
+ if ( ((pShader->lstTEXInstructions.uNumOfNode > 0) && (texOffset % 4 != 0)) ||
+ ((pShader->lstVTXInstructions.uNumOfNode > 0) && (vtxOffset % 4 != 0)) )
+ {
+ pALUinst = (R700ALUInstruction*) CALLOC_STRUCT(R700ALUInstruction);
+ Init_R700ALUInstruction(pALUinst);
+ AddALUInstruction(pShader, pALUinst);
+ texOffset += GetInstructionSize(SIT_ALU);
+ vtxOffset += GetInstructionSize(SIT_ALU);
+ }
+
+ pInst = pShader->lstALUInstructions.pHead;
+ uiSize = 0;
+ while(NULL != pInst)
+ {
+ pALUinst = (R700ALUInstruction*)pInst;
+
+ if(pALUinst->m_pLinkedALUClause != NULL)
+ {
+ // This address is quad-word aligned
+ pALUinst->m_pLinkedALUClause->m_Word0.f.addr = (aluOffset + uiSize) >> 1;
+ }
+
+ uiSize += GetInstructionSize(pALUinst->m_ShaderInstType);
+
+ pInst = pInst->pNextInst;
+ };
+
+ pInst = pShader->lstTEXInstructions.pHead;
+ uiSize = 0;
+ while(NULL != pInst)
+ {
+ pTEXinst = (R700TextureInstruction*)pInst;
+
+ if (pTEXinst->m_pLinkedGenericClause != NULL)
+ {
+ pTEXinst->m_pLinkedGenericClause->m_Word0.f.addr = (texOffset + uiSize) >> 1;
+ }
+
+ uiSize += GetInstructionSize(pTEXinst->m_ShaderInstType);
+
+ pInst = pInst->pNextInst;
+ };
+
+ pInst = pShader->lstVTXInstructions.pHead;
+ uiSize = 0;
+ while(NULL != pInst)
+ {
+ pVTXinst = (R700VertexInstruction*)pInst;
+
+ if (pVTXinst->m_pLinkedGenericClause != NULL)
+ {
+ pVTXinst->m_pLinkedGenericClause->m_Word0.f.addr = (vtxOffset + uiSize) >> 1;
+ }
+
+ uiSize += GetInstructionSize(pVTXinst->m_ShaderInstType);
+
+ pInst = pInst->pNextInst;
+ };
+
+ pShader->bLinksDirty = GL_FALSE;
+}
+
+void Assemble(R700_Shader *pShader)
+{
+ GLuint i;
+ GLuint *pShaderBinary;
+ GLuint size_of_program;
+ GLuint *pCurrPos;
+
+ GLuint end_of_cf_instructions;
+ GLuint number_of_alu_dwords;
+
+ R700ShaderInstruction *pInst;
+
+ if(GL_TRUE == pShader->bBinaryShader)
+ {
+ return;
+ }
+
+ if(pShader->bLinksDirty == GL_TRUE)
+ {
+ ResolveLinks(pShader);
+ }
+
+ size_of_program = pShader->uShaderBinaryDWORDSize;
+
+ pShaderBinary = (GLuint*) MALLOC(sizeof(GLuint)*size_of_program);
+
+ pCurrPos = pShaderBinary;
+
+ for (i = 0; i < size_of_program; i++)
+ {
+ pShaderBinary[i] = 0;
+ }
+
+ pInst = pShader->lstCFInstructions.pHead;
+ while(NULL != pInst)
+ {
+ switch (pInst->m_ShaderInstType)
+ {
+ case SIT_CF_GENERIC:
+ {
+ R700ControlFlowGenericClause* pCFgeneric = (R700ControlFlowGenericClause*)pInst;
+ *pCurrPos++ = pCFgeneric->m_Word0.val;
+ *pCurrPos++ = pCFgeneric->m_Word1.val;
+ }
+ break;
+ case SIT_CF_ALU:
+ {
+ R700ControlFlowALUClause* pCFalu = (R700ControlFlowALUClause*)pInst;
+ *pCurrPos++ = pCFalu->m_Word0.val;
+ *pCurrPos++ = pCFalu->m_Word1.val;
+ }
+ break;
+ case SIT_CF_ALL_EXP_SX:
+ {
+ R700ControlFlowSXClause* pCFsx = (R700ControlFlowSXClause*)pInst;
+ *pCurrPos++ = pCFsx->m_Word0.val;
+ *pCurrPos++ = (pCFsx->m_Word1.val | pCFsx->m_Word1_SWIZ.val);
+ }
+ break;
+ case SIT_CF_ALL_EXP_SMX:
+ {
+ R700ControlFlowSMXClause* pCFsmx = (R700ControlFlowSMXClause*)pInst;
+ *pCurrPos++ = pCFsmx->m_Word0.val;
+ *pCurrPos++ = (pCFsmx->m_Word1.val | pCFsmx->m_Word1_BUF.val);
+ }
+ break;
+ default:
+ break;
+ }
+
+ pInst = pInst->pNextInst;
+ };
+
+ number_of_alu_dwords = 0;
+ pInst = pShader->lstALUInstructions.pHead;
+ while(NULL != pInst)
+ {
+ switch (pInst->m_ShaderInstType)
+ {
+ case SIT_ALU:
+ {
+ R700ALUInstruction* pALU = (R700ALUInstruction*)pInst;
+
+ *pCurrPos++ = pALU->m_Word0.val;
+ *pCurrPos++ = (pALU->m_Word1.val | pALU->m_Word1_OP2.val | pALU->m_Word1_OP3.val);
+
+ number_of_alu_dwords += 2;
+ }
+ break;
+ case SIT_ALU_HALF_LIT:
+ {
+ R700ALUInstructionHalfLiteral* pALUhalf = (R700ALUInstructionHalfLiteral*)pInst;
+
+ *pCurrPos++ = pALUhalf->m_Word0.val;
+ *pCurrPos++ = (pALUhalf->m_Word1.val | pALUhalf->m_Word1_OP2.val | pALUhalf->m_Word1_OP3.val);
+ *pCurrPos++ = *((GLuint*)&(pALUhalf->m_fLiteralX));
+ *pCurrPos++ = *((GLuint*)&(pALUhalf->m_fLiteralY));
+
+ number_of_alu_dwords += 4;
+ }
+ break;
+ case SIT_ALU_FALL_LIT:
+ {
+ R700ALUInstructionFullLiteral* pALUfull = (R700ALUInstructionFullLiteral*)pInst;
+
+ *pCurrPos++ = pALUfull->m_Word0.val;
+ *pCurrPos++ = (pALUfull->m_Word1.val | pALUfull->m_Word1_OP2.val | pALUfull->m_Word1_OP3.val);
+
+ *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralX));
+ *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralY));
+ *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralZ));
+ *pCurrPos++ = *((GLuint*)&(pALUfull->m_fLiteralW));
+
+ number_of_alu_dwords += 6;
+ }
+ break;
+ default:
+ break;
+ }
+
+ pInst = pInst->pNextInst;
+ };
+
+ pInst = pShader->lstTEXInstructions.pHead;
+ while(NULL != pInst)
+ {
+ R700TextureInstruction* pTEX = (R700TextureInstruction*)pInst;
+
+ *pCurrPos++ = pTEX->m_Word0.val;
+ *pCurrPos++ = pTEX->m_Word1.val;
+ *pCurrPos++ = pTEX->m_Word2.val;
+ *pCurrPos++ = 0x0beadeaf;
+
+ pInst = pInst->pNextInst;
+ };
+
+ pInst = pShader->lstVTXInstructions.pHead;
+ while(NULL != pInst)
+ {
+ switch (pInst->m_ShaderInstType)
+ {
+ case SIT_VTX_SEM: //
+ {
+ R700VertexSemanticFetch* pVTXsem = (R700VertexSemanticFetch*)pInst;
+
+ *pCurrPos++ = pVTXsem->m_Word0.val;
+ *pCurrPos++ = (pVTXsem->m_Word1.val | pVTXsem->m_Word1_SEM.val);
+ *pCurrPos++ = pVTXsem->m_Word2.val;
+ *pCurrPos++ = 0x0beadeaf;
+ }
+ break;
+ case SIT_VTX_GENERIC: //
+ {
+ R700VertexGenericFetch* pVTXgeneric = (R700VertexGenericFetch*)pInst;
+
+ *pCurrPos++ = pVTXgeneric->m_Word0.val;
+ *pCurrPos++ = (pVTXgeneric->m_Word1.val | pVTXgeneric->m_Word1_GPR.val);
+ *pCurrPos++ = pVTXgeneric->m_Word2.val;
+ *pCurrPos++ = 0x0beadeaf;
+ }
+ break;
+ default:
+ break;
+ }
+
+ pInst = pInst->pNextInst;
+ };
+
+ if(NULL != pShader->pProgram)
+ {
+ FREE(pShader->pProgram);
+ }
+ pShader->pProgram = (GLubyte*)pShaderBinary;
+
+ end_of_cf_instructions = pShader->uCFOffset + pShader->lstCFInstructions.uNumOfNode * GetInstructionSize(SIT_CF);
+
+ pShader->uEndOfCF = end_of_cf_instructions >> 1;
+
+ pShader->uEndOfALU = (end_of_cf_instructions + number_of_alu_dwords) >> 1;
+
+ pShader->uEndOfFetch = (pShader->uCFOffset + pShader->uShaderBinaryDWORDSize) >> 1;
+
+ pShader->bNeedsAssembly = GL_FALSE;
+}
+
+void LoadProgram(R700_Shader *pShader) //context
+{
+}
+
+void UpdateShaderRegisters(R700_Shader *pShader) //context
+{
+}
+
+void DeleteInstructions(R700_Shader *pShader)
+{
+}
+
+void DebugPrint(void)
+{
+}
+
+void Clean_Up_Shader(R700_Shader *pShader)
+{
+ FREE(pShader->pProgram);
+
+ R700ShaderInstruction *pInst;
+ R700ShaderInstruction *pInstToFree;
+
+ pInst = pShader->lstCFInstructions.pHead;
+ while(NULL != pInst)
+ {
+ pInstToFree = pInst;
+ pInst = pInst->pNextInst;
+ FREE(pInstToFree);
+ };
+ pInst = pShader->lstALUInstructions.pHead;
+ while(NULL != pInst)
+ {
+ pInstToFree = pInst;
+ pInst = pInst->pNextInst;
+ FREE(pInstToFree);
+ };
+ pInst = pShader->lstTEXInstructions.pHead;
+ while(NULL != pInst)
+ {
+ pInstToFree = pInst;
+ pInst = pInst->pNextInst;
+ FREE(pInstToFree);
+ };
+ pInst = pShader->lstVTXInstructions.pHead;
+ while(NULL != pInst)
+ {
+ pInstToFree = pInst;
+ pInst = pInst->pNextInst;
+ FREE(pInstToFree);
+ };
+}
+
diff --git a/src/mesa/drivers/dri/r600/r700_shader.h b/src/mesa/drivers/dri/r600/r700_shader.h
new file mode 100644
index 0000000000..bfd01e1a93
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_shader.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+
+#ifndef __R700_SHADER_H__
+#define __R700_SHADER_H__
+
+#include "main/mtypes.h"
+
+#include "r700_shaderinst.h"
+
+
+void r700ShaderInit(GLcontext * ctx);
+
+typedef enum R700ShaderType
+{
+ R700_SHADER_FS = 0x0,
+ R700_SHADER_ES = 0x1,
+ R700_SHADER_GS = 0x2,
+ R700_SHADER_VS = 0x3,
+ R700_SHADER_PS = 0x4,
+ R700_SHADER_INVALID = 0x5,
+} R700ShaderType;
+
+typedef struct TypedShaderList
+{
+ R700ShaderInstruction * pHead;
+ R700ShaderInstruction * pTail;
+ GLuint uNumOfNode;
+} TypedShaderList;
+
+typedef struct RealRegister
+{
+ GLuint uAddr;
+ GLuint uValue;
+} RealRegister;
+
+typedef struct InstDeps
+{
+ GLint nDstDep;
+ GLint nSrcDeps[3];
+} InstDeps;
+
+typedef struct R700_Shader
+{
+ R700ShaderType Type;
+
+ GLubyte* pProgram;
+
+ GLboolean bBinaryShader;
+ GLboolean bFetchShaderRequired;
+ GLboolean bNeedsAssembly;
+ GLboolean bLinksDirty;
+
+ GLuint uShaderBinaryDWORDSize; // in DWORDS
+ GLuint nRegs;
+ GLuint nParamExports; // VS_ EXPORT_COUNT (1 based, the actual register is 0 based!)
+ GLuint nMemExports;
+ GLuint resource; // VS and PS _RESOURCE
+ GLuint exportMode; // VS and PS _EXPORT_MODE
+
+ GLboolean depthIsImported;
+
+ // Vertex program exports
+ GLboolean positionVectorIsExported;
+
+ GLboolean miscVectorIsExported;
+ GLboolean renderTargetArrayIndexIsExported;
+
+ GLboolean ccDist0VectorIsExported;
+ GLboolean ccDist1VectorIsExported;
+
+ // Pixel program exports
+ GLboolean depthIsExported;
+ GLboolean stencilRefIsExported;
+ GLboolean coverageToMaskIsExported;
+ GLboolean maskIsExported;
+
+ GLboolean killIsUsed;
+
+ GLuint uStartAddr;
+ GLuint uCFOffset;
+ GLuint uEndOfCF;
+ GLuint uEndOfALU;
+ GLuint uEndOfFetch;
+ GLuint uStackSize;
+ GLuint uMaxCallDepth;
+
+ TypedShaderList lstCFInstructions;
+ TypedShaderList lstALUInstructions;
+ TypedShaderList lstTEXInstructions;
+ TypedShaderList lstVTXInstructions;
+
+ RealRegister RegStartAddr;
+ RealRegister RegCFOffset;
+ RealRegister RegEndCF;
+ RealRegister RegEndALU;
+ RealRegister egEndFetcg;
+
+ // -------- constants
+ GLfloat ConstantArray[SQ_ALU_CONSTANT_PS_COUNT * 4];
+
+ GLboolean bSurfAllocated;
+} R700_Shader;
+
+//Internal
+void AddInstToList(TypedShaderList * plstCFInstructions, R700ShaderInstruction * pInst);
+void ResolveLinks(R700_Shader *pShader);
+void Assemble(R700_Shader *pShader);
+
+
+//Interface
+void Init_R700_Shader(R700_Shader * pShader);
+void AddCFInstruction(R700_Shader *pShader, R700ControlFlowInstruction *pCFInst);
+void AddVTXInstruction(R700_Shader *pShader, R700VertexInstruction *pVTXInst);
+void AddTEXInstruction(R700_Shader *pShader, R700TextureInstruction *pTEXInst);
+void AddALUInstruction(R700_Shader *pShader, R700ALUInstruction *pALUInst);
+
+void LoadProgram(R700_Shader *pShader);
+void UpdateShaderRegisters(R700_Shader *pShader);
+void DeleteInstructions(R700_Shader *pShader);
+void DebugPrint(void);
+
+void Clean_Up_Shader(R700_Shader *pShader);
+
+#endif /*__R700_SHADER_H__*/
+
diff --git a/src/mesa/drivers/dri/r600/r700_shaderinst.c b/src/mesa/drivers/dri/r600/r700_shaderinst.c
new file mode 100644
index 0000000000..f120d9f941
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_shaderinst.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+
+#include "main/mtypes.h"
+
+#include "radeon_debug.h"
+#include "r700_shaderinst.h"
+
+void Init_R700ControlFlowGenericClause(R700ControlFlowGenericClause* pInst)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+
+ pInst->m_pLinkedVTXInstruction = 0;
+ pInst->m_pLinkedTEXInstruction = 0;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_CF_GENERIC;
+}
+
+void Init_R700ControlFlowALUClause(R700ControlFlowALUClause* pInst)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+
+ pInst->m_pLinkedALUInstruction = 0;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_CF_ALU;
+}
+
+void Init_R700ControlFlowSXClause(R700ControlFlowSXClause* pInst)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+ pInst->m_Word1_SWIZ.val = 0x00000000;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_CF_ALL_EXP_SX;
+}
+
+void Init_R700ControlFlowSMXClause(R700ControlFlowSMXClause* pInst)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+ pInst->m_Word1_BUF.val = 0x00000000;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_CF_ALL_EXP_SMX;
+}
+
+void Init_R700ALUInstruction(R700ALUInstruction* pInst)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+ pInst->m_Word1_OP2.val = 0x00000000;
+ pInst->m_Word1_OP3.val = 0x00000000;
+
+ pInst->m_pLinkedALUClause = 0;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_ALU;
+}
+
+void Init_R700ALUInstructionHalfLiteral(R700ALUInstructionHalfLiteral* pInst, GLfloat x, GLfloat y)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+ pInst->m_Word1_OP2.val = 0x00000000;
+ pInst->m_Word1_OP3.val = 0x00000000;
+
+ pInst->m_pLinkedALUClause = 0;
+
+ pInst->m_fLiteralX = x;
+ pInst->m_fLiteralY = y;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_ALU_HALF_LIT;
+}
+
+void Init_R700ALUInstructionFullLiteral(R700ALUInstructionFullLiteral* pInst, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+ pInst->m_Word1_OP2.val = 0x00000000;
+ pInst->m_Word1_OP3.val = 0x00000000;
+
+ pInst->m_pLinkedALUClause = 0;
+
+ pInst->m_fLiteralX = x;
+ pInst->m_fLiteralY = y;
+ pInst->m_fLiteralZ = z;
+ pInst->m_fLiteralW = w;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_ALU_FALL_LIT;
+}
+
+void Init_R700TextureInstruction(R700TextureInstruction* pInst)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+ pInst->m_Word2.val = 0x00000000;
+
+ pInst->m_pLinkedGenericClause = 0;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_TEX;
+}
+
+void Init_R700VertexSemanticFetch(R700VertexSemanticFetch* pInst)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+ pInst->m_Word1_SEM.val = 0x00000000;
+ pInst->m_Word2.val = 0x00000000;
+
+ pInst->m_pLinkedGenericClause = 0;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_VTX_SEM;
+}
+
+void Init_R700VertexGenericFetch(R700VertexGenericFetch* pInst)
+{
+ pInst->m_Word0.val = 0x00000000;
+ pInst->m_Word1.val = 0x00000000;
+ pInst->m_Word1_GPR.val = 0x00000000;
+ pInst->m_Word2.val = 0x00000000;
+
+ pInst->m_pLinkedGenericClause = 0;
+
+ pInst->useCount = 0;
+
+ pInst->m_ShaderInstType = SIT_VTX_GENERIC;
+}
+
+unsigned int GetInstructionSize(ShaderInstType instType)
+{
+ switch(instType)
+ {
+ case SIT_ALU_HALF_LIT:
+ case SIT_TEX:
+ case SIT_VTX:
+ case SIT_VTX_GENERIC:
+ case SIT_VTX_SEM:
+ return 4;
+ case SIT_ALU_FALL_LIT:
+ return 6;
+ default:
+ break;
+ }
+
+ return 2;
+}
+
+unsigned int GetCFMaxInstructions(ShaderInstType instType)
+{
+ switch (instType)
+ {
+ case SIT_CF_ALL_EXP:
+ case SIT_CF_ALL_EXP_SX:
+ case SIT_CF_ALL_EXP_SMX:
+ return 0x10;
+ case SIT_CF_GENERIC:
+ return 0x8; //For tex and vtx
+ case SIT_CF_ALU:
+ return 0x80;
+ default:
+ break;
+ }
+ return 0x10;
+}
+
+GLboolean LinkVertexInstruction(R700ControlFlowGenericClause *pCFGeneric,
+ R700VertexInstruction *pVTXInstruction)
+{
+ if (pCFGeneric->m_pLinkedTEXInstruction != 0)
+ {
+ radeon_error("This instruction is already linked to a texture instruction.\n");
+ return GL_FALSE;
+ }
+
+ pCFGeneric->m_pLinkedVTXInstruction = pVTXInstruction;
+ pVTXInstruction->m_pLinkedGenericClause = pCFGeneric;
+
+ return GL_TRUE;
+}
+
+
+
diff --git a/src/mesa/drivers/dri/r600/r700_shaderinst.h b/src/mesa/drivers/dri/r600/r700_shaderinst.h
new file mode 100644
index 0000000000..2829cca0a3
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_shaderinst.h
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+
+#ifndef _R700_SHADERINST_H_
+#define _R700_SHADERINST_H_
+
+#include "main/glheader.h"
+
+#include "defaultendian.h"
+#include "sq_micro_reg.h"
+
+#define SQ_ALU_CONSTANT_PS_OFFSET 0x00000000
+#define SQ_ALU_CONSTANT_PS_COUNT 0x00000100
+#define SQ_ALU_CONSTANT_VS_OFFSET 0x00000100
+#define SQ_ALU_CONSTANT_VS_COUNT 0x00000100
+#define SQ_FETCH_RESOURCE_PS_OFFSET 0x00000000
+#define SQ_FETCH_RESOURCE_PS_COUNT 0x000000a0
+#define SQ_FETCH_RESOURCE_VS_OFFSET 0x000000a0
+#define SQ_FETCH_RESOURCE_VS_COUNT 0x000000b0
+
+#define SHADERINST_TYPEMASK_CF 0x10
+#define SHADERINST_TYPEMASK_ALU 0x20
+#define SHADERINST_TYPEMASK_TEX 0x40
+#define SHADERINST_TYPEMASK_VTX 0x80
+
+typedef enum ShaderInstType
+{
+ SIT_CF = 0x10, /*SIZE = 0x2*/
+ SIT_CF_ALL_EXP = 0x14, /*SIZE = 0x2, MAX_INSTRUCTIONS = 0x10;*/
+ SIT_CF_ALL_EXP_SX = 0x15, /*SIZE = 0x2, MAX_INSTRUCTIONS = 0x10;*/
+ SIT_CF_ALL_EXP_SMX= 0x16, /*SIZE = 0x2, MAX_INSTRUCTIONS = 0x10;*/
+ SIT_CF_GENERIC = 0x18, /*SIZE = 0x2, MAX_INSTRUCTIONS = 0x8; //For tex and vtx*/
+ SIT_CF_ALU = 0x19, /*SIZE = 0x2, MAX_INSTRUCTIONS = 0x80;*/
+ SIT_ALU = 0x20, /*SIZE = 0x2,*/
+ SIT_ALU_HALF_LIT = 0x21, /*SIZE = 0x4,*/
+ SIT_ALU_FALL_LIT = 0x22, /*SIZE = 0x6,*/
+ SIT_TEX = 0x40, /*SIZE = 0x4,*/
+ SIT_VTX = 0x80, /*SIZE = 0x4, MEGA_FETCH_BYTES = 0x20*/
+ SIT_VTX_GENERIC = 0x81, /*SIZE = 0x4, MEGA_FETCH_BYTES = 0x20*/
+ SIT_VTX_SEM = 0x82 /*SIZE = 0x4, MEGA_FETCH_BYTES = 0x20*/
+} ShaderInstType;
+
+typedef struct R700ShaderInstruction
+{
+ ShaderInstType m_ShaderInstType;
+ struct R700ShaderInstruction *pNextInst;
+ GLuint m_uIndex;
+ GLuint useCount;
+} R700ShaderInstruction;
+
+// ------------------ CF insts ---------------------------
+
+typedef R700ShaderInstruction R700ControlFlowInstruction;
+
+typedef struct R700ControlFlowAllocExportClause
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ GLuint m_uIndex;
+ GLuint useCount;
+
+ sq_cf_alloc_export_word0_u m_Word0;
+ sq_cf_alloc_export_word1_u m_Word1;
+} R700ControlFlowAllocExportClause;
+
+typedef struct R700ControlFlowSXClause
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700ControlFlowAllocExportClause
+ //R700ControlFlowInstruction
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+ //---------------------------
+ sq_cf_alloc_export_word0_u m_Word0;
+ sq_cf_alloc_export_word1_u m_Word1;
+ //-------------------------------------
+
+ sq_cf_alloc_export_word1_swiz_u m_Word1_SWIZ;
+} R700ControlFlowSXClause;
+
+typedef struct R700ControlFlowSMXClause
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700ControlFlowAllocExportClause
+ //R700ControlFlowInstruction
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+ //---------------------------
+ sq_cf_alloc_export_word0_u m_Word0;
+ sq_cf_alloc_export_word1_u m_Word1;
+ //-------------------------------
+
+ sq_cf_alloc_export_word1_buf_u m_Word1_BUF;
+} R700ControlFlowSMXClause;
+
+typedef struct R700ControlFlowGenericClause
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700ControlFlowInstruction
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+ //---------------------
+
+ sq_cf_word0_u m_Word0;
+ sq_cf_word1_u m_Word1;
+
+ struct R700VertexInstruction *m_pLinkedVTXInstruction;
+ struct R700TextureInstruction *m_pLinkedTEXInstruction;
+} R700ControlFlowGenericClause;
+
+typedef struct R700ControlFlowALUClause
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700ControlFlowInstruction
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+ //---------------------
+
+ sq_cf_alu_word0_u m_Word0;
+ sq_cf_alu_word1_u m_Word1;
+
+ struct R700ALUInstruction *m_pLinkedALUInstruction;
+} R700ControlFlowALUClause;
+
+// ------------------- End of CF Inst ------------------------
+
+// ------------------- ALU Inst ------------------------------
+typedef struct R700ALUInstruction
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+
+ sq_alu_word0_u m_Word0;
+ sq_alu_word1_u m_Word1;
+ sq_alu_word1_op2_v2_u m_Word1_OP2;
+ sq_alu_word1_op3_u m_Word1_OP3;
+
+ struct R700ControlFlowALUClause *m_pLinkedALUClause;
+} R700ALUInstruction;
+
+typedef struct R700ALUInstructionHalfLiteral
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700ALUInstruction
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+
+ sq_alu_word0_u m_Word0;
+ sq_alu_word1_u m_Word1;
+ sq_alu_word1_op2_v2_u m_Word1_OP2;
+ sq_alu_word1_op3_u m_Word1_OP3;
+
+ struct R700ControlFlowALUClause *m_pLinkedALUClause;
+ //-------------------
+
+ GLfloat m_fLiteralX,
+ m_fLiteralY;
+} R700ALUInstructionHalfLiteral;
+
+typedef struct R700ALUInstructionFullLiteral
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700ALUInstruction
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+
+ sq_alu_word0_u m_Word0;
+ sq_alu_word1_u m_Word1;
+ sq_alu_word1_op2_v2_u m_Word1_OP2;
+ sq_alu_word1_op3_u m_Word1_OP3;
+
+ struct R700ControlFlowALUClause *m_pLinkedALUClause;
+ //-------------------
+
+ GLfloat m_fLiteralX,
+ m_fLiteralY,
+ m_fLiteralZ,
+ m_fLiteralW;
+} R700ALUInstructionFullLiteral;
+// ------------------- End of ALU Inst -----------------------
+
+// ------------------- Textuer/Vertex Instruction --------------------
+
+typedef struct R700TextureInstruction
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+
+ sq_tex_word0_u m_Word0;
+ sq_tex_word1_u m_Word1;
+ sq_tex_word2_u m_Word2;
+
+ struct R700ControlFlowGenericClause *m_pLinkedGenericClause;
+} R700TextureInstruction;
+
+typedef struct R700VertexInstruction
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+
+ sq_vtx_word0_u m_Word0;
+ sq_vtx_word1_u m_Word1;
+ sq_vtx_word2_u m_Word2;
+
+ struct R700ControlFlowGenericClause *m_pLinkedGenericClause;
+} R700VertexInstruction;
+//
+typedef struct R700VertexSemanticFetch
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700VertexInstruction
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+
+ sq_vtx_word0_u m_Word0;
+ sq_vtx_word1_u m_Word1;
+ sq_vtx_word2_u m_Word2;
+
+ struct R700ControlFlowGenericClause *m_pLinkedGenericClause;
+ //---------------------------
+
+ sq_vtx_word1_sem_u m_Word1_SEM;
+} R700VertexSemanticFetch;
+//
+typedef struct R700VertexGenericFetch
+{
+ ShaderInstType m_ShaderInstType;
+ R700ShaderInstruction * pNextInst;
+ //R700VertexInstruction
+ //R700ShaderInstruction
+ GLuint m_uIndex;
+ GLuint useCount;
+ //---------------------
+
+ sq_vtx_word0_u m_Word0;
+ sq_vtx_word1_u m_Word1;
+ sq_vtx_word2_u m_Word2;
+
+ struct R700ControlFlowGenericClause *m_pLinkedGenericClause;
+ //---------------------------
+
+ sq_vtx_word1_gpr_u m_Word1_GPR;
+} R700VertexGenericFetch;
+
+// ------------------- End of Texture Vertex Instruction --------------------
+
+void Init_R700ControlFlowGenericClause(R700ControlFlowGenericClause* pInst);
+void Init_R700ControlFlowALUClause(R700ControlFlowALUClause* pInst);
+void Init_R700ControlFlowSXClause(R700ControlFlowSXClause* pInst);
+void Init_R700ControlFlowSMXClause(R700ControlFlowSMXClause* pInst);
+void Init_R700ALUInstruction(R700ALUInstruction* pInst);
+void Init_R700ALUInstructionHalfLiteral(R700ALUInstructionHalfLiteral* pInst, GLfloat x, GLfloat y);
+void Init_R700ALUInstructionFullLiteral(R700ALUInstructionFullLiteral* pInst, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void Init_R700TextureInstruction(R700TextureInstruction* pInst);
+void Init_R700VertexSemanticFetch(R700VertexSemanticFetch* pInst);
+void Init_R700VertexGenericFetch(R700VertexGenericFetch* pInst);
+
+unsigned int GetInstructionSize(ShaderInstType instType);
+unsigned int GetCFMaxInstructions(ShaderInstType instType);
+
+GLboolean LinkVertexInstruction(R700ControlFlowGenericClause *pCFGeneric,
+ R700VertexInstruction *pVTXInstruction);
+
+#endif //_R700_SHADERINST_H_
diff --git a/src/mesa/drivers/dri/r600/r700_state.c b/src/mesa/drivers/dri/r600/r700_state.c
new file mode 100644
index 0000000000..e91aa43118
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_state.c
@@ -0,0 +1,1810 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/state.h"
+#include "main/imports.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "main/dd.h"
+#include "main/simple_list.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_vp_build.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "main/api_arrayelt.h"
+#include "main/state.h"
+#include "main/framebuffer.h"
+
+#include "shader/prog_parameter.h"
+#include "shader/prog_statevars.h"
+#include "vbo/vbo.h"
+#include "main/texformat.h"
+
+#include "r600_context.h"
+
+#include "r700_state.h"
+
+#include "r700_fragprog.h"
+#include "r700_vertprog.h"
+
+
+static void r700SetClipPlaneState(GLcontext * ctx, GLenum cap, GLboolean state);
+static void r700UpdatePolygonMode(GLcontext * ctx);
+static void r700SetPolygonOffsetState(GLcontext * ctx, GLboolean state);
+static void r700SetStencilState(GLcontext * ctx, GLboolean state);
+
+void r700UpdateShaders (GLcontext * ctx) //----------------------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ GLvector4f dummy_attrib[_TNL_ATTRIB_MAX];
+ GLvector4f *temp_attrib[_TNL_ATTRIB_MAX];
+ int i;
+
+ /* should only happenen once, just after context is created */
+ /* TODO: shouldn't we fallback to sw here? */
+ if (!ctx->FragmentProgram._Current) {
+ _mesa_fprintf(stderr, "No ctx->FragmentProgram._Current!!\n");
+ return;
+ }
+
+ r700SelectFragmentShader(ctx);
+
+ if (context->radeon.NewGLState) {
+ for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
+ /* mat states from state var not array for sw */
+ dummy_attrib[i].stride = 0;
+ temp_attrib[i] = TNL_CONTEXT(ctx)->vb.AttribPtr[i];
+ TNL_CONTEXT(ctx)->vb.AttribPtr[i] = &(dummy_attrib[i]);
+ }
+
+ _tnl_UpdateFixedFunctionProgram(ctx);
+
+ for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
+ TNL_CONTEXT(ctx)->vb.AttribPtr[i] = temp_attrib[i];
+ }
+ }
+
+ r700SelectVertexShader(ctx);
+ r700UpdateStateParameters(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+ context->radeon.NewGLState = 0;
+}
+
+/*
+ * To correctly position primitives:
+ */
+void r700UpdateViewportOffset(GLcontext * ctx) //------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&context->radeon);
+ GLfloat xoffset = (GLfloat) dPriv->x;
+ GLfloat yoffset = (GLfloat) dPriv->y + dPriv->h;
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+ int id = 0;
+
+ GLfloat tx = v[MAT_TX] + xoffset;
+ GLfloat ty = (-v[MAT_TY]) + yoffset;
+
+ if (r700->viewport[id].PA_CL_VPORT_XOFFSET.f32All != tx ||
+ r700->viewport[id].PA_CL_VPORT_YOFFSET.f32All != ty) {
+ /* Note: this should also modify whatever data the context reset
+ * code uses...
+ */
+ R600_STATECHANGE(context, vpt);
+ r700->viewport[id].PA_CL_VPORT_XOFFSET.f32All = tx;
+ r700->viewport[id].PA_CL_VPORT_YOFFSET.f32All = ty;
+ }
+
+ radeonUpdateScissor(ctx);
+}
+
+void r700UpdateStateParameters(GLcontext * ctx, GLuint new_state) //--------------------
+{
+ struct r700_fragment_program *fp =
+ (struct r700_fragment_program *)ctx->FragmentProgram._Current;
+ struct gl_program_parameter_list *paramList;
+
+ if (!(new_state & (_NEW_BUFFERS | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)))
+ return;
+
+ if (!ctx->FragmentProgram._Current || !fp)
+ return;
+
+ paramList = ctx->FragmentProgram._Current->Base.Parameters;
+
+ if (!paramList)
+ return;
+
+ _mesa_load_state_parameters(ctx, paramList);
+
+}
+
+/**
+ * Called by Mesa after an internal state update.
+ */
+static void r700InvalidateState(GLcontext * ctx, GLuint new_state) //-------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ _swrast_InvalidateState(ctx, new_state);
+ _swsetup_InvalidateState(ctx, new_state);
+ _vbo_InvalidateState(ctx, new_state);
+ _tnl_InvalidateState(ctx, new_state);
+ _ae_invalidate_state(ctx, new_state);
+
+ if (new_state & _NEW_BUFFERS) {
+ _mesa_update_framebuffer(ctx);
+ /* this updates the DrawBuffer's Width/Height if it's a FBO */
+ _mesa_update_draw_buffer_bounds(ctx);
+
+ R600_STATECHANGE(context, cb_target);
+ R600_STATECHANGE(context, db_target);
+ }
+
+ if (new_state & (_NEW_LIGHT)) {
+ R600_STATECHANGE(context, su);
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION)
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, PROVOKING_VTX_LAST_bit);
+ else
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, PROVOKING_VTX_LAST_bit);
+ }
+
+ r700UpdateStateParameters(ctx, new_state);
+
+ R600_STATECHANGE(context, cl);
+ R600_STATECHANGE(context, spi);
+
+ if(GL_TRUE == r700->bEnablePerspective)
+ {
+ /* Do scale XY and Z by 1/W0 for perspective correction on pos. For orthogonal case, set both to one. */
+ CLEARbit(r700->PA_CL_VTE_CNTL.u32All, VTX_XY_FMT_bit);
+ CLEARbit(r700->PA_CL_VTE_CNTL.u32All, VTX_Z_FMT_bit);
+
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VTX_W0_FMT_bit);
+
+ SETbit(r700->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit);
+ CLEARbit(r700->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit);
+ }
+ else
+ {
+ /* For orthogonal case. */
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VTX_XY_FMT_bit);
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VTX_Z_FMT_bit);
+
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VTX_W0_FMT_bit);
+
+ CLEARbit(r700->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit);
+ SETbit(r700->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit);
+ }
+
+ context->radeon.NewGLState |= new_state;
+}
+
+static void r700SetDepthState(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ R600_STATECHANGE(context, db);
+
+ if (ctx->Depth.Test)
+ {
+ SETbit(r700->DB_DEPTH_CONTROL.u32All, Z_ENABLE_bit);
+ if (ctx->Depth.Mask)
+ {
+ SETbit(r700->DB_DEPTH_CONTROL.u32All, Z_WRITE_ENABLE_bit);
+ }
+ else
+ {
+ CLEARbit(r700->DB_DEPTH_CONTROL.u32All, Z_WRITE_ENABLE_bit);
+ }
+
+ switch (ctx->Depth.Func)
+ {
+ case GL_NEVER:
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, FRAG_NEVER,
+ ZFUNC_shift, ZFUNC_mask);
+ break;
+ case GL_LESS:
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, FRAG_LESS,
+ ZFUNC_shift, ZFUNC_mask);
+ break;
+ case GL_EQUAL:
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, FRAG_EQUAL,
+ ZFUNC_shift, ZFUNC_mask);
+ break;
+ case GL_LEQUAL:
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, FRAG_LEQUAL,
+ ZFUNC_shift, ZFUNC_mask);
+ break;
+ case GL_GREATER:
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, FRAG_GREATER,
+ ZFUNC_shift, ZFUNC_mask);
+ break;
+ case GL_NOTEQUAL:
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, FRAG_NOTEQUAL,
+ ZFUNC_shift, ZFUNC_mask);
+ break;
+ case GL_GEQUAL:
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, FRAG_GEQUAL,
+ ZFUNC_shift, ZFUNC_mask);
+ break;
+ case GL_ALWAYS:
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, FRAG_ALWAYS,
+ ZFUNC_shift, ZFUNC_mask);
+ break;
+ default:
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, FRAG_ALWAYS,
+ ZFUNC_shift, ZFUNC_mask);
+ break;
+ }
+ }
+ else
+ {
+ CLEARbit(r700->DB_DEPTH_CONTROL.u32All, Z_ENABLE_bit);
+ CLEARbit(r700->DB_DEPTH_CONTROL.u32All, Z_WRITE_ENABLE_bit);
+ }
+}
+
+static void r700SetAlphaState(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ uint32_t alpha_func = REF_ALWAYS;
+ GLboolean really_enabled = ctx->Color.AlphaEnabled;
+
+ R600_STATECHANGE(context, sx);
+
+ switch (ctx->Color.AlphaFunc) {
+ case GL_NEVER:
+ alpha_func = REF_NEVER;
+ break;
+ case GL_LESS:
+ alpha_func = REF_LESS;
+ break;
+ case GL_EQUAL:
+ alpha_func = REF_EQUAL;
+ break;
+ case GL_LEQUAL:
+ alpha_func = REF_LEQUAL;
+ break;
+ case GL_GREATER:
+ alpha_func = REF_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ alpha_func = REF_NOTEQUAL;
+ break;
+ case GL_GEQUAL:
+ alpha_func = REF_GEQUAL;
+ break;
+ case GL_ALWAYS:
+ /*alpha_func = REF_ALWAYS; */
+ really_enabled = GL_FALSE;
+ break;
+ }
+
+ if (really_enabled) {
+ SETfield(r700->SX_ALPHA_TEST_CONTROL.u32All, alpha_func,
+ ALPHA_FUNC_shift, ALPHA_FUNC_mask);
+ SETbit(r700->SX_ALPHA_TEST_CONTROL.u32All, ALPHA_TEST_ENABLE_bit);
+ r700->SX_ALPHA_REF.f32All = ctx->Color.AlphaRef;
+ } else {
+ CLEARbit(r700->SX_ALPHA_TEST_CONTROL.u32All, ALPHA_TEST_ENABLE_bit);
+ }
+
+}
+
+static void r700AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref) //---------------
+{
+ (void)func;
+ (void)ref;
+ r700SetAlphaState(ctx);
+}
+
+
+static void r700BlendColor(GLcontext * ctx, const GLfloat cf[4]) //----------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ R600_STATECHANGE(context, blnd_clr);
+
+ r700->CB_BLEND_RED.f32All = cf[0];
+ r700->CB_BLEND_GREEN.f32All = cf[1];
+ r700->CB_BLEND_BLUE.f32All = cf[2];
+ r700->CB_BLEND_ALPHA.f32All = cf[3];
+}
+
+static int blend_factor(GLenum factor, GLboolean is_src)
+{
+ switch (factor) {
+ case GL_ZERO:
+ return BLEND_ZERO;
+ break;
+ case GL_ONE:
+ return BLEND_ONE;
+ break;
+ case GL_DST_COLOR:
+ return BLEND_DST_COLOR;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ return BLEND_ONE_MINUS_DST_COLOR;
+ break;
+ case GL_SRC_COLOR:
+ return BLEND_SRC_COLOR;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return BLEND_ONE_MINUS_SRC_COLOR;
+ break;
+ case GL_SRC_ALPHA:
+ return BLEND_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return BLEND_ONE_MINUS_SRC_ALPHA;
+ break;
+ case GL_DST_ALPHA:
+ return BLEND_DST_ALPHA;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return BLEND_ONE_MINUS_DST_ALPHA;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ return (is_src) ? BLEND_SRC_ALPHA_SATURATE : BLEND_ZERO;
+ break;
+ case GL_CONSTANT_COLOR:
+ return BLEND_CONSTANT_COLOR;
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ return BLEND_ONE_MINUS_CONSTANT_COLOR;
+ break;
+ case GL_CONSTANT_ALPHA:
+ return BLEND_CONSTANT_ALPHA;
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ return BLEND_ONE_MINUS_CONSTANT_ALPHA;
+ break;
+ default:
+ fprintf(stderr, "unknown blend factor %x\n", factor);
+ return (is_src) ? BLEND_ONE : BLEND_ZERO;
+ break;
+ }
+}
+
+static void r700SetBlendState(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ int id = 0;
+ uint32_t blend_reg = 0, eqn, eqnA;
+
+ R600_STATECHANGE(context, blnd);
+
+ if (RGBA_LOGICOP_ENABLED(ctx) || !ctx->Color.BlendEnabled) {
+ SETfield(blend_reg,
+ BLEND_ONE, COLOR_SRCBLEND_shift, COLOR_SRCBLEND_mask);
+ SETfield(blend_reg,
+ BLEND_ZERO, COLOR_DESTBLEND_shift, COLOR_DESTBLEND_mask);
+ SETfield(blend_reg,
+ COMB_DST_PLUS_SRC, COLOR_COMB_FCN_shift, COLOR_COMB_FCN_mask);
+ SETfield(blend_reg,
+ BLEND_ONE, ALPHA_SRCBLEND_shift, ALPHA_SRCBLEND_mask);
+ SETfield(blend_reg,
+ BLEND_ZERO, ALPHA_DESTBLEND_shift, ALPHA_DESTBLEND_mask);
+ SETfield(blend_reg,
+ COMB_DST_PLUS_SRC, ALPHA_COMB_FCN_shift, ALPHA_COMB_FCN_mask);
+ if (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_R600)
+ r700->CB_BLEND_CONTROL.u32All = blend_reg;
+ else
+ r700->render_target[id].CB_BLEND0_CONTROL.u32All = blend_reg;
+ return;
+ }
+
+ SETfield(blend_reg,
+ blend_factor(ctx->Color.BlendSrcRGB, GL_TRUE),
+ COLOR_SRCBLEND_shift, COLOR_SRCBLEND_mask);
+ SETfield(blend_reg,
+ blend_factor(ctx->Color.BlendDstRGB, GL_FALSE),
+ COLOR_DESTBLEND_shift, COLOR_DESTBLEND_mask);
+
+ switch (ctx->Color.BlendEquationRGB) {
+ case GL_FUNC_ADD:
+ eqn = COMB_DST_PLUS_SRC;
+ break;
+ case GL_FUNC_SUBTRACT:
+ eqn = COMB_SRC_MINUS_DST;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ eqn = COMB_DST_MINUS_SRC;
+ break;
+ case GL_MIN:
+ eqn = COMB_MIN_DST_SRC;
+ SETfield(blend_reg,
+ BLEND_ONE,
+ COLOR_SRCBLEND_shift, COLOR_SRCBLEND_mask);
+ SETfield(blend_reg,
+ BLEND_ONE,
+ COLOR_DESTBLEND_shift, COLOR_DESTBLEND_mask);
+ break;
+ case GL_MAX:
+ eqn = COMB_MAX_DST_SRC;
+ SETfield(blend_reg,
+ BLEND_ONE,
+ COLOR_SRCBLEND_shift, COLOR_SRCBLEND_mask);
+ SETfield(blend_reg,
+ BLEND_ONE,
+ COLOR_DESTBLEND_shift, COLOR_DESTBLEND_mask);
+ break;
+
+ default:
+ fprintf(stderr,
+ "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
+ __FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB);
+ return;
+ }
+ SETfield(blend_reg,
+ eqn, COLOR_COMB_FCN_shift, COLOR_COMB_FCN_mask);
+
+ SETfield(blend_reg,
+ blend_factor(ctx->Color.BlendSrcRGB, GL_TRUE),
+ ALPHA_SRCBLEND_shift, ALPHA_SRCBLEND_mask);
+ SETfield(blend_reg,
+ blend_factor(ctx->Color.BlendDstRGB, GL_FALSE),
+ ALPHA_DESTBLEND_shift, ALPHA_DESTBLEND_mask);
+
+ switch (ctx->Color.BlendEquationA) {
+ case GL_FUNC_ADD:
+ eqnA = COMB_DST_PLUS_SRC;
+ break;
+ case GL_FUNC_SUBTRACT:
+ eqnA = COMB_SRC_MINUS_DST;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ eqnA = COMB_DST_MINUS_SRC;
+ break;
+ case GL_MIN:
+ eqnA = COMB_MIN_DST_SRC;
+ SETfield(blend_reg,
+ BLEND_ONE,
+ ALPHA_SRCBLEND_shift, ALPHA_SRCBLEND_mask);
+ SETfield(blend_reg,
+ BLEND_ONE,
+ ALPHA_DESTBLEND_shift, ALPHA_DESTBLEND_mask);
+ break;
+ case GL_MAX:
+ eqnA = COMB_MAX_DST_SRC;
+ SETfield(blend_reg,
+ BLEND_ONE,
+ ALPHA_SRCBLEND_shift, ALPHA_SRCBLEND_mask);
+ SETfield(blend_reg,
+ BLEND_ONE,
+ ALPHA_DESTBLEND_shift, ALPHA_DESTBLEND_mask);
+ break;
+ default:
+ fprintf(stderr,
+ "[%s:%u] Invalid A blend equation (0x%04x).\n",
+ __FUNCTION__, __LINE__, ctx->Color.BlendEquationA);
+ return;
+ }
+
+ SETfield(blend_reg,
+ eqnA, ALPHA_COMB_FCN_shift, ALPHA_COMB_FCN_mask);
+
+ SETbit(blend_reg, SEPARATE_ALPHA_BLEND_bit);
+
+ if (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_R600)
+ r700->CB_BLEND_CONTROL.u32All = blend_reg;
+ else {
+ r700->render_target[id].CB_BLEND0_CONTROL.u32All = blend_reg;
+ SETbit(r700->CB_COLOR_CONTROL.u32All, PER_MRT_BLEND_bit);
+ }
+ SETfield(r700->CB_COLOR_CONTROL.u32All, (1 << id),
+ TARGET_BLEND_ENABLE_shift, TARGET_BLEND_ENABLE_mask);
+
+}
+
+static void r700BlendEquationSeparate(GLcontext * ctx,
+ GLenum modeRGB, GLenum modeA) //-----------------
+{
+ r700SetBlendState(ctx);
+}
+
+static void r700BlendFuncSeparate(GLcontext * ctx,
+ GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA) //------------------------
+{
+ r700SetBlendState(ctx);
+}
+
+/**
+ * Translate LogicOp enums into hardware representation.
+ */
+static GLuint translate_logicop(GLenum logicop)
+{
+ switch (logicop) {
+ case GL_CLEAR:
+ return 0x00;
+ case GL_SET:
+ return 0xff;
+ case GL_COPY:
+ return 0xcc;
+ case GL_COPY_INVERTED:
+ return 0x33;
+ case GL_NOOP:
+ return 0xaa;
+ case GL_INVERT:
+ return 0x55;
+ case GL_AND:
+ return 0x88;
+ case GL_NAND:
+ return 0x77;
+ case GL_OR:
+ return 0xee;
+ case GL_NOR:
+ return 0x11;
+ case GL_XOR:
+ return 0x66;
+ case GL_EQUIV:
+ return 0xaa;
+ case GL_AND_REVERSE:
+ return 0x44;
+ case GL_AND_INVERTED:
+ return 0x22;
+ case GL_OR_REVERSE:
+ return 0xdd;
+ case GL_OR_INVERTED:
+ return 0xbb;
+ default:
+ fprintf(stderr, "unknown blend logic operation %x\n", logicop);
+ return 0xcc;
+ }
+}
+
+/**
+ * Used internally to update the r300->hw hardware state to match the
+ * current OpenGL state.
+ */
+static void r700SetLogicOpState(GLcontext *ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&R700_CONTEXT(ctx)->hw);
+
+ R600_STATECHANGE(context, blnd);
+
+ if (RGBA_LOGICOP_ENABLED(ctx))
+ SETfield(r700->CB_COLOR_CONTROL.u32All,
+ translate_logicop(ctx->Color.LogicOp), ROP3_shift, ROP3_mask);
+ else
+ SETfield(r700->CB_COLOR_CONTROL.u32All, 0xCC, ROP3_shift, ROP3_mask);
+}
+
+/**
+ * Called by Mesa when an application program changes the LogicOp state
+ * via glLogicOp.
+ */
+static void r700LogicOpcode(GLcontext *ctx, GLenum logicop)
+{
+ if (RGBA_LOGICOP_ENABLED(ctx))
+ r700SetLogicOpState(ctx);
+}
+
+static void r700UpdateCulling(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&R700_CONTEXT(ctx)->hw);
+
+ R600_STATECHANGE(context, su);
+
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, FACE_bit);
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+
+ if (ctx->Polygon.CullFlag)
+ {
+ switch (ctx->Polygon.CullFaceMode)
+ {
+ case GL_FRONT:
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+ break;
+ case GL_BACK:
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+ break;
+ case GL_FRONT_AND_BACK:
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+ break;
+ default:
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+ break;
+ }
+ }
+
+ switch (ctx->Polygon.FrontFace)
+ {
+ case GL_CW:
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, FACE_bit);
+ break;
+ case GL_CCW:
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, FACE_bit);
+ break;
+ default:
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, FACE_bit); /* default: ccw */
+ break;
+ }
+}
+
+static void r700UpdateLineStipple(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&R700_CONTEXT(ctx)->hw);
+
+ R600_STATECHANGE(context, sc);
+
+ if (ctx->Line.StippleFlag)
+ {
+ SETbit(r700->PA_SC_MODE_CNTL.u32All, LINE_STIPPLE_ENABLE_bit);
+ }
+ else
+ {
+ CLEARbit(r700->PA_SC_MODE_CNTL.u32All, LINE_STIPPLE_ENABLE_bit);
+ }
+}
+
+static void r700Enable(GLcontext * ctx, GLenum cap, GLboolean state) //------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+
+ switch (cap) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ /* empty */
+ break;
+ case GL_FOG:
+ /* empty */
+ break;
+ case GL_ALPHA_TEST:
+ r700SetAlphaState(ctx);
+ break;
+ case GL_COLOR_LOGIC_OP:
+ r700SetLogicOpState(ctx);
+ /* fall-through, because logic op overrides blending */
+ case GL_BLEND:
+ r700SetBlendState(ctx);
+ break;
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ r700SetClipPlaneState(ctx, cap, state);
+ break;
+ case GL_DEPTH_TEST:
+ r700SetDepthState(ctx);
+ break;
+ case GL_STENCIL_TEST:
+ r700SetStencilState(ctx, state);
+ break;
+ case GL_CULL_FACE:
+ r700UpdateCulling(ctx);
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ case GL_POLYGON_OFFSET_LINE:
+ case GL_POLYGON_OFFSET_FILL:
+ r700SetPolygonOffsetState(ctx, state);
+ break;
+ case GL_SCISSOR_TEST:
+ radeon_firevertices(&context->radeon);
+ context->radeon.state.scissor.enabled = state;
+ radeonUpdateScissor(ctx);
+ break;
+ case GL_LINE_STIPPLE:
+ r700UpdateLineStipple(ctx);
+ break;
+ default:
+ break;
+ }
+
+}
+
+/**
+ * Handle glColorMask()
+ */
+static void r700ColorMask(GLcontext * ctx,
+ GLboolean r, GLboolean g, GLboolean b, GLboolean a) //------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&R700_CONTEXT(ctx)->hw);
+ unsigned int mask = ((r ? 1 : 0) |
+ (g ? 2 : 0) |
+ (b ? 4 : 0) |
+ (a ? 8 : 0));
+
+ if (mask != r700->CB_SHADER_MASK.u32All) {
+ R600_STATECHANGE(context, cb);
+ SETfield(r700->CB_SHADER_MASK.u32All, mask, OUTPUT0_ENABLE_shift, OUTPUT0_ENABLE_mask);
+ }
+}
+
+/**
+ * Change the depth testing function.
+ *
+ * \note Mesa already filters redundant calls to this function.
+ */
+static void r700DepthFunc(GLcontext * ctx, GLenum func) //--------------------
+{
+ r700SetDepthState(ctx);
+}
+
+/**
+ * Enable/Disable depth writing.
+ *
+ * \note Mesa already filters redundant calls to this function.
+ */
+static void r700DepthMask(GLcontext * ctx, GLboolean mask) //------------------
+{
+ r700SetDepthState(ctx);
+}
+
+/**
+ * Change the culling mode.
+ *
+ * \note Mesa already filters redundant calls to this function.
+ */
+static void r700CullFace(GLcontext * ctx, GLenum mode) //-----------------
+{
+ r700UpdateCulling(ctx);
+}
+
+/* =============================================================
+ * Fog
+ */
+static void r700Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param) //--------------
+{
+}
+
+/**
+ * Change the polygon orientation.
+ *
+ * \note Mesa already filters redundant calls to this function.
+ */
+static void r700FrontFace(GLcontext * ctx, GLenum mode) //------------------
+{
+ r700UpdateCulling(ctx);
+ r700UpdatePolygonMode(ctx);
+}
+
+static void r700ShadeModel(GLcontext * ctx, GLenum mode) //--------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ R600_STATECHANGE(context, spi);
+
+ /* also need to set/clear FLAT_SHADE bit per param in SPI_PS_INPUT_CNTL_[0-31] */
+ switch (mode) {
+ case GL_FLAT:
+ SETbit(r700->SPI_INTERP_CONTROL_0.u32All, FLAT_SHADE_ENA_bit);
+ break;
+ case GL_SMOOTH:
+ CLEARbit(r700->SPI_INTERP_CONTROL_0.u32All, FLAT_SHADE_ENA_bit);
+ break;
+ default:
+ return;
+ }
+}
+
+/* =============================================================
+ * Point state
+ */
+static void r700PointSize(GLcontext * ctx, GLfloat size)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ R600_STATECHANGE(context, su);
+
+ /* We need to clamp to user defined range here, because
+ * the HW clamping happens only for per vertex point size. */
+ size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
+
+ /* same size limits for AA, non-AA points */
+ size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
+
+ /* format is 12.4 fixed point */
+ SETfield(r700->PA_SU_POINT_SIZE.u32All, (int)(size * 16),
+ PA_SU_POINT_SIZE__HEIGHT_shift, PA_SU_POINT_SIZE__HEIGHT_mask);
+ SETfield(r700->PA_SU_POINT_SIZE.u32All, (int)(size * 16),
+ PA_SU_POINT_SIZE__WIDTH_shift, PA_SU_POINT_SIZE__WIDTH_mask);
+
+}
+
+static void r700PointParameter(GLcontext * ctx, GLenum pname, const GLfloat * param) //---------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ R600_STATECHANGE(context, su);
+
+ /* format is 12.4 fixed point */
+ switch (pname) {
+ case GL_POINT_SIZE_MIN:
+ SETfield(r700->PA_SU_POINT_MINMAX.u32All, (int)(ctx->Point.MinSize * 16.0),
+ MIN_SIZE_shift, MIN_SIZE_mask);
+ break;
+ case GL_POINT_SIZE_MAX:
+ SETfield(r700->PA_SU_POINT_MINMAX.u32All, (int)(ctx->Point.MaxSize * 16.0),
+ MAX_SIZE_shift, MAX_SIZE_mask);
+ break;
+ case GL_POINT_DISTANCE_ATTENUATION:
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE:
+ break;
+ default:
+ break;
+ }
+}
+
+static int translate_stencil_func(int func)
+{
+ switch (func) {
+ case GL_NEVER:
+ return REF_NEVER;
+ case GL_LESS:
+ return REF_LESS;
+ case GL_EQUAL:
+ return REF_EQUAL;
+ case GL_LEQUAL:
+ return REF_LEQUAL;
+ case GL_GREATER:
+ return REF_GREATER;
+ case GL_NOTEQUAL:
+ return REF_NOTEQUAL;
+ case GL_GEQUAL:
+ return REF_GEQUAL;
+ case GL_ALWAYS:
+ return REF_ALWAYS;
+ }
+ return 0;
+}
+
+static int translate_stencil_op(int op)
+{
+ switch (op) {
+ case GL_KEEP:
+ return STENCIL_KEEP;
+ case GL_ZERO:
+ return STENCIL_ZERO;
+ case GL_REPLACE:
+ return STENCIL_REPLACE;
+ case GL_INCR:
+ return STENCIL_INCR_CLAMP;
+ case GL_DECR:
+ return STENCIL_DECR_CLAMP;
+ case GL_INCR_WRAP_EXT:
+ return STENCIL_INCR_WRAP;
+ case GL_DECR_WRAP_EXT:
+ return STENCIL_DECR_WRAP;
+ case GL_INVERT:
+ return STENCIL_INVERT;
+ default:
+ WARN_ONCE("Do not know how to translate stencil op");
+ return STENCIL_KEEP;
+ }
+ return 0;
+}
+
+static void r700SetStencilState(GLcontext * ctx, GLboolean state)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ GLboolean hw_stencil = GL_FALSE;
+
+ if (ctx->DrawBuffer) {
+ struct radeon_renderbuffer *rrbStencil
+ = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
+ hw_stencil = (rrbStencil && rrbStencil->bo);
+ }
+
+ if (hw_stencil) {
+ R600_STATECHANGE(context, db);
+ if (state) {
+ SETbit(r700->DB_DEPTH_CONTROL.u32All, STENCIL_ENABLE_bit);
+ SETbit(r700->DB_DEPTH_CONTROL.u32All, BACKFACE_ENABLE_bit);
+ } else
+ CLEARbit(r700->DB_DEPTH_CONTROL.u32All, STENCIL_ENABLE_bit);
+ }
+}
+
+static void r700StencilFuncSeparate(GLcontext * ctx, GLenum face,
+ GLenum func, GLint ref, GLuint mask) //---------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ const unsigned back = ctx->Stencil._BackFace;
+
+ R600_STATECHANGE(context, stencil);
+ R600_STATECHANGE(context, db);
+
+ //front
+ SETfield(r700->DB_STENCILREFMASK.u32All, ctx->Stencil.Ref[0],
+ STENCILREF_shift, STENCILREF_mask);
+ SETfield(r700->DB_STENCILREFMASK.u32All, ctx->Stencil.ValueMask[0],
+ STENCILMASK_shift, STENCILMASK_mask);
+
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, translate_stencil_func(ctx->Stencil.Function[0]),
+ STENCILFUNC_shift, STENCILFUNC_mask);
+
+ //back
+ SETfield(r700->DB_STENCILREFMASK_BF.u32All, ctx->Stencil.Ref[back],
+ STENCILREF_BF_shift, STENCILREF_BF_mask);
+ SETfield(r700->DB_STENCILREFMASK_BF.u32All, ctx->Stencil.ValueMask[back],
+ STENCILMASK_BF_shift, STENCILMASK_BF_mask);
+
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, translate_stencil_func(ctx->Stencil.Function[back]),
+ STENCILFUNC_BF_shift, STENCILFUNC_BF_mask);
+
+}
+
+static void r700StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask) //--------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ const unsigned back = ctx->Stencil._BackFace;
+
+ R600_STATECHANGE(context, stencil);
+
+ // front
+ SETfield(r700->DB_STENCILREFMASK.u32All, ctx->Stencil.WriteMask[0],
+ STENCILWRITEMASK_shift, STENCILWRITEMASK_mask);
+
+ // back
+ SETfield(r700->DB_STENCILREFMASK_BF.u32All, ctx->Stencil.WriteMask[back],
+ STENCILWRITEMASK_BF_shift, STENCILWRITEMASK_BF_mask);
+
+}
+
+static void r700StencilOpSeparate(GLcontext * ctx, GLenum face,
+ GLenum fail, GLenum zfail, GLenum zpass) //--------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ const unsigned back = ctx->Stencil._BackFace;
+
+ R600_STATECHANGE(context, db);
+
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, translate_stencil_op(ctx->Stencil.FailFunc[0]),
+ STENCILFAIL_shift, STENCILFAIL_mask);
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, translate_stencil_op(ctx->Stencil.ZFailFunc[0]),
+ STENCILZFAIL_shift, STENCILZFAIL_mask);
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, translate_stencil_op(ctx->Stencil.ZPassFunc[0]),
+ STENCILZPASS_shift, STENCILZPASS_mask);
+
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, translate_stencil_op(ctx->Stencil.FailFunc[back]),
+ STENCILFAIL_BF_shift, STENCILFAIL_BF_mask);
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, translate_stencil_op(ctx->Stencil.ZFailFunc[back]),
+ STENCILZFAIL_BF_shift, STENCILZFAIL_BF_mask);
+ SETfield(r700->DB_DEPTH_CONTROL.u32All, translate_stencil_op(ctx->Stencil.ZPassFunc[back]),
+ STENCILZPASS_BF_shift, STENCILZPASS_BF_mask);
+}
+
+static void r700UpdateWindow(GLcontext * ctx, int id) //--------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&context->radeon);
+ GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
+ GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+ const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+ const GLboolean render_to_fbo = (ctx->DrawBuffer->Name != 0);
+ GLfloat y_scale, y_bias;
+
+ if (render_to_fbo) {
+ y_scale = 1.0;
+ y_bias = 0;
+ } else {
+ y_scale = -1.0;
+ y_bias = yoffset;
+ }
+
+ GLfloat sx = v[MAT_SX];
+ GLfloat tx = v[MAT_TX] + xoffset;
+ GLfloat sy = v[MAT_SY] * y_scale;
+ GLfloat ty = (v[MAT_TY] * y_scale) + y_bias;
+ GLfloat sz = v[MAT_SZ] * depthScale;
+ GLfloat tz = v[MAT_TZ] * depthScale;
+
+ R600_STATECHANGE(context, vpt);
+
+ r700->viewport[id].PA_CL_VPORT_XSCALE.f32All = sx;
+ r700->viewport[id].PA_CL_VPORT_XOFFSET.f32All = tx;
+
+ r700->viewport[id].PA_CL_VPORT_YSCALE.f32All = sy;
+ r700->viewport[id].PA_CL_VPORT_YOFFSET.f32All = ty;
+
+ r700->viewport[id].PA_CL_VPORT_ZSCALE.f32All = sz;
+ r700->viewport[id].PA_CL_VPORT_ZOFFSET.f32All = tz;
+
+ r700->viewport[id].enabled = GL_TRUE;
+
+ r700SetScissor(context);
+}
+
+
+static void r700Viewport(GLcontext * ctx,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height) //--------------------
+{
+ r700UpdateWindow(ctx, 0);
+
+ radeon_viewport(ctx, x, y, width, height);
+}
+
+static void r700DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval) //-------------
+{
+ r700UpdateWindow(ctx, 0);
+}
+
+static void r700LineWidth(GLcontext * ctx, GLfloat widthf) //---------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ uint32_t lineWidth = (uint32_t)((widthf * 0.5) * (1 << 4));
+
+ R600_STATECHANGE(context, su);
+
+ if (lineWidth > 0xFFFF)
+ lineWidth = 0xFFFF;
+ SETfield(r700->PA_SU_LINE_CNTL.u32All,(uint16_t)lineWidth,
+ PA_SU_LINE_CNTL__WIDTH_shift, PA_SU_LINE_CNTL__WIDTH_mask);
+}
+
+static void r700LineStipple(GLcontext *ctx, GLint factor, GLushort pattern)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ R600_STATECHANGE(context, sc);
+
+ SETfield(r700->PA_SC_LINE_STIPPLE.u32All, pattern, LINE_PATTERN_shift, LINE_PATTERN_mask);
+ SETfield(r700->PA_SC_LINE_STIPPLE.u32All, (factor-1), REPEAT_COUNT_shift, REPEAT_COUNT_mask);
+ SETfield(r700->PA_SC_LINE_STIPPLE.u32All, 1, AUTO_RESET_CNTL_shift, AUTO_RESET_CNTL_mask);
+}
+
+static void r700SetPolygonOffsetState(GLcontext * ctx, GLboolean state)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ R600_STATECHANGE(context, su);
+
+ if (state) {
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_FRONT_ENABLE_bit);
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_BACK_ENABLE_bit);
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_PARA_ENABLE_bit);
+ } else {
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_FRONT_ENABLE_bit);
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_BACK_ENABLE_bit);
+ CLEARbit(r700->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_PARA_ENABLE_bit);
+ }
+}
+
+static void r700PolygonOffset(GLcontext * ctx, GLfloat factor, GLfloat units) //--------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ GLfloat constant = units;
+
+ switch (ctx->Visual.depthBits) {
+ case 16:
+ constant *= 4.0;
+ break;
+ case 24:
+ constant *= 2.0;
+ break;
+ }
+
+ factor *= 12.0;
+
+ R600_STATECHANGE(context, poly);
+
+ r700->PA_SU_POLY_OFFSET_FRONT_SCALE.f32All = factor;
+ r700->PA_SU_POLY_OFFSET_FRONT_OFFSET.f32All = constant;
+ r700->PA_SU_POLY_OFFSET_BACK_SCALE.f32All = factor;
+ r700->PA_SU_POLY_OFFSET_BACK_OFFSET.f32All = constant;
+}
+
+static void r700UpdatePolygonMode(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
+ R600_STATECHANGE(context, su);
+
+ SETfield(r700->PA_SU_SC_MODE_CNTL.u32All, X_DISABLE_POLY_MODE, POLY_MODE_shift, POLY_MODE_mask);
+
+ /* Only do something if a polygon mode is wanted, default is GL_FILL */
+ if (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL) {
+ GLenum f, b;
+
+ /* Handle GL_CW (clock wise and GL_CCW (counter clock wise)
+ * correctly by selecting the correct front and back face
+ */
+ if (ctx->Polygon.FrontFace == GL_CCW) {
+ f = ctx->Polygon.FrontMode;
+ b = ctx->Polygon.BackMode;
+ } else {
+ f = ctx->Polygon.BackMode;
+ b = ctx->Polygon.FrontMode;
+ }
+
+ /* Enable polygon mode */
+ SETfield(r700->PA_SU_SC_MODE_CNTL.u32All, X_DUAL_MODE, POLY_MODE_shift, POLY_MODE_mask);
+
+ switch (f) {
+ case GL_LINE:
+ SETfield(r700->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_LINES,
+ POLYMODE_FRONT_PTYPE_shift, POLYMODE_FRONT_PTYPE_mask);
+ break;
+ case GL_POINT:
+ SETfield(r700->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_POINTS,
+ POLYMODE_FRONT_PTYPE_shift, POLYMODE_FRONT_PTYPE_mask);
+ break;
+ case GL_FILL:
+ SETfield(r700->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_TRIANGLES,
+ POLYMODE_FRONT_PTYPE_shift, POLYMODE_FRONT_PTYPE_mask);
+ break;
+ }
+
+ switch (b) {
+ case GL_LINE:
+ SETfield(r700->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_LINES,
+ POLYMODE_BACK_PTYPE_shift, POLYMODE_BACK_PTYPE_mask);
+ break;
+ case GL_POINT:
+ SETfield(r700->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_POINTS,
+ POLYMODE_BACK_PTYPE_shift, POLYMODE_BACK_PTYPE_mask);
+ break;
+ case GL_FILL:
+ SETfield(r700->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_TRIANGLES,
+ POLYMODE_BACK_PTYPE_shift, POLYMODE_BACK_PTYPE_mask);
+ break;
+ }
+ }
+}
+
+static void r700PolygonMode(GLcontext * ctx, GLenum face, GLenum mode) //------------------
+{
+ (void)face;
+ (void)mode;
+
+ r700UpdatePolygonMode(ctx);
+}
+
+static void r700RenderMode(GLcontext * ctx, GLenum mode) //---------------------
+{
+}
+
+static void r700ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ GLint p;
+ GLint *ip;
+
+ p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
+ ip = (GLint *)ctx->Transform._ClipUserPlane[p];
+
+ R600_STATECHANGE(context, ucp);
+
+ r700->ucp[p].PA_CL_UCP_0_X.u32All = ip[0];
+ r700->ucp[p].PA_CL_UCP_0_Y.u32All = ip[1];
+ r700->ucp[p].PA_CL_UCP_0_Z.u32All = ip[2];
+ r700->ucp[p].PA_CL_UCP_0_W.u32All = ip[3];
+}
+
+static void r700SetClipPlaneState(GLcontext * ctx, GLenum cap, GLboolean state)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ GLuint p;
+
+ p = cap - GL_CLIP_PLANE0;
+
+ R600_STATECHANGE(context, cl);
+
+ if (state) {
+ r700->PA_CL_CLIP_CNTL.u32All |= (UCP_ENA_0_bit << p);
+ r700->ucp[p].enabled = GL_TRUE;
+ r700ClipPlane(ctx, cap, NULL);
+ } else {
+ r700->PA_CL_CLIP_CNTL.u32All &= ~(UCP_ENA_0_bit << p);
+ r700->ucp[p].enabled = GL_FALSE;
+ }
+}
+
+void r700SetScissor(context_t *context) //---------------
+{
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ unsigned x1, y1, x2, y2;
+ int id = 0;
+ struct radeon_renderbuffer *rrb;
+
+ rrb = radeon_get_colorbuffer(&context->radeon);
+ if (!rrb || !rrb->bo) {
+ return;
+ }
+ if (context->radeon.state.scissor.enabled) {
+ x1 = context->radeon.state.scissor.rect.x1;
+ y1 = context->radeon.state.scissor.rect.y1;
+ x2 = context->radeon.state.scissor.rect.x2;
+ y2 = context->radeon.state.scissor.rect.y2;
+ } else {
+ if (context->radeon.radeonScreen->driScreen->dri2.enabled) {
+ x1 = 0;
+ y1 = 0;
+ x2 = rrb->base.Width;
+ y2 = rrb->base.Height;
+ } else {
+ x1 = rrb->dPriv->x;
+ y1 = rrb->dPriv->y;
+ x2 = rrb->dPriv->x + rrb->dPriv->w;
+ y2 = rrb->dPriv->y + rrb->dPriv->h;
+ }
+ }
+
+ R600_STATECHANGE(context, scissor);
+
+ /* screen */
+ SETbit(r700->PA_SC_SCREEN_SCISSOR_TL.u32All, WINDOW_OFFSET_DISABLE_bit);
+ SETfield(r700->PA_SC_SCREEN_SCISSOR_TL.u32All, x1,
+ PA_SC_SCREEN_SCISSOR_TL__TL_X_shift, PA_SC_SCREEN_SCISSOR_TL__TL_X_mask);
+ SETfield(r700->PA_SC_SCREEN_SCISSOR_TL.u32All, y1,
+ PA_SC_SCREEN_SCISSOR_TL__TL_Y_shift, PA_SC_SCREEN_SCISSOR_TL__TL_Y_mask);
+
+ SETfield(r700->PA_SC_SCREEN_SCISSOR_BR.u32All, x2,
+ PA_SC_SCREEN_SCISSOR_BR__BR_X_shift, PA_SC_SCREEN_SCISSOR_BR__BR_X_mask);
+ SETfield(r700->PA_SC_SCREEN_SCISSOR_BR.u32All, y2,
+ PA_SC_SCREEN_SCISSOR_BR__BR_Y_shift, PA_SC_SCREEN_SCISSOR_BR__BR_Y_mask);
+
+ /* window */
+ SETbit(r700->PA_SC_WINDOW_SCISSOR_TL.u32All, WINDOW_OFFSET_DISABLE_bit);
+ SETfield(r700->PA_SC_WINDOW_SCISSOR_TL.u32All, x1,
+ PA_SC_WINDOW_SCISSOR_TL__TL_X_shift, PA_SC_WINDOW_SCISSOR_TL__TL_X_mask);
+ SETfield(r700->PA_SC_WINDOW_SCISSOR_TL.u32All, y1,
+ PA_SC_WINDOW_SCISSOR_TL__TL_Y_shift, PA_SC_WINDOW_SCISSOR_TL__TL_Y_mask);
+
+ SETfield(r700->PA_SC_WINDOW_SCISSOR_BR.u32All, x2,
+ PA_SC_WINDOW_SCISSOR_BR__BR_X_shift, PA_SC_WINDOW_SCISSOR_BR__BR_X_mask);
+ SETfield(r700->PA_SC_WINDOW_SCISSOR_BR.u32All, y2,
+ PA_SC_WINDOW_SCISSOR_BR__BR_Y_shift, PA_SC_WINDOW_SCISSOR_BR__BR_Y_mask);
+
+
+ SETfield(r700->PA_SC_CLIPRECT_0_TL.u32All, x1,
+ PA_SC_CLIPRECT_0_TL__TL_X_shift, PA_SC_CLIPRECT_0_TL__TL_X_mask);
+ SETfield(r700->PA_SC_CLIPRECT_0_TL.u32All, y1,
+ PA_SC_CLIPRECT_0_TL__TL_Y_shift, PA_SC_CLIPRECT_0_TL__TL_Y_mask);
+ SETfield(r700->PA_SC_CLIPRECT_0_BR.u32All, x2,
+ PA_SC_CLIPRECT_0_BR__BR_X_shift, PA_SC_CLIPRECT_0_BR__BR_X_mask);
+ SETfield(r700->PA_SC_CLIPRECT_0_BR.u32All, y2,
+ PA_SC_CLIPRECT_0_BR__BR_Y_shift, PA_SC_CLIPRECT_0_BR__BR_Y_mask);
+
+ r700->PA_SC_CLIPRECT_1_TL.u32All = r700->PA_SC_CLIPRECT_0_TL.u32All;
+ r700->PA_SC_CLIPRECT_1_BR.u32All = r700->PA_SC_CLIPRECT_0_BR.u32All;
+ r700->PA_SC_CLIPRECT_2_TL.u32All = r700->PA_SC_CLIPRECT_0_TL.u32All;
+ r700->PA_SC_CLIPRECT_2_BR.u32All = r700->PA_SC_CLIPRECT_0_BR.u32All;
+ r700->PA_SC_CLIPRECT_3_TL.u32All = r700->PA_SC_CLIPRECT_0_TL.u32All;
+ r700->PA_SC_CLIPRECT_3_BR.u32All = r700->PA_SC_CLIPRECT_0_BR.u32All;
+
+ /* more....2d clip */
+ SETbit(r700->PA_SC_GENERIC_SCISSOR_TL.u32All, WINDOW_OFFSET_DISABLE_bit);
+ SETfield(r700->PA_SC_GENERIC_SCISSOR_TL.u32All, x1,
+ PA_SC_GENERIC_SCISSOR_TL__TL_X_shift, PA_SC_GENERIC_SCISSOR_TL__TL_X_mask);
+ SETfield(r700->PA_SC_GENERIC_SCISSOR_TL.u32All, y1,
+ PA_SC_GENERIC_SCISSOR_TL__TL_Y_shift, PA_SC_GENERIC_SCISSOR_TL__TL_Y_mask);
+ SETfield(r700->PA_SC_GENERIC_SCISSOR_BR.u32All, x2,
+ PA_SC_GENERIC_SCISSOR_BR__BR_X_shift, PA_SC_GENERIC_SCISSOR_BR__BR_X_mask);
+ SETfield(r700->PA_SC_GENERIC_SCISSOR_BR.u32All, y2,
+ PA_SC_GENERIC_SCISSOR_BR__BR_Y_shift, PA_SC_GENERIC_SCISSOR_BR__BR_Y_mask);
+
+ SETbit(r700->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All, WINDOW_OFFSET_DISABLE_bit);
+ SETfield(r700->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All, x1,
+ PA_SC_VPORT_SCISSOR_0_TL__TL_X_shift, PA_SC_VPORT_SCISSOR_0_TL__TL_X_mask);
+ SETfield(r700->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All, y1,
+ PA_SC_VPORT_SCISSOR_0_TL__TL_Y_shift, PA_SC_VPORT_SCISSOR_0_TL__TL_Y_mask);
+ SETfield(r700->viewport[id].PA_SC_VPORT_SCISSOR_0_BR.u32All, x2,
+ PA_SC_VPORT_SCISSOR_0_BR__BR_X_shift, PA_SC_VPORT_SCISSOR_0_BR__BR_X_mask);
+ SETfield(r700->viewport[id].PA_SC_VPORT_SCISSOR_0_BR.u32All, y2,
+ PA_SC_VPORT_SCISSOR_0_BR__BR_Y_shift, PA_SC_VPORT_SCISSOR_0_BR__BR_Y_mask);
+
+ r700->viewport[id].PA_SC_VPORT_ZMIN_0.u32All = 0;
+ r700->viewport[id].PA_SC_VPORT_ZMAX_0.u32All = 0x3F800000;
+ r700->viewport[id].enabled = GL_TRUE;
+}
+
+static void r700InitSQConfig(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ int ps_prio;
+ int vs_prio;
+ int gs_prio;
+ int es_prio;
+ int num_ps_gprs;
+ int num_vs_gprs;
+ int num_gs_gprs;
+ int num_es_gprs;
+ int num_temp_gprs;
+ int num_ps_threads;
+ int num_vs_threads;
+ int num_gs_threads;
+ int num_es_threads;
+ int num_ps_stack_entries;
+ int num_vs_stack_entries;
+ int num_gs_stack_entries;
+ int num_es_stack_entries;
+
+ R600_STATECHANGE(context, sq);
+
+ // SQ
+ ps_prio = 0;
+ vs_prio = 1;
+ gs_prio = 2;
+ es_prio = 3;
+ switch (context->radeon.radeonScreen->chip_family) {
+ case CHIP_FAMILY_R600:
+ num_ps_gprs = 192;
+ num_vs_gprs = 56;
+ num_temp_gprs = 4;
+ num_gs_gprs = 0;
+ num_es_gprs = 0;
+ num_ps_threads = 136;
+ num_vs_threads = 48;
+ num_gs_threads = 4;
+ num_es_threads = 4;
+ num_ps_stack_entries = 128;
+ num_vs_stack_entries = 128;
+ num_gs_stack_entries = 0;
+ num_es_stack_entries = 0;
+ break;
+ case CHIP_FAMILY_RV630:
+ case CHIP_FAMILY_RV635:
+ num_ps_gprs = 84;
+ num_vs_gprs = 36;
+ num_temp_gprs = 4;
+ num_gs_gprs = 0;
+ num_es_gprs = 0;
+ num_ps_threads = 144;
+ num_vs_threads = 40;
+ num_gs_threads = 4;
+ num_es_threads = 4;
+ num_ps_stack_entries = 40;
+ num_vs_stack_entries = 40;
+ num_gs_stack_entries = 32;
+ num_es_stack_entries = 16;
+ break;
+ case CHIP_FAMILY_RV610:
+ case CHIP_FAMILY_RV620:
+ case CHIP_FAMILY_RS780:
+ case CHIP_FAMILY_RS880:
+ default:
+ num_ps_gprs = 84;
+ num_vs_gprs = 36;
+ num_temp_gprs = 4;
+ num_gs_gprs = 0;
+ num_es_gprs = 0;
+ num_ps_threads = 136;
+ num_vs_threads = 48;
+ num_gs_threads = 4;
+ num_es_threads = 4;
+ num_ps_stack_entries = 40;
+ num_vs_stack_entries = 40;
+ num_gs_stack_entries = 32;
+ num_es_stack_entries = 16;
+ break;
+ case CHIP_FAMILY_RV670:
+ num_ps_gprs = 144;
+ num_vs_gprs = 40;
+ num_temp_gprs = 4;
+ num_gs_gprs = 0;
+ num_es_gprs = 0;
+ num_ps_threads = 136;
+ num_vs_threads = 48;
+ num_gs_threads = 4;
+ num_es_threads = 4;
+ num_ps_stack_entries = 40;
+ num_vs_stack_entries = 40;
+ num_gs_stack_entries = 32;
+ num_es_stack_entries = 16;
+ break;
+ case CHIP_FAMILY_RV770:
+ num_ps_gprs = 192;
+ num_vs_gprs = 56;
+ num_temp_gprs = 4;
+ num_gs_gprs = 0;
+ num_es_gprs = 0;
+ num_ps_threads = 188;
+ num_vs_threads = 60;
+ num_gs_threads = 0;
+ num_es_threads = 0;
+ num_ps_stack_entries = 256;
+ num_vs_stack_entries = 256;
+ num_gs_stack_entries = 0;
+ num_es_stack_entries = 0;
+ break;
+ case CHIP_FAMILY_RV730:
+ case CHIP_FAMILY_RV740:
+ num_ps_gprs = 84;
+ num_vs_gprs = 36;
+ num_temp_gprs = 4;
+ num_gs_gprs = 0;
+ num_es_gprs = 0;
+ num_ps_threads = 188;
+ num_vs_threads = 60;
+ num_gs_threads = 0;
+ num_es_threads = 0;
+ num_ps_stack_entries = 128;
+ num_vs_stack_entries = 128;
+ num_gs_stack_entries = 0;
+ num_es_stack_entries = 0;
+ break;
+ case CHIP_FAMILY_RV710:
+ num_ps_gprs = 192;
+ num_vs_gprs = 56;
+ num_temp_gprs = 4;
+ num_gs_gprs = 0;
+ num_es_gprs = 0;
+ num_ps_threads = 144;
+ num_vs_threads = 48;
+ num_gs_threads = 0;
+ num_es_threads = 0;
+ num_ps_stack_entries = 128;
+ num_vs_stack_entries = 128;
+ num_gs_stack_entries = 0;
+ num_es_stack_entries = 0;
+ break;
+ }
+
+ r700->sq_config.SQ_CONFIG.u32All = 0;
+ if ((context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV610) ||
+ (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV620) ||
+ (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RS780) ||
+ (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RS880) ||
+ (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV710))
+ CLEARbit(r700->sq_config.SQ_CONFIG.u32All, VC_ENABLE_bit);
+ else
+ SETbit(r700->sq_config.SQ_CONFIG.u32All, VC_ENABLE_bit);
+ SETbit(r700->sq_config.SQ_CONFIG.u32All, DX9_CONSTS_bit);
+ SETbit(r700->sq_config.SQ_CONFIG.u32All, ALU_INST_PREFER_VECTOR_bit);
+ SETfield(r700->sq_config.SQ_CONFIG.u32All, ps_prio, PS_PRIO_shift, PS_PRIO_mask);
+ SETfield(r700->sq_config.SQ_CONFIG.u32All, ps_prio, VS_PRIO_shift, VS_PRIO_mask);
+ SETfield(r700->sq_config.SQ_CONFIG.u32All, ps_prio, GS_PRIO_shift, GS_PRIO_mask);
+ SETfield(r700->sq_config.SQ_CONFIG.u32All, ps_prio, ES_PRIO_shift, ES_PRIO_mask);
+
+ r700->sq_config.SQ_GPR_RESOURCE_MGMT_1.u32All = 0;
+ SETfield(r700->sq_config.SQ_GPR_RESOURCE_MGMT_1.u32All, num_ps_gprs, NUM_PS_GPRS_shift, NUM_PS_GPRS_mask);
+ SETfield(r700->sq_config.SQ_GPR_RESOURCE_MGMT_1.u32All, num_vs_gprs, NUM_VS_GPRS_shift, NUM_VS_GPRS_mask);
+ SETfield(r700->sq_config.SQ_GPR_RESOURCE_MGMT_1.u32All, num_temp_gprs,
+ NUM_CLAUSE_TEMP_GPRS_shift, NUM_CLAUSE_TEMP_GPRS_mask);
+
+ r700->sq_config.SQ_GPR_RESOURCE_MGMT_2.u32All = 0;
+ SETfield(r700->sq_config.SQ_GPR_RESOURCE_MGMT_2.u32All, num_gs_gprs, NUM_GS_GPRS_shift, NUM_GS_GPRS_mask);
+ SETfield(r700->sq_config.SQ_GPR_RESOURCE_MGMT_2.u32All, num_es_gprs, NUM_ES_GPRS_shift, NUM_ES_GPRS_mask);
+
+ r700->sq_config.SQ_THREAD_RESOURCE_MGMT.u32All = 0;
+ SETfield(r700->sq_config.SQ_THREAD_RESOURCE_MGMT.u32All, num_ps_threads,
+ NUM_PS_THREADS_shift, NUM_PS_THREADS_mask);
+ SETfield(r700->sq_config.SQ_THREAD_RESOURCE_MGMT.u32All, num_vs_threads,
+ NUM_VS_THREADS_shift, NUM_VS_THREADS_mask);
+ SETfield(r700->sq_config.SQ_THREAD_RESOURCE_MGMT.u32All, num_gs_threads,
+ NUM_GS_THREADS_shift, NUM_GS_THREADS_mask);
+ SETfield(r700->sq_config.SQ_THREAD_RESOURCE_MGMT.u32All, num_es_threads,
+ NUM_ES_THREADS_shift, NUM_ES_THREADS_mask);
+
+ r700->sq_config.SQ_STACK_RESOURCE_MGMT_1.u32All = 0;
+ SETfield(r700->sq_config.SQ_STACK_RESOURCE_MGMT_1.u32All, num_ps_stack_entries,
+ NUM_PS_STACK_ENTRIES_shift, NUM_PS_STACK_ENTRIES_mask);
+ SETfield(r700->sq_config.SQ_STACK_RESOURCE_MGMT_1.u32All, num_vs_stack_entries,
+ NUM_VS_STACK_ENTRIES_shift, NUM_VS_STACK_ENTRIES_mask);
+
+ r700->sq_config.SQ_STACK_RESOURCE_MGMT_2.u32All = 0;
+ SETfield(r700->sq_config.SQ_STACK_RESOURCE_MGMT_2.u32All, num_gs_stack_entries,
+ NUM_GS_STACK_ENTRIES_shift, NUM_GS_STACK_ENTRIES_mask);
+ SETfield(r700->sq_config.SQ_STACK_RESOURCE_MGMT_2.u32All, num_es_stack_entries,
+ NUM_ES_STACK_ENTRIES_shift, NUM_ES_STACK_ENTRIES_mask);
+
+}
+
+/**
+ * Calculate initial hardware state and register state functions.
+ * Assumes that the command buffer and state atoms have been
+ * initialized already.
+ */
+void r700InitState(GLcontext * ctx) //-------------------
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ int id = 0;
+
+ radeon_firevertices(&context->radeon);
+
+ r700->TA_CNTL_AUX.u32All = 0;
+ SETfield(r700->TA_CNTL_AUX.u32All, 28, TD_FIFO_CREDIT_shift, TD_FIFO_CREDIT_mask);
+ r700->VC_ENHANCE.u32All = 0;
+ r700->DB_WATERMARKS.u32All = 0;
+ SETfield(r700->DB_WATERMARKS.u32All, 4, DEPTH_FREE_shift, DEPTH_FREE_mask);
+ SETfield(r700->DB_WATERMARKS.u32All, 16, DEPTH_FLUSH_shift, DEPTH_FLUSH_mask);
+ SETfield(r700->DB_WATERMARKS.u32All, 0, FORCE_SUMMARIZE_shift, FORCE_SUMMARIZE_mask);
+ SETfield(r700->DB_WATERMARKS.u32All, 4, DEPTH_PENDING_FREE_shift, DEPTH_PENDING_FREE_mask);
+ r700->SQ_DYN_GPR_CNTL_PS_FLUSH_REQ.u32All = 0;
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770) {
+ SETfield(r700->TA_CNTL_AUX.u32All, 3, GRADIENT_CREDIT_shift, GRADIENT_CREDIT_mask);
+ r700->DB_DEBUG.u32All = 0x82000000;
+ SETfield(r700->DB_WATERMARKS.u32All, 16, DEPTH_CACHELINE_FREE_shift, DEPTH_CACHELINE_FREE_mask);
+ } else {
+ SETfield(r700->TA_CNTL_AUX.u32All, 2, GRADIENT_CREDIT_shift, GRADIENT_CREDIT_mask);
+ SETfield(r700->DB_WATERMARKS.u32All, 4, DEPTH_CACHELINE_FREE_shift, DEPTH_CACHELINE_FREE_mask);
+ SETbit(r700->SQ_DYN_GPR_CNTL_PS_FLUSH_REQ.u32All, VS_PC_LIMIT_ENABLE_bit);
+ }
+
+ /* Turn off vgt reuse */
+ r700->VGT_REUSE_OFF.u32All = 0;
+ SETbit(r700->VGT_REUSE_OFF.u32All, REUSE_OFF_bit);
+
+ /* Specify offsetting and clamp values for vertices */
+ r700->VGT_MAX_VTX_INDX.u32All = 0xFFFFFF;
+ r700->VGT_MIN_VTX_INDX.u32All = 0;
+ r700->VGT_INDX_OFFSET.u32All = 0;
+
+ /* default shader connections. */
+ r700->SPI_VS_OUT_ID_0.u32All = 0x03020100;
+ r700->SPI_VS_OUT_ID_1.u32All = 0x07060504;
+ r700->SPI_VS_OUT_ID_2.u32All = 0x0b0a0908;
+ r700->SPI_VS_OUT_ID_3.u32All = 0x0f0e0d0c;
+
+ r700->SPI_THREAD_GROUPING.u32All = 0;
+ if (context->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV770)
+ SETfield(r700->SPI_THREAD_GROUPING.u32All, 1, PS_GROUPING_shift, PS_GROUPING_mask);
+
+ /* 4 clip rectangles */ /* TODO : set these clip rects according to context->currentDraw->numClipRects */
+ r700->PA_SC_CLIPRECT_RULE.u32All = 0;
+ SETfield(r700->PA_SC_CLIPRECT_RULE.u32All, CLIP_RULE_mask, CLIP_RULE_shift, CLIP_RULE_mask);
+
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+ r700->PA_SC_EDGERULE.u32All = 0;
+ else
+ r700->PA_SC_EDGERULE.u32All = 0xAAAAAAAA;
+
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770) {
+ r700->PA_SC_MODE_CNTL.u32All = 0;
+ SETbit(r700->PA_SC_MODE_CNTL.u32All, WALK_ORDER_ENABLE_bit);
+ SETbit(r700->PA_SC_MODE_CNTL.u32All, FORCE_EOV_CNTDWN_ENABLE_bit);
+ } else {
+ r700->PA_SC_MODE_CNTL.u32All = 0x00500000;
+ SETbit(r700->PA_SC_MODE_CNTL.u32All, FORCE_EOV_REZ_ENABLE_bit);
+ SETbit(r700->PA_SC_MODE_CNTL.u32All, FORCE_EOV_CNTDWN_ENABLE_bit);
+ }
+
+ /* Do scale XY and Z by 1/W0. */
+ r700->bEnablePerspective = GL_TRUE;
+ CLEARbit(r700->PA_CL_VTE_CNTL.u32All, VTX_XY_FMT_bit);
+ CLEARbit(r700->PA_CL_VTE_CNTL.u32All, VTX_Z_FMT_bit);
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VTX_W0_FMT_bit);
+
+ /* Enable viewport scaling for all three axis */
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VPORT_X_SCALE_ENA_bit);
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VPORT_X_OFFSET_ENA_bit);
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VPORT_Y_SCALE_ENA_bit);
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VPORT_Y_OFFSET_ENA_bit);
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VPORT_Z_SCALE_ENA_bit);
+ SETbit(r700->PA_CL_VTE_CNTL.u32All, VPORT_Z_OFFSET_ENA_bit);
+
+ /* GL uses last vtx for flat shading components */
+ SETbit(r700->PA_SU_SC_MODE_CNTL.u32All, PROVOKING_VTX_LAST_bit);
+
+ /* Set up vertex control */
+ r700->PA_SU_VTX_CNTL.u32All = 0;
+ CLEARfield(r700->PA_SU_VTX_CNTL.u32All, QUANT_MODE_mask);
+ SETbit(r700->PA_SU_VTX_CNTL.u32All, PIX_CENTER_bit);
+ SETfield(r700->PA_SU_VTX_CNTL.u32All, X_ROUND_TO_EVEN,
+ PA_SU_VTX_CNTL__ROUND_MODE_shift, PA_SU_VTX_CNTL__ROUND_MODE_mask);
+
+ /* to 1.0 = no guard band */
+ r700->PA_CL_GB_VERT_CLIP_ADJ.u32All = 0x3F800000; /* 1.0 */
+ r700->PA_CL_GB_VERT_DISC_ADJ.u32All = 0x3F800000;
+ r700->PA_CL_GB_HORZ_CLIP_ADJ.u32All = 0x3F800000;
+ r700->PA_CL_GB_HORZ_DISC_ADJ.u32All = 0x3F800000;
+
+ /* Enable all samples for multi-sample anti-aliasing */
+ r700->PA_SC_AA_MASK.u32All = 0xFFFFFFFF;
+ /* Turn off AA */
+ r700->PA_SC_AA_CONFIG.u32All = 0;
+
+ r700->SX_MISC.u32All = 0;
+
+ r700InitSQConfig(ctx);
+
+ r700ColorMask(ctx,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP]);
+
+ r700Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test);
+ r700DepthMask(ctx, ctx->Depth.Mask);
+ r700DepthFunc(ctx, ctx->Depth.Func);
+ SETbit(r700->DB_SHADER_CONTROL.u32All, DUAL_EXPORT_ENABLE_bit);
+
+ r700->DB_DEPTH_CLEAR.u32All = 0x3F800000;
+
+ r700->DB_RENDER_CONTROL.u32All = 0;
+ SETbit(r700->DB_RENDER_CONTROL.u32All, STENCIL_COMPRESS_DISABLE_bit);
+ SETbit(r700->DB_RENDER_CONTROL.u32All, DEPTH_COMPRESS_DISABLE_bit);
+ r700->DB_RENDER_OVERRIDE.u32All = 0;
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+ SETbit(r700->DB_RENDER_OVERRIDE.u32All, FORCE_SHADER_Z_ORDER_bit);
+ SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIZ_ENABLE_shift, FORCE_HIZ_ENABLE_mask);
+ SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE0_shift, FORCE_HIS_ENABLE0_mask);
+ SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE1_shift, FORCE_HIS_ENABLE1_mask);
+
+ r700->DB_ALPHA_TO_MASK.u32All = 0;
+ SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET0_shift, ALPHA_TO_MASK_OFFSET0_mask);
+ SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET1_shift, ALPHA_TO_MASK_OFFSET1_mask);
+ SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET2_shift, ALPHA_TO_MASK_OFFSET2_mask);
+ SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET3_shift, ALPHA_TO_MASK_OFFSET3_mask);
+
+ /* stencil */
+ r700Enable(ctx, GL_STENCIL_TEST, ctx->Stencil._Enabled);
+ r700StencilMaskSeparate(ctx, 0, ctx->Stencil.WriteMask[0]);
+ r700StencilFuncSeparate(ctx, 0, ctx->Stencil.Function[0],
+ ctx->Stencil.Ref[0], ctx->Stencil.ValueMask[0]);
+ r700StencilOpSeparate(ctx, 0, ctx->Stencil.FailFunc[0],
+ ctx->Stencil.ZFailFunc[0],
+ ctx->Stencil.ZPassFunc[0]);
+
+ r700UpdateCulling(ctx);
+
+ r700SetBlendState(ctx);
+ r700SetLogicOpState(ctx);
+
+ r700AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);
+ r700Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled);
+
+ r700PointSize(ctx, 1.0);
+
+ CLEARfield(r700->PA_SU_POINT_MINMAX.u32All, MIN_SIZE_mask);
+ SETfield(r700->PA_SU_POINT_MINMAX.u32All, 0x8000, MAX_SIZE_shift, MAX_SIZE_mask);
+
+ r700LineWidth(ctx, 1.0);
+
+ r700->PA_SC_LINE_CNTL.u32All = 0;
+ CLEARbit(r700->PA_SC_LINE_CNTL.u32All, EXPAND_LINE_WIDTH_bit);
+ SETbit(r700->PA_SC_LINE_CNTL.u32All, LAST_PIXEL_bit);
+
+ r700ShadeModel(ctx, ctx->Light.ShadeModel);
+ r700PolygonMode(ctx, GL_FRONT, ctx->Polygon.FrontMode);
+ r700PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode);
+ r700PolygonOffset(ctx, ctx->Polygon.OffsetFactor,
+ ctx->Polygon.OffsetUnits);
+ r700Enable(ctx, GL_POLYGON_OFFSET_POINT, ctx->Polygon.OffsetPoint);
+ r700Enable(ctx, GL_POLYGON_OFFSET_LINE, ctx->Polygon.OffsetLine);
+ r700Enable(ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill);
+
+ /* CB */
+ r700BlendColor(ctx, ctx->Color.BlendColor);
+
+ r700->CB_CLEAR_RED_R6XX.f32All = 1.0; //r6xx only
+ r700->CB_CLEAR_GREEN_R6XX.f32All = 0.0; //r6xx only
+ r700->CB_CLEAR_BLUE_R6XX.f32All = 1.0; //r6xx only
+ r700->CB_CLEAR_ALPHA_R6XX.f32All = 1.0; //r6xx only
+ r700->CB_FOG_RED_R6XX.u32All = 0; //r6xx only
+ r700->CB_FOG_GREEN_R6XX.u32All = 0; //r6xx only
+ r700->CB_FOG_BLUE_R6XX.u32All = 0; //r6xx only
+
+ /* Disable color compares */
+ SETfield(r700->CB_CLRCMP_CONTROL.u32All, CLRCMP_DRAW_ALWAYS,
+ CLRCMP_FCN_SRC_shift, CLRCMP_FCN_SRC_mask);
+ SETfield(r700->CB_CLRCMP_CONTROL.u32All, CLRCMP_DRAW_ALWAYS,
+ CLRCMP_FCN_DST_shift, CLRCMP_FCN_DST_mask);
+ SETfield(r700->CB_CLRCMP_CONTROL.u32All, CLRCMP_SEL_SRC,
+ CLRCMP_FCN_SEL_shift, CLRCMP_FCN_SEL_mask);
+
+ /* Zero out source */
+ r700->CB_CLRCMP_SRC.u32All = 0x00000000;
+
+ /* Put a compare color in for error checking */
+ r700->CB_CLRCMP_DST.u32All = 0x000000FF;
+
+ /* Set up color compare mask */
+ r700->CB_CLRCMP_MSK.u32All = 0xFFFFFFFF;
+
+ /* screen/window/view */
+ SETfield(r700->CB_TARGET_MASK.u32All, 0xF, (4 * id), TARGET0_ENABLE_mask);
+
+ context->radeon.hw.all_dirty = GL_TRUE;
+
+}
+
+void r700InitStateFuncs(struct dd_function_table *functions) //-----------------
+{
+ functions->UpdateState = r700InvalidateState;
+ functions->AlphaFunc = r700AlphaFunc;
+ functions->BlendColor = r700BlendColor;
+ functions->BlendEquationSeparate = r700BlendEquationSeparate;
+ functions->BlendFuncSeparate = r700BlendFuncSeparate;
+ functions->Enable = r700Enable;
+ functions->ColorMask = r700ColorMask;
+ functions->DepthFunc = r700DepthFunc;
+ functions->DepthMask = r700DepthMask;
+ functions->CullFace = r700CullFace;
+ functions->Fogfv = r700Fogfv;
+ functions->FrontFace = r700FrontFace;
+ functions->ShadeModel = r700ShadeModel;
+ functions->LogicOpcode = r700LogicOpcode;
+
+ /* ARB_point_parameters */
+ functions->PointParameterfv = r700PointParameter;
+
+ /* Stencil related */
+ functions->StencilFuncSeparate = r700StencilFuncSeparate;
+ functions->StencilMaskSeparate = r700StencilMaskSeparate;
+ functions->StencilOpSeparate = r700StencilOpSeparate;
+
+ /* Viewport related */
+ functions->Viewport = r700Viewport;
+ functions->DepthRange = r700DepthRange;
+ functions->PointSize = r700PointSize;
+ functions->LineWidth = r700LineWidth;
+ functions->LineStipple = r700LineStipple;
+
+ functions->PolygonOffset = r700PolygonOffset;
+ functions->PolygonMode = r700PolygonMode;
+
+ functions->RenderMode = r700RenderMode;
+
+ functions->ClipPlane = r700ClipPlane;
+
+ functions->Scissor = radeonScissor;
+
+ functions->DrawBuffer = radeonDrawBuffer;
+ functions->ReadBuffer = radeonReadBuffer;
+
+}
+
diff --git a/src/mesa/drivers/dri/r600/r700_state.h b/src/mesa/drivers/dri/r600/r700_state.h
new file mode 100644
index 0000000000..0f53d5b4c5
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_state.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _R700_STATE_H
+#define _R700_STATE_H
+
+#include "main/mtypes.h"
+
+#include "r600_context.h"
+
+#include "r700_chip.h"
+
+extern void r700UpdateStateParameters(GLcontext * ctx, GLuint new_state);
+extern void r700UpdateShaders (GLcontext * ctx);
+
+extern void r700UpdateViewportOffset(GLcontext * ctx);
+
+extern void r700InitState (GLcontext * ctx);
+extern void r700InitStateFuncs (struct dd_function_table *functions);
+
+extern void r700SetScissor(context_t *context);
+
+#endif /* _R600_SCREEN_H */
diff --git a/src/mesa/drivers/dri/r600/r700_vertprog.c b/src/mesa/drivers/dri/r600/r700_vertprog.c
new file mode 100644
index 0000000000..8c2b0071df
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_vertprog.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "tnl/t_context.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_statevars.h"
+
+#include "radeon_debug.h"
+#include "r600_context.h"
+#include "r600_cmdbuf.h"
+
+#include "r700_debug.h"
+#include "r700_vertprog.h"
+
+unsigned int Map_Vertex_Output(r700_AssemblerBase *pAsm,
+ struct gl_vertex_program *mesa_vp,
+ unsigned int unStart)
+{
+ unsigned int i;
+ unsigned int unBit;
+ unsigned int unTotal = unStart;
+
+ //!!!!!!! THE ORDER MATCH FS INPUT
+
+ unBit = 1 << VERT_RESULT_HPOS;
+ if(mesa_vp->Base.OutputsWritten & unBit)
+ {
+ pAsm->ucVP_OutputMap[VERT_RESULT_HPOS] = unTotal++;
+ }
+
+ unBit = 1 << VERT_RESULT_COL0;
+ if(mesa_vp->Base.OutputsWritten & unBit)
+ {
+ pAsm->ucVP_OutputMap[VERT_RESULT_COL0] = unTotal++;
+ }
+
+ unBit = 1 << VERT_RESULT_COL1;
+ if(mesa_vp->Base.OutputsWritten & unBit)
+ {
+ pAsm->ucVP_OutputMap[VERT_RESULT_COL1] = unTotal++;
+ }
+
+ //TODO : dealing back face.
+ unBit = 1 << VERT_RESULT_BFC0;
+ if(mesa_vp->Base.OutputsWritten & unBit)
+ {
+ pAsm->ucVP_OutputMap[VERT_RESULT_BFC0] = unTotal++;
+ }
+
+ unBit = 1 << VERT_RESULT_BFC1;
+ if(mesa_vp->Base.OutputsWritten & unBit)
+ {
+ pAsm->ucVP_OutputMap[VERT_RESULT_BFC1] = unTotal++;
+ }
+
+ //TODO : dealing fog.
+ unBit = 1 << VERT_RESULT_FOGC;
+ if(mesa_vp->Base.OutputsWritten & unBit)
+ {
+ pAsm->ucVP_OutputMap[VERT_RESULT_FOGC] = unTotal++;
+ }
+
+ //TODO : dealing point size.
+ unBit = 1 << VERT_RESULT_PSIZ;
+ if(mesa_vp->Base.OutputsWritten & unBit)
+ {
+ pAsm->ucVP_OutputMap[VERT_RESULT_PSIZ] = unTotal++;
+ }
+
+ for(i=0; i<8; i++)
+ {
+ unBit = 1 << (VERT_RESULT_TEX0 + i);
+ if(mesa_vp->Base.OutputsWritten & unBit)
+ {
+ pAsm->ucVP_OutputMap[VERT_RESULT_TEX0 + i] = unTotal++;
+ }
+ }
+
+ return (unTotal - unStart);
+}
+
+unsigned int Map_Vertex_Input(r700_AssemblerBase *pAsm,
+ struct gl_vertex_program *mesa_vp,
+ unsigned int unStart)
+{
+ int i;
+ unsigned int unBit;
+ unsigned int unTotal = unStart;
+ for(i=0; i<VERT_ATTRIB_MAX; i++)
+ {
+ unBit = 1 << i;
+ if(mesa_vp->Base.InputsRead & unBit)
+ {
+ pAsm->ucVP_AttributeMap[i] = unTotal++;
+ }
+ }
+ return (unTotal - unStart);
+}
+
+GLboolean Process_Vertex_Program_Vfetch_Instructions(
+ struct r700_vertex_program *vp,
+ struct gl_vertex_program *mesa_vp)
+{
+ int i;
+ unsigned int unBit;
+ VTX_FETCH_METHOD vtxFetchMethod;
+ vtxFetchMethod.bEnableMini = GL_FALSE;
+ vtxFetchMethod.mega_fetch_remainder = 0;
+
+ for(i=0; i<VERT_ATTRIB_MAX; i++)
+ {
+ unBit = 1 << i;
+ if(mesa_vp->Base.InputsRead & unBit)
+ {
+ assemble_vfetch_instruction(&vp->r700AsmCode,
+ i,
+ vp->r700AsmCode.ucVP_AttributeMap[i],
+ vp->aos_desc[i].size,
+ vp->aos_desc[i].type,
+ &vtxFetchMethod);
+ }
+ }
+
+ return GL_TRUE;
+}
+
+void Map_Vertex_Program(struct r700_vertex_program *vp,
+ struct gl_vertex_program *mesa_vp)
+{
+ GLuint ui;
+ r700_AssemblerBase *pAsm = &(vp->r700AsmCode);
+ unsigned int num_inputs;
+
+ // R0 will always be used for index into vertex buffer
+ pAsm->number_used_registers = 1;
+ pAsm->starting_vfetch_register_number = pAsm->number_used_registers;
+
+ // Map Inputs: Add 1 to mapping since R0 is used for index
+ num_inputs = Map_Vertex_Input(pAsm, mesa_vp, pAsm->number_used_registers);
+ pAsm->number_used_registers += num_inputs;
+
+ // Create VFETCH instructions for inputs
+ if (GL_TRUE != Process_Vertex_Program_Vfetch_Instructions(vp, mesa_vp) )
+ {
+ radeon_error("Calling Process_Vertex_Program_Vfetch_Instructions return error. \n");
+ return; //error
+ }
+
+ // Map Outputs
+ pAsm->number_of_exports = Map_Vertex_Output(pAsm, mesa_vp, pAsm->number_used_registers);
+
+ pAsm->starting_export_register_number = pAsm->number_used_registers;
+
+ pAsm->number_used_registers += pAsm->number_of_exports;
+
+ pAsm->pucOutMask = (unsigned char*) MALLOC(pAsm->number_of_exports);
+
+ for(ui=0; ui<pAsm->number_of_exports; ui++)
+ {
+ pAsm->pucOutMask[ui] = 0x0;
+ }
+
+ /* Map temporary registers (GPRs) */
+ pAsm->starting_temp_register_number = pAsm->number_used_registers;
+
+ if(mesa_vp->Base.NumNativeTemporaries >= mesa_vp->Base.NumTemporaries)
+ { /* arb uses NumNativeTemporaries */
+ pAsm->number_used_registers += mesa_vp->Base.NumNativeTemporaries;
+ }
+ else
+ { /* fix func t_vp uses NumTemporaries */
+ pAsm->number_used_registers += mesa_vp->Base.NumTemporaries;
+ }
+
+ pAsm->uFirstHelpReg = pAsm->number_used_registers;
+}
+
+GLboolean Find_Instruction_Dependencies_vp(struct r700_vertex_program *vp,
+ struct gl_vertex_program *mesa_vp)
+{
+ GLuint i, j;
+ GLint * puiTEMPwrites;
+ struct prog_instruction *pILInst;
+ InstDeps *pInstDeps;
+
+ puiTEMPwrites = (GLint*) MALLOC(sizeof(GLuint)*mesa_vp->Base.NumTemporaries);
+ for(i=0; i<mesa_vp->Base.NumTemporaries; i++)
+ {
+ puiTEMPwrites[i] = -1;
+ }
+
+ pInstDeps = (InstDeps*)MALLOC(sizeof(InstDeps)*mesa_vp->Base.NumInstructions);
+
+ for(i=0; i<mesa_vp->Base.NumInstructions; i++)
+ {
+ pInstDeps[i].nDstDep = -1;
+ pILInst = &(mesa_vp->Base.Instructions[i]);
+
+ //Dst
+ if(pILInst->DstReg.File == PROGRAM_TEMPORARY)
+ {
+ //Set lastwrite for the temp
+ puiTEMPwrites[pILInst->DstReg.Index] = i;
+ }
+
+ //Src
+ for(j=0; j<3; j++)
+ {
+ if(pILInst->SrcReg[j].File == PROGRAM_TEMPORARY)
+ {
+ //Set dep.
+ pInstDeps[i].nSrcDeps[j] = puiTEMPwrites[pILInst->SrcReg[j].Index];
+ }
+ else
+ {
+ pInstDeps[i].nSrcDeps[j] = -1;
+ }
+ }
+ }
+
+ vp->r700AsmCode.pInstDeps = pInstDeps;
+
+ FREE(puiTEMPwrites);
+
+ return GL_TRUE;
+}
+
+struct r700_vertex_program* r700TranslateVertexShader(GLcontext *ctx,
+ struct gl_vertex_program *mesa_vp)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ struct r700_vertex_program *vp;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *vb = &tnl->vb;
+ unsigned int unBit;
+ unsigned int i;
+
+ vp = _mesa_calloc(sizeof(*vp));
+ vp->mesa_program = (struct gl_vertex_program *)_mesa_clone_program(ctx, &mesa_vp->Base);
+
+ for(i=0; i<VERT_ATTRIB_MAX; i++)
+ {
+ unBit = 1 << i;
+ if(vp->mesa_program->Base.InputsRead & unBit) /* ctx->Array.ArrayObj->xxxxxxx */
+ {
+ vp->aos_desc[i].size = vb->AttribPtr[i]->size;
+ vp->aos_desc[i].stride = vb->AttribPtr[i]->size * sizeof(GL_FLOAT);/* when emit array, data is packed. vb->AttribPtr[i]->stride;*/
+ vp->aos_desc[i].type = GL_FLOAT;
+ }
+ }
+
+ if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+ {
+ vp->r700AsmCode.bR6xx = 1;
+ }
+
+ //Init_Program
+ Init_r700_AssemblerBase(SPT_VP, &(vp->r700AsmCode), &(vp->r700Shader) );
+ Map_Vertex_Program( vp, mesa_vp );
+
+ if(GL_FALSE == Find_Instruction_Dependencies_vp(vp, mesa_vp))
+ {
+ return NULL;
+ }
+
+ if(GL_FALSE == AssembleInstr(mesa_vp->Base.NumInstructions,
+ &(mesa_vp->Base.Instructions[0]),
+ &(vp->r700AsmCode)) )
+ {
+ return NULL;
+ }
+
+ if(GL_FALSE == Process_Vertex_Exports(&(vp->r700AsmCode), mesa_vp->Base.OutputsWritten) )
+ {
+ return NULL;
+ }
+
+ vp->r700Shader.nRegs = (vp->r700AsmCode.number_used_registers == 0) ? 0
+ : (vp->r700AsmCode.number_used_registers - 1);
+
+ vp->r700Shader.nParamExports = vp->r700AsmCode.number_of_exports;
+
+ vp->translated = GL_TRUE;
+
+ return vp;
+}
+
+void r700SelectVertexShader(GLcontext *ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ struct r700_vertex_program_cont *vpc;
+ struct r700_vertex_program *vp;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *vb = &tnl->vb;
+ unsigned int unBit;
+ unsigned int i;
+ GLboolean match;
+
+ vpc = (struct r700_vertex_program_cont *)ctx->VertexProgram._Current;
+
+#if 0
+ if (context->radeon.NewGLState & (_NEW_PROGRAM_CONSTANTS|_NEW_PROGRAM))
+ {
+ vpc->needUpdateVF = 1;
+ }
+#endif
+
+ for (vp = vpc->progs; vp; vp = vp->next)
+ {
+ match = GL_TRUE;
+ for(i=0; i<VERT_ATTRIB_MAX; i++)
+ {
+ unBit = 1 << i;
+ if(vpc->mesa_program.Base.InputsRead & unBit)
+ {
+ if (vp->aos_desc[i].size != vb->AttribPtr[i]->size)
+ match = GL_FALSE;
+ break;
+ }
+ }
+ if (match)
+ {
+ context->selected_vp = vp;
+ return;
+ }
+ }
+
+ vp = r700TranslateVertexShader(ctx, &(vpc->mesa_program) );
+ if(!vp)
+ {
+ radeon_error("Failed to translate vertex shader. \n");
+ return;
+ }
+ vp->next = vpc->progs;
+ vpc->progs = vp;
+ context->selected_vp = vp;
+ return;
+}
+
+void * r700GetActiveVpShaderBo(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ struct r700_vertex_program *vp = context->selected_vp;;
+
+ if (vp)
+ return vp->shaderbo;
+ else
+ return NULL;
+}
+
+GLboolean r700SetupVertexProgram(GLcontext * ctx)
+{
+ context_t *context = R700_CONTEXT(ctx);
+ R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+ struct r700_vertex_program *vp = context->selected_vp;
+
+ struct gl_program_parameter_list *paramList;
+ unsigned int unNumParamData;
+ unsigned int ui;
+
+ if(GL_FALSE == vp->loaded)
+ {
+ if(vp->r700Shader.bNeedsAssembly == GL_TRUE)
+ {
+ Assemble( &(vp->r700Shader) );
+ }
+
+ /* Load vp to gpu */
+ r600EmitShader(ctx,
+ &(vp->shaderbo),
+ (GLvoid *)(vp->r700Shader.pProgram),
+ vp->r700Shader.uShaderBinaryDWORDSize,
+ "VS");
+
+ vp->loaded = GL_TRUE;
+ }
+
+ DumpHwBinary(DUMP_VERTEX_SHADER, (GLvoid *)(vp->r700Shader.pProgram),
+ vp->r700Shader.uShaderBinaryDWORDSize);
+
+ /* TODO : enable this after MemUse fixed *=
+ (context->chipobj.MemUse)(context, vp->shadercode.buf->id);
+ */
+
+ R600_STATECHANGE(context, vs);
+ R600_STATECHANGE(context, fs); /* hack */
+
+ r700->vs.SQ_PGM_RESOURCES_VS.u32All = 0;
+ SETbit(r700->vs.SQ_PGM_RESOURCES_VS.u32All, PGM_RESOURCES__PRIME_CACHE_ON_DRAW_bit);
+
+ r700->vs.SQ_PGM_START_VS.u32All = 0; /* set from buffer object. */
+
+ SETfield(r700->vs.SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.nRegs + 1,
+ NUM_GPRS_shift, NUM_GPRS_mask);
+
+ if(vp->r700Shader.uStackSize) /* we don't use branch for now, it should be zero. */
+ {
+ SETfield(r700->vs.SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.uStackSize,
+ STACK_SIZE_shift, STACK_SIZE_mask);
+ }
+
+ R600_STATECHANGE(context, spi);
+
+ SETfield(r700->SPI_VS_OUT_CONFIG.u32All,
+ vp->r700Shader.nParamExports ? (vp->r700Shader.nParamExports - 1) : 0,
+ VS_EXPORT_COUNT_shift, VS_EXPORT_COUNT_mask);
+ SETfield(r700->SPI_PS_IN_CONTROL_0.u32All, vp->r700Shader.nParamExports,
+ NUM_INTERP_shift, NUM_INTERP_mask);
+
+ /*
+ SETbit(r700->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit);
+ CLEARbit(r700->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit);
+ */
+
+ /* sent out shader constants. */
+ paramList = vp->mesa_program->Base.Parameters;
+
+ if(NULL != paramList) {
+ _mesa_load_state_parameters(ctx, paramList);
+
+ if (paramList->NumParameters > R700_MAX_DX9_CONSTS)
+ return GL_FALSE;
+
+ R600_STATECHANGE(context, vs_consts);
+
+ r700->vs.num_consts = paramList->NumParameters;
+
+ unNumParamData = paramList->NumParameters;
+
+ for(ui=0; ui<unNumParamData; ui++) {
+ r700->vs.consts[ui][0].f32All = paramList->ParameterValues[ui][0];
+ r700->vs.consts[ui][1].f32All = paramList->ParameterValues[ui][1];
+ r700->vs.consts[ui][2].f32All = paramList->ParameterValues[ui][2];
+ r700->vs.consts[ui][3].f32All = paramList->ParameterValues[ui][3];
+ }
+ } else
+ r700->vs.num_consts = 0;
+
+ return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/r600/r700_vertprog.h b/src/mesa/drivers/dri/r600/r700_vertprog.h
new file mode 100644
index 0000000000..c48764c43b
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/r700_vertprog.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+
+#ifndef _R700_VERTPROG_H_
+#define _R700_VERTPROG_H_
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+
+#include "r700_shader.h"
+#include "r700_assembler.h"
+
+typedef struct ArrayDesc //TEMP
+{
+ GLint size; //number of data element
+ GLenum type; //data element type
+ GLsizei stride;
+} ArrayDesc;
+
+struct r700_vertex_program
+{
+ struct gl_vertex_program *mesa_program; /* Must be first */
+
+ struct r700_vertex_program *next;
+
+ r700_AssemblerBase r700AsmCode;
+ R700_Shader r700Shader;
+
+ GLboolean translated;
+ GLboolean loaded;
+ GLboolean needUpdateVF;
+
+ void * shaderbo;
+
+ ArrayDesc aos_desc[VERT_ATTRIB_MAX];
+};
+
+struct r700_vertex_program_cont
+{
+ struct gl_vertex_program mesa_program;
+
+ struct r700_vertex_program *progs;
+};
+
+//Internal
+unsigned int Map_Vertex_Output(r700_AssemblerBase *pAsm,
+ struct gl_vertex_program *mesa_vp,
+ unsigned int unStart);
+unsigned int Map_Vertex_Input(r700_AssemblerBase *pAsm,
+ struct gl_vertex_program *mesa_vp,
+ unsigned int unStart);
+GLboolean Process_Vertex_Program_Vfetch_Instructions(
+ struct r700_vertex_program *vp,
+ struct gl_vertex_program *mesa_vp);
+void Map_Vertex_Program(struct r700_vertex_program *vp,
+ struct gl_vertex_program *mesa_vp);
+GLboolean Find_Instruction_Dependencies_vp(struct r700_vertex_program *vp,
+ struct gl_vertex_program *mesa_vp);
+
+struct r700_vertex_program* r700TranslateVertexShader(GLcontext *ctx,
+ struct gl_vertex_program *mesa_vp);
+
+/* Interface */
+extern void r700SelectVertexShader(GLcontext *ctx);
+
+extern GLboolean r700SetupVertexProgram(GLcontext * ctx);
+
+extern void * r700GetActiveVpShaderBo(GLcontext * ctx);
+
+#endif /* _R700_VERTPROG_H_ */
diff --git a/src/mesa/drivers/dri/r600/radeon_bo_legacy.c b/src/mesa/drivers/dri/r600/radeon_bo_legacy.c
new file mode 120000
index 0000000000..79ad050e6b
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_bo_legacy.c
@@ -0,0 +1 @@
+../radeon/radeon_bo_legacy.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_bo_legacy.h b/src/mesa/drivers/dri/r600/radeon_bo_legacy.h
new file mode 120000
index 0000000000..83b0f7ffab
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_bo_legacy.h
@@ -0,0 +1 @@
+../radeon/radeon_bo_legacy.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_bocs_wrapper.h b/src/mesa/drivers/dri/r600/radeon_bocs_wrapper.h
new file mode 120000
index 0000000000..ca894b2443
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_bocs_wrapper.h
@@ -0,0 +1 @@
+../radeon/radeon_bocs_wrapper.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_chipset.h b/src/mesa/drivers/dri/r600/radeon_chipset.h
new file mode 120000
index 0000000000..eba99001ff
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_chipset.h
@@ -0,0 +1 @@
+../radeon/radeon_chipset.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_cmdbuf.h b/src/mesa/drivers/dri/r600/radeon_cmdbuf.h
new file mode 120000
index 0000000000..a799e1dc6d
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_cmdbuf.h
@@ -0,0 +1 @@
+../radeon/radeon_cmdbuf.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_common.c b/src/mesa/drivers/dri/r600/radeon_common.c
new file mode 120000
index 0000000000..67b19ba940
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_common.c
@@ -0,0 +1 @@
+../radeon/radeon_common.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_common.h b/src/mesa/drivers/dri/r600/radeon_common.h
new file mode 120000
index 0000000000..5bcb696a9f
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_common.h
@@ -0,0 +1 @@
+../radeon/radeon_common.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_common_context.c b/src/mesa/drivers/dri/r600/radeon_common_context.c
new file mode 120000
index 0000000000..86800f3819
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_common_context.c
@@ -0,0 +1 @@
+../radeon/radeon_common_context.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_common_context.h b/src/mesa/drivers/dri/r600/radeon_common_context.h
new file mode 120000
index 0000000000..4d66312550
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_common_context.h
@@ -0,0 +1 @@
+../radeon/radeon_common_context.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_cs_legacy.c b/src/mesa/drivers/dri/r600/radeon_cs_legacy.c
new file mode 120000
index 0000000000..006720f8a4
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_cs_legacy.c
@@ -0,0 +1 @@
+../radeon/radeon_cs_legacy.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_cs_legacy.h b/src/mesa/drivers/dri/r600/radeon_cs_legacy.h
new file mode 120000
index 0000000000..a5f95e0a3d
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_cs_legacy.h
@@ -0,0 +1 @@
+../radeon/radeon_cs_legacy.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_cs_space_drm.c b/src/mesa/drivers/dri/r600/radeon_cs_space_drm.c
new file mode 120000
index 0000000000..c248ea7d1a
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_cs_space_drm.c
@@ -0,0 +1 @@
+../radeon/radeon_cs_space_drm.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_debug.c b/src/mesa/drivers/dri/r600/radeon_debug.c
new file mode 120000
index 0000000000..c98c2e074c
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_debug.c
@@ -0,0 +1 @@
+../radeon/radeon_debug.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_debug.h b/src/mesa/drivers/dri/r600/radeon_debug.h
new file mode 120000
index 0000000000..bd8aa28e89
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_debug.h
@@ -0,0 +1 @@
+../radeon/radeon_debug.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_dma.c b/src/mesa/drivers/dri/r600/radeon_dma.c
new file mode 120000
index 0000000000..43be000625
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_dma.c
@@ -0,0 +1 @@
+../radeon/radeon_dma.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_dma.h b/src/mesa/drivers/dri/r600/radeon_dma.h
new file mode 120000
index 0000000000..82e50634e3
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_dma.h
@@ -0,0 +1 @@
+../radeon/radeon_dma.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_fbo.c b/src/mesa/drivers/dri/r600/radeon_fbo.c
new file mode 120000
index 0000000000..0d738d8d78
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_fbo.c
@@ -0,0 +1 @@
+../radeon/radeon_fbo.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_lock.c b/src/mesa/drivers/dri/r600/radeon_lock.c
new file mode 120000
index 0000000000..af4108a8e3
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_lock.c
@@ -0,0 +1 @@
+../radeon/radeon_lock.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_lock.h b/src/mesa/drivers/dri/r600/radeon_lock.h
new file mode 120000
index 0000000000..64bdf94ee7
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_lock.h
@@ -0,0 +1 @@
+../radeon/radeon_lock.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_mipmap_tree.c b/src/mesa/drivers/dri/r600/radeon_mipmap_tree.c
new file mode 120000
index 0000000000..31c0cfbe94
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_mipmap_tree.c
@@ -0,0 +1 @@
+../radeon/radeon_mipmap_tree.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_mipmap_tree.h b/src/mesa/drivers/dri/r600/radeon_mipmap_tree.h
new file mode 120000
index 0000000000..254d50cf8c
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_mipmap_tree.h
@@ -0,0 +1 @@
+../radeon/radeon_mipmap_tree.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_queryobj.c b/src/mesa/drivers/dri/r600/radeon_queryobj.c
new file mode 120000
index 0000000000..1d6ebc1c48
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_queryobj.c
@@ -0,0 +1 @@
+../radeon/radeon_queryobj.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_queryobj.h b/src/mesa/drivers/dri/r600/radeon_queryobj.h
new file mode 120000
index 0000000000..8f6f842b0a
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_queryobj.h
@@ -0,0 +1 @@
+../radeon/radeon_queryobj.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_screen.c b/src/mesa/drivers/dri/r600/radeon_screen.c
new file mode 120000
index 0000000000..86161118dd
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_screen.c
@@ -0,0 +1 @@
+../radeon/radeon_screen.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_screen.h b/src/mesa/drivers/dri/r600/radeon_screen.h
new file mode 120000
index 0000000000..23bb6bd459
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_screen.h
@@ -0,0 +1 @@
+../radeon/radeon_screen.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_span.c b/src/mesa/drivers/dri/r600/radeon_span.c
new file mode 120000
index 0000000000..232868c4c9
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_span.c
@@ -0,0 +1 @@
+../radeon/radeon_span.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_span.h b/src/mesa/drivers/dri/r600/radeon_span.h
new file mode 120000
index 0000000000..f9d634508c
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_span.h
@@ -0,0 +1 @@
+../radeon/radeon_span.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_texture.c b/src/mesa/drivers/dri/r600/radeon_texture.c
new file mode 120000
index 0000000000..a822710915
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_texture.c
@@ -0,0 +1 @@
+../radeon/radeon_texture.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/radeon_texture.h b/src/mesa/drivers/dri/r600/radeon_texture.h
new file mode 120000
index 0000000000..17fac3d5ea
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/radeon_texture.h
@@ -0,0 +1 @@
+../radeon/radeon_texture.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/server/radeon.h b/src/mesa/drivers/dri/r600/server/radeon.h
new file mode 120000
index 0000000000..81274a54f1
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/server/radeon.h
@@ -0,0 +1 @@
+../../radeon/server/radeon.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/server/radeon_dri.c b/src/mesa/drivers/dri/r600/server/radeon_dri.c
new file mode 120000
index 0000000000..d05847d650
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/server/radeon_dri.c
@@ -0,0 +1 @@
+../../radeon/server/radeon_dri.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/server/radeon_dri.h b/src/mesa/drivers/dri/r600/server/radeon_dri.h
new file mode 120000
index 0000000000..27c591d3c9
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/server/radeon_dri.h
@@ -0,0 +1 @@
+../../radeon/server/radeon_dri.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/server/radeon_egl.c b/src/mesa/drivers/dri/r600/server/radeon_egl.c
new file mode 120000
index 0000000000..d7735a7643
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/server/radeon_egl.c
@@ -0,0 +1 @@
+../../radeon/server/radeon_egl.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/server/radeon_macros.h b/src/mesa/drivers/dri/r600/server/radeon_macros.h
new file mode 120000
index 0000000000..c56cd735b8
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/server/radeon_macros.h
@@ -0,0 +1 @@
+../../radeon/server/radeon_macros.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/server/radeon_reg.h b/src/mesa/drivers/dri/r600/server/radeon_reg.h
new file mode 120000
index 0000000000..e2349dcb68
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/server/radeon_reg.h
@@ -0,0 +1 @@
+../../radeon/server/radeon_reg.h \ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/sq_micro_reg.h b/src/mesa/drivers/dri/r600/sq_micro_reg.h
new file mode 100644
index 0000000000..bfd21cef62
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/sq_micro_reg.h
@@ -0,0 +1,2008 @@
+/*
+ * Copyright (C) 2008-2009 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Contacts:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#if !defined (_SQ_MICRO_REG_H)
+#define _SQ_MICRO_REG_H
+
+#if defined(LITTLEENDIAN_CPU)
+#elif defined(BIGENDIAN_CPU)
+#else
+#error "BIGENDIAN_CPU or LITTLEENDIAN_CPU must be defined"
+#endif
+
+/*
+ * SQ_ALU_SRC_GPR_BASE value
+ */
+
+#define SQ_ALU_SRC_GPR_BASE 0x00000000
+
+/*
+ * SQ_ALU_SRC_GPR_SIZE value
+ */
+
+#define SQ_ALU_SRC_GPR_SIZE 0x00000080
+
+/*
+ * SQ_ALU_SRC_KCACHE0_BASE value
+ */
+
+#define SQ_ALU_SRC_KCACHE0_BASE 0x00000080
+
+/*
+ * SQ_ALU_SRC_KCACHE0_SIZE value
+ */
+
+#define SQ_ALU_SRC_KCACHE0_SIZE 0x00000020
+
+/*
+ * SQ_ALU_SRC_KCACHE1_BASE value
+ */
+
+#define SQ_ALU_SRC_KCACHE1_BASE 0x000000a0
+
+/*
+ * SQ_ALU_SRC_KCACHE1_SIZE value
+ */
+
+#define SQ_ALU_SRC_KCACHE1_SIZE 0x00000020
+
+/*
+ * SQ_ALU_SRC_CFILE_BASE value
+ */
+
+#define SQ_ALU_SRC_CFILE_BASE 0x00000100
+
+/*
+ * SQ_ALU_SRC_CFILE_SIZE value
+ */
+
+#define SQ_ALU_SRC_CFILE_SIZE 0x00000100
+
+/*
+ * SQ_SP_OP_REDUC_BEGIN value
+ */
+
+#define SQ_SP_OP_REDUC_BEGIN 0x00000050
+
+/*
+ * SQ_SP_OP_REDUC_END value
+ */
+
+#define SQ_SP_OP_REDUC_END 0x00000053
+
+/*
+ * SQ_SP_OP_TRANS_BEGIN value
+ */
+
+#define SQ_SP_OP_TRANS_BEGIN 0x00000060
+
+/*
+ * SQ_SP_OP_TRANS_END value
+ */
+
+#define SQ_SP_OP_TRANS_END 0x0000007f
+
+/*
+ * SQ_CF_WORD0 struct
+ */
+
+#define SQ_CF_WORD0_ADDR_SIZE 32
+
+#define SQ_CF_WORD0_ADDR_SHIFT 0
+
+#define SQ_CF_WORD0_ADDR_MASK 0xffffffff
+
+#define SQ_CF_WORD0_MASK \
+ (SQ_CF_WORD0_ADDR_MASK)
+
+#define SQ_CF_WORD0_DEFAULT 0xcdcdcdcd
+
+#define SQ_CF_WORD0_GET_ADDR(sq_cf_word0) \
+ ((sq_cf_word0 & SQ_CF_WORD0_ADDR_MASK) >> SQ_CF_WORD0_ADDR_SHIFT)
+
+#define SQ_CF_WORD0_SET_ADDR(sq_cf_word0_reg, addr) \
+ sq_cf_word0_reg = (sq_cf_word0_reg & ~SQ_CF_WORD0_ADDR_MASK) | (addr << SQ_CF_WORD0_ADDR_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_cf_word0_t {
+ unsigned int addr : SQ_CF_WORD0_ADDR_SIZE;
+ } sq_cf_word0_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_cf_word0_t {
+ unsigned int addr : SQ_CF_WORD0_ADDR_SIZE;
+ } sq_cf_word0_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_cf_word0_t f;
+} sq_cf_word0_u;
+
+
+/*
+ * SQ_CF_WORD1 struct
+ */
+
+#define SQ_CF_WORD1_POP_COUNT_SIZE 3
+#define SQ_CF_WORD1_CF_CONST_SIZE 5
+#define SQ_CF_WORD1_COND_SIZE 2
+#define SQ_CF_WORD1_COUNT_SIZE 3
+#define SQ_CF_WORD1_CALL_COUNT_SIZE 6
+#define SQ_CF_WORD1_COUNT_3_SIZE 1
+#define SQ_CF_WORD1_END_OF_PROGRAM_SIZE 1
+#define SQ_CF_WORD1_VALID_PIXEL_MODE_SIZE 1
+#define SQ_CF_WORD1_CF_INST_SIZE 7
+#define SQ_CF_WORD1_WHOLE_QUAD_MODE_SIZE 1
+#define SQ_CF_WORD1_BARRIER_SIZE 1
+
+#define SQ_CF_WORD1_POP_COUNT_SHIFT 0
+#define SQ_CF_WORD1_CF_CONST_SHIFT 3
+#define SQ_CF_WORD1_COND_SHIFT 8
+#define SQ_CF_WORD1_COUNT_SHIFT 10
+#define SQ_CF_WORD1_CALL_COUNT_SHIFT 13
+#define SQ_CF_WORD1_COUNT_3_SHIFT 19
+#define SQ_CF_WORD1_END_OF_PROGRAM_SHIFT 21
+#define SQ_CF_WORD1_VALID_PIXEL_MODE_SHIFT 22
+#define SQ_CF_WORD1_CF_INST_SHIFT 23
+#define SQ_CF_WORD1_WHOLE_QUAD_MODE_SHIFT 30
+#define SQ_CF_WORD1_BARRIER_SHIFT 31
+
+#define SQ_CF_WORD1_POP_COUNT_MASK 0x00000007
+#define SQ_CF_WORD1_CF_CONST_MASK 0x000000f8
+#define SQ_CF_WORD1_COND_MASK 0x00000300
+#define SQ_CF_WORD1_COUNT_MASK 0x00001c00
+#define SQ_CF_WORD1_CALL_COUNT_MASK 0x0007e000
+#define SQ_CF_WORD1_COUNT_3_MASK 0x00080000
+#define SQ_CF_WORD1_END_OF_PROGRAM_MASK 0x00200000
+#define SQ_CF_WORD1_VALID_PIXEL_MODE_MASK 0x00400000
+#define SQ_CF_WORD1_CF_INST_MASK 0x3f800000
+#define SQ_CF_WORD1_WHOLE_QUAD_MODE_MASK 0x40000000
+#define SQ_CF_WORD1_BARRIER_MASK 0x80000000
+
+#define SQ_CF_WORD1_MASK \
+ (SQ_CF_WORD1_POP_COUNT_MASK | \
+ SQ_CF_WORD1_CF_CONST_MASK | \
+ SQ_CF_WORD1_COND_MASK | \
+ SQ_CF_WORD1_COUNT_MASK | \
+ SQ_CF_WORD1_CALL_COUNT_MASK | \
+ SQ_CF_WORD1_COUNT_3_MASK | \
+ SQ_CF_WORD1_END_OF_PROGRAM_MASK | \
+ SQ_CF_WORD1_VALID_PIXEL_MODE_MASK | \
+ SQ_CF_WORD1_CF_INST_MASK | \
+ SQ_CF_WORD1_WHOLE_QUAD_MODE_MASK | \
+ SQ_CF_WORD1_BARRIER_MASK)
+
+#define SQ_CF_WORD1_DEFAULT 0xcdcdcdcd
+
+#define SQ_CF_WORD1_GET_POP_COUNT(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_POP_COUNT_MASK) >> SQ_CF_WORD1_POP_COUNT_SHIFT)
+#define SQ_CF_WORD1_GET_CF_CONST(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_CF_CONST_MASK) >> SQ_CF_WORD1_CF_CONST_SHIFT)
+#define SQ_CF_WORD1_GET_COND(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_COND_MASK) >> SQ_CF_WORD1_COND_SHIFT)
+#define SQ_CF_WORD1_GET_COUNT(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_COUNT_MASK) >> SQ_CF_WORD1_COUNT_SHIFT)
+#define SQ_CF_WORD1_GET_CALL_COUNT(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_CALL_COUNT_MASK) >> SQ_CF_WORD1_CALL_COUNT_SHIFT)
+#define SQ_CF_WORD1_GET_COUNT_3(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_COUNT_3_MASK) >> SQ_CF_WORD1_COUNT_3_SHIFT)
+#define SQ_CF_WORD1_GET_END_OF_PROGRAM(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_END_OF_PROGRAM_MASK) >> SQ_CF_WORD1_END_OF_PROGRAM_SHIFT)
+#define SQ_CF_WORD1_GET_VALID_PIXEL_MODE(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_VALID_PIXEL_MODE_MASK) >> SQ_CF_WORD1_VALID_PIXEL_MODE_SHIFT)
+#define SQ_CF_WORD1_GET_CF_INST(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_CF_INST_MASK) >> SQ_CF_WORD1_CF_INST_SHIFT)
+#define SQ_CF_WORD1_GET_WHOLE_QUAD_MODE(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_WHOLE_QUAD_MODE_MASK) >> SQ_CF_WORD1_WHOLE_QUAD_MODE_SHIFT)
+#define SQ_CF_WORD1_GET_BARRIER(sq_cf_word1) \
+ ((sq_cf_word1 & SQ_CF_WORD1_BARRIER_MASK) >> SQ_CF_WORD1_BARRIER_SHIFT)
+
+#define SQ_CF_WORD1_SET_POP_COUNT(sq_cf_word1_reg, pop_count) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_POP_COUNT_MASK) | (pop_count << SQ_CF_WORD1_POP_COUNT_SHIFT)
+#define SQ_CF_WORD1_SET_CF_CONST(sq_cf_word1_reg, cf_const) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_CF_CONST_MASK) | (cf_const << SQ_CF_WORD1_CF_CONST_SHIFT)
+#define SQ_CF_WORD1_SET_COND(sq_cf_word1_reg, cond) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_COND_MASK) | (cond << SQ_CF_WORD1_COND_SHIFT)
+#define SQ_CF_WORD1_SET_COUNT(sq_cf_word1_reg, count) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_COUNT_MASK) | (count << SQ_CF_WORD1_COUNT_SHIFT)
+#define SQ_CF_WORD1_SET_CALL_COUNT(sq_cf_word1_reg, call_count) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_CALL_COUNT_MASK) | (call_count << SQ_CF_WORD1_CALL_COUNT_SHIFT)
+#define SQ_CF_WORD1_SET_COUNT_3(sq_cf_word1_reg, count_3) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_COUNT_3_MASK) | (count_3 << SQ_CF_WORD1_COUNT_3_SHIFT)
+#define SQ_CF_WORD1_SET_END_OF_PROGRAM(sq_cf_word1_reg, end_of_program) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_END_OF_PROGRAM_MASK) | (end_of_program << SQ_CF_WORD1_END_OF_PROGRAM_SHIFT)
+#define SQ_CF_WORD1_SET_VALID_PIXEL_MODE(sq_cf_word1_reg, valid_pixel_mode) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_VALID_PIXEL_MODE_MASK) | (valid_pixel_mode << SQ_CF_WORD1_VALID_PIXEL_MODE_SHIFT)
+#define SQ_CF_WORD1_SET_CF_INST(sq_cf_word1_reg, cf_inst) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_CF_INST_MASK) | (cf_inst << SQ_CF_WORD1_CF_INST_SHIFT)
+#define SQ_CF_WORD1_SET_WHOLE_QUAD_MODE(sq_cf_word1_reg, whole_quad_mode) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_WHOLE_QUAD_MODE_MASK) | (whole_quad_mode << SQ_CF_WORD1_WHOLE_QUAD_MODE_SHIFT)
+#define SQ_CF_WORD1_SET_BARRIER(sq_cf_word1_reg, barrier) \
+ sq_cf_word1_reg = (sq_cf_word1_reg & ~SQ_CF_WORD1_BARRIER_MASK) | (barrier << SQ_CF_WORD1_BARRIER_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_cf_word1_t {
+ unsigned int pop_count : SQ_CF_WORD1_POP_COUNT_SIZE;
+ unsigned int cf_const : SQ_CF_WORD1_CF_CONST_SIZE;
+ unsigned int cond : SQ_CF_WORD1_COND_SIZE;
+ unsigned int count : SQ_CF_WORD1_COUNT_SIZE;
+ unsigned int call_count : SQ_CF_WORD1_CALL_COUNT_SIZE;
+ unsigned int count_3 : SQ_CF_WORD1_COUNT_3_SIZE;
+ unsigned int : 1;
+ unsigned int end_of_program : SQ_CF_WORD1_END_OF_PROGRAM_SIZE;
+ unsigned int valid_pixel_mode : SQ_CF_WORD1_VALID_PIXEL_MODE_SIZE;
+ unsigned int cf_inst : SQ_CF_WORD1_CF_INST_SIZE;
+ unsigned int whole_quad_mode : SQ_CF_WORD1_WHOLE_QUAD_MODE_SIZE;
+ unsigned int barrier : SQ_CF_WORD1_BARRIER_SIZE;
+ } sq_cf_word1_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_cf_word1_t {
+ unsigned int barrier : SQ_CF_WORD1_BARRIER_SIZE;
+ unsigned int whole_quad_mode : SQ_CF_WORD1_WHOLE_QUAD_MODE_SIZE;
+ unsigned int cf_inst : SQ_CF_WORD1_CF_INST_SIZE;
+ unsigned int valid_pixel_mode : SQ_CF_WORD1_VALID_PIXEL_MODE_SIZE;
+ unsigned int end_of_program : SQ_CF_WORD1_END_OF_PROGRAM_SIZE;
+ unsigned int : 1;
+ unsigned int count_3 : SQ_CF_WORD1_COUNT_3_SIZE;
+ unsigned int call_count : SQ_CF_WORD1_CALL_COUNT_SIZE;
+ unsigned int count : SQ_CF_WORD1_COUNT_SIZE;
+ unsigned int cond : SQ_CF_WORD1_COND_SIZE;
+ unsigned int cf_const : SQ_CF_WORD1_CF_CONST_SIZE;
+ unsigned int pop_count : SQ_CF_WORD1_POP_COUNT_SIZE;
+ } sq_cf_word1_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_cf_word1_t f;
+} sq_cf_word1_u;
+
+
+/*
+ * SQ_CF_ALU_WORD0 struct
+ */
+
+#define SQ_CF_ALU_WORD0_ADDR_SIZE 22
+#define SQ_CF_ALU_WORD0_KCACHE_BANK0_SIZE 4
+#define SQ_CF_ALU_WORD0_KCACHE_BANK1_SIZE 4
+#define SQ_CF_ALU_WORD0_KCACHE_MODE0_SIZE 2
+
+#define SQ_CF_ALU_WORD0_ADDR_SHIFT 0
+#define SQ_CF_ALU_WORD0_KCACHE_BANK0_SHIFT 22
+#define SQ_CF_ALU_WORD0_KCACHE_BANK1_SHIFT 26
+#define SQ_CF_ALU_WORD0_KCACHE_MODE0_SHIFT 30
+
+#define SQ_CF_ALU_WORD0_ADDR_MASK 0x003fffff
+#define SQ_CF_ALU_WORD0_KCACHE_BANK0_MASK 0x03c00000
+#define SQ_CF_ALU_WORD0_KCACHE_BANK1_MASK 0x3c000000
+#define SQ_CF_ALU_WORD0_KCACHE_MODE0_MASK 0xc0000000
+
+#define SQ_CF_ALU_WORD0_MASK \
+ (SQ_CF_ALU_WORD0_ADDR_MASK | \
+ SQ_CF_ALU_WORD0_KCACHE_BANK0_MASK | \
+ SQ_CF_ALU_WORD0_KCACHE_BANK1_MASK | \
+ SQ_CF_ALU_WORD0_KCACHE_MODE0_MASK)
+
+#define SQ_CF_ALU_WORD0_DEFAULT 0xcdcdcdcd
+
+#define SQ_CF_ALU_WORD0_GET_ADDR(sq_cf_alu_word0) \
+ ((sq_cf_alu_word0 & SQ_CF_ALU_WORD0_ADDR_MASK) >> SQ_CF_ALU_WORD0_ADDR_SHIFT)
+#define SQ_CF_ALU_WORD0_GET_KCACHE_BANK0(sq_cf_alu_word0) \
+ ((sq_cf_alu_word0 & SQ_CF_ALU_WORD0_KCACHE_BANK0_MASK) >> SQ_CF_ALU_WORD0_KCACHE_BANK0_SHIFT)
+#define SQ_CF_ALU_WORD0_GET_KCACHE_BANK1(sq_cf_alu_word0) \
+ ((sq_cf_alu_word0 & SQ_CF_ALU_WORD0_KCACHE_BANK1_MASK) >> SQ_CF_ALU_WORD0_KCACHE_BANK1_SHIFT)
+#define SQ_CF_ALU_WORD0_GET_KCACHE_MODE0(sq_cf_alu_word0) \
+ ((sq_cf_alu_word0 & SQ_CF_ALU_WORD0_KCACHE_MODE0_MASK) >> SQ_CF_ALU_WORD0_KCACHE_MODE0_SHIFT)
+
+#define SQ_CF_ALU_WORD0_SET_ADDR(sq_cf_alu_word0_reg, addr) \
+ sq_cf_alu_word0_reg = (sq_cf_alu_word0_reg & ~SQ_CF_ALU_WORD0_ADDR_MASK) | (addr << SQ_CF_ALU_WORD0_ADDR_SHIFT)
+#define SQ_CF_ALU_WORD0_SET_KCACHE_BANK0(sq_cf_alu_word0_reg, kcache_bank0) \
+ sq_cf_alu_word0_reg = (sq_cf_alu_word0_reg & ~SQ_CF_ALU_WORD0_KCACHE_BANK0_MASK) | (kcache_bank0 << SQ_CF_ALU_WORD0_KCACHE_BANK0_SHIFT)
+#define SQ_CF_ALU_WORD0_SET_KCACHE_BANK1(sq_cf_alu_word0_reg, kcache_bank1) \
+ sq_cf_alu_word0_reg = (sq_cf_alu_word0_reg & ~SQ_CF_ALU_WORD0_KCACHE_BANK1_MASK) | (kcache_bank1 << SQ_CF_ALU_WORD0_KCACHE_BANK1_SHIFT)
+#define SQ_CF_ALU_WORD0_SET_KCACHE_MODE0(sq_cf_alu_word0_reg, kcache_mode0) \
+ sq_cf_alu_word0_reg = (sq_cf_alu_word0_reg & ~SQ_CF_ALU_WORD0_KCACHE_MODE0_MASK) | (kcache_mode0 << SQ_CF_ALU_WORD0_KCACHE_MODE0_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_cf_alu_word0_t {
+ unsigned int addr : SQ_CF_ALU_WORD0_ADDR_SIZE;
+ unsigned int kcache_bank0 : SQ_CF_ALU_WORD0_KCACHE_BANK0_SIZE;
+ unsigned int kcache_bank1 : SQ_CF_ALU_WORD0_KCACHE_BANK1_SIZE;
+ unsigned int kcache_mode0 : SQ_CF_ALU_WORD0_KCACHE_MODE0_SIZE;
+ } sq_cf_alu_word0_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_cf_alu_word0_t {
+ unsigned int kcache_mode0 : SQ_CF_ALU_WORD0_KCACHE_MODE0_SIZE;
+ unsigned int kcache_bank1 : SQ_CF_ALU_WORD0_KCACHE_BANK1_SIZE;
+ unsigned int kcache_bank0 : SQ_CF_ALU_WORD0_KCACHE_BANK0_SIZE;
+ unsigned int addr : SQ_CF_ALU_WORD0_ADDR_SIZE;
+ } sq_cf_alu_word0_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_cf_alu_word0_t f;
+} sq_cf_alu_word0_u;
+
+
+/*
+ * SQ_CF_ALU_WORD1 struct
+ */
+
+#define SQ_CF_ALU_WORD1_KCACHE_MODE1_SIZE 2
+#define SQ_CF_ALU_WORD1_KCACHE_ADDR0_SIZE 8
+#define SQ_CF_ALU_WORD1_KCACHE_ADDR1_SIZE 8
+#define SQ_CF_ALU_WORD1_COUNT_SIZE 7
+#define SQ_CF_ALU_WORD1_ALT_CONST_SIZE 1
+#define SQ_CF_ALU_WORD1_CF_INST_SIZE 4
+#define SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_SIZE 1
+#define SQ_CF_ALU_WORD1_BARRIER_SIZE 1
+
+#define SQ_CF_ALU_WORD1_KCACHE_MODE1_SHIFT 0
+#define SQ_CF_ALU_WORD1_KCACHE_ADDR0_SHIFT 2
+#define SQ_CF_ALU_WORD1_KCACHE_ADDR1_SHIFT 10
+#define SQ_CF_ALU_WORD1_COUNT_SHIFT 18
+#define SQ_CF_ALU_WORD1_ALT_CONST_SHIFT 25
+#define SQ_CF_ALU_WORD1_CF_INST_SHIFT 26
+#define SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_SHIFT 30
+#define SQ_CF_ALU_WORD1_BARRIER_SHIFT 31
+
+#define SQ_CF_ALU_WORD1_KCACHE_MODE1_MASK 0x00000003
+#define SQ_CF_ALU_WORD1_KCACHE_ADDR0_MASK 0x000003fc
+#define SQ_CF_ALU_WORD1_KCACHE_ADDR1_MASK 0x0003fc00
+#define SQ_CF_ALU_WORD1_COUNT_MASK 0x01fc0000
+#define SQ_CF_ALU_WORD1_ALT_CONST_MASK 0x02000000
+#define SQ_CF_ALU_WORD1_CF_INST_MASK 0x3c000000
+#define SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_MASK 0x40000000
+#define SQ_CF_ALU_WORD1_BARRIER_MASK 0x80000000
+
+#define SQ_CF_ALU_WORD1_MASK \
+ (SQ_CF_ALU_WORD1_KCACHE_MODE1_MASK | \
+ SQ_CF_ALU_WORD1_KCACHE_ADDR0_MASK | \
+ SQ_CF_ALU_WORD1_KCACHE_ADDR1_MASK | \
+ SQ_CF_ALU_WORD1_COUNT_MASK | \
+ SQ_CF_ALU_WORD1_ALT_CONST_MASK | \
+ SQ_CF_ALU_WORD1_CF_INST_MASK | \
+ SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_MASK | \
+ SQ_CF_ALU_WORD1_BARRIER_MASK)
+
+#define SQ_CF_ALU_WORD1_DEFAULT 0xcdcdcdcd
+
+#define SQ_CF_ALU_WORD1_GET_KCACHE_MODE1(sq_cf_alu_word1) \
+ ((sq_cf_alu_word1 & SQ_CF_ALU_WORD1_KCACHE_MODE1_MASK) >> SQ_CF_ALU_WORD1_KCACHE_MODE1_SHIFT)
+#define SQ_CF_ALU_WORD1_GET_KCACHE_ADDR0(sq_cf_alu_word1) \
+ ((sq_cf_alu_word1 & SQ_CF_ALU_WORD1_KCACHE_ADDR0_MASK) >> SQ_CF_ALU_WORD1_KCACHE_ADDR0_SHIFT)
+#define SQ_CF_ALU_WORD1_GET_KCACHE_ADDR1(sq_cf_alu_word1) \
+ ((sq_cf_alu_word1 & SQ_CF_ALU_WORD1_KCACHE_ADDR1_MASK) >> SQ_CF_ALU_WORD1_KCACHE_ADDR1_SHIFT)
+#define SQ_CF_ALU_WORD1_GET_COUNT(sq_cf_alu_word1) \
+ ((sq_cf_alu_word1 & SQ_CF_ALU_WORD1_COUNT_MASK) >> SQ_CF_ALU_WORD1_COUNT_SHIFT)
+#define SQ_CF_ALU_WORD1_GET_ALT_CONST(sq_cf_alu_word1) \
+ ((sq_cf_alu_word1 & SQ_CF_ALU_WORD1_ALT_CONST_MASK) >> SQ_CF_ALU_WORD1_ALT_CONST_SHIFT)
+#define SQ_CF_ALU_WORD1_GET_CF_INST(sq_cf_alu_word1) \
+ ((sq_cf_alu_word1 & SQ_CF_ALU_WORD1_CF_INST_MASK) >> SQ_CF_ALU_WORD1_CF_INST_SHIFT)
+#define SQ_CF_ALU_WORD1_GET_WHOLE_QUAD_MODE(sq_cf_alu_word1) \
+ ((sq_cf_alu_word1 & SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_MASK) >> SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_SHIFT)
+#define SQ_CF_ALU_WORD1_GET_BARRIER(sq_cf_alu_word1) \
+ ((sq_cf_alu_word1 & SQ_CF_ALU_WORD1_BARRIER_MASK) >> SQ_CF_ALU_WORD1_BARRIER_SHIFT)
+
+#define SQ_CF_ALU_WORD1_SET_KCACHE_MODE1(sq_cf_alu_word1_reg, kcache_mode1) \
+ sq_cf_alu_word1_reg = (sq_cf_alu_word1_reg & ~SQ_CF_ALU_WORD1_KCACHE_MODE1_MASK) | (kcache_mode1 << SQ_CF_ALU_WORD1_KCACHE_MODE1_SHIFT)
+#define SQ_CF_ALU_WORD1_SET_KCACHE_ADDR0(sq_cf_alu_word1_reg, kcache_addr0) \
+ sq_cf_alu_word1_reg = (sq_cf_alu_word1_reg & ~SQ_CF_ALU_WORD1_KCACHE_ADDR0_MASK) | (kcache_addr0 << SQ_CF_ALU_WORD1_KCACHE_ADDR0_SHIFT)
+#define SQ_CF_ALU_WORD1_SET_KCACHE_ADDR1(sq_cf_alu_word1_reg, kcache_addr1) \
+ sq_cf_alu_word1_reg = (sq_cf_alu_word1_reg & ~SQ_CF_ALU_WORD1_KCACHE_ADDR1_MASK) | (kcache_addr1 << SQ_CF_ALU_WORD1_KCACHE_ADDR1_SHIFT)
+#define SQ_CF_ALU_WORD1_SET_COUNT(sq_cf_alu_word1_reg, count) \
+ sq_cf_alu_word1_reg = (sq_cf_alu_word1_reg & ~SQ_CF_ALU_WORD1_COUNT_MASK) | (count << SQ_CF_ALU_WORD1_COUNT_SHIFT)
+#define SQ_CF_ALU_WORD1_SET_ALT_CONST(sq_cf_alu_word1_reg, alt_const) \
+ sq_cf_alu_word1_reg = (sq_cf_alu_word1_reg & ~SQ_CF_ALU_WORD1_ALT_CONST_MASK) | (alt_const << SQ_CF_ALU_WORD1_ALT_CONST_SHIFT)
+#define SQ_CF_ALU_WORD1_SET_CF_INST(sq_cf_alu_word1_reg, cf_inst) \
+ sq_cf_alu_word1_reg = (sq_cf_alu_word1_reg & ~SQ_CF_ALU_WORD1_CF_INST_MASK) | (cf_inst << SQ_CF_ALU_WORD1_CF_INST_SHIFT)
+#define SQ_CF_ALU_WORD1_SET_WHOLE_QUAD_MODE(sq_cf_alu_word1_reg, whole_quad_mode) \
+ sq_cf_alu_word1_reg = (sq_cf_alu_word1_reg & ~SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_MASK) | (whole_quad_mode << SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_SHIFT)
+#define SQ_CF_ALU_WORD1_SET_BARRIER(sq_cf_alu_word1_reg, barrier) \
+ sq_cf_alu_word1_reg = (sq_cf_alu_word1_reg & ~SQ_CF_ALU_WORD1_BARRIER_MASK) | (barrier << SQ_CF_ALU_WORD1_BARRIER_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_cf_alu_word1_t {
+ unsigned int kcache_mode1 : SQ_CF_ALU_WORD1_KCACHE_MODE1_SIZE;
+ unsigned int kcache_addr0 : SQ_CF_ALU_WORD1_KCACHE_ADDR0_SIZE;
+ unsigned int kcache_addr1 : SQ_CF_ALU_WORD1_KCACHE_ADDR1_SIZE;
+ unsigned int count : SQ_CF_ALU_WORD1_COUNT_SIZE;
+ unsigned int alt_const : SQ_CF_ALU_WORD1_ALT_CONST_SIZE;
+ unsigned int cf_inst : SQ_CF_ALU_WORD1_CF_INST_SIZE;
+ unsigned int whole_quad_mode : SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_SIZE;
+ unsigned int barrier : SQ_CF_ALU_WORD1_BARRIER_SIZE;
+ } sq_cf_alu_word1_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_cf_alu_word1_t {
+ unsigned int barrier : SQ_CF_ALU_WORD1_BARRIER_SIZE;
+ unsigned int whole_quad_mode : SQ_CF_ALU_WORD1_WHOLE_QUAD_MODE_SIZE;
+ unsigned int cf_inst : SQ_CF_ALU_WORD1_CF_INST_SIZE;
+ unsigned int alt_const : SQ_CF_ALU_WORD1_ALT_CONST_SIZE;
+ unsigned int count : SQ_CF_ALU_WORD1_COUNT_SIZE;
+ unsigned int kcache_addr1 : SQ_CF_ALU_WORD1_KCACHE_ADDR1_SIZE;
+ unsigned int kcache_addr0 : SQ_CF_ALU_WORD1_KCACHE_ADDR0_SIZE;
+ unsigned int kcache_mode1 : SQ_CF_ALU_WORD1_KCACHE_MODE1_SIZE;
+ } sq_cf_alu_word1_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_cf_alu_word1_t f;
+} sq_cf_alu_word1_u;
+
+
+/*
+ * SQ_CF_ALLOC_EXPORT_WORD0 struct
+ */
+
+#define SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_SIZE 13
+#define SQ_CF_ALLOC_EXPORT_WORD0_TYPE_SIZE 2
+#define SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_SIZE 7
+#define SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_SIZE 1
+#define SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_SIZE 7
+#define SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_SIZE 2
+
+#define SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_SHIFT 0
+#define SQ_CF_ALLOC_EXPORT_WORD0_TYPE_SHIFT 13
+#define SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_SHIFT 15
+#define SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_SHIFT 22
+#define SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_SHIFT 23
+#define SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_SHIFT 30
+
+#define SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_MASK 0x00001fff
+#define SQ_CF_ALLOC_EXPORT_WORD0_TYPE_MASK 0x00006000
+#define SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_MASK 0x003f8000
+#define SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_MASK 0x00400000
+#define SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_MASK 0x3f800000
+#define SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_MASK 0xc0000000
+
+#define SQ_CF_ALLOC_EXPORT_WORD0_MASK \
+ (SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD0_TYPE_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_MASK)
+
+#define SQ_CF_ALLOC_EXPORT_WORD0_DEFAULT 0xcdcdcdcd
+
+#define SQ_CF_ALLOC_EXPORT_WORD0_GET_ARRAY_BASE(sq_cf_alloc_export_word0) \
+ ((sq_cf_alloc_export_word0 & SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_MASK) >> SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_GET_TYPE(sq_cf_alloc_export_word0) \
+ ((sq_cf_alloc_export_word0 & SQ_CF_ALLOC_EXPORT_WORD0_TYPE_MASK) >> SQ_CF_ALLOC_EXPORT_WORD0_TYPE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_GET_RW_GPR(sq_cf_alloc_export_word0) \
+ ((sq_cf_alloc_export_word0 & SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_MASK) >> SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_GET_RW_REL(sq_cf_alloc_export_word0) \
+ ((sq_cf_alloc_export_word0 & SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_MASK) >> SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_GET_INDEX_GPR(sq_cf_alloc_export_word0) \
+ ((sq_cf_alloc_export_word0 & SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_MASK) >> SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_GET_ELEM_SIZE(sq_cf_alloc_export_word0) \
+ ((sq_cf_alloc_export_word0 & SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_MASK) >> SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_SHIFT)
+
+#define SQ_CF_ALLOC_EXPORT_WORD0_SET_ARRAY_BASE(sq_cf_alloc_export_word0_reg, array_base) \
+ sq_cf_alloc_export_word0_reg = (sq_cf_alloc_export_word0_reg & ~SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_MASK) | (array_base << SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_SET_TYPE(sq_cf_alloc_export_word0_reg, type) \
+ sq_cf_alloc_export_word0_reg = (sq_cf_alloc_export_word0_reg & ~SQ_CF_ALLOC_EXPORT_WORD0_TYPE_MASK) | (type << SQ_CF_ALLOC_EXPORT_WORD0_TYPE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_SET_RW_GPR(sq_cf_alloc_export_word0_reg, rw_gpr) \
+ sq_cf_alloc_export_word0_reg = (sq_cf_alloc_export_word0_reg & ~SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_MASK) | (rw_gpr << SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_SET_RW_REL(sq_cf_alloc_export_word0_reg, rw_rel) \
+ sq_cf_alloc_export_word0_reg = (sq_cf_alloc_export_word0_reg & ~SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_MASK) | (rw_rel << SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_SET_INDEX_GPR(sq_cf_alloc_export_word0_reg, index_gpr) \
+ sq_cf_alloc_export_word0_reg = (sq_cf_alloc_export_word0_reg & ~SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_MASK) | (index_gpr << SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD0_SET_ELEM_SIZE(sq_cf_alloc_export_word0_reg, elem_size) \
+ sq_cf_alloc_export_word0_reg = (sq_cf_alloc_export_word0_reg & ~SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_MASK) | (elem_size << SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_cf_alloc_export_word0_t {
+ unsigned int array_base : SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_SIZE;
+ unsigned int type : SQ_CF_ALLOC_EXPORT_WORD0_TYPE_SIZE;
+ unsigned int rw_gpr : SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_SIZE;
+ unsigned int rw_rel : SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_SIZE;
+ unsigned int index_gpr : SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_SIZE;
+ unsigned int elem_size : SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_SIZE;
+ } sq_cf_alloc_export_word0_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_cf_alloc_export_word0_t {
+ unsigned int elem_size : SQ_CF_ALLOC_EXPORT_WORD0_ELEM_SIZE_SIZE;
+ unsigned int index_gpr : SQ_CF_ALLOC_EXPORT_WORD0_INDEX_GPR_SIZE;
+ unsigned int rw_rel : SQ_CF_ALLOC_EXPORT_WORD0_RW_REL_SIZE;
+ unsigned int rw_gpr : SQ_CF_ALLOC_EXPORT_WORD0_RW_GPR_SIZE;
+ unsigned int type : SQ_CF_ALLOC_EXPORT_WORD0_TYPE_SIZE;
+ unsigned int array_base : SQ_CF_ALLOC_EXPORT_WORD0_ARRAY_BASE_SIZE;
+ } sq_cf_alloc_export_word0_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_cf_alloc_export_word0_t f;
+} sq_cf_alloc_export_word0_u;
+
+
+/*
+ * SQ_CF_ALLOC_EXPORT_WORD1 struct
+ */
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_SIZE 4
+#define SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_SIZE 1
+#define SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_SIZE 1
+#define SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_SIZE 7
+#define SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_SIZE 1
+#define SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_SIZE 1
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_SHIFT 17
+#define SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_SHIFT 21
+#define SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_SHIFT 22
+#define SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_SHIFT 23
+#define SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_SHIFT 30
+#define SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_SHIFT 31
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_MASK 0x001e0000
+#define SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_MASK 0x00200000
+#define SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_MASK 0x00400000
+#define SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_MASK 0x3f800000
+#define SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_MASK 0x40000000
+#define SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_MASK 0x80000000
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_MASK \
+ (SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_MASK)
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_DEFAULT 0xcdcc0000
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_GET_BURST_COUNT(sq_cf_alloc_export_word1) \
+ ((sq_cf_alloc_export_word1 & SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_GET_END_OF_PROGRAM(sq_cf_alloc_export_word1) \
+ ((sq_cf_alloc_export_word1 & SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_GET_VALID_PIXEL_MODE(sq_cf_alloc_export_word1) \
+ ((sq_cf_alloc_export_word1 & SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_GET_CF_INST(sq_cf_alloc_export_word1) \
+ ((sq_cf_alloc_export_word1 & SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_GET_WHOLE_QUAD_MODE(sq_cf_alloc_export_word1) \
+ ((sq_cf_alloc_export_word1 & SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_GET_BARRIER(sq_cf_alloc_export_word1) \
+ ((sq_cf_alloc_export_word1 & SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_SHIFT)
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_SET_BURST_COUNT(sq_cf_alloc_export_word1_reg, burst_count) \
+ sq_cf_alloc_export_word1_reg = (sq_cf_alloc_export_word1_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_MASK) | (burst_count << SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SET_END_OF_PROGRAM(sq_cf_alloc_export_word1_reg, end_of_program) \
+ sq_cf_alloc_export_word1_reg = (sq_cf_alloc_export_word1_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_MASK) | (end_of_program << SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SET_VALID_PIXEL_MODE(sq_cf_alloc_export_word1_reg, valid_pixel_mode) \
+ sq_cf_alloc_export_word1_reg = (sq_cf_alloc_export_word1_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_MASK) | (valid_pixel_mode << SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SET_CF_INST(sq_cf_alloc_export_word1_reg, cf_inst) \
+ sq_cf_alloc_export_word1_reg = (sq_cf_alloc_export_word1_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_MASK) | (cf_inst << SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SET_WHOLE_QUAD_MODE(sq_cf_alloc_export_word1_reg, whole_quad_mode) \
+ sq_cf_alloc_export_word1_reg = (sq_cf_alloc_export_word1_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_MASK) | (whole_quad_mode << SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SET_BARRIER(sq_cf_alloc_export_word1_reg, barrier) \
+ sq_cf_alloc_export_word1_reg = (sq_cf_alloc_export_word1_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_MASK) | (barrier << SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_cf_alloc_export_word1_t {
+ unsigned int : 17;
+ unsigned int burst_count : SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_SIZE;
+ unsigned int end_of_program : SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_SIZE;
+ unsigned int valid_pixel_mode : SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_SIZE;
+ unsigned int cf_inst : SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_SIZE;
+ unsigned int whole_quad_mode : SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_SIZE;
+ unsigned int barrier : SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_SIZE;
+ } sq_cf_alloc_export_word1_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_cf_alloc_export_word1_t {
+ unsigned int barrier : SQ_CF_ALLOC_EXPORT_WORD1_BARRIER_SIZE;
+ unsigned int whole_quad_mode : SQ_CF_ALLOC_EXPORT_WORD1_WHOLE_QUAD_MODE_SIZE;
+ unsigned int cf_inst : SQ_CF_ALLOC_EXPORT_WORD1_CF_INST_SIZE;
+ unsigned int valid_pixel_mode : SQ_CF_ALLOC_EXPORT_WORD1_VALID_PIXEL_MODE_SIZE;
+ unsigned int end_of_program : SQ_CF_ALLOC_EXPORT_WORD1_END_OF_PROGRAM_SIZE;
+ unsigned int burst_count : SQ_CF_ALLOC_EXPORT_WORD1_BURST_COUNT_SIZE;
+ unsigned int : 17;
+ } sq_cf_alloc_export_word1_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_cf_alloc_export_word1_t f;
+} sq_cf_alloc_export_word1_u;
+
+
+/*
+ * SQ_CF_ALLOC_EXPORT_WORD1_BUF struct
+ */
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_SIZE 12
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_SIZE 4
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_SHIFT 0
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_SHIFT 12
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_MASK 0x00000fff
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_MASK 0x0000f000
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_MASK \
+ (SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_MASK)
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_DEFAULT 0x0000cdcd
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_GET_ARRAY_SIZE(sq_cf_alloc_export_word1_buf) \
+ ((sq_cf_alloc_export_word1_buf & SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_GET_COMP_MASK(sq_cf_alloc_export_word1_buf) \
+ ((sq_cf_alloc_export_word1_buf & SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_SHIFT)
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_SET_ARRAY_SIZE(sq_cf_alloc_export_word1_buf_reg, array_size) \
+ sq_cf_alloc_export_word1_buf_reg = (sq_cf_alloc_export_word1_buf_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_MASK) | (array_size << SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_BUF_SET_COMP_MASK(sq_cf_alloc_export_word1_buf_reg, comp_mask) \
+ sq_cf_alloc_export_word1_buf_reg = (sq_cf_alloc_export_word1_buf_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_MASK) | (comp_mask << SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_cf_alloc_export_word1_buf_t {
+ unsigned int array_size : SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_SIZE;
+ unsigned int comp_mask : SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_SIZE;
+ unsigned int : 16;
+ } sq_cf_alloc_export_word1_buf_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_cf_alloc_export_word1_buf_t {
+ unsigned int : 16;
+ unsigned int comp_mask : SQ_CF_ALLOC_EXPORT_WORD1_BUF_COMP_MASK_SIZE;
+ unsigned int array_size : SQ_CF_ALLOC_EXPORT_WORD1_BUF_ARRAY_SIZE_SIZE;
+ } sq_cf_alloc_export_word1_buf_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_cf_alloc_export_word1_buf_t f;
+} sq_cf_alloc_export_word1_buf_u;
+
+
+/*
+ * SQ_CF_ALLOC_EXPORT_WORD1_SWIZ struct
+ */
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_SIZE 3
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_SIZE 3
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_SIZE 3
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_SIZE 3
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_SHIFT 0
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_SHIFT 3
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_SHIFT 6
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_SHIFT 9
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_MASK 0x00000007
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_MASK 0x00000038
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_MASK 0x000001c0
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_MASK 0x00000e00
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_MASK \
+ (SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_MASK | \
+ SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_MASK)
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_DEFAULT 0x00000dcd
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_GET_SEL_X(sq_cf_alloc_export_word1_swiz) \
+ ((sq_cf_alloc_export_word1_swiz & SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_GET_SEL_Y(sq_cf_alloc_export_word1_swiz) \
+ ((sq_cf_alloc_export_word1_swiz & SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_GET_SEL_Z(sq_cf_alloc_export_word1_swiz) \
+ ((sq_cf_alloc_export_word1_swiz & SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_GET_SEL_W(sq_cf_alloc_export_word1_swiz) \
+ ((sq_cf_alloc_export_word1_swiz & SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_MASK) >> SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_SHIFT)
+
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SET_SEL_X(sq_cf_alloc_export_word1_swiz_reg, sel_x) \
+ sq_cf_alloc_export_word1_swiz_reg = (sq_cf_alloc_export_word1_swiz_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_MASK) | (sel_x << SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SET_SEL_Y(sq_cf_alloc_export_word1_swiz_reg, sel_y) \
+ sq_cf_alloc_export_word1_swiz_reg = (sq_cf_alloc_export_word1_swiz_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_MASK) | (sel_y << SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SET_SEL_Z(sq_cf_alloc_export_word1_swiz_reg, sel_z) \
+ sq_cf_alloc_export_word1_swiz_reg = (sq_cf_alloc_export_word1_swiz_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_MASK) | (sel_z << SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_SHIFT)
+#define SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SET_SEL_W(sq_cf_alloc_export_word1_swiz_reg, sel_w) \
+ sq_cf_alloc_export_word1_swiz_reg = (sq_cf_alloc_export_word1_swiz_reg & ~SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_MASK) | (sel_w << SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_cf_alloc_export_word1_swiz_t {
+ unsigned int sel_x : SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_SIZE;
+ unsigned int sel_y : SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_SIZE;
+ unsigned int sel_z : SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_SIZE;
+ unsigned int sel_w : SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_SIZE;
+ unsigned int : 20;
+ } sq_cf_alloc_export_word1_swiz_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_cf_alloc_export_word1_swiz_t {
+ unsigned int : 20;
+ unsigned int sel_w : SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_W_SIZE;
+ unsigned int sel_z : SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Z_SIZE;
+ unsigned int sel_y : SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_Y_SIZE;
+ unsigned int sel_x : SQ_CF_ALLOC_EXPORT_WORD1_SWIZ_SEL_X_SIZE;
+ } sq_cf_alloc_export_word1_swiz_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_cf_alloc_export_word1_swiz_t f;
+} sq_cf_alloc_export_word1_swiz_u;
+
+
+/*
+ * SQ_ALU_WORD0 struct
+ */
+
+#define SQ_ALU_WORD0_SRC0_SEL_SIZE 9
+#define SQ_ALU_WORD0_SRC0_REL_SIZE 1
+#define SQ_ALU_WORD0_SRC0_CHAN_SIZE 2
+#define SQ_ALU_WORD0_SRC0_NEG_SIZE 1
+#define SQ_ALU_WORD0_SRC1_SEL_SIZE 9
+#define SQ_ALU_WORD0_SRC1_REL_SIZE 1
+#define SQ_ALU_WORD0_SRC1_CHAN_SIZE 2
+#define SQ_ALU_WORD0_SRC1_NEG_SIZE 1
+#define SQ_ALU_WORD0_INDEX_MODE_SIZE 3
+#define SQ_ALU_WORD0_PRED_SEL_SIZE 2
+#define SQ_ALU_WORD0_LAST_SIZE 1
+
+#define SQ_ALU_WORD0_SRC0_SEL_SHIFT 0
+#define SQ_ALU_WORD0_SRC0_REL_SHIFT 9
+#define SQ_ALU_WORD0_SRC0_CHAN_SHIFT 10
+#define SQ_ALU_WORD0_SRC0_NEG_SHIFT 12
+#define SQ_ALU_WORD0_SRC1_SEL_SHIFT 13
+#define SQ_ALU_WORD0_SRC1_REL_SHIFT 22
+#define SQ_ALU_WORD0_SRC1_CHAN_SHIFT 23
+#define SQ_ALU_WORD0_SRC1_NEG_SHIFT 25
+#define SQ_ALU_WORD0_INDEX_MODE_SHIFT 26
+#define SQ_ALU_WORD0_PRED_SEL_SHIFT 29
+#define SQ_ALU_WORD0_LAST_SHIFT 31
+
+#define SQ_ALU_WORD0_SRC0_SEL_MASK 0x000001ff
+#define SQ_ALU_WORD0_SRC0_REL_MASK 0x00000200
+#define SQ_ALU_WORD0_SRC0_CHAN_MASK 0x00000c00
+#define SQ_ALU_WORD0_SRC0_NEG_MASK 0x00001000
+#define SQ_ALU_WORD0_SRC1_SEL_MASK 0x003fe000
+#define SQ_ALU_WORD0_SRC1_REL_MASK 0x00400000
+#define SQ_ALU_WORD0_SRC1_CHAN_MASK 0x01800000
+#define SQ_ALU_WORD0_SRC1_NEG_MASK 0x02000000
+#define SQ_ALU_WORD0_INDEX_MODE_MASK 0x1c000000
+#define SQ_ALU_WORD0_PRED_SEL_MASK 0x60000000
+#define SQ_ALU_WORD0_LAST_MASK 0x80000000
+
+#define SQ_ALU_WORD0_MASK \
+ (SQ_ALU_WORD0_SRC0_SEL_MASK | \
+ SQ_ALU_WORD0_SRC0_REL_MASK | \
+ SQ_ALU_WORD0_SRC0_CHAN_MASK | \
+ SQ_ALU_WORD0_SRC0_NEG_MASK | \
+ SQ_ALU_WORD0_SRC1_SEL_MASK | \
+ SQ_ALU_WORD0_SRC1_REL_MASK | \
+ SQ_ALU_WORD0_SRC1_CHAN_MASK | \
+ SQ_ALU_WORD0_SRC1_NEG_MASK | \
+ SQ_ALU_WORD0_INDEX_MODE_MASK | \
+ SQ_ALU_WORD0_PRED_SEL_MASK | \
+ SQ_ALU_WORD0_LAST_MASK)
+
+#define SQ_ALU_WORD0_DEFAULT 0xcdcdcdcd
+
+#define SQ_ALU_WORD0_GET_SRC0_SEL(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_SRC0_SEL_MASK) >> SQ_ALU_WORD0_SRC0_SEL_SHIFT)
+#define SQ_ALU_WORD0_GET_SRC0_REL(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_SRC0_REL_MASK) >> SQ_ALU_WORD0_SRC0_REL_SHIFT)
+#define SQ_ALU_WORD0_GET_SRC0_CHAN(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_SRC0_CHAN_MASK) >> SQ_ALU_WORD0_SRC0_CHAN_SHIFT)
+#define SQ_ALU_WORD0_GET_SRC0_NEG(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_SRC0_NEG_MASK) >> SQ_ALU_WORD0_SRC0_NEG_SHIFT)
+#define SQ_ALU_WORD0_GET_SRC1_SEL(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_SRC1_SEL_MASK) >> SQ_ALU_WORD0_SRC1_SEL_SHIFT)
+#define SQ_ALU_WORD0_GET_SRC1_REL(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_SRC1_REL_MASK) >> SQ_ALU_WORD0_SRC1_REL_SHIFT)
+#define SQ_ALU_WORD0_GET_SRC1_CHAN(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_SRC1_CHAN_MASK) >> SQ_ALU_WORD0_SRC1_CHAN_SHIFT)
+#define SQ_ALU_WORD0_GET_SRC1_NEG(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_SRC1_NEG_MASK) >> SQ_ALU_WORD0_SRC1_NEG_SHIFT)
+#define SQ_ALU_WORD0_GET_INDEX_MODE(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_INDEX_MODE_MASK) >> SQ_ALU_WORD0_INDEX_MODE_SHIFT)
+#define SQ_ALU_WORD0_GET_PRED_SEL(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_PRED_SEL_MASK) >> SQ_ALU_WORD0_PRED_SEL_SHIFT)
+#define SQ_ALU_WORD0_GET_LAST(sq_alu_word0) \
+ ((sq_alu_word0 & SQ_ALU_WORD0_LAST_MASK) >> SQ_ALU_WORD0_LAST_SHIFT)
+
+#define SQ_ALU_WORD0_SET_SRC0_SEL(sq_alu_word0_reg, src0_sel) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_SRC0_SEL_MASK) | (src0_sel << SQ_ALU_WORD0_SRC0_SEL_SHIFT)
+#define SQ_ALU_WORD0_SET_SRC0_REL(sq_alu_word0_reg, src0_rel) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_SRC0_REL_MASK) | (src0_rel << SQ_ALU_WORD0_SRC0_REL_SHIFT)
+#define SQ_ALU_WORD0_SET_SRC0_CHAN(sq_alu_word0_reg, src0_chan) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_SRC0_CHAN_MASK) | (src0_chan << SQ_ALU_WORD0_SRC0_CHAN_SHIFT)
+#define SQ_ALU_WORD0_SET_SRC0_NEG(sq_alu_word0_reg, src0_neg) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_SRC0_NEG_MASK) | (src0_neg << SQ_ALU_WORD0_SRC0_NEG_SHIFT)
+#define SQ_ALU_WORD0_SET_SRC1_SEL(sq_alu_word0_reg, src1_sel) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_SRC1_SEL_MASK) | (src1_sel << SQ_ALU_WORD0_SRC1_SEL_SHIFT)
+#define SQ_ALU_WORD0_SET_SRC1_REL(sq_alu_word0_reg, src1_rel) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_SRC1_REL_MASK) | (src1_rel << SQ_ALU_WORD0_SRC1_REL_SHIFT)
+#define SQ_ALU_WORD0_SET_SRC1_CHAN(sq_alu_word0_reg, src1_chan) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_SRC1_CHAN_MASK) | (src1_chan << SQ_ALU_WORD0_SRC1_CHAN_SHIFT)
+#define SQ_ALU_WORD0_SET_SRC1_NEG(sq_alu_word0_reg, src1_neg) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_SRC1_NEG_MASK) | (src1_neg << SQ_ALU_WORD0_SRC1_NEG_SHIFT)
+#define SQ_ALU_WORD0_SET_INDEX_MODE(sq_alu_word0_reg, index_mode) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_INDEX_MODE_MASK) | (index_mode << SQ_ALU_WORD0_INDEX_MODE_SHIFT)
+#define SQ_ALU_WORD0_SET_PRED_SEL(sq_alu_word0_reg, pred_sel) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_PRED_SEL_MASK) | (pred_sel << SQ_ALU_WORD0_PRED_SEL_SHIFT)
+#define SQ_ALU_WORD0_SET_LAST(sq_alu_word0_reg, last) \
+ sq_alu_word0_reg = (sq_alu_word0_reg & ~SQ_ALU_WORD0_LAST_MASK) | (last << SQ_ALU_WORD0_LAST_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_alu_word0_t {
+ unsigned int src0_sel : SQ_ALU_WORD0_SRC0_SEL_SIZE;
+ unsigned int src0_rel : SQ_ALU_WORD0_SRC0_REL_SIZE;
+ unsigned int src0_chan : SQ_ALU_WORD0_SRC0_CHAN_SIZE;
+ unsigned int src0_neg : SQ_ALU_WORD0_SRC0_NEG_SIZE;
+ unsigned int src1_sel : SQ_ALU_WORD0_SRC1_SEL_SIZE;
+ unsigned int src1_rel : SQ_ALU_WORD0_SRC1_REL_SIZE;
+ unsigned int src1_chan : SQ_ALU_WORD0_SRC1_CHAN_SIZE;
+ unsigned int src1_neg : SQ_ALU_WORD0_SRC1_NEG_SIZE;
+ unsigned int index_mode : SQ_ALU_WORD0_INDEX_MODE_SIZE;
+ unsigned int pred_sel : SQ_ALU_WORD0_PRED_SEL_SIZE;
+ unsigned int last : SQ_ALU_WORD0_LAST_SIZE;
+ } sq_alu_word0_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_alu_word0_t {
+ unsigned int last : SQ_ALU_WORD0_LAST_SIZE;
+ unsigned int pred_sel : SQ_ALU_WORD0_PRED_SEL_SIZE;
+ unsigned int index_mode : SQ_ALU_WORD0_INDEX_MODE_SIZE;
+ unsigned int src1_neg : SQ_ALU_WORD0_SRC1_NEG_SIZE;
+ unsigned int src1_chan : SQ_ALU_WORD0_SRC1_CHAN_SIZE;
+ unsigned int src1_rel : SQ_ALU_WORD0_SRC1_REL_SIZE;
+ unsigned int src1_sel : SQ_ALU_WORD0_SRC1_SEL_SIZE;
+ unsigned int src0_neg : SQ_ALU_WORD0_SRC0_NEG_SIZE;
+ unsigned int src0_chan : SQ_ALU_WORD0_SRC0_CHAN_SIZE;
+ unsigned int src0_rel : SQ_ALU_WORD0_SRC0_REL_SIZE;
+ unsigned int src0_sel : SQ_ALU_WORD0_SRC0_SEL_SIZE;
+ } sq_alu_word0_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_alu_word0_t f;
+} sq_alu_word0_u;
+
+
+/*
+ * SQ_ALU_WORD1 struct
+ */
+
+#define SQ_ALU_WORD1_ENCODING_SIZE 3
+#define SQ_ALU_WORD1_BANK_SWIZZLE_SIZE 3
+#define SQ_ALU_WORD1_DST_GPR_SIZE 7
+#define SQ_ALU_WORD1_DST_REL_SIZE 1
+#define SQ_ALU_WORD1_DST_CHAN_SIZE 2
+#define SQ_ALU_WORD1_CLAMP_SIZE 1
+
+#define SQ_ALU_WORD1_ENCODING_SHIFT 15
+#define SQ_ALU_WORD1_BANK_SWIZZLE_SHIFT 18
+#define SQ_ALU_WORD1_DST_GPR_SHIFT 21
+#define SQ_ALU_WORD1_DST_REL_SHIFT 28
+#define SQ_ALU_WORD1_DST_CHAN_SHIFT 29
+#define SQ_ALU_WORD1_CLAMP_SHIFT 31
+
+#define SQ_ALU_WORD1_ENCODING_MASK 0x00038000
+#define SQ_ALU_WORD1_BANK_SWIZZLE_MASK 0x001c0000
+#define SQ_ALU_WORD1_DST_GPR_MASK 0x0fe00000
+#define SQ_ALU_WORD1_DST_REL_MASK 0x10000000
+#define SQ_ALU_WORD1_DST_CHAN_MASK 0x60000000
+#define SQ_ALU_WORD1_CLAMP_MASK 0x80000000
+
+#define SQ_ALU_WORD1_MASK \
+ (SQ_ALU_WORD1_ENCODING_MASK | \
+ SQ_ALU_WORD1_BANK_SWIZZLE_MASK | \
+ SQ_ALU_WORD1_DST_GPR_MASK | \
+ SQ_ALU_WORD1_DST_REL_MASK | \
+ SQ_ALU_WORD1_DST_CHAN_MASK | \
+ SQ_ALU_WORD1_CLAMP_MASK)
+
+#define SQ_ALU_WORD1_DEFAULT 0xcdcd8000
+
+#define SQ_ALU_WORD1_GET_ENCODING(sq_alu_word1) \
+ ((sq_alu_word1 & SQ_ALU_WORD1_ENCODING_MASK) >> SQ_ALU_WORD1_ENCODING_SHIFT)
+#define SQ_ALU_WORD1_GET_BANK_SWIZZLE(sq_alu_word1) \
+ ((sq_alu_word1 & SQ_ALU_WORD1_BANK_SWIZZLE_MASK) >> SQ_ALU_WORD1_BANK_SWIZZLE_SHIFT)
+#define SQ_ALU_WORD1_GET_DST_GPR(sq_alu_word1) \
+ ((sq_alu_word1 & SQ_ALU_WORD1_DST_GPR_MASK) >> SQ_ALU_WORD1_DST_GPR_SHIFT)
+#define SQ_ALU_WORD1_GET_DST_REL(sq_alu_word1) \
+ ((sq_alu_word1 & SQ_ALU_WORD1_DST_REL_MASK) >> SQ_ALU_WORD1_DST_REL_SHIFT)
+#define SQ_ALU_WORD1_GET_DST_CHAN(sq_alu_word1) \
+ ((sq_alu_word1 & SQ_ALU_WORD1_DST_CHAN_MASK) >> SQ_ALU_WORD1_DST_CHAN_SHIFT)
+#define SQ_ALU_WORD1_GET_CLAMP(sq_alu_word1) \
+ ((sq_alu_word1 & SQ_ALU_WORD1_CLAMP_MASK) >> SQ_ALU_WORD1_CLAMP_SHIFT)
+
+#define SQ_ALU_WORD1_SET_ENCODING(sq_alu_word1_reg, encoding) \
+ sq_alu_word1_reg = (sq_alu_word1_reg & ~SQ_ALU_WORD1_ENCODING_MASK) | (encoding << SQ_ALU_WORD1_ENCODING_SHIFT)
+#define SQ_ALU_WORD1_SET_BANK_SWIZZLE(sq_alu_word1_reg, bank_swizzle) \
+ sq_alu_word1_reg = (sq_alu_word1_reg & ~SQ_ALU_WORD1_BANK_SWIZZLE_MASK) | (bank_swizzle << SQ_ALU_WORD1_BANK_SWIZZLE_SHIFT)
+#define SQ_ALU_WORD1_SET_DST_GPR(sq_alu_word1_reg, dst_gpr) \
+ sq_alu_word1_reg = (sq_alu_word1_reg & ~SQ_ALU_WORD1_DST_GPR_MASK) | (dst_gpr << SQ_ALU_WORD1_DST_GPR_SHIFT)
+#define SQ_ALU_WORD1_SET_DST_REL(sq_alu_word1_reg, dst_rel) \
+ sq_alu_word1_reg = (sq_alu_word1_reg & ~SQ_ALU_WORD1_DST_REL_MASK) | (dst_rel << SQ_ALU_WORD1_DST_REL_SHIFT)
+#define SQ_ALU_WORD1_SET_DST_CHAN(sq_alu_word1_reg, dst_chan) \
+ sq_alu_word1_reg = (sq_alu_word1_reg & ~SQ_ALU_WORD1_DST_CHAN_MASK) | (dst_chan << SQ_ALU_WORD1_DST_CHAN_SHIFT)
+#define SQ_ALU_WORD1_SET_CLAMP(sq_alu_word1_reg, clamp) \
+ sq_alu_word1_reg = (sq_alu_word1_reg & ~SQ_ALU_WORD1_CLAMP_MASK) | (clamp << SQ_ALU_WORD1_CLAMP_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_alu_word1_t {
+ unsigned int : 15;
+ unsigned int encoding : SQ_ALU_WORD1_ENCODING_SIZE;
+ unsigned int bank_swizzle : SQ_ALU_WORD1_BANK_SWIZZLE_SIZE;
+ unsigned int dst_gpr : SQ_ALU_WORD1_DST_GPR_SIZE;
+ unsigned int dst_rel : SQ_ALU_WORD1_DST_REL_SIZE;
+ unsigned int dst_chan : SQ_ALU_WORD1_DST_CHAN_SIZE;
+ unsigned int clamp : SQ_ALU_WORD1_CLAMP_SIZE;
+ } sq_alu_word1_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_alu_word1_t {
+ unsigned int clamp : SQ_ALU_WORD1_CLAMP_SIZE;
+ unsigned int dst_chan : SQ_ALU_WORD1_DST_CHAN_SIZE;
+ unsigned int dst_rel : SQ_ALU_WORD1_DST_REL_SIZE;
+ unsigned int dst_gpr : SQ_ALU_WORD1_DST_GPR_SIZE;
+ unsigned int bank_swizzle : SQ_ALU_WORD1_BANK_SWIZZLE_SIZE;
+ unsigned int encoding : SQ_ALU_WORD1_ENCODING_SIZE;
+ unsigned int : 15;
+ } sq_alu_word1_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_alu_word1_t f;
+} sq_alu_word1_u;
+
+
+/*
+ * SQ_ALU_WORD1_OP2_V2 struct
+ */
+
+#define SQ_ALU_WORD1_OP2_V2_SRC0_ABS_SIZE 1
+#define SQ_ALU_WORD1_OP2_V2_SRC1_ABS_SIZE 1
+#define SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_SIZE 1
+#define SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_SIZE 1
+#define SQ_ALU_WORD1_OP2_V2_WRITE_MASK_SIZE 1
+#define SQ_ALU_WORD1_OP2_V2_OMOD_SIZE 2
+#define SQ_ALU_WORD1_OP2_V2_ALU_INST_SIZE 11
+
+#define SQ_ALU_WORD1_OP2_V2_SRC0_ABS_SHIFT 0
+#define SQ_ALU_WORD1_OP2_V2_SRC1_ABS_SHIFT 1
+#define SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_SHIFT 2
+#define SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_SHIFT 3
+#define SQ_ALU_WORD1_OP2_V2_WRITE_MASK_SHIFT 4
+#define SQ_ALU_WORD1_OP2_V2_OMOD_SHIFT 5
+#define SQ_ALU_WORD1_OP2_V2_ALU_INST_SHIFT 7
+
+#define SQ_ALU_WORD1_OP2_V2_SRC0_ABS_MASK 0x00000001
+#define SQ_ALU_WORD1_OP2_V2_SRC1_ABS_MASK 0x00000002
+#define SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_MASK 0x00000004
+#define SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_MASK 0x00000008
+#define SQ_ALU_WORD1_OP2_V2_WRITE_MASK_MASK 0x00000010
+#define SQ_ALU_WORD1_OP2_V2_OMOD_MASK 0x00000060
+#define SQ_ALU_WORD1_OP2_V2_ALU_INST_MASK 0x0003ff80
+
+#define SQ_ALU_WORD1_OP2_V2_MASK \
+ (SQ_ALU_WORD1_OP2_V2_SRC0_ABS_MASK | \
+ SQ_ALU_WORD1_OP2_V2_SRC1_ABS_MASK | \
+ SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_MASK | \
+ SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_MASK | \
+ SQ_ALU_WORD1_OP2_V2_WRITE_MASK_MASK | \
+ SQ_ALU_WORD1_OP2_V2_OMOD_MASK | \
+ SQ_ALU_WORD1_OP2_V2_ALU_INST_MASK)
+
+#define SQ_ALU_WORD1_OP2_V2_DEFAULT 0x0001cdcd
+
+#define SQ_ALU_WORD1_OP2_V2_GET_SRC0_ABS(sq_alu_word1_op2_v2) \
+ ((sq_alu_word1_op2_v2 & SQ_ALU_WORD1_OP2_V2_SRC0_ABS_MASK) >> SQ_ALU_WORD1_OP2_V2_SRC0_ABS_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_GET_SRC1_ABS(sq_alu_word1_op2_v2) \
+ ((sq_alu_word1_op2_v2 & SQ_ALU_WORD1_OP2_V2_SRC1_ABS_MASK) >> SQ_ALU_WORD1_OP2_V2_SRC1_ABS_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_GET_UPDATE_EXECUTE_MASK(sq_alu_word1_op2_v2) \
+ ((sq_alu_word1_op2_v2 & SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_MASK) >> SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_GET_UPDATE_PRED(sq_alu_word1_op2_v2) \
+ ((sq_alu_word1_op2_v2 & SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_MASK) >> SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_GET_WRITE_MASK(sq_alu_word1_op2_v2) \
+ ((sq_alu_word1_op2_v2 & SQ_ALU_WORD1_OP2_V2_WRITE_MASK_MASK) >> SQ_ALU_WORD1_OP2_V2_WRITE_MASK_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_GET_OMOD(sq_alu_word1_op2_v2) \
+ ((sq_alu_word1_op2_v2 & SQ_ALU_WORD1_OP2_V2_OMOD_MASK) >> SQ_ALU_WORD1_OP2_V2_OMOD_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_GET_ALU_INST(sq_alu_word1_op2_v2) \
+ ((sq_alu_word1_op2_v2 & SQ_ALU_WORD1_OP2_V2_ALU_INST_MASK) >> SQ_ALU_WORD1_OP2_V2_ALU_INST_SHIFT)
+
+#define SQ_ALU_WORD1_OP2_V2_SET_SRC0_ABS(sq_alu_word1_op2_v2_reg, src0_abs) \
+ sq_alu_word1_op2_v2_reg = (sq_alu_word1_op2_v2_reg & ~SQ_ALU_WORD1_OP2_V2_SRC0_ABS_MASK) | (src0_abs << SQ_ALU_WORD1_OP2_V2_SRC0_ABS_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_SET_SRC1_ABS(sq_alu_word1_op2_v2_reg, src1_abs) \
+ sq_alu_word1_op2_v2_reg = (sq_alu_word1_op2_v2_reg & ~SQ_ALU_WORD1_OP2_V2_SRC1_ABS_MASK) | (src1_abs << SQ_ALU_WORD1_OP2_V2_SRC1_ABS_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_SET_UPDATE_EXECUTE_MASK(sq_alu_word1_op2_v2_reg, update_execute_mask) \
+ sq_alu_word1_op2_v2_reg = (sq_alu_word1_op2_v2_reg & ~SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_MASK) | (update_execute_mask << SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_SET_UPDATE_PRED(sq_alu_word1_op2_v2_reg, update_pred) \
+ sq_alu_word1_op2_v2_reg = (sq_alu_word1_op2_v2_reg & ~SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_MASK) | (update_pred << SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_SET_WRITE_MASK(sq_alu_word1_op2_v2_reg, write_mask) \
+ sq_alu_word1_op2_v2_reg = (sq_alu_word1_op2_v2_reg & ~SQ_ALU_WORD1_OP2_V2_WRITE_MASK_MASK) | (write_mask << SQ_ALU_WORD1_OP2_V2_WRITE_MASK_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_SET_OMOD(sq_alu_word1_op2_v2_reg, omod) \
+ sq_alu_word1_op2_v2_reg = (sq_alu_word1_op2_v2_reg & ~SQ_ALU_WORD1_OP2_V2_OMOD_MASK) | (omod << SQ_ALU_WORD1_OP2_V2_OMOD_SHIFT)
+#define SQ_ALU_WORD1_OP2_V2_SET_ALU_INST(sq_alu_word1_op2_v2_reg, alu_inst) \
+ sq_alu_word1_op2_v2_reg = (sq_alu_word1_op2_v2_reg & ~SQ_ALU_WORD1_OP2_V2_ALU_INST_MASK) | (alu_inst << SQ_ALU_WORD1_OP2_V2_ALU_INST_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_alu_word1_op2_v2_t {
+ unsigned int src0_abs : SQ_ALU_WORD1_OP2_V2_SRC0_ABS_SIZE;
+ unsigned int src1_abs : SQ_ALU_WORD1_OP2_V2_SRC1_ABS_SIZE;
+ unsigned int update_execute_mask : SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_SIZE;
+ unsigned int update_pred : SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_SIZE;
+ unsigned int write_mask : SQ_ALU_WORD1_OP2_V2_WRITE_MASK_SIZE;
+ unsigned int omod : SQ_ALU_WORD1_OP2_V2_OMOD_SIZE;
+ unsigned int alu_inst : SQ_ALU_WORD1_OP2_V2_ALU_INST_SIZE;
+ unsigned int : 14;
+ } sq_alu_word1_op2_v2_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_alu_word1_op2_v2_t {
+ unsigned int : 14;
+ unsigned int alu_inst : SQ_ALU_WORD1_OP2_V2_ALU_INST_SIZE;
+ unsigned int omod : SQ_ALU_WORD1_OP2_V2_OMOD_SIZE;
+ unsigned int write_mask : SQ_ALU_WORD1_OP2_V2_WRITE_MASK_SIZE;
+ unsigned int update_pred : SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_SIZE;
+ unsigned int update_execute_mask : SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_SIZE;
+ unsigned int src1_abs : SQ_ALU_WORD1_OP2_V2_SRC1_ABS_SIZE;
+ unsigned int src0_abs : SQ_ALU_WORD1_OP2_V2_SRC0_ABS_SIZE;
+ } sq_alu_word1_op2_v2_t;
+
+#endif
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_alu_word1_op2_r6xx_t {
+ unsigned int src0_abs : SQ_ALU_WORD1_OP2_V2_SRC0_ABS_SIZE;
+ unsigned int src1_abs : SQ_ALU_WORD1_OP2_V2_SRC1_ABS_SIZE;
+ unsigned int update_execute_mask : SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_SIZE;
+ unsigned int update_pred : SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_SIZE;
+ unsigned int write_mask : SQ_ALU_WORD1_OP2_V2_WRITE_MASK_SIZE;
+ unsigned int fog_export : 1;
+ unsigned int omod : SQ_ALU_WORD1_OP2_V2_OMOD_SIZE;
+ unsigned int alu_inst : 10;
+ unsigned int : 14;
+ } sq_alu_word1_op2_v1_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_alu_word1_op2_r6xx_t {
+ unsigned int : 14;
+ unsigned int alu_inst : 10;
+ unsigned int omod : SQ_ALU_WORD1_OP2_V2_OMOD_SIZE;
+ unsigned int fog_export : 1;
+ unsigned int write_mask : SQ_ALU_WORD1_OP2_V2_WRITE_MASK_SIZE;
+ unsigned int update_pred : SQ_ALU_WORD1_OP2_V2_UPDATE_PRED_SIZE;
+ unsigned int update_execute_mask : SQ_ALU_WORD1_OP2_V2_UPDATE_EXECUTE_MASK_SIZE;
+ unsigned int src1_abs : SQ_ALU_WORD1_OP2_V2_SRC1_ABS_SIZE;
+ unsigned int src0_abs : SQ_ALU_WORD1_OP2_V2_SRC0_ABS_SIZE;
+ } sq_alu_word1_op2_v1_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_alu_word1_op2_v2_t f;
+ sq_alu_word1_op2_v1_t f6;
+} sq_alu_word1_op2_v2_u;
+
+
+/*
+ * SQ_ALU_WORD1_OP3 struct
+ */
+
+#define SQ_ALU_WORD1_OP3_SRC2_SEL_SIZE 9
+#define SQ_ALU_WORD1_OP3_SRC2_REL_SIZE 1
+#define SQ_ALU_WORD1_OP3_SRC2_CHAN_SIZE 2
+#define SQ_ALU_WORD1_OP3_SRC2_NEG_SIZE 1
+#define SQ_ALU_WORD1_OP3_ALU_INST_SIZE 5
+
+#define SQ_ALU_WORD1_OP3_SRC2_SEL_SHIFT 0
+#define SQ_ALU_WORD1_OP3_SRC2_REL_SHIFT 9
+#define SQ_ALU_WORD1_OP3_SRC2_CHAN_SHIFT 10
+#define SQ_ALU_WORD1_OP3_SRC2_NEG_SHIFT 12
+#define SQ_ALU_WORD1_OP3_ALU_INST_SHIFT 13
+
+#define SQ_ALU_WORD1_OP3_SRC2_SEL_MASK 0x000001ff
+#define SQ_ALU_WORD1_OP3_SRC2_REL_MASK 0x00000200
+#define SQ_ALU_WORD1_OP3_SRC2_CHAN_MASK 0x00000c00
+#define SQ_ALU_WORD1_OP3_SRC2_NEG_MASK 0x00001000
+#define SQ_ALU_WORD1_OP3_ALU_INST_MASK 0x0003e000
+
+#define SQ_ALU_WORD1_OP3_MASK \
+ (SQ_ALU_WORD1_OP3_SRC2_SEL_MASK | \
+ SQ_ALU_WORD1_OP3_SRC2_REL_MASK | \
+ SQ_ALU_WORD1_OP3_SRC2_CHAN_MASK | \
+ SQ_ALU_WORD1_OP3_SRC2_NEG_MASK | \
+ SQ_ALU_WORD1_OP3_ALU_INST_MASK)
+
+#define SQ_ALU_WORD1_OP3_DEFAULT 0x0001cdcd
+
+#define SQ_ALU_WORD1_OP3_GET_SRC2_SEL(sq_alu_word1_op3) \
+ ((sq_alu_word1_op3 & SQ_ALU_WORD1_OP3_SRC2_SEL_MASK) >> SQ_ALU_WORD1_OP3_SRC2_SEL_SHIFT)
+#define SQ_ALU_WORD1_OP3_GET_SRC2_REL(sq_alu_word1_op3) \
+ ((sq_alu_word1_op3 & SQ_ALU_WORD1_OP3_SRC2_REL_MASK) >> SQ_ALU_WORD1_OP3_SRC2_REL_SHIFT)
+#define SQ_ALU_WORD1_OP3_GET_SRC2_CHAN(sq_alu_word1_op3) \
+ ((sq_alu_word1_op3 & SQ_ALU_WORD1_OP3_SRC2_CHAN_MASK) >> SQ_ALU_WORD1_OP3_SRC2_CHAN_SHIFT)
+#define SQ_ALU_WORD1_OP3_GET_SRC2_NEG(sq_alu_word1_op3) \
+ ((sq_alu_word1_op3 & SQ_ALU_WORD1_OP3_SRC2_NEG_MASK) >> SQ_ALU_WORD1_OP3_SRC2_NEG_SHIFT)
+#define SQ_ALU_WORD1_OP3_GET_ALU_INST(sq_alu_word1_op3) \
+ ((sq_alu_word1_op3 & SQ_ALU_WORD1_OP3_ALU_INST_MASK) >> SQ_ALU_WORD1_OP3_ALU_INST_SHIFT)
+
+#define SQ_ALU_WORD1_OP3_SET_SRC2_SEL(sq_alu_word1_op3_reg, src2_sel) \
+ sq_alu_word1_op3_reg = (sq_alu_word1_op3_reg & ~SQ_ALU_WORD1_OP3_SRC2_SEL_MASK) | (src2_sel << SQ_ALU_WORD1_OP3_SRC2_SEL_SHIFT)
+#define SQ_ALU_WORD1_OP3_SET_SRC2_REL(sq_alu_word1_op3_reg, src2_rel) \
+ sq_alu_word1_op3_reg = (sq_alu_word1_op3_reg & ~SQ_ALU_WORD1_OP3_SRC2_REL_MASK) | (src2_rel << SQ_ALU_WORD1_OP3_SRC2_REL_SHIFT)
+#define SQ_ALU_WORD1_OP3_SET_SRC2_CHAN(sq_alu_word1_op3_reg, src2_chan) \
+ sq_alu_word1_op3_reg = (sq_alu_word1_op3_reg & ~SQ_ALU_WORD1_OP3_SRC2_CHAN_MASK) | (src2_chan << SQ_ALU_WORD1_OP3_SRC2_CHAN_SHIFT)
+#define SQ_ALU_WORD1_OP3_SET_SRC2_NEG(sq_alu_word1_op3_reg, src2_neg) \
+ sq_alu_word1_op3_reg = (sq_alu_word1_op3_reg & ~SQ_ALU_WORD1_OP3_SRC2_NEG_MASK) | (src2_neg << SQ_ALU_WORD1_OP3_SRC2_NEG_SHIFT)
+#define SQ_ALU_WORD1_OP3_SET_ALU_INST(sq_alu_word1_op3_reg, alu_inst) \
+ sq_alu_word1_op3_reg = (sq_alu_word1_op3_reg & ~SQ_ALU_WORD1_OP3_ALU_INST_MASK) | (alu_inst << SQ_ALU_WORD1_OP3_ALU_INST_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_alu_word1_op3_t {
+ unsigned int src2_sel : SQ_ALU_WORD1_OP3_SRC2_SEL_SIZE;
+ unsigned int src2_rel : SQ_ALU_WORD1_OP3_SRC2_REL_SIZE;
+ unsigned int src2_chan : SQ_ALU_WORD1_OP3_SRC2_CHAN_SIZE;
+ unsigned int src2_neg : SQ_ALU_WORD1_OP3_SRC2_NEG_SIZE;
+ unsigned int alu_inst : SQ_ALU_WORD1_OP3_ALU_INST_SIZE;
+ unsigned int : 14;
+ } sq_alu_word1_op3_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_alu_word1_op3_t {
+ unsigned int : 14;
+ unsigned int alu_inst : SQ_ALU_WORD1_OP3_ALU_INST_SIZE;
+ unsigned int src2_neg : SQ_ALU_WORD1_OP3_SRC2_NEG_SIZE;
+ unsigned int src2_chan : SQ_ALU_WORD1_OP3_SRC2_CHAN_SIZE;
+ unsigned int src2_rel : SQ_ALU_WORD1_OP3_SRC2_REL_SIZE;
+ unsigned int src2_sel : SQ_ALU_WORD1_OP3_SRC2_SEL_SIZE;
+ } sq_alu_word1_op3_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_alu_word1_op3_t f;
+} sq_alu_word1_op3_u;
+
+
+/*
+ * SQ_TEX_WORD0 struct
+ */
+
+#define SQ_TEX_WORD0_TEX_INST_SIZE 5
+#define SQ_TEX_WORD0_BC_FRAC_MODE_SIZE 1
+#define SQ_TEX_WORD0_FETCH_WHOLE_QUAD_SIZE 1
+#define SQ_TEX_WORD0_RESOURCE_ID_SIZE 8
+#define SQ_TEX_WORD0_SRC_GPR_SIZE 7
+#define SQ_TEX_WORD0_SRC_REL_SIZE 1
+#define SQ_TEX_WORD0_ALT_CONST_SIZE 1
+
+#define SQ_TEX_WORD0_TEX_INST_SHIFT 0
+#define SQ_TEX_WORD0_BC_FRAC_MODE_SHIFT 5
+#define SQ_TEX_WORD0_FETCH_WHOLE_QUAD_SHIFT 7
+#define SQ_TEX_WORD0_RESOURCE_ID_SHIFT 8
+#define SQ_TEX_WORD0_SRC_GPR_SHIFT 16
+#define SQ_TEX_WORD0_SRC_REL_SHIFT 23
+#define SQ_TEX_WORD0_ALT_CONST_SHIFT 24
+
+#define SQ_TEX_WORD0_TEX_INST_MASK 0x0000001f
+#define SQ_TEX_WORD0_BC_FRAC_MODE_MASK 0x00000020
+#define SQ_TEX_WORD0_FETCH_WHOLE_QUAD_MASK 0x00000080
+#define SQ_TEX_WORD0_RESOURCE_ID_MASK 0x0000ff00
+#define SQ_TEX_WORD0_SRC_GPR_MASK 0x007f0000
+#define SQ_TEX_WORD0_SRC_REL_MASK 0x00800000
+#define SQ_TEX_WORD0_ALT_CONST_MASK 0x01000000
+
+#define SQ_TEX_WORD0_MASK \
+ (SQ_TEX_WORD0_TEX_INST_MASK | \
+ SQ_TEX_WORD0_BC_FRAC_MODE_MASK | \
+ SQ_TEX_WORD0_FETCH_WHOLE_QUAD_MASK | \
+ SQ_TEX_WORD0_RESOURCE_ID_MASK | \
+ SQ_TEX_WORD0_SRC_GPR_MASK | \
+ SQ_TEX_WORD0_SRC_REL_MASK | \
+ SQ_TEX_WORD0_ALT_CONST_MASK)
+
+#define SQ_TEX_WORD0_DEFAULT 0x01cdcd8d
+
+#define SQ_TEX_WORD0_GET_TEX_INST(sq_tex_word0) \
+ ((sq_tex_word0 & SQ_TEX_WORD0_TEX_INST_MASK) >> SQ_TEX_WORD0_TEX_INST_SHIFT)
+#define SQ_TEX_WORD0_GET_BC_FRAC_MODE(sq_tex_word0) \
+ ((sq_tex_word0 & SQ_TEX_WORD0_BC_FRAC_MODE_MASK) >> SQ_TEX_WORD0_BC_FRAC_MODE_SHIFT)
+#define SQ_TEX_WORD0_GET_FETCH_WHOLE_QUAD(sq_tex_word0) \
+ ((sq_tex_word0 & SQ_TEX_WORD0_FETCH_WHOLE_QUAD_MASK) >> SQ_TEX_WORD0_FETCH_WHOLE_QUAD_SHIFT)
+#define SQ_TEX_WORD0_GET_RESOURCE_ID(sq_tex_word0) \
+ ((sq_tex_word0 & SQ_TEX_WORD0_RESOURCE_ID_MASK) >> SQ_TEX_WORD0_RESOURCE_ID_SHIFT)
+#define SQ_TEX_WORD0_GET_SRC_GPR(sq_tex_word0) \
+ ((sq_tex_word0 & SQ_TEX_WORD0_SRC_GPR_MASK) >> SQ_TEX_WORD0_SRC_GPR_SHIFT)
+#define SQ_TEX_WORD0_GET_SRC_REL(sq_tex_word0) \
+ ((sq_tex_word0 & SQ_TEX_WORD0_SRC_REL_MASK) >> SQ_TEX_WORD0_SRC_REL_SHIFT)
+#define SQ_TEX_WORD0_GET_ALT_CONST(sq_tex_word0) \
+ ((sq_tex_word0 & SQ_TEX_WORD0_ALT_CONST_MASK) >> SQ_TEX_WORD0_ALT_CONST_SHIFT)
+
+#define SQ_TEX_WORD0_SET_TEX_INST(sq_tex_word0_reg, tex_inst) \
+ sq_tex_word0_reg = (sq_tex_word0_reg & ~SQ_TEX_WORD0_TEX_INST_MASK) | (tex_inst << SQ_TEX_WORD0_TEX_INST_SHIFT)
+#define SQ_TEX_WORD0_SET_BC_FRAC_MODE(sq_tex_word0_reg, bc_frac_mode) \
+ sq_tex_word0_reg = (sq_tex_word0_reg & ~SQ_TEX_WORD0_BC_FRAC_MODE_MASK) | (bc_frac_mode << SQ_TEX_WORD0_BC_FRAC_MODE_SHIFT)
+#define SQ_TEX_WORD0_SET_FETCH_WHOLE_QUAD(sq_tex_word0_reg, fetch_whole_quad) \
+ sq_tex_word0_reg = (sq_tex_word0_reg & ~SQ_TEX_WORD0_FETCH_WHOLE_QUAD_MASK) | (fetch_whole_quad << SQ_TEX_WORD0_FETCH_WHOLE_QUAD_SHIFT)
+#define SQ_TEX_WORD0_SET_RESOURCE_ID(sq_tex_word0_reg, resource_id) \
+ sq_tex_word0_reg = (sq_tex_word0_reg & ~SQ_TEX_WORD0_RESOURCE_ID_MASK) | (resource_id << SQ_TEX_WORD0_RESOURCE_ID_SHIFT)
+#define SQ_TEX_WORD0_SET_SRC_GPR(sq_tex_word0_reg, src_gpr) \
+ sq_tex_word0_reg = (sq_tex_word0_reg & ~SQ_TEX_WORD0_SRC_GPR_MASK) | (src_gpr << SQ_TEX_WORD0_SRC_GPR_SHIFT)
+#define SQ_TEX_WORD0_SET_SRC_REL(sq_tex_word0_reg, src_rel) \
+ sq_tex_word0_reg = (sq_tex_word0_reg & ~SQ_TEX_WORD0_SRC_REL_MASK) | (src_rel << SQ_TEX_WORD0_SRC_REL_SHIFT)
+#define SQ_TEX_WORD0_SET_ALT_CONST(sq_tex_word0_reg, alt_const) \
+ sq_tex_word0_reg = (sq_tex_word0_reg & ~SQ_TEX_WORD0_ALT_CONST_MASK) | (alt_const << SQ_TEX_WORD0_ALT_CONST_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_tex_word0_t {
+ unsigned int tex_inst : SQ_TEX_WORD0_TEX_INST_SIZE;
+ unsigned int bc_frac_mode : SQ_TEX_WORD0_BC_FRAC_MODE_SIZE;
+ unsigned int : 1;
+ unsigned int fetch_whole_quad : SQ_TEX_WORD0_FETCH_WHOLE_QUAD_SIZE;
+ unsigned int resource_id : SQ_TEX_WORD0_RESOURCE_ID_SIZE;
+ unsigned int src_gpr : SQ_TEX_WORD0_SRC_GPR_SIZE;
+ unsigned int src_rel : SQ_TEX_WORD0_SRC_REL_SIZE;
+ unsigned int alt_const : SQ_TEX_WORD0_ALT_CONST_SIZE;
+ unsigned int : 7;
+ } sq_tex_word0_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_tex_word0_t {
+ unsigned int : 7;
+ unsigned int alt_const : SQ_TEX_WORD0_ALT_CONST_SIZE;
+ unsigned int src_rel : SQ_TEX_WORD0_SRC_REL_SIZE;
+ unsigned int src_gpr : SQ_TEX_WORD0_SRC_GPR_SIZE;
+ unsigned int resource_id : SQ_TEX_WORD0_RESOURCE_ID_SIZE;
+ unsigned int fetch_whole_quad : SQ_TEX_WORD0_FETCH_WHOLE_QUAD_SIZE;
+ unsigned int : 1;
+ unsigned int bc_frac_mode : SQ_TEX_WORD0_BC_FRAC_MODE_SIZE;
+ unsigned int tex_inst : SQ_TEX_WORD0_TEX_INST_SIZE;
+ } sq_tex_word0_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_tex_word0_t f;
+} sq_tex_word0_u;
+
+
+/*
+ * SQ_TEX_WORD1 struct
+ */
+
+#define SQ_TEX_WORD1_DST_GPR_SIZE 7
+#define SQ_TEX_WORD1_DST_REL_SIZE 1
+#define SQ_TEX_WORD1_DST_SEL_X_SIZE 3
+#define SQ_TEX_WORD1_DST_SEL_Y_SIZE 3
+#define SQ_TEX_WORD1_DST_SEL_Z_SIZE 3
+#define SQ_TEX_WORD1_DST_SEL_W_SIZE 3
+#define SQ_TEX_WORD1_LOD_BIAS_SIZE 7
+#define SQ_TEX_WORD1_COORD_TYPE_X_SIZE 1
+#define SQ_TEX_WORD1_COORD_TYPE_Y_SIZE 1
+#define SQ_TEX_WORD1_COORD_TYPE_Z_SIZE 1
+#define SQ_TEX_WORD1_COORD_TYPE_W_SIZE 1
+
+#define SQ_TEX_WORD1_DST_GPR_SHIFT 0
+#define SQ_TEX_WORD1_DST_REL_SHIFT 7
+#define SQ_TEX_WORD1_DST_SEL_X_SHIFT 9
+#define SQ_TEX_WORD1_DST_SEL_Y_SHIFT 12
+#define SQ_TEX_WORD1_DST_SEL_Z_SHIFT 15
+#define SQ_TEX_WORD1_DST_SEL_W_SHIFT 18
+#define SQ_TEX_WORD1_LOD_BIAS_SHIFT 21
+#define SQ_TEX_WORD1_COORD_TYPE_X_SHIFT 28
+#define SQ_TEX_WORD1_COORD_TYPE_Y_SHIFT 29
+#define SQ_TEX_WORD1_COORD_TYPE_Z_SHIFT 30
+#define SQ_TEX_WORD1_COORD_TYPE_W_SHIFT 31
+
+#define SQ_TEX_WORD1_DST_GPR_MASK 0x0000007f
+#define SQ_TEX_WORD1_DST_REL_MASK 0x00000080
+#define SQ_TEX_WORD1_DST_SEL_X_MASK 0x00000e00
+#define SQ_TEX_WORD1_DST_SEL_Y_MASK 0x00007000
+#define SQ_TEX_WORD1_DST_SEL_Z_MASK 0x00038000
+#define SQ_TEX_WORD1_DST_SEL_W_MASK 0x001c0000
+#define SQ_TEX_WORD1_LOD_BIAS_MASK 0x0fe00000
+#define SQ_TEX_WORD1_COORD_TYPE_X_MASK 0x10000000
+#define SQ_TEX_WORD1_COORD_TYPE_Y_MASK 0x20000000
+#define SQ_TEX_WORD1_COORD_TYPE_Z_MASK 0x40000000
+#define SQ_TEX_WORD1_COORD_TYPE_W_MASK 0x80000000
+
+#define SQ_TEX_WORD1_MASK \
+ (SQ_TEX_WORD1_DST_GPR_MASK | \
+ SQ_TEX_WORD1_DST_REL_MASK | \
+ SQ_TEX_WORD1_DST_SEL_X_MASK | \
+ SQ_TEX_WORD1_DST_SEL_Y_MASK | \
+ SQ_TEX_WORD1_DST_SEL_Z_MASK | \
+ SQ_TEX_WORD1_DST_SEL_W_MASK | \
+ SQ_TEX_WORD1_LOD_BIAS_MASK | \
+ SQ_TEX_WORD1_COORD_TYPE_X_MASK | \
+ SQ_TEX_WORD1_COORD_TYPE_Y_MASK | \
+ SQ_TEX_WORD1_COORD_TYPE_Z_MASK | \
+ SQ_TEX_WORD1_COORD_TYPE_W_MASK)
+
+#define SQ_TEX_WORD1_DEFAULT 0xcdcdcccd
+
+#define SQ_TEX_WORD1_GET_DST_GPR(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_DST_GPR_MASK) >> SQ_TEX_WORD1_DST_GPR_SHIFT)
+#define SQ_TEX_WORD1_GET_DST_REL(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_DST_REL_MASK) >> SQ_TEX_WORD1_DST_REL_SHIFT)
+#define SQ_TEX_WORD1_GET_DST_SEL_X(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_DST_SEL_X_MASK) >> SQ_TEX_WORD1_DST_SEL_X_SHIFT)
+#define SQ_TEX_WORD1_GET_DST_SEL_Y(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_DST_SEL_Y_MASK) >> SQ_TEX_WORD1_DST_SEL_Y_SHIFT)
+#define SQ_TEX_WORD1_GET_DST_SEL_Z(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_DST_SEL_Z_MASK) >> SQ_TEX_WORD1_DST_SEL_Z_SHIFT)
+#define SQ_TEX_WORD1_GET_DST_SEL_W(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_DST_SEL_W_MASK) >> SQ_TEX_WORD1_DST_SEL_W_SHIFT)
+#define SQ_TEX_WORD1_GET_LOD_BIAS(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_LOD_BIAS_MASK) >> SQ_TEX_WORD1_LOD_BIAS_SHIFT)
+#define SQ_TEX_WORD1_GET_COORD_TYPE_X(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_COORD_TYPE_X_MASK) >> SQ_TEX_WORD1_COORD_TYPE_X_SHIFT)
+#define SQ_TEX_WORD1_GET_COORD_TYPE_Y(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_COORD_TYPE_Y_MASK) >> SQ_TEX_WORD1_COORD_TYPE_Y_SHIFT)
+#define SQ_TEX_WORD1_GET_COORD_TYPE_Z(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_COORD_TYPE_Z_MASK) >> SQ_TEX_WORD1_COORD_TYPE_Z_SHIFT)
+#define SQ_TEX_WORD1_GET_COORD_TYPE_W(sq_tex_word1) \
+ ((sq_tex_word1 & SQ_TEX_WORD1_COORD_TYPE_W_MASK) >> SQ_TEX_WORD1_COORD_TYPE_W_SHIFT)
+
+#define SQ_TEX_WORD1_SET_DST_GPR(sq_tex_word1_reg, dst_gpr) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_DST_GPR_MASK) | (dst_gpr << SQ_TEX_WORD1_DST_GPR_SHIFT)
+#define SQ_TEX_WORD1_SET_DST_REL(sq_tex_word1_reg, dst_rel) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_DST_REL_MASK) | (dst_rel << SQ_TEX_WORD1_DST_REL_SHIFT)
+#define SQ_TEX_WORD1_SET_DST_SEL_X(sq_tex_word1_reg, dst_sel_x) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_DST_SEL_X_MASK) | (dst_sel_x << SQ_TEX_WORD1_DST_SEL_X_SHIFT)
+#define SQ_TEX_WORD1_SET_DST_SEL_Y(sq_tex_word1_reg, dst_sel_y) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_DST_SEL_Y_MASK) | (dst_sel_y << SQ_TEX_WORD1_DST_SEL_Y_SHIFT)
+#define SQ_TEX_WORD1_SET_DST_SEL_Z(sq_tex_word1_reg, dst_sel_z) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_DST_SEL_Z_MASK) | (dst_sel_z << SQ_TEX_WORD1_DST_SEL_Z_SHIFT)
+#define SQ_TEX_WORD1_SET_DST_SEL_W(sq_tex_word1_reg, dst_sel_w) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_DST_SEL_W_MASK) | (dst_sel_w << SQ_TEX_WORD1_DST_SEL_W_SHIFT)
+#define SQ_TEX_WORD1_SET_LOD_BIAS(sq_tex_word1_reg, lod_bias) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_LOD_BIAS_MASK) | (lod_bias << SQ_TEX_WORD1_LOD_BIAS_SHIFT)
+#define SQ_TEX_WORD1_SET_COORD_TYPE_X(sq_tex_word1_reg, coord_type_x) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_COORD_TYPE_X_MASK) | (coord_type_x << SQ_TEX_WORD1_COORD_TYPE_X_SHIFT)
+#define SQ_TEX_WORD1_SET_COORD_TYPE_Y(sq_tex_word1_reg, coord_type_y) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_COORD_TYPE_Y_MASK) | (coord_type_y << SQ_TEX_WORD1_COORD_TYPE_Y_SHIFT)
+#define SQ_TEX_WORD1_SET_COORD_TYPE_Z(sq_tex_word1_reg, coord_type_z) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_COORD_TYPE_Z_MASK) | (coord_type_z << SQ_TEX_WORD1_COORD_TYPE_Z_SHIFT)
+#define SQ_TEX_WORD1_SET_COORD_TYPE_W(sq_tex_word1_reg, coord_type_w) \
+ sq_tex_word1_reg = (sq_tex_word1_reg & ~SQ_TEX_WORD1_COORD_TYPE_W_MASK) | (coord_type_w << SQ_TEX_WORD1_COORD_TYPE_W_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_tex_word1_t {
+ unsigned int dst_gpr : SQ_TEX_WORD1_DST_GPR_SIZE;
+ unsigned int dst_rel : SQ_TEX_WORD1_DST_REL_SIZE;
+ unsigned int : 1;
+ unsigned int dst_sel_x : SQ_TEX_WORD1_DST_SEL_X_SIZE;
+ unsigned int dst_sel_y : SQ_TEX_WORD1_DST_SEL_Y_SIZE;
+ unsigned int dst_sel_z : SQ_TEX_WORD1_DST_SEL_Z_SIZE;
+ unsigned int dst_sel_w : SQ_TEX_WORD1_DST_SEL_W_SIZE;
+ unsigned int lod_bias : SQ_TEX_WORD1_LOD_BIAS_SIZE;
+ unsigned int coord_type_x : SQ_TEX_WORD1_COORD_TYPE_X_SIZE;
+ unsigned int coord_type_y : SQ_TEX_WORD1_COORD_TYPE_Y_SIZE;
+ unsigned int coord_type_z : SQ_TEX_WORD1_COORD_TYPE_Z_SIZE;
+ unsigned int coord_type_w : SQ_TEX_WORD1_COORD_TYPE_W_SIZE;
+ } sq_tex_word1_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_tex_word1_t {
+ unsigned int coord_type_w : SQ_TEX_WORD1_COORD_TYPE_W_SIZE;
+ unsigned int coord_type_z : SQ_TEX_WORD1_COORD_TYPE_Z_SIZE;
+ unsigned int coord_type_y : SQ_TEX_WORD1_COORD_TYPE_Y_SIZE;
+ unsigned int coord_type_x : SQ_TEX_WORD1_COORD_TYPE_X_SIZE;
+ unsigned int lod_bias : SQ_TEX_WORD1_LOD_BIAS_SIZE;
+ unsigned int dst_sel_w : SQ_TEX_WORD1_DST_SEL_W_SIZE;
+ unsigned int dst_sel_z : SQ_TEX_WORD1_DST_SEL_Z_SIZE;
+ unsigned int dst_sel_y : SQ_TEX_WORD1_DST_SEL_Y_SIZE;
+ unsigned int dst_sel_x : SQ_TEX_WORD1_DST_SEL_X_SIZE;
+ unsigned int : 1;
+ unsigned int dst_rel : SQ_TEX_WORD1_DST_REL_SIZE;
+ unsigned int dst_gpr : SQ_TEX_WORD1_DST_GPR_SIZE;
+ } sq_tex_word1_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_tex_word1_t f;
+} sq_tex_word1_u;
+
+
+/*
+ * SQ_TEX_WORD2 struct
+ */
+
+#define SQ_TEX_WORD2_OFFSET_X_SIZE 5
+#define SQ_TEX_WORD2_OFFSET_Y_SIZE 5
+#define SQ_TEX_WORD2_OFFSET_Z_SIZE 5
+#define SQ_TEX_WORD2_SAMPLER_ID_SIZE 5
+#define SQ_TEX_WORD2_SRC_SEL_X_SIZE 3
+#define SQ_TEX_WORD2_SRC_SEL_Y_SIZE 3
+#define SQ_TEX_WORD2_SRC_SEL_Z_SIZE 3
+#define SQ_TEX_WORD2_SRC_SEL_W_SIZE 3
+
+#define SQ_TEX_WORD2_OFFSET_X_SHIFT 0
+#define SQ_TEX_WORD2_OFFSET_Y_SHIFT 5
+#define SQ_TEX_WORD2_OFFSET_Z_SHIFT 10
+#define SQ_TEX_WORD2_SAMPLER_ID_SHIFT 15
+#define SQ_TEX_WORD2_SRC_SEL_X_SHIFT 20
+#define SQ_TEX_WORD2_SRC_SEL_Y_SHIFT 23
+#define SQ_TEX_WORD2_SRC_SEL_Z_SHIFT 26
+#define SQ_TEX_WORD2_SRC_SEL_W_SHIFT 29
+
+#define SQ_TEX_WORD2_OFFSET_X_MASK 0x0000001f
+#define SQ_TEX_WORD2_OFFSET_Y_MASK 0x000003e0
+#define SQ_TEX_WORD2_OFFSET_Z_MASK 0x00007c00
+#define SQ_TEX_WORD2_SAMPLER_ID_MASK 0x000f8000
+#define SQ_TEX_WORD2_SRC_SEL_X_MASK 0x00700000
+#define SQ_TEX_WORD2_SRC_SEL_Y_MASK 0x03800000
+#define SQ_TEX_WORD2_SRC_SEL_Z_MASK 0x1c000000
+#define SQ_TEX_WORD2_SRC_SEL_W_MASK 0xe0000000
+
+#define SQ_TEX_WORD2_MASK \
+ (SQ_TEX_WORD2_OFFSET_X_MASK | \
+ SQ_TEX_WORD2_OFFSET_Y_MASK | \
+ SQ_TEX_WORD2_OFFSET_Z_MASK | \
+ SQ_TEX_WORD2_SAMPLER_ID_MASK | \
+ SQ_TEX_WORD2_SRC_SEL_X_MASK | \
+ SQ_TEX_WORD2_SRC_SEL_Y_MASK | \
+ SQ_TEX_WORD2_SRC_SEL_Z_MASK | \
+ SQ_TEX_WORD2_SRC_SEL_W_MASK)
+
+#define SQ_TEX_WORD2_DEFAULT 0xcdcdcdcd
+
+#define SQ_TEX_WORD2_GET_OFFSET_X(sq_tex_word2) \
+ ((sq_tex_word2 & SQ_TEX_WORD2_OFFSET_X_MASK) >> SQ_TEX_WORD2_OFFSET_X_SHIFT)
+#define SQ_TEX_WORD2_GET_OFFSET_Y(sq_tex_word2) \
+ ((sq_tex_word2 & SQ_TEX_WORD2_OFFSET_Y_MASK) >> SQ_TEX_WORD2_OFFSET_Y_SHIFT)
+#define SQ_TEX_WORD2_GET_OFFSET_Z(sq_tex_word2) \
+ ((sq_tex_word2 & SQ_TEX_WORD2_OFFSET_Z_MASK) >> SQ_TEX_WORD2_OFFSET_Z_SHIFT)
+#define SQ_TEX_WORD2_GET_SAMPLER_ID(sq_tex_word2) \
+ ((sq_tex_word2 & SQ_TEX_WORD2_SAMPLER_ID_MASK) >> SQ_TEX_WORD2_SAMPLER_ID_SHIFT)
+#define SQ_TEX_WORD2_GET_SRC_SEL_X(sq_tex_word2) \
+ ((sq_tex_word2 & SQ_TEX_WORD2_SRC_SEL_X_MASK) >> SQ_TEX_WORD2_SRC_SEL_X_SHIFT)
+#define SQ_TEX_WORD2_GET_SRC_SEL_Y(sq_tex_word2) \
+ ((sq_tex_word2 & SQ_TEX_WORD2_SRC_SEL_Y_MASK) >> SQ_TEX_WORD2_SRC_SEL_Y_SHIFT)
+#define SQ_TEX_WORD2_GET_SRC_SEL_Z(sq_tex_word2) \
+ ((sq_tex_word2 & SQ_TEX_WORD2_SRC_SEL_Z_MASK) >> SQ_TEX_WORD2_SRC_SEL_Z_SHIFT)
+#define SQ_TEX_WORD2_GET_SRC_SEL_W(sq_tex_word2) \
+ ((sq_tex_word2 & SQ_TEX_WORD2_SRC_SEL_W_MASK) >> SQ_TEX_WORD2_SRC_SEL_W_SHIFT)
+
+#define SQ_TEX_WORD2_SET_OFFSET_X(sq_tex_word2_reg, offset_x) \
+ sq_tex_word2_reg = (sq_tex_word2_reg & ~SQ_TEX_WORD2_OFFSET_X_MASK) | (offset_x << SQ_TEX_WORD2_OFFSET_X_SHIFT)
+#define SQ_TEX_WORD2_SET_OFFSET_Y(sq_tex_word2_reg, offset_y) \
+ sq_tex_word2_reg = (sq_tex_word2_reg & ~SQ_TEX_WORD2_OFFSET_Y_MASK) | (offset_y << SQ_TEX_WORD2_OFFSET_Y_SHIFT)
+#define SQ_TEX_WORD2_SET_OFFSET_Z(sq_tex_word2_reg, offset_z) \
+ sq_tex_word2_reg = (sq_tex_word2_reg & ~SQ_TEX_WORD2_OFFSET_Z_MASK) | (offset_z << SQ_TEX_WORD2_OFFSET_Z_SHIFT)
+#define SQ_TEX_WORD2_SET_SAMPLER_ID(sq_tex_word2_reg, sampler_id) \
+ sq_tex_word2_reg = (sq_tex_word2_reg & ~SQ_TEX_WORD2_SAMPLER_ID_MASK) | (sampler_id << SQ_TEX_WORD2_SAMPLER_ID_SHIFT)
+#define SQ_TEX_WORD2_SET_SRC_SEL_X(sq_tex_word2_reg, src_sel_x) \
+ sq_tex_word2_reg = (sq_tex_word2_reg & ~SQ_TEX_WORD2_SRC_SEL_X_MASK) | (src_sel_x << SQ_TEX_WORD2_SRC_SEL_X_SHIFT)
+#define SQ_TEX_WORD2_SET_SRC_SEL_Y(sq_tex_word2_reg, src_sel_y) \
+ sq_tex_word2_reg = (sq_tex_word2_reg & ~SQ_TEX_WORD2_SRC_SEL_Y_MASK) | (src_sel_y << SQ_TEX_WORD2_SRC_SEL_Y_SHIFT)
+#define SQ_TEX_WORD2_SET_SRC_SEL_Z(sq_tex_word2_reg, src_sel_z) \
+ sq_tex_word2_reg = (sq_tex_word2_reg & ~SQ_TEX_WORD2_SRC_SEL_Z_MASK) | (src_sel_z << SQ_TEX_WORD2_SRC_SEL_Z_SHIFT)
+#define SQ_TEX_WORD2_SET_SRC_SEL_W(sq_tex_word2_reg, src_sel_w) \
+ sq_tex_word2_reg = (sq_tex_word2_reg & ~SQ_TEX_WORD2_SRC_SEL_W_MASK) | (src_sel_w << SQ_TEX_WORD2_SRC_SEL_W_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_tex_word2_t {
+ unsigned int offset_x : SQ_TEX_WORD2_OFFSET_X_SIZE;
+ unsigned int offset_y : SQ_TEX_WORD2_OFFSET_Y_SIZE;
+ unsigned int offset_z : SQ_TEX_WORD2_OFFSET_Z_SIZE;
+ unsigned int sampler_id : SQ_TEX_WORD2_SAMPLER_ID_SIZE;
+ unsigned int src_sel_x : SQ_TEX_WORD2_SRC_SEL_X_SIZE;
+ unsigned int src_sel_y : SQ_TEX_WORD2_SRC_SEL_Y_SIZE;
+ unsigned int src_sel_z : SQ_TEX_WORD2_SRC_SEL_Z_SIZE;
+ unsigned int src_sel_w : SQ_TEX_WORD2_SRC_SEL_W_SIZE;
+ } sq_tex_word2_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_tex_word2_t {
+ unsigned int src_sel_w : SQ_TEX_WORD2_SRC_SEL_W_SIZE;
+ unsigned int src_sel_z : SQ_TEX_WORD2_SRC_SEL_Z_SIZE;
+ unsigned int src_sel_y : SQ_TEX_WORD2_SRC_SEL_Y_SIZE;
+ unsigned int src_sel_x : SQ_TEX_WORD2_SRC_SEL_X_SIZE;
+ unsigned int sampler_id : SQ_TEX_WORD2_SAMPLER_ID_SIZE;
+ unsigned int offset_z : SQ_TEX_WORD2_OFFSET_Z_SIZE;
+ unsigned int offset_y : SQ_TEX_WORD2_OFFSET_Y_SIZE;
+ unsigned int offset_x : SQ_TEX_WORD2_OFFSET_X_SIZE;
+ } sq_tex_word2_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_tex_word2_t f;
+} sq_tex_word2_u;
+
+
+/*
+ * SQ_VTX_WORD0 struct
+ */
+
+#define SQ_VTX_WORD0_VTX_INST_SIZE 5
+#define SQ_VTX_WORD0_FETCH_TYPE_SIZE 2
+#define SQ_VTX_WORD0_FETCH_WHOLE_QUAD_SIZE 1
+#define SQ_VTX_WORD0_BUFFER_ID_SIZE 8
+#define SQ_VTX_WORD0_SRC_GPR_SIZE 7
+#define SQ_VTX_WORD0_SRC_REL_SIZE 1
+#define SQ_VTX_WORD0_SRC_SEL_X_SIZE 2
+#define SQ_VTX_WORD0_MEGA_FETCH_COUNT_SIZE 6
+
+#define SQ_VTX_WORD0_VTX_INST_SHIFT 0
+#define SQ_VTX_WORD0_FETCH_TYPE_SHIFT 5
+#define SQ_VTX_WORD0_FETCH_WHOLE_QUAD_SHIFT 7
+#define SQ_VTX_WORD0_BUFFER_ID_SHIFT 8
+#define SQ_VTX_WORD0_SRC_GPR_SHIFT 16
+#define SQ_VTX_WORD0_SRC_REL_SHIFT 23
+#define SQ_VTX_WORD0_SRC_SEL_X_SHIFT 24
+#define SQ_VTX_WORD0_MEGA_FETCH_COUNT_SHIFT 26
+
+#define SQ_VTX_WORD0_VTX_INST_MASK 0x0000001f
+#define SQ_VTX_WORD0_FETCH_TYPE_MASK 0x00000060
+#define SQ_VTX_WORD0_FETCH_WHOLE_QUAD_MASK 0x00000080
+#define SQ_VTX_WORD0_BUFFER_ID_MASK 0x0000ff00
+#define SQ_VTX_WORD0_SRC_GPR_MASK 0x007f0000
+#define SQ_VTX_WORD0_SRC_REL_MASK 0x00800000
+#define SQ_VTX_WORD0_SRC_SEL_X_MASK 0x03000000
+#define SQ_VTX_WORD0_MEGA_FETCH_COUNT_MASK 0xfc000000
+
+#define SQ_VTX_WORD0_MASK \
+ (SQ_VTX_WORD0_VTX_INST_MASK | \
+ SQ_VTX_WORD0_FETCH_TYPE_MASK | \
+ SQ_VTX_WORD0_FETCH_WHOLE_QUAD_MASK | \
+ SQ_VTX_WORD0_BUFFER_ID_MASK | \
+ SQ_VTX_WORD0_SRC_GPR_MASK | \
+ SQ_VTX_WORD0_SRC_REL_MASK | \
+ SQ_VTX_WORD0_SRC_SEL_X_MASK | \
+ SQ_VTX_WORD0_MEGA_FETCH_COUNT_MASK)
+
+#define SQ_VTX_WORD0_DEFAULT 0xcdcdcdcd
+
+#define SQ_VTX_WORD0_GET_VTX_INST(sq_vtx_word0) \
+ ((sq_vtx_word0 & SQ_VTX_WORD0_VTX_INST_MASK) >> SQ_VTX_WORD0_VTX_INST_SHIFT)
+#define SQ_VTX_WORD0_GET_FETCH_TYPE(sq_vtx_word0) \
+ ((sq_vtx_word0 & SQ_VTX_WORD0_FETCH_TYPE_MASK) >> SQ_VTX_WORD0_FETCH_TYPE_SHIFT)
+#define SQ_VTX_WORD0_GET_FETCH_WHOLE_QUAD(sq_vtx_word0) \
+ ((sq_vtx_word0 & SQ_VTX_WORD0_FETCH_WHOLE_QUAD_MASK) >> SQ_VTX_WORD0_FETCH_WHOLE_QUAD_SHIFT)
+#define SQ_VTX_WORD0_GET_BUFFER_ID(sq_vtx_word0) \
+ ((sq_vtx_word0 & SQ_VTX_WORD0_BUFFER_ID_MASK) >> SQ_VTX_WORD0_BUFFER_ID_SHIFT)
+#define SQ_VTX_WORD0_GET_SRC_GPR(sq_vtx_word0) \
+ ((sq_vtx_word0 & SQ_VTX_WORD0_SRC_GPR_MASK) >> SQ_VTX_WORD0_SRC_GPR_SHIFT)
+#define SQ_VTX_WORD0_GET_SRC_REL(sq_vtx_word0) \
+ ((sq_vtx_word0 & SQ_VTX_WORD0_SRC_REL_MASK) >> SQ_VTX_WORD0_SRC_REL_SHIFT)
+#define SQ_VTX_WORD0_GET_SRC_SEL_X(sq_vtx_word0) \
+ ((sq_vtx_word0 & SQ_VTX_WORD0_SRC_SEL_X_MASK) >> SQ_VTX_WORD0_SRC_SEL_X_SHIFT)
+#define SQ_VTX_WORD0_GET_MEGA_FETCH_COUNT(sq_vtx_word0) \
+ ((sq_vtx_word0 & SQ_VTX_WORD0_MEGA_FETCH_COUNT_MASK) >> SQ_VTX_WORD0_MEGA_FETCH_COUNT_SHIFT)
+
+#define SQ_VTX_WORD0_SET_VTX_INST(sq_vtx_word0_reg, vtx_inst) \
+ sq_vtx_word0_reg = (sq_vtx_word0_reg & ~SQ_VTX_WORD0_VTX_INST_MASK) | (vtx_inst << SQ_VTX_WORD0_VTX_INST_SHIFT)
+#define SQ_VTX_WORD0_SET_FETCH_TYPE(sq_vtx_word0_reg, fetch_type) \
+ sq_vtx_word0_reg = (sq_vtx_word0_reg & ~SQ_VTX_WORD0_FETCH_TYPE_MASK) | (fetch_type << SQ_VTX_WORD0_FETCH_TYPE_SHIFT)
+#define SQ_VTX_WORD0_SET_FETCH_WHOLE_QUAD(sq_vtx_word0_reg, fetch_whole_quad) \
+ sq_vtx_word0_reg = (sq_vtx_word0_reg & ~SQ_VTX_WORD0_FETCH_WHOLE_QUAD_MASK) | (fetch_whole_quad << SQ_VTX_WORD0_FETCH_WHOLE_QUAD_SHIFT)
+#define SQ_VTX_WORD0_SET_BUFFER_ID(sq_vtx_word0_reg, buffer_id) \
+ sq_vtx_word0_reg = (sq_vtx_word0_reg & ~SQ_VTX_WORD0_BUFFER_ID_MASK) | (buffer_id << SQ_VTX_WORD0_BUFFER_ID_SHIFT)
+#define SQ_VTX_WORD0_SET_SRC_GPR(sq_vtx_word0_reg, src_gpr) \
+ sq_vtx_word0_reg = (sq_vtx_word0_reg & ~SQ_VTX_WORD0_SRC_GPR_MASK) | (src_gpr << SQ_VTX_WORD0_SRC_GPR_SHIFT)
+#define SQ_VTX_WORD0_SET_SRC_REL(sq_vtx_word0_reg, src_rel) \
+ sq_vtx_word0_reg = (sq_vtx_word0_reg & ~SQ_VTX_WORD0_SRC_REL_MASK) | (src_rel << SQ_VTX_WORD0_SRC_REL_SHIFT)
+#define SQ_VTX_WORD0_SET_SRC_SEL_X(sq_vtx_word0_reg, src_sel_x) \
+ sq_vtx_word0_reg = (sq_vtx_word0_reg & ~SQ_VTX_WORD0_SRC_SEL_X_MASK) | (src_sel_x << SQ_VTX_WORD0_SRC_SEL_X_SHIFT)
+#define SQ_VTX_WORD0_SET_MEGA_FETCH_COUNT(sq_vtx_word0_reg, mega_fetch_count) \
+ sq_vtx_word0_reg = (sq_vtx_word0_reg & ~SQ_VTX_WORD0_MEGA_FETCH_COUNT_MASK) | (mega_fetch_count << SQ_VTX_WORD0_MEGA_FETCH_COUNT_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_vtx_word0_t {
+ unsigned int vtx_inst : SQ_VTX_WORD0_VTX_INST_SIZE;
+ unsigned int fetch_type : SQ_VTX_WORD0_FETCH_TYPE_SIZE;
+ unsigned int fetch_whole_quad : SQ_VTX_WORD0_FETCH_WHOLE_QUAD_SIZE;
+ unsigned int buffer_id : SQ_VTX_WORD0_BUFFER_ID_SIZE;
+ unsigned int src_gpr : SQ_VTX_WORD0_SRC_GPR_SIZE;
+ unsigned int src_rel : SQ_VTX_WORD0_SRC_REL_SIZE;
+ unsigned int src_sel_x : SQ_VTX_WORD0_SRC_SEL_X_SIZE;
+ unsigned int mega_fetch_count : SQ_VTX_WORD0_MEGA_FETCH_COUNT_SIZE;
+ } sq_vtx_word0_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_vtx_word0_t {
+ unsigned int mega_fetch_count : SQ_VTX_WORD0_MEGA_FETCH_COUNT_SIZE;
+ unsigned int src_sel_x : SQ_VTX_WORD0_SRC_SEL_X_SIZE;
+ unsigned int src_rel : SQ_VTX_WORD0_SRC_REL_SIZE;
+ unsigned int src_gpr : SQ_VTX_WORD0_SRC_GPR_SIZE;
+ unsigned int buffer_id : SQ_VTX_WORD0_BUFFER_ID_SIZE;
+ unsigned int fetch_whole_quad : SQ_VTX_WORD0_FETCH_WHOLE_QUAD_SIZE;
+ unsigned int fetch_type : SQ_VTX_WORD0_FETCH_TYPE_SIZE;
+ unsigned int vtx_inst : SQ_VTX_WORD0_VTX_INST_SIZE;
+ } sq_vtx_word0_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_vtx_word0_t f;
+} sq_vtx_word0_u;
+
+
+/*
+ * SQ_VTX_WORD1 struct
+ */
+
+#define SQ_VTX_WORD1_DST_SEL_X_SIZE 3
+#define SQ_VTX_WORD1_DST_SEL_Y_SIZE 3
+#define SQ_VTX_WORD1_DST_SEL_Z_SIZE 3
+#define SQ_VTX_WORD1_DST_SEL_W_SIZE 3
+#define SQ_VTX_WORD1_USE_CONST_FIELDS_SIZE 1
+#define SQ_VTX_WORD1_DATA_FORMAT_SIZE 6
+#define SQ_VTX_WORD1_NUM_FORMAT_ALL_SIZE 2
+#define SQ_VTX_WORD1_FORMAT_COMP_ALL_SIZE 1
+#define SQ_VTX_WORD1_SRF_MODE_ALL_SIZE 1
+
+#define SQ_VTX_WORD1_DST_SEL_X_SHIFT 9
+#define SQ_VTX_WORD1_DST_SEL_Y_SHIFT 12
+#define SQ_VTX_WORD1_DST_SEL_Z_SHIFT 15
+#define SQ_VTX_WORD1_DST_SEL_W_SHIFT 18
+#define SQ_VTX_WORD1_USE_CONST_FIELDS_SHIFT 21
+#define SQ_VTX_WORD1_DATA_FORMAT_SHIFT 22
+#define SQ_VTX_WORD1_NUM_FORMAT_ALL_SHIFT 28
+#define SQ_VTX_WORD1_FORMAT_COMP_ALL_SHIFT 30
+#define SQ_VTX_WORD1_SRF_MODE_ALL_SHIFT 31
+
+#define SQ_VTX_WORD1_DST_SEL_X_MASK 0x00000e00
+#define SQ_VTX_WORD1_DST_SEL_Y_MASK 0x00007000
+#define SQ_VTX_WORD1_DST_SEL_Z_MASK 0x00038000
+#define SQ_VTX_WORD1_DST_SEL_W_MASK 0x001c0000
+#define SQ_VTX_WORD1_USE_CONST_FIELDS_MASK 0x00200000
+#define SQ_VTX_WORD1_DATA_FORMAT_MASK 0x0fc00000
+#define SQ_VTX_WORD1_NUM_FORMAT_ALL_MASK 0x30000000
+#define SQ_VTX_WORD1_FORMAT_COMP_ALL_MASK 0x40000000
+#define SQ_VTX_WORD1_SRF_MODE_ALL_MASK 0x80000000
+
+#define SQ_VTX_WORD1_MASK \
+ (SQ_VTX_WORD1_DST_SEL_X_MASK | \
+ SQ_VTX_WORD1_DST_SEL_Y_MASK | \
+ SQ_VTX_WORD1_DST_SEL_Z_MASK | \
+ SQ_VTX_WORD1_DST_SEL_W_MASK | \
+ SQ_VTX_WORD1_USE_CONST_FIELDS_MASK | \
+ SQ_VTX_WORD1_DATA_FORMAT_MASK | \
+ SQ_VTX_WORD1_NUM_FORMAT_ALL_MASK | \
+ SQ_VTX_WORD1_FORMAT_COMP_ALL_MASK | \
+ SQ_VTX_WORD1_SRF_MODE_ALL_MASK)
+
+#define SQ_VTX_WORD1_DEFAULT 0xcdcdcc00
+
+#define SQ_VTX_WORD1_GET_DST_SEL_X(sq_vtx_word1) \
+ ((sq_vtx_word1 & SQ_VTX_WORD1_DST_SEL_X_MASK) >> SQ_VTX_WORD1_DST_SEL_X_SHIFT)
+#define SQ_VTX_WORD1_GET_DST_SEL_Y(sq_vtx_word1) \
+ ((sq_vtx_word1 & SQ_VTX_WORD1_DST_SEL_Y_MASK) >> SQ_VTX_WORD1_DST_SEL_Y_SHIFT)
+#define SQ_VTX_WORD1_GET_DST_SEL_Z(sq_vtx_word1) \
+ ((sq_vtx_word1 & SQ_VTX_WORD1_DST_SEL_Z_MASK) >> SQ_VTX_WORD1_DST_SEL_Z_SHIFT)
+#define SQ_VTX_WORD1_GET_DST_SEL_W(sq_vtx_word1) \
+ ((sq_vtx_word1 & SQ_VTX_WORD1_DST_SEL_W_MASK) >> SQ_VTX_WORD1_DST_SEL_W_SHIFT)
+#define SQ_VTX_WORD1_GET_USE_CONST_FIELDS(sq_vtx_word1) \
+ ((sq_vtx_word1 & SQ_VTX_WORD1_USE_CONST_FIELDS_MASK) >> SQ_VTX_WORD1_USE_CONST_FIELDS_SHIFT)
+#define SQ_VTX_WORD1_GET_DATA_FORMAT(sq_vtx_word1) \
+ ((sq_vtx_word1 & SQ_VTX_WORD1_DATA_FORMAT_MASK) >> SQ_VTX_WORD1_DATA_FORMAT_SHIFT)
+#define SQ_VTX_WORD1_GET_NUM_FORMAT_ALL(sq_vtx_word1) \
+ ((sq_vtx_word1 & SQ_VTX_WORD1_NUM_FORMAT_ALL_MASK) >> SQ_VTX_WORD1_NUM_FORMAT_ALL_SHIFT)
+#define SQ_VTX_WORD1_GET_FORMAT_COMP_ALL(sq_vtx_word1) \
+ ((sq_vtx_word1 & SQ_VTX_WORD1_FORMAT_COMP_ALL_MASK) >> SQ_VTX_WORD1_FORMAT_COMP_ALL_SHIFT)
+#define SQ_VTX_WORD1_GET_SRF_MODE_ALL(sq_vtx_word1) \
+ ((sq_vtx_word1 & SQ_VTX_WORD1_SRF_MODE_ALL_MASK) >> SQ_VTX_WORD1_SRF_MODE_ALL_SHIFT)
+
+#define SQ_VTX_WORD1_SET_DST_SEL_X(sq_vtx_word1_reg, dst_sel_x) \
+ sq_vtx_word1_reg = (sq_vtx_word1_reg & ~SQ_VTX_WORD1_DST_SEL_X_MASK) | (dst_sel_x << SQ_VTX_WORD1_DST_SEL_X_SHIFT)
+#define SQ_VTX_WORD1_SET_DST_SEL_Y(sq_vtx_word1_reg, dst_sel_y) \
+ sq_vtx_word1_reg = (sq_vtx_word1_reg & ~SQ_VTX_WORD1_DST_SEL_Y_MASK) | (dst_sel_y << SQ_VTX_WORD1_DST_SEL_Y_SHIFT)
+#define SQ_VTX_WORD1_SET_DST_SEL_Z(sq_vtx_word1_reg, dst_sel_z) \
+ sq_vtx_word1_reg = (sq_vtx_word1_reg & ~SQ_VTX_WORD1_DST_SEL_Z_MASK) | (dst_sel_z << SQ_VTX_WORD1_DST_SEL_Z_SHIFT)
+#define SQ_VTX_WORD1_SET_DST_SEL_W(sq_vtx_word1_reg, dst_sel_w) \
+ sq_vtx_word1_reg = (sq_vtx_word1_reg & ~SQ_VTX_WORD1_DST_SEL_W_MASK) | (dst_sel_w << SQ_VTX_WORD1_DST_SEL_W_SHIFT)
+#define SQ_VTX_WORD1_SET_USE_CONST_FIELDS(sq_vtx_word1_reg, use_const_fields) \
+ sq_vtx_word1_reg = (sq_vtx_word1_reg & ~SQ_VTX_WORD1_USE_CONST_FIELDS_MASK) | (use_const_fields << SQ_VTX_WORD1_USE_CONST_FIELDS_SHIFT)
+#define SQ_VTX_WORD1_SET_DATA_FORMAT(sq_vtx_word1_reg, data_format) \
+ sq_vtx_word1_reg = (sq_vtx_word1_reg & ~SQ_VTX_WORD1_DATA_FORMAT_MASK) | (data_format << SQ_VTX_WORD1_DATA_FORMAT_SHIFT)
+#define SQ_VTX_WORD1_SET_NUM_FORMAT_ALL(sq_vtx_word1_reg, num_format_all) \
+ sq_vtx_word1_reg = (sq_vtx_word1_reg & ~SQ_VTX_WORD1_NUM_FORMAT_ALL_MASK) | (num_format_all << SQ_VTX_WORD1_NUM_FORMAT_ALL_SHIFT)
+#define SQ_VTX_WORD1_SET_FORMAT_COMP_ALL(sq_vtx_word1_reg, format_comp_all) \
+ sq_vtx_word1_reg = (sq_vtx_word1_reg & ~SQ_VTX_WORD1_FORMAT_COMP_ALL_MASK) | (format_comp_all << SQ_VTX_WORD1_FORMAT_COMP_ALL_SHIFT)
+#define SQ_VTX_WORD1_SET_SRF_MODE_ALL(sq_vtx_word1_reg, srf_mode_all) \
+ sq_vtx_word1_reg = (sq_vtx_word1_reg & ~SQ_VTX_WORD1_SRF_MODE_ALL_MASK) | (srf_mode_all << SQ_VTX_WORD1_SRF_MODE_ALL_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_vtx_word1_t {
+ unsigned int : 9;
+ unsigned int dst_sel_x : SQ_VTX_WORD1_DST_SEL_X_SIZE;
+ unsigned int dst_sel_y : SQ_VTX_WORD1_DST_SEL_Y_SIZE;
+ unsigned int dst_sel_z : SQ_VTX_WORD1_DST_SEL_Z_SIZE;
+ unsigned int dst_sel_w : SQ_VTX_WORD1_DST_SEL_W_SIZE;
+ unsigned int use_const_fields : SQ_VTX_WORD1_USE_CONST_FIELDS_SIZE;
+ unsigned int data_format : SQ_VTX_WORD1_DATA_FORMAT_SIZE;
+ unsigned int num_format_all : SQ_VTX_WORD1_NUM_FORMAT_ALL_SIZE;
+ unsigned int format_comp_all : SQ_VTX_WORD1_FORMAT_COMP_ALL_SIZE;
+ unsigned int srf_mode_all : SQ_VTX_WORD1_SRF_MODE_ALL_SIZE;
+ } sq_vtx_word1_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_vtx_word1_t {
+ unsigned int srf_mode_all : SQ_VTX_WORD1_SRF_MODE_ALL_SIZE;
+ unsigned int format_comp_all : SQ_VTX_WORD1_FORMAT_COMP_ALL_SIZE;
+ unsigned int num_format_all : SQ_VTX_WORD1_NUM_FORMAT_ALL_SIZE;
+ unsigned int data_format : SQ_VTX_WORD1_DATA_FORMAT_SIZE;
+ unsigned int use_const_fields : SQ_VTX_WORD1_USE_CONST_FIELDS_SIZE;
+ unsigned int dst_sel_w : SQ_VTX_WORD1_DST_SEL_W_SIZE;
+ unsigned int dst_sel_z : SQ_VTX_WORD1_DST_SEL_Z_SIZE;
+ unsigned int dst_sel_y : SQ_VTX_WORD1_DST_SEL_Y_SIZE;
+ unsigned int dst_sel_x : SQ_VTX_WORD1_DST_SEL_X_SIZE;
+ unsigned int : 9;
+ } sq_vtx_word1_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_vtx_word1_t f;
+} sq_vtx_word1_u;
+
+
+/*
+ * SQ_VTX_WORD1_GPR struct
+ */
+
+#define SQ_VTX_WORD1_GPR_DST_GPR_SIZE 7
+#define SQ_VTX_WORD1_GPR_DST_REL_SIZE 1
+
+#define SQ_VTX_WORD1_GPR_DST_GPR_SHIFT 0
+#define SQ_VTX_WORD1_GPR_DST_REL_SHIFT 7
+
+#define SQ_VTX_WORD1_GPR_DST_GPR_MASK 0x0000007f
+#define SQ_VTX_WORD1_GPR_DST_REL_MASK 0x00000080
+
+#define SQ_VTX_WORD1_GPR_MASK \
+ (SQ_VTX_WORD1_GPR_DST_GPR_MASK | \
+ SQ_VTX_WORD1_GPR_DST_REL_MASK)
+
+#define SQ_VTX_WORD1_GPR_DEFAULT 0x000000cd
+
+#define SQ_VTX_WORD1_GPR_GET_DST_GPR(sq_vtx_word1_gpr) \
+ ((sq_vtx_word1_gpr & SQ_VTX_WORD1_GPR_DST_GPR_MASK) >> SQ_VTX_WORD1_GPR_DST_GPR_SHIFT)
+#define SQ_VTX_WORD1_GPR_GET_DST_REL(sq_vtx_word1_gpr) \
+ ((sq_vtx_word1_gpr & SQ_VTX_WORD1_GPR_DST_REL_MASK) >> SQ_VTX_WORD1_GPR_DST_REL_SHIFT)
+
+#define SQ_VTX_WORD1_GPR_SET_DST_GPR(sq_vtx_word1_gpr_reg, dst_gpr) \
+ sq_vtx_word1_gpr_reg = (sq_vtx_word1_gpr_reg & ~SQ_VTX_WORD1_GPR_DST_GPR_MASK) | (dst_gpr << SQ_VTX_WORD1_GPR_DST_GPR_SHIFT)
+#define SQ_VTX_WORD1_GPR_SET_DST_REL(sq_vtx_word1_gpr_reg, dst_rel) \
+ sq_vtx_word1_gpr_reg = (sq_vtx_word1_gpr_reg & ~SQ_VTX_WORD1_GPR_DST_REL_MASK) | (dst_rel << SQ_VTX_WORD1_GPR_DST_REL_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_vtx_word1_gpr_t {
+ unsigned int dst_gpr : SQ_VTX_WORD1_GPR_DST_GPR_SIZE;
+ unsigned int dst_rel : SQ_VTX_WORD1_GPR_DST_REL_SIZE;
+ unsigned int : 24;
+ } sq_vtx_word1_gpr_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_vtx_word1_gpr_t {
+ unsigned int : 24;
+ unsigned int dst_rel : SQ_VTX_WORD1_GPR_DST_REL_SIZE;
+ unsigned int dst_gpr : SQ_VTX_WORD1_GPR_DST_GPR_SIZE;
+ } sq_vtx_word1_gpr_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_vtx_word1_gpr_t f;
+} sq_vtx_word1_gpr_u;
+
+
+/*
+ * SQ_VTX_WORD1_SEM struct
+ */
+
+#define SQ_VTX_WORD1_SEM_SEMANTIC_ID_SIZE 8
+
+#define SQ_VTX_WORD1_SEM_SEMANTIC_ID_SHIFT 0
+
+#define SQ_VTX_WORD1_SEM_SEMANTIC_ID_MASK 0x000000ff
+
+#define SQ_VTX_WORD1_SEM_MASK \
+ (SQ_VTX_WORD1_SEM_SEMANTIC_ID_MASK)
+
+#define SQ_VTX_WORD1_SEM_DEFAULT 0x000000cd
+
+#define SQ_VTX_WORD1_SEM_GET_SEMANTIC_ID(sq_vtx_word1_sem) \
+ ((sq_vtx_word1_sem & SQ_VTX_WORD1_SEM_SEMANTIC_ID_MASK) >> SQ_VTX_WORD1_SEM_SEMANTIC_ID_SHIFT)
+
+#define SQ_VTX_WORD1_SEM_SET_SEMANTIC_ID(sq_vtx_word1_sem_reg, semantic_id) \
+ sq_vtx_word1_sem_reg = (sq_vtx_word1_sem_reg & ~SQ_VTX_WORD1_SEM_SEMANTIC_ID_MASK) | (semantic_id << SQ_VTX_WORD1_SEM_SEMANTIC_ID_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_vtx_word1_sem_t {
+ unsigned int semantic_id : SQ_VTX_WORD1_SEM_SEMANTIC_ID_SIZE;
+ unsigned int : 24;
+ } sq_vtx_word1_sem_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_vtx_word1_sem_t {
+ unsigned int : 24;
+ unsigned int semantic_id : SQ_VTX_WORD1_SEM_SEMANTIC_ID_SIZE;
+ } sq_vtx_word1_sem_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_vtx_word1_sem_t f;
+} sq_vtx_word1_sem_u;
+
+
+/*
+ * SQ_VTX_WORD2 struct
+ */
+
+#define SQ_VTX_WORD2_OFFSET_SIZE 16
+#define SQ_VTX_WORD2_ENDIAN_SWAP_SIZE 2
+#define SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_SIZE 1
+#define SQ_VTX_WORD2_MEGA_FETCH_SIZE 1
+#define SQ_VTX_WORD2_ALT_CONST_SIZE 1
+
+#define SQ_VTX_WORD2_OFFSET_SHIFT 0
+#define SQ_VTX_WORD2_ENDIAN_SWAP_SHIFT 16
+#define SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_SHIFT 18
+#define SQ_VTX_WORD2_MEGA_FETCH_SHIFT 19
+#define SQ_VTX_WORD2_ALT_CONST_SHIFT 20
+
+#define SQ_VTX_WORD2_OFFSET_MASK 0x0000ffff
+#define SQ_VTX_WORD2_ENDIAN_SWAP_MASK 0x00030000
+#define SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_MASK 0x00040000
+#define SQ_VTX_WORD2_MEGA_FETCH_MASK 0x00080000
+#define SQ_VTX_WORD2_ALT_CONST_MASK 0x00100000
+
+#define SQ_VTX_WORD2_MASK \
+ (SQ_VTX_WORD2_OFFSET_MASK | \
+ SQ_VTX_WORD2_ENDIAN_SWAP_MASK | \
+ SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_MASK | \
+ SQ_VTX_WORD2_MEGA_FETCH_MASK | \
+ SQ_VTX_WORD2_ALT_CONST_MASK)
+
+#define SQ_VTX_WORD2_DEFAULT 0x000dcdcd
+
+#define SQ_VTX_WORD2_GET_OFFSET(sq_vtx_word2) \
+ ((sq_vtx_word2 & SQ_VTX_WORD2_OFFSET_MASK) >> SQ_VTX_WORD2_OFFSET_SHIFT)
+#define SQ_VTX_WORD2_GET_ENDIAN_SWAP(sq_vtx_word2) \
+ ((sq_vtx_word2 & SQ_VTX_WORD2_ENDIAN_SWAP_MASK) >> SQ_VTX_WORD2_ENDIAN_SWAP_SHIFT)
+#define SQ_VTX_WORD2_GET_CONST_BUF_NO_STRIDE(sq_vtx_word2) \
+ ((sq_vtx_word2 & SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_MASK) >> SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_SHIFT)
+#define SQ_VTX_WORD2_GET_MEGA_FETCH(sq_vtx_word2) \
+ ((sq_vtx_word2 & SQ_VTX_WORD2_MEGA_FETCH_MASK) >> SQ_VTX_WORD2_MEGA_FETCH_SHIFT)
+#define SQ_VTX_WORD2_GET_ALT_CONST(sq_vtx_word2) \
+ ((sq_vtx_word2 & SQ_VTX_WORD2_ALT_CONST_MASK) >> SQ_VTX_WORD2_ALT_CONST_SHIFT)
+
+#define SQ_VTX_WORD2_SET_OFFSET(sq_vtx_word2_reg, offset) \
+ sq_vtx_word2_reg = (sq_vtx_word2_reg & ~SQ_VTX_WORD2_OFFSET_MASK) | (offset << SQ_VTX_WORD2_OFFSET_SHIFT)
+#define SQ_VTX_WORD2_SET_ENDIAN_SWAP(sq_vtx_word2_reg, endian_swap) \
+ sq_vtx_word2_reg = (sq_vtx_word2_reg & ~SQ_VTX_WORD2_ENDIAN_SWAP_MASK) | (endian_swap << SQ_VTX_WORD2_ENDIAN_SWAP_SHIFT)
+#define SQ_VTX_WORD2_SET_CONST_BUF_NO_STRIDE(sq_vtx_word2_reg, const_buf_no_stride) \
+ sq_vtx_word2_reg = (sq_vtx_word2_reg & ~SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_MASK) | (const_buf_no_stride << SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_SHIFT)
+#define SQ_VTX_WORD2_SET_MEGA_FETCH(sq_vtx_word2_reg, mega_fetch) \
+ sq_vtx_word2_reg = (sq_vtx_word2_reg & ~SQ_VTX_WORD2_MEGA_FETCH_MASK) | (mega_fetch << SQ_VTX_WORD2_MEGA_FETCH_SHIFT)
+#define SQ_VTX_WORD2_SET_ALT_CONST(sq_vtx_word2_reg, alt_const) \
+ sq_vtx_word2_reg = (sq_vtx_word2_reg & ~SQ_VTX_WORD2_ALT_CONST_MASK) | (alt_const << SQ_VTX_WORD2_ALT_CONST_SHIFT)
+
+#if defined(LITTLEENDIAN_CPU)
+
+ typedef struct _sq_vtx_word2_t {
+ unsigned int offset : SQ_VTX_WORD2_OFFSET_SIZE;
+ unsigned int endian_swap : SQ_VTX_WORD2_ENDIAN_SWAP_SIZE;
+ unsigned int const_buf_no_stride : SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_SIZE;
+ unsigned int mega_fetch : SQ_VTX_WORD2_MEGA_FETCH_SIZE;
+ unsigned int alt_const : SQ_VTX_WORD2_ALT_CONST_SIZE;
+ unsigned int : 11;
+ } sq_vtx_word2_t;
+
+#elif defined(BIGENDIAN_CPU)
+
+ typedef struct _sq_vtx_word2_t {
+ unsigned int : 11;
+ unsigned int alt_const : SQ_VTX_WORD2_ALT_CONST_SIZE;
+ unsigned int mega_fetch : SQ_VTX_WORD2_MEGA_FETCH_SIZE;
+ unsigned int const_buf_no_stride : SQ_VTX_WORD2_CONST_BUF_NO_STRIDE_SIZE;
+ unsigned int endian_swap : SQ_VTX_WORD2_ENDIAN_SWAP_SIZE;
+ unsigned int offset : SQ_VTX_WORD2_OFFSET_SIZE;
+ } sq_vtx_word2_t;
+
+#endif
+
+typedef union {
+ unsigned int val : 32;
+ sq_vtx_word2_t f;
+} sq_vtx_word2_u;
+
+#endif /* _SQ_MICRO_REG_H */
+
+
diff --git a/src/mesa/drivers/dri/radeon/Makefile b/src/mesa/drivers/dri/radeon/Makefile
index f223b2d922..1f286776b5 100644
--- a/src/mesa/drivers/dri/radeon/Makefile
+++ b/src/mesa/drivers/dri/radeon/Makefile
@@ -4,31 +4,53 @@
TOP = ../../../../..
include $(TOP)/configs/current
+CFLAGS += $(RADEON_CFLAGS)
+
LIBNAME = radeon_dri.so
MINIGLX_SOURCES = server/radeon_dri.c
+ifeq ($(RADEON_LDFLAGS),)
+CS_SOURCES = radeon_cs_space_drm.c
+endif
+
+RADEON_COMMON_SOURCES = \
+ radeon_bo_legacy.c \
+ radeon_common_context.c \
+ radeon_common.c \
+ radeon_cs_legacy.c \
+ radeon_dma.c \
+ radeon_debug.c \
+ radeon_fbo.c \
+ radeon_lock.c \
+ radeon_mipmap_tree.c \
+ radeon_queryobj.c \
+ radeon_span.c \
+ radeon_texture.c
+
DRIVER_SOURCES = \
radeon_context.c \
radeon_ioctl.c \
- radeon_lock.c \
radeon_screen.c \
radeon_state.c \
radeon_state_init.c \
radeon_tex.c \
- radeon_texmem.c \
radeon_texstate.c \
radeon_tcl.c \
radeon_swtcl.c \
- radeon_span.c \
radeon_maos.c \
- radeon_sanity.c
+ radeon_sanity.c \
+ $(RADEON_COMMON_SOURCES)
C_SOURCES = \
$(COMMON_SOURCES) \
- $(DRIVER_SOURCES)
+ $(DRIVER_SOURCES) \
+ $(CS_SOURCES)
+
+DRIVER_DEFINES = -DRADEON_COMMON=0 \
+ -Wall
-DRIVER_DEFINES = -DRADEON_COMMON=0
+DRI_LIB_DEPS += $(RADEON_LDFLAGS)
X86_SOURCES =
diff --git a/src/mesa/drivers/dri/radeon/radeon_bo_drm.h b/src/mesa/drivers/dri/radeon/radeon_bo_drm.h
new file mode 100644
index 0000000000..7141371633
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_bo_drm.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Jérôme Glisse <glisse@freedesktop.org>
+ */
+#ifndef RADEON_BO_H
+#define RADEON_BO_H
+
+#include <stdio.h>
+#include <stdint.h>
+//#include "radeon_track.h"
+
+/* bo object */
+#define RADEON_BO_FLAGS_MACRO_TILE 1
+#define RADEON_BO_FLAGS_MICRO_TILE 2
+
+struct radeon_bo_manager;
+
+struct radeon_bo {
+ uint32_t alignment;
+ uint32_t handle;
+ uint32_t size;
+ uint32_t domains;
+ uint32_t flags;
+ unsigned cref;
+#ifdef RADEON_BO_TRACK
+ struct radeon_track *track;
+#endif
+ void *ptr;
+ struct radeon_bo_manager *bom;
+ uint32_t space_accounted;
+};
+
+/* bo functions */
+struct radeon_bo_funcs {
+ struct radeon_bo *(*bo_open)(struct radeon_bo_manager *bom,
+ uint32_t handle,
+ uint32_t size,
+ uint32_t alignment,
+ uint32_t domains,
+ uint32_t flags);
+ void (*bo_ref)(struct radeon_bo *bo);
+ struct radeon_bo *(*bo_unref)(struct radeon_bo *bo);
+ int (*bo_map)(struct radeon_bo *bo, int write);
+ int (*bo_unmap)(struct radeon_bo *bo);
+ int (*bo_wait)(struct radeon_bo *bo);
+ int (*bo_is_static)(struct radeon_bo *bo);
+ int (*bo_set_tiling)(struct radeon_bo *bo, uint32_t tiling_flags,
+ uint32_t pitch);
+ int (*bo_get_tiling)(struct radeon_bo *bo, uint32_t *tiling_flags,
+ uint32_t *pitch);
+ int (*bo_is_busy)(struct radeon_bo *bo, uint32_t *domain);
+};
+
+struct radeon_bo_manager {
+ struct radeon_bo_funcs *funcs;
+ int fd;
+
+#ifdef RADEON_BO_TRACK
+ struct radeon_tracker tracker;
+#endif
+};
+
+static inline void _radeon_bo_debug(struct radeon_bo *bo,
+ const char *op,
+ const char *file,
+ const char *func,
+ int line)
+{
+ fprintf(stderr, "%s %p 0x%08X 0x%08X 0x%08X [%s %s %d]\n",
+ op, bo, bo->handle, bo->size, bo->cref, file, func, line);
+}
+
+static inline struct radeon_bo *_radeon_bo_open(struct radeon_bo_manager *bom,
+ uint32_t handle,
+ uint32_t size,
+ uint32_t alignment,
+ uint32_t domains,
+ uint32_t flags,
+ const char *file,
+ const char *func,
+ int line)
+{
+ struct radeon_bo *bo;
+
+ bo = bom->funcs->bo_open(bom, handle, size, alignment, domains, flags);
+
+#ifdef RADEON_BO_TRACK
+ if (bo) {
+ bo->track = radeon_tracker_add_track(&bom->tracker, bo->handle);
+ radeon_track_add_event(bo->track, file, func, "open", line);
+ }
+#endif
+ return bo;
+}
+
+static inline void _radeon_bo_ref(struct radeon_bo *bo,
+ const char *file,
+ const char *func,
+ int line)
+{
+ bo->cref++;
+#ifdef RADEON_BO_TRACK
+ radeon_track_add_event(bo->track, file, func, "ref", line);
+#endif
+ bo->bom->funcs->bo_ref(bo);
+}
+
+static inline struct radeon_bo *_radeon_bo_unref(struct radeon_bo *bo,
+ const char *file,
+ const char *func,
+ int line)
+{
+ bo->cref--;
+#ifdef RADEON_BO_TRACK
+ radeon_track_add_event(bo->track, file, func, "unref", line);
+ if (bo->cref <= 0) {
+ radeon_tracker_remove_track(&bo->bom->tracker, bo->track);
+ bo->track = NULL;
+ }
+#endif
+ return bo->bom->funcs->bo_unref(bo);
+}
+
+static inline int _radeon_bo_map(struct radeon_bo *bo,
+ int write,
+ const char *file,
+ const char *func,
+ int line)
+{
+ return bo->bom->funcs->bo_map(bo, write);
+}
+
+static inline int _radeon_bo_unmap(struct radeon_bo *bo,
+ const char *file,
+ const char *func,
+ int line)
+{
+ return bo->bom->funcs->bo_unmap(bo);
+}
+
+static inline int _radeon_bo_wait(struct radeon_bo *bo,
+ const char *file,
+ const char *func,
+ int line)
+{
+ return bo->bom->funcs->bo_wait(bo);
+}
+
+static inline int _radeon_bo_is_busy(struct radeon_bo *bo,
+ uint32_t *domain,
+ const char *file,
+ const char *func,
+ int line)
+{
+ return bo->bom->funcs->bo_is_busy(bo, domain);
+}
+
+static inline int radeon_bo_set_tiling(struct radeon_bo *bo,
+ uint32_t tiling_flags, uint32_t pitch)
+{
+ return bo->bom->funcs->bo_set_tiling(bo, tiling_flags, pitch);
+}
+
+static inline int radeon_bo_get_tiling(struct radeon_bo *bo,
+ uint32_t *tiling_flags, uint32_t *pitch)
+{
+ return bo->bom->funcs->bo_get_tiling(bo, tiling_flags, pitch);
+}
+
+static inline int radeon_bo_is_static(struct radeon_bo *bo)
+{
+ if (bo->bom->funcs->bo_is_static)
+ return bo->bom->funcs->bo_is_static(bo);
+ return 0;
+}
+
+#define radeon_bo_open(bom, h, s, a, d, f)\
+ _radeon_bo_open(bom, h, s, a, d, f, __FILE__, __FUNCTION__, __LINE__)
+#define radeon_bo_ref(bo)\
+ _radeon_bo_ref(bo, __FILE__, __FUNCTION__, __LINE__)
+#define radeon_bo_unref(bo)\
+ _radeon_bo_unref(bo, __FILE__, __FUNCTION__, __LINE__)
+#define radeon_bo_map(bo, w)\
+ _radeon_bo_map(bo, w, __FILE__, __FUNCTION__, __LINE__)
+#define radeon_bo_unmap(bo)\
+ _radeon_bo_unmap(bo, __FILE__, __FUNCTION__, __LINE__)
+#define radeon_bo_debug(bo, opcode)\
+ _radeon_bo_debug(bo, opcode, __FILE__, __FUNCTION__, __LINE__)
+#define radeon_bo_wait(bo) \
+ _radeon_bo_wait(bo, __FILE__, __func__, __LINE__)
+#define radeon_bo_is_busy(bo, domain) \
+ _radeon_bo_is_busy(bo, domain, __FILE__, __func__, __LINE__)
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c
new file mode 100644
index 0000000000..3e7547d2f9
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.c
@@ -0,0 +1,926 @@
+/*
+ * Copyright © 2008 Nicolai Haehnle
+ * Copyright © 2008 Dave Airlie
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Aapo Tahkola <aet@rasterburn.org>
+ * Nicolai Haehnle <prefect_@gmx.net>
+ * Dave Airlie
+ * Jérôme Glisse <glisse@freedesktop.org>
+ */
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include "xf86drm.h"
+#include "texmem.h"
+#include "main/simple_list.h"
+
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_common.h"
+#include "radeon_bocs_wrapper.h"
+#include "radeon_macros.h"
+
+/* no seriously texmem.c is this screwed up */
+struct bo_legacy_texture_object {
+ driTextureObject base;
+ struct bo_legacy *parent;
+};
+
+struct bo_legacy {
+ struct radeon_bo base;
+ int map_count;
+ uint32_t pending;
+ int is_pending;
+ int static_bo;
+ uint32_t offset;
+ struct bo_legacy_texture_object *tobj;
+ int validated;
+ int dirty;
+ void *ptr;
+ struct bo_legacy *next, *prev;
+ struct bo_legacy *pnext, *pprev;
+};
+
+struct bo_manager_legacy {
+ struct radeon_bo_manager base;
+ unsigned nhandle;
+ unsigned nfree_handles;
+ unsigned cfree_handles;
+ uint32_t current_age;
+ struct bo_legacy bos;
+ struct bo_legacy pending_bos;
+ uint32_t fb_location;
+ uint32_t texture_offset;
+ unsigned dma_alloc_size;
+ uint32_t dma_buf_count;
+ unsigned cpendings;
+ driTextureObject texture_swapped;
+ driTexHeap *texture_heap;
+ struct radeon_screen *screen;
+ unsigned *free_handles;
+};
+
+static void bo_legacy_tobj_destroy(void *data, driTextureObject *t)
+{
+ struct bo_legacy_texture_object *tobj = (struct bo_legacy_texture_object *)t;
+
+ if (tobj->parent) {
+ tobj->parent->tobj = NULL;
+ tobj->parent->validated = 0;
+ }
+}
+
+static void inline clean_handles(struct bo_manager_legacy *bom)
+{
+ while (bom->cfree_handles > 0 &&
+ !bom->free_handles[bom->cfree_handles - 1])
+ bom->cfree_handles--;
+
+}
+static int legacy_new_handle(struct bo_manager_legacy *bom, uint32_t *handle)
+{
+ uint32_t tmp;
+
+ *handle = 0;
+ if (bom->nhandle == 0xFFFFFFFF) {
+ return -EINVAL;
+ }
+ if (bom->cfree_handles > 0) {
+ tmp = bom->free_handles[--bom->cfree_handles];
+ clean_handles(bom);
+ } else {
+ bom->cfree_handles = 0;
+ tmp = bom->nhandle++;
+ }
+ assert(tmp);
+ *handle = tmp;
+ return 0;
+}
+
+static int legacy_free_handle(struct bo_manager_legacy *bom, uint32_t handle)
+{
+ uint32_t *handles;
+
+ if (!handle) {
+ return 0;
+ }
+ if (handle == (bom->nhandle - 1)) {
+ int i;
+
+ bom->nhandle--;
+ for (i = bom->cfree_handles - 1; i >= 0; i--) {
+ if (bom->free_handles[i] == (bom->nhandle - 1)) {
+ bom->nhandle--;
+ bom->free_handles[i] = 0;
+ }
+ }
+ clean_handles(bom);
+ return 0;
+ }
+ if (bom->cfree_handles < bom->nfree_handles) {
+ bom->free_handles[bom->cfree_handles++] = handle;
+ return 0;
+ }
+ bom->nfree_handles += 0x100;
+ handles = (uint32_t*)realloc(bom->free_handles, bom->nfree_handles * 4);
+ if (handles == NULL) {
+ bom->nfree_handles -= 0x100;
+ return -ENOMEM;
+ }
+ bom->free_handles = handles;
+ bom->free_handles[bom->cfree_handles++] = handle;
+ return 0;
+}
+
+static void legacy_get_current_age(struct bo_manager_legacy *boml)
+{
+ drm_radeon_getparam_t gp;
+ unsigned char *RADEONMMIO = NULL;
+ int r;
+
+ if ( IS_R300_CLASS(boml->screen)
+ || IS_R600_CLASS(boml->screen) )
+ {
+ gp.param = RADEON_PARAM_LAST_CLEAR;
+ gp.value = (int *)&boml->current_age;
+ r = drmCommandWriteRead(boml->base.fd, DRM_RADEON_GETPARAM,
+ &gp, sizeof(gp));
+ if (r) {
+ fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, r);
+ exit(1);
+ }
+ }
+ else {
+ RADEONMMIO = boml->screen->mmio.map;
+ boml->current_age = boml->screen->scratch[3];
+ boml->current_age = INREG(RADEON_GUI_SCRATCH_REG3);
+ }
+}
+
+static int legacy_is_pending(struct radeon_bo *bo)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+
+ if (bo_legacy->is_pending <= 0) {
+ bo_legacy->is_pending = 0;
+ return 0;
+ }
+ if (boml->current_age >= bo_legacy->pending) {
+ if (boml->pending_bos.pprev == bo_legacy) {
+ boml->pending_bos.pprev = bo_legacy->pprev;
+ }
+ bo_legacy->pprev->pnext = bo_legacy->pnext;
+ if (bo_legacy->pnext) {
+ bo_legacy->pnext->pprev = bo_legacy->pprev;
+ }
+ assert(bo_legacy->is_pending <= bo->cref);
+ while (bo_legacy->is_pending--) {
+ bo = radeon_bo_unref(bo);
+ if (!bo)
+ break;
+ }
+ if (bo)
+ bo_legacy->is_pending = 0;
+ boml->cpendings--;
+ return 0;
+ }
+ return 1;
+}
+
+static int legacy_wait_pending(struct radeon_bo *bo)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+
+ if (!bo_legacy->is_pending) {
+ return 0;
+ }
+ /* FIXME: lockup and userspace busy looping that's all the folks */
+ legacy_get_current_age(boml);
+ while (legacy_is_pending(bo)) {
+ usleep(10);
+ legacy_get_current_age(boml);
+ }
+ return 0;
+}
+
+void legacy_track_pending(struct radeon_bo_manager *bom, int debug)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy*) bom;
+ struct bo_legacy *bo_legacy;
+ struct bo_legacy *next;
+
+ legacy_get_current_age(boml);
+ bo_legacy = boml->pending_bos.pnext;
+ while (bo_legacy) {
+ if (debug)
+ fprintf(stderr,"pending %p %d %d %d\n", bo_legacy, bo_legacy->base.size,
+ boml->current_age, bo_legacy->pending);
+ next = bo_legacy->pnext;
+ if (legacy_is_pending(&(bo_legacy->base))) {
+ }
+ bo_legacy = next;
+ }
+}
+
+static int legacy_wait_any_pending(struct bo_manager_legacy *boml)
+{
+ struct bo_legacy *bo_legacy;
+
+ legacy_get_current_age(boml);
+ bo_legacy = boml->pending_bos.pnext;
+ if (!bo_legacy)
+ return -1;
+ legacy_wait_pending(&bo_legacy->base);
+ return 0;
+}
+
+static void legacy_kick_all_buffers(struct bo_manager_legacy *boml)
+{
+ struct bo_legacy *legacy;
+
+ legacy = boml->bos.next;
+ while (legacy != &boml->bos) {
+ if (legacy->tobj) {
+ if (legacy->validated) {
+ driDestroyTextureObject(&legacy->tobj->base);
+ legacy->tobj = 0;
+ legacy->validated = 0;
+ }
+ }
+ legacy = legacy->next;
+ }
+}
+
+static struct bo_legacy *bo_allocate(struct bo_manager_legacy *boml,
+ uint32_t size,
+ uint32_t alignment,
+ uint32_t domains,
+ uint32_t flags)
+{
+ struct bo_legacy *bo_legacy;
+ static int pgsize;
+
+ if (pgsize == 0)
+ pgsize = getpagesize() - 1;
+
+ size = (size + pgsize) & ~pgsize;
+
+ bo_legacy = (struct bo_legacy*)calloc(1, sizeof(struct bo_legacy));
+ if (bo_legacy == NULL) {
+ return NULL;
+ }
+ bo_legacy->base.bom = (struct radeon_bo_manager*)boml;
+ bo_legacy->base.handle = 0;
+ bo_legacy->base.size = size;
+ bo_legacy->base.alignment = alignment;
+ bo_legacy->base.domains = domains;
+ bo_legacy->base.flags = flags;
+ bo_legacy->base.ptr = NULL;
+ bo_legacy->map_count = 0;
+ bo_legacy->next = NULL;
+ bo_legacy->prev = NULL;
+ bo_legacy->pnext = NULL;
+ bo_legacy->pprev = NULL;
+ bo_legacy->next = boml->bos.next;
+ bo_legacy->prev = &boml->bos;
+ boml->bos.next = bo_legacy;
+ if (bo_legacy->next) {
+ bo_legacy->next->prev = bo_legacy;
+ }
+
+ return bo_legacy;
+}
+
+static int bo_dma_alloc(struct radeon_bo *bo)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+ drm_radeon_mem_alloc_t alloc;
+ unsigned size;
+ int base_offset;
+ int r;
+
+ /* align size on 4Kb */
+ size = (((4 * 1024) - 1) + bo->size) & ~((4 * 1024) - 1);
+ alloc.region = RADEON_MEM_REGION_GART;
+ alloc.alignment = bo_legacy->base.alignment;
+ alloc.size = size;
+ alloc.region_offset = &base_offset;
+ r = drmCommandWriteRead(bo->bom->fd,
+ DRM_RADEON_ALLOC,
+ &alloc,
+ sizeof(alloc));
+ if (r) {
+ /* ptr is set to NULL if dma allocation failed */
+ bo_legacy->ptr = NULL;
+ return r;
+ }
+ bo_legacy->ptr = boml->screen->gartTextures.map + base_offset;
+ bo_legacy->offset = boml->screen->gart_texture_offset + base_offset;
+ bo->size = size;
+ boml->dma_alloc_size += size;
+ boml->dma_buf_count++;
+ return 0;
+}
+
+static int bo_dma_free(struct radeon_bo *bo)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+ drm_radeon_mem_free_t memfree;
+ int r;
+
+ if (bo_legacy->ptr == NULL) {
+ /* ptr is set to NULL if dma allocation failed */
+ return 0;
+ }
+ legacy_get_current_age(boml);
+ memfree.region = RADEON_MEM_REGION_GART;
+ memfree.region_offset = bo_legacy->offset;
+ memfree.region_offset -= boml->screen->gart_texture_offset;
+ r = drmCommandWrite(boml->base.fd,
+ DRM_RADEON_FREE,
+ &memfree,
+ sizeof(memfree));
+ if (r) {
+ fprintf(stderr, "Failed to free bo[%p] at %08x\n",
+ &bo_legacy->base, memfree.region_offset);
+ fprintf(stderr, "ret = %s\n", strerror(-r));
+ return r;
+ }
+ boml->dma_alloc_size -= bo_legacy->base.size;
+ boml->dma_buf_count--;
+ return 0;
+}
+
+static void bo_free(struct bo_legacy *bo_legacy)
+{
+ struct bo_manager_legacy *boml;
+
+ if (bo_legacy == NULL) {
+ return;
+ }
+ boml = (struct bo_manager_legacy *)bo_legacy->base.bom;
+ bo_legacy->prev->next = bo_legacy->next;
+ if (bo_legacy->next) {
+ bo_legacy->next->prev = bo_legacy->prev;
+ }
+ if (!bo_legacy->static_bo) {
+ legacy_free_handle(boml, bo_legacy->base.handle);
+ if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT) {
+ /* dma buffers */
+ bo_dma_free(&bo_legacy->base);
+ } else {
+ driDestroyTextureObject(&bo_legacy->tobj->base);
+ bo_legacy->tobj = NULL;
+ /* free backing store */
+ free(bo_legacy->ptr);
+ }
+ }
+ memset(bo_legacy, 0 , sizeof(struct bo_legacy));
+ free(bo_legacy);
+}
+
+static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
+ uint32_t handle,
+ uint32_t size,
+ uint32_t alignment,
+ uint32_t domains,
+ uint32_t flags)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
+ struct bo_legacy *bo_legacy;
+ int r;
+
+ if (handle) {
+ bo_legacy = boml->bos.next;
+ while (bo_legacy) {
+ if (bo_legacy->base.handle == handle) {
+ radeon_bo_ref(&(bo_legacy->base));
+ return (struct radeon_bo*)bo_legacy;
+ }
+ bo_legacy = bo_legacy->next;
+ }
+ return NULL;
+ }
+ bo_legacy = bo_allocate(boml, size, alignment, domains, flags);
+ bo_legacy->static_bo = 0;
+ r = legacy_new_handle(boml, &bo_legacy->base.handle);
+ if (r) {
+ bo_free(bo_legacy);
+ return NULL;
+ }
+ if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT)
+ {
+retry:
+ legacy_track_pending(&boml->base, 0);
+ /* dma buffers */
+
+ r = bo_dma_alloc(&(bo_legacy->base));
+ if (r)
+ {
+ if (legacy_wait_any_pending(boml) == -1)
+ {
+ bo_free(bo_legacy);
+ return NULL;
+ }
+ goto retry;
+ return NULL;
+ }
+ }
+ else
+ {
+ bo_legacy->ptr = malloc(bo_legacy->base.size);
+ if (bo_legacy->ptr == NULL) {
+ bo_free(bo_legacy);
+ return NULL;
+ }
+ }
+ radeon_bo_ref(&(bo_legacy->base));
+
+ return (struct radeon_bo*)bo_legacy;
+}
+
+static void bo_ref(struct radeon_bo *bo)
+{
+}
+
+static struct radeon_bo *bo_unref(struct radeon_bo *bo)
+{
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+
+ if (bo->cref <= 0) {
+ bo_legacy->prev->next = bo_legacy->next;
+ if (bo_legacy->next) {
+ bo_legacy->next->prev = bo_legacy->prev;
+ }
+ if (!bo_legacy->is_pending) {
+ bo_free(bo_legacy);
+ }
+ return NULL;
+ }
+ return bo;
+}
+
+static int bo_map(struct radeon_bo *bo, int write)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+
+ legacy_wait_pending(bo);
+ bo_legacy->validated = 0;
+ bo_legacy->dirty = 1;
+ bo_legacy->map_count++;
+ bo->ptr = bo_legacy->ptr;
+ /* Read the first pixel in the frame buffer. This should
+ * be a noop, right? In fact without this conform fails as reading
+ * from the framebuffer sometimes produces old results -- the
+ * on-card read cache gets mixed up and doesn't notice that the
+ * framebuffer has been updated.
+ *
+ * Note that we should probably be reading some otherwise unused
+ * region of VRAM, otherwise we might get incorrect results when
+ * reading pixels from the top left of the screen.
+ *
+ * I found this problem on an R420 with glean's texCube test.
+ * Note that the R200 span code also *writes* the first pixel in the
+ * framebuffer, but I've found this to be unnecessary.
+ * -- Nicolai Hähnle, June 2008
+ */
+ if (!(bo->domains & RADEON_GEM_DOMAIN_GTT)) {
+ int p;
+ volatile int *buf = (int*)boml->screen->driScreen->pFB;
+ p = *buf;
+ }
+
+ return 0;
+}
+
+static int bo_unmap(struct radeon_bo *bo)
+{
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+
+ if (--bo_legacy->map_count > 0)
+ {
+ return 0;
+ }
+
+ bo->ptr = NULL;
+
+ return 0;
+}
+
+static int bo_is_busy(struct radeon_bo *bo, uint32_t *domain)
+{
+ *domain = 0;
+ if (bo->domains & RADEON_GEM_DOMAIN_GTT)
+ *domain = RADEON_GEM_DOMAIN_GTT;
+ else
+ *domain = RADEON_GEM_DOMAIN_CPU;
+ if (legacy_is_pending(bo))
+ return -EBUSY;
+ else
+ return 0;
+}
+
+static int bo_is_static(struct radeon_bo *bo)
+{
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+ return bo_legacy->static_bo;
+}
+
+static struct radeon_bo_funcs bo_legacy_funcs = {
+ bo_open,
+ bo_ref,
+ bo_unref,
+ bo_map,
+ bo_unmap,
+ NULL,
+ bo_is_static,
+ NULL,
+ NULL,
+ bo_is_busy
+};
+
+static int bo_vram_validate(struct radeon_bo *bo,
+ uint32_t *soffset,
+ uint32_t *eoffset)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+ int r;
+ int retry_count = 0, pending_retry = 0;
+
+ if (!bo_legacy->tobj) {
+ bo_legacy->tobj = CALLOC(sizeof(struct bo_legacy_texture_object));
+ bo_legacy->tobj->parent = bo_legacy;
+ make_empty_list(&bo_legacy->tobj->base);
+ bo_legacy->tobj->base.totalSize = bo->size;
+ retry:
+ r = driAllocateTexture(&boml->texture_heap, 1,
+ &bo_legacy->tobj->base);
+ if (r) {
+ pending_retry = 0;
+ while(boml->cpendings && pending_retry++ < 10000) {
+ legacy_track_pending(&boml->base, 0);
+ retry_count++;
+ if (retry_count > 2) {
+ free(bo_legacy->tobj);
+ bo_legacy->tobj = NULL;
+ fprintf(stderr, "Ouch! vram_validate failed %d\n", r);
+ return -1;
+ }
+ goto retry;
+ }
+ }
+ bo_legacy->offset = boml->texture_offset +
+ bo_legacy->tobj->base.memBlock->ofs;
+ bo_legacy->dirty = 1;
+ }
+
+ assert(bo_legacy->tobj->base.memBlock);
+
+ if (bo_legacy->tobj)
+ driUpdateTextureLRU(&bo_legacy->tobj->base);
+
+ if (bo_legacy->dirty || bo_legacy->tobj->base.dirty_images[0]) {
+ if (IS_R600_CLASS(boml->screen)) {
+ drm_radeon_texture_t tex;
+ drm_radeon_tex_image_t tmp;
+ int ret;
+
+ tex.offset = bo_legacy->offset;
+ tex.image = &tmp;
+ assert(!(tex.offset & 1023));
+
+ tmp.x = 0;
+ tmp.y = 0;
+ tmp.width = bo->size;
+ tmp.height = 1;
+ tmp.data = bo_legacy->ptr;
+ tex.format = RADEON_TXFORMAT_ARGB8888;
+ tex.width = tmp.width;
+ tex.height = tmp.height;
+ tex.pitch = bo->size;
+ do {
+ ret = drmCommandWriteRead(bo->bom->fd,
+ DRM_RADEON_TEXTURE,
+ &tex,
+ sizeof(drm_radeon_texture_t));
+ if (ret) {
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n");
+ usleep(1);
+ }
+ } while (ret == -EAGAIN);
+ } else {
+ /* Copy to VRAM using a blit.
+ * All memory is 4K aligned. We're using 1024 pixels wide blits.
+ */
+ drm_radeon_texture_t tex;
+ drm_radeon_tex_image_t tmp;
+ int ret;
+
+ tex.offset = bo_legacy->offset;
+ tex.image = &tmp;
+ assert(!(tex.offset & 1023));
+
+ tmp.x = 0;
+ tmp.y = 0;
+ if (bo->size < 4096) {
+ tmp.width = (bo->size + 3) / 4;
+ tmp.height = 1;
+ } else {
+ tmp.width = 1024;
+ tmp.height = (bo->size + 4095) / 4096;
+ }
+ tmp.data = bo_legacy->ptr;
+ tex.format = RADEON_TXFORMAT_ARGB8888;
+ tex.width = tmp.width;
+ tex.height = tmp.height;
+ tex.pitch = MAX2(tmp.width / 16, 1);
+ do {
+ ret = drmCommandWriteRead(bo->bom->fd,
+ DRM_RADEON_TEXTURE,
+ &tex,
+ sizeof(drm_radeon_texture_t));
+ if (ret) {
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n");
+ usleep(1);
+ }
+ } while (ret == -EAGAIN);
+ }
+ bo_legacy->dirty = 0;
+ bo_legacy->tobj->base.dirty_images[0] = 0;
+ }
+ return 0;
+}
+
+/*
+ * radeon_bo_legacy_validate -
+ * returns:
+ * 0 - all good
+ * -EINVAL - mapped buffer can't be validated
+ * -EAGAIN - restart validation we've kicked all the buffers out
+ */
+int radeon_bo_legacy_validate(struct radeon_bo *bo,
+ uint32_t *soffset,
+ uint32_t *eoffset)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+ int r;
+ int retries = 0;
+
+ if (bo_legacy->map_count) {
+ fprintf(stderr, "bo(%p, %d) is mapped (%d) can't valide it.\n",
+ bo, bo->size, bo_legacy->map_count);
+ return -EINVAL;
+ }
+ if (bo_legacy->static_bo || bo_legacy->validated) {
+ *soffset = bo_legacy->offset;
+ *eoffset = bo_legacy->offset + bo->size;
+
+ return 0;
+ }
+ if (!(bo->domains & RADEON_GEM_DOMAIN_GTT)) {
+
+ r = bo_vram_validate(bo, soffset, eoffset);
+ if (r) {
+ legacy_track_pending(&boml->base, 0);
+ legacy_kick_all_buffers(boml);
+ retries++;
+ if (retries == 2) {
+ fprintf(stderr,"legacy bo: failed to get relocations into aperture\n");
+ assert(0);
+ exit(-1);
+ }
+ return -EAGAIN;
+ }
+ }
+ *soffset = bo_legacy->offset;
+ *eoffset = bo_legacy->offset + bo->size;
+ bo_legacy->validated = 1;
+
+ return 0;
+}
+
+void radeon_bo_legacy_pending(struct radeon_bo *bo, uint32_t pending)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bo->bom;
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+
+ bo_legacy->pending = pending;
+ bo_legacy->is_pending++;
+ /* add to pending list */
+ radeon_bo_ref(bo);
+ if (bo_legacy->is_pending > 1) {
+ return;
+ }
+ bo_legacy->pprev = boml->pending_bos.pprev;
+ bo_legacy->pnext = NULL;
+ bo_legacy->pprev->pnext = bo_legacy;
+ boml->pending_bos.pprev = bo_legacy;
+ boml->cpendings++;
+}
+
+void radeon_bo_manager_legacy_dtor(struct radeon_bo_manager *bom)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
+ struct bo_legacy *bo_legacy;
+
+ if (bom == NULL) {
+ return;
+ }
+ bo_legacy = boml->bos.next;
+ while (bo_legacy) {
+ struct bo_legacy *next;
+
+ next = bo_legacy->next;
+ bo_free(bo_legacy);
+ bo_legacy = next;
+ }
+ driDestroyTextureHeap(boml->texture_heap);
+ free(boml->free_handles);
+ free(boml);
+}
+
+static struct bo_legacy *radeon_legacy_bo_alloc_static(struct bo_manager_legacy *bom,
+ int size,
+ uint32_t offset)
+{
+ struct bo_legacy *bo;
+
+ bo = bo_allocate(bom, size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+ if (bo == NULL)
+ return NULL;
+ bo->static_bo = 1;
+ bo->offset = offset + bom->fb_location;
+ bo->base.handle = bo->offset;
+ bo->ptr = bom->screen->driScreen->pFB + offset;
+ if (bo->base.handle > bom->nhandle) {
+ bom->nhandle = bo->base.handle + 1;
+ }
+ radeon_bo_ref(&(bo->base));
+ return bo;
+}
+
+struct radeon_bo_manager *radeon_bo_manager_legacy_ctor(struct radeon_screen *scrn)
+{
+ struct bo_manager_legacy *bom;
+ struct bo_legacy *bo;
+ unsigned size;
+
+ bom = (struct bo_manager_legacy*)
+ calloc(1, sizeof(struct bo_manager_legacy));
+ if (bom == NULL) {
+ return NULL;
+ }
+
+ make_empty_list(&bom->texture_swapped);
+
+ bom->texture_heap = driCreateTextureHeap(0,
+ bom,
+ scrn->texSize[0],
+ 12,
+ RADEON_NR_TEX_REGIONS,
+ (drmTextureRegionPtr)scrn->sarea->tex_list[0],
+ &scrn->sarea->tex_age[0],
+ &bom->texture_swapped,
+ sizeof(struct bo_legacy_texture_object),
+ &bo_legacy_tobj_destroy);
+ bom->texture_offset = scrn->texOffset[0];
+
+ bom->base.funcs = &bo_legacy_funcs;
+ bom->base.fd = scrn->driScreen->fd;
+ bom->bos.next = NULL;
+ bom->bos.prev = NULL;
+ bom->pending_bos.pprev = &bom->pending_bos;
+ bom->pending_bos.pnext = NULL;
+ bom->screen = scrn;
+ bom->fb_location = scrn->fbLocation;
+ bom->nhandle = 1;
+ bom->cfree_handles = 0;
+ bom->nfree_handles = 0x400;
+ bom->free_handles = (uint32_t*)malloc(bom->nfree_handles * 4);
+ if (bom->free_handles == NULL) {
+ radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
+ return NULL;
+ }
+
+ /* biggest framebuffer size */
+ size = 4096*4096*4;
+
+ /* allocate front */
+ bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->frontOffset);
+
+ if (!bo) {
+ radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
+ return NULL;
+ }
+ if (scrn->sarea->tiling_enabled) {
+ bo->base.flags = RADEON_BO_FLAGS_MACRO_TILE;
+ }
+
+ /* allocate back */
+ bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->backOffset);
+
+ if (!bo) {
+ radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
+ return NULL;
+ }
+ if (scrn->sarea->tiling_enabled) {
+ bo->base.flags = RADEON_BO_FLAGS_MACRO_TILE;
+ }
+
+ /* allocate depth */
+ bo = radeon_legacy_bo_alloc_static(bom, size, bom->screen->depthOffset);
+
+ if (!bo) {
+ radeon_bo_manager_legacy_dtor((struct radeon_bo_manager*)bom);
+ return NULL;
+ }
+ bo->base.flags = 0;
+ if (scrn->sarea->tiling_enabled) {
+ bo->base.flags |= RADEON_BO_FLAGS_MACRO_TILE;
+ bo->base.flags |= RADEON_BO_FLAGS_MICRO_TILE;
+ }
+ return (struct radeon_bo_manager*)bom;
+}
+
+void radeon_bo_legacy_texture_age(struct radeon_bo_manager *bom)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
+ DRI_AGE_TEXTURES(boml->texture_heap);
+}
+
+unsigned radeon_bo_legacy_relocs_size(struct radeon_bo *bo)
+{
+ struct bo_legacy *bo_legacy = (struct bo_legacy*)bo;
+
+ if (bo_legacy->static_bo || (bo->domains & RADEON_GEM_DOMAIN_GTT)) {
+ return 0;
+ }
+ return bo->size;
+}
+
+/*
+ * Fake up a bo for things like texture image_override.
+ * bo->offset already includes fb_location
+ */
+struct radeon_bo *radeon_legacy_bo_alloc_fake(struct radeon_bo_manager *bom,
+ int size,
+ uint32_t offset)
+{
+ struct bo_manager_legacy *boml = (struct bo_manager_legacy *)bom;
+ struct bo_legacy *bo;
+
+ bo = bo_allocate(boml, size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+ if (bo == NULL)
+ return NULL;
+ bo->static_bo = 1;
+ bo->offset = offset;
+ bo->base.handle = bo->offset;
+ bo->ptr = boml->screen->driScreen->pFB + (offset - boml->fb_location);
+ if (bo->base.handle > boml->nhandle) {
+ boml->nhandle = bo->base.handle + 1;
+ }
+ radeon_bo_ref(&(bo->base));
+ return &(bo->base);
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_bo_legacy.h b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.h
new file mode 100644
index 0000000000..2cf15dfaff
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_bo_legacy.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2008 Nicolai Haehnle
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Aapo Tahkola <aet@rasterburn.org>
+ * Nicolai Haehnle <prefect_@gmx.net>
+ * Jérôme Glisse <glisse@freedesktop.org>
+ */
+#ifndef RADEON_BO_LEGACY_H
+#define RADEON_BO_LEGACY_H
+
+#include "radeon_screen.h"
+
+void radeon_bo_legacy_pending(struct radeon_bo *bo, uint32_t pending);
+int radeon_bo_legacy_validate(struct radeon_bo *bo,
+ uint32_t *soffset,
+ uint32_t *eoffset);
+struct radeon_bo_manager *radeon_bo_manager_legacy_ctor(struct radeon_screen *scrn);
+void radeon_bo_manager_legacy_dtor(struct radeon_bo_manager *bom);
+void radeon_bo_legacy_texture_age(struct radeon_bo_manager *bom);
+unsigned radeon_bo_legacy_relocs_size(struct radeon_bo *bo);
+struct radeon_bo *radeon_legacy_bo_alloc_fake(struct radeon_bo_manager *bom,
+ int size,
+ uint32_t offset);
+void legacy_track_pending(struct radeon_bo_manager *bom, int debug);
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_bocs_wrapper.h b/src/mesa/drivers/dri/radeon/radeon_bocs_wrapper.h
new file mode 100644
index 0000000000..4520a7d7d4
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_bocs_wrapper.h
@@ -0,0 +1,99 @@
+#ifndef RADEON_CS_WRAPPER_H
+#define RADEON_CS_WRAPPER_H
+
+#ifdef HAVE_LIBDRM_RADEON
+
+#include "radeon_bo.h"
+#include "radeon_bo_gem.h"
+#include "radeon_cs.h"
+#include "radeon_cs_gem.h"
+
+#else
+#include <stdint.h>
+
+#define RADEON_GEM_DOMAIN_CPU 0x1 // Cached CPU domain
+#define RADEON_GEM_DOMAIN_GTT 0x2 // GTT or cache flushed
+#define RADEON_GEM_DOMAIN_VRAM 0x4 // VRAM domain
+
+#define RADEON_TILING_MACRO 0x1
+#define RADEON_TILING_MICRO 0x2
+#define RADEON_TILING_SWAP 0x4
+#define RADEON_TILING_SURFACE 0x8 /* this object requires a surface
+ * when mapped - i.e. front buffer */
+
+/* to be used to build locally in mesa with no libdrm bits */
+#include "../radeon/radeon_bo_drm.h"
+#include "../radeon/radeon_cs_drm.h"
+
+#ifndef DRM_RADEON_GEM_INFO
+#define DRM_RADEON_GEM_INFO 0x1c
+
+struct drm_radeon_gem_info {
+ uint64_t gart_size;
+ uint64_t vram_size;
+ uint64_t vram_visible;
+};
+
+struct drm_radeon_info {
+ uint32_t request;
+ uint32_t pad;
+ uint32_t value;
+};
+#endif
+
+#ifndef RADEON_PARAM_DEVICE_ID
+#define RADEON_PARAM_DEVICE_ID 16
+#endif
+
+#ifndef RADEON_PARAM_NUM_Z_PIPES
+#define RADEON_PARAM_NUM_Z_PIPES 17
+#endif
+
+#ifndef RADEON_INFO_DEVICE_ID
+#define RADEON_INFO_DEVICE_ID 0
+#endif
+#ifndef RADEON_INFO_NUM_GB_PIPES
+#define RADEON_INFO_NUM_GB_PIPES 0
+#endif
+
+#ifndef RADEON_INFO_NUM_Z_PIPES
+#define RADEON_INFO_NUM_Z_PIPES 0
+#endif
+
+#ifndef DRM_RADEON_INFO
+#define DRM_RADEON_INFO 0x1
+#endif
+
+
+static inline uint32_t radeon_gem_name_bo(struct radeon_bo *dummy)
+{
+ return 0;
+}
+
+static inline void *radeon_bo_manager_gem_ctor(int fd)
+{
+ return NULL;
+}
+
+static inline void radeon_bo_manager_gem_dtor(void *dummy)
+{
+}
+
+static inline void *radeon_cs_manager_gem_ctor(int fd)
+{
+ return NULL;
+}
+
+static inline void radeon_cs_manager_gem_dtor(void *dummy)
+{
+}
+
+static inline void radeon_tracker_print(void *ptr, int io)
+{
+}
+#endif
+
+#include "radeon_bo_legacy.h"
+#include "radeon_cs_legacy.h"
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_buffer_objects.c b/src/mesa/drivers/dri/radeon/radeon_buffer_objects.c
new file mode 100644
index 0000000000..a24b6dac26
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_buffer_objects.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "radeon_buffer_objects.h"
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/bufferobj.h"
+
+#include "radeon_common.h"
+
+struct radeon_buffer_object *
+get_radeon_buffer_object(struct gl_buffer_object *obj)
+{
+ return (struct radeon_buffer_object *) obj;
+}
+
+static struct gl_buffer_object *
+radeonNewBufferObject(GLcontext * ctx,
+ GLuint name,
+ GLenum target)
+{
+ struct radeon_buffer_object *obj = CALLOC_STRUCT(radeon_buffer_object);
+
+ _mesa_initialize_buffer_object(&obj->Base, name, target);
+
+ obj->bo = NULL;
+
+ return &obj->Base;
+}
+
+/**
+ * Called via glDeleteBuffersARB().
+ */
+static void
+radeonDeleteBufferObject(GLcontext * ctx,
+ struct gl_buffer_object *obj)
+{
+ struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
+
+ if (obj->Pointer) {
+ radeon_bo_unmap(radeon_obj->bo);
+ }
+
+ if (radeon_obj->bo) {
+ radeon_bo_unref(radeon_obj->bo);
+ }
+
+ _mesa_free(radeon_obj);
+}
+
+
+/**
+ * Allocate space for and store data in a buffer object. Any data that was
+ * previously stored in the buffer object is lost. If data is NULL,
+ * memory will be allocated, but no copy will occur.
+ * Called via ctx->Driver.BufferData().
+ * \return GL_TRUE for success, GL_FALSE if out of memory
+ */
+static GLboolean
+radeonBufferData(GLcontext * ctx,
+ GLenum target,
+ GLsizeiptrARB size,
+ const GLvoid * data,
+ GLenum usage,
+ struct gl_buffer_object *obj)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
+
+ radeon_obj->Base.Size = size;
+ radeon_obj->Base.Usage = usage;
+
+ if (radeon_obj->bo != NULL) {
+ radeon_bo_unref(radeon_obj->bo);
+ radeon_obj->bo = NULL;
+ }
+
+ if (size != 0) {
+ radeon_obj->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ 0,
+ size,
+ 32,
+ RADEON_GEM_DOMAIN_GTT,
+ 0);
+
+ if (!radeon_obj->bo)
+ return GL_FALSE;
+
+ if (data != NULL) {
+ radeon_bo_map(radeon_obj->bo, GL_TRUE);
+
+ _mesa_memcpy(radeon_obj->bo->ptr, data, size);
+
+ radeon_bo_unmap(radeon_obj->bo);
+ }
+ }
+ return GL_TRUE;
+}
+
+/**
+ * Replace data in a subrange of buffer object. If the data range
+ * specified by size + offset extends beyond the end of the buffer or
+ * if data is NULL, no copy is performed.
+ * Called via glBufferSubDataARB().
+ */
+static void
+radeonBufferSubData(GLcontext * ctx,
+ GLenum target,
+ GLintptrARB offset,
+ GLsizeiptrARB size,
+ const GLvoid * data,
+ struct gl_buffer_object *obj)
+{
+ struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
+
+ radeon_bo_map(radeon_obj->bo, GL_TRUE);
+
+ _mesa_memcpy(radeon_obj->bo->ptr + offset, data, size);
+
+ radeon_bo_unmap(radeon_obj->bo);
+}
+
+/**
+ * Called via glGetBufferSubDataARB()
+ */
+static void
+radeonGetBufferSubData(GLcontext * ctx,
+ GLenum target,
+ GLintptrARB offset,
+ GLsizeiptrARB size,
+ GLvoid * data,
+ struct gl_buffer_object *obj)
+{
+ struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
+
+ radeon_bo_map(radeon_obj->bo, GL_FALSE);
+
+ _mesa_memcpy(data, radeon_obj->bo->ptr + offset, size);
+
+ radeon_bo_unmap(radeon_obj->bo);
+}
+
+/**
+ * Called via glMapBufferARB()
+ */
+static void *
+radeonMapBuffer(GLcontext * ctx,
+ GLenum target,
+ GLenum access,
+ struct gl_buffer_object *obj)
+{
+ struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
+
+ if (access == GL_WRITE_ONLY_ARB) {
+ ctx->Driver.Flush(ctx);
+ }
+
+ if (radeon_obj->bo == NULL) {
+ obj->Pointer = NULL;
+ return NULL;
+ }
+
+ radeon_bo_map(radeon_obj->bo, access == GL_WRITE_ONLY_ARB);
+
+ return obj->Pointer = radeon_obj->bo->ptr;
+}
+
+
+/**
+ * Called via glUnmapBufferARB()
+ */
+static GLboolean
+radeonUnmapBuffer(GLcontext * ctx,
+ GLenum target,
+ struct gl_buffer_object *obj)
+{
+ struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
+
+ if (radeon_obj->bo != NULL) {
+ radeon_bo_unmap(radeon_obj->bo);
+ obj->Pointer = NULL;
+ }
+
+ return GL_TRUE;
+}
+
+void
+radeonInitBufferObjectFuncs(struct dd_function_table *functions)
+{
+ functions->NewBufferObject = radeonNewBufferObject;
+ functions->DeleteBuffer = radeonDeleteBufferObject;
+ functions->BufferData = radeonBufferData;
+ functions->BufferSubData = radeonBufferSubData;
+ functions->GetBufferSubData = radeonGetBufferSubData;
+ functions->MapBuffer = radeonMapBuffer;
+ functions->UnmapBuffer = radeonUnmapBuffer;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_buffer_objects.h b/src/mesa/drivers/dri/radeon/radeon_buffer_objects.h
new file mode 100644
index 0000000000..d681960825
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_buffer_objects.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef RADEON_BUFFER_OBJECTS_H
+#define RADEON_BUFFER_OBJECTS_H
+
+#include "main/mtypes.h"
+
+struct radeon_bo;
+
+/**
+ * Radeon vertex/pixel buffer object, derived from Mesa's gl_buffer_object.
+ */
+struct radeon_buffer_object
+{
+ struct gl_buffer_object Base;
+ struct radeon_bo *bo;
+};
+
+struct radeon_buffer_object *
+get_radeon_buffer_object(struct gl_buffer_object *obj);
+
+/**
+ * Hook the bufferobject implementation into mesa:
+ */
+void radeonInitBufferObjectFuncs(struct dd_function_table *functions);
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_chipset.h b/src/mesa/drivers/dri/radeon/radeon_chipset.h
index 55a73eab20..46a9cd5ff8 100644
--- a/src/mesa/drivers/dri/radeon/radeon_chipset.h
+++ b/src/mesa/drivers/dri/radeon/radeon_chipset.h
@@ -247,11 +247,153 @@
#define PCI_CHIP_RS350_7835 0x7835
#define PCI_CHIP_RS690_791E 0x791E
#define PCI_CHIP_RS690_791F 0x791F
+#define PCI_CHIP_RS600_793F 0x793F
+#define PCI_CHIP_RS600_7941 0x7941
+#define PCI_CHIP_RS600_7942 0x7942
#define PCI_CHIP_RS740_796C 0x796C
#define PCI_CHIP_RS740_796D 0x796D
#define PCI_CHIP_RS740_796E 0x796E
#define PCI_CHIP_RS740_796F 0x796F
+#define PCI_CHIP_R600_9400 0x9400
+#define PCI_CHIP_R600_9401 0x9401
+#define PCI_CHIP_R600_9402 0x9402
+#define PCI_CHIP_R600_9403 0x9403
+#define PCI_CHIP_R600_9405 0x9405
+#define PCI_CHIP_R600_940A 0x940A
+#define PCI_CHIP_R600_940B 0x940B
+#define PCI_CHIP_R600_940F 0x940F
+
+#define PCI_CHIP_RV610_94C0 0x94C0
+#define PCI_CHIP_RV610_94C1 0x94C1
+#define PCI_CHIP_RV610_94C3 0x94C3
+#define PCI_CHIP_RV610_94C4 0x94C4
+#define PCI_CHIP_RV610_94C5 0x94C5
+#define PCI_CHIP_RV610_94C6 0x94C6
+#define PCI_CHIP_RV610_94C7 0x94C7
+#define PCI_CHIP_RV610_94C8 0x94C8
+#define PCI_CHIP_RV610_94C9 0x94C9
+#define PCI_CHIP_RV610_94CB 0x94CB
+#define PCI_CHIP_RV610_94CC 0x94CC
+#define PCI_CHIP_RV610_94CD 0x94CD
+
+#define PCI_CHIP_RV630_9580 0x9580
+#define PCI_CHIP_RV630_9581 0x9581
+#define PCI_CHIP_RV630_9583 0x9583
+#define PCI_CHIP_RV630_9586 0x9586
+#define PCI_CHIP_RV630_9587 0x9587
+#define PCI_CHIP_RV630_9588 0x9588
+#define PCI_CHIP_RV630_9589 0x9589
+#define PCI_CHIP_RV630_958A 0x958A
+#define PCI_CHIP_RV630_958B 0x958B
+#define PCI_CHIP_RV630_958C 0x958C
+#define PCI_CHIP_RV630_958D 0x958D
+#define PCI_CHIP_RV630_958E 0x958E
+#define PCI_CHIP_RV630_958F 0x958F
+
+#define PCI_CHIP_RV670_9500 0x9500
+#define PCI_CHIP_RV670_9501 0x9501
+#define PCI_CHIP_RV670_9504 0x9504
+#define PCI_CHIP_RV670_9505 0x9505
+#define PCI_CHIP_RV670_9506 0x9506
+#define PCI_CHIP_RV670_9507 0x9507
+#define PCI_CHIP_RV670_9508 0x9508
+#define PCI_CHIP_RV670_9509 0x9509
+#define PCI_CHIP_RV670_950F 0x950F
+#define PCI_CHIP_RV670_9511 0x9511
+#define PCI_CHIP_RV670_9515 0x9515
+#define PCI_CHIP_RV670_9517 0x9517
+#define PCI_CHIP_RV670_9519 0x9519
+
+#define PCI_CHIP_RV620_95C0 0x95C0
+#define PCI_CHIP_RV620_95C2 0x95C2
+#define PCI_CHIP_RV620_95C4 0x95C4
+#define PCI_CHIP_RV620_95C5 0x95C5
+#define PCI_CHIP_RV620_95C6 0x95C6
+#define PCI_CHIP_RV620_95C7 0x95C7
+#define PCI_CHIP_RV620_95C9 0x95C9
+#define PCI_CHIP_RV620_95CC 0x95CC
+#define PCI_CHIP_RV620_95CD 0x95CD
+#define PCI_CHIP_RV620_95CE 0x95CE
+#define PCI_CHIP_RV620_95CF 0x95CF
+
+#define PCI_CHIP_RV635_9590 0x9590
+#define PCI_CHIP_RV635_9591 0x9591
+#define PCI_CHIP_RV635_9593 0x9593
+#define PCI_CHIP_RV635_9595 0x9595
+#define PCI_CHIP_RV635_9596 0x9596
+#define PCI_CHIP_RV635_9597 0x9597
+#define PCI_CHIP_RV635_9598 0x9598
+#define PCI_CHIP_RV635_9599 0x9599
+#define PCI_CHIP_RV635_959B 0x959B
+
+#define PCI_CHIP_RS780_9610 0x9610
+#define PCI_CHIP_RS780_9611 0x9611
+#define PCI_CHIP_RS780_9612 0x9612
+#define PCI_CHIP_RS780_9613 0x9613
+#define PCI_CHIP_RS780_9614 0x9614
+#define PCI_CHIP_RS780_9615 0x9615
+#define PCI_CHIP_RS780_9616 0x9616
+
+#define PCI_CHIP_RS880_9710 0x9710
+#define PCI_CHIP_RS880_9711 0x9711
+#define PCI_CHIP_RS880_9712 0x9712
+#define PCI_CHIP_RS880_9713 0x9713
+#define PCI_CHIP_RS880_9714 0x9714
+
+#define PCI_CHIP_RV770_9440 0x9440
+#define PCI_CHIP_RV770_9441 0x9441
+#define PCI_CHIP_RV770_9442 0x9442
+#define PCI_CHIP_RV770_9443 0x9443
+#define PCI_CHIP_RV770_9444 0x9444
+#define PCI_CHIP_RV770_9446 0x9446
+#define PCI_CHIP_RV770_944A 0x944A
+#define PCI_CHIP_RV770_944B 0x944B
+#define PCI_CHIP_RV770_944C 0x944C
+#define PCI_CHIP_RV770_944E 0x944E
+#define PCI_CHIP_RV770_9450 0x9450
+#define PCI_CHIP_RV770_9452 0x9452
+#define PCI_CHIP_RV770_9456 0x9456
+#define PCI_CHIP_RV770_945A 0x945A
+#define PCI_CHIP_RV770_945B 0x945B
+#define PCI_CHIP_RV790_9460 0x9460
+#define PCI_CHIP_RV790_9462 0x9462
+#define PCI_CHIP_RV770_946A 0x946A
+#define PCI_CHIP_RV770_946B 0x946B
+#define PCI_CHIP_RV770_947A 0x947A
+#define PCI_CHIP_RV770_947B 0x947B
+
+#define PCI_CHIP_RV730_9480 0x9480
+#define PCI_CHIP_RV730_9487 0x9487
+#define PCI_CHIP_RV730_9488 0x9488
+#define PCI_CHIP_RV730_9489 0x9489
+#define PCI_CHIP_RV730_948F 0x948F
+#define PCI_CHIP_RV730_9490 0x9490
+#define PCI_CHIP_RV730_9491 0x9491
+#define PCI_CHIP_RV730_9495 0x9495
+#define PCI_CHIP_RV730_9498 0x9498
+#define PCI_CHIP_RV730_949C 0x949C
+#define PCI_CHIP_RV730_949E 0x949E
+#define PCI_CHIP_RV730_949F 0x949F
+
+#define PCI_CHIP_RV710_9540 0x9540
+#define PCI_CHIP_RV710_9541 0x9541
+#define PCI_CHIP_RV710_9542 0x9542
+#define PCI_CHIP_RV710_954E 0x954E
+#define PCI_CHIP_RV710_954F 0x954F
+#define PCI_CHIP_RV710_9552 0x9552
+#define PCI_CHIP_RV710_9553 0x9553
+#define PCI_CHIP_RV710_9555 0x9555
+#define PCI_CHIP_RV710_9557 0x9557
+
+#define PCI_CHIP_RV740_94A0 0x94A0
+#define PCI_CHIP_RV740_94A1 0x94A1
+#define PCI_CHIP_RV740_94A3 0x94A3
+#define PCI_CHIP_RV740_94B1 0x94B1
+#define PCI_CHIP_RV740_94B3 0x94B3
+#define PCI_CHIP_RV740_94B4 0x94B4
+#define PCI_CHIP_RV740_94B5 0x94B5
+#define PCI_CHIP_RV740_94B9 0x94B9
enum {
CHIP_FAMILY_R100,
@@ -270,6 +412,7 @@ enum {
CHIP_FAMILY_R420,
CHIP_FAMILY_RV410,
CHIP_FAMILY_RS400,
+ CHIP_FAMILY_RS600,
CHIP_FAMILY_RS690,
CHIP_FAMILY_RS740,
CHIP_FAMILY_RV515,
@@ -278,6 +421,18 @@ enum {
CHIP_FAMILY_R580,
CHIP_FAMILY_RV560,
CHIP_FAMILY_RV570,
+ CHIP_FAMILY_R600,
+ CHIP_FAMILY_RV610,
+ CHIP_FAMILY_RV630,
+ CHIP_FAMILY_RV670,
+ CHIP_FAMILY_RV620,
+ CHIP_FAMILY_RV635,
+ CHIP_FAMILY_RS780,
+ CHIP_FAMILY_RS880,
+ CHIP_FAMILY_RV770,
+ CHIP_FAMILY_RV730,
+ CHIP_FAMILY_RV710,
+ CHIP_FAMILY_RV740,
CHIP_FAMILY_LAST
};
@@ -285,6 +440,7 @@ enum {
#define RADEON_CLASS_R100 (0 << 0)
#define RADEON_CLASS_R200 (1 << 0)
#define RADEON_CLASS_R300 (2 << 0)
+#define RADEON_CLASS_R600 (3 << 0)
#define RADEON_CLASS_MASK (3 << 0)
#define RADEON_CHIPSET_TCL (1 << 2) /* tcl support - any radeon */
diff --git a/src/mesa/drivers/dri/radeon/radeon_cmdbuf.h b/src/mesa/drivers/dri/radeon/radeon_cmdbuf.h
new file mode 100644
index 0000000000..6fcd1ce7ca
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_cmdbuf.h
@@ -0,0 +1,121 @@
+#ifndef COMMON_CMDBUF_H
+#define COMMON_CMDBUF_H
+
+#include "radeon_bocs_wrapper.h"
+
+GLboolean rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller);
+int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller);
+int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller);
+void rcommonInitCmdBuf(radeonContextPtr rmesa);
+void rcommonDestroyCmdBuf(radeonContextPtr rmesa);
+
+void rcommonBeginBatch(radeonContextPtr rmesa,
+ int n,
+ int dostate,
+ const char *file,
+ const char *function,
+ int line);
+
+/* +r6/r7 : code here moved */
+
+#define CP_PACKET2 (2 << 30)
+#define CP_PACKET0(reg, n) (RADEON_CP_PACKET0 | ((n)<<16) | ((reg)>>2))
+#define CP_PACKET0_ONE(reg, n) (RADEON_CP_PACKET0 | RADEON_CP_PACKET0_ONE_REG_WR | ((n)<<16) | ((reg)>>2))
+#define CP_PACKET3(pkt, n) (RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
+
+/**
+ * Every function writing to the command buffer needs to declare this
+ * to get the necessary local variables.
+ */
+#define BATCH_LOCALS(rmesa) \
+ const radeonContextPtr b_l_rmesa = rmesa
+
+/**
+ * Prepare writing n dwords to the command buffer,
+ * including producing any necessary state emits on buffer wraparound.
+ */
+#define BEGIN_BATCH(n) rcommonBeginBatch(b_l_rmesa, n, 1, __FILE__, __FUNCTION__, __LINE__)
+
+/**
+ * Same as BEGIN_BATCH, but do not cause automatic state emits.
+ */
+#define BEGIN_BATCH_NO_AUTOSTATE(n) rcommonBeginBatch(b_l_rmesa, n, 0, __FILE__, __FUNCTION__, __LINE__)
+
+/**
+ * Write one dword to the command buffer.
+ */
+#define OUT_BATCH(data) \
+ do { \
+ radeon_cs_write_dword(b_l_rmesa->cmdbuf.cs, data);\
+ } while(0)
+
+/**
+ * Write a relocated dword to the command buffer.
+ */
+#define OUT_BATCH_RELOC(data, bo, offset, rd, wd, flags) \
+ do { \
+ int __offset = (offset); \
+ if (0 && __offset) { \
+ fprintf(stderr, "(%s:%s:%d) offset : %d\n", \
+ __FILE__, __FUNCTION__, __LINE__, __offset); \
+ } \
+ radeon_cs_write_dword(b_l_rmesa->cmdbuf.cs, __offset); \
+ radeon_cs_write_reloc(b_l_rmesa->cmdbuf.cs, \
+ bo, rd, wd, flags); \
+ if (!b_l_rmesa->radeonScreen->kernel_mm) \
+ b_l_rmesa->cmdbuf.cs->section_cdw += 2; \
+ } while(0)
+
+
+/**
+ * Write n dwords from ptr to the command buffer.
+ */
+#define OUT_BATCH_TABLE(ptr,n) \
+ do { \
+ radeon_cs_write_table(b_l_rmesa->cmdbuf.cs, (ptr), (n));\
+ } while(0)
+
+/**
+ * Finish writing dwords to the command buffer.
+ * The number of (direct or indirect) OUT_BATCH calls between the previous
+ * BEGIN_BATCH and END_BATCH must match the number specified at BEGIN_BATCH time.
+ */
+#define END_BATCH() \
+ do { \
+ radeon_cs_end(b_l_rmesa->cmdbuf.cs, __FILE__, __FUNCTION__, __LINE__);\
+ } while(0)
+
+/**
+ * After the last END_BATCH() of rendering, this indicates that flushing
+ * the command buffer now is okay.
+ */
+#define COMMIT_BATCH() \
+ do { \
+ } while(0)
+
+
+/** Single register write to command buffer; requires 2 dwords. */
+#define OUT_BATCH_REGVAL(reg, val) \
+ OUT_BATCH(cmdpacket0(b_l_rmesa->radeonScreen, (reg), 1)); \
+ OUT_BATCH((val))
+
+/** Continuous register range write to command buffer; requires 1 dword,
+ * expects count dwords afterwards for register contents. */
+#define OUT_BATCH_REGSEQ(reg, count) \
+ OUT_BATCH(cmdpacket0(b_l_rmesa->radeonScreen, (reg), (count)))
+
+/** Write a 32 bit float to the ring; requires 1 dword. */
+#define OUT_BATCH_FLOAT32(f) \
+ OUT_BATCH(radeonPackFloat32((f)))
+
+/* +r6/r7 : code here moved */
+
+/* Fire the buffered vertices no matter what.
+ */
+static INLINE void radeon_firevertices(radeonContextPtr radeon)
+{
+ if (radeon->cmdbuf.cs->cdw || radeon->dma.flush )
+ radeon->glCtx->Driver.Flush(radeon->glCtx); /* +r6/r7 */
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_common.c b/src/mesa/drivers/dri/radeon/radeon_common.c
new file mode 100644
index 0000000000..a4c7b40798
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_common.c
@@ -0,0 +1,1349 @@
+/**************************************************************************
+
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ - Scissor implementation
+ - buffer swap/copy ioctls
+ - finish/flush
+ - state emission
+ - cmdbuffer management
+*/
+
+#include <errno.h>
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+#include "drivers/common/meta.h"
+
+#include "vblank.h"
+
+#include "radeon_common.h"
+#include "radeon_bocs_wrapper.h"
+#include "radeon_lock.h"
+#include "radeon_drm.h"
+#include "radeon_queryobj.h"
+
+/**
+ * Enable verbose debug output for emit code.
+ * 0 no output
+ * 1 most output
+ * 2 also print state alues
+ */
+#define RADEON_CMDBUF 0
+
+/* =============================================================
+ * Scissoring
+ */
+
+static GLboolean intersect_rect(drm_clip_rect_t * out,
+ drm_clip_rect_t * a, drm_clip_rect_t * b)
+{
+ *out = *a;
+ if (b->x1 > out->x1)
+ out->x1 = b->x1;
+ if (b->y1 > out->y1)
+ out->y1 = b->y1;
+ if (b->x2 < out->x2)
+ out->x2 = b->x2;
+ if (b->y2 < out->y2)
+ out->y2 = b->y2;
+ if (out->x1 >= out->x2)
+ return GL_FALSE;
+ if (out->y1 >= out->y2)
+ return GL_FALSE;
+ return GL_TRUE;
+}
+
+void radeonRecalcScissorRects(radeonContextPtr radeon)
+{
+ drm_clip_rect_t *out;
+ int i;
+
+ /* Grow cliprect store?
+ */
+ if (radeon->state.scissor.numAllocedClipRects < radeon->numClipRects) {
+ while (radeon->state.scissor.numAllocedClipRects <
+ radeon->numClipRects) {
+ radeon->state.scissor.numAllocedClipRects += 1; /* zero case */
+ radeon->state.scissor.numAllocedClipRects *= 2;
+ }
+
+ if (radeon->state.scissor.pClipRects)
+ FREE(radeon->state.scissor.pClipRects);
+
+ radeon->state.scissor.pClipRects =
+ MALLOC(radeon->state.scissor.numAllocedClipRects *
+ sizeof(drm_clip_rect_t));
+
+ if (radeon->state.scissor.pClipRects == NULL) {
+ radeon->state.scissor.numAllocedClipRects = 0;
+ return;
+ }
+ }
+
+ out = radeon->state.scissor.pClipRects;
+ radeon->state.scissor.numClipRects = 0;
+
+ for (i = 0; i < radeon->numClipRects; i++) {
+ if (intersect_rect(out,
+ &radeon->pClipRects[i],
+ &radeon->state.scissor.rect)) {
+ radeon->state.scissor.numClipRects++;
+ out++;
+ }
+ }
+
+ if (radeon->vtbl.update_scissor)
+ radeon->vtbl.update_scissor(radeon->glCtx);
+}
+
+void radeon_get_cliprects(radeonContextPtr radeon,
+ struct drm_clip_rect **cliprects,
+ unsigned int *num_cliprects,
+ int *x_off, int *y_off)
+{
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(radeon);
+ struct radeon_framebuffer *rfb = dPriv->driverPrivate;
+
+ if (radeon->constant_cliprect) {
+ radeon->fboRect.x1 = 0;
+ radeon->fboRect.y1 = 0;
+ radeon->fboRect.x2 = radeon->glCtx->DrawBuffer->Width;
+ radeon->fboRect.y2 = radeon->glCtx->DrawBuffer->Height;
+
+ *cliprects = &radeon->fboRect;
+ *num_cliprects = 1;
+ *x_off = 0;
+ *y_off = 0;
+ } else if (radeon->front_cliprects ||
+ rfb->pf_active || dPriv->numBackClipRects == 0) {
+ *cliprects = dPriv->pClipRects;
+ *num_cliprects = dPriv->numClipRects;
+ *x_off = dPriv->x;
+ *y_off = dPriv->y;
+ } else {
+ *num_cliprects = dPriv->numBackClipRects;
+ *cliprects = dPriv->pBackClipRects;
+ *x_off = dPriv->backX;
+ *y_off = dPriv->backY;
+ }
+}
+
+/**
+ * Update cliprects and scissors.
+ */
+void radeonSetCliprects(radeonContextPtr radeon)
+{
+ __DRIdrawablePrivate *const drawable = radeon_get_drawable(radeon);
+ __DRIdrawablePrivate *const readable = radeon_get_readable(radeon);
+ struct radeon_framebuffer *const draw_rfb = drawable->driverPrivate;
+ struct radeon_framebuffer *const read_rfb = readable->driverPrivate;
+ int x_off, y_off;
+
+ radeon_get_cliprects(radeon, &radeon->pClipRects,
+ &radeon->numClipRects, &x_off, &y_off);
+
+ if ((draw_rfb->base.Width != drawable->w) ||
+ (draw_rfb->base.Height != drawable->h)) {
+ _mesa_resize_framebuffer(radeon->glCtx, &draw_rfb->base,
+ drawable->w, drawable->h);
+ draw_rfb->base.Initialized = GL_TRUE;
+ }
+
+ if (drawable != readable) {
+ if ((read_rfb->base.Width != readable->w) ||
+ (read_rfb->base.Height != readable->h)) {
+ _mesa_resize_framebuffer(radeon->glCtx, &read_rfb->base,
+ readable->w, readable->h);
+ read_rfb->base.Initialized = GL_TRUE;
+ }
+ }
+
+ if (radeon->state.scissor.enabled)
+ radeonRecalcScissorRects(radeon);
+
+}
+
+
+
+void radeonUpdateScissor( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLint x = ctx->Scissor.X, y = ctx->Scissor.Y;
+ GLsizei w = ctx->Scissor.Width, h = ctx->Scissor.Height;
+ int x1, y1, x2, y2;
+ int min_x, min_y, max_x, max_y;
+
+ if (!ctx->DrawBuffer)
+ return;
+ min_x = min_y = 0;
+ max_x = ctx->DrawBuffer->Width - 1;
+ max_y = ctx->DrawBuffer->Height - 1;
+
+ if ( !ctx->DrawBuffer->Name ) {
+ x1 = x;
+ y1 = ctx->DrawBuffer->Height - (y + h);
+ x2 = x + w - 1;
+ y2 = y1 + h - 1;
+ } else {
+ x1 = x;
+ y1 = y;
+ x2 = x + w - 1;
+ y2 = y + h - 1;
+
+ }
+ if (!rmesa->radeonScreen->kernel_mm) {
+ /* Fix scissors for dri 1 */
+
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(rmesa);
+ x1 += dPriv->x;
+ x2 += dPriv->x + 1;
+ min_x += dPriv->x;
+ max_x += dPriv->x + 1;
+ y1 += dPriv->y;
+ y2 += dPriv->y + 1;
+ min_y += dPriv->y;
+ max_y += dPriv->y + 1;
+ }
+
+ rmesa->state.scissor.rect.x1 = CLAMP(x1, min_x, max_x);
+ rmesa->state.scissor.rect.y1 = CLAMP(y1, min_y, max_y);
+ rmesa->state.scissor.rect.x2 = CLAMP(x2, min_x, max_x);
+ rmesa->state.scissor.rect.y2 = CLAMP(y2, min_y, max_y);
+
+ radeonRecalcScissorRects( rmesa );
+}
+
+/* =============================================================
+ * Scissoring
+ */
+
+void radeonScissor(GLcontext* ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ if (ctx->Scissor.Enabled) {
+ /* We don't pipeline cliprect changes */
+ radeon_firevertices(radeon);
+ radeonUpdateScissor(ctx);
+ }
+}
+
+void radeonPolygonStipplePreKMS( GLcontext *ctx, const GLubyte *mask )
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ GLuint i;
+ drm_radeon_stipple_t stipple;
+
+ /* Must flip pattern upside down.
+ */
+ for ( i = 0 ; i < 32 ; i++ ) {
+ stipple.mask[31 - i] = ((GLuint *) mask)[i];
+ }
+
+ /* TODO: push this into cmd mechanism
+ */
+ radeon_firevertices(radeon);
+ LOCK_HARDWARE( radeon );
+
+ drmCommandWrite( radeon->dri.fd, DRM_RADEON_STIPPLE,
+ &stipple, sizeof(stipple) );
+ UNLOCK_HARDWARE( radeon );
+}
+
+
+/* ================================================================
+ * SwapBuffers with client-side throttling
+ */
+
+static uint32_t radeonGetLastFrame(radeonContextPtr radeon)
+{
+ drm_radeon_getparam_t gp;
+ int ret;
+ uint32_t frame = 0;
+
+ gp.param = RADEON_PARAM_LAST_FRAME;
+ gp.value = (int *)&frame;
+ ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_GETPARAM,
+ &gp, sizeof(gp));
+ if (ret) {
+ fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__,
+ ret);
+ exit(1);
+ }
+
+ return frame;
+}
+
+uint32_t radeonGetAge(radeonContextPtr radeon)
+{
+ drm_radeon_getparam_t gp;
+ int ret;
+ uint32_t age;
+
+ gp.param = RADEON_PARAM_LAST_CLEAR;
+ gp.value = (int *)&age;
+ ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_GETPARAM,
+ &gp, sizeof(gp));
+ if (ret) {
+ fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__,
+ ret);
+ exit(1);
+ }
+
+ return age;
+}
+
+static void radeonEmitIrqLocked(radeonContextPtr radeon)
+{
+ drm_radeon_irq_emit_t ie;
+ int ret;
+
+ ie.irq_seq = &radeon->iw.irq_seq;
+ ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_IRQ_EMIT,
+ &ie, sizeof(ie));
+ if (ret) {
+ fprintf(stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__,
+ ret);
+ exit(1);
+ }
+}
+
+static void radeonWaitIrq(radeonContextPtr radeon)
+{
+ int ret;
+
+ do {
+ ret = drmCommandWrite(radeon->dri.fd, DRM_RADEON_IRQ_WAIT,
+ &radeon->iw, sizeof(radeon->iw));
+ } while (ret && (errno == EINTR || errno == EBUSY));
+
+ if (ret) {
+ fprintf(stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__,
+ ret);
+ exit(1);
+ }
+}
+
+static void radeonWaitForFrameCompletion(radeonContextPtr radeon)
+{
+ drm_radeon_sarea_t *sarea = radeon->sarea;
+
+ if (radeon->do_irqs) {
+ if (radeonGetLastFrame(radeon) < sarea->last_frame) {
+ if (!radeon->irqsEmitted) {
+ while (radeonGetLastFrame(radeon) <
+ sarea->last_frame) ;
+ } else {
+ UNLOCK_HARDWARE(radeon);
+ radeonWaitIrq(radeon);
+ LOCK_HARDWARE(radeon);
+ }
+ radeon->irqsEmitted = 10;
+ }
+
+ if (radeon->irqsEmitted) {
+ radeonEmitIrqLocked(radeon);
+ radeon->irqsEmitted--;
+ }
+ } else {
+ while (radeonGetLastFrame(radeon) < sarea->last_frame) {
+ UNLOCK_HARDWARE(radeon);
+ if (radeon->do_usleeps)
+ DO_USLEEP(1);
+ LOCK_HARDWARE(radeon);
+ }
+ }
+}
+
+/* wait for idle */
+void radeonWaitForIdleLocked(radeonContextPtr radeon)
+{
+ int ret;
+ int i = 0;
+
+ do {
+ ret = drmCommandNone(radeon->dri.fd, DRM_RADEON_CP_IDLE);
+ if (ret)
+ DO_USLEEP(1);
+ } while (ret && ++i < 100);
+
+ if (ret < 0) {
+ UNLOCK_HARDWARE(radeon);
+ fprintf(stderr, "Error: R300 timed out... exiting\n");
+ exit(-1);
+ }
+}
+
+static void radeonWaitForIdle(radeonContextPtr radeon)
+{
+ if (!radeon->radeonScreen->driScreen->dri2.enabled) {
+ LOCK_HARDWARE(radeon);
+ radeonWaitForIdleLocked(radeon);
+ UNLOCK_HARDWARE(radeon);
+ }
+}
+
+static void radeon_flip_renderbuffers(struct radeon_framebuffer *rfb)
+{
+ int current_page = rfb->pf_current_page;
+ int next_page = (current_page + 1) % rfb->pf_num_pages;
+ struct gl_renderbuffer *tmp_rb;
+
+ /* Exchange renderbuffers if necessary but make sure their
+ * reference counts are preserved.
+ */
+ if (rfb->color_rb[current_page] &&
+ rfb->base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer !=
+ &rfb->color_rb[current_page]->base) {
+ tmp_rb = NULL;
+ _mesa_reference_renderbuffer(&tmp_rb,
+ rfb->base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ tmp_rb = &rfb->color_rb[current_page]->base;
+ _mesa_reference_renderbuffer(&rfb->base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer, tmp_rb);
+ _mesa_reference_renderbuffer(&tmp_rb, NULL);
+ }
+
+ if (rfb->color_rb[next_page] &&
+ rfb->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer !=
+ &rfb->color_rb[next_page]->base) {
+ tmp_rb = NULL;
+ _mesa_reference_renderbuffer(&tmp_rb,
+ rfb->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ tmp_rb = &rfb->color_rb[next_page]->base;
+ _mesa_reference_renderbuffer(&rfb->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer, tmp_rb);
+ _mesa_reference_renderbuffer(&tmp_rb, NULL);
+ }
+}
+
+/* Copy the back color buffer to the front color buffer.
+ */
+void radeonCopyBuffer( __DRIdrawablePrivate *dPriv,
+ const drm_clip_rect_t *rect)
+{
+ radeonContextPtr rmesa;
+ struct radeon_framebuffer *rfb;
+ GLint nbox, i, ret;
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+
+ LOCK_HARDWARE(rmesa);
+
+ rfb = dPriv->driverPrivate;
+
+ if ( RADEON_DEBUG & RADEON_IOCTL ) {
+ fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, (void *) rmesa->glCtx );
+ }
+
+ nbox = dPriv->numClipRects; /* must be in locked region */
+
+ for ( i = 0 ; i < nbox ; ) {
+ GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox );
+ drm_clip_rect_t *box = dPriv->pClipRects;
+ drm_clip_rect_t *b = rmesa->sarea->boxes;
+ GLint n = 0;
+
+ for ( ; i < nr ; i++ ) {
+
+ *b = box[i];
+
+ if (rect)
+ {
+ if (rect->x1 > b->x1)
+ b->x1 = rect->x1;
+ if (rect->y1 > b->y1)
+ b->y1 = rect->y1;
+ if (rect->x2 < b->x2)
+ b->x2 = rect->x2;
+ if (rect->y2 < b->y2)
+ b->y2 = rect->y2;
+
+ if (b->x1 >= b->x2 || b->y1 >= b->y2)
+ continue;
+ }
+
+ b++;
+ n++;
+ }
+ rmesa->sarea->nbox = n;
+
+ if (!n)
+ continue;
+
+ ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP );
+
+ if ( ret ) {
+ fprintf( stderr, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret );
+ UNLOCK_HARDWARE( rmesa );
+ exit( 1 );
+ }
+ }
+
+ UNLOCK_HARDWARE( rmesa );
+}
+
+static int radeonScheduleSwap(__DRIdrawablePrivate *dPriv, GLboolean *missed_target)
+{
+ radeonContextPtr rmesa;
+
+ rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+ radeon_firevertices(rmesa);
+
+ LOCK_HARDWARE( rmesa );
+
+ if (!dPriv->numClipRects) {
+ UNLOCK_HARDWARE(rmesa);
+ usleep(10000); /* throttle invisible client 10ms */
+ return 0;
+ }
+
+ radeonWaitForFrameCompletion(rmesa);
+
+ UNLOCK_HARDWARE(rmesa);
+ driWaitForVBlank(dPriv, missed_target);
+
+ return 0;
+}
+
+static GLboolean radeonPageFlip( __DRIdrawablePrivate *dPriv )
+{
+ radeonContextPtr radeon;
+ GLint ret;
+ __DRIscreenPrivate *psp;
+ struct radeon_renderbuffer *rrb;
+ struct radeon_framebuffer *rfb;
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+ rfb = dPriv->driverPrivate;
+ rrb = (void *)rfb->base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+
+ psp = dPriv->driScreenPriv;
+
+ LOCK_HARDWARE(radeon);
+
+ if ( RADEON_DEBUG & RADEON_IOCTL ) {
+ fprintf(stderr, "%s: pfCurrentPage: %d %d\n", __FUNCTION__,
+ radeon->sarea->pfCurrentPage, radeon->sarea->pfState);
+ }
+ drm_clip_rect_t *box = dPriv->pClipRects;
+ drm_clip_rect_t *b = radeon->sarea->boxes;
+ b[0] = box[0];
+ radeon->sarea->nbox = 1;
+
+ ret = drmCommandNone( radeon->dri.fd, DRM_RADEON_FLIP );
+
+ UNLOCK_HARDWARE(radeon);
+
+ if ( ret ) {
+ fprintf( stderr, "DRM_RADEON_FLIP: return = %d\n", ret );
+ return GL_FALSE;
+ }
+
+ if (!rfb->pf_active)
+ return GL_FALSE;
+
+ rfb->pf_current_page = radeon->sarea->pfCurrentPage;
+ radeon_flip_renderbuffers(rfb);
+ radeon_draw_buffer(radeon->glCtx, &rfb->base);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Swap front and back buffer.
+ */
+void radeonSwapBuffers(__DRIdrawablePrivate * dPriv)
+{
+ int64_t ust;
+ __DRIscreenPrivate *psp;
+
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ radeonContextPtr radeon;
+ GLcontext *ctx;
+
+ radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+ ctx = radeon->glCtx;
+
+ if (ctx->Visual.doubleBufferMode) {
+ GLboolean missed_target;
+ struct radeon_framebuffer *rfb = dPriv->driverPrivate;
+ _mesa_notifySwapBuffers(ctx);/* flush pending rendering comands */
+
+ radeonScheduleSwap(dPriv, &missed_target);
+
+ if (rfb->pf_active) {
+ radeonPageFlip(dPriv);
+ } else {
+ radeonCopyBuffer(dPriv, NULL);
+ }
+
+ psp = dPriv->driScreenPriv;
+
+ rfb->swap_count++;
+ (*psp->systemTime->getUST)( & ust );
+ if ( missed_target ) {
+ rfb->swap_missed_count++;
+ rfb->swap_missed_ust = ust - rfb->swap_ust;
+ }
+
+ rfb->swap_ust = ust;
+ radeon->hw.all_dirty = GL_TRUE;
+ }
+ } else {
+ /* XXX this shouldn't be an error but we can't handle it for now */
+ _mesa_problem(NULL, "%s: drawable has no context!",
+ __FUNCTION__);
+ }
+}
+
+void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
+ int x, int y, int w, int h )
+{
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ radeonContextPtr radeon;
+ GLcontext *ctx;
+
+ radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+ ctx = radeon->glCtx;
+
+ if (ctx->Visual.doubleBufferMode) {
+ drm_clip_rect_t rect;
+ rect.x1 = x + dPriv->x;
+ rect.y1 = (dPriv->h - y - h) + dPriv->y;
+ rect.x2 = rect.x1 + w;
+ rect.y2 = rect.y1 + h;
+ _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
+ radeonCopyBuffer(dPriv, &rect);
+ }
+ } else {
+ /* XXX this shouldn't be an error but we can't handle it for now */
+ _mesa_problem(NULL, "%s: drawable has no context!",
+ __FUNCTION__);
+ }
+}
+
+void radeon_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrbDepth = NULL, *rrbStencil = NULL,
+ *rrbColor = NULL;
+ uint32_t offset = 0;
+
+
+ if (!fb) {
+ /* this can happen during the initial context initialization */
+ return;
+ }
+
+ /* radeons only handle 1 color draw so far */
+ if (fb->_NumColorDrawBuffers != 1) {
+ radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE);
+ return;
+ }
+
+ /* Do this here, note core Mesa, since this function is called from
+ * many places within the driver.
+ */
+ if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
+ /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
+ _mesa_update_framebuffer(ctx);
+ /* this updates the DrawBuffer's Width/Height if it's a FBO */
+ _mesa_update_draw_buffer_bounds(ctx);
+ }
+
+ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ /* this may occur when we're called by glBindFrameBuffer() during
+ * the process of someone setting up renderbuffers, etc.
+ */
+ /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
+ return;
+ }
+
+ if (fb->Name)
+ ;/* do something depthy/stencily TODO */
+
+
+ /* none */
+ if (fb->Name == 0) {
+ if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
+ rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ radeon->front_cliprects = GL_TRUE;
+ radeon->front_buffer_dirty = GL_TRUE;
+ } else {
+ rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ radeon->front_cliprects = GL_FALSE;
+ }
+ } else {
+ /* user FBO in theory */
+ struct radeon_renderbuffer *rrb;
+ rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[0]);
+ if (rrb) {
+ offset = rrb->draw_offset;
+ rrbColor = rrb;
+ }
+ radeon->constant_cliprect = GL_TRUE;
+ }
+
+ if (rrbColor == NULL)
+ radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE);
+ else
+ radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE);
+
+
+ if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
+ rrbDepth = radeon_renderbuffer(fb->_DepthBuffer->Wrapped);
+ if (rrbDepth && rrbDepth->bo) {
+ radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE);
+ } else {
+ radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_TRUE);
+ }
+ } else {
+ radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE);
+ rrbDepth = NULL;
+ }
+
+ if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
+ rrbStencil = radeon_renderbuffer(fb->_StencilBuffer->Wrapped);
+ if (rrbStencil && rrbStencil->bo) {
+ radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE);
+ /* need to re-compute stencil hw state */
+ if (!rrbDepth)
+ rrbDepth = rrbStencil;
+ } else {
+ radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_TRUE);
+ }
+ } else {
+ radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE);
+ if (ctx->Driver.Enable != NULL)
+ ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
+ else
+ ctx->NewState |= _NEW_STENCIL;
+ }
+
+ /* Update culling direction which changes depending on the
+ * orientation of the buffer:
+ */
+ if (ctx->Driver.FrontFace)
+ ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
+ else
+ ctx->NewState |= _NEW_POLYGON;
+
+ /*
+ * Update depth test state
+ */
+ if (ctx->Driver.Enable) {
+ ctx->Driver.Enable(ctx, GL_DEPTH_TEST,
+ (ctx->Depth.Test && fb->Visual.depthBits > 0));
+ /* Need to update the derived ctx->Stencil._Enabled first */
+ ctx->Driver.Enable(ctx, GL_STENCIL_TEST,
+ (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0));
+ } else {
+ ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL);
+ }
+
+ _mesa_reference_renderbuffer(&radeon->state.depth.rb, &rrbDepth->base);
+ _mesa_reference_renderbuffer(&radeon->state.color.rb, &rrbColor->base);
+ radeon->state.color.draw_offset = offset;
+
+#if 0
+ /* update viewport since it depends on window size */
+ if (ctx->Driver.Viewport) {
+ ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
+ ctx->Viewport.Width, ctx->Viewport.Height);
+ } else {
+
+ }
+#endif
+ ctx->NewState |= _NEW_VIEWPORT;
+
+ /* Set state we know depends on drawable parameters:
+ */
+ radeonUpdateScissor(ctx);
+ radeon->NewGLState |= _NEW_SCISSOR;
+
+ if (ctx->Driver.DepthRange)
+ ctx->Driver.DepthRange(ctx,
+ ctx->Viewport.Near,
+ ctx->Viewport.Far);
+
+ /* Update culling direction which changes depending on the
+ * orientation of the buffer:
+ */
+ if (ctx->Driver.FrontFace)
+ ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
+ else
+ ctx->NewState |= _NEW_POLYGON;
+}
+
+/**
+ * Called via glDrawBuffer.
+ */
+void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
+{
+ if (RADEON_DEBUG & RADEON_DRI)
+ fprintf(stderr, "%s %s\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr( mode ));
+
+ if (ctx->DrawBuffer->Name == 0) {
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+
+ const GLboolean was_front_buffer_rendering =
+ radeon->is_front_buffer_rendering;
+
+ radeon->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) ||
+ (mode == GL_FRONT);
+
+ /* If we weren't front-buffer rendering before but we are now, make sure
+ * that the front-buffer has actually been allocated.
+ */
+ if (!was_front_buffer_rendering && radeon->is_front_buffer_rendering) {
+ radeon_update_renderbuffers(radeon->dri.context,
+ radeon->dri.context->driDrawablePriv);
+ }
+ }
+
+ radeon_draw_buffer(ctx, ctx->DrawBuffer);
+}
+
+void radeonReadBuffer( GLcontext *ctx, GLenum mode )
+{
+ if ((ctx->DrawBuffer != NULL) && (ctx->DrawBuffer->Name == 0)) {
+ struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
+ const GLboolean was_front_buffer_reading = rmesa->is_front_buffer_reading;
+ rmesa->is_front_buffer_reading = (mode == GL_FRONT_LEFT)
+ || (mode == GL_FRONT);
+
+ if (!was_front_buffer_reading && rmesa->is_front_buffer_reading) {
+ radeon_update_renderbuffers(rmesa->dri.context,
+ rmesa->dri.context->driReadablePriv);
+ }
+ }
+ /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+ if (ctx->ReadBuffer == ctx->DrawBuffer) {
+ /* This will update FBO completeness status.
+ * A framebuffer will be incomplete if the GL_READ_BUFFER setting
+ * refers to a missing renderbuffer. Calling glReadBuffer can set
+ * that straight and can make the drawing buffer complete.
+ */
+ radeon_draw_buffer(ctx, ctx->DrawBuffer);
+ }
+}
+
+
+/* Turn on/off page flipping according to the flags in the sarea:
+ */
+void radeonUpdatePageFlipping(radeonContextPtr radeon)
+{
+ struct radeon_framebuffer *rfb = radeon_get_drawable(radeon)->driverPrivate;
+
+ rfb->pf_active = radeon->sarea->pfState;
+ rfb->pf_current_page = radeon->sarea->pfCurrentPage;
+ rfb->pf_num_pages = 2;
+ radeon_flip_renderbuffers(rfb);
+ radeon_draw_buffer(radeon->glCtx, radeon->glCtx->DrawBuffer);
+}
+
+void radeon_window_moved(radeonContextPtr radeon)
+{
+ /* Cliprects has to be updated before doing anything else */
+ radeonSetCliprects(radeon);
+ if (!radeon->radeonScreen->driScreen->dri2.enabled) {
+ radeonUpdatePageFlipping(radeon);
+ }
+}
+
+void radeon_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ __DRIcontext *driContext = radeon->dri.context;
+ void (*old_viewport)(GLcontext *ctx, GLint x, GLint y,
+ GLsizei w, GLsizei h);
+
+ if (!driContext->driScreenPriv->dri2.enabled)
+ return;
+
+ if (!radeon->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
+ if (radeon->is_front_buffer_rendering) {
+ ctx->Driver.Flush(ctx);
+ }
+ radeon_update_renderbuffers(driContext, driContext->driDrawablePriv);
+ if (driContext->driDrawablePriv != driContext->driReadablePriv)
+ radeon_update_renderbuffers(driContext, driContext->driReadablePriv);
+ }
+
+ old_viewport = ctx->Driver.Viewport;
+ ctx->Driver.Viewport = NULL;
+ radeon_window_moved(radeon);
+ radeon_draw_buffer(ctx, radeon->glCtx->DrawBuffer);
+ ctx->Driver.Viewport = old_viewport;
+}
+
+static void radeon_print_state_atom_prekmm(radeonContextPtr radeon, struct radeon_state_atom *state)
+{
+ int i, j, reg;
+ int dwords = (*state->check) (radeon->glCtx, state);
+ drm_r300_cmd_header_t cmd;
+
+ fprintf(stderr, " emit %s %d/%d\n", state->name, dwords, state->cmd_size);
+
+ if (radeon_is_debug_enabled(RADEON_STATE, RADEON_TRACE)) {
+ if (dwords > state->cmd_size)
+ dwords = state->cmd_size;
+
+ for (i = 0; i < dwords;) {
+ cmd = *((drm_r300_cmd_header_t *) &state->cmd[i]);
+ reg = (cmd.packet0.reghi << 8) | cmd.packet0.reglo;
+ fprintf(stderr, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
+ state->name, i, reg, cmd.packet0.count);
+ ++i;
+ for (j = 0; j < cmd.packet0.count && i < dwords; j++) {
+ fprintf(stderr, " %s[%d]: 0x%04x = %08x\n",
+ state->name, i, reg, state->cmd[i]);
+ reg += 4;
+ ++i;
+ }
+ }
+ }
+}
+
+static void radeon_print_state_atom(radeonContextPtr radeon, struct radeon_state_atom *state)
+{
+ int i, j, reg, count;
+ int dwords;
+ uint32_t packet0;
+ if (!radeon_is_debug_enabled(RADEON_STATE, RADEON_VERBOSE) )
+ return;
+
+ if (!radeon->radeonScreen->kernel_mm) {
+ radeon_print_state_atom_prekmm(radeon, state);
+ return;
+ }
+
+ dwords = (*state->check) (radeon->glCtx, state);
+
+ fprintf(stderr, " emit %s %d/%d\n", state->name, dwords, state->cmd_size);
+
+ if (radeon_is_debug_enabled(RADEON_STATE, RADEON_TRACE)) {
+ if (dwords > state->cmd_size)
+ dwords = state->cmd_size;
+ for (i = 0; i < dwords;) {
+ packet0 = state->cmd[i];
+ reg = (packet0 & 0x1FFF) << 2;
+ count = ((packet0 & 0x3FFF0000) >> 16) + 1;
+ fprintf(stderr, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
+ state->name, i, reg, count);
+ ++i;
+ for (j = 0; j < count && i < dwords; j++) {
+ fprintf(stderr, " %s[%d]: 0x%04x = %08x\n",
+ state->name, i, reg, state->cmd[i]);
+ reg += 4;
+ ++i;
+ }
+ }
+ }
+}
+
+/**
+ * Count total size for next state emit.
+ **/
+GLuint radeonCountStateEmitSize(radeonContextPtr radeon)
+{
+ struct radeon_state_atom *atom;
+ GLuint dwords = 0;
+ /* check if we are going to emit full state */
+
+ if (radeon->cmdbuf.cs->cdw && !radeon->hw.all_dirty) {
+ if (!radeon->hw.is_dirty)
+ goto out;
+ foreach(atom, &radeon->hw.atomlist) {
+ if (atom->dirty) {
+ const GLuint atom_size = atom->check(radeon->glCtx, atom);
+ dwords += atom_size;
+ if (RADEON_CMDBUF && atom_size) {
+ radeon_print_state_atom(radeon, atom);
+ }
+ }
+ }
+ } else {
+ foreach(atom, &radeon->hw.atomlist) {
+ const GLuint atom_size = atom->check(radeon->glCtx, atom);
+ dwords += atom_size;
+ if (RADEON_CMDBUF && atom_size) {
+ radeon_print_state_atom(radeon, atom);
+ }
+
+ }
+ }
+out:
+ radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %u\n", __func__, dwords);
+ return dwords;
+}
+
+static INLINE void radeon_emit_atom(radeonContextPtr radeon, struct radeon_state_atom *atom)
+{
+ BATCH_LOCALS(radeon);
+ int dwords;
+
+ dwords = (*atom->check) (radeon->glCtx, atom);
+ if (dwords) {
+
+ radeon_print_state_atom(radeon, atom);
+
+ if (atom->emit) {
+ (*atom->emit)(radeon->glCtx, atom);
+ } else {
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(atom->cmd, dwords);
+ END_BATCH();
+ }
+ } else {
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, " skip state %s\n", atom->name);
+ }
+ atom->dirty = GL_FALSE;
+
+}
+
+static INLINE void radeonEmitAtoms(radeonContextPtr radeon, GLboolean emitAll)
+{
+ struct radeon_state_atom *atom;
+
+ if (radeon->vtbl.pre_emit_atoms)
+ radeon->vtbl.pre_emit_atoms(radeon);
+
+ /* Emit actual atoms */
+ if (radeon->hw.all_dirty || emitAll) {
+ foreach(atom, &radeon->hw.atomlist)
+ radeon_emit_atom( radeon, atom );
+ } else {
+ foreach(atom, &radeon->hw.atomlist) {
+ if ( atom->dirty )
+ radeon_emit_atom( radeon, atom );
+ }
+ }
+
+ COMMIT_BATCH();
+}
+
+static GLboolean radeon_revalidate_bos(GLcontext *ctx)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ int ret;
+
+ ret = radeon_cs_space_check(radeon->cmdbuf.cs);
+ if (ret == RADEON_CS_SPACE_FLUSH)
+ return GL_FALSE;
+ return GL_TRUE;
+}
+
+void radeonEmitState(radeonContextPtr radeon)
+{
+ radeon_print(RADEON_STATE, RADEON_NORMAL, "%s\n", __FUNCTION__);
+
+ if (radeon->vtbl.pre_emit_state)
+ radeon->vtbl.pre_emit_state(radeon);
+
+ /* this code used to return here but now it emits zbs */
+ if (radeon->cmdbuf.cs->cdw && !radeon->hw.is_dirty && !radeon->hw.all_dirty)
+ return;
+
+ if (!radeon->cmdbuf.cs->cdw) {
+ if (RADEON_DEBUG & RADEON_STATE)
+ fprintf(stderr, "Begin reemit state\n");
+
+ radeonEmitAtoms(radeon, GL_TRUE);
+ } else {
+
+ if (RADEON_DEBUG & RADEON_STATE)
+ fprintf(stderr, "Begin dirty state\n");
+
+ radeonEmitAtoms(radeon, GL_FALSE);
+ }
+
+ radeon->hw.is_dirty = GL_FALSE;
+ radeon->hw.all_dirty = GL_FALSE;
+}
+
+
+void radeonFlush(GLcontext *ctx)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, radeon->cmdbuf.cs->cdw);
+
+ /* okay if we have no cmds in the buffer &&
+ we have no DMA flush &&
+ we have no DMA buffer allocated.
+ then no point flushing anything at all.
+ */
+ if (!radeon->dma.flush && !radeon->cmdbuf.cs->cdw && is_empty_list(&radeon->dma.reserved))
+ return;
+
+ if (radeon->dma.flush)
+ radeon->dma.flush( ctx );
+
+ radeonEmitState(radeon);
+
+ if (radeon->cmdbuf.cs->cdw)
+ rcommonFlushCmdBuf(radeon, __FUNCTION__);
+
+ if ((ctx->DrawBuffer->Name == 0) && radeon->front_buffer_dirty) {
+ __DRIscreen *const screen = radeon->radeonScreen->driScreen;
+
+ if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2)
+ && (screen->dri2.loader->flushFrontBuffer != NULL)) {
+ __DRIdrawablePrivate * drawable = radeon_get_drawable(radeon);
+ (*screen->dri2.loader->flushFrontBuffer)(drawable, drawable->loaderPrivate);
+
+ /* Only clear the dirty bit if front-buffer rendering is no longer
+ * enabled. This is done so that the dirty bit can only be set in
+ * glDrawBuffer. Otherwise the dirty bit would have to be set at
+ * each of N places that do rendering. This has worse performances,
+ * but it is much easier to get correct.
+ */
+ if (!radeon->is_front_buffer_rendering) {
+ radeon->front_buffer_dirty = GL_FALSE;
+ }
+ }
+ }
+
+ make_empty_list(&radeon->query.not_flushed_head);
+
+}
+
+/* Make sure all commands have been sent to the hardware and have
+ * completed processing.
+ */
+void radeonFinish(GLcontext * ctx)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ int i;
+
+ if (ctx->Driver.Flush)
+ ctx->Driver.Flush(ctx); /* +r6/r7 */
+
+ if (radeon->radeonScreen->kernel_mm) {
+ for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ struct radeon_renderbuffer *rrb;
+ rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[i]);
+ if (rrb && rrb->bo)
+ radeon_bo_wait(rrb->bo);
+ }
+ {
+ struct radeon_renderbuffer *rrb;
+ rrb = radeon_get_depthbuffer(radeon);
+ if (rrb && rrb->bo)
+ radeon_bo_wait(rrb->bo);
+ }
+ } else if (radeon->do_irqs) {
+ LOCK_HARDWARE(radeon);
+ radeonEmitIrqLocked(radeon);
+ UNLOCK_HARDWARE(radeon);
+ radeonWaitIrq(radeon);
+ } else {
+ radeonWaitForIdle(radeon);
+ }
+}
+
+/* cmdbuffer */
+/**
+ * Send the current command buffer via ioctl to the hardware.
+ */
+int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller)
+{
+ int ret = 0;
+
+ if (rmesa->cmdbuf.flushing) {
+ fprintf(stderr, "Recursive call into r300FlushCmdBufLocked!\n");
+ exit(-1);
+ }
+ rmesa->cmdbuf.flushing = 1;
+
+ if (RADEON_DEBUG & RADEON_IOCTL) {
+ fprintf(stderr, "%s from %s - %i cliprects\n",
+ __FUNCTION__, caller, rmesa->numClipRects);
+ }
+
+ radeonEmitQueryEnd(rmesa->glCtx);
+
+ if (rmesa->cmdbuf.cs->cdw) {
+ ret = radeon_cs_emit(rmesa->cmdbuf.cs);
+ rmesa->hw.all_dirty = GL_TRUE;
+ }
+ radeon_cs_erase(rmesa->cmdbuf.cs);
+ rmesa->cmdbuf.flushing = 0;
+
+ if (radeon_revalidate_bos(rmesa->glCtx) == GL_FALSE) {
+ fprintf(stderr,"failed to revalidate buffers\n");
+ }
+
+ return ret;
+}
+
+int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller)
+{
+ int ret;
+
+ radeonReleaseDmaRegions(rmesa);
+
+ LOCK_HARDWARE(rmesa);
+ ret = rcommonFlushCmdBufLocked(rmesa, caller);
+ UNLOCK_HARDWARE(rmesa);
+
+ if (ret) {
+ fprintf(stderr, "drmRadeonCmdBuffer: %d. Kernel failed to "
+ "parse or rejected command stream. See dmesg "
+ "for more info.\n", ret);
+ _mesa_exit(ret);
+ }
+
+ return ret;
+}
+
+/**
+ * Make sure that enough space is available in the command buffer
+ * by flushing if necessary.
+ *
+ * \param dwords The number of dwords we need to be free on the command buffer
+ */
+GLboolean rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller)
+{
+ if ((rmesa->cmdbuf.cs->cdw + dwords + 128) > rmesa->cmdbuf.size
+ || radeon_cs_need_flush(rmesa->cmdbuf.cs)) {
+ /* If we try to flush empty buffer there is too big rendering operation. */
+ assert(rmesa->cmdbuf.cs->cdw);
+ rcommonFlushCmdBuf(rmesa, caller);
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+void rcommonInitCmdBuf(radeonContextPtr rmesa)
+{
+ GLuint size;
+ /* Initialize command buffer */
+ size = 256 * driQueryOptioni(&rmesa->optionCache,
+ "command_buffer_size");
+ if (size < 2 * rmesa->hw.max_state_size) {
+ size = 2 * rmesa->hw.max_state_size + 65535;
+ }
+ if (size > 64 * 256)
+ size = 64 * 256;
+
+ radeon_print(RADEON_CS, RADEON_VERBOSE,
+ "sizeof(drm_r300_cmd_header_t)=%zd\n", sizeof(drm_r300_cmd_header_t));
+ radeon_print(RADEON_CS, RADEON_VERBOSE,
+ "sizeof(drm_radeon_cmd_buffer_t)=%zd\n", sizeof(drm_radeon_cmd_buffer_t));
+ radeon_print(RADEON_CS, RADEON_VERBOSE,
+ "Allocating %d bytes command buffer (max state is %d bytes)\n",
+ size * 4, rmesa->hw.max_state_size * 4);
+
+ if (rmesa->radeonScreen->kernel_mm) {
+ int fd = rmesa->radeonScreen->driScreen->fd;
+ rmesa->cmdbuf.csm = radeon_cs_manager_gem_ctor(fd);
+ } else {
+ rmesa->cmdbuf.csm = radeon_cs_manager_legacy_ctor(rmesa);
+ }
+ if (rmesa->cmdbuf.csm == NULL) {
+ /* FIXME: fatal error */
+ return;
+ }
+ rmesa->cmdbuf.cs = radeon_cs_create(rmesa->cmdbuf.csm, size);
+ assert(rmesa->cmdbuf.cs != NULL);
+ rmesa->cmdbuf.size = size;
+
+ radeon_cs_space_set_flush(rmesa->cmdbuf.cs,
+ (void (*)(void *))rmesa->glCtx->Driver.Flush, rmesa->glCtx);
+
+ if (!rmesa->radeonScreen->kernel_mm) {
+ radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM, rmesa->radeonScreen->texSize[0]);
+ radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT, rmesa->radeonScreen->gartTextures.size);
+ } else {
+ struct drm_radeon_gem_info mminfo = { 0 };
+
+ if (!drmCommandWriteRead(rmesa->dri.fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
+ {
+ radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM, mminfo.vram_visible);
+ radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT, mminfo.gart_size);
+ }
+ }
+
+}
+/**
+ * Destroy the command buffer
+ */
+void rcommonDestroyCmdBuf(radeonContextPtr rmesa)
+{
+ radeon_cs_destroy(rmesa->cmdbuf.cs);
+ if (rmesa->radeonScreen->driScreen->dri2.enabled || rmesa->radeonScreen->kernel_mm) {
+ radeon_cs_manager_gem_dtor(rmesa->cmdbuf.csm);
+ } else {
+ radeon_cs_manager_legacy_dtor(rmesa->cmdbuf.csm);
+ }
+}
+
+void rcommonBeginBatch(radeonContextPtr rmesa, int n,
+ int dostate,
+ const char *file,
+ const char *function,
+ int line)
+{
+ if (!rmesa->cmdbuf.cs->cdw && dostate) {
+ radeon_print(RADEON_STATE, RADEON_NORMAL,
+ "Reemit state after flush (from %s)\n", function);
+ radeonEmitState(rmesa);
+ }
+ radeon_cs_begin(rmesa->cmdbuf.cs, n, file, function, line);
+
+ radeon_print(RADEON_CS, RADEON_VERBOSE, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
+ n, rmesa->cmdbuf.cs->cdw, function, line);
+
+}
+
+void radeonUserClear(GLcontext *ctx, GLuint mask)
+{
+ _mesa_meta_clear(ctx, mask);
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_common.h b/src/mesa/drivers/dri/radeon/radeon_common.h
new file mode 100644
index 0000000000..f3201911ac
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_common.h
@@ -0,0 +1,87 @@
+#ifndef COMMON_MISC_H
+#define COMMON_MISC_H
+
+#include "radeon_common_context.h"
+#include "radeon_dma.h"
+#include "radeon_texture.h"
+
+void radeonUserClear(GLcontext *ctx, GLuint mask);
+void radeonRecalcScissorRects(radeonContextPtr radeon);
+void radeonSetCliprects(radeonContextPtr radeon);
+void radeonUpdateScissor( GLcontext *ctx );
+void radeonScissor(GLcontext* ctx, GLint x, GLint y, GLsizei w, GLsizei h);
+void radeonPolygonStipplePreKMS( GLcontext *ctx, const GLubyte *mask );
+
+void radeonWaitForIdleLocked(radeonContextPtr radeon);
+extern uint32_t radeonGetAge(radeonContextPtr radeon);
+void radeonCopyBuffer( __DRIdrawablePrivate *dPriv,
+ const drm_clip_rect_t *rect);
+void radeonSwapBuffers(__DRIdrawablePrivate * dPriv);
+void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
+ int x, int y, int w, int h );
+
+void radeonUpdatePageFlipping(radeonContextPtr rmesa);
+
+void radeonFlush(GLcontext *ctx);
+void radeonFinish(GLcontext * ctx);
+void radeonEmitState(radeonContextPtr radeon);
+GLuint radeonCountStateEmitSize(radeonContextPtr radeon);
+
+void radeon_clear_tris(GLcontext *ctx, GLbitfield mask);
+
+void radeon_window_moved(radeonContextPtr radeon);
+void radeon_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb);
+void radeonDrawBuffer( GLcontext *ctx, GLenum mode );
+void radeonReadBuffer( GLcontext *ctx, GLenum mode );
+void radeon_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height);
+void radeon_get_cliprects(radeonContextPtr radeon,
+ struct drm_clip_rect **cliprects,
+ unsigned int *num_cliprects,
+ int *x_off, int *y_off);
+void radeon_fbo_init(struct radeon_context *radeon);
+void
+radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
+ struct radeon_bo *bo);
+struct radeon_renderbuffer *
+radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv);
+static inline struct radeon_renderbuffer *radeon_renderbuffer(struct gl_renderbuffer *rb)
+{
+ struct radeon_renderbuffer *rrb = (struct radeon_renderbuffer *)rb;
+ if (rrb && rrb->base.ClassID == RADEON_RB_CLASS)
+ return rrb;
+ else
+ return NULL;
+}
+
+static inline struct radeon_renderbuffer *radeon_get_renderbuffer(struct gl_framebuffer *fb, int att_index)
+{
+ if (att_index >= 0)
+ return radeon_renderbuffer(fb->Attachment[att_index].Renderbuffer);
+ else
+ return NULL;
+}
+
+static inline struct radeon_renderbuffer *radeon_get_depthbuffer(radeonContextPtr rmesa)
+{
+ struct radeon_renderbuffer *rrb;
+ rrb = radeon_renderbuffer(rmesa->state.depth.rb);
+ if (!rrb)
+ return NULL;
+
+ return rrb;
+}
+
+static inline struct radeon_renderbuffer *radeon_get_colorbuffer(radeonContextPtr rmesa)
+{
+ struct radeon_renderbuffer *rrb;
+
+ rrb = radeon_renderbuffer(rmesa->state.color.rb);
+ if (!rrb)
+ return NULL;
+ return rrb;
+}
+
+#include "radeon_cmdbuf.h"
+
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c
new file mode 100644
index 0000000000..71ee06d9a7
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c
@@ -0,0 +1,805 @@
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ VA Linux Systems Inc., Fremont, California.
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "radeon_common.h"
+#include "xmlpool.h" /* for symbolic values of enum-type options */
+#include "utils.h"
+#include "vblank.h"
+#include "drirenderbuffer.h"
+#include "drivers/common/meta.h"
+#include "main/context.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+#include "main/state.h"
+#include "main/simple_list.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+
+#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R600) /* +r6/r7 */
+#include "r600_context.h"
+#endif
+
+#define DRIVER_DATE "20090101"
+
+#ifndef RADEON_DEBUG
+int RADEON_DEBUG = (0);
+#endif
+
+
+static const char* get_chip_family_name(int chip_family)
+{
+ switch(chip_family) {
+ case CHIP_FAMILY_R100: return "R100";
+ case CHIP_FAMILY_RV100: return "RV100";
+ case CHIP_FAMILY_RS100: return "RS100";
+ case CHIP_FAMILY_RV200: return "RV200";
+ case CHIP_FAMILY_RS200: return "RS200";
+ case CHIP_FAMILY_R200: return "R200";
+ case CHIP_FAMILY_RV250: return "RV250";
+ case CHIP_FAMILY_RS300: return "RS300";
+ case CHIP_FAMILY_RV280: return "RV280";
+ case CHIP_FAMILY_R300: return "R300";
+ case CHIP_FAMILY_R350: return "R350";
+ case CHIP_FAMILY_RV350: return "RV350";
+ case CHIP_FAMILY_RV380: return "RV380";
+ case CHIP_FAMILY_R420: return "R420";
+ case CHIP_FAMILY_RV410: return "RV410";
+ case CHIP_FAMILY_RS400: return "RS400";
+ case CHIP_FAMILY_RS600: return "RS600";
+ case CHIP_FAMILY_RS690: return "RS690";
+ case CHIP_FAMILY_RS740: return "RS740";
+ case CHIP_FAMILY_RV515: return "RV515";
+ case CHIP_FAMILY_R520: return "R520";
+ case CHIP_FAMILY_RV530: return "RV530";
+ case CHIP_FAMILY_R580: return "R580";
+ case CHIP_FAMILY_RV560: return "RV560";
+ case CHIP_FAMILY_RV570: return "RV570";
+ case CHIP_FAMILY_R600: return "R600";
+ case CHIP_FAMILY_RV610: return "RV610";
+ case CHIP_FAMILY_RV630: return "RV630";
+ case CHIP_FAMILY_RV670: return "RV670";
+ case CHIP_FAMILY_RV620: return "RV620";
+ case CHIP_FAMILY_RV635: return "RV635";
+ case CHIP_FAMILY_RS780: return "RS780";
+ case CHIP_FAMILY_RS880: return "RS880";
+ case CHIP_FAMILY_RV770: return "RV770";
+ case CHIP_FAMILY_RV730: return "RV730";
+ case CHIP_FAMILY_RV710: return "RV710";
+ case CHIP_FAMILY_RV740: return "RV740";
+ default: return "unknown";
+ }
+}
+
+
+/* Return various strings for glGetString().
+ */
+static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ static char buffer[128];
+
+ switch (name) {
+ case GL_VENDOR:
+ if (IS_R600_CLASS(radeon->radeonScreen))
+ return (GLubyte *) "Advanced Micro Devices, Inc.";
+ else if (IS_R300_CLASS(radeon->radeonScreen))
+ return (GLubyte *) "DRI R300 Project";
+ else
+ return (GLubyte *) "Tungsten Graphics, Inc.";
+
+ case GL_RENDERER:
+ {
+ unsigned offset;
+ GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
+ radeon->radeonScreen->AGPMode;
+ const char* chipclass;
+ char hardwarename[32];
+
+ if (IS_R600_CLASS(radeon->radeonScreen))
+ chipclass = "R600";
+ else if (IS_R300_CLASS(radeon->radeonScreen))
+ chipclass = "R300";
+ else if (IS_R200_CLASS(radeon->radeonScreen))
+ chipclass = "R200";
+ else
+ chipclass = "R100";
+
+ sprintf(hardwarename, "%s (%s %04X)",
+ chipclass,
+ get_chip_family_name(radeon->radeonScreen->chip_family),
+ radeon->radeonScreen->device_id);
+
+ offset = driGetRendererString(buffer, hardwarename, DRIVER_DATE,
+ agp_mode);
+
+ if (IS_R600_CLASS(radeon->radeonScreen)) {
+ sprintf(&buffer[offset], " TCL");
+ } else if (IS_R300_CLASS(radeon->radeonScreen)) {
+ sprintf(&buffer[offset], " %sTCL",
+ (radeon->radeonScreen->chip_flags & RADEON_CHIPSET_TCL)
+ ? "" : "NO-");
+ } else {
+ sprintf(&buffer[offset], " %sTCL",
+ !(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
+ ? "" : "NO-");
+ }
+
+ if (radeon->radeonScreen->driScreen->dri2.enabled)
+ strcat(buffer, " DRI2");
+
+ return (GLubyte *) buffer;
+ }
+
+ default:
+ return NULL;
+ }
+}
+
+/* Initialize the driver's misc functions.
+ */
+static void radeonInitDriverFuncs(struct dd_function_table *functions)
+{
+ functions->GetString = radeonGetString;
+}
+
+/**
+ * Create and initialize all common fields of the context,
+ * including the Mesa context itself.
+ */
+GLboolean radeonInitContext(radeonContextPtr radeon,
+ struct dd_function_table* functions,
+ const __GLcontextModes * glVisual,
+ __DRIcontextPrivate * driContextPriv,
+ void *sharedContextPrivate)
+{
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
+ GLcontext* ctx;
+ GLcontext* shareCtx;
+ int fthrottle_mode;
+
+ /* Fill in additional standard functions. */
+ radeonInitDriverFuncs(functions);
+
+ radeon->radeonScreen = screen;
+ /* Allocate and initialize the Mesa context */
+ if (sharedContextPrivate)
+ shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx;
+ else
+ shareCtx = NULL;
+ radeon->glCtx = _mesa_create_context(glVisual, shareCtx,
+ functions, (void *)radeon);
+ if (!radeon->glCtx)
+ return GL_FALSE;
+
+ ctx = radeon->glCtx;
+ driContextPriv->driverPrivate = radeon;
+
+ meta_init_metaops(ctx, &radeon->meta);
+
+ _mesa_meta_init(ctx);
+
+ /* DRI fields */
+ radeon->dri.context = driContextPriv;
+ radeon->dri.screen = sPriv;
+ radeon->dri.hwContext = driContextPriv->hHWContext;
+ radeon->dri.hwLock = &sPriv->pSAREA->lock;
+ radeon->dri.hwLockCount = 0;
+ radeon->dri.fd = sPriv->fd;
+ radeon->dri.drmMinor = sPriv->drm_version.minor;
+
+ radeon->sarea = (drm_radeon_sarea_t *) ((GLubyte *) sPriv->pSAREA +
+ screen->sarea_priv_offset);
+
+ /* Setup IRQs */
+ fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode");
+ radeon->iw.irq_seq = -1;
+ radeon->irqsEmitted = 0;
+ if (IS_R600_CLASS(radeon->radeonScreen))
+ radeon->do_irqs = 0;
+ else
+ radeon->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
+ radeon->radeonScreen->irq);
+
+ radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
+
+ if (!radeon->do_irqs)
+ fprintf(stderr,
+ "IRQ's not enabled, falling back to %s: %d %d\n",
+ radeon->do_usleeps ? "usleeps" : "busy waits",
+ fthrottle_mode, radeon->radeonScreen->irq);
+
+ radeon->texture_depth = driQueryOptioni (&radeon->optionCache,
+ "texture_depth");
+ if (radeon->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
+ radeon->texture_depth = ( glVisual->rgbBits > 16 ) ?
+ DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
+
+ if (IS_R600_CLASS(radeon->radeonScreen)) {
+ radeon->texture_row_align = 256;
+ radeon->texture_rect_row_align = 256;
+ radeon->texture_compressed_row_align = 256;
+ } else if (IS_R200_CLASS(radeon->radeonScreen) ||
+ IS_R100_CLASS(radeon->radeonScreen)) {
+ radeon->texture_row_align = 32;
+ radeon->texture_rect_row_align = 64;
+ radeon->texture_compressed_row_align = 32;
+ } else { /* R300 - not sure this is all correct */
+ int chip_family = radeon->radeonScreen->chip_family;
+ if (chip_family == CHIP_FAMILY_RS600 ||
+ chip_family == CHIP_FAMILY_RS690 ||
+ chip_family == CHIP_FAMILY_RS740)
+ radeon->texture_row_align = 64;
+ else
+ radeon->texture_row_align = 32;
+ radeon->texture_rect_row_align = 64;
+ radeon->texture_compressed_row_align = 64;
+ }
+
+ make_empty_list(&radeon->query.not_flushed_head);
+ radeon_init_dma(radeon);
+
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Destroy the command buffer and state atoms.
+ */
+static void radeon_destroy_atom_list(radeonContextPtr radeon)
+{
+ struct radeon_state_atom *atom;
+
+ foreach(atom, &radeon->hw.atomlist) {
+ FREE(atom->cmd);
+ if (atom->lastcmd)
+ FREE(atom->lastcmd);
+ }
+
+}
+
+/**
+ * Cleanup common context fields.
+ * Called by r200DestroyContext/r300DestroyContext
+ */
+void radeonDestroyContext(__DRIcontextPrivate *driContextPriv )
+{
+#ifdef RADEON_BO_TRACK
+ FILE *track;
+#endif
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
+ radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
+
+ assert(radeon);
+
+ _mesa_meta_free(radeon->glCtx);
+
+ if (radeon == current) {
+ radeon_firevertices(radeon);
+ _mesa_make_current(NULL, NULL, NULL);
+ }
+
+ if (!is_empty_list(&radeon->dma.reserved)) {
+ rcommonFlushCmdBuf( radeon, __FUNCTION__ );
+ }
+
+ 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 );
+ _tnl_DestroyContext( radeon->glCtx );
+ _vbo_DestroyContext( radeon->glCtx );
+ _swrast_DestroyContext( radeon->glCtx );
+
+ /* free atom list */
+ /* free the Mesa context */
+ _mesa_destroy_context(radeon->glCtx);
+
+ /* _mesa_destroy_context() might result in calls to functions that
+ * depend on the DriverCtx, so don't set it to NULL before.
+ *
+ * radeon->glCtx->DriverCtx = NULL;
+ */
+ /* free the option cache */
+ driDestroyOptionCache(&radeon->optionCache);
+
+ rcommonDestroyCmdBuf(radeon);
+
+ radeon_destroy_atom_list(radeon);
+
+ if (radeon->state.scissor.pClipRects) {
+ FREE(radeon->state.scissor.pClipRects);
+ radeon->state.scissor.pClipRects = 0;
+ }
+#ifdef RADEON_BO_TRACK
+ track = fopen("/tmp/tracklog", "w");
+ if (track) {
+ radeon_tracker_print(&radeon->radeonScreen->bom->tracker, track);
+ fclose(track);
+ }
+#endif
+ FREE(radeon);
+}
+
+/* Force the context `c' to be unbound from its buffer.
+ */
+GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv)
+{
+ radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
+
+ if (RADEON_DEBUG & RADEON_DRI)
+ fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
+ radeon->glCtx);
+
+ return GL_TRUE;
+}
+
+
+static void
+radeon_make_kernel_renderbuffer_current(radeonContextPtr radeon,
+ struct radeon_framebuffer *draw)
+{
+ /* if radeon->fake */
+ struct radeon_renderbuffer *rb;
+
+ if ((rb = (void *)draw->base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
+ if (!rb->bo) {
+ rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ radeon->radeonScreen->frontOffset,
+ 0,
+ 0,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+ }
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
+ }
+ if ((rb = (void *)draw->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
+ if (!rb->bo) {
+ rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ radeon->radeonScreen->backOffset,
+ 0,
+ 0,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+ }
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->backPitch * rb->cpp;
+ }
+ if ((rb = (void *)draw->base.Attachment[BUFFER_DEPTH].Renderbuffer)) {
+ if (!rb->bo) {
+ rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ radeon->radeonScreen->depthOffset,
+ 0,
+ 0,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+ }
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
+ }
+ if ((rb = (void *)draw->base.Attachment[BUFFER_STENCIL].Renderbuffer)) {
+ if (!rb->bo) {
+ rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ radeon->radeonScreen->depthOffset,
+ 0,
+ 0,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+ }
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
+ }
+}
+
+static void
+radeon_make_renderbuffer_current(radeonContextPtr radeon,
+ struct radeon_framebuffer *draw)
+{
+ int size = 4096*4096*4;
+ /* if radeon->fake */
+ struct radeon_renderbuffer *rb;
+
+ if (radeon->radeonScreen->kernel_mm) {
+ radeon_make_kernel_renderbuffer_current(radeon, draw);
+ return;
+ }
+
+
+ if ((rb = (void *)draw->base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer)) {
+ if (!rb->bo) {
+ rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ radeon->radeonScreen->frontOffset +
+ radeon->radeonScreen->fbLocation,
+ size,
+ 4096,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+ }
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->frontPitch * rb->cpp;
+ }
+ if ((rb = (void *)draw->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer)) {
+ if (!rb->bo) {
+ rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ radeon->radeonScreen->backOffset +
+ radeon->radeonScreen->fbLocation,
+ size,
+ 4096,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+ }
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->backPitch * rb->cpp;
+ }
+ if ((rb = (void *)draw->base.Attachment[BUFFER_DEPTH].Renderbuffer)) {
+ if (!rb->bo) {
+ rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ radeon->radeonScreen->depthOffset +
+ radeon->radeonScreen->fbLocation,
+ size,
+ 4096,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+ }
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
+ }
+ if ((rb = (void *)draw->base.Attachment[BUFFER_STENCIL].Renderbuffer)) {
+ if (!rb->bo) {
+ rb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ radeon->radeonScreen->depthOffset +
+ radeon->radeonScreen->fbLocation,
+ size,
+ 4096,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+ }
+ rb->cpp = radeon->radeonScreen->cpp;
+ rb->pitch = radeon->radeonScreen->depthPitch * rb->cpp;
+ }
+}
+
+static unsigned
+radeon_bits_per_pixel(const struct radeon_renderbuffer *rb)
+{
+ switch (rb->base._ActualFormat) {
+ case GL_RGB5:
+ case GL_DEPTH_COMPONENT16:
+ return 16;
+ case GL_RGB8:
+ case GL_RGBA8:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH24_STENCIL8_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ return 32;
+ default:
+ return 0;
+ }
+}
+
+void
+radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+{
+ unsigned int attachments[10];
+ __DRIbuffer *buffers = NULL;
+ __DRIscreen *screen;
+ struct radeon_renderbuffer *rb;
+ int i, count;
+ struct radeon_framebuffer *draw;
+ radeonContextPtr radeon;
+ char *regname;
+ struct radeon_bo *depth_bo = NULL, *bo;
+
+ if (RADEON_DEBUG & RADEON_DRI)
+ fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
+
+ draw = drawable->driverPrivate;
+ screen = context->driScreenPriv;
+ radeon = (radeonContextPtr) context->driverPrivate;
+
+ if (screen->dri2.loader
+ && (screen->dri2.loader->base.version > 2)
+ && (screen->dri2.loader->getBuffersWithFormat != NULL)) {
+ struct radeon_renderbuffer *depth_rb;
+ struct radeon_renderbuffer *stencil_rb;
+
+ i = 0;
+ if ((radeon->is_front_buffer_rendering ||
+ radeon->is_front_buffer_reading ||
+ !draw->color_rb[1])
+ && draw->color_rb[0]) {
+ attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+ attachments[i++] = radeon_bits_per_pixel(draw->color_rb[0]);
+ }
+
+ if (draw->color_rb[1]) {
+ attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+ attachments[i++] = radeon_bits_per_pixel(draw->color_rb[1]);
+ }
+
+ depth_rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH);
+ stencil_rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL);
+
+ if ((depth_rb != NULL) && (stencil_rb != NULL)) {
+ attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
+ attachments[i++] = radeon_bits_per_pixel(depth_rb);
+ } else if (depth_rb != NULL) {
+ attachments[i++] = __DRI_BUFFER_DEPTH;
+ attachments[i++] = radeon_bits_per_pixel(depth_rb);
+ } else if (stencil_rb != NULL) {
+ attachments[i++] = __DRI_BUFFER_STENCIL;
+ attachments[i++] = radeon_bits_per_pixel(stencil_rb);
+ }
+
+ buffers = (*screen->dri2.loader->getBuffersWithFormat)(drawable,
+ &drawable->w,
+ &drawable->h,
+ attachments, i / 2,
+ &count,
+ drawable->loaderPrivate);
+ } else if (screen->dri2.loader) {
+ i = 0;
+ if (draw->color_rb[0])
+ attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
+ if (draw->color_rb[1])
+ attachments[i++] = __DRI_BUFFER_BACK_LEFT;
+ if (radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH))
+ attachments[i++] = __DRI_BUFFER_DEPTH;
+ if (radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL))
+ attachments[i++] = __DRI_BUFFER_STENCIL;
+
+ buffers = (*screen->dri2.loader->getBuffers)(drawable,
+ &drawable->w,
+ &drawable->h,
+ attachments, i,
+ &count,
+ drawable->loaderPrivate);
+ }
+
+ if (buffers == NULL)
+ return;
+
+ /* set one cliprect to cover the whole drawable */
+ drawable->x = 0;
+ drawable->y = 0;
+ drawable->backX = 0;
+ drawable->backY = 0;
+ drawable->numClipRects = 1;
+ drawable->pClipRects[0].x1 = 0;
+ drawable->pClipRects[0].y1 = 0;
+ drawable->pClipRects[0].x2 = drawable->w;
+ drawable->pClipRects[0].y2 = drawable->h;
+ drawable->numBackClipRects = 1;
+ drawable->pBackClipRects[0].x1 = 0;
+ drawable->pBackClipRects[0].y1 = 0;
+ drawable->pBackClipRects[0].x2 = drawable->w;
+ drawable->pBackClipRects[0].y2 = drawable->h;
+ for (i = 0; i < count; i++) {
+ switch (buffers[i].attachment) {
+ case __DRI_BUFFER_FRONT_LEFT:
+ rb = draw->color_rb[0];
+ regname = "dri2 front buffer";
+ break;
+ case __DRI_BUFFER_FAKE_FRONT_LEFT:
+ rb = draw->color_rb[0];
+ regname = "dri2 fake front buffer";
+ break;
+ case __DRI_BUFFER_BACK_LEFT:
+ rb = draw->color_rb[1];
+ regname = "dri2 back buffer";
+ break;
+ case __DRI_BUFFER_DEPTH:
+ rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH);
+ regname = "dri2 depth buffer";
+ break;
+ case __DRI_BUFFER_DEPTH_STENCIL:
+ rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH);
+ regname = "dri2 depth / stencil buffer";
+ break;
+ case __DRI_BUFFER_STENCIL:
+ rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL);
+ regname = "dri2 stencil buffer";
+ break;
+ case __DRI_BUFFER_ACCUM:
+ default:
+ fprintf(stderr,
+ "unhandled buffer attach event, attacment type %d\n",
+ buffers[i].attachment);
+ return;
+ }
+
+ if (rb == NULL)
+ continue;
+
+ if (rb->bo) {
+ uint32_t name = radeon_gem_name_bo(rb->bo);
+ if (name == buffers[i].name)
+ continue;
+ }
+
+ if (RADEON_DEBUG & RADEON_DRI)
+ fprintf(stderr,
+ "attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
+ regname, buffers[i].name, buffers[i].attachment,
+ buffers[i].cpp, buffers[i].pitch);
+
+ rb->cpp = buffers[i].cpp;
+ rb->pitch = buffers[i].pitch;
+ rb->base.Width = drawable->w;
+ rb->base.Height = drawable->h;
+ rb->has_surface = 0;
+
+ if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_bo) {
+ if (RADEON_DEBUG & RADEON_DRI)
+ fprintf(stderr, "(reusing depth buffer as stencil)\n");
+ bo = depth_bo;
+ radeon_bo_ref(bo);
+ } else {
+ uint32_t tiling_flags = 0, pitch = 0;
+ int ret;
+
+ bo = radeon_bo_open(radeon->radeonScreen->bom,
+ buffers[i].name,
+ 0,
+ 0,
+ RADEON_GEM_DOMAIN_VRAM,
+ buffers[i].flags);
+
+ if (bo == NULL) {
+
+ fprintf(stderr, "failed to attach %s %d\n",
+ regname, buffers[i].name);
+
+ }
+
+ ret = radeon_bo_get_tiling(bo, &tiling_flags, &pitch);
+ if (tiling_flags & RADEON_TILING_MACRO)
+ bo->flags |= RADEON_BO_FLAGS_MACRO_TILE;
+ if (tiling_flags & RADEON_TILING_MICRO)
+ bo->flags |= RADEON_BO_FLAGS_MICRO_TILE;
+
+ }
+
+ if (buffers[i].attachment == __DRI_BUFFER_DEPTH) {
+ if (draw->base.Visual.depthBits == 16)
+ rb->cpp = 2;
+ depth_bo = bo;
+ }
+
+ radeon_renderbuffer_set_bo(rb, bo);
+ radeon_bo_unref(bo);
+
+ if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) {
+ rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL);
+ if (rb != NULL) {
+ struct radeon_bo *stencil_bo = NULL;
+
+ if (rb->bo) {
+ uint32_t name = radeon_gem_name_bo(rb->bo);
+ if (name == buffers[i].name)
+ continue;
+ }
+
+ stencil_bo = bo;
+ radeon_bo_ref(stencil_bo);
+ radeon_renderbuffer_set_bo(rb, stencil_bo);
+ radeon_bo_unref(stencil_bo);
+ }
+ }
+ }
+
+ driUpdateFramebufferSize(radeon->glCtx, drawable);
+}
+
+/* Force the context `c' to be the current context and associate with it
+ * buffer `b'.
+ */
+GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
+ __DRIdrawablePrivate * driDrawPriv,
+ __DRIdrawablePrivate * driReadPriv)
+{
+ radeonContextPtr radeon;
+ struct radeon_framebuffer *drfb;
+ struct gl_framebuffer *readfb;
+
+ if (!driContextPriv) {
+ if (RADEON_DEBUG & RADEON_DRI)
+ fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
+ _mesa_make_current(NULL, NULL, NULL);
+ return GL_TRUE;
+ }
+
+ radeon = (radeonContextPtr) driContextPriv->driverPrivate;
+ drfb = driDrawPriv->driverPrivate;
+ readfb = driReadPriv->driverPrivate;
+
+ if (driContextPriv->driScreenPriv->dri2.enabled) {
+ radeon_update_renderbuffers(driContextPriv, driDrawPriv);
+ if (driDrawPriv != driReadPriv)
+ radeon_update_renderbuffers(driContextPriv, driReadPriv);
+ _mesa_reference_renderbuffer(&radeon->state.color.rb,
+ &(radeon_get_renderbuffer(&drfb->base, BUFFER_BACK_LEFT)->base));
+ _mesa_reference_renderbuffer(&radeon->state.depth.rb,
+ &(radeon_get_renderbuffer(&drfb->base, BUFFER_DEPTH)->base));
+ } else {
+ radeon_make_renderbuffer_current(radeon, drfb);
+ }
+
+ if (RADEON_DEBUG & RADEON_DRI)
+ fprintf(stderr, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__, radeon->glCtx, drfb, readfb);
+
+ driUpdateFramebufferSize(radeon->glCtx, driDrawPriv);
+ if (driReadPriv != driDrawPriv)
+ driUpdateFramebufferSize(radeon->glCtx, driReadPriv);
+
+ _mesa_make_current(radeon->glCtx, &drfb->base, readfb);
+
+ _mesa_update_state(radeon->glCtx);
+
+ if (radeon->glCtx->DrawBuffer == &drfb->base) {
+ if (driDrawPriv->swap_interval == (unsigned)-1) {
+ int i;
+ driDrawPriv->vblFlags =
+ (radeon->radeonScreen->irq != 0)
+ ? driGetDefaultVBlankFlags(&radeon->
+ optionCache)
+ : VBLANK_FLAG_NO_IRQ;
+
+ driDrawableInitVBlank(driDrawPriv);
+ drfb->vbl_waited = driDrawPriv->vblSeq;
+
+ for (i = 0; i < 2; i++) {
+ if (drfb->color_rb[i])
+ drfb->color_rb[i]->vbl_pending = driDrawPriv->vblSeq;
+ }
+
+ }
+
+ radeon_window_moved(radeon);
+ radeon_draw_buffer(radeon->glCtx, &drfb->base);
+ }
+
+
+ if (RADEON_DEBUG & RADEON_DRI)
+ fprintf(stderr, "End %s\n", __FUNCTION__);
+
+ return GL_TRUE;
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
new file mode 100644
index 0000000000..0309345393
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -0,0 +1,594 @@
+
+#ifndef COMMON_CONTEXT_H
+#define COMMON_CONTEXT_H
+
+#include "main/mm.h"
+#include "math/m_vector.h"
+#include "texmem.h"
+#include "tnl/t_context.h"
+#include "main/colormac.h"
+
+#include "radeon_debug.h"
+#include "radeon_screen.h"
+#include "radeon_drm.h"
+#include "dri_util.h"
+#include "tnl/t_vertex.h"
+
+#include "dri_metaops.h"
+struct radeon_context;
+
+#include "radeon_bocs_wrapper.h"
+
+/* This union is used to avoid warnings/miscompilation
+ with float to uint32_t casts due to strict-aliasing */
+typedef union { GLfloat f; uint32_t ui32; } float_ui32_type;
+
+struct radeon_context;
+typedef struct radeon_context radeonContextRec;
+typedef struct radeon_context *radeonContextPtr;
+
+
+#define TEX_0 0x1
+#define TEX_1 0x2
+#define TEX_2 0x4
+#define TEX_3 0x8
+#define TEX_4 0x10
+#define TEX_5 0x20
+
+/* Rasterizing fallbacks */
+/* See correponding strings in r200_swtcl.c */
+#define RADEON_FALLBACK_TEXTURE 0x0001
+#define RADEON_FALLBACK_DRAW_BUFFER 0x0002
+#define RADEON_FALLBACK_STENCIL 0x0004
+#define RADEON_FALLBACK_RENDER_MODE 0x0008
+#define RADEON_FALLBACK_BLEND_EQ 0x0010
+#define RADEON_FALLBACK_BLEND_FUNC 0x0020
+#define RADEON_FALLBACK_DISABLE 0x0040
+#define RADEON_FALLBACK_BORDER_MODE 0x0080
+#define RADEON_FALLBACK_DEPTH_BUFFER 0x0100
+#define RADEON_FALLBACK_STENCIL_BUFFER 0x0200
+
+#define R200_FALLBACK_TEXTURE 0x01
+#define R200_FALLBACK_DRAW_BUFFER 0x02
+#define R200_FALLBACK_STENCIL 0x04
+#define R200_FALLBACK_RENDER_MODE 0x08
+#define R200_FALLBACK_DISABLE 0x10
+#define R200_FALLBACK_BORDER_MODE 0x20
+
+#define RADEON_TCL_FALLBACK_RASTER 0x1 /* rasterization */
+#define RADEON_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */
+#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */
+#define RADEON_TCL_FALLBACK_MATERIAL 0x8 /* material in vb */
+#define RADEON_TCL_FALLBACK_TEXGEN_0 0x10 /* texgen, unit 0 */
+#define RADEON_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */
+#define RADEON_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */
+#define RADEON_TCL_FALLBACK_TCL_DISABLE 0x80 /* user disable */
+#define RADEON_TCL_FALLBACK_FOGCOORDSPEC 0x100 /* fogcoord, sep. spec light */
+
+/* The blit width for texture uploads
+ */
+#define BLIT_WIDTH_BYTES 1024
+
+/* Use the templated vertex format:
+ */
+#define COLOR_IS_RGBA
+#define TAG(x) radeon##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+#define RADEON_RB_CLASS 0xdeadbeef
+
+struct radeon_renderbuffer
+{
+ struct gl_renderbuffer base;
+ struct radeon_bo *bo;
+ unsigned int cpp;
+ /* unsigned int offset; */
+ unsigned int pitch;
+
+ uint32_t draw_offset; /* FBO */
+ /* boo Xorg 6.8.2 compat */
+ int has_surface;
+
+ GLuint pf_pending; /**< sequence number of pending flip */
+ GLuint vbl_pending; /**< vblank sequence number of pending flip */
+ __DRIdrawablePrivate *dPriv;
+};
+
+struct radeon_framebuffer
+{
+ struct gl_framebuffer base;
+
+ struct radeon_renderbuffer *color_rb[2];
+
+ GLuint vbl_waited;
+
+ /* buffer swap */
+ int64_t swap_ust;
+ int64_t swap_missed_ust;
+
+ GLuint swap_count;
+ GLuint swap_missed_count;
+
+ /* Drawable page flipping state */
+ GLboolean pf_active;
+ GLint pf_current_page;
+ GLint pf_num_pages;
+
+};
+
+
+struct radeon_colorbuffer_state {
+ GLuint clear;
+ int roundEnable;
+ struct gl_renderbuffer *rb;
+ uint32_t draw_offset; /* offset into color renderbuffer - FBOs */
+};
+
+struct radeon_depthbuffer_state {
+ GLuint clear;
+ struct gl_renderbuffer *rb;
+};
+
+struct radeon_scissor_state {
+ drm_clip_rect_t rect;
+ GLboolean enabled;
+
+ GLuint numClipRects; /* Cliprects active */
+ GLuint numAllocedClipRects; /* Cliprects available */
+ drm_clip_rect_t *pClipRects;
+};
+
+struct radeon_stencilbuffer_state {
+ GLuint clear; /* rb3d_stencilrefmask value */
+};
+
+struct radeon_state_atom {
+ struct radeon_state_atom *next, *prev;
+ const char *name; /* for debug */
+ int cmd_size; /* size in bytes */
+ GLuint idx;
+ GLuint is_tcl;
+ GLuint *cmd; /* one or more cmd's */
+ GLuint *lastcmd; /* one or more cmd's */
+ GLboolean dirty; /* dirty-mark in emit_state_list */
+ int (*check) (GLcontext *, struct radeon_state_atom *atom); /* is this state active? */
+ void (*emit) (GLcontext *, struct radeon_state_atom *atom);
+};
+
+struct radeon_hw_state {
+ /* Head of the linked list of state atoms. */
+ struct radeon_state_atom atomlist;
+ int max_state_size; /* Number of bytes necessary for a full state emit. */
+ int max_post_flush_size; /* Number of bytes necessary for post flushing emits */
+ GLboolean is_dirty, all_dirty;
+};
+
+
+/* Texture related */
+typedef struct _radeon_texture_image radeon_texture_image;
+
+struct _radeon_texture_image {
+ struct gl_texture_image base;
+
+ /**
+ * If mt != 0, the image is stored in hardware format in the
+ * given mipmap tree. In this case, base.Data may point into the
+ * mapping of the buffer object that contains the mipmap tree.
+ *
+ * If mt == 0, the image is stored in normal memory pointed to
+ * by base.Data.
+ */
+ struct _radeon_mipmap_tree *mt;
+ struct radeon_bo *bo;
+
+ int mtlevel; /** if mt != 0, this is the image's level in the mipmap tree */
+ int mtface; /** if mt != 0, this is the image's face in the mipmap tree */
+};
+
+
+static INLINE radeon_texture_image *get_radeon_texture_image(struct gl_texture_image *image)
+{
+ return (radeon_texture_image*)image;
+}
+
+
+typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr;
+
+#define RADEON_TXO_MICRO_TILE (1 << 3)
+
+/* Texture object in locally shared texture space.
+ */
+struct radeon_tex_obj {
+ struct gl_texture_object base;
+ struct _radeon_mipmap_tree *mt;
+
+ /**
+ * This is true if we've verified that the mipmap tree above is complete
+ * and so on.
+ */
+ GLboolean validated;
+
+ GLuint override_offset;
+ GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
+ GLuint tile_bits; /* hw texture tile bits used on this texture */
+ struct radeon_bo *bo;
+
+ GLuint pp_txfilter; /* hardware register values */
+ GLuint pp_txformat;
+ GLuint pp_txformat_x;
+ GLuint pp_txsize; /* npot only */
+ GLuint pp_txpitch; /* npot only */
+ GLuint pp_border_color;
+ GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */
+
+ GLuint pp_txfilter_1; /* r300 */
+
+ /* r700 texture states */
+ GLuint SQ_TEX_RESOURCE0;
+ GLuint SQ_TEX_RESOURCE1;
+ GLuint SQ_TEX_RESOURCE2;
+ GLuint SQ_TEX_RESOURCE3;
+ GLuint SQ_TEX_RESOURCE4;
+ GLuint SQ_TEX_RESOURCE5;
+ GLuint SQ_TEX_RESOURCE6;
+
+ GLuint SQ_TEX_SAMPLER0;
+ GLuint SQ_TEX_SAMPLER1;
+ GLuint SQ_TEX_SAMPLER2;
+
+ GLuint TD_PS_SAMPLER0_BORDER_RED;
+ GLuint TD_PS_SAMPLER0_BORDER_GREEN;
+ GLuint TD_PS_SAMPLER0_BORDER_BLUE;
+ GLuint TD_PS_SAMPLER0_BORDER_ALPHA;
+
+ GLboolean border_fallback;
+
+
+};
+
+static INLINE radeonTexObj* radeon_tex_obj(struct gl_texture_object *texObj)
+{
+ return (radeonTexObj*)texObj;
+}
+
+/* occlusion query */
+struct radeon_query_object {
+ struct gl_query_object Base;
+ struct radeon_bo *bo;
+ int curr_offset;
+ GLboolean emitted_begin;
+
+ /* Double linked list of not flushed query objects */
+ struct radeon_query_object *prev, *next;
+};
+
+/* Need refcounting on dma buffers:
+ */
+struct radeon_dma_buffer {
+ int refcount; /* the number of retained regions in buf */
+ drmBufPtr buf;
+};
+
+struct radeon_aos {
+ struct radeon_bo *bo; /** Buffer object where vertex data is stored */
+ int offset; /** Offset into buffer object, in bytes */
+ int components; /** Number of components per vertex */
+ int stride; /** Stride in dwords (may be 0 for repeating) */
+ int count; /** Number of vertices */
+};
+
+#define DMA_BO_FREE_TIME 100
+
+struct radeon_dma_bo {
+ struct radeon_dma_bo *next, *prev;
+ struct radeon_bo *bo;
+ int expire_counter;
+};
+
+struct radeon_dma {
+ /* Active dma region. Allocations for vertices and retained
+ * regions come from here. Also used for emitting random vertices,
+ * these may be flushed by calling flush_current();
+ */
+ struct radeon_dma_bo free;
+ struct radeon_dma_bo wait;
+ struct radeon_dma_bo reserved;
+ size_t current_used; /** Number of bytes allocated and forgotten about */
+ size_t current_vertexptr; /** End of active vertex region */
+ size_t minimum_size;
+
+ /**
+ * If current_vertexptr != current_used then flush must be non-zero.
+ * flush must be called before non-active vertex allocations can be
+ * performed.
+ */
+ void (*flush) (GLcontext *);
+};
+
+/* radeon_swtcl.c
+ */
+struct radeon_swtcl_info {
+
+ GLuint RenderIndex;
+ GLuint vertex_size;
+ GLubyte *verts;
+
+ /* Fallback rasterization functions
+ */
+ GLuint hw_primitive;
+ GLenum render_primitive;
+ GLuint numverts;
+
+ struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
+ GLuint vertex_attr_count;
+
+ GLuint emit_prediction;
+};
+
+#define RADEON_MAX_AOS_ARRAYS 16
+struct radeon_tcl_info {
+ struct radeon_aos aos[RADEON_MAX_AOS_ARRAYS];
+ GLuint aos_count;
+ struct radeon_bo *elt_dma_bo; /** Buffer object that contains element indices */
+ int elt_dma_offset; /** Offset into this buffer object, in bytes */
+};
+
+struct radeon_ioctl {
+ GLuint vertex_offset;
+ GLuint vertex_max;
+ struct radeon_bo *bo;
+ GLuint vertex_size;
+};
+
+#define RADEON_MAX_PRIMS 64
+
+struct radeon_prim {
+ GLuint start;
+ GLuint end;
+ GLuint prim;
+};
+
+static INLINE GLuint radeonPackColor(GLuint cpp,
+ GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a)
+{
+ switch (cpp) {
+ case 2:
+ return PACK_COLOR_565(r, g, b);
+ case 4:
+ return PACK_COLOR_8888(a, r, g, b);
+ default:
+ return 0;
+ }
+}
+
+#define MAX_CMD_BUF_SZ (16*1024)
+
+#define MAX_DMA_BUF_SZ (64*1024)
+
+struct radeon_store {
+ GLuint statenr;
+ GLuint primnr;
+ char cmd_buf[MAX_CMD_BUF_SZ];
+ int cmd_used;
+ int elts_start;
+};
+
+struct radeon_dri_mirror {
+ __DRIcontextPrivate *context; /* DRI context */
+ __DRIscreenPrivate *screen; /* DRI screen */
+
+ drm_context_t hwContext;
+ drm_hw_lock_t *hwLock;
+ int hwLockCount;
+ int fd;
+ int drmMinor;
+};
+
+typedef void (*radeon_tri_func) (radeonContextPtr,
+ radeonVertex *,
+ radeonVertex *, radeonVertex *);
+
+typedef void (*radeon_line_func) (radeonContextPtr,
+ radeonVertex *, radeonVertex *);
+
+typedef void (*radeon_point_func) (radeonContextPtr, radeonVertex *);
+
+#define RADEON_MAX_BOS 32
+struct radeon_state {
+ struct radeon_colorbuffer_state color;
+ struct radeon_depthbuffer_state depth;
+ struct radeon_scissor_state scissor;
+ struct radeon_stencilbuffer_state stencil;
+
+ struct radeon_cs_space_check bos[RADEON_MAX_BOS];
+ int validated_bo_count;
+};
+
+/**
+ * This structure holds the command buffer while it is being constructed.
+ *
+ * The first batch of commands in the buffer is always the state that needs
+ * to be re-emitted when the context is lost. This batch can be skipped
+ * otherwise.
+ */
+struct radeon_cmdbuf {
+ struct radeon_cs_manager *csm;
+ struct radeon_cs *cs;
+ int size; /** # of dwords total */
+ unsigned int flushing:1; /** whether we're currently in FlushCmdBufLocked */
+};
+
+struct radeon_context {
+ GLcontext *glCtx;
+ radeonScreenPtr radeonScreen; /* Screen private DRI data */
+
+ /* Texture object bookkeeping
+ */
+ int texture_depth;
+ float initialMaxAnisotropy;
+ uint32_t texture_row_align;
+ uint32_t texture_rect_row_align;
+ uint32_t texture_compressed_row_align;
+
+ struct radeon_dma dma;
+ struct radeon_hw_state hw;
+ /* Rasterization and vertex state:
+ */
+ GLuint TclFallback;
+ GLuint Fallback;
+ GLuint NewGLState;
+ DECLARE_RENDERINPUTS(tnl_index_bitset); /* index of bits for last tnl_install_attrs */
+
+ /* Drawable, cliprect and scissor information */
+ GLuint numClipRects; /* Cliprects for the draw buffer */
+ drm_clip_rect_t *pClipRects;
+ unsigned int lastStamp;
+ drm_radeon_sarea_t *sarea; /* Private SAREA data */
+
+ /* Mirrors of some DRI state */
+ struct radeon_dri_mirror dri;
+
+ /* Busy waiting */
+ GLuint do_usleeps;
+ GLuint do_irqs;
+ GLuint irqsEmitted;
+ drm_radeon_irq_wait_t iw;
+
+ /* Derived state - for r300 only */
+ struct radeon_state state;
+
+ struct radeon_swtcl_info swtcl;
+ struct radeon_tcl_info tcl;
+ /* Configuration cache
+ */
+ driOptionCache optionCache;
+
+ struct radeon_cmdbuf cmdbuf;
+
+ struct radeon_debug debug;
+
+ drm_clip_rect_t fboRect;
+ GLboolean constant_cliprect; /* use for FBO or DRI2 rendering */
+ GLboolean front_cliprects;
+
+ /**
+ * Set if rendering has occured to the drawable's front buffer.
+ *
+ * This is used in the DRI2 case to detect that glFlush should also copy
+ * the contents of the fake front buffer to the real front buffer.
+ */
+ GLboolean front_buffer_dirty;
+
+ /**
+ * Track whether front-buffer rendering is currently enabled
+ *
+ * A separate flag is used to track this in order to support MRT more
+ * easily.
+ */
+ GLboolean is_front_buffer_rendering;
+
+ /**
+ * Track whether front-buffer is the current read target.
+ *
+ * This is closely associated with is_front_buffer_rendering, but may
+ * be set separately. The DRI2 fake front buffer must be referenced
+ * either way.
+ */
+ GLboolean is_front_buffer_reading;
+
+ struct dri_metaops meta;
+
+ struct {
+ struct radeon_query_object *current;
+ struct radeon_query_object not_flushed_head;
+ struct radeon_state_atom queryobj;
+ } query;
+
+ struct {
+ void (*get_lock)(radeonContextPtr radeon);
+ void (*update_viewport_offset)(GLcontext *ctx);
+ void (*emit_cs_header)(struct radeon_cs *cs, radeonContextPtr rmesa);
+ void (*swtcl_flush)(GLcontext *ctx, uint32_t offset);
+ void (*pre_emit_atoms)(radeonContextPtr rmesa);
+ void (*pre_emit_state)(radeonContextPtr rmesa);
+ void (*fallback)(GLcontext *ctx, GLuint bit, GLboolean mode);
+ void (*free_context)(GLcontext *ctx);
+ void (*emit_query_finish)(radeonContextPtr radeon);
+ void (*update_scissor)(GLcontext *ctx);
+ } vtbl;
+};
+
+#define RADEON_CONTEXT(glctx) ((radeonContextPtr)(ctx->DriverCtx))
+
+static inline __DRIdrawablePrivate* radeon_get_drawable(radeonContextPtr radeon)
+{
+ return radeon->dri.context->driDrawablePriv;
+}
+
+static inline __DRIdrawablePrivate* radeon_get_readable(radeonContextPtr radeon)
+{
+ return radeon->dri.context->driReadablePriv;
+}
+
+/**
+ * This function takes a float and packs it into a uint32_t
+ */
+static INLINE uint32_t radeonPackFloat32(float fl)
+{
+ union {
+ float fl;
+ uint32_t u;
+ } u;
+
+ u.fl = fl;
+ return u.u;
+}
+
+/* This is probably wrong for some values, I need to test this
+ * some more. Range checking would be a good idea also..
+ *
+ * But it works for most things. I'll fix it later if someone
+ * else with a better clue doesn't
+ */
+static INLINE uint32_t radeonPackFloat24(float f)
+{
+ float mantissa;
+ int exponent;
+ uint32_t float24 = 0;
+
+ if (f == 0.0)
+ return 0;
+
+ mantissa = frexpf(f, &exponent);
+
+ /* Handle -ve */
+ if (mantissa < 0) {
+ float24 |= (1 << 23);
+ mantissa = mantissa * -1.0;
+ }
+ /* Handle exponent, bias of 63 */
+ exponent += 62;
+ float24 |= (exponent << 16);
+ /* Kill 7 LSB of mantissa */
+ float24 |= (radeonPackFloat32(mantissa) & 0x7FFFFF) >> 7;
+
+ return float24;
+}
+
+GLboolean radeonInitContext(radeonContextPtr radeon,
+ struct dd_function_table* functions,
+ const __GLcontextModes * glVisual,
+ __DRIcontextPrivate * driContextPriv,
+ void *sharedContextPrivate);
+
+void radeonCleanupContext(radeonContextPtr radeon);
+GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv);
+void radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable);
+GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
+ __DRIdrawablePrivate * driDrawPriv,
+ __DRIdrawablePrivate * driReadPriv);
+extern void radeonDestroyContext(__DRIcontextPrivate * driContextPriv);
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_compat.c b/src/mesa/drivers/dri/radeon/radeon_compat.c
deleted file mode 100644
index 46b490d61f..0000000000
--- a/src/mesa/drivers/dri/radeon/radeon_compat.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/**************************************************************************
-
-Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
- Tungsten Graphics Inc., Austin, Texas.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-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
-ATI, TUNGSTEN GRAPHICS 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:
- * Keith Whitwell <keith@tungstengraphics.com>
- *
- */
-
-#include "main/glheader.h"
-#include "main/imports.h"
-
-#include "radeon_context.h"
-#include "radeon_state.h"
-#include "radeon_ioctl.h"
-
-
-static struct {
- int start;
- int len;
- const char *name;
-} packet[RADEON_MAX_STATE_PACKETS] = {
- { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
- { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
- { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
- { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
- { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
- { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
- { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
- { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
- { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
- { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
- { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
- { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
- { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
- { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
- { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
- { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
- { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
- { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
- { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
- { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
- { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
-};
-
-
-static void radeonCompatEmitPacket( radeonContextPtr rmesa,
- struct radeon_state_atom *state )
-{
- drm_radeon_sarea_t *sarea = rmesa->sarea;
- drm_radeon_context_regs_t *ctx = &sarea->context_state;
- drm_radeon_texture_regs_t *tex0 = &sarea->tex_state[0];
- drm_radeon_texture_regs_t *tex1 = &sarea->tex_state[1];
- int i;
- int *buf = state->cmd;
-
- for ( i = 0 ; i < state->cmd_size ; ) {
- drm_radeon_cmd_header_t *header = (drm_radeon_cmd_header_t *)&buf[i++];
-
- if (RADEON_DEBUG & DEBUG_STATE)
- fprintf(stderr, "%s %d: %s\n", __FUNCTION__, header->packet.packet_id,
- packet[(int)header->packet.packet_id].name);
-
- switch (header->packet.packet_id) {
- case RADEON_EMIT_PP_MISC:
- ctx->pp_misc = buf[i++];
- ctx->pp_fog_color = buf[i++];
- ctx->re_solid_color = buf[i++];
- ctx->rb3d_blendcntl = buf[i++];
- ctx->rb3d_depthoffset = buf[i++];
- ctx->rb3d_depthpitch = buf[i++];
- ctx->rb3d_zstencilcntl = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_CONTEXT;
- break;
- case RADEON_EMIT_PP_CNTL:
- ctx->pp_cntl = buf[i++];
- ctx->rb3d_cntl = buf[i++];
- ctx->rb3d_coloroffset = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_CONTEXT;
- break;
- case RADEON_EMIT_RB3D_COLORPITCH:
- ctx->rb3d_colorpitch = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_CONTEXT;
- break;
- case RADEON_EMIT_RE_LINE_PATTERN:
- ctx->re_line_pattern = buf[i++];
- ctx->re_line_state = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_LINE;
- break;
- case RADEON_EMIT_SE_LINE_WIDTH:
- ctx->se_line_width = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_LINE;
- break;
- case RADEON_EMIT_PP_LUM_MATRIX:
- ctx->pp_lum_matrix = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_BUMPMAP;
- break;
- case RADEON_EMIT_PP_ROT_MATRIX_0:
- ctx->pp_rot_matrix_0 = buf[i++];
- ctx->pp_rot_matrix_1 = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_BUMPMAP;
- break;
- case RADEON_EMIT_RB3D_STENCILREFMASK:
- ctx->rb3d_stencilrefmask = buf[i++];
- ctx->rb3d_ropcntl = buf[i++];
- ctx->rb3d_planemask = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_MASKS;
- break;
- case RADEON_EMIT_SE_VPORT_XSCALE:
- ctx->se_vport_xscale = buf[i++];
- ctx->se_vport_xoffset = buf[i++];
- ctx->se_vport_yscale = buf[i++];
- ctx->se_vport_yoffset = buf[i++];
- ctx->se_vport_zscale = buf[i++];
- ctx->se_vport_zoffset = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_VIEWPORT;
- break;
- case RADEON_EMIT_SE_CNTL:
- ctx->se_cntl = buf[i++];
- ctx->se_coord_fmt = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_VERTFMT;
- break;
- case RADEON_EMIT_SE_CNTL_STATUS:
- ctx->se_cntl_status = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_SETUP;
- break;
- case RADEON_EMIT_RE_MISC:
- ctx->re_misc = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_MISC;
- break;
- case RADEON_EMIT_PP_TXFILTER_0:
- tex0->pp_txfilter = buf[i++];
- tex0->pp_txformat = buf[i++];
- tex0->pp_txoffset = buf[i++];
- tex0->pp_txcblend = buf[i++];
- tex0->pp_txablend = buf[i++];
- tex0->pp_tfactor = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_TEX0;
- break;
- case RADEON_EMIT_PP_BORDER_COLOR_0:
- tex0->pp_border_color = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_TEX0;
- break;
- case RADEON_EMIT_PP_TXFILTER_1:
- tex1->pp_txfilter = buf[i++];
- tex1->pp_txformat = buf[i++];
- tex1->pp_txoffset = buf[i++];
- tex1->pp_txcblend = buf[i++];
- tex1->pp_txablend = buf[i++];
- tex1->pp_tfactor = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_TEX1;
- break;
- case RADEON_EMIT_PP_BORDER_COLOR_1:
- tex1->pp_border_color = buf[i++];
- sarea->dirty |= RADEON_UPLOAD_TEX1;
- break;
-
- case RADEON_EMIT_SE_ZBIAS_FACTOR:
- i++;
- i++;
- break;
-
- case RADEON_EMIT_PP_TXFILTER_2:
- case RADEON_EMIT_PP_BORDER_COLOR_2:
- case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
- case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
- default:
- /* These states aren't understood by radeon drm 1.1 */
- fprintf(stderr, "Tried to emit unsupported state\n");
- return;
- }
- }
-}
-
-
-
-static void radeonCompatEmitStateLocked( radeonContextPtr rmesa )
-{
- struct radeon_state_atom *atom;
-
- if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
- return;
-
- foreach(atom, &rmesa->hw.atomlist) {
- if (rmesa->hw.all_dirty)
- atom->dirty = GL_TRUE;
- if (atom->is_tcl)
- atom->dirty = GL_FALSE;
- if (atom->dirty)
- radeonCompatEmitPacket(rmesa, atom);
- }
-
- rmesa->hw.is_dirty = GL_FALSE;
- rmesa->hw.all_dirty = GL_FALSE;
-}
-
-
-static void radeonCompatEmitPrimitiveLocked( radeonContextPtr rmesa,
- GLuint hw_primitive,
- GLuint nverts,
- drm_clip_rect_t *pbox,
- GLuint nbox )
-{
- int i;
-
- for ( i = 0 ; i < nbox ; ) {
- int nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, nbox );
- drm_clip_rect_t *b = rmesa->sarea->boxes;
- drm_radeon_vertex_t vtx;
-
- rmesa->sarea->dirty |= RADEON_UPLOAD_CLIPRECTS;
- rmesa->sarea->nbox = nr - i;
-
- for ( ; i < nr ; i++)
- *b++ = pbox[i];
-
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr,
- "RadeonFlushVertexBuffer: prim %x buf %d verts %d "
- "disc %d nbox %d\n",
- hw_primitive,
- rmesa->dma.current.buf->buf->idx,
- nverts,
- nr == nbox,
- rmesa->sarea->nbox );
-
- vtx.prim = hw_primitive;
- vtx.idx = rmesa->dma.current.buf->buf->idx;
- vtx.count = nverts;
- vtx.discard = (nr == nbox);
-
- drmCommandWrite( rmesa->dri.fd,
- DRM_RADEON_VERTEX,
- &vtx, sizeof(vtx));
- }
-}
-
-
-
-/* No 'start' for 1.1 vertices ioctl: only one vertex prim/buffer!
- */
-void radeonCompatEmitPrimitive( radeonContextPtr rmesa,
- GLuint vertex_format,
- GLuint hw_primitive,
- GLuint nrverts )
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- LOCK_HARDWARE( rmesa );
-
- radeonCompatEmitStateLocked( rmesa );
- rmesa->sarea->vc_format = vertex_format;
-
- if (rmesa->state.scissor.enabled) {
- radeonCompatEmitPrimitiveLocked( rmesa,
- hw_primitive,
- nrverts,
- rmesa->state.scissor.pClipRects,
- rmesa->state.scissor.numClipRects );
- }
- else {
- radeonCompatEmitPrimitiveLocked( rmesa,
- hw_primitive,
- nrverts,
- rmesa->pClipRects,
- rmesa->numClipRects );
- }
-
-
- UNLOCK_HARDWARE( rmesa );
-}
-
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c
index 1e992c0b3d..8f4485aee7 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_context.c
@@ -53,6 +53,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "drivers/common/driverfuncs.h"
+#include "radeon_common.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
@@ -61,13 +62,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_swtcl.h"
#include "radeon_tcl.h"
#include "radeon_maos.h"
+#include "radeon_queryobj.h"
-#define need_GL_ARB_multisample
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
+#define need_GL_ARB_occlusion_query
#define need_GL_EXT_blend_minmax
#define need_GL_EXT_fog_coord
#define need_GL_EXT_secondary_color
+#define need_GL_EXT_framebuffer_object
#include "extension_helper.h"
#define DRIVER_DATE "20061018"
@@ -75,58 +76,23 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "vblank.h"
#include "utils.h"
#include "xmlpool.h" /* for symbolic values of enum-type options */
-#ifndef RADEON_DEBUG
-int RADEON_DEBUG = (0);
-#endif
-
-
-/* Return various strings for glGetString().
- */
-static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- static char buffer[128];
- unsigned offset;
- GLuint agp_mode = (rmesa->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
- rmesa->radeonScreen->AGPMode;
-
- switch ( name ) {
- case GL_VENDOR:
- return (GLubyte *)"Tungsten Graphics, Inc.";
-
- case GL_RENDERER:
- offset = driGetRendererString( buffer, "Radeon", DRIVER_DATE,
- agp_mode );
-
- sprintf( & buffer[ offset ], " %sTCL",
- !(rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
- ? "" : "NO-" );
-
- return (GLubyte *)buffer;
-
- default:
- return NULL;
- }
-}
-
/* Extension strings exported by the R100 driver.
*/
const struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_multitexture", NULL },
+ { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions},
{ "GL_ARB_texture_border_clamp", NULL },
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
{ "GL_ARB_texture_env_add", NULL },
{ "GL_ARB_texture_env_combine", NULL },
{ "GL_ARB_texture_env_crossbar", NULL },
{ "GL_ARB_texture_env_dot3", NULL },
{ "GL_ARB_texture_mirrored_repeat", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_blend_logic_op", NULL },
{ "GL_EXT_blend_subtract", GL_EXT_blend_minmax_functions },
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
+ { "GL_EXT_packed_depth_stencil", NULL},
{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
{ "GL_EXT_stencil_wrap", NULL },
{ "GL_EXT_texture_edge_clamp", NULL },
@@ -143,6 +109,11 @@ const struct dri_extension card_extensions[] =
{ NULL, NULL }
};
+const struct dri_extension mm_extensions[] = {
+ { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+ { NULL, NULL }
+};
+
extern const struct tnl_pipeline_stage _radeon_render_stage;
extern const struct tnl_pipeline_stage _radeon_tcl_stage;
@@ -166,47 +137,85 @@ static const struct tnl_pipeline_stage *radeon_pipeline[] = {
NULL,
};
+static void r100_get_lock(radeonContextPtr radeon)
+{
+ r100ContextPtr rmesa = (r100ContextPtr)radeon;
+ drm_radeon_sarea_t *sarea = radeon->sarea;
+ RADEON_STATECHANGE(rmesa, ctx);
+ if (rmesa->radeon.sarea->tiling_enabled) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |=
+ RADEON_COLOR_TILE_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &=
+ ~RADEON_COLOR_TILE_ENABLE;
+ }
+
+ if (sarea->ctx_owner != rmesa->radeon.dri.hwContext) {
+ sarea->ctx_owner = rmesa->radeon.dri.hwContext;
+
+ if (!radeon->radeonScreen->kernel_mm)
+ radeon_bo_legacy_texture_age(radeon->radeonScreen->bom);
+ }
+}
-/* Initialize the driver's misc functions.
- */
-static void radeonInitDriverFuncs( struct dd_function_table *functions )
+static void r100_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
{
- functions->GetString = radeonGetString;
}
-static const struct dri_debug_control debug_control[] =
+static void r100_vtbl_pre_emit_state(radeonContextPtr radeon)
{
- { "fall", DEBUG_FALLBACKS },
- { "tex", DEBUG_TEXTURE },
- { "ioctl", DEBUG_IOCTL },
- { "prim", DEBUG_PRIMS },
- { "vert", DEBUG_VERTS },
- { "state", DEBUG_STATE },
- { "code", DEBUG_CODEGEN },
- { "vfmt", DEBUG_VFMT },
- { "vtxf", DEBUG_VFMT },
- { "verb", DEBUG_VERBOSE },
- { "dri", DEBUG_DRI },
- { "dma", DEBUG_DMA },
- { "san", DEBUG_SANITY },
- { "sync", DEBUG_SYNC },
- { NULL, 0 }
-};
+ r100ContextPtr rmesa = (r100ContextPtr)radeon;
+
+ /* r100 always needs to emit ZBS to avoid TCL lockups */
+ rmesa->hw.zbs.dirty = 1;
+ radeon->hw.is_dirty = 1;
+}
+static void r100_vtbl_free_context(GLcontext *ctx)
+{
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ _mesa_vector4f_free( &rmesa->tcl.ObjClean );
+}
+
+static void r100_emit_query_finish(radeonContextPtr radeon)
+{
+ BATCH_LOCALS(radeon);
+ struct radeon_query_object *query = radeon->query.current;
+
+ BEGIN_BATCH_NO_AUTOSTATE(4);
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0));
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ END_BATCH();
+ query->curr_offset += sizeof(uint32_t);
+ assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+ query->emitted_begin = GL_FALSE;
+}
+
+static void r100_init_vtbl(radeonContextPtr radeon)
+{
+ radeon->vtbl.get_lock = r100_get_lock;
+ radeon->vtbl.update_viewport_offset = radeonUpdateViewportOffset;
+ radeon->vtbl.emit_cs_header = r100_vtbl_emit_cs_header;
+ radeon->vtbl.swtcl_flush = r100_swtcl_flush;
+ radeon->vtbl.pre_emit_state = r100_vtbl_pre_emit_state;
+ radeon->vtbl.fallback = radeonFallback;
+ radeon->vtbl.free_context = r100_vtbl_free_context;
+ radeon->vtbl.emit_query_finish = r100_emit_query_finish;
+}
/* Create the device specific context.
*/
GLboolean
-radeonCreateContext( const __GLcontextModes *glVisual,
+r100CreateContext( const __GLcontextModes *glVisual,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate)
{
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
struct dd_function_table functions;
- radeonContextPtr rmesa;
- GLcontext *ctx, *shareCtx;
+ r100ContextPtr rmesa;
+ GLcontext *ctx;
int i;
int tcl_mode, fthrottle_mode;
@@ -215,10 +224,12 @@ radeonCreateContext( const __GLcontextModes *glVisual,
assert(screen);
/* Allocate the Radeon context */
- rmesa = (radeonContextPtr) CALLOC( sizeof(*rmesa) );
+ rmesa = (r100ContextPtr) CALLOC( sizeof(*rmesa) );
if ( !rmesa )
return GL_FALSE;
+ r100_init_vtbl(&rmesa->radeon);
+
/* init exp fog table data */
radeonInitStaticFogData();
@@ -226,12 +237,12 @@ radeonCreateContext( const __GLcontextModes *glVisual,
* Do this here so that initialMaxAnisotropy is set before we create
* the default textures.
*/
- driParseConfigFiles (&rmesa->optionCache, &screen->optionCache,
+ driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache,
screen->driScreen->myNum, "radeon");
- rmesa->initialMaxAnisotropy = driQueryOptionf(&rmesa->optionCache,
+ rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache,
"def_max_anisotropy");
- if ( driQueryOptionb( &rmesa->optionCache, "hyperz" ) ) {
+ if ( driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) {
if ( sPriv->drm_version.minor < 13 )
fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
"disabling.\n", sPriv->drm_version.minor );
@@ -246,65 +257,18 @@ radeonCreateContext( const __GLcontextModes *glVisual,
* (the texture functions are especially important)
*/
_mesa_init_driver_functions( &functions );
- radeonInitDriverFuncs( &functions );
radeonInitTextureFuncs( &functions );
+ radeonInitQueryObjFunctions(&functions);
- /* Allocate the Mesa context */
- if (sharedContextPrivate)
- shareCtx = ((radeonContextPtr) sharedContextPrivate)->glCtx;
- else
- shareCtx = NULL;
- rmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
- &functions, (void *) rmesa);
- if (!rmesa->glCtx) {
- FREE(rmesa);
- return GL_FALSE;
- }
- driContextPriv->driverPrivate = rmesa;
-
- /* Init radeon context data */
- rmesa->dri.context = driContextPriv;
- rmesa->dri.screen = sPriv;
- rmesa->dri.drawable = NULL;
- rmesa->dri.readable = NULL;
- rmesa->dri.hwContext = driContextPriv->hHWContext;
- rmesa->dri.hwLock = &sPriv->pSAREA->lock;
- rmesa->dri.fd = sPriv->fd;
- rmesa->dri.drmMinor = sPriv->drm_version.minor;
-
- rmesa->radeonScreen = screen;
- rmesa->sarea = (drm_radeon_sarea_t *)((GLubyte *)sPriv->pSAREA +
- screen->sarea_priv_offset);
-
-
- rmesa->dma.buf0_address = rmesa->radeonScreen->buffers->list[0].address;
-
- (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
- make_empty_list( & rmesa->swapped );
-
- rmesa->nr_heaps = screen->numTexHeaps;
- for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
- rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
- screen->texSize[i],
- 12,
- RADEON_NR_TEX_REGIONS,
- (drmTextureRegionPtr)rmesa->sarea->tex_list[i],
- & rmesa->sarea->tex_age[i],
- & rmesa->swapped,
- sizeof( radeonTexObj ),
- (destroy_texture_object_t *) radeonDestroyTexObj );
-
- driSetTextureSwapCounterLocation( rmesa->texture_heaps[i],
- & rmesa->c_textureSwaps );
+ if (!radeonInitContext(&rmesa->radeon, &functions,
+ glVisual, driContextPriv,
+ sharedContextPrivate)) {
+ FREE(rmesa);
+ return GL_FALSE;
}
- rmesa->texture_depth = driQueryOptioni (&rmesa->optionCache,
- "texture_depth");
- if (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
- rmesa->texture_depth = ( screen->cpp == 4 ) ?
- DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
- rmesa->swtcl.RenderIndex = ~0;
- rmesa->hw.all_dirty = GL_TRUE;
+ rmesa->radeon.swtcl.RenderIndex = ~0;
+ rmesa->radeon.hw.all_dirty = GL_TRUE;
/* Set the maximum texture size small enough that we can guarentee that
* all texture units can bind a maximal texture and have all of them in
@@ -312,26 +276,20 @@ radeonCreateContext( const __GLcontextModes *glVisual,
* setting allow larger textures.
*/
- ctx = rmesa->glCtx;
- ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->optionCache,
+ ctx = rmesa->radeon.glCtx;
+ ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache,
"texture_units");
ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
- i = driQueryOptioni( &rmesa->optionCache, "allow_large_textures");
-
- driCalculateMaxTextureLevels( rmesa->texture_heaps,
- rmesa->nr_heaps,
- & ctx->Const,
- 4,
- 11, /* max 2D texture size is 2048x2048 */
- 8, /* 256^3 */
- 9, /* \todo: max cube texture size seems to be 512x512(x6) */
- 11, /* max rect texture size is 2048x2048. */
- 12,
- GL_FALSE,
- i );
+ i = driQueryOptioni( &rmesa->radeon.optionCache, "allow_large_textures");
+ /* FIXME: When no memory manager is available we should set this
+ * to some reasonable value based on texture memory pool size */
+ ctx->Const.MaxTextureLevels = 12;
+ ctx->Const.Max3DTextureLevels = 9;
+ ctx->Const.MaxCubeTextureLevels = 12;
+ ctx->Const.MaxTextureRectSize = 2048;
ctx->Const.MaxTextureMaxAnisotropy = 16.0;
@@ -359,6 +317,10 @@ radeonCreateContext( const __GLcontextModes *glVisual,
rmesa->boxes = 0;
+ ctx->Const.MaxDrawBuffers = 1;
+
+ _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
+
/* Initialize the software rasterizer and helper modules.
*/
_swrast_CreateContext( ctx );
@@ -392,38 +354,42 @@ radeonCreateContext( const __GLcontextModes *glVisual,
}
driInitExtensions( ctx, card_extensions, GL_TRUE );
- if (rmesa->radeonScreen->drmSupportsCubeMapsR100)
+ if (rmesa->radeon.radeonScreen->kernel_mm)
+ driInitExtensions(ctx, mm_extensions, GL_FALSE);
+ if (rmesa->radeon.radeonScreen->drmSupportsCubeMapsR100)
_mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" );
- if (rmesa->glCtx->Mesa_DXTn) {
+ if (rmesa->radeon.glCtx->Mesa_DXTn) {
_mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
_mesa_enable_extension( ctx, "GL_S3_s3tc" );
}
- else if (driQueryOptionb (&rmesa->optionCache, "force_s3tc_enable")) {
+ else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) {
_mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
}
- if (rmesa->dri.drmMinor >= 9)
+ if (rmesa->radeon.radeonScreen->kernel_mm || rmesa->radeon.dri.drmMinor >= 9)
_mesa_enable_extension( ctx, "GL_NV_texture_rectangle");
+ if (!rmesa->radeon.radeonScreen->kernel_mm)
+ _mesa_disable_extension(ctx, "GL_ARB_occlusion_query");
+
/* XXX these should really go right after _mesa_init_driver_functions() */
- radeonInitIoctlFuncs( ctx );
- radeonInitStateFuncs( ctx );
+ radeon_fbo_init(&rmesa->radeon);
radeonInitSpanFuncs( ctx );
+ radeonInitIoctlFuncs( ctx );
+ radeonInitStateFuncs( ctx , rmesa->radeon.radeonScreen->kernel_mm );
radeonInitState( rmesa );
radeonInitSwtcl( ctx );
_mesa_vector4f_alloc( &rmesa->tcl.ObjClean, 0,
ctx->Const.MaxArrayLockSize, 32 );
- fthrottle_mode = driQueryOptioni(&rmesa->optionCache, "fthrottle_mode");
- rmesa->iw.irq_seq = -1;
- rmesa->irqsEmitted = 0;
- rmesa->do_irqs = (rmesa->radeonScreen->irq != 0 &&
- fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS);
+ fthrottle_mode = driQueryOptioni(&rmesa->radeon.optionCache, "fthrottle_mode");
+ rmesa->radeon.iw.irq_seq = -1;
+ rmesa->radeon.irqsEmitted = 0;
+ rmesa->radeon.do_irqs = (rmesa->radeon.radeonScreen->irq != 0 &&
+ fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS);
- rmesa->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
-
- (*sPriv->systemTime->getUST)( & rmesa->swap_ust );
+ rmesa->radeon.do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
#if DO_DEBUG
@@ -431,206 +397,21 @@ radeonCreateContext( const __GLcontextModes *glVisual,
debug_control );
#endif
- tcl_mode = driQueryOptioni(&rmesa->optionCache, "tcl_mode");
- if (driQueryOptionb(&rmesa->optionCache, "no_rast")) {
+ tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode");
+ if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) {
fprintf(stderr, "disabling 3D acceleration\n");
FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1);
} else if (tcl_mode == DRI_CONF_TCL_SW ||
- !(rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
- if (rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
- rmesa->radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
+ !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
+ if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
+ rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
fprintf(stderr, "Disabling HW TCL support\n");
}
- TCL_FALLBACK(rmesa->glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
+ TCL_FALLBACK(rmesa->radeon.glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
}
- if (rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
+ if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
/* _tnl_need_dlist_norm_lengths( ctx, GL_FALSE ); */
}
return GL_TRUE;
}
-
-
-/* Destroy the device specific context.
- */
-/* Destroy the Mesa and driver specific context data.
- */
-void radeonDestroyContext( __DRIcontextPrivate *driContextPriv )
-{
- GET_CURRENT_CONTEXT(ctx);
- radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
- radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
-
- /* check if we're deleting the currently bound context */
- if (rmesa == current) {
- RADEON_FIREVERTICES( rmesa );
- _mesa_make_current(NULL, NULL, NULL);
- }
-
- /* Free radeon context resources */
- assert(rmesa); /* should never be null */
- if ( rmesa ) {
- GLboolean release_texture_heaps;
-
-
- release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
- _swsetup_DestroyContext( rmesa->glCtx );
- _tnl_DestroyContext( rmesa->glCtx );
- _vbo_DestroyContext( rmesa->glCtx );
- _swrast_DestroyContext( rmesa->glCtx );
-
- radeonDestroySwtcl( rmesa->glCtx );
- radeonReleaseArrays( rmesa->glCtx, ~0 );
- if (rmesa->dma.current.buf) {
- radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
- radeonFlushCmdBuf( rmesa, __FUNCTION__ );
- }
-
- _mesa_vector4f_free( &rmesa->tcl.ObjClean );
-
- if (rmesa->state.scissor.pClipRects) {
- FREE(rmesa->state.scissor.pClipRects);
- rmesa->state.scissor.pClipRects = NULL;
- }
-
- if ( release_texture_heaps ) {
- /* This share group is about to go away, free our private
- * texture object data.
- */
- int i;
-
- for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
- driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
- rmesa->texture_heaps[ i ] = NULL;
- }
-
- assert( is_empty_list( & rmesa->swapped ) );
- }
-
- /* free the Mesa context */
- rmesa->glCtx->DriverCtx = NULL;
- _mesa_destroy_context( rmesa->glCtx );
-
- /* free the option cache */
- driDestroyOptionCache (&rmesa->optionCache);
-
- FREE( rmesa );
- }
-}
-
-
-
-
-void
-radeonSwapBuffers( __DRIdrawablePrivate *dPriv )
-{
-
- if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
- radeonContextPtr rmesa;
- GLcontext *ctx;
- rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
- ctx = rmesa->glCtx;
- if (ctx->Visual.doubleBufferMode) {
- _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
-
- if ( rmesa->doPageFlip ) {
- radeonPageFlip( dPriv );
- }
- else {
- radeonCopyBuffer( dPriv, NULL );
- }
- }
- }
- else {
- /* XXX this shouldn't be an error but we can't handle it for now */
- _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
- }
-}
-
-void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
- int x, int y, int w, int h )
-{
- if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
- radeonContextPtr radeon;
- GLcontext *ctx;
-
- radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
- ctx = radeon->glCtx;
-
- if (ctx->Visual.doubleBufferMode) {
- drm_clip_rect_t rect;
- rect.x1 = x + dPriv->x;
- rect.y1 = (dPriv->h - y - h) + dPriv->y;
- rect.x2 = rect.x1 + w;
- rect.y2 = rect.y1 + h;
- _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
- radeonCopyBuffer(dPriv, &rect);
- }
- } else {
- /* XXX this shouldn't be an error but we can't handle it for now */
- _mesa_problem(NULL, "%s: drawable has no context!",
- __FUNCTION__);
- }
-}
-
-/* Make context `c' the current context and bind it to the given
- * drawing and reading surfaces.
- */
-GLboolean
-radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
- __DRIdrawablePrivate *driDrawPriv,
- __DRIdrawablePrivate *driReadPriv )
-{
- if ( driContextPriv ) {
- radeonContextPtr newCtx =
- (radeonContextPtr) driContextPriv->driverPrivate;
-
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *) newCtx->glCtx);
-
- newCtx->dri.readable = driReadPriv;
-
- if ( (newCtx->dri.drawable != driDrawPriv) ||
- newCtx->lastStamp != driDrawPriv->lastStamp ) {
- if (driDrawPriv->swap_interval == (unsigned)-1) {
- driDrawPriv->vblFlags = (newCtx->radeonScreen->irq != 0)
- ? driGetDefaultVBlankFlags(&newCtx->optionCache)
- : VBLANK_FLAG_NO_IRQ;
-
- driDrawableInitVBlank( driDrawPriv );
- }
-
- newCtx->dri.drawable = driDrawPriv;
-
- radeonSetCliprects(newCtx);
- radeonUpdateViewportOffset( newCtx->glCtx );
- }
-
- _mesa_make_current( newCtx->glCtx,
- (GLframebuffer *) driDrawPriv->driverPrivate,
- (GLframebuffer *) driReadPriv->driverPrivate );
-
- _mesa_update_state( newCtx->glCtx );
- } else {
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
- _mesa_make_current( NULL, NULL, NULL );
- }
-
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "End %s\n", __FUNCTION__);
- return GL_TRUE;
-}
-
-/* Force the context `c' to be unbound from its buffer.
- */
-GLboolean
-radeonUnbindContext( __DRIcontextPrivate *driContextPriv )
-{
- radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
-
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *) rmesa->glCtx);
-
- return GL_TRUE;
-}
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.h b/src/mesa/drivers/dri/radeon/radeon_context.h
index 53df766f8c..4e2c52c835 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_context.h
@@ -48,91 +48,23 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "drm.h"
#include "radeon_drm.h"
#include "texmem.h"
-
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/colormac.h"
-
-struct radeon_context;
-typedef struct radeon_context radeonContextRec;
-typedef struct radeon_context *radeonContextPtr;
-
-/* This union is used to avoid warnings/miscompilation
- with float to uint32_t casts due to strict-aliasing */
-typedef union {
- GLfloat f;
- uint32_t ui32;
-} float_ui32_type;
-
-#include "radeon_lock.h"
#include "radeon_screen.h"
-#include "main/mm.h"
-
-#include "math/m_vector.h"
-
-#define TEX_0 0x1
-#define TEX_1 0x2
-#define TEX_2 0x4
-#define TEX_ALL 0x7
-
-/* Rasterizing fallbacks */
-/* See correponding strings in r200_swtcl.c */
-#define RADEON_FALLBACK_TEXTURE 0x0001
-#define RADEON_FALLBACK_DRAW_BUFFER 0x0002
-#define RADEON_FALLBACK_STENCIL 0x0004
-#define RADEON_FALLBACK_RENDER_MODE 0x0008
-#define RADEON_FALLBACK_BLEND_EQ 0x0010
-#define RADEON_FALLBACK_BLEND_FUNC 0x0020
-#define RADEON_FALLBACK_DISABLE 0x0040
-#define RADEON_FALLBACK_BORDER_MODE 0x0080
-
-/* The blit width for texture uploads
- */
-#define BLIT_WIDTH_BYTES 1024
-/* Use the templated vertex format:
- */
-#define COLOR_IS_RGBA
-#define TAG(x) radeon##x
-#include "tnl_dd/t_dd_vertex.h"
-#undef TAG
-
-typedef void (*radeon_tri_func) (radeonContextPtr,
- radeonVertex *,
- radeonVertex *, radeonVertex *);
-
-typedef void (*radeon_line_func) (radeonContextPtr,
- radeonVertex *, radeonVertex *);
+#include "radeon_common.h"
-typedef void (*radeon_point_func) (radeonContextPtr, radeonVertex *);
-
-struct radeon_colorbuffer_state {
- GLuint clear;
- int roundEnable;
-};
-struct radeon_depthbuffer_state {
- GLuint clear;
- GLfloat scale;
-};
+struct r100_context;
+typedef struct r100_context r100ContextRec;
+typedef struct r100_context *r100ContextPtr;
-struct radeon_scissor_state {
- drm_clip_rect_t rect;
- GLboolean enabled;
+#include "radeon_lock.h"
- GLuint numClipRects; /* Cliprects active */
- GLuint numAllocedClipRects; /* Cliprects available */
- drm_clip_rect_t *pClipRects;
-};
-struct radeon_stencilbuffer_state {
- GLboolean hwBuffer;
- GLuint clear; /* rb3d_stencilrefmask value */
-};
-struct radeon_stipple_state {
- GLuint mask[32];
-};
+#define R100_TEX_ALL 0x7
/* used for both tcl_vtx and vc_frmt tex bits (they are identical) */
#define RADEON_ST_BIT(unit) \
@@ -141,42 +73,6 @@ struct radeon_stipple_state {
#define RADEON_Q_BIT(unit) \
(unit == 0 ? RADEON_CP_VC_FRMT_Q0 : (RADEON_CP_VC_FRMT_Q1 >> 2) << (2 * unit))
-typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr;
-
-/* Texture object in locally shared texture space.
- */
-struct radeon_tex_obj {
- driTextureObject base;
-
- GLuint bufAddr; /* Offset to start of locally
- shared texture block */
-
- GLuint dirty_state; /* Flags (1 per texunit) for
- whether or not this texobj
- has dirty hardware state
- (pp_*) that needs to be
- brought into the
- texunit. */
-
- drm_radeon_tex_image_t image[6][RADEON_MAX_TEXTURE_LEVELS];
- /* Six, for the cube faces */
-
- GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
-
- GLuint pp_txfilter; /* hardware register values */
- GLuint pp_txformat;
- GLuint pp_txoffset; /* Image location in texmem.
- All cube faces follow. */
- GLuint pp_txsize; /* npot only */
- GLuint pp_txpitch; /* npot only */
- GLuint pp_border_color;
- GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */
-
- GLboolean border_fallback;
-
- GLuint tile_bits; /* hw texture tile bits used on this texture */
-};
-
struct radeon_texture_env_state {
radeonTexObjPtr texobj;
GLenum format;
@@ -187,17 +83,6 @@ struct radeon_texture_state {
struct radeon_texture_env_state unit[RADEON_MAX_TEXTURE_UNITS];
};
-struct radeon_state_atom {
- struct radeon_state_atom *next, *prev;
- const char *name; /* for debug */
- int cmd_size; /* size in bytes */
- GLuint is_tcl;
- int *cmd; /* one or more cmd's */
- int *lastcmd; /* one or more cmd's */
- GLboolean dirty; /* dirty-mark in emit_state_list */
- GLboolean(*check) (GLcontext *); /* is this state active? */
-};
-
/* Trying to keep these relatively short as the variables are becoming
* extravagently long. Drop the driver name prefix off the front of
* everything - I think we know which driver we're in by now, and keep the
@@ -410,10 +295,16 @@ struct radeon_state_atom {
#define SHN_SHININESS 1
#define SHN_STATE_SIZE 2
-struct radeon_hw_state {
- /* Head of the linked list of state atoms. */
- struct radeon_state_atom atomlist;
+#define R100_QUERYOBJ_CMD_0 0
+#define R100_QUERYOBJ_DATA_0 1
+#define R100_QUERYOBJ_CMDSIZE 2
+
+#define STP_CMD_0 0
+#define STP_DATA_0 1
+#define STP_CMD_1 2
+#define STP_STATE_SIZE 35
+struct r100_hw_state {
/* Hardware state, stored as cmdbuf commands:
* -- Need to doublebuffer for
* - eliding noop statechange loops? (except line stipple count)
@@ -437,90 +328,19 @@ struct radeon_hw_state {
struct radeon_state_atom fog;
struct radeon_state_atom glt;
struct radeon_state_atom txr[3]; /* for NPOT */
-
- int max_state_size; /* Number of bytes necessary for a full state emit. */
- GLboolean is_dirty, all_dirty;
-};
-
-struct radeon_state {
- /* Derived state for internal purposes:
- */
- struct radeon_colorbuffer_state color;
- struct radeon_depthbuffer_state depth;
- struct radeon_scissor_state scissor;
- struct radeon_stencilbuffer_state stencil;
- struct radeon_stipple_state stipple;
- struct radeon_texture_state texture;
-};
-
-/* Need refcounting on dma buffers:
- */
-struct radeon_dma_buffer {
- int refcount; /* the number of retained regions in buf */
- drmBufPtr buf;
-};
-
-#define GET_START(rvb) (rmesa->radeonScreen->gart_buffer_offset + \
- (rvb)->address - rmesa->dma.buf0_address + \
- (rvb)->start)
-
-/* A retained region, eg vertices for indexed vertices.
- */
-struct radeon_dma_region {
- struct radeon_dma_buffer *buf;
- char *address; /* == buf->address */
- int start, end, ptr; /* offsets from start of buf */
- int aos_start;
- int aos_stride;
- int aos_size;
-};
-
-struct radeon_dma {
- /* Active dma region. Allocations for vertices and retained
- * regions come from here. Also used for emitting random vertices,
- * these may be flushed by calling flush_current();
- */
- struct radeon_dma_region current;
-
- void (*flush) (radeonContextPtr);
-
- char *buf0_address; /* start of buf[0], for index calcs */
- GLuint nr_released_bufs; /* flush after so many buffers released */
+ struct radeon_state_atom stp;
};
-struct radeon_dri_mirror {
- __DRIcontextPrivate *context; /* DRI context */
- __DRIscreenPrivate *screen; /* DRI screen */
-
- /**
- * DRI drawable bound to this context for drawing.
- */
- __DRIdrawablePrivate *drawable;
- /**
- * DRI drawable bound to this context for reading.
- */
- __DRIdrawablePrivate *readable;
-
- drm_context_t hwContext;
- drm_hw_lock_t *hwLock;
- int fd;
- int drmMinor;
+struct r100_state {
+ struct radeon_texture_state texture;
};
#define RADEON_CMD_BUF_SZ (8*1024)
-
-struct radeon_store {
- GLuint statenr;
- GLuint primnr;
- char cmd_buf[RADEON_CMD_BUF_SZ];
- int cmd_used;
- int elts_start;
-};
-
+#define R200_ELT_BUF_SZ (8*1024)
/* radeon_tcl.c
*/
-struct radeon_tcl_info {
+struct r100_tcl_info {
GLuint vertex_format;
GLuint hw_primitive;
@@ -529,30 +349,18 @@ struct radeon_tcl_info {
*/
GLvector4f ObjClean;
- struct radeon_dma_region *aos_components[8];
- GLuint nr_aos_components;
-
GLuint *Elts;
- struct radeon_dma_region indexed_verts;
- struct radeon_dma_region obj;
- struct radeon_dma_region rgba;
- struct radeon_dma_region spec;
- struct radeon_dma_region fog;
- struct radeon_dma_region tex[RADEON_MAX_TEXTURE_UNITS];
- struct radeon_dma_region norm;
+ int elt_cmd_offset;
+ int elt_cmd_start;
+ int elt_used;
};
/* radeon_swtcl.c
*/
-struct radeon_swtcl_info {
- GLuint RenderIndex;
- GLuint vertex_size;
+struct r100_swtcl_info {
GLuint vertex_format;
- struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
- GLuint vertex_attr_count;
-
GLubyte *verts;
/* Fallback rasterization functions
@@ -561,10 +369,6 @@ struct radeon_swtcl_info {
radeon_line_func draw_line;
radeon_tri_func draw_tri;
- GLuint hw_primitive;
- GLenum render_primitive;
- GLuint numverts;
-
/**
* Offset of the 4UB color data within a hardware (swtcl) vertex.
*/
@@ -576,22 +380,9 @@ struct radeon_swtcl_info {
GLuint specoffset;
GLboolean needproj;
-
- struct radeon_dma_region indexed_verts;
};
-struct radeon_ioctl {
- GLuint vertex_offset;
- GLuint vertex_size;
-};
-#define RADEON_MAX_PRIMS 64
-
-struct radeon_prim {
- GLuint start;
- GLuint end;
- GLuint prim;
-};
/* A maximum total of 20 elements per vertex: 3 floats for position, 3
* floats for normal, 4 floats for color, 4 bytes for secondary color,
@@ -602,59 +393,18 @@ struct radeon_prim {
*/
#define RADEON_MAX_VERTEX_SIZE 20
-struct radeon_context {
- GLcontext *glCtx; /* Mesa context */
+struct r100_context {
+ struct radeon_context radeon;
/* Driver and hardware state management
*/
- struct radeon_hw_state hw;
- struct radeon_state state;
-
- /* Texture object bookkeeping
- */
- unsigned nr_heaps;
- driTexHeap *texture_heaps[RADEON_NR_TEX_HEAPS];
- driTextureObject swapped;
- int texture_depth;
- float initialMaxAnisotropy;
-
- /* Rasterization and vertex state:
- */
- GLuint TclFallback;
- GLuint Fallback;
- GLuint NewGLState;
- DECLARE_RENDERINPUTS(tnl_index_bitset); /* index of bits for last tnl_install_attrs */
+ struct r100_hw_state hw;
+ struct r100_state state;
/* Vertex buffers
*/
struct radeon_ioctl ioctl;
- struct radeon_dma dma;
struct radeon_store store;
- /* A full state emit as of the first state emit in the main store, in case
- * the context is lost.
- */
- struct radeon_store backup_store;
-
- /* Page flipping
- */
- GLuint doPageFlip;
-
- /* Busy waiting
- */
- GLuint do_usleeps;
- GLuint do_irqs;
- GLuint irqsEmitted;
- drm_radeon_irq_wait_t iw;
-
- /* Drawable, cliprect and scissor information
- */
- GLuint numClipRects; /* Cliprects for the draw buffer */
- drm_clip_rect_t *pClipRects;
- unsigned int lastStamp;
- GLboolean lost_context;
- GLboolean save_on_next_emit;
- radeonScreenPtr radeonScreen; /* Screen private DRI data */
- drm_radeon_sarea_t *sarea; /* Private SAREA data */
/* TCL stuff
*/
@@ -667,29 +417,13 @@ struct radeon_context {
GLmatrix tmpmat[RADEON_MAX_TEXTURE_UNITS];
GLuint last_ReallyEnabled;
- /* VBI
- */
- int64_t swap_ust;
- int64_t swap_missed_ust;
-
- GLuint swap_count;
- GLuint swap_missed_count;
-
/* radeon_tcl.c
*/
- struct radeon_tcl_info tcl;
+ struct r100_tcl_info tcl;
/* radeon_swtcl.c
*/
- struct radeon_swtcl_info swtcl;
-
- /* Mirrors of some DRI state
- */
- struct radeon_dri_mirror dri;
-
- /* Configuration cache
- */
- driOptionCache optionCache;
+ struct r100_swtcl_info swtcl;
GLboolean using_hyperz;
GLboolean texmicrotile;
@@ -703,61 +437,19 @@ struct radeon_context {
GLuint c_textureSwaps;
GLuint c_textureBytes;
GLuint c_vertexBuffers;
+
};
-#define RADEON_CONTEXT(ctx) ((radeonContextPtr)(ctx->DriverCtx))
-
-static INLINE GLuint radeonPackColor(GLuint cpp,
- GLubyte r, GLubyte g,
- GLubyte b, GLubyte a)
-{
- switch (cpp) {
- case 2:
- return PACK_COLOR_565(r, g, b);
- case 4:
- return PACK_COLOR_8888(a, r, g, b);
- default:
- return 0;
- }
-}
+
+#define R100_CONTEXT(ctx) ((r100ContextPtr)(ctx->DriverCtx))
+
#define RADEON_OLD_PACKETS 1
-extern void radeonDestroyContext(__DRIcontextPrivate * driContextPriv);
-extern GLboolean radeonCreateContext(const __GLcontextModes * glVisual,
- __DRIcontextPrivate * driContextPriv,
- void *sharedContextPrivate);
-extern void radeonSwapBuffers(__DRIdrawablePrivate * dPriv);
-extern void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
- int x, int y, int w, int h);
-extern GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
- __DRIdrawablePrivate * driDrawPriv,
- __DRIdrawablePrivate * driReadPriv);
-extern GLboolean radeonUnbindContext(__DRIcontextPrivate * driContextPriv);
-
-/* ================================================================
- * Debugging:
- */
-#define DO_DEBUG 1
-
-#if DO_DEBUG
-extern int RADEON_DEBUG;
-#else
-#define RADEON_DEBUG 0
-#endif
-
-#define DEBUG_TEXTURE 0x0001
-#define DEBUG_STATE 0x0002
-#define DEBUG_IOCTL 0x0004
-#define DEBUG_PRIMS 0x0008
-#define DEBUG_VERTS 0x0010
-#define DEBUG_FALLBACKS 0x0020
-#define DEBUG_VFMT 0x0040
-#define DEBUG_CODEGEN 0x0080
-#define DEBUG_VERBOSE 0x0100
-#define DEBUG_DRI 0x0200
-#define DEBUG_DMA 0x0400
-#define DEBUG_SANITY 0x0800
-#define DEBUG_SYNC 0x1000
+extern GLboolean r100CreateContext( const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate);
+
+
#endif /* __RADEON_CONTEXT_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_cs_drm.h b/src/mesa/drivers/dri/radeon/radeon_cs_drm.h
new file mode 100644
index 0000000000..ab4eca31a3
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_cs_drm.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright © 2008 Nicolai Haehnle
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Aapo Tahkola <aet@rasterburn.org>
+ * Nicolai Haehnle <prefect_@gmx.net>
+ * Jérôme Glisse <glisse@freedesktop.org>
+ */
+#ifndef RADEON_CS_H
+#define RADEON_CS_H
+
+#include <stdint.h>
+#include <string.h>
+#include "drm.h"
+#include "radeon_drm.h"
+
+struct radeon_cs_reloc {
+ struct radeon_bo *bo;
+ uint32_t read_domain;
+ uint32_t write_domain;
+ uint32_t flags;
+};
+
+
+#define RADEON_CS_SPACE_OK 0
+#define RADEON_CS_SPACE_OP_TO_BIG 1
+#define RADEON_CS_SPACE_FLUSH 2
+
+struct radeon_cs_space_check {
+ struct radeon_bo *bo;
+ uint32_t read_domains;
+ uint32_t write_domain;
+ uint32_t new_accounted;
+};
+
+#define MAX_SPACE_BOS (32)
+
+struct radeon_cs_manager;
+
+struct radeon_cs {
+ struct radeon_cs_manager *csm;
+ void *relocs;
+ uint32_t *packets;
+ unsigned crelocs;
+ unsigned relocs_total_size;
+ unsigned cdw;
+ unsigned ndw;
+ int section;
+ unsigned section_ndw;
+ unsigned section_cdw;
+ const char *section_file;
+ const char *section_func;
+ int section_line;
+ struct radeon_cs_space_check bos[MAX_SPACE_BOS];
+ int bo_count;
+ void (*space_flush_fn)(void *);
+ void *space_flush_data;
+};
+
+/* cs functions */
+struct radeon_cs_funcs {
+ struct radeon_cs *(*cs_create)(struct radeon_cs_manager *csm,
+ uint32_t ndw);
+ int (*cs_write_reloc)(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t read_domain,
+ uint32_t write_domain,
+ uint32_t flags);
+ int (*cs_begin)(struct radeon_cs *cs,
+ uint32_t ndw,
+ const char *file,
+ const char *func,
+ int line);
+ int (*cs_end)(struct radeon_cs *cs,
+ const char *file,
+ const char *func,
+ int line);
+ int (*cs_emit)(struct radeon_cs *cs);
+ int (*cs_destroy)(struct radeon_cs *cs);
+ int (*cs_erase)(struct radeon_cs *cs);
+ int (*cs_need_flush)(struct radeon_cs *cs);
+ void (*cs_print)(struct radeon_cs *cs, FILE *file);
+};
+
+struct radeon_cs_manager {
+ struct radeon_cs_funcs *funcs;
+ int fd;
+ int32_t vram_limit, gart_limit;
+ int32_t vram_write_used, gart_write_used;
+ int32_t read_used;
+};
+
+static inline struct radeon_cs *radeon_cs_create(struct radeon_cs_manager *csm,
+ uint32_t ndw)
+{
+ return csm->funcs->cs_create(csm, ndw);
+}
+
+static inline int radeon_cs_write_reloc(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t read_domain,
+ uint32_t write_domain,
+ uint32_t flags)
+{
+ return cs->csm->funcs->cs_write_reloc(cs,
+ bo,
+ read_domain,
+ write_domain,
+ flags);
+}
+
+static inline int radeon_cs_begin(struct radeon_cs *cs,
+ uint32_t ndw,
+ const char *file,
+ const char *func,
+ int line)
+{
+ return cs->csm->funcs->cs_begin(cs, ndw, file, func, line);
+}
+
+static inline int radeon_cs_end(struct radeon_cs *cs,
+ const char *file,
+ const char *func,
+ int line)
+{
+ return cs->csm->funcs->cs_end(cs, file, func, line);
+}
+
+static inline int radeon_cs_emit(struct radeon_cs *cs)
+{
+ return cs->csm->funcs->cs_emit(cs);
+}
+
+static inline int radeon_cs_destroy(struct radeon_cs *cs)
+{
+ return cs->csm->funcs->cs_destroy(cs);
+}
+
+static inline int radeon_cs_erase(struct radeon_cs *cs)
+{
+ return cs->csm->funcs->cs_erase(cs);
+}
+
+static inline int radeon_cs_need_flush(struct radeon_cs *cs)
+{
+ return cs->csm->funcs->cs_need_flush(cs);
+}
+
+static inline void radeon_cs_print(struct radeon_cs *cs, FILE *file)
+{
+ cs->csm->funcs->cs_print(cs, file);
+}
+
+static inline void radeon_cs_set_limit(struct radeon_cs *cs, uint32_t domain, uint32_t limit)
+{
+
+ if (domain == RADEON_GEM_DOMAIN_VRAM)
+ cs->csm->vram_limit = limit;
+ else
+ cs->csm->gart_limit = limit;
+}
+
+static inline void radeon_cs_write_dword(struct radeon_cs *cs, uint32_t dword)
+{
+ cs->packets[cs->cdw++] = dword;
+ if (cs->section) {
+ cs->section_cdw++;
+ }
+}
+
+static inline void radeon_cs_write_qword(struct radeon_cs *cs, uint64_t qword)
+{
+
+ memcpy(cs->packets + cs->cdw, &qword, sizeof(qword));
+ cs->cdw+=2;
+ if (cs->section) {
+ cs->section_cdw+=2;
+ }
+}
+
+static inline void radeon_cs_write_table(struct radeon_cs *cs, void *data, uint32_t size)
+{
+ memcpy(cs->packets + cs->cdw, data, size * 4);
+ cs->cdw += size;
+ if (cs->section) {
+ cs->section_cdw += size;
+ }
+}
+
+static inline void radeon_cs_space_set_flush(struct radeon_cs *cs, void (*fn)(void *), void *data)
+{
+ cs->space_flush_fn = fn;
+ cs->space_flush_data = data;
+}
+
+
+/*
+ * add a persistent BO to the list
+ * a persistent BO is one that will be referenced across flushes,
+ * i.e. colorbuffer, textures etc.
+ * They get reset when a new "operation" happens, where an operation
+ * is a state emission with a color/textures etc followed by a bunch of vertices.
+ */
+void radeon_cs_space_add_persistent_bo(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t read_domains,
+ uint32_t write_domain);
+
+/* reset the persistent BO list */
+void radeon_cs_space_reset_bos(struct radeon_cs *cs);
+
+/* do a space check with the current persistent BO list */
+int radeon_cs_space_check(struct radeon_cs *cs);
+
+/* do a space check with the current persistent BO list and a temporary BO
+ * a temporary BO is like a DMA buffer, which gets flushed with the
+ * command buffer */
+int radeon_cs_space_check_with_bo(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t read_domains,
+ uint32_t write_domain);
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_cs_legacy.c b/src/mesa/drivers/dri/radeon/radeon_cs_legacy.c
new file mode 100644
index 0000000000..f1addb299e
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_cs_legacy.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright © 2008 Nicolai Haehnle
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Aapo Tahkola <aet@rasterburn.org>
+ * Nicolai Haehnle <prefect_@gmx.net>
+ * Jérôme Glisse <glisse@freedesktop.org>
+ */
+#include <errno.h>
+
+#include "radeon_bocs_wrapper.h"
+#include "radeon_common.h"
+
+struct cs_manager_legacy {
+ struct radeon_cs_manager base;
+ struct radeon_context *ctx;
+ /* hack for scratch stuff */
+ uint32_t pending_age;
+ uint32_t pending_count;
+
+
+};
+
+struct cs_reloc_legacy {
+ struct radeon_cs_reloc base;
+ uint32_t cindices;
+ uint32_t *indices;
+};
+
+
+static struct radeon_cs *cs_create(struct radeon_cs_manager *csm,
+ uint32_t ndw)
+{
+ struct radeon_cs *cs;
+
+ cs = (struct radeon_cs*)calloc(1, sizeof(struct radeon_cs));
+ if (cs == NULL) {
+ return NULL;
+ }
+ cs->csm = csm;
+ cs->ndw = (ndw + 0x3FF) & (~0x3FF);
+ cs->packets = (uint32_t*)malloc(4*cs->ndw);
+ if (cs->packets == NULL) {
+ free(cs);
+ return NULL;
+ }
+ cs->relocs_total_size = 0;
+ return cs;
+}
+
+static int cs_write_reloc(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t read_domain,
+ uint32_t write_domain,
+ uint32_t flags)
+{
+ struct cs_reloc_legacy *relocs;
+ int i;
+
+ relocs = (struct cs_reloc_legacy *)cs->relocs;
+ /* check domains */
+ if ((read_domain && write_domain) || (!read_domain && !write_domain)) {
+ /* in one CS a bo can only be in read or write domain but not
+ * in read & write domain at the same sime
+ */
+ return -EINVAL;
+ }
+ if (read_domain == RADEON_GEM_DOMAIN_CPU) {
+ return -EINVAL;
+ }
+ if (write_domain == RADEON_GEM_DOMAIN_CPU) {
+ return -EINVAL;
+ }
+ /* check if bo is already referenced */
+ for(i = 0; i < cs->crelocs; i++) {
+ uint32_t *indices;
+
+ if (relocs[i].base.bo->handle == bo->handle) {
+ /* Check domains must be in read or write. As we check already
+ * checked that in argument one of the read or write domain was
+ * set we only need to check that if previous reloc as the read
+ * domain set then the read_domain should also be set for this
+ * new relocation.
+ */
+ if (relocs[i].base.read_domain && !read_domain) {
+ return -EINVAL;
+ }
+ if (relocs[i].base.write_domain && !write_domain) {
+ return -EINVAL;
+ }
+ relocs[i].base.read_domain |= read_domain;
+ relocs[i].base.write_domain |= write_domain;
+ /* save indice */
+ relocs[i].cindices++;
+ indices = (uint32_t*)realloc(relocs[i].indices,
+ relocs[i].cindices * 4);
+ if (indices == NULL) {
+ relocs[i].cindices -= 1;
+ return -ENOMEM;
+ }
+ relocs[i].indices = indices;
+ relocs[i].indices[relocs[i].cindices - 1] = cs->cdw - 1;
+ return 0;
+ }
+ }
+ /* add bo to reloc */
+ relocs = (struct cs_reloc_legacy*)
+ realloc(cs->relocs,
+ sizeof(struct cs_reloc_legacy) * (cs->crelocs + 1));
+ if (relocs == NULL) {
+ return -ENOMEM;
+ }
+ cs->relocs = relocs;
+ relocs[cs->crelocs].base.bo = bo;
+ relocs[cs->crelocs].base.read_domain = read_domain;
+ relocs[cs->crelocs].base.write_domain = write_domain;
+ relocs[cs->crelocs].base.flags = flags;
+ relocs[cs->crelocs].indices = (uint32_t*)malloc(4);
+ if (relocs[cs->crelocs].indices == NULL) {
+ return -ENOMEM;
+ }
+ relocs[cs->crelocs].indices[0] = cs->cdw - 1;
+ relocs[cs->crelocs].cindices = 1;
+ cs->relocs_total_size += radeon_bo_legacy_relocs_size(bo);
+ cs->crelocs++;
+ radeon_bo_ref(bo);
+ return 0;
+}
+
+static int cs_begin(struct radeon_cs *cs,
+ uint32_t ndw,
+ const char *file,
+ const char *func,
+ int line)
+{
+ if (cs->section) {
+ fprintf(stderr, "CS already in a section(%s,%s,%d)\n",
+ cs->section_file, cs->section_func, cs->section_line);
+ fprintf(stderr, "CS can't start section(%s,%s,%d)\n",
+ file, func, line);
+ return -EPIPE;
+ }
+ cs->section = 1;
+ cs->section_ndw = ndw;
+ cs->section_cdw = 0;
+ cs->section_file = file;
+ cs->section_func = func;
+ cs->section_line = line;
+
+
+ if (cs->cdw + ndw > cs->ndw) {
+ uint32_t tmp, *ptr;
+ int num = (ndw > 0x3FF) ? ndw : 0x3FF;
+
+ tmp = (cs->cdw + 1 + num) & (~num);
+ ptr = (uint32_t*)realloc(cs->packets, 4 * tmp);
+ if (ptr == NULL) {
+ return -ENOMEM;
+ }
+ cs->packets = ptr;
+ cs->ndw = tmp;
+ }
+
+ return 0;
+}
+
+static int cs_end(struct radeon_cs *cs,
+ const char *file,
+ const char *func,
+ int line)
+
+{
+ if (!cs->section) {
+ fprintf(stderr, "CS no section to end at (%s,%s,%d)\n",
+ file, func, line);
+ return -EPIPE;
+ }
+ cs->section = 0;
+ if (cs->section_ndw != cs->section_cdw) {
+ fprintf(stderr, "CS section size missmatch start at (%s,%s,%d) %d vs %d\n",
+ cs->section_file, cs->section_func, cs->section_line, cs->section_ndw, cs->section_cdw);
+ fprintf(stderr, "CS section end at (%s,%s,%d)\n",
+ file, func, line);
+ return -EPIPE;
+ }
+ return 0;
+}
+
+static int cs_process_relocs(struct radeon_cs *cs)
+{
+ struct cs_manager_legacy *csm = (struct cs_manager_legacy*)cs->csm;
+ struct cs_reloc_legacy *relocs;
+ int i, j, r;
+
+ csm = (struct cs_manager_legacy*)cs->csm;
+ relocs = (struct cs_reloc_legacy *)cs->relocs;
+restart:
+ for (i = 0; i < cs->crelocs; i++)
+ {
+ for (j = 0; j < relocs[i].cindices; j++)
+ {
+ uint32_t soffset, eoffset;
+
+ r = radeon_bo_legacy_validate(relocs[i].base.bo,
+ &soffset, &eoffset);
+ if (r == -EAGAIN)
+ {
+ goto restart;
+ }
+ if (r)
+ {
+ fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n",
+ relocs[i].base.bo, soffset, eoffset);
+ return r;
+ }
+ cs->packets[relocs[i].indices[j]] += soffset;
+ if (cs->packets[relocs[i].indices[j]] >= eoffset)
+ {
+ /* radeon_bo_debug(relocs[i].base.bo, 12); */
+ fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n",
+ relocs[i].base.bo, soffset, eoffset);
+ fprintf(stderr, "above end: %p 0x%08X 0x%08X\n",
+ relocs[i].base.bo,
+ cs->packets[relocs[i].indices[j]],
+ eoffset);
+ exit(0);
+ return -EINVAL;
+ }
+ }
+ }
+ return 0;
+}
+
+static int cs_set_age(struct radeon_cs *cs)
+{
+ struct cs_manager_legacy *csm = (struct cs_manager_legacy*)cs->csm;
+ struct cs_reloc_legacy *relocs;
+ int i;
+
+ relocs = (struct cs_reloc_legacy *)cs->relocs;
+ for (i = 0; i < cs->crelocs; i++) {
+ radeon_bo_legacy_pending(relocs[i].base.bo, csm->pending_age);
+ radeon_bo_unref(relocs[i].base.bo);
+ }
+ return 0;
+}
+
+static int cs_emit(struct radeon_cs *cs)
+{
+ struct cs_manager_legacy *csm = (struct cs_manager_legacy*)cs->csm;
+ drm_radeon_cmd_buffer_t cmd;
+ drm_r300_cmd_header_t age;
+ uint64_t ull;
+ int r;
+
+ csm->ctx->vtbl.emit_cs_header(cs, csm->ctx);
+
+ /* append buffer age */
+ if ( IS_R300_CLASS(csm->ctx->radeonScreen) )
+ {
+ age.scratch.cmd_type = R300_CMD_SCRATCH;
+ /* Scratch register 2 corresponds to what radeonGetAge polls */
+ csm->pending_age = 0;
+ csm->pending_count = 1;
+ ull = (uint64_t) (intptr_t) &csm->pending_age;
+ age.scratch.reg = 2;
+ age.scratch.n_bufs = 1;
+ age.scratch.flags = 0;
+ radeon_cs_write_dword(cs, age.u);
+ radeon_cs_write_qword(cs, ull);
+ radeon_cs_write_dword(cs, 0);
+ }
+
+ r = cs_process_relocs(cs);
+ if (r) {
+ return 0;
+ }
+
+ cmd.buf = (char *)cs->packets;
+ cmd.bufsz = cs->cdw * 4;
+ if (csm->ctx->state.scissor.enabled) {
+ cmd.nbox = csm->ctx->state.scissor.numClipRects;
+ cmd.boxes = (drm_clip_rect_t *) csm->ctx->state.scissor.pClipRects;
+ } else {
+ cmd.nbox = csm->ctx->numClipRects;
+ cmd.boxes = (drm_clip_rect_t *) csm->ctx->pClipRects;
+ }
+
+ //dump_cmdbuf(cs);
+
+ r = drmCommandWrite(cs->csm->fd, DRM_RADEON_CMDBUF, &cmd, sizeof(cmd));
+ if (r) {
+ return r;
+ }
+ if ((!IS_R300_CLASS(csm->ctx->radeonScreen)) &&
+ (!IS_R600_CLASS(csm->ctx->radeonScreen))) { /* +r6/r7 : No irq for r6/r7 yet. */
+ drm_radeon_irq_emit_t emit_cmd;
+ emit_cmd.irq_seq = (int*)&csm->pending_age;
+ r = drmCommandWrite(cs->csm->fd, DRM_RADEON_IRQ_EMIT, &emit_cmd, sizeof(emit_cmd));
+ if (r) {
+ return r;
+ }
+ }
+ cs_set_age(cs);
+
+ cs->csm->read_used = 0;
+ cs->csm->vram_write_used = 0;
+ cs->csm->gart_write_used = 0;
+ return 0;
+}
+
+static void inline cs_free_reloc(void *relocs_p, int crelocs)
+{
+ struct cs_reloc_legacy *relocs = relocs_p;
+ int i;
+ if (!relocs_p)
+ return;
+ for (i = 0; i < crelocs; i++)
+ free(relocs[i].indices);
+}
+
+static int cs_destroy(struct radeon_cs *cs)
+{
+ cs_free_reloc(cs->relocs, cs->crelocs);
+ free(cs->relocs);
+ free(cs->packets);
+ free(cs);
+ return 0;
+}
+
+static int cs_erase(struct radeon_cs *cs)
+{
+ cs_free_reloc(cs->relocs, cs->crelocs);
+ free(cs->relocs);
+ cs->relocs_total_size = 0;
+ cs->relocs = NULL;
+ cs->crelocs = 0;
+ cs->cdw = 0;
+ cs->section = 0;
+ return 0;
+}
+
+static int cs_need_flush(struct radeon_cs *cs)
+{
+ /* this function used to flush when the BO usage got to
+ * a certain size, now the higher levels handle this better */
+ return 0;
+}
+
+static void cs_print(struct radeon_cs *cs, FILE *file)
+{
+}
+
+static struct radeon_cs_funcs radeon_cs_legacy_funcs = {
+ cs_create,
+ cs_write_reloc,
+ cs_begin,
+ cs_end,
+ cs_emit,
+ cs_destroy,
+ cs_erase,
+ cs_need_flush,
+ cs_print,
+};
+
+struct radeon_cs_manager *radeon_cs_manager_legacy_ctor(struct radeon_context *ctx)
+{
+ struct cs_manager_legacy *csm;
+
+ csm = (struct cs_manager_legacy*)
+ calloc(1, sizeof(struct cs_manager_legacy));
+ if (csm == NULL) {
+ return NULL;
+ }
+ csm->base.funcs = &radeon_cs_legacy_funcs;
+ csm->base.fd = ctx->dri.fd;
+ csm->ctx = ctx;
+ csm->pending_age = 1;
+ return (struct radeon_cs_manager*)csm;
+}
+
+void radeon_cs_manager_legacy_dtor(struct radeon_cs_manager *csm)
+{
+ free(csm);
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_cs_legacy.h b/src/mesa/drivers/dri/radeon/radeon_cs_legacy.h
new file mode 100644
index 0000000000..cafbc9e576
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_cs_legacy.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2008 Nicolai Haehnle
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Aapo Tahkola <aet@rasterburn.org>
+ * Nicolai Haehnle <prefect_@gmx.net>
+ * Jérôme Glisse <glisse@freedesktop.org>
+ */
+#ifndef RADEON_CS_LEGACY_H
+#define RADEON_CS_LEGACY_H
+
+struct radeon_context;
+
+struct radeon_cs_manager *radeon_cs_manager_legacy_ctor(struct radeon_context *ctx);
+void radeon_cs_manager_legacy_dtor(struct radeon_cs_manager *csm);
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_cs_space_drm.c b/src/mesa/drivers/dri/radeon/radeon_cs_space_drm.c
new file mode 100644
index 0000000000..89cbbb5a6b
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_cs_space_drm.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright © 2009 Red Hat Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ */
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "radeon_bocs_wrapper.h"
+
+struct rad_sizes {
+ int32_t op_read;
+ int32_t op_gart_write;
+ int32_t op_vram_write;
+};
+
+static inline int radeon_cs_setup_bo(struct radeon_cs_space_check *sc, struct rad_sizes *sizes)
+{
+ uint32_t read_domains, write_domain;
+ struct radeon_bo *bo;
+
+ bo = sc->bo;
+ sc->new_accounted = 0;
+ read_domains = sc->read_domains;
+ write_domain = sc->write_domain;
+
+ /* legacy needs a static check */
+ if (radeon_bo_is_static(bo)) {
+ bo->space_accounted = sc->new_accounted = (read_domains << 16) | write_domain;
+ return 0;
+ }
+
+ /* already accounted this bo */
+ if (write_domain && (write_domain == bo->space_accounted)) {
+ sc->new_accounted = bo->space_accounted;
+ return 0;
+ }
+ if (read_domains && ((read_domains << 16) == bo->space_accounted)) {
+ sc->new_accounted = bo->space_accounted;
+ return 0;
+ }
+
+ if (bo->space_accounted == 0) {
+ if (write_domain == RADEON_GEM_DOMAIN_VRAM)
+ sizes->op_vram_write += bo->size;
+ else if (write_domain == RADEON_GEM_DOMAIN_GTT)
+ sizes->op_gart_write += bo->size;
+ else
+ sizes->op_read += bo->size;
+ sc->new_accounted = (read_domains << 16) | write_domain;
+ } else {
+ uint16_t old_read, old_write;
+
+ old_read = bo->space_accounted >> 16;
+ old_write = bo->space_accounted & 0xffff;
+
+ if (write_domain && (old_read & write_domain)) {
+ sc->new_accounted = write_domain;
+ /* moving from read to a write domain */
+ if (write_domain == RADEON_GEM_DOMAIN_VRAM) {
+ sizes->op_read -= bo->size;
+ sizes->op_vram_write += bo->size;
+ } else if (write_domain == RADEON_GEM_DOMAIN_GTT) {
+ sizes->op_read -= bo->size;
+ sizes->op_gart_write += bo->size;
+ }
+ } else if (read_domains & old_write) {
+ sc->new_accounted = bo->space_accounted & 0xffff;
+ } else {
+ /* rewrite the domains */
+ if (write_domain != old_write)
+ fprintf(stderr,"WRITE DOMAIN RELOC FAILURE 0x%x %d %d\n", bo->handle, write_domain, old_write);
+ if (read_domains != old_read)
+ fprintf(stderr,"READ DOMAIN RELOC FAILURE 0x%x %d %d\n", bo->handle, read_domains, old_read);
+ return RADEON_CS_SPACE_FLUSH;
+ }
+ }
+ return 0;
+}
+
+static int radeon_cs_do_space_check(struct radeon_cs *cs, struct radeon_cs_space_check *new_tmp)
+{
+ struct radeon_cs_manager *csm = cs->csm;
+ int i;
+ struct radeon_bo *bo;
+ struct rad_sizes sizes;
+ int ret;
+
+ /* check the totals for this operation */
+
+ if (cs->bo_count == 0 && !new_tmp)
+ return 0;
+
+ memset(&sizes, 0, sizeof(struct rad_sizes));
+
+ /* prepare */
+ for (i = 0; i < cs->bo_count; i++) {
+ ret = radeon_cs_setup_bo(&cs->bos[i], &sizes);
+ if (ret)
+ return ret;
+ }
+
+ if (new_tmp) {
+ ret = radeon_cs_setup_bo(new_tmp, &sizes);
+ if (ret)
+ return ret;
+ }
+
+ if (sizes.op_read < 0)
+ sizes.op_read = 0;
+
+ /* check sizes - operation first */
+ if ((sizes.op_read + sizes.op_gart_write > csm->gart_limit) ||
+ (sizes.op_vram_write > csm->vram_limit)) {
+ return RADEON_CS_SPACE_OP_TO_BIG;
+ }
+
+ if (((csm->vram_write_used + sizes.op_vram_write) > csm->vram_limit) ||
+ ((csm->read_used + csm->gart_write_used + sizes.op_gart_write + sizes.op_read) > csm->gart_limit)) {
+ return RADEON_CS_SPACE_FLUSH;
+ }
+
+ csm->gart_write_used += sizes.op_gart_write;
+ csm->vram_write_used += sizes.op_vram_write;
+ csm->read_used += sizes.op_read;
+ /* commit */
+ for (i = 0; i < cs->bo_count; i++) {
+ bo = cs->bos[i].bo;
+ bo->space_accounted = cs->bos[i].new_accounted;
+ }
+ if (new_tmp)
+ new_tmp->bo->space_accounted = new_tmp->new_accounted;
+
+ return RADEON_CS_SPACE_OK;
+}
+
+void radeon_cs_space_add_persistent_bo(struct radeon_cs *cs, struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain)
+{
+ int i;
+ for (i = 0; i < cs->bo_count; i++) {
+ if (cs->bos[i].bo == bo &&
+ cs->bos[i].read_domains == read_domains &&
+ cs->bos[i].write_domain == write_domain)
+ return;
+ }
+ radeon_bo_ref(bo);
+ i = cs->bo_count;
+ cs->bos[i].bo = bo;
+ cs->bos[i].read_domains = read_domains;
+ cs->bos[i].write_domain = write_domain;
+ cs->bos[i].new_accounted = 0;
+ cs->bo_count++;
+
+ assert(cs->bo_count < MAX_SPACE_BOS);
+}
+
+static int radeon_cs_check_space_internal(struct radeon_cs *cs, struct radeon_cs_space_check *tmp_bo)
+{
+ int ret;
+ int flushed = 0;
+
+again:
+ ret = radeon_cs_do_space_check(cs, tmp_bo);
+ if (ret == RADEON_CS_SPACE_OP_TO_BIG)
+ return -1;
+ if (ret == RADEON_CS_SPACE_FLUSH) {
+ (*cs->space_flush_fn)(cs->space_flush_data);
+ if (flushed)
+ return -1;
+ flushed = 1;
+ goto again;
+ }
+ return 0;
+}
+
+int radeon_cs_space_check_with_bo(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t read_domains, uint32_t write_domain)
+{
+ struct radeon_cs_space_check temp_bo;
+ int ret = 0;
+
+ if (bo) {
+ temp_bo.bo = bo;
+ temp_bo.read_domains = read_domains;
+ temp_bo.write_domain = write_domain;
+ temp_bo.new_accounted = 0;
+ }
+
+ ret = radeon_cs_check_space_internal(cs, bo ? &temp_bo : NULL);
+ return ret;
+}
+
+int radeon_cs_space_check(struct radeon_cs *cs)
+{
+ return radeon_cs_check_space_internal(cs, NULL);
+}
+
+void radeon_cs_space_reset_bos(struct radeon_cs *cs)
+{
+ int i;
+ for (i = 0; i < cs->bo_count; i++) {
+ radeon_bo_unref(cs->bos[i].bo);
+ cs->bos[i].bo = NULL;
+ cs->bos[i].read_domains = 0;
+ cs->bos[i].write_domain = 0;
+ cs->bos[i].new_accounted = 0;
+ }
+ cs->bo_count = 0;
+}
+
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_debug.c b/src/mesa/drivers/dri/radeon/radeon_debug.c
new file mode 100644
index 0000000000..3b6f003803
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_debug.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2009 Pauli Nieminen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Pauli Nieminen <suokkos@gmail.com>
+ */
+
+#include "utils.h"
+
+#include "radeon_debug.h"
+#include "radeon_common_context.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+static const struct dri_debug_control debug_control[] = {
+ {"fall", RADEON_FALLBACKS},
+ {"tex", RADEON_TEXTURE},
+ {"ioctl", RADEON_IOCTL},
+ {"verts", RADEON_RENDER},
+ {"render", RADEON_RENDER},
+ {"swrender", RADEON_SWRENDER},
+ {"state", RADEON_STATE},
+ {"shader", RADEON_SHADER},
+ {"vfmt", RADEON_VFMT},
+ {"vtxf", RADEON_VFMT},
+ {"dri", RADEON_DRI},
+ {"dma", RADEON_DMA},
+ {"sanity", RADEON_SANITY},
+ {"sync", RADEON_SYNC},
+ {"pixel", RADEON_PIXEL},
+ {"mem", RADEON_MEMORY},
+ {"cs", RADEON_CS},
+ {"allmsg", ~RADEON_SYNC}, /* avoid the term "sync" because the parser uses strstr */
+ {NULL, 0}
+};
+
+radeon_debug_type_t radeon_enabled_debug_types;
+
+void radeon_init_debug(void)
+{
+ radeon_enabled_debug_types = driParseDebugString(getenv("RADEON_DEBUG"), debug_control);
+
+ radeon_enabled_debug_types |= RADEON_GENERAL;
+}
+
+void _radeon_debug_add_indent(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ const size_t length = sizeof(radeon->debug.indent)
+ / sizeof(radeon->debug.indent[0]);
+ if (radeon->debug.indent_depth < length - 1) {
+ radeon->debug.indent[radeon->debug.indent_depth] = '\t';
+ ++radeon->debug.indent_depth;
+ };
+}
+
+void _radeon_debug_remove_indent(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ if (radeon->debug.indent_depth > 0) {
+ radeon->debug.indent[radeon->debug.indent_depth] = '\0';
+ --radeon->debug.indent_depth;
+ }
+}
+
+void _radeon_print(const radeon_debug_type_t type,
+ const radeon_debug_level_t level,
+ const char* message,
+ ...)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx) {
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ // FIXME: Make this multi thread safe
+ if (radeon->debug.indent_depth)
+ fprintf(stderr, "%s", radeon->debug.indent);
+ }
+ va_list values;
+ va_start( values, message );
+ vfprintf(stderr, message, values);
+ va_end( values );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_debug.h b/src/mesa/drivers/dri/radeon/radeon_debug.h
new file mode 100644
index 0000000000..2a8302293b
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_debug.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2009 Pauli Nieminen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ * Pauli Nieminen <suokkos@gmail.com>
+ */
+
+#ifndef RADEON_DEBUG_H_INCLUDED
+#define RADEON_DEBUG_H_INCLUDED
+
+#include <stdlib.h>
+
+typedef enum radeon_debug_levels {
+ RADEON_CRITICAL = 0, /* Only errors */
+ RADEON_IMPORTANT = 1, /* Important warnings and messages */
+ RADEON_NORMAL = 2, /* Normal log messages usefull for debugging */
+ RADEON_VERBOSE = 3, /* Extra details to debugging */
+ RADEON_TRACE = 4 /* Log about everything that happens */
+} radeon_debug_level_t;
+
+/**
+ * Compile time option to change level of debugging compiled to dri driver.
+ * Selecting critical level is not recommended because perfromance gains are
+ * going to minimal but you will lose a lot of important warnings in case of
+ * errors.
+ */
+#ifndef RADEON_DEBUG_LEVEL
+#define RADEON_DEBUG_LEVEL RADEON_VERBOSE
+#endif
+
+typedef enum radeon_debug_types {
+ RADEON_TEXTURE = 0x00001,
+ RADEON_STATE = 0x00002,
+ RADEON_IOCTL = 0x00004,
+ RADEON_RENDER = 0x00008,
+ RADEON_SWRENDER = 0x00010,
+ RADEON_FALLBACKS = 0x00020,
+ RADEON_VFMT = 0x00040,
+ RADEON_SHADER = 0x00080,
+ RADEON_CS = 0x00100,
+ RADEON_DRI = 0x00200,
+ RADEON_DMA = 0x00400,
+ RADEON_SANITY = 0x00800,
+ RADEON_SYNC = 0x01000,
+ RADEON_PIXEL = 0x02000,
+ RADEON_MEMORY = 0x04000,
+ RADEON_VERTS = 0x08000,
+ RADEON_GENERAL = 0x10000 /* Used for errors and warnings */
+} radeon_debug_type_t;
+
+#define RADEON_MAX_INDENT 5
+
+struct radeon_debug {
+ size_t indent_depth;
+ char indent[RADEON_MAX_INDENT];
+};
+
+extern radeon_debug_type_t radeon_enabled_debug_types;
+
+/**
+ * Compabibility layer for old debug code
+ **/
+#define RADEON_DEBUG radeon_enabled_debug_types
+
+static inline int radeon_is_debug_enabled(const radeon_debug_type_t type,
+ const radeon_debug_level_t level)
+{
+ return RADEON_DEBUG_LEVEL >= level
+ && (type & radeon_enabled_debug_types);
+}
+/*
+ * define macro for gcc specific __attribute__ if using alternative compiler
+ */
+#ifndef __GNUC__
+#define __attribute__(x) /*empty*/
+#endif
+
+
+extern void _radeon_print(const radeon_debug_type_t type,
+ const radeon_debug_level_t level,
+ const char* message,
+ ...) __attribute__((format(printf,3,4)));
+/**
+ * Print out debug message if channel specified by type is enabled
+ * and compile time debugging level is at least as high as level parameter
+ */
+#define radeon_print(type, level, message, ...) do { \
+ const radeon_debug_level_t _debug_level = (level); \
+ const radeon_debug_type_t _debug_type = (type); \
+ /* Compile out if level of message is too high */ \
+ if (radeon_is_debug_enabled(type, level)) { \
+ _radeon_print(_debug_type, _debug_level, \
+ (message), ## __VA_ARGS__); \
+ } \
+} while(0)
+
+/**
+ * printf style function for writing error messages.
+ */
+#define radeon_error(message, ...) do { \
+ radeon_print(RADEON_GENERAL, RADEON_CRITICAL, \
+ (message), ## __VA_ARGS__); \
+} while(0)
+
+/**
+ * printf style function for writing warnings.
+ */
+#define radeon_warning(message, ...) do { \
+ radeon_print(RADEON_GENERAL, RADEON_IMPORTANT, \
+ (message), ## __VA_ARGS__); \
+} while(0)
+
+extern void radeon_init_debug(void);
+extern void _radeon_debug_add_indent(void);
+extern void _radeon_debug_remove_indent(void);
+
+static inline void radeon_debug_add_indent(void)
+{
+ if (RADEON_DEBUG_LEVEL >= RADEON_VERBOSE) {
+ _radeon_debug_add_indent();
+ }
+}
+static inline void radeon_debug_remove_indent(void)
+{
+ if (RADEON_DEBUG_LEVEL >= RADEON_VERBOSE) {
+ _radeon_debug_remove_indent();
+ }
+}
+
+/* From http://gcc. gnu.org/onlinedocs/gcc-3.2.3/gcc/Variadic-Macros.html .
+ I suppose we could inline this and use macro to fetch out __LINE__ and stuff in case we run into trouble
+ with other compilers ... GLUE!
+*/
+#define WARN_ONCE(a, ...) { \
+ static int warn##__LINE__=1; \
+ if(warn##__LINE__){ \
+ radeon_warning("*********************************WARN_ONCE*********************************\n"); \
+ radeon_warning("File %s function %s line %d\n", \
+ __FILE__, __FUNCTION__, __LINE__); \
+ radeon_warning( (a), ## __VA_ARGS__);\
+ radeon_warning("***************************************************************************\n"); \
+ warn##__LINE__=0;\
+ } \
+ }
+
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_dma.c b/src/mesa/drivers/dri/radeon/radeon_dma.c
new file mode 100644
index 0000000000..2eefa3f2b1
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_dma.c
@@ -0,0 +1,476 @@
+/**************************************************************************
+
+Copyright (C) 2004 Nicolai Haehnle.
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS 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 <errno.h>
+#include "radeon_common.h"
+#include "main/simple_list.h"
+
+#if defined(USE_X86_ASM)
+#define COPY_DWORDS( dst, src, nr ) \
+do { \
+ int __tmp; \
+ __asm__ __volatile__( "rep ; movsl" \
+ : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
+ : "0" (nr), \
+ "D" ((long)dst), \
+ "S" ((long)src) ); \
+} while (0)
+#else
+#define COPY_DWORDS( dst, src, nr ) \
+do { \
+ int j; \
+ for ( j = 0 ; j < nr ; j++ ) \
+ dst[j] = ((int *)src)[j]; \
+ dst += nr; \
+} while (0)
+#endif
+
+void radeonEmitVec4(uint32_t *out, const GLvoid * data, int stride, int count)
+{
+ int i;
+
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s count %d stride %d out %p data %p\n",
+ __FUNCTION__, count, stride, (void *)out, (void *)data);
+
+ if (stride == 4)
+ COPY_DWORDS(out, data, count);
+ else
+ for (i = 0; i < count; i++) {
+ out[0] = *(int *)data;
+ out++;
+ data += stride;
+ }
+}
+
+void radeonEmitVec8(uint32_t *out, const GLvoid * data, int stride, int count)
+{
+ int i;
+
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s count %d stride %d out %p data %p\n",
+ __FUNCTION__, count, stride, (void *)out, (void *)data);
+
+ if (stride == 8)
+ COPY_DWORDS(out, data, count * 2);
+ else
+ for (i = 0; i < count; i++) {
+ out[0] = *(int *)data;
+ out[1] = *(int *)(data + 4);
+ out += 2;
+ data += stride;
+ }
+}
+
+void radeonEmitVec12(uint32_t *out, const GLvoid * data, int stride, int count)
+{
+ int i;
+
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s count %d stride %d out %p data %p\n",
+ __FUNCTION__, count, stride, (void *)out, (void *)data);
+
+ if (stride == 12) {
+ COPY_DWORDS(out, data, count * 3);
+ }
+ else
+ for (i = 0; i < count; i++) {
+ out[0] = *(int *)data;
+ out[1] = *(int *)(data + 4);
+ out[2] = *(int *)(data + 8);
+ out += 3;
+ data += stride;
+ }
+}
+
+void radeonEmitVec16(uint32_t *out, const GLvoid * data, int stride, int count)
+{
+ int i;
+
+ if (RADEON_DEBUG & RADEON_VERTS)
+ fprintf(stderr, "%s count %d stride %d out %p data %p\n",
+ __FUNCTION__, count, stride, (void *)out, (void *)data);
+
+ if (stride == 16)
+ COPY_DWORDS(out, data, count * 4);
+ else
+ for (i = 0; i < count; i++) {
+ out[0] = *(int *)data;
+ out[1] = *(int *)(data + 4);
+ out[2] = *(int *)(data + 8);
+ out[3] = *(int *)(data + 12);
+ out += 4;
+ data += stride;
+ }
+}
+
+void rcommon_emit_vector(GLcontext * ctx, struct radeon_aos *aos,
+ const GLvoid * data, int size, int stride, int count)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ uint32_t *out;
+
+ if (stride == 0) {
+ radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * 4, 32);
+ count = 1;
+ aos->stride = 0;
+ } else {
+ radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * count * 4, 32);
+ aos->stride = size;
+ }
+
+ aos->components = size;
+ aos->count = count;
+
+ out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
+ switch (size) {
+ case 1: radeonEmitVec4(out, data, stride, count); break;
+ case 2: radeonEmitVec8(out, data, stride, count); break;
+ case 3: radeonEmitVec12(out, data, stride, count); break;
+ case 4: radeonEmitVec16(out, data, stride, count); break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+void radeon_init_dma(radeonContextPtr rmesa)
+{
+ make_empty_list(&rmesa->dma.free);
+ make_empty_list(&rmesa->dma.wait);
+ make_empty_list(&rmesa->dma.reserved);
+ rmesa->dma.minimum_size = MAX_DMA_BUF_SZ;
+}
+
+void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size)
+{
+ struct radeon_dma_bo *dma_bo = NULL;
+ /* we set minimum sizes to at least requested size
+ aligned to next 16 bytes. */
+ if (size > rmesa->dma.minimum_size)
+ rmesa->dma.minimum_size = (size + 15) & (~15);
+
+ radeon_print(RADEON_DMA, RADEON_NORMAL, "%s size %d minimum_size %d\n",
+ __FUNCTION__, size, rmesa->dma.minimum_size);
+
+
+ /* unmap old reserved bo */
+ if (!is_empty_list(&rmesa->dma.reserved))
+ radeon_bo_unmap(first_elem(&rmesa->dma.reserved)->bo);
+
+ if (is_empty_list(&rmesa->dma.free)
+ || last_elem(&rmesa->dma.free)->bo->size < size) {
+ dma_bo = CALLOC_STRUCT(radeon_dma_bo);
+ assert(dma_bo);
+
+again_alloc:
+ dma_bo->bo = radeon_bo_open(rmesa->radeonScreen->bom,
+ 0, rmesa->dma.minimum_size, 4,
+ RADEON_GEM_DOMAIN_GTT, 0);
+
+ if (!dma_bo->bo) {
+ rcommonFlushCmdBuf(rmesa, __FUNCTION__);
+ goto again_alloc;
+ }
+ insert_at_head(&rmesa->dma.reserved, dma_bo);
+ } else {
+ /* We push and pop buffers from end of list so we can keep
+ counter on unused buffers for later freeing them from
+ begin of list */
+ dma_bo = last_elem(&rmesa->dma.free);
+ assert(dma_bo->bo->cref == 1);
+ remove_from_list(dma_bo);
+ insert_at_head(&rmesa->dma.reserved, dma_bo);
+ }
+
+ rmesa->dma.current_used = 0;
+ rmesa->dma.current_vertexptr = 0;
+
+ if (radeon_cs_space_check_with_bo(rmesa->cmdbuf.cs,
+ first_elem(&rmesa->dma.reserved)->bo,
+ RADEON_GEM_DOMAIN_GTT, 0))
+ fprintf(stderr,"failure to revalidate BOs - badness\n");
+
+ if (is_empty_list(&rmesa->dma.reserved)) {
+ /* Cmd buff have been flushed in radeon_revalidate_bos */
+ goto again_alloc;
+ }
+
+ radeon_bo_map(first_elem(&rmesa->dma.reserved)->bo, 1);
+}
+
+/* Allocates a region from rmesa->dma.current. If there isn't enough
+ * space in current, grab a new buffer (and discard what was left of current)
+ */
+void radeonAllocDmaRegion(radeonContextPtr rmesa,
+ struct radeon_bo **pbo, int *poffset,
+ int bytes, int alignment)
+{
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
+
+ if (rmesa->dma.flush)
+ rmesa->dma.flush(rmesa->glCtx);
+
+ assert(rmesa->dma.current_used == rmesa->dma.current_vertexptr);
+
+ alignment--;
+ rmesa->dma.current_used = (rmesa->dma.current_used + alignment) & ~alignment;
+
+ if (is_empty_list(&rmesa->dma.reserved)
+ || rmesa->dma.current_used + bytes > first_elem(&rmesa->dma.reserved)->bo->size)
+ radeonRefillCurrentDmaRegion(rmesa, bytes);
+
+ *poffset = rmesa->dma.current_used;
+ *pbo = first_elem(&rmesa->dma.reserved)->bo;
+ radeon_bo_ref(*pbo);
+
+ /* Always align to at least 16 bytes */
+ rmesa->dma.current_used = (rmesa->dma.current_used + bytes + 15) & ~15;
+ rmesa->dma.current_vertexptr = rmesa->dma.current_used;
+
+ assert(rmesa->dma.current_used <= first_elem(&rmesa->dma.reserved)->bo->size);
+}
+
+void radeonFreeDmaRegions(radeonContextPtr rmesa)
+{
+ struct radeon_dma_bo *dma_bo = CALLOC_STRUCT(radeon_dma_bo);
+ struct radeon_dma_bo *temp;
+ if (RADEON_DEBUG & RADEON_DMA)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ foreach_s(dma_bo, temp, &rmesa->dma.free) {
+ remove_from_list(dma_bo);
+ radeon_bo_unref(dma_bo->bo);
+ FREE(dma_bo);
+ }
+
+ foreach_s(dma_bo, temp, &rmesa->dma.wait) {
+ remove_from_list(dma_bo);
+ radeon_bo_unref(dma_bo->bo);
+ FREE(dma_bo);
+ }
+
+ foreach_s(dma_bo, temp, &rmesa->dma.reserved) {
+ remove_from_list(dma_bo);
+ radeon_bo_unmap(dma_bo->bo);
+ radeon_bo_unref(dma_bo->bo);
+ FREE(dma_bo);
+ }
+}
+
+void radeonReturnDmaRegion(radeonContextPtr rmesa, int return_bytes)
+{
+ if (is_empty_list(&rmesa->dma.reserved))
+ return;
+
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, return_bytes);
+ rmesa->dma.current_used -= return_bytes;
+ rmesa->dma.current_vertexptr = rmesa->dma.current_used;
+}
+
+static int radeon_bo_is_idle(struct radeon_bo* bo)
+{
+ uint32_t domain;
+ int ret = radeon_bo_is_busy(bo, &domain);
+ if (ret == -EINVAL) {
+ WARN_ONCE("Your libdrm or kernel doesn't have support for busy query.\n"
+ "This may cause small performance drop for you.\n");
+ }
+ return ret != -EBUSY;
+}
+
+void radeonReleaseDmaRegions(radeonContextPtr rmesa)
+{
+ struct radeon_dma_bo *dma_bo;
+ struct radeon_dma_bo *temp;
+ const int expire_at = ++rmesa->dma.free.expire_counter + DMA_BO_FREE_TIME;
+ const int time = rmesa->dma.free.expire_counter;
+
+ if (RADEON_DEBUG & RADEON_DMA) {
+ size_t free = 0,
+ wait = 0,
+ reserved = 0;
+ foreach(dma_bo, &rmesa->dma.free)
+ ++free;
+
+ foreach(dma_bo, &rmesa->dma.wait)
+ ++wait;
+
+ foreach(dma_bo, &rmesa->dma.reserved)
+ ++reserved;
+
+ fprintf(stderr, "%s: free %zu, wait %zu, reserved %zu, minimum_size: %zu\n",
+ __FUNCTION__, free, wait, reserved, rmesa->dma.minimum_size);
+ }
+
+ if (!rmesa->radeonScreen->driScreen->dri2.enabled) {
+ /* request updated cs processing information from kernel */
+ legacy_track_pending(rmesa->radeonScreen->bom, 0);
+ }
+ /* move waiting bos to free list.
+ wait list provides gpu time to handle data before reuse */
+ foreach_s(dma_bo, temp, &rmesa->dma.wait) {
+ if (dma_bo->expire_counter == time) {
+ WARN_ONCE("Leaking dma buffer object!\n");
+ radeon_bo_unref(dma_bo->bo);
+ remove_from_list(dma_bo);
+ FREE(dma_bo);
+ continue;
+ }
+ /* free objects that are too small to be used because of large request */
+ if (dma_bo->bo->size < rmesa->dma.minimum_size) {
+ radeon_bo_unref(dma_bo->bo);
+ remove_from_list(dma_bo);
+ FREE(dma_bo);
+ continue;
+ }
+ if (!radeon_bo_is_idle(dma_bo->bo))
+ continue;
+ remove_from_list(dma_bo);
+ dma_bo->expire_counter = expire_at;
+ insert_at_tail(&rmesa->dma.free, dma_bo);
+ }
+
+ /* unmap the last dma region */
+ if (!is_empty_list(&rmesa->dma.reserved))
+ radeon_bo_unmap(first_elem(&rmesa->dma.reserved)->bo);
+ /* move reserved to wait list */
+ foreach_s(dma_bo, temp, &rmesa->dma.reserved) {
+ /* free objects that are too small to be used because of large request */
+ if (dma_bo->bo->size < rmesa->dma.minimum_size) {
+ radeon_bo_unref(dma_bo->bo);
+ remove_from_list(dma_bo);
+ FREE(dma_bo);
+ continue;
+ }
+ remove_from_list(dma_bo);
+ dma_bo->expire_counter = expire_at;
+ insert_at_tail(&rmesa->dma.wait, dma_bo);
+ }
+
+ /* free bos that have been unused for some time */
+ foreach_s(dma_bo, temp, &rmesa->dma.free) {
+ if (dma_bo->expire_counter != time)
+ break;
+ remove_from_list(dma_bo);
+ radeon_bo_unref(dma_bo->bo);
+ FREE(dma_bo);
+ }
+
+}
+
+
+/* Flush vertices in the current dma region.
+ */
+void rcommon_flush_last_swtcl_prim( GLcontext *ctx )
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ struct radeon_dma *dma = &rmesa->dma;
+
+
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+ dma->flush = NULL;
+
+ if (!is_empty_list(&dma->reserved)) {
+ GLuint current_offset = dma->current_used;
+
+ assert (dma->current_used +
+ rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+ dma->current_vertexptr);
+
+ if (dma->current_used != dma->current_vertexptr) {
+ dma->current_used = dma->current_vertexptr;
+
+ rmesa->vtbl.swtcl_flush(ctx, current_offset);
+ }
+ rmesa->swtcl.numverts = 0;
+ }
+}
+/* Alloc space in the current dma region.
+ */
+void *
+rcommonAllocDmaLowVerts( radeonContextPtr rmesa, int nverts, int vsize )
+{
+ GLuint bytes = vsize * nverts;
+ void *head;
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+ if(is_empty_list(&rmesa->dma.reserved)
+ ||rmesa->dma.current_vertexptr + bytes > first_elem(&rmesa->dma.reserved)->bo->size) {
+ if (rmesa->dma.flush) {
+ rmesa->dma.flush(rmesa->glCtx);
+ }
+
+ radeonRefillCurrentDmaRegion(rmesa, bytes);
+
+ return NULL;
+ }
+
+ if (!rmesa->dma.flush) {
+ /* if cmdbuf flushed DMA restart */
+ rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ rmesa->dma.flush = rcommon_flush_last_swtcl_prim;
+ }
+
+ ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
+ ASSERT( rmesa->dma.flush == rcommon_flush_last_swtcl_prim );
+ ASSERT( rmesa->dma.current_used +
+ rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+ rmesa->dma.current_vertexptr );
+
+ head = (first_elem(&rmesa->dma.reserved)->bo->ptr + rmesa->dma.current_vertexptr);
+ rmesa->dma.current_vertexptr += bytes;
+ rmesa->swtcl.numverts += nverts;
+ return head;
+}
+
+void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
+{
+ radeonContextPtr radeon = RADEON_CONTEXT( ctx );
+ int i;
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (radeon->dma.flush) {
+ radeon->dma.flush(radeon->glCtx);
+ }
+ for (i = 0; i < radeon->tcl.aos_count; i++) {
+ if (radeon->tcl.aos[i].bo) {
+ radeon_bo_unref(radeon->tcl.aos[i].bo);
+ radeon->tcl.aos[i].bo = NULL;
+
+ }
+ }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_dma.h b/src/mesa/drivers/dri/radeon/radeon_dma.h
new file mode 100644
index 0000000000..74e653fd18
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_dma.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+
+Copyright (C) 2004 Nicolai Haehnle.
+Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+
+The Weather Channel (TM) funded Tungsten Graphics to develop the
+initial release of the Radeon 8500 driver under the XFree86 license.
+This notice must be preserved.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef RADEON_DMA_H
+#define RADEON_DMA_H
+
+void radeonEmitVec4(uint32_t *out, const GLvoid * data, int stride, int count);
+void radeonEmitVec8(uint32_t *out, const GLvoid * data, int stride, int count);
+void radeonEmitVec12(uint32_t *out, const GLvoid * data, int stride, int count);
+void radeonEmitVec16(uint32_t *out, const GLvoid * data, int stride, int count);
+
+void rcommon_emit_vector(GLcontext * ctx, struct radeon_aos *aos,
+ const GLvoid * data, int size, int stride, int count);
+
+void radeonReturnDmaRegion(radeonContextPtr rmesa, int return_bytes);
+void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size);
+void radeon_init_dma(radeonContextPtr rmesa);
+void radeonReturnDmaRegion(radeonContextPtr rmesa, int return_bytes);
+void radeonAllocDmaRegion(radeonContextPtr rmesa,
+ struct radeon_bo **pbo, int *poffset,
+ int bytes, int alignment);
+void radeonReleaseDmaRegions(radeonContextPtr rmesa);
+
+void rcommon_flush_last_swtcl_prim(GLcontext *ctx);
+
+void *rcommonAllocDmaLowVerts(radeonContextPtr rmesa, int nverts, int vsize);
+void radeonFreeDmaRegions(radeonContextPtr rmesa);
+void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs );
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c
new file mode 100644
index 0000000000..d83b166742
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c
@@ -0,0 +1,599 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Red Hat Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/fbobject.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+#include "main/context.h"
+#include "main/texformat.h"
+#include "main/texrender.h"
+#include "drivers/common/meta.h"
+
+#include "radeon_common.h"
+#include "radeon_mipmap_tree.h"
+
+#define FILE_DEBUG_FLAG RADEON_TEXTURE
+#define DBG(...) do { \
+ if (RADEON_DEBUG & FILE_DEBUG_FLAG) \
+ _mesa_printf(__VA_ARGS__); \
+} while(0)
+
+static struct gl_framebuffer *
+radeon_new_framebuffer(GLcontext *ctx, GLuint name)
+{
+ return _mesa_new_framebuffer(ctx, name);
+}
+
+static void
+radeon_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+
+ ASSERT(rrb);
+
+ if (rrb && rrb->bo) {
+ radeon_bo_unref(rrb->bo);
+ }
+ _mesa_free(rrb);
+}
+
+static void *
+radeon_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ return NULL;
+}
+
+/**
+ * Called via glRenderbufferStorageEXT() to set the format and allocate
+ * storage for a user-created renderbuffer.
+ */
+static GLboolean
+radeon_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height)
+{
+ struct radeon_context *radeon = RADEON_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+ GLboolean software_buffer = GL_FALSE;
+ int cpp;
+
+ ASSERT(rb->Name != 0);
+ switch (internalFormat) {
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ rb->_ActualFormat = GL_RGB5;
+ rb->DataType = GL_UNSIGNED_BYTE;
+ rb->RedBits = 5;
+ rb->GreenBits = 6;
+ rb->BlueBits = 5;
+ cpp = 2;
+ break;
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ rb->_ActualFormat = GL_RGB8;
+ rb->DataType = GL_UNSIGNED_BYTE;
+ rb->RedBits = 8;
+ rb->GreenBits = 8;
+ rb->BlueBits = 8;
+ rb->AlphaBits = 0;
+ cpp = 4;
+ break;
+ 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:
+ rb->_ActualFormat = GL_RGBA8;
+ rb->DataType = GL_UNSIGNED_BYTE;
+ rb->RedBits = 8;
+ rb->GreenBits = 8;
+ rb->BlueBits = 8;
+ rb->AlphaBits = 8;
+ cpp = 4;
+ break;
+ case GL_STENCIL_INDEX:
+ case GL_STENCIL_INDEX1_EXT:
+ case GL_STENCIL_INDEX4_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ case GL_STENCIL_INDEX16_EXT:
+ /* alloc a depth+stencil buffer */
+ rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
+ rb->StencilBits = 8;
+ cpp = 4;
+ break;
+ case GL_DEPTH_COMPONENT16:
+ rb->_ActualFormat = GL_DEPTH_COMPONENT16;
+ rb->DataType = GL_UNSIGNED_SHORT;
+ rb->DepthBits = 16;
+ cpp = 2;
+ break;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ rb->_ActualFormat = GL_DEPTH_COMPONENT24;
+ rb->DataType = GL_UNSIGNED_INT;
+ rb->DepthBits = 24;
+ cpp = 4;
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
+ rb->DepthBits = 24;
+ rb->StencilBits = 8;
+ cpp = 4;
+ break;
+ default:
+ _mesa_problem(ctx,
+ "Unexpected format in intel_alloc_renderbuffer_storage");
+ return GL_FALSE;
+ }
+
+ if (ctx->Driver.Flush)
+ ctx->Driver.Flush(ctx); /* +r6/r7 */
+
+ if (rrb->bo)
+ radeon_bo_unref(rrb->bo);
+
+
+ if (software_buffer) {
+ return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
+ width, height);
+ }
+ else {
+ uint32_t size;
+ uint32_t pitch = ((cpp * width + 63) & ~63) / cpp;
+
+ fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width,
+ height, pitch);
+
+ size = pitch * height * cpp;
+ rrb->pitch = pitch * cpp;
+ rrb->cpp = cpp;
+ rrb->bo = radeon_bo_open(radeon->radeonScreen->bom,
+ 0,
+ size,
+ 0,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+ rb->Width = width;
+ rb->Height = height;
+ return GL_TRUE;
+ }
+
+}
+
+
+/**
+ * Called for each hardware renderbuffer when a _window_ is resized.
+ * Just update fields.
+ * Not used for user-created renderbuffers!
+ */
+static GLboolean
+radeon_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ ASSERT(rb->Name == 0);
+ rb->Width = width;
+ rb->Height = height;
+ rb->_ActualFormat = internalFormat;
+
+ return GL_TRUE;
+}
+
+
+static void
+radeon_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint width, GLuint height)
+{
+ struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb;
+ int i;
+
+ _mesa_resize_framebuffer(ctx, fb, width, height);
+
+ fb->Initialized = GL_TRUE; /* XXX remove someday */
+
+ if (fb->Name != 0) {
+ return;
+ }
+
+ /* Make sure all window system renderbuffers are up to date */
+ for (i = 0; i < 2; i++) {
+ struct gl_renderbuffer *rb = &radeon_fb->color_rb[i]->base;
+
+ /* only resize if size is changing */
+ if (rb && (rb->Width != width || rb->Height != height)) {
+ rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
+ }
+ }
+}
+
+
+/** Dummy function for gl_renderbuffer::AllocStorage() */
+static GLboolean
+radeon_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
+ return GL_FALSE;
+}
+
+struct radeon_renderbuffer *
+radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv)
+{
+ struct radeon_renderbuffer *rrb;
+
+ rrb = CALLOC_STRUCT(radeon_renderbuffer);
+ if (!rrb)
+ return NULL;
+
+ _mesa_init_renderbuffer(&rrb->base, 0);
+ rrb->base.ClassID = RADEON_RB_CLASS;
+
+ /* XXX format junk */
+ switch (format) {
+ case GL_RGB5:
+ rrb->base._ActualFormat = GL_RGB5;
+ rrb->base._BaseFormat = GL_RGBA;
+ rrb->base.RedBits = 5;
+ rrb->base.GreenBits = 6;
+ rrb->base.BlueBits = 5;
+ rrb->base.DataType = GL_UNSIGNED_BYTE;
+ break;
+ case GL_RGB8:
+ rrb->base._ActualFormat = GL_RGB8;
+ rrb->base._BaseFormat = GL_RGB;
+ rrb->base.RedBits = 8;
+ rrb->base.GreenBits = 8;
+ rrb->base.BlueBits = 8;
+ rrb->base.AlphaBits = 0;
+ rrb->base.DataType = GL_UNSIGNED_BYTE;
+ break;
+ case GL_RGBA8:
+ rrb->base._ActualFormat = GL_RGBA8;
+ rrb->base._BaseFormat = GL_RGBA;
+ rrb->base.RedBits = 8;
+ rrb->base.GreenBits = 8;
+ rrb->base.BlueBits = 8;
+ rrb->base.AlphaBits = 8;
+ rrb->base.DataType = GL_UNSIGNED_BYTE;
+ break;
+ case GL_STENCIL_INDEX8_EXT:
+ rrb->base._ActualFormat = GL_STENCIL_INDEX8_EXT;
+ rrb->base._BaseFormat = GL_STENCIL_INDEX;
+ rrb->base.StencilBits = 8;
+ rrb->base.DataType = GL_UNSIGNED_BYTE;
+ break;
+ case GL_DEPTH_COMPONENT16:
+ rrb->base._ActualFormat = GL_DEPTH_COMPONENT16;
+ rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
+ rrb->base.DepthBits = 16;
+ rrb->base.DataType = GL_UNSIGNED_SHORT;
+ break;
+ case GL_DEPTH_COMPONENT24:
+ rrb->base._ActualFormat = GL_DEPTH_COMPONENT24;
+ rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
+ rrb->base.DepthBits = 24;
+ rrb->base.DataType = GL_UNSIGNED_INT;
+ break;
+ case GL_DEPTH24_STENCIL8_EXT:
+ rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+ rrb->base.DepthBits = 24;
+ rrb->base.StencilBits = 8;
+ rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ break;
+ default:
+ fprintf(stderr, "%s: Unknown format 0x%04x\n", __FUNCTION__, format);
+ _mesa_delete_renderbuffer(&rrb->base);
+ return NULL;
+ }
+
+ rrb->dPriv = driDrawPriv;
+ rrb->base.InternalFormat = format;
+
+ rrb->base.Delete = radeon_delete_renderbuffer;
+ rrb->base.AllocStorage = radeon_alloc_window_storage;
+ rrb->base.GetPointer = radeon_get_pointer;
+
+ rrb->bo = NULL;
+ return rrb;
+}
+
+static struct gl_renderbuffer *
+radeon_new_renderbuffer(GLcontext * ctx, GLuint name)
+{
+ struct radeon_renderbuffer *rrb;
+
+ rrb = CALLOC_STRUCT(radeon_renderbuffer);
+ if (!rrb)
+ return NULL;
+
+ _mesa_init_renderbuffer(&rrb->base, name);
+ rrb->base.ClassID = RADEON_RB_CLASS;
+
+ rrb->base.Delete = radeon_delete_renderbuffer;
+ rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage;
+ rrb->base.GetPointer = radeon_get_pointer;
+
+ return &rrb->base;
+}
+
+static void
+radeon_bind_framebuffer(GLcontext * ctx, GLenum target,
+ struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
+{
+ if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
+ radeon_draw_buffer(ctx, fb);
+ }
+ else {
+ /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
+ }
+}
+
+static void
+radeon_framebuffer_renderbuffer(GLcontext * ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment, struct gl_renderbuffer *rb)
+{
+
+ if (ctx->Driver.Flush)
+ ctx->Driver.Flush(ctx); /* +r6/r7 */
+
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+ radeon_draw_buffer(ctx, fb);
+}
+
+
+static GLboolean
+radeon_update_wrapper(GLcontext *ctx, struct radeon_renderbuffer *rrb,
+ struct gl_texture_image *texImage)
+{
+ int retry = 0;
+restart:
+ if (texImage->TexFormat == &_mesa_texformat_argb8888) {
+ rrb->cpp = 4;
+ rrb->base._ActualFormat = GL_RGBA8;
+ rrb->base._BaseFormat = GL_RGBA;
+ rrb->base.DataType = GL_UNSIGNED_BYTE;
+ DBG("Render to RGBA8 texture OK\n");
+ }
+ else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
+ rrb->cpp = 2;
+ rrb->base._ActualFormat = GL_RGB5;
+ rrb->base._BaseFormat = GL_RGB;
+ rrb->base.DataType = GL_UNSIGNED_BYTE;
+ DBG("Render to RGB5 texture OK\n");
+ }
+ else if (texImage->TexFormat == &_mesa_texformat_argb1555) {
+ rrb->cpp = 2;
+ rrb->base._ActualFormat = GL_RGB5_A1;
+ rrb->base._BaseFormat = GL_RGBA;
+ rrb->base.DataType = GL_UNSIGNED_BYTE;
+ DBG("Render to ARGB1555 texture OK\n");
+ }
+ else if (texImage->TexFormat == &_mesa_texformat_argb4444) {
+ rrb->cpp = 2;
+ rrb->base._ActualFormat = GL_RGBA4;
+ rrb->base._BaseFormat = GL_RGBA;
+ rrb->base.DataType = GL_UNSIGNED_BYTE;
+ DBG("Render to ARGB1555 texture OK\n");
+ }
+ else if (texImage->TexFormat == &_mesa_texformat_z16) {
+ rrb->cpp = 2;
+ rrb->base._ActualFormat = GL_DEPTH_COMPONENT16;
+ rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
+ rrb->base.DataType = GL_UNSIGNED_SHORT;
+ DBG("Render to DEPTH16 texture OK\n");
+ }
+ else if (texImage->TexFormat == &_mesa_texformat_s8_z24) {
+ rrb->cpp = 4;
+ rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+ rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ DBG("Render to DEPTH_STENCIL texture OK\n");
+ }
+ else {
+ /* try redoing the FBO */
+ if (retry == 1) {
+ DBG("Render to texture BAD FORMAT %d\n",
+ texImage->TexFormat->MesaFormat);
+ return GL_FALSE;
+ }
+ texImage->TexFormat = radeonChooseTextureFormat(ctx, texImage->InternalFormat, 0,
+ texImage->TexFormat->DataType,
+ 1);
+
+ retry++;
+ goto restart;
+ }
+
+ rrb->pitch = texImage->Width * rrb->cpp;
+ rrb->base.InternalFormat = rrb->base._ActualFormat;
+ rrb->base.Width = texImage->Width;
+ rrb->base.Height = texImage->Height;
+ rrb->base.RedBits = texImage->TexFormat->RedBits;
+ rrb->base.GreenBits = texImage->TexFormat->GreenBits;
+ rrb->base.BlueBits = texImage->TexFormat->BlueBits;
+ rrb->base.AlphaBits = texImage->TexFormat->AlphaBits;
+ rrb->base.DepthBits = texImage->TexFormat->DepthBits;
+ rrb->base.StencilBits = texImage->TexFormat->StencilBits;
+
+ rrb->base.Delete = radeon_delete_renderbuffer;
+ rrb->base.AllocStorage = radeon_nop_alloc_storage;
+
+ return GL_TRUE;
+}
+
+
+static struct radeon_renderbuffer *
+radeon_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
+{
+ const GLuint name = ~0; /* not significant, but distinct for debugging */
+ struct radeon_renderbuffer *rrb;
+
+ /* make an radeon_renderbuffer to wrap the texture image */
+ rrb = CALLOC_STRUCT(radeon_renderbuffer);
+ if (!rrb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
+ return NULL;
+ }
+
+ _mesa_init_renderbuffer(&rrb->base, name);
+ rrb->base.ClassID = RADEON_RB_CLASS;
+
+ if (!radeon_update_wrapper(ctx, rrb, texImage)) {
+ _mesa_free(rrb);
+ return NULL;
+ }
+
+ return rrb;
+
+}
+static void
+radeon_render_texture(GLcontext * ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att)
+{
+ struct gl_texture_image *newImage
+ = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer);
+ radeon_texture_image *radeon_image;
+ GLuint imageOffset;
+
+ (void) fb;
+
+ ASSERT(newImage);
+
+ if (newImage->Border != 0) {
+ /* Fallback on drawing to a texture with a border, which won't have a
+ * miptree.
+ */
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+ _mesa_render_texture(ctx, fb, att);
+ return;
+ }
+ else if (!rrb) {
+ rrb = radeon_wrap_texture(ctx, newImage);
+ if (rrb) {
+ /* bind the wrapper to the attachment point */
+ _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
+ }
+ else {
+ /* fallback to software rendering */
+ _mesa_render_texture(ctx, fb, att);
+ return;
+ }
+ }
+
+ if (!radeon_update_wrapper(ctx, rrb, newImage)) {
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+ _mesa_render_texture(ctx, fb, att);
+ return;
+ }
+
+ DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
+ _glthread_GetID(),
+ att->Texture->Name, newImage->Width, newImage->Height,
+ rrb->base.RefCount);
+
+ /* point the renderbufer's region to the texture image region */
+ radeon_image = (radeon_texture_image *)newImage;
+ if (rrb->bo != radeon_image->mt->bo) {
+ if (rrb->bo)
+ radeon_bo_unref(rrb->bo);
+ rrb->bo = radeon_image->mt->bo;
+ radeon_bo_ref(rrb->bo);
+ }
+
+ /* compute offset of the particular 2D image within the texture region */
+ imageOffset = radeon_miptree_image_offset(radeon_image->mt,
+ att->CubeMapFace,
+ att->TextureLevel);
+
+ if (att->Texture->Target == GL_TEXTURE_3D) {
+ GLuint offsets[6];
+ radeon_miptree_depth_offsets(radeon_image->mt, att->TextureLevel,
+ offsets);
+ imageOffset += offsets[att->Zoffset];
+ }
+
+ /* store that offset in the region */
+ rrb->draw_offset = imageOffset;
+
+ /* update drawing region, etc */
+ radeon_draw_buffer(ctx, fb);
+}
+
+static void
+radeon_finish_render_texture(GLcontext * ctx,
+ struct gl_renderbuffer_attachment *att)
+{
+
+}
+static void
+radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+}
+
+void radeon_fbo_init(struct radeon_context *radeon)
+{
+ radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
+ radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer;
+ radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer;
+ radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
+ radeon->glCtx->Driver.RenderTexture = radeon_render_texture;
+ radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture;
+ radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers;
+ radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer;
+ radeon->glCtx->Driver.BlitFramebuffer = _mesa_meta_blit_framebuffer;
+}
+
+
+void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
+ struct radeon_bo *bo)
+{
+ struct radeon_bo *old;
+ old = rb->bo;
+ rb->bo = bo;
+ radeon_bo_ref(bo);
+ if (old)
+ radeon_bo_unref(old);
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.c b/src/mesa/drivers/dri/radeon/radeon_ioctl.c
index 09acf6b4f8..a0106d00fa 100644
--- a/src/mesa/drivers/dri/radeon/radeon_ioctl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.c
@@ -35,7 +35,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sched.h>
-#include <errno.h>
+#include <errno.h>
+
+#include "main/attrib.h"
+#include "main/enable.h"
+#include "main/blend.h"
+#include "main/bufferobj.h"
+#include "main/buffers.h"
+#include "main/depth.h"
+#include "main/shaders.h"
+#include "main/texstate.h"
+#include "main/varray.h"
+#include "glapi/dispatch.h"
+#include "swrast/swrast.h"
+#include "main/stencil.h"
+#include "main/matrix.h"
#include "main/glheader.h"
#include "main/imports.h"
@@ -43,6 +57,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "swrast/swrast.h"
#include "radeon_context.h"
+#include "radeon_common.h"
#include "radeon_state.h"
#include "radeon_ioctl.h"
#include "radeon_tcl.h"
@@ -58,75 +73,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define RADEON_IDLE_RETRY 16
-static void radeonWaitForIdle( radeonContextPtr rmesa );
-static int radeonFlushCmdBufLocked( radeonContextPtr rmesa,
- const char * caller );
-
-static void print_state_atom( struct radeon_state_atom *state )
-{
- int i;
-
- fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size);
-
- if (RADEON_DEBUG & DEBUG_VERBOSE)
- for (i = 0 ; i < state->cmd_size ; i++)
- fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]);
-
-}
-
-static void radeonSaveHwState( radeonContextPtr rmesa )
-{
- struct radeon_state_atom *atom;
- char * dest = rmesa->backup_store.cmd_buf;
-
- if (RADEON_DEBUG & DEBUG_STATE)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- rmesa->backup_store.cmd_used = 0;
-
- foreach( atom, &rmesa->hw.atomlist ) {
- if ( atom->check( rmesa->glCtx ) ) {
- int size = atom->cmd_size * 4;
- memcpy( dest, atom->cmd, size);
- dest += size;
- rmesa->backup_store.cmd_used += size;
- if (RADEON_DEBUG & DEBUG_STATE)
- print_state_atom( atom );
- }
- }
-
- assert( rmesa->backup_store.cmd_used <= RADEON_CMD_BUF_SZ );
- if (RADEON_DEBUG & DEBUG_STATE)
- fprintf(stderr, "Returning to radeonEmitState\n");
-}
-
-/* At this point we were in FlushCmdBufLocked but we had lost our context, so
- * we need to unwire our current cmdbuf, hook the one with the saved state in
- * it, flush it, and then put the current one back. This is so commands at the
- * start of a cmdbuf can rely on the state being kept from the previous one.
- */
-static void radeonBackUpAndEmitLostStateLocked( radeonContextPtr rmesa )
-{
- GLuint nr_released_bufs;
- struct radeon_store saved_store;
-
- if (rmesa->backup_store.cmd_used == 0)
- return;
-
- if (RADEON_DEBUG & DEBUG_STATE)
- fprintf(stderr, "Emitting backup state on lost context\n");
-
- rmesa->lost_context = GL_FALSE;
-
- nr_released_bufs = rmesa->dma.nr_released_bufs;
- saved_store = rmesa->store;
- rmesa->dma.nr_released_bufs = 0;
- rmesa->store = rmesa->backup_store;
- radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
- rmesa->dma.nr_released_bufs = nr_released_bufs;
- rmesa->store = saved_store;
-}
-
/* =============================================================
* Kernel command buffer handling
*/
@@ -134,965 +80,382 @@ static void radeonBackUpAndEmitLostStateLocked( radeonContextPtr rmesa )
/* The state atoms will be emitted in the order they appear in the atom list,
* so this step is important.
*/
-void radeonSetUpAtomList( radeonContextPtr rmesa )
+void radeonSetUpAtomList( r100ContextPtr rmesa )
{
- int i, mtu = rmesa->glCtx->Const.MaxTextureUnits;
-
- make_empty_list(&rmesa->hw.atomlist);
- rmesa->hw.atomlist.name = "atom-list";
-
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.ctx);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.set);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.lin);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.msk);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.vpt);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.tcl);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.msc);
+ int i, mtu = rmesa->radeon.glCtx->Const.MaxTextureUnits;
+
+ make_empty_list(&rmesa->radeon.hw.atomlist);
+ rmesa->radeon.hw.atomlist.name = "atom-list";
+
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ctx);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.set);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lin);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msk);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.vpt);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tcl);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msc);
for (i = 0; i < mtu; ++i) {
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.tex[i]);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.txr[i]);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.cube[i]);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i]);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.txr[i]);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i]);
}
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.zbs);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.mtl);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.zbs);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mtl);
for (i = 0; i < 3 + mtu; ++i)
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.mat[i]);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i]);
for (i = 0; i < 8; ++i)
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.lit[i]);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i]);
for (i = 0; i < 6; ++i)
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.ucp[i]);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.eye);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.grd);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.fog);
- insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.glt);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i]);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.eye);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.grd);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.fog);
+ insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.glt);
}
-void radeonEmitState( radeonContextPtr rmesa )
+static void radeonEmitScissor(r100ContextPtr rmesa)
{
- struct radeon_state_atom *atom;
- char *dest;
-
- if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (rmesa->save_on_next_emit) {
- radeonSaveHwState(rmesa);
- rmesa->save_on_next_emit = GL_FALSE;
- }
-
- /* this code used to return here but now it emits zbs */
-
- /* To avoid going across the entire set of states multiple times, just check
- * for enough space for the case of emitting all state, and inline the
- * radeonAllocCmdBuf code here without all the checks.
- */
- radeonEnsureCmdBufSpace(rmesa, rmesa->hw.max_state_size);
- dest = rmesa->store.cmd_buf + rmesa->store.cmd_used;
-
- /* We always always emit zbs, this is due to a bug found by keithw in
- the hardware and rediscovered after Erics changes by me.
- if you ever touch this code make sure you emit zbs otherwise
- you get tcl lockups on at least M7/7500 class of chips - airlied */
- rmesa->hw.zbs.dirty=1;
-
- if (RADEON_DEBUG & DEBUG_STATE) {
- foreach(atom, &rmesa->hw.atomlist) {
- if (atom->dirty || rmesa->hw.all_dirty) {
- if (atom->check(rmesa->glCtx))
- print_state_atom(atom);
- else
- fprintf(stderr, "skip state %s\n", atom->name);
- }
- }
- }
-
- foreach(atom, &rmesa->hw.atomlist) {
- if (rmesa->hw.all_dirty)
- atom->dirty = GL_TRUE;
- if (!(rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_TCL) &&
- atom->is_tcl)
- atom->dirty = GL_FALSE;
- if (atom->dirty) {
- if (atom->check(rmesa->glCtx)) {
- int size = atom->cmd_size * 4;
- memcpy(dest, atom->cmd, size);
- dest += size;
- rmesa->store.cmd_used += size;
- atom->dirty = GL_FALSE;
- }
- }
- }
-
- assert(rmesa->store.cmd_used <= RADEON_CMD_BUF_SZ);
-
- rmesa->hw.is_dirty = GL_FALSE;
- rmesa->hw.all_dirty = GL_FALSE;
+ BATCH_LOCALS(&rmesa->radeon);
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ return;
+ }
+ if (rmesa->radeon.state.scissor.enabled) {
+ BEGIN_BATCH(6);
+ OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0));
+ OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] | RADEON_SCISSOR_ENABLE);
+ OUT_BATCH(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
+ OUT_BATCH((rmesa->radeon.state.scissor.rect.y1 << 16) |
+ rmesa->radeon.state.scissor.rect.x1);
+ OUT_BATCH(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
+ OUT_BATCH(((rmesa->radeon.state.scissor.rect.y2) << 16) |
+ (rmesa->radeon.state.scissor.rect.x2));
+ END_BATCH();
+ } else {
+ BEGIN_BATCH(2);
+ OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0));
+ OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ~RADEON_SCISSOR_ENABLE);
+ END_BATCH();
+ }
}
/* Fire a section of the retained (indexed_verts) buffer as a regular
- * primtive.
+ * primtive.
*/
-extern void radeonEmitVbufPrim( radeonContextPtr rmesa,
+extern void radeonEmitVbufPrim( r100ContextPtr rmesa,
GLuint vertex_format,
GLuint primitive,
GLuint vertex_nr )
{
- drm_radeon_cmd_header_t *cmd;
-
+ BATCH_LOCALS(&rmesa->radeon);
assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
-
- radeonEmitState( rmesa );
-
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s cmd_used/4: %d\n", __FUNCTION__,
- rmesa->store.cmd_used/4);
-
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, VBUF_BUFSZ,
- __FUNCTION__ );
+
+ radeonEmitState(&rmesa->radeon);
+ radeonEmitScissor(rmesa);
+
#if RADEON_OLD_PACKETS
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
- cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM | (3 << 16);
- cmd[2].i = rmesa->ioctl.vertex_offset;
- cmd[3].i = vertex_nr;
- cmd[4].i = vertex_format;
- cmd[5].i = (primitive |
- RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
- RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
- RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
- (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
-
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
- __FUNCTION__,
- cmd[1].i, cmd[2].i, cmd[4].i, cmd[5].i);
+ BEGIN_BATCH(8);
+ OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3);
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ OUT_BATCH_RELOC(rmesa->ioctl.vertex_offset, rmesa->ioctl.bo, rmesa->ioctl.vertex_offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ } else {
+ OUT_BATCH(rmesa->ioctl.vertex_offset);
+ }
+
+ OUT_BATCH(vertex_nr);
+ OUT_BATCH(vertex_format);
+ OUT_BATCH(primitive | RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
+ RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+ (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->ioctl.bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ }
+
+ END_BATCH();
+
#else
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
- cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_VBUF | (1 << 16);
- cmd[2].i = vertex_format;
- cmd[3].i = (primitive |
- RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
- RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
- RADEON_CP_VC_CNTL_MAOS_ENABLE |
- RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
- (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
-
-
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
- __FUNCTION__,
- cmd[1].i, cmd[2].i, cmd[3].i);
+ BEGIN_BATCH(4);
+ OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_DRAW_VBUF, 1);
+ OUT_BATCH(vertex_format);
+ OUT_BATCH(primitive |
+ RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
+ RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+ RADEON_CP_VC_CNTL_MAOS_ENABLE |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+ (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
+ END_BATCH();
#endif
}
-
-void radeonFlushElts( radeonContextPtr rmesa )
+void radeonFlushElts( GLcontext *ctx )
{
- int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
- int dwords;
-#if RADEON_OLD_PACKETS
- int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 24)) / 2;
-#else
- int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 16)) / 2;
-#endif
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&rmesa->radeon);
+ int nr;
+ uint32_t *cmd = (uint32_t *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_start);
+ int dwords = (rmesa->radeon.cmdbuf.cs->section_ndw - rmesa->radeon.cmdbuf.cs->section_cdw);
- if (RADEON_DEBUG & DEBUG_IOCTL)
+ if (RADEON_DEBUG & RADEON_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
- assert( rmesa->dma.flush == radeonFlushElts );
- rmesa->dma.flush = NULL;
+ assert( rmesa->radeon.dma.flush == radeonFlushElts );
+ rmesa->radeon.dma.flush = NULL;
- /* Cope with odd number of elts:
- */
- rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
- dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
+ nr = rmesa->tcl.elt_used;
#if RADEON_OLD_PACKETS
- cmd[1] |= (dwords - 3) << 16;
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ dwords -= 2;
+ }
+#endif
+
+#if RADEON_OLD_PACKETS
+ cmd[1] |= (dwords + 3) << 16;
cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
#else
- cmd[1] |= (dwords - 3) << 16;
+ cmd[1] |= (dwords + 2) << 16;
cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
#endif
- if (RADEON_DEBUG & DEBUG_SYNC) {
+ rmesa->radeon.cmdbuf.cs->cdw += dwords;
+ rmesa->radeon.cmdbuf.cs->section_cdw += dwords;
+
+#if RADEON_OLD_PACKETS
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->ioctl.bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ }
+#endif
+
+ END_BATCH();
+
+ if (RADEON_DEBUG & RADEON_SYNC) {
fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
- radeonFinish( rmesa->glCtx );
+ radeonFinish( rmesa->radeon.glCtx );
}
-}
+}
-GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa,
+GLushort *radeonAllocEltsOpenEnded( r100ContextPtr rmesa,
GLuint vertex_format,
GLuint primitive,
GLuint min_nr )
{
- drm_radeon_cmd_header_t *cmd;
GLushort *retval;
+ int align_min_nr;
+ BATCH_LOCALS(&rmesa->radeon);
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %d\n", __FUNCTION__, min_nr);
+ if (RADEON_DEBUG & RADEON_IOCTL)
+ fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
-
- radeonEmitState( rmesa );
-
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa,
- ELTS_BUFSZ(min_nr),
- __FUNCTION__ );
+
+ radeonEmitState(&rmesa->radeon);
+ radeonEmitScissor(rmesa);
+
+ rmesa->tcl.elt_cmd_start = rmesa->radeon.cmdbuf.cs->cdw;
+
+ /* round up min_nr to align the state */
+ align_min_nr = (min_nr + 1) & ~1;
+
#if RADEON_OLD_PACKETS
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
- cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM;
- cmd[2].i = rmesa->ioctl.vertex_offset;
- cmd[3].i = 0xffff;
- cmd[4].i = vertex_format;
- cmd[5].i = (primitive |
- RADEON_CP_VC_CNTL_PRIM_WALK_IND |
- RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
- RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
-
- retval = (GLushort *)(cmd+6);
-#else
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
- cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_INDX;
- cmd[2].i = vertex_format;
- cmd[3].i = (primitive |
- RADEON_CP_VC_CNTL_PRIM_WALK_IND |
- RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
- RADEON_CP_VC_CNTL_MAOS_ENABLE |
- RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
-
- retval = (GLushort *)(cmd+4);
+ BEGIN_BATCH_NO_AUTOSTATE(2+ELTS_BUFSZ(align_min_nr)/4);
+ OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 0);
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ OUT_BATCH_RELOC(rmesa->ioctl.vertex_offset, rmesa->ioctl.bo, rmesa->ioctl.vertex_offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ } else {
+ OUT_BATCH(rmesa->ioctl.vertex_offset);
+ }
+ OUT_BATCH(rmesa->ioctl.vertex_max);
+ OUT_BATCH(vertex_format);
+ OUT_BATCH(primitive |
+ RADEON_CP_VC_CNTL_PRIM_WALK_IND |
+ RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
+#else
+ BEGIN_BATCH_NO_AUTOSTATE(ELTS_BUFSZ(align_min_nr)/4);
+ OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_DRAW_INDX, 0);
+ OUT_BATCH(vertex_format);
+ OUT_BATCH(primitive |
+ RADEON_CP_VC_CNTL_PRIM_WALK_IND |
+ RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+ RADEON_CP_VC_CNTL_MAOS_ENABLE |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
#endif
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s: header 0x%x vfmt 0x%x prim %x \n",
- __FUNCTION__,
- cmd[1].i, vertex_format, primitive);
- assert(!rmesa->dma.flush);
- rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
- rmesa->dma.flush = radeonFlushElts;
+ rmesa->tcl.elt_cmd_offset = rmesa->radeon.cmdbuf.cs->cdw;
+ rmesa->tcl.elt_used = min_nr;
- rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
+ retval = (GLushort *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_offset);
- return retval;
-}
+ if (RADEON_DEBUG & RADEON_RENDER)
+ fprintf(stderr, "%s: header prim %x \n",
+ __FUNCTION__, primitive);
+ assert(!rmesa->radeon.dma.flush);
+ rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ rmesa->radeon.dma.flush = radeonFlushElts;
+ return retval;
+}
-void radeonEmitVertexAOS( radeonContextPtr rmesa,
+void radeonEmitVertexAOS( r100ContextPtr rmesa,
GLuint vertex_size,
+ struct radeon_bo *bo,
GLuint offset )
{
#if RADEON_OLD_PACKETS
- rmesa->ioctl.vertex_size = vertex_size;
rmesa->ioctl.vertex_offset = offset;
+ rmesa->ioctl.bo = bo;
#else
- drm_radeon_cmd_header_t *cmd;
+ BATCH_LOCALS(&rmesa->radeon);
- if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
+ if (RADEON_DEBUG & (RADEON_PRIMS|DEBUG_IOCTL))
fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
__FUNCTION__, vertex_size, offset);
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
- __FUNCTION__ );
+ BEGIN_BATCH(7);
+ OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, 2);
+ OUT_BATCH(1);
+ OUT_BATCH(vertex_size | (vertex_size << 8));
+ OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
+ END_BATCH();
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
- cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (2 << 16);
- cmd[2].i = 1;
- cmd[3].i = vertex_size | (vertex_size << 8);
- cmd[4].i = offset;
#endif
}
-
-void radeonEmitAOS( radeonContextPtr rmesa,
- struct radeon_dma_region **component,
+
+void radeonEmitAOS( r100ContextPtr rmesa,
GLuint nr,
GLuint offset )
{
#if RADEON_OLD_PACKETS
assert( nr == 1 );
- assert( component[0]->aos_size == component[0]->aos_stride );
- rmesa->ioctl.vertex_size = component[0]->aos_size;
- rmesa->ioctl.vertex_offset =
- (component[0]->aos_start + offset * component[0]->aos_stride * 4);
+ rmesa->ioctl.bo = rmesa->radeon.tcl.aos[0].bo;
+ rmesa->ioctl.vertex_offset =
+ (rmesa->radeon.tcl.aos[0].offset + offset * rmesa->radeon.tcl.aos[0].stride * 4);
+ rmesa->ioctl.vertex_max = rmesa->radeon.tcl.aos[0].count;
#else
- drm_radeon_cmd_header_t *cmd;
- int sz = AOS_BUFSZ(nr);
+ BATCH_LOCALS(&rmesa->radeon);
+ uint32_t voffset;
+ // int sz = AOS_BUFSZ(nr);
+ int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
int i;
- int *tmp;
- if (RADEON_DEBUG & DEBUG_IOCTL)
+ if (RADEON_DEBUG & RADEON_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
-
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sz,
- __FUNCTION__ );
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
- cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (((sz / sizeof(int))-3) << 16);
- cmd[2].i = nr;
- tmp = &cmd[0].i;
- cmd += 3;
-
- for (i = 0 ; i < nr ; i++) {
- if (i & 1) {
- cmd[0].i |= ((component[i]->aos_stride << 24) |
- (component[i]->aos_size << 16));
- cmd[2].i = (component[i]->aos_start +
- offset * component[i]->aos_stride * 4);
- cmd += 3;
- }
- else {
- cmd[0].i = ((component[i]->aos_stride << 8) |
- (component[i]->aos_size << 0));
- cmd[1].i = (component[i]->aos_start +
- offset * component[i]->aos_stride * 4);
+ BEGIN_BATCH(sz+2+(nr * 2));
+ OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, sz - 1);
+ OUT_BATCH(nr);
+
+ if (!rmesa->radeon.radeonScreen->kernel_mm) {
+ for (i = 0; i + 1 < nr; i += 2) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
+ (rmesa->radeon.tcl.aos[i].stride << 8) |
+ (rmesa->radeon.tcl.aos[i + 1].components << 16) |
+ (rmesa->radeon.tcl.aos[i + 1].stride << 24));
+
+ voffset = rmesa->radeon.tcl.aos[i + 0].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
+ OUT_BATCH_RELOC(voffset,
+ rmesa->radeon.tcl.aos[i].bo,
+ voffset,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ voffset = rmesa->radeon.tcl.aos[i + 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
+ OUT_BATCH_RELOC(voffset,
+ rmesa->radeon.tcl.aos[i+1].bo,
+ voffset,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
}
- }
- if (RADEON_DEBUG & DEBUG_VERTS) {
- fprintf(stderr, "%s:\n", __FUNCTION__);
- for (i = 0 ; i < sz ; i++)
- fprintf(stderr, " %d: %x\n", i, tmp[i]);
- }
-#endif
-}
-
-/* using already shifted color_fmt! */
-void radeonEmitBlit( radeonContextPtr rmesa, /* FIXME: which drmMinor is required? */
- GLuint color_fmt,
- GLuint src_pitch,
- GLuint src_offset,
- GLuint dst_pitch,
- GLuint dst_offset,
- GLint srcx, GLint srcy,
- GLint dstx, GLint dsty,
- GLuint w, GLuint h )
-{
- drm_radeon_cmd_header_t *cmd;
-
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
- __FUNCTION__,
- src_pitch, src_offset, srcx, srcy,
- dst_pitch, dst_offset, dstx, dsty,
- w, h);
-
- assert( (src_pitch & 63) == 0 );
- assert( (dst_pitch & 63) == 0 );
- assert( (src_offset & 1023) == 0 );
- assert( (dst_offset & 1023) == 0 );
- assert( w < (1<<16) );
- assert( h < (1<<16) );
-
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 8 * sizeof(int),
- __FUNCTION__ );
-
-
- cmd[0].i = 0;
- cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
- cmd[1].i = RADEON_CP_PACKET3_CNTL_BITBLT_MULTI | (5 << 16);
- cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
- RADEON_GMC_DST_PITCH_OFFSET_CNTL |
- RADEON_GMC_BRUSH_NONE |
- color_fmt |
- RADEON_GMC_SRC_DATATYPE_COLOR |
- RADEON_ROP3_S |
- RADEON_DP_SRC_SOURCE_MEMORY |
- RADEON_GMC_CLR_CMP_CNTL_DIS |
- RADEON_GMC_WR_MSK_DIS );
-
- cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
- cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
- cmd[5].i = (srcx << 16) | srcy;
- cmd[6].i = (dstx << 16) | dsty; /* dst */
- cmd[7].i = (w << 16) | h;
-}
-
-
-void radeonEmitWait( radeonContextPtr rmesa, GLuint flags )
-{
- drm_radeon_cmd_header_t *cmd;
-
- assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
-
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 1 * sizeof(int),
- __FUNCTION__ );
- cmd[0].i = 0;
- cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
- cmd[0].wait.flags = flags;
-}
-
-
-static int radeonFlushCmdBufLocked( radeonContextPtr rmesa,
- const char * caller )
-{
- int ret, i;
- drm_radeon_cmd_buffer_t cmd;
-
- if (rmesa->lost_context)
- radeonBackUpAndEmitLostStateLocked(rmesa);
-
- if (RADEON_DEBUG & DEBUG_IOCTL) {
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (RADEON_DEBUG & DEBUG_VERBOSE)
- for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 )
- fprintf(stderr, "%d: %x\n", i/4,
- *(int *)(&rmesa->store.cmd_buf[i]));
- }
-
- if (RADEON_DEBUG & DEBUG_DMA)
- fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__,
- rmesa->dma.nr_released_bufs);
-
-
- if (RADEON_DEBUG & DEBUG_SANITY) {
- if (rmesa->state.scissor.enabled)
- ret = radeonSanityCmdBuffer( rmesa,
- rmesa->state.scissor.numClipRects,
- rmesa->state.scissor.pClipRects);
- else
- ret = radeonSanityCmdBuffer( rmesa,
- rmesa->numClipRects,
- rmesa->pClipRects);
- if (ret) {
- fprintf(stderr, "drmSanityCommandWrite: %d\n", ret);
- goto out;
+ if (nr & 1) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
+ (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
+ voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
+ OUT_BATCH_RELOC(voffset,
+ rmesa->radeon.tcl.aos[nr - 1].bo,
+ voffset,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
}
- }
-
-
- cmd.bufsz = rmesa->store.cmd_used;
- cmd.buf = rmesa->store.cmd_buf;
-
- if (rmesa->state.scissor.enabled) {
- cmd.nbox = rmesa->state.scissor.numClipRects;
- cmd.boxes = rmesa->state.scissor.pClipRects;
} else {
- cmd.nbox = rmesa->numClipRects;
- cmd.boxes = rmesa->pClipRects;
- }
-
- ret = drmCommandWrite( rmesa->dri.fd,
- DRM_RADEON_CMDBUF,
- &cmd, sizeof(cmd) );
-
- if (ret)
- fprintf(stderr, "drmCommandWrite: %d\n", ret);
-
- if (RADEON_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "\nSyncing in %s\n\n", __FUNCTION__);
- radeonWaitForIdleLocked( rmesa );
- }
-
- out:
- rmesa->store.primnr = 0;
- rmesa->store.statenr = 0;
- rmesa->store.cmd_used = 0;
- rmesa->dma.nr_released_bufs = 0;
- rmesa->save_on_next_emit = 1;
-
- return ret;
-}
-
-
-/* Note: does not emit any commands to avoid recursion on
- * radeonAllocCmdBuf.
- */
-void radeonFlushCmdBuf( radeonContextPtr rmesa, const char *caller )
-{
- int ret;
-
-
- LOCK_HARDWARE( rmesa );
-
- ret = radeonFlushCmdBufLocked( rmesa, caller );
-
- UNLOCK_HARDWARE( rmesa );
-
- if (ret) {
- fprintf(stderr, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret);
- exit(ret);
- }
-}
-
-/* =============================================================
- * Hardware vertex buffer handling
- */
-
-
-void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa )
-{
- struct radeon_dma_buffer *dmabuf;
- int fd = rmesa->dri.fd;
- int index = 0;
- int size = 0;
- drmDMAReq dma;
- int ret;
-
- if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- if (rmesa->dma.flush) {
- rmesa->dma.flush( rmesa );
- }
-
- if (rmesa->dma.current.buf)
- radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
-
- if (rmesa->dma.nr_released_bufs > 4)
- radeonFlushCmdBuf( rmesa, __FUNCTION__ );
-
- dma.context = rmesa->dri.hwContext;
- dma.send_count = 0;
- dma.send_list = NULL;
- dma.send_sizes = NULL;
- dma.flags = 0;
- dma.request_count = 1;
- dma.request_size = RADEON_BUFFER_SIZE;
- dma.request_list = &index;
- dma.request_sizes = &size;
- dma.granted_count = 0;
-
- LOCK_HARDWARE(rmesa); /* no need to validate */
-
- ret = drmDMA( fd, &dma );
-
- if (ret != 0) {
- /* Free some up this way?
- */
- if (rmesa->dma.nr_released_bufs) {
- radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
- }
-
- if (RADEON_DEBUG & DEBUG_DMA)
- fprintf(stderr, "Waiting for buffers\n");
-
- radeonWaitForIdleLocked( rmesa );
- ret = drmDMA( fd, &dma );
-
- if ( ret != 0 ) {
- UNLOCK_HARDWARE( rmesa );
- fprintf( stderr, "Error: Could not get dma buffer... exiting\n" );
- exit( -1 );
- }
- }
-
- UNLOCK_HARDWARE(rmesa);
-
- if (RADEON_DEBUG & DEBUG_DMA)
- fprintf(stderr, "Allocated buffer %d\n", index);
-
- dmabuf = CALLOC_STRUCT( radeon_dma_buffer );
- dmabuf->buf = &rmesa->radeonScreen->buffers->list[index];
- dmabuf->refcount = 1;
-
- rmesa->dma.current.buf = dmabuf;
- rmesa->dma.current.address = dmabuf->buf->address;
- rmesa->dma.current.end = dmabuf->buf->total;
- rmesa->dma.current.start = 0;
- rmesa->dma.current.ptr = 0;
-
- rmesa->c_vertexBuffers++;
-}
-
-void radeonReleaseDmaRegion( radeonContextPtr rmesa,
- struct radeon_dma_region *region,
- const char *caller )
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
-
- if (!region->buf)
- return;
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
-
- if (--region->buf->refcount == 0) {
- drm_radeon_cmd_header_t *cmd;
-
- if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
- fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
- region->buf->buf->idx);
-
- cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sizeof(*cmd),
- __FUNCTION__ );
- cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
- cmd->dma.buf_idx = region->buf->buf->idx;
- FREE(region->buf);
- rmesa->dma.nr_released_bufs++;
- }
-
- region->buf = NULL;
- region->start = 0;
-}
-
-/* Allocates a region from rmesa->dma.current. If there isn't enough
- * space in current, grab a new buffer (and discard what was left of current)
- */
-void radeonAllocDmaRegion( radeonContextPtr rmesa,
- struct radeon_dma_region *region,
- int bytes,
- int alignment )
-{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
-
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
-
- if (region->buf)
- radeonReleaseDmaRegion( rmesa, region, __FUNCTION__ );
-
- alignment--;
- rmesa->dma.current.start = rmesa->dma.current.ptr =
- (rmesa->dma.current.ptr + alignment) & ~alignment;
-
- if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
- radeonRefillCurrentDmaRegion( rmesa );
-
- region->start = rmesa->dma.current.start;
- region->ptr = rmesa->dma.current.start;
- region->end = rmesa->dma.current.start + bytes;
- region->address = rmesa->dma.current.address;
- region->buf = rmesa->dma.current.buf;
- region->buf->refcount++;
-
- rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
- rmesa->dma.current.start =
- rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
-}
-
-/* ================================================================
- * SwapBuffers with client-side throttling
- */
-
-static uint32_t radeonGetLastFrame (radeonContextPtr rmesa)
-{
- drm_radeon_getparam_t gp;
- int ret;
- uint32_t frame;
-
- gp.param = RADEON_PARAM_LAST_FRAME;
- gp.value = (int *)&frame;
- ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
- &gp, sizeof(gp) );
-
- if ( ret ) {
- fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret );
- exit(1);
- }
-
- return frame;
-}
-
-static void radeonEmitIrqLocked( radeonContextPtr rmesa )
-{
- drm_radeon_irq_emit_t ie;
- int ret;
-
- ie.irq_seq = &rmesa->iw.irq_seq;
- ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_IRQ_EMIT,
- &ie, sizeof(ie) );
- if ( ret ) {
- fprintf( stderr, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__, ret );
- exit(1);
- }
-}
-
-
-static void radeonWaitIrq( radeonContextPtr rmesa )
-{
- int ret;
-
- do {
- ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT,
- &rmesa->iw, sizeof(rmesa->iw) );
- } while (ret && (errno == EINTR || errno == EBUSY));
-
- if ( ret ) {
- fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
- exit(1);
- }
-}
-
-
-static void radeonWaitForFrameCompletion( radeonContextPtr rmesa )
-{
- drm_radeon_sarea_t *sarea = rmesa->sarea;
-
- if (rmesa->do_irqs) {
- if (radeonGetLastFrame(rmesa) < sarea->last_frame) {
- if (!rmesa->irqsEmitted) {
- while (radeonGetLastFrame (rmesa) < sarea->last_frame)
- ;
- }
- else {
- UNLOCK_HARDWARE( rmesa );
- radeonWaitIrq( rmesa );
- LOCK_HARDWARE( rmesa );
- }
- rmesa->irqsEmitted = 10;
+ for (i = 0; i + 1 < nr; i += 2) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
+ (rmesa->radeon.tcl.aos[i].stride << 8) |
+ (rmesa->radeon.tcl.aos[i + 1].components << 16) |
+ (rmesa->radeon.tcl.aos[i + 1].stride << 24));
+
+ voffset = rmesa->radeon.tcl.aos[i + 0].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
+ OUT_BATCH(voffset);
+ voffset = rmesa->radeon.tcl.aos[i + 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
+ OUT_BATCH(voffset);
}
- if (rmesa->irqsEmitted) {
- radeonEmitIrqLocked( rmesa );
- rmesa->irqsEmitted--;
+ if (nr & 1) {
+ OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
+ (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
+ voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
+ OUT_BATCH(voffset);
}
- }
- else {
- while (radeonGetLastFrame (rmesa) < sarea->last_frame) {
- UNLOCK_HARDWARE( rmesa );
- if (rmesa->do_usleeps)
- DO_USLEEP( 1 );
- LOCK_HARDWARE( rmesa );
+ for (i = 0; i + 1 < nr; i += 2) {
+ voffset = rmesa->radeon.tcl.aos[i + 0].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.aos[i+0].bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
+ voffset = rmesa->radeon.tcl.aos[i + 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.aos[i+1].bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
}
- }
-}
-
-/* Copy the back color buffer to the front color buffer.
- */
-void radeonCopyBuffer( __DRIdrawablePrivate *dPriv,
- const drm_clip_rect_t *rect)
-{
- radeonContextPtr rmesa;
- GLint nbox, i, ret;
- GLboolean missed_target;
- int64_t ust;
- __DRIscreenPrivate *psp;
-
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
-
- rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
-
- if ( RADEON_DEBUG & DEBUG_IOCTL ) {
- fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, (void *) rmesa->glCtx );
- }
-
- RADEON_FIREVERTICES( rmesa );
- LOCK_HARDWARE( rmesa );
-
- /* Throttle the frame rate -- only allow one pending swap buffers
- * request at a time.
- */
- radeonWaitForFrameCompletion( rmesa );
- if (!rect)
- {
- UNLOCK_HARDWARE( rmesa );
- driWaitForVBlank( dPriv, & missed_target );
- LOCK_HARDWARE( rmesa );
- }
-
- nbox = dPriv->numClipRects; /* must be in locked region */
-
- for ( i = 0 ; i < nbox ; ) {
- GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox );
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t *b = rmesa->sarea->boxes;
- GLint n = 0;
-
- for ( ; i < nr ; i++ ) {
-
- *b = box[i];
-
- if (rect)
- {
- if (rect->x1 > b->x1)
- b->x1 = rect->x1;
- if (rect->y1 > b->y1)
- b->y1 = rect->y1;
- if (rect->x2 < b->x2)
- b->x2 = rect->x2;
- if (rect->y2 < b->y2)
- b->y2 = rect->y2;
-
- if (b->x1 >= b->x2 || b->y1 >= b->y2)
- continue;
- }
-
- b++;
- n++;
- }
- rmesa->sarea->nbox = n;
-
- if (!n)
- continue;
-
- ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP );
-
- if ( ret ) {
- fprintf( stderr, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret );
- UNLOCK_HARDWARE( rmesa );
- exit( 1 );
+ if (nr & 1) {
+ voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
+ offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
+ radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
+ rmesa->radeon.tcl.aos[nr-1].bo,
+ RADEON_GEM_DOMAIN_GTT,
+ 0, 0);
}
}
+ END_BATCH();
- UNLOCK_HARDWARE( rmesa );
- if (!rect)
- {
- psp = dPriv->driScreenPriv;
- rmesa->swap_count++;
- (*psp->systemTime->getUST)( & ust );
- if ( missed_target ) {
- rmesa->swap_missed_count++;
- rmesa->swap_missed_ust = ust - rmesa->swap_ust;
- }
-
- rmesa->swap_ust = ust;
- rmesa->hw.all_dirty = GL_TRUE;
- }
-}
-
-void radeonPageFlip( __DRIdrawablePrivate *dPriv )
-{
- radeonContextPtr rmesa;
- GLint ret;
- GLboolean missed_target;
- __DRIscreenPrivate *psp;
-
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
-
- rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
- psp = dPriv->driScreenPriv;
-
- if ( RADEON_DEBUG & DEBUG_IOCTL ) {
- fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__,
- rmesa->sarea->pfCurrentPage);
- }
-
- RADEON_FIREVERTICES( rmesa );
- LOCK_HARDWARE( rmesa );
-
- /* Need to do this for the perf box placement:
- */
- if (dPriv->numClipRects)
- {
- drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t *b = rmesa->sarea->boxes;
- b[0] = box[0];
- rmesa->sarea->nbox = 1;
- }
-
- /* Throttle the frame rate -- only allow a few pending swap buffers
- * request at a time.
- */
- radeonWaitForFrameCompletion( rmesa );
- UNLOCK_HARDWARE( rmesa );
- driWaitForVBlank( dPriv, & missed_target );
- if ( missed_target ) {
- rmesa->swap_missed_count++;
- (void) (*psp->systemTime->getUST)( & rmesa->swap_missed_ust );
- }
- LOCK_HARDWARE( rmesa );
-
- ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP );
-
- UNLOCK_HARDWARE( rmesa );
-
- if ( ret ) {
- fprintf( stderr, "DRM_RADEON_FLIP: return = %d\n", ret );
- exit( 1 );
- }
-
- rmesa->swap_count++;
- (void) (*psp->systemTime->getUST)( & rmesa->swap_ust );
-
- /* Get ready for drawing next frame. Update the renderbuffers'
- * flippedOffset/Pitch fields so we draw into the right place.
- */
- driFlipRenderbuffers(rmesa->glCtx->WinSysDrawBuffer,
- rmesa->sarea->pfCurrentPage);
-
- radeonUpdateDrawBuffer(rmesa->glCtx);
+#endif
}
-
/* ================================================================
* Buffer clear
*/
#define RADEON_MAX_CLEARS 256
-static void radeonClear( GLcontext *ctx, GLbitfield mask )
+static void radeonKernelClear(GLcontext *ctx, GLuint flags)
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
- drm_radeon_sarea_t *sarea = rmesa->sarea;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
+ drm_radeon_sarea_t *sarea = rmesa->radeon.sarea;
uint32_t clear;
- GLuint flags = 0;
- GLuint color_mask = 0;
GLint ret, i;
GLint cx, cy, cw, ch;
- if ( RADEON_DEBUG & DEBUG_IOCTL ) {
- fprintf( stderr, "radeonClear\n");
- }
-
- {
- LOCK_HARDWARE( rmesa );
- UNLOCK_HARDWARE( rmesa );
- if ( dPriv->numClipRects == 0 )
- return;
- }
-
- radeonFlush( ctx );
-
- if ( mask & BUFFER_BIT_FRONT_LEFT ) {
- flags |= RADEON_FRONT;
- color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~BUFFER_BIT_FRONT_LEFT;
- }
-
- if ( mask & BUFFER_BIT_BACK_LEFT ) {
- flags |= RADEON_BACK;
- color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- mask &= ~BUFFER_BIT_BACK_LEFT;
- }
-
- if ( mask & BUFFER_BIT_DEPTH ) {
- flags |= RADEON_DEPTH;
- mask &= ~BUFFER_BIT_DEPTH;
- }
-
- if ( (mask & BUFFER_BIT_STENCIL) && rmesa->state.stencil.hwBuffer ) {
- flags |= RADEON_STENCIL;
- mask &= ~BUFFER_BIT_STENCIL;
- }
-
- if ( mask ) {
- if (RADEON_DEBUG & DEBUG_FALLBACKS)
- fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
- _swrast_Clear( ctx, mask );
- }
-
- if ( !flags )
- return;
-
- if (rmesa->using_hyperz) {
- flags |= RADEON_USE_COMP_ZBUF;
-/* if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)
- flags |= RADEON_USE_HIERZ; */
- if (!(rmesa->state.stencil.hwBuffer) ||
- ((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
- ((rmesa->state.stencil.clear & RADEON_STENCIL_WRITE_MASK) == RADEON_STENCIL_WRITE_MASK))) {
- flags |= RADEON_CLEAR_FASTZ;
- }
- }
-
- LOCK_HARDWARE( rmesa );
+ LOCK_HARDWARE( &rmesa->radeon );
/* compute region after locking: */
cx = ctx->DrawBuffer->_Xmin;
@@ -1112,7 +475,7 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask )
gp.param = RADEON_PARAM_LAST_CLEAR;
gp.value = (int *)&clear;
- ret = drmCommandWriteRead( rmesa->dri.fd,
+ ret = drmCommandWriteRead( rmesa->radeon.dri.fd,
DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
if ( ret ) {
@@ -1124,20 +487,20 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask )
break;
}
- if ( rmesa->do_usleeps ) {
- UNLOCK_HARDWARE( rmesa );
+ if ( rmesa->radeon.do_usleeps ) {
+ UNLOCK_HARDWARE( &rmesa->radeon );
DO_USLEEP( 1 );
- LOCK_HARDWARE( rmesa );
+ LOCK_HARDWARE( &rmesa->radeon );
}
}
/* Send current state to the hardware */
- radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
+ rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
for ( i = 0 ; i < dPriv->numClipRects ; ) {
GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
drm_clip_rect_t *box = dPriv->pClipRects;
- drm_clip_rect_t *b = rmesa->sarea->boxes;
+ drm_clip_rect_t *b = rmesa->radeon.sarea->boxes;
drm_radeon_clear_t clear;
drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
GLint n = 0;
@@ -1172,105 +535,107 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask )
}
}
- rmesa->sarea->nbox = n;
+ rmesa->radeon.sarea->nbox = n;
clear.flags = flags;
- clear.clear_color = rmesa->state.color.clear;
- clear.clear_depth = rmesa->state.depth.clear;
+ clear.clear_color = rmesa->radeon.state.color.clear;
+ clear.clear_depth = rmesa->radeon.state.depth.clear;
clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
- clear.depth_mask = rmesa->state.stencil.clear;
+ clear.depth_mask = rmesa->radeon.state.stencil.clear;
clear.depth_boxes = depth_boxes;
n--;
- b = rmesa->sarea->boxes;
+ b = rmesa->radeon.sarea->boxes;
for ( ; n >= 0 ; n-- ) {
depth_boxes[n].f[CLEAR_X1] = (float)b[n].x1;
depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1;
depth_boxes[n].f[CLEAR_X2] = (float)b[n].x2;
depth_boxes[n].f[CLEAR_Y2] = (float)b[n].y2;
- depth_boxes[n].f[CLEAR_DEPTH] =
- (float)rmesa->state.depth.clear;
+ depth_boxes[n].f[CLEAR_DEPTH] =
+ (float)rmesa->radeon.state.depth.clear;
}
- ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR,
+ ret = drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_CLEAR,
&clear, sizeof(drm_radeon_clear_t));
if ( ret ) {
- UNLOCK_HARDWARE( rmesa );
+ UNLOCK_HARDWARE( &rmesa->radeon );
fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
exit( 1 );
}
}
-
- UNLOCK_HARDWARE( rmesa );
- rmesa->hw.all_dirty = GL_TRUE;
+ UNLOCK_HARDWARE( &rmesa->radeon );
}
-
-void radeonWaitForIdleLocked( radeonContextPtr rmesa )
+static void radeonClear( GLcontext *ctx, GLbitfield mask )
{
- int fd = rmesa->dri.fd;
- int to = 0;
- int ret, i = 0;
-
- rmesa->c_drawWaits++;
-
- do {
- do {
- ret = drmCommandNone( fd, DRM_RADEON_CP_IDLE);
- } while ( ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY );
- } while ( ( ret == -EBUSY ) && ( to++ < RADEON_TIMEOUT ) );
-
- if ( ret < 0 ) {
- UNLOCK_HARDWARE( rmesa );
- fprintf( stderr, "Error: Radeon timed out... exiting\n" );
- exit( -1 );
- }
-}
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
+ GLuint flags = 0;
+ GLuint color_mask = 0;
+ GLuint orig_mask = mask;
+ if ( RADEON_DEBUG & RADEON_IOCTL ) {
+ fprintf( stderr, "radeonClear\n");
+ }
-static void radeonWaitForIdle( radeonContextPtr rmesa )
-{
- LOCK_HARDWARE(rmesa);
- radeonWaitForIdleLocked( rmesa );
- UNLOCK_HARDWARE(rmesa);
-}
+ {
+ LOCK_HARDWARE( &rmesa->radeon );
+ UNLOCK_HARDWARE( &rmesa->radeon );
+ if ( dPriv->numClipRects == 0 )
+ return;
+ }
+ radeon_firevertices(&rmesa->radeon);
-void radeonFlush( GLcontext *ctx )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ if ( mask & BUFFER_BIT_FRONT_LEFT ) {
+ flags |= RADEON_FRONT;
+ color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+ mask &= ~BUFFER_BIT_FRONT_LEFT;
+ }
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ if ( mask & BUFFER_BIT_BACK_LEFT ) {
+ flags |= RADEON_BACK;
+ color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+ mask &= ~BUFFER_BIT_BACK_LEFT;
+ }
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
+ if ( mask & BUFFER_BIT_DEPTH ) {
+ flags |= RADEON_DEPTH;
+ mask &= ~BUFFER_BIT_DEPTH;
+ }
- radeonEmitState( rmesa );
-
- if (rmesa->store.cmd_used)
- radeonFlushCmdBuf( rmesa, __FUNCTION__ );
-}
+ if ( (mask & BUFFER_BIT_STENCIL) ) {
+ flags |= RADEON_STENCIL;
+ mask &= ~BUFFER_BIT_STENCIL;
+ }
-/* Make sure all commands have been sent to the hardware and have
- * completed processing.
- */
-void radeonFinish( GLcontext *ctx )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- radeonFlush( ctx );
-
- if (rmesa->do_irqs) {
- LOCK_HARDWARE( rmesa );
- radeonEmitIrqLocked( rmesa );
- UNLOCK_HARDWARE( rmesa );
- radeonWaitIrq( rmesa );
+ if ( mask ) {
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
+ fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
+ _swrast_Clear( ctx, mask );
}
- else
- radeonWaitForIdle( rmesa );
-}
+ if ( !flags )
+ return;
+
+ if (rmesa->using_hyperz) {
+ flags |= RADEON_USE_COMP_ZBUF;
+/* if (rmesa->radeon.radeonScreen->chipset & RADEON_CHIPSET_TCL)
+ flags |= RADEON_USE_HIERZ; */
+ if (((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
+ ((rmesa->radeon.state.stencil.clear & RADEON_STENCIL_WRITE_MASK) == RADEON_STENCIL_WRITE_MASK))) {
+ flags |= RADEON_CLEAR_FASTZ;
+ }
+ }
+
+ if (rmesa->radeon.radeonScreen->kernel_mm)
+ radeonUserClear(ctx, orig_mask);
+ else {
+ radeonKernelClear(ctx, flags);
+ rmesa->radeon.hw.all_dirty = GL_TRUE;
+ }
+}
void radeonInitIoctlFuncs( GLcontext *ctx )
{
diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.h b/src/mesa/drivers/dri/radeon/radeon_ioctl.h
index 4e3a44df07..deb53ae313 100644
--- a/src/mesa/drivers/dri/radeon/radeon_ioctl.h
+++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.h
@@ -38,31 +38,32 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/simple_list.h"
#include "radeon_lock.h"
+#include "radeon_bocs_wrapper.h"
-
-extern void radeonEmitState( radeonContextPtr rmesa );
-extern void radeonEmitVertexAOS( radeonContextPtr rmesa,
+extern void radeonEmitVertexAOS( r100ContextPtr rmesa,
GLuint vertex_size,
+ struct radeon_bo *bo,
GLuint offset );
-extern void radeonEmitVbufPrim( radeonContextPtr rmesa,
+extern void radeonEmitVbufPrim( r100ContextPtr rmesa,
GLuint vertex_format,
GLuint primitive,
GLuint vertex_nr );
-extern void radeonFlushElts( radeonContextPtr rmesa );
+extern void radeonFlushElts( GLcontext *ctx );
+
-extern GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa,
+extern GLushort *radeonAllocEltsOpenEnded( r100ContextPtr rmesa,
GLuint vertex_format,
GLuint primitive,
GLuint min_nr );
-extern void radeonEmitAOS( radeonContextPtr rmesa,
- struct radeon_dma_region **regions,
+
+extern void radeonEmitAOS( r100ContextPtr rmesa,
GLuint n,
GLuint offset );
-extern void radeonEmitBlit( radeonContextPtr rmesa,
+extern void radeonEmitBlit( r100ContextPtr rmesa,
GLuint color_fmt,
GLuint src_pitch,
GLuint src_offset,
@@ -72,30 +73,15 @@ extern void radeonEmitBlit( radeonContextPtr rmesa,
GLint dstx, GLint dsty,
GLuint w, GLuint h );
-extern void radeonEmitWait( radeonContextPtr rmesa, GLuint flags );
-
-extern void radeonFlushCmdBuf( radeonContextPtr rmesa, const char * );
-extern void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa );
+extern void radeonEmitWait( r100ContextPtr rmesa, GLuint flags );
-extern void radeonAllocDmaRegion( radeonContextPtr rmesa,
- struct radeon_dma_region *region,
- int bytes,
- int alignment );
+extern void radeonFlushCmdBuf( r100ContextPtr rmesa, const char * );
-extern void radeonReleaseDmaRegion( radeonContextPtr rmesa,
- struct radeon_dma_region *region,
- const char *caller );
-
-extern void radeonCopyBuffer( __DRIdrawablePrivate *drawable,
- const drm_clip_rect_t *rect);
-extern void radeonPageFlip( __DRIdrawablePrivate *drawable );
extern void radeonFlush( GLcontext *ctx );
extern void radeonFinish( GLcontext *ctx );
-extern void radeonWaitForIdleLocked( radeonContextPtr rmesa );
-extern void radeonWaitForVBlank( radeonContextPtr rmesa );
extern void radeonInitIoctlFuncs( GLcontext *ctx );
-extern void radeonGetAllParams( radeonContextPtr rmesa );
-extern void radeonSetUpAtomList( radeonContextPtr rmesa );
+extern void radeonGetAllParams( r100ContextPtr rmesa );
+extern void radeonSetUpAtomList( r100ContextPtr rmesa );
/* ================================================================
* Helper macros:
@@ -105,33 +91,33 @@ extern void radeonSetUpAtomList( radeonContextPtr rmesa );
*/
#define RADEON_NEWPRIM( rmesa ) \
do { \
- if ( rmesa->dma.flush ) \
- rmesa->dma.flush( rmesa ); \
+ if ( rmesa->radeon.dma.flush ) \
+ rmesa->radeon.dma.flush( rmesa->radeon.glCtx ); \
} while (0)
/* Can accomodate several state changes and primitive changes without
* actually firing the buffer.
*/
+
#define RADEON_STATECHANGE( rmesa, ATOM ) \
do { \
RADEON_NEWPRIM( rmesa ); \
rmesa->hw.ATOM.dirty = GL_TRUE; \
- rmesa->hw.is_dirty = GL_TRUE; \
+ rmesa->radeon.hw.is_dirty = GL_TRUE; \
} while (0)
-#define RADEON_DB_STATE( ATOM ) \
+#define RADEON_DB_STATE( ATOM ) \
memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \
rmesa->hw.ATOM.cmd_size * 4)
-static INLINE int RADEON_DB_STATECHANGE(
- radeonContextPtr rmesa,
- struct radeon_state_atom *atom )
+static INLINE int RADEON_DB_STATECHANGE(r100ContextPtr rmesa,
+ struct radeon_state_atom *atom )
{
if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) {
- int *tmp;
+ GLuint *tmp;
RADEON_NEWPRIM( rmesa );
atom->dirty = GL_TRUE;
- rmesa->hw.is_dirty = GL_TRUE;
+ rmesa->radeon.hw.is_dirty = GL_TRUE;
tmp = atom->cmd;
atom->cmd = atom->lastcmd;
atom->lastcmd = tmp;
@@ -141,62 +127,55 @@ static INLINE int RADEON_DB_STATECHANGE(
return 0;
}
-
-/* Fire the buffered vertices no matter what.
- */
-#define RADEON_FIREVERTICES( rmesa ) \
-do { \
- if ( rmesa->store.cmd_used || rmesa->dma.flush ) { \
- radeonFlush( rmesa->glCtx ); \
- } \
-} while (0)
-
/* Command lengths. Note that any time you ensure ELTS_BUFSZ or VBUF_BUFSZ
* are available, you will also be adding an rmesa->state.max_state_size because
* r200EmitState is called from within r200EmitVbufPrim and r200FlushElts.
*/
#if RADEON_OLD_PACKETS
-#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2)) * sizeof(int))
+#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2))+nr*2)
#define VERT_AOS_BUFSZ (0)
#define ELTS_BUFSZ(nr) (24 + nr * 2)
-#define VBUF_BUFSZ (6 * sizeof(int))
+#define VBUF_BUFSZ (8)
#else
-#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2)) * sizeof(int))
-#define VERT_AOS_BUFSZ (5 * sizeof(int))
+#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2) + nr*2))
+#define VERT_AOS_BUFSZ (5)
#define ELTS_BUFSZ(nr) (16 + nr * 2)
-#define VBUF_BUFSZ (4 * sizeof(int))
+#define VBUF_BUFSZ (4)
#endif
+#define SCISSOR_BUFSZ (8)
+#define INDEX_BUFSZ (7)
-/* Ensure that a minimum amount of space is available in the command buffer.
- * This is used to ensure atomicity of state updates with the rendering requests
- * that rely on them.
- *
- * An alternative would be to implement a "soft lock" such that when the buffer
- * wraps at an inopportune time, we grab the lock, flush the current buffer,
- * and hang on to the lock until the critical section is finished and we flush
- * the buffer again and unlock.
- */
-static INLINE void radeonEnsureCmdBufSpace( radeonContextPtr rmesa,
- int bytes )
-{
- if (rmesa->store.cmd_used + bytes > RADEON_CMD_BUF_SZ)
- radeonFlushCmdBuf( rmesa, __FUNCTION__ );
- assert( bytes <= RADEON_CMD_BUF_SZ );
-}
-/* Alloc space in the command buffer
- */
-static INLINE char *radeonAllocCmdBuf( radeonContextPtr rmesa,
- int bytes, const char *where )
+static inline uint32_t cmdpacket3(int cmd_type)
{
- if (rmesa->store.cmd_used + bytes > RADEON_CMD_BUF_SZ)
- radeonFlushCmdBuf( rmesa, __FUNCTION__ );
+ drm_radeon_cmd_header_t cmd;
+
+ cmd.i = 0;
+ cmd.header.cmd_type = cmd_type;
+
+ return (uint32_t)cmd.i;
- {
- char *head = rmesa->store.cmd_buf + rmesa->store.cmd_used;
- rmesa->store.cmd_used += bytes;
- return head;
- }
}
+#define OUT_BATCH_PACKET3(packet, num_extra) do { \
+ if (!b_l_rmesa->radeonScreen->kernel_mm) { \
+ OUT_BATCH(cmdpacket3(RADEON_CMD_PACKET3)); \
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
+ } else { \
+ OUT_BATCH(CP_PACKET2); \
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
+ } \
+ } while(0)
+
+#define OUT_BATCH_PACKET3_CLIP(packet, num_extra) do { \
+ if (!b_l_rmesa->radeonScreen->kernel_mm) { \
+ OUT_BATCH(cmdpacket3(RADEON_CMD_PACKET3_CLIP)); \
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
+ } else { \
+ OUT_BATCH(CP_PACKET2); \
+ OUT_BATCH(CP_PACKET3((packet), (num_extra))); \
+ } \
+ } while(0)
+
+
#endif /* __RADEON_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_lighting.c b/src/mesa/drivers/dri/radeon/radeon_lighting.c
index 6d9ccfa24d..ba444f2b10 100644
--- a/src/mesa/drivers/dri/radeon/radeon_lighting.c
+++ b/src/mesa/drivers/dri/radeon/radeon_lighting.c
@@ -195,7 +195,7 @@ void radeonUpdateMaterial( GLcontext *ctx )
if (ctx->Light.ColorMaterialEnabled)
mask &= ~ctx->Light.ColorMaterialBitmask;
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr, "%s\n", __FUNCTION__);
@@ -234,7 +234,7 @@ void radeonUpdateMaterial( GLcontext *ctx )
check_twoside_fallback( ctx );
update_global_ambient( ctx );
}
- else if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_STATE))
+ else if (RADEON_DEBUG & (RADEON_PRIMS|DEBUG_STATE))
fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);
}
@@ -246,7 +246,7 @@ void radeonUpdateMaterial( GLcontext *ctx )
* _VP_inf_norm
* _h_inf_norm
* _Position
- * _NormDirection
+ * _NormSpotDirection
* _ModelViewInvScale
* _NeedEyeCoords
* _EyeZDir
@@ -308,9 +308,9 @@ void radeonUpdateLighting( GLcontext *ctx )
fcmd[LIT_DIRECTION_W] = 0;
} else {
COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
- fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
- fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
- fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
+ fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0];
+ fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1];
+ fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2];
fcmd[LIT_DIRECTION_W] = 0;
}
@@ -624,7 +624,7 @@ static void radeonLightingSpaceChange( GLcontext *ctx )
GLboolean tmp;
RADEON_STATECHANGE( rmesa, tcl );
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr, "%s %d\n", __FUNCTION__, ctx->_NeedEyeCoords);
if (ctx->_NeedEyeCoords)
diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.c b/src/mesa/drivers/dri/radeon/radeon_lock.c
index 64bb3ca103..02de8e5fd1 100644
--- a/src/mesa/drivers/dri/radeon/radeon_lock.c
+++ b/src/mesa/drivers/dri/radeon/radeon_lock.c
@@ -41,30 +41,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/glheader.h"
#include "main/mtypes.h"
-#include "radeon_context.h"
+#include "main/colormac.h"
+#include "dri_util.h"
+#include "radeon_screen.h"
+#include "radeon_common.h"
#include "radeon_lock.h"
-#include "radeon_tex.h"
-#include "radeon_state.h"
-#include "radeon_ioctl.h"
-
#include "drirenderbuffer.h"
-#if DEBUG_LOCKING
-char *prevLockFile = NULL;
-int prevLockLine = 0;
-#endif
-
-/* Turn on/off page flipping according to the flags in the sarea:
- */
-static void radeonUpdatePageFlipping(radeonContextPtr rmesa)
-{
- rmesa->doPageFlip = rmesa->sarea->pfState;
- if (rmesa->glCtx->WinSysDrawBuffer) {
- driFlipRenderbuffers(rmesa->glCtx->WinSysDrawBuffer,
- rmesa->sarea->pfCurrentPage);
- }
-}
-
/* Update the hardware state. This is called if another context has
* grabbed the hardware lock, which includes the X server. This
* function also updates the driver's window state after the X server
@@ -75,10 +58,11 @@ static void radeonUpdatePageFlipping(radeonContextPtr rmesa)
*/
void radeonGetLock(radeonContextPtr rmesa, GLuint flags)
{
- __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
- __DRIdrawablePrivate *const readable = rmesa->dri.readable;
+ __DRIdrawablePrivate *const drawable = radeon_get_drawable(rmesa);
+ __DRIdrawablePrivate *const readable = radeon_get_readable(rmesa);
__DRIscreenPrivate *sPriv = rmesa->dri.screen;
- drm_radeon_sarea_t *sarea = rmesa->sarea;
+
+ assert(drawable != NULL);
drmGetLock(rmesa->dri.fd, rmesa->dri.hwContext, flags);
@@ -96,29 +80,89 @@ void radeonGetLock(radeonContextPtr rmesa, GLuint flags)
}
if (rmesa->lastStamp != drawable->lastStamp) {
- radeonUpdatePageFlipping(rmesa);
- radeonSetCliprects(rmesa);
- radeonUpdateViewportOffset(rmesa->glCtx);
- driUpdateFramebufferSize(rmesa->glCtx, drawable);
+ radeon_window_moved(rmesa);
+ rmesa->lastStamp = drawable->lastStamp;
}
- RADEON_STATECHANGE(rmesa, ctx);
- if (rmesa->sarea->tiling_enabled) {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |=
- RADEON_COLOR_TILE_ENABLE;
- } else {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &=
- ~RADEON_COLOR_TILE_ENABLE;
- }
+ rmesa->vtbl.get_lock(rmesa);
+}
+#ifndef NDEBUG
+struct lock_debug {
+ const char* function;
+ const char* file;
+ int line;
+};
+
+static struct lock_debug ldebug = {0};
+#endif
+
+#if 0
+/** TODO: use atomic operations for reference counting **/
+/** gcc 4.2 has builtin functios for this **/
+#define ATOMIC_INC_AND_FETCH(atomic) __sync_add_and_fetch(&atomic, 1)
+#define ATOMIC_DEC_AND_FETCH(atomic) __sync_sub_and_fetch(&atomic, 1)
+#else
+#define ATOMIC_INC_AND_FETCH(atomic) (++atomic)
+#define ATOMIC_DEC_AND_FETCH(atomic) (--atomic)
+#endif
+
- if (sarea->ctx_owner != rmesa->dri.hwContext) {
- int i;
- sarea->ctx_owner = rmesa->dri.hwContext;
+void radeon_lock_hardware(radeonContextPtr radeon
+#ifndef NDEBUG
+ ,const char* function
+ ,const char* file
+ ,const int line
+#endif
+ )
+{
+ char ret = 0;
+ struct radeon_framebuffer *rfb = NULL;
+ struct radeon_renderbuffer *rrb = NULL;
+
+ if (radeon_get_drawable(radeon)) {
+ rfb = radeon_get_drawable(radeon)->driverPrivate;
+
+ if (rfb)
+ rrb = radeon_get_renderbuffer(&rfb->base,
+ rfb->base._ColorDrawBufferIndexes[0]);
+ }
- for (i = 0; i < rmesa->nr_heaps; i++) {
- DRI_AGE_TEXTURES(rmesa->texture_heaps[i]);
+ if (!radeon->radeonScreen->driScreen->dri2.enabled) {
+ if (ATOMIC_INC_AND_FETCH(radeon->dri.hwLockCount) > 1)
+ {
+#ifndef NDEBUG
+ if ( RADEON_DEBUG & RADEON_SANITY )
+ fprintf(stderr, "*** %d times of recursive call to %s ***\n"
+ "Original call was from %s (file: %s line: %d)\n"
+ "Now call is coming from %s (file: %s line: %d)\n"
+ , radeon->dri.hwLockCount, __FUNCTION__
+ , ldebug.function, ldebug.file, ldebug.line
+ , function, file, line
+ );
+#endif
+ return;
}
+ DRM_CAS(radeon->dri.hwLock, radeon->dri.hwContext,
+ (DRM_LOCK_HELD | radeon->dri.hwContext), ret );
+ if (ret)
+ radeonGetLock(radeon, 0);
+#ifndef NDEBUG
+ ldebug.function = function;
+ ldebug.file = file;
+ ldebug.line = line;
+#endif
}
+}
- rmesa->lost_context = GL_TRUE;
+void radeon_unlock_hardware(radeonContextPtr radeon)
+{
+ if (!radeon->radeonScreen->driScreen->dri2.enabled) {
+ if (ATOMIC_DEC_AND_FETCH(radeon->dri.hwLockCount) > 0)
+ {
+ return;
+ }
+ DRM_UNLOCK( radeon->dri.fd,
+ radeon->dri.hwLock,
+ radeon->dri.hwContext );
+ }
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.h b/src/mesa/drivers/dri/radeon/radeon_lock.h
index 86e96aa7d2..da5a5b4371 100644
--- a/src/mesa/drivers/dri/radeon/radeon_lock.h
+++ b/src/mesa/drivers/dri/radeon/radeon_lock.h
@@ -39,74 +39,31 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* Kevin E. Martin <martin@valinux.com>
*/
-#ifndef __RADEON_LOCK_H__
-#define __RADEON_LOCK_H__
+#ifndef COMMON_LOCK_H
+#define COMMON_LOCK_H
-extern void radeonGetLock(radeonContextPtr rmesa, GLuint flags);
-
-/* Turn DEBUG_LOCKING on to find locking conflicts.
- */
-#define DEBUG_LOCKING 0
-
-#if DEBUG_LOCKING
-extern char *prevLockFile;
-extern int prevLockLine;
-
-#define DEBUG_LOCK() \
- do { \
- prevLockFile = (__FILE__); \
- prevLockLine = (__LINE__); \
- } while (0)
-
-#define DEBUG_RESET() \
- do { \
- prevLockFile = 0; \
- prevLockLine = 0; \
- } while (0)
-
-#define DEBUG_CHECK_LOCK() \
- do { \
- if ( prevLockFile ) { \
- fprintf( stderr, \
- "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
- prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
- exit( 1 ); \
- } \
- } while (0)
-
-#else
+#include "main/colormac.h"
+#include "radeon_screen.h"
+#include "radeon_common.h"
-#define DEBUG_LOCK()
-#define DEBUG_RESET()
-#define DEBUG_CHECK_LOCK()
+extern void radeonGetLock(radeonContextPtr rmesa, GLuint flags);
+void radeon_lock_hardware(radeonContextPtr rmesa
+#ifndef NDEBUG
+ ,const char* function
+ ,const char* file
+ ,const int line
#endif
-
-/*
- * !!! We may want to separate locks from locks with validation. This
- * could be used to improve performance for those things commands that
- * do not do any drawing !!!
- */
+ );
+void radeon_unlock_hardware(radeonContextPtr rmesa);
/* Lock the hardware and validate our state.
*/
-#define LOCK_HARDWARE( rmesa ) \
- do { \
- char __ret = 0; \
- DEBUG_CHECK_LOCK(); \
- DRM_CAS( (rmesa)->dri.hwLock, (rmesa)->dri.hwContext, \
- (DRM_LOCK_HELD | (rmesa)->dri.hwContext), __ret ); \
- if ( __ret ) \
- radeonGetLock( (rmesa), 0 ); \
- DEBUG_LOCK(); \
- } while (0)
-
-#define UNLOCK_HARDWARE( rmesa ) \
- do { \
- DRM_UNLOCK( (rmesa)->dri.fd, \
- (rmesa)->dri.hwLock, \
- (rmesa)->dri.hwContext ); \
- DEBUG_RESET(); \
- } while (0)
+#ifdef NDEBUG
+#define LOCK_HARDWARE( rmesa ) radeon_lock_hardware(rmesa)
+#else
+#define LOCK_HARDWARE( rmesa ) radeon_lock_hardware(rmesa, __FUNCTION__, __FILE__, __LINE__)
+#endif
+#define UNLOCK_HARDWARE( rmesa ) radeon_unlock_hardware(rmesa)
-#endif /* __RADEON_LOCK_H__ */
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos.h b/src/mesa/drivers/dri/radeon/radeon_maos.h
index b8935e84a0..b88eb198d5 100644
--- a/src/mesa/drivers/dri/radeon/radeon_maos.h
+++ b/src/mesa/drivers/dri/radeon/radeon_maos.h
@@ -38,6 +38,5 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_context.h"
extern void radeonEmitArrays( GLcontext *ctx, GLuint inputs );
-extern void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs );
#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c b/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c
index de3c3a15a7..08e1c5d00d 100644
--- a/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c
@@ -40,7 +40,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "swrast_setup/swrast_setup.h"
#include "math/m_translate.h"
#include "tnl/tnl.h"
-#include "tnl/tcontext.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
@@ -49,160 +48,35 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_maos.h"
#include "radeon_tcl.h"
-#if 0
-/* Usage:
- * - from radeon_tcl_render
- * - call radeonEmitArrays to ensure uptodate arrays in dma
- * - emit primitives (new type?) which reference the data
- * -- need to use elts for lineloop, quads, quadstrip/flat
- * -- other primitives are all well-formed (need tristrip-1,fake-poly)
- *
- */
-static void emit_ubyte_rgba3( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- radeon_color_t *out = (radeon_color_t *)(rvb->start + rvb->address);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d out %p\n",
- __FUNCTION__, count, stride, (void *)out);
-
- for (i = 0; i < count; i++) {
- out->red = *data;
- out->green = *(data+1);
- out->blue = *(data+2);
- out->alpha = 0xFF;
- out++;
- data += stride;
- }
-}
-
-static void emit_ubyte_rgba4( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
+static void emit_vecfog(GLcontext *ctx, struct radeon_aos *aos,
+ GLvoid *data, int stride, int count)
{
int i;
- int *out = (int *)(rvb->address + rvb->start);
+ uint32_t *out;
+ int size = 1;
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- if (RADEON_DEBUG & DEBUG_VERTS)
+ if (RADEON_DEBUG & RADEON_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
- if (stride == 4)
- COPY_DWORDS( out, data, count );
- else
- for (i = 0; i < count; i++) {
- *out++ = LE32_TO_CPU(*(int *)data);
- data += stride;
- }
-}
-
-
-static void emit_ubyte_rgba( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int size,
- int stride,
- int count )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
-
- assert (!rvb->buf);
-
if (stride == 0) {
- radeonAllocDmaRegion( rmesa, rvb, 4, 4 );
+ radeonAllocDmaRegion( rmesa, &aos->bo, &aos->offset, size * 4, 32 );
count = 1;
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 0;
- rvb->aos_size = 1;
+ aos->stride = 0;
}
else {
- radeonAllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 1;
- rvb->aos_size = 1;
- }
-
- /* Emit the data
- */
- switch (size) {
- case 3:
- emit_ubyte_rgba3( ctx, rvb, data, stride, count );
- break;
- case 4:
- emit_ubyte_rgba4( ctx, rvb, data, stride, count );
- break;
- default:
- assert(0);
- exit(1);
- break;
+ radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * 4, 32);
+ aos->stride = size;
}
-}
-#endif
-
-#if defined(USE_X86_ASM)
-#define COPY_DWORDS( dst, src, nr ) \
-do { \
- int __tmp; \
- __asm__ __volatile__( "rep ; movsl" \
- : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
- : "0" (nr), \
- "D" ((long)dst), \
- "S" ((long)src) ); \
-} while (0)
-#else
-#define COPY_DWORDS( dst, src, nr ) \
-do { \
- int j; \
- for ( j = 0 ; j < nr ; j++ ) \
- dst[j] = ((int *)src)[j]; \
- dst += nr; \
-} while (0)
-#endif
-
-static void emit_vecfog( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- GLfloat *out;
-
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
+ aos->components = size;
+ aos->count = count;
- assert (!rvb->buf);
-
- if (stride == 0) {
- radeonAllocDmaRegion( rmesa, rvb, 4, 4 );
- count = 1;
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 0;
- rvb->aos_size = 1;
- }
- else {
- radeonAllocDmaRegion( rmesa, rvb, count * 4, 4 ); /* alignment? */
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 1;
- rvb->aos_size = 1;
- }
/* Emit the data
*/
- out = (GLfloat *)(rvb->address + rvb->start);
+ out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
for (i = 0; i < count; i++) {
out[0] = radeonComputeFogBlendFactor( ctx, *(GLfloat *)data );
out++;
@@ -210,170 +84,10 @@ static void emit_vecfog( GLcontext *ctx,
}
}
-static void emit_vec4( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
-
- if (stride == 4)
- COPY_DWORDS( out, data, count );
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out++;
- data += stride;
- }
-}
-
-
-static void emit_vec8( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
-
- if (stride == 8)
- COPY_DWORDS( out, data, count*2 );
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out[1] = *(int *)(data+4);
- out += 2;
- data += stride;
- }
-}
-
-static void emit_vec12( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d out %p data %p\n",
- __FUNCTION__, count, stride, (void *)out, (void *)data);
-
- if (stride == 12)
- COPY_DWORDS( out, data, count*3 );
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out[1] = *(int *)(data+4);
- out[2] = *(int *)(data+8);
- out += 3;
- data += stride;
- }
-}
-
-static void emit_vec16( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
-
- if (stride == 16)
- COPY_DWORDS( out, data, count*4 );
- else
- for (i = 0; i < count; i++) {
- out[0] = *(int *)data;
- out[1] = *(int *)(data+4);
- out[2] = *(int *)(data+8);
- out[3] = *(int *)(data+12);
- out += 4;
- data += stride;
- }
-}
-
-
-static void emit_vector( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int size,
- int stride,
- int count )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d size %d stride %d\n",
- __FUNCTION__, count, size, stride);
-
- assert (!rvb->buf);
-
- if (stride == 0) {
- radeonAllocDmaRegion( rmesa, rvb, size * 4, 4 );
- count = 1;
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 0;
- rvb->aos_size = size;
- }
- else {
- radeonAllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = size;
- rvb->aos_size = size;
- }
-
- /* Emit the data
- */
- switch (size) {
- case 1:
- emit_vec4( ctx, rvb, data, stride, count );
- break;
- case 2:
- emit_vec8( ctx, rvb, data, stride, count );
- break;
- case 3:
- emit_vec12( ctx, rvb, data, stride, count );
- break;
- case 4:
- emit_vec16( ctx, rvb, data, stride, count );
- break;
- default:
- assert(0);
- exit(1);
- break;
- }
-
-}
-
-
-
-static void emit_s0_vec( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
+static void emit_s0_vec(uint32_t *out, GLvoid *data, int stride, int count)
{
int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (RADEON_DEBUG & DEBUG_VERTS)
+ if (RADEON_DEBUG & RADEON_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
@@ -385,16 +99,11 @@ static void emit_s0_vec( GLcontext *ctx,
}
}
-static void emit_stq_vec( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
+static void emit_stq_vec(uint32_t *out, GLvoid *data, int stride, int count)
{
int i;
- int *out = (int *)(rvb->address + rvb->start);
- if (RADEON_DEBUG & DEBUG_VERTS)
+ if (RADEON_DEBUG & RADEON_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
@@ -410,21 +119,16 @@ static void emit_stq_vec( GLcontext *ctx,
-static void emit_tex_vector( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int size,
- int stride,
- int count )
+static void emit_tex_vector(GLcontext *ctx, struct radeon_aos *aos,
+ GLvoid *data, int size, int stride, int count)
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
int emitsize;
+ uint32_t *out;
- if (RADEON_DEBUG & DEBUG_VERTS)
+ if (RADEON_DEBUG & RADEON_VERTS)
fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
- assert (!rvb->buf);
-
switch (size) {
case 4: emitsize = 3; break;
case 3: emitsize = 3; break;
@@ -433,34 +137,33 @@ static void emit_tex_vector( GLcontext *ctx,
if (stride == 0) {
- radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize, 4 );
+ radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * 4, 32);
count = 1;
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 0;
- rvb->aos_size = emitsize;
+ aos->stride = 0;
}
else {
- radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize * count, 4 );
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = emitsize;
- rvb->aos_size = emitsize;
+ radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * count * 4, 32);
+ aos->stride = emitsize;
}
+ aos->components = emitsize;
+ aos->count = count;
/* Emit the data
*/
+ out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
switch (size) {
case 1:
- emit_s0_vec( ctx, rvb, data, stride, count );
+ emit_s0_vec( out, data, stride, count );
break;
case 2:
- emit_vec8( ctx, rvb, data, stride, count );
+ radeonEmitVec8( out, data, stride, count );
break;
case 3:
- emit_vec12( ctx, rvb, data, stride, count );
+ radeonEmitVec12( out, data, stride, count );
break;
case 4:
- emit_stq_vec( ctx, rvb, data, stride, count );
+ emit_stq_vec( out, data, stride, count );
break;
default:
assert(0);
@@ -477,27 +180,26 @@ static void emit_tex_vector( GLcontext *ctx,
*/
void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
{
- radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ r100ContextPtr rmesa = R100_CONTEXT( ctx );
struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
- struct radeon_dma_region **component = rmesa->tcl.aos_components;
GLuint nr = 0;
GLuint vfmt = 0;
GLuint count = VB->Count;
GLuint vtx, unit;
#if 0
- if (RADEON_DEBUG & DEBUG_VERTS)
+ if (RADEON_DEBUG & RADEON_VERTS)
_tnl_print_vert_flags( __FUNCTION__, inputs );
#endif
if (1) {
if (!rmesa->tcl.obj.buf)
- emit_vector( ctx,
- &rmesa->tcl.obj,
- (char *)VB->ObjPtr->data,
- VB->ObjPtr->size,
- VB->ObjPtr->stride,
- count);
+ rcommon_emit_vector( ctx,
+ &(rmesa->tcl.aos[nr]),
+ (char *)VB->ObjPtr->data,
+ VB->ObjPtr->size,
+ VB->ObjPtr->stride,
+ count);
switch( VB->ObjPtr->size ) {
case 4: vfmt |= RADEON_CP_VC_FRMT_W0;
@@ -506,21 +208,21 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
default:
break;
}
- component[nr++] = &rmesa->tcl.obj;
+ nr++;
}
if (inputs & VERT_BIT_NORMAL) {
if (!rmesa->tcl.norm.buf)
- emit_vector( ctx,
- &(rmesa->tcl.norm),
- (char *)VB->NormalPtr->data,
- 3,
- VB->NormalPtr->stride,
- count);
+ rcommon_emit_vector( ctx,
+ &(rmesa->tcl.aos[nr]),
+ (char *)VB->NormalPtr->data,
+ 3,
+ VB->NormalPtr->stride,
+ count);
vfmt |= RADEON_CP_VC_FRMT_N0;
- component[nr++] = &rmesa->tcl.norm;
+ nr++;
}
if (inputs & VERT_BIT_COLOR0) {
@@ -538,31 +240,30 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
}
if (!rmesa->tcl.rgba.buf)
- emit_vector( ctx,
- &(rmesa->tcl.rgba),
- (char *)VB->ColorPtr[0]->data,
- emitsize,
- VB->ColorPtr[0]->stride,
- count);
-
-
- component[nr++] = &rmesa->tcl.rgba;
+ rcommon_emit_vector( ctx,
+ &(rmesa->tcl.aos[nr]),
+ (char *)VB->ColorPtr[0]->data,
+ emitsize,
+ VB->ColorPtr[0]->stride,
+ count);
+
+ nr++;
}
if (inputs & VERT_BIT_COLOR1) {
if (!rmesa->tcl.spec.buf) {
- emit_vector( ctx,
- &rmesa->tcl.spec,
- (char *)VB->SecondaryColorPtr[0]->data,
- 3,
- VB->SecondaryColorPtr[0]->stride,
- count);
+ rcommon_emit_vector( ctx,
+ &(rmesa->tcl.aos[nr]),
+ (char *)VB->SecondaryColorPtr[0]->data,
+ 3,
+ VB->SecondaryColorPtr[0]->stride,
+ count);
}
vfmt |= RADEON_CP_VC_FRMT_FPSPEC;
- component[nr++] = &rmesa->tcl.spec;
+ nr++;
}
/* FIXME: not sure if this is correct. May need to stitch this together with
@@ -571,13 +272,13 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
if (inputs & VERT_BIT_FOG) {
if (!rmesa->tcl.fog.buf)
emit_vecfog( ctx,
- &(rmesa->tcl.fog),
+ &(rmesa->tcl.aos[nr]),
(char *)VB->FogCoordPtr->data,
VB->FogCoordPtr->stride,
count);
vfmt |= RADEON_CP_VC_FRMT_FPFOG;
- component[nr++] = &rmesa->tcl.fog;
+ nr++;
}
@@ -588,11 +289,12 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
if (inputs & VERT_BIT_TEX(unit)) {
if (!rmesa->tcl.tex[unit].buf)
emit_tex_vector( ctx,
- &(rmesa->tcl.tex[unit]),
+ &(rmesa->tcl.aos[nr]),
(char *)VB->TexCoordPtr[unit]->data,
VB->TexCoordPtr[unit]->size,
VB->TexCoordPtr[unit]->stride,
count );
+ nr++;
vfmt |= RADEON_ST_BIT(unit);
/* assume we need the 3rd coord if texgen is active for r/q OR at least
@@ -610,7 +312,6 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
(swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1)))
radeonUploadTexMatrix( rmesa, unit, swaptexmatcol ) ;
}
- component[nr++] = &rmesa->tcl.tex[unit];
}
}
@@ -623,34 +324,3 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
rmesa->tcl.vertex_format = vfmt;
}
-
-void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
- GLuint unit;
-
-#if 0
- if (RADEON_DEBUG & DEBUG_VERTS)
- _tnl_print_vert_flags( __FUNCTION__, newinputs );
-#endif
-
- if (newinputs & VERT_BIT_POS)
- radeonReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ );
-
- if (newinputs & VERT_BIT_NORMAL)
- radeonReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ );
-
- if (newinputs & VERT_BIT_COLOR0)
- radeonReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ );
-
- if (newinputs & VERT_BIT_COLOR1)
- radeonReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ );
-
- if (newinputs & VERT_BIT_FOG)
- radeonReleaseDmaRegion( rmesa, &rmesa->tcl.fog, __FUNCTION__ );
-
- for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
- if (newinputs & VERT_BIT_TEX(unit))
- radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[unit], __FUNCTION__ );
- }
-}
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h b/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h
index 034cda8a65..515783135d 100644
--- a/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h
@@ -54,8 +54,7 @@ static void TAG(emit)( GLcontext *ctx,
union emit_union *v = (union emit_union *)dest;
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s\n", __FUNCTION__);
coord = (GLuint (*)[4])VB->ObjPtr->data;
coord_stride = VB->ObjPtr->stride;
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
index 126d0727c6..78ec119302 100644
--- a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
@@ -310,7 +310,7 @@ static void init_tcl_verts( void )
void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint req = 0;
GLuint unit;
@@ -374,14 +374,15 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
break;
if (rmesa->tcl.vertex_format == setup_tab[i].vertex_format &&
- rmesa->tcl.indexed_verts.buf)
+ rmesa->radeon.tcl.aos[0].bo)
return;
- if (rmesa->tcl.indexed_verts.buf)
+ if (rmesa->radeon.tcl.aos[0].bo)
radeonReleaseArrays( ctx, ~0 );
- radeonAllocDmaRegion( rmesa,
- &rmesa->tcl.indexed_verts,
+ radeonAllocDmaRegion( &rmesa->radeon,
+ &rmesa->radeon.tcl.aos[0].bo,
+ &rmesa->radeon.tcl.aos[0].offset,
VB->Count * setup_tab[i].vertex_size * 4,
4);
@@ -421,29 +422,12 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
setup_tab[i].emit( ctx, 0, VB->Count,
- rmesa->tcl.indexed_verts.address +
- rmesa->tcl.indexed_verts.start );
+ rmesa->radeon.tcl.aos[0].bo->ptr + rmesa->radeon.tcl.aos[0].offset);
+ // rmesa->radeon.tcl.aos[0].size = setup_tab[i].vertex_size;
+ rmesa->radeon.tcl.aos[0].stride = setup_tab[i].vertex_size;
rmesa->tcl.vertex_format = setup_tab[i].vertex_format;
- rmesa->tcl.indexed_verts.aos_start = GET_START( &rmesa->tcl.indexed_verts );
- rmesa->tcl.indexed_verts.aos_size = setup_tab[i].vertex_size;
- rmesa->tcl.indexed_verts.aos_stride = setup_tab[i].vertex_size;
-
- rmesa->tcl.aos_components[0] = &rmesa->tcl.indexed_verts;
- rmesa->tcl.nr_aos_components = 1;
+ rmesa->radeon.tcl.aos_count = 1;
}
-
-void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
-
-#if 0
- if (RADEON_DEBUG & DEBUG_VERTS)
- _tnl_print_vert_flags( __FUNCTION__, newinputs );
-#endif
-
- if (newinputs)
- radeonReleaseDmaRegion( rmesa, &rmesa->tcl.indexed_verts, __FUNCTION__ );
-}
diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
new file mode 100644
index 0000000000..38db305e2a
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "radeon_mipmap_tree.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "main/simple_list.h"
+#include "main/texcompress.h"
+#include "main/texformat.h"
+
+static GLuint radeon_compressed_texture_size(GLcontext *ctx,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLuint mesaFormat)
+{
+ GLuint size = _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat);
+
+ if (mesaFormat == MESA_FORMAT_RGB_DXT1 ||
+ mesaFormat == MESA_FORMAT_RGBA_DXT1) {
+ if (width + 3 < 8) /* width one block */
+ size = size * 4;
+ else if (width + 3 < 16)
+ size = size * 2;
+ } else {
+ /* DXT3/5, 16 bytes per block */
+ // WARN_ONCE("DXT 3/5 suffers from multitexturing problems!\n");
+ if (width + 3 < 8)
+ size = size * 2;
+ }
+
+ return size;
+}
+
+
+static int radeon_compressed_num_bytes(GLuint mesaFormat)
+{
+ int bytes = 0;
+ switch(mesaFormat) {
+
+ case MESA_FORMAT_RGB_FXT1:
+ case MESA_FORMAT_RGBA_FXT1:
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+ bytes = 2;
+ break;
+
+ case MESA_FORMAT_RGBA_DXT3:
+ case MESA_FORMAT_RGBA_DXT5:
+ bytes = 4;
+ default:
+ break;
+ }
+
+ return bytes;
+}
+
+/**
+ * Compute sizes and fill in offset and blit information for the given
+ * image (determined by \p face and \p level).
+ *
+ * \param curOffset points to the offset at which the image is to be stored
+ * and is updated by this function according to the size of the image.
+ */
+static void compute_tex_image_offset(radeonContextPtr rmesa, radeon_mipmap_tree *mt,
+ GLuint face, GLuint level, GLuint* curOffset)
+{
+ radeon_mipmap_level *lvl = &mt->levels[level];
+ uint32_t row_align;
+
+ /* Find image size in bytes */
+ if (mt->compressed) {
+ /* TODO: Is this correct? Need test cases for compressed textures! */
+ row_align = rmesa->texture_compressed_row_align - 1;
+ lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align;
+ lvl->size = radeon_compressed_texture_size(mt->radeon->glCtx,
+ lvl->width, lvl->height, lvl->depth, mt->compressed);
+ } else if (mt->target == GL_TEXTURE_RECTANGLE_NV) {
+ row_align = rmesa->texture_rect_row_align - 1;
+ lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align;
+ lvl->size = lvl->rowstride * lvl->height;
+ } else if (mt->tilebits & RADEON_TXO_MICRO_TILE) {
+ /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
+ * though the actual offset may be different (if texture is less than
+ * 32 bytes width) to the untiled case */
+ lvl->rowstride = (lvl->width * mt->bpp * 2 + 31) & ~31;
+ lvl->size = lvl->rowstride * ((lvl->height + 1) / 2) * lvl->depth;
+ } else {
+ row_align = rmesa->texture_row_align - 1;
+ lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align;
+ lvl->size = lvl->rowstride * lvl->height * lvl->depth;
+ }
+ assert(lvl->size > 0);
+
+ /* All images are aligned to a 32-byte offset */
+ *curOffset = (*curOffset + 0x1f) & ~0x1f;
+ lvl->faces[face].offset = *curOffset;
+ *curOffset += lvl->size;
+
+ if (RADEON_DEBUG & RADEON_TEXTURE)
+ fprintf(stderr,
+ "level %d, face %d: rs:%d %dx%d at %d\n",
+ level, face, lvl->rowstride, lvl->width, lvl->height, lvl->faces[face].offset);
+}
+
+static GLuint minify(GLuint size, GLuint levels)
+{
+ size = size >> levels;
+ if (size < 1)
+ size = 1;
+ return size;
+}
+
+
+static void calculate_miptree_layout_r100(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
+{
+ GLuint curOffset;
+ GLuint numLevels;
+ GLuint i;
+ GLuint face;
+
+ numLevels = mt->lastLevel - mt->firstLevel + 1;
+ assert(numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
+
+ curOffset = 0;
+ for(face = 0; face < mt->faces; face++) {
+
+ for(i = 0; i < numLevels; i++) {
+ mt->levels[i].width = minify(mt->width0, i);
+ mt->levels[i].height = minify(mt->height0, i);
+ mt->levels[i].depth = minify(mt->depth0, i);
+ compute_tex_image_offset(rmesa, mt, face, i, &curOffset);
+ }
+ }
+
+ /* Note the required size in memory */
+ mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
+}
+
+static void calculate_miptree_layout_r300(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
+{
+ GLuint curOffset;
+ GLuint numLevels;
+ GLuint i;
+
+ numLevels = mt->lastLevel - mt->firstLevel + 1;
+ assert(numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
+
+ curOffset = 0;
+ for(i = 0; i < numLevels; i++) {
+ GLuint face;
+
+ mt->levels[i].width = minify(mt->width0, i);
+ mt->levels[i].height = minify(mt->height0, i);
+ mt->levels[i].depth = minify(mt->depth0, i);
+
+ for(face = 0; face < mt->faces; face++)
+ compute_tex_image_offset(rmesa, mt, face, i, &curOffset);
+ }
+
+ /* Note the required size in memory */
+ mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
+}
+
+/**
+ * Create a new mipmap tree, calculate its layout and allocate memory.
+ */
+radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
+ GLenum target, GLenum internal_format, GLuint firstLevel, GLuint lastLevel,
+ GLuint width0, GLuint height0, GLuint depth0,
+ GLuint bpp, GLuint tilebits, GLuint compressed)
+{
+ radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
+
+ mt->radeon = rmesa;
+ mt->internal_format = internal_format;
+ mt->refcount = 1;
+ mt->t = t;
+ mt->target = target;
+ mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ mt->firstLevel = firstLevel;
+ mt->lastLevel = lastLevel;
+ mt->width0 = width0;
+ mt->height0 = height0;
+ mt->depth0 = depth0;
+ mt->bpp = compressed ? radeon_compressed_num_bytes(compressed) : bpp;
+ mt->tilebits = tilebits;
+ mt->compressed = compressed;
+
+ if (rmesa->radeonScreen->chip_family >= CHIP_FAMILY_R300)
+ calculate_miptree_layout_r300(rmesa, mt);
+ else
+ calculate_miptree_layout_r100(rmesa, mt);
+
+ mt->bo = radeon_bo_open(rmesa->radeonScreen->bom,
+ 0, mt->totalsize, 1024,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+
+ return mt;
+}
+
+void radeon_miptree_reference(radeon_mipmap_tree *mt)
+{
+ mt->refcount++;
+ assert(mt->refcount > 0);
+}
+
+void radeon_miptree_unreference(radeon_mipmap_tree *mt)
+{
+ if (!mt)
+ return;
+
+ assert(mt->refcount > 0);
+ mt->refcount--;
+ if (!mt->refcount) {
+ radeon_bo_unref(mt->bo);
+ free(mt);
+ }
+}
+
+
+/**
+ * Calculate first and last mip levels for the given texture object,
+ * where the dimensions are taken from the given texture image at
+ * the given level.
+ *
+ * Note: level is the OpenGL level number, which is not necessarily the same
+ * as the first level that is actually present.
+ *
+ * The base level image of the given texture face must be non-null,
+ * or this will fail.
+ */
+static void calculate_first_last_level(struct gl_texture_object *tObj,
+ GLuint *pfirstLevel, GLuint *plastLevel,
+ GLuint face, GLuint level)
+{
+ const struct gl_texture_image * const baseImage =
+ tObj->Image[face][level];
+
+ assert(baseImage);
+
+ /* These must be signed values. MinLod and MaxLod can be negative numbers,
+ * and having firstLevel and lastLevel as signed prevents the need for
+ * extra sign checks.
+ */
+ int firstLevel;
+ int lastLevel;
+
+ /* Yes, this looks overly complicated, but it's all needed.
+ */
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+ firstLevel = lastLevel = tObj->BaseLevel;
+ } else {
+ firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ firstLevel = MIN2(firstLevel, level + baseImage->MaxLog2);
+ lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, level + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_4D_SGIS:
+ firstLevel = lastLevel = 0;
+ break;
+ default:
+ return;
+ }
+
+ /* save these values */
+ *pfirstLevel = firstLevel;
+ *plastLevel = lastLevel;
+}
+
+
+/**
+ * Checks whether the given miptree can hold the given texture image at the
+ * given face and level.
+ */
+GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
+ struct gl_texture_image *texImage, GLuint face, GLuint level)
+{
+ radeon_mipmap_level *lvl;
+
+ if (face >= mt->faces || level < mt->firstLevel || level > mt->lastLevel)
+ return GL_FALSE;
+
+ if (texImage->InternalFormat != mt->internal_format ||
+ texImage->IsCompressed != mt->compressed)
+ return GL_FALSE;
+
+ if (!texImage->IsCompressed &&
+ !mt->compressed &&
+ texImage->TexFormat->TexelBytes != mt->bpp)
+ return GL_FALSE;
+
+ lvl = &mt->levels[level - mt->firstLevel];
+ if (lvl->width != texImage->Width ||
+ lvl->height != texImage->Height ||
+ lvl->depth != texImage->Depth)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Checks whether the given miptree has the right format to store the given texture object.
+ */
+GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj)
+{
+ struct gl_texture_image *firstImage;
+ GLuint compressed;
+ GLuint numfaces = 1;
+ GLuint firstLevel, lastLevel;
+
+ calculate_first_last_level(texObj, &firstLevel, &lastLevel, 0, texObj->BaseLevel);
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP)
+ numfaces = 6;
+
+ firstImage = texObj->Image[0][firstLevel];
+ compressed = firstImage->IsCompressed ? firstImage->TexFormat->MesaFormat : 0;
+
+ return (mt->firstLevel == firstLevel &&
+ mt->lastLevel == lastLevel &&
+ mt->width0 == firstImage->Width &&
+ mt->height0 == firstImage->Height &&
+ mt->depth0 == firstImage->Depth &&
+ mt->compressed == compressed &&
+ (!mt->compressed ? (mt->bpp == firstImage->TexFormat->TexelBytes) : 1));
+}
+
+
+/**
+ * Try to allocate a mipmap tree for the given texture that will fit the
+ * given image in the given position.
+ */
+void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
+ radeon_texture_image *image, GLuint face, GLuint level)
+{
+ GLuint compressed = image->base.IsCompressed ? image->base.TexFormat->MesaFormat : 0;
+ GLuint numfaces = 1;
+ GLuint firstLevel, lastLevel;
+
+ assert(!t->mt);
+
+ calculate_first_last_level(&t->base, &firstLevel, &lastLevel, face, level);
+ if (t->base.Target == GL_TEXTURE_CUBE_MAP)
+ numfaces = 6;
+
+ if (level != firstLevel || face >= numfaces)
+ return;
+
+ t->mt = radeon_miptree_create(rmesa, t, t->base.Target,
+ image->base.InternalFormat,
+ firstLevel, lastLevel,
+ image->base.Width, image->base.Height, image->base.Depth,
+ image->base.TexFormat->TexelBytes, t->tile_bits, compressed);
+}
+
+/* Although we use the image_offset[] array to store relative offsets
+ * to cube faces, Mesa doesn't know anything about this and expects
+ * each cube face to be treated as a separate image.
+ *
+ * These functions present that view to mesa:
+ */
+void
+radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level, GLuint *offsets)
+{
+ if (mt->target != GL_TEXTURE_3D || mt->faces == 1)
+ offsets[0] = 0;
+ else {
+ int i;
+ for (i = 0; i < 6; i++)
+ offsets[i] = mt->levels[level].faces[i].offset;
+ }
+}
+
+GLuint
+radeon_miptree_image_offset(radeon_mipmap_tree *mt,
+ GLuint face, GLuint level)
+{
+ if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
+ return (mt->levels[level].faces[face].offset);
+ else
+ return mt->levels[level].faces[0].offset;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
new file mode 100644
index 0000000000..db28252da3
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __RADEON_MIPMAP_TREE_H_
+#define __RADEON_MIPMAP_TREE_H_
+
+#include "radeon_common.h"
+
+typedef struct _radeon_mipmap_tree radeon_mipmap_tree;
+typedef struct _radeon_mipmap_level radeon_mipmap_level;
+typedef struct _radeon_mipmap_image radeon_mipmap_image;
+
+struct _radeon_mipmap_image {
+ GLuint offset; /** Offset of this image from the start of mipmap tree buffer, in bytes */
+};
+
+struct _radeon_mipmap_level {
+ GLuint width;
+ GLuint height;
+ GLuint depth;
+ GLuint size; /** Size of each image, in bytes */
+ GLuint rowstride; /** in bytes */
+ radeon_mipmap_image faces[6];
+};
+
+/* store the max possible in the miptree */
+#define RADEON_MIPTREE_MAX_TEXTURE_LEVELS 13
+
+/**
+ * A mipmap tree contains texture images in the layout that the hardware
+ * expects.
+ *
+ * The meta-data of mipmap trees is immutable, i.e. you cannot change the
+ * layout on-the-fly; however, the texture contents (i.e. texels) can be
+ * changed.
+ */
+struct _radeon_mipmap_tree {
+ radeonContextPtr radeon;
+ radeonTexObj *t;
+ struct radeon_bo *bo;
+ GLuint refcount;
+
+ GLuint totalsize; /** total size of the miptree, in bytes */
+
+ GLenum target; /** GL_TEXTURE_xxx */
+ GLenum internal_format;
+ GLuint faces; /** # of faces: 6 for cubemaps, 1 otherwise */
+ GLuint firstLevel; /** First mip level stored in this mipmap tree */
+ GLuint lastLevel; /** Last mip level stored in this mipmap tree */
+
+ GLuint width0; /** Width of firstLevel image */
+ GLuint height0; /** Height of firstLevel image */
+ GLuint depth0; /** Depth of firstLevel image */
+
+ GLuint bpp; /** Bytes per texel */
+ GLuint tilebits; /** RADEON_TXO_xxx_TILE */
+ GLuint compressed; /** MESA_FORMAT_xxx indicating a compressed format, or 0 if uncompressed */
+
+ radeon_mipmap_level levels[RADEON_MIPTREE_MAX_TEXTURE_LEVELS];
+};
+
+radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
+ GLenum target, GLenum internal_format, GLuint firstLevel, GLuint lastLevel,
+ GLuint width0, GLuint height0, GLuint depth0,
+ GLuint bpp, GLuint tilebits, GLuint compressed);
+void radeon_miptree_reference(radeon_mipmap_tree *mt);
+void radeon_miptree_unreference(radeon_mipmap_tree *mt);
+
+GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
+ struct gl_texture_image *texImage, GLuint face, GLuint level);
+GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj);
+void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
+ radeon_texture_image *texImage, GLuint face, GLuint level);
+GLuint radeon_miptree_image_offset(radeon_mipmap_tree *mt,
+ GLuint face, GLuint level);
+void radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level, GLuint *offsets);
+#endif /* __RADEON_MIPMAP_TREE_H_ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_queryobj.c b/src/mesa/drivers/dri/radeon/radeon_queryobj.c
new file mode 100644
index 0000000000..b79d864ba2
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_queryobj.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright © 2008-2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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:
+ * Maciej Cencora <m.cencora@gmail.com>
+ *
+ */
+#include "radeon_common.h"
+#include "radeon_queryobj.h"
+#include "radeon_debug.h"
+
+#include "main/imports.h"
+#include "main/simple_list.h"
+
+static int radeonQueryIsFlushed(GLcontext *ctx, struct gl_query_object *q)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_query_object *tmp, *query = (struct radeon_query_object *)q;
+
+ foreach(tmp, &radeon->query.not_flushed_head) {
+ if (tmp == query) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void radeonQueryGetResult(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct radeon_query_object *query = (struct radeon_query_object *)q;
+ uint32_t *result;
+ int i;
+
+ radeon_print(RADEON_STATE, RADEON_VERBOSE,
+ "%s: query id %d, result %d\n",
+ __FUNCTION__, query->Base.Id, (int) query->Base.Result);
+
+ radeon_bo_map(query->bo, GL_FALSE);
+
+ result = query->bo->ptr;
+
+ query->Base.Result = 0;
+ for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) {
+ query->Base.Result += result[i];
+ radeon_print(RADEON_STATE, RADEON_TRACE, "result[%d] = %d\n", i, result[i]);
+ }
+
+ radeon_bo_unmap(query->bo);
+}
+
+static struct gl_query_object * radeonNewQueryObject(GLcontext *ctx, GLuint id)
+{
+ struct radeon_query_object *query;
+
+ query = _mesa_calloc(sizeof(struct radeon_query_object));
+
+ query->Base.Id = id;
+ query->Base.Result = 0;
+ query->Base.Active = GL_FALSE;
+ query->Base.Ready = GL_TRUE;
+
+ radeon_print(RADEON_STATE, RADEON_VERBOSE,"%s: query id %d\n", __FUNCTION__, query->Base.Id);
+
+ return &query->Base;
+}
+
+static void radeonDeleteQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct radeon_query_object *query = (struct radeon_query_object *)q;
+
+ radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d\n", __FUNCTION__, q->Id);
+
+ if (query->bo) {
+ radeon_bo_unref(query->bo);
+ }
+
+ _mesa_free(query);
+}
+
+static void radeonWaitQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct radeon_query_object *query = (struct radeon_query_object *)q;
+
+ /* If the cmdbuf with packets for this query hasn't been flushed yet, do it now */
+ if (!radeonQueryIsFlushed(ctx, q))
+ ctx->Driver.Flush(ctx);
+
+ radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, q->Id, query->bo, query->curr_offset);
+
+ radeonQueryGetResult(ctx, q);
+
+ query->Base.Ready = GL_TRUE;
+}
+
+
+static void radeonBeginQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_query_object *query = (struct radeon_query_object *)q;
+
+ radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d\n", __FUNCTION__, q->Id);
+
+ assert(radeon->query.current == NULL);
+
+ if (radeon->dma.flush)
+ radeon->dma.flush(radeon->glCtx);
+
+ if (!query->bo) {
+ query->bo = radeon_bo_open(radeon->radeonScreen->bom, 0, RADEON_QUERY_PAGE_SIZE, RADEON_QUERY_PAGE_SIZE, RADEON_GEM_DOMAIN_GTT, 0);
+ }
+ query->curr_offset = 0;
+
+ radeon->query.current = query;
+
+ radeon->query.queryobj.dirty = GL_TRUE;
+ radeon->hw.is_dirty = GL_TRUE;
+ insert_at_tail(&radeon->query.not_flushed_head, query);
+
+}
+
+void radeonEmitQueryEnd(GLcontext *ctx)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_query_object *query = radeon->query.current;
+
+ if (!query)
+ return;
+
+ if (query->emitted_begin == GL_FALSE)
+ return;
+
+ radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, query->Base.Id, query->bo, query->curr_offset);
+
+ radeon_cs_space_check_with_bo(radeon->cmdbuf.cs,
+ query->bo,
+ 0, RADEON_GEM_DOMAIN_GTT);
+
+ radeon->vtbl.emit_query_finish(radeon);
+}
+
+static void radeonEndQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+
+ radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d\n", __FUNCTION__, q->Id);
+
+ if (radeon->dma.flush)
+ radeon->dma.flush(radeon->glCtx);
+ radeonEmitQueryEnd(ctx);
+
+ radeon->query.current = NULL;
+}
+
+static void radeonCheckQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ radeon_print(RADEON_STATE, RADEON_TRACE, "%s: query id %d\n", __FUNCTION__, q->Id);
+
+#ifdef DRM_RADEON_GEM_BUSY
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+
+ if (radeon->radeonScreen->kernel_mm) {
+ struct radeon_query_object *query = (struct radeon_query_object *)q;
+ uint32_t domain;
+
+ /* Need to perform a flush, as per ARB_occlusion_query spec */
+ if (!radeonQueryIsFlushed(ctx, q)) {
+ ctx->Driver.Flush(ctx);
+ }
+
+ if (radeon_bo_is_busy(query->bo, &domain) == 0) {
+ radeonQueryGetResult(ctx, q);
+ query->Base.Ready = GL_TRUE;
+ }
+ } else {
+ radeonWaitQuery(ctx, q);
+ }
+#else
+ radeonWaitQuery(ctx, q);
+#endif
+}
+
+void radeonInitQueryObjFunctions(struct dd_function_table *functions)
+{
+ functions->NewQueryObject = radeonNewQueryObject;
+ functions->DeleteQuery = radeonDeleteQuery;
+ functions->BeginQuery = radeonBeginQuery;
+ functions->EndQuery = radeonEndQuery;
+ functions->CheckQuery = radeonCheckQuery;
+ functions->WaitQuery = radeonWaitQuery;
+}
+
+int radeon_check_query_active(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_query_object *query = radeon->query.current;
+
+ if (!query || query->emitted_begin)
+ return 0;
+ return atom->cmd_size;
+}
+
+void radeon_emit_queryobj(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ BATCH_LOCALS(radeon);
+ int dwords;
+
+ dwords = (*atom->check) (ctx, atom);
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(atom->cmd, dwords);
+ END_BATCH();
+
+ radeon->query.current->emitted_begin = GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_queryobj.h b/src/mesa/drivers/dri/radeon/radeon_queryobj.h
new file mode 100644
index 0000000000..19374dc76b
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_queryobj.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2008 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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:
+ * Maciej Cencora <m.cencora@gmail.com>
+ *
+ */
+
+#include "main/imports.h"
+#include "main/simple_list.h"
+#include "radeon_common_context.h"
+
+extern void radeonEmitQueryBegin(GLcontext *ctx);
+extern void radeonEmitQueryEnd(GLcontext *ctx);
+
+extern void radeonInitQueryObjFunctions(struct dd_function_table *functions);
+
+#define RADEON_QUERY_PAGE_SIZE 4096
+
+int radeon_check_query_active(GLcontext *ctx, struct radeon_state_atom *atom);
+void radeon_emit_queryobj(GLcontext *ctx, struct radeon_state_atom *atom);
+
+static inline void radeon_init_query_stateobj(radeonContextPtr radeon, int SZ)
+{
+ radeon->query.queryobj.cmd_size = (SZ);
+ radeon->query.queryobj.cmd = (uint32_t*)CALLOC((SZ) * sizeof(uint32_t));
+ radeon->query.queryobj.name = "queryobj";
+ radeon->query.queryobj.idx = 0;
+ radeon->query.queryobj.check = radeon_check_query_active;
+ radeon->query.queryobj.dirty = GL_FALSE;
+ radeon->query.queryobj.emit = radeon_emit_queryobj;
+
+ radeon->hw.max_state_size += (SZ);
+ insert_at_tail(&radeon->hw.atomlist, &radeon->query.queryobj);
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_sanity.c b/src/mesa/drivers/dri/radeon/radeon_sanity.c
index 6613757fce..1ab570f507 100644
--- a/src/mesa/drivers/dri/radeon/radeon_sanity.c
+++ b/src/mesa/drivers/dri/radeon/radeon_sanity.c
@@ -44,11 +44,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define MORE_VERBOSE 1
#if MORE_VERBOSE
-#define VERBOSE (RADEON_DEBUG & DEBUG_VERBOSE)
+#define VERBOSE (RADEON_DEBUG & RADEON_VERBOSE)
#define NORMAL (1)
#else
#define VERBOSE 0
-#define NORMAL (RADEON_DEBUG & DEBUG_VERBOSE)
+#define NORMAL (RADEON_DEBUG & RADEON_VERBOSE)
#endif
@@ -973,7 +973,7 @@ static int radeon_emit_packet3_cliprect( drm_radeon_cmd_buffer_t *cmdbuf )
}
-int radeonSanityCmdBuffer( radeonContextPtr rmesa,
+int radeonSanityCmdBuffer( r100ContextPtr rmesa,
int nbox,
drm_clip_rect_t *boxes )
{
diff --git a/src/mesa/drivers/dri/radeon/radeon_sanity.h b/src/mesa/drivers/dri/radeon/radeon_sanity.h
index 1ec06bc586..f30eb1c4f1 100644
--- a/src/mesa/drivers/dri/radeon/radeon_sanity.h
+++ b/src/mesa/drivers/dri/radeon/radeon_sanity.h
@@ -1,7 +1,7 @@
#ifndef RADEON_SANITY_H
#define RADEON_SANITY_H
-extern int radeonSanityCmdBuffer( radeonContextPtr rmesa,
+extern int radeonSanityCmdBuffer( r100ContextPtr rmesa,
int nbox,
drm_clip_rect_t *boxes );
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index 5f32dd575e..5ffb55db5e 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -35,6 +35,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* \author Gareth Hughes <gareth@valinux.com>
*/
+#include <errno.h>
#include "main/glheader.h"
#include "main/imports.h"
#include "main/mtypes.h"
@@ -45,32 +46,42 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_chipset.h"
#include "radeon_macros.h"
#include "radeon_screen.h"
+#include "radeon_common.h"
+#include "radeon_span.h"
#if !RADEON_COMMON
#include "radeon_context.h"
-#include "radeon_span.h"
#include "radeon_tex.h"
#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
#include "r200_context.h"
#include "r200_ioctl.h"
-#include "r200_span.h"
#include "r200_tex.h"
#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
#include "r300_context.h"
-#include "r300_fragprog.h"
#include "r300_tex.h"
-#include "radeon_span.h"
+#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R600)
+#include "r600_context.h"
+#include "r700_driconf.h" /* +r6/r7 */
+#include "r600_tex.h" /* +r6/r7 */
#endif
#include "utils.h"
#include "vblank.h"
#include "drirenderbuffer.h"
+#include "radeon_bocs_wrapper.h"
+
#include "GL/internal/dri_interface.h"
/* Radeon configuration
*/
#include "xmlpool.h"
+#define DRI_CONF_COMMAND_BUFFER_SIZE(def,min,max) \
+DRI_CONF_OPT_BEGIN_V(command_buffer_size,int,def, # min ":" # max ) \
+ DRI_CONF_DESC(en,"Size of command buffer (in KB)") \
+ DRI_CONF_DESC(de,"Grösse des Befehlspuffers (in KB)") \
+DRI_CONF_OPT_END
+
#if !RADEON_COMMON /* R100 */
PUBLIC const char __driConfigOptions[] =
DRI_CONF_BEGIN
@@ -80,6 +91,7 @@ DRI_CONF_BEGIN
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
DRI_CONF_MAX_TEXTURE_UNITS(3,2,3)
DRI_CONF_HYPERZ(false)
+ DRI_CONF_COMMAND_BUFFER_SIZE(8, 8, 32)
DRI_CONF_SECTION_END
DRI_CONF_SECTION_QUALITY
DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
@@ -95,7 +107,7 @@ DRI_CONF_BEGIN
DRI_CONF_NO_RAST(false)
DRI_CONF_SECTION_END
DRI_CONF_END;
-static const GLuint __driNConfigOptions = 14;
+static const GLuint __driNConfigOptions = 15;
#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
@@ -107,6 +119,7 @@ DRI_CONF_BEGIN
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
DRI_CONF_MAX_TEXTURE_UNITS(6,2,6)
DRI_CONF_HYPERZ(false)
+ DRI_CONF_COMMAND_BUFFER_SIZE(8, 8, 32)
DRI_CONF_SECTION_END
DRI_CONF_SECTION_QUALITY
DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
@@ -126,7 +139,7 @@ DRI_CONF_BEGIN
DRI_CONF_NV_VERTEX_PROGRAM(false)
DRI_CONF_SECTION_END
DRI_CONF_END;
-static const GLuint __driNConfigOptions = 16;
+static const GLuint __driNConfigOptions = 17;
extern const struct dri_extension blend_extensions[];
extern const struct dri_extension ARB_vp_extension[];
@@ -134,7 +147,10 @@ extern const struct dri_extension NV_vp_extension[];
extern const struct dri_extension ATI_fs_extension[];
extern const struct dri_extension point_extensions[];
-#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
+#elif RADEON_COMMON && (defined(RADEON_COMMON_FOR_R300) || defined(RADEON_COMMON_FOR_R600))
+
+#define DRI_CONF_FP_OPTIMIZATION_SPEED 0
+#define DRI_CONF_FP_OPTIMIZATION_QUALITY 1
/* TODO: integrate these into xmlpool.h! */
#define DRI_CONF_MAX_TEXTURE_IMAGE_UNITS(def,min,max) \
@@ -149,11 +165,7 @@ DRI_CONF_OPT_BEGIN_V(texture_coord_units,int,def, # min ":" # max ) \
DRI_CONF_DESC(de,"Anzahl der Texturkoordinateneinheiten") \
DRI_CONF_OPT_END
-#define DRI_CONF_COMMAND_BUFFER_SIZE(def,min,max) \
-DRI_CONF_OPT_BEGIN_V(command_buffer_size,int,def, # min ":" # max ) \
- DRI_CONF_DESC(en,"Size of command buffer (in KB)") \
- DRI_CONF_DESC(de,"Grösse des Befehlspuffers (in KB)") \
-DRI_CONF_OPT_END
+
#define DRI_CONF_DISABLE_S3TC(def) \
DRI_CONF_OPT_BEGIN(disable_s3tc,bool,def) \
@@ -206,47 +218,44 @@ DRI_CONF_BEGIN
DRI_CONF_END;
static const GLuint __driNConfigOptions = 17;
-#ifndef RADEON_DEBUG
-int RADEON_DEBUG = 0;
-
-static const struct dri_debug_control debug_control[] = {
- {"fall", DEBUG_FALLBACKS},
- {"tex", DEBUG_TEXTURE},
- {"ioctl", DEBUG_IOCTL},
- {"prim", DEBUG_PRIMS},
- {"vert", DEBUG_VERTS},
- {"state", DEBUG_STATE},
- {"code", DEBUG_CODEGEN},
- {"vfmt", DEBUG_VFMT},
- {"vtxf", DEBUG_VFMT},
- {"verb", DEBUG_VERBOSE},
- {"dri", DEBUG_DRI},
- {"dma", DEBUG_DMA},
- {"san", DEBUG_SANITY},
- {"sync", DEBUG_SYNC},
- {"pix", DEBUG_PIXEL},
- {"mem", DEBUG_MEMORY},
- {"allmsg", ~DEBUG_SYNC}, /* avoid the term "sync" because the parser uses strstr */
- {NULL, 0}
-};
-#endif /* RADEON_DEBUG */
+extern const struct dri_extension gl_20_extension[];
#endif /* RADEON_COMMON && defined(RADEON_COMMON_FOR_R300) */
extern const struct dri_extension card_extensions[];
+extern const struct dri_extension mm_extensions[];
static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
static int
-radeonGetParam(int fd, int param, void *value)
+radeonGetParam(__DRIscreenPrivate *sPriv, int param, void *value)
{
int ret;
- drm_radeon_getparam_t gp;
-
- gp.param = param;
- gp.value = value;
+ drm_radeon_getparam_t gp = { 0 };
+ struct drm_radeon_info info = { 0 };
+
+ if (sPriv->drm_version.major >= 2) {
+ info.value = (uint64_t)(uintptr_t)value;
+ switch (param) {
+ case RADEON_PARAM_DEVICE_ID:
+ info.request = RADEON_INFO_DEVICE_ID;
+ break;
+ case RADEON_PARAM_NUM_GB_PIPES:
+ info.request = RADEON_INFO_NUM_GB_PIPES;
+ break;
+ case RADEON_PARAM_NUM_Z_PIPES:
+ info.request = RADEON_INFO_NUM_Z_PIPES;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ret = drmCommandWriteRead(sPriv->fd, DRM_RADEON_INFO, &info, sizeof(info));
+ } else {
+ gp.param = param;
+ gp.value = value;
- ret = drmCommandWriteRead( fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp));
+ ret = drmCommandWriteRead(sPriv->fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp));
+ }
return ret;
}
@@ -259,8 +268,6 @@ radeonFillInModes( __DRIscreenPrivate *psp,
__GLcontextModes *m;
unsigned depth_buffer_factor;
unsigned back_buffer_factor;
- GLenum fb_format;
- GLenum fb_type;
int i;
/* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
@@ -274,7 +281,7 @@ radeonFillInModes( __DRIscreenPrivate *psp,
uint8_t depth_bits_array[2];
uint8_t stencil_bits_array[2];
-
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = depth_bits;
depth_bits_array[1] = depth_bits;
@@ -283,25 +290,35 @@ radeonFillInModes( __DRIscreenPrivate *psp,
* with a stencil buffer. It will be a sw fallback, but some apps won't
* care about that.
*/
- stencil_bits_array[0] = 0;
+ stencil_bits_array[0] = stencil_bits;
stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
- depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
+ msaa_samples_array[0] = 0;
+
+ depth_buffer_factor = (stencil_bits == 0) ? 2 : 1;
back_buffer_factor = (have_back_buffer) ? 2 : 1;
- if ( pixel_bits == 16 ) {
- fb_format = GL_RGB;
- fb_type = GL_UNSIGNED_SHORT_5_6_5;
- }
- else {
- fb_format = GL_BGRA;
- fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
- }
+ if (pixel_bits == 16) {
+ __DRIconfig **configs_a8r8g8b8;
+ __DRIconfig **configs_r5g6b5;
+
+ configs_r5g6b5 = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+ depth_bits_array, stencil_bits_array,
+ depth_buffer_factor, back_buffer_modes,
+ back_buffer_factor, msaa_samples_array,
+ 1);
+ configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ depth_bits_array, stencil_bits_array,
+ 1, back_buffer_modes, 1,
+ msaa_samples_array, 1);
+ configs = driConcatConfigs(configs_r5g6b5, configs_a8r8g8b8);
+ } else
+ configs = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ depth_bits_array, stencil_bits_array,
+ depth_buffer_factor,
+ back_buffer_modes, back_buffer_factor,
+ msaa_samples_array, 1);
- configs = driCreateConfigs(fb_format, fb_type,
- depth_bits_array, stencil_bits_array,
- depth_buffer_factor,
- back_buffer_modes, back_buffer_factor);
if (configs == NULL) {
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
__func__, __LINE__ );
@@ -325,6 +342,12 @@ static const __DRItexOffsetExtension radeonTexOffsetExtension = {
{ __DRI_TEX_OFFSET, __DRI_TEX_OFFSET_VERSION },
radeonSetTexOffset,
};
+
+static const __DRItexBufferExtension radeonTexBufferExtension = {
+ { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
+ radeonSetTexBuffer,
+ radeonSetTexBuffer2,
+};
#endif
#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
@@ -339,6 +362,12 @@ static const __DRItexOffsetExtension r200texOffsetExtension = {
{ __DRI_TEX_OFFSET, __DRI_TEX_OFFSET_VERSION },
r200SetTexOffset,
};
+
+static const __DRItexBufferExtension r200TexBufferExtension = {
+ { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
+ r200SetTexBuffer,
+ r200SetTexBuffer2,
+};
#endif
#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
@@ -346,137 +375,32 @@ static const __DRItexOffsetExtension r300texOffsetExtension = {
{ __DRI_TEX_OFFSET, __DRI_TEX_OFFSET_VERSION },
r300SetTexOffset,
};
-#endif
-/* Create the device specific screen private data struct.
- */
-static radeonScreenPtr
-radeonCreateScreen( __DRIscreenPrivate *sPriv )
-{
- radeonScreenPtr screen;
- RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
- unsigned char *RADEONMMIO;
- int i;
- int ret;
- uint32_t temp;
-
- if (sPriv->devPrivSize != sizeof(RADEONDRIRec)) {
- fprintf(stderr,"\nERROR! sizeof(RADEONDRIRec) does not match passed size from device driver\n");
- return GL_FALSE;
- }
-
- /* Allocate the private area */
- screen = (radeonScreenPtr) CALLOC( sizeof(*screen) );
- if ( !screen ) {
- __driUtilMessage("%s: Could not allocate memory for screen structure",
- __FUNCTION__);
- return NULL;
- }
-
-#if DO_DEBUG && RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
- RADEON_DEBUG = driParseDebugString(getenv("RADEON_DEBUG"), debug_control);
+static const __DRItexBufferExtension r300TexBufferExtension = {
+ { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
+ r300SetTexBuffer,
+ r300SetTexBuffer2,
+};
#endif
- /* parse information in __driConfigOptions */
- driParseOptionInfo (&screen->optionCache,
- __driConfigOptions, __driNConfigOptions);
-
- /* This is first since which regions we map depends on whether or
- * not we are using a PCI card.
- */
- screen->card_type = (dri_priv->IsPCI ? RADEON_CARD_PCI : RADEON_CARD_AGP);
- {
- int ret;
- ret = radeonGetParam( sPriv->fd, RADEON_PARAM_GART_BUFFER_OFFSET,
- &screen->gart_buffer_offset);
-
- if (ret) {
- FREE( screen );
- fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret);
- return NULL;
- }
-
- ret = radeonGetParam( sPriv->fd, RADEON_PARAM_GART_BASE,
- &screen->gart_base);
- if (ret) {
- FREE( screen );
- fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BASE): %d\n", ret);
- return NULL;
- }
-
- ret = radeonGetParam( sPriv->fd, RADEON_PARAM_IRQ_NR,
- &screen->irq);
- if (ret) {
- FREE( screen );
- fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_IRQ_NR): %d\n", ret);
- return NULL;
- }
- screen->drmSupportsCubeMapsR200 = (sPriv->drm_version.minor >= 7);
- screen->drmSupportsBlendColor = (sPriv->drm_version.minor >= 11);
- screen->drmSupportsTriPerf = (sPriv->drm_version.minor >= 16);
- screen->drmSupportsFragShader = (sPriv->drm_version.minor >= 18);
- screen->drmSupportsPointSprites = (sPriv->drm_version.minor >= 13);
- screen->drmSupportsCubeMapsR100 = (sPriv->drm_version.minor >= 15);
- screen->drmSupportsVertexProgram = (sPriv->drm_version.minor >= 25);
- }
-
- screen->mmio.handle = dri_priv->registerHandle;
- screen->mmio.size = dri_priv->registerSize;
- if ( drmMap( sPriv->fd,
- screen->mmio.handle,
- screen->mmio.size,
- &screen->mmio.map ) ) {
- FREE( screen );
- __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ );
- return NULL;
- }
-
- RADEONMMIO = screen->mmio.map;
-
- screen->status.handle = dri_priv->statusHandle;
- screen->status.size = dri_priv->statusSize;
- if ( drmMap( sPriv->fd,
- screen->status.handle,
- screen->status.size,
- &screen->status.map ) ) {
- drmUnmap( screen->mmio.map, screen->mmio.size );
- FREE( screen );
- __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
- return NULL;
- }
- screen->scratch = (__volatile__ uint32_t *)
- ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
-
- screen->buffers = drmMapBufs( sPriv->fd );
- if ( !screen->buffers ) {
- drmUnmap( screen->status.map, screen->status.size );
- drmUnmap( screen->mmio.map, screen->mmio.size );
- FREE( screen );
- __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__ );
- return NULL;
- }
-
- if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
- screen->gartTextures.handle = dri_priv->gartTexHandle;
- screen->gartTextures.size = dri_priv->gartTexMapSize;
- if ( drmMap( sPriv->fd,
- screen->gartTextures.handle,
- screen->gartTextures.size,
- (drmAddressPtr)&screen->gartTextures.map ) ) {
- drmUnmapBufs( screen->buffers );
- drmUnmap( screen->status.map, screen->status.size );
- drmUnmap( screen->mmio.map, screen->mmio.size );
- FREE( screen );
- __driUtilMessage("%s: drmMap failed for GART texture area\n", __FUNCTION__);
- return NULL;
- }
+#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R600)
+static const __DRItexOffsetExtension r600texOffsetExtension = {
+ { __DRI_TEX_OFFSET, __DRI_TEX_OFFSET_VERSION },
+ r600SetTexOffset, /* +r6/r7 */
+};
- screen->gart_texture_offset = dri_priv->gartTexOffset + screen->gart_base;
- }
+static const __DRItexBufferExtension r600TexBufferExtension = {
+ { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
+ r600SetTexBuffer, /* +r6/r7 */
+ r600SetTexBuffer2, /* +r6/r7 */
+};
+#endif
+static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id)
+{
+ screen->device_id = device_id;
screen->chip_flags = 0;
- /* XXX: add more chipsets */
- switch ( dri_priv->deviceID ) {
+ switch ( device_id ) {
case PCI_CHIP_RADEON_LY:
case PCI_CHIP_RADEON_LZ:
case PCI_CHIP_RADEON_QY:
@@ -551,11 +475,7 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
screen->chip_family = CHIP_FAMILY_RS300;
break;
- /* 9500 with 1 pipe verified by: Reid Linnemann <lreid@cs.okstate.edu> */
case PCI_CHIP_R300_AD:
- screen->chip_family = CHIP_FAMILY_RV350;
- screen->chip_flags = RADEON_CHIPSET_TCL;
- break;
case PCI_CHIP_R300_AE:
case PCI_CHIP_R300_AF:
case PCI_CHIP_R300_AG:
@@ -680,6 +600,12 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
screen->chip_family = CHIP_FAMILY_RS400;
break;
+ case PCI_CHIP_RS600_793F:
+ case PCI_CHIP_RS600_7941:
+ case PCI_CHIP_RS600_7942:
+ screen->chip_family = CHIP_FAMILY_RS600;
+ break;
+
case PCI_CHIP_RS690_791E:
case PCI_CHIP_RS690_791F:
screen->chip_family = CHIP_FAMILY_RS690;
@@ -806,11 +732,325 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
screen->chip_flags = RADEON_CHIPSET_TCL;
break;
+ case PCI_CHIP_R600_9400:
+ case PCI_CHIP_R600_9401:
+ case PCI_CHIP_R600_9402:
+ case PCI_CHIP_R600_9403:
+ case PCI_CHIP_R600_9405:
+ case PCI_CHIP_R600_940A:
+ case PCI_CHIP_R600_940B:
+ case PCI_CHIP_R600_940F:
+ screen->chip_family = CHIP_FAMILY_R600;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RV610_94C0:
+ case PCI_CHIP_RV610_94C1:
+ case PCI_CHIP_RV610_94C3:
+ case PCI_CHIP_RV610_94C4:
+ case PCI_CHIP_RV610_94C5:
+ case PCI_CHIP_RV610_94C6:
+ case PCI_CHIP_RV610_94C7:
+ case PCI_CHIP_RV610_94C8:
+ case PCI_CHIP_RV610_94C9:
+ case PCI_CHIP_RV610_94CB:
+ case PCI_CHIP_RV610_94CC:
+ case PCI_CHIP_RV610_94CD:
+ screen->chip_family = CHIP_FAMILY_RV610;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RV630_9580:
+ case PCI_CHIP_RV630_9581:
+ case PCI_CHIP_RV630_9583:
+ case PCI_CHIP_RV630_9586:
+ case PCI_CHIP_RV630_9587:
+ case PCI_CHIP_RV630_9588:
+ case PCI_CHIP_RV630_9589:
+ case PCI_CHIP_RV630_958A:
+ case PCI_CHIP_RV630_958B:
+ case PCI_CHIP_RV630_958C:
+ case PCI_CHIP_RV630_958D:
+ case PCI_CHIP_RV630_958E:
+ case PCI_CHIP_RV630_958F:
+ screen->chip_family = CHIP_FAMILY_RV630;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RV670_9500:
+ case PCI_CHIP_RV670_9501:
+ case PCI_CHIP_RV670_9504:
+ case PCI_CHIP_RV670_9505:
+ case PCI_CHIP_RV670_9506:
+ case PCI_CHIP_RV670_9507:
+ case PCI_CHIP_RV670_9508:
+ case PCI_CHIP_RV670_9509:
+ case PCI_CHIP_RV670_950F:
+ case PCI_CHIP_RV670_9511:
+ case PCI_CHIP_RV670_9515:
+ case PCI_CHIP_RV670_9517:
+ case PCI_CHIP_RV670_9519:
+ screen->chip_family = CHIP_FAMILY_RV670;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RV620_95C0:
+ case PCI_CHIP_RV620_95C2:
+ case PCI_CHIP_RV620_95C4:
+ case PCI_CHIP_RV620_95C5:
+ case PCI_CHIP_RV620_95C6:
+ case PCI_CHIP_RV620_95C7:
+ case PCI_CHIP_RV620_95C9:
+ case PCI_CHIP_RV620_95CC:
+ case PCI_CHIP_RV620_95CD:
+ case PCI_CHIP_RV620_95CE:
+ case PCI_CHIP_RV620_95CF:
+ screen->chip_family = CHIP_FAMILY_RV620;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RV635_9590:
+ case PCI_CHIP_RV635_9591:
+ case PCI_CHIP_RV635_9593:
+ case PCI_CHIP_RV635_9595:
+ case PCI_CHIP_RV635_9596:
+ case PCI_CHIP_RV635_9597:
+ case PCI_CHIP_RV635_9598:
+ case PCI_CHIP_RV635_9599:
+ case PCI_CHIP_RV635_959B:
+ screen->chip_family = CHIP_FAMILY_RV635;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RS780_9610:
+ case PCI_CHIP_RS780_9611:
+ case PCI_CHIP_RS780_9612:
+ case PCI_CHIP_RS780_9613:
+ case PCI_CHIP_RS780_9614:
+ case PCI_CHIP_RS780_9615:
+ case PCI_CHIP_RS780_9616:
+ screen->chip_family = CHIP_FAMILY_RS780;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+ case PCI_CHIP_RS880_9710:
+ case PCI_CHIP_RS880_9711:
+ case PCI_CHIP_RS880_9712:
+ case PCI_CHIP_RS880_9713:
+ case PCI_CHIP_RS880_9714:
+ screen->chip_family = CHIP_FAMILY_RS880;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RV770_9440:
+ case PCI_CHIP_RV770_9441:
+ case PCI_CHIP_RV770_9442:
+ case PCI_CHIP_RV770_9443:
+ case PCI_CHIP_RV770_9444:
+ case PCI_CHIP_RV770_9446:
+ case PCI_CHIP_RV770_944A:
+ case PCI_CHIP_RV770_944B:
+ case PCI_CHIP_RV770_944C:
+ case PCI_CHIP_RV770_944E:
+ case PCI_CHIP_RV770_9450:
+ case PCI_CHIP_RV770_9452:
+ case PCI_CHIP_RV770_9456:
+ case PCI_CHIP_RV770_945A:
+ case PCI_CHIP_RV770_945B:
+ case PCI_CHIP_RV790_9460:
+ case PCI_CHIP_RV790_9462:
+ case PCI_CHIP_RV770_946A:
+ case PCI_CHIP_RV770_946B:
+ case PCI_CHIP_RV770_947A:
+ case PCI_CHIP_RV770_947B:
+ screen->chip_family = CHIP_FAMILY_RV770;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RV730_9480:
+ case PCI_CHIP_RV730_9487:
+ case PCI_CHIP_RV730_9488:
+ case PCI_CHIP_RV730_9489:
+ case PCI_CHIP_RV730_948F:
+ case PCI_CHIP_RV730_9490:
+ case PCI_CHIP_RV730_9491:
+ case PCI_CHIP_RV730_9495:
+ case PCI_CHIP_RV730_9498:
+ case PCI_CHIP_RV730_949C:
+ case PCI_CHIP_RV730_949E:
+ case PCI_CHIP_RV730_949F:
+ screen->chip_family = CHIP_FAMILY_RV730;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RV710_9540:
+ case PCI_CHIP_RV710_9541:
+ case PCI_CHIP_RV710_9542:
+ case PCI_CHIP_RV710_954E:
+ case PCI_CHIP_RV710_954F:
+ case PCI_CHIP_RV710_9552:
+ case PCI_CHIP_RV710_9553:
+ case PCI_CHIP_RV710_9555:
+ case PCI_CHIP_RV710_9557:
+ screen->chip_family = CHIP_FAMILY_RV710;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
+ case PCI_CHIP_RV740_94A0:
+ case PCI_CHIP_RV740_94A1:
+ case PCI_CHIP_RV740_94A3:
+ case PCI_CHIP_RV740_94B1:
+ case PCI_CHIP_RV740_94B3:
+ case PCI_CHIP_RV740_94B4:
+ case PCI_CHIP_RV740_94B5:
+ case PCI_CHIP_RV740_94B9:
+ screen->chip_family = CHIP_FAMILY_RV740;
+ screen->chip_flags = RADEON_CHIPSET_TCL;
+ break;
+
default:
fprintf(stderr, "unknown chip id 0x%x, can't guess.\n",
- dri_priv->deviceID);
+ device_id);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* Create the device specific screen private data struct.
+ */
+static radeonScreenPtr
+radeonCreateScreen( __DRIscreenPrivate *sPriv )
+{
+ radeonScreenPtr screen;
+ RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
+ unsigned char *RADEONMMIO = NULL;
+ int i;
+ int ret;
+ uint32_t temp = 0;
+
+ if (sPriv->devPrivSize != sizeof(RADEONDRIRec)) {
+ fprintf(stderr,"\nERROR! sizeof(RADEONDRIRec) does not match passed size from device driver\n");
+ return GL_FALSE;
+ }
+
+ /* Allocate the private area */
+ screen = (radeonScreenPtr) CALLOC( sizeof(*screen) );
+ if ( !screen ) {
+ __driUtilMessage("%s: Could not allocate memory for screen structure",
+ __FUNCTION__);
return NULL;
}
+
+ radeon_init_debug();
+
+ /* parse information in __driConfigOptions */
+ driParseOptionInfo (&screen->optionCache,
+ __driConfigOptions, __driNConfigOptions);
+
+ /* This is first since which regions we map depends on whether or
+ * not we are using a PCI card.
+ */
+ screen->card_type = (dri_priv->IsPCI ? RADEON_CARD_PCI : RADEON_CARD_AGP);
+ {
+ int ret;
+
+ ret = radeonGetParam(sPriv, RADEON_PARAM_GART_BUFFER_OFFSET,
+ &screen->gart_buffer_offset);
+
+ if (ret) {
+ FREE( screen );
+ fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret);
+ return NULL;
+ }
+
+ ret = radeonGetParam(sPriv, RADEON_PARAM_GART_BASE,
+ &screen->gart_base);
+ if (ret) {
+ FREE( screen );
+ fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BASE): %d\n", ret);
+ return NULL;
+ }
+
+ ret = radeonGetParam(sPriv, RADEON_PARAM_IRQ_NR,
+ &screen->irq);
+ if (ret) {
+ FREE( screen );
+ fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_IRQ_NR): %d\n", ret);
+ return NULL;
+ }
+ screen->drmSupportsCubeMapsR200 = (sPriv->drm_version.minor >= 7);
+ screen->drmSupportsBlendColor = (sPriv->drm_version.minor >= 11);
+ screen->drmSupportsTriPerf = (sPriv->drm_version.minor >= 16);
+ screen->drmSupportsFragShader = (sPriv->drm_version.minor >= 18);
+ screen->drmSupportsPointSprites = (sPriv->drm_version.minor >= 13);
+ screen->drmSupportsCubeMapsR100 = (sPriv->drm_version.minor >= 15);
+ screen->drmSupportsVertexProgram = (sPriv->drm_version.minor >= 25);
+ screen->drmSupportsOcclusionQueries = (sPriv->drm_version.minor >= 30);
+ }
+
+ ret = radeon_set_screen_flags(screen, dri_priv->deviceID);
+ if (ret == -1)
+ return NULL;
+
+ screen->mmio.handle = dri_priv->registerHandle;
+ screen->mmio.size = dri_priv->registerSize;
+ if ( drmMap( sPriv->fd,
+ screen->mmio.handle,
+ screen->mmio.size,
+ &screen->mmio.map ) ) {
+ FREE( screen );
+ __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ );
+ return NULL;
+ }
+
+ RADEONMMIO = screen->mmio.map;
+
+ screen->status.handle = dri_priv->statusHandle;
+ screen->status.size = dri_priv->statusSize;
+ if ( drmMap( sPriv->fd,
+ screen->status.handle,
+ screen->status.size,
+ &screen->status.map ) ) {
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ FREE( screen );
+ __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
+ return NULL;
+ }
+ if (screen->chip_family < CHIP_FAMILY_R600)
+ screen->scratch = (__volatile__ uint32_t *)
+ ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
+ else
+ screen->scratch = (__volatile__ uint32_t *)
+ ((GLubyte *)screen->status.map + R600_SCRATCH_REG_OFFSET);
+
+ screen->buffers = drmMapBufs( sPriv->fd );
+ if ( !screen->buffers ) {
+ drmUnmap( screen->status.map, screen->status.size );
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ FREE( screen );
+ __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__ );
+ return NULL;
+ }
+
+ if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
+ screen->gartTextures.handle = dri_priv->gartTexHandle;
+ screen->gartTextures.size = dri_priv->gartTexMapSize;
+ if ( drmMap( sPriv->fd,
+ screen->gartTextures.handle,
+ screen->gartTextures.size,
+ (drmAddressPtr)&screen->gartTextures.map ) ) {
+ drmUnmapBufs( screen->buffers );
+ drmUnmap( screen->status.map, screen->status.size );
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ FREE( screen );
+ __driUtilMessage("%s: drmMap failed for GART texture area\n", __FUNCTION__);
+ return NULL;
+ }
+
+ screen->gart_texture_offset = dri_priv->gartTexOffset + screen->gart_base;
+ }
+
if ((screen->chip_family == CHIP_FAMILY_R350 || screen->chip_family == CHIP_FAMILY_R300) &&
sPriv->ddx_version.minor < 2) {
fprintf(stderr, "xf86-video-ati-6.6.2 or newer needed for Radeon 9500/9700/9800 cards.\n");
@@ -823,35 +1063,57 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
}
if (getenv("R300_NO_TCL"))
- screen->chip_flags &= ~RADEON_CHIPSET_TCL;
+ screen->chip_flags &= ~RADEON_CHIPSET_TCL;
if (screen->chip_family <= CHIP_FAMILY_RS200)
- screen->chip_flags |= RADEON_CLASS_R100;
+ screen->chip_flags |= RADEON_CLASS_R100;
else if (screen->chip_family <= CHIP_FAMILY_RV280)
- screen->chip_flags |= RADEON_CLASS_R200;
+ screen->chip_flags |= RADEON_CLASS_R200;
+ else if (screen->chip_family <= CHIP_FAMILY_RV570)
+ screen->chip_flags |= RADEON_CLASS_R300;
else
- screen->chip_flags |= RADEON_CLASS_R300;
+ screen->chip_flags |= RADEON_CLASS_R600;
screen->cpp = dri_priv->bpp / 8;
screen->AGPMode = dri_priv->AGPMode;
- ret = radeonGetParam( sPriv->fd, RADEON_PARAM_FB_LOCATION,
- &temp);
- if (ret) {
- if (screen->chip_family < CHIP_FAMILY_RS690)
- screen->fbLocation = ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff) << 16;
- else {
- FREE( screen );
- fprintf(stderr, "Unable to get fb location need newer drm\n");
- return NULL;
+ ret = radeonGetParam(sPriv, RADEON_PARAM_FB_LOCATION, &temp);
+
+ /* +r6/r7 */
+ if(screen->chip_family >= CHIP_FAMILY_R600)
+ {
+ if (ret)
+ {
+ FREE( screen );
+ fprintf(stderr, "Unable to get fb location need newer drm\n");
+ return NULL;
}
- } else {
- screen->fbLocation = (temp & 0xffff) << 16;
+ else
+ {
+ screen->fbLocation = (temp & 0xffff) << 24;
+ }
+ }
+ else
+ {
+ if (ret)
+ {
+ if (screen->chip_family < CHIP_FAMILY_RS600 && !screen->kernel_mm)
+ screen->fbLocation = ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff) << 16;
+ else
+ {
+ FREE( screen );
+ fprintf(stderr, "Unable to get fb location need newer drm\n");
+ return NULL;
+ }
+ }
+ else
+ {
+ screen->fbLocation = (temp & 0xffff) << 16;
+ }
}
- if (screen->chip_family >= CHIP_FAMILY_RV515) {
- ret = radeonGetParam( sPriv->fd, RADEON_PARAM_NUM_GB_PIPES,
- &temp);
+ if (IS_R300_CLASS(screen)) {
+ ret = radeonGetParam(sPriv, RADEON_PARAM_NUM_GB_PIPES, &temp);
if (ret) {
fprintf(stderr, "Unable to get num_pipes, need newer drm\n");
switch (screen->chip_family) {
@@ -877,6 +1139,26 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
} else {
screen->num_gb_pipes = temp;
}
+
+ /* pipe overrides */
+ switch (dri_priv->deviceID) {
+ case PCI_CHIP_R300_AD: /* 9500 with 1 quadpipe verified by: Reid Linnemann <lreid@cs.okstate.edu> */
+ case PCI_CHIP_RV410_5E4C: /* RV410 SE only have 1 quadpipe */
+ case PCI_CHIP_RV410_5E4F: /* RV410 SE only have 1 quadpipe */
+ screen->num_gb_pipes = 1;
+ break;
+ default:
+ break;
+ }
+
+ if ( sPriv->drm_version.minor >= 31 ) {
+ ret = radeonGetParam(sPriv, RADEON_PARAM_NUM_Z_PIPES, &temp);
+ if (ret)
+ screen->num_z_pipes = 2;
+ else
+ screen->num_z_pipes = temp;
+ } else
+ screen->num_z_pipes = 2;
}
if ( sPriv->drm_version.minor >= 10 ) {
@@ -946,7 +1228,7 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
if (IS_R200_CLASS(screen))
- screen->extensions[i++] = &r200AllocateExtension.base;
+ screen->extensions[i++] = &r200AllocateExtension.base;
screen->extensions[i++] = &r200texOffsetExtension.base;
#endif
@@ -955,11 +1237,173 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
screen->extensions[i++] = &r300texOffsetExtension.base;
#endif
+#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R600)
+ screen->extensions[i++] = &r600texOffsetExtension.base;
+#endif
+
screen->extensions[i++] = NULL;
sPriv->extensions = screen->extensions;
screen->driScreen = sPriv;
screen->sarea_priv_offset = dri_priv->sarea_priv_offset;
+ screen->sarea = (drm_radeon_sarea_t *) ((GLubyte *) sPriv->pSAREA +
+ screen->sarea_priv_offset);
+
+ screen->bom = radeon_bo_manager_legacy_ctor(screen);
+ if (screen->bom == NULL) {
+ free(screen);
+ return NULL;
+ }
+
+ return screen;
+}
+
+static radeonScreenPtr
+radeonCreateScreen2(__DRIscreenPrivate *sPriv)
+{
+ radeonScreenPtr screen;
+ int i;
+ int ret;
+ uint32_t device_id = 0;
+ uint32_t temp = 0;
+
+ /* Allocate the private area */
+ screen = (radeonScreenPtr) CALLOC( sizeof(*screen) );
+ if ( !screen ) {
+ __driUtilMessage("%s: Could not allocate memory for screen structure",
+ __FUNCTION__);
+ fprintf(stderr, "leaving here\n");
+ return NULL;
+ }
+
+ radeon_init_debug();
+
+ /* parse information in __driConfigOptions */
+ driParseOptionInfo (&screen->optionCache,
+ __driConfigOptions, __driNConfigOptions);
+
+ screen->kernel_mm = 1;
+ screen->chip_flags = 0;
+
+ /* if we have kms we can support all of these */
+ screen->drmSupportsCubeMapsR200 = 1;
+ screen->drmSupportsBlendColor = 1;
+ screen->drmSupportsTriPerf = 1;
+ screen->drmSupportsFragShader = 1;
+ screen->drmSupportsPointSprites = 1;
+ screen->drmSupportsCubeMapsR100 = 1;
+ screen->drmSupportsVertexProgram = 1;
+ screen->drmSupportsOcclusionQueries = 1;
+ screen->irq = 1;
+
+ ret = radeonGetParam(sPriv, RADEON_PARAM_DEVICE_ID, &device_id);
+ if (ret) {
+ FREE( screen );
+ fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_DEVICE_ID): %d\n", ret);
+ return NULL;
+ }
+
+ ret = radeon_set_screen_flags(screen, device_id);
+ if (ret == -1)
+ return NULL;
+
+ if (getenv("R300_NO_TCL"))
+ screen->chip_flags &= ~RADEON_CHIPSET_TCL;
+
+ if (screen->chip_family <= CHIP_FAMILY_RS200)
+ screen->chip_flags |= RADEON_CLASS_R100;
+ else if (screen->chip_family <= CHIP_FAMILY_RV280)
+ screen->chip_flags |= RADEON_CLASS_R200;
+ else if (screen->chip_family <= CHIP_FAMILY_RV570)
+ screen->chip_flags |= RADEON_CLASS_R300;
+ else
+ screen->chip_flags |= RADEON_CLASS_R600;
+
+ if (IS_R300_CLASS(screen)) {
+ ret = radeonGetParam(sPriv, RADEON_PARAM_NUM_GB_PIPES, &temp);
+ if (ret) {
+ fprintf(stderr, "Unable to get num_pipes, need newer drm\n");
+ switch (screen->chip_family) {
+ case CHIP_FAMILY_R300:
+ case CHIP_FAMILY_R350:
+ screen->num_gb_pipes = 2;
+ break;
+ case CHIP_FAMILY_R420:
+ case CHIP_FAMILY_R520:
+ case CHIP_FAMILY_R580:
+ case CHIP_FAMILY_RV560:
+ case CHIP_FAMILY_RV570:
+ screen->num_gb_pipes = 4;
+ break;
+ case CHIP_FAMILY_RV350:
+ case CHIP_FAMILY_RV515:
+ case CHIP_FAMILY_RV530:
+ case CHIP_FAMILY_RV410:
+ default:
+ screen->num_gb_pipes = 1;
+ break;
+ }
+ } else {
+ screen->num_gb_pipes = temp;
+ }
+
+ /* pipe overrides */
+ switch (device_id) {
+ case PCI_CHIP_R300_AD: /* 9500 with 1 quadpipe verified by: Reid Linnemann <lreid@cs.okstate.edu> */
+ case PCI_CHIP_RV410_5E4C: /* RV410 SE only have 1 quadpipe */
+ case PCI_CHIP_RV410_5E4F: /* RV410 SE only have 1 quadpipe */
+ screen->num_gb_pipes = 1;
+ break;
+ default:
+ break;
+ }
+
+ ret = radeonGetParam(sPriv, RADEON_PARAM_NUM_Z_PIPES, &temp);
+ if (ret)
+ screen->num_z_pipes = 2;
+ else
+ screen->num_z_pipes = temp;
+
+ }
+
+ i = 0;
+ screen->extensions[i++] = &driCopySubBufferExtension.base;
+ screen->extensions[i++] = &driFrameTrackingExtension.base;
+ screen->extensions[i++] = &driReadDrawableExtension;
+
+ if ( screen->irq != 0 ) {
+ screen->extensions[i++] = &driSwapControlExtension.base;
+ screen->extensions[i++] = &driMediaStreamCounterExtension.base;
+ }
+
+#if !RADEON_COMMON
+ screen->extensions[i++] = &radeonTexBufferExtension.base;
+#endif
+
+#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
+ if (IS_R200_CLASS(screen))
+ screen->extensions[i++] = &r200AllocateExtension.base;
+
+ screen->extensions[i++] = &r200TexBufferExtension.base;
+#endif
+
+#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
+ screen->extensions[i++] = &r300TexBufferExtension.base;
+#endif
+
+#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R600)
+ screen->extensions[i++] = &r600TexBufferExtension.base;
+#endif
+
+ screen->extensions[i++] = NULL;
+ sPriv->extensions = screen->extensions;
+
+ screen->driScreen = sPriv;
+ screen->bom = radeon_bo_manager_gem_ctor(sPriv->fd);
+ if (screen->bom == NULL) {
+ free(screen);
+ return NULL;
+ }
return screen;
}
@@ -968,23 +1412,32 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
static void
radeonDestroyScreen( __DRIscreenPrivate *sPriv )
{
- radeonScreenPtr screen = (radeonScreenPtr)sPriv->private;
+ radeonScreenPtr screen = (radeonScreenPtr)sPriv->private;
- if (!screen)
- return;
+ if (!screen)
+ return;
- if ( screen->gartTextures.map ) {
- drmUnmap( screen->gartTextures.map, screen->gartTextures.size );
- }
- drmUnmapBufs( screen->buffers );
- drmUnmap( screen->status.map, screen->status.size );
- drmUnmap( screen->mmio.map, screen->mmio.size );
+ if (screen->kernel_mm) {
+#ifdef RADEON_BO_TRACK
+ radeon_tracker_print(&screen->bom->tracker, stderr);
+#endif
+ radeon_bo_manager_gem_dtor(screen->bom);
+ } else {
+ radeon_bo_manager_legacy_dtor(screen->bom);
+
+ if ( screen->gartTextures.map ) {
+ drmUnmap( screen->gartTextures.map, screen->gartTextures.size );
+ }
+ drmUnmapBufs( screen->buffers );
+ drmUnmap( screen->status.map, screen->status.size );
+ drmUnmap( screen->mmio.map, screen->mmio.size );
+ }
- /* free all option information */
- driDestroyOptionInfo (&screen->optionCache);
+ /* free all option information */
+ driDestroyOptionInfo (&screen->optionCache);
- FREE( screen );
- sPriv->private = NULL;
+ FREE( screen );
+ sPriv->private = NULL;
}
@@ -993,16 +1446,21 @@ radeonDestroyScreen( __DRIscreenPrivate *sPriv )
static GLboolean
radeonInitDriver( __DRIscreenPrivate *sPriv )
{
- sPriv->private = (void *) radeonCreateScreen( sPriv );
- if ( !sPriv->private ) {
- radeonDestroyScreen( sPriv );
- return GL_FALSE;
- }
+ if (sPriv->dri2.enabled) {
+ sPriv->private = (void *) radeonCreateScreen2( sPriv );
+ } else {
+ sPriv->private = (void *) radeonCreateScreen( sPriv );
+ }
+ if ( !sPriv->private ) {
+ radeonDestroyScreen( sPriv );
+ return GL_FALSE;
+ }
- return GL_TRUE;
+ return GL_TRUE;
}
+
/**
* Create the Mesa framebuffer and renderbuffers for a given window/drawable.
*
@@ -1015,131 +1473,112 @@ radeonCreateBuffer( __DRIscreenPrivate *driScrnPriv,
const __GLcontextModes *mesaVis,
GLboolean isPixmap )
{
- radeonScreenPtr screen = (radeonScreenPtr) driScrnPriv->private;
+ radeonScreenPtr screen = (radeonScreenPtr) driScrnPriv->private;
- if (isPixmap) {
+ const GLboolean swDepth = GL_FALSE;
+ const GLboolean swAlpha = GL_FALSE;
+ const GLboolean swAccum = mesaVis->accumRedBits > 0;
+ const GLboolean swStencil = mesaVis->stencilBits > 0 &&
+ mesaVis->depthBits != 24;
+ GLenum rgbFormat;
+ struct radeon_framebuffer *rfb;
+
+ if (isPixmap)
return GL_FALSE; /* not implemented */
- }
- else {
- const GLboolean swDepth = GL_FALSE;
- const GLboolean swAlpha = GL_FALSE;
- const GLboolean swAccum = mesaVis->accumRedBits > 0;
- const GLboolean swStencil = mesaVis->stencilBits > 0 &&
- mesaVis->depthBits != 24;
- struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
-
- /* front color renderbuffer */
- {
- driRenderbuffer *frontRb
- = driNewRenderbuffer(GL_RGBA,
- driScrnPriv->pFB + screen->frontOffset,
- screen->cpp,
- screen->frontOffset, screen->frontPitch,
- driDrawPriv);
- radeonSetSpanFunctions(frontRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
- }
- /* back color renderbuffer */
- if (mesaVis->doubleBufferMode) {
- driRenderbuffer *backRb
- = driNewRenderbuffer(GL_RGBA,
- driScrnPriv->pFB + screen->backOffset,
- screen->cpp,
- screen->backOffset, screen->backPitch,
- driDrawPriv);
- radeonSetSpanFunctions(backRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
- }
+ rfb = CALLOC_STRUCT(radeon_framebuffer);
+ if (!rfb)
+ return GL_FALSE;
- /* depth renderbuffer */
- if (mesaVis->depthBits == 16) {
- driRenderbuffer *depthRb
- = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
- driScrnPriv->pFB + screen->depthOffset,
- screen->cpp,
- screen->depthOffset, screen->depthPitch,
- driDrawPriv);
- radeonSetSpanFunctions(depthRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
- depthRb->depthHasSurface = screen->depthHasSurface;
- }
- else if (mesaVis->depthBits == 24) {
- driRenderbuffer *depthRb
- = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
- driScrnPriv->pFB + screen->depthOffset,
- screen->cpp,
- screen->depthOffset, screen->depthPitch,
- driDrawPriv);
- radeonSetSpanFunctions(depthRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
- depthRb->depthHasSurface = screen->depthHasSurface;
- }
+ _mesa_initialize_framebuffer(&rfb->base, mesaVis);
+
+ if (mesaVis->redBits == 5)
+ rgbFormat = GL_RGB5;
+ else if (mesaVis->alphaBits == 0)
+ rgbFormat = GL_RGB8;
+ else
+ rgbFormat = GL_RGBA8;
+
+ /* front color renderbuffer */
+ rfb->color_rb[0] = radeon_create_renderbuffer(rgbFormat, driDrawPriv);
+ _mesa_add_renderbuffer(&rfb->base, BUFFER_FRONT_LEFT, &rfb->color_rb[0]->base);
+ rfb->color_rb[0]->has_surface = 1;
+
+ /* back color renderbuffer */
+ if (mesaVis->doubleBufferMode) {
+ rfb->color_rb[1] = radeon_create_renderbuffer(rgbFormat, driDrawPriv);
+ _mesa_add_renderbuffer(&rfb->base, BUFFER_BACK_LEFT, &rfb->color_rb[1]->base);
+ rfb->color_rb[1]->has_surface = 1;
+ }
- /* stencil renderbuffer */
- if (mesaVis->stencilBits > 0 && !swStencil) {
- driRenderbuffer *stencilRb
- = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
- driScrnPriv->pFB + screen->depthOffset,
- screen->cpp,
- screen->depthOffset, screen->depthPitch,
- driDrawPriv);
- radeonSetSpanFunctions(stencilRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
- stencilRb->depthHasSurface = screen->depthHasSurface;
+ if (mesaVis->depthBits == 24) {
+ if (mesaVis->stencilBits == 8) {
+ struct radeon_renderbuffer *depthStencilRb = radeon_create_renderbuffer(GL_DEPTH24_STENCIL8_EXT, driDrawPriv);
+ _mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depthStencilRb->base);
+ _mesa_add_renderbuffer(&rfb->base, BUFFER_STENCIL, &depthStencilRb->base);
+ depthStencilRb->has_surface = screen->depthHasSurface;
+ } else {
+ /* depth renderbuffer */
+ struct radeon_renderbuffer *depth = radeon_create_renderbuffer(GL_DEPTH_COMPONENT24, driDrawPriv);
+ _mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depth->base);
+ depth->has_surface = screen->depthHasSurface;
}
+ } else if (mesaVis->depthBits == 16) {
+ /* just 16-bit depth buffer, no hw stencil */
+ struct radeon_renderbuffer *depth = radeon_create_renderbuffer(GL_DEPTH_COMPONENT16, driDrawPriv);
+ _mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depth->base);
+ depth->has_surface = screen->depthHasSurface;
+ }
- _mesa_add_soft_renderbuffers(fb,
- GL_FALSE, /* color */
- swDepth,
- swStencil,
- swAccum,
- swAlpha,
- GL_FALSE /* aux */);
- driDrawPriv->driverPrivate = (void *) fb;
+ _mesa_add_soft_renderbuffers(&rfb->base,
+ GL_FALSE, /* color */
+ swDepth,
+ swStencil,
+ swAccum,
+ swAlpha,
+ GL_FALSE /* aux */);
+ driDrawPriv->driverPrivate = (void *) rfb;
- return (driDrawPriv->driverPrivate != NULL);
- }
+ return (driDrawPriv->driverPrivate != NULL);
}
-static void
-radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
-{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
-}
-
-#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
-/**
- * Choose the appropriate CreateContext function based on the chipset.
- * Eventually, all drivers will go through this process.
- */
-static GLboolean radeonCreateContext(const __GLcontextModes * glVisual,
- __DRIcontextPrivate * driContextPriv,
- void *sharedContextPriv)
+static void radeon_cleanup_renderbuffers(struct radeon_framebuffer *rfb)
{
- __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
- radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
+ struct radeon_renderbuffer *rb;
- if (IS_R300_CLASS(screen))
- return r300CreateContext(glVisual, driContextPriv, sharedContextPriv);
- return GL_FALSE;
+ rb = rfb->color_rb[0];
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
+ rb = rfb->color_rb[1];
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
+ rb = radeon_get_renderbuffer(&rfb->base, BUFFER_DEPTH);
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
}
-/**
- * Choose the appropriate DestroyContext function based on the chipset.
- */
-static void radeonDestroyContext(__DRIcontextPrivate * driContextPriv)
+void
+radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
-
- if (IS_R300_CLASS(radeon->radeonScreen))
- return r300DestroyContext(driContextPriv);
+ struct radeon_framebuffer *rfb;
+ if (!driDrawPriv)
+ return;
+
+ rfb = (void*)driDrawPriv->driverPrivate;
+ if (!rfb)
+ return;
+ radeon_cleanup_renderbuffers(rfb);
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
-#endif
-
/**
* This is the driver specific part of the createNewScreen entry point.
*
@@ -1165,6 +1604,11 @@ radeonInitScreen(__DRIscreenPrivate *psp)
static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 };
static const __DRIversion dri_expected = { 4, 0, 0 };
static const __DRIversion drm_expected = { 1, 24, 0 };
+#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R600)
+ static const char *driver_name = "R600";
+ static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 };
+ static const __DRIversion dri_expected = { 4, 0, 0 };
+ static const __DRIversion drm_expected = { 1, 24, 0 };
#endif
RADEONDRIPtr dri_priv = (RADEONDRIPtr) psp->pDevPriv;
@@ -1192,18 +1636,112 @@ radeonInitScreen(__DRIscreenPrivate *psp)
driInitSingleExtension( NULL, NV_vp_extension );
driInitSingleExtension( NULL, ATI_fs_extension );
driInitExtensions( NULL, point_extensions, GL_FALSE );
+#elif (defined(RADEON_COMMON_FOR_R300) || defined(RADEON_COMMON_FOR_R600))
+ driInitSingleExtension( NULL, gl_20_extension );
#endif
if (!radeonInitDriver(psp))
return NULL;
+ /* for now fill in all modes */
return radeonFillInModes( psp,
dri_priv->bpp,
(dri_priv->bpp == 16) ? 16 : 24,
- (dri_priv->bpp == 16) ? 0 : 8,
- (dri_priv->backOffset != dri_priv->depthOffset) );
+ (dri_priv->bpp == 16) ? 0 : 8, 1);
}
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+/**
+ * This is the driver specific part of the createNewScreen entry point.
+ * Called when using DRI2.
+ *
+ * \return the __GLcontextModes supported by this driver
+ */
+static const
+__DRIconfig **radeonInitScreen2(__DRIscreenPrivate *psp)
+{
+ GLenum fb_format[3];
+ GLenum fb_type[3];
+ /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+ * support pageflipping at all.
+ */
+ static const GLenum back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML, /*, GLX_SWAP_COPY_OML*/
+ };
+ uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1];
+ int color;
+ __DRIconfig **configs = NULL;
+
+ /* Calling driInitExtensions here, with a NULL context pointer,
+ * does not actually enable the extensions. It just makes sure
+ * that all the dispatch offsets for all the extensions that
+ * *might* be enables are known. This is needed because the
+ * dispatch offsets need to be known when _mesa_context_create
+ * is called, but we can't enable the extensions until we have a
+ * context pointer.
+ *
+ * Hello chicken. Hello egg. How are you two today?
+ */
+ driInitExtensions( NULL, card_extensions, GL_FALSE );
+ driInitExtensions( NULL, mm_extensions, GL_FALSE );
+#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
+ driInitExtensions( NULL, blend_extensions, GL_FALSE );
+ driInitSingleExtension( NULL, ARB_vp_extension );
+ driInitSingleExtension( NULL, NV_vp_extension );
+ driInitSingleExtension( NULL, ATI_fs_extension );
+ driInitExtensions( NULL, point_extensions, GL_FALSE );
+#elif (defined(RADEON_COMMON_FOR_R300) || defined(RADEON_COMMON_FOR_R600))
+ driInitSingleExtension( NULL, gl_20_extension );
+#endif
+
+ if (!radeonInitDriver(psp)) {
+ return NULL;
+ }
+ depth_bits[0] = 0;
+ stencil_bits[0] = 0;
+ depth_bits[1] = 16;
+ stencil_bits[1] = 0;
+ depth_bits[2] = 24;
+ stencil_bits[2] = 0;
+ depth_bits[3] = 24;
+ stencil_bits[3] = 8;
+
+ msaa_samples_array[0] = 0;
+
+ fb_format[0] = GL_RGB;
+ fb_type[0] = GL_UNSIGNED_SHORT_5_6_5;
+
+ fb_format[1] = GL_BGR;
+ fb_type[1] = GL_UNSIGNED_INT_8_8_8_8_REV;
+
+ fb_format[2] = GL_BGRA;
+ fb_type[2] = GL_UNSIGNED_INT_8_8_8_8_REV;
+
+ for (color = 0; color < ARRAY_SIZE(fb_format); color++) {
+ __DRIconfig **new_configs;
+
+ new_configs = driCreateConfigs(fb_format[color], fb_type[color],
+ depth_bits,
+ stencil_bits,
+ ARRAY_SIZE(depth_bits),
+ back_buffer_modes,
+ ARRAY_SIZE(back_buffer_modes),
+ msaa_samples_array,
+ ARRAY_SIZE(msaa_samples_array));
+ if (configs == NULL)
+ configs = new_configs;
+ else
+ configs = driConcatConfigs(configs, new_configs);
+ }
+
+ if (configs == NULL) {
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+ __LINE__);
+ return NULL;
+ }
+
+ return (const __DRIconfig **)configs;
+}
/**
* Get information about previous buffer swaps.
@@ -1211,36 +1749,42 @@ radeonInitScreen(__DRIscreenPrivate *psp)
static int
getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
{
-#if !RADEON_COMMON || (RADEON_COMMON && defined(RADEON_COMMON_FOR_R300))
- radeonContextPtr rmesa;
-#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
- r200ContextPtr rmesa;
-#endif
+ struct radeon_framebuffer *rfb;
- if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
- || (dPriv->driContextPriv->driverPrivate == NULL)
- || (sInfo == NULL) ) {
- return -1;
+ if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
+ || (dPriv->driContextPriv->driverPrivate == NULL)
+ || (sInfo == NULL) ) {
+ return -1;
}
- rmesa = dPriv->driContextPriv->driverPrivate;
- sInfo->swap_count = rmesa->swap_count;
- sInfo->swap_ust = rmesa->swap_ust;
- sInfo->swap_missed_count = rmesa->swap_missed_count;
+ rfb = dPriv->driverPrivate;
+ sInfo->swap_count = rfb->swap_count;
+ sInfo->swap_ust = rfb->swap_ust;
+ sInfo->swap_missed_count = rfb->swap_missed_count;
sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
- ? driCalculateSwapUsage( dPriv, 0, rmesa->swap_missed_ust )
+ ? driCalculateSwapUsage( dPriv, 0, rfb->swap_missed_ust )
: 0.0;
return 0;
}
-#if !RADEON_COMMON || (RADEON_COMMON && defined(RADEON_COMMON_FOR_R300))
const struct __DriverAPIRec driDriverAPI = {
.InitScreen = radeonInitScreen,
.DestroyScreen = radeonDestroyScreen,
- .CreateContext = radeonCreateContext,
+#if RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
+ .CreateContext = r200CreateContext,
+ .DestroyContext = r200DestroyContext,
+#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R600)
+ .CreateContext = r600CreateContext,
+ .DestroyContext = radeonDestroyContext,
+#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
+ .CreateContext = r300CreateContext,
.DestroyContext = radeonDestroyContext,
+#else
+ .CreateContext = r100CreateContext,
+ .DestroyContext = radeonDestroyContext,
+#endif
.CreateBuffer = radeonCreateBuffer,
.DestroyBuffer = radeonDestroyBuffer,
.SwapBuffers = radeonSwapBuffers,
@@ -1252,23 +1796,7 @@ const struct __DriverAPIRec driDriverAPI = {
.WaitForSBC = NULL,
.SwapBuffersMSC = NULL,
.CopySubBuffer = radeonCopySubBuffer,
+ /* DRI2 */
+ .InitScreen2 = radeonInitScreen2,
};
-#else
-const struct __DriverAPIRec driDriverAPI = {
- .InitScreen = radeonInitScreen,
- .DestroyScreen = radeonDestroyScreen,
- .CreateContext = r200CreateContext,
- .DestroyContext = r200DestroyContext,
- .CreateBuffer = radeonCreateBuffer,
- .DestroyBuffer = radeonDestroyBuffer,
- .SwapBuffers = r200SwapBuffers,
- .MakeCurrent = r200MakeCurrent,
- .UnbindContext = r200UnbindContext,
- .GetSwapInfo = getSwapInfo,
- .GetDrawableMSC = driDrawableGetMSC32,
- .WaitForMSC = driWaitForMSC32,
- .WaitForSBC = NULL,
- .SwapBuffersMSC = NULL,
- .CopySubBuffer = r200CopySubBuffer,
-};
-#endif
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.h b/src/mesa/drivers/dri/radeon/radeon_screen.h
index b84c70bfae..15744e8828 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.h
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.h
@@ -54,11 +54,12 @@ typedef struct {
drmAddress map; /* Mapping of the DRM region */
} radeonRegionRec, *radeonRegionPtr;
-typedef struct {
+typedef struct radeon_screen {
int chip_family;
int chip_flags;
int cpp;
int card_type;
+ int device_id; /* PCI ID */
int AGPMode;
unsigned int irq; /* IRQ number (0 means none) */
@@ -98,14 +99,19 @@ typedef struct {
GLboolean drmSupportsPointSprites; /* need radeon kernel module >= 1.13 */
GLboolean drmSupportsCubeMapsR100; /* need radeon kernel module >= 1.15 */
GLboolean drmSupportsVertexProgram; /* need radeon kernel module >= 1.25 */
+ GLboolean drmSupportsOcclusionQueries; /* need radeon kernel module >= 1.30 */
GLboolean depthHasSurface;
/* Configuration cache with default values for all contexts */
driOptionCache optionCache;
- const __DRIextension *extensions[8];
+ const __DRIextension *extensions[16];
int num_gb_pipes;
+ int num_z_pipes;
+ int kernel_mm;
+ drm_radeon_sarea_t *sarea; /* Private SAREA data */
+ struct radeon_bo_manager *bom;
} radeonScreenRec, *radeonScreenPtr;
#define IS_R100_CLASS(screen) \
@@ -114,5 +120,8 @@ typedef struct {
((screen->chip_flags & RADEON_CLASS_MASK) == RADEON_CLASS_R200)
#define IS_R300_CLASS(screen) \
((screen->chip_flags & RADEON_CLASS_MASK) == RADEON_CLASS_R300)
+#define IS_R600_CLASS(screen) \
+ ((screen->chip_flags & RADEON_CLASS_MASK) == RADEON_CLASS_R600)
+extern void radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv);
#endif /* __RADEON_SCREEN_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_span.c b/src/mesa/drivers/dri/radeon/radeon_span.c
index 12051ff1c8..4e100d854e 100644
--- a/src/mesa/drivers/dri/radeon/radeon_span.c
+++ b/src/mesa/drivers/dri/radeon/radeon_span.c
@@ -43,46 +43,222 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/glheader.h"
#include "swrast/swrast.h"
-#include "radeon_context.h"
-#include "radeon_ioctl.h"
-#include "radeon_state.h"
+#include "radeon_common.h"
+#include "radeon_lock.h"
#include "radeon_span.h"
-#include "radeon_tex.h"
-
-#include "drirenderbuffer.h"
#define DBG 0
+static void radeonSetSpanFunctions(struct radeon_renderbuffer *rrb);
+
+
+/* r200 depth buffer is always tiled - this is the formula
+ according to the docs unless I typo'ed in it
+*/
+#if defined(RADEON_COMMON_FOR_R200)
+static GLubyte *r200_depth_2byte(const struct radeon_renderbuffer * rrb,
+ GLint x, GLint y)
+{
+ GLubyte *ptr = rrb->bo->ptr;
+ GLint offset;
+ if (rrb->has_surface) {
+ offset = x * rrb->cpp + y * rrb->pitch;
+ } else {
+ GLuint b;
+ offset = 0;
+ b = (((y >> 4) * (rrb->pitch >> 8) + (x >> 6)));
+ offset += (b >> 1) << 12;
+ offset += (((rrb->pitch >> 8) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11;
+ offset += ((y >> 2) & 0x3) << 9;
+ offset += ((x >> 3) & 0x1) << 8;
+ offset += ((x >> 4) & 0x3) << 6;
+ offset += ((x >> 2) & 0x1) << 5;
+ offset += ((y >> 1) & 0x1) << 4;
+ offset += ((x >> 1) & 0x1) << 3;
+ offset += (y & 0x1) << 2;
+ offset += (x & 0x1) << 1;
+ }
+ return &ptr[offset];
+}
+
+static GLubyte *r200_depth_4byte(const struct radeon_renderbuffer * rrb,
+ GLint x, GLint y)
+{
+ GLubyte *ptr = rrb->bo->ptr;
+ GLint offset;
+ if (rrb->has_surface) {
+ offset = x * rrb->cpp + y * rrb->pitch;
+ } else {
+ GLuint b;
+ offset = 0;
+ b = (((y & 0x7ff) >> 4) * (rrb->pitch >> 7) + (x >> 5));
+ offset += (b >> 1) << 12;
+ offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11;
+ offset += ((y >> 2) & 0x3) << 9;
+ offset += ((x >> 2) & 0x1) << 8;
+ offset += ((x >> 3) & 0x3) << 6;
+ offset += ((y >> 1) & 0x1) << 5;
+ offset += ((x >> 1) & 0x1) << 4;
+ offset += (y & 0x1) << 3;
+ offset += (x & 0x1) << 2;
+ }
+ return &ptr[offset];
+}
+#endif
+
+/* radeon tiling on r300-r500 has 4 states,
+ macro-linear/micro-linear
+ macro-linear/micro-tiled
+ macro-tiled /micro-linear
+ macro-tiled /micro-tiled
+ 1 byte surface
+ 2 byte surface - two types - we only provide 8x2 microtiling
+ 4 byte surface
+ 8/16 byte (unused)
+*/
+static GLubyte *radeon_ptr_4byte(const struct radeon_renderbuffer * rrb,
+ GLint x, GLint y)
+{
+ GLubyte *ptr = rrb->bo->ptr;
+ uint32_t mask = RADEON_BO_FLAGS_MACRO_TILE | RADEON_BO_FLAGS_MICRO_TILE;
+ GLint offset;
+
+ if (rrb->has_surface || !(rrb->bo->flags & mask)) {
+ offset = x * rrb->cpp + y * rrb->pitch;
+ } else {
+ offset = 0;
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE) {
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MICRO_TILE) {
+ offset = ((y >> 4) * (rrb->pitch >> 7) + (x >> 5)) << 11;
+ offset += (((y >> 3) ^ (x >> 5)) & 0x1) << 10;
+ offset += (((y >> 4) ^ (x >> 4)) & 0x1) << 9;
+ offset += (((y >> 2) ^ (x >> 4)) & 0x1) << 8;
+ offset += (((y >> 3) ^ (x >> 3)) & 0x1) << 7;
+ offset += ((y >> 1) & 0x1) << 6;
+ offset += ((x >> 2) & 0x1) << 5;
+ offset += (y & 1) << 4;
+ offset += (x & 3) << 2;
+ } else {
+ offset = ((y >> 3) * (rrb->pitch >> 8) + (x >> 6)) << 11;
+ offset += (((y >> 2) ^ (x >> 6)) & 0x1) << 10;
+ offset += (((y >> 3) ^ (x >> 5)) & 0x1) << 9;
+ offset += (((y >> 1) ^ (x >> 5)) & 0x1) << 8;
+ offset += (((y >> 2) ^ (x >> 4)) & 0x1) << 7;
+ offset += (y & 1) << 6;
+ offset += (x & 15) << 2;
+ }
+ } else {
+ offset = ((y >> 1) * (rrb->pitch >> 4) + (x >> 2)) << 5;
+ offset += (y & 1) << 4;
+ offset += (x & 3) << 2;
+ }
+ }
+ return &ptr[offset];
+}
+
+static GLubyte *radeon_ptr_2byte_8x2(const struct radeon_renderbuffer * rrb,
+ GLint x, GLint y)
+{
+ GLubyte *ptr = rrb->bo->ptr;
+ uint32_t mask = RADEON_BO_FLAGS_MACRO_TILE | RADEON_BO_FLAGS_MICRO_TILE;
+ GLint offset;
+
+ if (rrb->has_surface || !(rrb->bo->flags & mask)) {
+ offset = x * rrb->cpp + y * rrb->pitch;
+ } else {
+ offset = 0;
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE) {
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MICRO_TILE) {
+ offset = ((y >> 4) * (rrb->pitch >> 7) + (x >> 6)) << 11;
+ offset += (((y >> 3) ^ (x >> 6)) & 0x1) << 10;
+ offset += (((y >> 4) ^ (x >> 5)) & 0x1) << 9;
+ offset += (((y >> 2) ^ (x >> 5)) & 0x1) << 8;
+ offset += (((y >> 3) ^ (x >> 4)) & 0x1) << 7;
+ offset += ((y >> 1) & 0x1) << 6;
+ offset += ((x >> 3) & 0x1) << 5;
+ offset += (y & 1) << 4;
+ offset += (x & 3) << 2;
+ } else {
+ offset = ((y >> 3) * (rrb->pitch >> 8) + (x >> 7)) << 11;
+ offset += (((y >> 2) ^ (x >> 7)) & 0x1) << 10;
+ offset += (((y >> 3) ^ (x >> 6)) & 0x1) << 9;
+ offset += (((y >> 1) ^ (x >> 6)) & 0x1) << 8;
+ offset += (((y >> 2) ^ (x >> 5)) & 0x1) << 7;
+ offset += (y & 1) << 6;
+ offset += ((x >> 4) & 0x1) << 5;
+ offset += (x & 15) << 2;
+ }
+ } else {
+ offset = ((y >> 1) * (rrb->pitch >> 4) + (x >> 3)) << 5;
+ offset += (y & 0x1) << 4;
+ offset += (x & 0x7) << 1;
+ }
+ }
+ return &ptr[offset];
+}
+
+#ifndef COMPILE_R300
+static uint32_t
+z24s8_to_s8z24(uint32_t val)
+{
+ return (val << 24) | (val >> 8);
+}
+
+static uint32_t
+s8z24_to_z24s8(uint32_t val)
+{
+ return (val >> 24) | (val << 8);
+}
+#endif
+
/*
* Note that all information needed to access pixels in a renderbuffer
* should be obtained through the gl_renderbuffer parameter, not per-context
* information.
*/
#define LOCAL_VARS \
- driRenderbuffer *drb = (driRenderbuffer *) rb; \
- const __DRIdrawablePrivate *dPriv = drb->dPriv; \
- const GLuint bottom = dPriv->h - 1; \
- GLubyte *buf = (GLubyte *) drb->flippedData \
- + (dPriv->y * drb->flippedPitch + dPriv->x) * drb->cpp; \
- GLuint p; \
- (void) p;
+ struct radeon_context *radeon = RADEON_CONTEXT(ctx); \
+ struct radeon_renderbuffer *rrb = (void *) rb; \
+ const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \
+ const GLint yBias = ctx->DrawBuffer->Name ? 0 : rrb->base.Height - 1;\
+ unsigned int num_cliprects; \
+ struct drm_clip_rect *cliprects; \
+ int x_off, y_off; \
+ GLuint p; \
+ (void)p; \
+ radeon_get_cliprects(radeon, &cliprects, &num_cliprects, &x_off, &y_off);
#define LOCAL_DEPTH_VARS \
- driRenderbuffer *drb = (driRenderbuffer *) rb; \
- const __DRIdrawablePrivate *dPriv = drb->dPriv; \
- const GLuint bottom = dPriv->h - 1; \
- GLuint xo = dPriv->x; \
- GLuint yo = dPriv->y; \
- GLubyte *buf = (GLubyte *) drb->Base.Data;
+ struct radeon_context *radeon = RADEON_CONTEXT(ctx); \
+ struct radeon_renderbuffer *rrb = (void *) rb; \
+ const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \
+ const GLint yBias = ctx->DrawBuffer->Name ? 0 : rrb->base.Height - 1;\
+ unsigned int num_cliprects; \
+ struct drm_clip_rect *cliprects; \
+ int x_off, y_off; \
+ radeon_get_cliprects(radeon, &cliprects, &num_cliprects, &x_off, &y_off);
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
-#define Y_FLIP(Y) (bottom - (Y))
+#define Y_FLIP(_y) ((_y) * yScale + yBias)
#define HW_LOCK()
#define HW_UNLOCK()
+/* XXX FBO: this is identical to the macro in spantmp2.h except we get
+ * the cliprect info from the context, not the driDrawable.
+ * Move this into spantmp2.h someday.
+ */
+#define HW_CLIPLOOP() \
+ do { \
+ int _nc = num_cliprects; \
+ while ( _nc-- ) { \
+ int minx = cliprects[_nc].x1 - x_off; \
+ int miny = cliprects[_nc].y1 - y_off; \
+ int maxx = cliprects[_nc].x2 - x_off; \
+ int maxy = cliprects[_nc].y2 - y_off;
+
/* ================================================================
* Color buffer
*/
@@ -94,7 +270,41 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define TAG(x) radeon##x##_RGB565
#define TAG2(x,y) radeon##x##_RGB565##y
-#define GET_PTR(X,Y) (buf + ((Y) * drb->flippedPitch + (X)) * 2)
+#define GET_PTR(X,Y) radeon_ptr_2byte_8x2(rrb, (X) + x_off, (Y) + y_off)
+#include "spantmp2.h"
+
+/* 16 bit, ARGB1555 color spanline and pixel functions
+ */
+#define SPANTMP_PIXEL_FMT GL_BGRA
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_1_5_5_5_REV
+
+#define TAG(x) radeon##x##_ARGB1555
+#define TAG2(x,y) radeon##x##_ARGB1555##y
+#define GET_PTR(X,Y) radeon_ptr_2byte_8x2(rrb, (X) + x_off, (Y) + y_off)
+#include "spantmp2.h"
+
+/* 16 bit, RGBA4 color spanline and pixel functions
+ */
+#define SPANTMP_PIXEL_FMT GL_BGRA
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_4_4_4_4_REV
+
+#define TAG(x) radeon##x##_ARGB4444
+#define TAG2(x,y) radeon##x##_ARGB4444##y
+#define GET_PTR(X,Y) radeon_ptr_2byte_8x2(rrb, (X) + x_off, (Y) + y_off)
+#include "spantmp2.h"
+
+/* 32 bit, xRGB8888 color spanline and pixel functions
+ */
+#define SPANTMP_PIXEL_FMT GL_BGRA
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
+
+#define TAG(x) radeon##x##_xRGB8888
+#define TAG2(x,y) radeon##x##_xRGB8888##y
+#define GET_VALUE(_x, _y) ((*(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off)) | 0xff000000))
+#define PUT_VALUE(_x, _y, d) { \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \
+ *_ptr = d; \
+} while (0)
#include "spantmp2.h"
/* 32 bit, ARGB8888 color spanline and pixel functions
@@ -104,7 +314,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define TAG(x) radeon##x##_ARGB8888
#define TAG2(x,y) radeon##x##_ARGB8888##y
-#define GET_PTR(X,Y) (buf + ((Y) * drb->flippedPitch + (X)) * 4)
+#define GET_VALUE(_x, _y) (*(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off)))
+#define PUT_VALUE(_x, _y, d) { \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \
+ *_ptr = d; \
+} while (0)
#include "spantmp2.h"
/* ================================================================
@@ -121,106 +335,127 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* too...
*/
-static GLuint radeon_mba_z32(const driRenderbuffer * drb, GLint x, GLint y)
-{
- GLuint pitch = drb->pitch;
- if (drb->depthHasSurface) {
- return 4 * (x + y * pitch);
- } else {
- GLuint ba, address = 0; /* a[0..1] = 0 */
-
-#ifdef COMPILE_R300
- ba = (y / 8) * (pitch / 8) + (x / 8);
-#else
- ba = (y / 16) * (pitch / 16) + (x / 16);
-#endif
-
- address |= (x & 0x7) << 2; /* a[2..4] = x[0..2] */
- address |= (y & 0x3) << 5; /* a[5..6] = y[0..1] */
- address |= (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; /* a[7] = x[4] ^ y[2] */
- address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
-
- address |= (y & 0x8) << 7; /* a[10] = y[3] */
- address |= (((x & 0x8) << 1) ^ (y & 0x10)) << 7; /* a[11] = x[3] ^ y[4] */
- address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
-
- return address;
- }
-}
-
-static INLINE GLuint
-radeon_mba_z16(const driRenderbuffer * drb, GLint x, GLint y)
-{
- GLuint pitch = drb->pitch;
- if (drb->depthHasSurface) {
- return 2 * (x + y * pitch);
- } else {
- GLuint ba, address = 0; /* a[0] = 0 */
-
- ba = (y / 16) * (pitch / 32) + (x / 32);
-
- address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */
- address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */
- address |= (x & 0x8) << 4; /* a[7] = x[3] */
- address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */
- address |= (y & 0x8) << 7; /* a[10] = y[3] */
- address |= ((x & 0x10) ^ (y & 0x10)) << 7; /* a[11] = x[4] ^ y[4] */
- address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */
-
- return address;
- }
-}
-
/* 16-bit depth buffer functions
*/
#define VALUE_TYPE GLushort
+#if defined(RADEON_COMMON_FOR_R200)
+#define WRITE_DEPTH( _x, _y, d ) \
+ *(GLushort *)r200_depth_2byte(rrb, _x + x_off, _y + y_off) = d
+#else
#define WRITE_DEPTH( _x, _y, d ) \
- *(GLushort *)(buf + radeon_mba_z16( drb, _x + xo, _y + yo )) = d;
+ *(GLushort *)radeon_ptr_2byte_8x2(rrb, _x + x_off, _y + y_off) = d
+#endif
+#if defined(RADEON_COMMON_FOR_R200)
#define READ_DEPTH( d, _x, _y ) \
- d = *(GLushort *)(buf + radeon_mba_z16( drb, _x + xo, _y + yo ));
+ d = *(GLushort *)r200_depth_2byte(rrb, _x + x_off, _y + y_off)
+#else
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLushort *)radeon_ptr_2byte_8x2(rrb, _x + x_off, _y + y_off)
+#endif
#define TAG(x) radeon##x##_z16
#include "depthtmp.h"
-/* 24 bit depth, 8 bit stencil depthbuffer functions
+/* 24 bit depth
*
* Careful: It looks like the R300 uses ZZZS byte order while the R200
* uses SZZZ for 24 bit depth, 8 bit stencil mode.
*/
#define VALUE_TYPE GLuint
-#ifdef COMPILE_R300
+#if defined(COMPILE_R300)
#define WRITE_DEPTH( _x, _y, d ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \
+ GLuint tmp = *_ptr; \
tmp &= 0x000000ff; \
tmp |= ((d << 8) & 0xffffff00); \
- *(GLuint *)(buf + offset) = tmp; \
+ *_ptr = tmp; \
+} while (0)
+#elif defined(RADEON_COMMON_FOR_R200)
+#define WRITE_DEPTH( _x, _y, d ) \
+do { \
+ GLuint *_ptr = (GLuint*)r200_depth_4byte( rrb, _x + x_off, _y + y_off ); \
+ GLuint tmp = *_ptr; \
+ tmp &= 0xff000000; \
+ tmp |= ((d) & 0x00ffffff); \
+ *_ptr = tmp; \
} while (0)
#else
#define WRITE_DEPTH( _x, _y, d ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \
+ GLuint tmp = *_ptr; \
tmp &= 0xff000000; \
tmp |= ((d) & 0x00ffffff); \
- *(GLuint *)(buf + offset) = tmp; \
+ *_ptr = tmp; \
} while (0)
#endif
-#ifdef COMPILE_R300
+#if defined(COMPILE_R300)
#define READ_DEPTH( d, _x, _y ) \
- do { \
- d = (*(GLuint *)(buf + radeon_mba_z32( drb, _x + xo, \
- _y + yo )) & 0xffffff00) >> 8; \
+ do { \
+ d = (*(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off)) & 0xffffff00) >> 8; \
+ }while(0)
+#elif defined(RADEON_COMMON_FOR_R200)
+#define READ_DEPTH( d, _x, _y ) \
+ do { \
+ d = *(GLuint*)(r200_depth_4byte(rrb, _x + x_off, _y + y_off)) & 0x00ffffff; \
}while(0)
#else
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off)) & 0x00ffffff;
+#endif
+
+#define TAG(x) radeon##x##_z24
+#include "depthtmp.h"
+
+/* 24 bit depth, 8 bit stencil depthbuffer functions
+ * EXT_depth_stencil
+ *
+ * Careful: It looks like the R300 uses ZZZS byte order while the R200
+ * uses SZZZ for 24 bit depth, 8 bit stencil mode.
+ */
+#define VALUE_TYPE GLuint
+
+#if defined(COMPILE_R300)
+#define WRITE_DEPTH( _x, _y, d ) \
+do { \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \
+ *_ptr = d; \
+} while (0)
+#elif defined(RADEON_COMMON_FOR_R200)
+#define WRITE_DEPTH( _x, _y, d ) \
+do { \
+ GLuint *_ptr = (GLuint*)r200_depth_4byte( rrb, _x + x_off, _y + y_off ); \
+ GLuint tmp = z24s8_to_s8z24(d); \
+ *_ptr = tmp; \
+} while (0)
+#else
+#define WRITE_DEPTH( _x, _y, d ) \
+do { \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \
+ GLuint tmp = z24s8_to_s8z24(d); \
+ *_ptr = tmp; \
+} while (0)
+#endif
+
+#if defined(COMPILE_R300)
+#define READ_DEPTH( d, _x, _y ) \
+ do { \
+ d = (*(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off))); \
+ }while(0)
+#elif defined(RADEON_COMMON_FOR_R200)
#define READ_DEPTH( d, _x, _y ) \
- d = *(GLuint *)(buf + radeon_mba_z32( drb, _x + xo, \
- _y + yo )) & 0x00ffffff;
+ do { \
+ d = s8z24_to_z24s8(*(GLuint*)(r200_depth_4byte(rrb, _x + x_off, _y + y_off))); \
+ }while(0)
+#else
+#define READ_DEPTH( d, _x, _y ) do { \
+ d = s8z24_to_z24s8(*(GLuint*)(radeon_ptr_4byte(rrb, _x + x_off, _y + y_off ))); \
+ } while (0)
#endif
#define TAG(x) radeon##x##_z24_s8
@@ -235,35 +470,51 @@ do { \
#ifdef COMPILE_R300
#define WRITE_STENCIL( _x, _y, d ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte(rrb, _x + x_off, _y + y_off); \
+ GLuint tmp = *_ptr; \
tmp &= 0xffffff00; \
tmp |= (d) & 0xff; \
- *(GLuint *)(buf + offset) = tmp; \
+ *_ptr = tmp; \
+} while (0)
+#elif defined(RADEON_COMMON_FOR_R200)
+#define WRITE_STENCIL( _x, _y, d ) \
+do { \
+ GLuint *_ptr = (GLuint*)r200_depth_4byte(rrb, _x + x_off, _y + y_off); \
+ GLuint tmp = *_ptr; \
+ tmp &= 0x00ffffff; \
+ tmp |= (((d) & 0xff) << 24); \
+ *_ptr = tmp; \
} while (0)
#else
#define WRITE_STENCIL( _x, _y, d ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte(rrb, _x + x_off, _y + y_off); \
+ GLuint tmp = *_ptr; \
tmp &= 0x00ffffff; \
tmp |= (((d) & 0xff) << 24); \
- *(GLuint *)(buf + offset) = tmp; \
+ *_ptr = tmp; \
} while (0)
#endif
#ifdef COMPILE_R300
#define READ_STENCIL( d, _x, _y ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \
+ GLuint tmp = *_ptr; \
d = tmp & 0x000000ff; \
} while (0)
+#elif defined(RADEON_COMMON_FOR_R200)
+#define READ_STENCIL( d, _x, _y ) \
+do { \
+ GLuint *_ptr = (GLuint*)r200_depth_4byte( rrb, _x + x_off, _y + y_off ); \
+ GLuint tmp = *_ptr; \
+ d = (tmp & 0xff000000) >> 24; \
+} while (0)
#else
#define READ_STENCIL( d, _x, _y ) \
do { \
- GLuint offset = radeon_mba_z32( drb, _x + xo, _y + yo ); \
- GLuint tmp = *(GLuint *)(buf + offset); \
+ GLuint *_ptr = (GLuint*)radeon_ptr_4byte( rrb, _x + x_off, _y + y_off ); \
+ GLuint tmp = *_ptr; \
d = (tmp & 0xff000000) >> 24; \
} while (0)
#endif
@@ -271,29 +522,110 @@ do { \
#define TAG(x) radeon##x##_z24_s8
#include "stenciltmp.h"
-/* Move locking out to get reasonable span performance (10x better
- * than doing this in HW_LOCK above). WaitForIdle() is the main
- * culprit.
- */
+
+static void map_unmap_rb(struct gl_renderbuffer *rb, int flag)
+{
+ struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+ int r;
+
+ if (rrb == NULL || !rrb->bo)
+ return;
+
+ if (flag) {
+ if (rrb->bo->bom->funcs->bo_wait)
+ radeon_bo_wait(rrb->bo);
+ r = radeon_bo_map(rrb->bo, 1);
+ if (r) {
+ fprintf(stderr, "(%s) error(%d) mapping buffer.\n",
+ __FUNCTION__, r);
+ }
+
+ radeonSetSpanFunctions(rrb);
+ } else {
+ radeon_bo_unmap(rrb->bo);
+ rb->GetRow = NULL;
+ rb->PutRow = NULL;
+ }
+}
+
+static void
+radeon_map_unmap_buffers(GLcontext *ctx, GLboolean map)
+{
+ GLuint i, j;
+
+ /* color draw buffers */
+ for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers; j++)
+ map_unmap_rb(ctx->DrawBuffer->_ColorDrawBuffers[j], map);
+
+ /* check for render to textures */
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att =
+ ctx->DrawBuffer->Attachment + i;
+ struct gl_texture_object *tex = att->Texture;
+ if (tex) {
+ /* Render to texture. Note that a mipmapped texture need not
+ * be complete for render to texture, so we must restrict to
+ * mapping only the attached image.
+ */
+ radeon_texture_image *image = get_radeon_texture_image(tex->Image[att->CubeMapFace][att->TextureLevel]);
+ ASSERT(att->Renderbuffer);
+
+ if (map)
+ radeon_teximage_map(image, GL_TRUE);
+ else
+ radeon_teximage_unmap(image);
+ }
+ }
+
+ map_unmap_rb(ctx->ReadBuffer->_ColorReadBuffer, map);
+
+ /* depth buffer (Note wrapper!) */
+ if (ctx->DrawBuffer->_DepthBuffer)
+ map_unmap_rb(ctx->DrawBuffer->_DepthBuffer->Wrapped, map);
+
+ if (ctx->DrawBuffer->_StencilBuffer)
+ map_unmap_rb(ctx->DrawBuffer->_StencilBuffer->Wrapped, map);
+}
static void radeonSpanRenderStart(GLcontext * ctx)
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-#ifdef COMPILE_R300
- r300ContextPtr r300 = (r300ContextPtr) rmesa;
- R300_FIREVERTICES(r300);
-#else
- RADEON_FIREVERTICES(rmesa);
-#endif
- LOCK_HARDWARE(rmesa);
- radeonWaitForIdleLocked(rmesa);
+ int i;
+
+ radeon_firevertices(rmesa);
+
+ /* The locking and wait for idle should really only be needed in classic mode.
+ * In a future memory manager based implementation, this should become
+ * unnecessary due to the fact that mapping our buffers, textures, etc.
+ * should implicitly wait for any previous rendering commands that must
+ * be waited on. */
+ if (!rmesa->radeonScreen->driScreen->dri2.enabled) {
+ LOCK_HARDWARE(rmesa);
+ radeonWaitForIdleLocked(rmesa);
+ }
+
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled)
+ ctx->Driver.MapTexture(ctx, ctx->Texture.Unit[i]._Current);
+ }
+
+ radeon_map_unmap_buffers(ctx, 1);
}
static void radeonSpanRenderFinish(GLcontext * ctx)
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ int i;
_swrast_flush(ctx);
- UNLOCK_HARDWARE(rmesa);
+ if (!rmesa->radeonScreen->driScreen->dri2.enabled) {
+ UNLOCK_HARDWARE(rmesa);
+ }
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled)
+ ctx->Driver.UnmapTexture(ctx, ctx->Texture.Unit[i]._Current);
+ }
+
+ radeon_map_unmap_buffers(ctx, 0);
}
void radeonInitSpanFuncs(GLcontext * ctx)
@@ -307,20 +639,27 @@ void radeonInitSpanFuncs(GLcontext * ctx)
/**
* Plug in the Get/Put routines for the given driRenderbuffer.
*/
-void radeonSetSpanFunctions(driRenderbuffer * drb, const GLvisual * vis)
+static void radeonSetSpanFunctions(struct radeon_renderbuffer *rrb)
{
- if (drb->Base.InternalFormat == GL_RGBA) {
- if (vis->redBits == 5 && vis->greenBits == 6
- && vis->blueBits == 5) {
- radeonInitPointers_RGB565(&drb->Base);
- } else {
- radeonInitPointers_ARGB8888(&drb->Base);
- }
- } else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
- radeonInitDepthPointers_z16(&drb->Base);
- } else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
- radeonInitDepthPointers_z24_s8(&drb->Base);
- } else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
- radeonInitStencilPointers_z24_s8(&drb->Base);
+ if (rrb->base._ActualFormat == GL_RGB5) {
+ radeonInitPointers_RGB565(&rrb->base);
+ } else if (rrb->base._ActualFormat == GL_RGB8) {
+ radeonInitPointers_xRGB8888(&rrb->base);
+ } else if (rrb->base._ActualFormat == GL_RGBA8) {
+ radeonInitPointers_ARGB8888(&rrb->base);
+ } else if (rrb->base._ActualFormat == GL_RGBA4) {
+ radeonInitPointers_ARGB4444(&rrb->base);
+ } else if (rrb->base._ActualFormat == GL_RGB5_A1) {
+ radeonInitPointers_ARGB1555(&rrb->base);
+ } else if (rrb->base._ActualFormat == GL_DEPTH_COMPONENT16) {
+ radeonInitDepthPointers_z16(&rrb->base);
+ } else if (rrb->base._ActualFormat == GL_DEPTH_COMPONENT24) {
+ radeonInitDepthPointers_z24(&rrb->base);
+ } else if (rrb->base._ActualFormat == GL_DEPTH24_STENCIL8_EXT) {
+ radeonInitDepthPointers_z24_s8(&rrb->base);
+ } else if (rrb->base._ActualFormat == GL_STENCIL_INDEX8_EXT) {
+ radeonInitStencilPointers_z24_s8(&rrb->base);
+ } else {
+ fprintf(stderr, "radeonSetSpanFunctions: bad actual format: 0x%04X\n", rrb->base._ActualFormat);
}
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_span.h b/src/mesa/drivers/dri/radeon/radeon_span.h
index 9abe0864b1..ea6a2e7fb4 100644
--- a/src/mesa/drivers/dri/radeon/radeon_span.h
+++ b/src/mesa/drivers/dri/radeon/radeon_span.h
@@ -42,9 +42,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef __RADEON_SPAN_H__
#define __RADEON_SPAN_H__
-#include "drirenderbuffer.h"
-
extern void radeonInitSpanFuncs(GLcontext * ctx);
-extern void radeonSetSpanFunctions(driRenderbuffer * rb, const GLvisual * vis);
#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c
index 32bcff3360..4d0d35ee0c 100644
--- a/src/mesa/drivers/dri/radeon/radeon_state.c
+++ b/src/mesa/drivers/dri/radeon/radeon_state.c
@@ -40,6 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/state.h"
#include "main/context.h"
#include "main/framebuffer.h"
+#include "main/simple_list.h"
#include "vbo/vbo.h"
#include "tnl/tnl.h"
@@ -47,6 +48,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "swrast_setup/swrast_setup.h"
#include "radeon_context.h"
+#include "radeon_mipmap_tree.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "radeon_tcl.h"
@@ -62,7 +64,7 @@ static void radeonUpdateSpecular( GLcontext *ctx );
static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
GLubyte refByte;
@@ -106,7 +108,7 @@ static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
static void radeonBlendEquationSeparate( GLcontext *ctx,
GLenum modeRGB, GLenum modeA )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK;
GLboolean fallback = GL_FALSE;
@@ -147,8 +149,8 @@ static void radeonBlendFuncSeparate( GLcontext *ctx,
GLenum sfactorRGB, GLenum dfactorRGB,
GLenum sfactorA, GLenum dfactorA )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK);
GLboolean fallback = GL_FALSE;
@@ -257,7 +259,7 @@ static void radeonBlendFuncSeparate( GLcontext *ctx,
static void radeonDepthFunc( GLcontext *ctx, GLenum func )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK;
@@ -293,7 +295,7 @@ static void radeonDepthFunc( GLcontext *ctx, GLenum func )
static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, ctx );
if ( ctx->Depth.Mask ) {
@@ -305,16 +307,16 @@ static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
static void radeonClearDepth( GLcontext *ctx, GLclampd d )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
RADEON_DEPTH_FORMAT_MASK);
switch ( format ) {
case RADEON_DEPTH_FORMAT_16BIT_INT_Z:
- rmesa->state.depth.clear = d * 0x0000ffff;
+ rmesa->radeon.state.depth.clear = d * 0x0000ffff;
break;
case RADEON_DEPTH_FORMAT_24BIT_INT_Z:
- rmesa->state.depth.clear = d * 0x00ffffff;
+ rmesa->radeon.state.depth.clear = d * 0x00ffffff;
break;
}
}
@@ -327,7 +329,7 @@ static void radeonClearDepth( GLcontext *ctx, GLclampd d )
static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
union { int i; float f; } c, d;
GLchan col[4];
@@ -391,7 +393,7 @@ static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
rmesa->hw.fog.cmd[FOG_D] = d.i;
}
break;
- case GL_FOG_COLOR:
+ case GL_FOG_COLOR:
RADEON_STATECHANGE( rmesa, ctx );
UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~RADEON_FOG_COLOR_MASK;
@@ -406,109 +408,13 @@ static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
}
}
-
-/* =============================================================
- * Scissoring
- */
-
-
-static GLboolean intersect_rect( drm_clip_rect_t *out,
- drm_clip_rect_t *a,
- drm_clip_rect_t *b )
-{
- *out = *a;
- if ( b->x1 > out->x1 ) out->x1 = b->x1;
- if ( b->y1 > out->y1 ) out->y1 = b->y1;
- if ( b->x2 < out->x2 ) out->x2 = b->x2;
- if ( b->y2 < out->y2 ) out->y2 = b->y2;
- if ( out->x1 >= out->x2 ) return GL_FALSE;
- if ( out->y1 >= out->y2 ) return GL_FALSE;
- return GL_TRUE;
-}
-
-
-void radeonRecalcScissorRects( radeonContextPtr rmesa )
-{
- drm_clip_rect_t *out;
- int i;
-
- /* Grow cliprect store?
- */
- if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
- while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
- rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
- rmesa->state.scissor.numAllocedClipRects *= 2;
- }
-
- if (rmesa->state.scissor.pClipRects)
- FREE(rmesa->state.scissor.pClipRects);
-
- rmesa->state.scissor.pClipRects =
- MALLOC( rmesa->state.scissor.numAllocedClipRects *
- sizeof(drm_clip_rect_t) );
-
- if ( rmesa->state.scissor.pClipRects == NULL ) {
- rmesa->state.scissor.numAllocedClipRects = 0;
- return;
- }
- }
-
- out = rmesa->state.scissor.pClipRects;
- rmesa->state.scissor.numClipRects = 0;
-
- for ( i = 0 ; i < rmesa->numClipRects ; i++ ) {
- if ( intersect_rect( out,
- &rmesa->pClipRects[i],
- &rmesa->state.scissor.rect ) ) {
- rmesa->state.scissor.numClipRects++;
- out++;
- }
- }
-}
-
-
-static void radeonUpdateScissor( GLcontext *ctx )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-
- if ( rmesa->dri.drawable ) {
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
-
- int x = ctx->Scissor.X;
- int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
- int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
- int h = dPriv->h - ctx->Scissor.Y - 1;
-
- rmesa->state.scissor.rect.x1 = x + dPriv->x;
- rmesa->state.scissor.rect.y1 = y + dPriv->y;
- rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
- rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
-
- radeonRecalcScissorRects( rmesa );
- }
-}
-
-
-static void radeonScissor( GLcontext *ctx,
- GLint x, GLint y, GLsizei w, GLsizei h )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-
- if ( ctx->Scissor.Enabled ) {
- RADEON_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */
- radeonUpdateScissor( ctx );
- }
-
-}
-
-
/* =============================================================
* Culling
*/
static void radeonCullFace( GLcontext *ctx, GLenum unused )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
@@ -545,7 +451,7 @@ static void radeonCullFace( GLcontext *ctx, GLenum unused )
static void radeonFrontFace( GLcontext *ctx, GLenum mode )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, set );
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK;
@@ -553,6 +459,10 @@ static void radeonFrontFace( GLcontext *ctx, GLenum mode )
RADEON_STATECHANGE( rmesa, tcl );
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW;
+ /* Winding is inverted when rendering to FBO */
+ if (ctx->DrawBuffer && ctx->DrawBuffer->Name)
+ mode = (mode == GL_CW) ? GL_CCW : GL_CW;
+
switch ( mode ) {
case GL_CW:
rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW;
@@ -570,7 +480,7 @@ static void radeonFrontFace( GLcontext *ctx, GLenum mode )
*/
static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, lin );
RADEON_STATECHANGE( rmesa, set );
@@ -587,10 +497,10 @@ static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, lin );
- rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
+ rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
}
@@ -602,12 +512,19 @@ static void radeonColorMask( GLcontext *ctx,
GLboolean r, GLboolean g,
GLboolean b, GLboolean a )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- GLuint mask = radeonPackColor( rmesa->radeonScreen->cpp,
- ctx->Color.ColorMask[RCOMP],
- ctx->Color.ColorMask[GCOMP],
- ctx->Color.ColorMask[BCOMP],
- ctx->Color.ColorMask[ACOMP] );
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrb;
+ GLuint mask;
+
+ rrb = radeon_get_colorbuffer(&rmesa->radeon);
+ if (!rrb)
+ return;
+
+ mask = radeonPackColor( rrb->cpp,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] );
if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
RADEON_STATECHANGE( rmesa, msk );
@@ -623,8 +540,9 @@ static void radeonColorMask( GLcontext *ctx,
static void radeonPolygonOffset( GLcontext *ctx,
GLfloat factor, GLfloat units )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- float_ui32_type constant = { units * rmesa->state.depth.scale };
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+ float_ui32_type constant = { units * depthScale };
float_ui32_type factoru = { factor };
RADEON_STATECHANGE( rmesa, zbs );
@@ -632,41 +550,16 @@ static void radeonPolygonOffset( GLcontext *ctx,
rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
}
-static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- GLuint i;
- drm_radeon_stipple_t stipple;
-
- /* Must flip pattern upside down.
- */
- for ( i = 0 ; i < 32 ; i++ ) {
- rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
- }
-
- /* TODO: push this into cmd mechanism
- */
- RADEON_FIREVERTICES( rmesa );
- LOCK_HARDWARE( rmesa );
-
- /* FIXME: Use window x,y offsets into stipple RAM.
- */
- stipple.mask = rmesa->state.stipple.mask;
- drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
- &stipple, sizeof(drm_radeon_stipple_t) );
- UNLOCK_HARDWARE( rmesa );
-}
-
static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
/* Can't generally do unfilled via tcl, but some good special
- * cases work.
+ * cases work.
*/
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag);
- if (rmesa->TclFallback) {
+ if (rmesa->radeon.TclFallback) {
radeonChooseRenderState( ctx );
radeonChooseVertexState( ctx );
}
@@ -686,7 +579,7 @@ static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
*/
static void radeonUpdateSpecular( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
GLuint flag = 0;
@@ -711,7 +604,7 @@ static void radeonUpdateSpecular( GLcontext *ctx )
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
p |= RADEON_SPECULAR_ENABLE;
- rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &=
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &=
~RADEON_DIFFUSE_SPECULAR_COMBINE;
}
else if (ctx->Light.Enabled) {
@@ -741,7 +634,7 @@ static void radeonUpdateSpecular( GLcontext *ctx )
RADEON_TCL_COMPUTE_SPECULAR) != 0;
}
}
-
+
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag);
if (NEED_SECONDARY_COLOR(ctx)) {
@@ -757,7 +650,7 @@ static void radeonUpdateSpecular( GLcontext *ctx )
/* Update vertex/render formats
*/
- if (rmesa->TclFallback) {
+ if (rmesa->radeon.TclFallback) {
radeonChooseRenderState( ctx );
radeonChooseVertexState( ctx );
}
@@ -769,12 +662,12 @@ static void radeonUpdateSpecular( GLcontext *ctx )
*/
-/* Update on colormaterial, material emmissive/ambient,
+/* Update on colormaterial, material emmissive/ambient,
* lightmodel.globalambient
*/
static void update_global_ambient( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
float *fcmd = (float *)RADEON_DB_STATE( glt );
/* Need to do more if both emmissive & ambient are PREMULT:
@@ -782,23 +675,23 @@ static void update_global_ambient( GLcontext *ctx )
*/
if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
- (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0)
+ (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0)
{
- COPY_3V( &fcmd[GLT_RED],
+ COPY_3V( &fcmd[GLT_RED],
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
ACC_SCALE_3V( &fcmd[GLT_RED],
ctx->Light.Model.Ambient,
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
- }
+ }
else
{
COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
}
-
+
RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
}
-/* Update on change to
+/* Update on change to
* - light[p].colors
* - light[p].enabled
*/
@@ -809,13 +702,13 @@ static void update_light_colors( GLcontext *ctx, GLuint p )
/* fprintf(stderr, "%s\n", __FUNCTION__); */
if (l->Enabled) {
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
- COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
+ COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
-
+
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
}
}
@@ -829,7 +722,7 @@ static void check_twoside_fallback( GLcontext *ctx )
if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
if (ctx->Light.ColorMaterialEnabled &&
- (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
+ (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
fallback = GL_TRUE;
else {
@@ -837,7 +730,7 @@ static void check_twoside_fallback( GLcontext *ctx )
if (memcmp( ctx->Light.Material.Attrib[i],
ctx->Light.Material.Attrib[i+1],
sizeof(GLfloat)*4) != 0) {
- fallback = GL_TRUE;
+ fallback = GL_TRUE;
break;
}
}
@@ -849,14 +742,14 @@ static void check_twoside_fallback( GLcontext *ctx )
static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
light_model_ctl1 &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
(3 << RADEON_AMBIENT_SOURCE_SHIFT) |
(3 << RADEON_DIFFUSE_SOURCE_SHIFT) |
- (3 << RADEON_SPECULAR_SOURCE_SHIFT));
-
+ (3 << RADEON_SPECULAR_SOURCE_SHIFT));
+
if (ctx->Light.ColorMaterialEnabled) {
GLuint mask = ctx->Light.ColorMaterialBitmask;
@@ -877,7 +770,7 @@ static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
RADEON_AMBIENT_SOURCE_SHIFT);
}
-
+
if (mask & MAT_BIT_FRONT_DIFFUSE) {
light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
RADEON_DIFFUSE_SOURCE_SHIFT);
@@ -886,7 +779,7 @@ static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
RADEON_DIFFUSE_SOURCE_SHIFT);
}
-
+
if (mask & MAT_BIT_FRONT_SPECULAR) {
light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
RADEON_SPECULAR_SOURCE_SHIFT);
@@ -904,27 +797,27 @@ static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
(RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
(RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT);
}
-
+
if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
RADEON_STATECHANGE( rmesa, tcl );
- rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1;
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1;
}
}
void radeonUpdateMaterial( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
GLuint mask = ~0;
-
+
if (ctx->Light.ColorMaterialEnabled)
mask &= ~ctx->Light.ColorMaterialBitmask;
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr, "%s\n", __FUNCTION__);
-
+
if (mask & MAT_BIT_FRONT_EMISSION) {
fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0];
fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
@@ -967,18 +860,18 @@ void radeonUpdateMaterial( GLcontext *ctx )
* _VP_inf_norm
* _h_inf_norm
* _Position
- * _NormDirection
+ * _NormSpotDirection
* _ModelViewInvScale
* _NeedEyeCoords
* _EyeZDir
*
* which are calculated in light.c and are correct for the current
* lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
- * and _MESA_NEW_NEED_EYE_COORDS.
+ * and _MESA_NEW_NEED_EYE_COORDS.
*/
static void update_light( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
/* Have to check these, or have an automatic shortcircuit mechanism
* to remove noop statechanges. (Or just do a better job on the
@@ -991,12 +884,12 @@ static void update_light( GLcontext *ctx )
tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
else
tmp |= RADEON_LIGHT_IN_MODELSPACE;
-
+
/* Leave this test disabled: (unexplained q3 lockup) (even with
new packets)
*/
- if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL])
+ if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL])
{
RADEON_STATECHANGE( rmesa, tcl );
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp;
@@ -1020,17 +913,17 @@ static void update_light( GLcontext *ctx )
if (ctx->Light.Light[p].Enabled) {
struct gl_light *l = &ctx->Light.Light[p];
GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] );
-
+
if (l->EyePosition[3] == 0.0) {
- COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
- COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
+ COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
+ COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
fcmd[LIT_POSITION_W] = 0;
fcmd[LIT_DIRECTION_W] = 0;
} else {
COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
- fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
- fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
- fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
+ fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0];
+ fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1];
+ fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2];
fcmd[LIT_DIRECTION_W] = 0;
}
@@ -1043,30 +936,30 @@ static void update_light( GLcontext *ctx )
static void radeonLightfv( GLcontext *ctx, GLenum light,
GLenum pname, const GLfloat *params )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLint p = light - GL_LIGHT0;
struct gl_light *l = &ctx->Light.Light[p];
GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
-
+
switch (pname) {
- case GL_AMBIENT:
+ case GL_AMBIENT:
case GL_DIFFUSE:
case GL_SPECULAR:
update_light_colors( ctx, p );
break;
- case GL_SPOT_DIRECTION:
- /* picked up in update_light */
+ case GL_SPOT_DIRECTION:
+ /* picked up in update_light */
break;
case GL_POSITION: {
- /* positions picked up in update_light, but can do flag here */
+ /* positions picked up in update_light, but can do flag here */
GLuint flag;
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
/* FIXME: Set RANGE_ATTEN only when needed */
- if (p&1)
+ if (p&1)
flag = RADEON_LIGHT_1_IS_LOCAL;
else
flag = RADEON_LIGHT_0_IS_LOCAL;
@@ -1158,16 +1051,16 @@ static void radeonLightfv( GLcontext *ctx, GLenum light,
}
}
-
+
static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
const GLfloat *param )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
switch (pname) {
- case GL_LIGHT_MODEL_AMBIENT:
+ case GL_LIGHT_MODEL_AMBIENT:
update_global_ambient( ctx );
break;
@@ -1188,7 +1081,7 @@ static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
check_twoside_fallback( ctx );
- if (rmesa->TclFallback) {
+ if (rmesa->radeon.TclFallback) {
radeonChooseRenderState( ctx );
radeonChooseVertexState( ctx );
}
@@ -1205,7 +1098,7 @@ static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
static void radeonShadeModel( GLcontext *ctx, GLenum mode )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
s &= ~(RADEON_DIFFUSE_SHADE_MASK |
@@ -1244,7 +1137,7 @@ static void radeonShadeModel( GLcontext *ctx, GLenum mode )
static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
{
GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
RADEON_STATECHANGE( rmesa, ucp[p] );
@@ -1256,7 +1149,7 @@ static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
static void radeonUpdateClipPlanes( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint p;
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
@@ -1281,7 +1174,7 @@ static void
radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
GLint ref, GLuint mask )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << RADEON_STENCIL_REF_SHIFT) |
((ctx->Stencil.ValueMask[0] & 0xff) << RADEON_STENCIL_MASK_SHIFT));
@@ -1325,7 +1218,7 @@ radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
static void
radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, msk );
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK;
@@ -1336,20 +1229,20 @@ radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
GLenum zfail, GLenum zpass )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
/* radeon 7200 have stencil bug, DEC and INC_WRAP will actually both do DEC_WRAP,
and DEC_WRAP (and INVERT) will do INVERT. No way to get correct INC_WRAP and DEC,
but DEC_WRAP can be fixed by using DEC and INC_WRAP at least use INC. */
-
+
GLuint tempRADEON_STENCIL_FAIL_DEC_WRAP;
GLuint tempRADEON_STENCIL_FAIL_INC_WRAP;
GLuint tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
GLuint tempRADEON_STENCIL_ZFAIL_INC_WRAP;
GLuint tempRADEON_STENCIL_ZPASS_DEC_WRAP;
GLuint tempRADEON_STENCIL_ZPASS_INC_WRAP;
-
- if (rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_BROKEN_STENCIL) {
+
+ if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_BROKEN_STENCIL) {
tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC;
tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC;
tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC;
@@ -1365,7 +1258,7 @@ static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC_WRAP;
tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC_WRAP;
}
-
+
RADEON_STATECHANGE( rmesa, ctx );
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK |
RADEON_STENCIL_ZFAIL_MASK |
@@ -1455,9 +1348,9 @@ static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
static void radeonClearStencil( GLcontext *ctx, GLint s )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
- rmesa->state.stencil.clear =
+ rmesa->radeon.state.stencil.clear =
((GLuint) (ctx->Stencil.Clear & 0xff) |
(0xff << RADEON_STENCIL_MASK_SHIFT) |
((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT));
@@ -1481,20 +1374,30 @@ static void radeonClearStencil( GLcontext *ctx, GLint s )
*/
void radeonUpdateWindow( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
- GLfloat xoffset = (GLfloat)dPriv->x;
- GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
+ GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
+ GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
const GLfloat *v = ctx->Viewport._WindowMap.m;
+ const GLboolean render_to_fbo = (ctx->DrawBuffer ? (ctx->DrawBuffer->Name != 0) : 0);
+ const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+ GLfloat y_scale, y_bias;
+
+ if (render_to_fbo) {
+ y_scale = 1.0;
+ y_bias = 0;
+ } else {
+ y_scale = -1.0;
+ y_bias = yoffset;
+ }
float_ui32_type sx = { v[MAT_SX] };
float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
- float_ui32_type sy = { - v[MAT_SY] };
- float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
- float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale };
- float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale };
+ float_ui32_type sy = { v[MAT_SY] * y_scale };
+ float_ui32_type ty = { (v[MAT_TY] * y_scale) + y_bias + SUBPIXEL_Y };
+ float_ui32_type sz = { v[MAT_SZ] * depthScale };
+ float_ui32_type tz = { v[MAT_TZ] * depthScale };
- RADEON_FIREVERTICES( rmesa );
RADEON_STATECHANGE( rmesa, vpt );
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32;
@@ -1514,6 +1417,8 @@ static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
* values, or keep the originals hanging around.
*/
radeonUpdateWindow( ctx );
+
+ radeon_viewport(ctx, x, y, width, height);
}
static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
@@ -1524,8 +1429,8 @@ static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
void radeonUpdateViewportOffset( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
GLfloat xoffset = (GLfloat)dPriv->x;
GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
const GLfloat *v = ctx->Viewport._WindowMap.m;
@@ -1555,8 +1460,8 @@ void radeonUpdateViewportOffset( GLcontext *ctx )
RADEON_STIPPLE_Y_OFFSET_MASK);
/* add magic offsets, then invert */
- stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
- sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
+ stx = 31 - ((dPriv->x - 1) & RADEON_STIPPLE_COORD_MASK);
+ sty = 31 - ((dPriv->y + dPriv->h - 1)
& RADEON_STIPPLE_COORD_MASK);
m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) |
@@ -1580,20 +1485,26 @@ void radeonUpdateViewportOffset( GLcontext *ctx )
static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLubyte c[4];
+ struct radeon_renderbuffer *rrb;
+
+ rrb = radeon_get_colorbuffer(&rmesa->radeon);
+ if (!rrb)
+ return;
+
CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
- rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp,
+ rmesa->radeon.state.color.clear = radeonPackColor( rrb->cpp,
c[0], c[1], c[2], c[3] );
}
static void radeonRenderMode( GLcontext *ctx, GLenum mode )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
}
@@ -1619,7 +1530,7 @@ static GLuint radeon_rop_tab[] = {
static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint rop = (GLuint)opcode - GL_CLEAR;
ASSERT( rop < 16 );
@@ -1628,108 +1539,16 @@ static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop];
}
-
-/**
- * Set up the cliprects for either front or back-buffer drawing.
- */
-void radeonSetCliprects( radeonContextPtr rmesa )
-{
- __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
- __DRIdrawablePrivate *const readable = rmesa->dri.readable;
- GLframebuffer *const draw_fb = (GLframebuffer*) drawable->driverPrivate;
- GLframebuffer *const read_fb = (GLframebuffer*) readable->driverPrivate;
-
- if (draw_fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
- /* Can't ignore 2d windows if we are page flipping.
- */
- if ( drawable->numBackClipRects == 0 || rmesa->doPageFlip ) {
- rmesa->numClipRects = drawable->numClipRects;
- rmesa->pClipRects = drawable->pClipRects;
- }
- else {
- rmesa->numClipRects = drawable->numBackClipRects;
- rmesa->pClipRects = drawable->pBackClipRects;
- }
- }
- else {
- /* front buffer (or none, or multiple buffers */
- rmesa->numClipRects = drawable->numClipRects;
- rmesa->pClipRects = drawable->pClipRects;
- }
-
- if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) {
- _mesa_resize_framebuffer(rmesa->glCtx, draw_fb,
- drawable->w, drawable->h);
- draw_fb->Initialized = GL_TRUE;
- }
-
- if (drawable != readable) {
- if ((read_fb->Width != readable->w) || (read_fb->Height != readable->h)) {
- _mesa_resize_framebuffer(rmesa->glCtx, read_fb,
- readable->w, readable->h);
- read_fb->Initialized = GL_TRUE;
- }
- }
-
- if (rmesa->state.scissor.enabled)
- radeonRecalcScissorRects( rmesa );
-
- rmesa->lastStamp = drawable->lastStamp;
-}
-
-
-/**
- * Called via glDrawBuffer.
- */
-static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-
- if (RADEON_DEBUG & DEBUG_DRI)
- fprintf(stderr, "%s %s\n", __FUNCTION__,
- _mesa_lookup_enum_by_nr( mode ));
-
- RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
-
- if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
- /* 0 (GL_NONE) buffers or multiple color drawing buffers */
- FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
- return;
- }
-
- switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
- case BUFFER_FRONT_LEFT:
- case BUFFER_BACK_LEFT:
- FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
- break;
- default:
- FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
- return;
- }
-
- radeonSetCliprects( rmesa );
-
- /* We'll set the drawing engine's offset/pitch parameters later
- * when we update other state.
- */
-}
-
-static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
-{
- /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
-}
-
-
/* =============================================================
* State enable/disable
*/
static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint p, flag;
- if ( RADEON_DEBUG & DEBUG_STATE )
+ if ( RADEON_DEBUG & RADEON_STATE )
fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr( cap ),
state ? "GL_TRUE" : "GL_FALSE" );
@@ -1787,7 +1606,7 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
case GL_CLIP_PLANE2:
case GL_CLIP_PLANE3:
case GL_CLIP_PLANE4:
- case GL_CLIP_PLANE5:
+ case GL_CLIP_PLANE5:
p = cap-GL_CLIP_PLANE0;
RADEON_STATECHANGE( rmesa, tcl );
if (state) {
@@ -1821,10 +1640,10 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
RADEON_STATECHANGE(rmesa, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
} else {
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;
}
break;
@@ -1852,13 +1671,13 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
case GL_LIGHT7:
RADEON_STATECHANGE(rmesa, tcl);
p = cap - GL_LIGHT0;
- if (p&1)
+ if (p&1)
flag = (RADEON_LIGHT_1_ENABLE |
- RADEON_LIGHT_1_ENABLE_AMBIENT |
+ RADEON_LIGHT_1_ENABLE_AMBIENT |
RADEON_LIGHT_1_ENABLE_SPECULAR);
else
flag = (RADEON_LIGHT_0_ENABLE |
- RADEON_LIGHT_0_ENABLE_AMBIENT |
+ RADEON_LIGHT_0_ENABLE_AMBIENT |
RADEON_LIGHT_0_ENABLE_SPECULAR);
if (state)
@@ -1866,7 +1685,7 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
else
rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
- /*
+ /*
*/
update_light_colors( ctx, p );
break;
@@ -1904,7 +1723,7 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
}
break;
-
+
case GL_NORMALIZE:
RADEON_STATECHANGE( rmesa, tcl );
if ( state ) {
@@ -1971,21 +1790,30 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
}
case GL_SCISSOR_TEST:
- RADEON_FIREVERTICES( rmesa );
- rmesa->state.scissor.enabled = state;
+ radeon_firevertices(&rmesa->radeon);
+ rmesa->radeon.state.scissor.enabled = state;
radeonUpdateScissor( ctx );
break;
case GL_STENCIL_TEST:
- if ( rmesa->state.stencil.hwBuffer ) {
- RADEON_STATECHANGE( rmesa, ctx );
- if ( state ) {
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE;
+ {
+ GLboolean hw_stencil = GL_FALSE;
+ if (ctx->DrawBuffer) {
+ struct radeon_renderbuffer *rrbStencil
+ = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
+ hw_stencil = (rrbStencil && rrbStencil->bo);
+ }
+
+ if (hw_stencil) {
+ RADEON_STATECHANGE( rmesa, ctx );
+ if ( state ) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE;
+ } else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
+ }
} else {
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
+ FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
}
- } else {
- FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
}
break;
@@ -1995,7 +1823,7 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
case GL_TEXTURE_GEN_T:
/* Picked up in radeonUpdateTextureState.
*/
- rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
+ rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
break;
case GL_COLOR_SUM_EXT:
@@ -2010,11 +1838,11 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
static void radeonLightingSpaceChange( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLboolean tmp;
RADEON_STATECHANGE( rmesa, tcl );
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
@@ -2029,7 +1857,7 @@ static void radeonLightingSpaceChange( GLcontext *ctx )
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
}
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & RADEON_STATE)
fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
}
@@ -2039,7 +1867,7 @@ static void radeonLightingSpaceChange( GLcontext *ctx )
*/
-void radeonUploadTexMatrix( radeonContextPtr rmesa,
+void radeonUploadTexMatrix( r100ContextPtr rmesa,
int unit, GLboolean swapcols )
{
/* Here's how this works: on r100, only 3 tex coords can be submitted, so the
@@ -2065,7 +1893,7 @@ void radeonUploadTexMatrix( radeonContextPtr rmesa,
int idx = TEXMAT_0 + unit;
float *dest = ((float *)RADEON_DB_STATE( mat[idx] )) + MAT_ELT_0;
int i;
- struct gl_texture_unit tUnit = rmesa->glCtx->Texture.Unit[unit];
+ struct gl_texture_unit tUnit = rmesa->radeon.glCtx->Texture.Unit[unit];
GLfloat *src = rmesa->tmpmat[unit].m;
rmesa->TexMatColSwap &= ~(1 << unit);
@@ -2119,7 +1947,7 @@ void radeonUploadTexMatrix( radeonContextPtr rmesa,
}
-static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
+static void upload_matrix( r100ContextPtr rmesa, GLfloat *src, int idx )
{
float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
int i;
@@ -2135,7 +1963,7 @@ static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
}
-static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
+static void upload_matrix_t( r100ContextPtr rmesa, GLfloat *src, int idx )
{
float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
memcpy(dest, src, 16*sizeof(float));
@@ -2145,7 +1973,7 @@ static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
static void update_texturematrix( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ r100ContextPtr rmesa = R100_CONTEXT( ctx );
GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL];
GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL];
int unit;
@@ -2209,64 +2037,74 @@ static void update_texturematrix( GLcontext *ctx )
}
}
-
-/**
- * Tell the card where to render (offset, pitch).
- * Effected by glDrawBuffer, etc
- */
-void
-radeonUpdateDrawBuffer(GLcontext *ctx)
+static GLboolean r100ValidateBuffers(GLcontext *ctx)
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- struct gl_framebuffer *fb = ctx->DrawBuffer;
- driRenderbuffer *drb;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrb;
+ int i, ret;
- if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
- /* draw to front */
- drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
- }
- else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
- /* draw to back */
- drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
+
+ rrb = radeon_get_colorbuffer(&rmesa->radeon);
+ /* color buffer */
+ if (rrb && rrb->bo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
+ 0, RADEON_GEM_DOMAIN_VRAM);
}
- else {
- /* drawing to multiple buffers, or none */
- return;
+
+ /* depth buffer */
+ rrb = radeon_get_depthbuffer(&rmesa->radeon);
+ /* color buffer */
+ if (rrb && rrb->bo) {
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
+ 0, RADEON_GEM_DOMAIN_VRAM);
}
- assert(drb);
- assert(drb->flippedPitch);
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
+ radeonTexObj *t;
- RADEON_STATECHANGE( rmesa, ctx );
+ if (!ctx->Texture.Unit[i]._ReallyEnabled)
+ continue;
- /* Note: we used the (possibly) page-flipped values */
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
- = ((drb->flippedOffset + rmesa->radeonScreen->fbLocation)
- & RADEON_COLOROFFSET_MASK);
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
- if (rmesa->sarea->tiling_enabled) {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= RADEON_COLOR_TILE_ENABLE;
+ t = rmesa->state.texture.unit[i].texobj;
+ if (t->image_override && t->bo)
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+ else if (t->mt->bo)
+ radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo,
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
}
-}
+ ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, first_elem(&rmesa->radeon.dma.reserved)->bo, RADEON_GEM_DOMAIN_GTT, 0);
+ if (ret)
+ return GL_FALSE;
+ return GL_TRUE;
+}
-void radeonValidateState( GLcontext *ctx )
+GLboolean radeonValidateState( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- GLuint new_state = rmesa->NewGLState;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ GLuint new_state = rmesa->radeon.NewGLState;
- if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
- radeonUpdateDrawBuffer(ctx);
+ if (new_state & _NEW_BUFFERS) {
+ _mesa_update_framebuffer(ctx);
+ /* this updates the DrawBuffer's Width/Height if it's a FBO */
+ _mesa_update_draw_buffer_bounds(ctx);
+ RADEON_STATECHANGE(rmesa, ctx);
}
if (new_state & _NEW_TEXTURE) {
radeonUpdateTextureState( ctx );
- new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
+ new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
}
+ /* we need to do a space check here */
+ if (!r100ValidateBuffers(ctx))
+ return GL_FALSE;
+
/* Need an event driven matrix update?
*/
- if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
+ if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
/* Need these for lighting (shouldn't upload otherwise)
@@ -2290,12 +2128,14 @@ void radeonValidateState( GLcontext *ctx )
/* emit all active clip planes if projection matrix changes.
*/
if (new_state & (_NEW_PROJECTION)) {
- if (ctx->Transform.ClipPlanesEnabled)
+ if (ctx->Transform.ClipPlanesEnabled)
radeonUpdateClipPlanes( ctx );
}
- rmesa->NewGLState = 0;
+ rmesa->radeon.NewGLState = 0;
+
+ return GL_TRUE;
}
@@ -2306,7 +2146,7 @@ static void radeonInvalidateState( GLcontext *ctx, GLuint new_state )
_vbo_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
_ae_invalidate_state( ctx, new_state );
- RADEON_CONTEXT(ctx)->NewGLState |= new_state;
+ R100_CONTEXT(ctx)->radeon.NewGLState |= new_state;
}
@@ -2317,8 +2157,8 @@ static GLboolean check_material( GLcontext *ctx )
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLint i;
- for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
- i < _TNL_ATTRIB_MAT_BACK_INDEXES;
+ for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
+ i < _TNL_ATTRIB_MAT_BACK_INDEXES;
i++)
if (tnl->vb.AttribPtr[i] &&
tnl->vb.AttribPtr[i]->stride)
@@ -2326,20 +2166,21 @@ static GLboolean check_material( GLcontext *ctx )
return GL_FALSE;
}
-
+
static void radeonWrapRunPipeline( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLboolean has_material;
if (0)
- fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
+ fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState);
/* Validate state:
*/
- if (rmesa->NewGLState)
- radeonValidateState( ctx );
+ if (rmesa->radeon.NewGLState)
+ if (!radeonValidateState( ctx ))
+ FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
has_material = (ctx->Light.Enabled && check_material( ctx ));
@@ -2348,7 +2189,7 @@ static void radeonWrapRunPipeline( GLcontext *ctx )
}
/* Run the pipeline.
- */
+ */
_tnl_run_pipeline( ctx );
if (has_material) {
@@ -2356,12 +2197,28 @@ static void radeonWrapRunPipeline( GLcontext *ctx )
}
}
+static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ GLint i;
+
+ radeon_firevertices(&r100->radeon);
+
+ RADEON_STATECHANGE(r100, stp);
+
+ /* Must flip pattern upside down.
+ */
+ for ( i = 31 ; i >= 0; i--) {
+ r100->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i];
+ }
+}
+
/* Initialize the driver's state functions.
* Many of the ctx->Driver functions might have been initialized to
* software defaults in the earlier _mesa_init_driver_functions() call.
*/
-void radeonInitStateFuncs( GLcontext *ctx )
+void radeonInitStateFuncs( GLcontext *ctx , GLboolean dri2 )
{
ctx->Driver.UpdateState = radeonInvalidateState;
ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange;
@@ -2394,7 +2251,10 @@ void radeonInitStateFuncs( GLcontext *ctx )
ctx->Driver.LogicOpcode = radeonLogicOpCode;
ctx->Driver.PolygonMode = radeonPolygonMode;
ctx->Driver.PolygonOffset = radeonPolygonOffset;
- ctx->Driver.PolygonStipple = radeonPolygonStipple;
+ if (dri2)
+ ctx->Driver.PolygonStipple = radeonPolygonStipple;
+ else
+ ctx->Driver.PolygonStipple = radeonPolygonStipplePreKMS;
ctx->Driver.RenderMode = radeonRenderMode;
ctx->Driver.Scissor = radeonScissor;
ctx->Driver.ShadeModel = radeonShadeModel;
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.h b/src/mesa/drivers/dri/radeon/radeon_state.h
index 2171879f75..c780cff0cf 100644
--- a/src/mesa/drivers/dri/radeon/radeon_state.h
+++ b/src/mesa/drivers/dri/radeon/radeon_state.h
@@ -39,30 +39,25 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_context.h"
-extern void radeonInitState( radeonContextPtr rmesa );
-extern void radeonInitStateFuncs( GLcontext *ctx );
+extern void radeonInitState( r100ContextPtr rmesa );
+extern void radeonInitStateFuncs( GLcontext *ctx , GLboolean dri2);
extern void radeonUpdateMaterial( GLcontext *ctx );
-extern void radeonSetCliprects( radeonContextPtr rmesa );
-extern void radeonRecalcScissorRects( radeonContextPtr rmesa );
extern void radeonUpdateViewportOffset( GLcontext *ctx );
extern void radeonUpdateWindow( GLcontext *ctx );
extern void radeonUpdateDrawBuffer( GLcontext *ctx );
-extern void radeonUploadTexMatrix( radeonContextPtr rmesa,
+extern void radeonUploadTexMatrix( r100ContextPtr rmesa,
int unit, GLboolean swapcols );
-extern void radeonValidateState( GLcontext *ctx );
-
-extern void radeonPrintDirty( radeonContextPtr rmesa,
- const char *msg );
+extern GLboolean radeonValidateState( GLcontext *ctx );
extern void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define FALLBACK( rmesa, bit, mode ) do { \
if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \
__FUNCTION__, bit, mode ); \
- radeonFallback( rmesa->glCtx, bit, mode ); \
+ radeonFallback( rmesa->radeon.glCtx, bit, mode ); \
} while (0)
diff --git a/src/mesa/drivers/dri/radeon/radeon_state_init.c b/src/mesa/drivers/dri/radeon/radeon_state_init.c
index 57dc380050..f3ad0dd17a 100644
--- a/src/mesa/drivers/dri/radeon/radeon_state_init.c
+++ b/src/mesa/drivers/dri/radeon/radeon_state_init.c
@@ -38,39 +38,141 @@
#include "swrast_setup/swrast_setup.h"
#include "radeon_context.h"
+#include "radeon_mipmap_tree.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "radeon_tcl.h"
#include "radeon_tex.h"
#include "radeon_swtcl.h"
+#include "radeon_queryobj.h"
+
+#include "../r200/r200_reg.h"
#include "xmlpool.h"
+/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
+ * 1.3 cmdbuffers allow all previous state to be updated as well as
+ * the tcl scalar and vector areas.
+ */
+static struct {
+ int start;
+ int len;
+ const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+ {RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
+ {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
+ {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
+ {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
+ {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
+ {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
+ {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
+ {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
+ {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
+ {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
+ {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
+ {RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
+ {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
+ {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
+ {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
+ {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
+ {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
+ {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
+ {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
+ {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
+ {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
+ "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
+ {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
+ {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
+ {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
+ {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
+ {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
+ {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
+ {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
+ {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
+ {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
+ {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
+ {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
+ {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
+ {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
+ {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
+ {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
+ {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
+ {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
+ {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
+ {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
+ {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
+ {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
+ {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
+ {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
+ {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
+ {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
+ {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
+ {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
+ {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
+ {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1,
+ "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
+ {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
+ {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
+ {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
+ {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
+ {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
+ {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
+ {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
+ {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
+ {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
+ {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
+ {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
+ "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
+ {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */
+ {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
+ {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
+ {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
+ {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
+ {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
+ {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
+ {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
+ {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
+ {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
+ {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
+ {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
+ {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
+ {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
+ {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
+ {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
+ {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
+ {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
+ {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
+ {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
+ {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
+ {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
+ {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
+ {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
+ {R200_PP_TXCBLEND_8, 32, "R200_PP_AFS_0"}, /* 85 */
+ {R200_PP_TXCBLEND_0, 32, "R200_PP_AFS_1"},
+ {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
+ {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
+ {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
+ {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
+ {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
+ {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
+ {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
+ {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
+};
+
/* =============================================================
* State initialization
*/
-
-void radeonPrintDirty( radeonContextPtr rmesa, const char *msg )
+static int cmdpkt( r100ContextPtr rmesa, int id )
{
- struct radeon_state_atom *l;
-
- fprintf(stderr, msg);
- fprintf(stderr, ": ");
+ drm_radeon_cmd_header_t h;
- foreach(l, &rmesa->hw.atomlist) {
- if (l->dirty || rmesa->hw.all_dirty)
- fprintf(stderr, "%s, ", l->name);
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ return CP_PACKET0(packet[id].start, packet[id].len - 1);
+ } else {
+ h.i = 0;
+ h.packet.cmd_type = RADEON_CMD_PACKET;
+ h.packet.packet_id = id;
}
-
- fprintf(stderr, "\n");
-}
-
-static int cmdpkt( int id )
-{
- drm_radeon_cmd_header_t h;
- h.i = 0;
- h.packet.cmd_type = RADEON_CMD_PACKET;
- h.packet.packet_id = id;
return h.i;
}
@@ -96,131 +198,523 @@ static int cmdscl( int offset, int stride, int count )
return h.i;
}
-#define CHECK( NM, FLAG ) \
-static GLboolean check_##NM( GLcontext *ctx ) \
-{ \
- return FLAG; \
+#define CHECK( NM, FLAG, ADD ) \
+static int check_##NM( GLcontext *ctx, struct radeon_state_atom *atom ) \
+{ \
+ return FLAG ? atom->cmd_size + (ADD) : 0; \
}
-#define TCL_CHECK( NM, FLAG ) \
-static GLboolean check_##NM( GLcontext *ctx ) \
+#define TCL_CHECK( NM, FLAG, ADD ) \
+static int check_##NM( GLcontext *ctx, struct radeon_state_atom *atom ) \
{ \
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
- return !rmesa->TclFallback && (FLAG); \
+ r100ContextPtr rmesa = R100_CONTEXT(ctx); \
+ return (!rmesa->radeon.TclFallback && (FLAG)) ? atom->cmd_size + (ADD) : 0; \
}
-CHECK( always, GL_TRUE )
-CHECK( never, GL_FALSE )
-CHECK( tex0, ctx->Texture.Unit[0]._ReallyEnabled )
-CHECK( tex1, ctx->Texture.Unit[1]._ReallyEnabled )
+CHECK( always, GL_TRUE, 0 )
+CHECK( always_add2, GL_TRUE, 2 )
+CHECK( always_add4, GL_TRUE, 4 )
+CHECK( never, GL_FALSE, 0 )
+CHECK( tex0_mm, ctx->Texture.Unit[0]._ReallyEnabled, 3 )
+CHECK( tex1_mm, ctx->Texture.Unit[1]._ReallyEnabled, 3 )
/* need this for the cubic_map on disabled unit 2 bug, maybe r100 only? */
-CHECK( tex2, ctx->Texture._EnabledUnits )
-CHECK( cube0, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_CUBE_BIT))
-CHECK( cube1, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_CUBE_BIT))
-CHECK( cube2, (ctx->Texture.Unit[2]._ReallyEnabled & TEXTURE_CUBE_BIT))
-CHECK( fog, ctx->Fog.Enabled )
-TCL_CHECK( tcl, GL_TRUE )
-TCL_CHECK( tcl_tex0, ctx->Texture.Unit[0]._ReallyEnabled )
-TCL_CHECK( tcl_tex1, ctx->Texture.Unit[1]._ReallyEnabled )
-TCL_CHECK( tcl_tex2, ctx->Texture.Unit[2]._ReallyEnabled )
-TCL_CHECK( tcl_lighting, ctx->Light.Enabled )
-TCL_CHECK( tcl_eyespace_or_lighting, ctx->_NeedEyeCoords || ctx->Light.Enabled )
-TCL_CHECK( tcl_lit0, ctx->Light.Enabled && ctx->Light.Light[0].Enabled )
-TCL_CHECK( tcl_lit1, ctx->Light.Enabled && ctx->Light.Light[1].Enabled )
-TCL_CHECK( tcl_lit2, ctx->Light.Enabled && ctx->Light.Light[2].Enabled )
-TCL_CHECK( tcl_lit3, ctx->Light.Enabled && ctx->Light.Light[3].Enabled )
-TCL_CHECK( tcl_lit4, ctx->Light.Enabled && ctx->Light.Light[4].Enabled )
-TCL_CHECK( tcl_lit5, ctx->Light.Enabled && ctx->Light.Light[5].Enabled )
-TCL_CHECK( tcl_lit6, ctx->Light.Enabled && ctx->Light.Light[6].Enabled )
-TCL_CHECK( tcl_lit7, ctx->Light.Enabled && ctx->Light.Light[7].Enabled )
-TCL_CHECK( tcl_ucp0, (ctx->Transform.ClipPlanesEnabled & 0x1) )
-TCL_CHECK( tcl_ucp1, (ctx->Transform.ClipPlanesEnabled & 0x2) )
-TCL_CHECK( tcl_ucp2, (ctx->Transform.ClipPlanesEnabled & 0x4) )
-TCL_CHECK( tcl_ucp3, (ctx->Transform.ClipPlanesEnabled & 0x8) )
-TCL_CHECK( tcl_ucp4, (ctx->Transform.ClipPlanesEnabled & 0x10) )
-TCL_CHECK( tcl_ucp5, (ctx->Transform.ClipPlanesEnabled & 0x20) )
-TCL_CHECK( tcl_eyespace_or_fog, ctx->_NeedEyeCoords || ctx->Fog.Enabled )
-
-CHECK( txr0, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_RECT_BIT))
-CHECK( txr1, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_RECT_BIT))
-CHECK( txr2, (ctx->Texture.Unit[2]._ReallyEnabled & TEXTURE_RECT_BIT))
+CHECK( tex2_mm, ctx->Texture._EnabledUnits, 3 )
+CHECK( tex0, ctx->Texture.Unit[0]._ReallyEnabled, 2 )
+CHECK( tex1, ctx->Texture.Unit[1]._ReallyEnabled, 2 )
+CHECK( tex2, ctx->Texture._EnabledUnits, 2 )
+CHECK( cube0, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_CUBE_BIT), 3 + 3*5 - CUBE_STATE_SIZE )
+CHECK( cube1, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_CUBE_BIT), 3 + 3*5 - CUBE_STATE_SIZE )
+CHECK( cube2, (ctx->Texture.Unit[2]._ReallyEnabled & TEXTURE_CUBE_BIT), 3 + 3*5 - CUBE_STATE_SIZE )
+CHECK( cube0_mm, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_CUBE_BIT), 2 + 4*5 - CUBE_STATE_SIZE )
+CHECK( cube1_mm, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_CUBE_BIT), 2 + 4*5 - CUBE_STATE_SIZE )
+CHECK( cube2_mm, (ctx->Texture.Unit[2]._ReallyEnabled & TEXTURE_CUBE_BIT), 2 + 4*5 - CUBE_STATE_SIZE )
+CHECK( fog, ctx->Fog.Enabled, 0 )
+CHECK( fog_add4, ctx->Fog.Enabled, 4 )
+TCL_CHECK( tcl, GL_TRUE, 0 )
+TCL_CHECK( tcl_add4, GL_TRUE, 4 )
+TCL_CHECK( tcl_tex0, ctx->Texture.Unit[0]._ReallyEnabled, 0 )
+TCL_CHECK( tcl_tex1, ctx->Texture.Unit[1]._ReallyEnabled, 0 )
+TCL_CHECK( tcl_tex2, ctx->Texture.Unit[2]._ReallyEnabled, 0 )
+TCL_CHECK( tcl_tex0_add4, ctx->Texture.Unit[0]._ReallyEnabled, 4 )
+TCL_CHECK( tcl_tex1_add4, ctx->Texture.Unit[1]._ReallyEnabled, 4 )
+TCL_CHECK( tcl_tex2_add4, ctx->Texture.Unit[2]._ReallyEnabled, 4 )
+TCL_CHECK( tcl_lighting, ctx->Light.Enabled, 0 )
+TCL_CHECK( tcl_lighting_add4, ctx->Light.Enabled, 4 )
+TCL_CHECK( tcl_eyespace_or_lighting, ctx->_NeedEyeCoords || ctx->Light.Enabled, 0 )
+TCL_CHECK( tcl_eyespace_or_lighting_add4, ctx->_NeedEyeCoords || ctx->Light.Enabled, 4 )
+TCL_CHECK( tcl_lit0, ctx->Light.Enabled && ctx->Light.Light[0].Enabled, 0 )
+TCL_CHECK( tcl_lit1, ctx->Light.Enabled && ctx->Light.Light[1].Enabled, 0 )
+TCL_CHECK( tcl_lit2, ctx->Light.Enabled && ctx->Light.Light[2].Enabled, 0 )
+TCL_CHECK( tcl_lit3, ctx->Light.Enabled && ctx->Light.Light[3].Enabled, 0 )
+TCL_CHECK( tcl_lit4, ctx->Light.Enabled && ctx->Light.Light[4].Enabled, 0 )
+TCL_CHECK( tcl_lit5, ctx->Light.Enabled && ctx->Light.Light[5].Enabled, 0 )
+TCL_CHECK( tcl_lit6, ctx->Light.Enabled && ctx->Light.Light[6].Enabled, 0 )
+TCL_CHECK( tcl_lit7, ctx->Light.Enabled && ctx->Light.Light[7].Enabled, 0 )
+TCL_CHECK( tcl_lit0_add6, ctx->Light.Enabled && ctx->Light.Light[0].Enabled, 6 )
+TCL_CHECK( tcl_lit1_add6, ctx->Light.Enabled && ctx->Light.Light[1].Enabled, 6 )
+TCL_CHECK( tcl_lit2_add6, ctx->Light.Enabled && ctx->Light.Light[2].Enabled, 6 )
+TCL_CHECK( tcl_lit3_add6, ctx->Light.Enabled && ctx->Light.Light[3].Enabled, 6 )
+TCL_CHECK( tcl_lit4_add6, ctx->Light.Enabled && ctx->Light.Light[4].Enabled, 6 )
+TCL_CHECK( tcl_lit5_add6, ctx->Light.Enabled && ctx->Light.Light[5].Enabled, 6 )
+TCL_CHECK( tcl_lit6_add6, ctx->Light.Enabled && ctx->Light.Light[6].Enabled, 6 )
+TCL_CHECK( tcl_lit7_add6, ctx->Light.Enabled && ctx->Light.Light[7].Enabled, 6 )
+TCL_CHECK( tcl_ucp0, (ctx->Transform.ClipPlanesEnabled & 0x1), 0 )
+TCL_CHECK( tcl_ucp1, (ctx->Transform.ClipPlanesEnabled & 0x2), 0 )
+TCL_CHECK( tcl_ucp2, (ctx->Transform.ClipPlanesEnabled & 0x4), 0 )
+TCL_CHECK( tcl_ucp3, (ctx->Transform.ClipPlanesEnabled & 0x8), 0 )
+TCL_CHECK( tcl_ucp4, (ctx->Transform.ClipPlanesEnabled & 0x10), 0 )
+TCL_CHECK( tcl_ucp5, (ctx->Transform.ClipPlanesEnabled & 0x20), 0 )
+TCL_CHECK( tcl_ucp0_add4, (ctx->Transform.ClipPlanesEnabled & 0x1), 4 )
+TCL_CHECK( tcl_ucp1_add4, (ctx->Transform.ClipPlanesEnabled & 0x2), 4 )
+TCL_CHECK( tcl_ucp2_add4, (ctx->Transform.ClipPlanesEnabled & 0x4), 4 )
+TCL_CHECK( tcl_ucp3_add4, (ctx->Transform.ClipPlanesEnabled & 0x8), 4 )
+TCL_CHECK( tcl_ucp4_add4, (ctx->Transform.ClipPlanesEnabled & 0x10), 4 )
+TCL_CHECK( tcl_ucp5_add4, (ctx->Transform.ClipPlanesEnabled & 0x20), 4 )
+TCL_CHECK( tcl_eyespace_or_fog, ctx->_NeedEyeCoords || ctx->Fog.Enabled, 0 )
+TCL_CHECK( tcl_eyespace_or_fog_add4, ctx->_NeedEyeCoords || ctx->Fog.Enabled, 4 )
+
+CHECK( txr0, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_RECT_BIT), 0 )
+CHECK( txr1, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_RECT_BIT), 0 )
+CHECK( txr2, (ctx->Texture.Unit[2]._ReallyEnabled & TEXTURE_RECT_BIT), 0 )
+
+#define OUT_VEC(hdr, data) do { \
+ drm_radeon_cmd_header_t h; \
+ h.i = hdr; \
+ OUT_BATCH(CP_PACKET0(RADEON_SE_TCL_STATE_FLUSH, 0)); \
+ OUT_BATCH(0); \
+ OUT_BATCH(CP_PACKET0(R200_SE_TCL_VECTOR_INDX_REG, 0)); \
+ OUT_BATCH(h.vectors.offset | (h.vectors.stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); \
+ OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_VECTOR_DATA_REG, h.vectors.count - 1)); \
+ OUT_BATCH_TABLE((data), h.vectors.count); \
+ } while(0)
+
+#define OUT_SCL(hdr, data) do { \
+ drm_radeon_cmd_header_t h; \
+ h.i = hdr; \
+ OUT_BATCH(CP_PACKET0(R200_SE_TCL_SCALAR_INDX_REG, 0)); \
+ OUT_BATCH((h.scalars.offset) | (h.scalars.stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); \
+ OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_SCALAR_DATA_REG, h.scalars.count - 1)); \
+ OUT_BATCH_TABLE((data), h.scalars.count); \
+ } while(0)
+
+static void scl_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&r100->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_SCL(atom->cmd[0], atom->cmd+1);
+ END_BATCH();
+}
+static void vec_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&r100->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
-/* Initialize the context's hardware state.
- */
-void radeonInitState( radeonContextPtr rmesa )
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_VEC(atom->cmd[0], atom->cmd+1);
+ END_BATCH();
+}
+
+
+static void lit_emit(GLcontext *ctx, struct radeon_state_atom *atom)
{
- GLcontext *ctx = rmesa->glCtx;
- GLuint color_fmt, depth_fmt, i;
- GLint drawPitch, drawOffset;
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&r100->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_VEC(atom->cmd[LIT_CMD_0], atom->cmd+1);
+ OUT_SCL(atom->cmd[LIT_CMD_1], atom->cmd+LIT_CMD_1+1);
+ END_BATCH();
+}
- switch ( rmesa->radeonScreen->cpp ) {
- case 2:
- color_fmt = RADEON_COLOR_FORMAT_RGB565;
- break;
- case 4:
- color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
- break;
- default:
- fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" );
- exit( -1 );
+static void ctx_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&r100->radeon);
+ struct radeon_renderbuffer *rrb;
+ uint32_t cbpitch;
+ uint32_t zbpitch, depth_fmt;
+ uint32_t dwords = atom->check(ctx, atom);
+
+ /* output the first 7 bytes of context */
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(atom->cmd, 5);
+
+ rrb = radeon_get_depthbuffer(&r100->radeon);
+ if (!rrb) {
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ } else {
+ zbpitch = (rrb->pitch / rrb->cpp);
+ if (r100->using_hyperz)
+ zbpitch |= RADEON_DEPTH_HYPERZ;
+
+ OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_BATCH(zbpitch);
+ if (rrb->cpp == 4)
+ depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+ else
+ depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+ atom->cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_DEPTH_FORMAT_MASK;
+ atom->cmd[CTX_RB3D_ZSTENCILCNTL] |= depth_fmt;
+ }
+
+ OUT_BATCH(atom->cmd[CTX_RB3D_ZSTENCILCNTL]);
+ OUT_BATCH(atom->cmd[CTX_CMD_1]);
+ OUT_BATCH(atom->cmd[CTX_PP_CNTL]);
+
+ rrb = radeon_get_colorbuffer(&r100->radeon);
+ if (!rrb || !rrb->bo) {
+ OUT_BATCH(atom->cmd[CTX_RB3D_CNTL]);
+ OUT_BATCH(atom->cmd[CTX_RB3D_COLOROFFSET]);
+ } else {
+ atom->cmd[CTX_RB3D_CNTL] &= ~(0xf << 10);
+ if (rrb->cpp == 4)
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB8888;
+ else
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_RGB565;
+
+ OUT_BATCH(atom->cmd[CTX_RB3D_CNTL]);
+ OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
}
- rmesa->state.color.clear = 0x00000000;
+ OUT_BATCH(atom->cmd[CTX_CMD_2]);
+
+ if (!rrb || !rrb->bo) {
+ OUT_BATCH(atom->cmd[CTX_RB3D_COLORPITCH]);
+ } else {
+ cbpitch = (rrb->pitch / rrb->cpp);
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+ cbpitch |= RADEON_COLOR_TILE_ENABLE;
+ OUT_BATCH(cbpitch);
+ }
+
+ END_BATCH();
+}
+
+static int check_always_ctx( GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ struct radeon_renderbuffer *rrb, *drb;
+ uint32_t dwords;
+
+ rrb = radeon_get_colorbuffer(&r100->radeon);
+ if (!rrb || !rrb->bo) {
+ return 0;
+ }
+
+ drb = radeon_get_depthbuffer(&r100->radeon);
+
+ dwords = 10;
+ if (drb)
+ dwords += 6;
+ if (rrb)
+ dwords += 8;
+
+ return dwords;
+}
+
+static void ctx_emit_cs(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&r100->radeon);
+ struct radeon_renderbuffer *rrb, *drb;
+ uint32_t cbpitch = 0;
+ uint32_t zbpitch = 0;
+ uint32_t dwords = atom->check(ctx, atom);
+ uint32_t depth_fmt;
+
+ rrb = radeon_get_colorbuffer(&r100->radeon);
+ if (!rrb || !rrb->bo) {
+ fprintf(stderr, "no rrb\n");
+ return;
+ }
+
+ atom->cmd[CTX_RB3D_CNTL] &= ~(0xf << 10);
+ if (rrb->cpp == 4)
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB8888;
+ else switch (rrb->base._ActualFormat) {
+ case GL_RGB5:
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_RGB565;
+ break;
+ case GL_RGBA4:
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB4444;
+ break;
+ case GL_RGB5_A1:
+ atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB1555;
+ break;
+ }
+
+ cbpitch = (rrb->pitch / rrb->cpp);
+ if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
+ cbpitch |= R200_COLOR_TILE_ENABLE;
+
+ drb = radeon_get_depthbuffer(&r100->radeon);
+ if (drb) {
+ zbpitch = (drb->pitch / drb->cpp);
+ if (drb->cpp == 4)
+ depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+ else
+ depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+ atom->cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_DEPTH_FORMAT_MASK;
+ atom->cmd[CTX_RB3D_ZSTENCILCNTL] |= depth_fmt;
+
+ }
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+
+ /* In the CS case we need to split this up */
+ OUT_BATCH(CP_PACKET0(packet[0].start, 3));
+ OUT_BATCH_TABLE((atom->cmd + 1), 4);
+
+ if (drb) {
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHOFFSET, 0));
+ OUT_BATCH_RELOC(0, drb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHPITCH, 0));
+ OUT_BATCH(zbpitch);
+ }
+
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZSTENCILCNTL, 0));
+ OUT_BATCH(atom->cmd[CTX_RB3D_ZSTENCILCNTL]);
+ OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 1));
+ OUT_BATCH(atom->cmd[CTX_PP_CNTL]);
+ OUT_BATCH(atom->cmd[CTX_RB3D_CNTL]);
+
+ if (rrb) {
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLOROFFSET, 0));
+ OUT_BATCH_RELOC(0, rrb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+ OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
+ OUT_BATCH_RELOC(cbpitch, rrb->bo, cbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ }
+
+ // if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM) {
+ // OUT_BATCH_TABLE((atom->cmd + 14), 4);
+ // }
+
+ END_BATCH();
+ BEGIN_BATCH_NO_AUTOSTATE(4);
+ OUT_BATCH(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
+ OUT_BATCH(0);
+ OUT_BATCH(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
+ if (rrb) {
+ OUT_BATCH(((rrb->base.Width - 1) << RADEON_RE_WIDTH_SHIFT) |
+ ((rrb->base.Height - 1) << RADEON_RE_HEIGHT_SHIFT));
+ } else {
+ OUT_BATCH(0);
+ }
+ END_BATCH();
+}
+
+static void cube_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&r100->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+ int i = atom->idx, j;
+ radeonTexObj *t = r100->state.texture.unit[i].texobj;
+ radeon_mipmap_level *lvl;
+
+ if (!(ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT))
+ return;
+
+ if (!t)
+ return;
+
+ if (!t->mt)
+ return;
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(atom->cmd, 3);
+ lvl = &t->mt->levels[0];
+ for (j = 0; j < 5; j++) {
+ OUT_BATCH_RELOC(lvl->faces[j].offset, t->mt->bo, lvl->faces[j].offset,
+ RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ }
+ END_BATCH();
+}
+
+static void cube_emit_cs(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&r100->radeon);
+ uint32_t dwords = atom->check(ctx, atom);
+ int i = atom->idx, j;
+ radeonTexObj *t = r100->state.texture.unit[i].texobj;
+ radeon_mipmap_level *lvl;
+ uint32_t base_reg;
+
+ if (!(ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT))
+ return;
+
+ if (!t)
+ return;
+
+ if (!t->mt)
+ return;
+
+ switch(i) {
+ case 1: base_reg = RADEON_PP_CUBIC_OFFSET_T1_0; break;
+ case 2: base_reg = RADEON_PP_CUBIC_OFFSET_T2_0; break;
+ default:
+ case 0: base_reg = RADEON_PP_CUBIC_OFFSET_T0_0; break;
+ };
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(atom->cmd, 2);
+ lvl = &t->mt->levels[0];
+ for (j = 0; j < 5; j++) {
+ OUT_BATCH(CP_PACKET0(base_reg + (4 * j), 0));
+ OUT_BATCH_RELOC(lvl->faces[j].offset, t->mt->bo, lvl->faces[j].offset,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ }
+ END_BATCH();
+}
+
+static void tex_emit(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&r100->radeon);
+ uint32_t dwords = atom->cmd_size;
+ int i = atom->idx;
+ radeonTexObj *t = r100->state.texture.unit[i].texobj;
+ radeon_mipmap_level *lvl;
+
+ if (t && t->mt && !t->image_override)
+ dwords += 2;
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+
+ OUT_BATCH_TABLE(atom->cmd, 3);
+ if (t && t->mt && !t->image_override) {
+ if ((ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT)) {
+ lvl = &t->mt->levels[0];
+ OUT_BATCH_RELOC(lvl->faces[5].offset, t->mt->bo, lvl->faces[5].offset,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ } else {
+ OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ }
+ } else if (!t) {
+ /* workaround for old CS mechanism */
+ OUT_BATCH(r100->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]);
+ // OUT_BATCH(r100->radeon.radeonScreen);
+ } else {
+ OUT_BATCH(t->override_offset);
+ }
+
+ OUT_BATCH_TABLE((atom->cmd+4), 5);
+ END_BATCH();
+}
+
+static void tex_emit_cs(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ r100ContextPtr r100 = R100_CONTEXT(ctx);
+ BATCH_LOCALS(&r100->radeon);
+ uint32_t dwords = atom->cmd_size;
+ int i = atom->idx;
+ radeonTexObj *t = r100->state.texture.unit[i].texobj;
+ radeon_mipmap_level *lvl;
+ int hastexture = 1;
+
+ if (!t)
+ hastexture = 0;
+ else {
+ if (!t->mt && !t->bo)
+ hastexture = 0;
+ }
+ dwords += 1;
+ if (hastexture)
+ dwords += 2;
+ else
+ dwords -= 2;
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+
+ OUT_BATCH(CP_PACKET0(RADEON_PP_TXFILTER_0 + (24 * i), 1));
+ OUT_BATCH_TABLE((atom->cmd + 1), 2);
+
+ if (hastexture) {
+ OUT_BATCH(CP_PACKET0(RADEON_PP_TXOFFSET_0 + (24 * i), 0));
+ if (t->mt && !t->image_override) {
+ if ((ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT)) {
+ lvl = &t->mt->levels[0];
+ OUT_BATCH_RELOC(lvl->faces[5].offset, t->mt->bo, lvl->faces[5].offset,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ } else {
+ OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ }
+ } else {
+ if (t->bo)
+ OUT_BATCH_RELOC(t->tile_bits, t->bo, 0,
+ RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ }
+ }
+
+ OUT_BATCH(CP_PACKET0(RADEON_PP_TXCBLEND_0 + (i * 24), 1));
+ OUT_BATCH_TABLE((atom->cmd+4), 2);
+ OUT_BATCH(CP_PACKET0(RADEON_PP_BORDER_COLOR_0 + (i * 4), 0));
+ OUT_BATCH((atom->cmd[TEX_PP_BORDER_COLOR]));
+ END_BATCH();
+}
+
+/* Initialize the context's hardware state.
+ */
+void radeonInitState( r100ContextPtr rmesa )
+{
+ GLcontext *ctx = rmesa->radeon.glCtx;
+ GLuint i;
+
+ rmesa->radeon.state.color.clear = 0x00000000;
switch ( ctx->Visual.depthBits ) {
case 16:
- rmesa->state.depth.clear = 0x0000ffff;
- rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff;
- depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
- rmesa->state.stencil.clear = 0x00000000;
+ rmesa->radeon.state.depth.clear = 0x0000ffff;
+ rmesa->radeon.state.stencil.clear = 0x00000000;
break;
case 24:
- rmesa->state.depth.clear = 0x00ffffff;
- rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff;
- depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
- rmesa->state.stencil.clear = 0xffff0000;
+ rmesa->radeon.state.depth.clear = 0x00ffffff;
+ rmesa->radeon.state.stencil.clear = 0xffff0000;
break;
default:
- fprintf( stderr, "Error: Unsupported depth %d... exiting\n",
- ctx->Visual.depthBits );
- exit( -1 );
+ break;
}
- /* Only have hw stencil when depth buffer is 24 bits deep */
- rmesa->state.stencil.hwBuffer = ( ctx->Visual.stencilBits > 0 &&
- ctx->Visual.depthBits == 24 );
+ rmesa->radeon.Fallback = 0;
- rmesa->Fallback = 0;
- if ( ctx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
- drawOffset = rmesa->radeonScreen->backOffset;
- drawPitch = rmesa->radeonScreen->backPitch;
- } else {
- drawOffset = rmesa->radeonScreen->frontOffset;
- drawPitch = rmesa->radeonScreen->frontPitch;
- }
+ rmesa->radeon.hw.max_state_size = 0;
- rmesa->hw.max_state_size = 0;
-
-#define ALLOC_STATE( ATOM, CHK, SZ, NM, FLAG ) \
+#define ALLOC_STATE_IDX( ATOM, CHK, SZ, NM, FLAG, IDX ) \
do { \
rmesa->hw.ATOM.cmd_size = SZ; \
- rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int)); \
- rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int)); \
- rmesa->hw.ATOM.name = NM; \
+ rmesa->hw.ATOM.cmd = (GLuint *)CALLOC(SZ * sizeof(int)); \
+ rmesa->hw.ATOM.lastcmd = (GLuint *)CALLOC(SZ * sizeof(int)); \
+ rmesa->hw.ATOM.name = NM; \
rmesa->hw.ATOM.is_tcl = FLAG; \
rmesa->hw.ATOM.check = check_##CHK; \
- rmesa->hw.ATOM.dirty = GL_TRUE; \
- rmesa->hw.max_state_size += SZ * sizeof(int); \
+ rmesa->hw.ATOM.dirty = GL_TRUE; \
+ rmesa->hw.ATOM.idx = IDX; \
+ rmesa->radeon.hw.max_state_size += SZ * sizeof(int); \
} while (0)
-
-
+
+#define ALLOC_STATE( ATOM, CHK, SZ, NM, FLAG ) \
+ ALLOC_STATE_IDX(ATOM, CHK, SZ, NM, FLAG, 0)
+
/* Allocate state buffers:
*/
- ALLOC_STATE( ctx, always, CTX_STATE_SIZE, "CTX/context", 0 );
+ ALLOC_STATE( ctx, always_add4, CTX_STATE_SIZE, "CTX/context", 0 );
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ rmesa->hw.ctx.emit = ctx_emit_cs;
+ rmesa->hw.ctx.check = check_always_ctx;
+ } else
+ rmesa->hw.ctx.emit = ctx_emit;
ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 );
ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 );
ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 );
@@ -229,82 +723,133 @@ void radeonInitState( radeonContextPtr rmesa )
ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 );
ALLOC_STATE( tcl, always, TCL_STATE_SIZE, "TCL/tcl", 1 );
ALLOC_STATE( mtl, tcl_lighting, MTL_STATE_SIZE, "MTL/material", 1 );
- ALLOC_STATE( grd, always, GRD_STATE_SIZE, "GRD/guard-band", 1 );
- ALLOC_STATE( fog, fog, FOG_STATE_SIZE, "FOG/fog", 1 );
- ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 1 );
- ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 1 );
- ALLOC_STATE( tex[0], tex0, TEX_STATE_SIZE, "TEX/tex-0", 0 );
- ALLOC_STATE( tex[1], tex1, TEX_STATE_SIZE, "TEX/tex-1", 0 );
- ALLOC_STATE( tex[2], tex2, TEX_STATE_SIZE, "TEX/tex-2", 0 );
- if (rmesa->radeonScreen->drmSupportsCubeMapsR100)
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ ALLOC_STATE( grd, always_add2, GRD_STATE_SIZE, "GRD/guard-band", 1 );
+ ALLOC_STATE( fog, fog_add4, FOG_STATE_SIZE, "FOG/fog", 1 );
+ ALLOC_STATE( glt, tcl_lighting_add4, GLT_STATE_SIZE, "GLT/light-global", 1 );
+ ALLOC_STATE( eye, tcl_lighting_add4, EYE_STATE_SIZE, "EYE/eye-vector", 1 );
+ ALLOC_STATE_IDX( tex[0], tex0_mm, TEX_STATE_SIZE, "TEX/tex-0", 0, 0);
+ ALLOC_STATE_IDX( tex[1], tex1_mm, TEX_STATE_SIZE, "TEX/tex-1", 0, 1);
+ ALLOC_STATE_IDX( tex[2], tex2_mm, TEX_STATE_SIZE, "TEX/tex-2", 0, 2);
+ ALLOC_STATE( mat[0], tcl_add4, MAT_STATE_SIZE, "MAT/modelproject", 1 );
+ ALLOC_STATE( mat[1], tcl_eyespace_or_fog_add4, MAT_STATE_SIZE, "MAT/modelview", 1 );
+ ALLOC_STATE( mat[2], tcl_eyespace_or_lighting_add4, MAT_STATE_SIZE, "MAT/it-modelview", 1 );
+ ALLOC_STATE( mat[3], tcl_tex0_add4, MAT_STATE_SIZE, "MAT/texmat0", 1 );
+ ALLOC_STATE( mat[4], tcl_tex1_add4, MAT_STATE_SIZE, "MAT/texmat1", 1 );
+ ALLOC_STATE( mat[5], tcl_tex2_add4, MAT_STATE_SIZE, "MAT/texmat2", 1 );
+ ALLOC_STATE( lit[0], tcl_lit0_add6, LIT_STATE_SIZE, "LIT/light-0", 1 );
+ ALLOC_STATE( lit[1], tcl_lit1_add6, LIT_STATE_SIZE, "LIT/light-1", 1 );
+ ALLOC_STATE( lit[2], tcl_lit2_add6, LIT_STATE_SIZE, "LIT/light-2", 1 );
+ ALLOC_STATE( lit[3], tcl_lit3_add6, LIT_STATE_SIZE, "LIT/light-3", 1 );
+ ALLOC_STATE( lit[4], tcl_lit4_add6, LIT_STATE_SIZE, "LIT/light-4", 1 );
+ ALLOC_STATE( lit[5], tcl_lit5_add6, LIT_STATE_SIZE, "LIT/light-5", 1 );
+ ALLOC_STATE( lit[6], tcl_lit6_add6, LIT_STATE_SIZE, "LIT/light-6", 1 );
+ ALLOC_STATE( lit[7], tcl_lit7_add6, LIT_STATE_SIZE, "LIT/light-7", 1 );
+ ALLOC_STATE( ucp[0], tcl_ucp0_add4, UCP_STATE_SIZE, "UCP/userclip-0", 1 );
+ ALLOC_STATE( ucp[1], tcl_ucp1_add4, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
+ ALLOC_STATE( ucp[2], tcl_ucp2_add4, UCP_STATE_SIZE, "UCP/userclip-2", 1 );
+ ALLOC_STATE( ucp[3], tcl_ucp3_add4, UCP_STATE_SIZE, "UCP/userclip-3", 1 );
+ ALLOC_STATE( ucp[4], tcl_ucp4_add4, UCP_STATE_SIZE, "UCP/userclip-4", 1 );
+ ALLOC_STATE( ucp[5], tcl_ucp5_add4, UCP_STATE_SIZE, "UCP/userclip-5", 1 );
+ } else {
+ ALLOC_STATE( grd, always, GRD_STATE_SIZE, "GRD/guard-band", 1 );
+ ALLOC_STATE( fog, fog, FOG_STATE_SIZE, "FOG/fog", 1 );
+ ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 1 );
+ ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 1 );
+ ALLOC_STATE_IDX( tex[0], tex0, TEX_STATE_SIZE, "TEX/tex-0", 0, 0);
+ ALLOC_STATE_IDX( tex[1], tex1, TEX_STATE_SIZE, "TEX/tex-1", 0, 1);
+ ALLOC_STATE_IDX( tex[2], tex2, TEX_STATE_SIZE, "TEX/tex-2", 0, 2);
+ ALLOC_STATE( mat[0], tcl, MAT_STATE_SIZE, "MAT/modelproject", 1 );
+ ALLOC_STATE( mat[1], tcl_eyespace_or_fog, MAT_STATE_SIZE, "MAT/modelview", 1 );
+ ALLOC_STATE( mat[2], tcl_eyespace_or_lighting, MAT_STATE_SIZE, "MAT/it-modelview", 1 );
+ ALLOC_STATE( mat[3], tcl_tex0, MAT_STATE_SIZE, "MAT/texmat0", 1 );
+ ALLOC_STATE( mat[4], tcl_tex1, MAT_STATE_SIZE, "MAT/texmat1", 1 );
+ ALLOC_STATE( mat[5], tcl_tex2, MAT_STATE_SIZE, "MAT/texmat2", 1 );
+ ALLOC_STATE( lit[0], tcl_lit0, LIT_STATE_SIZE, "LIT/light-0", 1 );
+ ALLOC_STATE( lit[1], tcl_lit1, LIT_STATE_SIZE, "LIT/light-1", 1 );
+ ALLOC_STATE( lit[2], tcl_lit2, LIT_STATE_SIZE, "LIT/light-2", 1 );
+ ALLOC_STATE( lit[3], tcl_lit3, LIT_STATE_SIZE, "LIT/light-3", 1 );
+ ALLOC_STATE( lit[4], tcl_lit4, LIT_STATE_SIZE, "LIT/light-4", 1 );
+ ALLOC_STATE( lit[5], tcl_lit5, LIT_STATE_SIZE, "LIT/light-5", 1 );
+ ALLOC_STATE( lit[6], tcl_lit6, LIT_STATE_SIZE, "LIT/light-6", 1 );
+ ALLOC_STATE( lit[7], tcl_lit7, LIT_STATE_SIZE, "LIT/light-7", 1 );
+ ALLOC_STATE( ucp[0], tcl_ucp0, UCP_STATE_SIZE, "UCP/userclip-0", 1 );
+ ALLOC_STATE( ucp[1], tcl_ucp1, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
+ ALLOC_STATE( ucp[2], tcl_ucp2, UCP_STATE_SIZE, "UCP/userclip-2", 1 );
+ ALLOC_STATE( ucp[3], tcl_ucp3, UCP_STATE_SIZE, "UCP/userclip-3", 1 );
+ ALLOC_STATE( ucp[4], tcl_ucp4, UCP_STATE_SIZE, "UCP/userclip-4", 1 );
+ ALLOC_STATE( ucp[5], tcl_ucp5, UCP_STATE_SIZE, "UCP/userclip-5", 1 );
+ }
+
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ ALLOC_STATE( stp, always, STP_STATE_SIZE, "STP/stp", 0 );
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (rmesa->radeon.radeonScreen->kernel_mm)
+ rmesa->hw.tex[i].emit = tex_emit_cs;
+ else
+ rmesa->hw.tex[i].emit = tex_emit;
+ }
+ if (rmesa->radeon.radeonScreen->drmSupportsCubeMapsR100)
{
- ALLOC_STATE( cube[0], cube0, CUBE_STATE_SIZE, "CUBE/cube-0", 0 );
- ALLOC_STATE( cube[1], cube1, CUBE_STATE_SIZE, "CUBE/cube-1", 0 );
- ALLOC_STATE( cube[2], cube2, CUBE_STATE_SIZE, "CUBE/cube-2", 0 );
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ ALLOC_STATE_IDX( cube[0], cube0_mm, CUBE_STATE_SIZE, "CUBE/cube-0", 0, 0 );
+ ALLOC_STATE_IDX( cube[1], cube1_mm, CUBE_STATE_SIZE, "CUBE/cube-1", 0, 1 );
+ ALLOC_STATE_IDX( cube[2], cube2_mm, CUBE_STATE_SIZE, "CUBE/cube-2", 0, 2 );
+ for (i = 0; i < 3; i++)
+ rmesa->hw.cube[i].emit = cube_emit_cs;
+ } else {
+ ALLOC_STATE_IDX( cube[0], cube0, CUBE_STATE_SIZE, "CUBE/cube-0", 0, 0 );
+ ALLOC_STATE_IDX( cube[1], cube1, CUBE_STATE_SIZE, "CUBE/cube-1", 0, 1 );
+ ALLOC_STATE_IDX( cube[2], cube2, CUBE_STATE_SIZE, "CUBE/cube-2", 0, 2 );
+ for (i = 0; i < 3; i++)
+ rmesa->hw.cube[i].emit = cube_emit;
+ }
}
else
{
- ALLOC_STATE( cube[0], never, CUBE_STATE_SIZE, "CUBE/cube-0", 0 );
- ALLOC_STATE( cube[1], never, CUBE_STATE_SIZE, "CUBE/cube-1", 0 );
- ALLOC_STATE( cube[2], never, CUBE_STATE_SIZE, "CUBE/cube-2", 0 );
- }
- ALLOC_STATE( mat[0], tcl, MAT_STATE_SIZE, "MAT/modelproject", 1 );
- ALLOC_STATE( mat[1], tcl_eyespace_or_fog, MAT_STATE_SIZE, "MAT/modelview", 1 );
- ALLOC_STATE( mat[2], tcl_eyespace_or_lighting, MAT_STATE_SIZE, "MAT/it-modelview", 1 );
- ALLOC_STATE( mat[3], tcl_tex0, MAT_STATE_SIZE, "MAT/texmat0", 1 );
- ALLOC_STATE( mat[4], tcl_tex1, MAT_STATE_SIZE, "MAT/texmat1", 1 );
- ALLOC_STATE( mat[5], tcl_tex2, MAT_STATE_SIZE, "MAT/texmat2", 1 );
- ALLOC_STATE( ucp[0], tcl_ucp0, UCP_STATE_SIZE, "UCP/userclip-0", 1 );
- ALLOC_STATE( ucp[1], tcl_ucp1, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
- ALLOC_STATE( ucp[2], tcl_ucp2, UCP_STATE_SIZE, "UCP/userclip-2", 1 );
- ALLOC_STATE( ucp[3], tcl_ucp3, UCP_STATE_SIZE, "UCP/userclip-3", 1 );
- ALLOC_STATE( ucp[4], tcl_ucp4, UCP_STATE_SIZE, "UCP/userclip-4", 1 );
- ALLOC_STATE( ucp[5], tcl_ucp5, UCP_STATE_SIZE, "UCP/userclip-5", 1 );
- ALLOC_STATE( lit[0], tcl_lit0, LIT_STATE_SIZE, "LIT/light-0", 1 );
- ALLOC_STATE( lit[1], tcl_lit1, LIT_STATE_SIZE, "LIT/light-1", 1 );
- ALLOC_STATE( lit[2], tcl_lit2, LIT_STATE_SIZE, "LIT/light-2", 1 );
- ALLOC_STATE( lit[3], tcl_lit3, LIT_STATE_SIZE, "LIT/light-3", 1 );
- ALLOC_STATE( lit[4], tcl_lit4, LIT_STATE_SIZE, "LIT/light-4", 1 );
- ALLOC_STATE( lit[5], tcl_lit5, LIT_STATE_SIZE, "LIT/light-5", 1 );
- ALLOC_STATE( lit[6], tcl_lit6, LIT_STATE_SIZE, "LIT/light-6", 1 );
- ALLOC_STATE( lit[7], tcl_lit7, LIT_STATE_SIZE, "LIT/light-7", 1 );
- ALLOC_STATE( txr[0], txr0, TXR_STATE_SIZE, "TXR/txr-0", 0 );
- ALLOC_STATE( txr[1], txr1, TXR_STATE_SIZE, "TXR/txr-1", 0 );
- ALLOC_STATE( txr[2], txr2, TXR_STATE_SIZE, "TXR/txr-2", 0 );
+ ALLOC_STATE_IDX( cube[0], never, CUBE_STATE_SIZE, "CUBE/cube-0", 0, 0 );
+ ALLOC_STATE_IDX( cube[1], never, CUBE_STATE_SIZE, "CUBE/cube-1", 0, 1 );
+ ALLOC_STATE_IDX( cube[2], never, CUBE_STATE_SIZE, "CUBE/cube-2", 0, 2 );
+ }
+ ALLOC_STATE_IDX( txr[0], txr0, TXR_STATE_SIZE, "TXR/txr-0", 0, 0 );
+ ALLOC_STATE_IDX( txr[1], txr1, TXR_STATE_SIZE, "TXR/txr-1", 0, 1 );
+ ALLOC_STATE_IDX( txr[2], txr2, TXR_STATE_SIZE, "TXR/txr-2", 0, 2 );
radeonSetUpAtomList( rmesa );
/* Fill in the packet headers:
*/
- rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(RADEON_EMIT_PP_MISC);
- rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(RADEON_EMIT_PP_CNTL);
- rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(RADEON_EMIT_RB3D_COLORPITCH);
- rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(RADEON_EMIT_RE_LINE_PATTERN);
- rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(RADEON_EMIT_SE_LINE_WIDTH);
- rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(RADEON_EMIT_RB3D_STENCILREFMASK);
- rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(RADEON_EMIT_SE_VPORT_XSCALE);
- rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(RADEON_EMIT_SE_CNTL);
- rmesa->hw.set.cmd[SET_CMD_1] = cmdpkt(RADEON_EMIT_SE_CNTL_STATUS);
- rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(RADEON_EMIT_RE_MISC);
- rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_0);
- rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_0);
- rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_1);
- rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_1);
- rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_2);
- rmesa->hw.tex[2].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_2);
- rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(RADEON_EMIT_PP_CUBIC_FACES_0);
- rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(RADEON_EMIT_PP_CUBIC_OFFSETS_T0);
- rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(RADEON_EMIT_PP_CUBIC_FACES_1);
- rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(RADEON_EMIT_PP_CUBIC_OFFSETS_T1);
- rmesa->hw.cube[2].cmd[CUBE_CMD_0] = cmdpkt(RADEON_EMIT_PP_CUBIC_FACES_2);
- rmesa->hw.cube[2].cmd[CUBE_CMD_1] = cmdpkt(RADEON_EMIT_PP_CUBIC_OFFSETS_T2);
- rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR);
- rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT);
+ rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_MISC);
+ rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CNTL);
+ rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(rmesa, RADEON_EMIT_RB3D_COLORPITCH);
+ rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_LINE_PATTERN);
+ rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_SE_LINE_WIDTH);
+ rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RB3D_STENCILREFMASK);
+ rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_VPORT_XSCALE);
+ rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_CNTL);
+ rmesa->hw.set.cmd[SET_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_SE_CNTL_STATUS);
+ rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_MISC);
+ rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TXFILTER_0);
+ rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_BORDER_COLOR_0);
+ rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TXFILTER_1);
+ rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_BORDER_COLOR_1);
+ rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TXFILTER_2);
+ rmesa->hw.tex[2].cmd[TEX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_BORDER_COLOR_2);
+ rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_FACES_0);
+ rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_OFFSETS_T0);
+ rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_FACES_1);
+ rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_OFFSETS_T1);
+ rmesa->hw.cube[2].cmd[CUBE_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_FACES_2);
+ rmesa->hw.cube[2].cmd[CUBE_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_OFFSETS_T2);
+ rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_ZBIAS_FACTOR);
+ rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT);
rmesa->hw.mtl.cmd[MTL_CMD_0] =
- cmdpkt(RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED);
- rmesa->hw.txr[0].cmd[TXR_CMD_0] = cmdpkt(RADEON_EMIT_PP_TEX_SIZE_0);
- rmesa->hw.txr[1].cmd[TXR_CMD_0] = cmdpkt(RADEON_EMIT_PP_TEX_SIZE_1);
- rmesa->hw.txr[2].cmd[TXR_CMD_0] = cmdpkt(RADEON_EMIT_PP_TEX_SIZE_2);
+ cmdpkt(rmesa, RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED);
+ rmesa->hw.txr[0].cmd[TXR_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TEX_SIZE_0);
+ rmesa->hw.txr[1].cmd[TXR_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TEX_SIZE_1);
+ rmesa->hw.txr[2].cmd[TXR_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TEX_SIZE_2);
rmesa->hw.grd.cmd[GRD_CMD_0] =
cmdscl( RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 );
rmesa->hw.fog.cmd[FOG_CMD_0] =
@@ -331,6 +876,26 @@ void radeonInitState( radeonContextPtr rmesa )
cmdvec( RADEON_VS_UCP_ADDR + i, 1, 4 );
}
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ rmesa->hw.stp.cmd[STP_CMD_0] = CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0);
+ rmesa->hw.stp.cmd[STP_DATA_0] = 0;
+ rmesa->hw.stp.cmd[STP_CMD_1] = CP_PACKET0_ONE(RADEON_RE_STIPPLE_DATA, 31);
+
+ rmesa->hw.grd.emit = scl_emit;
+ rmesa->hw.fog.emit = vec_emit;
+ rmesa->hw.glt.emit = vec_emit;
+ rmesa->hw.eye.emit = vec_emit;
+
+ for (i = 0; i < 6; i++)
+ rmesa->hw.mat[i].emit = vec_emit;
+
+ for (i = 0; i < 8; i++)
+ rmesa->hw.lit[i].emit = lit_emit;
+
+ for (i = 0; i < 6; i++)
+ rmesa->hw.ucp[i].emit = vec_emit;
+ }
+
rmesa->last_ReallyEnabled = -1;
/* Initial Harware state:
@@ -352,19 +917,7 @@ void radeonInitState( radeonContextPtr rmesa )
RADEON_SRC_BLEND_GL_ONE |
RADEON_DST_BLEND_GL_ZERO );
- rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] =
- rmesa->radeonScreen->depthOffset + rmesa->radeonScreen->fbLocation;
-
- rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] =
- ((rmesa->radeonScreen->depthPitch &
- RADEON_DEPTHPITCH_MASK) |
- RADEON_DEPTH_ENDIAN_NO_SWAP);
-
- if (rmesa->using_hyperz)
- rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] |= RADEON_DEPTH_HYPERZ;
-
- rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (depth_fmt |
- RADEON_Z_TEST_LESS |
+ rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (RADEON_Z_TEST_LESS |
RADEON_STENCIL_TEST_ALWAYS |
RADEON_STENCIL_FAIL_KEEP |
RADEON_STENCIL_ZPASS_KEEP |
@@ -374,7 +927,7 @@ void radeonInitState( radeonContextPtr rmesa )
if (rmesa->using_hyperz) {
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_COMPRESSION_ENABLE |
RADEON_Z_DECOMPRESSION_ENABLE;
- if (rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
+ if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
/* works for q3, but slight rendering errors with glxgears ? */
/* rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_HIERARCHY_ENABLE;*/
/* need this otherwise get lots of lockups with q3 ??? */
@@ -386,10 +939,9 @@ void radeonInitState( radeonContextPtr rmesa )
RADEON_ANTI_ALIAS_NONE);
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = (RADEON_PLANE_MASK_ENABLE |
- color_fmt |
RADEON_ZBLOCK16);
- switch ( driQueryOptioni( &rmesa->optionCache, "dither_mode" ) ) {
+ switch ( driQueryOptioni( &rmesa->radeon.optionCache, "dither_mode" ) ) {
case DRI_CONF_DITHER_XERRORDIFFRESET:
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_INIT;
break;
@@ -397,30 +949,17 @@ void radeonInitState( radeonContextPtr rmesa )
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_SCALE_DITHER_ENABLE;
break;
}
- if ( driQueryOptioni( &rmesa->optionCache, "round_mode" ) ==
+ if ( driQueryOptioni( &rmesa->radeon.optionCache, "round_mode" ) ==
DRI_CONF_ROUND_ROUND )
- rmesa->state.color.roundEnable = RADEON_ROUND_ENABLE;
+ rmesa->radeon.state.color.roundEnable = RADEON_ROUND_ENABLE;
else
- rmesa->state.color.roundEnable = 0;
- if ( driQueryOptioni (&rmesa->optionCache, "color_reduction" ) ==
+ rmesa->radeon.state.color.roundEnable = 0;
+ if ( driQueryOptioni (&rmesa->radeon.optionCache, "color_reduction" ) ==
DRI_CONF_COLOR_REDUCTION_DITHER )
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
else
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable;
-
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((drawOffset +
- rmesa->radeonScreen->fbLocation)
- & RADEON_COLOROFFSET_MASK);
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((drawPitch &
- RADEON_COLORPITCH_MASK) |
- RADEON_COLOR_ENDIAN_NO_SWAP);
-
-
- /* (fixed size) sarea is initialized to zero afaics so can omit version check. Phew! */
- if (rmesa->sarea->tiling_enabled) {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= RADEON_COLOR_TILE_ENABLE;
- }
rmesa->hw.set.cmd[SET_SE_CNTL] = (RADEON_FFACE_CULL_CCW |
RADEON_BFACE_SOLID |
@@ -444,7 +983,7 @@ void radeonInitState( radeonContextPtr rmesa )
RADEON_VC_NO_SWAP;
#endif
- if (!(rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
+ if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] |= RADEON_TCL_BYPASS;
}
@@ -491,8 +1030,8 @@ void radeonInitState( radeonContextPtr rmesa )
(2 << RADEON_TXFORMAT_HEIGHT_SHIFT));
/* Initialize the texture offset to the start of the card texture heap */
- rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET] =
- rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ // rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET] =
+ // rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.tex[i].cmd[TEX_PP_BORDER_COLOR] = 0;
rmesa->hw.tex[i].cmd[TEX_PP_TXCBLEND] =
@@ -513,15 +1052,15 @@ void radeonInitState( radeonContextPtr rmesa )
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_FACES] = 0;
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_0] =
- rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_1] =
- rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_2] =
- rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_3] =
- rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_4] =
- rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
+ rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
}
/* Can only add ST1 at the time of doing some multitex but can keep
@@ -612,6 +1151,14 @@ void radeonInitState( radeonContextPtr rmesa )
rmesa->hw.eye.cmd[EYE_Y] = 0;
rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE;
rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE;
-
- rmesa->hw.all_dirty = GL_TRUE;
+
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ radeon_init_query_stateobj(&rmesa->radeon, R100_QUERYOBJ_CMDSIZE);
+ rmesa->radeon.query.queryobj.cmd[R100_QUERYOBJ_CMD_0] = CP_PACKET0(RADEON_RB3D_ZPASS_DATA, 0);
+ rmesa->radeon.query.queryobj.cmd[R100_QUERYOBJ_DATA_0] = 0;
+ }
+
+ rmesa->radeon.hw.all_dirty = GL_TRUE;
+
+ rcommonInitCmdBuf(&rmesa->radeon);
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.c b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
index ebea1fecdc..e61f59eaea 100644
--- a/src/mesa/drivers/dri/radeon/radeon_swtcl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
@@ -38,6 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/enums.h"
#include "main/imports.h"
#include "main/macros.h"
+#include "main/simple_list.h"
#include "swrast_setup/swrast_setup.h"
#include "math/m_translate.h"
@@ -50,10 +51,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_state.h"
#include "radeon_swtcl.h"
#include "radeon_tcl.h"
+#include "radeon_debug.h"
-static void flush_last_swtcl_prim( radeonContextPtr rmesa );
-
/* R100: xyzw, c0, c1/fog, stq[0..2] = 4+1+1+3*3 = 15 right? */
/* R200: xyzw, c0, c1/fog, strq[0..5] = 4+1+1+4*6 = 30 */
#define RADEON_MAX_TNL_VERTEX_SIZE (15 * sizeof(GLfloat)) /* for mesa _tnl stage */
@@ -64,18 +64,18 @@ static void flush_last_swtcl_prim( radeonContextPtr rmesa );
#define EMIT_ATTR( ATTR, STYLE, F0 ) \
do { \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = (ATTR); \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = (STYLE); \
- rmesa->swtcl.vertex_attr_count++; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = (ATTR); \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = (STYLE); \
+ rmesa->radeon.swtcl.vertex_attr_count++; \
fmt_0 |= F0; \
} while (0)
#define EMIT_PAD( N ) \
do { \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = 0; \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = EMIT_PAD; \
- rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].offset = (N); \
- rmesa->swtcl.vertex_attr_count++; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = 0; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = EMIT_PAD; \
+ rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].offset = (N); \
+ rmesa->radeon.swtcl.vertex_attr_count++; \
} while (0)
static GLuint radeon_cp_vc_frmts[3][2] =
@@ -87,7 +87,7 @@ static GLuint radeon_cp_vc_frmts[3][2] =
static void radeonSetVertexFormat( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ r100ContextPtr rmesa = R100_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
DECLARE_RENDERINPUTS(index_bitset);
@@ -106,7 +106,7 @@ static void radeonSetVertexFormat( GLcontext *ctx )
}
assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL );
- rmesa->swtcl.vertex_attr_count = 0;
+ rmesa->radeon.swtcl.vertex_attr_count = 0;
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
* build up a hardware vertex.
@@ -204,33 +204,52 @@ static void radeonSetVertexFormat( GLcontext *ctx )
}
}
- if (!RENDERINPUTS_EQUAL( rmesa->tnl_index_bitset, index_bitset ) ||
+ if (!RENDERINPUTS_EQUAL( rmesa->radeon.tnl_index_bitset, index_bitset ) ||
fmt_0 != rmesa->swtcl.vertex_format) {
RADEON_NEWPRIM(rmesa);
rmesa->swtcl.vertex_format = fmt_0;
- rmesa->swtcl.vertex_size =
+ rmesa->radeon.swtcl.vertex_size =
_tnl_install_attrs( ctx,
- rmesa->swtcl.vertex_attrs,
- rmesa->swtcl.vertex_attr_count,
+ rmesa->radeon.swtcl.vertex_attrs,
+ rmesa->radeon.swtcl.vertex_attr_count,
NULL, 0 );
- rmesa->swtcl.vertex_size /= 4;
- RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset );
- if (RADEON_DEBUG & DEBUG_VERTS)
- fprintf( stderr, "%s: vertex_size= %d floats\n",
- __FUNCTION__, rmesa->swtcl.vertex_size);
+ rmesa->radeon.swtcl.vertex_size /= 4;
+ RENDERINPUTS_COPY( rmesa->radeon.tnl_index_bitset, index_bitset );
+ radeon_print(RADEON_SWRENDER, RADEON_VERBOSE,
+ "%s: vertex_size= %d floats\n", __FUNCTION__, rmesa->radeon.swtcl.vertex_size);
}
}
+static void radeon_predict_emit_size( r100ContextPtr rmesa )
+{
+
+ if (!rmesa->radeon.swtcl.emit_prediction) {
+ const int state_size = radeonCountStateEmitSize( &rmesa->radeon );
+ const int scissor_size = 8;
+ const int prims_size = 8;
+ const int vertex_size = 7;
+
+ if (rcommonEnsureCmdBufSpace(&rmesa->radeon,
+ state_size +
+ (scissor_size + prims_size + vertex_size),
+ __FUNCTION__))
+ rmesa->radeon.swtcl.emit_prediction = radeonCountStateEmitSize( &rmesa->radeon );
+ else
+ rmesa->radeon.swtcl.emit_prediction = state_size;
+ rmesa->radeon.swtcl.emit_prediction += scissor_size + prims_size + vertex_size
+ + rmesa->radeon.cmdbuf.cs->cdw;
+ }
+}
static void radeonRenderStart( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ r100ContextPtr rmesa = R100_CONTEXT( ctx );
- radeonSetVertexFormat( ctx );
-
- if (rmesa->dma.flush != 0 &&
- rmesa->dma.flush != flush_last_swtcl_prim)
- rmesa->dma.flush( rmesa );
+ radeonSetVertexFormat( ctx );
+
+ if (rmesa->radeon.dma.flush != 0 &&
+ rmesa->radeon.dma.flush != rcommon_flush_last_swtcl_prim)
+ rmesa->radeon.dma.flush( ctx );
}
@@ -241,7 +260,7 @@ static void radeonRenderStart( GLcontext *ctx )
*/
void radeonChooseVertexState( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ r100ContextPtr rmesa = R100_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT];
@@ -254,7 +273,7 @@ void radeonChooseVertexState( GLcontext *ctx )
* rasterization fallback. As this function will be called again when we
* leave a rasterization fallback, we can just skip it for now.
*/
- if (rmesa->Fallback != 0)
+ if (rmesa->radeon.Fallback != 0)
return;
/* HW perspective divide is a win, but tiny vertex formats are a
@@ -281,80 +300,33 @@ void radeonChooseVertexState( GLcontext *ctx )
}
}
-
-/* Flush vertices in the current dma region.
- */
-static void flush_last_swtcl_prim( radeonContextPtr rmesa )
+void r100_swtcl_flush(GLcontext *ctx, uint32_t current_offset)
{
- if (RADEON_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
- rmesa->dma.flush = NULL;
- if (rmesa->dma.current.buf) {
- struct radeon_dma_region *current = &rmesa->dma.current;
- GLuint current_offset = (rmesa->radeonScreen->gart_buffer_offset +
- current->buf->buf->idx * RADEON_BUFFER_SIZE +
- current->start);
- assert (!(rmesa->swtcl.hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
+ radeonEmitState(&rmesa->radeon);
+ radeonEmitVertexAOS( rmesa,
+ rmesa->radeon.swtcl.vertex_size,
+ first_elem(&rmesa->radeon.dma.reserved)->bo,
+ current_offset);
- assert (current->start +
- rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
- current->ptr);
+
+ radeonEmitVbufPrim( rmesa,
+ rmesa->swtcl.vertex_format,
+ rmesa->radeon.swtcl.hw_primitive,
+ rmesa->radeon.swtcl.numverts);
+ if ( rmesa->radeon.swtcl.emit_prediction < rmesa->radeon.cmdbuf.cs->cdw )
+ WARN_ONCE("Rendering was %d commands larger than predicted size."
+ " We might overflow command buffer.\n",
+ rmesa->radeon.cmdbuf.cs->cdw - rmesa->radeon.swtcl.emit_prediction );
- if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
- radeonEnsureCmdBufSpace( rmesa, VERT_AOS_BUFSZ +
- rmesa->hw.max_state_size + VBUF_BUFSZ );
- radeonEmitVertexAOS( rmesa,
- rmesa->swtcl.vertex_size,
- current_offset);
+ rmesa->radeon.swtcl.emit_prediction = 0;
- radeonEmitVbufPrim( rmesa,
- rmesa->swtcl.vertex_format,
- rmesa->swtcl.hw_primitive,
- rmesa->swtcl.numverts);
- }
-
- rmesa->swtcl.numverts = 0;
- current->start = current->ptr;
- }
}
-
-/* Alloc space in the current dma region.
- */
-static INLINE void *
-radeonAllocDmaLowVerts( radeonContextPtr rmesa, int nverts, int vsize )
-{
- GLuint bytes = vsize * nverts;
-
- if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
- radeonRefillCurrentDmaRegion( rmesa );
-
- if (!rmesa->dma.flush) {
- rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
- rmesa->dma.flush = flush_last_swtcl_prim;
- }
-
- assert( vsize == rmesa->swtcl.vertex_size * 4 );
- assert( rmesa->dma.flush == flush_last_swtcl_prim );
- assert (rmesa->dma.current.start +
- rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
- rmesa->dma.current.ptr);
-
-
- {
- GLubyte *head = (GLubyte *)(rmesa->dma.current.address + rmesa->dma.current.ptr);
- rmesa->dma.current.ptr += bytes;
- rmesa->swtcl.numverts += nverts;
- return head;
- }
-
-}
-
-
/*
* Render unclipped vertex buffers by emitting vertices directly to
* dma buffers. Use strip/fan hardware primitives where possible.
@@ -387,22 +359,31 @@ static const GLuint hw_prim[GL_POLYGON+1] = {
};
static INLINE void
-radeonDmaPrimitive( radeonContextPtr rmesa, GLenum prim )
+radeonDmaPrimitive( r100ContextPtr rmesa, GLenum prim )
{
RADEON_NEWPRIM( rmesa );
- rmesa->swtcl.hw_primitive = hw_prim[prim];
- assert(rmesa->dma.current.ptr == rmesa->dma.current.start);
+ rmesa->radeon.swtcl.hw_primitive = hw_prim[prim];
+ // assert(rmesa->radeon.dma.current.ptr == rmesa->radeon.dma.current.start);
+}
+
+static void* radeon_alloc_verts( r100ContextPtr rmesa , GLuint nr, GLuint size )
+{
+ void *rv;
+ do {
+ radeon_predict_emit_size( rmesa );
+ rv = rcommonAllocDmaLowVerts( &rmesa->radeon, nr, size );
+ } while (!rv);
+ return rv;
}
-#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
+#define LOCAL_VARS r100ContextPtr rmesa = R100_CONTEXT(ctx)
#define INIT( prim ) radeonDmaPrimitive( rmesa, prim )
#define FLUSH() RADEON_NEWPRIM( rmesa )
-#define GET_CURRENT_VB_MAX_VERTS() \
- (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4))
+#define GET_CURRENT_VB_MAX_VERTS() 10\
+// (((int)rmesa->radeon.dma.current.end - (int)rmesa->radeon.dma.current.ptr) / (rmesa->radeon.swtcl.vertex_size*4))
#define GET_SUBSEQUENT_VB_MAX_VERTS() \
- ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4))
-#define ALLOC_VERTS( nr ) \
- radeonAllocDmaLowVerts( rmesa, nr, rmesa->swtcl.vertex_size * 4 )
+ ((RADEON_BUFFER_SIZE) / (rmesa->radeon.swtcl.vertex_size*4))
+#define ALLOC_VERTS( nr ) radeon_alloc_verts( rmesa, nr, rmesa->radeon.swtcl.vertex_size * 4 )
#define EMIT_VERTS( ctx, j, nr, buf ) \
_tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf)
@@ -418,16 +399,13 @@ radeonDmaPrimitive( radeonContextPtr rmesa, GLenum prim )
static GLboolean radeon_run_render( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
tnl_render_func *tab = TAG(render_tab_verts);
GLuint i;
- if (rmesa->swtcl.indexed_verts.buf)
- RELEASE_ELT_VERTS();
-
- if (rmesa->swtcl.RenderIndex != 0 ||
+ if (rmesa->radeon.swtcl.RenderIndex != 0 ||
!radeon_dma_validate_render( ctx, VB ))
return GL_TRUE;
@@ -442,8 +420,8 @@ static GLboolean radeon_run_render( GLcontext *ctx,
if (!length)
continue;
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "radeon_render.c: prim %s %d..%d\n",
+ radeon_print(RADEON_SWRENDER, RADEON_NORMAL,
+ "radeon_render.c: prim %s %d..%d\n",
_mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK),
start, start+length);
@@ -496,13 +474,13 @@ static void radeonResetLineStipple( GLcontext *ctx );
#undef LOCAL_VARS
#undef ALLOC_VERTS
-#define CTX_ARG radeonContextPtr rmesa
-#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
-#define ALLOC_VERTS( n, size ) radeonAllocDmaLowVerts( rmesa, n, (size) * 4 )
+#define CTX_ARG r100ContextPtr rmesa
+#define GET_VERTEX_DWORDS() rmesa->radeon.swtcl.vertex_size
+#define ALLOC_VERTS( n, size ) radeon_alloc_verts( rmesa, n, (size) * 4 )
#undef LOCAL_VARS
#define LOCAL_VARS \
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
- const char *radeonverts = (char *)rmesa->swtcl.verts;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx); \
+ const char *radeonverts = (char *)rmesa->radeon.swtcl.verts;
#define VERT(x) (radeonVertex *)(radeonverts + ((x) * (vertsize) * sizeof(int)))
#define VERTEX radeonVertex
#undef TAG
@@ -560,7 +538,7 @@ static struct {
#define VERT_Y(_v) _v->v.y
#define VERT_Z(_v) _v->v.z
#define AREA_IS_CCW( a ) (a < 0)
-#define GET_VERTEX(e) (rmesa->swtcl.verts + ((e) * rmesa->swtcl.vertex_size * sizeof(int)))
+#define GET_VERTEX(e) (rmesa->radeon.swtcl.verts + ((e) * rmesa->radeon.swtcl.vertex_size * sizeof(int)))
#define VERT_SET_RGBA( v, c ) \
do { \
@@ -606,8 +584,8 @@ do { \
#undef INIT
#define LOCAL_VARS(n) \
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
- GLuint color[n], spec[n]; \
+ r100ContextPtr rmesa = R100_CONTEXT(ctx); \
+ GLuint color[n] = {0}, spec[n] = {0}; \
GLuint coloroffset = rmesa->swtcl.coloroffset; \
GLuint specoffset = rmesa->swtcl.specoffset; \
(void) color; (void) spec; (void) coloroffset; (void) specoffset;
@@ -617,7 +595,7 @@ do { \
***********************************************************************/
#define RASTERIZE(x) radeonRasterPrimitive( ctx, reduced_hw_prim[x] )
-#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
+#define RENDER_PRIMITIVE rmesa->radeon.swtcl.render_primitive
#undef TAG
#define TAG(x) x
#include "tnl_dd/t_dd_unfilled.h"
@@ -673,9 +651,9 @@ static void init_rast_tab( void )
} while (0)
#undef LOCAL_VARS
#define LOCAL_VARS \
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
- const GLuint vertsize = rmesa->swtcl.vertex_size; \
- const char *radeonverts = (char *)rmesa->swtcl.verts; \
+ r100ContextPtr rmesa = R100_CONTEXT(ctx); \
+ const GLuint vertsize = rmesa->radeon.swtcl.vertex_size; \
+ const char *radeonverts = (char *)rmesa->radeon.swtcl.verts; \
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
const GLboolean stipple = ctx->Line.StippleFlag; \
(void) elt; (void) stipple;
@@ -700,17 +678,17 @@ static void init_rast_tab( void )
void radeonChooseRenderState( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint index = 0;
GLuint flags = ctx->_TriangleCaps;
- if (!rmesa->TclFallback || rmesa->Fallback)
+ if (!rmesa->radeon.TclFallback || rmesa->radeon.Fallback)
return;
if (flags & DD_TRI_LIGHT_TWOSIDE) index |= RADEON_TWOSIDE_BIT;
if (flags & DD_TRI_UNFILLED) index |= RADEON_UNFILLED_BIT;
- if (index != rmesa->swtcl.RenderIndex) {
+ if (index != rmesa->radeon.swtcl.RenderIndex) {
tnl->Driver.Render.Points = rast_tab[index].points;
tnl->Driver.Render.Line = rast_tab[index].line;
tnl->Driver.Render.ClippedLine = rast_tab[index].line;
@@ -727,7 +705,7 @@ void radeonChooseRenderState( GLcontext *ctx )
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
}
- rmesa->swtcl.RenderIndex = index;
+ rmesa->radeon.swtcl.RenderIndex = index;
}
}
@@ -739,18 +717,18 @@ void radeonChooseRenderState( GLcontext *ctx )
static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
- if (rmesa->swtcl.hw_primitive != hwprim) {
+ if (rmesa->radeon.swtcl.hw_primitive != hwprim) {
RADEON_NEWPRIM( rmesa );
- rmesa->swtcl.hw_primitive = hwprim;
+ rmesa->radeon.swtcl.hw_primitive = hwprim;
}
}
static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- rmesa->swtcl.render_primitive = prim;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ rmesa->radeon.swtcl.render_primitive = prim;
if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED))
radeonRasterPrimitive( ctx, reduced_hw_prim[prim] );
}
@@ -761,7 +739,7 @@ static void radeonRenderFinish( GLcontext *ctx )
static void radeonResetLineStipple( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
RADEON_STATECHANGE( rmesa, lin );
}
@@ -795,25 +773,25 @@ static const char *getFallbackString(GLuint bit)
void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
- GLuint oldfallback = rmesa->Fallback;
+ GLuint oldfallback = rmesa->radeon.Fallback;
if (mode) {
- rmesa->Fallback |= bit;
+ rmesa->radeon.Fallback |= bit;
if (oldfallback == 0) {
- RADEON_FIREVERTICES( rmesa );
+ radeon_firevertices(&rmesa->radeon);
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_TRUE );
_swsetup_Wakeup( ctx );
- rmesa->swtcl.RenderIndex = ~0;
- if (RADEON_DEBUG & DEBUG_FALLBACKS) {
+ rmesa->radeon.swtcl.RenderIndex = ~0;
+ if (RADEON_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "Radeon begin rasterization fallback: 0x%x %s\n",
bit, getFallbackString(bit));
}
}
}
else {
- rmesa->Fallback &= ~bit;
+ rmesa->radeon.Fallback &= ~bit;
if (oldfallback == bit) {
_swrast_flush( ctx );
tnl->Driver.Render.Start = radeonRenderStart;
@@ -826,18 +804,18 @@ void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple;
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_FALSE );
- if (rmesa->TclFallback) {
- /* These are already done if rmesa->TclFallback goes to
+ if (rmesa->radeon.TclFallback) {
+ /* These are already done if rmesa->radeon.TclFallback goes to
* zero above. But not if it doesn't (RADEON_NO_TCL for
* example?)
*/
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
- RENDERINPUTS_ZERO( rmesa->tnl_index_bitset );
+ RENDERINPUTS_ZERO( rmesa->radeon.tnl_index_bitset );
radeonChooseVertexState( ctx );
radeonChooseRenderState( ctx );
}
- if (RADEON_DEBUG & DEBUG_FALLBACKS) {
+ if (RADEON_DEBUG & RADEON_FALLBACKS) {
fprintf(stderr, "Radeon end rasterization fallback: 0x%x %s\n",
bit, getFallbackString(bit));
}
@@ -853,13 +831,14 @@ void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
void radeonInitSwtcl( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
static int firsttime = 1;
if (firsttime) {
init_rast_tab();
firsttime = 0;
}
+ rmesa->radeon.swtcl.emit_prediction = 0;
tnl->Driver.Render.Start = radeonRenderStart;
tnl->Driver.Render.Finish = radeonRenderFinish;
@@ -872,18 +851,9 @@ void radeonInitSwtcl( GLcontext *ctx )
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
RADEON_MAX_TNL_VERTEX_SIZE);
- rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
- rmesa->swtcl.RenderIndex = ~0;
- rmesa->swtcl.render_primitive = GL_TRIANGLES;
- rmesa->swtcl.hw_primitive = 0;
+ rmesa->radeon.swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
+ rmesa->radeon.swtcl.RenderIndex = ~0;
+ rmesa->radeon.swtcl.render_primitive = GL_TRIANGLES;
+ rmesa->radeon.swtcl.hw_primitive = 0;
}
-
-void radeonDestroySwtcl( GLcontext *ctx )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-
- if (rmesa->swtcl.indexed_verts.buf)
- radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts,
- __FUNCTION__ );
-}
diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.h b/src/mesa/drivers/dri/radeon/radeon_swtcl.h
index e485052ad7..da89158eeb 100644
--- a/src/mesa/drivers/dri/radeon/radeon_swtcl.h
+++ b/src/mesa/drivers/dri/radeon/radeon_swtcl.h
@@ -40,7 +40,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_context.h"
extern void radeonInitSwtcl( GLcontext *ctx );
-extern void radeonDestroySwtcl( GLcontext *ctx );
extern void radeonChooseRenderState( GLcontext *ctx );
extern void radeonChooseVertexState( GLcontext *ctx );
@@ -63,5 +62,5 @@ extern void radeon_translate_vertex( GLcontext *ctx,
extern void radeon_print_vertex( GLcontext *ctx, const radeonVertex *v );
-
+extern void r100_swtcl_flush(GLcontext *ctx, uint32_t current_offset);
#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_tcl.c b/src/mesa/drivers/dri/radeon/radeon_tcl.c
index 779e9ae5df..b334ea05e5 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tcl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_tcl.c
@@ -42,6 +42,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
+#include "radeon_common.h"
#include "radeon_context.h"
#include "radeon_state.h"
#include "radeon_ioctl.h"
@@ -49,6 +50,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_tcl.h"
#include "radeon_swtcl.h"
#include "radeon_maos.h"
+#include "radeon_common_context.h"
@@ -104,7 +106,7 @@ static GLboolean discrete_prim[0x10] = {
};
-#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
+#define LOCAL_VARS r100ContextPtr rmesa = R100_CONTEXT(ctx)
#define ELT_TYPE GLushort
#define ELT_INIT(prim, hw_prim) \
@@ -125,7 +127,7 @@ static GLboolean discrete_prim[0x10] = {
#define RESET_STIPPLE() do { \
RADEON_STATECHANGE( rmesa, lin ); \
- radeonEmitState( rmesa ); \
+ radeonEmitState(&rmesa->radeon); \
} while (0)
#define AUTO_STIPPLE( mode ) do { \
@@ -136,31 +138,26 @@ static GLboolean discrete_prim[0x10] = {
else \
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
~RADEON_LINE_PATTERN_AUTO_RESET; \
- radeonEmitState( rmesa ); \
+ radeonEmitState(&rmesa->radeon); \
} while (0)
#define ALLOC_ELTS(nr) radeonAllocElts( rmesa, nr )
-static GLushort *radeonAllocElts( radeonContextPtr rmesa, GLuint nr )
+static GLushort *radeonAllocElts( r100ContextPtr rmesa, GLuint nr )
{
- if (rmesa->dma.flush)
- rmesa->dma.flush( rmesa );
+ if (rmesa->radeon.dma.flush)
+ rmesa->radeon.dma.flush( rmesa->radeon.glCtx );
- radeonEnsureCmdBufSpace(rmesa, AOS_BUFSZ(rmesa->tcl.nr_aos_components) +
- rmesa->hw.max_state_size + ELTS_BUFSZ(nr));
+ radeonEmitAOS( rmesa,
+ rmesa->radeon.tcl.aos_count, 0 );
- radeonEmitAOS( rmesa,
- rmesa->tcl.aos_components,
- rmesa->tcl.nr_aos_components, 0 );
-
- return radeonAllocEltsOpenEnded( rmesa,
- rmesa->tcl.vertex_format,
- rmesa->tcl.hw_primitive, nr );
+ return radeonAllocEltsOpenEnded( rmesa, rmesa->tcl.vertex_format,
+ rmesa->tcl.hw_primitive, nr );
}
-#define CLOSE_ELTS() RADEON_NEWPRIM( rmesa )
+#define CLOSE_ELTS() if (0) RADEON_NEWPRIM( rmesa )
@@ -174,15 +171,11 @@ static void radeonEmitPrim( GLcontext *ctx,
GLuint start,
GLuint count)
{
- radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ r100ContextPtr rmesa = R100_CONTEXT( ctx );
radeonTclPrimitive( ctx, prim, hwprim );
- radeonEnsureCmdBufSpace( rmesa, AOS_BUFSZ(rmesa->tcl.nr_aos_components) +
- rmesa->hw.max_state_size + VBUF_BUFSZ );
-
radeonEmitAOS( rmesa,
- rmesa->tcl.aos_components,
- rmesa->tcl.nr_aos_components,
+ rmesa->radeon.tcl.aos_count,
start );
/* Why couldn't this packet have taken an offset param?
@@ -197,6 +190,8 @@ static void radeonEmitPrim( GLcontext *ctx,
radeonEmitPrim( ctx, prim, hwprim, start, count ); \
(void) rmesa; } while (0)
+#define MAX_CONVERSION_SIZE 40
+
/* Try & join small primitives
*/
#if 0
@@ -254,7 +249,7 @@ void radeonTclPrimitive( GLcontext *ctx,
GLenum prim,
int hw_prim )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint se_cntl;
GLuint newprim = hw_prim | RADEON_CP_VC_CNTL_TCL_ENABLE;
@@ -361,6 +356,73 @@ radeonComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord )
}
}
+/**
+ * Predict total emit size for next rendering operation so there is no flush in middle of rendering
+ * Prediction has to aim towards the best possible value that is worse than worst case scenario
+ */
+static GLuint radeonEnsureEmitSize( GLcontext * ctx , GLuint inputs )
+{
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint space_required;
+ GLuint state_size;
+ GLuint nr_aos = 1; /* radeonEmitArrays does always emit one */
+ int i;
+ /* list of flags that are allocating aos object */
+ const GLuint flags_to_check[] = {
+ VERT_BIT_NORMAL,
+ VERT_BIT_COLOR0,
+ VERT_BIT_COLOR1,
+ VERT_BIT_FOG
+ };
+ /* predict number of aos to emit */
+ for (i=0; i < sizeof(flags_to_check)/sizeof(flags_to_check[0]); ++i)
+ {
+ if (inputs & flags_to_check[i])
+ ++nr_aos;
+ }
+ for (i = 0; i < ctx->Const.MaxTextureUnits; ++i)
+ {
+ if (inputs & VERT_BIT_TEX(i))
+ ++nr_aos;
+ }
+
+ {
+ /* count the prediction for state size */
+ space_required = 0;
+ state_size = radeonCountStateEmitSize( &rmesa->radeon );
+ /* tcl may be changed in radeonEmitArrays so account for it if not dirty */
+ if (!rmesa->hw.tcl.dirty)
+ state_size += rmesa->hw.tcl.check( rmesa->radeon.glCtx, &rmesa->hw.tcl );
+ /* predict size for elements */
+ for (i = 0; i < VB->PrimitiveCount; ++i)
+ {
+ if (!VB->Primitive[i].count)
+ continue;
+ /* If primitive.count is less than MAX_CONVERSION_SIZE
+ rendering code may decide convert to elts.
+ In that case we have to make pessimistic prediction.
+ and use larger of 2 paths. */
+ const GLuint elts = ELTS_BUFSZ(nr_aos);
+ const GLuint index = INDEX_BUFSZ;
+ const GLuint vbuf = VBUF_BUFSZ;
+ if ( (!VB->Elts && VB->Primitive[i].count >= MAX_CONVERSION_SIZE)
+ || vbuf > index + elts)
+ space_required += vbuf;
+ else
+ space_required += index + elts;
+ space_required += AOS_BUFSZ(nr_aos);
+ }
+ space_required += SCISSOR_BUFSZ;
+ }
+ /* flush the buffer in case we need more than is left. */
+ if (rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required, __FUNCTION__))
+ return space_required + radeonCountStateEmitSize( &rmesa->radeon );
+ else
+ return space_required + state_size;
+}
+
/**********************************************************************/
/* Render pipeline stage */
/**********************************************************************/
@@ -371,7 +433,7 @@ radeonComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord )
static GLboolean radeon_run_tcl_render( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint inputs = VERT_BIT_POS | VERT_BIT_COLOR0;
@@ -379,7 +441,7 @@ static GLboolean radeon_run_tcl_render( GLcontext *ctx,
/* TODO: separate this from the swtnl pipeline
*/
- if (rmesa->TclFallback)
+ if (rmesa->radeon.TclFallback)
return GL_TRUE; /* fallback to software t&l */
if (VB->Count == 0)
@@ -411,6 +473,8 @@ static GLboolean radeon_run_tcl_render( GLcontext *ctx,
}
radeonReleaseArrays( ctx, ~0 );
+ GLuint emit_end = radeonEnsureEmitSize( ctx, inputs )
+ + rmesa->radeon.cmdbuf.cs->cdw;
radeonEmitArrays( ctx, inputs );
rmesa->tcl.Elts = VB->Elts;
@@ -430,6 +494,10 @@ static GLboolean radeon_run_tcl_render( GLcontext *ctx,
radeonEmitPrimitive( ctx, start, start+length, prim );
}
+ if (emit_end < rmesa->radeon.cmdbuf.cs->cdw)
+ WARN_ONCE("Rendering was %d commands larger than predicted size."
+ " We might overflow command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end);
+
return GL_FALSE; /* finished the pipe */
}
@@ -461,7 +529,7 @@ const struct tnl_pipeline_stage _radeon_tcl_stage =
static void transition_to_swtnl( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint se_cntl;
@@ -490,7 +558,7 @@ static void transition_to_swtnl( GLcontext *ctx )
static void transition_to_hwtnl( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT];
@@ -509,17 +577,17 @@ static void transition_to_hwtnl( GLcontext *ctx )
tnl->Driver.NotifyMaterialChange = radeonUpdateMaterial;
- if ( rmesa->dma.flush )
- rmesa->dma.flush( rmesa );
+ if ( rmesa->radeon.dma.flush )
+ rmesa->radeon.dma.flush( rmesa->radeon.glCtx );
- rmesa->dma.flush = NULL;
+ rmesa->radeon.dma.flush = NULL;
rmesa->swtcl.vertex_format = 0;
- if (rmesa->swtcl.indexed_verts.buf)
- radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts,
- __FUNCTION__ );
+ // if (rmesa->swtcl.indexed_verts.buf)
+ // radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts,
+ // __FUNCTION__ );
- if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "Radeon end tcl fallback\n");
}
@@ -550,22 +618,22 @@ static char *getFallbackString(GLuint bit)
void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- GLuint oldfallback = rmesa->TclFallback;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ GLuint oldfallback = rmesa->radeon.TclFallback;
if (mode) {
- rmesa->TclFallback |= bit;
+ rmesa->radeon.TclFallback |= bit;
if (oldfallback == 0) {
- if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "Radeon begin tcl fallback %s\n",
getFallbackString( bit ));
transition_to_swtnl( ctx );
}
}
else {
- rmesa->TclFallback &= ~bit;
+ rmesa->radeon.TclFallback &= ~bit;
if (oldfallback == bit) {
- if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "Radeon end tcl fallback %s\n",
getFallbackString( bit ));
transition_to_hwtnl( ctx );
diff --git a/src/mesa/drivers/dri/radeon/radeon_tex.c b/src/mesa/drivers/dri/radeon/radeon_tex.c
index b0aec21670..99865fff27 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tex.c
+++ b/src/mesa/drivers/dri/radeon/radeon_tex.c
@@ -44,6 +44,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/texobj.h"
#include "radeon_context.h"
+#include "radeon_mipmap_tree.h"
#include "radeon_state.h"
#include "radeon_ioctl.h"
#include "radeon_swtcl.h"
@@ -170,10 +171,13 @@ static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf )
{
GLuint anisotropy = (t->pp_txfilter & RADEON_MAX_ANISO_MASK);
+ /* Force revalidation to account for switches from/to mipmapping. */
+ t->validated = GL_FALSE;
+
t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK);
/* r100 chips can't handle mipmaps/aniso for cubemap/volume textures */
- if ( t->base.tObj->Target == GL_TEXTURE_CUBE_MAP ) {
+ if ( t->base.Target == GL_TEXTURE_CUBE_MAP ) {
switch ( minf ) {
case GL_NEAREST:
case GL_NEAREST_MIPMAP_NEAREST:
@@ -239,442 +243,27 @@ static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf )
}
}
-static void radeonSetTexBorderColor( radeonTexObjPtr t, GLubyte c[4] )
+static void radeonSetTexBorderColor( radeonTexObjPtr t, const GLfloat color[4] )
{
+ GLubyte c[4];
+ CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
}
-
-/**
- * Allocate space for and load the mesa images into the texture memory block.
- * This will happen before drawing with a new texture, or drawing with a
- * texture after it was swapped out or teximaged again.
- */
-
-static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj )
-{
- radeonTexObjPtr t;
-
- t = CALLOC_STRUCT( radeon_tex_obj );
- texObj->DriverData = t;
- if ( t != NULL ) {
- if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
- fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)texObj, (void *)t );
- }
-
- /* Initialize non-image-dependent parts of the state:
- */
- t->base.tObj = texObj;
- t->border_fallback = GL_FALSE;
-
- t->pp_txfilter = RADEON_BORDER_MODE_OGL;
- t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
- RADEON_TXFORMAT_PERSPECTIVE_ENABLE);
-
- make_empty_list( & t->base );
-
- radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
- radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
- radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
- radeonSetTexBorderColor( t, texObj->_BorderChan );
- }
-
- return t;
-}
-
-
-static const struct gl_texture_format *
-radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
- GLenum format, GLenum type )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- const GLboolean do32bpt =
- ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
- const GLboolean force16bpt =
- ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
- (void) format;
-
- switch ( internalFormat ) {
- case 4:
- case GL_RGBA:
- case GL_COMPRESSED_RGBA:
- switch ( type ) {
- case GL_UNSIGNED_INT_10_10_10_2:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_argb1555;
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return _dri_texformat_argb4444;
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return _dri_texformat_argb1555;
- default:
- return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_argb4444;
- }
-
- case 3:
- case GL_RGB:
- case GL_COMPRESSED_RGB:
- switch ( type ) {
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV:
- return _dri_texformat_argb4444;
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV:
- return _dri_texformat_argb1555;
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- return _dri_texformat_rgb565;
- default:
- return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
- }
-
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- return !force16bpt ?
- _dri_texformat_argb8888 : _dri_texformat_argb4444;
-
- case GL_RGBA4:
- case GL_RGBA2:
- return _dri_texformat_argb4444;
-
- case GL_RGB5_A1:
- return _dri_texformat_argb1555;
-
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- return !force16bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
-
- case GL_RGB5:
- case GL_RGB4:
- case GL_R3_G3_B2:
- return _dri_texformat_rgb565;
-
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- case GL_ALPHA12:
- case GL_ALPHA16:
- case GL_COMPRESSED_ALPHA:
- return _dri_texformat_a8;
-
- case 1:
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- case GL_COMPRESSED_LUMINANCE:
- return _dri_texformat_l8;
-
- case 2:
- 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:
- case GL_COMPRESSED_LUMINANCE_ALPHA:
- return _dri_texformat_al88;
-
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- case GL_COMPRESSED_INTENSITY:
- return _dri_texformat_i8;
-
- case GL_YCBCR_MESA:
- if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
- type == GL_UNSIGNED_BYTE)
- return &_mesa_texformat_ycbcr;
- else
- return &_mesa_texformat_ycbcr_rev;
-
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- return &_mesa_texformat_rgb_dxt1;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- return &_mesa_texformat_rgba_dxt1;
-
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- return &_mesa_texformat_rgba_dxt3;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- return &_mesa_texformat_rgba_dxt5;
-
- default:
- _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
- return NULL;
- }
-
- return NULL; /* never get here */
-}
-
-
-static void radeonTexImage1D( GLcontext *ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint border,
- GLenum format, GLenum type, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
-
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) radeonAllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
- return;
- }
- }
-
- /* Note, this will call ChooseTextureFormat */
- _mesa_store_teximage1d(ctx, target, level, internalFormat,
- width, border, format, type, pixels,
- &ctx->Unpack, texObj, texImage);
-
- t->dirty_images[0] |= (1 << level);
-}
-
-
-static void radeonTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset,
- GLsizei width,
- GLenum format, GLenum type,
- const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
-
- assert( t ); /* this _should_ be true */
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) radeonAllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
- return;
- }
- }
-
- _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
- format, type, pixels, packing, texObj,
- texImage);
-
- t->dirty_images[0] |= (1 << level);
-}
-
-
-static void radeonTexImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLenum format, GLenum type, const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- if ( t != NULL ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) radeonAllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
- return;
- }
- }
-
- /* Note, this will call ChooseTextureFormat */
- _mesa_store_teximage2d(ctx, target, level, internalFormat,
- width, height, border, format, type, pixels,
- &ctx->Unpack, texObj, texImage);
-
- t->dirty_images[face] |= (1 << level);
-}
-
-
-static void radeonTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- assert( t ); /* this _should_ be true */
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) radeonAllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
- return;
- }
- }
-
- _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
- height, format, type, pixels, packing, texObj,
- texImage);
-
- t->dirty_images[face] |= (1 << level);
-}
-
-static void radeonCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLsizei imageSize, const GLvoid *data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- if ( t != NULL ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) radeonAllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
- return;
- }
- }
-
- /* Note, this will call ChooseTextureFormat */
- _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
- height, border, imageSize, data, texObj, texImage);
-
- t->dirty_images[face] |= (1 << level);
-}
-
-
-static void radeonCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format,
- GLsizei imageSize, const GLvoid *data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage )
-{
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
- GLuint face;
-
-
- /* which cube face or ordinary 2D image */
- switch (target) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- ASSERT(face < 6);
- break;
- default:
- face = 0;
- }
-
- assert( t ); /* this _should_ be true */
- if ( t ) {
- driSwapOutTextureObject( t );
- }
- else {
- t = (driTextureObject *) radeonAllocTexObj( texObj );
- if (!t) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
- return;
- }
- }
-
- _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
- height, format, imageSize, data, texObj, texImage);
-
- t->dirty_images[face] |= (1 << level);
-}
-
#define SCALED_FLOAT_TO_BYTE( x, scale ) \
(((GLuint)((255.0F / scale) * (x))) / 2)
static void radeonTexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint unit = ctx->Texture.CurrentUnit;
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- if ( RADEON_DEBUG & DEBUG_STATE ) {
+ if ( RADEON_DEBUG & RADEON_STATE ) {
fprintf( stderr, "%s( %s )\n",
__FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
}
@@ -701,7 +290,7 @@ static void radeonTexEnv( GLcontext *ctx, GLenum target,
* functions, one mapping [-1.0,0.0] to [-128,0] and one mapping
* [0.0,4.0] to [0,127].
*/
- min = driQueryOptionb (&rmesa->optionCache, "no_neg_lod_bias") ?
+ min = driQueryOptionb (&rmesa->radeon.optionCache, "no_neg_lod_bias") ?
0.0 : -1.0;
bias = CLAMP( *param, min, 4.0 );
if ( bias == 0 ) {
@@ -734,12 +323,10 @@ static void radeonTexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj,
GLenum pname, const GLfloat *params )
{
- radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
+ radeonTexObj* t = radeon_tex_obj(texObj);
- if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
- fprintf( stderr, "%s( %s )\n", __FUNCTION__,
+ radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s( %s )\n", __FUNCTION__,
_mesa_lookup_enum_by_nr( pname ) );
- }
switch ( pname ) {
case GL_TEXTURE_MIN_FILTER:
@@ -755,64 +342,57 @@ static void radeonTexParameter( GLcontext *ctx, GLenum target,
break;
case GL_TEXTURE_BORDER_COLOR:
- radeonSetTexBorderColor( t, texObj->_BorderChan );
+ radeonSetTexBorderColor( t, texObj->BorderColor );
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
+
/* This isn't the most efficient solution but there doesn't appear to
* be a nice alternative. Since there's no LOD clamping,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
- driSwapOutTextureObject( (driTextureObject *) t );
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = 0;
+ t->validated = GL_FALSE;
+ }
break;
default:
return;
}
-
- /* Mark this texobj as dirty (one bit per tex unit)
- */
- t->dirty_state = TEX_ALL;
-}
-
-
-static void radeonBindTexture( GLcontext *ctx, GLenum target,
- struct gl_texture_object *texObj )
-{
- if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
- fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *)texObj,
- ctx->Texture.CurrentUnit );
- }
-
- assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D &&
- target != GL_TEXTURE_RECTANGLE_NV && target != GL_TEXTURE_CUBE_MAP) ||
- (texObj->DriverData != NULL) );
}
-
static void radeonDeleteTexture( GLcontext *ctx,
struct gl_texture_object *texObj )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- driTextureObject * t = (driTextureObject *) texObj->DriverData;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ radeonTexObj* t = radeon_tex_obj(texObj);
+ int i;
- if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
- fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
+ radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
+ "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
_mesa_lookup_enum_by_nr( texObj->Target ) );
- }
-
- if ( t != NULL ) {
- if ( rmesa ) {
- RADEON_FIREVERTICES( rmesa );
- }
- driDestroyTextureObject( t );
+ if ( rmesa ) {
+ radeon_firevertices(&rmesa->radeon);
+ for ( i = 0 ; i < rmesa->radeon.glCtx->Const.MaxTextureUnits ; i++ ) {
+ if ( t == rmesa->state.texture.unit[i].texobj ) {
+ rmesa->state.texture.unit[i].texobj = NULL;
+ rmesa->hw.tex[i].dirty = GL_FALSE;
+ rmesa->hw.cube[i].dirty = GL_FALSE;
+ }
+ }
}
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = 0;
+ }
/* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, texObj);
}
@@ -832,7 +412,7 @@ static void radeonTexGen( GLcontext *ctx,
GLenum pname,
const GLfloat *params )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint unit = ctx->Texture.CurrentUnit;
rmesa->recheck_texgen[unit] = GL_TRUE;
}
@@ -846,29 +426,40 @@ static void radeonTexGen( GLcontext *ctx,
static struct gl_texture_object *
radeonNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- struct gl_texture_object *obj;
- obj = _mesa_new_texture_object(ctx, name, target);
- if (!obj)
- return NULL;
- obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
- radeonAllocTexObj( obj );
- return obj;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj);
+
+ _mesa_initialize_texture_object(&t->base, name, target);
+ t->base.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
+
+ t->border_fallback = GL_FALSE;
+
+ t->pp_txfilter = RADEON_BORDER_MODE_OGL;
+ t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
+ RADEON_TXFORMAT_PERSPECTIVE_ENABLE);
+
+ radeonSetTexWrap( t, t->base.WrapS, t->base.WrapT );
+ radeonSetTexMaxAnisotropy( t, t->base.MaxAnisotropy );
+ radeonSetTexFilter( t, t->base.MinFilter, t->base.MagFilter );
+ radeonSetTexBorderColor( t, t->base.BorderColor );
+ return &t->base;
}
+
void radeonInitTextureFuncs( struct dd_function_table *functions )
{
- functions->ChooseTextureFormat = radeonChooseTextureFormat;
+ functions->ChooseTextureFormat = radeonChooseTextureFormat_mesa;
functions->TexImage1D = radeonTexImage1D;
functions->TexImage2D = radeonTexImage2D;
functions->TexSubImage1D = radeonTexSubImage1D;
functions->TexSubImage2D = radeonTexSubImage2D;
+ functions->GetTexImage = radeonGetTexImage;
+ functions->GetCompressedTexImage = radeonGetCompressedTexImage;
functions->NewTextureObject = radeonNewTextureObject;
- functions->BindTexture = radeonBindTexture;
+ // functions->BindTexture = radeonBindTexture;
functions->DeleteTexture = radeonDeleteTexture;
- functions->IsTextureResident = driIsTextureResident;
functions->TexEnv = radeonTexEnv;
functions->TexParameter = radeonTexParameter;
@@ -877,5 +468,12 @@ void radeonInitTextureFuncs( struct dd_function_table *functions )
functions->CompressedTexImage2D = radeonCompressedTexImage2D;
functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
+ functions->GenerateMipmap = radeonGenerateMipmap;
+
+ functions->NewTextureImage = radeonNewTextureImage;
+ functions->FreeTexImageData = radeonFreeTexImageData;
+ functions->MapTexture = radeonMapTexture;
+ functions->UnmapTexture = radeonUnmapTexture;
+
driInitTextureFormats();
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_tex.h b/src/mesa/drivers/dri/radeon/radeon_tex.h
index 8000880828..a4aaddc74f 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tex.h
+++ b/src/mesa/drivers/dri/radeon/radeon_tex.h
@@ -41,12 +41,16 @@ extern void radeonSetTexOffset(__DRIcontext *pDRICtx, GLint texname,
unsigned long long offset, GLint depth,
GLuint pitch);
+extern void radeonSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv);
+extern void radeonSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format,
+ __DRIdrawable *dPriv);
+
extern void radeonUpdateTextureState( GLcontext *ctx );
-extern int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t,
+extern int radeonUploadTexImages( r100ContextPtr rmesa, radeonTexObjPtr t,
GLuint face );
-extern void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t );
+extern void radeonDestroyTexObj( r100ContextPtr rmesa, radeonTexObjPtr t );
extern void radeonInitTextureFuncs( struct dd_function_table *functions );
diff --git a/src/mesa/drivers/dri/radeon/radeon_texmem.c b/src/mesa/drivers/dri/radeon/radeon_texmem.c
deleted file mode 100644
index 5f7bbe6a4c..0000000000
--- a/src/mesa/drivers/dri/radeon/radeon_texmem.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/**************************************************************************
-
-Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
- VA Linux Systems Inc., Fremont, California.
-
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation on the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS 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:
- * Kevin E. Martin <martin@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
- */
-#include <errno.h>
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/macros.h"
-
-#include "radeon_context.h"
-#include "radeon_ioctl.h"
-#include "radeon_tex.h"
-
-#include <unistd.h> /* for usleep() */
-
-
-/**
- * Destroy any device-dependent state associated with the texture. This may
- * include NULLing out hardware state that points to the texture.
- */
-void
-radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
-{
- if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
- fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)t, (void *)t->base.tObj );
- }
-
- if ( rmesa != NULL ) {
- unsigned i;
-
-
- for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ ) {
- if ( t == rmesa->state.texture.unit[i].texobj ) {
- rmesa->state.texture.unit[i].texobj = NULL;
- }
- }
- }
-}
-
-
-/* ------------------------------------------------------------
- * Texture image conversions
- */
-
-
-static void radeonUploadRectSubImage( radeonContextPtr rmesa,
- radeonTexObjPtr t,
- struct gl_texture_image *texImage,
- GLint x, GLint y,
- GLint width, GLint height )
-{
- const struct gl_texture_format *texFormat = texImage->TexFormat;
- int blit_format, dstPitch, done;
-
- switch ( texFormat->TexelBytes ) {
- case 1:
- blit_format = RADEON_GMC_DST_8BPP_CI;
- break;
- case 2:
- blit_format = RADEON_GMC_DST_16BPP;
- break;
- case 4:
- blit_format = RADEON_GMC_DST_32BPP;
- break;
- default:
- fprintf( stderr, "radeonUploadRectSubImage: unknown blit_format (texelbytes=%d)\n",
- texFormat->TexelBytes);
- return;
- }
-
- t->image[0][0].data = texImage->Data;
-
- /* Currently don't need to cope with small pitches.
- */
- width = texImage->Width;
- height = texImage->Height;
- dstPitch = t->pp_txpitch + 32;
-
- { /* FIXME: prefer GART-texturing if possible */
- /* Data not in GART memory, or bad pitch.
- */
- for (done = 0; done < height ; ) {
- struct radeon_dma_region region;
- int lines = MIN2( height - done, RADEON_BUFFER_SIZE / dstPitch );
- int src_pitch;
- char *tex;
-
- src_pitch = texImage->RowStride * texFormat->TexelBytes;
-
- tex = (char *)texImage->Data + done * src_pitch;
-
- memset(&region, 0, sizeof(region));
- radeonAllocDmaRegion( rmesa, &region, lines * dstPitch, 1024 );
-
- /* Copy texdata to dma:
- */
- if (0)
- fprintf(stderr, "%s: src_pitch %d dst_pitch %d\n",
- __FUNCTION__, src_pitch, dstPitch);
-
- if (src_pitch == dstPitch) {
- memcpy( region.address + region.start, tex, lines * src_pitch );
- }
- else {
- char *buf = region.address + region.start;
- int i;
- for (i = 0 ; i < lines ; i++) {
- memcpy( buf, tex, src_pitch );
- buf += dstPitch;
- tex += src_pitch;
- }
- }
-
- radeonEmitWait( rmesa, RADEON_WAIT_3D );
-
-
-
- /* Blit to framebuffer
- */
- radeonEmitBlit( rmesa,
- blit_format,
- dstPitch, GET_START( &region ),
- dstPitch, t->bufAddr,
- 0, 0,
- 0, done,
- width, lines );
-
- radeonEmitWait( rmesa, RADEON_WAIT_2D );
-
- radeonReleaseDmaRegion( rmesa, &region, __FUNCTION__ );
- done += lines;
- }
- }
-}
-
-
-/**
- * Upload the texture image associated with texture \a t at the specified
- * level at the address relative to \a start.
- */
-static void uploadSubImage( radeonContextPtr rmesa, radeonTexObjPtr t,
- GLint hwlevel,
- GLint x, GLint y, GLint width, GLint height,
- GLuint face )
-{
- struct gl_texture_image *texImage = NULL;
- GLuint offset;
- GLint imageWidth, imageHeight;
- GLint ret;
- drm_radeon_texture_t tex;
- drm_radeon_tex_image_t tmp;
- const int level = hwlevel + t->base.firstLevel;
-
- if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
- fprintf( stderr, "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n",
- __FUNCTION__, (void *)t, (void *)t->base.tObj, level, width, height, face );
- }
-
- ASSERT(face < 6);
-
- /* Ensure we have a valid texture to upload */
- if ( ( hwlevel < 0 ) || ( hwlevel >= RADEON_MAX_TEXTURE_LEVELS ) ) {
- _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
- return;
- }
-
- texImage = t->base.tObj->Image[face][level];
-
- if ( !texImage ) {
- if ( RADEON_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level );
- return;
- }
- if ( !texImage->Data ) {
- if ( RADEON_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ );
- return;
- }
-
-
- if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- assert(level == 0);
- assert(hwlevel == 0);
- if ( RADEON_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__);
- radeonUploadRectSubImage( rmesa, t, texImage, x, y, width, height );
- return;
- }
-
- imageWidth = texImage->Width;
- imageHeight = texImage->Height;
-
- offset = t->bufAddr + t->base.totalSize * face / 6;
-
- if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
- GLint imageX = 0;
- GLint imageY = 0;
- GLint blitX = t->image[face][hwlevel].x;
- GLint blitY = t->image[face][hwlevel].y;
- GLint blitWidth = t->image[face][hwlevel].width;
- GLint blitHeight = t->image[face][hwlevel].height;
- fprintf( stderr, " upload image: %d,%d at %d,%d\n",
- imageWidth, imageHeight, imageX, imageY );
- fprintf( stderr, " upload blit: %d,%d at %d,%d\n",
- blitWidth, blitHeight, blitX, blitY );
- fprintf( stderr, " blit ofs: 0x%07x level: %d/%d\n",
- (GLuint)offset, hwlevel, level );
- }
-
- t->image[face][hwlevel].data = texImage->Data;
-
- /* Init the DRM_RADEON_TEXTURE command / drm_radeon_texture_t struct.
- * NOTE: we're always use a 1KB-wide blit and I8 texture format.
- * We used to use 1, 2 and 4-byte texels and used to use the texture
- * width to dictate the blit width - but that won't work for compressed
- * textures. (Brian)
- * NOTE: can't do that with texture tiling. (sroland)
- */
- tex.offset = offset;
- tex.image = &tmp;
- /* copy (x,y,width,height,data) */
- memcpy( &tmp, &t->image[face][hwlevel], sizeof(drm_radeon_tex_image_t) );
-
- if (texImage->TexFormat->TexelBytes) {
- /* use multi-byte upload scheme */
- tex.height = imageHeight;
- tex.width = imageWidth;
- tex.format = t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK;
- tex.pitch = MAX2((texImage->Width * texImage->TexFormat->TexelBytes) / 64, 1);
- tex.offset += tmp.x & ~1023;
- tmp.x = tmp.x % 1024;
- if (t->tile_bits & RADEON_TXO_MICRO_TILE_X2) {
- /* need something like "tiled coordinates" ? */
- tmp.y = tmp.x / (tex.pitch * 128) * 2;
- tmp.x = tmp.x % (tex.pitch * 128) / 2 / texImage->TexFormat->TexelBytes;
- tex.pitch |= RADEON_DST_TILE_MICRO >> 22;
- }
- else {
- tmp.x = tmp.x >> (texImage->TexFormat->TexelBytes >> 1);
- }
- if ((t->tile_bits & RADEON_TXO_MACRO_TILE) &&
- (texImage->Width * texImage->TexFormat->TexelBytes >= 256)) {
- /* radeon switches off macro tiling for small textures/mipmaps it seems */
- tex.pitch |= RADEON_DST_TILE_MACRO >> 22;
- }
- }
- else {
- /* In case of for instance 8x8 texture (2x2 dxt blocks), padding after the first two blocks is
- needed (only with dxt1 since 2 dxt3/dxt5 blocks already use 32 Byte). */
- /* set tex.height to 1/4 since 1 "macropixel" (dxt-block) has 4 real pixels. Needed
- so the kernel module reads the right amount of data. */
- tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */
- tex.pitch = (BLIT_WIDTH_BYTES / 64);
- tex.height = (imageHeight + 3) / 4;
- tex.width = (imageWidth + 3) / 4;
- switch (t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK) {
- case RADEON_TXFORMAT_DXT1:
- tex.width *= 8;
- break;
- case RADEON_TXFORMAT_DXT23:
- case RADEON_TXFORMAT_DXT45:
- tex.width *= 16;
- break;
- }
- }
-
- LOCK_HARDWARE( rmesa );
- do {
- ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
- &tex, sizeof(drm_radeon_texture_t) );
- } while ( ret == -EAGAIN );
-
- UNLOCK_HARDWARE( rmesa );
-
- if ( ret ) {
- fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
- fprintf( stderr, " offset=0x%08x\n",
- offset );
- fprintf( stderr, " image width=%d height=%d\n",
- imageWidth, imageHeight );
- fprintf( stderr, " blit width=%d height=%d data=%p\n",
- t->image[face][hwlevel].width, t->image[face][hwlevel].height,
- t->image[face][hwlevel].data );
- exit( 1 );
- }
-}
-
-
-/**
- * Upload the texture images associated with texture \a t. This might
- * require the allocation of texture memory.
- *
- * \param rmesa Context pointer
- * \param t Texture to be uploaded
- * \param face Cube map face to be uploaded. Zero for non-cube maps.
- */
-
-int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t, GLuint face )
-{
- int numLevels;
-
- if ( !t || t->base.totalSize == 0 || t->image_override )
- return 0;
-
- if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
- fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
- (void *)rmesa->glCtx, (void *)t->base.tObj, t->base.totalSize,
- t->base.firstLevel, t->base.lastLevel );
- }
-
- numLevels = t->base.lastLevel - t->base.firstLevel + 1;
-
- if (RADEON_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "%s: Syncing\n", __FUNCTION__ );
- radeonFinish( rmesa->glCtx );
- }
-
- LOCK_HARDWARE( rmesa );
-
- if ( t->base.memBlock == NULL ) {
- int heap;
-
- heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps,
- (driTextureObject *) t );
- if ( heap == -1 ) {
- UNLOCK_HARDWARE( rmesa );
- return -1;
- }
-
- /* Set the base offset of the texture image */
- t->bufAddr = rmesa->radeonScreen->texOffset[heap]
- + t->base.memBlock->ofs;
- t->pp_txoffset = t->bufAddr;
-
- if (!(t->base.tObj->Image[0][0]->IsClientData)) {
- /* hope it's safe to add that here... */
- t->pp_txoffset |= t->tile_bits;
- }
-
- /* Mark this texobj as dirty on all units:
- */
- t->dirty_state = TEX_ALL;
- }
-
-
- /* Let the world know we've used this memory recently.
- */
- driUpdateTextureLRU( (driTextureObject *) t );
- UNLOCK_HARDWARE( rmesa );
-
-
- /* Upload any images that are new */
- if (t->base.dirty_images[face]) {
- int i;
- for ( i = 0 ; i < numLevels ; i++ ) {
- if ( (t->base.dirty_images[face] & (1 << (i+t->base.firstLevel))) != 0 ) {
- uploadSubImage( rmesa, t, i, 0, 0, t->image[face][i].width,
- t->image[face][i].height, face );
- }
- }
- t->base.dirty_images[face] = 0;
- }
-
- if (RADEON_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "%s: Syncing\n", __FUNCTION__ );
- radeonFinish( rmesa->glCtx );
- }
-
- return 0;
-}
diff --git a/src/mesa/drivers/dri/radeon/radeon_texstate.c b/src/mesa/drivers/dri/radeon/radeon_texstate.c
index 1e2f654add..9d252aa74c 100644
--- a/src/mesa/drivers/dri/radeon/radeon_texstate.c
+++ b/src/mesa/drivers/dri/radeon/radeon_texstate.c
@@ -39,10 +39,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/context.h"
#include "main/macros.h"
#include "main/texformat.h"
+#include "main/teximage.h"
#include "main/texobj.h"
#include "main/enums.h"
#include "radeon_context.h"
+#include "radeon_mipmap_tree.h"
#include "radeon_state.h"
#include "radeon_ioctl.h"
#include "radeon_swtcl.h"
@@ -75,10 +77,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
&& (tx_table[f].format != 0xffffffff) )
-static const struct {
+struct tx_table {
GLuint format, filter;
-}
-tx_table[] =
+};
+
+static const struct tx_table tx_table[] =
{
_ALPHA(RGBA8888),
_ALPHA_REV(RGBA8888),
@@ -111,252 +114,6 @@ tx_table[] =
#undef _ALPHA
#undef _INVALID
-/**
- * This function computes the number of bytes of storage needed for
- * the given texture object (all mipmap levels, all cube faces).
- * The \c image[face][level].x/y/width/height parameters for upload/blitting
- * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
- * too.
- *
- * \param rmesa Context pointer
- * \param tObj GL texture object whose images are to be posted to
- * hardware state.
- */
-static void radeonSetTexImages( radeonContextPtr rmesa,
- struct gl_texture_object *tObj )
-{
- radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData;
- const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
- GLint curOffset, blitWidth;
- GLint i, texelBytes;
- GLint numLevels;
- GLint log2Width, log2Height, log2Depth;
-
- /* Set the hardware texture format
- */
- if ( !t->image_override ) {
- t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK |
- RADEON_TXFORMAT_ALPHA_IN_MAP);
- t->pp_txfilter &= ~RADEON_YUV_TO_RGB;
-
- if ( VALID_FORMAT( baseImage->TexFormat->MesaFormat ) ) {
- t->pp_txformat |= tx_table[ baseImage->TexFormat->MesaFormat ].format;
- t->pp_txfilter |= tx_table[ baseImage->TexFormat->MesaFormat ].filter;
- }
- else {
- _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
- return;
- }
- }
-
- texelBytes = baseImage->TexFormat->TexelBytes;
-
- /* Compute which mipmap levels we really want to send to the hardware.
- */
-
- if (tObj->Target != GL_TEXTURE_CUBE_MAP)
- driCalculateTextureFirstLastLevel( (driTextureObject *) t );
- else {
- /* r100 can't handle mipmaps for cube/3d textures, so don't waste
- memory for them */
- t->base.firstLevel = t->base.lastLevel = tObj->BaseLevel;
- }
- log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
- log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
- log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
-
- numLevels = t->base.lastLevel - t->base.firstLevel + 1;
-
- assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
-
- /* Calculate mipmap offsets and dimensions for blitting (uploading)
- * The idea is that we lay out the mipmap levels within a block of
- * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
- */
- curOffset = 0;
- blitWidth = BLIT_WIDTH_BYTES;
- t->tile_bits = 0;
-
- /* figure out if this texture is suitable for tiling. */
- if (texelBytes && (tObj->Target != GL_TEXTURE_RECTANGLE_NV)) {
- if (rmesa->texmicrotile && (baseImage->Height > 1)) {
- /* allow 32 (bytes) x 1 mip (which will use two times the space
- the non-tiled version would use) max if base texture is large enough */
- if ((numLevels == 1) ||
- (((baseImage->Width * texelBytes / baseImage->Height) <= 32) &&
- (baseImage->Width * texelBytes > 64)) ||
- ((baseImage->Width * texelBytes / baseImage->Height) <= 16)) {
- /* R100 has two microtile bits (only the txoffset reg, not the blitter)
- weird: X2 + OPT: 32bit correct, 16bit completely hosed
- X2: 32bit correct, 16bit correct
- OPT: 32bit large mips correct, small mips hosed, 16bit completely hosed */
- t->tile_bits |= RADEON_TXO_MICRO_TILE_X2 /*| RADEON_TXO_MICRO_TILE_OPT*/;
- }
- }
- if ((baseImage->Width * texelBytes >= 256) && (baseImage->Height >= 16)) {
- /* R100 disables macro tiling only if mip width is smaller than 256 bytes, and not
- in the case if height is smaller than 16 (not 100% sure), as does the r200,
- so need to disable macro tiling in that case */
- if ((numLevels == 1) || ((baseImage->Width * texelBytes / baseImage->Height) <= 4)) {
- t->tile_bits |= RADEON_TXO_MACRO_TILE;
- }
- }
- }
-
- for (i = 0; i < numLevels; i++) {
- const struct gl_texture_image *texImage;
- GLuint size;
-
- texImage = tObj->Image[0][i + t->base.firstLevel];
- if ( !texImage )
- break;
-
- /* find image size in bytes */
- if (texImage->IsCompressed) {
- /* need to calculate the size AFTER padding even though the texture is
- submitted without padding.
- Only handle pot textures currently - don't know if npot is even possible,
- size calculation would certainly need (trivial) adjustments.
- Align (and later pad) to 32byte, not sure what that 64byte blit width is
- good for? */
- if ((t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK) == RADEON_TXFORMAT_DXT1) {
- /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
- if ((texImage->Width + 3) < 8) /* width one block */
- size = texImage->CompressedSize * 4;
- else if ((texImage->Width + 3) < 16)
- size = texImage->CompressedSize * 2;
- else size = texImage->CompressedSize;
- }
- else /* DXT3/5, 16 bytes per block */
- if ((texImage->Width + 3) < 8)
- size = texImage->CompressedSize * 2;
- else size = texImage->CompressedSize;
- }
- else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- size = ((texImage->Width * texelBytes + 63) & ~63) * texImage->Height;
- }
- else if (t->tile_bits & RADEON_TXO_MICRO_TILE_X2) {
- /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
- though the actual offset may be different (if texture is less than
- 32 bytes width) to the untiled case */
- int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
- size = (w * ((texImage->Height + 1) / 2)) * texImage->Depth;
- blitWidth = MAX2(texImage->Width, 64 / texelBytes);
- }
- else {
- int w = (texImage->Width * texelBytes + 31) & ~31;
- size = w * texImage->Height * texImage->Depth;
- blitWidth = MAX2(texImage->Width, 64 / texelBytes);
- }
- assert(size > 0);
-
- /* Align to 32-byte offset. It is faster to do this unconditionally
- * (no branch penalty).
- */
-
- curOffset = (curOffset + 0x1f) & ~0x1f;
-
- if (texelBytes) {
- t->image[0][i].x = curOffset; /* fix x and y coords up later together with offset */
- t->image[0][i].y = 0;
- t->image[0][i].width = MIN2(size / texelBytes, blitWidth);
- t->image[0][i].height = (size / texelBytes) / t->image[0][i].width;
- }
- else {
- t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
- t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
- t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES);
- t->image[0][i].height = size / t->image[0][i].width;
- }
-
-#if 0
- /* for debugging only and only applicable to non-rectangle targets */
- assert(size % t->image[0][i].width == 0);
- assert(t->image[0][i].x == 0
- || (size < BLIT_WIDTH_BYTES && t->image[0][i].height == 1));
-#endif
-
- if (0)
- fprintf(stderr,
- "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
- i, texImage->Width, texImage->Height,
- t->image[0][i].x, t->image[0][i].y,
- t->image[0][i].width, t->image[0][i].height, size, curOffset);
-
- curOffset += size;
-
- }
-
- /* Align the total size of texture memory block.
- */
- t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
-
- /* Setup remaining cube face blits, if needed */
- if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
- const GLuint faceSize = t->base.totalSize;
- GLuint face;
- /* reuse face 0 x/y/width/height - just update the offset when uploading */
- for (face = 1; face < 6; face++) {
- for (i = 0; i < numLevels; i++) {
- t->image[face][i].x = t->image[0][i].x;
- t->image[face][i].y = t->image[0][i].y;
- t->image[face][i].width = t->image[0][i].width;
- t->image[face][i].height = t->image[0][i].height;
- }
- }
- t->base.totalSize = 6 * faceSize; /* total texmem needed */
- }
-
- /* Hardware state:
- */
- t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
- t->pp_txfilter |= (numLevels - 1) << RADEON_MAX_MIP_LEVEL_SHIFT;
-
- t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
- RADEON_TXFORMAT_HEIGHT_MASK |
- RADEON_TXFORMAT_CUBIC_MAP_ENABLE |
- RADEON_TXFORMAT_F5_WIDTH_MASK |
- RADEON_TXFORMAT_F5_HEIGHT_MASK);
- t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
- (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
-
- if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
- assert(log2Width == log2Height);
- t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_F5_WIDTH_SHIFT) |
- (log2Height << RADEON_TXFORMAT_F5_HEIGHT_SHIFT) |
- (RADEON_TXFORMAT_CUBIC_MAP_ENABLE));
- t->pp_cubic_faces = ((log2Width << RADEON_FACE_WIDTH_1_SHIFT) |
- (log2Height << RADEON_FACE_HEIGHT_1_SHIFT) |
- (log2Width << RADEON_FACE_WIDTH_2_SHIFT) |
- (log2Height << RADEON_FACE_HEIGHT_2_SHIFT) |
- (log2Width << RADEON_FACE_WIDTH_3_SHIFT) |
- (log2Height << RADEON_FACE_HEIGHT_3_SHIFT) |
- (log2Width << RADEON_FACE_WIDTH_4_SHIFT) |
- (log2Height << RADEON_FACE_HEIGHT_4_SHIFT));
- }
-
- t->pp_txsize = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << 0) |
- ((tObj->Image[0][t->base.firstLevel]->Height - 1) << 16));
-
- /* Only need to round to nearest 32 for textures, but the blitter
- * requires 64-byte aligned pitches, and we may/may not need the
- * blitter. NPOT only!
- */
- if ( !t->image_override ) {
- if (baseImage->IsCompressed)
- t->pp_txpitch = (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
- else
- t->pp_txpitch = ((tObj->Image[0][t->base.firstLevel]->Width * texelBytes) + 63) & ~(63);
- t->pp_txpitch -= 32;
- }
-
- t->dirty_state = TEX_ALL;
-
- /* FYI: radeonUploadTexImages( rmesa, t ); used to be called here */
-}
-
-
-
/* ================================================================
* Texture combine functions
*/
@@ -503,7 +260,7 @@ do { \
static GLboolean radeonUpdateTextureEnv( GLcontext *ctx, int unit )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
GLuint color_combine, alpha_combine;
const GLuint color_combine0 = RADEON_COLOR_ARG_A_ZERO | RADEON_COLOR_ARG_B_ZERO
@@ -520,7 +277,7 @@ static GLboolean radeonUpdateTextureEnv( GLcontext *ctx, int unit )
assert( (texUnit->_ReallyEnabled == 0)
|| (texUnit->_Current != NULL) );
- if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+ if ( RADEON_DEBUG & RADEON_TEXTURE ) {
fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit );
}
@@ -846,22 +603,21 @@ static GLboolean radeonUpdateTextureEnv( GLcontext *ctx, int unit )
void radeonSetTexOffset(__DRIcontext * pDRICtx, GLint texname,
unsigned long long offset, GLint depth, GLuint pitch)
{
- radeonContextPtr rmesa = pDRICtx->driverPrivate;
+ r100ContextPtr rmesa = pDRICtx->driverPrivate;
struct gl_texture_object *tObj =
- _mesa_lookup_texture(rmesa->glCtx, texname);
- radeonTexObjPtr t;
+ _mesa_lookup_texture(rmesa->radeon.glCtx, texname);
+ radeonTexObjPtr t = radeon_tex_obj(tObj);
if (tObj == NULL)
return;
- t = (radeonTexObjPtr) tObj->DriverData;
-
t->image_override = GL_TRUE;
if (!offset)
return;
-
- t->pp_txoffset = offset;
+
+ t->bo = NULL;
+ t->override_offset = offset;
t->pp_txpitch = pitch - 32;
switch (depth) {
@@ -881,6 +637,125 @@ void radeonSetTexOffset(__DRIcontext * pDRICtx, GLint texname,
}
}
+void radeonSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format,
+ __DRIdrawable *dPriv)
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ struct radeon_renderbuffer *rb;
+ radeon_texture_image *rImage;
+ radeonContextPtr radeon;
+ r100ContextPtr rmesa;
+ struct radeon_framebuffer *rfb;
+ radeonTexObjPtr t;
+ uint32_t pitch_val;
+ uint32_t internalFormat, type, format;
+
+ type = GL_BGRA;
+ format = GL_UNSIGNED_BYTE;
+ internalFormat = (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT ? 3 : 4);
+
+ radeon = pDRICtx->driverPrivate;
+ rmesa = pDRICtx->driverPrivate;
+
+ rfb = dPriv->driverPrivate;
+ texUnit = &radeon->glCtx->Texture.Unit[radeon->glCtx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(radeon->glCtx, texUnit, target);
+ texImage = _mesa_get_tex_image(radeon->glCtx, texObj, target, 0);
+
+ rImage = get_radeon_texture_image(texImage);
+ t = radeon_tex_obj(texObj);
+ if (t == NULL) {
+ return;
+ }
+
+ radeon_update_renderbuffers(pDRICtx, dPriv);
+ /* back & depth buffer are useless free them right away */
+ rb = (void*)rfb->base.Attachment[BUFFER_DEPTH].Renderbuffer;
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
+ rb = (void*)rfb->base.Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ if (rb && rb->bo) {
+ radeon_bo_unref(rb->bo);
+ rb->bo = NULL;
+ }
+ rb = rfb->color_rb[0];
+ if (rb->bo == NULL) {
+ /* Failed to BO for the buffer */
+ return;
+ }
+
+ _mesa_lock_texture(radeon->glCtx, texObj);
+ if (t->bo) {
+ radeon_bo_unref(t->bo);
+ t->bo = NULL;
+ }
+ if (rImage->bo) {
+ radeon_bo_unref(rImage->bo);
+ rImage->bo = NULL;
+ }
+ if (t->mt) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = NULL;
+ }
+ if (rImage->mt) {
+ radeon_miptree_unreference(rImage->mt);
+ rImage->mt = NULL;
+ }
+ _mesa_init_teximage_fields(radeon->glCtx, target, texImage,
+ rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
+ texImage->RowStride = rb->pitch / rb->cpp;
+ texImage->TexFormat = radeonChooseTextureFormat(radeon->glCtx,
+ internalFormat,
+ type, format, 0);
+ rImage->bo = rb->bo;
+ radeon_bo_ref(rImage->bo);
+ t->bo = rb->bo;
+ radeon_bo_ref(t->bo);
+ t->tile_bits = 0;
+ t->image_override = GL_TRUE;
+ t->override_offset = 0;
+ t->pp_txpitch &= (1 << 13) -1;
+ pitch_val = rb->pitch;
+ switch (rb->cpp) {
+ case 4:
+ if (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT)
+ t->pp_txformat = tx_table[MESA_FORMAT_RGB888].format;
+ else
+ t->pp_txformat = tx_table[MESA_FORMAT_ARGB8888].format;
+ t->pp_txfilter |= tx_table[MESA_FORMAT_ARGB8888].filter;
+ break;
+ case 3:
+ default:
+ t->pp_txformat = tx_table[MESA_FORMAT_RGB888].format;
+ t->pp_txfilter |= tx_table[MESA_FORMAT_RGB888].filter;
+ break;
+ case 2:
+ t->pp_txformat = tx_table[MESA_FORMAT_RGB565].format;
+ t->pp_txfilter |= tx_table[MESA_FORMAT_RGB565].filter;
+ break;
+ }
+ t->pp_txsize = ((rb->base.Width - 1) << RADEON_TEX_USIZE_SHIFT)
+ | ((rb->base.Height - 1) << RADEON_TEX_VSIZE_SHIFT);
+ t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2;
+ t->pp_txpitch = pitch_val;
+ t->pp_txpitch -= 32;
+
+ t->validated = GL_TRUE;
+ _mesa_unlock_texture(radeon->glCtx, texObj);
+ return;
+}
+
+
+void radeonSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
+{
+ radeonSetTexBuffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
+}
+
+
#define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
RADEON_MIN_FILTER_MASK | \
RADEON_MAG_FILTER_MASK | \
@@ -901,12 +776,53 @@ void radeonSetTexOffset(__DRIcontext * pDRICtx, GLint texname,
RADEON_TXFORMAT_NON_POWER2)
-static void import_tex_obj_state( radeonContextPtr rmesa,
+static void disable_tex_obj_state( r100ContextPtr rmesa,
+ int unit )
+{
+ RADEON_STATECHANGE( rmesa, tex[unit] );
+
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_ST_BIT(unit) |
+ RADEON_Q_BIT(unit));
+
+ if (rmesa->radeon.TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) {
+ TCL_FALLBACK( rmesa->radeon.glCtx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
+ rmesa->recheck_texgen[unit] = GL_TRUE;
+ }
+
+ if (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) {
+ /* this seems to be a genuine (r100 only?) hw bug. Need to remove the
+ cubic_map bit on unit 2 when the unit is disabled, otherwise every
+ 2nd (2d) mipmap on unit 0 will be broken (may not be needed for other
+ units, better be safe than sorry though).*/
+ RADEON_STATECHANGE( rmesa, tex[unit] );
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= ~RADEON_TXFORMAT_CUBIC_MAP_ENABLE;
+ }
+
+ {
+ GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
+ GLuint tmp = rmesa->TexGenEnabled;
+
+ rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
+ rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
+ rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
+ rmesa->TexGenNeedNormals[unit] = 0;
+ rmesa->TexGenEnabled |=
+ (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
+
+ if (tmp != rmesa->TexGenEnabled) {
+ rmesa->recheck_texgen[unit] = GL_TRUE;
+ rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
+ }
+ }
+}
+
+static void import_tex_obj_state( r100ContextPtr rmesa,
int unit,
radeonTexObjPtr texobj )
{
/* do not use RADEON_DB_STATE to avoid stale texture caches */
- int *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0];
+ uint32_t *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0];
GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT];
RADEON_STATECHANGE( rmesa, tex[unit] );
@@ -915,10 +831,9 @@ static void import_tex_obj_state( radeonContextPtr rmesa,
cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
- cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
- if (texobj->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+ if (texobj->base.Target == GL_TEXTURE_RECTANGLE_NV) {
GLuint *txr_cmd = RADEON_DB_STATE( txr[unit] );
txr_cmd[TXR_PP_TEX_SIZE] = texobj->pp_txsize; /* NPOT only! */
txr_cmd[TXR_PP_TEX_PITCH] = texobj->pp_txpitch; /* NPOT only! */
@@ -928,22 +843,12 @@ static void import_tex_obj_state( radeonContextPtr rmesa,
else {
se_coord_fmt &= ~(RADEON_VTX_ST0_NONPARAMETRIC << unit);
- if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) {
- int *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0];
- GLuint bytesPerFace = texobj->base.totalSize / 6;
- ASSERT(texobj->base.totalSize % 6 == 0);
+ if (texobj->base.Target == GL_TEXTURE_CUBE_MAP) {
+ uint32_t *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0];
RADEON_STATECHANGE( rmesa, cube[unit] );
cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
- /* dont know if this setup conforms to OpenGL..
- * at least it matches the behavior of mesa software renderer
- */
- cube_cmd[CUBE_PP_CUBIC_OFFSET_0] = texobj->pp_txoffset; /* right */
- cube_cmd[CUBE_PP_CUBIC_OFFSET_1] = texobj->pp_txoffset + 1 * bytesPerFace; /* left */
- cube_cmd[CUBE_PP_CUBIC_OFFSET_2] = texobj->pp_txoffset + 2 * bytesPerFace; /* top */
- cube_cmd[CUBE_PP_CUBIC_OFFSET_3] = texobj->pp_txoffset + 3 * bytesPerFace; /* bottom */
- cube_cmd[CUBE_PP_CUBIC_OFFSET_4] = texobj->pp_txoffset + 4 * bytesPerFace; /* front */
- cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset + 5 * bytesPerFace; /* back */
+ /* state filled out in the cube_emit */
}
}
@@ -952,13 +857,11 @@ static void import_tex_obj_state( radeonContextPtr rmesa,
rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt;
}
- texobj->dirty_state &= ~(1<<unit);
+ rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
}
-
-
-static void set_texgen_matrix( radeonContextPtr rmesa,
+static void set_texgen_matrix( r100ContextPtr rmesa,
GLuint unit,
const GLfloat *s_plane,
const GLfloat *t_plane,
@@ -986,14 +889,14 @@ static void set_texgen_matrix( radeonContextPtr rmesa,
rmesa->TexGenMatrix[unit].m[15] = q_plane[3];
rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE << unit;
- rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+ rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
}
/* Returns GL_FALSE if fallback required.
*/
static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
GLuint tmp = rmesa->TexGenEnabled;
@@ -1023,14 +926,14 @@ static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
*/
else if ( (texUnit->TexGenEnabled & S_BIT) &&
(texUnit->TexGenEnabled & T_BIT) &&
- (texUnit->GenModeS == texUnit->GenModeT) ) {
+ (texUnit->GenS.Mode == texUnit->GenT.Mode) ) {
if ( ((texUnit->TexGenEnabled & R_BIT) &&
- (texUnit->GenModeS != texUnit->GenModeR)) ||
+ (texUnit->GenS.Mode != texUnit->GenR.Mode)) ||
((texUnit->TexGenEnabled & Q_BIT) &&
- (texUnit->GenModeS != texUnit->GenModeQ)) ) {
+ (texUnit->GenS.Mode != texUnit->GenQ.Mode)) ) {
/* Mixed modes, fallback:
*/
- if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "fallback mixed texgen\n");
return GL_FALSE;
}
@@ -1038,7 +941,7 @@ static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
}
else {
/* some texgen mode not including both S and T bits */
- if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "fallback mixed texgen/nontexgen\n");
return GL_FALSE;
}
@@ -1051,23 +954,23 @@ static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_Q_BIT(unit);
}
- switch (texUnit->GenModeS) {
+ switch (texUnit->GenS.Mode) {
case GL_OBJECT_LINEAR:
rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift;
set_texgen_matrix( rmesa, unit,
- texUnit->ObjectPlaneS,
- texUnit->ObjectPlaneT,
- texUnit->ObjectPlaneR,
- texUnit->ObjectPlaneQ);
+ texUnit->GenS.ObjectPlane,
+ texUnit->GenT.ObjectPlane,
+ texUnit->GenR.ObjectPlane,
+ texUnit->GenQ.ObjectPlane);
break;
case GL_EYE_LINEAR:
rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift;
set_texgen_matrix( rmesa, unit,
- texUnit->EyePlaneS,
- texUnit->EyePlaneT,
- texUnit->EyePlaneR,
- texUnit->EyePlaneQ);
+ texUnit->GenS.EyePlane,
+ texUnit->GenT.EyePlane,
+ texUnit->GenR.EyePlane,
+ texUnit->GenQ.EyePlane);
break;
case GL_REFLECTION_MAP_NV:
@@ -1088,289 +991,195 @@ static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
default:
/* Unsupported mode, fallback:
*/
- if (RADEON_DEBUG & DEBUG_FALLBACKS)
+ if (RADEON_DEBUG & RADEON_FALLBACKS)
fprintf(stderr, "fallback GL_SPHERE_MAP\n");
return GL_FALSE;
}
if (tmp != rmesa->TexGenEnabled) {
- rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+ rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
}
return GL_TRUE;
}
-
-static void disable_tex( GLcontext *ctx, int unit )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-
- if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit)) {
- /* Texture unit disabled */
- if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
- /* The old texture is no longer bound to this texture unit.
- * Mark it as such.
- */
-
- rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
- rmesa->state.texture.unit[unit].texobj = NULL;
- }
-
- RADEON_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_PP_CNTL] &=
- ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit);
-
- RADEON_STATECHANGE( rmesa, tcl );
- rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_ST_BIT(unit) |
- RADEON_Q_BIT(unit));
-
- if (rmesa->TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) {
- TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
- rmesa->recheck_texgen[unit] = GL_TRUE;
- }
-
- if (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) {
- /* this seems to be a genuine (r100 only?) hw bug. Need to remove the
- cubic_map bit on unit 2 when the unit is disabled, otherwise every
- 2nd (2d) mipmap on unit 0 will be broken (may not be needed for other
- units, better be safe than sorry though).*/
- RADEON_STATECHANGE( rmesa, tex[unit] );
- rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= ~RADEON_TXFORMAT_CUBIC_MAP_ENABLE;
- }
-
- {
- GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
- GLuint tmp = rmesa->TexGenEnabled;
-
- rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
- rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
- rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
- rmesa->TexGenNeedNormals[unit] = 0;
- rmesa->TexGenEnabled |=
- (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
-
- if (tmp != rmesa->TexGenEnabled) {
- rmesa->recheck_texgen[unit] = GL_TRUE;
- rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
- }
- }
- }
-}
-
-static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
-
- /* Need to load the 2d images associated with this unit.
- */
- if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) {
- t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2;
- t->base.dirty_images[0] = ~0;
- }
-
- ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
-
- if ( t->base.dirty_images[0] ) {
- RADEON_FIREVERTICES( rmesa );
- radeonSetTexImages( rmesa, tObj );
- radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
- if ( !t->base.memBlock && !t->image_override )
- return GL_FALSE;
- }
-
- return GL_TRUE;
-}
-
-static GLboolean enable_tex_cube( GLcontext *ctx, int unit )
+/**
+ * Compute the cached hardware register values for the given texture object.
+ *
+ * \param rmesa Context pointer
+ * \param t the r300 texture object
+ */
+static GLboolean setup_hardware_state(r100ContextPtr rmesa, radeonTexObj *t, int unit)
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
- GLuint face;
+ const struct gl_texture_image *firstImage;
+ GLint log2Width, log2Height, log2Depth, texelBytes;
- /* Need to load the 2d images associated with this unit.
- */
- if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) {
- t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2;
- for (face = 0; face < 6; face++)
- t->base.dirty_images[face] = ~0;
+ if ( t->bo ) {
+ return GL_TRUE;
}
- ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
+ firstImage = t->base.Image[0][t->mt->firstLevel];
- if ( t->base.dirty_images[0] || t->base.dirty_images[1] ||
- t->base.dirty_images[2] || t->base.dirty_images[3] ||
- t->base.dirty_images[4] || t->base.dirty_images[5] ) {
- /* flush */
- RADEON_FIREVERTICES( rmesa );
- /* layout memory space, once for all faces */
- radeonSetTexImages( rmesa, tObj );
+ if (firstImage->Border > 0) {
+ fprintf(stderr, "%s: border\n", __FUNCTION__);
+ return GL_FALSE;
}
- /* upload (per face) */
- for (face = 0; face < 6; face++) {
- if (t->base.dirty_images[face]) {
- radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, face );
+ log2Width = firstImage->WidthLog2;
+ log2Height = firstImage->HeightLog2;
+ log2Depth = firstImage->DepthLog2;
+ texelBytes = firstImage->TexFormat->TexelBytes;
+
+ if (!t->image_override) {
+ if (VALID_FORMAT(firstImage->TexFormat->MesaFormat)) {
+ const struct tx_table *table = tx_table;
+
+ t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK |
+ RADEON_TXFORMAT_ALPHA_IN_MAP);
+ t->pp_txfilter &= ~RADEON_YUV_TO_RGB;
+
+ t->pp_txformat |= table[ firstImage->TexFormat->MesaFormat ].format;
+ t->pp_txfilter |= table[ firstImage->TexFormat->MesaFormat ].filter;
+ } else {
+ _mesa_problem(NULL, "unexpected texture format in %s",
+ __FUNCTION__);
+ return GL_FALSE;
}
}
-
- if ( !t->base.memBlock ) {
- /* texmem alloc failed, use s/w fallback */
- return GL_FALSE;
+
+ t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
+ t->pp_txfilter |= (t->mt->lastLevel - t->mt->firstLevel) << RADEON_MAX_MIP_LEVEL_SHIFT;
+
+ t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
+ RADEON_TXFORMAT_HEIGHT_MASK |
+ RADEON_TXFORMAT_CUBIC_MAP_ENABLE |
+ RADEON_TXFORMAT_F5_WIDTH_MASK |
+ RADEON_TXFORMAT_F5_HEIGHT_MASK);
+ t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
+ (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
+
+ t->tile_bits = 0;
+
+ if (t->base.Target == GL_TEXTURE_CUBE_MAP) {
+ ASSERT(log2Width == log2Height);
+ t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_F5_WIDTH_SHIFT) |
+ (log2Height << RADEON_TXFORMAT_F5_HEIGHT_SHIFT) |
+ /* don't think we need this bit, if it exists at all - fglrx does not set it */
+ (RADEON_TXFORMAT_CUBIC_MAP_ENABLE));
+ t->pp_cubic_faces = ((log2Width << RADEON_FACE_WIDTH_1_SHIFT) |
+ (log2Height << RADEON_FACE_HEIGHT_1_SHIFT) |
+ (log2Width << RADEON_FACE_WIDTH_2_SHIFT) |
+ (log2Height << RADEON_FACE_HEIGHT_2_SHIFT) |
+ (log2Width << RADEON_FACE_WIDTH_3_SHIFT) |
+ (log2Height << RADEON_FACE_HEIGHT_3_SHIFT) |
+ (log2Width << RADEON_FACE_WIDTH_4_SHIFT) |
+ (log2Height << RADEON_FACE_HEIGHT_4_SHIFT));
}
- return GL_TRUE;
-}
-
-static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+ t->pp_txsize = (((firstImage->Width - 1) << RADEON_TEX_USIZE_SHIFT)
+ | ((firstImage->Height - 1) << RADEON_TEX_VSIZE_SHIFT));
- if (!(t->pp_txformat & RADEON_TXFORMAT_NON_POWER2)) {
- t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2;
- t->base.dirty_images[0] = ~0;
+ if ( !t->image_override ) {
+ if (firstImage->IsCompressed)
+ t->pp_txpitch = (firstImage->Width + 63) & ~(63);
+ else
+ t->pp_txpitch = ((firstImage->Width * texelBytes) + 63) & ~(63);
+ t->pp_txpitch -= 32;
}
- ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
-
- if ( t->base.dirty_images[0] ) {
- RADEON_FIREVERTICES( rmesa );
- radeonSetTexImages( rmesa, tObj );
- radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
- if ( !t->base.memBlock &&
- !t->image_override /* && !rmesa->prefer_gart_client_texturing FIXME */ ) {
- fprintf(stderr, "%s: upload failed\n", __FUNCTION__);
- return GL_FALSE;
- }
+ if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
+ t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2;
}
return GL_TRUE;
}
-
-static GLboolean update_tex_common( GLcontext *ctx, int unit )
+static GLboolean radeon_validate_texture(GLcontext *ctx, struct gl_texture_object *texObj, int unit)
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
- GLenum format;
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
+ radeonTexObj *t = radeon_tex_obj(texObj);
+ int ret;
- /* Fallback if there's a texture border */
- if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
- fprintf(stderr, "%s: border\n", __FUNCTION__);
+ if (!radeon_validate_texture_miptree(ctx, texObj))
return GL_FALSE;
- }
+
+ ret = setup_hardware_state(rmesa, t, unit);
+ if (ret == GL_FALSE)
+ return GL_FALSE;
+
/* yuv conversion only works in first unit */
if (unit != 0 && (t->pp_txfilter & RADEON_YUV_TO_RGB))
return GL_FALSE;
- /* Update state if this is a different texture object to last
- * time.
- */
- if ( rmesa->state.texture.unit[unit].texobj != t ) {
- if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
- /* The old texture is no longer bound to this texture unit.
- * Mark it as such.
- */
-
- rmesa->state.texture.unit[unit].texobj->base.bound &=
- ~(1UL << unit);
- }
-
- rmesa->state.texture.unit[unit].texobj = t;
- t->base.bound |= (1UL << unit);
- t->dirty_state |= 1<<unit;
- driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
- }
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=
+ (RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit;
+ RADEON_STATECHANGE( rmesa, tcl );
+ rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_ST_BIT(unit);
- /* Newly enabled?
- */
- if ( !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit))) {
- RADEON_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=
- (RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit;
+ rmesa->recheck_texgen[unit] = GL_TRUE;
- RADEON_STATECHANGE( rmesa, tcl );
-
- rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_ST_BIT(unit);
-
- rmesa->recheck_texgen[unit] = GL_TRUE;
- }
-
- if (t->dirty_state & (1<<unit)) {
- import_tex_obj_state( rmesa, unit, t );
- /* may need to update texture matrix (for texrect adjustments) */
- rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
- }
+ import_tex_obj_state( rmesa, unit, t );
if (rmesa->recheck_texgen[unit]) {
GLboolean fallback = !radeon_validate_texgen( ctx, unit );
TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
rmesa->recheck_texgen[unit] = 0;
- rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+ rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
}
- format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
- if ( rmesa->state.texture.unit[unit].format != format ||
- rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) {
- rmesa->state.texture.unit[unit].format = format;
- rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode;
- if ( ! radeonUpdateTextureEnv( ctx, unit ) ) {
- return GL_FALSE;
- }
+ if ( ! radeonUpdateTextureEnv( ctx, unit ) ) {
+ return GL_FALSE;
}
-
FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
+
+ t->validated = GL_TRUE;
return !t->border_fallback;
}
-
-
static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit )
{
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
- if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
- return (enable_tex_rect( ctx, unit ) &&
- update_tex_common( ctx, unit ));
- }
- else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
- return (enable_tex_2d( ctx, unit ) &&
- update_tex_common( ctx, unit ));
- }
- else if ( texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT) ) {
- return (enable_tex_cube( ctx, unit ) &&
- update_tex_common( ctx, unit ));
+ if (ctx->Texture.Unit[unit]._ReallyEnabled & TEXTURE_3D_BIT) {
+ rmesa->state.texture.unit[unit].texobj = NULL;
+ return GL_FALSE;
}
- else if ( texUnit->_ReallyEnabled ) {
- return GL_FALSE;
+
+ if (!ctx->Texture.Unit[unit]._ReallyEnabled) {
+ /* disable the unit */
+ disable_tex_obj_state(rmesa, unit);
+ rmesa->state.texture.unit[unit].texobj = NULL;
+ return GL_TRUE;
}
- else {
- disable_tex( ctx, unit );
- return GL_TRUE;
+
+ if (!radeon_validate_texture(ctx, ctx->Texture.Unit[unit]._Current, unit)) {
+ _mesa_warning(ctx,
+ "failed to validate texture for unit %d.\n",
+ unit);
+ rmesa->state.texture.unit[unit].texobj = NULL;
+ return GL_FALSE;
}
+ rmesa->state.texture.unit[unit].texobj = radeon_tex_obj(ctx->Texture.Unit[unit]._Current);
+ return GL_TRUE;
}
void radeonUpdateTextureState( GLcontext *ctx )
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLboolean ok;
+ /* set the ctx all textures off */
+ RADEON_STATECHANGE( rmesa, ctx );
+ rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~((RADEON_TEX_ENABLE_MASK) | (RADEON_TEX_BLEND_ENABLE_MASK));
+
ok = (radeonUpdateTextureUnit( ctx, 0 ) &&
radeonUpdateTextureUnit( ctx, 1 ) &&
radeonUpdateTextureUnit( ctx, 2 ));
FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok );
- if (rmesa->TclFallback)
+ if (rmesa->radeon.TclFallback)
radeonChooseVertexState( ctx );
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c
new file mode 100644
index 0000000000..fad3d1ceda
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_texture.c
@@ -0,0 +1,1052 @@
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/convolve.h"
+#include "main/mipmap.h"
+#include "main/texcompress.h"
+#include "main/texformat.h"
+#include "main/texstore.h"
+#include "main/teximage.h"
+#include "main/texobj.h"
+#include "main/texgetimage.h"
+
+#include "xmlpool.h" /* for symbolic values of enum-type options */
+
+#include "radeon_common.h"
+
+#include "radeon_mipmap_tree.h"
+
+
+static void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
+ GLuint numrows, GLuint rowsize)
+{
+ assert(rowsize <= dststride);
+ assert(rowsize <= srcstride);
+
+ if (rowsize == srcstride && rowsize == dststride) {
+ memcpy(dst, src, numrows*rowsize);
+ } else {
+ GLuint i;
+ for(i = 0; i < numrows; ++i) {
+ memcpy(dst, src, rowsize);
+ dst += dststride;
+ src += srcstride;
+ }
+ }
+}
+
+/* textures */
+/**
+ * Allocate an empty texture image object.
+ */
+struct gl_texture_image *radeonNewTextureImage(GLcontext *ctx)
+{
+ return CALLOC(sizeof(radeon_texture_image));
+}
+
+/**
+ * Free memory associated with this texture image.
+ */
+void radeonFreeTexImageData(GLcontext *ctx, struct gl_texture_image *timage)
+{
+ radeon_texture_image* image = get_radeon_texture_image(timage);
+
+ if (image->mt) {
+ radeon_miptree_unreference(image->mt);
+ image->mt = 0;
+ assert(!image->base.Data);
+ } else {
+ _mesa_free_texture_image_data(ctx, timage);
+ }
+ if (image->bo) {
+ radeon_bo_unref(image->bo);
+ image->bo = NULL;
+ }
+ if (timage->Data) {
+ _mesa_free_texmemory(timage->Data);
+ timage->Data = NULL;
+ }
+}
+
+/* Set Data pointer and additional data for mapped texture image */
+static void teximage_set_map_data(radeon_texture_image *image)
+{
+ radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
+
+ image->base.Data = image->mt->bo->ptr + lvl->faces[image->mtface].offset;
+ image->base.RowStride = lvl->rowstride / image->mt->bpp;
+}
+
+
+/**
+ * Map a single texture image for glTexImage and friends.
+ */
+void radeon_teximage_map(radeon_texture_image *image, GLboolean write_enable)
+{
+ if (image->mt) {
+ assert(!image->base.Data);
+
+ radeon_bo_map(image->mt->bo, write_enable);
+ teximage_set_map_data(image);
+ }
+}
+
+
+void radeon_teximage_unmap(radeon_texture_image *image)
+{
+ if (image->mt) {
+ assert(image->base.Data);
+
+ image->base.Data = 0;
+ radeon_bo_unmap(image->mt->bo);
+ }
+}
+
+static void map_override(GLcontext *ctx, radeonTexObj *t)
+{
+ radeon_texture_image *img = get_radeon_texture_image(t->base.Image[0][0]);
+
+ radeon_bo_map(t->bo, GL_FALSE);
+
+ img->base.Data = t->bo->ptr;
+ _mesa_set_fetch_functions(&img->base, 2);
+}
+
+static void unmap_override(GLcontext *ctx, radeonTexObj *t)
+{
+ radeon_texture_image *img = get_radeon_texture_image(t->base.Image[0][0]);
+
+ radeon_bo_unmap(t->bo);
+
+ img->base.Data = NULL;
+}
+
+/**
+ * Map a validated texture for reading during software rendering.
+ */
+void radeonMapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ radeonTexObj* t = radeon_tex_obj(texObj);
+ int face, level;
+
+ if (!radeon_validate_texture_miptree(ctx, texObj))
+ return;
+
+ /* for r100 3D sw fallbacks don't have mt */
+ if (t->image_override && t->bo)
+ map_override(ctx, t);
+
+ if (!t->mt)
+ return;
+
+ radeon_bo_map(t->mt->bo, GL_FALSE);
+ for(face = 0; face < t->mt->faces; ++face) {
+ for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level)
+ teximage_set_map_data(get_radeon_texture_image(texObj->Image[face][level]));
+ }
+}
+
+void radeonUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ radeonTexObj* t = radeon_tex_obj(texObj);
+ int face, level;
+
+ if (t->image_override && t->bo)
+ unmap_override(ctx, t);
+ /* for r100 3D sw fallbacks don't have mt */
+ if (!t->mt)
+ return;
+
+ for(face = 0; face < t->mt->faces; ++face) {
+ for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level)
+ texObj->Image[face][level]->Data = 0;
+ }
+ radeon_bo_unmap(t->mt->bo);
+}
+
+GLuint radeon_face_for_target(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Wraps Mesa's implementation to ensure that the base level image is mapped.
+ *
+ * This relies on internal details of _mesa_generate_mipmap, in particular
+ * the fact that the memory for recreated texture images is always freed.
+ */
+static void radeon_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ radeonTexObj* t = radeon_tex_obj(texObj);
+ GLuint nr_faces = (t->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ int i, face;
+
+
+ _mesa_generate_mipmap(ctx, target, texObj);
+
+ for (face = 0; face < nr_faces; face++) {
+ for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) {
+ radeon_texture_image *image;
+
+ image = get_radeon_texture_image(texObj->Image[face][i]);
+
+ if (image == NULL)
+ break;
+
+ image->mtlevel = i;
+ image->mtface = face;
+
+ radeon_miptree_unreference(image->mt);
+ image->mt = NULL;
+ }
+ }
+
+}
+
+void radeonGenerateMipmap(GLcontext* ctx, GLenum target, struct gl_texture_object *texObj)
+{
+ GLuint face = radeon_face_for_target(target);
+ radeon_texture_image *baseimage = get_radeon_texture_image(texObj->Image[face][texObj->BaseLevel]);
+
+ radeon_teximage_map(baseimage, GL_FALSE);
+ radeon_generate_mipmap(ctx, target, texObj);
+ radeon_teximage_unmap(baseimage);
+}
+
+
+/* try to find a format which will only need a memcopy */
+static const struct gl_texture_format *radeonChoose8888TexFormat(radeonContextPtr rmesa,
+ GLenum srcFormat,
+ GLenum srcType, GLboolean fbo)
+{
+ const GLuint ui = 1;
+ const GLubyte littleEndian = *((const GLubyte *)&ui);
+
+ /* r100 can only do this */
+ if (IS_R100_CLASS(rmesa->radeonScreen) || fbo)
+ return _dri_texformat_argb8888;
+
+ if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
+ (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) {
+ return &_mesa_texformat_rgba8888;
+ } else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
+ (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) {
+ return &_mesa_texformat_rgba8888_rev;
+ } else if (IS_R200_CLASS(rmesa->radeonScreen)) {
+ return _dri_texformat_argb8888;
+ } else if (srcFormat == GL_BGRA && ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8)) {
+ return &_mesa_texformat_argb8888_rev;
+ } else if (srcFormat == GL_BGRA && ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
+ return &_mesa_texformat_argb8888;
+ } else
+ return _dri_texformat_argb8888;
+}
+
+const struct gl_texture_format *radeonChooseTextureFormat_mesa(GLcontext * ctx,
+ GLint internalFormat,
+ GLenum format,
+ GLenum type)
+{
+ return radeonChooseTextureFormat(ctx, internalFormat, format,
+ type, 0);
+}
+
+const struct gl_texture_format *radeonChooseTextureFormat(GLcontext * ctx,
+ GLint internalFormat,
+ GLenum format,
+ GLenum type, GLboolean fbo)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ const GLboolean do32bpt =
+ (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32);
+ const GLboolean force16bpt =
+ (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16);
+ (void)format;
+
+#if 0
+ fprintf(stderr, "InternalFormat=%s(%d) type=%s format=%s\n",
+ _mesa_lookup_enum_by_nr(internalFormat), internalFormat,
+ _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
+ fprintf(stderr, "do32bpt=%d force16bpt=%d\n", do32bpt, force16bpt);
+#endif
+
+ switch (internalFormat) {
+ case 4:
+ case GL_RGBA:
+ case GL_COMPRESSED_RGBA:
+ switch (type) {
+ case GL_UNSIGNED_INT_10_10_10_2:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return do32bpt ? _dri_texformat_argb8888 :
+ _dri_texformat_argb1555;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ return _dri_texformat_argb4444;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ return _dri_texformat_argb1555;
+ default:
+ return do32bpt ? radeonChoose8888TexFormat(rmesa, format, type, fbo) :
+ _dri_texformat_argb4444;
+ }
+
+ case 3:
+ case GL_RGB:
+ case GL_COMPRESSED_RGB:
+ switch (type) {
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ return _dri_texformat_argb4444;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ return _dri_texformat_argb1555;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ return _dri_texformat_rgb565;
+ default:
+ return do32bpt ? _dri_texformat_argb8888 :
+ _dri_texformat_rgb565;
+ }
+
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return !force16bpt ?
+ radeonChoose8888TexFormat(rmesa, format, type, fbo) :
+ _dri_texformat_argb4444;
+
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return _dri_texformat_argb4444;
+
+ case GL_RGB5_A1:
+ return _dri_texformat_argb1555;
+
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return !force16bpt ? _dri_texformat_argb8888 :
+ _dri_texformat_rgb565;
+
+ case GL_RGB5:
+ case GL_RGB4:
+ case GL_R3_G3_B2:
+ return _dri_texformat_rgb565;
+
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case GL_COMPRESSED_ALPHA:
+ /* r200: can't use a8 format since interpreting hw I8 as a8 would result
+ in wrong rgb values (same as alpha value instead of 0). */
+ if (IS_R200_CLASS(rmesa->radeonScreen))
+ return _dri_texformat_al88;
+ else
+ return _dri_texformat_a8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_COMPRESSED_LUMINANCE:
+ return _dri_texformat_l8;
+
+ case 2:
+ 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:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ return _dri_texformat_al88;
+
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case GL_COMPRESSED_INTENSITY:
+ return _dri_texformat_i8;
+
+ case GL_YCBCR_MESA:
+ if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
+ type == GL_UNSIGNED_BYTE)
+ return &_mesa_texformat_ycbcr;
+ else
+ return &_mesa_texformat_ycbcr_rev;
+
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return &_mesa_texformat_rgb_dxt1;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return &_mesa_texformat_rgba_dxt1;
+
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ return &_mesa_texformat_rgba_dxt3;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return &_mesa_texformat_rgba_dxt5;
+
+ case GL_ALPHA16F_ARB:
+ return &_mesa_texformat_alpha_float16;
+ case GL_ALPHA32F_ARB:
+ return &_mesa_texformat_alpha_float32;
+ case GL_LUMINANCE16F_ARB:
+ return &_mesa_texformat_luminance_float16;
+ case GL_LUMINANCE32F_ARB:
+ return &_mesa_texformat_luminance_float32;
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ return &_mesa_texformat_luminance_alpha_float16;
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ return &_mesa_texformat_luminance_alpha_float32;
+ case GL_INTENSITY16F_ARB:
+ return &_mesa_texformat_intensity_float16;
+ case GL_INTENSITY32F_ARB:
+ return &_mesa_texformat_intensity_float32;
+ case GL_RGB16F_ARB:
+ return &_mesa_texformat_rgba_float16;
+ case GL_RGB32F_ARB:
+ return &_mesa_texformat_rgba_float32;
+ case GL_RGBA16F_ARB:
+ return &_mesa_texformat_rgba_float16;
+ case GL_RGBA32F_ARB:
+ return &_mesa_texformat_rgba_float32;
+
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ return &_mesa_texformat_s8_z24;
+
+ /* EXT_texture_sRGB */
+ case GL_SRGB:
+ case GL_SRGB8:
+ case GL_SRGB_ALPHA:
+ case GL_SRGB8_ALPHA8:
+ case GL_COMPRESSED_SRGB:
+ case GL_COMPRESSED_SRGB_ALPHA:
+ return &_mesa_texformat_srgba8;
+
+ case GL_SLUMINANCE:
+ case GL_SLUMINANCE8:
+ case GL_COMPRESSED_SLUMINANCE:
+ return &_mesa_texformat_sl8;
+
+ case GL_SLUMINANCE_ALPHA:
+ case GL_SLUMINANCE8_ALPHA8:
+ case GL_COMPRESSED_SLUMINANCE_ALPHA:
+ return &_mesa_texformat_sla8;
+
+ default:
+ _mesa_problem(ctx,
+ "unexpected internalFormat 0x%x in %s",
+ (int)internalFormat, __func__);
+ return NULL;
+ }
+
+ return NULL; /* never get here */
+}
+
+/**
+ * All glTexImage calls go through this function.
+ */
+static void radeon_teximage(
+ GLcontext *ctx, int dims,
+ GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth,
+ GLsizei imageSize,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ int compressed)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeonTexObj* t = radeon_tex_obj(texObj);
+ radeon_texture_image* image = get_radeon_texture_image(texImage);
+ GLuint dstRowStride;
+ GLint postConvWidth = width;
+ GLint postConvHeight = height;
+ GLuint texelBytes;
+ GLuint face = radeon_face_for_target(target);
+
+ radeon_firevertices(rmesa);
+
+ t->validated = GL_FALSE;
+
+ if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
+ _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
+ &postConvHeight);
+ }
+
+ /* Choose and fill in the texture format for this image */
+ texImage->TexFormat = radeonChooseTextureFormat(ctx, internalFormat, format, type, 0);
+ _mesa_set_fetch_functions(texImage, dims);
+
+ if (texImage->TexFormat->TexelBytes == 0) {
+ texelBytes = 0;
+ texImage->IsCompressed = GL_TRUE;
+ texImage->CompressedSize =
+ ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
+ texImage->Height, texImage->Depth,
+ texImage->TexFormat->MesaFormat);
+ } else {
+ texImage->IsCompressed = GL_FALSE;
+ texImage->CompressedSize = 0;
+
+ texelBytes = texImage->TexFormat->TexelBytes;
+ /* Minimum pitch of 32 bytes */
+ if (postConvWidth * texelBytes < 32) {
+ postConvWidth = 32 / texelBytes;
+ texImage->RowStride = postConvWidth;
+ }
+ if (!image->mt) {
+ assert(texImage->RowStride == postConvWidth);
+ }
+ }
+
+ /* Allocate memory for image */
+ radeonFreeTexImageData(ctx, texImage); /* Mesa core only clears texImage->Data but not image->mt */
+
+ if (t->mt &&
+ t->mt->firstLevel == level &&
+ t->mt->lastLevel == level &&
+ t->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
+ !radeon_miptree_matches_image(t->mt, texImage, face, level)) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = NULL;
+ }
+
+ if (!t->mt)
+ radeon_try_alloc_miptree(rmesa, t, image, face, level);
+ if (t->mt && radeon_miptree_matches_image(t->mt, texImage, face, level)) {
+ radeon_mipmap_level *lvl;
+ image->mt = t->mt;
+ image->mtlevel = level - t->mt->firstLevel;
+ image->mtface = face;
+ radeon_miptree_reference(t->mt);
+ lvl = &image->mt->levels[image->mtlevel];
+ dstRowStride = lvl->rowstride;
+ } else {
+ int size;
+ if (texImage->IsCompressed) {
+ size = texImage->CompressedSize;
+ } else {
+ size = texImage->Width * texImage->Height * texImage->Depth * texImage->TexFormat->TexelBytes;
+ }
+ texImage->Data = _mesa_alloc_texmemory(size);
+ }
+
+ /* Upload texture image; note that the spec allows pixels to be NULL */
+ if (compressed) {
+ pixels = _mesa_validate_pbo_compressed_teximage(
+ ctx, imageSize, pixels, packing, "glCompressedTexImage");
+ } else {
+ pixels = _mesa_validate_pbo_teximage(
+ ctx, dims, width, height, depth,
+ format, type, pixels, packing, "glTexImage");
+ }
+
+ if (pixels) {
+ radeon_teximage_map(image, GL_TRUE);
+ if (compressed) {
+ if (image->mt) {
+ uint32_t srcRowStride, bytesPerRow, rows;
+ srcRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
+ bytesPerRow = srcRowStride;
+ rows = (height + 3) / 4;
+ copy_rows(texImage->Data, image->mt->levels[level].rowstride,
+ pixels, srcRowStride, rows, bytesPerRow);
+ } else {
+ memcpy(texImage->Data, pixels, imageSize);
+ }
+ } else {
+ GLuint dstRowStride;
+ GLuint *dstImageOffsets;
+
+ if (image->mt) {
+ radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
+ dstRowStride = lvl->rowstride;
+ } else {
+ dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
+ }
+
+ if (dims == 3) {
+ int i;
+
+ dstImageOffsets = _mesa_malloc(depth * sizeof(GLuint)) ;
+ if (!dstImageOffsets)
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+
+ for (i = 0; i < depth; ++i) {
+ dstImageOffsets[i] = dstRowStride/texImage->TexFormat->TexelBytes * height * i;
+ }
+ } else {
+ dstImageOffsets = texImage->ImageOffsets;
+ }
+
+ if (!texImage->TexFormat->StoreImage(ctx, dims,
+ texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ dstImageOffsets,
+ width, height, depth,
+ format, type, pixels, packing))
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+
+ if (dims == 3)
+ _mesa_free(dstImageOffsets);
+ }
+
+ /* SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ radeon_generate_mipmap(ctx, target, texObj);
+ }
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+
+ if (pixels)
+ radeon_teximage_unmap(image);
+
+
+}
+
+void radeonTexImage1D(GLcontext * ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeon_teximage(ctx, 1, target, level, internalFormat, width, 1, 1,
+ 0, format, type, pixels, packing, texObj, texImage, 0);
+}
+
+void radeonTexImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+
+{
+ radeon_teximage(ctx, 2, target, level, internalFormat, width, height, 1,
+ 0, format, type, pixels, packing, texObj, texImage, 0);
+}
+
+void radeonCompressedTexImage2D(GLcontext * ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLsizei imageSize, const GLvoid * data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeon_teximage(ctx, 2, target, level, internalFormat, width, height, 1,
+ imageSize, 0, 0, data, &ctx->Unpack, texObj, texImage, 1);
+}
+
+void radeonTexImage3D(GLcontext * ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth,
+ GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeon_teximage(ctx, 3, target, level, internalFormat, width, height, depth,
+ 0, format, type, pixels, packing, texObj, texImage, 0);
+}
+
+/**
+ * Update a subregion of the given texture image.
+ */
+static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLsizei imageSize,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ int compressed)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeonTexObj* t = radeon_tex_obj(texObj);
+ radeon_texture_image* image = get_radeon_texture_image(texImage);
+
+ radeon_firevertices(rmesa);
+
+ t->validated = GL_FALSE;
+ if (compressed) {
+ pixels = _mesa_validate_pbo_compressed_teximage(
+ ctx, imageSize, pixels, packing, "glCompressedTexImage");
+ } else {
+ pixels = _mesa_validate_pbo_teximage(ctx, dims,
+ width, height, depth, format, type, pixels, packing, "glTexSubImage1D");
+ }
+
+ if (pixels) {
+ GLint dstRowStride;
+ radeon_teximage_map(image, GL_TRUE);
+
+ if (image->mt) {
+ radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
+ dstRowStride = lvl->rowstride;
+ } else {
+ dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
+ }
+
+ if (compressed) {
+ uint32_t srcRowStride, bytesPerRow, rows;
+ GLubyte *img_start;
+ if (!image->mt) {
+ dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, texImage->Width);
+ img_start = _mesa_compressed_image_address(xoffset, yoffset, 0,
+ texImage->TexFormat->MesaFormat,
+ texImage->Width, texImage->Data);
+ }
+ else {
+ uint32_t blocks_x = dstRowStride / (image->mt->bpp * 4);
+ img_start = texImage->Data + image->mt->bpp * 4 * (blocks_x * (yoffset / 4) + xoffset / 4);
+ }
+ srcRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
+ bytesPerRow = srcRowStride;
+ rows = (height + 3) / 4;
+
+ copy_rows(img_start, dstRowStride, pixels, srcRowStride, rows, bytesPerRow);
+
+ } else {
+ if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
+ texImage->TexFormat, texImage->Data,
+ xoffset, yoffset, zoffset,
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, depth,
+ format, type, pixels, packing))
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ radeon_generate_mipmap(ctx, target, texObj);
+ }
+ }
+
+ radeon_teximage_unmap(image);
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+
+
+}
+
+void radeonTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeon_texsubimage(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1, 0,
+ format, type, pixels, packing, texObj, texImage, 0);
+}
+
+void radeonTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeon_texsubimage(ctx, 2, target, level, xoffset, yoffset, 0, width, height, 1,
+ 0, format, type, pixels, packing, texObj, texImage,
+ 0);
+}
+
+void radeonCompressedTexSubImage2D(GLcontext * ctx, GLenum target,
+ GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width,
+ GLsizei height, GLenum format,
+ GLsizei imageSize, const GLvoid * data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeon_texsubimage(ctx, 2, target, level, xoffset, yoffset, 0, width, height, 1,
+ imageSize, format, 0, data, &ctx->Unpack, texObj, texImage, 1);
+}
+
+
+void radeonTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeon_texsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, width, height, depth, 0,
+ format, type, pixels, packing, texObj, texImage, 0);
+}
+
+
+
+/**
+ * Ensure that the given image is stored in the given miptree from now on.
+ */
+static void migrate_image_to_miptree(radeon_mipmap_tree *mt, radeon_texture_image *image, int face, int level)
+{
+ radeon_mipmap_level *dstlvl = &mt->levels[level - mt->firstLevel];
+ unsigned char *dest;
+
+ assert(image->mt != mt);
+ assert(dstlvl->width == image->base.Width);
+ assert(dstlvl->height == image->base.Height);
+ assert(dstlvl->depth == image->base.Depth);
+
+
+ radeon_bo_map(mt->bo, GL_TRUE);
+ dest = mt->bo->ptr + dstlvl->faces[face].offset;
+
+ if (image->mt) {
+ /* Format etc. should match, so we really just need a memcpy().
+ * In fact, that memcpy() could be done by the hardware in many
+ * cases, provided that we have a proper memory manager.
+ */
+ radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel-image->mt->firstLevel];
+
+ assert(srclvl->size == dstlvl->size);
+ assert(srclvl->rowstride == dstlvl->rowstride);
+
+ radeon_bo_map(image->mt->bo, GL_FALSE);
+
+ memcpy(dest,
+ image->mt->bo->ptr + srclvl->faces[face].offset,
+ dstlvl->size);
+ radeon_bo_unmap(image->mt->bo);
+
+ radeon_miptree_unreference(image->mt);
+ } else {
+ uint32_t srcrowstride;
+ uint32_t height;
+ /* need to confirm this value is correct */
+ if (mt->compressed) {
+ height = (image->base.Height + 3) / 4;
+ srcrowstride = _mesa_compressed_row_stride(image->base.TexFormat->MesaFormat, image->base.Width);
+ } else {
+ height = image->base.Height * image->base.Depth;
+ srcrowstride = image->base.Width * image->base.TexFormat->TexelBytes;
+ }
+
+// if (mt->tilebits)
+// WARN_ONCE("%s: tiling not supported yet", __FUNCTION__);
+
+ copy_rows(dest, dstlvl->rowstride, image->base.Data, srcrowstride,
+ height, srcrowstride);
+
+ _mesa_free_texmemory(image->base.Data);
+ image->base.Data = 0;
+ }
+
+ radeon_bo_unmap(mt->bo);
+
+ image->mt = mt;
+ image->mtface = face;
+ image->mtlevel = level;
+ radeon_miptree_reference(image->mt);
+}
+
+int radeon_validate_texture_miptree(GLcontext * ctx, struct gl_texture_object *texObj)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeonTexObj *t = radeon_tex_obj(texObj);
+ radeon_texture_image *baseimage = get_radeon_texture_image(texObj->Image[0][texObj->BaseLevel]);
+ int face, level;
+
+ if (t->validated || t->image_override)
+ return GL_TRUE;
+
+ if (RADEON_DEBUG & RADEON_TEXTURE)
+ fprintf(stderr, "%s: Validating texture %p now\n", __FUNCTION__, texObj);
+
+ if (baseimage->base.Border > 0)
+ return GL_FALSE;
+
+ /* Ensure a matching miptree exists.
+ *
+ * Differing mipmap trees can result when the app uses TexImage to
+ * change texture dimensions.
+ *
+ * Prefer to use base image's miptree if it
+ * exists, since that most likely contains more valid data (remember
+ * that the base level is usually significantly larger than the rest
+ * of the miptree, so cubemaps are the only possible exception).
+ */
+ if (baseimage->mt &&
+ baseimage->mt != t->mt &&
+ radeon_miptree_matches_texture(baseimage->mt, &t->base)) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = baseimage->mt;
+ radeon_miptree_reference(t->mt);
+ } else if (t->mt && !radeon_miptree_matches_texture(t->mt, &t->base)) {
+ radeon_miptree_unreference(t->mt);
+ t->mt = 0;
+ }
+
+ if (!t->mt) {
+ if (RADEON_DEBUG & RADEON_TEXTURE)
+ fprintf(stderr, " Allocate new miptree\n");
+ radeon_try_alloc_miptree(rmesa, t, baseimage, 0, texObj->BaseLevel);
+ if (!t->mt) {
+ _mesa_problem(ctx, "radeon_validate_texture failed to alloc miptree");
+ return GL_FALSE;
+ }
+ }
+
+ /* Ensure all images are stored in the single main miptree */
+ for(face = 0; face < t->mt->faces; ++face) {
+ for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level) {
+ radeon_texture_image *image = get_radeon_texture_image(texObj->Image[face][level]);
+ if (RADEON_DEBUG & RADEON_TEXTURE)
+ fprintf(stderr, " face %i, level %i... %p vs %p ", face, level, t->mt, image->mt);
+ if (t->mt == image->mt) {
+ if (RADEON_DEBUG & RADEON_TEXTURE)
+ fprintf(stderr, "OK\n");
+
+ continue;
+ }
+
+ if (RADEON_DEBUG & RADEON_TEXTURE)
+ fprintf(stderr, "migrating\n");
+ migrate_image_to_miptree(t->mt, image, face, level);
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Need to map texture image into memory before copying image data,
+ * then unmap it.
+ */
+static void
+radeon_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid * pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage, int compressed)
+{
+ radeon_texture_image *image = get_radeon_texture_image(texImage);
+
+ if (image->mt) {
+ /* Map the texture image read-only */
+ radeon_teximage_map(image, GL_FALSE);
+ } else {
+ /* Image hasn't been uploaded to a miptree yet */
+ assert(image->base.Data);
+ }
+
+ if (compressed) {
+ /* FIXME: this can't work for small textures (mips) which
+ use different hw stride */
+ _mesa_get_compressed_teximage(ctx, target, level, pixels,
+ texObj, texImage);
+ } else {
+ _mesa_get_teximage(ctx, target, level, format, type, pixels,
+ texObj, texImage);
+ }
+
+ if (image->mt) {
+ radeon_teximage_unmap(image);
+ }
+}
+
+void
+radeonGetTexImage(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid * pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeon_get_tex_image(ctx, target, level, format, type, pixels,
+ texObj, texImage, 0);
+}
+
+void
+radeonGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeon_get_tex_image(ctx, target, level, 0, 0, pixels,
+ texObj, texImage, 1);
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.h b/src/mesa/drivers/dri/radeon/radeon_texture.h
new file mode 100644
index 0000000000..888a55ba91
--- /dev/null
+++ b/src/mesa/drivers/dri/radeon/radeon_texture.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef RADEON_TEXTURE_H
+#define RADEON_TEXTURE_H
+struct gl_texture_image *radeonNewTextureImage(GLcontext *ctx);
+void radeonFreeTexImageData(GLcontext *ctx, struct gl_texture_image *timage);
+
+void radeon_teximage_map(radeon_texture_image *image, GLboolean write_enable);
+void radeon_teximage_unmap(radeon_texture_image *image);
+void radeonMapTexture(GLcontext *ctx, struct gl_texture_object *texObj);
+void radeonUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj);
+void radeonGenerateMipmap(GLcontext* ctx, GLenum target, struct gl_texture_object *texObj);
+int radeon_validate_texture_miptree(GLcontext * ctx, struct gl_texture_object *texObj);
+GLuint radeon_face_for_target(GLenum target);
+const struct gl_texture_format *radeonChooseTextureFormat_mesa(GLcontext * ctx,
+ GLint internalFormat,
+ GLenum format,
+ GLenum type);
+const struct gl_texture_format *radeonChooseTextureFormat(GLcontext * ctx,
+ GLint internalFormat,
+ GLenum format,
+ GLenum type, GLboolean fbo);
+
+void radeonTexImage1D(GLcontext * ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+void radeonTexImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+void radeonCompressedTexImage2D(GLcontext * ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLsizei imageSize, const GLvoid * data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+void radeonTexImage3D(GLcontext * ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth,
+ GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+void radeonTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+void radeonTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+void radeonCompressedTexSubImage2D(GLcontext * ctx, GLenum target,
+ GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width,
+ GLsizei height, GLenum format,
+ GLsizei imageSize, const GLvoid * data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+void radeonTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+void radeonGetTexImage(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid * pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+void radeonGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/server/radeon_reg.h b/src/mesa/drivers/dri/radeon/server/radeon_reg.h
index 596a8aa715..e81d7fdcd0 100644
--- a/src/mesa/drivers/dri/radeon/server/radeon_reg.h
+++ b/src/mesa/drivers/dri/radeon/server/radeon_reg.h
@@ -1500,7 +1500,7 @@
# define RADEON_ALPHA_ARG_C_T1_ALPHA (6 << 8)
# define RADEON_ALPHA_ARG_C_T2_ALPHA (7 << 8)
# define RADEON_ALPHA_ARG_C_T3_ALPHA (8 << 8)
-# define RADEON_DOT_ALPHA_DONT_REPLICATE (1 << 9)
+# define RADEON_DOT_ALPHA_DONT_REPLICATE (1 << 12)
# define RADEON_ALPHA_ARG_MASK 0xf
#define RADEON_PP_TFACTOR_0 0x1c68
@@ -1601,6 +1601,8 @@
# define RADEON_STENCIL_VALUE_MASK (0xff << 16)
# define RADEON_STENCIL_WRITEMASK_SHIFT 24
# define RADEON_STENCIL_WRITE_MASK (0xff << 24)
+#define RADEON_RB3D_ZPASS_DATA 0x3290
+#define RADEON_RB3D_ZPASS_ADDR 0x3294
#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
# define RADEON_DEPTH_FORMAT_MASK (0xf << 0)
# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0)
@@ -1661,6 +1663,9 @@
# define RADEON_FORCE_Z_DIRTY (1 << 29)
# define RADEON_Z_WRITE_ENABLE (1 << 30)
# define RADEON_Z_DECOMPRESSION_ENABLE (1 << 31)
+
+#define RADEON_RE_STIPPLE_ADDR 0x1cc8
+#define RADEON_RE_STIPPLE_DATA 0x1ccc
#define RADEON_RE_LINE_PATTERN 0x1cd0
# define RADEON_LINE_PATTERN_MASK 0x0000ffff
# define RADEON_LINE_REPEAT_COUNT_SHIFT 16
@@ -2031,6 +2036,9 @@
#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00
#define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00
#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00
+#define R200_CP_CMD_3D_DRAW_VBUF_2 0xC0003400
+#define R200_CP_CMD_3D_DRAW_IMMD_2 0xC0003500
+#define R200_CP_CMD_3D_DRAW_INDX_2 0xC0003600
#define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100
#define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200
#define RADEON_CP_PACKET3_CNTL_SMALLTEXT 0xC0009300
diff --git a/src/mesa/drivers/dri/s3v/s3v_context.c b/src/mesa/drivers/dri/s3v/s3v_context.c
index 14502f95ae..0a3bf7258d 100644
--- a/src/mesa/drivers/dri/s3v/s3v_context.c
+++ b/src/mesa/drivers/dri/s3v/s3v_context.c
@@ -108,6 +108,8 @@ GLboolean s3vCreateContext(const __GLcontextModes *glVisual,
ctx->Const.MaxLineWidthAA = 1.0;
ctx->Const.LineWidthGranularity = 1.0;
+ ctx->Const.MaxDrawBuffers = 1;
+
vmesa->texHeap = mmInit( 0, vmesa->s3vScreen->textureSize );
DEBUG(("vmesa->s3vScreen->textureSize = 0x%x\n",
vmesa->s3vScreen->textureSize));
diff --git a/src/mesa/drivers/dri/s3v/s3v_state.c b/src/mesa/drivers/dri/s3v/s3v_state.c
index c71c89a3e1..561f42c705 100644
--- a/src/mesa/drivers/dri/s3v/s3v_state.c
+++ b/src/mesa/drivers/dri/s3v/s3v_state.c
@@ -2,7 +2,6 @@
* Author: Max Lingua <sunmax@libero.it>
*/
-#include <X11/Xlibint.h>
#include "s3v_context.h"
#include "s3v_macros.h"
#include "s3v_dri.h"
@@ -24,7 +23,7 @@
static void s3vUpdateAlphaMode( GLcontext *ctx )
{
s3vContextPtr vmesa = S3V_CONTEXT(ctx);
- CARD32 cmd = vmesa->CMD;
+ uint32_t cmd = vmesa->CMD;
cmd &= ~ALPHA_BLEND_MASK;
if ( ctx->Color.BlendEnabled ) {
@@ -173,7 +172,7 @@ static void s3vDDClear( GLcontext *ctx, GLbitfield mask )
static void s3vUpdateZMode( GLcontext *ctx )
{
s3vContextPtr vmesa = S3V_CONTEXT(ctx);
- CARD32 cmd = vmesa->CMD;
+ uint32_t cmd = vmesa->CMD;
DEBUG(("Depth.Test = %i\n", ctx->Depth.Test));
DEBUG(("CMD was = 0x%x ", cmd));
diff --git a/src/mesa/drivers/dri/s3v/s3v_tex.c b/src/mesa/drivers/dri/s3v/s3v_tex.c
index 8bf2ea9878..9b92519862 100644
--- a/src/mesa/drivers/dri/s3v/s3v_tex.c
+++ b/src/mesa/drivers/dri/s3v/s3v_tex.c
@@ -132,8 +132,14 @@ static void s3vSetTexFilter(s3vContextPtr vmesa,
static void s3vSetTexBorderColor(s3vContextPtr vmesa,
s3vTextureObjectPtr t,
- GLubyte color[4])
+ const GLfloat color[4])
{
+ GLubyte c[4];
+ CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
+
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vSetTexBorderColor: #%i ***\n", ++times));
@@ -143,8 +149,7 @@ static void s3vSetTexBorderColor(s3vContextPtr vmesa,
/* switch(t0 ... t->TextureColorMode) */
/* case TEX_COL_ARGB1555: */
- t->TextureBorderColor =
- S3VIRGEPACKCOLOR555(color[0], color[1], color[2], color[3]);
+ t->TextureBorderColor = S3VIRGEPACKCOLOR555(c[0], c[1], c[2], c[3]);
DEBUG(("TextureBorderColor = 0x%x\n", t->TextureBorderColor));
@@ -182,7 +187,7 @@ static void s3vTexParameter( GLcontext *ctx, GLenum target,
break;
case GL_TEXTURE_BORDER_COLOR:
- s3vSetTexBorderColor( vmesa, t, tObj->_BorderChan );
+ s3vSetTexBorderColor( vmesa, t, tObj->BorderColor );
break;
case GL_TEXTURE_BASE_LEVEL:
@@ -502,20 +507,20 @@ static void s3vInitTextureObjects( GLcontext *ctx )
#if 1
ctx->Texture.CurrentUnit = 0;
- texObj = ctx->Texture.Unit[0].Current1D;
+ texObj = ctx->Texture.Unit[0].CurrentTex[TEXTURE_1D_INDEX];
s3vBindTexture( ctx, GL_TEXTURE_1D, texObj );
- texObj = ctx->Texture.Unit[0].Current2D;
+ texObj = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];
s3vBindTexture( ctx, GL_TEXTURE_2D, texObj );
#endif
#if 0
ctx->Texture.CurrentUnit = 1;
- texObj = ctx->Texture.Unit[1].Current1D;
+ texObj = ctx->Texture.Unit[1].CurrentTex[TEXTURE_1D_INDEX];
s3vBindTexture( ctx, GL_TEXTURE_1D, texObj );
- texObj = ctx->Texture.Unit[1].Current2D;
+ texObj = ctx->Texture.Unit[1].CurrentTex[TEXTURE_2D_INDEX];
s3vBindTexture( ctx, GL_TEXTURE_2D, texObj );
#endif
diff --git a/src/mesa/drivers/dri/s3v/s3v_xmesa.c b/src/mesa/drivers/dri/s3v/s3v_xmesa.c
index b18c8763c3..85f1481769 100644
--- a/src/mesa/drivers/dri/s3v/s3v_xmesa.c
+++ b/src/mesa/drivers/dri/s3v/s3v_xmesa.c
@@ -4,11 +4,12 @@
#include "s3v_context.h"
#include "s3v_vb.h"
+#include "s3v_dri.h"
#include "main/context.h"
#include "main/matrix.h"
-#include "s3v_dri.h"
#include "main/framebuffer.h"
#include "main/renderbuffer.h"
+#include "main/viewport.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
@@ -131,7 +132,7 @@ s3vCreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
s3vDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
static void
diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c
index a344aab71b..931ceff0a8 100644
--- a/src/mesa/drivers/dri/savage/savage_xmesa.c
+++ b/src/mesa/drivers/dri/savage/savage_xmesa.c
@@ -23,7 +23,6 @@
*/
-#include <X11/Xlibint.h>
#include <stdio.h>
#include "main/context.h"
@@ -59,9 +58,6 @@
#include "drirenderbuffer.h"
#include "texmem.h"
-#define need_GL_ARB_multisample
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
#define need_GL_EXT_secondary_color
#include "extension_helper.h"
@@ -133,10 +129,7 @@ struct timeval tv_s1,tv_f1;
static const struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_multitexture", NULL },
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_stencil_wrap", NULL },
{ "GL_EXT_texture_lod_bias", NULL },
{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
@@ -186,7 +179,7 @@ savageInitDriver(__DRIscreenPrivate *sPriv)
}
/* Allocate the private area */
- savageScreen = (savageScreenPrivate *)Xmalloc(sizeof(savageScreenPrivate));
+ savageScreen = (savageScreenPrivate *)_mesa_malloc(sizeof(savageScreenPrivate));
if (!savageScreen)
return GL_FALSE;
@@ -233,7 +226,7 @@ savageInitDriver(__DRIscreenPrivate *sPriv)
savageScreen->agpTextures.handle,
savageScreen->agpTextures.size,
(drmAddress *)&(savageScreen->agpTextures.map)) != 0) {
- Xfree(savageScreen);
+ _mesa_free(savageScreen);
sPriv->private = NULL;
return GL_FALSE;
}
@@ -253,7 +246,7 @@ savageInitDriver(__DRIscreenPrivate *sPriv)
savageScreen->aperture.size,
(drmAddress *)&savageScreen->aperture.map) != 0)
{
- Xfree(savageScreen);
+ _mesa_free(savageScreen);
sPriv->private = NULL;
return GL_FALSE;
}
@@ -289,7 +282,7 @@ savageDestroyScreen(__DRIscreenPrivate *sPriv)
/* free all option information */
driDestroyOptionInfo (&savageScreen->optionCache);
- Xfree(savageScreen);
+ _mesa_free(savageScreen);
sPriv->private = NULL;
}
@@ -307,7 +300,7 @@ savageCreateContext( const __GLcontextModes *mesaVis,
savageScreen->sarea_priv_offset);
int textureSize[SAVAGE_NR_TEX_HEAPS];
int i;
- imesa = (savageContextPtr)Xcalloc(sizeof(savageContext), 1);
+ imesa = (savageContextPtr)_mesa_calloc(sizeof(savageContext));
if (!imesa) {
return GL_FALSE;
}
@@ -324,7 +317,7 @@ savageCreateContext( const __GLcontextModes *mesaVis,
shareCtx = NULL;
ctx = _mesa_create_context(mesaVis, shareCtx, &functions, imesa);
if (!ctx) {
- Xfree(imesa);
+ _mesa_free(imesa);
return GL_FALSE;
}
driContextPriv->driverPrivate = imesa;
@@ -350,7 +343,9 @@ savageCreateContext( const __GLcontextModes *mesaVis,
ctx->Const.MaxLineWidthAA = 3.0;
ctx->Const.LineWidthGranularity = 1.0;
#endif
-
+
+ ctx->Const.MaxDrawBuffers = 1;
+
/* Dri stuff
*/
imesa->hHWContext = driContextPriv->hHWContext;
@@ -682,7 +677,7 @@ savageCreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
savageDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
#if 0
@@ -914,7 +909,7 @@ savageFillInModes( __DRIscreenPrivate *psp,
uint8_t depth_bits_array[2];
uint8_t stencil_bits_array[2];
-
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = depth_bits;
depth_bits_array[1] = depth_bits;
@@ -926,6 +921,8 @@ savageFillInModes( __DRIscreenPrivate *psp,
stencil_bits_array[0] = 0;
stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+ msaa_samples_array[0] = 0;
+
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
back_buffer_factor = (have_back_buffer) ? 2 : 1;
@@ -941,7 +938,8 @@ savageFillInModes( __DRIscreenPrivate *psp,
configs = driCreateConfigs(fb_format, fb_type,
depth_bits_array, stencil_bits_array,
depth_buffer_factor,
- back_buffer_modes, back_buffer_factor);
+ back_buffer_modes, back_buffer_factor,
+ msaa_samples_array, 1);
if (configs == NULL) {
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
__func__, __LINE__ );
diff --git a/src/mesa/drivers/dri/savage/savagecontext.h b/src/mesa/drivers/dri/savage/savagecontext.h
index fd6399d6a6..53a37db1cb 100644
--- a/src/mesa/drivers/dri/savage/savagecontext.h
+++ b/src/mesa/drivers/dri/savage/savagecontext.h
@@ -31,7 +31,6 @@ typedef struct savage_context_t savageContext;
typedef struct savage_context_t *savageContextPtr;
typedef struct savage_texture_object_t *savageTextureObjectPtr;
-#include <X11/Xlibint.h>
#include "dri_util.h"
#include "main/mtypes.h"
#include "xf86drm.h"
diff --git a/src/mesa/drivers/dri/savage/savagestate.c b/src/mesa/drivers/dri/savage/savagestate.c
index 73d85ed57b..84e1b52585 100644
--- a/src/mesa/drivers/dri/savage/savagestate.c
+++ b/src/mesa/drivers/dri/savage/savagestate.c
@@ -514,7 +514,7 @@ static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
imesa->regs.s4.zBufCtrl.ni.zBufEn = GL_TRUE;
}
- else if (imesa->glCtx->Stencil.Enabled && imesa->hw_stencil)
+ else if (imesa->glCtx->Stencil._Enabled && imesa->hw_stencil)
{
/* Need to keep Z on for Stencil. */
imesa->regs.s4.zBufCtrl.ni.zCmpFunc = CF_Always;
@@ -1092,7 +1092,7 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state);
else {
imesa->regs.s4.stencilCtrl.ni.stencilEn = state;
- if (ctx->Stencil.Enabled &&
+ if (ctx->Stencil._Enabled &&
imesa->regs.s4.zBufCtrl.ni.zBufEn != GL_TRUE)
{
/* Stencil buffer requires Z enabled. */
diff --git a/src/mesa/drivers/dri/savage/savagetex.c b/src/mesa/drivers/dri/savage/savagetex.c
index a3bebfa8cf..fe239e1b05 100644
--- a/src/mesa/drivers/dri/savage/savagetex.c
+++ b/src/mesa/drivers/dri/savage/savagetex.c
@@ -474,7 +474,7 @@ static void savageSetTexFilter(savageTexObjPtr t, GLenum minf, GLenum magf)
/* Need a fallback ?
*/
-static void savageSetTexBorderColor(savageTexObjPtr t, GLubyte color[4])
+static void savageSetTexBorderColor(savageTexObjPtr t, const GLfloat color[4])
{
/* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
/*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
@@ -512,7 +512,7 @@ savageAllocTexObj( struct gl_texture_object *texObj )
savageSetTexWrapping(t,texObj->WrapS,texObj->WrapT);
savageSetTexFilter(t,texObj->MinFilter,texObj->MagFilter);
- savageSetTexBorderColor(t,texObj->_BorderChan);
+ savageSetTexBorderColor(t,texObj->BorderColor);
}
return t;
@@ -2018,7 +2018,7 @@ static void savageTexParameter( GLcontext *ctx, GLenum target,
break;
case GL_TEXTURE_BORDER_COLOR:
- savageSetTexBorderColor(t,tObj->_BorderChan);
+ savageSetTexBorderColor(t,tObj->BorderColor);
break;
default:
diff --git a/src/mesa/drivers/dri/sis/sis_alloc.c b/src/mesa/drivers/dri/sis/sis_alloc.c
index 4ca4052803..ce34e44da2 100644
--- a/src/mesa/drivers/dri/sis/sis_alloc.c
+++ b/src/mesa/drivers/dri/sis/sis_alloc.c
@@ -137,7 +137,7 @@ sisAllocZStencilBuffer( sisContextPtr smesa )
{
int cpp = ( smesa->glCtx->Visual.depthBits +
smesa->glCtx->Visual.stencilBits ) / 8;
- unsigned char *addr;
+ char *addr;
smesa->depth.bpp = cpp * 8;
smesa->depth.pitch = ALIGNMENT(smesa->driDrawable->w * cpp, 4);
@@ -150,7 +150,7 @@ sisAllocZStencilBuffer( sisContextPtr smesa )
addr = (char *)ALIGNMENT((unsigned long)addr, Z_BUFFER_HW_ALIGNMENT);
smesa->depth.map = addr;
- smesa->depth.offset = addr - smesa->FbBase;
+ smesa->depth.offset = addr - (char *)smesa->FbBase;
/* stencil buffer is same as depth buffer */
smesa->stencil.size = smesa->depth.size;
@@ -173,7 +173,7 @@ void
sisAllocBackbuffer( sisContextPtr smesa )
{
int cpp = smesa->bytesPerPixel;
- unsigned char *addr;
+ char *addr;
smesa->back.bpp = smesa->bytesPerPixel * 8;
smesa->back.pitch = ALIGNMENT(smesa->driDrawable->w * cpp, 4);
@@ -186,7 +186,7 @@ sisAllocBackbuffer( sisContextPtr smesa )
addr = (char *)ALIGNMENT((unsigned long)addr, DRAW_BUFFER_HW_ALIGNMENT);
smesa->back.map = addr;
- smesa->back.offset = addr - smesa->FbBase;
+ smesa->back.offset = addr - (char *)smesa->FbBase;
}
void
diff --git a/src/mesa/drivers/dri/sis/sis_context.c b/src/mesa/drivers/dri/sis/sis_context.c
index 00d17da3ba..a070fe3d79 100644
--- a/src/mesa/drivers/dri/sis/sis_context.c
+++ b/src/mesa/drivers/dri/sis/sis_context.c
@@ -57,9 +57,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
-#define need_GL_ARB_multisample
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
#define need_GL_EXT_fog_coord
#define need_GL_EXT_secondary_color
#include "extension_helper.h"
@@ -74,12 +71,9 @@ int GlobalCmdQueueLen = 0;
struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_multitexture", NULL },
{ "GL_ARB_texture_border_clamp", NULL },
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
{ "GL_ARB_texture_mirrored_repeat", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
/*{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },*/
{ "GL_EXT_texture_lod_bias", NULL },
{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
@@ -91,9 +85,7 @@ struct dri_extension card_extensions[] =
struct dri_extension card_extensions_6326[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
/*{ "GL_ARB_texture_border_clamp", NULL },*/
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
/*{ "GL_ARB_texture_mirrored_repeat", NULL },*/
/*{ "GL_MESA_ycbcr_texture", NULL },*/
{ NULL, NULL }
diff --git a/src/mesa/drivers/dri/sis/sis_screen.c b/src/mesa/drivers/dri/sis/sis_screen.c
index b1a5d15236..b5f04ae28d 100644
--- a/src/mesa/drivers/dri/sis/sis_screen.c
+++ b/src/mesa/drivers/dri/sis/sis_screen.c
@@ -77,6 +77,7 @@ sisFillInModes(__DRIscreenPrivate *psp, int bpp)
};
uint8_t depth_bits_array[4];
uint8_t stencil_bits_array[4];
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = 0;
stencil_bits_array[0] = 0;
@@ -87,6 +88,8 @@ sisFillInModes(__DRIscreenPrivate *psp, int bpp)
depth_bits_array[3] = 32;
stencil_bits_array[3] = 0;
+ msaa_samples_array[0] = 0;
+
depth_buffer_factor = 4;
back_buffer_factor = 2;
@@ -100,7 +103,8 @@ sisFillInModes(__DRIscreenPrivate *psp, int bpp)
configs = driCreateConfigs(fb_format, fb_type, depth_bits_array,
stencil_bits_array, depth_buffer_factor,
- back_buffer_modes, back_buffer_factor);
+ back_buffer_modes, back_buffer_factor,
+ msaa_samples_array, 1);
if (configs == NULL) {
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, __LINE__);
return NULL;
@@ -217,7 +221,7 @@ sisCreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
sisDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
static void sisCopyBuffer( __DRIdrawablePrivate *dPriv )
diff --git a/src/mesa/drivers/dri/sis/sis_texstate.c b/src/mesa/drivers/dri/sis/sis_texstate.c
index 63f23fc014..46417ce414 100644
--- a/src/mesa/drivers/dri/sis/sis_texstate.c
+++ b/src/mesa/drivers/dri/sis/sis_texstate.c
@@ -456,11 +456,16 @@ sis_set_texobj_parm( GLcontext *ctx, struct gl_texture_object *texObj,
break;
}
- current->texture[hw_unit].hwTextureBorderColor =
- ((GLuint) texObj->_BorderChan[3] << 24) +
- ((GLuint) texObj->_BorderChan[0] << 16) +
- ((GLuint) texObj->_BorderChan[1] << 8) +
- ((GLuint) texObj->_BorderChan[2]);
+ {
+ GLubyte c[4];
+ CLAMPED_FLOAT_TO_UBYTE(c[0], texObj->BorderColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(c[1], texObj->BorderColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(c[2], texObj->BorderColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(c[3], texObj->BorderColor[3]);
+
+ current->texture[hw_unit].hwTextureBorderColor =
+ PACK_COLOR_8888(c[3], c[0], c[1], c[2]);
+ }
if (current->texture[hw_unit].hwTextureBorderColor !=
prev->texture[hw_unit].hwTextureBorderColor)
diff --git a/src/mesa/drivers/dri/sis/sis_tris.c b/src/mesa/drivers/dri/sis/sis_tris.c
index 095941aea2..76d12d07b3 100644
--- a/src/mesa/drivers/dri/sis/sis_tris.c
+++ b/src/mesa/drivers/dri/sis/sis_tris.c
@@ -994,7 +994,7 @@ sisFlushPrimsLocked(sisContextPtr smesa)
MMIO(REG_3D_PrimitiveSet, smesa->dwPrimitiveSet);
}
while (smesa->vb_last < smesa->vb_cur) {
- sis_emit_func(smesa, smesa->vb_last);
+ sis_emit_func(smesa, (char *)smesa->vb_last);
smesa->vb_last += incr;
}
mWait3DCmdQueue(1);
diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c
index 15b57244dc..3016987d56 100644
--- a/src/mesa/drivers/dri/swrast/swrast.c
+++ b/src/mesa/drivers/dri/swrast/swrast.c
@@ -62,8 +62,11 @@
#define need_GL_SGI_color_table
/* sw extensions not associated with some GL version */
+#define need_GL_ARB_draw_elements_base_vertex
#define need_GL_ARB_shader_objects
+#define need_GL_ARB_vertex_array_object
#define need_GL_ARB_vertex_program
+#define need_GL_ARB_sync
#define need_GL_APPLE_vertex_array_object
#define need_GL_ATI_fragment_shader
#define need_GL_ATI_separate_stencil
@@ -72,7 +75,7 @@
#define need_GL_EXT_framebuffer_blit
#define need_GL_EXT_gpu_program_parameters
#define need_GL_EXT_paletted_texture
-#define need_GL_IBM_multimode_draw_arrays
+#define need_GL_EXT_stencil_two_side
#define need_GL_MESA_resize_buffers
#define need_GL_NV_vertex_program
#define need_GL_NV_fragment_program
@@ -93,8 +96,12 @@ const struct dri_extension card_extensions[] =
{ "GL_EXT_histogram", GL_EXT_histogram_functions },
{ "GL_SGI_color_table", GL_SGI_color_table_functions },
+ { "GL_ARB_depth_clamp", NULL },
+ { "GL_ARB_draw_elements_base_vertex", GL_ARB_draw_elements_base_vertex_functions },
{ "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
+ { "GL_ARB_vertex_array_object", GL_ARB_vertex_array_object_functions },
{ "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
+ { "GL_ARB_sync", GL_ARB_sync_functions },
{ "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions },
{ "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions },
{ "GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions },
@@ -103,8 +110,9 @@ const struct dri_extension card_extensions[] =
{ "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
{ "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
{ "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
- { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
+ { "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions },
{ "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions },
+ { "GL_NV_depth_clamp", NULL },
{ "GL_NV_vertex_program", GL_NV_vertex_program_functions },
{ "GL_NV_fragment_program", GL_NV_fragment_program_functions },
{ NULL, NULL }
@@ -147,6 +155,7 @@ swrastFillInModes(__DRIscreen *psp,
uint8_t depth_bits_array[4];
uint8_t stencil_bits_array[4];
+ uint8_t msaa_samples_array[1];
depth_bits_array[0] = 0;
depth_bits_array[1] = 0;
@@ -161,26 +170,38 @@ swrastFillInModes(__DRIscreen *psp,
stencil_bits_array[2] = 0;
stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits;
+ msaa_samples_array[0] = 0;
+
depth_buffer_factor = 4;
back_buffer_factor = 2;
- if (pixel_bits == 8) {
+ switch (pixel_bits) {
+ case 8:
fb_format = GL_RGB;
fb_type = GL_UNSIGNED_BYTE_2_3_3_REV;
- }
- else if (pixel_bits == 16) {
+ break;
+ case 16:
fb_format = GL_RGB;
fb_type = GL_UNSIGNED_SHORT_5_6_5;
- }
- else {
+ break;
+ case 24:
+ fb_format = GL_BGR;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ case 32:
fb_format = GL_BGRA;
fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ default:
+ fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__,
+ pixel_bits);
+ return NULL;
}
configs = driCreateConfigs(fb_format, fb_type,
depth_bits_array, stencil_bits_array,
depth_buffer_factor, back_buffer_modes,
- back_buffer_factor);
+ back_buffer_factor, msaa_samples_array, 1);
if (configs == NULL) {
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
__LINE__);
@@ -196,7 +217,7 @@ driCreateNewScreen(int scrn, const __DRIextension **extensions,
{
static const __DRIextension *emptyExtensionList[] = { NULL };
__DRIscreen *psp;
- __DRIconfig **configs8, **configs16, **configs32;
+ __DRIconfig **configs8, **configs16, **configs24, **configs32;
(void) data;
@@ -213,11 +234,13 @@ driCreateNewScreen(int scrn, const __DRIextension **extensions,
configs8 = swrastFillInModes(psp, 8, 8, 0, 1);
configs16 = swrastFillInModes(psp, 16, 16, 0, 1);
+ configs24 = swrastFillInModes(psp, 24, 24, 8, 1);
configs32 = swrastFillInModes(psp, 32, 24, 8, 1);
- configs16 = (__DRIconfig **)driConcatConfigs(configs8, configs16);
-
- *driver_configs = driConcatConfigs(configs16, configs32);
+ configs16 = driConcatConfigs(configs8, configs16);
+ configs24 = driConcatConfigs(configs16, configs24);
+ *driver_configs = (const __DRIconfig **)
+ driConcatConfigs(configs24, configs32);
driInitExtensions( NULL, card_extensions, GL_FALSE );
@@ -249,19 +272,24 @@ static GLuint
choose_pixel_format(const GLvisual *v)
{
if (v->rgbMode) {
- int bpp = v->rgbBits;
+ int depth = v->rgbBits;
- if (bpp == 32
+ if (depth == 32
&& v->redMask == 0xff0000
&& v->greenMask == 0x00ff00
&& v->blueMask == 0x0000ff)
return PF_A8R8G8B8;
- else if (bpp == 16
+ else if (depth == 24
+ && v->redMask == 0xff0000
+ && v->greenMask == 0x00ff00
+ && v->blueMask == 0x0000ff)
+ return PF_X8R8G8B8;
+ else if (depth == 16
&& v->redMask == 0xf800
&& v->greenMask == 0x07e0
&& v->blueMask == 0x001f)
return PF_R5G6B5;
- else if (bpp == 8
+ else if (depth == 8
&& v->redMask == 0x07
&& v->greenMask == 0x38
&& v->blueMask == 0xc0)
@@ -290,7 +318,6 @@ swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
{
struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
- int bpp;
unsigned mask = PITCH_ALIGN_BITS - 1;
TRACE;
@@ -299,23 +326,8 @@ swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
rb->Width = width;
rb->Height = height;
- switch (internalFormat) {
- case GL_RGB:
- bpp = rb->RedBits + rb->GreenBits + rb->BlueBits;
- break;
- case GL_RGBA:
- bpp = rb->RedBits + rb->GreenBits + rb->BlueBits + rb->AlphaBits;
- break;
- case GL_COLOR_INDEX8_EXT:
- bpp = rb->IndexBits;
- break;
- default:
- _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
- return GL_FALSE;
- }
-
/* always pad to PITCH_ALIGN_BITS */
- xrb->pitch = ((width * bpp + mask) & ~mask) / 8;
+ xrb->pitch = ((width * xrb->bpp + mask) & ~mask) / 8;
return GL_TRUE;
}
@@ -371,6 +383,17 @@ swrast_new_renderbuffer(const GLvisual *visual, GLboolean front)
xrb->Base.GreenBits = 8 * sizeof(GLubyte);
xrb->Base.BlueBits = 8 * sizeof(GLubyte);
xrb->Base.AlphaBits = 8 * sizeof(GLubyte);
+ xrb->bpp = 32;
+ break;
+ case PF_X8R8G8B8:
+ xrb->Base.InternalFormat = GL_RGB;
+ xrb->Base._BaseFormat = GL_RGB;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->Base.RedBits = 8 * sizeof(GLubyte);
+ xrb->Base.GreenBits = 8 * sizeof(GLubyte);
+ xrb->Base.BlueBits = 8 * sizeof(GLubyte);
+ xrb->Base.AlphaBits = 0;
+ xrb->bpp = 32;
break;
case PF_R5G6B5:
xrb->Base.InternalFormat = GL_RGB;
@@ -380,6 +403,7 @@ swrast_new_renderbuffer(const GLvisual *visual, GLboolean front)
xrb->Base.GreenBits = 6 * sizeof(GLubyte);
xrb->Base.BlueBits = 5 * sizeof(GLubyte);
xrb->Base.AlphaBits = 0;
+ xrb->bpp = 16;
break;
case PF_R3G3B2:
xrb->Base.InternalFormat = GL_RGB;
@@ -389,12 +413,14 @@ swrast_new_renderbuffer(const GLvisual *visual, GLboolean front)
xrb->Base.GreenBits = 3 * sizeof(GLubyte);
xrb->Base.BlueBits = 2 * sizeof(GLubyte);
xrb->Base.AlphaBits = 0;
+ xrb->bpp = 8;
break;
case PF_CI8:
xrb->Base.InternalFormat = GL_COLOR_INDEX8_EXT;
xrb->Base._BaseFormat = GL_COLOR_INDEX;
xrb->Base.DataType = GL_UNSIGNED_BYTE;
xrb->Base.IndexBits = 8 * sizeof(GLubyte);
+ xrb->bpp = 8;
break;
default:
return NULL;
@@ -458,7 +484,7 @@ driDestroyDrawable(__DRIdrawable *buf)
_mesa_free(buf->row);
fb->DeletePending = GL_TRUE;
- _mesa_unreference_framebuffer(&fb);
+ _mesa_reference_framebuffer(&fb, NULL);
}
}
diff --git a/src/mesa/drivers/dri/swrast/swrast_priv.h b/src/mesa/drivers/dri/swrast/swrast_priv.h
index a707ffc40a..1a5fb31d5a 100644
--- a/src/mesa/drivers/dri/swrast/swrast_priv.h
+++ b/src/mesa/drivers/dri/swrast/swrast_priv.h
@@ -90,6 +90,8 @@ struct swrast_renderbuffer {
/* renderbuffer pitch (in bytes) */
GLuint pitch;
+ /* bits per pixel of storage */
+ GLuint bpp;
};
static INLINE __DRIcontext *
@@ -115,10 +117,10 @@ swrast_renderbuffer(struct gl_renderbuffer *rb)
* Pixel formats we support
*/
#define PF_CI8 1 /**< Color Index mode */
-#define PF_A8R8G8B8 2 /**< 32-bit TrueColor: 8-A, 8-R, 8-G, 8-B bits */
-#define PF_R5G6B5 3 /**< 16-bit TrueColor: 5-R, 6-G, 5-B bits */
-#define PF_R3G3B2 4 /**< 8-bit TrueColor: 3-R, 3-G, 2-B bits */
-
+#define PF_A8R8G8B8 2 /**< 32bpp TrueColor: 8-A, 8-R, 8-G, 8-B bits */
+#define PF_R5G6B5 3 /**< 16bpp TrueColor: 5-R, 6-G, 5-B bits */
+#define PF_R3G3B2 4 /**< 8bpp TrueColor: 3-R, 3-G, 2-B bits */
+#define PF_X8R8G8B8 5 /**< 32bpp TrueColor: 8-R, 8-G, 8-B bits */
/**
* Renderbuffer pitch alignment (in bits).
diff --git a/src/mesa/drivers/dri/swrast/swrast_span.c b/src/mesa/drivers/dri/swrast/swrast_span.c
index 5e990368b2..2d3c25dcbe 100644
--- a/src/mesa/drivers/dri/swrast/swrast_span.c
+++ b/src/mesa/drivers/dri/swrast/swrast_span.c
@@ -79,6 +79,24 @@ static const GLubyte kernel[16] = {
DST[BCOMP] = SRC[0]
+/* 32-bit BGRX */
+#define STORE_PIXEL_X8R8G8B8(DST, X, Y, VALUE) \
+ DST[3] = 0xff; \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]
+#define STORE_PIXEL_RGB_X8R8G8B8(DST, X, Y, VALUE) \
+ DST[3] = 0xff; \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]
+#define FETCH_PIXEL_X8R8G8B8(DST, SRC) \
+ DST[ACOMP] = 0xff; \
+ DST[RCOMP] = SRC[2]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[0]
+
+
/* 16-bit BGR */
#define STORE_PIXEL_R5G6B5(DST, X, Y, VALUE) \
do { \
@@ -139,6 +157,24 @@ static const GLubyte kernel[16] = {
#include "swrast/s_spantemp.h"
+/* 32-bit BGRX */
+#define NAME(FUNC) FUNC##_X8R8G8B8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch + (X) * 4;
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_X8R8G8B8(DST, X, Y, VALUE)
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ STORE_PIXEL_RGB_X8R8G8B8(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_X8R8G8B8(DST, SRC)
+
+#include "swrast/s_spantemp.h"
+
+
/* 16-bit BGR */
#define NAME(FUNC) FUNC##_R5G6B5
#define RB_TYPE GLubyte
@@ -210,6 +246,24 @@ static const GLubyte kernel[16] = {
#include "swrast_spantemp.h"
+/* 32-bit BGRX */
+#define NAME(FUNC) FUNC##_X8R8G8B8_front
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)row;
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_X8R8G8B8(DST, X, Y, VALUE)
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ STORE_PIXEL_RGB_X8R8G8B8(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_X8R8G8B8(DST, SRC)
+
+#include "swrast_spantemp.h"
+
+
/* 16-bit BGR */
#define NAME(FUNC) FUNC##_R5G6B5_front
#define RB_TYPE GLubyte
@@ -279,6 +333,15 @@ swrast_set_span_funcs_back(struct swrast_renderbuffer *xrb,
xrb->Base.PutValues = put_values_A8R8G8B8;
xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8;
break;
+ case PF_X8R8G8B8:
+ xrb->Base.GetRow = get_row_X8R8G8B8;
+ xrb->Base.GetValues = get_values_X8R8G8B8;
+ xrb->Base.PutRow = put_row_X8R8G8B8;
+ xrb->Base.PutRowRGB = put_row_rgb_X8R8G8B8;
+ xrb->Base.PutMonoRow = put_mono_row_X8R8G8B8;
+ xrb->Base.PutValues = put_values_X8R8G8B8;
+ xrb->Base.PutMonoValues = put_mono_values_X8R8G8B8;
+ break;
case PF_R5G6B5:
xrb->Base.GetRow = get_row_R5G6B5;
xrb->Base.GetValues = get_values_R5G6B5;
@@ -334,6 +397,15 @@ swrast_set_span_funcs_front(struct swrast_renderbuffer *xrb,
xrb->Base.PutValues = put_values_A8R8G8B8_front;
xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8_front;
break;
+ case PF_X8R8G8B8:
+ xrb->Base.GetRow = get_row_X8R8G8B8_front;
+ xrb->Base.GetValues = get_values_X8R8G8B8_front;
+ xrb->Base.PutRow = put_row_X8R8G8B8_front;
+ xrb->Base.PutRowRGB = put_row_rgb_X8R8G8B8_front;
+ xrb->Base.PutMonoRow = put_mono_row_X8R8G8B8_front;
+ xrb->Base.PutValues = put_values_X8R8G8B8_front;
+ xrb->Base.PutMonoValues = put_mono_values_X8R8G8B8_front;
+ break;
case PF_R5G6B5:
xrb->Base.GetRow = get_row_R5G6B5_front;
xrb->Base.GetValues = get_values_R5G6B5_front;
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_context.c b/src/mesa/drivers/dri/tdfx/tdfx_context.c
index ef688d103d..68b5027561 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_context.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_context.c
@@ -58,21 +58,15 @@
#include "utils.h"
-#define need_GL_ARB_multisample
/* #define need_GL_ARB_point_parameters */
#define need_GL_ARB_occlusion_query
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_vertex_buffer_object
/* #define need_GL_ARB_vertex_program */
#define need_GL_EXT_blend_equation_separate
#define need_GL_EXT_blend_func_separate
#define need_GL_EXT_blend_minmax
#define need_GL_EXT_fog_coord
-#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_paletted_texture
/* #define need_GL_EXT_secondary_color */
-#define need_GL_IBM_multimode_draw_arrays
-/* #define need_GL_MESA_program_debug */
/* #define need_GL_NV_vertex_program */
#include "extension_helper.h"
@@ -82,20 +76,16 @@
*/
const struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions },
{ "GL_ARB_texture_mirrored_repeat", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions },
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
- { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
{ "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
{ "GL_EXT_shared_texture_palette", NULL },
{ "GL_EXT_stencil_wrap", NULL },
{ "GL_EXT_texture_env_add", NULL },
{ "GL_EXT_texture_lod_bias", NULL },
- { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
#ifdef need_GL_ARB_point_parameters
{ "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
@@ -111,9 +101,6 @@ const struct dri_extension card_extensions[] =
{ "GL_NV_vertex_program", GL_NV_vertex_program_functions }
{ "GL_NV_vertex_program1_1", NULL },
#endif
-#ifdef need_GL_MESA_program_debug
- { "GL_MESA_program_debug", GL_MESA_program_debug_functions },
-#endif
{ NULL, NULL }
};
@@ -122,7 +109,6 @@ const struct dri_extension card_extensions[] =
*/
const struct dri_extension napalm_extensions[] =
{
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
{ "GL_ARB_texture_env_combine", NULL },
{ "GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions },
{ "GL_EXT_blend_subtract", GL_EXT_blend_minmax_functions },
@@ -319,6 +305,8 @@ GLboolean tdfxCreateContext( const __GLcontextModes *mesaVis,
ctx->Const.MaxLineWidthAA = 1.0;
ctx->Const.LineWidthGranularity = 1.0;
+ ctx->Const.MaxDrawBuffers = 1;
+
/* Initialize the software rasterizer and helper modules.
*/
_swrast_CreateContext( ctx );
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_dd.c b/src/mesa/drivers/dri/tdfx/tdfx_dd.c
index 2cef079515..8472df607a 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_dd.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_dd.c
@@ -110,13 +110,13 @@ static const GLubyte *tdfxDDGetString( GLcontext *ctx, GLenum name )
static void
-tdfxBeginQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q)
+tdfxBeginQuery(GLcontext *ctx, struct gl_query_object *q)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
(void) q;
- if (target == GL_SAMPLES_PASSED_ARB) {
+ if (q->Target == GL_SAMPLES_PASSED_ARB) {
LOCK_HARDWARE(fxMesa);
fxMesa->Glide.grFinish();
fxMesa->Glide.grReset(GR_STATS_PIXELS);
@@ -126,14 +126,14 @@ tdfxBeginQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q)
static void
-tdfxEndQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q)
+tdfxEndQuery(GLcontext *ctx, struct gl_query_object *q)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
FxI32 total_pixels;
FxI32 z_fail_pixels;
- if (target == GL_SAMPLES_PASSED_ARB) {
+ if (q->Target == GL_SAMPLES_PASSED_ARB) {
LOCK_HARDWARE(fxMesa);
fxMesa->Glide.grFinish();
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_pixels.c b/src/mesa/drivers/dri/tdfx/tdfx_pixels.c
index 9ab9c05f2b..18729d5ae0 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_pixels.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_pixels.c
@@ -610,7 +610,7 @@ tdfx_drawpixels_R8G8B8A8(GLcontext * ctx, GLint x, GLint y,
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
- ctx->Stencil.Enabled ||
+ ctx->Stencil._Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_render.c b/src/mesa/drivers/dri/tdfx/tdfx_render.c
index cf840c57a7..2cd8e12d95 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_render.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_render.c
@@ -740,7 +740,7 @@ void tdfxEmitHwStateLocked( tdfxContextPtr fxMesa )
}
if ( fxMesa->dirty & TDFX_UPLOAD_STENCIL ) {
- if (fxMesa->glCtx->Stencil.Enabled) {
+ if (fxMesa->glCtx->Stencil._Enabled) {
fxMesa->Glide.grEnable(GR_STENCIL_MODE_EXT);
fxMesa->Glide.grStencilOp(fxMesa->Stencil.FailFunc,
fxMesa->Stencil.ZFailFunc,
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_screen.c b/src/mesa/drivers/dri/tdfx/tdfx_screen.c
index cd22b84951..58bd48b294 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_screen.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_screen.c
@@ -232,7 +232,7 @@ tdfxCreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
tdfxDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
@@ -361,6 +361,7 @@ tdfxFillInModes(__DRIscreenPrivate *psp,
static const GLenum db_modes[2] = { GLX_NONE, GLX_SWAP_UNDEFINED_OML };
uint8_t depth_bits_array[4];
uint8_t stencil_bits_array[4];
+ uint8_t msaa_samples_array[1];
if(deep) {
depth_bits_array[0] = 0;
depth_bits_array[1] = 24;
@@ -377,13 +378,17 @@ tdfxFillInModes(__DRIscreenPrivate *psp,
stencil_bits_array[3] = 8;
}
- return driCreateConfigs(
- deep ? GL_RGBA : GL_RGB,
- deep ? GL_UNSIGNED_INT_8_8_8_8 : GL_UNSIGNED_SHORT_5_6_5,
- depth_bits_array,
- stencil_bits_array,
- deep ? 2 : 4,
- db_modes, 2);
+ msaa_samples_array[0] = 0;
+
+ return (const __DRIconfig **)
+ driCreateConfigs(deep ? GL_RGBA : GL_RGB,
+ deep ? GL_UNSIGNED_INT_8_8_8_8 :
+ GL_UNSIGNED_SHORT_5_6_5,
+ depth_bits_array,
+ stencil_bits_array,
+ deep ? 2 : 4,
+ db_modes, 2,
+ msaa_samples_array, 1);
}
/**
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_state.c b/src/mesa/drivers/dri/tdfx/tdfx_state.c
index a2d7bcd97d..591df8a905 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_state.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_state.c
@@ -459,7 +459,7 @@ static void tdfxUpdateStencil( GLcontext *ctx )
}
if (fxMesa->haveHwStencil) {
- if (ctx->Stencil.Enabled) {
+ if (ctx->Stencil._Enabled) {
fxMesa->Stencil.Function = ctx->Stencil.Function[0] - GL_NEVER + GR_CMP_NEVER;
fxMesa->Stencil.RefValue = ctx->Stencil.Ref[0] & 0xff;
fxMesa->Stencil.ValueMask = ctx->Stencil.ValueMask[0] & 0xff;
diff --git a/src/mesa/drivers/dri/trident/trident_context.c b/src/mesa/drivers/dri/trident/trident_context.c
index e134cfcf8e..b5126b07ea 100644
--- a/src/mesa/drivers/dri/trident/trident_context.c
+++ b/src/mesa/drivers/dri/trident/trident_context.c
@@ -41,6 +41,7 @@
#include "main/extensions.h"
#include "main/framebuffer.h"
#include "main/renderbuffer.h"
+#include "main/viewport.h"
#if defined(USE_X86_ASM)
#include "x86/common_x86_asm.h"
#endif
@@ -128,6 +129,8 @@ tridentCreateContext( const __GLcontextModes *glVisual,
ctx->Const.MaxPointSizeAA = 16.0;
ctx->Const.PointSizeGranularity = 0.25;
+ ctx->Const.MaxDrawBuffers = 1;
+
#if 0
tmesa->texHeap = mmInit( 0, tmesa->tridentScreen->textureSize );
@@ -279,7 +282,7 @@ tridentCreateBuffer( __DRIscreenPrivate *driScrnPriv,
static void
tridentDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
static void
diff --git a/src/mesa/drivers/dri/trident/trident_vb.c b/src/mesa/drivers/dri/trident/trident_vb.c
index b231f5ef15..055a914595 100644
--- a/src/mesa/drivers/dri/trident/trident_vb.c
+++ b/src/mesa/drivers/dri/trident/trident_vb.c
@@ -402,7 +402,7 @@ void tridentInitVB( GLcontext *ctx )
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
GLuint size = TNL_CONTEXT(ctx)->vb.Size;
- tmesa->verts = (char *)ALIGN_MALLOC( size * 16 * 4, 32 );
+ tmesa->verts = (GLubyte *)ALIGN_MALLOC( size * 16 * 4, 32 );
{
static int firsttime = 1;
diff --git a/src/mesa/drivers/dri/unichrome/via_context.c b/src/mesa/drivers/dri/unichrome/via_context.c
index f5bdb65eb0..6eb19ac079 100644
--- a/src/mesa/drivers/dri/unichrome/via_context.c
+++ b/src/mesa/drivers/dri/unichrome/via_context.c
@@ -62,9 +62,7 @@
#include "main/macros.h"
#include "drirenderbuffer.h"
-#define need_GL_ARB_multisample
#define need_GL_ARB_point_parameters
-#define need_GL_ARB_vertex_buffer_object
#define need_GL_EXT_fog_coord
#define need_GL_EXT_secondary_color
#include "extension_helper.h"
@@ -366,14 +364,12 @@ void viaReAllocateBuffers(GLcontext *ctx, GLframebuffer *drawbuffer,
*/
const struct dri_extension card_extensions[] =
{
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
{ "GL_ARB_multitexture", NULL },
{ "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
{ "GL_ARB_texture_env_add", NULL },
{ "GL_ARB_texture_env_combine", NULL },
/* { "GL_ARB_texture_env_dot3", NULL }, */
{ "GL_ARB_texture_mirrored_repeat", NULL },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
{ "GL_EXT_stencil_wrap", NULL },
@@ -577,6 +573,8 @@ viaCreateContext(const __GLcontextModes *visual,
ctx->Const.MaxPointSizeAA = 1.0;
ctx->Const.PointSizeGranularity = 1.0;
+ ctx->Const.MaxDrawBuffers = 1;
+
ctx->Driver.GetString = viaGetString;
ctx->DriverCtx = (void *)vmesa;
diff --git a/src/mesa/drivers/dri/unichrome/via_screen.c b/src/mesa/drivers/dri/unichrome/via_screen.c
index 988f9935ac..3dbb570571 100644
--- a/src/mesa/drivers/dri/unichrome/via_screen.c
+++ b/src/mesa/drivers/dri/unichrome/via_screen.c
@@ -316,7 +316,7 @@ viaCreateBuffer(__DRIscreenPrivate *driScrnPriv,
static void
viaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
static const __DRIconfig **
@@ -342,6 +342,7 @@ viaFillInModes( __DRIscreenPrivate *psp,
*/
static const uint8_t depth_bits_array[4] = { 0, 16, 24, 32 };
static const uint8_t stencil_bits_array[4] = { 0, 0, 8, 0 };
+ uint8_t msaa_samples_array[1] = { 0 };
const unsigned depth_buffer_factor = 3;
if ( pixel_bits == 16 ) {
@@ -356,7 +357,8 @@ viaFillInModes( __DRIscreenPrivate *psp,
configs = driCreateConfigs(fb_format, fb_type,
depth_bits_array, stencil_bits_array,
depth_buffer_factor, back_buffer_modes,
- back_buffer_factor);
+ back_buffer_factor,
+ msaa_samples_array, 1);
if (configs == NULL) {
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
__LINE__);
diff --git a/src/mesa/drivers/dri/unichrome/via_state.c b/src/mesa/drivers/dri/unichrome/via_state.c
index 1cef01ab03..840e4e42da 100644
--- a/src/mesa/drivers/dri/unichrome/via_state.c
+++ b/src/mesa/drivers/dri/unichrome/via_state.c
@@ -1342,7 +1342,7 @@ static void viaChooseStencilState(GLcontext *ctx)
{
struct via_context *vmesa = VIA_CONTEXT(ctx);
- if (ctx->Stencil.Enabled) {
+ if (ctx->Stencil._Enabled) {
GLuint temp;
vmesa->regEnable |= HC_HenST_MASK;
diff --git a/src/mesa/drivers/fbdev/glfbdev.c b/src/mesa/drivers/fbdev/glfbdev.c
index 3c874ba57a..531558dc4d 100644
--- a/src/mesa/drivers/fbdev/glfbdev.c
+++ b/src/mesa/drivers/fbdev/glfbdev.c
@@ -685,7 +685,7 @@ glFBDevDestroyBuffer( GLFBDevBufferPtr buffer )
}
{
struct gl_framebuffer *fb = &buffer->glframebuffer;
- _mesa_unreference_framebuffer(&fb);
+ _mesa_reference_framebuffer(&fb, NULL);
}
}
}
diff --git a/src/mesa/drivers/ggi/default/stubs.c b/src/mesa/drivers/ggi/default/stubs.c
index 7b442b6d20..62722972b2 100644
--- a/src/mesa/drivers/ggi/default/stubs.c
+++ b/src/mesa/drivers/ggi/default/stubs.c
@@ -472,7 +472,7 @@ static void GGItriangle_flat_depth(GLcontext *ctx, const SWvertex *v0, const SWv
static swrast_tri_func ggimesa_stubs_get_triangle_func(GLcontext *ctx)
{
- if (ctx->Stencil.Enabled) return NULL;
+ if (ctx->Stencil._Enabled) return NULL;
if (ctx->Polygon.SmoothFlag) return NULL;
if (ctx->Polygon.StippleFlag) return NULL;
if (ctx->Texture._ReallyEnabled) return NULL;
diff --git a/src/mesa/drivers/glide/fxapi.c b/src/mesa/drivers/glide/fxapi.c
index b7708fd636..238f491599 100644
--- a/src/mesa/drivers/glide/fxapi.c
+++ b/src/mesa/drivers/glide/fxapi.c
@@ -728,7 +728,7 @@ errorhandler:
FREE(fxMesa->fogTable);
}
if (fxMesa->glBuffer) {
- _mesa_unreference_framebuffer(&fxMesa->glBuffer);
+ _mesa_reference_framebuffer(&fxMesa->glBuffer, NULL);
}
if (fxMesa->glVis) {
_mesa_destroy_visual(fxMesa->glVis);
@@ -828,7 +828,7 @@ fxMesaDestroyContext(fxMesaContext fxMesa)
fxDDDestroyFxMesaContext(fxMesa); /* must be before _mesa_destroy_context */
_mesa_destroy_visual(fxMesa->glVis);
_mesa_destroy_context(fxMesa->glCtx);
- _mesa_unreference_framebuffer(&fxMesa->glBuffer);
+ _mesa_reference_framebuffer(&fxMesa->glBuffer, NULL);
fxTMClose(fxMesa); /* must be after _mesa_destroy_context */
FREE(fxMesa);
diff --git a/src/mesa/drivers/glide/fxdd.c b/src/mesa/drivers/glide/fxdd.c
index 213ef2382f..2bc60399ea 100644
--- a/src/mesa/drivers/glide/fxdd.c
+++ b/src/mesa/drivers/glide/fxdd.c
@@ -1773,6 +1773,8 @@ fxDDInitFxMesaContext(fxMesaContext fxMesa)
ctx->Const.MaxTextureImageUnits = fxMesa->haveTwoTMUs ? 2 : 1;
ctx->Const.MaxTextureUnits = MAX2(ctx->Const.MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits);
+ ctx->Const.MaxDrawBuffers = 1;
+
fxMesa->new_state = _NEW_ALL;
if (!fxMesa->haveHwStencil) {
/* don't touch stencil if there is none */
@@ -1862,7 +1864,6 @@ fxDDInitExtensions(GLcontext * ctx)
}
if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
- _mesa_enable_extension(ctx, "GL_ARB_texture_compression");
_mesa_enable_extension(ctx, "GL_3DFX_texture_compression_FXT1");
_mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
_mesa_enable_extension(ctx, "GL_S3_s3tc");
@@ -1894,7 +1895,6 @@ fxDDInitExtensions(GLcontext * ctx)
* fxSetupSingleTMU_NoLock/fxSetupDoubleTMU_NoLock:
* grTexDownloadTable(GR_TEXTABLE_NCC0, &(ti->palette));
*/
- /*_mesa_enable_extension(ctx, "GL_ARB_texture_compression");*/
_mesa_enable_extension(ctx, "GL_SGIS_generate_mipmap");
}
@@ -1917,15 +1917,11 @@ fxDDInitExtensions(GLcontext * ctx)
}
/* core-level extensions */
- _mesa_enable_extension(ctx, "GL_EXT_multi_draw_arrays");
- _mesa_enable_extension(ctx, "GL_IBM_multimode_draw_arrays");
- _mesa_enable_extension(ctx, "GL_ARB_vertex_buffer_object");
/* dangerous */
if (getenv("MESA_FX_ALLOW_VP")) {
_mesa_enable_extension(ctx, "GL_ARB_vertex_program");
_mesa_enable_extension(ctx, "GL_NV_vertex_program");
_mesa_enable_extension(ctx, "GL_NV_vertex_program1_1");
- _mesa_enable_extension(ctx, "GL_MESA_program_debug");
}
#if 0
/* this requires _tnl_vertex_cull_stage in the pipeline */
@@ -1951,7 +1947,7 @@ fx_check_IsInHardware(GLcontext * ctx)
return FX_FALLBACK_RENDER_MODE;
}
- if (ctx->Stencil.Enabled && !fxMesa->haveHwStencil) {
+ if (ctx->Stencil._Enabled && !fxMesa->haveHwStencil) {
return FX_FALLBACK_STENCIL;
}
diff --git a/src/mesa/drivers/glslcompiler/glslcompiler.c b/src/mesa/drivers/glslcompiler/glslcompiler.c
index 34cce977c8..e4527abdec 100644
--- a/src/mesa/drivers/glslcompiler/glslcompiler.c
+++ b/src/mesa/drivers/glslcompiler/glslcompiler.c
@@ -72,6 +72,8 @@ struct options {
const char *VertFile;
const char *FragFile;
const char *OutputFile;
+ GLboolean Params;
+ struct gl_sl_pragmas Pragmas;
};
static struct options Options;
@@ -147,6 +149,9 @@ CreateContext(void)
TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
_swsetup_Wakeup( ctx );
+ /* Override the context's default pragma settings */
+ ctx->Shader.DefaultPragmas = Options.Pragmas;
+
_mesa_make_current(ctx, buf, buf);
return GL_TRUE;
@@ -227,7 +232,9 @@ PrintShaderInstructions(GLuint shader, FILE *f)
GET_CURRENT_CONTEXT(ctx);
struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
struct gl_program *prog = sh->Program;
- _mesa_print_program_opt(prog, Options.Mode, Options.LineNumbers);
+ _mesa_fprint_program_opt(stdout, prog, Options.Mode, Options.LineNumbers);
+ if (Options.Params)
+ _mesa_print_program_parameters(ctx, prog);
}
@@ -253,11 +260,15 @@ Usage(void)
printf("Usage:\n");
printf(" --vs FILE vertex shader input filename\n");
printf(" --fs FILE fragment shader input filename\n");
- printf(" --arb emit ARB-style instructions (the default)\n");
+ printf(" --arb emit ARB-style instructions\n");
printf(" --nv emit NV-style instructions\n");
- printf(" --debug emit debug-style instructions\n");
- printf(" --number, -n emit line numbers\n");
+ printf(" --debug force #pragma debug(on)\n");
+ printf(" --nodebug force #pragma debug(off)\n");
+ printf(" --opt force #pragma optimize(on)\n");
+ printf(" --noopt force #pragma optimize(off)\n");
+ printf(" --number, -n emit line numbers (if --arb or --nv)\n");
printf(" --output, -o FILE output filename\n");
+ printf(" --params also emit program parameter info\n");
printf(" --help display this information\n");
}
@@ -268,10 +279,15 @@ ParseOptions(int argc, char *argv[])
int i;
Options.LineNumbers = GL_FALSE;
- Options.Mode = PROG_PRINT_ARB;
+ Options.Mode = PROG_PRINT_DEBUG;
Options.VertFile = NULL;
Options.FragFile = NULL;
Options.OutputFile = NULL;
+ Options.Params = GL_FALSE;
+ Options.Pragmas.IgnoreOptimize = GL_FALSE;
+ Options.Pragmas.IgnoreDebug = GL_FALSE;
+ Options.Pragmas.Debug = GL_FALSE;
+ Options.Pragmas.Optimize = GL_TRUE;
if (argc == 1) {
Usage();
@@ -294,7 +310,20 @@ ParseOptions(int argc, char *argv[])
Options.Mode = PROG_PRINT_NV;
}
else if (strcmp(argv[i], "--debug") == 0) {
- Options.Mode = PROG_PRINT_DEBUG;
+ Options.Pragmas.IgnoreDebug = GL_TRUE;
+ Options.Pragmas.Debug = GL_TRUE;
+ }
+ else if (strcmp(argv[i], "--nodebug") == 0) {
+ Options.Pragmas.IgnoreDebug = GL_TRUE;
+ Options.Pragmas.Debug = GL_FALSE;
+ }
+ else if (strcmp(argv[i], "--opt") == 0) {
+ Options.Pragmas.IgnoreOptimize = GL_TRUE;
+ Options.Pragmas.Optimize = GL_TRUE;
+ }
+ else if (strcmp(argv[i], "--noopt") == 0) {
+ Options.Pragmas.IgnoreOptimize = GL_TRUE;
+ Options.Pragmas.Optimize = GL_FALSE;
}
else if (strcmp(argv[i], "--number") == 0 ||
strcmp(argv[i], "-n") == 0) {
@@ -305,6 +334,9 @@ ParseOptions(int argc, char *argv[])
Options.OutputFile = argv[i + 1];
i++;
}
+ else if (strcmp(argv[i], "--params") == 0) {
+ Options.Params = GL_TRUE;
+ }
else if (strcmp(argv[i], "--help") == 0) {
Usage();
exit(0);
@@ -315,6 +347,11 @@ ParseOptions(int argc, char *argv[])
exit(1);
}
}
+
+ if (Options.Mode == PROG_PRINT_DEBUG) {
+ /* always print line numbers when emitting debug-style output */
+ Options.LineNumbers = GL_TRUE;
+ }
}
@@ -323,13 +360,13 @@ main(int argc, char *argv[])
{
GLuint shader = 0;
+ ParseOptions(argc, argv);
+
if (!CreateContext()) {
fprintf(stderr, "%s: Failed to create compiler context\n", Prog);
exit(1);
}
- ParseOptions(argc, argv);
-
if (Options.VertFile) {
shader = CompileShader(Options.VertFile, GL_VERTEX_SHADER);
}
diff --git a/src/mesa/drivers/osmesa/Makefile b/src/mesa/drivers/osmesa/Makefile
index 3b3984200a..92d4149466 100644
--- a/src/mesa/drivers/osmesa/Makefile
+++ b/src/mesa/drivers/osmesa/Makefile
@@ -19,11 +19,12 @@ INCLUDE_DIRS = \
-I$(TOP)/src/mesa \
-I$(TOP)/src/mesa/main
+# Standalone osmesa needs to be linked with core Mesa APIs
+ifeq ($(DRIVER_DIRS), osmesa)
CORE_MESA = $(TOP)/src/mesa/libmesa.a $(TOP)/src/mesa/libglapi.a
-
-
-.PHONY: osmesa8
-.PHONY: osmesa16
+else
+CORE_MESA =
+endif
.c.o:
@@ -31,31 +32,12 @@ CORE_MESA = $(TOP)/src/mesa/libmesa.a $(TOP)/src/mesa/libglapi.a
default: $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME)
- @ if [ "${DRIVER_DIRS}" = "osmesa" ] ; then \
- $(MAKE) osmesa16 ; \
- else \
- $(MAKE) osmesa8 ; \
- fi
-
-
-
-
-# The normal libOSMesa is used in conjuction with libGL
-osmesa8: $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME)
-
-$(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME): $(OBJECTS)
- $(MKLIB) -o $(OSMESA_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
- -major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \
- -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \
- -id $(INSTALL_LIB_DIR)/lib$(OSMESA_LIB).$(MESA_MAJOR).dylib \
- $(OSMESA_LIB_DEPS) $(OBJECTS)
-
-
-# The libOSMesa16/libOSMesa32 libraries do not use libGL but rather are built
-# with all the other Mesa sources (compiled with -DCHAN_BITS=16/32
-osmesa16: $(OBJECTS) $(CORE_MESA)
+# libOSMesa can be used in conjuction with libGL or with all other Mesa
+# sources. We can also build libOSMesa16/libOSMesa32 by setting
+# -DCHAN_BITS=16/32.
+$(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME): $(OBJECTS) $(CORE_MESA)
$(MKLIB) -o $(OSMESA_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \
-install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \
diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c
index f2367bbbb7..904659e345 100644
--- a/src/mesa/drivers/osmesa/osmesa.c
+++ b/src/mesa/drivers/osmesa/osmesa.c
@@ -1310,7 +1310,7 @@ OSMesaDestroyContext( OSMesaContext osmesa )
_swrast_DestroyContext( &osmesa->mesa );
_mesa_destroy_visual( osmesa->gl_visual );
- _mesa_unreference_framebuffer( &osmesa->gl_buffer );
+ _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
_mesa_free_context_data( &osmesa->mesa );
_mesa_free( osmesa );
diff --git a/src/mesa/drivers/windows/gdi/mesa.def b/src/mesa/drivers/windows/gdi/mesa.def
index b386e34aad..bd3e5b2137 100644
--- a/src/mesa/drivers/windows/gdi/mesa.def
+++ b/src/mesa/drivers/windows/gdi/mesa.def
@@ -902,7 +902,6 @@ EXPORTS
_mesa_generate_mipmap
_mesa_get_compressed_teximage
_mesa_get_current_context
- _mesa_get_program_register
_mesa_get_teximage
_mesa_init_driver_functions
_mesa_init_glsl_driver_functions
@@ -940,7 +939,7 @@ EXPORTS
_mesa_store_texsubimage3d
_mesa_strcmp
_mesa_test_proxy_teximage
- _mesa_unreference_framebuffer
+ _mesa_reference_framebuffer
_mesa_update_framebuffer_visual
_mesa_use_program
_mesa_Viewport
diff --git a/src/mesa/drivers/windows/gdi/wmesa.c b/src/mesa/drivers/windows/gdi/wmesa.c
index 80746950c7..e1971db693 100644
--- a/src/mesa/drivers/windows/gdi/wmesa.c
+++ b/src/mesa/drivers/windows/gdi/wmesa.c
@@ -62,7 +62,7 @@ wmesa_free_framebuffer(HDC hdc)
else
prev->next = pwfb->next;
fb = &pwfb->Base;
- _mesa_unreference_framebuffer(&fb);
+ _mesa_reference_framebuffer(&fb, NULL);
}
}
@@ -1679,80 +1679,3 @@ void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
_mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);
}
-/* This is hopefully a temporary hack to define some needed dispatch
- * table entries. Hopefully, I'll find a better solution. The
- * dispatch table generation scripts ought to be making these dummy
- * stubs as well. */
-#if !defined(__MINGW32__) || !defined(GL_NO_STDCALL)
-void gl_dispatch_stub_543(void){}
-void gl_dispatch_stub_544(void){}
-void gl_dispatch_stub_545(void){}
-void gl_dispatch_stub_546(void){}
-void gl_dispatch_stub_547(void){}
-void gl_dispatch_stub_548(void){}
-void gl_dispatch_stub_549(void){}
-void gl_dispatch_stub_550(void){}
-void gl_dispatch_stub_551(void){}
-void gl_dispatch_stub_552(void){}
-void gl_dispatch_stub_553(void){}
-void gl_dispatch_stub_554(void){}
-void gl_dispatch_stub_555(void){}
-void gl_dispatch_stub_556(void){}
-void gl_dispatch_stub_557(void){}
-void gl_dispatch_stub_558(void){}
-void gl_dispatch_stub_559(void){}
-void gl_dispatch_stub_560(void){}
-void gl_dispatch_stub_561(void){}
-void gl_dispatch_stub_565(void){}
-void gl_dispatch_stub_566(void){}
-void gl_dispatch_stub_577(void){}
-void gl_dispatch_stub_578(void){}
-void gl_dispatch_stub_603(void){}
-void gl_dispatch_stub_645(void){}
-void gl_dispatch_stub_646(void){}
-void gl_dispatch_stub_647(void){}
-void gl_dispatch_stub_648(void){}
-void gl_dispatch_stub_649(void){}
-void gl_dispatch_stub_650(void){}
-void gl_dispatch_stub_651(void){}
-void gl_dispatch_stub_652(void){}
-void gl_dispatch_stub_653(void){}
-void gl_dispatch_stub_733(void){}
-void gl_dispatch_stub_734(void){}
-void gl_dispatch_stub_735(void){}
-void gl_dispatch_stub_736(void){}
-void gl_dispatch_stub_737(void){}
-void gl_dispatch_stub_738(void){}
-void gl_dispatch_stub_744(void){}
-void gl_dispatch_stub_745(void){}
-void gl_dispatch_stub_746(void){}
-void gl_dispatch_stub_760(void){}
-void gl_dispatch_stub_761(void){}
-void gl_dispatch_stub_763(void){}
-void gl_dispatch_stub_765(void){}
-void gl_dispatch_stub_766(void){}
-void gl_dispatch_stub_767(void){}
-void gl_dispatch_stub_768(void){}
-
-void gl_dispatch_stub_562(void){}
-void gl_dispatch_stub_563(void){}
-void gl_dispatch_stub_564(void){}
-void gl_dispatch_stub_567(void){}
-void gl_dispatch_stub_568(void){}
-void gl_dispatch_stub_569(void){}
-void gl_dispatch_stub_580(void){}
-void gl_dispatch_stub_581(void){}
-void gl_dispatch_stub_606(void){}
-void gl_dispatch_stub_654(void){}
-void gl_dispatch_stub_655(void){}
-void gl_dispatch_stub_656(void){}
-void gl_dispatch_stub_739(void){}
-void gl_dispatch_stub_740(void){}
-void gl_dispatch_stub_741(void){}
-void gl_dispatch_stub_748(void){}
-void gl_dispatch_stub_749(void){}
-void gl_dispatch_stub_769(void){}
-void gl_dispatch_stub_770(void){}
-void gl_dispatch_stub_771(void){}
-
-#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglcontext.c b/src/mesa/drivers/windows/gldirect/dglcontext.c
index 4ad7a76e67..e9c23d1ccb 100644
--- a/src/mesa/drivers/windows/gldirect/dglcontext.c
+++ b/src/mesa/drivers/windows/gldirect/dglcontext.c
@@ -1482,6 +1482,7 @@ SkipPrimaryCreate:
#else
lpCtx->glCtx->Const.MaxTextureSize = 1024;
#endif
+ lpCtx->glCtx->Const.MaxDrawBuffers = 1;
// Setup the Display Driver pointers
dglSetupDDPointers(lpCtx->glCtx);
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c
index 0f8fe33eb1..fa44a952a0 100644
--- a/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c
@@ -1422,6 +1422,8 @@ BOOL gldInitialiseMesa_DX(
lpCtx->glCtx->Const.MaxTextureUnits = 1;
}
+ lpCtx->glCtx->Const.MaxDrawBuffers = 1;
+
// max texture size
// MaxTextureSize = min(gld->d3dCaps8.MaxTextureHeight, gld->d3dCaps8.MaxTextureWidth);
MaxTextureSize = min(gld->d3dCaps.dwMaxTextureHeight, gld->d3dCaps.dwMaxTextureWidth);
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c
index 690f68b68f..011d810e97 100644
--- a/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c
@@ -1204,6 +1204,7 @@ BOOL gldInitialiseMesa_DX(
MaxTextureSize >>= 1;
}
lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
+ lpCtx->glCtx->Const.MaxDrawBuffers = 1;
IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE);
IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c
index dc465c5418..a03b865bb4 100644
--- a/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c
@@ -1206,6 +1206,7 @@ BOOL gldInitialiseMesa_DX(
MaxTextureSize >>= 1;
}
lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
+ lpCtx->glCtx->Const.MaxDrawBuffers = 1;
IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE);
IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
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 b590dc795a..342a742867 100644
--- a/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
+++ b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
@@ -1625,6 +1625,7 @@ BOOL gldInitialiseMesa_MesaSW(
// Added this to force max texture diminsion to 256. KeithH
ctx->Const.MaxTextureLevels = 8;
+ ctx->Const.MaxDrawBuffers = 1;
_mesa_enable_sw_extensions(ctx);
_mesa_enable_imaging_extensions(ctx);
diff --git a/src/mesa/drivers/x11/Makefile b/src/mesa/drivers/x11/Makefile
index d2780e62c9..5e427d2d5c 100644
--- a/src/mesa/drivers/x11/Makefile
+++ b/src/mesa/drivers/x11/Makefile
@@ -41,7 +41,8 @@ OBJECTS = $(SOURCES:.c=.o)
INCLUDE_DIRS = \
-I$(TOP)/include \
-I$(TOP)/src/mesa \
- -I$(TOP)/src/mesa/main
+ -I$(TOP)/src/mesa/main \
+ $(X11_INCLUDES)
CORE_MESA = $(TOP)/src/mesa/libmesa.a $(TOP)/src/mesa/libglapi.a
diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c
index ea3585258d..34e0b8bc8d 100644
--- a/src/mesa/drivers/x11/fakeglx.c
+++ b/src/mesa/drivers/x11/fakeglx.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.5
*
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -1392,6 +1393,25 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list )
}
+/**
+ * Init basic fields of a new fake_glx_context.
+ */
+static void
+init_glx_context(struct fake_glx_context *glxCtx, Display *dpy)
+{
+ /* Always return True. See if anyone's confused... */
+ GLboolean direct = GL_TRUE;
+
+ glxCtx->xmesaContext->direct = direct;
+ glxCtx->glxContext.isDirect = direct;
+ glxCtx->glxContext.currentDpy = dpy;
+ glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
+
+ assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+}
+
+
+
static GLXContext
Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
GLXContext share_list, Bool direct )
@@ -1430,12 +1450,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
return NULL;
}
- glxCtx->xmesaContext->direct = GL_FALSE;
- glxCtx->glxContext.isDirect = GL_FALSE;
- glxCtx->glxContext.currentDpy = dpy;
- glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
-
- assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+ init_glx_context(glxCtx, dpy);
return (GLXContext) glxCtx;
}
@@ -2203,7 +2218,7 @@ Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
if (!dpy || !config || !pixmap)
return 0;
- for (attr = attribList; *attr; attr++) {
+ for (attr = attribList; attr && *attr; attr++) {
switch (*attr) {
case GLX_TEXTURE_FORMAT_EXT:
attr++;
@@ -2441,12 +2456,7 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
return NULL;
}
- glxCtx->xmesaContext->direct = GL_FALSE;
- glxCtx->glxContext.isDirect = GL_FALSE;
- glxCtx->glxContext.currentDpy = dpy;
- glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
-
- assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+ init_glx_context(glxCtx, dpy);
return (GLXContext) glxCtx;
}
@@ -2664,12 +2674,7 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re
return NULL;
}
- glxCtx->xmesaContext->direct = GL_FALSE;
- glxCtx->glxContext.isDirect = GL_FALSE;
- glxCtx->glxContext.currentDpy = dpy;
- glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
-
- assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+ init_glx_context(glxCtx, dpy);
return (GLXContext) glxCtx;
}
diff --git a/src/mesa/drivers/x11/glxapi.c b/src/mesa/drivers/x11/glxapi.c
index c2ccce6f52..02eea25a71 100644
--- a/src/mesa/drivers/x11/glxapi.c
+++ b/src/mesa/drivers/x11/glxapi.c
@@ -35,6 +35,7 @@
#include <stdio.h>
#include <string.h>
#include "main/glheader.h"
+#include "main/compiler.h"
#include "glapi/glapi.h"
#include "glxapi.h"
@@ -1374,7 +1375,12 @@ _glxapi_get_proc_address(const char *funcName)
{
GLuint i;
for (i = 0; GLX_functions[i].Name; i++) {
+#ifdef MANGLE
+ /* skip the "m" prefix on the name */
+ if (strcmp(GLX_functions[i].Name, funcName+1) == 0)
+#else
if (strcmp(GLX_functions[i].Name, funcName) == 0)
+#endif
return GLX_functions[i].Address;
}
return NULL;
diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c
index 18aa8bcc09..662c61ae7e 100644
--- a/src/mesa/drivers/x11/xm_api.c
+++ b/src/mesa/drivers/x11/xm_api.c
@@ -79,6 +79,7 @@
#include "tnl/t_context.h"
#include "tnl/t_pipeline.h"
#include "drivers/common/driverfuncs.h"
+#include "drivers/common/meta.h"
/**
* Global X driver lock
@@ -492,7 +493,7 @@ xmesa_free_buffer(XMesaBuffer buffer)
b->frontxrb->drawable = 0;
/* Unreference. If count = zero we'll really delete the buffer */
- _mesa_unreference_framebuffer(&fb);
+ _mesa_reference_framebuffer(&fb, NULL);
return;
}
@@ -1316,7 +1317,9 @@ xmesa_convert_from_x_visual_type( int visualType )
#define need_GL_SGI_color_table
/* sw extensions not associated with some GL version */
+#define need_GL_ARB_draw_elements_base_vertex
#define need_GL_ARB_shader_objects
+#define need_GL_ARB_sync
#define need_GL_ARB_vertex_program
#define need_GL_APPLE_vertex_array_object
#define need_GL_ATI_fragment_shader
@@ -1325,7 +1328,6 @@ xmesa_convert_from_x_visual_type( int visualType )
#define need_GL_EXT_framebuffer_blit
#define need_GL_EXT_gpu_program_parameters
#define need_GL_EXT_paletted_texture
-#define need_GL_IBM_multimode_draw_arrays
#define need_GL_MESA_resize_buffers
#define need_GL_NV_vertex_program
#define need_GL_NV_fragment_program
@@ -1346,7 +1348,10 @@ const struct dri_extension card_extensions[] =
{ "GL_EXT_histogram", GL_EXT_histogram_functions },
{ "GL_SGI_color_table", GL_SGI_color_table_functions },
+ { "GL_ARB_depth_clamp", NULL },
+ { "GL_ARB_draw_elements_base_vertex", GL_ARB_draw_elements_base_vertex_functions },
{ "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
+ { "GL_ARB_sync", GL_ARB_sync_functions },
{ "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
{ "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions },
{ "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions },
@@ -1355,8 +1360,8 @@ const struct dri_extension card_extensions[] =
{ "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
{ "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
{ "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
- { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
{ "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions },
+ { "GL_NV_depth_clamp", NULL },
{ "GL_NV_vertex_program", GL_NV_vertex_program_functions },
{ "GL_NV_fragment_program", GL_NV_fragment_program_functions },
{ NULL, NULL }
@@ -1586,6 +1591,14 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
return NULL;
}
+ /* Enable this to exercise fixed function -> shader translation
+ * with software rendering.
+ */
+ if (0) {
+ mesaCtx->VertexProgram._MaintainTnlProgram = GL_TRUE;
+ mesaCtx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+ }
+
_mesa_enable_sw_extensions(mesaCtx);
_mesa_enable_1_3_extensions(mesaCtx);
_mesa_enable_1_4_extensions(mesaCtx);
@@ -1635,6 +1648,9 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
xmesa_register_swrast_functions( mesaCtx );
_swsetup_Wakeup(mesaCtx);
+ if (TEST_META_FUNCS)
+ _mesa_meta_init(mesaCtx);
+
return c;
}
@@ -1649,6 +1665,9 @@ void XMesaDestroyContext( XMesaContext c )
FXdestroyContext( XMESA_BUFFER(mesaCtx->DrawBuffer) );
#endif
+ if (TEST_META_FUNCS)
+ _mesa_meta_free( mesaCtx );
+
_swsetup_DestroyContext( mesaCtx );
_swrast_DestroyContext( mesaCtx );
_tnl_DestroyContext( mesaCtx );
@@ -2412,11 +2431,8 @@ xbuffer_to_renderbuffer(int buffer)
case GLX_AUX0_EXT:
return BUFFER_AUX0;
case GLX_AUX1_EXT:
- return BUFFER_AUX1;
case GLX_AUX2_EXT:
- return BUFFER_AUX2;
case GLX_AUX3_EXT:
- return BUFFER_AUX3;
case GLX_AUX4_EXT:
case GLX_AUX5_EXT:
case GLX_AUX6_EXT:
@@ -2463,13 +2479,13 @@ XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer,
#if 0
switch (drawable->TextureTarget) {
case GLX_TEXTURE_1D_EXT:
- texObj = texUnit->Current1D;
+ texObj = texUnit->CurrentTex[TEXTURE_1D_INDEX];
break;
case GLX_TEXTURE_2D_EXT:
- texObj = texUnit->Current2D;
+ texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX];
break;
case GLX_TEXTURE_RECTANGLE_EXT:
- texObj = texUnit->CurrentRect;
+ texObj = texUnit->CurrentTex[TEXTURE_RECT_INDEX];
break;
default:
return; /* BadMatch error */
diff --git a/src/mesa/drivers/x11/xm_buffer.c b/src/mesa/drivers/x11/xm_buffer.c
index 7ad67bc34d..821e2a8e08 100644
--- a/src/mesa/drivers/x11/xm_buffer.c
+++ b/src/mesa/drivers/x11/xm_buffer.c
@@ -229,6 +229,7 @@ alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height)
}
b->backxrb->ximage = NULL;
+ b->backxrb->drawable = b->backxrb->pixmap;
}
}
diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c
index 305df548fa..4e9c001cc7 100644
--- a/src/mesa/drivers/x11/xm_dd.c
+++ b/src/mesa/drivers/x11/xm_dd.c
@@ -51,6 +51,7 @@
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
+#include "drivers/common/meta.h"
#include "xmesaP.h"
@@ -912,8 +913,9 @@ xmesa_update_state( GLcontext *ctx, GLbitfield new_state )
/*
* GL_DITHER, GL_READ/DRAW_BUFFER, buffer binding state, etc. effect
* renderbuffer span/clear funcs.
+ * Check _NEW_COLOR to detect dither enable/disable.
*/
- if (new_state & (_NEW_COLOR | _NEW_PIXEL | _NEW_BUFFERS)) {
+ if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) {
XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
struct xmesa_renderbuffer *front_xrb, *back_xrb;
@@ -1146,19 +1148,28 @@ xmesa_init_driver_functions( XMesaVisual xmvisual,
driver->IndexMask = index_mask;
driver->ColorMask = color_mask;
driver->Enable = enable;
- driver->Clear = clear_buffers;
driver->Viewport = xmesa_viewport;
-#ifndef XFree86Server
- driver->CopyPixels = xmesa_CopyPixels;
- if (xmvisual->undithered_pf == PF_8R8G8B &&
- xmvisual->dithered_pf == PF_8R8G8B &&
- xmvisual->BitsPerPixel == 32) {
- driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
- }
- else if (xmvisual->undithered_pf == PF_5R6G5B) {
- driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
+ if (TEST_META_FUNCS) {
+ driver->Clear = _mesa_meta_clear;
+ driver->CopyPixels = _mesa_meta_copy_pixels;
+ driver->BlitFramebuffer = _mesa_meta_blit_framebuffer;
+ driver->DrawPixels = _mesa_meta_draw_pixels;
+ driver->Bitmap = _mesa_meta_bitmap;
}
+ else {
+ driver->Clear = clear_buffers;
+#ifndef XFree86Server
+ driver->CopyPixels = xmesa_CopyPixels;
+ if (xmvisual->undithered_pf == PF_8R8G8B &&
+ xmvisual->dithered_pf == PF_8R8G8B &&
+ xmvisual->BitsPerPixel == 32) {
+ driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
+ }
+ else if (xmvisual->undithered_pf == PF_5R6G5B) {
+ driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
+ }
#endif
+ }
driver->TestProxyTexImage = test_proxy_teximage;
#if ENABLE_EXT_texure_compression_s3tc
driver->ChooseTextureFormat = choose_tex_format;
diff --git a/src/mesa/drivers/x11/xm_span.c b/src/mesa/drivers/x11/xm_span.c
index 57b5749448..309cefcb8e 100644
--- a/src/mesa/drivers/x11/xm_span.c
+++ b/src/mesa/drivers/x11/xm_span.c
@@ -471,8 +471,26 @@ static void put_row_8R8G8B_pixmap( PUT_ROW_ARGS )
if (mask) {
for (i=0;i<n;i++,x++) {
if (mask[i]) {
+#if 1
+ /*
+ * XXX Something funny is going on here.
+ * If we're drawing into a window that uses a depth 32 TrueColor
+ * visual, we see the right pixels on screen, but when we read
+ * them back with XGetImage() we get random colors.
+ * The alternative code below which uses XPutImage() instead
+ * seems to mostly fix the problem, but not always.
+ * We don't normally create windows with this visual, but glean
+ * does and we're seeing some failures there.
+ */
XMesaSetForeground( dpy, gc, PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+#else
+ /* This code works more often, but not always */
+ XMesaImage *rowimg = XMESA_BUFFER(ctx->DrawBuffer)->rowimage;
+ GLuint *ptr4 = (GLuint *) rowimg->data;
+ *ptr4 = PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, 1, 1 );
+#endif
}
}
}
diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h
index 65e747d7b9..25db55862e 100644
--- a/src/mesa/drivers/x11/xmesaP.h
+++ b/src/mesa/drivers/x11/xmesaP.h
@@ -581,4 +581,8 @@ extern void xmesa_register_swrast_functions( GLcontext *ctx );
#define ENABLE_EXT_timer_query 0 /* may not have 64-bit GLuint64EXT */
#endif
+
+#define TEST_META_FUNCS 0
+
+
#endif
diff --git a/src/mesa/es/Makefile b/src/mesa/es/Makefile
new file mode 100644
index 0000000000..b571eedecf
--- /dev/null
+++ b/src/mesa/es/Makefile
@@ -0,0 +1,115 @@
+# src/mesa/es/Makefile
+#
+TOP := ../../..
+MESA := ..
+
+include $(TOP)/configs/current
+include sources.mak
+
+# no libes1.a and libes2.a by default
+ES1_LIBS := libes1.a libes1gallium.a libes1api.a
+ES2_LIBS := libes2.a libes2gallium.a libes2api.a
+
+# Default rule: create ES1 and ES2 libs
+.PHONY: default
+default: subdirs $(ES1_LIBS) $(ES2_LIBS)
+
+# force the inclusion of es's mfeatures.h
+ES1_CFLAGS := -include main/mfeatures.h -D__GL_EXPORTS -UIN_DRI_DRIVER
+ES2_CFLAGS := $(ES1_CFLAGS)
+
+# rebuild when these files are changed
+ES1_GLAPI_DEPS := glapi/headers-es1/glapi/dispatch.h
+ES2_GLAPI_DEPS := glapi/headers-es2/glapi/dispatch.h
+
+ES1_OBJ_DIR := objs-es1
+ES2_OBJ_DIR := objs-es2
+
+# adjust output dir
+ES1_OBJECTS := $(addprefix $(ES1_OBJ_DIR)/, $(ES1_OBJECTS))
+ES1_GALLIUM_OBJECTS := $(addprefix $(ES1_OBJ_DIR)/, $(ES1_GALLIUM_OBJECTS))
+ES1_API_OBJECTS := $(addprefix $(ES1_OBJ_DIR)/, $(ES1_API_OBJECTS))
+
+ES2_OBJECTS := $(addprefix $(ES2_OBJ_DIR)/, $(ES2_OBJECTS))
+ES2_GALLIUM_OBJECTS := $(addprefix $(ES2_OBJ_DIR)/, $(ES2_GALLIUM_OBJECTS))
+ES2_API_OBJECTS := $(addprefix $(ES2_OBJ_DIR)/, $(ES2_API_OBJECTS))
+
+# specify prerequisites
+$(foreach obj,$(ALL_LOCAL_OBJECTS), \
+ $(eval $(ES1_OBJ_DIR)/$(obj): $(obj:.o=.c) $(ES1_GLAPI_DEPS)) \
+ $(eval $(ES2_OBJ_DIR)/$(obj): $(obj:.o=.c) $(ES2_GLAPI_DEPS)))
+$(foreach obj,$(ALL_MESA_OBJECTS), \
+ $(eval $(ES1_OBJ_DIR)/$(obj): $(MESA)/$(obj:.o=.c) $(ES1_GLAPI_DEPS)) \
+ $(eval $(ES2_OBJ_DIR)/$(obj): $(MESA)/$(obj:.o=.c) $(ES2_GLAPI_DEPS)))
+
+# sort to remove duplicates
+ES1_ANY_OBJECTS := $(sort $(ES1_OBJECTS) $(ES1_GALLIUM_OBJECTS))
+ES2_ANY_OBJECTS := $(sort $(ES2_OBJECTS) $(ES2_GALLIUM_OBJECTS))
+
+$(ES1_ANY_OBJECTS):
+ @mkdir -p $(dir $@)
+ $(CC) -c $(CFLAGS) $(ES1_CFLAGS) $(ES1_INCLUDES) $< -o $@
+
+$(ES1_API_OBJECTS):
+ @mkdir -p $(dir $@)
+ $(CC) -c $(CFLAGS) $(ES1_CFLAGS) -UIN_DRI_DRIVER $(ES1_INCLUDES) $< -o $@
+
+$(ES2_ANY_OBJECTS):
+ @mkdir -p $(dir $@)
+ $(CC) -c $(CFLAGS) $(ES2_CFLAGS) $(ES2_INCLUDES) $< -o $@
+
+$(ES2_API_OBJECTS):
+ @mkdir -p $(dir $@)
+ $(CC) -c $(CFLAGS) $(ES2_CFLAGS) -UIN_DRI_DRIVER $(ES2_INCLUDES) $< -o $@
+
+libes1.a: $(ES1_OBJECTS)
+ @echo "Making $@"
+ @$(TOP)/bin/mklib -o es1 -static $(ES1_OBJECTS)
+
+libes2.a: $(ES2_OBJECTS)
+ @echo "Making $@"
+ @$(TOP)/bin/mklib -o es2 -static $(ES1_OBJECTS)
+
+libes1gallium.a: $(ES1_GALLIUM_OBJECTS)
+ @echo "Making $@"
+ @$(TOP)/bin/mklib -o es1gallium -static $(ES1_GALLIUM_OBJECTS)
+
+libes2gallium.a: $(ES2_GALLIUM_OBJECTS)
+ @echo "Making $@"
+ @$(TOP)/bin/mklib -o es2gallium -static $(ES2_GALLIUM_OBJECTS)
+
+libes1api.a: $(ES1_API_OBJECTS)
+ @echo "Making $@"
+ @$(TOP)/bin/mklib -o es1api -static $(ES1_API_OBJECTS)
+
+libes2api.a: $(ES2_API_OBJECTS)
+ @echo "Making $@"
+ @$(TOP)/bin/mklib -o es2api -static $(ES2_API_OBJECTS)
+
+GENERATED_SOURCES := \
+ main/api_exec_es1.c \
+ main/api_exec_es2.c \
+ main/get_es1.c \
+ main/get_es2.c
+
+main/api_exec_es1.c: main/APIspec.txt main/es_generator.py main/apiutil.py main/es1_special
+ $(PYTHON2) $(PYTHON_FLAGS) main/es_generator.py -S main/APIspec.txt -V GLES1.1 > $@
+
+main/api_exec_es2.c: main/APIspec.txt main/es_generator.py main/apiutil.py main/es2_special
+ $(PYTHON2) $(PYTHON_FLAGS) main/es_generator.py -S main/APIspec.txt -V GLES2.0 > $@
+
+main/get_es1.c: main/get_gen.py
+ $(PYTHON2) $(PYTHON_FLAGS) $< 1 > $@
+
+main/get_es2.c: main/get_gen.py
+ $(PYTHON2) $(PYTHON_FLAGS) $< 2 > $@
+
+subdirs:
+ make -C glapi
+
+.PHONY: clean
+clean:
+ -rm -f $(ES1_LIBS) $(ES2_LIBS)
+ -rm -rf $(ES1_OBJ_DIR) $(ES2_OBJ_DIR)
+ -rm -f $(GENERATED_SOURCES)
+ -rm -f *~
diff --git a/src/mesa/es/glapi/Makefile b/src/mesa/es/glapi/Makefile
new file mode 100644
index 0000000000..a658bb1f0c
--- /dev/null
+++ b/src/mesa/es/glapi/Makefile
@@ -0,0 +1,65 @@
+TOP = ../../../..
+GLAPI = ../../glapi
+include $(TOP)/configs/current
+
+OUTPUTS := glprocs.h glapitemp.h glapioffsets.h glapitable.h dispatch.h
+
+COMMON = gl_XML.py glX_XML.py license.py typeexpr.py
+COMMON := $(addprefix $(GLAPI)/, $(COMMON))
+
+ES1_APIXML := es1_API.xml
+ES2_APIXML := es2_API.xml
+ES1_OUTPUT_DIR := headers-es1
+ES2_OUTPUT_DIR := headers-es2
+
+ES1_DEPS = $(ES1_APIXML) base1_API.xml es1_EXT.xml es_EXT.xml \
+ es1_COMPAT.xml es_COMPAT.xml
+ES2_DEPS = $(ES2_APIXML) base2_API.xml es2_EXT.xml es_EXT.xml \
+ es2_COMPAT.xml es_COMPAT.xml
+
+ES1_OUTPUTS := $(addprefix $(ES1_OUTPUT_DIR)/glapi/, $(OUTPUTS))
+ES2_OUTPUTS := $(addprefix $(ES2_OUTPUT_DIR)/glapi/, $(OUTPUTS))
+
+all: $(ES1_OUTPUTS) $(ES2_OUTPUTS)
+
+$(ES1_OUTPUTS): APIXML := $(ES1_APIXML)
+$(ES2_OUTPUTS): APIXML := $(ES2_APIXML)
+$(ES1_OUTPUTS): $(ES1_DEPS)
+$(ES2_OUTPUTS): $(ES2_DEPS)
+
+%/glprocs.h: $(GLAPI)/gl_procs.py $(COMMON)
+ @mkdir -p $(dir $@)
+ $(PYTHON2) $(PYTHON_FLAGS) $< -f $(APIXML) -c > $@
+
+%/glapitemp.h: $(GLAPI)/gl_apitemp.py $(COMMON)
+ @mkdir -p $(dir $@)
+ $(PYTHON2) $(PYTHON_FLAGS) $< -f $(APIXML) > $@
+
+%/glapioffsets.h: $(GLAPI)/gl_offsets.py $(COMMON)
+ @mkdir -p $(dir $@)
+ $(PYTHON2) $(PYTHON_FLAGS) $< -f $(APIXML) -c > $@
+
+%/glapitable.h: $(GLAPI)/gl_table.py $(COMMON)
+ @mkdir -p $(dir $@)
+ $(PYTHON2) $(PYTHON_FLAGS) $< -f $(APIXML) -c > $@
+
+%/dispatch.h: $(GLAPI)/gl_table.py $(COMMON)
+ @mkdir -p $(dir $@)
+ $(PYTHON2) $(PYTHON_FLAGS) $< -f $(APIXML) -m remap_table -c > $@
+
+verify_xml:
+ @if [ ! -f gl.h ]; then \
+ echo "Please copy gl.h and gl2.h to this directory"; \
+ exit 1; \
+ fi
+ @echo "Verifying that es1_API.xml covers OpenGL ES 1.1..."
+ @$(PYTHON2) $(PYTHON_FLAGS) gl_parse_header.py gl.h > tmp.xml
+ @$(PYTHON2) $(PYTHON_FLAGS) gl_compare.py difference tmp.xml es1_API.xml
+ @echo "Verifying that es2_API.xml covers OpenGL ES 2.0..."
+ @$(PYTHON2) $(PYTHON_FLAGS) gl_parse_header.py gl2.h > tmp.xml
+ @$(PYTHON2) $(PYTHON_FLAGS) gl_compare.py difference tmp.xml es2_API.xml
+ @rm -f tmp.xml
+
+clean:
+ -rm -rf $(ES1_OUTPUT_DIR) $(ES2_OUTPUT_DIR)
+ -rm -f *~ *.pyc *.pyo
diff --git a/src/mesa/es/glapi/base1_API.xml b/src/mesa/es/glapi/base1_API.xml
new file mode 100644
index 0000000000..a7c5264c88
--- /dev/null
+++ b/src/mesa/es/glapi/base1_API.xml
@@ -0,0 +1,760 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<!-- OpenGL and OpenGL ES 1.x APIs
+ This file defines the base categories that can be shared by all APIs.
+ They are defined in an incremental fashion. The "es" variant of a
+ category, if exists, is not usually used, except for OpenGL ES 1.0.
+-->
+
+<OpenGLAPI>
+
+<!-- base subset of OpenGL 1.0, excluding those not in OpenGL ES 1.0 -->
+<category name="base1.0es">
+ <enum name="FALSE" value="0x0"/>
+ <enum name="TRUE" value="0x1"/>
+ <enum name="ZERO" value="0x0"/>
+ <enum name="ONE" value="0x1"/>
+ <enum name="NO_ERROR" value="0x0"/>
+
+ <enum name="POINTS" value="0x0000"/>
+ <enum name="LINES" value="0x0001"/>
+ <enum name="LINE_LOOP" value="0x0002"/>
+ <enum name="LINE_STRIP" value="0x0003"/>
+ <enum name="TRIANGLES" value="0x0004"/>
+ <enum name="TRIANGLE_STRIP" value="0x0005"/>
+ <enum name="TRIANGLE_FAN" value="0x0006"/>
+ <enum name="NEVER" value="0x0200"/>
+ <enum name="LESS" value="0x0201"/>
+ <enum name="EQUAL" value="0x0202"/>
+ <enum name="LEQUAL" value="0x0203"/>
+ <enum name="GREATER" value="0x0204"/>
+ <enum name="NOTEQUAL" value="0x0205"/>
+ <enum name="GEQUAL" value="0x0206"/>
+ <enum name="ALWAYS" value="0x0207"/>
+ <enum name="SRC_COLOR" value="0x0300"/>
+ <enum name="ONE_MINUS_SRC_COLOR" value="0x0301"/>
+ <enum name="SRC_ALPHA" value="0x0302"/>
+ <enum name="ONE_MINUS_SRC_ALPHA" value="0x0303"/>
+ <enum name="DST_ALPHA" value="0x0304"/>
+ <enum name="ONE_MINUS_DST_ALPHA" value="0x0305"/>
+ <enum name="DST_COLOR" value="0x0306"/>
+ <enum name="ONE_MINUS_DST_COLOR" value="0x0307"/>
+ <enum name="SRC_ALPHA_SATURATE" value="0x0308"/>
+ <enum name="FRONT" value="0x0404"/>
+ <enum name="BACK" value="0x0405"/>
+ <enum name="FRONT_AND_BACK" value="0x0408"/>
+ <enum name="INVALID_ENUM" value="0x0500"/>
+ <enum name="INVALID_VALUE" value="0x0501"/>
+ <enum name="INVALID_OPERATION" value="0x0502"/>
+ <enum name="OUT_OF_MEMORY" value="0x0505"/>
+ <enum name="CW" value="0x0900"/>
+ <enum name="CCW" value="0x0901"/>
+ <enum name="CULL_FACE" count="1" value="0x0B44">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DEPTH_TEST" count="1" value="0x0B71">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_TEST" count="1" value="0x0B90">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DITHER" count="1" value="0x0BD0">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND" count="1" value="0x0BE2">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SCISSOR_TEST" count="1" value="0x0C11">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="UNPACK_ALIGNMENT" count="1" value="0x0CF5">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="PACK_ALIGNMENT" count="1" value="0x0D05">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_TEXTURE_SIZE" count="1" value="0x0D33">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_VIEWPORT_DIMS" count="2" value="0x0D3A">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SUBPIXEL_BITS" count="1" value="0x0D50">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="RED_BITS" count="1" value="0x0D52">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="GREEN_BITS" count="1" value="0x0D53">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLUE_BITS" count="1" value="0x0D54">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="ALPHA_BITS" count="1" value="0x0D55">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DEPTH_BITS" count="1" value="0x0D56">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_BITS" count="1" value="0x0D57">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_2D" count="1" value="0x0DE1">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DONT_CARE" value="0x1100"/>
+ <enum name="FASTEST" value="0x1101"/>
+ <enum name="NICEST" value="0x1102"/>
+ <enum name="BYTE" count="1" value="0x1400">
+ <size name="CallLists"/>
+ </enum>
+ <enum name="UNSIGNED_BYTE" count="1" value="0x1401">
+ <size name="CallLists"/>
+ </enum>
+ <enum name="SHORT" count="2" value="0x1402">
+ <size name="CallLists"/>
+ </enum>
+ <enum name="UNSIGNED_SHORT" count="2" value="0x1403">
+ <size name="CallLists"/>
+ </enum>
+ <enum name="FLOAT" count="4" value="0x1406">
+ <size name="CallLists"/>
+ </enum>
+ <enum name="INVERT" value="0x150A"/>
+ <enum name="TEXTURE" value="0x1702"/>
+ <enum name="ALPHA" value="0x1906"/>
+ <enum name="RGB" value="0x1907"/>
+ <enum name="RGBA" value="0x1908"/>
+ <enum name="LUMINANCE" value="0x1909"/>
+ <enum name="LUMINANCE_ALPHA" value="0x190A"/>
+ <enum name="KEEP" value="0x1E00"/>
+ <enum name="REPLACE" value="0x1E01"/>
+ <enum name="INCR" value="0x1E02"/>
+ <enum name="DECR" value="0x1E03"/>
+ <enum name="VENDOR" value="0x1F00"/>
+ <enum name="RENDERER" value="0x1F01"/>
+ <enum name="VERSION" value="0x1F02"/>
+ <enum name="EXTENSIONS" value="0x1F03"/>
+ <enum name="NEAREST" value="0x2600"/>
+ <enum name="LINEAR" value="0x2601"/>
+ <enum name="NEAREST_MIPMAP_NEAREST" value="0x2700"/>
+ <enum name="LINEAR_MIPMAP_NEAREST" value="0x2701"/>
+ <enum name="NEAREST_MIPMAP_LINEAR" value="0x2702"/>
+ <enum name="LINEAR_MIPMAP_LINEAR" value="0x2703"/>
+ <enum name="TEXTURE_MAG_FILTER" count="1" value="0x2800">
+ <size name="TexParameterfv"/>
+ <size name="TexParameteriv"/>
+ <size name="GetTexParameterfv" mode="get"/>
+ <size name="GetTexParameteriv" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_MIN_FILTER" count="1" value="0x2801">
+ <size name="TexParameterfv"/>
+ <size name="TexParameteriv"/>
+ <size name="GetTexParameterfv" mode="get"/>
+ <size name="GetTexParameteriv" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_WRAP_S" count="1" value="0x2802">
+ <size name="TexParameterfv"/>
+ <size name="TexParameteriv"/>
+ <size name="GetTexParameterfv" mode="get"/>
+ <size name="GetTexParameteriv" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_WRAP_T" count="1" value="0x2803">
+ <size name="TexParameterfv"/>
+ <size name="TexParameteriv"/>
+ <size name="GetTexParameterfv" mode="get"/>
+ <size name="GetTexParameteriv" mode="get"/>
+ </enum>
+ <enum name="REPEAT" value="0x2901"/>
+
+ <enum name="DEPTH_BUFFER_BIT" value="0x00000100"/>
+ <enum name="STENCIL_BUFFER_BIT" value="0x00000400"/>
+ <enum name="COLOR_BUFFER_BIT" value="0x00004000"/>
+
+ <type name="float" size="4" float="true" glx_name="FLOAT32"/>
+ <type name="clampf" size="4" float="true" glx_name="FLOAT32"/>
+
+ <type name="int" size="4" glx_name="CARD32"/>
+ <type name="uint" size="4" unsigned="true" glx_name="CARD32"/>
+ <type name="sizei" size="4" glx_name="CARD32"/>
+ <type name="enum" size="4" unsigned="true" glx_name="ENUM"/>
+ <type name="bitfield" size="4" unsigned="true" glx_name="CARD32"/>
+
+ <type name="short" size="2" glx_name="CARD16"/>
+ <type name="ushort" size="2" unsigned="true" glx_name="CARD16"/>
+
+ <type name="byte" size="1" glx_name="CARD8"/>
+ <type name="ubyte" size="1" unsigned="true" glx_name="CARD8"/>
+ <type name="boolean" size="1" unsigned="true" glx_name="CARD8"/>
+
+ <type name="void" size="1"/>
+
+ <function name="BlendFunc" offset="241">
+ <param name="sfactor" type="GLenum"/>
+ <param name="dfactor" type="GLenum"/>
+ <glx rop="160"/>
+ </function>
+
+ <function name="Clear" offset="203">
+ <param name="mask" type="GLbitfield"/>
+ <glx rop="127"/>
+ </function>
+
+ <function name="ClearColor" offset="206">
+ <param name="red" type="GLclampf"/>
+ <param name="green" type="GLclampf"/>
+ <param name="blue" type="GLclampf"/>
+ <param name="alpha" type="GLclampf"/>
+ <glx rop="130"/>
+ </function>
+
+ <function name="ClearStencil" offset="207">
+ <param name="s" type="GLint"/>
+ <glx rop="131"/>
+ </function>
+
+ <function name="ColorMask" offset="210">
+ <param name="red" type="GLboolean"/>
+ <param name="green" type="GLboolean"/>
+ <param name="blue" type="GLboolean"/>
+ <param name="alpha" type="GLboolean"/>
+ <glx rop="134"/>
+ </function>
+
+ <function name="CullFace" offset="152">
+ <param name="mode" type="GLenum"/>
+ <glx rop="79"/>
+ </function>
+
+ <function name="DepthFunc" offset="245">
+ <param name="func" type="GLenum"/>
+ <glx rop="164"/>
+ </function>
+
+ <function name="DepthMask" offset="211">
+ <param name="flag" type="GLboolean"/>
+ <glx rop="135"/>
+ </function>
+
+ <function name="Disable" offset="214">
+ <param name="cap" type="GLenum"/>
+ <glx rop="138" handcode="client"/>
+ </function>
+
+ <function name="Enable" offset="215">
+ <param name="cap" type="GLenum"/>
+ <glx rop="139" handcode="client"/>
+ </function>
+
+ <function name="Finish" offset="216">
+ <glx sop="108" handcode="true"/>
+ </function>
+
+ <function name="Flush" offset="217">
+ <glx sop="142" handcode="true"/>
+ </function>
+
+ <function name="FrontFace" offset="157">
+ <param name="mode" type="GLenum"/>
+ <glx rop="84"/>
+ </function>
+
+ <function name="GetError" offset="261">
+ <return type="GLenum"/>
+ <glx sop="115" handcode="client"/>
+ </function>
+
+ <function name="GetIntegerv" offset="263">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="117" handcode="client"/>
+ </function>
+
+ <function name="GetString" offset="275">
+ <param name="name" type="GLenum"/>
+ <return type="const GLubyte *"/>
+ <glx sop="129" handcode="true"/>
+ </function>
+
+ <function name="Hint" offset="158">
+ <param name="target" type="GLenum"/>
+ <param name="mode" type="GLenum"/>
+ <glx rop="85"/>
+ </function>
+
+ <function name="LineWidth" offset="168">
+ <param name="width" type="GLfloat"/>
+ <glx rop="95"/>
+ </function>
+
+ <function name="PixelStorei" offset="250">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx sop="110" handcode="client"/>
+ </function>
+
+ <function name="ReadPixels" offset="256">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="GLvoid *" output="true" img_width="width" img_height="height" img_format="format" img_type="type" img_target="0"/>
+ <glx sop="111"/>
+ </function>
+
+ <function name="Scissor" offset="176">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="103"/>
+ </function>
+
+ <function name="StencilFunc" offset="243">
+ <param name="func" type="GLenum"/>
+ <param name="ref" type="GLint"/>
+ <param name="mask" type="GLuint"/>
+ <glx rop="162"/>
+ </function>
+
+ <function name="StencilMask" offset="209">
+ <param name="mask" type="GLuint"/>
+ <glx rop="133"/>
+ </function>
+
+ <function name="StencilOp" offset="244">
+ <param name="fail" type="GLenum"/>
+ <param name="zfail" type="GLenum"/>
+ <param name="zpass" type="GLenum"/>
+ <glx rop="163"/>
+ </function>
+
+ <function name="TexParameterf" offset="178">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="105"/>
+ </function>
+
+ <function name="Viewport" offset="305">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="191"/>
+ </function>
+</category>
+
+<!-- base subset of OpenGL 1.1, excluding those not in OpenGL ES 1.0 -->
+<category name="base1.1es">
+ <enum name="POLYGON_OFFSET_FILL" value="0x8037"/>
+
+ <function name="BindTexture" offset="307">
+ <param name="target" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <glx rop="4117"/>
+ </function>
+
+ <function name="CopyTexImage2D" offset="324">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <glx rop="4120"/>
+ </function>
+
+ <function name="CopyTexSubImage2D" offset="326">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="4122"/>
+ </function>
+
+ <function name="DeleteTextures" offset="327">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="textures" type="const GLuint *" count="n"/>
+ <glx sop="144"/>
+ </function>
+
+ <function name="DrawArrays" offset="310">
+ <param name="mode" type="GLenum"/>
+ <param name="first" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <glx rop="193" handcode="true"/>
+ </function>
+
+ <function name="DrawElements" offset="311">
+ <param name="mode" type="GLenum"/>
+ <param name="count" type="GLsizei"/>
+ <param name="type" type="GLenum"/>
+ <param name="indices" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="GenTextures" offset="328">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="textures" type="GLuint *" output="true" count="n"/>
+ <glx sop="145" always_array="true"/>
+ </function>
+
+ <function name="PolygonOffset" offset="319">
+ <param name="factor" type="GLfloat"/>
+ <param name="units" type="GLfloat"/>
+ <glx rop="192"/>
+ </function>
+
+ <function name="TexSubImage2D" offset="333">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="UNUSED" type="GLuint" padding="true"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_xoff="xoffset" img_yoff="yoffset" img_format="format" img_type="type" img_target="target" img_pad_dimensions="true"/>
+ <glx rop="4100" large="true"/>
+ </function>
+</category>
+
+<!-- base subset of OpenGL 1.2, excluding those not in OpenGL ES 1.0 -->
+<category name="base1.2es">
+ <enum name="UNSIGNED_SHORT_4_4_4_4" value="0x8033"/>
+ <enum name="UNSIGNED_SHORT_5_5_5_1" value="0x8034"/>
+ <enum name="CLAMP_TO_EDGE" value="0x812F"/>
+ <enum name="UNSIGNED_SHORT_5_6_5" value="0x8363"/>
+ <enum name="ALIASED_POINT_SIZE_RANGE" count="2" value="0x846D">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="ALIASED_LINE_WIDTH_RANGE" count="2" value="0x846E">
+ <size name="Get" mode="get"/>
+ </enum>
+</category>
+
+<!-- base subset of OpenGL 1.3, excluding those not in OpenGL ES 1.0 -->
+<category name="base1.3es">
+ <enum name="SAMPLE_ALPHA_TO_COVERAGE" count="1" value="0x809E">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SAMPLE_COVERAGE" count="1" value="0x80A0">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE0" value="0x84C0"/>
+ <enum name="TEXTURE1" value="0x84C1"/>
+ <enum name="TEXTURE2" value="0x84C2"/>
+ <enum name="TEXTURE3" value="0x84C3"/>
+ <enum name="TEXTURE4" value="0x84C4"/>
+ <enum name="TEXTURE5" value="0x84C5"/>
+ <enum name="TEXTURE6" value="0x84C6"/>
+ <enum name="TEXTURE7" value="0x84C7"/>
+ <enum name="TEXTURE8" value="0x84C8"/>
+ <enum name="TEXTURE9" value="0x84C9"/>
+ <enum name="TEXTURE10" value="0x84CA"/>
+ <enum name="TEXTURE11" value="0x84CB"/>
+ <enum name="TEXTURE12" value="0x84CC"/>
+ <enum name="TEXTURE13" value="0x84CD"/>
+ <enum name="TEXTURE14" value="0x84CE"/>
+ <enum name="TEXTURE15" value="0x84CF"/>
+ <enum name="TEXTURE16" value="0x84D0"/>
+ <enum name="TEXTURE17" value="0x84D1"/>
+ <enum name="TEXTURE18" value="0x84D2"/>
+ <enum name="TEXTURE19" value="0x84D3"/>
+ <enum name="TEXTURE20" value="0x84D4"/>
+ <enum name="TEXTURE21" value="0x84D5"/>
+ <enum name="TEXTURE22" value="0x84D6"/>
+ <enum name="TEXTURE23" value="0x84D7"/>
+ <enum name="TEXTURE24" value="0x84D8"/>
+ <enum name="TEXTURE25" value="0x84D9"/>
+ <enum name="TEXTURE26" value="0x84DA"/>
+ <enum name="TEXTURE27" value="0x84DB"/>
+ <enum name="TEXTURE28" value="0x84DC"/>
+ <enum name="TEXTURE29" value="0x84DD"/>
+ <enum name="TEXTURE30" value="0x84DE"/>
+ <enum name="TEXTURE31" value="0x84DF"/>
+ <enum name="NUM_COMPRESSED_TEXTURE_FORMATS" count="1" value="0x86A2">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="COMPRESSED_TEXTURE_FORMATS" count="-1" value="0x86A3">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="ActiveTexture" offset="374">
+ <param name="texture" type="GLenum"/>
+ <glx rop="197"/>
+ </function>
+
+ <function name="CompressedTexImage2D" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="imageSize" type="GLsizei" counter="true"/>
+ <param name="data" type="const GLvoid *" count="imageSize"/>
+ <glx rop="215" handcode="client"/>
+ </function>
+
+ <function name="CompressedTexSubImage2D" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="imageSize" type="GLsizei" counter="true"/>
+ <param name="data" type="const GLvoid *" count="imageSize"/>
+ <glx rop="218" handcode="client"/>
+ </function>
+
+ <function name="SampleCoverage" offset="assign">
+ <param name="value" type="GLclampf"/>
+ <param name="invert" type="GLboolean"/>
+ <glx rop="229"/>
+ </function>
+</category>
+
+<!-- base subset of OpenGL 1.0 -->
+<category name="base1.0">
+ <!-- addition to base1.0es -->
+ <enum name="LINE_WIDTH" count="1" value="0x0B21">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="CULL_FACE_MODE" count="1" value="0x0B45">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FRONT_FACE" count="1" value="0x0B46">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DEPTH_RANGE" count="2" value="0x0B70">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DEPTH_WRITEMASK" count="1" value="0x0B72">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DEPTH_CLEAR_VALUE" count="1" value="0x0B73">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DEPTH_FUNC" count="1" value="0x0B74">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_CLEAR_VALUE" count="1" value="0x0B91">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_FUNC" count="1" value="0x0B92">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_VALUE_MASK" count="1" value="0x0B93">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_FAIL" count="1" value="0x0B94">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_PASS_DEPTH_FAIL" count="1" value="0x0B95">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_PASS_DEPTH_PASS" count="1" value="0x0B96">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_REF" count="1" value="0x0B97">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_WRITEMASK" count="1" value="0x0B98">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="VIEWPORT" count="4" value="0x0BA2">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SCISSOR_BOX" count="4" value="0x0C10">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="COLOR_CLEAR_VALUE" count="4" value="0x0C22">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="COLOR_WRITEMASK" count="4" value="0x0C23">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="TexParameterfv" offset="179">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="106"/>
+ </function>
+
+ <function name="TexParameteri" offset="180">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="107"/>
+ </function>
+
+ <function name="TexParameteriv" offset="181">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="108"/>
+ </function>
+
+ <function name="GetBooleanv" offset="258">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLboolean *" output="true" variable_param="pname"/>
+ <glx sop="112" handcode="client"/>
+ </function>
+
+ <function name="GetFloatv" offset="262">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="116" handcode="client"/>
+ </function>
+
+ <function name="GetTexParameterfv" offset="282">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="136"/>
+ </function>
+
+ <function name="GetTexParameteriv" offset="283">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="137"/>
+ </function>
+
+ <function name="IsEnabled" offset="286">
+ <param name="cap" type="GLenum"/>
+ <return type="GLboolean"/>
+ <glx sop="140" handcode="client"/>
+ </function>
+</category>
+
+<!-- base subset of OpenGL 1.1 -->
+<category name="base1.1">
+ <!-- addition to base1.1es -->
+ <enum name="POLYGON_OFFSET_UNITS" count="1" value="0x2A00">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="POLYGON_OFFSET_FACTOR" count="1" value="0x8038">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_BINDING_2D" count="1" value="0x8069">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="IsTexture" offset="330">
+ <param name="texture" type="GLuint"/>
+ <return type="GLboolean"/>
+ <glx sop="146"/>
+ </function>
+</category>
+
+<!-- base subset of OpenGL 1.2 -->
+<category name="base1.2">
+ <!-- addition to base1.2es -->
+ <!-- No new functions, types, enums. -->
+</category>
+
+<!-- base subset of OpenGL 1.3 -->
+<category name="base1.3">
+ <!-- addition to base1.3es -->
+ <enum name="SAMPLE_BUFFERS" count="1" value="0x80A8">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SAMPLES" count="1" value="0x80A9">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SAMPLE_COVERAGE_VALUE" count="1" value="0x80AA">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SAMPLE_COVERAGE_INVERT" count="1" value="0x80AB">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="ACTIVE_TEXTURE" count="1" value="0x84E0">
+ <size name="Get" mode="get"/>
+ </enum>
+</category>
+
+<!-- base subset of OpenGL 1.4 -->
+<category name="base1.4">
+ <enum name="GENERATE_MIPMAP_HINT" value="0x8192"/>
+</category>
+
+<!-- base subset of OpenGL 1.5 -->
+<category name="base1.5">
+ <enum name="BUFFER_SIZE" value="0x8764"/>
+ <enum name="BUFFER_USAGE" value="0x8765"/>
+ <enum name="ARRAY_BUFFER" value="0x8892"/>
+ <enum name="ELEMENT_ARRAY_BUFFER" value="0x8893"/>
+ <enum name="ARRAY_BUFFER_BINDING" value="0x8894"/>
+ <enum name="ELEMENT_ARRAY_BUFFER_BINDING" value="0x8895"/>
+ <enum name="STATIC_DRAW" value="0x88E4"/>
+ <enum name="DYNAMIC_DRAW" value="0x88E8"/>
+
+ <type name="intptr" size="4" glx_name="CARD32"/>
+ <type name="sizeiptr" size="4" glx_name="CARD32"/>
+
+ <function name="BindBuffer" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="buffer" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="BufferData" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="size" type="GLsizeiptr" counter="true"/>
+ <param name="data" type="const GLvoid *" count="size" img_null_flag="true"/>
+ <param name="usage" type="GLenum"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="BufferSubData" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="offset" type="GLintptr"/>
+ <param name="size" type="GLsizeiptr" counter="true"/>
+ <param name="data" type="const GLvoid *" count="size"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="DeleteBuffers" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="buffer" type="const GLuint *" count="n"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GenBuffers" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="buffer" type="GLuint *" output="true" count="n"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetBufferParameteriv" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="IsBuffer" offset="assign">
+ <param name="buffer" type="GLuint"/>
+ <return type="GLboolean"/>
+ <glx ignore="true"/>
+ </function>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/base2_API.xml b/src/mesa/es/glapi/base2_API.xml
new file mode 100644
index 0000000000..6aa43b728a
--- /dev/null
+++ b/src/mesa/es/glapi/base2_API.xml
@@ -0,0 +1,533 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<!-- OpenGL and OpenGL ES 2.x APIs -->
+
+<OpenGLAPI>
+
+<xi:include href="base1_API.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<!-- base subset of OpenGL 2.0 -->
+<category name="base2.0">
+ <enum name="BLEND_EQUATION_RGB" count="1" value="0x8009"> <!-- same as BLEND_EQUATION -->
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="VERTEX_ATTRIB_ARRAY_ENABLED" count="1" value="0x8622">
+ <size name="GetVertexAttribdv" mode="get"/>
+ <size name="GetVertexAttribfv" mode="get"/>
+ <size name="GetVertexAttribiv" mode="get"/>
+ </enum>
+ <enum name="VERTEX_ATTRIB_ARRAY_SIZE" count="1" value="0x8623">
+ <size name="GetVertexAttribdv" mode="get"/>
+ <size name="GetVertexAttribfv" mode="get"/>
+ <size name="GetVertexAttribiv" mode="get"/>
+ </enum>
+ <enum name="VERTEX_ATTRIB_ARRAY_STRIDE" count="1" value="0x8624">
+ <size name="GetVertexAttribdv" mode="get"/>
+ <size name="GetVertexAttribfv" mode="get"/>
+ <size name="GetVertexAttribiv" mode="get"/>
+ </enum>
+ <enum name="VERTEX_ATTRIB_ARRAY_TYPE" count="1" value="0x8625">
+ <size name="GetVertexAttribdv" mode="get"/>
+ <size name="GetVertexAttribfv" mode="get"/>
+ <size name="GetVertexAttribiv" mode="get"/>
+ </enum>
+ <enum name="CURRENT_VERTEX_ATTRIB" count="1" value="0x8626">
+ <size name="GetVertexAttribdv" mode="get"/>
+ <size name="GetVertexAttribfv" mode="get"/>
+ <size name="GetVertexAttribiv" mode="get"/>
+ </enum>
+ <enum name="VERTEX_ATTRIB_ARRAY_POINTER" value="0x8645"/>
+ <enum name="STENCIL_BACK_FUNC" count="1" value="0x8800">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_BACK_FAIL" count="1" value="0x8801">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_BACK_PASS_DEPTH_FAIL" count="1" value="0x8802">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="STENCIL_BACK_PASS_DEPTH_PASS" count="1" value="0x8803">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_EQUATION_ALPHA" count="1" value="0x883D">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_VERTEX_ATTRIBS" count="1" value="0x8869">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="VERTEX_ATTRIB_ARRAY_NORMALIZED" value="0x886A"/>
+ <enum name="MAX_TEXTURE_IMAGE_UNITS" count="1" value="0x8872">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FRAGMENT_SHADER" value="0x8B30"/>
+ <enum name="VERTEX_SHADER" value="0x8B31"/>
+ <enum name="MAX_VERTEX_TEXTURE_IMAGE_UNITS" value="0x8B4C"/>
+ <enum name="MAX_COMBINED_TEXTURE_IMAGE_UNITS" value="0x8B4D"/>
+ <enum name="SHADER_TYPE" value="0x8B4F"/>
+ <enum name="FLOAT_VEC2" value="0x8B50"/>
+ <enum name="FLOAT_VEC3" value="0x8B51"/>
+ <enum name="FLOAT_VEC4" value="0x8B52"/>
+ <enum name="INT_VEC2" value="0x8B53"/>
+ <enum name="INT_VEC3" value="0x8B54"/>
+ <enum name="INT_VEC4" value="0x8B55"/>
+ <enum name="BOOL" value="0x8B56"/>
+ <enum name="BOOL_VEC2" value="0x8B57"/>
+ <enum name="BOOL_VEC3" value="0x8B58"/>
+ <enum name="BOOL_VEC4" value="0x8B59"/>
+ <enum name="FLOAT_MAT2" value="0x8B5A"/>
+ <enum name="FLOAT_MAT3" value="0x8B5B"/>
+ <enum name="FLOAT_MAT4" value="0x8B5C"/>
+ <enum name="SAMPLER_2D" value="0x8B5E"/>
+ <enum name="SAMPLER_CUBE" value="0x8B60"/>
+ <enum name="DELETE_STATUS" value="0x8B80"/>
+ <enum name="COMPILE_STATUS" value="0x8B81"/>
+ <enum name="LINK_STATUS" value="0x8B82"/>
+ <enum name="VALIDATE_STATUS" value="0x8B83"/>
+ <enum name="INFO_LOG_LENGTH" value="0x8B84"/>
+ <enum name="ATTACHED_SHADERS" value="0x8B85"/>
+ <enum name="ACTIVE_UNIFORMS" value="0x8B86"/>
+ <enum name="ACTIVE_UNIFORM_MAX_LENGTH" value="0x8B87"/>
+ <enum name="SHADER_SOURCE_LENGTH" value="0x8B88"/>
+ <enum name="ACTIVE_ATTRIBUTES" value="0x8B89"/>
+ <enum name="ACTIVE_ATTRIBUTE_MAX_LENGTH" value="0x8B8A"/>
+ <enum name="SHADING_LANGUAGE_VERSION" value="0x8B8C"/>
+ <enum name="CURRENT_PROGRAM" value="0x8B8D"/>
+ <enum name="STENCIL_BACK_REF" value="0x8CA3"/>
+ <enum name="STENCIL_BACK_VALUE_MASK" value="0x8CA4"/>
+ <enum name="STENCIL_BACK_WRITEMASK" value="0x8CA5"/>
+
+ <type name="char" size="1" glx_name="CARD8"/>
+
+ <function name="AttachShader" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="shader" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="BindAttribLocation" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="index" type="GLuint"/>
+ <param name="name" type="const GLchar *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="BlendEquationSeparate" offset="assign">
+ <param name="modeRGB" type="GLenum"/>
+ <param name="modeA" type="GLenum"/>
+ <glx rop="4228"/>
+ </function>
+
+ <function name="CompileShader" offset="assign">
+ <param name="shader" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="CreateProgram" offset="assign">
+ <return type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="CreateShader" offset="assign">
+ <param name="type" type="GLenum"/>
+ <return type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="DeleteProgram" offset="assign">
+ <param name="program" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="DeleteShader" offset="assign">
+ <param name="program" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="DetachShader" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="shader" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="DisableVertexAttribArray" offset="assign">
+ <param name="index" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="EnableVertexAttribArray" offset="assign">
+ <param name="index" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetActiveAttrib" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="index" type="GLuint"/>
+ <param name="bufSize" type="GLsizei "/>
+ <param name="length" type="GLsizei *" output="true"/>
+ <param name="size" type="GLint *" output="true"/>
+ <param name="type" type="GLenum *" output="true"/>
+ <param name="name" type="GLchar *" output="true"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetActiveUniform" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="index" type="GLuint"/>
+ <param name="bufSize" type="GLsizei"/>
+ <param name="length" type="GLsizei *" output="true"/>
+ <param name="size" type="GLint *" output="true"/>
+ <param name="type" type="GLenum *" output="true"/>
+ <param name="name" type="GLchar *" output="true"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetAttachedShaders" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="maxCount" type="GLsizei"/>
+ <param name="count" type="GLsizei *" output="true"/>
+ <param name="obj" type="GLuint *" output="true"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetAttribLocation" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="name" type="const GLchar *"/>
+ <return type="GLint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetProgramiv" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetProgramInfoLog" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="bufSize" type="GLsizei"/>
+ <param name="length" type="GLsizei *"/>
+ <param name="infoLog" type="GLchar *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetShaderiv" offset="assign">
+ <param name="shader" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetShaderInfoLog" offset="assign">
+ <param name="shader" type="GLuint"/>
+ <param name="bufSize" type="GLsizei"/>
+ <param name="length" type="GLsizei *"/>
+ <param name="infoLog" type="GLchar *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetShaderSource" offset="assign">
+ <param name="shader" type="GLuint"/>
+ <param name="bufSize" type="GLsizei"/>
+ <param name="length" type="GLsizei *" output="true"/>
+ <param name="source" type="GLchar *" output="true"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetUniformfv" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="location" type="GLint"/>
+ <param name="params" type="GLfloat *" output="true"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetUniformiv" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="location" type="GLint"/>
+ <param name="params" type="GLint *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetUniformLocation" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="name" type="const GLchar *"/>
+ <return type="GLint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetVertexAttribfv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetVertexAttribiv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="GetVertexAttribPointerv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="pointer" type="GLvoid **" output="true"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="IsProgram" offset="assign">
+ <param name="program" type="GLuint"/>
+ <return type="GLboolean"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="IsShader" offset="assign">
+ <param name="shader" type="GLuint"/>
+ <return type="GLboolean"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="LinkProgram" offset="assign">
+ <param name="program" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="ShaderSource" offset="assign">
+ <param name="shader" type="GLuint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="string" type="const GLchar **"/>
+ <param name="length" type="const GLint *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="StencilFuncSeparate" offset="assign">
+ <param name="face" type="GLenum"/>
+ <param name="func" type="GLenum"/>
+ <param name="ref" type="GLint"/>
+ <param name="mask" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="StencilOpSeparate" offset="assign">
+ <param name="face" type="GLenum"/>
+ <param name="sfail" type="GLenum"/>
+ <param name="zfail" type="GLenum"/>
+ <param name="zpass" type="GLenum"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="StencilMaskSeparate" offset="assign">
+ <param name="face" type="GLenum"/>
+ <param name="mask" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform1f" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="v0" type="GLfloat"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform1fv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="value" type="const GLfloat *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform1i" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="v0" type="GLint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform1iv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="value" type="const GLint *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform2f" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="v0" type="GLfloat"/>
+ <param name="v1" type="GLfloat"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform2fv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="value" type="const GLfloat *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform2i" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="v0" type="GLint"/>
+ <param name="v1" type="GLint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform2iv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="value" type="const GLint *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform3f" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="v0" type="GLfloat"/>
+ <param name="v1" type="GLfloat"/>
+ <param name="v2" type="GLfloat"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform3fv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="value" type="const GLfloat *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform3i" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="v0" type="GLint"/>
+ <param name="v1" type="GLint"/>
+ <param name="v2" type="GLint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform3iv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="value" type="const GLint *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform4f" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="v0" type="GLfloat"/>
+ <param name="v1" type="GLfloat"/>
+ <param name="v2" type="GLfloat"/>
+ <param name="v3" type="GLfloat"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform4fv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="value" type="const GLfloat *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform4i" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="v0" type="GLint"/>
+ <param name="v1" type="GLint"/>
+ <param name="v2" type="GLint"/>
+ <param name="v3" type="GLint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="Uniform4iv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="value" type="const GLint *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="UniformMatrix2fv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="transpose" type="GLboolean"/>
+ <param name="value" type="const GLfloat *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="UniformMatrix3fv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="transpose" type="GLboolean"/>
+ <param name="value" type="const GLfloat *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="UniformMatrix4fv" offset="assign">
+ <param name="location" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="transpose" type="GLboolean"/>
+ <param name="value" type="const GLfloat *"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="UseProgram" offset="assign">
+ <param name="program" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="ValidateProgram" offset="assign">
+ <param name="program" type="GLuint"/>
+ <glx ignore="true"/>
+ </function>
+
+ <function name="VertexAttrib1f" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="x" type="GLfloat"/>
+ </function>
+
+ <function name="VertexAttrib1fv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="v" type="const GLfloat *"/>
+ </function>
+
+ <function name="VertexAttrib2f" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ </function>
+
+ <function name="VertexAttrib2fv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="v" type="const GLfloat *"/>
+ </function>
+
+ <function name="VertexAttrib3f" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ </function>
+
+ <function name="VertexAttrib3fv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="v" type="const GLfloat *"/>
+ </function>
+
+ <function name="VertexAttrib4f" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <param name="w" type="GLfloat"/>
+ </function>
+
+ <function name="VertexAttrib4fv" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="v" type="const GLfloat *"/>
+ </function>
+
+ <function name="VertexAttribPointer" offset="assign">
+ <param name="index" type="GLuint"/>
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="normalized" type="GLboolean"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ </function>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/es1_API.xml b/src/mesa/es/glapi/es1_API.xml
new file mode 100644
index 0000000000..4ecd99e9c1
--- /dev/null
+++ b/src/mesa/es/glapi/es1_API.xml
@@ -0,0 +1,1100 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<!-- OpenGL ES 1.x API -->
+
+<OpenGLAPI>
+
+<xi:include href="base1_API.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<!-- subset of OpenGL 1.3 defined by OpenGL ES 1.0 -->
+<category name="es1.0core">
+ <!-- addition to base1.0es -->
+ <enum name="ADD" value="0x0104"/>
+ <enum name="STACK_OVERFLOW" value="0x0503"/>
+ <enum name="STACK_UNDERFLOW" value="0x0504"/>
+ <enum name="EXP" value="0x0800"/>
+ <enum name="EXP2" value="0x0801"/>
+ <enum name="POINT_SMOOTH" count="1" value="0x0B10">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LINE_SMOOTH" count="1" value="0x0B20">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHTING" count="1" value="0x0B50">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHT_MODEL_TWO_SIDE" count="1" value="0x0B52">
+ <size name="LightModelfv"/>
+ <size name="LightModeliv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHT_MODEL_AMBIENT" count="4" value="0x0B53">
+ <size name="LightModelfv"/>
+ <size name="LightModeliv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="COLOR_MATERIAL" count="1" value="0x0B57">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FOG" count="1" value="0x0B60">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FOG_DENSITY" count="1" value="0x0B62">
+ <size name="Fogfv"/>
+ <size name="Fogiv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FOG_START" count="1" value="0x0B63">
+ <size name="Fogfv"/>
+ <size name="Fogiv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FOG_END" count="1" value="0x0B64">
+ <size name="Fogfv"/>
+ <size name="Fogiv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FOG_MODE" count="1" value="0x0B65">
+ <size name="Fogfv"/>
+ <size name="Fogiv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FOG_COLOR" count="4" value="0x0B66">
+ <size name="Fogfv"/>
+ <size name="Fogiv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="NORMALIZE" count="1" value="0x0BA1">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="ALPHA_TEST" count="1" value="0x0BC0">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="PERSPECTIVE_CORRECTION_HINT" count="1" value="0x0C50">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="POINT_SMOOTH_HINT" count="1" value="0x0C51">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LINE_SMOOTH_HINT" count="1" value="0x0C52">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="POLYGON_SMOOTH_HINT" count="1" value="0x0C53">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FOG_HINT" count="1" value="0x0C54">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_LIGHTS" count="1" value="0x0D31">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_MODELVIEW_STACK_DEPTH" count="1" value="0x0D36">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_PROJECTION_STACK_DEPTH" count="1" value="0x0D38">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_TEXTURE_STACK_DEPTH" count="1" value="0x0D39">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="AMBIENT" count="4" value="0x1200">
+ <size name="Materialfv"/>
+ <size name="Materialiv"/>
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetMaterialfv" mode="get"/>
+ <size name="GetMaterialiv" mode="get"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="DIFFUSE" count="4" value="0x1201">
+ <size name="Materialfv"/>
+ <size name="Materialiv"/>
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetMaterialfv" mode="get"/>
+ <size name="GetMaterialiv" mode="get"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="SPECULAR" count="4" value="0x1202">
+ <size name="Materialfv"/>
+ <size name="Materialiv"/>
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetMaterialfv" mode="get"/>
+ <size name="GetMaterialiv" mode="get"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="POSITION" count="4" value="0x1203">
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="SPOT_DIRECTION" count="3" value="0x1204">
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="SPOT_EXPONENT" count="1" value="0x1205">
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="SPOT_CUTOFF" count="1" value="0x1206">
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="CONSTANT_ATTENUATION" count="1" value="0x1207">
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="LINEAR_ATTENUATION" count="1" value="0x1208">
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="QUADRATIC_ATTENUATION" count="1" value="0x1209">
+ <size name="Lightfv"/>
+ <size name="Lightiv"/>
+ <size name="GetLightfv" mode="get"/>
+ <size name="GetLightiv" mode="get"/>
+ </enum>
+ <enum name="CLEAR" value="0x1500"/>
+ <enum name="AND" value="0x1501"/>
+ <enum name="AND_REVERSE" value="0x1502"/>
+ <enum name="COPY" value="0x1503"/>
+ <enum name="AND_INVERTED" value="0x1504"/>
+ <enum name="NOOP" value="0x1505"/>
+ <enum name="XOR" value="0x1506"/>
+ <enum name="OR" value="0x1507"/>
+ <enum name="NOR" value="0x1508"/>
+ <enum name="EQUIV" value="0x1509"/>
+ <enum name="OR_REVERSE" value="0x150B"/>
+ <enum name="COPY_INVERTED" value="0x150C"/>
+ <enum name="OR_INVERTED" value="0x150D"/>
+ <enum name="NAND" value="0x150E"/>
+ <enum name="SET" value="0x150F"/>
+ <enum name="EMISSION" count="4" value="0x1600">
+ <size name="Materialfv"/>
+ <size name="Materialiv"/>
+ <size name="GetMaterialfv" mode="get"/>
+ <size name="GetMaterialiv" mode="get"/>
+ </enum>
+ <enum name="SHININESS" count="1" value="0x1601">
+ <size name="Materialfv"/>
+ <size name="Materialiv"/>
+ <size name="GetMaterialfv" mode="get"/>
+ <size name="GetMaterialiv" mode="get"/>
+ </enum>
+ <enum name="AMBIENT_AND_DIFFUSE" count="4" value="0x1602">
+ <size name="Materialfv"/>
+ <size name="Materialiv"/>
+ <size name="GetMaterialfv" mode="get"/>
+ <size name="GetMaterialiv" mode="get"/>
+ </enum>
+ <enum name="MODELVIEW" value="0x1700"/>
+ <enum name="PROJECTION" value="0x1701"/>
+ <enum name="FLAT" value="0x1D00"/>
+ <enum name="SMOOTH" value="0x1D01"/>
+ <enum name="MODULATE" value="0x2100"/>
+ <enum name="DECAL" value="0x2101"/>
+ <enum name="TEXTURE_ENV_MODE" count="1" value="0x2200">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_ENV_COLOR" count="4" value="0x2201">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_ENV" value="0x2300"/>
+ <enum name="LIGHT0" count="1" value="0x4000">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHT1" count="1" value="0x4001">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHT2" count="1" value="0x4002">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHT3" count="1" value="0x4003">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHT4" count="1" value="0x4004">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHT5" count="1" value="0x4005">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHT6" count="1" value="0x4006">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LIGHT7" count="1" value="0x4007">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="AlphaFunc" offset="240">
+ <param name="func" type="GLenum"/>
+ <param name="ref" type="GLclampf"/>
+ <glx rop="159"/>
+ </function>
+
+ <function name="Color4f" offset="29" vectorequiv="Color4fv">
+ <param name="red" type="GLfloat"/>
+ <param name="green" type="GLfloat"/>
+ <param name="blue" type="GLfloat"/>
+ <param name="alpha" type="GLfloat"/>
+ </function>
+
+ <function name="Fogf" offset="153">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="80"/>
+ </function>
+
+ <function name="Fogfv" offset="154">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="81"/>
+ </function>
+
+ <function name="Lightf" offset="159">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="86"/>
+ </function>
+
+ <function name="Lightfv" offset="160">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="87"/>
+ </function>
+
+ <function name="LightModelf" offset="163">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="90"/>
+ </function>
+
+ <function name="LightModelfv" offset="164">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="91"/>
+ </function>
+
+ <function name="LoadIdentity" offset="290">
+ <glx rop="176"/>
+ </function>
+
+ <function name="LoadMatrixf" offset="291">
+ <param name="m" type="const GLfloat *" count="16"/>
+ <glx rop="177"/>
+ </function>
+
+ <function name="LogicOp" offset="242">
+ <param name="opcode" type="GLenum"/>
+ <glx rop="161"/>
+ </function>
+
+ <function name="Materialf" offset="169">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="96"/>
+ </function>
+
+ <function name="Materialfv" offset="170">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="97"/>
+ </function>
+
+ <function name="MatrixMode" offset="293">
+ <param name="mode" type="GLenum"/>
+ <glx rop="179"/>
+ </function>
+
+ <function name="MultMatrixf" offset="294">
+ <param name="m" type="const GLfloat *" count="16"/>
+ <glx rop="180"/>
+ </function>
+
+ <function name="Normal3f" offset="56" vectorequiv="Normal3fv">
+ <param name="nx" type="GLfloat"/>
+ <param name="ny" type="GLfloat"/>
+ <param name="nz" type="GLfloat"/>
+ </function>
+
+ <function name="PointSize" offset="173">
+ <param name="size" type="GLfloat"/>
+ <glx rop="100"/>
+ </function>
+
+ <function name="PopMatrix" offset="297">
+ <glx rop="183"/>
+ </function>
+
+ <function name="PushMatrix" offset="298">
+ <glx rop="184"/>
+ </function>
+
+ <function name="Rotatef" offset="300">
+ <param name="angle" type="GLfloat"/>
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <glx rop="186"/>
+ </function>
+
+ <function name="Scalef" offset="302">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <glx rop="188"/>
+ </function>
+
+ <function name="ShadeModel" offset="177">
+ <param name="mode" type="GLenum"/>
+ <glx rop="104"/>
+ </function>
+
+ <function name="TexEnvf" offset="184">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="111"/>
+ </function>
+
+ <function name="TexEnvfv" offset="185">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="112"/>
+ </function>
+
+ <function name="TexImage2D" offset="183">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_format="format" img_type="type" img_target="target" img_send_null="true" img_pad_dimensions="true"/>
+ <glx rop="110" large="true"/>
+ </function>
+
+ <function name="Translatef" offset="304">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <glx rop="190"/>
+ </function>
+
+ <!-- addition to base1.1es -->
+ <enum name="COLOR_LOGIC_OP" value="0x0BF2"/>
+ <enum name="VERTEX_ARRAY" count="1" value="0x8074">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="NORMAL_ARRAY" count="1" value="0x8075">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="COLOR_ARRAY" count="1" value="0x8076">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_COORD_ARRAY" count="1" value="0x8078">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="ColorPointer" offset="308">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="DisableClientState" offset="309">
+ <param name="array" type="GLenum"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="EnableClientState" offset="313">
+ <param name="array" type="GLenum"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="NormalPointer" offset="318">
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="TexCoordPointer" offset="320">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="VertexPointer" offset="321">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <!-- addition to base1.2es -->
+ <enum name="SMOOTH_POINT_SIZE_RANGE" count="2" value="0x0B12">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SMOOTH_LINE_WIDTH_RANGE" count="2" value="0x0B22">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="RESCALE_NORMAL" count="1" value="0x803A">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_ELEMENTS_VERTICES" count="1" value="0x80E8">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_ELEMENTS_INDICES" count="1" value="0x80E9">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <!-- addition to base1.3es -->
+ <enum name="MULTISAMPLE" count="1" value="0x809D">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SAMPLE_ALPHA_TO_ONE" count="1" value="0x809F">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_TEXTURE_UNITS" count="1" value="0x84E2">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="ClientActiveTexture" offset="375">
+ <param name="texture" type="GLenum"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="MultiTexCoord4f" offset="402" vectorequiv="MultiTexCoord4fv">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLfloat"/>
+ <param name="t" type="GLfloat"/>
+ <param name="r" type="GLfloat"/>
+ <param name="q" type="GLfloat"/>
+ </function>
+</category>
+
+<!-- subset of OpenGL 1.5 defined by OpenGL ES 1.1 -->
+<category name="es1.1core">
+ <!-- addition to base1.0 -->
+ <enum name="CURRENT_COLOR" count="4" value="0x0B00">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="CURRENT_NORMAL" count="3" value="0x0B02">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="CURRENT_TEXTURE_COORDS" count="4" value="0x0B03">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="POINT_SIZE" count="1" value="0x0B11">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SHADE_MODEL" count="1" value="0x0B54">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MATRIX_MODE" count="1" value="0x0BA0">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MODELVIEW_STACK_DEPTH" count="1" value="0x0BA3">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="PROJECTION_STACK_DEPTH" count="1" value="0x0BA4">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_STACK_DEPTH" count="1" value="0x0BA5">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MODELVIEW_MATRIX" count="16" value="0x0BA6">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="PROJECTION_MATRIX" count="16" value="0x0BA7">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_MATRIX" count="16" value="0x0BA8">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="ALPHA_TEST_FUNC" count="1" value="0x0BC1">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="ALPHA_TEST_REF" count="1" value="0x0BC2">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_DST" count="1" value="0x0BE0">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_SRC" count="1" value="0x0BE1">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="LOGIC_OP_MODE" count="1" value="0x0BF0">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="ALPHA_SCALE" count="1" value="0x0D1C">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_CLIP_PLANES" count="1" value="0x0D32">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="CLIP_PLANE0" count="1" value="0x3000">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="CLIP_PLANE1" count="1" value="0x3001">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="CLIP_PLANE2" count="1" value="0x3002">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="CLIP_PLANE3" count="1" value="0x3003">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="CLIP_PLANE4" count="1" value="0x3004">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="CLIP_PLANE5" count="1" value="0x3005">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="Color4ub" offset="35" vectorequiv="Color4ubv">
+ <param name="red" type="GLubyte"/>
+ <param name="green" type="GLubyte"/>
+ <param name="blue" type="GLubyte"/>
+ <param name="alpha" type="GLubyte"/>
+ </function>
+
+ <function name="GetLightfv" offset="264">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="118"/>
+ </function>
+
+ <function name="GetMaterialfv" offset="269">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="123"/>
+ </function>
+
+ <function name="GetTexEnvfv" offset="276">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="130"/>
+ </function>
+
+ <function name="GetTexEnviv" offset="277">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="131"/>
+ </function>
+
+ <function name="TexEnvi" offset="186">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="113"/>
+ </function>
+
+ <function name="TexEnviv" offset="187">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="114"/>
+ </function>
+
+ <!-- addition to base1.1 -->
+ <enum name="VERTEX_ARRAY_SIZE" count="1" value="0x807A">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="VERTEX_ARRAY_TYPE" count="1" value="0x807B">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="VERTEX_ARRAY_STRIDE" count="1" value="0x807C">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="NORMAL_ARRAY_TYPE" count="1" value="0x807E">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="NORMAL_ARRAY_STRIDE" count="1" value="0x807F">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="COLOR_ARRAY_SIZE" count="1" value="0x8081">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="COLOR_ARRAY_TYPE" count="1" value="0x8082">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="COLOR_ARRAY_STRIDE" count="1" value="0x8083">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_COORD_ARRAY_SIZE" count="1" value="0x8088">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_COORD_ARRAY_TYPE" count="1" value="0x8089">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_COORD_ARRAY_STRIDE" count="1" value="0x808A">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="VERTEX_ARRAY_POINTER" value="0x808E"/>
+ <enum name="NORMAL_ARRAY_POINTER" value="0x808F"/>
+ <enum name="COLOR_ARRAY_POINTER" value="0x8090"/>
+ <enum name="TEXTURE_COORD_ARRAY_POINTER" value="0x8092"/>
+
+ <function name="GetPointerv" offset="329">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLvoid **" output="true"/>
+ <glx handcode="true"/>
+ </function>
+
+ <!-- addition to base1.2 -->
+
+ <!-- addition to base1.3 -->
+ <enum name="CLIENT_ACTIVE_TEXTURE" count="1" value="0x84E1">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="SUBTRACT" value="0x84E7"/>
+ <enum name="COMBINE" value="0x8570"/>
+ <enum name="COMBINE_RGB" count="1" value="0x8571">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="COMBINE_ALPHA" count="1" value="0x8572">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="RGB_SCALE" count="1" value="0x8573">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="ADD_SIGNED" value="0x8574"/>
+ <enum name="INTERPOLATE" value="0x8575"/>
+ <enum name="CONSTANT" value="0x8576"/>
+ <enum name="PRIMARY_COLOR" value="0x8577"/>
+ <enum name="PREVIOUS" value="0x8578"/>
+ <enum name="OPERAND0_RGB" count="1" value="0x8590">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="OPERAND1_RGB" count="1" value="0x8591">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="OPERAND2_RGB" count="1" value="0x8592">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="OPERAND0_ALPHA" count="1" value="0x8598">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="OPERAND1_ALPHA" count="1" value="0x8599">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="OPERAND2_ALPHA" count="1" value="0x859A">
+ <size name="TexEnvfv"/>
+ <size name="TexEnviv"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ <size name="GetTexEnviv" mode="get"/>
+ </enum>
+ <enum name="DOT3_RGB" value="0x86AE"/>
+ <enum name="DOT3_RGBA" value="0x86AF"/>
+
+ <!-- addition to base1.4 -->
+ <enum name="POINT_SIZE_MIN" count="1" value="0x8126">
+ <size name="PointParameterfv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="POINT_SIZE_MAX" count="1" value="0x8127">
+ <size name="PointParameterfv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="POINT_FADE_THRESHOLD_SIZE" count="1" value="0x8128">
+ <size name="PointParameterfv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="POINT_DISTANCE_ATTENUATION" count="3" value="0x8129">
+ <size name="PointParameterfv"/>
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="GENERATE_MIPMAP" count="1" value="0x8191">
+ <size name="TexParameterfv"/>
+ <size name="TexParameteriv"/>
+ <size name="GetTexParameterfv" mode="get"/>
+ <size name="GetTexParameteriv" mode="get"/>
+ </enum>
+
+ <function name="PointParameterf" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="2065"/>
+ </function>
+
+ <function name="PointParameterfv" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="2066"/>
+ </function>
+
+ <!-- addition to base1.5 -->
+ <enum name="SRC0_RGB" value="0x8580"/>
+ <enum name="SRC1_RGB" value="0x8581"/>
+ <enum name="SRC2_RGB" value="0x8582"/>
+ <enum name="SRC0_ALPHA" value="0x8588"/>
+ <enum name="SRC1_ALPHA" value="0x8589"/>
+ <enum name="SRC2_ALPHA" value="0x858A"/>
+ <enum name="VERTEX_ARRAY_BUFFER_BINDING" count="1" value="0x8896">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="NORMAL_ARRAY_BUFFER_BINDING" count="1" value="0x8897">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="COLOR_ARRAY_BUFFER_BINDING" count="1" value="0x8898">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_COORD_ARRAY_BUFFER_BINDING" count="1" value="0x889A">
+ <size name="Get" mode="get"/>
+ </enum>
+</category>
+
+<!-- OpenGL ES 1.0 -->
+<category name="es1.0">
+ <!-- addition to es1.0core -->
+
+ <!-- from GL_OES_fixed_point -->
+ <enum name="FIXED" value="0x140C"/>
+
+ <type name="fixed" size="4" />
+ <type name="clampx" size="4" />
+
+ <function name="AlphaFuncx" offset="assign">
+ <param name="func" type="GLenum"/>
+ <param name="ref" type="GLclampx"/>
+ </function>
+
+ <function name="ClearColorx" offset="assign">
+ <param name="red" type="GLclampx"/>
+ <param name="green" type="GLclampx"/>
+ <param name="blue" type="GLclampx"/>
+ <param name="alpha" type="GLclampx"/>
+ </function>
+
+ <function name="ClearDepthx" offset="assign">
+ <param name="depth" type="GLclampx"/>
+ </function>
+
+ <function name="Color4x" offset="assign">
+ <param name="red" type="GLfixed"/>
+ <param name="green" type="GLfixed"/>
+ <param name="blue" type="GLfixed"/>
+ <param name="alpha" type="GLfixed"/>
+ </function>
+
+ <function name="DepthRangex" offset="assign">
+ <param name="zNear" type="GLclampx"/>
+ <param name="zFar" type="GLclampx"/>
+ </function>
+
+ <function name="Fogx" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="Fogxv" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="Frustumx" offset="assign">
+ <param name="left" type="GLfixed"/>
+ <param name="right" type="GLfixed"/>
+ <param name="bottom" type="GLfixed"/>
+ <param name="top" type="GLfixed"/>
+ <param name="zNear" type="GLfixed"/>
+ <param name="zFar" type="GLfixed"/>
+ </function>
+
+ <function name="LightModelx" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="LightModelxv" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="Lightx" offset="assign">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="Lightxv" offset="assign">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="LineWidthx" offset="assign">
+ <param name="width" type="GLfixed"/>
+ </function>
+
+ <function name="LoadMatrixx" offset="assign">
+ <param name="m" type="const GLfixed *" count="16"/>
+ </function>
+
+ <function name="Materialx" offset="assign">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="Materialxv" offset="assign">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="MultMatrixx" offset="assign">
+ <param name="m" type="const GLfixed *" count="16"/>
+ </function>
+
+ <function name="MultiTexCoord4x" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLfixed"/>
+ <param name="t" type="GLfixed"/>
+ <param name="r" type="GLfixed"/>
+ <param name="q" type="GLfixed"/>
+ </function>
+
+ <function name="Normal3x" offset="assign">
+ <param name="nx" type="GLfixed"/>
+ <param name="ny" type="GLfixed"/>
+ <param name="nz" type="GLfixed"/>
+ </function>
+
+ <function name="Orthox" offset="assign">
+ <param name="left" type="GLfixed"/>
+ <param name="right" type="GLfixed"/>
+ <param name="bottom" type="GLfixed"/>
+ <param name="top" type="GLfixed"/>
+ <param name="zNear" type="GLfixed"/>
+ <param name="zFar" type="GLfixed"/>
+ </function>
+
+ <function name="PointSizex" offset="assign">
+ <param name="size" type="GLfixed"/>
+ </function>
+
+ <function name="PolygonOffsetx" offset="assign">
+ <param name="factor" type="GLfixed"/>
+ <param name="units" type="GLfixed"/>
+ </function>
+
+ <function name="Rotatex" offset="assign">
+ <param name="angle" type="GLfixed"/>
+ <param name="x" type="GLfixed"/>
+ <param name="y" type="GLfixed"/>
+ <param name="z" type="GLfixed"/>
+ </function>
+
+ <function name="SampleCoveragex" offset="assign">
+ <param name="value" type="GLclampx"/>
+ <param name="invert" type="GLboolean"/>
+ </function>
+
+ <function name="Scalex" offset="assign">
+ <param name="x" type="GLfixed"/>
+ <param name="y" type="GLfixed"/>
+ <param name="z" type="GLfixed"/>
+ </function>
+
+ <function name="TexEnvx" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="TexEnvxv" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="TexParameterx" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="Translatex" offset="assign">
+ <param name="x" type="GLfixed"/>
+ <param name="y" type="GLfixed"/>
+ <param name="z" type="GLfixed"/>
+ </function>
+
+ <!-- from GL_OES_single_precision -->
+ <function name="ClearDepthf" offset="assign">
+ <param name="depth" type="GLclampf"/>
+ </function>
+
+ <function name="DepthRangef" offset="assign">
+ <param name="zNear" type="GLclampf"/>
+ <param name="zFar" type="GLclampf"/>
+ </function>
+
+ <function name="Frustumf" offset="assign">
+ <param name="left" type="GLfloat"/>
+ <param name="right" type="GLfloat"/>
+ <param name="bottom" type="GLfloat"/>
+ <param name="top" type="GLfloat"/>
+ <param name="zNear" type="GLfloat"/>
+ <param name="zFar" type="GLfloat"/>
+ </function>
+
+ <function name="Orthof" offset="assign">
+ <param name="left" type="GLfloat"/>
+ <param name="right" type="GLfloat"/>
+ <param name="bottom" type="GLfloat"/>
+ <param name="top" type="GLfloat"/>
+ <param name="zNear" type="GLfloat"/>
+ <param name="zFar" type="GLfloat"/>
+ </function>
+</category>
+
+<!-- OpenGL ES 1.1 -->
+<category name="es1.1">
+ <!-- addition to es1.1core -->
+
+ <!-- from GL_OES_fixed_point -->
+ <function name="ClipPlanex" offset="assign">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="const GLfixed *" count="4"/>
+ </function>
+
+ <function name="GetClipPlanex" offset="assign">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="GLfixed *" output="true" count="4"/>
+ </function>
+
+ <function name="GetFixedv" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="GetLightxv" offset="assign">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="GetMaterialxv" offset="assign">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="GetTexEnvxv" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="GetTexParameterxv" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="PointParameterx" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="PointParameterxv" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *"/>
+ </function>
+
+ <function name="TexParameterxv" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <!-- from GL_OES_matrix_get -->
+ <enum name="MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES" value="0x898D"/>
+ <enum name="PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES" value="0x898E"/>
+ <enum name="TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES" value="0x898F"/>
+
+ <!-- from GL_OES_single_precision -->
+ <function name="ClipPlanef" offset="assign">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="const GLfloat *" count="4"/>
+ </function>
+
+ <function name="GetClipPlanef" offset="assign">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="GLfloat *" output="true" count="4"/>
+ </function>
+</category>
+
+<xi:include href="es1_EXT.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+<xi:include href="es1_COMPAT.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/es1_COMPAT.xml b/src/mesa/es/glapi/es1_COMPAT.xml
new file mode 100644
index 0000000000..305a645223
--- /dev/null
+++ b/src/mesa/es/glapi/es1_COMPAT.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<OpenGLAPI>
+
+<xi:include href="es_COMPAT.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<!-- these functions are also missing in es1_API.xml or es1_EXT.xml -->
+<category name="es1compat">
+ <!-- OpenGL 1.0 -->
+ <function name="TexGenf" alias="TexGenfOES" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="117"/>
+ </function>
+
+ <function name="TexGenfv" alias="TexGenfvOES" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="118"/>
+ </function>
+
+ <function name="TexGeni" alias="TexGeniOES" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="119"/>
+ </function>
+
+ <function name="TexGeniv" alias="TexGenivOES" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="120"/>
+ </function>
+
+ <function name="GetTexGenfv" alias="GetTexGenfvOES" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="133"/>
+ </function>
+
+ <function name="GetTexGeniv" alias="GetTexGenivOES" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="134"/>
+ </function>
+
+ <!-- OpenGL 1.2 -->
+ <function name="BlendColor" offset="336" static_dispatch="false">
+ <param name="red" type="GLclampf"/>
+ <param name="green" type="GLclampf"/>
+ <param name="blue" type="GLclampf"/>
+ <param name="alpha" type="GLclampf"/>
+ <glx rop="4096"/>
+ </function>
+
+ <function name="BlendEquation" alias="BlendEquationOES" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="4097"/>
+ </function>
+
+ <function name="TexImage3D" offset="371" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_depth="depth" img_format="format" img_type="type" img_target="target" img_null_flag="true" img_pad_dimensions="true"/>
+ <glx rop="4114" large="true"/>
+ </function>
+
+ <function name="TexSubImage3D" offset="372" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="UNUSED" type="GLuint" padding="true"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_depth="depth" img_xoff="xoffset" img_yoff="yoffset" img_zoff="zoffset" img_format="format" img_type="type" img_target="target" img_pad_dimensions="true"/>
+ <glx rop="4115" large="true"/>
+ </function>
+
+ <function name="CopyTexSubImage3D" offset="373" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="4123"/>
+ </function>
+
+ <!-- GL_ARB_multitexture -->
+ <function name="ActiveTextureARB" alias="ActiveTexture" static_dispatch="false">
+ <param name="texture" type="GLenum"/>
+ <glx rop="197"/>
+ </function>
+
+ <function name="ClientActiveTextureARB" alias="ClientActiveTexture" static_dispatch="false">
+ <param name="texture" type="GLenum"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="MultiTexCoord4fARB" alias="MultiTexCoord4f" vectorequiv="MultiTexCoord4fvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLfloat"/>
+ <param name="t" type="GLfloat"/>
+ <param name="r" type="GLfloat"/>
+ <param name="q" type="GLfloat"/>
+ </function>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/es1_EXT.xml b/src/mesa/es/glapi/es1_EXT.xml
new file mode 100644
index 0000000000..7c7c585736
--- /dev/null
+++ b/src/mesa/es/glapi/es1_EXT.xml
@@ -0,0 +1,693 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<!-- OpenGL ES 1.x extensions -->
+
+<OpenGLAPI>
+
+<xi:include href="es_EXT.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<!-- part of es1.1 extension pack -->
+<category name="GL_OES_blend_equation_separate" number="1">
+ <enum name="BLEND_EQUATION_RGB_OES" count="1" value="0x8009">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_EQUATION_ALPHA_OES" count="1" value="0x883D">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="BlendEquationSeparateOES" offset="assign">
+ <param name="modeRGB" type="GLenum"/>
+ <param name="modeA" type="GLenum"/>
+ <glx rop="4228"/>
+ </function>
+</category>
+
+<!-- part of es1.1 extension pack -->
+<category name="GL_OES_blend_func_separate" number="2">
+ <enum name="BLEND_DST_RGB_OES" count="1" value="0x80C8">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_SRC_RGB_OES" count="1" value="0x80C9">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_DST_ALPHA_OES" count="1" value="0x80CA">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_SRC_ALPHA_OES" count="1" value="0x80CB">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <function name="BlendFuncSeparateOES" offset="assign">
+ <param name="sfactorRGB" type="GLenum"/>
+ <param name="dfactorRGB" type="GLenum"/>
+ <param name="sfactorAlpha" type="GLenum"/>
+ <param name="dfactorAlpha" type="GLenum"/>
+ <glx rop="4134"/>
+ </function>
+</category>
+
+<!-- part of es1.1 extension pack -->
+<category name="GL_OES_blend_subtract" number="3">
+ <enum name="FUNC_ADD_OES" value="0x8006"/>
+ <enum name="BLEND_EQUATION_OES" count="1" value="0x8009">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FUNC_SUBTRACT_OES" value="0x800A"/>
+ <enum name="FUNC_REVERSE_SUBTRACT_OES" value="0x800B"/>
+
+ <function name="BlendEquationOES" offset="337">
+ <param name="mode" type="GLenum"/>
+ <glx rop="4097"/>
+ </function>
+</category>
+
+<!-- core addition to es1.0 and later -->
+<category name="GL_OES_byte_coordinates" number="4">
+ <enum name="BYTE" value="0x1400"/>
+</category>
+
+<!-- optional for es1.1 -->
+<category name="GL_OES_draw_texture" number="7">
+ <enum name="TEXTURE_CROP_RECT_OES" value="0x8B9D"/>
+
+ <function name="DrawTexiOES" offset="assign">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="z" type="GLint"/>
+ <param name="width" type="GLint"/>
+ <param name="height" type="GLint"/>
+ </function>
+
+ <function name="DrawTexivOES" offset="assign">
+ <param name="coords" type="const GLint *" count="5"/>
+ </function>
+
+ <function name="DrawTexfOES" offset="assign">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <param name="width" type="GLfloat"/>
+ <param name="height" type="GLfloat"/>
+ </function>
+
+ <function name="DrawTexfvOES" offset="assign">
+ <param name="coords" type="const GLfloat *" count="5"/>
+ </function>
+
+ <function name="DrawTexsOES" offset="assign">
+ <param name="x" type="GLshort"/>
+ <param name="y" type="GLshort"/>
+ <param name="z" type="GLshort"/>
+ <param name="width" type="GLshort"/>
+ <param name="height" type="GLshort"/>
+ </function>
+
+ <function name="DrawTexsvOES" offset="assign">
+ <param name="coords" type="const GLshort *" count="5"/>
+ </function>
+
+ <function name="DrawTexxOES" offset="assign">
+ <param name="x" type="GLfixed"/>
+ <param name="y" type="GLfixed"/>
+ <param name="z" type="GLfixed"/>
+ <param name="width" type="GLfixed"/>
+ <param name="height" type="GLfixed"/>
+ </function>
+
+ <function name="DrawTexxvOES" offset="assign">
+ <param name="coords" type="const GLfixed *" count="5"/>
+ </function>
+
+ <!-- TexParameter{ifx}v is skipped here -->
+</category>
+
+<!-- core addition to es1.0 and later -->
+<category name="GL_OES_fixed_point" number="9">
+ <enum name="FIXED_OES" value="0x140C"/>
+
+ <!-- additon to es1.0 -->
+ <function name="AlphaFuncxOES" alias="AlphaFuncx">
+ <param name="func" type="GLenum"/>
+ <param name="ref" type="GLclampx"/>
+ </function>
+
+ <function name="ClearColorxOES" alias="ClearColorx">
+ <param name="red" type="GLclampx"/>
+ <param name="green" type="GLclampx"/>
+ <param name="blue" type="GLclampx"/>
+ <param name="alpha" type="GLclampx"/>
+ </function>
+
+ <function name="ClearDepthxOES" alias="ClearDepthx">
+ <param name="depth" type="GLclampx"/>
+ </function>
+
+ <function name="Color4xOES" alias="Color4x">
+ <param name="red" type="GLfixed"/>
+ <param name="green" type="GLfixed"/>
+ <param name="blue" type="GLfixed"/>
+ <param name="alpha" type="GLfixed"/>
+ </function>
+
+ <function name="DepthRangexOES" alias="DepthRangex">
+ <param name="zNear" type="GLclampx"/>
+ <param name="zFar" type="GLclampx"/>
+ </function>
+
+ <function name="FogxOES" alias="Fogx">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="FogxvOES" alias="Fogxv">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="FrustumxOES" alias="Frustumx">
+ <param name="left" type="GLfixed"/>
+ <param name="right" type="GLfixed"/>
+ <param name="bottom" type="GLfixed"/>
+ <param name="top" type="GLfixed"/>
+ <param name="zNear" type="GLfixed"/>
+ <param name="zFar" type="GLfixed"/>
+ </function>
+
+ <function name="LightModelxOES" alias="LightModelx">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="LightModelxvOES" alias="LightModelxv">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="LightxOES" alias="Lightx">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="LightxvOES" alias="Lightxv">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="LineWidthxOES" alias="LineWidthx">
+ <param name="width" type="GLfixed"/>
+ </function>
+
+ <function name="LoadMatrixxOES" alias="LoadMatrixx">
+ <param name="m" type="const GLfixed *" count="16"/>
+ </function>
+
+ <function name="MaterialxOES" alias="Materialx">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="MaterialxvOES" alias="Materialxv">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="MultiTexCoord4xOES" alias="MultiTexCoord4x">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLfixed"/>
+ <param name="t" type="GLfixed"/>
+ <param name="r" type="GLfixed"/>
+ <param name="q" type="GLfixed"/>
+ </function>
+
+ <function name="MultMatrixxOES" alias="MultMatrixx">
+ <param name="m" type="const GLfixed *" count="16"/>
+ </function>
+
+ <function name="Normal3xOES" alias="Normal3x">
+ <param name="nx" type="GLfixed"/>
+ <param name="ny" type="GLfixed"/>
+ <param name="nz" type="GLfixed"/>
+ </function>
+
+ <function name="OrthoxOES" alias="Orthox">
+ <param name="left" type="GLfixed"/>
+ <param name="right" type="GLfixed"/>
+ <param name="bottom" type="GLfixed"/>
+ <param name="top" type="GLfixed"/>
+ <param name="zNear" type="GLfixed"/>
+ <param name="zFar" type="GLfixed"/>
+ </function>
+
+ <function name="PointSizexOES" alias="PointSizex">
+ <param name="size" type="GLfixed"/>
+ </function>
+
+ <function name="PolygonOffsetxOES" alias="PolygonOffsetx">
+ <param name="factor" type="GLfixed"/>
+ <param name="units" type="GLfixed"/>
+ </function>
+
+ <function name="RotatexOES" alias="Rotatex">
+ <param name="angle" type="GLfixed"/>
+ <param name="x" type="GLfixed"/>
+ <param name="y" type="GLfixed"/>
+ <param name="z" type="GLfixed"/>
+ </function>
+
+ <function name="SampleCoveragexOES" alias="SampleCoveragex">
+ <param name="value" type="GLclampx"/>
+ <param name="invert" type="GLboolean"/>
+ </function>
+
+ <function name="ScalexOES" alias="Scalex">
+ <param name="x" type="GLfixed"/>
+ <param name="y" type="GLfixed"/>
+ <param name="z" type="GLfixed"/>
+ </function>
+
+ <function name="TexEnvxOES" alias="TexEnvx">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="TexEnvxvOES" alias="TexEnvxv">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+
+ <function name="TexParameterxOES" alias="TexParameterx">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="TranslatexOES" alias="Translatex">
+ <param name="x" type="GLfixed"/>
+ <param name="y" type="GLfixed"/>
+ <param name="z" type="GLfixed"/>
+ </function>
+
+ <!-- additon to es1.1 -->
+ <function name="ClipPlanexOES" alias="ClipPlanex">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="const GLfixed *" count="4"/>
+ </function>
+
+ <function name="GetClipPlanexOES" alias="GetClipPlanex">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="GLfixed *" output="true" count="4"/>
+ </function>
+
+ <function name="GetFixedvOES" alias="GetFixedv">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="GetLightxvOES" alias="GetLightxv">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="GetMaterialxvOES" alias="GetMaterialxv">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="GetTexEnvxvOES" alias="GetTexEnvxv">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="GetTexParameterxvOES" alias="GetTexParameterxv">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="PointParameterxOES" alias="PointParameterx">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfixed"/>
+ </function>
+
+ <function name="PointParameterxvOES" alias="PointParameterxv">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *"/>
+ </function>
+
+ <function name="TexParameterxvOES" alias="TexParameterxv">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+</category>
+
+<!-- part of es1.1 extension pack -->
+<category name="GL_OES_framebuffer_object" number="10">
+ <enum name="NONE_OES" value="0"/>
+ <enum name="INVALID_FRAMEBUFFER_OPERATION_OES" value="0x0506"/>
+ <enum name="RGBA4_OES" value="0x8056"/>
+ <enum name="RGB5_A1_OES" value="0x8057"/>
+ <enum name="DEPTH_COMPONENT16_OES" value="0x81A5"/>
+
+ <enum name="MAX_RENDERBUFFER_SIZE_OES" value="0x84E8"/>
+ <enum name="FRAMEBUFFER_BINDING_OES" value="0x8CA6"/>
+ <enum name="RENDERBUFFER_BINDING_OES" value="0x8CA7"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES" value="0x8CD0"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES" value="0x8CD1"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES" value="0x8CD2"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES" value="0x8CD3"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES" value="0x8CD4"/>
+ <enum name="FRAMEBUFFER_COMPLETE_OES" value="0x8CD5"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES" value="0x8CD6"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES" value="0x8CD7"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES" value="0x8CD9"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_FORMATS_OES" value="0x8CDA"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES" value="0x8CDB"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES" value="0x8CDC"/>
+ <enum name="FRAMEBUFFER_UNSUPPORTED_OES" value="0x8CDD"/>
+ <enum name="COLOR_ATTACHMENT0_OES" value="0x8CE0"/>
+ <enum name="DEPTH_ATTACHMENT_OES" value="0x8D00"/>
+ <enum name="STENCIL_ATTACHMENT_OES" value="0x8D20"/>
+ <enum name="FRAMEBUFFER_OES" value="0x8D40"/>
+ <enum name="RENDERBUFFER_OES" value="0x8D41"/>
+ <enum name="RENDERBUFFER_WIDTH_OES" value="0x8D42"/>
+ <enum name="RENDERBUFFER_HEIGHT_OES" value="0x8D43"/>
+ <enum name="RENDERBUFFER_INTERNAL_FORMAT_OES" value="0x8D44"/>
+ <enum name="STENCIL_INDEX1_OES" value="0x8D46"/>
+ <enum name="STENCIL_INDEX4_OES" value="0x8D47"/>
+ <enum name="STENCIL_INDEX8_OES" value="0x8D48"/>
+ <enum name="RENDERBUFFER_RED_SIZE_OES" value="0x8D50"/>
+ <enum name="RENDERBUFFER_GREEN_SIZE_OES" value="0x8D51"/>
+ <enum name="RENDERBUFFER_BLUE_SIZE_OES" value="0x8D52"/>
+ <enum name="RENDERBUFFER_ALPHA_SIZE_OES" value="0x8D53"/>
+ <enum name="RENDERBUFFER_DEPTH_SIZE_OES" value="0x8D54"/>
+ <enum name="RENDERBUFFER_STENCIL_SIZE_OES" value="0x8D55"/>
+ <enum name="RGB565_OES" value="0x8D62"/>
+
+ <function name="BindFramebufferOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="framebuffer" type="GLuint"/>
+ </function>
+
+ <function name="BindRenderbufferOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="renderbuffer" type="GLuint"/>
+ </function>
+
+ <function name="CheckFramebufferStatusOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <return type="GLenum"/>
+ </function>
+
+ <function name="DeleteFramebuffersOES" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="framebuffers" type="const GLuint *" count="n"/>
+ </function>
+
+ <function name="DeleteRenderbuffersOES" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="renderbuffers" type="const GLuint *" count="n"/>
+ </function>
+
+ <function name="FramebufferRenderbufferOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="renderbuffertarget" type="GLenum"/>
+ <param name="renderbuffer" type="GLuint"/>
+ </function>
+
+ <function name="FramebufferTexture2DOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="textarget" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ </function>
+
+ <function name="GenerateMipmapOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ </function>
+
+ <function name="GenFramebuffersOES" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="framebuffers" type="GLuint *" count="n" output="true"/>
+ </function>
+
+ <function name="GenRenderbuffersOES" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="renderbuffers" type="GLuint *" count="n" output="true"/>
+ </function>
+
+ <function name="GetFramebufferAttachmentParameterivOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true"/>
+ </function>
+
+ <function name="GetRenderbufferParameterivOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true"/>
+ </function>
+
+ <function name="IsFramebufferOES" offset="assign">
+ <param name="framebuffer" type="GLuint"/>
+ <return type="GLboolean"/>
+ </function>
+
+ <function name="IsRenderbufferOES" offset="assign">
+ <param name="renderbuffer" type="GLuint"/>
+ <return type="GLboolean"/>
+ </function>
+
+ <function name="RenderbufferStorageOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ </function>
+</category>
+
+<!-- core addition to es1.1 -->
+<category name="GL_OES_matrix_get" number="11">
+ <enum name="MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES" value="0x898D"/>
+ <enum name="PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES" value="0x898E"/>
+ <enum name="TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES" value="0x898F"/>
+</category>
+
+<!-- optional for es1.1 -->
+<category name="GL_OES_matrix_palette" number="12">
+ <enum name="MAX_VERTEX_UNITS_OES" value="0x86A4"/>
+ <enum name="WEIGHT_ARRAY_TYPE_OES" value="0x86A9"/>
+ <enum name="WEIGHT_ARRAY_STRIDE_OES" value="0x86AA"/>
+ <enum name="WEIGHT_ARRAY_SIZE_OES" value="0x86AB"/>
+ <enum name="WEIGHT_ARRAY_POINTER_OES" value="0x86AC"/>
+ <enum name="WEIGHT_ARRAY_OES" value="0x86AD"/>
+ <enum name="MATRIX_PALETTE_OES" value="0x8840"/>
+ <enum name="MAX_PALETTE_MATRICES_OES" value="0x8842"/>
+ <enum name="CURRENT_PALETTE_MATRIX_OES" value="0x8843"/>
+ <enum name="MATRIX_INDEX_ARRAY_OES" value="0x8844"/>
+ <enum name="MATRIX_INDEX_ARRAY_SIZE_OES" value="0x8846"/>
+ <enum name="MATRIX_INDEX_ARRAY_TYPE_OES" value="0x8847"/>
+ <enum name="MATRIX_INDEX_ARRAY_STRIDE_OES" value="0x8848"/>
+ <enum name="MATRIX_INDEX_ARRAY_POINTER_OES" value="0x8849"/>
+ <enum name="WEIGHT_ARRAY_BUFFER_BINDING_OES" value="0x889E"/>
+ <enum name="MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES" value="0x8B9E"/>
+
+ <function name="CurrentPaletteMatrixOES">
+ <param name="matrixpaletteindex" type="GLuint"/>
+ </function>
+
+ <function name="LoadPaletteFromModelViewMatrixOES">
+ </function>
+
+ <function name="MatrixIndexPointerOES">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ </function>
+
+ <function name="WeightPointerOES">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ </function>
+</category>
+
+<!-- required for es1.1 -->
+<category name="GL_OES_point_size_array" number="14">
+ <enum name="POINT_SIZE_ARRAY_TYPE_OES" value="0x898A"/>
+ <enum name="POINT_SIZE_ARRAY_STRIDE_OES" value="0x898B"/>
+ <enum name="POINT_SIZE_ARRAY_POINTER_OES" value="0x898C"/>
+ <enum name="POINT_SIZE_ARRAY_OES" value="0x8B9C"/>
+ <enum name="POINT_SIZE_ARRAY_BUFFER_BINDING_OES" value="0x8B9F"/>
+
+ <function name="PointSizePointerOES" offset="assign">
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ </function>
+</category>
+
+<!-- required for es1.1 -->
+<category name="GL_OES_point_sprite" number="15">
+ <enum name="POINT_SPRITE_OES" value="0x8861"/>
+ <enum name="COORD_REPLACE_OES" value="0x8862"/>
+</category>
+
+<!-- optional for es1.0 -->
+<category name="GL_OES_query_matrix" number="16">
+ <function name="QueryMatrixxOES" offset="assign">
+ <param name="mantissa" type="GLfixed *" count="16" />
+ <param name="exponent" type="GLint *" count="16" />
+ <return type="GLbitfield"/>
+ </function>
+</category>
+
+<!-- required for es1.0 and later -->
+<category name="GL_OES_read_format" number="17">
+ <enum name="IMPLEMENTATION_COLOR_READ_TYPE_OES" value="0x8B9A"/>
+ <enum name="IMPLEMENTATION_COLOR_READ_FORMAT_OES" value="0x8B9B"/>
+</category>
+
+<!-- core addition to es1.0 and later -->
+<category name="GL_OES_single_precision" number="18">
+ <!-- additon to es1.0 -->
+ <function name="ClearDepthfOES" alias="ClearDepthf">
+ <param name="depth" type="GLclampf"/>
+ </function>
+
+ <function name="DepthRangefOES" alias="DepthRangef">
+ <param name="zNear" type="GLclampf"/>
+ <param name="zFar" type="GLclampf"/>
+ </function>
+
+ <function name="FrustumfOES" alias="Frustumf">
+ <param name="left" type="GLfloat"/>
+ <param name="right" type="GLfloat"/>
+ <param name="bottom" type="GLfloat"/>
+ <param name="top" type="GLfloat"/>
+ <param name="zNear" type="GLfloat"/>
+ <param name="zFar" type="GLfloat"/>
+ </function>
+
+ <function name="OrthofOES" alias="Orthof">
+ <param name="left" type="GLfloat"/>
+ <param name="right" type="GLfloat"/>
+ <param name="bottom" type="GLfloat"/>
+ <param name="top" type="GLfloat"/>
+ <param name="zNear" type="GLfloat"/>
+ <param name="zFar" type="GLfloat"/>
+ </function>
+
+ <!-- additon to es1.1 -->
+ <function name="ClipPlanefOES" alias="ClipPlanef">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="const GLfloat *" count="4"/>
+ </function>
+
+ <function name="GetClipPlanefOES" alias="GetClipPlanef">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="GLfloat *" output="true" count="4"/>
+ </function>
+</category>
+
+<!-- part of es1.1 extension pack -->
+<category name="GL_OES_texture_cube_map" number="20">
+ <enum name="GL_TEXTURE_GEN_MODE_OES" value="0x2500"/>
+ <enum name="GL_NORMAL_MAP_OES" value="0x8511"/>
+ <enum name="GL_REFLECTION_MAP_OES" value="0x8512"/>
+ <enum name="GL_TEXTURE_CUBE_MAP_OES" value="0x8513"/>
+ <enum name="GL_TEXTURE_BINDING_CUBE_MAP_OES" value="0x8514"/>
+ <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES" value="0x8515"/>
+ <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES" value="0x8516"/>
+ <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES" value="0x8517"/>
+ <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES" value="0x8518"/>
+ <enum name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES" value="0x8519"/>
+ <enum name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES" value="0x851A"/>
+ <enum name="GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES" value="0x851C"/>
+ <enum name="GL_TEXTURE_GEN_STR_OES" value="0x8D60"/>
+
+ <function name="GetTexGenfvOES" offset="279">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="133"/>
+ </function>
+
+ <function name="GetTexGenivOES" offset="280">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="134"/>
+ </function>
+
+ <function name="GetTexGenxvOES" offset="assign">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfixed *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="TexGenfOES" offset="190">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="117"/>
+ </function>
+
+ <function name="TexGenfvOES" offset="191">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="118"/>
+ </function>
+
+ <function name="TexGeniOES" offset="192">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="119"/>
+ </function>
+
+ <function name="TexGenivOES" offset="193">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="120"/>
+ </function>
+
+ <function name="TexGenxOES" offset="assign">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ </function>
+
+ <function name="TexGenxvOES" offset="assign">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfixed *" variable_param="pname"/>
+ </function>
+</category>
+
+<category name="GL_OES_texture_env_crossbar" number="21">
+ <!-- No new functions, types, enums. -->
+</category>
+
+<category name="GL_OES_texture_mirrored_repeat" number="22">
+ <!-- No new functions, types, enums. -->
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/es2_API.xml b/src/mesa/es/glapi/es2_API.xml
new file mode 100644
index 0000000000..ef5eb0b5da
--- /dev/null
+++ b/src/mesa/es/glapi/es2_API.xml
@@ -0,0 +1,294 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<!-- OpenGL ES 2.x API -->
+
+<OpenGLAPI>
+
+<xi:include href="base2_API.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<!-- subset of OpenGL 2.0 defined by OpenGL ES 2.0 -->
+<category name="es2.0core">
+ <!-- addition to base1.0 -->
+ <enum name="NONE" value="0x0"/>
+ <enum name="INT" count="4" value="0x1404">
+ <size name="CallLists"/>
+ </enum>
+ <enum name="UNSIGNED_INT" count="4" value="0x1405">
+ <size name="CallLists"/>
+ </enum>
+ <enum name="STENCIL_INDEX" value="0x1901"/>
+ <enum name="DEPTH_COMPONENT" value="0x1902"/>
+
+ <function name="TexImage2D" offset="183">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLint"/> <!-- XXX the actual type is GLenum... -->
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_format="format" img_type="type" img_target="target" img_send_null="true" img_pad_dimensions="true"/>
+ <glx rop="110" large="true"/>
+ </function>
+
+ <!-- addition to base1.1 -->
+ <enum name="RGBA4" value="0x8056"/>
+ <enum name="RGB5_A1" value="0x8057"/>
+
+ <!-- addition to base1.2 -->
+ <enum name="CONSTANT_COLOR" value="0x8001"/>
+ <enum name="ONE_MINUS_CONSTANT_COLOR" value="0x8002"/>
+ <enum name="CONSTANT_ALPHA" value="0x8003"/>
+ <enum name="ONE_MINUS_CONSTANT_ALPHA" value="0x8004"/>
+ <enum name="BLEND_COLOR" count="4" value="0x8005">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FUNC_ADD" value="0x8006"/>
+ <enum name="BLEND_EQUATION" count="1" value="0x8009">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="FUNC_SUBTRACT" value="0x800A"/>
+ <enum name="FUNC_REVERSE_SUBTRACT" value="0x800B"/>
+
+ <function name="BlendColor" offset="336">
+ <param name="red" type="GLclampf"/>
+ <param name="green" type="GLclampf"/>
+ <param name="blue" type="GLclampf"/>
+ <param name="alpha" type="GLclampf"/>
+ <glx rop="4096"/>
+ </function>
+
+ <function name="BlendEquation" offset="337">
+ <param name="mode" type="GLenum"/>
+ <glx rop="4097"/>
+ </function>
+
+ <!-- addition to base1.3 -->
+ <enum name="TEXTURE_CUBE_MAP" count="1" value="0x8513">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_BINDING_CUBE_MAP" count="1" value="0x8514">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_CUBE_MAP_POSITIVE_X" value="0x8515"/>
+ <enum name="TEXTURE_CUBE_MAP_NEGATIVE_X" value="0x8516"/>
+ <enum name="TEXTURE_CUBE_MAP_POSITIVE_Y" value="0x8517"/>
+ <enum name="TEXTURE_CUBE_MAP_NEGATIVE_Y" value="0x8518"/>
+ <enum name="TEXTURE_CUBE_MAP_POSITIVE_Z" value="0x8519"/>
+ <enum name="TEXTURE_CUBE_MAP_NEGATIVE_Z" value="0x851A"/>
+ <enum name="MAX_CUBE_MAP_TEXTURE_SIZE" count="1" value="0x851C">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <!-- addition to base1.4 -->
+ <enum name="BLEND_DST_RGB" count="1" value="0x80C8">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_SRC_RGB" count="1" value="0x80C9">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_DST_ALPHA" count="1" value="0x80CA">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="BLEND_SRC_ALPHA" count="1" value="0x80CB">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DEPTH_COMPONENT16" value="0x81A5"/>
+ <enum name="MIRRORED_REPEAT" value="0x8370"/>
+ <enum name="INCR_WRAP" value="0x8507"/>
+ <enum name="DECR_WRAP" value="0x8508"/>
+
+ <function name="BlendFuncSeparate" offset="assign">
+ <param name="sfactorRGB" type="GLenum"/>
+ <param name="dfactorRGB" type="GLenum"/>
+ <param name="sfactorAlpha" type="GLenum"/>
+ <param name="dfactorAlpha" type="GLenum"/>
+ <glx rop="4134"/>
+ </function>
+
+ <!-- addition to base1.5 -->
+ <enum name="VERTEX_ATTRIB_ARRAY_BUFFER_BINDING" count="1" value="0x889F">
+ <size name="GetVertexAttribdv" mode="get"/>
+ <size name="GetVertexAttribfv" mode="get"/>
+ <size name="GetVertexAttribiv" mode="get"/>
+ </enum>
+ <enum name="STREAM_DRAW" value="0x88E0"/>
+
+ <!-- addition to base2.0 -->
+ <!-- base2.0 should have everything defined -->
+</category>
+
+<!-- OpenGL ES 2.0 -->
+<category name="es2.0">
+ <!-- addition to es2.0core -->
+ <enum name="LOW_FLOAT" value="0x8DF0"/>
+ <enum name="MEDIUM_FLOAT" value="0x8DF1"/>
+ <enum name="HIGH_FLOAT" value="0x8DF2"/>
+ <enum name="LOW_INT" value="0x8DF3"/>
+ <enum name="MEDIUM_INT" value="0x8DF4"/>
+ <enum name="HIGH_INT" value="0x8DF5"/>
+ <enum name="SHADER_BINARY_FORMATS" value="0x8DF8"/>
+ <enum name="NUM_SHADER_BINARY_FORMATS" value="0x8DF9"/>
+ <enum name="SHADER_COMPILER" value="0x8DFA"/>
+ <enum name="MAX_VERTEX_UNIFORM_VECTORS" value="0x8DFB"/>
+ <enum name="MAX_VARYING_VECTORS" value="0x8DFC"/>
+ <enum name="MAX_FRAGMENT_UNIFORM_VECTORS" value="0x8DFD"/>
+
+ <function name="GetShaderPrecisionFormat" offset="assign">
+ <param name="shadertype" type="GLenum"/>
+ <param name="precisiontype" type="GLenum"/>
+ <param name="range" type="GLint *"/>
+ <param name="precision" type="GLint *"/>
+ </function>
+
+ <function name="ReleaseShaderCompiler" offset="assign">
+ </function>
+
+ <function name="ShaderBinary" offset="assign">
+ <param name="n" type="GLsizei"/>
+ <param name="shaders" type="const GLuint *"/>
+ <param name="binaryformat" type="GLenum"/>
+ <param name="binary" type="const GLvoid *"/>
+ <param name="length" type="GLsizei"/>
+ </function>
+
+ <!-- from GL_OES_fixed_point -->
+ <enum name="FIXED" value="0x140C"/>
+ <type name="fixed" size="4" />
+
+ <!-- from GL_OES_framebuffer_object -->
+ <enum name="INVALID_FRAMEBUFFER_OPERATION" value="0x0506"/>
+ <enum name="MAX_RENDERBUFFER_SIZE" value="0x84E8"/>
+ <enum name="FRAMEBUFFER_BINDING" value="0x8CA6"/>
+ <enum name="RENDERBUFFER_BINDING" value="0x8CA7"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE" value="0x8CD0"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_OBJECT_NAME" value="0x8CD1"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL" value="0x8CD2"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE" value="0x8CD3"/>
+ <enum name="FRAMEBUFFER_COMPLETE" value="0x8CD5"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_ATTACHMENT" value="0x8CD6"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" value="0x8CD7"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_DIMENSIONS" value="0x8CD9"/>
+ <enum name="FRAMEBUFFER_UNSUPPORTED" value="0x8CDD"/>
+ <enum name="COLOR_ATTACHMENT0" value="0x8CE0"/>
+ <enum name="DEPTH_ATTACHMENT" value="0x8D00"/>
+ <enum name="STENCIL_ATTACHMENT" value="0x8D20"/>
+ <enum name="FRAMEBUFFER" value="0x8D40"/>
+ <enum name="RENDERBUFFER" value="0x8D41"/>
+ <enum name="RENDERBUFFER_WIDTH" value="0x8D42"/>
+ <enum name="RENDERBUFFER_HEIGHT" value="0x8D43"/>
+ <enum name="RENDERBUFFER_INTERNAL_FORMAT" value="0x8D44"/>
+ <enum name="STENCIL_INDEX8" value="0x8D48"/>
+ <enum name="RENDERBUFFER_RED_SIZE" value="0x8D50"/>
+ <enum name="RENDERBUFFER_GREEN_SIZE" value="0x8D51"/>
+ <enum name="RENDERBUFFER_BLUE_SIZE" value="0x8D52"/>
+ <enum name="RENDERBUFFER_ALPHA_SIZE" value="0x8D53"/>
+ <enum name="RENDERBUFFER_DEPTH_SIZE" value="0x8D54"/>
+ <enum name="RENDERBUFFER_STENCIL_SIZE" value="0x8D55"/>
+ <enum name="RGB565" value="0x8D62"/>
+
+ <function name="BindFramebuffer" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="framebuffer" type="GLuint"/>
+ </function>
+
+ <function name="BindRenderbuffer" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="renderbuffer" type="GLuint"/>
+ </function>
+
+ <function name="CheckFramebufferStatus" offset="assign">
+ <param name="target" type="GLenum"/>
+ <return type="GLenum"/>
+ </function>
+
+ <function name="DeleteFramebuffers" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="framebuffers" type="const GLuint *" count="n"/>
+ </function>
+
+ <function name="DeleteRenderbuffers" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="renderbuffers" type="const GLuint *" count="n"/>
+ </function>
+
+ <function name="FramebufferRenderbuffer" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="renderbuffertarget" type="GLenum"/>
+ <param name="renderbuffer" type="GLuint"/>
+ </function>
+
+ <function name="FramebufferTexture2D" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="textarget" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ </function>
+
+ <function name="GenerateMipmap" offset="assign">
+ <param name="target" type="GLenum"/>
+ </function>
+
+ <function name="GenFramebuffers" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="framebuffers" type="GLuint *" count="n" output="true"/>
+ </function>
+
+ <function name="GenRenderbuffers" offset="assign">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="renderbuffers" type="GLuint *" count="n" output="true"/>
+ </function>
+
+ <function name="GetFramebufferAttachmentParameteriv" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true"/>
+ </function>
+
+ <function name="GetRenderbufferParameteriv" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true"/>
+ </function>
+
+ <function name="IsFramebuffer" offset="assign">
+ <param name="framebuffer" type="GLuint"/>
+ <return type="GLboolean"/>
+ </function>
+
+ <function name="IsRenderbuffer" offset="assign">
+ <param name="renderbuffer" type="GLuint"/>
+ <return type="GLboolean"/>
+ </function>
+
+ <function name="RenderbufferStorage" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ </function>
+
+ <!-- from GL_OES_read_format -->
+ <enum name="IMPLEMENTATION_COLOR_READ_TYPE" value="0x8B9A"/>
+ <enum name="IMPLEMENTATION_COLOR_READ_FORMAT" value="0x8B9B"/>
+
+ <!-- from GL_OES_single_precision -->
+ <function name="ClearDepthf" offset="assign">
+ <param name="depth" type="GLclampf"/>
+ </function>
+
+ <function name="DepthRangef" offset="assign">
+ <param name="zNear" type="GLclampf"/>
+ <param name="zFar" type="GLclampf"/>
+ </function>
+</category>
+
+<xi:include href="es2_EXT.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+<xi:include href="es2_COMPAT.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/es2_COMPAT.xml b/src/mesa/es/glapi/es2_COMPAT.xml
new file mode 100644
index 0000000000..a6bcf4d894
--- /dev/null
+++ b/src/mesa/es/glapi/es2_COMPAT.xml
@@ -0,0 +1,363 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<OpenGLAPI>
+
+<xi:include href="es_COMPAT.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<!-- these functions are also missing in es2_API.xml -->
+<category name="es2compat">
+ <!-- OpenGL 1.0 -->
+ <function name="Color4f" offset="29" vectorequiv="Color4fv" static_dispatch="false">
+ <param name="red" type="GLfloat"/>
+ <param name="green" type="GLfloat"/>
+ <param name="blue" type="GLfloat"/>
+ <param name="alpha" type="GLfloat"/>
+ </function>
+
+ <function name="Color4ub" offset="35" vectorequiv="Color4ubv" static_dispatch="false">
+ <param name="red" type="GLubyte"/>
+ <param name="green" type="GLubyte"/>
+ <param name="blue" type="GLubyte"/>
+ <param name="alpha" type="GLubyte"/>
+ </function>
+
+ <function name="Normal3f" offset="56" vectorequiv="Normal3fv" static_dispatch="false">
+ <param name="nx" type="GLfloat"/>
+ <param name="ny" type="GLfloat"/>
+ <param name="nz" type="GLfloat"/>
+ </function>
+
+ <function name="Fogf" offset="153" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="80"/>
+ </function>
+
+ <function name="Fogfv" offset="154" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="81"/>
+ </function>
+
+ <function name="Lightf" offset="159" static_dispatch="false">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="86"/>
+ </function>
+
+ <function name="Lightfv" offset="160" static_dispatch="false">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="87"/>
+ </function>
+
+ <function name="LightModelf" offset="163" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="90"/>
+ </function>
+
+ <function name="LightModelfv" offset="164" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="91"/>
+ </function>
+
+ <function name="Materialf" offset="169" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="96"/>
+ </function>
+
+ <function name="Materialfv" offset="170" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="97"/>
+ </function>
+
+ <function name="PointSize" offset="173" static_dispatch="false">
+ <param name="size" type="GLfloat"/>
+ <glx rop="100"/>
+ </function>
+
+ <function name="ShadeModel" offset="177" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="104"/>
+ </function>
+
+ <function name="TexEnvf" offset="184" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="111"/>
+ </function>
+
+ <function name="TexEnvfv" offset="185" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="112"/>
+ </function>
+
+ <function name="TexEnvi" offset="186" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="113"/>
+ </function>
+
+ <function name="TexEnviv" offset="187" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="114"/>
+ </function>
+
+ <function name="TexGenf" offset="190" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="117"/>
+ </function>
+
+ <function name="TexGenfv" offset="191" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="118"/>
+ </function>
+
+ <function name="TexGeni" offset="192" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="119"/>
+ </function>
+
+ <function name="TexGeniv" offset="193" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="120"/>
+ </function>
+
+ <function name="AlphaFunc" offset="240" static_dispatch="false">
+ <param name="func" type="GLenum"/>
+ <param name="ref" type="GLclampf"/>
+ <glx rop="159"/>
+ </function>
+
+ <function name="LogicOp" offset="242" static_dispatch="false">
+ <param name="opcode" type="GLenum"/>
+ <glx rop="161"/>
+ </function>
+
+ <function name="GetLightfv" offset="264" static_dispatch="false">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="118"/>
+ </function>
+
+ <function name="GetMaterialfv" offset="269" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="123"/>
+ </function>
+
+ <function name="GetTexEnvfv" offset="276" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="130"/>
+ </function>
+
+ <function name="GetTexEnviv" offset="277" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="131"/>
+ </function>
+
+ <function name="GetTexGenfv" offset="279" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="133"/>
+ </function>
+
+ <function name="GetTexGeniv" offset="280" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="134"/>
+ </function>
+
+ <function name="LoadIdentity" offset="290" static_dispatch="false">
+ <glx rop="176"/>
+ </function>
+
+ <function name="LoadMatrixf" offset="291" static_dispatch="false">
+ <param name="m" type="const GLfloat *" count="16"/>
+ <glx rop="177"/>
+ </function>
+
+ <function name="MatrixMode" offset="293" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="179"/>
+ </function>
+
+ <function name="MultMatrixf" offset="294" static_dispatch="false">
+ <param name="m" type="const GLfloat *" count="16"/>
+ <glx rop="180"/>
+ </function>
+
+ <function name="PopMatrix" offset="297" static_dispatch="false">
+ <glx rop="183"/>
+ </function>
+
+ <function name="PushMatrix" offset="298" static_dispatch="false">
+ <glx rop="184"/>
+ </function>
+
+ <function name="Rotatef" offset="300" static_dispatch="false">
+ <param name="angle" type="GLfloat"/>
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <glx rop="186"/>
+ </function>
+
+ <function name="Scalef" offset="302" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <glx rop="188"/>
+ </function>
+
+ <function name="Translatef" offset="304" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <glx rop="190"/>
+ </function>
+
+ <!-- OpenGL 1.1 -->
+ <function name="ColorPointer" offset="308" static_dispatch="false">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="DisableClientState" offset="309" static_dispatch="false">
+ <param name="array" type="GLenum"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="EnableClientState" offset="313" static_dispatch="false">
+ <param name="array" type="GLenum"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="NormalPointer" offset="318" static_dispatch="false">
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="TexCoordPointer" offset="320" static_dispatch="false">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="VertexPointer" offset="321" static_dispatch="false">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="GetPointerv" offset="329" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLvoid **" output="true"/>
+ <glx handcode="true"/>
+ </function>
+
+ <!-- OpenGL 1.2 -->
+ <function name="TexImage3D" alias="TexImage3DOES" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_depth="depth" img_format="format" img_type="type" img_target="target" img_null_flag="true" img_pad_dimensions="true"/>
+ <glx rop="4114" large="true"/>
+ </function>
+
+ <function name="TexSubImage3D" alias="TexSubImage3DOES" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="UNUSED" type="GLuint" padding="true"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_depth="depth" img_xoff="xoffset" img_yoff="yoffset" img_zoff="zoffset" img_format="format" img_type="type" img_target="target" img_pad_dimensions="true"/>
+ <glx rop="4115" large="true"/>
+ </function>
+
+ <function name="CopyTexSubImage3D" alias="CopyTexSubImage3DOES" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="4123"/>
+ </function>
+
+ <!-- GL_ARB_multitexture -->
+ <function name="ActiveTextureARB" alias="ActiveTexture" static_dispatch="false">
+ <param name="texture" type="GLenum"/>
+ <glx rop="197"/>
+ </function>
+
+ <function name="ClientActiveTextureARB" offset="375" static_dispatch="false">
+ <param name="texture" type="GLenum"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="MultiTexCoord4fARB" offset="402" vectorequiv="MultiTexCoord4fvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLfloat"/>
+ <param name="t" type="GLfloat"/>
+ <param name="r" type="GLfloat"/>
+ <param name="q" type="GLfloat"/>
+ </function>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/es2_EXT.xml b/src/mesa/es/glapi/es2_EXT.xml
new file mode 100644
index 0000000000..fef6368022
--- /dev/null
+++ b/src/mesa/es/glapi/es2_EXT.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<!-- OpenGL ES 2.x extensions -->
+
+<OpenGLAPI>
+
+<xi:include href="es_EXT.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<category name="GL_OES_texture_3D" number="34">
+ <enum name="TEXTURE_BINDING_3D_OES" value="0x806A"/>
+ <enum name="TEXTURE_3D_OES" value="0x806F"/>
+ <enum name="TEXTURE_WRAP_R_OES" value="0x8072"/>
+ <enum name="MAX_3D_TEXTURE_SIZE_OES" value="0x8073"/>
+ <enum name="SAMPLER_3D_OES" value="0x8B5F"/>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES" value="0x8CD4"/>
+
+ <function name="CompressedTexImage3DOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="imageSize" type="GLsizei" counter="true"/>
+ <param name="data" type="const GLvoid *" count="imageSize"/>
+ <glx rop="216" handcode="client"/>
+ </function>
+
+ <function name="CompressedTexSubImage3DOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="imageSize" type="GLsizei" counter="true"/>
+ <param name="data" type="const GLvoid *" count="imageSize"/>
+ <glx rop="219" handcode="client"/>
+ </function>
+
+ <function name="CopyTexSubImage3DOES" offset="373">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="4123"/>
+ </function>
+
+ <function name="FramebufferTexture3DOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="textarget" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <glx rop="4323"/>
+ </function>
+
+ <function name="TexImage3DOES" offset="371">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_depth="depth" img_format="format" img_type="type" img_target="target" img_null_flag="true" img_pad_dimensions="true"/>
+ <glx rop="4114" large="true"/>
+ </function>
+
+ <function name="TexSubImage3DOES" offset="372">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="UNUSED" type="GLuint" padding="true"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_depth="depth" img_xoff="xoffset" img_yoff="yoffset" img_zoff="zoffset" img_format="format" img_type="type" img_target="target" img_pad_dimensions="true"/>
+ <glx rop="4115" large="true"/>
+ </function>
+</category>
+
+<category name="GL_OES_texture_npot" number="37">
+ <!-- No new functions, types, enums. -->
+</category>
+
+<category name="GL_EXT_texture_type_2_10_10_10_REV" number="42">
+ <enum name="UNSIGNED_INT_2_10_10_10_REV_EXT" value="0x8368"/>
+</category>
+
+<category name="GL_OES_packed_depth_stencil" number="43">
+ <enum name="DEPTH_STENCIL_OES" value="0x84F9"/>
+ <enum name="UNSIGNED_INT_24_8_OES" value="0x84FA"/>
+ <enum name="DEPTH24_STENCIL8_OES" value="0x88F0"/>
+</category>
+
+<category name="GL_OES_depth_texture" number="44">
+ <!-- No new functions, types, enums. -->
+</category>
+
+<category name="GL_OES_standard_derivatives" number="45">
+ <enum name="FRAGMENT_SHADER_DERIVATIVE_HINT_OES" value="0x8B8B"/>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/es_COMPAT.xml b/src/mesa/es/glapi/es_COMPAT.xml
new file mode 100644
index 0000000000..6e3acaa66c
--- /dev/null
+++ b/src/mesa/es/glapi/es_COMPAT.xml
@@ -0,0 +1,2650 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<OpenGLAPI>
+
+<!-- This file defines the following categories
+
+ a subset of 1.0
+ a subset of 1.1
+ a subset of 1.2
+ a subset of GL_ARB_multitexture
+ GL_APPLE_vertex_array_object
+
+ to keep compatibility with Mesa. It is included by es1_COMPAT.xml
+ and es2_COMPAT.xml. When a function is later defined, it should be
+ commented out from this file. Take BlendEquation for example. It
+ is defined in OpenGL ES 2.0, and is defined as BlendEquationOES in
+ GL_OES_blend_subtract. Thus, it is commented out from this file,
+ and has an alias in es1_COMPAT.xml.
+-->
+
+<category name="1.0">
+ <type name="double" size="8" float="true" glx_name="FLOAT64"/>
+ <type name="clampd" size="8" float="true" glx_name="FLOAT64"/>
+
+ <type name="float" size="4" float="true" glx_name="FLOAT32"/>
+ <type name="clampf" size="4" float="true" glx_name="FLOAT32"/>
+
+ <type name="int" size="4" glx_name="CARD32"/>
+ <type name="uint" size="4" unsigned="true" glx_name="CARD32"/>
+ <type name="sizei" size="4" unsigned="true" glx_name="CARD32"/>
+ <type name="enum" size="4" unsigned="true" glx_name="ENUM"/>
+ <type name="bitfield" size="4" unsigned="true" glx_name="CARD32"/>
+
+ <type name="short" size="2" glx_name="CARD16"/>
+ <type name="ushort" size="2" unsigned="true" glx_name="CARD16"/>
+
+ <type name="byte" size="1" glx_name="CARD8"/>
+ <type name="ubyte" size="1" unsigned="true" glx_name="CARD8"/>
+ <type name="boolean" size="1" unsigned="true" glx_name="CARD8"/>
+
+ <type name="void" size="1"/>
+
+ <function name="NewList" offset="0" static_dispatch="false">
+ <param name="list" type="GLuint"/>
+ <param name="mode" type="GLenum"/>
+ <glx sop="101"/>
+ </function>
+
+ <function name="EndList" offset="1" static_dispatch="false">
+ <glx sop="102"/>
+ </function>
+
+ <function name="CallList" offset="2" static_dispatch="false">
+ <param name="list" type="GLuint"/>
+ <glx rop="1"/>
+ </function>
+
+ <function name="CallLists" offset="3" static_dispatch="false">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="type" type="GLenum"/>
+ <param name="lists" type="const GLvoid *" variable_param="type" count="n"/>
+ <glx rop="2" large="true"/>
+ </function>
+
+ <function name="DeleteLists" offset="4" static_dispatch="false">
+ <param name="list" type="GLuint"/>
+ <param name="range" type="GLsizei"/>
+ <glx sop="103"/>
+ </function>
+
+ <function name="GenLists" offset="5" static_dispatch="false">
+ <param name="range" type="GLsizei"/>
+ <return type="GLuint"/>
+ <glx sop="104"/>
+ </function>
+
+ <function name="ListBase" offset="6" static_dispatch="false">
+ <param name="base" type="GLuint"/>
+ <glx rop="3"/>
+ </function>
+
+ <function name="Begin" offset="7" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="4"/>
+ </function>
+
+ <function name="Bitmap" offset="8" static_dispatch="false">
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="xorig" type="GLfloat"/>
+ <param name="yorig" type="GLfloat"/>
+ <param name="xmove" type="GLfloat"/>
+ <param name="ymove" type="GLfloat"/>
+ <param name="bitmap" type="const GLubyte *" img_width="width" img_height="height" img_format="GL_COLOR_INDEX" img_type="GL_BITMAP" img_target="0" img_pad_dimensions="false"/>
+ <glx rop="5" large="true"/>
+ </function>
+
+ <function name="Color3b" offset="9" vectorequiv="Color3bv" static_dispatch="false">
+ <param name="red" type="GLbyte"/>
+ <param name="green" type="GLbyte"/>
+ <param name="blue" type="GLbyte"/>
+ </function>
+
+ <function name="Color3bv" offset="10" static_dispatch="false">
+ <param name="v" type="const GLbyte *" count="3"/>
+ <glx rop="6"/>
+ </function>
+
+ <function name="Color3d" offset="11" vectorequiv="Color3dv" static_dispatch="false">
+ <param name="red" type="GLdouble"/>
+ <param name="green" type="GLdouble"/>
+ <param name="blue" type="GLdouble"/>
+ </function>
+
+ <function name="Color3dv" offset="12" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="3"/>
+ <glx rop="7"/>
+ </function>
+
+ <function name="Color3f" offset="13" vectorequiv="Color3fv" static_dispatch="false">
+ <param name="red" type="GLfloat"/>
+ <param name="green" type="GLfloat"/>
+ <param name="blue" type="GLfloat"/>
+ </function>
+
+ <function name="Color3fv" offset="14" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="3"/>
+ <glx rop="8"/>
+ </function>
+
+ <function name="Color3i" offset="15" vectorequiv="Color3iv" static_dispatch="false">
+ <param name="red" type="GLint"/>
+ <param name="green" type="GLint"/>
+ <param name="blue" type="GLint"/>
+ </function>
+
+ <function name="Color3iv" offset="16" static_dispatch="false">
+ <param name="v" type="const GLint *" count="3"/>
+ <glx rop="9"/>
+ </function>
+
+ <function name="Color3s" offset="17" vectorequiv="Color3sv" static_dispatch="false">
+ <param name="red" type="GLshort"/>
+ <param name="green" type="GLshort"/>
+ <param name="blue" type="GLshort"/>
+ </function>
+
+ <function name="Color3sv" offset="18" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="3"/>
+ <glx rop="10"/>
+ </function>
+
+ <function name="Color3ub" offset="19" vectorequiv="Color3ubv" static_dispatch="false">
+ <param name="red" type="GLubyte"/>
+ <param name="green" type="GLubyte"/>
+ <param name="blue" type="GLubyte"/>
+ </function>
+
+ <function name="Color3ubv" offset="20" static_dispatch="false">
+ <param name="v" type="const GLubyte *" count="3"/>
+ <glx rop="11"/>
+ </function>
+
+ <function name="Color3ui" offset="21" vectorequiv="Color3uiv" static_dispatch="false">
+ <param name="red" type="GLuint"/>
+ <param name="green" type="GLuint"/>
+ <param name="blue" type="GLuint"/>
+ </function>
+
+ <function name="Color3uiv" offset="22" static_dispatch="false">
+ <param name="v" type="const GLuint *" count="3"/>
+ <glx rop="12"/>
+ </function>
+
+ <function name="Color3us" offset="23" vectorequiv="Color3usv" static_dispatch="false">
+ <param name="red" type="GLushort"/>
+ <param name="green" type="GLushort"/>
+ <param name="blue" type="GLushort"/>
+ </function>
+
+ <function name="Color3usv" offset="24" static_dispatch="false">
+ <param name="v" type="const GLushort *" count="3"/>
+ <glx rop="13"/>
+ </function>
+
+ <function name="Color4b" offset="25" vectorequiv="Color4bv" static_dispatch="false">
+ <param name="red" type="GLbyte"/>
+ <param name="green" type="GLbyte"/>
+ <param name="blue" type="GLbyte"/>
+ <param name="alpha" type="GLbyte"/>
+ </function>
+
+ <function name="Color4bv" offset="26" static_dispatch="false">
+ <param name="v" type="const GLbyte *" count="4"/>
+ <glx rop="14"/>
+ </function>
+
+ <function name="Color4d" offset="27" vectorequiv="Color4dv" static_dispatch="false">
+ <param name="red" type="GLdouble"/>
+ <param name="green" type="GLdouble"/>
+ <param name="blue" type="GLdouble"/>
+ <param name="alpha" type="GLdouble"/>
+ </function>
+
+ <function name="Color4dv" offset="28" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="4"/>
+ <glx rop="15"/>
+ </function>
+
+ <!--function name="Color4f" offset="29" vectorequiv="Color4fv" static_dispatch="false">
+ <param name="red" type="GLfloat"/>
+ <param name="green" type="GLfloat"/>
+ <param name="blue" type="GLfloat"/>
+ <param name="alpha" type="GLfloat"/>
+ </function-->
+
+ <function name="Color4fv" offset="30" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="4"/>
+ <glx rop="16"/>
+ </function>
+
+ <function name="Color4i" offset="31" vectorequiv="Color4iv" static_dispatch="false">
+ <param name="red" type="GLint"/>
+ <param name="green" type="GLint"/>
+ <param name="blue" type="GLint"/>
+ <param name="alpha" type="GLint"/>
+ </function>
+
+ <function name="Color4iv" offset="32" static_dispatch="false">
+ <param name="v" type="const GLint *" count="4"/>
+ <glx rop="17"/>
+ </function>
+
+ <function name="Color4s" offset="33" vectorequiv="Color4sv" static_dispatch="false">
+ <param name="red" type="GLshort"/>
+ <param name="green" type="GLshort"/>
+ <param name="blue" type="GLshort"/>
+ <param name="alpha" type="GLshort"/>
+ </function>
+
+ <function name="Color4sv" offset="34" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="4"/>
+ <glx rop="18"/>
+ </function>
+
+ <!--function name="Color4ub" offset="35" vectorequiv="Color4ubv" static_dispatch="false">
+ <param name="red" type="GLubyte"/>
+ <param name="green" type="GLubyte"/>
+ <param name="blue" type="GLubyte"/>
+ <param name="alpha" type="GLubyte"/>
+ </function-->
+
+ <function name="Color4ubv" offset="36" static_dispatch="false">
+ <param name="v" type="const GLubyte *" count="4"/>
+ <glx rop="19"/>
+ </function>
+
+ <function name="Color4ui" offset="37" vectorequiv="Color4uiv" static_dispatch="false">
+ <param name="red" type="GLuint"/>
+ <param name="green" type="GLuint"/>
+ <param name="blue" type="GLuint"/>
+ <param name="alpha" type="GLuint"/>
+ </function>
+
+ <function name="Color4uiv" offset="38" static_dispatch="false">
+ <param name="v" type="const GLuint *" count="4"/>
+ <glx rop="20"/>
+ </function>
+
+ <function name="Color4us" offset="39" vectorequiv="Color4usv" static_dispatch="false">
+ <param name="red" type="GLushort"/>
+ <param name="green" type="GLushort"/>
+ <param name="blue" type="GLushort"/>
+ <param name="alpha" type="GLushort"/>
+ </function>
+
+ <function name="Color4usv" offset="40" static_dispatch="false">
+ <param name="v" type="const GLushort *" count="4"/>
+ <glx rop="21"/>
+ </function>
+
+ <function name="EdgeFlag" offset="41" vectorequiv="EdgeFlagv" static_dispatch="false">
+ <param name="flag" type="GLboolean"/>
+ </function>
+
+ <function name="EdgeFlagv" offset="42" static_dispatch="false">
+ <param name="flag" type="const GLboolean *" count="1"/>
+ <glx rop="22"/>
+ </function>
+
+ <function name="End" offset="43" static_dispatch="false">
+ <glx rop="23"/>
+ </function>
+
+ <function name="Indexd" offset="44" vectorequiv="Indexdv" static_dispatch="false">
+ <param name="c" type="GLdouble"/>
+ </function>
+
+ <function name="Indexdv" offset="45" static_dispatch="false">
+ <param name="c" type="const GLdouble *" count="1"/>
+ <glx rop="24"/>
+ </function>
+
+ <function name="Indexf" offset="46" vectorequiv="Indexfv" static_dispatch="false">
+ <param name="c" type="GLfloat"/>
+ </function>
+
+ <function name="Indexfv" offset="47" static_dispatch="false">
+ <param name="c" type="const GLfloat *" count="1"/>
+ <glx rop="25"/>
+ </function>
+
+ <function name="Indexi" offset="48" vectorequiv="Indexiv" static_dispatch="false">
+ <param name="c" type="GLint"/>
+ </function>
+
+ <function name="Indexiv" offset="49" static_dispatch="false">
+ <param name="c" type="const GLint *" count="1"/>
+ <glx rop="26"/>
+ </function>
+
+ <function name="Indexs" offset="50" vectorequiv="Indexsv" static_dispatch="false">
+ <param name="c" type="GLshort"/>
+ </function>
+
+ <function name="Indexsv" offset="51" static_dispatch="false">
+ <param name="c" type="const GLshort *" count="1"/>
+ <glx rop="27"/>
+ </function>
+
+ <function name="Normal3b" offset="52" vectorequiv="Normal3bv" static_dispatch="false">
+ <param name="nx" type="GLbyte"/>
+ <param name="ny" type="GLbyte"/>
+ <param name="nz" type="GLbyte"/>
+ </function>
+
+ <function name="Normal3bv" offset="53" static_dispatch="false">
+ <param name="v" type="const GLbyte *" count="3"/>
+ <glx rop="28"/>
+ </function>
+
+ <function name="Normal3d" offset="54" vectorequiv="Normal3dv" static_dispatch="false">
+ <param name="nx" type="GLdouble"/>
+ <param name="ny" type="GLdouble"/>
+ <param name="nz" type="GLdouble"/>
+ </function>
+
+ <function name="Normal3dv" offset="55" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="3"/>
+ <glx rop="29"/>
+ </function>
+
+ <!--function name="Normal3f" offset="56" vectorequiv="Normal3fv" static_dispatch="false">
+ <param name="nx" type="GLfloat"/>
+ <param name="ny" type="GLfloat"/>
+ <param name="nz" type="GLfloat"/>
+ </function-->
+
+ <function name="Normal3fv" offset="57" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="3"/>
+ <glx rop="30"/>
+ </function>
+
+ <function name="Normal3i" offset="58" vectorequiv="Normal3iv" static_dispatch="false">
+ <param name="nx" type="GLint"/>
+ <param name="ny" type="GLint"/>
+ <param name="nz" type="GLint"/>
+ </function>
+
+ <function name="Normal3iv" offset="59" static_dispatch="false">
+ <param name="v" type="const GLint *" count="3"/>
+ <glx rop="31"/>
+ </function>
+
+ <function name="Normal3s" offset="60" vectorequiv="Normal3sv" static_dispatch="false">
+ <param name="nx" type="GLshort"/>
+ <param name="ny" type="GLshort"/>
+ <param name="nz" type="GLshort"/>
+ </function>
+
+ <function name="Normal3sv" offset="61" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="3"/>
+ <glx rop="32"/>
+ </function>
+
+ <function name="RasterPos2d" offset="62" vectorequiv="RasterPos2dv" static_dispatch="false">
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ </function>
+
+ <function name="RasterPos2dv" offset="63" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="2"/>
+ <glx rop="33"/>
+ </function>
+
+ <function name="RasterPos2f" offset="64" vectorequiv="RasterPos2fv" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ </function>
+
+ <function name="RasterPos2fv" offset="65" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="2"/>
+ <glx rop="34"/>
+ </function>
+
+ <function name="RasterPos2i" offset="66" vectorequiv="RasterPos2iv" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ </function>
+
+ <function name="RasterPos2iv" offset="67" static_dispatch="false">
+ <param name="v" type="const GLint *" count="2"/>
+ <glx rop="35"/>
+ </function>
+
+ <function name="RasterPos2s" offset="68" vectorequiv="RasterPos2sv" static_dispatch="false">
+ <param name="x" type="GLshort"/>
+ <param name="y" type="GLshort"/>
+ </function>
+
+ <function name="RasterPos2sv" offset="69" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="2"/>
+ <glx rop="36"/>
+ </function>
+
+ <function name="RasterPos3d" offset="70" vectorequiv="RasterPos3dv" static_dispatch="false">
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ <param name="z" type="GLdouble"/>
+ </function>
+
+ <function name="RasterPos3dv" offset="71" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="3"/>
+ <glx rop="37"/>
+ </function>
+
+ <function name="RasterPos3f" offset="72" vectorequiv="RasterPos3fv" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ </function>
+
+ <function name="RasterPos3fv" offset="73" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="3"/>
+ <glx rop="38"/>
+ </function>
+
+ <function name="RasterPos3i" offset="74" vectorequiv="RasterPos3iv" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="z" type="GLint"/>
+ </function>
+
+ <function name="RasterPos3iv" offset="75" static_dispatch="false">
+ <param name="v" type="const GLint *" count="3"/>
+ <glx rop="39"/>
+ </function>
+
+ <function name="RasterPos3s" offset="76" vectorequiv="RasterPos3sv" static_dispatch="false">
+ <param name="x" type="GLshort"/>
+ <param name="y" type="GLshort"/>
+ <param name="z" type="GLshort"/>
+ </function>
+
+ <function name="RasterPos3sv" offset="77" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="3"/>
+ <glx rop="40"/>
+ </function>
+
+ <function name="RasterPos4d" offset="78" vectorequiv="RasterPos4dv" static_dispatch="false">
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ <param name="z" type="GLdouble"/>
+ <param name="w" type="GLdouble"/>
+ </function>
+
+ <function name="RasterPos4dv" offset="79" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="4"/>
+ <glx rop="41"/>
+ </function>
+
+ <function name="RasterPos4f" offset="80" vectorequiv="RasterPos4fv" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <param name="w" type="GLfloat"/>
+ </function>
+
+ <function name="RasterPos4fv" offset="81" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="4"/>
+ <glx rop="42"/>
+ </function>
+
+ <function name="RasterPos4i" offset="82" vectorequiv="RasterPos4iv" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="z" type="GLint"/>
+ <param name="w" type="GLint"/>
+ </function>
+
+ <function name="RasterPos4iv" offset="83" static_dispatch="false">
+ <param name="v" type="const GLint *" count="4"/>
+ <glx rop="43"/>
+ </function>
+
+ <function name="RasterPos4s" offset="84" vectorequiv="RasterPos4sv" static_dispatch="false">
+ <param name="x" type="GLshort"/>
+ <param name="y" type="GLshort"/>
+ <param name="z" type="GLshort"/>
+ <param name="w" type="GLshort"/>
+ </function>
+
+ <function name="RasterPos4sv" offset="85" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="4"/>
+ <glx rop="44"/>
+ </function>
+
+ <function name="Rectd" offset="86" vectorequiv="Rectdv" static_dispatch="false">
+ <param name="x1" type="GLdouble"/>
+ <param name="y1" type="GLdouble"/>
+ <param name="x2" type="GLdouble"/>
+ <param name="y2" type="GLdouble"/>
+ </function>
+
+ <function name="Rectdv" offset="87" static_dispatch="false">
+ <param name="v1" type="const GLdouble *" count="2"/>
+ <param name="v2" type="const GLdouble *" count="2"/>
+ <glx rop="45"/>
+ </function>
+
+ <function name="Rectf" offset="88" vectorequiv="Rectfv" static_dispatch="false">
+ <param name="x1" type="GLfloat"/>
+ <param name="y1" type="GLfloat"/>
+ <param name="x2" type="GLfloat"/>
+ <param name="y2" type="GLfloat"/>
+ </function>
+
+ <function name="Rectfv" offset="89" static_dispatch="false">
+ <param name="v1" type="const GLfloat *" count="2"/>
+ <param name="v2" type="const GLfloat *" count="2"/>
+ <glx rop="46"/>
+ </function>
+
+ <function name="Recti" offset="90" vectorequiv="Rectiv" static_dispatch="false">
+ <param name="x1" type="GLint"/>
+ <param name="y1" type="GLint"/>
+ <param name="x2" type="GLint"/>
+ <param name="y2" type="GLint"/>
+ </function>
+
+ <function name="Rectiv" offset="91" static_dispatch="false">
+ <param name="v1" type="const GLint *" count="2"/>
+ <param name="v2" type="const GLint *" count="2"/>
+ <glx rop="47"/>
+ </function>
+
+ <function name="Rects" offset="92" vectorequiv="Rectsv" static_dispatch="false">
+ <param name="x1" type="GLshort"/>
+ <param name="y1" type="GLshort"/>
+ <param name="x2" type="GLshort"/>
+ <param name="y2" type="GLshort"/>
+ </function>
+
+ <function name="Rectsv" offset="93" static_dispatch="false">
+ <param name="v1" type="const GLshort *" count="2"/>
+ <param name="v2" type="const GLshort *" count="2"/>
+ <glx rop="48"/>
+ </function>
+
+ <function name="TexCoord1d" offset="94" vectorequiv="TexCoord1dv" static_dispatch="false">
+ <param name="s" type="GLdouble"/>
+ </function>
+
+ <function name="TexCoord1dv" offset="95" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="1"/>
+ <glx rop="49"/>
+ </function>
+
+ <function name="TexCoord1f" offset="96" vectorequiv="TexCoord1fv" static_dispatch="false">
+ <param name="s" type="GLfloat"/>
+ </function>
+
+ <function name="TexCoord1fv" offset="97" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="1"/>
+ <glx rop="50"/>
+ </function>
+
+ <function name="TexCoord1i" offset="98" vectorequiv="TexCoord1iv" static_dispatch="false">
+ <param name="s" type="GLint"/>
+ </function>
+
+ <function name="TexCoord1iv" offset="99" static_dispatch="false">
+ <param name="v" type="const GLint *" count="1"/>
+ <glx rop="51"/>
+ </function>
+
+ <function name="TexCoord1s" offset="100" vectorequiv="TexCoord1sv" static_dispatch="false">
+ <param name="s" type="GLshort"/>
+ </function>
+
+ <function name="TexCoord1sv" offset="101" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="1"/>
+ <glx rop="52"/>
+ </function>
+
+ <function name="TexCoord2d" offset="102" vectorequiv="TexCoord2dv" static_dispatch="false">
+ <param name="s" type="GLdouble"/>
+ <param name="t" type="GLdouble"/>
+ </function>
+
+ <function name="TexCoord2dv" offset="103" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="2"/>
+ <glx rop="53"/>
+ </function>
+
+ <function name="TexCoord2f" offset="104" vectorequiv="TexCoord2fv" static_dispatch="false">
+ <param name="s" type="GLfloat"/>
+ <param name="t" type="GLfloat"/>
+ </function>
+
+ <function name="TexCoord2fv" offset="105" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="2"/>
+ <glx rop="54"/>
+ </function>
+
+ <function name="TexCoord2i" offset="106" vectorequiv="TexCoord2iv" static_dispatch="false">
+ <param name="s" type="GLint"/>
+ <param name="t" type="GLint"/>
+ </function>
+
+ <function name="TexCoord2iv" offset="107" static_dispatch="false">
+ <param name="v" type="const GLint *" count="2"/>
+ <glx rop="55"/>
+ </function>
+
+ <function name="TexCoord2s" offset="108" vectorequiv="TexCoord2sv" static_dispatch="false">
+ <param name="s" type="GLshort"/>
+ <param name="t" type="GLshort"/>
+ </function>
+
+ <function name="TexCoord2sv" offset="109" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="2"/>
+ <glx rop="56"/>
+ </function>
+
+ <function name="TexCoord3d" offset="110" vectorequiv="TexCoord3dv" static_dispatch="false">
+ <param name="s" type="GLdouble"/>
+ <param name="t" type="GLdouble"/>
+ <param name="r" type="GLdouble"/>
+ </function>
+
+ <function name="TexCoord3dv" offset="111" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="3"/>
+ <glx rop="57"/>
+ </function>
+
+ <function name="TexCoord3f" offset="112" vectorequiv="TexCoord3fv" static_dispatch="false">
+ <param name="s" type="GLfloat"/>
+ <param name="t" type="GLfloat"/>
+ <param name="r" type="GLfloat"/>
+ </function>
+
+ <function name="TexCoord3fv" offset="113" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="3"/>
+ <glx rop="58"/>
+ </function>
+
+ <function name="TexCoord3i" offset="114" vectorequiv="TexCoord3iv" static_dispatch="false">
+ <param name="s" type="GLint"/>
+ <param name="t" type="GLint"/>
+ <param name="r" type="GLint"/>
+ </function>
+
+ <function name="TexCoord3iv" offset="115" static_dispatch="false">
+ <param name="v" type="const GLint *" count="3"/>
+ <glx rop="59"/>
+ </function>
+
+ <function name="TexCoord3s" offset="116" vectorequiv="TexCoord3sv" static_dispatch="false">
+ <param name="s" type="GLshort"/>
+ <param name="t" type="GLshort"/>
+ <param name="r" type="GLshort"/>
+ </function>
+
+ <function name="TexCoord3sv" offset="117" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="3"/>
+ <glx rop="60"/>
+ </function>
+
+ <function name="TexCoord4d" offset="118" vectorequiv="TexCoord4dv" static_dispatch="false">
+ <param name="s" type="GLdouble"/>
+ <param name="t" type="GLdouble"/>
+ <param name="r" type="GLdouble"/>
+ <param name="q" type="GLdouble"/>
+ </function>
+
+ <function name="TexCoord4dv" offset="119" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="4"/>
+ <glx rop="61"/>
+ </function>
+
+ <function name="TexCoord4f" offset="120" vectorequiv="TexCoord4fv" static_dispatch="false">
+ <param name="s" type="GLfloat"/>
+ <param name="t" type="GLfloat"/>
+ <param name="r" type="GLfloat"/>
+ <param name="q" type="GLfloat"/>
+ </function>
+
+ <function name="TexCoord4fv" offset="121" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="4"/>
+ <glx rop="62"/>
+ </function>
+
+ <function name="TexCoord4i" offset="122" vectorequiv="TexCoord4iv" static_dispatch="false">
+ <param name="s" type="GLint"/>
+ <param name="t" type="GLint"/>
+ <param name="r" type="GLint"/>
+ <param name="q" type="GLint"/>
+ </function>
+
+ <function name="TexCoord4iv" offset="123" static_dispatch="false">
+ <param name="v" type="const GLint *" count="4"/>
+ <glx rop="63"/>
+ </function>
+
+ <function name="TexCoord4s" offset="124" vectorequiv="TexCoord4sv" static_dispatch="false">
+ <param name="s" type="GLshort"/>
+ <param name="t" type="GLshort"/>
+ <param name="r" type="GLshort"/>
+ <param name="q" type="GLshort"/>
+ </function>
+
+ <function name="TexCoord4sv" offset="125" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="4"/>
+ <glx rop="64"/>
+ </function>
+
+ <function name="Vertex2d" offset="126" vectorequiv="Vertex2dv" static_dispatch="false">
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ </function>
+
+ <function name="Vertex2dv" offset="127" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="2"/>
+ <glx rop="65"/>
+ </function>
+
+ <function name="Vertex2f" offset="128" vectorequiv="Vertex2fv" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ </function>
+
+ <function name="Vertex2fv" offset="129" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="2"/>
+ <glx rop="66"/>
+ </function>
+
+ <function name="Vertex2i" offset="130" vectorequiv="Vertex2iv" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ </function>
+
+ <function name="Vertex2iv" offset="131" static_dispatch="false">
+ <param name="v" type="const GLint *" count="2"/>
+ <glx rop="67"/>
+ </function>
+
+ <function name="Vertex2s" offset="132" vectorequiv="Vertex2sv" static_dispatch="false">
+ <param name="x" type="GLshort"/>
+ <param name="y" type="GLshort"/>
+ </function>
+
+ <function name="Vertex2sv" offset="133" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="2"/>
+ <glx rop="68"/>
+ </function>
+
+ <function name="Vertex3d" offset="134" vectorequiv="Vertex3dv" static_dispatch="false">
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ <param name="z" type="GLdouble"/>
+ </function>
+
+ <function name="Vertex3dv" offset="135" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="3"/>
+ <glx rop="69"/>
+ </function>
+
+ <function name="Vertex3f" offset="136" vectorequiv="Vertex3fv" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ </function>
+
+ <function name="Vertex3fv" offset="137" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="3"/>
+ <glx rop="70"/>
+ </function>
+
+ <function name="Vertex3i" offset="138" vectorequiv="Vertex3iv" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="z" type="GLint"/>
+ </function>
+
+ <function name="Vertex3iv" offset="139" static_dispatch="false">
+ <param name="v" type="const GLint *" count="3"/>
+ <glx rop="71"/>
+ </function>
+
+ <function name="Vertex3s" offset="140" vectorequiv="Vertex3sv" static_dispatch="false">
+ <param name="x" type="GLshort"/>
+ <param name="y" type="GLshort"/>
+ <param name="z" type="GLshort"/>
+ </function>
+
+ <function name="Vertex3sv" offset="141" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="3"/>
+ <glx rop="72"/>
+ </function>
+
+ <function name="Vertex4d" offset="142" vectorequiv="Vertex4dv" static_dispatch="false">
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ <param name="z" type="GLdouble"/>
+ <param name="w" type="GLdouble"/>
+ </function>
+
+ <function name="Vertex4dv" offset="143" static_dispatch="false">
+ <param name="v" type="const GLdouble *" count="4"/>
+ <glx rop="73"/>
+ </function>
+
+ <function name="Vertex4f" offset="144" vectorequiv="Vertex4fv" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <param name="w" type="GLfloat"/>
+ </function>
+
+ <function name="Vertex4fv" offset="145" static_dispatch="false">
+ <param name="v" type="const GLfloat *" count="4"/>
+ <glx rop="74"/>
+ </function>
+
+ <function name="Vertex4i" offset="146" vectorequiv="Vertex4iv" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="z" type="GLint"/>
+ <param name="w" type="GLint"/>
+ </function>
+
+ <function name="Vertex4iv" offset="147" static_dispatch="false">
+ <param name="v" type="const GLint *" count="4"/>
+ <glx rop="75"/>
+ </function>
+
+ <function name="Vertex4s" offset="148" vectorequiv="Vertex4sv" static_dispatch="false">
+ <param name="x" type="GLshort"/>
+ <param name="y" type="GLshort"/>
+ <param name="z" type="GLshort"/>
+ <param name="w" type="GLshort"/>
+ </function>
+
+ <function name="Vertex4sv" offset="149" static_dispatch="false">
+ <param name="v" type="const GLshort *" count="4"/>
+ <glx rop="76"/>
+ </function>
+
+ <function name="ClipPlane" offset="150" static_dispatch="false">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="const GLdouble *" count="4"/>
+ <glx rop="77"/>
+ </function>
+
+ <function name="ColorMaterial" offset="151" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="mode" type="GLenum"/>
+ <glx rop="78"/>
+ </function>
+
+ <!--function name="CullFace" offset="152" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="79"/>
+ </function>
+
+ <function name="Fogf" offset="153" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="80"/>
+ </function>
+
+ <function name="Fogfv" offset="154" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="81"/>
+ </function-->
+
+ <function name="Fogi" offset="155" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="82"/>
+ </function>
+
+ <function name="Fogiv" offset="156" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="83"/>
+ </function>
+
+ <!--function name="FrontFace" offset="157" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="84"/>
+ </function>
+
+ <function name="Hint" offset="158" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="mode" type="GLenum"/>
+ <glx rop="85"/>
+ </function>
+
+ <function name="Lightf" offset="159" static_dispatch="false">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="86"/>
+ </function>
+
+ <function name="Lightfv" offset="160" static_dispatch="false">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="87"/>
+ </function-->
+
+ <function name="Lighti" offset="161" static_dispatch="false">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="88"/>
+ </function>
+
+ <function name="Lightiv" offset="162" static_dispatch="false">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="89"/>
+ </function>
+
+ <!--function name="LightModelf" offset="163" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="90"/>
+ </function>
+
+ <function name="LightModelfv" offset="164" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="91"/>
+ </function-->
+
+ <function name="LightModeli" offset="165" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="92"/>
+ </function>
+
+ <function name="LightModeliv" offset="166" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="93"/>
+ </function>
+
+ <function name="LineStipple" offset="167" static_dispatch="false">
+ <param name="factor" type="GLint"/>
+ <param name="pattern" type="GLushort"/>
+ <glx rop="94"/>
+ </function>
+
+ <!--function name="LineWidth" offset="168" static_dispatch="false">
+ <param name="width" type="GLfloat"/>
+ <glx rop="95"/>
+ </function>
+
+ <function name="Materialf" offset="169" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="96"/>
+ </function>
+
+ <function name="Materialfv" offset="170" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="97"/>
+ </function-->
+
+ <function name="Materiali" offset="171" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="98"/>
+ </function>
+
+ <function name="Materialiv" offset="172" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="99"/>
+ </function>
+
+ <!--function name="PointSize" offset="173" static_dispatch="false">
+ <param name="size" type="GLfloat"/>
+ <glx rop="100"/>
+ </function-->
+
+ <function name="PolygonMode" offset="174" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="mode" type="GLenum"/>
+ <glx rop="101"/>
+ </function>
+
+ <function name="PolygonStipple" offset="175" static_dispatch="false">
+ <param name="mask" type="const GLubyte *" img_width="32" img_height="32" img_format="GL_COLOR_INDEX" img_type="GL_BITMAP" img_target="0" img_pad_dimensions="false"/>
+ <glx rop="102"/>
+ </function>
+
+ <!--function name="Scissor" offset="176" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="103"/>
+ </function>
+
+ <function name="ShadeModel" offset="177" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="104"/>
+ </function>
+
+ <function name="TexParameterf" offset="178" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="105"/>
+ </function>
+
+ <function name="TexParameterfv" offset="179" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="106"/>
+ </function>
+
+ <function name="TexParameteri" offset="180" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="107"/>
+ </function>
+
+ <function name="TexParameteriv" offset="181" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="108"/>
+ </function-->
+
+ <function name="TexImage1D" offset="182" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_format="format" img_type="type" img_target="target" img_send_null="true" img_pad_dimensions="true"/>
+ <glx rop="109" large="true"/>
+ </function>
+
+ <!--function name="TexImage2D" offset="183" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_format="format" img_type="type" img_target="target" img_send_null="true" img_pad_dimensions="true"/>
+ <glx rop="110" large="true"/>
+ </function>
+
+ <function name="TexEnvf" offset="184" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="111"/>
+ </function>
+
+ <function name="TexEnvfv" offset="185" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="112"/>
+ </function>
+
+ <function name="TexEnvi" offset="186" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="113"/>
+ </function>
+
+ <function name="TexEnviv" offset="187" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="114"/>
+ </function-->
+
+ <function name="TexGend" offset="188" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLdouble"/>
+ <glx rop="115"/>
+ </function>
+
+ <function name="TexGendv" offset="189" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLdouble *" variable_param="pname"/>
+ <glx rop="116"/>
+ </function>
+
+ <!--function name="TexGenf" offset="190" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="117"/>
+ </function>
+
+ <function name="TexGenfv" offset="191" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="118"/>
+ </function>
+
+ <function name="TexGeni" offset="192" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="119"/>
+ </function>
+
+ <function name="TexGeniv" offset="193" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="120"/>
+ </function-->
+
+ <function name="FeedbackBuffer" offset="194" static_dispatch="false">
+ <param name="size" type="GLsizei"/>
+ <param name="type" type="GLenum"/>
+ <param name="buffer" type="GLfloat *" output="true"/>
+ <glx sop="105" handcode="true"/>
+ </function>
+
+ <function name="SelectBuffer" offset="195" static_dispatch="false">
+ <param name="size" type="GLsizei"/>
+ <param name="buffer" type="GLuint *" output="true"/>
+ <glx sop="106" handcode="true"/>
+ </function>
+
+ <function name="RenderMode" offset="196" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <return type="GLint"/>
+ <glx sop="107" handcode="true"/>
+ </function>
+
+ <function name="InitNames" offset="197" static_dispatch="false">
+ <glx rop="121"/>
+ </function>
+
+ <function name="LoadName" offset="198" static_dispatch="false">
+ <param name="name" type="GLuint"/>
+ <glx rop="122"/>
+ </function>
+
+ <function name="PassThrough" offset="199" static_dispatch="false">
+ <param name="token" type="GLfloat"/>
+ <glx rop="123"/>
+ </function>
+
+ <function name="PopName" offset="200" static_dispatch="false">
+ <glx rop="124"/>
+ </function>
+
+ <function name="PushName" offset="201" static_dispatch="false">
+ <param name="name" type="GLuint"/>
+ <glx rop="125"/>
+ </function>
+
+ <function name="DrawBuffer" offset="202" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="126"/>
+ </function>
+
+ <!--function name="Clear" offset="203" static_dispatch="false">
+ <param name="mask" type="GLbitfield"/>
+ <glx rop="127"/>
+ </function-->
+
+ <function name="ClearAccum" offset="204" static_dispatch="false">
+ <param name="red" type="GLfloat"/>
+ <param name="green" type="GLfloat"/>
+ <param name="blue" type="GLfloat"/>
+ <param name="alpha" type="GLfloat"/>
+ <glx rop="128"/>
+ </function>
+
+ <function name="ClearIndex" offset="205" static_dispatch="false">
+ <param name="c" type="GLfloat"/>
+ <glx rop="129"/>
+ </function>
+
+ <!--function name="ClearColor" offset="206" static_dispatch="false">
+ <param name="red" type="GLclampf"/>
+ <param name="green" type="GLclampf"/>
+ <param name="blue" type="GLclampf"/>
+ <param name="alpha" type="GLclampf"/>
+ <glx rop="130"/>
+ </function>
+
+ <function name="ClearStencil" offset="207" static_dispatch="false">
+ <param name="s" type="GLint"/>
+ <glx rop="131"/>
+ </function-->
+
+ <function name="ClearDepth" offset="208" static_dispatch="false">
+ <param name="depth" type="GLclampd"/>
+ <glx rop="132"/>
+ </function>
+
+ <!--function name="StencilMask" offset="209" static_dispatch="false">
+ <param name="mask" type="GLuint"/>
+ <glx rop="133"/>
+ </function>
+
+ <function name="ColorMask" offset="210" static_dispatch="false">
+ <param name="red" type="GLboolean"/>
+ <param name="green" type="GLboolean"/>
+ <param name="blue" type="GLboolean"/>
+ <param name="alpha" type="GLboolean"/>
+ <glx rop="134"/>
+ </function>
+
+ <function name="DepthMask" offset="211" static_dispatch="false">
+ <param name="flag" type="GLboolean"/>
+ <glx rop="135"/>
+ </function-->
+
+ <function name="IndexMask" offset="212" static_dispatch="false">
+ <param name="mask" type="GLuint"/>
+ <glx rop="136"/>
+ </function>
+
+ <function name="Accum" offset="213" static_dispatch="false">
+ <param name="op" type="GLenum"/>
+ <param name="value" type="GLfloat"/>
+ <glx rop="137"/>
+ </function>
+
+ <!--function name="Disable" offset="214" static_dispatch="false">
+ <param name="cap" type="GLenum"/>
+ <glx rop="138" handcode="client"/>
+ </function>
+
+ <function name="Enable" offset="215" static_dispatch="false">
+ <param name="cap" type="GLenum"/>
+ <glx rop="139" handcode="client"/>
+ </function>
+
+ <function name="Finish" offset="216" static_dispatch="false">
+ <glx sop="108" handcode="true"/>
+ </function>
+
+ <function name="Flush" offset="217" static_dispatch="false">
+ <glx sop="142" handcode="true"/>
+ </function-->
+
+ <function name="PopAttrib" offset="218" static_dispatch="false">
+ <glx rop="141"/>
+ </function>
+
+ <function name="PushAttrib" offset="219" static_dispatch="false">
+ <param name="mask" type="GLbitfield"/>
+ <glx rop="142"/>
+ </function>
+
+ <function name="Map1d" offset="220" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="u1" type="GLdouble"/>
+ <param name="u2" type="GLdouble"/>
+ <param name="stride" type="GLint" client_only="true"/>
+ <param name="order" type="GLint"/>
+ <param name="points" type="const GLdouble *" variable_param="order"/>
+ <glx rop="143" handcode="true"/>
+ </function>
+
+ <function name="Map1f" offset="221" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="u1" type="GLfloat"/>
+ <param name="u2" type="GLfloat"/>
+ <param name="stride" type="GLint" client_only="true"/>
+ <param name="order" type="GLint"/>
+ <param name="points" type="const GLfloat *" variable_param="order"/>
+ <glx rop="144" handcode="true"/>
+ </function>
+
+ <function name="Map2d" offset="222" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="u1" type="GLdouble"/>
+ <param name="u2" type="GLdouble"/>
+ <param name="ustride" type="GLint" client_only="true"/>
+ <param name="uorder" type="GLint"/>
+ <param name="v1" type="GLdouble"/>
+ <param name="v2" type="GLdouble"/>
+ <param name="vstride" type="GLint" client_only="true"/>
+ <param name="vorder" type="GLint"/>
+ <param name="points" type="const GLdouble *" variable_param="uorder"/>
+ <glx rop="145" handcode="true"/>
+ </function>
+
+ <function name="Map2f" offset="223" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="u1" type="GLfloat"/>
+ <param name="u2" type="GLfloat"/>
+ <param name="ustride" type="GLint" client_only="true"/>
+ <param name="uorder" type="GLint"/>
+ <param name="v1" type="GLfloat"/>
+ <param name="v2" type="GLfloat"/>
+ <param name="vstride" type="GLint" client_only="true"/>
+ <param name="vorder" type="GLint"/>
+ <param name="points" type="const GLfloat *" variable_param="uorder"/>
+ <glx rop="146" handcode="true"/>
+ </function>
+
+ <function name="MapGrid1d" offset="224" static_dispatch="false">
+ <param name="un" type="GLint"/>
+ <param name="u1" type="GLdouble"/>
+ <param name="u2" type="GLdouble"/>
+ <glx rop="147"/>
+ </function>
+
+ <function name="MapGrid1f" offset="225" static_dispatch="false">
+ <param name="un" type="GLint"/>
+ <param name="u1" type="GLfloat"/>
+ <param name="u2" type="GLfloat"/>
+ <glx rop="148"/>
+ </function>
+
+ <function name="MapGrid2d" offset="226" static_dispatch="false">
+ <param name="un" type="GLint"/>
+ <param name="u1" type="GLdouble"/>
+ <param name="u2" type="GLdouble"/>
+ <param name="vn" type="GLint"/>
+ <param name="v1" type="GLdouble"/>
+ <param name="v2" type="GLdouble"/>
+ <glx rop="149"/>
+ </function>
+
+ <function name="MapGrid2f" offset="227" static_dispatch="false">
+ <param name="un" type="GLint"/>
+ <param name="u1" type="GLfloat"/>
+ <param name="u2" type="GLfloat"/>
+ <param name="vn" type="GLint"/>
+ <param name="v1" type="GLfloat"/>
+ <param name="v2" type="GLfloat"/>
+ <glx rop="150"/>
+ </function>
+
+ <function name="EvalCoord1d" offset="228" vectorequiv="EvalCoord1dv" static_dispatch="false">
+ <param name="u" type="GLdouble"/>
+ </function>
+
+ <function name="EvalCoord1dv" offset="229" static_dispatch="false">
+ <param name="u" type="const GLdouble *" count="1"/>
+ <glx rop="151"/>
+ </function>
+
+ <function name="EvalCoord1f" offset="230" vectorequiv="EvalCoord1fv" static_dispatch="false">
+ <param name="u" type="GLfloat"/>
+ </function>
+
+ <function name="EvalCoord1fv" offset="231" static_dispatch="false">
+ <param name="u" type="const GLfloat *" count="1"/>
+ <glx rop="152"/>
+ </function>
+
+ <function name="EvalCoord2d" offset="232" vectorequiv="EvalCoord2dv" static_dispatch="false">
+ <param name="u" type="GLdouble"/>
+ <param name="v" type="GLdouble"/>
+ </function>
+
+ <function name="EvalCoord2dv" offset="233" static_dispatch="false">
+ <param name="u" type="const GLdouble *" count="2"/>
+ <glx rop="153"/>
+ </function>
+
+ <function name="EvalCoord2f" offset="234" vectorequiv="EvalCoord2fv" static_dispatch="false">
+ <param name="u" type="GLfloat"/>
+ <param name="v" type="GLfloat"/>
+ </function>
+
+ <function name="EvalCoord2fv" offset="235" static_dispatch="false">
+ <param name="u" type="const GLfloat *" count="2"/>
+ <glx rop="154"/>
+ </function>
+
+ <function name="EvalMesh1" offset="236" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <param name="i1" type="GLint"/>
+ <param name="i2" type="GLint"/>
+ <glx rop="155"/>
+ </function>
+
+ <function name="EvalPoint1" offset="237" static_dispatch="false">
+ <param name="i" type="GLint"/>
+ <glx rop="156"/>
+ </function>
+
+ <function name="EvalMesh2" offset="238" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <param name="i1" type="GLint"/>
+ <param name="i2" type="GLint"/>
+ <param name="j1" type="GLint"/>
+ <param name="j2" type="GLint"/>
+ <glx rop="157"/>
+ </function>
+
+ <function name="EvalPoint2" offset="239" static_dispatch="false">
+ <param name="i" type="GLint"/>
+ <param name="j" type="GLint"/>
+ <glx rop="158"/>
+ </function>
+
+ <!--function name="AlphaFunc" offset="240" static_dispatch="false">
+ <param name="func" type="GLenum"/>
+ <param name="ref" type="GLclampf"/>
+ <glx rop="159"/>
+ </function>
+
+ <function name="BlendFunc" offset="241" static_dispatch="false">
+ <param name="sfactor" type="GLenum"/>
+ <param name="dfactor" type="GLenum"/>
+ <glx rop="160"/>
+ </function>
+
+ <function name="LogicOp" offset="242" static_dispatch="false">
+ <param name="opcode" type="GLenum"/>
+ <glx rop="161"/>
+ </function>
+
+ <function name="StencilFunc" offset="243" static_dispatch="false">
+ <param name="func" type="GLenum"/>
+ <param name="ref" type="GLint"/>
+ <param name="mask" type="GLuint"/>
+ <glx rop="162"/>
+ </function>
+
+ <function name="StencilOp" offset="244" static_dispatch="false">
+ <param name="fail" type="GLenum"/>
+ <param name="zfail" type="GLenum"/>
+ <param name="zpass" type="GLenum"/>
+ <glx rop="163"/>
+ </function>
+
+ <function name="DepthFunc" offset="245" static_dispatch="false">
+ <param name="func" type="GLenum"/>
+ <glx rop="164"/>
+ </function-->
+
+ <function name="PixelZoom" offset="246" static_dispatch="false">
+ <param name="xfactor" type="GLfloat"/>
+ <param name="yfactor" type="GLfloat"/>
+ <glx rop="165"/>
+ </function>
+
+ <function name="PixelTransferf" offset="247" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx rop="166"/>
+ </function>
+
+ <function name="PixelTransferi" offset="248" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx rop="167"/>
+ </function>
+
+ <function name="PixelStoref" offset="249" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat"/>
+ <glx sop="109" handcode="client"/>
+ </function>
+
+ <!--function name="PixelStorei" offset="250" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ <glx sop="110" handcode="client"/>
+ </function-->
+
+ <function name="PixelMapfv" offset="251" static_dispatch="false">
+ <param name="map" type="GLenum"/>
+ <param name="mapsize" type="GLsizei" counter="true"/>
+ <param name="values" type="const GLfloat *" count="mapsize"/>
+ <glx rop="168" large="true"/>
+ </function>
+
+ <function name="PixelMapuiv" offset="252" static_dispatch="false">
+ <param name="map" type="GLenum"/>
+ <param name="mapsize" type="GLsizei" counter="true"/>
+ <param name="values" type="const GLuint *" count="mapsize"/>
+ <glx rop="169" large="true"/>
+ </function>
+
+ <function name="PixelMapusv" offset="253" static_dispatch="false">
+ <param name="map" type="GLenum"/>
+ <param name="mapsize" type="GLsizei" counter="true"/>
+ <param name="values" type="const GLushort *" count="mapsize"/>
+ <glx rop="170" large="true"/>
+ </function>
+
+ <function name="ReadBuffer" offset="254" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="171"/>
+ </function>
+
+ <function name="CopyPixels" offset="255" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="type" type="GLenum"/>
+ <glx rop="172"/>
+ </function>
+
+ <!--function name="ReadPixels" offset="256" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="GLvoid *" output="true" img_width="width" img_height="height" img_format="format" img_type="type" img_target="0"/>
+ <glx sop="111"/>
+ </function-->
+
+ <function name="DrawPixels" offset="257" static_dispatch="false">
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_format="format" img_type="type" img_target="0" img_pad_dimensions="false"/>
+ <glx rop="173" large="true"/>
+ </function>
+
+ <!--function name="GetBooleanv" offset="258" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLboolean *" output="true" variable_param="pname"/>
+ <glx sop="112" handcode="client"/>
+ </function-->
+
+ <function name="GetClipPlane" offset="259" static_dispatch="false">
+ <param name="plane" type="GLenum"/>
+ <param name="equation" type="GLdouble *" output="true" count="4"/>
+ <glx sop="113" always_array="true"/>
+ </function>
+
+ <function name="GetDoublev" offset="260" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLdouble *" output="true" variable_param="pname"/>
+ <glx sop="114" handcode="client"/>
+ </function>
+
+ <!--function name="GetError" offset="261" static_dispatch="false">
+ <return type="GLenum"/>
+ <glx sop="115" handcode="client"/>
+ </function>
+
+ <function name="GetFloatv" offset="262" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="116" handcode="client"/>
+ </function>
+
+ <function name="GetIntegerv" offset="263" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="117" handcode="client"/>
+ </function>
+
+ <function name="GetLightfv" offset="264" static_dispatch="false">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="118"/>
+ </function-->
+
+ <function name="GetLightiv" offset="265" static_dispatch="false">
+ <param name="light" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="119"/>
+ </function>
+
+ <function name="GetMapdv" offset="266" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="query" type="GLenum"/>
+ <param name="v" type="GLdouble *" output="true" variable_param="target query"/>
+ <glx sop="120"/>
+ </function>
+
+ <function name="GetMapfv" offset="267" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="query" type="GLenum"/>
+ <param name="v" type="GLfloat *" output="true" variable_param="target query"/>
+ <glx sop="121"/>
+ </function>
+
+ <function name="GetMapiv" offset="268" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="query" type="GLenum"/>
+ <param name="v" type="GLint *" output="true" variable_param="target query"/>
+ <glx sop="122"/>
+ </function>
+
+ <!--function name="GetMaterialfv" offset="269" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="123"/>
+ </function-->
+
+ <function name="GetMaterialiv" offset="270" static_dispatch="false">
+ <param name="face" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="124"/>
+ </function>
+
+ <function name="GetPixelMapfv" offset="271" static_dispatch="false">
+ <param name="map" type="GLenum"/>
+ <param name="values" type="GLfloat *" output="true" variable_param="map"/>
+ <glx sop="125"/>
+ </function>
+
+ <function name="GetPixelMapuiv" offset="272" static_dispatch="false">
+ <param name="map" type="GLenum"/>
+ <param name="values" type="GLuint *" output="true" variable_param="map"/>
+ <glx sop="126"/>
+ </function>
+
+ <function name="GetPixelMapusv" offset="273" static_dispatch="false">
+ <param name="map" type="GLenum"/>
+ <param name="values" type="GLushort *" output="true" variable_param="map"/>
+ <glx sop="127"/>
+ </function>
+
+ <function name="GetPolygonStipple" offset="274" static_dispatch="false">
+ <param name="mask" type="GLubyte *" output="true" img_width="32" img_height="32" img_format="GL_COLOR_INDEX" img_type="GL_BITMAP"/>
+ <glx sop="128"/>
+ </function>
+
+ <!--function name="GetString" offset="275" static_dispatch="false">
+ <param name="name" type="GLenum"/>
+ <return type="const GLubyte *"/>
+ <glx sop="129" handcode="true"/>
+ </function>
+
+ <function name="GetTexEnvfv" offset="276" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="130"/>
+ </function>
+
+ <function name="GetTexEnviv" offset="277" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="131"/>
+ </function-->
+
+ <function name="GetTexGendv" offset="278" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLdouble *" output="true" variable_param="pname"/>
+ <glx sop="132"/>
+ </function>
+
+ <!--function name="GetTexGenfv" offset="279" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="133"/>
+ </function>
+
+ <function name="GetTexGeniv" offset="280" static_dispatch="false">
+ <param name="coord" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="134"/>
+ </function-->
+
+ <function name="GetTexImage" offset="281" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="GLvoid *" output="true" img_width="width" img_height="height" img_depth="depth" img_format="format" img_type="type"/>
+ <glx sop="135" dimensions_in_reply="true"/>
+ </function>
+
+ <!--function name="GetTexParameterfv" offset="282" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="136"/>
+ </function>
+
+ <function name="GetTexParameteriv" offset="283" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="137"/>
+ </function-->
+
+ <function name="GetTexLevelParameterfv" offset="284" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="138"/>
+ </function>
+
+ <function name="GetTexLevelParameteriv" offset="285" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="139"/>
+ </function>
+
+ <!--function name="IsEnabled" offset="286" static_dispatch="false">
+ <param name="cap" type="GLenum"/>
+ <return type="GLboolean"/>
+ <glx sop="140" handcode="client"/>
+ </function-->
+
+ <function name="IsList" offset="287" static_dispatch="false">
+ <param name="list" type="GLuint"/>
+ <return type="GLboolean"/>
+ <glx sop="141"/>
+ </function>
+
+ <function name="DepthRange" offset="288" static_dispatch="false">
+ <param name="zNear" type="GLclampd"/>
+ <param name="zFar" type="GLclampd"/>
+ <glx rop="174"/>
+ </function>
+
+ <function name="Frustum" offset="289" static_dispatch="false">
+ <param name="left" type="GLdouble"/>
+ <param name="right" type="GLdouble"/>
+ <param name="bottom" type="GLdouble"/>
+ <param name="top" type="GLdouble"/>
+ <param name="zNear" type="GLdouble"/>
+ <param name="zFar" type="GLdouble"/>
+ <glx rop="175"/>
+ </function>
+
+ <!--function name="LoadIdentity" offset="290" static_dispatch="false">
+ <glx rop="176"/>
+ </function>
+
+ <function name="LoadMatrixf" offset="291" static_dispatch="false">
+ <param name="m" type="const GLfloat *" count="16"/>
+ <glx rop="177"/>
+ </function-->
+
+ <function name="LoadMatrixd" offset="292" static_dispatch="false">
+ <param name="m" type="const GLdouble *" count="16"/>
+ <glx rop="178"/>
+ </function>
+
+ <!--function name="MatrixMode" offset="293" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="179"/>
+ </function>
+
+ <function name="MultMatrixf" offset="294" static_dispatch="false">
+ <param name="m" type="const GLfloat *" count="16"/>
+ <glx rop="180"/>
+ </function-->
+
+ <function name="MultMatrixd" offset="295" static_dispatch="false">
+ <param name="m" type="const GLdouble *" count="16"/>
+ <glx rop="181"/>
+ </function>
+
+ <function name="Ortho" offset="296" static_dispatch="false">
+ <param name="left" type="GLdouble"/>
+ <param name="right" type="GLdouble"/>
+ <param name="bottom" type="GLdouble"/>
+ <param name="top" type="GLdouble"/>
+ <param name="zNear" type="GLdouble"/>
+ <param name="zFar" type="GLdouble"/>
+ <glx rop="182"/>
+ </function>
+
+ <!--function name="PopMatrix" offset="297" static_dispatch="false">
+ <glx rop="183"/>
+ </function>
+
+ <function name="PushMatrix" offset="298" static_dispatch="false">
+ <glx rop="184"/>
+ </function-->
+
+ <function name="Rotated" offset="299" static_dispatch="false">
+ <param name="angle" type="GLdouble"/>
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ <param name="z" type="GLdouble"/>
+ <glx rop="185"/>
+ </function>
+
+ <!--function name="Rotatef" offset="300" static_dispatch="false">
+ <param name="angle" type="GLfloat"/>
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <glx rop="186"/>
+ </function-->
+
+ <function name="Scaled" offset="301" static_dispatch="false">
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ <param name="z" type="GLdouble"/>
+ <glx rop="187"/>
+ </function>
+
+ <!--function name="Scalef" offset="302" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <glx rop="188"/>
+ </function-->
+
+ <function name="Translated" offset="303" static_dispatch="false">
+ <param name="x" type="GLdouble"/>
+ <param name="y" type="GLdouble"/>
+ <param name="z" type="GLdouble"/>
+ <glx rop="189"/>
+ </function>
+
+ <!--function name="Translatef" offset="304" static_dispatch="false">
+ <param name="x" type="GLfloat"/>
+ <param name="y" type="GLfloat"/>
+ <param name="z" type="GLfloat"/>
+ <glx rop="190"/>
+ </function>
+
+ <function name="Viewport" offset="305" static_dispatch="false">
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="191"/>
+ </function-->
+</category>
+
+<category name="1.1">
+ <function name="ArrayElement" offset="306" static_dispatch="false">
+ <param name="i" type="GLint"/>
+ <glx handcode="true"/>
+ </function>
+
+ <!--function name="ColorPointer" offset="308" static_dispatch="false">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="DisableClientState" offset="309" static_dispatch="false">
+ <param name="array" type="GLenum"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="DrawArrays" offset="310" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <param name="first" type="GLint"/>
+ <param name="count" type="GLsizei"/>
+ <glx rop="193" handcode="true"/>
+ </function>
+
+ <function name="DrawElements" offset="311" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <param name="count" type="GLsizei"/>
+ <param name="type" type="GLenum"/>
+ <param name="indices" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function-->
+
+ <function name="EdgeFlagPointer" offset="312" static_dispatch="false">
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <!--function name="EnableClientState" offset="313" static_dispatch="false">
+ <param name="array" type="GLenum"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="GetPointerv" offset="329" static_dispatch="false">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLvoid **" output="true"/>
+ <glx handcode="true"/>
+ </function-->
+
+ <function name="IndexPointer" offset="314" static_dispatch="false">
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="InterleavedArrays" offset="317" static_dispatch="false">
+ <param name="format" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <!--function name="NormalPointer" offset="318" static_dispatch="false">
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="TexCoordPointer" offset="320" static_dispatch="false">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="VertexPointer" offset="321" static_dispatch="false">
+ <param name="size" type="GLint"/>
+ <param name="type" type="GLenum"/>
+ <param name="stride" type="GLsizei"/>
+ <param name="pointer" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="PolygonOffset" offset="319" static_dispatch="false">
+ <param name="factor" type="GLfloat"/>
+ <param name="units" type="GLfloat"/>
+ <glx rop="192"/>
+ </function-->
+
+ <function name="CopyTexImage1D" offset="323" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <glx rop="4119"/>
+ </function>
+
+ <!--function name="CopyTexImage2D" offset="324" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <glx rop="4120"/>
+ </function-->
+
+ <function name="CopyTexSubImage1D" offset="325" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <glx rop="4121"/>
+ </function>
+
+ <!--function name="CopyTexSubImage2D" offset="326" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="4122"/>
+ </function-->
+
+ <function name="TexSubImage1D" offset="332" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="UNUSED" type="GLuint" padding="true"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_xoff="xoffset" img_format="format" img_type="type" img_target="target" img_pad_dimensions="true"/>
+ <glx rop="4099" large="true"/>
+ </function>
+
+ <!--function name="TexSubImage2D" offset="333" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="UNUSED" type="GLuint" padding="true"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_xoff="xoffset" img_yoff="yoffset" img_format="format" img_type="type" img_target="target" img_pad_dimensions="true"/>
+ <glx rop="4100" large="true"/>
+ </function-->
+
+ <function name="AreTexturesResident" offset="322" static_dispatch="false">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="textures" type="const GLuint *" count="n"/>
+ <param name="residences" type="GLboolean *" output="true" count="n"/>
+ <return type="GLboolean"/>
+ <glx sop="143" handcode="client" always_array="true"/>
+ </function>
+
+ <!--function name="BindTexture" offset="307" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <glx rop="4117"/>
+ </function>
+
+ <function name="DeleteTextures" offset="327" static_dispatch="false">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="textures" type="const GLuint *" count="n"/>
+ <glx sop="144"/>
+ </function>
+
+ <function name="GenTextures" offset="328" static_dispatch="false">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="textures" type="GLuint *" output="true" count="n"/>
+ <glx sop="145" always_array="true"/>
+ </function>
+
+ <function name="IsTexture" offset="330" static_dispatch="false">
+ <param name="texture" type="GLuint"/>
+ <return type="GLboolean"/>
+ <glx sop="146"/>
+ </function-->
+
+ <function name="PrioritizeTextures" offset="331" static_dispatch="false">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="textures" type="const GLuint *" count="n"/>
+ <param name="priorities" type="const GLclampf *" count="n"/>
+ <glx rop="4118"/>
+ </function>
+
+ <function name="Indexub" offset="315" vectorequiv="Indexubv" static_dispatch="false">
+ <param name="c" type="GLubyte"/>
+ </function>
+
+ <function name="Indexubv" offset="316" static_dispatch="false">
+ <param name="c" type="const GLubyte *" count="1"/>
+ <glx rop="194"/>
+ </function>
+
+ <function name="PopClientAttrib" offset="334" static_dispatch="false">
+ <glx handcode="true"/>
+ </function>
+
+ <function name="PushClientAttrib" offset="335" static_dispatch="false">
+ <param name="mask" type="GLbitfield"/>
+ <glx handcode="true"/>
+ </function>
+</category>
+
+<category name="1.2">
+ <!--function name="BlendColor" offset="336" static_dispatch="false">
+ <param name="red" type="GLclampf"/>
+ <param name="green" type="GLclampf"/>
+ <param name="blue" type="GLclampf"/>
+ <param name="alpha" type="GLclampf"/>
+ <glx rop="4096"/>
+ </function>
+
+ <function name="BlendEquation" offset="337" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <glx rop="4097"/>
+ </function-->
+
+ <function name="DrawRangeElements" offset="338" static_dispatch="false">
+ <param name="mode" type="GLenum"/>
+ <param name="start" type="GLuint"/>
+ <param name="end" type="GLuint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="type" type="GLenum"/>
+ <param name="indices" type="const GLvoid *"/>
+ <glx handcode="true"/>
+ </function>
+
+ <function name="ColorTable" offset="339" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="table" type="const GLvoid *" img_width="width" img_pad_dimensions="false" img_format="format" img_type="type" img_target="target"/>
+ <glx rop="2053" large="true"/>
+ </function>
+
+ <function name="ColorTableParameterfv" offset="340" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="2054"/>
+ </function>
+
+ <function name="ColorTableParameteriv" offset="341" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="2055"/>
+ </function>
+
+ <function name="CopyColorTable" offset="342" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <glx rop="2056"/>
+ </function>
+
+ <function name="GetColorTable" offset="343" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="table" type="GLvoid *" output="true" img_width="width" img_format="format" img_type="type"/>
+ <glx sop="147" dimensions_in_reply="true"/>
+ </function>
+
+ <function name="GetColorTableParameterfv" offset="344" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="148"/>
+ </function>
+
+ <function name="GetColorTableParameteriv" offset="345" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="149"/>
+ </function>
+
+ <function name="ColorSubTable" offset="346" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="start" type="GLsizei"/>
+ <param name="count" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="data" type="const GLvoid *" img_width="count" img_pad_dimensions="false" img_format="format" img_type="type" img_target="target"/>
+ <glx rop="195" large="true"/>
+ </function>
+
+ <function name="CopyColorSubTable" offset="347" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="start" type="GLsizei"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <glx rop="196"/>
+ </function>
+
+ <function name="ConvolutionFilter1D" offset="348" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="image" type="const GLvoid *" img_width="width" img_format="format" img_type="type" img_target="target" img_pad_dimensions="true"/>
+ <glx rop="4101" large="true"/>
+ </function>
+
+ <function name="ConvolutionFilter2D" offset="349" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="image" type="const GLvoid *" img_width="width" img_height="height" img_format="format" img_type="type" img_target="target" img_pad_dimensions="true"/>
+ <glx rop="4102" large="true"/>
+ </function>
+
+ <function name="ConvolutionParameterf" offset="350" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat"/>
+ <glx rop="4103"/>
+ </function>
+
+ <function name="ConvolutionParameterfv" offset="351" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLfloat *" variable_param="pname"/>
+ <glx rop="4104"/>
+ </function>
+
+ <function name="ConvolutionParameteri" offset="352" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint"/>
+ <glx rop="4105"/>
+ </function>
+
+ <function name="ConvolutionParameteriv" offset="353" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *" variable_param="pname"/>
+ <glx rop="4106"/>
+ </function>
+
+ <function name="CopyConvolutionFilter1D" offset="354" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <glx rop="4107"/>
+ </function>
+
+ <function name="CopyConvolutionFilter2D" offset="355" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="4108"/>
+ </function>
+
+ <function name="GetConvolutionFilter" offset="356" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="image" type="GLvoid *" output="true" img_width="width" img_height="height" img_format="format" img_type="type"/>
+ <glx sop="150" dimensions_in_reply="true"/>
+ </function>
+
+ <function name="GetConvolutionParameterfv" offset="357" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="151"/>
+ </function>
+
+ <function name="GetConvolutionParameteriv" offset="358" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="152"/>
+ </function>
+
+ <function name="GetSeparableFilter" offset="359" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="row" type="GLvoid *" output="true"/>
+ <param name="column" type="GLvoid *" output="true"/>
+ <param name="span" type="GLvoid *" output="true"/>
+ <glx sop="153" handcode="true"/>
+ </function>
+
+ <function name="SeparableFilter2D" offset="360" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="row" type="const GLvoid *"/>
+ <param name="column" type="const GLvoid *"/>
+ <glx rop="4109" handcode="true"/>
+ </function>
+
+ <function name="GetHistogram" offset="361" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="reset" type="GLboolean"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="values" type="GLvoid *" output="true" img_width="width" img_format="format" img_type="type"/>
+ <glx sop="154" dimensions_in_reply="true" img_reset="reset"/>
+ </function>
+
+ <function name="GetHistogramParameterfv" offset="362" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="155"/>
+ </function>
+
+ <function name="GetHistogramParameteriv" offset="363" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="156"/>
+ </function>
+
+ <function name="GetMinmax" offset="364" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="reset" type="GLboolean"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="values" type="GLvoid *" output="true" img_width="2" img_format="format" img_type="type"/>
+ <glx sop="157" img_reset="reset"/>
+ </function>
+
+ <function name="GetMinmaxParameterfv" offset="365" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLfloat *" output="true" variable_param="pname"/>
+ <glx sop="158"/>
+ </function>
+
+ <function name="GetMinmaxParameteriv" offset="366" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true" variable_param="pname"/>
+ <glx sop="159"/>
+ </function>
+
+ <function name="Histogram" offset="367" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="sink" type="GLboolean"/>
+ <glx rop="4110"/>
+ </function>
+
+ <function name="Minmax" offset="368" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="sink" type="GLboolean"/>
+ <glx rop="4111"/>
+ </function>
+
+ <function name="ResetHistogram" offset="369" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <glx rop="4112"/>
+ </function>
+
+ <function name="ResetMinmax" offset="370" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <glx rop="4113"/>
+ </function>
+
+ <!--function name="TexImage3D" offset="371" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="internalformat" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="border" type="GLint"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_depth="depth" img_format="format" img_type="type" img_target="target" img_null_flag="true" img_pad_dimensions="true"/>
+ <glx rop="4114" large="true"/>
+ </function>
+
+ <function name="TexSubImage3D" offset="372" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="format" type="GLenum"/>
+ <param name="type" type="GLenum"/>
+ <param name="UNUSED" type="GLuint" padding="true"/>
+ <param name="pixels" type="const GLvoid *" img_width="width" img_height="height" img_depth="depth" img_xoff="xoffset" img_yoff="yoffset" img_zoff="zoffset" img_format="format" img_type="type" img_target="target" img_pad_dimensions="true"/>
+ <glx rop="4115" large="true"/>
+ </function>
+
+ <function name="CopyTexSubImage3D" offset="373" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="level" type="GLint"/>
+ <param name="xoffset" type="GLint"/>
+ <param name="yoffset" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ <param name="x" type="GLint"/>
+ <param name="y" type="GLint"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <glx rop="4123"/>
+ </function-->
+</category>
+
+<category name="GL_ARB_multitexture" number="1">
+ <!--function name="ActiveTextureARB" offset="374" static_dispatch="false">
+ <param name="texture" type="GLenum"/>
+ <glx rop="197"/>
+ </function>
+
+ <function name="ClientActiveTextureARB" offset="375" static_dispatch="false">
+ <param name="texture" type="GLenum"/>
+ <glx handcode="true"/>
+ </function-->
+
+ <function name="MultiTexCoord1dARB" offset="376" vectorequiv="MultiTexCoord1dvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLdouble"/>
+ </function>
+
+ <function name="MultiTexCoord1dvARB" offset="377" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLdouble *" count="1"/>
+ <glx rop="198"/>
+ </function>
+
+ <function name="MultiTexCoord1fARB" offset="378" vectorequiv="MultiTexCoord1fvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLfloat"/>
+ </function>
+
+ <function name="MultiTexCoord1fvARB" offset="379" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLfloat *" count="1"/>
+ <glx rop="199"/>
+ </function>
+
+ <function name="MultiTexCoord1iARB" offset="380" vectorequiv="MultiTexCoord1ivARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLint"/>
+ </function>
+
+ <function name="MultiTexCoord1ivARB" offset="381" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLint *" count="1"/>
+ <glx rop="200"/>
+ </function>
+
+ <function name="MultiTexCoord1sARB" offset="382" vectorequiv="MultiTexCoord1svARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLshort"/>
+ </function>
+
+ <function name="MultiTexCoord1svARB" offset="383" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLshort *" count="1"/>
+ <glx rop="201"/>
+ </function>
+
+ <function name="MultiTexCoord2dARB" offset="384" vectorequiv="MultiTexCoord2dvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLdouble"/>
+ <param name="t" type="GLdouble"/>
+ </function>
+
+ <function name="MultiTexCoord2dvARB" offset="385" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLdouble *" count="2"/>
+ <glx rop="202"/>
+ </function>
+
+ <function name="MultiTexCoord2fARB" offset="386" vectorequiv="MultiTexCoord2fvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLfloat"/>
+ <param name="t" type="GLfloat"/>
+ </function>
+
+ <function name="MultiTexCoord2fvARB" offset="387" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLfloat *" count="2"/>
+ <glx rop="203"/>
+ </function>
+
+ <function name="MultiTexCoord2iARB" offset="388" vectorequiv="MultiTexCoord2ivARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLint"/>
+ <param name="t" type="GLint"/>
+ </function>
+
+ <function name="MultiTexCoord2ivARB" offset="389" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLint *" count="2"/>
+ <glx rop="204"/>
+ </function>
+
+ <function name="MultiTexCoord2sARB" offset="390" vectorequiv="MultiTexCoord2svARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLshort"/>
+ <param name="t" type="GLshort"/>
+ </function>
+
+ <function name="MultiTexCoord2svARB" offset="391" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLshort *" count="2"/>
+ <glx rop="205"/>
+ </function>
+
+ <function name="MultiTexCoord3dARB" offset="392" vectorequiv="MultiTexCoord3dvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLdouble"/>
+ <param name="t" type="GLdouble"/>
+ <param name="r" type="GLdouble"/>
+ </function>
+
+ <function name="MultiTexCoord3dvARB" offset="393" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLdouble *" count="3"/>
+ <glx rop="206"/>
+ </function>
+
+ <function name="MultiTexCoord3fARB" offset="394" vectorequiv="MultiTexCoord3fvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLfloat"/>
+ <param name="t" type="GLfloat"/>
+ <param name="r" type="GLfloat"/>
+ </function>
+
+ <function name="MultiTexCoord3fvARB" offset="395" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLfloat *" count="3"/>
+ <glx rop="207"/>
+ </function>
+
+ <function name="MultiTexCoord3iARB" offset="396" vectorequiv="MultiTexCoord3ivARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLint"/>
+ <param name="t" type="GLint"/>
+ <param name="r" type="GLint"/>
+ </function>
+
+ <function name="MultiTexCoord3ivARB" offset="397" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLint *" count="3"/>
+ <glx rop="208"/>
+ </function>
+
+ <function name="MultiTexCoord3sARB" offset="398" vectorequiv="MultiTexCoord3svARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLshort"/>
+ <param name="t" type="GLshort"/>
+ <param name="r" type="GLshort"/>
+ </function>
+
+ <function name="MultiTexCoord3svARB" offset="399" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLshort *" count="3"/>
+ <glx rop="209"/>
+ </function>
+
+ <function name="MultiTexCoord4dARB" offset="400" vectorequiv="MultiTexCoord4dvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLdouble"/>
+ <param name="t" type="GLdouble"/>
+ <param name="r" type="GLdouble"/>
+ <param name="q" type="GLdouble"/>
+ </function>
+
+ <function name="MultiTexCoord4dvARB" offset="401" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLdouble *" count="4"/>
+ <glx rop="210"/>
+ </function>
+
+ <!--function name="MultiTexCoord4fARB" offset="402" vectorequiv="MultiTexCoord4fvARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLfloat"/>
+ <param name="t" type="GLfloat"/>
+ <param name="r" type="GLfloat"/>
+ <param name="q" type="GLfloat"/>
+ </function-->
+
+ <function name="MultiTexCoord4fvARB" offset="403" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLfloat *" count="4"/>
+ <glx rop="211"/>
+ </function>
+
+ <function name="MultiTexCoord4iARB" offset="404" vectorequiv="MultiTexCoord4ivARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLint"/>
+ <param name="t" type="GLint"/>
+ <param name="r" type="GLint"/>
+ <param name="q" type="GLint"/>
+ </function>
+
+ <function name="MultiTexCoord4ivARB" offset="405" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLint *" count="4"/>
+ <glx rop="212"/>
+ </function>
+
+ <function name="MultiTexCoord4sARB" offset="406" vectorequiv="MultiTexCoord4svARB" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="s" type="GLshort"/>
+ <param name="t" type="GLshort"/>
+ <param name="r" type="GLshort"/>
+ <param name="q" type="GLshort"/>
+ </function>
+
+ <function name="MultiTexCoord4svARB" offset="407" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="v" type="const GLshort *" count="4"/>
+ <glx rop="213"/>
+ </function>
+</category>
+
+<xi:include href="../../glapi/APPLE_vertex_array_object.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/es_EXT.xml b/src/mesa/es/glapi/es_EXT.xml
new file mode 100644
index 0000000000..8878b54141
--- /dev/null
+++ b/src/mesa/es/glapi/es_EXT.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "../../glapi/gl_API.dtd">
+
+<!-- OpenGL ES extensions -->
+
+<OpenGLAPI>
+
+<category name="GL_OES_compressed_paletted_texture" number="6">
+ <enum name="PALETTE4_RGB8_OES" value="0x8B90"/>
+ <enum name="PALETTE4_RGBA8_OES" value="0x8B91"/>
+ <enum name="PALETTE4_R5_G6_B5_OES" value="0x8B92"/>
+ <enum name="PALETTE4_RGBA4_OES" value="0x8B93"/>
+ <enum name="PALETTE4_RGB5_A1_OES" value="0x8B94"/>
+ <enum name="PALETTE8_RGB8_OES" value="0x8B95"/>
+ <enum name="PALETTE8_RGBA8_OES" value="0x8B96"/>
+ <enum name="PALETTE8_R5_G6_B5_OES" value="0x8B97"/>
+ <enum name="PALETTE8_RGBA4_OES" value="0x8B98"/>
+ <enum name="PALETTE8_RGB5_A1_OES" value="0x8B99"/>
+</category>
+
+<category name="GL_OES_EGL_image" number="23">
+ <type name="eglImageOES" size="4" />
+
+ <function name="EGLImageTargetTexture2DOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="image" type="GLeglImageOES"/>
+ </function>
+
+ <function name="EGLImageTargetRenderbufferStorageOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="image" type="GLeglImageOES"/>
+ </function>
+</category>
+
+<category name="GL_OES_depth24" number="24">
+ <enum name="DEPTH_COMPONENT24_OES" value="0x81A6"/>
+</category>
+
+<category name="GL_OES_depth32" number="25">
+ <enum name="DEPTH_COMPONENT32_OES" value="0x81A7"/>
+</category>
+
+<category name="GL_OES_element_index_uint" number="26">
+ <!-- No new functions, types, enums. -->
+</category>
+
+<category name="GL_OES_fbo_render_mipmap" number="27">
+ <!-- No new functions, types, enums. -->
+</category>
+
+<category name="GL_OES_mapbuffer" number="29">
+ <enum name="WRITE_ONLY_OES" value="0x88B9"/>
+ <enum name="BUFFER_ACCESS_OES" value="0x88BB"/>
+ <enum name="BUFFER_MAPPED_OES" value="0x88BC"/>
+ <enum name="BUFFER_MAP_POINTER_OES" value="0x88BD"/>
+
+ <function name="GetBufferPointervOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLvoid **"/>
+ </function>
+
+ <function name="MapBufferOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="access" type="GLenum"/>
+ <return type="GLvoid *"/>
+ </function>
+
+ <function name="UnmapBufferOES" offset="assign">
+ <param name="target" type="GLenum"/>
+ <return type="GLboolean"/>
+ </function>
+</category>
+
+<category name="GL_OES_rgb8_rgba8" number="30">
+ <enum name="RGB8_OES" value="0x8051"/>
+ <enum name="RGBA8_OES" value="0x8058"/>
+</category>
+
+<category name="GL_OES_stencil1" number="31">
+ <enum name="STENCIL_INDEX1_OES" value="0x8D46"/>
+</category>
+
+<category name="GL_OES_stencil4" number="32">
+ <enum name="STENCIL_INDEX4_OES" value="0x8D47"/>
+</category>
+
+<category name="GL_OES_stencil8" number="33">
+ <enum name="STENCIL_INDEX8_OES" value="0x8D48"/>
+</category>
+
+<category name="GL_EXT_texture_filter_anisotropic" number="41">
+ <enum name="TEXTURE_MAX_ANISOTROPY_EXT" value="0x84FE"/>
+ <enum name="MAX_TEXTURE_MAX_ANISOTROPY_EXT" value="0x84FF"/>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/es/glapi/gl_compare.py b/src/mesa/es/glapi/gl_compare.py
new file mode 100644
index 0000000000..ae286e3621
--- /dev/null
+++ b/src/mesa/es/glapi/gl_compare.py
@@ -0,0 +1,354 @@
+#!/usr/bin/python
+#
+# Copyright (C) Chia-I Wu <olvaffe@gmail.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# IBM 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.
+
+import sys
+import os.path
+import getopt
+
+GLAPI = "../../glapi"
+sys.path.append(GLAPI)
+
+import gl_XML
+import glX_XML
+
+class ApiSet(object):
+ def __init__(self, api, elts=["enum", "type", "function"]):
+ self.api = api
+ self.elts = elts
+
+ def _check_enum(self, e1, e2, strict=True):
+ if e1.name != e2.name:
+ raise ValueError("%s: name mismatch" % e1.name)
+ if e1.value != e2.value:
+ raise ValueError("%s: value 0x%04x != 0x%04x"
+ % (e1.name, e1.value, e2.value))
+
+ def _check_type(self, t1, t2, strict=True):
+ if t1.name != t2.name:
+ raise ValueError("%s: name mismatch" % t1.name)
+ if t1.type_expr.string() != t2.type_expr.string():
+ raise ValueError("%s: type %s != %s"
+ % (t1.name, t1.type_expr.string(), t2.type_expr.string()))
+
+ def _check_function(self, f1, f2, strict=True):
+ if f1.name != f2.name:
+ raise ValueError("%s: name mismatch" % f1.name)
+ if f1.return_type != f2.return_type:
+ raise ValueError("%s: return type %s != %s"
+ % (f1.name, f1.return_type, f2.return_type))
+ # there might be padded parameters
+ if strict and len(f1.parameters) != len(f2.parameters):
+ raise ValueError("%s: parameter length %d != %d"
+ % (f1.name, len(f1.parameters), len(f2.parameters)))
+ if f1.assign_offset != f2.assign_offset:
+ if ((f1.assign_offset and f2.offset < 0) or
+ (f2.assign_offset and f1.offset < 0)):
+ raise ValueError("%s: assign offset %d != %d"
+ % (f1.name, f1.assign_offset, f2.assign_offset))
+ elif not f1.assign_offset:
+ if f1.offset != f2.offset:
+ raise ValueError("%s: offset %d != %d"
+ % (f1.name, f1.offset, f2.offset))
+
+ if strict:
+ l1 = f1.entry_points
+ l2 = f2.entry_points
+ l1.sort()
+ l2.sort()
+ if l1 != l2:
+ raise ValueError("%s: entry points %s != %s"
+ % (f1.name, l1, l2))
+
+ l1 = f1.static_entry_points
+ l2 = f2.static_entry_points
+ l1.sort()
+ l2.sort()
+ if l1 != l2:
+ raise ValueError("%s: static entry points %s != %s"
+ % (f1.name, l1, l2))
+
+ pad = 0
+ for i in xrange(len(f1.parameters)):
+ p1 = f1.parameters[i]
+ p2 = f2.parameters[i + pad]
+
+ if not strict and p1.is_padding != p2.is_padding:
+ if p1.is_padding:
+ pad -= 1
+ continue
+ else:
+ pad += 1
+ p2 = f2.parameters[i + pad]
+
+ if strict and p1.name != p2.name:
+ raise ValueError("%s: parameter %d name %s != %s"
+ % (f1.name, i, p1.name, p2.name))
+ if p1.type_expr.string() != p2.type_expr.string():
+ if (strict or
+ # special case
+ f1.name == "TexImage2D" and p1.name != "internalformat"):
+ raise ValueError("%s: parameter %s type %s != %s"
+ % (f1.name, p1.name, p1.type_expr.string(),
+ p2.type_expr.string()))
+
+ def union(self, other):
+ union = gl_XML.gl_api(None)
+
+ if "enum" in self.elts:
+ union.enums_by_name = other.enums_by_name.copy()
+ for key, val in self.api.enums_by_name.iteritems():
+ if key not in union.enums_by_name:
+ union.enums_by_name[key] = val
+ else:
+ self._check_enum(val, other.enums_by_name[key])
+
+ if "type" in self.elts:
+ union.types_by_name = other.types_by_name.copy()
+ for key, val in self.api.types_by_name.iteritems():
+ if key not in union.types_by_name:
+ union.types_by_name[key] = val
+ else:
+ self._check_type(val, other.types_by_name[key])
+
+ if "function" in self.elts:
+ union.functions_by_name = other.functions_by_name.copy()
+ for key, val in self.api.functions_by_name.iteritems():
+ if key not in union.functions_by_name:
+ union.functions_by_name[key] = val
+ else:
+ self._check_function(val, other.functions_by_name[key])
+
+ return union
+
+ def intersection(self, other):
+ intersection = gl_XML.gl_api(None)
+
+ if "enum" in self.elts:
+ for key, val in self.api.enums_by_name.iteritems():
+ if key in other.enums_by_name:
+ self._check_enum(val, other.enums_by_name[key])
+ intersection.enums_by_name[key] = val
+
+ if "type" in self.elts:
+ for key, val in self.api.types_by_name.iteritems():
+ if key in other.types_by_name:
+ self._check_type(val, other.types_by_name[key])
+ intersection.types_by_name[key] = val
+
+ if "function" in self.elts:
+ for key, val in self.api.functions_by_name.iteritems():
+ if key in other.functions_by_name:
+ self._check_function(val, other.functions_by_name[key])
+ intersection.functions_by_name[key] = val
+
+ return intersection
+
+ def difference(self, other):
+ difference = gl_XML.gl_api(None)
+
+ if "enum" in self.elts:
+ for key, val in self.api.enums_by_name.iteritems():
+ if key not in other.enums_by_name:
+ difference.enums_by_name[key] = val
+ else:
+ self._check_enum(val, other.enums_by_name[key])
+
+ if "type" in self.elts:
+ for key, val in self.api.types_by_name.iteritems():
+ if key not in other.types_by_name:
+ difference.types_by_name[key] = val
+ else:
+ self._check_type(val, other.types_by_name[key])
+
+ if "function" in self.elts:
+ for key, val in self.api.functions_by_name.iteritems():
+ if key not in other.functions_by_name:
+ difference.functions_by_name[key] = val
+ else:
+ self._check_function(val, other.functions_by_name[key], False)
+
+ return difference
+
+def cmp_enum(e1, e2):
+ if e1.value < e2.value:
+ return -1
+ elif e1.value > e2.value:
+ return 1
+ else:
+ return 0
+
+def cmp_type(t1, t2):
+ return t1.size - t2.size
+
+def cmp_function(f1, f2):
+ if f1.name > f2.name:
+ return 1
+ elif f1.name < f2.name:
+ return -1
+ else:
+ return 0
+
+def spaces(n, str=""):
+ spaces = n - len(str)
+ if spaces < 1:
+ spaces = 1
+ return " " * spaces
+
+def output_enum(e, indent=0):
+ attrs = 'name="%s"' % e.name
+ if e.default_count > 0:
+ tab = spaces(37, attrs)
+ attrs += '%scount="%d"' % (tab, e.default_count)
+ tab = spaces(48, attrs)
+ val = "%04x" % e.value
+ val = "0x" + val.upper()
+ attrs += '%svalue="%s"' % (tab, val)
+
+ # no child
+ if not e.functions:
+ print '%s<enum %s/>' % (spaces(indent), attrs)
+ return
+
+ print '%s<enum %s>' % (spaces(indent), attrs)
+ for key, val in e.functions.iteritems():
+ attrs = 'name="%s"' % key
+ if val[0] != e.default_count:
+ attrs += ' count="%d"' % val[0]
+ if not val[1]:
+ attrs += ' mode="get"'
+
+ print '%s<size %s/>' % (spaces(indent * 2), attrs)
+
+ print '%s</enum>' % spaces(indent)
+
+def output_type(t, indent=0):
+ tab = spaces(16, t.name)
+ attrs = 'name="%s"%ssize="%d"' % (t.name, tab, t.size)
+ ctype = t.type_expr.string()
+ if ctype.find("unsigned") != -1:
+ attrs += ' unsigned="true"'
+ elif ctype.find("signed") == -1:
+ attrs += ' float="true"'
+ print '%s<type %s/>' % (spaces(indent), attrs)
+
+def output_function(f, indent=0):
+ attrs = 'name="%s"' % f.name
+ if f.offset > 0:
+ if f.assign_offset:
+ attrs += ' offset="assign"'
+ else:
+ attrs += ' offset="%d"' % f.offset
+ print '%s<function %s>' % (spaces(indent), attrs)
+
+ for p in f.parameters:
+ attrs = 'name="%s" type="%s"' \
+ % (p.name, p.type_expr.original_string)
+ print '%s<param %s/>' % (spaces(indent * 2), attrs)
+ if f.return_type != "void":
+ attrs = 'type="%s"' % f.return_type
+ print '%s<return %s/>' % (spaces(indent * 2), attrs)
+
+ print '%s</function>' % spaces(indent)
+
+def output_category(api, indent=0):
+ enums = api.enums_by_name.values()
+ enums.sort(cmp_enum)
+ types = api.types_by_name.values()
+ types.sort(cmp_type)
+ functions = api.functions_by_name.values()
+ functions.sort(cmp_function)
+
+ for e in enums:
+ output_enum(e, indent)
+ if enums and types:
+ print
+ for t in types:
+ output_type(t, indent)
+ if enums or types:
+ print
+ for f in functions:
+ output_function(f, indent)
+ if f != functions[-1]:
+ print
+
+def is_api_empty(api):
+ return bool(not api.enums_by_name and
+ not api.types_by_name and
+ not api.functions_by_name)
+
+def show_usage(ops):
+ print "Usage: %s [-k elts] <%s> <file1> <file2>" % (sys.argv[0], "|".join(ops))
+ print " -k elts A comma separated string of types of elements to"
+ print " skip. Possible types are enum, type, and function."
+ sys.exit(1)
+
+def main():
+ ops = ["union", "intersection", "difference"]
+ elts = ["enum", "type", "function"]
+
+ try:
+ options, args = getopt.getopt(sys.argv[1:], "k:")
+ except Exception, e:
+ show_usage(ops)
+
+ if len(args) != 3:
+ show_usage(ops)
+ op, file1, file2 = args
+ if op not in ops:
+ show_usage(ops)
+
+ skips = []
+ for opt, val in options:
+ if opt == "-k":
+ skips = val.split(",")
+
+ for elt in skips:
+ try:
+ elts.remove(elt)
+ except ValueError:
+ show_usage(ops)
+
+ api1 = gl_XML.parse_GL_API(file1, glX_XML.glx_item_factory())
+ api2 = gl_XML.parse_GL_API(file2, glX_XML.glx_item_factory())
+
+ set = ApiSet(api1, elts)
+ func = getattr(set, op)
+ result = func(api2)
+
+ if not is_api_empty(result):
+ cat_name = "%s_of_%s_and_%s" \
+ % (op, os.path.basename(file1), os.path.basename(file2))
+
+ print '<?xml version="1.0"?>'
+ print '<!DOCTYPE OpenGLAPI SYSTEM "%s/gl_API.dtd">' % GLAPI
+ print
+ print '<OpenGLAPI>'
+ print
+ print '<category name="%s">' % (cat_name)
+ output_category(result, 4)
+ print '</category>'
+ print
+ print '</OpenGLAPI>'
+
+if __name__ == "__main__":
+ main()
diff --git a/src/mesa/es/glapi/gl_parse_header.py b/src/mesa/es/glapi/gl_parse_header.py
new file mode 100644
index 0000000000..897bc2b3c3
--- /dev/null
+++ b/src/mesa/es/glapi/gl_parse_header.py
@@ -0,0 +1,450 @@
+#!/usr/bin/python
+#
+# Copyright (C) Chia-I Wu <olvaffe@gmail.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# IBM 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.
+
+import sys
+import os.path
+import getopt
+import re
+
+GLAPI = "../../glapi"
+sys.path.append(GLAPI)
+
+class HeaderParser(object):
+ """Parser for GL header files."""
+
+ def __init__(self, verbose=0):
+ # match #if and #ifdef
+ self.IFDEF = re.compile('#\s*if(n?def\s+(?P<ifdef>\w+)|\s+(?P<if>.+))')
+ # match #endif
+ self.ENDIF = re.compile('#\s*endif')
+ # match typedef abc def;
+ self.TYPEDEF = re.compile('typedef\s+(?P<from>[\w ]+)\s+(?P<to>\w+);')
+ # match #define XYZ VAL
+ self.DEFINE = re.compile('#\s*define\s+(?P<key>\w+)(?P<value>\s+[\w"]*)?')
+ # match GLAPI
+ self.GLAPI = re.compile('^GL_?API(CALL)?\s+(?P<return>[\w\s*]+[\w*])\s+(GL)?_?APIENTRY\s+(?P<name>\w+)\s*\((?P<params>[\w\s(,*\[\])]+)\)\s*;')
+
+ self.split_params = re.compile('\s*,\s*')
+ self.split_ctype = re.compile('(\W)')
+ # ignore GL_VERSION_X_Y
+ self.ignore_enum = re.compile('GL(_ES)?_VERSION(_ES_C[ML])?_\d_\d')
+
+ self.verbose = verbose
+ self._reset()
+
+ def _reset(self):
+ """Reset to initial state."""
+ self.ifdef_levels = []
+ self.need_char = False
+
+ # use typeexpr?
+ def _format_ctype(self, ctype, fix=True):
+ """Format a ctype string, optionally fix it."""
+ # split the type string
+ tmp = self.split_ctype.split(ctype)
+ tmp = [s for s in tmp if s and s != " "]
+
+ pretty = ""
+ for i in xrange(len(tmp)):
+ # add missing GL prefix
+ if (fix and tmp[i] != "const" and tmp[i] != "*" and
+ not tmp[i].startswith("GL")):
+ tmp[i] = "GL" + tmp[i]
+
+ if i == 0:
+ pretty = tmp[i]
+ else:
+ sep = " "
+ if tmp[i - 1] == "*":
+ sep = ""
+ pretty += sep + tmp[i]
+ return pretty
+
+ # use typeexpr?
+ def _get_ctype_attrs(self, ctype):
+ """Get the attributes of a ctype."""
+ is_float = (ctype.find("float") != -1 or ctype.find("double") != -1)
+ is_signed = not (ctype.find("unsigned") != -1)
+
+ size = 0
+ if ctype.find("char") != -1:
+ size = 1
+ elif ctype.find("short") != -1:
+ size = 2
+ elif ctype.find("int") != -1:
+ size = 4
+ elif is_float:
+ if ctype.find("float") != -1:
+ size = 4
+ else:
+ size = 8
+
+ return (size, is_float, is_signed)
+
+ def _parse_define(self, line):
+ """Parse a #define line for an <enum>."""
+ m = self.DEFINE.search(line)
+ if not m:
+ if self.verbose and line.find("#define") >= 0:
+ print "ignore %s" % (line)
+ return None
+
+ key = m.group("key").strip()
+ val = m.group("value").strip()
+
+ # enum must begin with GL_ and be all uppercase
+ if ((not (key.startswith("GL_") and key.isupper())) or
+ (self.ignore_enum.match(key) and val == "1")):
+ if self.verbose:
+ print "ignore enum %s" % (key)
+ return None
+
+ return (key, val)
+
+ def _parse_typedef(self, line):
+ """Parse a typedef line for a <type>."""
+ m = self.TYPEDEF.search(line)
+ if not m:
+ if self.verbose and line.find("typedef") >= 0:
+ print "ignore %s" % (line)
+ return None
+
+ f = m.group("from").strip()
+ t = m.group("to").strip()
+ if not t.startswith("GL"):
+ if self.verbose:
+ print "ignore type %s" % (t)
+ return None
+ attrs = self._get_ctype_attrs(f)
+
+ return (f, t, attrs)
+
+ def _parse_gl_api(self, line):
+ """Parse a GLAPI line for a <function>."""
+ m = self.GLAPI.search(line)
+ if not m:
+ if self.verbose and line.find("APIENTRY") >= 0:
+ print "ignore %s" % (line)
+ return None
+
+ rettype = m.group("return")
+ rettype = self._format_ctype(rettype)
+ if rettype == "GLvoid":
+ rettype = ""
+
+ name = m.group("name")
+
+ param_str = m.group("params")
+ chunks = self.split_params.split(param_str)
+ chunks = [s.strip() for s in chunks]
+ if len(chunks) == 1 and (chunks[0] == "void" or chunks[0] == "GLvoid"):
+ chunks = []
+
+ params = []
+ for c in chunks:
+ # split type and variable name
+ idx = c.rfind("*")
+ if idx < 0:
+ idx = c.rfind(" ")
+ if idx >= 0:
+ idx += 1
+ ctype = c[:idx]
+ var = c[idx:]
+ else:
+ ctype = c
+ var = "unnamed"
+
+ # convert array to pointer
+ idx = var.find("[")
+ if idx >= 0:
+ var = var[:idx]
+ ctype += "*"
+
+ ctype = self._format_ctype(ctype)
+ var = var.strip()
+
+ if not self.need_char and ctype.find("GLchar") >= 0:
+ self.need_char = True
+
+ params.append((ctype, var))
+
+ return (rettype, name, params)
+
+ def _change_level(self, line):
+ """Parse a #ifdef line and change level."""
+ m = self.IFDEF.search(line)
+ if m:
+ ifdef = m.group("ifdef")
+ if not ifdef:
+ ifdef = m.group("if")
+ self.ifdef_levels.append(ifdef)
+ return True
+ m = self.ENDIF.search(line)
+ if m:
+ self.ifdef_levels.pop()
+ return True
+ return False
+
+ def _read_header(self, header):
+ """Open a header file and read its contents."""
+ lines = []
+ try:
+ fp = open(header, "rb")
+ lines = fp.readlines()
+ fp.close()
+ except IOError, e:
+ print "failed to read %s: %s" % (header, e)
+ return lines
+
+ def _cmp_enum(self, enum1, enum2):
+ """Compare two enums."""
+ # sort by length of the values as strings
+ val1 = enum1[1]
+ val2 = enum2[1]
+ ret = len(val1) - len(val2)
+ # sort by the values
+ if not ret:
+ val1 = int(val1, 16)
+ val2 = int(val2, 16)
+ ret = val1 - val2
+ # in case int cannot hold the result
+ if ret > 0:
+ ret = 1
+ elif ret < 0:
+ ret = -1
+ # sort by the names
+ if not ret:
+ if enum1[0] < enum2[0]:
+ ret = -1
+ elif enum1[0] > enum2[0]:
+ ret = 1
+ return ret
+
+ def _cmp_type(self, type1, type2):
+ """Compare two types."""
+ attrs1 = type1[2]
+ attrs2 = type2[2]
+ # sort by type size
+ ret = attrs1[0] - attrs2[0]
+ # float is larger
+ if not ret:
+ ret = attrs1[1] - attrs2[1]
+ # signed is larger
+ if not ret:
+ ret = attrs1[2] - attrs2[2]
+ # reverse
+ ret = -ret
+ return ret
+
+ def _cmp_function(self, func1, func2):
+ """Compare two functions."""
+ name1 = func1[1]
+ name2 = func2[1]
+ ret = 0
+ # sort by the names
+ if name1 < name2:
+ ret = -1
+ elif name1 > name2:
+ ret = 1
+ return ret
+
+ def _postprocess_dict(self, hdict):
+ """Post-process a header dict and return an ordered list."""
+ hlist = []
+ largest = 0
+ for key, cat in hdict.iteritems():
+ size = len(cat["enums"]) + len(cat["types"]) + len(cat["functions"])
+ # ignore empty category
+ if not size:
+ continue
+
+ cat["enums"].sort(self._cmp_enum)
+ # remove duplicates
+ dup = []
+ for i in xrange(1, len(cat["enums"])):
+ if cat["enums"][i] == cat["enums"][i - 1]:
+ dup.insert(0, i)
+ for i in dup:
+ e = cat["enums"].pop(i)
+ if self.verbose:
+ print "remove duplicate enum %s" % e[0]
+
+ cat["types"].sort(self._cmp_type)
+ cat["functions"].sort(self._cmp_function)
+
+ # largest category comes first
+ if size > largest:
+ hlist.insert(0, (key, cat))
+ largest = size
+ else:
+ hlist.append((key, cat))
+ return hlist
+
+ def parse(self, header):
+ """Parse a header file."""
+ self._reset()
+
+ if self.verbose:
+ print "Parsing %s" % (header)
+
+ hdict = {}
+ lines = self._read_header(header)
+ for line in lines:
+ if self._change_level(line):
+ continue
+
+ # skip until the first ifdef (i.e. __gl_h_)
+ if not self.ifdef_levels:
+ continue
+
+ cat_name = os.path.basename(header)
+ # check if we are in an extension
+ if (len(self.ifdef_levels) > 1 and
+ self.ifdef_levels[-1].startswith("GL_")):
+ cat_name = self.ifdef_levels[-1]
+
+ try:
+ cat = hdict[cat_name]
+ except KeyError:
+ cat = {
+ "enums": [],
+ "types": [],
+ "functions": []
+ }
+ hdict[cat_name] = cat
+
+ key = "enums"
+ elem = self._parse_define(line)
+ if not elem:
+ key = "types"
+ elem = self._parse_typedef(line)
+ if not elem:
+ key = "functions"
+ elem = self._parse_gl_api(line)
+
+ if elem:
+ cat[key].append(elem)
+
+ if self.need_char:
+ if self.verbose:
+ print "define GLchar"
+ elem = self._parse_typedef("typedef char GLchar;")
+ cat["types"].append(elem)
+ return self._postprocess_dict(hdict)
+
+def spaces(n, str=""):
+ spaces = n - len(str)
+ if spaces < 1:
+ spaces = 1
+ return " " * spaces
+
+def output_xml(name, hlist):
+ """Output a parsed header in OpenGLAPI XML."""
+
+ for i in xrange(len(hlist)):
+ cat_name, cat = hlist[i]
+
+ print '<category name="%s">' % (cat_name)
+ indent = 4
+
+ for enum in cat["enums"]:
+ name = enum[0][3:]
+ value = enum[1]
+ tab = spaces(41, name)
+ attrs = 'name="%s"%svalue="%s"' % (name, tab, value)
+ print '%s<enum %s/>' % (spaces(indent), attrs)
+
+ if cat["enums"] and cat["types"]:
+ print
+
+ for type in cat["types"]:
+ ctype = type[0]
+ size, is_float, is_signed = type[2]
+
+ attrs = 'name="%s"' % (type[1][2:])
+ attrs += spaces(16, attrs) + 'size="%d"' % (size)
+ if is_float:
+ attrs += ' float="true"'
+ elif not is_signed:
+ attrs += ' unsigned="true"'
+
+ print '%s<type %s/>' % (spaces(indent), attrs)
+
+ for func in cat["functions"]:
+ print
+ ret = func[0]
+ name = func[1][2:]
+ params = func[2]
+
+ attrs = 'name="%s" offset="assign"' % name
+ print '%s<function %s>' % (spaces(indent), attrs)
+
+ for param in params:
+ attrs = 'name="%s" type="%s"' % (param[1], param[0])
+ print '%s<param %s/>' % (spaces(indent * 2), attrs)
+ if ret:
+ attrs = 'type="%s"' % ret
+ print '%s<return %s/>' % (spaces(indent * 2), attrs)
+
+ print '%s</function>' % spaces(indent)
+
+ print '</category>'
+ print
+
+def show_usage():
+ print "Usage: %s [-v] <header> ..." % sys.argv[0]
+ sys.exit(1)
+
+def main():
+ try:
+ args, headers = getopt.getopt(sys.argv[1:], "v")
+ except Exception, e:
+ show_usage()
+ if not headers:
+ show_usage()
+
+ verbose = 0
+ for arg in args:
+ if arg[0] == "-v":
+ verbose += 1
+
+ need_xml_header = True
+ parser = HeaderParser(verbose)
+ for h in headers:
+ h = os.path.abspath(h)
+ hlist = parser.parse(h)
+
+ if need_xml_header:
+ print '<?xml version="1.0"?>'
+ print '<!DOCTYPE OpenGLAPI SYSTEM "%s/gl_API.dtd">' % GLAPI
+ need_xml_header = False
+
+ print
+ print '<!-- %s -->' % (h)
+ print '<OpenGLAPI>'
+ print
+ output_xml(h, hlist)
+ print '</OpenGLAPI>'
+
+if __name__ == '__main__':
+ main()
diff --git a/src/mesa/es/main/APIspec.txt b/src/mesa/es/main/APIspec.txt
new file mode 100644
index 0000000000..08ce699696
--- /dev/null
+++ b/src/mesa/es/main/APIspec.txt
@@ -0,0 +1,2974 @@
+## Adapted from Mesa and Chromium.
+# Python scripts read this file and generate various C files.
+
+# Possible lines:
+# name Name of the function (without "gl" prefix). Required.
+#
+# return Datatype of returned value, or void. Required.
+#
+# param Zero or more of these lines may be present. Each describes a
+# function parameter. Two fields follow: parameter name and the
+# parameter type (which may be several tokens like "const GLvoid *").
+#
+# vector Used to indicate the size of constant arrays referenced by
+# the given parameter. (If the number of elements in the
+# array is dependent on another parameter, use "dependentvector"
+# (below) instead.)
+# Two fields follow: the parameter name (previously defined by a
+# 'param' line) and a number indicating how may elements are
+# referenced by the vector. If the number is unknown, don't use
+# a vector line. Example for glGetClipPlane:
+# vector equation 4
+#
+# dependentvector Used to indicate how many elements are referenced by
+# pointer params, if the number depends on the value of another
+# parameter. It is followed by the parameter name of the vector
+# parameter (previously defined by a 'param' line, one of the
+# potential sizes of the array, the name of the controlling
+# parameter, and a list (one or more) of parameter values of the
+# controlling parameter that are associated with the given size.
+# There will always be more than one line of this type (or otherwise
+# you could have used the "vector" specifier above).
+# As a convenience, each parameter value named in a
+# "dependentvector" specifier will also be considered as a
+# "paramprop" specifier.
+# Example for glLightfv:
+# dependentvector params 4 pname GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION
+# dependentvector params 3 pname GL_SPOT_DIRECTION
+# dependentvector params 1 pname GL_SPOT_EXPONENT GL_SPOT_CUTOFF GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION
+#
+# category May be 1.x to indicate that the function belongs to OpenGL
+# version 1.x. Or may be the name of an extension such as
+# GL_ARB_multitexture. Or may be GLES1.x to indicate
+# that the function belongs to GLES version 1.x. Required.
+# May have more than one token to indicate that a function
+# belongs to more than one category.
+#
+# alias Names the Mesa function _mesa_<alias> that will be called.
+# Mostly used when the function was originally defined and
+# introduced into Mesa as an extension function (i.e. <func>ARB);
+# even though the function loses the extension as it is adopted
+# into the core, the Mesa support remains named the same
+# (for compatibility).
+#
+# aliasprefix May be used to change the default Mesa support functional
+# prefix on a per-function basis. By default, it's "_mesa_";
+# but this allows it to be changed (e.g. to "_vbo_" for many
+# of the core functions).
+#
+# props An optional list of properties for this function. Possible
+# properties include:
+# get - the function is a state-getter
+#
+# convertalias
+#
+# convertparams
+#
+# checkparam
+#
+# checkdependentparam
+
+name Color4f
+aliasprefix _vbo_
+return void
+param red GLfloat
+param green GLfloat
+param blue GLfloat
+param alpha GLfloat
+category 1.0 GLES1.1
+
+name Color4ub
+return void
+param red GLubyte
+param green GLubyte
+param blue GLubyte
+param alpha GLubyte
+aliasprefix _vbo_
+convertalias Color4f
+convertparams GLfloat red green blue alpha
+category 1.0 GLES1.1
+
+name Color4x
+return void
+param red GLfixed
+param green GLfixed
+param blue GLfixed
+param alpha GLfixed
+aliasprefix _vbo_
+convertalias Color4f
+convertparams GLfloat red green blue alpha
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name ClipPlane
+return void
+param plane GLenum
+checkparam plane GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5
+param equation const GLdouble *
+vector equation 4
+category 1.0
+
+name ClipPlanef
+return void
+param plane GLenum
+checkparam plane GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5
+param equation const GLfloat *
+vector equation 4
+convertalias ClipPlane
+convertparams GLdouble equation
+category GLES1.1 GLES1.1:OES_single_precision
+
+name ClipPlanex
+return void
+param plane GLenum
+checkparam plane GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5
+param equation const GLfixed *
+vector equation 4
+convertalias ClipPlane
+convertparams GLdouble equation
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name CullFace
+return void
+param mode GLenum
+checkparam mode GL_FRONT GL_BACK GL_FRONT_AND_BACK
+category 1.0 GLES1.1 GLES2.0
+
+name Fogf
+return void
+param pname GLenum
+checkparam pname GL_FOG_MODE GL_FOG_DENSITY GL_FOG_START GL_FOG_END
+param param GLfloat
+checkdependentparam pname GL_FOG_MODE param GL_EXP GL_EXP2 GL_LINEAR
+category 1.0 GLES1.1
+
+name Fogfv
+return void
+param pname GLenum
+param params const GLfloat *
+paramvec params GL_LINEAR
+dependentvector params 4 pname GL_FOG_COLOR
+dependentvector params 1 pname GL_FOG_DENSITY GL_FOG_START GL_FOG_END
+dependentvector params 1 pname GL_FOG_MODE
+checkdependentparam pname GL_FOG_MODE params GL_EXP GL_EXP2 GL_LINEAR
+category 1.0 GLES1.1
+
+name Fogx
+return void
+param pname GLenum
+checkparam pname GL_FOG_MODE GL_FOG_DENSITY GL_FOG_START GL_FOG_END
+param param GLfixed
+checkdependentparam pname GL_FOG_MODE param GL_EXP GL_EXP2 GL_LINEAR
+convertalias Fogf
+convertparams GLfloat param
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name Fogxv
+return void
+param pname GLenum
+param params const GLfixed *
+dependentvector params 4 pname GL_FOG_COLOR
+dependentvector params 1 pname GL_FOG_DENSITY GL_FOG_START GL_FOG_END
+dependentvector params 1 pname GL_FOG_MODE
+checkdependentparam pname GL_FOG_MODE params GL_EXP GL_EXP2 GL_LINEAR
+convertalias Fogfv
+convertparams GLfloat params
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name FrontFace
+return void
+param mode GLenum
+checkparam mode GL_CW GL_CCW
+category 1.0 GLES1.1 GLES2.0
+
+name Hint
+return void
+param target GLenum
+param mode GLenum
+checkparam target GLES1.1:GL_FOG_HINT GLES1.1:GL_LINE_SMOOTH_HINT GLES1.1:GL_PERSPECTIVE_CORRECTION_HINT GLES1.1:GL_POINT_SMOOTH_HINT
+checkparam target GL_GENERATE_MIPMAP_HINT
+checkparam mode GL_FASTEST GL_NICEST GL_DONT_CARE
+# OES_standard_derivatives
+checkparam target GLES2.0:GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES
+category GLES1.1 GLES2.0
+
+name Lightf
+return void
+param light GLenum
+checkparam light GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7
+param pname GLenum
+checkparam pname GL_SPOT_EXPONENT GL_SPOT_CUTOFF GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION
+param param GLfloat
+category 1.0 GLES1.1
+
+name Lightfv
+return void
+param light GLenum
+checkparam light GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7
+param pname GLenum
+param params const GLfloat *
+paramvec params 0.0 1.0 1.0 0.0
+dependentvector params 4 pname GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION
+dependentvector params 3 pname GL_SPOT_DIRECTION
+dependentvector params 1 pname GL_SPOT_EXPONENT GL_SPOT_CUTOFF GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION
+category 1.0 1.1 GLES1.1
+
+name Lightx
+return void
+param light GLenum
+checkparam light GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7
+param pname GLenum
+checkparam pname GL_SPOT_EXPONENT GL_SPOT_CUTOFF GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION
+param param GLfixed
+convertalias Lightf
+convertparams GLfloat param
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name Lightxv
+return void
+param light GLenum
+checkparam light GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7
+param pname GLenum
+param params const GLfixed *
+dependentvector params 4 pname GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION
+dependentvector params 3 pname GL_SPOT_DIRECTION
+dependentvector params 1 pname GL_SPOT_EXPONENT GL_SPOT_CUTOFF GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION
+convertalias Lightfv
+convertparams GLfloat params
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name LightModelf
+return void
+param pname GLenum
+checkparam pname GL_LIGHT_MODEL_TWO_SIDE
+param param GLfloat
+checkdependentparam pname GL_LIGHT_MODEL_TWO_SIDE param GL_TRUE GL_FALSE
+category 1.0 GLES1.1
+
+name LightModelfv
+return void
+param pname GLenum
+param params const GLfloat *
+dependentvector params 4 pname GL_LIGHT_MODEL_AMBIENT
+dependentvector params 1 pname GL_LIGHT_MODEL_TWO_SIDE
+category 1.0 GLES1.1
+
+name LightModelx
+return void
+param pname GLenum
+checkparam pname GL_LIGHT_MODEL_TWO_SIDE
+param param GLfixed
+checkdependentparam pname GL_LIGHT_MODEL_TWO_SIDE param GL_TRUE GL_FALSE
+convertalias LightModelf
+convertparams GLfloat param
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name LightModelxv
+return void
+param pname GLenum
+param params const GLfixed *
+dependentvector params 4 pname GL_LIGHT_MODEL_AMBIENT
+dependentvector params 1 pname GL_LIGHT_MODEL_TWO_SIDE
+checkdependentparam pname GL_LIGHT_MODEL_TWO_SIDE params GL_TRUE GL_FALSE
+convertalias LightModelfv
+convertparams GLfloat params
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name LineWidth
+return void
+param width GLfloat
+category 1.0 GLES1.1 GLES2.0
+
+name LineWidthx
+return void
+param width GLfixed
+convertalias LineWidth
+convertparams GLfloat width
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name Materialf
+aliasprefix _vbo_
+return void
+param face GLenum
+checkparam face GL_FRONT_AND_BACK
+param pname GLenum
+checkparam pname GL_SHININESS
+param param GLfloat
+category 1.0 GLES1.1
+
+name Materialfv
+aliasprefix _vbo_
+return void
+param face GLenum
+checkparam face GL_FRONT_AND_BACK
+param pname GLenum
+param params const GLfloat *
+paramvec params 0.8 0.8 0.5 0.1
+dependentvector params 4 pname GL_AMBIENT GL_DIFFUSE GL_AMBIENT_AND_DIFFUSE GL_SPECULAR GL_EMISSION
+dependentvector params 1 pname GL_SHININESS
+category 1.0 GLES1.1
+
+name Materialx
+return void
+param face GLenum
+checkparam face GL_FRONT_AND_BACK
+param pname GLenum
+checkparam pname GL_SHININESS
+param param GLfixed
+aliasprefix _vbo_
+convertalias Materialf
+convertparams GLfloat param
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name Materialxv
+return void
+param face GLenum
+checkparam face GL_FRONT_AND_BACK
+param pname GLenum
+param params const GLfixed *
+dependentvector params 4 pname GL_AMBIENT GL_DIFFUSE GL_AMBIENT_AND_DIFFUSE GL_SPECULAR GL_EMISSION
+dependentvector params 1 pname GL_SHININESS
+aliasprefix _vbo_
+convertalias Materialfv
+convertparams GLfloat params
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name PointSize
+return void
+param size GLfloat
+category 1.0 GLES1.1
+
+name PointSizex
+return void
+param size GLfixed
+convertalias PointSize
+convertparams GLfloat size
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name PointSizePointer
+return void
+param type GLenum
+checkparam type GL_FIXED GL_FLOAT
+param stride GLsizei
+param pointer const GLvoid *
+props setclient
+# OES_vertex_half_float - not in glext.h
+#checkparam type GL_HALF_FLOAT_OES
+category GLES1.1:OES_point_size_array
+
+name Scissor
+return void
+param x GLint
+param y GLint
+param width GLsizei
+param height GLsizei
+category 1.0 GLES1.1 GLES2.0
+
+name ShadeModel
+return void
+param mode GLenum
+checkparam mode GL_FLAT GL_SMOOTH
+category 1.0 GLES1.1
+
+name TexParameterf
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP
+param pname GLenum
+param param GLfloat
+checkdependentparam pname GL_TEXTURE_WRAP_S param GL_CLAMP_TO_EDGE GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+checkdependentparam pname GL_TEXTURE_WRAP_T param GL_CLAMP_TO_EDGE GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+checkdependentparam pname GL_TEXTURE_MIN_FILTER param GL_NEAREST GL_LINEAR GL_NEAREST_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_NEAREST GL_LINEAR_MIPMAP_LINEAR
+checkdependentparam pname GL_TEXTURE_MAG_FILTER param GL_NEAREST GL_LINEAR
+checkdependentparam pname GL_GENERATE_MIPMAP param GLES1.1:GL_TRUE GLES1.1:GL_FALSE
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_OES
+# OES_texture_mirrored_repeat
+checkdependentparam pname GL_TEXTURE_WRAP_S param GLES1.1:GL_MIRRORED_REPEAT_OES
+checkdependentparam pname GL_TEXTURE_WRAP_T param GLES1.1:GL_MIRRORED_REPEAT_OES
+# EXT_texture_filter_anisotropic
+checkparam pname GL_TEXTURE_MAX_ANISOTROPY_EXT
+# OES_texture_3D
+checkdependentparam pname GL_TEXTURE_WRAP_R_OES param GLES2.0:GL_CLAMP_TO_EDGE GLES2.0:GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+category GLES1.1 GLES2.0
+
+name TexParameterfv
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP
+param pname GLenum
+param params const GLfloat *
+dependentvector params 1 pname GL_TEXTURE_WRAP_S GL_TEXTURE_WRAP_T GL_TEXTURE_MIN_FILTER GL_TEXTURE_MAG_FILTER GLES1.1:GL_GENERATE_MIPMAP
+checkdependentparam pname GL_TEXTURE_WRAP_S params GL_CLAMP_TO_EDGE GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+checkdependentparam pname GL_TEXTURE_WRAP_T params GL_CLAMP_TO_EDGE GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+checkdependentparam pname GL_TEXTURE_MIN_FILTER params GL_NEAREST GL_LINEAR GL_NEAREST_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_NEAREST GL_LINEAR_MIPMAP_LINEAR
+checkdependentparam pname GL_TEXTURE_MAG_FILTER params GL_NEAREST GL_LINEAR
+checkdependentparam pname GL_GENERATE_MIPMAP params GLES1.1:GL_TRUE GLES1.1:GL_FALSE
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_OES
+# OES_texture_mirrored_repeat
+checkdependentparam pname GL_TEXTURE_WRAP_S params GLES1.1:GL_MIRRORED_REPEAT_OES
+checkdependentparam pname GL_TEXTURE_WRAP_T params GLES1.1:GL_MIRRORED_REPEAT_OES
+# EXT_texture_filter_anisotropic
+dependentvector params 1 pname GL_TEXTURE_MAX_ANISOTROPY_EXT
+# OES_texture_3D
+checkdependentparam pname GL_TEXTURE_WRAP_R_OES params GLES2.0:GL_CLAMP_TO_EDGE GLES2.0:GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+# OES_draw_texture - not in gl2ext.h yet, not supported in Mesa yet
+#dependentvector params 4 pname GLES1.1:GL_TEXTURE_CROP_RECT_OES
+category GLES1.1 GLES2.0
+
+name TexParameteri
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP
+param pname GLenum
+param param GLint
+checkdependentparam pname GL_TEXTURE_WRAP_S param GL_CLAMP_TO_EDGE GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+checkdependentparam pname GL_TEXTURE_WRAP_T param GL_CLAMP_TO_EDGE GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+checkdependentparam pname GL_TEXTURE_MIN_FILTER param GL_NEAREST GL_LINEAR GL_NEAREST_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_NEAREST GL_LINEAR_MIPMAP_LINEAR
+checkdependentparam pname GL_TEXTURE_MAG_FILTER param GL_NEAREST GL_LINEAR
+checkdependentparam pname GL_GENERATE_MIPMAP param GLES1.1:GL_TRUE GLES1.1:GL_FALSE
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_OES
+# OES_texture_mirrored_repeat
+checkdependentparam pname GL_TEXTURE_WRAP_S param GLES1.1:GL_MIRRORED_REPEAT_OES
+checkdependentparam pname GL_TEXTURE_WRAP_T param GLES1.1:GL_MIRRORED_REPEAT_OES
+# EXT_texture_filter_anisotropic
+checkparam pname GL_TEXTURE_MAX_ANISOTROPY_EXT
+# OES_texture_3D
+checkdependentparam pname GL_TEXTURE_WRAP_R_OES param GLES2.0:GL_CLAMP_TO_EDGE GLES2.0:GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+category GLES1.1 GLES2.0
+
+name TexParameteriv
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP
+param pname GLenum
+param params const GLint *
+dependentvector params 1 pname GL_TEXTURE_WRAP_S GL_TEXTURE_WRAP_T GL_TEXTURE_MIN_FILTER GL_TEXTURE_MAG_FILTER GLES1.1:GL_GENERATE_MIPMAP
+checkdependentparam pname GL_TEXTURE_WRAP_S params GL_CLAMP_TO_EDGE GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+checkdependentparam pname GL_TEXTURE_WRAP_T params GL_CLAMP_TO_EDGE GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+checkdependentparam pname GL_TEXTURE_MIN_FILTER params GL_NEAREST GL_LINEAR GL_NEAREST_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_NEAREST GL_LINEAR_MIPMAP_LINEAR
+checkdependentparam pname GL_TEXTURE_MAG_FILTER params GL_NEAREST GL_LINEAR
+checkdependentparam pname GL_GENERATE_MIPMAP params GLES1.1:GL_TRUE GLES1.1:GL_FALSE
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_OES
+# OES_texture_mirrored_repeat
+checkdependentparam pname GL_TEXTURE_WRAP_S params GLES1.1:GL_MIRRORED_REPEAT_OES
+checkdependentparam pname GL_TEXTURE_WRAP_T params GLES1.1:GL_MIRRORED_REPEAT_OES
+# EXT_texture_filter_anisotropic
+dependentvector params 1 pname GL_TEXTURE_MAX_ANISOTROPY_EXT
+# OES_texture_3D
+checkdependentparam pname GL_TEXTURE_WRAP_R_OES params GLES2.0:GL_CLAMP_TO_EDGE GLES2.0:GL_REPEAT GLES2.0:GL_MIRRORED_REPEAT
+# OES_draw_texture - not in gl2ext.h yet
+dependentvector params 4 pname GLES1.1:GL_TEXTURE_CROP_RECT_OES
+category GLES1.1 GLES2.0
+
+name TexParameterx
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D
+param pname GLenum
+param param GLfixed
+checkdependentparam pname GL_TEXTURE_WRAP_S param GL_CLAMP_TO_EDGE GL_REPEAT
+checkdependentparam pname GL_TEXTURE_WRAP_T param GL_CLAMP_TO_EDGE GL_REPEAT
+checkdependentparam pname GL_TEXTURE_MIN_FILTER param GL_NEAREST GL_LINEAR GL_NEAREST_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_NEAREST GL_LINEAR_MIPMAP_LINEAR
+checkdependentparam pname GL_TEXTURE_MAG_FILTER param GL_NEAREST GL_LINEAR
+checkdependentparam pname GL_GENERATE_MIPMAP param GL_TRUE GL_FALSE
+convertalias TexParameterf
+convertparams GLfloat param
+# OES_texture_cube_map
+checkparam target GL_TEXTURE_CUBE_MAP_OES
+# OES_texture_mirrored_repeat
+checkdependentparam pname GL_TEXTURE_WRAP_S param GL_MIRRORED_REPEAT_OES
+checkdependentparam pname GL_TEXTURE_WRAP_T param GL_MIRRORED_REPEAT_OES
+# EXT_texture_filter_anisotropic
+checkparam pname GL_TEXTURE_MAX_ANISOTROPY_EXT
+category GLES1.1 GLES1.1:OES_fixed_point
+
+
+# Same is true for this function.
+name TexParameterxv
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GL_TEXTURE_CUBE_MAP_OES
+param pname GLenum
+param params const GLfixed *
+vector params 1
+dependentvector params 1 pname GL_TEXTURE_WRAP_S GL_TEXTURE_WRAP_T GL_TEXTURE_MIN_FILTER GL_TEXTURE_MAG_FILTER GL_GENERATE_MIPMAP
+checkdependentparam pname GL_TEXTURE_WRAP_S params GL_CLAMP_TO_EDGE GL_REPEAT
+checkdependentparam pname GL_TEXTURE_WRAP_T params GL_CLAMP_TO_EDGE GL_REPEAT
+checkdependentparam pname GL_TEXTURE_MIN_FILTER params GL_NEAREST GL_LINEAR GL_NEAREST_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_NEAREST GL_LINEAR_MIPMAP_LINEAR
+checkdependentparam pname GL_TEXTURE_MAG_FILTER params GL_NEAREST GL_LINEAR
+checkdependentparam pname GL_GENERATE_MIPMAP params GL_TRUE GL_FALSE
+convertalias TexParameterfv
+convertparams GLfloat params
+# OES_draw_texture - not supported in Mesa yet
+dependentvector params 4 pname GL_TEXTURE_CROP_RECT_OES
+# OES_texture_cube_map
+checkparam target GL_TEXTURE_CUBE_MAP_OES
+# OES_texture_mirrored_repeat
+checkdependentparam pname GL_TEXTURE_WRAP_S params GL_MIRRORED_REPEAT_OES
+checkdependentparam pname GL_TEXTURE_WRAP_T params GL_MIRRORED_REPEAT_OES
+# EXT_texture_filter_anisotropic
+dependentvector params 1 pname GL_TEXTURE_MAX_ANISOTROPY_EXT
+category GLES1.1 GLES1.1:OES_fixed_point
+
+# TexImage2D has *different* versions for GLES1 and GLES2, strangely,
+# with different types for "internalFormat". There's also a few
+# tokens with different spellings.
+name TexImage2D
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D
+param level GLint
+param internalFormat GLint
+param width GLsizei
+param height GLsizei
+param border GLint
+param format GLenum
+param type GLenum
+param pixels const GLvoid *
+checkparam internalFormat /GL_INVALID_VALUE GL_ALPHA GL_LUMINANCE GL_LUMINANCE_ALPHA GL_RGB GL_RGBA
+checkparam border /GL_INVALID_VALUE 0
+# OES_texture_cube_map
+checkparam target GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES
+## OES_packed_depth_stencil - only appears in GLES2 header files?
+#checkdependentparam format GL_DEPTH_STENCIL_OES internalFormat GL_UNSIGNED_INT_24_8_OES
+category 1.0 GLES1.1
+
+name TexImage2D
+return void
+param target GLenum
+param level GLint
+# it is compiled with OpenGL header
+#param internalFormat GLenum
+param internalFormat GLint
+param width GLsizei
+param height GLsizei
+param border GLint
+param format GLenum
+param type GLenum
+param pixels const GLvoid *
+checkparam target GL_TEXTURE_2D GL_TEXTURE_CUBE_MAP_POSITIVE_X GL_TEXTURE_CUBE_MAP_POSITIVE_Y GL_TEXTURE_CUBE_MAP_POSITIVE_Z GL_TEXTURE_CUBE_MAP_NEGATIVE_X GL_TEXTURE_CUBE_MAP_NEGATIVE_Y GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+checkparam internalFormat /GL_INVALID_VALUE GL_ALPHA GL_LUMINANCE GL_LUMINANCE_ALPHA GL_RGB GL_RGBA
+checkparam border /GL_INVALID_VALUE 0
+checkdependentparam format GL_ALPHA type GL_UNSIGNED_BYTE
+checkdependentparam format GL_RGB type GL_UNSIGNED_BYTE GL_UNSIGNED_SHORT_5_6_5
+checkdependentparam format GL_RGBA type GL_UNSIGNED_BYTE GL_UNSIGNED_SHORT_4_4_4_4 GL_UNSIGNED_SHORT_5_5_5_1
+checkdependentparam format GL_LUMINANCE type GL_UNSIGNED_BYTE
+checkdependentparam format GL_LUMINANCE_ALPHA type GL_UNSIGNED_BYTE
+# OES_texture_float
+checkdependentparam format GL_ALPHA type GL_FLOAT
+checkdependentparam format GL_RGB type GL_FLOAT
+checkdependentparam format GL_RGBA type GL_FLOAT
+checkdependentparam format GL_LUMINANCE type GL_FLOAT
+checkdependentparam format GL_LUMINANCE_ALPHA type GL_FLOAT
+# OES_texture_half_float
+checkdependentparam format GL_ALPHA type GL_HALF_FLOAT_OES
+checkdependentparam format GL_RGB type GL_HALF_FLOAT_OES
+checkdependentparam format GL_RGBA type GL_HALF_FLOAT_OES
+checkdependentparam format GL_LUMINANCE type GL_HALF_FLOAT_OES
+checkdependentparam format GL_LUMINANCE_ALPHA type GL_HALF_FLOAT_OES
+# EXT_texture_type_2_10_10_10_REV
+checkdependentparam format GL_RGBA type GL_UNSIGNED_INT_2_10_10_10_REV_EXT
+# OES_depth_texture
+checkdependentparam format GL_DEPTH_COMPONENT type GL_UNSIGNED_SHORT GL_UNSIGNED_INT
+checkparam internalFormat GL_DEPTH_COMPONENT
+category GLES2.0
+
+name TexEnvf
+return void
+param target GLenum
+param pname GLenum
+param param GLfloat
+checkdependentparam target GL_TEXTURE_ENV pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_RGB_SCALE GL_ALPHA_SCALE GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+checkdependentparam pname GL_TEXTURE_ENV_MODE param GL_REPLACE GL_MODULATE GL_DECAL GL_BLEND GL_ADD GL_COMBINE
+checkdependentparam pname GL_COMBINE_RGB param GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT GL_DOT3_RGB GL_DOT3_RGBA
+checkdependentparam pname GL_COMBINE_ALPHA param GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT
+checkdependentparam pname GL_RGB_SCALE param /GL_INVALID_VALUE 1.0 2.0 4.0
+checkdependentparam pname GL_ALPHA_SCALE param /GL_INVALID_VALUE 1.0 2.0 4.0
+checkdependentparam pname GL_SRC0_RGB param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_RGB param GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC0_ALPHA param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_ALPHA param GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_RGB param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_RGB param GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_ALPHA param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_ALPHA param GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_RGB param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_RGB param GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_ALPHA param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_ALPHA param GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+# OES_texture_env_crossbar
+checkdependentparam pname GL_SRC0_RGB param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_RGB param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_RGB param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC0_ALPHA param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_ALPHA param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_ALPHA param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+# OES_point_sprite
+checkdependentparam target GL_POINT_SPRITE_OES pname GL_COORD_REPLACE_OES
+checkdependentparam pname GL_COORD_REPLACE_OES param GL_TRUE GL_FALSE
+category 1.0 GLES1.1
+
+name TexEnvfv
+return void
+param target GLenum
+param pname GLenum
+param params const GLfloat *
+checkdependentparam target GL_POINT_SPRITE_OES pname GL_COORD_REPLACE_OES
+checkdependentparam pname GL_COORD_REPLACE_OES params GL_TRUE GL_FALSE
+checkdependentparam target GL_TEXTURE_ENV pname GL_TEXTURE_ENV_MODE GL_TEXTURE_ENV_COLOR GL_COMBINE_RGB GL_COMBINE_ALPHA GL_RGB_SCALE GL_ALPHA_SCALE GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+checkdependentparam pname GL_TEXTURE_ENV_MODE params GL_REPLACE GL_MODULATE GL_DECAL GL_BLEND GL_ADD GL_COMBINE
+checkdependentparam pname GL_COMBINE_RGB params GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT GL_DOT3_RGB GL_DOT3_RGBA
+checkdependentparam pname GL_COMBINE_ALPHA params GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT
+checkdependentparam pname GL_SRC0_RGB params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_RGB params GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC0_ALPHA params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_ALPHA params GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_RGB params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_RGB params GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_ALPHA params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_ALPHA params GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_RGB params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_RGB params GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_ALPHA params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_ALPHA params GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_RGB_SCALE params /GL_INVALID_VALUE 1.0 2.0 4.0
+checkdependentparam pname GL_ALPHA_SCALE params /GL_INVALID_VALUE 1.0 2.0 4.0
+dependentvector params 4 pname GL_TEXTURE_ENV_COLOR
+dependentvector params 1 pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_COORD_REPLACE_OES GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+dependentvector params 1 pname GL_RGB_SCALE GL_ALPHA_SCALE
+# OES_texture_env_crossbar
+dependentvector params 1 pname GL_SRC0_RGB GL_SRC1_RGB GL_SRC2_RGB GL_SRC0_ALPHA GL_SRC1_ALPHA GL_SRC2_ALPHA
+checkdependentparam pname GL_SRC0_RGB params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_RGB params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_RGB params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC0_ALPHA params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_ALPHA params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_ALPHA params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+category 1.0 GLES1.1
+
+name TexEnvi
+return void
+param target GLenum
+param pname GLenum
+param param GLint
+checkdependentparam target GL_POINT_SPRITE_OES pname GL_COORD_REPLACE_OES
+checkdependentparam pname GL_COORD_REPLACE_OES param GL_TRUE GL_FALSE
+checkdependentparam target GL_TEXTURE_ENV pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_RGB_SCALE GL_ALPHA_SCALE GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+checkdependentparam pname GL_TEXTURE_ENV_MODE param GL_REPLACE GL_MODULATE GL_DECAL GL_BLEND GL_ADD GL_COMBINE
+checkdependentparam pname GL_COMBINE_RGB param GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT GL_DOT3_RGB GL_DOT3_RGBA
+checkdependentparam pname GL_COMBINE_ALPHA param GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT
+checkdependentparam pname GL_RGB_SCALE param /GL_INVALID_VALUE 1.0 2.0 4.0
+checkdependentparam pname GL_ALPHA_SCALE param /GL_INVALID_VALUE 1.0 2.0 4.0
+checkdependentparam pname GL_SRC0_RGB param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_RGB param GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC0_ALPHA param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_ALPHA param GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_RGB param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_RGB param GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_ALPHA param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_ALPHA param GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_RGB param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_RGB param GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_ALPHA param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_ALPHA param GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+# OES_texture_env_crossbar
+checkdependentparam pname GL_SRC0_RGB param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_RGB param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_RGB param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC0_ALPHA param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_ALPHA param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_ALPHA param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+category 1.0 GLES1.1
+
+name TexEnviv
+return void
+param target GLenum
+param pname GLenum
+param params const GLint *
+checkdependentparam target GL_POINT_SPRITE_OES pname GL_COORD_REPLACE_OES
+checkdependentparam pname GL_COORD_REPLACE_OES params GL_TRUE GL_FALSE
+checkdependentparam target GL_TEXTURE_ENV pname GL_TEXTURE_ENV_MODE GL_TEXTURE_ENV_COLOR GL_COMBINE_RGB GL_COMBINE_ALPHA GL_RGB_SCALE GL_ALPHA_SCALE GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+checkdependentparam pname GL_TEXTURE_ENV_MODE params GL_REPLACE GL_MODULATE GL_DECAL GL_BLEND GL_ADD GL_COMBINE
+checkdependentparam pname GL_COMBINE_RGB params GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT GL_DOT3_RGB GL_DOT3_RGBA
+checkdependentparam pname GL_COMBINE_ALPHA params GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT
+checkdependentparam pname GL_SRC0_RGB params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_RGB params GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC0_ALPHA params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_ALPHA params GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_RGB params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_RGB params GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_ALPHA params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_ALPHA params GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_RGB params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_RGB params GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_ALPHA params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_ALPHA params GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_RGB_SCALE params /GL_INVALID_VALUE 1.0 2.0 4.0
+checkdependentparam pname GL_ALPHA_SCALE params /GL_INVALID_VALUE 1.0 2.0 4.0
+dependentvector params 4 pname GL_TEXTURE_ENV_COLOR
+dependentvector params 1 pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_COORD_REPLACE_OES GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+dependentvector params 1 pname GL_RGB_SCALE GL_ALPHA_SCALE
+# OES_texture_env_crossbar
+checkdependentparam pname GL_SRC0_RGB params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_RGB params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_RGB params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC0_ALPHA params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_ALPHA params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_ALPHA params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+category 1.0 GLES1.1
+
+name TexEnvx
+return void
+param target GLenum
+param pname GLenum
+param param GLfixed
+checkdependentparam target GL_POINT_SPRITE_OES pname GL_COORD_REPLACE_OES
+checkdependentparam pname GL_COORD_REPLACE_OES param GL_TRUE GL_FALSE
+checkdependentparam target GL_TEXTURE_ENV pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_RGB_SCALE GL_ALPHA_SCALE GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+checkdependentparam pname GL_TEXTURE_ENV_MODE param GL_REPLACE GL_MODULATE GL_DECAL GL_BLEND GL_ADD GL_COMBINE
+checkdependentparam pname GL_COMBINE_RGB param GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT GL_DOT3_RGB GL_DOT3_RGBA
+checkdependentparam pname GL_COMBINE_ALPHA param GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT
+checkdependentparam pname GL_RGB_SCALE param /GL_INVALID_VALUE 1.0 2.0 4.0
+checkdependentparam pname GL_ALPHA_SCALE param /GL_INVALID_VALUE 1.0 2.0 4.0
+checkdependentparam pname GL_SRC0_RGB param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_RGB param GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC0_ALPHA param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_ALPHA param GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_RGB param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_RGB param GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_ALPHA param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_ALPHA param GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_RGB param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_RGB param GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_ALPHA param GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_ALPHA param GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+convertalias TexEnvf
+convertparams GLfloat param
+# OES_texture_env_crossbar
+checkdependentparam pname GL_SRC0_RGB param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_RGB param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_RGB param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC0_ALPHA param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_ALPHA param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_ALPHA param GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+category 1.0 GLES1.1 GLES1.1:OES_fixed_point
+
+name TexEnvxv
+return void
+param target GLenum
+param pname GLenum
+param params const GLfixed *
+checkdependentparam target GL_POINT_SPRITE_OES pname GL_COORD_REPLACE_OES
+checkdependentparam pname GL_COORD_REPLACE_OES params GL_TRUE GL_FALSE
+checkdependentparam target GL_TEXTURE_ENV pname GL_TEXTURE_ENV_MODE GL_TEXTURE_ENV_COLOR GL_COMBINE_RGB GL_COMBINE_ALPHA GL_RGB_SCALE GL_ALPHA_SCALE GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+checkdependentparam pname GL_TEXTURE_ENV_MODE params GL_REPLACE GL_MODULATE GL_DECAL GL_BLEND GL_ADD GL_COMBINE
+checkdependentparam pname GL_COMBINE_RGB params GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT GL_DOT3_RGB GL_DOT3_RGBA
+checkdependentparam pname GL_COMBINE_ALPHA params GL_REPLACE GL_MODULATE GL_ADD GL_ADD_SIGNED GL_INTERPOLATE GL_SUBTRACT
+checkdependentparam pname GL_SRC0_RGB params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_RGB params GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC0_ALPHA params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND0_ALPHA params GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_RGB params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_RGB params GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC1_ALPHA params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND1_ALPHA params GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_RGB params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_RGB params GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_SRC2_ALPHA params GL_TEXTURE GL_CONSTANT GL_PRIMARY_COLOR GL_PREVIOUS
+checkdependentparam pname GL_OPERAND2_ALPHA params GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+checkdependentparam pname GL_RGB_SCALE params /GL_INVALID_VALUE 1.0 2.0 4.0
+checkdependentparam pname GL_ALPHA_SCALE params /GL_INVALID_VALUE 1.0 2.0 4.0
+dependentvector params 4 pname GL_TEXTURE_ENV_COLOR
+dependentvector params 1 pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_COORD_REPLACE_OES GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+dependentvector params 1 pname GL_RGB_SCALE GL_ALPHA_SCALE
+convertalias TexEnvfv
+convertparams GLfloat params
+# OES_texture_env_crossbar
+dependentvector params 1 pname GL_SRC0_RGB GL_SRC1_RGB GL_SRC2_RGB GL_SRC0_ALPHA GL_SRC1_ALPHA GL_SRC2_ALPHA
+checkdependentparam pname GL_SRC0_RGB params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_RGB params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_RGB params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC0_ALPHA params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC1_ALPHA params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+checkdependentparam pname GL_SRC2_ALPHA params GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name TexGenx
+return void
+param coord GLenum
+checkparam coord GL_TEXTURE_GEN_STR_OES
+param pname GLenum
+param param GLfixed
+checkdependentparam pname GL_TEXTURE_GEN_MODE_OES param GL_NORMAL_MAP_OES GL_REFLECTION_MAP_OES
+convertalias TexGenf
+convertparams GLfloat param
+category GLES1.1:OES_texture_cube_map
+
+name TexGenxv
+return void
+param coord GLenum
+checkparam coord GL_TEXTURE_GEN_STR_OES
+param pname GLenum
+param params const GLfixed *
+dependentvector params 1 pname GL_TEXTURE_GEN_MODE_OES
+checkdependentparam pname GL_TEXTURE_GEN_MODE_OES params GL_NORMAL_MAP_OES GL_REFLECTION_MAP_OES
+convertalias TexGenfv
+convertparams GLfloat params
+category GLES1.1:OES_texture_cube_map
+
+name TexGenf
+return void
+param coord GLenum
+checkparam coord GL_TEXTURE_GEN_STR_OES
+param pname GLenum
+checkparam pname GL_TEXTURE_GEN_MODE_OES
+param param GLfloat
+checkdependentparam pname GL_TEXTURE_GEN_MODE_OES param GL_NORMAL_MAP_OES GL_REFLECTION_MAP_OES
+category 1.0 GLES1.1:OES_texture_cube_map
+
+name TexGenfv
+return void
+param coord GLenum
+checkparam coord GL_TEXTURE_GEN_STR_OES
+param pname GLenum
+param params const GLfloat *
+dependentvector params 1 pname GL_TEXTURE_GEN_MODE_OES
+checkdependentparam pname GL_TEXTURE_GEN_MODE_OES params GL_NORMAL_MAP_OES GL_REFLECTION_MAP_OES
+category 1.0 GLES1.1:OES_texture_cube_map
+
+name TexGeni
+return void
+param coord GLenum
+checkparam coord GL_TEXTURE_GEN_STR_OES
+param pname GLenum
+checkparam pname GL_TEXTURE_GEN_MODE_OES
+param param GLint
+checkdependentparam pname GL_TEXTURE_GEN_MODE_OES param GL_NORMAL_MAP_OES GL_REFLECTION_MAP_OES
+category 1.0 GLES1.1:OES_texture_cube_map
+
+name TexGeniv
+return void
+param coord GLenum
+checkparam coord GL_TEXTURE_GEN_STR_OES
+param pname GLenum
+checkparam pname GL_TEXTURE_GEN_MODE_OES
+param params const GLint *
+dependentvector params 1 pname GL_TEXTURE_GEN_MODE_OES
+checkdependentparam pname GL_TEXTURE_GEN_MODE_OES params GL_NORMAL_MAP_OES GL_REFLECTION_MAP_OES
+category 1.0 GLES1.1:OES_texture_cube_map
+
+name Clear
+return void
+param mask GLbitfield
+checkparam mask /GL_INVALID_VALUE 0 (GL_COLOR_BUFFER_BIT) (GL_DEPTH_BUFFER_BIT) (GL_STENCIL_BUFFER_BIT) (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) (GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)
+category 1.0 GLES1.1 GLES2.0
+
+name ClearColor
+return void
+param red GLclampf
+param green GLclampf
+param blue GLclampf
+param alpha GLclampf
+category 1.0 GLES1.1 GLES2.0
+
+name ClearColorx
+return void
+param red GLclampx
+param green GLclampx
+param blue GLclampx
+param alpha GLclampx
+convertalias ClearColor
+convertparams GLclampf red green blue alpha
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name ClearStencil
+return void
+param s GLint
+category 1.0 GLES1.1 GLES2.0
+
+name ClearDepthf
+return void
+param depth GLclampf
+convertalias ClearDepth
+convertparams GLclampd depth
+category GLES1.1 GLES1.1:OES_single_precision GLES2.0
+
+name ClearDepthx
+return void
+param depth GLclampx
+convertalias ClearDepth
+convertparams GLclampd depth
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name StencilMask
+return void
+param mask GLuint
+category 1.0 GLES1.1 GLES2.0
+
+name StencilMaskSeparate
+return void
+param face GLenum
+param mask GLuint
+checkparam face GL_FRONT GL_BACK GL_FRONT_AND_BACK
+category GLES2.0
+
+name ColorMask
+return void
+param red GLboolean
+param green GLboolean
+param blue GLboolean
+param alpha GLboolean
+category 1.0 GLES1.1 GLES2.0
+
+name DepthMask
+return void
+param flag GLboolean
+category 1.0 GLES1.1 GLES2.0
+
+# Two versions, as GLES2 has a vastly different set of enable/disable capabilities
+name Disable
+return void
+param cap GLenum
+checkparam cap GL_VERTEX_ARRAY GL_NORMAL_ARRAY GL_COLOR_ARRAY GL_TEXTURE_COORD_ARRAY GL_NORMALIZE GL_RESCALE_NORMAL GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_FOG GL_LIGHTING GL_COLOR_MATERIAL GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_POINT_SMOOTH GL_LINE_SMOOTH GL_CULL_FACE GL_POLYGON_OFFSET_FILL GL_MULTISAMPLE GL_SAMPLE_ALPHA_TO_COVERAGE GL_SAMPLE_ALPHA_TO_ONE GL_SAMPLE_COVERAGE GL_TEXTURE_2D GL_SCISSOR_TEST GL_ALPHA_TEST GL_STENCIL_TEST GL_DEPTH_TEST GL_BLEND GL_DITHER GL_COLOR_LOGIC_OP
+# OES_matrix_palette
+checkparam cap GL_MATRIX_INDEX_ARRAY_OES GL_WEIGHT_ARRAY_OES
+# OES_point_size_array
+checkparam cap GL_POINT_SIZE_ARRAY_OES
+# OES_point_sprite
+checkparam cap GL_POINT_SPRITE_OES
+# OES_texture_cube_map
+checkparam cap GL_TEXTURE_CUBE_MAP_OES GL_TEXTURE_GEN_STR_OES
+category GLES1.1
+
+name Disable
+return void
+param cap GLenum
+checkparam cap GL_CULL_FACE GL_SCISSOR_TEST GL_POLYGON_OFFSET_FILL GL_SAMPLE_ALPHA_TO_COVERAGE GL_SAMPLE_COVERAGE GL_STENCIL_TEST GL_DEPTH_TEST GL_DITHER GL_BLEND
+category GLES2.0
+
+# Two versions, as GLES2 has a vastly different set of enable/disable capabilities
+name Enable
+return void
+param cap GLenum
+checkparam cap GL_VERTEX_ARRAY GL_NORMAL_ARRAY GL_COLOR_ARRAY GL_TEXTURE_COORD_ARRAY GL_NORMALIZE GL_RESCALE_NORMAL GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_FOG GL_LIGHTING GL_COLOR_MATERIAL GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_POINT_SMOOTH GL_LINE_SMOOTH GL_CULL_FACE GL_POLYGON_OFFSET_FILL GL_MULTISAMPLE GL_SAMPLE_ALPHA_TO_COVERAGE GL_SAMPLE_ALPHA_TO_ONE GL_SAMPLE_COVERAGE GL_TEXTURE_2D GL_SCISSOR_TEST GL_ALPHA_TEST GL_STENCIL_TEST GL_DEPTH_TEST GL_BLEND GL_DITHER GL_COLOR_LOGIC_OP
+# OES_matrix_palette
+checkparam cap GL_MATRIX_INDEX_ARRAY_OES GL_WEIGHT_ARRAY_OES
+# OES_point_size_array
+checkparam cap GL_POINT_SIZE_ARRAY_OES
+# OES_point_sprite
+checkparam cap GL_POINT_SPRITE_OES
+# OES_texture_cube_map
+checkparam cap GL_TEXTURE_CUBE_MAP_OES GL_TEXTURE_GEN_STR_OES
+category GLES1.1
+
+name Enable
+return void
+param cap GLenum
+checkparam cap GL_CULL_FACE GL_SCISSOR_TEST GL_POLYGON_OFFSET_FILL GL_SAMPLE_ALPHA_TO_COVERAGE GL_SAMPLE_COVERAGE GL_STENCIL_TEST GL_DEPTH_TEST GL_DITHER GL_BLEND
+category GLES2.0
+
+name Finish
+return void
+category 1.0 GLES1.1 GLES2.0
+
+name Flush
+return void
+category 1.0 GLES1.1 GLES2.0
+
+name AlphaFunc
+return void
+param func GLenum
+checkparam func GL_NEVER GL_LESS GL_EQUAL GL_LEQUAL GL_GREATER GL_NOTEQUAL GL_GEQUAL GL_ALWAYS
+param ref GLclampf
+category 1.0 GLES1.1
+
+name AlphaFuncx
+return void
+param func GLenum
+checkparam func GL_NEVER GL_LESS GL_EQUAL GL_LEQUAL GL_GREATER GL_NOTEQUAL GL_GEQUAL GL_ALWAYS
+param ref GLclampx
+convertalias AlphaFunc
+convertparams GLclampf ref
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name BlendFunc
+return void
+param sfactor GLenum
+checkparam sfactor GL_ZERO GL_ONE GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_DST_COLOR GL_ONE_MINUS_DST_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_DST_COLOR GL_DST_ALPHA GL_ONE_MINUS_DST_COLOR GL_ONE_MINUS_DST_ALPHA GL_SRC_ALPHA_SATURATE
+checkparam sfactor GLES2.0:GL_CONSTANT_COLOR GLES2.0:GL_CONSTANT_ALPHA GLES2.0:GL_ONE_MINUS_CONSTANT_COLOR GLES2.0:GL_ONE_MINUS_CONSTANT_ALPHA
+param dfactor GLenum
+checkparam dfactor GL_ZERO GL_ONE GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_DST_COLOR GL_DST_ALPHA GL_ONE_MINUS_DST_COLOR GL_ONE_MINUS_DST_ALPHA
+checkparam dfactor GLES2.0:GL_CONSTANT_COLOR GLES2.0:GL_CONSTANT_ALPHA GLES2.0:GL_ONE_MINUS_CONSTANT_COLOR GLES2.0:GL_ONE_MINUS_CONSTANT_ALPHA
+category 1.0 GLES1.1 GLES2.0
+
+name LogicOp
+return void
+param opcode GLenum
+checkparam opcode GL_CLEAR GL_SET GL_COPY GL_COPY_INVERTED GL_NOOP GL_INVERT GL_AND GL_NAND GL_OR GL_NOR GL_XOR GL_EQUIV GL_AND_REVERSE GL_AND_INVERTED GL_OR_REVERSE GL_OR_INVERTED
+category 1.0 GLES1.1
+
+name StencilFunc
+return void
+param func GLenum
+param ref GLint
+param mask GLuint
+checkparam func GL_NEVER GL_LESS GL_LEQUAL GL_GREATER GL_GEQUAL GL_EQUAL GL_NOTEQUAL GL_ALWAYS
+category 1.0 GLES1.1 GLES2.0
+
+name StencilFuncSeparate
+return void
+param face GLenum
+param func GLenum
+param ref GLint
+param mask GLuint
+checkparam face GL_FRONT GL_BACK GL_FRONT_AND_BACK
+checkparam func GL_NEVER GL_LESS GL_LEQUAL GL_GREATER GL_GEQUAL GL_EQUAL GL_NOTEQUAL GL_ALWAYS
+category GLES2.0
+
+name StencilOp
+return void
+param fail GLenum
+param zfail GLenum
+param zpass GLenum
+checkparam fail GL_KEEP GL_ZERO GL_REPLACE GL_INCR GL_DECR GL_INVERT GLES2.0:GL_INCR_WRAP GLES2.0:GL_DECR_WRAP
+checkparam zfail GL_KEEP GL_ZERO GL_REPLACE GL_INCR GL_DECR GL_INVERT GLES2.0:GL_INCR_WRAP GLES2.0:GL_DECR_WRAP
+checkparam zpass GL_KEEP GL_ZERO GL_REPLACE GL_INCR GL_DECR GL_INVERT GLES2.0:GL_INCR_WRAP GLES2.0:GL_DECR_WRAP
+# OES_stencil_wrap
+checkparam fail GLES1.1:GL_INCR_WRAP_OES GLES1.1:GL_DECR_WRAP_OES
+checkparam zfail GLES1.1:GL_INCR_WRAP_OES GLES1.1:GL_DECR_WRAP_OES
+checkparam zpass GLES1.1:GL_INCR_WRAP_OES GLES1.1:GL_DECR_WRAP_OES
+category GLES1.1 GLES2.0
+
+name StencilOpSeparate
+return void
+param face GLenum
+param fail GLenum
+param zfail GLenum
+param zpass GLenum
+checkparam face GL_FRONT GL_BACK GL_FRONT_AND_BACK
+checkparam fail GL_KEEP GL_ZERO GL_REPLACE GL_INCR GL_DECR GL_INVERT GL_INCR_WRAP GL_DECR_WRAP
+checkparam zfail GL_KEEP GL_ZERO GL_REPLACE GL_INCR GL_DECR GL_INVERT GL_INCR_WRAP GL_DECR_WRAP
+checkparam zpass GL_KEEP GL_ZERO GL_REPLACE GL_INCR GL_DECR GL_INVERT GL_INCR_WRAP GL_DECR_WRAP
+category GLES2.0
+
+name DepthFunc
+return void
+param func GLenum
+checkparam func GL_NEVER GL_LESS GL_EQUAL GL_LEQUAL GL_GREATER GL_NOTEQUAL GL_GEQUAL GL_ALWAYS
+category 1.0 GLES1.1 GLES2.0
+
+name PixelStorei
+return void
+param pname GLenum
+checkparam pname GL_PACK_ALIGNMENT GL_UNPACK_ALIGNMENT
+param param GLint
+checkparam param /GL_INVALID_VALUE 1 2 4 8
+category 1.0 GLES1.1 GLES2.0
+
+name ReadPixels
+return void
+param x GLint
+param y GLint
+param width GLsizei
+param height GLsizei
+param format GLenum
+param type GLenum
+param pixels GLvoid *
+# Technically, only two combinations are actually allowed:
+# GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
+# preferred combination. I don't know what that is, so I'm allowing
+# any valid combination for now; the underlying support should fail
+# when necessary.
+checkdependentparam format GL_RGBA type GL_UNSIGNED_BYTE
+checkdependentparam format GL_RGBA type GL_UNSIGNED_BYTE GL_UNSIGNED_SHORT_4_4_4_4 GL_UNSIGNED_SHORT_5_5_5_1
+checkdependentparam format GL_RGB type GL_UNSIGNED_BYTE GL_UNSIGNED_SHORT_5_6_5
+checkdependentparam format GL_LUMINANCE_ALPHA format GL_UNSIGNED_BYTE
+checkdependentparam format GL_LUMINANCE format GL_UNSIGNED_BYTE
+checkdependentparam format GL_ALPHA format GL_UNSIGNED_BYTE
+props get
+category 1.0 GLES1.1 GLES2.0
+
+# Note: glGetBooleanv param checking done inside Mesa
+name GetBooleanv
+return void
+param pname GLenum
+param params GLboolean *
+props get
+category GLES1.1 GLES2.0
+
+name GetClipPlanef
+return void
+param plane GLenum
+checkparam plane GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5
+param equation GLfloat *
+paramvec equation 0.0 0.0 0.0 0.0
+vector equation 4
+convertalias GetClipPlane
+convertparams GLdouble equation
+props get
+category GLES1.1 GLES1.1:OES_single_precision
+
+name GetClipPlanex
+return void
+param plane GLenum
+checkparam plane GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5
+param equation GLfixed *
+paramvec equation 0.0 0.0 0.0 0.0
+vector equation 4
+convertalias GetClipPlane
+convertparams GLdouble equation
+props get
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name GetError
+return GLenum
+props get
+category 1.0 GLES1.1 GLES2.0
+
+# Note: glGetFloatv param checking done inside Mesa
+name GetFloatv
+return void
+param pname GLenum
+param params GLfloat *
+props get
+category GLES1.1 GLES2.0
+
+name GetFixedv
+return void
+param pname GLenum
+param params GLfixed *
+convertalias GetFloatv
+convertparams GLfloat params
+props get
+dependentvector params 1 pname GL_CLIENT_ACTIVE_TEXTURE GL_VERTEX_ARRAY GL_VERTEX_ARRAY_SIZE GL_VERTEX_ARRAY_TYPE GL_VERTEX_ARRAY_STRIDE GL_NORMAL_ARRAY GL_NORMAL_ARRAY_TYPE GL_NORMAL_ARRAY_STRIDE GL_COLOR_ARRAY GL_COLOR_ARRAY_SIZE GL_COLOR_ARRAY_TYPE
+dependentvector params 1 pname GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_SIZE GL_TEXTURE_COORD_ARRAY_TYPE GL_TEXTURE_COORD_ARRAY_STRIDE GL_POINT_SIZE_ARRAY_OES GL_POINT_SIZE_ARRAY_STRIDE_OES GL_ARRAY_BUFFER_BINDING GL_VERTEX_ARRAY_BUFFER_BINDING GL_NORMAL_ARRAY_BUFFER_BINDING GL_COLOR_ARRAY_BUFFER_BINDING GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES GL_ELEMENT_ARRAY_BUFFER_BINDING
+dependentvector params 1 pname GL_MODELVIEW_STACK_DEPTH GL_PROJECTION_STACK_DEPTH GL_TEXTURE_STACK_DEPTH GL_MATRIX_MODE GL_NORMALIZE GL_RESCALE_NORMAL GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5
+dependentvector params 1 pname GL_FOG_DENSITY GL_FOG_START GL_FOG_END GL_FOG_MODE GL_FOG GL_SHADE_MODEL
+dependentvector params 1 pname GL_LIGHTING GL_COLOR_MATERIAL GL_LIGHT_MODEL_TWO_SIDE
+dependentvector params 1 pname GL_POINT_SIZE GL_POINT_SMOOTH GL_POINT_SIZE_MIN GL_POINT_SIZE_MAX GL_POINT_FADE_THRESHOLD_SIZE GL_POINT_SPRITE_OES GL_LINE_WIDTH GL_LINE_SMOOTH GL_CULL_FACE GL_CULL_FACE_MODE GL_FRONT_FACE GL_POLYGON_OFFSET_FACTOR GL_POLYGON_OFFSET_UNITS GL_POLYGON_OFFSET_FILL
+dependentvector params 1 pname GL_MULTISAMPLE GL_SAMPLE_ALPHA_TO_COVERAGE GL_SAMPLE_ALPHA_TO_ONE GL_SAMPLE_COVERAGE GL_SAMPLE_COVERAGE_VALUE
+dependentvector params 1 pname GL_TEXTURE_2D GL_TEXTURE_BINDING_2D
+dependentvector params 1 pname GL_ACTIVE_TEXTURE
+dependentvector params 1 pname GL_SCISSOR_TEST GL_ALPHA_TEST_FUNC GL_ALPHA_TEST_REF GL_STENCIL_TEST GL_STENCIL_FUNC GL_STENCIL_VALUE_MASK GL_STENCIL_REF GL_STENCIL_FAIL GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_DEPTH_TEST GL_DEPTH_FUNC GL_BLEND GL_BLEND_SRC GL_BLEND_DST GL_DITHER GL_COLOR_LOGIC_OP GL_LOGIC_OP_MODE
+dependentvector params 1 pname GL_DEPTH_WRITEMASK GL_STENCIL_WRITEMASK GL_DEPTH_CLEAR_VALUE GL_STENCIL_CLEAR_VALUE
+dependentvector params 1 pname GL_UNPACK_ALIGNMENT GL_PACK_ALIGNMENT
+dependentvector params 1 pname GL_PERSPECTIVE_CORRECTION_HINT GL_POINT_SMOOTH_HINT GL_LINE_SMOOTH_HINT GL_FOG_HINT GL_GENERATE_MIPMAP_HINT
+dependentvector params 1 pname GL_MAX_LIGHTS GL_MAX_CLIP_PLANES GL_MAX_MODELVIEW_STACK_DEPTH GL_MAX_PROJECTION_STACK_DEPTH GL_MAX_TEXTURE_STACK_DEPTH GL_SUBPIXEL_BITS GL_MAX_TEXTURE_SIZE GL_MAX_TEXTURE_UNITS GL_SAMPLE_BUFFERS GL_SAMPLES GL_NUM_COMPRESSED_TEXTURE_FORMATS GL_RED_BITS GL_GREEN_BITS GL_BLUE_BITS GL_ALPHA_BITS GL_DEPTH_BITS GL_STENCIL_BITS
+dependentvector params 2 pname GL_MAX_VIEWPORT_DIMS GL_ALIASED_POINT_SIZE_RANGE GL_SMOOTH_POINT_SIZE_RANGE GL_ALIASED_LINE_WIDTH_RANGE GL_SMOOTH_LINE_WIDTH_RANGE
+dependentvector params 2 pname GL_DEPTH_RANGE
+dependentvector params 3 pname GL_CURRENT_NORMAL
+dependentvector params 3 pname GL_POINT_DISTANCE_ATTENUATION
+dependentvector params 4 pname GL_CURRENT_COLOR GL_CURRENT_TEXTURE_COORDS
+dependentvector params 4 pname GL_SCISSOR_BOX
+dependentvector params 4 pname GL_COLOR_WRITEMASK GL_COLOR_CLEAR_VALUE
+dependentvector params 4 pname GL_LIGHT_MODEL_AMBIENT
+dependentvector params 4 pname GL_VIEWPORT
+dependentvector params 4 pname GL_FOG_COLOR
+dependentvector params 16 pname GL_MODELVIEW_MATRIX GL_PROJECTION_MATRIX GL_TEXTURE_MATRIX
+dependentvector params _get_size(GL_NUM_COMPRESSED_TEXTURE_FORMATS) pname GL_COMPRESSED_TEXTURE_FORMATS
+# OES_blend_subtract
+dependentvector params 1 pname GL_BLEND_SRC_RGB_OES GL_BLEND_DST_RGB_OES GL_BLEND_SRC_ALPHA_OES GL_BLEND_DST_ALPHA_OES
+# OES_blend_equation_separate
+dependentvector params 1 pname GL_BLEND_EQUATION_RGB_OES GL_BLEND_EQUATION_ALPHA_OES
+# OES_framebuffer_object
+dependentvector params 1 pname GL_FRAMEBUFFER_BINDING_OES GL_RENDERBUFFER_BINDING_OES GL_MAX_RENDERBUFFER_SIZE_OES
+# OES_matrix_get
+dependentvector params 16 pname GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES
+# OES_matrix_palette
+dependentvector params 1 pname GL_MAX_PALETTE_MATRICES_OES GL_MAX_VERTEX_UNITS_OES GL_CURRENT_PALETTE_MATRIX_OES
+dependentvector params 1 pname GL_MATRIX_INDEX_ARRAY_SIZE_OES GL_MATRIX_INDEX_ARRAY_TYPE_OES GL_MATRIX_INDEX_ARRAY_STRIDE_OES GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES GL_WEIGHT_ARRAY_SIZE_OES GL_WEIGHT_ARRAY_TYPE_OES GL_WEIGHT_ARRAY_STRIDE_OES GL_WEIGHT_ARRAY_BUFFER_BINDING_OES
+# OES_point_size_array
+dependentvector params 1 pname GL_POINT_SIZE_ARRAY_TYPE_OES GL_POINT_SIZE_ARRAY_STRIDE_OES GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES
+# OES_read_format
+dependentvector params 1 pname GL_IMPLEMENTATION_COLOR_READ_TYPE_OES GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES
+# OES_texture_cube_map
+dependentvector params 1 pname GL_TEXTURE_CUBE_MAP_OES GL_TEXTURE_BINDING_CUBE_MAP_OES GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES
+# EXT_texture_filter_anisotropic
+dependentvector params 1 pname GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
+# These values return booleans or GLenums, and should not have their
+# value converted when used with glGetFixed()
+dependentnovalueconvert params pname GL_VERTEX_ARRAY GL_VERTEX_ARRAY_TYPE GL_NORMAL_ARRAY GL_NORMAL_ARRAY_TYPE GL_COLOR_ARRAY GL_COLOR_ARRAY_TYPE GL_TEXTURE_COORD_ARRAY GL_TEXTURE_COORD_ARRAY_TYPE GL_POINT_SIZE_ARRAY_OES GL_MATRIX_MODE GL_NORMALIZE GL_RESCALE_NORMAL GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_FOG_MODE GL_FOG GL_SHADE_MODEL GL_LIGHTING GL_COLOR_MATERIAL GL_LIGHT_MODEL_TWO_SIDE GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_POINT_SMOOTH GL_POINT_SPRITE_OES GL_LINE_SMOOTH GL_CULL_FACE GL_CULL_FACE_MODE GL_FRONT_FACE GL_POLYGON_OFFSET_FILL GL_MULTISAMPLE GL_SAMPLE_ALPHA_TO_COVERAGE GL_SAMPLE_ALPHA_TO_ONE GL_SAMPLE_COVERAGE GL_TEXTURE_2D GL_ACTIVE_TEXTURE GL_SCISSOR_TEST GL_ALPHA_TEST GL_ALPHA_TEST_FUNC GL_STENCIL_TEST GL_STENCIL_FUNC GL_STENCIL_FAIL GL_STENCIL_PASS_DEPTH_FAIL GL_STENCIL_PASS_DEPTH_PASS GL_DEPTH_TEST GL_DEPTH_FUNC GL_BLEND GL_BLEND_SRC GL_BLEND_DST GL_DITHER GL_COLOR_LOGIC_OP GL_LOGIC_OP_MODE GL_DEPTH_WRITEMASK GL_PERSPECTIVE_CORRECTION_HINT GL_POINT_SMOOTH_HINT GL_LINE_SMOOTH_HINT GL_FOG_HINT GL_GENERATE_MIPMAP_HINT GL_COMPRESSED_TEXTURE_FORMATS GL_IMPLEMENTATION_COLOR_READ_TYPE_OES GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES GL_BLEND_SRC_RGB_OES GL_BLEND_DST_RGB_OES GL_BLEND_SRC_ALPHA_OES GL_BLEND_DST_ALPHA_OES GL_BLEND_EQUATION_RGB_OES GL_BLEND_EQUATION_ALPHA_OES GL_MATRIX_INDEX_ARRAY_TYPE_OES GL_WEIGHT_ARRAY_TYPE_OES GL_POINT_SIZE_ARRAY_TYPE_OES GL_TEXTURE_CUBE_MAP_OES
+category GLES1.1 GLES1.1:OES_fixed_point
+
+# Note: glGetIntegerv param checking done inside Mesa
+name GetIntegerv
+return void
+param pname GLenum
+param params GLint *
+props get
+category GLES1.1 GLES2.0
+
+
+# This does *not* specify dependent vectors because everything is just
+# passed down to Mesa - no copy or conversion is done.
+name GetLightfv
+return void
+param light GLenum
+checkparam light GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7
+param pname GLenum
+checkparam pname GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION GL_SPOT_DIRECTION GL_SPOT_EXPONENT GL_SPOT_CUTOFF GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION
+param params GLfloat *
+props get
+category 1.0 GLES1.1
+
+name GetLightxv
+return void
+param light GLenum
+checkparam light GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7
+param pname GLenum
+param params GLfixed *
+dependentvector params 4 pname GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION
+dependentvector params 3 pname GL_SPOT_DIRECTION
+dependentvector params 1 pname GL_SPOT_EXPONENT GL_SPOT_CUTOFF GL_CONSTANT_ATTENUATION GL_QUADRATIC_ATTENUATION
+convertalias GetLightfv
+convertparams GLfloat params
+props get
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name GetMaterialfv
+return void
+param face GLenum
+checkparam face GL_FRONT GL_BACK
+param pname GLenum
+checkparam pname GL_AMBIENT GL_DIFFUSE GL_AMBIENT_AND_DIFFUSE GL_SPECULAR GL_EMISSION GL_SHININESS
+param params GLfloat *
+props get
+category 1.0 GLES1.1
+
+name GetMaterialiv
+return void
+param face GLenum
+checkparam face GL_FRONT GL_BACK
+param pname GLenum
+checkparam pname GL_AMBIENT GL_DIFFUSE GL_AMBIENT_AND_DIFFUSE GL_SPECULAR GL_EMISSION GL_SHININESS
+param params GLint *
+category 1.0
+props get
+
+name GetMaterialxv
+return void
+param face GLenum
+checkparam face GL_FRONT GL_BACK
+param pname GLenum
+param params GLfixed *
+props get
+dependentvector params 1 pname GL_SHININESS
+dependentvector params 4 pname GL_AMBIENT GL_DIFFUSE GL_AMBIENT_AND_DIFFUSE GL_SPECULAR GL_EMISSION
+convertalias GetMaterialfv
+convertparams GLfloat params
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name GetString
+return const GLubyte *
+param name GLenum
+checkparam name GL_VENDOR GL_RENDERER GL_VERSION GL_EXTENSIONS
+props get
+category 1.0 GLES1.1 GLES2.0
+
+name GetTexEnvfv
+return void
+param target GLenum
+param pname GLenum
+param params GLfloat *
+checkdependentparam target GL_POINT_SPRITE_OES pname GL_COORD_REPLACE_OES
+checkdependentparam target GL_TEXTURE_ENV pname GL_TEXTURE_ENV_MODE GL_TEXTURE_ENV_COLOR GL_COMBINE_RGB GL_COMBINE_ALPHA GL_RGB_SCALE GL_ALPHA_SCALE GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+dependentvector params 4 pname GL_TEXTURE_ENV_COLOR
+dependentvector params 1 pname GL_RGB_SCALE GL_ALPHA_SCALE
+dependentvector params 1 pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_SRC0_RGB GL_SRC1_RGB GL_SRC2_RGB GL_SRC0_ALPHA GL_SRC1_ALPHA GL_SRC2_ALPHA GL_OPERAND0_RGB GL_OPERAND1_RGB GL_OPERAND2_RGB GL_OPERAND0_ALPHA GL_OPERAND1_ALPHA GL_OPERAND2_ALPHA GL_COORD_REPLACE_OES
+dependentnovalueconvert params pname GL_COORD_REPLACE_OES GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+props get
+category 1.0 GLES1.1
+
+name GetTexEnviv
+return void
+param target GLenum
+param pname GLenum
+param params GLint *
+props get
+checkdependentparam target GL_POINT_SPRITE_OES pname GL_COORD_REPLACE_OES
+checkdependentparam target GL_TEXTURE_ENV pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_RGB_SCALE GL_ALPHA_SCALE GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+category 1.0 GLES1.1
+dependentvector params 4 pname GL_TEXTURE_ENV_COLOR
+dependentvector params 1 pname GL_RGB_SCALE GL_ALPHA_SCALE
+dependentvector params 1 pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_SRC0_RGB GL_SRC1_RGB GL_SRC2_RGB GL_SRC0_ALPHA GL_SRC1_ALPHA GL_SRC2_ALPHA GL_OPERAND0_RGB GL_OPERAND1_RGB GL_OPERAND2_RGB GL_OPERAND0_ALPHA GL_OPERAND1_ALPHA GL_OPERAND2_ALPHA GL_COORD_REPLACE_OES
+dependentnovalueconvert params pname GL_COORD_REPLACE_OES GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+
+name GetTexEnvxv
+return void
+param target GLenum
+param pname GLenum
+param params GLfixed *
+checkdependentparam target GL_POINT_SPRITE_OES pname GL_COORD_REPLACE_OES
+checkdependentparam target GL_TEXTURE_ENV pname GL_TEXTURE_ENV_MODE GL_TEXTURE_ENV_COLOR GL_COMBINE_RGB GL_COMBINE_ALPHA GL_RGB_SCALE GL_ALPHA_SCALE GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+dependentvector params 4 pname GL_TEXTURE_ENV_COLOR
+dependentvector params 1 pname GL_RGB_SCALE GL_ALPHA_SCALE
+dependentvector params 1 pname GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_SRC0_RGB GL_SRC1_RGB GL_SRC2_RGB GL_SRC0_ALPHA GL_SRC1_ALPHA GL_SRC2_ALPHA GL_OPERAND0_RGB GL_OPERAND1_RGB GL_OPERAND2_RGB GL_OPERAND0_ALPHA GL_OPERAND1_ALPHA GL_OPERAND2_ALPHA GL_COORD_REPLACE_OES
+dependentnovalueconvert params pname GL_COORD_REPLACE_OES GL_TEXTURE_ENV_MODE GL_COMBINE_RGB GL_COMBINE_ALPHA GL_SRC0_RGB GL_OPERAND0_RGB GL_SRC0_ALPHA GL_OPERAND0_ALPHA GL_SRC1_RGB GL_OPERAND1_RGB GL_SRC1_ALPHA GL_OPERAND1_ALPHA GL_SRC2_RGB GL_OPERAND2_RGB GL_SRC2_ALPHA GL_OPERAND2_ALPHA
+convertalias GetTexEnvfv
+convertparams GLfloat params
+props get
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name GetTexGenfv
+return void
+param coord GLenum
+checkparam coord GL_TEXTURE_GEN_STR_OES
+param pname GLenum
+param params GLfloat *
+dependentvector params 1 pname GL_TEXTURE_GEN_MODE_OES
+props get
+category 1.0 GLES1.1:OES_texture_cube_map
+
+name GetTexGenxv
+return void
+param coord GLenum
+checkparam coord GL_TEXTURE_GEN_STR_OES
+param pname GLenum
+param params GLfixed *
+dependentvector params 1 pname GL_TEXTURE_GEN_MODE_OES
+convertalias GetTexGenfv
+convertparams GLfloat params
+dependentnovalueconvert params pname GL_TEXTURE_GEN_MODE_OES
+props get
+category 1.0 GLES1.1:OES_texture_cube_map
+
+name GetTexGeniv
+return void
+param coord GLenum
+checkparam coord GL_TEXTURE_GEN_STR_OES
+param pname GLenum
+param params GLint *
+dependentvector params 1 pname GL_TEXTURE_GEN_MODE_OES
+props get
+category 1.0 GLES1.1:OES_texture_cube_map
+
+name GetTexParameterfv
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP
+param pname GLenum
+param params GLfloat *
+dependentvector params 1 pname GL_TEXTURE_WRAP_S GL_TEXTURE_WRAP_T GL_TEXTURE_MIN_FILTER GL_TEXTURE_MAG_FILTER GLES1.1:GL_GENERATE_MIPMAP
+props get
+# OES_draw_texture - not in gl2ext.h yet
+dependentvector params 4 pname GLES1.1:GL_TEXTURE_CROP_RECT_OES
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_OES
+category GLES1.1 GLES2.0
+
+name GetTexParameteriv
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP
+param pname GLenum
+param params GLint *
+dependentvector params 1 pname GL_TEXTURE_WRAP_S GL_TEXTURE_WRAP_T GL_TEXTURE_MIN_FILTER GL_TEXTURE_MAG_FILTER GLES1.1:GL_GENERATE_MIPMAP
+props get
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_OES
+# OES_draw_texture - not in gl2ext.h yet, not supported in Mesa yet
+dependentvector params 4 pname GLES1.1:GL_TEXTURE_CROP_RECT_OES
+# OES_texture_3D
+checkparam target GLES2.0:GL_TEXTURE_3D_OES
+category GLES1.1 GLES2.0
+
+name GetTexParameterxv
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D
+param pname GLenum
+param params GLfixed *
+dependentvector params 1 pname GL_TEXTURE_WRAP_S GL_TEXTURE_WRAP_T GL_TEXTURE_MIN_FILTER GL_TEXTURE_MAG_FILTER GL_GENERATE_MIPMAP
+convertalias GetTexParameterfv
+convertparams GLfloat params
+dependentnovalueconvert params pname GL_TEXTURE_WRAP_S GL_TEXTURE_WRAP_T GL_TEXTURE_MIN_FILTER GL_TEXTURE_MAG_FILTER GL_GENERATE_MIPMAP
+props get
+# OES_texture_cube_map
+checkparam target GL_TEXTURE_CUBE_MAP_OES
+# OES_draw_texture - not supported in Mesa yet
+#dependentvector params 4 pname GL_TEXTURE_CROP_RECT_OES
+category GLES1.1 GLES1.1:OES_fixed_point
+
+# GLES1.1 and GLES2.0 have different capabilities
+name IsEnabled
+return GLboolean
+param cap GLenum
+props get
+checkparam cap GL_VERTEX_ARRAY GL_NORMAL_ARRAY GL_COLOR_ARRAY GL_TEXTURE_COORD_ARRAY GL_NORMALIZE GL_RESCALE_NORMAL GL_CLIP_PLANE0 GL_CLIP_PLANE1 GL_CLIP_PLANE2 GL_CLIP_PLANE3 GL_CLIP_PLANE4 GL_CLIP_PLANE5 GL_FOG GL_LIGHTING GL_COLOR_MATERIAL GL_LIGHT0 GL_LIGHT1 GL_LIGHT2 GL_LIGHT3 GL_LIGHT4 GL_LIGHT5 GL_LIGHT6 GL_LIGHT7 GL_POINT_SMOOTH GL_LINE_SMOOTH GL_CULL_FACE GL_POLYGON_OFFSET_FILL GL_MULTISAMPLE GL_SAMPLE_ALPHA_TO_COVERAGE GL_SAMPLE_ALPHA_TO_ONE GL_SAMPLE_COVERAGE GL_TEXTURE_2D GL_SCISSOR_TEST GL_ALPHA_TEST GL_STENCIL_TEST GL_DEPTH_TEST GL_BLEND GL_DITHER GL_COLOR_LOGIC_OP
+# OES_matrix_palette
+checkparam cap GL_MATRIX_INDEX_ARRAY_OES GL_WEIGHT_ARRAY_OES
+# OES_point_size_array
+checkparam cap GL_POINT_SIZE_ARRAY_OES
+# OES_point_sprite
+checkparam cap GL_POINT_SPRITE_OES
+# OES_texture_cube_map
+checkparam cap GL_TEXTURE_CUBE_MAP_OES GL_TEXTURE_GEN_STR_OES
+category GLES1.1
+
+name IsEnabled
+return GLboolean
+param cap GLenum
+checkparam cap GL_CULL_FACE GL_SCISSOR_TEST GL_POLYGON_OFFSET_FILL GL_SAMPLE_ALPHA_TO_COVERAGE GL_SAMPLE_COVERAGE GL_STENCIL_TEST GL_DEPTH_TEST GL_DITHER GL_BLEND
+props get
+category GLES2.0
+
+
+name DepthRangef
+return void
+param zNear GLclampf
+param zFar GLclampf
+convertalias DepthRange
+convertparams GLclampd zNear zFar
+category GLES1.1 GLES1.1:OES_single_precision GLES2.0
+
+name DepthRangex
+return void
+param zNear GLclampx
+param zFar GLclampx
+convertalias DepthRange
+convertparams GLclampd zNear zFar
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name Frustumf
+return void
+param left GLfloat
+param right GLfloat
+param bottom GLfloat
+param top GLfloat
+param zNear GLfloat
+param zFar GLfloat
+convertalias Frustum
+convertparams GLdouble left right bottom top zNear zFar
+category GLES1.1 GLES1.1:OES_single_precision
+
+name Frustumx
+return void
+param left GLfixed
+param right GLfixed
+param bottom GLfixed
+param top GLfixed
+param zNear GLfixed
+param zFar GLfixed
+convertalias Frustum
+convertparams GLdouble left right bottom top zNear zFar
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name LoadIdentity
+return void
+category 1.0 GLES1.1
+
+name LoadMatrixf
+return void
+param m const GLfloat *
+vector m 16
+category 1.0 GLES1.1
+
+name LoadMatrixx
+return void
+param m const GLfixed *
+vector m 16
+convertalias LoadMatrixf
+convertparams GLfloat m
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name MatrixMode
+return void
+param mode GLenum
+checkparam mode GL_MODELVIEW GL_PROJECTION GL_TEXTURE
+# OES_matrix_palette
+checkparam mode GL_MATRIX_PALETTE_OES
+category 1.0 GLES1.1
+
+name MultMatrixf
+return void
+param m const GLfloat *
+vector m 16
+category 1.0 GLES1.1
+
+name MultMatrixx
+return void
+param m const GLfixed *
+vector m 16
+convertalias MultMatrixf
+convertparams GLfloat m
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name Orthof
+return void
+param left GLfloat
+param right GLfloat
+param bottom GLfloat
+param top GLfloat
+param zNear GLfloat
+param zFar GLfloat
+convertalias Ortho
+convertparams GLdouble left right bottom top zNear zFar
+category GLES1.1 GLES1.1:OES_single_precision
+
+name Orthox
+return void
+param left GLfixed
+param right GLfixed
+param bottom GLfixed
+param top GLfixed
+param zNear GLfixed
+param zFar GLfixed
+convertalias Ortho
+convertparams GLdouble left right bottom top zNear zFar
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name PopMatrix
+return void
+category GLES1.1
+
+name PushMatrix
+return void
+category GLES1.1
+
+name Rotatef
+return void
+param angle GLfloat
+param x GLfloat
+param y GLfloat
+param z GLfloat
+category 1.0 GLES1.1
+
+name Rotatex
+return void
+param angle GLfixed
+param x GLfixed
+param y GLfixed
+param z GLfixed
+convertalias Rotatef
+convertparams GLfloat angle x y z
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name Scalef
+return void
+param x GLfloat
+param y GLfloat
+param z GLfloat
+category 1.0 GLES1.1
+
+name Scalex
+return void
+param x GLfixed
+param y GLfixed
+param z GLfixed
+convertalias Scalef
+convertparams GLfloat x y z
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name Translatef
+return void
+param x GLfloat
+param y GLfloat
+param z GLfloat
+category 1.0 GLES1.1
+
+name Translatex
+return void
+param x GLfixed
+param y GLfixed
+param z GLfixed
+convertalias Translatef
+convertparams GLfloat x y z
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name Viewport
+return void
+param x GLint
+param y GLint
+param width GLsizei
+param height GLsizei
+category 1.0 GLES1.1 GLES2.0
+
+name ColorPointer
+return void
+param size GLint
+param type GLenum
+param stride GLsizei
+paramlist stride 0
+param pointer const GLvoid *
+checkparam size /GL_INVALID_VALUE 4
+checkparam type GL_UNSIGNED_BYTE GL_FIXED GL_FLOAT
+# OES_vertex_half_float: its values aren't in glext.h yet
+#checkparam type GL_HALF_FLOAT_OES
+category 1.1 GLES1.1
+
+name DisableClientState
+return void
+param array GLenum
+checkparam array GL_COLOR_ARRAY GL_NORMAL_ARRAY GL_TEXTURE_COORD_ARRAY GL_VERTEX_ARRAY
+# OES_matrix_palette
+checkparam array GL_MATRIX_INDEX_ARRAY_OES GL_WEIGHT_ARRAY_OES
+# OES_point_size_array
+checkparam array GL_POINT_SIZE_ARRAY_OES
+category 1.1 GLES1.1
+
+name DrawArrays
+return void
+param mode GLenum
+checkparam mode GL_POINTS GL_LINE_STRIP GL_LINE_LOOP GL_LINES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN GL_TRIANGLES
+param first GLint
+param count GLsizei
+category 1.1 GLES1.1 GLES2.0
+
+name DrawElements
+return void
+param mode GLenum
+checkparam mode GL_POINTS GL_LINE_STRIP GL_LINE_LOOP GL_LINES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN GL_TRIANGLES
+param count GLsizei
+param type GLenum
+checkparam type GL_UNSIGNED_BYTE GL_UNSIGNED_SHORT
+param indices const GLvoid *
+# OES_element_index_uint - not in GLES1.1 extension headers yet
+checkparam type GLES2.0:GL_UNSIGNED_INT
+category 1.1 GLES1.1 GLES2.0
+
+name EnableClientState
+return void
+param array GLenum
+checkparam array GL_COLOR_ARRAY GL_NORMAL_ARRAY GL_TEXTURE_COORD_ARRAY GL_VERTEX_ARRAY
+# OES_matrix_palette
+checkparam array GL_MATRIX_INDEX_ARRAY_OES GL_WEIGHT_ARRAY_OES
+# OES_point_size_array
+checkparam array GL_POINT_SIZE_ARRAY_OES
+category 1.1 GLES1.1
+
+name GetPointerv
+return void
+param pname GLenum
+checkparam pname GL_COLOR_ARRAY_POINTER GL_NORMAL_ARRAY_POINTER GL_TEXTURE_COORD_ARRAY_POINTER GL_VERTEX_ARRAY_POINTER
+param params GLvoid **
+props get
+# OES_matrix_palette
+checkparam pname GL_MATRIX_INDEX_ARRAY_POINTER_OES GL_WEIGHT_ARRAY_POINTER_OES
+# OES_point_size_array
+checkparam pname GL_POINT_SIZE_ARRAY_POINTER_OES
+category 1.1 GLES1.1
+
+name Normal3f
+aliasprefix _vbo_
+return void
+param nx GLfloat
+param ny GLfloat
+param nz GLfloat
+category GLES1.1
+
+name Normal3x
+aliasprefix _vbo_
+return void
+param nx GLfixed
+param ny GLfixed
+param nz GLfixed
+convertalias Normal3f
+convertparams GLfloat nx ny nz
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name NormalPointer
+return void
+param type GLenum
+checkparam type GL_BYTE GL_SHORT GL_FIXED GL_FLOAT
+param stride GLsizei
+param pointer const GLvoid *
+# OES_vertex_half_float - not yet in glext.h
+#checkparam type GL_HALF_FLOAT_OES
+category 1.1 GLES1.1
+
+name TexCoordPointer
+return void
+param size GLint
+param type GLenum
+param stride GLsizei
+param pointer const GLvoid *
+checkparam size /GL_INVALID_VALUE 2 3 4
+checkparam type GL_BYTE GL_SHORT GL_FIXED GL_FLOAT
+# OES_vertex_half_float - not yet in glext.h
+#checkparam type GL_HALF_FLOAT_OES
+category 1.1 GLES1.1
+
+name VertexPointer
+return void
+param size GLint
+param type GLenum
+param stride GLsizei
+param pointer const GLvoid *
+checkparam size /GL_INVALID_VALUE 2 3 4
+checkparam type GL_BYTE GL_SHORT GL_FIXED GL_FLOAT
+# OES_vertex_half_float - not yet in glext.h
+#checkparam type GL_HALF_FLOAT_OES
+category 1.1 GLES1.1
+
+name PolygonOffset
+return void
+param factor GLfloat
+param units GLfloat
+category 1.1 GLES1.1 GLES2.0
+
+name PolygonOffsetx
+return void
+param factor GLfixed
+param units GLfixed
+convertalias PolygonOffset
+convertparams GLfloat factor units
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name CopyTexImage2D
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Z GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+param level GLint
+param internalFormat GLenum
+param x GLint
+param y GLint
+param width GLsizei
+param height GLsizei
+param border GLint
+checkparam internalFormat /GL_INVALID_VALUE GL_ALPHA GL_LUMINANCE GL_LUMINANCE_ALPHA GL_RGB GL_RGBA
+checkparam border /GL_INVALID_VALUE 0
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES
+# OES_depth_texture
+checkparam internalFormat GLES2.0:GL_DEPTH_COMPONENT
+category GLES1.1 GLES2.0
+
+name CopyTexSubImage2D
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Z GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+param level GLint
+param xoffset GLint
+param yoffset GLint
+param x GLint
+param y GLint
+param width GLsizei
+param height GLsizei
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES
+category GLES1.1 GLES2.0
+
+name TexSubImage2D
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Z GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP
+param level GLint
+param xoffset GLint
+param yoffset GLint
+param width GLsizei
+param height GLsizei
+param format GLenum
+param type GLenum
+param pixels const GLvoid *
+checkparam format /GL_INVALID_VALUE GL_ALPHA GL_LUMINANCE GL_LUMINANCE_ALPHA GL_RGB GL_RGBA
+checkdependentparam format GL_RGBA type GL_UNSIGNED_BYTE GL_UNSIGNED_SHORT_4_4_4_4 GL_UNSIGNED_SHORT_5_5_5_1
+checkdependentparam format GL_RGB type GL_UNSIGNED_BYTE GL_UNSIGNED_SHORT_5_6_5
+checkdependentparam format GL_LUMINANCE_ALPHA type GL_UNSIGNED_BYTE
+checkdependentparam format GL_LUMINANCE type GL_UNSIGNED_BYTE
+checkdependentparam format GL_ALPHA type GL_UNSIGNED_BYTE
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_OES
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES
+# OES_texture_float
+checkdependentparam format GL_ALPHA type GL_FLOAT
+checkdependentparam format GL_RGB type GL_FLOAT
+checkdependentparam format GL_RGBA type GL_FLOAT
+checkdependentparam format GL_LUMINANCE type GL_FLOAT
+checkdependentparam format GL_LUMINANCE_ALPHA type GL_FLOAT
+# OES_texture_half_float
+checkdependentparam format GL_ALPHA type GLES2.0:GL_HALF_FLOAT_OES
+checkdependentparam format GL_RGB type GLES2.0:GL_HALF_FLOAT_OES
+checkdependentparam format GL_RGBA type GLES2.0:GL_HALF_FLOAT_OES
+checkdependentparam format GL_LUMINANCE type GLES2.0:GL_HALF_FLOAT_OES
+checkdependentparam format GL_LUMINANCE_ALPHA type GLES2.0:GL_HALF_FLOAT_OES
+# EXT_texture_type_2_10_10_10_REV
+checkdependentparam format GL_RGBA type GLES2.0:GL_UNSIGNED_INT_2_10_10_10_REV_EXT
+# OES_depth_texture
+checkdependentparam format GL_DEPTH_COMPONENT type GLES2.0:GL_UNSIGNED_SHORT GLES2.0:GL_UNSIGNED_INT
+category GLES1.1 GLES2.0
+
+name BindTexture
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP
+param texture GLuint
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_OES
+category GLES1.1 GLES2.0
+
+name DeleteTextures
+return void
+param n GLsizei
+param textures const GLuint *
+category 1.1 GLES1.1 GLES2.0
+
+name GenTextures
+return void
+param n GLsizei
+param textures GLuint *
+props get
+category 1.1 GLES1.1 GLES2.0
+
+name IsTexture
+return GLboolean
+param texture GLuint
+props get
+category 1.1 GLES1.1 GLES2.0
+
+name BlendColor
+return void
+param red GLclampf
+param green GLclampf
+param blue GLclampf
+param alpha GLclampf
+category 1.2 GLES2.0
+
+name BlendEquation
+return void
+param mode GLenum
+checkparam mode GLES1.1:GL_FUNC_ADD_OES GLES1.1:GL_FUNC_SUBTRACT_OES GLES1.1:GL_FUNC_REVERSE_SUBTRACT_OES
+checkparam mode GLES2.0:GL_FUNC_ADD GLES2.0:GL_FUNC_SUBTRACT GLES2.0:GL_FUNC_REVERSE_SUBTRACT
+category GLES1.1:OES_blend_subtract GLES2.0
+
+name BlendEquationSeparate
+alias BlendEquationSeparateEXT
+return void
+param modeRGB GLenum
+param modeAlpha GLenum
+checkparam modeRGB GLES1.1:GL_FUNC_ADD_OES GLES1.1:GL_FUNC_SUBTRACT_OES GLES1.1:GL_FUNC_REVERSE_SUBTRACT_OES
+checkparam modeAlpha GLES1.1:GL_FUNC_ADD_OES GLES1.1:GL_FUNC_SUBTRACT_OES GLES1.1:GL_FUNC_REVERSE_SUBTRACT_OES
+checkparam modeRGB GLES1.1:GL_FUNC_ADD_OES GLES1.1:GL_FUNC_SUBTRACT_OES GLES1.1:GL_FUNC_REVERSE_SUBTRACT_OES
+checkparam modeAlpha GLES1.1:GL_FUNC_ADD_OES GLES1.1:GL_FUNC_SUBTRACT_OES GLES1.1:GL_FUNC_REVERSE_SUBTRACT_OES
+checkparam modeRGB GLES2.0:GL_FUNC_ADD GLES2.0:GL_FUNC_SUBTRACT GLES2.0:GL_FUNC_REVERSE_SUBTRACT
+checkparam modeAlpha GLES2.0:GL_FUNC_ADD GLES2.0:GL_FUNC_SUBTRACT GLES2.0:GL_FUNC_REVERSE_SUBTRACT
+checkparam modeRGB GLES2.0:GL_FUNC_ADD GLES2.0:GL_FUNC_SUBTRACT GLES2.0:GL_FUNC_REVERSE_SUBTRACT
+checkparam modeAlpha GLES2.0:GL_FUNC_ADD GLES2.0:GL_FUNC_SUBTRACT GLES2.0:GL_FUNC_REVERSE_SUBTRACT
+category GLES1.1:OES_blend_equation_separate GLES2.0
+
+name TexImage3D
+return void
+param target GLenum
+checkparam target GL_TEXTURE_3D_OES
+param level GLint
+param internalFormat GLenum
+checkparam internalFormat GL_ALPHA GL_LUMINANCE GL_LUMINANCE_ALPHA GL_RGB GL_RGBA
+param width GLsizei
+param height GLsizei
+param depth GLsizei
+param border GLint
+param format GLenum
+param type GLenum
+param pixels const GLvoid *
+# OES_texture_float
+checkparam type GL_FLOAT
+# OES_texture_half_float
+checkparam type GL_HALF_FLOAT_OES
+category GLES2.0:OES_texture_3D
+
+name TexSubImage3D
+return void
+param target GLenum
+param level GLint
+param xoffset GLint
+param yoffset GLint
+param zoffset GLint
+param width GLsizei
+param height GLsizei
+param depth GLsizei
+param format GLenum
+param type GLenum
+param pixels const GLvoid *
+# OES_texture_float
+checkparam type GL_FLOAT
+# OES_texture_half_float
+checkparam type GL_HALF_FLOAT_OES
+category GLES2.0:OES_texture_3D
+
+name CopyTexSubImage3D
+return void
+param target GLenum
+checkparam target GL_TEXTURE_3D_OES
+param level GLint
+param xoffset GLint
+param yoffset GLint
+param zoffset GLint
+param x GLint
+param y GLint
+param width GLsizei
+param height GLsizei
+category GLES2.0:OES_texture_3D
+
+name MultiTexCoord4x
+return void
+param texture GLenum
+checkparam texture GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7
+param s GLfixed
+param t GLfixed
+param r GLfixed
+param q GLfixed
+aliasprefix _vbo_
+convertalias MultiTexCoord4f
+convertparams GLfloat s t r q
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name CompressedTexImage3D
+alias CompressedTexImage3DARB
+return void
+param target GLenum
+checkparam target GL_TEXTURE_3D_OES
+param level GLint
+param internalFormat GLenum
+checkparam internalFormat GL_ALPHA GL_LUMINANCE GL_LUMINANCE_ALPHA GL_RGB GL_RGBA
+param width GLsizei
+param height GLsizei
+param depth GLsizei
+param border GLint
+param imagesize GLsizei
+param data const GLvoid *
+# AMD_compressed_3DC_texture
+checkparam internalFormat GL_3DC_X_AMD GL_3DC_XY_AMD
+# AMD_compressed_ATC_texture
+checkparam internalFormat GL_ATC_RGB_AMD GL_ATC_RGBA_EXPLICIT_ALPHA_AMD GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
+category GLES2.0:OES_texture_3D
+
+name CompressedTexSubImage3D
+alias CompressedTexSubImage3DARB
+return void
+param target GLenum
+checkparam target GL_TEXTURE_3D_OES
+param level GLint
+param xoffset GLint
+param yoffset GLint
+param zoffset GLint
+param width GLsizei
+param height GLsizei
+param depth GLsizei
+param format GLenum
+param imagesize GLsizei
+param data const GLvoid *
+category GLES2.0:OES_texture_3D
+
+name ActiveTexture
+alias ActiveTextureARB
+return void
+param texture GLenum
+checkparam texture GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+category 1.3 GLES1.1 GLES2.0
+
+name ClientActiveTexture
+alias ClientActiveTextureARB
+return void
+param texture GLenum
+checkparam texture GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+category 1.3 GLES1.1
+
+name MultiTexCoord4f
+aliasprefix _vbo_
+return void
+param texture GLenum
+checkparam texture GL_TEXTURE0 GL_TEXTURE1 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4 GL_TEXTURE5 GL_TEXTURE6 GL_TEXTURE7 GL_TEXTURE8 GL_TEXTURE9 GL_TEXTURE10 GL_TEXTURE11 GL_TEXTURE12 GL_TEXTURE13 GL_TEXTURE14 GL_TEXTURE15 GL_TEXTURE16 GL_TEXTURE17 GL_TEXTURE18 GL_TEXTURE19 GL_TEXTURE20 GL_TEXTURE21 GL_TEXTURE22 GL_TEXTURE23 GL_TEXTURE24 GL_TEXTURE25 GL_TEXTURE26 GL_TEXTURE27 GL_TEXTURE28 GL_TEXTURE29 GL_TEXTURE30 GL_TEXTURE31
+param s GLfloat
+param t GLfloat
+param r GLfloat
+param q GLfloat
+category 1.3 GLES1.1
+
+name SampleCoverage
+alias SampleCoverageARB
+return void
+param value GLclampf
+param invert GLboolean
+category 1.3 GLES1.1 GLES2.0
+
+name SampleCoveragex
+return void
+param value GLclampx
+param invert GLboolean
+convertalias SampleCoverageARB
+convertparams GLclampf value
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name CompressedTexImage2D
+alias CompressedTexImage2DARB
+return void
+param target GLenum
+param level GLint
+param internalFormat GLenum
+param width GLsizei
+param height GLsizei
+param border GLint
+param imageSize GLsizei
+param data const GLvoid *
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Z GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+checkparam border /GL_INVALID_VALUE 0
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES
+# OES_compressed_paletted_texture
+checkparam internalFormat /GL_INVALID_VALUE GL_PALETTE4_RGB8_OES GL_PALETTE4_RGBA8_OES GL_PALETTE4_R5_G6_B5_OES GL_PALETTE4_RGBA4_OES GL_PALETTE4_RGB5_A1_OES GL_PALETTE8_RGB8_OES GL_PALETTE8_RGBA8_OES GL_PALETTE8_R5_G6_B5_OES GL_PALETTE8_RGBA4_OES GL_PALETTE8_RGB5_A1_OES
+# OES_compressed_ETC1_RGB8_texture
+checkparam internalFormat GL_ETC1_RGB8_OES
+# AMD_compressed_3DC_texture
+checkparam internalFormat GL_3DC_X_AMD GL_3DC_XY_AMD
+# AMD_compressed_ATC_texture (GLES2.0 only?)
+checkparam internalFormat GL_ATC_RGB_AMD GL_ATC_RGBA_EXPLICIT_ALPHA_AMD GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
+category GLES1.1 GLES2.0
+
+name CompressedTexSubImage2D
+alias CompressedTexSubImage2DARB
+return void
+param target GLenum
+param level GLint
+param xoffset GLint
+param yoffset GLint
+param width GLsizei
+param height GLsizei
+param format GLenum
+param imageSize GLsizei
+param data const GLvoid *
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Z GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+checkparam format GL_PALETTE4_RGB8_OES GL_PALETTE4_RGBA8_OES GL_PALETTE4_R5_G6_B5_OES GL_PALETTE4_RGBA4_OES GL_PALETTE4_RGB5_A1_OES GL_PALETTE8_RGB8_OES GL_PALETTE8_RGBA8_OES GL_PALETTE8_R5_G6_B5_OES GL_PALETTE8_RGBA4_OES GL_PALETTE8_RGB5_A1_OES
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES
+category GLES1.1 GLES2.0
+
+name BlendFuncSeparate
+alias BlendFuncSeparateEXT
+return void
+param srcRGB GLenum
+param dstRGB GLenum
+param srcAlpha GLenum
+param dstAlpha GLenum
+checkparam srcRGB GL_ZERO GL_ONE GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_DST_COLOR GL_ONE_MINUS_DST_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_DST_ALPHA GL_ONE_MINUS_DST_ALPHA GL_SRC_ALPHA_SATURATE GLES2.0:GL_CONSTANT_COLOR GLES2.0:GL_ONE_MINUS_CONSTANT_COLOR GLES2.0:GL_CONSTANT_ALPHA GLES2.0:GL_ONE_MINUS_CONSTANT_ALPHA
+checkparam dstRGB GL_ZERO GL_ONE GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_DST_COLOR GL_ONE_MINUS_DST_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_DST_ALPHA GL_ONE_MINUS_DST_ALPHA GLES2.0:GL_CONSTANT_COLOR GLES2.0:GL_ONE_MINUS_CONSTANT_COLOR GLES2.0:GL_CONSTANT_ALPHA GLES2.0:GL_ONE_MINUS_CONSTANT_ALPHA
+checkparam srcAlpha GL_ZERO GL_ONE GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_DST_COLOR GL_ONE_MINUS_DST_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_DST_ALPHA GL_ONE_MINUS_DST_ALPHA GL_SRC_ALPHA_SATURATE GLES2.0:GL_CONSTANT_COLOR GLES2.0:GL_ONE_MINUS_CONSTANT_COLOR GLES2.0:GL_CONSTANT_ALPHA GLES2.0:GL_ONE_MINUS_CONSTANT_ALPHA
+checkparam dstAlpha GL_ZERO GL_ONE GL_SRC_COLOR GL_ONE_MINUS_SRC_COLOR GL_DST_COLOR GL_ONE_MINUS_DST_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA GL_DST_ALPHA GL_ONE_MINUS_DST_ALPHA GLES2.0:GL_CONSTANT_COLOR GLES2.0:GL_ONE_MINUS_CONSTANT_COLOR GLES2.0:GL_CONSTANT_ALPHA GLES2.0:GL_ONE_MINUS_CONSTANT_ALPHA
+category GLES1.1:OES_blend_func_separate GLES2.0
+
+name PointParameterf
+return void
+param pname GLenum
+checkparam pname GL_POINT_SIZE_MIN GL_POINT_SIZE_MAX GL_POINT_FADE_THRESHOLD_SIZE
+param param GLfloat
+category 1.4 GLES1.1
+
+name PointParameterfv
+return void
+param pname GLenum
+checkparam pname GL_POINT_SIZE_MIN GL_POINT_SIZE_MAX GL_POINT_FADE_THRESHOLD_SIZE GL_POINT_DISTANCE_ATTENUATION
+param params const GLfloat *
+dependentvector params 1 pname GL_POINT_SIZE_MIN GL_POINT_SIZE_MAX GL_POINT_FADE_THRESHOLD_SIZE
+dependentvector params 3 pname GL_POINT_DISTANCE_ATTENUATION
+category 1.4 GLES1.1
+
+name PointParameterx
+return void
+param pname GLenum
+checkparam pname GL_POINT_SIZE_MIN GL_POINT_SIZE_MAX GL_POINT_FADE_THRESHOLD_SIZE
+param param GLfixed
+convertalias PointParameterf
+convertparams GLfloat param
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name PointParameterxv
+return void
+param pname GLenum
+checkparam pname GL_POINT_SIZE_MIN GL_POINT_SIZE_MAX GL_POINT_FADE_THRESHOLD_SIZE GL_POINT_DISTANCE_ATTENUATION
+param params const GLfixed *
+dependentvector params 1 pname GL_POINT_SIZE_MIN GL_POINT_SIZE_MAX GL_POINT_FADE_THRESHOLD_SIZE
+dependentvector params 3 pname GL_POINT_DISTANCE_ATTENUATION
+convertalias PointParameterfv
+convertparams GLfloat params
+category GLES1.1 GLES1.1:OES_fixed_point
+
+name VertexAttrib1f
+aliasprefix _vbo_
+return void
+param index GLuint
+param x GLfloat
+category GLES2.0
+
+name VertexAttrib2f
+aliasprefix _vbo_
+return void
+param index GLuint
+param x GLfloat
+param y GLfloat
+category GLES2.0
+
+name VertexAttrib3f
+aliasprefix _vbo_
+return void
+param index GLuint
+param x GLfloat
+param y GLfloat
+param z GLfloat
+category GLES2.0
+
+name VertexAttrib4f
+aliasprefix _vbo_
+return void
+param index GLuint
+param x GLfloat
+param y GLfloat
+param z GLfloat
+param w GLfloat
+category GLES2.0
+
+name VertexAttrib1fv
+aliasprefix _vbo_
+return void
+param index GLuint
+param v const GLfloat *
+vector v 1
+category GLES2.0
+
+name VertexAttrib2fv
+aliasprefix _vbo_
+return void
+param index GLuint
+param v const GLfloat *
+vector v 2
+category GLES2.0
+
+name VertexAttrib3fv
+aliasprefix _vbo_
+return void
+param index GLuint
+param v const GLfloat *
+vector v 3
+category GLES2.0
+
+name VertexAttrib4fv
+aliasprefix _vbo_
+return void
+param index GLuint
+param v const GLfloat *
+vector v 4
+category GLES2.0
+
+name VertexAttribPointer
+alias VertexAttribPointerARB
+return void
+param index GLuint
+param size GLint
+checkparam size /GL_INVALID_VALUE 1 2 3 4
+param type GLenum
+checkparam type /GL_INVALID_VALUE GL_BYTE GL_UNSIGNED_BYTE GL_SHORT GL_UNSIGNED_SHORT GL_FIXED GL_FLOAT
+param normalized GLboolean
+param stride GLsizei
+param pointer const GLvoid *
+# OES_vertex_half_float
+checkparam type GL_HALF_FLOAT_OES
+# OES_vertex_type_10_10_10_2
+checkdependentparam type GL_UNSIGNED_INT_10_10_10_2_OES size /GL_INVALID_VALUE 3 4
+checkdependentparam type GL_INT_10_10_10_2_OES size /GL_INVALID_VALUE 3 4
+category GLES2.0
+
+name EnableVertexAttribArray
+alias EnableVertexAttribArrayARB
+return void
+param index GLuint
+category GLES2.0
+
+name DisableVertexAttribArray
+alias DisableVertexAttribArrayARB
+return void
+param index GLuint
+category GLES2.0
+
+name IsProgram
+return GLboolean
+param program GLuint
+props get
+category GLES2.0
+
+name GetProgramiv
+return void
+param program GLuint
+param pname GLenum
+checkparam pname GL_DELETE_STATUS GL_LINK_STATUS GL_VALIDATE_STATUS GL_INFO_LOG_LENGTH GL_ATTACHED_SHADERS GL_ACTIVE_ATTRIBUTES GL_ACTIVE_ATTRIBUTE_MAX_LENGTH GL_ACTIVE_UNIFORMS GL_ACTIVE_UNIFORM_MAX_LENGTH
+param params GLint *
+props get
+# OES_get_program_binary
+checkparam pname GL_PROGRAM_BINARY_LENGTH_OES
+category GLES2.0
+
+name GetVertexAttribfv
+alias GetVertexAttribfvARB
+return void
+param index GLuint
+param pname GLenum
+param params GLfloat *
+dependentvector params 1 pname GL_VERTEX_ATTRIB_ARRAY_ENABLED GL_VERTEX_ATTRIB_ARRAY_SIZE GL_VERTEX_ATTRIB_ARRAY_STRIDE GL_VERTEX_ATTRIB_ARRAY_TYPE GL_VERTEX_ATTRIB_ARRAY_NORMALIZED GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
+dependentvector params 16? pname GL_CURRENT_VERTEX_ATTRIB
+props get
+category GLES2.0
+
+name GetVertexAttribiv
+alias GetVertexAttribivARB
+return void
+param index GLuint
+param pname GLenum
+param params GLint *
+dependentvector params 1 pname GL_VERTEX_ATTRIB_ARRAY_ENABLED GL_VERTEX_ATTRIB_ARRAY_SIZE GL_VERTEX_ATTRIB_ARRAY_STRIDE GL_VERTEX_ATTRIB_ARRAY_TYPE GL_VERTEX_ATTRIB_ARRAY_NORMALIZED GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING GL_CURRENT_VERTEX_ATTRIB
+props get
+category GLES2.0
+
+name GetVertexAttribPointerv
+alias GetVertexAttribPointervARB
+return void
+param index GLuint
+param pname GLenum
+checkparam pname GL_VERTEX_ATTRIB_ARRAY_POINTER
+param pointer GLvoid **
+props get
+category GLES2.0
+
+name GetBufferPointerv
+alias GetBufferPointervARB
+return void
+param target GLenum
+checkparam target GL_ARRAY_BUFFER GL_ELEMENT_ARRAY_BUFFER
+param pname GLenum
+checkparam pname GL_BUFFER_MAP_POINTER_OES
+param params GLvoid **
+props get
+category GLES1.1:OES_mapbuffer GLES2.0:OES_mapbuffer
+
+name MapBuffer
+alias MapBufferARB
+return void *
+param target GLenum
+checkparam target GL_ARRAY_BUFFER GL_ELEMENT_ARRAY_BUFFER
+param access GLenum
+checkparam access GL_WRITE_ONLY_OES
+props get
+category GLES1.1:OES_mapbuffer GLES2.0:OES_mapbuffer
+
+name UnmapBuffer
+alias UnmapBufferARB
+return GLboolean
+param target GLenum
+checkparam target GL_ARRAY_BUFFER GL_ELEMENT_ARRAY_BUFFER
+props get
+category GLES1.1:OES_mapbuffer GLES2.0:OES_mapbuffer
+
+name BindBuffer
+alias BindBufferARB
+return void
+param target GLenum
+checkparam target GL_ARRAY_BUFFER GL_ELEMENT_ARRAY_BUFFER
+param buffer GLuint
+category 1.5 GLES1.1 GLES2.0
+
+name BufferData
+alias BufferDataARB
+return void
+param target GLenum
+checkparam target GL_ARRAY_BUFFER GL_ELEMENT_ARRAY_BUFFER
+param size GLsizeiptr
+param data const GLvoid *
+param usage GLenum
+checkparam usage GL_STATIC_DRAW GL_DYNAMIC_DRAW GLES2.0:GL_STREAM_DRAW
+category GLES1.1 GLES2.0
+
+name BufferSubData
+alias BufferSubDataARB
+return void
+param target GLenum
+checkparam target GL_ARRAY_BUFFER GL_ELEMENT_ARRAY_BUFFER
+param offset GLintptr
+param size GLsizeiptr
+param data const GLvoid *
+category 1.5 GLES1.1 GLES2.0
+
+name DeleteBuffers
+return void
+param n GLsizei
+param buffer const GLuint *
+category 1.5 GLES1.1 GLES2.0
+alias DeleteBuffersARB
+
+name GenBuffers
+alias GenBuffersARB
+return void
+param n GLsizei
+param buffer GLuint *
+props get
+category 1.5 GLES1.1 GLES2.0
+
+name GetBufferParameteriv
+alias GetBufferParameterivARB
+return void
+param target GLenum
+checkparam target GL_ARRAY_BUFFER GL_ELEMENT_ARRAY_BUFFER
+param pname GLenum
+checkparam pname GL_BUFFER_SIZE GL_BUFFER_USAGE
+param params GLint *
+props get
+# OES_mapbuffer
+checkparam pname GL_BUFFER_ACCESS_OES GL_BUFFER_MAPPED_OES
+category 1.5 GLES1.1 GLES2.0
+
+name IsBuffer
+alias IsBufferARB
+return GLboolean
+param buffer GLuint
+paramlist buffer 0
+props get
+category 1.5 GLES1.1 GLES2.0
+
+name CreateShader
+return GLuint
+param type GLenum
+checkparam type GL_VERTEX_SHADER GL_FRAGMENT_SHADER
+category GLES2.0
+
+name ShaderSource
+alias ShaderSourceARB
+return void
+param shader GLuint
+param count GLsizei
+param string const GLchar **
+param length const int *
+category GLES2.0
+
+name CompileShader
+alias CompileShaderARB
+return void
+param shader GLuint
+category GLES2.0
+
+name ReleaseShaderCompiler
+return void
+category GLES2.0
+
+name DeleteShader
+return void
+param shader GLuint
+category GLES2.0
+
+name ShaderBinary
+return void
+param n GLsizei
+param shaders const GLuint *
+param binaryformat GLenum
+param binary const GLvoid *
+param length GLsizei
+category GLES2.0
+
+name CreateProgram
+return GLuint
+category GLES2.0
+
+name AttachShader
+return void
+param program GLuint
+param shader GLuint
+category GLES2.0
+
+name DetachShader
+return void
+param program GLuint
+param shader GLuint
+category GLES2.0
+
+name LinkProgram
+alias LinkProgramARB
+return void
+param program GLuint
+category GLES2.0
+
+name UseProgram
+alias UseProgramObjectARB
+return void
+param program GLuint
+category GLES2.0
+
+name DeleteProgram
+return void
+param program GLuint
+category GLES2.0
+
+name GetActiveAttrib
+alias GetActiveAttribARB
+return void
+param program GLuint
+param index GLuint
+param bufSize GLsizei
+param length GLsizei *
+param size GLint *
+param type GLenum *
+param name GLchar *
+props get
+category GLES2.0
+
+name GetAttribLocation
+alias GetAttribLocationARB
+return GLint
+param program GLuint
+param name const char *
+props get
+category GLES2.0
+
+name BindAttribLocation
+alias BindAttribLocationARB
+return void
+param program GLuint
+param index GLuint
+param name const char *
+category GLES2.0
+
+name GetUniformLocation
+alias GetUniformLocationARB
+return GLint
+param program GLuint
+param name const char *
+props get
+category GLES2.0
+
+name GetActiveUniform
+alias GetActiveUniformARB
+return void
+param program GLuint
+param index GLuint
+param bufSize GLsizei
+param length GLsizei *
+param size GLint *
+param type GLenum *
+param name GLchar *
+props get
+category GLES2.0
+
+name Uniform1f
+alias Uniform1fARB
+return void
+param location GLint
+param v0 GLfloat
+category GLES2.0
+
+name Uniform2f
+alias Uniform2fARB
+return void
+return void
+param location GLint
+param v0 GLfloat
+param v1 GLfloat
+category GLES2.0
+
+name Uniform3f
+alias Uniform3fARB
+return void
+return void
+param location GLint
+param v0 GLfloat
+param v1 GLfloat
+param v2 GLfloat
+category GLES2.0
+
+name Uniform4f
+alias Uniform4fARB
+return void
+return void
+param location GLint
+param v0 GLfloat
+param v1 GLfloat
+param v2 GLfloat
+param v3 GLfloat
+category GLES2.0
+
+name Uniform1i
+alias Uniform1iARB
+return void
+param location GLint
+param v0 GLint
+category GLES2.0
+
+name Uniform2i
+alias Uniform2iARB
+return void
+param location GLint
+param v0 GLint
+param v1 GLint
+category GLES2.0
+
+name Uniform3i
+alias Uniform3iARB
+return void
+param location GLint
+param v0 GLint
+param v1 GLint
+param v2 GLint
+category GLES2.0
+
+name Uniform4i
+alias Uniform4iARB
+return void
+param location GLint
+param v0 GLint
+param v1 GLint
+param v2 GLint
+param v3 GLint
+category GLES2.0
+
+name Uniform1fv
+alias Uniform1fvARB
+return void
+param location GLint
+param count GLsizei
+param values const GLfloat *
+category GLES2.0
+
+name Uniform2fv
+alias Uniform2fvARB
+return void
+param location GLint
+param count GLsizei
+param values const GLfloat *
+category GLES2.0
+
+name Uniform3fv
+alias Uniform3fvARB
+return void
+param location GLint
+param count GLsizei
+param values const GLfloat *
+category GLES2.0
+
+name Uniform4fv
+alias Uniform4fvARB
+return void
+param location GLint
+param count GLsizei
+param values const GLfloat *
+category GLES2.0
+
+name Uniform1iv
+alias Uniform1ivARB
+return void
+param location GLint
+param count GLsizei
+param values const GLint *
+category GLES2.0
+
+name Uniform2iv
+alias Uniform2ivARB
+return void
+param location GLint
+param count GLsizei
+param values const GLint *
+category GLES2.0
+
+name Uniform3iv
+alias Uniform3ivARB
+return void
+param location GLint
+param count GLsizei
+param values const GLint *
+category GLES2.0
+
+name Uniform4iv
+alias Uniform4ivARB
+return void
+param location GLint
+param count GLsizei
+param values const GLint *
+category GLES2.0
+
+name UniformMatrix2fv
+alias UniformMatrix2fvARB
+return void
+param location GLint
+param count GLsizei
+param transpose GLboolean
+param value const GLfloat *
+category GLES2.0
+
+name UniformMatrix3fv
+alias UniformMatrix3fvARB
+return void
+param location GLint
+param count GLsizei
+param transpose GLboolean
+param value const GLfloat *
+category GLES2.0
+
+name UniformMatrix4fv
+alias UniformMatrix4fvARB
+return void
+param location GLint
+param count GLsizei
+param transpose GLboolean
+param value const GLfloat *
+category GLES2.0
+
+name ValidateProgram
+alias ValidateProgramARB
+return void
+param program GLuint
+category GLES2.0
+
+name GenerateMipmap
+alias GenerateMipmapEXT
+return void
+param target GLenum
+checkparam target GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP
+# OES_texture_cube_map
+checkparam target GLES1.1:GL_TEXTURE_CUBE_MAP_OES
+category GLES1.1:OES_framebuffer_object GLES2.0
+
+
+name BindFramebuffer
+alias BindFramebufferEXT
+return void
+param target GLenum
+checkparam target GLES1.1:GL_FRAMEBUFFER_OES GLES2.0:GL_FRAMEBUFFER
+param framebuffer GLuint
+category GLES1.1:OES_framebuffer_object GLES2.0
+
+name DeleteFramebuffers
+alias DeleteFramebuffersEXT
+return void
+param n GLsizei
+param framebuffers const GLuint *
+category GLES2.0 GLES1.1:OES_framebuffer_object
+
+name GenFramebuffers
+alias GenFramebuffersEXT
+return void
+param n GLsizei
+param ids GLuint *
+category GLES2.0 GLES1.1:OES_framebuffer_object
+
+name BindRenderbuffer
+alias BindRenderbufferEXT
+return void
+param target GLenum
+checkparam target GLES1.1:GL_RENDERBUFFER_OES GLES2.0:GL_RENDERBUFFER
+param renderbuffer GLuint
+category GLES1.1:OES_framebuffer_object GLES2.0
+
+name DeleteRenderbuffers
+alias DeleteRenderbuffersEXT
+return void
+param n GLsizei
+param renderbuffers const GLuint *
+category GLES2.0 GLES1.1:OES_framebuffer_object
+
+name GenRenderbuffers
+alias GenRenderbuffersEXT
+return void
+param n GLsizei
+param renderbuffers GLuint *
+category GLES2.0 GLES1.1:OES_framebuffer_object
+
+name RenderbufferStorage
+alias RenderbufferStorageEXT
+return void
+param target GLenum
+checkparam target GLES1.1:GL_RENDERBUFFER_OES GLES2.0:GL_RENDERBUFFER
+param internalFormat GLenum
+checkparam internalFormat GL_DEPTH_COMPONENT16_OES GL_RGBA4_OES GL_RGB5_A1_OES GL_RGB565_OES
+param width GLsizei
+param height GLsizei
+# OES_depth24
+checkparam internalFormat GL_DEPTH_COMPONENT24_OES
+# OES_depth32
+checkparam internalFormat GL_DEPTH_COMPONENT32_OES
+# OES_rgb8_rgba8
+checkparam internalFormat GL_RGB8_OES GL_RGBA8_OES
+# OES_stencil1
+checkparam internalFormat GL_STENCIL_INDEX1_OES
+# OES_stencil4
+checkparam internalFormat GL_STENCIL_INDEX4_OES
+# OES_stencil8
+checkparam internalFormat GL_STENCIL_INDEX8_OES
+# OES_packed_depth_stencil - not in glext.h yet
+checkparam internalFormat GLES2.0:GL_DEPTH24_STENCIL8_OES
+category GLES1.1:OES_framebuffer_object GLES2.0
+
+name FramebufferRenderbuffer
+alias FramebufferRenderbufferEXT
+return void
+param target GLenum
+checkparam target GLES1.1:GL_FRAMEBUFFER_OES GLES2.0:GL_FRAMEBUFFER
+param attachment GLenum
+checkparam attachment GLES1.1:GL_COLOR_ATTACHMENT0_OES GLES1.1:GL_DEPTH_ATTACHMENT_OES GLES1.1:GL_STENCIL_ATTACHMENT_OES
+checkparam attachment GLES2.0:GL_COLOR_ATTACHMENT0 GLES2.0:GL_DEPTH_ATTACHMENT GLES2.0:GL_STENCIL_ATTACHMENT
+param renderbuffertarget GLenum
+checkparam renderbuffertarget GLES1.1:GL_RENDERBUFFER_OES GLES2.0:GL_RENDERBUFFER
+param renderbuffer GLuint
+category GLES1.1:OES_framebuffer_object GLES2.0
+
+name FramebufferTexture2D
+alias FramebufferTexture2DEXT
+return void
+param target GLenum
+checkparam target GLES1.1:GL_FRAMEBUFFER_OES GLES2.0:GL_FRAMEBUFFER
+param attachment GLenum
+checkparam attachment GLES1.1:GL_COLOR_ATTACHMENT0_OES GLES1.1:GL_DEPTH_ATTACHMENT_OES GLES1.1:GL_STENCIL_ATTACHMENT_OES
+checkparam attachment GLES2.0:GL_COLOR_ATTACHMENT0 GLES2.0:GL_DEPTH_ATTACHMENT GLES2.0:GL_STENCIL_ATTACHMENT
+param textarget GLenum
+checkparam textarget /GL_INVALID_OPERATION GL_TEXTURE_2D GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_POSITIVE_Z GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_X GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y GLES2.0:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+param texture GLuint
+param level GLint
+# OES_texture_cube_map
+checkparam textarget GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES GLES1.1:GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES
+# According to the base specification, "level" must be 0. But
+# extension GL_OES_fbo_render_mipmap lifts that restriction,
+# so no restriction is placed here.
+category GLES1.1:OES_framebuffer_object GLES2.0
+
+name FramebufferTexture3D
+alias FramebufferTexture3DEXT
+return void
+param target GLenum
+param attachment GLenum
+param textarget GLenum
+param texture GLuint
+param level GLint
+param zoffset GLint
+category GLES2.0:OES_texture_3D
+
+name CheckFramebufferStatus
+alias CheckFramebufferStatusEXT
+return GLenum
+param target GLenum
+checkparam target GLES1.1:GL_FRAMEBUFFER_OES GLES2.0:GL_FRAMEBUFFER
+props get
+category GLES1.1:OES_framebuffer_object GLES2.0
+
+# One for GLES1.1 extension, one for GLES2.0 core
+name GetFramebufferAttachmentParameteriv
+alias GetFramebufferAttachmentParameterivEXT
+return void
+param target GLenum
+checkparam target GLES1.1:GL_FRAMEBUFFER_OES GLES2.0:GL_FRAMEBUFFER
+param attachment GLenum
+param pname GLenum
+param params GLint *
+props get
+dependentvector params 1 pname GLES1.1:GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES GLES1.1:GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES GLES1.1:GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES GLES1.1:GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES
+dependentvector params 1 pname GLES2.0:GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE GLES2.0:GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME GLES2.0:GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL GLES2.0:GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE
+# OES_texture3D
+dependentvector params 1 pname GLES2.0:GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES
+category GLES1.1:OES_framebuffer_object GLES2.0
+
+name GetRenderbufferParameteriv
+alias GetRenderbufferParameterivEXT
+return void
+param target GLenum
+checkparam target GLES1.1:GL_RENDERBUFFER_OES GLES2.0:GL_RENDERBUFFER
+param pname GLenum
+param params GLint *
+props get
+dependentvector params 1 pname GLES1.1:GL_RENDERBUFFER_WIDTH_OES GLES1.1:GL_RENDERBUFFER_HEIGHT_OES GLES1.1:GL_RENDERBUFFER_INTERNAL_FORMAT_OES GLES1.1:GL_RENDERBUFFER_RED_SIZE_OES GLES1.1:GL_RENDERBUFFER_GREEN_SIZE_OES GLES1.1:GL_RENDERBUFFER_BLUE_SIZE_OES GLES1.1:GL_RENDERBUFFER_ALPHA_SIZE_OES GLES1.1:GL_RENDERBUFFER_DEPTH_SIZE_OES GLES1.1:GL_RENDERBUFFER_STENCIL_SIZE_OES
+dependentvector params 1 pname GLES2.0:GL_RENDERBUFFER_WIDTH GLES2.0:GL_RENDERBUFFER_HEIGHT GLES2.0:GL_RENDERBUFFER_INTERNAL_FORMAT GLES2.0:GL_RENDERBUFFER_RED_SIZE GLES2.0:GL_RENDERBUFFER_GREEN_SIZE GLES2.0:GL_RENDERBUFFER_BLUE_SIZE GLES2.0:GL_RENDERBUFFER_ALPHA_SIZE GLES2.0:GL_RENDERBUFFER_DEPTH_SIZE GLES2.0:GL_RENDERBUFFER_STENCIL_SIZE
+category GLES1.1:OES_framebuffer_object GLES2.0
+
+name IsRenderbuffer
+alias IsRenderbufferEXT
+return GLboolean
+param renderbuffer GLuint
+props get
+category GLES2.0 GLES1.1:OES_framebuffer_object
+
+name IsFramebuffer
+alias IsFramebufferEXT
+return GLboolean
+param framebuffer GLuint
+props get
+category GLES2.0 GLES1.1:OES_framebuffer_object
+
+name IsShader
+return GLboolean
+param shader GLuint
+props get
+category GLES2.0
+
+name GetShaderiv
+return void
+param shader GLuint
+param pname GLenum
+param params GLint *
+props get
+checkparam pname GL_SHADER_TYPE GL_COMPILE_STATUS GL_DELETE_STATUS GL_INFO_LOG_LENGTH GL_SHADER_SOURCE_LENGTH
+category GLES2.0
+
+name GetAttachedShaders
+return void
+param program GLuint
+param maxCount GLsizei
+param count GLsizei *
+param shaders GLuint *
+props get
+category GLES2.0
+
+name GetShaderInfoLog
+return void
+param shader GLuint
+param bufSize GLsizei
+param length GLsizei *
+param infoLog GLchar *
+props get
+category GLES2.0
+
+name GetProgramInfoLog
+return void
+param program GLuint
+param bufSize GLsizei
+param length GLsizei *
+param infoLog GLchar *
+props get
+category GLES2.0
+
+name GetShaderSource
+alias GetShaderSourceARB
+return void
+param shader GLuint
+param bufSize GLsizei
+param length GLsizei *
+param source GLchar *
+props get
+category GLES2.0
+
+name GetShaderPrecisionFormat
+return void
+param shadertype GLenum
+param precisiontype GLenum
+param range GLint *
+param precision GLint *
+props get
+checkparam shadertype GL_VERTEX_SHADER GL_FRAGMENT_SHADER
+checkparam precisiontype GL_LOW_FLOAT GL_MEDIUM_FLOAT GL_HIGH_FLOAT GL_LOW_INT GL_MEDIUM_INT GL_HIGH_INT
+category GLES2.0
+
+name GetUniformfv
+alias GetUniformfvARB
+return void
+param program GLuint
+param location GLint
+param params GLfloat *
+props get
+category GLES2.0
+
+name GetUniformiv
+alias GetUniformivARB
+return void
+param program GLuint
+param location GLint
+param params GLint *
+props get
+category GLES2.0
+
+name QueryMatrixx
+return GLbitfield
+param mantissa GLfixed *
+vector mantissa 16
+param exponent GLint *
+vector exponent 16
+props get
+category GLES1.1:OES_query_matrix
+
+# OES_draw_texture doesn't appear to be supported in Mesa yet
+name DrawTexf
+return void
+param x GLfloat
+param y GLfloat
+param z GLfloat
+param w GLfloat
+param h GLfloat
+category GLES1.1:OES_draw_texture
+
+name DrawTexi
+return void
+param x GLint
+param y GLint
+param z GLint
+param w GLint
+param h GLint
+category GLES1.1:OES_draw_texture
+
+name DrawTexs
+return void
+param x GLshort
+param y GLshort
+param z GLshort
+param w GLshort
+param h GLshort
+category GLES1.1:OES_draw_texture
+
+name DrawTexx
+return void
+param x GLfixed
+param y GLfixed
+param z GLfixed
+param w GLfixed
+param h GLfixed
+convertalias DrawTexf
+convertparams GLfloat x y z w h
+category GLES1.1:OES_draw_texture
+
+name DrawTexfv
+return void
+param coords const GLfloat *
+vector coords 5
+category GLES1.1:OES_draw_texture
+
+name DrawTexiv
+return void
+param coords const GLint *
+vector coords 5
+category GLES1.1:OES_draw_texture
+
+name DrawTexsv
+return void
+param coords const GLshort *
+vector coords 5
+category GLES1.1:OES_draw_texture
+
+name DrawTexxv
+return void
+param coords const GLfixed *
+vector coords 5
+convertalias DrawTexfv
+convertparams GLfloat coords
+category GLES1.1:OES_draw_texture
+
+name EGLImageTargetTexture2D
+alias EGLImageTargetTexture2DOES
+return void
+param target GLenum
+param image GLeglImageOES
+checkparam target GL_TEXTURE_2D
+category GLES1.1:OES_EGL_image GLES2.0:OES_EGL_image
+
+name EGLImageTargetRenderbufferStorage
+alias EGLImageTargetRenderbufferStorageOES
+return void
+param target GLenum
+param image GLeglImageOES
+checkparam target GLES1.1:GL_RENDERBUFFER_OES GLES2.0:GL_RENDERBUFFER
+category GLES1.1:OES_EGL_image GLES2.0:OES_EGL_image
+
+# We don't support OES_get_program_binary yet either
+#name GetProgramBinary
+#return void
+#param program GLuint
+#param bufSize GLsizei
+#param length GLsizei *
+#param binaryFormat GLenum *
+#param binary GLvoid *
+#category GLES2.0:OES_get_program_binary
+#
+#name ProgramBinary
+#return void
+#param program GLuint
+#param binaryFormat GLenum
+#param binary const GLvoid *
+#param length GLint
+#category GLES2.0:OES_get_program_binary
diff --git a/src/mesa/es/main/apiutil.py b/src/mesa/es/main/apiutil.py
new file mode 100644
index 0000000000..7fb1afc3a8
--- /dev/null
+++ b/src/mesa/es/main/apiutil.py
@@ -0,0 +1,1117 @@
+
+# apiutil.py
+#
+# This file defines a bunch of utility functions for OpenGL API code
+# generation.
+
+import sys, string, re
+
+
+#======================================================================
+
+def CopyrightC( ):
+ print """/* Copyright (c) 2001, Stanford University
+ All rights reserved.
+
+ See the file LICENSE.txt for information on redistributing this software. */
+ """
+
+def CopyrightDef( ):
+ print """; Copyright (c) 2001, Stanford University
+ ; All rights reserved.
+ ;
+ ; See the file LICENSE.txt for information on redistributing this software.
+ """
+
+
+#======================================================================
+
+class APIFunction:
+ """Class to represent a GL API function (name, return type,
+ parameters, etc)."""
+ def __init__(self):
+ self.name = ''
+ self.returnType = ''
+ self.category = ''
+ self.categories = []
+ self.offset = -1
+ self.alias = ''
+ self.vectoralias = ''
+ self.convertalias = ''
+ self.aliasprefix = ''
+ self.params = []
+ self.paramlist = []
+ self.paramvec = []
+ self.paramaction = []
+ self.paramprop = []
+ self.paramset = []
+ self.props = []
+ self.chromium = []
+
+def FindParamIndex(params, paramName):
+ """Given a function record, find the index of a named parameter"""
+ for i in range (len(params)):
+ if paramName == params[i][0]:
+ return i
+ # If we get here, there was no such parameter
+ return None
+
+def SetTupleIndex(tuple, index, value):
+ t = ()
+ for i in range(len(tuple)):
+ if i == index:
+ t += (value,)
+ else:
+ t += (tuple[i],)
+ return t
+
+def VersionSpecificValues(category, values):
+ selectedValues = []
+ for value in values:
+ # Version-specific values are prefixed with the version
+ # number, e.g. GLES1.0:GL_TEXTURE_CUBE_MAP_OES
+ splitValue = value.split(":")
+ if len(splitValue) == 2:
+ if category != None and splitValue[0] != category:
+ # Don't want this one.
+ continue
+ else:
+ selectedValues.append(splitValue[1])
+ else:
+ selectedValues.append(value)
+ return selectedValues
+
+def ProcessSpecFile(filename, userFunc, category = None):
+ """Open the named API spec file and call userFunc(record, category) for each record
+ processed."""
+ specFile = open(filename, "r")
+ if not specFile:
+ print >>sys.stderr, "Error: couldn't open %s file!" % filename
+ sys.exit()
+
+ record = APIFunction()
+
+ for line in specFile.readlines():
+
+ # split line into tokens
+ tokens = string.split(line)
+
+ if len(tokens) > 0 and line[0] != '#':
+
+ if tokens[0] == 'name':
+ if record.name != '':
+ # process the old function now
+ userFunc(record, category)
+ # reset the record
+ record = APIFunction()
+
+ record.name = tokens[1]
+
+ elif tokens[0] == 'return':
+ record.returnType = string.join(tokens[1:], ' ')
+
+ elif tokens[0] == 'param':
+ name = tokens[1]
+ type = string.join(tokens[2:], ' ')
+ vecSize = 0
+ record.params.append((name, type, vecSize, None, [], None))
+
+ elif tokens[0] == 'paramprop':
+ name = tokens[1]
+ str = tokens[2:]
+ enums = []
+ for i in range(len(str)):
+ enums.append(str[i])
+ record.paramprop.append((name, enums))
+
+ elif tokens[0] == 'paramlist':
+ name = tokens[1]
+ str = tokens[2:]
+ list = []
+ for i in range(len(str)):
+ list.append(str[i])
+ record.paramlist.append((name,list))
+
+ elif tokens[0] == 'paramvec':
+ name = tokens[1]
+ str = tokens[2:]
+ vec = []
+ for i in range(len(str)):
+ vec.append(str[i])
+ record.paramvec.append((name,vec))
+
+ elif tokens[0] == 'paramset':
+ line = tokens[1:]
+ result = []
+ for i in range(len(line)):
+ tset = line[i]
+ if tset == '[':
+ nlist = []
+ elif tset == ']':
+ result.append(nlist)
+ nlist = []
+ else:
+ nlist.append(tset)
+ if result != []:
+ record.paramset.append(result)
+
+ elif tokens[0] == 'paramaction':
+ name = tokens[1]
+ str = tokens[2:]
+ list = []
+ for i in range(len(str)):
+ list.append(str[i])
+ record.paramaction.append((name,list))
+
+ elif tokens[0] == 'category':
+ record.category = tokens[1]
+ record.categories = tokens[1:]
+
+ elif tokens[0] == 'offset':
+ if tokens[1] == '?':
+ record.offset = -2
+ else:
+ record.offset = int(tokens[1])
+
+ elif tokens[0] == 'alias':
+ record.alias = tokens[1]
+
+ elif tokens[0] == 'vectoralias':
+ record.vectoralias = tokens[1]
+
+ elif tokens[0] == 'convertalias':
+ record.convertalias = tokens[1]
+
+ elif tokens[0] == 'aliasprefix':
+ record.aliasprefix = tokens[1]
+
+ elif tokens[0] == 'props':
+ record.props = tokens[1:]
+
+ elif tokens[0] == 'chromium':
+ record.chromium = tokens[1:]
+
+ elif tokens[0] == 'vector':
+ vecName = tokens[1]
+ vecSize = int(tokens[2])
+ index = FindParamIndex(record.params, vecName)
+ if index == None:
+ print >>sys.stderr, "Can't find vector '%s' for function '%s'" % (vecName, record.name)
+ # Adjust just the vector size
+ record.params[index] = SetTupleIndex(record.params[index], 2, vecSize)
+
+ elif tokens[0] == 'dependentvector':
+ dependentVecName = tokens[1]
+ # the dependentVecSize may be an int
+ # expression
+ dependentVecSize = tokens[2]
+ controllingParam = tokens[3]
+ controllingParamIndex = FindParamIndex(record.params, controllingParam)
+ if controllingParamIndex == None:
+ print >>sys.stderr, "Can't find controlling param '%s' for function '%s'" % (controllingParam, record.name)
+ controllingValues = tokens[4:]
+
+ # Remember that all of the controllingValues
+ # are valid values for the controllingParam.
+ # We may be duplicating controllingValues
+ # here (i.e. if we get them from different
+ # places); we'll sort them out later.
+ validValues = record.params[controllingParamIndex][4]
+ for value in VersionSpecificValues(category, controllingValues):
+ validValues.append((value, dependentVecSize, dependentVecName, [], None, None))
+ # Don't need to reassign validValues back
+ # to the tuple - it's a shallow pointer,
+ # so the tuple is already modified.
+ # (And attempting to do so would produce an
+ # error anyway.)
+
+ elif tokens[0] == "dependentnovalueconvert":
+ paramName = tokens[1]
+ controllingParamName = tokens[2]
+ controllingValues = tokens[3:]
+
+ controllingParamIndex = FindParamIndex(record.params, controllingParamName)
+ if controllingParamIndex == None:
+ print >>sys.stderr, "Can't find controlling param '%s' for function '%s'" % (controllingParamName, record.name)
+
+ validValues = record.params[controllingParamIndex][4]
+ for value in VersionSpecificValues(category, controllingValues):
+ validValues.append((value, None, None, [], None, "noconvert"))
+
+
+
+ elif tokens[0] == 'checkparam':
+ paramName = tokens[1]
+ values = tokens[2:]
+ paramIndex = FindParamIndex(record.params, paramName)
+ if paramIndex == None:
+ print >>sys.stderr, "Can't find checked param '%s' for function '%s'" % (paramName, record.name)
+
+ errorCode = None
+
+ # We may be duplicating valid values here;
+ # just add all values to the existing
+ # record, and we'll prune out duplicates
+ # later
+ validValues = record.params[paramIndex][4]
+
+ # A /GL_* value represents an error, not
+ # a real value. Look through the values
+ # and only append the non-error values.
+ for v in VersionSpecificValues(category, values):
+ if v[0] == "/":
+ errorCode = v[1:]
+ else:
+ validValues.append((v, None, None, [], errorCode, None))
+ # Don't need to reassign validValues back
+ # to the parameter tuple - it's a shallow pointer,
+ # so the tuple is already modified.
+ # (And attempting to do so would produce an
+ # error anyway.)
+
+ elif tokens[0] == 'checkdependentparam':
+ paramName = tokens[1]
+ controllingValue = tokens[2]
+ dependentParamName = tokens[3]
+ validDependentValues = tokens[4:]
+ errorCode = None
+
+ # A /GL_* value represents an error, not
+ # a real value. Look through the values
+ # and only append the non-error values.
+ validDependentValues = []
+ for v in tokens[4:]:
+ if v[0] == "/":
+ errorCode = v[1:]
+ else:
+ validDependentValues.append(v)
+
+ paramIndex = FindParamIndex(record.params, paramName)
+ if paramIndex == None:
+ print >>sys.stderr, "Can't find dependent param '%s' for function '%s'" % (paramName, record.name)
+
+ validValues = record.params[paramIndex][4]
+ # We may be duplicating valid values here;
+ # we'll sort them out later. Avoid
+ # adding a controlling value record
+ # at all if there are no values
+ # in the list of values (so that
+ # controlling values with only
+ # version-specific values listed
+ # end up as version-specific
+ # themselves).
+ versionSpecificValues = VersionSpecificValues(category, validDependentValues)
+ if versionSpecificValues != []:
+ validValues.append((controllingValue, None, dependentParamName, versionSpecificValues, errorCode, None))
+ # Don't need to reassign validValues back
+ # to the tuple - it's a shallow pointer,
+ # so the tuple is already modified.
+ # (And attempting to do so would produce an
+ # error anyway.)
+
+ elif tokens[0] == 'convertparams':
+ convertToType = tokens[1]
+ # Replace the conversion type in each named
+ # parameter
+ for paramName in tokens[2:]:
+ paramIndex = FindParamIndex(record.params, paramName)
+ if paramIndex == None:
+ print >>sys.stderr, "Can't find converted param '%s' for function '%s'" % (paramName, record.name)
+ # Tuples don't support item assignment,
+ # so to replace scalar values in a
+ # tuple, you have to reassign the
+ # whole friggin' thing.
+ record.params[paramIndex] = SetTupleIndex(record.params[paramIndex], 3, convertToType)
+
+ else:
+ print >>sys.stderr, 'Invalid token %s after function %s' % (tokens[0], record.name)
+ #endif
+ #endif
+ #endfor
+
+ # Call the user function for the last record, if we still have one
+ # lying around nearly finished
+ if record.name != '':
+ # process the function now
+ userFunc(record, category)
+ specFile.close()
+#enddef
+
+
+# Dictionary [name] of APIFunction:
+__FunctionDict = {}
+
+# Dictionary [name] of name
+__VectorVersion = {}
+
+# Reverse mapping of function name aliases
+__ReverseAliases = {}
+
+def CheckCategories(category, categories):
+ for c in categories:
+ if category == c.split(":")[0]:
+ return 1
+
+ return 0
+
+def AddFunction(record, category):
+ # If there is a category, we only want records from that category.
+ # Note that a category may be in the form "GLES1.1:OES_extension_name",
+ # which means that the function is supported as an extension in
+ # GLES1.1...
+ if category and not CheckCategories(category, record.categories):
+ return
+
+ # Don't allow duplicates
+ if __FunctionDict.has_key(record.name):
+ print >>sys.stderr, "Duplicate record name '%s' ignored" % record.name
+ return
+
+ # Clean up a bit. We collected valid values for parameters
+ # on the fly; it's quite possible that there are duplicates.
+ # If there are, collect them together.
+ #
+ # We're also going to keep track of all the dependent values
+ # that can show up for a parameter; the number of GLenum values
+ # (identified with a prefixed "GL_") affects how parameter
+ # value conversion happens, as GLenum values are not scaled
+ # when converted to or from GLfixed values, the way integer
+ # and floating point values are.
+ paramValueConversion = {}
+
+ for i in range(len(record.params)):
+ foundValidValues = {}
+
+ (name, type, maxVecSize, convertToType, validValues, valueConversion) = record.params[i]
+ for (controllingValue, vecSize, dependentParamName, dependentValues, errorCode, valueConvert) in validValues:
+ # Keep track of the maximum vector size for the
+ # *dependent* parameter, not for the controlling
+ # parameter. Note that the dependent parameter
+ # may be an expression - in this case, don't
+ # consider it.
+ if dependentParamName != None and vecSize != None and vecSize.isdigit():
+ dependentParamIndex = FindParamIndex(record.params, dependentParamName)
+ if dependentParamIndex == None:
+ print >>sys.stderr, "Couldn't find dependent parameter '%s' of function '%s'" % (dependentParamName, record.name)
+ (dName, dType, dMaxVecSize, dConvert, dValid, dValueConversion) = record.params[dependentParamIndex]
+ if dMaxVecSize == None or int(vecSize) > dMaxVecSize:
+ dMaxVecSize = int(vecSize)
+ record.params[dependentParamIndex] = (dName, dType, dMaxVecSize, dConvert, dValid, dValueConversion)
+
+ # Make sure an entry for the controlling value
+ # exists in the foundValidValues dictionary
+ if controllingValue in foundValidValues:
+ # The value was already there. Merge the
+ # two together, giving errors if needed.
+ (oldControllingValue, oldVecSize, oldDependentParamName, oldDependentValues, oldErrorCode, oldValueConvert) = foundValidValues[controllingValue]
+
+ # Make sure the vector sizes are compatible;
+ # either one should be None (and be
+ # overridden by the other), or they should
+ # match exactly. If one is not an
+ # integer (this can happen if the
+ # dependent value is an integer expression,
+ # which occurs a couple of times), don't
+ # use it.
+ if oldVecSize == None:
+ oldVecSize = vecSize
+ elif vecSize != None and vecSize != oldVecSize:
+ print >>sys.stderr, "Found two different vector sizes (%s and %s) for the same controlling value '%s' of the same parameter '%s' of function '%s'" % (oldVecSize, vecSize, controllingValue, name, record.name)
+
+ # Same for the dependent parameter name.
+ if oldDependentParamName == None:
+ oldDependentParamName = dependentParamName
+ elif dependentParamName != None and dependentParamName != oldDependentParamName:
+ print >>sys.stderr, "Found two different dependent parameter names (%s and %s) for the same controlling value '%s' of the same parameter '%s' of function '%s'" % (oldDependentParamName, dependentParamName, controllingValue, name, record.name)
+
+ # And for the error code.
+ if oldErrorCode == None:
+ oldErrorCode = errorCode
+ elif errorCode != None and errorCode != oldErrorCode:
+ print >>sys.stderr, "Found two different error codes(%s and %s) for the same controlling value '%s' of the same parameter '%s' of function '%s'" % (oldErrorCode, errorCode, controllingValue, name, record.name)
+
+ # And for the value conversion flag
+ if oldValueConvert == None:
+ oldValueConvert = valueConvert
+ elif valueConvert != None and valueConvert != oldValueConvert:
+ print >>sys.stderr, "Found two different value conversions(%s and %s) for the same controlling value '%s' of the same parameter '%s' of function '%s'" % (oldValueConvert, valueConvert, controllingValue, name, record.name)
+
+ # Combine the dependentValues together
+ # directly, but uniquely
+ for value in dependentValues:
+ if value not in oldDependentValues:
+ oldDependentValues.append(value)
+
+ # Stick the combined value back into the
+ # dictionary. We'll sort it back to the
+ # array later.
+ foundValidValues[oldControllingValue] = (oldControllingValue, oldVecSize, oldDependentParamName, oldDependentValues, oldErrorCode, oldValueConvert)
+ else: # new controlling value
+ # Just add it to the dictionary so we don't
+ # add the same value more than once.
+ foundValidValues[controllingValue] = (controllingValue, vecSize, dependentParamName, dependentValues, errorCode, valueConvert)
+ # endif a new controlling value
+
+ # endfor all valid values for this parameter
+
+ # Now the foundValidValues[] dictionary holds all the
+ # pruned values (at most one for each valid value).
+ # But the validValues[] array still holds the order,
+ # which we want to maintain. Go through the validValues
+ # array just for the names of the controlling values;
+ # add any uncopied values to the prunedValidValues array.
+ prunedValidValues = []
+
+ for (controllingValue, vecSize, dependentParamName, dependentValues, errorCode, valueConvert) in validValues:
+ if controllingValue in foundValidValues:
+ prunedValidValues.append(foundValidValues[controllingValue])
+ # Delete it from the dictionary so it isn't
+ # copied again.
+ del foundValidValues[controllingValue]
+
+ # Each parameter that is being converted may have a
+ # subset of values that are GLenums and are never
+ # converted. In some cases, the parameter will
+ # be implicitly determined to be such, by examining
+ # the listed possible values and determining for
+ # any particular controlling value whether there are
+ # any GLenum-valued allowed values.
+ #
+ # In other cases, the parameter will be explicitly
+ # marked as such with the "dependentnovalueconvert" flag;
+ # this is the way it has to be done with queries (which
+ # cannot list a valid list of values to be passed,
+ # because values are returned, not passed).
+ #
+ # For each value of controlling GLenum, we'll also
+ # need to know whether its dependent values are
+ # always converted (none of its values require
+ # GLenums to be passed in dependent parameters),
+ # never converted (all of its values require GLenums),
+ # or sometimes converted.
+ numNoConvertValues = 0
+ allDependentParams = []
+ for j in range(len(prunedValidValues)):
+ (controllingValue, vecSize, dependentParamName, dependentValues, errorCode, valueConvert) = prunedValidValues[j]
+ if dependentParamName != None and dependentParamName not in allDependentParams:
+ allDependentParams.append(dependentParamName)
+
+ # Check for an explicit noconvert marking...
+ if valueConvert == "noconvert":
+ numNoConvertValues += 1
+ else:
+ # Or check for an implicit one.
+ for value in dependentValues:
+ if value[0:3] == "GL_":
+ valueConvert = "noconvert"
+ prunedValidValues[j] = (controllingValue, vecSize, dependentParamName, dependentValues, errorCode, valueConvert)
+ numNoConvertValues += 1
+ break
+
+ # For each named dependent param, set the value conversion
+ # flag based on whether all values, none, or some need
+ # value conversion. This value is set stepwise
+ # for each parameter examined -
+ for dp in allDependentParams:
+ if numNoConvertValues == 0:
+ if not paramValueConversion.has_key(dp):
+ paramValueConversion[dp] = "all"
+ elif paramValueConversion[dp] == "none":
+ paramValueConversion[dp] = "some"
+ elif numNoConvertValues == len(prunedValidValues):
+ if not paramValueConversion.has_key(dp):
+ paramValueConversion[dp] = "none"
+ elif paramValueConversion[dp] == "all":
+ paramValueConversion[dp] = "some"
+ else:
+ paramValueConversion[dp] = "some"
+
+ # Save away the record. Save a placeholder in the
+ # valueConversion field - we can't set that until we've
+ # examined all the parameters.
+ record.params[i] = (name, type, maxVecSize, convertToType, prunedValidValues, None)
+
+ # endfor each param of the passed-in function record
+
+ # One more pass: for each parameter, if it is a parameter that
+ # needs conversion, save its value conversion type ("all", "none",
+ # or "some"). We only have to worry about conditional value
+ # conversion for GLfixed parameters; in all other cases, we
+ # either don't convert at all (for non-converting parameters) or
+ # we convert everything.
+ for i in range(len(record.params)):
+ (name, type, maxVecSize, convertToType, validValues, valueConversion) = record.params[i]
+ if convertToType == None:
+ valueConversion = None
+ elif paramValueConversion.has_key(name):
+ valueConversion = paramValueConversion[name]
+ else:
+ valueConversion = "all"
+
+ record.params[i] = (name, type, maxVecSize, convertToType, validValues, valueConversion)
+
+ # We're done cleaning up!
+ # Add the function to the permanent record and we're done.
+ __FunctionDict[record.name] = record
+
+
+def GetFunctionDict(specFile = "", category = None):
+ if not specFile:
+ specFile = "../glapi_parser/APIspec.txt"
+ if len(__FunctionDict) == 0:
+ ProcessSpecFile(specFile, AddFunction, category)
+ # Look for vector aliased functions
+ for func in __FunctionDict.keys():
+ va = __FunctionDict[func].vectoralias
+ if va != '':
+ __VectorVersion[va] = func
+ #endif
+
+ # and look for regular aliases (for glloader)
+ a = __FunctionDict[func].alias
+ if a:
+ __ReverseAliases[a] = func
+ #endif
+ #endfor
+ #endif
+ return __FunctionDict
+
+
+def GetAllFunctions(specFile = "", category = None):
+ """Return sorted list of all functions known to Chromium."""
+ d = GetFunctionDict(specFile, category)
+ funcs = []
+ for func in d.keys():
+ rec = d[func]
+ if not "omit" in rec.chromium:
+ funcs.append(func)
+ funcs.sort()
+ return funcs
+
+
+def GetDispatchedFunctions(specFile = "", category = None):
+ """Return sorted list of all functions handled by SPU dispatch table."""
+ d = GetFunctionDict(specFile, category)
+ funcs = []
+ for func in d.keys():
+ rec = d[func]
+ if (not "omit" in rec.chromium and
+ not "stub" in rec.chromium and
+ rec.alias == ''):
+ funcs.append(func)
+ funcs.sort()
+ return funcs
+
+#======================================================================
+
+def ReturnType(funcName):
+ """Return the C return type of named function.
+ Examples: "void" or "const GLubyte *". """
+ d = GetFunctionDict()
+ return d[funcName].returnType
+
+
+def Parameters(funcName):
+ """Return list of tuples (name, type, vecSize) of function parameters.
+ Example: if funcName=="ClipPlane" return
+ [ ("plane", "GLenum", 0), ("equation", "const GLdouble *", 4) ] """
+ d = GetFunctionDict()
+ return d[funcName].params
+
+def ParamAction(funcName):
+ """Return list of names of actions for testing.
+ For PackerTest only."""
+ d = GetFunctionDict()
+ return d[funcName].paramaction
+
+def ParamList(funcName):
+ """Return list of tuples (name, list of values) of function parameters.
+ For PackerTest only."""
+ d = GetFunctionDict()
+ return d[funcName].paramlist
+
+def ParamVec(funcName):
+ """Return list of tuples (name, vector of values) of function parameters.
+ For PackerTest only."""
+ d = GetFunctionDict()
+ return d[funcName].paramvec
+
+def ParamSet(funcName):
+ """Return list of tuples (name, list of values) of function parameters.
+ For PackerTest only."""
+ d = GetFunctionDict()
+ return d[funcName].paramset
+
+
+def Properties(funcName):
+ """Return list of properties of the named GL function."""
+ d = GetFunctionDict()
+ return d[funcName].props
+
+def AllWithProperty(property):
+ """Return list of functions that have the named property."""
+ funcs = []
+ for funcName in GetDispatchedFunctions():
+ if property in Properties(funcName):
+ funcs.append(funcName)
+ return funcs
+
+def Category(funcName):
+ """Return the primary category of the named GL function."""
+ d = GetFunctionDict()
+ return d[funcName].category
+
+def Categories(funcName):
+ """Return all the categories of the named GL function."""
+ d = GetFunctionDict()
+ return d[funcName].categories
+
+def ChromiumProps(funcName):
+ """Return list of Chromium-specific properties of the named GL function."""
+ d = GetFunctionDict()
+ return d[funcName].chromium
+
+def ParamProps(funcName):
+ """Return list of Parameter-specific properties of the named GL function."""
+ d = GetFunctionDict()
+ return d[funcName].paramprop
+
+def Alias(funcName):
+ """Return the function that the named function is an alias of.
+ Ex: Alias('DrawArraysEXT') = 'DrawArrays'.
+ """
+ d = GetFunctionDict()
+ return d[funcName].alias
+
+def AliasPrefix(funcName):
+ """Return the function that the named function is an alias of.
+ Ex: Alias('DrawArraysEXT') = 'DrawArrays'.
+ """
+ d = GetFunctionDict()
+ if d[funcName].aliasprefix == '':
+ return "_mesa_"
+ else:
+ return d[funcName].aliasprefix
+
+def ReverseAlias(funcName):
+ """Like Alias(), but the inverse."""
+ d = GetFunctionDict()
+ if funcName in __ReverseAliases.keys():
+ return __ReverseAliases[funcName]
+ else:
+ return ''
+
+def NonVectorFunction(funcName):
+ """Return the non-vector version of the given function, or ''.
+ For example: NonVectorFunction("Color3fv") = "Color3f"."""
+ d = GetFunctionDict()
+ return d[funcName].vectoralias
+
+def ConversionFunction(funcName):
+ """Return a function that can be used to implement the
+ given function, using different types.
+ For example: ConvertedFunction("Color4x") = "Color4f"."""
+ d = GetFunctionDict()
+ return d[funcName].convertalias
+
+def VectorFunction(funcName):
+ """Return the vector version of the given non-vector-valued function,
+ or ''.
+ For example: VectorVersion("Color3f") = "Color3fv"."""
+ d = GetFunctionDict()
+ if funcName in __VectorVersion.keys():
+ return __VectorVersion[funcName]
+ else:
+ return ''
+
+def GetCategoryWrapper(func_name):
+ """Return a C preprocessor token to test in order to wrap code.
+ This handles extensions.
+ Example: GetTestWrapper("glActiveTextureARB") = "CR_multitexture"
+ Example: GetTestWrapper("glBegin") = ""
+ """
+ cat = Category(func_name)
+ if (cat == "1.0" or
+ cat == "1.1" or
+ cat == "1.2" or
+ cat == "Chromium" or
+ cat == "GL_chromium"):
+ return ''
+ elif cat[0] =='1':
+ # i.e. OpenGL 1.3 or 1.4 or 1.5
+ return "OPENGL_VERSION_" + string.replace(cat, ".", "_")
+ else:
+ assert cat != ''
+ return string.replace(cat, "GL_", "")
+
+
+def CanCompile(funcName):
+ """Return 1 if the function can be compiled into display lists, else 0."""
+ props = Properties(funcName)
+ if ("nolist" in props or
+ "get" in props or
+ "setclient" in props):
+ return 0
+ else:
+ return 1
+
+def HasChromiumProperty(funcName, propertyList):
+ """Return 1 if the function or any alias has any property in the
+ propertyList"""
+ for funcAlias in [funcName, NonVectorFunction(funcName), VectorFunction(funcName)]:
+ if funcAlias:
+ props = ChromiumProps(funcAlias)
+ for p in propertyList:
+ if p in props:
+ return 1
+ return 0
+
+def CanPack(funcName):
+ """Return 1 if the function can be packed, else 0."""
+ return HasChromiumProperty(funcName, ['pack', 'extpack', 'expandpack'])
+
+def HasPackOpcode(funcName):
+ """Return 1 if the function has a true pack opcode"""
+ return HasChromiumProperty(funcName, ['pack', 'extpack'])
+
+def SetsState(funcName):
+ """Return 1 if the function sets server-side state, else 0."""
+ props = Properties(funcName)
+
+ # Exceptions. The first set of these functions *do* have
+ # server-side state-changing effects, but will be missed
+ # by the general query, because they either render (e.g.
+ # Bitmap) or do not compile into display lists (e.g. all the others).
+ #
+ # The second set do *not* have server-side state-changing
+ # effects, despite the fact that they do not render
+ # and can be compiled. They are control functions
+ # that are not trackable via state.
+ if funcName in ['Bitmap', 'DeleteTextures', 'FeedbackBuffer',
+ 'RenderMode', 'BindBufferARB', 'DeleteFencesNV']:
+ return 1
+ elif funcName in ['ExecuteProgramNV']:
+ return 0
+
+ # All compilable functions that do not render and that do
+ # not set or use client-side state (e.g. DrawArrays, et al.), set
+ # server-side state.
+ if CanCompile(funcName) and "render" not in props and "useclient" not in props and "setclient" not in props:
+ return 1
+
+ # All others don't set server-side state.
+ return 0
+
+def SetsClientState(funcName):
+ """Return 1 if the function sets client-side state, else 0."""
+ props = Properties(funcName)
+ if "setclient" in props:
+ return 1
+ return 0
+
+def SetsTrackedState(funcName):
+ """Return 1 if the function sets state that is tracked by
+ the state tracker, else 0."""
+ # These functions set state, but aren't tracked by the state
+ # tracker for various reasons:
+ # - because the state tracker doesn't manage display lists
+ # (e.g. CallList and CallLists)
+ # - because the client doesn't have information about what
+ # the server supports, so the function has to go to the
+ # server (e.g. CompressedTexImage calls)
+ # - because they require a round-trip to the server (e.g.
+ # the CopyTexImage calls, SetFenceNV, TrackMatrixNV)
+ if funcName in [
+ 'CopyTexImage1D', 'CopyTexImage2D',
+ 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'CopyTexSubImage3D',
+ 'CallList', 'CallLists',
+ 'CompressedTexImage1DARB', 'CompressedTexSubImage1DARB',
+ 'CompressedTexImage2DARB', 'CompressedTexSubImage2DARB',
+ 'CompressedTexImage3DARB', 'CompressedTexSubImage3DARB',
+ 'SetFenceNV'
+ ]:
+ return 0
+
+ # Anything else that affects client-side state is trackable.
+ if SetsClientState(funcName):
+ return 1
+
+ # Anything else that doesn't set state at all is certainly
+ # not trackable.
+ if not SetsState(funcName):
+ return 0
+
+ # Per-vertex state isn't tracked the way other state is
+ # tracked, so it is specifically excluded.
+ if "pervertex" in Properties(funcName):
+ return 0
+
+ # Everything else is fine
+ return 1
+
+def UsesClientState(funcName):
+ """Return 1 if the function uses client-side state, else 0."""
+ props = Properties(funcName)
+ if "pixelstore" in props or "useclient" in props:
+ return 1
+ return 0
+
+def IsQuery(funcName):
+ """Return 1 if the function returns information to the user, else 0."""
+ props = Properties(funcName)
+ if "get" in props:
+ return 1
+ return 0
+
+def FuncGetsState(funcName):
+ """Return 1 if the function gets GL state, else 0."""
+ d = GetFunctionDict()
+ props = Properties(funcName)
+ if "get" in props:
+ return 1
+ else:
+ return 0
+
+def IsPointer(dataType):
+ """Determine if the datatype is a pointer. Return 1 or 0."""
+ if string.find(dataType, "*") == -1:
+ return 0
+ else:
+ return 1
+
+
+def PointerType(pointerType):
+ """Return the type of a pointer.
+ Ex: PointerType('const GLubyte *') = 'GLubyte'
+ """
+ t = string.split(pointerType, ' ')
+ if t[0] == "const":
+ t[0] = t[1]
+ return t[0]
+
+
+
+
+def OpcodeName(funcName):
+ """Return the C token for the opcode for the given function."""
+ return "CR_" + string.upper(funcName) + "_OPCODE"
+
+
+def ExtendedOpcodeName(funcName):
+ """Return the C token for the extended opcode for the given function."""
+ return "CR_" + string.upper(funcName) + "_EXTEND_OPCODE"
+
+
+
+
+#======================================================================
+
+def MakeCallString(params):
+ """Given a list of (name, type, vectorSize) parameters, make a C-style
+ formal parameter string.
+ Ex return: 'index, x, y, z'.
+ """
+ result = ''
+ i = 1
+ n = len(params)
+ for (name, type, vecSize, convertToType, validValues, valueConversion) in params:
+ result += name
+ if i < n:
+ result = result + ', '
+ i += 1
+ #endfor
+ return result
+#enddef
+
+
+def MakeDeclarationString(params):
+ """Given a list of (name, type, vectorSize) parameters, make a C-style
+ parameter declaration string.
+ Ex return: 'GLuint index, GLfloat x, GLfloat y, GLfloat z'.
+ """
+ n = len(params)
+ if n == 0:
+ return 'void'
+ else:
+ result = ''
+ i = 1
+ for (name, type, vecSize, convertToType, validValues, valueConversion) in params:
+ result = result + type + ' ' + name
+ if i < n:
+ result = result + ', '
+ i += 1
+ #endfor
+ return result
+ #endif
+#enddef
+
+
+def MakePrototypeString(params):
+ """Given a list of (name, type, vectorSize) parameters, make a C-style
+ parameter prototype string (types only).
+ Ex return: 'GLuint, GLfloat, GLfloat, GLfloat'.
+ """
+ n = len(params)
+ if n == 0:
+ return 'void'
+ else:
+ result = ''
+ i = 1
+ for (name, type, vecSize, convertToType, validValues, valueConversion) in params:
+ result = result + type
+ # see if we need a comma separator
+ if i < n:
+ result = result + ', '
+ i += 1
+ #endfor
+ return result
+ #endif
+#enddef
+
+
+#======================================================================
+
+__lengths = {
+ 'GLbyte': 1,
+ 'GLubyte': 1,
+ 'GLshort': 2,
+ 'GLushort': 2,
+ 'GLint': 4,
+ 'GLuint': 4,
+ 'GLfloat': 4,
+ 'GLclampf': 4,
+ 'GLdouble': 8,
+ 'GLclampd': 8,
+ 'GLenum': 4,
+ 'GLboolean': 1,
+ 'GLsizei': 4,
+ 'GLbitfield': 4,
+ 'void': 0, # XXX why?
+ 'int': 4,
+ 'GLintptrARB': 4, # XXX or 8 bytes?
+ 'GLsizeiptrARB': 4 # XXX or 8 bytes?
+}
+
+def sizeof(type):
+ """Return size of C datatype, in bytes."""
+ if not type in __lengths.keys():
+ print >>sys.stderr, "%s not in lengths!" % type
+ return __lengths[type]
+
+
+#======================================================================
+align_types = 1
+
+def FixAlignment( pos, alignment ):
+ # if we want double-alignment take word-alignment instead,
+ # yes, this is super-lame, but we know what we are doing
+ if alignment > 4:
+ alignment = 4
+ if align_types and alignment and ( pos % alignment ):
+ pos += alignment - ( pos % alignment )
+ return pos
+
+def WordAlign( pos ):
+ return FixAlignment( pos, 4 )
+
+def PointerSize():
+ return 8 # Leave room for a 64 bit pointer
+
+def PacketLength( params ):
+ len = 0
+ for (name, type, vecSize, convertToType, validValues, valueConversion) in params:
+ if IsPointer(type):
+ size = PointerSize()
+ else:
+ assert string.find(type, "const") == -1
+ size = sizeof(type)
+ len = FixAlignment( len, size ) + size
+ len = WordAlign( len )
+ return len
+
+#======================================================================
+
+__specials = {}
+
+def LoadSpecials( filename ):
+ table = {}
+ try:
+ f = open( filename, "r" )
+ except:
+ __specials[filename] = {}
+ print >>sys.stderr, "%s not present" % filename
+ return {}
+
+ for line in f.readlines():
+ line = string.strip(line)
+ if line == "" or line[0] == '#':
+ continue
+ table[line] = 1
+
+ __specials[filename] = table
+ return table
+
+
+def FindSpecial( filename, glName ):
+ table = {}
+ try:
+ table = __specials[filename]
+ except KeyError:
+ table = LoadSpecials( filename )
+
+ try:
+ if (table[glName] == 1):
+ return 1
+ else:
+ return 0 #should never happen
+ except KeyError:
+ return 0
+
+
+def AllSpecials( table_file ):
+ table = {}
+ filename = table_file + "_special"
+ try:
+ table = __specials[filename]
+ except KeyError:
+ table = LoadSpecials( filename )
+
+ keys = table.keys()
+ keys.sort()
+ return keys
+
+
+def AllSpecials( table_file ):
+ filename = table_file + "_special"
+ table = {}
+ try:
+ table = __specials[filename]
+ except KeyError:
+ table = LoadSpecials(filename)
+
+ ret = table.keys()
+ ret.sort()
+ return ret
+
+
+def NumSpecials( table_file ):
+ filename = table_file + "_special"
+ table = {}
+ try:
+ table = __specials[filename]
+ except KeyError:
+ table = LoadSpecials(filename)
+ return len(table.keys())
+
+def PrintRecord(record):
+ argList = MakeDeclarationString(record.params)
+ if record.category == "Chromium":
+ prefix = "cr"
+ else:
+ prefix = "gl"
+ print '%s %s%s(%s);' % (record.returnType, prefix, record.name, argList )
+ if len(record.props) > 0:
+ print ' /* %s */' % string.join(record.props, ' ')
+
+#ProcessSpecFile("APIspec.txt", PrintRecord)
+
diff --git a/src/mesa/es/main/drawtex.c b/src/mesa/es/main/drawtex.c
new file mode 100644
index 0000000000..1462807f9d
--- /dev/null
+++ b/src/mesa/es/main/drawtex.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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 "drawtex.h"
+#include "main/state.h"
+#include "main/imports.h"
+
+#include "glapi/dispatch.h"
+
+
+#if FEATURE_OES_draw_texture
+
+
+static INLINE void
+draw_texture(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat width, GLfloat height)
+{
+ if (!ctx->Extensions.OES_draw_texture) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawTex(unsupported)");
+ return;
+ }
+ if (width <= 0.0f || height <= 0.0f) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTex(width or height <= 0)");
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ ASSERT(ctx->Driver.DrawTex);
+ ctx->Driver.DrawTex(ctx, x, y, z, width, height);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawTexf(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ draw_texture(ctx, x, y, z, width, height);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawTexfv(const GLfloat *coords)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ draw_texture(ctx, coords[0], coords[1], coords[2], coords[3], coords[4]);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawTexi(GLint x, GLint y, GLint z, GLint width, GLint height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ draw_texture(ctx, (GLfloat) x, (GLfloat) y, (GLfloat) z,
+ (GLfloat) width, (GLfloat) height);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawTexiv(const GLint *coords)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ draw_texture(ctx, (GLfloat) coords[0], (GLfloat) coords[1],
+ (GLfloat) coords[2], (GLfloat) coords[3], (GLfloat) coords[4]);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawTexs(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ draw_texture(ctx, (GLfloat) x, (GLfloat) y, (GLfloat) z,
+ (GLfloat) width, (GLfloat) height);
+}
+
+
+void GLAPIENTRY
+_mesa_DrawTexsv(const GLshort *coords)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ draw_texture(ctx, (GLfloat) coords[0], (GLfloat) coords[1],
+ (GLfloat) coords[2], (GLfloat) coords[3], (GLfloat) coords[4]);
+}
+
+
+/* it is static because GLfixed is not defined publicly */
+static void GLAPIENTRY
+_mesa_DrawTexx(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ draw_texture(ctx,
+ (GLfloat) x / 65536.0f,
+ (GLfloat) y / 65536.0f,
+ (GLfloat) z / 65536.0f,
+ (GLfloat) width / 65536.0f,
+ (GLfloat) height / 65536.0f);
+}
+
+
+static void GLAPIENTRY
+_mesa_DrawTexxv(const GLfixed *coords)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ draw_texture(ctx,
+ (GLfloat) coords[0] / 65536.0f,
+ (GLfloat) coords[1] / 65536.0f,
+ (GLfloat) coords[2] / 65536.0f,
+ (GLfloat) coords[3] / 65536.0f,
+ (GLfloat) coords[4] / 65536.0f);
+}
+
+
+void
+_mesa_init_drawtex_dispatch(struct _glapi_table *disp)
+{
+ SET_DrawTexfOES(disp, _mesa_DrawTexf);
+ SET_DrawTexfvOES(disp, _mesa_DrawTexfv);
+ SET_DrawTexiOES(disp, _mesa_DrawTexi);
+ SET_DrawTexivOES(disp, _mesa_DrawTexiv);
+ SET_DrawTexsOES(disp, _mesa_DrawTexs);
+ SET_DrawTexsvOES(disp, _mesa_DrawTexsv);
+ SET_DrawTexxOES(disp, _mesa_DrawTexx);
+ SET_DrawTexxvOES(disp, _mesa_DrawTexxv);
+}
+
+
+#endif /* FEATURE_OES_draw_texture */
diff --git a/src/mesa/es/main/drawtex.h b/src/mesa/es/main/drawtex.h
new file mode 100644
index 0000000000..04c5bdd123
--- /dev/null
+++ b/src/mesa/es/main/drawtex.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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 DRAWTEX_H
+#define DRAWTEX_H
+
+
+#include "main/mtypes.h"
+
+
+#if FEATURE_OES_draw_texture
+
+#define _MESA_INIT_DRAWTEX_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->DrawTex = impl ## DrawTex; \
+ } while (0)
+
+extern void GLAPIENTRY
+_mesa_DrawTexf(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height);
+
+extern void GLAPIENTRY
+_mesa_DrawTexfv(const GLfloat *coords);
+
+extern void GLAPIENTRY
+_mesa_DrawTexi(GLint x, GLint y, GLint z, GLint width, GLint height);
+
+extern void GLAPIENTRY
+_mesa_DrawTexiv(const GLint *coords);
+
+extern void GLAPIENTRY
+_mesa_DrawTexs(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height);
+
+extern void GLAPIENTRY
+_mesa_DrawTexsv(const GLshort *coords);
+
+#if 0
+extern void GLAPIENTRY
+_mesa_DrawTexx(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height);
+
+extern void GLAPIENTRY
+_mesa_DrawTexxv(const GLfixed *coords);
+#endif
+
+extern void
+_mesa_init_drawtex_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_OES_draw_texture */
+
+#define _MESA_INIT_DRAWTEX_FUNCTIONS(driver, impl) do { } while (0)
+
+static INLINE void
+_mesa_init_drawtex_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_OES_draw_texture */
+
+
+#endif /* DRAWTEX_H */
diff --git a/src/mesa/es/main/eglimage.c b/src/mesa/es/main/eglimage.c
new file mode 100644
index 0000000000..5dd7a0cfaa
--- /dev/null
+++ b/src/mesa/es/main/eglimage.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "main/mtypes.h"
+#include "main/context.h"
+#include "main/teximage.h"
+#include "main/texstate.h"
+#include "main/imports.h"
+#include "glapi/dispatch.h"
+
+#include "eglimage.h"
+
+
+#if FEATURE_OES_EGL_image
+
+
+void GLAPIENTRY
+_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_renderbuffer *rb;
+
+ if (!ctx->Extensions.OES_EGL_image) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glEGLImageTargetRenderbufferStorageOES(unsupported)");
+ return;
+ }
+
+ if (target != GL_RENDERBUFFER) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glEGLImageTargetRenderbufferStorage(target=0x%x)", target);
+ return;
+ }
+
+ rb = ctx->CurrentRenderbuffer;
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glEGLImageTargetRenderbufferStorageOES(no bound rb)");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ ASSERT(ctx->Driver.EGLImageTargetRenderbufferStorage);
+ ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
+ /* invalidate fbo? */
+}
+
+void GLAPIENTRY _mesa_EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+
+ if (!ctx->Extensions.OES_EGL_image) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glEGLImageTargetTexture2DOES(unsupported)");
+ return;
+ }
+
+ if (target != GL_TEXTURE_2D) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glEGLImageTargetTexture2D(target=0x%x)", target);
+ return;
+ }
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+
+ ASSERT(ctx->Driver.EGLImageTargetTexture2D);
+ ctx->Driver.EGLImageTargetTexture2D(ctx, texObj ,image);
+
+ /* invalidate state and fbo?*/
+ /* fbo? */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void
+_mesa_init_eglimage_dispatch(struct _glapi_table *disp)
+{
+ SET_EGLImageTargetRenderbufferStorageOES(disp,
+ _mesa_EGLImageTargetRenderbufferStorageOES);
+ SET_EGLImageTargetTexture2DOES(disp, _mesa_EGLImageTargetTexture2DOES);
+}
+
+
+#endif /* FEATURE_OES_EGL_image */
diff --git a/src/mesa/es/main/eglimage.h b/src/mesa/es/main/eglimage.h
new file mode 100644
index 0000000000..7acb991200
--- /dev/null
+++ b/src/mesa/es/main/eglimage.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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 EGLIMAGE_H
+#define EGLIMAGE_H
+
+
+#include "main/mtypes.h"
+
+
+#if FEATURE_OES_EGL_image
+
+#define _MESA_INIT_EGLIMAGE_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->EGLImageTargetRenderbufferStorage = \
+ impl ## EGLImageTargetRenderbufferStorage; \
+ (driver)->EGLImageTargetTexture2D = impl ## EGLImageTargetTexture2D; \
+ } while (0)
+
+extern void GLAPIENTRY
+_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
+
+extern void GLAPIENTRY
+_mesa_EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
+
+extern void
+_mesa_init_eglimage_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_OES_EGL_image */
+
+#define _MESA_INIT_EGLIMAGE_FUNCTIONS(driver, impl) do { } while (0)
+
+static INLINE void
+_mesa_init_eglimage_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_OES_EGL_image */
+
+
+#endif /* EGLIMAGE_H */
diff --git a/src/mesa/es/main/es1_special b/src/mesa/es/main/es1_special
new file mode 100644
index 0000000000..4cc97c30f3
--- /dev/null
+++ b/src/mesa/es/main/es1_special
@@ -0,0 +1,8 @@
+# GetString is always special.
+GetString
+# CompressedTexImage2D calls out to two different functions based on
+# whether the image is a paletted image or not
+CompressedTexImage2D
+# QueryMatrixx returns values in an unusual, decomposed, fixed-value
+# form; it has its own code for this
+QueryMatrixx
diff --git a/src/mesa/es/main/es2_special b/src/mesa/es/main/es2_special
new file mode 100644
index 0000000000..8de76a3735
--- /dev/null
+++ b/src/mesa/es/main/es2_special
@@ -0,0 +1,5 @@
+# GetString must always have its own implementation, so we return our
+# implementation values instead of Mesa's.
+GetString
+CompressedTexImage2D
+RenderbufferStorage
diff --git a/src/mesa/es/main/es_cpaltex.c b/src/mesa/es/main/es_cpaltex.c
new file mode 100644
index 0000000000..0d6f7410c3
--- /dev/null
+++ b/src/mesa/es/main/es_cpaltex.c
@@ -0,0 +1,240 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+
+/**
+ * Code to convert compressed/paletted texture images to ordinary 4-byte RGBA.
+ * See the GL_OES_compressed_paletted_texture spec at
+ * http://khronos.org/registry/gles/extensions/OES/OES_compressed_paletted_texture.txt
+ */
+
+
+#include <stdlib.h>
+#include <assert.h>
+#include "GLES/gl.h"
+#include "GLES/glext.h"
+
+
+void GL_APIENTRY _es_CompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+
+void GL_APIENTRY _mesa_TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void GL_APIENTRY _mesa_CompressedTexImage2DARB(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+
+
+static const struct {
+ GLenum format;
+ GLuint palette_size;
+ GLuint size;
+} formats[] = {
+ { GL_PALETTE4_RGB8_OES, 16, 3 },
+ { GL_PALETTE4_RGBA8_OES, 16, 4 },
+ { GL_PALETTE4_R5_G6_B5_OES, 16, 2 },
+ { GL_PALETTE4_RGBA4_OES, 16, 2 },
+ { GL_PALETTE4_RGB5_A1_OES, 16, 2 },
+ { GL_PALETTE8_RGB8_OES, 256, 3 },
+ { GL_PALETTE8_RGBA8_OES, 256, 4 },
+ { GL_PALETTE8_R5_G6_B5_OES, 256, 2 },
+ { GL_PALETTE8_RGBA4_OES, 256, 2 },
+ { GL_PALETTE8_RGB5_A1_OES, 256, 2 }
+};
+
+
+/**
+ * Get a color/entry from the palette. Convert to GLubyte/RGBA format.
+ */
+static void
+get_palette_entry(GLenum format, const void *palette, GLuint index,
+ GLubyte rgba[4])
+{
+ switch (format) {
+ case GL_PALETTE4_RGB8_OES:
+ case GL_PALETTE8_RGB8_OES:
+ {
+ const GLubyte *pal = (const GLubyte *) palette;
+ rgba[0] = pal[index * 3 + 0];
+ rgba[1] = pal[index * 3 + 1];
+ rgba[2] = pal[index * 3 + 2];
+ rgba[3] = 255;
+ }
+ break;
+ case GL_PALETTE4_RGBA8_OES:
+ case GL_PALETTE8_RGBA8_OES:
+ {
+ const GLubyte *pal = (const GLubyte *) palette;
+ rgba[0] = pal[index * 4 + 0];
+ rgba[1] = pal[index * 4 + 1];
+ rgba[2] = pal[index * 4 + 2];
+ rgba[3] = pal[index * 4 + 3];
+ }
+ break;
+ case GL_PALETTE4_R5_G6_B5_OES:
+ case GL_PALETTE8_R5_G6_B5_OES:
+ {
+ const GLushort *pal = (const GLushort *) palette;
+ const GLushort color = pal[index];
+ rgba[0] = ((color >> 8) & 0xf8) | ((color >> 11) & 0x3);
+ rgba[1] = ((color >> 3) & 0xfc) | ((color >> 1 ) & 0x3);
+ rgba[2] = ((color << 3) & 0xf8) | ((color ) & 0x7);
+ rgba[3] = 255;
+ }
+ break;
+ case GL_PALETTE4_RGBA4_OES:
+ case GL_PALETTE8_RGBA4_OES:
+ {
+ const GLushort *pal = (const GLushort *) palette;
+ const GLushort color = pal[index];
+ rgba[0] = ((color & 0xf000) >> 8) | ((color & 0xf000) >> 12);
+ rgba[1] = ((color & 0x0f00) >> 4) | ((color & 0x0f00) >> 8);
+ rgba[2] = ((color & 0x00f0) ) | ((color & 0x00f0) >> 4);
+ rgba[3] = ((color & 0x000f) << 4) | ((color & 0x000f) );
+ }
+ break;
+ case GL_PALETTE4_RGB5_A1_OES:
+ case GL_PALETTE8_RGB5_A1_OES:
+ {
+ const GLushort *pal = (const GLushort *) palette;
+ const GLushort color = pal[index];
+ rgba[0] = ((color >> 8) & 0xf8) | ((color >> 11) & 0x7);
+ rgba[1] = ((color >> 3) & 0xf8) | ((color >> 6) & 0x7);
+ rgba[2] = ((color << 2) & 0xf8) | ((color >> 1) & 0x7);
+ rgba[3] = (color & 0x1) * 255;
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Convert paletted texture to simple GLubyte/RGBA format.
+ */
+static void
+paletted_to_rgba(GLenum src_format,
+ const void *palette,
+ const void *indexes,
+ GLsizei width, GLsizei height,
+ GLubyte *rgba)
+{
+ GLuint pal_ents, i;
+
+ assert(src_format >= GL_PALETTE4_RGB8_OES);
+ assert(src_format <= GL_PALETTE8_RGB5_A1_OES);
+ assert(formats[src_format - GL_PALETTE4_RGB8_OES].format == src_format);
+
+ pal_ents = formats[src_format - GL_PALETTE4_RGB8_OES].palette_size;
+
+ if (pal_ents == 16) {
+ /* 4 bits per index */
+ const GLubyte *ind = (const GLubyte *) indexes;
+
+ if (width * height == 1) {
+ /* special case the only odd-sized image */
+ GLuint index0 = ind[0] >> 4;
+ get_palette_entry(src_format, palette, index0, rgba);
+ return;
+ }
+ /* two pixels per iteration */
+ for (i = 0; i < width * height / 2; i++) {
+ GLuint index0 = ind[i] >> 4;
+ GLuint index1 = ind[i] & 0xf;
+ get_palette_entry(src_format, palette, index0, rgba + i * 8);
+ get_palette_entry(src_format, palette, index1, rgba + i * 8 + 4);
+ }
+ }
+ else {
+ /* 8 bits per index */
+ const GLubyte *ind = (const GLubyte *) indexes;
+ for (i = 0; i < width * height; i++) {
+ GLuint index = ind[i];
+ get_palette_entry(src_format, palette, index, rgba + i * 4);
+ }
+ }
+}
+
+
+/**
+ * Convert a call to glCompressedTexImage2D() where internalFormat is a
+ * compressed palette format into a regular GLubyte/RGBA glTexImage2D() call.
+ */
+static void
+cpal_compressed_teximage2d(GLenum target, GLint level,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height,
+ const void *pixels)
+{
+ GLuint pal_ents, pal_ent_size, pal_bytes;
+ const GLint num_levels = level + 1;
+ GLint lvl;
+ const GLubyte *indexes;
+
+ assert(internalFormat >= GL_PALETTE4_RGB8_OES);
+ assert(internalFormat <= GL_PALETTE8_RGB5_A1_OES);
+ assert(formats[internalFormat - GL_PALETTE4_RGB8_OES].format == internalFormat);
+
+ pal_ents = formats[internalFormat - GL_PALETTE4_RGB8_OES].palette_size;
+ pal_ent_size = formats[internalFormat - GL_PALETTE4_RGB8_OES].size;
+ pal_bytes = pal_ents * pal_ent_size;
+
+ /* first image follows the palette */
+ indexes = (const GLubyte *) pixels + pal_bytes;
+
+ /* No worries about glPixelStore state since the only supported parameter is
+ * GL_UNPACK_ALIGNMENT and it doesn't matter when unpacking GLubyte/RGBA.
+ */
+
+ for (lvl = 0; lvl < num_levels; lvl++) {
+ /* Allocate GLubyte/RGBA dest image buffer */
+ GLubyte *rgba = (GLubyte *) malloc(width * height * 4);
+
+ if (pixels)
+ paletted_to_rgba(internalFormat, pixels, indexes, width, height, rgba);
+
+ _mesa_TexImage2D(target, lvl, GL_RGBA, width, height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, rgba);
+
+ free(rgba);
+
+ /* advance index pointer to point to next src mipmap */
+ if (pal_ents == 4)
+ indexes += width * height / 2;
+ else
+ indexes += width * height;
+
+ /* next mipmap level size */
+ if (width > 1)
+ width /= 2;
+ if (height > 1)
+ height /= 2;
+ }
+}
+
+
+void GL_APIENTRY
+_es_CompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const GLvoid *data)
+{
+ switch (internalFormat) {
+ case GL_PALETTE4_RGB8_OES:
+ case GL_PALETTE4_RGBA8_OES:
+ case GL_PALETTE4_R5_G6_B5_OES:
+ case GL_PALETTE4_RGBA4_OES:
+ case GL_PALETTE4_RGB5_A1_OES:
+ case GL_PALETTE8_RGB8_OES:
+ case GL_PALETTE8_RGBA8_OES:
+ case GL_PALETTE8_R5_G6_B5_OES:
+ case GL_PALETTE8_RGBA4_OES:
+ case GL_PALETTE8_RGB5_A1_OES:
+ cpal_compressed_teximage2d(target, level, internalFormat,
+ width, height, data);
+ break;
+ default:
+ _mesa_CompressedTexImage2DARB(target, level, internalFormat,
+ width, height, border, imageSize, data);
+ }
+}
diff --git a/src/mesa/es/main/es_fbo.c b/src/mesa/es/main/es_fbo.c
new file mode 100644
index 0000000000..545c46ca99
--- /dev/null
+++ b/src/mesa/es/main/es_fbo.c
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+
+#include "GLES2/gl2.h"
+#include "GLES2/gl2ext.h"
+
+
+extern void GL_APIENTRY _es_RenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
+
+extern void GL_APIENTRY _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
+
+
+void GL_APIENTRY
+_es_RenderbufferStorage(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ switch (internalFormat) {
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB565:
+ internalFormat = GL_RGBA;
+ break;
+ case GL_STENCIL_INDEX1_OES:
+ case GL_STENCIL_INDEX4_OES:
+ case GL_STENCIL_INDEX8:
+ internalFormat = GL_STENCIL_INDEX;
+ break;
+ default:
+ ; /* no op */
+ }
+ _mesa_RenderbufferStorageEXT(target, internalFormat, width, height);
+}
diff --git a/src/mesa/es/main/es_generator.py b/src/mesa/es/main/es_generator.py
new file mode 100644
index 0000000000..a1381a5925
--- /dev/null
+++ b/src/mesa/es/main/es_generator.py
@@ -0,0 +1,782 @@
+#*************************************************************************
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to 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
+# TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#*************************************************************************
+
+
+import sys, os
+import apiutil
+
+# These dictionary entries are used for automatic conversion.
+# The string will be used as a format string with the conversion
+# variable.
+Converters = {
+ 'GLint': {
+ 'GLfloat': "(GLfloat) (%s)",
+ },
+ 'GLshort': {
+ 'GLfloat': "(GLfloat) (%s)",
+ },
+ 'GLfloat': {
+ 'GLdouble': "(GLdouble) (%s)",
+ 'GLint': "(GLint) (%s)",
+ 'GLshort': "(GLshort) (%s)",
+ 'GLfixed' : "(GLint) (%s * 65536)",
+ },
+ 'GLfixed': {
+ 'GLfloat': "(GLfloat) (%s / 65536.0f)",
+ 'GLdouble': "(GLdouble) (%s / 65536.0)",
+ },
+ 'GLdouble': {
+ 'GLfloat': "(GLfloat) (%s)",
+ 'GLfixed': "(GLfixed) (%s * 65536)",
+ },
+ 'GLclampf': {
+ 'GLclampd': "(GLclampd) (%s)",
+ 'GLclampx': "(GLclampx) (%s * 65536)",
+ },
+ 'GLclampx': {
+ 'GLclampf': "(GLclampf) (%s / 65536.0f)",
+ 'GLclampd': "(GLclampd) (%s / 65536.0)",
+ },
+ 'GLubyte': {
+ 'GLfloat': "(GLfloat) (%s / 255.0f)",
+ },
+}
+
+def GetBaseType(type):
+ typeTokens = type.split(' ')
+ baseType = None
+ typeModifiers = []
+ for t in typeTokens:
+ if t in ['const', '*']:
+ typeModifiers.append(t)
+ else:
+ baseType = t
+ return (baseType, typeModifiers)
+
+def ConvertValue(value, fromType, toType):
+ """Returns a string that represents the given parameter string,
+ type-converted if necessary."""
+
+ if not Converters.has_key(fromType):
+ sys.stderr.write("No base converter for type '%s' found. Ignoring." % fromType)
+ return value
+
+ if not Converters[fromType].has_key(toType):
+ sys.stderr.write("No converter found for type '%s' to type '%s'. Ignoring." % (fromType, toType))
+ return value
+
+ # This part is simple. Return the proper conversion.
+ conversionString = Converters[fromType][toType]
+ return conversionString % value
+
+def GetLoopSizeExpression(funcName, paramName, paramMaxVecSize):
+ # The VariantArrays() list will have all the information (for all
+ # parameters) on how to calculate variant array sizes.
+ variantArrays = apiutil.VariantArrays(funcName)
+ defaultSize = paramMaxVecSize
+ loopSizeExpression = ''
+
+ # There can be many different entries in the variantArrays for the
+ # same parameter. We have to look at all of them and pick out the
+ # ones of interest.
+ for (variantName, variantSize, controllingParam, controllingValues) in variantArrays:
+ if paramName == variantName:
+ # This variant specification applies to us. It may be of
+ # the form "param size default", meaning that the value should
+ # replace the default size, or it may be
+ # "param size controlParam value...", in which case the size should
+ # be used if the controlParam has any one of the given values.
+ if len(controllingValues) == 0:
+ defaultSize = variantSize
+ else:
+ # Create a compound conditional that expresses
+ # all the possible values in the list
+ conditional = ''
+ for value in controllingValues:
+ if len(conditional) > 0:
+ conditional = conditional + " || "
+ conditional = conditional + "%s == %s" % (controllingParam, value)
+
+ # Add the possibly compound conditional and
+ # the associated vector size to the
+ # loop control expression
+ loopSizeExpression = loopSizeExpression + "(%s) ? %s : " % (conditional, variantSize)
+
+ # end if the name matches
+ # end for the list of all variant array declarations
+
+ # Return the expression that returns the actual size of the
+ # array. Note that 'loopSizeExpression' will already have a
+ # trailing ": " if it is nonempty.
+ if len(loopSizeExpression) > 0:
+ return "(%s%s)" % (loopSizeExpression, defaultSize)
+ else:
+ return "%s" % defaultSize
+
+FormatStrings = {
+ 'GLenum' : '0x%x',
+ 'GLfloat' : '%f',
+ 'GLint' : '%d',
+ 'GLbitfield' : '0x%x',
+}
+def GetFormatString(type):
+ if FormatStrings.has_key(type):
+ return FormatStrings[type]
+ else:
+ return None
+
+
+######################################################################
+# Version-specific values to be used in the main script
+# header: which header file to include
+# api: what text specifies an API-level function
+# special: the name of the "specials" file
+VersionSpecificValues = {
+ 'GLES1.1' : {
+ 'description' : 'GLES1.1 functions',
+ 'header' : 'GLES/gl.h',
+ 'extheader' : 'GLES/glext.h',
+ 'special' : 'es1_special',
+ },
+ 'GLES2.0': {
+ 'description' : 'GLES2.0 functions',
+ 'header' : 'GLES2/gl2.h',
+ 'extheader' : 'GLES2/gl2ext.h',
+ 'special' : 'es2_special',
+ }
+}
+
+
+######################################################################
+# Main code for the script begins here.
+
+# Get the name of the program (without the directory part) for use in
+# error messages.
+program = os.path.basename(sys.argv[0])
+
+# We assume that the directory that the Python script is in also
+# houses the "special" files.
+programDir = os.path.dirname(sys.argv[0])
+
+# Set default values
+verbose = 0
+functionList = "APIspec.txt"
+version = "GLES1.1"
+
+# Allow for command-line switches
+import getopt, time
+options = "hvV:S:"
+try:
+ optlist, args = getopt.getopt(sys.argv[1:], options)
+except getopt.GetoptError, message:
+ sys.stderr.write("%s: %s. Use -h for help.\n" % (program, message))
+ sys.exit(1)
+
+for option, optarg in optlist:
+ if option == "-h":
+ sys.stderr.write("Usage: %s [-%s]\n" % (program, options))
+ sys.stderr.write("Parse an API specification file and generate wrapper functions for a given GLES version\n")
+ sys.stderr.write("-h gives help\n")
+ sys.stderr.write("-v is verbose\n")
+ sys.stderr.write("-V specifies GLES version to generate [%s]:\n" % version)
+ for key in VersionSpecificValues.keys():
+ sys.stderr.write(" %s - %s\n" % (key, VersionSpecificValues[key]['description']))
+ sys.stderr.write("-S specifies API specification file to use [%s]\n" % functionList)
+ sys.exit(1)
+ elif option == "-v":
+ verbose += 1
+ elif option == "-V":
+ version = optarg
+ elif option == "-S":
+ functionList = optarg
+
+# Beyond switches, we support no further command-line arguments
+if len(args) > 0:
+ sys.stderr.write("%s: only switch arguments are supported - use -h for help\n" % program)
+ sys.exit(1)
+
+# If we don't have a valid version, abort.
+if not VersionSpecificValues.has_key(version):
+ sys.stderr.write("%s: version '%s' is not valid - use -h for help\n" % (program, version))
+ sys.exit(1)
+
+# Grab the version-specific items we need to use
+versionHeader = VersionSpecificValues[version]['header']
+versionExtHeader = VersionSpecificValues[version]['extheader']
+versionSpecial = VersionSpecificValues[version]['special']
+
+# We're probably being invoked from a different directory,
+# so look for the "special" file in the same directory that
+# holds the Python script
+specialFile = os.path.join(programDir, versionSpecial)
+if not os.path.isfile(specialFile):
+ sys.stderr.write("%s: can't find special file '%s' for version '%s' - aborting" % (program, specialFile, version))
+ sys.exit(1)
+
+allSpecials = apiutil.AllSpecials(specialFile.split("_")[0])
+
+# If we get to here, we're good to go. The "version" parameter
+# directs GetDispatchedFunctions to only allow functions from
+# that "category" (version in our parlance). This allows
+# functions with different declarations in different categories
+# to exist (glTexImage2D, for example, is different between
+# GLES1 and GLES2).
+keys = apiutil.GetAllFunctions(functionList, version)
+
+print """/* DO NOT EDIT *************************************************
+ * THIS FILE AUTOMATICALLY GENERATED BY THE %s SCRIPT
+ * API specification file: %s
+ * GLES version: %s
+ * date: %s
+ */
+""" % (program, functionList, version, time.strftime("%Y-%m-%d %H:%M:%S"))
+
+# The headers we choose are version-specific.
+print """
+#include "%s"
+#include "%s"
+""" % (versionHeader, versionExtHeader)
+
+# Everyone needs these types.
+print """
+/* These types are needed for the Mesa veneer, but are not defined in
+ * the standard GLES headers.
+ */
+typedef double GLdouble;
+typedef double GLclampd;
+
+/* This type is normally in glext.h, but needed here */
+typedef char GLchar;
+
+/* Mesa error handling requires these */
+extern void *_mesa_get_current_context(void);
+extern void _mesa_error(void *ctx, GLenum error, const char *fmtString, ... );
+
+#include "main/compiler.h"
+#include "main/api_exec.h"
+
+#define HAVE_GLES_TYPES
+#include "glapi/dispatch.h"
+
+typedef void (*_glapi_proc)(void); /* generic function pointer */
+"""
+
+# All variant-length arrays in the GLES API are controlled by some
+# selector parameter. Almost all of those are constant length based
+# on the selector parameter (e.g., in glFogfv(), if the "pname"
+# parameter is GL_FOG_COLOR, the "params" array is considered to be
+# 4 floats long; for any other value of "pname", the "params' array
+# is considered to be 1 float long.
+#
+# There are a very few instances where the selector parameter chooses
+# a runtime-determined value:
+# glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS)
+# glGetIntegerv(GL_SHADER_BINARY_FORMATS)
+# plus the glGetBooleanv, glGetFloatv, glGetFixedv counterparts.
+#
+# The number of formats in both cases is not a constant, but is a
+# runtime-determined value (based on the return value of
+# glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS) or
+# glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS).
+#
+# Rather than hard-code some value (and risk memory errors when we
+# overshoot arrays), in these cases we'll use a constant expresssion
+# (e.g. _get_size(GL_NUM_COMPRESSED_TEXTURE_FORMATS)) to get the
+# value of the variant array. Note, though, that in these cases the
+# "vector" parameter should be set to some size large enough to hold
+# all values (and must be set for GLfixed-based conversions, which
+# need it to define an auxiliary array size).
+#
+# Here's the function itself. Although we only need a couple of values,
+# we'll make it general.
+print """
+extern void GLAPIENTRY _mesa_GetIntegerv(GLenum, GLint *);
+static INLINE unsigned int _get_size(GLenum pname)
+{
+ /* In case of error, make sure the value returned is 0. */
+ GLint value = 0;
+ _mesa_GetIntegerv(pname, &value);
+ return (unsigned int) value;
+}
+"""
+
+# Finally we get to the all-important functions
+print """/*************************************************************
+ * Generated functions begin here
+ */
+"""
+for funcName in keys:
+ if verbose > 0: sys.stderr.write("%s: processing function %s\n" % (program, funcName))
+
+ # start figuring out what this function will look like.
+ returnType = apiutil.ReturnType(funcName)
+ props = apiutil.Properties(funcName)
+ params = apiutil.Parameters(funcName)
+ declarationString = apiutil.MakeDeclarationString(params)
+
+ # In case of error, a function may have to return. Make
+ # sure we have valid return values in this case.
+ if returnType == "void":
+ errorReturn = "return"
+ elif returnType == "GLboolean":
+ errorReturn = "return GL_FALSE"
+ else:
+ errorReturn = "return (%s) 0" % returnType
+
+ # These are the output of this large calculation block.
+ # passthroughDeclarationString: a typed set of parameters that
+ # will be used to create the "extern" reference for the
+ # underlying Mesa or support function. Note that as generated
+ # these have an extra ", " at the beginning, which will be
+ # removed before use.
+ #
+ # passthroughDeclarationString: an untyped list of parameters
+ # that will be used to call the underlying Mesa or support
+ # function (including references to converted parameters).
+ # This will also be generated with an extra ", " at the
+ # beginning, which will be removed before use.
+ #
+ # variables: C code to create any local variables determined to
+ # be necessary.
+ # conversionCodeOutgoing: C code to convert application parameters
+ # to a necessary type before calling the underlying support code.
+ # May be empty if no conversion is required.
+ # conversionCodeIncoming: C code to do the converse: convert
+ # values returned by underlying Mesa code to the types needed
+ # by the application.
+ # Note that *either* the conversionCodeIncoming will be used (for
+ # generated query functions), *or* the conversionCodeOutgoing will
+ # be used (for generated non-query functions), never both.
+ passthroughFuncName = ""
+ passthroughDeclarationString = ""
+ passthroughCallString = ""
+ variables = []
+ conversionCodeOutgoing = []
+ conversionCodeIncoming = []
+ switchCode = []
+
+ # Calculate the name of the underlying support function to call.
+ # By default, the passthrough function is named _mesa_<funcName>.
+ # We're allowed to override the prefix and/or the function name
+ # for each function record, though. The "ConversionFunction"
+ # utility is poorly named, BTW...
+ aliasprefix = apiutil.AliasPrefix(funcName)
+ alias = apiutil.ConversionFunction(funcName)
+ if not alias:
+ # There may still be a Mesa alias for the function
+ if apiutil.Alias(funcName):
+ passthroughFuncName = "%s%s" % (aliasprefix, apiutil.Alias(funcName))
+ else:
+ passthroughFuncName = "%s%s" % (aliasprefix, funcName)
+ else: # a specific alias is provided
+ passthroughFuncName = "%s%s" % (aliasprefix, alias)
+
+ # Look at every parameter: each one may have only specific
+ # allowed values, or dependent parameters to check, or
+ # variant-sized vector arrays to calculate
+ for (paramName, paramType, paramMaxVecSize, paramConvertToType, paramValidValues, paramValueConversion) in params:
+ # We'll need this below if we're doing conversions
+ (paramBaseType, paramTypeModifiers) = GetBaseType(paramType)
+
+ # Conversion management.
+ # We'll handle three cases, easiest to hardest: a parameter
+ # that doesn't require conversion, a scalar parameter that
+ # requires conversion, and a vector parameter that requires
+ # conversion.
+ if paramConvertToType == None:
+ # Unconverted parameters are easy, whether they're vector
+ # or scalar - just add them to the call list. No conversions
+ # or anything to worry about.
+ passthroughDeclarationString += ", %s %s" % (paramType, paramName)
+ passthroughCallString += ", %s" % paramName
+
+ elif paramMaxVecSize == 0: # a scalar parameter that needs conversion
+ # A scalar to hold a converted parameter
+ variables.append(" %s converted_%s;" % (paramConvertToType, paramName))
+
+ # Outgoing conversion depends on whether we have to conditionally
+ # perform value conversion.
+ if paramValueConversion == "none":
+ conversionCodeOutgoing.append(" converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
+ elif paramValueConversion == "some":
+ # We'll need a conditional variable to keep track of
+ # whether we're converting values or not.
+ if (" int convert_%s_value = 1;" % paramName) not in variables:
+ variables.append(" int convert_%s_value = 1;" % paramName)
+
+ # Write code based on that conditional.
+ conversionCodeOutgoing.append(" if (convert_%s_value) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
+ conversionCodeOutgoing.append(" } else {")
+ conversionCodeOutgoing.append(" converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
+ conversionCodeOutgoing.append(" }")
+ else: # paramValueConversion == "all"
+ conversionCodeOutgoing.append(" converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
+
+ # Note that there can be no incoming conversion for a
+ # scalar parameter; changing the scalar will only change
+ # the local value, and won't ultimately change anything
+ # that passes back to the application.
+
+ # Call strings. The unusual " ".join() call will join the
+ # array of parameter modifiers with spaces as separators.
+ passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
+ passthroughCallString += ", converted_%s" % paramName
+
+ else: # a vector parameter that needs conversion
+ # We'll need an index variable for conversions
+ if " register unsigned int i;" not in variables:
+ variables.append(" register unsigned int i;")
+
+ # This variable will hold the (possibly variant) size of
+ # this array needing conversion. By default, we'll set
+ # it to the maximal size (which is correct for functions
+ # with a constant-sized vector parameter); for true
+ # variant arrays, we'll modify it with other code.
+ variables.append(" unsigned int n_%s = %d;" % (paramName, paramMaxVecSize))
+
+ # This array will hold the actual converted values.
+ variables.append(" %s converted_%s[%d];" % (paramConvertToType, paramName, paramMaxVecSize))
+
+ # Again, we choose the conversion code based on whether we
+ # have to always convert values, never convert values, or
+ # conditionally convert values.
+ if paramValueConversion == "none":
+ conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
+ conversionCodeOutgoing.append(" }")
+ elif paramValueConversion == "some":
+ # We'll need a conditional variable to keep track of
+ # whether we're converting values or not.
+ if (" int convert_%s_value = 1;" % paramName) not in variables:
+ variables.append(" int convert_%s_value = 1;" % paramName)
+ # Write code based on that conditional.
+ conversionCodeOutgoing.append(" if (convert_%s_value) {" % paramName)
+ conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
+ conversionCodeOutgoing.append(" }")
+ conversionCodeOutgoing.append(" } else {")
+ conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
+ conversionCodeOutgoing.append(" }")
+ conversionCodeOutgoing.append(" }")
+ else: # paramValueConversion == "all"
+ conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
+
+ conversionCodeOutgoing.append(" }")
+
+ # If instead we need an incoming conversion (i.e. results
+ # from Mesa have to be converted before handing back
+ # to the application), this is it. Fortunately, we don't
+ # have to worry about conditional value conversion - the
+ # functions that do (e.g. glGetFixedv()) are handled
+ # specially, outside this code generation.
+ #
+ # Whether we use incoming conversion or outgoing conversion
+ # is determined later - we only ever use one or the other.
+
+ if paramValueConversion == "none":
+ conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeIncoming.append(" %s[i] = (%s) converted_%s[i];" % (paramName, paramConvertToType, paramName))
+ conversionCodeIncoming.append(" }")
+ elif paramValueConversion == "some":
+ # We'll need a conditional variable to keep track of
+ # whether we're converting values or not.
+ if (" int convert_%s_value = 1;" % paramName) not in variables:
+ variables.append(" int convert_%s_value = 1;" % paramName)
+
+ # Write code based on that conditional.
+ conversionCodeIncoming.append(" if (convert_%s_value) {" % paramName)
+ conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeIncoming.append(" %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
+ conversionCodeIncoming.append(" }")
+ conversionCodeIncoming.append(" } else {")
+ conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeIncoming.append(" %s[i] = (%s) converted_%s[i];" % (paramName, paramConvertToType, paramName))
+ conversionCodeIncoming.append(" }")
+ conversionCodeIncoming.append(" }")
+ else: # paramValueConversion == "all"
+ conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeIncoming.append(" %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
+ conversionCodeIncoming.append(" }")
+
+ # Call strings. The unusual " ".join() call will join the
+ # array of parameter modifiers with spaces as separators.
+ passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
+ passthroughCallString += ", converted_%s" % paramName
+
+ # endif conversion management
+
+ # Parameter checking. If the parameter has a specific list of
+ # valid values, we have to make sure that the passed-in values
+ # match these, or we make an error.
+ if len(paramValidValues) > 0:
+ # We're about to make a big switch statement with an
+ # error at the end. By default, the error is GL_INVALID_ENUM,
+ # unless we find a "case" statement in the middle with a
+ # non-GLenum value.
+ errorDefaultCase = "GL_INVALID_ENUM"
+
+ # This parameter has specific valid values. Make a big
+ # switch statement to handle it. Note that the original
+ # parameters are always what is checked, not the
+ # converted parameters.
+ switchCode.append(" switch(%s) {" % paramName)
+
+ for valueIndex in range(len(paramValidValues)):
+ (paramValue, dependentVecSize, dependentParamName, dependentValidValues, errorCode, valueConvert) = paramValidValues[valueIndex]
+
+ # We're going to need information on the dependent param
+ # as well.
+ if dependentParamName:
+ depParamIndex = apiutil.FindParamIndex(params, dependentParamName)
+ if depParamIndex == None:
+ sys.stderr.write("%s: can't find dependent param '%s' for function '%s'\n" % (program, dependentParamName, funcName))
+
+ (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = params[depParamIndex]
+ else:
+ (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = (None, None, None, None, [], None)
+
+ # This is a sneaky trick. It's valid syntax for a parameter
+ # that is *not* going to be converted to be declared
+ # with a dependent vector size; but in this case, the
+ # dependent vector size is unused and unnecessary.
+ # So check for this and ignore the dependent vector size
+ # if the parameter is not going to be converted.
+ if depParamConvertToType:
+ usedDependentVecSize = dependentVecSize
+ else:
+ usedDependentVecSize = None
+
+ # We'll peek ahead at the next parameter, to see whether
+ # we can combine cases
+ if valueIndex + 1 < len(paramValidValues) :
+ (nextParamValue, nextDependentVecSize, nextDependentParamName, nextDependentValidValues, nextErrorCode, nextValueConvert) = paramValidValues[valueIndex + 1]
+ if depParamConvertToType:
+ usedNextDependentVecSize = nextDependentVecSize
+ else:
+ usedNextDependentVecSize = None
+
+ # Create a case for this value. As a mnemonic,
+ # if we have a dependent vector size that we're ignoring,
+ # add it as a comment.
+ if usedDependentVecSize == None and dependentVecSize != None:
+ switchCode.append(" case %s: /* size %s */" % (paramValue, dependentVecSize))
+ else:
+ switchCode.append(" case %s:" % paramValue)
+
+ # If this is not a GLenum case, then switch our error
+ # if no value is matched to be GL_INVALID_VALUE instead
+ # of GL_INVALID_ENUM. (Yes, this does get confused
+ # if there are both values and GLenums in the same
+ # switch statement, which shouldn't happen.)
+ if paramValue[0:3] != "GL_":
+ errorDefaultCase = "GL_INVALID_VALUE"
+
+ # If all the remaining parameters are identical to the
+ # next set, then we're done - we'll just create the
+ # official code on the next pass through, and the two
+ # cases will share the code.
+ if valueIndex + 1 < len(paramValidValues) and usedDependentVecSize == usedNextDependentVecSize and dependentParamName == nextDependentParamName and dependentValidValues == nextDependentValidValues and errorCode == nextErrorCode and valueConvert == nextValueConvert:
+ continue
+
+ # Otherwise, we'll have to generate code for this case.
+ # Start off with a check: if there is a dependent parameter,
+ # and a list of valid values for that parameter, we need
+ # to generate an error if something other than one
+ # of those values is passed.
+ if len(dependentValidValues) > 0:
+ conditional=""
+
+ # If the parameter being checked is actually an array,
+ # check only its first element.
+ if depParamMaxVecSize == 0:
+ valueToCheck = dependentParamName
+ else:
+ valueToCheck = "%s[0]" % dependentParamName
+
+ for v in dependentValidValues:
+ conditional += " && %s != %s" % (valueToCheck, v)
+ switchCode.append(" if (%s) {" % conditional[4:])
+ if errorCode == None:
+ errorCode = "GL_INVALID_ENUM"
+ switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=0x%s)", %s);' % (errorCode, funcName, paramName, "%x", paramName))
+ switchCode.append(" %s;" % errorReturn)
+ switchCode.append(" }")
+ # endif there are dependent valid values
+
+ # The dependent parameter may require conditional
+ # value conversion. If it does, and we don't want
+ # to convert values, we'll have to generate code for that
+ if depParamValueConversion == "some" and valueConvert == "noconvert":
+ switchCode.append(" convert_%s_value = 0;" % dependentParamName)
+
+ # If there's a dependent vector size for this parameter
+ # that we're actually going to use (i.e. we need conversion),
+ # mark it.
+ if usedDependentVecSize:
+ switchCode.append(" n_%s = %s;" % (dependentParamName, dependentVecSize))
+
+ # In all cases, break out of the switch if any valid
+ # value is found.
+ switchCode.append(" break;")
+
+
+ # Need a default case to catch all the other, invalid
+ # parameter values. These will all generate errors.
+ switchCode.append(" default:")
+ if errorCode == None:
+ errorCode = "GL_INVALID_ENUM"
+ formatString = GetFormatString(paramType)
+ if formatString == None:
+ switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s)");' % (errorCode, funcName, paramName))
+ else:
+ switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=%s)", %s);' % (errorCode, funcName, paramName, formatString, paramName))
+ switchCode.append(" %s;" % errorReturn)
+
+ # End of our switch code.
+ switchCode.append(" }")
+
+ # endfor every recognized parameter value
+
+ # endfor every param
+
+ # Here, the passthroughDeclarationString and passthroughCallString
+ # are complete; remove the extra ", " at the front of each.
+ passthroughDeclarationString = passthroughDeclarationString[2:]
+ passthroughCallString = passthroughCallString[2:]
+
+ # The Mesa functions are scattered across all the Mesa
+ # header files. The easiest way to manage declarations
+ # is to create them ourselves.
+ if funcName not in allSpecials:
+ print "extern %s GLAPIENTRY %s(%s);" % (returnType, passthroughFuncName, passthroughDeclarationString)
+
+ # A function may be a core function (i.e. it exists in
+ # the core specification), a core addition (extension
+ # functions added officially to the core), a required
+ # extension (usually an extension for an earlier version
+ # that has been officially adopted), or an optional extension.
+ #
+ # Core functions have a simple category (e.g. "GLES1.1");
+ # we generate only a simple callback for them.
+ #
+ # Core additions have two category listings, one simple
+ # and one compound (e.g. ["GLES1.1", "GLES1.1:OES_fixed_point"]).
+ # We generate the core function, and also an extension function.
+ #
+ # Required extensions and implemented optional extensions
+ # have a single compound category "GLES1.1:OES_point_size_array".
+ # For these we generate just the extension function.
+ for categorySpec in apiutil.Categories(funcName):
+ compoundCategory = categorySpec.split(":")
+
+ # This category isn't for us, if the base category doesn't match
+ # our version
+ if compoundCategory[0] != version:
+ continue
+
+ # Otherwise, determine if we're writing code for a core
+ # function (no suffix) or an extension function.
+ if len(compoundCategory) == 1:
+ # This is a core function
+ extensionName = None
+ fullFuncName = "_es_" + funcName
+ else:
+ # This is an extension function. We'll need to append
+ # the extension suffix.
+ extensionName = compoundCategory[1]
+ extensionSuffix = extensionName.split("_")[0]
+ fullFuncName = "_es_" + funcName + extensionSuffix
+
+ # Now the generated function. The text used to mark an API-level
+ # function, oddly, is version-specific.
+ if extensionName:
+ print "/* Extension %s */" % extensionName
+
+ if funcName in allSpecials:
+ print "/* this function is special and is defined elsewhere */"
+ print "extern %s %s(%s);" % (returnType, fullFuncName, declarationString)
+ print
+ continue
+
+ print "static %s %s(%s)" % (returnType, fullFuncName, declarationString)
+ print "{"
+
+ # Start printing our code pieces. Start with any local
+ # variables we need. This unusual syntax joins the
+ # lines in the variables[] array with the "\n" separator.
+ if len(variables) > 0:
+ print "\n".join(variables), "\n";
+
+ # If there's any sort of parameter checking or variable
+ # array sizing, the switch code will contain it.
+ if len(switchCode) > 0:
+ print "\n".join(switchCode), "\n";
+
+ # In the case of an outgoing conversion (i.e. parameters must
+ # be converted before calling the underlying Mesa function),
+ # use the appropriate code.
+ if "get" not in props and len(conversionCodeOutgoing) > 0:
+ print "\n".join(conversionCodeOutgoing), "\n";
+
+ # Call the Mesa function. Note that there are very few functions
+ # that return a value (i.e. returnType is not "void"), and that
+ # none of them require incoming translation; so we're safe
+ # to generate code that directly returns in those cases,
+ # even though it's not completely independent.
+
+ if returnType == "void":
+ print " %s(%s);" % (passthroughFuncName, passthroughCallString)
+ else:
+ print " return %s(%s);" % (passthroughFuncName, passthroughCallString)
+
+ # If the function is one that returns values (i.e. "get" in props),
+ # it might return values of a different type than we need, that
+ # require conversion before passing back to the application.
+ if "get" in props and len(conversionCodeIncoming) > 0:
+ print "\n".join(conversionCodeIncoming)
+
+ # All done.
+ print "}"
+ print
+ # end for each category provided for a function
+
+# end for each function
+
+print "void"
+print "_mesa_init_exec_table(struct _glapi_table *exec)"
+print "{"
+for func in keys:
+ for spec in apiutil.Categories(func):
+ ext = spec.split(":")
+ # version does not match
+ if ext.pop(0) != version:
+ continue
+ entry = func
+ if ext:
+ suffix = ext[0].split("_")[0]
+ entry += suffix
+ print " SET_%s(exec, _es_%s);" % (entry, entry)
+print "}"
diff --git a/src/mesa/es/main/es_query_matrix.c b/src/mesa/es/main/es_query_matrix.c
new file mode 100644
index 0000000000..82b6fe7ab9
--- /dev/null
+++ b/src/mesa/es/main/es_query_matrix.c
@@ -0,0 +1,199 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+
+/**
+ * Code to implement GL_OES_query_matrix. See the spec at:
+ * http://www.khronos.org/registry/gles/extensions/OES/OES_query_matrix.txt
+ */
+
+
+#include <stdlib.h>
+#include <math.h>
+#include "GLES/gl.h"
+#include "GLES/glext.h"
+
+
+/**
+ * This is from the GL_OES_query_matrix extension specification:
+ *
+ * GLbitfield glQueryMatrixxOES( GLfixed mantissa[16],
+ * GLint exponent[16] )
+ * mantissa[16] contains the contents of the current matrix in GLfixed
+ * format. exponent[16] contains the unbiased exponents applied to the
+ * matrix components, so that the internal representation of component i
+ * is close to mantissa[i] * 2^exponent[i]. The function returns a status
+ * word which is zero if all the components are valid. If
+ * status & (1<<i) != 0, the component i is invalid (e.g., NaN, Inf).
+ * The implementations are not required to keep track of overflows. In
+ * that case, the invalid bits are never set.
+ */
+
+#define INT_TO_FIXED(x) ((GLfixed) ((x) << 16))
+#define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0))
+
+#if defined(WIN32) || defined(_WIN32_WCE)
+/* Oddly, the fpclassify() function doesn't exist in such a form
+ * on Windows. This is an implementation using slightly different
+ * lower-level Windows functions.
+ */
+#include <float.h>
+
+enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
+fpclassify(double x)
+{
+ switch(_fpclass(x)) {
+ case _FPCLASS_SNAN: /* signaling NaN */
+ case _FPCLASS_QNAN: /* quiet NaN */
+ return FP_NAN;
+ case _FPCLASS_NINF: /* negative infinity */
+ case _FPCLASS_PINF: /* positive infinity */
+ return FP_INFINITE;
+ case _FPCLASS_NN: /* negative normal */
+ case _FPCLASS_PN: /* positive normal */
+ return FP_NORMAL;
+ case _FPCLASS_ND: /* negative denormalized */
+ case _FPCLASS_PD: /* positive denormalized */
+ return FP_SUBNORMAL;
+ case _FPCLASS_NZ: /* negative zero */
+ case _FPCLASS_PZ: /* positive zero */
+ return FP_ZERO;
+ default:
+ /* Should never get here; but if we do, this will guarantee
+ * that the pattern is not treated like a number.
+ */
+ return FP_NAN;
+ }
+}
+#endif
+
+extern GLbitfield GL_APIENTRY _es_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]);
+
+/* The Mesa functions we'll need */
+extern void GL_APIENTRY _mesa_GetIntegerv(GLenum pname, GLint *params);
+extern void GL_APIENTRY _mesa_GetFloatv(GLenum pname, GLfloat *params);
+
+GLbitfield GL_APIENTRY _es_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16])
+{
+ GLfloat matrix[16];
+ GLint tmp;
+ GLenum currentMode = GL_FALSE;
+ GLenum desiredMatrix = GL_FALSE;
+ /* The bitfield returns 1 for each component that is invalid (i.e.
+ * NaN or Inf). In case of error, everything is invalid.
+ */
+ GLbitfield rv;
+ register unsigned int i;
+ unsigned int bit;
+
+ /* This data structure defines the mapping between the current matrix
+ * mode and the desired matrix identifier.
+ */
+ static struct {
+ GLenum currentMode;
+ GLenum desiredMatrix;
+ } modes[] = {
+ {GL_MODELVIEW, GL_MODELVIEW_MATRIX},
+ {GL_PROJECTION, GL_PROJECTION_MATRIX},
+ {GL_TEXTURE, GL_TEXTURE_MATRIX},
+#if 0
+ /* this doesn't exist in GLES */
+ {GL_COLOR, GL_COLOR_MATRIX},
+#endif
+ };
+
+ /* Call Mesa to get the current matrix in floating-point form. First,
+ * we have to figure out what the current matrix mode is.
+ */
+ _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp);
+ currentMode = (GLenum) tmp;
+
+ /* The mode is either GL_FALSE, if for some reason we failed to query
+ * the mode, or a given mode from the above table. Search for the
+ * returned mode to get the desired matrix; if we don't find it,
+ * we can return immediately, as _mesa_GetInteger() will have
+ * logged the necessary error already.
+ */
+ for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
+ if (modes[i].currentMode == currentMode) {
+ desiredMatrix = modes[i].desiredMatrix;
+ break;
+ }
+ }
+ if (desiredMatrix == GL_FALSE) {
+ /* Early error means all values are invalid. */
+ return 0xffff;
+ }
+
+ /* Now pull the matrix itself. */
+ _mesa_GetFloatv(desiredMatrix, matrix);
+
+ rv = 0;
+ for (i = 0, bit = 1; i < 16; i++, bit<<=1) {
+ float normalizedFraction;
+ int exp;
+
+ switch (fpclassify(matrix[i])) {
+ /* A "subnormal" or denormalized number is too small to be
+ * represented in normal format; but despite that it's a
+ * valid floating point number. FP_ZERO and FP_NORMAL
+ * are both valid as well. We should be fine treating
+ * these three cases as legitimate floating-point numbers.
+ */
+ case FP_SUBNORMAL:
+ case FP_NORMAL:
+ case FP_ZERO:
+ normalizedFraction = (GLfloat)frexp(matrix[i], &exp);
+ mantissa[i] = FLOAT_TO_FIXED(normalizedFraction);
+ exponent[i] = (GLint) exp;
+ break;
+
+ /* If the entry is not-a-number or an infinity, then the
+ * matrix component is invalid. The invalid flag for
+ * the component is already set; might as well set the
+ * other return values to known values. We'll set
+ * distinct values so that a savvy end user could determine
+ * whether the matrix component was a NaN or an infinity,
+ * but this is more useful for debugging than anything else
+ * since the standard doesn't specify any such magic
+ * values to return.
+ */
+ case FP_NAN:
+ mantissa[i] = INT_TO_FIXED(0);
+ exponent[i] = (GLint) 0;
+ rv |= bit;
+ break;
+
+ case FP_INFINITE:
+ /* Return +/- 1 based on whether it's a positive or
+ * negative infinity.
+ */
+ if (matrix[i] > 0) {
+ mantissa[i] = INT_TO_FIXED(1);
+ }
+ else {
+ mantissa[i] = -INT_TO_FIXED(1);
+ }
+ exponent[i] = (GLint) 0;
+ rv |= bit;
+ break;
+
+ /* We should never get here; but here's a catching case
+ * in case fpclassify() is returnings something unexpected.
+ */
+ default:
+ mantissa[i] = INT_TO_FIXED(2);
+ exponent[i] = (GLint) 0;
+ rv |= bit;
+ break;
+ }
+
+ } /* for each component */
+
+ /* All done */
+ return rv;
+}
diff --git a/src/mesa/es/main/get_gen.py b/src/mesa/es/main/get_gen.py
new file mode 100644
index 0000000000..516facc8a3
--- /dev/null
+++ b/src/mesa/es/main/get_gen.py
@@ -0,0 +1,785 @@
+#!/usr/bin/env python
+
+# Mesa 3-D graphics library
+#
+# Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+# This script is used to generate the get.c file:
+# python get_gen.py > get.c
+
+
+import string
+import sys
+
+
+GLint = 1
+GLenum = 2
+GLfloat = 3
+GLdouble = 4
+GLboolean = 5
+GLfloatN = 6 # A normalized value, such as a color or depth range
+
+
+TypeStrings = {
+ GLint : "GLint",
+ GLenum : "GLenum",
+ GLfloat : "GLfloat",
+ GLdouble : "GLdouble",
+ GLboolean : "GLboolean"
+}
+
+
+# Each entry is a tuple of:
+# - the GL state name, such as GL_CURRENT_COLOR
+# - the state datatype, one of GLint, GLfloat, GLboolean or GLenum
+# - list of code fragments to get the state, such as ["ctx->Foo.Bar"]
+# - optional extra code or empty string
+# - optional extensions to check, or None
+#
+
+# Present in ES 1.x and 2.x:
+StateVars_common = [
+ ( "GL_ALPHA_BITS", GLint, ["ctx->DrawBuffer->Visual.alphaBits"],
+ "", None ),
+ ( "GL_BLEND", GLboolean, ["ctx->Color.BlendEnabled"], "", None ),
+ ( "GL_BLEND_SRC", GLenum, ["ctx->Color.BlendSrcRGB"], "", None ),
+ ( "GL_BLUE_BITS", GLint, ["ctx->DrawBuffer->Visual.blueBits"], "", None ),
+ ( "GL_COLOR_CLEAR_VALUE", GLfloatN,
+ [ "ctx->Color.ClearColor[0]",
+ "ctx->Color.ClearColor[1]",
+ "ctx->Color.ClearColor[2]",
+ "ctx->Color.ClearColor[3]" ], "", None ),
+ ( "GL_COLOR_WRITEMASK", GLint,
+ [ "ctx->Color.ColorMask[RCOMP] ? 1 : 0",
+ "ctx->Color.ColorMask[GCOMP] ? 1 : 0",
+ "ctx->Color.ColorMask[BCOMP] ? 1 : 0",
+ "ctx->Color.ColorMask[ACOMP] ? 1 : 0" ], "", None ),
+ ( "GL_CULL_FACE", GLboolean, ["ctx->Polygon.CullFlag"], "", None ),
+ ( "GL_CULL_FACE_MODE", GLenum, ["ctx->Polygon.CullFaceMode"], "", None ),
+ ( "GL_DEPTH_BITS", GLint, ["ctx->DrawBuffer->Visual.depthBits"],
+ "", None ),
+ ( "GL_DEPTH_CLEAR_VALUE", GLfloatN, ["ctx->Depth.Clear"], "", None ),
+ ( "GL_DEPTH_FUNC", GLenum, ["ctx->Depth.Func"], "", None ),
+ ( "GL_DEPTH_RANGE", GLfloatN,
+ [ "ctx->Viewport.Near", "ctx->Viewport.Far" ], "", None ),
+ ( "GL_DEPTH_TEST", GLboolean, ["ctx->Depth.Test"], "", None ),
+ ( "GL_DEPTH_WRITEMASK", GLboolean, ["ctx->Depth.Mask"], "", None ),
+ ( "GL_DITHER", GLboolean, ["ctx->Color.DitherFlag"], "", None ),
+ ( "GL_FRONT_FACE", GLenum, ["ctx->Polygon.FrontFace"], "", None ),
+ ( "GL_GREEN_BITS", GLint, ["ctx->DrawBuffer->Visual.greenBits"],
+ "", None ),
+ ( "GL_LINE_WIDTH", GLfloat, ["ctx->Line.Width"], "", None ),
+ ( "GL_ALIASED_LINE_WIDTH_RANGE", GLfloat,
+ ["ctx->Const.MinLineWidth",
+ "ctx->Const.MaxLineWidth"], "", None ),
+ ( "GL_MAX_ELEMENTS_INDICES", GLint, ["ctx->Const.MaxArrayLockSize"], "", None ),
+ ( "GL_MAX_ELEMENTS_VERTICES", GLint, ["ctx->Const.MaxArrayLockSize"], "", None ),
+
+ ( "GL_MAX_TEXTURE_SIZE", GLint, ["1 << (ctx->Const.MaxTextureLevels - 1)"], "", None ),
+ ( "GL_MAX_VIEWPORT_DIMS", GLint,
+ ["ctx->Const.MaxViewportWidth", "ctx->Const.MaxViewportHeight"],
+ "", None ),
+ ( "GL_PACK_ALIGNMENT", GLint, ["ctx->Pack.Alignment"], "", None ),
+ ( "GL_ALIASED_POINT_SIZE_RANGE", GLfloat,
+ ["ctx->Const.MinPointSize",
+ "ctx->Const.MaxPointSize"], "", None ),
+ ( "GL_POLYGON_OFFSET_FACTOR", GLfloat, ["ctx->Polygon.OffsetFactor "], "", None ),
+ ( "GL_POLYGON_OFFSET_UNITS", GLfloat, ["ctx->Polygon.OffsetUnits "], "", None ),
+ ( "GL_RED_BITS", GLint, ["ctx->DrawBuffer->Visual.redBits"], "", None ),
+ ( "GL_SCISSOR_BOX", GLint,
+ ["ctx->Scissor.X",
+ "ctx->Scissor.Y",
+ "ctx->Scissor.Width",
+ "ctx->Scissor.Height"], "", None ),
+ ( "GL_SCISSOR_TEST", GLboolean, ["ctx->Scissor.Enabled"], "", None ),
+ ( "GL_STENCIL_BITS", GLint, ["ctx->DrawBuffer->Visual.stencilBits"], "", None ),
+ ( "GL_STENCIL_CLEAR_VALUE", GLint, ["ctx->Stencil.Clear"], "", None ),
+ ( "GL_STENCIL_FAIL", GLenum,
+ ["ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]"], "", None ),
+ ( "GL_STENCIL_FUNC", GLenum,
+ ["ctx->Stencil.Function[ctx->Stencil.ActiveFace]"], "", None ),
+ ( "GL_STENCIL_PASS_DEPTH_FAIL", GLenum,
+ ["ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]"], "", None ),
+ ( "GL_STENCIL_PASS_DEPTH_PASS", GLenum,
+ ["ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]"], "", None ),
+ ( "GL_STENCIL_REF", GLint,
+ ["ctx->Stencil.Ref[ctx->Stencil.ActiveFace]"], "", None ),
+ ( "GL_STENCIL_TEST", GLboolean, ["ctx->Stencil.Enabled"], "", None ),
+ ( "GL_STENCIL_VALUE_MASK", GLint,
+ ["ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace]"], "", None ),
+ ( "GL_STENCIL_WRITEMASK", GLint,
+ ["ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace]"], "", None ),
+ ( "GL_SUBPIXEL_BITS", GLint, ["ctx->Const.SubPixelBits"], "", None ),
+ ( "GL_TEXTURE_BINDING_2D", GLint,
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name"], "", None ),
+ ( "GL_UNPACK_ALIGNMENT", GLint, ["ctx->Unpack.Alignment"], "", None ),
+ ( "GL_VIEWPORT", GLint, [ "ctx->Viewport.X", "ctx->Viewport.Y",
+ "ctx->Viewport.Width", "ctx->Viewport.Height" ], "", None ),
+
+ # GL_ARB_multitexture
+ ( "GL_ACTIVE_TEXTURE_ARB", GLint,
+ [ "GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit"], "", ["ARB_multitexture"] ),
+
+ # Note that all the OES_* extensions require that the Mesa
+ # "struct gl_extensions" include a member with the name of
+ # the extension. That structure does not yet include OES
+ # extensions (and we're not sure whether it will). If
+ # it does, all the OES_* extensions below should mark the
+ # dependency.
+
+ # OES_texture_cube_map
+ ( "GL_TEXTURE_BINDING_CUBE_MAP_ARB", GLint,
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name"],
+ "", None),
+ ( "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB", GLint,
+ ["(1 << (ctx->Const.MaxCubeTextureLevels - 1))"],
+ "", None),
+
+ # OES_blend_subtract
+ ( "GL_BLEND_SRC_RGB_EXT", GLenum, ["ctx->Color.BlendSrcRGB"], "", None),
+ ( "GL_BLEND_DST_RGB_EXT", GLenum, ["ctx->Color.BlendDstRGB"], "", None),
+ ( "GL_BLEND_SRC_ALPHA_EXT", GLenum, ["ctx->Color.BlendSrcA"], "", None),
+ ( "GL_BLEND_DST_ALPHA_EXT", GLenum, ["ctx->Color.BlendDstA"], "", None),
+
+ # GL_BLEND_EQUATION_RGB, which is what we're really after,
+ # is defined identically to GL_BLEND_EQUATION.
+ ( "GL_BLEND_EQUATION", GLenum, ["ctx->Color.BlendEquationRGB "], "", None),
+ ( "GL_BLEND_EQUATION_ALPHA_EXT", GLenum, ["ctx->Color.BlendEquationA "],
+ "", None),
+
+ # GL_ARB_texture_compression */
+# ( "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB", GLint,
+# ["_mesa_get_compressed_formats(ctx, NULL, GL_FALSE)"],
+# "", ["ARB_texture_compression"] ),
+# ( "GL_COMPRESSED_TEXTURE_FORMATS_ARB", GLenum,
+# [],
+# """GLint formats[100];
+# GLuint i, n = _mesa_get_compressed_formats(ctx, formats, GL_FALSE);
+# ASSERT(n <= 100);
+# for (i = 0; i < n; i++)
+# params[i] = ENUM_TO_INT(formats[i]);""",
+# ["ARB_texture_compression"] ),
+
+ # GL_ARB_multisample
+ ( "GL_SAMPLE_ALPHA_TO_COVERAGE_ARB", GLboolean,
+ ["ctx->Multisample.SampleAlphaToCoverage"], "", ["ARB_multisample"] ),
+ ( "GL_SAMPLE_COVERAGE_ARB", GLboolean,
+ ["ctx->Multisample.SampleCoverage"], "", ["ARB_multisample"] ),
+ ( "GL_SAMPLE_COVERAGE_VALUE_ARB", GLfloat,
+ ["ctx->Multisample.SampleCoverageValue"], "", ["ARB_multisample"] ),
+ ( "GL_SAMPLE_COVERAGE_INVERT_ARB", GLboolean,
+ ["ctx->Multisample.SampleCoverageInvert"], "", ["ARB_multisample"] ),
+ ( "GL_SAMPLE_BUFFERS_ARB", GLint,
+ ["ctx->DrawBuffer->Visual.sampleBuffers"], "", ["ARB_multisample"] ),
+ ( "GL_SAMPLES_ARB", GLint,
+ ["ctx->DrawBuffer->Visual.samples"], "", ["ARB_multisample"] ),
+
+
+ # GL_SGIS_generate_mipmap
+ ( "GL_GENERATE_MIPMAP_HINT_SGIS", GLenum, ["ctx->Hint.GenerateMipmap"],
+ "", ["SGIS_generate_mipmap"] ),
+
+ # GL_ARB_vertex_buffer_object
+ ( "GL_ARRAY_BUFFER_BINDING_ARB", GLint,
+ ["ctx->Array.ArrayBufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ # GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB - not supported
+ ( "GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB", GLint,
+ ["ctx->Array.ElementArrayBufferObj->Name"],
+ "", ["ARB_vertex_buffer_object"] ),
+
+ # GL_OES_read_format
+ ( "GL_IMPLEMENTATION_COLOR_READ_TYPE_OES", GLint,
+ ["ctx->Const.ColorReadType"], "", None),
+ ( "GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES", GLint,
+ ["ctx->Const.ColorReadFormat"], "", None),
+
+ # GL_OES_framebuffer_object
+ ( "GL_FRAMEBUFFER_BINDING_EXT", GLint, ["ctx->DrawBuffer->Name"], "",
+ None),
+ ( "GL_RENDERBUFFER_BINDING_EXT", GLint,
+ ["ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0"], "",
+ None),
+ ( "GL_MAX_RENDERBUFFER_SIZE_EXT", GLint,
+ ["ctx->Const.MaxRenderbufferSize"], "",
+ None),
+
+ # OpenGL ES 1/2 special:
+ ( "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB", GLint,
+ [ "ARRAY_SIZE(compressed_formats)" ],
+ "",
+ None ),
+
+ ("GL_COMPRESSED_TEXTURE_FORMATS_ARB", GLint,
+ [],
+ """
+ int i;
+ for (i = 0; i < ARRAY_SIZE(compressed_formats); i++) {
+ params[i] = compressed_formats[i];
+ }""",
+ None ),
+
+ ( "GL_POLYGON_OFFSET_FILL", GLboolean, ["ctx->Polygon.OffsetFill"], "", None ),
+
+]
+
+# Only present in ES 1.x:
+StateVars_es1 = [
+ ( "GL_MAX_LIGHTS", GLint, ["ctx->Const.MaxLights"], "", None ),
+ ( "GL_LIGHT0", GLboolean, ["ctx->Light.Light[0].Enabled"], "", None ),
+ ( "GL_LIGHT1", GLboolean, ["ctx->Light.Light[1].Enabled"], "", None ),
+ ( "GL_LIGHT2", GLboolean, ["ctx->Light.Light[2].Enabled"], "", None ),
+ ( "GL_LIGHT3", GLboolean, ["ctx->Light.Light[3].Enabled"], "", None ),
+ ( "GL_LIGHT4", GLboolean, ["ctx->Light.Light[4].Enabled"], "", None ),
+ ( "GL_LIGHT5", GLboolean, ["ctx->Light.Light[5].Enabled"], "", None ),
+ ( "GL_LIGHT6", GLboolean, ["ctx->Light.Light[6].Enabled"], "", None ),
+ ( "GL_LIGHT7", GLboolean, ["ctx->Light.Light[7].Enabled"], "", None ),
+ ( "GL_LIGHTING", GLboolean, ["ctx->Light.Enabled"], "", None ),
+ ( "GL_LIGHT_MODEL_AMBIENT", GLfloatN,
+ ["ctx->Light.Model.Ambient[0]",
+ "ctx->Light.Model.Ambient[1]",
+ "ctx->Light.Model.Ambient[2]",
+ "ctx->Light.Model.Ambient[3]"], "", None ),
+ ( "GL_LIGHT_MODEL_TWO_SIDE", GLboolean, ["ctx->Light.Model.TwoSide"], "", None ),
+ ( "GL_ALPHA_TEST", GLboolean, ["ctx->Color.AlphaEnabled"], "", None ),
+ ( "GL_ALPHA_TEST_FUNC", GLenum, ["ctx->Color.AlphaFunc"], "", None ),
+ ( "GL_ALPHA_TEST_REF", GLfloatN, ["ctx->Color.AlphaRef"], "", None ),
+ ( "GL_BLEND_DST", GLenum, ["ctx->Color.BlendDstRGB"], "", None ),
+ ( "GL_MAX_CLIP_PLANES", GLint, ["ctx->Const.MaxClipPlanes"], "", None ),
+ ( "GL_CLIP_PLANE0", GLboolean,
+ [ "(ctx->Transform.ClipPlanesEnabled >> 0) & 1" ], "", None ),
+ ( "GL_CLIP_PLANE1", GLboolean,
+ [ "(ctx->Transform.ClipPlanesEnabled >> 1) & 1" ], "", None ),
+ ( "GL_CLIP_PLANE2", GLboolean,
+ [ "(ctx->Transform.ClipPlanesEnabled >> 2) & 1" ], "", None ),
+ ( "GL_CLIP_PLANE3", GLboolean,
+ [ "(ctx->Transform.ClipPlanesEnabled >> 3) & 1" ], "", None ),
+ ( "GL_CLIP_PLANE4", GLboolean,
+ [ "(ctx->Transform.ClipPlanesEnabled >> 4) & 1" ], "", None ),
+ ( "GL_CLIP_PLANE5", GLboolean,
+ [ "(ctx->Transform.ClipPlanesEnabled >> 5) & 1" ], "", None ),
+ ( "GL_COLOR_MATERIAL", GLboolean,
+ ["ctx->Light.ColorMaterialEnabled"], "", None ),
+ ( "GL_CURRENT_COLOR", GLfloatN,
+ [ "ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0]",
+ "ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1]",
+ "ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2]",
+ "ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3]" ],
+ "FLUSH_CURRENT(ctx, 0);", None ),
+ ( "GL_CURRENT_NORMAL", GLfloatN,
+ [ "ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0]",
+ "ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1]",
+ "ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2]"],
+ "FLUSH_CURRENT(ctx, 0);", None ),
+ ( "GL_CURRENT_TEXTURE_COORDS", GLfloat,
+ ["ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]",
+ "ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]",
+ "ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]",
+ "ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3]"],
+ "const GLuint texUnit = ctx->Texture.CurrentUnit;", None ),
+ ( "GL_DISTANCE_ATTENUATION_EXT", GLfloat,
+ ["ctx->Point.Params[0]",
+ "ctx->Point.Params[1]",
+ "ctx->Point.Params[2]"], "", None ),
+ ( "GL_FOG", GLboolean, ["ctx->Fog.Enabled"], "", None ),
+ ( "GL_FOG_COLOR", GLfloatN,
+ [ "ctx->Fog.Color[0]",
+ "ctx->Fog.Color[1]",
+ "ctx->Fog.Color[2]",
+ "ctx->Fog.Color[3]" ], "", None ),
+ ( "GL_FOG_DENSITY", GLfloat, ["ctx->Fog.Density"], "", None ),
+ ( "GL_FOG_END", GLfloat, ["ctx->Fog.End"], "", None ),
+ ( "GL_FOG_HINT", GLenum, ["ctx->Hint.Fog"], "", None ),
+ ( "GL_FOG_MODE", GLenum, ["ctx->Fog.Mode"], "", None ),
+ ( "GL_FOG_START", GLfloat, ["ctx->Fog.Start"], "", None ),
+ ( "GL_LINE_SMOOTH", GLboolean, ["ctx->Line.SmoothFlag"], "", None ),
+ ( "GL_LINE_SMOOTH_HINT", GLenum, ["ctx->Hint.LineSmooth"], "", None ),
+ ( "GL_LINE_WIDTH_RANGE", GLfloat,
+ ["ctx->Const.MinLineWidthAA",
+ "ctx->Const.MaxLineWidthAA"], "", None ),
+ ( "GL_COLOR_LOGIC_OP", GLboolean, ["ctx->Color.ColorLogicOpEnabled"], "", None ),
+ ( "GL_LOGIC_OP_MODE", GLenum, ["ctx->Color.LogicOp"], "", None ),
+ ( "GL_MATRIX_MODE", GLenum, ["ctx->Transform.MatrixMode"], "", None ),
+
+ ( "GL_MAX_MODELVIEW_STACK_DEPTH", GLint, ["MAX_MODELVIEW_STACK_DEPTH"], "", None ),
+ ( "GL_MAX_PROJECTION_STACK_DEPTH", GLint, ["MAX_PROJECTION_STACK_DEPTH"], "", None ),
+ ( "GL_MAX_TEXTURE_STACK_DEPTH", GLint, ["MAX_TEXTURE_STACK_DEPTH"], "", None ),
+ ( "GL_MODELVIEW_MATRIX", GLfloat,
+ [ "matrix[0]", "matrix[1]", "matrix[2]", "matrix[3]",
+ "matrix[4]", "matrix[5]", "matrix[6]", "matrix[7]",
+ "matrix[8]", "matrix[9]", "matrix[10]", "matrix[11]",
+ "matrix[12]", "matrix[13]", "matrix[14]", "matrix[15]" ],
+ "const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;", None ),
+ ( "GL_MODELVIEW_STACK_DEPTH", GLint, ["ctx->ModelviewMatrixStack.Depth + 1"], "", None ),
+ ( "GL_NORMALIZE", GLboolean, ["ctx->Transform.Normalize"], "", None ),
+ ( "GL_PACK_SKIP_IMAGES_EXT", GLint, ["ctx->Pack.SkipImages"], "", None ),
+ ( "GL_PERSPECTIVE_CORRECTION_HINT", GLenum,
+ ["ctx->Hint.PerspectiveCorrection"], "", None ),
+ ( "GL_POINT_SIZE", GLfloat, ["ctx->Point.Size"], "", None ),
+ ( "GL_POINT_SIZE_RANGE", GLfloat,
+ ["ctx->Const.MinPointSizeAA",
+ "ctx->Const.MaxPointSizeAA"], "", None ),
+ ( "GL_POINT_SMOOTH", GLboolean, ["ctx->Point.SmoothFlag"], "", None ),
+ ( "GL_POINT_SMOOTH_HINT", GLenum, ["ctx->Hint.PointSmooth"], "", None ),
+ ( "GL_POINT_SIZE_MIN_EXT", GLfloat, ["ctx->Point.MinSize"], "", None ),
+ ( "GL_POINT_SIZE_MAX_EXT", GLfloat, ["ctx->Point.MaxSize"], "", None ),
+ ( "GL_POINT_FADE_THRESHOLD_SIZE_EXT", GLfloat,
+ ["ctx->Point.Threshold"], "", None ),
+ ( "GL_PROJECTION_MATRIX", GLfloat,
+ [ "matrix[0]", "matrix[1]", "matrix[2]", "matrix[3]",
+ "matrix[4]", "matrix[5]", "matrix[6]", "matrix[7]",
+ "matrix[8]", "matrix[9]", "matrix[10]", "matrix[11]",
+ "matrix[12]", "matrix[13]", "matrix[14]", "matrix[15]" ],
+ "const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;", None ),
+ ( "GL_PROJECTION_STACK_DEPTH", GLint,
+ ["ctx->ProjectionMatrixStack.Depth + 1"], "", None ),
+ ( "GL_RESCALE_NORMAL", GLboolean,
+ ["ctx->Transform.RescaleNormals"], "", None ),
+ ( "GL_SHADE_MODEL", GLenum, ["ctx->Light.ShadeModel"], "", None ),
+ ( "GL_TEXTURE_2D", GLboolean, ["_mesa_IsEnabled(GL_TEXTURE_2D)"], "", None ),
+ ( "GL_TEXTURE_MATRIX", GLfloat,
+ ["matrix[0]", "matrix[1]", "matrix[2]", "matrix[3]",
+ "matrix[4]", "matrix[5]", "matrix[6]", "matrix[7]",
+ "matrix[8]", "matrix[9]", "matrix[10]", "matrix[11]",
+ "matrix[12]", "matrix[13]", "matrix[14]", "matrix[15]" ],
+ "const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;", None ),
+ ( "GL_TEXTURE_STACK_DEPTH", GLint,
+ ["ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Depth + 1"], "", None ),
+ ( "GL_VERTEX_ARRAY", GLboolean, ["ctx->Array.ArrayObj->Vertex.Enabled"], "", None ),
+ ( "GL_VERTEX_ARRAY_SIZE", GLint, ["ctx->Array.ArrayObj->Vertex.Size"], "", None ),
+ ( "GL_VERTEX_ARRAY_TYPE", GLenum, ["ctx->Array.ArrayObj->Vertex.Type"], "", None ),
+ ( "GL_VERTEX_ARRAY_STRIDE", GLint, ["ctx->Array.ArrayObj->Vertex.Stride"], "", None ),
+ ( "GL_NORMAL_ARRAY", GLenum, ["ctx->Array.ArrayObj->Normal.Enabled"], "", None ),
+ ( "GL_NORMAL_ARRAY_TYPE", GLenum, ["ctx->Array.ArrayObj->Normal.Type"], "", None ),
+ ( "GL_NORMAL_ARRAY_STRIDE", GLint, ["ctx->Array.ArrayObj->Normal.Stride"], "", None ),
+ ( "GL_COLOR_ARRAY", GLboolean, ["ctx->Array.ArrayObj->Color.Enabled"], "", None ),
+ ( "GL_COLOR_ARRAY_SIZE", GLint, ["ctx->Array.ArrayObj->Color.Size"], "", None ),
+ ( "GL_COLOR_ARRAY_TYPE", GLenum, ["ctx->Array.ArrayObj->Color.Type"], "", None ),
+ ( "GL_COLOR_ARRAY_STRIDE", GLint, ["ctx->Array.ArrayObj->Color.Stride"], "", None ),
+ ( "GL_TEXTURE_COORD_ARRAY", GLboolean,
+ ["ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled"], "", None ),
+ ( "GL_TEXTURE_COORD_ARRAY_SIZE", GLint,
+ ["ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Size"], "", None ),
+ ( "GL_TEXTURE_COORD_ARRAY_TYPE", GLenum,
+ ["ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Type"], "", None ),
+ ( "GL_TEXTURE_COORD_ARRAY_STRIDE", GLint,
+ ["ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Stride"], "", None ),
+ # GL_ARB_multitexture
+ ( "GL_MAX_TEXTURE_UNITS_ARB", GLint,
+ ["ctx->Const.MaxTextureUnits"], "", ["ARB_multitexture"] ),
+ ( "GL_CLIENT_ACTIVE_TEXTURE_ARB", GLint,
+ ["GL_TEXTURE0_ARB + ctx->Array.ActiveTexture"], "", ["ARB_multitexture"] ),
+ # OES_texture_cube_map
+ ( "GL_TEXTURE_CUBE_MAP_ARB", GLboolean,
+ ["_mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB)"], "", None),
+ ( "GL_TEXTURE_GEN_S", GLboolean,
+ ["((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0)"], "", None),
+ ( "GL_TEXTURE_GEN_T", GLboolean,
+ ["((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & T_BIT) ? 1 : 0)"], "", None),
+ ( "GL_TEXTURE_GEN_R", GLboolean,
+ ["((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & R_BIT) ? 1 : 0)"], "", None),
+ # ARB_multisample
+ ( "GL_MULTISAMPLE_ARB", GLboolean,
+ ["ctx->Multisample.Enabled"], "", ["ARB_multisample"] ),
+ ( "GL_SAMPLE_ALPHA_TO_ONE_ARB", GLboolean,
+ ["ctx->Multisample.SampleAlphaToOne"], "", ["ARB_multisample"] ),
+
+ ( "GL_VERTEX_ARRAY_BUFFER_BINDING_ARB", GLint,
+ ["ctx->Array.ArrayObj->Vertex.BufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ ( "GL_NORMAL_ARRAY_BUFFER_BINDING_ARB", GLint,
+ ["ctx->Array.ArrayObj->Normal.BufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ ( "GL_COLOR_ARRAY_BUFFER_BINDING_ARB", GLint,
+ ["ctx->Array.ArrayObj->Color.BufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ ( "GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB", GLint,
+ ["ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name"],
+ "", ["ARB_vertex_buffer_object"] ),
+
+ # OES_point_sprite
+ ( "GL_POINT_SPRITE_NV", GLboolean, ["ctx->Point.PointSprite"], # == GL_POINT_SPRITE_ARB
+ "", None),
+
+ # GL_ARB_fragment_shader
+ ( "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB", GLint,
+ ["ctx->Const.FragmentProgram.MaxUniformComponents"], "",
+ ["ARB_fragment_shader"] ),
+
+ # GL_ARB_vertex_shader
+ ( "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB", GLint,
+ ["ctx->Const.VertexProgram.MaxUniformComponents"], "",
+ ["ARB_vertex_shader"] ),
+ ( "GL_MAX_VARYING_FLOATS_ARB", GLint,
+ ["ctx->Const.MaxVarying * 4"], "", ["ARB_vertex_shader"] ),
+
+ # OES_matrix_get
+ ( "GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES", GLint, [],
+ """
+ /* See GL_OES_matrix_get */
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ memcpy(params, matrix, 16 * sizeof(GLint));
+ }""",
+ None),
+
+ ( "GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES", GLint, [],
+ """
+ /* See GL_OES_matrix_get */
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ memcpy(params, matrix, 16 * sizeof(GLint));
+ }""",
+ None),
+
+ ( "GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES", GLint, [],
+ """
+ /* See GL_OES_matrix_get */
+ {
+ const GLfloat *matrix =
+ ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ memcpy(params, matrix, 16 * sizeof(GLint));
+ }""",
+ None),
+
+ # OES_point_size_array
+ ("GL_POINT_SIZE_ARRAY_OES", GLboolean,
+ ["ctx->Array.ArrayObj->PointSize.Enabled"], "", None),
+ ("GL_POINT_SIZE_ARRAY_TYPE_OES", GLenum,
+ ["ctx->Array.ArrayObj->PointSize.Type"], "", None),
+ ("GL_POINT_SIZE_ARRAY_STRIDE_OES", GLint,
+ ["ctx->Array.ArrayObj->PointSize.Stride"], "", None),
+ ("GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES", GLint,
+ ["ctx->Array.ArrayObj->PointSize.BufferObj->Name"], "", None),
+
+ # GL_EXT_texture_filter_anisotropic
+ ( "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT", GLfloat,
+ ["ctx->Const.MaxTextureMaxAnisotropy"], "", ["EXT_texture_filter_anisotropic"]),
+
+]
+
+# Only present in ES 2.x:
+StateVars_es2 = [
+ # XXX These entries are not spec'ed for GLES 2, but are
+ # needed for Mesa's GLSL:
+ ( "GL_MAX_LIGHTS", GLint, ["ctx->Const.MaxLights"], "", None ),
+ ( "GL_MAX_CLIP_PLANES", GLint, ["ctx->Const.MaxClipPlanes"], "", None ),
+ ( "GL_MAX_TEXTURE_COORDS_ARB", GLint, # == GL_MAX_TEXTURE_COORDS_NV
+ ["ctx->Const.MaxTextureCoordUnits"], "",
+ ["ARB_fragment_program", "NV_fragment_program"] ),
+ ( "GL_MAX_DRAW_BUFFERS_ARB", GLint,
+ ["ctx->Const.MaxDrawBuffers"], "", ["ARB_draw_buffers"] ),
+ ( "GL_BLEND_COLOR_EXT", GLfloatN,
+ [ "ctx->Color.BlendColor[0]",
+ "ctx->Color.BlendColor[1]",
+ "ctx->Color.BlendColor[2]",
+ "ctx->Color.BlendColor[3]"], "", None ),
+
+ # This is required for GLES2, but also needed for GLSL:
+ ( "GL_MAX_TEXTURE_IMAGE_UNITS_ARB", GLint, # == GL_MAX_TEXTURE_IMAGE_UNI
+ ["ctx->Const.MaxTextureImageUnits"], "",
+ ["ARB_fragment_program", "NV_fragment_program"] ),
+
+ ( "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB", GLint,
+ ["ctx->Const.MaxVertexTextureImageUnits"], "", ["ARB_vertex_shader"] ),
+ ( "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB", GLint,
+ ["MAX_COMBINED_TEXTURE_IMAGE_UNITS"], "", ["ARB_vertex_shader"] ),
+
+ # GL_ARB_shader_objects
+ # Actually, this token isn't part of GL_ARB_shader_objects, but is
+ # close enough for now.
+ ( "GL_CURRENT_PROGRAM", GLint,
+ ["ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0"],
+ "", ["ARB_shader_objects"] ),
+
+ # OpenGL 2.0
+ ( "GL_STENCIL_BACK_FUNC", GLenum, ["ctx->Stencil.Function[1]"], "", None ),
+ ( "GL_STENCIL_BACK_VALUE_MASK", GLint, ["ctx->Stencil.ValueMask[1]"], "", None ),
+ ( "GL_STENCIL_BACK_WRITEMASK", GLint, ["ctx->Stencil.WriteMask[1]"], "", None ),
+ ( "GL_STENCIL_BACK_REF", GLint, ["ctx->Stencil.Ref[1]"], "", None ),
+ ( "GL_STENCIL_BACK_FAIL", GLenum, ["ctx->Stencil.FailFunc[1]"], "", None ),
+ ( "GL_STENCIL_BACK_PASS_DEPTH_FAIL", GLenum, ["ctx->Stencil.ZFailFunc[1]"], "", None ),
+ ( "GL_STENCIL_BACK_PASS_DEPTH_PASS", GLenum, ["ctx->Stencil.ZPassFunc[1]"], "", None ),
+
+ ( "GL_MAX_VERTEX_ATTRIBS_ARB", GLint,
+ ["ctx->Const.VertexProgram.MaxAttribs"], "", ["ARB_vertex_program"] ),
+
+ # OES_texture_3D
+ ( "GL_TEXTURE_BINDING_3D", GLint,
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name"], "", None),
+ ( "GL_MAX_3D_TEXTURE_SIZE", GLint, ["1 << (ctx->Const.Max3DTextureLevels - 1)"], "", None),
+
+ # OES_standard_derivatives
+ ( "GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB", GLenum,
+ ["ctx->Hint.FragmentShaderDerivative"], "", ["ARB_fragment_shader"] ),
+
+ # Unique to ES 2 (not in full GL)
+ ( "GL_MAX_FRAGMENT_UNIFORM_VECTORS", GLint,
+ ["ctx->Const.FragmentProgram.MaxUniformComponents / 4"], "", None),
+ ( "GL_MAX_VARYING_VECTORS", GLint,
+ ["ctx->Const.MaxVarying"], "", None),
+ ( "GL_MAX_VERTEX_UNIFORM_VECTORS", GLint,
+ ["ctx->Const.VertexProgram.MaxUniformComponents / 4"], "", None),
+ ( "GL_SHADER_COMPILER", GLint, ["1"], "", None),
+ # OES_get_program_binary
+ ( "GL_NUM_SHADER_BINARY_FORMATS", GLint, ["0"], "", None),
+ ( "GL_SHADER_BINARY_FORMATS", GLint, [], "", None),
+]
+
+
+
+def ConversionFunc(fromType, toType):
+ """Return the name of the macro to convert between two data types."""
+ if fromType == toType:
+ return ""
+ elif fromType == GLfloat and toType == GLint:
+ return "IROUND"
+ elif fromType == GLfloatN and toType == GLfloat:
+ return ""
+ elif fromType == GLint and toType == GLfloat: # but not GLfloatN!
+ return "(GLfloat)"
+ else:
+ if fromType == GLfloatN:
+ fromType = GLfloat
+ fromStr = TypeStrings[fromType]
+ fromStr = string.upper(fromStr[2:])
+ toStr = TypeStrings[toType]
+ toStr = string.upper(toStr[2:])
+ return fromStr + "_TO_" + toStr
+
+
+def EmitGetFunction(stateVars, returnType):
+ """Emit the code to implement glGetBooleanv, glGetIntegerv or glGetFloatv."""
+ assert (returnType == GLboolean or
+ returnType == GLint or
+ returnType == GLfloat)
+
+ strType = TypeStrings[returnType]
+ # Capitalize first letter of return type
+ if returnType == GLint:
+ function = "_mesa_GetIntegerv"
+ elif returnType == GLboolean:
+ function = "_mesa_GetBooleanv"
+ elif returnType == GLfloat:
+ function = "_mesa_GetFloatv"
+ else:
+ abort()
+
+ print "void GLAPIENTRY"
+ print "%s( GLenum pname, %s *params )" % (function, strType)
+ print "{"
+ print " GET_CURRENT_CONTEXT(ctx);"
+ print " ASSERT_OUTSIDE_BEGIN_END(ctx);"
+ print ""
+ print " if (!params)"
+ print " return;"
+ print ""
+ print " if (ctx->NewState)"
+ print " _mesa_update_state(ctx);"
+ print ""
+ print " switch (pname) {"
+
+ for (name, varType, state, optionalCode, extensions) in stateVars:
+ print " case " + name + ":"
+ if extensions:
+ if len(extensions) == 1:
+ print (' CHECK_EXT1(%s, "%s");' %
+ (extensions[0], function))
+ elif len(extensions) == 2:
+ print (' CHECK_EXT2(%s, %s, "%s");' %
+ (extensions[0], extensions[1], function))
+ elif len(extensions) == 3:
+ print (' CHECK_EXT3(%s, %s, %s, "%s");' %
+ (extensions[0], extensions[1], extensions[2], function))
+ else:
+ assert len(extensions) == 4
+ print (' CHECK_EXT4(%s, %s, %s, %s, "%s");' %
+ (extensions[0], extensions[1], extensions[2], extensions[3], function))
+ if optionalCode:
+ print " {"
+ print " " + optionalCode
+ conversion = ConversionFunc(varType, returnType)
+ n = len(state)
+ for i in range(n):
+ if conversion:
+ print " params[%d] = %s(%s);" % (i, conversion, state[i])
+ else:
+ print " params[%d] = %s;" % (i, state[i])
+ if optionalCode:
+ print " }"
+ print " break;"
+
+ print " default:"
+ print ' _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(pname=0x%%x)", pname);' % function
+ print " }"
+ print "}"
+ print ""
+ return
+
+
+
+def EmitHeader():
+ """Print the get.c file header."""
+ print """
+/***
+ *** NOTE!!! DO NOT EDIT THIS FILE!!! IT IS GENERATED BY get_gen.py
+ ***/
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/enable.h"
+#include "main/extensions.h"
+#include "main/fbobject.h"
+#include "main/get.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/state.h"
+#include "main/texcompress.h"
+
+
+/* ES1 tokens that should be in gl.h but aren't */
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+
+
+/* ES2 special tokens */
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_PLATFORM_BINARY 0x8D63
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+
+
+#ifndef GL_OES_matrix_get
+#define GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES 0x898D
+#define GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES 0x898E
+#define GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES 0x898F
+#endif
+
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#endif
+
+
+#define FLOAT_TO_BOOLEAN(X) ( (X) ? GL_TRUE : GL_FALSE )
+
+#define INT_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
+
+#define BOOLEAN_TO_INT(B) ( (GLint) (B) )
+#define BOOLEAN_TO_FLOAT(B) ( (B) ? 1.0F : 0.0F )
+
+
+/*
+ * Check if named extension is enabled, if not generate error and return.
+ */
+#define CHECK_EXT1(EXT1, FUNC) \\
+ if (!ctx->Extensions.EXT1) { \\
+ _mesa_error(ctx, GL_INVALID_ENUM, FUNC "(0x%x)", (int) pname); \\
+ return; \\
+ }
+
+/*
+ * Check if either of two extensions is enabled.
+ */
+#define CHECK_EXT2(EXT1, EXT2, FUNC) \\
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \\
+ _mesa_error(ctx, GL_INVALID_ENUM, FUNC "(0x%x)", (int) pname); \\
+ return; \\
+ }
+
+/*
+ * Check if either of three extensions is enabled.
+ */
+#define CHECK_EXT3(EXT1, EXT2, EXT3, FUNC) \\
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2 && \\
+ !ctx->Extensions.EXT3) { \\
+ _mesa_error(ctx, GL_INVALID_ENUM, FUNC "(0x%x)", (int) pname); \\
+ return; \\
+ }
+
+/*
+ * Check if either of four extensions is enabled.
+ */
+#define CHECK_EXT4(EXT1, EXT2, EXT3, EXT4, FUNC) \\
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2 && \\
+ !ctx->Extensions.EXT3 && !ctx->Extensions.EXT4) { \\
+ _mesa_error(ctx, GL_INVALID_ENUM, FUNC "(0x%x)", (int) pname); \\
+ return; \\
+ }
+
+
+
+/**
+ * List of compressed texture formats supported by ES.
+ */
+static GLenum compressed_formats[] = {
+ GL_PALETTE4_RGB8_OES,
+ GL_PALETTE4_RGBA8_OES,
+ GL_PALETTE4_R5_G6_B5_OES,
+ GL_PALETTE4_RGBA4_OES,
+ GL_PALETTE4_RGB5_A1_OES,
+ GL_PALETTE8_RGB8_OES,
+ GL_PALETTE8_RGBA8_OES,
+ GL_PALETTE8_R5_G6_B5_OES,
+ GL_PALETTE8_RGBA4_OES,
+ GL_PALETTE8_RGB5_A1_OES
+};
+
+#define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0]))
+
+"""
+ return
+
+
+def EmitAll(stateVars):
+ EmitHeader()
+ EmitGetFunction(stateVars, GLboolean)
+ EmitGetFunction(stateVars, GLfloat)
+ EmitGetFunction(stateVars, GLint)
+
+
+def main(args):
+ # Determine whether to generate ES1 or ES2 queries
+ if len(args) > 1 and args[1] == "1":
+ API = 1
+ elif len(args) > 1 and args[1] == "2":
+ API = 2
+ else:
+ API = 1
+ #print "len args = %d API = %d" % (len(args), API)
+
+ if API == 1:
+ vars = StateVars_common + StateVars_es1
+ else:
+ vars = StateVars_common + StateVars_es2
+
+ EmitAll(vars)
+
+
+main(sys.argv)
diff --git a/src/mesa/es/main/mfeatures.h b/src/mesa/es/main/mfeatures.h
new file mode 100644
index 0000000000..28f376d2d1
--- /dev/null
+++ b/src/mesa/es/main/mfeatures.h
@@ -0,0 +1,113 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file mfeatures.h
+ *
+ * The #defines in this file enable/disable Mesa features needed
+ * for OpenGL ES 1.1 / 2.0
+ */
+
+
+#ifndef MFEATURES_H
+#define MFEATURES_H
+
+#include "main/compiler.h"
+
+/* this file replaces main/mfeatures.h */
+#ifdef FEATURES_H
+#error "main/mfeatures.h was wrongly included"
+#endif
+#define FEATURES_H
+
+#define ASSERT_NO_FEATURE() ASSERT(0)
+
+/*
+ * Enable/disable features (blocks of code) by setting FEATURE_xyz to 0 or 1.
+ */
+#ifndef _HAVE_FULL_GL
+#define _HAVE_FULL_GL 1
+#endif
+
+#define FEATURE_accum 0
+#define FEATURE_arrayelt 0
+#define FEATURE_attrib_stack 0
+#define FEATURE_colortable 0
+#define FEATURE_convolve 0
+#define FEATURE_dispatch 1
+#define FEATURE_dlist 0
+#define FEATURE_draw_read_buffer 0
+#define FEATURE_drawpix 0
+#define FEATURE_es2_glsl 1
+#define FEATURE_evaluators 0
+#define FEATURE_feedback 0
+#define FEATURE_fixedpt 1
+#define FEATURE_histogram 0
+#define FEATURE_pixeltransfer 0
+#define FEATURE_point_size_array 1
+#define FEATURE_rastpos 0
+#define FEATURE_texgen 1
+#define FEATURE_texture_fxt1 0
+#define FEATURE_texture_s3tc 0
+#define FEATURE_userclip 1
+#define FEATURE_vertex_array_byte 1
+
+#define FEATURE_ARB_occlusion_query 0
+#define FEATURE_ARB_fragment_program _HAVE_FULL_GL
+#define FEATURE_ARB_vertex_buffer_object _HAVE_FULL_GL
+#define FEATURE_ARB_vertex_program _HAVE_FULL_GL
+
+#define FEATURE_ARB_vertex_shader _HAVE_FULL_GL
+#define FEATURE_ARB_fragment_shader _HAVE_FULL_GL
+#define FEATURE_ARB_shader_objects (FEATURE_ARB_vertex_shader || FEATURE_ARB_fragment_shader)
+#define FEATURE_ARB_shading_language_100 FEATURE_ARB_shader_objects
+#define FEATURE_ARB_shading_language_120 FEATURE_ARB_shader_objects
+
+#define FEATURE_EXT_framebuffer_blit 0
+#define FEATURE_EXT_framebuffer_object _HAVE_FULL_GL
+#define FEATURE_EXT_pixel_buffer_object _HAVE_FULL_GL
+#define FEATURE_EXT_texture_sRGB 0
+#define FEATURE_EXT_timer_query 0
+#define FEATURE_ATI_fragment_shader 0
+#define FEATURE_MESA_program_debug _HAVE_FULL_GL
+#define FEATURE_NV_fence 0
+#define FEATURE_NV_fragment_program 0
+#define FEATURE_NV_vertex_program 0
+
+#define FEATURE_OES_EGL_image 1
+#define FEATURE_OES_framebuffer_object 1
+#define FEATURE_OES_draw_texture 1
+#define FEATURE_OES_mapbuffer 1
+
+#define FEATURE_extra_context_init 1
+
+/*@}*/
+
+
+
+
+#endif /* MFEATURES_H */
diff --git a/src/mesa/es/main/specials_es1.c b/src/mesa/es/main/specials_es1.c
new file mode 100644
index 0000000000..02c3247e94
--- /dev/null
+++ b/src/mesa/es/main/specials_es1.c
@@ -0,0 +1,186 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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
+ * TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION 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/mtypes.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/get.h"
+
+
+extern const GLubyte * GLAPIENTRY _es_GetString(GLenum name);
+
+
+static const GLubyte *
+compute_es_version(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ static const char es_1_0[] = "OpenGL ES-CM 1.0";
+ static const char es_1_1[] = "OpenGL ES-CM 1.1";
+ /* OpenGL ES 1.0 is derived from OpenGL 1.3 */
+ const GLboolean ver_1_0 = (ctx->Extensions.ARB_multisample &&
+ ctx->Extensions.ARB_multitexture &&
+ ctx->Extensions.ARB_texture_compression &&
+ ctx->Extensions.EXT_texture_env_add &&
+ ctx->Extensions.ARB_texture_env_combine &&
+ ctx->Extensions.ARB_texture_env_dot3);
+ /* OpenGL ES 1.1 is derived from OpenGL 1.5 */
+ const GLboolean ver_1_1 = (ver_1_0 &&
+ ctx->Extensions.EXT_point_parameters &&
+ ctx->Extensions.SGIS_generate_mipmap &&
+ ctx->Extensions.ARB_vertex_buffer_object);
+ if (ver_1_1)
+ return (const GLubyte *) es_1_1;
+
+ if (!ver_1_0)
+ _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support.");
+ return (const GLubyte *) es_1_0;
+}
+
+
+static size_t
+append_extension(char **str, const char *ext)
+{
+ char *s = *str;
+ size_t len = strlen(ext);
+
+ if (s) {
+ memcpy(s, ext, len);
+ s[len++] = ' ';
+ s[len] = '\0';
+
+ *str += len;
+ }
+ else {
+ len++;
+ }
+
+ return len;
+}
+
+
+static size_t
+make_extension_string(const GLcontext *ctx, char *str)
+{
+ size_t len = 0;
+
+ /* Core additions */
+ len += append_extension(&str, "GL_OES_byte_coordinates");
+ len += append_extension(&str, "GL_OES_fixed_point");
+ len += append_extension(&str, "GL_OES_single_precision");
+ len += append_extension(&str, "GL_OES_matrix_get");
+
+ /* 1.1 required extensions */
+ len += append_extension(&str, "GL_OES_read_format");
+ len += append_extension(&str, "GL_OES_compressed_paletted_texture");
+ len += append_extension(&str, "GL_OES_point_size_array");
+ len += append_extension(&str, "GL_OES_point_sprite");
+
+ /* 1.1 deprecated extensions */
+ len += append_extension(&str, "GL_OES_query_matrix");
+
+ if (ctx->Extensions.OES_EGL_image)
+ len += append_extension(&str, "GL_OES_EGL_image");
+
+ if (ctx->Extensions.OES_draw_texture)
+ len += append_extension(&str, "GL_OES_draw_texture");
+
+ if (ctx->Extensions.EXT_blend_equation_separate)
+ len += append_extension(&str, "GL_OES_blend_equation_separate");
+ if (ctx->Extensions.EXT_blend_func_separate)
+ len += append_extension(&str, "GL_OES_blend_func_separate");
+ if (ctx->Extensions.EXT_blend_subtract)
+ len += append_extension(&str, "GL_OES_blend_subtract");
+
+ if (ctx->Extensions.ARB_texture_cube_map)
+ len += append_extension(&str, "GL_OES_texture_cube_map");
+ if (ctx->Extensions.ARB_texture_env_crossbar)
+ len += append_extension(&str, "GL_OES_texture_env_crossbar");
+ if (ctx->Extensions.ARB_texture_mirrored_repeat)
+ len += append_extension(&str, "GL_OES_texture_mirrored_repeat");
+
+ if (ctx->Extensions.ARB_framebuffer_object) {
+ len += append_extension(&str, "GL_OES_framebuffer_object");
+ len += append_extension(&str, "GL_OES_depth24");
+ len += append_extension(&str, "GL_OES_depth32");
+ len += append_extension(&str, "GL_OES_fbo_render_mipmap");
+ len += append_extension(&str, "GL_OES_rgb8_rgba8");
+ len += append_extension(&str, "GL_OES_stencil1");
+ len += append_extension(&str, "GL_OES_stencil4");
+ len += append_extension(&str, "GL_OES_stencil8");
+ }
+
+ if (ctx->Extensions.EXT_vertex_array)
+ len += append_extension(&str, "GL_OES_element_index_uint");
+ if (ctx->Extensions.ARB_vertex_buffer_object)
+ len += append_extension(&str, "GL_OES_mapbuffer");
+ if (ctx->Extensions.EXT_texture_filter_anisotropic)
+ len += append_extension(&str, "GL_EXT_texture_filter_anisotropic");
+
+ return len;
+}
+
+
+static const GLubyte *
+compute_es_extensions(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.String) {
+ char *s;
+ unsigned int len;
+
+ len = make_extension_string(ctx, NULL);
+ s = (char *) _mesa_malloc(len + 1);
+ if (!s)
+ return NULL;
+ make_extension_string(ctx, s);
+ ctx->Extensions.String = (const GLubyte *) s;
+ }
+
+ return ctx->Extensions.String;
+}
+
+
+const GLubyte * GLAPIENTRY
+_es_GetString(GLenum name)
+{
+ switch (name) {
+ case GL_VERSION:
+ return compute_es_version();
+ case GL_EXTENSIONS:
+ return compute_es_extensions();
+ default:
+ return _mesa_GetString(name);
+ }
+}
+
+
+void
+_mesa_initialize_context_extra(GLcontext *ctx)
+{
+ /* FEATURE_es2_glsl is on */
+ ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+ ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
+}
diff --git a/src/mesa/es/main/specials_es2.c b/src/mesa/es/main/specials_es2.c
new file mode 100644
index 0000000000..791f178361
--- /dev/null
+++ b/src/mesa/es/main/specials_es2.c
@@ -0,0 +1,173 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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
+ * TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION 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/mtypes.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/get.h"
+
+
+const GLubyte * GLAPIENTRY _es_GetString(GLenum name);
+
+
+static const GLubyte *
+compute_es_version(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ static const char es_2_0[] = "OpenGL ES 2.0";
+ /* OpenGL ES 2.0 is derived from OpenGL 2.0 */
+ const GLboolean ver_2_0 = (ctx->Extensions.ARB_multisample &&
+ ctx->Extensions.ARB_multitexture &&
+ ctx->Extensions.ARB_texture_compression &&
+ ctx->Extensions.ARB_texture_cube_map &&
+ ctx->Extensions.ARB_texture_mirrored_repeat &&
+ ctx->Extensions.EXT_blend_color &&
+ ctx->Extensions.EXT_blend_func_separate &&
+ ctx->Extensions.EXT_blend_minmax &&
+ ctx->Extensions.EXT_blend_subtract &&
+ ctx->Extensions.EXT_stencil_wrap &&
+ ctx->Extensions.ARB_vertex_buffer_object &&
+ ctx->Extensions.ARB_shader_objects &&
+ ctx->Extensions.ARB_vertex_shader &&
+ ctx->Extensions.ARB_fragment_shader &&
+ ctx->Extensions.ARB_texture_non_power_of_two &&
+ ctx->Extensions.EXT_blend_equation_separate);
+ if (!ver_2_0)
+ _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support.");
+ return (const GLubyte *) es_2_0;
+}
+
+
+static size_t
+append_extension(char **str, const char *ext)
+{
+ char *s = *str;
+ size_t len = strlen(ext);
+
+ if (s) {
+ memcpy(s, ext, len);
+ s[len++] = ' ';
+ s[len] = '\0';
+
+ *str += len;
+ }
+ else {
+ len++;
+ }
+
+ return len;
+}
+
+
+static size_t
+make_extension_string(const GLcontext *ctx, char *str)
+{
+ size_t len = 0;
+
+ /* Core additions */
+ len += append_extension(&str, "GL_OES_single_precision");
+
+ /* Required extensions */
+ len += append_extension(&str, "GL_OES_compressed_paletted_texture");
+
+ if (ctx->Extensions.ARB_framebuffer_object) {
+ len += append_extension(&str, "GL_OES_framebuffer_object");
+ len += append_extension(&str, "GL_OES_depth24");
+ len += append_extension(&str, "GL_OES_depth32");
+ len += append_extension(&str, "GL_OES_fbo_render_mipmap");
+ len += append_extension(&str, "GL_OES_rgb8_rgba8");
+ len += append_extension(&str, "GL_OES_stencil1");
+ len += append_extension(&str, "GL_OES_stencil4");
+ len += append_extension(&str, "GL_OES_stencil8");
+ }
+
+ if (ctx->Extensions.EXT_vertex_array)
+ len += append_extension(&str, "GL_OES_element_index_uint");
+ if (ctx->Extensions.ARB_vertex_buffer_object)
+ len += append_extension(&str, "GL_OES_mapbuffer");
+
+ if (ctx->Extensions.EXT_texture3D)
+ len += append_extension(&str, "GL_OES_texture_3D");
+ if (ctx->Extensions.ARB_texture_non_power_of_two)
+ len += append_extension(&str, "GL_OES_texture_npot");
+ if (ctx->Extensions.EXT_texture_filter_anisotropic)
+ len += append_extension(&str, "GL_EXT_texture_filter_anisotropic");
+
+ len += append_extension(&str, "GL_EXT_texture_type_2_10_10_10_REV");
+ if (ctx->Extensions.ARB_depth_texture)
+ len += append_extension(&str, "GL_OES_depth_texture");
+ if (ctx->Extensions.EXT_packed_depth_stencil)
+ len += append_extension(&str, "GL_OES_packed_depth_stencil");
+ if (ctx->Extensions.ARB_fragment_shader)
+ len += append_extension(&str, "GL_OES_standard_derivatives");
+
+ return len;
+}
+
+
+static const GLubyte *
+compute_es_extensions(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.String) {
+ char *s;
+ unsigned int len;
+
+ len = make_extension_string(ctx, NULL);
+ s = (char *) _mesa_malloc(len + 1);
+ if (!s)
+ return NULL;
+ make_extension_string(ctx, s);
+ ctx->Extensions.String = (const GLubyte *) s;
+ }
+
+ return ctx->Extensions.String;
+}
+
+const GLubyte * GLAPIENTRY
+_es_GetString(GLenum name)
+{
+ switch (name) {
+ case GL_VERSION:
+ return compute_es_version();
+ case GL_SHADING_LANGUAGE_VERSION:
+ return (const GLubyte *) "OpenGL ES GLSL ES 1.0.16";
+ case GL_EXTENSIONS:
+ return compute_es_extensions();
+ default:
+ return _mesa_GetString(name);
+ }
+}
+
+
+void
+_mesa_initialize_context_extra(GLcontext *ctx)
+{
+ ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+ ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
+
+ ctx->Point.PointSprite = GL_TRUE; /* always on for ES 2.x */
+}
diff --git a/src/mesa/es/main/stubs.c b/src/mesa/es/main/stubs.c
new file mode 100644
index 0000000000..e7b8bc780f
--- /dev/null
+++ b/src/mesa/es/main/stubs.c
@@ -0,0 +1,138 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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
+ * TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ **************************************************************************/
+
+
+/**
+ * Temporary stubs for "missing" mesa functions.
+ */
+
+
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "vbo/vbo.h"
+
+#define NEED_IMPLEMENT() do { \
+ GET_CURRENT_CONTEXT(ctx); \
+ _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__); \
+ } while (0)
+
+#if FEATURE_accum
+/* This is a sanity check that to be sure we're using the correct mfeatures.h
+ * header. We don't want to accidentally use the one from mainline Mesa.
+ */
+#error "The wrong mfeatures.h file is being included!"
+#endif
+
+
+/* silence compiler warnings */
+extern void GLAPIENTRY _vbo_Materialf(GLenum face, GLenum pname, GLfloat param);
+extern void GLAPIENTRY _mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+extern void GLAPIENTRY _mesa_ReleaseShaderCompiler(void);
+extern void GLAPIENTRY _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length);
+extern void GLAPIENTRY _vbo_VertexAttrib1f(GLuint indx, GLfloat x);
+extern void GLAPIENTRY _vbo_VertexAttrib1fv(GLuint indx, const GLfloat* values);
+extern void GLAPIENTRY _vbo_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
+extern void GLAPIENTRY _vbo_VertexAttrib2fv(GLuint indx, const GLfloat* values);
+extern void GLAPIENTRY _vbo_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+extern void GLAPIENTRY _vbo_VertexAttrib3fv(GLuint indx, const GLfloat* values);
+extern void GLAPIENTRY _vbo_VertexAttrib4fv(GLuint indx, const GLfloat* values);
+
+
+void GLAPIENTRY
+_vbo_Materialf(GLenum face, GLenum pname, GLfloat param)
+{
+ _vbo_Materialfv(face, pname, &param);
+}
+
+
+void GLAPIENTRY
+_mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
+ GLint* range, GLint* precision)
+{
+ NEED_IMPLEMENT();
+}
+
+
+void GLAPIENTRY
+_mesa_ReleaseShaderCompiler(void)
+{
+ NEED_IMPLEMENT();
+}
+
+
+void GLAPIENTRY
+_mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
+ const void* binary, GLint length)
+{
+ NEED_IMPLEMENT();
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib1f(GLuint indx, GLfloat x)
+{
+ _vbo_VertexAttrib4f(indx, x, 0.0, 0.0, 1.0f);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib1fv(GLuint indx, const GLfloat* values)
+{
+ _vbo_VertexAttrib4f(indx, values[0], 0.0, 0.0, 1.0f);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+{
+ _vbo_VertexAttrib4f(indx, x, y, 0.0, 1.0f);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib2fv(GLuint indx, const GLfloat* values)
+{
+ _vbo_VertexAttrib4f(indx, values[0], values[1], 0.0, 1.0f);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+{
+ _vbo_VertexAttrib4f(indx, x, y, z, 1.0f);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib3fv(GLuint indx, const GLfloat* values)
+{
+ _vbo_VertexAttrib4f(indx, values[0], values[1], values[2], 1.0f);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib4fv(GLuint indx, const GLfloat* values)
+{
+ _vbo_VertexAttrib4f(indx, values[0], values[1], values[2], values[3]);
+}
diff --git a/src/mesa/es/sources.mak b/src/mesa/es/sources.mak
new file mode 100644
index 0000000000..6d20740095
--- /dev/null
+++ b/src/mesa/es/sources.mak
@@ -0,0 +1,159 @@
+# LOCAL sources
+
+ES1_LOCAL_SOURCES := \
+ main/api_exec_es1.c \
+ main/drawtex.c \
+ main/eglimage.c \
+ main/get_es1.c \
+ main/specials_es1.c \
+ main/es_cpaltex.c \
+ main/es_fbo.c \
+ main/es_query_matrix.c \
+ main/stubs.c
+
+ES1_GALLIUM_LOCAL_SOURCES := \
+ $(ES1_LOCAL_SOURCES)
+
+ES1_API_LOCAL_SOURCES := \
+
+ES1_LOCAL_INCLUDES := \
+ -I. \
+ -I./glapi/headers-es1 \
+ -I./state_tracker \
+ -I$(MESA)/state_tracker
+
+ES2_LOCAL_SOURCES := \
+ main/api_exec_es2.c \
+ main/eglimage.c \
+ main/get_es2.c \
+ main/specials_es2.c \
+ main/es_cpaltex.c \
+ main/es_fbo.c \
+ main/stubs.c
+
+ES2_GALLIUM_LOCAL_SOURCES := \
+ $(ES2_LOCAL_SOURCES)
+
+ES2_API_LOCAL_SOURCES :=
+
+ES2_LOCAL_INCLUDES := $(subst es1,es2,$(ES1_LOCAL_INCLUDES))
+
+# MESA sources
+
+include $(MESA)/sources.mak
+
+MAIN_OMITTED := \
+ main/api_exec.c \
+ main/dlopen.c \
+ main/get.c
+MAIN_SOURCES := $(filter-out $(MAIN_OMITTED), $(MAIN_SOURCES))
+
+VBO_OMITTED := \
+ vbo/vbo_save_api.c \
+ vbo/vbo_save.c \
+ vbo/vbo_save_draw.c \
+ vbo/vbo_save_loopback.c
+VBO_SOURCES := $(filter-out $(VBO_OMITTED), $(VBO_SOURCES))
+
+STATETRACKER_OMITTED := \
+ state_tracker/st_cb_drawpixels.c \
+ state_tracker/st_cb_feedback.c \
+ state_tracker/st_cb_rasterpos.c \
+ state_tracker/st_api.c \
+ state_tracker/st_draw_feedback.c
+STATETRACKER_SOURCES := $(filter-out $(STATETRACKER_OMITTED), $(STATETRACKER_SOURCES))
+
+SHADER_OMITTED := \
+ shader/atifragshader.c \
+ shader/nvfragparse.c \
+ shader/nvprogram.c \
+ shader/nvvertparse.c
+SHADER_SOURCES := $(filter-out $(SHADER_OMITTED), $(SHADER_SOURCES))
+
+STATETRACKER_SOURCES += \
+ state_tracker/st_cb_drawtex.c
+
+ES1_MESA_SOURCES := \
+ $(MAIN_SOURCES) \
+ $(MATH_SOURCES) \
+ $(MATH_XFORM_SOURCES) \
+ $(VBO_SOURCES) \
+ $(TNL_SOURCES) \
+ $(SHADER_SOURCES) \
+ $(SWRAST_SOURCES) \
+ $(SWRAST_SETUP_SOURCES) \
+ $(COMMON_DRIVER_SOURCES) \
+ $(ASM_C_SOURCES) \
+ $(SLANG_SOURCES)
+
+ES1_GALLIUM_MESA_SOURCES := \
+ $(MAIN_SOURCES) \
+ $(MATH_SOURCES) \
+ $(MATH_XFORM_SOURCES) \
+ $(VBO_SOURCES) \
+ $(STATETRACKER_SOURCES) \
+ $(SHADER_SOURCES) \
+ $(SLANG_SOURCES)
+
+ES1_API_MESA_SOURCES := \
+ $(GLAPI_SOURCES)
+
+ES1_MESA_INCLUDES := $(INCLUDE_DIRS)
+
+# remove LOCAL sources from MESA sources
+ES1_MESA_SOURCES := $(filter-out $(ES1_LOCAL_SOURCES), $(ES1_MESA_SOURCES))
+ES1_GALLIUM_MESA_SOURCES := $(filter-out $(ES1_GALLIUM_LOCAL_SOURCES), $(ES1_GALLIUM_MESA_SOURCES))
+ES1_API_MESA_SOURCES := $(filter-out $(ES1_API_LOCAL_SOURCES), $(ES1_API_MESA_SOURCES))
+
+# es2 and es1 share sources
+ES2_MESA_SOURCES := $(ES1_MESA_SOURCES)
+ES2_GALLIUM_MESA_SOURCES := $(ES1_GALLIUM_MESA_SOURCES)
+ES2_API_MESA_SOURCES := $(ES1_API_MESA_SOURCES)
+
+ES2_MESA_INCLUDES := $(ES1_MESA_INCLUDES)
+
+
+# collect sources
+ES1_SOURCES := $(ES1_LOCAL_SOURCES) $(ES1_MESA_SOURCES)
+ES1_GALLIUM_SOURCES := $(ES1_GALLIUM_LOCAL_SOURCES) $(ES1_GALLIUM_MESA_SOURCES)
+ES1_API_SOURCES := $(ES1_API_LOCAL_SOURCES) $(ES1_API_MESA_SOURCES)
+
+ES2_SOURCES := $(ES2_LOCAL_SOURCES) $(ES2_MESA_SOURCES)
+ES2_GALLIUM_SOURCES := $(ES2_GALLIUM_LOCAL_SOURCES) $(ES2_GALLIUM_MESA_SOURCES)
+ES2_API_SOURCES := $(ES2_API_LOCAL_SOURCES) $(ES2_API_MESA_SOURCES)
+
+# collect includes
+ES1_INCLUDES := $(ES1_LOCAL_INCLUDES) $(ES1_MESA_INCLUDES)
+ES2_INCLUDES := $(ES2_LOCAL_INCLUDES) $(ES2_MESA_INCLUDES)
+
+# group sources in another way
+ALL_LOCAL_SOURCES := \
+ $(ES1_LOCAL_SOURCES) \
+ $(ES1_GALLIUM_LOCAL_SOURCES) \
+ $(ES1_API_LOCAL_SOURCES) \
+ $(ES2_LOCAL_SOURCES) \
+ $(ES2_GALLIUM_LOCAL_SOURCES) \
+ $(ES2_API_LOCAL_SOURCES)
+ALL_MESA_SOURCES := \
+ $(ES1_MESA_SOURCES) \
+ $(ES1_GALLIUM_MESA_SOURCES) \
+ $(ES1_API_MESA_SOURCES) \
+ $(ES2_MESA_SOURCES) \
+ $(ES2_GALLIUM_MESA_SOURCES) \
+ $(ES2_API_MESA_SOURCES)
+
+# sort to remove duplicates
+ALL_LOCAL_SOURCES := $(sort $(ALL_LOCAL_SOURCES))
+ALL_MESA_SOURCES := $(sort $(ALL_MESA_SOURCES))
+
+# convert to objects
+ES1_OBJECTS := $(ES1_SOURCES:.c=.o)
+ES1_GALLIUM_OBJECTS := $(ES1_GALLIUM_SOURCES:.c=.o)
+ES1_API_OBJECTS := $(ES1_API_SOURCES:.c=.o)
+
+ES2_OBJECTS := $(ES2_SOURCES:.c=.o)
+ES2_GALLIUM_OBJECTS := $(ES2_GALLIUM_SOURCES:.c=.o)
+ES2_API_OBJECTS := $(ES2_API_SOURCES:.c=.o)
+
+ALL_LOCAL_OBJECTS := $(ALL_LOCAL_SOURCES:.c=.o)
+ALL_MESA_OBJECTS := $(ALL_MESA_SOURCES:.c=.o)
diff --git a/src/mesa/gl.pc.in b/src/mesa/gl.pc.in
index 0462b9fca2..97b86596fc 100644
--- a/src/mesa/gl.pc.in
+++ b/src/mesa/gl.pc.in
@@ -7,6 +7,6 @@ Name: gl
Description: Mesa OpenGL library
Requires.private: @GL_PC_REQ_PRIV@
Version: @VERSION@
-Libs: -L${libdir} -lGL
+Libs: -L${libdir} -l@GL_LIB@
Libs.private: @GL_PC_LIB_PRIV@
Cflags: -I${includedir} @GL_PC_CFLAGS@
diff --git a/src/mesa/glapi/ARB_copy_buffer.xml b/src/mesa/glapi/ARB_copy_buffer.xml
new file mode 100644
index 0000000000..719816d817
--- /dev/null
+++ b/src/mesa/glapi/ARB_copy_buffer.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+
+<category name="GL_ARB_copy_buffer" number="59">
+
+ <enum name="COPY_READ_BUFFER" value="0x8F36"/>
+ <enum name="COPY_WRITE_BUFFER" value="0x8F37"/>
+
+ <function name="CopyBufferSubData" offset="assign">
+ <param name="readTarget" type="GLenum"/>
+ <param name="writeTarget" type="GLenum"/>
+ <param name="readOffset" type="GLintptr"/>
+ <param name="writeOffset" type="GLintptr"/>
+ <param name="size" type="GLsizeiptr"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/ARB_depth_clamp.xml b/src/mesa/glapi/ARB_depth_clamp.xml
new file mode 100644
index 0000000000..157c9a86b1
--- /dev/null
+++ b/src/mesa/glapi/ARB_depth_clamp.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_ARB_depth_clamp" number="61">
+ <enum name="DEPTH_CLAMP" count="1" value="0x864F">
+ <size name="Get" mode="get"/>
+ </enum>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/ARB_draw_elements_base_vertex.xml b/src/mesa/glapi/ARB_draw_elements_base_vertex.xml
new file mode 100644
index 0000000000..f4067f4c8d
--- /dev/null
+++ b/src/mesa/glapi/ARB_draw_elements_base_vertex.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+
+<category name="GL_ARB_draw_elements_base_vertex" number="62">
+
+ <function name="DrawElementsBaseVertex" offset="assign">
+ <param name="mode" type="GLenum"/>
+ <param name="count" type="GLsizei"/>
+ <param name="type" type="GLenum"/>
+ <param name="indices" type="const GLvoid *"/>
+ <param name="basevertex" type="GLint"/>
+ </function>
+
+ <function name="DrawRangeElementsBaseVertex" offset="assign">
+ <param name="mode" type="GLenum"/>
+ <param name="start" type="GLuint"/>
+ <param name="end" type="GLuint"/>
+ <param name="count" type="GLsizei"/>
+ <param name="type" type="GLenum"/>
+ <param name="indices" type="const GLvoid *"/>
+ <param name="basevertex" type="GLint"/>
+ </function>
+
+ <function name="MultiDrawElementsBaseVertex" offset="assign">
+ <param name="mode" type="GLenum"/>
+ <param name="count" type="const GLsizei *"/>
+ <param name="type" type="GLenum"/>
+ <param name="indices" type="const GLvoid **"/>
+ <param name="primcount" type="GLsizei"/>
+ <param name="basevertex" type="const GLint *"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/ARB_framebuffer_object.xml b/src/mesa/glapi/ARB_framebuffer_object.xml
new file mode 100644
index 0000000000..b700e7e77d
--- /dev/null
+++ b/src/mesa/glapi/ARB_framebuffer_object.xml
@@ -0,0 +1,269 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+<category name="GL_ARB_framebuffer_object" number="45">
+ <enum name="FRAMEBUFFER" value="0x8D40"/>
+ <enum name="READ_FRAMEBUFFER" value="0x8CA8"/>
+ <enum name="DRAW_FRAMEBUFFER" value="0x8CA9"/>
+
+ <enum name="RENDERBUFFER" value="0x8D41"/>
+
+ <enum name="STENCIL_INDEX1_EXT" value="0x8D46"/>
+ <enum name="STENCIL_INDEX4_EXT" value="0x8D47"/>
+ <enum name="STENCIL_INDEX8_EXT" value="0x8D48"/>
+ <enum name="STENCIL_INDEX16_EXT" value="0x8D49"/>
+
+ <enum name="RENDERBUFFER_WIDTH" value="0x8D42"/>
+ <enum name="RENDERBUFFER_HEIGHT" value="0x8D43"/>
+ <enum name="RENDERBUFFER_INTERNAL_FORMAT" value="0x8D44"/>
+ <enum name="RENDERBUFFER_RED_SIZE" value="0x8D50"/>
+ <enum name="RENDERBUFFER_GREEN_SIZE" value="0x8D51"/>
+ <enum name="RENDERBUFFER_BLUE_SIZE" value="0x8D52"/>
+ <enum name="RENDERBUFFER_ALPHA_SIZE" value="0x8D53"/>
+ <enum name="RENDERBUFFER_DEPTH_SIZE" value="0x8D54"/>
+ <enum name="RENDERBUFFER_STENCIL_SIZE" value="0x8D55"/>
+ <enum name="RENDERBUFFER_SAMPLES" value="0x8CAB"/>
+
+ <enum name="FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE" count="1" value="0x8CD0">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_OBJECT_NAME" count="1" value="0x8CD1">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL" count="1" value="0x8CD2">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE" count="1" value="0x8CD3">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER" count="1" value="0x8CD4">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING" count="1" value="0x8210">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE" count="1" value="0x8211">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_RED_SIZE" count="1" value="0x8212">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_GREEN_SIZE" count="1" value="0x8213">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_BLUE_SIZE" count="1" value="0x8214">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE" count="1" value="0x8215">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE" count="1" value="0x8216">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+ <enum name="FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE" count="1" value="0x8217">
+ <size name="GetFramebufferAttachmentParameteriv" mode="get"/>
+ </enum>
+
+ <enum name="SRGB" value="0x8C40"/>
+ <enum name="UNSIGNED_NORMALIZED" value="0x8C17"/>
+ <enum name="FRAMEBUFFER_DEFAULT" value="0x8218"/>
+ <enum name="INDEX" value="0x8222"/>
+
+ <enum name="COLOR_ATTACHMENT0" value="0x8CE0"/>
+ <enum name="COLOR_ATTACHMENT1" value="0x8CE1"/>
+ <enum name="COLOR_ATTACHMENT2" value="0x8CE2"/>
+ <enum name="COLOR_ATTACHMENT3" value="0x8CE3"/>
+ <enum name="COLOR_ATTACHMENT4" value="0x8CE4"/>
+ <enum name="COLOR_ATTACHMENT5" value="0x8CE5"/>
+ <enum name="COLOR_ATTACHMENT6" value="0x8CE6"/>
+ <enum name="COLOR_ATTACHMENT7" value="0x8CE7"/>
+ <enum name="COLOR_ATTACHMENT8" value="0x8CE8"/>
+ <enum name="COLOR_ATTACHMENT9" value="0x8CE9"/>
+ <enum name="COLOR_ATTACHMENT10" value="0x8CEA"/>
+ <enum name="COLOR_ATTACHMENT11" value="0x8CEB"/>
+ <enum name="COLOR_ATTACHMENT12" value="0x8CEC"/>
+ <enum name="COLOR_ATTACHMENT13" value="0x8CED"/>
+ <enum name="COLOR_ATTACHMENT14" value="0x8CEE"/>
+ <enum name="COLOR_ATTACHMENT15" value="0x8CEF"/>
+ <enum name="DEPTH_ATTACHMENT" value="0x8D00"/>
+ <enum name="STENCIL_ATTACHMENT" value="0x8D20"/>
+ <enum name="DEPTH_STENCIL_ATTACHMENT" value="0x821A"/>
+
+ <enum name="MAX_SAMPLES" value="0x8D57"/>
+
+ <enum name="FRAMEBUFFER_COMPLETE" value="0x8CD5"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_ATTACHMENT" value="0x8CD6"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" value="0x8CD7"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT" value="0x8CDB"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT" value="0x8CDC"/>
+ <enum name="FRAMEBUFFER_UNSUPPORTED" value="0x8CDD"/>
+ <enum name="FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" value="0x8D56"/>
+ <enum name="FRAMEBUFFER_UNDEFINED" value="0x8219"/>
+
+ <enum name="FRAMEBUFFER_BINDING_EXT" count="1" value="0x8CA6">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="DRAW_FRAMEBUFFER_BINDING_EXT" count="1" value="0x8CA6">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="READ_FRAMEBUFFER_BINDING_EXT" count="1" value="0x8CAA">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="RENDERBUFFER_BINDING_EXT" count="1" value="0x8CA7">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_COLOR_ATTACHMENTS_EXT" count="1" value="0x8CDF">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="MAX_RENDERBUFFER_SIZE_EXT" count="1" value="0x84E8">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <enum name="INVALID_FRAMEBUFFER_OPERATION" value="0x0506"/>
+
+ <enum name="DEPTH_STENCIL" value="0x84F9"/>
+
+ <enum name="UNSIGNED_INT_24_8" value="0x84FA"/>
+
+ <enum name="DEPTH24_STENCIL8" value="0x88F0"/>
+
+ <enum name="TEXTURE_STENCIL_SIZE" value="0x88F1"/>
+
+
+
+ <function name="IsRenderbuffer" alias="IsRenderbufferEXT">
+ <param name="renderbuffer" type="GLuint"/>
+ <return type="GLboolean"/>
+ </function>
+
+ <function name="BindRenderbuffer" alias="BindRenderbufferEXT">
+ <param name="target" type="GLenum"/>
+ <param name="renderbuffer" type="GLuint"/>
+ </function>
+
+ <function name="DeleteRenderbuffers" alias="DeleteRenderbuffersEXT">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="renderbuffers" type="const GLuint *" count="n"/>
+ </function>
+
+ <function name="GenRenderbuffers" alias="GenRenderbuffersEXT">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="renderbuffers" type="GLuint *" count="n" output="true"/>
+ </function>
+
+ <function name="RenderbufferStorage" alias="RenderbufferStorageEXT">
+ <param name="target" type="GLenum"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ </function>
+
+ <function name="RenderbufferStorageMultisample" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="samples" type="GLsizei"/>
+ <param name="internalformat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ </function>
+
+ <function name="GetRenderbufferParameteriv" alias="GetRenderbufferParameterivEXT">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true"/>
+ </function>
+
+ <function name="IsFramebuffer" alias="IsFramebufferEXT">
+ <param name="framebuffer" type="GLuint"/>
+ <return type="GLboolean"/>
+ </function>
+
+ <function name="BindFramebuffer" alias="BindFramebufferEXT">
+ <param name="target" type="GLenum"/>
+ <param name="framebuffer" type="GLuint"/>
+ </function>
+
+ <function name="DeleteFramebuffers" alias="DeleteFramebuffersEXT">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="framebuffers" type="const GLuint *" count="n"/>
+ </function>
+
+ <function name="GenFramebuffers" alias="GenFramebuffersEXT">
+ <param name="n" type="GLsizei" counter="true"/>
+ <param name="framebuffers" type="GLuint *" count="n" output="true"/>
+ </function>
+
+ <function name="CheckFramebufferStatus" alias="CheckFramebufferStatusEXT">
+ <param name="target" type="GLenum"/>
+ <return type="GLenum"/>
+ </function>
+
+ <function name="FramebufferTexture1D" alias="FramebufferTexture1DEXT">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="textarget" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ </function>
+
+ <function name="FramebufferTexture2D" alias="FramebufferTexture2DEXT">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="textarget" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ </function>
+
+ <function name="FramebufferTexture3D" alias="FramebufferTexture3DEXT">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="textarget" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="zoffset" type="GLint"/>
+ </function>
+
+ <function name="FramebufferTextureLayer" alias="FramebufferTextureLayerEXT">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="layer" type="GLint"/>
+ </function>
+
+ <function name="FramebufferRenderbuffer" alias="FramebufferRenderbufferEXT">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="renderbuffertarget" type="GLenum"/>
+ <param name="renderbuffer" type="GLuint"/>
+ </function>
+
+ <function name="GetFramebufferAttachmentParameteriv" alias="GetFramebufferAttachmentParameterivEXT">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true"/>
+ </function>
+
+ <function name="BlitFramebuffer" alias="BlitFramebufferEXT">
+ <param name="srcX0" type="GLint"/>
+ <param name="srcY0" type="GLint"/>
+ <param name="srcX1" type="GLint"/>
+ <param name="srcY1" type="GLint"/>
+ <param name="dstX0" type="GLint"/>
+ <param name="dstY0" type="GLint"/>
+ <param name="dstX1" type="GLint"/>
+ <param name="dstY1" type="GLint"/>
+ <param name="mask" type="GLbitfield"/>
+ <param name="filter" type="GLenum"/>
+ </function>
+
+ <function name="GenerateMipmap" alias="GenerateMipmapEXT">
+ <param name="target" type="GLenum"/>
+ </function>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/ARB_map_buffer_range.xml b/src/mesa/glapi/ARB_map_buffer_range.xml
new file mode 100644
index 0000000000..afcb9b6ba6
--- /dev/null
+++ b/src/mesa/glapi/ARB_map_buffer_range.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+
+<category name="GL_ARB_map_buffer_range" number="50">
+
+ <enum name="MAP_READ_BIT" value="0x0001"/>
+ <enum name="MAP_WRITE_BIT" value="0x0002"/>
+ <enum name="MAP_INVALIDATE_RANGE_BIT" value="0x0004"/>
+ <enum name="MAP_INVALIDATE_BUFFER_BIT" value="0x0008"/>
+ <enum name="MAP_FLUSH_EXPLICIT_BIT" value="0x0010"/>
+ <enum name="MAP_UNSYNCHRONIZED_BIT" value="0x0020"/>
+
+ <function name="MapBufferRange" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="offset" type="GLintptr"/>
+ <param name="length" type="GLsizeiptr"/>
+ <param name="access" type="GLbitfield"/>
+ <return type="GLvoid *"/>
+ </function>
+
+ <function name="FlushMappedBufferRange" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="offset" type="GLintptr"/>
+ <param name="length" type="GLsizeiptr"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/ARB_seamless_cube_map.xml b/src/mesa/glapi/ARB_seamless_cube_map.xml
new file mode 100644
index 0000000000..3cdc84d2b9
--- /dev/null
+++ b/src/mesa/glapi/ARB_seamless_cube_map.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_ARB_seamless_cubemap" number="65">
+ <enum name="TEXTURE_CUBE_MAP_SEAMLESS" count="1" value="0x88F4">
+ <size name="Get" mode="get"/>
+ </enum>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/ARB_sync.xml b/src/mesa/glapi/ARB_sync.xml
new file mode 100644
index 0000000000..37f474980c
--- /dev/null
+++ b/src/mesa/glapi/ARB_sync.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+<category name="GL_ARB_sync" number="61">
+ <type name="int64" size="8" glx_name="CARD64"/>
+ <type name="uint64" size="8" unsigned="true" glx_name="CARD64"/>
+ <type name="sync" size="8" unsigned="true" glx_name="CARD64"/>
+
+ <enum name="MAX_SERVER_WAIT_TIMEOUT" count="1" value="0x9111">
+ <size name="Get" mode="get"/>
+ </enum>
+ <enum name="OBJECT_TYPE" count="1" value="0x9112">
+ <size name="GetSynciv" mode="get"/>
+ </enum>
+ <enum name="SYNC_CONDITION" count="1" value="0x9113">
+ <size name="GetSynciv" mode="get"/>
+ </enum>
+ <enum name="SYNC_STATUS" count="1" value="0x9114">
+ <size name="GetSynciv" mode="get"/>
+ </enum>
+ <enum name="SYNC_FLAGS" count="1" value="0x9115">
+ <size name="GetSynciv" mode="get"/>
+ </enum>
+
+ <enum name="SYNC_FENCE" value="0x9116"/>
+ <enum name="SYNC_GPU_COMMANDS_COMPLETE" value="0x9117"/>
+ <enum name="UNSIGNALED" value="0x9118"/>
+ <enum name="SIGNALED" value="0x9119"/>
+ <enum name="ALREADY_SIGNALED" value="0x911A"/>
+ <enum name="TIMEOUT_EXPIRED" value="0x911B"/>
+ <enum name="CONDITION_SATISFIED" value="0x911C"/>
+ <enum name="WAIT_FAILED" value="0x911D"/>
+
+ <enum name="SYNC_FLUSH_COMMANDS_BIT" value="0x00000001"/>
+ <enum name="TIMEOUT_IGNORED" value="0xFFFFFFFFFFFFFFFF"/>
+
+
+
+ <function name="FenceSync" offset="assign">
+ <param name="condition" type="GLenum"/>
+ <param name="flags" type="GLbitfield"/>
+ <return type="GLsync"/>
+ </function>
+
+ <function name="IsSync" offset="assign">
+ <param name="sync" type="GLsync"/>
+ <return type="GLboolean"/>
+ </function>
+
+ <function name="DeleteSync" offset="assign">
+ <param name="sync" type="GLsync"/>
+ </function>
+
+ <function name="ClientWaitSync" offset="assign">
+ <param name="sync" type="GLsync"/>
+ <param name="flags" type="GLbitfield"/>
+ <param name="timeout" type="GLuint64"/>
+ <return type="GLenum"/>
+ </function>
+
+ <function name="WaitSync" offset="assign">
+ <param name="sync" type="GLsync"/>
+ <param name="flags" type="GLbitfield"/>
+ <param name="timeout" type="GLuint64"/>
+ </function>
+
+ <function name="GetInteger64v" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint64 *" output="true" variable_param="pname"/>
+ </function>
+
+ <function name="GetSynciv" offset="assign">
+ <param name="sync" type="GLsync"/>
+ <param name="pname" type="GLenum"/>
+ <param name="bufSize" type="GLsizei"/>
+ <param name="length" type="GLsizei *" output="true"/>
+ <param name="values" type="GLint *" output="true" variable_param="pname"/>
+ </function>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/ARB_vertex_array_object.xml b/src/mesa/glapi/ARB_vertex_array_object.xml
new file mode 100644
index 0000000000..3b4ab64f55
--- /dev/null
+++ b/src/mesa/glapi/ARB_vertex_array_object.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+
+<category name="GL_ARB_vertex_array_object" number="54">
+
+ <enum name="VERTEX_ARRAY_BINDING" value="0x85B5"/>
+
+ <function name="BindVertexArray" offset="assign">
+ <param name="array" type="GLuint"/>
+ </function>
+
+ <function name="DeleteVertexArrays" alias="DeleteVertexArraysAPPLE">
+ <param name="n" type="GLsizei"/>
+ <param name="arrays" type="const GLuint *"/>
+ </function>
+
+ <function name="GenVertexArrays" offset="assign">
+ <param name="n" type="GLsizei"/>
+ <param name="arrays" type="GLuint *"/>
+ </function>
+
+ <function name="IsVertexArray" alias="IsVertexArrayAPPLE">
+ <param name="array" type="GLuint"/>
+ <return type="GLboolean"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/EXT_framebuffer_object.xml b/src/mesa/glapi/EXT_framebuffer_object.xml
index 1b0de2ad23..5559b48b11 100644
--- a/src/mesa/glapi/EXT_framebuffer_object.xml
+++ b/src/mesa/glapi/EXT_framebuffer_object.xml
@@ -192,42 +192,4 @@
</function>
</category>
-
-
-<category name="GL_EXT_texture_array" number="329">
- <enum name="TEXTURE_1D_ARRAY_EXT" value="0x8C18"/>
- <enum name="PROXY_TEXTURE_1D_ARRAY_EXT" value="0x8C19"/>
- <enum name="TEXTURE_2D_ARRAY_EXT" value="0x8C1A"/>
- <enum name="PROXY_TEXTURE_2D_ARRAY_EXT" value="0x8C1B"/>
-
- <enum name="TEXTURE_BINDING_1D_ARRAY_EXT" count="1" value="0x8C1C">
- <size name="Get" mode="get"/>
- </enum>
-
- <enum name="TEXTURE_BINDING_2D_ARRAY_EXT" count="1" value="0x8C1D">
- <size name="Get" mode="get"/>
- </enum>
-
- <enum name="MAX_ARRAY_TEXTURE_LAYERS_EXT" count="1" value="0x88FF">
- <size name="Get" mode="get"/>
- </enum>
-
- <enum name="COMPARE_REF_DEPTH_TO_TEXTURE_EXT" count="1" value="0x884E">
- <size name="Get" mode="get"/>
- </enum>
-
- <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT" count="1" value="0x8CD4">
- <size name="GetFramebufferAttachmentParameterivEXT" mode="get"/>
- </enum>
-
- <function name="FramebufferTextureLayerEXT" offset="assign">
- <param name="target" type="GLenum"/>
- <param name="attachment" type="GLenum"/>
- <param name="texture" type="GLuint"/>
- <param name="level" type="GLint"/>
- <param name="layer" type="GLint"/>
- </function>
-</category>
-
-
</OpenGLAPI>
diff --git a/src/mesa/glapi/EXT_provoking_vertex.xml b/src/mesa/glapi/EXT_provoking_vertex.xml
new file mode 100644
index 0000000000..f528a2c7d3
--- /dev/null
+++ b/src/mesa/glapi/EXT_provoking_vertex.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+
+<category name="GL_EXT_provoking_vertex" number="364">
+
+ <enum name="FIRST_VERTEX_CONVENTION_EXT" value="0x8E4D"/>
+ <enum name="LAST_VERTEX_CONVENTION_EXT" value="0x8E4E"/>
+ <enum name="PROVOKING_VERTEX_EXT" value="0x8E4F"/>
+ <enum name="QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT" value="0x8E4C"/>
+
+ <function name="ProvokingVertexEXT" offset="assign">
+ <param name="mode" type="GLenum"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/EXT_texture_array.xml b/src/mesa/glapi/EXT_texture_array.xml
new file mode 100644
index 0000000000..e5bd9f3c69
--- /dev/null
+++ b/src/mesa/glapi/EXT_texture_array.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_EXT_texture_array" number="329">
+ <enum name="TEXTURE_1D_ARRAY_EXT" value="0x8C18"/>
+ <enum name="PROXY_TEXTURE_1D_ARRAY_EXT" value="0x8C19"/>
+ <enum name="TEXTURE_2D_ARRAY_EXT" value="0x8C1A"/>
+ <enum name="PROXY_TEXTURE_2D_ARRAY_EXT" value="0x8C1B"/>
+
+ <enum name="TEXTURE_BINDING_1D_ARRAY_EXT" count="1" value="0x8C1C">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <enum name="TEXTURE_BINDING_2D_ARRAY_EXT" count="1" value="0x8C1D">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <enum name="MAX_ARRAY_TEXTURE_LAYERS_EXT" count="1" value="0x88FF">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <enum name="COMPARE_REF_DEPTH_TO_TEXTURE_EXT" count="1" value="0x884E">
+ <size name="Get" mode="get"/>
+ </enum>
+
+ <enum name="FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT" count="1" value="0x8CD4">
+ <size name="GetFramebufferAttachmentParameterivEXT" mode="get"/>
+ </enum>
+
+ <function name="FramebufferTextureLayerEXT" offset="assign">
+ <param name="target" type="GLenum"/>
+ <param name="attachment" type="GLenum"/>
+ <param name="texture" type="GLuint"/>
+ <param name="level" type="GLint"/>
+ <param name="layer" type="GLint"/>
+ </function>
+</category>
+
+</OpenGLAPI>
diff --git a/src/mesa/glapi/Makefile b/src/mesa/glapi/Makefile
index adc53d9249..22f65b74c2 100644
--- a/src/mesa/glapi/Makefile
+++ b/src/mesa/glapi/Makefile
@@ -47,7 +47,15 @@ SERVER_OUTPUTS = \
API_XML = gl_API.xml \
EXT_framebuffer_object.xml \
- APPLE_vertex_array_object.xml
+ ARB_copy_buffer.xml \
+ ARB_depth_clamp.xml \
+ ARB_framebuffer_object.xml \
+ ARB_map_buffer_range.xml \
+ ARB_seamless_cube_map.xml \
+ ARB_sync.xml \
+ ARB_vertex_array_object.xml \
+ APPLE_vertex_array_object.xml \
+ EXT_provoking_vertex.xml
COMMON = gl_XML.py glX_XML.py license.py $(API_XML) typeexpr.py
COMMON_GLX = $(COMMON) glX_API.xml glX_XML.py glX_proto_common.py
diff --git a/src/mesa/glapi/descrip.mms b/src/mesa/glapi/descrip.mms
deleted file mode 100644
index ee96baa6fc..0000000000
--- a/src/mesa/glapi/descrip.mms
+++ /dev/null
@@ -1,39 +0,0 @@
-# Makefile for core library for VMS
-# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
-# Last revision : 29 September 2008
-
-.first
- define gl [---.include.gl]
- define main [-.main]
-
-.include [---]mms-config.
-
-##### MACROS #####
-
-VPATH = RCS
-
-INCDIR = [---.include],[-.main]
-LIBDIR = [---.lib]
-CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
-
-SOURCES = glapi.c glthread.c glapi_getproc.c
-
-OBJECTS = glapi.obj,glthread.obj,glapi_getproc.obj
-
-##### RULES #####
-
-VERSION=Mesa V3.4
-
-##### TARGETS #####
-# Make the library
-$(LIBDIR)$(GL_LIB) : $(OBJECTS)
- @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
-
-clean :
- purge
- delete *.obj;*
-
-glapi.obj : glapi.c
-
-glthread.obj : glthread.c
-glapi_getproc.obj : glapi_getproc.c
diff --git a/src/mesa/glapi/dispatch.h b/src/mesa/glapi/dispatch.h
index f019aa6aaf..efbd56fa71 100644
--- a/src/mesa/glapi/dispatch.h
+++ b/src/mesa/glapi/dispatch.h
@@ -1743,6 +1743,54 @@
#define CALL_DrawBuffersARB(disp, parameters) (*((disp)->DrawBuffersARB)) parameters
#define GET_DrawBuffersARB(disp) ((disp)->DrawBuffersARB)
#define SET_DrawBuffersARB(disp, fn) ((disp)->DrawBuffersARB = fn)
+#define CALL_RenderbufferStorageMultisample(disp, parameters) (*((disp)->RenderbufferStorageMultisample)) parameters
+#define GET_RenderbufferStorageMultisample(disp) ((disp)->RenderbufferStorageMultisample)
+#define SET_RenderbufferStorageMultisample(disp, fn) ((disp)->RenderbufferStorageMultisample = fn)
+#define CALL_FlushMappedBufferRange(disp, parameters) (*((disp)->FlushMappedBufferRange)) parameters
+#define GET_FlushMappedBufferRange(disp) ((disp)->FlushMappedBufferRange)
+#define SET_FlushMappedBufferRange(disp, fn) ((disp)->FlushMappedBufferRange = fn)
+#define CALL_MapBufferRange(disp, parameters) (*((disp)->MapBufferRange)) parameters
+#define GET_MapBufferRange(disp) ((disp)->MapBufferRange)
+#define SET_MapBufferRange(disp, fn) ((disp)->MapBufferRange = fn)
+#define CALL_BindVertexArray(disp, parameters) (*((disp)->BindVertexArray)) parameters
+#define GET_BindVertexArray(disp) ((disp)->BindVertexArray)
+#define SET_BindVertexArray(disp, fn) ((disp)->BindVertexArray = fn)
+#define CALL_GenVertexArrays(disp, parameters) (*((disp)->GenVertexArrays)) parameters
+#define GET_GenVertexArrays(disp) ((disp)->GenVertexArrays)
+#define SET_GenVertexArrays(disp, fn) ((disp)->GenVertexArrays = fn)
+#define CALL_CopyBufferSubData(disp, parameters) (*((disp)->CopyBufferSubData)) parameters
+#define GET_CopyBufferSubData(disp) ((disp)->CopyBufferSubData)
+#define SET_CopyBufferSubData(disp, fn) ((disp)->CopyBufferSubData = fn)
+#define CALL_ClientWaitSync(disp, parameters) (*((disp)->ClientWaitSync)) parameters
+#define GET_ClientWaitSync(disp) ((disp)->ClientWaitSync)
+#define SET_ClientWaitSync(disp, fn) ((disp)->ClientWaitSync = fn)
+#define CALL_DeleteSync(disp, parameters) (*((disp)->DeleteSync)) parameters
+#define GET_DeleteSync(disp) ((disp)->DeleteSync)
+#define SET_DeleteSync(disp, fn) ((disp)->DeleteSync = fn)
+#define CALL_FenceSync(disp, parameters) (*((disp)->FenceSync)) parameters
+#define GET_FenceSync(disp) ((disp)->FenceSync)
+#define SET_FenceSync(disp, fn) ((disp)->FenceSync = fn)
+#define CALL_GetInteger64v(disp, parameters) (*((disp)->GetInteger64v)) parameters
+#define GET_GetInteger64v(disp) ((disp)->GetInteger64v)
+#define SET_GetInteger64v(disp, fn) ((disp)->GetInteger64v = fn)
+#define CALL_GetSynciv(disp, parameters) (*((disp)->GetSynciv)) parameters
+#define GET_GetSynciv(disp) ((disp)->GetSynciv)
+#define SET_GetSynciv(disp, fn) ((disp)->GetSynciv = fn)
+#define CALL_IsSync(disp, parameters) (*((disp)->IsSync)) parameters
+#define GET_IsSync(disp) ((disp)->IsSync)
+#define SET_IsSync(disp, fn) ((disp)->IsSync = fn)
+#define CALL_WaitSync(disp, parameters) (*((disp)->WaitSync)) parameters
+#define GET_WaitSync(disp) ((disp)->WaitSync)
+#define SET_WaitSync(disp, fn) ((disp)->WaitSync = fn)
+#define CALL_DrawElementsBaseVertex(disp, parameters) (*((disp)->DrawElementsBaseVertex)) parameters
+#define GET_DrawElementsBaseVertex(disp) ((disp)->DrawElementsBaseVertex)
+#define SET_DrawElementsBaseVertex(disp, fn) ((disp)->DrawElementsBaseVertex = fn)
+#define CALL_DrawRangeElementsBaseVertex(disp, parameters) (*((disp)->DrawRangeElementsBaseVertex)) parameters
+#define GET_DrawRangeElementsBaseVertex(disp) ((disp)->DrawRangeElementsBaseVertex)
+#define SET_DrawRangeElementsBaseVertex(disp, fn) ((disp)->DrawRangeElementsBaseVertex = fn)
+#define CALL_MultiDrawElementsBaseVertex(disp, parameters) (*((disp)->MultiDrawElementsBaseVertex)) parameters
+#define GET_MultiDrawElementsBaseVertex(disp) ((disp)->MultiDrawElementsBaseVertex)
+#define SET_MultiDrawElementsBaseVertex(disp, fn) ((disp)->MultiDrawElementsBaseVertex = fn)
#define CALL_PolygonOffsetEXT(disp, parameters) (*((disp)->PolygonOffsetEXT)) parameters
#define GET_PolygonOffsetEXT(disp) ((disp)->PolygonOffsetEXT)
#define SET_PolygonOffsetEXT(disp, fn) ((disp)->PolygonOffsetEXT = fn)
@@ -2211,6 +2259,18 @@
#define CALL_VertexAttribs4ubvNV(disp, parameters) (*((disp)->VertexAttribs4ubvNV)) parameters
#define GET_VertexAttribs4ubvNV(disp) ((disp)->VertexAttribs4ubvNV)
#define SET_VertexAttribs4ubvNV(disp, fn) ((disp)->VertexAttribs4ubvNV = fn)
+#define CALL_GetTexBumpParameterfvATI(disp, parameters) (*((disp)->GetTexBumpParameterfvATI)) parameters
+#define GET_GetTexBumpParameterfvATI(disp) ((disp)->GetTexBumpParameterfvATI)
+#define SET_GetTexBumpParameterfvATI(disp, fn) ((disp)->GetTexBumpParameterfvATI = fn)
+#define CALL_GetTexBumpParameterivATI(disp, parameters) (*((disp)->GetTexBumpParameterivATI)) parameters
+#define GET_GetTexBumpParameterivATI(disp) ((disp)->GetTexBumpParameterivATI)
+#define SET_GetTexBumpParameterivATI(disp, fn) ((disp)->GetTexBumpParameterivATI = fn)
+#define CALL_TexBumpParameterfvATI(disp, parameters) (*((disp)->TexBumpParameterfvATI)) parameters
+#define GET_TexBumpParameterfvATI(disp) ((disp)->TexBumpParameterfvATI)
+#define SET_TexBumpParameterfvATI(disp, fn) ((disp)->TexBumpParameterfvATI = fn)
+#define CALL_TexBumpParameterivATI(disp, parameters) (*((disp)->TexBumpParameterivATI)) parameters
+#define GET_TexBumpParameterivATI(disp) ((disp)->TexBumpParameterivATI)
+#define SET_TexBumpParameterivATI(disp, fn) ((disp)->TexBumpParameterivATI = fn)
#define CALL_AlphaFragmentOp1ATI(disp, parameters) (*((disp)->AlphaFragmentOp1ATI)) parameters
#define GET_AlphaFragmentOp1ATI(disp) ((disp)->AlphaFragmentOp1ATI)
#define SET_AlphaFragmentOp1ATI(disp, fn) ((disp)->AlphaFragmentOp1ATI = fn)
@@ -2352,9 +2412,24 @@
#define CALL_BlitFramebufferEXT(disp, parameters) (*((disp)->BlitFramebufferEXT)) parameters
#define GET_BlitFramebufferEXT(disp) ((disp)->BlitFramebufferEXT)
#define SET_BlitFramebufferEXT(disp, fn) ((disp)->BlitFramebufferEXT = fn)
+#define CALL_BufferParameteriAPPLE(disp, parameters) (*((disp)->BufferParameteriAPPLE)) parameters
+#define GET_BufferParameteriAPPLE(disp) ((disp)->BufferParameteriAPPLE)
+#define SET_BufferParameteriAPPLE(disp, fn) ((disp)->BufferParameteriAPPLE = fn)
+#define CALL_FlushMappedBufferRangeAPPLE(disp, parameters) (*((disp)->FlushMappedBufferRangeAPPLE)) parameters
+#define GET_FlushMappedBufferRangeAPPLE(disp) ((disp)->FlushMappedBufferRangeAPPLE)
+#define SET_FlushMappedBufferRangeAPPLE(disp, fn) ((disp)->FlushMappedBufferRangeAPPLE = fn)
#define CALL_FramebufferTextureLayerEXT(disp, parameters) (*((disp)->FramebufferTextureLayerEXT)) parameters
#define GET_FramebufferTextureLayerEXT(disp) ((disp)->FramebufferTextureLayerEXT)
#define SET_FramebufferTextureLayerEXT(disp, fn) ((disp)->FramebufferTextureLayerEXT = fn)
+#define CALL_ProvokingVertexEXT(disp, parameters) (*((disp)->ProvokingVertexEXT)) parameters
+#define GET_ProvokingVertexEXT(disp) ((disp)->ProvokingVertexEXT)
+#define SET_ProvokingVertexEXT(disp, fn) ((disp)->ProvokingVertexEXT = fn)
+#define CALL_GetTexParameterPointervAPPLE(disp, parameters) (*((disp)->GetTexParameterPointervAPPLE)) parameters
+#define GET_GetTexParameterPointervAPPLE(disp) ((disp)->GetTexParameterPointervAPPLE)
+#define SET_GetTexParameterPointervAPPLE(disp, fn) ((disp)->GetTexParameterPointervAPPLE = fn)
+#define CALL_TextureRangeAPPLE(disp, parameters) (*((disp)->TextureRangeAPPLE)) parameters
+#define GET_TextureRangeAPPLE(disp) ((disp)->TextureRangeAPPLE)
+#define SET_TextureRangeAPPLE(disp, fn) ((disp)->TextureRangeAPPLE = fn)
#define CALL_StencilFuncSeparateATI(disp, parameters) (*((disp)->StencilFuncSeparateATI)) parameters
#define GET_StencilFuncSeparateATI(disp) ((disp)->StencilFuncSeparateATI)
#define SET_StencilFuncSeparateATI(disp, fn) ((disp)->StencilFuncSeparateATI = fn)
@@ -2373,7 +2448,7 @@
#else
-#define driDispatchRemapTable_size 362
+#define driDispatchRemapTable_size 387
extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
#define AttachShader_remap_index 0
@@ -2529,215 +2604,240 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
#define GetActiveAttribARB_remap_index 150
#define GetAttribLocationARB_remap_index 151
#define DrawBuffersARB_remap_index 152
-#define PolygonOffsetEXT_remap_index 153
-#define GetPixelTexGenParameterfvSGIS_remap_index 154
-#define GetPixelTexGenParameterivSGIS_remap_index 155
-#define PixelTexGenParameterfSGIS_remap_index 156
-#define PixelTexGenParameterfvSGIS_remap_index 157
-#define PixelTexGenParameteriSGIS_remap_index 158
-#define PixelTexGenParameterivSGIS_remap_index 159
-#define SampleMaskSGIS_remap_index 160
-#define SamplePatternSGIS_remap_index 161
-#define ColorPointerEXT_remap_index 162
-#define EdgeFlagPointerEXT_remap_index 163
-#define IndexPointerEXT_remap_index 164
-#define NormalPointerEXT_remap_index 165
-#define TexCoordPointerEXT_remap_index 166
-#define VertexPointerEXT_remap_index 167
-#define PointParameterfEXT_remap_index 168
-#define PointParameterfvEXT_remap_index 169
-#define LockArraysEXT_remap_index 170
-#define UnlockArraysEXT_remap_index 171
-#define CullParameterdvEXT_remap_index 172
-#define CullParameterfvEXT_remap_index 173
-#define SecondaryColor3bEXT_remap_index 174
-#define SecondaryColor3bvEXT_remap_index 175
-#define SecondaryColor3dEXT_remap_index 176
-#define SecondaryColor3dvEXT_remap_index 177
-#define SecondaryColor3fEXT_remap_index 178
-#define SecondaryColor3fvEXT_remap_index 179
-#define SecondaryColor3iEXT_remap_index 180
-#define SecondaryColor3ivEXT_remap_index 181
-#define SecondaryColor3sEXT_remap_index 182
-#define SecondaryColor3svEXT_remap_index 183
-#define SecondaryColor3ubEXT_remap_index 184
-#define SecondaryColor3ubvEXT_remap_index 185
-#define SecondaryColor3uiEXT_remap_index 186
-#define SecondaryColor3uivEXT_remap_index 187
-#define SecondaryColor3usEXT_remap_index 188
-#define SecondaryColor3usvEXT_remap_index 189
-#define SecondaryColorPointerEXT_remap_index 190
-#define MultiDrawArraysEXT_remap_index 191
-#define MultiDrawElementsEXT_remap_index 192
-#define FogCoordPointerEXT_remap_index 193
-#define FogCoorddEXT_remap_index 194
-#define FogCoorddvEXT_remap_index 195
-#define FogCoordfEXT_remap_index 196
-#define FogCoordfvEXT_remap_index 197
-#define PixelTexGenSGIX_remap_index 198
-#define BlendFuncSeparateEXT_remap_index 199
-#define FlushVertexArrayRangeNV_remap_index 200
-#define VertexArrayRangeNV_remap_index 201
-#define CombinerInputNV_remap_index 202
-#define CombinerOutputNV_remap_index 203
-#define CombinerParameterfNV_remap_index 204
-#define CombinerParameterfvNV_remap_index 205
-#define CombinerParameteriNV_remap_index 206
-#define CombinerParameterivNV_remap_index 207
-#define FinalCombinerInputNV_remap_index 208
-#define GetCombinerInputParameterfvNV_remap_index 209
-#define GetCombinerInputParameterivNV_remap_index 210
-#define GetCombinerOutputParameterfvNV_remap_index 211
-#define GetCombinerOutputParameterivNV_remap_index 212
-#define GetFinalCombinerInputParameterfvNV_remap_index 213
-#define GetFinalCombinerInputParameterivNV_remap_index 214
-#define ResizeBuffersMESA_remap_index 215
-#define WindowPos2dMESA_remap_index 216
-#define WindowPos2dvMESA_remap_index 217
-#define WindowPos2fMESA_remap_index 218
-#define WindowPos2fvMESA_remap_index 219
-#define WindowPos2iMESA_remap_index 220
-#define WindowPos2ivMESA_remap_index 221
-#define WindowPos2sMESA_remap_index 222
-#define WindowPos2svMESA_remap_index 223
-#define WindowPos3dMESA_remap_index 224
-#define WindowPos3dvMESA_remap_index 225
-#define WindowPos3fMESA_remap_index 226
-#define WindowPos3fvMESA_remap_index 227
-#define WindowPos3iMESA_remap_index 228
-#define WindowPos3ivMESA_remap_index 229
-#define WindowPos3sMESA_remap_index 230
-#define WindowPos3svMESA_remap_index 231
-#define WindowPos4dMESA_remap_index 232
-#define WindowPos4dvMESA_remap_index 233
-#define WindowPos4fMESA_remap_index 234
-#define WindowPos4fvMESA_remap_index 235
-#define WindowPos4iMESA_remap_index 236
-#define WindowPos4ivMESA_remap_index 237
-#define WindowPos4sMESA_remap_index 238
-#define WindowPos4svMESA_remap_index 239
-#define MultiModeDrawArraysIBM_remap_index 240
-#define MultiModeDrawElementsIBM_remap_index 241
-#define DeleteFencesNV_remap_index 242
-#define FinishFenceNV_remap_index 243
-#define GenFencesNV_remap_index 244
-#define GetFenceivNV_remap_index 245
-#define IsFenceNV_remap_index 246
-#define SetFenceNV_remap_index 247
-#define TestFenceNV_remap_index 248
-#define AreProgramsResidentNV_remap_index 249
-#define BindProgramNV_remap_index 250
-#define DeleteProgramsNV_remap_index 251
-#define ExecuteProgramNV_remap_index 252
-#define GenProgramsNV_remap_index 253
-#define GetProgramParameterdvNV_remap_index 254
-#define GetProgramParameterfvNV_remap_index 255
-#define GetProgramStringNV_remap_index 256
-#define GetProgramivNV_remap_index 257
-#define GetTrackMatrixivNV_remap_index 258
-#define GetVertexAttribPointervNV_remap_index 259
-#define GetVertexAttribdvNV_remap_index 260
-#define GetVertexAttribfvNV_remap_index 261
-#define GetVertexAttribivNV_remap_index 262
-#define IsProgramNV_remap_index 263
-#define LoadProgramNV_remap_index 264
-#define ProgramParameters4dvNV_remap_index 265
-#define ProgramParameters4fvNV_remap_index 266
-#define RequestResidentProgramsNV_remap_index 267
-#define TrackMatrixNV_remap_index 268
-#define VertexAttrib1dNV_remap_index 269
-#define VertexAttrib1dvNV_remap_index 270
-#define VertexAttrib1fNV_remap_index 271
-#define VertexAttrib1fvNV_remap_index 272
-#define VertexAttrib1sNV_remap_index 273
-#define VertexAttrib1svNV_remap_index 274
-#define VertexAttrib2dNV_remap_index 275
-#define VertexAttrib2dvNV_remap_index 276
-#define VertexAttrib2fNV_remap_index 277
-#define VertexAttrib2fvNV_remap_index 278
-#define VertexAttrib2sNV_remap_index 279
-#define VertexAttrib2svNV_remap_index 280
-#define VertexAttrib3dNV_remap_index 281
-#define VertexAttrib3dvNV_remap_index 282
-#define VertexAttrib3fNV_remap_index 283
-#define VertexAttrib3fvNV_remap_index 284
-#define VertexAttrib3sNV_remap_index 285
-#define VertexAttrib3svNV_remap_index 286
-#define VertexAttrib4dNV_remap_index 287
-#define VertexAttrib4dvNV_remap_index 288
-#define VertexAttrib4fNV_remap_index 289
-#define VertexAttrib4fvNV_remap_index 290
-#define VertexAttrib4sNV_remap_index 291
-#define VertexAttrib4svNV_remap_index 292
-#define VertexAttrib4ubNV_remap_index 293
-#define VertexAttrib4ubvNV_remap_index 294
-#define VertexAttribPointerNV_remap_index 295
-#define VertexAttribs1dvNV_remap_index 296
-#define VertexAttribs1fvNV_remap_index 297
-#define VertexAttribs1svNV_remap_index 298
-#define VertexAttribs2dvNV_remap_index 299
-#define VertexAttribs2fvNV_remap_index 300
-#define VertexAttribs2svNV_remap_index 301
-#define VertexAttribs3dvNV_remap_index 302
-#define VertexAttribs3fvNV_remap_index 303
-#define VertexAttribs3svNV_remap_index 304
-#define VertexAttribs4dvNV_remap_index 305
-#define VertexAttribs4fvNV_remap_index 306
-#define VertexAttribs4svNV_remap_index 307
-#define VertexAttribs4ubvNV_remap_index 308
-#define AlphaFragmentOp1ATI_remap_index 309
-#define AlphaFragmentOp2ATI_remap_index 310
-#define AlphaFragmentOp3ATI_remap_index 311
-#define BeginFragmentShaderATI_remap_index 312
-#define BindFragmentShaderATI_remap_index 313
-#define ColorFragmentOp1ATI_remap_index 314
-#define ColorFragmentOp2ATI_remap_index 315
-#define ColorFragmentOp3ATI_remap_index 316
-#define DeleteFragmentShaderATI_remap_index 317
-#define EndFragmentShaderATI_remap_index 318
-#define GenFragmentShadersATI_remap_index 319
-#define PassTexCoordATI_remap_index 320
-#define SampleMapATI_remap_index 321
-#define SetFragmentShaderConstantATI_remap_index 322
-#define PointParameteriNV_remap_index 323
-#define PointParameterivNV_remap_index 324
-#define ActiveStencilFaceEXT_remap_index 325
-#define BindVertexArrayAPPLE_remap_index 326
-#define DeleteVertexArraysAPPLE_remap_index 327
-#define GenVertexArraysAPPLE_remap_index 328
-#define IsVertexArrayAPPLE_remap_index 329
-#define GetProgramNamedParameterdvNV_remap_index 330
-#define GetProgramNamedParameterfvNV_remap_index 331
-#define ProgramNamedParameter4dNV_remap_index 332
-#define ProgramNamedParameter4dvNV_remap_index 333
-#define ProgramNamedParameter4fNV_remap_index 334
-#define ProgramNamedParameter4fvNV_remap_index 335
-#define DepthBoundsEXT_remap_index 336
-#define BlendEquationSeparateEXT_remap_index 337
-#define BindFramebufferEXT_remap_index 338
-#define BindRenderbufferEXT_remap_index 339
-#define CheckFramebufferStatusEXT_remap_index 340
-#define DeleteFramebuffersEXT_remap_index 341
-#define DeleteRenderbuffersEXT_remap_index 342
-#define FramebufferRenderbufferEXT_remap_index 343
-#define FramebufferTexture1DEXT_remap_index 344
-#define FramebufferTexture2DEXT_remap_index 345
-#define FramebufferTexture3DEXT_remap_index 346
-#define GenFramebuffersEXT_remap_index 347
-#define GenRenderbuffersEXT_remap_index 348
-#define GenerateMipmapEXT_remap_index 349
-#define GetFramebufferAttachmentParameterivEXT_remap_index 350
-#define GetRenderbufferParameterivEXT_remap_index 351
-#define IsFramebufferEXT_remap_index 352
-#define IsRenderbufferEXT_remap_index 353
-#define RenderbufferStorageEXT_remap_index 354
-#define BlitFramebufferEXT_remap_index 355
-#define FramebufferTextureLayerEXT_remap_index 356
-#define StencilFuncSeparateATI_remap_index 357
-#define ProgramEnvParameters4fvEXT_remap_index 358
-#define ProgramLocalParameters4fvEXT_remap_index 359
-#define GetQueryObjecti64vEXT_remap_index 360
-#define GetQueryObjectui64vEXT_remap_index 361
+#define RenderbufferStorageMultisample_remap_index 153
+#define FlushMappedBufferRange_remap_index 154
+#define MapBufferRange_remap_index 155
+#define BindVertexArray_remap_index 156
+#define GenVertexArrays_remap_index 157
+#define CopyBufferSubData_remap_index 158
+#define ClientWaitSync_remap_index 159
+#define DeleteSync_remap_index 160
+#define FenceSync_remap_index 161
+#define GetInteger64v_remap_index 162
+#define GetSynciv_remap_index 163
+#define IsSync_remap_index 164
+#define WaitSync_remap_index 165
+#define DrawElementsBaseVertex_remap_index 166
+#define DrawRangeElementsBaseVertex_remap_index 167
+#define MultiDrawElementsBaseVertex_remap_index 168
+#define PolygonOffsetEXT_remap_index 169
+#define GetPixelTexGenParameterfvSGIS_remap_index 170
+#define GetPixelTexGenParameterivSGIS_remap_index 171
+#define PixelTexGenParameterfSGIS_remap_index 172
+#define PixelTexGenParameterfvSGIS_remap_index 173
+#define PixelTexGenParameteriSGIS_remap_index 174
+#define PixelTexGenParameterivSGIS_remap_index 175
+#define SampleMaskSGIS_remap_index 176
+#define SamplePatternSGIS_remap_index 177
+#define ColorPointerEXT_remap_index 178
+#define EdgeFlagPointerEXT_remap_index 179
+#define IndexPointerEXT_remap_index 180
+#define NormalPointerEXT_remap_index 181
+#define TexCoordPointerEXT_remap_index 182
+#define VertexPointerEXT_remap_index 183
+#define PointParameterfEXT_remap_index 184
+#define PointParameterfvEXT_remap_index 185
+#define LockArraysEXT_remap_index 186
+#define UnlockArraysEXT_remap_index 187
+#define CullParameterdvEXT_remap_index 188
+#define CullParameterfvEXT_remap_index 189
+#define SecondaryColor3bEXT_remap_index 190
+#define SecondaryColor3bvEXT_remap_index 191
+#define SecondaryColor3dEXT_remap_index 192
+#define SecondaryColor3dvEXT_remap_index 193
+#define SecondaryColor3fEXT_remap_index 194
+#define SecondaryColor3fvEXT_remap_index 195
+#define SecondaryColor3iEXT_remap_index 196
+#define SecondaryColor3ivEXT_remap_index 197
+#define SecondaryColor3sEXT_remap_index 198
+#define SecondaryColor3svEXT_remap_index 199
+#define SecondaryColor3ubEXT_remap_index 200
+#define SecondaryColor3ubvEXT_remap_index 201
+#define SecondaryColor3uiEXT_remap_index 202
+#define SecondaryColor3uivEXT_remap_index 203
+#define SecondaryColor3usEXT_remap_index 204
+#define SecondaryColor3usvEXT_remap_index 205
+#define SecondaryColorPointerEXT_remap_index 206
+#define MultiDrawArraysEXT_remap_index 207
+#define MultiDrawElementsEXT_remap_index 208
+#define FogCoordPointerEXT_remap_index 209
+#define FogCoorddEXT_remap_index 210
+#define FogCoorddvEXT_remap_index 211
+#define FogCoordfEXT_remap_index 212
+#define FogCoordfvEXT_remap_index 213
+#define PixelTexGenSGIX_remap_index 214
+#define BlendFuncSeparateEXT_remap_index 215
+#define FlushVertexArrayRangeNV_remap_index 216
+#define VertexArrayRangeNV_remap_index 217
+#define CombinerInputNV_remap_index 218
+#define CombinerOutputNV_remap_index 219
+#define CombinerParameterfNV_remap_index 220
+#define CombinerParameterfvNV_remap_index 221
+#define CombinerParameteriNV_remap_index 222
+#define CombinerParameterivNV_remap_index 223
+#define FinalCombinerInputNV_remap_index 224
+#define GetCombinerInputParameterfvNV_remap_index 225
+#define GetCombinerInputParameterivNV_remap_index 226
+#define GetCombinerOutputParameterfvNV_remap_index 227
+#define GetCombinerOutputParameterivNV_remap_index 228
+#define GetFinalCombinerInputParameterfvNV_remap_index 229
+#define GetFinalCombinerInputParameterivNV_remap_index 230
+#define ResizeBuffersMESA_remap_index 231
+#define WindowPos2dMESA_remap_index 232
+#define WindowPos2dvMESA_remap_index 233
+#define WindowPos2fMESA_remap_index 234
+#define WindowPos2fvMESA_remap_index 235
+#define WindowPos2iMESA_remap_index 236
+#define WindowPos2ivMESA_remap_index 237
+#define WindowPos2sMESA_remap_index 238
+#define WindowPos2svMESA_remap_index 239
+#define WindowPos3dMESA_remap_index 240
+#define WindowPos3dvMESA_remap_index 241
+#define WindowPos3fMESA_remap_index 242
+#define WindowPos3fvMESA_remap_index 243
+#define WindowPos3iMESA_remap_index 244
+#define WindowPos3ivMESA_remap_index 245
+#define WindowPos3sMESA_remap_index 246
+#define WindowPos3svMESA_remap_index 247
+#define WindowPos4dMESA_remap_index 248
+#define WindowPos4dvMESA_remap_index 249
+#define WindowPos4fMESA_remap_index 250
+#define WindowPos4fvMESA_remap_index 251
+#define WindowPos4iMESA_remap_index 252
+#define WindowPos4ivMESA_remap_index 253
+#define WindowPos4sMESA_remap_index 254
+#define WindowPos4svMESA_remap_index 255
+#define MultiModeDrawArraysIBM_remap_index 256
+#define MultiModeDrawElementsIBM_remap_index 257
+#define DeleteFencesNV_remap_index 258
+#define FinishFenceNV_remap_index 259
+#define GenFencesNV_remap_index 260
+#define GetFenceivNV_remap_index 261
+#define IsFenceNV_remap_index 262
+#define SetFenceNV_remap_index 263
+#define TestFenceNV_remap_index 264
+#define AreProgramsResidentNV_remap_index 265
+#define BindProgramNV_remap_index 266
+#define DeleteProgramsNV_remap_index 267
+#define ExecuteProgramNV_remap_index 268
+#define GenProgramsNV_remap_index 269
+#define GetProgramParameterdvNV_remap_index 270
+#define GetProgramParameterfvNV_remap_index 271
+#define GetProgramStringNV_remap_index 272
+#define GetProgramivNV_remap_index 273
+#define GetTrackMatrixivNV_remap_index 274
+#define GetVertexAttribPointervNV_remap_index 275
+#define GetVertexAttribdvNV_remap_index 276
+#define GetVertexAttribfvNV_remap_index 277
+#define GetVertexAttribivNV_remap_index 278
+#define IsProgramNV_remap_index 279
+#define LoadProgramNV_remap_index 280
+#define ProgramParameters4dvNV_remap_index 281
+#define ProgramParameters4fvNV_remap_index 282
+#define RequestResidentProgramsNV_remap_index 283
+#define TrackMatrixNV_remap_index 284
+#define VertexAttrib1dNV_remap_index 285
+#define VertexAttrib1dvNV_remap_index 286
+#define VertexAttrib1fNV_remap_index 287
+#define VertexAttrib1fvNV_remap_index 288
+#define VertexAttrib1sNV_remap_index 289
+#define VertexAttrib1svNV_remap_index 290
+#define VertexAttrib2dNV_remap_index 291
+#define VertexAttrib2dvNV_remap_index 292
+#define VertexAttrib2fNV_remap_index 293
+#define VertexAttrib2fvNV_remap_index 294
+#define VertexAttrib2sNV_remap_index 295
+#define VertexAttrib2svNV_remap_index 296
+#define VertexAttrib3dNV_remap_index 297
+#define VertexAttrib3dvNV_remap_index 298
+#define VertexAttrib3fNV_remap_index 299
+#define VertexAttrib3fvNV_remap_index 300
+#define VertexAttrib3sNV_remap_index 301
+#define VertexAttrib3svNV_remap_index 302
+#define VertexAttrib4dNV_remap_index 303
+#define VertexAttrib4dvNV_remap_index 304
+#define VertexAttrib4fNV_remap_index 305
+#define VertexAttrib4fvNV_remap_index 306
+#define VertexAttrib4sNV_remap_index 307
+#define VertexAttrib4svNV_remap_index 308
+#define VertexAttrib4ubNV_remap_index 309
+#define VertexAttrib4ubvNV_remap_index 310
+#define VertexAttribPointerNV_remap_index 311
+#define VertexAttribs1dvNV_remap_index 312
+#define VertexAttribs1fvNV_remap_index 313
+#define VertexAttribs1svNV_remap_index 314
+#define VertexAttribs2dvNV_remap_index 315
+#define VertexAttribs2fvNV_remap_index 316
+#define VertexAttribs2svNV_remap_index 317
+#define VertexAttribs3dvNV_remap_index 318
+#define VertexAttribs3fvNV_remap_index 319
+#define VertexAttribs3svNV_remap_index 320
+#define VertexAttribs4dvNV_remap_index 321
+#define VertexAttribs4fvNV_remap_index 322
+#define VertexAttribs4svNV_remap_index 323
+#define VertexAttribs4ubvNV_remap_index 324
+#define GetTexBumpParameterfvATI_remap_index 325
+#define GetTexBumpParameterivATI_remap_index 326
+#define TexBumpParameterfvATI_remap_index 327
+#define TexBumpParameterivATI_remap_index 328
+#define AlphaFragmentOp1ATI_remap_index 329
+#define AlphaFragmentOp2ATI_remap_index 330
+#define AlphaFragmentOp3ATI_remap_index 331
+#define BeginFragmentShaderATI_remap_index 332
+#define BindFragmentShaderATI_remap_index 333
+#define ColorFragmentOp1ATI_remap_index 334
+#define ColorFragmentOp2ATI_remap_index 335
+#define ColorFragmentOp3ATI_remap_index 336
+#define DeleteFragmentShaderATI_remap_index 337
+#define EndFragmentShaderATI_remap_index 338
+#define GenFragmentShadersATI_remap_index 339
+#define PassTexCoordATI_remap_index 340
+#define SampleMapATI_remap_index 341
+#define SetFragmentShaderConstantATI_remap_index 342
+#define PointParameteriNV_remap_index 343
+#define PointParameterivNV_remap_index 344
+#define ActiveStencilFaceEXT_remap_index 345
+#define BindVertexArrayAPPLE_remap_index 346
+#define DeleteVertexArraysAPPLE_remap_index 347
+#define GenVertexArraysAPPLE_remap_index 348
+#define IsVertexArrayAPPLE_remap_index 349
+#define GetProgramNamedParameterdvNV_remap_index 350
+#define GetProgramNamedParameterfvNV_remap_index 351
+#define ProgramNamedParameter4dNV_remap_index 352
+#define ProgramNamedParameter4dvNV_remap_index 353
+#define ProgramNamedParameter4fNV_remap_index 354
+#define ProgramNamedParameter4fvNV_remap_index 355
+#define DepthBoundsEXT_remap_index 356
+#define BlendEquationSeparateEXT_remap_index 357
+#define BindFramebufferEXT_remap_index 358
+#define BindRenderbufferEXT_remap_index 359
+#define CheckFramebufferStatusEXT_remap_index 360
+#define DeleteFramebuffersEXT_remap_index 361
+#define DeleteRenderbuffersEXT_remap_index 362
+#define FramebufferRenderbufferEXT_remap_index 363
+#define FramebufferTexture1DEXT_remap_index 364
+#define FramebufferTexture2DEXT_remap_index 365
+#define FramebufferTexture3DEXT_remap_index 366
+#define GenFramebuffersEXT_remap_index 367
+#define GenRenderbuffersEXT_remap_index 368
+#define GenerateMipmapEXT_remap_index 369
+#define GetFramebufferAttachmentParameterivEXT_remap_index 370
+#define GetRenderbufferParameterivEXT_remap_index 371
+#define IsFramebufferEXT_remap_index 372
+#define IsRenderbufferEXT_remap_index 373
+#define RenderbufferStorageEXT_remap_index 374
+#define BlitFramebufferEXT_remap_index 375
+#define BufferParameteriAPPLE_remap_index 376
+#define FlushMappedBufferRangeAPPLE_remap_index 377
+#define FramebufferTextureLayerEXT_remap_index 378
+#define ProvokingVertexEXT_remap_index 379
+#define GetTexParameterPointervAPPLE_remap_index 380
+#define TextureRangeAPPLE_remap_index 381
+#define StencilFuncSeparateATI_remap_index 382
+#define ProgramEnvParameters4fvEXT_remap_index 383
+#define ProgramLocalParameters4fvEXT_remap_index 384
+#define GetQueryObjecti64vEXT_remap_index 385
+#define GetQueryObjectui64vEXT_remap_index 386
#define CALL_AttachShader(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLuint)), driDispatchRemapTable[AttachShader_remap_index], parameters)
#define GET_AttachShader(disp) GET_by_offset(disp, driDispatchRemapTable[AttachShader_remap_index])
@@ -3198,6 +3298,54 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
#define CALL_DrawBuffersARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLenum *)), driDispatchRemapTable[DrawBuffersARB_remap_index], parameters)
#define GET_DrawBuffersARB(disp) GET_by_offset(disp, driDispatchRemapTable[DrawBuffersARB_remap_index])
#define SET_DrawBuffersARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DrawBuffersARB_remap_index], fn)
+#define CALL_RenderbufferStorageMultisample(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)), driDispatchRemapTable[RenderbufferStorageMultisample_remap_index], parameters)
+#define GET_RenderbufferStorageMultisample(disp) GET_by_offset(disp, driDispatchRemapTable[RenderbufferStorageMultisample_remap_index])
+#define SET_RenderbufferStorageMultisample(disp, fn) SET_by_offset(disp, driDispatchRemapTable[RenderbufferStorageMultisample_remap_index], fn)
+#define CALL_FlushMappedBufferRange(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLintptr, GLsizeiptr)), driDispatchRemapTable[FlushMappedBufferRange_remap_index], parameters)
+#define GET_FlushMappedBufferRange(disp) GET_by_offset(disp, driDispatchRemapTable[FlushMappedBufferRange_remap_index])
+#define SET_FlushMappedBufferRange(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FlushMappedBufferRange_remap_index], fn)
+#define CALL_MapBufferRange(disp, parameters) CALL_by_offset(disp, (GLvoid * (GLAPIENTRYP)(GLenum, GLintptr, GLsizeiptr, GLbitfield)), driDispatchRemapTable[MapBufferRange_remap_index], parameters)
+#define GET_MapBufferRange(disp) GET_by_offset(disp, driDispatchRemapTable[MapBufferRange_remap_index])
+#define SET_MapBufferRange(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MapBufferRange_remap_index], fn)
+#define CALL_BindVertexArray(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[BindVertexArray_remap_index], parameters)
+#define GET_BindVertexArray(disp) GET_by_offset(disp, driDispatchRemapTable[BindVertexArray_remap_index])
+#define SET_BindVertexArray(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BindVertexArray_remap_index], fn)
+#define CALL_GenVertexArrays(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLuint *)), driDispatchRemapTable[GenVertexArrays_remap_index], parameters)
+#define GET_GenVertexArrays(disp) GET_by_offset(disp, driDispatchRemapTable[GenVertexArrays_remap_index])
+#define SET_GenVertexArrays(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenVertexArrays_remap_index], fn)
+#define CALL_CopyBufferSubData(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr)), driDispatchRemapTable[CopyBufferSubData_remap_index], parameters)
+#define GET_CopyBufferSubData(disp) GET_by_offset(disp, driDispatchRemapTable[CopyBufferSubData_remap_index])
+#define SET_CopyBufferSubData(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CopyBufferSubData_remap_index], fn)
+#define CALL_ClientWaitSync(disp, parameters) CALL_by_offset(disp, (GLenum (GLAPIENTRYP)(GLsync, GLbitfield, GLuint64)), driDispatchRemapTable[ClientWaitSync_remap_index], parameters)
+#define GET_ClientWaitSync(disp) GET_by_offset(disp, driDispatchRemapTable[ClientWaitSync_remap_index])
+#define SET_ClientWaitSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ClientWaitSync_remap_index], fn)
+#define CALL_DeleteSync(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsync)), driDispatchRemapTable[DeleteSync_remap_index], parameters)
+#define GET_DeleteSync(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteSync_remap_index])
+#define SET_DeleteSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteSync_remap_index], fn)
+#define CALL_FenceSync(disp, parameters) CALL_by_offset(disp, (GLsync (GLAPIENTRYP)(GLenum, GLbitfield)), driDispatchRemapTable[FenceSync_remap_index], parameters)
+#define GET_FenceSync(disp) GET_by_offset(disp, driDispatchRemapTable[FenceSync_remap_index])
+#define SET_FenceSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FenceSync_remap_index], fn)
+#define CALL_GetInteger64v(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint64 *)), driDispatchRemapTable[GetInteger64v_remap_index], parameters)
+#define GET_GetInteger64v(disp) GET_by_offset(disp, driDispatchRemapTable[GetInteger64v_remap_index])
+#define SET_GetInteger64v(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetInteger64v_remap_index], fn)
+#define CALL_GetSynciv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsync, GLenum, GLsizei, GLsizei *, GLint *)), driDispatchRemapTable[GetSynciv_remap_index], parameters)
+#define GET_GetSynciv(disp) GET_by_offset(disp, driDispatchRemapTable[GetSynciv_remap_index])
+#define SET_GetSynciv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetSynciv_remap_index], fn)
+#define CALL_IsSync(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLsync)), driDispatchRemapTable[IsSync_remap_index], parameters)
+#define GET_IsSync(disp) GET_by_offset(disp, driDispatchRemapTable[IsSync_remap_index])
+#define SET_IsSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsSync_remap_index], fn)
+#define CALL_WaitSync(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsync, GLbitfield, GLuint64)), driDispatchRemapTable[WaitSync_remap_index], parameters)
+#define GET_WaitSync(disp) GET_by_offset(disp, driDispatchRemapTable[WaitSync_remap_index])
+#define SET_WaitSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WaitSync_remap_index], fn)
+#define CALL_DrawElementsBaseVertex(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLsizei, GLenum, const GLvoid *, GLint)), driDispatchRemapTable[DrawElementsBaseVertex_remap_index], parameters)
+#define GET_DrawElementsBaseVertex(disp) GET_by_offset(disp, driDispatchRemapTable[DrawElementsBaseVertex_remap_index])
+#define SET_DrawElementsBaseVertex(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DrawElementsBaseVertex_remap_index], fn)
+#define CALL_DrawRangeElementsBaseVertex(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *, GLint)), driDispatchRemapTable[DrawRangeElementsBaseVertex_remap_index], parameters)
+#define GET_DrawRangeElementsBaseVertex(disp) GET_by_offset(disp, driDispatchRemapTable[DrawRangeElementsBaseVertex_remap_index])
+#define SET_DrawRangeElementsBaseVertex(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DrawRangeElementsBaseVertex_remap_index], fn)
+#define CALL_MultiDrawElementsBaseVertex(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLsizei *, GLenum, const GLvoid **, GLsizei, const GLint *)), driDispatchRemapTable[MultiDrawElementsBaseVertex_remap_index], parameters)
+#define GET_MultiDrawElementsBaseVertex(disp) GET_by_offset(disp, driDispatchRemapTable[MultiDrawElementsBaseVertex_remap_index])
+#define SET_MultiDrawElementsBaseVertex(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MultiDrawElementsBaseVertex_remap_index], fn)
#define CALL_PolygonOffsetEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLfloat, GLfloat)), driDispatchRemapTable[PolygonOffsetEXT_remap_index], parameters)
#define GET_PolygonOffsetEXT(disp) GET_by_offset(disp, driDispatchRemapTable[PolygonOffsetEXT_remap_index])
#define SET_PolygonOffsetEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PolygonOffsetEXT_remap_index], fn)
@@ -3666,6 +3814,18 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
#define CALL_VertexAttribs4ubvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLubyte *)), driDispatchRemapTable[VertexAttribs4ubvNV_remap_index], parameters)
#define GET_VertexAttribs4ubvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs4ubvNV_remap_index])
#define SET_VertexAttribs4ubvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs4ubvNV_remap_index], fn)
+#define CALL_GetTexBumpParameterfvATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLfloat *)), driDispatchRemapTable[GetTexBumpParameterfvATI_remap_index], parameters)
+#define GET_GetTexBumpParameterfvATI(disp) GET_by_offset(disp, driDispatchRemapTable[GetTexBumpParameterfvATI_remap_index])
+#define SET_GetTexBumpParameterfvATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetTexBumpParameterfvATI_remap_index], fn)
+#define CALL_GetTexBumpParameterivATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint *)), driDispatchRemapTable[GetTexBumpParameterivATI_remap_index], parameters)
+#define GET_GetTexBumpParameterivATI(disp) GET_by_offset(disp, driDispatchRemapTable[GetTexBumpParameterivATI_remap_index])
+#define SET_GetTexBumpParameterivATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetTexBumpParameterivATI_remap_index], fn)
+#define CALL_TexBumpParameterfvATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLfloat *)), driDispatchRemapTable[TexBumpParameterfvATI_remap_index], parameters)
+#define GET_TexBumpParameterfvATI(disp) GET_by_offset(disp, driDispatchRemapTable[TexBumpParameterfvATI_remap_index])
+#define SET_TexBumpParameterfvATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[TexBumpParameterfvATI_remap_index], fn)
+#define CALL_TexBumpParameterivATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLint *)), driDispatchRemapTable[TexBumpParameterivATI_remap_index], parameters)
+#define GET_TexBumpParameterivATI(disp) GET_by_offset(disp, driDispatchRemapTable[TexBumpParameterivATI_remap_index])
+#define SET_TexBumpParameterivATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[TexBumpParameterivATI_remap_index], fn)
#define CALL_AlphaFragmentOp1ATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, GLuint, GLuint, GLuint)), driDispatchRemapTable[AlphaFragmentOp1ATI_remap_index], parameters)
#define GET_AlphaFragmentOp1ATI(disp) GET_by_offset(disp, driDispatchRemapTable[AlphaFragmentOp1ATI_remap_index])
#define SET_AlphaFragmentOp1ATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[AlphaFragmentOp1ATI_remap_index], fn)
@@ -3807,9 +3967,24 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
#define CALL_BlitFramebufferEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)), driDispatchRemapTable[BlitFramebufferEXT_remap_index], parameters)
#define GET_BlitFramebufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index])
#define SET_BlitFramebufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index], fn)
+#define CALL_BufferParameteriAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint)), driDispatchRemapTable[BufferParameteriAPPLE_remap_index], parameters)
+#define GET_BufferParameteriAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[BufferParameteriAPPLE_remap_index])
+#define SET_BufferParameteriAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BufferParameteriAPPLE_remap_index], fn)
+#define CALL_FlushMappedBufferRangeAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLintptr, GLsizeiptr)), driDispatchRemapTable[FlushMappedBufferRangeAPPLE_remap_index], parameters)
+#define GET_FlushMappedBufferRangeAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[FlushMappedBufferRangeAPPLE_remap_index])
+#define SET_FlushMappedBufferRangeAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FlushMappedBufferRangeAPPLE_remap_index], fn)
#define CALL_FramebufferTextureLayerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint)), driDispatchRemapTable[FramebufferTextureLayerEXT_remap_index], parameters)
#define GET_FramebufferTextureLayerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FramebufferTextureLayerEXT_remap_index])
#define SET_FramebufferTextureLayerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FramebufferTextureLayerEXT_remap_index], fn)
+#define CALL_ProvokingVertexEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[ProvokingVertexEXT_remap_index], parameters)
+#define GET_ProvokingVertexEXT(disp) GET_by_offset(disp, driDispatchRemapTable[ProvokingVertexEXT_remap_index])
+#define SET_ProvokingVertexEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProvokingVertexEXT_remap_index], fn)
+#define CALL_GetTexParameterPointervAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLvoid **)), driDispatchRemapTable[GetTexParameterPointervAPPLE_remap_index], parameters)
+#define GET_GetTexParameterPointervAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[GetTexParameterPointervAPPLE_remap_index])
+#define SET_GetTexParameterPointervAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetTexParameterPointervAPPLE_remap_index], fn)
+#define CALL_TextureRangeAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLsizei, GLvoid *)), driDispatchRemapTable[TextureRangeAPPLE_remap_index], parameters)
+#define GET_TextureRangeAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[TextureRangeAPPLE_remap_index])
+#define SET_TextureRangeAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[TextureRangeAPPLE_remap_index], fn)
#define CALL_StencilFuncSeparateATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint, GLuint)), driDispatchRemapTable[StencilFuncSeparateATI_remap_index], parameters)
#define GET_StencilFuncSeparateATI(disp) GET_by_offset(disp, driDispatchRemapTable[StencilFuncSeparateATI_remap_index])
#define SET_StencilFuncSeparateATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[StencilFuncSeparateATI_remap_index], fn)
diff --git a/src/mesa/glapi/extension_helper.py b/src/mesa/glapi/extension_helper.py
index 64f64a2fd8..3b6e2ce404 100644
--- a/src/mesa/glapi/extension_helper.py
+++ b/src/mesa/glapi/extension_helper.py
@@ -165,12 +165,14 @@ class PrintGlExtensionGlue(gl_XML.gl_print_base):
print '# define NULL 0'
print '#endif'
print ''
+ print '#if defined(IN_DRI_DRIVER)'
+ print ''
for f in api.functionIterateAll():
condition = condition_for_function(f, abi, 0)
if len(condition):
print '#if %s' % (string.join(condition, " || "))
- print 'static const char %s_names[] = ' % (f.name)
+ print 'static const char %s_names[] =' % (f.name)
parameter_signature = ''
for p in f.parameterIterator():
@@ -232,6 +234,15 @@ class PrintGlExtensionGlue(gl_XML.gl_print_base):
print '#endif'
print ''
+ print '#else /* IN_DRI_DRIVER */'
+ print ''
+ for category in keys:
+ print '#if defined(need_%s)' % (category)
+ print '#define %s_functions NULL' % (category)
+ print '#endif'
+ print ''
+ print '#endif /* IN_DRI_DRIVER */'
+ print ''
return
diff --git a/src/mesa/glapi/glX_proto_recv.py b/src/mesa/glapi/glX_proto_recv.py
index 923c1958f0..f423c6db08 100644
--- a/src/mesa/glapi/glX_proto_recv.py
+++ b/src/mesa/glapi/glX_proto_recv.py
@@ -277,7 +277,7 @@ class PrintGlxDispatchFunctions(glX_proto_common.glx_print_proto):
if param.is_image():
offset = f.offset_of( param.name )
- print '%s %s const %s = (%s) %s(pc + %s);' % (indent, type_string, param.name, type_string, cond, offset)
+ print '%s %s const %s = (%s) (%s(pc + %s));' % (indent, type_string, param.name, type_string, cond, offset)
if param.depth:
print '%s __GLXpixel3DHeader * const hdr = (__GLXpixel3DHeader *)(pc);' % (indent)
diff --git a/src/mesa/glapi/glX_proto_send.py b/src/mesa/glapi/glX_proto_send.py
index 501706acc7..daca1b767a 100644
--- a/src/mesa/glapi/glX_proto_send.py
+++ b/src/mesa/glapi/glX_proto_send.py
@@ -373,9 +373,13 @@ const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
print '{'
print ' __GLXcontext * const gc = __glXGetCurrentContext();'
print ''
+ print '#ifdef GLX_DIRECT_RENDERING'
print ' if (gc->driContext) {'
print ' %sCALL_%s(GET_DISPATCH(), (%s));' % (ret_string, func.name, func.get_called_parameter_string())
- print ' } else {'
+ print ' } else'
+ print '#endif'
+ print ' {'
+
footer = '}\n}\n'
else:
print '#define %s %d' % (func.opcode_name(), func.opcode_value())
diff --git a/src/mesa/glapi/gl_API.xml b/src/mesa/glapi/gl_API.xml
index 951fd95799..da4be14707 100644
--- a/src/mesa/glapi/gl_API.xml
+++ b/src/mesa/glapi/gl_API.xml
@@ -5039,7 +5039,7 @@
<type name="char" size="1" glx_name="CARD8"/>
- <enum name="GL_BLEND_EQUATION_RGB" value="0x8009"/>
+ <enum name="BLEND_EQUATION_RGB" value="0x8009"/>
<enum name="VERTEX_ATTRIB_ARRAY_ENABLED" value="0x8622"/>
<enum name="VERTEX_ATTRIB_ARRAY_SIZE" value="0x8623"/>
<enum name="VERTEX_ATTRIB_ARRAY_STRIDE" value="0x8624"/>
@@ -5684,29 +5684,29 @@
<!-- XXX some of the enums and functions probably need additional -->
<!-- flags/attributes. -->
- <enum name="GL_CURRENT_RASTER_SECONDARY_COLOR" value="0x845F"/>
- <enum name="GL_PIXEL_PACK_BUFFER" value="0x88EB"/>
- <enum name="GL_PIXEL_UNPACK_BUFFER" value="0x88EC"/>
- <enum name="GL_PIXEL_PACK_BUFFER_BINDING" value="0x88ED"/>
- <enum name="GL_PIXEL_UNPACK_BUFFER_BINDING" value="0x88EF"/>
- <enum name="GL_FLOAT_MAT2x3" value="0x8B65"/>
- <enum name="GL_FLOAT_MAT2x4" value="0x8B66"/>
- <enum name="GL_FLOAT_MAT3x2" value="0x8B67"/>
- <enum name="GL_FLOAT_MAT3x4" value="0x8B68"/>
- <enum name="GL_FLOAT_MAT4x2" value="0x8B69"/>
- <enum name="GL_FLOAT_MAT4x3" value="0x8B6A"/>
- <enum name="GL_SRGB" value="0x8C40"/>
- <enum name="GL_SRGB8" value="0x8C41"/>
- <enum name="GL_SRGB_ALPHA" value="0x8C42"/>
- <enum name="GL_SRGB8_ALPHA8" value="0x8C43"/>
- <enum name="GL_SLUMINANCE_ALPHA" value="0x8C44"/>
- <enum name="GL_SLUMINANCE8_ALPHA8" value="0x8C45"/>
- <enum name="GL_SLUMINANCE" value="0x8C46"/>
- <enum name="GL_SLUMINANCE8" value="0x8C47"/>
- <enum name="GL_COMPRESSED_SRGB" value="0x8C48"/>
- <enum name="GL_COMPRESSED_SRGB_ALPHA" value="0x8C49"/>
- <enum name="GL_COMPRESSED_SLUMINANCE" value="0x8C4A"/>
- <enum name="GL_COMPRESSED_SLUMINANCE_ALPHA" value="0x8C4B"/>
+ <enum name="CURRENT_RASTER_SECONDARY_COLOR" value="0x845F"/>
+ <enum name="PIXEL_PACK_BUFFER" value="0x88EB"/>
+ <enum name="PIXEL_UNPACK_BUFFER" value="0x88EC"/>
+ <enum name="PIXEL_PACK_BUFFER_BINDING" value="0x88ED"/>
+ <enum name="PIXEL_UNPACK_BUFFER_BINDING" value="0x88EF"/>
+ <enum name="FLOAT_MAT2x3" value="0x8B65"/>
+ <enum name="FLOAT_MAT2x4" value="0x8B66"/>
+ <enum name="FLOAT_MAT3x2" value="0x8B67"/>
+ <enum name="FLOAT_MAT3x4" value="0x8B68"/>
+ <enum name="FLOAT_MAT4x2" value="0x8B69"/>
+ <enum name="FLOAT_MAT4x3" value="0x8B6A"/>
+ <enum name="SRGB" value="0x8C40"/>
+ <enum name="SRGB8" value="0x8C41"/>
+ <enum name="SRGB_ALPHA" value="0x8C42"/>
+ <enum name="SRGB8_ALPHA8" value="0x8C43"/>
+ <enum name="SLUMINANCE_ALPHA" value="0x8C44"/>
+ <enum name="SLUMINANCE8_ALPHA8" value="0x8C45"/>
+ <enum name="SLUMINANCE" value="0x8C46"/>
+ <enum name="SLUMINANCE8" value="0x8C47"/>
+ <enum name="COMPRESSED_SRGB" value="0x8C48"/>
+ <enum name="COMPRESSED_SRGB_ALPHA" value="0x8C49"/>
+ <enum name="COMPRESSED_SLUMINANCE" value="0x8C4A"/>
+ <enum name="COMPRESSED_SLUMINANCE_ALPHA" value="0x8C4B"/>
<function name="UniformMatrix2x3fv" offset="assign">
<param name="location" type="GLint"/>
@@ -7946,6 +7946,23 @@
</enum>
</category>
+<xi:include href="ARB_framebuffer_object.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<xi:include href="ARB_copy_buffer.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<xi:include href="ARB_depth_clamp.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<xi:include href="ARB_map_buffer_range.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<xi:include href="ARB_vertex_array_object.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<xi:include href="ARB_sync.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<xi:include href="ARB_seamless_cube_map.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<xi:include href="ARB_draw_elements_base_vertex.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+
<!-- Non-ARB extensions sorted by extension number. -->
<category name="GL_EXT_blend_color" number="2">
@@ -11678,6 +11695,56 @@
<enum name="DEPTH_STENCIL_TO_BGRA_NV" value="0x886F"/>
</category>
+<category name="GL_ATI_envmap_bumpmap" number="244">
+ <enum name="BUMP_ROT_MATRIX_ATI" count="4" value="0x8775">
+ <size name="TexBumpParameterfv"/>
+ <size name="TexBumpParameteriv"/>
+ <size name="GetTexBumpParameterfv" mode="get"/>
+ <size name="GetTexBumpParameteriv" mode="get"/>
+ </enum>
+ <enum name="BUMP_ROT_MATRIX_SIZE_ATI" count="1" value="0x8776">
+ <size name="GetTexBumpParameterfv" mode="get"/>
+ <size name="GetTexBumpParameteriv" mode="get"/>
+ </enum>
+ <enum name="BUMP_NUM_TEX_UNITS_ATI" count="1" value="0x8777">
+ <size name="GetTexBumpParameterfv" mode="get"/>
+ <size name="GetTexBumpParameteriv" mode="get"/>
+ </enum>
+ <enum name="BUMP_TEX_UNITS_ATI" count="-1" value="0x8778">
+ <size name="GetTexBumpParameterfv" mode="get"/>
+ <size name="GetTexBumpParameteriv" mode="get"/>
+ </enum>
+ <enum name="DUDV_ATI" value="0x8779"/>
+ <enum name="DU8DV8_ATI" value="0x877A"/>
+ <enum name="BUMP_ENVMAP_ATI" value="0x877B"/>
+ <enum name="BUMP_TARGET_ATI" count="1" value="0x877C">
+ <size name="TexEnviv"/>
+ <size name="TexEnvfv"/>
+ <size name="GetTexEnviv" mode="get"/>
+ <size name="GetTexEnvfv" mode="get"/>
+ </enum>
+ <function name="TexBumpParameterfvATI" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="const GLfloat *" variable_param="pname"/>
+ <glx ignore="true"/>
+ </function>
+ <function name="TexBumpParameterivATI" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="const GLint *" variable_param="pname"/>
+ <glx ignore="true"/>
+ </function>
+ <function name="GetTexBumpParameterfvATI" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLfloat *" variable_param="pname"/>
+ <glx ignore="true"/>
+ </function>
+ <function name="GetTexBumpParameterivATI" offset="assign">
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint *" variable_param="pname"/>
+ <glx ignore="true"/>
+ </function>
+</category>
+
<category name="GL_ATI_fragment_shader" number="245">
<function name="GenFragmentShadersATI" offset="assign">
<return type="GLuint"/>
@@ -12171,6 +12238,8 @@
<xi:include href="EXT_framebuffer_object.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+<xi:include href="EXT_provoking_vertex.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
<category name="GL_EXT_framebuffer_blit" number="316">
<enum name="READ_FRAMEBUFFER_EXT" value="0x8CA8"/>
<enum name="DRAW_FRAMEBUFFER_EXT" value="0x8CA9"/>
@@ -12194,6 +12263,65 @@
</function>
</category>
+<category name="GL_APPLE_flush_buffer_range" number="321">
+ <enum name="BUFFER_SERIALIZED_MODIFY_APPLE" count="1" value="0x8A12">
+ <size name="GetBufferParameteriv" mode="get"/>
+ </enum>
+ <enum name="BUFFER_FLUSHING_UNMAP_APPLE" count="1" value="0x8A13">
+ <size name="GetBufferParameteriv" mode="get"/>
+ </enum>
+ <function name="BufferParameteriAPPLE" offset="assign" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="param" type="GLint"/>
+ </function>
+ <function name="FlushMappedBufferRangeAPPLE" offset="assign" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="offset" type="GLintptr"/>
+ <param name="size" type="GLsizeiptr"/>
+ </function>
+</category>
+
+<xi:include href="EXT_texture_array.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<category name="GL_APPLE_texture_range" number="367">
+ <enum name="TEXTURE_STORAGE_HINT_APPLE" count="1" value="0x85BC">
+ <size name="TexParameteriv"/>
+ <size name="TexParameterfv"/>
+ <size name="GetTexParameteriv" mode="get"/>
+ <size name="GetTexParameterfv" mode="get"/>
+ </enum>
+ <enum name="STORAGE_PRIVATE_APPLE" count="1" value="0x85BD">
+ <size name="TexParameteriv"/>
+ <size name="TexParameterfv"/>
+ </enum>
+ <enum name="STORAGE_CACHED_APPLE" count="1" value="0x85BE">
+ <size name="TexParameteriv"/>
+ <size name="TexParameterfv"/>
+ </enum>
+ <enum name="STORAGE_SHARED_APPLE" count="1" value="0x85BF">
+ <size name="TexParameteriv"/>
+ <size name="TexParameterfv"/>
+ </enum>
+ <enum name="TEXTURE_RANGE_LENGTH_APPLE" count="1" value="0x85B7">
+ <size name="GetTexParameteriv" mode="get"/>
+ <size name="GetTexParameterfv" mode="get"/>
+ </enum>
+ <enum name="TEXTURE_RANGE_POINTER_APPLE" count="1" value="0x85B8">
+ <size name="GetTexParameterPointervAPPLE" mode="get"/>
+ </enum>
+ <function name="TextureRangeAPPLE" offset="assign" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="length" type="GLsizei"/>
+ <param name="pointer" type="GLvoid *"/>
+ </function>
+ <function name="GetTexParameterPointervAPPLE" offset="assign" static_dispatch="false">
+ <param name="target" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLvoid **"/>
+ </function>
+</category>
+
<!-- Unnumbered extensions sorted by name. -->
<category name="GL_ATI_blend_equation_separate">
@@ -12273,6 +12401,12 @@
</function>
</category>
+<category name="GL_MESA_texture_signed_rgba">
+ <enum name="SIGNED_NORMALIZED" value="0x8F9C"/>
+ <enum name="RGBA_SNORM" value="0x8F93"/>
+ <enum name="RGBA8_SNORM" value="0x8F97"/>
+</category>
+
<category name="GL_MESA_shader_debug">
<enum name="DEBUG_OBJECT_MESA" value="0x8759"/>
<enum name="DEBUG_PRINT_MESA" value="0x875A"/>
diff --git a/src/mesa/glapi/gl_SPARC_asm.py b/src/mesa/glapi/gl_SPARC_asm.py
index 178c00a227..33e752df38 100644
--- a/src/mesa/glapi/gl_SPARC_asm.py
+++ b/src/mesa/glapi/gl_SPARC_asm.py
@@ -39,80 +39,202 @@ class PrintGenericStubs(gl_XML.gl_print_base):
def printRealHeader(self):
- print '#include "glapioffsets.h"'
+ print '#include "glapi/glapioffsets.h"'
print ''
print '#ifdef __arch64__'
- print '# define GL_STUB(fn,off)\t\t\t\t\\'
- print 'fn:\t\t\t\t\t\\'
- print '\tsethi\t%hi(0xDEADBEEF), %g4 ;\t\t\t\\'
- print '\tsethi\t%hi(0xDEADBEEF), %g1 ;\t\t\t\\'
- print '\tor\t%g4, %lo(0xDEADBEEF), %g4 ;\t\t\\'
- print '\tor\t%g1, %lo(0xDEADBEEF), %g1 ;\t\t\\'
- print '\tsllx\t%g4, 32, %g4 ;\t\t\t\t\\'
- print '\tldx\t[%g1 + %g4], %g1 ;\t\t\t\\'
- print '\tsethi\t%hi(8 * off), %g4 ;\t\t\t\\'
- print '\tor\t%g4, %lo(8 * off), %g4 ;\t\t\\'
- print '\tldx\t[%g1 + %g4], %g5 ;\t\t\t\\'
- print '\tjmpl\t%g5, %g0 ;\t\t\t\t\\'
- print '\tnop'
+ print '#define GL_OFF(N)\t((N) * 8)'
+ print '#define GL_LL\t\tldx'
+ print '#define GL_TIE_LD(SYM)\t%tie_ldx(SYM)'
+ print '#define GL_STACK_SIZE\t128'
print '#else'
- print '# define GL_STUB(fn,off)\t\t\t\t\\'
- print 'fn:\t\t\t\t\t\\'
- print '\tsethi\t%hi(0xDEADBEEF), %g1 ;\t\t\t\\'
- print '\tld\t[%g1 + %lo(0xDEADBEEF)], %g1 ;\t\t\\'
- print '\tld\t[%g1 + (4 * off)], %g5 ;\t\t\\'
- print '\tjmpl\t%g5, %g0 ;\t\t\t\t\\'
- print '\tnop'
+ print '#define GL_OFF(N)\t((N) * 4)'
+ print '#define GL_LL\t\tld'
+ print '#define GL_TIE_LD(SYM)\t%tie_ld(SYM)'
+ print '#define GL_STACK_SIZE\t64'
print '#endif'
print ''
- print '#define GL_STUB_ALIAS(fn,alias) fn = alias'
+ print '#define GLOBL_FN(x) .globl x ; .type x, @function'
+ print '#define HIDDEN(x) .hidden x'
print ''
- print '.text'
- print '.align 32'
- print '\t\t.globl __glapi_sparc_icache_flush ; .type __glapi_sparc_icache_flush,#function'
+ print '\t.register %g2, #scratch'
+ print '\t.register %g3, #scratch'
+ print ''
+ print '\t.text'
+ print ''
+ print '\tGLOBL_FN(__glapi_sparc_icache_flush)'
+ print '\tHIDDEN(__glapi_sparc_icache_flush)'
+ print '\t.type\t__glapi_sparc_icache_flush, @function'
print '__glapi_sparc_icache_flush: /* %o0 = insn_addr */'
print '\tflush\t%o0'
print '\tretl'
- print '\tnop'
+ print '\t nop'
+ print ''
+ print '\t.align\t32'
+ print ''
+ print '\t.type\t__glapi_sparc_get_pc, @function'
+ print '__glapi_sparc_get_pc:'
+ print '\tretl'
+ print '\t add\t%o7, %g2, %g2'
+ print '\t.size\t__glapi_sparc_get_pc, .-__glapi_sparc_get_pc'
+ print ''
+ print '#ifdef GLX_USE_TLS'
+ print ''
+ print '\tGLOBL_FN(__glapi_sparc_get_dispatch)'
+ print '\tHIDDEN(__glapi_sparc_get_dispatch)'
+ print '__glapi_sparc_get_dispatch:'
+ print '\tmov\t%o7, %g1'
+ print '\tsethi\t%hi(_GLOBAL_OFFSET_TABLE_-4), %g2'
+ print '\tcall\t__glapi_sparc_get_pc'
+ print '\tadd\t%g2, %lo(_GLOBAL_OFFSET_TABLE_+4), %g2'
+ print '\tmov\t%g1, %o7'
+ print '\tsethi\t%tie_hi22(_glapi_tls_Dispatch), %g1'
+ print '\tadd\t%g1, %tie_lo10(_glapi_tls_Dispatch), %g1'
+ print '\tGL_LL\t[%g2 + %g1], %g2, GL_TIE_LD(_glapi_tls_Dispatch)'
+ print '\tretl'
+ print '\t mov\t%g2, %o0'
+ print ''
+ print '\t.data'
+ print '\t.align\t32'
+ print ''
+ print '\t/* --> sethi %hi(_glapi_tls_Dispatch), %g1 */'
+ print '\t/* --> or %g1, %lo(_glapi_tls_Dispatch), %g1 */'
+ print '\tGLOBL_FN(__glapi_sparc_tls_stub)'
+ print '\tHIDDEN(__glapi_sparc_tls_stub)'
+ print '__glapi_sparc_tls_stub: /* Call offset in %g3 */'
+ print '\tmov\t%o7, %g1'
+ print '\tsethi\t%hi(_GLOBAL_OFFSET_TABLE_-4), %g2'
+ print '\tcall\t__glapi_sparc_get_pc'
+ print '\tadd\t%g2, %lo(_GLOBAL_OFFSET_TABLE_+4), %g2'
+ print '\tmov\t%g1, %o7'
+ print '\tsrl\t%g3, 10, %g3'
+ print '\tsethi\t%tie_hi22(_glapi_tls_Dispatch), %g1'
+ print '\tadd\t%g1, %tie_lo10(_glapi_tls_Dispatch), %g1'
+ print '\tGL_LL\t[%g2 + %g1], %g2, GL_TIE_LD(_glapi_tls_Dispatch)'
+ print '\tGL_LL\t[%g7+%g2], %g1'
+ print '\tGL_LL\t[%g1 + %g3], %g1'
+ print '\tjmp\t%g1'
+ print '\t nop'
+ print '\t.size\t__glapi_sparc_tls_stub, .-__glapi_sparc_tls_stub'
+ print ''
+ print '#define GL_STUB(fn, off)\t\t\t\t\\'
+ print '\tGLOBL_FN(fn);\t\t\t\t\t\\'
+ print 'fn:\tba\t__glapi_sparc_tls_stub;\t\t\t\\'
+ print '\t sethi\tGL_OFF(off), %g3;\t\t\t\\'
+ print '\t.size\tfn,.-fn;'
+ print ''
+ print '#elif defined(PTHREADS)'
+ print ''
+ print '\t/* 64-bit 0x00 --> sethi %hh(_glapi_Dispatch), %g1 */'
+ print '\t/* 64-bit 0x04 --> sethi %lm(_glapi_Dispatch), %g2 */'
+ print '\t/* 64-bit 0x08 --> or %g1, %hm(_glapi_Dispatch), %g1 */'
+ print '\t/* 64-bit 0x0c --> sllx %g1, 32, %g1 */'
+ print '\t/* 64-bit 0x10 --> add %g1, %g2, %g1 */'
+ print '\t/* 64-bit 0x14 --> ldx [%g1 + %lo(_glapi_Dispatch)], %g1 */'
+ print ''
+ print '\t/* 32-bit 0x00 --> sethi %hi(_glapi_Dispatch), %g1 */'
+ print '\t/* 32-bit 0x04 --> ld [%g1 + %lo(_glapi_Dispatch)], %g1 */'
+ print ''
+ print '\t.data'
+ print '\t.align\t32'
+ print ''
+ print '\tGLOBL_FN(__glapi_sparc_pthread_stub)'
+ print '\tHIDDEN(__glapi_sparc_pthread_stub)'
+ print '__glapi_sparc_pthread_stub: /* Call offset in %g3 */'
+ print '\tmov\t%o7, %g1'
+ print '\tsethi\t%hi(_GLOBAL_OFFSET_TABLE_-4), %g2'
+ print '\tcall\t__glapi_sparc_get_pc'
+ print '\t add\t%g2, %lo(_GLOBAL_OFFSET_TABLE_+4), %g2'
+ print '\tmov\t%g1, %o7'
+ print '\tsethi\t%hi(_glapi_Dispatch), %g1'
+ print '\tor\t%g1, %lo(_glapi_Dispatch), %g1'
+ print '\tsrl\t%g3, 10, %g3'
+ print '\tGL_LL\t[%g2+%g1], %g2'
+ print '\tGL_LL\t[%g2], %g1'
+ print '\tcmp\t%g1, 0'
+ print '\tbe\t2f'
+ print '\t nop'
+ print '1:\tGL_LL\t[%g1 + %g3], %g1'
+ print '\tjmp\t%g1'
+ print '\t nop'
+ print '2:\tsave\t%sp, GL_STACK_SIZE, %sp'
+ print '\tmov\t%g3, %l0'
+ print '\tcall\t_glapi_get_dispatch'
+ print '\t nop'
+ print '\tmov\t%o0, %g1'
+ print '\tmov\t%l0, %g3'
+ print '\tba\t1b'
+ print '\t restore %g0, %g0, %g0'
+ print '\t.size\t__glapi_sparc_pthread_stub, .-__glapi_sparc_pthread_stub'
+ print ''
+ print '#define GL_STUB(fn, off)\t\t\t\\'
+ print '\tGLOBL_FN(fn);\t\t\t\t\\'
+ print 'fn:\tba\t__glapi_sparc_pthread_stub;\t\\'
+ print '\t sethi\tGL_OFF(off), %g3;\t\t\\'
+ print '\t.size\tfn,.-fn;'
+ print ''
+ print '#else /* Non-threaded version. */'
print ''
- print '.data'
- print '.align 64'
+ print '\t.type __glapi_sparc_nothread_stub, @function'
+ print '__glapi_sparc_nothread_stub: /* Call offset in %g3 */'
+ print '\tmov\t%o7, %g1'
+ print '\tsethi\t%hi(_GLOBAL_OFFSET_TABLE_-4), %g2'
+ print '\tcall\t__glapi_sparc_get_pc'
+ print '\t add\t%g2, %lo(_GLOBAL_OFFSET_TABLE_+4), %g2'
+ print '\tmov\t%g1, %o7'
+ print '\tsrl\t%g3, 10, %g3'
+ print '\tsethi\t%hi(_glapi_Dispatch), %g1'
+ print '\tor\t%g1, %lo(_glapi_Dispatch), %g1'
+ print '\tGL_LL\t[%g2+%g1], %g2'
+ print '\tGL_LL\t[%g2], %g1'
+ print '\tGL_LL\t[%g1 + %g3], %g1'
+ print '\tjmp\t%g1'
+ print '\t nop'
+ print '\t.size\t__glapi_sparc_nothread_stub, .-__glapi_sparc_nothread_stub'
+ print ''
+ print '#define GL_STUB(fn, off)\t\t\t\\'
+ print '\tGLOBL_FN(fn);\t\t\t\t\\'
+ print 'fn:\tba\t__glapi_sparc_nothread_stub;\t\\'
+ print '\t sethi\tGL_OFF(off), %g3;\t\t\\'
+ print '\t.size\tfn,.-fn;'
+ print ''
+ print '#endif'
+ print ''
+ print '#define GL_STUB_ALIAS(fn, alias) \\'
+ print ' .globl fn; \\'
+ print ' .set fn, alias'
+ print ''
+ print '\t.text'
+ print '\t.align\t32'
+ print ''
+ print '\t.globl\tgl_dispatch_functions_start'
+ print '\tHIDDEN(gl_dispatch_functions_start)'
+ print 'gl_dispatch_functions_start:'
print ''
return
+ def printRealFooter(self):
+ print ''
+ print '\t.globl\tgl_dispatch_functions_end'
+ print '\tHIDDEN(gl_dispatch_functions_end)'
+ print 'gl_dispatch_functions_end:'
+ return
def printBody(self, api):
for f in api.functionIterateByOffset():
- if f.is_static_entry_point(f.name):
- name = f.name
- else:
- name = "_dispatch_stub_%u" % (f.offset)
+ name = f.dispatch_name()
- print '\t\t.globl gl%s ; .type gl%s,#function' % (name, name)
+ print '\tGL_STUB(gl%s, _gloffset_%s)' % (name, f.name)
- print '\t\t.globl _mesa_sparc_glapi_begin ; .type _mesa_sparc_glapi_begin,#function'
- print '_mesa_sparc_glapi_begin:'
- print ''
+ if not f.is_static_entry_point(f.name):
+ print '\tHIDDEN(gl%s)' % (name)
for f in api.functionIterateByOffset():
- if f.is_static_entry_point(f.name):
- name = f.name
- else:
- name = "_dispatch_stub_%u" % (f.offset)
-
- print '\tGL_STUB(gl%s, _gloffset_%s)' % (name, name)
+ name = f.dispatch_name()
- print ''
- print '\t\t.globl _mesa_sparc_glapi_end ; .type _mesa_sparc_glapi_end,#function'
- print '_mesa_sparc_glapi_end:'
- print ''
-
-
- for f in api.functionIterateByOffset():
- for n in f.entry_points:
- if n != f.name:
- if f.is_static_entry_point(n):
- text = '\t.globl gl%s ; .type gl%s,#function ; gl%s = gl%s' % (n, n, n, f.name)
+ if f.is_static_entry_point(f.name):
+ for n in f.entry_points:
+ if n != f.name:
+ text = '\tGL_STUB_ALIAS(gl%s, gl%s)' % (n, f.name)
if f.has_different_protocol(n):
print '#ifndef GLX_INDIRECT_RENDERING'
diff --git a/src/mesa/glapi/gl_enums.py b/src/mesa/glapi/gl_enums.py
index 67fec7968a..27ab119537 100644
--- a/src/mesa/glapi/gl_enums.py
+++ b/src/mesa/glapi/gl_enums.py
@@ -43,6 +43,7 @@ class PrintGlEnums(gl_XML.gl_print_base):
def printRealHeader(self):
print '#include "glheader.h"'
+ print '#include "mfeatures.h"'
print '#include "enums.h"'
print '#include "imports.h"'
print ''
@@ -55,8 +56,6 @@ class PrintGlEnums(gl_XML.gl_print_base):
def print_code(self):
print """
-#define Elements(x) sizeof(x)/sizeof(*x)
-
typedef int (*cfunc)(const void *, const void *);
/**
@@ -111,6 +110,29 @@ const char *_mesa_lookup_enum_by_nr( int nr )
}
}
+/* Get the name of an enum given that it is a primitive type. Avoids
+ * GL_FALSE/GL_POINTS ambiguity and others.
+ */
+const char *_mesa_lookup_prim_by_nr( int nr )
+{
+ switch (nr) {
+ case GL_POINTS: return "GL_POINTS";
+ case GL_LINES: return "GL_LINES";
+ case GL_LINE_STRIP: return "GL_LINE_STRIP";
+ case GL_LINE_LOOP: return "GL_LINE_LOOP";
+ case GL_TRIANGLES: return "GL_TRIANGLES";
+ case GL_TRIANGLE_STRIP: return "GL_TRIANGLE_STRIP";
+ case GL_TRIANGLE_FAN: return "GL_TRIANGLE_FAN";
+ case GL_QUADS: return "GL_QUADS";
+ case GL_QUAD_STRIP: return "GL_QUAD_STRIP";
+ case GL_POLYGON: return "GL_POLYGON";
+ case GL_POLYGON+1: return "OUTSIDE_BEGIN_END";
+ default: return "<invalid>";
+ }
+}
+
+
+
int _mesa_lookup_enum_by_name( const char *symbol )
{
enum_elt * f = NULL;
diff --git a/src/mesa/glapi/gl_offsets.py b/src/mesa/glapi/gl_offsets.py
index 59f8d372b0..07db370649 100644
--- a/src/mesa/glapi/gl_offsets.py
+++ b/src/mesa/glapi/gl_offsets.py
@@ -30,9 +30,10 @@ import license
import sys, getopt
class PrintGlOffsets(gl_XML.gl_print_base):
- def __init__(self):
+ def __init__(self, es=False):
gl_XML.gl_print_base.__init__(self)
+ self.es = es
self.name = "gl_offsets.py (from Mesa)"
self.header_tag = '_GLAPI_OFFSETS_H_'
self.license = license.bsd_license_template % ( \
@@ -45,6 +46,7 @@ class PrintGlOffsets(gl_XML.gl_print_base):
functions = []
abi_functions = []
+ alias_functions = []
count = 0
for f in api.functionIterateByOffset():
[category, num] = api.get_category_for_name( f.name )
@@ -54,6 +56,10 @@ class PrintGlOffsets(gl_XML.gl_print_base):
else:
abi_functions.append( f )
+ if self.es:
+ # remember functions with aliases
+ if [f.name] != f.entry_points:
+ alias_functions.append(f)
for f in abi_functions:
print '#define _gloffset_%s %d' % (f.name, f.offset)
@@ -78,26 +84,37 @@ class PrintGlOffsets(gl_XML.gl_print_base):
print ''
print '#endif /* !defined(IN_DRI_DRIVER) */'
+ if self.es and alias_functions:
+ print ''
+ print '/* define aliases for compatibility */'
+ for f in alias_functions:
+ for name in f.entry_points:
+ if name != f.name:
+ print '#define _gloffset_%s _gloffset_%s' % (name, f.name)
return
def show_usage():
- print "Usage: %s [-f input_file_name]" % sys.argv[0]
+ print "Usage: %s [-f input_file_name] [-c]" % sys.argv[0]
+ print " -c Enable compatibility with OpenGL ES."
sys.exit(1)
if __name__ == '__main__':
file_name = "gl_API.xml"
try:
- (args, trail) = getopt.getopt(sys.argv[1:], "f:")
+ (args, trail) = getopt.getopt(sys.argv[1:], "f:c")
except Exception,e:
show_usage()
+ es = False
for (arg,val) in args:
if arg == "-f":
file_name = val
+ elif arg == "-c":
+ es = True
api = gl_XML.parse_GL_API( file_name )
- printer = PrintGlOffsets()
+ printer = PrintGlOffsets(es)
printer.Print( api )
diff --git a/src/mesa/glapi/gl_procs.py b/src/mesa/glapi/gl_procs.py
index 96e59a58ca..a5aebaec75 100644
--- a/src/mesa/glapi/gl_procs.py
+++ b/src/mesa/glapi/gl_procs.py
@@ -30,9 +30,10 @@ import gl_XML, glX_XML
import sys, getopt
class PrintGlProcs(gl_XML.gl_print_base):
- def __init__(self, long_strings):
+ def __init__(self, long_strings, es=False):
gl_XML.gl_print_base.__init__(self)
+ self.es = es
self.long_strings = long_strings
self.name = "gl_procs.py (from Mesa)"
self.license = license.bsd_license_template % ( \
@@ -85,6 +86,18 @@ typedef struct {
def printBody(self, api):
print ''
+ if self.es:
+ print '/* OpenGL ES specific prototypes */'
+ for func in api.functionIterateByOffset():
+ for n in func.entry_points:
+ cat, num = api.get_category_for_name(n)
+ if ((cat.startswith("es") and not (cat.endswith("core") or cat.endswith("compat"))) or
+ cat.startswith("GL_OES")):
+ print '/* category %s */' % cat
+ print 'GLAPI %s GLAPIENTRY %s(%s);' \
+ % (func.return_type, "gl" + n, func.get_parameter_string(n))
+ print ''
+
if self.long_strings:
print 'static const char gl_string_table[] ='
else:
@@ -134,12 +147,11 @@ typedef struct {
print "#endif /* USE_MGL_NAMESPACE */"
print ''
print ''
- print '/* FIXME: Having these (incorrect) prototypes here is ugly. */'
print '#if defined(NEED_FUNCTION_POINTER) || defined(GLX_INDIRECT_RENDERING)'
for func in api.functionIterateByOffset():
for n in func.entry_points:
if (not func.is_static_entry_point(func.name)) or (func.has_different_protocol(n) and not func.is_static_entry_point(n)):
- print 'extern void gl_dispatch_stub_%u(void);' % (func.offset)
+ print '%s GLAPIENTRY gl_dispatch_stub_%u(%s);' % (func.return_type, func.offset, func.get_parameter_string())
break
print '#endif /* defined(NEED_FUNCTION_POINTER) || defined(GLX_INDIRECT_RENDERING) */'
@@ -156,8 +168,9 @@ typedef struct {
def show_usage():
- print "Usage: %s [-f input_file_name] [-m mode]" % sys.argv[0]
- print "mode can be one of:"
+ print "Usage: %s [-f input_file_name] [-m mode] [-c]" % sys.argv[0]
+ print "-c Enable compatibility with OpenGL ES."
+ print "-m mode mode can be one of:"
print " long - Create code for compilers that can handle very"
print " long string constants. (default)"
print " short - Create code for compilers that can only handle"
@@ -168,11 +181,12 @@ if __name__ == '__main__':
file_name = "gl_API.xml"
try:
- (args, trail) = getopt.getopt(sys.argv[1:], "f:m:")
+ (args, trail) = getopt.getopt(sys.argv[1:], "f:m:c")
except Exception,e:
show_usage()
long_string = 1
+ es = False
for (arg,val) in args:
if arg == "-f":
file_name = val
@@ -183,7 +197,9 @@ if __name__ == '__main__':
long_string = 1
else:
show_usage()
+ elif arg == "-c":
+ es = True
api = gl_XML.parse_GL_API(file_name, glX_XML.glx_item_factory())
- printer = PrintGlProcs(long_string)
+ printer = PrintGlProcs(long_string, es)
printer.Print(api)
diff --git a/src/mesa/glapi/gl_table.py b/src/mesa/glapi/gl_table.py
index 55a33748ae..908d966da5 100644
--- a/src/mesa/glapi/gl_table.py
+++ b/src/mesa/glapi/gl_table.py
@@ -30,9 +30,10 @@ import license
import sys, getopt
class PrintGlTable(gl_XML.gl_print_base):
- def __init__(self):
+ def __init__(self, es=False):
gl_XML.gl_print_base.__init__(self)
+ self.es = es
self.header_tag = '_GLAPI_TABLE_H_'
self.name = "gl_table.py (from Mesa)"
self.license = license.bsd_license_template % ( \
@@ -42,10 +43,29 @@ class PrintGlTable(gl_XML.gl_print_base):
def printBody(self, api):
+ if self.es:
+ typedefs = []
+ for t in api.typeIterate():
+ if t.name == "fixed":
+ typedefs.append("typedef int GLfixed;")
+ elif t.name == "clampx":
+ typedefs.append("typedef int GLclampx;")
+ elif t.name == "eglImageOES":
+ typedefs.append("typedef void *GLeglImageOES;")
+ if typedefs:
+ print '#ifndef HAVE_GLES_TYPES'
+ print "\n".join(typedefs)
+ print '#endif'
+ print ''
+ print 'struct _glapi_table'
+ print '{'
+
for f in api.functionIterateByOffset():
arg_string = f.get_parameter_string()
print ' %s (GLAPIENTRYP %s)(%s); /* %d */' % (f.return_type, f.name, arg_string, f.offset)
+ print '};'
+
def printRealHeader(self):
print '#ifndef GLAPIENTRYP'
@@ -56,21 +76,18 @@ class PrintGlTable(gl_XML.gl_print_base):
print '# define GLAPIENTRYP GLAPIENTRY *'
print '#endif'
print ''
- print ''
- print 'struct _glapi_table'
- print '{'
return
def printRealFooter(self):
- print '};'
return
class PrintRemapTable(gl_XML.gl_print_base):
- def __init__(self):
+ def __init__(self, es=False):
gl_XML.gl_print_base.__init__(self)
+ self.es = es
self.header_tag = '_DISPATCH_H_'
self.name = "gl_table.py (from Mesa)"
self.license = license.bsd_license_template % ("(C) Copyright IBM Corporation 2005", "IBM")
@@ -116,6 +133,7 @@ class PrintRemapTable(gl_XML.gl_print_base):
functions = []
abi_functions = []
+ alias_functions = []
count = 0
for f in api.functionIterateByOffset():
[category, num] = api.get_category_for_name( f.name )
@@ -125,6 +143,11 @@ class PrintRemapTable(gl_XML.gl_print_base):
else:
abi_functions.append( f )
+ if self.es:
+ # remember functions with aliases
+ if [f.name] != f.entry_points:
+ alias_functions.append(f)
+
for f in abi_functions:
print '#define CALL_%s(disp, parameters) (*((disp)->%s)) parameters' % (f.name, f.name)
@@ -164,33 +187,57 @@ class PrintRemapTable(gl_XML.gl_print_base):
print ''
print '#endif /* !defined(IN_DRI_DRIVER) */'
+
+ if self.es and alias_functions:
+ print ''
+ print '/* define aliases for compatibility */'
+ for f in alias_functions:
+ for name in f.entry_points:
+ if name != f.name:
+ print '#define CALL_%s(disp, parameters) CALL_%s(disp, parameters)' % (name, f.name)
+ print '#define GET_%s(disp) GET_%s(disp)' % (name, f.name)
+ print '#define SET_%s(disp, fn) SET_%s(disp, fn)' % (name, f.name)
+ print ''
+
+ print '#if defined(IN_DRI_DRIVER)'
+ for f in alias_functions:
+ for name in f.entry_points:
+ if name != f.name:
+ print '#define %s_remap_index %s_remap_index' % (name, f.name)
+ print '#endif /* defined(IN_DRI_DRIVER) */'
+ print ''
+
return
def show_usage():
- print "Usage: %s [-f input_file_name] [-m mode]" % sys.argv[0]
+ print "Usage: %s [-f input_file_name] [-m mode] [-c]" % sys.argv[0]
print " -m mode Mode can be 'table' or 'remap_table'."
+ print " -c Enable compatibility with OpenGL ES."
sys.exit(1)
if __name__ == '__main__':
file_name = "gl_API.xml"
try:
- (args, trail) = getopt.getopt(sys.argv[1:], "f:m:")
+ (args, trail) = getopt.getopt(sys.argv[1:], "f:m:c")
except Exception,e:
show_usage()
mode = "table"
+ es = False
for (arg,val) in args:
if arg == "-f":
file_name = val
elif arg == "-m":
mode = val
+ elif arg == "-c":
+ es = True
if mode == "table":
- printer = PrintGlTable()
+ printer = PrintGlTable(es)
elif mode == "remap_table":
- printer = PrintRemapTable()
+ printer = PrintRemapTable(es)
else:
show_usage()
diff --git a/src/mesa/glapi/gl_x86-64_asm.py b/src/mesa/glapi/gl_x86-64_asm.py
index fa45406f47..f36ad3a5d8 100644
--- a/src/mesa/glapi/gl_x86-64_asm.py
+++ b/src/mesa/glapi/gl_x86-64_asm.py
@@ -138,7 +138,7 @@ class PrintGenericStubs(gl_XML.gl_print_base):
print '# define GL_PREFIX(n) GLNAME(CONCAT(gl,n))'
print '# endif'
print ''
- print '#if defined(PTHREADS) || defined(USE_XTHREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS)'
+ print '#if defined(PTHREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS)'
print '# define THREADS'
print '#endif'
print ''
diff --git a/src/mesa/glapi/gl_x86_asm.py b/src/mesa/glapi/gl_x86_asm.py
index 0dbf3ebe0a..36f0e31fe2 100644
--- a/src/mesa/glapi/gl_x86_asm.py
+++ b/src/mesa/glapi/gl_x86_asm.py
@@ -79,7 +79,7 @@ class PrintGenericStubs(gl_XML.gl_print_base):
print '#define GLOBL_FN(x) GLOBL x'
print '#endif'
print ''
- print '#if defined(PTHREADS) || defined(USE_XTHREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS)'
+ print '#if defined(PTHREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS)'
print '# define THREADS'
print '#endif'
print ''
diff --git a/src/mesa/glapi/glapi.c b/src/mesa/glapi/glapi.c
index c3ebf60719..ad72fe48be 100644
--- a/src/mesa/glapi/glapi.c
+++ b/src/mesa/glapi/glapi.c
@@ -61,15 +61,17 @@
#endif
+#include "main/compiler.h"
+
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG
#include <assert.h>
#endif
-#include "glapi.h"
-#include "glapioffsets.h"
-#include "glapitable.h"
+#include "glapi/glapi.h"
+#include "glapi/glapioffsets.h"
+#include "glapi/glapitable.h"
/***** BEGIN NO-OP DISPATCH *****/
@@ -98,6 +100,7 @@ _glapi_set_warning_func( _glapi_warning_func func )
static GLboolean
warn(void)
{
+#if !defined(_WIN32_WCE)
if ((WarnFlag || getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG"))
&& warning_func) {
return GL_TRUE;
@@ -105,6 +108,9 @@ warn(void)
else {
return GL_FALSE;
}
+#else
+ return GL_FALSE;
+#endif
}
@@ -139,7 +145,7 @@ static GLint NoOpUnused(void)
return 0;
}
-#include "glapitemp.h"
+#include "glapi/glapitemp.h"
/***** END NO-OP DISPATCH *****/
@@ -192,6 +198,16 @@ PUBLIC const void *_glapi_Context = NULL;
#if defined(THREADS)
+#ifdef WIN32_THREADS
+/* _glthread_DECLARE_STATIC_MUTEX is broken on windows. There will be race! */
+#define CHECK_MULTITHREAD_LOCK()
+#define CHECK_MULTITHREAD_UNLOCK()
+#else
+_glthread_DECLARE_STATIC_MUTEX(ThreadCheckMutex);
+#define CHECK_MULTITHREAD_LOCK() _glthread_LOCK_MUTEX(ThreadCheckMutex)
+#define CHECK_MULTITHREAD_UNLOCK() _glthread_UNLOCK_MUTEX(ThreadCheckMutex)
+#endif
+
static GLboolean ThreadSafe = GL_FALSE; /**< In thread-safe mode? */
_glthread_TSD _gl_DispatchTSD; /**< Per-thread dispatch pointer */
static _glthread_TSD ContextTSD; /**< Per-thread context pointer */
@@ -225,23 +241,27 @@ void
_glapi_check_multithread(void)
{
#if defined(THREADS) && !defined(GLX_USE_TLS)
- if (!ThreadSafe) {
- static unsigned long knownID;
- static GLboolean firstCall = GL_TRUE;
- if (firstCall) {
- knownID = _glthread_GetID();
- firstCall = GL_FALSE;
- }
- else if (knownID != _glthread_GetID()) {
- ThreadSafe = GL_TRUE;
- _glapi_set_dispatch(NULL);
- _glapi_set_context(NULL);
- }
+ static unsigned long knownID;
+ static GLboolean firstCall = GL_TRUE;
+
+ if (ThreadSafe)
+ return;
+
+ CHECK_MULTITHREAD_LOCK();
+ if (firstCall) {
+ /* initialize TSDs */
+ (void) _glthread_GetTSD(&ContextTSD);
+ (void) _glthread_GetTSD(&_gl_DispatchTSD);
+
+ knownID = _glthread_GetID();
+ firstCall = GL_FALSE;
}
- else if (!_glapi_get_dispatch()) {
- /* make sure that this thread's dispatch pointer isn't null */
+ else if (knownID != _glthread_GetID()) {
+ ThreadSafe = GL_TRUE;
_glapi_set_dispatch(NULL);
+ _glapi_set_context(NULL);
}
+ CHECK_MULTITHREAD_UNLOCK();
#endif
}
@@ -312,6 +332,14 @@ extern const GLubyte gl_dispatch_functions_start[];
# endif
#endif
+#ifdef USE_SPARC_ASM
+#ifdef GLX_USE_TLS
+extern unsigned int __glapi_sparc_tls_stub;
+#else
+extern unsigned int __glapi_sparc_pthread_stub;
+#endif
+#endif
+
#if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server) && !defined(XGLServer)
# define NEED_FUNCTION_POINTER
#endif
@@ -338,6 +366,129 @@ init_glapi_relocs( void )
curr_func += DISPATCH_FUNCTION_SIZE;
}
#endif
+#ifdef USE_SPARC_ASM
+ extern void __glapi_sparc_icache_flush(unsigned int *);
+ static const unsigned int template[] = {
+#ifdef GLX_USE_TLS
+ 0x05000000, /* sethi %hi(_glapi_tls_Dispatch), %g2 */
+ 0x8730e00a, /* srl %g3, 10, %g3 */
+ 0x8410a000, /* or %g2, %lo(_glapi_tls_Dispatch), %g2 */
+#ifdef __arch64__
+ 0xc259c002, /* ldx [%g7 + %g2], %g1 */
+ 0xc2584003, /* ldx [%g1 + %g3], %g1 */
+#else
+ 0xc201c002, /* ld [%g7 + %g2], %g1 */
+ 0xc2004003, /* ld [%g1 + %g3], %g1 */
+#endif
+ 0x81c04000, /* jmp %g1 */
+ 0x01000000, /* nop */
+#else
+#ifdef __arch64__
+ 0x03000000, /* 64-bit 0x00 --> sethi %hh(_glapi_Dispatch), %g1 */
+ 0x05000000, /* 64-bit 0x04 --> sethi %lm(_glapi_Dispatch), %g2 */
+ 0x82106000, /* 64-bit 0x08 --> or %g1, %hm(_glapi_Dispatch), %g1 */
+ 0x8730e00a, /* 64-bit 0x0c --> srl %g3, 10, %g3 */
+ 0x83287020, /* 64-bit 0x10 --> sllx %g1, 32, %g1 */
+ 0x82004002, /* 64-bit 0x14 --> add %g1, %g2, %g1 */
+ 0xc2586000, /* 64-bit 0x18 --> ldx [%g1 + %lo(_glapi_Dispatch)], %g1 */
+#else
+ 0x03000000, /* 32-bit 0x00 --> sethi %hi(_glapi_Dispatch), %g1 */
+ 0x8730e00a, /* 32-bit 0x04 --> srl %g3, 10, %g3 */
+ 0xc2006000, /* 32-bit 0x08 --> ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
+#endif
+ 0x80a06000, /* --> cmp %g1, 0 */
+ 0x02800005, /* --> be +4*5 */
+ 0x01000000, /* --> nop */
+#ifdef __arch64__
+ 0xc2584003, /* 64-bit --> ldx [%g1 + %g3], %g1 */
+#else
+ 0xc2004003, /* 32-bit --> ld [%g1 + %g3], %g1 */
+#endif
+ 0x81c04000, /* --> jmp %g1 */
+ 0x01000000, /* --> nop */
+#ifdef __arch64__
+ 0x9de3bf80, /* 64-bit --> save %sp, -128, %sp */
+#else
+ 0x9de3bfc0, /* 32-bit --> save %sp, -64, %sp */
+#endif
+ 0xa0100003, /* --> mov %g3, %l0 */
+ 0x40000000, /* --> call _glapi_get_dispatch */
+ 0x01000000, /* --> nop */
+ 0x82100008, /* --> mov %o0, %g1 */
+ 0x86100010, /* --> mov %l0, %g3 */
+ 0x10bffff7, /* --> ba -4*9 */
+ 0x81e80000, /* --> restore */
+#endif
+ };
+#ifdef GLX_USE_TLS
+ extern unsigned long __glapi_sparc_get_dispatch(void);
+ unsigned int *code = &__glapi_sparc_tls_stub;
+ unsigned long dispatch = __glapi_sparc_get_dispatch();
+#else
+ unsigned int *code = &__glapi_sparc_pthread_stub;
+ unsigned long dispatch = (unsigned long) &_glapi_Dispatch;
+ unsigned long call_dest = (unsigned long ) &_glapi_get_dispatch;
+ int idx;
+#endif
+
+#if defined(GLX_USE_TLS)
+ code[0] = template[0] | (dispatch >> 10);
+ code[1] = template[1];
+ __glapi_sparc_icache_flush(&code[0]);
+ code[2] = template[2] | (dispatch & 0x3ff);
+ code[3] = template[3];
+ __glapi_sparc_icache_flush(&code[2]);
+ code[4] = template[4];
+ code[5] = template[5];
+ __glapi_sparc_icache_flush(&code[4]);
+ code[6] = template[6];
+ __glapi_sparc_icache_flush(&code[6]);
+#else
+#if defined(__arch64__)
+ code[0] = template[0] | (dispatch >> (32 + 10));
+ code[1] = template[1] | ((dispatch & 0xffffffff) >> 10);
+ __glapi_sparc_icache_flush(&code[0]);
+ code[2] = template[2] | ((dispatch >> 32) & 0x3ff);
+ code[3] = template[3];
+ __glapi_sparc_icache_flush(&code[2]);
+ code[4] = template[4];
+ code[5] = template[5];
+ __glapi_sparc_icache_flush(&code[4]);
+ code[6] = template[6] | (dispatch & 0x3ff);
+ idx = 7;
+#else
+ code[0] = template[0] | (dispatch >> 10);
+ code[1] = template[1];
+ __glapi_sparc_icache_flush(&code[0]);
+ code[2] = template[2] | (dispatch & 0x3ff);
+ idx = 3;
+#endif
+ code[idx + 0] = template[idx + 0];
+ __glapi_sparc_icache_flush(&code[idx - 1]);
+ code[idx + 1] = template[idx + 1];
+ code[idx + 2] = template[idx + 2];
+ __glapi_sparc_icache_flush(&code[idx + 1]);
+ code[idx + 3] = template[idx + 3];
+ code[idx + 4] = template[idx + 4];
+ __glapi_sparc_icache_flush(&code[idx + 3]);
+ code[idx + 5] = template[idx + 5];
+ code[idx + 6] = template[idx + 6];
+ __glapi_sparc_icache_flush(&code[idx + 5]);
+ code[idx + 7] = template[idx + 7];
+ code[idx + 8] = template[idx + 8] |
+ (((call_dest - ((unsigned long) &code[idx + 8]))
+ >> 2) & 0x3fffffff);
+ __glapi_sparc_icache_flush(&code[idx + 7]);
+ code[idx + 9] = template[idx + 9];
+ code[idx + 10] = template[idx + 10];
+ __glapi_sparc_icache_flush(&code[idx + 9]);
+ code[idx + 11] = template[idx + 11];
+ code[idx + 12] = template[idx + 12];
+ __glapi_sparc_icache_flush(&code[idx + 11]);
+ code[idx + 13] = template[idx + 13];
+ __glapi_sparc_icache_flush(&code[idx + 13]);
+#endif
+#endif
}
#endif /* defined(PTHREADS) || defined(GLX_USE_TLS) */
diff --git a/src/mesa/glapi/glapi.h b/src/mesa/glapi/glapi.h
index 8f2cf66218..5fb5401229 100644
--- a/src/mesa/glapi/glapi.h
+++ b/src/mesa/glapi/glapi.h
@@ -80,8 +80,8 @@ typedef void (*_glapi_warning_func)(void *ctx, const char *str, ...);
**/
#if defined (GLX_USE_TLS)
-const extern void *_glapi_Context;
-const extern struct _glapi_table *_glapi_Dispatch;
+extern const void *_glapi_Context;
+extern const struct _glapi_table *_glapi_Dispatch;
extern __thread void * _glapi_tls_Context
__attribute__((tls_model("initial-exec")));
diff --git a/src/mesa/glapi/glapi_getproc.c b/src/mesa/glapi/glapi_getproc.c
index 6d40b495c7..decdd05b13 100644
--- a/src/mesa/glapi/glapi_getproc.c
+++ b/src/mesa/glapi/glapi_getproc.c
@@ -23,7 +23,7 @@
*/
/**
- * \file glapi_getproc.
+ * \file glapi_getproc.c
*
* Code for implementing glXGetProcAddress(), etc.
* This was originally in glapi.c but refactored out.
@@ -33,9 +33,10 @@
#include <stdlib.h>
#include <string.h>
#include "main/glheader.h"
-#include "glapi.h"
-#include "glapioffsets.h"
-#include "glapitable.h"
+#include "main/compiler.h"
+#include "glapi/glapi.h"
+#include "glapi/glapioffsets.h"
+#include "glapi/glapitable.h"
static void
@@ -74,7 +75,7 @@ str_dup(const char *str)
#endif
/* The code in this file is auto-generated with Python */
-#include "glprocs.h"
+#include "glapi/glprocs.h"
/**
@@ -87,7 +88,13 @@ find_entry( const char * n )
GLuint i;
for (i = 0; static_functions[i].Name_offset >= 0; i++) {
const char *testName = gl_string_table + static_functions[i].Name_offset;
- if (strcmp(testName, n) == 0) {
+#ifdef MANGLE
+ /* skip the "m" prefix on the name */
+ if (strcmp(testName, n + 1) == 0)
+#else
+ if (strcmp(testName, n) == 0)
+#endif
+ {
return &static_functions[i];
}
}
@@ -252,53 +259,30 @@ generate_entrypoint(GLuint functionOffset)
}
return (_glapi_proc) code;
-#elif defined(USE_SPARC_ASM)
-
-#ifdef __arch64__
- static const unsigned int insn_template[] = {
- 0x05000000, /* sethi %uhi(_glapi_Dispatch), %g2 */
- 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
- 0x8410a000, /* or %g2, %ulo(_glapi_Dispatch), %g2 */
- 0x82106000, /* or %g1, %lo(_glapi_Dispatch), %g1 */
- 0x8528b020, /* sllx %g2, 32, %g2 */
- 0xc2584002, /* ldx [%g1 + %g2], %g1 */
- 0x05000000, /* sethi %hi(8 * glapioffset), %g2 */
- 0x8410a000, /* or %g2, %lo(8 * glapioffset), %g2 */
- 0xc6584002, /* ldx [%g1 + %g2], %g3 */
- 0x81c0c000, /* jmpl %g3, %g0 */
- 0x01000000 /* nop */
+#elif defined(USE_SPARC_ASM) && (defined(PTHREADS) || defined(GLX_USE_TLS))
+ static const unsigned int template[] = {
+ 0x07000000, /* sethi %hi(0), %g3 */
+ 0x8210000f, /* mov %o7, %g1 */
+ 0x40000000, /* call */
+ 0x9e100001, /* mov %g1, %o7 */
};
+#ifdef GLX_USE_TLS
+ extern unsigned int __glapi_sparc_tls_stub;
+ unsigned long call_dest = (unsigned long ) &__glapi_sparc_tls_stub;
#else
- static const unsigned int insn_template[] = {
- 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
- 0xc2006000, /* ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
- 0xc6006000, /* ld [%g1 + %lo(4*glapioffset)], %g3 */
- 0x81c0c000, /* jmpl %g3, %g0 */
- 0x01000000 /* nop */
- };
-#endif /* __arch64__ */
- unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
- unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
+ extern unsigned int __glapi_sparc_pthread_stub;
+ unsigned long call_dest = (unsigned long ) &__glapi_sparc_pthread_stub;
+#endif
+ unsigned int *code = (unsigned int *) malloc(sizeof(template));
if (code) {
- memcpy(code, insn_template, sizeof(insn_template));
-
-#ifdef __arch64__
- code[0] |= (glapi_addr >> (32 + 10));
- code[1] |= ((glapi_addr & 0xffffffff) >> 10);
- __glapi_sparc_icache_flush(&code[0]);
- code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
- code[3] |= (glapi_addr & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[2]);
- code[6] |= ((functionOffset * 8) >> 10);
- code[7] |= ((functionOffset * 8) & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[6]);
-#else
- code[0] |= (glapi_addr >> 10);
- code[1] |= (glapi_addr & ((1 << 10) - 1));
+ code[0] = template[0] | (functionOffset & 0x3fffff);
+ code[1] = template[1];
__glapi_sparc_icache_flush(&code[0]);
- code[2] |= (functionOffset * 4);
+ code[2] = template[2] |
+ (((call_dest - ((unsigned long) &code[2]))
+ >> 2) & 0x3fffffff);
+ code[3] = template[3];
__glapi_sparc_icache_flush(&code[2]);
-#endif /* __arch64__ */
}
return (_glapi_proc) code;
#else
@@ -330,21 +314,10 @@ fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
#endif
#elif defined(USE_SPARC_ASM)
-
- /* XXX this hasn't been tested! */
unsigned int *code = (unsigned int *) entrypoint;
-#ifdef __arch64__
- code[6] = 0x05000000; /* sethi %hi(8 * glapioffset), %g2 */
- code[7] = 0x8410a000; /* or %g2, %lo(8 * glapioffset), %g2 */
- code[6] |= ((offset * 8) >> 10);
- code[7] |= ((offset * 8) & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[6]);
-#else /* __arch64__ */
- code[2] = 0xc6006000; /* ld [%g1 + %lo(4*glapioffset)], %g3 */
- code[2] |= (offset * 4);
- __glapi_sparc_icache_flush(&code[2]);
-#endif /* __arch64__ */
-
+ code[0] &= ~0x3fffff;
+ code[0] |= (offset * sizeof(void *)) & 0x3fffff;
+ __glapi_sparc_icache_flush(&code[0]);
#else
/* an unimplemented architecture */
diff --git a/src/mesa/glapi/glapioffsets.h b/src/mesa/glapi/glapioffsets.h
index 43c265924b..a3807744ff 100644
--- a/src/mesa/glapi/glapioffsets.h
+++ b/src/mesa/glapi/glapioffsets.h
@@ -593,216 +593,241 @@
#define _gloffset_GetActiveAttribARB 558
#define _gloffset_GetAttribLocationARB 559
#define _gloffset_DrawBuffersARB 560
-#define _gloffset_PolygonOffsetEXT 561
-#define _gloffset_GetPixelTexGenParameterfvSGIS 562
-#define _gloffset_GetPixelTexGenParameterivSGIS 563
-#define _gloffset_PixelTexGenParameterfSGIS 564
-#define _gloffset_PixelTexGenParameterfvSGIS 565
-#define _gloffset_PixelTexGenParameteriSGIS 566
-#define _gloffset_PixelTexGenParameterivSGIS 567
-#define _gloffset_SampleMaskSGIS 568
-#define _gloffset_SamplePatternSGIS 569
-#define _gloffset_ColorPointerEXT 570
-#define _gloffset_EdgeFlagPointerEXT 571
-#define _gloffset_IndexPointerEXT 572
-#define _gloffset_NormalPointerEXT 573
-#define _gloffset_TexCoordPointerEXT 574
-#define _gloffset_VertexPointerEXT 575
-#define _gloffset_PointParameterfEXT 576
-#define _gloffset_PointParameterfvEXT 577
-#define _gloffset_LockArraysEXT 578
-#define _gloffset_UnlockArraysEXT 579
-#define _gloffset_CullParameterdvEXT 580
-#define _gloffset_CullParameterfvEXT 581
-#define _gloffset_SecondaryColor3bEXT 582
-#define _gloffset_SecondaryColor3bvEXT 583
-#define _gloffset_SecondaryColor3dEXT 584
-#define _gloffset_SecondaryColor3dvEXT 585
-#define _gloffset_SecondaryColor3fEXT 586
-#define _gloffset_SecondaryColor3fvEXT 587
-#define _gloffset_SecondaryColor3iEXT 588
-#define _gloffset_SecondaryColor3ivEXT 589
-#define _gloffset_SecondaryColor3sEXT 590
-#define _gloffset_SecondaryColor3svEXT 591
-#define _gloffset_SecondaryColor3ubEXT 592
-#define _gloffset_SecondaryColor3ubvEXT 593
-#define _gloffset_SecondaryColor3uiEXT 594
-#define _gloffset_SecondaryColor3uivEXT 595
-#define _gloffset_SecondaryColor3usEXT 596
-#define _gloffset_SecondaryColor3usvEXT 597
-#define _gloffset_SecondaryColorPointerEXT 598
-#define _gloffset_MultiDrawArraysEXT 599
-#define _gloffset_MultiDrawElementsEXT 600
-#define _gloffset_FogCoordPointerEXT 601
-#define _gloffset_FogCoorddEXT 602
-#define _gloffset_FogCoorddvEXT 603
-#define _gloffset_FogCoordfEXT 604
-#define _gloffset_FogCoordfvEXT 605
-#define _gloffset_PixelTexGenSGIX 606
-#define _gloffset_BlendFuncSeparateEXT 607
-#define _gloffset_FlushVertexArrayRangeNV 608
-#define _gloffset_VertexArrayRangeNV 609
-#define _gloffset_CombinerInputNV 610
-#define _gloffset_CombinerOutputNV 611
-#define _gloffset_CombinerParameterfNV 612
-#define _gloffset_CombinerParameterfvNV 613
-#define _gloffset_CombinerParameteriNV 614
-#define _gloffset_CombinerParameterivNV 615
-#define _gloffset_FinalCombinerInputNV 616
-#define _gloffset_GetCombinerInputParameterfvNV 617
-#define _gloffset_GetCombinerInputParameterivNV 618
-#define _gloffset_GetCombinerOutputParameterfvNV 619
-#define _gloffset_GetCombinerOutputParameterivNV 620
-#define _gloffset_GetFinalCombinerInputParameterfvNV 621
-#define _gloffset_GetFinalCombinerInputParameterivNV 622
-#define _gloffset_ResizeBuffersMESA 623
-#define _gloffset_WindowPos2dMESA 624
-#define _gloffset_WindowPos2dvMESA 625
-#define _gloffset_WindowPos2fMESA 626
-#define _gloffset_WindowPos2fvMESA 627
-#define _gloffset_WindowPos2iMESA 628
-#define _gloffset_WindowPos2ivMESA 629
-#define _gloffset_WindowPos2sMESA 630
-#define _gloffset_WindowPos2svMESA 631
-#define _gloffset_WindowPos3dMESA 632
-#define _gloffset_WindowPos3dvMESA 633
-#define _gloffset_WindowPos3fMESA 634
-#define _gloffset_WindowPos3fvMESA 635
-#define _gloffset_WindowPos3iMESA 636
-#define _gloffset_WindowPos3ivMESA 637
-#define _gloffset_WindowPos3sMESA 638
-#define _gloffset_WindowPos3svMESA 639
-#define _gloffset_WindowPos4dMESA 640
-#define _gloffset_WindowPos4dvMESA 641
-#define _gloffset_WindowPos4fMESA 642
-#define _gloffset_WindowPos4fvMESA 643
-#define _gloffset_WindowPos4iMESA 644
-#define _gloffset_WindowPos4ivMESA 645
-#define _gloffset_WindowPos4sMESA 646
-#define _gloffset_WindowPos4svMESA 647
-#define _gloffset_MultiModeDrawArraysIBM 648
-#define _gloffset_MultiModeDrawElementsIBM 649
-#define _gloffset_DeleteFencesNV 650
-#define _gloffset_FinishFenceNV 651
-#define _gloffset_GenFencesNV 652
-#define _gloffset_GetFenceivNV 653
-#define _gloffset_IsFenceNV 654
-#define _gloffset_SetFenceNV 655
-#define _gloffset_TestFenceNV 656
-#define _gloffset_AreProgramsResidentNV 657
-#define _gloffset_BindProgramNV 658
-#define _gloffset_DeleteProgramsNV 659
-#define _gloffset_ExecuteProgramNV 660
-#define _gloffset_GenProgramsNV 661
-#define _gloffset_GetProgramParameterdvNV 662
-#define _gloffset_GetProgramParameterfvNV 663
-#define _gloffset_GetProgramStringNV 664
-#define _gloffset_GetProgramivNV 665
-#define _gloffset_GetTrackMatrixivNV 666
-#define _gloffset_GetVertexAttribPointervNV 667
-#define _gloffset_GetVertexAttribdvNV 668
-#define _gloffset_GetVertexAttribfvNV 669
-#define _gloffset_GetVertexAttribivNV 670
-#define _gloffset_IsProgramNV 671
-#define _gloffset_LoadProgramNV 672
-#define _gloffset_ProgramParameters4dvNV 673
-#define _gloffset_ProgramParameters4fvNV 674
-#define _gloffset_RequestResidentProgramsNV 675
-#define _gloffset_TrackMatrixNV 676
-#define _gloffset_VertexAttrib1dNV 677
-#define _gloffset_VertexAttrib1dvNV 678
-#define _gloffset_VertexAttrib1fNV 679
-#define _gloffset_VertexAttrib1fvNV 680
-#define _gloffset_VertexAttrib1sNV 681
-#define _gloffset_VertexAttrib1svNV 682
-#define _gloffset_VertexAttrib2dNV 683
-#define _gloffset_VertexAttrib2dvNV 684
-#define _gloffset_VertexAttrib2fNV 685
-#define _gloffset_VertexAttrib2fvNV 686
-#define _gloffset_VertexAttrib2sNV 687
-#define _gloffset_VertexAttrib2svNV 688
-#define _gloffset_VertexAttrib3dNV 689
-#define _gloffset_VertexAttrib3dvNV 690
-#define _gloffset_VertexAttrib3fNV 691
-#define _gloffset_VertexAttrib3fvNV 692
-#define _gloffset_VertexAttrib3sNV 693
-#define _gloffset_VertexAttrib3svNV 694
-#define _gloffset_VertexAttrib4dNV 695
-#define _gloffset_VertexAttrib4dvNV 696
-#define _gloffset_VertexAttrib4fNV 697
-#define _gloffset_VertexAttrib4fvNV 698
-#define _gloffset_VertexAttrib4sNV 699
-#define _gloffset_VertexAttrib4svNV 700
-#define _gloffset_VertexAttrib4ubNV 701
-#define _gloffset_VertexAttrib4ubvNV 702
-#define _gloffset_VertexAttribPointerNV 703
-#define _gloffset_VertexAttribs1dvNV 704
-#define _gloffset_VertexAttribs1fvNV 705
-#define _gloffset_VertexAttribs1svNV 706
-#define _gloffset_VertexAttribs2dvNV 707
-#define _gloffset_VertexAttribs2fvNV 708
-#define _gloffset_VertexAttribs2svNV 709
-#define _gloffset_VertexAttribs3dvNV 710
-#define _gloffset_VertexAttribs3fvNV 711
-#define _gloffset_VertexAttribs3svNV 712
-#define _gloffset_VertexAttribs4dvNV 713
-#define _gloffset_VertexAttribs4fvNV 714
-#define _gloffset_VertexAttribs4svNV 715
-#define _gloffset_VertexAttribs4ubvNV 716
-#define _gloffset_AlphaFragmentOp1ATI 717
-#define _gloffset_AlphaFragmentOp2ATI 718
-#define _gloffset_AlphaFragmentOp3ATI 719
-#define _gloffset_BeginFragmentShaderATI 720
-#define _gloffset_BindFragmentShaderATI 721
-#define _gloffset_ColorFragmentOp1ATI 722
-#define _gloffset_ColorFragmentOp2ATI 723
-#define _gloffset_ColorFragmentOp3ATI 724
-#define _gloffset_DeleteFragmentShaderATI 725
-#define _gloffset_EndFragmentShaderATI 726
-#define _gloffset_GenFragmentShadersATI 727
-#define _gloffset_PassTexCoordATI 728
-#define _gloffset_SampleMapATI 729
-#define _gloffset_SetFragmentShaderConstantATI 730
-#define _gloffset_PointParameteriNV 731
-#define _gloffset_PointParameterivNV 732
-#define _gloffset_ActiveStencilFaceEXT 733
-#define _gloffset_BindVertexArrayAPPLE 734
-#define _gloffset_DeleteVertexArraysAPPLE 735
-#define _gloffset_GenVertexArraysAPPLE 736
-#define _gloffset_IsVertexArrayAPPLE 737
-#define _gloffset_GetProgramNamedParameterdvNV 738
-#define _gloffset_GetProgramNamedParameterfvNV 739
-#define _gloffset_ProgramNamedParameter4dNV 740
-#define _gloffset_ProgramNamedParameter4dvNV 741
-#define _gloffset_ProgramNamedParameter4fNV 742
-#define _gloffset_ProgramNamedParameter4fvNV 743
-#define _gloffset_DepthBoundsEXT 744
-#define _gloffset_BlendEquationSeparateEXT 745
-#define _gloffset_BindFramebufferEXT 746
-#define _gloffset_BindRenderbufferEXT 747
-#define _gloffset_CheckFramebufferStatusEXT 748
-#define _gloffset_DeleteFramebuffersEXT 749
-#define _gloffset_DeleteRenderbuffersEXT 750
-#define _gloffset_FramebufferRenderbufferEXT 751
-#define _gloffset_FramebufferTexture1DEXT 752
-#define _gloffset_FramebufferTexture2DEXT 753
-#define _gloffset_FramebufferTexture3DEXT 754
-#define _gloffset_GenFramebuffersEXT 755
-#define _gloffset_GenRenderbuffersEXT 756
-#define _gloffset_GenerateMipmapEXT 757
-#define _gloffset_GetFramebufferAttachmentParameterivEXT 758
-#define _gloffset_GetRenderbufferParameterivEXT 759
-#define _gloffset_IsFramebufferEXT 760
-#define _gloffset_IsRenderbufferEXT 761
-#define _gloffset_RenderbufferStorageEXT 762
-#define _gloffset_BlitFramebufferEXT 763
-#define _gloffset_FramebufferTextureLayerEXT 764
-#define _gloffset_StencilFuncSeparateATI 765
-#define _gloffset_ProgramEnvParameters4fvEXT 766
-#define _gloffset_ProgramLocalParameters4fvEXT 767
-#define _gloffset_GetQueryObjecti64vEXT 768
-#define _gloffset_GetQueryObjectui64vEXT 769
-#define _gloffset_FIRST_DYNAMIC 770
+#define _gloffset_RenderbufferStorageMultisample 561
+#define _gloffset_FlushMappedBufferRange 562
+#define _gloffset_MapBufferRange 563
+#define _gloffset_BindVertexArray 564
+#define _gloffset_GenVertexArrays 565
+#define _gloffset_CopyBufferSubData 566
+#define _gloffset_ClientWaitSync 567
+#define _gloffset_DeleteSync 568
+#define _gloffset_FenceSync 569
+#define _gloffset_GetInteger64v 570
+#define _gloffset_GetSynciv 571
+#define _gloffset_IsSync 572
+#define _gloffset_WaitSync 573
+#define _gloffset_DrawElementsBaseVertex 574
+#define _gloffset_DrawRangeElementsBaseVertex 575
+#define _gloffset_MultiDrawElementsBaseVertex 576
+#define _gloffset_PolygonOffsetEXT 577
+#define _gloffset_GetPixelTexGenParameterfvSGIS 578
+#define _gloffset_GetPixelTexGenParameterivSGIS 579
+#define _gloffset_PixelTexGenParameterfSGIS 580
+#define _gloffset_PixelTexGenParameterfvSGIS 581
+#define _gloffset_PixelTexGenParameteriSGIS 582
+#define _gloffset_PixelTexGenParameterivSGIS 583
+#define _gloffset_SampleMaskSGIS 584
+#define _gloffset_SamplePatternSGIS 585
+#define _gloffset_ColorPointerEXT 586
+#define _gloffset_EdgeFlagPointerEXT 587
+#define _gloffset_IndexPointerEXT 588
+#define _gloffset_NormalPointerEXT 589
+#define _gloffset_TexCoordPointerEXT 590
+#define _gloffset_VertexPointerEXT 591
+#define _gloffset_PointParameterfEXT 592
+#define _gloffset_PointParameterfvEXT 593
+#define _gloffset_LockArraysEXT 594
+#define _gloffset_UnlockArraysEXT 595
+#define _gloffset_CullParameterdvEXT 596
+#define _gloffset_CullParameterfvEXT 597
+#define _gloffset_SecondaryColor3bEXT 598
+#define _gloffset_SecondaryColor3bvEXT 599
+#define _gloffset_SecondaryColor3dEXT 600
+#define _gloffset_SecondaryColor3dvEXT 601
+#define _gloffset_SecondaryColor3fEXT 602
+#define _gloffset_SecondaryColor3fvEXT 603
+#define _gloffset_SecondaryColor3iEXT 604
+#define _gloffset_SecondaryColor3ivEXT 605
+#define _gloffset_SecondaryColor3sEXT 606
+#define _gloffset_SecondaryColor3svEXT 607
+#define _gloffset_SecondaryColor3ubEXT 608
+#define _gloffset_SecondaryColor3ubvEXT 609
+#define _gloffset_SecondaryColor3uiEXT 610
+#define _gloffset_SecondaryColor3uivEXT 611
+#define _gloffset_SecondaryColor3usEXT 612
+#define _gloffset_SecondaryColor3usvEXT 613
+#define _gloffset_SecondaryColorPointerEXT 614
+#define _gloffset_MultiDrawArraysEXT 615
+#define _gloffset_MultiDrawElementsEXT 616
+#define _gloffset_FogCoordPointerEXT 617
+#define _gloffset_FogCoorddEXT 618
+#define _gloffset_FogCoorddvEXT 619
+#define _gloffset_FogCoordfEXT 620
+#define _gloffset_FogCoordfvEXT 621
+#define _gloffset_PixelTexGenSGIX 622
+#define _gloffset_BlendFuncSeparateEXT 623
+#define _gloffset_FlushVertexArrayRangeNV 624
+#define _gloffset_VertexArrayRangeNV 625
+#define _gloffset_CombinerInputNV 626
+#define _gloffset_CombinerOutputNV 627
+#define _gloffset_CombinerParameterfNV 628
+#define _gloffset_CombinerParameterfvNV 629
+#define _gloffset_CombinerParameteriNV 630
+#define _gloffset_CombinerParameterivNV 631
+#define _gloffset_FinalCombinerInputNV 632
+#define _gloffset_GetCombinerInputParameterfvNV 633
+#define _gloffset_GetCombinerInputParameterivNV 634
+#define _gloffset_GetCombinerOutputParameterfvNV 635
+#define _gloffset_GetCombinerOutputParameterivNV 636
+#define _gloffset_GetFinalCombinerInputParameterfvNV 637
+#define _gloffset_GetFinalCombinerInputParameterivNV 638
+#define _gloffset_ResizeBuffersMESA 639
+#define _gloffset_WindowPos2dMESA 640
+#define _gloffset_WindowPos2dvMESA 641
+#define _gloffset_WindowPos2fMESA 642
+#define _gloffset_WindowPos2fvMESA 643
+#define _gloffset_WindowPos2iMESA 644
+#define _gloffset_WindowPos2ivMESA 645
+#define _gloffset_WindowPos2sMESA 646
+#define _gloffset_WindowPos2svMESA 647
+#define _gloffset_WindowPos3dMESA 648
+#define _gloffset_WindowPos3dvMESA 649
+#define _gloffset_WindowPos3fMESA 650
+#define _gloffset_WindowPos3fvMESA 651
+#define _gloffset_WindowPos3iMESA 652
+#define _gloffset_WindowPos3ivMESA 653
+#define _gloffset_WindowPos3sMESA 654
+#define _gloffset_WindowPos3svMESA 655
+#define _gloffset_WindowPos4dMESA 656
+#define _gloffset_WindowPos4dvMESA 657
+#define _gloffset_WindowPos4fMESA 658
+#define _gloffset_WindowPos4fvMESA 659
+#define _gloffset_WindowPos4iMESA 660
+#define _gloffset_WindowPos4ivMESA 661
+#define _gloffset_WindowPos4sMESA 662
+#define _gloffset_WindowPos4svMESA 663
+#define _gloffset_MultiModeDrawArraysIBM 664
+#define _gloffset_MultiModeDrawElementsIBM 665
+#define _gloffset_DeleteFencesNV 666
+#define _gloffset_FinishFenceNV 667
+#define _gloffset_GenFencesNV 668
+#define _gloffset_GetFenceivNV 669
+#define _gloffset_IsFenceNV 670
+#define _gloffset_SetFenceNV 671
+#define _gloffset_TestFenceNV 672
+#define _gloffset_AreProgramsResidentNV 673
+#define _gloffset_BindProgramNV 674
+#define _gloffset_DeleteProgramsNV 675
+#define _gloffset_ExecuteProgramNV 676
+#define _gloffset_GenProgramsNV 677
+#define _gloffset_GetProgramParameterdvNV 678
+#define _gloffset_GetProgramParameterfvNV 679
+#define _gloffset_GetProgramStringNV 680
+#define _gloffset_GetProgramivNV 681
+#define _gloffset_GetTrackMatrixivNV 682
+#define _gloffset_GetVertexAttribPointervNV 683
+#define _gloffset_GetVertexAttribdvNV 684
+#define _gloffset_GetVertexAttribfvNV 685
+#define _gloffset_GetVertexAttribivNV 686
+#define _gloffset_IsProgramNV 687
+#define _gloffset_LoadProgramNV 688
+#define _gloffset_ProgramParameters4dvNV 689
+#define _gloffset_ProgramParameters4fvNV 690
+#define _gloffset_RequestResidentProgramsNV 691
+#define _gloffset_TrackMatrixNV 692
+#define _gloffset_VertexAttrib1dNV 693
+#define _gloffset_VertexAttrib1dvNV 694
+#define _gloffset_VertexAttrib1fNV 695
+#define _gloffset_VertexAttrib1fvNV 696
+#define _gloffset_VertexAttrib1sNV 697
+#define _gloffset_VertexAttrib1svNV 698
+#define _gloffset_VertexAttrib2dNV 699
+#define _gloffset_VertexAttrib2dvNV 700
+#define _gloffset_VertexAttrib2fNV 701
+#define _gloffset_VertexAttrib2fvNV 702
+#define _gloffset_VertexAttrib2sNV 703
+#define _gloffset_VertexAttrib2svNV 704
+#define _gloffset_VertexAttrib3dNV 705
+#define _gloffset_VertexAttrib3dvNV 706
+#define _gloffset_VertexAttrib3fNV 707
+#define _gloffset_VertexAttrib3fvNV 708
+#define _gloffset_VertexAttrib3sNV 709
+#define _gloffset_VertexAttrib3svNV 710
+#define _gloffset_VertexAttrib4dNV 711
+#define _gloffset_VertexAttrib4dvNV 712
+#define _gloffset_VertexAttrib4fNV 713
+#define _gloffset_VertexAttrib4fvNV 714
+#define _gloffset_VertexAttrib4sNV 715
+#define _gloffset_VertexAttrib4svNV 716
+#define _gloffset_VertexAttrib4ubNV 717
+#define _gloffset_VertexAttrib4ubvNV 718
+#define _gloffset_VertexAttribPointerNV 719
+#define _gloffset_VertexAttribs1dvNV 720
+#define _gloffset_VertexAttribs1fvNV 721
+#define _gloffset_VertexAttribs1svNV 722
+#define _gloffset_VertexAttribs2dvNV 723
+#define _gloffset_VertexAttribs2fvNV 724
+#define _gloffset_VertexAttribs2svNV 725
+#define _gloffset_VertexAttribs3dvNV 726
+#define _gloffset_VertexAttribs3fvNV 727
+#define _gloffset_VertexAttribs3svNV 728
+#define _gloffset_VertexAttribs4dvNV 729
+#define _gloffset_VertexAttribs4fvNV 730
+#define _gloffset_VertexAttribs4svNV 731
+#define _gloffset_VertexAttribs4ubvNV 732
+#define _gloffset_GetTexBumpParameterfvATI 733
+#define _gloffset_GetTexBumpParameterivATI 734
+#define _gloffset_TexBumpParameterfvATI 735
+#define _gloffset_TexBumpParameterivATI 736
+#define _gloffset_AlphaFragmentOp1ATI 737
+#define _gloffset_AlphaFragmentOp2ATI 738
+#define _gloffset_AlphaFragmentOp3ATI 739
+#define _gloffset_BeginFragmentShaderATI 740
+#define _gloffset_BindFragmentShaderATI 741
+#define _gloffset_ColorFragmentOp1ATI 742
+#define _gloffset_ColorFragmentOp2ATI 743
+#define _gloffset_ColorFragmentOp3ATI 744
+#define _gloffset_DeleteFragmentShaderATI 745
+#define _gloffset_EndFragmentShaderATI 746
+#define _gloffset_GenFragmentShadersATI 747
+#define _gloffset_PassTexCoordATI 748
+#define _gloffset_SampleMapATI 749
+#define _gloffset_SetFragmentShaderConstantATI 750
+#define _gloffset_PointParameteriNV 751
+#define _gloffset_PointParameterivNV 752
+#define _gloffset_ActiveStencilFaceEXT 753
+#define _gloffset_BindVertexArrayAPPLE 754
+#define _gloffset_DeleteVertexArraysAPPLE 755
+#define _gloffset_GenVertexArraysAPPLE 756
+#define _gloffset_IsVertexArrayAPPLE 757
+#define _gloffset_GetProgramNamedParameterdvNV 758
+#define _gloffset_GetProgramNamedParameterfvNV 759
+#define _gloffset_ProgramNamedParameter4dNV 760
+#define _gloffset_ProgramNamedParameter4dvNV 761
+#define _gloffset_ProgramNamedParameter4fNV 762
+#define _gloffset_ProgramNamedParameter4fvNV 763
+#define _gloffset_DepthBoundsEXT 764
+#define _gloffset_BlendEquationSeparateEXT 765
+#define _gloffset_BindFramebufferEXT 766
+#define _gloffset_BindRenderbufferEXT 767
+#define _gloffset_CheckFramebufferStatusEXT 768
+#define _gloffset_DeleteFramebuffersEXT 769
+#define _gloffset_DeleteRenderbuffersEXT 770
+#define _gloffset_FramebufferRenderbufferEXT 771
+#define _gloffset_FramebufferTexture1DEXT 772
+#define _gloffset_FramebufferTexture2DEXT 773
+#define _gloffset_FramebufferTexture3DEXT 774
+#define _gloffset_GenFramebuffersEXT 775
+#define _gloffset_GenRenderbuffersEXT 776
+#define _gloffset_GenerateMipmapEXT 777
+#define _gloffset_GetFramebufferAttachmentParameterivEXT 778
+#define _gloffset_GetRenderbufferParameterivEXT 779
+#define _gloffset_IsFramebufferEXT 780
+#define _gloffset_IsRenderbufferEXT 781
+#define _gloffset_RenderbufferStorageEXT 782
+#define _gloffset_BlitFramebufferEXT 783
+#define _gloffset_BufferParameteriAPPLE 784
+#define _gloffset_FlushMappedBufferRangeAPPLE 785
+#define _gloffset_FramebufferTextureLayerEXT 786
+#define _gloffset_ProvokingVertexEXT 787
+#define _gloffset_GetTexParameterPointervAPPLE 788
+#define _gloffset_TextureRangeAPPLE 789
+#define _gloffset_StencilFuncSeparateATI 790
+#define _gloffset_ProgramEnvParameters4fvEXT 791
+#define _gloffset_ProgramLocalParameters4fvEXT 792
+#define _gloffset_GetQueryObjecti64vEXT 793
+#define _gloffset_GetQueryObjectui64vEXT 794
+#define _gloffset_FIRST_DYNAMIC 795
#else
@@ -959,6 +984,22 @@
#define _gloffset_GetActiveAttribARB driDispatchRemapTable[GetActiveAttribARB_remap_index]
#define _gloffset_GetAttribLocationARB driDispatchRemapTable[GetAttribLocationARB_remap_index]
#define _gloffset_DrawBuffersARB driDispatchRemapTable[DrawBuffersARB_remap_index]
+#define _gloffset_RenderbufferStorageMultisample driDispatchRemapTable[RenderbufferStorageMultisample_remap_index]
+#define _gloffset_FlushMappedBufferRange driDispatchRemapTable[FlushMappedBufferRange_remap_index]
+#define _gloffset_MapBufferRange driDispatchRemapTable[MapBufferRange_remap_index]
+#define _gloffset_BindVertexArray driDispatchRemapTable[BindVertexArray_remap_index]
+#define _gloffset_GenVertexArrays driDispatchRemapTable[GenVertexArrays_remap_index]
+#define _gloffset_CopyBufferSubData driDispatchRemapTable[CopyBufferSubData_remap_index]
+#define _gloffset_ClientWaitSync driDispatchRemapTable[ClientWaitSync_remap_index]
+#define _gloffset_DeleteSync driDispatchRemapTable[DeleteSync_remap_index]
+#define _gloffset_FenceSync driDispatchRemapTable[FenceSync_remap_index]
+#define _gloffset_GetInteger64v driDispatchRemapTable[GetInteger64v_remap_index]
+#define _gloffset_GetSynciv driDispatchRemapTable[GetSynciv_remap_index]
+#define _gloffset_IsSync driDispatchRemapTable[IsSync_remap_index]
+#define _gloffset_WaitSync driDispatchRemapTable[WaitSync_remap_index]
+#define _gloffset_DrawElementsBaseVertex driDispatchRemapTable[DrawElementsBaseVertex_remap_index]
+#define _gloffset_DrawRangeElementsBaseVertex driDispatchRemapTable[DrawRangeElementsBaseVertex_remap_index]
+#define _gloffset_MultiDrawElementsBaseVertex driDispatchRemapTable[MultiDrawElementsBaseVertex_remap_index]
#define _gloffset_PolygonOffsetEXT driDispatchRemapTable[PolygonOffsetEXT_remap_index]
#define _gloffset_GetPixelTexGenParameterfvSGIS driDispatchRemapTable[GetPixelTexGenParameterfvSGIS_remap_index]
#define _gloffset_GetPixelTexGenParameterivSGIS driDispatchRemapTable[GetPixelTexGenParameterivSGIS_remap_index]
@@ -1115,6 +1156,10 @@
#define _gloffset_VertexAttribs4fvNV driDispatchRemapTable[VertexAttribs4fvNV_remap_index]
#define _gloffset_VertexAttribs4svNV driDispatchRemapTable[VertexAttribs4svNV_remap_index]
#define _gloffset_VertexAttribs4ubvNV driDispatchRemapTable[VertexAttribs4ubvNV_remap_index]
+#define _gloffset_GetTexBumpParameterfvATI driDispatchRemapTable[GetTexBumpParameterfvATI_remap_index]
+#define _gloffset_GetTexBumpParameterivATI driDispatchRemapTable[GetTexBumpParameterivATI_remap_index]
+#define _gloffset_TexBumpParameterfvATI driDispatchRemapTable[TexBumpParameterfvATI_remap_index]
+#define _gloffset_TexBumpParameterivATI driDispatchRemapTable[TexBumpParameterivATI_remap_index]
#define _gloffset_AlphaFragmentOp1ATI driDispatchRemapTable[AlphaFragmentOp1ATI_remap_index]
#define _gloffset_AlphaFragmentOp2ATI driDispatchRemapTable[AlphaFragmentOp2ATI_remap_index]
#define _gloffset_AlphaFragmentOp3ATI driDispatchRemapTable[AlphaFragmentOp3ATI_remap_index]
@@ -1162,7 +1207,12 @@
#define _gloffset_IsRenderbufferEXT driDispatchRemapTable[IsRenderbufferEXT_remap_index]
#define _gloffset_RenderbufferStorageEXT driDispatchRemapTable[RenderbufferStorageEXT_remap_index]
#define _gloffset_BlitFramebufferEXT driDispatchRemapTable[BlitFramebufferEXT_remap_index]
+#define _gloffset_BufferParameteriAPPLE driDispatchRemapTable[BufferParameteriAPPLE_remap_index]
+#define _gloffset_FlushMappedBufferRangeAPPLE driDispatchRemapTable[FlushMappedBufferRangeAPPLE_remap_index]
#define _gloffset_FramebufferTextureLayerEXT driDispatchRemapTable[FramebufferTextureLayerEXT_remap_index]
+#define _gloffset_ProvokingVertexEXT driDispatchRemapTable[ProvokingVertexEXT_remap_index]
+#define _gloffset_GetTexParameterPointervAPPLE driDispatchRemapTable[GetTexParameterPointervAPPLE_remap_index]
+#define _gloffset_TextureRangeAPPLE driDispatchRemapTable[TextureRangeAPPLE_remap_index]
#define _gloffset_StencilFuncSeparateATI driDispatchRemapTable[StencilFuncSeparateATI_remap_index]
#define _gloffset_ProgramEnvParameters4fvEXT driDispatchRemapTable[ProgramEnvParameters4fvEXT_remap_index]
#define _gloffset_ProgramLocalParameters4fvEXT driDispatchRemapTable[ProgramLocalParameters4fvEXT_remap_index]
diff --git a/src/mesa/glapi/glapitable.h b/src/mesa/glapi/glapitable.h
index 5d9d40a8a2..4f9e53b62d 100644
--- a/src/mesa/glapi/glapitable.h
+++ b/src/mesa/glapi/glapitable.h
@@ -601,215 +601,240 @@ struct _glapi_table
void (GLAPIENTRYP GetActiveAttribARB)(GLhandleARB program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name); /* 558 */
GLint (GLAPIENTRYP GetAttribLocationARB)(GLhandleARB program, const GLcharARB * name); /* 559 */
void (GLAPIENTRYP DrawBuffersARB)(GLsizei n, const GLenum * bufs); /* 560 */
- void (GLAPIENTRYP PolygonOffsetEXT)(GLfloat factor, GLfloat bias); /* 561 */
- void (GLAPIENTRYP GetPixelTexGenParameterfvSGIS)(GLenum pname, GLfloat * params); /* 562 */
- void (GLAPIENTRYP GetPixelTexGenParameterivSGIS)(GLenum pname, GLint * params); /* 563 */
- void (GLAPIENTRYP PixelTexGenParameterfSGIS)(GLenum pname, GLfloat param); /* 564 */
- void (GLAPIENTRYP PixelTexGenParameterfvSGIS)(GLenum pname, const GLfloat * params); /* 565 */
- void (GLAPIENTRYP PixelTexGenParameteriSGIS)(GLenum pname, GLint param); /* 566 */
- void (GLAPIENTRYP PixelTexGenParameterivSGIS)(GLenum pname, const GLint * params); /* 567 */
- void (GLAPIENTRYP SampleMaskSGIS)(GLclampf value, GLboolean invert); /* 568 */
- void (GLAPIENTRYP SamplePatternSGIS)(GLenum pattern); /* 569 */
- void (GLAPIENTRYP ColorPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 570 */
- void (GLAPIENTRYP EdgeFlagPointerEXT)(GLsizei stride, GLsizei count, const GLboolean * pointer); /* 571 */
- void (GLAPIENTRYP IndexPointerEXT)(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 572 */
- void (GLAPIENTRYP NormalPointerEXT)(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 573 */
- void (GLAPIENTRYP TexCoordPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 574 */
- void (GLAPIENTRYP VertexPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 575 */
- void (GLAPIENTRYP PointParameterfEXT)(GLenum pname, GLfloat param); /* 576 */
- void (GLAPIENTRYP PointParameterfvEXT)(GLenum pname, const GLfloat * params); /* 577 */
- void (GLAPIENTRYP LockArraysEXT)(GLint first, GLsizei count); /* 578 */
- void (GLAPIENTRYP UnlockArraysEXT)(void); /* 579 */
- void (GLAPIENTRYP CullParameterdvEXT)(GLenum pname, GLdouble * params); /* 580 */
- void (GLAPIENTRYP CullParameterfvEXT)(GLenum pname, GLfloat * params); /* 581 */
- void (GLAPIENTRYP SecondaryColor3bEXT)(GLbyte red, GLbyte green, GLbyte blue); /* 582 */
- void (GLAPIENTRYP SecondaryColor3bvEXT)(const GLbyte * v); /* 583 */
- void (GLAPIENTRYP SecondaryColor3dEXT)(GLdouble red, GLdouble green, GLdouble blue); /* 584 */
- void (GLAPIENTRYP SecondaryColor3dvEXT)(const GLdouble * v); /* 585 */
- void (GLAPIENTRYP SecondaryColor3fEXT)(GLfloat red, GLfloat green, GLfloat blue); /* 586 */
- void (GLAPIENTRYP SecondaryColor3fvEXT)(const GLfloat * v); /* 587 */
- void (GLAPIENTRYP SecondaryColor3iEXT)(GLint red, GLint green, GLint blue); /* 588 */
- void (GLAPIENTRYP SecondaryColor3ivEXT)(const GLint * v); /* 589 */
- void (GLAPIENTRYP SecondaryColor3sEXT)(GLshort red, GLshort green, GLshort blue); /* 590 */
- void (GLAPIENTRYP SecondaryColor3svEXT)(const GLshort * v); /* 591 */
- void (GLAPIENTRYP SecondaryColor3ubEXT)(GLubyte red, GLubyte green, GLubyte blue); /* 592 */
- void (GLAPIENTRYP SecondaryColor3ubvEXT)(const GLubyte * v); /* 593 */
- void (GLAPIENTRYP SecondaryColor3uiEXT)(GLuint red, GLuint green, GLuint blue); /* 594 */
- void (GLAPIENTRYP SecondaryColor3uivEXT)(const GLuint * v); /* 595 */
- void (GLAPIENTRYP SecondaryColor3usEXT)(GLushort red, GLushort green, GLushort blue); /* 596 */
- void (GLAPIENTRYP SecondaryColor3usvEXT)(const GLushort * v); /* 597 */
- void (GLAPIENTRYP SecondaryColorPointerEXT)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); /* 598 */
- void (GLAPIENTRYP MultiDrawArraysEXT)(GLenum mode, GLint * first, GLsizei * count, GLsizei primcount); /* 599 */
- void (GLAPIENTRYP MultiDrawElementsEXT)(GLenum mode, const GLsizei * count, GLenum type, const GLvoid ** indices, GLsizei primcount); /* 600 */
- void (GLAPIENTRYP FogCoordPointerEXT)(GLenum type, GLsizei stride, const GLvoid * pointer); /* 601 */
- void (GLAPIENTRYP FogCoorddEXT)(GLdouble coord); /* 602 */
- void (GLAPIENTRYP FogCoorddvEXT)(const GLdouble * coord); /* 603 */
- void (GLAPIENTRYP FogCoordfEXT)(GLfloat coord); /* 604 */
- void (GLAPIENTRYP FogCoordfvEXT)(const GLfloat * coord); /* 605 */
- void (GLAPIENTRYP PixelTexGenSGIX)(GLenum mode); /* 606 */
- void (GLAPIENTRYP BlendFuncSeparateEXT)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); /* 607 */
- void (GLAPIENTRYP FlushVertexArrayRangeNV)(void); /* 608 */
- void (GLAPIENTRYP VertexArrayRangeNV)(GLsizei length, const GLvoid * pointer); /* 609 */
- void (GLAPIENTRYP CombinerInputNV)(GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); /* 610 */
- void (GLAPIENTRYP CombinerOutputNV)(GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); /* 611 */
- void (GLAPIENTRYP CombinerParameterfNV)(GLenum pname, GLfloat param); /* 612 */
- void (GLAPIENTRYP CombinerParameterfvNV)(GLenum pname, const GLfloat * params); /* 613 */
- void (GLAPIENTRYP CombinerParameteriNV)(GLenum pname, GLint param); /* 614 */
- void (GLAPIENTRYP CombinerParameterivNV)(GLenum pname, const GLint * params); /* 615 */
- void (GLAPIENTRYP FinalCombinerInputNV)(GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); /* 616 */
- void (GLAPIENTRYP GetCombinerInputParameterfvNV)(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat * params); /* 617 */
- void (GLAPIENTRYP GetCombinerInputParameterivNV)(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint * params); /* 618 */
- void (GLAPIENTRYP GetCombinerOutputParameterfvNV)(GLenum stage, GLenum portion, GLenum pname, GLfloat * params); /* 619 */
- void (GLAPIENTRYP GetCombinerOutputParameterivNV)(GLenum stage, GLenum portion, GLenum pname, GLint * params); /* 620 */
- void (GLAPIENTRYP GetFinalCombinerInputParameterfvNV)(GLenum variable, GLenum pname, GLfloat * params); /* 621 */
- void (GLAPIENTRYP GetFinalCombinerInputParameterivNV)(GLenum variable, GLenum pname, GLint * params); /* 622 */
- void (GLAPIENTRYP ResizeBuffersMESA)(void); /* 623 */
- void (GLAPIENTRYP WindowPos2dMESA)(GLdouble x, GLdouble y); /* 624 */
- void (GLAPIENTRYP WindowPos2dvMESA)(const GLdouble * v); /* 625 */
- void (GLAPIENTRYP WindowPos2fMESA)(GLfloat x, GLfloat y); /* 626 */
- void (GLAPIENTRYP WindowPos2fvMESA)(const GLfloat * v); /* 627 */
- void (GLAPIENTRYP WindowPos2iMESA)(GLint x, GLint y); /* 628 */
- void (GLAPIENTRYP WindowPos2ivMESA)(const GLint * v); /* 629 */
- void (GLAPIENTRYP WindowPos2sMESA)(GLshort x, GLshort y); /* 630 */
- void (GLAPIENTRYP WindowPos2svMESA)(const GLshort * v); /* 631 */
- void (GLAPIENTRYP WindowPos3dMESA)(GLdouble x, GLdouble y, GLdouble z); /* 632 */
- void (GLAPIENTRYP WindowPos3dvMESA)(const GLdouble * v); /* 633 */
- void (GLAPIENTRYP WindowPos3fMESA)(GLfloat x, GLfloat y, GLfloat z); /* 634 */
- void (GLAPIENTRYP WindowPos3fvMESA)(const GLfloat * v); /* 635 */
- void (GLAPIENTRYP WindowPos3iMESA)(GLint x, GLint y, GLint z); /* 636 */
- void (GLAPIENTRYP WindowPos3ivMESA)(const GLint * v); /* 637 */
- void (GLAPIENTRYP WindowPos3sMESA)(GLshort x, GLshort y, GLshort z); /* 638 */
- void (GLAPIENTRYP WindowPos3svMESA)(const GLshort * v); /* 639 */
- void (GLAPIENTRYP WindowPos4dMESA)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 640 */
- void (GLAPIENTRYP WindowPos4dvMESA)(const GLdouble * v); /* 641 */
- void (GLAPIENTRYP WindowPos4fMESA)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 642 */
- void (GLAPIENTRYP WindowPos4fvMESA)(const GLfloat * v); /* 643 */
- void (GLAPIENTRYP WindowPos4iMESA)(GLint x, GLint y, GLint z, GLint w); /* 644 */
- void (GLAPIENTRYP WindowPos4ivMESA)(const GLint * v); /* 645 */
- void (GLAPIENTRYP WindowPos4sMESA)(GLshort x, GLshort y, GLshort z, GLshort w); /* 646 */
- void (GLAPIENTRYP WindowPos4svMESA)(const GLshort * v); /* 647 */
- void (GLAPIENTRYP MultiModeDrawArraysIBM)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride); /* 648 */
- void (GLAPIENTRYP MultiModeDrawElementsIBM)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride); /* 649 */
- void (GLAPIENTRYP DeleteFencesNV)(GLsizei n, const GLuint * fences); /* 650 */
- void (GLAPIENTRYP FinishFenceNV)(GLuint fence); /* 651 */
- void (GLAPIENTRYP GenFencesNV)(GLsizei n, GLuint * fences); /* 652 */
- void (GLAPIENTRYP GetFenceivNV)(GLuint fence, GLenum pname, GLint * params); /* 653 */
- GLboolean (GLAPIENTRYP IsFenceNV)(GLuint fence); /* 654 */
- void (GLAPIENTRYP SetFenceNV)(GLuint fence, GLenum condition); /* 655 */
- GLboolean (GLAPIENTRYP TestFenceNV)(GLuint fence); /* 656 */
- GLboolean (GLAPIENTRYP AreProgramsResidentNV)(GLsizei n, const GLuint * ids, GLboolean * residences); /* 657 */
- void (GLAPIENTRYP BindProgramNV)(GLenum target, GLuint program); /* 658 */
- void (GLAPIENTRYP DeleteProgramsNV)(GLsizei n, const GLuint * programs); /* 659 */
- void (GLAPIENTRYP ExecuteProgramNV)(GLenum target, GLuint id, const GLfloat * params); /* 660 */
- void (GLAPIENTRYP GenProgramsNV)(GLsizei n, GLuint * programs); /* 661 */
- void (GLAPIENTRYP GetProgramParameterdvNV)(GLenum target, GLuint index, GLenum pname, GLdouble * params); /* 662 */
- void (GLAPIENTRYP GetProgramParameterfvNV)(GLenum target, GLuint index, GLenum pname, GLfloat * params); /* 663 */
- void (GLAPIENTRYP GetProgramStringNV)(GLuint id, GLenum pname, GLubyte * program); /* 664 */
- void (GLAPIENTRYP GetProgramivNV)(GLuint id, GLenum pname, GLint * params); /* 665 */
- void (GLAPIENTRYP GetTrackMatrixivNV)(GLenum target, GLuint address, GLenum pname, GLint * params); /* 666 */
- void (GLAPIENTRYP GetVertexAttribPointervNV)(GLuint index, GLenum pname, GLvoid ** pointer); /* 667 */
- void (GLAPIENTRYP GetVertexAttribdvNV)(GLuint index, GLenum pname, GLdouble * params); /* 668 */
- void (GLAPIENTRYP GetVertexAttribfvNV)(GLuint index, GLenum pname, GLfloat * params); /* 669 */
- void (GLAPIENTRYP GetVertexAttribivNV)(GLuint index, GLenum pname, GLint * params); /* 670 */
- GLboolean (GLAPIENTRYP IsProgramNV)(GLuint program); /* 671 */
- void (GLAPIENTRYP LoadProgramNV)(GLenum target, GLuint id, GLsizei len, const GLubyte * program); /* 672 */
- void (GLAPIENTRYP ProgramParameters4dvNV)(GLenum target, GLuint index, GLuint num, const GLdouble * params); /* 673 */
- void (GLAPIENTRYP ProgramParameters4fvNV)(GLenum target, GLuint index, GLuint num, const GLfloat * params); /* 674 */
- void (GLAPIENTRYP RequestResidentProgramsNV)(GLsizei n, const GLuint * ids); /* 675 */
- void (GLAPIENTRYP TrackMatrixNV)(GLenum target, GLuint address, GLenum matrix, GLenum transform); /* 676 */
- void (GLAPIENTRYP VertexAttrib1dNV)(GLuint index, GLdouble x); /* 677 */
- void (GLAPIENTRYP VertexAttrib1dvNV)(GLuint index, const GLdouble * v); /* 678 */
- void (GLAPIENTRYP VertexAttrib1fNV)(GLuint index, GLfloat x); /* 679 */
- void (GLAPIENTRYP VertexAttrib1fvNV)(GLuint index, const GLfloat * v); /* 680 */
- void (GLAPIENTRYP VertexAttrib1sNV)(GLuint index, GLshort x); /* 681 */
- void (GLAPIENTRYP VertexAttrib1svNV)(GLuint index, const GLshort * v); /* 682 */
- void (GLAPIENTRYP VertexAttrib2dNV)(GLuint index, GLdouble x, GLdouble y); /* 683 */
- void (GLAPIENTRYP VertexAttrib2dvNV)(GLuint index, const GLdouble * v); /* 684 */
- void (GLAPIENTRYP VertexAttrib2fNV)(GLuint index, GLfloat x, GLfloat y); /* 685 */
- void (GLAPIENTRYP VertexAttrib2fvNV)(GLuint index, const GLfloat * v); /* 686 */
- void (GLAPIENTRYP VertexAttrib2sNV)(GLuint index, GLshort x, GLshort y); /* 687 */
- void (GLAPIENTRYP VertexAttrib2svNV)(GLuint index, const GLshort * v); /* 688 */
- void (GLAPIENTRYP VertexAttrib3dNV)(GLuint index, GLdouble x, GLdouble y, GLdouble z); /* 689 */
- void (GLAPIENTRYP VertexAttrib3dvNV)(GLuint index, const GLdouble * v); /* 690 */
- void (GLAPIENTRYP VertexAttrib3fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z); /* 691 */
- void (GLAPIENTRYP VertexAttrib3fvNV)(GLuint index, const GLfloat * v); /* 692 */
- void (GLAPIENTRYP VertexAttrib3sNV)(GLuint index, GLshort x, GLshort y, GLshort z); /* 693 */
- void (GLAPIENTRYP VertexAttrib3svNV)(GLuint index, const GLshort * v); /* 694 */
- void (GLAPIENTRYP VertexAttrib4dNV)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 695 */
- void (GLAPIENTRYP VertexAttrib4dvNV)(GLuint index, const GLdouble * v); /* 696 */
- void (GLAPIENTRYP VertexAttrib4fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 697 */
- void (GLAPIENTRYP VertexAttrib4fvNV)(GLuint index, const GLfloat * v); /* 698 */
- void (GLAPIENTRYP VertexAttrib4sNV)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); /* 699 */
- void (GLAPIENTRYP VertexAttrib4svNV)(GLuint index, const GLshort * v); /* 700 */
- void (GLAPIENTRYP VertexAttrib4ubNV)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); /* 701 */
- void (GLAPIENTRYP VertexAttrib4ubvNV)(GLuint index, const GLubyte * v); /* 702 */
- void (GLAPIENTRYP VertexAttribPointerNV)(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); /* 703 */
- void (GLAPIENTRYP VertexAttribs1dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 704 */
- void (GLAPIENTRYP VertexAttribs1fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 705 */
- void (GLAPIENTRYP VertexAttribs1svNV)(GLuint index, GLsizei n, const GLshort * v); /* 706 */
- void (GLAPIENTRYP VertexAttribs2dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 707 */
- void (GLAPIENTRYP VertexAttribs2fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 708 */
- void (GLAPIENTRYP VertexAttribs2svNV)(GLuint index, GLsizei n, const GLshort * v); /* 709 */
- void (GLAPIENTRYP VertexAttribs3dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 710 */
- void (GLAPIENTRYP VertexAttribs3fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 711 */
- void (GLAPIENTRYP VertexAttribs3svNV)(GLuint index, GLsizei n, const GLshort * v); /* 712 */
- void (GLAPIENTRYP VertexAttribs4dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 713 */
- void (GLAPIENTRYP VertexAttribs4fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 714 */
- void (GLAPIENTRYP VertexAttribs4svNV)(GLuint index, GLsizei n, const GLshort * v); /* 715 */
- void (GLAPIENTRYP VertexAttribs4ubvNV)(GLuint index, GLsizei n, const GLubyte * v); /* 716 */
- void (GLAPIENTRYP AlphaFragmentOp1ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); /* 717 */
- void (GLAPIENTRYP AlphaFragmentOp2ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); /* 718 */
- void (GLAPIENTRYP AlphaFragmentOp3ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); /* 719 */
- void (GLAPIENTRYP BeginFragmentShaderATI)(void); /* 720 */
- void (GLAPIENTRYP BindFragmentShaderATI)(GLuint id); /* 721 */
- void (GLAPIENTRYP ColorFragmentOp1ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); /* 722 */
- void (GLAPIENTRYP ColorFragmentOp2ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); /* 723 */
- void (GLAPIENTRYP ColorFragmentOp3ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); /* 724 */
- void (GLAPIENTRYP DeleteFragmentShaderATI)(GLuint id); /* 725 */
- void (GLAPIENTRYP EndFragmentShaderATI)(void); /* 726 */
- GLuint (GLAPIENTRYP GenFragmentShadersATI)(GLuint range); /* 727 */
- void (GLAPIENTRYP PassTexCoordATI)(GLuint dst, GLuint coord, GLenum swizzle); /* 728 */
- void (GLAPIENTRYP SampleMapATI)(GLuint dst, GLuint interp, GLenum swizzle); /* 729 */
- void (GLAPIENTRYP SetFragmentShaderConstantATI)(GLuint dst, const GLfloat * value); /* 730 */
- void (GLAPIENTRYP PointParameteriNV)(GLenum pname, GLint param); /* 731 */
- void (GLAPIENTRYP PointParameterivNV)(GLenum pname, const GLint * params); /* 732 */
- void (GLAPIENTRYP ActiveStencilFaceEXT)(GLenum face); /* 733 */
- void (GLAPIENTRYP BindVertexArrayAPPLE)(GLuint array); /* 734 */
- void (GLAPIENTRYP DeleteVertexArraysAPPLE)(GLsizei n, const GLuint * arrays); /* 735 */
- void (GLAPIENTRYP GenVertexArraysAPPLE)(GLsizei n, GLuint * arrays); /* 736 */
- GLboolean (GLAPIENTRYP IsVertexArrayAPPLE)(GLuint array); /* 737 */
- void (GLAPIENTRYP GetProgramNamedParameterdvNV)(GLuint id, GLsizei len, const GLubyte * name, GLdouble * params); /* 738 */
- void (GLAPIENTRYP GetProgramNamedParameterfvNV)(GLuint id, GLsizei len, const GLubyte * name, GLfloat * params); /* 739 */
- void (GLAPIENTRYP ProgramNamedParameter4dNV)(GLuint id, GLsizei len, const GLubyte * name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 740 */
- void (GLAPIENTRYP ProgramNamedParameter4dvNV)(GLuint id, GLsizei len, const GLubyte * name, const GLdouble * v); /* 741 */
- void (GLAPIENTRYP ProgramNamedParameter4fNV)(GLuint id, GLsizei len, const GLubyte * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 742 */
- void (GLAPIENTRYP ProgramNamedParameter4fvNV)(GLuint id, GLsizei len, const GLubyte * name, const GLfloat * v); /* 743 */
- void (GLAPIENTRYP DepthBoundsEXT)(GLclampd zmin, GLclampd zmax); /* 744 */
- void (GLAPIENTRYP BlendEquationSeparateEXT)(GLenum modeRGB, GLenum modeA); /* 745 */
- void (GLAPIENTRYP BindFramebufferEXT)(GLenum target, GLuint framebuffer); /* 746 */
- void (GLAPIENTRYP BindRenderbufferEXT)(GLenum target, GLuint renderbuffer); /* 747 */
- GLenum (GLAPIENTRYP CheckFramebufferStatusEXT)(GLenum target); /* 748 */
- void (GLAPIENTRYP DeleteFramebuffersEXT)(GLsizei n, const GLuint * framebuffers); /* 749 */
- void (GLAPIENTRYP DeleteRenderbuffersEXT)(GLsizei n, const GLuint * renderbuffers); /* 750 */
- void (GLAPIENTRYP FramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); /* 751 */
- void (GLAPIENTRYP FramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); /* 752 */
- void (GLAPIENTRYP FramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); /* 753 */
- void (GLAPIENTRYP FramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); /* 754 */
- void (GLAPIENTRYP GenFramebuffersEXT)(GLsizei n, GLuint * framebuffers); /* 755 */
- void (GLAPIENTRYP GenRenderbuffersEXT)(GLsizei n, GLuint * renderbuffers); /* 756 */
- void (GLAPIENTRYP GenerateMipmapEXT)(GLenum target); /* 757 */
- void (GLAPIENTRYP GetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint * params); /* 758 */
- void (GLAPIENTRYP GetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint * params); /* 759 */
- GLboolean (GLAPIENTRYP IsFramebufferEXT)(GLuint framebuffer); /* 760 */
- GLboolean (GLAPIENTRYP IsRenderbufferEXT)(GLuint renderbuffer); /* 761 */
- void (GLAPIENTRYP RenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); /* 762 */
- void (GLAPIENTRYP BlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); /* 763 */
- void (GLAPIENTRYP FramebufferTextureLayerEXT)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); /* 764 */
- void (GLAPIENTRYP StencilFuncSeparateATI)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); /* 765 */
- void (GLAPIENTRYP ProgramEnvParameters4fvEXT)(GLenum target, GLuint index, GLsizei count, const GLfloat * params); /* 766 */
- void (GLAPIENTRYP ProgramLocalParameters4fvEXT)(GLenum target, GLuint index, GLsizei count, const GLfloat * params); /* 767 */
- void (GLAPIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT * params); /* 768 */
- void (GLAPIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT * params); /* 769 */
+ void (GLAPIENTRYP RenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); /* 561 */
+ void (GLAPIENTRYP FlushMappedBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length); /* 562 */
+ GLvoid * (GLAPIENTRYP MapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); /* 563 */
+ void (GLAPIENTRYP BindVertexArray)(GLuint array); /* 564 */
+ void (GLAPIENTRYP GenVertexArrays)(GLsizei n, GLuint * arrays); /* 565 */
+ void (GLAPIENTRYP CopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); /* 566 */
+ GLenum (GLAPIENTRYP ClientWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout); /* 567 */
+ void (GLAPIENTRYP DeleteSync)(GLsync sync); /* 568 */
+ GLsync (GLAPIENTRYP FenceSync)(GLenum condition, GLbitfield flags); /* 569 */
+ void (GLAPIENTRYP GetInteger64v)(GLenum pname, GLint64 * params); /* 570 */
+ void (GLAPIENTRYP GetSynciv)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values); /* 571 */
+ GLboolean (GLAPIENTRYP IsSync)(GLsync sync); /* 572 */
+ void (GLAPIENTRYP WaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout); /* 573 */
+ void (GLAPIENTRYP DrawElementsBaseVertex)(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices, GLint basevertex); /* 574 */
+ void (GLAPIENTRYP DrawRangeElementsBaseVertex)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices, GLint basevertex); /* 575 */
+ void (GLAPIENTRYP MultiDrawElementsBaseVertex)(GLenum mode, const GLsizei * count, GLenum type, const GLvoid ** indices, GLsizei primcount, const GLint * basevertex); /* 576 */
+ void (GLAPIENTRYP PolygonOffsetEXT)(GLfloat factor, GLfloat bias); /* 577 */
+ void (GLAPIENTRYP GetPixelTexGenParameterfvSGIS)(GLenum pname, GLfloat * params); /* 578 */
+ void (GLAPIENTRYP GetPixelTexGenParameterivSGIS)(GLenum pname, GLint * params); /* 579 */
+ void (GLAPIENTRYP PixelTexGenParameterfSGIS)(GLenum pname, GLfloat param); /* 580 */
+ void (GLAPIENTRYP PixelTexGenParameterfvSGIS)(GLenum pname, const GLfloat * params); /* 581 */
+ void (GLAPIENTRYP PixelTexGenParameteriSGIS)(GLenum pname, GLint param); /* 582 */
+ void (GLAPIENTRYP PixelTexGenParameterivSGIS)(GLenum pname, const GLint * params); /* 583 */
+ void (GLAPIENTRYP SampleMaskSGIS)(GLclampf value, GLboolean invert); /* 584 */
+ void (GLAPIENTRYP SamplePatternSGIS)(GLenum pattern); /* 585 */
+ void (GLAPIENTRYP ColorPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 586 */
+ void (GLAPIENTRYP EdgeFlagPointerEXT)(GLsizei stride, GLsizei count, const GLboolean * pointer); /* 587 */
+ void (GLAPIENTRYP IndexPointerEXT)(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 588 */
+ void (GLAPIENTRYP NormalPointerEXT)(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 589 */
+ void (GLAPIENTRYP TexCoordPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 590 */
+ void (GLAPIENTRYP VertexPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 591 */
+ void (GLAPIENTRYP PointParameterfEXT)(GLenum pname, GLfloat param); /* 592 */
+ void (GLAPIENTRYP PointParameterfvEXT)(GLenum pname, const GLfloat * params); /* 593 */
+ void (GLAPIENTRYP LockArraysEXT)(GLint first, GLsizei count); /* 594 */
+ void (GLAPIENTRYP UnlockArraysEXT)(void); /* 595 */
+ void (GLAPIENTRYP CullParameterdvEXT)(GLenum pname, GLdouble * params); /* 596 */
+ void (GLAPIENTRYP CullParameterfvEXT)(GLenum pname, GLfloat * params); /* 597 */
+ void (GLAPIENTRYP SecondaryColor3bEXT)(GLbyte red, GLbyte green, GLbyte blue); /* 598 */
+ void (GLAPIENTRYP SecondaryColor3bvEXT)(const GLbyte * v); /* 599 */
+ void (GLAPIENTRYP SecondaryColor3dEXT)(GLdouble red, GLdouble green, GLdouble blue); /* 600 */
+ void (GLAPIENTRYP SecondaryColor3dvEXT)(const GLdouble * v); /* 601 */
+ void (GLAPIENTRYP SecondaryColor3fEXT)(GLfloat red, GLfloat green, GLfloat blue); /* 602 */
+ void (GLAPIENTRYP SecondaryColor3fvEXT)(const GLfloat * v); /* 603 */
+ void (GLAPIENTRYP SecondaryColor3iEXT)(GLint red, GLint green, GLint blue); /* 604 */
+ void (GLAPIENTRYP SecondaryColor3ivEXT)(const GLint * v); /* 605 */
+ void (GLAPIENTRYP SecondaryColor3sEXT)(GLshort red, GLshort green, GLshort blue); /* 606 */
+ void (GLAPIENTRYP SecondaryColor3svEXT)(const GLshort * v); /* 607 */
+ void (GLAPIENTRYP SecondaryColor3ubEXT)(GLubyte red, GLubyte green, GLubyte blue); /* 608 */
+ void (GLAPIENTRYP SecondaryColor3ubvEXT)(const GLubyte * v); /* 609 */
+ void (GLAPIENTRYP SecondaryColor3uiEXT)(GLuint red, GLuint green, GLuint blue); /* 610 */
+ void (GLAPIENTRYP SecondaryColor3uivEXT)(const GLuint * v); /* 611 */
+ void (GLAPIENTRYP SecondaryColor3usEXT)(GLushort red, GLushort green, GLushort blue); /* 612 */
+ void (GLAPIENTRYP SecondaryColor3usvEXT)(const GLushort * v); /* 613 */
+ void (GLAPIENTRYP SecondaryColorPointerEXT)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); /* 614 */
+ void (GLAPIENTRYP MultiDrawArraysEXT)(GLenum mode, GLint * first, GLsizei * count, GLsizei primcount); /* 615 */
+ void (GLAPIENTRYP MultiDrawElementsEXT)(GLenum mode, const GLsizei * count, GLenum type, const GLvoid ** indices, GLsizei primcount); /* 616 */
+ void (GLAPIENTRYP FogCoordPointerEXT)(GLenum type, GLsizei stride, const GLvoid * pointer); /* 617 */
+ void (GLAPIENTRYP FogCoorddEXT)(GLdouble coord); /* 618 */
+ void (GLAPIENTRYP FogCoorddvEXT)(const GLdouble * coord); /* 619 */
+ void (GLAPIENTRYP FogCoordfEXT)(GLfloat coord); /* 620 */
+ void (GLAPIENTRYP FogCoordfvEXT)(const GLfloat * coord); /* 621 */
+ void (GLAPIENTRYP PixelTexGenSGIX)(GLenum mode); /* 622 */
+ void (GLAPIENTRYP BlendFuncSeparateEXT)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); /* 623 */
+ void (GLAPIENTRYP FlushVertexArrayRangeNV)(void); /* 624 */
+ void (GLAPIENTRYP VertexArrayRangeNV)(GLsizei length, const GLvoid * pointer); /* 625 */
+ void (GLAPIENTRYP CombinerInputNV)(GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); /* 626 */
+ void (GLAPIENTRYP CombinerOutputNV)(GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); /* 627 */
+ void (GLAPIENTRYP CombinerParameterfNV)(GLenum pname, GLfloat param); /* 628 */
+ void (GLAPIENTRYP CombinerParameterfvNV)(GLenum pname, const GLfloat * params); /* 629 */
+ void (GLAPIENTRYP CombinerParameteriNV)(GLenum pname, GLint param); /* 630 */
+ void (GLAPIENTRYP CombinerParameterivNV)(GLenum pname, const GLint * params); /* 631 */
+ void (GLAPIENTRYP FinalCombinerInputNV)(GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); /* 632 */
+ void (GLAPIENTRYP GetCombinerInputParameterfvNV)(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat * params); /* 633 */
+ void (GLAPIENTRYP GetCombinerInputParameterivNV)(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint * params); /* 634 */
+ void (GLAPIENTRYP GetCombinerOutputParameterfvNV)(GLenum stage, GLenum portion, GLenum pname, GLfloat * params); /* 635 */
+ void (GLAPIENTRYP GetCombinerOutputParameterivNV)(GLenum stage, GLenum portion, GLenum pname, GLint * params); /* 636 */
+ void (GLAPIENTRYP GetFinalCombinerInputParameterfvNV)(GLenum variable, GLenum pname, GLfloat * params); /* 637 */
+ void (GLAPIENTRYP GetFinalCombinerInputParameterivNV)(GLenum variable, GLenum pname, GLint * params); /* 638 */
+ void (GLAPIENTRYP ResizeBuffersMESA)(void); /* 639 */
+ void (GLAPIENTRYP WindowPos2dMESA)(GLdouble x, GLdouble y); /* 640 */
+ void (GLAPIENTRYP WindowPos2dvMESA)(const GLdouble * v); /* 641 */
+ void (GLAPIENTRYP WindowPos2fMESA)(GLfloat x, GLfloat y); /* 642 */
+ void (GLAPIENTRYP WindowPos2fvMESA)(const GLfloat * v); /* 643 */
+ void (GLAPIENTRYP WindowPos2iMESA)(GLint x, GLint y); /* 644 */
+ void (GLAPIENTRYP WindowPos2ivMESA)(const GLint * v); /* 645 */
+ void (GLAPIENTRYP WindowPos2sMESA)(GLshort x, GLshort y); /* 646 */
+ void (GLAPIENTRYP WindowPos2svMESA)(const GLshort * v); /* 647 */
+ void (GLAPIENTRYP WindowPos3dMESA)(GLdouble x, GLdouble y, GLdouble z); /* 648 */
+ void (GLAPIENTRYP WindowPos3dvMESA)(const GLdouble * v); /* 649 */
+ void (GLAPIENTRYP WindowPos3fMESA)(GLfloat x, GLfloat y, GLfloat z); /* 650 */
+ void (GLAPIENTRYP WindowPos3fvMESA)(const GLfloat * v); /* 651 */
+ void (GLAPIENTRYP WindowPos3iMESA)(GLint x, GLint y, GLint z); /* 652 */
+ void (GLAPIENTRYP WindowPos3ivMESA)(const GLint * v); /* 653 */
+ void (GLAPIENTRYP WindowPos3sMESA)(GLshort x, GLshort y, GLshort z); /* 654 */
+ void (GLAPIENTRYP WindowPos3svMESA)(const GLshort * v); /* 655 */
+ void (GLAPIENTRYP WindowPos4dMESA)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 656 */
+ void (GLAPIENTRYP WindowPos4dvMESA)(const GLdouble * v); /* 657 */
+ void (GLAPIENTRYP WindowPos4fMESA)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 658 */
+ void (GLAPIENTRYP WindowPos4fvMESA)(const GLfloat * v); /* 659 */
+ void (GLAPIENTRYP WindowPos4iMESA)(GLint x, GLint y, GLint z, GLint w); /* 660 */
+ void (GLAPIENTRYP WindowPos4ivMESA)(const GLint * v); /* 661 */
+ void (GLAPIENTRYP WindowPos4sMESA)(GLshort x, GLshort y, GLshort z, GLshort w); /* 662 */
+ void (GLAPIENTRYP WindowPos4svMESA)(const GLshort * v); /* 663 */
+ void (GLAPIENTRYP MultiModeDrawArraysIBM)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride); /* 664 */
+ void (GLAPIENTRYP MultiModeDrawElementsIBM)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride); /* 665 */
+ void (GLAPIENTRYP DeleteFencesNV)(GLsizei n, const GLuint * fences); /* 666 */
+ void (GLAPIENTRYP FinishFenceNV)(GLuint fence); /* 667 */
+ void (GLAPIENTRYP GenFencesNV)(GLsizei n, GLuint * fences); /* 668 */
+ void (GLAPIENTRYP GetFenceivNV)(GLuint fence, GLenum pname, GLint * params); /* 669 */
+ GLboolean (GLAPIENTRYP IsFenceNV)(GLuint fence); /* 670 */
+ void (GLAPIENTRYP SetFenceNV)(GLuint fence, GLenum condition); /* 671 */
+ GLboolean (GLAPIENTRYP TestFenceNV)(GLuint fence); /* 672 */
+ GLboolean (GLAPIENTRYP AreProgramsResidentNV)(GLsizei n, const GLuint * ids, GLboolean * residences); /* 673 */
+ void (GLAPIENTRYP BindProgramNV)(GLenum target, GLuint program); /* 674 */
+ void (GLAPIENTRYP DeleteProgramsNV)(GLsizei n, const GLuint * programs); /* 675 */
+ void (GLAPIENTRYP ExecuteProgramNV)(GLenum target, GLuint id, const GLfloat * params); /* 676 */
+ void (GLAPIENTRYP GenProgramsNV)(GLsizei n, GLuint * programs); /* 677 */
+ void (GLAPIENTRYP GetProgramParameterdvNV)(GLenum target, GLuint index, GLenum pname, GLdouble * params); /* 678 */
+ void (GLAPIENTRYP GetProgramParameterfvNV)(GLenum target, GLuint index, GLenum pname, GLfloat * params); /* 679 */
+ void (GLAPIENTRYP GetProgramStringNV)(GLuint id, GLenum pname, GLubyte * program); /* 680 */
+ void (GLAPIENTRYP GetProgramivNV)(GLuint id, GLenum pname, GLint * params); /* 681 */
+ void (GLAPIENTRYP GetTrackMatrixivNV)(GLenum target, GLuint address, GLenum pname, GLint * params); /* 682 */
+ void (GLAPIENTRYP GetVertexAttribPointervNV)(GLuint index, GLenum pname, GLvoid ** pointer); /* 683 */
+ void (GLAPIENTRYP GetVertexAttribdvNV)(GLuint index, GLenum pname, GLdouble * params); /* 684 */
+ void (GLAPIENTRYP GetVertexAttribfvNV)(GLuint index, GLenum pname, GLfloat * params); /* 685 */
+ void (GLAPIENTRYP GetVertexAttribivNV)(GLuint index, GLenum pname, GLint * params); /* 686 */
+ GLboolean (GLAPIENTRYP IsProgramNV)(GLuint program); /* 687 */
+ void (GLAPIENTRYP LoadProgramNV)(GLenum target, GLuint id, GLsizei len, const GLubyte * program); /* 688 */
+ void (GLAPIENTRYP ProgramParameters4dvNV)(GLenum target, GLuint index, GLuint num, const GLdouble * params); /* 689 */
+ void (GLAPIENTRYP ProgramParameters4fvNV)(GLenum target, GLuint index, GLuint num, const GLfloat * params); /* 690 */
+ void (GLAPIENTRYP RequestResidentProgramsNV)(GLsizei n, const GLuint * ids); /* 691 */
+ void (GLAPIENTRYP TrackMatrixNV)(GLenum target, GLuint address, GLenum matrix, GLenum transform); /* 692 */
+ void (GLAPIENTRYP VertexAttrib1dNV)(GLuint index, GLdouble x); /* 693 */
+ void (GLAPIENTRYP VertexAttrib1dvNV)(GLuint index, const GLdouble * v); /* 694 */
+ void (GLAPIENTRYP VertexAttrib1fNV)(GLuint index, GLfloat x); /* 695 */
+ void (GLAPIENTRYP VertexAttrib1fvNV)(GLuint index, const GLfloat * v); /* 696 */
+ void (GLAPIENTRYP VertexAttrib1sNV)(GLuint index, GLshort x); /* 697 */
+ void (GLAPIENTRYP VertexAttrib1svNV)(GLuint index, const GLshort * v); /* 698 */
+ void (GLAPIENTRYP VertexAttrib2dNV)(GLuint index, GLdouble x, GLdouble y); /* 699 */
+ void (GLAPIENTRYP VertexAttrib2dvNV)(GLuint index, const GLdouble * v); /* 700 */
+ void (GLAPIENTRYP VertexAttrib2fNV)(GLuint index, GLfloat x, GLfloat y); /* 701 */
+ void (GLAPIENTRYP VertexAttrib2fvNV)(GLuint index, const GLfloat * v); /* 702 */
+ void (GLAPIENTRYP VertexAttrib2sNV)(GLuint index, GLshort x, GLshort y); /* 703 */
+ void (GLAPIENTRYP VertexAttrib2svNV)(GLuint index, const GLshort * v); /* 704 */
+ void (GLAPIENTRYP VertexAttrib3dNV)(GLuint index, GLdouble x, GLdouble y, GLdouble z); /* 705 */
+ void (GLAPIENTRYP VertexAttrib3dvNV)(GLuint index, const GLdouble * v); /* 706 */
+ void (GLAPIENTRYP VertexAttrib3fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z); /* 707 */
+ void (GLAPIENTRYP VertexAttrib3fvNV)(GLuint index, const GLfloat * v); /* 708 */
+ void (GLAPIENTRYP VertexAttrib3sNV)(GLuint index, GLshort x, GLshort y, GLshort z); /* 709 */
+ void (GLAPIENTRYP VertexAttrib3svNV)(GLuint index, const GLshort * v); /* 710 */
+ void (GLAPIENTRYP VertexAttrib4dNV)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 711 */
+ void (GLAPIENTRYP VertexAttrib4dvNV)(GLuint index, const GLdouble * v); /* 712 */
+ void (GLAPIENTRYP VertexAttrib4fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 713 */
+ void (GLAPIENTRYP VertexAttrib4fvNV)(GLuint index, const GLfloat * v); /* 714 */
+ void (GLAPIENTRYP VertexAttrib4sNV)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); /* 715 */
+ void (GLAPIENTRYP VertexAttrib4svNV)(GLuint index, const GLshort * v); /* 716 */
+ void (GLAPIENTRYP VertexAttrib4ubNV)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); /* 717 */
+ void (GLAPIENTRYP VertexAttrib4ubvNV)(GLuint index, const GLubyte * v); /* 718 */
+ void (GLAPIENTRYP VertexAttribPointerNV)(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); /* 719 */
+ void (GLAPIENTRYP VertexAttribs1dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 720 */
+ void (GLAPIENTRYP VertexAttribs1fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 721 */
+ void (GLAPIENTRYP VertexAttribs1svNV)(GLuint index, GLsizei n, const GLshort * v); /* 722 */
+ void (GLAPIENTRYP VertexAttribs2dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 723 */
+ void (GLAPIENTRYP VertexAttribs2fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 724 */
+ void (GLAPIENTRYP VertexAttribs2svNV)(GLuint index, GLsizei n, const GLshort * v); /* 725 */
+ void (GLAPIENTRYP VertexAttribs3dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 726 */
+ void (GLAPIENTRYP VertexAttribs3fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 727 */
+ void (GLAPIENTRYP VertexAttribs3svNV)(GLuint index, GLsizei n, const GLshort * v); /* 728 */
+ void (GLAPIENTRYP VertexAttribs4dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 729 */
+ void (GLAPIENTRYP VertexAttribs4fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 730 */
+ void (GLAPIENTRYP VertexAttribs4svNV)(GLuint index, GLsizei n, const GLshort * v); /* 731 */
+ void (GLAPIENTRYP VertexAttribs4ubvNV)(GLuint index, GLsizei n, const GLubyte * v); /* 732 */
+ void (GLAPIENTRYP GetTexBumpParameterfvATI)(GLenum pname, GLfloat * param); /* 733 */
+ void (GLAPIENTRYP GetTexBumpParameterivATI)(GLenum pname, GLint * param); /* 734 */
+ void (GLAPIENTRYP TexBumpParameterfvATI)(GLenum pname, const GLfloat * param); /* 735 */
+ void (GLAPIENTRYP TexBumpParameterivATI)(GLenum pname, const GLint * param); /* 736 */
+ void (GLAPIENTRYP AlphaFragmentOp1ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); /* 737 */
+ void (GLAPIENTRYP AlphaFragmentOp2ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); /* 738 */
+ void (GLAPIENTRYP AlphaFragmentOp3ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); /* 739 */
+ void (GLAPIENTRYP BeginFragmentShaderATI)(void); /* 740 */
+ void (GLAPIENTRYP BindFragmentShaderATI)(GLuint id); /* 741 */
+ void (GLAPIENTRYP ColorFragmentOp1ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); /* 742 */
+ void (GLAPIENTRYP ColorFragmentOp2ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); /* 743 */
+ void (GLAPIENTRYP ColorFragmentOp3ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); /* 744 */
+ void (GLAPIENTRYP DeleteFragmentShaderATI)(GLuint id); /* 745 */
+ void (GLAPIENTRYP EndFragmentShaderATI)(void); /* 746 */
+ GLuint (GLAPIENTRYP GenFragmentShadersATI)(GLuint range); /* 747 */
+ void (GLAPIENTRYP PassTexCoordATI)(GLuint dst, GLuint coord, GLenum swizzle); /* 748 */
+ void (GLAPIENTRYP SampleMapATI)(GLuint dst, GLuint interp, GLenum swizzle); /* 749 */
+ void (GLAPIENTRYP SetFragmentShaderConstantATI)(GLuint dst, const GLfloat * value); /* 750 */
+ void (GLAPIENTRYP PointParameteriNV)(GLenum pname, GLint param); /* 751 */
+ void (GLAPIENTRYP PointParameterivNV)(GLenum pname, const GLint * params); /* 752 */
+ void (GLAPIENTRYP ActiveStencilFaceEXT)(GLenum face); /* 753 */
+ void (GLAPIENTRYP BindVertexArrayAPPLE)(GLuint array); /* 754 */
+ void (GLAPIENTRYP DeleteVertexArraysAPPLE)(GLsizei n, const GLuint * arrays); /* 755 */
+ void (GLAPIENTRYP GenVertexArraysAPPLE)(GLsizei n, GLuint * arrays); /* 756 */
+ GLboolean (GLAPIENTRYP IsVertexArrayAPPLE)(GLuint array); /* 757 */
+ void (GLAPIENTRYP GetProgramNamedParameterdvNV)(GLuint id, GLsizei len, const GLubyte * name, GLdouble * params); /* 758 */
+ void (GLAPIENTRYP GetProgramNamedParameterfvNV)(GLuint id, GLsizei len, const GLubyte * name, GLfloat * params); /* 759 */
+ void (GLAPIENTRYP ProgramNamedParameter4dNV)(GLuint id, GLsizei len, const GLubyte * name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 760 */
+ void (GLAPIENTRYP ProgramNamedParameter4dvNV)(GLuint id, GLsizei len, const GLubyte * name, const GLdouble * v); /* 761 */
+ void (GLAPIENTRYP ProgramNamedParameter4fNV)(GLuint id, GLsizei len, const GLubyte * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 762 */
+ void (GLAPIENTRYP ProgramNamedParameter4fvNV)(GLuint id, GLsizei len, const GLubyte * name, const GLfloat * v); /* 763 */
+ void (GLAPIENTRYP DepthBoundsEXT)(GLclampd zmin, GLclampd zmax); /* 764 */
+ void (GLAPIENTRYP BlendEquationSeparateEXT)(GLenum modeRGB, GLenum modeA); /* 765 */
+ void (GLAPIENTRYP BindFramebufferEXT)(GLenum target, GLuint framebuffer); /* 766 */
+ void (GLAPIENTRYP BindRenderbufferEXT)(GLenum target, GLuint renderbuffer); /* 767 */
+ GLenum (GLAPIENTRYP CheckFramebufferStatusEXT)(GLenum target); /* 768 */
+ void (GLAPIENTRYP DeleteFramebuffersEXT)(GLsizei n, const GLuint * framebuffers); /* 769 */
+ void (GLAPIENTRYP DeleteRenderbuffersEXT)(GLsizei n, const GLuint * renderbuffers); /* 770 */
+ void (GLAPIENTRYP FramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); /* 771 */
+ void (GLAPIENTRYP FramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); /* 772 */
+ void (GLAPIENTRYP FramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); /* 773 */
+ void (GLAPIENTRYP FramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); /* 774 */
+ void (GLAPIENTRYP GenFramebuffersEXT)(GLsizei n, GLuint * framebuffers); /* 775 */
+ void (GLAPIENTRYP GenRenderbuffersEXT)(GLsizei n, GLuint * renderbuffers); /* 776 */
+ void (GLAPIENTRYP GenerateMipmapEXT)(GLenum target); /* 777 */
+ void (GLAPIENTRYP GetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint * params); /* 778 */
+ void (GLAPIENTRYP GetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint * params); /* 779 */
+ GLboolean (GLAPIENTRYP IsFramebufferEXT)(GLuint framebuffer); /* 780 */
+ GLboolean (GLAPIENTRYP IsRenderbufferEXT)(GLuint renderbuffer); /* 781 */
+ void (GLAPIENTRYP RenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); /* 782 */
+ void (GLAPIENTRYP BlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); /* 783 */
+ void (GLAPIENTRYP BufferParameteriAPPLE)(GLenum target, GLenum pname, GLint param); /* 784 */
+ void (GLAPIENTRYP FlushMappedBufferRangeAPPLE)(GLenum target, GLintptr offset, GLsizeiptr size); /* 785 */
+ void (GLAPIENTRYP FramebufferTextureLayerEXT)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); /* 786 */
+ void (GLAPIENTRYP ProvokingVertexEXT)(GLenum mode); /* 787 */
+ void (GLAPIENTRYP GetTexParameterPointervAPPLE)(GLenum target, GLenum pname, GLvoid ** params); /* 788 */
+ void (GLAPIENTRYP TextureRangeAPPLE)(GLenum target, GLsizei length, GLvoid * pointer); /* 789 */
+ void (GLAPIENTRYP StencilFuncSeparateATI)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); /* 790 */
+ void (GLAPIENTRYP ProgramEnvParameters4fvEXT)(GLenum target, GLuint index, GLsizei count, const GLfloat * params); /* 791 */
+ void (GLAPIENTRYP ProgramLocalParameters4fvEXT)(GLenum target, GLuint index, GLsizei count, const GLfloat * params); /* 792 */
+ void (GLAPIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT * params); /* 793 */
+ void (GLAPIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT * params); /* 794 */
};
#endif /* !defined( _GLAPI_TABLE_H_ ) */
diff --git a/src/mesa/glapi/glapitemp.h b/src/mesa/glapi/glapitemp.h
index 09259f4704..3da0f63143 100644
--- a/src/mesa/glapi/glapitemp.h
+++ b/src/mesa/glapi/glapitemp.h
@@ -4006,63 +4006,143 @@ KEYWORD1 void KEYWORD2 NAME(DrawBuffersATI)(GLsizei n, const GLenum * bufs)
DISPATCH(DrawBuffersARB, (n, bufs), (F, "glDrawBuffersATI(%d, %p);\n", n, (const void *) bufs));
}
+KEYWORD1 void KEYWORD2 NAME(RenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ DISPATCH(RenderbufferStorageMultisample, (target, samples, internalformat, width, height), (F, "glRenderbufferStorageMultisample(0x%x, %d, 0x%x, %d, %d);\n", target, samples, internalformat, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FlushMappedBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+ DISPATCH(FlushMappedBufferRange, (target, offset, length), (F, "glFlushMappedBufferRange(0x%x, %d, %d);\n", target, offset, length));
+}
+
+KEYWORD1 GLvoid * KEYWORD2 NAME(MapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+{
+ RETURN_DISPATCH(MapBufferRange, (target, offset, length, access), (F, "glMapBufferRange(0x%x, %d, %d, %d);\n", target, offset, length, access));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindVertexArray)(GLuint array)
+{
+ DISPATCH(BindVertexArray, (array), (F, "glBindVertexArray(%d);\n", array));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenVertexArrays)(GLsizei n, GLuint * arrays)
+{
+ DISPATCH(GenVertexArrays, (n, arrays), (F, "glGenVertexArrays(%d, %p);\n", n, (const void *) arrays));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
+{
+ DISPATCH(CopyBufferSubData, (readTarget, writeTarget, readOffset, writeOffset, size), (F, "glCopyBufferSubData(0x%x, 0x%x, %d, %d, %d);\n", readTarget, writeTarget, readOffset, writeOffset, size));
+}
+
+KEYWORD1 GLenum KEYWORD2 NAME(ClientWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ RETURN_DISPATCH(ClientWaitSync, (sync, flags, timeout), (F, "glClientWaitSync(%d, %d, %d);\n", sync, flags, timeout));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteSync)(GLsync sync)
+{
+ DISPATCH(DeleteSync, (sync), (F, "glDeleteSync(%d);\n", sync));
+}
+
+KEYWORD1 GLsync KEYWORD2 NAME(FenceSync)(GLenum condition, GLbitfield flags)
+{
+ RETURN_DISPATCH(FenceSync, (condition, flags), (F, "glFenceSync(0x%x, %d);\n", condition, flags));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetInteger64v)(GLenum pname, GLint64 * params)
+{
+ DISPATCH(GetInteger64v, (pname, params), (F, "glGetInteger64v(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetSynciv)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values)
+{
+ DISPATCH(GetSynciv, (sync, pname, bufSize, length, values), (F, "glGetSynciv(%d, 0x%x, %d, %p, %p);\n", sync, pname, bufSize, (const void *) length, (const void *) values));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsSync)(GLsync sync)
+{
+ RETURN_DISPATCH(IsSync, (sync), (F, "glIsSync(%d);\n", sync));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ DISPATCH(WaitSync, (sync, flags, timeout), (F, "glWaitSync(%d, %d, %d);\n", sync, flags, timeout));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawElementsBaseVertex)(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices, GLint basevertex)
+{
+ DISPATCH(DrawElementsBaseVertex, (mode, count, type, indices, basevertex), (F, "glDrawElementsBaseVertex(0x%x, %d, 0x%x, %p, %d);\n", mode, count, type, (const void *) indices, basevertex));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawRangeElementsBaseVertex)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices, GLint basevertex)
+{
+ DISPATCH(DrawRangeElementsBaseVertex, (mode, start, end, count, type, indices, basevertex), (F, "glDrawRangeElementsBaseVertex(0x%x, %d, %d, %d, 0x%x, %p, %d);\n", mode, start, end, count, type, (const void *) indices, basevertex));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiDrawElementsBaseVertex)(GLenum mode, const GLsizei * count, GLenum type, const GLvoid ** indices, GLsizei primcount, const GLint * basevertex)
+{
+ DISPATCH(MultiDrawElementsBaseVertex, (mode, count, type, indices, primcount, basevertex), (F, "glMultiDrawElementsBaseVertex(0x%x, %p, 0x%x, %p, %d, %p);\n", mode, (const void *) count, type, (const void *) indices, primcount, (const void *) basevertex));
+}
+
KEYWORD1 void KEYWORD2 NAME(PolygonOffsetEXT)(GLfloat factor, GLfloat bias)
{
DISPATCH(PolygonOffsetEXT, (factor, bias), (F, "glPolygonOffsetEXT(%f, %f);\n", factor, bias));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_562)(GLenum pname, GLfloat * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_578)(GLenum pname, GLfloat * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_562)(GLenum pname, GLfloat * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_578)(GLenum pname, GLfloat * params)
{
DISPATCH(GetPixelTexGenParameterfvSGIS, (pname, params), (F, "glGetPixelTexGenParameterfvSGIS(0x%x, %p);\n", pname, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_563)(GLenum pname, GLint * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_579)(GLenum pname, GLint * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_563)(GLenum pname, GLint * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_579)(GLenum pname, GLint * params)
{
DISPATCH(GetPixelTexGenParameterivSGIS, (pname, params), (F, "glGetPixelTexGenParameterivSGIS(0x%x, %p);\n", pname, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_564)(GLenum pname, GLfloat param);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_580)(GLenum pname, GLfloat param);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_564)(GLenum pname, GLfloat param)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_580)(GLenum pname, GLfloat param)
{
DISPATCH(PixelTexGenParameterfSGIS, (pname, param), (F, "glPixelTexGenParameterfSGIS(0x%x, %f);\n", pname, param));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_565)(GLenum pname, const GLfloat * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_581)(GLenum pname, const GLfloat * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_565)(GLenum pname, const GLfloat * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_581)(GLenum pname, const GLfloat * params)
{
DISPATCH(PixelTexGenParameterfvSGIS, (pname, params), (F, "glPixelTexGenParameterfvSGIS(0x%x, %p);\n", pname, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_566)(GLenum pname, GLint param);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_582)(GLenum pname, GLint param);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_566)(GLenum pname, GLint param)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_582)(GLenum pname, GLint param)
{
DISPATCH(PixelTexGenParameteriSGIS, (pname, param), (F, "glPixelTexGenParameteriSGIS(0x%x, %d);\n", pname, param));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_567)(GLenum pname, const GLint * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_583)(GLenum pname, const GLint * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_567)(GLenum pname, const GLint * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_583)(GLenum pname, const GLint * params)
{
DISPATCH(PixelTexGenParameterivSGIS, (pname, params), (F, "glPixelTexGenParameterivSGIS(0x%x, %p);\n", pname, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_568)(GLclampf value, GLboolean invert);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_584)(GLclampf value, GLboolean invert);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_568)(GLclampf value, GLboolean invert)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_584)(GLclampf value, GLboolean invert)
{
DISPATCH(SampleMaskSGIS, (value, invert), (F, "glSampleMaskSGIS(%f, %d);\n", value, invert));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_569)(GLenum pattern);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_585)(GLenum pattern);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_569)(GLenum pattern)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_585)(GLenum pattern)
{
DISPATCH(SamplePatternSGIS, (pattern), (F, "glSamplePatternSGIS(0x%x);\n", pattern));
}
@@ -4112,9 +4192,9 @@ KEYWORD1 void KEYWORD2 NAME(PointParameterfEXT)(GLenum pname, GLfloat param)
DISPATCH(PointParameterfEXT, (pname, param), (F, "glPointParameterfEXT(0x%x, %f);\n", pname, param));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_576)(GLenum pname, GLfloat param);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_592)(GLenum pname, GLfloat param);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_576)(GLenum pname, GLfloat param)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_592)(GLenum pname, GLfloat param)
{
DISPATCH(PointParameterfEXT, (pname, param), (F, "glPointParameterfSGIS(0x%x, %f);\n", pname, param));
}
@@ -4134,9 +4214,9 @@ KEYWORD1 void KEYWORD2 NAME(PointParameterfvEXT)(GLenum pname, const GLfloat * p
DISPATCH(PointParameterfvEXT, (pname, params), (F, "glPointParameterfvEXT(0x%x, %p);\n", pname, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_577)(GLenum pname, const GLfloat * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_593)(GLenum pname, const GLfloat * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_577)(GLenum pname, const GLfloat * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_593)(GLenum pname, const GLfloat * params)
{
DISPATCH(PointParameterfvEXT, (pname, params), (F, "glPointParameterfvSGIS(0x%x, %p);\n", pname, (const void *) params));
}
@@ -4151,16 +4231,16 @@ KEYWORD1 void KEYWORD2 NAME(UnlockArraysEXT)(void)
DISPATCH(UnlockArraysEXT, (), (F, "glUnlockArraysEXT();\n"));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_580)(GLenum pname, GLdouble * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_596)(GLenum pname, GLdouble * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_580)(GLenum pname, GLdouble * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_596)(GLenum pname, GLdouble * params)
{
DISPATCH(CullParameterdvEXT, (pname, params), (F, "glCullParameterdvEXT(0x%x, %p);\n", pname, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_581)(GLenum pname, GLfloat * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_597)(GLenum pname, GLfloat * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_581)(GLenum pname, GLfloat * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_597)(GLenum pname, GLfloat * params)
{
DISPATCH(CullParameterfvEXT, (pname, params), (F, "glCullParameterfvEXT(0x%x, %p);\n", pname, (const void *) params));
}
@@ -4405,9 +4485,9 @@ KEYWORD1 void KEYWORD2 NAME(FogCoordfvEXT)(const GLfloat * coord)
DISPATCH(FogCoordfvEXT, (coord), (F, "glFogCoordfvEXT(%p);\n", (const void *) coord));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_606)(GLenum mode);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_622)(GLenum mode);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_606)(GLenum mode)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_622)(GLenum mode)
{
DISPATCH(PixelTexGenSGIX, (mode), (F, "glPixelTexGenSGIX(0x%x);\n", mode));
}
@@ -4422,9 +4502,9 @@ KEYWORD1 void KEYWORD2 NAME(BlendFuncSeparateEXT)(GLenum sfactorRGB, GLenum dfac
DISPATCH(BlendFuncSeparateEXT, (sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha), (F, "glBlendFuncSeparateEXT(0x%x, 0x%x, 0x%x, 0x%x);\n", sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_607)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_623)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_607)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_623)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
{
DISPATCH(BlendFuncSeparateEXT, (sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha), (F, "glBlendFuncSeparateINGR(0x%x, 0x%x, 0x%x, 0x%x);\n", sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha));
}
@@ -4789,65 +4869,65 @@ KEYWORD1 void KEYWORD2 NAME(WindowPos4svMESA)(const GLshort * v)
DISPATCH(WindowPos4svMESA, (v), (F, "glWindowPos4svMESA(%p);\n", (const void *) v));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_648)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_664)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_648)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_664)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride)
{
DISPATCH(MultiModeDrawArraysIBM, (mode, first, count, primcount, modestride), (F, "glMultiModeDrawArraysIBM(%p, %p, %p, %d, %d);\n", (const void *) mode, (const void *) first, (const void *) count, primcount, modestride));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_649)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_665)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_649)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_665)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride)
{
DISPATCH(MultiModeDrawElementsIBM, (mode, count, type, indices, primcount, modestride), (F, "glMultiModeDrawElementsIBM(%p, %p, 0x%x, %p, %d, %d);\n", (const void *) mode, (const void *) count, type, (const void *) indices, primcount, modestride));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_650)(GLsizei n, const GLuint * fences);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_666)(GLsizei n, const GLuint * fences);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_650)(GLsizei n, const GLuint * fences)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_666)(GLsizei n, const GLuint * fences)
{
DISPATCH(DeleteFencesNV, (n, fences), (F, "glDeleteFencesNV(%d, %p);\n", n, (const void *) fences));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_651)(GLuint fence);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_667)(GLuint fence);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_651)(GLuint fence)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_667)(GLuint fence)
{
DISPATCH(FinishFenceNV, (fence), (F, "glFinishFenceNV(%d);\n", fence));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_652)(GLsizei n, GLuint * fences);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_668)(GLsizei n, GLuint * fences);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_652)(GLsizei n, GLuint * fences)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_668)(GLsizei n, GLuint * fences)
{
DISPATCH(GenFencesNV, (n, fences), (F, "glGenFencesNV(%d, %p);\n", n, (const void *) fences));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_653)(GLuint fence, GLenum pname, GLint * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_669)(GLuint fence, GLenum pname, GLint * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_653)(GLuint fence, GLenum pname, GLint * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_669)(GLuint fence, GLenum pname, GLint * params)
{
DISPATCH(GetFenceivNV, (fence, pname, params), (F, "glGetFenceivNV(%d, 0x%x, %p);\n", fence, pname, (const void *) params));
}
-KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_654)(GLuint fence);
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_670)(GLuint fence);
-KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_654)(GLuint fence)
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_670)(GLuint fence)
{
RETURN_DISPATCH(IsFenceNV, (fence), (F, "glIsFenceNV(%d);\n", fence));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_655)(GLuint fence, GLenum condition);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_671)(GLuint fence, GLenum condition);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_655)(GLuint fence, GLenum condition)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_671)(GLuint fence, GLenum condition)
{
DISPATCH(SetFenceNV, (fence, condition), (F, "glSetFenceNV(%d, 0x%x);\n", fence, condition));
}
-KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_656)(GLuint fence);
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_672)(GLuint fence);
-KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_656)(GLuint fence)
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_672)(GLuint fence)
{
RETURN_DISPATCH(TestFenceNV, (fence), (F, "glTestFenceNV(%d);\n", fence));
}
@@ -5182,6 +5262,26 @@ KEYWORD1 void KEYWORD2 NAME(VertexAttribs4ubvNV)(GLuint index, GLsizei n, const
DISPATCH(VertexAttribs4ubvNV, (index, n, v), (F, "glVertexAttribs4ubvNV(%d, %d, %p);\n", index, n, (const void *) v));
}
+KEYWORD1 void KEYWORD2 NAME(GetTexBumpParameterfvATI)(GLenum pname, GLfloat * param)
+{
+ DISPATCH(GetTexBumpParameterfvATI, (pname, param), (F, "glGetTexBumpParameterfvATI(0x%x, %p);\n", pname, (const void *) param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexBumpParameterivATI)(GLenum pname, GLint * param)
+{
+ DISPATCH(GetTexBumpParameterivATI, (pname, param), (F, "glGetTexBumpParameterivATI(0x%x, %p);\n", pname, (const void *) param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexBumpParameterfvATI)(GLenum pname, const GLfloat * param)
+{
+ DISPATCH(TexBumpParameterfvATI, (pname, param), (F, "glTexBumpParameterfvATI(0x%x, %p);\n", pname, (const void *) param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexBumpParameterivATI)(GLenum pname, const GLint * param)
+{
+ DISPATCH(TexBumpParameterivATI, (pname, param), (F, "glTexBumpParameterivATI(0x%x, %p);\n", pname, (const void *) param));
+}
+
KEYWORD1 void KEYWORD2 NAME(AlphaFragmentOp1ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod)
{
DISPATCH(AlphaFragmentOp1ATI, (op, dst, dstMod, arg1, arg1Rep, arg1Mod), (F, "glAlphaFragmentOp1ATI(0x%x, %d, %d, %d, %d, %d);\n", op, dst, dstMod, arg1, arg1Rep, arg1Mod));
@@ -5272,37 +5372,47 @@ KEYWORD1 void KEYWORD2 NAME(PointParameterivNV)(GLenum pname, const GLint * para
DISPATCH(PointParameterivNV, (pname, params), (F, "glPointParameterivNV(0x%x, %p);\n", pname, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_733)(GLenum face);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_753)(GLenum face);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_733)(GLenum face)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_753)(GLenum face)
{
DISPATCH(ActiveStencilFaceEXT, (face), (F, "glActiveStencilFaceEXT(0x%x);\n", face));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_734)(GLuint array);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_754)(GLuint array);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_734)(GLuint array)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_754)(GLuint array)
{
DISPATCH(BindVertexArrayAPPLE, (array), (F, "glBindVertexArrayAPPLE(%d);\n", array));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_735)(GLsizei n, const GLuint * arrays);
+KEYWORD1 void KEYWORD2 NAME(DeleteVertexArrays)(GLsizei n, const GLuint * arrays)
+{
+ DISPATCH(DeleteVertexArraysAPPLE, (n, arrays), (F, "glDeleteVertexArrays(%d, %p);\n", n, (const void *) arrays));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_755)(GLsizei n, const GLuint * arrays);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_735)(GLsizei n, const GLuint * arrays)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_755)(GLsizei n, const GLuint * arrays)
{
DISPATCH(DeleteVertexArraysAPPLE, (n, arrays), (F, "glDeleteVertexArraysAPPLE(%d, %p);\n", n, (const void *) arrays));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_736)(GLsizei n, GLuint * arrays);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_756)(GLsizei n, GLuint * arrays);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_736)(GLsizei n, GLuint * arrays)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_756)(GLsizei n, GLuint * arrays)
{
DISPATCH(GenVertexArraysAPPLE, (n, arrays), (F, "glGenVertexArraysAPPLE(%d, %p);\n", n, (const void *) arrays));
}
-KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_737)(GLuint array);
+KEYWORD1 GLboolean KEYWORD2 NAME(IsVertexArray)(GLuint array)
+{
+ RETURN_DISPATCH(IsVertexArrayAPPLE, (array), (F, "glIsVertexArray(%d);\n", array));
+}
+
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_757)(GLuint array);
-KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_737)(GLuint array)
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_757)(GLuint array)
{
RETURN_DISPATCH(IsVertexArrayAPPLE, (array), (F, "glIsVertexArrayAPPLE(%d);\n", array));
}
@@ -5337,9 +5447,9 @@ KEYWORD1 void KEYWORD2 NAME(ProgramNamedParameter4fvNV)(GLuint id, GLsizei len,
DISPATCH(ProgramNamedParameter4fvNV, (id, len, name, v), (F, "glProgramNamedParameter4fvNV(%d, %d, %p, %p);\n", id, len, (const void *) name, (const void *) v));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_744)(GLclampd zmin, GLclampd zmax);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_764)(GLclampd zmin, GLclampd zmax);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_744)(GLclampd zmin, GLclampd zmax)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_764)(GLclampd zmin, GLclampd zmax)
{
DISPATCH(DepthBoundsEXT, (zmin, zmax), (F, "glDepthBoundsEXT(%f, %f);\n", zmin, zmax));
}
@@ -5349,141 +5459,269 @@ KEYWORD1 void KEYWORD2 NAME(BlendEquationSeparate)(GLenum modeRGB, GLenum modeA)
DISPATCH(BlendEquationSeparateEXT, (modeRGB, modeA), (F, "glBlendEquationSeparate(0x%x, 0x%x);\n", modeRGB, modeA));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_745)(GLenum modeRGB, GLenum modeA);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_765)(GLenum modeRGB, GLenum modeA);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_745)(GLenum modeRGB, GLenum modeA)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_765)(GLenum modeRGB, GLenum modeA)
{
DISPATCH(BlendEquationSeparateEXT, (modeRGB, modeA), (F, "glBlendEquationSeparateEXT(0x%x, 0x%x);\n", modeRGB, modeA));
}
+KEYWORD1 void KEYWORD2 NAME(BindFramebuffer)(GLenum target, GLuint framebuffer)
+{
+ DISPATCH(BindFramebufferEXT, (target, framebuffer), (F, "glBindFramebuffer(0x%x, %d);\n", target, framebuffer));
+}
+
KEYWORD1 void KEYWORD2 NAME(BindFramebufferEXT)(GLenum target, GLuint framebuffer)
{
DISPATCH(BindFramebufferEXT, (target, framebuffer), (F, "glBindFramebufferEXT(0x%x, %d);\n", target, framebuffer));
}
+KEYWORD1 void KEYWORD2 NAME(BindRenderbuffer)(GLenum target, GLuint renderbuffer)
+{
+ DISPATCH(BindRenderbufferEXT, (target, renderbuffer), (F, "glBindRenderbuffer(0x%x, %d);\n", target, renderbuffer));
+}
+
KEYWORD1 void KEYWORD2 NAME(BindRenderbufferEXT)(GLenum target, GLuint renderbuffer)
{
DISPATCH(BindRenderbufferEXT, (target, renderbuffer), (F, "glBindRenderbufferEXT(0x%x, %d);\n", target, renderbuffer));
}
+KEYWORD1 GLenum KEYWORD2 NAME(CheckFramebufferStatus)(GLenum target)
+{
+ RETURN_DISPATCH(CheckFramebufferStatusEXT, (target), (F, "glCheckFramebufferStatus(0x%x);\n", target));
+}
+
KEYWORD1 GLenum KEYWORD2 NAME(CheckFramebufferStatusEXT)(GLenum target)
{
RETURN_DISPATCH(CheckFramebufferStatusEXT, (target), (F, "glCheckFramebufferStatusEXT(0x%x);\n", target));
}
+KEYWORD1 void KEYWORD2 NAME(DeleteFramebuffers)(GLsizei n, const GLuint * framebuffers)
+{
+ DISPATCH(DeleteFramebuffersEXT, (n, framebuffers), (F, "glDeleteFramebuffers(%d, %p);\n", n, (const void *) framebuffers));
+}
+
KEYWORD1 void KEYWORD2 NAME(DeleteFramebuffersEXT)(GLsizei n, const GLuint * framebuffers)
{
DISPATCH(DeleteFramebuffersEXT, (n, framebuffers), (F, "glDeleteFramebuffersEXT(%d, %p);\n", n, (const void *) framebuffers));
}
+KEYWORD1 void KEYWORD2 NAME(DeleteRenderbuffers)(GLsizei n, const GLuint * renderbuffers)
+{
+ DISPATCH(DeleteRenderbuffersEXT, (n, renderbuffers), (F, "glDeleteRenderbuffers(%d, %p);\n", n, (const void *) renderbuffers));
+}
+
KEYWORD1 void KEYWORD2 NAME(DeleteRenderbuffersEXT)(GLsizei n, const GLuint * renderbuffers)
{
DISPATCH(DeleteRenderbuffersEXT, (n, renderbuffers), (F, "glDeleteRenderbuffersEXT(%d, %p);\n", n, (const void *) renderbuffers));
}
+KEYWORD1 void KEYWORD2 NAME(FramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+ DISPATCH(FramebufferRenderbufferEXT, (target, attachment, renderbuffertarget, renderbuffer), (F, "glFramebufferRenderbuffer(0x%x, 0x%x, 0x%x, %d);\n", target, attachment, renderbuffertarget, renderbuffer));
+}
+
KEYWORD1 void KEYWORD2 NAME(FramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
{
DISPATCH(FramebufferRenderbufferEXT, (target, attachment, renderbuffertarget, renderbuffer), (F, "glFramebufferRenderbufferEXT(0x%x, 0x%x, 0x%x, %d);\n", target, attachment, renderbuffertarget, renderbuffer));
}
+KEYWORD1 void KEYWORD2 NAME(FramebufferTexture1D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ DISPATCH(FramebufferTexture1DEXT, (target, attachment, textarget, texture, level), (F, "glFramebufferTexture1D(0x%x, 0x%x, 0x%x, %d, %d);\n", target, attachment, textarget, texture, level));
+}
+
KEYWORD1 void KEYWORD2 NAME(FramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
{
DISPATCH(FramebufferTexture1DEXT, (target, attachment, textarget, texture, level), (F, "glFramebufferTexture1DEXT(0x%x, 0x%x, 0x%x, %d, %d);\n", target, attachment, textarget, texture, level));
}
+KEYWORD1 void KEYWORD2 NAME(FramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ DISPATCH(FramebufferTexture2DEXT, (target, attachment, textarget, texture, level), (F, "glFramebufferTexture2D(0x%x, 0x%x, 0x%x, %d, %d);\n", target, attachment, textarget, texture, level));
+}
+
KEYWORD1 void KEYWORD2 NAME(FramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
{
DISPATCH(FramebufferTexture2DEXT, (target, attachment, textarget, texture, level), (F, "glFramebufferTexture2DEXT(0x%x, 0x%x, 0x%x, %d, %d);\n", target, attachment, textarget, texture, level));
}
+KEYWORD1 void KEYWORD2 NAME(FramebufferTexture3D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+{
+ DISPATCH(FramebufferTexture3DEXT, (target, attachment, textarget, texture, level, zoffset), (F, "glFramebufferTexture3D(0x%x, 0x%x, 0x%x, %d, %d, %d);\n", target, attachment, textarget, texture, level, zoffset));
+}
+
KEYWORD1 void KEYWORD2 NAME(FramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
{
DISPATCH(FramebufferTexture3DEXT, (target, attachment, textarget, texture, level, zoffset), (F, "glFramebufferTexture3DEXT(0x%x, 0x%x, 0x%x, %d, %d, %d);\n", target, attachment, textarget, texture, level, zoffset));
}
+KEYWORD1 void KEYWORD2 NAME(GenFramebuffers)(GLsizei n, GLuint * framebuffers)
+{
+ DISPATCH(GenFramebuffersEXT, (n, framebuffers), (F, "glGenFramebuffers(%d, %p);\n", n, (const void *) framebuffers));
+}
+
KEYWORD1 void KEYWORD2 NAME(GenFramebuffersEXT)(GLsizei n, GLuint * framebuffers)
{
DISPATCH(GenFramebuffersEXT, (n, framebuffers), (F, "glGenFramebuffersEXT(%d, %p);\n", n, (const void *) framebuffers));
}
+KEYWORD1 void KEYWORD2 NAME(GenRenderbuffers)(GLsizei n, GLuint * renderbuffers)
+{
+ DISPATCH(GenRenderbuffersEXT, (n, renderbuffers), (F, "glGenRenderbuffers(%d, %p);\n", n, (const void *) renderbuffers));
+}
+
KEYWORD1 void KEYWORD2 NAME(GenRenderbuffersEXT)(GLsizei n, GLuint * renderbuffers)
{
DISPATCH(GenRenderbuffersEXT, (n, renderbuffers), (F, "glGenRenderbuffersEXT(%d, %p);\n", n, (const void *) renderbuffers));
}
+KEYWORD1 void KEYWORD2 NAME(GenerateMipmap)(GLenum target)
+{
+ DISPATCH(GenerateMipmapEXT, (target), (F, "glGenerateMipmap(0x%x);\n", target));
+}
+
KEYWORD1 void KEYWORD2 NAME(GenerateMipmapEXT)(GLenum target)
{
DISPATCH(GenerateMipmapEXT, (target), (F, "glGenerateMipmapEXT(0x%x);\n", target));
}
+KEYWORD1 void KEYWORD2 NAME(GetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint * params)
+{
+ DISPATCH(GetFramebufferAttachmentParameterivEXT, (target, attachment, pname, params), (F, "glGetFramebufferAttachmentParameteriv(0x%x, 0x%x, 0x%x, %p);\n", target, attachment, pname, (const void *) params));
+}
+
KEYWORD1 void KEYWORD2 NAME(GetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint * params)
{
DISPATCH(GetFramebufferAttachmentParameterivEXT, (target, attachment, pname, params), (F, "glGetFramebufferAttachmentParameterivEXT(0x%x, 0x%x, 0x%x, %p);\n", target, attachment, pname, (const void *) params));
}
+KEYWORD1 void KEYWORD2 NAME(GetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetRenderbufferParameterivEXT, (target, pname, params), (F, "glGetRenderbufferParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
KEYWORD1 void KEYWORD2 NAME(GetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint * params)
{
DISPATCH(GetRenderbufferParameterivEXT, (target, pname, params), (F, "glGetRenderbufferParameterivEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
}
+KEYWORD1 GLboolean KEYWORD2 NAME(IsFramebuffer)(GLuint framebuffer)
+{
+ RETURN_DISPATCH(IsFramebufferEXT, (framebuffer), (F, "glIsFramebuffer(%d);\n", framebuffer));
+}
+
KEYWORD1 GLboolean KEYWORD2 NAME(IsFramebufferEXT)(GLuint framebuffer)
{
RETURN_DISPATCH(IsFramebufferEXT, (framebuffer), (F, "glIsFramebufferEXT(%d);\n", framebuffer));
}
+KEYWORD1 GLboolean KEYWORD2 NAME(IsRenderbuffer)(GLuint renderbuffer)
+{
+ RETURN_DISPATCH(IsRenderbufferEXT, (renderbuffer), (F, "glIsRenderbuffer(%d);\n", renderbuffer));
+}
+
KEYWORD1 GLboolean KEYWORD2 NAME(IsRenderbufferEXT)(GLuint renderbuffer)
{
RETURN_DISPATCH(IsRenderbufferEXT, (renderbuffer), (F, "glIsRenderbufferEXT(%d);\n", renderbuffer));
}
+KEYWORD1 void KEYWORD2 NAME(RenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ DISPATCH(RenderbufferStorageEXT, (target, internalformat, width, height), (F, "glRenderbufferStorage(0x%x, 0x%x, %d, %d);\n", target, internalformat, width, height));
+}
+
KEYWORD1 void KEYWORD2 NAME(RenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
{
DISPATCH(RenderbufferStorageEXT, (target, internalformat, width, height), (F, "glRenderbufferStorageEXT(0x%x, 0x%x, %d, %d);\n", target, internalformat, width, height));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_763)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+KEYWORD1 void KEYWORD2 NAME(BlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+{
+ DISPATCH(BlitFramebufferEXT, (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), (F, "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x);\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter));
+}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_763)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_783)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_783)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
{
DISPATCH(BlitFramebufferEXT, (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), (F, "glBlitFramebufferEXT(%d, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x);\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter));
}
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_784)(GLenum target, GLenum pname, GLint param);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_784)(GLenum target, GLenum pname, GLint param)
+{
+ DISPATCH(BufferParameteriAPPLE, (target, pname, param), (F, "glBufferParameteriAPPLE(0x%x, 0x%x, %d);\n", target, pname, param));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_785)(GLenum target, GLintptr offset, GLsizeiptr size);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_785)(GLenum target, GLintptr offset, GLsizeiptr size)
+{
+ DISPATCH(FlushMappedBufferRangeAPPLE, (target, offset, size), (F, "glFlushMappedBufferRangeAPPLE(0x%x, %d, %d);\n", target, offset, size));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferTextureLayer)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+{
+ DISPATCH(FramebufferTextureLayerEXT, (target, attachment, texture, level, layer), (F, "glFramebufferTextureLayer(0x%x, 0x%x, %d, %d, %d);\n", target, attachment, texture, level, layer));
+}
+
KEYWORD1 void KEYWORD2 NAME(FramebufferTextureLayerEXT)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
{
DISPATCH(FramebufferTextureLayerEXT, (target, attachment, texture, level, layer), (F, "glFramebufferTextureLayerEXT(0x%x, 0x%x, %d, %d, %d);\n", target, attachment, texture, level, layer));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_765)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+KEYWORD1 void KEYWORD2 NAME(ProvokingVertexEXT)(GLenum mode)
+{
+ DISPATCH(ProvokingVertexEXT, (mode), (F, "glProvokingVertexEXT(0x%x);\n", mode));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_788)(GLenum target, GLenum pname, GLvoid ** params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_788)(GLenum target, GLenum pname, GLvoid ** params)
+{
+ DISPATCH(GetTexParameterPointervAPPLE, (target, pname, params), (F, "glGetTexParameterPointervAPPLE(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_789)(GLenum target, GLsizei length, GLvoid * pointer);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_789)(GLenum target, GLsizei length, GLvoid * pointer)
+{
+ DISPATCH(TextureRangeAPPLE, (target, length, pointer), (F, "glTextureRangeAPPLE(0x%x, %d, %p);\n", target, length, (const void *) pointer));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_790)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_765)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_790)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask)
{
DISPATCH(StencilFuncSeparateATI, (frontfunc, backfunc, ref, mask), (F, "glStencilFuncSeparateATI(0x%x, 0x%x, %d, %d);\n", frontfunc, backfunc, ref, mask));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_766)(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_791)(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_766)(GLenum target, GLuint index, GLsizei count, const GLfloat * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_791)(GLenum target, GLuint index, GLsizei count, const GLfloat * params)
{
DISPATCH(ProgramEnvParameters4fvEXT, (target, index, count, params), (F, "glProgramEnvParameters4fvEXT(0x%x, %d, %d, %p);\n", target, index, count, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_767)(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_792)(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_767)(GLenum target, GLuint index, GLsizei count, const GLfloat * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_792)(GLenum target, GLuint index, GLsizei count, const GLfloat * params)
{
DISPATCH(ProgramLocalParameters4fvEXT, (target, index, count, params), (F, "glProgramLocalParameters4fvEXT(0x%x, %d, %d, %p);\n", target, index, count, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_768)(GLuint id, GLenum pname, GLint64EXT * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_793)(GLuint id, GLenum pname, GLint64EXT * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_768)(GLuint id, GLenum pname, GLint64EXT * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_793)(GLuint id, GLenum pname, GLint64EXT * params)
{
DISPATCH(GetQueryObjecti64vEXT, (id, pname, params), (F, "glGetQueryObjecti64vEXT(%d, 0x%x, %p);\n", id, pname, (const void *) params));
}
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_769)(GLuint id, GLenum pname, GLuint64EXT * params);
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_794)(GLuint id, GLenum pname, GLuint64EXT * params);
-KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_769)(GLuint id, GLenum pname, GLuint64EXT * params)
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_794)(GLuint id, GLenum pname, GLuint64EXT * params)
{
DISPATCH(GetQueryObjectui64vEXT, (id, pname, params), (F, "glGetQueryObjectui64vEXT(%d, 0x%x, %p);\n", id, pname, (const void *) params));
}
@@ -6063,15 +6301,31 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = {
TABLE_ENTRY(GetActiveAttribARB),
TABLE_ENTRY(GetAttribLocationARB),
TABLE_ENTRY(DrawBuffersARB),
+ TABLE_ENTRY(RenderbufferStorageMultisample),
+ TABLE_ENTRY(FlushMappedBufferRange),
+ TABLE_ENTRY(MapBufferRange),
+ TABLE_ENTRY(BindVertexArray),
+ TABLE_ENTRY(GenVertexArrays),
+ TABLE_ENTRY(CopyBufferSubData),
+ TABLE_ENTRY(ClientWaitSync),
+ TABLE_ENTRY(DeleteSync),
+ TABLE_ENTRY(FenceSync),
+ TABLE_ENTRY(GetInteger64v),
+ TABLE_ENTRY(GetSynciv),
+ TABLE_ENTRY(IsSync),
+ TABLE_ENTRY(WaitSync),
+ TABLE_ENTRY(DrawElementsBaseVertex),
+ TABLE_ENTRY(DrawRangeElementsBaseVertex),
+ TABLE_ENTRY(MultiDrawElementsBaseVertex),
TABLE_ENTRY(PolygonOffsetEXT),
- TABLE_ENTRY(_dispatch_stub_562),
- TABLE_ENTRY(_dispatch_stub_563),
- TABLE_ENTRY(_dispatch_stub_564),
- TABLE_ENTRY(_dispatch_stub_565),
- TABLE_ENTRY(_dispatch_stub_566),
- TABLE_ENTRY(_dispatch_stub_567),
- TABLE_ENTRY(_dispatch_stub_568),
- TABLE_ENTRY(_dispatch_stub_569),
+ TABLE_ENTRY(_dispatch_stub_578),
+ TABLE_ENTRY(_dispatch_stub_579),
+ TABLE_ENTRY(_dispatch_stub_580),
+ TABLE_ENTRY(_dispatch_stub_581),
+ TABLE_ENTRY(_dispatch_stub_582),
+ TABLE_ENTRY(_dispatch_stub_583),
+ TABLE_ENTRY(_dispatch_stub_584),
+ TABLE_ENTRY(_dispatch_stub_585),
TABLE_ENTRY(ColorPointerEXT),
TABLE_ENTRY(EdgeFlagPointerEXT),
TABLE_ENTRY(IndexPointerEXT),
@@ -6082,8 +6336,8 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = {
TABLE_ENTRY(PointParameterfvEXT),
TABLE_ENTRY(LockArraysEXT),
TABLE_ENTRY(UnlockArraysEXT),
- TABLE_ENTRY(_dispatch_stub_580),
- TABLE_ENTRY(_dispatch_stub_581),
+ TABLE_ENTRY(_dispatch_stub_596),
+ TABLE_ENTRY(_dispatch_stub_597),
TABLE_ENTRY(SecondaryColor3bEXT),
TABLE_ENTRY(SecondaryColor3bvEXT),
TABLE_ENTRY(SecondaryColor3dEXT),
@@ -6108,7 +6362,7 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = {
TABLE_ENTRY(FogCoorddvEXT),
TABLE_ENTRY(FogCoordfEXT),
TABLE_ENTRY(FogCoordfvEXT),
- TABLE_ENTRY(_dispatch_stub_606),
+ TABLE_ENTRY(_dispatch_stub_622),
TABLE_ENTRY(BlendFuncSeparateEXT),
TABLE_ENTRY(FlushVertexArrayRangeNV),
TABLE_ENTRY(VertexArrayRangeNV),
@@ -6150,15 +6404,15 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = {
TABLE_ENTRY(WindowPos4ivMESA),
TABLE_ENTRY(WindowPos4sMESA),
TABLE_ENTRY(WindowPos4svMESA),
- TABLE_ENTRY(_dispatch_stub_648),
- TABLE_ENTRY(_dispatch_stub_649),
- TABLE_ENTRY(_dispatch_stub_650),
- TABLE_ENTRY(_dispatch_stub_651),
- TABLE_ENTRY(_dispatch_stub_652),
- TABLE_ENTRY(_dispatch_stub_653),
- TABLE_ENTRY(_dispatch_stub_654),
- TABLE_ENTRY(_dispatch_stub_655),
- TABLE_ENTRY(_dispatch_stub_656),
+ TABLE_ENTRY(_dispatch_stub_664),
+ TABLE_ENTRY(_dispatch_stub_665),
+ TABLE_ENTRY(_dispatch_stub_666),
+ TABLE_ENTRY(_dispatch_stub_667),
+ TABLE_ENTRY(_dispatch_stub_668),
+ TABLE_ENTRY(_dispatch_stub_669),
+ TABLE_ENTRY(_dispatch_stub_670),
+ TABLE_ENTRY(_dispatch_stub_671),
+ TABLE_ENTRY(_dispatch_stub_672),
TABLE_ENTRY(AreProgramsResidentNV),
TABLE_ENTRY(BindProgramNV),
TABLE_ENTRY(DeleteProgramsNV),
@@ -6219,6 +6473,10 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = {
TABLE_ENTRY(VertexAttribs4fvNV),
TABLE_ENTRY(VertexAttribs4svNV),
TABLE_ENTRY(VertexAttribs4ubvNV),
+ TABLE_ENTRY(GetTexBumpParameterfvATI),
+ TABLE_ENTRY(GetTexBumpParameterivATI),
+ TABLE_ENTRY(TexBumpParameterfvATI),
+ TABLE_ENTRY(TexBumpParameterivATI),
TABLE_ENTRY(AlphaFragmentOp1ATI),
TABLE_ENTRY(AlphaFragmentOp2ATI),
TABLE_ENTRY(AlphaFragmentOp3ATI),
@@ -6235,19 +6493,19 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = {
TABLE_ENTRY(SetFragmentShaderConstantATI),
TABLE_ENTRY(PointParameteriNV),
TABLE_ENTRY(PointParameterivNV),
- TABLE_ENTRY(_dispatch_stub_733),
- TABLE_ENTRY(_dispatch_stub_734),
- TABLE_ENTRY(_dispatch_stub_735),
- TABLE_ENTRY(_dispatch_stub_736),
- TABLE_ENTRY(_dispatch_stub_737),
+ TABLE_ENTRY(_dispatch_stub_753),
+ TABLE_ENTRY(_dispatch_stub_754),
+ TABLE_ENTRY(_dispatch_stub_755),
+ TABLE_ENTRY(_dispatch_stub_756),
+ TABLE_ENTRY(_dispatch_stub_757),
TABLE_ENTRY(GetProgramNamedParameterdvNV),
TABLE_ENTRY(GetProgramNamedParameterfvNV),
TABLE_ENTRY(ProgramNamedParameter4dNV),
TABLE_ENTRY(ProgramNamedParameter4dvNV),
TABLE_ENTRY(ProgramNamedParameter4fNV),
TABLE_ENTRY(ProgramNamedParameter4fvNV),
- TABLE_ENTRY(_dispatch_stub_744),
- TABLE_ENTRY(_dispatch_stub_745),
+ TABLE_ENTRY(_dispatch_stub_764),
+ TABLE_ENTRY(_dispatch_stub_765),
TABLE_ENTRY(BindFramebufferEXT),
TABLE_ENTRY(BindRenderbufferEXT),
TABLE_ENTRY(CheckFramebufferStatusEXT),
@@ -6265,13 +6523,18 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = {
TABLE_ENTRY(IsFramebufferEXT),
TABLE_ENTRY(IsRenderbufferEXT),
TABLE_ENTRY(RenderbufferStorageEXT),
- TABLE_ENTRY(_dispatch_stub_763),
+ TABLE_ENTRY(_dispatch_stub_783),
+ TABLE_ENTRY(_dispatch_stub_784),
+ TABLE_ENTRY(_dispatch_stub_785),
TABLE_ENTRY(FramebufferTextureLayerEXT),
- TABLE_ENTRY(_dispatch_stub_765),
- TABLE_ENTRY(_dispatch_stub_766),
- TABLE_ENTRY(_dispatch_stub_767),
- TABLE_ENTRY(_dispatch_stub_768),
- TABLE_ENTRY(_dispatch_stub_769),
+ TABLE_ENTRY(ProvokingVertexEXT),
+ TABLE_ENTRY(_dispatch_stub_788),
+ TABLE_ENTRY(_dispatch_stub_789),
+ TABLE_ENTRY(_dispatch_stub_790),
+ TABLE_ENTRY(_dispatch_stub_791),
+ TABLE_ENTRY(_dispatch_stub_792),
+ TABLE_ENTRY(_dispatch_stub_793),
+ TABLE_ENTRY(_dispatch_stub_794),
/* A whole bunch of no-op functions. These might be called
* when someone tries to call a dynamically-registered
* extension function without a current rendering context.
@@ -6638,7 +6901,28 @@ static _glapi_proc UNUSED_TABLE_NAME[] = {
TABLE_ENTRY(IsProgramARB),
TABLE_ENTRY(PointParameteri),
TABLE_ENTRY(PointParameteriv),
+ TABLE_ENTRY(DeleteVertexArrays),
+ TABLE_ENTRY(IsVertexArray),
TABLE_ENTRY(BlendEquationSeparate),
+ TABLE_ENTRY(BindFramebuffer),
+ TABLE_ENTRY(BindRenderbuffer),
+ TABLE_ENTRY(CheckFramebufferStatus),
+ TABLE_ENTRY(DeleteFramebuffers),
+ TABLE_ENTRY(DeleteRenderbuffers),
+ TABLE_ENTRY(FramebufferRenderbuffer),
+ TABLE_ENTRY(FramebufferTexture1D),
+ TABLE_ENTRY(FramebufferTexture2D),
+ TABLE_ENTRY(FramebufferTexture3D),
+ TABLE_ENTRY(GenFramebuffers),
+ TABLE_ENTRY(GenRenderbuffers),
+ TABLE_ENTRY(GenerateMipmap),
+ TABLE_ENTRY(GetFramebufferAttachmentParameteriv),
+ TABLE_ENTRY(GetRenderbufferParameteriv),
+ TABLE_ENTRY(IsFramebuffer),
+ TABLE_ENTRY(IsRenderbuffer),
+ TABLE_ENTRY(RenderbufferStorage),
+ TABLE_ENTRY(BlitFramebuffer),
+ TABLE_ENTRY(FramebufferTextureLayer),
};
#endif /*UNUSED_TABLE_NAME*/
diff --git a/src/mesa/glapi/glprocs.h b/src/mesa/glapi/glprocs.h
index 5a99d505ec..fc0fcd331a 100644
--- a/src/mesa/glapi/glprocs.h
+++ b/src/mesa/glapi/glprocs.h
@@ -613,6 +613,22 @@ static const char gl_string_table[] =
"glGetActiveAttribARB\0"
"glGetAttribLocationARB\0"
"glDrawBuffersARB\0"
+ "glRenderbufferStorageMultisample\0"
+ "glFlushMappedBufferRange\0"
+ "glMapBufferRange\0"
+ "glBindVertexArray\0"
+ "glGenVertexArrays\0"
+ "glCopyBufferSubData\0"
+ "glClientWaitSync\0"
+ "glDeleteSync\0"
+ "glFenceSync\0"
+ "glGetInteger64v\0"
+ "glGetSynciv\0"
+ "glIsSync\0"
+ "glWaitSync\0"
+ "glDrawElementsBaseVertex\0"
+ "glDrawRangeElementsBaseVertex\0"
+ "glMultiDrawElementsBaseVertex\0"
"glPolygonOffsetEXT\0"
"glGetPixelTexGenParameterfvSGIS\0"
"glGetPixelTexGenParameterivSGIS\0"
@@ -769,6 +785,10 @@ static const char gl_string_table[] =
"glVertexAttribs4fvNV\0"
"glVertexAttribs4svNV\0"
"glVertexAttribs4ubvNV\0"
+ "glGetTexBumpParameterfvATI\0"
+ "glGetTexBumpParameterivATI\0"
+ "glTexBumpParameterfvATI\0"
+ "glTexBumpParameterivATI\0"
"glAlphaFragmentOp1ATI\0"
"glAlphaFragmentOp2ATI\0"
"glAlphaFragmentOp3ATI\0"
@@ -816,7 +836,12 @@ static const char gl_string_table[] =
"glIsRenderbufferEXT\0"
"glRenderbufferStorageEXT\0"
"glBlitFramebufferEXT\0"
+ "glBufferParameteriAPPLE\0"
+ "glFlushMappedBufferRangeAPPLE\0"
"glFramebufferTextureLayerEXT\0"
+ "glProvokingVertexEXT\0"
+ "glGetTexParameterPointervAPPLE\0"
+ "glTextureRangeAPPLE\0"
"glStencilFuncSeparateATI\0"
"glProgramEnvParameters4fvEXT\0"
"glProgramLocalParameters4fvEXT\0"
@@ -1099,8 +1124,29 @@ static const char gl_string_table[] =
"glIsProgramARB\0"
"glPointParameteri\0"
"glPointParameteriv\0"
+ "glDeleteVertexArrays\0"
+ "glIsVertexArray\0"
"glBlendEquationSeparate\0"
"glBlendEquationSeparateATI\0"
+ "glBindFramebuffer\0"
+ "glBindRenderbuffer\0"
+ "glCheckFramebufferStatus\0"
+ "glDeleteFramebuffers\0"
+ "glDeleteRenderbuffers\0"
+ "glFramebufferRenderbuffer\0"
+ "glFramebufferTexture1D\0"
+ "glFramebufferTexture2D\0"
+ "glFramebufferTexture3D\0"
+ "glGenFramebuffers\0"
+ "glGenRenderbuffers\0"
+ "glGenerateMipmap\0"
+ "glGetFramebufferAttachmentParameteriv\0"
+ "glGetRenderbufferParameteriv\0"
+ "glIsFramebuffer\0"
+ "glIsRenderbuffer\0"
+ "glRenderbufferStorage\0"
+ "glBlitFramebuffer\0"
+ "glFramebufferTextureLayer\0"
;
@@ -1118,90 +1164,97 @@ static const char gl_string_table[] =
#define gl_dispatch_stub_364 mgl_dispatch_stub_364
#define gl_dispatch_stub_365 mgl_dispatch_stub_365
#define gl_dispatch_stub_366 mgl_dispatch_stub_366
-#define gl_dispatch_stub_562 mgl_dispatch_stub_562
-#define gl_dispatch_stub_563 mgl_dispatch_stub_563
-#define gl_dispatch_stub_564 mgl_dispatch_stub_564
-#define gl_dispatch_stub_565 mgl_dispatch_stub_565
-#define gl_dispatch_stub_566 mgl_dispatch_stub_566
-#define gl_dispatch_stub_567 mgl_dispatch_stub_567
-#define gl_dispatch_stub_568 mgl_dispatch_stub_568
-#define gl_dispatch_stub_569 mgl_dispatch_stub_569
+#define gl_dispatch_stub_578 mgl_dispatch_stub_578
+#define gl_dispatch_stub_579 mgl_dispatch_stub_579
#define gl_dispatch_stub_580 mgl_dispatch_stub_580
#define gl_dispatch_stub_581 mgl_dispatch_stub_581
-#define gl_dispatch_stub_606 mgl_dispatch_stub_606
-#define gl_dispatch_stub_648 mgl_dispatch_stub_648
-#define gl_dispatch_stub_649 mgl_dispatch_stub_649
-#define gl_dispatch_stub_650 mgl_dispatch_stub_650
-#define gl_dispatch_stub_651 mgl_dispatch_stub_651
-#define gl_dispatch_stub_652 mgl_dispatch_stub_652
-#define gl_dispatch_stub_653 mgl_dispatch_stub_653
-#define gl_dispatch_stub_654 mgl_dispatch_stub_654
-#define gl_dispatch_stub_655 mgl_dispatch_stub_655
-#define gl_dispatch_stub_656 mgl_dispatch_stub_656
-#define gl_dispatch_stub_733 mgl_dispatch_stub_733
-#define gl_dispatch_stub_734 mgl_dispatch_stub_734
-#define gl_dispatch_stub_735 mgl_dispatch_stub_735
-#define gl_dispatch_stub_736 mgl_dispatch_stub_736
-#define gl_dispatch_stub_737 mgl_dispatch_stub_737
-#define gl_dispatch_stub_744 mgl_dispatch_stub_744
-#define gl_dispatch_stub_745 mgl_dispatch_stub_745
-#define gl_dispatch_stub_763 mgl_dispatch_stub_763
+#define gl_dispatch_stub_582 mgl_dispatch_stub_582
+#define gl_dispatch_stub_583 mgl_dispatch_stub_583
+#define gl_dispatch_stub_584 mgl_dispatch_stub_584
+#define gl_dispatch_stub_585 mgl_dispatch_stub_585
+#define gl_dispatch_stub_596 mgl_dispatch_stub_596
+#define gl_dispatch_stub_597 mgl_dispatch_stub_597
+#define gl_dispatch_stub_622 mgl_dispatch_stub_622
+#define gl_dispatch_stub_664 mgl_dispatch_stub_664
+#define gl_dispatch_stub_665 mgl_dispatch_stub_665
+#define gl_dispatch_stub_666 mgl_dispatch_stub_666
+#define gl_dispatch_stub_667 mgl_dispatch_stub_667
+#define gl_dispatch_stub_668 mgl_dispatch_stub_668
+#define gl_dispatch_stub_669 mgl_dispatch_stub_669
+#define gl_dispatch_stub_670 mgl_dispatch_stub_670
+#define gl_dispatch_stub_671 mgl_dispatch_stub_671
+#define gl_dispatch_stub_672 mgl_dispatch_stub_672
+#define gl_dispatch_stub_753 mgl_dispatch_stub_753
+#define gl_dispatch_stub_754 mgl_dispatch_stub_754
+#define gl_dispatch_stub_755 mgl_dispatch_stub_755
+#define gl_dispatch_stub_756 mgl_dispatch_stub_756
+#define gl_dispatch_stub_757 mgl_dispatch_stub_757
+#define gl_dispatch_stub_764 mgl_dispatch_stub_764
#define gl_dispatch_stub_765 mgl_dispatch_stub_765
-#define gl_dispatch_stub_766 mgl_dispatch_stub_766
-#define gl_dispatch_stub_767 mgl_dispatch_stub_767
-#define gl_dispatch_stub_768 mgl_dispatch_stub_768
-#define gl_dispatch_stub_769 mgl_dispatch_stub_769
+#define gl_dispatch_stub_783 mgl_dispatch_stub_783
+#define gl_dispatch_stub_784 mgl_dispatch_stub_784
+#define gl_dispatch_stub_785 mgl_dispatch_stub_785
+#define gl_dispatch_stub_788 mgl_dispatch_stub_788
+#define gl_dispatch_stub_789 mgl_dispatch_stub_789
+#define gl_dispatch_stub_790 mgl_dispatch_stub_790
+#define gl_dispatch_stub_791 mgl_dispatch_stub_791
+#define gl_dispatch_stub_792 mgl_dispatch_stub_792
+#define gl_dispatch_stub_793 mgl_dispatch_stub_793
+#define gl_dispatch_stub_794 mgl_dispatch_stub_794
#endif /* USE_MGL_NAMESPACE */
-/* FIXME: Having these (incorrect) prototypes here is ugly. */
#if defined(NEED_FUNCTION_POINTER) || defined(GLX_INDIRECT_RENDERING)
-extern void gl_dispatch_stub_343(void);
-extern void gl_dispatch_stub_344(void);
-extern void gl_dispatch_stub_345(void);
-extern void gl_dispatch_stub_356(void);
-extern void gl_dispatch_stub_357(void);
-extern void gl_dispatch_stub_358(void);
-extern void gl_dispatch_stub_359(void);
-extern void gl_dispatch_stub_361(void);
-extern void gl_dispatch_stub_362(void);
-extern void gl_dispatch_stub_363(void);
-extern void gl_dispatch_stub_364(void);
-extern void gl_dispatch_stub_365(void);
-extern void gl_dispatch_stub_366(void);
-extern void gl_dispatch_stub_562(void);
-extern void gl_dispatch_stub_563(void);
-extern void gl_dispatch_stub_564(void);
-extern void gl_dispatch_stub_565(void);
-extern void gl_dispatch_stub_566(void);
-extern void gl_dispatch_stub_567(void);
-extern void gl_dispatch_stub_568(void);
-extern void gl_dispatch_stub_569(void);
-extern void gl_dispatch_stub_580(void);
-extern void gl_dispatch_stub_581(void);
-extern void gl_dispatch_stub_606(void);
-extern void gl_dispatch_stub_648(void);
-extern void gl_dispatch_stub_649(void);
-extern void gl_dispatch_stub_650(void);
-extern void gl_dispatch_stub_651(void);
-extern void gl_dispatch_stub_652(void);
-extern void gl_dispatch_stub_653(void);
-extern void gl_dispatch_stub_654(void);
-extern void gl_dispatch_stub_655(void);
-extern void gl_dispatch_stub_656(void);
-extern void gl_dispatch_stub_733(void);
-extern void gl_dispatch_stub_734(void);
-extern void gl_dispatch_stub_735(void);
-extern void gl_dispatch_stub_736(void);
-extern void gl_dispatch_stub_737(void);
-extern void gl_dispatch_stub_744(void);
-extern void gl_dispatch_stub_745(void);
-extern void gl_dispatch_stub_763(void);
-extern void gl_dispatch_stub_765(void);
-extern void gl_dispatch_stub_766(void);
-extern void gl_dispatch_stub_767(void);
-extern void gl_dispatch_stub_768(void);
-extern void gl_dispatch_stub_769(void);
+void GLAPIENTRY gl_dispatch_stub_343(GLenum target, GLenum format, GLenum type, GLvoid * table);
+void GLAPIENTRY gl_dispatch_stub_344(GLenum target, GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_345(GLenum target, GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_356(GLenum target, GLenum format, GLenum type, GLvoid * image);
+void GLAPIENTRY gl_dispatch_stub_357(GLenum target, GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_358(GLenum target, GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_359(GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span);
+void GLAPIENTRY gl_dispatch_stub_361(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values);
+void GLAPIENTRY gl_dispatch_stub_362(GLenum target, GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_363(GLenum target, GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_364(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values);
+void GLAPIENTRY gl_dispatch_stub_365(GLenum target, GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_366(GLenum target, GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_578(GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_579(GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_580(GLenum pname, GLfloat param);
+void GLAPIENTRY gl_dispatch_stub_581(GLenum pname, const GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_582(GLenum pname, GLint param);
+void GLAPIENTRY gl_dispatch_stub_583(GLenum pname, const GLint * params);
+void GLAPIENTRY gl_dispatch_stub_584(GLclampf value, GLboolean invert);
+void GLAPIENTRY gl_dispatch_stub_585(GLenum pattern);
+void GLAPIENTRY gl_dispatch_stub_596(GLenum pname, GLdouble * params);
+void GLAPIENTRY gl_dispatch_stub_597(GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_622(GLenum mode);
+void GLAPIENTRY gl_dispatch_stub_664(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride);
+void GLAPIENTRY gl_dispatch_stub_665(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride);
+void GLAPIENTRY gl_dispatch_stub_666(GLsizei n, const GLuint * fences);
+void GLAPIENTRY gl_dispatch_stub_667(GLuint fence);
+void GLAPIENTRY gl_dispatch_stub_668(GLsizei n, GLuint * fences);
+void GLAPIENTRY gl_dispatch_stub_669(GLuint fence, GLenum pname, GLint * params);
+GLboolean GLAPIENTRY gl_dispatch_stub_670(GLuint fence);
+void GLAPIENTRY gl_dispatch_stub_671(GLuint fence, GLenum condition);
+GLboolean GLAPIENTRY gl_dispatch_stub_672(GLuint fence);
+void GLAPIENTRY gl_dispatch_stub_753(GLenum face);
+void GLAPIENTRY gl_dispatch_stub_754(GLuint array);
+void GLAPIENTRY gl_dispatch_stub_755(GLsizei n, const GLuint * arrays);
+void GLAPIENTRY gl_dispatch_stub_756(GLsizei n, GLuint * arrays);
+GLboolean GLAPIENTRY gl_dispatch_stub_757(GLuint array);
+void GLAPIENTRY gl_dispatch_stub_764(GLclampd zmin, GLclampd zmax);
+void GLAPIENTRY gl_dispatch_stub_765(GLenum modeRGB, GLenum modeA);
+void GLAPIENTRY gl_dispatch_stub_783(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+void GLAPIENTRY gl_dispatch_stub_784(GLenum target, GLenum pname, GLint param);
+void GLAPIENTRY gl_dispatch_stub_785(GLenum target, GLintptr offset, GLsizeiptr size);
+void GLAPIENTRY gl_dispatch_stub_788(GLenum target, GLenum pname, GLvoid ** params);
+void GLAPIENTRY gl_dispatch_stub_789(GLenum target, GLsizei length, GLvoid * pointer);
+void GLAPIENTRY gl_dispatch_stub_790(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+void GLAPIENTRY gl_dispatch_stub_791(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_792(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_793(GLuint id, GLenum pname, GLint64EXT * params);
+void GLAPIENTRY gl_dispatch_stub_794(GLuint id, GLenum pname, GLuint64EXT * params);
#endif /* defined(NEED_FUNCTION_POINTER) || defined(GLX_INDIRECT_RENDERING) */
static const glprocs_table_t static_functions[] = {
@@ -1766,494 +1819,540 @@ static const glprocs_table_t static_functions[] = {
NAME_FUNC_OFFSET( 8890, glGetActiveAttribARB, glGetActiveAttribARB, NULL, _gloffset_GetActiveAttribARB),
NAME_FUNC_OFFSET( 8911, glGetAttribLocationARB, glGetAttribLocationARB, NULL, _gloffset_GetAttribLocationARB),
NAME_FUNC_OFFSET( 8934, glDrawBuffersARB, glDrawBuffersARB, NULL, _gloffset_DrawBuffersARB),
- NAME_FUNC_OFFSET( 8951, glPolygonOffsetEXT, glPolygonOffsetEXT, NULL, _gloffset_PolygonOffsetEXT),
- NAME_FUNC_OFFSET( 8970, gl_dispatch_stub_562, gl_dispatch_stub_562, NULL, _gloffset_GetPixelTexGenParameterfvSGIS),
- NAME_FUNC_OFFSET( 9002, gl_dispatch_stub_563, gl_dispatch_stub_563, NULL, _gloffset_GetPixelTexGenParameterivSGIS),
- NAME_FUNC_OFFSET( 9034, gl_dispatch_stub_564, gl_dispatch_stub_564, NULL, _gloffset_PixelTexGenParameterfSGIS),
- NAME_FUNC_OFFSET( 9062, gl_dispatch_stub_565, gl_dispatch_stub_565, NULL, _gloffset_PixelTexGenParameterfvSGIS),
- NAME_FUNC_OFFSET( 9091, gl_dispatch_stub_566, gl_dispatch_stub_566, NULL, _gloffset_PixelTexGenParameteriSGIS),
- NAME_FUNC_OFFSET( 9119, gl_dispatch_stub_567, gl_dispatch_stub_567, NULL, _gloffset_PixelTexGenParameterivSGIS),
- NAME_FUNC_OFFSET( 9148, gl_dispatch_stub_568, gl_dispatch_stub_568, NULL, _gloffset_SampleMaskSGIS),
- NAME_FUNC_OFFSET( 9165, gl_dispatch_stub_569, gl_dispatch_stub_569, NULL, _gloffset_SamplePatternSGIS),
- NAME_FUNC_OFFSET( 9185, glColorPointerEXT, glColorPointerEXT, NULL, _gloffset_ColorPointerEXT),
- NAME_FUNC_OFFSET( 9203, glEdgeFlagPointerEXT, glEdgeFlagPointerEXT, NULL, _gloffset_EdgeFlagPointerEXT),
- NAME_FUNC_OFFSET( 9224, glIndexPointerEXT, glIndexPointerEXT, NULL, _gloffset_IndexPointerEXT),
- NAME_FUNC_OFFSET( 9242, glNormalPointerEXT, glNormalPointerEXT, NULL, _gloffset_NormalPointerEXT),
- NAME_FUNC_OFFSET( 9261, glTexCoordPointerEXT, glTexCoordPointerEXT, NULL, _gloffset_TexCoordPointerEXT),
- NAME_FUNC_OFFSET( 9282, glVertexPointerEXT, glVertexPointerEXT, NULL, _gloffset_VertexPointerEXT),
- NAME_FUNC_OFFSET( 9301, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
- NAME_FUNC_OFFSET( 9322, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
- NAME_FUNC_OFFSET( 9344, glLockArraysEXT, glLockArraysEXT, NULL, _gloffset_LockArraysEXT),
- NAME_FUNC_OFFSET( 9360, glUnlockArraysEXT, glUnlockArraysEXT, NULL, _gloffset_UnlockArraysEXT),
- NAME_FUNC_OFFSET( 9378, gl_dispatch_stub_580, gl_dispatch_stub_580, NULL, _gloffset_CullParameterdvEXT),
- NAME_FUNC_OFFSET( 9399, gl_dispatch_stub_581, gl_dispatch_stub_581, NULL, _gloffset_CullParameterfvEXT),
- NAME_FUNC_OFFSET( 9420, glSecondaryColor3bEXT, glSecondaryColor3bEXT, NULL, _gloffset_SecondaryColor3bEXT),
- NAME_FUNC_OFFSET( 9442, glSecondaryColor3bvEXT, glSecondaryColor3bvEXT, NULL, _gloffset_SecondaryColor3bvEXT),
- NAME_FUNC_OFFSET( 9465, glSecondaryColor3dEXT, glSecondaryColor3dEXT, NULL, _gloffset_SecondaryColor3dEXT),
- NAME_FUNC_OFFSET( 9487, glSecondaryColor3dvEXT, glSecondaryColor3dvEXT, NULL, _gloffset_SecondaryColor3dvEXT),
- NAME_FUNC_OFFSET( 9510, glSecondaryColor3fEXT, glSecondaryColor3fEXT, NULL, _gloffset_SecondaryColor3fEXT),
- NAME_FUNC_OFFSET( 9532, glSecondaryColor3fvEXT, glSecondaryColor3fvEXT, NULL, _gloffset_SecondaryColor3fvEXT),
- NAME_FUNC_OFFSET( 9555, glSecondaryColor3iEXT, glSecondaryColor3iEXT, NULL, _gloffset_SecondaryColor3iEXT),
- NAME_FUNC_OFFSET( 9577, glSecondaryColor3ivEXT, glSecondaryColor3ivEXT, NULL, _gloffset_SecondaryColor3ivEXT),
- NAME_FUNC_OFFSET( 9600, glSecondaryColor3sEXT, glSecondaryColor3sEXT, NULL, _gloffset_SecondaryColor3sEXT),
- NAME_FUNC_OFFSET( 9622, glSecondaryColor3svEXT, glSecondaryColor3svEXT, NULL, _gloffset_SecondaryColor3svEXT),
- NAME_FUNC_OFFSET( 9645, glSecondaryColor3ubEXT, glSecondaryColor3ubEXT, NULL, _gloffset_SecondaryColor3ubEXT),
- NAME_FUNC_OFFSET( 9668, glSecondaryColor3ubvEXT, glSecondaryColor3ubvEXT, NULL, _gloffset_SecondaryColor3ubvEXT),
- NAME_FUNC_OFFSET( 9692, glSecondaryColor3uiEXT, glSecondaryColor3uiEXT, NULL, _gloffset_SecondaryColor3uiEXT),
- NAME_FUNC_OFFSET( 9715, glSecondaryColor3uivEXT, glSecondaryColor3uivEXT, NULL, _gloffset_SecondaryColor3uivEXT),
- NAME_FUNC_OFFSET( 9739, glSecondaryColor3usEXT, glSecondaryColor3usEXT, NULL, _gloffset_SecondaryColor3usEXT),
- NAME_FUNC_OFFSET( 9762, glSecondaryColor3usvEXT, glSecondaryColor3usvEXT, NULL, _gloffset_SecondaryColor3usvEXT),
- NAME_FUNC_OFFSET( 9786, glSecondaryColorPointerEXT, glSecondaryColorPointerEXT, NULL, _gloffset_SecondaryColorPointerEXT),
- NAME_FUNC_OFFSET( 9813, glMultiDrawArraysEXT, glMultiDrawArraysEXT, NULL, _gloffset_MultiDrawArraysEXT),
- NAME_FUNC_OFFSET( 9834, glMultiDrawElementsEXT, glMultiDrawElementsEXT, NULL, _gloffset_MultiDrawElementsEXT),
- NAME_FUNC_OFFSET( 9857, glFogCoordPointerEXT, glFogCoordPointerEXT, NULL, _gloffset_FogCoordPointerEXT),
- NAME_FUNC_OFFSET( 9878, glFogCoorddEXT, glFogCoorddEXT, NULL, _gloffset_FogCoorddEXT),
- NAME_FUNC_OFFSET( 9893, glFogCoorddvEXT, glFogCoorddvEXT, NULL, _gloffset_FogCoorddvEXT),
- NAME_FUNC_OFFSET( 9909, glFogCoordfEXT, glFogCoordfEXT, NULL, _gloffset_FogCoordfEXT),
- NAME_FUNC_OFFSET( 9924, glFogCoordfvEXT, glFogCoordfvEXT, NULL, _gloffset_FogCoordfvEXT),
- NAME_FUNC_OFFSET( 9940, gl_dispatch_stub_606, gl_dispatch_stub_606, NULL, _gloffset_PixelTexGenSGIX),
- NAME_FUNC_OFFSET( 9958, glBlendFuncSeparateEXT, glBlendFuncSeparateEXT, NULL, _gloffset_BlendFuncSeparateEXT),
- NAME_FUNC_OFFSET( 9981, glFlushVertexArrayRangeNV, glFlushVertexArrayRangeNV, NULL, _gloffset_FlushVertexArrayRangeNV),
- NAME_FUNC_OFFSET(10007, glVertexArrayRangeNV, glVertexArrayRangeNV, NULL, _gloffset_VertexArrayRangeNV),
- NAME_FUNC_OFFSET(10028, glCombinerInputNV, glCombinerInputNV, NULL, _gloffset_CombinerInputNV),
- NAME_FUNC_OFFSET(10046, glCombinerOutputNV, glCombinerOutputNV, NULL, _gloffset_CombinerOutputNV),
- NAME_FUNC_OFFSET(10065, glCombinerParameterfNV, glCombinerParameterfNV, NULL, _gloffset_CombinerParameterfNV),
- NAME_FUNC_OFFSET(10088, glCombinerParameterfvNV, glCombinerParameterfvNV, NULL, _gloffset_CombinerParameterfvNV),
- NAME_FUNC_OFFSET(10112, glCombinerParameteriNV, glCombinerParameteriNV, NULL, _gloffset_CombinerParameteriNV),
- NAME_FUNC_OFFSET(10135, glCombinerParameterivNV, glCombinerParameterivNV, NULL, _gloffset_CombinerParameterivNV),
- NAME_FUNC_OFFSET(10159, glFinalCombinerInputNV, glFinalCombinerInputNV, NULL, _gloffset_FinalCombinerInputNV),
- NAME_FUNC_OFFSET(10182, glGetCombinerInputParameterfvNV, glGetCombinerInputParameterfvNV, NULL, _gloffset_GetCombinerInputParameterfvNV),
- NAME_FUNC_OFFSET(10214, glGetCombinerInputParameterivNV, glGetCombinerInputParameterivNV, NULL, _gloffset_GetCombinerInputParameterivNV),
- NAME_FUNC_OFFSET(10246, glGetCombinerOutputParameterfvNV, glGetCombinerOutputParameterfvNV, NULL, _gloffset_GetCombinerOutputParameterfvNV),
- NAME_FUNC_OFFSET(10279, glGetCombinerOutputParameterivNV, glGetCombinerOutputParameterivNV, NULL, _gloffset_GetCombinerOutputParameterivNV),
- NAME_FUNC_OFFSET(10312, glGetFinalCombinerInputParameterfvNV, glGetFinalCombinerInputParameterfvNV, NULL, _gloffset_GetFinalCombinerInputParameterfvNV),
- NAME_FUNC_OFFSET(10349, glGetFinalCombinerInputParameterivNV, glGetFinalCombinerInputParameterivNV, NULL, _gloffset_GetFinalCombinerInputParameterivNV),
- NAME_FUNC_OFFSET(10386, glResizeBuffersMESA, glResizeBuffersMESA, NULL, _gloffset_ResizeBuffersMESA),
- NAME_FUNC_OFFSET(10406, glWindowPos2dMESA, glWindowPos2dMESA, NULL, _gloffset_WindowPos2dMESA),
- NAME_FUNC_OFFSET(10424, glWindowPos2dvMESA, glWindowPos2dvMESA, NULL, _gloffset_WindowPos2dvMESA),
- NAME_FUNC_OFFSET(10443, glWindowPos2fMESA, glWindowPos2fMESA, NULL, _gloffset_WindowPos2fMESA),
- NAME_FUNC_OFFSET(10461, glWindowPos2fvMESA, glWindowPos2fvMESA, NULL, _gloffset_WindowPos2fvMESA),
- NAME_FUNC_OFFSET(10480, glWindowPos2iMESA, glWindowPos2iMESA, NULL, _gloffset_WindowPos2iMESA),
- NAME_FUNC_OFFSET(10498, glWindowPos2ivMESA, glWindowPos2ivMESA, NULL, _gloffset_WindowPos2ivMESA),
- NAME_FUNC_OFFSET(10517, glWindowPos2sMESA, glWindowPos2sMESA, NULL, _gloffset_WindowPos2sMESA),
- NAME_FUNC_OFFSET(10535, glWindowPos2svMESA, glWindowPos2svMESA, NULL, _gloffset_WindowPos2svMESA),
- NAME_FUNC_OFFSET(10554, glWindowPos3dMESA, glWindowPos3dMESA, NULL, _gloffset_WindowPos3dMESA),
- NAME_FUNC_OFFSET(10572, glWindowPos3dvMESA, glWindowPos3dvMESA, NULL, _gloffset_WindowPos3dvMESA),
- NAME_FUNC_OFFSET(10591, glWindowPos3fMESA, glWindowPos3fMESA, NULL, _gloffset_WindowPos3fMESA),
- NAME_FUNC_OFFSET(10609, glWindowPos3fvMESA, glWindowPos3fvMESA, NULL, _gloffset_WindowPos3fvMESA),
- NAME_FUNC_OFFSET(10628, glWindowPos3iMESA, glWindowPos3iMESA, NULL, _gloffset_WindowPos3iMESA),
- NAME_FUNC_OFFSET(10646, glWindowPos3ivMESA, glWindowPos3ivMESA, NULL, _gloffset_WindowPos3ivMESA),
- NAME_FUNC_OFFSET(10665, glWindowPos3sMESA, glWindowPos3sMESA, NULL, _gloffset_WindowPos3sMESA),
- NAME_FUNC_OFFSET(10683, glWindowPos3svMESA, glWindowPos3svMESA, NULL, _gloffset_WindowPos3svMESA),
- NAME_FUNC_OFFSET(10702, glWindowPos4dMESA, glWindowPos4dMESA, NULL, _gloffset_WindowPos4dMESA),
- NAME_FUNC_OFFSET(10720, glWindowPos4dvMESA, glWindowPos4dvMESA, NULL, _gloffset_WindowPos4dvMESA),
- NAME_FUNC_OFFSET(10739, glWindowPos4fMESA, glWindowPos4fMESA, NULL, _gloffset_WindowPos4fMESA),
- NAME_FUNC_OFFSET(10757, glWindowPos4fvMESA, glWindowPos4fvMESA, NULL, _gloffset_WindowPos4fvMESA),
- NAME_FUNC_OFFSET(10776, glWindowPos4iMESA, glWindowPos4iMESA, NULL, _gloffset_WindowPos4iMESA),
- NAME_FUNC_OFFSET(10794, glWindowPos4ivMESA, glWindowPos4ivMESA, NULL, _gloffset_WindowPos4ivMESA),
- NAME_FUNC_OFFSET(10813, glWindowPos4sMESA, glWindowPos4sMESA, NULL, _gloffset_WindowPos4sMESA),
- NAME_FUNC_OFFSET(10831, glWindowPos4svMESA, glWindowPos4svMESA, NULL, _gloffset_WindowPos4svMESA),
- NAME_FUNC_OFFSET(10850, gl_dispatch_stub_648, gl_dispatch_stub_648, NULL, _gloffset_MultiModeDrawArraysIBM),
- NAME_FUNC_OFFSET(10875, gl_dispatch_stub_649, gl_dispatch_stub_649, NULL, _gloffset_MultiModeDrawElementsIBM),
- NAME_FUNC_OFFSET(10902, gl_dispatch_stub_650, gl_dispatch_stub_650, NULL, _gloffset_DeleteFencesNV),
- NAME_FUNC_OFFSET(10919, gl_dispatch_stub_651, gl_dispatch_stub_651, NULL, _gloffset_FinishFenceNV),
- NAME_FUNC_OFFSET(10935, gl_dispatch_stub_652, gl_dispatch_stub_652, NULL, _gloffset_GenFencesNV),
- NAME_FUNC_OFFSET(10949, gl_dispatch_stub_653, gl_dispatch_stub_653, NULL, _gloffset_GetFenceivNV),
- NAME_FUNC_OFFSET(10964, gl_dispatch_stub_654, gl_dispatch_stub_654, NULL, _gloffset_IsFenceNV),
- NAME_FUNC_OFFSET(10976, gl_dispatch_stub_655, gl_dispatch_stub_655, NULL, _gloffset_SetFenceNV),
- NAME_FUNC_OFFSET(10989, gl_dispatch_stub_656, gl_dispatch_stub_656, NULL, _gloffset_TestFenceNV),
- NAME_FUNC_OFFSET(11003, glAreProgramsResidentNV, glAreProgramsResidentNV, NULL, _gloffset_AreProgramsResidentNV),
- NAME_FUNC_OFFSET(11027, glBindProgramNV, glBindProgramNV, NULL, _gloffset_BindProgramNV),
- NAME_FUNC_OFFSET(11043, glDeleteProgramsNV, glDeleteProgramsNV, NULL, _gloffset_DeleteProgramsNV),
- NAME_FUNC_OFFSET(11062, glExecuteProgramNV, glExecuteProgramNV, NULL, _gloffset_ExecuteProgramNV),
- NAME_FUNC_OFFSET(11081, glGenProgramsNV, glGenProgramsNV, NULL, _gloffset_GenProgramsNV),
- NAME_FUNC_OFFSET(11097, glGetProgramParameterdvNV, glGetProgramParameterdvNV, NULL, _gloffset_GetProgramParameterdvNV),
- NAME_FUNC_OFFSET(11123, glGetProgramParameterfvNV, glGetProgramParameterfvNV, NULL, _gloffset_GetProgramParameterfvNV),
- NAME_FUNC_OFFSET(11149, glGetProgramStringNV, glGetProgramStringNV, NULL, _gloffset_GetProgramStringNV),
- NAME_FUNC_OFFSET(11170, glGetProgramivNV, glGetProgramivNV, NULL, _gloffset_GetProgramivNV),
- NAME_FUNC_OFFSET(11187, glGetTrackMatrixivNV, glGetTrackMatrixivNV, NULL, _gloffset_GetTrackMatrixivNV),
- NAME_FUNC_OFFSET(11208, glGetVertexAttribPointervNV, glGetVertexAttribPointervNV, NULL, _gloffset_GetVertexAttribPointervNV),
- NAME_FUNC_OFFSET(11236, glGetVertexAttribdvNV, glGetVertexAttribdvNV, NULL, _gloffset_GetVertexAttribdvNV),
- NAME_FUNC_OFFSET(11258, glGetVertexAttribfvNV, glGetVertexAttribfvNV, NULL, _gloffset_GetVertexAttribfvNV),
- NAME_FUNC_OFFSET(11280, glGetVertexAttribivNV, glGetVertexAttribivNV, NULL, _gloffset_GetVertexAttribivNV),
- NAME_FUNC_OFFSET(11302, glIsProgramNV, glIsProgramNV, NULL, _gloffset_IsProgramNV),
- NAME_FUNC_OFFSET(11316, glLoadProgramNV, glLoadProgramNV, NULL, _gloffset_LoadProgramNV),
- NAME_FUNC_OFFSET(11332, glProgramParameters4dvNV, glProgramParameters4dvNV, NULL, _gloffset_ProgramParameters4dvNV),
- NAME_FUNC_OFFSET(11357, glProgramParameters4fvNV, glProgramParameters4fvNV, NULL, _gloffset_ProgramParameters4fvNV),
- NAME_FUNC_OFFSET(11382, glRequestResidentProgramsNV, glRequestResidentProgramsNV, NULL, _gloffset_RequestResidentProgramsNV),
- NAME_FUNC_OFFSET(11410, glTrackMatrixNV, glTrackMatrixNV, NULL, _gloffset_TrackMatrixNV),
- NAME_FUNC_OFFSET(11426, glVertexAttrib1dNV, glVertexAttrib1dNV, NULL, _gloffset_VertexAttrib1dNV),
- NAME_FUNC_OFFSET(11445, glVertexAttrib1dvNV, glVertexAttrib1dvNV, NULL, _gloffset_VertexAttrib1dvNV),
- NAME_FUNC_OFFSET(11465, glVertexAttrib1fNV, glVertexAttrib1fNV, NULL, _gloffset_VertexAttrib1fNV),
- NAME_FUNC_OFFSET(11484, glVertexAttrib1fvNV, glVertexAttrib1fvNV, NULL, _gloffset_VertexAttrib1fvNV),
- NAME_FUNC_OFFSET(11504, glVertexAttrib1sNV, glVertexAttrib1sNV, NULL, _gloffset_VertexAttrib1sNV),
- NAME_FUNC_OFFSET(11523, glVertexAttrib1svNV, glVertexAttrib1svNV, NULL, _gloffset_VertexAttrib1svNV),
- NAME_FUNC_OFFSET(11543, glVertexAttrib2dNV, glVertexAttrib2dNV, NULL, _gloffset_VertexAttrib2dNV),
- NAME_FUNC_OFFSET(11562, glVertexAttrib2dvNV, glVertexAttrib2dvNV, NULL, _gloffset_VertexAttrib2dvNV),
- NAME_FUNC_OFFSET(11582, glVertexAttrib2fNV, glVertexAttrib2fNV, NULL, _gloffset_VertexAttrib2fNV),
- NAME_FUNC_OFFSET(11601, glVertexAttrib2fvNV, glVertexAttrib2fvNV, NULL, _gloffset_VertexAttrib2fvNV),
- NAME_FUNC_OFFSET(11621, glVertexAttrib2sNV, glVertexAttrib2sNV, NULL, _gloffset_VertexAttrib2sNV),
- NAME_FUNC_OFFSET(11640, glVertexAttrib2svNV, glVertexAttrib2svNV, NULL, _gloffset_VertexAttrib2svNV),
- NAME_FUNC_OFFSET(11660, glVertexAttrib3dNV, glVertexAttrib3dNV, NULL, _gloffset_VertexAttrib3dNV),
- NAME_FUNC_OFFSET(11679, glVertexAttrib3dvNV, glVertexAttrib3dvNV, NULL, _gloffset_VertexAttrib3dvNV),
- NAME_FUNC_OFFSET(11699, glVertexAttrib3fNV, glVertexAttrib3fNV, NULL, _gloffset_VertexAttrib3fNV),
- NAME_FUNC_OFFSET(11718, glVertexAttrib3fvNV, glVertexAttrib3fvNV, NULL, _gloffset_VertexAttrib3fvNV),
- NAME_FUNC_OFFSET(11738, glVertexAttrib3sNV, glVertexAttrib3sNV, NULL, _gloffset_VertexAttrib3sNV),
- NAME_FUNC_OFFSET(11757, glVertexAttrib3svNV, glVertexAttrib3svNV, NULL, _gloffset_VertexAttrib3svNV),
- NAME_FUNC_OFFSET(11777, glVertexAttrib4dNV, glVertexAttrib4dNV, NULL, _gloffset_VertexAttrib4dNV),
- NAME_FUNC_OFFSET(11796, glVertexAttrib4dvNV, glVertexAttrib4dvNV, NULL, _gloffset_VertexAttrib4dvNV),
- NAME_FUNC_OFFSET(11816, glVertexAttrib4fNV, glVertexAttrib4fNV, NULL, _gloffset_VertexAttrib4fNV),
- NAME_FUNC_OFFSET(11835, glVertexAttrib4fvNV, glVertexAttrib4fvNV, NULL, _gloffset_VertexAttrib4fvNV),
- NAME_FUNC_OFFSET(11855, glVertexAttrib4sNV, glVertexAttrib4sNV, NULL, _gloffset_VertexAttrib4sNV),
- NAME_FUNC_OFFSET(11874, glVertexAttrib4svNV, glVertexAttrib4svNV, NULL, _gloffset_VertexAttrib4svNV),
- NAME_FUNC_OFFSET(11894, glVertexAttrib4ubNV, glVertexAttrib4ubNV, NULL, _gloffset_VertexAttrib4ubNV),
- NAME_FUNC_OFFSET(11914, glVertexAttrib4ubvNV, glVertexAttrib4ubvNV, NULL, _gloffset_VertexAttrib4ubvNV),
- NAME_FUNC_OFFSET(11935, glVertexAttribPointerNV, glVertexAttribPointerNV, NULL, _gloffset_VertexAttribPointerNV),
- NAME_FUNC_OFFSET(11959, glVertexAttribs1dvNV, glVertexAttribs1dvNV, NULL, _gloffset_VertexAttribs1dvNV),
- NAME_FUNC_OFFSET(11980, glVertexAttribs1fvNV, glVertexAttribs1fvNV, NULL, _gloffset_VertexAttribs1fvNV),
- NAME_FUNC_OFFSET(12001, glVertexAttribs1svNV, glVertexAttribs1svNV, NULL, _gloffset_VertexAttribs1svNV),
- NAME_FUNC_OFFSET(12022, glVertexAttribs2dvNV, glVertexAttribs2dvNV, NULL, _gloffset_VertexAttribs2dvNV),
- NAME_FUNC_OFFSET(12043, glVertexAttribs2fvNV, glVertexAttribs2fvNV, NULL, _gloffset_VertexAttribs2fvNV),
- NAME_FUNC_OFFSET(12064, glVertexAttribs2svNV, glVertexAttribs2svNV, NULL, _gloffset_VertexAttribs2svNV),
- NAME_FUNC_OFFSET(12085, glVertexAttribs3dvNV, glVertexAttribs3dvNV, NULL, _gloffset_VertexAttribs3dvNV),
- NAME_FUNC_OFFSET(12106, glVertexAttribs3fvNV, glVertexAttribs3fvNV, NULL, _gloffset_VertexAttribs3fvNV),
- NAME_FUNC_OFFSET(12127, glVertexAttribs3svNV, glVertexAttribs3svNV, NULL, _gloffset_VertexAttribs3svNV),
- NAME_FUNC_OFFSET(12148, glVertexAttribs4dvNV, glVertexAttribs4dvNV, NULL, _gloffset_VertexAttribs4dvNV),
- NAME_FUNC_OFFSET(12169, glVertexAttribs4fvNV, glVertexAttribs4fvNV, NULL, _gloffset_VertexAttribs4fvNV),
- NAME_FUNC_OFFSET(12190, glVertexAttribs4svNV, glVertexAttribs4svNV, NULL, _gloffset_VertexAttribs4svNV),
- NAME_FUNC_OFFSET(12211, glVertexAttribs4ubvNV, glVertexAttribs4ubvNV, NULL, _gloffset_VertexAttribs4ubvNV),
- NAME_FUNC_OFFSET(12233, glAlphaFragmentOp1ATI, glAlphaFragmentOp1ATI, NULL, _gloffset_AlphaFragmentOp1ATI),
- NAME_FUNC_OFFSET(12255, glAlphaFragmentOp2ATI, glAlphaFragmentOp2ATI, NULL, _gloffset_AlphaFragmentOp2ATI),
- NAME_FUNC_OFFSET(12277, glAlphaFragmentOp3ATI, glAlphaFragmentOp3ATI, NULL, _gloffset_AlphaFragmentOp3ATI),
- NAME_FUNC_OFFSET(12299, glBeginFragmentShaderATI, glBeginFragmentShaderATI, NULL, _gloffset_BeginFragmentShaderATI),
- NAME_FUNC_OFFSET(12324, glBindFragmentShaderATI, glBindFragmentShaderATI, NULL, _gloffset_BindFragmentShaderATI),
- NAME_FUNC_OFFSET(12348, glColorFragmentOp1ATI, glColorFragmentOp1ATI, NULL, _gloffset_ColorFragmentOp1ATI),
- NAME_FUNC_OFFSET(12370, glColorFragmentOp2ATI, glColorFragmentOp2ATI, NULL, _gloffset_ColorFragmentOp2ATI),
- NAME_FUNC_OFFSET(12392, glColorFragmentOp3ATI, glColorFragmentOp3ATI, NULL, _gloffset_ColorFragmentOp3ATI),
- NAME_FUNC_OFFSET(12414, glDeleteFragmentShaderATI, glDeleteFragmentShaderATI, NULL, _gloffset_DeleteFragmentShaderATI),
- NAME_FUNC_OFFSET(12440, glEndFragmentShaderATI, glEndFragmentShaderATI, NULL, _gloffset_EndFragmentShaderATI),
- NAME_FUNC_OFFSET(12463, glGenFragmentShadersATI, glGenFragmentShadersATI, NULL, _gloffset_GenFragmentShadersATI),
- NAME_FUNC_OFFSET(12487, glPassTexCoordATI, glPassTexCoordATI, NULL, _gloffset_PassTexCoordATI),
- NAME_FUNC_OFFSET(12505, glSampleMapATI, glSampleMapATI, NULL, _gloffset_SampleMapATI),
- NAME_FUNC_OFFSET(12520, glSetFragmentShaderConstantATI, glSetFragmentShaderConstantATI, NULL, _gloffset_SetFragmentShaderConstantATI),
- NAME_FUNC_OFFSET(12551, glPointParameteriNV, glPointParameteriNV, NULL, _gloffset_PointParameteriNV),
- NAME_FUNC_OFFSET(12571, glPointParameterivNV, glPointParameterivNV, NULL, _gloffset_PointParameterivNV),
- NAME_FUNC_OFFSET(12592, gl_dispatch_stub_733, gl_dispatch_stub_733, NULL, _gloffset_ActiveStencilFaceEXT),
- NAME_FUNC_OFFSET(12615, gl_dispatch_stub_734, gl_dispatch_stub_734, NULL, _gloffset_BindVertexArrayAPPLE),
- NAME_FUNC_OFFSET(12638, gl_dispatch_stub_735, gl_dispatch_stub_735, NULL, _gloffset_DeleteVertexArraysAPPLE),
- NAME_FUNC_OFFSET(12664, gl_dispatch_stub_736, gl_dispatch_stub_736, NULL, _gloffset_GenVertexArraysAPPLE),
- NAME_FUNC_OFFSET(12687, gl_dispatch_stub_737, gl_dispatch_stub_737, NULL, _gloffset_IsVertexArrayAPPLE),
- NAME_FUNC_OFFSET(12708, glGetProgramNamedParameterdvNV, glGetProgramNamedParameterdvNV, NULL, _gloffset_GetProgramNamedParameterdvNV),
- NAME_FUNC_OFFSET(12739, glGetProgramNamedParameterfvNV, glGetProgramNamedParameterfvNV, NULL, _gloffset_GetProgramNamedParameterfvNV),
- NAME_FUNC_OFFSET(12770, glProgramNamedParameter4dNV, glProgramNamedParameter4dNV, NULL, _gloffset_ProgramNamedParameter4dNV),
- NAME_FUNC_OFFSET(12798, glProgramNamedParameter4dvNV, glProgramNamedParameter4dvNV, NULL, _gloffset_ProgramNamedParameter4dvNV),
- NAME_FUNC_OFFSET(12827, glProgramNamedParameter4fNV, glProgramNamedParameter4fNV, NULL, _gloffset_ProgramNamedParameter4fNV),
- NAME_FUNC_OFFSET(12855, glProgramNamedParameter4fvNV, glProgramNamedParameter4fvNV, NULL, _gloffset_ProgramNamedParameter4fvNV),
- NAME_FUNC_OFFSET(12884, gl_dispatch_stub_744, gl_dispatch_stub_744, NULL, _gloffset_DepthBoundsEXT),
- NAME_FUNC_OFFSET(12901, gl_dispatch_stub_745, gl_dispatch_stub_745, NULL, _gloffset_BlendEquationSeparateEXT),
- NAME_FUNC_OFFSET(12928, glBindFramebufferEXT, glBindFramebufferEXT, NULL, _gloffset_BindFramebufferEXT),
- NAME_FUNC_OFFSET(12949, glBindRenderbufferEXT, glBindRenderbufferEXT, NULL, _gloffset_BindRenderbufferEXT),
- NAME_FUNC_OFFSET(12971, glCheckFramebufferStatusEXT, glCheckFramebufferStatusEXT, NULL, _gloffset_CheckFramebufferStatusEXT),
- NAME_FUNC_OFFSET(12999, glDeleteFramebuffersEXT, glDeleteFramebuffersEXT, NULL, _gloffset_DeleteFramebuffersEXT),
- NAME_FUNC_OFFSET(13023, glDeleteRenderbuffersEXT, glDeleteRenderbuffersEXT, NULL, _gloffset_DeleteRenderbuffersEXT),
- NAME_FUNC_OFFSET(13048, glFramebufferRenderbufferEXT, glFramebufferRenderbufferEXT, NULL, _gloffset_FramebufferRenderbufferEXT),
- NAME_FUNC_OFFSET(13077, glFramebufferTexture1DEXT, glFramebufferTexture1DEXT, NULL, _gloffset_FramebufferTexture1DEXT),
- NAME_FUNC_OFFSET(13103, glFramebufferTexture2DEXT, glFramebufferTexture2DEXT, NULL, _gloffset_FramebufferTexture2DEXT),
- NAME_FUNC_OFFSET(13129, glFramebufferTexture3DEXT, glFramebufferTexture3DEXT, NULL, _gloffset_FramebufferTexture3DEXT),
- NAME_FUNC_OFFSET(13155, glGenFramebuffersEXT, glGenFramebuffersEXT, NULL, _gloffset_GenFramebuffersEXT),
- NAME_FUNC_OFFSET(13176, glGenRenderbuffersEXT, glGenRenderbuffersEXT, NULL, _gloffset_GenRenderbuffersEXT),
- NAME_FUNC_OFFSET(13198, glGenerateMipmapEXT, glGenerateMipmapEXT, NULL, _gloffset_GenerateMipmapEXT),
- NAME_FUNC_OFFSET(13218, glGetFramebufferAttachmentParameterivEXT, glGetFramebufferAttachmentParameterivEXT, NULL, _gloffset_GetFramebufferAttachmentParameterivEXT),
- NAME_FUNC_OFFSET(13259, glGetRenderbufferParameterivEXT, glGetRenderbufferParameterivEXT, NULL, _gloffset_GetRenderbufferParameterivEXT),
- NAME_FUNC_OFFSET(13291, glIsFramebufferEXT, glIsFramebufferEXT, NULL, _gloffset_IsFramebufferEXT),
- NAME_FUNC_OFFSET(13310, glIsRenderbufferEXT, glIsRenderbufferEXT, NULL, _gloffset_IsRenderbufferEXT),
- NAME_FUNC_OFFSET(13330, glRenderbufferStorageEXT, glRenderbufferStorageEXT, NULL, _gloffset_RenderbufferStorageEXT),
- NAME_FUNC_OFFSET(13355, gl_dispatch_stub_763, gl_dispatch_stub_763, NULL, _gloffset_BlitFramebufferEXT),
- NAME_FUNC_OFFSET(13376, glFramebufferTextureLayerEXT, glFramebufferTextureLayerEXT, NULL, _gloffset_FramebufferTextureLayerEXT),
- NAME_FUNC_OFFSET(13405, gl_dispatch_stub_765, gl_dispatch_stub_765, NULL, _gloffset_StencilFuncSeparateATI),
- NAME_FUNC_OFFSET(13430, gl_dispatch_stub_766, gl_dispatch_stub_766, NULL, _gloffset_ProgramEnvParameters4fvEXT),
- NAME_FUNC_OFFSET(13459, gl_dispatch_stub_767, gl_dispatch_stub_767, NULL, _gloffset_ProgramLocalParameters4fvEXT),
- NAME_FUNC_OFFSET(13490, gl_dispatch_stub_768, gl_dispatch_stub_768, NULL, _gloffset_GetQueryObjecti64vEXT),
- NAME_FUNC_OFFSET(13514, gl_dispatch_stub_769, gl_dispatch_stub_769, NULL, _gloffset_GetQueryObjectui64vEXT),
- NAME_FUNC_OFFSET(13539, glArrayElement, glArrayElement, NULL, _gloffset_ArrayElement),
- NAME_FUNC_OFFSET(13557, glBindTexture, glBindTexture, NULL, _gloffset_BindTexture),
- NAME_FUNC_OFFSET(13574, glDrawArrays, glDrawArrays, NULL, _gloffset_DrawArrays),
- NAME_FUNC_OFFSET(13590, glAreTexturesResident, glAreTexturesResidentEXT, glAreTexturesResidentEXT, _gloffset_AreTexturesResident),
- NAME_FUNC_OFFSET(13615, glCopyTexImage1D, glCopyTexImage1D, NULL, _gloffset_CopyTexImage1D),
- NAME_FUNC_OFFSET(13635, glCopyTexImage2D, glCopyTexImage2D, NULL, _gloffset_CopyTexImage2D),
- NAME_FUNC_OFFSET(13655, glCopyTexSubImage1D, glCopyTexSubImage1D, NULL, _gloffset_CopyTexSubImage1D),
- NAME_FUNC_OFFSET(13678, glCopyTexSubImage2D, glCopyTexSubImage2D, NULL, _gloffset_CopyTexSubImage2D),
- NAME_FUNC_OFFSET(13701, glDeleteTextures, glDeleteTexturesEXT, glDeleteTexturesEXT, _gloffset_DeleteTextures),
- NAME_FUNC_OFFSET(13721, glGenTextures, glGenTexturesEXT, glGenTexturesEXT, _gloffset_GenTextures),
- NAME_FUNC_OFFSET(13738, glGetPointerv, glGetPointerv, NULL, _gloffset_GetPointerv),
- NAME_FUNC_OFFSET(13755, glIsTexture, glIsTextureEXT, glIsTextureEXT, _gloffset_IsTexture),
- NAME_FUNC_OFFSET(13770, glPrioritizeTextures, glPrioritizeTextures, NULL, _gloffset_PrioritizeTextures),
- NAME_FUNC_OFFSET(13794, glTexSubImage1D, glTexSubImage1D, NULL, _gloffset_TexSubImage1D),
- NAME_FUNC_OFFSET(13813, glTexSubImage2D, glTexSubImage2D, NULL, _gloffset_TexSubImage2D),
- NAME_FUNC_OFFSET(13832, glBlendColor, glBlendColor, NULL, _gloffset_BlendColor),
- NAME_FUNC_OFFSET(13848, glBlendEquation, glBlendEquation, NULL, _gloffset_BlendEquation),
- NAME_FUNC_OFFSET(13867, glDrawRangeElements, glDrawRangeElements, NULL, _gloffset_DrawRangeElements),
- NAME_FUNC_OFFSET(13890, glColorTable, glColorTable, NULL, _gloffset_ColorTable),
- NAME_FUNC_OFFSET(13906, glColorTable, glColorTable, NULL, _gloffset_ColorTable),
- NAME_FUNC_OFFSET(13922, glColorTableParameterfv, glColorTableParameterfv, NULL, _gloffset_ColorTableParameterfv),
- NAME_FUNC_OFFSET(13949, glColorTableParameteriv, glColorTableParameteriv, NULL, _gloffset_ColorTableParameteriv),
- NAME_FUNC_OFFSET(13976, glCopyColorTable, glCopyColorTable, NULL, _gloffset_CopyColorTable),
- NAME_FUNC_OFFSET(13996, glGetColorTable, glGetColorTableEXT, glGetColorTableEXT, _gloffset_GetColorTable),
- NAME_FUNC_OFFSET(14015, glGetColorTable, glGetColorTableEXT, glGetColorTableEXT, _gloffset_GetColorTable),
- NAME_FUNC_OFFSET(14034, glGetColorTableParameterfv, glGetColorTableParameterfvEXT, glGetColorTableParameterfvEXT, _gloffset_GetColorTableParameterfv),
- NAME_FUNC_OFFSET(14064, glGetColorTableParameterfv, glGetColorTableParameterfvEXT, glGetColorTableParameterfvEXT, _gloffset_GetColorTableParameterfv),
- NAME_FUNC_OFFSET(14094, glGetColorTableParameteriv, glGetColorTableParameterivEXT, glGetColorTableParameterivEXT, _gloffset_GetColorTableParameteriv),
- NAME_FUNC_OFFSET(14124, glGetColorTableParameteriv, glGetColorTableParameterivEXT, glGetColorTableParameterivEXT, _gloffset_GetColorTableParameteriv),
- NAME_FUNC_OFFSET(14154, glColorSubTable, glColorSubTable, NULL, _gloffset_ColorSubTable),
- NAME_FUNC_OFFSET(14173, glCopyColorSubTable, glCopyColorSubTable, NULL, _gloffset_CopyColorSubTable),
- NAME_FUNC_OFFSET(14196, glConvolutionFilter1D, glConvolutionFilter1D, NULL, _gloffset_ConvolutionFilter1D),
- NAME_FUNC_OFFSET(14221, glConvolutionFilter2D, glConvolutionFilter2D, NULL, _gloffset_ConvolutionFilter2D),
- NAME_FUNC_OFFSET(14246, glConvolutionParameterf, glConvolutionParameterf, NULL, _gloffset_ConvolutionParameterf),
- NAME_FUNC_OFFSET(14273, glConvolutionParameterfv, glConvolutionParameterfv, NULL, _gloffset_ConvolutionParameterfv),
- NAME_FUNC_OFFSET(14301, glConvolutionParameteri, glConvolutionParameteri, NULL, _gloffset_ConvolutionParameteri),
- NAME_FUNC_OFFSET(14328, glConvolutionParameteriv, glConvolutionParameteriv, NULL, _gloffset_ConvolutionParameteriv),
- NAME_FUNC_OFFSET(14356, glCopyConvolutionFilter1D, glCopyConvolutionFilter1D, NULL, _gloffset_CopyConvolutionFilter1D),
- NAME_FUNC_OFFSET(14385, glCopyConvolutionFilter2D, glCopyConvolutionFilter2D, NULL, _gloffset_CopyConvolutionFilter2D),
- NAME_FUNC_OFFSET(14414, glGetConvolutionFilter, gl_dispatch_stub_356, gl_dispatch_stub_356, _gloffset_GetConvolutionFilter),
- NAME_FUNC_OFFSET(14440, glGetConvolutionParameterfv, gl_dispatch_stub_357, gl_dispatch_stub_357, _gloffset_GetConvolutionParameterfv),
- NAME_FUNC_OFFSET(14471, glGetConvolutionParameteriv, gl_dispatch_stub_358, gl_dispatch_stub_358, _gloffset_GetConvolutionParameteriv),
- NAME_FUNC_OFFSET(14502, glGetSeparableFilter, gl_dispatch_stub_359, gl_dispatch_stub_359, _gloffset_GetSeparableFilter),
- NAME_FUNC_OFFSET(14526, glSeparableFilter2D, glSeparableFilter2D, NULL, _gloffset_SeparableFilter2D),
- NAME_FUNC_OFFSET(14549, glGetHistogram, gl_dispatch_stub_361, gl_dispatch_stub_361, _gloffset_GetHistogram),
- NAME_FUNC_OFFSET(14567, glGetHistogramParameterfv, gl_dispatch_stub_362, gl_dispatch_stub_362, _gloffset_GetHistogramParameterfv),
- NAME_FUNC_OFFSET(14596, glGetHistogramParameteriv, gl_dispatch_stub_363, gl_dispatch_stub_363, _gloffset_GetHistogramParameteriv),
- NAME_FUNC_OFFSET(14625, glGetMinmax, gl_dispatch_stub_364, gl_dispatch_stub_364, _gloffset_GetMinmax),
- NAME_FUNC_OFFSET(14640, glGetMinmaxParameterfv, gl_dispatch_stub_365, gl_dispatch_stub_365, _gloffset_GetMinmaxParameterfv),
- NAME_FUNC_OFFSET(14666, glGetMinmaxParameteriv, gl_dispatch_stub_366, gl_dispatch_stub_366, _gloffset_GetMinmaxParameteriv),
- NAME_FUNC_OFFSET(14692, glHistogram, glHistogram, NULL, _gloffset_Histogram),
- NAME_FUNC_OFFSET(14707, glMinmax, glMinmax, NULL, _gloffset_Minmax),
- NAME_FUNC_OFFSET(14719, glResetHistogram, glResetHistogram, NULL, _gloffset_ResetHistogram),
- NAME_FUNC_OFFSET(14739, glResetMinmax, glResetMinmax, NULL, _gloffset_ResetMinmax),
- NAME_FUNC_OFFSET(14756, glTexImage3D, glTexImage3D, NULL, _gloffset_TexImage3D),
- NAME_FUNC_OFFSET(14772, glTexSubImage3D, glTexSubImage3D, NULL, _gloffset_TexSubImage3D),
- NAME_FUNC_OFFSET(14791, glCopyTexSubImage3D, glCopyTexSubImage3D, NULL, _gloffset_CopyTexSubImage3D),
- NAME_FUNC_OFFSET(14814, glActiveTextureARB, glActiveTextureARB, NULL, _gloffset_ActiveTextureARB),
- NAME_FUNC_OFFSET(14830, glClientActiveTextureARB, glClientActiveTextureARB, NULL, _gloffset_ClientActiveTextureARB),
- NAME_FUNC_OFFSET(14852, glMultiTexCoord1dARB, glMultiTexCoord1dARB, NULL, _gloffset_MultiTexCoord1dARB),
- NAME_FUNC_OFFSET(14870, glMultiTexCoord1dvARB, glMultiTexCoord1dvARB, NULL, _gloffset_MultiTexCoord1dvARB),
- NAME_FUNC_OFFSET(14889, glMultiTexCoord1fARB, glMultiTexCoord1fARB, NULL, _gloffset_MultiTexCoord1fARB),
- NAME_FUNC_OFFSET(14907, glMultiTexCoord1fvARB, glMultiTexCoord1fvARB, NULL, _gloffset_MultiTexCoord1fvARB),
- NAME_FUNC_OFFSET(14926, glMultiTexCoord1iARB, glMultiTexCoord1iARB, NULL, _gloffset_MultiTexCoord1iARB),
- NAME_FUNC_OFFSET(14944, glMultiTexCoord1ivARB, glMultiTexCoord1ivARB, NULL, _gloffset_MultiTexCoord1ivARB),
- NAME_FUNC_OFFSET(14963, glMultiTexCoord1sARB, glMultiTexCoord1sARB, NULL, _gloffset_MultiTexCoord1sARB),
- NAME_FUNC_OFFSET(14981, glMultiTexCoord1svARB, glMultiTexCoord1svARB, NULL, _gloffset_MultiTexCoord1svARB),
- NAME_FUNC_OFFSET(15000, glMultiTexCoord2dARB, glMultiTexCoord2dARB, NULL, _gloffset_MultiTexCoord2dARB),
- NAME_FUNC_OFFSET(15018, glMultiTexCoord2dvARB, glMultiTexCoord2dvARB, NULL, _gloffset_MultiTexCoord2dvARB),
- NAME_FUNC_OFFSET(15037, glMultiTexCoord2fARB, glMultiTexCoord2fARB, NULL, _gloffset_MultiTexCoord2fARB),
- NAME_FUNC_OFFSET(15055, glMultiTexCoord2fvARB, glMultiTexCoord2fvARB, NULL, _gloffset_MultiTexCoord2fvARB),
- NAME_FUNC_OFFSET(15074, glMultiTexCoord2iARB, glMultiTexCoord2iARB, NULL, _gloffset_MultiTexCoord2iARB),
- NAME_FUNC_OFFSET(15092, glMultiTexCoord2ivARB, glMultiTexCoord2ivARB, NULL, _gloffset_MultiTexCoord2ivARB),
- NAME_FUNC_OFFSET(15111, glMultiTexCoord2sARB, glMultiTexCoord2sARB, NULL, _gloffset_MultiTexCoord2sARB),
- NAME_FUNC_OFFSET(15129, glMultiTexCoord2svARB, glMultiTexCoord2svARB, NULL, _gloffset_MultiTexCoord2svARB),
- NAME_FUNC_OFFSET(15148, glMultiTexCoord3dARB, glMultiTexCoord3dARB, NULL, _gloffset_MultiTexCoord3dARB),
- NAME_FUNC_OFFSET(15166, glMultiTexCoord3dvARB, glMultiTexCoord3dvARB, NULL, _gloffset_MultiTexCoord3dvARB),
- NAME_FUNC_OFFSET(15185, glMultiTexCoord3fARB, glMultiTexCoord3fARB, NULL, _gloffset_MultiTexCoord3fARB),
- NAME_FUNC_OFFSET(15203, glMultiTexCoord3fvARB, glMultiTexCoord3fvARB, NULL, _gloffset_MultiTexCoord3fvARB),
- NAME_FUNC_OFFSET(15222, glMultiTexCoord3iARB, glMultiTexCoord3iARB, NULL, _gloffset_MultiTexCoord3iARB),
- NAME_FUNC_OFFSET(15240, glMultiTexCoord3ivARB, glMultiTexCoord3ivARB, NULL, _gloffset_MultiTexCoord3ivARB),
- NAME_FUNC_OFFSET(15259, glMultiTexCoord3sARB, glMultiTexCoord3sARB, NULL, _gloffset_MultiTexCoord3sARB),
- NAME_FUNC_OFFSET(15277, glMultiTexCoord3svARB, glMultiTexCoord3svARB, NULL, _gloffset_MultiTexCoord3svARB),
- NAME_FUNC_OFFSET(15296, glMultiTexCoord4dARB, glMultiTexCoord4dARB, NULL, _gloffset_MultiTexCoord4dARB),
- NAME_FUNC_OFFSET(15314, glMultiTexCoord4dvARB, glMultiTexCoord4dvARB, NULL, _gloffset_MultiTexCoord4dvARB),
- NAME_FUNC_OFFSET(15333, glMultiTexCoord4fARB, glMultiTexCoord4fARB, NULL, _gloffset_MultiTexCoord4fARB),
- NAME_FUNC_OFFSET(15351, glMultiTexCoord4fvARB, glMultiTexCoord4fvARB, NULL, _gloffset_MultiTexCoord4fvARB),
- NAME_FUNC_OFFSET(15370, glMultiTexCoord4iARB, glMultiTexCoord4iARB, NULL, _gloffset_MultiTexCoord4iARB),
- NAME_FUNC_OFFSET(15388, glMultiTexCoord4ivARB, glMultiTexCoord4ivARB, NULL, _gloffset_MultiTexCoord4ivARB),
- NAME_FUNC_OFFSET(15407, glMultiTexCoord4sARB, glMultiTexCoord4sARB, NULL, _gloffset_MultiTexCoord4sARB),
- NAME_FUNC_OFFSET(15425, glMultiTexCoord4svARB, glMultiTexCoord4svARB, NULL, _gloffset_MultiTexCoord4svARB),
- NAME_FUNC_OFFSET(15444, glStencilOpSeparate, glStencilOpSeparate, NULL, _gloffset_StencilOpSeparate),
- NAME_FUNC_OFFSET(15467, glLoadTransposeMatrixdARB, glLoadTransposeMatrixdARB, NULL, _gloffset_LoadTransposeMatrixdARB),
- NAME_FUNC_OFFSET(15490, glLoadTransposeMatrixfARB, glLoadTransposeMatrixfARB, NULL, _gloffset_LoadTransposeMatrixfARB),
- NAME_FUNC_OFFSET(15513, glMultTransposeMatrixdARB, glMultTransposeMatrixdARB, NULL, _gloffset_MultTransposeMatrixdARB),
- NAME_FUNC_OFFSET(15536, glMultTransposeMatrixfARB, glMultTransposeMatrixfARB, NULL, _gloffset_MultTransposeMatrixfARB),
- NAME_FUNC_OFFSET(15559, glSampleCoverageARB, glSampleCoverageARB, NULL, _gloffset_SampleCoverageARB),
- NAME_FUNC_OFFSET(15576, glCompressedTexImage1DARB, glCompressedTexImage1DARB, NULL, _gloffset_CompressedTexImage1DARB),
- NAME_FUNC_OFFSET(15599, glCompressedTexImage2DARB, glCompressedTexImage2DARB, NULL, _gloffset_CompressedTexImage2DARB),
- NAME_FUNC_OFFSET(15622, glCompressedTexImage3DARB, glCompressedTexImage3DARB, NULL, _gloffset_CompressedTexImage3DARB),
- NAME_FUNC_OFFSET(15645, glCompressedTexSubImage1DARB, glCompressedTexSubImage1DARB, NULL, _gloffset_CompressedTexSubImage1DARB),
- NAME_FUNC_OFFSET(15671, glCompressedTexSubImage2DARB, glCompressedTexSubImage2DARB, NULL, _gloffset_CompressedTexSubImage2DARB),
- NAME_FUNC_OFFSET(15697, glCompressedTexSubImage3DARB, glCompressedTexSubImage3DARB, NULL, _gloffset_CompressedTexSubImage3DARB),
- NAME_FUNC_OFFSET(15723, glGetCompressedTexImageARB, glGetCompressedTexImageARB, NULL, _gloffset_GetCompressedTexImageARB),
- NAME_FUNC_OFFSET(15747, glDisableVertexAttribArrayARB, glDisableVertexAttribArrayARB, NULL, _gloffset_DisableVertexAttribArrayARB),
- NAME_FUNC_OFFSET(15774, glEnableVertexAttribArrayARB, glEnableVertexAttribArrayARB, NULL, _gloffset_EnableVertexAttribArrayARB),
- NAME_FUNC_OFFSET(15800, glGetVertexAttribdvARB, glGetVertexAttribdvARB, NULL, _gloffset_GetVertexAttribdvARB),
- NAME_FUNC_OFFSET(15820, glGetVertexAttribfvARB, glGetVertexAttribfvARB, NULL, _gloffset_GetVertexAttribfvARB),
- NAME_FUNC_OFFSET(15840, glGetVertexAttribivARB, glGetVertexAttribivARB, NULL, _gloffset_GetVertexAttribivARB),
- NAME_FUNC_OFFSET(15860, glProgramEnvParameter4dARB, glProgramEnvParameter4dARB, NULL, _gloffset_ProgramEnvParameter4dARB),
- NAME_FUNC_OFFSET(15883, glProgramEnvParameter4dvARB, glProgramEnvParameter4dvARB, NULL, _gloffset_ProgramEnvParameter4dvARB),
- NAME_FUNC_OFFSET(15907, glProgramEnvParameter4fARB, glProgramEnvParameter4fARB, NULL, _gloffset_ProgramEnvParameter4fARB),
- NAME_FUNC_OFFSET(15930, glProgramEnvParameter4fvARB, glProgramEnvParameter4fvARB, NULL, _gloffset_ProgramEnvParameter4fvARB),
- NAME_FUNC_OFFSET(15954, glVertexAttrib1dARB, glVertexAttrib1dARB, NULL, _gloffset_VertexAttrib1dARB),
- NAME_FUNC_OFFSET(15971, glVertexAttrib1dvARB, glVertexAttrib1dvARB, NULL, _gloffset_VertexAttrib1dvARB),
- NAME_FUNC_OFFSET(15989, glVertexAttrib1fARB, glVertexAttrib1fARB, NULL, _gloffset_VertexAttrib1fARB),
- NAME_FUNC_OFFSET(16006, glVertexAttrib1fvARB, glVertexAttrib1fvARB, NULL, _gloffset_VertexAttrib1fvARB),
- NAME_FUNC_OFFSET(16024, glVertexAttrib1sARB, glVertexAttrib1sARB, NULL, _gloffset_VertexAttrib1sARB),
- NAME_FUNC_OFFSET(16041, glVertexAttrib1svARB, glVertexAttrib1svARB, NULL, _gloffset_VertexAttrib1svARB),
- NAME_FUNC_OFFSET(16059, glVertexAttrib2dARB, glVertexAttrib2dARB, NULL, _gloffset_VertexAttrib2dARB),
- NAME_FUNC_OFFSET(16076, glVertexAttrib2dvARB, glVertexAttrib2dvARB, NULL, _gloffset_VertexAttrib2dvARB),
- NAME_FUNC_OFFSET(16094, glVertexAttrib2fARB, glVertexAttrib2fARB, NULL, _gloffset_VertexAttrib2fARB),
- NAME_FUNC_OFFSET(16111, glVertexAttrib2fvARB, glVertexAttrib2fvARB, NULL, _gloffset_VertexAttrib2fvARB),
- NAME_FUNC_OFFSET(16129, glVertexAttrib2sARB, glVertexAttrib2sARB, NULL, _gloffset_VertexAttrib2sARB),
- NAME_FUNC_OFFSET(16146, glVertexAttrib2svARB, glVertexAttrib2svARB, NULL, _gloffset_VertexAttrib2svARB),
- NAME_FUNC_OFFSET(16164, glVertexAttrib3dARB, glVertexAttrib3dARB, NULL, _gloffset_VertexAttrib3dARB),
- NAME_FUNC_OFFSET(16181, glVertexAttrib3dvARB, glVertexAttrib3dvARB, NULL, _gloffset_VertexAttrib3dvARB),
- NAME_FUNC_OFFSET(16199, glVertexAttrib3fARB, glVertexAttrib3fARB, NULL, _gloffset_VertexAttrib3fARB),
- NAME_FUNC_OFFSET(16216, glVertexAttrib3fvARB, glVertexAttrib3fvARB, NULL, _gloffset_VertexAttrib3fvARB),
- NAME_FUNC_OFFSET(16234, glVertexAttrib3sARB, glVertexAttrib3sARB, NULL, _gloffset_VertexAttrib3sARB),
- NAME_FUNC_OFFSET(16251, glVertexAttrib3svARB, glVertexAttrib3svARB, NULL, _gloffset_VertexAttrib3svARB),
- NAME_FUNC_OFFSET(16269, glVertexAttrib4NbvARB, glVertexAttrib4NbvARB, NULL, _gloffset_VertexAttrib4NbvARB),
- NAME_FUNC_OFFSET(16288, glVertexAttrib4NivARB, glVertexAttrib4NivARB, NULL, _gloffset_VertexAttrib4NivARB),
- NAME_FUNC_OFFSET(16307, glVertexAttrib4NsvARB, glVertexAttrib4NsvARB, NULL, _gloffset_VertexAttrib4NsvARB),
- NAME_FUNC_OFFSET(16326, glVertexAttrib4NubARB, glVertexAttrib4NubARB, NULL, _gloffset_VertexAttrib4NubARB),
- NAME_FUNC_OFFSET(16345, glVertexAttrib4NubvARB, glVertexAttrib4NubvARB, NULL, _gloffset_VertexAttrib4NubvARB),
- NAME_FUNC_OFFSET(16365, glVertexAttrib4NuivARB, glVertexAttrib4NuivARB, NULL, _gloffset_VertexAttrib4NuivARB),
- NAME_FUNC_OFFSET(16385, glVertexAttrib4NusvARB, glVertexAttrib4NusvARB, NULL, _gloffset_VertexAttrib4NusvARB),
- NAME_FUNC_OFFSET(16405, glVertexAttrib4bvARB, glVertexAttrib4bvARB, NULL, _gloffset_VertexAttrib4bvARB),
- NAME_FUNC_OFFSET(16423, glVertexAttrib4dARB, glVertexAttrib4dARB, NULL, _gloffset_VertexAttrib4dARB),
- NAME_FUNC_OFFSET(16440, glVertexAttrib4dvARB, glVertexAttrib4dvARB, NULL, _gloffset_VertexAttrib4dvARB),
- NAME_FUNC_OFFSET(16458, glVertexAttrib4fARB, glVertexAttrib4fARB, NULL, _gloffset_VertexAttrib4fARB),
- NAME_FUNC_OFFSET(16475, glVertexAttrib4fvARB, glVertexAttrib4fvARB, NULL, _gloffset_VertexAttrib4fvARB),
- NAME_FUNC_OFFSET(16493, glVertexAttrib4ivARB, glVertexAttrib4ivARB, NULL, _gloffset_VertexAttrib4ivARB),
- NAME_FUNC_OFFSET(16511, glVertexAttrib4sARB, glVertexAttrib4sARB, NULL, _gloffset_VertexAttrib4sARB),
- NAME_FUNC_OFFSET(16528, glVertexAttrib4svARB, glVertexAttrib4svARB, NULL, _gloffset_VertexAttrib4svARB),
- NAME_FUNC_OFFSET(16546, glVertexAttrib4ubvARB, glVertexAttrib4ubvARB, NULL, _gloffset_VertexAttrib4ubvARB),
- NAME_FUNC_OFFSET(16565, glVertexAttrib4uivARB, glVertexAttrib4uivARB, NULL, _gloffset_VertexAttrib4uivARB),
- NAME_FUNC_OFFSET(16584, glVertexAttrib4usvARB, glVertexAttrib4usvARB, NULL, _gloffset_VertexAttrib4usvARB),
- NAME_FUNC_OFFSET(16603, glVertexAttribPointerARB, glVertexAttribPointerARB, NULL, _gloffset_VertexAttribPointerARB),
- NAME_FUNC_OFFSET(16625, glBindBufferARB, glBindBufferARB, NULL, _gloffset_BindBufferARB),
- NAME_FUNC_OFFSET(16638, glBufferDataARB, glBufferDataARB, NULL, _gloffset_BufferDataARB),
- NAME_FUNC_OFFSET(16651, glBufferSubDataARB, glBufferSubDataARB, NULL, _gloffset_BufferSubDataARB),
- NAME_FUNC_OFFSET(16667, glDeleteBuffersARB, glDeleteBuffersARB, NULL, _gloffset_DeleteBuffersARB),
- NAME_FUNC_OFFSET(16683, glGenBuffersARB, glGenBuffersARB, NULL, _gloffset_GenBuffersARB),
- NAME_FUNC_OFFSET(16696, glGetBufferParameterivARB, glGetBufferParameterivARB, NULL, _gloffset_GetBufferParameterivARB),
- NAME_FUNC_OFFSET(16719, glGetBufferPointervARB, glGetBufferPointervARB, NULL, _gloffset_GetBufferPointervARB),
- NAME_FUNC_OFFSET(16739, glGetBufferSubDataARB, glGetBufferSubDataARB, NULL, _gloffset_GetBufferSubDataARB),
- NAME_FUNC_OFFSET(16758, glIsBufferARB, glIsBufferARB, NULL, _gloffset_IsBufferARB),
- NAME_FUNC_OFFSET(16769, glMapBufferARB, glMapBufferARB, NULL, _gloffset_MapBufferARB),
- NAME_FUNC_OFFSET(16781, glUnmapBufferARB, glUnmapBufferARB, NULL, _gloffset_UnmapBufferARB),
- NAME_FUNC_OFFSET(16795, glBeginQueryARB, glBeginQueryARB, NULL, _gloffset_BeginQueryARB),
- NAME_FUNC_OFFSET(16808, glDeleteQueriesARB, glDeleteQueriesARB, NULL, _gloffset_DeleteQueriesARB),
- NAME_FUNC_OFFSET(16824, glEndQueryARB, glEndQueryARB, NULL, _gloffset_EndQueryARB),
- NAME_FUNC_OFFSET(16835, glGenQueriesARB, glGenQueriesARB, NULL, _gloffset_GenQueriesARB),
- NAME_FUNC_OFFSET(16848, glGetQueryObjectivARB, glGetQueryObjectivARB, NULL, _gloffset_GetQueryObjectivARB),
- NAME_FUNC_OFFSET(16867, glGetQueryObjectuivARB, glGetQueryObjectuivARB, NULL, _gloffset_GetQueryObjectuivARB),
- NAME_FUNC_OFFSET(16887, glGetQueryivARB, glGetQueryivARB, NULL, _gloffset_GetQueryivARB),
- NAME_FUNC_OFFSET(16900, glIsQueryARB, glIsQueryARB, NULL, _gloffset_IsQueryARB),
- NAME_FUNC_OFFSET(16910, glCompileShaderARB, glCompileShaderARB, NULL, _gloffset_CompileShaderARB),
- NAME_FUNC_OFFSET(16926, glGetActiveUniformARB, glGetActiveUniformARB, NULL, _gloffset_GetActiveUniformARB),
- NAME_FUNC_OFFSET(16945, glGetShaderSourceARB, glGetShaderSourceARB, NULL, _gloffset_GetShaderSourceARB),
- NAME_FUNC_OFFSET(16963, glGetUniformLocationARB, glGetUniformLocationARB, NULL, _gloffset_GetUniformLocationARB),
- NAME_FUNC_OFFSET(16984, glGetUniformfvARB, glGetUniformfvARB, NULL, _gloffset_GetUniformfvARB),
- NAME_FUNC_OFFSET(16999, glGetUniformivARB, glGetUniformivARB, NULL, _gloffset_GetUniformivARB),
- NAME_FUNC_OFFSET(17014, glLinkProgramARB, glLinkProgramARB, NULL, _gloffset_LinkProgramARB),
- NAME_FUNC_OFFSET(17028, glShaderSourceARB, glShaderSourceARB, NULL, _gloffset_ShaderSourceARB),
- NAME_FUNC_OFFSET(17043, glUniform1fARB, glUniform1fARB, NULL, _gloffset_Uniform1fARB),
- NAME_FUNC_OFFSET(17055, glUniform1fvARB, glUniform1fvARB, NULL, _gloffset_Uniform1fvARB),
- NAME_FUNC_OFFSET(17068, glUniform1iARB, glUniform1iARB, NULL, _gloffset_Uniform1iARB),
- NAME_FUNC_OFFSET(17080, glUniform1ivARB, glUniform1ivARB, NULL, _gloffset_Uniform1ivARB),
- NAME_FUNC_OFFSET(17093, glUniform2fARB, glUniform2fARB, NULL, _gloffset_Uniform2fARB),
- NAME_FUNC_OFFSET(17105, glUniform2fvARB, glUniform2fvARB, NULL, _gloffset_Uniform2fvARB),
- NAME_FUNC_OFFSET(17118, glUniform2iARB, glUniform2iARB, NULL, _gloffset_Uniform2iARB),
- NAME_FUNC_OFFSET(17130, glUniform2ivARB, glUniform2ivARB, NULL, _gloffset_Uniform2ivARB),
- NAME_FUNC_OFFSET(17143, glUniform3fARB, glUniform3fARB, NULL, _gloffset_Uniform3fARB),
- NAME_FUNC_OFFSET(17155, glUniform3fvARB, glUniform3fvARB, NULL, _gloffset_Uniform3fvARB),
- NAME_FUNC_OFFSET(17168, glUniform3iARB, glUniform3iARB, NULL, _gloffset_Uniform3iARB),
- NAME_FUNC_OFFSET(17180, glUniform3ivARB, glUniform3ivARB, NULL, _gloffset_Uniform3ivARB),
- NAME_FUNC_OFFSET(17193, glUniform4fARB, glUniform4fARB, NULL, _gloffset_Uniform4fARB),
- NAME_FUNC_OFFSET(17205, glUniform4fvARB, glUniform4fvARB, NULL, _gloffset_Uniform4fvARB),
- NAME_FUNC_OFFSET(17218, glUniform4iARB, glUniform4iARB, NULL, _gloffset_Uniform4iARB),
- NAME_FUNC_OFFSET(17230, glUniform4ivARB, glUniform4ivARB, NULL, _gloffset_Uniform4ivARB),
- NAME_FUNC_OFFSET(17243, glUniformMatrix2fvARB, glUniformMatrix2fvARB, NULL, _gloffset_UniformMatrix2fvARB),
- NAME_FUNC_OFFSET(17262, glUniformMatrix3fvARB, glUniformMatrix3fvARB, NULL, _gloffset_UniformMatrix3fvARB),
- NAME_FUNC_OFFSET(17281, glUniformMatrix4fvARB, glUniformMatrix4fvARB, NULL, _gloffset_UniformMatrix4fvARB),
- NAME_FUNC_OFFSET(17300, glUseProgramObjectARB, glUseProgramObjectARB, NULL, _gloffset_UseProgramObjectARB),
- NAME_FUNC_OFFSET(17313, glValidateProgramARB, glValidateProgramARB, NULL, _gloffset_ValidateProgramARB),
- NAME_FUNC_OFFSET(17331, glBindAttribLocationARB, glBindAttribLocationARB, NULL, _gloffset_BindAttribLocationARB),
- NAME_FUNC_OFFSET(17352, glGetActiveAttribARB, glGetActiveAttribARB, NULL, _gloffset_GetActiveAttribARB),
- NAME_FUNC_OFFSET(17370, glGetAttribLocationARB, glGetAttribLocationARB, NULL, _gloffset_GetAttribLocationARB),
- NAME_FUNC_OFFSET(17390, glDrawBuffersARB, glDrawBuffersARB, NULL, _gloffset_DrawBuffersARB),
- NAME_FUNC_OFFSET(17404, glDrawBuffersARB, glDrawBuffersARB, NULL, _gloffset_DrawBuffersARB),
- NAME_FUNC_OFFSET(17421, gl_dispatch_stub_568, gl_dispatch_stub_568, NULL, _gloffset_SampleMaskSGIS),
- NAME_FUNC_OFFSET(17437, gl_dispatch_stub_569, gl_dispatch_stub_569, NULL, _gloffset_SamplePatternSGIS),
- NAME_FUNC_OFFSET(17456, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
- NAME_FUNC_OFFSET(17474, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
- NAME_FUNC_OFFSET(17495, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
- NAME_FUNC_OFFSET(17517, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
- NAME_FUNC_OFFSET(17536, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
- NAME_FUNC_OFFSET(17558, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
- NAME_FUNC_OFFSET(17581, glSecondaryColor3bEXT, glSecondaryColor3bEXT, NULL, _gloffset_SecondaryColor3bEXT),
- NAME_FUNC_OFFSET(17600, glSecondaryColor3bvEXT, glSecondaryColor3bvEXT, NULL, _gloffset_SecondaryColor3bvEXT),
- NAME_FUNC_OFFSET(17620, glSecondaryColor3dEXT, glSecondaryColor3dEXT, NULL, _gloffset_SecondaryColor3dEXT),
- NAME_FUNC_OFFSET(17639, glSecondaryColor3dvEXT, glSecondaryColor3dvEXT, NULL, _gloffset_SecondaryColor3dvEXT),
- NAME_FUNC_OFFSET(17659, glSecondaryColor3fEXT, glSecondaryColor3fEXT, NULL, _gloffset_SecondaryColor3fEXT),
- NAME_FUNC_OFFSET(17678, glSecondaryColor3fvEXT, glSecondaryColor3fvEXT, NULL, _gloffset_SecondaryColor3fvEXT),
- NAME_FUNC_OFFSET(17698, glSecondaryColor3iEXT, glSecondaryColor3iEXT, NULL, _gloffset_SecondaryColor3iEXT),
- NAME_FUNC_OFFSET(17717, glSecondaryColor3ivEXT, glSecondaryColor3ivEXT, NULL, _gloffset_SecondaryColor3ivEXT),
- NAME_FUNC_OFFSET(17737, glSecondaryColor3sEXT, glSecondaryColor3sEXT, NULL, _gloffset_SecondaryColor3sEXT),
- NAME_FUNC_OFFSET(17756, glSecondaryColor3svEXT, glSecondaryColor3svEXT, NULL, _gloffset_SecondaryColor3svEXT),
- NAME_FUNC_OFFSET(17776, glSecondaryColor3ubEXT, glSecondaryColor3ubEXT, NULL, _gloffset_SecondaryColor3ubEXT),
- NAME_FUNC_OFFSET(17796, glSecondaryColor3ubvEXT, glSecondaryColor3ubvEXT, NULL, _gloffset_SecondaryColor3ubvEXT),
- NAME_FUNC_OFFSET(17817, glSecondaryColor3uiEXT, glSecondaryColor3uiEXT, NULL, _gloffset_SecondaryColor3uiEXT),
- NAME_FUNC_OFFSET(17837, glSecondaryColor3uivEXT, glSecondaryColor3uivEXT, NULL, _gloffset_SecondaryColor3uivEXT),
- NAME_FUNC_OFFSET(17858, glSecondaryColor3usEXT, glSecondaryColor3usEXT, NULL, _gloffset_SecondaryColor3usEXT),
- NAME_FUNC_OFFSET(17878, glSecondaryColor3usvEXT, glSecondaryColor3usvEXT, NULL, _gloffset_SecondaryColor3usvEXT),
- NAME_FUNC_OFFSET(17899, glSecondaryColorPointerEXT, glSecondaryColorPointerEXT, NULL, _gloffset_SecondaryColorPointerEXT),
- NAME_FUNC_OFFSET(17923, glMultiDrawArraysEXT, glMultiDrawArraysEXT, NULL, _gloffset_MultiDrawArraysEXT),
- NAME_FUNC_OFFSET(17941, glMultiDrawElementsEXT, glMultiDrawElementsEXT, NULL, _gloffset_MultiDrawElementsEXT),
- NAME_FUNC_OFFSET(17961, glFogCoordPointerEXT, glFogCoordPointerEXT, NULL, _gloffset_FogCoordPointerEXT),
- NAME_FUNC_OFFSET(17979, glFogCoorddEXT, glFogCoorddEXT, NULL, _gloffset_FogCoorddEXT),
- NAME_FUNC_OFFSET(17991, glFogCoorddvEXT, glFogCoorddvEXT, NULL, _gloffset_FogCoorddvEXT),
- NAME_FUNC_OFFSET(18004, glFogCoordfEXT, glFogCoordfEXT, NULL, _gloffset_FogCoordfEXT),
- NAME_FUNC_OFFSET(18016, glFogCoordfvEXT, glFogCoordfvEXT, NULL, _gloffset_FogCoordfvEXT),
- NAME_FUNC_OFFSET(18029, glBlendFuncSeparateEXT, glBlendFuncSeparateEXT, NULL, _gloffset_BlendFuncSeparateEXT),
- NAME_FUNC_OFFSET(18049, glBlendFuncSeparateEXT, glBlendFuncSeparateEXT, NULL, _gloffset_BlendFuncSeparateEXT),
- NAME_FUNC_OFFSET(18073, glWindowPos2dMESA, glWindowPos2dMESA, NULL, _gloffset_WindowPos2dMESA),
- NAME_FUNC_OFFSET(18087, glWindowPos2dMESA, glWindowPos2dMESA, NULL, _gloffset_WindowPos2dMESA),
- NAME_FUNC_OFFSET(18104, glWindowPos2dvMESA, glWindowPos2dvMESA, NULL, _gloffset_WindowPos2dvMESA),
- NAME_FUNC_OFFSET(18119, glWindowPos2dvMESA, glWindowPos2dvMESA, NULL, _gloffset_WindowPos2dvMESA),
- NAME_FUNC_OFFSET(18137, glWindowPos2fMESA, glWindowPos2fMESA, NULL, _gloffset_WindowPos2fMESA),
- NAME_FUNC_OFFSET(18151, glWindowPos2fMESA, glWindowPos2fMESA, NULL, _gloffset_WindowPos2fMESA),
- NAME_FUNC_OFFSET(18168, glWindowPos2fvMESA, glWindowPos2fvMESA, NULL, _gloffset_WindowPos2fvMESA),
- NAME_FUNC_OFFSET(18183, glWindowPos2fvMESA, glWindowPos2fvMESA, NULL, _gloffset_WindowPos2fvMESA),
- NAME_FUNC_OFFSET(18201, glWindowPos2iMESA, glWindowPos2iMESA, NULL, _gloffset_WindowPos2iMESA),
- NAME_FUNC_OFFSET(18215, glWindowPos2iMESA, glWindowPos2iMESA, NULL, _gloffset_WindowPos2iMESA),
- NAME_FUNC_OFFSET(18232, glWindowPos2ivMESA, glWindowPos2ivMESA, NULL, _gloffset_WindowPos2ivMESA),
- NAME_FUNC_OFFSET(18247, glWindowPos2ivMESA, glWindowPos2ivMESA, NULL, _gloffset_WindowPos2ivMESA),
- NAME_FUNC_OFFSET(18265, glWindowPos2sMESA, glWindowPos2sMESA, NULL, _gloffset_WindowPos2sMESA),
- NAME_FUNC_OFFSET(18279, glWindowPos2sMESA, glWindowPos2sMESA, NULL, _gloffset_WindowPos2sMESA),
- NAME_FUNC_OFFSET(18296, glWindowPos2svMESA, glWindowPos2svMESA, NULL, _gloffset_WindowPos2svMESA),
- NAME_FUNC_OFFSET(18311, glWindowPos2svMESA, glWindowPos2svMESA, NULL, _gloffset_WindowPos2svMESA),
- NAME_FUNC_OFFSET(18329, glWindowPos3dMESA, glWindowPos3dMESA, NULL, _gloffset_WindowPos3dMESA),
- NAME_FUNC_OFFSET(18343, glWindowPos3dMESA, glWindowPos3dMESA, NULL, _gloffset_WindowPos3dMESA),
- NAME_FUNC_OFFSET(18360, glWindowPos3dvMESA, glWindowPos3dvMESA, NULL, _gloffset_WindowPos3dvMESA),
- NAME_FUNC_OFFSET(18375, glWindowPos3dvMESA, glWindowPos3dvMESA, NULL, _gloffset_WindowPos3dvMESA),
- NAME_FUNC_OFFSET(18393, glWindowPos3fMESA, glWindowPos3fMESA, NULL, _gloffset_WindowPos3fMESA),
- NAME_FUNC_OFFSET(18407, glWindowPos3fMESA, glWindowPos3fMESA, NULL, _gloffset_WindowPos3fMESA),
- NAME_FUNC_OFFSET(18424, glWindowPos3fvMESA, glWindowPos3fvMESA, NULL, _gloffset_WindowPos3fvMESA),
- NAME_FUNC_OFFSET(18439, glWindowPos3fvMESA, glWindowPos3fvMESA, NULL, _gloffset_WindowPos3fvMESA),
- NAME_FUNC_OFFSET(18457, glWindowPos3iMESA, glWindowPos3iMESA, NULL, _gloffset_WindowPos3iMESA),
- NAME_FUNC_OFFSET(18471, glWindowPos3iMESA, glWindowPos3iMESA, NULL, _gloffset_WindowPos3iMESA),
- NAME_FUNC_OFFSET(18488, glWindowPos3ivMESA, glWindowPos3ivMESA, NULL, _gloffset_WindowPos3ivMESA),
- NAME_FUNC_OFFSET(18503, glWindowPos3ivMESA, glWindowPos3ivMESA, NULL, _gloffset_WindowPos3ivMESA),
- NAME_FUNC_OFFSET(18521, glWindowPos3sMESA, glWindowPos3sMESA, NULL, _gloffset_WindowPos3sMESA),
- NAME_FUNC_OFFSET(18535, glWindowPos3sMESA, glWindowPos3sMESA, NULL, _gloffset_WindowPos3sMESA),
- NAME_FUNC_OFFSET(18552, glWindowPos3svMESA, glWindowPos3svMESA, NULL, _gloffset_WindowPos3svMESA),
- NAME_FUNC_OFFSET(18567, glWindowPos3svMESA, glWindowPos3svMESA, NULL, _gloffset_WindowPos3svMESA),
- NAME_FUNC_OFFSET(18585, glBindProgramNV, glBindProgramNV, NULL, _gloffset_BindProgramNV),
- NAME_FUNC_OFFSET(18602, glDeleteProgramsNV, glDeleteProgramsNV, NULL, _gloffset_DeleteProgramsNV),
- NAME_FUNC_OFFSET(18622, glGenProgramsNV, glGenProgramsNV, NULL, _gloffset_GenProgramsNV),
- NAME_FUNC_OFFSET(18639, glGetVertexAttribPointervNV, glGetVertexAttribPointervNV, NULL, _gloffset_GetVertexAttribPointervNV),
- NAME_FUNC_OFFSET(18665, glGetVertexAttribPointervNV, glGetVertexAttribPointervNV, NULL, _gloffset_GetVertexAttribPointervNV),
- NAME_FUNC_OFFSET(18694, glIsProgramNV, glIsProgramNV, NULL, _gloffset_IsProgramNV),
- NAME_FUNC_OFFSET(18709, glPointParameteriNV, glPointParameteriNV, NULL, _gloffset_PointParameteriNV),
- NAME_FUNC_OFFSET(18727, glPointParameterivNV, glPointParameterivNV, NULL, _gloffset_PointParameterivNV),
- NAME_FUNC_OFFSET(18746, gl_dispatch_stub_745, gl_dispatch_stub_745, NULL, _gloffset_BlendEquationSeparateEXT),
- NAME_FUNC_OFFSET(18770, gl_dispatch_stub_745, gl_dispatch_stub_745, NULL, _gloffset_BlendEquationSeparateEXT),
+ NAME_FUNC_OFFSET( 8951, glRenderbufferStorageMultisample, glRenderbufferStorageMultisample, NULL, _gloffset_RenderbufferStorageMultisample),
+ NAME_FUNC_OFFSET( 8984, glFlushMappedBufferRange, glFlushMappedBufferRange, NULL, _gloffset_FlushMappedBufferRange),
+ NAME_FUNC_OFFSET( 9009, glMapBufferRange, glMapBufferRange, NULL, _gloffset_MapBufferRange),
+ NAME_FUNC_OFFSET( 9026, glBindVertexArray, glBindVertexArray, NULL, _gloffset_BindVertexArray),
+ NAME_FUNC_OFFSET( 9044, glGenVertexArrays, glGenVertexArrays, NULL, _gloffset_GenVertexArrays),
+ NAME_FUNC_OFFSET( 9062, glCopyBufferSubData, glCopyBufferSubData, NULL, _gloffset_CopyBufferSubData),
+ NAME_FUNC_OFFSET( 9082, glClientWaitSync, glClientWaitSync, NULL, _gloffset_ClientWaitSync),
+ NAME_FUNC_OFFSET( 9099, glDeleteSync, glDeleteSync, NULL, _gloffset_DeleteSync),
+ NAME_FUNC_OFFSET( 9112, glFenceSync, glFenceSync, NULL, _gloffset_FenceSync),
+ NAME_FUNC_OFFSET( 9124, glGetInteger64v, glGetInteger64v, NULL, _gloffset_GetInteger64v),
+ NAME_FUNC_OFFSET( 9140, glGetSynciv, glGetSynciv, NULL, _gloffset_GetSynciv),
+ NAME_FUNC_OFFSET( 9152, glIsSync, glIsSync, NULL, _gloffset_IsSync),
+ NAME_FUNC_OFFSET( 9161, glWaitSync, glWaitSync, NULL, _gloffset_WaitSync),
+ NAME_FUNC_OFFSET( 9172, glDrawElementsBaseVertex, glDrawElementsBaseVertex, NULL, _gloffset_DrawElementsBaseVertex),
+ NAME_FUNC_OFFSET( 9197, glDrawRangeElementsBaseVertex, glDrawRangeElementsBaseVertex, NULL, _gloffset_DrawRangeElementsBaseVertex),
+ NAME_FUNC_OFFSET( 9227, glMultiDrawElementsBaseVertex, glMultiDrawElementsBaseVertex, NULL, _gloffset_MultiDrawElementsBaseVertex),
+ NAME_FUNC_OFFSET( 9257, glPolygonOffsetEXT, glPolygonOffsetEXT, NULL, _gloffset_PolygonOffsetEXT),
+ NAME_FUNC_OFFSET( 9276, gl_dispatch_stub_578, gl_dispatch_stub_578, NULL, _gloffset_GetPixelTexGenParameterfvSGIS),
+ NAME_FUNC_OFFSET( 9308, gl_dispatch_stub_579, gl_dispatch_stub_579, NULL, _gloffset_GetPixelTexGenParameterivSGIS),
+ NAME_FUNC_OFFSET( 9340, gl_dispatch_stub_580, gl_dispatch_stub_580, NULL, _gloffset_PixelTexGenParameterfSGIS),
+ NAME_FUNC_OFFSET( 9368, gl_dispatch_stub_581, gl_dispatch_stub_581, NULL, _gloffset_PixelTexGenParameterfvSGIS),
+ NAME_FUNC_OFFSET( 9397, gl_dispatch_stub_582, gl_dispatch_stub_582, NULL, _gloffset_PixelTexGenParameteriSGIS),
+ NAME_FUNC_OFFSET( 9425, gl_dispatch_stub_583, gl_dispatch_stub_583, NULL, _gloffset_PixelTexGenParameterivSGIS),
+ NAME_FUNC_OFFSET( 9454, gl_dispatch_stub_584, gl_dispatch_stub_584, NULL, _gloffset_SampleMaskSGIS),
+ NAME_FUNC_OFFSET( 9471, gl_dispatch_stub_585, gl_dispatch_stub_585, NULL, _gloffset_SamplePatternSGIS),
+ NAME_FUNC_OFFSET( 9491, glColorPointerEXT, glColorPointerEXT, NULL, _gloffset_ColorPointerEXT),
+ NAME_FUNC_OFFSET( 9509, glEdgeFlagPointerEXT, glEdgeFlagPointerEXT, NULL, _gloffset_EdgeFlagPointerEXT),
+ NAME_FUNC_OFFSET( 9530, glIndexPointerEXT, glIndexPointerEXT, NULL, _gloffset_IndexPointerEXT),
+ NAME_FUNC_OFFSET( 9548, glNormalPointerEXT, glNormalPointerEXT, NULL, _gloffset_NormalPointerEXT),
+ NAME_FUNC_OFFSET( 9567, glTexCoordPointerEXT, glTexCoordPointerEXT, NULL, _gloffset_TexCoordPointerEXT),
+ NAME_FUNC_OFFSET( 9588, glVertexPointerEXT, glVertexPointerEXT, NULL, _gloffset_VertexPointerEXT),
+ NAME_FUNC_OFFSET( 9607, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
+ NAME_FUNC_OFFSET( 9628, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
+ NAME_FUNC_OFFSET( 9650, glLockArraysEXT, glLockArraysEXT, NULL, _gloffset_LockArraysEXT),
+ NAME_FUNC_OFFSET( 9666, glUnlockArraysEXT, glUnlockArraysEXT, NULL, _gloffset_UnlockArraysEXT),
+ NAME_FUNC_OFFSET( 9684, gl_dispatch_stub_596, gl_dispatch_stub_596, NULL, _gloffset_CullParameterdvEXT),
+ NAME_FUNC_OFFSET( 9705, gl_dispatch_stub_597, gl_dispatch_stub_597, NULL, _gloffset_CullParameterfvEXT),
+ NAME_FUNC_OFFSET( 9726, glSecondaryColor3bEXT, glSecondaryColor3bEXT, NULL, _gloffset_SecondaryColor3bEXT),
+ NAME_FUNC_OFFSET( 9748, glSecondaryColor3bvEXT, glSecondaryColor3bvEXT, NULL, _gloffset_SecondaryColor3bvEXT),
+ NAME_FUNC_OFFSET( 9771, glSecondaryColor3dEXT, glSecondaryColor3dEXT, NULL, _gloffset_SecondaryColor3dEXT),
+ NAME_FUNC_OFFSET( 9793, glSecondaryColor3dvEXT, glSecondaryColor3dvEXT, NULL, _gloffset_SecondaryColor3dvEXT),
+ NAME_FUNC_OFFSET( 9816, glSecondaryColor3fEXT, glSecondaryColor3fEXT, NULL, _gloffset_SecondaryColor3fEXT),
+ NAME_FUNC_OFFSET( 9838, glSecondaryColor3fvEXT, glSecondaryColor3fvEXT, NULL, _gloffset_SecondaryColor3fvEXT),
+ NAME_FUNC_OFFSET( 9861, glSecondaryColor3iEXT, glSecondaryColor3iEXT, NULL, _gloffset_SecondaryColor3iEXT),
+ NAME_FUNC_OFFSET( 9883, glSecondaryColor3ivEXT, glSecondaryColor3ivEXT, NULL, _gloffset_SecondaryColor3ivEXT),
+ NAME_FUNC_OFFSET( 9906, glSecondaryColor3sEXT, glSecondaryColor3sEXT, NULL, _gloffset_SecondaryColor3sEXT),
+ NAME_FUNC_OFFSET( 9928, glSecondaryColor3svEXT, glSecondaryColor3svEXT, NULL, _gloffset_SecondaryColor3svEXT),
+ NAME_FUNC_OFFSET( 9951, glSecondaryColor3ubEXT, glSecondaryColor3ubEXT, NULL, _gloffset_SecondaryColor3ubEXT),
+ NAME_FUNC_OFFSET( 9974, glSecondaryColor3ubvEXT, glSecondaryColor3ubvEXT, NULL, _gloffset_SecondaryColor3ubvEXT),
+ NAME_FUNC_OFFSET( 9998, glSecondaryColor3uiEXT, glSecondaryColor3uiEXT, NULL, _gloffset_SecondaryColor3uiEXT),
+ NAME_FUNC_OFFSET(10021, glSecondaryColor3uivEXT, glSecondaryColor3uivEXT, NULL, _gloffset_SecondaryColor3uivEXT),
+ NAME_FUNC_OFFSET(10045, glSecondaryColor3usEXT, glSecondaryColor3usEXT, NULL, _gloffset_SecondaryColor3usEXT),
+ NAME_FUNC_OFFSET(10068, glSecondaryColor3usvEXT, glSecondaryColor3usvEXT, NULL, _gloffset_SecondaryColor3usvEXT),
+ NAME_FUNC_OFFSET(10092, glSecondaryColorPointerEXT, glSecondaryColorPointerEXT, NULL, _gloffset_SecondaryColorPointerEXT),
+ NAME_FUNC_OFFSET(10119, glMultiDrawArraysEXT, glMultiDrawArraysEXT, NULL, _gloffset_MultiDrawArraysEXT),
+ NAME_FUNC_OFFSET(10140, glMultiDrawElementsEXT, glMultiDrawElementsEXT, NULL, _gloffset_MultiDrawElementsEXT),
+ NAME_FUNC_OFFSET(10163, glFogCoordPointerEXT, glFogCoordPointerEXT, NULL, _gloffset_FogCoordPointerEXT),
+ NAME_FUNC_OFFSET(10184, glFogCoorddEXT, glFogCoorddEXT, NULL, _gloffset_FogCoorddEXT),
+ NAME_FUNC_OFFSET(10199, glFogCoorddvEXT, glFogCoorddvEXT, NULL, _gloffset_FogCoorddvEXT),
+ NAME_FUNC_OFFSET(10215, glFogCoordfEXT, glFogCoordfEXT, NULL, _gloffset_FogCoordfEXT),
+ NAME_FUNC_OFFSET(10230, glFogCoordfvEXT, glFogCoordfvEXT, NULL, _gloffset_FogCoordfvEXT),
+ NAME_FUNC_OFFSET(10246, gl_dispatch_stub_622, gl_dispatch_stub_622, NULL, _gloffset_PixelTexGenSGIX),
+ NAME_FUNC_OFFSET(10264, glBlendFuncSeparateEXT, glBlendFuncSeparateEXT, NULL, _gloffset_BlendFuncSeparateEXT),
+ NAME_FUNC_OFFSET(10287, glFlushVertexArrayRangeNV, glFlushVertexArrayRangeNV, NULL, _gloffset_FlushVertexArrayRangeNV),
+ NAME_FUNC_OFFSET(10313, glVertexArrayRangeNV, glVertexArrayRangeNV, NULL, _gloffset_VertexArrayRangeNV),
+ NAME_FUNC_OFFSET(10334, glCombinerInputNV, glCombinerInputNV, NULL, _gloffset_CombinerInputNV),
+ NAME_FUNC_OFFSET(10352, glCombinerOutputNV, glCombinerOutputNV, NULL, _gloffset_CombinerOutputNV),
+ NAME_FUNC_OFFSET(10371, glCombinerParameterfNV, glCombinerParameterfNV, NULL, _gloffset_CombinerParameterfNV),
+ NAME_FUNC_OFFSET(10394, glCombinerParameterfvNV, glCombinerParameterfvNV, NULL, _gloffset_CombinerParameterfvNV),
+ NAME_FUNC_OFFSET(10418, glCombinerParameteriNV, glCombinerParameteriNV, NULL, _gloffset_CombinerParameteriNV),
+ NAME_FUNC_OFFSET(10441, glCombinerParameterivNV, glCombinerParameterivNV, NULL, _gloffset_CombinerParameterivNV),
+ NAME_FUNC_OFFSET(10465, glFinalCombinerInputNV, glFinalCombinerInputNV, NULL, _gloffset_FinalCombinerInputNV),
+ NAME_FUNC_OFFSET(10488, glGetCombinerInputParameterfvNV, glGetCombinerInputParameterfvNV, NULL, _gloffset_GetCombinerInputParameterfvNV),
+ NAME_FUNC_OFFSET(10520, glGetCombinerInputParameterivNV, glGetCombinerInputParameterivNV, NULL, _gloffset_GetCombinerInputParameterivNV),
+ NAME_FUNC_OFFSET(10552, glGetCombinerOutputParameterfvNV, glGetCombinerOutputParameterfvNV, NULL, _gloffset_GetCombinerOutputParameterfvNV),
+ NAME_FUNC_OFFSET(10585, glGetCombinerOutputParameterivNV, glGetCombinerOutputParameterivNV, NULL, _gloffset_GetCombinerOutputParameterivNV),
+ NAME_FUNC_OFFSET(10618, glGetFinalCombinerInputParameterfvNV, glGetFinalCombinerInputParameterfvNV, NULL, _gloffset_GetFinalCombinerInputParameterfvNV),
+ NAME_FUNC_OFFSET(10655, glGetFinalCombinerInputParameterivNV, glGetFinalCombinerInputParameterivNV, NULL, _gloffset_GetFinalCombinerInputParameterivNV),
+ NAME_FUNC_OFFSET(10692, glResizeBuffersMESA, glResizeBuffersMESA, NULL, _gloffset_ResizeBuffersMESA),
+ NAME_FUNC_OFFSET(10712, glWindowPos2dMESA, glWindowPos2dMESA, NULL, _gloffset_WindowPos2dMESA),
+ NAME_FUNC_OFFSET(10730, glWindowPos2dvMESA, glWindowPos2dvMESA, NULL, _gloffset_WindowPos2dvMESA),
+ NAME_FUNC_OFFSET(10749, glWindowPos2fMESA, glWindowPos2fMESA, NULL, _gloffset_WindowPos2fMESA),
+ NAME_FUNC_OFFSET(10767, glWindowPos2fvMESA, glWindowPos2fvMESA, NULL, _gloffset_WindowPos2fvMESA),
+ NAME_FUNC_OFFSET(10786, glWindowPos2iMESA, glWindowPos2iMESA, NULL, _gloffset_WindowPos2iMESA),
+ NAME_FUNC_OFFSET(10804, glWindowPos2ivMESA, glWindowPos2ivMESA, NULL, _gloffset_WindowPos2ivMESA),
+ NAME_FUNC_OFFSET(10823, glWindowPos2sMESA, glWindowPos2sMESA, NULL, _gloffset_WindowPos2sMESA),
+ NAME_FUNC_OFFSET(10841, glWindowPos2svMESA, glWindowPos2svMESA, NULL, _gloffset_WindowPos2svMESA),
+ NAME_FUNC_OFFSET(10860, glWindowPos3dMESA, glWindowPos3dMESA, NULL, _gloffset_WindowPos3dMESA),
+ NAME_FUNC_OFFSET(10878, glWindowPos3dvMESA, glWindowPos3dvMESA, NULL, _gloffset_WindowPos3dvMESA),
+ NAME_FUNC_OFFSET(10897, glWindowPos3fMESA, glWindowPos3fMESA, NULL, _gloffset_WindowPos3fMESA),
+ NAME_FUNC_OFFSET(10915, glWindowPos3fvMESA, glWindowPos3fvMESA, NULL, _gloffset_WindowPos3fvMESA),
+ NAME_FUNC_OFFSET(10934, glWindowPos3iMESA, glWindowPos3iMESA, NULL, _gloffset_WindowPos3iMESA),
+ NAME_FUNC_OFFSET(10952, glWindowPos3ivMESA, glWindowPos3ivMESA, NULL, _gloffset_WindowPos3ivMESA),
+ NAME_FUNC_OFFSET(10971, glWindowPos3sMESA, glWindowPos3sMESA, NULL, _gloffset_WindowPos3sMESA),
+ NAME_FUNC_OFFSET(10989, glWindowPos3svMESA, glWindowPos3svMESA, NULL, _gloffset_WindowPos3svMESA),
+ NAME_FUNC_OFFSET(11008, glWindowPos4dMESA, glWindowPos4dMESA, NULL, _gloffset_WindowPos4dMESA),
+ NAME_FUNC_OFFSET(11026, glWindowPos4dvMESA, glWindowPos4dvMESA, NULL, _gloffset_WindowPos4dvMESA),
+ NAME_FUNC_OFFSET(11045, glWindowPos4fMESA, glWindowPos4fMESA, NULL, _gloffset_WindowPos4fMESA),
+ NAME_FUNC_OFFSET(11063, glWindowPos4fvMESA, glWindowPos4fvMESA, NULL, _gloffset_WindowPos4fvMESA),
+ NAME_FUNC_OFFSET(11082, glWindowPos4iMESA, glWindowPos4iMESA, NULL, _gloffset_WindowPos4iMESA),
+ NAME_FUNC_OFFSET(11100, glWindowPos4ivMESA, glWindowPos4ivMESA, NULL, _gloffset_WindowPos4ivMESA),
+ NAME_FUNC_OFFSET(11119, glWindowPos4sMESA, glWindowPos4sMESA, NULL, _gloffset_WindowPos4sMESA),
+ NAME_FUNC_OFFSET(11137, glWindowPos4svMESA, glWindowPos4svMESA, NULL, _gloffset_WindowPos4svMESA),
+ NAME_FUNC_OFFSET(11156, gl_dispatch_stub_664, gl_dispatch_stub_664, NULL, _gloffset_MultiModeDrawArraysIBM),
+ NAME_FUNC_OFFSET(11181, gl_dispatch_stub_665, gl_dispatch_stub_665, NULL, _gloffset_MultiModeDrawElementsIBM),
+ NAME_FUNC_OFFSET(11208, gl_dispatch_stub_666, gl_dispatch_stub_666, NULL, _gloffset_DeleteFencesNV),
+ NAME_FUNC_OFFSET(11225, gl_dispatch_stub_667, gl_dispatch_stub_667, NULL, _gloffset_FinishFenceNV),
+ NAME_FUNC_OFFSET(11241, gl_dispatch_stub_668, gl_dispatch_stub_668, NULL, _gloffset_GenFencesNV),
+ NAME_FUNC_OFFSET(11255, gl_dispatch_stub_669, gl_dispatch_stub_669, NULL, _gloffset_GetFenceivNV),
+ NAME_FUNC_OFFSET(11270, gl_dispatch_stub_670, gl_dispatch_stub_670, NULL, _gloffset_IsFenceNV),
+ NAME_FUNC_OFFSET(11282, gl_dispatch_stub_671, gl_dispatch_stub_671, NULL, _gloffset_SetFenceNV),
+ NAME_FUNC_OFFSET(11295, gl_dispatch_stub_672, gl_dispatch_stub_672, NULL, _gloffset_TestFenceNV),
+ NAME_FUNC_OFFSET(11309, glAreProgramsResidentNV, glAreProgramsResidentNV, NULL, _gloffset_AreProgramsResidentNV),
+ NAME_FUNC_OFFSET(11333, glBindProgramNV, glBindProgramNV, NULL, _gloffset_BindProgramNV),
+ NAME_FUNC_OFFSET(11349, glDeleteProgramsNV, glDeleteProgramsNV, NULL, _gloffset_DeleteProgramsNV),
+ NAME_FUNC_OFFSET(11368, glExecuteProgramNV, glExecuteProgramNV, NULL, _gloffset_ExecuteProgramNV),
+ NAME_FUNC_OFFSET(11387, glGenProgramsNV, glGenProgramsNV, NULL, _gloffset_GenProgramsNV),
+ NAME_FUNC_OFFSET(11403, glGetProgramParameterdvNV, glGetProgramParameterdvNV, NULL, _gloffset_GetProgramParameterdvNV),
+ NAME_FUNC_OFFSET(11429, glGetProgramParameterfvNV, glGetProgramParameterfvNV, NULL, _gloffset_GetProgramParameterfvNV),
+ NAME_FUNC_OFFSET(11455, glGetProgramStringNV, glGetProgramStringNV, NULL, _gloffset_GetProgramStringNV),
+ NAME_FUNC_OFFSET(11476, glGetProgramivNV, glGetProgramivNV, NULL, _gloffset_GetProgramivNV),
+ NAME_FUNC_OFFSET(11493, glGetTrackMatrixivNV, glGetTrackMatrixivNV, NULL, _gloffset_GetTrackMatrixivNV),
+ NAME_FUNC_OFFSET(11514, glGetVertexAttribPointervNV, glGetVertexAttribPointervNV, NULL, _gloffset_GetVertexAttribPointervNV),
+ NAME_FUNC_OFFSET(11542, glGetVertexAttribdvNV, glGetVertexAttribdvNV, NULL, _gloffset_GetVertexAttribdvNV),
+ NAME_FUNC_OFFSET(11564, glGetVertexAttribfvNV, glGetVertexAttribfvNV, NULL, _gloffset_GetVertexAttribfvNV),
+ NAME_FUNC_OFFSET(11586, glGetVertexAttribivNV, glGetVertexAttribivNV, NULL, _gloffset_GetVertexAttribivNV),
+ NAME_FUNC_OFFSET(11608, glIsProgramNV, glIsProgramNV, NULL, _gloffset_IsProgramNV),
+ NAME_FUNC_OFFSET(11622, glLoadProgramNV, glLoadProgramNV, NULL, _gloffset_LoadProgramNV),
+ NAME_FUNC_OFFSET(11638, glProgramParameters4dvNV, glProgramParameters4dvNV, NULL, _gloffset_ProgramParameters4dvNV),
+ NAME_FUNC_OFFSET(11663, glProgramParameters4fvNV, glProgramParameters4fvNV, NULL, _gloffset_ProgramParameters4fvNV),
+ NAME_FUNC_OFFSET(11688, glRequestResidentProgramsNV, glRequestResidentProgramsNV, NULL, _gloffset_RequestResidentProgramsNV),
+ NAME_FUNC_OFFSET(11716, glTrackMatrixNV, glTrackMatrixNV, NULL, _gloffset_TrackMatrixNV),
+ NAME_FUNC_OFFSET(11732, glVertexAttrib1dNV, glVertexAttrib1dNV, NULL, _gloffset_VertexAttrib1dNV),
+ NAME_FUNC_OFFSET(11751, glVertexAttrib1dvNV, glVertexAttrib1dvNV, NULL, _gloffset_VertexAttrib1dvNV),
+ NAME_FUNC_OFFSET(11771, glVertexAttrib1fNV, glVertexAttrib1fNV, NULL, _gloffset_VertexAttrib1fNV),
+ NAME_FUNC_OFFSET(11790, glVertexAttrib1fvNV, glVertexAttrib1fvNV, NULL, _gloffset_VertexAttrib1fvNV),
+ NAME_FUNC_OFFSET(11810, glVertexAttrib1sNV, glVertexAttrib1sNV, NULL, _gloffset_VertexAttrib1sNV),
+ NAME_FUNC_OFFSET(11829, glVertexAttrib1svNV, glVertexAttrib1svNV, NULL, _gloffset_VertexAttrib1svNV),
+ NAME_FUNC_OFFSET(11849, glVertexAttrib2dNV, glVertexAttrib2dNV, NULL, _gloffset_VertexAttrib2dNV),
+ NAME_FUNC_OFFSET(11868, glVertexAttrib2dvNV, glVertexAttrib2dvNV, NULL, _gloffset_VertexAttrib2dvNV),
+ NAME_FUNC_OFFSET(11888, glVertexAttrib2fNV, glVertexAttrib2fNV, NULL, _gloffset_VertexAttrib2fNV),
+ NAME_FUNC_OFFSET(11907, glVertexAttrib2fvNV, glVertexAttrib2fvNV, NULL, _gloffset_VertexAttrib2fvNV),
+ NAME_FUNC_OFFSET(11927, glVertexAttrib2sNV, glVertexAttrib2sNV, NULL, _gloffset_VertexAttrib2sNV),
+ NAME_FUNC_OFFSET(11946, glVertexAttrib2svNV, glVertexAttrib2svNV, NULL, _gloffset_VertexAttrib2svNV),
+ NAME_FUNC_OFFSET(11966, glVertexAttrib3dNV, glVertexAttrib3dNV, NULL, _gloffset_VertexAttrib3dNV),
+ NAME_FUNC_OFFSET(11985, glVertexAttrib3dvNV, glVertexAttrib3dvNV, NULL, _gloffset_VertexAttrib3dvNV),
+ NAME_FUNC_OFFSET(12005, glVertexAttrib3fNV, glVertexAttrib3fNV, NULL, _gloffset_VertexAttrib3fNV),
+ NAME_FUNC_OFFSET(12024, glVertexAttrib3fvNV, glVertexAttrib3fvNV, NULL, _gloffset_VertexAttrib3fvNV),
+ NAME_FUNC_OFFSET(12044, glVertexAttrib3sNV, glVertexAttrib3sNV, NULL, _gloffset_VertexAttrib3sNV),
+ NAME_FUNC_OFFSET(12063, glVertexAttrib3svNV, glVertexAttrib3svNV, NULL, _gloffset_VertexAttrib3svNV),
+ NAME_FUNC_OFFSET(12083, glVertexAttrib4dNV, glVertexAttrib4dNV, NULL, _gloffset_VertexAttrib4dNV),
+ NAME_FUNC_OFFSET(12102, glVertexAttrib4dvNV, glVertexAttrib4dvNV, NULL, _gloffset_VertexAttrib4dvNV),
+ NAME_FUNC_OFFSET(12122, glVertexAttrib4fNV, glVertexAttrib4fNV, NULL, _gloffset_VertexAttrib4fNV),
+ NAME_FUNC_OFFSET(12141, glVertexAttrib4fvNV, glVertexAttrib4fvNV, NULL, _gloffset_VertexAttrib4fvNV),
+ NAME_FUNC_OFFSET(12161, glVertexAttrib4sNV, glVertexAttrib4sNV, NULL, _gloffset_VertexAttrib4sNV),
+ NAME_FUNC_OFFSET(12180, glVertexAttrib4svNV, glVertexAttrib4svNV, NULL, _gloffset_VertexAttrib4svNV),
+ NAME_FUNC_OFFSET(12200, glVertexAttrib4ubNV, glVertexAttrib4ubNV, NULL, _gloffset_VertexAttrib4ubNV),
+ NAME_FUNC_OFFSET(12220, glVertexAttrib4ubvNV, glVertexAttrib4ubvNV, NULL, _gloffset_VertexAttrib4ubvNV),
+ NAME_FUNC_OFFSET(12241, glVertexAttribPointerNV, glVertexAttribPointerNV, NULL, _gloffset_VertexAttribPointerNV),
+ NAME_FUNC_OFFSET(12265, glVertexAttribs1dvNV, glVertexAttribs1dvNV, NULL, _gloffset_VertexAttribs1dvNV),
+ NAME_FUNC_OFFSET(12286, glVertexAttribs1fvNV, glVertexAttribs1fvNV, NULL, _gloffset_VertexAttribs1fvNV),
+ NAME_FUNC_OFFSET(12307, glVertexAttribs1svNV, glVertexAttribs1svNV, NULL, _gloffset_VertexAttribs1svNV),
+ NAME_FUNC_OFFSET(12328, glVertexAttribs2dvNV, glVertexAttribs2dvNV, NULL, _gloffset_VertexAttribs2dvNV),
+ NAME_FUNC_OFFSET(12349, glVertexAttribs2fvNV, glVertexAttribs2fvNV, NULL, _gloffset_VertexAttribs2fvNV),
+ NAME_FUNC_OFFSET(12370, glVertexAttribs2svNV, glVertexAttribs2svNV, NULL, _gloffset_VertexAttribs2svNV),
+ NAME_FUNC_OFFSET(12391, glVertexAttribs3dvNV, glVertexAttribs3dvNV, NULL, _gloffset_VertexAttribs3dvNV),
+ NAME_FUNC_OFFSET(12412, glVertexAttribs3fvNV, glVertexAttribs3fvNV, NULL, _gloffset_VertexAttribs3fvNV),
+ NAME_FUNC_OFFSET(12433, glVertexAttribs3svNV, glVertexAttribs3svNV, NULL, _gloffset_VertexAttribs3svNV),
+ NAME_FUNC_OFFSET(12454, glVertexAttribs4dvNV, glVertexAttribs4dvNV, NULL, _gloffset_VertexAttribs4dvNV),
+ NAME_FUNC_OFFSET(12475, glVertexAttribs4fvNV, glVertexAttribs4fvNV, NULL, _gloffset_VertexAttribs4fvNV),
+ NAME_FUNC_OFFSET(12496, glVertexAttribs4svNV, glVertexAttribs4svNV, NULL, _gloffset_VertexAttribs4svNV),
+ NAME_FUNC_OFFSET(12517, glVertexAttribs4ubvNV, glVertexAttribs4ubvNV, NULL, _gloffset_VertexAttribs4ubvNV),
+ NAME_FUNC_OFFSET(12539, glGetTexBumpParameterfvATI, glGetTexBumpParameterfvATI, NULL, _gloffset_GetTexBumpParameterfvATI),
+ NAME_FUNC_OFFSET(12566, glGetTexBumpParameterivATI, glGetTexBumpParameterivATI, NULL, _gloffset_GetTexBumpParameterivATI),
+ NAME_FUNC_OFFSET(12593, glTexBumpParameterfvATI, glTexBumpParameterfvATI, NULL, _gloffset_TexBumpParameterfvATI),
+ NAME_FUNC_OFFSET(12617, glTexBumpParameterivATI, glTexBumpParameterivATI, NULL, _gloffset_TexBumpParameterivATI),
+ NAME_FUNC_OFFSET(12641, glAlphaFragmentOp1ATI, glAlphaFragmentOp1ATI, NULL, _gloffset_AlphaFragmentOp1ATI),
+ NAME_FUNC_OFFSET(12663, glAlphaFragmentOp2ATI, glAlphaFragmentOp2ATI, NULL, _gloffset_AlphaFragmentOp2ATI),
+ NAME_FUNC_OFFSET(12685, glAlphaFragmentOp3ATI, glAlphaFragmentOp3ATI, NULL, _gloffset_AlphaFragmentOp3ATI),
+ NAME_FUNC_OFFSET(12707, glBeginFragmentShaderATI, glBeginFragmentShaderATI, NULL, _gloffset_BeginFragmentShaderATI),
+ NAME_FUNC_OFFSET(12732, glBindFragmentShaderATI, glBindFragmentShaderATI, NULL, _gloffset_BindFragmentShaderATI),
+ NAME_FUNC_OFFSET(12756, glColorFragmentOp1ATI, glColorFragmentOp1ATI, NULL, _gloffset_ColorFragmentOp1ATI),
+ NAME_FUNC_OFFSET(12778, glColorFragmentOp2ATI, glColorFragmentOp2ATI, NULL, _gloffset_ColorFragmentOp2ATI),
+ NAME_FUNC_OFFSET(12800, glColorFragmentOp3ATI, glColorFragmentOp3ATI, NULL, _gloffset_ColorFragmentOp3ATI),
+ NAME_FUNC_OFFSET(12822, glDeleteFragmentShaderATI, glDeleteFragmentShaderATI, NULL, _gloffset_DeleteFragmentShaderATI),
+ NAME_FUNC_OFFSET(12848, glEndFragmentShaderATI, glEndFragmentShaderATI, NULL, _gloffset_EndFragmentShaderATI),
+ NAME_FUNC_OFFSET(12871, glGenFragmentShadersATI, glGenFragmentShadersATI, NULL, _gloffset_GenFragmentShadersATI),
+ NAME_FUNC_OFFSET(12895, glPassTexCoordATI, glPassTexCoordATI, NULL, _gloffset_PassTexCoordATI),
+ NAME_FUNC_OFFSET(12913, glSampleMapATI, glSampleMapATI, NULL, _gloffset_SampleMapATI),
+ NAME_FUNC_OFFSET(12928, glSetFragmentShaderConstantATI, glSetFragmentShaderConstantATI, NULL, _gloffset_SetFragmentShaderConstantATI),
+ NAME_FUNC_OFFSET(12959, glPointParameteriNV, glPointParameteriNV, NULL, _gloffset_PointParameteriNV),
+ NAME_FUNC_OFFSET(12979, glPointParameterivNV, glPointParameterivNV, NULL, _gloffset_PointParameterivNV),
+ NAME_FUNC_OFFSET(13000, gl_dispatch_stub_753, gl_dispatch_stub_753, NULL, _gloffset_ActiveStencilFaceEXT),
+ NAME_FUNC_OFFSET(13023, gl_dispatch_stub_754, gl_dispatch_stub_754, NULL, _gloffset_BindVertexArrayAPPLE),
+ NAME_FUNC_OFFSET(13046, gl_dispatch_stub_755, gl_dispatch_stub_755, NULL, _gloffset_DeleteVertexArraysAPPLE),
+ NAME_FUNC_OFFSET(13072, gl_dispatch_stub_756, gl_dispatch_stub_756, NULL, _gloffset_GenVertexArraysAPPLE),
+ NAME_FUNC_OFFSET(13095, gl_dispatch_stub_757, gl_dispatch_stub_757, NULL, _gloffset_IsVertexArrayAPPLE),
+ NAME_FUNC_OFFSET(13116, glGetProgramNamedParameterdvNV, glGetProgramNamedParameterdvNV, NULL, _gloffset_GetProgramNamedParameterdvNV),
+ NAME_FUNC_OFFSET(13147, glGetProgramNamedParameterfvNV, glGetProgramNamedParameterfvNV, NULL, _gloffset_GetProgramNamedParameterfvNV),
+ NAME_FUNC_OFFSET(13178, glProgramNamedParameter4dNV, glProgramNamedParameter4dNV, NULL, _gloffset_ProgramNamedParameter4dNV),
+ NAME_FUNC_OFFSET(13206, glProgramNamedParameter4dvNV, glProgramNamedParameter4dvNV, NULL, _gloffset_ProgramNamedParameter4dvNV),
+ NAME_FUNC_OFFSET(13235, glProgramNamedParameter4fNV, glProgramNamedParameter4fNV, NULL, _gloffset_ProgramNamedParameter4fNV),
+ NAME_FUNC_OFFSET(13263, glProgramNamedParameter4fvNV, glProgramNamedParameter4fvNV, NULL, _gloffset_ProgramNamedParameter4fvNV),
+ NAME_FUNC_OFFSET(13292, gl_dispatch_stub_764, gl_dispatch_stub_764, NULL, _gloffset_DepthBoundsEXT),
+ NAME_FUNC_OFFSET(13309, gl_dispatch_stub_765, gl_dispatch_stub_765, NULL, _gloffset_BlendEquationSeparateEXT),
+ NAME_FUNC_OFFSET(13336, glBindFramebufferEXT, glBindFramebufferEXT, NULL, _gloffset_BindFramebufferEXT),
+ NAME_FUNC_OFFSET(13357, glBindRenderbufferEXT, glBindRenderbufferEXT, NULL, _gloffset_BindRenderbufferEXT),
+ NAME_FUNC_OFFSET(13379, glCheckFramebufferStatusEXT, glCheckFramebufferStatusEXT, NULL, _gloffset_CheckFramebufferStatusEXT),
+ NAME_FUNC_OFFSET(13407, glDeleteFramebuffersEXT, glDeleteFramebuffersEXT, NULL, _gloffset_DeleteFramebuffersEXT),
+ NAME_FUNC_OFFSET(13431, glDeleteRenderbuffersEXT, glDeleteRenderbuffersEXT, NULL, _gloffset_DeleteRenderbuffersEXT),
+ NAME_FUNC_OFFSET(13456, glFramebufferRenderbufferEXT, glFramebufferRenderbufferEXT, NULL, _gloffset_FramebufferRenderbufferEXT),
+ NAME_FUNC_OFFSET(13485, glFramebufferTexture1DEXT, glFramebufferTexture1DEXT, NULL, _gloffset_FramebufferTexture1DEXT),
+ NAME_FUNC_OFFSET(13511, glFramebufferTexture2DEXT, glFramebufferTexture2DEXT, NULL, _gloffset_FramebufferTexture2DEXT),
+ NAME_FUNC_OFFSET(13537, glFramebufferTexture3DEXT, glFramebufferTexture3DEXT, NULL, _gloffset_FramebufferTexture3DEXT),
+ NAME_FUNC_OFFSET(13563, glGenFramebuffersEXT, glGenFramebuffersEXT, NULL, _gloffset_GenFramebuffersEXT),
+ NAME_FUNC_OFFSET(13584, glGenRenderbuffersEXT, glGenRenderbuffersEXT, NULL, _gloffset_GenRenderbuffersEXT),
+ NAME_FUNC_OFFSET(13606, glGenerateMipmapEXT, glGenerateMipmapEXT, NULL, _gloffset_GenerateMipmapEXT),
+ NAME_FUNC_OFFSET(13626, glGetFramebufferAttachmentParameterivEXT, glGetFramebufferAttachmentParameterivEXT, NULL, _gloffset_GetFramebufferAttachmentParameterivEXT),
+ NAME_FUNC_OFFSET(13667, glGetRenderbufferParameterivEXT, glGetRenderbufferParameterivEXT, NULL, _gloffset_GetRenderbufferParameterivEXT),
+ NAME_FUNC_OFFSET(13699, glIsFramebufferEXT, glIsFramebufferEXT, NULL, _gloffset_IsFramebufferEXT),
+ NAME_FUNC_OFFSET(13718, glIsRenderbufferEXT, glIsRenderbufferEXT, NULL, _gloffset_IsRenderbufferEXT),
+ NAME_FUNC_OFFSET(13738, glRenderbufferStorageEXT, glRenderbufferStorageEXT, NULL, _gloffset_RenderbufferStorageEXT),
+ NAME_FUNC_OFFSET(13763, gl_dispatch_stub_783, gl_dispatch_stub_783, NULL, _gloffset_BlitFramebufferEXT),
+ NAME_FUNC_OFFSET(13784, gl_dispatch_stub_784, gl_dispatch_stub_784, NULL, _gloffset_BufferParameteriAPPLE),
+ NAME_FUNC_OFFSET(13808, gl_dispatch_stub_785, gl_dispatch_stub_785, NULL, _gloffset_FlushMappedBufferRangeAPPLE),
+ NAME_FUNC_OFFSET(13838, glFramebufferTextureLayerEXT, glFramebufferTextureLayerEXT, NULL, _gloffset_FramebufferTextureLayerEXT),
+ NAME_FUNC_OFFSET(13867, glProvokingVertexEXT, glProvokingVertexEXT, NULL, _gloffset_ProvokingVertexEXT),
+ NAME_FUNC_OFFSET(13888, gl_dispatch_stub_788, gl_dispatch_stub_788, NULL, _gloffset_GetTexParameterPointervAPPLE),
+ NAME_FUNC_OFFSET(13919, gl_dispatch_stub_789, gl_dispatch_stub_789, NULL, _gloffset_TextureRangeAPPLE),
+ NAME_FUNC_OFFSET(13939, gl_dispatch_stub_790, gl_dispatch_stub_790, NULL, _gloffset_StencilFuncSeparateATI),
+ NAME_FUNC_OFFSET(13964, gl_dispatch_stub_791, gl_dispatch_stub_791, NULL, _gloffset_ProgramEnvParameters4fvEXT),
+ NAME_FUNC_OFFSET(13993, gl_dispatch_stub_792, gl_dispatch_stub_792, NULL, _gloffset_ProgramLocalParameters4fvEXT),
+ NAME_FUNC_OFFSET(14024, gl_dispatch_stub_793, gl_dispatch_stub_793, NULL, _gloffset_GetQueryObjecti64vEXT),
+ NAME_FUNC_OFFSET(14048, gl_dispatch_stub_794, gl_dispatch_stub_794, NULL, _gloffset_GetQueryObjectui64vEXT),
+ NAME_FUNC_OFFSET(14073, glArrayElement, glArrayElement, NULL, _gloffset_ArrayElement),
+ NAME_FUNC_OFFSET(14091, glBindTexture, glBindTexture, NULL, _gloffset_BindTexture),
+ NAME_FUNC_OFFSET(14108, glDrawArrays, glDrawArrays, NULL, _gloffset_DrawArrays),
+ NAME_FUNC_OFFSET(14124, glAreTexturesResident, glAreTexturesResidentEXT, glAreTexturesResidentEXT, _gloffset_AreTexturesResident),
+ NAME_FUNC_OFFSET(14149, glCopyTexImage1D, glCopyTexImage1D, NULL, _gloffset_CopyTexImage1D),
+ NAME_FUNC_OFFSET(14169, glCopyTexImage2D, glCopyTexImage2D, NULL, _gloffset_CopyTexImage2D),
+ NAME_FUNC_OFFSET(14189, glCopyTexSubImage1D, glCopyTexSubImage1D, NULL, _gloffset_CopyTexSubImage1D),
+ NAME_FUNC_OFFSET(14212, glCopyTexSubImage2D, glCopyTexSubImage2D, NULL, _gloffset_CopyTexSubImage2D),
+ NAME_FUNC_OFFSET(14235, glDeleteTextures, glDeleteTexturesEXT, glDeleteTexturesEXT, _gloffset_DeleteTextures),
+ NAME_FUNC_OFFSET(14255, glGenTextures, glGenTexturesEXT, glGenTexturesEXT, _gloffset_GenTextures),
+ NAME_FUNC_OFFSET(14272, glGetPointerv, glGetPointerv, NULL, _gloffset_GetPointerv),
+ NAME_FUNC_OFFSET(14289, glIsTexture, glIsTextureEXT, glIsTextureEXT, _gloffset_IsTexture),
+ NAME_FUNC_OFFSET(14304, glPrioritizeTextures, glPrioritizeTextures, NULL, _gloffset_PrioritizeTextures),
+ NAME_FUNC_OFFSET(14328, glTexSubImage1D, glTexSubImage1D, NULL, _gloffset_TexSubImage1D),
+ NAME_FUNC_OFFSET(14347, glTexSubImage2D, glTexSubImage2D, NULL, _gloffset_TexSubImage2D),
+ NAME_FUNC_OFFSET(14366, glBlendColor, glBlendColor, NULL, _gloffset_BlendColor),
+ NAME_FUNC_OFFSET(14382, glBlendEquation, glBlendEquation, NULL, _gloffset_BlendEquation),
+ NAME_FUNC_OFFSET(14401, glDrawRangeElements, glDrawRangeElements, NULL, _gloffset_DrawRangeElements),
+ NAME_FUNC_OFFSET(14424, glColorTable, glColorTable, NULL, _gloffset_ColorTable),
+ NAME_FUNC_OFFSET(14440, glColorTable, glColorTable, NULL, _gloffset_ColorTable),
+ NAME_FUNC_OFFSET(14456, glColorTableParameterfv, glColorTableParameterfv, NULL, _gloffset_ColorTableParameterfv),
+ NAME_FUNC_OFFSET(14483, glColorTableParameteriv, glColorTableParameteriv, NULL, _gloffset_ColorTableParameteriv),
+ NAME_FUNC_OFFSET(14510, glCopyColorTable, glCopyColorTable, NULL, _gloffset_CopyColorTable),
+ NAME_FUNC_OFFSET(14530, glGetColorTable, glGetColorTableEXT, glGetColorTableEXT, _gloffset_GetColorTable),
+ NAME_FUNC_OFFSET(14549, glGetColorTable, glGetColorTableEXT, glGetColorTableEXT, _gloffset_GetColorTable),
+ NAME_FUNC_OFFSET(14568, glGetColorTableParameterfv, glGetColorTableParameterfvEXT, glGetColorTableParameterfvEXT, _gloffset_GetColorTableParameterfv),
+ NAME_FUNC_OFFSET(14598, glGetColorTableParameterfv, glGetColorTableParameterfvEXT, glGetColorTableParameterfvEXT, _gloffset_GetColorTableParameterfv),
+ NAME_FUNC_OFFSET(14628, glGetColorTableParameteriv, glGetColorTableParameterivEXT, glGetColorTableParameterivEXT, _gloffset_GetColorTableParameteriv),
+ NAME_FUNC_OFFSET(14658, glGetColorTableParameteriv, glGetColorTableParameterivEXT, glGetColorTableParameterivEXT, _gloffset_GetColorTableParameteriv),
+ NAME_FUNC_OFFSET(14688, glColorSubTable, glColorSubTable, NULL, _gloffset_ColorSubTable),
+ NAME_FUNC_OFFSET(14707, glCopyColorSubTable, glCopyColorSubTable, NULL, _gloffset_CopyColorSubTable),
+ NAME_FUNC_OFFSET(14730, glConvolutionFilter1D, glConvolutionFilter1D, NULL, _gloffset_ConvolutionFilter1D),
+ NAME_FUNC_OFFSET(14755, glConvolutionFilter2D, glConvolutionFilter2D, NULL, _gloffset_ConvolutionFilter2D),
+ NAME_FUNC_OFFSET(14780, glConvolutionParameterf, glConvolutionParameterf, NULL, _gloffset_ConvolutionParameterf),
+ NAME_FUNC_OFFSET(14807, glConvolutionParameterfv, glConvolutionParameterfv, NULL, _gloffset_ConvolutionParameterfv),
+ NAME_FUNC_OFFSET(14835, glConvolutionParameteri, glConvolutionParameteri, NULL, _gloffset_ConvolutionParameteri),
+ NAME_FUNC_OFFSET(14862, glConvolutionParameteriv, glConvolutionParameteriv, NULL, _gloffset_ConvolutionParameteriv),
+ NAME_FUNC_OFFSET(14890, glCopyConvolutionFilter1D, glCopyConvolutionFilter1D, NULL, _gloffset_CopyConvolutionFilter1D),
+ NAME_FUNC_OFFSET(14919, glCopyConvolutionFilter2D, glCopyConvolutionFilter2D, NULL, _gloffset_CopyConvolutionFilter2D),
+ NAME_FUNC_OFFSET(14948, glGetConvolutionFilter, gl_dispatch_stub_356, gl_dispatch_stub_356, _gloffset_GetConvolutionFilter),
+ NAME_FUNC_OFFSET(14974, glGetConvolutionParameterfv, gl_dispatch_stub_357, gl_dispatch_stub_357, _gloffset_GetConvolutionParameterfv),
+ NAME_FUNC_OFFSET(15005, glGetConvolutionParameteriv, gl_dispatch_stub_358, gl_dispatch_stub_358, _gloffset_GetConvolutionParameteriv),
+ NAME_FUNC_OFFSET(15036, glGetSeparableFilter, gl_dispatch_stub_359, gl_dispatch_stub_359, _gloffset_GetSeparableFilter),
+ NAME_FUNC_OFFSET(15060, glSeparableFilter2D, glSeparableFilter2D, NULL, _gloffset_SeparableFilter2D),
+ NAME_FUNC_OFFSET(15083, glGetHistogram, gl_dispatch_stub_361, gl_dispatch_stub_361, _gloffset_GetHistogram),
+ NAME_FUNC_OFFSET(15101, glGetHistogramParameterfv, gl_dispatch_stub_362, gl_dispatch_stub_362, _gloffset_GetHistogramParameterfv),
+ NAME_FUNC_OFFSET(15130, glGetHistogramParameteriv, gl_dispatch_stub_363, gl_dispatch_stub_363, _gloffset_GetHistogramParameteriv),
+ NAME_FUNC_OFFSET(15159, glGetMinmax, gl_dispatch_stub_364, gl_dispatch_stub_364, _gloffset_GetMinmax),
+ NAME_FUNC_OFFSET(15174, glGetMinmaxParameterfv, gl_dispatch_stub_365, gl_dispatch_stub_365, _gloffset_GetMinmaxParameterfv),
+ NAME_FUNC_OFFSET(15200, glGetMinmaxParameteriv, gl_dispatch_stub_366, gl_dispatch_stub_366, _gloffset_GetMinmaxParameteriv),
+ NAME_FUNC_OFFSET(15226, glHistogram, glHistogram, NULL, _gloffset_Histogram),
+ NAME_FUNC_OFFSET(15241, glMinmax, glMinmax, NULL, _gloffset_Minmax),
+ NAME_FUNC_OFFSET(15253, glResetHistogram, glResetHistogram, NULL, _gloffset_ResetHistogram),
+ NAME_FUNC_OFFSET(15273, glResetMinmax, glResetMinmax, NULL, _gloffset_ResetMinmax),
+ NAME_FUNC_OFFSET(15290, glTexImage3D, glTexImage3D, NULL, _gloffset_TexImage3D),
+ NAME_FUNC_OFFSET(15306, glTexSubImage3D, glTexSubImage3D, NULL, _gloffset_TexSubImage3D),
+ NAME_FUNC_OFFSET(15325, glCopyTexSubImage3D, glCopyTexSubImage3D, NULL, _gloffset_CopyTexSubImage3D),
+ NAME_FUNC_OFFSET(15348, glActiveTextureARB, glActiveTextureARB, NULL, _gloffset_ActiveTextureARB),
+ NAME_FUNC_OFFSET(15364, glClientActiveTextureARB, glClientActiveTextureARB, NULL, _gloffset_ClientActiveTextureARB),
+ NAME_FUNC_OFFSET(15386, glMultiTexCoord1dARB, glMultiTexCoord1dARB, NULL, _gloffset_MultiTexCoord1dARB),
+ NAME_FUNC_OFFSET(15404, glMultiTexCoord1dvARB, glMultiTexCoord1dvARB, NULL, _gloffset_MultiTexCoord1dvARB),
+ NAME_FUNC_OFFSET(15423, glMultiTexCoord1fARB, glMultiTexCoord1fARB, NULL, _gloffset_MultiTexCoord1fARB),
+ NAME_FUNC_OFFSET(15441, glMultiTexCoord1fvARB, glMultiTexCoord1fvARB, NULL, _gloffset_MultiTexCoord1fvARB),
+ NAME_FUNC_OFFSET(15460, glMultiTexCoord1iARB, glMultiTexCoord1iARB, NULL, _gloffset_MultiTexCoord1iARB),
+ NAME_FUNC_OFFSET(15478, glMultiTexCoord1ivARB, glMultiTexCoord1ivARB, NULL, _gloffset_MultiTexCoord1ivARB),
+ NAME_FUNC_OFFSET(15497, glMultiTexCoord1sARB, glMultiTexCoord1sARB, NULL, _gloffset_MultiTexCoord1sARB),
+ NAME_FUNC_OFFSET(15515, glMultiTexCoord1svARB, glMultiTexCoord1svARB, NULL, _gloffset_MultiTexCoord1svARB),
+ NAME_FUNC_OFFSET(15534, glMultiTexCoord2dARB, glMultiTexCoord2dARB, NULL, _gloffset_MultiTexCoord2dARB),
+ NAME_FUNC_OFFSET(15552, glMultiTexCoord2dvARB, glMultiTexCoord2dvARB, NULL, _gloffset_MultiTexCoord2dvARB),
+ NAME_FUNC_OFFSET(15571, glMultiTexCoord2fARB, glMultiTexCoord2fARB, NULL, _gloffset_MultiTexCoord2fARB),
+ NAME_FUNC_OFFSET(15589, glMultiTexCoord2fvARB, glMultiTexCoord2fvARB, NULL, _gloffset_MultiTexCoord2fvARB),
+ NAME_FUNC_OFFSET(15608, glMultiTexCoord2iARB, glMultiTexCoord2iARB, NULL, _gloffset_MultiTexCoord2iARB),
+ NAME_FUNC_OFFSET(15626, glMultiTexCoord2ivARB, glMultiTexCoord2ivARB, NULL, _gloffset_MultiTexCoord2ivARB),
+ NAME_FUNC_OFFSET(15645, glMultiTexCoord2sARB, glMultiTexCoord2sARB, NULL, _gloffset_MultiTexCoord2sARB),
+ NAME_FUNC_OFFSET(15663, glMultiTexCoord2svARB, glMultiTexCoord2svARB, NULL, _gloffset_MultiTexCoord2svARB),
+ NAME_FUNC_OFFSET(15682, glMultiTexCoord3dARB, glMultiTexCoord3dARB, NULL, _gloffset_MultiTexCoord3dARB),
+ NAME_FUNC_OFFSET(15700, glMultiTexCoord3dvARB, glMultiTexCoord3dvARB, NULL, _gloffset_MultiTexCoord3dvARB),
+ NAME_FUNC_OFFSET(15719, glMultiTexCoord3fARB, glMultiTexCoord3fARB, NULL, _gloffset_MultiTexCoord3fARB),
+ NAME_FUNC_OFFSET(15737, glMultiTexCoord3fvARB, glMultiTexCoord3fvARB, NULL, _gloffset_MultiTexCoord3fvARB),
+ NAME_FUNC_OFFSET(15756, glMultiTexCoord3iARB, glMultiTexCoord3iARB, NULL, _gloffset_MultiTexCoord3iARB),
+ NAME_FUNC_OFFSET(15774, glMultiTexCoord3ivARB, glMultiTexCoord3ivARB, NULL, _gloffset_MultiTexCoord3ivARB),
+ NAME_FUNC_OFFSET(15793, glMultiTexCoord3sARB, glMultiTexCoord3sARB, NULL, _gloffset_MultiTexCoord3sARB),
+ NAME_FUNC_OFFSET(15811, glMultiTexCoord3svARB, glMultiTexCoord3svARB, NULL, _gloffset_MultiTexCoord3svARB),
+ NAME_FUNC_OFFSET(15830, glMultiTexCoord4dARB, glMultiTexCoord4dARB, NULL, _gloffset_MultiTexCoord4dARB),
+ NAME_FUNC_OFFSET(15848, glMultiTexCoord4dvARB, glMultiTexCoord4dvARB, NULL, _gloffset_MultiTexCoord4dvARB),
+ NAME_FUNC_OFFSET(15867, glMultiTexCoord4fARB, glMultiTexCoord4fARB, NULL, _gloffset_MultiTexCoord4fARB),
+ NAME_FUNC_OFFSET(15885, glMultiTexCoord4fvARB, glMultiTexCoord4fvARB, NULL, _gloffset_MultiTexCoord4fvARB),
+ NAME_FUNC_OFFSET(15904, glMultiTexCoord4iARB, glMultiTexCoord4iARB, NULL, _gloffset_MultiTexCoord4iARB),
+ NAME_FUNC_OFFSET(15922, glMultiTexCoord4ivARB, glMultiTexCoord4ivARB, NULL, _gloffset_MultiTexCoord4ivARB),
+ NAME_FUNC_OFFSET(15941, glMultiTexCoord4sARB, glMultiTexCoord4sARB, NULL, _gloffset_MultiTexCoord4sARB),
+ NAME_FUNC_OFFSET(15959, glMultiTexCoord4svARB, glMultiTexCoord4svARB, NULL, _gloffset_MultiTexCoord4svARB),
+ NAME_FUNC_OFFSET(15978, glStencilOpSeparate, glStencilOpSeparate, NULL, _gloffset_StencilOpSeparate),
+ NAME_FUNC_OFFSET(16001, glLoadTransposeMatrixdARB, glLoadTransposeMatrixdARB, NULL, _gloffset_LoadTransposeMatrixdARB),
+ NAME_FUNC_OFFSET(16024, glLoadTransposeMatrixfARB, glLoadTransposeMatrixfARB, NULL, _gloffset_LoadTransposeMatrixfARB),
+ NAME_FUNC_OFFSET(16047, glMultTransposeMatrixdARB, glMultTransposeMatrixdARB, NULL, _gloffset_MultTransposeMatrixdARB),
+ NAME_FUNC_OFFSET(16070, glMultTransposeMatrixfARB, glMultTransposeMatrixfARB, NULL, _gloffset_MultTransposeMatrixfARB),
+ NAME_FUNC_OFFSET(16093, glSampleCoverageARB, glSampleCoverageARB, NULL, _gloffset_SampleCoverageARB),
+ NAME_FUNC_OFFSET(16110, glCompressedTexImage1DARB, glCompressedTexImage1DARB, NULL, _gloffset_CompressedTexImage1DARB),
+ NAME_FUNC_OFFSET(16133, glCompressedTexImage2DARB, glCompressedTexImage2DARB, NULL, _gloffset_CompressedTexImage2DARB),
+ NAME_FUNC_OFFSET(16156, glCompressedTexImage3DARB, glCompressedTexImage3DARB, NULL, _gloffset_CompressedTexImage3DARB),
+ NAME_FUNC_OFFSET(16179, glCompressedTexSubImage1DARB, glCompressedTexSubImage1DARB, NULL, _gloffset_CompressedTexSubImage1DARB),
+ NAME_FUNC_OFFSET(16205, glCompressedTexSubImage2DARB, glCompressedTexSubImage2DARB, NULL, _gloffset_CompressedTexSubImage2DARB),
+ NAME_FUNC_OFFSET(16231, glCompressedTexSubImage3DARB, glCompressedTexSubImage3DARB, NULL, _gloffset_CompressedTexSubImage3DARB),
+ NAME_FUNC_OFFSET(16257, glGetCompressedTexImageARB, glGetCompressedTexImageARB, NULL, _gloffset_GetCompressedTexImageARB),
+ NAME_FUNC_OFFSET(16281, glDisableVertexAttribArrayARB, glDisableVertexAttribArrayARB, NULL, _gloffset_DisableVertexAttribArrayARB),
+ NAME_FUNC_OFFSET(16308, glEnableVertexAttribArrayARB, glEnableVertexAttribArrayARB, NULL, _gloffset_EnableVertexAttribArrayARB),
+ NAME_FUNC_OFFSET(16334, glGetVertexAttribdvARB, glGetVertexAttribdvARB, NULL, _gloffset_GetVertexAttribdvARB),
+ NAME_FUNC_OFFSET(16354, glGetVertexAttribfvARB, glGetVertexAttribfvARB, NULL, _gloffset_GetVertexAttribfvARB),
+ NAME_FUNC_OFFSET(16374, glGetVertexAttribivARB, glGetVertexAttribivARB, NULL, _gloffset_GetVertexAttribivARB),
+ NAME_FUNC_OFFSET(16394, glProgramEnvParameter4dARB, glProgramEnvParameter4dARB, NULL, _gloffset_ProgramEnvParameter4dARB),
+ NAME_FUNC_OFFSET(16417, glProgramEnvParameter4dvARB, glProgramEnvParameter4dvARB, NULL, _gloffset_ProgramEnvParameter4dvARB),
+ NAME_FUNC_OFFSET(16441, glProgramEnvParameter4fARB, glProgramEnvParameter4fARB, NULL, _gloffset_ProgramEnvParameter4fARB),
+ NAME_FUNC_OFFSET(16464, glProgramEnvParameter4fvARB, glProgramEnvParameter4fvARB, NULL, _gloffset_ProgramEnvParameter4fvARB),
+ NAME_FUNC_OFFSET(16488, glVertexAttrib1dARB, glVertexAttrib1dARB, NULL, _gloffset_VertexAttrib1dARB),
+ NAME_FUNC_OFFSET(16505, glVertexAttrib1dvARB, glVertexAttrib1dvARB, NULL, _gloffset_VertexAttrib1dvARB),
+ NAME_FUNC_OFFSET(16523, glVertexAttrib1fARB, glVertexAttrib1fARB, NULL, _gloffset_VertexAttrib1fARB),
+ NAME_FUNC_OFFSET(16540, glVertexAttrib1fvARB, glVertexAttrib1fvARB, NULL, _gloffset_VertexAttrib1fvARB),
+ NAME_FUNC_OFFSET(16558, glVertexAttrib1sARB, glVertexAttrib1sARB, NULL, _gloffset_VertexAttrib1sARB),
+ NAME_FUNC_OFFSET(16575, glVertexAttrib1svARB, glVertexAttrib1svARB, NULL, _gloffset_VertexAttrib1svARB),
+ NAME_FUNC_OFFSET(16593, glVertexAttrib2dARB, glVertexAttrib2dARB, NULL, _gloffset_VertexAttrib2dARB),
+ NAME_FUNC_OFFSET(16610, glVertexAttrib2dvARB, glVertexAttrib2dvARB, NULL, _gloffset_VertexAttrib2dvARB),
+ NAME_FUNC_OFFSET(16628, glVertexAttrib2fARB, glVertexAttrib2fARB, NULL, _gloffset_VertexAttrib2fARB),
+ NAME_FUNC_OFFSET(16645, glVertexAttrib2fvARB, glVertexAttrib2fvARB, NULL, _gloffset_VertexAttrib2fvARB),
+ NAME_FUNC_OFFSET(16663, glVertexAttrib2sARB, glVertexAttrib2sARB, NULL, _gloffset_VertexAttrib2sARB),
+ NAME_FUNC_OFFSET(16680, glVertexAttrib2svARB, glVertexAttrib2svARB, NULL, _gloffset_VertexAttrib2svARB),
+ NAME_FUNC_OFFSET(16698, glVertexAttrib3dARB, glVertexAttrib3dARB, NULL, _gloffset_VertexAttrib3dARB),
+ NAME_FUNC_OFFSET(16715, glVertexAttrib3dvARB, glVertexAttrib3dvARB, NULL, _gloffset_VertexAttrib3dvARB),
+ NAME_FUNC_OFFSET(16733, glVertexAttrib3fARB, glVertexAttrib3fARB, NULL, _gloffset_VertexAttrib3fARB),
+ NAME_FUNC_OFFSET(16750, glVertexAttrib3fvARB, glVertexAttrib3fvARB, NULL, _gloffset_VertexAttrib3fvARB),
+ NAME_FUNC_OFFSET(16768, glVertexAttrib3sARB, glVertexAttrib3sARB, NULL, _gloffset_VertexAttrib3sARB),
+ NAME_FUNC_OFFSET(16785, glVertexAttrib3svARB, glVertexAttrib3svARB, NULL, _gloffset_VertexAttrib3svARB),
+ NAME_FUNC_OFFSET(16803, glVertexAttrib4NbvARB, glVertexAttrib4NbvARB, NULL, _gloffset_VertexAttrib4NbvARB),
+ NAME_FUNC_OFFSET(16822, glVertexAttrib4NivARB, glVertexAttrib4NivARB, NULL, _gloffset_VertexAttrib4NivARB),
+ NAME_FUNC_OFFSET(16841, glVertexAttrib4NsvARB, glVertexAttrib4NsvARB, NULL, _gloffset_VertexAttrib4NsvARB),
+ NAME_FUNC_OFFSET(16860, glVertexAttrib4NubARB, glVertexAttrib4NubARB, NULL, _gloffset_VertexAttrib4NubARB),
+ NAME_FUNC_OFFSET(16879, glVertexAttrib4NubvARB, glVertexAttrib4NubvARB, NULL, _gloffset_VertexAttrib4NubvARB),
+ NAME_FUNC_OFFSET(16899, glVertexAttrib4NuivARB, glVertexAttrib4NuivARB, NULL, _gloffset_VertexAttrib4NuivARB),
+ NAME_FUNC_OFFSET(16919, glVertexAttrib4NusvARB, glVertexAttrib4NusvARB, NULL, _gloffset_VertexAttrib4NusvARB),
+ NAME_FUNC_OFFSET(16939, glVertexAttrib4bvARB, glVertexAttrib4bvARB, NULL, _gloffset_VertexAttrib4bvARB),
+ NAME_FUNC_OFFSET(16957, glVertexAttrib4dARB, glVertexAttrib4dARB, NULL, _gloffset_VertexAttrib4dARB),
+ NAME_FUNC_OFFSET(16974, glVertexAttrib4dvARB, glVertexAttrib4dvARB, NULL, _gloffset_VertexAttrib4dvARB),
+ NAME_FUNC_OFFSET(16992, glVertexAttrib4fARB, glVertexAttrib4fARB, NULL, _gloffset_VertexAttrib4fARB),
+ NAME_FUNC_OFFSET(17009, glVertexAttrib4fvARB, glVertexAttrib4fvARB, NULL, _gloffset_VertexAttrib4fvARB),
+ NAME_FUNC_OFFSET(17027, glVertexAttrib4ivARB, glVertexAttrib4ivARB, NULL, _gloffset_VertexAttrib4ivARB),
+ NAME_FUNC_OFFSET(17045, glVertexAttrib4sARB, glVertexAttrib4sARB, NULL, _gloffset_VertexAttrib4sARB),
+ NAME_FUNC_OFFSET(17062, glVertexAttrib4svARB, glVertexAttrib4svARB, NULL, _gloffset_VertexAttrib4svARB),
+ NAME_FUNC_OFFSET(17080, glVertexAttrib4ubvARB, glVertexAttrib4ubvARB, NULL, _gloffset_VertexAttrib4ubvARB),
+ NAME_FUNC_OFFSET(17099, glVertexAttrib4uivARB, glVertexAttrib4uivARB, NULL, _gloffset_VertexAttrib4uivARB),
+ NAME_FUNC_OFFSET(17118, glVertexAttrib4usvARB, glVertexAttrib4usvARB, NULL, _gloffset_VertexAttrib4usvARB),
+ NAME_FUNC_OFFSET(17137, glVertexAttribPointerARB, glVertexAttribPointerARB, NULL, _gloffset_VertexAttribPointerARB),
+ NAME_FUNC_OFFSET(17159, glBindBufferARB, glBindBufferARB, NULL, _gloffset_BindBufferARB),
+ NAME_FUNC_OFFSET(17172, glBufferDataARB, glBufferDataARB, NULL, _gloffset_BufferDataARB),
+ NAME_FUNC_OFFSET(17185, glBufferSubDataARB, glBufferSubDataARB, NULL, _gloffset_BufferSubDataARB),
+ NAME_FUNC_OFFSET(17201, glDeleteBuffersARB, glDeleteBuffersARB, NULL, _gloffset_DeleteBuffersARB),
+ NAME_FUNC_OFFSET(17217, glGenBuffersARB, glGenBuffersARB, NULL, _gloffset_GenBuffersARB),
+ NAME_FUNC_OFFSET(17230, glGetBufferParameterivARB, glGetBufferParameterivARB, NULL, _gloffset_GetBufferParameterivARB),
+ NAME_FUNC_OFFSET(17253, glGetBufferPointervARB, glGetBufferPointervARB, NULL, _gloffset_GetBufferPointervARB),
+ NAME_FUNC_OFFSET(17273, glGetBufferSubDataARB, glGetBufferSubDataARB, NULL, _gloffset_GetBufferSubDataARB),
+ NAME_FUNC_OFFSET(17292, glIsBufferARB, glIsBufferARB, NULL, _gloffset_IsBufferARB),
+ NAME_FUNC_OFFSET(17303, glMapBufferARB, glMapBufferARB, NULL, _gloffset_MapBufferARB),
+ NAME_FUNC_OFFSET(17315, glUnmapBufferARB, glUnmapBufferARB, NULL, _gloffset_UnmapBufferARB),
+ NAME_FUNC_OFFSET(17329, glBeginQueryARB, glBeginQueryARB, NULL, _gloffset_BeginQueryARB),
+ NAME_FUNC_OFFSET(17342, glDeleteQueriesARB, glDeleteQueriesARB, NULL, _gloffset_DeleteQueriesARB),
+ NAME_FUNC_OFFSET(17358, glEndQueryARB, glEndQueryARB, NULL, _gloffset_EndQueryARB),
+ NAME_FUNC_OFFSET(17369, glGenQueriesARB, glGenQueriesARB, NULL, _gloffset_GenQueriesARB),
+ NAME_FUNC_OFFSET(17382, glGetQueryObjectivARB, glGetQueryObjectivARB, NULL, _gloffset_GetQueryObjectivARB),
+ NAME_FUNC_OFFSET(17401, glGetQueryObjectuivARB, glGetQueryObjectuivARB, NULL, _gloffset_GetQueryObjectuivARB),
+ NAME_FUNC_OFFSET(17421, glGetQueryivARB, glGetQueryivARB, NULL, _gloffset_GetQueryivARB),
+ NAME_FUNC_OFFSET(17434, glIsQueryARB, glIsQueryARB, NULL, _gloffset_IsQueryARB),
+ NAME_FUNC_OFFSET(17444, glCompileShaderARB, glCompileShaderARB, NULL, _gloffset_CompileShaderARB),
+ NAME_FUNC_OFFSET(17460, glGetActiveUniformARB, glGetActiveUniformARB, NULL, _gloffset_GetActiveUniformARB),
+ NAME_FUNC_OFFSET(17479, glGetShaderSourceARB, glGetShaderSourceARB, NULL, _gloffset_GetShaderSourceARB),
+ NAME_FUNC_OFFSET(17497, glGetUniformLocationARB, glGetUniformLocationARB, NULL, _gloffset_GetUniformLocationARB),
+ NAME_FUNC_OFFSET(17518, glGetUniformfvARB, glGetUniformfvARB, NULL, _gloffset_GetUniformfvARB),
+ NAME_FUNC_OFFSET(17533, glGetUniformivARB, glGetUniformivARB, NULL, _gloffset_GetUniformivARB),
+ NAME_FUNC_OFFSET(17548, glLinkProgramARB, glLinkProgramARB, NULL, _gloffset_LinkProgramARB),
+ NAME_FUNC_OFFSET(17562, glShaderSourceARB, glShaderSourceARB, NULL, _gloffset_ShaderSourceARB),
+ NAME_FUNC_OFFSET(17577, glUniform1fARB, glUniform1fARB, NULL, _gloffset_Uniform1fARB),
+ NAME_FUNC_OFFSET(17589, glUniform1fvARB, glUniform1fvARB, NULL, _gloffset_Uniform1fvARB),
+ NAME_FUNC_OFFSET(17602, glUniform1iARB, glUniform1iARB, NULL, _gloffset_Uniform1iARB),
+ NAME_FUNC_OFFSET(17614, glUniform1ivARB, glUniform1ivARB, NULL, _gloffset_Uniform1ivARB),
+ NAME_FUNC_OFFSET(17627, glUniform2fARB, glUniform2fARB, NULL, _gloffset_Uniform2fARB),
+ NAME_FUNC_OFFSET(17639, glUniform2fvARB, glUniform2fvARB, NULL, _gloffset_Uniform2fvARB),
+ NAME_FUNC_OFFSET(17652, glUniform2iARB, glUniform2iARB, NULL, _gloffset_Uniform2iARB),
+ NAME_FUNC_OFFSET(17664, glUniform2ivARB, glUniform2ivARB, NULL, _gloffset_Uniform2ivARB),
+ NAME_FUNC_OFFSET(17677, glUniform3fARB, glUniform3fARB, NULL, _gloffset_Uniform3fARB),
+ NAME_FUNC_OFFSET(17689, glUniform3fvARB, glUniform3fvARB, NULL, _gloffset_Uniform3fvARB),
+ NAME_FUNC_OFFSET(17702, glUniform3iARB, glUniform3iARB, NULL, _gloffset_Uniform3iARB),
+ NAME_FUNC_OFFSET(17714, glUniform3ivARB, glUniform3ivARB, NULL, _gloffset_Uniform3ivARB),
+ NAME_FUNC_OFFSET(17727, glUniform4fARB, glUniform4fARB, NULL, _gloffset_Uniform4fARB),
+ NAME_FUNC_OFFSET(17739, glUniform4fvARB, glUniform4fvARB, NULL, _gloffset_Uniform4fvARB),
+ NAME_FUNC_OFFSET(17752, glUniform4iARB, glUniform4iARB, NULL, _gloffset_Uniform4iARB),
+ NAME_FUNC_OFFSET(17764, glUniform4ivARB, glUniform4ivARB, NULL, _gloffset_Uniform4ivARB),
+ NAME_FUNC_OFFSET(17777, glUniformMatrix2fvARB, glUniformMatrix2fvARB, NULL, _gloffset_UniformMatrix2fvARB),
+ NAME_FUNC_OFFSET(17796, glUniformMatrix3fvARB, glUniformMatrix3fvARB, NULL, _gloffset_UniformMatrix3fvARB),
+ NAME_FUNC_OFFSET(17815, glUniformMatrix4fvARB, glUniformMatrix4fvARB, NULL, _gloffset_UniformMatrix4fvARB),
+ NAME_FUNC_OFFSET(17834, glUseProgramObjectARB, glUseProgramObjectARB, NULL, _gloffset_UseProgramObjectARB),
+ NAME_FUNC_OFFSET(17847, glValidateProgramARB, glValidateProgramARB, NULL, _gloffset_ValidateProgramARB),
+ NAME_FUNC_OFFSET(17865, glBindAttribLocationARB, glBindAttribLocationARB, NULL, _gloffset_BindAttribLocationARB),
+ NAME_FUNC_OFFSET(17886, glGetActiveAttribARB, glGetActiveAttribARB, NULL, _gloffset_GetActiveAttribARB),
+ NAME_FUNC_OFFSET(17904, glGetAttribLocationARB, glGetAttribLocationARB, NULL, _gloffset_GetAttribLocationARB),
+ NAME_FUNC_OFFSET(17924, glDrawBuffersARB, glDrawBuffersARB, NULL, _gloffset_DrawBuffersARB),
+ NAME_FUNC_OFFSET(17938, glDrawBuffersARB, glDrawBuffersARB, NULL, _gloffset_DrawBuffersARB),
+ NAME_FUNC_OFFSET(17955, gl_dispatch_stub_584, gl_dispatch_stub_584, NULL, _gloffset_SampleMaskSGIS),
+ NAME_FUNC_OFFSET(17971, gl_dispatch_stub_585, gl_dispatch_stub_585, NULL, _gloffset_SamplePatternSGIS),
+ NAME_FUNC_OFFSET(17990, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
+ NAME_FUNC_OFFSET(18008, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
+ NAME_FUNC_OFFSET(18029, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
+ NAME_FUNC_OFFSET(18051, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
+ NAME_FUNC_OFFSET(18070, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
+ NAME_FUNC_OFFSET(18092, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
+ NAME_FUNC_OFFSET(18115, glSecondaryColor3bEXT, glSecondaryColor3bEXT, NULL, _gloffset_SecondaryColor3bEXT),
+ NAME_FUNC_OFFSET(18134, glSecondaryColor3bvEXT, glSecondaryColor3bvEXT, NULL, _gloffset_SecondaryColor3bvEXT),
+ NAME_FUNC_OFFSET(18154, glSecondaryColor3dEXT, glSecondaryColor3dEXT, NULL, _gloffset_SecondaryColor3dEXT),
+ NAME_FUNC_OFFSET(18173, glSecondaryColor3dvEXT, glSecondaryColor3dvEXT, NULL, _gloffset_SecondaryColor3dvEXT),
+ NAME_FUNC_OFFSET(18193, glSecondaryColor3fEXT, glSecondaryColor3fEXT, NULL, _gloffset_SecondaryColor3fEXT),
+ NAME_FUNC_OFFSET(18212, glSecondaryColor3fvEXT, glSecondaryColor3fvEXT, NULL, _gloffset_SecondaryColor3fvEXT),
+ NAME_FUNC_OFFSET(18232, glSecondaryColor3iEXT, glSecondaryColor3iEXT, NULL, _gloffset_SecondaryColor3iEXT),
+ NAME_FUNC_OFFSET(18251, glSecondaryColor3ivEXT, glSecondaryColor3ivEXT, NULL, _gloffset_SecondaryColor3ivEXT),
+ NAME_FUNC_OFFSET(18271, glSecondaryColor3sEXT, glSecondaryColor3sEXT, NULL, _gloffset_SecondaryColor3sEXT),
+ NAME_FUNC_OFFSET(18290, glSecondaryColor3svEXT, glSecondaryColor3svEXT, NULL, _gloffset_SecondaryColor3svEXT),
+ NAME_FUNC_OFFSET(18310, glSecondaryColor3ubEXT, glSecondaryColor3ubEXT, NULL, _gloffset_SecondaryColor3ubEXT),
+ NAME_FUNC_OFFSET(18330, glSecondaryColor3ubvEXT, glSecondaryColor3ubvEXT, NULL, _gloffset_SecondaryColor3ubvEXT),
+ NAME_FUNC_OFFSET(18351, glSecondaryColor3uiEXT, glSecondaryColor3uiEXT, NULL, _gloffset_SecondaryColor3uiEXT),
+ NAME_FUNC_OFFSET(18371, glSecondaryColor3uivEXT, glSecondaryColor3uivEXT, NULL, _gloffset_SecondaryColor3uivEXT),
+ NAME_FUNC_OFFSET(18392, glSecondaryColor3usEXT, glSecondaryColor3usEXT, NULL, _gloffset_SecondaryColor3usEXT),
+ NAME_FUNC_OFFSET(18412, glSecondaryColor3usvEXT, glSecondaryColor3usvEXT, NULL, _gloffset_SecondaryColor3usvEXT),
+ NAME_FUNC_OFFSET(18433, glSecondaryColorPointerEXT, glSecondaryColorPointerEXT, NULL, _gloffset_SecondaryColorPointerEXT),
+ NAME_FUNC_OFFSET(18457, glMultiDrawArraysEXT, glMultiDrawArraysEXT, NULL, _gloffset_MultiDrawArraysEXT),
+ NAME_FUNC_OFFSET(18475, glMultiDrawElementsEXT, glMultiDrawElementsEXT, NULL, _gloffset_MultiDrawElementsEXT),
+ NAME_FUNC_OFFSET(18495, glFogCoordPointerEXT, glFogCoordPointerEXT, NULL, _gloffset_FogCoordPointerEXT),
+ NAME_FUNC_OFFSET(18513, glFogCoorddEXT, glFogCoorddEXT, NULL, _gloffset_FogCoorddEXT),
+ NAME_FUNC_OFFSET(18525, glFogCoorddvEXT, glFogCoorddvEXT, NULL, _gloffset_FogCoorddvEXT),
+ NAME_FUNC_OFFSET(18538, glFogCoordfEXT, glFogCoordfEXT, NULL, _gloffset_FogCoordfEXT),
+ NAME_FUNC_OFFSET(18550, glFogCoordfvEXT, glFogCoordfvEXT, NULL, _gloffset_FogCoordfvEXT),
+ NAME_FUNC_OFFSET(18563, glBlendFuncSeparateEXT, glBlendFuncSeparateEXT, NULL, _gloffset_BlendFuncSeparateEXT),
+ NAME_FUNC_OFFSET(18583, glBlendFuncSeparateEXT, glBlendFuncSeparateEXT, NULL, _gloffset_BlendFuncSeparateEXT),
+ NAME_FUNC_OFFSET(18607, glWindowPos2dMESA, glWindowPos2dMESA, NULL, _gloffset_WindowPos2dMESA),
+ NAME_FUNC_OFFSET(18621, glWindowPos2dMESA, glWindowPos2dMESA, NULL, _gloffset_WindowPos2dMESA),
+ NAME_FUNC_OFFSET(18638, glWindowPos2dvMESA, glWindowPos2dvMESA, NULL, _gloffset_WindowPos2dvMESA),
+ NAME_FUNC_OFFSET(18653, glWindowPos2dvMESA, glWindowPos2dvMESA, NULL, _gloffset_WindowPos2dvMESA),
+ NAME_FUNC_OFFSET(18671, glWindowPos2fMESA, glWindowPos2fMESA, NULL, _gloffset_WindowPos2fMESA),
+ NAME_FUNC_OFFSET(18685, glWindowPos2fMESA, glWindowPos2fMESA, NULL, _gloffset_WindowPos2fMESA),
+ NAME_FUNC_OFFSET(18702, glWindowPos2fvMESA, glWindowPos2fvMESA, NULL, _gloffset_WindowPos2fvMESA),
+ NAME_FUNC_OFFSET(18717, glWindowPos2fvMESA, glWindowPos2fvMESA, NULL, _gloffset_WindowPos2fvMESA),
+ NAME_FUNC_OFFSET(18735, glWindowPos2iMESA, glWindowPos2iMESA, NULL, _gloffset_WindowPos2iMESA),
+ NAME_FUNC_OFFSET(18749, glWindowPos2iMESA, glWindowPos2iMESA, NULL, _gloffset_WindowPos2iMESA),
+ NAME_FUNC_OFFSET(18766, glWindowPos2ivMESA, glWindowPos2ivMESA, NULL, _gloffset_WindowPos2ivMESA),
+ NAME_FUNC_OFFSET(18781, glWindowPos2ivMESA, glWindowPos2ivMESA, NULL, _gloffset_WindowPos2ivMESA),
+ NAME_FUNC_OFFSET(18799, glWindowPos2sMESA, glWindowPos2sMESA, NULL, _gloffset_WindowPos2sMESA),
+ NAME_FUNC_OFFSET(18813, glWindowPos2sMESA, glWindowPos2sMESA, NULL, _gloffset_WindowPos2sMESA),
+ NAME_FUNC_OFFSET(18830, glWindowPos2svMESA, glWindowPos2svMESA, NULL, _gloffset_WindowPos2svMESA),
+ NAME_FUNC_OFFSET(18845, glWindowPos2svMESA, glWindowPos2svMESA, NULL, _gloffset_WindowPos2svMESA),
+ NAME_FUNC_OFFSET(18863, glWindowPos3dMESA, glWindowPos3dMESA, NULL, _gloffset_WindowPos3dMESA),
+ NAME_FUNC_OFFSET(18877, glWindowPos3dMESA, glWindowPos3dMESA, NULL, _gloffset_WindowPos3dMESA),
+ NAME_FUNC_OFFSET(18894, glWindowPos3dvMESA, glWindowPos3dvMESA, NULL, _gloffset_WindowPos3dvMESA),
+ NAME_FUNC_OFFSET(18909, glWindowPos3dvMESA, glWindowPos3dvMESA, NULL, _gloffset_WindowPos3dvMESA),
+ NAME_FUNC_OFFSET(18927, glWindowPos3fMESA, glWindowPos3fMESA, NULL, _gloffset_WindowPos3fMESA),
+ NAME_FUNC_OFFSET(18941, glWindowPos3fMESA, glWindowPos3fMESA, NULL, _gloffset_WindowPos3fMESA),
+ NAME_FUNC_OFFSET(18958, glWindowPos3fvMESA, glWindowPos3fvMESA, NULL, _gloffset_WindowPos3fvMESA),
+ NAME_FUNC_OFFSET(18973, glWindowPos3fvMESA, glWindowPos3fvMESA, NULL, _gloffset_WindowPos3fvMESA),
+ NAME_FUNC_OFFSET(18991, glWindowPos3iMESA, glWindowPos3iMESA, NULL, _gloffset_WindowPos3iMESA),
+ NAME_FUNC_OFFSET(19005, glWindowPos3iMESA, glWindowPos3iMESA, NULL, _gloffset_WindowPos3iMESA),
+ NAME_FUNC_OFFSET(19022, glWindowPos3ivMESA, glWindowPos3ivMESA, NULL, _gloffset_WindowPos3ivMESA),
+ NAME_FUNC_OFFSET(19037, glWindowPos3ivMESA, glWindowPos3ivMESA, NULL, _gloffset_WindowPos3ivMESA),
+ NAME_FUNC_OFFSET(19055, glWindowPos3sMESA, glWindowPos3sMESA, NULL, _gloffset_WindowPos3sMESA),
+ NAME_FUNC_OFFSET(19069, glWindowPos3sMESA, glWindowPos3sMESA, NULL, _gloffset_WindowPos3sMESA),
+ NAME_FUNC_OFFSET(19086, glWindowPos3svMESA, glWindowPos3svMESA, NULL, _gloffset_WindowPos3svMESA),
+ NAME_FUNC_OFFSET(19101, glWindowPos3svMESA, glWindowPos3svMESA, NULL, _gloffset_WindowPos3svMESA),
+ NAME_FUNC_OFFSET(19119, glBindProgramNV, glBindProgramNV, NULL, _gloffset_BindProgramNV),
+ NAME_FUNC_OFFSET(19136, glDeleteProgramsNV, glDeleteProgramsNV, NULL, _gloffset_DeleteProgramsNV),
+ NAME_FUNC_OFFSET(19156, glGenProgramsNV, glGenProgramsNV, NULL, _gloffset_GenProgramsNV),
+ NAME_FUNC_OFFSET(19173, glGetVertexAttribPointervNV, glGetVertexAttribPointervNV, NULL, _gloffset_GetVertexAttribPointervNV),
+ NAME_FUNC_OFFSET(19199, glGetVertexAttribPointervNV, glGetVertexAttribPointervNV, NULL, _gloffset_GetVertexAttribPointervNV),
+ NAME_FUNC_OFFSET(19228, glIsProgramNV, glIsProgramNV, NULL, _gloffset_IsProgramNV),
+ NAME_FUNC_OFFSET(19243, glPointParameteriNV, glPointParameteriNV, NULL, _gloffset_PointParameteriNV),
+ NAME_FUNC_OFFSET(19261, glPointParameterivNV, glPointParameterivNV, NULL, _gloffset_PointParameterivNV),
+ NAME_FUNC_OFFSET(19280, gl_dispatch_stub_755, gl_dispatch_stub_755, NULL, _gloffset_DeleteVertexArraysAPPLE),
+ NAME_FUNC_OFFSET(19301, gl_dispatch_stub_757, gl_dispatch_stub_757, NULL, _gloffset_IsVertexArrayAPPLE),
+ NAME_FUNC_OFFSET(19317, gl_dispatch_stub_765, gl_dispatch_stub_765, NULL, _gloffset_BlendEquationSeparateEXT),
+ NAME_FUNC_OFFSET(19341, gl_dispatch_stub_765, gl_dispatch_stub_765, NULL, _gloffset_BlendEquationSeparateEXT),
+ NAME_FUNC_OFFSET(19368, glBindFramebufferEXT, glBindFramebufferEXT, NULL, _gloffset_BindFramebufferEXT),
+ NAME_FUNC_OFFSET(19386, glBindRenderbufferEXT, glBindRenderbufferEXT, NULL, _gloffset_BindRenderbufferEXT),
+ NAME_FUNC_OFFSET(19405, glCheckFramebufferStatusEXT, glCheckFramebufferStatusEXT, NULL, _gloffset_CheckFramebufferStatusEXT),
+ NAME_FUNC_OFFSET(19430, glDeleteFramebuffersEXT, glDeleteFramebuffersEXT, NULL, _gloffset_DeleteFramebuffersEXT),
+ NAME_FUNC_OFFSET(19451, glDeleteRenderbuffersEXT, glDeleteRenderbuffersEXT, NULL, _gloffset_DeleteRenderbuffersEXT),
+ NAME_FUNC_OFFSET(19473, glFramebufferRenderbufferEXT, glFramebufferRenderbufferEXT, NULL, _gloffset_FramebufferRenderbufferEXT),
+ NAME_FUNC_OFFSET(19499, glFramebufferTexture1DEXT, glFramebufferTexture1DEXT, NULL, _gloffset_FramebufferTexture1DEXT),
+ NAME_FUNC_OFFSET(19522, glFramebufferTexture2DEXT, glFramebufferTexture2DEXT, NULL, _gloffset_FramebufferTexture2DEXT),
+ NAME_FUNC_OFFSET(19545, glFramebufferTexture3DEXT, glFramebufferTexture3DEXT, NULL, _gloffset_FramebufferTexture3DEXT),
+ NAME_FUNC_OFFSET(19568, glGenFramebuffersEXT, glGenFramebuffersEXT, NULL, _gloffset_GenFramebuffersEXT),
+ NAME_FUNC_OFFSET(19586, glGenRenderbuffersEXT, glGenRenderbuffersEXT, NULL, _gloffset_GenRenderbuffersEXT),
+ NAME_FUNC_OFFSET(19605, glGenerateMipmapEXT, glGenerateMipmapEXT, NULL, _gloffset_GenerateMipmapEXT),
+ NAME_FUNC_OFFSET(19622, glGetFramebufferAttachmentParameterivEXT, glGetFramebufferAttachmentParameterivEXT, NULL, _gloffset_GetFramebufferAttachmentParameterivEXT),
+ NAME_FUNC_OFFSET(19660, glGetRenderbufferParameterivEXT, glGetRenderbufferParameterivEXT, NULL, _gloffset_GetRenderbufferParameterivEXT),
+ NAME_FUNC_OFFSET(19689, glIsFramebufferEXT, glIsFramebufferEXT, NULL, _gloffset_IsFramebufferEXT),
+ NAME_FUNC_OFFSET(19705, glIsRenderbufferEXT, glIsRenderbufferEXT, NULL, _gloffset_IsRenderbufferEXT),
+ NAME_FUNC_OFFSET(19722, glRenderbufferStorageEXT, glRenderbufferStorageEXT, NULL, _gloffset_RenderbufferStorageEXT),
+ NAME_FUNC_OFFSET(19744, gl_dispatch_stub_783, gl_dispatch_stub_783, NULL, _gloffset_BlitFramebufferEXT),
+ NAME_FUNC_OFFSET(19762, glFramebufferTextureLayerEXT, glFramebufferTextureLayerEXT, NULL, _gloffset_FramebufferTextureLayerEXT),
NAME_FUNC_OFFSET(-1, NULL, NULL, NULL, 0)
};
diff --git a/src/mesa/glapi/glthread.c b/src/mesa/glapi/glthread.c
index b818f4e26e..dc90b3602c 100644
--- a/src/mesa/glapi/glthread.c
+++ b/src/mesa/glapi/glthread.c
@@ -25,17 +25,15 @@
/*
* XXX There's probably some work to do in order to make this file
- * truly reusable outside of Mesa.
+ * truly reusable outside of Mesa. First, the glheader.h include must go.
*/
-
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
-#include <stdlib.h>
-#include <stdio.h>
-#include "glthread.h"
+#include "main/compiler.h"
+#include "glapi/glthread.h"
/*
@@ -248,57 +246,6 @@ _glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
#endif /* WIN32_THREADS */
-
-
-/*
- * XFree86 has its own thread wrapper, Xthreads.h
- * We wrap it again for GL.
- */
-#ifdef USE_XTHREADS
-
-unsigned long
-_glthread_GetID(void)
-{
- return (unsigned long) xthread_self();
-}
-
-
-void
-_glthread_InitTSD(_glthread_TSD *tsd)
-{
- if (xthread_key_create(&tsd->key, NULL) != 0) {
- perror(INIT_TSD_ERROR);
- exit(-1);
- }
- tsd->initMagic = INIT_MAGIC;
-}
-
-
-void *
-_glthread_GetTSD(_glthread_TSD *tsd)
-{
- void *ptr;
- if (tsd->initMagic != INIT_MAGIC) {
- _glthread_InitTSD(tsd);
- }
- xthread_get_specific(tsd->key, &ptr);
- return ptr;
-}
-
-
-void
-_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
-{
- if (tsd->initMagic != INIT_MAGIC) {
- _glthread_InitTSD(tsd);
- }
- xthread_set_specific(tsd->key, ptr);
-}
-
-#endif /* XTHREAD */
-
-
-
/*
* BeOS threads
*/
diff --git a/src/mesa/glapi/glthread.h b/src/mesa/glapi/glthread.h
index 27ccd2e2e7..8ec933a851 100644
--- a/src/mesa/glapi/glthread.h
+++ b/src/mesa/glapi/glthread.h
@@ -71,7 +71,7 @@
#if (defined(PTHREADS) || defined(SOLARIS_THREADS) ||\
- defined(WIN32_THREADS) || defined(USE_XTHREADS) || defined(BEOS_THREADS)) \
+ defined(WIN32_THREADS) || defined(BEOS_THREADS)) \
&& !defined(THREADS)
# define THREADS
#endif
@@ -116,9 +116,49 @@ typedef pthread_mutex_t _glthread_Mutex;
#define _glthread_UNLOCK_MUTEX(name) \
(void) pthread_mutex_unlock(&(name))
-#endif /* PTHREADS */
+typedef pthread_cond_t _glthread_Cond;
+#define _glthread_DECLARE_STATIC_COND(name) \
+ static _glthread_Cond name = PTHREAD_COND_INITIALIZER
+#define _glthread_INIT_COND(cond) \
+ pthread_cond_init(&(cond), NULL)
+
+#define _glthread_DESTROY_COND(name) \
+ pthread_cond_destroy(&(name))
+
+#define _glthread_COND_WAIT(cond, mutex) \
+ pthread_cond_wait(&(cond), &(mutex))
+
+#define _glthread_COND_SIGNAL(cond) \
+ pthread_cond_signal(&(cond))
+
+#define _glthread_COND_BROADCAST(cond) \
+ pthread_cond_broadcast(&(cond))
+
+
+#else /* PTHREADS */
+
+typedef unsigned int _glthread_Cond;
+#define _glthread_DECLARE_STATIC_COND(name) \
+// #warning Condition variables not implemented.
+
+#define _glthread_INIT_COND(cond) \
+ ASSERT(0);
+
+#define _glthread_DESTROY_COND(name) \
+ ASSERT(0);
+
+#define _glthread_COND_WAIT(cond, mutex) \
+ ASSERT(0);
+
+#define _glthread_COND_SIGNAL(cond) \
+ ASSERT(0);
+
+#define _glthread_COND_BROADCAST(cond) \
+ ASSERT(0);
+
+#endif
/*
@@ -178,56 +218,26 @@ typedef CRITICAL_SECTION _glthread_Mutex;
#endif /* WIN32_THREADS */
-
-
-/*
- * XFree86 has its own thread wrapper, Xthreads.h
- * We wrap it again for GL.
- */
-#ifdef USE_XTHREADS
-#include <X11/Xthreads.h>
-
-typedef struct {
- xthread_key_t key;
- int initMagic;
-} _glthread_TSD;
-
-typedef xthread_t _glthread_Thread;
-
-typedef xmutex_rec _glthread_Mutex;
-
-#ifdef XMUTEX_INITIALIZER
-#define _glthread_DECLARE_STATIC_MUTEX(name) \
- static _glthread_Mutex name = XMUTEX_INITIALIZER
-#else
-#define _glthread_DECLARE_STATIC_MUTEX(name) \
- static _glthread_Mutex name
-#endif
-
-#define _glthread_INIT_MUTEX(name) \
- xmutex_init(&(name))
-
-#define _glthread_DESTROY_MUTEX(name) \
- xmutex_clear(&(name))
-
-#define _glthread_LOCK_MUTEX(name) \
- (void) xmutex_lock(&(name))
-
-#define _glthread_UNLOCK_MUTEX(name) \
- (void) xmutex_unlock(&(name))
-
-#endif /* USE_XTHREADS */
-
-
-
/*
* BeOS threads. R5.x required.
*/
#ifdef BEOS_THREADS
+/* Problem with OS.h and this file on haiku */
+#ifndef __HAIKU__
#include <kernel/OS.h>
+#endif
+
#include <support/TLS.h>
+/* The only two typedefs required here
+ * this is cause of the OS.h problem
+ */
+#ifdef __HAIKU__
+typedef int32 thread_id;
+typedef int32 sem_id;
+#endif
+
typedef struct {
int32 key;
int initMagic;
@@ -259,11 +269,11 @@ typedef benaphore _glthread_Mutex;
* THREADS not defined
*/
-typedef int _glthread_TSD;
+typedef unsigned _glthread_TSD;
-typedef int _glthread_Thread;
+typedef unsigned _glthread_Thread;
-typedef int _glthread_Mutex;
+typedef unsigned _glthread_Mutex;
#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0
diff --git a/src/mesa/main/accum.c b/src/mesa/main/accum.c
index 2345695f3c..30e2f9664a 100644
--- a/src/mesa/main/accum.c
+++ b/src/mesa/main/accum.c
@@ -29,6 +29,10 @@
#include "macros.h"
#include "state.h"
#include "mtypes.h"
+#include "glapi/dispatch.h"
+
+
+#if FEATURE_accum
void GLAPIENTRY
@@ -99,6 +103,16 @@ _mesa_Accum( GLenum op, GLfloat value )
}
+void
+_mesa_init_accum_dispatch(struct _glapi_table *disp)
+{
+ SET_Accum(disp, _mesa_Accum);
+ SET_ClearAccum(disp, _mesa_ClearAccum);
+}
+
+
+#endif /* FEATURE_accum */
+
void
_mesa_init_accum( GLcontext *ctx )
diff --git a/src/mesa/main/accum.h b/src/mesa/main/accum.h
index ce92688a5b..ef5e44ea9e 100644
--- a/src/mesa/main/accum.h
+++ b/src/mesa/main/accum.h
@@ -38,25 +38,41 @@
#define ACCUM_H
-#include "mtypes.h"
+#include "main/mtypes.h"
-#if _HAVE_FULL_GL
+#if FEATURE_accum
+
+#define _MESA_INIT_ACCUM_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->Accum = impl ## Accum; \
+ } while (0)
extern void GLAPIENTRY
_mesa_Accum( GLenum op, GLfloat value );
-
extern void GLAPIENTRY
_mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha );
-extern void
-_mesa_init_accum( GLcontext *ctx );
+extern void
+_mesa_init_accum_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_accum */
-#else
+#define _MESA_INIT_ACCUM_FUNCTIONS(driver, impl) do { } while (0)
-/** No-op */
-#define _mesa_init_accum( c ) ((void)0)
+static INLINE void
+_mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
+{
+}
-#endif
+static INLINE void
+_mesa_init_accum_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_accum */
+
+extern void
+_mesa_init_accum( GLcontext *ctx );
-#endif
+#endif /* ACCUM_H */
diff --git a/src/mesa/main/api_arrayelt.c b/src/mesa/main/api_arrayelt.c
index d124c724c9..a058227110 100644
--- a/src/mesa/main/api_arrayelt.c
+++ b/src/mesa/main/api_arrayelt.c
@@ -28,6 +28,7 @@
#include "glheader.h"
#include "api_arrayelt.h"
+#include "bufferobj.h"
#include "context.h"
#include "imports.h"
#include "macros.h"
@@ -70,6 +71,10 @@ typedef struct {
*/
#define TYPE_IDX(t) ( (t) == GL_DOUBLE ? 7 : (t) & 7 )
+
+#if FEATURE_arrayelt
+
+
static const int ColorFuncs[2][8] = {
{
_gloffset_Color3bv,
@@ -1071,7 +1076,7 @@ void _ae_destroy_context( GLcontext *ctx )
static void check_vbo( AEcontext *actx,
struct gl_buffer_object *vbo )
{
- if (vbo->Name && !vbo->Pointer) {
+ if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) {
GLuint i;
for (i = 0; i < actx->nr_vbos; i++)
if (actx->vbo[i] == vbo)
@@ -1094,48 +1099,49 @@ static void _ae_update_state( GLcontext *ctx )
AEarray *aa = actx->arrays;
AEattrib *at = actx->attribs;
GLuint i;
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
actx->nr_vbos = 0;
/* conventional vertex arrays */
- if (ctx->Array.ArrayObj->Index.Enabled) {
- aa->array = &ctx->Array.ArrayObj->Index;
+ if (arrayObj->Index.Enabled) {
+ aa->array = &arrayObj->Index;
aa->offset = IndexFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (ctx->Array.ArrayObj->EdgeFlag.Enabled) {
- aa->array = &ctx->Array.ArrayObj->EdgeFlag;
+ if (arrayObj->EdgeFlag.Enabled) {
+ aa->array = &arrayObj->EdgeFlag;
aa->offset = _gloffset_EdgeFlagv;
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (ctx->Array.ArrayObj->Normal.Enabled) {
- aa->array = &ctx->Array.ArrayObj->Normal;
+ if (arrayObj->Normal.Enabled) {
+ aa->array = &arrayObj->Normal;
aa->offset = NormalFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (ctx->Array.ArrayObj->Color.Enabled) {
- aa->array = &ctx->Array.ArrayObj->Color;
+ if (arrayObj->Color.Enabled) {
+ aa->array = &arrayObj->Color;
aa->offset = ColorFuncs[aa->array->Size-3][TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (ctx->Array.ArrayObj->SecondaryColor.Enabled) {
- aa->array = &ctx->Array.ArrayObj->SecondaryColor;
+ if (arrayObj->SecondaryColor.Enabled) {
+ aa->array = &arrayObj->SecondaryColor;
aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (ctx->Array.ArrayObj->FogCoord.Enabled) {
- aa->array = &ctx->Array.ArrayObj->FogCoord;
+ if (arrayObj->FogCoord.Enabled) {
+ aa->array = &arrayObj->FogCoord;
aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
- struct gl_client_array *attribArray = &ctx->Array.ArrayObj->TexCoord[i];
+ struct gl_client_array *attribArray = &arrayObj->TexCoord[i];
if (attribArray->Enabled) {
/* NOTE: we use generic glVertexAttribNV functions here.
* If we ever remove GL_NV_vertex_program this will have to change.
@@ -1152,13 +1158,13 @@ static void _ae_update_state( GLcontext *ctx )
}
/* generic vertex attribute arrays */
- for (i = 1; i < VERT_ATTRIB_MAX; i++) { /* skip zero! */
- struct gl_client_array *attribArray = &ctx->Array.ArrayObj->VertexAttrib[i];
+ for (i = 1; i < Elements(arrayObj->VertexAttrib); i++) { /* skip zero! */
+ struct gl_client_array *attribArray = &arrayObj->VertexAttrib[i];
if (attribArray->Enabled) {
at->array = attribArray;
/* Note: we can't grab the _glapi_Dispatch->VertexAttrib1fvNV
* function pointer here (for float arrays) since the pointer may
- * change from one execution of _ae_loopback_array_elt() to
+ * change from one execution of _ae_ArrayElement() to
* the next. Doing so caused UT to break.
*/
if (ctx->VertexProgram._Enabled
@@ -1179,18 +1185,18 @@ static void _ae_update_state( GLcontext *ctx )
}
/* finally, vertex position */
- if (ctx->Array.ArrayObj->VertexAttrib[0].Enabled) {
+ if (arrayObj->VertexAttrib[0].Enabled) {
/* Use glVertex(v) instead of glVertexAttrib(0, v) to be sure it's
* issued as the last (provoking) attribute).
*/
- aa->array = &ctx->Array.ArrayObj->VertexAttrib[0];
+ aa->array = &arrayObj->VertexAttrib[0];
assert(aa->array->Size >= 2); /* XXX fix someday? */
aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- else if (ctx->Array.ArrayObj->Vertex.Enabled) {
- aa->array = &ctx->Array.ArrayObj->Vertex;
+ else if (arrayObj->Vertex.Enabled) {
+ aa->array = &arrayObj->Vertex;
aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
@@ -1252,7 +1258,7 @@ void _ae_unmap_vbos( GLcontext *ctx )
* for all enabled vertex arrays (for elt-th element).
* Note: this may be called during display list construction.
*/
-void GLAPIENTRY _ae_loopback_array_elt( GLint elt )
+void GLAPIENTRY _ae_ArrayElement( GLint elt )
{
GET_CURRENT_CONTEXT(ctx);
const AEcontext *actx = AE_CONTEXT(ctx);
@@ -1315,3 +1321,13 @@ void _ae_invalidate_state( GLcontext *ctx, GLuint new_state )
actx->NewState |= new_state;
}
}
+
+
+void _mesa_install_arrayelt_vtxfmt(struct _glapi_table *disp,
+ const GLvertexformat *vfmt)
+{
+ SET_ArrayElement(disp, vfmt->ArrayElement);
+}
+
+
+#endif /* FEATURE_arrayelt */
diff --git a/src/mesa/main/api_arrayelt.h b/src/mesa/main/api_arrayelt.h
index e621724fb2..d18c0792c3 100644
--- a/src/mesa/main/api_arrayelt.h
+++ b/src/mesa/main/api_arrayelt.h
@@ -27,16 +27,57 @@
#ifndef API_ARRAYELT_H
#define API_ARRAYELT_H
-#include "mtypes.h"
+
+#include "main/mtypes.h"
+
+#if FEATURE_arrayelt
+
+#define _MESA_INIT_ARRAYELT_VTXFMT(vfmt, impl) \
+ do { \
+ (vfmt)->ArrayElement = impl ## ArrayElement; \
+ } while (0)
extern GLboolean _ae_create_context( GLcontext *ctx );
extern void _ae_destroy_context( GLcontext *ctx );
extern void _ae_invalidate_state( GLcontext *ctx, GLuint new_state );
-extern void GLAPIENTRY _ae_loopback_array_elt( GLint elt );
+extern void GLAPIENTRY _ae_ArrayElement( GLint elt );
/* May optionally be called before a batch of element calls:
*/
extern void _ae_map_vbos( GLcontext *ctx );
extern void _ae_unmap_vbos( GLcontext *ctx );
-#endif
+extern void
+_mesa_install_arrayelt_vtxfmt(struct _glapi_table *disp,
+ const GLvertexformat *vfmt);
+
+#else /* FEATURE_arrayelt */
+
+#define _MESA_INIT_ARRAYELT_VTXFMT(vfmt, impl) do { } while (0)
+
+static INLINE GLboolean
+_ae_create_context( GLcontext *ctx )
+{
+ return GL_TRUE;
+}
+
+static INLINE void
+_ae_destroy_context( GLcontext *ctx )
+{
+}
+
+static INLINE void
+_ae_invalidate_state( GLcontext *ctx, GLuint new_state )
+{
+}
+
+static INLINE void
+_mesa_install_arrayelt_vtxfmt(struct _glapi_table *disp,
+ const GLvertexformat *vfmt)
+{
+}
+
+#endif /* FEATURE_arrayelt */
+
+
+#endif /* API_ARRAYELT_H */
diff --git a/src/mesa/main/api_exec.c b/src/mesa/main/api_exec.c
index bae3bf11cb..1559984f43 100644
--- a/src/mesa/main/api_exec.c
+++ b/src/mesa/main/api_exec.c
@@ -29,10 +29,8 @@
*/
-#include "glheader.h"
-#if FEATURE_accum
+#include "mfeatures.h"
#include "accum.h"
-#endif
#include "api_loopback.h"
#include "api_exec.h"
#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
@@ -41,9 +39,7 @@
#if FEATURE_ATI_fragment_shader
#include "shader/atifragshader.h"
#endif
-#if FEATURE_attrib_stack
#include "attrib.h"
-#endif
#include "blend.h"
#if FEATURE_ARB_vertex_buffer_object
#include "bufferobj.h"
@@ -54,29 +50,17 @@
#endif
#include "clear.h"
#include "clip.h"
-#if FEATURE_colortable
#include "colortab.h"
-#endif
#include "context.h"
-#if FEATURE_convolve
#include "convolve.h"
-#endif
#include "depth.h"
-#if FEATURE_dlist
#include "dlist.h"
-#endif
-#if FEATURE_drawpix
#include "drawpix.h"
#include "rastpos.h"
-#endif
#include "enable.h"
-#if FEATURE_evaluators
#include "eval.h"
-#endif
#include "get.h"
-#if FEATURE_feedback
#include "feedback.h"
-#endif
#include "fog.h"
#if FEATURE_EXT_framebuffer_object
#include "fbobject.h"
@@ -84,38 +68,32 @@
#include "ffvertex_prog.h"
#include "framebuffer.h"
#include "hint.h"
-#if FEATURE_histogram
#include "histogram.h"
-#endif
#include "imports.h"
#include "light.h"
#include "lines.h"
#include "macros.h"
#include "matrix.h"
#include "multisample.h"
-#if FEATURE_pixel_transfer
#include "pixel.h"
-#endif
#include "pixelstore.h"
#include "points.h"
#include "polygon.h"
-#if FEATURE_ARB_occlusion_query || FEATURE_EXT_timer_query
#include "queryobj.h"
-#endif
#include "readpix.h"
#include "scissor.h"
#include "state.h"
#include "stencil.h"
#include "texenv.h"
+#include "texgetimage.h"
#include "teximage.h"
-#if FEATURE_texgen
#include "texgen.h"
-#endif
#include "texobj.h"
#include "texparam.h"
#include "texstate.h"
#include "mtypes.h"
#include "varray.h"
+#include "viewport.h"
#if FEATURE_NV_vertex_program
#include "shader/nvprogram.h"
#endif
@@ -127,6 +105,9 @@
#if FEATURE_ARB_shader_objects
#include "shaders.h"
#endif
+#if FEATURE_ARB_sync
+#include "syncobj.h"
+#endif
#include "debug.h"
#include "glapi/dispatch.h"
@@ -194,20 +175,10 @@ _mesa_init_exec_table(struct _glapi_table *exec)
SET_TexParameteri(exec, _mesa_TexParameteri);
SET_Translatef(exec, _mesa_Translatef);
SET_Viewport(exec, _mesa_Viewport);
-#if FEATURE_accum
- SET_Accum(exec, _mesa_Accum);
- SET_ClearAccum(exec, _mesa_ClearAccum);
-#endif
-#if FEATURE_dlist
- SET_CallList(exec, _mesa_CallList);
- SET_CallLists(exec, _mesa_CallLists);
- SET_DeleteLists(exec, _mesa_DeleteLists);
- SET_EndList(exec, _mesa_EndList);
- SET_GenLists(exec, _mesa_GenLists);
- SET_IsList(exec, _mesa_IsList);
- SET_ListBase(exec, _mesa_ListBase);
- SET_NewList(exec, _mesa_NewList);
-#endif
+
+ _mesa_init_accum_dispatch(exec);
+ _mesa_init_dlist_dispatch(exec);
+
SET_ClearDepth(exec, _mesa_ClearDepth);
SET_ClearIndex(exec, _mesa_ClearIndex);
SET_ClipPlane(exec, _mesa_ClipPlane);
@@ -217,21 +188,10 @@ _mesa_init_exec_table(struct _glapi_table *exec)
SET_DepthFunc(exec, _mesa_DepthFunc);
SET_DepthMask(exec, _mesa_DepthMask);
SET_DepthRange(exec, _mesa_DepthRange);
-#if FEATURE_drawpix
- SET_Bitmap(exec, _mesa_Bitmap);
- SET_CopyPixels(exec, _mesa_CopyPixels);
- SET_DrawPixels(exec, _mesa_DrawPixels);
-#endif
-#if FEATURE_feedback
- SET_InitNames(exec, _mesa_InitNames);
- SET_FeedbackBuffer(exec, _mesa_FeedbackBuffer);
- SET_LoadName(exec, _mesa_LoadName);
- SET_PassThrough(exec, _mesa_PassThrough);
- SET_PopName(exec, _mesa_PopName);
- SET_PushName(exec, _mesa_PushName);
- SET_SelectBuffer(exec, _mesa_SelectBuffer);
- SET_RenderMode(exec, _mesa_RenderMode);
-#endif
+
+ _mesa_init_drawpix_dispatch(exec);
+ _mesa_init_feedback_dispatch(exec);
+
SET_FogCoordPointerEXT(exec, _mesa_FogCoordPointerEXT);
SET_Fogf(exec, _mesa_Fogf);
SET_Fogfv(exec, _mesa_Fogfv);
@@ -265,68 +225,22 @@ _mesa_init_exec_table(struct _glapi_table *exec)
SET_Lighti(exec, _mesa_Lighti);
SET_Lightiv(exec, _mesa_Lightiv);
SET_LoadMatrixd(exec, _mesa_LoadMatrixd);
-#if FEATURE_evaluators
- SET_GetMapdv(exec, _mesa_GetMapdv);
- SET_GetMapfv(exec, _mesa_GetMapfv);
- SET_GetMapiv(exec, _mesa_GetMapiv);
- SET_Map1d(exec, _mesa_Map1d);
- SET_Map1f(exec, _mesa_Map1f);
- SET_Map2d(exec, _mesa_Map2d);
- SET_Map2f(exec, _mesa_Map2f);
- SET_MapGrid1d(exec, _mesa_MapGrid1d);
- SET_MapGrid1f(exec, _mesa_MapGrid1f);
- SET_MapGrid2d(exec, _mesa_MapGrid2d);
- SET_MapGrid2f(exec, _mesa_MapGrid2f);
-#endif
+
+ _mesa_init_eval_dispatch(exec);
+
SET_MultMatrixd(exec, _mesa_MultMatrixd);
-#if FEATURE_pixel_transfer
- SET_GetPixelMapfv(exec, _mesa_GetPixelMapfv);
- SET_GetPixelMapuiv(exec, _mesa_GetPixelMapuiv);
- SET_GetPixelMapusv(exec, _mesa_GetPixelMapusv);
- SET_PixelMapfv(exec, _mesa_PixelMapfv);
- SET_PixelMapuiv(exec, _mesa_PixelMapuiv);
- SET_PixelMapusv(exec, _mesa_PixelMapusv);
- SET_PixelTransferf(exec, _mesa_PixelTransferf);
- SET_PixelTransferi(exec, _mesa_PixelTransferi);
- SET_PixelZoom(exec, _mesa_PixelZoom);
-#endif
+
+ _mesa_init_pixel_dispatch(exec);
+
SET_PixelStoref(exec, _mesa_PixelStoref);
SET_PointSize(exec, _mesa_PointSize);
SET_PolygonMode(exec, _mesa_PolygonMode);
SET_PolygonOffset(exec, _mesa_PolygonOffset);
SET_PolygonStipple(exec, _mesa_PolygonStipple);
-#if FEATURE_attrib_stack
- SET_PopAttrib(exec, _mesa_PopAttrib);
- SET_PushAttrib(exec, _mesa_PushAttrib);
- SET_PopClientAttrib(exec, _mesa_PopClientAttrib);
- SET_PushClientAttrib(exec, _mesa_PushClientAttrib);
-#endif
-#if FEATURE_drawpix
- SET_RasterPos2f(exec, _mesa_RasterPos2f);
- SET_RasterPos2fv(exec, _mesa_RasterPos2fv);
- SET_RasterPos2i(exec, _mesa_RasterPos2i);
- SET_RasterPos2iv(exec, _mesa_RasterPos2iv);
- SET_RasterPos2d(exec, _mesa_RasterPos2d);
- SET_RasterPos2dv(exec, _mesa_RasterPos2dv);
- SET_RasterPos2s(exec, _mesa_RasterPos2s);
- SET_RasterPos2sv(exec, _mesa_RasterPos2sv);
- SET_RasterPos3d(exec, _mesa_RasterPos3d);
- SET_RasterPos3dv(exec, _mesa_RasterPos3dv);
- SET_RasterPos3f(exec, _mesa_RasterPos3f);
- SET_RasterPos3fv(exec, _mesa_RasterPos3fv);
- SET_RasterPos3i(exec, _mesa_RasterPos3i);
- SET_RasterPos3iv(exec, _mesa_RasterPos3iv);
- SET_RasterPos3s(exec, _mesa_RasterPos3s);
- SET_RasterPos3sv(exec, _mesa_RasterPos3sv);
- SET_RasterPos4d(exec, _mesa_RasterPos4d);
- SET_RasterPos4dv(exec, _mesa_RasterPos4dv);
- SET_RasterPos4f(exec, _mesa_RasterPos4f);
- SET_RasterPos4fv(exec, _mesa_RasterPos4fv);
- SET_RasterPos4i(exec, _mesa_RasterPos4i);
- SET_RasterPos4iv(exec, _mesa_RasterPos4iv);
- SET_RasterPos4s(exec, _mesa_RasterPos4s);
- SET_RasterPos4sv(exec, _mesa_RasterPos4sv);
-#endif
+
+ _mesa_init_attrib_dispatch(exec);
+ _mesa_init_rastpos_dispatch(exec);
+
SET_ReadPixels(exec, _mesa_ReadPixels);
SET_Rotated(exec, _mesa_Rotated);
SET_Scaled(exec, _mesa_Scaled);
@@ -334,17 +248,7 @@ _mesa_init_exec_table(struct _glapi_table *exec)
SET_TexEnvf(exec, _mesa_TexEnvf);
SET_TexEnviv(exec, _mesa_TexEnviv);
-#if FEATURE_texgen
- SET_GetTexGendv(exec, _mesa_GetTexGendv);
- SET_GetTexGenfv(exec, _mesa_GetTexGenfv);
- SET_GetTexGeniv(exec, _mesa_GetTexGeniv);
- SET_TexGend(exec, _mesa_TexGend);
- SET_TexGendv(exec, _mesa_TexGendv);
- SET_TexGenf(exec, _mesa_TexGenf);
- SET_TexGenfv(exec, _mesa_TexGenfv);
- SET_TexGeni(exec, _mesa_TexGeni);
- SET_TexGeniv(exec, _mesa_TexGeniv);
-#endif
+ _mesa_init_texgen_dispatch(exec);
SET_TexImage1D(exec, _mesa_TexImage1D);
SET_TexParameterf(exec, _mesa_TexParameterf);
@@ -390,45 +294,9 @@ _mesa_init_exec_table(struct _glapi_table *exec)
SET_BlendEquation(exec, _mesa_BlendEquation);
SET_BlendEquationSeparateEXT(exec, _mesa_BlendEquationSeparateEXT);
-#if FEATURE_colortable
- SET_ColorSubTable(exec, _mesa_ColorSubTable);
- SET_ColorTable(exec, _mesa_ColorTable);
- SET_ColorTableParameterfv(exec, _mesa_ColorTableParameterfv);
- SET_ColorTableParameteriv(exec, _mesa_ColorTableParameteriv);
- SET_CopyColorSubTable(exec, _mesa_CopyColorSubTable);
- SET_CopyColorTable(exec, _mesa_CopyColorTable);
- SET_GetColorTable(exec, _mesa_GetColorTable);
- SET_GetColorTableParameterfv(exec, _mesa_GetColorTableParameterfv);
- SET_GetColorTableParameteriv(exec, _mesa_GetColorTableParameteriv);
-#endif
-
-#if FEATURE_convolve
- SET_ConvolutionFilter1D(exec, _mesa_ConvolutionFilter1D);
- SET_ConvolutionFilter2D(exec, _mesa_ConvolutionFilter2D);
- SET_ConvolutionParameterf(exec, _mesa_ConvolutionParameterf);
- SET_ConvolutionParameterfv(exec, _mesa_ConvolutionParameterfv);
- SET_ConvolutionParameteri(exec, _mesa_ConvolutionParameteri);
- SET_ConvolutionParameteriv(exec, _mesa_ConvolutionParameteriv);
- SET_CopyConvolutionFilter1D(exec, _mesa_CopyConvolutionFilter1D);
- SET_CopyConvolutionFilter2D(exec, _mesa_CopyConvolutionFilter2D);
- SET_GetConvolutionFilter(exec, _mesa_GetConvolutionFilter);
- SET_GetConvolutionParameterfv(exec, _mesa_GetConvolutionParameterfv);
- SET_GetConvolutionParameteriv(exec, _mesa_GetConvolutionParameteriv);
- SET_SeparableFilter2D(exec, _mesa_SeparableFilter2D);
-#endif
-#if FEATURE_histogram
- SET_GetHistogram(exec, _mesa_GetHistogram);
- SET_GetHistogramParameterfv(exec, _mesa_GetHistogramParameterfv);
- SET_GetHistogramParameteriv(exec, _mesa_GetHistogramParameteriv);
- SET_GetMinmax(exec, _mesa_GetMinmax);
- SET_GetMinmaxParameterfv(exec, _mesa_GetMinmaxParameterfv);
- SET_GetMinmaxParameteriv(exec, _mesa_GetMinmaxParameteriv);
- SET_GetSeparableFilter(exec, _mesa_GetSeparableFilter);
- SET_Histogram(exec, _mesa_Histogram);
- SET_Minmax(exec, _mesa_Minmax);
- SET_ResetHistogram(exec, _mesa_ResetHistogram);
- SET_ResetMinmax(exec, _mesa_ResetMinmax);
-#endif
+ _mesa_init_colortable_dispatch(exec);
+ _mesa_init_convolve_dispatch(exec);
+ _mesa_init_histogram_dispatch(exec);
/* OpenGL 2.0 */
SET_StencilFuncSeparate(exec, _mesa_StencilFuncSeparate);
@@ -527,7 +395,6 @@ _mesa_init_exec_table(struct _glapi_table *exec)
/* 148. GL_EXT_multi_draw_arrays */
#if _HAVE_FULL_GL
SET_MultiDrawArraysEXT(exec, _mesa_MultiDrawArraysEXT);
- SET_MultiDrawElementsEXT(exec, _mesa_MultiDrawElementsEXT);
#endif
/* 173. GL_INGR_blend_func_separate */
@@ -541,32 +408,7 @@ _mesa_init_exec_table(struct _glapi_table *exec)
#endif
/* 197. GL_MESA_window_pos */
-#if FEATURE_drawpix
- SET_WindowPos2dMESA(exec, _mesa_WindowPos2dMESA);
- SET_WindowPos2dvMESA(exec, _mesa_WindowPos2dvMESA);
- SET_WindowPos2fMESA(exec, _mesa_WindowPos2fMESA);
- SET_WindowPos2fvMESA(exec, _mesa_WindowPos2fvMESA);
- SET_WindowPos2iMESA(exec, _mesa_WindowPos2iMESA);
- SET_WindowPos2ivMESA(exec, _mesa_WindowPos2ivMESA);
- SET_WindowPos2sMESA(exec, _mesa_WindowPos2sMESA);
- SET_WindowPos2svMESA(exec, _mesa_WindowPos2svMESA);
- SET_WindowPos3dMESA(exec, _mesa_WindowPos3dMESA);
- SET_WindowPos3dvMESA(exec, _mesa_WindowPos3dvMESA);
- SET_WindowPos3fMESA(exec, _mesa_WindowPos3fMESA);
- SET_WindowPos3fvMESA(exec, _mesa_WindowPos3fvMESA);
- SET_WindowPos3iMESA(exec, _mesa_WindowPos3iMESA);
- SET_WindowPos3ivMESA(exec, _mesa_WindowPos3ivMESA);
- SET_WindowPos3sMESA(exec, _mesa_WindowPos3sMESA);
- SET_WindowPos3svMESA(exec, _mesa_WindowPos3svMESA);
- SET_WindowPos4dMESA(exec, _mesa_WindowPos4dMESA);
- SET_WindowPos4dvMESA(exec, _mesa_WindowPos4dvMESA);
- SET_WindowPos4fMESA(exec, _mesa_WindowPos4fMESA);
- SET_WindowPos4fvMESA(exec, _mesa_WindowPos4fvMESA);
- SET_WindowPos4iMESA(exec, _mesa_WindowPos4iMESA);
- SET_WindowPos4ivMESA(exec, _mesa_WindowPos4ivMESA);
- SET_WindowPos4sMESA(exec, _mesa_WindowPos4sMESA);
- SET_WindowPos4svMESA(exec, _mesa_WindowPos4svMESA);
-#endif
+ /* part of _mesa_init_rastpos_dispatch(exec); */
/* 200. GL_IBM_multimode_draw_arrays */
#if _HAVE_FULL_GL
@@ -640,6 +482,8 @@ _mesa_init_exec_table(struct _glapi_table *exec)
/* ???. GL_EXT_depth_bounds_test */
SET_DepthBoundsEXT(exec, _mesa_DepthBoundsEXT);
+ SET_ProvokingVertexEXT(exec, _mesa_ProvokingVertexEXT);
+
/* ARB 1. GL_ARB_multitexture */
#if _HAVE_FULL_GL
SET_ActiveTextureARB(exec, _mesa_ActiveTextureARB);
@@ -756,16 +600,7 @@ _mesa_init_exec_table(struct _glapi_table *exec)
#endif
/* ARB 29. GL_ARB_occlusion_query */
-#if FEATURE_ARB_occlusion_query
- SET_GenQueriesARB(exec, _mesa_GenQueriesARB);
- SET_DeleteQueriesARB(exec, _mesa_DeleteQueriesARB);
- SET_IsQueryARB(exec, _mesa_IsQueryARB);
- SET_BeginQueryARB(exec, _mesa_BeginQueryARB);
- SET_EndQueryARB(exec, _mesa_EndQueryARB);
- SET_GetQueryivARB(exec, _mesa_GetQueryivARB);
- SET_GetQueryObjectivARB(exec, _mesa_GetQueryObjectivARB);
- SET_GetQueryObjectuivARB(exec, _mesa_GetQueryObjectuivARB);
-#endif
+ _mesa_init_queryobj_dispatch(exec);
/* ARB 37. GL_ARB_draw_buffers */
#if FEATURE_draw_read_buffer
@@ -820,6 +655,17 @@ _mesa_init_exec_table(struct _glapi_table *exec)
SET_GetAttribLocationARB(exec, _mesa_GetAttribLocationARB);
#endif /* FEATURE_ARB_vertex_shader */
+ /* GL_ARB_sync */
+#if FEATURE_ARB_sync
+ SET_IsSync(exec, _mesa_IsSync);
+ SET_DeleteSync(exec, _mesa_DeleteSync);
+ SET_FenceSync(exec, _mesa_FenceSync);
+ SET_ClientWaitSync(exec, _mesa_ClientWaitSync);
+ SET_WaitSync(exec, _mesa_WaitSync);
+ SET_GetInteger64v(exec, _mesa_GetInteger64v);
+ SET_GetSynciv(exec, _mesa_GetSynciv);
+#endif
+
/* GL_ATI_fragment_shader */
#if FEATURE_ATI_fragment_shader
SET_GenFragmentShadersATI(exec, _mesa_GenFragmentShadersATI);
@@ -838,6 +684,12 @@ _mesa_init_exec_table(struct _glapi_table *exec)
SET_SetFragmentShaderConstantATI(exec, _mesa_SetFragmentShaderConstantATI);
#endif
+ /* GL_ATI_envmap_bumpmap */
+ SET_GetTexBumpParameterivATI(exec, _mesa_GetTexBumpParameterivATI);
+ SET_GetTexBumpParameterfvATI(exec, _mesa_GetTexBumpParameterfvATI);
+ SET_TexBumpParameterivATI(exec, _mesa_TexBumpParameterivATI);
+ SET_TexBumpParameterfvATI(exec, _mesa_TexBumpParameterfvATI);
+
#if FEATURE_EXT_framebuffer_object
SET_IsRenderbufferEXT(exec, _mesa_IsRenderbufferEXT);
SET_BindRenderbufferEXT(exec, _mesa_BindRenderbufferEXT);
@@ -858,11 +710,6 @@ _mesa_init_exec_table(struct _glapi_table *exec)
SET_GenerateMipmapEXT(exec, _mesa_GenerateMipmapEXT);
#endif
-#if FEATURE_EXT_timer_query
- SET_GetQueryObjecti64vEXT(exec, _mesa_GetQueryObjecti64vEXT);
- SET_GetQueryObjectui64vEXT(exec, _mesa_GetQueryObjectui64vEXT);
-#endif
-
#if FEATURE_EXT_framebuffer_blit
SET_BlitFramebufferEXT(exec, _mesa_BlitFramebufferEXT);
#endif
@@ -880,5 +727,23 @@ _mesa_init_exec_table(struct _glapi_table *exec)
/* GL_ATI_separate_stencil */
SET_StencilFuncSeparateATI(exec, _mesa_StencilFuncSeparateATI);
-}
+#if FEATURE_ARB_framebuffer_object
+ /* The ARB_fbo functions are the union of
+ * GL_EXT_fbo, GL_EXT_framebuffer_blit, GL_EXT_texture_array
+ */
+ SET_RenderbufferStorageMultisample(exec, _mesa_RenderbufferStorageMultisample);
+#endif
+
+#if FEATURE_ARB_map_buffer_range
+ SET_MapBufferRange(exec, _mesa_MapBufferRange);
+ SET_FlushMappedBufferRange(exec, _mesa_FlushMappedBufferRange);
+#endif
+
+ /* GL_ARB_copy_buffer */
+ SET_CopyBufferSubData(exec, _mesa_CopyBufferSubData);
+
+ /* GL_ARB_vertex_array_object */
+ SET_BindVertexArray(exec, _mesa_BindVertexArray);
+ SET_GenVertexArrays(exec, _mesa_GenVertexArrays);
+}
diff --git a/src/mesa/main/api_loopback.c b/src/mesa/main/api_loopback.c
index 0e3f5ff957..3d466ac44a 100644
--- a/src/mesa/main/api_loopback.c
+++ b/src/mesa/main/api_loopback.c
@@ -77,6 +77,10 @@
#define FOGCOORDF(x) CALL_FogCoordfEXT(GET_DISPATCH(), (x))
#define SECONDARYCOLORF(a,b,c) CALL_SecondaryColor3fEXT(GET_DISPATCH(), (a,b,c))
+
+#if FEATURE_beginend
+
+
static void GLAPIENTRY
loopback_Color3b_f( GLbyte red, GLbyte green, GLbyte blue )
{
@@ -1655,3 +1659,6 @@ _mesa_loopback_init_api_table( struct _glapi_table *dest )
SET_VertexAttrib4NusvARB(dest, loopback_VertexAttrib4NusvARB);
SET_VertexAttrib4NuivARB(dest, loopback_VertexAttrib4NuivARB);
}
+
+
+#endif /* FEATURE_beginend */
diff --git a/src/mesa/main/api_loopback.h b/src/mesa/main/api_loopback.h
index 6f85bbc1d9..751cba2931 100644
--- a/src/mesa/main/api_loopback.h
+++ b/src/mesa/main/api_loopback.h
@@ -27,11 +27,21 @@
#ifndef API_LOOPBACK_H
#define API_LOOPBACK_H
-#include "glheader.h"
+#include "main/mtypes.h"
+#if FEATURE_beginend
struct _glapi_table;
extern void _mesa_loopback_init_api_table( struct _glapi_table *dest );
-#endif
+#else /* FEATURE_beginend */
+
+static INLINE void
+_mesa_loopback_init_api_table( struct _glapi_table *dest )
+{
+}
+
+#endif /* FEATURE_beginend */
+
+#endif /* API_LOOPBACK_H */
diff --git a/src/mesa/main/api_noop.c b/src/mesa/main/api_noop.c
index a1cc3a2a4b..cd67661382 100644
--- a/src/mesa/main/api_noop.c
+++ b/src/mesa/main/api_noop.c
@@ -30,9 +30,8 @@
#include "context.h"
#include "light.h"
#include "macros.h"
-#if FEATURE_dlist
#include "dlist.h"
-#endif
+#include "eval.h"
#include "glapi/dispatch.h"
@@ -44,6 +43,9 @@
*/
+#if FEATURE_beginend
+
+
static void GLAPIENTRY _mesa_noop_EdgeFlag( GLboolean b )
{
GET_CURRENT_CONTEXT(ctx);
@@ -477,7 +479,7 @@ static void GLAPIENTRY _mesa_noop_VertexAttrib4fvNV( GLuint index, const GLfloat
static void GLAPIENTRY _mesa_noop_VertexAttrib1fARB( GLuint index, GLfloat x )
{
GET_CURRENT_CONTEXT(ctx);
- if (index < MAX_VERTEX_ATTRIBS) {
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], x, 0, 0, 1);
}
else
@@ -487,7 +489,7 @@ static void GLAPIENTRY _mesa_noop_VertexAttrib1fARB( GLuint index, GLfloat x )
static void GLAPIENTRY _mesa_noop_VertexAttrib1fvARB( GLuint index, const GLfloat *v )
{
GET_CURRENT_CONTEXT(ctx);
- if (index < MAX_VERTEX_ATTRIBS) {
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], v[0], 0, 0, 1);
}
else
@@ -497,7 +499,7 @@ static void GLAPIENTRY _mesa_noop_VertexAttrib1fvARB( GLuint index, const GLfloa
static void GLAPIENTRY _mesa_noop_VertexAttrib2fARB( GLuint index, GLfloat x, GLfloat y )
{
GET_CURRENT_CONTEXT(ctx);
- if (index < MAX_VERTEX_ATTRIBS) {
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], x, y, 0, 1);
}
else
@@ -507,7 +509,7 @@ static void GLAPIENTRY _mesa_noop_VertexAttrib2fARB( GLuint index, GLfloat x, GL
static void GLAPIENTRY _mesa_noop_VertexAttrib2fvARB( GLuint index, const GLfloat *v )
{
GET_CURRENT_CONTEXT(ctx);
- if (index < MAX_VERTEX_ATTRIBS) {
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], v[0], v[1], 0, 1);
}
else
@@ -518,7 +520,7 @@ static void GLAPIENTRY _mesa_noop_VertexAttrib3fARB( GLuint index, GLfloat x,
GLfloat y, GLfloat z )
{
GET_CURRENT_CONTEXT(ctx);
- if (index < MAX_VERTEX_ATTRIBS) {
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], x, y, z, 1);
}
else
@@ -528,7 +530,7 @@ static void GLAPIENTRY _mesa_noop_VertexAttrib3fARB( GLuint index, GLfloat x,
static void GLAPIENTRY _mesa_noop_VertexAttrib3fvARB( GLuint index, const GLfloat *v )
{
GET_CURRENT_CONTEXT(ctx);
- if (index < MAX_VERTEX_ATTRIBS) {
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], v[0], v[1], v[2], 1);
}
else
@@ -539,7 +541,7 @@ static void GLAPIENTRY _mesa_noop_VertexAttrib4fARB( GLuint index, GLfloat x,
GLfloat y, GLfloat z, GLfloat w )
{
GET_CURRENT_CONTEXT(ctx);
- if (index < MAX_VERTEX_ATTRIBS) {
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], x, y, z, w);
}
else
@@ -549,7 +551,7 @@ static void GLAPIENTRY _mesa_noop_VertexAttrib4fARB( GLuint index, GLfloat x,
static void GLAPIENTRY _mesa_noop_VertexAttrib4fvARB( GLuint index, const GLfloat *v )
{
GET_CURRENT_CONTEXT(ctx);
- if (index < MAX_VERTEX_ATTRIBS) {
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], v[0], v[1], v[2], v[3]);
}
else
@@ -624,7 +626,7 @@ static void GLAPIENTRY _mesa_noop_Vertex4f( GLfloat a, GLfloat b, GLfloat c, GLf
}
-#if FEATURE_evaluators
+#if FEATURE_eval
/* Similarly, these have no effect outside begin/end:
*/
static void GLAPIENTRY _mesa_noop_EvalCoord1f( GLfloat a )
@@ -656,7 +658,7 @@ static void GLAPIENTRY _mesa_noop_EvalPoint2( GLint a, GLint b )
{
(void) a; (void) b;
}
-#endif /* FEATURE_evaluators */
+#endif /* FEATURE_eval */
/* Begin -- call into driver, should result in the vtxfmt being
@@ -731,7 +733,7 @@ _mesa_noop_DrawElements(GLenum mode, GLsizei count, GLenum type,
GET_CURRENT_CONTEXT(ctx);
GLint i;
- if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
return;
CALL_Begin(GET_DISPATCH(), (mode));
@@ -757,6 +759,43 @@ _mesa_noop_DrawElements(GLenum mode, GLsizei count, GLenum type,
CALL_End(GET_DISPATCH(), ());
}
+static void GLAPIENTRY
+_mesa_noop_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
+ basevertex ))
+ return;
+
+ CALL_Begin(GET_DISPATCH(), (mode));
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] +
+ basevertex));
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] +
+ basevertex ));
+ break;
+ case GL_UNSIGNED_INT:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] +
+ basevertex ));
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElementsBaseVertex(type)" );
+ break;
+ }
+
+ CALL_End(GET_DISPATCH(), ());
+}
+
static void GLAPIENTRY
_mesa_noop_DrawRangeElements(GLenum mode,
@@ -768,10 +807,58 @@ _mesa_noop_DrawRangeElements(GLenum mode,
if (_mesa_validate_DrawRangeElements( ctx, mode,
start, end,
- count, type, indices ))
+ count, type, indices, 0 ))
CALL_DrawElements(GET_DISPATCH(), (mode, count, type, indices));
}
+/* GL_EXT_multi_draw_arrays */
+void GLAPIENTRY
+_mesa_noop_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount)
+{
+ GLsizei i;
+
+ for (i = 0; i < primcount; i++) {
+ if (count[i] > 0) {
+ CALL_DrawElements(GET_DISPATCH(), (mode, count[i], type, indices[i]));
+ }
+ }
+}
+
+static void GLAPIENTRY
+_mesa_noop_DrawRangeElementsBaseVertex(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (_mesa_validate_DrawRangeElements( ctx, mode,
+ start, end,
+ count, type, indices, basevertex ))
+ CALL_DrawElementsBaseVertex(GET_DISPATCH(), (mode, count, type, indices,
+ basevertex));
+}
+
+/* GL_EXT_multi_draw_arrays */
+void GLAPIENTRY
+_mesa_noop_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
+ GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount,
+ const GLint *basevertex)
+{
+ GLsizei i;
+
+ for (i = 0; i < primcount; i++) {
+ if (count[i] > 0) {
+ CALL_DrawElementsBaseVertex(GET_DISPATCH(), (mode, count[i], type,
+ indices[i],
+ basevertex[i]));
+ }
+ }
+}
+
/*
* Eval Mesh
*/
@@ -907,26 +994,21 @@ _mesa_noop_EvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 )
void
_mesa_noop_vtxfmt_init( GLvertexformat *vfmt )
{
- vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
+ _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
+
vfmt->Begin = _mesa_noop_Begin;
-#if FEATURE_dlist
- vfmt->CallList = _mesa_CallList;
- vfmt->CallLists = _mesa_CallLists;
-#endif
+
+ _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_);
+
vfmt->Color3f = _mesa_noop_Color3f;
vfmt->Color3fv = _mesa_noop_Color3fv;
vfmt->Color4f = _mesa_noop_Color4f;
vfmt->Color4fv = _mesa_noop_Color4fv;
vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
vfmt->End = _mesa_noop_End;
-#if FEATURE_evaluators
- vfmt->EvalCoord1f = _mesa_noop_EvalCoord1f;
- vfmt->EvalCoord1fv = _mesa_noop_EvalCoord1fv;
- vfmt->EvalCoord2f = _mesa_noop_EvalCoord2f;
- vfmt->EvalCoord2fv = _mesa_noop_EvalCoord2fv;
- vfmt->EvalPoint1 = _mesa_noop_EvalPoint1;
- vfmt->EvalPoint2 = _mesa_noop_EvalPoint2;
-#endif
+
+ _MESA_INIT_EVAL_VTXFMT(vfmt, _mesa_noop_);
+
vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
vfmt->Indexf = _mesa_noop_Indexf;
@@ -980,6 +1062,11 @@ _mesa_noop_vtxfmt_init( GLvertexformat *vfmt )
vfmt->DrawArrays = _mesa_noop_DrawArrays;
vfmt->DrawElements = _mesa_noop_DrawElements;
vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements;
- vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
- vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
+ vfmt->MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ vfmt->DrawElementsBaseVertex = _mesa_noop_DrawElementsBaseVertex;
+ vfmt->DrawRangeElementsBaseVertex = _mesa_noop_DrawRangeElementsBaseVertex;
+ vfmt->MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
}
+
+
+#endif /* FEATURE_beginend */
diff --git a/src/mesa/main/api_noop.h b/src/mesa/main/api_noop.h
index 8bf4660800..e7fd49bafb 100644
--- a/src/mesa/main/api_noop.h
+++ b/src/mesa/main/api_noop.h
@@ -25,8 +25,9 @@
#ifndef _API_NOOP_H
#define _API_NOOP_H
-#include "mtypes.h"
-#include "context.h"
+#include "main/mtypes.h"
+
+#if FEATURE_beginend
extern void GLAPIENTRY
_mesa_noop_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
@@ -40,7 +41,20 @@ _mesa_noop_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
extern void GLAPIENTRY
_mesa_noop_Materialfv(GLenum face, GLenum pname, const GLfloat *param);
+extern void GLAPIENTRY
+_mesa_noop_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount);
+
+extern void GLAPIENTRY
+_mesa_noop_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
+ GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount,
+ const GLint *basevertex);
+
extern void
_mesa_noop_vtxfmt_init(GLvertexformat *vfmt);
-#endif
+#endif /* FEATURE_beginend */
+
+#endif /* _API_NOOP_H */
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
index 59c2debb22..4a1448deee 100644
--- a/src/mesa/main/api_validate.c
+++ b/src/mesa/main/api_validate.c
@@ -24,82 +24,105 @@
#include "glheader.h"
#include "api_validate.h"
+#include "bufferobj.h"
#include "context.h"
#include "imports.h"
#include "mtypes.h"
#include "state.h"
+#include "vbo/vbo.h"
/**
- * Find the max index in the given element/index buffer
+ * \return number of bytes in array [count] of type.
*/
-static GLuint
-max_buffer_index(GLcontext *ctx, GLuint count, GLenum type,
- const void *indices,
- struct gl_buffer_object *elementBuf)
+static GLsizei
+index_bytes(GLenum type, GLsizei count)
{
- const GLubyte *map = NULL;
- GLuint max = 0;
- GLint i;
-
- if (elementBuf->Name) {
- /* elements are in a user-defined buffer object. need to map it */
- map = ctx->Driver.MapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- GL_READ_ONLY,
- elementBuf);
- /* Actual address is the sum of pointers */
- indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices);
- }
-
if (type == GL_UNSIGNED_INT) {
- for (i = 0; i < count; i++)
- if (((GLuint *) indices)[i] > max)
- max = ((GLuint *) indices)[i];
+ return count * sizeof(GLuint);
}
- else if (type == GL_UNSIGNED_SHORT) {
- for (i = 0; i < count; i++)
- if (((GLushort *) indices)[i] > max)
- max = ((GLushort *) indices)[i];
+ else if (type == GL_UNSIGNED_BYTE) {
+ return count * sizeof(GLubyte);
}
else {
- ASSERT(type == GL_UNSIGNED_BYTE);
- for (i = 0; i < count; i++)
- if (((GLubyte *) indices)[i] > max)
- max = ((GLubyte *) indices)[i];
- }
-
- if (map) {
- ctx->Driver.UnmapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- ctx->Array.ElementArrayBufferObj);
+ ASSERT(type == GL_UNSIGNED_SHORT);
+ return count * sizeof(GLushort);
}
-
- return max;
}
+
+/**
+ * Check if OK to draw arrays/elements.
+ */
static GLboolean
-check_valid_to_render(GLcontext *ctx, char *function)
+check_valid_to_render(GLcontext *ctx, const char *function)
{
- if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glDraw%s(incomplete framebuffer)", function);
+ if (!_mesa_valid_to_render(ctx, function)) {
return GL_FALSE;
}
- /* Always need vertex positions, unless a vertex program is in use */
- if (!ctx->VertexProgram._Current &&
- !ctx->Array.ArrayObj->Vertex.Enabled &&
+#if FEATURE_es2_glsl
+ /* For ES2, we can draw if any vertex array is enabled (and we should
+ * always have a vertex program/shader).
+ */
+ if (ctx->Array.ArrayObj->_Enabled == 0x0 || !ctx->VertexProgram._Current)
+ return GL_FALSE;
+#else
+ /* For regular OpenGL, only draw if we have vertex positions (regardless
+ * of whether or not we have a vertex program/shader).
+ */
+ if (!ctx->Array.ArrayObj->Vertex.Enabled &&
!ctx->Array.ArrayObj->VertexAttrib[0].Enabled)
return GL_FALSE;
+#endif
return GL_TRUE;
}
+static GLboolean
+check_index_bounds(GLcontext *ctx, GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ struct _mesa_prim prim;
+ struct _mesa_index_buffer ib;
+ GLuint min, max;
+
+ /* Only the X Server needs to do this -- otherwise, accessing outside
+ * array/BO bounds allows application termination.
+ */
+ if (!ctx->Const.CheckArrayBounds)
+ return GL_TRUE;
+
+ memset(&prim, 0, sizeof(prim));
+ prim.count = count;
+
+ memset(&ib, 0, sizeof(ib));
+ ib.type = type;
+ ib.ptr = indices;
+ ib.obj = ctx->Array.ElementArrayBufferObj;
+
+ vbo_get_minmax_index(ctx, &prim, &ib, &min, &max);
+
+ if (min + basevertex < 0 ||
+ max + basevertex > ctx->Array.ArrayObj->_MaxElement) {
+ /* the max element is out of bounds of one or more enabled arrays */
+ _mesa_warning(ctx, "glDrawElements() index=%u is "
+ "out of bounds (max=%u)", max, ctx->Array.ArrayObj->_MaxElement);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+/**
+ * Error checking for glDrawElements(). Includes parameter checking
+ * and VBO bounds checking.
+ * \return GL_TRUE if OK to render, GL_FALSE if error found
+ */
GLboolean
_mesa_validate_DrawElements(GLcontext *ctx,
GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices)
+ const GLvoid *indices, GLint basevertex)
{
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
@@ -125,27 +148,14 @@ _mesa_validate_DrawElements(GLcontext *ctx,
if (ctx->NewState)
_mesa_update_state(ctx);
- if (!check_valid_to_render(ctx, "Elements"))
+ if (!check_valid_to_render(ctx, "glDrawElements"))
return GL_FALSE;
/* Vertex buffer object tests */
- if (ctx->Array.ElementArrayBufferObj->Name) {
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
/* use indices in the buffer object */
- GLuint indexBytes;
-
- if (type == GL_UNSIGNED_INT) {
- indexBytes = count * sizeof(GLuint);
- }
- else if (type == GL_UNSIGNED_BYTE) {
- indexBytes = count * sizeof(GLubyte);
- }
- else {
- ASSERT(type == GL_UNSIGNED_SHORT);
- indexBytes = count * sizeof(GLushort);
- }
-
/* make sure count doesn't go outside buffer bounds */
- if (indexBytes > (GLuint) ctx->Array.ElementArrayBufferObj->Size) {
+ if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) {
_mesa_warning(ctx, "glDrawElements index out of buffer bounds");
return GL_FALSE;
}
@@ -156,24 +166,23 @@ _mesa_validate_DrawElements(GLcontext *ctx,
return GL_FALSE;
}
- if (ctx->Const.CheckArrayBounds) {
- /* find max array index */
- GLuint max = max_buffer_index(ctx, count, type, indices,
- ctx->Array.ElementArrayBufferObj);
- if (max >= ctx->Array._MaxElement) {
- /* the max element is out of bounds of one or more enabled arrays */
- return GL_FALSE;
- }
- }
+ if (!check_index_bounds(ctx, count, type, indices, basevertex))
+ return GL_FALSE;
return GL_TRUE;
}
+
+/**
+ * Error checking for glDrawRangeElements(). Includes parameter checking
+ * and VBO bounds checking.
+ * \return GL_TRUE if OK to render, GL_FALSE if error found
+ */
GLboolean
_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
GLuint start, GLuint end,
GLsizei count, GLenum type,
- const GLvoid *indices)
+ const GLvoid *indices, GLint basevertex)
{
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
@@ -203,27 +212,14 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
if (ctx->NewState)
_mesa_update_state(ctx);
- if (!check_valid_to_render(ctx, "RangeElements"))
+ if (!check_valid_to_render(ctx, "glDrawRangeElements"))
return GL_FALSE;
/* Vertex buffer object tests */
- if (ctx->Array.ElementArrayBufferObj->Name) {
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
/* use indices in the buffer object */
- GLuint indexBytes;
-
- if (type == GL_UNSIGNED_INT) {
- indexBytes = count * sizeof(GLuint);
- }
- else if (type == GL_UNSIGNED_BYTE) {
- indexBytes = count * sizeof(GLubyte);
- }
- else {
- ASSERT(type == GL_UNSIGNED_SHORT);
- indexBytes = count * sizeof(GLushort);
- }
-
/* make sure count doesn't go outside buffer bounds */
- if (indexBytes > ctx->Array.ElementArrayBufferObj->Size) {
+ if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) {
_mesa_warning(ctx, "glDrawRangeElements index out of buffer bounds");
return GL_FALSE;
}
@@ -234,14 +230,8 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
return GL_FALSE;
}
- if (ctx->Const.CheckArrayBounds) {
- GLuint max = max_buffer_index(ctx, count, type, indices,
- ctx->Array.ElementArrayBufferObj);
- if (max >= ctx->Array._MaxElement) {
- /* the max element is out of bounds of one or more enabled arrays */
- return GL_FALSE;
- }
- }
+ if (!check_index_bounds(ctx, count, type, indices, basevertex))
+ return GL_FALSE;
return GL_TRUE;
}
@@ -250,6 +240,7 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
/**
* Called from the tnl module to error check the function parameters and
* verify that we really can draw something.
+ * \return GL_TRUE if OK to render, GL_FALSE if error found
*/
GLboolean
_mesa_validate_DrawArrays(GLcontext *ctx,
@@ -271,11 +262,11 @@ _mesa_validate_DrawArrays(GLcontext *ctx,
if (ctx->NewState)
_mesa_update_state(ctx);
- if (!check_valid_to_render(ctx, "Arrays"))
+ if (!check_valid_to_render(ctx, "glDrawArrays"))
return GL_FALSE;
if (ctx->Const.CheckArrayBounds) {
- if (start + count > (GLint) ctx->Array._MaxElement)
+ if (start + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
return GL_FALSE;
}
diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h
index 10f0c34e66..1d3ae157d7 100644
--- a/src/mesa/main/api_validate.h
+++ b/src/mesa/main/api_validate.h
@@ -37,13 +37,13 @@ _mesa_validate_DrawArrays(GLcontext *ctx,
extern GLboolean
_mesa_validate_DrawElements(GLcontext *ctx,
GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices);
+ const GLvoid *indices, GLint basevertex);
extern GLboolean
_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
GLuint start, GLuint end,
GLsizei count, GLenum type,
- const GLvoid *indices);
+ const GLvoid *indices, GLint basevertex);
#endif
diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c
index f3f482f8c8..fd35d4e38c 100644
--- a/src/mesa/main/arrayobj.c
+++ b/src/mesa/main/arrayobj.c
@@ -1,9 +1,10 @@
/*
* Mesa 3-D graphics library
- * Version: 7.2
+ * Version: 7.6
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* (C) Copyright IBM Corporation 2006
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -46,6 +47,7 @@
#include "bufferobj.h"
#endif
#include "arrayobj.h"
+#include "macros.h"
#include "glapi/dispatch.h"
@@ -61,10 +63,38 @@
static INLINE struct gl_array_object *
lookup_arrayobj(GLcontext *ctx, GLuint id)
{
- return (id == 0)
- ? NULL
- : (struct gl_array_object *) _mesa_HashLookup(ctx->Shared->ArrayObjects,
- id);
+ if (id == 0)
+ return NULL;
+ else
+ return (struct gl_array_object *)
+ _mesa_HashLookup(ctx->Array.Objects, id);
+}
+
+
+/**
+ * For all the vertex arrays in the array object, unbind any pointers
+ * to any buffer objects (VBOs).
+ * This is done just prior to array object destruction.
+ */
+static void
+unbind_array_object_vbos(GLcontext *ctx, struct gl_array_object *obj)
+{
+ GLuint i;
+
+ _mesa_reference_buffer_object(ctx, &obj->Vertex.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Weight.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Normal.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Color.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->SecondaryColor.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->FogCoord.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Index.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->EdgeFlag.BufferObj, NULL);
+
+ for (i = 0; i < Elements(obj->TexCoord); i++)
+ _mesa_reference_buffer_object(ctx, &obj->TexCoord[i].BufferObj, NULL);
+
+ for (i = 0; i < Elements(obj->VertexAttrib); i++)
+ _mesa_reference_buffer_object(ctx, &obj->VertexAttrib[i].BufferObj,NULL);
}
@@ -94,10 +124,93 @@ void
_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj )
{
(void) ctx;
+ unbind_array_object_vbos(ctx, obj);
+ _glthread_DESTROY_MUTEX(obj->Mutex);
_mesa_free(obj);
}
+/**
+ * Set ptr to arrayObj w/ reference counting.
+ */
+void
+_mesa_reference_array_object(GLcontext *ctx,
+ struct gl_array_object **ptr,
+ struct gl_array_object *arrayObj)
+{
+ if (*ptr == arrayObj)
+ return;
+
+ if (*ptr) {
+ /* Unreference the old array object */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_array_object *oldObj = *ptr;
+
+ _glthread_LOCK_MUTEX(oldObj->Mutex);
+ ASSERT(oldObj->RefCount > 0);
+ oldObj->RefCount--;
+#if 0
+ printf("ArrayObj %p %d DECR to %d\n",
+ (void *) oldObj, oldObj->Name, oldObj->RefCount);
+#endif
+ deleteFlag = (oldObj->RefCount == 0);
+ _glthread_UNLOCK_MUTEX(oldObj->Mutex);
+
+ if (deleteFlag) {
+ ASSERT(ctx->Driver.DeleteArrayObject);
+ ctx->Driver.DeleteArrayObject(ctx, oldObj);
+ }
+
+ *ptr = NULL;
+ }
+ ASSERT(!*ptr);
+
+ if (arrayObj) {
+ /* reference new array object */
+ _glthread_LOCK_MUTEX(arrayObj->Mutex);
+ if (arrayObj->RefCount == 0) {
+ /* this array's being deleted (look just above) */
+ /* Not sure this can every really happen. Warn if it does. */
+ _mesa_problem(NULL, "referencing deleted array object");
+ *ptr = NULL;
+ }
+ else {
+ arrayObj->RefCount++;
+#if 0
+ printf("ArrayObj %p %d INCR to %d\n",
+ (void *) arrayObj, arrayObj->Name, arrayObj->RefCount);
+#endif
+ *ptr = arrayObj;
+ }
+ _glthread_UNLOCK_MUTEX(arrayObj->Mutex);
+ }
+}
+
+
+
+static void
+init_array(GLcontext *ctx,
+ struct gl_client_array *array, GLint size, GLint type)
+{
+ array->Size = size;
+ array->Type = type;
+ array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
+ array->Stride = 0;
+ array->StrideB = 0;
+ array->Ptr = NULL;
+ array->Enabled = GL_FALSE;
+ array->Normalized = GL_FALSE;
+#if FEATURE_ARB_vertex_buffer_object
+ /* Vertex array buffers */
+ _mesa_reference_buffer_object(ctx, &array->BufferObj,
+ ctx->Shared->NullBufferObj);
+#endif
+}
+
+
+/**
+ * Initialize a gl_array_object's arrays.
+ */
void
_mesa_initialize_array_object( GLcontext *ctx,
struct gl_array_object *obj,
@@ -107,87 +220,27 @@ _mesa_initialize_array_object( GLcontext *ctx,
obj->Name = name;
- /* Vertex arrays */
- obj->Vertex.Size = 4;
- obj->Vertex.Type = GL_FLOAT;
- obj->Vertex.Stride = 0;
- obj->Vertex.StrideB = 0;
- obj->Vertex.Ptr = NULL;
- obj->Vertex.Enabled = GL_FALSE;
- obj->Normal.Type = GL_FLOAT;
- obj->Normal.Stride = 0;
- obj->Normal.StrideB = 0;
- obj->Normal.Ptr = NULL;
- obj->Normal.Enabled = GL_FALSE;
- obj->Color.Size = 4;
- obj->Color.Type = GL_FLOAT;
- obj->Color.Stride = 0;
- obj->Color.StrideB = 0;
- obj->Color.Ptr = NULL;
- obj->Color.Enabled = GL_FALSE;
- obj->SecondaryColor.Size = 4;
- obj->SecondaryColor.Type = GL_FLOAT;
- obj->SecondaryColor.Stride = 0;
- obj->SecondaryColor.StrideB = 0;
- obj->SecondaryColor.Ptr = NULL;
- obj->SecondaryColor.Enabled = GL_FALSE;
- obj->FogCoord.Size = 1;
- obj->FogCoord.Type = GL_FLOAT;
- obj->FogCoord.Stride = 0;
- obj->FogCoord.StrideB = 0;
- obj->FogCoord.Ptr = NULL;
- obj->FogCoord.Enabled = GL_FALSE;
- obj->Index.Type = GL_FLOAT;
- obj->Index.Stride = 0;
- obj->Index.StrideB = 0;
- obj->Index.Ptr = NULL;
- obj->Index.Enabled = GL_FALSE;
- for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
- obj->TexCoord[i].Size = 4;
- obj->TexCoord[i].Type = GL_FLOAT;
- obj->TexCoord[i].Stride = 0;
- obj->TexCoord[i].StrideB = 0;
- obj->TexCoord[i].Ptr = NULL;
- obj->TexCoord[i].Enabled = GL_FALSE;
+ _glthread_INIT_MUTEX(obj->Mutex);
+ obj->RefCount = 1;
+
+ /* Init the individual arrays */
+ init_array(ctx, &obj->Vertex, 4, GL_FLOAT);
+ 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->FogCoord, 1, GL_FLOAT);
+ init_array(ctx, &obj->Index, 1, GL_FLOAT);
+ for (i = 0; i < Elements(obj->TexCoord); i++) {
+ init_array(ctx, &obj->TexCoord[i], 4, GL_FLOAT);
}
- obj->EdgeFlag.Stride = 0;
- obj->EdgeFlag.StrideB = 0;
- obj->EdgeFlag.Ptr = NULL;
- obj->EdgeFlag.Enabled = GL_FALSE;
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- obj->VertexAttrib[i].Size = 4;
- obj->VertexAttrib[i].Type = GL_FLOAT;
- obj->VertexAttrib[i].Stride = 0;
- obj->VertexAttrib[i].StrideB = 0;
- obj->VertexAttrib[i].Ptr = NULL;
- obj->VertexAttrib[i].Enabled = GL_FALSE;
- obj->VertexAttrib[i].Normalized = GL_FALSE;
+ init_array(ctx, &obj->EdgeFlag, 1, GL_BOOL);
+ for (i = 0; i < Elements(obj->VertexAttrib); i++) {
+ init_array(ctx, &obj->VertexAttrib[i], 4, GL_FLOAT);
}
#if FEATURE_point_size_array
- obj->PointSize.Type = GL_FLOAT;
- obj->PointSize.Stride = 0;
- obj->PointSize.StrideB = 0;
- obj->PointSize.Ptr = NULL;
- obj->PointSize.Enabled = GL_FALSE;
- obj->PointSize.BufferObj = ctx->Array.NullBufferObj;
-#endif
-
-#if FEATURE_ARB_vertex_buffer_object
- /* Vertex array buffers */
- obj->Vertex.BufferObj = ctx->Array.NullBufferObj;
- obj->Normal.BufferObj = ctx->Array.NullBufferObj;
- obj->Color.BufferObj = ctx->Array.NullBufferObj;
- obj->SecondaryColor.BufferObj = ctx->Array.NullBufferObj;
- obj->FogCoord.BufferObj = ctx->Array.NullBufferObj;
- obj->Index.BufferObj = ctx->Array.NullBufferObj;
- for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
- obj->TexCoord[i].BufferObj = ctx->Array.NullBufferObj;
- }
- obj->EdgeFlag.BufferObj = ctx->Array.NullBufferObj;
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- obj->VertexAttrib[i].BufferObj = ctx->Array.NullBufferObj;
- }
+ init_array(ctx, &obj->PointSize, 1, GL_FLOAT);
#endif
}
@@ -195,12 +248,12 @@ _mesa_initialize_array_object( GLcontext *ctx,
/**
* Add the given array object to the array object pool.
*/
-void
-_mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj )
+static void
+save_array_object( GLcontext *ctx, struct gl_array_object *obj )
{
if (obj->Name > 0) {
/* insert into hash table */
- _mesa_HashInsert(ctx->Shared->ArrayObjects, obj->Name, obj);
+ _mesa_HashInsert(ctx->Array.Objects, obj->Name, obj);
}
}
@@ -209,22 +262,90 @@ _mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj )
* Remove the given array object from the array object pool.
* Do not deallocate the array object though.
*/
-void
-_mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj )
+static void
+remove_array_object( GLcontext *ctx, struct gl_array_object *obj )
{
if (obj->Name > 0) {
/* remove from hash table */
- _mesa_HashRemove(ctx->Shared->ArrayObjects, obj->Name);
+ _mesa_HashRemove(ctx->Array.Objects, obj->Name);
}
}
+
+/**
+ * Compute the index of the last array element that can be safely accessed
+ * in a vertex array. We can really only do this when the array lives in
+ * a VBO.
+ * The array->_MaxElement field will be updated.
+ * Later in glDrawArrays/Elements/etc we can do some bounds checking.
+ */
static void
-unbind_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj )
+compute_max_element(struct gl_client_array *array)
{
- if (bufObj != ctx->Array.NullBufferObj) {
- _mesa_reference_buffer_object(ctx, &bufObj, NULL);
+ if (array->BufferObj->Name) {
+ /* Compute the max element we can access in the VBO without going
+ * out of bounds.
+ */
+ array->_MaxElement = ((GLsizeiptrARB) array->BufferObj->Size
+ - (GLsizeiptrARB) array->Ptr + array->StrideB
+ - array->_ElementSize) / array->StrideB;
+ if (0)
+ _mesa_printf("%s Object %u Size %u MaxElement %u\n",
+ __FUNCTION__,
+ array->BufferObj->Name,
+ (GLuint) array->BufferObj->Size,
+ array->_MaxElement);
}
+ else {
+ /* user-space array, no idea how big it is */
+ array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */
+ }
+}
+
+
+/**
+ * Helper for update_arrays().
+ * \return min(current min, array->_MaxElement).
+ */
+static GLuint
+update_min(GLuint min, struct gl_client_array *array)
+{
+ compute_max_element(array);
+ if (array->Enabled)
+ return MIN2(min, array->_MaxElement);
+ else
+ return min;
+}
+
+
+/**
+ * Examine vertex arrays to update the gl_array_object::_MaxElement field.
+ */
+void
+_mesa_update_array_object_max_element(GLcontext *ctx,
+ struct gl_array_object *arrayObj)
+{
+ GLuint i, min = ~0;
+
+ min = update_min(min, &arrayObj->Vertex);
+ min = update_min(min, &arrayObj->Weight);
+ min = update_min(min, &arrayObj->Normal);
+ min = update_min(min, &arrayObj->Color);
+ min = update_min(min, &arrayObj->SecondaryColor);
+ min = update_min(min, &arrayObj->FogCoord);
+ min = update_min(min, &arrayObj->Index);
+ min = update_min(min, &arrayObj->EdgeFlag);
+#if FEATURE_point_size_array
+ min = update_min(min, &arrayObj->PointSize);
+#endif
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
+ min = update_min(min, &arrayObj->TexCoord[i]);
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
+ min = update_min(min, &arrayObj->VertexAttrib[i]);
+
+ /* _MaxElement is one past the last legal array element */
+ arrayObj->_MaxElement = min;
}
@@ -232,18 +353,15 @@ unbind_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj )
/* API Functions */
/**********************************************************************/
+
/**
- * Bind a new array.
- *
- * \todo
- * The binding could be done more efficiently by comparing the non-NULL
- * pointers in the old and new objects. The only arrays that are "dirty" are
- * the ones that are non-NULL in either object.
+ * Helper for _mesa_BindVertexArray() and _mesa_BindVertexArrayAPPLE().
+ * \param genRequired specifies behavour when id was not generated with
+ * glGenVertexArrays().
*/
-void GLAPIENTRY
-_mesa_BindVertexArrayAPPLE( GLuint id )
+static void
+bind_vertex_array(GLcontext *ctx, GLuint id, GLboolean genRequired)
{
- GET_CURRENT_CONTEXT(ctx);
struct gl_array_object * const oldObj = ctx->Array.ArrayObj;
struct gl_array_object *newObj = NULL;
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -254,7 +372,7 @@ _mesa_BindVertexArrayAPPLE( GLuint id )
return; /* rebinding the same array object- no change */
/*
- * Get pointer to new array object (newBufObj)
+ * Get pointer to new array object (newObj)
*/
if (id == 0) {
/* The spec says there is no array object named 0, but we use
@@ -266,27 +384,58 @@ _mesa_BindVertexArrayAPPLE( GLuint id )
/* non-default array object */
newObj = lookup_arrayobj(ctx, id);
if (!newObj) {
- /* If this is a new array object id, allocate an array object now.
- */
+ if (genRequired) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindVertexArray(id)");
+ return;
+ }
+ /* For APPLE version, generate a new array object now */
newObj = (*ctx->Driver.NewArrayObject)(ctx, id);
if (!newObj) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE");
return;
}
- _mesa_save_array_object(ctx, newObj);
+ save_array_object(ctx, newObj);
}
}
-
ctx->NewState |= _NEW_ARRAY;
ctx->Array.NewState |= _NEW_ARRAY_ALL;
- ctx->Array.ArrayObj = newObj;
-
+ _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, newObj);
/* Pass BindVertexArray call to device driver */
if (ctx->Driver.BindArrayObject && newObj)
- (*ctx->Driver.BindArrayObject)( ctx, newObj );
+ ctx->Driver.BindArrayObject(ctx, newObj);
+}
+
+
+/**
+ * ARB version of glBindVertexArray()
+ * This function behaves differently from glBindVertexArrayAPPLE() in
+ * that this function requires all ids to have been previously generated
+ * by glGenVertexArrays[APPLE]().
+ */
+void GLAPIENTRY
+_mesa_BindVertexArray( GLuint id )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ bind_vertex_array(ctx, id, GL_TRUE);
+}
+
+
+/**
+ * Bind a new array.
+ *
+ * \todo
+ * The binding could be done more efficiently by comparing the non-NULL
+ * pointers in the old and new objects. The only arrays that are "dirty" are
+ * the ones that are non-NULL in either object.
+ */
+void GLAPIENTRY
+_mesa_BindVertexArrayAPPLE( GLuint id )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ bind_vertex_array(ctx, id, GL_FALSE);
}
@@ -308,15 +457,12 @@ _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids)
return;
}
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
-
for (i = 0; i < n; i++) {
struct gl_array_object *obj = lookup_arrayobj(ctx, ids[i]);
if ( obj != NULL ) {
ASSERT( obj->Name == ids[i] );
-
/* If the array object is currently bound, the spec says "the binding
* for that object reverts to zero and the default vertex array
* becomes current."
@@ -325,45 +471,28 @@ _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids)
CALL_BindVertexArrayAPPLE( ctx->Exec, (0) );
}
-#if FEATURE_ARB_vertex_buffer_object
- /* Unbind any buffer objects that might be bound to arrays in
- * this array object.
- */
- unbind_buffer_object( ctx, obj->Vertex.BufferObj );
- unbind_buffer_object( ctx, obj->Normal.BufferObj );
- unbind_buffer_object( ctx, obj->Color.BufferObj );
- unbind_buffer_object( ctx, obj->SecondaryColor.BufferObj );
- unbind_buffer_object( ctx, obj->FogCoord.BufferObj );
- unbind_buffer_object( ctx, obj->Index.BufferObj );
- for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
- unbind_buffer_object( ctx, obj->TexCoord[i].BufferObj );
- }
- unbind_buffer_object( ctx, obj->EdgeFlag.BufferObj );
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
- unbind_buffer_object( ctx, obj->VertexAttrib[i].BufferObj );
- }
-#endif
-
/* The ID is immediately freed for re-use */
- _mesa_remove_array_object(ctx, obj);
- ctx->Driver.DeleteArrayObject(ctx, obj);
+ remove_array_object(ctx, obj);
+
+ /* Unreference the array object.
+ * If refcount hits zero, the object will be deleted.
+ */
+ _mesa_reference_array_object(ctx, &obj, NULL);
}
}
-
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
}
/**
* Generate a set of unique array object IDs and store them in \c arrays.
- *
+ * Helper for _mesa_GenVertexArrays[APPLE]() functions below.
* \param n Number of IDs to generate.
* \param arrays Array of \c n locations to store the IDs.
+ * \param vboOnly Will arrays have to reside in VBOs?
*/
-void GLAPIENTRY
-_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
+static void
+gen_vertex_arrays(GLcontext *ctx, GLsizei n, GLuint *arrays, GLboolean vboOnly)
{
- GET_CURRENT_CONTEXT(ctx);
GLuint first;
GLint i;
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -377,12 +506,7 @@ _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
return;
}
- /*
- * This must be atomic (generation and allocation of array object IDs)
- */
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
-
- first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ArrayObjects, n);
+ first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n);
/* Allocate new, empty array objects and return identifiers */
for (i = 0; i < n; i++) {
@@ -391,15 +515,37 @@ _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
obj = (*ctx->Driver.NewArrayObject)( ctx, name );
if (!obj) {
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE");
return;
}
- _mesa_save_array_object(ctx, obj);
+ obj->VBOonly = vboOnly;
+ save_array_object(ctx, obj);
arrays[i] = first + i;
}
+}
+
+
+/**
+ * ARB version of glGenVertexArrays()
+ * All arrays will be required to live in VBOs.
+ */
+void GLAPIENTRY
+_mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ gen_vertex_arrays(ctx, n, arrays, GL_TRUE);
+}
+
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+/**
+ * APPLE version of glGenVertexArraysAPPLE()
+ * Arrays may live in VBOs or ordinary memory.
+ */
+void GLAPIENTRY
+_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ gen_vertex_arrays(ctx, n, arrays, GL_FALSE);
}
@@ -420,9 +566,7 @@ _mesa_IsVertexArrayAPPLE( GLuint id )
if (id == 0)
return GL_FALSE;
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
obj = lookup_arrayobj(ctx, id);
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
return (obj != NULL) ? GL_TRUE : GL_FALSE;
}
diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h
index c7d66ec166..8999edc724 100644
--- a/src/mesa/main/arrayobj.h
+++ b/src/mesa/main/arrayobj.h
@@ -1,9 +1,10 @@
/*
* Mesa 3-D graphics library
- * Version: 6.5
+ * Version: 7.6
*
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
* (C) Copyright IBM Corporation 2006
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -41,28 +42,40 @@
* Internal functions
*/
-struct gl_array_object * _mesa_new_array_object( GLcontext *ctx,
- GLuint name );
+extern struct gl_array_object *
+_mesa_new_array_object( GLcontext *ctx, GLuint name );
-void _mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj );
+extern void
+_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj );
-void _mesa_initialize_array_object( GLcontext *ctx,
- struct gl_array_object *obj, GLuint name );
+extern void
+_mesa_reference_array_object(GLcontext *ctx,
+ struct gl_array_object **ptr,
+ struct gl_array_object *arrayObj);
-void _mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj );
+extern void
+_mesa_initialize_array_object( GLcontext *ctx,
+ struct gl_array_object *obj, GLuint name );
-void _mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj );
+extern void
+_mesa_update_array_object_max_element(GLcontext *ctx,
+ struct gl_array_object *arrayObj);
/*
* API functions
*/
+
+void GLAPIENTRY _mesa_BindVertexArray( GLuint id );
+
void GLAPIENTRY _mesa_BindVertexArrayAPPLE( GLuint id );
void GLAPIENTRY _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids);
+void GLAPIENTRY _mesa_GenVertexArrays(GLsizei n, GLuint *arrays);
+
void GLAPIENTRY _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *buffer);
GLboolean GLAPIENTRY _mesa_IsVertexArrayAPPLE( GLuint id );
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index 825c841ee2..246c5521b7 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.3
+ * Version: 7.6
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
@@ -55,8 +55,107 @@
#include "texparam.h"
#include "texstate.h"
#include "varray.h"
+#include "viewport.h"
#include "mtypes.h"
-#include "math/m_xform.h"
+#include "glapi/dispatch.h"
+
+
+/**
+ * glEnable()/glDisable() attribute group (GL_ENABLE_BIT).
+ */
+struct gl_enable_attrib
+{
+ GLboolean AlphaTest;
+ GLboolean AutoNormal;
+ GLboolean Blend;
+ GLbitfield ClipPlanes;
+ GLboolean ColorMaterial;
+ GLboolean ColorTable[COLORTABLE_MAX];
+ GLboolean Convolution1D;
+ GLboolean Convolution2D;
+ GLboolean Separable2D;
+ GLboolean CullFace;
+ GLboolean DepthClamp;
+ GLboolean DepthTest;
+ GLboolean Dither;
+ GLboolean Fog;
+ GLboolean Histogram;
+ GLboolean Light[MAX_LIGHTS];
+ GLboolean Lighting;
+ GLboolean LineSmooth;
+ GLboolean LineStipple;
+ GLboolean IndexLogicOp;
+ GLboolean ColorLogicOp;
+
+ GLboolean Map1Color4;
+ GLboolean Map1Index;
+ GLboolean Map1Normal;
+ GLboolean Map1TextureCoord1;
+ GLboolean Map1TextureCoord2;
+ GLboolean Map1TextureCoord3;
+ GLboolean Map1TextureCoord4;
+ GLboolean Map1Vertex3;
+ GLboolean Map1Vertex4;
+ GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
+ GLboolean Map2Color4;
+ GLboolean Map2Index;
+ GLboolean Map2Normal;
+ GLboolean Map2TextureCoord1;
+ GLboolean Map2TextureCoord2;
+ GLboolean Map2TextureCoord3;
+ GLboolean Map2TextureCoord4;
+ GLboolean Map2Vertex3;
+ GLboolean Map2Vertex4;
+ GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
+
+ GLboolean MinMax;
+ GLboolean Normalize;
+ GLboolean PixelTexture;
+ GLboolean PointSmooth;
+ GLboolean PolygonOffsetPoint;
+ GLboolean PolygonOffsetLine;
+ GLboolean PolygonOffsetFill;
+ GLboolean PolygonSmooth;
+ GLboolean PolygonStipple;
+ GLboolean RescaleNormals;
+ GLboolean Scissor;
+ GLboolean Stencil;
+ GLboolean StencilTwoSide; /* GL_EXT_stencil_two_side */
+ GLboolean MultisampleEnabled; /* GL_ARB_multisample */
+ GLboolean SampleAlphaToCoverage; /* GL_ARB_multisample */
+ GLboolean SampleAlphaToOne; /* GL_ARB_multisample */
+ GLboolean SampleCoverage; /* GL_ARB_multisample */
+ GLboolean SampleCoverageInvert; /* GL_ARB_multisample */
+ GLboolean RasterPositionUnclipped; /* GL_IBM_rasterpos_clip */
+
+ GLbitfield Texture[MAX_TEXTURE_UNITS];
+ GLbitfield TexGen[MAX_TEXTURE_UNITS];
+
+ /* SGI_texture_color_table */
+ GLboolean TextureColorTable[MAX_TEXTURE_UNITS];
+
+ /* GL_ARB_vertex_program / GL_NV_vertex_program */
+ GLboolean VertexProgram;
+ GLboolean VertexProgramPointSize;
+ GLboolean VertexProgramTwoSide;
+
+ /* GL_ARB_point_sprite / GL_NV_point_sprite */
+ GLboolean PointSprite;
+ GLboolean FragmentShaderATI;
+};
+
+
+/**
+ * Node for the attribute stack.
+ */
+struct gl_attrib_node
+{
+ GLbitfield kind;
+ void *data;
+ struct gl_attrib_node *next;
+};
+
+
/**
* Special struct for saving/restoring texture state (GL_TEXTURE_BIT)
@@ -76,25 +175,34 @@ struct texture_state
};
+#if FEATURE_attrib_stack
+
+
/**
- * Allocate a new attribute state node. These nodes have a
- * "kind" value and a pointer to a struct of state data.
+ * Allocate new attribute node of given type/kind. Attach payload data.
+ * Insert it into the linked list named by 'head'.
*/
-static struct gl_attrib_node *
-new_attrib_node( GLbitfield kind )
+static void
+save_attrib_data(struct gl_attrib_node **head,
+ GLbitfield kind, void *payload)
{
- struct gl_attrib_node *an = MALLOC_STRUCT(gl_attrib_node);
- if (an) {
- an->kind = kind;
+ struct gl_attrib_node *n = MALLOC_STRUCT(gl_attrib_node);
+ if (n) {
+ n->kind = kind;
+ n->data = payload;
+ /* insert at head */
+ n->next = *head;
+ *head = n;
+ }
+ else {
+ /* out of memory! */
}
- return an;
}
void GLAPIENTRY
_mesa_PushAttrib(GLbitfield mask)
{
- struct gl_attrib_node *newnode;
struct gl_attrib_node *head;
GET_CURRENT_CONTEXT(ctx);
@@ -116,10 +224,7 @@ _mesa_PushAttrib(GLbitfield mask)
struct gl_accum_attrib *attr;
attr = MALLOC_STRUCT( gl_accum_attrib );
MEMCPY( attr, &ctx->Accum, sizeof(struct gl_accum_attrib) );
- newnode = new_attrib_node( GL_ACCUM_BUFFER_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_ACCUM_BUFFER_BIT, attr);
}
if (mask & GL_COLOR_BUFFER_BIT) {
@@ -130,10 +235,7 @@ _mesa_PushAttrib(GLbitfield mask)
/* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */
for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++)
attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i];
- newnode = new_attrib_node( GL_COLOR_BUFFER_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_COLOR_BUFFER_BIT, attr);
}
if (mask & GL_CURRENT_BIT) {
@@ -141,20 +243,14 @@ _mesa_PushAttrib(GLbitfield mask)
FLUSH_CURRENT( ctx, 0 );
attr = MALLOC_STRUCT( gl_current_attrib );
MEMCPY( attr, &ctx->Current, sizeof(struct gl_current_attrib) );
- newnode = new_attrib_node( GL_CURRENT_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_CURRENT_BIT, attr);
}
if (mask & GL_DEPTH_BUFFER_BIT) {
struct gl_depthbuffer_attrib *attr;
attr = MALLOC_STRUCT( gl_depthbuffer_attrib );
MEMCPY( attr, &ctx->Depth, sizeof(struct gl_depthbuffer_attrib) );
- newnode = new_attrib_node( GL_DEPTH_BUFFER_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_DEPTH_BUFFER_BIT, attr);
}
if (mask & GL_ENABLE_BIT) {
@@ -174,6 +270,7 @@ _mesa_PushAttrib(GLbitfield mask)
attr->Convolution2D = ctx->Pixel.Convolution2DEnabled;
attr->Separable2D = ctx->Pixel.Separable2DEnabled;
attr->CullFace = ctx->Polygon.CullFlag;
+ attr->DepthClamp = ctx->Transform.DepthClamp;
attr->DepthTest = ctx->Depth.Test;
attr->Dither = ctx->Color.DitherFlag;
attr->Fog = ctx->Fog.Enabled;
@@ -234,40 +331,28 @@ _mesa_PushAttrib(GLbitfield mask)
attr->VertexProgram = ctx->VertexProgram.Enabled;
attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled;
attr->VertexProgramTwoSide = ctx->VertexProgram.TwoSideEnabled;
- newnode = new_attrib_node( GL_ENABLE_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_ENABLE_BIT, attr);
}
if (mask & GL_EVAL_BIT) {
struct gl_eval_attrib *attr;
attr = MALLOC_STRUCT( gl_eval_attrib );
MEMCPY( attr, &ctx->Eval, sizeof(struct gl_eval_attrib) );
- newnode = new_attrib_node( GL_EVAL_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_EVAL_BIT, attr);
}
if (mask & GL_FOG_BIT) {
struct gl_fog_attrib *attr;
attr = MALLOC_STRUCT( gl_fog_attrib );
MEMCPY( attr, &ctx->Fog, sizeof(struct gl_fog_attrib) );
- newnode = new_attrib_node( GL_FOG_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_FOG_BIT, attr);
}
if (mask & GL_HINT_BIT) {
struct gl_hint_attrib *attr;
attr = MALLOC_STRUCT( gl_hint_attrib );
MEMCPY( attr, &ctx->Hint, sizeof(struct gl_hint_attrib) );
- newnode = new_attrib_node( GL_HINT_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_HINT_BIT, attr);
}
if (mask & GL_LIGHTING_BIT) {
@@ -275,30 +360,21 @@ _mesa_PushAttrib(GLbitfield mask)
FLUSH_CURRENT(ctx, 0); /* flush material changes */
attr = MALLOC_STRUCT( gl_light_attrib );
MEMCPY( attr, &ctx->Light, sizeof(struct gl_light_attrib) );
- newnode = new_attrib_node( GL_LIGHTING_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_LIGHTING_BIT, attr);
}
if (mask & GL_LINE_BIT) {
struct gl_line_attrib *attr;
attr = MALLOC_STRUCT( gl_line_attrib );
MEMCPY( attr, &ctx->Line, sizeof(struct gl_line_attrib) );
- newnode = new_attrib_node( GL_LINE_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_LINE_BIT, attr);
}
if (mask & GL_LIST_BIT) {
struct gl_list_attrib *attr;
attr = MALLOC_STRUCT( gl_list_attrib );
MEMCPY( attr, &ctx->List, sizeof(struct gl_list_attrib) );
- newnode = new_attrib_node( GL_LIST_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_LIST_BIT, attr);
}
if (mask & GL_PIXEL_MODE_BIT) {
@@ -307,65 +383,47 @@ _mesa_PushAttrib(GLbitfield mask)
MEMCPY( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) );
/* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */
attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer;
- newnode = new_attrib_node( GL_PIXEL_MODE_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_PIXEL_MODE_BIT, attr);
}
if (mask & GL_POINT_BIT) {
struct gl_point_attrib *attr;
attr = MALLOC_STRUCT( gl_point_attrib );
MEMCPY( attr, &ctx->Point, sizeof(struct gl_point_attrib) );
- newnode = new_attrib_node( GL_POINT_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_POINT_BIT, attr);
}
if (mask & GL_POLYGON_BIT) {
struct gl_polygon_attrib *attr;
attr = MALLOC_STRUCT( gl_polygon_attrib );
MEMCPY( attr, &ctx->Polygon, sizeof(struct gl_polygon_attrib) );
- newnode = new_attrib_node( GL_POLYGON_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_POLYGON_BIT, attr);
}
if (mask & GL_POLYGON_STIPPLE_BIT) {
GLuint *stipple;
stipple = (GLuint *) MALLOC( 32*sizeof(GLuint) );
MEMCPY( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) );
- newnode = new_attrib_node( GL_POLYGON_STIPPLE_BIT );
- newnode->data = stipple;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_POLYGON_STIPPLE_BIT, stipple);
}
if (mask & GL_SCISSOR_BIT) {
struct gl_scissor_attrib *attr;
attr = MALLOC_STRUCT( gl_scissor_attrib );
MEMCPY( attr, &ctx->Scissor, sizeof(struct gl_scissor_attrib) );
- newnode = new_attrib_node( GL_SCISSOR_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_SCISSOR_BIT, attr);
}
if (mask & GL_STENCIL_BUFFER_BIT) {
struct gl_stencil_attrib *attr;
attr = MALLOC_STRUCT( gl_stencil_attrib );
MEMCPY( attr, &ctx->Stencil, sizeof(struct gl_stencil_attrib) );
- newnode = new_attrib_node( GL_STENCIL_BUFFER_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_STENCIL_BUFFER_BIT, attr);
}
if (mask & GL_TEXTURE_BIT) {
struct texture_state *texstate = CALLOC_STRUCT(texture_state);
- GLuint u;
+ GLuint u, tex;
if (!texstate) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)");
@@ -381,66 +439,37 @@ _mesa_PushAttrib(GLbitfield mask)
* accidentally get deleted while referenced in the attribute stack.
*/
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_1D_INDEX],
- ctx->Texture.Unit[u].Current1D);
- _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_2D_INDEX],
- ctx->Texture.Unit[u].Current2D);
- _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_3D_INDEX],
- ctx->Texture.Unit[u].Current3D);
- _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_CUBE_INDEX],
- ctx->Texture.Unit[u].CurrentCubeMap);
- _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_RECT_INDEX],
- ctx->Texture.Unit[u].CurrentRect);
- _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_1D_ARRAY_INDEX],
- ctx->Texture.Unit[u].Current1DArray);
- _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_2D_ARRAY_INDEX],
- ctx->Texture.Unit[u].Current2DArray);
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&texstate->SavedTexRef[u][tex],
+ ctx->Texture.Unit[u].CurrentTex[tex]);
+ }
}
/* copy state/contents of the currently bound texture objects */
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_1D_INDEX],
- ctx->Texture.Unit[u].Current1D);
- _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_2D_INDEX],
- ctx->Texture.Unit[u].Current2D);
- _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_3D_INDEX],
- ctx->Texture.Unit[u].Current3D);
- _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_CUBE_INDEX],
- ctx->Texture.Unit[u].CurrentCubeMap);
- _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_RECT_INDEX],
- ctx->Texture.Unit[u].CurrentRect);
- _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_1D_ARRAY_INDEX],
- ctx->Texture.Unit[u].Current1DArray);
- _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_2D_ARRAY_INDEX],
- ctx->Texture.Unit[u].Current2DArray);
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_copy_texture_object(&texstate->SavedObj[u][tex],
+ ctx->Texture.Unit[u].CurrentTex[tex]);
+ }
}
_mesa_unlock_context_textures(ctx);
- newnode = new_attrib_node( GL_TEXTURE_BIT );
- newnode->data = texstate;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_TEXTURE_BIT, texstate);
}
if (mask & GL_TRANSFORM_BIT) {
struct gl_transform_attrib *attr;
attr = MALLOC_STRUCT( gl_transform_attrib );
MEMCPY( attr, &ctx->Transform, sizeof(struct gl_transform_attrib) );
- newnode = new_attrib_node( GL_TRANSFORM_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_TRANSFORM_BIT, attr);
}
if (mask & GL_VIEWPORT_BIT) {
struct gl_viewport_attrib *attr;
attr = MALLOC_STRUCT( gl_viewport_attrib );
MEMCPY( attr, &ctx->Viewport, sizeof(struct gl_viewport_attrib) );
- newnode = new_attrib_node( GL_VIEWPORT_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_VIEWPORT_BIT, attr);
}
/* GL_ARB_multisample */
@@ -448,10 +477,7 @@ _mesa_PushAttrib(GLbitfield mask)
struct gl_multisample_attrib *attr;
attr = MALLOC_STRUCT( gl_multisample_attrib );
MEMCPY( attr, &ctx->Multisample, sizeof(struct gl_multisample_attrib) );
- newnode = new_attrib_node( GL_MULTISAMPLE_BIT_ARB );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_MULTISAMPLE_BIT_ARB, attr);
}
end:
@@ -464,6 +490,7 @@ end:
static void
pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable)
{
+ const GLuint curTexUnitSave = ctx->Texture.CurrentUnit;
GLuint i;
#define TEST_AND_UPDATE(VALUE, NEWVALUE, ENUM) \
@@ -493,6 +520,8 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable)
enable->ColorTable[COLORTABLE_POSTCOLORMATRIX],
GL_POST_COLOR_MATRIX_COLOR_TABLE);
TEST_AND_UPDATE(ctx->Polygon.CullFlag, enable->CullFace, GL_CULL_FACE);
+ TEST_AND_UPDATE(ctx->Transform.DepthClamp, enable->DepthClamp,
+ GL_DEPTH_CLAMP);
TEST_AND_UPDATE(ctx->Depth.Test, enable->DepthTest, GL_DEPTH_TEST);
TEST_AND_UPDATE(ctx->Color.DitherFlag, enable->Dither, GL_DITHER);
TEST_AND_UPDATE(ctx->Pixel.Convolution1DEnabled, enable->Convolution1D,
@@ -608,59 +637,51 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable)
/* texture unit enables */
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (ctx->Texture.Unit[i].Enabled != enable->Texture[i]) {
- ctx->Texture.Unit[i].Enabled = enable->Texture[i];
- if (ctx->Driver.Enable) {
- if (ctx->Driver.ActiveTexture) {
- (*ctx->Driver.ActiveTexture)(ctx, i);
- }
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_1D,
- (GLboolean) (enable->Texture[i] & TEXTURE_1D_BIT) );
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_2D,
- (GLboolean) (enable->Texture[i] & TEXTURE_2D_BIT) );
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_3D,
- (GLboolean) (enable->Texture[i] & TEXTURE_3D_BIT) );
- if (ctx->Extensions.ARB_texture_cube_map)
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_CUBE_MAP_ARB,
- (GLboolean) (enable->Texture[i] & TEXTURE_CUBE_BIT) );
- if (ctx->Extensions.NV_texture_rectangle)
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_RECTANGLE_NV,
- (GLboolean) (enable->Texture[i] & TEXTURE_RECT_BIT) );
+ const GLbitfield enabled = enable->Texture[i];
+ const GLbitfield genEnabled = enable->TexGen[i];
+
+ if (ctx->Texture.Unit[i].Enabled != enabled) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
+
+ _mesa_set_enable(ctx, GL_TEXTURE_1D,
+ (enabled & TEXTURE_1D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D,
+ (enabled & TEXTURE_2D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_3D,
+ (enabled & TEXTURE_3D_BIT) ? GL_TRUE : GL_FALSE);
+ if (ctx->Extensions.NV_texture_rectangle) {
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_ARB,
+ (enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.ARB_texture_cube_map) {
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP,
+ (enabled & TEXTURE_CUBE_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.MESA_texture_array) {
+ _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT,
+ (enabled & TEXTURE_1D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT,
+ (enabled & TEXTURE_2D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
}
}
- if (ctx->Texture.Unit[i].TexGenEnabled != enable->TexGen[i]) {
- ctx->Texture.Unit[i].TexGenEnabled = enable->TexGen[i];
- if (ctx->Driver.Enable) {
- if (ctx->Driver.ActiveTexture) {
- (*ctx->Driver.ActiveTexture)(ctx, i);
- }
- if (enable->TexGen[i] & S_BIT)
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_S, GL_TRUE);
- else
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_S, GL_FALSE);
- if (enable->TexGen[i] & T_BIT)
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_T, GL_TRUE);
- else
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_T, GL_FALSE);
- if (enable->TexGen[i] & R_BIT)
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_R, GL_TRUE);
- else
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_R, GL_FALSE);
- if (enable->TexGen[i] & Q_BIT)
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_Q, GL_TRUE);
- else
- (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
- }
+ if (ctx->Texture.Unit[i].TexGenEnabled != genEnabled) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S,
+ (genEnabled & S_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T,
+ (genEnabled & T_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R,
+ (genEnabled & R_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q,
+ (genEnabled & Q_BIT) ? GL_TRUE : GL_FALSE);
}
/* GL_SGI_texture_color_table */
ctx->Texture.Unit[i].ColorTableEnabled = enable->TextureColorTable[i];
}
- if (ctx->Driver.ActiveTexture) {
- (*ctx->Driver.ActiveTexture)(ctx, ctx->Texture.CurrentUnit);
- }
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + curTexUnitSave);
}
@@ -693,32 +714,39 @@ pop_texture_group(GLcontext *ctx, struct texture_state *texstate)
_mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_NV,
(unit->Enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE);
}
+ if (ctx->Extensions.MESA_texture_array) {
+ _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT,
+ (unit->Enabled & TEXTURE_1D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT,
+ (unit->Enabled & TEXTURE_2D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ }
+
if (ctx->Extensions.SGI_texture_color_table) {
_mesa_set_enable(ctx, GL_TEXTURE_COLOR_TABLE_SGI,
unit->ColorTableEnabled);
}
_mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode);
_mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor);
- _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenModeS);
- _mesa_TexGeni(GL_T, GL_TEXTURE_GEN_MODE, unit->GenModeT);
- _mesa_TexGeni(GL_R, GL_TEXTURE_GEN_MODE, unit->GenModeR);
- _mesa_TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, unit->GenModeQ);
- _mesa_TexGenfv(GL_S, GL_OBJECT_PLANE, unit->ObjectPlaneS);
- _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->ObjectPlaneT);
- _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->ObjectPlaneR);
- _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->ObjectPlaneQ);
+ _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenS.Mode);
+ _mesa_TexGeni(GL_T, GL_TEXTURE_GEN_MODE, unit->GenT.Mode);
+ _mesa_TexGeni(GL_R, GL_TEXTURE_GEN_MODE, unit->GenR.Mode);
+ _mesa_TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, unit->GenQ.Mode);
+ _mesa_TexGenfv(GL_S, GL_OBJECT_PLANE, unit->GenS.ObjectPlane);
+ _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->GenT.ObjectPlane);
+ _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->GenR.ObjectPlane);
+ _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->GenQ.ObjectPlane);
/* Eye plane done differently to avoid re-transformation */
{
struct gl_texture_unit *destUnit = &ctx->Texture.Unit[u];
- COPY_4FV(destUnit->EyePlaneS, unit->EyePlaneS);
- COPY_4FV(destUnit->EyePlaneT, unit->EyePlaneT);
- COPY_4FV(destUnit->EyePlaneR, unit->EyePlaneR);
- COPY_4FV(destUnit->EyePlaneQ, unit->EyePlaneQ);
+ COPY_4FV(destUnit->GenS.EyePlane, unit->GenS.EyePlane);
+ COPY_4FV(destUnit->GenT.EyePlane, unit->GenT.EyePlane);
+ COPY_4FV(destUnit->GenR.EyePlane, unit->GenR.EyePlane);
+ COPY_4FV(destUnit->GenQ.EyePlane, unit->GenQ.EyePlane);
if (ctx->Driver.TexGen) {
- ctx->Driver.TexGen(ctx, GL_S, GL_EYE_PLANE, unit->EyePlaneS);
- ctx->Driver.TexGen(ctx, GL_T, GL_EYE_PLANE, unit->EyePlaneT);
- ctx->Driver.TexGen(ctx, GL_R, GL_EYE_PLANE, unit->EyePlaneR);
- ctx->Driver.TexGen(ctx, GL_Q, GL_EYE_PLANE, unit->EyePlaneQ);
+ ctx->Driver.TexGen(ctx, GL_S, GL_EYE_PLANE, unit->GenS.EyePlane);
+ ctx->Driver.TexGen(ctx, GL_T, GL_EYE_PLANE, unit->GenT.EyePlane);
+ ctx->Driver.TexGen(ctx, GL_R, GL_EYE_PLANE, unit->GenR.EyePlane);
+ ctx->Driver.TexGen(ctx, GL_Q, GL_EYE_PLANE, unit->GenQ.EyePlane);
}
}
_mesa_set_enable(ctx, GL_TEXTURE_GEN_S,
@@ -772,7 +800,6 @@ pop_texture_group(GLcontext *ctx, struct texture_state *texstate)
/* Restore texture object state for each target */
for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
const struct gl_texture_object *obj = NULL;
- GLfloat bordColor[4];
GLenum target;
obj = &texstate->SavedObj[u][tgt];
@@ -798,12 +825,7 @@ pop_texture_group(GLcontext *ctx, struct texture_state *texstate)
_mesa_BindTexture(target, obj->Name);
- bordColor[0] = CHAN_TO_FLOAT(obj->BorderColor[0]);
- bordColor[1] = CHAN_TO_FLOAT(obj->BorderColor[1]);
- bordColor[2] = CHAN_TO_FLOAT(obj->BorderColor[2]);
- bordColor[3] = CHAN_TO_FLOAT(obj->BorderColor[3]);
-
- _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, bordColor);
+ _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, obj->BorderColor);
_mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority);
_mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, obj->WrapS);
_mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, obj->WrapT);
@@ -820,15 +842,9 @@ pop_texture_group(GLcontext *ctx, struct texture_state *texstate)
_mesa_TexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
obj->MaxAnisotropy);
}
- if (ctx->Extensions.SGIX_shadow) {
- _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_SGIX,
- obj->CompareFlag);
- _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_OPERATOR_SGIX,
- obj->CompareOperator);
- }
- if (ctx->Extensions.SGIX_shadow_ambient) {
- _mesa_TexParameterf(target, GL_SHADOW_AMBIENT_SGIX,
- obj->ShadowAmbient);
+ if (ctx->Extensions.ARB_shadow_ambient) {
+ _mesa_TexParameterf(target, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB,
+ obj->CompareFailValue);
}
}
@@ -909,14 +925,13 @@ _mesa_PopAttrib(void)
* function, but legal for the later.
*/
GLboolean multipleBuffers = GL_FALSE;
- if (ctx->Extensions.ARB_draw_buffers) {
- GLuint i;
- for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
- if (color->DrawBuffer[i] != GL_NONE) {
- multipleBuffers = GL_TRUE;
- break;
- }
- }
+ GLuint i;
+
+ for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
+ if (color->DrawBuffer[i] != GL_NONE) {
+ multipleBuffers = GL_TRUE;
+ break;
+ }
}
/* Call the API_level functions, not _mesa_drawbuffers()
* since we need to do error checking on the pop'd
@@ -1012,9 +1027,8 @@ _mesa_PopAttrib(void)
_mesa_Hint(GL_FOG_HINT, hint->Fog);
_mesa_Hint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT,
hint->ClipVolumeClipping);
- if (ctx->Extensions.ARB_texture_compression)
- _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB,
- hint->TextureCompression);
+ _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB,
+ hint->TextureCompression);
}
break;
case GL_LIGHTING_BIT:
@@ -1035,7 +1049,7 @@ _mesa_PopAttrib(void)
_mesa_light(ctx, i, GL_DIFFUSE, l->Diffuse);
_mesa_light(ctx, i, GL_SPECULAR, l->Specular );
_mesa_light(ctx, i, GL_POSITION, l->EyePosition);
- _mesa_light(ctx, i, GL_SPOT_DIRECTION, l->EyeDirection);
+ _mesa_light(ctx, i, GL_SPOT_DIRECTION, l->SpotDirection);
_mesa_light(ctx, i, GL_SPOT_EXPONENT, &l->SpotExponent);
_mesa_light(ctx, i, GL_SPOT_CUTOFF, &l->SpotCutoff);
_mesa_light(ctx, i, GL_CONSTANT_ATTENUATION,
@@ -1196,7 +1210,7 @@ _mesa_PopAttrib(void)
/* restore clip planes */
for (i = 0; i < MAX_CLIP_PLANES; i++) {
- const GLuint mask = 1 << 1;
+ const GLuint mask = 1 << i;
const GLfloat *eyePlane = xform->EyeUserPlane[i];
COPY_4V(ctx->Transform.EyeUserPlane[i], eyePlane);
if (xform->ClipPlanesEnabled & mask) {
@@ -1215,6 +1229,9 @@ _mesa_PopAttrib(void)
if (xform->RescaleNormals != ctx->Transform.RescaleNormals)
_mesa_set_enable(ctx, GL_RESCALE_NORMAL_EXT,
ctx->Transform.RescaleNormals);
+ if (xform->DepthClamp != ctx->Transform.DepthClamp)
+ _mesa_set_enable(ctx, GL_DEPTH_CLAMP,
+ ctx->Transform.DepthClamp);
}
break;
case GL_TEXTURE_BIT:
@@ -1261,23 +1278,22 @@ _mesa_PopAttrib(void)
* counts when pushing/popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
*/
static void
-adjust_buffer_object_ref_counts(struct gl_array_attrib *array, GLint step)
+adjust_buffer_object_ref_counts(struct gl_array_object *arrayObj, GLint step)
{
GLuint i;
- array->ArrayObj->Vertex.BufferObj->RefCount += step;
- array->ArrayObj->Normal.BufferObj->RefCount += step;
- array->ArrayObj->Color.BufferObj->RefCount += step;
- array->ArrayObj->SecondaryColor.BufferObj->RefCount += step;
- array->ArrayObj->FogCoord.BufferObj->RefCount += step;
- array->ArrayObj->Index.BufferObj->RefCount += step;
- array->ArrayObj->EdgeFlag.BufferObj->RefCount += step;
- for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++)
- array->ArrayObj->TexCoord[i].BufferObj->RefCount += step;
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
- array->ArrayObj->VertexAttrib[i].BufferObj->RefCount += step;
-
- array->ArrayBufferObj->RefCount += step;
- array->ElementArrayBufferObj->RefCount += step;
+
+ arrayObj->Vertex.BufferObj->RefCount += step;
+ arrayObj->Weight.BufferObj->RefCount += step;
+ arrayObj->Normal.BufferObj->RefCount += step;
+ arrayObj->Color.BufferObj->RefCount += step;
+ arrayObj->SecondaryColor.BufferObj->RefCount += step;
+ arrayObj->FogCoord.BufferObj->RefCount += step;
+ arrayObj->Index.BufferObj->RefCount += step;
+ arrayObj->EdgeFlag.BufferObj->RefCount += step;
+ for (i = 0; i < Elements(arrayObj->TexCoord); i++)
+ arrayObj->TexCoord[i].BufferObj->RefCount += step;
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
+ arrayObj->VertexAttrib[i].BufferObj->RefCount += step;
}
@@ -1311,7 +1327,6 @@ copy_pixelstore(GLcontext *ctx,
void GLAPIENTRY
_mesa_PushClientAttrib(GLbitfield mask)
{
- struct gl_attrib_node *newnode;
struct gl_attrib_node *head;
GET_CURRENT_CONTEXT(ctx);
@@ -1332,17 +1347,11 @@ _mesa_PushClientAttrib(GLbitfield mask)
/* packing attribs */
attr = CALLOC_STRUCT( gl_pixelstore_attrib );
copy_pixelstore(ctx, attr, &ctx->Pack);
- newnode = new_attrib_node( GL_CLIENT_PACK_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_CLIENT_PACK_BIT, attr);
/* unpacking attribs */
attr = CALLOC_STRUCT( gl_pixelstore_attrib );
copy_pixelstore(ctx, attr, &ctx->Unpack);
- newnode = new_attrib_node( GL_CLIENT_UNPACK_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_CLIENT_UNPACK_BIT, attr);
}
if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
@@ -1363,12 +1372,10 @@ _mesa_PushClientAttrib(GLbitfield mask)
attr->ArrayObj = obj;
- newnode = new_attrib_node( GL_CLIENT_VERTEX_ARRAY_BIT );
- newnode->data = attr;
- newnode->next = head;
- head = newnode;
+ save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr);
+
/* bump reference counts on buffer objects */
- adjust_buffer_object_ref_counts(&ctx->Array, 1);
+ adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, 1);
}
ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head;
@@ -1418,7 +1425,7 @@ _mesa_PopClientAttrib(void)
struct gl_array_attrib * data =
(struct gl_array_attrib *) node->data;
- adjust_buffer_object_ref_counts(&ctx->Array, -1);
+ adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, -1);
ctx->Array.ActiveTexture = data->ActiveTexture;
if (data->LockCount != 0)
@@ -1461,6 +1468,19 @@ _mesa_PopClientAttrib(void)
}
+void
+_mesa_init_attrib_dispatch(struct _glapi_table *disp)
+{
+ SET_PopAttrib(disp, _mesa_PopAttrib);
+ SET_PushAttrib(disp, _mesa_PushAttrib);
+ SET_PopClientAttrib(disp, _mesa_PopClientAttrib);
+ SET_PushClientAttrib(disp, _mesa_PushClientAttrib);
+}
+
+
+#endif /* FEATURE_attrib_stack */
+
+
/**
* Free any attribute state data that might be attached to the context.
*/
diff --git a/src/mesa/main/attrib.h b/src/mesa/main/attrib.h
index 2cf8fe6934..aa9d42e408 100644
--- a/src/mesa/main/attrib.h
+++ b/src/mesa/main/attrib.h
@@ -26,10 +26,10 @@
#define ATTRIB_H
-#include "mtypes.h"
+#include "main/mtypes.h"
-#if _HAVE_FULL_GL
+#if FEATURE_attrib_stack
extern void GLAPIENTRY
_mesa_PushAttrib( GLbitfield mask );
@@ -43,18 +43,32 @@ _mesa_PushClientAttrib( GLbitfield mask );
extern void GLAPIENTRY
_mesa_PopClientAttrib( void );
+extern void
+_mesa_init_attrib_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_attrib_stack */
+
+static INLINE void
+_mesa_PushClientAttrib( GLbitfield mask )
+{
+}
+
+static INLINE void
+_mesa_PopClientAttrib( void )
+{
+}
+
+static INLINE void
+_mesa_init_attrib_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_attrib_stack */
+
extern void
_mesa_init_attrib( GLcontext *ctx );
extern void
_mesa_free_attrib_data( GLcontext *ctx );
-#else
-
-/** No-op */
-#define _mesa_init_attrib( c ) ((void)0)
-#define _mesa_free_attrib_data( c ) ((void)0)
-
-#endif
-
-#endif
+#endif /* ATTRIB_H */
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index 59fe8e25de..b95e00af5b 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.2
+ * Version: 7.6
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -25,7 +26,7 @@
/**
* \file bufferobj.c
- * \brief Functions for the GL_ARB_vertex_buffer_object extension.
+ * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions.
* \author Brian Paul, Ian Romanick
*/
@@ -38,6 +39,18 @@
#include "bufferobj.h"
+/* Debug flags */
+/*#define VBO_DEBUG*/
+/*#define BOUNDS_CHECK*/
+
+
+#ifdef FEATURE_OES_mapbuffer
+#define DEFAULT_ACCESS GL_MAP_WRITE_BIT
+#else
+#define DEFAULT_ACCESS (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)
+#endif
+
+
/**
* Get the buffer object bound to the specified target in a GL context.
*
@@ -65,6 +78,16 @@ get_buffer(GLcontext *ctx, GLenum target)
case GL_PIXEL_UNPACK_BUFFER_EXT:
bufObj = ctx->Unpack.BufferObj;
break;
+ case GL_COPY_READ_BUFFER:
+ if (ctx->Extensions.ARB_copy_buffer) {
+ bufObj = ctx->CopyReadBuffer;
+ }
+ break;
+ case GL_COPY_WRITE_BUFFER:
+ if (ctx->Extensions.ARB_copy_buffer) {
+ bufObj = ctx->CopyWriteBuffer;
+ }
+ break;
default:
/* error must be recorded by caller */
return NULL;
@@ -78,6 +101,24 @@ get_buffer(GLcontext *ctx, GLenum target)
/**
+ * Convert a GLbitfield describing the mapped buffer access flags
+ * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
+ */
+static GLenum
+simplified_access_mode(GLbitfield access)
+{
+ const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
+ if ((access & rwFlags) == rwFlags)
+ return GL_READ_WRITE;
+ if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT)
+ return GL_READ_ONLY;
+ if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT)
+ return GL_WRITE_ONLY;
+ return GL_READ_WRITE; /* this should never happen, but no big deal */
+}
+
+
+/**
* Tests the subdata range parameters and sets the GL error code for
* \c glBufferSubDataARB and \c glGetBufferSubDataARB.
*
@@ -115,7 +156,7 @@ buffer_object_subdata_range_good( GLcontext * ctx, GLenum target,
_mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller);
return NULL;
}
- if (bufObj->Name == 0) {
+ if (!_mesa_is_bufferobj(bufObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
return NULL;
}
@@ -124,7 +165,7 @@ buffer_object_subdata_range_good( GLcontext * ctx, GLenum target,
"%s(size + offset > buffer size)", caller);
return NULL;
}
- if (bufObj->Pointer) {
+ if (_mesa_bufferobj_mapped(bufObj)) {
/* Buffer is currently mapped */
_mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
return NULL;
@@ -137,10 +178,9 @@ buffer_object_subdata_range_good( GLcontext * ctx, GLenum target,
/**
* Allocate and initialize a new buffer object.
*
- * This function is intended to be called via
- * \c dd_function_table::NewBufferObject.
+ * Default callback for the \c dd_function_table::NewBufferObject() hook.
*/
-struct gl_buffer_object *
+static struct gl_buffer_object *
_mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target )
{
struct gl_buffer_object *obj;
@@ -156,10 +196,9 @@ _mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target )
/**
* Delete a buffer object.
*
- * This function is intended to be called via
- * \c dd_function_table::DeleteBuffer.
+ * Default callback for the \c dd_function_table::DeleteBuffer() hook.
*/
-void
+static void
_mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj )
{
(void) ctx;
@@ -188,7 +227,7 @@ _mesa_reference_buffer_object(GLcontext *ctx,
return;
if (*ptr) {
- /* Unreference the old texture */
+ /* Unreference the old buffer */
GLboolean deleteFlag = GL_FALSE;
struct gl_buffer_object *oldObj = *ptr;
@@ -221,7 +260,7 @@ _mesa_reference_buffer_object(GLcontext *ctx,
ASSERT(!*ptr);
if (bufObj) {
- /* reference new texture */
+ /* reference new buffer */
/*_glthread_LOCK_MUTEX(tex->Mutex);*/
if (bufObj->RefCount == 0) {
/* this buffer's being deleted (look just above) */
@@ -255,7 +294,7 @@ _mesa_initialize_buffer_object( struct gl_buffer_object *obj,
obj->RefCount = 1;
obj->Name = name;
obj->Usage = GL_STATIC_DRAW_ARB;
- obj->Access = GL_READ_WRITE_ARB;
+ obj->AccessFlags = DEFAULT_ACCESS;
}
@@ -264,9 +303,8 @@ _mesa_initialize_buffer_object( struct gl_buffer_object *obj,
* previously stored in the buffer object is lost. If \c data is \c NULL,
* memory will be allocated, but no copy will occur.
*
- * This function is intended to be called via
- * \c dd_function_table::BufferData. This function need not set GL error
- * codes. The input parameters will have been tested before calling.
+ * This is the default callback for \c dd_function_table::BufferData()
+ * Note that all GL error checking will have been done already.
*
* \param ctx GL context.
* \param target Buffer object target on which to operate.
@@ -276,9 +314,10 @@ _mesa_initialize_buffer_object( struct gl_buffer_object *obj,
* \param usage Hints about how the data will be used.
* \param bufObj Object to be used.
*
+ * \return GL_TRUE for success, GL_FALSE for failure
* \sa glBufferDataARB, dd_function_table::BufferData.
*/
-void
+static GLboolean
_mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
const GLvoid * data, GLenum usage,
struct gl_buffer_object * bufObj )
@@ -296,6 +335,11 @@ _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
if (data) {
_mesa_memcpy( bufObj->Data, data, size );
}
+
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
}
}
@@ -305,9 +349,8 @@ _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
* specified by \c size + \c offset extends beyond the end of the buffer or
* if \c data is \c NULL, no copy is performed.
*
- * This function is intended to be called by
- * \c dd_function_table::BufferSubData. This function need not set GL error
- * codes. The input parameters will have been tested before calling.
+ * This is the default callback for \c dd_function_table::BufferSubData()
+ * Note that all GL error checking will have been done already.
*
* \param ctx GL context.
* \param target Buffer object target on which to operate.
@@ -318,7 +361,7 @@ _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
*
* \sa glBufferSubDataARB, dd_function_table::BufferSubData.
*/
-void
+static void
_mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
GLsizeiptrARB size, const GLvoid * data,
struct gl_buffer_object * bufObj )
@@ -339,20 +382,19 @@ _mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
* specified by \c size + \c offset extends beyond the end of the buffer or
* if \c data is \c NULL, no copy is performed.
*
- * This function is intended to be called by
- * \c dd_function_table::BufferGetSubData. This function need not set GL error
- * codes. The input parameters will have been tested before calling.
+ * This is the default callback for \c dd_function_table::GetBufferSubData()
+ * Note that all GL error checking will have been done already.
*
* \param ctx GL context.
* \param target Buffer object target on which to operate.
- * \param offset Offset of the first byte to be modified.
+ * \param offset Offset of the first byte to be fetched.
* \param size Size, in bytes, of the data range.
- * \param data Pointer to the data to store in the buffer object.
+ * \param data Destination for data
* \param bufObj Object to be used.
*
* \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
*/
-void
+static void
_mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
GLsizeiptrARB size, GLvoid * data,
struct gl_buffer_object * bufObj )
@@ -366,9 +408,7 @@ _mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
/**
- * Fallback function called via ctx->Driver.MapBuffer().
- * Hardware drivers that really implement buffer objects should never use
- * this function.
+ * Default callback for \c dd_function_tabel::MapBuffer().
*
* The function parameters will have been already tested for errors.
*
@@ -381,64 +421,135 @@ _mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
*
* \sa glMapBufferARB, dd_function_table::MapBuffer
*/
-void *
+static void *
_mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
struct gl_buffer_object *bufObj )
{
(void) ctx;
(void) target;
(void) access;
- ASSERT(!bufObj->OnCard);
/* Just return a direct pointer to the data */
- if (bufObj->Pointer) {
+ if (_mesa_bufferobj_mapped(bufObj)) {
/* already mapped! */
return NULL;
}
bufObj->Pointer = bufObj->Data;
+ bufObj->Length = bufObj->Size;
+ bufObj->Offset = 0;
return bufObj->Pointer;
}
/**
- * Fallback function called via ctx->Driver.MapBuffer().
- * Hardware drivers that really implement buffer objects should never use
- * function.
+ * Default fallback for \c dd_function_table::MapBufferRange().
+ * Called via glMapBufferRange().
+ */
+static void *
+_mesa_buffer_map_range( GLcontext *ctx, GLenum target, GLintptr offset,
+ GLsizeiptr length, GLbitfield access,
+ struct gl_buffer_object *bufObj )
+{
+ (void) ctx;
+ (void) target;
+ assert(!_mesa_bufferobj_mapped(bufObj));
+ /* Just return a direct pointer to the data */
+ bufObj->Pointer = bufObj->Data + offset;
+ bufObj->Length = length;
+ bufObj->Offset = offset;
+ bufObj->AccessFlags = access;
+ return bufObj->Pointer;
+}
+
+
+/**
+ * Default fallback for \c dd_function_table::FlushMappedBufferRange().
+ * Called via glFlushMappedBufferRange().
+ */
+static void
+_mesa_buffer_flush_mapped_range( GLcontext *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length,
+ struct gl_buffer_object *obj )
+{
+ (void) ctx;
+ (void) target;
+ (void) offset;
+ (void) length;
+ (void) obj;
+ /* no-op */
+}
+
+
+/**
+ * Default callback for \c dd_function_table::MapBuffer().
*
* The input parameters will have been already tested for errors.
*
* \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
*/
-GLboolean
+static GLboolean
_mesa_buffer_unmap( GLcontext *ctx, GLenum target,
struct gl_buffer_object *bufObj )
{
(void) ctx;
(void) target;
- ASSERT(!bufObj->OnCard);
/* XXX we might assert here that bufObj->Pointer is non-null */
bufObj->Pointer = NULL;
+ bufObj->Length = 0;
+ bufObj->Offset = 0;
+ bufObj->AccessFlags = 0x0;
return GL_TRUE;
}
/**
+ * Default fallback for \c dd_function_table::CopyBufferSubData().
+ * Called via glCopyBuffserSubData().
+ */
+static void
+_mesa_copy_buffer_subdata(GLcontext *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ GLubyte *srcPtr, *dstPtr;
+
+ /* buffer should not already be mapped */
+ assert(!_mesa_bufferobj_mapped(src));
+ assert(!_mesa_bufferobj_mapped(dst));
+
+ srcPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_READ_BUFFER,
+ GL_READ_ONLY, src);
+ dstPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_WRITE_BUFFER,
+ GL_WRITE_ONLY, dst);
+
+ if (srcPtr && dstPtr)
+ _mesa_memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
+
+ ctx->Driver.UnmapBuffer(ctx, GL_COPY_READ_BUFFER, src);
+ ctx->Driver.UnmapBuffer(ctx, GL_COPY_WRITE_BUFFER, dst);
+}
+
+
+
+/**
* Initialize the state associated with buffer objects
*/
void
_mesa_init_buffer_objects( GLcontext *ctx )
{
- /* Allocate the default buffer object and set refcount so high that
- * it never gets deleted.
- * XXX with recent/improved refcounting this may not longer be needed.
- */
- ctx->Array.NullBufferObj = _mesa_new_buffer_object(ctx, 0, 0);
- if (ctx->Array.NullBufferObj)
- ctx->Array.NullBufferObj->RefCount = 1000;
-
- ctx->Array.ArrayBufferObj = ctx->Array.NullBufferObj;
- ctx->Array.ElementArrayBufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj,
+ ctx->Shared->NullBufferObj);
+ _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj,
+ ctx->Shared->NullBufferObj);
+
+ _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer,
+ ctx->Shared->NullBufferObj);
+ _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer,
+ ctx->Shared->NullBufferObj);
}
+
/**
* Bind the specified target to buffer for the specified context.
*/
@@ -462,8 +573,22 @@ bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
case GL_PIXEL_UNPACK_BUFFER_EXT:
bindTarget = &ctx->Unpack.BufferObj;
break;
+ case GL_COPY_READ_BUFFER:
+ if (ctx->Extensions.ARB_copy_buffer) {
+ bindTarget = &ctx->CopyReadBuffer;
+ }
+ break;
+ case GL_COPY_WRITE_BUFFER:
+ if (ctx->Extensions.ARB_copy_buffer) {
+ bindTarget = &ctx->CopyWriteBuffer;
+ }
+ break;
default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target)");
+ ; /* no-op / we'll hit the follow error test next */
+ }
+
+ if (!bindTarget) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)");
return;
}
@@ -479,7 +604,7 @@ bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
/* The spec says there's not a buffer object named 0, but we use
* one internally because it simplifies things.
*/
- newBufObj = ctx->Array.NullBufferObj;
+ newBufObj = ctx->Shared->NullBufferObj;
}
else {
/* non-default buffer object */
@@ -500,7 +625,7 @@ bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
_mesa_reference_buffer_object(ctx, bindTarget, newBufObj);
/* Pass BindBuffer call to device driver */
- if (ctx->Driver.BindBuffer && newBufObj)
+ if (ctx->Driver.BindBuffer)
ctx->Driver.BindBuffer( ctx, target, newBufObj );
}
@@ -533,6 +658,8 @@ _mesa_update_default_objects_buffer_objects(GLcontext *ctx)
* currently mapped. Whoever calls this function should check for that.
* Remember, we can't use a PBO when it's mapped!
*
+ * If we're not using a PBO, this is a no-op.
+ *
* \param width width of image to read/write
* \param height height of image to read/write
* \param depth depth of image to read/write
@@ -551,7 +678,8 @@ _mesa_validate_pbo_access(GLuint dimensions,
GLvoid *start, *end;
const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
- ASSERT(pack->BufferObj->Name != 0);
+ if (!_mesa_is_bufferobj(pack->BufferObj))
+ return GL_TRUE; /* no PBO, OK */
if (pack->BufferObj->Size == 0)
/* no buffer! */
@@ -583,21 +711,22 @@ _mesa_validate_pbo_access(GLuint dimensions,
/**
- * If the source of glBitmap data is a PBO, check that we won't read out
- * of buffer bounds, then map the buffer.
- * If not sourcing from a PBO, just return the bitmap pointer.
- * This is a helper function for (some) drivers.
- * Return NULL if error.
- * If non-null return, must call _mesa_unmap_bitmap_pbo() when done.
+ * For commands that read from a PBO (glDrawPixels, glTexImage,
+ * glPolygonStipple, etc), if we're reading from a PBO, map it read-only
+ * and return the pointer into the PBO. If we're not reading from a
+ * PBO, return \p src as-is.
+ * If non-null return, must call _mesa_unmap_pbo_source() when done.
+ *
+ * \return NULL if error, else pointer to start of data
*/
-const GLubyte *
-_mesa_map_bitmap_pbo(GLcontext *ctx,
+const GLvoid *
+_mesa_map_pbo_source(GLcontext *ctx,
const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap)
+ const GLvoid *src)
{
const GLubyte *buf;
- if (unpack->BufferObj->Name) {
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
/* unpack from PBO */
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
GL_READ_ONLY_ARB,
@@ -605,11 +734,11 @@ _mesa_map_bitmap_pbo(GLcontext *ctx,
if (!buf)
return NULL;
- buf = ADD_POINTERS(buf, bitmap);
+ buf = ADD_POINTERS(buf, src);
}
else {
/* unpack from normal memory */
- buf = bitmap;
+ buf = src;
}
return buf;
@@ -617,57 +746,55 @@ _mesa_map_bitmap_pbo(GLcontext *ctx,
/**
- * Counterpart to _mesa_map_bitmap_pbo()
- * This is a helper function for (some) drivers.
- */
-void
-_mesa_unmap_bitmap_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *unpack)
-{
- if (unpack->BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- unpack->BufferObj);
- }
-}
-
-
-/**
- * \sa _mesa_map_bitmap_pbo
+ * Combine PBO-read validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_source
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_source().
*/
const GLvoid *
-_mesa_map_drawpix_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *pixels)
+_mesa_map_validate_pbo_source(GLcontext *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr,
+ const char *where)
{
- const GLvoid *buf;
+ ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
- if (unpack->BufferObj->Name) {
- /* unpack from PBO */
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- unpack->BufferObj);
- if (!buf)
- return NULL;
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* non-PBO access: no validation to be done */
+ return ptr;
+ }
- buf = ADD_POINTERS(buf, pixels);
+ if (!_mesa_validate_pbo_access(dimensions, unpack,
+ width, height, depth, format, type, ptr)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(out of bounds PBO access)", where);
+ return NULL;
}
- else {
- /* unpack from normal memory */
- buf = pixels;
+
+ if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+ return NULL;
}
- return buf;
+ ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
+ return ptr;
}
/**
- * \sa _mesa_unmap_bitmap_pbo
+ * Counterpart to _mesa_map_pbo_source()
*/
void
-_mesa_unmap_drapix_pbo(GLcontext *ctx,
+_mesa_unmap_pbo_source(GLcontext *ctx,
const struct gl_pixelstore_attrib *unpack)
{
- if (unpack->BufferObj->Name) {
+ ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
unpack->BufferObj);
}
@@ -675,18 +802,21 @@ _mesa_unmap_drapix_pbo(GLcontext *ctx,
/**
- * If PBO is bound, map the buffer, return dest pointer in mapped buffer.
- * Call _mesa_unmap_readpix_pbo() when finished
- * \return NULL if error
+ * For commands that write to a PBO (glReadPixels, glGetColorTable, etc),
+ * if we're writing to a PBO, map it write-only and return the pointer
+ * into the PBO. If we're not writing to a PBO, return \p dst as-is.
+ * If non-null return, must call _mesa_unmap_pbo_dest() when done.
+ *
+ * \return NULL if error, else pointer to start of data
*/
void *
-_mesa_map_readpix_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *pack,
- GLvoid *dest)
+_mesa_map_pbo_dest(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
{
void *buf;
- if (pack->BufferObj->Name) {
+ if (_mesa_is_bufferobj(pack->BufferObj)) {
/* pack into PBO */
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
GL_WRITE_ONLY_ARB,
@@ -706,13 +836,55 @@ _mesa_map_readpix_pbo(GLcontext *ctx,
/**
- * Counterpart to _mesa_map_readpix_pbo()
+ * Combine PBO-write validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_dest
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_dest().
+ */
+GLvoid *
+_mesa_map_validate_pbo_dest(GLcontext *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, GLvoid *ptr,
+ const char *where)
+{
+ ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
+
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* non-PBO access: no validation to be done */
+ return ptr;
+ }
+
+ if (!_mesa_validate_pbo_access(dimensions, unpack,
+ width, height, depth, format, type, ptr)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(out of bounds PBO access)", where);
+ return NULL;
+ }
+
+ if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+ return NULL;
+ }
+
+ ptr = _mesa_map_pbo_dest(ctx, unpack, ptr);
+ return ptr;
+}
+
+
+/**
+ * Counterpart to _mesa_map_pbo_dest()
*/
void
-_mesa_unmap_readpix_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *pack)
+_mesa_unmap_pbo_dest(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *pack)
{
- if (pack->BufferObj->Name) {
+ ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */
+ if (_mesa_is_bufferobj(pack->BufferObj)) {
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
}
}
@@ -746,11 +918,37 @@ unbind(GLcontext *ctx,
struct gl_buffer_object *obj)
{
if (*ptr == obj) {
- _mesa_reference_buffer_object(ctx, ptr, ctx->Array.NullBufferObj);
+ _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj);
}
}
+/**
+ * Plug default/fallback buffer object functions into the device
+ * driver hooks.
+ */
+void
+_mesa_init_buffer_object_functions(struct dd_function_table *driver)
+{
+ /* GL_ARB_vertex/pixel_buffer_object */
+ driver->NewBufferObject = _mesa_new_buffer_object;
+ driver->DeleteBuffer = _mesa_delete_buffer_object;
+ driver->BindBuffer = NULL;
+ driver->BufferData = _mesa_buffer_data;
+ driver->BufferSubData = _mesa_buffer_subdata;
+ driver->GetBufferSubData = _mesa_buffer_get_subdata;
+ driver->MapBuffer = _mesa_buffer_map;
+ driver->UnmapBuffer = _mesa_buffer_unmap;
+
+ /* GL_ARB_map_buffer_range */
+ driver->MapBufferRange = _mesa_buffer_map_range;
+ driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range;
+
+ /* GL_ARB_copy_buffer */
+ driver->CopyBufferSubData = _mesa_copy_buffer_subdata;
+}
+
+
/**********************************************************************/
/* API Functions */
@@ -789,23 +987,32 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
for (i = 0; i < n; i++) {
struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]);
if (bufObj) {
- /* unbind any vertex pointers bound to this buffer */
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
GLuint j;
ASSERT(bufObj->Name == ids[i]);
- unbind(ctx, &ctx->Array.ArrayObj->Vertex.BufferObj, bufObj);
- unbind(ctx, &ctx->Array.ArrayObj->Normal.BufferObj, bufObj);
- unbind(ctx, &ctx->Array.ArrayObj->Color.BufferObj, bufObj);
- unbind(ctx, &ctx->Array.ArrayObj->SecondaryColor.BufferObj, bufObj);
- unbind(ctx, &ctx->Array.ArrayObj->FogCoord.BufferObj, bufObj);
- unbind(ctx, &ctx->Array.ArrayObj->Index.BufferObj, bufObj);
- unbind(ctx, &ctx->Array.ArrayObj->EdgeFlag.BufferObj, bufObj);
- for (j = 0; j < MAX_TEXTURE_COORD_UNITS; j++) {
- unbind(ctx, &ctx->Array.ArrayObj->TexCoord[j].BufferObj, bufObj);
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ /* if mapped, unmap it now */
+ ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
+ bufObj->AccessFlags = DEFAULT_ACCESS;
+ bufObj->Pointer = NULL;
}
- for (j = 0; j < VERT_ATTRIB_MAX; j++) {
- unbind(ctx, &ctx->Array.ArrayObj->VertexAttrib[j].BufferObj, bufObj);
+
+ /* unbind any vertex pointers bound to this buffer */
+ unbind(ctx, &arrayObj->Vertex.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->Weight.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->Normal.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->Color.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->SecondaryColor.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->FogCoord.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->Index.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->EdgeFlag.BufferObj, bufObj);
+ for (j = 0; j < Elements(arrayObj->TexCoord); j++) {
+ unbind(ctx, &arrayObj->TexCoord[j].BufferObj, bufObj);
+ }
+ for (j = 0; j < Elements(arrayObj->VertexAttrib); j++) {
+ unbind(ctx, &arrayObj->VertexAttrib[j].BufferObj, bufObj);
}
if (ctx->Array.ArrayBufferObj == bufObj) {
@@ -815,6 +1022,7 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
_mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
}
+ /* unbind any pixel pack/unpack pointers bound to this buffer */
if (ctx->Pack.BufferObj == bufObj) {
_mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 );
}
@@ -938,20 +1146,35 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
_mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" );
return;
}
- if (bufObj->Name == 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB" );
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer 0)" );
return;
}
- if (bufObj->Pointer) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer is mapped)" );
- return;
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ /* Unmap the existing buffer. We'll replace it now. Not an error. */
+ ctx->Driver.UnmapBuffer(ctx, target, bufObj);
+ bufObj->AccessFlags = DEFAULT_ACCESS;
+ ASSERT(bufObj->Pointer == NULL);
}
- ASSERT(ctx->Driver.BufferData);
+ FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
+
+ bufObj->Written = GL_TRUE;
+
+#ifdef VBO_DEBUG
+ _mesa_printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
+ bufObj->Name, size, data, usage);
+#endif
- /* Give the buffer object to the driver! <data> may be null! */
- ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj );
+#ifdef BOUNDS_CHECK
+ size += 100;
+#endif
+
+ ASSERT(ctx->Driver.BufferData);
+ if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB(access)");
+ }
}
@@ -970,6 +1193,8 @@ _mesa_BufferSubDataARB(GLenum target, GLintptrARB offset,
return;
}
+ bufObj->Written = GL_TRUE;
+
ASSERT(ctx->Driver.BufferSubData);
ctx->Driver.BufferSubData( ctx, target, offset, size, data, bufObj );
}
@@ -1000,13 +1225,20 @@ _mesa_MapBufferARB(GLenum target, GLenum access)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object * bufObj;
+ GLbitfield accessFlags;
+ void *map;
+
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
switch (access) {
case GL_READ_ONLY_ARB:
+ accessFlags = GL_MAP_READ_BIT;
+ break;
case GL_WRITE_ONLY_ARB:
+ accessFlags = GL_MAP_WRITE_BIT;
+ break;
case GL_READ_WRITE_ARB:
- /* OK */
+ accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)");
@@ -1018,22 +1250,56 @@ _mesa_MapBufferARB(GLenum target, GLenum access)
_mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" );
return NULL;
}
- if (bufObj->Name == 0) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB" );
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(buffer 0)" );
return NULL;
}
- if (bufObj->Pointer) {
+ if (_mesa_bufferobj_mapped(bufObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)");
return NULL;
}
ASSERT(ctx->Driver.MapBuffer);
- bufObj->Pointer = ctx->Driver.MapBuffer( ctx, target, access, bufObj );
- if (!bufObj->Pointer) {
+ map = ctx->Driver.MapBuffer( ctx, target, access, bufObj );
+ if (!map) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)");
+ return NULL;
+ }
+ else {
+ /* The driver callback should have set these fields.
+ * This is important because other modules (like VBO) might call
+ * the driver function directly.
+ */
+ ASSERT(bufObj->Pointer == map);
+ ASSERT(bufObj->Length == bufObj->Size);
+ ASSERT(bufObj->Offset == 0);
+ bufObj->AccessFlags = accessFlags;
}
- bufObj->Access = access;
+ if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
+ bufObj->Written = GL_TRUE;
+
+#ifdef VBO_DEBUG
+ _mesa_printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n",
+ bufObj->Name, bufObj->Size, access);
+ if (access == GL_WRITE_ONLY_ARB) {
+ GLuint i;
+ GLubyte *b = (GLubyte *) bufObj->Pointer;
+ for (i = 0; i < bufObj->Size; i++)
+ b[i] = i & 0xff;
+ }
+#endif
+
+#ifdef BOUNDS_CHECK
+ {
+ GLubyte *buf = (GLubyte *) bufObj->Pointer;
+ GLuint i;
+ /* buffer is 100 bytes larger than requested, fill with magic value */
+ for (i = 0; i < 100; i++) {
+ buf[bufObj->Size - i - 1] = 123;
+ }
+ }
+#endif
return bufObj->Pointer;
}
@@ -1052,21 +1318,56 @@ _mesa_UnmapBufferARB(GLenum target)
_mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" );
return GL_FALSE;
}
- if (bufObj->Name == 0) {
+ if (!_mesa_is_bufferobj(bufObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" );
return GL_FALSE;
}
- if (!bufObj->Pointer) {
+ if (!_mesa_bufferobj_mapped(bufObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB");
return GL_FALSE;
}
- if (ctx->Driver.UnmapBuffer) {
- status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
+#ifdef BOUNDS_CHECK
+ if (bufObj->Access != GL_READ_ONLY_ARB) {
+ GLubyte *buf = (GLubyte *) bufObj->Pointer;
+ GLuint i;
+ /* check that last 100 bytes are still = magic value */
+ for (i = 0; i < 100; i++) {
+ GLuint pos = bufObj->Size - i - 1;
+ if (buf[pos] != 123) {
+ _mesa_warning(ctx, "Out of bounds buffer object write detected"
+ " at position %d (value = %u)\n",
+ pos, buf[pos]);
+ }
+ }
}
+#endif
- bufObj->Access = GL_READ_WRITE_ARB; /* initial value, OK? */
- bufObj->Pointer = NULL;
+#ifdef VBO_DEBUG
+ if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
+ GLuint i, unchanged = 0;
+ GLubyte *b = (GLubyte *) bufObj->Pointer;
+ GLint pos = -1;
+ /* check which bytes changed */
+ for (i = 0; i < bufObj->Size - 1; i++) {
+ if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) {
+ unchanged++;
+ if (pos == -1)
+ pos = i;
+ }
+ }
+ if (unchanged) {
+ _mesa_printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
+ bufObj->Name, unchanged, bufObj->Size, pos);
+ }
+ }
+#endif
+
+ status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
+ bufObj->AccessFlags = DEFAULT_ACCESS;
+ ASSERT(bufObj->Pointer == NULL);
+ ASSERT(bufObj->Offset == 0);
+ ASSERT(bufObj->Length == 0);
return status;
}
@@ -1084,7 +1385,7 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
_mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameterivARB(target)" );
return;
}
- if (bufObj->Name == 0) {
+ if (!_mesa_is_bufferobj(bufObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" );
return;
}
@@ -1097,10 +1398,10 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
*params = bufObj->Usage;
break;
case GL_BUFFER_ACCESS_ARB:
- *params = bufObj->Access;
+ *params = simplified_access_mode(bufObj->AccessFlags);
break;
case GL_BUFFER_MAPPED_ARB:
- *params = (bufObj->Pointer != NULL);
+ *params = _mesa_bufferobj_mapped(bufObj);
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)");
@@ -1126,10 +1427,252 @@ _mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
_mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" );
return;
}
- if (bufObj->Name == 0) {
+ if (!_mesa_is_bufferobj(bufObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" );
return;
}
*params = bufObj->Pointer;
}
+
+
+void GLAPIENTRY
+_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *src, *dst;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ src = get_buffer(ctx, readTarget);
+ if (!src || !_mesa_is_bufferobj(src)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCopyBuffserSubData(readTarget = 0x%x)", readTarget);
+ return;
+ }
+
+ dst = get_buffer(ctx, writeTarget);
+ if (!dst || !_mesa_is_bufferobj(dst)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCopyBuffserSubData(writeTarget = 0x%x)", writeTarget);
+ return;
+ }
+
+ if (_mesa_bufferobj_mapped(src)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyBuffserSubData(readBuffer is mapped)");
+ return;
+ }
+
+ if (_mesa_bufferobj_mapped(dst)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyBuffserSubData(writeBuffer is mapped)");
+ return;
+ }
+
+ if (readOffset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(readOffset = %d)", readOffset);
+ return;
+ }
+
+ if (writeOffset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(writeOffset = %d)", writeOffset);
+ return;
+ }
+
+ if (readOffset + size > src->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(readOffset + size = %d)",
+ readOffset, size);
+ return;
+ }
+
+ if (writeOffset + size > dst->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(writeOffset + size = %d)",
+ writeOffset, size);
+ return;
+ }
+
+ if (src == dst) {
+ if (readOffset + size <= writeOffset) {
+ /* OK */
+ }
+ else if (writeOffset + size <= readOffset) {
+ /* OK */
+ }
+ else {
+ /* overlapping src/dst is illegal */
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(overlapping src/dst)");
+ return;
+ }
+ }
+
+ ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
+}
+
+
+/**
+ * See GL_ARB_map_buffer_range spec
+ */
+void * GLAPIENTRY
+_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
+ GLbitfield access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ void *map;
+
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
+
+ if (!ctx->Extensions.ARB_map_buffer_range) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(extension not supported)");
+ return NULL;
+ }
+
+ if (offset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(offset = %ld)", offset);
+ return NULL;
+ }
+
+ if (length < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(length = %ld)", length);
+ return NULL;
+ }
+
+ if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(access indicates neither read or write)");
+ return NULL;
+ }
+
+ if (access & GL_MAP_READ_BIT) {
+ if ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
+ (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
+ (access & GL_MAP_UNSYNCHRONIZED_BIT)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(invalid access flags)");
+ return NULL;
+ }
+ }
+
+ if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
+ ((access & GL_MAP_WRITE_BIT) == 0)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(invalid access flags)");
+ return NULL;
+ }
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj || !_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glMapBufferRange(target = 0x%x)", target);
+ return NULL;
+ }
+
+ if (offset + length > bufObj->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(offset + length > size)");
+ return NULL;
+ }
+
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(buffer already mapped)");
+ return NULL;
+ }
+
+ ASSERT(ctx->Driver.MapBufferRange);
+ map = ctx->Driver.MapBufferRange(ctx, target, offset, length,
+ access, bufObj);
+ if (!map) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)");
+ }
+ else {
+ /* The driver callback should have set all these fields.
+ * This is important because other modules (like VBO) might call
+ * the driver function directly.
+ */
+ ASSERT(bufObj->Pointer == map);
+ ASSERT(bufObj->Length == length);
+ ASSERT(bufObj->Offset == offset);
+ ASSERT(bufObj->AccessFlags == access);
+ }
+
+ return map;
+}
+
+
+/**
+ * See GL_ARB_map_buffer_range spec
+ */
+void GLAPIENTRY
+_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ARB_map_buffer_range) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(extension not supported)");
+ return;
+ }
+
+ if (offset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(offset = %ld)", offset);
+ return;
+ }
+
+ if (length < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(length = %ld)", length);
+ return;
+ }
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glMapBufferRange(target = 0x%x)", target);
+ return;
+ }
+
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(current buffer is 0)");
+ return;
+ }
+
+ if (!_mesa_bufferobj_mapped(bufObj)) {
+ /* buffer is not mapped */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(buffer is not mapped)");
+ return;
+ }
+
+ if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)");
+ return;
+ }
+
+ if (offset + length > bufObj->Length) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(offset %ld + length %ld > mapped length %ld)",
+ offset, length, bufObj->Length);
+ return;
+ }
+
+ ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT);
+
+ if (ctx->Driver.FlushMappedBufferRange)
+ ctx->Driver.FlushMappedBufferRange(ctx, target, offset, length, bufObj);
+}
diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h
index 163fe241aa..9f732ec0c0 100644
--- a/src/mesa/main/bufferobj.h
+++ b/src/mesa/main/bufferobj.h
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.2
+ * Version: 7.6
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -35,17 +36,32 @@
* Internal functions
*/
+
+/** Is the given buffer object currently mapped? */
+static INLINE GLboolean
+_mesa_bufferobj_mapped(const struct gl_buffer_object *obj)
+{
+ return obj->Pointer != NULL;
+}
+
+/**
+ * Is the given buffer object a user-created buffer object?
+ * Mesa uses default buffer objects in several places. Default buffers
+ * always have Name==0. User created buffers have Name!=0.
+ */
+static INLINE GLboolean
+_mesa_is_bufferobj(const struct gl_buffer_object *obj)
+{
+ return obj->Name != 0;
+}
+
+
extern void
_mesa_init_buffer_objects( GLcontext *ctx );
extern void
_mesa_update_default_objects_buffer_objects(GLcontext *ctx);
-extern struct gl_buffer_object *
-_mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target );
-
-extern void
-_mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj );
extern struct gl_buffer_object *
_mesa_lookup_bufferobj(GLcontext *ctx, GLuint buffer);
@@ -59,64 +75,50 @@ _mesa_reference_buffer_object(GLcontext *ctx,
struct gl_buffer_object **ptr,
struct gl_buffer_object *bufObj);
-extern void
-_mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
- const GLvoid * data, GLenum usage,
- struct gl_buffer_object * bufObj );
-
-extern void
-_mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
- GLsizeiptrARB size, const GLvoid * data,
- struct gl_buffer_object * bufObj );
-
-extern void
-_mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
- GLsizeiptrARB size, GLvoid * data,
- struct gl_buffer_object * bufObj );
-
-extern void *
-_mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
- struct gl_buffer_object * bufObj );
-
-extern GLboolean
-_mesa_buffer_unmap( GLcontext *ctx, GLenum target,
- struct gl_buffer_object * bufObj );
-
extern GLboolean
_mesa_validate_pbo_access(GLuint dimensions,
const struct gl_pixelstore_attrib *pack,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const GLvoid *ptr);
-extern const GLubyte *
-_mesa_map_bitmap_pbo(GLcontext *ctx,
+extern const GLvoid *
+_mesa_map_pbo_source(GLcontext *ctx,
const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap);
-
-extern void
-_mesa_unmap_bitmap_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *unpack);
+ const GLvoid *src);
extern const GLvoid *
-_mesa_map_drawpix_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *pixels);
+_mesa_map_validate_pbo_source(GLcontext *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr,
+ const char *where);
extern void
-_mesa_unmap_drapix_pbo(GLcontext *ctx,
+_mesa_unmap_pbo_source(GLcontext *ctx,
const struct gl_pixelstore_attrib *unpack);
-
extern void *
-_mesa_map_readpix_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *pack,
- GLvoid *dest);
+_mesa_map_pbo_dest(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest);
+
+extern GLvoid *
+_mesa_map_validate_pbo_dest(GLcontext *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, GLvoid *ptr,
+ const char *where);
extern void
-_mesa_unmap_readpix_pbo(GLcontext *ctx,
- const struct gl_pixelstore_attrib *pack);
+_mesa_unmap_pbo_dest(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *pack);
+extern void
+_mesa_init_buffer_object_functions(struct dd_function_table *driver);
+
/*
* API functions
@@ -155,4 +157,16 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params);
extern void GLAPIENTRY
_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params);
+extern void GLAPIENTRY
+_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size);
+
+extern void * GLAPIENTRY
+_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
+ GLbitfield access);
+
+extern void GLAPIENTRY
+_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
+
#endif
diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c
index b23d2f612b..d8b5f3b1f4 100644
--- a/src/mesa/main/buffers.c
+++ b/src/mesa/main/buffers.c
@@ -120,11 +120,9 @@ draw_buffer_enum_to_bitmask(GLenum buffer)
case GL_AUX0:
return BUFFER_BIT_AUX0;
case GL_AUX1:
- return BUFFER_BIT_AUX1;
case GL_AUX2:
- return BUFFER_BIT_AUX2;
case GL_AUX3:
- return BUFFER_BIT_AUX3;
+ return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */
case GL_COLOR_ATTACHMENT0_EXT:
return BUFFER_BIT_COLOR0;
case GL_COLOR_ATTACHMENT1_EXT:
@@ -177,11 +175,9 @@ read_buffer_enum_to_index(GLenum buffer)
case GL_AUX0:
return BUFFER_AUX0;
case GL_AUX1:
- return BUFFER_AUX1;
case GL_AUX2:
- return BUFFER_AUX2;
case GL_AUX3:
- return BUFFER_AUX3;
+ return BUFFER_COUNT; /* invalid, but not -1 */
case GL_COLOR_ATTACHMENT0_EXT:
return BUFFER_COLOR0;
case GL_COLOR_ATTACHMENT1_EXT:
@@ -247,13 +243,14 @@ _mesa_DrawBuffer(GLenum buffer)
destMask = draw_buffer_enum_to_bitmask(buffer);
if (destMask == BAD_MASK) {
/* totally bogus buffer */
- _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer=0x%x)", buffer);
return;
}
destMask &= supportedMask;
if (destMask == 0x0) {
/* none of the named color buffers exist! */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffer(buffer)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawBuffer(buffer=0x%x)", buffer);
return;
}
}
@@ -289,11 +286,10 @@ _mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers)
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (!ctx->Extensions.ARB_draw_buffers) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB");
- return;
- }
- if (n < 1 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
+ /* Turns out n==0 is a valid input that should not produce an error.
+ * The remaining code below correctly handles the n==0 case.
+ */
+ if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
_mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)");
return;
}
@@ -335,12 +331,14 @@ _mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers)
_mesa_drawbuffers(ctx, n, buffers, destMask);
/*
- * Call device driver function.
+ * Call device driver function. Note that n can be equal to 0,
+ * in which case we don't want to reference buffers[0], which
+ * may not be valid.
*/
if (ctx->Driver.DrawBuffers)
ctx->Driver.DrawBuffers(ctx, n, buffers);
else if (ctx->Driver.DrawBuffer)
- ctx->Driver.DrawBuffer(ctx, buffers[0]);
+ ctx->Driver.DrawBuffer(ctx, n>0? buffers[0]:GL_NONE);
}
@@ -419,7 +417,7 @@ _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers,
}
}
- ctx->NewState |= _NEW_COLOR;
+ ctx->NewState |= _NEW_BUFFERS;
}
@@ -445,7 +443,7 @@ _mesa_readbuffer(GLcontext *ctx, GLenum buffer, GLint bufferIndex)
fb->ColorReadBuffer = buffer;
fb->_ColorReadBufferIndex = bufferIndex;
- ctx->NewState |= _NEW_PIXEL;
+ ctx->NewState |= _NEW_BUFFERS;
}
@@ -494,6 +492,7 @@ _mesa_ReadBuffer(GLenum buffer)
/* OK, all error checking has been completed now */
_mesa_readbuffer(ctx, buffer, srcBuffer);
+ ctx->NewState |= _NEW_BUFFERS;
/*
* Call device driver function.
diff --git a/src/mesa/main/clip.c b/src/mesa/main/clip.c
index 43ef55ee3b..96c80e6ef8 100644
--- a/src/mesa/main/clip.c
+++ b/src/mesa/main/clip.c
@@ -29,7 +29,6 @@
#include "macros.h"
#include "mtypes.h"
-#include "math/m_xform.h"
#include "math/m_matrix.h"
diff --git a/src/mesa/main/colormac.h b/src/mesa/main/colormac.h
index 74692e9a98..815624ee50 100644
--- a/src/mesa/main/colormac.h
+++ b/src/mesa/main/colormac.h
@@ -71,9 +71,6 @@
/** \def COPY_CHAN4
* Copy a GLchan[4] array */
-/** \def CHAN_PRODUCT
- * Scaled product (usually approximated) between two GLchan arguments */
-
#if CHAN_BITS == 8
#define BYTE_TO_CHAN(b) ((b) < 0 ? 0 : (GLchan) (b))
@@ -91,8 +88,6 @@
#define COPY_CHAN4(DST, SRC) COPY_4UBV(DST, SRC)
-#define CHAN_PRODUCT(a, b) ((GLubyte) (((GLint)(a) * ((GLint)(b) + 1)) >> 8))
-
#elif CHAN_BITS == 16
#define BYTE_TO_CHAN(b) ((b) < 0 ? 0 : (((GLchan) (b)) * 516))
@@ -110,8 +105,6 @@
#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC)
-#define CHAN_PRODUCT(a, b) ((GLchan) ((((GLuint) (a)) * ((GLuint) (b))) / 65535))
-
#elif CHAN_BITS == 32
/* XXX floating-point color channels not fully thought-out */
@@ -130,8 +123,6 @@
#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC)
-#define CHAN_PRODUCT(a, b) ((a) * (b))
-
#else
#error unexpected CHAN_BITS size
diff --git a/src/mesa/main/colortab.c b/src/mesa/main/colortab.c
index bd9cf438b4..d6f3121cb4 100644
--- a/src/mesa/main/colortab.c
+++ b/src/mesa/main/colortab.c
@@ -31,6 +31,10 @@
#include "macros.h"
#include "state.h"
#include "teximage.h"
+#include "glapi/dispatch.h"
+
+
+#if FEATURE_colortable
/**
@@ -179,26 +183,12 @@ store_colortable_entries(GLcontext *ctx, struct gl_color_table *table,
GLfloat bScale, GLfloat bBias,
GLfloat aScale, GLfloat aBias)
{
- if (ctx->Unpack.BufferObj->Name) {
- /* Get/unpack the color table data from a PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(1, &ctx->Unpack, count, 1, 1,
- format, type, data)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glColor[Sub]Table(bad PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- ctx->Unpack.BufferObj);
- if (!buf) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glColor[Sub]Table(PBO mapped)");
- return;
- }
- data = ADD_POINTERS(buf, data);
- }
-
+ data = _mesa_map_validate_pbo_source(ctx,
+ 1, &ctx->Unpack, count, 1, 1,
+ format, type, data,
+ "glColor[Sub]Table");
+ if (!data)
+ return;
{
/* convert user-provided data to GLfloat values */
@@ -279,10 +269,7 @@ store_colortable_entries(GLcontext *ctx, struct gl_color_table *table,
}
}
- if (ctx->Unpack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- ctx->Unpack.BufferObj);
- }
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
}
@@ -696,34 +683,17 @@ _mesa_GetColorTable( GLenum target, GLenum format,
return;
}
- if (ctx->Pack.BufferObj->Name) {
- /* pack color table into PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(1, &ctx->Pack, table->Size, 1, 1,
- format, type, data)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetColorTable(invalid PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetColorTable(PBO is mapped)");
- return;
- }
- data = ADD_POINTERS(buf, data);
- }
+ data = _mesa_map_validate_pbo_dest(ctx,
+ 1, &ctx->Pack, table->Size, 1, 1,
+ format, type, data,
+ "glGetColorTable");
+ if (!data)
+ return;
_mesa_pack_rgba_span_float(ctx, table->Size, rgba,
format, type, data, &ctx->Pack, 0x0);
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
@@ -1078,6 +1048,25 @@ _mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params )
}
}
+
+void
+_mesa_init_colortable_dispatch(struct _glapi_table *disp)
+{
+ SET_ColorSubTable(disp, _mesa_ColorSubTable);
+ SET_ColorTable(disp, _mesa_ColorTable);
+ SET_ColorTableParameterfv(disp, _mesa_ColorTableParameterfv);
+ SET_ColorTableParameteriv(disp, _mesa_ColorTableParameteriv);
+ SET_CopyColorSubTable(disp, _mesa_CopyColorSubTable);
+ SET_CopyColorTable(disp, _mesa_CopyColorTable);
+ SET_GetColorTable(disp, _mesa_GetColorTable);
+ SET_GetColorTableParameterfv(disp, _mesa_GetColorTableParameterfv);
+ SET_GetColorTableParameteriv(disp, _mesa_GetColorTableParameteriv);
+}
+
+
+#endif /* FEATURE_colortable */
+
+
/**********************************************************************/
/***** Initialization *****/
/**********************************************************************/
diff --git a/src/mesa/main/colortab.h b/src/mesa/main/colortab.h
index b6ff737a65..ec28ceca9d 100644
--- a/src/mesa/main/colortab.h
+++ b/src/mesa/main/colortab.h
@@ -27,9 +27,16 @@
#define COLORTAB_H
-#include "mtypes.h"
+#include "main/mtypes.h"
-#if _HAVE_FULL_GL
+#if FEATURE_colortable
+
+#define _MESA_INIT_COLORTABLE_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->CopyColorTable = impl ## CopyColorTable; \
+ (driver)->CopyColorSubTable = impl ## CopyColorSubTable; \
+ (driver)->UpdateTexturePalette = impl ## UpdateTexturePalette; \
+ } while (0)
extern void GLAPIENTRY
_mesa_ColorTable( GLenum target, GLenum internalformat,
@@ -67,6 +74,19 @@ _mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params );
extern void GLAPIENTRY
_mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params );
+extern void
+_mesa_init_colortable_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_colortable */
+
+#define _MESA_INIT_COLORTABLE_FUNCTIONS(driver, impl) do { } while (0)
+
+static INLINE void
+_mesa_init_colortable_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_colortable */
extern void
@@ -81,20 +101,5 @@ _mesa_init_colortables( GLcontext *ctx );
extern void
_mesa_free_colortables_data( GLcontext *ctx );
-#else
-
-/** No-op */
-#define _mesa_init_colortable( p ) ((void) 0)
-
-/** No-op */
-#define _mesa_free_colortable_data( p ) ((void) 0)
-
-/** No-op */
-#define _mesa_init_colortables( p ) ((void)0)
-
-/** No-op */
-#define _mesa_free_colortables_data( p ) ((void)0)
-
-#endif
-#endif
+#endif /* COLORTAB_H */
diff --git a/src/mesa/main/compiler.h b/src/mesa/main/compiler.h
new file mode 100644
index 0000000000..9319505a75
--- /dev/null
+++ b/src/mesa/main/compiler.h
@@ -0,0 +1,484 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * \file compiler.h
+ * Compiler-related stuff.
+ */
+
+
+#ifndef COMPILER_H
+#define COMPILER_H
+
+
+#include <assert.h>
+#include <ctype.h>
+#if defined(__alpha__) && defined(CCPML)
+#include <cpml.h> /* use Compaq's Fast Math Library on Alpha */
+#else
+#include <math.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if defined(__linux__) && defined(__i386__)
+#include <fpu_control.h>
+#endif
+#include <float.h>
+#include <stdarg.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Get standard integer types
+ */
+#if defined(_MSC_VER)
+ typedef __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+ typedef __int16 int16_t;
+ typedef unsigned __int16 uint16_t;
+# ifndef __eglplatform_h_
+ typedef __int32 int32_t;
+# endif
+ typedef unsigned __int32 uint32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+
+# if defined(_WIN64)
+ typedef __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+# else
+ typedef __int32 intptr_t;
+ typedef unsigned __int32 uintptr_t;
+# endif
+
+# define INT64_C(__val) __val##i64
+# define UINT64_C(__val) __val##ui64
+#else
+# include <stdint.h>
+#endif
+
+
+/**
+ * Sun compilers define __i386 instead of the gcc-style __i386__
+ */
+#ifdef __SUNPRO_C
+# if !defined(__i386__) && defined(__i386)
+# define __i386__
+# elif !defined(__amd64__) && defined(__amd64)
+# define __amd64__
+# elif !defined(__sparc__) && defined(__sparc)
+# define __sparc__
+# endif
+# if !defined(__volatile)
+# define __volatile volatile
+# endif
+#endif
+
+
+/**
+ * finite macro.
+ */
+#if defined(_WIN32) && !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(BUILD_FOR_SNAP)
+# define __WIN32__
+# define finite _finite
+#elif defined(__WATCOMC__)
+# define finite _finite
+#endif
+
+
+/**
+ * Disable assorted warnings
+ */
+#if !defined(OPENSTEP) && (defined(__WIN32__) && !defined(__CYGWIN__)) && !defined(BUILD_FOR_SNAP)
+# if !defined(__GNUC__) /* mingw environment */
+# pragma warning( disable : 4068 ) /* unknown pragma */
+# pragma warning( disable : 4710 ) /* function 'foo' not inlined */
+# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */
+# pragma warning( disable : 4127 ) /* conditional expression is constant */
+# if defined(MESA_MINWARN)
+# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */
+# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */
+# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */
+# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */
+# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */
+# endif
+# endif
+#endif
+#if defined(__WATCOMC__)
+# pragma disable_message(201) /* Disable unreachable code warnings */
+#endif
+
+
+
+/**
+ * Function inlining
+ */
+#if defined(__GNUC__)
+# define INLINE __inline__
+#elif defined(__MSC__)
+# define INLINE __inline
+#elif defined(_MSC_VER)
+# define INLINE __inline
+#elif defined(__ICL)
+# define INLINE __inline
+#elif defined(__INTEL_COMPILER)
+# define INLINE inline
+#elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100)
+# define INLINE __inline
+#elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
+# define INLINE inline
+# define __inline inline
+# define __inline__ inline
+#elif (__STDC_VERSION__ >= 199901L) /* C99 */
+# define INLINE inline
+#else
+# define INLINE
+#endif
+
+
+/**
+ * PUBLIC/USED macros
+ *
+ * If we build the library with gcc's -fvisibility=hidden flag, we'll
+ * use the PUBLIC macro to mark functions that are to be exported.
+ *
+ * We also need to define a USED attribute, so the optimizer doesn't
+ * inline a static function that we later use in an alias. - ajax
+ */
+#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
+# define PUBLIC __attribute__((visibility("default")))
+# define USED __attribute__((used))
+#else
+# define PUBLIC
+# define USED
+#endif
+
+
+/**
+ * Some compilers don't like some of Mesa's const usage. In those places use
+ * CONST instead of const. Pass -DNO_CONST to compilers where this matters.
+ */
+#ifdef NO_CONST
+# define CONST
+#else
+# define CONST const
+#endif
+
+
+/**
+ * __builtin_expect macros
+ */
+#if (!defined(__GNUC__) || __GNUC__ < 3) && (!defined(__IBMC__) || __IBMC__ < 900)
+# define __builtin_expect(x, y) x
+#endif
+
+
+/**
+ * The __FUNCTION__ gcc variable is generally only used for debugging.
+ * If we're not using gcc, define __FUNCTION__ as a cpp symbol here.
+ * Don't define it if using a newer Windows compiler.
+ */
+#ifndef __FUNCTION__
+# if defined(__VMS)
+# define __FUNCTION__ "VMS$NL:"
+# elif ((!defined __GNUC__) || (__GNUC__ < 2)) && (!defined __xlC__) && \
+ (!defined(_MSC_VER) || _MSC_VER < 1300)
+# if (__STDC_VERSION__ >= 199901L) /* C99 */ || \
+ (defined(__SUNPRO_C) && defined(__C99FEATURES__))
+# define __FUNCTION__ __func__
+# else
+# define __FUNCTION__ "<unknown>"
+# endif
+# endif
+#endif
+
+
+/**
+ * Either define MESA_BIG_ENDIAN or MESA_LITTLE_ENDIAN.
+ * Do not use them unless absolutely necessary!
+ * Try to use a runtime test instead.
+ * For now, only used by some DRI hardware drivers for color/texel packing.
+ */
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+#if defined(__linux__)
+#include <byteswap.h>
+#define CPU_TO_LE32( x ) bswap_32( x )
+#elif defined(__APPLE__)
+#include <CoreFoundation/CFByteOrder.h>
+#define CPU_TO_LE32( x ) CFSwapInt32HostToLittle( x )
+#else /*__linux__ __APPLE__*/
+#include <sys/endian.h>
+#define CPU_TO_LE32( x ) bswap32( x )
+#endif /*__linux__*/
+#define MESA_BIG_ENDIAN 1
+#else
+#define CPU_TO_LE32( x ) ( x )
+#define MESA_LITTLE_ENDIAN 1
+#endif
+#define LE32_TO_CPU( x ) CPU_TO_LE32( x )
+
+
+
+#if !defined(CAPI) && defined(WIN32) && !defined(BUILD_FOR_SNAP)
+#define CAPI _cdecl
+#endif
+
+
+/**
+ * Create a macro so that asm functions can be linked into compilers other
+ * than GNU C
+ */
+#ifndef _ASMAPI
+#if defined(WIN32) && !defined(BUILD_FOR_SNAP)/* was: !defined( __GNUC__ ) && !defined( VMS ) && !defined( __INTEL_COMPILER )*/
+#define _ASMAPI __cdecl
+#else
+#define _ASMAPI
+#endif
+#ifdef PTR_DECL_IN_FRONT
+#define _ASMAPIP * _ASMAPI
+#else
+#define _ASMAPIP _ASMAPI *
+#endif
+#endif
+
+#ifdef USE_X86_ASM
+#define _NORMAPI _ASMAPI
+#define _NORMAPIP _ASMAPIP
+#else
+#define _NORMAPI
+#define _NORMAPIP *
+#endif
+
+
+/* This is a macro on IRIX */
+#ifdef _P
+#undef _P
+#endif
+
+
+/* Turn off macro checking systems used by other libraries */
+#ifdef CHECK
+#undef CHECK
+#endif
+
+
+/**
+ * ASSERT macro
+ */
+#if !defined(_WIN32_WCE)
+#if defined(BUILD_FOR_SNAP) && defined(CHECKED)
+# define ASSERT(X) _CHECK(X)
+#elif defined(DEBUG)
+# define ASSERT(X) assert(X)
+#else
+# define ASSERT(X)
+#endif
+#endif
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/**
+ * LONGSTRING macro
+ * gcc -pedantic warns about long string literals, LONGSTRING silences that.
+ */
+#if !defined(__GNUC__) || (__GNUC__ < 2) || \
+ ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
+# define LONGSTRING
+#else
+# define LONGSTRING __extension__
+#endif
+
+
+#ifndef M_PI
+#define M_PI (3.1415926536)
+#endif
+
+#ifndef M_E
+#define M_E (2.7182818284590452354)
+#endif
+
+#ifndef ONE_DIV_LN2
+#define ONE_DIV_LN2 (1.442695040888963456)
+#endif
+
+#ifndef ONE_DIV_SQRT_LN2
+#define ONE_DIV_SQRT_LN2 (1.201122408786449815)
+#endif
+
+#ifndef FLT_MAX_EXP
+#define FLT_MAX_EXP 128
+#endif
+
+
+/**
+ * USE_IEEE: Determine if we're using IEEE floating point
+ */
+#if defined(__i386__) || defined(__386__) || defined(__sparc__) || \
+ defined(__s390x__) || defined(__powerpc__) || \
+ defined(__x86_64__) || \
+ defined(ia64) || defined(__ia64__) || \
+ defined(__hppa__) || defined(hpux) || \
+ defined(__mips) || defined(_MIPS_ARCH) || \
+ defined(__arm__) || \
+ defined(__sh__) || defined(__m32r__) || \
+ (defined(__sun) && defined(_IEEE_754)) || \
+ (defined(__alpha__) && (defined(__IEEE_FLOAT) || !defined(VMS)))
+#define USE_IEEE
+#define IEEE_ONE 0x3f800000
+#endif
+
+
+/**
+ * START/END_FAST_MATH macros:
+ *
+ * START_FAST_MATH: Set x86 FPU to faster, 32-bit precision mode (and save
+ * original mode to a temporary).
+ * END_FAST_MATH: Restore x86 FPU to original mode.
+ */
+#if defined(__GNUC__) && defined(__i386__)
+/*
+ * Set the x86 FPU control word to guarentee only 32 bits of precision
+ * are stored in registers. Allowing the FPU to store more introduces
+ * differences between situations where numbers are pulled out of memory
+ * vs. situations where the compiler is able to optimize register usage.
+ *
+ * In the worst case, we force the compiler to use a memory access to
+ * truncate the float, by specifying the 'volatile' keyword.
+ */
+/* Hardware default: All exceptions masked, extended double precision,
+ * round to nearest (IEEE compliant):
+ */
+#define DEFAULT_X86_FPU 0x037f
+/* All exceptions masked, single precision, round to nearest:
+ */
+#define FAST_X86_FPU 0x003f
+/* The fldcw instruction will cause any pending FP exceptions to be
+ * raised prior to entering the block, and we clear any pending
+ * exceptions before exiting the block. Hence, asm code has free
+ * reign over the FPU while in the fast math block.
+ */
+#if defined(NO_FAST_MATH)
+#define START_FAST_MATH(x) \
+do { \
+ static GLuint mask = DEFAULT_X86_FPU; \
+ __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
+ __asm__ ( "fldcw %0" : : "m" (mask) ); \
+} while (0)
+#else
+#define START_FAST_MATH(x) \
+do { \
+ static GLuint mask = FAST_X86_FPU; \
+ __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
+ __asm__ ( "fldcw %0" : : "m" (mask) ); \
+} while (0)
+#endif
+/* Restore original FPU mode, and clear any exceptions that may have
+ * occurred in the FAST_MATH block.
+ */
+#define END_FAST_MATH(x) \
+do { \
+ __asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \
+} while (0)
+
+#elif defined(__WATCOMC__) && defined(__386__)
+#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */
+#define FAST_X86_FPU 0x003f /* See GCC comments above */
+void _watcom_start_fast_math(unsigned short *x,unsigned short *mask);
+#pragma aux _watcom_start_fast_math = \
+ "fnstcw word ptr [eax]" \
+ "fldcw word ptr [ecx]" \
+ parm [eax] [ecx] \
+ modify exact [];
+void _watcom_end_fast_math(unsigned short *x);
+#pragma aux _watcom_end_fast_math = \
+ "fnclex" \
+ "fldcw word ptr [eax]" \
+ parm [eax] \
+ modify exact [];
+#if defined(NO_FAST_MATH)
+#define START_FAST_MATH(x) \
+do { \
+ static GLushort mask = DEFAULT_X86_FPU; \
+ _watcom_start_fast_math(&x,&mask); \
+} while (0)
+#else
+#define START_FAST_MATH(x) \
+do { \
+ static GLushort mask = FAST_X86_FPU; \
+ _watcom_start_fast_math(&x,&mask); \
+} while (0)
+#endif
+#define END_FAST_MATH(x) _watcom_end_fast_math(&x)
+
+#elif defined(_MSC_VER) && defined(_M_IX86)
+#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */
+#define FAST_X86_FPU 0x003f /* See GCC comments above */
+#if defined(NO_FAST_MATH)
+#define START_FAST_MATH(x) do {\
+ static GLuint mask = DEFAULT_X86_FPU;\
+ __asm fnstcw word ptr [x]\
+ __asm fldcw word ptr [mask]\
+} while(0)
+#else
+#define START_FAST_MATH(x) do {\
+ static GLuint mask = FAST_X86_FPU;\
+ __asm fnstcw word ptr [x]\
+ __asm fldcw word ptr [mask]\
+} while(0)
+#endif
+#define END_FAST_MATH(x) do {\
+ __asm fnclex\
+ __asm fldcw word ptr [x]\
+} while(0)
+
+#else
+#define START_FAST_MATH(x) x = 0
+#define END_FAST_MATH(x) (void)(x)
+#endif
+
+
+#ifndef Elements
+#define Elements(x) (sizeof(x)/sizeof(*(x)))
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* COMPILER_H */
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index cf1198cd0d..8a09efdb53 100644
--- a/src/mesa/main/config.h
+++ b/src/mesa/main/config.h
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.3
+ * Version: 7.5
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
* Copyright (C) 2008 VMware, Inc. All Rights Reserved.
@@ -32,9 +32,6 @@
#define MESA_CONFIG_H_INCLUDED
-#include "main/mfeatures.h"
-
-
/**
* \name OpenGL implementation limits
*/
@@ -71,7 +68,7 @@
#define MAX_PIXEL_MAP_TABLE 256
/** Maximum number of auxillary color buffers */
-#define MAX_AUX_BUFFERS 4
+#define MAX_AUX_BUFFERS 1
/** Maximum order (degree) of curves */
#ifdef AMIGA
@@ -101,16 +98,16 @@
#define MAX_COLOR_TABLE_SIZE 256
/** Number of 1D/2D texture mipmap levels */
-#define MAX_TEXTURE_LEVELS 12
+#define MAX_TEXTURE_LEVELS 13
/** Number of 3D texture mipmap levels */
#define MAX_3D_TEXTURE_LEVELS 9
/** Number of cube texture mipmap levels - GL_ARB_texture_cube_map */
-#define MAX_CUBE_TEXTURE_LEVELS 12
+#define MAX_CUBE_TEXTURE_LEVELS 13
/** Maximum rectangular texture size - GL_NV_texture_rectangle */
-#define MAX_TEXTURE_RECT_SIZE 2048
+#define MAX_TEXTURE_RECT_SIZE 4096
/** Maximum number of layers in a 1D or 2D array texture - GL_MESA_texture_array */
#define MAX_ARRAY_TEXTURE_LAYERS 64
@@ -141,9 +138,14 @@
/**
* Maximum viewport/image width. Must accomodate all texture sizes too.
*/
-#define MAX_WIDTH 4096
+
+#ifndef MAX_WIDTH
+# define MAX_WIDTH 4096
+#endif
/** Maximum viewport/image height */
-#define MAX_HEIGHT 4096
+#ifndef MAX_HEIGHT
+# define MAX_HEIGHT 4096
+#endif
/** Maxmimum size for CVA. May be overridden by the drivers. */
#define MAX_ARRAY_LOCK_SIZE 3000
@@ -166,43 +168,62 @@
#define MAX_TEXTURE_MAX_ANISOTROPY 16.0
/** For GL_EXT_texture_lod_bias (typically MAX_TEXTURE_LEVELS - 1) */
-#define MAX_TEXTURE_LOD_BIAS 11.0
+#define MAX_TEXTURE_LOD_BIAS 12.0
+
+/** For any program target/extension */
+/*@{*/
+#define MAX_PROGRAM_INSTRUCTIONS (16 * 1024)
+
+/**
+ * Per-program constants (power of two)
+ *
+ * \c MAX_PROGRAM_LOCAL_PARAMS and \c MAX_UNIFORMS are just the assmebly shader
+ * and GLSL shader names for the same thing. They should \b always have the
+ * same value. Each refers to the number of vec4 values supplied as
+ * per-program parameters.
+ */
+/*@{*/
+#define MAX_PROGRAM_LOCAL_PARAMS 1024
+#define MAX_UNIFORMS 1024
+/*@}*/
+
+/**
+ * Per-context constants (power of two)
+ *
+ * \note
+ * This value should always be less than or equal to \c MAX_PROGRAM_LOCAL_PARAMS
+ * and \c MAX_VERTEX_PROGRAM_PARAMS. Otherwise some applications will make
+ * incorrect assumptions.
+ */
+#define MAX_PROGRAM_ENV_PARAMS 256
+
+#define MAX_PROGRAM_MATRICES 8
+#define MAX_PROGRAM_MATRIX_STACK_DEPTH 4
+#define MAX_PROGRAM_CALL_DEPTH 8
+#define MAX_PROGRAM_TEMPS 256
+#define MAX_PROGRAM_ADDRESS_REGS 2
+#define MAX_VARYING 16 /**< number of float[4] vectors */
+#define MAX_SAMPLERS MAX_TEXTURE_IMAGE_UNITS
+#define MAX_PROGRAM_INPUTS 32
+#define MAX_PROGRAM_OUTPUTS 32
+/*@}*/
/** For GL_ARB_vertex_program */
/*@{*/
#define MAX_VERTEX_PROGRAM_ADDRESS_REGS 1
-#define MAX_VERTEX_PROGRAM_ATTRIBS 16
+#define MAX_VERTEX_PROGRAM_PARAMS MAX_UNIFORMS
/*@}*/
/** For GL_ARB_fragment_program */
/*@{*/
#define MAX_FRAGMENT_PROGRAM_ADDRESS_REGS 0
-#define MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS 48
-#define MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS 24
-#define MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS 4
-/*@}*/
-
-/** For any program target/extension */
-/*@{*/
-#define MAX_PROGRAM_LOCAL_PARAMS 256 /**< per-program constants (power of two) */
-#define MAX_PROGRAM_ENV_PARAMS 128
-#define MAX_PROGRAM_MATRICES 8
-#define MAX_PROGRAM_MATRIX_STACK_DEPTH 4
-#define MAX_PROGRAM_CALL_DEPTH 8
-#define MAX_PROGRAM_TEMPS 128
-#define MAX_PROGRAM_ADDRESS_REGS 2
-#define MAX_UNIFORMS 256 /**< number of vec4 uniforms */
-#define MAX_VARYING 8 /**< number of float[4] vectors */
-#define MAX_SAMPLERS MAX_TEXTURE_IMAGE_UNITS
-#define MAX_PROGRAM_INPUTS 32
-#define MAX_PROGRAM_OUTPUTS 32
/*@}*/
/** For GL_NV_vertex_program */
/*@{*/
#define MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS 128
#define MAX_NV_VERTEX_PROGRAM_TEMPS 12
-#define MAX_NV_VERTEX_PROGRAM_PARAMS MAX_PROGRAM_ENV_PARAMS
+#define MAX_NV_VERTEX_PROGRAM_PARAMS 96
#define MAX_NV_VERTEX_PROGRAM_INPUTS 16
#define MAX_NV_VERTEX_PROGRAM_OUTPUTS 15
/*@}*/
@@ -220,7 +241,7 @@
/** For GL_ARB_vertex_shader */
/*@{*/
-#define MAX_VERTEX_ATTRIBS 16
+#define MAX_VERTEX_GENERIC_ATTRIBS 16
#define MAX_VERTEX_TEXTURE_IMAGE_UNITS MAX_TEXTURE_IMAGE_UNITS
#define MAX_COMBINED_TEXTURE_IMAGE_UNITS MAX_TEXTURE_IMAGE_UNITS
/*@}*/
@@ -237,7 +258,8 @@
#define MAX_COLOR_ATTACHMENTS 8
/*@}*/
-
+/** For GL_ATI_envmap_bump - support bump mapping on first 8 units */
+#define SUPPORTED_ATI_BUMP_UNITS 0xff
/**
* \name Mesa-specific parameters
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 98c23bbd3a..4e637ff44b 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -77,42 +77,30 @@
#include "glheader.h"
+#include "mfeatures.h"
#include "imports.h"
-#if FEATURE_accum
#include "accum.h"
-#endif
#include "api_exec.h"
#include "arrayobj.h"
-#if FEATURE_attrib_stack
#include "attrib.h"
-#endif
#include "blend.h"
#include "buffers.h"
#include "bufferobj.h"
-#if FEATURE_colortable
#include "colortab.h"
-#endif
#include "context.h"
+#include "cpuinfo.h"
#include "debug.h"
#include "depth.h"
-#if FEATURE_dlist
#include "dlist.h"
-#endif
-#if FEATURE_evaluators
#include "eval.h"
-#endif
#include "enums.h"
#include "extensions.h"
#include "fbobject.h"
-#if FEATURE_feedback
#include "feedback.h"
-#endif
#include "fog.h"
#include "framebuffer.h"
#include "get.h"
-#if FEATURE_histogram
#include "histogram.h"
-#endif
#include "hint.h"
#include "hash.h"
#include "light.h"
@@ -124,13 +112,13 @@
#include "pixelstore.h"
#include "points.h"
#include "polygon.h"
-#if FEATURE_ARB_occlusion_query
#include "queryobj.h"
+#if FEATURE_ARB_sync
+#include "syncobj.h"
#endif
-#if FEATURE_drawpix
#include "rastpos.h"
-#endif
#include "scissor.h"
+#include "shared.h"
#include "simple_list.h"
#include "state.h"
#include "stencil.h"
@@ -141,22 +129,19 @@
#include "mtypes.h"
#include "varray.h"
#include "version.h"
+#include "viewport.h"
#include "vtxfmt.h"
#include "glapi/glthread.h"
#include "glapi/glapioffsets.h"
#include "glapi/glapitable.h"
-#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
#include "shader/program.h"
-#endif
+#include "shader/prog_print.h"
#include "shader/shader_api.h"
#if FEATURE_ATI_fragment_shader
#include "shader/atifragshader.h"
#endif
#if _HAVE_FULL_GL
-#include "math/m_translate.h"
#include "math/m_matrix.h"
-#include "math/m_xform.h"
-#include "math/mathmod.h"
#endif
#ifdef USE_SPARC_ASM
@@ -180,15 +165,18 @@ GLfloat _mesa_ubyte_to_float_color_tab[256];
/**
* Swap buffers notification callback.
*
- * \param gc GL context.
+ * \param ctx GL context.
*
* Called by window system just before swapping buffers.
* We have to finish any pending rendering.
*/
void
-_mesa_notifySwapBuffers(__GLcontext *gc)
+_mesa_notifySwapBuffers(__GLcontext *ctx)
{
- FLUSH_VERTICES( gc, 0 );
+ FLUSH_CURRENT( ctx, 0 );
+ if (ctx->Driver.Flush) {
+ ctx->Driver.Flush(ctx);
+ }
}
@@ -352,6 +340,36 @@ _mesa_destroy_visual( GLvisual *vis )
/**********************************************************************/
/*@{*/
+
+/**
+ * This is lame. gdb only seems to recognize enum types that are
+ * actually used somewhere. We want to be able to print/use enum
+ * values such as TEXTURE_2D_INDEX in gdb. But we don't actually use
+ * the gl_texture_index type anywhere. Thus, this lame function.
+ */
+static void
+dummy_enum_func(void)
+{
+ gl_buffer_index bi;
+ gl_colortable_index ci;
+ gl_face_index fi;
+ gl_frag_attrib fa;
+ gl_frag_result fr;
+ gl_texture_index ti;
+ gl_vert_attrib va;
+ gl_vert_result vr;
+
+ (void) bi;
+ (void) ci;
+ (void) fi;
+ (void) fa;
+ (void) fr;
+ (void) ti;
+ (void) va;
+ (void) vr;
+}
+
+
/**
* One-time initialization mutex lock.
*
@@ -385,19 +403,14 @@ one_time_init( GLcontext *ctx )
assert( sizeof(GLint) == 4 );
assert( sizeof(GLuint) == 4 );
- _mesa_init_sqrt_table();
+ _mesa_get_cpu_features();
-#if _HAVE_FULL_GL
- _math_init();
+ _mesa_init_sqrt_table();
for (i = 0; i < 256; i++) {
_mesa_ubyte_to_float_color_tab[i] = (float) i / 255.0F;
}
-#endif
-#ifdef USE_SPARC_ASM
- _mesa_init_sparc_glapi_relocs();
-#endif
if (_mesa_getenv("MESA_DEBUG")) {
_glapi_noop_enable_warnings(GL_TRUE);
_glapi_set_warning_func( (_glapi_warning_func) _mesa_warning );
@@ -414,383 +427,8 @@ one_time_init( GLcontext *ctx )
alreadyCalled = GL_TRUE;
}
_glthread_UNLOCK_MUTEX(OneTimeLock);
-}
-
-
-/**
- * Allocate and initialize a shared context state structure.
- * Initializes the display list, texture objects and vertex programs hash
- * tables, allocates the texture objects. If it runs out of memory, frees
- * everything already allocated before returning NULL.
- *
- * \return pointer to a gl_shared_state structure on success, or NULL on
- * failure.
- */
-static GLboolean
-alloc_shared_state( GLcontext *ctx )
-{
- struct gl_shared_state *ss = CALLOC_STRUCT(gl_shared_state);
- if (!ss)
- return GL_FALSE;
-
- ctx->Shared = ss;
-
- _glthread_INIT_MUTEX(ss->Mutex);
-
- ss->DisplayList = _mesa_NewHashTable();
- ss->TexObjects = _mesa_NewHashTable();
- ss->Programs = _mesa_NewHashTable();
-
-#if FEATURE_ARB_vertex_program
- ss->DefaultVertexProgram = (struct gl_vertex_program *)
- ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
- if (!ss->DefaultVertexProgram)
- goto cleanup;
-#endif
-#if FEATURE_ARB_fragment_program
- ss->DefaultFragmentProgram = (struct gl_fragment_program *)
- ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
- if (!ss->DefaultFragmentProgram)
- goto cleanup;
-#endif
-#if FEATURE_ATI_fragment_shader
- ss->ATIShaders = _mesa_NewHashTable();
- ss->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0);
- if (!ss->DefaultFragmentShader)
- goto cleanup;
-#endif
-
-#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
- ss->BufferObjects = _mesa_NewHashTable();
-#endif
-
- ss->ArrayObjects = _mesa_NewHashTable();
-
-#if FEATURE_ARB_shader_objects
- ss->ShaderObjects = _mesa_NewHashTable();
-#endif
-
- ss->Default1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
- if (!ss->Default1D)
- goto cleanup;
-
- ss->Default2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D);
- if (!ss->Default2D)
- goto cleanup;
-
- ss->Default3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D);
- if (!ss->Default3D)
- goto cleanup;
-
- ss->DefaultCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB);
- if (!ss->DefaultCubeMap)
- goto cleanup;
-
- ss->DefaultRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV);
- if (!ss->DefaultRect)
- goto cleanup;
-
- ss->Default1DArray = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D_ARRAY_EXT);
- if (!ss->Default1DArray)
- goto cleanup;
-
- ss->Default2DArray = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D_ARRAY_EXT);
- if (!ss->Default2DArray)
- goto cleanup;
-
- /* sanity check */
- assert(ss->Default1D->RefCount == 1);
-
- _glthread_INIT_MUTEX(ss->TexMutex);
- ss->TextureStateStamp = 0;
-
-#if FEATURE_EXT_framebuffer_object
- ss->FrameBuffers = _mesa_NewHashTable();
- if (!ss->FrameBuffers)
- goto cleanup;
- ss->RenderBuffers = _mesa_NewHashTable();
- if (!ss->RenderBuffers)
- goto cleanup;
-#endif
-
- return GL_TRUE;
-
-cleanup:
- /* Ran out of memory at some point. Free everything and return NULL */
- if (ss->DisplayList)
- _mesa_DeleteHashTable(ss->DisplayList);
- if (ss->TexObjects)
- _mesa_DeleteHashTable(ss->TexObjects);
- if (ss->Programs)
- _mesa_DeleteHashTable(ss->Programs);
-#if FEATURE_ARB_vertex_program
- _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL);
-#endif
-#if FEATURE_ARB_fragment_program
- _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL);
-#endif
-#if FEATURE_ATI_fragment_shader
- if (ss->DefaultFragmentShader)
- _mesa_delete_ati_fragment_shader(ctx, ss->DefaultFragmentShader);
-#endif
-#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
- if (ss->BufferObjects)
- _mesa_DeleteHashTable(ss->BufferObjects);
-#endif
-
- if (ss->ArrayObjects)
- _mesa_DeleteHashTable (ss->ArrayObjects);
-
-#if FEATURE_ARB_shader_objects
- if (ss->ShaderObjects)
- _mesa_DeleteHashTable (ss->ShaderObjects);
-#endif
-
-#if FEATURE_EXT_framebuffer_object
- if (ss->FrameBuffers)
- _mesa_DeleteHashTable(ss->FrameBuffers);
- if (ss->RenderBuffers)
- _mesa_DeleteHashTable(ss->RenderBuffers);
-#endif
-
- if (ss->Default1D)
- (*ctx->Driver.DeleteTexture)(ctx, ss->Default1D);
- if (ss->Default2D)
- (*ctx->Driver.DeleteTexture)(ctx, ss->Default2D);
- if (ss->Default3D)
- (*ctx->Driver.DeleteTexture)(ctx, ss->Default3D);
- if (ss->DefaultCubeMap)
- (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultCubeMap);
- if (ss->DefaultRect)
- (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultRect);
- if (ss->Default1DArray)
- (*ctx->Driver.DeleteTexture)(ctx, ss->Default1DArray);
- if (ss->Default2DArray)
- (*ctx->Driver.DeleteTexture)(ctx, ss->Default2DArray);
-
- _mesa_free(ss);
-
- return GL_FALSE;
-}
-
-
-/**
- * Callback for deleting a display list. Called by _mesa_HashDeleteAll().
- */
-static void
-delete_displaylist_cb(GLuint id, void *data, void *userData)
-{
-#if FEATURE_dlist
- struct mesa_display_list *list = (struct mesa_display_list *) data;
- GLcontext *ctx = (GLcontext *) userData;
- _mesa_delete_list(ctx, list);
-#endif
-}
-
-/**
- * Callback for deleting a texture object. Called by _mesa_HashDeleteAll().
- */
-static void
-delete_texture_cb(GLuint id, void *data, void *userData)
-{
- struct gl_texture_object *texObj = (struct gl_texture_object *) data;
- GLcontext *ctx = (GLcontext *) userData;
- ctx->Driver.DeleteTexture(ctx, texObj);
-}
-
-/**
- * Callback for deleting a program object. Called by _mesa_HashDeleteAll().
- */
-static void
-delete_program_cb(GLuint id, void *data, void *userData)
-{
- struct gl_program *prog = (struct gl_program *) data;
- GLcontext *ctx = (GLcontext *) userData;
- ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */
- prog->RefCount = 0; /* now going away */
- ctx->Driver.DeleteProgram(ctx, prog);
-}
-
-/**
- * Callback for deleting an ATI fragment shader object.
- * Called by _mesa_HashDeleteAll().
- */
-static void
-delete_fragshader_cb(GLuint id, void *data, void *userData)
-{
- struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data;
- GLcontext *ctx = (GLcontext *) userData;
- _mesa_delete_ati_fragment_shader(ctx, shader);
-}
-
-/**
- * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll().
- */
-static void
-delete_bufferobj_cb(GLuint id, void *data, void *userData)
-{
- struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data;
- GLcontext *ctx = (GLcontext *) userData;
- ctx->Driver.DeleteBuffer(ctx, bufObj);
-}
-
-/**
- * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
- */
-static void
-delete_arrayobj_cb(GLuint id, void *data, void *userData)
-{
- struct gl_array_object *arrayObj = (struct gl_array_object *) data;
- GLcontext *ctx = (GLcontext *) userData;
- _mesa_delete_array_object(ctx, arrayObj);
-}
-
-/**
- * Callback for freeing shader program data. Call it before delete_shader_cb
- * to avoid memory access error.
- */
-static void
-free_shader_program_data_cb(GLuint id, void *data, void *userData)
-{
- GLcontext *ctx = (GLcontext *) userData;
- struct gl_shader_program *shProg = (struct gl_shader_program *) data;
-
- if (shProg->Type == GL_SHADER_PROGRAM_MESA) {
- _mesa_free_shader_program_data(ctx, shProg);
- }
-}
-
-/**
- * Callback for deleting shader and shader programs objects.
- * Called by _mesa_HashDeleteAll().
- */
-static void
-delete_shader_cb(GLuint id, void *data, void *userData)
-{
- GLcontext *ctx = (GLcontext *) userData;
- struct gl_shader *sh = (struct gl_shader *) data;
- if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) {
- _mesa_free_shader(ctx, sh);
- }
- else {
- struct gl_shader_program *shProg = (struct gl_shader_program *) data;
- ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA);
- _mesa_free_shader_program(ctx, shProg);
- }
-}
-
-/**
- * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll()
- */
-static void
-delete_framebuffer_cb(GLuint id, void *data, void *userData)
-{
- struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
- /* The fact that the framebuffer is in the hashtable means its refcount
- * is one, but we're removing from the hashtable now. So clear refcount.
- */
- /*assert(fb->RefCount == 1);*/
- fb->RefCount = 0;
- /* NOTE: Delete should always be defined but there are two reports
- * of it being NULL (bugs 13507, 14293). Work-around for now.
- */
- if (fb->Delete)
- fb->Delete(fb);
-}
-
-/**
- * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll()
- */
-static void
-delete_renderbuffer_cb(GLuint id, void *data, void *userData)
-{
- struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data;
- rb->RefCount = 0; /* see comment for FBOs above */
- if (rb->Delete)
- rb->Delete(rb);
-}
-
-
-
-/**
- * Deallocate a shared state object and all children structures.
- *
- * \param ctx GL context.
- * \param ss shared state pointer.
- *
- * Frees the display lists, the texture objects (calling the driver texture
- * deletion callback to free its private data) and the vertex programs, as well
- * as their hash tables.
- *
- * \sa alloc_shared_state().
- */
-static void
-free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
-{
- /*
- * Free display lists
- */
- _mesa_HashDeleteAll(ss->DisplayList, delete_displaylist_cb, ctx);
- _mesa_DeleteHashTable(ss->DisplayList);
-
-#if FEATURE_ARB_shader_objects
- _mesa_HashWalk(ss->ShaderObjects, free_shader_program_data_cb, ctx);
- _mesa_HashDeleteAll(ss->ShaderObjects, delete_shader_cb, ctx);
- _mesa_DeleteHashTable(ss->ShaderObjects);
-#endif
-
- _mesa_HashDeleteAll(ss->Programs, delete_program_cb, ctx);
- _mesa_DeleteHashTable(ss->Programs);
-
-#if FEATURE_ARB_vertex_program
- _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL);
-#endif
-#if FEATURE_ARB_fragment_program
- _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL);
-#endif
-
-#if FEATURE_ATI_fragment_shader
- _mesa_HashDeleteAll(ss->ATIShaders, delete_fragshader_cb, ctx);
- _mesa_DeleteHashTable(ss->ATIShaders);
- _mesa_delete_ati_fragment_shader(ctx, ss->DefaultFragmentShader);
-#endif
-
-#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
- _mesa_HashDeleteAll(ss->BufferObjects, delete_bufferobj_cb, ctx);
- _mesa_DeleteHashTable(ss->BufferObjects);
-#endif
-
- _mesa_HashDeleteAll(ss->ArrayObjects, delete_arrayobj_cb, ctx);
- _mesa_DeleteHashTable(ss->ArrayObjects);
-
-#if FEATURE_EXT_framebuffer_object
- _mesa_HashDeleteAll(ss->FrameBuffers, delete_framebuffer_cb, ctx);
- _mesa_DeleteHashTable(ss->FrameBuffers);
- _mesa_HashDeleteAll(ss->RenderBuffers, delete_renderbuffer_cb, ctx);
- _mesa_DeleteHashTable(ss->RenderBuffers);
-#endif
-
- /*
- * Free texture objects (after FBOs since some textures might have
- * been bound to FBOs).
- */
- ASSERT(ctx->Driver.DeleteTexture);
- /* the default textures */
- ctx->Driver.DeleteTexture(ctx, ss->Default1D);
- ctx->Driver.DeleteTexture(ctx, ss->Default2D);
- ctx->Driver.DeleteTexture(ctx, ss->Default3D);
- ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap);
- ctx->Driver.DeleteTexture(ctx, ss->DefaultRect);
- ctx->Driver.DeleteTexture(ctx, ss->Default1DArray);
- ctx->Driver.DeleteTexture(ctx, ss->Default2DArray);
- /* all other textures */
- _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx);
- _mesa_DeleteHashTable(ss->TexObjects);
-
- _glthread_DESTROY_MUTEX(ss->Mutex);
-
- _mesa_free(ss);
+ dummy_enum_func();
}
@@ -803,7 +441,7 @@ _mesa_init_current(GLcontext *ctx)
GLuint i;
/* Init all to (0,0,0,1) */
- for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ for (i = 0; i < Elements(ctx->Current.Attrib); i++) {
ASSIGN_4V( ctx->Current.Attrib[i], 0.0, 0.0, 0.0, 1.0 );
}
@@ -818,19 +456,43 @@ _mesa_init_current(GLcontext *ctx)
/**
- * Init vertex/fragment program native limits from logical limits.
+ * Init vertex/fragment program limits.
+ * Important: drivers should override these with actual limits.
*/
static void
-init_natives(struct gl_program_constants *prog)
+init_program_limits(GLenum type, struct gl_program_constants *prog)
{
- prog->MaxNativeInstructions = prog->MaxInstructions;
- prog->MaxNativeAluInstructions = prog->MaxAluInstructions;
- prog->MaxNativeTexInstructions = prog->MaxTexInstructions;
- prog->MaxNativeTexIndirections = prog->MaxTexIndirections;
- prog->MaxNativeAttribs = prog->MaxAttribs;
- prog->MaxNativeTemps = prog->MaxTemps;
- prog->MaxNativeAddressRegs = prog->MaxAddressRegs;
- prog->MaxNativeParameters = prog->MaxParameters;
+ prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxAluInstructions = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxTexInstructions = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxTexIndirections = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxTemps = MAX_PROGRAM_TEMPS;
+ prog->MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
+ prog->MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
+ prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
+
+ if (type == GL_VERTEX_PROGRAM_ARB) {
+ prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS;
+ prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
+ prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
+ }
+ else {
+ prog->MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
+ prog->MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS;
+ prog->MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
+ }
+
+ /* Set the native limits to zero. This implies that there is no native
+ * support for shaders. Let the drivers fill in the actual values.
+ */
+ prog->MaxNativeInstructions = 0;
+ prog->MaxNativeAluInstructions = 0;
+ prog->MaxNativeTexInstructions = 0;
+ prog->MaxNativeTexIndirections = 0;
+ prog->MaxNativeAttribs = 0;
+ prog->MaxNativeTemps = 0;
+ prog->MaxNativeAddressRegs = 0;
+ prog->MaxNativeParameters = 0;
}
@@ -847,6 +509,9 @@ _mesa_init_constants(GLcontext *ctx)
assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
+ /* Max texture size should be <= max viewport size (render to texture) */
+ assert((1 << (MAX_TEXTURE_LEVELS - 1)) <= MAX_WIDTH);
+
/* Constants, may be overriden (usually only reduced) by device drivers */
ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
@@ -881,33 +546,10 @@ _mesa_init_constants(GLcontext *ctx)
ctx->Const.MaxViewportWidth = MAX_WIDTH;
ctx->Const.MaxViewportHeight = MAX_HEIGHT;
#if FEATURE_ARB_vertex_program
- ctx->Const.VertexProgram.MaxInstructions = MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS;
- ctx->Const.VertexProgram.MaxAluInstructions = 0;
- ctx->Const.VertexProgram.MaxTexInstructions = 0;
- ctx->Const.VertexProgram.MaxTexIndirections = 0;
- ctx->Const.VertexProgram.MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
- ctx->Const.VertexProgram.MaxTemps = MAX_PROGRAM_TEMPS;
- ctx->Const.VertexProgram.MaxParameters = MAX_NV_VERTEX_PROGRAM_PARAMS;
- ctx->Const.VertexProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
- ctx->Const.VertexProgram.MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
- ctx->Const.VertexProgram.MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
- ctx->Const.VertexProgram.MaxUniformComponents = 4 * MAX_UNIFORMS;
- init_natives(&ctx->Const.VertexProgram);
+ init_program_limits(GL_VERTEX_PROGRAM_ARB, &ctx->Const.VertexProgram);
#endif
-
#if FEATURE_ARB_fragment_program
- ctx->Const.FragmentProgram.MaxInstructions = MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS;
- ctx->Const.FragmentProgram.MaxAluInstructions = MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS;
- ctx->Const.FragmentProgram.MaxTexInstructions = MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS;
- ctx->Const.FragmentProgram.MaxTexIndirections = MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS;
- ctx->Const.FragmentProgram.MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS;
- ctx->Const.FragmentProgram.MaxTemps = MAX_PROGRAM_TEMPS;
- ctx->Const.FragmentProgram.MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
- ctx->Const.FragmentProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
- ctx->Const.FragmentProgram.MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
- ctx->Const.FragmentProgram.MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
- ctx->Const.FragmentProgram.MaxUniformComponents = 4 * MAX_UNIFORMS;
- init_natives(&ctx->Const.FragmentProgram);
+ init_program_limits(GL_FRAGMENT_PROGRAM_ARB, &ctx->Const.FragmentProgram);
#endif
ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES;
ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
@@ -932,6 +574,18 @@ _mesa_init_constants(GLcontext *ctx)
ctx->Const.MaxVarying = MAX_VARYING;
#endif
+ /* GL_ARB_framebuffer_object */
+ ctx->Const.MaxSamples = 0;
+
+ /* GL_ARB_sync */
+ ctx->Const.MaxServerWaitTimeout = (GLuint64) ~0;
+
+ /* GL_ATI_envmap_bumpmap */
+ ctx->Const.SupportedBumpUnits = SUPPORTED_ATI_BUMP_UNITS;
+
+ /* GL_EXT_provoking_vertex */
+ ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE;
+
/* sanity checks */
ASSERT(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits,
ctx->Const.MaxTextureCoordUnits));
@@ -942,6 +596,10 @@ _mesa_init_constants(GLcontext *ctx)
ASSERT(MAX_NV_VERTEX_PROGRAM_TEMPS <= MAX_PROGRAM_TEMPS);
ASSERT(MAX_NV_VERTEX_PROGRAM_INPUTS <= VERT_ATTRIB_MAX);
ASSERT(MAX_NV_VERTEX_PROGRAM_OUTPUTS <= VERT_RESULT_MAX);
+
+ /* check that we don't exceed various 32-bit bitfields */
+ ASSERT(VERT_RESULT_MAX <= 32);
+ ASSERT(FRAG_ATTRIB_MAX <= 32);
}
@@ -963,13 +621,18 @@ check_context_limits(GLcontext *ctx)
/* number of coord units cannot be greater than number of image units */
assert(ctx->Const.MaxTextureCoordUnits <= ctx->Const.MaxTextureImageUnits);
- assert(ctx->Const.MaxViewportWidth <= MAX_WIDTH);
- assert(ctx->Const.MaxViewportHeight <= MAX_WIDTH);
+ assert(ctx->Const.MaxTextureLevels <= MAX_TEXTURE_LEVELS);
+ assert(ctx->Const.Max3DTextureLevels <= MAX_3D_TEXTURE_LEVELS);
+ assert(ctx->Const.MaxCubeTextureLevels <= MAX_CUBE_TEXTURE_LEVELS);
+ assert(ctx->Const.MaxTextureRectSize <= MAX_TEXTURE_RECT_SIZE);
/* make sure largest texture image is <= MAX_WIDTH in size */
- assert((1 << (ctx->Const.MaxTextureLevels -1 )) <= MAX_WIDTH);
- assert((1 << (ctx->Const.MaxCubeTextureLevels -1 )) <= MAX_WIDTH);
- assert((1 << (ctx->Const.Max3DTextureLevels -1 )) <= MAX_WIDTH);
+ assert((1 << (ctx->Const.MaxTextureLevels - 1)) <= MAX_WIDTH);
+ assert((1 << (ctx->Const.MaxCubeTextureLevels - 1)) <= MAX_WIDTH);
+ assert((1 << (ctx->Const.Max3DTextureLevels - 1)) <= MAX_WIDTH);
+
+ assert(ctx->Const.MaxViewportWidth <= MAX_WIDTH);
+ assert(ctx->Const.MaxViewportHeight <= MAX_WIDTH);
assert(ctx->Const.MaxDrawBuffers <= MAX_DRAW_BUFFERS);
@@ -997,36 +660,20 @@ init_attrib_groups(GLcontext *ctx)
_mesa_init_extensions( ctx );
/* Attribute Groups */
-#if FEATURE_accum
_mesa_init_accum( ctx );
-#endif
-#if FEATURE_attrib_stack
_mesa_init_attrib( ctx );
-#endif
_mesa_init_buffer_objects( ctx );
_mesa_init_color( ctx );
-#if FEATURE_colortable
_mesa_init_colortables( ctx );
-#endif
_mesa_init_current( ctx );
_mesa_init_depth( ctx );
_mesa_init_debug( ctx );
-#if FEATURE_dlist
_mesa_init_display_list( ctx );
-#endif
-#if FEATURE_evaluators
_mesa_init_eval( ctx );
-#endif
_mesa_init_fbobjects( ctx );
-#if FEATURE_feedback
_mesa_init_feedback( ctx );
-#else
- ctx->RenderMode = GL_RENDER;
-#endif
_mesa_init_fog( ctx );
-#if FEATURE_histogram
_mesa_init_histogram( ctx );
-#endif
_mesa_init_hint( ctx );
_mesa_init_line( ctx );
_mesa_init_lighting( ctx );
@@ -1037,12 +684,11 @@ init_attrib_groups(GLcontext *ctx)
_mesa_init_point( ctx );
_mesa_init_polygon( ctx );
_mesa_init_program( ctx );
-#if FEATURE_ARB_occlusion_query
- _mesa_init_query( ctx );
+ _mesa_init_queryobj( ctx );
+#if FEATURE_ARB_sync
+ _mesa_init_sync( ctx );
#endif
-#if FEATURE_drawpix
_mesa_init_rastpos( ctx );
-#endif
_mesa_init_scissor( ctx );
_mesa_init_shader_state( ctx );
_mesa_init_stencil( ctx );
@@ -1053,16 +699,13 @@ init_attrib_groups(GLcontext *ctx)
if (!_mesa_init_texture( ctx ))
return GL_FALSE;
-#if FEATURE_texture_s3tc
_mesa_init_texture_s3tc( ctx );
-#endif
-#if FEATURE_texture_fxt1
_mesa_init_texture_fxt1( ctx );
-#endif
/* Miscellaneous */
ctx->NewState = _NEW_ALL;
ctx->ErrorValue = (GLenum) GL_NO_ERROR;
+ ctx->varying_vp_inputs = ~0;
return GL_TRUE;
}
@@ -1162,7 +805,9 @@ _mesa_initialize_context(GLcontext *ctx,
const struct dd_function_table *driverFunctions,
void *driverContext)
{
- ASSERT(driverContext);
+ struct gl_shared_state *shared;
+
+ /*ASSERT(driverContext);*/
assert(driverFunctions->NewTextureObject);
assert(driverFunctions->FreeTexImageData);
@@ -1185,20 +830,22 @@ _mesa_initialize_context(GLcontext *ctx,
if (share_list) {
/* share state with another context */
- ctx->Shared = share_list->Shared;
+ shared = share_list->Shared;
}
else {
/* allocate new, unshared state */
- if (!alloc_shared_state( ctx )) {
+ shared = _mesa_alloc_shared_state(ctx);
+ if (!shared)
return GL_FALSE;
- }
}
- _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
- ctx->Shared->RefCount++;
- _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ _glthread_LOCK_MUTEX(shared->Mutex);
+ ctx->Shared = shared;
+ shared->RefCount++;
+ _glthread_UNLOCK_MUTEX(shared->Mutex);
if (!init_attrib_groups( ctx )) {
- free_shared_state(ctx, ctx->Shared);
+ _mesa_free_shared_state(ctx, ctx->Shared);
return GL_FALSE;
}
@@ -1206,7 +853,7 @@ _mesa_initialize_context(GLcontext *ctx,
ctx->Exec = alloc_dispatch_table();
ctx->Save = alloc_dispatch_table();
if (!ctx->Exec || !ctx->Save) {
- free_shared_state(ctx, ctx->Shared);
+ _mesa_free_shared_state(ctx, ctx->Shared);
if (ctx->Exec)
_mesa_free(ctx->Exec);
}
@@ -1214,10 +861,10 @@ _mesa_initialize_context(GLcontext *ctx,
_mesa_init_exec_table(ctx->Exec);
#endif
ctx->CurrentDispatch = ctx->Exec;
-#if FEATURE_dlist
- _mesa_init_dlist_table(ctx->Save);
+
+ _mesa_init_save_table(ctx->Save);
_mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
-#endif
+
/* Neutral tnl module stuff */
_mesa_init_exec_vtxfmt( ctx );
ctx->TnlModule.Current = NULL;
@@ -1253,7 +900,7 @@ _mesa_initialize_context(GLcontext *ctx,
* \param share_list another context to share display lists with or NULL
* \param driverFunctions points to the dd_function_table into which the
* driver has plugged in all its special functions.
- * \param driverCtx points to the device driver's private context state
+ * \param driverContext points to the device driver's private context state
*
* \return pointer to a new __GLcontextRec or NULL if error.
*/
@@ -1266,7 +913,7 @@ _mesa_create_context(const GLvisual *visual,
GLcontext *ctx;
ASSERT(visual);
- ASSERT(driverContext);
+ /*ASSERT(driverContext);*/
ctx = (GLcontext *) _mesa_calloc(sizeof(GLcontext));
if (!ctx)
@@ -1293,6 +940,8 @@ _mesa_create_context(const GLvisual *visual,
void
_mesa_free_context_data( GLcontext *ctx )
{
+ GLint RefCount;
+
if (!_mesa_get_current_context()){
/* No current context, but we may need one in order to delete
* texture objs, etc. So temporarily bind the context now.
@@ -1301,10 +950,10 @@ _mesa_free_context_data( GLcontext *ctx )
}
/* unreference WinSysDraw/Read buffers */
- _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer);
- _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer);
- _mesa_unreference_framebuffer(&ctx->DrawBuffer);
- _mesa_unreference_framebuffer(&ctx->ReadBuffer);
+ _mesa_reference_framebuffer(&ctx->WinSysDrawBuffer, NULL);
+ _mesa_reference_framebuffer(&ctx->WinSysReadBuffer, NULL);
+ _mesa_reference_framebuffer(&ctx->DrawBuffer, NULL);
+ _mesa_reference_framebuffer(&ctx->ReadBuffer, NULL);
_mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
_mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
@@ -1316,25 +965,30 @@ _mesa_free_context_data( GLcontext *ctx )
_mesa_free_attrib_data(ctx);
_mesa_free_lighting_data( ctx );
-#if FEATURE_evaluators
_mesa_free_eval_data( ctx );
-#endif
_mesa_free_texture_data( ctx );
_mesa_free_matrix_data( ctx );
_mesa_free_viewport_data( ctx );
-#if FEATURE_colortable
_mesa_free_colortables_data( ctx );
-#endif
_mesa_free_program_data(ctx);
_mesa_free_shader_state(ctx);
-#if FEATURE_ARB_occlusion_query
- _mesa_free_query_data(ctx);
+ _mesa_free_queryobj_data(ctx);
+#if FEATURE_ARB_sync
+ _mesa_free_sync_data(ctx);
+#endif
+ _mesa_free_varray_data(ctx);
+
+ _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);
+
+#if FEATURE_ARB_pixel_buffer_object
+ _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
#endif
#if FEATURE_ARB_vertex_buffer_object
- _mesa_delete_buffer_object(ctx, ctx->Array.NullBufferObj);
+ _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL);
#endif
- _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);
/* free dispatch tables */
_mesa_free(ctx->Exec);
@@ -1342,12 +996,12 @@ _mesa_free_context_data( GLcontext *ctx )
/* Shared context state (display lists, textures, etc) */
_glthread_LOCK_MUTEX(ctx->Shared->Mutex);
- ctx->Shared->RefCount--;
- assert(ctx->Shared->RefCount >= 0);
+ RefCount = --ctx->Shared->RefCount;
_glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
- if (ctx->Shared->RefCount == 0) {
+ assert(RefCount >= 0);
+ if (RefCount == 0) {
/* free shared state */
- free_shared_state( ctx, ctx->Shared );
+ _mesa_free_shared_state( ctx, ctx->Shared );
}
if (ctx->Extensions.String)
@@ -1571,6 +1225,24 @@ initialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb)
/**
+ * Check if the viewport/scissor size has not yet been initialized.
+ * Initialize the size if the given width and height are non-zero.
+ */
+void
+_mesa_check_init_viewport(GLcontext *ctx, GLuint width, GLuint height)
+{
+ if (!ctx->ViewportInitialized && width > 0 && height > 0) {
+ /* Note: set flag here, before calling _mesa_set_viewport(), to prevent
+ * potential infinite recursion.
+ */
+ ctx->ViewportInitialized = GL_TRUE;
+ _mesa_set_viewport(ctx, 0, 0, width, height);
+ _mesa_set_scissor(ctx, 0, 0, width, height);
+ }
+}
+
+
+/**
* Bind the given context to the given drawBuffer and readBuffer and
* make it the current context for the calling thread.
* We'll render into the drawBuffer and read pixels from the
@@ -1584,7 +1256,7 @@ initialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb)
* \param drawBuffer the drawing framebuffer
* \param readBuffer the reading framebuffer
*/
-void
+GLboolean
_mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
GLframebuffer *readBuffer )
{
@@ -1597,14 +1269,14 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
if (!check_compatible(newCtx, drawBuffer)) {
_mesa_warning(newCtx,
"MakeCurrent: incompatible visuals for context and drawbuffer");
- return;
+ return GL_FALSE;
}
}
if (newCtx && readBuffer && newCtx->WinSysReadBuffer != readBuffer) {
if (!check_compatible(newCtx, readBuffer)) {
_mesa_warning(newCtx,
"MakeCurrent: incompatible visuals for context and readbuffer");
- return;
+ return GL_FALSE;
}
}
@@ -1631,7 +1303,22 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
* or not bound to a user-created FBO.
*/
if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
+ /* KW: merge conflict here, revisit.
+ */
+ /* fix up the fb fields - these will end up wrong otherwise
+ * if the DRIdrawable changes, and everything relies on them.
+ * This is a bit messy (same as needed in _mesa_BindFramebufferEXT)
+ */
+ unsigned int i;
+ GLenum buffers[MAX_DRAW_BUFFERS];
+
_mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer);
+
+ for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) {
+ buffers[i] = newCtx->Color.DrawBuffer[i];
+ }
+
+ _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL);
}
if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) {
_mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
@@ -1672,28 +1359,29 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
ASSERT(drawBuffer->Height > 0);
#endif
- if (newCtx->FirstTimeCurrent) {
- /* set initial viewport and scissor size now */
- _mesa_set_viewport(newCtx, 0, 0,
- drawBuffer->Width, drawBuffer->Height);
- _mesa_set_scissor(newCtx, 0, 0,
- drawBuffer->Width, drawBuffer->Height );
- check_context_limits(newCtx);
+ if (drawBuffer) {
+ _mesa_check_init_viewport(newCtx,
+ drawBuffer->Width, drawBuffer->Height);
}
}
- /* We can use this to help debug user's problems. Tell them to set
- * the MESA_INFO env variable before running their app. Then the
- * first time each context is made current we'll print some useful
- * information.
- */
if (newCtx->FirstTimeCurrent) {
+ check_context_limits(newCtx);
+
+ /* We can use this to help debug user's problems. Tell them to set
+ * the MESA_INFO env variable before running their app. Then the
+ * first time each context is made current we'll print some useful
+ * information.
+ */
if (_mesa_getenv("MESA_INFO")) {
_mesa_print_info();
}
+
newCtx->FirstTimeCurrent = GL_FALSE;
}
}
+
+ return GL_TRUE;
}
@@ -1708,15 +1396,22 @@ _mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
{
if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
struct gl_shared_state *oldSharedState = ctx->Shared;
+ GLint RefCount;
ctx->Shared = ctxToShare->Shared;
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
ctx->Shared->RefCount++;
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
update_default_objects(ctx);
- oldSharedState->RefCount--;
- if (oldSharedState->RefCount == 0) {
- free_shared_state(ctx, oldSharedState);
+ _glthread_LOCK_MUTEX(oldSharedState->Mutex);
+ RefCount = --oldSharedState->RefCount;
+ _glthread_UNLOCK_MUTEX(oldSharedState->Mutex);
+
+ if (RefCount == 0) {
+ _mesa_free_shared_state(ctx, oldSharedState);
}
return GL_TRUE;
@@ -1808,6 +1503,7 @@ _mesa_Finish(void)
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ FLUSH_CURRENT( ctx, 0 );
if (ctx->Driver.Finish) {
ctx->Driver.Finish(ctx);
}
@@ -1825,10 +1521,102 @@ _mesa_Flush(void)
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ FLUSH_CURRENT( ctx, 0 );
if (ctx->Driver.Flush) {
ctx->Driver.Flush(ctx);
}
}
+/**
+ * Set mvp_with_dp4 flag. If a driver has a preference for DP4 over
+ * MUL/MAD, or vice versa, call this function to register that.
+ * Otherwise we default to MUL/MAD.
+ */
+void
+_mesa_set_mvp_with_dp4( GLcontext *ctx,
+ GLboolean flag )
+{
+ ctx->mvp_with_dp4 = flag;
+}
+
+
+
+/**
+ * Prior to drawing anything with glBegin, glDrawArrays, etc. this function
+ * is called to see if it's valid to render. This involves checking that
+ * the current shader is valid and the framebuffer is complete.
+ * If an error is detected it'll be recorded here.
+ * \return GL_TRUE if OK to render, GL_FALSE if not
+ */
+GLboolean
+_mesa_valid_to_render(GLcontext *ctx, const char *where)
+{
+ if (ctx->Shader.CurrentProgram) {
+ /* using shaders */
+ if (!ctx->Shader.CurrentProgram->LinkStatus) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(shader not linked), where");
+ return GL_FALSE;
+ }
+#if 0 /* not normally enabled */
+ {
+ char errMsg[100];
+ if (!_mesa_validate_shader_program(ctx, ctx->Shader.CurrentProgram,
+ errMsg)) {
+ _mesa_warning(ctx, "Shader program %u is invalid: %s",
+ ctx->Shader.CurrentProgram->Name, errMsg);
+ }
+ }
+#endif
+ }
+ else {
+ if (ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(vertex program not valid)", where);
+ return GL_FALSE;
+ }
+ if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(fragment program not valid)", where);
+ return GL_FALSE;
+ }
+ }
+
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "%s(incomplete framebuffer)", where);
+ return GL_FALSE;
+ }
+
+#ifdef DEBUG
+ if (ctx->Shader.Flags & GLSL_LOG) {
+ struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ if (shProg) {
+ if (!shProg->_Used) {
+ /* This is the first time this shader is being used.
+ * Append shader's constants/uniforms to log file.
+ */
+ GLuint i;
+ for (i = 0; i < shProg->NumShaders; i++) {
+ struct gl_shader *sh = shProg->Shaders[i];
+ if (sh->Type == GL_VERTEX_SHADER) {
+ _mesa_append_uniforms_to_file(sh,
+ &shProg->VertexProgram->Base);
+ }
+ else if (sh->Type == GL_FRAGMENT_SHADER) {
+ _mesa_append_uniforms_to_file(sh,
+ &shProg->FragmentProgram->Base);
+ }
+ }
+ shProg->_Used = GL_TRUE;
+ }
+ }
+ }
+#endif
+
+ return GL_TRUE;
+}
+
+
/*@}*/
diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h
index 54f1af911d..5587695fa0 100644
--- a/src/mesa/main/context.h
+++ b/src/mesa/main/context.h
@@ -49,11 +49,13 @@
#define CONTEXT_H
-#include "glapi/glapi.h"
#include "imports.h"
#include "mtypes.h"
+struct _glapi_table;
+
+
/** \name Visual-related functions */
/*@{*/
@@ -129,6 +131,9 @@ _mesa_copy_context(const GLcontext *src, GLcontext *dst, GLuint mask);
extern void
+_mesa_check_init_viewport(GLcontext *ctx, GLuint width, GLuint height);
+
+extern GLboolean
_mesa_make_current( GLcontext *ctx, GLframebuffer *drawBuffer,
GLframebuffer *readBuffer );
@@ -149,6 +154,15 @@ extern struct _glapi_table *
_mesa_get_dispatch(GLcontext *ctx);
+void
+_mesa_set_mvp_with_dp4( GLcontext *ctx,
+ GLboolean flag );
+
+
+extern GLboolean
+_mesa_valid_to_render(GLcontext *ctx, const char *where);
+
+
/** \name Miscellaneous */
/*@{*/
@@ -165,7 +179,6 @@ _mesa_Flush( void );
/*@}*/
-
/**
* \name Macros for flushing buffered rendering commands before state changes,
* checking if inside glBegin/glEnd, etc.
diff --git a/src/mesa/main/convolve.c b/src/mesa/main/convolve.c
index 814c6a0a5a..4bca436095 100644
--- a/src/mesa/main/convolve.c
+++ b/src/mesa/main/convolve.c
@@ -40,6 +40,10 @@
#include "mtypes.h"
#include "pixel.h"
#include "state.h"
+#include "glapi/dispatch.h"
+
+
+#if FEATURE_convolve
/*
@@ -144,39 +148,19 @@ _mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, G
ctx->Convolution1D.Width = width;
ctx->Convolution1D.Height = 1;
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack filter from PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1,
- format, type, image)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glConvolutionFilter1D(invalid PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- ctx->Unpack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glConvolutionFilter1D(PBO is mapped)");
- return;
- }
- image = ADD_POINTERS(buf, image);
- }
- else if (!image) {
+ image = _mesa_map_validate_pbo_source(ctx,
+ 1, &ctx->Unpack, width, 1, 1,
+ format, type, image,
+ "glConvolutionFilter1D");
+ if (!image)
return;
- }
_mesa_unpack_color_span_float(ctx, width, GL_RGBA,
ctx->Convolution1D.Filter,
format, type, image, &ctx->Unpack,
0); /* transferOps */
- if (ctx->Unpack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- ctx->Unpack.BufferObj);
- }
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
_mesa_scale_and_bias_rgba(width,
(GLfloat (*)[4]) ctx->Convolution1D.Filter,
@@ -242,29 +226,12 @@ _mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, G
ctx->Convolution2D.Width = width;
ctx->Convolution2D.Height = height;
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack filter from PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
- format, type, image)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glConvolutionFilter2D(invalid PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- ctx->Unpack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glConvolutionFilter2D(PBO is mapped)");
- return;
- }
- image = ADD_POINTERS(buf, image);
- }
- else if (!image) {
+ image = _mesa_map_validate_pbo_source(ctx,
+ 2, &ctx->Unpack, width, height, 1,
+ format, type, image,
+ "glConvolutionFilter2D");
+ if (!image)
return;
- }
/* Unpack filter image. We always store filters in RGBA format. */
for (i = 0; i < height; i++) {
@@ -276,10 +243,7 @@ _mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, G
0); /* transferOps */
}
- if (ctx->Unpack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- ctx->Unpack.BufferObj);
- }
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
_mesa_scale_and_bias_rgba(width * height,
(GLfloat (*)[4]) ctx->Convolution2D.Filter,
@@ -598,27 +562,12 @@ _mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type,
return;
}
- if (ctx->Pack.BufferObj->Name) {
- /* Pack the filter into a PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(2, &ctx->Pack,
- filter->Width, filter->Height,
- 1, format, type, image)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetConvolutionFilter(invalid PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetConvolutionFilter(PBO is mapped)");
- return;
- }
- image = ADD_POINTERS(image, buf);
- }
+ image = _mesa_map_validate_pbo_dest(ctx, 2, &ctx->Pack,
+ filter->Width, filter->Height, 1,
+ format, type, image,
+ "glGetConvolutionFilter");
+ if (!image)
+ return;
for (row = 0; row < filter->Height; row++) {
GLvoid *dst = _mesa_image_address2d(&ctx->Pack, image, filter->Width,
@@ -629,10 +578,7 @@ _mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type,
format, type, dst, &ctx->Pack, 0x0);
}
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
@@ -802,59 +748,35 @@ _mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type,
filter = &ctx->Separable2D;
- if (ctx->Pack.BufferObj->Name) {
- /* Pack filter into PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(1, &ctx->Pack, filter->Width, 1, 1,
- format, type, row)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetSeparableFilter(invalid PBO access, width)");
- return;
- }
- if (!_mesa_validate_pbo_access(1, &ctx->Pack, filter->Height, 1, 1,
- format, type, column)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetSeparableFilter(invalid PBO access, height)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetSeparableFilter(PBO is mapped)");
- return;
- }
- row = ADD_POINTERS(buf, row);
- column = ADD_POINTERS(buf, column);
- }
-
- /* Row filter */
+ /* Get row filter */
+ row = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack,
+ filter->Width, 1, 1,
+ format, type, row,
+ "glGetConvolutionFilter");
if (row) {
GLvoid *dst = _mesa_image_address1d(&ctx->Pack, row, filter->Width,
format, type, 0);
_mesa_pack_rgba_span_float(ctx, filter->Width,
(GLfloat (*)[4]) filter->Filter,
format, type, dst, &ctx->Pack, 0x0);
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
- /* Column filter */
+ /* get column filter */
+ column = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack,
+ filter->Height, 1, 1,
+ format, type, column,
+ "glGetConvolutionFilter");
if (column) {
GLvoid *dst = _mesa_image_address1d(&ctx->Pack, column, filter->Height,
format, type, 0);
GLfloat (*src)[4] = (GLfloat (*)[4]) (filter->Filter + colStart);
_mesa_pack_rgba_span_float(ctx, filter->Height, src,
format, type, dst, &ctx->Pack, 0x0);
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
(void) span; /* unused at this time */
-
- if (ctx->Pack.BufferObj->Name) {
- /* Pack filter into PBO */
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- ctx->Unpack.BufferObj);
- }
}
@@ -905,41 +827,16 @@ _mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLs
ctx->Separable2D.Width = width;
ctx->Separable2D.Height = height;
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack filter from PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1,
- format, type, row)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glSeparableFilter2D(invalid PBO access, width)");
- return;
- }
- if (!_mesa_validate_pbo_access(1, &ctx->Unpack, height, 1, 1,
- format, type, column)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glSeparableFilter2D(invalid PBO access, height)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- ctx->Unpack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glSeparableFilter2D(PBO is mapped)");
- return;
- }
- row = ADD_POINTERS(buf, row);
- column = ADD_POINTERS(buf, column);
- }
-
/* unpack row filter */
+ row = _mesa_map_validate_pbo_source(ctx, 1, &ctx->Unpack,
+ width, 1, 1,
+ format, type, row,
+ "glSeparableFilter2D");
if (row) {
_mesa_unpack_color_span_float(ctx, width, GL_RGBA,
ctx->Separable2D.Filter,
format, type, row, &ctx->Unpack,
- 0); /* transferOps */
-
+ 0x0); /* transferOps */
_mesa_scale_and_bias_rgba(width,
(GLfloat (*)[4]) ctx->Separable2D.Filter,
ctx->Pixel.ConvolutionFilterScale[2][0],
@@ -950,9 +847,14 @@ _mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLs
ctx->Pixel.ConvolutionFilterBias[2][1],
ctx->Pixel.ConvolutionFilterBias[2][2],
ctx->Pixel.ConvolutionFilterBias[2][3]);
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
}
/* unpack column filter */
+ column = _mesa_map_validate_pbo_source(ctx, 1, &ctx->Unpack,
+ height, 1, 1,
+ format, type, column,
+ "glSeparableFilter2D");
if (column) {
_mesa_unpack_color_span_float(ctx, height, GL_RGBA,
&ctx->Separable2D.Filter[colStart],
@@ -969,9 +871,10 @@ _mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLs
ctx->Pixel.ConvolutionFilterBias[2][1],
ctx->Pixel.ConvolutionFilterBias[2][2],
ctx->Pixel.ConvolutionFilterBias[2][3]);
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
}
- if (ctx->Unpack.BufferObj->Name) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
ctx->Unpack.BufferObj);
}
@@ -1526,3 +1429,25 @@ _mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions,
*height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
}
}
+
+
+void
+_mesa_init_convolve_dispatch(struct _glapi_table *disp)
+{
+ SET_ConvolutionFilter1D(disp, _mesa_ConvolutionFilter1D);
+ SET_ConvolutionFilter2D(disp, _mesa_ConvolutionFilter2D);
+ SET_ConvolutionParameterf(disp, _mesa_ConvolutionParameterf);
+ SET_ConvolutionParameterfv(disp, _mesa_ConvolutionParameterfv);
+ SET_ConvolutionParameteri(disp, _mesa_ConvolutionParameteri);
+ SET_ConvolutionParameteriv(disp, _mesa_ConvolutionParameteriv);
+ SET_CopyConvolutionFilter1D(disp, _mesa_CopyConvolutionFilter1D);
+ SET_CopyConvolutionFilter2D(disp, _mesa_CopyConvolutionFilter2D);
+ SET_GetConvolutionFilter(disp, _mesa_GetConvolutionFilter);
+ SET_GetConvolutionParameterfv(disp, _mesa_GetConvolutionParameterfv);
+ SET_GetConvolutionParameteriv(disp, _mesa_GetConvolutionParameteriv);
+ SET_SeparableFilter2D(disp, _mesa_SeparableFilter2D);
+ SET_GetSeparableFilter(disp, _mesa_GetSeparableFilter);
+}
+
+
+#endif /* FEATURE_convolve */
diff --git a/src/mesa/main/convolve.h b/src/mesa/main/convolve.h
index 4505cdae01..565a51ef8f 100644
--- a/src/mesa/main/convolve.h
+++ b/src/mesa/main/convolve.h
@@ -28,10 +28,17 @@
#define CONVOLVE_H
-#include "mtypes.h"
+#include "main/mtypes.h"
-#if _HAVE_FULL_GL
+#if FEATURE_convolve
+
+#define _MESA_INIT_CONVOLVE_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->CopyConvolutionFilter1D = impl ## CopyConvolutionFilter1D; \
+ (driver)->CopyConvolutionFilter2D = impl ## CopyConvolutionFilter2D; \
+ } while (0)
+
extern void GLAPIENTRY
_mesa_ConvolutionFilter1D(GLenum target, GLenum internalformat, GLsizei width,
GLenum format, GLenum type, const GLvoid *image);
@@ -83,32 +90,66 @@ _mesa_SeparableFilter2D(GLenum target, GLenum internalformat,
const GLvoid *row, const GLvoid *column);
-
extern void
_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width,
const GLfloat *srcImage, GLfloat *dstImage);
-
extern void
_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height,
const GLfloat *srcImage, GLfloat *dstImage);
-
extern void
_mesa_convolve_sep_image(const GLcontext *ctx,
GLsizei *width, GLsizei *height,
const GLfloat *srcImage, GLfloat *dstImage);
-
extern void
_mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions,
GLsizei *width, GLsizei *height);
-#else
-#define _mesa_adjust_image_for_convolution(c, d, w, h) ((void)0)
-#define _mesa_convolve_1d_image(c,w,s,d) ((void)0)
-#define _mesa_convolve_2d_image(c,w,h,s,d) ((void)0)
-#define _mesa_convolve_sep_image(c,w,h,s,d) ((void)0)
-#endif
+extern void
+_mesa_init_convolve_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_convolve */
+
+#define _MESA_INIT_CONVOLVE_FUNCTIONS(driver, impl) do { } while (0)
+
+static INLINE void
+_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width,
+ const GLfloat *srcImage, GLfloat *dstImage)
+{
+ *width = 0;
+}
+
+static INLINE void
+_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height,
+ const GLfloat *srcImage, GLfloat *dstImage)
+{
+ *width = 0;
+ *height = 0;
+}
+
+
+static INLINE void
+_mesa_convolve_sep_image(const GLcontext *ctx,
+ GLsizei *width, GLsizei *height,
+ const GLfloat *srcImage, GLfloat *dstImage)
+{
+ *width = 0;
+ *height = 0;
+}
+
+static INLINE void
+_mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions,
+ GLsizei *width, GLsizei *height)
+{
+}
+
+static INLINE void
+_mesa_init_convolve_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_convolve */
-#endif
+#endif /* CONVOLVE_H */
diff --git a/src/mesa/main/cpuinfo.c b/src/mesa/main/cpuinfo.c
new file mode 100644
index 0000000000..b4bfb40eb1
--- /dev/null
+++ b/src/mesa/main/cpuinfo.c
@@ -0,0 +1,109 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "main/imports.h"
+#include "main/cpuinfo.h"
+
+
+/**
+ * This function should be called before the various "cpu_has_foo" macros
+ * are used.
+ */
+void
+_mesa_get_cpu_features(void)
+{
+#ifdef USE_X86_ASM
+ _mesa_get_x86_features();
+#endif
+}
+
+
+/**
+ * Return a string describing the CPU architexture and extensions that
+ * Mesa is using (such as SSE or Altivec).
+ * \return information string, free it with _mesa_free()
+ */
+char *
+_mesa_get_cpu_string(void)
+{
+#define MAX_STRING 50
+ char *buffer;
+
+ buffer = (char *) _mesa_malloc(MAX_STRING);
+ if (!buffer)
+ return NULL;
+
+ buffer[0] = 0;
+
+#ifdef USE_X86_ASM
+
+ if (_mesa_x86_cpu_features) {
+ strcat(buffer, "x86");
+ }
+
+# ifdef USE_MMX_ASM
+ if (cpu_has_mmx) {
+ strcat(buffer, (cpu_has_mmxext) ? "/MMX+" : "/MMX");
+ }
+# endif
+# ifdef USE_3DNOW_ASM
+ if (cpu_has_3dnow) {
+ strcat(buffer, (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!");
+ }
+# endif
+# ifdef USE_SSE_ASM
+ if (cpu_has_xmm) {
+ strcat(buffer, (cpu_has_xmm2) ? "/SSE2" : "/SSE");
+ }
+# endif
+
+#elif defined(USE_SPARC_ASM)
+
+ strcat(buffer, "SPARC");
+
+#elif defined(USE_PPC_ASM)
+
+ if (_mesa_ppc_cpu_features) {
+ strcat(buffer, (cpu_has_64) ? "PowerPC 64" : "PowerPC");
+ }
+
+# ifdef USE_VMX_ASM
+
+ if (cpu_has_vmx) {
+ strcat(buffer, "/Altivec");
+ }
+
+# endif
+
+ if (! cpu_has_fpu) {
+ strcat(buffer, "/No FPU");
+ }
+
+#endif
+
+ assert(_mesa_strlen(buffer) < MAX_STRING);
+
+ return buffer;
+}
diff --git a/src/mesa/math/mathmod.h b/src/mesa/main/cpuinfo.h
index 6fbaaea94b..c41a90b075 100644
--- a/src/mesa/math/mathmod.h
+++ b/src/mesa/main/cpuinfo.h
@@ -1,9 +1,8 @@
-
/*
* Mesa 3-D graphics library
- * Version: 3.5
+ * Version: 7.5
*
- * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -24,18 +23,25 @@
*/
-/**
- * \mainpage Mesa Math Module
- *
- * This module contains math-related utility functions for transforming
- * vertices, translating arrays of numbers from one data type to another,
- * evaluating curved surfaces, etc.
- */
-
+#ifndef CPUINFO_H
+#define CPUINFO_H
-#ifndef _MESA_MATH_H_
-#define _MESA_MATH_H_
-extern void _math_init( void );
+#if defined(USE_X86_ASM)
+#include "x86/common_x86_asm.h"
+#endif
+#if defined(USE_PPC_ASM)
+#include "ppc/common_ppc_features.h"
#endif
+
+
+extern void
+_mesa_get_cpu_features(void);
+
+
+extern char *
+_mesa_get_cpu_string(void);
+
+
+#endif /* CPUINFO_H */
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index ddb38030bf..307ecd3d8b 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -34,7 +34,23 @@
/* THIS FILE ONLY INCLUDED BY mtypes.h !!!!! */
struct gl_pixelstore_attrib;
-struct mesa_display_list;
+struct gl_display_list;
+
+#if FEATURE_ARB_vertex_buffer_object
+/* Modifies GL_MAP_UNSYNCHRONIZED_BIT to allow driver to fail (return
+ * NULL) if buffer is unavailable for immediate mapping.
+ *
+ * Does GL_MAP_INVALIDATE_RANGE_BIT do this? It seems so, but it
+ * would require more book-keeping in the driver than seems necessary
+ * at this point.
+ *
+ * Does GL_MAP_INVALDIATE_BUFFER_BIT do this? Not really -- we don't
+ * want to provoke the driver to throw away the old storage, we will
+ * respect the contents of already referenced data.
+ */
+#define MESA_MAP_NOWAIT_BIT 0x0040
+#endif
+
/**
* Device driver function table.
@@ -586,9 +602,6 @@ struct dd_function_table {
/** Notify driver that a program string has been specified. */
void (*ProgramStringNotify)(GLcontext *ctx, GLenum target,
struct gl_program *prog);
- /** Get value of a program register during program execution. */
- void (*GetProgramRegister)(GLcontext *ctx, enum register_file file,
- GLuint index, GLfloat val[4]);
/** Query if program can be loaded onto hardware */
GLboolean (*IsProgramNative)(GLcontext *ctx, GLenum target,
@@ -753,6 +766,8 @@ struct dd_function_table {
/** Return the value or values of a selected parameter */
GLboolean (*GetIntegerv)(GLcontext *ctx, GLenum pname, GLint *result);
/** Return the value or values of a selected parameter */
+ GLboolean (*GetInteger64v)(GLcontext *ctx, GLenum pname, GLint64 *result);
+ /** Return the value or values of a selected parameter */
GLboolean (*GetPointerv)(GLcontext *ctx, GLenum pname, GLvoid **result);
/*@}*/
@@ -770,9 +785,9 @@ struct dd_function_table {
void (*DeleteBuffer)( GLcontext *ctx, struct gl_buffer_object *obj );
- void (*BufferData)( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
- const GLvoid *data, GLenum usage,
- struct gl_buffer_object *obj );
+ GLboolean (*BufferData)( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
+ const GLvoid *data, GLenum usage,
+ struct gl_buffer_object *obj );
void (*BufferSubData)( GLcontext *ctx, GLenum target, GLintptrARB offset,
GLsizeiptrARB size, const GLvoid *data,
@@ -785,6 +800,22 @@ struct dd_function_table {
void * (*MapBuffer)( GLcontext *ctx, GLenum target, GLenum access,
struct gl_buffer_object *obj );
+ void (*CopyBufferSubData)( GLcontext *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size );
+
+ /* May return NULL if MESA_MAP_NOWAIT_BIT is set in access:
+ */
+ void * (*MapBufferRange)( GLcontext *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length, GLbitfield access,
+ struct gl_buffer_object *obj);
+
+ void (*FlushMappedBufferRange) (GLcontext *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length,
+ struct gl_buffer_object *obj);
+
GLboolean (*UnmapBuffer)( GLcontext *ctx, GLenum target,
struct gl_buffer_object *obj );
/*@}*/
@@ -808,6 +839,8 @@ struct dd_function_table {
struct gl_renderbuffer_attachment *att);
void (*FinishRenderTexture)(GLcontext *ctx,
struct gl_renderbuffer_attachment *att);
+ void (*ValidateFramebuffer)(GLcontext *ctx,
+ struct gl_framebuffer *fb);
/*@}*/
#endif
#if FEATURE_EXT_framebuffer_blit
@@ -886,7 +919,7 @@ struct dd_function_table {
void (*Uniform)(GLcontext *ctx, GLint location, GLsizei count,
const GLvoid *values, GLenum type);
void (*UniformMatrix)(GLcontext *ctx, GLint cols, GLint rows,
- GLenum matrixType, GLint location, GLsizei count,
+ GLint location, GLsizei count,
GLboolean transpose, const GLfloat *values);
void (*UseProgram)(GLcontext *ctx, GLuint program);
void (*ValidateProgram)(GLcontext *ctx, GLuint program);
@@ -952,6 +985,12 @@ struct dd_function_table {
GLuint NeedFlush;
GLuint SaveNeedFlush;
+
+ /* Called prior to any of the GLvertexformat functions being
+ * called. Paired with Driver.FlushVertices().
+ */
+ void (*BeginVertices)( GLcontext *ctx );
+
/**
* If inside glBegin()/glEnd(), it should ASSERT(0). Otherwise, if
* FLUSH_STORED_VERTICES bit in \p flags is set flushes any buffered
@@ -997,7 +1036,7 @@ struct dd_function_table {
* Notify the T&L component before and after calling a display list.
*/
void (*BeginCallList)( GLcontext *ctx,
- struct mesa_display_list *dlist );
+ struct gl_display_list *dlist );
/**
* Called by glEndCallList().
*
@@ -1005,6 +1044,45 @@ struct dd_function_table {
*/
void (*EndCallList)( GLcontext *ctx );
+
+#if FEATURE_ARB_sync
+ /**
+ * \name GL_ARB_sync interfaces
+ */
+ /*@{*/
+ struct gl_sync_object * (*NewSyncObject)(GLcontext *, GLenum);
+ void (*FenceSync)(GLcontext *, struct gl_sync_object *, GLenum, GLbitfield);
+ void (*DeleteSyncObject)(GLcontext *, struct gl_sync_object *);
+ void (*CheckSync)(GLcontext *, struct gl_sync_object *);
+ void (*ClientWaitSync)(GLcontext *, struct gl_sync_object *,
+ GLbitfield, GLuint64);
+ void (*ServerWaitSync)(GLcontext *, struct gl_sync_object *,
+ GLbitfield, GLuint64);
+ /*@}*/
+#endif
+
+#if FEATURE_OES_draw_texture
+ /**
+ * \name GL_OES_draw_texture interface
+ */
+ /*@{*/
+ void (*DrawTex)(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat width, GLfloat height);
+ /*@}*/
+#endif
+#if FEATURE_OES_EGL_image
+ /**
+ * \name GL_OES_EGL_image interface
+ */
+ /*@{*/
+ void (*EGLImageTargetRenderbufferStorage)(GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLvoid *image);
+ void (*EGLImageTargetTexture2D)(GLcontext *ctx,
+ struct gl_texture_object *texObj,
+ GLvoid *image);
+ /*@}*/
+#endif
};
@@ -1113,6 +1191,25 @@ typedef struct {
void (GLAPIENTRYP DrawRangeElements)( GLenum mode, GLuint start,
GLuint end, GLsizei count,
GLenum type, const GLvoid *indices );
+ void (GLAPIENTRYP MultiDrawElementsEXT)( GLenum mode, const GLsizei *count,
+ GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount);
+ void (GLAPIENTRYP DrawElementsBaseVertex)( GLenum mode, GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex );
+ void (GLAPIENTRYP DrawRangeElementsBaseVertex)( GLenum mode, GLuint start,
+ GLuint end, GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex);
+ void (GLAPIENTRYP MultiDrawElementsBaseVertex)( GLenum mode,
+ const GLsizei *count,
+ GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount,
+ const GLint *basevertex);
/*@}*/
/**
diff --git a/src/mesa/main/debug.c b/src/mesa/main/debug.c
index 77fef32558..8492c8561d 100644
--- a/src/mesa/main/debug.c
+++ b/src/mesa/main/debug.c
@@ -3,6 +3,7 @@
* Version: 6.5
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -23,10 +24,19 @@
*/
#include "mtypes.h"
+#include "attrib.h"
+#include "colormac.h"
#include "context.h"
+#include "hash.h"
#include "imports.h"
#include "debug.h"
#include "get.h"
+#include "pixelstore.h"
+#include "readpix.h"
+#include "texgetimage.h"
+#include "texobj.h"
+#include "texformat.h"
+
/**
* Primitive names
@@ -164,9 +174,7 @@ static void add_debug_flags( const char *debug )
{ "api", VERBOSE_API },
{ "list", VERBOSE_DISPLAY_LIST },
{ "lighting", VERBOSE_LIGHTING },
- { "disassem", VERBOSE_DISASSEM },
- { "glsl", VERBOSE_GLSL }, /* report GLSL compile/link errors */
- { "glsl_dump", VERBOSE_GLSL_DUMP } /* print shader GPU instructions */
+ { "disassem", VERBOSE_DISASSEM }
};
GLuint i;
@@ -221,3 +229,212 @@ _mesa_init_debug( GLcontext *ctx )
add_debug_flags(c);
}
+
+/*
+ * Write ppm file
+ */
+static void
+write_ppm(const char *filename, const GLubyte *buffer, int width, int height,
+ int comps, int rcomp, int gcomp, int bcomp, GLboolean invert)
+{
+ FILE *f = fopen( filename, "w" );
+ if (f) {
+ int x, y;
+ const GLubyte *ptr = buffer;
+ fprintf(f,"P6\n");
+ fprintf(f,"# ppm-file created by osdemo.c\n");
+ fprintf(f,"%i %i\n", width,height);
+ fprintf(f,"255\n");
+ fclose(f);
+ f = fopen( filename, "ab" ); /* reopen in binary append mode */
+ for (y=0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ int yy = invert ? (height - 1 - y) : y;
+ int i = (yy * width + x) * comps;
+ fputc(ptr[i+rcomp], f); /* write red */
+ fputc(ptr[i+gcomp], f); /* write green */
+ fputc(ptr[i+bcomp], f); /* write blue */
+ }
+ }
+ fclose(f);
+ }
+}
+
+
+/**
+ * Write level[0] image to a ppm file.
+ */
+static void
+write_texture_image(struct gl_texture_object *texObj, GLuint face, GLuint level)
+{
+ struct gl_texture_image *img = texObj->Image[face][level];
+ if (img) {
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_pixelstore_attrib store;
+ GLubyte *buffer;
+ char s[100];
+
+ buffer = (GLubyte *) _mesa_malloc(img->Width * img->Height
+ * img->Depth * 4);
+
+ store = ctx->Pack; /* save */
+ ctx->Pack = ctx->DefaultPacking;
+
+ ctx->Driver.GetTexImage(ctx, texObj->Target, level,
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ buffer, texObj, img);
+
+ /* make filename */
+ _mesa_sprintf(s, "/tmp/teximage%u.ppm", texObj->Name);
+
+ _mesa_printf(" Writing image level %u to %s\n", level, s);
+ write_ppm(s, buffer, img->Width, img->Height, 4, 0, 1, 2, GL_FALSE);
+
+ ctx->Pack = store; /* restore */
+
+ _mesa_free(buffer);
+ }
+}
+
+
+static GLboolean DumpImages;
+
+
+static void
+dump_texture_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_texture_object *texObj = (struct gl_texture_object *) data;
+ int i;
+ GLboolean written = GL_FALSE;
+ (void) userData;
+
+ _mesa_printf("Texture %u\n", texObj->Name);
+ _mesa_printf(" Target 0x%x\n", texObj->Target);
+ for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
+ struct gl_texture_image *texImg = texObj->Image[0][i];
+ if (texImg) {
+ _mesa_printf(" Image %u: %d x %d x %d, format %u at %p\n", i,
+ texImg->Width, texImg->Height, texImg->Depth,
+ texImg->TexFormat->MesaFormat, texImg->Data);
+ if (DumpImages && !written) {
+ GLuint face = 0;
+ write_texture_image(texObj, face, i);
+ written = GL_TRUE;
+ }
+ }
+ }
+}
+
+
+/**
+ * Print basic info about all texture objext to stdout.
+ * If dumpImages is true, write PPM of level[0] image to a file.
+ */
+void
+_mesa_dump_textures(GLboolean dumpImages)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DumpImages = dumpImages;
+ _mesa_HashWalk(ctx->Shared->TexObjects, dump_texture_cb, ctx);
+}
+
+
+void
+_mesa_dump_color_buffer(const char *filename)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint w = ctx->DrawBuffer->Width;
+ const GLuint h = ctx->DrawBuffer->Height;
+ GLubyte *buf;
+
+ buf = (GLubyte *) _mesa_malloc(w * h * 4);
+
+ _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
+ _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
+
+ _mesa_ReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+
+ _mesa_printf("ReadBuffer %p 0x%x DrawBuffer %p 0x%x\n",
+ ctx->ReadBuffer->_ColorReadBuffer,
+ ctx->ReadBuffer->ColorReadBuffer,
+ ctx->DrawBuffer->_ColorDrawBuffers[0],
+ ctx->DrawBuffer->ColorDrawBuffer[0]);
+ _mesa_printf("Writing %d x %d color buffer to %s\n", w, h, filename);
+ write_ppm(filename, buf, w, h, 4, 0, 1, 2, GL_TRUE);
+
+ _mesa_PopClientAttrib();
+
+ _mesa_free(buf);
+}
+
+
+void
+_mesa_dump_depth_buffer(const char *filename)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint w = ctx->DrawBuffer->Width;
+ const GLuint h = ctx->DrawBuffer->Height;
+ GLuint *buf;
+ GLubyte *buf2;
+ GLuint i;
+
+ buf = (GLuint *) _mesa_malloc(w * h * 4); /* 4 bpp */
+ buf2 = (GLubyte *) _mesa_malloc(w * h * 3); /* 3 bpp */
+
+ _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
+ _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
+
+ _mesa_ReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buf);
+
+ /* spread 24 bits of Z across R, G, B */
+ for (i = 0; i < w * h; i++) {
+ buf2[i*3+0] = (buf[i] >> 24) & 0xff;
+ buf2[i*3+1] = (buf[i] >> 16) & 0xff;
+ buf2[i*3+2] = (buf[i] >> 8) & 0xff;
+ }
+
+ _mesa_printf("Writing %d x %d depth buffer to %s\n", w, h, filename);
+ write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
+
+ _mesa_PopClientAttrib();
+
+ _mesa_free(buf);
+ _mesa_free(buf2);
+}
+
+
+void
+_mesa_dump_stencil_buffer(const char *filename)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint w = ctx->DrawBuffer->Width;
+ const GLuint h = ctx->DrawBuffer->Height;
+ GLubyte *buf;
+ GLubyte *buf2;
+ GLuint i;
+
+ buf = (GLubyte *) _mesa_malloc(w * h); /* 1 bpp */
+ buf2 = (GLubyte *) _mesa_malloc(w * h * 3); /* 3 bpp */
+
+ _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
+ _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
+
+ _mesa_ReadPixels(0, 0, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf);
+
+ for (i = 0; i < w * h; i++) {
+ buf2[i*3+0] = buf[i];
+ buf2[i*3+1] = (buf[i] & 127) * 2;
+ buf2[i*3+2] = (buf[i] - 128) * 2;
+ }
+
+ _mesa_printf("Writing %d x %d stencil buffer to %s\n", w, h, filename);
+ write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
+
+ _mesa_PopClientAttrib();
+
+ _mesa_free(buf);
+ _mesa_free(buf2);
+}
diff --git a/src/mesa/main/debug.h b/src/mesa/main/debug.h
index 94d99c384b..bb384c4324 100644
--- a/src/mesa/main/debug.h
+++ b/src/mesa/main/debug.h
@@ -57,4 +57,16 @@ extern void _mesa_init_debug( GLcontext *ctx );
#endif
+extern void
+_mesa_dump_textures(GLboolean dumpImages);
+
+extern void
+_mesa_dump_color_buffer(const char *filename);
+
+extern void
+_mesa_dump_depth_buffer(const char *filename);
+
+extern void
+_mesa_dump_stencil_buffer(const char *filename);
+
#endif
diff --git a/src/mesa/main/depthstencil.c b/src/mesa/main/depthstencil.c
index 9d208e2997..7be2aacaf2 100644
--- a/src/mesa/main/depthstencil.c
+++ b/src/mesa/main/depthstencil.c
@@ -62,15 +62,9 @@ nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
static void
delete_wrapper(struct gl_renderbuffer *rb)
{
- struct gl_renderbuffer *dsrb = rb->Wrapped;
- ASSERT(dsrb);
ASSERT(rb->_ActualFormat == GL_DEPTH_COMPONENT24 ||
rb->_ActualFormat == GL_STENCIL_INDEX8_EXT);
- /* decrement refcount on the wrapped buffer and delete it if necessary */
- dsrb->RefCount--;
- if (dsrb->RefCount <= 0) {
- dsrb->Delete(dsrb);
- }
+ _mesa_reference_renderbuffer(&rb->Wrapped, NULL);
_mesa_free(rb);
}
diff --git a/src/mesa/main/dispatch.c b/src/mesa/main/dispatch.c
index 34127cb248..bf1a013789 100644
--- a/src/mesa/main/dispatch.c
+++ b/src/mesa/main/dispatch.c
@@ -40,6 +40,7 @@
#ifndef GLX_USE_APPLEGL
#include "main/glheader.h"
+#include "main/compiler.h"
#include "glapi/glapi.h"
#include "glapi/glapitable.h"
#include "glapi/glthread.h"
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index d3aee196c7..f793b60284 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -33,6 +33,7 @@
#include "api_arrayelt.h"
#include "api_loopback.h"
#include "config.h"
+#include "mfeatures.h"
#include "attrib.h"
#include "blend.h"
#include "buffers.h"
@@ -72,6 +73,7 @@
#include "texstate.h"
#include "mtypes.h"
#include "varray.h"
+#include "vtxfmt.h"
#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
#include "shader/arbprogram.h"
#include "shader/program.h"
@@ -85,7 +87,6 @@
#endif
#include "math/m_matrix.h"
-#include "math/m_xform.h"
#include "glapi/dispatch.h"
@@ -320,6 +321,8 @@ typedef enum
/* GL_ARB_draw_buffers */
OPCODE_DRAW_BUFFERS_ARB,
/* GL_ATI_fragment_shader */
+ OPCODE_TEX_BUMP_PARAMETER_ATI,
+ /* GL_ATI_fragment_shader */
OPCODE_BIND_FRAGMENT_SHADER_ATI,
OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI,
/* OpenGL 2.0 */
@@ -350,6 +353,9 @@ typedef enum
OPCODE_EVAL_P1,
OPCODE_EVAL_P2,
+ /* GL_EXT_provoking_vertex */
+ OPCODE_PROVOKING_VERTEX,
+
/* The following three are meta instructions */
OPCODE_ERROR, /* raise compiled-in error */
OPCODE_CONTINUE,
@@ -370,7 +376,7 @@ typedef enum
* contiguous nodes in memory.
* Each node is the union of a variety of data types.
*/
-union node
+union gl_dlist_node
{
OpCode opcode;
GLboolean b;
@@ -387,6 +393,9 @@ union node
};
+typedef union gl_dlist_node Node;
+
+
/**
* How many nodes to allocate at a time.
*
@@ -402,6 +411,10 @@ union node
*/
static GLuint InstSize[OPCODE_END_OF_LIST + 1];
+
+#if FEATURE_dlist
+
+
void mesa_print_display_list(GLuint list);
@@ -414,13 +427,13 @@ void mesa_print_display_list(GLuint list);
* Make an empty display list. This is used by glGenLists() to
* reserve display list IDs.
*/
-static struct mesa_display_list *
-make_list(GLuint list, GLuint count)
+static struct gl_display_list *
+make_list(GLuint name, GLuint count)
{
- struct mesa_display_list *dlist = CALLOC_STRUCT(mesa_display_list);
- dlist->id = list;
- dlist->node = (Node *) _mesa_malloc(sizeof(Node) * count);
- dlist->node[0].opcode = OPCODE_END_OF_LIST;
+ struct gl_display_list *dlist = CALLOC_STRUCT(gl_display_list);
+ dlist->Name = name;
+ dlist->Head = (Node *) _mesa_malloc(sizeof(Node) * count);
+ dlist->Head[0].opcode = OPCODE_END_OF_LIST;
return dlist;
}
@@ -428,10 +441,10 @@ make_list(GLuint list, GLuint count)
/**
* Lookup function to just encapsulate casting.
*/
-static INLINE struct mesa_display_list *
+static INLINE struct gl_display_list *
lookup_list(GLcontext *ctx, GLuint list)
{
- return (struct mesa_display_list *)
+ return (struct gl_display_list *)
_mesa_HashLookup(ctx->Shared->DisplayList, list);
}
@@ -442,12 +455,12 @@ lookup_list(GLcontext *ctx, GLuint list)
* \param dlist - display list pointer
*/
void
-_mesa_delete_list(GLcontext *ctx, struct mesa_display_list *dlist)
+_mesa_delete_list(GLcontext *ctx, struct gl_display_list *dlist)
{
Node *n, *block;
GLboolean done;
- n = block = dlist->node;
+ n = block = dlist->Head;
done = block ? GL_FALSE : GL_TRUE;
while (!done) {
@@ -596,7 +609,7 @@ _mesa_delete_list(GLcontext *ctx, struct mesa_display_list *dlist)
static void
destroy_list(GLcontext *ctx, GLuint list)
{
- struct mesa_display_list *dlist;
+ struct gl_display_list *dlist;
if (list == 0)
return;
@@ -675,24 +688,48 @@ translate_id(GLsizei n, GLenum type, const GLvoid * list)
/**
* Wrapper for _mesa_unpack_image() that handles pixel buffer objects.
- * \todo This won't suffice when the PBO is really in VRAM/GPU memory.
+ * If we run out of memory, GL_OUT_OF_MEMORY will be recorded.
*/
static GLvoid *
-unpack_image(GLuint dimensions, GLsizei width, GLsizei height, GLsizei depth,
+unpack_image(GLcontext *ctx, GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const GLvoid * pixels,
const struct gl_pixelstore_attrib *unpack)
{
- if (unpack->BufferObj->Name == 0) {
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
/* no PBO */
- return _mesa_unpack_image(dimensions, width, height, depth, format,
- type, pixels, unpack);
+ GLvoid *image = _mesa_unpack_image(dimensions, width, height, depth,
+ format, type, pixels, unpack);
+ if (pixels && !image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction");
+ }
+ return image;
}
- else
- if (_mesa_validate_pbo_access
- (dimensions, unpack, width, height, depth, format, type, pixels)) {
- const GLubyte *src = ADD_POINTERS(unpack->BufferObj->Data, pixels);
- return _mesa_unpack_image(dimensions, width, height, depth, format,
- type, src, unpack);
+ else if (_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
+ format, type, pixels)) {
+ const GLubyte *map, *src;
+ GLvoid *image;
+
+ map = (GLubyte *)
+ ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB, unpack->BufferObj);
+ if (!map) {
+ /* unable to map src buffer! */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "unable to map PBO");
+ return NULL;
+ }
+
+ src = ADD_POINTERS(map, pixels);
+ image = _mesa_unpack_image(dimensions, width, height, depth,
+ format, type, src, unpack);
+
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ unpack->BufferObj);
+
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction");
+ }
+ return image;
}
/* bad access! */
return NULL;
@@ -702,7 +739,7 @@ unpack_image(GLuint dimensions, GLsizei width, GLsizei height, GLsizei depth,
/**
* Allocate space for a display list instruction.
* \param opcode the instruction opcode (OPCODE_* value)
- * \param size instruction size in bytes, not counting opcode.
+ * \param bytes instruction size in bytes, not counting opcode.
* \return pointer to the usable data area (not including the internal
* opcode).
*/
@@ -850,7 +887,6 @@ save_Bitmap(GLsizei width, GLsizei height,
GLfloat xmove, GLfloat ymove, const GLubyte * pixels)
{
GET_CURRENT_CONTEXT(ctx);
- GLvoid *image = _mesa_unpack_bitmap(width, height, pixels, &ctx->Unpack);
Node *n;
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
n = ALLOC_INSTRUCTION(ctx, OPCODE_BITMAP, 7);
@@ -861,10 +897,7 @@ save_Bitmap(GLsizei width, GLsizei height,
n[4].f = yorig;
n[5].f = xmove;
n[6].f = ymove;
- n[7].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[7].data = _mesa_unpack_bitmap(width, height, pixels, &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_Bitmap(ctx->Exec, (width, height,
@@ -952,6 +985,20 @@ save_BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
}
}
+static void invalidate_saved_current_state( GLcontext *ctx )
+{
+ GLint i;
+
+ for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ ctx->ListState.ActiveAttribSize[i] = 0;
+
+ for (i = 0; i < MAT_ATTRIB_MAX; i++)
+ ctx->ListState.ActiveMaterialSize[i] = 0;
+
+ memset(&ctx->ListState.Current, 0, sizeof ctx->ListState.Current);
+
+ ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+}
void GLAPIENTRY
_mesa_save_CallList(GLuint list)
@@ -965,18 +1012,19 @@ _mesa_save_CallList(GLuint list)
n[1].ui = list;
}
- /* After this, we don't know what begin/end state we're in:
+ /* After this, we don't know what state we're in. Invalidate all
+ * cached information previously gathered:
*/
- ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+ invalidate_saved_current_state( ctx );
if (ctx->ExecuteFlag) {
- CALL_CallList(ctx->Exec, (list));
+ _mesa_CallList(list);
}
}
void GLAPIENTRY
-_mesa_save_CallLists(GLsizei n, GLenum type, const GLvoid * lists)
+_mesa_save_CallLists(GLsizei num, GLenum type, const GLvoid * lists)
{
GET_CURRENT_CONTEXT(ctx);
GLint i;
@@ -1001,7 +1049,7 @@ _mesa_save_CallLists(GLsizei n, GLenum type, const GLvoid * lists)
typeErrorFlag = GL_TRUE;
}
- for (i = 0; i < n; i++) {
+ for (i = 0; i < num; i++) {
GLint list = translate_id(i, type, lists);
Node *n = ALLOC_INSTRUCTION(ctx, OPCODE_CALL_LIST_OFFSET, 2);
if (n) {
@@ -1010,12 +1058,13 @@ _mesa_save_CallLists(GLsizei n, GLenum type, const GLvoid * lists)
}
}
- /* After this, we don't know what begin/end state we're in:
+ /* After this, we don't know what state we're in. Invalidate all
+ * cached information previously gathered:
*/
- ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+ invalidate_saved_current_state( ctx );
if (ctx->ExecuteFlag) {
- CALL_CallLists(ctx->Exec, (n, type, lists));
+ CALL_CallLists(ctx->Exec, (num, type, lists));
}
}
@@ -1193,8 +1242,6 @@ save_ColorTable(GLenum target, GLenum internalFormat,
format, type, table));
}
else {
- GLvoid *image = unpack_image(1, width, 1, 1, format, type, table,
- &ctx->Unpack);
Node *n;
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
n = ALLOC_INSTRUCTION(ctx, OPCODE_COLOR_TABLE, 6);
@@ -1204,10 +1251,8 @@ save_ColorTable(GLenum target, GLenum internalFormat,
n[3].i = width;
n[4].e = format;
n[5].e = type;
- n[6].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, table,
+ &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_ColorTable(ctx->Exec, (target, internalFormat, width,
@@ -1283,8 +1328,6 @@ save_ColorSubTable(GLenum target, GLsizei start, GLsizei count,
GLenum format, GLenum type, const GLvoid * table)
{
GET_CURRENT_CONTEXT(ctx);
- GLvoid *image = unpack_image(1, count, 1, 1, format, type, table,
- &ctx->Unpack);
Node *n;
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
n = ALLOC_INSTRUCTION(ctx, OPCODE_COLOR_SUB_TABLE, 6);
@@ -1294,10 +1337,8 @@ save_ColorSubTable(GLenum target, GLsizei start, GLsizei count,
n[3].i = count;
n[4].e = format;
n[5].e = type;
- n[6].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[6].data = unpack_image(ctx, 1, count, 1, 1, format, type, table,
+ &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_ColorSubTable(ctx->Exec,
@@ -1355,10 +1396,10 @@ save_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width,
GLenum format, GLenum type, const GLvoid * filter)
{
GET_CURRENT_CONTEXT(ctx);
- GLvoid *image = unpack_image(1, width, 1, 1, format, type, filter,
- &ctx->Unpack);
Node *n;
+
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_FILTER_1D, 6);
if (n) {
n[1].e = target;
@@ -1366,10 +1407,8 @@ save_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width,
n[3].i = width;
n[4].e = format;
n[5].e = type;
- n[6].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, filter,
+ &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_ConvolutionFilter1D(ctx->Exec, (target, internalFormat, width,
@@ -1384,10 +1423,10 @@ save_ConvolutionFilter2D(GLenum target, GLenum internalFormat,
GLenum type, const GLvoid * filter)
{
GET_CURRENT_CONTEXT(ctx);
- GLvoid *image = unpack_image(2, width, height, 1, format, type, filter,
- &ctx->Unpack);
Node *n;
+
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_FILTER_2D, 7);
if (n) {
n[1].e = target;
@@ -1396,10 +1435,8 @@ save_ConvolutionFilter2D(GLenum target, GLenum internalFormat,
n[4].i = height;
n[5].e = format;
n[6].e = type;
- n[7].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[7].data = unpack_image(ctx, 2, width, height, 1, format, type, filter,
+ &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_ConvolutionFilter2D(ctx->Exec,
@@ -1754,20 +1791,18 @@ save_DrawPixels(GLsizei width, GLsizei height,
GLenum format, GLenum type, const GLvoid * pixels)
{
GET_CURRENT_CONTEXT(ctx);
- GLvoid *image = unpack_image(2, width, height, 1, format, type,
- pixels, &ctx->Unpack);
Node *n;
+
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_DRAW_PIXELS, 5);
if (n) {
n[1].i = width;
n[2].i = height;
n[3].e = format;
n[4].e = type;
- n[5].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[5].data = unpack_image(ctx, 2, width, height, 1, format, type,
+ pixels, &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_DrawPixels(ctx->Exec, (width, height, format, type, pixels));
@@ -1794,7 +1829,7 @@ save_Enable(GLenum cap)
static void GLAPIENTRY
-_mesa_save_EvalMesh1(GLenum mode, GLint i1, GLint i2)
+save_EvalMesh1(GLenum mode, GLint i1, GLint i2)
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
@@ -1812,7 +1847,7 @@ _mesa_save_EvalMesh1(GLenum mode, GLint i1, GLint i2)
static void GLAPIENTRY
-_mesa_save_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
+save_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
@@ -1856,7 +1891,10 @@ save_Fogfv(GLenum pname, const GLfloat *params)
static void GLAPIENTRY
save_Fogf(GLenum pname, GLfloat param)
{
- save_Fogfv(pname, &param);
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_Fogfv(pname, parray);
}
@@ -1880,7 +1918,7 @@ save_Fogiv(GLenum pname, const GLint *params)
break;
default:
/* Error will be caught later in gl_Fogfv */
- ;
+ ASSIGN_4V(p, 0.0F, 0.0F, 0.0F, 0.0F);
}
save_Fogfv(pname, p);
}
@@ -1889,7 +1927,10 @@ save_Fogiv(GLenum pname, const GLint *params)
static void GLAPIENTRY
save_Fogi(GLenum pname, GLint param)
{
- save_Fogiv(pname, &param);
+ GLint parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0;
+ save_Fogiv(pname, parray);
}
@@ -2053,9 +2094,12 @@ save_Lightfv(GLenum light, GLenum pname, const GLfloat *params)
static void GLAPIENTRY
-save_Lightf(GLenum light, GLenum pname, GLfloat params)
+save_Lightf(GLenum light, GLenum pname, GLfloat param)
{
- save_Lightfv(light, pname, &params);
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_Lightfv(light, pname, parray);
}
@@ -2101,7 +2145,10 @@ save_Lightiv(GLenum light, GLenum pname, const GLint *params)
static void GLAPIENTRY
save_Lighti(GLenum light, GLenum pname, GLint param)
{
- save_Lightiv(light, pname, &param);
+ GLint parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0;
+ save_Lightiv(light, pname, parray);
}
@@ -2128,7 +2175,10 @@ save_LightModelfv(GLenum pname, const GLfloat *params)
static void GLAPIENTRY
save_LightModelf(GLenum pname, GLfloat param)
{
- save_LightModelfv(pname, &param);
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_LightModelfv(pname, parray);
}
@@ -2150,7 +2200,7 @@ save_LightModeliv(GLenum pname, const GLint *params)
break;
default:
/* Error will be caught later in gl_LightModelfv */
- ;
+ ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F);
}
save_LightModelfv(pname, fparam);
}
@@ -2159,7 +2209,10 @@ save_LightModeliv(GLenum pname, const GLint *params)
static void GLAPIENTRY
save_LightModeli(GLenum pname, GLint param)
{
- save_LightModeliv(pname, &param);
+ GLint parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0;
+ save_LightModeliv(pname, parray);
}
@@ -2521,12 +2574,12 @@ save_MultMatrixd(const GLdouble * m)
static void GLAPIENTRY
-save_NewList(GLuint list, GLenum mode)
+save_NewList(GLuint name, GLenum mode)
{
GET_CURRENT_CONTEXT(ctx);
/* It's an error to call this function while building a display list */
_mesa_error(ctx, GL_INVALID_OPERATION, "glNewList");
- (void) list;
+ (void) name;
(void) mode;
}
@@ -2674,21 +2727,28 @@ save_PointParameterfvEXT(GLenum pname, const GLfloat *params)
static void GLAPIENTRY
save_PointParameterfEXT(GLenum pname, GLfloat param)
{
- save_PointParameterfvEXT(pname, &param);
+ GLfloat parray[3];
+ parray[0] = param;
+ parray[1] = parray[2] = 0.0F;
+ save_PointParameterfvEXT(pname, parray);
}
static void GLAPIENTRY
save_PointParameteriNV(GLenum pname, GLint param)
{
- GLfloat p = (GLfloat) param;
- save_PointParameterfvEXT(pname, &p);
+ GLfloat parray[3];
+ parray[0] = (GLfloat) param;
+ parray[1] = parray[2] = 0.0F;
+ save_PointParameterfvEXT(pname, parray);
}
static void GLAPIENTRY
save_PointParameterivNV(GLenum pname, const GLint * param)
{
- GLfloat p = (GLfloat) param[0];
- save_PointParameterfvEXT(pname, &p);
+ GLfloat parray[3];
+ parray[0] = (GLfloat) param[0];
+ parray[1] = parray[2] = 0.0F;
+ save_PointParameterfvEXT(pname, parray);
}
@@ -2729,16 +2789,14 @@ static void GLAPIENTRY
save_PolygonStipple(const GLubyte * pattern)
{
GET_CURRENT_CONTEXT(ctx);
- GLvoid *image = unpack_image(2, 32, 32, 1, GL_COLOR_INDEX, GL_BITMAP,
- pattern, &ctx->Unpack);
Node *n;
+
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_POLYGON_STIPPLE, 1);
if (n) {
- n[1].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[1].data = unpack_image(ctx, 2, 32, 32, 1, GL_COLOR_INDEX, GL_BITMAP,
+ pattern, &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_PolygonStipple(ctx->Exec, ((GLubyte *) pattern));
@@ -3172,14 +3230,26 @@ save_ShadeModel(GLenum mode)
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
- ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx);
+
+ if (ctx->ExecuteFlag) {
+ CALL_ShadeModel(ctx->Exec, (mode));
+ }
+
+ if (ctx->ListState.Current.ShadeModel == mode)
+ return;
+
+ SAVE_FLUSH_VERTICES(ctx);
+
+ /* Only save the value if we know the statechange will take effect:
+ */
+ if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
+ ctx->ListState.Current.ShadeModel = mode;
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_SHADE_MODEL, 1);
if (n) {
n[1].e = mode;
}
- if (ctx->ExecuteFlag) {
- CALL_ShadeModel(ctx->Exec, (mode));
- }
}
@@ -3350,7 +3420,10 @@ save_TexEnvfv(GLenum target, GLenum pname, const GLfloat *params)
static void GLAPIENTRY
save_TexEnvf(GLenum target, GLenum pname, GLfloat param)
{
- save_TexEnvfv(target, pname, &param);
+ GLfloat parray[4];
+ parray[0] = (GLfloat) param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_TexEnvfv(target, pname, parray);
}
@@ -3418,8 +3491,10 @@ save_TexGeniv(GLenum coord, GLenum pname, const GLint *params)
static void GLAPIENTRY
save_TexGend(GLenum coord, GLenum pname, GLdouble param)
{
- GLfloat p = (GLfloat) param;
- save_TexGenfv(coord, pname, &p);
+ GLfloat parray[4];
+ parray[0] = (GLfloat) param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_TexGenfv(coord, pname, parray);
}
@@ -3438,14 +3513,20 @@ save_TexGendv(GLenum coord, GLenum pname, const GLdouble *params)
static void GLAPIENTRY
save_TexGenf(GLenum coord, GLenum pname, GLfloat param)
{
- save_TexGenfv(coord, pname, &param);
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_TexGenfv(coord, pname, parray);
}
static void GLAPIENTRY
save_TexGeni(GLenum coord, GLenum pname, GLint param)
{
- save_TexGeniv(coord, pname, &param);
+ GLint parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0;
+ save_TexGeniv(coord, pname, parray);
}
@@ -3473,7 +3554,10 @@ save_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
static void GLAPIENTRY
save_TexParameterf(GLenum target, GLenum pname, GLfloat param)
{
- save_TexParameterfv(target, pname, &param);
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_TexParameterfv(target, pname, parray);
}
@@ -3510,8 +3594,6 @@ save_TexImage1D(GLenum target,
border, format, type, pixels));
}
else {
- GLvoid *image = unpack_image(1, width, 1, 1, format, type,
- pixels, &ctx->Unpack);
Node *n;
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_IMAGE1D, 8);
@@ -3523,10 +3605,8 @@ save_TexImage1D(GLenum target,
n[5].i = border;
n[6].e = format;
n[7].e = type;
- n[8].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[8].data = unpack_image(ctx, 1, width, 1, 1, format, type,
+ pixels, &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_TexImage1D(ctx->Exec, (target, level, components, width,
@@ -3549,8 +3629,6 @@ save_TexImage2D(GLenum target,
height, border, format, type, pixels));
}
else {
- GLvoid *image = unpack_image(2, width, height, 1, format, type,
- pixels, &ctx->Unpack);
Node *n;
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_IMAGE2D, 9);
@@ -3563,10 +3641,8 @@ save_TexImage2D(GLenum target,
n[6].i = border;
n[7].e = format;
n[8].e = type;
- n[9].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[9].data = unpack_image(ctx, 2, width, height, 1, format, type,
+ pixels, &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_TexImage2D(ctx->Exec, (target, level, components, width,
@@ -3592,8 +3668,6 @@ save_TexImage3D(GLenum target,
}
else {
Node *n;
- GLvoid *image = unpack_image(3, width, height, depth, format, type,
- pixels, &ctx->Unpack);
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_IMAGE3D, 10);
if (n) {
@@ -3606,10 +3680,8 @@ save_TexImage3D(GLenum target,
n[7].i = border;
n[8].e = format;
n[9].e = type;
- n[10].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[10].data = unpack_image(ctx, 3, width, height, depth, format, type,
+ pixels, &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_TexImage3D(ctx->Exec, (target, level, internalFormat, width,
@@ -3627,9 +3699,9 @@ save_TexSubImage1D(GLenum target, GLint level, GLint xoffset,
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
- GLvoid *image = unpack_image(1, width, 1, 1, format, type,
- pixels, &ctx->Unpack);
+
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_SUB_IMAGE1D, 7);
if (n) {
n[1].e = target;
@@ -3638,10 +3710,8 @@ save_TexSubImage1D(GLenum target, GLint level, GLint xoffset,
n[4].i = (GLint) width;
n[5].e = format;
n[6].e = type;
- n[7].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[7].data = unpack_image(ctx, 1, width, 1, 1, format, type,
+ pixels, &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_TexSubImage1D(ctx->Exec, (target, level, xoffset, width,
@@ -3658,9 +3728,9 @@ save_TexSubImage2D(GLenum target, GLint level,
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
- GLvoid *image = unpack_image(2, width, height, 1, format, type,
- pixels, &ctx->Unpack);
+
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_SUB_IMAGE2D, 9);
if (n) {
n[1].e = target;
@@ -3671,10 +3741,8 @@ save_TexSubImage2D(GLenum target, GLint level,
n[6].i = (GLint) height;
n[7].e = format;
n[8].e = type;
- n[9].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[9].data = unpack_image(ctx, 2, width, height, 1, format, type,
+ pixels, &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_TexSubImage2D(ctx->Exec, (target, level, xoffset, yoffset,
@@ -3691,9 +3759,9 @@ save_TexSubImage3D(GLenum target, GLint level,
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
- GLvoid *image = unpack_image(3, width, height, depth, format, type,
- pixels, &ctx->Unpack);
+
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_SUB_IMAGE3D, 11);
if (n) {
n[1].e = target;
@@ -3706,10 +3774,8 @@ save_TexSubImage3D(GLenum target, GLint level,
n[8].i = (GLint) depth;
n[9].e = format;
n[10].e = type;
- n[11].data = image;
- }
- else if (image) {
- _mesa_free(image);
+ n[11].data = unpack_image(ctx, 3, width, height, depth, format, type,
+ pixels, &ctx->Unpack);
}
if (ctx->ExecuteFlag) {
CALL_TexSubImage3D(ctx->Exec, (target, level,
@@ -4422,18 +4488,17 @@ save_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
- GLubyte *programCopy;
-
- programCopy = (GLubyte *) _mesa_malloc(len);
- if (!programCopy) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
- return;
- }
- _mesa_memcpy(programCopy, program, len);
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_LOAD_PROGRAM_NV, 4);
if (n) {
+ GLubyte *programCopy = (GLubyte *) _mesa_malloc(len);
+ if (!programCopy) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ return;
+ }
+ _mesa_memcpy(programCopy, program, len);
n[1].e = target;
n[2].ui = id;
n[3].i = len;
@@ -4450,15 +4515,17 @@ save_RequestResidentProgramsNV(GLsizei num, const GLuint * ids)
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
- GLuint *idCopy = (GLuint *) _mesa_malloc(num * sizeof(GLuint));
- if (!idCopy) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glRequestResidentProgramsNV");
- return;
- }
- _mesa_memcpy(idCopy, ids, num * sizeof(GLuint));
+
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_TRACK_MATRIX_NV, 2);
if (n) {
+ GLuint *idCopy = (GLuint *) _mesa_malloc(num * sizeof(GLuint));
+ if (!idCopy) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glRequestResidentProgramsNV");
+ return;
+ }
+ _mesa_memcpy(idCopy, ids, num * sizeof(GLuint));
n[1].i = num;
n[2].data = idCopy;
}
@@ -4619,16 +4686,17 @@ save_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte * name,
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
- GLubyte *nameCopy = (GLubyte *) _mesa_malloc(len);
- if (!nameCopy) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramNamedParameter4fNV");
- return;
- }
- _mesa_memcpy(nameCopy, name, len);
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_NAMED_PARAMETER_NV, 6);
if (n) {
+ GLubyte *nameCopy = (GLubyte *) _mesa_malloc(len);
+ if (!nameCopy) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramNamedParameter4fNV");
+ return;
+ }
+ _mesa_memcpy(nameCopy, name, len);
n[1].ui = id;
n[2].i = len;
n[3].data = nameCopy;
@@ -4717,18 +4785,17 @@ save_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
- GLubyte *programCopy;
-
- programCopy = (GLubyte *) _mesa_malloc(len);
- if (!programCopy) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
- return;
- }
- _mesa_memcpy(programCopy, string, len);
ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_STRING_ARB, 4);
if (n) {
+ GLubyte *programCopy = (GLubyte *) _mesa_malloc(len);
+ if (!programCopy) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
+ return;
+ }
+ _mesa_memcpy(programCopy, string, len);
n[1].e = target;
n[2].e = format;
n[3].i = len;
@@ -4742,7 +4809,7 @@ save_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
#endif /* FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program */
-#if FEATURE_ARB_occlusion_query
+#if FEATURE_queryobj
static void GLAPIENTRY
save_BeginQueryARB(GLenum target, GLuint id)
@@ -4776,7 +4843,7 @@ save_EndQueryARB(GLenum target)
}
}
-#endif /* FEATURE_ARB_occlusion_query */
+#endif /* FEATURE_queryobj */
static void GLAPIENTRY
@@ -4800,6 +4867,36 @@ save_DrawBuffersARB(GLsizei count, const GLenum * buffers)
}
}
+static void GLAPIENTRY
+save_TexBumpParameterfvATI(GLenum pname, const GLfloat *param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_BUMP_PARAMETER_ATI, 5);
+ if (n) {
+ n[1].ui = pname;
+ n[2].f = param[0];
+ n[3].f = param[1];
+ n[4].f = param[2];
+ n[5].f = param[3];
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TexBumpParameterfvATI(ctx->Exec, (pname, param));
+ }
+}
+
+static void GLAPIENTRY
+save_TexBumpParameterivATI(GLenum pname, const GLint *param)
+{
+ GLfloat p[4];
+ p[0] = INT_TO_FLOAT(param[0]);
+ p[1] = INT_TO_FLOAT(param[1]);
+ p[2] = INT_TO_FLOAT(param[2]);
+ p[3] = INT_TO_FLOAT(param[3]);
+ save_TexBumpParameterfvATI(pname, p);
+}
+
#if FEATURE_ATI_fragment_shader
static void GLAPIENTRY
save_BindFragmentShaderATI(GLuint id)
@@ -4848,7 +4945,7 @@ save_Attr1fNV(GLenum attr, GLfloat x)
n[2].f = x;
}
- ASSERT(attr < MAX_VERTEX_PROGRAM_ATTRIBS);
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
ctx->ListState.ActiveAttribSize[attr] = 1;
ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, 0, 0, 1);
@@ -4870,7 +4967,7 @@ save_Attr2fNV(GLenum attr, GLfloat x, GLfloat y)
n[3].f = y;
}
- ASSERT(attr < MAX_VERTEX_PROGRAM_ATTRIBS);
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
ctx->ListState.ActiveAttribSize[attr] = 2;
ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, 0, 1);
@@ -4893,7 +4990,7 @@ save_Attr3fNV(GLenum attr, GLfloat x, GLfloat y, GLfloat z)
n[4].f = z;
}
- ASSERT(attr < MAX_VERTEX_PROGRAM_ATTRIBS);
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
ctx->ListState.ActiveAttribSize[attr] = 3;
ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, 1);
@@ -4917,7 +5014,7 @@ save_Attr4fNV(GLenum attr, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
n[5].f = w;
}
- ASSERT(attr < MAX_VERTEX_PROGRAM_ATTRIBS);
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
ctx->ListState.ActiveAttribSize[attr] = 4;
ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, w);
@@ -4939,7 +5036,7 @@ save_Attr1fARB(GLenum attr, GLfloat x)
n[2].f = x;
}
- ASSERT(attr < MAX_VERTEX_ATTRIBS);
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
ctx->ListState.ActiveAttribSize[attr] = 1;
ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, 0, 0, 1);
@@ -4961,7 +5058,7 @@ save_Attr2fARB(GLenum attr, GLfloat x, GLfloat y)
n[3].f = y;
}
- ASSERT(attr < MAX_VERTEX_ATTRIBS);
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
ctx->ListState.ActiveAttribSize[attr] = 2;
ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, 0, 1);
@@ -4984,7 +5081,7 @@ save_Attr3fARB(GLenum attr, GLfloat x, GLfloat y, GLfloat z)
n[4].f = z;
}
- ASSERT(attr < MAX_VERTEX_ATTRIBS);
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
ctx->ListState.ActiveAttribSize[attr] = 3;
ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, 1);
@@ -5008,7 +5105,7 @@ save_Attr4fARB(GLenum attr, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
n[5].f = w;
}
- ASSERT(attr < MAX_VERTEX_ATTRIBS);
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
ctx->ListState.ActiveAttribSize[attr] = 4;
ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, w);
@@ -5111,14 +5208,21 @@ save_EdgeFlag(GLboolean x)
save_Attr1fNV(VERT_ATTRIB_EDGEFLAG, x ? (GLfloat)1.0 : (GLfloat)0.0);
}
+static INLINE GLboolean compare4fv( const GLfloat *a,
+ const GLfloat *b,
+ GLuint count )
+{
+ return memcmp( a, b, count * sizeof(GLfloat) ) == 0;
+}
+
+
static void GLAPIENTRY
save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
{
GET_CURRENT_CONTEXT(ctx);
Node *n;
int args, i;
-
- SAVE_FLUSH_VERTICES(ctx);
+ GLuint bitmask;
switch (face) {
case GL_BACK:
@@ -5148,26 +5252,43 @@ save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
_mesa_compile_error(ctx, GL_INVALID_ENUM, "material(pname)");
return;
}
-
- n = ALLOC_INSTRUCTION(ctx, OPCODE_MATERIAL, 6);
- if (n) {
- n[1].e = face;
- n[2].e = pname;
- for (i = 0; i < args; i++)
- n[3 + i].f = param[i];
+
+ if (ctx->ExecuteFlag) {
+ CALL_Materialfv(ctx->Exec, (face, pname, param));
}
- {
- GLuint bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL);
- for (i = 0; i < MAT_ATTRIB_MAX; i++)
- if (bitmask & (1 << i)) {
+ bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL);
+
+ /* Try to eliminate redundant statechanges. Because it is legal to
+ * call glMaterial even inside begin/end calls, don't need to worry
+ * about ctx->Driver.CurrentSavePrimitive here.
+ */
+ for (i = 0; i < MAT_ATTRIB_MAX; i++) {
+ if (bitmask & (1 << i)) {
+ if (ctx->ListState.ActiveMaterialSize[i] == args &&
+ compare4fv(ctx->ListState.CurrentMaterial[i], param, args)) {
+ bitmask &= ~(1 << i);
+ }
+ else {
ctx->ListState.ActiveMaterialSize[i] = args;
COPY_SZ_4V(ctx->ListState.CurrentMaterial[i], args, param);
}
+ }
}
- if (ctx->ExecuteFlag) {
- CALL_Materialfv(ctx->Exec, (face, pname, param));
+ /* If this call has effect, return early:
+ */
+ if (bitmask == 0)
+ return;
+
+ SAVE_FLUSH_VERTICES(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_MATERIAL, 6);
+ if (n) {
+ n[1].e = face;
+ n[2].e = pname;
+ for (i = 0; i < args; i++)
+ n[3 + i].f = param[i];
}
}
@@ -5471,7 +5592,7 @@ index_error(void)
static void GLAPIENTRY
save_VertexAttrib1fNV(GLuint index, GLfloat x)
{
- if (index < MAX_VERTEX_PROGRAM_ATTRIBS)
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
save_Attr1fNV(index, x);
else
index_error();
@@ -5480,7 +5601,7 @@ save_VertexAttrib1fNV(GLuint index, GLfloat x)
static void GLAPIENTRY
save_VertexAttrib1fvNV(GLuint index, const GLfloat * v)
{
- if (index < MAX_VERTEX_PROGRAM_ATTRIBS)
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
save_Attr1fNV(index, v[0]);
else
index_error();
@@ -5489,7 +5610,7 @@ save_VertexAttrib1fvNV(GLuint index, const GLfloat * v)
static void GLAPIENTRY
save_VertexAttrib2fNV(GLuint index, GLfloat x, GLfloat y)
{
- if (index < MAX_VERTEX_PROGRAM_ATTRIBS)
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
save_Attr2fNV(index, x, y);
else
index_error();
@@ -5498,7 +5619,7 @@ save_VertexAttrib2fNV(GLuint index, GLfloat x, GLfloat y)
static void GLAPIENTRY
save_VertexAttrib2fvNV(GLuint index, const GLfloat * v)
{
- if (index < MAX_VERTEX_PROGRAM_ATTRIBS)
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
save_Attr2fNV(index, v[0], v[1]);
else
index_error();
@@ -5507,7 +5628,7 @@ save_VertexAttrib2fvNV(GLuint index, const GLfloat * v)
static void GLAPIENTRY
save_VertexAttrib3fNV(GLuint index, GLfloat x, GLfloat y, GLfloat z)
{
- if (index < MAX_VERTEX_PROGRAM_ATTRIBS)
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
save_Attr3fNV(index, x, y, z);
else
index_error();
@@ -5516,7 +5637,7 @@ save_VertexAttrib3fNV(GLuint index, GLfloat x, GLfloat y, GLfloat z)
static void GLAPIENTRY
save_VertexAttrib3fvNV(GLuint index, const GLfloat * v)
{
- if (index < MAX_VERTEX_PROGRAM_ATTRIBS)
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
save_Attr3fNV(index, v[0], v[1], v[2]);
else
index_error();
@@ -5526,7 +5647,7 @@ static void GLAPIENTRY
save_VertexAttrib4fNV(GLuint index, GLfloat x, GLfloat y,
GLfloat z, GLfloat w)
{
- if (index < MAX_VERTEX_PROGRAM_ATTRIBS)
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
save_Attr4fNV(index, x, y, z, w);
else
index_error();
@@ -5535,7 +5656,7 @@ save_VertexAttrib4fNV(GLuint index, GLfloat x, GLfloat y,
static void GLAPIENTRY
save_VertexAttrib4fvNV(GLuint index, const GLfloat * v)
{
- if (index < MAX_VERTEX_PROGRAM_ATTRIBS)
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
save_Attr4fNV(index, v[0], v[1], v[2], v[3]);
else
index_error();
@@ -5547,7 +5668,7 @@ save_VertexAttrib4fvNV(GLuint index, const GLfloat * v)
static void GLAPIENTRY
save_VertexAttrib1fARB(GLuint index, GLfloat x)
{
- if (index < MAX_VERTEX_ATTRIBS)
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
save_Attr1fARB(index, x);
else
index_error();
@@ -5556,7 +5677,7 @@ save_VertexAttrib1fARB(GLuint index, GLfloat x)
static void GLAPIENTRY
save_VertexAttrib1fvARB(GLuint index, const GLfloat * v)
{
- if (index < MAX_VERTEX_ATTRIBS)
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
save_Attr1fARB(index, v[0]);
else
index_error();
@@ -5565,7 +5686,7 @@ save_VertexAttrib1fvARB(GLuint index, const GLfloat * v)
static void GLAPIENTRY
save_VertexAttrib2fARB(GLuint index, GLfloat x, GLfloat y)
{
- if (index < MAX_VERTEX_ATTRIBS)
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
save_Attr2fARB(index, x, y);
else
index_error();
@@ -5574,7 +5695,7 @@ save_VertexAttrib2fARB(GLuint index, GLfloat x, GLfloat y)
static void GLAPIENTRY
save_VertexAttrib2fvARB(GLuint index, const GLfloat * v)
{
- if (index < MAX_VERTEX_ATTRIBS)
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
save_Attr2fARB(index, v[0], v[1]);
else
index_error();
@@ -5583,7 +5704,7 @@ save_VertexAttrib2fvARB(GLuint index, const GLfloat * v)
static void GLAPIENTRY
save_VertexAttrib3fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z)
{
- if (index < MAX_VERTEX_ATTRIBS)
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
save_Attr3fARB(index, x, y, z);
else
index_error();
@@ -5592,7 +5713,7 @@ save_VertexAttrib3fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z)
static void GLAPIENTRY
save_VertexAttrib3fvARB(GLuint index, const GLfloat * v)
{
- if (index < MAX_VERTEX_ATTRIBS)
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
save_Attr3fARB(index, v[0], v[1], v[2]);
else
index_error();
@@ -5602,7 +5723,7 @@ static void GLAPIENTRY
save_VertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z,
GLfloat w)
{
- if (index < MAX_VERTEX_ATTRIBS)
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
save_Attr4fARB(index, x, y, z, w);
else
index_error();
@@ -5611,7 +5732,7 @@ save_VertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z,
static void GLAPIENTRY
save_VertexAttrib4fvARB(GLuint index, const GLfloat * v)
{
- if (index < MAX_VERTEX_ATTRIBS)
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
save_Attr4fARB(index, v[0], v[1], v[2], v[3]);
else
index_error();
@@ -5670,6 +5791,25 @@ save_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
#endif
+/** GL_EXT_provoking_vertex */
+static void GLAPIENTRY
+save_ProvokingVertexEXT(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROVOKING_VERTEX, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ /*CALL_ProvokingVertexEXT(ctx->Exec, (mode));*/
+ _mesa_ProvokingVertexEXT(mode);
+ }
+}
+
+
+
/**
* Save an error-generating command into display list.
*
@@ -5731,7 +5871,7 @@ islist(GLcontext *ctx, GLuint list)
static void
execute_list(GLcontext *ctx, GLuint list)
{
- struct mesa_display_list *dlist;
+ struct gl_display_list *dlist;
Node *n;
GLboolean done;
@@ -5752,7 +5892,7 @@ execute_list(GLcontext *ctx, GLuint list)
if (ctx->Driver.BeginCallList)
ctx->Driver.BeginCallList(ctx, dlist);
- n = dlist->node;
+ n = dlist->Head;
done = GL_FALSE;
while (!done) {
@@ -6234,6 +6374,9 @@ execute_list(GLcontext *ctx, GLuint list)
case OPCODE_SHADE_MODEL:
CALL_ShadeModel(ctx->Exec, (n[1].e));
break;
+ case OPCODE_PROVOKING_VERTEX:
+ CALL_ProvokingVertexEXT(ctx->Exec, (n[1].e));
+ break;
case OPCODE_STENCIL_FUNC:
CALL_StencilFunc(ctx->Exec, (n[1].e, n[2].i, n[3].ui));
break;
@@ -6478,7 +6621,7 @@ execute_list(GLcontext *ctx, GLuint list)
n[6].f));
break;
#endif
-#if FEATURE_ARB_occlusion_query
+#if FEATURE_queryobj
case OPCODE_BEGIN_QUERY_ARB:
CALL_BeginQueryARB(ctx->Exec, (n[1].e, n[2].ui));
break;
@@ -6502,6 +6645,16 @@ execute_list(GLcontext *ctx, GLuint list)
n[9].i, n[10].e));
break;
#endif
+ case OPCODE_TEX_BUMP_PARAMETER_ATI:
+ {
+ GLfloat values[4];
+ GLuint i, pname = n[1].ui;
+
+ for (i = 0; i < 4; i++)
+ values[i] = n[1 + i].f;
+ CALL_TexBumpParameterfvATI(ctx->Exec, (pname, values));
+ }
+ break;
#if FEATURE_ATI_fragment_shader
case OPCODE_BIND_FRAGMENT_SHADER_ATI:
CALL_BindFragmentShaderATI(ctx->Exec, (n[1].i));
@@ -6723,19 +6876,18 @@ _mesa_GenLists(GLsizei range)
* Begin a new display list.
*/
void GLAPIENTRY
-_mesa_NewList(GLuint list, GLenum mode)
+_mesa_NewList(GLuint name, GLenum mode)
{
GET_CURRENT_CONTEXT(ctx);
- GLint i;
FLUSH_CURRENT(ctx, 0); /* must be called before assert */
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glNewList %u %s\n", list,
+ _mesa_debug(ctx, "glNewList %u %s\n", name,
_mesa_lookup_enum_by_nr(mode));
- if (list == 0) {
+ if (name == 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glNewList");
return;
}
@@ -6745,7 +6897,7 @@ _mesa_NewList(GLuint list, GLenum mode)
return;
}
- if (ctx->ListState.CurrentListPtr) {
+ if (ctx->ListState.CurrentList) {
/* already compiling a display list */
_mesa_error(ctx, GL_INVALID_OPERATION, "glNewList");
return;
@@ -6754,23 +6906,16 @@ _mesa_NewList(GLuint list, GLenum mode)
ctx->CompileFlag = GL_TRUE;
ctx->ExecuteFlag = (mode == GL_COMPILE_AND_EXECUTE);
- /* Allocate new display list */
- ctx->ListState.CurrentListNum = list;
- ctx->ListState.CurrentList = make_list(list, BLOCK_SIZE);
- ctx->ListState.CurrentBlock = ctx->ListState.CurrentList->node;
- ctx->ListState.CurrentListPtr = ctx->ListState.CurrentBlock;
- ctx->ListState.CurrentPos = 0;
-
/* Reset acumulated list state:
*/
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
- ctx->ListState.ActiveAttribSize[i] = 0;
+ invalidate_saved_current_state( ctx );
- for (i = 0; i < MAT_ATTRIB_MAX; i++)
- ctx->ListState.ActiveMaterialSize[i] = 0;
+ /* Allocate new display list */
+ ctx->ListState.CurrentList = make_list(name, BLOCK_SIZE);
+ ctx->ListState.CurrentBlock = ctx->ListState.CurrentList->Head;
+ ctx->ListState.CurrentPos = 0;
- ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
- ctx->Driver.NewList(ctx, list, mode);
+ ctx->Driver.NewList(ctx, name, mode);
ctx->CurrentDispatch = ctx->Save;
_glapi_set_dispatch(ctx->CurrentDispatch);
@@ -6791,7 +6936,7 @@ _mesa_EndList(void)
_mesa_debug(ctx, "glEndList\n");
/* Check that a list is under construction */
- if (!ctx->ListState.CurrentListPtr) {
+ if (!ctx->ListState.CurrentList) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glEndList");
return;
}
@@ -6804,18 +6949,18 @@ _mesa_EndList(void)
(void) ALLOC_INSTRUCTION(ctx, OPCODE_END_OF_LIST, 0);
/* Destroy old list, if any */
- destroy_list(ctx, ctx->ListState.CurrentListNum);
- /* Install the list */
- _mesa_HashInsert(ctx->Shared->DisplayList, ctx->ListState.CurrentListNum,
+ destroy_list(ctx, ctx->ListState.CurrentList->Name);
+
+ /* Install the new list */
+ _mesa_HashInsert(ctx->Shared->DisplayList,
+ ctx->ListState.CurrentList->Name,
ctx->ListState.CurrentList);
if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST)
- mesa_print_display_list(ctx->ListState.CurrentListNum);
+ mesa_print_display_list(ctx->ListState.CurrentList->Name);
ctx->ListState.CurrentList = NULL;
- ctx->ListState.CurrentListNum = 0;
- ctx->ListState.CurrentListPtr = NULL;
ctx->ExecuteFlag = GL_TRUE;
ctx->CompileFlag = GL_FALSE;
@@ -7611,18 +7756,6 @@ exec_MultiDrawArraysEXT(GLenum mode, GLint * first,
CALL_MultiDrawArraysEXT(ctx->Exec, (mode, first, count, primcount));
}
-/* GL_EXT_multi_draw_arrays */
-static void GLAPIENTRY
-exec_MultiDrawElementsEXT(GLenum mode, const GLsizei * count,
- GLenum type, const GLvoid ** indices,
- GLsizei primcount)
-{
- GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0);
- CALL_MultiDrawElementsEXT(ctx->Exec,
- (mode, count, type, indices, primcount));
-}
-
/* GL_IBM_multimode_draw_arrays */
static void GLAPIENTRY
exec_MultiModeDrawArraysIBM(const GLenum * mode, const GLint * first,
@@ -7661,7 +7794,7 @@ exec_MultiModeDrawElementsIBM(const GLenum * mode,
* struct.
*/
void
-_mesa_init_dlist_table(struct _glapi_table *table)
+_mesa_init_save_table(struct _glapi_table *table)
{
_mesa_loopback_init_api_table(table);
@@ -7692,8 +7825,8 @@ _mesa_init_dlist_table(struct _glapi_table *table)
SET_DrawPixels(table, save_DrawPixels);
SET_Enable(table, save_Enable);
SET_EndList(table, _mesa_EndList);
- SET_EvalMesh1(table, _mesa_save_EvalMesh1);
- SET_EvalMesh2(table, _mesa_save_EvalMesh2);
+ SET_EvalMesh1(table, save_EvalMesh1);
+ SET_EvalMesh2(table, save_EvalMesh2);
SET_Finish(table, exec_Finish);
SET_Flush(table, exec_Flush);
SET_Fogf(table, save_Fogf);
@@ -7968,7 +8101,6 @@ _mesa_init_dlist_table(struct _glapi_table *table)
/* 148. GL_EXT_multi_draw_arrays */
SET_MultiDrawArraysEXT(table, exec_MultiDrawArraysEXT);
- SET_MultiDrawElementsEXT(table, exec_MultiDrawElementsEXT);
/* 149. GL_EXT_fog_coord */
SET_FogCoordPointerEXT(table, exec_FogCoordPointerEXT);
@@ -8042,6 +8174,10 @@ _mesa_init_dlist_table(struct _glapi_table *table)
SET_VertexAttribPointerNV(table, _mesa_VertexAttribPointerNV);
#endif
+ /* 244. GL_ATI_envmap_bumpmap */
+ SET_TexBumpParameterivATI(table, save_TexBumpParameterivATI);
+ SET_TexBumpParameterfvATI(table, save_TexBumpParameterfvATI);
+
/* 245. GL_ATI_fragment_shader */
#if FEATURE_ATI_fragment_shader
SET_BindFragmentShaderATI(table, save_BindFragmentShaderATI);
@@ -8162,7 +8298,7 @@ _mesa_init_dlist_table(struct _glapi_table *table)
SET_UnmapBufferARB(table, _mesa_UnmapBufferARB);
#endif
-#if FEATURE_ARB_occlusion_query
+#if FEATURE_queryobj
SET_BeginQueryARB(table, save_BeginQueryARB);
SET_EndQueryARB(table, save_EndQueryARB);
SET_GenQueriesARB(table, _mesa_GenQueriesARB);
@@ -8191,6 +8327,18 @@ _mesa_init_dlist_table(struct _glapi_table *table)
SET_ProgramEnvParameters4fvEXT(table, save_ProgramEnvParameters4fvEXT);
SET_ProgramLocalParameters4fvEXT(table, save_ProgramLocalParameters4fvEXT);
#endif
+
+ /* ARB 50. GL_ARB_map_buffer_range */
+#if FEATURE_ARB_map_buffer_range
+ SET_MapBufferRange(table, _mesa_MapBufferRange); /* no dlist save */
+ SET_FlushMappedBufferRange(table, _mesa_FlushMappedBufferRange); /* no dl */
+#endif
+
+ /* ARB 59. GL_ARB_copy_buffer */
+ SET_CopyBufferSubData(table, _mesa_CopyBufferSubData); /* no dlist save */
+
+ /* 364. GL_EXT_provoking_vertex */
+ SET_ProvokingVertexEXT(table, save_ProvokingVertexEXT);
}
@@ -8209,7 +8357,7 @@ enum_string(GLenum k)
static void GLAPIENTRY
print_list(GLcontext *ctx, GLuint list)
{
- struct mesa_display_list *dlist;
+ struct gl_display_list *dlist;
Node *n;
GLboolean done;
@@ -8222,7 +8370,7 @@ print_list(GLcontext *ctx, GLuint list)
if (!dlist)
return;
- n = dlist->node;
+ n = dlist->Head;
_mesa_printf("START-LIST %u, address %p\n", list, (void *) n);
@@ -8427,6 +8575,11 @@ print_list(GLcontext *ctx, GLuint list)
_mesa_printf("EVAL_P2 %d %d\n", n[1].i, n[2].i);
break;
+ case OPCODE_PROVOKING_VERTEX:
+ _mesa_printf("ProvokingVertex %s\n",
+ _mesa_lookup_enum_by_nr(n[1].ui));
+ break;
+
/*
* meta opcodes/commands
*/
@@ -8484,22 +8637,21 @@ mesa_print_display_list(GLuint list)
void
_mesa_save_vtxfmt_init(GLvertexformat * vfmt)
{
- vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
+ _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
+
vfmt->Begin = save_Begin;
- vfmt->CallList = _mesa_save_CallList;
- vfmt->CallLists = _mesa_save_CallLists;
+
+ _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_save_);
+
vfmt->Color3f = save_Color3f;
vfmt->Color3fv = save_Color3fv;
vfmt->Color4f = save_Color4f;
vfmt->Color4fv = save_Color4fv;
vfmt->EdgeFlag = save_EdgeFlag;
vfmt->End = save_End;
- vfmt->EvalCoord1f = save_EvalCoord1f;
- vfmt->EvalCoord1fv = save_EvalCoord1fv;
- vfmt->EvalCoord2f = save_EvalCoord2f;
- vfmt->EvalCoord2fv = save_EvalCoord2fv;
- vfmt->EvalPoint1 = save_EvalPoint1;
- vfmt->EvalPoint2 = save_EvalPoint2;
+
+ _MESA_INIT_EVAL_VTXFMT(vfmt, save_);
+
vfmt->FogCoordfEXT = save_FogCoordfEXT;
vfmt->FogCoordfvEXT = save_FogCoordfvEXT;
vfmt->Indexf = save_Indexf;
@@ -8548,8 +8700,6 @@ _mesa_save_vtxfmt_init(GLvertexformat * vfmt)
vfmt->VertexAttrib4fARB = save_VertexAttrib4fARB;
vfmt->VertexAttrib4fvARB = save_VertexAttrib4fvARB;
- vfmt->EvalMesh1 = _mesa_save_EvalMesh1;
- vfmt->EvalMesh2 = _mesa_save_EvalMesh2;
vfmt->Rectf = save_Rectf;
/* The driver is required to implement these as
@@ -8562,10 +8712,40 @@ _mesa_save_vtxfmt_init(GLvertexformat * vfmt)
vfmt->DrawArrays = 0;
vfmt->DrawElements = 0;
vfmt->DrawRangeElements = 0;
+ vfmt->MultiDrawElemementsEXT = 0;
+ vfmt->DrawElementsBaseVertex = 0;
+ vfmt->DrawRangeElementsBaseVertex = 0;
+ vfmt->MultiDrawElemementsBaseVertex = 0;
#endif
}
+void
+_mesa_install_dlist_vtxfmt(struct _glapi_table *disp,
+ const GLvertexformat *vfmt)
+{
+ SET_CallList(disp, vfmt->CallList);
+ SET_CallLists(disp, vfmt->CallLists);
+}
+
+
+void _mesa_init_dlist_dispatch(struct _glapi_table *disp)
+{
+ SET_CallList(disp, _mesa_CallList);
+ SET_CallLists(disp, _mesa_CallLists);
+
+ SET_DeleteLists(disp, _mesa_DeleteLists);
+ SET_EndList(disp, _mesa_EndList);
+ SET_GenLists(disp, _mesa_GenLists);
+ SET_IsList(disp, _mesa_IsList);
+ SET_ListBase(disp, _mesa_ListBase);
+ SET_NewList(disp, _mesa_NewList);
+}
+
+
+#endif /* FEATURE_dlist */
+
+
/**
* Initialize display list state for given context.
*/
@@ -8584,13 +8764,13 @@ _mesa_init_display_list(GLcontext *ctx)
ctx->ListState.CallDepth = 0;
ctx->ExecuteFlag = GL_TRUE;
ctx->CompileFlag = GL_FALSE;
- ctx->ListState.CurrentListPtr = NULL;
ctx->ListState.CurrentBlock = NULL;
- ctx->ListState.CurrentListNum = 0;
ctx->ListState.CurrentPos = 0;
/* Display List group */
ctx->List.ListBase = 0;
+#if FEATURE_dlist
_mesa_save_vtxfmt_init(&ctx->ListState.ListVtxfmt);
+#endif
}
diff --git a/src/mesa/main/dlist.h b/src/mesa/main/dlist.h
index ef6a10af83..6e1059eac2 100644
--- a/src/mesa/main/dlist.h
+++ b/src/mesa/main/dlist.h
@@ -33,13 +33,26 @@
#define DLIST_H
-#include "mtypes.h"
+#include "main/mtypes.h"
-#if _HAVE_FULL_GL
+#if FEATURE_dlist
-extern void
-_mesa_delete_list(GLcontext *ctx, struct mesa_display_list *dlist);
+#define _MESA_INIT_DLIST_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->NewList = impl ## NewList; \
+ (driver)->EndList = impl ## EndList; \
+ (driver)->BeginCallList = impl ## BeginCallList; \
+ (driver)->EndCallList = impl ## EndCallList; \
+ (driver)->SaveFlushVertices = impl ## SaveFlushVertices; \
+ (driver)->NotifySaveBegin = impl ## NotifyBegin; \
+ } while (0)
+
+#define _MESA_INIT_DLIST_VTXFMT(vfmt, impl) \
+ do { \
+ (vfmt)->CallList = impl ## CallList; \
+ (vfmt)->CallLists = impl ## CallLists; \
+ } while (0)
extern void GLAPIENTRY _mesa_CallList( GLuint list );
@@ -62,12 +75,8 @@ extern void GLAPIENTRY _mesa_save_CallLists( GLsizei n, GLenum type, const GLvoi
extern void GLAPIENTRY _mesa_save_CallList( GLuint list );
-
-extern void _mesa_init_dlist_table( struct _glapi_table *table );
-
extern void _mesa_compile_error( GLcontext *ctx, GLenum error, const char *s );
-
extern void *_mesa_alloc_instruction(GLcontext *ctx, GLuint opcode, GLuint sz);
extern GLint _mesa_alloc_opcode( GLcontext *ctx, GLuint sz,
@@ -75,22 +84,48 @@ extern GLint _mesa_alloc_opcode( GLcontext *ctx, GLuint sz,
void (*destroy)( GLcontext *, void * ),
void (*print)( GLcontext *, void * ) );
-extern void _mesa_init_display_list( GLcontext * ctx );
+extern void _mesa_delete_list(GLcontext *ctx, struct gl_display_list *dlist);
extern void _mesa_save_vtxfmt_init( GLvertexformat *vfmt );
+extern void _mesa_init_save_table( struct _glapi_table *table );
+
+extern void _mesa_install_dlist_vtxfmt(struct _glapi_table *disp,
+ const GLvertexformat *vfmt);
-#else
+extern void _mesa_init_dlist_dispatch(struct _glapi_table *disp);
-/** No-op */
-#define _mesa_init_dlist_table(t,ts) ((void)0)
+#else /* FEATURE_dlist */
-/** No-op */
-#define _mesa_init_display_list(c) ((void)0)
+#define _MESA_INIT_DLIST_FUNCTIONS(driver, impl) do { } while (0)
+#define _MESA_INIT_DLIST_VTXFMT(vfmt, impl) do { } while (0)
-/** No-op */
-#define _mesa_save_vtxfmt_init(v) ((void)0)
+static INLINE void
+_mesa_delete_list(GLcontext *ctx, struct gl_display_list *dlist)
+{
+ /* there should be no list to delete */
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_mesa_init_save_table(struct _glapi_table *disp)
+{
+}
+
+static INLINE void
+_mesa_install_dlist_vtxfmt(struct _glapi_table *disp,
+ const GLvertexformat *vfmt)
+{
+}
+
+static INLINE void
+_mesa_init_dlist_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_dlist */
+
+extern void _mesa_init_display_list( GLcontext * ctx );
-#endif
-#endif
+#endif /* DLIST_H */
diff --git a/src/mesa/main/dlopen.c b/src/mesa/main/dlopen.c
index becef8173e..414cfad8e2 100644
--- a/src/mesa/main/dlopen.c
+++ b/src/mesa/main/dlopen.c
@@ -28,13 +28,15 @@
*/
-#include "glheader.h"
-#include "imports.h"
+#include "compiler.h"
#include "dlopen.h"
#if defined(_GNU_SOURCE) && !defined(__MINGW32__)
#include <dlfcn.h>
#endif
+#if defined(_WIN32)
+#include <windows.h>
+#endif
/**
@@ -48,7 +50,7 @@ _mesa_dlopen(const char *libname, int flags)
flags = RTLD_LAZY | RTLD_GLOBAL; /* Overriding flags at this time */
return dlopen(libname, flags);
#elif defined(__MINGW32__)
- return LoadLibrary(libname);
+ return LoadLibraryA(libname);
#else
return NULL;
#endif
diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c
index ac97bc1ff9..f7ce64fd7c 100644
--- a/src/mesa/main/drawpix.c
+++ b/src/mesa/main/drawpix.c
@@ -27,14 +27,28 @@
#include "bufferobj.h"
#include "context.h"
#include "drawpix.h"
+#include "enums.h"
#include "feedback.h"
#include "framebuffer.h"
#include "image.h"
#include "readpix.h"
#include "state.h"
+#include "glapi/dispatch.h"
-#if _HAVE_FULL_GL
+#if FEATURE_drawpix
+
+
+/**
+ * If a fragment program is enabled, check that it's valid.
+ * \return GL_TRUE if valid, GL_FALSE otherwise
+ */
+static GLboolean
+valid_fragment_program(GLcontext *ctx)
+{
+ return !(ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled);
+}
+
/*
* Execute glDrawPixels
@@ -51,59 +65,66 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
return;
}
+ /* We're not using the current vertex program, and the driver may install
+ * it's own.
+ */
+ _mesa_set_vp_override(ctx, GL_TRUE);
+
if (ctx->NewState) {
_mesa_update_state(ctx);
}
- if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+ if (!valid_fragment_program(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glDrawPixels (invalid fragment program)");
- return;
+ goto end;
}
if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) {
- /* found an error */
- return;
+ /* the error was already recorded */
+ goto end;
}
if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
"glDrawPixels(incomplete framebuffer)" );
- return;
+ goto end;
}
if (!ctx->Current.RasterPosValid) {
- return;
+ goto end; /* no-op, not an error */
}
if (ctx->RenderMode == GL_RENDER) {
- /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
- GLint x = IROUND(ctx->Current.RasterPos[0]);
- GLint y = IROUND(ctx->Current.RasterPos[1]);
-
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack from PBO */
- if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawPixels(invalid PBO access)");
- return;
- }
- if (ctx->Unpack.BufferObj->Pointer) {
- /* buffer is mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glDrawPixels(PBO is mapped)");
- return;
+ if (width > 0 && height > 0) {
+ /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
+ GLint x = IROUND(ctx->Current.RasterPos[0]);
+ GLint y = IROUND(ctx->Current.RasterPos[1]);
+
+ if (ctx->Unpack.BufferObj->Name) {
+ /* unpack from PBO */
+ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(invalid PBO access)");
+ goto end;
+ }
+ if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(PBO is mapped)");
+ goto end;
+ }
}
- }
- ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
- &ctx->Unpack, pixels);
+ ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
+ &ctx->Unpack, pixels);
+ }
}
else if (ctx->RenderMode == GL_FEEDBACK) {
/* Feedback the current raster pos info */
FLUSH_CURRENT( ctx, 0 );
- FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
_mesa_feedback_vertex( ctx,
ctx->Current.RasterPos,
ctx->Current.RasterColor,
@@ -114,6 +135,9 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
ASSERT(ctx->RenderMode == GL_SELECT);
/* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
}
+
+end:
+ _mesa_set_vp_override(ctx, GL_FALSE);
}
@@ -124,49 +148,69 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ if (width < 0 || height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
+ return;
+ }
+
+ /* Note: more detailed 'type' checking is done by the
+ * _mesa_source/dest_buffer_exists() calls below. That's where we
+ * check if the stencil buffer exists, etc.
+ */
+ if (type != GL_COLOR &&
+ type != GL_DEPTH &&
+ type != GL_STENCIL &&
+ type != GL_DEPTH_STENCIL) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
+ return;
+ }
+
+ /* We're not using the current vertex program, and the driver may install
+ * it's own.
+ */
+ _mesa_set_vp_override(ctx, GL_TRUE);
+
if (ctx->NewState) {
_mesa_update_state(ctx);
}
- if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+ if (!valid_fragment_program(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyPixels (invalid fragment program)");
- return;
- }
-
- if (width < 0 || height < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
- return;
+ goto end;
}
if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
"glCopyPixels(incomplete framebuffer)" );
- return;
+ goto end;
}
if (!_mesa_source_buffer_exists(ctx, type) ||
!_mesa_dest_buffer_exists(ctx, type)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyPixels(missing source or dest buffer)");
- return;
+ goto end;
}
- if (!ctx->Current.RasterPosValid) {
- return;
+ if (!ctx->Current.RasterPosValid || width ==0 || height == 0) {
+ goto end; /* no-op, not an error */
}
if (ctx->RenderMode == GL_RENDER) {
/* Round to satisfy conformance tests (matches SGI's OpenGL) */
- GLint destx = IROUND(ctx->Current.RasterPos[0]);
- GLint desty = IROUND(ctx->Current.RasterPos[1]);
- ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
- type );
+ if (width > 0 && height > 0) {
+ GLint destx = IROUND(ctx->Current.RasterPos[0]);
+ GLint desty = IROUND(ctx->Current.RasterPos[1]);
+ ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
+ type );
+ }
}
else if (ctx->RenderMode == GL_FEEDBACK) {
FLUSH_CURRENT( ctx, 0 );
- FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
_mesa_feedback_vertex( ctx,
ctx->Current.RasterPos,
ctx->Current.RasterColor,
@@ -177,10 +221,10 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
ASSERT(ctx->RenderMode == GL_SELECT);
/* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
}
-}
-
-#endif /* _HAVE_FULL_GL */
+end:
+ _mesa_set_vp_override(ctx, GL_FALSE);
+}
void GLAPIENTRY
@@ -204,7 +248,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
_mesa_update_state(ctx);
}
- if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+ if (!valid_fragment_program(ctx)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBitmap (invalid fragment program)");
return;
@@ -218,32 +262,35 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
if (ctx->RenderMode == GL_RENDER) {
/* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
- const GLfloat epsilon = (const GLfloat)0.0001;
- GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
- GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
-
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack from PBO */
- if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
- GL_COLOR_INDEX, GL_BITMAP,
- (GLvoid *) bitmap)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBitmap(invalid PBO access)");
- return;
- }
- if (ctx->Unpack.BufferObj->Pointer) {
- /* buffer is mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
- return;
+ if (width > 0 && height > 0) {
+ const GLfloat epsilon = 0.0001F;
+ GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
+ GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
+
+ if (ctx->Unpack.BufferObj->Name) {
+ /* unpack from PBO */
+ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+ GL_COLOR_INDEX, GL_BITMAP,
+ (GLvoid *) bitmap)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBitmap(invalid PBO access)");
+ return;
+ }
+ if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBitmap(PBO is mapped)");
+ return;
+ }
}
- }
- ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
+ ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
+ }
}
#if _HAVE_FULL_GL
else if (ctx->RenderMode == GL_FEEDBACK) {
FLUSH_CURRENT(ctx, 0);
- FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
_mesa_feedback_vertex( ctx,
ctx->Current.RasterPos,
ctx->Current.RasterColor,
@@ -262,66 +309,13 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
}
-
-#if 0 /* experimental */
-/*
- * Execute glDrawDepthPixelsMESA(). This function accepts both a color
- * image and depth (Z) image. Rasterization produces fragments with
- * color and Z taken from these images. This function is intended for
- * Z-compositing. Normally, this operation requires two glDrawPixels
- * calls with stencil testing.
- */
-void GLAPIENTRY
-_mesa_DrawDepthPixelsMESA( GLsizei width, GLsizei height,
- GLenum colorFormat, GLenum colorType,
- const GLvoid *colors,
- GLenum depthType, const GLvoid *depths )
+void
+_mesa_init_drawpix_dispatch(struct _glapi_table *disp)
{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (width < 0 || height < 0) {
- _mesa_error( ctx, GL_INVALID_VALUE,
- "glDrawDepthPixelsMESA(width or height < 0" );
- return;
- }
-
- if (!ctx->Current.RasterPosValid) {
- return;
- }
-
- if (ctx->NewState) {
- _mesa_update_state(ctx);
- }
-
- if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
- "glDrawDepthPixelsMESA(incomplete framebuffer)");
- return;
- }
-
- if (ctx->RenderMode == GL_RENDER) {
- /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
- GLint x = IROUND(ctx->Current.RasterPos[0]);
- GLint y = IROUND(ctx->Current.RasterPos[1]);
- ctx->Driver.DrawDepthPixelsMESA(ctx, x, y, width, height,
- colorFormat, colorType, colors,
- depthType, depths, &ctx->Unpack);
- }
- else if (ctx->RenderMode == GL_FEEDBACK) {
- /* Feedback the current raster pos info */
- FLUSH_CURRENT( ctx, 0 );
- FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
- _mesa_feedback_vertex( ctx,
- ctx->Current.RasterPos,
- ctx->Current.RasterColor,
- ctx->Current.RasterIndex,
- ctx->Current.RasterTexCoords[0] );
- }
- else {
- ASSERT(ctx->RenderMode == GL_SELECT);
- /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
- }
+ SET_Bitmap(disp, _mesa_Bitmap);
+ SET_CopyPixels(disp, _mesa_CopyPixels);
+ SET_DrawPixels(disp, _mesa_DrawPixels);
}
-#endif
+
+#endif /* FEATURE_drawpix */
diff --git a/src/mesa/main/drawpix.h b/src/mesa/main/drawpix.h
index 6177adad6d..01564b3ed7 100644
--- a/src/mesa/main/drawpix.h
+++ b/src/mesa/main/drawpix.h
@@ -22,13 +22,21 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+#ifndef DRAWPIX_H
+#define DRAWPIX_H
-#ifndef DRAWPIXELS_H
-#define DRAWPIXELS_H
+#include "main/mtypes.h"
-#include "main/glheader.h"
+#if FEATURE_drawpix
+
+#define _MESA_INIT_DRAWPIX_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->DrawPixels = impl ## DrawPixels; \
+ (driver)->CopyPixels = impl ## CopyPixels; \
+ (driver)->Bitmap = impl ## Bitmap; \
+ } while (0)
extern void GLAPIENTRY
_mesa_DrawPixels( GLsizei width, GLsizei height,
@@ -45,5 +53,19 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
const GLubyte *bitmap );
+extern void
+_mesa_init_drawpix_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_drawpix */
+
+#define _MESA_INIT_DRAWPIX_FUNCTIONS(driver, impl) do { } while (0)
+
+static INLINE void
+_mesa_init_drawpix_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_drawpix */
+
-#endif
+#endif /* DRAWPIX_H */
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index dae576ae5a..4c1f46102d 100644
--- a/src/mesa/main/enable.c
+++ b/src/mesa/main/enable.c
@@ -36,8 +36,6 @@
#include "simple_list.h"
#include "mtypes.h"
#include "enums.h"
-#include "math/m_matrix.h"
-#include "math/m_xform.h"
#include "api_arrayelt.h"
@@ -120,6 +118,7 @@ client_state(GLcontext *ctx, GLenum cap, GLboolean state)
CHECK_EXTENSION(NV_vertex_program, cap);
{
GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
+ ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
var = &ctx->Array.ArrayObj->VertexAttrib[n].Enabled;
flag = _NEW_ARRAY_ATTRIB(n);
}
@@ -223,14 +222,16 @@ get_texcoord_unit(GLcontext *ctx)
/**
* Helper function to enable or disable a texture target.
+ * \param bit one of the TEXTURE_x_BIT values
+ * \return GL_TRUE if state is changing or GL_FALSE if no change
*/
static GLboolean
-enable_texture(GLcontext *ctx, GLboolean state, GLbitfield bit)
+enable_texture(GLcontext *ctx, GLboolean state, GLbitfield texBit)
{
const GLuint curr = ctx->Texture.CurrentUnit;
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr];
- const GLuint newenabled = (!state)
- ? (texUnit->Enabled & ~bit) : (texUnit->Enabled | bit);
+ const GLbitfield newenabled = state
+ ? (texUnit->Enabled | texBit) : (texUnit->Enabled & ~texBit);
if (!ctx->DrawBuffer->Visual.rgbMode || texUnit->Enabled == newenabled)
return GL_FALSE;
@@ -603,11 +604,6 @@ _mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state)
ctx->Texture.SharedPalette = state;
break;
case GL_STENCIL_TEST:
- if (state && ctx->DrawBuffer->Visual.stencilBits == 0) {
- _mesa_warning(ctx,
- "glEnable(GL_STENCIL_TEST) but no stencil buffer");
- return;
- }
if (ctx->Stencil.Enabled == state)
return;
FLUSH_VERTICES(ctx, _NEW_STENCIL);
@@ -772,35 +768,30 @@ _mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state)
/* GL_ARB_multisample */
case GL_MULTISAMPLE_ARB:
- CHECK_EXTENSION(ARB_multisample, cap);
if (ctx->Multisample.Enabled == state)
return;
FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
ctx->Multisample.Enabled = state;
break;
case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
- CHECK_EXTENSION(ARB_multisample, cap);
if (ctx->Multisample.SampleAlphaToCoverage == state)
return;
FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
ctx->Multisample.SampleAlphaToCoverage = state;
break;
case GL_SAMPLE_ALPHA_TO_ONE_ARB:
- CHECK_EXTENSION(ARB_multisample, cap);
if (ctx->Multisample.SampleAlphaToOne == state)
return;
FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
ctx->Multisample.SampleAlphaToOne = state;
break;
case GL_SAMPLE_COVERAGE_ARB:
- CHECK_EXTENSION(ARB_multisample, cap);
if (ctx->Multisample.SampleCoverage == state)
return;
FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
ctx->Multisample.SampleCoverage = state;
break;
case GL_SAMPLE_COVERAGE_INVERT_ARB:
- CHECK_EXTENSION(ARB_multisample, cap);
if (ctx->Multisample.SampleCoverageInvert == state)
return;
FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
@@ -922,10 +913,13 @@ _mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state)
return;
FLUSH_VERTICES(ctx, _NEW_STENCIL);
ctx->Stencil.TestTwoSide = state;
- if (state)
+ if (state) {
+ ctx->Stencil._BackFace = 2;
ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL;
- else
+ } else {
+ ctx->Stencil._BackFace = 1;
ctx->_TriangleCaps &= ~DD_TRI_TWOSTENCIL;
+ }
break;
#if FEATURE_ARB_fragment_program
@@ -952,15 +946,13 @@ _mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state)
ctx->Depth.BoundsTest = state;
break;
- /* GL_MESA_program_debug */
- case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
- CHECK_EXTENSION(MESA_program_debug, cap);
- ctx->FragmentProgram.CallbackEnabled = state;
- break;
- case GL_VERTEX_PROGRAM_CALLBACK_MESA:
- CHECK_EXTENSION(MESA_program_debug, cap);
- ctx->VertexProgram.CallbackEnabled = state;
- break;
+ case GL_DEPTH_CLAMP:
+ if (ctx->Transform.DepthClamp == state)
+ return;
+ CHECK_EXTENSION(ARB_depth_clamp, cap);
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.DepthClamp = state;
+ break;
#if FEATURE_ATI_fragment_shader
case GL_FRAGMENT_SHADER_ATI:
@@ -987,6 +979,11 @@ _mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state)
}
break;
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXTENSION(ARB_seamless_cube_map, cap);
+ ctx->Texture.CubeMapSeamless = state;
+ break;
+
default:
_mesa_error(ctx, GL_INVALID_ENUM,
"%s(0x%x)", state ? "glEnable" : "glDisable", cap);
@@ -1281,19 +1278,14 @@ _mesa_IsEnabled( GLenum cap )
/* GL_ARB_multisample */
case GL_MULTISAMPLE_ARB:
- CHECK_EXTENSION(ARB_multisample);
return ctx->Multisample.Enabled;
case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
- CHECK_EXTENSION(ARB_multisample);
return ctx->Multisample.SampleAlphaToCoverage;
case GL_SAMPLE_ALPHA_TO_ONE_ARB:
- CHECK_EXTENSION(ARB_multisample);
return ctx->Multisample.SampleAlphaToOne;
case GL_SAMPLE_COVERAGE_ARB:
- CHECK_EXTENSION(ARB_multisample);
return ctx->Multisample.SampleCoverage;
case GL_SAMPLE_COVERAGE_INVERT_ARB:
- CHECK_EXTENSION(ARB_multisample);
return ctx->Multisample.SampleCoverageInvert;
/* GL_IBM_rasterpos_clip */
@@ -1337,6 +1329,7 @@ _mesa_IsEnabled( GLenum cap )
CHECK_EXTENSION(NV_vertex_program);
{
GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
+ ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
return (ctx->Array.ArrayObj->VertexAttrib[n].Enabled != 0);
}
case GL_MAP1_VERTEX_ATTRIB0_4_NV:
@@ -1409,18 +1402,21 @@ _mesa_IsEnabled( GLenum cap )
CHECK_EXTENSION(EXT_depth_bounds_test);
return ctx->Depth.BoundsTest;
- /* GL_MESA_program_debug */
- case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
- CHECK_EXTENSION(MESA_program_debug);
- return ctx->FragmentProgram.CallbackEnabled;
- case GL_VERTEX_PROGRAM_CALLBACK_MESA:
- CHECK_EXTENSION(MESA_program_debug);
- return ctx->VertexProgram.CallbackEnabled;
+ /* GL_ARB_depth_clamp */
+ case GL_DEPTH_CLAMP:
+ CHECK_EXTENSION(ARB_depth_clamp);
+ return ctx->Transform.DepthClamp;
+
#if FEATURE_ATI_fragment_shader
case GL_FRAGMENT_SHADER_ATI:
CHECK_EXTENSION(ATI_fragment_shader);
return ctx->ATIFragmentShader.Enabled;
#endif /* FEATURE_ATI_fragment_shader */
+
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXTENSION(ARB_seamless_cube_map);
+ return ctx->Texture.CubeMapSeamless;
+
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap);
return GL_FALSE;
diff --git a/src/mesa/main/enums.c b/src/mesa/main/enums.c
index 4796f3027a..2d1594eb7a 100644
--- a/src/mesa/main/enums.c
+++ b/src/mesa/main/enums.c
@@ -26,6 +26,7 @@
*/
#include "glheader.h"
+#include "mfeatures.h"
#include "enums.h"
#include "imports.h"
@@ -81,6 +82,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_ALPHA_TEST\0"
"GL_ALPHA_TEST_FUNC\0"
"GL_ALPHA_TEST_REF\0"
+ "GL_ALREADY_SIGNALED\0"
"GL_ALWAYS\0"
"GL_AMBIENT\0"
"GL_AMBIENT_AND_DIFFUSE\0"
@@ -119,6 +121,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_BLEND_EQUATION_ALPHA\0"
"GL_BLEND_EQUATION_ALPHA_EXT\0"
"GL_BLEND_EQUATION_EXT\0"
+ "GL_BLEND_EQUATION_RGB\0"
"GL_BLEND_EQUATION_RGB_EXT\0"
"GL_BLEND_SRC\0"
"GL_BLEND_SRC_ALPHA\0"
@@ -137,14 +140,22 @@ LONGSTRING static const char enum_string_table[] =
"GL_BOOL_VEC4_ARB\0"
"GL_BUFFER_ACCESS\0"
"GL_BUFFER_ACCESS_ARB\0"
+ "GL_BUFFER_FLUSHING_UNMAP_APPLE\0"
"GL_BUFFER_MAPPED\0"
"GL_BUFFER_MAPPED_ARB\0"
"GL_BUFFER_MAP_POINTER\0"
"GL_BUFFER_MAP_POINTER_ARB\0"
+ "GL_BUFFER_SERIALIZED_MODIFY_APPLE\0"
"GL_BUFFER_SIZE\0"
"GL_BUFFER_SIZE_ARB\0"
"GL_BUFFER_USAGE\0"
"GL_BUFFER_USAGE_ARB\0"
+ "GL_BUMP_ENVMAP_ATI\0"
+ "GL_BUMP_NUM_TEX_UNITS_ATI\0"
+ "GL_BUMP_ROT_MATRIX_ATI\0"
+ "GL_BUMP_ROT_MATRIX_SIZE_ATI\0"
+ "GL_BUMP_TARGET_ATI\0"
+ "GL_BUMP_TEX_UNITS_ATI\0"
"GL_BYTE\0"
"GL_C3F_V3F\0"
"GL_C4F_N3F_V3F\0"
@@ -180,21 +191,37 @@ LONGSTRING static const char enum_string_table[] =
"GL_COLOR_ARRAY_SIZE\0"
"GL_COLOR_ARRAY_STRIDE\0"
"GL_COLOR_ARRAY_TYPE\0"
+ "GL_COLOR_ATTACHMENT0\0"
"GL_COLOR_ATTACHMENT0_EXT\0"
+ "GL_COLOR_ATTACHMENT1\0"
+ "GL_COLOR_ATTACHMENT10\0"
"GL_COLOR_ATTACHMENT10_EXT\0"
+ "GL_COLOR_ATTACHMENT11\0"
"GL_COLOR_ATTACHMENT11_EXT\0"
+ "GL_COLOR_ATTACHMENT12\0"
"GL_COLOR_ATTACHMENT12_EXT\0"
+ "GL_COLOR_ATTACHMENT13\0"
"GL_COLOR_ATTACHMENT13_EXT\0"
+ "GL_COLOR_ATTACHMENT14\0"
"GL_COLOR_ATTACHMENT14_EXT\0"
+ "GL_COLOR_ATTACHMENT15\0"
"GL_COLOR_ATTACHMENT15_EXT\0"
"GL_COLOR_ATTACHMENT1_EXT\0"
+ "GL_COLOR_ATTACHMENT2\0"
"GL_COLOR_ATTACHMENT2_EXT\0"
+ "GL_COLOR_ATTACHMENT3\0"
"GL_COLOR_ATTACHMENT3_EXT\0"
+ "GL_COLOR_ATTACHMENT4\0"
"GL_COLOR_ATTACHMENT4_EXT\0"
+ "GL_COLOR_ATTACHMENT5\0"
"GL_COLOR_ATTACHMENT5_EXT\0"
+ "GL_COLOR_ATTACHMENT6\0"
"GL_COLOR_ATTACHMENT6_EXT\0"
+ "GL_COLOR_ATTACHMENT7\0"
"GL_COLOR_ATTACHMENT7_EXT\0"
+ "GL_COLOR_ATTACHMENT8\0"
"GL_COLOR_ATTACHMENT8_EXT\0"
+ "GL_COLOR_ATTACHMENT9\0"
"GL_COLOR_ATTACHMENT9_EXT\0"
"GL_COLOR_BUFFER_BIT\0"
"GL_COLOR_CLEAR_VALUE\0"
@@ -274,7 +301,12 @@ LONGSTRING static const char enum_string_table[] =
"GL_COMPRESSED_RGB_ARB\0"
"GL_COMPRESSED_RGB_FXT1_3DFX\0"
"GL_COMPRESSED_RGB_S3TC_DXT1_EXT\0"
+ "GL_COMPRESSED_SLUMINANCE\0"
+ "GL_COMPRESSED_SLUMINANCE_ALPHA\0"
+ "GL_COMPRESSED_SRGB\0"
+ "GL_COMPRESSED_SRGB_ALPHA\0"
"GL_COMPRESSED_TEXTURE_FORMATS\0"
+ "GL_CONDITION_SATISFIED\0"
"GL_CONSTANT\0"
"GL_CONSTANT_ALPHA\0"
"GL_CONSTANT_ALPHA_EXT\0"
@@ -306,6 +338,8 @@ LONGSTRING static const char enum_string_table[] =
"GL_COPY\0"
"GL_COPY_INVERTED\0"
"GL_COPY_PIXEL_TOKEN\0"
+ "GL_COPY_READ_BUFFER\0"
+ "GL_COPY_WRITE_BUFFER\0"
"GL_CULL_FACE\0"
"GL_CULL_FACE_MODE\0"
"GL_CULL_VERTEX_EXT\0"
@@ -332,6 +366,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_CURRENT_RASTER_INDEX\0"
"GL_CURRENT_RASTER_POSITION\0"
"GL_CURRENT_RASTER_POSITION_VALID\0"
+ "GL_CURRENT_RASTER_SECONDARY_COLOR\0"
"GL_CURRENT_RASTER_TEXTURE_COORDS\0"
"GL_CURRENT_SECONDARY_COLOR\0"
"GL_CURRENT_TEXTURE_COORDS\0"
@@ -348,12 +383,15 @@ LONGSTRING static const char enum_string_table[] =
"GL_DECR_WRAP_EXT\0"
"GL_DELETE_STATUS\0"
"GL_DEPTH\0"
+ "GL_DEPTH24_STENCIL8\0"
+ "GL_DEPTH_ATTACHMENT\0"
"GL_DEPTH_ATTACHMENT_EXT\0"
"GL_DEPTH_BIAS\0"
"GL_DEPTH_BITS\0"
"GL_DEPTH_BOUNDS_EXT\0"
"GL_DEPTH_BOUNDS_TEST_EXT\0"
"GL_DEPTH_BUFFER_BIT\0"
+ "GL_DEPTH_CLAMP\0"
"GL_DEPTH_CLAMP_NV\0"
"GL_DEPTH_CLEAR_VALUE\0"
"GL_DEPTH_COMPONENT\0"
@@ -369,6 +407,8 @@ LONGSTRING static const char enum_string_table[] =
"GL_DEPTH_FUNC\0"
"GL_DEPTH_RANGE\0"
"GL_DEPTH_SCALE\0"
+ "GL_DEPTH_STENCIL\0"
+ "GL_DEPTH_STENCIL_ATTACHMENT\0"
"GL_DEPTH_STENCIL_NV\0"
"GL_DEPTH_STENCIL_TO_BGRA_NV\0"
"GL_DEPTH_STENCIL_TO_RGBA_NV\0"
@@ -437,11 +477,14 @@ LONGSTRING static const char enum_string_table[] =
"GL_DRAW_BUFFER9\0"
"GL_DRAW_BUFFER9_ARB\0"
"GL_DRAW_BUFFER9_ATI\0"
+ "GL_DRAW_FRAMEBUFFER\0"
"GL_DRAW_FRAMEBUFFER_BINDING_EXT\0"
"GL_DRAW_FRAMEBUFFER_EXT\0"
"GL_DRAW_PIXEL_TOKEN\0"
"GL_DST_ALPHA\0"
"GL_DST_COLOR\0"
+ "GL_DU8DV8_ATI\0"
+ "GL_DUDV_ATI\0"
"GL_DYNAMIC_COPY\0"
"GL_DYNAMIC_COPY_ARB\0"
"GL_DYNAMIC_DRAW\0"
@@ -476,14 +519,21 @@ LONGSTRING static const char enum_string_table[] =
"GL_FEEDBACK_BUFFER_SIZE\0"
"GL_FEEDBACK_BUFFER_TYPE\0"
"GL_FILL\0"
+ "GL_FIRST_VERTEX_CONVENTION_EXT\0"
"GL_FLAT\0"
"GL_FLOAT\0"
"GL_FLOAT_MAT2\0"
"GL_FLOAT_MAT2_ARB\0"
+ "GL_FLOAT_MAT2x3\0"
+ "GL_FLOAT_MAT2x4\0"
"GL_FLOAT_MAT3\0"
"GL_FLOAT_MAT3_ARB\0"
+ "GL_FLOAT_MAT3x2\0"
+ "GL_FLOAT_MAT3x4\0"
"GL_FLOAT_MAT4\0"
"GL_FLOAT_MAT4_ARB\0"
+ "GL_FLOAT_MAT4x2\0"
+ "GL_FLOAT_MAT4x3\0"
"GL_FLOAT_VEC2\0"
"GL_FLOAT_VEC2_ARB\0"
"GL_FLOAT_VEC3\0"
@@ -522,23 +572,44 @@ LONGSTRING static const char enum_string_table[] =
"GL_FRAGMENT_SHADER\0"
"GL_FRAGMENT_SHADER_ARB\0"
"GL_FRAGMENT_SHADER_DERIVATIVE_HINT\0"
+ "GL_FRAMEBUFFER\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME\0"
"GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE\0"
"GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE\0"
"GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE\0"
"GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER\0"
"GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL\0"
"GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT\0"
"GL_FRAMEBUFFER_BINDING_EXT\0"
+ "GL_FRAMEBUFFER_COMPLETE\0"
"GL_FRAMEBUFFER_COMPLETE_EXT\0"
+ "GL_FRAMEBUFFER_DEFAULT\0"
"GL_FRAMEBUFFER_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\0"
"GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\0"
"GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\0"
"GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\0"
"GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT\0"
"GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\0"
"GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE\0"
"GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\0"
"GL_FRAMEBUFFER_STATUS_ERROR_EXT\0"
+ "GL_FRAMEBUFFER_UNDEFINED\0"
+ "GL_FRAMEBUFFER_UNSUPPORTED\0"
"GL_FRAMEBUFFER_UNSUPPORTED_EXT\0"
"GL_FRONT\0"
"GL_FRONT_AND_BACK\0"
@@ -556,30 +627,6 @@ LONGSTRING static const char enum_string_table[] =
"GL_GENERATE_MIPMAP_HINT_SGIS\0"
"GL_GENERATE_MIPMAP_SGIS\0"
"GL_GEQUAL\0"
- "GL_GL_BLEND_EQUATION_RGB\0"
- "GL_GL_COMPRESSED_SLUMINANCE\0"
- "GL_GL_COMPRESSED_SLUMINANCE_ALPHA\0"
- "GL_GL_COMPRESSED_SRGB\0"
- "GL_GL_COMPRESSED_SRGB_ALPHA\0"
- "GL_GL_CURRENT_RASTER_SECONDARY_COLOR\0"
- "GL_GL_FLOAT_MAT2x3\0"
- "GL_GL_FLOAT_MAT2x4\0"
- "GL_GL_FLOAT_MAT3x2\0"
- "GL_GL_FLOAT_MAT3x4\0"
- "GL_GL_FLOAT_MAT4x2\0"
- "GL_GL_FLOAT_MAT4x3\0"
- "GL_GL_PIXEL_PACK_BUFFER\0"
- "GL_GL_PIXEL_PACK_BUFFER_BINDING\0"
- "GL_GL_PIXEL_UNPACK_BUFFER\0"
- "GL_GL_PIXEL_UNPACK_BUFFER_BINDING\0"
- "GL_GL_SLUMINANCE\0"
- "GL_GL_SLUMINANCE8\0"
- "GL_GL_SLUMINANCE8_ALPHA8\0"
- "GL_GL_SLUMINANCE_ALPHA\0"
- "GL_GL_SRGB\0"
- "GL_GL_SRGB8\0"
- "GL_GL_SRGB8_ALPHA8\0"
- "GL_GL_SRGB_ALPHA\0"
"GL_GREATER\0"
"GL_GREEN\0"
"GL_GREEN_BIAS\0"
@@ -611,6 +658,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_INCR\0"
"GL_INCR_WRAP\0"
"GL_INCR_WRAP_EXT\0"
+ "GL_INDEX\0"
"GL_INDEX_ARRAY\0"
"GL_INDEX_ARRAY_BUFFER_BINDING\0"
"GL_INDEX_ARRAY_BUFFER_BINDING_ARB\0"
@@ -646,6 +694,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_INT_VEC4\0"
"GL_INT_VEC4_ARB\0"
"GL_INVALID_ENUM\0"
+ "GL_INVALID_FRAMEBUFFER_OPERATION\0"
"GL_INVALID_FRAMEBUFFER_OPERATION_EXT\0"
"GL_INVALID_OPERATION\0"
"GL_INVALID_VALUE\0"
@@ -653,6 +702,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_INVERSE_TRANSPOSE_NV\0"
"GL_INVERT\0"
"GL_KEEP\0"
+ "GL_LAST_VERTEX_CONVENTION_EXT\0"
"GL_LEFT\0"
"GL_LEQUAL\0"
"GL_LESS\0"
@@ -778,7 +828,13 @@ LONGSTRING static const char enum_string_table[] =
"GL_MAP2_VERTEX_ATTRIB8_4_NV\0"
"GL_MAP2_VERTEX_ATTRIB9_4_NV\0"
"GL_MAP_COLOR\0"
+ "GL_MAP_FLUSH_EXPLICIT_BIT\0"
+ "GL_MAP_INVALIDATE_BUFFER_BIT\0"
+ "GL_MAP_INVALIDATE_RANGE_BIT\0"
+ "GL_MAP_READ_BIT\0"
"GL_MAP_STENCIL\0"
+ "GL_MAP_UNSYNCHRONIZED_BIT\0"
+ "GL_MAP_WRITE_BIT\0"
"GL_MATRIX0_ARB\0"
"GL_MATRIX0_NV\0"
"GL_MATRIX10_ARB\0"
@@ -890,6 +946,8 @@ LONGSTRING static const char enum_string_table[] =
"GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB\0"
"GL_MAX_RECTANGLE_TEXTURE_SIZE_NV\0"
"GL_MAX_RENDERBUFFER_SIZE_EXT\0"
+ "GL_MAX_SAMPLES\0"
+ "GL_MAX_SERVER_WAIT_TIMEOUT\0"
"GL_MAX_SHININESS_NV\0"
"GL_MAX_SPOT_EXPONENT_NV\0"
"GL_MAX_TEXTURE_COORDS\0"
@@ -1018,6 +1076,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_OBJECT_PLANE\0"
"GL_OBJECT_SHADER_SOURCE_LENGTH_ARB\0"
"GL_OBJECT_SUBTYPE_ARB\0"
+ "GL_OBJECT_TYPE\0"
"GL_OBJECT_TYPE_ARB\0"
"GL_OBJECT_VALIDATE_STATUS_ARB\0"
"GL_OCCLUSION_TEST_HP\0"
@@ -1098,8 +1157,12 @@ LONGSTRING static const char enum_string_table[] =
"GL_PIXEL_MAP_S_TO_S\0"
"GL_PIXEL_MAP_S_TO_S_SIZE\0"
"GL_PIXEL_MODE_BIT\0"
+ "GL_PIXEL_PACK_BUFFER\0"
+ "GL_PIXEL_PACK_BUFFER_BINDING\0"
"GL_PIXEL_PACK_BUFFER_BINDING_EXT\0"
"GL_PIXEL_PACK_BUFFER_EXT\0"
+ "GL_PIXEL_UNPACK_BUFFER\0"
+ "GL_PIXEL_UNPACK_BUFFER_BINDING\0"
"GL_PIXEL_UNPACK_BUFFER_BINDING_EXT\0"
"GL_PIXEL_UNPACK_BUFFER_EXT\0"
"GL_POINT\0"
@@ -1225,6 +1288,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_PROJECTION\0"
"GL_PROJECTION_MATRIX\0"
"GL_PROJECTION_STACK_DEPTH\0"
+ "GL_PROVOKING_VERTEX_EXT\0"
"GL_PROXY_COLOR_TABLE\0"
"GL_PROXY_HISTOGRAM\0"
"GL_PROXY_HISTOGRAM_EXT\0"
@@ -1245,6 +1309,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_Q\0"
"GL_QUADRATIC_ATTENUATION\0"
"GL_QUADS\0"
+ "GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT\0"
"GL_QUAD_MESH_SUN\0"
"GL_QUAD_STRIP\0"
"GL_QUERY_COUNTER_BITS\0"
@@ -1257,6 +1322,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_R3_G3_B2\0"
"GL_RASTER_POSITION_UNCLIPPED_IBM\0"
"GL_READ_BUFFER\0"
+ "GL_READ_FRAMEBUFFER\0"
"GL_READ_FRAMEBUFFER_BINDING_EXT\0"
"GL_READ_FRAMEBUFFER_EXT\0"
"GL_READ_ONLY\0"
@@ -1273,10 +1339,21 @@ LONGSTRING static const char enum_string_table[] =
"GL_REFLECTION_MAP_ARB\0"
"GL_REFLECTION_MAP_NV\0"
"GL_RENDER\0"
+ "GL_RENDERBUFFER\0"
+ "GL_RENDERBUFFER_ALPHA_SIZE\0"
"GL_RENDERBUFFER_BINDING_EXT\0"
+ "GL_RENDERBUFFER_BLUE_SIZE\0"
+ "GL_RENDERBUFFER_DEPTH_SIZE\0"
"GL_RENDERBUFFER_EXT\0"
+ "GL_RENDERBUFFER_GREEN_SIZE\0"
+ "GL_RENDERBUFFER_HEIGHT\0"
"GL_RENDERBUFFER_HEIGHT_EXT\0"
+ "GL_RENDERBUFFER_INTERNAL_FORMAT\0"
"GL_RENDERBUFFER_INTERNAL_FORMAT_EXT\0"
+ "GL_RENDERBUFFER_RED_SIZE\0"
+ "GL_RENDERBUFFER_SAMPLES\0"
+ "GL_RENDERBUFFER_STENCIL_SIZE\0"
+ "GL_RENDERBUFFER_WIDTH\0"
"GL_RENDERBUFFER_WIDTH_EXT\0"
"GL_RENDERER\0"
"GL_RENDER_MODE\0"
@@ -1319,9 +1396,11 @@ LONGSTRING static const char enum_string_table[] =
"GL_RGBA4_S3TC\0"
"GL_RGBA8\0"
"GL_RGBA8_EXT\0"
+ "GL_RGBA8_SNORM\0"
"GL_RGBA_DXT5_S3TC\0"
"GL_RGBA_MODE\0"
"GL_RGBA_S3TC\0"
+ "GL_RGBA_SNORM\0"
"GL_RGB_S3TC\0"
"GL_RGB_SCALE\0"
"GL_RGB_SCALE_ARB\0"
@@ -1378,9 +1457,15 @@ LONGSTRING static const char enum_string_table[] =
"GL_SHARED_TEXTURE_PALETTE_EXT\0"
"GL_SHININESS\0"
"GL_SHORT\0"
+ "GL_SIGNALED\0"
+ "GL_SIGNED_NORMALIZED\0"
"GL_SINGLE_COLOR\0"
"GL_SINGLE_COLOR_EXT\0"
"GL_SLICE_ACCUM_SUN\0"
+ "GL_SLUMINANCE\0"
+ "GL_SLUMINANCE8\0"
+ "GL_SLUMINANCE8_ALPHA8\0"
+ "GL_SLUMINANCE_ALPHA\0"
"GL_SMOOTH\0"
"GL_SMOOTH_LINE_WIDTH_GRANULARITY\0"
"GL_SMOOTH_LINE_WIDTH_RANGE\0"
@@ -1420,6 +1505,10 @@ LONGSTRING static const char enum_string_table[] =
"GL_SRC_ALPHA\0"
"GL_SRC_ALPHA_SATURATE\0"
"GL_SRC_COLOR\0"
+ "GL_SRGB\0"
+ "GL_SRGB8\0"
+ "GL_SRGB8_ALPHA8\0"
+ "GL_SRGB_ALPHA\0"
"GL_STACK_OVERFLOW\0"
"GL_STACK_UNDERFLOW\0"
"GL_STATIC_COPY\0"
@@ -1429,6 +1518,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_STATIC_READ\0"
"GL_STATIC_READ_ARB\0"
"GL_STENCIL\0"
+ "GL_STENCIL_ATTACHMENT\0"
"GL_STENCIL_ATTACHMENT_EXT\0"
"GL_STENCIL_BACK_FAIL\0"
"GL_STENCIL_BACK_FAIL_ATI\0"
@@ -1460,6 +1550,9 @@ LONGSTRING static const char enum_string_table[] =
"GL_STENCIL_VALUE_MASK\0"
"GL_STENCIL_WRITEMASK\0"
"GL_STEREO\0"
+ "GL_STORAGE_CACHED_APPLE\0"
+ "GL_STORAGE_PRIVATE_APPLE\0"
+ "GL_STORAGE_SHARED_APPLE\0"
"GL_STREAM_COPY\0"
"GL_STREAM_COPY_ARB\0"
"GL_STREAM_DRAW\0"
@@ -1469,6 +1562,12 @@ LONGSTRING static const char enum_string_table[] =
"GL_SUBPIXEL_BITS\0"
"GL_SUBTRACT\0"
"GL_SUBTRACT_ARB\0"
+ "GL_SYNC_CONDITION\0"
+ "GL_SYNC_FENCE\0"
+ "GL_SYNC_FLAGS\0"
+ "GL_SYNC_FLUSH_COMMANDS_BIT\0"
+ "GL_SYNC_GPU_COMMANDS_COMPLETE\0"
+ "GL_SYNC_STATUS\0"
"GL_T\0"
"GL_T2F_C3F_V3F\0"
"GL_T2F_C4F_N3F_V3F\0"
@@ -1609,6 +1708,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\0"
"GL_TEXTURE_CUBE_MAP_POSITIVE_Z\0"
"GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\0"
+ "GL_TEXTURE_CUBE_MAP_SEAMLESS\0"
"GL_TEXTURE_DEPTH\0"
"GL_TEXTURE_DEPTH_SIZE\0"
"GL_TEXTURE_DEPTH_SIZE_ARB\0"
@@ -1648,18 +1748,24 @@ LONGSTRING static const char enum_string_table[] =
"GL_TEXTURE_MIN_FILTER\0"
"GL_TEXTURE_MIN_LOD\0"
"GL_TEXTURE_PRIORITY\0"
+ "GL_TEXTURE_RANGE_LENGTH_APPLE\0"
+ "GL_TEXTURE_RANGE_POINTER_APPLE\0"
"GL_TEXTURE_RECTANGLE_ARB\0"
"GL_TEXTURE_RECTANGLE_NV\0"
"GL_TEXTURE_RED_SIZE\0"
"GL_TEXTURE_RED_SIZE_EXT\0"
"GL_TEXTURE_RESIDENT\0"
"GL_TEXTURE_STACK_DEPTH\0"
+ "GL_TEXTURE_STENCIL_SIZE\0"
+ "GL_TEXTURE_STORAGE_HINT_APPLE\0"
"GL_TEXTURE_TOO_LARGE_EXT\0"
"GL_TEXTURE_UNSIGNED_REMAP_MODE_NV\0"
"GL_TEXTURE_WIDTH\0"
"GL_TEXTURE_WRAP_R\0"
"GL_TEXTURE_WRAP_S\0"
"GL_TEXTURE_WRAP_T\0"
+ "GL_TIMEOUT_EXPIRED\0"
+ "GL_TIMEOUT_IGNORED\0"
"GL_TIME_ELAPSED_EXT\0"
"GL_TRACK_MATRIX_NV\0"
"GL_TRACK_MATRIX_TRANSFORM_NV\0"
@@ -1687,15 +1793,18 @@ LONGSTRING static const char enum_string_table[] =
"GL_UNPACK_SKIP_PIXELS\0"
"GL_UNPACK_SKIP_ROWS\0"
"GL_UNPACK_SWAP_BYTES\0"
+ "GL_UNSIGNALED\0"
"GL_UNSIGNED_BYTE\0"
"GL_UNSIGNED_BYTE_2_3_3_REV\0"
"GL_UNSIGNED_BYTE_3_3_2\0"
"GL_UNSIGNED_INT\0"
"GL_UNSIGNED_INT_10_10_10_2\0"
+ "GL_UNSIGNED_INT_24_8\0"
"GL_UNSIGNED_INT_24_8_NV\0"
"GL_UNSIGNED_INT_2_10_10_10_REV\0"
"GL_UNSIGNED_INT_8_8_8_8\0"
"GL_UNSIGNED_INT_8_8_8_8_REV\0"
+ "GL_UNSIGNED_NORMALIZED\0"
"GL_UNSIGNED_SHORT\0"
"GL_UNSIGNED_SHORT_1_5_5_5_REV\0"
"GL_UNSIGNED_SHORT_4_4_4_4\0"
@@ -1714,6 +1823,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_VENDOR\0"
"GL_VERSION\0"
"GL_VERTEX_ARRAY\0"
+ "GL_VERTEX_ARRAY_BINDING\0"
"GL_VERTEX_ARRAY_BINDING_APPLE\0"
"GL_VERTEX_ARRAY_BUFFER_BINDING\0"
"GL_VERTEX_ARRAY_BUFFER_BINDING_ARB\0"
@@ -1766,6 +1876,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_VERTEX_STATE_PROGRAM_NV\0"
"GL_VIEWPORT\0"
"GL_VIEWPORT_BIT\0"
+ "GL_WAIT_FAILED\0"
"GL_WEIGHT_ARRAY_ARB\0"
"GL_WEIGHT_ARRAY_BUFFER_BINDING\0"
"GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB\0"
@@ -1785,7 +1896,7 @@ LONGSTRING static const char enum_string_table[] =
"GL_ZOOM_Y\0"
;
-static const enum_elt all_enums[1748] =
+static const enum_elt all_enums[1858] =
{
{ 0, 0x00000600 }, /* GL_2D */
{ 6, 0x00001407 }, /* GL_2_BYTES */
@@ -1833,3000 +1944,3171 @@ static const enum_elt all_enums[1748] =
{ 728, 0x00000BC0 }, /* GL_ALPHA_TEST */
{ 742, 0x00000BC1 }, /* GL_ALPHA_TEST_FUNC */
{ 761, 0x00000BC2 }, /* GL_ALPHA_TEST_REF */
- { 779, 0x00000207 }, /* GL_ALWAYS */
- { 789, 0x00001200 }, /* GL_AMBIENT */
- { 800, 0x00001602 }, /* GL_AMBIENT_AND_DIFFUSE */
- { 823, 0x00001501 }, /* GL_AND */
- { 830, 0x00001504 }, /* GL_AND_INVERTED */
- { 846, 0x00001502 }, /* GL_AND_REVERSE */
- { 861, 0x00008892 }, /* GL_ARRAY_BUFFER */
- { 877, 0x00008894 }, /* GL_ARRAY_BUFFER_BINDING */
- { 901, 0x00008894 }, /* GL_ARRAY_BUFFER_BINDING_ARB */
- { 929, 0x00008B85 }, /* GL_ATTACHED_SHADERS */
- { 949, 0x00008645 }, /* GL_ATTRIB_ARRAY_POINTER_NV */
- { 976, 0x00008623 }, /* GL_ATTRIB_ARRAY_SIZE_NV */
- { 1000, 0x00008624 }, /* GL_ATTRIB_ARRAY_STRIDE_NV */
- { 1026, 0x00008625 }, /* GL_ATTRIB_ARRAY_TYPE_NV */
- { 1050, 0x00000BB0 }, /* GL_ATTRIB_STACK_DEPTH */
- { 1072, 0x00000D80 }, /* GL_AUTO_NORMAL */
- { 1087, 0x00000409 }, /* GL_AUX0 */
- { 1095, 0x0000040A }, /* GL_AUX1 */
- { 1103, 0x0000040B }, /* GL_AUX2 */
- { 1111, 0x0000040C }, /* GL_AUX3 */
- { 1119, 0x00000C00 }, /* GL_AUX_BUFFERS */
- { 1134, 0x00000405 }, /* GL_BACK */
- { 1142, 0x00000402 }, /* GL_BACK_LEFT */
- { 1155, 0x00000403 }, /* GL_BACK_RIGHT */
- { 1169, 0x000080E0 }, /* GL_BGR */
- { 1176, 0x000080E1 }, /* GL_BGRA */
- { 1184, 0x00001A00 }, /* GL_BITMAP */
- { 1194, 0x00000704 }, /* GL_BITMAP_TOKEN */
- { 1210, 0x00000BE2 }, /* GL_BLEND */
- { 1219, 0x00008005 }, /* GL_BLEND_COLOR */
- { 1234, 0x00008005 }, /* GL_BLEND_COLOR_EXT */
- { 1253, 0x00000BE0 }, /* GL_BLEND_DST */
- { 1266, 0x000080CA }, /* GL_BLEND_DST_ALPHA */
- { 1285, 0x000080C8 }, /* GL_BLEND_DST_RGB */
- { 1302, 0x00008009 }, /* GL_BLEND_EQUATION */
- { 1320, 0x0000883D }, /* GL_BLEND_EQUATION_ALPHA */
- { 1344, 0x0000883D }, /* GL_BLEND_EQUATION_ALPHA_EXT */
- { 1372, 0x00008009 }, /* GL_BLEND_EQUATION_EXT */
- { 1394, 0x00008009 }, /* GL_BLEND_EQUATION_RGB_EXT */
- { 1420, 0x00000BE1 }, /* GL_BLEND_SRC */
- { 1433, 0x000080CB }, /* GL_BLEND_SRC_ALPHA */
- { 1452, 0x000080C9 }, /* GL_BLEND_SRC_RGB */
- { 1469, 0x00001905 }, /* GL_BLUE */
- { 1477, 0x00000D1B }, /* GL_BLUE_BIAS */
- { 1490, 0x00000D54 }, /* GL_BLUE_BITS */
- { 1503, 0x00000D1A }, /* GL_BLUE_SCALE */
- { 1517, 0x00008B56 }, /* GL_BOOL */
- { 1525, 0x00008B56 }, /* GL_BOOL_ARB */
- { 1537, 0x00008B57 }, /* GL_BOOL_VEC2 */
- { 1550, 0x00008B57 }, /* GL_BOOL_VEC2_ARB */
- { 1567, 0x00008B58 }, /* GL_BOOL_VEC3 */
- { 1580, 0x00008B58 }, /* GL_BOOL_VEC3_ARB */
- { 1597, 0x00008B59 }, /* GL_BOOL_VEC4 */
- { 1610, 0x00008B59 }, /* GL_BOOL_VEC4_ARB */
- { 1627, 0x000088BB }, /* GL_BUFFER_ACCESS */
- { 1644, 0x000088BB }, /* GL_BUFFER_ACCESS_ARB */
- { 1665, 0x000088BC }, /* GL_BUFFER_MAPPED */
- { 1682, 0x000088BC }, /* GL_BUFFER_MAPPED_ARB */
- { 1703, 0x000088BD }, /* GL_BUFFER_MAP_POINTER */
- { 1725, 0x000088BD }, /* GL_BUFFER_MAP_POINTER_ARB */
- { 1751, 0x00008764 }, /* GL_BUFFER_SIZE */
- { 1766, 0x00008764 }, /* GL_BUFFER_SIZE_ARB */
- { 1785, 0x00008765 }, /* GL_BUFFER_USAGE */
- { 1801, 0x00008765 }, /* GL_BUFFER_USAGE_ARB */
- { 1821, 0x00001400 }, /* GL_BYTE */
- { 1829, 0x00002A24 }, /* GL_C3F_V3F */
- { 1840, 0x00002A26 }, /* GL_C4F_N3F_V3F */
- { 1855, 0x00002A22 }, /* GL_C4UB_V2F */
- { 1867, 0x00002A23 }, /* GL_C4UB_V3F */
- { 1879, 0x00000901 }, /* GL_CCW */
- { 1886, 0x00002900 }, /* GL_CLAMP */
- { 1895, 0x0000812D }, /* GL_CLAMP_TO_BORDER */
- { 1914, 0x0000812D }, /* GL_CLAMP_TO_BORDER_ARB */
- { 1937, 0x0000812D }, /* GL_CLAMP_TO_BORDER_SGIS */
- { 1961, 0x0000812F }, /* GL_CLAMP_TO_EDGE */
- { 1978, 0x0000812F }, /* GL_CLAMP_TO_EDGE_SGIS */
- { 2000, 0x00001500 }, /* GL_CLEAR */
- { 2009, 0x000084E1 }, /* GL_CLIENT_ACTIVE_TEXTURE */
- { 2034, 0x000084E1 }, /* GL_CLIENT_ACTIVE_TEXTURE_ARB */
- { 2063, 0xFFFFFFFF }, /* GL_CLIENT_ALL_ATTRIB_BITS */
- { 2089, 0x00000BB1 }, /* GL_CLIENT_ATTRIB_STACK_DEPTH */
- { 2118, 0x00000001 }, /* GL_CLIENT_PIXEL_STORE_BIT */
- { 2144, 0x00000002 }, /* GL_CLIENT_VERTEX_ARRAY_BIT */
- { 2171, 0x00003000 }, /* GL_CLIP_PLANE0 */
- { 2186, 0x00003001 }, /* GL_CLIP_PLANE1 */
- { 2201, 0x00003002 }, /* GL_CLIP_PLANE2 */
- { 2216, 0x00003003 }, /* GL_CLIP_PLANE3 */
- { 2231, 0x00003004 }, /* GL_CLIP_PLANE4 */
- { 2246, 0x00003005 }, /* GL_CLIP_PLANE5 */
- { 2261, 0x000080F0 }, /* GL_CLIP_VOLUME_CLIPPING_HINT_EXT */
- { 2294, 0x00000A00 }, /* GL_COEFF */
- { 2303, 0x00001800 }, /* GL_COLOR */
- { 2312, 0x00008076 }, /* GL_COLOR_ARRAY */
- { 2327, 0x00008898 }, /* GL_COLOR_ARRAY_BUFFER_BINDING */
- { 2357, 0x00008898 }, /* GL_COLOR_ARRAY_BUFFER_BINDING_ARB */
- { 2391, 0x00008090 }, /* GL_COLOR_ARRAY_POINTER */
- { 2414, 0x00008081 }, /* GL_COLOR_ARRAY_SIZE */
- { 2434, 0x00008083 }, /* GL_COLOR_ARRAY_STRIDE */
- { 2456, 0x00008082 }, /* GL_COLOR_ARRAY_TYPE */
- { 2476, 0x00008CE0 }, /* GL_COLOR_ATTACHMENT0_EXT */
- { 2501, 0x00008CEA }, /* GL_COLOR_ATTACHMENT10_EXT */
- { 2527, 0x00008CEB }, /* GL_COLOR_ATTACHMENT11_EXT */
- { 2553, 0x00008CEC }, /* GL_COLOR_ATTACHMENT12_EXT */
- { 2579, 0x00008CED }, /* GL_COLOR_ATTACHMENT13_EXT */
- { 2605, 0x00008CEE }, /* GL_COLOR_ATTACHMENT14_EXT */
- { 2631, 0x00008CEF }, /* GL_COLOR_ATTACHMENT15_EXT */
- { 2657, 0x00008CE1 }, /* GL_COLOR_ATTACHMENT1_EXT */
- { 2682, 0x00008CE2 }, /* GL_COLOR_ATTACHMENT2_EXT */
- { 2707, 0x00008CE3 }, /* GL_COLOR_ATTACHMENT3_EXT */
- { 2732, 0x00008CE4 }, /* GL_COLOR_ATTACHMENT4_EXT */
- { 2757, 0x00008CE5 }, /* GL_COLOR_ATTACHMENT5_EXT */
- { 2782, 0x00008CE6 }, /* GL_COLOR_ATTACHMENT6_EXT */
- { 2807, 0x00008CE7 }, /* GL_COLOR_ATTACHMENT7_EXT */
- { 2832, 0x00008CE8 }, /* GL_COLOR_ATTACHMENT8_EXT */
- { 2857, 0x00008CE9 }, /* GL_COLOR_ATTACHMENT9_EXT */
- { 2882, 0x00004000 }, /* GL_COLOR_BUFFER_BIT */
- { 2902, 0x00000C22 }, /* GL_COLOR_CLEAR_VALUE */
- { 2923, 0x00001900 }, /* GL_COLOR_INDEX */
- { 2938, 0x00001603 }, /* GL_COLOR_INDEXES */
- { 2955, 0x00000BF2 }, /* GL_COLOR_LOGIC_OP */
- { 2973, 0x00000B57 }, /* GL_COLOR_MATERIAL */
- { 2991, 0x00000B55 }, /* GL_COLOR_MATERIAL_FACE */
- { 3014, 0x00000B56 }, /* GL_COLOR_MATERIAL_PARAMETER */
- { 3042, 0x000080B1 }, /* GL_COLOR_MATRIX */
- { 3058, 0x000080B1 }, /* GL_COLOR_MATRIX_SGI */
- { 3078, 0x000080B2 }, /* GL_COLOR_MATRIX_STACK_DEPTH */
- { 3106, 0x000080B2 }, /* GL_COLOR_MATRIX_STACK_DEPTH_SGI */
- { 3138, 0x00008458 }, /* GL_COLOR_SUM */
- { 3151, 0x00008458 }, /* GL_COLOR_SUM_ARB */
- { 3168, 0x000080D0 }, /* GL_COLOR_TABLE */
- { 3183, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE */
- { 3209, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE_EXT */
- { 3239, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE_SGI */
- { 3269, 0x000080D7 }, /* GL_COLOR_TABLE_BIAS */
- { 3289, 0x000080D7 }, /* GL_COLOR_TABLE_BIAS_SGI */
- { 3313, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE */
- { 3338, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE_EXT */
- { 3367, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE_SGI */
- { 3396, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT */
- { 3418, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT_EXT */
- { 3444, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT_SGI */
- { 3470, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE */
- { 3496, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE_EXT */
- { 3526, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE_SGI */
- { 3556, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE */
- { 3586, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE_EXT */
- { 3620, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE_SGI */
- { 3654, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE */
- { 3684, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE_EXT */
- { 3718, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE_SGI */
- { 3752, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE */
- { 3776, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE_EXT */
- { 3804, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE_SGI */
- { 3832, 0x000080D6 }, /* GL_COLOR_TABLE_SCALE */
- { 3853, 0x000080D6 }, /* GL_COLOR_TABLE_SCALE_SGI */
- { 3878, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH */
- { 3899, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH_EXT */
- { 3924, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH_SGI */
- { 3949, 0x00000C23 }, /* GL_COLOR_WRITEMASK */
- { 3968, 0x00008570 }, /* GL_COMBINE */
- { 3979, 0x00008503 }, /* GL_COMBINE4 */
- { 3991, 0x00008572 }, /* GL_COMBINE_ALPHA */
- { 4008, 0x00008572 }, /* GL_COMBINE_ALPHA_ARB */
- { 4029, 0x00008572 }, /* GL_COMBINE_ALPHA_EXT */
- { 4050, 0x00008570 }, /* GL_COMBINE_ARB */
- { 4065, 0x00008570 }, /* GL_COMBINE_EXT */
- { 4080, 0x00008571 }, /* GL_COMBINE_RGB */
- { 4095, 0x00008571 }, /* GL_COMBINE_RGB_ARB */
- { 4114, 0x00008571 }, /* GL_COMBINE_RGB_EXT */
- { 4133, 0x0000884E }, /* GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT */
- { 4169, 0x0000884E }, /* GL_COMPARE_R_TO_TEXTURE */
- { 4193, 0x0000884E }, /* GL_COMPARE_R_TO_TEXTURE_ARB */
- { 4221, 0x00001300 }, /* GL_COMPILE */
- { 4232, 0x00001301 }, /* GL_COMPILE_AND_EXECUTE */
- { 4255, 0x00008B81 }, /* GL_COMPILE_STATUS */
- { 4273, 0x000084E9 }, /* GL_COMPRESSED_ALPHA */
- { 4293, 0x000084E9 }, /* GL_COMPRESSED_ALPHA_ARB */
- { 4317, 0x000084EC }, /* GL_COMPRESSED_INTENSITY */
- { 4341, 0x000084EC }, /* GL_COMPRESSED_INTENSITY_ARB */
- { 4369, 0x000084EA }, /* GL_COMPRESSED_LUMINANCE */
- { 4393, 0x000084EB }, /* GL_COMPRESSED_LUMINANCE_ALPHA */
- { 4423, 0x000084EB }, /* GL_COMPRESSED_LUMINANCE_ALPHA_ARB */
- { 4457, 0x000084EA }, /* GL_COMPRESSED_LUMINANCE_ARB */
- { 4485, 0x000084ED }, /* GL_COMPRESSED_RGB */
- { 4503, 0x000084EE }, /* GL_COMPRESSED_RGBA */
- { 4522, 0x000084EE }, /* GL_COMPRESSED_RGBA_ARB */
- { 4545, 0x000086B1 }, /* GL_COMPRESSED_RGBA_FXT1_3DFX */
- { 4574, 0x000083F1 }, /* GL_COMPRESSED_RGBA_S3TC_DXT1_EXT */
- { 4607, 0x000083F2 }, /* GL_COMPRESSED_RGBA_S3TC_DXT3_EXT */
- { 4640, 0x000083F3 }, /* GL_COMPRESSED_RGBA_S3TC_DXT5_EXT */
- { 4673, 0x000084ED }, /* GL_COMPRESSED_RGB_ARB */
- { 4695, 0x000086B0 }, /* GL_COMPRESSED_RGB_FXT1_3DFX */
- { 4723, 0x000083F0 }, /* GL_COMPRESSED_RGB_S3TC_DXT1_EXT */
- { 4755, 0x000086A3 }, /* GL_COMPRESSED_TEXTURE_FORMATS */
- { 4785, 0x00008576 }, /* GL_CONSTANT */
- { 4797, 0x00008003 }, /* GL_CONSTANT_ALPHA */
- { 4815, 0x00008003 }, /* GL_CONSTANT_ALPHA_EXT */
- { 4837, 0x00008576 }, /* GL_CONSTANT_ARB */
- { 4853, 0x00001207 }, /* GL_CONSTANT_ATTENUATION */
- { 4877, 0x00008151 }, /* GL_CONSTANT_BORDER_HP */
- { 4899, 0x00008001 }, /* GL_CONSTANT_COLOR */
- { 4917, 0x00008001 }, /* GL_CONSTANT_COLOR_EXT */
- { 4939, 0x00008576 }, /* GL_CONSTANT_EXT */
- { 4955, 0x00008010 }, /* GL_CONVOLUTION_1D */
- { 4973, 0x00008011 }, /* GL_CONVOLUTION_2D */
- { 4991, 0x00008154 }, /* GL_CONVOLUTION_BORDER_COLOR */
- { 5019, 0x00008154 }, /* GL_CONVOLUTION_BORDER_COLOR_HP */
- { 5050, 0x00008013 }, /* GL_CONVOLUTION_BORDER_MODE */
- { 5077, 0x00008013 }, /* GL_CONVOLUTION_BORDER_MODE_EXT */
- { 5108, 0x00008015 }, /* GL_CONVOLUTION_FILTER_BIAS */
- { 5135, 0x00008015 }, /* GL_CONVOLUTION_FILTER_BIAS_EXT */
- { 5166, 0x00008014 }, /* GL_CONVOLUTION_FILTER_SCALE */
- { 5194, 0x00008014 }, /* GL_CONVOLUTION_FILTER_SCALE_EXT */
- { 5226, 0x00008017 }, /* GL_CONVOLUTION_FORMAT */
- { 5248, 0x00008017 }, /* GL_CONVOLUTION_FORMAT_EXT */
- { 5274, 0x00008019 }, /* GL_CONVOLUTION_HEIGHT */
- { 5296, 0x00008019 }, /* GL_CONVOLUTION_HEIGHT_EXT */
- { 5322, 0x00008018 }, /* GL_CONVOLUTION_WIDTH */
- { 5343, 0x00008018 }, /* GL_CONVOLUTION_WIDTH_EXT */
- { 5368, 0x00008862 }, /* GL_COORD_REPLACE */
- { 5385, 0x00008862 }, /* GL_COORD_REPLACE_ARB */
- { 5406, 0x00008862 }, /* GL_COORD_REPLACE_NV */
- { 5426, 0x00001503 }, /* GL_COPY */
- { 5434, 0x0000150C }, /* GL_COPY_INVERTED */
- { 5451, 0x00000706 }, /* GL_COPY_PIXEL_TOKEN */
- { 5471, 0x00000B44 }, /* GL_CULL_FACE */
- { 5484, 0x00000B45 }, /* GL_CULL_FACE_MODE */
- { 5502, 0x000081AA }, /* GL_CULL_VERTEX_EXT */
- { 5521, 0x000081AC }, /* GL_CULL_VERTEX_EYE_POSITION_EXT */
- { 5553, 0x000081AB }, /* GL_CULL_VERTEX_OBJECT_POSITION_EXT */
- { 5588, 0x00008626 }, /* GL_CURRENT_ATTRIB_NV */
- { 5609, 0x00000001 }, /* GL_CURRENT_BIT */
- { 5624, 0x00000B00 }, /* GL_CURRENT_COLOR */
- { 5641, 0x00008453 }, /* GL_CURRENT_FOG_COORD */
- { 5662, 0x00008453 }, /* GL_CURRENT_FOG_COORDINATE */
- { 5688, 0x00000B01 }, /* GL_CURRENT_INDEX */
- { 5705, 0x00008641 }, /* GL_CURRENT_MATRIX_ARB */
- { 5727, 0x00008845 }, /* GL_CURRENT_MATRIX_INDEX_ARB */
- { 5755, 0x00008641 }, /* GL_CURRENT_MATRIX_NV */
- { 5776, 0x00008640 }, /* GL_CURRENT_MATRIX_STACK_DEPTH_ARB */
- { 5810, 0x00008640 }, /* GL_CURRENT_MATRIX_STACK_DEPTH_NV */
- { 5843, 0x00000B02 }, /* GL_CURRENT_NORMAL */
- { 5861, 0x00008843 }, /* GL_CURRENT_PALETTE_MATRIX_ARB */
- { 5891, 0x00008B8D }, /* GL_CURRENT_PROGRAM */
- { 5910, 0x00008865 }, /* GL_CURRENT_QUERY */
- { 5927, 0x00008865 }, /* GL_CURRENT_QUERY_ARB */
- { 5948, 0x00000B04 }, /* GL_CURRENT_RASTER_COLOR */
- { 5972, 0x00000B09 }, /* GL_CURRENT_RASTER_DISTANCE */
- { 5999, 0x00000B05 }, /* GL_CURRENT_RASTER_INDEX */
- { 6023, 0x00000B07 }, /* GL_CURRENT_RASTER_POSITION */
- { 6050, 0x00000B08 }, /* GL_CURRENT_RASTER_POSITION_VALID */
- { 6083, 0x00000B06 }, /* GL_CURRENT_RASTER_TEXTURE_COORDS */
- { 6116, 0x00008459 }, /* GL_CURRENT_SECONDARY_COLOR */
- { 6143, 0x00000B03 }, /* GL_CURRENT_TEXTURE_COORDS */
- { 6169, 0x00008626 }, /* GL_CURRENT_VERTEX_ATTRIB */
- { 6194, 0x00008626 }, /* GL_CURRENT_VERTEX_ATTRIB_ARB */
- { 6223, 0x000086A8 }, /* GL_CURRENT_WEIGHT_ARB */
- { 6245, 0x00000900 }, /* GL_CW */
- { 6251, 0x0000875B }, /* GL_DEBUG_ASSERT_MESA */
- { 6272, 0x00008759 }, /* GL_DEBUG_OBJECT_MESA */
- { 6293, 0x0000875A }, /* GL_DEBUG_PRINT_MESA */
- { 6313, 0x00002101 }, /* GL_DECAL */
- { 6322, 0x00001E03 }, /* GL_DECR */
- { 6330, 0x00008508 }, /* GL_DECR_WRAP */
- { 6343, 0x00008508 }, /* GL_DECR_WRAP_EXT */
- { 6360, 0x00008B80 }, /* GL_DELETE_STATUS */
- { 6377, 0x00001801 }, /* GL_DEPTH */
- { 6386, 0x00008D00 }, /* GL_DEPTH_ATTACHMENT_EXT */
- { 6410, 0x00000D1F }, /* GL_DEPTH_BIAS */
- { 6424, 0x00000D56 }, /* GL_DEPTH_BITS */
- { 6438, 0x00008891 }, /* GL_DEPTH_BOUNDS_EXT */
- { 6458, 0x00008890 }, /* GL_DEPTH_BOUNDS_TEST_EXT */
- { 6483, 0x00000100 }, /* GL_DEPTH_BUFFER_BIT */
- { 6503, 0x0000864F }, /* GL_DEPTH_CLAMP_NV */
- { 6521, 0x00000B73 }, /* GL_DEPTH_CLEAR_VALUE */
- { 6542, 0x00001902 }, /* GL_DEPTH_COMPONENT */
- { 6561, 0x000081A5 }, /* GL_DEPTH_COMPONENT16 */
- { 6582, 0x000081A5 }, /* GL_DEPTH_COMPONENT16_ARB */
- { 6607, 0x000081A5 }, /* GL_DEPTH_COMPONENT16_SGIX */
- { 6633, 0x000081A6 }, /* GL_DEPTH_COMPONENT24 */
- { 6654, 0x000081A6 }, /* GL_DEPTH_COMPONENT24_ARB */
- { 6679, 0x000081A6 }, /* GL_DEPTH_COMPONENT24_SGIX */
- { 6705, 0x000081A7 }, /* GL_DEPTH_COMPONENT32 */
- { 6726, 0x000081A7 }, /* GL_DEPTH_COMPONENT32_ARB */
- { 6751, 0x000081A7 }, /* GL_DEPTH_COMPONENT32_SGIX */
- { 6777, 0x00000B74 }, /* GL_DEPTH_FUNC */
- { 6791, 0x00000B70 }, /* GL_DEPTH_RANGE */
- { 6806, 0x00000D1E }, /* GL_DEPTH_SCALE */
- { 6821, 0x000084F9 }, /* GL_DEPTH_STENCIL_NV */
- { 6841, 0x0000886F }, /* GL_DEPTH_STENCIL_TO_BGRA_NV */
- { 6869, 0x0000886E }, /* GL_DEPTH_STENCIL_TO_RGBA_NV */
- { 6897, 0x00000B71 }, /* GL_DEPTH_TEST */
- { 6911, 0x0000884B }, /* GL_DEPTH_TEXTURE_MODE */
- { 6933, 0x0000884B }, /* GL_DEPTH_TEXTURE_MODE_ARB */
- { 6959, 0x00000B72 }, /* GL_DEPTH_WRITEMASK */
- { 6978, 0x00001201 }, /* GL_DIFFUSE */
- { 6989, 0x00000BD0 }, /* GL_DITHER */
- { 6999, 0x00000A02 }, /* GL_DOMAIN */
- { 7009, 0x00001100 }, /* GL_DONT_CARE */
- { 7022, 0x000086AE }, /* GL_DOT3_RGB */
- { 7034, 0x000086AF }, /* GL_DOT3_RGBA */
- { 7047, 0x000086AF }, /* GL_DOT3_RGBA_ARB */
- { 7064, 0x00008741 }, /* GL_DOT3_RGBA_EXT */
- { 7081, 0x000086AE }, /* GL_DOT3_RGB_ARB */
- { 7097, 0x00008740 }, /* GL_DOT3_RGB_EXT */
- { 7113, 0x0000140A }, /* GL_DOUBLE */
- { 7123, 0x00000C32 }, /* GL_DOUBLEBUFFER */
- { 7139, 0x00000C01 }, /* GL_DRAW_BUFFER */
- { 7154, 0x00008825 }, /* GL_DRAW_BUFFER0 */
- { 7170, 0x00008825 }, /* GL_DRAW_BUFFER0_ARB */
- { 7190, 0x00008825 }, /* GL_DRAW_BUFFER0_ATI */
- { 7210, 0x00008826 }, /* GL_DRAW_BUFFER1 */
- { 7226, 0x0000882F }, /* GL_DRAW_BUFFER10 */
- { 7243, 0x0000882F }, /* GL_DRAW_BUFFER10_ARB */
- { 7264, 0x0000882F }, /* GL_DRAW_BUFFER10_ATI */
- { 7285, 0x00008830 }, /* GL_DRAW_BUFFER11 */
- { 7302, 0x00008830 }, /* GL_DRAW_BUFFER11_ARB */
- { 7323, 0x00008830 }, /* GL_DRAW_BUFFER11_ATI */
- { 7344, 0x00008831 }, /* GL_DRAW_BUFFER12 */
- { 7361, 0x00008831 }, /* GL_DRAW_BUFFER12_ARB */
- { 7382, 0x00008831 }, /* GL_DRAW_BUFFER12_ATI */
- { 7403, 0x00008832 }, /* GL_DRAW_BUFFER13 */
- { 7420, 0x00008832 }, /* GL_DRAW_BUFFER13_ARB */
- { 7441, 0x00008832 }, /* GL_DRAW_BUFFER13_ATI */
- { 7462, 0x00008833 }, /* GL_DRAW_BUFFER14 */
- { 7479, 0x00008833 }, /* GL_DRAW_BUFFER14_ARB */
- { 7500, 0x00008833 }, /* GL_DRAW_BUFFER14_ATI */
- { 7521, 0x00008834 }, /* GL_DRAW_BUFFER15 */
- { 7538, 0x00008834 }, /* GL_DRAW_BUFFER15_ARB */
- { 7559, 0x00008834 }, /* GL_DRAW_BUFFER15_ATI */
- { 7580, 0x00008826 }, /* GL_DRAW_BUFFER1_ARB */
- { 7600, 0x00008826 }, /* GL_DRAW_BUFFER1_ATI */
- { 7620, 0x00008827 }, /* GL_DRAW_BUFFER2 */
- { 7636, 0x00008827 }, /* GL_DRAW_BUFFER2_ARB */
- { 7656, 0x00008827 }, /* GL_DRAW_BUFFER2_ATI */
- { 7676, 0x00008828 }, /* GL_DRAW_BUFFER3 */
- { 7692, 0x00008828 }, /* GL_DRAW_BUFFER3_ARB */
- { 7712, 0x00008828 }, /* GL_DRAW_BUFFER3_ATI */
- { 7732, 0x00008829 }, /* GL_DRAW_BUFFER4 */
- { 7748, 0x00008829 }, /* GL_DRAW_BUFFER4_ARB */
- { 7768, 0x00008829 }, /* GL_DRAW_BUFFER4_ATI */
- { 7788, 0x0000882A }, /* GL_DRAW_BUFFER5 */
- { 7804, 0x0000882A }, /* GL_DRAW_BUFFER5_ARB */
- { 7824, 0x0000882A }, /* GL_DRAW_BUFFER5_ATI */
- { 7844, 0x0000882B }, /* GL_DRAW_BUFFER6 */
- { 7860, 0x0000882B }, /* GL_DRAW_BUFFER6_ARB */
- { 7880, 0x0000882B }, /* GL_DRAW_BUFFER6_ATI */
- { 7900, 0x0000882C }, /* GL_DRAW_BUFFER7 */
- { 7916, 0x0000882C }, /* GL_DRAW_BUFFER7_ARB */
- { 7936, 0x0000882C }, /* GL_DRAW_BUFFER7_ATI */
- { 7956, 0x0000882D }, /* GL_DRAW_BUFFER8 */
- { 7972, 0x0000882D }, /* GL_DRAW_BUFFER8_ARB */
- { 7992, 0x0000882D }, /* GL_DRAW_BUFFER8_ATI */
- { 8012, 0x0000882E }, /* GL_DRAW_BUFFER9 */
- { 8028, 0x0000882E }, /* GL_DRAW_BUFFER9_ARB */
- { 8048, 0x0000882E }, /* GL_DRAW_BUFFER9_ATI */
- { 8068, 0x00008CA6 }, /* GL_DRAW_FRAMEBUFFER_BINDING_EXT */
- { 8100, 0x00008CA9 }, /* GL_DRAW_FRAMEBUFFER_EXT */
- { 8124, 0x00000705 }, /* GL_DRAW_PIXEL_TOKEN */
- { 8144, 0x00000304 }, /* GL_DST_ALPHA */
- { 8157, 0x00000306 }, /* GL_DST_COLOR */
- { 8170, 0x000088EA }, /* GL_DYNAMIC_COPY */
- { 8186, 0x000088EA }, /* GL_DYNAMIC_COPY_ARB */
- { 8206, 0x000088E8 }, /* GL_DYNAMIC_DRAW */
- { 8222, 0x000088E8 }, /* GL_DYNAMIC_DRAW_ARB */
- { 8242, 0x000088E9 }, /* GL_DYNAMIC_READ */
- { 8258, 0x000088E9 }, /* GL_DYNAMIC_READ_ARB */
- { 8278, 0x00000B43 }, /* GL_EDGE_FLAG */
- { 8291, 0x00008079 }, /* GL_EDGE_FLAG_ARRAY */
- { 8310, 0x0000889B }, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING */
- { 8344, 0x0000889B }, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB */
- { 8382, 0x00008093 }, /* GL_EDGE_FLAG_ARRAY_POINTER */
- { 8409, 0x0000808C }, /* GL_EDGE_FLAG_ARRAY_STRIDE */
- { 8435, 0x00008893 }, /* GL_ELEMENT_ARRAY_BUFFER */
- { 8459, 0x00008895 }, /* GL_ELEMENT_ARRAY_BUFFER_BINDING */
- { 8491, 0x00008895 }, /* GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB */
- { 8527, 0x00001600 }, /* GL_EMISSION */
- { 8539, 0x00002000 }, /* GL_ENABLE_BIT */
- { 8553, 0x00000202 }, /* GL_EQUAL */
- { 8562, 0x00001509 }, /* GL_EQUIV */
- { 8571, 0x00010000 }, /* GL_EVAL_BIT */
- { 8583, 0x00000800 }, /* GL_EXP */
- { 8590, 0x00000801 }, /* GL_EXP2 */
- { 8598, 0x00001F03 }, /* GL_EXTENSIONS */
- { 8612, 0x00002400 }, /* GL_EYE_LINEAR */
- { 8626, 0x00002502 }, /* GL_EYE_PLANE */
- { 8639, 0x0000855C }, /* GL_EYE_PLANE_ABSOLUTE_NV */
- { 8664, 0x0000855B }, /* GL_EYE_RADIAL_NV */
- { 8681, 0x00000000 }, /* GL_FALSE */
- { 8690, 0x00001101 }, /* GL_FASTEST */
- { 8701, 0x00001C01 }, /* GL_FEEDBACK */
- { 8713, 0x00000DF0 }, /* GL_FEEDBACK_BUFFER_POINTER */
- { 8740, 0x00000DF1 }, /* GL_FEEDBACK_BUFFER_SIZE */
- { 8764, 0x00000DF2 }, /* GL_FEEDBACK_BUFFER_TYPE */
- { 8788, 0x00001B02 }, /* GL_FILL */
- { 8796, 0x00001D00 }, /* GL_FLAT */
- { 8804, 0x00001406 }, /* GL_FLOAT */
- { 8813, 0x00008B5A }, /* GL_FLOAT_MAT2 */
- { 8827, 0x00008B5A }, /* GL_FLOAT_MAT2_ARB */
- { 8845, 0x00008B5B }, /* GL_FLOAT_MAT3 */
- { 8859, 0x00008B5B }, /* GL_FLOAT_MAT3_ARB */
- { 8877, 0x00008B5C }, /* GL_FLOAT_MAT4 */
- { 8891, 0x00008B5C }, /* GL_FLOAT_MAT4_ARB */
- { 8909, 0x00008B50 }, /* GL_FLOAT_VEC2 */
- { 8923, 0x00008B50 }, /* GL_FLOAT_VEC2_ARB */
- { 8941, 0x00008B51 }, /* GL_FLOAT_VEC3 */
- { 8955, 0x00008B51 }, /* GL_FLOAT_VEC3_ARB */
- { 8973, 0x00008B52 }, /* GL_FLOAT_VEC4 */
- { 8987, 0x00008B52 }, /* GL_FLOAT_VEC4_ARB */
- { 9005, 0x00000B60 }, /* GL_FOG */
- { 9012, 0x00000080 }, /* GL_FOG_BIT */
- { 9023, 0x00000B66 }, /* GL_FOG_COLOR */
- { 9036, 0x00008451 }, /* GL_FOG_COORD */
- { 9049, 0x00008451 }, /* GL_FOG_COORDINATE */
- { 9067, 0x00008457 }, /* GL_FOG_COORDINATE_ARRAY */
- { 9091, 0x0000889D }, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING */
- { 9130, 0x0000889D }, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB */
- { 9173, 0x00008456 }, /* GL_FOG_COORDINATE_ARRAY_POINTER */
- { 9205, 0x00008455 }, /* GL_FOG_COORDINATE_ARRAY_STRIDE */
- { 9236, 0x00008454 }, /* GL_FOG_COORDINATE_ARRAY_TYPE */
- { 9265, 0x00008450 }, /* GL_FOG_COORDINATE_SOURCE */
- { 9290, 0x00008457 }, /* GL_FOG_COORD_ARRAY */
- { 9309, 0x0000889D }, /* GL_FOG_COORD_ARRAY_BUFFER_BINDING */
- { 9343, 0x00008456 }, /* GL_FOG_COORD_ARRAY_POINTER */
- { 9370, 0x00008455 }, /* GL_FOG_COORD_ARRAY_STRIDE */
- { 9396, 0x00008454 }, /* GL_FOG_COORD_ARRAY_TYPE */
- { 9420, 0x00008450 }, /* GL_FOG_COORD_SRC */
- { 9437, 0x00000B62 }, /* GL_FOG_DENSITY */
- { 9452, 0x0000855A }, /* GL_FOG_DISTANCE_MODE_NV */
- { 9476, 0x00000B64 }, /* GL_FOG_END */
- { 9487, 0x00000C54 }, /* GL_FOG_HINT */
- { 9499, 0x00000B61 }, /* GL_FOG_INDEX */
- { 9512, 0x00000B65 }, /* GL_FOG_MODE */
- { 9524, 0x00008198 }, /* GL_FOG_OFFSET_SGIX */
- { 9543, 0x00008199 }, /* GL_FOG_OFFSET_VALUE_SGIX */
- { 9568, 0x00000B63 }, /* GL_FOG_START */
- { 9581, 0x00008452 }, /* GL_FRAGMENT_DEPTH */
- { 9599, 0x00008804 }, /* GL_FRAGMENT_PROGRAM_ARB */
- { 9623, 0x00008B30 }, /* GL_FRAGMENT_SHADER */
- { 9642, 0x00008B30 }, /* GL_FRAGMENT_SHADER_ARB */
- { 9665, 0x00008B8B }, /* GL_FRAGMENT_SHADER_DERIVATIVE_HINT */
- { 9700, 0x00008CD1 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT */
- { 9742, 0x00008CD0 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT */
- { 9784, 0x00008CD4 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT */
- { 9833, 0x00008CD3 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT */
- { 9885, 0x00008CD4 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */
- { 9929, 0x00008CD2 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT */
- { 9973, 0x00008CA6 }, /* GL_FRAMEBUFFER_BINDING_EXT */
- { 10000, 0x00008CD5 }, /* GL_FRAMEBUFFER_COMPLETE_EXT */
- { 10028, 0x00008D40 }, /* GL_FRAMEBUFFER_EXT */
- { 10047, 0x00008CD6 }, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT */
- { 10088, 0x00008CD9 }, /* GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT */
- { 10129, 0x00008CDB }, /* GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT */
- { 10171, 0x00008CD8 }, /* GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT */
- { 10222, 0x00008CDA }, /* GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT */
- { 10260, 0x00008CD7 }, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT */
- { 10309, 0x00008CDC }, /* GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT */
- { 10351, 0x00008CDE }, /* GL_FRAMEBUFFER_STATUS_ERROR_EXT */
- { 10383, 0x00008CDD }, /* GL_FRAMEBUFFER_UNSUPPORTED_EXT */
- { 10414, 0x00000404 }, /* GL_FRONT */
- { 10423, 0x00000408 }, /* GL_FRONT_AND_BACK */
- { 10441, 0x00000B46 }, /* GL_FRONT_FACE */
- { 10455, 0x00000400 }, /* GL_FRONT_LEFT */
- { 10469, 0x00000401 }, /* GL_FRONT_RIGHT */
- { 10484, 0x00008006 }, /* GL_FUNC_ADD */
- { 10496, 0x00008006 }, /* GL_FUNC_ADD_EXT */
- { 10512, 0x0000800B }, /* GL_FUNC_REVERSE_SUBTRACT */
- { 10537, 0x0000800B }, /* GL_FUNC_REVERSE_SUBTRACT_EXT */
- { 10566, 0x0000800A }, /* GL_FUNC_SUBTRACT */
- { 10583, 0x0000800A }, /* GL_FUNC_SUBTRACT_EXT */
- { 10604, 0x00008191 }, /* GL_GENERATE_MIPMAP */
- { 10623, 0x00008192 }, /* GL_GENERATE_MIPMAP_HINT */
- { 10647, 0x00008192 }, /* GL_GENERATE_MIPMAP_HINT_SGIS */
- { 10676, 0x00008191 }, /* GL_GENERATE_MIPMAP_SGIS */
- { 10700, 0x00000206 }, /* GL_GEQUAL */
- { 10710, 0x00008009 }, /* GL_GL_BLEND_EQUATION_RGB */
- { 10735, 0x00008C4A }, /* GL_GL_COMPRESSED_SLUMINANCE */
- { 10763, 0x00008C4B }, /* GL_GL_COMPRESSED_SLUMINANCE_ALPHA */
- { 10797, 0x00008C48 }, /* GL_GL_COMPRESSED_SRGB */
- { 10819, 0x00008C49 }, /* GL_GL_COMPRESSED_SRGB_ALPHA */
- { 10847, 0x0000845F }, /* GL_GL_CURRENT_RASTER_SECONDARY_COLOR */
- { 10884, 0x00008B65 }, /* GL_GL_FLOAT_MAT2x3 */
- { 10903, 0x00008B66 }, /* GL_GL_FLOAT_MAT2x4 */
- { 10922, 0x00008B67 }, /* GL_GL_FLOAT_MAT3x2 */
- { 10941, 0x00008B68 }, /* GL_GL_FLOAT_MAT3x4 */
- { 10960, 0x00008B69 }, /* GL_GL_FLOAT_MAT4x2 */
- { 10979, 0x00008B6A }, /* GL_GL_FLOAT_MAT4x3 */
- { 10998, 0x000088EB }, /* GL_GL_PIXEL_PACK_BUFFER */
- { 11022, 0x000088ED }, /* GL_GL_PIXEL_PACK_BUFFER_BINDING */
- { 11054, 0x000088EC }, /* GL_GL_PIXEL_UNPACK_BUFFER */
- { 11080, 0x000088EF }, /* GL_GL_PIXEL_UNPACK_BUFFER_BINDING */
- { 11114, 0x00008C46 }, /* GL_GL_SLUMINANCE */
- { 11131, 0x00008C47 }, /* GL_GL_SLUMINANCE8 */
- { 11149, 0x00008C45 }, /* GL_GL_SLUMINANCE8_ALPHA8 */
- { 11174, 0x00008C44 }, /* GL_GL_SLUMINANCE_ALPHA */
- { 11197, 0x00008C40 }, /* GL_GL_SRGB */
- { 11208, 0x00008C41 }, /* GL_GL_SRGB8 */
- { 11220, 0x00008C43 }, /* GL_GL_SRGB8_ALPHA8 */
- { 11239, 0x00008C42 }, /* GL_GL_SRGB_ALPHA */
- { 11256, 0x00000204 }, /* GL_GREATER */
- { 11267, 0x00001904 }, /* GL_GREEN */
- { 11276, 0x00000D19 }, /* GL_GREEN_BIAS */
- { 11290, 0x00000D53 }, /* GL_GREEN_BITS */
- { 11304, 0x00000D18 }, /* GL_GREEN_SCALE */
- { 11319, 0x00008000 }, /* GL_HINT_BIT */
- { 11331, 0x00008024 }, /* GL_HISTOGRAM */
- { 11344, 0x0000802B }, /* GL_HISTOGRAM_ALPHA_SIZE */
- { 11368, 0x0000802B }, /* GL_HISTOGRAM_ALPHA_SIZE_EXT */
- { 11396, 0x0000802A }, /* GL_HISTOGRAM_BLUE_SIZE */
- { 11419, 0x0000802A }, /* GL_HISTOGRAM_BLUE_SIZE_EXT */
- { 11446, 0x00008024 }, /* GL_HISTOGRAM_EXT */
- { 11463, 0x00008027 }, /* GL_HISTOGRAM_FORMAT */
- { 11483, 0x00008027 }, /* GL_HISTOGRAM_FORMAT_EXT */
- { 11507, 0x00008029 }, /* GL_HISTOGRAM_GREEN_SIZE */
- { 11531, 0x00008029 }, /* GL_HISTOGRAM_GREEN_SIZE_EXT */
- { 11559, 0x0000802C }, /* GL_HISTOGRAM_LUMINANCE_SIZE */
- { 11587, 0x0000802C }, /* GL_HISTOGRAM_LUMINANCE_SIZE_EXT */
- { 11619, 0x00008028 }, /* GL_HISTOGRAM_RED_SIZE */
- { 11641, 0x00008028 }, /* GL_HISTOGRAM_RED_SIZE_EXT */
- { 11667, 0x0000802D }, /* GL_HISTOGRAM_SINK */
- { 11685, 0x0000802D }, /* GL_HISTOGRAM_SINK_EXT */
- { 11707, 0x00008026 }, /* GL_HISTOGRAM_WIDTH */
- { 11726, 0x00008026 }, /* GL_HISTOGRAM_WIDTH_EXT */
- { 11749, 0x0000862A }, /* GL_IDENTITY_NV */
- { 11764, 0x00008150 }, /* GL_IGNORE_BORDER_HP */
- { 11784, 0x00008B9B }, /* GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES */
- { 11824, 0x00008B9A }, /* GL_IMPLEMENTATION_COLOR_READ_TYPE_OES */
- { 11862, 0x00001E02 }, /* GL_INCR */
- { 11870, 0x00008507 }, /* GL_INCR_WRAP */
- { 11883, 0x00008507 }, /* GL_INCR_WRAP_EXT */
- { 11900, 0x00008077 }, /* GL_INDEX_ARRAY */
- { 11915, 0x00008899 }, /* GL_INDEX_ARRAY_BUFFER_BINDING */
- { 11945, 0x00008899 }, /* GL_INDEX_ARRAY_BUFFER_BINDING_ARB */
- { 11979, 0x00008091 }, /* GL_INDEX_ARRAY_POINTER */
- { 12002, 0x00008086 }, /* GL_INDEX_ARRAY_STRIDE */
- { 12024, 0x00008085 }, /* GL_INDEX_ARRAY_TYPE */
- { 12044, 0x00000D51 }, /* GL_INDEX_BITS */
- { 12058, 0x00000C20 }, /* GL_INDEX_CLEAR_VALUE */
- { 12079, 0x00000BF1 }, /* GL_INDEX_LOGIC_OP */
- { 12097, 0x00000C30 }, /* GL_INDEX_MODE */
- { 12111, 0x00000D13 }, /* GL_INDEX_OFFSET */
- { 12127, 0x00000D12 }, /* GL_INDEX_SHIFT */
- { 12142, 0x00000C21 }, /* GL_INDEX_WRITEMASK */
- { 12161, 0x00008B84 }, /* GL_INFO_LOG_LENGTH */
- { 12180, 0x00001404 }, /* GL_INT */
- { 12187, 0x00008049 }, /* GL_INTENSITY */
- { 12200, 0x0000804C }, /* GL_INTENSITY12 */
- { 12215, 0x0000804C }, /* GL_INTENSITY12_EXT */
- { 12234, 0x0000804D }, /* GL_INTENSITY16 */
- { 12249, 0x0000804D }, /* GL_INTENSITY16_EXT */
- { 12268, 0x0000804A }, /* GL_INTENSITY4 */
- { 12282, 0x0000804A }, /* GL_INTENSITY4_EXT */
- { 12300, 0x0000804B }, /* GL_INTENSITY8 */
- { 12314, 0x0000804B }, /* GL_INTENSITY8_EXT */
- { 12332, 0x00008049 }, /* GL_INTENSITY_EXT */
- { 12349, 0x00008575 }, /* GL_INTERPOLATE */
- { 12364, 0x00008575 }, /* GL_INTERPOLATE_ARB */
- { 12383, 0x00008575 }, /* GL_INTERPOLATE_EXT */
- { 12402, 0x00008B53 }, /* GL_INT_VEC2 */
- { 12414, 0x00008B53 }, /* GL_INT_VEC2_ARB */
- { 12430, 0x00008B54 }, /* GL_INT_VEC3 */
- { 12442, 0x00008B54 }, /* GL_INT_VEC3_ARB */
- { 12458, 0x00008B55 }, /* GL_INT_VEC4 */
- { 12470, 0x00008B55 }, /* GL_INT_VEC4_ARB */
- { 12486, 0x00000500 }, /* GL_INVALID_ENUM */
- { 12502, 0x00000506 }, /* GL_INVALID_FRAMEBUFFER_OPERATION_EXT */
- { 12539, 0x00000502 }, /* GL_INVALID_OPERATION */
- { 12560, 0x00000501 }, /* GL_INVALID_VALUE */
- { 12577, 0x0000862B }, /* GL_INVERSE_NV */
- { 12591, 0x0000862D }, /* GL_INVERSE_TRANSPOSE_NV */
- { 12615, 0x0000150A }, /* GL_INVERT */
- { 12625, 0x00001E00 }, /* GL_KEEP */
- { 12633, 0x00000406 }, /* GL_LEFT */
- { 12641, 0x00000203 }, /* GL_LEQUAL */
- { 12651, 0x00000201 }, /* GL_LESS */
- { 12659, 0x00004000 }, /* GL_LIGHT0 */
- { 12669, 0x00004001 }, /* GL_LIGHT1 */
- { 12679, 0x00004002 }, /* GL_LIGHT2 */
- { 12689, 0x00004003 }, /* GL_LIGHT3 */
- { 12699, 0x00004004 }, /* GL_LIGHT4 */
- { 12709, 0x00004005 }, /* GL_LIGHT5 */
- { 12719, 0x00004006 }, /* GL_LIGHT6 */
- { 12729, 0x00004007 }, /* GL_LIGHT7 */
- { 12739, 0x00000B50 }, /* GL_LIGHTING */
- { 12751, 0x00000040 }, /* GL_LIGHTING_BIT */
- { 12767, 0x00000B53 }, /* GL_LIGHT_MODEL_AMBIENT */
- { 12790, 0x000081F8 }, /* GL_LIGHT_MODEL_COLOR_CONTROL */
- { 12819, 0x000081F8 }, /* GL_LIGHT_MODEL_COLOR_CONTROL_EXT */
- { 12852, 0x00000B51 }, /* GL_LIGHT_MODEL_LOCAL_VIEWER */
- { 12880, 0x00000B52 }, /* GL_LIGHT_MODEL_TWO_SIDE */
- { 12904, 0x00001B01 }, /* GL_LINE */
- { 12912, 0x00002601 }, /* GL_LINEAR */
- { 12922, 0x00001208 }, /* GL_LINEAR_ATTENUATION */
- { 12944, 0x00008170 }, /* GL_LINEAR_CLIPMAP_LINEAR_SGIX */
- { 12974, 0x0000844F }, /* GL_LINEAR_CLIPMAP_NEAREST_SGIX */
- { 13005, 0x00002703 }, /* GL_LINEAR_MIPMAP_LINEAR */
- { 13029, 0x00002701 }, /* GL_LINEAR_MIPMAP_NEAREST */
- { 13054, 0x00000001 }, /* GL_LINES */
- { 13063, 0x00000004 }, /* GL_LINE_BIT */
- { 13075, 0x00000002 }, /* GL_LINE_LOOP */
- { 13088, 0x00000707 }, /* GL_LINE_RESET_TOKEN */
- { 13108, 0x00000B20 }, /* GL_LINE_SMOOTH */
- { 13123, 0x00000C52 }, /* GL_LINE_SMOOTH_HINT */
- { 13143, 0x00000B24 }, /* GL_LINE_STIPPLE */
- { 13159, 0x00000B25 }, /* GL_LINE_STIPPLE_PATTERN */
- { 13183, 0x00000B26 }, /* GL_LINE_STIPPLE_REPEAT */
- { 13206, 0x00000003 }, /* GL_LINE_STRIP */
- { 13220, 0x00000702 }, /* GL_LINE_TOKEN */
- { 13234, 0x00000B21 }, /* GL_LINE_WIDTH */
- { 13248, 0x00000B23 }, /* GL_LINE_WIDTH_GRANULARITY */
- { 13274, 0x00000B22 }, /* GL_LINE_WIDTH_RANGE */
- { 13294, 0x00008B82 }, /* GL_LINK_STATUS */
- { 13309, 0x00000B32 }, /* GL_LIST_BASE */
- { 13322, 0x00020000 }, /* GL_LIST_BIT */
- { 13334, 0x00000B33 }, /* GL_LIST_INDEX */
- { 13348, 0x00000B30 }, /* GL_LIST_MODE */
- { 13361, 0x00000101 }, /* GL_LOAD */
- { 13369, 0x00000BF1 }, /* GL_LOGIC_OP */
- { 13381, 0x00000BF0 }, /* GL_LOGIC_OP_MODE */
- { 13398, 0x00008CA1 }, /* GL_LOWER_LEFT */
- { 13412, 0x00001909 }, /* GL_LUMINANCE */
- { 13425, 0x00008041 }, /* GL_LUMINANCE12 */
- { 13440, 0x00008047 }, /* GL_LUMINANCE12_ALPHA12 */
- { 13463, 0x00008047 }, /* GL_LUMINANCE12_ALPHA12_EXT */
- { 13490, 0x00008046 }, /* GL_LUMINANCE12_ALPHA4 */
- { 13512, 0x00008046 }, /* GL_LUMINANCE12_ALPHA4_EXT */
- { 13538, 0x00008041 }, /* GL_LUMINANCE12_EXT */
- { 13557, 0x00008042 }, /* GL_LUMINANCE16 */
- { 13572, 0x00008048 }, /* GL_LUMINANCE16_ALPHA16 */
- { 13595, 0x00008048 }, /* GL_LUMINANCE16_ALPHA16_EXT */
- { 13622, 0x00008042 }, /* GL_LUMINANCE16_EXT */
- { 13641, 0x0000803F }, /* GL_LUMINANCE4 */
- { 13655, 0x00008043 }, /* GL_LUMINANCE4_ALPHA4 */
- { 13676, 0x00008043 }, /* GL_LUMINANCE4_ALPHA4_EXT */
- { 13701, 0x0000803F }, /* GL_LUMINANCE4_EXT */
- { 13719, 0x00008044 }, /* GL_LUMINANCE6_ALPHA2 */
- { 13740, 0x00008044 }, /* GL_LUMINANCE6_ALPHA2_EXT */
- { 13765, 0x00008040 }, /* GL_LUMINANCE8 */
- { 13779, 0x00008045 }, /* GL_LUMINANCE8_ALPHA8 */
- { 13800, 0x00008045 }, /* GL_LUMINANCE8_ALPHA8_EXT */
- { 13825, 0x00008040 }, /* GL_LUMINANCE8_EXT */
- { 13843, 0x0000190A }, /* GL_LUMINANCE_ALPHA */
- { 13862, 0x00000D90 }, /* GL_MAP1_COLOR_4 */
- { 13878, 0x00000DD0 }, /* GL_MAP1_GRID_DOMAIN */
- { 13898, 0x00000DD1 }, /* GL_MAP1_GRID_SEGMENTS */
- { 13920, 0x00000D91 }, /* GL_MAP1_INDEX */
- { 13934, 0x00000D92 }, /* GL_MAP1_NORMAL */
- { 13949, 0x00000D93 }, /* GL_MAP1_TEXTURE_COORD_1 */
- { 13973, 0x00000D94 }, /* GL_MAP1_TEXTURE_COORD_2 */
- { 13997, 0x00000D95 }, /* GL_MAP1_TEXTURE_COORD_3 */
- { 14021, 0x00000D96 }, /* GL_MAP1_TEXTURE_COORD_4 */
- { 14045, 0x00000D97 }, /* GL_MAP1_VERTEX_3 */
- { 14062, 0x00000D98 }, /* GL_MAP1_VERTEX_4 */
- { 14079, 0x00008660 }, /* GL_MAP1_VERTEX_ATTRIB0_4_NV */
- { 14107, 0x0000866A }, /* GL_MAP1_VERTEX_ATTRIB10_4_NV */
- { 14136, 0x0000866B }, /* GL_MAP1_VERTEX_ATTRIB11_4_NV */
- { 14165, 0x0000866C }, /* GL_MAP1_VERTEX_ATTRIB12_4_NV */
- { 14194, 0x0000866D }, /* GL_MAP1_VERTEX_ATTRIB13_4_NV */
- { 14223, 0x0000866E }, /* GL_MAP1_VERTEX_ATTRIB14_4_NV */
- { 14252, 0x0000866F }, /* GL_MAP1_VERTEX_ATTRIB15_4_NV */
- { 14281, 0x00008661 }, /* GL_MAP1_VERTEX_ATTRIB1_4_NV */
- { 14309, 0x00008662 }, /* GL_MAP1_VERTEX_ATTRIB2_4_NV */
- { 14337, 0x00008663 }, /* GL_MAP1_VERTEX_ATTRIB3_4_NV */
- { 14365, 0x00008664 }, /* GL_MAP1_VERTEX_ATTRIB4_4_NV */
- { 14393, 0x00008665 }, /* GL_MAP1_VERTEX_ATTRIB5_4_NV */
- { 14421, 0x00008666 }, /* GL_MAP1_VERTEX_ATTRIB6_4_NV */
- { 14449, 0x00008667 }, /* GL_MAP1_VERTEX_ATTRIB7_4_NV */
- { 14477, 0x00008668 }, /* GL_MAP1_VERTEX_ATTRIB8_4_NV */
- { 14505, 0x00008669 }, /* GL_MAP1_VERTEX_ATTRIB9_4_NV */
- { 14533, 0x00000DB0 }, /* GL_MAP2_COLOR_4 */
- { 14549, 0x00000DD2 }, /* GL_MAP2_GRID_DOMAIN */
- { 14569, 0x00000DD3 }, /* GL_MAP2_GRID_SEGMENTS */
- { 14591, 0x00000DB1 }, /* GL_MAP2_INDEX */
- { 14605, 0x00000DB2 }, /* GL_MAP2_NORMAL */
- { 14620, 0x00000DB3 }, /* GL_MAP2_TEXTURE_COORD_1 */
- { 14644, 0x00000DB4 }, /* GL_MAP2_TEXTURE_COORD_2 */
- { 14668, 0x00000DB5 }, /* GL_MAP2_TEXTURE_COORD_3 */
- { 14692, 0x00000DB6 }, /* GL_MAP2_TEXTURE_COORD_4 */
- { 14716, 0x00000DB7 }, /* GL_MAP2_VERTEX_3 */
- { 14733, 0x00000DB8 }, /* GL_MAP2_VERTEX_4 */
- { 14750, 0x00008670 }, /* GL_MAP2_VERTEX_ATTRIB0_4_NV */
- { 14778, 0x0000867A }, /* GL_MAP2_VERTEX_ATTRIB10_4_NV */
- { 14807, 0x0000867B }, /* GL_MAP2_VERTEX_ATTRIB11_4_NV */
- { 14836, 0x0000867C }, /* GL_MAP2_VERTEX_ATTRIB12_4_NV */
- { 14865, 0x0000867D }, /* GL_MAP2_VERTEX_ATTRIB13_4_NV */
- { 14894, 0x0000867E }, /* GL_MAP2_VERTEX_ATTRIB14_4_NV */
- { 14923, 0x0000867F }, /* GL_MAP2_VERTEX_ATTRIB15_4_NV */
- { 14952, 0x00008671 }, /* GL_MAP2_VERTEX_ATTRIB1_4_NV */
- { 14980, 0x00008672 }, /* GL_MAP2_VERTEX_ATTRIB2_4_NV */
- { 15008, 0x00008673 }, /* GL_MAP2_VERTEX_ATTRIB3_4_NV */
- { 15036, 0x00008674 }, /* GL_MAP2_VERTEX_ATTRIB4_4_NV */
- { 15064, 0x00008675 }, /* GL_MAP2_VERTEX_ATTRIB5_4_NV */
- { 15092, 0x00008676 }, /* GL_MAP2_VERTEX_ATTRIB6_4_NV */
- { 15120, 0x00008677 }, /* GL_MAP2_VERTEX_ATTRIB7_4_NV */
- { 15148, 0x00008678 }, /* GL_MAP2_VERTEX_ATTRIB8_4_NV */
- { 15176, 0x00008679 }, /* GL_MAP2_VERTEX_ATTRIB9_4_NV */
- { 15204, 0x00000D10 }, /* GL_MAP_COLOR */
- { 15217, 0x00000D11 }, /* GL_MAP_STENCIL */
- { 15232, 0x000088C0 }, /* GL_MATRIX0_ARB */
- { 15247, 0x00008630 }, /* GL_MATRIX0_NV */
- { 15261, 0x000088CA }, /* GL_MATRIX10_ARB */
- { 15277, 0x000088CB }, /* GL_MATRIX11_ARB */
- { 15293, 0x000088CC }, /* GL_MATRIX12_ARB */
- { 15309, 0x000088CD }, /* GL_MATRIX13_ARB */
- { 15325, 0x000088CE }, /* GL_MATRIX14_ARB */
- { 15341, 0x000088CF }, /* GL_MATRIX15_ARB */
- { 15357, 0x000088D0 }, /* GL_MATRIX16_ARB */
- { 15373, 0x000088D1 }, /* GL_MATRIX17_ARB */
- { 15389, 0x000088D2 }, /* GL_MATRIX18_ARB */
- { 15405, 0x000088D3 }, /* GL_MATRIX19_ARB */
- { 15421, 0x000088C1 }, /* GL_MATRIX1_ARB */
- { 15436, 0x00008631 }, /* GL_MATRIX1_NV */
- { 15450, 0x000088D4 }, /* GL_MATRIX20_ARB */
- { 15466, 0x000088D5 }, /* GL_MATRIX21_ARB */
- { 15482, 0x000088D6 }, /* GL_MATRIX22_ARB */
- { 15498, 0x000088D7 }, /* GL_MATRIX23_ARB */
- { 15514, 0x000088D8 }, /* GL_MATRIX24_ARB */
- { 15530, 0x000088D9 }, /* GL_MATRIX25_ARB */
- { 15546, 0x000088DA }, /* GL_MATRIX26_ARB */
- { 15562, 0x000088DB }, /* GL_MATRIX27_ARB */
- { 15578, 0x000088DC }, /* GL_MATRIX28_ARB */
- { 15594, 0x000088DD }, /* GL_MATRIX29_ARB */
- { 15610, 0x000088C2 }, /* GL_MATRIX2_ARB */
- { 15625, 0x00008632 }, /* GL_MATRIX2_NV */
- { 15639, 0x000088DE }, /* GL_MATRIX30_ARB */
- { 15655, 0x000088DF }, /* GL_MATRIX31_ARB */
- { 15671, 0x000088C3 }, /* GL_MATRIX3_ARB */
- { 15686, 0x00008633 }, /* GL_MATRIX3_NV */
- { 15700, 0x000088C4 }, /* GL_MATRIX4_ARB */
- { 15715, 0x00008634 }, /* GL_MATRIX4_NV */
- { 15729, 0x000088C5 }, /* GL_MATRIX5_ARB */
- { 15744, 0x00008635 }, /* GL_MATRIX5_NV */
- { 15758, 0x000088C6 }, /* GL_MATRIX6_ARB */
- { 15773, 0x00008636 }, /* GL_MATRIX6_NV */
- { 15787, 0x000088C7 }, /* GL_MATRIX7_ARB */
- { 15802, 0x00008637 }, /* GL_MATRIX7_NV */
- { 15816, 0x000088C8 }, /* GL_MATRIX8_ARB */
- { 15831, 0x000088C9 }, /* GL_MATRIX9_ARB */
- { 15846, 0x00008844 }, /* GL_MATRIX_INDEX_ARRAY_ARB */
- { 15872, 0x00008849 }, /* GL_MATRIX_INDEX_ARRAY_POINTER_ARB */
- { 15906, 0x00008846 }, /* GL_MATRIX_INDEX_ARRAY_SIZE_ARB */
- { 15937, 0x00008848 }, /* GL_MATRIX_INDEX_ARRAY_STRIDE_ARB */
- { 15970, 0x00008847 }, /* GL_MATRIX_INDEX_ARRAY_TYPE_ARB */
- { 16001, 0x00000BA0 }, /* GL_MATRIX_MODE */
- { 16016, 0x00008840 }, /* GL_MATRIX_PALETTE_ARB */
- { 16038, 0x00008008 }, /* GL_MAX */
- { 16045, 0x00008073 }, /* GL_MAX_3D_TEXTURE_SIZE */
- { 16068, 0x000088FF }, /* GL_MAX_ARRAY_TEXTURE_LAYERS_EXT */
- { 16100, 0x00000D35 }, /* GL_MAX_ATTRIB_STACK_DEPTH */
- { 16126, 0x00000D3B }, /* GL_MAX_CLIENT_ATTRIB_STACK_DEPTH */
- { 16159, 0x00008177 }, /* GL_MAX_CLIPMAP_DEPTH_SGIX */
- { 16185, 0x00008178 }, /* GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX */
- { 16219, 0x00000D32 }, /* GL_MAX_CLIP_PLANES */
- { 16238, 0x00008CDF }, /* GL_MAX_COLOR_ATTACHMENTS_EXT */
- { 16267, 0x000080B3 }, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH */
- { 16299, 0x000080B3 }, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI */
- { 16335, 0x00008B4D }, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */
- { 16371, 0x00008B4D }, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB */
- { 16411, 0x0000801B }, /* GL_MAX_CONVOLUTION_HEIGHT */
- { 16437, 0x0000801B }, /* GL_MAX_CONVOLUTION_HEIGHT_EXT */
- { 16467, 0x0000801A }, /* GL_MAX_CONVOLUTION_WIDTH */
- { 16492, 0x0000801A }, /* GL_MAX_CONVOLUTION_WIDTH_EXT */
- { 16521, 0x0000851C }, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */
- { 16550, 0x0000851C }, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB */
- { 16583, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS */
- { 16603, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS_ARB */
- { 16627, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS_ATI */
- { 16651, 0x000080E9 }, /* GL_MAX_ELEMENTS_INDICES */
- { 16675, 0x000080E8 }, /* GL_MAX_ELEMENTS_VERTICES */
- { 16700, 0x00000D30 }, /* GL_MAX_EVAL_ORDER */
- { 16718, 0x00008008 }, /* GL_MAX_EXT */
- { 16729, 0x00008B49 }, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS */
- { 16764, 0x00008B49 }, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB */
- { 16803, 0x00000D31 }, /* GL_MAX_LIGHTS */
- { 16817, 0x00000B31 }, /* GL_MAX_LIST_NESTING */
- { 16837, 0x00008841 }, /* GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB */
- { 16875, 0x00000D36 }, /* GL_MAX_MODELVIEW_STACK_DEPTH */
- { 16904, 0x00000D37 }, /* GL_MAX_NAME_STACK_DEPTH */
- { 16928, 0x00008842 }, /* GL_MAX_PALETTE_MATRICES_ARB */
- { 16956, 0x00000D34 }, /* GL_MAX_PIXEL_MAP_TABLE */
- { 16979, 0x000088B1 }, /* GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB */
- { 17016, 0x0000880B }, /* GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB */
- { 17052, 0x000088AD }, /* GL_MAX_PROGRAM_ATTRIBS_ARB */
- { 17079, 0x000088F5 }, /* GL_MAX_PROGRAM_CALL_DEPTH_NV */
- { 17108, 0x000088B5 }, /* GL_MAX_PROGRAM_ENV_PARAMETERS_ARB */
- { 17142, 0x000088F4 }, /* GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */
- { 17178, 0x000088F6 }, /* GL_MAX_PROGRAM_IF_DEPTH_NV */
- { 17205, 0x000088A1 }, /* GL_MAX_PROGRAM_INSTRUCTIONS_ARB */
- { 17237, 0x000088B4 }, /* GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB */
- { 17273, 0x000088F8 }, /* GL_MAX_PROGRAM_LOOP_COUNT_NV */
- { 17302, 0x000088F7 }, /* GL_MAX_PROGRAM_LOOP_DEPTH_NV */
- { 17331, 0x0000862F }, /* GL_MAX_PROGRAM_MATRICES_ARB */
- { 17359, 0x0000862E }, /* GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB */
- { 17397, 0x000088B3 }, /* GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
- { 17441, 0x0000880E }, /* GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
- { 17484, 0x000088AF }, /* GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB */
- { 17518, 0x000088A3 }, /* GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
- { 17557, 0x000088AB }, /* GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB */
- { 17594, 0x000088A7 }, /* GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB */
- { 17632, 0x00008810 }, /* GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
- { 17675, 0x0000880F }, /* GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
- { 17718, 0x000088A9 }, /* GL_MAX_PROGRAM_PARAMETERS_ARB */
- { 17748, 0x000088A5 }, /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
- { 17779, 0x0000880D }, /* GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB */
- { 17815, 0x0000880C }, /* GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB */
- { 17851, 0x00000D38 }, /* GL_MAX_PROJECTION_STACK_DEPTH */
- { 17881, 0x000084F8 }, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB */
- { 17915, 0x000084F8 }, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_NV */
- { 17948, 0x000084E8 }, /* GL_MAX_RENDERBUFFER_SIZE_EXT */
- { 17977, 0x00008504 }, /* GL_MAX_SHININESS_NV */
- { 17997, 0x00008505 }, /* GL_MAX_SPOT_EXPONENT_NV */
- { 18021, 0x00008871 }, /* GL_MAX_TEXTURE_COORDS */
- { 18043, 0x00008871 }, /* GL_MAX_TEXTURE_COORDS_ARB */
- { 18069, 0x00008872 }, /* GL_MAX_TEXTURE_IMAGE_UNITS */
- { 18096, 0x00008872 }, /* GL_MAX_TEXTURE_IMAGE_UNITS_ARB */
- { 18127, 0x000084FD }, /* GL_MAX_TEXTURE_LOD_BIAS */
- { 18151, 0x000084FF }, /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */
- { 18185, 0x00000D33 }, /* GL_MAX_TEXTURE_SIZE */
- { 18205, 0x00000D39 }, /* GL_MAX_TEXTURE_STACK_DEPTH */
- { 18232, 0x000084E2 }, /* GL_MAX_TEXTURE_UNITS */
- { 18253, 0x000084E2 }, /* GL_MAX_TEXTURE_UNITS_ARB */
- { 18278, 0x0000862F }, /* GL_MAX_TRACK_MATRICES_NV */
- { 18303, 0x0000862E }, /* GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV */
- { 18338, 0x00008B4B }, /* GL_MAX_VARYING_FLOATS */
- { 18360, 0x00008B4B }, /* GL_MAX_VARYING_FLOATS_ARB */
- { 18386, 0x00008869 }, /* GL_MAX_VERTEX_ATTRIBS */
- { 18408, 0x00008869 }, /* GL_MAX_VERTEX_ATTRIBS_ARB */
- { 18434, 0x00008B4C }, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS */
- { 18468, 0x00008B4C }, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */
- { 18506, 0x00008B4A }, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS */
- { 18539, 0x00008B4A }, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB */
- { 18576, 0x000086A4 }, /* GL_MAX_VERTEX_UNITS_ARB */
- { 18600, 0x00000D3A }, /* GL_MAX_VIEWPORT_DIMS */
- { 18621, 0x00008007 }, /* GL_MIN */
- { 18628, 0x0000802E }, /* GL_MINMAX */
- { 18638, 0x0000802E }, /* GL_MINMAX_EXT */
- { 18652, 0x0000802F }, /* GL_MINMAX_FORMAT */
- { 18669, 0x0000802F }, /* GL_MINMAX_FORMAT_EXT */
- { 18690, 0x00008030 }, /* GL_MINMAX_SINK */
- { 18705, 0x00008030 }, /* GL_MINMAX_SINK_EXT */
- { 18724, 0x00008007 }, /* GL_MIN_EXT */
- { 18735, 0x00008370 }, /* GL_MIRRORED_REPEAT */
- { 18754, 0x00008370 }, /* GL_MIRRORED_REPEAT_ARB */
- { 18777, 0x00008370 }, /* GL_MIRRORED_REPEAT_IBM */
- { 18800, 0x00008742 }, /* GL_MIRROR_CLAMP_ATI */
- { 18820, 0x00008742 }, /* GL_MIRROR_CLAMP_EXT */
- { 18840, 0x00008912 }, /* GL_MIRROR_CLAMP_TO_BORDER_EXT */
- { 18870, 0x00008743 }, /* GL_MIRROR_CLAMP_TO_EDGE_ATI */
- { 18898, 0x00008743 }, /* GL_MIRROR_CLAMP_TO_EDGE_EXT */
- { 18926, 0x00001700 }, /* GL_MODELVIEW */
- { 18939, 0x00001700 }, /* GL_MODELVIEW0_ARB */
- { 18957, 0x0000872A }, /* GL_MODELVIEW10_ARB */
- { 18976, 0x0000872B }, /* GL_MODELVIEW11_ARB */
- { 18995, 0x0000872C }, /* GL_MODELVIEW12_ARB */
- { 19014, 0x0000872D }, /* GL_MODELVIEW13_ARB */
- { 19033, 0x0000872E }, /* GL_MODELVIEW14_ARB */
- { 19052, 0x0000872F }, /* GL_MODELVIEW15_ARB */
- { 19071, 0x00008730 }, /* GL_MODELVIEW16_ARB */
- { 19090, 0x00008731 }, /* GL_MODELVIEW17_ARB */
- { 19109, 0x00008732 }, /* GL_MODELVIEW18_ARB */
- { 19128, 0x00008733 }, /* GL_MODELVIEW19_ARB */
- { 19147, 0x0000850A }, /* GL_MODELVIEW1_ARB */
- { 19165, 0x00008734 }, /* GL_MODELVIEW20_ARB */
- { 19184, 0x00008735 }, /* GL_MODELVIEW21_ARB */
- { 19203, 0x00008736 }, /* GL_MODELVIEW22_ARB */
- { 19222, 0x00008737 }, /* GL_MODELVIEW23_ARB */
- { 19241, 0x00008738 }, /* GL_MODELVIEW24_ARB */
- { 19260, 0x00008739 }, /* GL_MODELVIEW25_ARB */
- { 19279, 0x0000873A }, /* GL_MODELVIEW26_ARB */
- { 19298, 0x0000873B }, /* GL_MODELVIEW27_ARB */
- { 19317, 0x0000873C }, /* GL_MODELVIEW28_ARB */
- { 19336, 0x0000873D }, /* GL_MODELVIEW29_ARB */
- { 19355, 0x00008722 }, /* GL_MODELVIEW2_ARB */
- { 19373, 0x0000873E }, /* GL_MODELVIEW30_ARB */
- { 19392, 0x0000873F }, /* GL_MODELVIEW31_ARB */
- { 19411, 0x00008723 }, /* GL_MODELVIEW3_ARB */
- { 19429, 0x00008724 }, /* GL_MODELVIEW4_ARB */
- { 19447, 0x00008725 }, /* GL_MODELVIEW5_ARB */
- { 19465, 0x00008726 }, /* GL_MODELVIEW6_ARB */
- { 19483, 0x00008727 }, /* GL_MODELVIEW7_ARB */
- { 19501, 0x00008728 }, /* GL_MODELVIEW8_ARB */
- { 19519, 0x00008729 }, /* GL_MODELVIEW9_ARB */
- { 19537, 0x00000BA6 }, /* GL_MODELVIEW_MATRIX */
- { 19557, 0x00008629 }, /* GL_MODELVIEW_PROJECTION_NV */
- { 19584, 0x00000BA3 }, /* GL_MODELVIEW_STACK_DEPTH */
- { 19609, 0x00002100 }, /* GL_MODULATE */
- { 19621, 0x00008744 }, /* GL_MODULATE_ADD_ATI */
- { 19641, 0x00008745 }, /* GL_MODULATE_SIGNED_ADD_ATI */
- { 19668, 0x00008746 }, /* GL_MODULATE_SUBTRACT_ATI */
- { 19693, 0x00000103 }, /* GL_MULT */
- { 19701, 0x0000809D }, /* GL_MULTISAMPLE */
- { 19716, 0x000086B2 }, /* GL_MULTISAMPLE_3DFX */
- { 19736, 0x0000809D }, /* GL_MULTISAMPLE_ARB */
- { 19755, 0x20000000 }, /* GL_MULTISAMPLE_BIT */
- { 19774, 0x20000000 }, /* GL_MULTISAMPLE_BIT_3DFX */
- { 19798, 0x20000000 }, /* GL_MULTISAMPLE_BIT_ARB */
- { 19821, 0x00008534 }, /* GL_MULTISAMPLE_FILTER_HINT_NV */
- { 19851, 0x00002A25 }, /* GL_N3F_V3F */
- { 19862, 0x00000D70 }, /* GL_NAME_STACK_DEPTH */
- { 19882, 0x0000150E }, /* GL_NAND */
- { 19890, 0x00002600 }, /* GL_NEAREST */
- { 19901, 0x0000844E }, /* GL_NEAREST_CLIPMAP_LINEAR_SGIX */
- { 19932, 0x0000844D }, /* GL_NEAREST_CLIPMAP_NEAREST_SGIX */
- { 19964, 0x00002702 }, /* GL_NEAREST_MIPMAP_LINEAR */
- { 19989, 0x00002700 }, /* GL_NEAREST_MIPMAP_NEAREST */
- { 20015, 0x00000200 }, /* GL_NEVER */
- { 20024, 0x00001102 }, /* GL_NICEST */
- { 20034, 0x00000000 }, /* GL_NONE */
- { 20042, 0x00001505 }, /* GL_NOOP */
- { 20050, 0x00001508 }, /* GL_NOR */
- { 20057, 0x00000BA1 }, /* GL_NORMALIZE */
- { 20070, 0x00008075 }, /* GL_NORMAL_ARRAY */
- { 20086, 0x00008897 }, /* GL_NORMAL_ARRAY_BUFFER_BINDING */
- { 20117, 0x00008897 }, /* GL_NORMAL_ARRAY_BUFFER_BINDING_ARB */
- { 20152, 0x0000808F }, /* GL_NORMAL_ARRAY_POINTER */
- { 20176, 0x0000807F }, /* GL_NORMAL_ARRAY_STRIDE */
- { 20199, 0x0000807E }, /* GL_NORMAL_ARRAY_TYPE */
- { 20220, 0x00008511 }, /* GL_NORMAL_MAP */
- { 20234, 0x00008511 }, /* GL_NORMAL_MAP_ARB */
- { 20252, 0x00008511 }, /* GL_NORMAL_MAP_NV */
- { 20269, 0x00000205 }, /* GL_NOTEQUAL */
- { 20281, 0x00000000 }, /* GL_NO_ERROR */
- { 20293, 0x000086A2 }, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS */
- { 20327, 0x000086A2 }, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB */
- { 20365, 0x00008B89 }, /* GL_OBJECT_ACTIVE_ATTRIBUTES_ARB */
- { 20397, 0x00008B8A }, /* GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB */
- { 20439, 0x00008B86 }, /* GL_OBJECT_ACTIVE_UNIFORMS_ARB */
- { 20469, 0x00008B87 }, /* GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB */
- { 20509, 0x00008B85 }, /* GL_OBJECT_ATTACHED_OBJECTS_ARB */
- { 20540, 0x00008B81 }, /* GL_OBJECT_COMPILE_STATUS_ARB */
- { 20569, 0x00008B80 }, /* GL_OBJECT_DELETE_STATUS_ARB */
- { 20597, 0x00008B84 }, /* GL_OBJECT_INFO_LOG_LENGTH_ARB */
- { 20627, 0x00002401 }, /* GL_OBJECT_LINEAR */
- { 20644, 0x00008B82 }, /* GL_OBJECT_LINK_STATUS_ARB */
- { 20670, 0x00002501 }, /* GL_OBJECT_PLANE */
- { 20686, 0x00008B88 }, /* GL_OBJECT_SHADER_SOURCE_LENGTH_ARB */
- { 20721, 0x00008B4F }, /* GL_OBJECT_SUBTYPE_ARB */
- { 20743, 0x00008B4E }, /* GL_OBJECT_TYPE_ARB */
- { 20762, 0x00008B83 }, /* GL_OBJECT_VALIDATE_STATUS_ARB */
- { 20792, 0x00008165 }, /* GL_OCCLUSION_TEST_HP */
- { 20813, 0x00008166 }, /* GL_OCCLUSION_TEST_RESULT_HP */
- { 20841, 0x00000001 }, /* GL_ONE */
- { 20848, 0x00008004 }, /* GL_ONE_MINUS_CONSTANT_ALPHA */
- { 20876, 0x00008004 }, /* GL_ONE_MINUS_CONSTANT_ALPHA_EXT */
- { 20908, 0x00008002 }, /* GL_ONE_MINUS_CONSTANT_COLOR */
- { 20936, 0x00008002 }, /* GL_ONE_MINUS_CONSTANT_COLOR_EXT */
- { 20968, 0x00000305 }, /* GL_ONE_MINUS_DST_ALPHA */
- { 20991, 0x00000307 }, /* GL_ONE_MINUS_DST_COLOR */
- { 21014, 0x00000303 }, /* GL_ONE_MINUS_SRC_ALPHA */
- { 21037, 0x00000301 }, /* GL_ONE_MINUS_SRC_COLOR */
- { 21060, 0x00008598 }, /* GL_OPERAND0_ALPHA */
- { 21078, 0x00008598 }, /* GL_OPERAND0_ALPHA_ARB */
- { 21100, 0x00008598 }, /* GL_OPERAND0_ALPHA_EXT */
- { 21122, 0x00008590 }, /* GL_OPERAND0_RGB */
- { 21138, 0x00008590 }, /* GL_OPERAND0_RGB_ARB */
- { 21158, 0x00008590 }, /* GL_OPERAND0_RGB_EXT */
- { 21178, 0x00008599 }, /* GL_OPERAND1_ALPHA */
- { 21196, 0x00008599 }, /* GL_OPERAND1_ALPHA_ARB */
- { 21218, 0x00008599 }, /* GL_OPERAND1_ALPHA_EXT */
- { 21240, 0x00008591 }, /* GL_OPERAND1_RGB */
- { 21256, 0x00008591 }, /* GL_OPERAND1_RGB_ARB */
- { 21276, 0x00008591 }, /* GL_OPERAND1_RGB_EXT */
- { 21296, 0x0000859A }, /* GL_OPERAND2_ALPHA */
- { 21314, 0x0000859A }, /* GL_OPERAND2_ALPHA_ARB */
- { 21336, 0x0000859A }, /* GL_OPERAND2_ALPHA_EXT */
- { 21358, 0x00008592 }, /* GL_OPERAND2_RGB */
- { 21374, 0x00008592 }, /* GL_OPERAND2_RGB_ARB */
- { 21394, 0x00008592 }, /* GL_OPERAND2_RGB_EXT */
- { 21414, 0x0000859B }, /* GL_OPERAND3_ALPHA_NV */
- { 21435, 0x00008593 }, /* GL_OPERAND3_RGB_NV */
- { 21454, 0x00001507 }, /* GL_OR */
- { 21460, 0x00000A01 }, /* GL_ORDER */
- { 21469, 0x0000150D }, /* GL_OR_INVERTED */
- { 21484, 0x0000150B }, /* GL_OR_REVERSE */
- { 21498, 0x00000505 }, /* GL_OUT_OF_MEMORY */
- { 21515, 0x00000D05 }, /* GL_PACK_ALIGNMENT */
- { 21533, 0x0000806C }, /* GL_PACK_IMAGE_HEIGHT */
- { 21554, 0x00008758 }, /* GL_PACK_INVERT_MESA */
- { 21574, 0x00000D01 }, /* GL_PACK_LSB_FIRST */
- { 21592, 0x00000D02 }, /* GL_PACK_ROW_LENGTH */
- { 21611, 0x0000806B }, /* GL_PACK_SKIP_IMAGES */
- { 21631, 0x00000D04 }, /* GL_PACK_SKIP_PIXELS */
- { 21651, 0x00000D03 }, /* GL_PACK_SKIP_ROWS */
- { 21669, 0x00000D00 }, /* GL_PACK_SWAP_BYTES */
- { 21688, 0x00008B92 }, /* GL_PALETTE4_R5_G6_B5_OES */
- { 21713, 0x00008B94 }, /* GL_PALETTE4_RGB5_A1_OES */
- { 21737, 0x00008B90 }, /* GL_PALETTE4_RGB8_OES */
- { 21758, 0x00008B93 }, /* GL_PALETTE4_RGBA4_OES */
- { 21780, 0x00008B91 }, /* GL_PALETTE4_RGBA8_OES */
- { 21802, 0x00008B97 }, /* GL_PALETTE8_R5_G6_B5_OES */
- { 21827, 0x00008B99 }, /* GL_PALETTE8_RGB5_A1_OES */
- { 21851, 0x00008B95 }, /* GL_PALETTE8_RGB8_OES */
- { 21872, 0x00008B98 }, /* GL_PALETTE8_RGBA4_OES */
- { 21894, 0x00008B96 }, /* GL_PALETTE8_RGBA8_OES */
- { 21916, 0x00000700 }, /* GL_PASS_THROUGH_TOKEN */
- { 21938, 0x00000C50 }, /* GL_PERSPECTIVE_CORRECTION_HINT */
- { 21969, 0x00000C79 }, /* GL_PIXEL_MAP_A_TO_A */
- { 21989, 0x00000CB9 }, /* GL_PIXEL_MAP_A_TO_A_SIZE */
- { 22014, 0x00000C78 }, /* GL_PIXEL_MAP_B_TO_B */
- { 22034, 0x00000CB8 }, /* GL_PIXEL_MAP_B_TO_B_SIZE */
- { 22059, 0x00000C77 }, /* GL_PIXEL_MAP_G_TO_G */
- { 22079, 0x00000CB7 }, /* GL_PIXEL_MAP_G_TO_G_SIZE */
- { 22104, 0x00000C75 }, /* GL_PIXEL_MAP_I_TO_A */
- { 22124, 0x00000CB5 }, /* GL_PIXEL_MAP_I_TO_A_SIZE */
- { 22149, 0x00000C74 }, /* GL_PIXEL_MAP_I_TO_B */
- { 22169, 0x00000CB4 }, /* GL_PIXEL_MAP_I_TO_B_SIZE */
- { 22194, 0x00000C73 }, /* GL_PIXEL_MAP_I_TO_G */
- { 22214, 0x00000CB3 }, /* GL_PIXEL_MAP_I_TO_G_SIZE */
- { 22239, 0x00000C70 }, /* GL_PIXEL_MAP_I_TO_I */
- { 22259, 0x00000CB0 }, /* GL_PIXEL_MAP_I_TO_I_SIZE */
- { 22284, 0x00000C72 }, /* GL_PIXEL_MAP_I_TO_R */
- { 22304, 0x00000CB2 }, /* GL_PIXEL_MAP_I_TO_R_SIZE */
- { 22329, 0x00000C76 }, /* GL_PIXEL_MAP_R_TO_R */
- { 22349, 0x00000CB6 }, /* GL_PIXEL_MAP_R_TO_R_SIZE */
- { 22374, 0x00000C71 }, /* GL_PIXEL_MAP_S_TO_S */
- { 22394, 0x00000CB1 }, /* GL_PIXEL_MAP_S_TO_S_SIZE */
- { 22419, 0x00000020 }, /* GL_PIXEL_MODE_BIT */
- { 22437, 0x000088ED }, /* GL_PIXEL_PACK_BUFFER_BINDING_EXT */
- { 22470, 0x000088EB }, /* GL_PIXEL_PACK_BUFFER_EXT */
- { 22495, 0x000088EF }, /* GL_PIXEL_UNPACK_BUFFER_BINDING_EXT */
- { 22530, 0x000088EC }, /* GL_PIXEL_UNPACK_BUFFER_EXT */
- { 22557, 0x00001B00 }, /* GL_POINT */
- { 22566, 0x00000000 }, /* GL_POINTS */
- { 22576, 0x00000002 }, /* GL_POINT_BIT */
- { 22589, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION */
- { 22619, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_ARB */
- { 22653, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_EXT */
- { 22687, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_SGIS */
- { 22722, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE */
- { 22751, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_ARB */
- { 22784, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_EXT */
- { 22817, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_SGIS */
- { 22851, 0x00000B11 }, /* GL_POINT_SIZE */
- { 22865, 0x00000B13 }, /* GL_POINT_SIZE_GRANULARITY */
- { 22891, 0x00008127 }, /* GL_POINT_SIZE_MAX */
- { 22909, 0x00008127 }, /* GL_POINT_SIZE_MAX_ARB */
- { 22931, 0x00008127 }, /* GL_POINT_SIZE_MAX_EXT */
- { 22953, 0x00008127 }, /* GL_POINT_SIZE_MAX_SGIS */
- { 22976, 0x00008126 }, /* GL_POINT_SIZE_MIN */
- { 22994, 0x00008126 }, /* GL_POINT_SIZE_MIN_ARB */
- { 23016, 0x00008126 }, /* GL_POINT_SIZE_MIN_EXT */
- { 23038, 0x00008126 }, /* GL_POINT_SIZE_MIN_SGIS */
- { 23061, 0x00000B12 }, /* GL_POINT_SIZE_RANGE */
- { 23081, 0x00000B10 }, /* GL_POINT_SMOOTH */
- { 23097, 0x00000C51 }, /* GL_POINT_SMOOTH_HINT */
- { 23118, 0x00008861 }, /* GL_POINT_SPRITE */
- { 23134, 0x00008861 }, /* GL_POINT_SPRITE_ARB */
- { 23154, 0x00008CA0 }, /* GL_POINT_SPRITE_COORD_ORIGIN */
- { 23183, 0x00008861 }, /* GL_POINT_SPRITE_NV */
- { 23202, 0x00008863 }, /* GL_POINT_SPRITE_R_MODE_NV */
- { 23228, 0x00000701 }, /* GL_POINT_TOKEN */
- { 23243, 0x00000009 }, /* GL_POLYGON */
- { 23254, 0x00000008 }, /* GL_POLYGON_BIT */
- { 23269, 0x00000B40 }, /* GL_POLYGON_MODE */
- { 23285, 0x00008039 }, /* GL_POLYGON_OFFSET_BIAS */
- { 23308, 0x00008038 }, /* GL_POLYGON_OFFSET_FACTOR */
- { 23333, 0x00008037 }, /* GL_POLYGON_OFFSET_FILL */
- { 23356, 0x00002A02 }, /* GL_POLYGON_OFFSET_LINE */
- { 23379, 0x00002A01 }, /* GL_POLYGON_OFFSET_POINT */
- { 23403, 0x00002A00 }, /* GL_POLYGON_OFFSET_UNITS */
- { 23427, 0x00000B41 }, /* GL_POLYGON_SMOOTH */
- { 23445, 0x00000C53 }, /* GL_POLYGON_SMOOTH_HINT */
- { 23468, 0x00000B42 }, /* GL_POLYGON_STIPPLE */
- { 23487, 0x00000010 }, /* GL_POLYGON_STIPPLE_BIT */
- { 23510, 0x00000703 }, /* GL_POLYGON_TOKEN */
- { 23527, 0x00001203 }, /* GL_POSITION */
- { 23539, 0x000080BB }, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS */
- { 23571, 0x000080BB }, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI */
- { 23607, 0x000080B7 }, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE */
- { 23640, 0x000080B7 }, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI */
- { 23677, 0x000080BA }, /* GL_POST_COLOR_MATRIX_BLUE_BIAS */
- { 23708, 0x000080BA }, /* GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI */
- { 23743, 0x000080B6 }, /* GL_POST_COLOR_MATRIX_BLUE_SCALE */
- { 23775, 0x000080B6 }, /* GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI */
- { 23811, 0x000080D2 }, /* GL_POST_COLOR_MATRIX_COLOR_TABLE */
- { 23844, 0x000080B9 }, /* GL_POST_COLOR_MATRIX_GREEN_BIAS */
- { 23876, 0x000080B9 }, /* GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI */
- { 23912, 0x000080B5 }, /* GL_POST_COLOR_MATRIX_GREEN_SCALE */
- { 23945, 0x000080B5 }, /* GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI */
- { 23982, 0x000080B8 }, /* GL_POST_COLOR_MATRIX_RED_BIAS */
- { 24012, 0x000080B8 }, /* GL_POST_COLOR_MATRIX_RED_BIAS_SGI */
- { 24046, 0x000080B4 }, /* GL_POST_COLOR_MATRIX_RED_SCALE */
- { 24077, 0x000080B4 }, /* GL_POST_COLOR_MATRIX_RED_SCALE_SGI */
- { 24112, 0x00008023 }, /* GL_POST_CONVOLUTION_ALPHA_BIAS */
- { 24143, 0x00008023 }, /* GL_POST_CONVOLUTION_ALPHA_BIAS_EXT */
- { 24178, 0x0000801F }, /* GL_POST_CONVOLUTION_ALPHA_SCALE */
- { 24210, 0x0000801F }, /* GL_POST_CONVOLUTION_ALPHA_SCALE_EXT */
- { 24246, 0x00008022 }, /* GL_POST_CONVOLUTION_BLUE_BIAS */
- { 24276, 0x00008022 }, /* GL_POST_CONVOLUTION_BLUE_BIAS_EXT */
- { 24310, 0x0000801E }, /* GL_POST_CONVOLUTION_BLUE_SCALE */
- { 24341, 0x0000801E }, /* GL_POST_CONVOLUTION_BLUE_SCALE_EXT */
- { 24376, 0x000080D1 }, /* GL_POST_CONVOLUTION_COLOR_TABLE */
- { 24408, 0x00008021 }, /* GL_POST_CONVOLUTION_GREEN_BIAS */
- { 24439, 0x00008021 }, /* GL_POST_CONVOLUTION_GREEN_BIAS_EXT */
- { 24474, 0x0000801D }, /* GL_POST_CONVOLUTION_GREEN_SCALE */
- { 24506, 0x0000801D }, /* GL_POST_CONVOLUTION_GREEN_SCALE_EXT */
- { 24542, 0x00008020 }, /* GL_POST_CONVOLUTION_RED_BIAS */
- { 24571, 0x00008020 }, /* GL_POST_CONVOLUTION_RED_BIAS_EXT */
- { 24604, 0x0000801C }, /* GL_POST_CONVOLUTION_RED_SCALE */
- { 24634, 0x0000801C }, /* GL_POST_CONVOLUTION_RED_SCALE_EXT */
- { 24668, 0x0000817B }, /* GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX */
- { 24707, 0x00008179 }, /* GL_POST_TEXTURE_FILTER_BIAS_SGIX */
- { 24740, 0x0000817C }, /* GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX */
- { 24780, 0x0000817A }, /* GL_POST_TEXTURE_FILTER_SCALE_SGIX */
- { 24814, 0x00008578 }, /* GL_PREVIOUS */
- { 24826, 0x00008578 }, /* GL_PREVIOUS_ARB */
- { 24842, 0x00008578 }, /* GL_PREVIOUS_EXT */
- { 24858, 0x00008577 }, /* GL_PRIMARY_COLOR */
- { 24875, 0x00008577 }, /* GL_PRIMARY_COLOR_ARB */
- { 24896, 0x00008577 }, /* GL_PRIMARY_COLOR_EXT */
- { 24917, 0x000088B0 }, /* GL_PROGRAM_ADDRESS_REGISTERS_ARB */
- { 24950, 0x00008805 }, /* GL_PROGRAM_ALU_INSTRUCTIONS_ARB */
- { 24982, 0x000088AC }, /* GL_PROGRAM_ATTRIBS_ARB */
- { 25005, 0x00008677 }, /* GL_PROGRAM_BINDING_ARB */
- { 25028, 0x0000864B }, /* GL_PROGRAM_ERROR_POSITION_ARB */
- { 25058, 0x0000864B }, /* GL_PROGRAM_ERROR_POSITION_NV */
- { 25087, 0x00008874 }, /* GL_PROGRAM_ERROR_STRING_ARB */
- { 25115, 0x00008876 }, /* GL_PROGRAM_FORMAT_ARB */
- { 25137, 0x00008875 }, /* GL_PROGRAM_FORMAT_ASCII_ARB */
- { 25165, 0x000088A0 }, /* GL_PROGRAM_INSTRUCTIONS_ARB */
- { 25193, 0x00008627 }, /* GL_PROGRAM_LENGTH_ARB */
- { 25215, 0x00008627 }, /* GL_PROGRAM_LENGTH_NV */
- { 25236, 0x000088B2 }, /* GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
- { 25276, 0x00008808 }, /* GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
- { 25315, 0x000088AE }, /* GL_PROGRAM_NATIVE_ATTRIBS_ARB */
- { 25345, 0x000088A2 }, /* GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
- { 25380, 0x000088AA }, /* GL_PROGRAM_NATIVE_PARAMETERS_ARB */
- { 25413, 0x000088A6 }, /* GL_PROGRAM_NATIVE_TEMPORARIES_ARB */
- { 25447, 0x0000880A }, /* GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
- { 25486, 0x00008809 }, /* GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
- { 25525, 0x00008B40 }, /* GL_PROGRAM_OBJECT_ARB */
- { 25547, 0x000088A8 }, /* GL_PROGRAM_PARAMETERS_ARB */
- { 25573, 0x00008644 }, /* GL_PROGRAM_PARAMETER_NV */
- { 25597, 0x00008647 }, /* GL_PROGRAM_RESIDENT_NV */
- { 25620, 0x00008628 }, /* GL_PROGRAM_STRING_ARB */
- { 25642, 0x00008628 }, /* GL_PROGRAM_STRING_NV */
- { 25663, 0x00008646 }, /* GL_PROGRAM_TARGET_NV */
- { 25684, 0x000088A4 }, /* GL_PROGRAM_TEMPORARIES_ARB */
- { 25711, 0x00008807 }, /* GL_PROGRAM_TEX_INDIRECTIONS_ARB */
- { 25743, 0x00008806 }, /* GL_PROGRAM_TEX_INSTRUCTIONS_ARB */
- { 25775, 0x000088B6 }, /* GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB */
- { 25810, 0x00001701 }, /* GL_PROJECTION */
- { 25824, 0x00000BA7 }, /* GL_PROJECTION_MATRIX */
- { 25845, 0x00000BA4 }, /* GL_PROJECTION_STACK_DEPTH */
- { 25871, 0x000080D3 }, /* GL_PROXY_COLOR_TABLE */
- { 25892, 0x00008025 }, /* GL_PROXY_HISTOGRAM */
- { 25911, 0x00008025 }, /* GL_PROXY_HISTOGRAM_EXT */
- { 25934, 0x000080D5 }, /* GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE */
- { 25973, 0x000080D4 }, /* GL_PROXY_POST_CONVOLUTION_COLOR_TABLE */
- { 26011, 0x00008063 }, /* GL_PROXY_TEXTURE_1D */
- { 26031, 0x00008C19 }, /* GL_PROXY_TEXTURE_1D_ARRAY_EXT */
- { 26061, 0x00008063 }, /* GL_PROXY_TEXTURE_1D_EXT */
- { 26085, 0x00008064 }, /* GL_PROXY_TEXTURE_2D */
- { 26105, 0x00008C1B }, /* GL_PROXY_TEXTURE_2D_ARRAY_EXT */
- { 26135, 0x00008064 }, /* GL_PROXY_TEXTURE_2D_EXT */
- { 26159, 0x00008070 }, /* GL_PROXY_TEXTURE_3D */
- { 26179, 0x000080BD }, /* GL_PROXY_TEXTURE_COLOR_TABLE_SGI */
- { 26212, 0x0000851B }, /* GL_PROXY_TEXTURE_CUBE_MAP */
- { 26238, 0x0000851B }, /* GL_PROXY_TEXTURE_CUBE_MAP_ARB */
- { 26268, 0x000084F7 }, /* GL_PROXY_TEXTURE_RECTANGLE_ARB */
- { 26299, 0x000084F7 }, /* GL_PROXY_TEXTURE_RECTANGLE_NV */
- { 26329, 0x00002003 }, /* GL_Q */
- { 26334, 0x00001209 }, /* GL_QUADRATIC_ATTENUATION */
- { 26359, 0x00000007 }, /* GL_QUADS */
- { 26368, 0x00008614 }, /* GL_QUAD_MESH_SUN */
- { 26385, 0x00000008 }, /* GL_QUAD_STRIP */
- { 26399, 0x00008864 }, /* GL_QUERY_COUNTER_BITS */
- { 26421, 0x00008864 }, /* GL_QUERY_COUNTER_BITS_ARB */
- { 26447, 0x00008866 }, /* GL_QUERY_RESULT */
- { 26463, 0x00008866 }, /* GL_QUERY_RESULT_ARB */
- { 26483, 0x00008867 }, /* GL_QUERY_RESULT_AVAILABLE */
- { 26509, 0x00008867 }, /* GL_QUERY_RESULT_AVAILABLE_ARB */
- { 26539, 0x00002002 }, /* GL_R */
- { 26544, 0x00002A10 }, /* GL_R3_G3_B2 */
- { 26556, 0x00019262 }, /* GL_RASTER_POSITION_UNCLIPPED_IBM */
- { 26589, 0x00000C02 }, /* GL_READ_BUFFER */
- { 26604, 0x00008CAA }, /* GL_READ_FRAMEBUFFER_BINDING_EXT */
- { 26636, 0x00008CA8 }, /* GL_READ_FRAMEBUFFER_EXT */
- { 26660, 0x000088B8 }, /* GL_READ_ONLY */
- { 26673, 0x000088B8 }, /* GL_READ_ONLY_ARB */
- { 26690, 0x000088BA }, /* GL_READ_WRITE */
- { 26704, 0x000088BA }, /* GL_READ_WRITE_ARB */
- { 26722, 0x00001903 }, /* GL_RED */
- { 26729, 0x00008016 }, /* GL_REDUCE */
- { 26739, 0x00008016 }, /* GL_REDUCE_EXT */
- { 26753, 0x00000D15 }, /* GL_RED_BIAS */
- { 26765, 0x00000D52 }, /* GL_RED_BITS */
- { 26777, 0x00000D14 }, /* GL_RED_SCALE */
- { 26790, 0x00008512 }, /* GL_REFLECTION_MAP */
- { 26808, 0x00008512 }, /* GL_REFLECTION_MAP_ARB */
- { 26830, 0x00008512 }, /* GL_REFLECTION_MAP_NV */
- { 26851, 0x00001C00 }, /* GL_RENDER */
- { 26861, 0x00008CA7 }, /* GL_RENDERBUFFER_BINDING_EXT */
- { 26889, 0x00008D41 }, /* GL_RENDERBUFFER_EXT */
- { 26909, 0x00008D43 }, /* GL_RENDERBUFFER_HEIGHT_EXT */
- { 26936, 0x00008D44 }, /* GL_RENDERBUFFER_INTERNAL_FORMAT_EXT */
- { 26972, 0x00008D42 }, /* GL_RENDERBUFFER_WIDTH_EXT */
- { 26998, 0x00001F01 }, /* GL_RENDERER */
- { 27010, 0x00000C40 }, /* GL_RENDER_MODE */
- { 27025, 0x00002901 }, /* GL_REPEAT */
- { 27035, 0x00001E01 }, /* GL_REPLACE */
- { 27046, 0x00008062 }, /* GL_REPLACE_EXT */
- { 27061, 0x00008153 }, /* GL_REPLICATE_BORDER_HP */
- { 27084, 0x0000803A }, /* GL_RESCALE_NORMAL */
- { 27102, 0x0000803A }, /* GL_RESCALE_NORMAL_EXT */
- { 27124, 0x00000102 }, /* GL_RETURN */
- { 27134, 0x00001907 }, /* GL_RGB */
- { 27141, 0x00008052 }, /* GL_RGB10 */
- { 27150, 0x00008059 }, /* GL_RGB10_A2 */
- { 27162, 0x00008059 }, /* GL_RGB10_A2_EXT */
- { 27178, 0x00008052 }, /* GL_RGB10_EXT */
- { 27191, 0x00008053 }, /* GL_RGB12 */
- { 27200, 0x00008053 }, /* GL_RGB12_EXT */
- { 27213, 0x00008054 }, /* GL_RGB16 */
- { 27222, 0x00008054 }, /* GL_RGB16_EXT */
- { 27235, 0x0000804E }, /* GL_RGB2_EXT */
- { 27247, 0x0000804F }, /* GL_RGB4 */
- { 27255, 0x0000804F }, /* GL_RGB4_EXT */
- { 27267, 0x000083A1 }, /* GL_RGB4_S3TC */
- { 27280, 0x00008050 }, /* GL_RGB5 */
- { 27288, 0x00008057 }, /* GL_RGB5_A1 */
- { 27299, 0x00008057 }, /* GL_RGB5_A1_EXT */
- { 27314, 0x00008050 }, /* GL_RGB5_EXT */
- { 27326, 0x00008051 }, /* GL_RGB8 */
- { 27334, 0x00008051 }, /* GL_RGB8_EXT */
- { 27346, 0x00001908 }, /* GL_RGBA */
- { 27354, 0x0000805A }, /* GL_RGBA12 */
- { 27364, 0x0000805A }, /* GL_RGBA12_EXT */
- { 27378, 0x0000805B }, /* GL_RGBA16 */
- { 27388, 0x0000805B }, /* GL_RGBA16_EXT */
- { 27402, 0x00008055 }, /* GL_RGBA2 */
- { 27411, 0x00008055 }, /* GL_RGBA2_EXT */
- { 27424, 0x00008056 }, /* GL_RGBA4 */
- { 27433, 0x000083A5 }, /* GL_RGBA4_DXT5_S3TC */
- { 27452, 0x00008056 }, /* GL_RGBA4_EXT */
- { 27465, 0x000083A3 }, /* GL_RGBA4_S3TC */
- { 27479, 0x00008058 }, /* GL_RGBA8 */
- { 27488, 0x00008058 }, /* GL_RGBA8_EXT */
- { 27501, 0x000083A4 }, /* GL_RGBA_DXT5_S3TC */
- { 27519, 0x00000C31 }, /* GL_RGBA_MODE */
- { 27532, 0x000083A2 }, /* GL_RGBA_S3TC */
- { 27545, 0x000083A0 }, /* GL_RGB_S3TC */
- { 27557, 0x00008573 }, /* GL_RGB_SCALE */
- { 27570, 0x00008573 }, /* GL_RGB_SCALE_ARB */
- { 27587, 0x00008573 }, /* GL_RGB_SCALE_EXT */
- { 27604, 0x00000407 }, /* GL_RIGHT */
- { 27613, 0x00002000 }, /* GL_S */
- { 27618, 0x00008B5D }, /* GL_SAMPLER_1D */
- { 27632, 0x00008B61 }, /* GL_SAMPLER_1D_SHADOW */
- { 27653, 0x00008B5E }, /* GL_SAMPLER_2D */
- { 27667, 0x00008B62 }, /* GL_SAMPLER_2D_SHADOW */
- { 27688, 0x00008B5F }, /* GL_SAMPLER_3D */
- { 27702, 0x00008B60 }, /* GL_SAMPLER_CUBE */
- { 27718, 0x000080A9 }, /* GL_SAMPLES */
- { 27729, 0x000086B4 }, /* GL_SAMPLES_3DFX */
- { 27745, 0x000080A9 }, /* GL_SAMPLES_ARB */
- { 27760, 0x00008914 }, /* GL_SAMPLES_PASSED */
- { 27778, 0x00008914 }, /* GL_SAMPLES_PASSED_ARB */
- { 27800, 0x0000809E }, /* GL_SAMPLE_ALPHA_TO_COVERAGE */
- { 27828, 0x0000809E }, /* GL_SAMPLE_ALPHA_TO_COVERAGE_ARB */
- { 27860, 0x0000809F }, /* GL_SAMPLE_ALPHA_TO_ONE */
- { 27883, 0x0000809F }, /* GL_SAMPLE_ALPHA_TO_ONE_ARB */
- { 27910, 0x000080A8 }, /* GL_SAMPLE_BUFFERS */
- { 27928, 0x000086B3 }, /* GL_SAMPLE_BUFFERS_3DFX */
- { 27951, 0x000080A8 }, /* GL_SAMPLE_BUFFERS_ARB */
- { 27973, 0x000080A0 }, /* GL_SAMPLE_COVERAGE */
- { 27992, 0x000080A0 }, /* GL_SAMPLE_COVERAGE_ARB */
- { 28015, 0x000080AB }, /* GL_SAMPLE_COVERAGE_INVERT */
- { 28041, 0x000080AB }, /* GL_SAMPLE_COVERAGE_INVERT_ARB */
- { 28071, 0x000080AA }, /* GL_SAMPLE_COVERAGE_VALUE */
- { 28096, 0x000080AA }, /* GL_SAMPLE_COVERAGE_VALUE_ARB */
- { 28125, 0x00080000 }, /* GL_SCISSOR_BIT */
- { 28140, 0x00000C10 }, /* GL_SCISSOR_BOX */
- { 28155, 0x00000C11 }, /* GL_SCISSOR_TEST */
- { 28171, 0x0000845E }, /* GL_SECONDARY_COLOR_ARRAY */
- { 28196, 0x0000889C }, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING */
- { 28236, 0x0000889C }, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB */
- { 28280, 0x0000845D }, /* GL_SECONDARY_COLOR_ARRAY_POINTER */
- { 28313, 0x0000845A }, /* GL_SECONDARY_COLOR_ARRAY_SIZE */
- { 28343, 0x0000845C }, /* GL_SECONDARY_COLOR_ARRAY_STRIDE */
- { 28375, 0x0000845B }, /* GL_SECONDARY_COLOR_ARRAY_TYPE */
- { 28405, 0x00001C02 }, /* GL_SELECT */
- { 28415, 0x00000DF3 }, /* GL_SELECTION_BUFFER_POINTER */
- { 28443, 0x00000DF4 }, /* GL_SELECTION_BUFFER_SIZE */
- { 28468, 0x00008012 }, /* GL_SEPARABLE_2D */
- { 28484, 0x000081FA }, /* GL_SEPARATE_SPECULAR_COLOR */
- { 28511, 0x000081FA }, /* GL_SEPARATE_SPECULAR_COLOR_EXT */
- { 28542, 0x0000150F }, /* GL_SET */
- { 28549, 0x00008B48 }, /* GL_SHADER_OBJECT_ARB */
- { 28570, 0x00008B88 }, /* GL_SHADER_SOURCE_LENGTH */
- { 28594, 0x00008B4F }, /* GL_SHADER_TYPE */
- { 28609, 0x00000B54 }, /* GL_SHADE_MODEL */
- { 28624, 0x00008B8C }, /* GL_SHADING_LANGUAGE_VERSION */
- { 28652, 0x000080BF }, /* GL_SHADOW_AMBIENT_SGIX */
- { 28675, 0x000081FB }, /* GL_SHARED_TEXTURE_PALETTE_EXT */
- { 28705, 0x00001601 }, /* GL_SHININESS */
- { 28718, 0x00001402 }, /* GL_SHORT */
- { 28727, 0x000081F9 }, /* GL_SINGLE_COLOR */
- { 28743, 0x000081F9 }, /* GL_SINGLE_COLOR_EXT */
- { 28763, 0x000085CC }, /* GL_SLICE_ACCUM_SUN */
- { 28782, 0x00001D01 }, /* GL_SMOOTH */
- { 28792, 0x00000B23 }, /* GL_SMOOTH_LINE_WIDTH_GRANULARITY */
- { 28825, 0x00000B22 }, /* GL_SMOOTH_LINE_WIDTH_RANGE */
- { 28852, 0x00000B13 }, /* GL_SMOOTH_POINT_SIZE_GRANULARITY */
- { 28885, 0x00000B12 }, /* GL_SMOOTH_POINT_SIZE_RANGE */
- { 28912, 0x00008588 }, /* GL_SOURCE0_ALPHA */
- { 28929, 0x00008588 }, /* GL_SOURCE0_ALPHA_ARB */
- { 28950, 0x00008588 }, /* GL_SOURCE0_ALPHA_EXT */
- { 28971, 0x00008580 }, /* GL_SOURCE0_RGB */
- { 28986, 0x00008580 }, /* GL_SOURCE0_RGB_ARB */
- { 29005, 0x00008580 }, /* GL_SOURCE0_RGB_EXT */
- { 29024, 0x00008589 }, /* GL_SOURCE1_ALPHA */
- { 29041, 0x00008589 }, /* GL_SOURCE1_ALPHA_ARB */
- { 29062, 0x00008589 }, /* GL_SOURCE1_ALPHA_EXT */
- { 29083, 0x00008581 }, /* GL_SOURCE1_RGB */
- { 29098, 0x00008581 }, /* GL_SOURCE1_RGB_ARB */
- { 29117, 0x00008581 }, /* GL_SOURCE1_RGB_EXT */
- { 29136, 0x0000858A }, /* GL_SOURCE2_ALPHA */
- { 29153, 0x0000858A }, /* GL_SOURCE2_ALPHA_ARB */
- { 29174, 0x0000858A }, /* GL_SOURCE2_ALPHA_EXT */
- { 29195, 0x00008582 }, /* GL_SOURCE2_RGB */
- { 29210, 0x00008582 }, /* GL_SOURCE2_RGB_ARB */
- { 29229, 0x00008582 }, /* GL_SOURCE2_RGB_EXT */
- { 29248, 0x0000858B }, /* GL_SOURCE3_ALPHA_NV */
- { 29268, 0x00008583 }, /* GL_SOURCE3_RGB_NV */
- { 29286, 0x00001202 }, /* GL_SPECULAR */
- { 29298, 0x00002402 }, /* GL_SPHERE_MAP */
- { 29312, 0x00001206 }, /* GL_SPOT_CUTOFF */
- { 29327, 0x00001204 }, /* GL_SPOT_DIRECTION */
- { 29345, 0x00001205 }, /* GL_SPOT_EXPONENT */
- { 29362, 0x00008588 }, /* GL_SRC0_ALPHA */
- { 29376, 0x00008580 }, /* GL_SRC0_RGB */
- { 29388, 0x00008589 }, /* GL_SRC1_ALPHA */
- { 29402, 0x00008581 }, /* GL_SRC1_RGB */
- { 29414, 0x0000858A }, /* GL_SRC2_ALPHA */
- { 29428, 0x00008582 }, /* GL_SRC2_RGB */
- { 29440, 0x00000302 }, /* GL_SRC_ALPHA */
- { 29453, 0x00000308 }, /* GL_SRC_ALPHA_SATURATE */
- { 29475, 0x00000300 }, /* GL_SRC_COLOR */
- { 29488, 0x00000503 }, /* GL_STACK_OVERFLOW */
- { 29506, 0x00000504 }, /* GL_STACK_UNDERFLOW */
- { 29525, 0x000088E6 }, /* GL_STATIC_COPY */
- { 29540, 0x000088E6 }, /* GL_STATIC_COPY_ARB */
- { 29559, 0x000088E4 }, /* GL_STATIC_DRAW */
- { 29574, 0x000088E4 }, /* GL_STATIC_DRAW_ARB */
- { 29593, 0x000088E5 }, /* GL_STATIC_READ */
- { 29608, 0x000088E5 }, /* GL_STATIC_READ_ARB */
- { 29627, 0x00001802 }, /* GL_STENCIL */
- { 29638, 0x00008D20 }, /* GL_STENCIL_ATTACHMENT_EXT */
- { 29664, 0x00008801 }, /* GL_STENCIL_BACK_FAIL */
- { 29685, 0x00008801 }, /* GL_STENCIL_BACK_FAIL_ATI */
- { 29710, 0x00008800 }, /* GL_STENCIL_BACK_FUNC */
- { 29731, 0x00008800 }, /* GL_STENCIL_BACK_FUNC_ATI */
- { 29756, 0x00008802 }, /* GL_STENCIL_BACK_PASS_DEPTH_FAIL */
- { 29788, 0x00008802 }, /* GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI */
- { 29824, 0x00008803 }, /* GL_STENCIL_BACK_PASS_DEPTH_PASS */
- { 29856, 0x00008803 }, /* GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI */
- { 29892, 0x00008CA3 }, /* GL_STENCIL_BACK_REF */
- { 29912, 0x00008CA4 }, /* GL_STENCIL_BACK_VALUE_MASK */
- { 29939, 0x00008CA5 }, /* GL_STENCIL_BACK_WRITEMASK */
- { 29965, 0x00000D57 }, /* GL_STENCIL_BITS */
- { 29981, 0x00000400 }, /* GL_STENCIL_BUFFER_BIT */
- { 30003, 0x00000B91 }, /* GL_STENCIL_CLEAR_VALUE */
- { 30026, 0x00000B94 }, /* GL_STENCIL_FAIL */
- { 30042, 0x00000B92 }, /* GL_STENCIL_FUNC */
- { 30058, 0x00001901 }, /* GL_STENCIL_INDEX */
- { 30075, 0x00008D49 }, /* GL_STENCIL_INDEX16_EXT */
- { 30098, 0x00008D46 }, /* GL_STENCIL_INDEX1_EXT */
- { 30120, 0x00008D47 }, /* GL_STENCIL_INDEX4_EXT */
- { 30142, 0x00008D48 }, /* GL_STENCIL_INDEX8_EXT */
- { 30164, 0x00008D45 }, /* GL_STENCIL_INDEX_EXT */
- { 30185, 0x00000B95 }, /* GL_STENCIL_PASS_DEPTH_FAIL */
- { 30212, 0x00000B96 }, /* GL_STENCIL_PASS_DEPTH_PASS */
- { 30239, 0x00000B97 }, /* GL_STENCIL_REF */
- { 30254, 0x00000B90 }, /* GL_STENCIL_TEST */
- { 30270, 0x00008910 }, /* GL_STENCIL_TEST_TWO_SIDE_EXT */
- { 30299, 0x00000B93 }, /* GL_STENCIL_VALUE_MASK */
- { 30321, 0x00000B98 }, /* GL_STENCIL_WRITEMASK */
- { 30342, 0x00000C33 }, /* GL_STEREO */
- { 30352, 0x000088E2 }, /* GL_STREAM_COPY */
- { 30367, 0x000088E2 }, /* GL_STREAM_COPY_ARB */
- { 30386, 0x000088E0 }, /* GL_STREAM_DRAW */
- { 30401, 0x000088E0 }, /* GL_STREAM_DRAW_ARB */
- { 30420, 0x000088E1 }, /* GL_STREAM_READ */
- { 30435, 0x000088E1 }, /* GL_STREAM_READ_ARB */
- { 30454, 0x00000D50 }, /* GL_SUBPIXEL_BITS */
- { 30471, 0x000084E7 }, /* GL_SUBTRACT */
- { 30483, 0x000084E7 }, /* GL_SUBTRACT_ARB */
- { 30499, 0x00002001 }, /* GL_T */
- { 30504, 0x00002A2A }, /* GL_T2F_C3F_V3F */
- { 30519, 0x00002A2C }, /* GL_T2F_C4F_N3F_V3F */
- { 30538, 0x00002A29 }, /* GL_T2F_C4UB_V3F */
- { 30554, 0x00002A2B }, /* GL_T2F_N3F_V3F */
- { 30569, 0x00002A27 }, /* GL_T2F_V3F */
- { 30580, 0x00002A2D }, /* GL_T4F_C4F_N3F_V4F */
- { 30599, 0x00002A28 }, /* GL_T4F_V4F */
- { 30610, 0x00008031 }, /* GL_TABLE_TOO_LARGE_EXT */
- { 30633, 0x00001702 }, /* GL_TEXTURE */
- { 30644, 0x000084C0 }, /* GL_TEXTURE0 */
- { 30656, 0x000084C0 }, /* GL_TEXTURE0_ARB */
- { 30672, 0x000084C1 }, /* GL_TEXTURE1 */
- { 30684, 0x000084CA }, /* GL_TEXTURE10 */
- { 30697, 0x000084CA }, /* GL_TEXTURE10_ARB */
- { 30714, 0x000084CB }, /* GL_TEXTURE11 */
- { 30727, 0x000084CB }, /* GL_TEXTURE11_ARB */
- { 30744, 0x000084CC }, /* GL_TEXTURE12 */
- { 30757, 0x000084CC }, /* GL_TEXTURE12_ARB */
- { 30774, 0x000084CD }, /* GL_TEXTURE13 */
- { 30787, 0x000084CD }, /* GL_TEXTURE13_ARB */
- { 30804, 0x000084CE }, /* GL_TEXTURE14 */
- { 30817, 0x000084CE }, /* GL_TEXTURE14_ARB */
- { 30834, 0x000084CF }, /* GL_TEXTURE15 */
- { 30847, 0x000084CF }, /* GL_TEXTURE15_ARB */
- { 30864, 0x000084D0 }, /* GL_TEXTURE16 */
- { 30877, 0x000084D0 }, /* GL_TEXTURE16_ARB */
- { 30894, 0x000084D1 }, /* GL_TEXTURE17 */
- { 30907, 0x000084D1 }, /* GL_TEXTURE17_ARB */
- { 30924, 0x000084D2 }, /* GL_TEXTURE18 */
- { 30937, 0x000084D2 }, /* GL_TEXTURE18_ARB */
- { 30954, 0x000084D3 }, /* GL_TEXTURE19 */
- { 30967, 0x000084D3 }, /* GL_TEXTURE19_ARB */
- { 30984, 0x000084C1 }, /* GL_TEXTURE1_ARB */
- { 31000, 0x000084C2 }, /* GL_TEXTURE2 */
- { 31012, 0x000084D4 }, /* GL_TEXTURE20 */
- { 31025, 0x000084D4 }, /* GL_TEXTURE20_ARB */
- { 31042, 0x000084D5 }, /* GL_TEXTURE21 */
- { 31055, 0x000084D5 }, /* GL_TEXTURE21_ARB */
- { 31072, 0x000084D6 }, /* GL_TEXTURE22 */
- { 31085, 0x000084D6 }, /* GL_TEXTURE22_ARB */
- { 31102, 0x000084D7 }, /* GL_TEXTURE23 */
- { 31115, 0x000084D7 }, /* GL_TEXTURE23_ARB */
- { 31132, 0x000084D8 }, /* GL_TEXTURE24 */
- { 31145, 0x000084D8 }, /* GL_TEXTURE24_ARB */
- { 31162, 0x000084D9 }, /* GL_TEXTURE25 */
- { 31175, 0x000084D9 }, /* GL_TEXTURE25_ARB */
- { 31192, 0x000084DA }, /* GL_TEXTURE26 */
- { 31205, 0x000084DA }, /* GL_TEXTURE26_ARB */
- { 31222, 0x000084DB }, /* GL_TEXTURE27 */
- { 31235, 0x000084DB }, /* GL_TEXTURE27_ARB */
- { 31252, 0x000084DC }, /* GL_TEXTURE28 */
- { 31265, 0x000084DC }, /* GL_TEXTURE28_ARB */
- { 31282, 0x000084DD }, /* GL_TEXTURE29 */
- { 31295, 0x000084DD }, /* GL_TEXTURE29_ARB */
- { 31312, 0x000084C2 }, /* GL_TEXTURE2_ARB */
- { 31328, 0x000084C3 }, /* GL_TEXTURE3 */
- { 31340, 0x000084DE }, /* GL_TEXTURE30 */
- { 31353, 0x000084DE }, /* GL_TEXTURE30_ARB */
- { 31370, 0x000084DF }, /* GL_TEXTURE31 */
- { 31383, 0x000084DF }, /* GL_TEXTURE31_ARB */
- { 31400, 0x000084C3 }, /* GL_TEXTURE3_ARB */
- { 31416, 0x000084C4 }, /* GL_TEXTURE4 */
- { 31428, 0x000084C4 }, /* GL_TEXTURE4_ARB */
- { 31444, 0x000084C5 }, /* GL_TEXTURE5 */
- { 31456, 0x000084C5 }, /* GL_TEXTURE5_ARB */
- { 31472, 0x000084C6 }, /* GL_TEXTURE6 */
- { 31484, 0x000084C6 }, /* GL_TEXTURE6_ARB */
- { 31500, 0x000084C7 }, /* GL_TEXTURE7 */
- { 31512, 0x000084C7 }, /* GL_TEXTURE7_ARB */
- { 31528, 0x000084C8 }, /* GL_TEXTURE8 */
- { 31540, 0x000084C8 }, /* GL_TEXTURE8_ARB */
- { 31556, 0x000084C9 }, /* GL_TEXTURE9 */
- { 31568, 0x000084C9 }, /* GL_TEXTURE9_ARB */
- { 31584, 0x00000DE0 }, /* GL_TEXTURE_1D */
- { 31598, 0x00008C18 }, /* GL_TEXTURE_1D_ARRAY_EXT */
- { 31622, 0x00000DE1 }, /* GL_TEXTURE_2D */
- { 31636, 0x00008C1A }, /* GL_TEXTURE_2D_ARRAY_EXT */
- { 31660, 0x0000806F }, /* GL_TEXTURE_3D */
- { 31674, 0x0000805F }, /* GL_TEXTURE_ALPHA_SIZE */
- { 31696, 0x0000805F }, /* GL_TEXTURE_ALPHA_SIZE_EXT */
- { 31722, 0x0000813C }, /* GL_TEXTURE_BASE_LEVEL */
- { 31744, 0x00008068 }, /* GL_TEXTURE_BINDING_1D */
- { 31766, 0x00008C1C }, /* GL_TEXTURE_BINDING_1D_ARRAY_EXT */
- { 31798, 0x00008069 }, /* GL_TEXTURE_BINDING_2D */
- { 31820, 0x00008C1D }, /* GL_TEXTURE_BINDING_2D_ARRAY_EXT */
- { 31852, 0x0000806A }, /* GL_TEXTURE_BINDING_3D */
- { 31874, 0x00008514 }, /* GL_TEXTURE_BINDING_CUBE_MAP */
- { 31902, 0x00008514 }, /* GL_TEXTURE_BINDING_CUBE_MAP_ARB */
- { 31934, 0x000084F6 }, /* GL_TEXTURE_BINDING_RECTANGLE_ARB */
- { 31967, 0x000084F6 }, /* GL_TEXTURE_BINDING_RECTANGLE_NV */
- { 31999, 0x00040000 }, /* GL_TEXTURE_BIT */
- { 32014, 0x0000805E }, /* GL_TEXTURE_BLUE_SIZE */
- { 32035, 0x0000805E }, /* GL_TEXTURE_BLUE_SIZE_EXT */
- { 32060, 0x00001005 }, /* GL_TEXTURE_BORDER */
- { 32078, 0x00001004 }, /* GL_TEXTURE_BORDER_COLOR */
- { 32102, 0x00008171 }, /* GL_TEXTURE_CLIPMAP_CENTER_SGIX */
- { 32133, 0x00008176 }, /* GL_TEXTURE_CLIPMAP_DEPTH_SGIX */
- { 32163, 0x00008172 }, /* GL_TEXTURE_CLIPMAP_FRAME_SGIX */
- { 32193, 0x00008175 }, /* GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX */
- { 32228, 0x00008173 }, /* GL_TEXTURE_CLIPMAP_OFFSET_SGIX */
- { 32259, 0x00008174 }, /* GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX */
- { 32297, 0x000080BC }, /* GL_TEXTURE_COLOR_TABLE_SGI */
- { 32324, 0x000081EF }, /* GL_TEXTURE_COLOR_WRITEMASK_SGIS */
- { 32356, 0x000080BF }, /* GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
- { 32390, 0x0000884D }, /* GL_TEXTURE_COMPARE_FUNC */
- { 32414, 0x0000884D }, /* GL_TEXTURE_COMPARE_FUNC_ARB */
- { 32442, 0x0000884C }, /* GL_TEXTURE_COMPARE_MODE */
- { 32466, 0x0000884C }, /* GL_TEXTURE_COMPARE_MODE_ARB */
- { 32494, 0x0000819B }, /* GL_TEXTURE_COMPARE_OPERATOR_SGIX */
- { 32527, 0x0000819A }, /* GL_TEXTURE_COMPARE_SGIX */
- { 32551, 0x00001003 }, /* GL_TEXTURE_COMPONENTS */
- { 32573, 0x000086A1 }, /* GL_TEXTURE_COMPRESSED */
- { 32595, 0x000086A1 }, /* GL_TEXTURE_COMPRESSED_ARB */
- { 32621, 0x000086A3 }, /* GL_TEXTURE_COMPRESSED_FORMATS_ARB */
- { 32655, 0x000086A0 }, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE */
- { 32688, 0x000086A0 }, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB */
- { 32725, 0x000084EF }, /* GL_TEXTURE_COMPRESSION_HINT */
- { 32753, 0x000084EF }, /* GL_TEXTURE_COMPRESSION_HINT_ARB */
- { 32785, 0x00008078 }, /* GL_TEXTURE_COORD_ARRAY */
- { 32808, 0x0000889A }, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING */
- { 32846, 0x0000889A }, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB */
- { 32888, 0x00008092 }, /* GL_TEXTURE_COORD_ARRAY_POINTER */
- { 32919, 0x00008088 }, /* GL_TEXTURE_COORD_ARRAY_SIZE */
- { 32947, 0x0000808A }, /* GL_TEXTURE_COORD_ARRAY_STRIDE */
- { 32977, 0x00008089 }, /* GL_TEXTURE_COORD_ARRAY_TYPE */
- { 33005, 0x00008513 }, /* GL_TEXTURE_CUBE_MAP */
- { 33025, 0x00008513 }, /* GL_TEXTURE_CUBE_MAP_ARB */
- { 33049, 0x00008516 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */
- { 33080, 0x00008516 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB */
- { 33115, 0x00008518 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */
- { 33146, 0x00008518 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB */
- { 33181, 0x0000851A }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */
- { 33212, 0x0000851A }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB */
- { 33247, 0x00008515 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */
- { 33278, 0x00008515 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB */
- { 33313, 0x00008517 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */
- { 33344, 0x00008517 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB */
- { 33379, 0x00008519 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */
- { 33410, 0x00008519 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB */
- { 33445, 0x00008071 }, /* GL_TEXTURE_DEPTH */
- { 33462, 0x0000884A }, /* GL_TEXTURE_DEPTH_SIZE */
- { 33484, 0x0000884A }, /* GL_TEXTURE_DEPTH_SIZE_ARB */
- { 33510, 0x00002300 }, /* GL_TEXTURE_ENV */
- { 33525, 0x00002201 }, /* GL_TEXTURE_ENV_COLOR */
- { 33546, 0x00002200 }, /* GL_TEXTURE_ENV_MODE */
- { 33566, 0x00008500 }, /* GL_TEXTURE_FILTER_CONTROL */
- { 33592, 0x00002500 }, /* GL_TEXTURE_GEN_MODE */
- { 33612, 0x00000C63 }, /* GL_TEXTURE_GEN_Q */
- { 33629, 0x00000C62 }, /* GL_TEXTURE_GEN_R */
- { 33646, 0x00000C60 }, /* GL_TEXTURE_GEN_S */
- { 33663, 0x00000C61 }, /* GL_TEXTURE_GEN_T */
- { 33680, 0x0000819D }, /* GL_TEXTURE_GEQUAL_R_SGIX */
- { 33705, 0x0000805D }, /* GL_TEXTURE_GREEN_SIZE */
- { 33727, 0x0000805D }, /* GL_TEXTURE_GREEN_SIZE_EXT */
- { 33753, 0x00001001 }, /* GL_TEXTURE_HEIGHT */
- { 33771, 0x000080ED }, /* GL_TEXTURE_INDEX_SIZE_EXT */
- { 33797, 0x00008061 }, /* GL_TEXTURE_INTENSITY_SIZE */
- { 33823, 0x00008061 }, /* GL_TEXTURE_INTENSITY_SIZE_EXT */
- { 33853, 0x00001003 }, /* GL_TEXTURE_INTERNAL_FORMAT */
- { 33880, 0x0000819C }, /* GL_TEXTURE_LEQUAL_R_SGIX */
- { 33905, 0x00008501 }, /* GL_TEXTURE_LOD_BIAS */
- { 33925, 0x00008501 }, /* GL_TEXTURE_LOD_BIAS_EXT */
- { 33949, 0x00008190 }, /* GL_TEXTURE_LOD_BIAS_R_SGIX */
- { 33976, 0x0000818E }, /* GL_TEXTURE_LOD_BIAS_S_SGIX */
- { 34003, 0x0000818F }, /* GL_TEXTURE_LOD_BIAS_T_SGIX */
- { 34030, 0x00008060 }, /* GL_TEXTURE_LUMINANCE_SIZE */
- { 34056, 0x00008060 }, /* GL_TEXTURE_LUMINANCE_SIZE_EXT */
- { 34086, 0x00002800 }, /* GL_TEXTURE_MAG_FILTER */
- { 34108, 0x00000BA8 }, /* GL_TEXTURE_MATRIX */
- { 34126, 0x000084FE }, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */
- { 34156, 0x0000836B }, /* GL_TEXTURE_MAX_CLAMP_R_SGIX */
- { 34184, 0x00008369 }, /* GL_TEXTURE_MAX_CLAMP_S_SGIX */
- { 34212, 0x0000836A }, /* GL_TEXTURE_MAX_CLAMP_T_SGIX */
- { 34240, 0x0000813D }, /* GL_TEXTURE_MAX_LEVEL */
- { 34261, 0x0000813B }, /* GL_TEXTURE_MAX_LOD */
- { 34280, 0x00002801 }, /* GL_TEXTURE_MIN_FILTER */
- { 34302, 0x0000813A }, /* GL_TEXTURE_MIN_LOD */
- { 34321, 0x00008066 }, /* GL_TEXTURE_PRIORITY */
- { 34341, 0x000084F5 }, /* GL_TEXTURE_RECTANGLE_ARB */
- { 34366, 0x000084F5 }, /* GL_TEXTURE_RECTANGLE_NV */
- { 34390, 0x0000805C }, /* GL_TEXTURE_RED_SIZE */
- { 34410, 0x0000805C }, /* GL_TEXTURE_RED_SIZE_EXT */
- { 34434, 0x00008067 }, /* GL_TEXTURE_RESIDENT */
- { 34454, 0x00000BA5 }, /* GL_TEXTURE_STACK_DEPTH */
- { 34477, 0x00008065 }, /* GL_TEXTURE_TOO_LARGE_EXT */
- { 34502, 0x0000888F }, /* GL_TEXTURE_UNSIGNED_REMAP_MODE_NV */
- { 34536, 0x00001000 }, /* GL_TEXTURE_WIDTH */
- { 34553, 0x00008072 }, /* GL_TEXTURE_WRAP_R */
- { 34571, 0x00002802 }, /* GL_TEXTURE_WRAP_S */
- { 34589, 0x00002803 }, /* GL_TEXTURE_WRAP_T */
- { 34607, 0x000088BF }, /* GL_TIME_ELAPSED_EXT */
- { 34627, 0x00008648 }, /* GL_TRACK_MATRIX_NV */
- { 34646, 0x00008649 }, /* GL_TRACK_MATRIX_TRANSFORM_NV */
- { 34675, 0x00001000 }, /* GL_TRANSFORM_BIT */
- { 34692, 0x000084E6 }, /* GL_TRANSPOSE_COLOR_MATRIX */
- { 34718, 0x000084E6 }, /* GL_TRANSPOSE_COLOR_MATRIX_ARB */
- { 34748, 0x000088B7 }, /* GL_TRANSPOSE_CURRENT_MATRIX_ARB */
- { 34780, 0x000084E3 }, /* GL_TRANSPOSE_MODELVIEW_MATRIX */
- { 34810, 0x000084E3 }, /* GL_TRANSPOSE_MODELVIEW_MATRIX_ARB */
- { 34844, 0x0000862C }, /* GL_TRANSPOSE_NV */
- { 34860, 0x000084E4 }, /* GL_TRANSPOSE_PROJECTION_MATRIX */
- { 34891, 0x000084E4 }, /* GL_TRANSPOSE_PROJECTION_MATRIX_ARB */
- { 34926, 0x000084E5 }, /* GL_TRANSPOSE_TEXTURE_MATRIX */
- { 34954, 0x000084E5 }, /* GL_TRANSPOSE_TEXTURE_MATRIX_ARB */
- { 34986, 0x00000004 }, /* GL_TRIANGLES */
- { 34999, 0x00000006 }, /* GL_TRIANGLE_FAN */
- { 35015, 0x00008615 }, /* GL_TRIANGLE_MESH_SUN */
- { 35036, 0x00000005 }, /* GL_TRIANGLE_STRIP */
- { 35054, 0x00000001 }, /* GL_TRUE */
- { 35062, 0x00000CF5 }, /* GL_UNPACK_ALIGNMENT */
- { 35082, 0x0000806E }, /* GL_UNPACK_IMAGE_HEIGHT */
- { 35105, 0x00000CF1 }, /* GL_UNPACK_LSB_FIRST */
- { 35125, 0x00000CF2 }, /* GL_UNPACK_ROW_LENGTH */
- { 35146, 0x0000806D }, /* GL_UNPACK_SKIP_IMAGES */
- { 35168, 0x00000CF4 }, /* GL_UNPACK_SKIP_PIXELS */
- { 35190, 0x00000CF3 }, /* GL_UNPACK_SKIP_ROWS */
- { 35210, 0x00000CF0 }, /* GL_UNPACK_SWAP_BYTES */
- { 35231, 0x00001401 }, /* GL_UNSIGNED_BYTE */
- { 35248, 0x00008362 }, /* GL_UNSIGNED_BYTE_2_3_3_REV */
- { 35275, 0x00008032 }, /* GL_UNSIGNED_BYTE_3_3_2 */
- { 35298, 0x00001405 }, /* GL_UNSIGNED_INT */
- { 35314, 0x00008036 }, /* GL_UNSIGNED_INT_10_10_10_2 */
- { 35341, 0x000084FA }, /* GL_UNSIGNED_INT_24_8_NV */
- { 35365, 0x00008368 }, /* GL_UNSIGNED_INT_2_10_10_10_REV */
- { 35396, 0x00008035 }, /* GL_UNSIGNED_INT_8_8_8_8 */
- { 35420, 0x00008367 }, /* GL_UNSIGNED_INT_8_8_8_8_REV */
- { 35448, 0x00001403 }, /* GL_UNSIGNED_SHORT */
- { 35466, 0x00008366 }, /* GL_UNSIGNED_SHORT_1_5_5_5_REV */
- { 35496, 0x00008033 }, /* GL_UNSIGNED_SHORT_4_4_4_4 */
- { 35522, 0x00008365 }, /* GL_UNSIGNED_SHORT_4_4_4_4_REV */
- { 35552, 0x00008034 }, /* GL_UNSIGNED_SHORT_5_5_5_1 */
- { 35578, 0x00008363 }, /* GL_UNSIGNED_SHORT_5_6_5 */
- { 35602, 0x00008364 }, /* GL_UNSIGNED_SHORT_5_6_5_REV */
- { 35630, 0x000085BA }, /* GL_UNSIGNED_SHORT_8_8_APPLE */
- { 35658, 0x000085BA }, /* GL_UNSIGNED_SHORT_8_8_MESA */
- { 35685, 0x000085BB }, /* GL_UNSIGNED_SHORT_8_8_REV_APPLE */
- { 35717, 0x000085BB }, /* GL_UNSIGNED_SHORT_8_8_REV_MESA */
- { 35748, 0x00008CA2 }, /* GL_UPPER_LEFT */
- { 35762, 0x00002A20 }, /* GL_V2F */
- { 35769, 0x00002A21 }, /* GL_V3F */
- { 35776, 0x00008B83 }, /* GL_VALIDATE_STATUS */
- { 35795, 0x00001F00 }, /* GL_VENDOR */
- { 35805, 0x00001F02 }, /* GL_VERSION */
- { 35816, 0x00008074 }, /* GL_VERTEX_ARRAY */
- { 35832, 0x000085B5 }, /* GL_VERTEX_ARRAY_BINDING_APPLE */
- { 35862, 0x00008896 }, /* GL_VERTEX_ARRAY_BUFFER_BINDING */
- { 35893, 0x00008896 }, /* GL_VERTEX_ARRAY_BUFFER_BINDING_ARB */
- { 35928, 0x0000808E }, /* GL_VERTEX_ARRAY_POINTER */
- { 35952, 0x0000807A }, /* GL_VERTEX_ARRAY_SIZE */
- { 35973, 0x0000807C }, /* GL_VERTEX_ARRAY_STRIDE */
- { 35996, 0x0000807B }, /* GL_VERTEX_ARRAY_TYPE */
- { 36017, 0x00008650 }, /* GL_VERTEX_ATTRIB_ARRAY0_NV */
- { 36044, 0x0000865A }, /* GL_VERTEX_ATTRIB_ARRAY10_NV */
- { 36072, 0x0000865B }, /* GL_VERTEX_ATTRIB_ARRAY11_NV */
- { 36100, 0x0000865C }, /* GL_VERTEX_ATTRIB_ARRAY12_NV */
- { 36128, 0x0000865D }, /* GL_VERTEX_ATTRIB_ARRAY13_NV */
- { 36156, 0x0000865E }, /* GL_VERTEX_ATTRIB_ARRAY14_NV */
- { 36184, 0x0000865F }, /* GL_VERTEX_ATTRIB_ARRAY15_NV */
- { 36212, 0x00008651 }, /* GL_VERTEX_ATTRIB_ARRAY1_NV */
- { 36239, 0x00008652 }, /* GL_VERTEX_ATTRIB_ARRAY2_NV */
- { 36266, 0x00008653 }, /* GL_VERTEX_ATTRIB_ARRAY3_NV */
- { 36293, 0x00008654 }, /* GL_VERTEX_ATTRIB_ARRAY4_NV */
- { 36320, 0x00008655 }, /* GL_VERTEX_ATTRIB_ARRAY5_NV */
- { 36347, 0x00008656 }, /* GL_VERTEX_ATTRIB_ARRAY6_NV */
- { 36374, 0x00008657 }, /* GL_VERTEX_ATTRIB_ARRAY7_NV */
- { 36401, 0x00008658 }, /* GL_VERTEX_ATTRIB_ARRAY8_NV */
- { 36428, 0x00008659 }, /* GL_VERTEX_ATTRIB_ARRAY9_NV */
- { 36455, 0x0000889F }, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING */
- { 36493, 0x0000889F }, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB */
- { 36535, 0x00008622 }, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED */
- { 36566, 0x00008622 }, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB */
- { 36601, 0x0000886A }, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED */
- { 36635, 0x0000886A }, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB */
- { 36673, 0x00008645 }, /* GL_VERTEX_ATTRIB_ARRAY_POINTER */
- { 36704, 0x00008645 }, /* GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB */
- { 36739, 0x00008623 }, /* GL_VERTEX_ATTRIB_ARRAY_SIZE */
- { 36767, 0x00008623 }, /* GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB */
- { 36799, 0x00008624 }, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE */
- { 36829, 0x00008624 }, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB */
- { 36863, 0x00008625 }, /* GL_VERTEX_ATTRIB_ARRAY_TYPE */
- { 36891, 0x00008625 }, /* GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB */
- { 36923, 0x000086A7 }, /* GL_VERTEX_BLEND_ARB */
- { 36943, 0x00008620 }, /* GL_VERTEX_PROGRAM_ARB */
- { 36965, 0x0000864A }, /* GL_VERTEX_PROGRAM_BINDING_NV */
- { 36994, 0x00008620 }, /* GL_VERTEX_PROGRAM_NV */
- { 37015, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE */
- { 37044, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE_ARB */
- { 37077, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE_NV */
- { 37109, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE */
- { 37136, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE_ARB */
- { 37167, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE_NV */
- { 37197, 0x00008B31 }, /* GL_VERTEX_SHADER */
- { 37214, 0x00008B31 }, /* GL_VERTEX_SHADER_ARB */
- { 37235, 0x00008621 }, /* GL_VERTEX_STATE_PROGRAM_NV */
- { 37262, 0x00000BA2 }, /* GL_VIEWPORT */
- { 37274, 0x00000800 }, /* GL_VIEWPORT_BIT */
- { 37290, 0x000086AD }, /* GL_WEIGHT_ARRAY_ARB */
- { 37310, 0x0000889E }, /* GL_WEIGHT_ARRAY_BUFFER_BINDING */
- { 37341, 0x0000889E }, /* GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB */
- { 37376, 0x000086AC }, /* GL_WEIGHT_ARRAY_POINTER_ARB */
- { 37404, 0x000086AB }, /* GL_WEIGHT_ARRAY_SIZE_ARB */
- { 37429, 0x000086AA }, /* GL_WEIGHT_ARRAY_STRIDE_ARB */
- { 37456, 0x000086A9 }, /* GL_WEIGHT_ARRAY_TYPE_ARB */
- { 37481, 0x000086A6 }, /* GL_WEIGHT_SUM_UNITY_ARB */
- { 37505, 0x000081D4 }, /* GL_WRAP_BORDER_SUN */
- { 37524, 0x000088B9 }, /* GL_WRITE_ONLY */
- { 37538, 0x000088B9 }, /* GL_WRITE_ONLY_ARB */
- { 37556, 0x00001506 }, /* GL_XOR */
- { 37563, 0x000085B9 }, /* GL_YCBCR_422_APPLE */
- { 37582, 0x00008757 }, /* GL_YCBCR_MESA */
- { 37596, 0x00000000 }, /* GL_ZERO */
- { 37604, 0x00000D16 }, /* GL_ZOOM_X */
- { 37614, 0x00000D17 }, /* GL_ZOOM_Y */
+ { 779, 0x0000911A }, /* GL_ALREADY_SIGNALED */
+ { 799, 0x00000207 }, /* GL_ALWAYS */
+ { 809, 0x00001200 }, /* GL_AMBIENT */
+ { 820, 0x00001602 }, /* GL_AMBIENT_AND_DIFFUSE */
+ { 843, 0x00001501 }, /* GL_AND */
+ { 850, 0x00001504 }, /* GL_AND_INVERTED */
+ { 866, 0x00001502 }, /* GL_AND_REVERSE */
+ { 881, 0x00008892 }, /* GL_ARRAY_BUFFER */
+ { 897, 0x00008894 }, /* GL_ARRAY_BUFFER_BINDING */
+ { 921, 0x00008894 }, /* GL_ARRAY_BUFFER_BINDING_ARB */
+ { 949, 0x00008B85 }, /* GL_ATTACHED_SHADERS */
+ { 969, 0x00008645 }, /* GL_ATTRIB_ARRAY_POINTER_NV */
+ { 996, 0x00008623 }, /* GL_ATTRIB_ARRAY_SIZE_NV */
+ { 1020, 0x00008624 }, /* GL_ATTRIB_ARRAY_STRIDE_NV */
+ { 1046, 0x00008625 }, /* GL_ATTRIB_ARRAY_TYPE_NV */
+ { 1070, 0x00000BB0 }, /* GL_ATTRIB_STACK_DEPTH */
+ { 1092, 0x00000D80 }, /* GL_AUTO_NORMAL */
+ { 1107, 0x00000409 }, /* GL_AUX0 */
+ { 1115, 0x0000040A }, /* GL_AUX1 */
+ { 1123, 0x0000040B }, /* GL_AUX2 */
+ { 1131, 0x0000040C }, /* GL_AUX3 */
+ { 1139, 0x00000C00 }, /* GL_AUX_BUFFERS */
+ { 1154, 0x00000405 }, /* GL_BACK */
+ { 1162, 0x00000402 }, /* GL_BACK_LEFT */
+ { 1175, 0x00000403 }, /* GL_BACK_RIGHT */
+ { 1189, 0x000080E0 }, /* GL_BGR */
+ { 1196, 0x000080E1 }, /* GL_BGRA */
+ { 1204, 0x00001A00 }, /* GL_BITMAP */
+ { 1214, 0x00000704 }, /* GL_BITMAP_TOKEN */
+ { 1230, 0x00000BE2 }, /* GL_BLEND */
+ { 1239, 0x00008005 }, /* GL_BLEND_COLOR */
+ { 1254, 0x00008005 }, /* GL_BLEND_COLOR_EXT */
+ { 1273, 0x00000BE0 }, /* GL_BLEND_DST */
+ { 1286, 0x000080CA }, /* GL_BLEND_DST_ALPHA */
+ { 1305, 0x000080C8 }, /* GL_BLEND_DST_RGB */
+ { 1322, 0x00008009 }, /* GL_BLEND_EQUATION */
+ { 1340, 0x0000883D }, /* GL_BLEND_EQUATION_ALPHA */
+ { 1364, 0x0000883D }, /* GL_BLEND_EQUATION_ALPHA_EXT */
+ { 1392, 0x00008009 }, /* GL_BLEND_EQUATION_EXT */
+ { 1414, 0x00008009 }, /* GL_BLEND_EQUATION_RGB */
+ { 1436, 0x00008009 }, /* GL_BLEND_EQUATION_RGB_EXT */
+ { 1462, 0x00000BE1 }, /* GL_BLEND_SRC */
+ { 1475, 0x000080CB }, /* GL_BLEND_SRC_ALPHA */
+ { 1494, 0x000080C9 }, /* GL_BLEND_SRC_RGB */
+ { 1511, 0x00001905 }, /* GL_BLUE */
+ { 1519, 0x00000D1B }, /* GL_BLUE_BIAS */
+ { 1532, 0x00000D54 }, /* GL_BLUE_BITS */
+ { 1545, 0x00000D1A }, /* GL_BLUE_SCALE */
+ { 1559, 0x00008B56 }, /* GL_BOOL */
+ { 1567, 0x00008B56 }, /* GL_BOOL_ARB */
+ { 1579, 0x00008B57 }, /* GL_BOOL_VEC2 */
+ { 1592, 0x00008B57 }, /* GL_BOOL_VEC2_ARB */
+ { 1609, 0x00008B58 }, /* GL_BOOL_VEC3 */
+ { 1622, 0x00008B58 }, /* GL_BOOL_VEC3_ARB */
+ { 1639, 0x00008B59 }, /* GL_BOOL_VEC4 */
+ { 1652, 0x00008B59 }, /* GL_BOOL_VEC4_ARB */
+ { 1669, 0x000088BB }, /* GL_BUFFER_ACCESS */
+ { 1686, 0x000088BB }, /* GL_BUFFER_ACCESS_ARB */
+ { 1707, 0x00008A13 }, /* GL_BUFFER_FLUSHING_UNMAP_APPLE */
+ { 1738, 0x000088BC }, /* GL_BUFFER_MAPPED */
+ { 1755, 0x000088BC }, /* GL_BUFFER_MAPPED_ARB */
+ { 1776, 0x000088BD }, /* GL_BUFFER_MAP_POINTER */
+ { 1798, 0x000088BD }, /* GL_BUFFER_MAP_POINTER_ARB */
+ { 1824, 0x00008A12 }, /* GL_BUFFER_SERIALIZED_MODIFY_APPLE */
+ { 1858, 0x00008764 }, /* GL_BUFFER_SIZE */
+ { 1873, 0x00008764 }, /* GL_BUFFER_SIZE_ARB */
+ { 1892, 0x00008765 }, /* GL_BUFFER_USAGE */
+ { 1908, 0x00008765 }, /* GL_BUFFER_USAGE_ARB */
+ { 1928, 0x0000877B }, /* GL_BUMP_ENVMAP_ATI */
+ { 1947, 0x00008777 }, /* GL_BUMP_NUM_TEX_UNITS_ATI */
+ { 1973, 0x00008775 }, /* GL_BUMP_ROT_MATRIX_ATI */
+ { 1996, 0x00008776 }, /* GL_BUMP_ROT_MATRIX_SIZE_ATI */
+ { 2024, 0x0000877C }, /* GL_BUMP_TARGET_ATI */
+ { 2043, 0x00008778 }, /* GL_BUMP_TEX_UNITS_ATI */
+ { 2065, 0x00001400 }, /* GL_BYTE */
+ { 2073, 0x00002A24 }, /* GL_C3F_V3F */
+ { 2084, 0x00002A26 }, /* GL_C4F_N3F_V3F */
+ { 2099, 0x00002A22 }, /* GL_C4UB_V2F */
+ { 2111, 0x00002A23 }, /* GL_C4UB_V3F */
+ { 2123, 0x00000901 }, /* GL_CCW */
+ { 2130, 0x00002900 }, /* GL_CLAMP */
+ { 2139, 0x0000812D }, /* GL_CLAMP_TO_BORDER */
+ { 2158, 0x0000812D }, /* GL_CLAMP_TO_BORDER_ARB */
+ { 2181, 0x0000812D }, /* GL_CLAMP_TO_BORDER_SGIS */
+ { 2205, 0x0000812F }, /* GL_CLAMP_TO_EDGE */
+ { 2222, 0x0000812F }, /* GL_CLAMP_TO_EDGE_SGIS */
+ { 2244, 0x00001500 }, /* GL_CLEAR */
+ { 2253, 0x000084E1 }, /* GL_CLIENT_ACTIVE_TEXTURE */
+ { 2278, 0x000084E1 }, /* GL_CLIENT_ACTIVE_TEXTURE_ARB */
+ { 2307, 0xFFFFFFFF }, /* GL_CLIENT_ALL_ATTRIB_BITS */
+ { 2333, 0x00000BB1 }, /* GL_CLIENT_ATTRIB_STACK_DEPTH */
+ { 2362, 0x00000001 }, /* GL_CLIENT_PIXEL_STORE_BIT */
+ { 2388, 0x00000002 }, /* GL_CLIENT_VERTEX_ARRAY_BIT */
+ { 2415, 0x00003000 }, /* GL_CLIP_PLANE0 */
+ { 2430, 0x00003001 }, /* GL_CLIP_PLANE1 */
+ { 2445, 0x00003002 }, /* GL_CLIP_PLANE2 */
+ { 2460, 0x00003003 }, /* GL_CLIP_PLANE3 */
+ { 2475, 0x00003004 }, /* GL_CLIP_PLANE4 */
+ { 2490, 0x00003005 }, /* GL_CLIP_PLANE5 */
+ { 2505, 0x000080F0 }, /* GL_CLIP_VOLUME_CLIPPING_HINT_EXT */
+ { 2538, 0x00000A00 }, /* GL_COEFF */
+ { 2547, 0x00001800 }, /* GL_COLOR */
+ { 2556, 0x00008076 }, /* GL_COLOR_ARRAY */
+ { 2571, 0x00008898 }, /* GL_COLOR_ARRAY_BUFFER_BINDING */
+ { 2601, 0x00008898 }, /* GL_COLOR_ARRAY_BUFFER_BINDING_ARB */
+ { 2635, 0x00008090 }, /* GL_COLOR_ARRAY_POINTER */
+ { 2658, 0x00008081 }, /* GL_COLOR_ARRAY_SIZE */
+ { 2678, 0x00008083 }, /* GL_COLOR_ARRAY_STRIDE */
+ { 2700, 0x00008082 }, /* GL_COLOR_ARRAY_TYPE */
+ { 2720, 0x00008CE0 }, /* GL_COLOR_ATTACHMENT0 */
+ { 2741, 0x00008CE0 }, /* GL_COLOR_ATTACHMENT0_EXT */
+ { 2766, 0x00008CE1 }, /* GL_COLOR_ATTACHMENT1 */
+ { 2787, 0x00008CEA }, /* GL_COLOR_ATTACHMENT10 */
+ { 2809, 0x00008CEA }, /* GL_COLOR_ATTACHMENT10_EXT */
+ { 2835, 0x00008CEB }, /* GL_COLOR_ATTACHMENT11 */
+ { 2857, 0x00008CEB }, /* GL_COLOR_ATTACHMENT11_EXT */
+ { 2883, 0x00008CEC }, /* GL_COLOR_ATTACHMENT12 */
+ { 2905, 0x00008CEC }, /* GL_COLOR_ATTACHMENT12_EXT */
+ { 2931, 0x00008CED }, /* GL_COLOR_ATTACHMENT13 */
+ { 2953, 0x00008CED }, /* GL_COLOR_ATTACHMENT13_EXT */
+ { 2979, 0x00008CEE }, /* GL_COLOR_ATTACHMENT14 */
+ { 3001, 0x00008CEE }, /* GL_COLOR_ATTACHMENT14_EXT */
+ { 3027, 0x00008CEF }, /* GL_COLOR_ATTACHMENT15 */
+ { 3049, 0x00008CEF }, /* GL_COLOR_ATTACHMENT15_EXT */
+ { 3075, 0x00008CE1 }, /* GL_COLOR_ATTACHMENT1_EXT */
+ { 3100, 0x00008CE2 }, /* GL_COLOR_ATTACHMENT2 */
+ { 3121, 0x00008CE2 }, /* GL_COLOR_ATTACHMENT2_EXT */
+ { 3146, 0x00008CE3 }, /* GL_COLOR_ATTACHMENT3 */
+ { 3167, 0x00008CE3 }, /* GL_COLOR_ATTACHMENT3_EXT */
+ { 3192, 0x00008CE4 }, /* GL_COLOR_ATTACHMENT4 */
+ { 3213, 0x00008CE4 }, /* GL_COLOR_ATTACHMENT4_EXT */
+ { 3238, 0x00008CE5 }, /* GL_COLOR_ATTACHMENT5 */
+ { 3259, 0x00008CE5 }, /* GL_COLOR_ATTACHMENT5_EXT */
+ { 3284, 0x00008CE6 }, /* GL_COLOR_ATTACHMENT6 */
+ { 3305, 0x00008CE6 }, /* GL_COLOR_ATTACHMENT6_EXT */
+ { 3330, 0x00008CE7 }, /* GL_COLOR_ATTACHMENT7 */
+ { 3351, 0x00008CE7 }, /* GL_COLOR_ATTACHMENT7_EXT */
+ { 3376, 0x00008CE8 }, /* GL_COLOR_ATTACHMENT8 */
+ { 3397, 0x00008CE8 }, /* GL_COLOR_ATTACHMENT8_EXT */
+ { 3422, 0x00008CE9 }, /* GL_COLOR_ATTACHMENT9 */
+ { 3443, 0x00008CE9 }, /* GL_COLOR_ATTACHMENT9_EXT */
+ { 3468, 0x00004000 }, /* GL_COLOR_BUFFER_BIT */
+ { 3488, 0x00000C22 }, /* GL_COLOR_CLEAR_VALUE */
+ { 3509, 0x00001900 }, /* GL_COLOR_INDEX */
+ { 3524, 0x00001603 }, /* GL_COLOR_INDEXES */
+ { 3541, 0x00000BF2 }, /* GL_COLOR_LOGIC_OP */
+ { 3559, 0x00000B57 }, /* GL_COLOR_MATERIAL */
+ { 3577, 0x00000B55 }, /* GL_COLOR_MATERIAL_FACE */
+ { 3600, 0x00000B56 }, /* GL_COLOR_MATERIAL_PARAMETER */
+ { 3628, 0x000080B1 }, /* GL_COLOR_MATRIX */
+ { 3644, 0x000080B1 }, /* GL_COLOR_MATRIX_SGI */
+ { 3664, 0x000080B2 }, /* GL_COLOR_MATRIX_STACK_DEPTH */
+ { 3692, 0x000080B2 }, /* GL_COLOR_MATRIX_STACK_DEPTH_SGI */
+ { 3724, 0x00008458 }, /* GL_COLOR_SUM */
+ { 3737, 0x00008458 }, /* GL_COLOR_SUM_ARB */
+ { 3754, 0x000080D0 }, /* GL_COLOR_TABLE */
+ { 3769, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE */
+ { 3795, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE_EXT */
+ { 3825, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE_SGI */
+ { 3855, 0x000080D7 }, /* GL_COLOR_TABLE_BIAS */
+ { 3875, 0x000080D7 }, /* GL_COLOR_TABLE_BIAS_SGI */
+ { 3899, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE */
+ { 3924, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE_EXT */
+ { 3953, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE_SGI */
+ { 3982, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT */
+ { 4004, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT_EXT */
+ { 4030, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT_SGI */
+ { 4056, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE */
+ { 4082, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE_EXT */
+ { 4112, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE_SGI */
+ { 4142, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE */
+ { 4172, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE_EXT */
+ { 4206, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE_SGI */
+ { 4240, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE */
+ { 4270, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE_EXT */
+ { 4304, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE_SGI */
+ { 4338, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE */
+ { 4362, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE_EXT */
+ { 4390, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE_SGI */
+ { 4418, 0x000080D6 }, /* GL_COLOR_TABLE_SCALE */
+ { 4439, 0x000080D6 }, /* GL_COLOR_TABLE_SCALE_SGI */
+ { 4464, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH */
+ { 4485, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH_EXT */
+ { 4510, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH_SGI */
+ { 4535, 0x00000C23 }, /* GL_COLOR_WRITEMASK */
+ { 4554, 0x00008570 }, /* GL_COMBINE */
+ { 4565, 0x00008503 }, /* GL_COMBINE4 */
+ { 4577, 0x00008572 }, /* GL_COMBINE_ALPHA */
+ { 4594, 0x00008572 }, /* GL_COMBINE_ALPHA_ARB */
+ { 4615, 0x00008572 }, /* GL_COMBINE_ALPHA_EXT */
+ { 4636, 0x00008570 }, /* GL_COMBINE_ARB */
+ { 4651, 0x00008570 }, /* GL_COMBINE_EXT */
+ { 4666, 0x00008571 }, /* GL_COMBINE_RGB */
+ { 4681, 0x00008571 }, /* GL_COMBINE_RGB_ARB */
+ { 4700, 0x00008571 }, /* GL_COMBINE_RGB_EXT */
+ { 4719, 0x0000884E }, /* GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT */
+ { 4755, 0x0000884E }, /* GL_COMPARE_R_TO_TEXTURE */
+ { 4779, 0x0000884E }, /* GL_COMPARE_R_TO_TEXTURE_ARB */
+ { 4807, 0x00001300 }, /* GL_COMPILE */
+ { 4818, 0x00001301 }, /* GL_COMPILE_AND_EXECUTE */
+ { 4841, 0x00008B81 }, /* GL_COMPILE_STATUS */
+ { 4859, 0x000084E9 }, /* GL_COMPRESSED_ALPHA */
+ { 4879, 0x000084E9 }, /* GL_COMPRESSED_ALPHA_ARB */
+ { 4903, 0x000084EC }, /* GL_COMPRESSED_INTENSITY */
+ { 4927, 0x000084EC }, /* GL_COMPRESSED_INTENSITY_ARB */
+ { 4955, 0x000084EA }, /* GL_COMPRESSED_LUMINANCE */
+ { 4979, 0x000084EB }, /* GL_COMPRESSED_LUMINANCE_ALPHA */
+ { 5009, 0x000084EB }, /* GL_COMPRESSED_LUMINANCE_ALPHA_ARB */
+ { 5043, 0x000084EA }, /* GL_COMPRESSED_LUMINANCE_ARB */
+ { 5071, 0x000084ED }, /* GL_COMPRESSED_RGB */
+ { 5089, 0x000084EE }, /* GL_COMPRESSED_RGBA */
+ { 5108, 0x000084EE }, /* GL_COMPRESSED_RGBA_ARB */
+ { 5131, 0x000086B1 }, /* GL_COMPRESSED_RGBA_FXT1_3DFX */
+ { 5160, 0x000083F1 }, /* GL_COMPRESSED_RGBA_S3TC_DXT1_EXT */
+ { 5193, 0x000083F2 }, /* GL_COMPRESSED_RGBA_S3TC_DXT3_EXT */
+ { 5226, 0x000083F3 }, /* GL_COMPRESSED_RGBA_S3TC_DXT5_EXT */
+ { 5259, 0x000084ED }, /* GL_COMPRESSED_RGB_ARB */
+ { 5281, 0x000086B0 }, /* GL_COMPRESSED_RGB_FXT1_3DFX */
+ { 5309, 0x000083F0 }, /* GL_COMPRESSED_RGB_S3TC_DXT1_EXT */
+ { 5341, 0x00008C4A }, /* GL_COMPRESSED_SLUMINANCE */
+ { 5366, 0x00008C4B }, /* GL_COMPRESSED_SLUMINANCE_ALPHA */
+ { 5397, 0x00008C48 }, /* GL_COMPRESSED_SRGB */
+ { 5416, 0x00008C49 }, /* GL_COMPRESSED_SRGB_ALPHA */
+ { 5441, 0x000086A3 }, /* GL_COMPRESSED_TEXTURE_FORMATS */
+ { 5471, 0x0000911C }, /* GL_CONDITION_SATISFIED */
+ { 5494, 0x00008576 }, /* GL_CONSTANT */
+ { 5506, 0x00008003 }, /* GL_CONSTANT_ALPHA */
+ { 5524, 0x00008003 }, /* GL_CONSTANT_ALPHA_EXT */
+ { 5546, 0x00008576 }, /* GL_CONSTANT_ARB */
+ { 5562, 0x00001207 }, /* GL_CONSTANT_ATTENUATION */
+ { 5586, 0x00008151 }, /* GL_CONSTANT_BORDER_HP */
+ { 5608, 0x00008001 }, /* GL_CONSTANT_COLOR */
+ { 5626, 0x00008001 }, /* GL_CONSTANT_COLOR_EXT */
+ { 5648, 0x00008576 }, /* GL_CONSTANT_EXT */
+ { 5664, 0x00008010 }, /* GL_CONVOLUTION_1D */
+ { 5682, 0x00008011 }, /* GL_CONVOLUTION_2D */
+ { 5700, 0x00008154 }, /* GL_CONVOLUTION_BORDER_COLOR */
+ { 5728, 0x00008154 }, /* GL_CONVOLUTION_BORDER_COLOR_HP */
+ { 5759, 0x00008013 }, /* GL_CONVOLUTION_BORDER_MODE */
+ { 5786, 0x00008013 }, /* GL_CONVOLUTION_BORDER_MODE_EXT */
+ { 5817, 0x00008015 }, /* GL_CONVOLUTION_FILTER_BIAS */
+ { 5844, 0x00008015 }, /* GL_CONVOLUTION_FILTER_BIAS_EXT */
+ { 5875, 0x00008014 }, /* GL_CONVOLUTION_FILTER_SCALE */
+ { 5903, 0x00008014 }, /* GL_CONVOLUTION_FILTER_SCALE_EXT */
+ { 5935, 0x00008017 }, /* GL_CONVOLUTION_FORMAT */
+ { 5957, 0x00008017 }, /* GL_CONVOLUTION_FORMAT_EXT */
+ { 5983, 0x00008019 }, /* GL_CONVOLUTION_HEIGHT */
+ { 6005, 0x00008019 }, /* GL_CONVOLUTION_HEIGHT_EXT */
+ { 6031, 0x00008018 }, /* GL_CONVOLUTION_WIDTH */
+ { 6052, 0x00008018 }, /* GL_CONVOLUTION_WIDTH_EXT */
+ { 6077, 0x00008862 }, /* GL_COORD_REPLACE */
+ { 6094, 0x00008862 }, /* GL_COORD_REPLACE_ARB */
+ { 6115, 0x00008862 }, /* GL_COORD_REPLACE_NV */
+ { 6135, 0x00001503 }, /* GL_COPY */
+ { 6143, 0x0000150C }, /* GL_COPY_INVERTED */
+ { 6160, 0x00000706 }, /* GL_COPY_PIXEL_TOKEN */
+ { 6180, 0x00008F36 }, /* GL_COPY_READ_BUFFER */
+ { 6200, 0x00008F37 }, /* GL_COPY_WRITE_BUFFER */
+ { 6221, 0x00000B44 }, /* GL_CULL_FACE */
+ { 6234, 0x00000B45 }, /* GL_CULL_FACE_MODE */
+ { 6252, 0x000081AA }, /* GL_CULL_VERTEX_EXT */
+ { 6271, 0x000081AC }, /* GL_CULL_VERTEX_EYE_POSITION_EXT */
+ { 6303, 0x000081AB }, /* GL_CULL_VERTEX_OBJECT_POSITION_EXT */
+ { 6338, 0x00008626 }, /* GL_CURRENT_ATTRIB_NV */
+ { 6359, 0x00000001 }, /* GL_CURRENT_BIT */
+ { 6374, 0x00000B00 }, /* GL_CURRENT_COLOR */
+ { 6391, 0x00008453 }, /* GL_CURRENT_FOG_COORD */
+ { 6412, 0x00008453 }, /* GL_CURRENT_FOG_COORDINATE */
+ { 6438, 0x00000B01 }, /* GL_CURRENT_INDEX */
+ { 6455, 0x00008641 }, /* GL_CURRENT_MATRIX_ARB */
+ { 6477, 0x00008845 }, /* GL_CURRENT_MATRIX_INDEX_ARB */
+ { 6505, 0x00008641 }, /* GL_CURRENT_MATRIX_NV */
+ { 6526, 0x00008640 }, /* GL_CURRENT_MATRIX_STACK_DEPTH_ARB */
+ { 6560, 0x00008640 }, /* GL_CURRENT_MATRIX_STACK_DEPTH_NV */
+ { 6593, 0x00000B02 }, /* GL_CURRENT_NORMAL */
+ { 6611, 0x00008843 }, /* GL_CURRENT_PALETTE_MATRIX_ARB */
+ { 6641, 0x00008B8D }, /* GL_CURRENT_PROGRAM */
+ { 6660, 0x00008865 }, /* GL_CURRENT_QUERY */
+ { 6677, 0x00008865 }, /* GL_CURRENT_QUERY_ARB */
+ { 6698, 0x00000B04 }, /* GL_CURRENT_RASTER_COLOR */
+ { 6722, 0x00000B09 }, /* GL_CURRENT_RASTER_DISTANCE */
+ { 6749, 0x00000B05 }, /* GL_CURRENT_RASTER_INDEX */
+ { 6773, 0x00000B07 }, /* GL_CURRENT_RASTER_POSITION */
+ { 6800, 0x00000B08 }, /* GL_CURRENT_RASTER_POSITION_VALID */
+ { 6833, 0x0000845F }, /* GL_CURRENT_RASTER_SECONDARY_COLOR */
+ { 6867, 0x00000B06 }, /* GL_CURRENT_RASTER_TEXTURE_COORDS */
+ { 6900, 0x00008459 }, /* GL_CURRENT_SECONDARY_COLOR */
+ { 6927, 0x00000B03 }, /* GL_CURRENT_TEXTURE_COORDS */
+ { 6953, 0x00008626 }, /* GL_CURRENT_VERTEX_ATTRIB */
+ { 6978, 0x00008626 }, /* GL_CURRENT_VERTEX_ATTRIB_ARB */
+ { 7007, 0x000086A8 }, /* GL_CURRENT_WEIGHT_ARB */
+ { 7029, 0x00000900 }, /* GL_CW */
+ { 7035, 0x0000875B }, /* GL_DEBUG_ASSERT_MESA */
+ { 7056, 0x00008759 }, /* GL_DEBUG_OBJECT_MESA */
+ { 7077, 0x0000875A }, /* GL_DEBUG_PRINT_MESA */
+ { 7097, 0x00002101 }, /* GL_DECAL */
+ { 7106, 0x00001E03 }, /* GL_DECR */
+ { 7114, 0x00008508 }, /* GL_DECR_WRAP */
+ { 7127, 0x00008508 }, /* GL_DECR_WRAP_EXT */
+ { 7144, 0x00008B80 }, /* GL_DELETE_STATUS */
+ { 7161, 0x00001801 }, /* GL_DEPTH */
+ { 7170, 0x000088F0 }, /* GL_DEPTH24_STENCIL8 */
+ { 7190, 0x00008D00 }, /* GL_DEPTH_ATTACHMENT */
+ { 7210, 0x00008D00 }, /* GL_DEPTH_ATTACHMENT_EXT */
+ { 7234, 0x00000D1F }, /* GL_DEPTH_BIAS */
+ { 7248, 0x00000D56 }, /* GL_DEPTH_BITS */
+ { 7262, 0x00008891 }, /* GL_DEPTH_BOUNDS_EXT */
+ { 7282, 0x00008890 }, /* GL_DEPTH_BOUNDS_TEST_EXT */
+ { 7307, 0x00000100 }, /* GL_DEPTH_BUFFER_BIT */
+ { 7327, 0x0000864F }, /* GL_DEPTH_CLAMP */
+ { 7342, 0x0000864F }, /* GL_DEPTH_CLAMP_NV */
+ { 7360, 0x00000B73 }, /* GL_DEPTH_CLEAR_VALUE */
+ { 7381, 0x00001902 }, /* GL_DEPTH_COMPONENT */
+ { 7400, 0x000081A5 }, /* GL_DEPTH_COMPONENT16 */
+ { 7421, 0x000081A5 }, /* GL_DEPTH_COMPONENT16_ARB */
+ { 7446, 0x000081A5 }, /* GL_DEPTH_COMPONENT16_SGIX */
+ { 7472, 0x000081A6 }, /* GL_DEPTH_COMPONENT24 */
+ { 7493, 0x000081A6 }, /* GL_DEPTH_COMPONENT24_ARB */
+ { 7518, 0x000081A6 }, /* GL_DEPTH_COMPONENT24_SGIX */
+ { 7544, 0x000081A7 }, /* GL_DEPTH_COMPONENT32 */
+ { 7565, 0x000081A7 }, /* GL_DEPTH_COMPONENT32_ARB */
+ { 7590, 0x000081A7 }, /* GL_DEPTH_COMPONENT32_SGIX */
+ { 7616, 0x00000B74 }, /* GL_DEPTH_FUNC */
+ { 7630, 0x00000B70 }, /* GL_DEPTH_RANGE */
+ { 7645, 0x00000D1E }, /* GL_DEPTH_SCALE */
+ { 7660, 0x000084F9 }, /* GL_DEPTH_STENCIL */
+ { 7677, 0x0000821A }, /* GL_DEPTH_STENCIL_ATTACHMENT */
+ { 7705, 0x000084F9 }, /* GL_DEPTH_STENCIL_NV */
+ { 7725, 0x0000886F }, /* GL_DEPTH_STENCIL_TO_BGRA_NV */
+ { 7753, 0x0000886E }, /* GL_DEPTH_STENCIL_TO_RGBA_NV */
+ { 7781, 0x00000B71 }, /* GL_DEPTH_TEST */
+ { 7795, 0x0000884B }, /* GL_DEPTH_TEXTURE_MODE */
+ { 7817, 0x0000884B }, /* GL_DEPTH_TEXTURE_MODE_ARB */
+ { 7843, 0x00000B72 }, /* GL_DEPTH_WRITEMASK */
+ { 7862, 0x00001201 }, /* GL_DIFFUSE */
+ { 7873, 0x00000BD0 }, /* GL_DITHER */
+ { 7883, 0x00000A02 }, /* GL_DOMAIN */
+ { 7893, 0x00001100 }, /* GL_DONT_CARE */
+ { 7906, 0x000086AE }, /* GL_DOT3_RGB */
+ { 7918, 0x000086AF }, /* GL_DOT3_RGBA */
+ { 7931, 0x000086AF }, /* GL_DOT3_RGBA_ARB */
+ { 7948, 0x00008741 }, /* GL_DOT3_RGBA_EXT */
+ { 7965, 0x000086AE }, /* GL_DOT3_RGB_ARB */
+ { 7981, 0x00008740 }, /* GL_DOT3_RGB_EXT */
+ { 7997, 0x0000140A }, /* GL_DOUBLE */
+ { 8007, 0x00000C32 }, /* GL_DOUBLEBUFFER */
+ { 8023, 0x00000C01 }, /* GL_DRAW_BUFFER */
+ { 8038, 0x00008825 }, /* GL_DRAW_BUFFER0 */
+ { 8054, 0x00008825 }, /* GL_DRAW_BUFFER0_ARB */
+ { 8074, 0x00008825 }, /* GL_DRAW_BUFFER0_ATI */
+ { 8094, 0x00008826 }, /* GL_DRAW_BUFFER1 */
+ { 8110, 0x0000882F }, /* GL_DRAW_BUFFER10 */
+ { 8127, 0x0000882F }, /* GL_DRAW_BUFFER10_ARB */
+ { 8148, 0x0000882F }, /* GL_DRAW_BUFFER10_ATI */
+ { 8169, 0x00008830 }, /* GL_DRAW_BUFFER11 */
+ { 8186, 0x00008830 }, /* GL_DRAW_BUFFER11_ARB */
+ { 8207, 0x00008830 }, /* GL_DRAW_BUFFER11_ATI */
+ { 8228, 0x00008831 }, /* GL_DRAW_BUFFER12 */
+ { 8245, 0x00008831 }, /* GL_DRAW_BUFFER12_ARB */
+ { 8266, 0x00008831 }, /* GL_DRAW_BUFFER12_ATI */
+ { 8287, 0x00008832 }, /* GL_DRAW_BUFFER13 */
+ { 8304, 0x00008832 }, /* GL_DRAW_BUFFER13_ARB */
+ { 8325, 0x00008832 }, /* GL_DRAW_BUFFER13_ATI */
+ { 8346, 0x00008833 }, /* GL_DRAW_BUFFER14 */
+ { 8363, 0x00008833 }, /* GL_DRAW_BUFFER14_ARB */
+ { 8384, 0x00008833 }, /* GL_DRAW_BUFFER14_ATI */
+ { 8405, 0x00008834 }, /* GL_DRAW_BUFFER15 */
+ { 8422, 0x00008834 }, /* GL_DRAW_BUFFER15_ARB */
+ { 8443, 0x00008834 }, /* GL_DRAW_BUFFER15_ATI */
+ { 8464, 0x00008826 }, /* GL_DRAW_BUFFER1_ARB */
+ { 8484, 0x00008826 }, /* GL_DRAW_BUFFER1_ATI */
+ { 8504, 0x00008827 }, /* GL_DRAW_BUFFER2 */
+ { 8520, 0x00008827 }, /* GL_DRAW_BUFFER2_ARB */
+ { 8540, 0x00008827 }, /* GL_DRAW_BUFFER2_ATI */
+ { 8560, 0x00008828 }, /* GL_DRAW_BUFFER3 */
+ { 8576, 0x00008828 }, /* GL_DRAW_BUFFER3_ARB */
+ { 8596, 0x00008828 }, /* GL_DRAW_BUFFER3_ATI */
+ { 8616, 0x00008829 }, /* GL_DRAW_BUFFER4 */
+ { 8632, 0x00008829 }, /* GL_DRAW_BUFFER4_ARB */
+ { 8652, 0x00008829 }, /* GL_DRAW_BUFFER4_ATI */
+ { 8672, 0x0000882A }, /* GL_DRAW_BUFFER5 */
+ { 8688, 0x0000882A }, /* GL_DRAW_BUFFER5_ARB */
+ { 8708, 0x0000882A }, /* GL_DRAW_BUFFER5_ATI */
+ { 8728, 0x0000882B }, /* GL_DRAW_BUFFER6 */
+ { 8744, 0x0000882B }, /* GL_DRAW_BUFFER6_ARB */
+ { 8764, 0x0000882B }, /* GL_DRAW_BUFFER6_ATI */
+ { 8784, 0x0000882C }, /* GL_DRAW_BUFFER7 */
+ { 8800, 0x0000882C }, /* GL_DRAW_BUFFER7_ARB */
+ { 8820, 0x0000882C }, /* GL_DRAW_BUFFER7_ATI */
+ { 8840, 0x0000882D }, /* GL_DRAW_BUFFER8 */
+ { 8856, 0x0000882D }, /* GL_DRAW_BUFFER8_ARB */
+ { 8876, 0x0000882D }, /* GL_DRAW_BUFFER8_ATI */
+ { 8896, 0x0000882E }, /* GL_DRAW_BUFFER9 */
+ { 8912, 0x0000882E }, /* GL_DRAW_BUFFER9_ARB */
+ { 8932, 0x0000882E }, /* GL_DRAW_BUFFER9_ATI */
+ { 8952, 0x00008CA9 }, /* GL_DRAW_FRAMEBUFFER */
+ { 8972, 0x00008CA6 }, /* GL_DRAW_FRAMEBUFFER_BINDING_EXT */
+ { 9004, 0x00008CA9 }, /* GL_DRAW_FRAMEBUFFER_EXT */
+ { 9028, 0x00000705 }, /* GL_DRAW_PIXEL_TOKEN */
+ { 9048, 0x00000304 }, /* GL_DST_ALPHA */
+ { 9061, 0x00000306 }, /* GL_DST_COLOR */
+ { 9074, 0x0000877A }, /* GL_DU8DV8_ATI */
+ { 9088, 0x00008779 }, /* GL_DUDV_ATI */
+ { 9100, 0x000088EA }, /* GL_DYNAMIC_COPY */
+ { 9116, 0x000088EA }, /* GL_DYNAMIC_COPY_ARB */
+ { 9136, 0x000088E8 }, /* GL_DYNAMIC_DRAW */
+ { 9152, 0x000088E8 }, /* GL_DYNAMIC_DRAW_ARB */
+ { 9172, 0x000088E9 }, /* GL_DYNAMIC_READ */
+ { 9188, 0x000088E9 }, /* GL_DYNAMIC_READ_ARB */
+ { 9208, 0x00000B43 }, /* GL_EDGE_FLAG */
+ { 9221, 0x00008079 }, /* GL_EDGE_FLAG_ARRAY */
+ { 9240, 0x0000889B }, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING */
+ { 9274, 0x0000889B }, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB */
+ { 9312, 0x00008093 }, /* GL_EDGE_FLAG_ARRAY_POINTER */
+ { 9339, 0x0000808C }, /* GL_EDGE_FLAG_ARRAY_STRIDE */
+ { 9365, 0x00008893 }, /* GL_ELEMENT_ARRAY_BUFFER */
+ { 9389, 0x00008895 }, /* GL_ELEMENT_ARRAY_BUFFER_BINDING */
+ { 9421, 0x00008895 }, /* GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB */
+ { 9457, 0x00001600 }, /* GL_EMISSION */
+ { 9469, 0x00002000 }, /* GL_ENABLE_BIT */
+ { 9483, 0x00000202 }, /* GL_EQUAL */
+ { 9492, 0x00001509 }, /* GL_EQUIV */
+ { 9501, 0x00010000 }, /* GL_EVAL_BIT */
+ { 9513, 0x00000800 }, /* GL_EXP */
+ { 9520, 0x00000801 }, /* GL_EXP2 */
+ { 9528, 0x00001F03 }, /* GL_EXTENSIONS */
+ { 9542, 0x00002400 }, /* GL_EYE_LINEAR */
+ { 9556, 0x00002502 }, /* GL_EYE_PLANE */
+ { 9569, 0x0000855C }, /* GL_EYE_PLANE_ABSOLUTE_NV */
+ { 9594, 0x0000855B }, /* GL_EYE_RADIAL_NV */
+ { 9611, 0x00000000 }, /* GL_FALSE */
+ { 9620, 0x00001101 }, /* GL_FASTEST */
+ { 9631, 0x00001C01 }, /* GL_FEEDBACK */
+ { 9643, 0x00000DF0 }, /* GL_FEEDBACK_BUFFER_POINTER */
+ { 9670, 0x00000DF1 }, /* GL_FEEDBACK_BUFFER_SIZE */
+ { 9694, 0x00000DF2 }, /* GL_FEEDBACK_BUFFER_TYPE */
+ { 9718, 0x00001B02 }, /* GL_FILL */
+ { 9726, 0x00008E4D }, /* GL_FIRST_VERTEX_CONVENTION_EXT */
+ { 9757, 0x00001D00 }, /* GL_FLAT */
+ { 9765, 0x00001406 }, /* GL_FLOAT */
+ { 9774, 0x00008B5A }, /* GL_FLOAT_MAT2 */
+ { 9788, 0x00008B5A }, /* GL_FLOAT_MAT2_ARB */
+ { 9806, 0x00008B65 }, /* GL_FLOAT_MAT2x3 */
+ { 9822, 0x00008B66 }, /* GL_FLOAT_MAT2x4 */
+ { 9838, 0x00008B5B }, /* GL_FLOAT_MAT3 */
+ { 9852, 0x00008B5B }, /* GL_FLOAT_MAT3_ARB */
+ { 9870, 0x00008B67 }, /* GL_FLOAT_MAT3x2 */
+ { 9886, 0x00008B68 }, /* GL_FLOAT_MAT3x4 */
+ { 9902, 0x00008B5C }, /* GL_FLOAT_MAT4 */
+ { 9916, 0x00008B5C }, /* GL_FLOAT_MAT4_ARB */
+ { 9934, 0x00008B69 }, /* GL_FLOAT_MAT4x2 */
+ { 9950, 0x00008B6A }, /* GL_FLOAT_MAT4x3 */
+ { 9966, 0x00008B50 }, /* GL_FLOAT_VEC2 */
+ { 9980, 0x00008B50 }, /* GL_FLOAT_VEC2_ARB */
+ { 9998, 0x00008B51 }, /* GL_FLOAT_VEC3 */
+ { 10012, 0x00008B51 }, /* GL_FLOAT_VEC3_ARB */
+ { 10030, 0x00008B52 }, /* GL_FLOAT_VEC4 */
+ { 10044, 0x00008B52 }, /* GL_FLOAT_VEC4_ARB */
+ { 10062, 0x00000B60 }, /* GL_FOG */
+ { 10069, 0x00000080 }, /* GL_FOG_BIT */
+ { 10080, 0x00000B66 }, /* GL_FOG_COLOR */
+ { 10093, 0x00008451 }, /* GL_FOG_COORD */
+ { 10106, 0x00008451 }, /* GL_FOG_COORDINATE */
+ { 10124, 0x00008457 }, /* GL_FOG_COORDINATE_ARRAY */
+ { 10148, 0x0000889D }, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING */
+ { 10187, 0x0000889D }, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB */
+ { 10230, 0x00008456 }, /* GL_FOG_COORDINATE_ARRAY_POINTER */
+ { 10262, 0x00008455 }, /* GL_FOG_COORDINATE_ARRAY_STRIDE */
+ { 10293, 0x00008454 }, /* GL_FOG_COORDINATE_ARRAY_TYPE */
+ { 10322, 0x00008450 }, /* GL_FOG_COORDINATE_SOURCE */
+ { 10347, 0x00008457 }, /* GL_FOG_COORD_ARRAY */
+ { 10366, 0x0000889D }, /* GL_FOG_COORD_ARRAY_BUFFER_BINDING */
+ { 10400, 0x00008456 }, /* GL_FOG_COORD_ARRAY_POINTER */
+ { 10427, 0x00008455 }, /* GL_FOG_COORD_ARRAY_STRIDE */
+ { 10453, 0x00008454 }, /* GL_FOG_COORD_ARRAY_TYPE */
+ { 10477, 0x00008450 }, /* GL_FOG_COORD_SRC */
+ { 10494, 0x00000B62 }, /* GL_FOG_DENSITY */
+ { 10509, 0x0000855A }, /* GL_FOG_DISTANCE_MODE_NV */
+ { 10533, 0x00000B64 }, /* GL_FOG_END */
+ { 10544, 0x00000C54 }, /* GL_FOG_HINT */
+ { 10556, 0x00000B61 }, /* GL_FOG_INDEX */
+ { 10569, 0x00000B65 }, /* GL_FOG_MODE */
+ { 10581, 0x00008198 }, /* GL_FOG_OFFSET_SGIX */
+ { 10600, 0x00008199 }, /* GL_FOG_OFFSET_VALUE_SGIX */
+ { 10625, 0x00000B63 }, /* GL_FOG_START */
+ { 10638, 0x00008452 }, /* GL_FRAGMENT_DEPTH */
+ { 10656, 0x00008804 }, /* GL_FRAGMENT_PROGRAM_ARB */
+ { 10680, 0x00008B30 }, /* GL_FRAGMENT_SHADER */
+ { 10699, 0x00008B30 }, /* GL_FRAGMENT_SHADER_ARB */
+ { 10722, 0x00008B8B }, /* GL_FRAGMENT_SHADER_DERIVATIVE_HINT */
+ { 10757, 0x00008D40 }, /* GL_FRAMEBUFFER */
+ { 10772, 0x00008215 }, /* GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE */
+ { 10809, 0x00008214 }, /* GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE */
+ { 10845, 0x00008210 }, /* GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING */
+ { 10886, 0x00008211 }, /* GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE */
+ { 10927, 0x00008216 }, /* GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE */
+ { 10964, 0x00008213 }, /* GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE */
+ { 11001, 0x00008CD1 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME */
+ { 11039, 0x00008CD1 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT */
+ { 11081, 0x00008CD0 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE */
+ { 11119, 0x00008CD0 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT */
+ { 11161, 0x00008212 }, /* GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE */
+ { 11196, 0x00008217 }, /* GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE */
+ { 11235, 0x00008CD4 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT */
+ { 11284, 0x00008CD3 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE */
+ { 11332, 0x00008CD3 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT */
+ { 11384, 0x00008CD4 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */
+ { 11424, 0x00008CD4 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */
+ { 11468, 0x00008CD2 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL */
+ { 11508, 0x00008CD2 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT */
+ { 11552, 0x00008CA6 }, /* GL_FRAMEBUFFER_BINDING_EXT */
+ { 11579, 0x00008CD5 }, /* GL_FRAMEBUFFER_COMPLETE */
+ { 11603, 0x00008CD5 }, /* GL_FRAMEBUFFER_COMPLETE_EXT */
+ { 11631, 0x00008218 }, /* GL_FRAMEBUFFER_DEFAULT */
+ { 11654, 0x00008D40 }, /* GL_FRAMEBUFFER_EXT */
+ { 11673, 0x00008CD6 }, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT */
+ { 11710, 0x00008CD6 }, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT */
+ { 11751, 0x00008CD9 }, /* GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT */
+ { 11792, 0x00008CDB }, /* GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT */
+ { 11834, 0x00008CD8 }, /* GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT */
+ { 11885, 0x00008CDA }, /* GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT */
+ { 11923, 0x00008CD7 }, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT */
+ { 11968, 0x00008CD7 }, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT */
+ { 12017, 0x00008D56 }, /* GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE */
+ { 12055, 0x00008CDC }, /* GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT */
+ { 12097, 0x00008CDE }, /* GL_FRAMEBUFFER_STATUS_ERROR_EXT */
+ { 12129, 0x00008219 }, /* GL_FRAMEBUFFER_UNDEFINED */
+ { 12154, 0x00008CDD }, /* GL_FRAMEBUFFER_UNSUPPORTED */
+ { 12181, 0x00008CDD }, /* GL_FRAMEBUFFER_UNSUPPORTED_EXT */
+ { 12212, 0x00000404 }, /* GL_FRONT */
+ { 12221, 0x00000408 }, /* GL_FRONT_AND_BACK */
+ { 12239, 0x00000B46 }, /* GL_FRONT_FACE */
+ { 12253, 0x00000400 }, /* GL_FRONT_LEFT */
+ { 12267, 0x00000401 }, /* GL_FRONT_RIGHT */
+ { 12282, 0x00008006 }, /* GL_FUNC_ADD */
+ { 12294, 0x00008006 }, /* GL_FUNC_ADD_EXT */
+ { 12310, 0x0000800B }, /* GL_FUNC_REVERSE_SUBTRACT */
+ { 12335, 0x0000800B }, /* GL_FUNC_REVERSE_SUBTRACT_EXT */
+ { 12364, 0x0000800A }, /* GL_FUNC_SUBTRACT */
+ { 12381, 0x0000800A }, /* GL_FUNC_SUBTRACT_EXT */
+ { 12402, 0x00008191 }, /* GL_GENERATE_MIPMAP */
+ { 12421, 0x00008192 }, /* GL_GENERATE_MIPMAP_HINT */
+ { 12445, 0x00008192 }, /* GL_GENERATE_MIPMAP_HINT_SGIS */
+ { 12474, 0x00008191 }, /* GL_GENERATE_MIPMAP_SGIS */
+ { 12498, 0x00000206 }, /* GL_GEQUAL */
+ { 12508, 0x00000204 }, /* GL_GREATER */
+ { 12519, 0x00001904 }, /* GL_GREEN */
+ { 12528, 0x00000D19 }, /* GL_GREEN_BIAS */
+ { 12542, 0x00000D53 }, /* GL_GREEN_BITS */
+ { 12556, 0x00000D18 }, /* GL_GREEN_SCALE */
+ { 12571, 0x00008000 }, /* GL_HINT_BIT */
+ { 12583, 0x00008024 }, /* GL_HISTOGRAM */
+ { 12596, 0x0000802B }, /* GL_HISTOGRAM_ALPHA_SIZE */
+ { 12620, 0x0000802B }, /* GL_HISTOGRAM_ALPHA_SIZE_EXT */
+ { 12648, 0x0000802A }, /* GL_HISTOGRAM_BLUE_SIZE */
+ { 12671, 0x0000802A }, /* GL_HISTOGRAM_BLUE_SIZE_EXT */
+ { 12698, 0x00008024 }, /* GL_HISTOGRAM_EXT */
+ { 12715, 0x00008027 }, /* GL_HISTOGRAM_FORMAT */
+ { 12735, 0x00008027 }, /* GL_HISTOGRAM_FORMAT_EXT */
+ { 12759, 0x00008029 }, /* GL_HISTOGRAM_GREEN_SIZE */
+ { 12783, 0x00008029 }, /* GL_HISTOGRAM_GREEN_SIZE_EXT */
+ { 12811, 0x0000802C }, /* GL_HISTOGRAM_LUMINANCE_SIZE */
+ { 12839, 0x0000802C }, /* GL_HISTOGRAM_LUMINANCE_SIZE_EXT */
+ { 12871, 0x00008028 }, /* GL_HISTOGRAM_RED_SIZE */
+ { 12893, 0x00008028 }, /* GL_HISTOGRAM_RED_SIZE_EXT */
+ { 12919, 0x0000802D }, /* GL_HISTOGRAM_SINK */
+ { 12937, 0x0000802D }, /* GL_HISTOGRAM_SINK_EXT */
+ { 12959, 0x00008026 }, /* GL_HISTOGRAM_WIDTH */
+ { 12978, 0x00008026 }, /* GL_HISTOGRAM_WIDTH_EXT */
+ { 13001, 0x0000862A }, /* GL_IDENTITY_NV */
+ { 13016, 0x00008150 }, /* GL_IGNORE_BORDER_HP */
+ { 13036, 0x00008B9B }, /* GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES */
+ { 13076, 0x00008B9A }, /* GL_IMPLEMENTATION_COLOR_READ_TYPE_OES */
+ { 13114, 0x00001E02 }, /* GL_INCR */
+ { 13122, 0x00008507 }, /* GL_INCR_WRAP */
+ { 13135, 0x00008507 }, /* GL_INCR_WRAP_EXT */
+ { 13152, 0x00008222 }, /* GL_INDEX */
+ { 13161, 0x00008077 }, /* GL_INDEX_ARRAY */
+ { 13176, 0x00008899 }, /* GL_INDEX_ARRAY_BUFFER_BINDING */
+ { 13206, 0x00008899 }, /* GL_INDEX_ARRAY_BUFFER_BINDING_ARB */
+ { 13240, 0x00008091 }, /* GL_INDEX_ARRAY_POINTER */
+ { 13263, 0x00008086 }, /* GL_INDEX_ARRAY_STRIDE */
+ { 13285, 0x00008085 }, /* GL_INDEX_ARRAY_TYPE */
+ { 13305, 0x00000D51 }, /* GL_INDEX_BITS */
+ { 13319, 0x00000C20 }, /* GL_INDEX_CLEAR_VALUE */
+ { 13340, 0x00000BF1 }, /* GL_INDEX_LOGIC_OP */
+ { 13358, 0x00000C30 }, /* GL_INDEX_MODE */
+ { 13372, 0x00000D13 }, /* GL_INDEX_OFFSET */
+ { 13388, 0x00000D12 }, /* GL_INDEX_SHIFT */
+ { 13403, 0x00000C21 }, /* GL_INDEX_WRITEMASK */
+ { 13422, 0x00008B84 }, /* GL_INFO_LOG_LENGTH */
+ { 13441, 0x00001404 }, /* GL_INT */
+ { 13448, 0x00008049 }, /* GL_INTENSITY */
+ { 13461, 0x0000804C }, /* GL_INTENSITY12 */
+ { 13476, 0x0000804C }, /* GL_INTENSITY12_EXT */
+ { 13495, 0x0000804D }, /* GL_INTENSITY16 */
+ { 13510, 0x0000804D }, /* GL_INTENSITY16_EXT */
+ { 13529, 0x0000804A }, /* GL_INTENSITY4 */
+ { 13543, 0x0000804A }, /* GL_INTENSITY4_EXT */
+ { 13561, 0x0000804B }, /* GL_INTENSITY8 */
+ { 13575, 0x0000804B }, /* GL_INTENSITY8_EXT */
+ { 13593, 0x00008049 }, /* GL_INTENSITY_EXT */
+ { 13610, 0x00008575 }, /* GL_INTERPOLATE */
+ { 13625, 0x00008575 }, /* GL_INTERPOLATE_ARB */
+ { 13644, 0x00008575 }, /* GL_INTERPOLATE_EXT */
+ { 13663, 0x00008B53 }, /* GL_INT_VEC2 */
+ { 13675, 0x00008B53 }, /* GL_INT_VEC2_ARB */
+ { 13691, 0x00008B54 }, /* GL_INT_VEC3 */
+ { 13703, 0x00008B54 }, /* GL_INT_VEC3_ARB */
+ { 13719, 0x00008B55 }, /* GL_INT_VEC4 */
+ { 13731, 0x00008B55 }, /* GL_INT_VEC4_ARB */
+ { 13747, 0x00000500 }, /* GL_INVALID_ENUM */
+ { 13763, 0x00000506 }, /* GL_INVALID_FRAMEBUFFER_OPERATION */
+ { 13796, 0x00000506 }, /* GL_INVALID_FRAMEBUFFER_OPERATION_EXT */
+ { 13833, 0x00000502 }, /* GL_INVALID_OPERATION */
+ { 13854, 0x00000501 }, /* GL_INVALID_VALUE */
+ { 13871, 0x0000862B }, /* GL_INVERSE_NV */
+ { 13885, 0x0000862D }, /* GL_INVERSE_TRANSPOSE_NV */
+ { 13909, 0x0000150A }, /* GL_INVERT */
+ { 13919, 0x00001E00 }, /* GL_KEEP */
+ { 13927, 0x00008E4E }, /* GL_LAST_VERTEX_CONVENTION_EXT */
+ { 13957, 0x00000406 }, /* GL_LEFT */
+ { 13965, 0x00000203 }, /* GL_LEQUAL */
+ { 13975, 0x00000201 }, /* GL_LESS */
+ { 13983, 0x00004000 }, /* GL_LIGHT0 */
+ { 13993, 0x00004001 }, /* GL_LIGHT1 */
+ { 14003, 0x00004002 }, /* GL_LIGHT2 */
+ { 14013, 0x00004003 }, /* GL_LIGHT3 */
+ { 14023, 0x00004004 }, /* GL_LIGHT4 */
+ { 14033, 0x00004005 }, /* GL_LIGHT5 */
+ { 14043, 0x00004006 }, /* GL_LIGHT6 */
+ { 14053, 0x00004007 }, /* GL_LIGHT7 */
+ { 14063, 0x00000B50 }, /* GL_LIGHTING */
+ { 14075, 0x00000040 }, /* GL_LIGHTING_BIT */
+ { 14091, 0x00000B53 }, /* GL_LIGHT_MODEL_AMBIENT */
+ { 14114, 0x000081F8 }, /* GL_LIGHT_MODEL_COLOR_CONTROL */
+ { 14143, 0x000081F8 }, /* GL_LIGHT_MODEL_COLOR_CONTROL_EXT */
+ { 14176, 0x00000B51 }, /* GL_LIGHT_MODEL_LOCAL_VIEWER */
+ { 14204, 0x00000B52 }, /* GL_LIGHT_MODEL_TWO_SIDE */
+ { 14228, 0x00001B01 }, /* GL_LINE */
+ { 14236, 0x00002601 }, /* GL_LINEAR */
+ { 14246, 0x00001208 }, /* GL_LINEAR_ATTENUATION */
+ { 14268, 0x00008170 }, /* GL_LINEAR_CLIPMAP_LINEAR_SGIX */
+ { 14298, 0x0000844F }, /* GL_LINEAR_CLIPMAP_NEAREST_SGIX */
+ { 14329, 0x00002703 }, /* GL_LINEAR_MIPMAP_LINEAR */
+ { 14353, 0x00002701 }, /* GL_LINEAR_MIPMAP_NEAREST */
+ { 14378, 0x00000001 }, /* GL_LINES */
+ { 14387, 0x00000004 }, /* GL_LINE_BIT */
+ { 14399, 0x00000002 }, /* GL_LINE_LOOP */
+ { 14412, 0x00000707 }, /* GL_LINE_RESET_TOKEN */
+ { 14432, 0x00000B20 }, /* GL_LINE_SMOOTH */
+ { 14447, 0x00000C52 }, /* GL_LINE_SMOOTH_HINT */
+ { 14467, 0x00000B24 }, /* GL_LINE_STIPPLE */
+ { 14483, 0x00000B25 }, /* GL_LINE_STIPPLE_PATTERN */
+ { 14507, 0x00000B26 }, /* GL_LINE_STIPPLE_REPEAT */
+ { 14530, 0x00000003 }, /* GL_LINE_STRIP */
+ { 14544, 0x00000702 }, /* GL_LINE_TOKEN */
+ { 14558, 0x00000B21 }, /* GL_LINE_WIDTH */
+ { 14572, 0x00000B23 }, /* GL_LINE_WIDTH_GRANULARITY */
+ { 14598, 0x00000B22 }, /* GL_LINE_WIDTH_RANGE */
+ { 14618, 0x00008B82 }, /* GL_LINK_STATUS */
+ { 14633, 0x00000B32 }, /* GL_LIST_BASE */
+ { 14646, 0x00020000 }, /* GL_LIST_BIT */
+ { 14658, 0x00000B33 }, /* GL_LIST_INDEX */
+ { 14672, 0x00000B30 }, /* GL_LIST_MODE */
+ { 14685, 0x00000101 }, /* GL_LOAD */
+ { 14693, 0x00000BF1 }, /* GL_LOGIC_OP */
+ { 14705, 0x00000BF0 }, /* GL_LOGIC_OP_MODE */
+ { 14722, 0x00008CA1 }, /* GL_LOWER_LEFT */
+ { 14736, 0x00001909 }, /* GL_LUMINANCE */
+ { 14749, 0x00008041 }, /* GL_LUMINANCE12 */
+ { 14764, 0x00008047 }, /* GL_LUMINANCE12_ALPHA12 */
+ { 14787, 0x00008047 }, /* GL_LUMINANCE12_ALPHA12_EXT */
+ { 14814, 0x00008046 }, /* GL_LUMINANCE12_ALPHA4 */
+ { 14836, 0x00008046 }, /* GL_LUMINANCE12_ALPHA4_EXT */
+ { 14862, 0x00008041 }, /* GL_LUMINANCE12_EXT */
+ { 14881, 0x00008042 }, /* GL_LUMINANCE16 */
+ { 14896, 0x00008048 }, /* GL_LUMINANCE16_ALPHA16 */
+ { 14919, 0x00008048 }, /* GL_LUMINANCE16_ALPHA16_EXT */
+ { 14946, 0x00008042 }, /* GL_LUMINANCE16_EXT */
+ { 14965, 0x0000803F }, /* GL_LUMINANCE4 */
+ { 14979, 0x00008043 }, /* GL_LUMINANCE4_ALPHA4 */
+ { 15000, 0x00008043 }, /* GL_LUMINANCE4_ALPHA4_EXT */
+ { 15025, 0x0000803F }, /* GL_LUMINANCE4_EXT */
+ { 15043, 0x00008044 }, /* GL_LUMINANCE6_ALPHA2 */
+ { 15064, 0x00008044 }, /* GL_LUMINANCE6_ALPHA2_EXT */
+ { 15089, 0x00008040 }, /* GL_LUMINANCE8 */
+ { 15103, 0x00008045 }, /* GL_LUMINANCE8_ALPHA8 */
+ { 15124, 0x00008045 }, /* GL_LUMINANCE8_ALPHA8_EXT */
+ { 15149, 0x00008040 }, /* GL_LUMINANCE8_EXT */
+ { 15167, 0x0000190A }, /* GL_LUMINANCE_ALPHA */
+ { 15186, 0x00000D90 }, /* GL_MAP1_COLOR_4 */
+ { 15202, 0x00000DD0 }, /* GL_MAP1_GRID_DOMAIN */
+ { 15222, 0x00000DD1 }, /* GL_MAP1_GRID_SEGMENTS */
+ { 15244, 0x00000D91 }, /* GL_MAP1_INDEX */
+ { 15258, 0x00000D92 }, /* GL_MAP1_NORMAL */
+ { 15273, 0x00000D93 }, /* GL_MAP1_TEXTURE_COORD_1 */
+ { 15297, 0x00000D94 }, /* GL_MAP1_TEXTURE_COORD_2 */
+ { 15321, 0x00000D95 }, /* GL_MAP1_TEXTURE_COORD_3 */
+ { 15345, 0x00000D96 }, /* GL_MAP1_TEXTURE_COORD_4 */
+ { 15369, 0x00000D97 }, /* GL_MAP1_VERTEX_3 */
+ { 15386, 0x00000D98 }, /* GL_MAP1_VERTEX_4 */
+ { 15403, 0x00008660 }, /* GL_MAP1_VERTEX_ATTRIB0_4_NV */
+ { 15431, 0x0000866A }, /* GL_MAP1_VERTEX_ATTRIB10_4_NV */
+ { 15460, 0x0000866B }, /* GL_MAP1_VERTEX_ATTRIB11_4_NV */
+ { 15489, 0x0000866C }, /* GL_MAP1_VERTEX_ATTRIB12_4_NV */
+ { 15518, 0x0000866D }, /* GL_MAP1_VERTEX_ATTRIB13_4_NV */
+ { 15547, 0x0000866E }, /* GL_MAP1_VERTEX_ATTRIB14_4_NV */
+ { 15576, 0x0000866F }, /* GL_MAP1_VERTEX_ATTRIB15_4_NV */
+ { 15605, 0x00008661 }, /* GL_MAP1_VERTEX_ATTRIB1_4_NV */
+ { 15633, 0x00008662 }, /* GL_MAP1_VERTEX_ATTRIB2_4_NV */
+ { 15661, 0x00008663 }, /* GL_MAP1_VERTEX_ATTRIB3_4_NV */
+ { 15689, 0x00008664 }, /* GL_MAP1_VERTEX_ATTRIB4_4_NV */
+ { 15717, 0x00008665 }, /* GL_MAP1_VERTEX_ATTRIB5_4_NV */
+ { 15745, 0x00008666 }, /* GL_MAP1_VERTEX_ATTRIB6_4_NV */
+ { 15773, 0x00008667 }, /* GL_MAP1_VERTEX_ATTRIB7_4_NV */
+ { 15801, 0x00008668 }, /* GL_MAP1_VERTEX_ATTRIB8_4_NV */
+ { 15829, 0x00008669 }, /* GL_MAP1_VERTEX_ATTRIB9_4_NV */
+ { 15857, 0x00000DB0 }, /* GL_MAP2_COLOR_4 */
+ { 15873, 0x00000DD2 }, /* GL_MAP2_GRID_DOMAIN */
+ { 15893, 0x00000DD3 }, /* GL_MAP2_GRID_SEGMENTS */
+ { 15915, 0x00000DB1 }, /* GL_MAP2_INDEX */
+ { 15929, 0x00000DB2 }, /* GL_MAP2_NORMAL */
+ { 15944, 0x00000DB3 }, /* GL_MAP2_TEXTURE_COORD_1 */
+ { 15968, 0x00000DB4 }, /* GL_MAP2_TEXTURE_COORD_2 */
+ { 15992, 0x00000DB5 }, /* GL_MAP2_TEXTURE_COORD_3 */
+ { 16016, 0x00000DB6 }, /* GL_MAP2_TEXTURE_COORD_4 */
+ { 16040, 0x00000DB7 }, /* GL_MAP2_VERTEX_3 */
+ { 16057, 0x00000DB8 }, /* GL_MAP2_VERTEX_4 */
+ { 16074, 0x00008670 }, /* GL_MAP2_VERTEX_ATTRIB0_4_NV */
+ { 16102, 0x0000867A }, /* GL_MAP2_VERTEX_ATTRIB10_4_NV */
+ { 16131, 0x0000867B }, /* GL_MAP2_VERTEX_ATTRIB11_4_NV */
+ { 16160, 0x0000867C }, /* GL_MAP2_VERTEX_ATTRIB12_4_NV */
+ { 16189, 0x0000867D }, /* GL_MAP2_VERTEX_ATTRIB13_4_NV */
+ { 16218, 0x0000867E }, /* GL_MAP2_VERTEX_ATTRIB14_4_NV */
+ { 16247, 0x0000867F }, /* GL_MAP2_VERTEX_ATTRIB15_4_NV */
+ { 16276, 0x00008671 }, /* GL_MAP2_VERTEX_ATTRIB1_4_NV */
+ { 16304, 0x00008672 }, /* GL_MAP2_VERTEX_ATTRIB2_4_NV */
+ { 16332, 0x00008673 }, /* GL_MAP2_VERTEX_ATTRIB3_4_NV */
+ { 16360, 0x00008674 }, /* GL_MAP2_VERTEX_ATTRIB4_4_NV */
+ { 16388, 0x00008675 }, /* GL_MAP2_VERTEX_ATTRIB5_4_NV */
+ { 16416, 0x00008676 }, /* GL_MAP2_VERTEX_ATTRIB6_4_NV */
+ { 16444, 0x00008677 }, /* GL_MAP2_VERTEX_ATTRIB7_4_NV */
+ { 16472, 0x00008678 }, /* GL_MAP2_VERTEX_ATTRIB8_4_NV */
+ { 16500, 0x00008679 }, /* GL_MAP2_VERTEX_ATTRIB9_4_NV */
+ { 16528, 0x00000D10 }, /* GL_MAP_COLOR */
+ { 16541, 0x00000010 }, /* GL_MAP_FLUSH_EXPLICIT_BIT */
+ { 16567, 0x00000008 }, /* GL_MAP_INVALIDATE_BUFFER_BIT */
+ { 16596, 0x00000004 }, /* GL_MAP_INVALIDATE_RANGE_BIT */
+ { 16624, 0x00000001 }, /* GL_MAP_READ_BIT */
+ { 16640, 0x00000D11 }, /* GL_MAP_STENCIL */
+ { 16655, 0x00000020 }, /* GL_MAP_UNSYNCHRONIZED_BIT */
+ { 16681, 0x00000002 }, /* GL_MAP_WRITE_BIT */
+ { 16698, 0x000088C0 }, /* GL_MATRIX0_ARB */
+ { 16713, 0x00008630 }, /* GL_MATRIX0_NV */
+ { 16727, 0x000088CA }, /* GL_MATRIX10_ARB */
+ { 16743, 0x000088CB }, /* GL_MATRIX11_ARB */
+ { 16759, 0x000088CC }, /* GL_MATRIX12_ARB */
+ { 16775, 0x000088CD }, /* GL_MATRIX13_ARB */
+ { 16791, 0x000088CE }, /* GL_MATRIX14_ARB */
+ { 16807, 0x000088CF }, /* GL_MATRIX15_ARB */
+ { 16823, 0x000088D0 }, /* GL_MATRIX16_ARB */
+ { 16839, 0x000088D1 }, /* GL_MATRIX17_ARB */
+ { 16855, 0x000088D2 }, /* GL_MATRIX18_ARB */
+ { 16871, 0x000088D3 }, /* GL_MATRIX19_ARB */
+ { 16887, 0x000088C1 }, /* GL_MATRIX1_ARB */
+ { 16902, 0x00008631 }, /* GL_MATRIX1_NV */
+ { 16916, 0x000088D4 }, /* GL_MATRIX20_ARB */
+ { 16932, 0x000088D5 }, /* GL_MATRIX21_ARB */
+ { 16948, 0x000088D6 }, /* GL_MATRIX22_ARB */
+ { 16964, 0x000088D7 }, /* GL_MATRIX23_ARB */
+ { 16980, 0x000088D8 }, /* GL_MATRIX24_ARB */
+ { 16996, 0x000088D9 }, /* GL_MATRIX25_ARB */
+ { 17012, 0x000088DA }, /* GL_MATRIX26_ARB */
+ { 17028, 0x000088DB }, /* GL_MATRIX27_ARB */
+ { 17044, 0x000088DC }, /* GL_MATRIX28_ARB */
+ { 17060, 0x000088DD }, /* GL_MATRIX29_ARB */
+ { 17076, 0x000088C2 }, /* GL_MATRIX2_ARB */
+ { 17091, 0x00008632 }, /* GL_MATRIX2_NV */
+ { 17105, 0x000088DE }, /* GL_MATRIX30_ARB */
+ { 17121, 0x000088DF }, /* GL_MATRIX31_ARB */
+ { 17137, 0x000088C3 }, /* GL_MATRIX3_ARB */
+ { 17152, 0x00008633 }, /* GL_MATRIX3_NV */
+ { 17166, 0x000088C4 }, /* GL_MATRIX4_ARB */
+ { 17181, 0x00008634 }, /* GL_MATRIX4_NV */
+ { 17195, 0x000088C5 }, /* GL_MATRIX5_ARB */
+ { 17210, 0x00008635 }, /* GL_MATRIX5_NV */
+ { 17224, 0x000088C6 }, /* GL_MATRIX6_ARB */
+ { 17239, 0x00008636 }, /* GL_MATRIX6_NV */
+ { 17253, 0x000088C7 }, /* GL_MATRIX7_ARB */
+ { 17268, 0x00008637 }, /* GL_MATRIX7_NV */
+ { 17282, 0x000088C8 }, /* GL_MATRIX8_ARB */
+ { 17297, 0x000088C9 }, /* GL_MATRIX9_ARB */
+ { 17312, 0x00008844 }, /* GL_MATRIX_INDEX_ARRAY_ARB */
+ { 17338, 0x00008849 }, /* GL_MATRIX_INDEX_ARRAY_POINTER_ARB */
+ { 17372, 0x00008846 }, /* GL_MATRIX_INDEX_ARRAY_SIZE_ARB */
+ { 17403, 0x00008848 }, /* GL_MATRIX_INDEX_ARRAY_STRIDE_ARB */
+ { 17436, 0x00008847 }, /* GL_MATRIX_INDEX_ARRAY_TYPE_ARB */
+ { 17467, 0x00000BA0 }, /* GL_MATRIX_MODE */
+ { 17482, 0x00008840 }, /* GL_MATRIX_PALETTE_ARB */
+ { 17504, 0x00008008 }, /* GL_MAX */
+ { 17511, 0x00008073 }, /* GL_MAX_3D_TEXTURE_SIZE */
+ { 17534, 0x000088FF }, /* GL_MAX_ARRAY_TEXTURE_LAYERS_EXT */
+ { 17566, 0x00000D35 }, /* GL_MAX_ATTRIB_STACK_DEPTH */
+ { 17592, 0x00000D3B }, /* GL_MAX_CLIENT_ATTRIB_STACK_DEPTH */
+ { 17625, 0x00008177 }, /* GL_MAX_CLIPMAP_DEPTH_SGIX */
+ { 17651, 0x00008178 }, /* GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX */
+ { 17685, 0x00000D32 }, /* GL_MAX_CLIP_PLANES */
+ { 17704, 0x00008CDF }, /* GL_MAX_COLOR_ATTACHMENTS_EXT */
+ { 17733, 0x000080B3 }, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH */
+ { 17765, 0x000080B3 }, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI */
+ { 17801, 0x00008B4D }, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */
+ { 17837, 0x00008B4D }, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB */
+ { 17877, 0x0000801B }, /* GL_MAX_CONVOLUTION_HEIGHT */
+ { 17903, 0x0000801B }, /* GL_MAX_CONVOLUTION_HEIGHT_EXT */
+ { 17933, 0x0000801A }, /* GL_MAX_CONVOLUTION_WIDTH */
+ { 17958, 0x0000801A }, /* GL_MAX_CONVOLUTION_WIDTH_EXT */
+ { 17987, 0x0000851C }, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */
+ { 18016, 0x0000851C }, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB */
+ { 18049, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS */
+ { 18069, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS_ARB */
+ { 18093, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS_ATI */
+ { 18117, 0x000080E9 }, /* GL_MAX_ELEMENTS_INDICES */
+ { 18141, 0x000080E8 }, /* GL_MAX_ELEMENTS_VERTICES */
+ { 18166, 0x00000D30 }, /* GL_MAX_EVAL_ORDER */
+ { 18184, 0x00008008 }, /* GL_MAX_EXT */
+ { 18195, 0x00008B49 }, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS */
+ { 18230, 0x00008B49 }, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB */
+ { 18269, 0x00000D31 }, /* GL_MAX_LIGHTS */
+ { 18283, 0x00000B31 }, /* GL_MAX_LIST_NESTING */
+ { 18303, 0x00008841 }, /* GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB */
+ { 18341, 0x00000D36 }, /* GL_MAX_MODELVIEW_STACK_DEPTH */
+ { 18370, 0x00000D37 }, /* GL_MAX_NAME_STACK_DEPTH */
+ { 18394, 0x00008842 }, /* GL_MAX_PALETTE_MATRICES_ARB */
+ { 18422, 0x00000D34 }, /* GL_MAX_PIXEL_MAP_TABLE */
+ { 18445, 0x000088B1 }, /* GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB */
+ { 18482, 0x0000880B }, /* GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB */
+ { 18518, 0x000088AD }, /* GL_MAX_PROGRAM_ATTRIBS_ARB */
+ { 18545, 0x000088F5 }, /* GL_MAX_PROGRAM_CALL_DEPTH_NV */
+ { 18574, 0x000088B5 }, /* GL_MAX_PROGRAM_ENV_PARAMETERS_ARB */
+ { 18608, 0x000088F4 }, /* GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */
+ { 18644, 0x000088F6 }, /* GL_MAX_PROGRAM_IF_DEPTH_NV */
+ { 18671, 0x000088A1 }, /* GL_MAX_PROGRAM_INSTRUCTIONS_ARB */
+ { 18703, 0x000088B4 }, /* GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB */
+ { 18739, 0x000088F8 }, /* GL_MAX_PROGRAM_LOOP_COUNT_NV */
+ { 18768, 0x000088F7 }, /* GL_MAX_PROGRAM_LOOP_DEPTH_NV */
+ { 18797, 0x0000862F }, /* GL_MAX_PROGRAM_MATRICES_ARB */
+ { 18825, 0x0000862E }, /* GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB */
+ { 18863, 0x000088B3 }, /* GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
+ { 18907, 0x0000880E }, /* GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
+ { 18950, 0x000088AF }, /* GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB */
+ { 18984, 0x000088A3 }, /* GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
+ { 19023, 0x000088AB }, /* GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB */
+ { 19060, 0x000088A7 }, /* GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB */
+ { 19098, 0x00008810 }, /* GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
+ { 19141, 0x0000880F }, /* GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
+ { 19184, 0x000088A9 }, /* GL_MAX_PROGRAM_PARAMETERS_ARB */
+ { 19214, 0x000088A5 }, /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
+ { 19245, 0x0000880D }, /* GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB */
+ { 19281, 0x0000880C }, /* GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB */
+ { 19317, 0x00000D38 }, /* GL_MAX_PROJECTION_STACK_DEPTH */
+ { 19347, 0x000084F8 }, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB */
+ { 19381, 0x000084F8 }, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_NV */
+ { 19414, 0x000084E8 }, /* GL_MAX_RENDERBUFFER_SIZE_EXT */
+ { 19443, 0x00008D57 }, /* GL_MAX_SAMPLES */
+ { 19458, 0x00009111 }, /* GL_MAX_SERVER_WAIT_TIMEOUT */
+ { 19485, 0x00008504 }, /* GL_MAX_SHININESS_NV */
+ { 19505, 0x00008505 }, /* GL_MAX_SPOT_EXPONENT_NV */
+ { 19529, 0x00008871 }, /* GL_MAX_TEXTURE_COORDS */
+ { 19551, 0x00008871 }, /* GL_MAX_TEXTURE_COORDS_ARB */
+ { 19577, 0x00008872 }, /* GL_MAX_TEXTURE_IMAGE_UNITS */
+ { 19604, 0x00008872 }, /* GL_MAX_TEXTURE_IMAGE_UNITS_ARB */
+ { 19635, 0x000084FD }, /* GL_MAX_TEXTURE_LOD_BIAS */
+ { 19659, 0x000084FF }, /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */
+ { 19693, 0x00000D33 }, /* GL_MAX_TEXTURE_SIZE */
+ { 19713, 0x00000D39 }, /* GL_MAX_TEXTURE_STACK_DEPTH */
+ { 19740, 0x000084E2 }, /* GL_MAX_TEXTURE_UNITS */
+ { 19761, 0x000084E2 }, /* GL_MAX_TEXTURE_UNITS_ARB */
+ { 19786, 0x0000862F }, /* GL_MAX_TRACK_MATRICES_NV */
+ { 19811, 0x0000862E }, /* GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV */
+ { 19846, 0x00008B4B }, /* GL_MAX_VARYING_FLOATS */
+ { 19868, 0x00008B4B }, /* GL_MAX_VARYING_FLOATS_ARB */
+ { 19894, 0x00008869 }, /* GL_MAX_VERTEX_ATTRIBS */
+ { 19916, 0x00008869 }, /* GL_MAX_VERTEX_ATTRIBS_ARB */
+ { 19942, 0x00008B4C }, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS */
+ { 19976, 0x00008B4C }, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */
+ { 20014, 0x00008B4A }, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS */
+ { 20047, 0x00008B4A }, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB */
+ { 20084, 0x000086A4 }, /* GL_MAX_VERTEX_UNITS_ARB */
+ { 20108, 0x00000D3A }, /* GL_MAX_VIEWPORT_DIMS */
+ { 20129, 0x00008007 }, /* GL_MIN */
+ { 20136, 0x0000802E }, /* GL_MINMAX */
+ { 20146, 0x0000802E }, /* GL_MINMAX_EXT */
+ { 20160, 0x0000802F }, /* GL_MINMAX_FORMAT */
+ { 20177, 0x0000802F }, /* GL_MINMAX_FORMAT_EXT */
+ { 20198, 0x00008030 }, /* GL_MINMAX_SINK */
+ { 20213, 0x00008030 }, /* GL_MINMAX_SINK_EXT */
+ { 20232, 0x00008007 }, /* GL_MIN_EXT */
+ { 20243, 0x00008370 }, /* GL_MIRRORED_REPEAT */
+ { 20262, 0x00008370 }, /* GL_MIRRORED_REPEAT_ARB */
+ { 20285, 0x00008370 }, /* GL_MIRRORED_REPEAT_IBM */
+ { 20308, 0x00008742 }, /* GL_MIRROR_CLAMP_ATI */
+ { 20328, 0x00008742 }, /* GL_MIRROR_CLAMP_EXT */
+ { 20348, 0x00008912 }, /* GL_MIRROR_CLAMP_TO_BORDER_EXT */
+ { 20378, 0x00008743 }, /* GL_MIRROR_CLAMP_TO_EDGE_ATI */
+ { 20406, 0x00008743 }, /* GL_MIRROR_CLAMP_TO_EDGE_EXT */
+ { 20434, 0x00001700 }, /* GL_MODELVIEW */
+ { 20447, 0x00001700 }, /* GL_MODELVIEW0_ARB */
+ { 20465, 0x0000872A }, /* GL_MODELVIEW10_ARB */
+ { 20484, 0x0000872B }, /* GL_MODELVIEW11_ARB */
+ { 20503, 0x0000872C }, /* GL_MODELVIEW12_ARB */
+ { 20522, 0x0000872D }, /* GL_MODELVIEW13_ARB */
+ { 20541, 0x0000872E }, /* GL_MODELVIEW14_ARB */
+ { 20560, 0x0000872F }, /* GL_MODELVIEW15_ARB */
+ { 20579, 0x00008730 }, /* GL_MODELVIEW16_ARB */
+ { 20598, 0x00008731 }, /* GL_MODELVIEW17_ARB */
+ { 20617, 0x00008732 }, /* GL_MODELVIEW18_ARB */
+ { 20636, 0x00008733 }, /* GL_MODELVIEW19_ARB */
+ { 20655, 0x0000850A }, /* GL_MODELVIEW1_ARB */
+ { 20673, 0x00008734 }, /* GL_MODELVIEW20_ARB */
+ { 20692, 0x00008735 }, /* GL_MODELVIEW21_ARB */
+ { 20711, 0x00008736 }, /* GL_MODELVIEW22_ARB */
+ { 20730, 0x00008737 }, /* GL_MODELVIEW23_ARB */
+ { 20749, 0x00008738 }, /* GL_MODELVIEW24_ARB */
+ { 20768, 0x00008739 }, /* GL_MODELVIEW25_ARB */
+ { 20787, 0x0000873A }, /* GL_MODELVIEW26_ARB */
+ { 20806, 0x0000873B }, /* GL_MODELVIEW27_ARB */
+ { 20825, 0x0000873C }, /* GL_MODELVIEW28_ARB */
+ { 20844, 0x0000873D }, /* GL_MODELVIEW29_ARB */
+ { 20863, 0x00008722 }, /* GL_MODELVIEW2_ARB */
+ { 20881, 0x0000873E }, /* GL_MODELVIEW30_ARB */
+ { 20900, 0x0000873F }, /* GL_MODELVIEW31_ARB */
+ { 20919, 0x00008723 }, /* GL_MODELVIEW3_ARB */
+ { 20937, 0x00008724 }, /* GL_MODELVIEW4_ARB */
+ { 20955, 0x00008725 }, /* GL_MODELVIEW5_ARB */
+ { 20973, 0x00008726 }, /* GL_MODELVIEW6_ARB */
+ { 20991, 0x00008727 }, /* GL_MODELVIEW7_ARB */
+ { 21009, 0x00008728 }, /* GL_MODELVIEW8_ARB */
+ { 21027, 0x00008729 }, /* GL_MODELVIEW9_ARB */
+ { 21045, 0x00000BA6 }, /* GL_MODELVIEW_MATRIX */
+ { 21065, 0x00008629 }, /* GL_MODELVIEW_PROJECTION_NV */
+ { 21092, 0x00000BA3 }, /* GL_MODELVIEW_STACK_DEPTH */
+ { 21117, 0x00002100 }, /* GL_MODULATE */
+ { 21129, 0x00008744 }, /* GL_MODULATE_ADD_ATI */
+ { 21149, 0x00008745 }, /* GL_MODULATE_SIGNED_ADD_ATI */
+ { 21176, 0x00008746 }, /* GL_MODULATE_SUBTRACT_ATI */
+ { 21201, 0x00000103 }, /* GL_MULT */
+ { 21209, 0x0000809D }, /* GL_MULTISAMPLE */
+ { 21224, 0x000086B2 }, /* GL_MULTISAMPLE_3DFX */
+ { 21244, 0x0000809D }, /* GL_MULTISAMPLE_ARB */
+ { 21263, 0x20000000 }, /* GL_MULTISAMPLE_BIT */
+ { 21282, 0x20000000 }, /* GL_MULTISAMPLE_BIT_3DFX */
+ { 21306, 0x20000000 }, /* GL_MULTISAMPLE_BIT_ARB */
+ { 21329, 0x00008534 }, /* GL_MULTISAMPLE_FILTER_HINT_NV */
+ { 21359, 0x00002A25 }, /* GL_N3F_V3F */
+ { 21370, 0x00000D70 }, /* GL_NAME_STACK_DEPTH */
+ { 21390, 0x0000150E }, /* GL_NAND */
+ { 21398, 0x00002600 }, /* GL_NEAREST */
+ { 21409, 0x0000844E }, /* GL_NEAREST_CLIPMAP_LINEAR_SGIX */
+ { 21440, 0x0000844D }, /* GL_NEAREST_CLIPMAP_NEAREST_SGIX */
+ { 21472, 0x00002702 }, /* GL_NEAREST_MIPMAP_LINEAR */
+ { 21497, 0x00002700 }, /* GL_NEAREST_MIPMAP_NEAREST */
+ { 21523, 0x00000200 }, /* GL_NEVER */
+ { 21532, 0x00001102 }, /* GL_NICEST */
+ { 21542, 0x00000000 }, /* GL_NONE */
+ { 21550, 0x00001505 }, /* GL_NOOP */
+ { 21558, 0x00001508 }, /* GL_NOR */
+ { 21565, 0x00000BA1 }, /* GL_NORMALIZE */
+ { 21578, 0x00008075 }, /* GL_NORMAL_ARRAY */
+ { 21594, 0x00008897 }, /* GL_NORMAL_ARRAY_BUFFER_BINDING */
+ { 21625, 0x00008897 }, /* GL_NORMAL_ARRAY_BUFFER_BINDING_ARB */
+ { 21660, 0x0000808F }, /* GL_NORMAL_ARRAY_POINTER */
+ { 21684, 0x0000807F }, /* GL_NORMAL_ARRAY_STRIDE */
+ { 21707, 0x0000807E }, /* GL_NORMAL_ARRAY_TYPE */
+ { 21728, 0x00008511 }, /* GL_NORMAL_MAP */
+ { 21742, 0x00008511 }, /* GL_NORMAL_MAP_ARB */
+ { 21760, 0x00008511 }, /* GL_NORMAL_MAP_NV */
+ { 21777, 0x00000205 }, /* GL_NOTEQUAL */
+ { 21789, 0x00000000 }, /* GL_NO_ERROR */
+ { 21801, 0x000086A2 }, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS */
+ { 21835, 0x000086A2 }, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB */
+ { 21873, 0x00008B89 }, /* GL_OBJECT_ACTIVE_ATTRIBUTES_ARB */
+ { 21905, 0x00008B8A }, /* GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB */
+ { 21947, 0x00008B86 }, /* GL_OBJECT_ACTIVE_UNIFORMS_ARB */
+ { 21977, 0x00008B87 }, /* GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB */
+ { 22017, 0x00008B85 }, /* GL_OBJECT_ATTACHED_OBJECTS_ARB */
+ { 22048, 0x00008B81 }, /* GL_OBJECT_COMPILE_STATUS_ARB */
+ { 22077, 0x00008B80 }, /* GL_OBJECT_DELETE_STATUS_ARB */
+ { 22105, 0x00008B84 }, /* GL_OBJECT_INFO_LOG_LENGTH_ARB */
+ { 22135, 0x00002401 }, /* GL_OBJECT_LINEAR */
+ { 22152, 0x00008B82 }, /* GL_OBJECT_LINK_STATUS_ARB */
+ { 22178, 0x00002501 }, /* GL_OBJECT_PLANE */
+ { 22194, 0x00008B88 }, /* GL_OBJECT_SHADER_SOURCE_LENGTH_ARB */
+ { 22229, 0x00008B4F }, /* GL_OBJECT_SUBTYPE_ARB */
+ { 22251, 0x00009112 }, /* GL_OBJECT_TYPE */
+ { 22266, 0x00008B4E }, /* GL_OBJECT_TYPE_ARB */
+ { 22285, 0x00008B83 }, /* GL_OBJECT_VALIDATE_STATUS_ARB */
+ { 22315, 0x00008165 }, /* GL_OCCLUSION_TEST_HP */
+ { 22336, 0x00008166 }, /* GL_OCCLUSION_TEST_RESULT_HP */
+ { 22364, 0x00000001 }, /* GL_ONE */
+ { 22371, 0x00008004 }, /* GL_ONE_MINUS_CONSTANT_ALPHA */
+ { 22399, 0x00008004 }, /* GL_ONE_MINUS_CONSTANT_ALPHA_EXT */
+ { 22431, 0x00008002 }, /* GL_ONE_MINUS_CONSTANT_COLOR */
+ { 22459, 0x00008002 }, /* GL_ONE_MINUS_CONSTANT_COLOR_EXT */
+ { 22491, 0x00000305 }, /* GL_ONE_MINUS_DST_ALPHA */
+ { 22514, 0x00000307 }, /* GL_ONE_MINUS_DST_COLOR */
+ { 22537, 0x00000303 }, /* GL_ONE_MINUS_SRC_ALPHA */
+ { 22560, 0x00000301 }, /* GL_ONE_MINUS_SRC_COLOR */
+ { 22583, 0x00008598 }, /* GL_OPERAND0_ALPHA */
+ { 22601, 0x00008598 }, /* GL_OPERAND0_ALPHA_ARB */
+ { 22623, 0x00008598 }, /* GL_OPERAND0_ALPHA_EXT */
+ { 22645, 0x00008590 }, /* GL_OPERAND0_RGB */
+ { 22661, 0x00008590 }, /* GL_OPERAND0_RGB_ARB */
+ { 22681, 0x00008590 }, /* GL_OPERAND0_RGB_EXT */
+ { 22701, 0x00008599 }, /* GL_OPERAND1_ALPHA */
+ { 22719, 0x00008599 }, /* GL_OPERAND1_ALPHA_ARB */
+ { 22741, 0x00008599 }, /* GL_OPERAND1_ALPHA_EXT */
+ { 22763, 0x00008591 }, /* GL_OPERAND1_RGB */
+ { 22779, 0x00008591 }, /* GL_OPERAND1_RGB_ARB */
+ { 22799, 0x00008591 }, /* GL_OPERAND1_RGB_EXT */
+ { 22819, 0x0000859A }, /* GL_OPERAND2_ALPHA */
+ { 22837, 0x0000859A }, /* GL_OPERAND2_ALPHA_ARB */
+ { 22859, 0x0000859A }, /* GL_OPERAND2_ALPHA_EXT */
+ { 22881, 0x00008592 }, /* GL_OPERAND2_RGB */
+ { 22897, 0x00008592 }, /* GL_OPERAND2_RGB_ARB */
+ { 22917, 0x00008592 }, /* GL_OPERAND2_RGB_EXT */
+ { 22937, 0x0000859B }, /* GL_OPERAND3_ALPHA_NV */
+ { 22958, 0x00008593 }, /* GL_OPERAND3_RGB_NV */
+ { 22977, 0x00001507 }, /* GL_OR */
+ { 22983, 0x00000A01 }, /* GL_ORDER */
+ { 22992, 0x0000150D }, /* GL_OR_INVERTED */
+ { 23007, 0x0000150B }, /* GL_OR_REVERSE */
+ { 23021, 0x00000505 }, /* GL_OUT_OF_MEMORY */
+ { 23038, 0x00000D05 }, /* GL_PACK_ALIGNMENT */
+ { 23056, 0x0000806C }, /* GL_PACK_IMAGE_HEIGHT */
+ { 23077, 0x00008758 }, /* GL_PACK_INVERT_MESA */
+ { 23097, 0x00000D01 }, /* GL_PACK_LSB_FIRST */
+ { 23115, 0x00000D02 }, /* GL_PACK_ROW_LENGTH */
+ { 23134, 0x0000806B }, /* GL_PACK_SKIP_IMAGES */
+ { 23154, 0x00000D04 }, /* GL_PACK_SKIP_PIXELS */
+ { 23174, 0x00000D03 }, /* GL_PACK_SKIP_ROWS */
+ { 23192, 0x00000D00 }, /* GL_PACK_SWAP_BYTES */
+ { 23211, 0x00008B92 }, /* GL_PALETTE4_R5_G6_B5_OES */
+ { 23236, 0x00008B94 }, /* GL_PALETTE4_RGB5_A1_OES */
+ { 23260, 0x00008B90 }, /* GL_PALETTE4_RGB8_OES */
+ { 23281, 0x00008B93 }, /* GL_PALETTE4_RGBA4_OES */
+ { 23303, 0x00008B91 }, /* GL_PALETTE4_RGBA8_OES */
+ { 23325, 0x00008B97 }, /* GL_PALETTE8_R5_G6_B5_OES */
+ { 23350, 0x00008B99 }, /* GL_PALETTE8_RGB5_A1_OES */
+ { 23374, 0x00008B95 }, /* GL_PALETTE8_RGB8_OES */
+ { 23395, 0x00008B98 }, /* GL_PALETTE8_RGBA4_OES */
+ { 23417, 0x00008B96 }, /* GL_PALETTE8_RGBA8_OES */
+ { 23439, 0x00000700 }, /* GL_PASS_THROUGH_TOKEN */
+ { 23461, 0x00000C50 }, /* GL_PERSPECTIVE_CORRECTION_HINT */
+ { 23492, 0x00000C79 }, /* GL_PIXEL_MAP_A_TO_A */
+ { 23512, 0x00000CB9 }, /* GL_PIXEL_MAP_A_TO_A_SIZE */
+ { 23537, 0x00000C78 }, /* GL_PIXEL_MAP_B_TO_B */
+ { 23557, 0x00000CB8 }, /* GL_PIXEL_MAP_B_TO_B_SIZE */
+ { 23582, 0x00000C77 }, /* GL_PIXEL_MAP_G_TO_G */
+ { 23602, 0x00000CB7 }, /* GL_PIXEL_MAP_G_TO_G_SIZE */
+ { 23627, 0x00000C75 }, /* GL_PIXEL_MAP_I_TO_A */
+ { 23647, 0x00000CB5 }, /* GL_PIXEL_MAP_I_TO_A_SIZE */
+ { 23672, 0x00000C74 }, /* GL_PIXEL_MAP_I_TO_B */
+ { 23692, 0x00000CB4 }, /* GL_PIXEL_MAP_I_TO_B_SIZE */
+ { 23717, 0x00000C73 }, /* GL_PIXEL_MAP_I_TO_G */
+ { 23737, 0x00000CB3 }, /* GL_PIXEL_MAP_I_TO_G_SIZE */
+ { 23762, 0x00000C70 }, /* GL_PIXEL_MAP_I_TO_I */
+ { 23782, 0x00000CB0 }, /* GL_PIXEL_MAP_I_TO_I_SIZE */
+ { 23807, 0x00000C72 }, /* GL_PIXEL_MAP_I_TO_R */
+ { 23827, 0x00000CB2 }, /* GL_PIXEL_MAP_I_TO_R_SIZE */
+ { 23852, 0x00000C76 }, /* GL_PIXEL_MAP_R_TO_R */
+ { 23872, 0x00000CB6 }, /* GL_PIXEL_MAP_R_TO_R_SIZE */
+ { 23897, 0x00000C71 }, /* GL_PIXEL_MAP_S_TO_S */
+ { 23917, 0x00000CB1 }, /* GL_PIXEL_MAP_S_TO_S_SIZE */
+ { 23942, 0x00000020 }, /* GL_PIXEL_MODE_BIT */
+ { 23960, 0x000088EB }, /* GL_PIXEL_PACK_BUFFER */
+ { 23981, 0x000088ED }, /* GL_PIXEL_PACK_BUFFER_BINDING */
+ { 24010, 0x000088ED }, /* GL_PIXEL_PACK_BUFFER_BINDING_EXT */
+ { 24043, 0x000088EB }, /* GL_PIXEL_PACK_BUFFER_EXT */
+ { 24068, 0x000088EC }, /* GL_PIXEL_UNPACK_BUFFER */
+ { 24091, 0x000088EF }, /* GL_PIXEL_UNPACK_BUFFER_BINDING */
+ { 24122, 0x000088EF }, /* GL_PIXEL_UNPACK_BUFFER_BINDING_EXT */
+ { 24157, 0x000088EC }, /* GL_PIXEL_UNPACK_BUFFER_EXT */
+ { 24184, 0x00001B00 }, /* GL_POINT */
+ { 24193, 0x00000000 }, /* GL_POINTS */
+ { 24203, 0x00000002 }, /* GL_POINT_BIT */
+ { 24216, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION */
+ { 24246, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_ARB */
+ { 24280, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_EXT */
+ { 24314, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_SGIS */
+ { 24349, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE */
+ { 24378, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_ARB */
+ { 24411, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_EXT */
+ { 24444, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_SGIS */
+ { 24478, 0x00000B11 }, /* GL_POINT_SIZE */
+ { 24492, 0x00000B13 }, /* GL_POINT_SIZE_GRANULARITY */
+ { 24518, 0x00008127 }, /* GL_POINT_SIZE_MAX */
+ { 24536, 0x00008127 }, /* GL_POINT_SIZE_MAX_ARB */
+ { 24558, 0x00008127 }, /* GL_POINT_SIZE_MAX_EXT */
+ { 24580, 0x00008127 }, /* GL_POINT_SIZE_MAX_SGIS */
+ { 24603, 0x00008126 }, /* GL_POINT_SIZE_MIN */
+ { 24621, 0x00008126 }, /* GL_POINT_SIZE_MIN_ARB */
+ { 24643, 0x00008126 }, /* GL_POINT_SIZE_MIN_EXT */
+ { 24665, 0x00008126 }, /* GL_POINT_SIZE_MIN_SGIS */
+ { 24688, 0x00000B12 }, /* GL_POINT_SIZE_RANGE */
+ { 24708, 0x00000B10 }, /* GL_POINT_SMOOTH */
+ { 24724, 0x00000C51 }, /* GL_POINT_SMOOTH_HINT */
+ { 24745, 0x00008861 }, /* GL_POINT_SPRITE */
+ { 24761, 0x00008861 }, /* GL_POINT_SPRITE_ARB */
+ { 24781, 0x00008CA0 }, /* GL_POINT_SPRITE_COORD_ORIGIN */
+ { 24810, 0x00008861 }, /* GL_POINT_SPRITE_NV */
+ { 24829, 0x00008863 }, /* GL_POINT_SPRITE_R_MODE_NV */
+ { 24855, 0x00000701 }, /* GL_POINT_TOKEN */
+ { 24870, 0x00000009 }, /* GL_POLYGON */
+ { 24881, 0x00000008 }, /* GL_POLYGON_BIT */
+ { 24896, 0x00000B40 }, /* GL_POLYGON_MODE */
+ { 24912, 0x00008039 }, /* GL_POLYGON_OFFSET_BIAS */
+ { 24935, 0x00008038 }, /* GL_POLYGON_OFFSET_FACTOR */
+ { 24960, 0x00008037 }, /* GL_POLYGON_OFFSET_FILL */
+ { 24983, 0x00002A02 }, /* GL_POLYGON_OFFSET_LINE */
+ { 25006, 0x00002A01 }, /* GL_POLYGON_OFFSET_POINT */
+ { 25030, 0x00002A00 }, /* GL_POLYGON_OFFSET_UNITS */
+ { 25054, 0x00000B41 }, /* GL_POLYGON_SMOOTH */
+ { 25072, 0x00000C53 }, /* GL_POLYGON_SMOOTH_HINT */
+ { 25095, 0x00000B42 }, /* GL_POLYGON_STIPPLE */
+ { 25114, 0x00000010 }, /* GL_POLYGON_STIPPLE_BIT */
+ { 25137, 0x00000703 }, /* GL_POLYGON_TOKEN */
+ { 25154, 0x00001203 }, /* GL_POSITION */
+ { 25166, 0x000080BB }, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS */
+ { 25198, 0x000080BB }, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI */
+ { 25234, 0x000080B7 }, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE */
+ { 25267, 0x000080B7 }, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI */
+ { 25304, 0x000080BA }, /* GL_POST_COLOR_MATRIX_BLUE_BIAS */
+ { 25335, 0x000080BA }, /* GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI */
+ { 25370, 0x000080B6 }, /* GL_POST_COLOR_MATRIX_BLUE_SCALE */
+ { 25402, 0x000080B6 }, /* GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI */
+ { 25438, 0x000080D2 }, /* GL_POST_COLOR_MATRIX_COLOR_TABLE */
+ { 25471, 0x000080B9 }, /* GL_POST_COLOR_MATRIX_GREEN_BIAS */
+ { 25503, 0x000080B9 }, /* GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI */
+ { 25539, 0x000080B5 }, /* GL_POST_COLOR_MATRIX_GREEN_SCALE */
+ { 25572, 0x000080B5 }, /* GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI */
+ { 25609, 0x000080B8 }, /* GL_POST_COLOR_MATRIX_RED_BIAS */
+ { 25639, 0x000080B8 }, /* GL_POST_COLOR_MATRIX_RED_BIAS_SGI */
+ { 25673, 0x000080B4 }, /* GL_POST_COLOR_MATRIX_RED_SCALE */
+ { 25704, 0x000080B4 }, /* GL_POST_COLOR_MATRIX_RED_SCALE_SGI */
+ { 25739, 0x00008023 }, /* GL_POST_CONVOLUTION_ALPHA_BIAS */
+ { 25770, 0x00008023 }, /* GL_POST_CONVOLUTION_ALPHA_BIAS_EXT */
+ { 25805, 0x0000801F }, /* GL_POST_CONVOLUTION_ALPHA_SCALE */
+ { 25837, 0x0000801F }, /* GL_POST_CONVOLUTION_ALPHA_SCALE_EXT */
+ { 25873, 0x00008022 }, /* GL_POST_CONVOLUTION_BLUE_BIAS */
+ { 25903, 0x00008022 }, /* GL_POST_CONVOLUTION_BLUE_BIAS_EXT */
+ { 25937, 0x0000801E }, /* GL_POST_CONVOLUTION_BLUE_SCALE */
+ { 25968, 0x0000801E }, /* GL_POST_CONVOLUTION_BLUE_SCALE_EXT */
+ { 26003, 0x000080D1 }, /* GL_POST_CONVOLUTION_COLOR_TABLE */
+ { 26035, 0x00008021 }, /* GL_POST_CONVOLUTION_GREEN_BIAS */
+ { 26066, 0x00008021 }, /* GL_POST_CONVOLUTION_GREEN_BIAS_EXT */
+ { 26101, 0x0000801D }, /* GL_POST_CONVOLUTION_GREEN_SCALE */
+ { 26133, 0x0000801D }, /* GL_POST_CONVOLUTION_GREEN_SCALE_EXT */
+ { 26169, 0x00008020 }, /* GL_POST_CONVOLUTION_RED_BIAS */
+ { 26198, 0x00008020 }, /* GL_POST_CONVOLUTION_RED_BIAS_EXT */
+ { 26231, 0x0000801C }, /* GL_POST_CONVOLUTION_RED_SCALE */
+ { 26261, 0x0000801C }, /* GL_POST_CONVOLUTION_RED_SCALE_EXT */
+ { 26295, 0x0000817B }, /* GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX */
+ { 26334, 0x00008179 }, /* GL_POST_TEXTURE_FILTER_BIAS_SGIX */
+ { 26367, 0x0000817C }, /* GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX */
+ { 26407, 0x0000817A }, /* GL_POST_TEXTURE_FILTER_SCALE_SGIX */
+ { 26441, 0x00008578 }, /* GL_PREVIOUS */
+ { 26453, 0x00008578 }, /* GL_PREVIOUS_ARB */
+ { 26469, 0x00008578 }, /* GL_PREVIOUS_EXT */
+ { 26485, 0x00008577 }, /* GL_PRIMARY_COLOR */
+ { 26502, 0x00008577 }, /* GL_PRIMARY_COLOR_ARB */
+ { 26523, 0x00008577 }, /* GL_PRIMARY_COLOR_EXT */
+ { 26544, 0x000088B0 }, /* GL_PROGRAM_ADDRESS_REGISTERS_ARB */
+ { 26577, 0x00008805 }, /* GL_PROGRAM_ALU_INSTRUCTIONS_ARB */
+ { 26609, 0x000088AC }, /* GL_PROGRAM_ATTRIBS_ARB */
+ { 26632, 0x00008677 }, /* GL_PROGRAM_BINDING_ARB */
+ { 26655, 0x0000864B }, /* GL_PROGRAM_ERROR_POSITION_ARB */
+ { 26685, 0x0000864B }, /* GL_PROGRAM_ERROR_POSITION_NV */
+ { 26714, 0x00008874 }, /* GL_PROGRAM_ERROR_STRING_ARB */
+ { 26742, 0x00008876 }, /* GL_PROGRAM_FORMAT_ARB */
+ { 26764, 0x00008875 }, /* GL_PROGRAM_FORMAT_ASCII_ARB */
+ { 26792, 0x000088A0 }, /* GL_PROGRAM_INSTRUCTIONS_ARB */
+ { 26820, 0x00008627 }, /* GL_PROGRAM_LENGTH_ARB */
+ { 26842, 0x00008627 }, /* GL_PROGRAM_LENGTH_NV */
+ { 26863, 0x000088B2 }, /* GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
+ { 26903, 0x00008808 }, /* GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
+ { 26942, 0x000088AE }, /* GL_PROGRAM_NATIVE_ATTRIBS_ARB */
+ { 26972, 0x000088A2 }, /* GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
+ { 27007, 0x000088AA }, /* GL_PROGRAM_NATIVE_PARAMETERS_ARB */
+ { 27040, 0x000088A6 }, /* GL_PROGRAM_NATIVE_TEMPORARIES_ARB */
+ { 27074, 0x0000880A }, /* GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
+ { 27113, 0x00008809 }, /* GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
+ { 27152, 0x00008B40 }, /* GL_PROGRAM_OBJECT_ARB */
+ { 27174, 0x000088A8 }, /* GL_PROGRAM_PARAMETERS_ARB */
+ { 27200, 0x00008644 }, /* GL_PROGRAM_PARAMETER_NV */
+ { 27224, 0x00008647 }, /* GL_PROGRAM_RESIDENT_NV */
+ { 27247, 0x00008628 }, /* GL_PROGRAM_STRING_ARB */
+ { 27269, 0x00008628 }, /* GL_PROGRAM_STRING_NV */
+ { 27290, 0x00008646 }, /* GL_PROGRAM_TARGET_NV */
+ { 27311, 0x000088A4 }, /* GL_PROGRAM_TEMPORARIES_ARB */
+ { 27338, 0x00008807 }, /* GL_PROGRAM_TEX_INDIRECTIONS_ARB */
+ { 27370, 0x00008806 }, /* GL_PROGRAM_TEX_INSTRUCTIONS_ARB */
+ { 27402, 0x000088B6 }, /* GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB */
+ { 27437, 0x00001701 }, /* GL_PROJECTION */
+ { 27451, 0x00000BA7 }, /* GL_PROJECTION_MATRIX */
+ { 27472, 0x00000BA4 }, /* GL_PROJECTION_STACK_DEPTH */
+ { 27498, 0x00008E4F }, /* GL_PROVOKING_VERTEX_EXT */
+ { 27522, 0x000080D3 }, /* GL_PROXY_COLOR_TABLE */
+ { 27543, 0x00008025 }, /* GL_PROXY_HISTOGRAM */
+ { 27562, 0x00008025 }, /* GL_PROXY_HISTOGRAM_EXT */
+ { 27585, 0x000080D5 }, /* GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE */
+ { 27624, 0x000080D4 }, /* GL_PROXY_POST_CONVOLUTION_COLOR_TABLE */
+ { 27662, 0x00008063 }, /* GL_PROXY_TEXTURE_1D */
+ { 27682, 0x00008C19 }, /* GL_PROXY_TEXTURE_1D_ARRAY_EXT */
+ { 27712, 0x00008063 }, /* GL_PROXY_TEXTURE_1D_EXT */
+ { 27736, 0x00008064 }, /* GL_PROXY_TEXTURE_2D */
+ { 27756, 0x00008C1B }, /* GL_PROXY_TEXTURE_2D_ARRAY_EXT */
+ { 27786, 0x00008064 }, /* GL_PROXY_TEXTURE_2D_EXT */
+ { 27810, 0x00008070 }, /* GL_PROXY_TEXTURE_3D */
+ { 27830, 0x000080BD }, /* GL_PROXY_TEXTURE_COLOR_TABLE_SGI */
+ { 27863, 0x0000851B }, /* GL_PROXY_TEXTURE_CUBE_MAP */
+ { 27889, 0x0000851B }, /* GL_PROXY_TEXTURE_CUBE_MAP_ARB */
+ { 27919, 0x000084F7 }, /* GL_PROXY_TEXTURE_RECTANGLE_ARB */
+ { 27950, 0x000084F7 }, /* GL_PROXY_TEXTURE_RECTANGLE_NV */
+ { 27980, 0x00002003 }, /* GL_Q */
+ { 27985, 0x00001209 }, /* GL_QUADRATIC_ATTENUATION */
+ { 28010, 0x00000007 }, /* GL_QUADS */
+ { 28019, 0x00008E4C }, /* GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT */
+ { 28067, 0x00008614 }, /* GL_QUAD_MESH_SUN */
+ { 28084, 0x00000008 }, /* GL_QUAD_STRIP */
+ { 28098, 0x00008864 }, /* GL_QUERY_COUNTER_BITS */
+ { 28120, 0x00008864 }, /* GL_QUERY_COUNTER_BITS_ARB */
+ { 28146, 0x00008866 }, /* GL_QUERY_RESULT */
+ { 28162, 0x00008866 }, /* GL_QUERY_RESULT_ARB */
+ { 28182, 0x00008867 }, /* GL_QUERY_RESULT_AVAILABLE */
+ { 28208, 0x00008867 }, /* GL_QUERY_RESULT_AVAILABLE_ARB */
+ { 28238, 0x00002002 }, /* GL_R */
+ { 28243, 0x00002A10 }, /* GL_R3_G3_B2 */
+ { 28255, 0x00019262 }, /* GL_RASTER_POSITION_UNCLIPPED_IBM */
+ { 28288, 0x00000C02 }, /* GL_READ_BUFFER */
+ { 28303, 0x00008CA8 }, /* GL_READ_FRAMEBUFFER */
+ { 28323, 0x00008CAA }, /* GL_READ_FRAMEBUFFER_BINDING_EXT */
+ { 28355, 0x00008CA8 }, /* GL_READ_FRAMEBUFFER_EXT */
+ { 28379, 0x000088B8 }, /* GL_READ_ONLY */
+ { 28392, 0x000088B8 }, /* GL_READ_ONLY_ARB */
+ { 28409, 0x000088BA }, /* GL_READ_WRITE */
+ { 28423, 0x000088BA }, /* GL_READ_WRITE_ARB */
+ { 28441, 0x00001903 }, /* GL_RED */
+ { 28448, 0x00008016 }, /* GL_REDUCE */
+ { 28458, 0x00008016 }, /* GL_REDUCE_EXT */
+ { 28472, 0x00000D15 }, /* GL_RED_BIAS */
+ { 28484, 0x00000D52 }, /* GL_RED_BITS */
+ { 28496, 0x00000D14 }, /* GL_RED_SCALE */
+ { 28509, 0x00008512 }, /* GL_REFLECTION_MAP */
+ { 28527, 0x00008512 }, /* GL_REFLECTION_MAP_ARB */
+ { 28549, 0x00008512 }, /* GL_REFLECTION_MAP_NV */
+ { 28570, 0x00001C00 }, /* GL_RENDER */
+ { 28580, 0x00008D41 }, /* GL_RENDERBUFFER */
+ { 28596, 0x00008D53 }, /* GL_RENDERBUFFER_ALPHA_SIZE */
+ { 28623, 0x00008CA7 }, /* GL_RENDERBUFFER_BINDING_EXT */
+ { 28651, 0x00008D52 }, /* GL_RENDERBUFFER_BLUE_SIZE */
+ { 28677, 0x00008D54 }, /* GL_RENDERBUFFER_DEPTH_SIZE */
+ { 28704, 0x00008D41 }, /* GL_RENDERBUFFER_EXT */
+ { 28724, 0x00008D51 }, /* GL_RENDERBUFFER_GREEN_SIZE */
+ { 28751, 0x00008D43 }, /* GL_RENDERBUFFER_HEIGHT */
+ { 28774, 0x00008D43 }, /* GL_RENDERBUFFER_HEIGHT_EXT */
+ { 28801, 0x00008D44 }, /* GL_RENDERBUFFER_INTERNAL_FORMAT */
+ { 28833, 0x00008D44 }, /* GL_RENDERBUFFER_INTERNAL_FORMAT_EXT */
+ { 28869, 0x00008D50 }, /* GL_RENDERBUFFER_RED_SIZE */
+ { 28894, 0x00008CAB }, /* GL_RENDERBUFFER_SAMPLES */
+ { 28918, 0x00008D55 }, /* GL_RENDERBUFFER_STENCIL_SIZE */
+ { 28947, 0x00008D42 }, /* GL_RENDERBUFFER_WIDTH */
+ { 28969, 0x00008D42 }, /* GL_RENDERBUFFER_WIDTH_EXT */
+ { 28995, 0x00001F01 }, /* GL_RENDERER */
+ { 29007, 0x00000C40 }, /* GL_RENDER_MODE */
+ { 29022, 0x00002901 }, /* GL_REPEAT */
+ { 29032, 0x00001E01 }, /* GL_REPLACE */
+ { 29043, 0x00008062 }, /* GL_REPLACE_EXT */
+ { 29058, 0x00008153 }, /* GL_REPLICATE_BORDER_HP */
+ { 29081, 0x0000803A }, /* GL_RESCALE_NORMAL */
+ { 29099, 0x0000803A }, /* GL_RESCALE_NORMAL_EXT */
+ { 29121, 0x00000102 }, /* GL_RETURN */
+ { 29131, 0x00001907 }, /* GL_RGB */
+ { 29138, 0x00008052 }, /* GL_RGB10 */
+ { 29147, 0x00008059 }, /* GL_RGB10_A2 */
+ { 29159, 0x00008059 }, /* GL_RGB10_A2_EXT */
+ { 29175, 0x00008052 }, /* GL_RGB10_EXT */
+ { 29188, 0x00008053 }, /* GL_RGB12 */
+ { 29197, 0x00008053 }, /* GL_RGB12_EXT */
+ { 29210, 0x00008054 }, /* GL_RGB16 */
+ { 29219, 0x00008054 }, /* GL_RGB16_EXT */
+ { 29232, 0x0000804E }, /* GL_RGB2_EXT */
+ { 29244, 0x0000804F }, /* GL_RGB4 */
+ { 29252, 0x0000804F }, /* GL_RGB4_EXT */
+ { 29264, 0x000083A1 }, /* GL_RGB4_S3TC */
+ { 29277, 0x00008050 }, /* GL_RGB5 */
+ { 29285, 0x00008057 }, /* GL_RGB5_A1 */
+ { 29296, 0x00008057 }, /* GL_RGB5_A1_EXT */
+ { 29311, 0x00008050 }, /* GL_RGB5_EXT */
+ { 29323, 0x00008051 }, /* GL_RGB8 */
+ { 29331, 0x00008051 }, /* GL_RGB8_EXT */
+ { 29343, 0x00001908 }, /* GL_RGBA */
+ { 29351, 0x0000805A }, /* GL_RGBA12 */
+ { 29361, 0x0000805A }, /* GL_RGBA12_EXT */
+ { 29375, 0x0000805B }, /* GL_RGBA16 */
+ { 29385, 0x0000805B }, /* GL_RGBA16_EXT */
+ { 29399, 0x00008055 }, /* GL_RGBA2 */
+ { 29408, 0x00008055 }, /* GL_RGBA2_EXT */
+ { 29421, 0x00008056 }, /* GL_RGBA4 */
+ { 29430, 0x000083A5 }, /* GL_RGBA4_DXT5_S3TC */
+ { 29449, 0x00008056 }, /* GL_RGBA4_EXT */
+ { 29462, 0x000083A3 }, /* GL_RGBA4_S3TC */
+ { 29476, 0x00008058 }, /* GL_RGBA8 */
+ { 29485, 0x00008058 }, /* GL_RGBA8_EXT */
+ { 29498, 0x00008F97 }, /* GL_RGBA8_SNORM */
+ { 29513, 0x000083A4 }, /* GL_RGBA_DXT5_S3TC */
+ { 29531, 0x00000C31 }, /* GL_RGBA_MODE */
+ { 29544, 0x000083A2 }, /* GL_RGBA_S3TC */
+ { 29557, 0x00008F93 }, /* GL_RGBA_SNORM */
+ { 29571, 0x000083A0 }, /* GL_RGB_S3TC */
+ { 29583, 0x00008573 }, /* GL_RGB_SCALE */
+ { 29596, 0x00008573 }, /* GL_RGB_SCALE_ARB */
+ { 29613, 0x00008573 }, /* GL_RGB_SCALE_EXT */
+ { 29630, 0x00000407 }, /* GL_RIGHT */
+ { 29639, 0x00002000 }, /* GL_S */
+ { 29644, 0x00008B5D }, /* GL_SAMPLER_1D */
+ { 29658, 0x00008B61 }, /* GL_SAMPLER_1D_SHADOW */
+ { 29679, 0x00008B5E }, /* GL_SAMPLER_2D */
+ { 29693, 0x00008B62 }, /* GL_SAMPLER_2D_SHADOW */
+ { 29714, 0x00008B5F }, /* GL_SAMPLER_3D */
+ { 29728, 0x00008B60 }, /* GL_SAMPLER_CUBE */
+ { 29744, 0x000080A9 }, /* GL_SAMPLES */
+ { 29755, 0x000086B4 }, /* GL_SAMPLES_3DFX */
+ { 29771, 0x000080A9 }, /* GL_SAMPLES_ARB */
+ { 29786, 0x00008914 }, /* GL_SAMPLES_PASSED */
+ { 29804, 0x00008914 }, /* GL_SAMPLES_PASSED_ARB */
+ { 29826, 0x0000809E }, /* GL_SAMPLE_ALPHA_TO_COVERAGE */
+ { 29854, 0x0000809E }, /* GL_SAMPLE_ALPHA_TO_COVERAGE_ARB */
+ { 29886, 0x0000809F }, /* GL_SAMPLE_ALPHA_TO_ONE */
+ { 29909, 0x0000809F }, /* GL_SAMPLE_ALPHA_TO_ONE_ARB */
+ { 29936, 0x000080A8 }, /* GL_SAMPLE_BUFFERS */
+ { 29954, 0x000086B3 }, /* GL_SAMPLE_BUFFERS_3DFX */
+ { 29977, 0x000080A8 }, /* GL_SAMPLE_BUFFERS_ARB */
+ { 29999, 0x000080A0 }, /* GL_SAMPLE_COVERAGE */
+ { 30018, 0x000080A0 }, /* GL_SAMPLE_COVERAGE_ARB */
+ { 30041, 0x000080AB }, /* GL_SAMPLE_COVERAGE_INVERT */
+ { 30067, 0x000080AB }, /* GL_SAMPLE_COVERAGE_INVERT_ARB */
+ { 30097, 0x000080AA }, /* GL_SAMPLE_COVERAGE_VALUE */
+ { 30122, 0x000080AA }, /* GL_SAMPLE_COVERAGE_VALUE_ARB */
+ { 30151, 0x00080000 }, /* GL_SCISSOR_BIT */
+ { 30166, 0x00000C10 }, /* GL_SCISSOR_BOX */
+ { 30181, 0x00000C11 }, /* GL_SCISSOR_TEST */
+ { 30197, 0x0000845E }, /* GL_SECONDARY_COLOR_ARRAY */
+ { 30222, 0x0000889C }, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING */
+ { 30262, 0x0000889C }, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB */
+ { 30306, 0x0000845D }, /* GL_SECONDARY_COLOR_ARRAY_POINTER */
+ { 30339, 0x0000845A }, /* GL_SECONDARY_COLOR_ARRAY_SIZE */
+ { 30369, 0x0000845C }, /* GL_SECONDARY_COLOR_ARRAY_STRIDE */
+ { 30401, 0x0000845B }, /* GL_SECONDARY_COLOR_ARRAY_TYPE */
+ { 30431, 0x00001C02 }, /* GL_SELECT */
+ { 30441, 0x00000DF3 }, /* GL_SELECTION_BUFFER_POINTER */
+ { 30469, 0x00000DF4 }, /* GL_SELECTION_BUFFER_SIZE */
+ { 30494, 0x00008012 }, /* GL_SEPARABLE_2D */
+ { 30510, 0x000081FA }, /* GL_SEPARATE_SPECULAR_COLOR */
+ { 30537, 0x000081FA }, /* GL_SEPARATE_SPECULAR_COLOR_EXT */
+ { 30568, 0x0000150F }, /* GL_SET */
+ { 30575, 0x00008B48 }, /* GL_SHADER_OBJECT_ARB */
+ { 30596, 0x00008B88 }, /* GL_SHADER_SOURCE_LENGTH */
+ { 30620, 0x00008B4F }, /* GL_SHADER_TYPE */
+ { 30635, 0x00000B54 }, /* GL_SHADE_MODEL */
+ { 30650, 0x00008B8C }, /* GL_SHADING_LANGUAGE_VERSION */
+ { 30678, 0x000080BF }, /* GL_SHADOW_AMBIENT_SGIX */
+ { 30701, 0x000081FB }, /* GL_SHARED_TEXTURE_PALETTE_EXT */
+ { 30731, 0x00001601 }, /* GL_SHININESS */
+ { 30744, 0x00001402 }, /* GL_SHORT */
+ { 30753, 0x00009119 }, /* GL_SIGNALED */
+ { 30765, 0x00008F9C }, /* GL_SIGNED_NORMALIZED */
+ { 30786, 0x000081F9 }, /* GL_SINGLE_COLOR */
+ { 30802, 0x000081F9 }, /* GL_SINGLE_COLOR_EXT */
+ { 30822, 0x000085CC }, /* GL_SLICE_ACCUM_SUN */
+ { 30841, 0x00008C46 }, /* GL_SLUMINANCE */
+ { 30855, 0x00008C47 }, /* GL_SLUMINANCE8 */
+ { 30870, 0x00008C45 }, /* GL_SLUMINANCE8_ALPHA8 */
+ { 30892, 0x00008C44 }, /* GL_SLUMINANCE_ALPHA */
+ { 30912, 0x00001D01 }, /* GL_SMOOTH */
+ { 30922, 0x00000B23 }, /* GL_SMOOTH_LINE_WIDTH_GRANULARITY */
+ { 30955, 0x00000B22 }, /* GL_SMOOTH_LINE_WIDTH_RANGE */
+ { 30982, 0x00000B13 }, /* GL_SMOOTH_POINT_SIZE_GRANULARITY */
+ { 31015, 0x00000B12 }, /* GL_SMOOTH_POINT_SIZE_RANGE */
+ { 31042, 0x00008588 }, /* GL_SOURCE0_ALPHA */
+ { 31059, 0x00008588 }, /* GL_SOURCE0_ALPHA_ARB */
+ { 31080, 0x00008588 }, /* GL_SOURCE0_ALPHA_EXT */
+ { 31101, 0x00008580 }, /* GL_SOURCE0_RGB */
+ { 31116, 0x00008580 }, /* GL_SOURCE0_RGB_ARB */
+ { 31135, 0x00008580 }, /* GL_SOURCE0_RGB_EXT */
+ { 31154, 0x00008589 }, /* GL_SOURCE1_ALPHA */
+ { 31171, 0x00008589 }, /* GL_SOURCE1_ALPHA_ARB */
+ { 31192, 0x00008589 }, /* GL_SOURCE1_ALPHA_EXT */
+ { 31213, 0x00008581 }, /* GL_SOURCE1_RGB */
+ { 31228, 0x00008581 }, /* GL_SOURCE1_RGB_ARB */
+ { 31247, 0x00008581 }, /* GL_SOURCE1_RGB_EXT */
+ { 31266, 0x0000858A }, /* GL_SOURCE2_ALPHA */
+ { 31283, 0x0000858A }, /* GL_SOURCE2_ALPHA_ARB */
+ { 31304, 0x0000858A }, /* GL_SOURCE2_ALPHA_EXT */
+ { 31325, 0x00008582 }, /* GL_SOURCE2_RGB */
+ { 31340, 0x00008582 }, /* GL_SOURCE2_RGB_ARB */
+ { 31359, 0x00008582 }, /* GL_SOURCE2_RGB_EXT */
+ { 31378, 0x0000858B }, /* GL_SOURCE3_ALPHA_NV */
+ { 31398, 0x00008583 }, /* GL_SOURCE3_RGB_NV */
+ { 31416, 0x00001202 }, /* GL_SPECULAR */
+ { 31428, 0x00002402 }, /* GL_SPHERE_MAP */
+ { 31442, 0x00001206 }, /* GL_SPOT_CUTOFF */
+ { 31457, 0x00001204 }, /* GL_SPOT_DIRECTION */
+ { 31475, 0x00001205 }, /* GL_SPOT_EXPONENT */
+ { 31492, 0x00008588 }, /* GL_SRC0_ALPHA */
+ { 31506, 0x00008580 }, /* GL_SRC0_RGB */
+ { 31518, 0x00008589 }, /* GL_SRC1_ALPHA */
+ { 31532, 0x00008581 }, /* GL_SRC1_RGB */
+ { 31544, 0x0000858A }, /* GL_SRC2_ALPHA */
+ { 31558, 0x00008582 }, /* GL_SRC2_RGB */
+ { 31570, 0x00000302 }, /* GL_SRC_ALPHA */
+ { 31583, 0x00000308 }, /* GL_SRC_ALPHA_SATURATE */
+ { 31605, 0x00000300 }, /* GL_SRC_COLOR */
+ { 31618, 0x00008C40 }, /* GL_SRGB */
+ { 31626, 0x00008C41 }, /* GL_SRGB8 */
+ { 31635, 0x00008C43 }, /* GL_SRGB8_ALPHA8 */
+ { 31651, 0x00008C42 }, /* GL_SRGB_ALPHA */
+ { 31665, 0x00000503 }, /* GL_STACK_OVERFLOW */
+ { 31683, 0x00000504 }, /* GL_STACK_UNDERFLOW */
+ { 31702, 0x000088E6 }, /* GL_STATIC_COPY */
+ { 31717, 0x000088E6 }, /* GL_STATIC_COPY_ARB */
+ { 31736, 0x000088E4 }, /* GL_STATIC_DRAW */
+ { 31751, 0x000088E4 }, /* GL_STATIC_DRAW_ARB */
+ { 31770, 0x000088E5 }, /* GL_STATIC_READ */
+ { 31785, 0x000088E5 }, /* GL_STATIC_READ_ARB */
+ { 31804, 0x00001802 }, /* GL_STENCIL */
+ { 31815, 0x00008D20 }, /* GL_STENCIL_ATTACHMENT */
+ { 31837, 0x00008D20 }, /* GL_STENCIL_ATTACHMENT_EXT */
+ { 31863, 0x00008801 }, /* GL_STENCIL_BACK_FAIL */
+ { 31884, 0x00008801 }, /* GL_STENCIL_BACK_FAIL_ATI */
+ { 31909, 0x00008800 }, /* GL_STENCIL_BACK_FUNC */
+ { 31930, 0x00008800 }, /* GL_STENCIL_BACK_FUNC_ATI */
+ { 31955, 0x00008802 }, /* GL_STENCIL_BACK_PASS_DEPTH_FAIL */
+ { 31987, 0x00008802 }, /* GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI */
+ { 32023, 0x00008803 }, /* GL_STENCIL_BACK_PASS_DEPTH_PASS */
+ { 32055, 0x00008803 }, /* GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI */
+ { 32091, 0x00008CA3 }, /* GL_STENCIL_BACK_REF */
+ { 32111, 0x00008CA4 }, /* GL_STENCIL_BACK_VALUE_MASK */
+ { 32138, 0x00008CA5 }, /* GL_STENCIL_BACK_WRITEMASK */
+ { 32164, 0x00000D57 }, /* GL_STENCIL_BITS */
+ { 32180, 0x00000400 }, /* GL_STENCIL_BUFFER_BIT */
+ { 32202, 0x00000B91 }, /* GL_STENCIL_CLEAR_VALUE */
+ { 32225, 0x00000B94 }, /* GL_STENCIL_FAIL */
+ { 32241, 0x00000B92 }, /* GL_STENCIL_FUNC */
+ { 32257, 0x00001901 }, /* GL_STENCIL_INDEX */
+ { 32274, 0x00008D49 }, /* GL_STENCIL_INDEX16_EXT */
+ { 32297, 0x00008D46 }, /* GL_STENCIL_INDEX1_EXT */
+ { 32319, 0x00008D47 }, /* GL_STENCIL_INDEX4_EXT */
+ { 32341, 0x00008D48 }, /* GL_STENCIL_INDEX8_EXT */
+ { 32363, 0x00008D45 }, /* GL_STENCIL_INDEX_EXT */
+ { 32384, 0x00000B95 }, /* GL_STENCIL_PASS_DEPTH_FAIL */
+ { 32411, 0x00000B96 }, /* GL_STENCIL_PASS_DEPTH_PASS */
+ { 32438, 0x00000B97 }, /* GL_STENCIL_REF */
+ { 32453, 0x00000B90 }, /* GL_STENCIL_TEST */
+ { 32469, 0x00008910 }, /* GL_STENCIL_TEST_TWO_SIDE_EXT */
+ { 32498, 0x00000B93 }, /* GL_STENCIL_VALUE_MASK */
+ { 32520, 0x00000B98 }, /* GL_STENCIL_WRITEMASK */
+ { 32541, 0x00000C33 }, /* GL_STEREO */
+ { 32551, 0x000085BE }, /* GL_STORAGE_CACHED_APPLE */
+ { 32575, 0x000085BD }, /* GL_STORAGE_PRIVATE_APPLE */
+ { 32600, 0x000085BF }, /* GL_STORAGE_SHARED_APPLE */
+ { 32624, 0x000088E2 }, /* GL_STREAM_COPY */
+ { 32639, 0x000088E2 }, /* GL_STREAM_COPY_ARB */
+ { 32658, 0x000088E0 }, /* GL_STREAM_DRAW */
+ { 32673, 0x000088E0 }, /* GL_STREAM_DRAW_ARB */
+ { 32692, 0x000088E1 }, /* GL_STREAM_READ */
+ { 32707, 0x000088E1 }, /* GL_STREAM_READ_ARB */
+ { 32726, 0x00000D50 }, /* GL_SUBPIXEL_BITS */
+ { 32743, 0x000084E7 }, /* GL_SUBTRACT */
+ { 32755, 0x000084E7 }, /* GL_SUBTRACT_ARB */
+ { 32771, 0x00009113 }, /* GL_SYNC_CONDITION */
+ { 32789, 0x00009116 }, /* GL_SYNC_FENCE */
+ { 32803, 0x00009115 }, /* GL_SYNC_FLAGS */
+ { 32817, 0x00000001 }, /* GL_SYNC_FLUSH_COMMANDS_BIT */
+ { 32844, 0x00009117 }, /* GL_SYNC_GPU_COMMANDS_COMPLETE */
+ { 32874, 0x00009114 }, /* GL_SYNC_STATUS */
+ { 32889, 0x00002001 }, /* GL_T */
+ { 32894, 0x00002A2A }, /* GL_T2F_C3F_V3F */
+ { 32909, 0x00002A2C }, /* GL_T2F_C4F_N3F_V3F */
+ { 32928, 0x00002A29 }, /* GL_T2F_C4UB_V3F */
+ { 32944, 0x00002A2B }, /* GL_T2F_N3F_V3F */
+ { 32959, 0x00002A27 }, /* GL_T2F_V3F */
+ { 32970, 0x00002A2D }, /* GL_T4F_C4F_N3F_V4F */
+ { 32989, 0x00002A28 }, /* GL_T4F_V4F */
+ { 33000, 0x00008031 }, /* GL_TABLE_TOO_LARGE_EXT */
+ { 33023, 0x00001702 }, /* GL_TEXTURE */
+ { 33034, 0x000084C0 }, /* GL_TEXTURE0 */
+ { 33046, 0x000084C0 }, /* GL_TEXTURE0_ARB */
+ { 33062, 0x000084C1 }, /* GL_TEXTURE1 */
+ { 33074, 0x000084CA }, /* GL_TEXTURE10 */
+ { 33087, 0x000084CA }, /* GL_TEXTURE10_ARB */
+ { 33104, 0x000084CB }, /* GL_TEXTURE11 */
+ { 33117, 0x000084CB }, /* GL_TEXTURE11_ARB */
+ { 33134, 0x000084CC }, /* GL_TEXTURE12 */
+ { 33147, 0x000084CC }, /* GL_TEXTURE12_ARB */
+ { 33164, 0x000084CD }, /* GL_TEXTURE13 */
+ { 33177, 0x000084CD }, /* GL_TEXTURE13_ARB */
+ { 33194, 0x000084CE }, /* GL_TEXTURE14 */
+ { 33207, 0x000084CE }, /* GL_TEXTURE14_ARB */
+ { 33224, 0x000084CF }, /* GL_TEXTURE15 */
+ { 33237, 0x000084CF }, /* GL_TEXTURE15_ARB */
+ { 33254, 0x000084D0 }, /* GL_TEXTURE16 */
+ { 33267, 0x000084D0 }, /* GL_TEXTURE16_ARB */
+ { 33284, 0x000084D1 }, /* GL_TEXTURE17 */
+ { 33297, 0x000084D1 }, /* GL_TEXTURE17_ARB */
+ { 33314, 0x000084D2 }, /* GL_TEXTURE18 */
+ { 33327, 0x000084D2 }, /* GL_TEXTURE18_ARB */
+ { 33344, 0x000084D3 }, /* GL_TEXTURE19 */
+ { 33357, 0x000084D3 }, /* GL_TEXTURE19_ARB */
+ { 33374, 0x000084C1 }, /* GL_TEXTURE1_ARB */
+ { 33390, 0x000084C2 }, /* GL_TEXTURE2 */
+ { 33402, 0x000084D4 }, /* GL_TEXTURE20 */
+ { 33415, 0x000084D4 }, /* GL_TEXTURE20_ARB */
+ { 33432, 0x000084D5 }, /* GL_TEXTURE21 */
+ { 33445, 0x000084D5 }, /* GL_TEXTURE21_ARB */
+ { 33462, 0x000084D6 }, /* GL_TEXTURE22 */
+ { 33475, 0x000084D6 }, /* GL_TEXTURE22_ARB */
+ { 33492, 0x000084D7 }, /* GL_TEXTURE23 */
+ { 33505, 0x000084D7 }, /* GL_TEXTURE23_ARB */
+ { 33522, 0x000084D8 }, /* GL_TEXTURE24 */
+ { 33535, 0x000084D8 }, /* GL_TEXTURE24_ARB */
+ { 33552, 0x000084D9 }, /* GL_TEXTURE25 */
+ { 33565, 0x000084D9 }, /* GL_TEXTURE25_ARB */
+ { 33582, 0x000084DA }, /* GL_TEXTURE26 */
+ { 33595, 0x000084DA }, /* GL_TEXTURE26_ARB */
+ { 33612, 0x000084DB }, /* GL_TEXTURE27 */
+ { 33625, 0x000084DB }, /* GL_TEXTURE27_ARB */
+ { 33642, 0x000084DC }, /* GL_TEXTURE28 */
+ { 33655, 0x000084DC }, /* GL_TEXTURE28_ARB */
+ { 33672, 0x000084DD }, /* GL_TEXTURE29 */
+ { 33685, 0x000084DD }, /* GL_TEXTURE29_ARB */
+ { 33702, 0x000084C2 }, /* GL_TEXTURE2_ARB */
+ { 33718, 0x000084C3 }, /* GL_TEXTURE3 */
+ { 33730, 0x000084DE }, /* GL_TEXTURE30 */
+ { 33743, 0x000084DE }, /* GL_TEXTURE30_ARB */
+ { 33760, 0x000084DF }, /* GL_TEXTURE31 */
+ { 33773, 0x000084DF }, /* GL_TEXTURE31_ARB */
+ { 33790, 0x000084C3 }, /* GL_TEXTURE3_ARB */
+ { 33806, 0x000084C4 }, /* GL_TEXTURE4 */
+ { 33818, 0x000084C4 }, /* GL_TEXTURE4_ARB */
+ { 33834, 0x000084C5 }, /* GL_TEXTURE5 */
+ { 33846, 0x000084C5 }, /* GL_TEXTURE5_ARB */
+ { 33862, 0x000084C6 }, /* GL_TEXTURE6 */
+ { 33874, 0x000084C6 }, /* GL_TEXTURE6_ARB */
+ { 33890, 0x000084C7 }, /* GL_TEXTURE7 */
+ { 33902, 0x000084C7 }, /* GL_TEXTURE7_ARB */
+ { 33918, 0x000084C8 }, /* GL_TEXTURE8 */
+ { 33930, 0x000084C8 }, /* GL_TEXTURE8_ARB */
+ { 33946, 0x000084C9 }, /* GL_TEXTURE9 */
+ { 33958, 0x000084C9 }, /* GL_TEXTURE9_ARB */
+ { 33974, 0x00000DE0 }, /* GL_TEXTURE_1D */
+ { 33988, 0x00008C18 }, /* GL_TEXTURE_1D_ARRAY_EXT */
+ { 34012, 0x00000DE1 }, /* GL_TEXTURE_2D */
+ { 34026, 0x00008C1A }, /* GL_TEXTURE_2D_ARRAY_EXT */
+ { 34050, 0x0000806F }, /* GL_TEXTURE_3D */
+ { 34064, 0x0000805F }, /* GL_TEXTURE_ALPHA_SIZE */
+ { 34086, 0x0000805F }, /* GL_TEXTURE_ALPHA_SIZE_EXT */
+ { 34112, 0x0000813C }, /* GL_TEXTURE_BASE_LEVEL */
+ { 34134, 0x00008068 }, /* GL_TEXTURE_BINDING_1D */
+ { 34156, 0x00008C1C }, /* GL_TEXTURE_BINDING_1D_ARRAY_EXT */
+ { 34188, 0x00008069 }, /* GL_TEXTURE_BINDING_2D */
+ { 34210, 0x00008C1D }, /* GL_TEXTURE_BINDING_2D_ARRAY_EXT */
+ { 34242, 0x0000806A }, /* GL_TEXTURE_BINDING_3D */
+ { 34264, 0x00008514 }, /* GL_TEXTURE_BINDING_CUBE_MAP */
+ { 34292, 0x00008514 }, /* GL_TEXTURE_BINDING_CUBE_MAP_ARB */
+ { 34324, 0x000084F6 }, /* GL_TEXTURE_BINDING_RECTANGLE_ARB */
+ { 34357, 0x000084F6 }, /* GL_TEXTURE_BINDING_RECTANGLE_NV */
+ { 34389, 0x00040000 }, /* GL_TEXTURE_BIT */
+ { 34404, 0x0000805E }, /* GL_TEXTURE_BLUE_SIZE */
+ { 34425, 0x0000805E }, /* GL_TEXTURE_BLUE_SIZE_EXT */
+ { 34450, 0x00001005 }, /* GL_TEXTURE_BORDER */
+ { 34468, 0x00001004 }, /* GL_TEXTURE_BORDER_COLOR */
+ { 34492, 0x00008171 }, /* GL_TEXTURE_CLIPMAP_CENTER_SGIX */
+ { 34523, 0x00008176 }, /* GL_TEXTURE_CLIPMAP_DEPTH_SGIX */
+ { 34553, 0x00008172 }, /* GL_TEXTURE_CLIPMAP_FRAME_SGIX */
+ { 34583, 0x00008175 }, /* GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX */
+ { 34618, 0x00008173 }, /* GL_TEXTURE_CLIPMAP_OFFSET_SGIX */
+ { 34649, 0x00008174 }, /* GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX */
+ { 34687, 0x000080BC }, /* GL_TEXTURE_COLOR_TABLE_SGI */
+ { 34714, 0x000081EF }, /* GL_TEXTURE_COLOR_WRITEMASK_SGIS */
+ { 34746, 0x000080BF }, /* GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
+ { 34780, 0x0000884D }, /* GL_TEXTURE_COMPARE_FUNC */
+ { 34804, 0x0000884D }, /* GL_TEXTURE_COMPARE_FUNC_ARB */
+ { 34832, 0x0000884C }, /* GL_TEXTURE_COMPARE_MODE */
+ { 34856, 0x0000884C }, /* GL_TEXTURE_COMPARE_MODE_ARB */
+ { 34884, 0x0000819B }, /* GL_TEXTURE_COMPARE_OPERATOR_SGIX */
+ { 34917, 0x0000819A }, /* GL_TEXTURE_COMPARE_SGIX */
+ { 34941, 0x00001003 }, /* GL_TEXTURE_COMPONENTS */
+ { 34963, 0x000086A1 }, /* GL_TEXTURE_COMPRESSED */
+ { 34985, 0x000086A1 }, /* GL_TEXTURE_COMPRESSED_ARB */
+ { 35011, 0x000086A3 }, /* GL_TEXTURE_COMPRESSED_FORMATS_ARB */
+ { 35045, 0x000086A0 }, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE */
+ { 35078, 0x000086A0 }, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB */
+ { 35115, 0x000084EF }, /* GL_TEXTURE_COMPRESSION_HINT */
+ { 35143, 0x000084EF }, /* GL_TEXTURE_COMPRESSION_HINT_ARB */
+ { 35175, 0x00008078 }, /* GL_TEXTURE_COORD_ARRAY */
+ { 35198, 0x0000889A }, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING */
+ { 35236, 0x0000889A }, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB */
+ { 35278, 0x00008092 }, /* GL_TEXTURE_COORD_ARRAY_POINTER */
+ { 35309, 0x00008088 }, /* GL_TEXTURE_COORD_ARRAY_SIZE */
+ { 35337, 0x0000808A }, /* GL_TEXTURE_COORD_ARRAY_STRIDE */
+ { 35367, 0x00008089 }, /* GL_TEXTURE_COORD_ARRAY_TYPE */
+ { 35395, 0x00008513 }, /* GL_TEXTURE_CUBE_MAP */
+ { 35415, 0x00008513 }, /* GL_TEXTURE_CUBE_MAP_ARB */
+ { 35439, 0x00008516 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */
+ { 35470, 0x00008516 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB */
+ { 35505, 0x00008518 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */
+ { 35536, 0x00008518 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB */
+ { 35571, 0x0000851A }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */
+ { 35602, 0x0000851A }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB */
+ { 35637, 0x00008515 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */
+ { 35668, 0x00008515 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB */
+ { 35703, 0x00008517 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */
+ { 35734, 0x00008517 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB */
+ { 35769, 0x00008519 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */
+ { 35800, 0x00008519 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB */
+ { 35835, 0x000088F4 }, /* GL_TEXTURE_CUBE_MAP_SEAMLESS */
+ { 35864, 0x00008071 }, /* GL_TEXTURE_DEPTH */
+ { 35881, 0x0000884A }, /* GL_TEXTURE_DEPTH_SIZE */
+ { 35903, 0x0000884A }, /* GL_TEXTURE_DEPTH_SIZE_ARB */
+ { 35929, 0x00002300 }, /* GL_TEXTURE_ENV */
+ { 35944, 0x00002201 }, /* GL_TEXTURE_ENV_COLOR */
+ { 35965, 0x00002200 }, /* GL_TEXTURE_ENV_MODE */
+ { 35985, 0x00008500 }, /* GL_TEXTURE_FILTER_CONTROL */
+ { 36011, 0x00002500 }, /* GL_TEXTURE_GEN_MODE */
+ { 36031, 0x00000C63 }, /* GL_TEXTURE_GEN_Q */
+ { 36048, 0x00000C62 }, /* GL_TEXTURE_GEN_R */
+ { 36065, 0x00000C60 }, /* GL_TEXTURE_GEN_S */
+ { 36082, 0x00000C61 }, /* GL_TEXTURE_GEN_T */
+ { 36099, 0x0000819D }, /* GL_TEXTURE_GEQUAL_R_SGIX */
+ { 36124, 0x0000805D }, /* GL_TEXTURE_GREEN_SIZE */
+ { 36146, 0x0000805D }, /* GL_TEXTURE_GREEN_SIZE_EXT */
+ { 36172, 0x00001001 }, /* GL_TEXTURE_HEIGHT */
+ { 36190, 0x000080ED }, /* GL_TEXTURE_INDEX_SIZE_EXT */
+ { 36216, 0x00008061 }, /* GL_TEXTURE_INTENSITY_SIZE */
+ { 36242, 0x00008061 }, /* GL_TEXTURE_INTENSITY_SIZE_EXT */
+ { 36272, 0x00001003 }, /* GL_TEXTURE_INTERNAL_FORMAT */
+ { 36299, 0x0000819C }, /* GL_TEXTURE_LEQUAL_R_SGIX */
+ { 36324, 0x00008501 }, /* GL_TEXTURE_LOD_BIAS */
+ { 36344, 0x00008501 }, /* GL_TEXTURE_LOD_BIAS_EXT */
+ { 36368, 0x00008190 }, /* GL_TEXTURE_LOD_BIAS_R_SGIX */
+ { 36395, 0x0000818E }, /* GL_TEXTURE_LOD_BIAS_S_SGIX */
+ { 36422, 0x0000818F }, /* GL_TEXTURE_LOD_BIAS_T_SGIX */
+ { 36449, 0x00008060 }, /* GL_TEXTURE_LUMINANCE_SIZE */
+ { 36475, 0x00008060 }, /* GL_TEXTURE_LUMINANCE_SIZE_EXT */
+ { 36505, 0x00002800 }, /* GL_TEXTURE_MAG_FILTER */
+ { 36527, 0x00000BA8 }, /* GL_TEXTURE_MATRIX */
+ { 36545, 0x000084FE }, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */
+ { 36575, 0x0000836B }, /* GL_TEXTURE_MAX_CLAMP_R_SGIX */
+ { 36603, 0x00008369 }, /* GL_TEXTURE_MAX_CLAMP_S_SGIX */
+ { 36631, 0x0000836A }, /* GL_TEXTURE_MAX_CLAMP_T_SGIX */
+ { 36659, 0x0000813D }, /* GL_TEXTURE_MAX_LEVEL */
+ { 36680, 0x0000813B }, /* GL_TEXTURE_MAX_LOD */
+ { 36699, 0x00002801 }, /* GL_TEXTURE_MIN_FILTER */
+ { 36721, 0x0000813A }, /* GL_TEXTURE_MIN_LOD */
+ { 36740, 0x00008066 }, /* GL_TEXTURE_PRIORITY */
+ { 36760, 0x000085B7 }, /* GL_TEXTURE_RANGE_LENGTH_APPLE */
+ { 36790, 0x000085B8 }, /* GL_TEXTURE_RANGE_POINTER_APPLE */
+ { 36821, 0x000084F5 }, /* GL_TEXTURE_RECTANGLE_ARB */
+ { 36846, 0x000084F5 }, /* GL_TEXTURE_RECTANGLE_NV */
+ { 36870, 0x0000805C }, /* GL_TEXTURE_RED_SIZE */
+ { 36890, 0x0000805C }, /* GL_TEXTURE_RED_SIZE_EXT */
+ { 36914, 0x00008067 }, /* GL_TEXTURE_RESIDENT */
+ { 36934, 0x00000BA5 }, /* GL_TEXTURE_STACK_DEPTH */
+ { 36957, 0x000088F1 }, /* GL_TEXTURE_STENCIL_SIZE */
+ { 36981, 0x000085BC }, /* GL_TEXTURE_STORAGE_HINT_APPLE */
+ { 37011, 0x00008065 }, /* GL_TEXTURE_TOO_LARGE_EXT */
+ { 37036, 0x0000888F }, /* GL_TEXTURE_UNSIGNED_REMAP_MODE_NV */
+ { 37070, 0x00001000 }, /* GL_TEXTURE_WIDTH */
+ { 37087, 0x00008072 }, /* GL_TEXTURE_WRAP_R */
+ { 37105, 0x00002802 }, /* GL_TEXTURE_WRAP_S */
+ { 37123, 0x00002803 }, /* GL_TEXTURE_WRAP_T */
+ { 37141, 0x0000911B }, /* GL_TIMEOUT_EXPIRED */
+ { 37160, 0xFFFFFFFFFFFFFFFF }, /* GL_TIMEOUT_IGNORED */
+ { 37179, 0x000088BF }, /* GL_TIME_ELAPSED_EXT */
+ { 37199, 0x00008648 }, /* GL_TRACK_MATRIX_NV */
+ { 37218, 0x00008649 }, /* GL_TRACK_MATRIX_TRANSFORM_NV */
+ { 37247, 0x00001000 }, /* GL_TRANSFORM_BIT */
+ { 37264, 0x000084E6 }, /* GL_TRANSPOSE_COLOR_MATRIX */
+ { 37290, 0x000084E6 }, /* GL_TRANSPOSE_COLOR_MATRIX_ARB */
+ { 37320, 0x000088B7 }, /* GL_TRANSPOSE_CURRENT_MATRIX_ARB */
+ { 37352, 0x000084E3 }, /* GL_TRANSPOSE_MODELVIEW_MATRIX */
+ { 37382, 0x000084E3 }, /* GL_TRANSPOSE_MODELVIEW_MATRIX_ARB */
+ { 37416, 0x0000862C }, /* GL_TRANSPOSE_NV */
+ { 37432, 0x000084E4 }, /* GL_TRANSPOSE_PROJECTION_MATRIX */
+ { 37463, 0x000084E4 }, /* GL_TRANSPOSE_PROJECTION_MATRIX_ARB */
+ { 37498, 0x000084E5 }, /* GL_TRANSPOSE_TEXTURE_MATRIX */
+ { 37526, 0x000084E5 }, /* GL_TRANSPOSE_TEXTURE_MATRIX_ARB */
+ { 37558, 0x00000004 }, /* GL_TRIANGLES */
+ { 37571, 0x00000006 }, /* GL_TRIANGLE_FAN */
+ { 37587, 0x00008615 }, /* GL_TRIANGLE_MESH_SUN */
+ { 37608, 0x00000005 }, /* GL_TRIANGLE_STRIP */
+ { 37626, 0x00000001 }, /* GL_TRUE */
+ { 37634, 0x00000CF5 }, /* GL_UNPACK_ALIGNMENT */
+ { 37654, 0x0000806E }, /* GL_UNPACK_IMAGE_HEIGHT */
+ { 37677, 0x00000CF1 }, /* GL_UNPACK_LSB_FIRST */
+ { 37697, 0x00000CF2 }, /* GL_UNPACK_ROW_LENGTH */
+ { 37718, 0x0000806D }, /* GL_UNPACK_SKIP_IMAGES */
+ { 37740, 0x00000CF4 }, /* GL_UNPACK_SKIP_PIXELS */
+ { 37762, 0x00000CF3 }, /* GL_UNPACK_SKIP_ROWS */
+ { 37782, 0x00000CF0 }, /* GL_UNPACK_SWAP_BYTES */
+ { 37803, 0x00009118 }, /* GL_UNSIGNALED */
+ { 37817, 0x00001401 }, /* GL_UNSIGNED_BYTE */
+ { 37834, 0x00008362 }, /* GL_UNSIGNED_BYTE_2_3_3_REV */
+ { 37861, 0x00008032 }, /* GL_UNSIGNED_BYTE_3_3_2 */
+ { 37884, 0x00001405 }, /* GL_UNSIGNED_INT */
+ { 37900, 0x00008036 }, /* GL_UNSIGNED_INT_10_10_10_2 */
+ { 37927, 0x000084FA }, /* GL_UNSIGNED_INT_24_8 */
+ { 37948, 0x000084FA }, /* GL_UNSIGNED_INT_24_8_NV */
+ { 37972, 0x00008368 }, /* GL_UNSIGNED_INT_2_10_10_10_REV */
+ { 38003, 0x00008035 }, /* GL_UNSIGNED_INT_8_8_8_8 */
+ { 38027, 0x00008367 }, /* GL_UNSIGNED_INT_8_8_8_8_REV */
+ { 38055, 0x00008C17 }, /* GL_UNSIGNED_NORMALIZED */
+ { 38078, 0x00001403 }, /* GL_UNSIGNED_SHORT */
+ { 38096, 0x00008366 }, /* GL_UNSIGNED_SHORT_1_5_5_5_REV */
+ { 38126, 0x00008033 }, /* GL_UNSIGNED_SHORT_4_4_4_4 */
+ { 38152, 0x00008365 }, /* GL_UNSIGNED_SHORT_4_4_4_4_REV */
+ { 38182, 0x00008034 }, /* GL_UNSIGNED_SHORT_5_5_5_1 */
+ { 38208, 0x00008363 }, /* GL_UNSIGNED_SHORT_5_6_5 */
+ { 38232, 0x00008364 }, /* GL_UNSIGNED_SHORT_5_6_5_REV */
+ { 38260, 0x000085BA }, /* GL_UNSIGNED_SHORT_8_8_APPLE */
+ { 38288, 0x000085BA }, /* GL_UNSIGNED_SHORT_8_8_MESA */
+ { 38315, 0x000085BB }, /* GL_UNSIGNED_SHORT_8_8_REV_APPLE */
+ { 38347, 0x000085BB }, /* GL_UNSIGNED_SHORT_8_8_REV_MESA */
+ { 38378, 0x00008CA2 }, /* GL_UPPER_LEFT */
+ { 38392, 0x00002A20 }, /* GL_V2F */
+ { 38399, 0x00002A21 }, /* GL_V3F */
+ { 38406, 0x00008B83 }, /* GL_VALIDATE_STATUS */
+ { 38425, 0x00001F00 }, /* GL_VENDOR */
+ { 38435, 0x00001F02 }, /* GL_VERSION */
+ { 38446, 0x00008074 }, /* GL_VERTEX_ARRAY */
+ { 38462, 0x000085B5 }, /* GL_VERTEX_ARRAY_BINDING */
+ { 38486, 0x000085B5 }, /* GL_VERTEX_ARRAY_BINDING_APPLE */
+ { 38516, 0x00008896 }, /* GL_VERTEX_ARRAY_BUFFER_BINDING */
+ { 38547, 0x00008896 }, /* GL_VERTEX_ARRAY_BUFFER_BINDING_ARB */
+ { 38582, 0x0000808E }, /* GL_VERTEX_ARRAY_POINTER */
+ { 38606, 0x0000807A }, /* GL_VERTEX_ARRAY_SIZE */
+ { 38627, 0x0000807C }, /* GL_VERTEX_ARRAY_STRIDE */
+ { 38650, 0x0000807B }, /* GL_VERTEX_ARRAY_TYPE */
+ { 38671, 0x00008650 }, /* GL_VERTEX_ATTRIB_ARRAY0_NV */
+ { 38698, 0x0000865A }, /* GL_VERTEX_ATTRIB_ARRAY10_NV */
+ { 38726, 0x0000865B }, /* GL_VERTEX_ATTRIB_ARRAY11_NV */
+ { 38754, 0x0000865C }, /* GL_VERTEX_ATTRIB_ARRAY12_NV */
+ { 38782, 0x0000865D }, /* GL_VERTEX_ATTRIB_ARRAY13_NV */
+ { 38810, 0x0000865E }, /* GL_VERTEX_ATTRIB_ARRAY14_NV */
+ { 38838, 0x0000865F }, /* GL_VERTEX_ATTRIB_ARRAY15_NV */
+ { 38866, 0x00008651 }, /* GL_VERTEX_ATTRIB_ARRAY1_NV */
+ { 38893, 0x00008652 }, /* GL_VERTEX_ATTRIB_ARRAY2_NV */
+ { 38920, 0x00008653 }, /* GL_VERTEX_ATTRIB_ARRAY3_NV */
+ { 38947, 0x00008654 }, /* GL_VERTEX_ATTRIB_ARRAY4_NV */
+ { 38974, 0x00008655 }, /* GL_VERTEX_ATTRIB_ARRAY5_NV */
+ { 39001, 0x00008656 }, /* GL_VERTEX_ATTRIB_ARRAY6_NV */
+ { 39028, 0x00008657 }, /* GL_VERTEX_ATTRIB_ARRAY7_NV */
+ { 39055, 0x00008658 }, /* GL_VERTEX_ATTRIB_ARRAY8_NV */
+ { 39082, 0x00008659 }, /* GL_VERTEX_ATTRIB_ARRAY9_NV */
+ { 39109, 0x0000889F }, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING */
+ { 39147, 0x0000889F }, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB */
+ { 39189, 0x00008622 }, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED */
+ { 39220, 0x00008622 }, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB */
+ { 39255, 0x0000886A }, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED */
+ { 39289, 0x0000886A }, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB */
+ { 39327, 0x00008645 }, /* GL_VERTEX_ATTRIB_ARRAY_POINTER */
+ { 39358, 0x00008645 }, /* GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB */
+ { 39393, 0x00008623 }, /* GL_VERTEX_ATTRIB_ARRAY_SIZE */
+ { 39421, 0x00008623 }, /* GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB */
+ { 39453, 0x00008624 }, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE */
+ { 39483, 0x00008624 }, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB */
+ { 39517, 0x00008625 }, /* GL_VERTEX_ATTRIB_ARRAY_TYPE */
+ { 39545, 0x00008625 }, /* GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB */
+ { 39577, 0x000086A7 }, /* GL_VERTEX_BLEND_ARB */
+ { 39597, 0x00008620 }, /* GL_VERTEX_PROGRAM_ARB */
+ { 39619, 0x0000864A }, /* GL_VERTEX_PROGRAM_BINDING_NV */
+ { 39648, 0x00008620 }, /* GL_VERTEX_PROGRAM_NV */
+ { 39669, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE */
+ { 39698, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE_ARB */
+ { 39731, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE_NV */
+ { 39763, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE */
+ { 39790, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE_ARB */
+ { 39821, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE_NV */
+ { 39851, 0x00008B31 }, /* GL_VERTEX_SHADER */
+ { 39868, 0x00008B31 }, /* GL_VERTEX_SHADER_ARB */
+ { 39889, 0x00008621 }, /* GL_VERTEX_STATE_PROGRAM_NV */
+ { 39916, 0x00000BA2 }, /* GL_VIEWPORT */
+ { 39928, 0x00000800 }, /* GL_VIEWPORT_BIT */
+ { 39944, 0x0000911D }, /* GL_WAIT_FAILED */
+ { 39959, 0x000086AD }, /* GL_WEIGHT_ARRAY_ARB */
+ { 39979, 0x0000889E }, /* GL_WEIGHT_ARRAY_BUFFER_BINDING */
+ { 40010, 0x0000889E }, /* GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB */
+ { 40045, 0x000086AC }, /* GL_WEIGHT_ARRAY_POINTER_ARB */
+ { 40073, 0x000086AB }, /* GL_WEIGHT_ARRAY_SIZE_ARB */
+ { 40098, 0x000086AA }, /* GL_WEIGHT_ARRAY_STRIDE_ARB */
+ { 40125, 0x000086A9 }, /* GL_WEIGHT_ARRAY_TYPE_ARB */
+ { 40150, 0x000086A6 }, /* GL_WEIGHT_SUM_UNITY_ARB */
+ { 40174, 0x000081D4 }, /* GL_WRAP_BORDER_SUN */
+ { 40193, 0x000088B9 }, /* GL_WRITE_ONLY */
+ { 40207, 0x000088B9 }, /* GL_WRITE_ONLY_ARB */
+ { 40225, 0x00001506 }, /* GL_XOR */
+ { 40232, 0x000085B9 }, /* GL_YCBCR_422_APPLE */
+ { 40251, 0x00008757 }, /* GL_YCBCR_MESA */
+ { 40265, 0x00000000 }, /* GL_ZERO */
+ { 40273, 0x00000D16 }, /* GL_ZOOM_X */
+ { 40283, 0x00000D17 }, /* GL_ZOOM_Y */
};
-static const unsigned reduced_enums[1284] =
+static const unsigned reduced_enums[1347] =
{
- 434, /* GL_FALSE */
- 643, /* GL_LINES */
- 645, /* GL_LINE_LOOP */
- 652, /* GL_LINE_STRIP */
- 1639, /* GL_TRIANGLES */
- 1642, /* GL_TRIANGLE_STRIP */
- 1640, /* GL_TRIANGLE_FAN */
- 1209, /* GL_QUADS */
- 1211, /* GL_QUAD_STRIP */
- 1097, /* GL_POLYGON */
- 1109, /* GL_POLYGON_STIPPLE_BIT */
- 1062, /* GL_PIXEL_MODE_BIT */
- 630, /* GL_LIGHTING_BIT */
- 456, /* GL_FOG_BIT */
+ 476, /* GL_FALSE */
+ 692, /* GL_LINES */
+ 694, /* GL_LINE_LOOP */
+ 701, /* GL_LINE_STRIP */
+ 1744, /* GL_TRIANGLES */
+ 1747, /* GL_TRIANGLE_STRIP */
+ 1745, /* GL_TRIANGLE_FAN */
+ 1272, /* GL_QUADS */
+ 1275, /* GL_QUAD_STRIP */
+ 1159, /* GL_POLYGON */
+ 1171, /* GL_POLYGON_STIPPLE_BIT */
+ 1120, /* GL_PIXEL_MODE_BIT */
+ 679, /* GL_LIGHTING_BIT */
+ 505, /* GL_FOG_BIT */
8, /* GL_ACCUM */
- 662, /* GL_LOAD */
- 1251, /* GL_RETURN */
- 935, /* GL_MULT */
+ 711, /* GL_LOAD */
+ 1327, /* GL_RETURN */
+ 992, /* GL_MULT */
23, /* GL_ADD */
- 951, /* GL_NEVER */
- 620, /* GL_LESS */
- 424, /* GL_EQUAL */
- 619, /* GL_LEQUAL */
- 545, /* GL_GREATER */
- 966, /* GL_NOTEQUAL */
- 520, /* GL_GEQUAL */
- 46, /* GL_ALWAYS */
- 1384, /* GL_SRC_COLOR */
- 995, /* GL_ONE_MINUS_SRC_COLOR */
- 1382, /* GL_SRC_ALPHA */
- 994, /* GL_ONE_MINUS_SRC_ALPHA */
- 405, /* GL_DST_ALPHA */
- 992, /* GL_ONE_MINUS_DST_ALPHA */
- 406, /* GL_DST_COLOR */
- 993, /* GL_ONE_MINUS_DST_COLOR */
- 1383, /* GL_SRC_ALPHA_SATURATE */
- 508, /* GL_FRONT_LEFT */
- 509, /* GL_FRONT_RIGHT */
- 68, /* GL_BACK_LEFT */
- 69, /* GL_BACK_RIGHT */
- 505, /* GL_FRONT */
- 67, /* GL_BACK */
- 618, /* GL_LEFT */
- 1291, /* GL_RIGHT */
- 506, /* GL_FRONT_AND_BACK */
- 62, /* GL_AUX0 */
- 63, /* GL_AUX1 */
- 64, /* GL_AUX2 */
- 65, /* GL_AUX3 */
- 610, /* GL_INVALID_ENUM */
- 613, /* GL_INVALID_VALUE */
- 612, /* GL_INVALID_OPERATION */
- 1385, /* GL_STACK_OVERFLOW */
- 1386, /* GL_STACK_UNDERFLOW */
- 1020, /* GL_OUT_OF_MEMORY */
- 611, /* GL_INVALID_FRAMEBUFFER_OPERATION_EXT */
+ 1008, /* GL_NEVER */
+ 669, /* GL_LESS */
+ 466, /* GL_EQUAL */
+ 668, /* GL_LEQUAL */
+ 591, /* GL_GREATER */
+ 1023, /* GL_NOTEQUAL */
+ 590, /* GL_GEQUAL */
+ 47, /* GL_ALWAYS */
+ 1468, /* GL_SRC_COLOR */
+ 1053, /* GL_ONE_MINUS_SRC_COLOR */
+ 1466, /* GL_SRC_ALPHA */
+ 1052, /* GL_ONE_MINUS_SRC_ALPHA */
+ 445, /* GL_DST_ALPHA */
+ 1050, /* GL_ONE_MINUS_DST_ALPHA */
+ 446, /* GL_DST_COLOR */
+ 1051, /* GL_ONE_MINUS_DST_COLOR */
+ 1467, /* GL_SRC_ALPHA_SATURATE */
+ 578, /* GL_FRONT_LEFT */
+ 579, /* GL_FRONT_RIGHT */
+ 69, /* GL_BACK_LEFT */
+ 70, /* GL_BACK_RIGHT */
+ 575, /* GL_FRONT */
+ 68, /* GL_BACK */
+ 667, /* GL_LEFT */
+ 1369, /* GL_RIGHT */
+ 576, /* GL_FRONT_AND_BACK */
+ 63, /* GL_AUX0 */
+ 64, /* GL_AUX1 */
+ 65, /* GL_AUX2 */
+ 66, /* GL_AUX3 */
+ 657, /* GL_INVALID_ENUM */
+ 661, /* GL_INVALID_VALUE */
+ 660, /* GL_INVALID_OPERATION */
+ 1473, /* GL_STACK_OVERFLOW */
+ 1474, /* GL_STACK_UNDERFLOW */
+ 1078, /* GL_OUT_OF_MEMORY */
+ 658, /* GL_INVALID_FRAMEBUFFER_OPERATION */
0, /* GL_2D */
2, /* GL_3D */
3, /* GL_3D_COLOR */
4, /* GL_3D_COLOR_TEXTURE */
6, /* GL_4D_COLOR_TEXTURE */
- 1040, /* GL_PASS_THROUGH_TOKEN */
- 1096, /* GL_POINT_TOKEN */
- 653, /* GL_LINE_TOKEN */
- 1110, /* GL_POLYGON_TOKEN */
- 73, /* GL_BITMAP_TOKEN */
- 404, /* GL_DRAW_PIXEL_TOKEN */
- 270, /* GL_COPY_PIXEL_TOKEN */
- 646, /* GL_LINE_RESET_TOKEN */
- 427, /* GL_EXP */
- 428, /* GL_EXP2 */
- 303, /* GL_CW */
- 115, /* GL_CCW */
- 136, /* GL_COEFF */
- 1017, /* GL_ORDER */
- 343, /* GL_DOMAIN */
- 278, /* GL_CURRENT_COLOR */
- 281, /* GL_CURRENT_INDEX */
- 287, /* GL_CURRENT_NORMAL */
- 299, /* GL_CURRENT_TEXTURE_COORDS */
- 292, /* GL_CURRENT_RASTER_COLOR */
- 294, /* GL_CURRENT_RASTER_INDEX */
- 297, /* GL_CURRENT_RASTER_TEXTURE_COORDS */
- 295, /* GL_CURRENT_RASTER_POSITION */
- 296, /* GL_CURRENT_RASTER_POSITION_VALID */
- 293, /* GL_CURRENT_RASTER_DISTANCE */
- 1089, /* GL_POINT_SMOOTH */
- 1078, /* GL_POINT_SIZE */
- 1088, /* GL_POINT_SIZE_RANGE */
- 1079, /* GL_POINT_SIZE_GRANULARITY */
- 647, /* GL_LINE_SMOOTH */
- 654, /* GL_LINE_WIDTH */
- 656, /* GL_LINE_WIDTH_RANGE */
- 655, /* GL_LINE_WIDTH_GRANULARITY */
- 649, /* GL_LINE_STIPPLE */
- 650, /* GL_LINE_STIPPLE_PATTERN */
- 651, /* GL_LINE_STIPPLE_REPEAT */
- 661, /* GL_LIST_MODE */
- 820, /* GL_MAX_LIST_NESTING */
- 658, /* GL_LIST_BASE */
- 660, /* GL_LIST_INDEX */
- 1099, /* GL_POLYGON_MODE */
- 1106, /* GL_POLYGON_SMOOTH */
- 1108, /* GL_POLYGON_STIPPLE */
- 413, /* GL_EDGE_FLAG */
- 271, /* GL_CULL_FACE */
- 272, /* GL_CULL_FACE_MODE */
- 507, /* GL_FRONT_FACE */
- 629, /* GL_LIGHTING */
- 634, /* GL_LIGHT_MODEL_LOCAL_VIEWER */
- 635, /* GL_LIGHT_MODEL_TWO_SIDE */
- 631, /* GL_LIGHT_MODEL_AMBIENT */
- 1337, /* GL_SHADE_MODEL */
- 167, /* GL_COLOR_MATERIAL_FACE */
- 168, /* GL_COLOR_MATERIAL_PARAMETER */
- 166, /* GL_COLOR_MATERIAL */
- 455, /* GL_FOG */
- 477, /* GL_FOG_INDEX */
- 473, /* GL_FOG_DENSITY */
- 481, /* GL_FOG_START */
- 475, /* GL_FOG_END */
- 478, /* GL_FOG_MODE */
- 457, /* GL_FOG_COLOR */
- 332, /* GL_DEPTH_RANGE */
- 337, /* GL_DEPTH_TEST */
- 340, /* GL_DEPTH_WRITEMASK */
- 320, /* GL_DEPTH_CLEAR_VALUE */
- 331, /* GL_DEPTH_FUNC */
+ 1098, /* GL_PASS_THROUGH_TOKEN */
+ 1158, /* GL_POINT_TOKEN */
+ 702, /* GL_LINE_TOKEN */
+ 1172, /* GL_POLYGON_TOKEN */
+ 74, /* GL_BITMAP_TOKEN */
+ 444, /* GL_DRAW_PIXEL_TOKEN */
+ 301, /* GL_COPY_PIXEL_TOKEN */
+ 695, /* GL_LINE_RESET_TOKEN */
+ 469, /* GL_EXP */
+ 470, /* GL_EXP2 */
+ 337, /* GL_CW */
+ 125, /* GL_CCW */
+ 146, /* GL_COEFF */
+ 1075, /* GL_ORDER */
+ 382, /* GL_DOMAIN */
+ 311, /* GL_CURRENT_COLOR */
+ 314, /* GL_CURRENT_INDEX */
+ 320, /* GL_CURRENT_NORMAL */
+ 333, /* GL_CURRENT_TEXTURE_COORDS */
+ 325, /* GL_CURRENT_RASTER_COLOR */
+ 327, /* GL_CURRENT_RASTER_INDEX */
+ 331, /* GL_CURRENT_RASTER_TEXTURE_COORDS */
+ 328, /* GL_CURRENT_RASTER_POSITION */
+ 329, /* GL_CURRENT_RASTER_POSITION_VALID */
+ 326, /* GL_CURRENT_RASTER_DISTANCE */
+ 1151, /* GL_POINT_SMOOTH */
+ 1140, /* GL_POINT_SIZE */
+ 1150, /* GL_POINT_SIZE_RANGE */
+ 1141, /* GL_POINT_SIZE_GRANULARITY */
+ 696, /* GL_LINE_SMOOTH */
+ 703, /* GL_LINE_WIDTH */
+ 705, /* GL_LINE_WIDTH_RANGE */
+ 704, /* GL_LINE_WIDTH_GRANULARITY */
+ 698, /* GL_LINE_STIPPLE */
+ 699, /* GL_LINE_STIPPLE_PATTERN */
+ 700, /* GL_LINE_STIPPLE_REPEAT */
+ 710, /* GL_LIST_MODE */
+ 875, /* GL_MAX_LIST_NESTING */
+ 707, /* GL_LIST_BASE */
+ 709, /* GL_LIST_INDEX */
+ 1161, /* GL_POLYGON_MODE */
+ 1168, /* GL_POLYGON_SMOOTH */
+ 1170, /* GL_POLYGON_STIPPLE */
+ 455, /* GL_EDGE_FLAG */
+ 304, /* GL_CULL_FACE */
+ 305, /* GL_CULL_FACE_MODE */
+ 577, /* GL_FRONT_FACE */
+ 678, /* GL_LIGHTING */
+ 683, /* GL_LIGHT_MODEL_LOCAL_VIEWER */
+ 684, /* GL_LIGHT_MODEL_TWO_SIDE */
+ 680, /* GL_LIGHT_MODEL_AMBIENT */
+ 1415, /* GL_SHADE_MODEL */
+ 193, /* GL_COLOR_MATERIAL_FACE */
+ 194, /* GL_COLOR_MATERIAL_PARAMETER */
+ 192, /* GL_COLOR_MATERIAL */
+ 504, /* GL_FOG */
+ 526, /* GL_FOG_INDEX */
+ 522, /* GL_FOG_DENSITY */
+ 530, /* GL_FOG_START */
+ 524, /* GL_FOG_END */
+ 527, /* GL_FOG_MODE */
+ 506, /* GL_FOG_COLOR */
+ 369, /* GL_DEPTH_RANGE */
+ 376, /* GL_DEPTH_TEST */
+ 379, /* GL_DEPTH_WRITEMASK */
+ 357, /* GL_DEPTH_CLEAR_VALUE */
+ 368, /* GL_DEPTH_FUNC */
12, /* GL_ACCUM_CLEAR_VALUE */
- 1420, /* GL_STENCIL_TEST */
- 1408, /* GL_STENCIL_CLEAR_VALUE */
- 1410, /* GL_STENCIL_FUNC */
- 1422, /* GL_STENCIL_VALUE_MASK */
- 1409, /* GL_STENCIL_FAIL */
- 1417, /* GL_STENCIL_PASS_DEPTH_FAIL */
- 1418, /* GL_STENCIL_PASS_DEPTH_PASS */
- 1419, /* GL_STENCIL_REF */
- 1423, /* GL_STENCIL_WRITEMASK */
- 789, /* GL_MATRIX_MODE */
- 956, /* GL_NORMALIZE */
- 1729, /* GL_VIEWPORT */
- 930, /* GL_MODELVIEW_STACK_DEPTH */
- 1189, /* GL_PROJECTION_STACK_DEPTH */
- 1618, /* GL_TEXTURE_STACK_DEPTH */
- 928, /* GL_MODELVIEW_MATRIX */
- 1188, /* GL_PROJECTION_MATRIX */
- 1603, /* GL_TEXTURE_MATRIX */
- 60, /* GL_ATTRIB_STACK_DEPTH */
- 126, /* GL_CLIENT_ATTRIB_STACK_DEPTH */
+ 1509, /* GL_STENCIL_TEST */
+ 1497, /* GL_STENCIL_CLEAR_VALUE */
+ 1499, /* GL_STENCIL_FUNC */
+ 1511, /* GL_STENCIL_VALUE_MASK */
+ 1498, /* GL_STENCIL_FAIL */
+ 1506, /* GL_STENCIL_PASS_DEPTH_FAIL */
+ 1507, /* GL_STENCIL_PASS_DEPTH_PASS */
+ 1508, /* GL_STENCIL_REF */
+ 1512, /* GL_STENCIL_WRITEMASK */
+ 844, /* GL_MATRIX_MODE */
+ 1013, /* GL_NORMALIZE */
+ 1838, /* GL_VIEWPORT */
+ 987, /* GL_MODELVIEW_STACK_DEPTH */
+ 1251, /* GL_PROJECTION_STACK_DEPTH */
+ 1719, /* GL_TEXTURE_STACK_DEPTH */
+ 985, /* GL_MODELVIEW_MATRIX */
+ 1250, /* GL_PROJECTION_MATRIX */
+ 1702, /* GL_TEXTURE_MATRIX */
+ 61, /* GL_ATTRIB_STACK_DEPTH */
+ 136, /* GL_CLIENT_ATTRIB_STACK_DEPTH */
43, /* GL_ALPHA_TEST */
44, /* GL_ALPHA_TEST_FUNC */
45, /* GL_ALPHA_TEST_REF */
- 342, /* GL_DITHER */
- 77, /* GL_BLEND_DST */
- 85, /* GL_BLEND_SRC */
- 74, /* GL_BLEND */
- 664, /* GL_LOGIC_OP_MODE */
- 584, /* GL_INDEX_LOGIC_OP */
- 165, /* GL_COLOR_LOGIC_OP */
- 66, /* GL_AUX_BUFFERS */
- 353, /* GL_DRAW_BUFFER */
- 1221, /* GL_READ_BUFFER */
- 1318, /* GL_SCISSOR_BOX */
- 1319, /* GL_SCISSOR_TEST */
- 583, /* GL_INDEX_CLEAR_VALUE */
- 588, /* GL_INDEX_WRITEMASK */
- 162, /* GL_COLOR_CLEAR_VALUE */
- 204, /* GL_COLOR_WRITEMASK */
- 585, /* GL_INDEX_MODE */
- 1285, /* GL_RGBA_MODE */
- 352, /* GL_DOUBLEBUFFER */
- 1424, /* GL_STEREO */
- 1244, /* GL_RENDER_MODE */
- 1041, /* GL_PERSPECTIVE_CORRECTION_HINT */
- 1090, /* GL_POINT_SMOOTH_HINT */
- 648, /* GL_LINE_SMOOTH_HINT */
- 1107, /* GL_POLYGON_SMOOTH_HINT */
- 476, /* GL_FOG_HINT */
- 1584, /* GL_TEXTURE_GEN_S */
- 1585, /* GL_TEXTURE_GEN_T */
- 1583, /* GL_TEXTURE_GEN_R */
- 1582, /* GL_TEXTURE_GEN_Q */
- 1054, /* GL_PIXEL_MAP_I_TO_I */
- 1060, /* GL_PIXEL_MAP_S_TO_S */
- 1056, /* GL_PIXEL_MAP_I_TO_R */
- 1052, /* GL_PIXEL_MAP_I_TO_G */
- 1050, /* GL_PIXEL_MAP_I_TO_B */
- 1048, /* GL_PIXEL_MAP_I_TO_A */
- 1058, /* GL_PIXEL_MAP_R_TO_R */
- 1046, /* GL_PIXEL_MAP_G_TO_G */
- 1044, /* GL_PIXEL_MAP_B_TO_B */
- 1042, /* GL_PIXEL_MAP_A_TO_A */
- 1055, /* GL_PIXEL_MAP_I_TO_I_SIZE */
- 1061, /* GL_PIXEL_MAP_S_TO_S_SIZE */
- 1057, /* GL_PIXEL_MAP_I_TO_R_SIZE */
- 1053, /* GL_PIXEL_MAP_I_TO_G_SIZE */
- 1051, /* GL_PIXEL_MAP_I_TO_B_SIZE */
- 1049, /* GL_PIXEL_MAP_I_TO_A_SIZE */
- 1059, /* GL_PIXEL_MAP_R_TO_R_SIZE */
- 1047, /* GL_PIXEL_MAP_G_TO_G_SIZE */
- 1045, /* GL_PIXEL_MAP_B_TO_B_SIZE */
- 1043, /* GL_PIXEL_MAP_A_TO_A_SIZE */
- 1651, /* GL_UNPACK_SWAP_BYTES */
- 1646, /* GL_UNPACK_LSB_FIRST */
- 1647, /* GL_UNPACK_ROW_LENGTH */
- 1650, /* GL_UNPACK_SKIP_ROWS */
- 1649, /* GL_UNPACK_SKIP_PIXELS */
- 1644, /* GL_UNPACK_ALIGNMENT */
- 1029, /* GL_PACK_SWAP_BYTES */
- 1024, /* GL_PACK_LSB_FIRST */
- 1025, /* GL_PACK_ROW_LENGTH */
- 1028, /* GL_PACK_SKIP_ROWS */
- 1027, /* GL_PACK_SKIP_PIXELS */
- 1021, /* GL_PACK_ALIGNMENT */
- 742, /* GL_MAP_COLOR */
- 743, /* GL_MAP_STENCIL */
- 587, /* GL_INDEX_SHIFT */
- 586, /* GL_INDEX_OFFSET */
- 1233, /* GL_RED_SCALE */
- 1231, /* GL_RED_BIAS */
- 1746, /* GL_ZOOM_X */
- 1747, /* GL_ZOOM_Y */
- 549, /* GL_GREEN_SCALE */
- 547, /* GL_GREEN_BIAS */
- 91, /* GL_BLUE_SCALE */
- 89, /* GL_BLUE_BIAS */
+ 381, /* GL_DITHER */
+ 78, /* GL_BLEND_DST */
+ 87, /* GL_BLEND_SRC */
+ 75, /* GL_BLEND */
+ 713, /* GL_LOGIC_OP_MODE */
+ 631, /* GL_INDEX_LOGIC_OP */
+ 191, /* GL_COLOR_LOGIC_OP */
+ 67, /* GL_AUX_BUFFERS */
+ 392, /* GL_DRAW_BUFFER */
+ 1285, /* GL_READ_BUFFER */
+ 1396, /* GL_SCISSOR_BOX */
+ 1397, /* GL_SCISSOR_TEST */
+ 630, /* GL_INDEX_CLEAR_VALUE */
+ 635, /* GL_INDEX_WRITEMASK */
+ 188, /* GL_COLOR_CLEAR_VALUE */
+ 230, /* GL_COLOR_WRITEMASK */
+ 632, /* GL_INDEX_MODE */
+ 1362, /* GL_RGBA_MODE */
+ 391, /* GL_DOUBLEBUFFER */
+ 1513, /* GL_STEREO */
+ 1320, /* GL_RENDER_MODE */
+ 1099, /* GL_PERSPECTIVE_CORRECTION_HINT */
+ 1152, /* GL_POINT_SMOOTH_HINT */
+ 697, /* GL_LINE_SMOOTH_HINT */
+ 1169, /* GL_POLYGON_SMOOTH_HINT */
+ 525, /* GL_FOG_HINT */
+ 1683, /* GL_TEXTURE_GEN_S */
+ 1684, /* GL_TEXTURE_GEN_T */
+ 1682, /* GL_TEXTURE_GEN_R */
+ 1681, /* GL_TEXTURE_GEN_Q */
+ 1112, /* GL_PIXEL_MAP_I_TO_I */
+ 1118, /* GL_PIXEL_MAP_S_TO_S */
+ 1114, /* GL_PIXEL_MAP_I_TO_R */
+ 1110, /* GL_PIXEL_MAP_I_TO_G */
+ 1108, /* GL_PIXEL_MAP_I_TO_B */
+ 1106, /* GL_PIXEL_MAP_I_TO_A */
+ 1116, /* GL_PIXEL_MAP_R_TO_R */
+ 1104, /* GL_PIXEL_MAP_G_TO_G */
+ 1102, /* GL_PIXEL_MAP_B_TO_B */
+ 1100, /* GL_PIXEL_MAP_A_TO_A */
+ 1113, /* GL_PIXEL_MAP_I_TO_I_SIZE */
+ 1119, /* GL_PIXEL_MAP_S_TO_S_SIZE */
+ 1115, /* GL_PIXEL_MAP_I_TO_R_SIZE */
+ 1111, /* GL_PIXEL_MAP_I_TO_G_SIZE */
+ 1109, /* GL_PIXEL_MAP_I_TO_B_SIZE */
+ 1107, /* GL_PIXEL_MAP_I_TO_A_SIZE */
+ 1117, /* GL_PIXEL_MAP_R_TO_R_SIZE */
+ 1105, /* GL_PIXEL_MAP_G_TO_G_SIZE */
+ 1103, /* GL_PIXEL_MAP_B_TO_B_SIZE */
+ 1101, /* GL_PIXEL_MAP_A_TO_A_SIZE */
+ 1756, /* GL_UNPACK_SWAP_BYTES */
+ 1751, /* GL_UNPACK_LSB_FIRST */
+ 1752, /* GL_UNPACK_ROW_LENGTH */
+ 1755, /* GL_UNPACK_SKIP_ROWS */
+ 1754, /* GL_UNPACK_SKIP_PIXELS */
+ 1749, /* GL_UNPACK_ALIGNMENT */
+ 1087, /* GL_PACK_SWAP_BYTES */
+ 1082, /* GL_PACK_LSB_FIRST */
+ 1083, /* GL_PACK_ROW_LENGTH */
+ 1086, /* GL_PACK_SKIP_ROWS */
+ 1085, /* GL_PACK_SKIP_PIXELS */
+ 1079, /* GL_PACK_ALIGNMENT */
+ 791, /* GL_MAP_COLOR */
+ 796, /* GL_MAP_STENCIL */
+ 634, /* GL_INDEX_SHIFT */
+ 633, /* GL_INDEX_OFFSET */
+ 1298, /* GL_RED_SCALE */
+ 1296, /* GL_RED_BIAS */
+ 1856, /* GL_ZOOM_X */
+ 1857, /* GL_ZOOM_Y */
+ 595, /* GL_GREEN_SCALE */
+ 593, /* GL_GREEN_BIAS */
+ 93, /* GL_BLUE_SCALE */
+ 91, /* GL_BLUE_BIAS */
42, /* GL_ALPHA_SCALE */
40, /* GL_ALPHA_BIAS */
- 333, /* GL_DEPTH_SCALE */
- 314, /* GL_DEPTH_BIAS */
- 815, /* GL_MAX_EVAL_ORDER */
- 819, /* GL_MAX_LIGHTS */
- 798, /* GL_MAX_CLIP_PLANES */
- 863, /* GL_MAX_TEXTURE_SIZE */
- 825, /* GL_MAX_PIXEL_MAP_TABLE */
- 794, /* GL_MAX_ATTRIB_STACK_DEPTH */
- 822, /* GL_MAX_MODELVIEW_STACK_DEPTH */
- 823, /* GL_MAX_NAME_STACK_DEPTH */
- 851, /* GL_MAX_PROJECTION_STACK_DEPTH */
- 864, /* GL_MAX_TEXTURE_STACK_DEPTH */
- 878, /* GL_MAX_VIEWPORT_DIMS */
- 795, /* GL_MAX_CLIENT_ATTRIB_STACK_DEPTH */
- 1431, /* GL_SUBPIXEL_BITS */
- 582, /* GL_INDEX_BITS */
- 1232, /* GL_RED_BITS */
- 548, /* GL_GREEN_BITS */
- 90, /* GL_BLUE_BITS */
+ 370, /* GL_DEPTH_SCALE */
+ 350, /* GL_DEPTH_BIAS */
+ 870, /* GL_MAX_EVAL_ORDER */
+ 874, /* GL_MAX_LIGHTS */
+ 853, /* GL_MAX_CLIP_PLANES */
+ 920, /* GL_MAX_TEXTURE_SIZE */
+ 880, /* GL_MAX_PIXEL_MAP_TABLE */
+ 849, /* GL_MAX_ATTRIB_STACK_DEPTH */
+ 877, /* GL_MAX_MODELVIEW_STACK_DEPTH */
+ 878, /* GL_MAX_NAME_STACK_DEPTH */
+ 906, /* GL_MAX_PROJECTION_STACK_DEPTH */
+ 921, /* GL_MAX_TEXTURE_STACK_DEPTH */
+ 935, /* GL_MAX_VIEWPORT_DIMS */
+ 850, /* GL_MAX_CLIENT_ATTRIB_STACK_DEPTH */
+ 1523, /* GL_SUBPIXEL_BITS */
+ 629, /* GL_INDEX_BITS */
+ 1297, /* GL_RED_BITS */
+ 594, /* GL_GREEN_BITS */
+ 92, /* GL_BLUE_BITS */
41, /* GL_ALPHA_BITS */
- 315, /* GL_DEPTH_BITS */
- 1406, /* GL_STENCIL_BITS */
+ 351, /* GL_DEPTH_BITS */
+ 1495, /* GL_STENCIL_BITS */
14, /* GL_ACCUM_RED_BITS */
13, /* GL_ACCUM_GREEN_BITS */
10, /* GL_ACCUM_BLUE_BITS */
9, /* GL_ACCUM_ALPHA_BITS */
- 944, /* GL_NAME_STACK_DEPTH */
- 61, /* GL_AUTO_NORMAL */
- 688, /* GL_MAP1_COLOR_4 */
- 691, /* GL_MAP1_INDEX */
- 692, /* GL_MAP1_NORMAL */
- 693, /* GL_MAP1_TEXTURE_COORD_1 */
- 694, /* GL_MAP1_TEXTURE_COORD_2 */
- 695, /* GL_MAP1_TEXTURE_COORD_3 */
- 696, /* GL_MAP1_TEXTURE_COORD_4 */
- 697, /* GL_MAP1_VERTEX_3 */
- 698, /* GL_MAP1_VERTEX_4 */
- 715, /* GL_MAP2_COLOR_4 */
- 718, /* GL_MAP2_INDEX */
- 719, /* GL_MAP2_NORMAL */
- 720, /* GL_MAP2_TEXTURE_COORD_1 */
- 721, /* GL_MAP2_TEXTURE_COORD_2 */
- 722, /* GL_MAP2_TEXTURE_COORD_3 */
- 723, /* GL_MAP2_TEXTURE_COORD_4 */
- 724, /* GL_MAP2_VERTEX_3 */
- 725, /* GL_MAP2_VERTEX_4 */
- 689, /* GL_MAP1_GRID_DOMAIN */
- 690, /* GL_MAP1_GRID_SEGMENTS */
- 716, /* GL_MAP2_GRID_DOMAIN */
- 717, /* GL_MAP2_GRID_SEGMENTS */
- 1508, /* GL_TEXTURE_1D */
- 1510, /* GL_TEXTURE_2D */
- 437, /* GL_FEEDBACK_BUFFER_POINTER */
- 438, /* GL_FEEDBACK_BUFFER_SIZE */
- 439, /* GL_FEEDBACK_BUFFER_TYPE */
- 1328, /* GL_SELECTION_BUFFER_POINTER */
- 1329, /* GL_SELECTION_BUFFER_SIZE */
- 1621, /* GL_TEXTURE_WIDTH */
- 1589, /* GL_TEXTURE_HEIGHT */
- 1545, /* GL_TEXTURE_COMPONENTS */
- 1529, /* GL_TEXTURE_BORDER_COLOR */
- 1528, /* GL_TEXTURE_BORDER */
- 344, /* GL_DONT_CARE */
- 435, /* GL_FASTEST */
- 952, /* GL_NICEST */
- 47, /* GL_AMBIENT */
- 341, /* GL_DIFFUSE */
- 1371, /* GL_SPECULAR */
- 1111, /* GL_POSITION */
- 1374, /* GL_SPOT_DIRECTION */
- 1375, /* GL_SPOT_EXPONENT */
- 1373, /* GL_SPOT_CUTOFF */
- 244, /* GL_CONSTANT_ATTENUATION */
- 638, /* GL_LINEAR_ATTENUATION */
- 1208, /* GL_QUADRATIC_ATTENUATION */
- 218, /* GL_COMPILE */
- 219, /* GL_COMPILE_AND_EXECUTE */
- 110, /* GL_BYTE */
- 1652, /* GL_UNSIGNED_BYTE */
- 1342, /* GL_SHORT */
- 1661, /* GL_UNSIGNED_SHORT */
- 590, /* GL_INT */
- 1655, /* GL_UNSIGNED_INT */
- 442, /* GL_FLOAT */
+ 1001, /* GL_NAME_STACK_DEPTH */
+ 62, /* GL_AUTO_NORMAL */
+ 737, /* GL_MAP1_COLOR_4 */
+ 740, /* GL_MAP1_INDEX */
+ 741, /* GL_MAP1_NORMAL */
+ 742, /* GL_MAP1_TEXTURE_COORD_1 */
+ 743, /* GL_MAP1_TEXTURE_COORD_2 */
+ 744, /* GL_MAP1_TEXTURE_COORD_3 */
+ 745, /* GL_MAP1_TEXTURE_COORD_4 */
+ 746, /* GL_MAP1_VERTEX_3 */
+ 747, /* GL_MAP1_VERTEX_4 */
+ 764, /* GL_MAP2_COLOR_4 */
+ 767, /* GL_MAP2_INDEX */
+ 768, /* GL_MAP2_NORMAL */
+ 769, /* GL_MAP2_TEXTURE_COORD_1 */
+ 770, /* GL_MAP2_TEXTURE_COORD_2 */
+ 771, /* GL_MAP2_TEXTURE_COORD_3 */
+ 772, /* GL_MAP2_TEXTURE_COORD_4 */
+ 773, /* GL_MAP2_VERTEX_3 */
+ 774, /* GL_MAP2_VERTEX_4 */
+ 738, /* GL_MAP1_GRID_DOMAIN */
+ 739, /* GL_MAP1_GRID_SEGMENTS */
+ 765, /* GL_MAP2_GRID_DOMAIN */
+ 766, /* GL_MAP2_GRID_SEGMENTS */
+ 1606, /* GL_TEXTURE_1D */
+ 1608, /* GL_TEXTURE_2D */
+ 479, /* GL_FEEDBACK_BUFFER_POINTER */
+ 480, /* GL_FEEDBACK_BUFFER_SIZE */
+ 481, /* GL_FEEDBACK_BUFFER_TYPE */
+ 1406, /* GL_SELECTION_BUFFER_POINTER */
+ 1407, /* GL_SELECTION_BUFFER_SIZE */
+ 1724, /* GL_TEXTURE_WIDTH */
+ 1688, /* GL_TEXTURE_HEIGHT */
+ 1643, /* GL_TEXTURE_COMPONENTS */
+ 1627, /* GL_TEXTURE_BORDER_COLOR */
+ 1626, /* GL_TEXTURE_BORDER */
+ 383, /* GL_DONT_CARE */
+ 477, /* GL_FASTEST */
+ 1009, /* GL_NICEST */
+ 48, /* GL_AMBIENT */
+ 380, /* GL_DIFFUSE */
+ 1455, /* GL_SPECULAR */
+ 1173, /* GL_POSITION */
+ 1458, /* GL_SPOT_DIRECTION */
+ 1459, /* GL_SPOT_EXPONENT */
+ 1457, /* GL_SPOT_CUTOFF */
+ 275, /* GL_CONSTANT_ATTENUATION */
+ 687, /* GL_LINEAR_ATTENUATION */
+ 1271, /* GL_QUADRATIC_ATTENUATION */
+ 244, /* GL_COMPILE */
+ 245, /* GL_COMPILE_AND_EXECUTE */
+ 120, /* GL_BYTE */
+ 1758, /* GL_UNSIGNED_BYTE */
+ 1420, /* GL_SHORT */
+ 1769, /* GL_UNSIGNED_SHORT */
+ 637, /* GL_INT */
+ 1761, /* GL_UNSIGNED_INT */
+ 485, /* GL_FLOAT */
1, /* GL_2_BYTES */
5, /* GL_3_BYTES */
7, /* GL_4_BYTES */
- 351, /* GL_DOUBLE */
- 122, /* GL_CLEAR */
- 49, /* GL_AND */
- 51, /* GL_AND_REVERSE */
- 268, /* GL_COPY */
- 50, /* GL_AND_INVERTED */
- 954, /* GL_NOOP */
- 1742, /* GL_XOR */
- 1016, /* GL_OR */
- 955, /* GL_NOR */
- 425, /* GL_EQUIV */
- 616, /* GL_INVERT */
- 1019, /* GL_OR_REVERSE */
- 269, /* GL_COPY_INVERTED */
- 1018, /* GL_OR_INVERTED */
- 945, /* GL_NAND */
- 1333, /* GL_SET */
- 422, /* GL_EMISSION */
- 1341, /* GL_SHININESS */
- 48, /* GL_AMBIENT_AND_DIFFUSE */
- 164, /* GL_COLOR_INDEXES */
- 895, /* GL_MODELVIEW */
- 1187, /* GL_PROJECTION */
- 1443, /* GL_TEXTURE */
- 137, /* GL_COLOR */
- 312, /* GL_DEPTH */
- 1393, /* GL_STENCIL */
- 163, /* GL_COLOR_INDEX */
- 1411, /* GL_STENCIL_INDEX */
- 321, /* GL_DEPTH_COMPONENT */
- 1228, /* GL_RED */
- 546, /* GL_GREEN */
- 88, /* GL_BLUE */
+ 390, /* GL_DOUBLE */
+ 132, /* GL_CLEAR */
+ 50, /* GL_AND */
+ 52, /* GL_AND_REVERSE */
+ 299, /* GL_COPY */
+ 51, /* GL_AND_INVERTED */
+ 1011, /* GL_NOOP */
+ 1852, /* GL_XOR */
+ 1074, /* GL_OR */
+ 1012, /* GL_NOR */
+ 467, /* GL_EQUIV */
+ 664, /* GL_INVERT */
+ 1077, /* GL_OR_REVERSE */
+ 300, /* GL_COPY_INVERTED */
+ 1076, /* GL_OR_INVERTED */
+ 1002, /* GL_NAND */
+ 1411, /* GL_SET */
+ 464, /* GL_EMISSION */
+ 1419, /* GL_SHININESS */
+ 49, /* GL_AMBIENT_AND_DIFFUSE */
+ 190, /* GL_COLOR_INDEXES */
+ 952, /* GL_MODELVIEW */
+ 1249, /* GL_PROJECTION */
+ 1541, /* GL_TEXTURE */
+ 147, /* GL_COLOR */
+ 346, /* GL_DEPTH */
+ 1481, /* GL_STENCIL */
+ 189, /* GL_COLOR_INDEX */
+ 1500, /* GL_STENCIL_INDEX */
+ 358, /* GL_DEPTH_COMPONENT */
+ 1293, /* GL_RED */
+ 592, /* GL_GREEN */
+ 90, /* GL_BLUE */
31, /* GL_ALPHA */
- 1252, /* GL_RGB */
- 1271, /* GL_RGBA */
- 666, /* GL_LUMINANCE */
- 687, /* GL_LUMINANCE_ALPHA */
- 72, /* GL_BITMAP */
- 1067, /* GL_POINT */
- 636, /* GL_LINE */
- 440, /* GL_FILL */
- 1237, /* GL_RENDER */
- 436, /* GL_FEEDBACK */
- 1327, /* GL_SELECT */
- 441, /* GL_FLAT */
- 1346, /* GL_SMOOTH */
- 617, /* GL_KEEP */
- 1246, /* GL_REPLACE */
- 573, /* GL_INCR */
- 308, /* GL_DECR */
- 1676, /* GL_VENDOR */
- 1243, /* GL_RENDERER */
- 1677, /* GL_VERSION */
- 429, /* GL_EXTENSIONS */
- 1292, /* GL_S */
- 1434, /* GL_T */
- 1218, /* GL_R */
- 1207, /* GL_Q */
- 931, /* GL_MODULATE */
- 307, /* GL_DECAL */
- 1579, /* GL_TEXTURE_ENV_MODE */
- 1578, /* GL_TEXTURE_ENV_COLOR */
- 1577, /* GL_TEXTURE_ENV */
- 430, /* GL_EYE_LINEAR */
- 978, /* GL_OBJECT_LINEAR */
- 1372, /* GL_SPHERE_MAP */
- 1581, /* GL_TEXTURE_GEN_MODE */
- 980, /* GL_OBJECT_PLANE */
- 431, /* GL_EYE_PLANE */
- 946, /* GL_NEAREST */
- 637, /* GL_LINEAR */
- 950, /* GL_NEAREST_MIPMAP_NEAREST */
- 642, /* GL_LINEAR_MIPMAP_NEAREST */
- 949, /* GL_NEAREST_MIPMAP_LINEAR */
- 641, /* GL_LINEAR_MIPMAP_LINEAR */
- 1602, /* GL_TEXTURE_MAG_FILTER */
- 1610, /* GL_TEXTURE_MIN_FILTER */
- 1623, /* GL_TEXTURE_WRAP_S */
- 1624, /* GL_TEXTURE_WRAP_T */
- 116, /* GL_CLAMP */
- 1245, /* GL_REPEAT */
- 1105, /* GL_POLYGON_OFFSET_UNITS */
- 1104, /* GL_POLYGON_OFFSET_POINT */
- 1103, /* GL_POLYGON_OFFSET_LINE */
- 1219, /* GL_R3_G3_B2 */
- 1673, /* GL_V2F */
- 1674, /* GL_V3F */
- 113, /* GL_C4UB_V2F */
- 114, /* GL_C4UB_V3F */
- 111, /* GL_C3F_V3F */
- 943, /* GL_N3F_V3F */
- 112, /* GL_C4F_N3F_V3F */
- 1439, /* GL_T2F_V3F */
- 1441, /* GL_T4F_V4F */
- 1437, /* GL_T2F_C4UB_V3F */
- 1435, /* GL_T2F_C3F_V3F */
- 1438, /* GL_T2F_N3F_V3F */
- 1436, /* GL_T2F_C4F_N3F_V3F */
- 1440, /* GL_T4F_C4F_N3F_V4F */
- 129, /* GL_CLIP_PLANE0 */
- 130, /* GL_CLIP_PLANE1 */
- 131, /* GL_CLIP_PLANE2 */
- 132, /* GL_CLIP_PLANE3 */
- 133, /* GL_CLIP_PLANE4 */
- 134, /* GL_CLIP_PLANE5 */
- 621, /* GL_LIGHT0 */
- 622, /* GL_LIGHT1 */
- 623, /* GL_LIGHT2 */
- 624, /* GL_LIGHT3 */
- 625, /* GL_LIGHT4 */
- 626, /* GL_LIGHT5 */
- 627, /* GL_LIGHT6 */
- 628, /* GL_LIGHT7 */
- 550, /* GL_HINT_BIT */
- 246, /* GL_CONSTANT_COLOR */
- 990, /* GL_ONE_MINUS_CONSTANT_COLOR */
- 241, /* GL_CONSTANT_ALPHA */
- 988, /* GL_ONE_MINUS_CONSTANT_ALPHA */
- 75, /* GL_BLEND_COLOR */
- 510, /* GL_FUNC_ADD */
- 879, /* GL_MIN */
- 791, /* GL_MAX */
- 80, /* GL_BLEND_EQUATION */
- 514, /* GL_FUNC_SUBTRACT */
- 512, /* GL_FUNC_REVERSE_SUBTRACT */
- 249, /* GL_CONVOLUTION_1D */
- 250, /* GL_CONVOLUTION_2D */
- 1330, /* GL_SEPARABLE_2D */
- 253, /* GL_CONVOLUTION_BORDER_MODE */
- 257, /* GL_CONVOLUTION_FILTER_SCALE */
- 255, /* GL_CONVOLUTION_FILTER_BIAS */
- 1229, /* GL_REDUCE */
- 259, /* GL_CONVOLUTION_FORMAT */
- 263, /* GL_CONVOLUTION_WIDTH */
- 261, /* GL_CONVOLUTION_HEIGHT */
- 806, /* GL_MAX_CONVOLUTION_WIDTH */
- 804, /* GL_MAX_CONVOLUTION_HEIGHT */
- 1144, /* GL_POST_CONVOLUTION_RED_SCALE */
- 1140, /* GL_POST_CONVOLUTION_GREEN_SCALE */
- 1135, /* GL_POST_CONVOLUTION_BLUE_SCALE */
- 1131, /* GL_POST_CONVOLUTION_ALPHA_SCALE */
- 1142, /* GL_POST_CONVOLUTION_RED_BIAS */
- 1138, /* GL_POST_CONVOLUTION_GREEN_BIAS */
- 1133, /* GL_POST_CONVOLUTION_BLUE_BIAS */
- 1129, /* GL_POST_CONVOLUTION_ALPHA_BIAS */
- 551, /* GL_HISTOGRAM */
- 1191, /* GL_PROXY_HISTOGRAM */
- 567, /* GL_HISTOGRAM_WIDTH */
- 557, /* GL_HISTOGRAM_FORMAT */
- 563, /* GL_HISTOGRAM_RED_SIZE */
- 559, /* GL_HISTOGRAM_GREEN_SIZE */
- 554, /* GL_HISTOGRAM_BLUE_SIZE */
- 552, /* GL_HISTOGRAM_ALPHA_SIZE */
- 561, /* GL_HISTOGRAM_LUMINANCE_SIZE */
- 565, /* GL_HISTOGRAM_SINK */
- 880, /* GL_MINMAX */
- 882, /* GL_MINMAX_FORMAT */
- 884, /* GL_MINMAX_SINK */
- 1442, /* GL_TABLE_TOO_LARGE_EXT */
- 1654, /* GL_UNSIGNED_BYTE_3_3_2 */
- 1663, /* GL_UNSIGNED_SHORT_4_4_4_4 */
- 1665, /* GL_UNSIGNED_SHORT_5_5_5_1 */
- 1659, /* GL_UNSIGNED_INT_8_8_8_8 */
- 1656, /* GL_UNSIGNED_INT_10_10_10_2 */
- 1102, /* GL_POLYGON_OFFSET_FILL */
- 1101, /* GL_POLYGON_OFFSET_FACTOR */
- 1100, /* GL_POLYGON_OFFSET_BIAS */
- 1249, /* GL_RESCALE_NORMAL */
+ 1328, /* GL_RGB */
+ 1347, /* GL_RGBA */
+ 715, /* GL_LUMINANCE */
+ 736, /* GL_LUMINANCE_ALPHA */
+ 73, /* GL_BITMAP */
+ 1129, /* GL_POINT */
+ 685, /* GL_LINE */
+ 482, /* GL_FILL */
+ 1302, /* GL_RENDER */
+ 478, /* GL_FEEDBACK */
+ 1405, /* GL_SELECT */
+ 484, /* GL_FLAT */
+ 1430, /* GL_SMOOTH */
+ 665, /* GL_KEEP */
+ 1322, /* GL_REPLACE */
+ 619, /* GL_INCR */
+ 342, /* GL_DECR */
+ 1784, /* GL_VENDOR */
+ 1319, /* GL_RENDERER */
+ 1785, /* GL_VERSION */
+ 471, /* GL_EXTENSIONS */
+ 1370, /* GL_S */
+ 1532, /* GL_T */
+ 1282, /* GL_R */
+ 1270, /* GL_Q */
+ 988, /* GL_MODULATE */
+ 341, /* GL_DECAL */
+ 1678, /* GL_TEXTURE_ENV_MODE */
+ 1677, /* GL_TEXTURE_ENV_COLOR */
+ 1676, /* GL_TEXTURE_ENV */
+ 472, /* GL_EYE_LINEAR */
+ 1035, /* GL_OBJECT_LINEAR */
+ 1456, /* GL_SPHERE_MAP */
+ 1680, /* GL_TEXTURE_GEN_MODE */
+ 1037, /* GL_OBJECT_PLANE */
+ 473, /* GL_EYE_PLANE */
+ 1003, /* GL_NEAREST */
+ 686, /* GL_LINEAR */
+ 1007, /* GL_NEAREST_MIPMAP_NEAREST */
+ 691, /* GL_LINEAR_MIPMAP_NEAREST */
+ 1006, /* GL_NEAREST_MIPMAP_LINEAR */
+ 690, /* GL_LINEAR_MIPMAP_LINEAR */
+ 1701, /* GL_TEXTURE_MAG_FILTER */
+ 1709, /* GL_TEXTURE_MIN_FILTER */
+ 1726, /* GL_TEXTURE_WRAP_S */
+ 1727, /* GL_TEXTURE_WRAP_T */
+ 126, /* GL_CLAMP */
+ 1321, /* GL_REPEAT */
+ 1167, /* GL_POLYGON_OFFSET_UNITS */
+ 1166, /* GL_POLYGON_OFFSET_POINT */
+ 1165, /* GL_POLYGON_OFFSET_LINE */
+ 1283, /* GL_R3_G3_B2 */
+ 1781, /* GL_V2F */
+ 1782, /* GL_V3F */
+ 123, /* GL_C4UB_V2F */
+ 124, /* GL_C4UB_V3F */
+ 121, /* GL_C3F_V3F */
+ 1000, /* GL_N3F_V3F */
+ 122, /* GL_C4F_N3F_V3F */
+ 1537, /* GL_T2F_V3F */
+ 1539, /* GL_T4F_V4F */
+ 1535, /* GL_T2F_C4UB_V3F */
+ 1533, /* GL_T2F_C3F_V3F */
+ 1536, /* GL_T2F_N3F_V3F */
+ 1534, /* GL_T2F_C4F_N3F_V3F */
+ 1538, /* GL_T4F_C4F_N3F_V4F */
+ 139, /* GL_CLIP_PLANE0 */
+ 140, /* GL_CLIP_PLANE1 */
+ 141, /* GL_CLIP_PLANE2 */
+ 142, /* GL_CLIP_PLANE3 */
+ 143, /* GL_CLIP_PLANE4 */
+ 144, /* GL_CLIP_PLANE5 */
+ 670, /* GL_LIGHT0 */
+ 671, /* GL_LIGHT1 */
+ 672, /* GL_LIGHT2 */
+ 673, /* GL_LIGHT3 */
+ 674, /* GL_LIGHT4 */
+ 675, /* GL_LIGHT5 */
+ 676, /* GL_LIGHT6 */
+ 677, /* GL_LIGHT7 */
+ 596, /* GL_HINT_BIT */
+ 277, /* GL_CONSTANT_COLOR */
+ 1048, /* GL_ONE_MINUS_CONSTANT_COLOR */
+ 272, /* GL_CONSTANT_ALPHA */
+ 1046, /* GL_ONE_MINUS_CONSTANT_ALPHA */
+ 76, /* GL_BLEND_COLOR */
+ 580, /* GL_FUNC_ADD */
+ 936, /* GL_MIN */
+ 846, /* GL_MAX */
+ 81, /* GL_BLEND_EQUATION */
+ 584, /* GL_FUNC_SUBTRACT */
+ 582, /* GL_FUNC_REVERSE_SUBTRACT */
+ 280, /* GL_CONVOLUTION_1D */
+ 281, /* GL_CONVOLUTION_2D */
+ 1408, /* GL_SEPARABLE_2D */
+ 284, /* GL_CONVOLUTION_BORDER_MODE */
+ 288, /* GL_CONVOLUTION_FILTER_SCALE */
+ 286, /* GL_CONVOLUTION_FILTER_BIAS */
+ 1294, /* GL_REDUCE */
+ 290, /* GL_CONVOLUTION_FORMAT */
+ 294, /* GL_CONVOLUTION_WIDTH */
+ 292, /* GL_CONVOLUTION_HEIGHT */
+ 861, /* GL_MAX_CONVOLUTION_WIDTH */
+ 859, /* GL_MAX_CONVOLUTION_HEIGHT */
+ 1206, /* GL_POST_CONVOLUTION_RED_SCALE */
+ 1202, /* GL_POST_CONVOLUTION_GREEN_SCALE */
+ 1197, /* GL_POST_CONVOLUTION_BLUE_SCALE */
+ 1193, /* GL_POST_CONVOLUTION_ALPHA_SCALE */
+ 1204, /* GL_POST_CONVOLUTION_RED_BIAS */
+ 1200, /* GL_POST_CONVOLUTION_GREEN_BIAS */
+ 1195, /* GL_POST_CONVOLUTION_BLUE_BIAS */
+ 1191, /* GL_POST_CONVOLUTION_ALPHA_BIAS */
+ 597, /* GL_HISTOGRAM */
+ 1254, /* GL_PROXY_HISTOGRAM */
+ 613, /* GL_HISTOGRAM_WIDTH */
+ 603, /* GL_HISTOGRAM_FORMAT */
+ 609, /* GL_HISTOGRAM_RED_SIZE */
+ 605, /* GL_HISTOGRAM_GREEN_SIZE */
+ 600, /* GL_HISTOGRAM_BLUE_SIZE */
+ 598, /* GL_HISTOGRAM_ALPHA_SIZE */
+ 607, /* GL_HISTOGRAM_LUMINANCE_SIZE */
+ 611, /* GL_HISTOGRAM_SINK */
+ 937, /* GL_MINMAX */
+ 939, /* GL_MINMAX_FORMAT */
+ 941, /* GL_MINMAX_SINK */
+ 1540, /* GL_TABLE_TOO_LARGE_EXT */
+ 1760, /* GL_UNSIGNED_BYTE_3_3_2 */
+ 1771, /* GL_UNSIGNED_SHORT_4_4_4_4 */
+ 1773, /* GL_UNSIGNED_SHORT_5_5_5_1 */
+ 1766, /* GL_UNSIGNED_INT_8_8_8_8 */
+ 1762, /* GL_UNSIGNED_INT_10_10_10_2 */
+ 1164, /* GL_POLYGON_OFFSET_FILL */
+ 1163, /* GL_POLYGON_OFFSET_FACTOR */
+ 1162, /* GL_POLYGON_OFFSET_BIAS */
+ 1325, /* GL_RESCALE_NORMAL */
36, /* GL_ALPHA4 */
38, /* GL_ALPHA8 */
32, /* GL_ALPHA12 */
34, /* GL_ALPHA16 */
- 677, /* GL_LUMINANCE4 */
- 683, /* GL_LUMINANCE8 */
- 667, /* GL_LUMINANCE12 */
- 673, /* GL_LUMINANCE16 */
- 678, /* GL_LUMINANCE4_ALPHA4 */
- 681, /* GL_LUMINANCE6_ALPHA2 */
- 684, /* GL_LUMINANCE8_ALPHA8 */
- 670, /* GL_LUMINANCE12_ALPHA4 */
- 668, /* GL_LUMINANCE12_ALPHA12 */
- 674, /* GL_LUMINANCE16_ALPHA16 */
- 591, /* GL_INTENSITY */
- 596, /* GL_INTENSITY4 */
- 598, /* GL_INTENSITY8 */
- 592, /* GL_INTENSITY12 */
- 594, /* GL_INTENSITY16 */
- 1261, /* GL_RGB2_EXT */
- 1262, /* GL_RGB4 */
- 1265, /* GL_RGB5 */
- 1269, /* GL_RGB8 */
- 1253, /* GL_RGB10 */
- 1257, /* GL_RGB12 */
- 1259, /* GL_RGB16 */
- 1276, /* GL_RGBA2 */
- 1278, /* GL_RGBA4 */
- 1266, /* GL_RGB5_A1 */
- 1282, /* GL_RGBA8 */
- 1254, /* GL_RGB10_A2 */
- 1272, /* GL_RGBA12 */
- 1274, /* GL_RGBA16 */
- 1615, /* GL_TEXTURE_RED_SIZE */
- 1587, /* GL_TEXTURE_GREEN_SIZE */
- 1526, /* GL_TEXTURE_BLUE_SIZE */
- 1513, /* GL_TEXTURE_ALPHA_SIZE */
- 1600, /* GL_TEXTURE_LUMINANCE_SIZE */
- 1591, /* GL_TEXTURE_INTENSITY_SIZE */
- 1247, /* GL_REPLACE_EXT */
- 1195, /* GL_PROXY_TEXTURE_1D */
- 1198, /* GL_PROXY_TEXTURE_2D */
- 1619, /* GL_TEXTURE_TOO_LARGE_EXT */
- 1612, /* GL_TEXTURE_PRIORITY */
- 1617, /* GL_TEXTURE_RESIDENT */
- 1516, /* GL_TEXTURE_BINDING_1D */
- 1518, /* GL_TEXTURE_BINDING_2D */
- 1520, /* GL_TEXTURE_BINDING_3D */
- 1026, /* GL_PACK_SKIP_IMAGES */
- 1022, /* GL_PACK_IMAGE_HEIGHT */
- 1648, /* GL_UNPACK_SKIP_IMAGES */
- 1645, /* GL_UNPACK_IMAGE_HEIGHT */
- 1512, /* GL_TEXTURE_3D */
- 1201, /* GL_PROXY_TEXTURE_3D */
- 1574, /* GL_TEXTURE_DEPTH */
- 1622, /* GL_TEXTURE_WRAP_R */
- 792, /* GL_MAX_3D_TEXTURE_SIZE */
- 1678, /* GL_VERTEX_ARRAY */
- 957, /* GL_NORMAL_ARRAY */
- 138, /* GL_COLOR_ARRAY */
- 576, /* GL_INDEX_ARRAY */
- 1553, /* GL_TEXTURE_COORD_ARRAY */
- 414, /* GL_EDGE_FLAG_ARRAY */
- 1683, /* GL_VERTEX_ARRAY_SIZE */
- 1685, /* GL_VERTEX_ARRAY_TYPE */
- 1684, /* GL_VERTEX_ARRAY_STRIDE */
- 962, /* GL_NORMAL_ARRAY_TYPE */
- 961, /* GL_NORMAL_ARRAY_STRIDE */
- 142, /* GL_COLOR_ARRAY_SIZE */
- 144, /* GL_COLOR_ARRAY_TYPE */
- 143, /* GL_COLOR_ARRAY_STRIDE */
- 581, /* GL_INDEX_ARRAY_TYPE */
- 580, /* GL_INDEX_ARRAY_STRIDE */
- 1557, /* GL_TEXTURE_COORD_ARRAY_SIZE */
- 1559, /* GL_TEXTURE_COORD_ARRAY_TYPE */
- 1558, /* GL_TEXTURE_COORD_ARRAY_STRIDE */
- 418, /* GL_EDGE_FLAG_ARRAY_STRIDE */
- 1682, /* GL_VERTEX_ARRAY_POINTER */
- 960, /* GL_NORMAL_ARRAY_POINTER */
- 141, /* GL_COLOR_ARRAY_POINTER */
- 579, /* GL_INDEX_ARRAY_POINTER */
- 1556, /* GL_TEXTURE_COORD_ARRAY_POINTER */
- 417, /* GL_EDGE_FLAG_ARRAY_POINTER */
- 936, /* GL_MULTISAMPLE */
- 1304, /* GL_SAMPLE_ALPHA_TO_COVERAGE */
- 1306, /* GL_SAMPLE_ALPHA_TO_ONE */
- 1311, /* GL_SAMPLE_COVERAGE */
- 1308, /* GL_SAMPLE_BUFFERS */
- 1299, /* GL_SAMPLES */
- 1315, /* GL_SAMPLE_COVERAGE_VALUE */
- 1313, /* GL_SAMPLE_COVERAGE_INVERT */
- 169, /* GL_COLOR_MATRIX */
- 171, /* GL_COLOR_MATRIX_STACK_DEPTH */
- 800, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH */
- 1127, /* GL_POST_COLOR_MATRIX_RED_SCALE */
- 1123, /* GL_POST_COLOR_MATRIX_GREEN_SCALE */
- 1118, /* GL_POST_COLOR_MATRIX_BLUE_SCALE */
- 1114, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE */
- 1125, /* GL_POST_COLOR_MATRIX_RED_BIAS */
- 1121, /* GL_POST_COLOR_MATRIX_GREEN_BIAS */
- 1116, /* GL_POST_COLOR_MATRIX_BLUE_BIAS */
- 1112, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS */
- 1536, /* GL_TEXTURE_COLOR_TABLE_SGI */
- 1202, /* GL_PROXY_TEXTURE_COLOR_TABLE_SGI */
- 1538, /* GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
- 79, /* GL_BLEND_DST_RGB */
- 87, /* GL_BLEND_SRC_RGB */
- 78, /* GL_BLEND_DST_ALPHA */
- 86, /* GL_BLEND_SRC_ALPHA */
- 175, /* GL_COLOR_TABLE */
- 1137, /* GL_POST_CONVOLUTION_COLOR_TABLE */
- 1120, /* GL_POST_COLOR_MATRIX_COLOR_TABLE */
- 1190, /* GL_PROXY_COLOR_TABLE */
- 1194, /* GL_PROXY_POST_CONVOLUTION_COLOR_TABLE */
- 1193, /* GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE */
- 199, /* GL_COLOR_TABLE_SCALE */
- 179, /* GL_COLOR_TABLE_BIAS */
- 184, /* GL_COLOR_TABLE_FORMAT */
- 201, /* GL_COLOR_TABLE_WIDTH */
- 196, /* GL_COLOR_TABLE_RED_SIZE */
- 187, /* GL_COLOR_TABLE_GREEN_SIZE */
- 181, /* GL_COLOR_TABLE_BLUE_SIZE */
- 176, /* GL_COLOR_TABLE_ALPHA_SIZE */
- 193, /* GL_COLOR_TABLE_LUMINANCE_SIZE */
- 190, /* GL_COLOR_TABLE_INTENSITY_SIZE */
- 70, /* GL_BGR */
- 71, /* GL_BGRA */
- 814, /* GL_MAX_ELEMENTS_VERTICES */
- 813, /* GL_MAX_ELEMENTS_INDICES */
- 1590, /* GL_TEXTURE_INDEX_SIZE_EXT */
- 135, /* GL_CLIP_VOLUME_CLIPPING_HINT_EXT */
- 1084, /* GL_POINT_SIZE_MIN */
- 1080, /* GL_POINT_SIZE_MAX */
- 1074, /* GL_POINT_FADE_THRESHOLD_SIZE */
- 1070, /* GL_POINT_DISTANCE_ATTENUATION */
- 117, /* GL_CLAMP_TO_BORDER */
- 120, /* GL_CLAMP_TO_EDGE */
- 1611, /* GL_TEXTURE_MIN_LOD */
- 1609, /* GL_TEXTURE_MAX_LOD */
- 1515, /* GL_TEXTURE_BASE_LEVEL */
- 1608, /* GL_TEXTURE_MAX_LEVEL */
- 570, /* GL_IGNORE_BORDER_HP */
- 245, /* GL_CONSTANT_BORDER_HP */
- 1248, /* GL_REPLICATE_BORDER_HP */
- 251, /* GL_CONVOLUTION_BORDER_COLOR */
- 985, /* GL_OCCLUSION_TEST_HP */
- 986, /* GL_OCCLUSION_TEST_RESULT_HP */
- 639, /* GL_LINEAR_CLIPMAP_LINEAR_SGIX */
- 1530, /* GL_TEXTURE_CLIPMAP_CENTER_SGIX */
- 1532, /* GL_TEXTURE_CLIPMAP_FRAME_SGIX */
- 1534, /* GL_TEXTURE_CLIPMAP_OFFSET_SGIX */
- 1535, /* GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX */
- 1533, /* GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX */
- 1531, /* GL_TEXTURE_CLIPMAP_DEPTH_SGIX */
- 796, /* GL_MAX_CLIPMAP_DEPTH_SGIX */
- 797, /* GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX */
- 1147, /* GL_POST_TEXTURE_FILTER_BIAS_SGIX */
- 1149, /* GL_POST_TEXTURE_FILTER_SCALE_SGIX */
- 1146, /* GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX */
- 1148, /* GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX */
- 1598, /* GL_TEXTURE_LOD_BIAS_S_SGIX */
- 1599, /* GL_TEXTURE_LOD_BIAS_T_SGIX */
- 1597, /* GL_TEXTURE_LOD_BIAS_R_SGIX */
- 516, /* GL_GENERATE_MIPMAP */
- 517, /* GL_GENERATE_MIPMAP_HINT */
- 479, /* GL_FOG_OFFSET_SGIX */
- 480, /* GL_FOG_OFFSET_VALUE_SGIX */
- 1544, /* GL_TEXTURE_COMPARE_SGIX */
- 1543, /* GL_TEXTURE_COMPARE_OPERATOR_SGIX */
- 1594, /* GL_TEXTURE_LEQUAL_R_SGIX */
- 1586, /* GL_TEXTURE_GEQUAL_R_SGIX */
- 322, /* GL_DEPTH_COMPONENT16 */
- 325, /* GL_DEPTH_COMPONENT24 */
- 328, /* GL_DEPTH_COMPONENT32 */
- 273, /* GL_CULL_VERTEX_EXT */
- 275, /* GL_CULL_VERTEX_OBJECT_POSITION_EXT */
- 274, /* GL_CULL_VERTEX_EYE_POSITION_EXT */
- 1739, /* GL_WRAP_BORDER_SUN */
- 1537, /* GL_TEXTURE_COLOR_WRITEMASK_SGIS */
- 632, /* GL_LIGHT_MODEL_COLOR_CONTROL */
- 1343, /* GL_SINGLE_COLOR */
- 1331, /* GL_SEPARATE_SPECULAR_COLOR */
- 1340, /* GL_SHARED_TEXTURE_PALETTE_EXT */
- 1653, /* GL_UNSIGNED_BYTE_2_3_3_REV */
- 1666, /* GL_UNSIGNED_SHORT_5_6_5 */
- 1667, /* GL_UNSIGNED_SHORT_5_6_5_REV */
- 1664, /* GL_UNSIGNED_SHORT_4_4_4_4_REV */
- 1662, /* GL_UNSIGNED_SHORT_1_5_5_5_REV */
- 1660, /* GL_UNSIGNED_INT_8_8_8_8_REV */
- 1658, /* GL_UNSIGNED_INT_2_10_10_10_REV */
- 1606, /* GL_TEXTURE_MAX_CLAMP_S_SGIX */
- 1607, /* GL_TEXTURE_MAX_CLAMP_T_SGIX */
- 1605, /* GL_TEXTURE_MAX_CLAMP_R_SGIX */
- 887, /* GL_MIRRORED_REPEAT */
- 1287, /* GL_RGB_S3TC */
- 1264, /* GL_RGB4_S3TC */
- 1286, /* GL_RGBA_S3TC */
- 1281, /* GL_RGBA4_S3TC */
- 1284, /* GL_RGBA_DXT5_S3TC */
- 1279, /* GL_RGBA4_DXT5_S3TC */
- 238, /* GL_COMPRESSED_RGB_S3TC_DXT1_EXT */
- 233, /* GL_COMPRESSED_RGBA_S3TC_DXT1_EXT */
- 234, /* GL_COMPRESSED_RGBA_S3TC_DXT3_EXT */
- 235, /* GL_COMPRESSED_RGBA_S3TC_DXT5_EXT */
- 948, /* GL_NEAREST_CLIPMAP_NEAREST_SGIX */
- 947, /* GL_NEAREST_CLIPMAP_LINEAR_SGIX */
- 640, /* GL_LINEAR_CLIPMAP_NEAREST_SGIX */
- 466, /* GL_FOG_COORDINATE_SOURCE */
- 458, /* GL_FOG_COORD */
- 482, /* GL_FRAGMENT_DEPTH */
- 279, /* GL_CURRENT_FOG_COORD */
- 465, /* GL_FOG_COORDINATE_ARRAY_TYPE */
- 464, /* GL_FOG_COORDINATE_ARRAY_STRIDE */
- 463, /* GL_FOG_COORDINATE_ARRAY_POINTER */
- 460, /* GL_FOG_COORDINATE_ARRAY */
- 173, /* GL_COLOR_SUM */
- 298, /* GL_CURRENT_SECONDARY_COLOR */
- 1324, /* GL_SECONDARY_COLOR_ARRAY_SIZE */
- 1326, /* GL_SECONDARY_COLOR_ARRAY_TYPE */
- 1325, /* GL_SECONDARY_COLOR_ARRAY_STRIDE */
- 1323, /* GL_SECONDARY_COLOR_ARRAY_POINTER */
- 1320, /* GL_SECONDARY_COLOR_ARRAY */
- 526, /* GL_GL_CURRENT_RASTER_SECONDARY_COLOR */
+ 726, /* GL_LUMINANCE4 */
+ 732, /* GL_LUMINANCE8 */
+ 716, /* GL_LUMINANCE12 */
+ 722, /* GL_LUMINANCE16 */
+ 727, /* GL_LUMINANCE4_ALPHA4 */
+ 730, /* GL_LUMINANCE6_ALPHA2 */
+ 733, /* GL_LUMINANCE8_ALPHA8 */
+ 719, /* GL_LUMINANCE12_ALPHA4 */
+ 717, /* GL_LUMINANCE12_ALPHA12 */
+ 723, /* GL_LUMINANCE16_ALPHA16 */
+ 638, /* GL_INTENSITY */
+ 643, /* GL_INTENSITY4 */
+ 645, /* GL_INTENSITY8 */
+ 639, /* GL_INTENSITY12 */
+ 641, /* GL_INTENSITY16 */
+ 1337, /* GL_RGB2_EXT */
+ 1338, /* GL_RGB4 */
+ 1341, /* GL_RGB5 */
+ 1345, /* GL_RGB8 */
+ 1329, /* GL_RGB10 */
+ 1333, /* GL_RGB12 */
+ 1335, /* GL_RGB16 */
+ 1352, /* GL_RGBA2 */
+ 1354, /* GL_RGBA4 */
+ 1342, /* GL_RGB5_A1 */
+ 1358, /* GL_RGBA8 */
+ 1330, /* GL_RGB10_A2 */
+ 1348, /* GL_RGBA12 */
+ 1350, /* GL_RGBA16 */
+ 1716, /* GL_TEXTURE_RED_SIZE */
+ 1686, /* GL_TEXTURE_GREEN_SIZE */
+ 1624, /* GL_TEXTURE_BLUE_SIZE */
+ 1611, /* GL_TEXTURE_ALPHA_SIZE */
+ 1699, /* GL_TEXTURE_LUMINANCE_SIZE */
+ 1690, /* GL_TEXTURE_INTENSITY_SIZE */
+ 1323, /* GL_REPLACE_EXT */
+ 1258, /* GL_PROXY_TEXTURE_1D */
+ 1261, /* GL_PROXY_TEXTURE_2D */
+ 1722, /* GL_TEXTURE_TOO_LARGE_EXT */
+ 1711, /* GL_TEXTURE_PRIORITY */
+ 1718, /* GL_TEXTURE_RESIDENT */
+ 1614, /* GL_TEXTURE_BINDING_1D */
+ 1616, /* GL_TEXTURE_BINDING_2D */
+ 1618, /* GL_TEXTURE_BINDING_3D */
+ 1084, /* GL_PACK_SKIP_IMAGES */
+ 1080, /* GL_PACK_IMAGE_HEIGHT */
+ 1753, /* GL_UNPACK_SKIP_IMAGES */
+ 1750, /* GL_UNPACK_IMAGE_HEIGHT */
+ 1610, /* GL_TEXTURE_3D */
+ 1264, /* GL_PROXY_TEXTURE_3D */
+ 1673, /* GL_TEXTURE_DEPTH */
+ 1725, /* GL_TEXTURE_WRAP_R */
+ 847, /* GL_MAX_3D_TEXTURE_SIZE */
+ 1786, /* GL_VERTEX_ARRAY */
+ 1014, /* GL_NORMAL_ARRAY */
+ 148, /* GL_COLOR_ARRAY */
+ 623, /* GL_INDEX_ARRAY */
+ 1651, /* GL_TEXTURE_COORD_ARRAY */
+ 456, /* GL_EDGE_FLAG_ARRAY */
+ 1792, /* GL_VERTEX_ARRAY_SIZE */
+ 1794, /* GL_VERTEX_ARRAY_TYPE */
+ 1793, /* GL_VERTEX_ARRAY_STRIDE */
+ 1019, /* GL_NORMAL_ARRAY_TYPE */
+ 1018, /* GL_NORMAL_ARRAY_STRIDE */
+ 152, /* GL_COLOR_ARRAY_SIZE */
+ 154, /* GL_COLOR_ARRAY_TYPE */
+ 153, /* GL_COLOR_ARRAY_STRIDE */
+ 628, /* GL_INDEX_ARRAY_TYPE */
+ 627, /* GL_INDEX_ARRAY_STRIDE */
+ 1655, /* GL_TEXTURE_COORD_ARRAY_SIZE */
+ 1657, /* GL_TEXTURE_COORD_ARRAY_TYPE */
+ 1656, /* GL_TEXTURE_COORD_ARRAY_STRIDE */
+ 460, /* GL_EDGE_FLAG_ARRAY_STRIDE */
+ 1791, /* GL_VERTEX_ARRAY_POINTER */
+ 1017, /* GL_NORMAL_ARRAY_POINTER */
+ 151, /* GL_COLOR_ARRAY_POINTER */
+ 626, /* GL_INDEX_ARRAY_POINTER */
+ 1654, /* GL_TEXTURE_COORD_ARRAY_POINTER */
+ 459, /* GL_EDGE_FLAG_ARRAY_POINTER */
+ 993, /* GL_MULTISAMPLE */
+ 1382, /* GL_SAMPLE_ALPHA_TO_COVERAGE */
+ 1384, /* GL_SAMPLE_ALPHA_TO_ONE */
+ 1389, /* GL_SAMPLE_COVERAGE */
+ 1386, /* GL_SAMPLE_BUFFERS */
+ 1377, /* GL_SAMPLES */
+ 1393, /* GL_SAMPLE_COVERAGE_VALUE */
+ 1391, /* GL_SAMPLE_COVERAGE_INVERT */
+ 195, /* GL_COLOR_MATRIX */
+ 197, /* GL_COLOR_MATRIX_STACK_DEPTH */
+ 855, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH */
+ 1189, /* GL_POST_COLOR_MATRIX_RED_SCALE */
+ 1185, /* GL_POST_COLOR_MATRIX_GREEN_SCALE */
+ 1180, /* GL_POST_COLOR_MATRIX_BLUE_SCALE */
+ 1176, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE */
+ 1187, /* GL_POST_COLOR_MATRIX_RED_BIAS */
+ 1183, /* GL_POST_COLOR_MATRIX_GREEN_BIAS */
+ 1178, /* GL_POST_COLOR_MATRIX_BLUE_BIAS */
+ 1174, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS */
+ 1634, /* GL_TEXTURE_COLOR_TABLE_SGI */
+ 1265, /* GL_PROXY_TEXTURE_COLOR_TABLE_SGI */
+ 1636, /* GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
+ 80, /* GL_BLEND_DST_RGB */
+ 89, /* GL_BLEND_SRC_RGB */
+ 79, /* GL_BLEND_DST_ALPHA */
+ 88, /* GL_BLEND_SRC_ALPHA */
+ 201, /* GL_COLOR_TABLE */
+ 1199, /* GL_POST_CONVOLUTION_COLOR_TABLE */
+ 1182, /* GL_POST_COLOR_MATRIX_COLOR_TABLE */
+ 1253, /* GL_PROXY_COLOR_TABLE */
+ 1257, /* GL_PROXY_POST_CONVOLUTION_COLOR_TABLE */
+ 1256, /* GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE */
+ 225, /* GL_COLOR_TABLE_SCALE */
+ 205, /* GL_COLOR_TABLE_BIAS */
+ 210, /* GL_COLOR_TABLE_FORMAT */
+ 227, /* GL_COLOR_TABLE_WIDTH */
+ 222, /* GL_COLOR_TABLE_RED_SIZE */
+ 213, /* GL_COLOR_TABLE_GREEN_SIZE */
+ 207, /* GL_COLOR_TABLE_BLUE_SIZE */
+ 202, /* GL_COLOR_TABLE_ALPHA_SIZE */
+ 219, /* GL_COLOR_TABLE_LUMINANCE_SIZE */
+ 216, /* GL_COLOR_TABLE_INTENSITY_SIZE */
+ 71, /* GL_BGR */
+ 72, /* GL_BGRA */
+ 869, /* GL_MAX_ELEMENTS_VERTICES */
+ 868, /* GL_MAX_ELEMENTS_INDICES */
+ 1689, /* GL_TEXTURE_INDEX_SIZE_EXT */
+ 145, /* GL_CLIP_VOLUME_CLIPPING_HINT_EXT */
+ 1146, /* GL_POINT_SIZE_MIN */
+ 1142, /* GL_POINT_SIZE_MAX */
+ 1136, /* GL_POINT_FADE_THRESHOLD_SIZE */
+ 1132, /* GL_POINT_DISTANCE_ATTENUATION */
+ 127, /* GL_CLAMP_TO_BORDER */
+ 130, /* GL_CLAMP_TO_EDGE */
+ 1710, /* GL_TEXTURE_MIN_LOD */
+ 1708, /* GL_TEXTURE_MAX_LOD */
+ 1613, /* GL_TEXTURE_BASE_LEVEL */
+ 1707, /* GL_TEXTURE_MAX_LEVEL */
+ 616, /* GL_IGNORE_BORDER_HP */
+ 276, /* GL_CONSTANT_BORDER_HP */
+ 1324, /* GL_REPLICATE_BORDER_HP */
+ 282, /* GL_CONVOLUTION_BORDER_COLOR */
+ 1043, /* GL_OCCLUSION_TEST_HP */
+ 1044, /* GL_OCCLUSION_TEST_RESULT_HP */
+ 688, /* GL_LINEAR_CLIPMAP_LINEAR_SGIX */
+ 1628, /* GL_TEXTURE_CLIPMAP_CENTER_SGIX */
+ 1630, /* GL_TEXTURE_CLIPMAP_FRAME_SGIX */
+ 1632, /* GL_TEXTURE_CLIPMAP_OFFSET_SGIX */
+ 1633, /* GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX */
+ 1631, /* GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX */
+ 1629, /* GL_TEXTURE_CLIPMAP_DEPTH_SGIX */
+ 851, /* GL_MAX_CLIPMAP_DEPTH_SGIX */
+ 852, /* GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX */
+ 1209, /* GL_POST_TEXTURE_FILTER_BIAS_SGIX */
+ 1211, /* GL_POST_TEXTURE_FILTER_SCALE_SGIX */
+ 1208, /* GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX */
+ 1210, /* GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX */
+ 1697, /* GL_TEXTURE_LOD_BIAS_S_SGIX */
+ 1698, /* GL_TEXTURE_LOD_BIAS_T_SGIX */
+ 1696, /* GL_TEXTURE_LOD_BIAS_R_SGIX */
+ 586, /* GL_GENERATE_MIPMAP */
+ 587, /* GL_GENERATE_MIPMAP_HINT */
+ 528, /* GL_FOG_OFFSET_SGIX */
+ 529, /* GL_FOG_OFFSET_VALUE_SGIX */
+ 1642, /* GL_TEXTURE_COMPARE_SGIX */
+ 1641, /* GL_TEXTURE_COMPARE_OPERATOR_SGIX */
+ 1693, /* GL_TEXTURE_LEQUAL_R_SGIX */
+ 1685, /* GL_TEXTURE_GEQUAL_R_SGIX */
+ 359, /* GL_DEPTH_COMPONENT16 */
+ 362, /* GL_DEPTH_COMPONENT24 */
+ 365, /* GL_DEPTH_COMPONENT32 */
+ 306, /* GL_CULL_VERTEX_EXT */
+ 308, /* GL_CULL_VERTEX_OBJECT_POSITION_EXT */
+ 307, /* GL_CULL_VERTEX_EYE_POSITION_EXT */
+ 1849, /* GL_WRAP_BORDER_SUN */
+ 1635, /* GL_TEXTURE_COLOR_WRITEMASK_SGIS */
+ 681, /* GL_LIGHT_MODEL_COLOR_CONTROL */
+ 1423, /* GL_SINGLE_COLOR */
+ 1409, /* GL_SEPARATE_SPECULAR_COLOR */
+ 1418, /* GL_SHARED_TEXTURE_PALETTE_EXT */
+ 539, /* GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING */
+ 540, /* GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE */
+ 547, /* GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE */
+ 542, /* GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE */
+ 538, /* GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE */
+ 537, /* GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE */
+ 541, /* GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE */
+ 548, /* GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE */
+ 559, /* GL_FRAMEBUFFER_DEFAULT */
+ 572, /* GL_FRAMEBUFFER_UNDEFINED */
+ 372, /* GL_DEPTH_STENCIL_ATTACHMENT */
+ 622, /* GL_INDEX */
+ 1759, /* GL_UNSIGNED_BYTE_2_3_3_REV */
+ 1774, /* GL_UNSIGNED_SHORT_5_6_5 */
+ 1775, /* GL_UNSIGNED_SHORT_5_6_5_REV */
+ 1772, /* GL_UNSIGNED_SHORT_4_4_4_4_REV */
+ 1770, /* GL_UNSIGNED_SHORT_1_5_5_5_REV */
+ 1767, /* GL_UNSIGNED_INT_8_8_8_8_REV */
+ 1765, /* GL_UNSIGNED_INT_2_10_10_10_REV */
+ 1705, /* GL_TEXTURE_MAX_CLAMP_S_SGIX */
+ 1706, /* GL_TEXTURE_MAX_CLAMP_T_SGIX */
+ 1704, /* GL_TEXTURE_MAX_CLAMP_R_SGIX */
+ 944, /* GL_MIRRORED_REPEAT */
+ 1365, /* GL_RGB_S3TC */
+ 1340, /* GL_RGB4_S3TC */
+ 1363, /* GL_RGBA_S3TC */
+ 1357, /* GL_RGBA4_S3TC */
+ 1361, /* GL_RGBA_DXT5_S3TC */
+ 1355, /* GL_RGBA4_DXT5_S3TC */
+ 264, /* GL_COMPRESSED_RGB_S3TC_DXT1_EXT */
+ 259, /* GL_COMPRESSED_RGBA_S3TC_DXT1_EXT */
+ 260, /* GL_COMPRESSED_RGBA_S3TC_DXT3_EXT */
+ 261, /* GL_COMPRESSED_RGBA_S3TC_DXT5_EXT */
+ 1005, /* GL_NEAREST_CLIPMAP_NEAREST_SGIX */
+ 1004, /* GL_NEAREST_CLIPMAP_LINEAR_SGIX */
+ 689, /* GL_LINEAR_CLIPMAP_NEAREST_SGIX */
+ 515, /* GL_FOG_COORDINATE_SOURCE */
+ 507, /* GL_FOG_COORD */
+ 531, /* GL_FRAGMENT_DEPTH */
+ 312, /* GL_CURRENT_FOG_COORD */
+ 514, /* GL_FOG_COORDINATE_ARRAY_TYPE */
+ 513, /* GL_FOG_COORDINATE_ARRAY_STRIDE */
+ 512, /* GL_FOG_COORDINATE_ARRAY_POINTER */
+ 509, /* GL_FOG_COORDINATE_ARRAY */
+ 199, /* GL_COLOR_SUM */
+ 332, /* GL_CURRENT_SECONDARY_COLOR */
+ 1402, /* GL_SECONDARY_COLOR_ARRAY_SIZE */
+ 1404, /* GL_SECONDARY_COLOR_ARRAY_TYPE */
+ 1403, /* GL_SECONDARY_COLOR_ARRAY_STRIDE */
+ 1401, /* GL_SECONDARY_COLOR_ARRAY_POINTER */
+ 1398, /* GL_SECONDARY_COLOR_ARRAY */
+ 330, /* GL_CURRENT_RASTER_SECONDARY_COLOR */
28, /* GL_ALIASED_POINT_SIZE_RANGE */
27, /* GL_ALIASED_LINE_WIDTH_RANGE */
- 1444, /* GL_TEXTURE0 */
- 1446, /* GL_TEXTURE1 */
- 1468, /* GL_TEXTURE2 */
- 1490, /* GL_TEXTURE3 */
- 1496, /* GL_TEXTURE4 */
- 1498, /* GL_TEXTURE5 */
- 1500, /* GL_TEXTURE6 */
- 1502, /* GL_TEXTURE7 */
- 1504, /* GL_TEXTURE8 */
- 1506, /* GL_TEXTURE9 */
- 1447, /* GL_TEXTURE10 */
- 1449, /* GL_TEXTURE11 */
- 1451, /* GL_TEXTURE12 */
- 1453, /* GL_TEXTURE13 */
- 1455, /* GL_TEXTURE14 */
- 1457, /* GL_TEXTURE15 */
- 1459, /* GL_TEXTURE16 */
- 1461, /* GL_TEXTURE17 */
- 1463, /* GL_TEXTURE18 */
- 1465, /* GL_TEXTURE19 */
- 1469, /* GL_TEXTURE20 */
- 1471, /* GL_TEXTURE21 */
- 1473, /* GL_TEXTURE22 */
- 1475, /* GL_TEXTURE23 */
- 1477, /* GL_TEXTURE24 */
- 1479, /* GL_TEXTURE25 */
- 1481, /* GL_TEXTURE26 */
- 1483, /* GL_TEXTURE27 */
- 1485, /* GL_TEXTURE28 */
- 1487, /* GL_TEXTURE29 */
- 1491, /* GL_TEXTURE30 */
- 1493, /* GL_TEXTURE31 */
+ 1542, /* GL_TEXTURE0 */
+ 1544, /* GL_TEXTURE1 */
+ 1566, /* GL_TEXTURE2 */
+ 1588, /* GL_TEXTURE3 */
+ 1594, /* GL_TEXTURE4 */
+ 1596, /* GL_TEXTURE5 */
+ 1598, /* GL_TEXTURE6 */
+ 1600, /* GL_TEXTURE7 */
+ 1602, /* GL_TEXTURE8 */
+ 1604, /* GL_TEXTURE9 */
+ 1545, /* GL_TEXTURE10 */
+ 1547, /* GL_TEXTURE11 */
+ 1549, /* GL_TEXTURE12 */
+ 1551, /* GL_TEXTURE13 */
+ 1553, /* GL_TEXTURE14 */
+ 1555, /* GL_TEXTURE15 */
+ 1557, /* GL_TEXTURE16 */
+ 1559, /* GL_TEXTURE17 */
+ 1561, /* GL_TEXTURE18 */
+ 1563, /* GL_TEXTURE19 */
+ 1567, /* GL_TEXTURE20 */
+ 1569, /* GL_TEXTURE21 */
+ 1571, /* GL_TEXTURE22 */
+ 1573, /* GL_TEXTURE23 */
+ 1575, /* GL_TEXTURE24 */
+ 1577, /* GL_TEXTURE25 */
+ 1579, /* GL_TEXTURE26 */
+ 1581, /* GL_TEXTURE27 */
+ 1583, /* GL_TEXTURE28 */
+ 1585, /* GL_TEXTURE29 */
+ 1589, /* GL_TEXTURE30 */
+ 1591, /* GL_TEXTURE31 */
18, /* GL_ACTIVE_TEXTURE */
- 123, /* GL_CLIENT_ACTIVE_TEXTURE */
- 865, /* GL_MAX_TEXTURE_UNITS */
- 1632, /* GL_TRANSPOSE_MODELVIEW_MATRIX */
- 1635, /* GL_TRANSPOSE_PROJECTION_MATRIX */
- 1637, /* GL_TRANSPOSE_TEXTURE_MATRIX */
- 1629, /* GL_TRANSPOSE_COLOR_MATRIX */
- 1432, /* GL_SUBTRACT */
- 854, /* GL_MAX_RENDERBUFFER_SIZE_EXT */
- 221, /* GL_COMPRESSED_ALPHA */
- 225, /* GL_COMPRESSED_LUMINANCE */
- 226, /* GL_COMPRESSED_LUMINANCE_ALPHA */
- 223, /* GL_COMPRESSED_INTENSITY */
- 229, /* GL_COMPRESSED_RGB */
- 230, /* GL_COMPRESSED_RGBA */
- 1551, /* GL_TEXTURE_COMPRESSION_HINT */
- 1613, /* GL_TEXTURE_RECTANGLE_ARB */
- 1523, /* GL_TEXTURE_BINDING_RECTANGLE_ARB */
- 1205, /* GL_PROXY_TEXTURE_RECTANGLE_ARB */
- 852, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB */
- 334, /* GL_DEPTH_STENCIL_NV */
- 1657, /* GL_UNSIGNED_INT_24_8_NV */
- 861, /* GL_MAX_TEXTURE_LOD_BIAS */
- 1604, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */
- 862, /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */
- 1580, /* GL_TEXTURE_FILTER_CONTROL */
- 1595, /* GL_TEXTURE_LOD_BIAS */
- 206, /* GL_COMBINE4 */
- 855, /* GL_MAX_SHININESS_NV */
- 856, /* GL_MAX_SPOT_EXPONENT_NV */
- 574, /* GL_INCR_WRAP */
- 309, /* GL_DECR_WRAP */
- 907, /* GL_MODELVIEW1_ARB */
- 963, /* GL_NORMAL_MAP */
- 1234, /* GL_REFLECTION_MAP */
- 1560, /* GL_TEXTURE_CUBE_MAP */
- 1521, /* GL_TEXTURE_BINDING_CUBE_MAP */
- 1568, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */
- 1562, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */
- 1570, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */
- 1564, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */
- 1572, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */
- 1566, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */
- 1203, /* GL_PROXY_TEXTURE_CUBE_MAP */
- 808, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */
- 942, /* GL_MULTISAMPLE_FILTER_HINT_NV */
- 474, /* GL_FOG_DISTANCE_MODE_NV */
- 433, /* GL_EYE_RADIAL_NV */
- 432, /* GL_EYE_PLANE_ABSOLUTE_NV */
- 205, /* GL_COMBINE */
- 212, /* GL_COMBINE_RGB */
- 207, /* GL_COMBINE_ALPHA */
- 1288, /* GL_RGB_SCALE */
+ 133, /* GL_CLIENT_ACTIVE_TEXTURE */
+ 922, /* GL_MAX_TEXTURE_UNITS */
+ 1737, /* GL_TRANSPOSE_MODELVIEW_MATRIX */
+ 1740, /* GL_TRANSPOSE_PROJECTION_MATRIX */
+ 1742, /* GL_TRANSPOSE_TEXTURE_MATRIX */
+ 1734, /* GL_TRANSPOSE_COLOR_MATRIX */
+ 1524, /* GL_SUBTRACT */
+ 909, /* GL_MAX_RENDERBUFFER_SIZE_EXT */
+ 247, /* GL_COMPRESSED_ALPHA */
+ 251, /* GL_COMPRESSED_LUMINANCE */
+ 252, /* GL_COMPRESSED_LUMINANCE_ALPHA */
+ 249, /* GL_COMPRESSED_INTENSITY */
+ 255, /* GL_COMPRESSED_RGB */
+ 256, /* GL_COMPRESSED_RGBA */
+ 1649, /* GL_TEXTURE_COMPRESSION_HINT */
+ 1714, /* GL_TEXTURE_RECTANGLE_ARB */
+ 1621, /* GL_TEXTURE_BINDING_RECTANGLE_ARB */
+ 1268, /* GL_PROXY_TEXTURE_RECTANGLE_ARB */
+ 907, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB */
+ 371, /* GL_DEPTH_STENCIL */
+ 1763, /* GL_UNSIGNED_INT_24_8 */
+ 918, /* GL_MAX_TEXTURE_LOD_BIAS */
+ 1703, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */
+ 919, /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */
+ 1679, /* GL_TEXTURE_FILTER_CONTROL */
+ 1694, /* GL_TEXTURE_LOD_BIAS */
+ 232, /* GL_COMBINE4 */
+ 912, /* GL_MAX_SHININESS_NV */
+ 913, /* GL_MAX_SPOT_EXPONENT_NV */
+ 620, /* GL_INCR_WRAP */
+ 343, /* GL_DECR_WRAP */
+ 964, /* GL_MODELVIEW1_ARB */
+ 1020, /* GL_NORMAL_MAP */
+ 1299, /* GL_REFLECTION_MAP */
+ 1658, /* GL_TEXTURE_CUBE_MAP */
+ 1619, /* GL_TEXTURE_BINDING_CUBE_MAP */
+ 1666, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */
+ 1660, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */
+ 1668, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */
+ 1662, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */
+ 1670, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */
+ 1664, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */
+ 1266, /* GL_PROXY_TEXTURE_CUBE_MAP */
+ 863, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */
+ 999, /* GL_MULTISAMPLE_FILTER_HINT_NV */
+ 523, /* GL_FOG_DISTANCE_MODE_NV */
+ 475, /* GL_EYE_RADIAL_NV */
+ 474, /* GL_EYE_PLANE_ABSOLUTE_NV */
+ 231, /* GL_COMBINE */
+ 238, /* GL_COMBINE_RGB */
+ 233, /* GL_COMBINE_ALPHA */
+ 1366, /* GL_RGB_SCALE */
24, /* GL_ADD_SIGNED */
- 601, /* GL_INTERPOLATE */
- 240, /* GL_CONSTANT */
- 1153, /* GL_PRIMARY_COLOR */
- 1150, /* GL_PREVIOUS */
- 1354, /* GL_SOURCE0_RGB */
- 1360, /* GL_SOURCE1_RGB */
- 1366, /* GL_SOURCE2_RGB */
- 1370, /* GL_SOURCE3_RGB_NV */
- 1351, /* GL_SOURCE0_ALPHA */
- 1357, /* GL_SOURCE1_ALPHA */
- 1363, /* GL_SOURCE2_ALPHA */
- 1369, /* GL_SOURCE3_ALPHA_NV */
- 999, /* GL_OPERAND0_RGB */
- 1005, /* GL_OPERAND1_RGB */
- 1011, /* GL_OPERAND2_RGB */
- 1015, /* GL_OPERAND3_RGB_NV */
- 996, /* GL_OPERAND0_ALPHA */
- 1002, /* GL_OPERAND1_ALPHA */
- 1008, /* GL_OPERAND2_ALPHA */
- 1014, /* GL_OPERAND3_ALPHA_NV */
- 1679, /* GL_VERTEX_ARRAY_BINDING_APPLE */
- 1743, /* GL_YCBCR_422_APPLE */
- 1668, /* GL_UNSIGNED_SHORT_8_8_APPLE */
- 1670, /* GL_UNSIGNED_SHORT_8_8_REV_APPLE */
- 1345, /* GL_SLICE_ACCUM_SUN */
- 1210, /* GL_QUAD_MESH_SUN */
- 1641, /* GL_TRIANGLE_MESH_SUN */
- 1717, /* GL_VERTEX_PROGRAM_ARB */
- 1728, /* GL_VERTEX_STATE_PROGRAM_NV */
- 1704, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED */
- 1710, /* GL_VERTEX_ATTRIB_ARRAY_SIZE */
- 1712, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE */
- 1714, /* GL_VERTEX_ATTRIB_ARRAY_TYPE */
- 300, /* GL_CURRENT_VERTEX_ATTRIB */
- 1166, /* GL_PROGRAM_LENGTH_ARB */
- 1180, /* GL_PROGRAM_STRING_ARB */
- 929, /* GL_MODELVIEW_PROJECTION_NV */
- 569, /* GL_IDENTITY_NV */
- 614, /* GL_INVERSE_NV */
- 1634, /* GL_TRANSPOSE_NV */
- 615, /* GL_INVERSE_TRANSPOSE_NV */
- 838, /* GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB */
- 837, /* GL_MAX_PROGRAM_MATRICES_ARB */
- 745, /* GL_MATRIX0_NV */
- 757, /* GL_MATRIX1_NV */
- 769, /* GL_MATRIX2_NV */
- 773, /* GL_MATRIX3_NV */
- 775, /* GL_MATRIX4_NV */
- 777, /* GL_MATRIX5_NV */
- 779, /* GL_MATRIX6_NV */
- 781, /* GL_MATRIX7_NV */
- 285, /* GL_CURRENT_MATRIX_STACK_DEPTH_ARB */
- 282, /* GL_CURRENT_MATRIX_ARB */
- 1720, /* GL_VERTEX_PROGRAM_POINT_SIZE */
- 1723, /* GL_VERTEX_PROGRAM_TWO_SIDE */
- 1178, /* GL_PROGRAM_PARAMETER_NV */
- 1708, /* GL_VERTEX_ATTRIB_ARRAY_POINTER */
- 1182, /* GL_PROGRAM_TARGET_NV */
- 1179, /* GL_PROGRAM_RESIDENT_NV */
- 1626, /* GL_TRACK_MATRIX_NV */
- 1627, /* GL_TRACK_MATRIX_TRANSFORM_NV */
- 1718, /* GL_VERTEX_PROGRAM_BINDING_NV */
- 1160, /* GL_PROGRAM_ERROR_POSITION_ARB */
- 319, /* GL_DEPTH_CLAMP_NV */
- 1686, /* GL_VERTEX_ATTRIB_ARRAY0_NV */
- 1693, /* GL_VERTEX_ATTRIB_ARRAY1_NV */
- 1694, /* GL_VERTEX_ATTRIB_ARRAY2_NV */
- 1695, /* GL_VERTEX_ATTRIB_ARRAY3_NV */
- 1696, /* GL_VERTEX_ATTRIB_ARRAY4_NV */
- 1697, /* GL_VERTEX_ATTRIB_ARRAY5_NV */
- 1698, /* GL_VERTEX_ATTRIB_ARRAY6_NV */
- 1699, /* GL_VERTEX_ATTRIB_ARRAY7_NV */
- 1700, /* GL_VERTEX_ATTRIB_ARRAY8_NV */
- 1701, /* GL_VERTEX_ATTRIB_ARRAY9_NV */
- 1687, /* GL_VERTEX_ATTRIB_ARRAY10_NV */
- 1688, /* GL_VERTEX_ATTRIB_ARRAY11_NV */
- 1689, /* GL_VERTEX_ATTRIB_ARRAY12_NV */
- 1690, /* GL_VERTEX_ATTRIB_ARRAY13_NV */
- 1691, /* GL_VERTEX_ATTRIB_ARRAY14_NV */
- 1692, /* GL_VERTEX_ATTRIB_ARRAY15_NV */
- 699, /* GL_MAP1_VERTEX_ATTRIB0_4_NV */
- 706, /* GL_MAP1_VERTEX_ATTRIB1_4_NV */
- 707, /* GL_MAP1_VERTEX_ATTRIB2_4_NV */
- 708, /* GL_MAP1_VERTEX_ATTRIB3_4_NV */
- 709, /* GL_MAP1_VERTEX_ATTRIB4_4_NV */
- 710, /* GL_MAP1_VERTEX_ATTRIB5_4_NV */
- 711, /* GL_MAP1_VERTEX_ATTRIB6_4_NV */
- 712, /* GL_MAP1_VERTEX_ATTRIB7_4_NV */
- 713, /* GL_MAP1_VERTEX_ATTRIB8_4_NV */
- 714, /* GL_MAP1_VERTEX_ATTRIB9_4_NV */
- 700, /* GL_MAP1_VERTEX_ATTRIB10_4_NV */
- 701, /* GL_MAP1_VERTEX_ATTRIB11_4_NV */
- 702, /* GL_MAP1_VERTEX_ATTRIB12_4_NV */
- 703, /* GL_MAP1_VERTEX_ATTRIB13_4_NV */
- 704, /* GL_MAP1_VERTEX_ATTRIB14_4_NV */
- 705, /* GL_MAP1_VERTEX_ATTRIB15_4_NV */
- 726, /* GL_MAP2_VERTEX_ATTRIB0_4_NV */
- 733, /* GL_MAP2_VERTEX_ATTRIB1_4_NV */
- 734, /* GL_MAP2_VERTEX_ATTRIB2_4_NV */
- 735, /* GL_MAP2_VERTEX_ATTRIB3_4_NV */
- 736, /* GL_MAP2_VERTEX_ATTRIB4_4_NV */
- 737, /* GL_MAP2_VERTEX_ATTRIB5_4_NV */
- 738, /* GL_MAP2_VERTEX_ATTRIB6_4_NV */
- 1159, /* GL_PROGRAM_BINDING_ARB */
- 740, /* GL_MAP2_VERTEX_ATTRIB8_4_NV */
- 741, /* GL_MAP2_VERTEX_ATTRIB9_4_NV */
- 727, /* GL_MAP2_VERTEX_ATTRIB10_4_NV */
- 728, /* GL_MAP2_VERTEX_ATTRIB11_4_NV */
- 729, /* GL_MAP2_VERTEX_ATTRIB12_4_NV */
- 730, /* GL_MAP2_VERTEX_ATTRIB13_4_NV */
- 731, /* GL_MAP2_VERTEX_ATTRIB14_4_NV */
- 732, /* GL_MAP2_VERTEX_ATTRIB15_4_NV */
- 1549, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE */
- 1546, /* GL_TEXTURE_COMPRESSED */
- 968, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS */
- 239, /* GL_COMPRESSED_TEXTURE_FORMATS */
- 877, /* GL_MAX_VERTEX_UNITS_ARB */
+ 648, /* GL_INTERPOLATE */
+ 271, /* GL_CONSTANT */
+ 1215, /* GL_PRIMARY_COLOR */
+ 1212, /* GL_PREVIOUS */
+ 1438, /* GL_SOURCE0_RGB */
+ 1444, /* GL_SOURCE1_RGB */
+ 1450, /* GL_SOURCE2_RGB */
+ 1454, /* GL_SOURCE3_RGB_NV */
+ 1435, /* GL_SOURCE0_ALPHA */
+ 1441, /* GL_SOURCE1_ALPHA */
+ 1447, /* GL_SOURCE2_ALPHA */
+ 1453, /* GL_SOURCE3_ALPHA_NV */
+ 1057, /* GL_OPERAND0_RGB */
+ 1063, /* GL_OPERAND1_RGB */
+ 1069, /* GL_OPERAND2_RGB */
+ 1073, /* GL_OPERAND3_RGB_NV */
+ 1054, /* GL_OPERAND0_ALPHA */
+ 1060, /* GL_OPERAND1_ALPHA */
+ 1066, /* GL_OPERAND2_ALPHA */
+ 1072, /* GL_OPERAND3_ALPHA_NV */
+ 1787, /* GL_VERTEX_ARRAY_BINDING */
+ 1712, /* GL_TEXTURE_RANGE_LENGTH_APPLE */
+ 1713, /* GL_TEXTURE_RANGE_POINTER_APPLE */
+ 1853, /* GL_YCBCR_422_APPLE */
+ 1776, /* GL_UNSIGNED_SHORT_8_8_APPLE */
+ 1778, /* GL_UNSIGNED_SHORT_8_8_REV_APPLE */
+ 1721, /* GL_TEXTURE_STORAGE_HINT_APPLE */
+ 1515, /* GL_STORAGE_PRIVATE_APPLE */
+ 1514, /* GL_STORAGE_CACHED_APPLE */
+ 1516, /* GL_STORAGE_SHARED_APPLE */
+ 1425, /* GL_SLICE_ACCUM_SUN */
+ 1274, /* GL_QUAD_MESH_SUN */
+ 1746, /* GL_TRIANGLE_MESH_SUN */
+ 1826, /* GL_VERTEX_PROGRAM_ARB */
+ 1837, /* GL_VERTEX_STATE_PROGRAM_NV */
+ 1813, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED */
+ 1819, /* GL_VERTEX_ATTRIB_ARRAY_SIZE */
+ 1821, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE */
+ 1823, /* GL_VERTEX_ATTRIB_ARRAY_TYPE */
+ 334, /* GL_CURRENT_VERTEX_ATTRIB */
+ 1228, /* GL_PROGRAM_LENGTH_ARB */
+ 1242, /* GL_PROGRAM_STRING_ARB */
+ 986, /* GL_MODELVIEW_PROJECTION_NV */
+ 615, /* GL_IDENTITY_NV */
+ 662, /* GL_INVERSE_NV */
+ 1739, /* GL_TRANSPOSE_NV */
+ 663, /* GL_INVERSE_TRANSPOSE_NV */
+ 893, /* GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB */
+ 892, /* GL_MAX_PROGRAM_MATRICES_ARB */
+ 800, /* GL_MATRIX0_NV */
+ 812, /* GL_MATRIX1_NV */
+ 824, /* GL_MATRIX2_NV */
+ 828, /* GL_MATRIX3_NV */
+ 830, /* GL_MATRIX4_NV */
+ 832, /* GL_MATRIX5_NV */
+ 834, /* GL_MATRIX6_NV */
+ 836, /* GL_MATRIX7_NV */
+ 318, /* GL_CURRENT_MATRIX_STACK_DEPTH_ARB */
+ 315, /* GL_CURRENT_MATRIX_ARB */
+ 1829, /* GL_VERTEX_PROGRAM_POINT_SIZE */
+ 1832, /* GL_VERTEX_PROGRAM_TWO_SIDE */
+ 1240, /* GL_PROGRAM_PARAMETER_NV */
+ 1817, /* GL_VERTEX_ATTRIB_ARRAY_POINTER */
+ 1244, /* GL_PROGRAM_TARGET_NV */
+ 1241, /* GL_PROGRAM_RESIDENT_NV */
+ 1731, /* GL_TRACK_MATRIX_NV */
+ 1732, /* GL_TRACK_MATRIX_TRANSFORM_NV */
+ 1827, /* GL_VERTEX_PROGRAM_BINDING_NV */
+ 1222, /* GL_PROGRAM_ERROR_POSITION_ARB */
+ 355, /* GL_DEPTH_CLAMP */
+ 1795, /* GL_VERTEX_ATTRIB_ARRAY0_NV */
+ 1802, /* GL_VERTEX_ATTRIB_ARRAY1_NV */
+ 1803, /* GL_VERTEX_ATTRIB_ARRAY2_NV */
+ 1804, /* GL_VERTEX_ATTRIB_ARRAY3_NV */
+ 1805, /* GL_VERTEX_ATTRIB_ARRAY4_NV */
+ 1806, /* GL_VERTEX_ATTRIB_ARRAY5_NV */
+ 1807, /* GL_VERTEX_ATTRIB_ARRAY6_NV */
+ 1808, /* GL_VERTEX_ATTRIB_ARRAY7_NV */
+ 1809, /* GL_VERTEX_ATTRIB_ARRAY8_NV */
+ 1810, /* GL_VERTEX_ATTRIB_ARRAY9_NV */
+ 1796, /* GL_VERTEX_ATTRIB_ARRAY10_NV */
+ 1797, /* GL_VERTEX_ATTRIB_ARRAY11_NV */
+ 1798, /* GL_VERTEX_ATTRIB_ARRAY12_NV */
+ 1799, /* GL_VERTEX_ATTRIB_ARRAY13_NV */
+ 1800, /* GL_VERTEX_ATTRIB_ARRAY14_NV */
+ 1801, /* GL_VERTEX_ATTRIB_ARRAY15_NV */
+ 748, /* GL_MAP1_VERTEX_ATTRIB0_4_NV */
+ 755, /* GL_MAP1_VERTEX_ATTRIB1_4_NV */
+ 756, /* GL_MAP1_VERTEX_ATTRIB2_4_NV */
+ 757, /* GL_MAP1_VERTEX_ATTRIB3_4_NV */
+ 758, /* GL_MAP1_VERTEX_ATTRIB4_4_NV */
+ 759, /* GL_MAP1_VERTEX_ATTRIB5_4_NV */
+ 760, /* GL_MAP1_VERTEX_ATTRIB6_4_NV */
+ 761, /* GL_MAP1_VERTEX_ATTRIB7_4_NV */
+ 762, /* GL_MAP1_VERTEX_ATTRIB8_4_NV */
+ 763, /* GL_MAP1_VERTEX_ATTRIB9_4_NV */
+ 749, /* GL_MAP1_VERTEX_ATTRIB10_4_NV */
+ 750, /* GL_MAP1_VERTEX_ATTRIB11_4_NV */
+ 751, /* GL_MAP1_VERTEX_ATTRIB12_4_NV */
+ 752, /* GL_MAP1_VERTEX_ATTRIB13_4_NV */
+ 753, /* GL_MAP1_VERTEX_ATTRIB14_4_NV */
+ 754, /* GL_MAP1_VERTEX_ATTRIB15_4_NV */
+ 775, /* GL_MAP2_VERTEX_ATTRIB0_4_NV */
+ 782, /* GL_MAP2_VERTEX_ATTRIB1_4_NV */
+ 783, /* GL_MAP2_VERTEX_ATTRIB2_4_NV */
+ 784, /* GL_MAP2_VERTEX_ATTRIB3_4_NV */
+ 785, /* GL_MAP2_VERTEX_ATTRIB4_4_NV */
+ 786, /* GL_MAP2_VERTEX_ATTRIB5_4_NV */
+ 787, /* GL_MAP2_VERTEX_ATTRIB6_4_NV */
+ 1221, /* GL_PROGRAM_BINDING_ARB */
+ 789, /* GL_MAP2_VERTEX_ATTRIB8_4_NV */
+ 790, /* GL_MAP2_VERTEX_ATTRIB9_4_NV */
+ 776, /* GL_MAP2_VERTEX_ATTRIB10_4_NV */
+ 777, /* GL_MAP2_VERTEX_ATTRIB11_4_NV */
+ 778, /* GL_MAP2_VERTEX_ATTRIB12_4_NV */
+ 779, /* GL_MAP2_VERTEX_ATTRIB13_4_NV */
+ 780, /* GL_MAP2_VERTEX_ATTRIB14_4_NV */
+ 781, /* GL_MAP2_VERTEX_ATTRIB15_4_NV */
+ 1647, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE */
+ 1644, /* GL_TEXTURE_COMPRESSED */
+ 1025, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS */
+ 269, /* GL_COMPRESSED_TEXTURE_FORMATS */
+ 934, /* GL_MAX_VERTEX_UNITS_ARB */
22, /* GL_ACTIVE_VERTEX_UNITS_ARB */
- 1738, /* GL_WEIGHT_SUM_UNITY_ARB */
- 1716, /* GL_VERTEX_BLEND_ARB */
- 302, /* GL_CURRENT_WEIGHT_ARB */
- 1737, /* GL_WEIGHT_ARRAY_TYPE_ARB */
- 1736, /* GL_WEIGHT_ARRAY_STRIDE_ARB */
- 1735, /* GL_WEIGHT_ARRAY_SIZE_ARB */
- 1734, /* GL_WEIGHT_ARRAY_POINTER_ARB */
- 1731, /* GL_WEIGHT_ARRAY_ARB */
- 345, /* GL_DOT3_RGB */
- 346, /* GL_DOT3_RGBA */
- 237, /* GL_COMPRESSED_RGB_FXT1_3DFX */
- 232, /* GL_COMPRESSED_RGBA_FXT1_3DFX */
- 937, /* GL_MULTISAMPLE_3DFX */
- 1309, /* GL_SAMPLE_BUFFERS_3DFX */
- 1300, /* GL_SAMPLES_3DFX */
- 918, /* GL_MODELVIEW2_ARB */
- 921, /* GL_MODELVIEW3_ARB */
- 922, /* GL_MODELVIEW4_ARB */
- 923, /* GL_MODELVIEW5_ARB */
- 924, /* GL_MODELVIEW6_ARB */
- 925, /* GL_MODELVIEW7_ARB */
- 926, /* GL_MODELVIEW8_ARB */
- 927, /* GL_MODELVIEW9_ARB */
- 897, /* GL_MODELVIEW10_ARB */
- 898, /* GL_MODELVIEW11_ARB */
- 899, /* GL_MODELVIEW12_ARB */
- 900, /* GL_MODELVIEW13_ARB */
- 901, /* GL_MODELVIEW14_ARB */
- 902, /* GL_MODELVIEW15_ARB */
- 903, /* GL_MODELVIEW16_ARB */
- 904, /* GL_MODELVIEW17_ARB */
- 905, /* GL_MODELVIEW18_ARB */
- 906, /* GL_MODELVIEW19_ARB */
- 908, /* GL_MODELVIEW20_ARB */
- 909, /* GL_MODELVIEW21_ARB */
- 910, /* GL_MODELVIEW22_ARB */
- 911, /* GL_MODELVIEW23_ARB */
- 912, /* GL_MODELVIEW24_ARB */
- 913, /* GL_MODELVIEW25_ARB */
- 914, /* GL_MODELVIEW26_ARB */
- 915, /* GL_MODELVIEW27_ARB */
- 916, /* GL_MODELVIEW28_ARB */
- 917, /* GL_MODELVIEW29_ARB */
- 919, /* GL_MODELVIEW30_ARB */
- 920, /* GL_MODELVIEW31_ARB */
- 350, /* GL_DOT3_RGB_EXT */
- 348, /* GL_DOT3_RGBA_EXT */
- 891, /* GL_MIRROR_CLAMP_EXT */
- 894, /* GL_MIRROR_CLAMP_TO_EDGE_EXT */
- 932, /* GL_MODULATE_ADD_ATI */
- 933, /* GL_MODULATE_SIGNED_ADD_ATI */
- 934, /* GL_MODULATE_SUBTRACT_ATI */
- 1744, /* GL_YCBCR_MESA */
- 1023, /* GL_PACK_INVERT_MESA */
- 305, /* GL_DEBUG_OBJECT_MESA */
- 306, /* GL_DEBUG_PRINT_MESA */
- 304, /* GL_DEBUG_ASSERT_MESA */
- 106, /* GL_BUFFER_SIZE */
- 108, /* GL_BUFFER_USAGE */
- 1397, /* GL_STENCIL_BACK_FUNC */
- 1395, /* GL_STENCIL_BACK_FAIL */
- 1399, /* GL_STENCIL_BACK_PASS_DEPTH_FAIL */
- 1401, /* GL_STENCIL_BACK_PASS_DEPTH_PASS */
- 483, /* GL_FRAGMENT_PROGRAM_ARB */
- 1157, /* GL_PROGRAM_ALU_INSTRUCTIONS_ARB */
- 1185, /* GL_PROGRAM_TEX_INSTRUCTIONS_ARB */
- 1184, /* GL_PROGRAM_TEX_INDIRECTIONS_ARB */
- 1169, /* GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
- 1175, /* GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
- 1174, /* GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
- 827, /* GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB */
- 850, /* GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB */
- 849, /* GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB */
- 840, /* GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
- 846, /* GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
- 845, /* GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
- 810, /* GL_MAX_DRAW_BUFFERS */
- 354, /* GL_DRAW_BUFFER0 */
- 357, /* GL_DRAW_BUFFER1 */
- 378, /* GL_DRAW_BUFFER2 */
- 381, /* GL_DRAW_BUFFER3 */
- 384, /* GL_DRAW_BUFFER4 */
- 387, /* GL_DRAW_BUFFER5 */
- 390, /* GL_DRAW_BUFFER6 */
- 393, /* GL_DRAW_BUFFER7 */
- 396, /* GL_DRAW_BUFFER8 */
- 399, /* GL_DRAW_BUFFER9 */
- 358, /* GL_DRAW_BUFFER10 */
- 361, /* GL_DRAW_BUFFER11 */
- 364, /* GL_DRAW_BUFFER12 */
- 367, /* GL_DRAW_BUFFER13 */
- 370, /* GL_DRAW_BUFFER14 */
- 373, /* GL_DRAW_BUFFER15 */
- 81, /* GL_BLEND_EQUATION_ALPHA */
- 790, /* GL_MATRIX_PALETTE_ARB */
- 821, /* GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB */
- 824, /* GL_MAX_PALETTE_MATRICES_ARB */
- 288, /* GL_CURRENT_PALETTE_MATRIX_ARB */
- 784, /* GL_MATRIX_INDEX_ARRAY_ARB */
- 283, /* GL_CURRENT_MATRIX_INDEX_ARB */
- 786, /* GL_MATRIX_INDEX_ARRAY_SIZE_ARB */
- 788, /* GL_MATRIX_INDEX_ARRAY_TYPE_ARB */
- 787, /* GL_MATRIX_INDEX_ARRAY_STRIDE_ARB */
- 785, /* GL_MATRIX_INDEX_ARRAY_POINTER_ARB */
- 1575, /* GL_TEXTURE_DEPTH_SIZE */
- 338, /* GL_DEPTH_TEXTURE_MODE */
- 1541, /* GL_TEXTURE_COMPARE_MODE */
- 1539, /* GL_TEXTURE_COMPARE_FUNC */
- 216, /* GL_COMPARE_R_TO_TEXTURE */
- 1091, /* GL_POINT_SPRITE */
- 265, /* GL_COORD_REPLACE */
- 1095, /* GL_POINT_SPRITE_R_MODE_NV */
- 1212, /* GL_QUERY_COUNTER_BITS */
- 290, /* GL_CURRENT_QUERY */
- 1214, /* GL_QUERY_RESULT */
- 1216, /* GL_QUERY_RESULT_AVAILABLE */
- 871, /* GL_MAX_VERTEX_ATTRIBS */
- 1706, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED */
- 336, /* GL_DEPTH_STENCIL_TO_RGBA_NV */
- 335, /* GL_DEPTH_STENCIL_TO_BGRA_NV */
- 857, /* GL_MAX_TEXTURE_COORDS */
- 859, /* GL_MAX_TEXTURE_IMAGE_UNITS */
- 1162, /* GL_PROGRAM_ERROR_STRING_ARB */
- 1164, /* GL_PROGRAM_FORMAT_ASCII_ARB */
- 1163, /* GL_PROGRAM_FORMAT_ARB */
- 1620, /* GL_TEXTURE_UNSIGNED_REMAP_MODE_NV */
- 317, /* GL_DEPTH_BOUNDS_TEST_EXT */
- 316, /* GL_DEPTH_BOUNDS_EXT */
- 52, /* GL_ARRAY_BUFFER */
- 419, /* GL_ELEMENT_ARRAY_BUFFER */
- 53, /* GL_ARRAY_BUFFER_BINDING */
- 420, /* GL_ELEMENT_ARRAY_BUFFER_BINDING */
- 1680, /* GL_VERTEX_ARRAY_BUFFER_BINDING */
- 958, /* GL_NORMAL_ARRAY_BUFFER_BINDING */
- 139, /* GL_COLOR_ARRAY_BUFFER_BINDING */
- 577, /* GL_INDEX_ARRAY_BUFFER_BINDING */
- 1554, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING */
- 415, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING */
- 1321, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING */
- 461, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING */
- 1732, /* GL_WEIGHT_ARRAY_BUFFER_BINDING */
- 1702, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING */
- 1165, /* GL_PROGRAM_INSTRUCTIONS_ARB */
- 833, /* GL_MAX_PROGRAM_INSTRUCTIONS_ARB */
- 1171, /* GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
- 842, /* GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
- 1183, /* GL_PROGRAM_TEMPORARIES_ARB */
- 848, /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
- 1173, /* GL_PROGRAM_NATIVE_TEMPORARIES_ARB */
- 844, /* GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB */
- 1177, /* GL_PROGRAM_PARAMETERS_ARB */
- 847, /* GL_MAX_PROGRAM_PARAMETERS_ARB */
- 1172, /* GL_PROGRAM_NATIVE_PARAMETERS_ARB */
- 843, /* GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB */
- 1158, /* GL_PROGRAM_ATTRIBS_ARB */
- 828, /* GL_MAX_PROGRAM_ATTRIBS_ARB */
- 1170, /* GL_PROGRAM_NATIVE_ATTRIBS_ARB */
- 841, /* GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB */
- 1156, /* GL_PROGRAM_ADDRESS_REGISTERS_ARB */
- 826, /* GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB */
- 1168, /* GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
- 839, /* GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
- 834, /* GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB */
- 830, /* GL_MAX_PROGRAM_ENV_PARAMETERS_ARB */
- 1186, /* GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB */
- 1631, /* GL_TRANSPOSE_CURRENT_MATRIX_ARB */
- 1224, /* GL_READ_ONLY */
- 1740, /* GL_WRITE_ONLY */
- 1226, /* GL_READ_WRITE */
- 100, /* GL_BUFFER_ACCESS */
- 102, /* GL_BUFFER_MAPPED */
- 104, /* GL_BUFFER_MAP_POINTER */
- 1625, /* GL_TIME_ELAPSED_EXT */
- 744, /* GL_MATRIX0_ARB */
- 756, /* GL_MATRIX1_ARB */
- 768, /* GL_MATRIX2_ARB */
- 772, /* GL_MATRIX3_ARB */
- 774, /* GL_MATRIX4_ARB */
- 776, /* GL_MATRIX5_ARB */
- 778, /* GL_MATRIX6_ARB */
- 780, /* GL_MATRIX7_ARB */
- 782, /* GL_MATRIX8_ARB */
- 783, /* GL_MATRIX9_ARB */
- 746, /* GL_MATRIX10_ARB */
- 747, /* GL_MATRIX11_ARB */
- 748, /* GL_MATRIX12_ARB */
- 749, /* GL_MATRIX13_ARB */
- 750, /* GL_MATRIX14_ARB */
- 751, /* GL_MATRIX15_ARB */
- 752, /* GL_MATRIX16_ARB */
- 753, /* GL_MATRIX17_ARB */
- 754, /* GL_MATRIX18_ARB */
- 755, /* GL_MATRIX19_ARB */
- 758, /* GL_MATRIX20_ARB */
- 759, /* GL_MATRIX21_ARB */
- 760, /* GL_MATRIX22_ARB */
- 761, /* GL_MATRIX23_ARB */
- 762, /* GL_MATRIX24_ARB */
- 763, /* GL_MATRIX25_ARB */
- 764, /* GL_MATRIX26_ARB */
- 765, /* GL_MATRIX27_ARB */
- 766, /* GL_MATRIX28_ARB */
- 767, /* GL_MATRIX29_ARB */
- 770, /* GL_MATRIX30_ARB */
- 771, /* GL_MATRIX31_ARB */
- 1427, /* GL_STREAM_DRAW */
- 1429, /* GL_STREAM_READ */
- 1425, /* GL_STREAM_COPY */
- 1389, /* GL_STATIC_DRAW */
- 1391, /* GL_STATIC_READ */
- 1387, /* GL_STATIC_COPY */
- 409, /* GL_DYNAMIC_DRAW */
- 411, /* GL_DYNAMIC_READ */
- 407, /* GL_DYNAMIC_COPY */
- 533, /* GL_GL_PIXEL_PACK_BUFFER */
- 535, /* GL_GL_PIXEL_UNPACK_BUFFER */
- 534, /* GL_GL_PIXEL_PACK_BUFFER_BINDING */
- 536, /* GL_GL_PIXEL_UNPACK_BUFFER_BINDING */
- 831, /* GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */
- 829, /* GL_MAX_PROGRAM_CALL_DEPTH_NV */
- 832, /* GL_MAX_PROGRAM_IF_DEPTH_NV */
- 836, /* GL_MAX_PROGRAM_LOOP_DEPTH_NV */
- 835, /* GL_MAX_PROGRAM_LOOP_COUNT_NV */
- 793, /* GL_MAX_ARRAY_TEXTURE_LAYERS_EXT */
- 1421, /* GL_STENCIL_TEST_TWO_SIDE_EXT */
+ 1848, /* GL_WEIGHT_SUM_UNITY_ARB */
+ 1825, /* GL_VERTEX_BLEND_ARB */
+ 336, /* GL_CURRENT_WEIGHT_ARB */
+ 1847, /* GL_WEIGHT_ARRAY_TYPE_ARB */
+ 1846, /* GL_WEIGHT_ARRAY_STRIDE_ARB */
+ 1845, /* GL_WEIGHT_ARRAY_SIZE_ARB */
+ 1844, /* GL_WEIGHT_ARRAY_POINTER_ARB */
+ 1841, /* GL_WEIGHT_ARRAY_ARB */
+ 384, /* GL_DOT3_RGB */
+ 385, /* GL_DOT3_RGBA */
+ 263, /* GL_COMPRESSED_RGB_FXT1_3DFX */
+ 258, /* GL_COMPRESSED_RGBA_FXT1_3DFX */
+ 994, /* GL_MULTISAMPLE_3DFX */
+ 1387, /* GL_SAMPLE_BUFFERS_3DFX */
+ 1378, /* GL_SAMPLES_3DFX */
+ 975, /* GL_MODELVIEW2_ARB */
+ 978, /* GL_MODELVIEW3_ARB */
+ 979, /* GL_MODELVIEW4_ARB */
+ 980, /* GL_MODELVIEW5_ARB */
+ 981, /* GL_MODELVIEW6_ARB */
+ 982, /* GL_MODELVIEW7_ARB */
+ 983, /* GL_MODELVIEW8_ARB */
+ 984, /* GL_MODELVIEW9_ARB */
+ 954, /* GL_MODELVIEW10_ARB */
+ 955, /* GL_MODELVIEW11_ARB */
+ 956, /* GL_MODELVIEW12_ARB */
+ 957, /* GL_MODELVIEW13_ARB */
+ 958, /* GL_MODELVIEW14_ARB */
+ 959, /* GL_MODELVIEW15_ARB */
+ 960, /* GL_MODELVIEW16_ARB */
+ 961, /* GL_MODELVIEW17_ARB */
+ 962, /* GL_MODELVIEW18_ARB */
+ 963, /* GL_MODELVIEW19_ARB */
+ 965, /* GL_MODELVIEW20_ARB */
+ 966, /* GL_MODELVIEW21_ARB */
+ 967, /* GL_MODELVIEW22_ARB */
+ 968, /* GL_MODELVIEW23_ARB */
+ 969, /* GL_MODELVIEW24_ARB */
+ 970, /* GL_MODELVIEW25_ARB */
+ 971, /* GL_MODELVIEW26_ARB */
+ 972, /* GL_MODELVIEW27_ARB */
+ 973, /* GL_MODELVIEW28_ARB */
+ 974, /* GL_MODELVIEW29_ARB */
+ 976, /* GL_MODELVIEW30_ARB */
+ 977, /* GL_MODELVIEW31_ARB */
+ 389, /* GL_DOT3_RGB_EXT */
+ 387, /* GL_DOT3_RGBA_EXT */
+ 948, /* GL_MIRROR_CLAMP_EXT */
+ 951, /* GL_MIRROR_CLAMP_TO_EDGE_EXT */
+ 989, /* GL_MODULATE_ADD_ATI */
+ 990, /* GL_MODULATE_SIGNED_ADD_ATI */
+ 991, /* GL_MODULATE_SUBTRACT_ATI */
+ 1854, /* GL_YCBCR_MESA */
+ 1081, /* GL_PACK_INVERT_MESA */
+ 339, /* GL_DEBUG_OBJECT_MESA */
+ 340, /* GL_DEBUG_PRINT_MESA */
+ 338, /* GL_DEBUG_ASSERT_MESA */
+ 110, /* GL_BUFFER_SIZE */
+ 112, /* GL_BUFFER_USAGE */
+ 116, /* GL_BUMP_ROT_MATRIX_ATI */
+ 117, /* GL_BUMP_ROT_MATRIX_SIZE_ATI */
+ 115, /* GL_BUMP_NUM_TEX_UNITS_ATI */
+ 119, /* GL_BUMP_TEX_UNITS_ATI */
+ 448, /* GL_DUDV_ATI */
+ 447, /* GL_DU8DV8_ATI */
+ 114, /* GL_BUMP_ENVMAP_ATI */
+ 118, /* GL_BUMP_TARGET_ATI */
+ 1486, /* GL_STENCIL_BACK_FUNC */
+ 1484, /* GL_STENCIL_BACK_FAIL */
+ 1488, /* GL_STENCIL_BACK_PASS_DEPTH_FAIL */
+ 1490, /* GL_STENCIL_BACK_PASS_DEPTH_PASS */
+ 532, /* GL_FRAGMENT_PROGRAM_ARB */
+ 1219, /* GL_PROGRAM_ALU_INSTRUCTIONS_ARB */
+ 1247, /* GL_PROGRAM_TEX_INSTRUCTIONS_ARB */
+ 1246, /* GL_PROGRAM_TEX_INDIRECTIONS_ARB */
+ 1231, /* GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
+ 1237, /* GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
+ 1236, /* GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
+ 882, /* GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB */
+ 905, /* GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB */
+ 904, /* GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB */
+ 895, /* GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
+ 901, /* GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
+ 900, /* GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
+ 865, /* GL_MAX_DRAW_BUFFERS */
+ 393, /* GL_DRAW_BUFFER0 */
+ 396, /* GL_DRAW_BUFFER1 */
+ 417, /* GL_DRAW_BUFFER2 */
+ 420, /* GL_DRAW_BUFFER3 */
+ 423, /* GL_DRAW_BUFFER4 */
+ 426, /* GL_DRAW_BUFFER5 */
+ 429, /* GL_DRAW_BUFFER6 */
+ 432, /* GL_DRAW_BUFFER7 */
+ 435, /* GL_DRAW_BUFFER8 */
+ 438, /* GL_DRAW_BUFFER9 */
+ 397, /* GL_DRAW_BUFFER10 */
+ 400, /* GL_DRAW_BUFFER11 */
+ 403, /* GL_DRAW_BUFFER12 */
+ 406, /* GL_DRAW_BUFFER13 */
+ 409, /* GL_DRAW_BUFFER14 */
+ 412, /* GL_DRAW_BUFFER15 */
+ 82, /* GL_BLEND_EQUATION_ALPHA */
+ 845, /* GL_MATRIX_PALETTE_ARB */
+ 876, /* GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB */
+ 879, /* GL_MAX_PALETTE_MATRICES_ARB */
+ 321, /* GL_CURRENT_PALETTE_MATRIX_ARB */
+ 839, /* GL_MATRIX_INDEX_ARRAY_ARB */
+ 316, /* GL_CURRENT_MATRIX_INDEX_ARB */
+ 841, /* GL_MATRIX_INDEX_ARRAY_SIZE_ARB */
+ 843, /* GL_MATRIX_INDEX_ARRAY_TYPE_ARB */
+ 842, /* GL_MATRIX_INDEX_ARRAY_STRIDE_ARB */
+ 840, /* GL_MATRIX_INDEX_ARRAY_POINTER_ARB */
+ 1674, /* GL_TEXTURE_DEPTH_SIZE */
+ 377, /* GL_DEPTH_TEXTURE_MODE */
+ 1639, /* GL_TEXTURE_COMPARE_MODE */
+ 1637, /* GL_TEXTURE_COMPARE_FUNC */
+ 242, /* GL_COMPARE_R_TO_TEXTURE */
+ 1153, /* GL_POINT_SPRITE */
+ 296, /* GL_COORD_REPLACE */
+ 1157, /* GL_POINT_SPRITE_R_MODE_NV */
+ 1276, /* GL_QUERY_COUNTER_BITS */
+ 323, /* GL_CURRENT_QUERY */
+ 1278, /* GL_QUERY_RESULT */
+ 1280, /* GL_QUERY_RESULT_AVAILABLE */
+ 928, /* GL_MAX_VERTEX_ATTRIBS */
+ 1815, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED */
+ 375, /* GL_DEPTH_STENCIL_TO_RGBA_NV */
+ 374, /* GL_DEPTH_STENCIL_TO_BGRA_NV */
+ 914, /* GL_MAX_TEXTURE_COORDS */
+ 916, /* GL_MAX_TEXTURE_IMAGE_UNITS */
+ 1224, /* GL_PROGRAM_ERROR_STRING_ARB */
+ 1226, /* GL_PROGRAM_FORMAT_ASCII_ARB */
+ 1225, /* GL_PROGRAM_FORMAT_ARB */
+ 1723, /* GL_TEXTURE_UNSIGNED_REMAP_MODE_NV */
+ 353, /* GL_DEPTH_BOUNDS_TEST_EXT */
+ 352, /* GL_DEPTH_BOUNDS_EXT */
+ 53, /* GL_ARRAY_BUFFER */
+ 461, /* GL_ELEMENT_ARRAY_BUFFER */
+ 54, /* GL_ARRAY_BUFFER_BINDING */
+ 462, /* GL_ELEMENT_ARRAY_BUFFER_BINDING */
+ 1789, /* GL_VERTEX_ARRAY_BUFFER_BINDING */
+ 1015, /* GL_NORMAL_ARRAY_BUFFER_BINDING */
+ 149, /* GL_COLOR_ARRAY_BUFFER_BINDING */
+ 624, /* GL_INDEX_ARRAY_BUFFER_BINDING */
+ 1652, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING */
+ 457, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING */
+ 1399, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING */
+ 510, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING */
+ 1842, /* GL_WEIGHT_ARRAY_BUFFER_BINDING */
+ 1811, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING */
+ 1227, /* GL_PROGRAM_INSTRUCTIONS_ARB */
+ 888, /* GL_MAX_PROGRAM_INSTRUCTIONS_ARB */
+ 1233, /* GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
+ 897, /* GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
+ 1245, /* GL_PROGRAM_TEMPORARIES_ARB */
+ 903, /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
+ 1235, /* GL_PROGRAM_NATIVE_TEMPORARIES_ARB */
+ 899, /* GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB */
+ 1239, /* GL_PROGRAM_PARAMETERS_ARB */
+ 902, /* GL_MAX_PROGRAM_PARAMETERS_ARB */
+ 1234, /* GL_PROGRAM_NATIVE_PARAMETERS_ARB */
+ 898, /* GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB */
+ 1220, /* GL_PROGRAM_ATTRIBS_ARB */
+ 883, /* GL_MAX_PROGRAM_ATTRIBS_ARB */
+ 1232, /* GL_PROGRAM_NATIVE_ATTRIBS_ARB */
+ 896, /* GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB */
+ 1218, /* GL_PROGRAM_ADDRESS_REGISTERS_ARB */
+ 881, /* GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB */
+ 1230, /* GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
+ 894, /* GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
+ 889, /* GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB */
+ 885, /* GL_MAX_PROGRAM_ENV_PARAMETERS_ARB */
+ 1248, /* GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB */
+ 1736, /* GL_TRANSPOSE_CURRENT_MATRIX_ARB */
+ 1289, /* GL_READ_ONLY */
+ 1850, /* GL_WRITE_ONLY */
+ 1291, /* GL_READ_WRITE */
+ 102, /* GL_BUFFER_ACCESS */
+ 105, /* GL_BUFFER_MAPPED */
+ 107, /* GL_BUFFER_MAP_POINTER */
+ 1730, /* GL_TIME_ELAPSED_EXT */
+ 799, /* GL_MATRIX0_ARB */
+ 811, /* GL_MATRIX1_ARB */
+ 823, /* GL_MATRIX2_ARB */
+ 827, /* GL_MATRIX3_ARB */
+ 829, /* GL_MATRIX4_ARB */
+ 831, /* GL_MATRIX5_ARB */
+ 833, /* GL_MATRIX6_ARB */
+ 835, /* GL_MATRIX7_ARB */
+ 837, /* GL_MATRIX8_ARB */
+ 838, /* GL_MATRIX9_ARB */
+ 801, /* GL_MATRIX10_ARB */
+ 802, /* GL_MATRIX11_ARB */
+ 803, /* GL_MATRIX12_ARB */
+ 804, /* GL_MATRIX13_ARB */
+ 805, /* GL_MATRIX14_ARB */
+ 806, /* GL_MATRIX15_ARB */
+ 807, /* GL_MATRIX16_ARB */
+ 808, /* GL_MATRIX17_ARB */
+ 809, /* GL_MATRIX18_ARB */
+ 810, /* GL_MATRIX19_ARB */
+ 813, /* GL_MATRIX20_ARB */
+ 814, /* GL_MATRIX21_ARB */
+ 815, /* GL_MATRIX22_ARB */
+ 816, /* GL_MATRIX23_ARB */
+ 817, /* GL_MATRIX24_ARB */
+ 818, /* GL_MATRIX25_ARB */
+ 819, /* GL_MATRIX26_ARB */
+ 820, /* GL_MATRIX27_ARB */
+ 821, /* GL_MATRIX28_ARB */
+ 822, /* GL_MATRIX29_ARB */
+ 825, /* GL_MATRIX30_ARB */
+ 826, /* GL_MATRIX31_ARB */
+ 1519, /* GL_STREAM_DRAW */
+ 1521, /* GL_STREAM_READ */
+ 1517, /* GL_STREAM_COPY */
+ 1477, /* GL_STATIC_DRAW */
+ 1479, /* GL_STATIC_READ */
+ 1475, /* GL_STATIC_COPY */
+ 451, /* GL_DYNAMIC_DRAW */
+ 453, /* GL_DYNAMIC_READ */
+ 449, /* GL_DYNAMIC_COPY */
+ 1121, /* GL_PIXEL_PACK_BUFFER */
+ 1125, /* GL_PIXEL_UNPACK_BUFFER */
+ 1122, /* GL_PIXEL_PACK_BUFFER_BINDING */
+ 1126, /* GL_PIXEL_UNPACK_BUFFER_BINDING */
+ 347, /* GL_DEPTH24_STENCIL8 */
+ 1720, /* GL_TEXTURE_STENCIL_SIZE */
+ 1672, /* GL_TEXTURE_CUBE_MAP_SEAMLESS */
+ 884, /* GL_MAX_PROGRAM_CALL_DEPTH_NV */
+ 887, /* GL_MAX_PROGRAM_IF_DEPTH_NV */
+ 891, /* GL_MAX_PROGRAM_LOOP_DEPTH_NV */
+ 890, /* GL_MAX_PROGRAM_LOOP_COUNT_NV */
+ 848, /* GL_MAX_ARRAY_TEXTURE_LAYERS_EXT */
+ 1510, /* GL_STENCIL_TEST_TWO_SIDE_EXT */
17, /* GL_ACTIVE_STENCIL_FACE_EXT */
- 892, /* GL_MIRROR_CLAMP_TO_BORDER_EXT */
- 1302, /* GL_SAMPLES_PASSED */
- 484, /* GL_FRAGMENT_SHADER */
- 1726, /* GL_VERTEX_SHADER */
- 1176, /* GL_PROGRAM_OBJECT_ARB */
- 1334, /* GL_SHADER_OBJECT_ARB */
- 817, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS */
- 875, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS */
- 869, /* GL_MAX_VARYING_FLOATS */
- 873, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS */
- 802, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */
- 983, /* GL_OBJECT_TYPE_ARB */
- 1336, /* GL_SHADER_TYPE */
- 449, /* GL_FLOAT_VEC2 */
- 451, /* GL_FLOAT_VEC3 */
- 453, /* GL_FLOAT_VEC4 */
- 604, /* GL_INT_VEC2 */
- 606, /* GL_INT_VEC3 */
- 608, /* GL_INT_VEC4 */
- 92, /* GL_BOOL */
- 94, /* GL_BOOL_VEC2 */
- 96, /* GL_BOOL_VEC3 */
- 98, /* GL_BOOL_VEC4 */
- 443, /* GL_FLOAT_MAT2 */
- 445, /* GL_FLOAT_MAT3 */
- 447, /* GL_FLOAT_MAT4 */
- 1293, /* GL_SAMPLER_1D */
- 1295, /* GL_SAMPLER_2D */
- 1297, /* GL_SAMPLER_3D */
- 1298, /* GL_SAMPLER_CUBE */
- 1294, /* GL_SAMPLER_1D_SHADOW */
- 1296, /* GL_SAMPLER_2D_SHADOW */
- 527, /* GL_GL_FLOAT_MAT2x3 */
- 528, /* GL_GL_FLOAT_MAT2x4 */
- 529, /* GL_GL_FLOAT_MAT3x2 */
- 530, /* GL_GL_FLOAT_MAT3x4 */
- 531, /* GL_GL_FLOAT_MAT4x2 */
- 532, /* GL_GL_FLOAT_MAT4x3 */
- 311, /* GL_DELETE_STATUS */
- 220, /* GL_COMPILE_STATUS */
- 657, /* GL_LINK_STATUS */
- 1675, /* GL_VALIDATE_STATUS */
- 589, /* GL_INFO_LOG_LENGTH */
- 55, /* GL_ATTACHED_SHADERS */
+ 949, /* GL_MIRROR_CLAMP_TO_BORDER_EXT */
+ 1380, /* GL_SAMPLES_PASSED */
+ 109, /* GL_BUFFER_SERIALIZED_MODIFY_APPLE */
+ 104, /* GL_BUFFER_FLUSHING_UNMAP_APPLE */
+ 533, /* GL_FRAGMENT_SHADER */
+ 1835, /* GL_VERTEX_SHADER */
+ 1238, /* GL_PROGRAM_OBJECT_ARB */
+ 1412, /* GL_SHADER_OBJECT_ARB */
+ 872, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS */
+ 932, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS */
+ 926, /* GL_MAX_VARYING_FLOATS */
+ 930, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS */
+ 857, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */
+ 1041, /* GL_OBJECT_TYPE_ARB */
+ 1414, /* GL_SHADER_TYPE */
+ 498, /* GL_FLOAT_VEC2 */
+ 500, /* GL_FLOAT_VEC3 */
+ 502, /* GL_FLOAT_VEC4 */
+ 651, /* GL_INT_VEC2 */
+ 653, /* GL_INT_VEC3 */
+ 655, /* GL_INT_VEC4 */
+ 94, /* GL_BOOL */
+ 96, /* GL_BOOL_VEC2 */
+ 98, /* GL_BOOL_VEC3 */
+ 100, /* GL_BOOL_VEC4 */
+ 486, /* GL_FLOAT_MAT2 */
+ 490, /* GL_FLOAT_MAT3 */
+ 494, /* GL_FLOAT_MAT4 */
+ 1371, /* GL_SAMPLER_1D */
+ 1373, /* GL_SAMPLER_2D */
+ 1375, /* GL_SAMPLER_3D */
+ 1376, /* GL_SAMPLER_CUBE */
+ 1372, /* GL_SAMPLER_1D_SHADOW */
+ 1374, /* GL_SAMPLER_2D_SHADOW */
+ 488, /* GL_FLOAT_MAT2x3 */
+ 489, /* GL_FLOAT_MAT2x4 */
+ 492, /* GL_FLOAT_MAT3x2 */
+ 493, /* GL_FLOAT_MAT3x4 */
+ 496, /* GL_FLOAT_MAT4x2 */
+ 497, /* GL_FLOAT_MAT4x3 */
+ 345, /* GL_DELETE_STATUS */
+ 246, /* GL_COMPILE_STATUS */
+ 706, /* GL_LINK_STATUS */
+ 1783, /* GL_VALIDATE_STATUS */
+ 636, /* GL_INFO_LOG_LENGTH */
+ 56, /* GL_ATTACHED_SHADERS */
20, /* GL_ACTIVE_UNIFORMS */
21, /* GL_ACTIVE_UNIFORM_MAX_LENGTH */
- 1335, /* GL_SHADER_SOURCE_LENGTH */
+ 1413, /* GL_SHADER_SOURCE_LENGTH */
15, /* GL_ACTIVE_ATTRIBUTES */
16, /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */
- 486, /* GL_FRAGMENT_SHADER_DERIVATIVE_HINT */
- 1338, /* GL_SHADING_LANGUAGE_VERSION */
- 289, /* GL_CURRENT_PROGRAM */
- 1032, /* GL_PALETTE4_RGB8_OES */
- 1034, /* GL_PALETTE4_RGBA8_OES */
- 1030, /* GL_PALETTE4_R5_G6_B5_OES */
- 1033, /* GL_PALETTE4_RGBA4_OES */
- 1031, /* GL_PALETTE4_RGB5_A1_OES */
- 1037, /* GL_PALETTE8_RGB8_OES */
- 1039, /* GL_PALETTE8_RGBA8_OES */
- 1035, /* GL_PALETTE8_R5_G6_B5_OES */
- 1038, /* GL_PALETTE8_RGBA4_OES */
- 1036, /* GL_PALETTE8_RGB5_A1_OES */
- 572, /* GL_IMPLEMENTATION_COLOR_READ_TYPE_OES */
- 571, /* GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES */
- 1509, /* GL_TEXTURE_1D_ARRAY_EXT */
- 1196, /* GL_PROXY_TEXTURE_1D_ARRAY_EXT */
- 1511, /* GL_TEXTURE_2D_ARRAY_EXT */
- 1199, /* GL_PROXY_TEXTURE_2D_ARRAY_EXT */
- 1517, /* GL_TEXTURE_BINDING_1D_ARRAY_EXT */
- 1519, /* GL_TEXTURE_BINDING_2D_ARRAY_EXT */
- 541, /* GL_GL_SRGB */
- 542, /* GL_GL_SRGB8 */
- 544, /* GL_GL_SRGB_ALPHA */
- 543, /* GL_GL_SRGB8_ALPHA8 */
- 540, /* GL_GL_SLUMINANCE_ALPHA */
- 539, /* GL_GL_SLUMINANCE8_ALPHA8 */
- 537, /* GL_GL_SLUMINANCE */
- 538, /* GL_GL_SLUMINANCE8 */
- 524, /* GL_GL_COMPRESSED_SRGB */
- 525, /* GL_GL_COMPRESSED_SRGB_ALPHA */
- 522, /* GL_GL_COMPRESSED_SLUMINANCE */
- 523, /* GL_GL_COMPRESSED_SLUMINANCE_ALPHA */
- 1093, /* GL_POINT_SPRITE_COORD_ORIGIN */
- 665, /* GL_LOWER_LEFT */
- 1672, /* GL_UPPER_LEFT */
- 1403, /* GL_STENCIL_BACK_REF */
- 1404, /* GL_STENCIL_BACK_VALUE_MASK */
- 1405, /* GL_STENCIL_BACK_WRITEMASK */
- 402, /* GL_DRAW_FRAMEBUFFER_BINDING_EXT */
- 1238, /* GL_RENDERBUFFER_BINDING_EXT */
- 1223, /* GL_READ_FRAMEBUFFER_EXT */
- 403, /* GL_DRAW_FRAMEBUFFER_EXT */
- 1222, /* GL_READ_FRAMEBUFFER_BINDING_EXT */
- 488, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT */
- 487, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT */
- 492, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT */
- 490, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT */
- 489, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT */
- 494, /* GL_FRAMEBUFFER_COMPLETE_EXT */
- 496, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT */
- 501, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT */
- 499, /* GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT */
- 497, /* GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT */
- 500, /* GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT */
- 498, /* GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT */
- 502, /* GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT */
- 504, /* GL_FRAMEBUFFER_UNSUPPORTED_EXT */
- 503, /* GL_FRAMEBUFFER_STATUS_ERROR_EXT */
- 799, /* GL_MAX_COLOR_ATTACHMENTS_EXT */
- 145, /* GL_COLOR_ATTACHMENT0_EXT */
- 152, /* GL_COLOR_ATTACHMENT1_EXT */
- 153, /* GL_COLOR_ATTACHMENT2_EXT */
- 154, /* GL_COLOR_ATTACHMENT3_EXT */
- 155, /* GL_COLOR_ATTACHMENT4_EXT */
- 156, /* GL_COLOR_ATTACHMENT5_EXT */
- 157, /* GL_COLOR_ATTACHMENT6_EXT */
- 158, /* GL_COLOR_ATTACHMENT7_EXT */
- 159, /* GL_COLOR_ATTACHMENT8_EXT */
- 160, /* GL_COLOR_ATTACHMENT9_EXT */
- 146, /* GL_COLOR_ATTACHMENT10_EXT */
- 147, /* GL_COLOR_ATTACHMENT11_EXT */
- 148, /* GL_COLOR_ATTACHMENT12_EXT */
- 149, /* GL_COLOR_ATTACHMENT13_EXT */
- 150, /* GL_COLOR_ATTACHMENT14_EXT */
- 151, /* GL_COLOR_ATTACHMENT15_EXT */
- 313, /* GL_DEPTH_ATTACHMENT_EXT */
- 1394, /* GL_STENCIL_ATTACHMENT_EXT */
- 495, /* GL_FRAMEBUFFER_EXT */
- 1239, /* GL_RENDERBUFFER_EXT */
- 1242, /* GL_RENDERBUFFER_WIDTH_EXT */
- 1240, /* GL_RENDERBUFFER_HEIGHT_EXT */
- 1241, /* GL_RENDERBUFFER_INTERNAL_FORMAT_EXT */
- 1416, /* GL_STENCIL_INDEX_EXT */
- 1413, /* GL_STENCIL_INDEX1_EXT */
- 1414, /* GL_STENCIL_INDEX4_EXT */
- 1415, /* GL_STENCIL_INDEX8_EXT */
- 1412, /* GL_STENCIL_INDEX16_EXT */
- 426, /* GL_EVAL_BIT */
- 1220, /* GL_RASTER_POSITION_UNCLIPPED_IBM */
- 659, /* GL_LIST_BIT */
- 1525, /* GL_TEXTURE_BIT */
- 1317, /* GL_SCISSOR_BIT */
+ 535, /* GL_FRAGMENT_SHADER_DERIVATIVE_HINT */
+ 1416, /* GL_SHADING_LANGUAGE_VERSION */
+ 322, /* GL_CURRENT_PROGRAM */
+ 1090, /* GL_PALETTE4_RGB8_OES */
+ 1092, /* GL_PALETTE4_RGBA8_OES */
+ 1088, /* GL_PALETTE4_R5_G6_B5_OES */
+ 1091, /* GL_PALETTE4_RGBA4_OES */
+ 1089, /* GL_PALETTE4_RGB5_A1_OES */
+ 1095, /* GL_PALETTE8_RGB8_OES */
+ 1097, /* GL_PALETTE8_RGBA8_OES */
+ 1093, /* GL_PALETTE8_R5_G6_B5_OES */
+ 1096, /* GL_PALETTE8_RGBA4_OES */
+ 1094, /* GL_PALETTE8_RGB5_A1_OES */
+ 618, /* GL_IMPLEMENTATION_COLOR_READ_TYPE_OES */
+ 617, /* GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES */
+ 1768, /* GL_UNSIGNED_NORMALIZED */
+ 1607, /* GL_TEXTURE_1D_ARRAY_EXT */
+ 1259, /* GL_PROXY_TEXTURE_1D_ARRAY_EXT */
+ 1609, /* GL_TEXTURE_2D_ARRAY_EXT */
+ 1262, /* GL_PROXY_TEXTURE_2D_ARRAY_EXT */
+ 1615, /* GL_TEXTURE_BINDING_1D_ARRAY_EXT */
+ 1617, /* GL_TEXTURE_BINDING_2D_ARRAY_EXT */
+ 1469, /* GL_SRGB */
+ 1470, /* GL_SRGB8 */
+ 1472, /* GL_SRGB_ALPHA */
+ 1471, /* GL_SRGB8_ALPHA8 */
+ 1429, /* GL_SLUMINANCE_ALPHA */
+ 1428, /* GL_SLUMINANCE8_ALPHA8 */
+ 1426, /* GL_SLUMINANCE */
+ 1427, /* GL_SLUMINANCE8 */
+ 267, /* GL_COMPRESSED_SRGB */
+ 268, /* GL_COMPRESSED_SRGB_ALPHA */
+ 265, /* GL_COMPRESSED_SLUMINANCE */
+ 266, /* GL_COMPRESSED_SLUMINANCE_ALPHA */
+ 1155, /* GL_POINT_SPRITE_COORD_ORIGIN */
+ 714, /* GL_LOWER_LEFT */
+ 1780, /* GL_UPPER_LEFT */
+ 1492, /* GL_STENCIL_BACK_REF */
+ 1493, /* GL_STENCIL_BACK_VALUE_MASK */
+ 1494, /* GL_STENCIL_BACK_WRITEMASK */
+ 442, /* GL_DRAW_FRAMEBUFFER_BINDING_EXT */
+ 1305, /* GL_RENDERBUFFER_BINDING_EXT */
+ 1286, /* GL_READ_FRAMEBUFFER */
+ 441, /* GL_DRAW_FRAMEBUFFER */
+ 1287, /* GL_READ_FRAMEBUFFER_BINDING_EXT */
+ 1315, /* GL_RENDERBUFFER_SAMPLES */
+ 545, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE */
+ 543, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME */
+ 554, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL */
+ 550, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE */
+ 552, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */
+ 557, /* GL_FRAMEBUFFER_COMPLETE */
+ 561, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT */
+ 567, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT */
+ 565, /* GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT */
+ 563, /* GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT */
+ 566, /* GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT */
+ 564, /* GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT */
+ 570, /* GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT */
+ 573, /* GL_FRAMEBUFFER_UNSUPPORTED */
+ 571, /* GL_FRAMEBUFFER_STATUS_ERROR_EXT */
+ 854, /* GL_MAX_COLOR_ATTACHMENTS_EXT */
+ 155, /* GL_COLOR_ATTACHMENT0 */
+ 157, /* GL_COLOR_ATTACHMENT1 */
+ 171, /* GL_COLOR_ATTACHMENT2 */
+ 173, /* GL_COLOR_ATTACHMENT3 */
+ 175, /* GL_COLOR_ATTACHMENT4 */
+ 177, /* GL_COLOR_ATTACHMENT5 */
+ 179, /* GL_COLOR_ATTACHMENT6 */
+ 181, /* GL_COLOR_ATTACHMENT7 */
+ 183, /* GL_COLOR_ATTACHMENT8 */
+ 185, /* GL_COLOR_ATTACHMENT9 */
+ 158, /* GL_COLOR_ATTACHMENT10 */
+ 160, /* GL_COLOR_ATTACHMENT11 */
+ 162, /* GL_COLOR_ATTACHMENT12 */
+ 164, /* GL_COLOR_ATTACHMENT13 */
+ 166, /* GL_COLOR_ATTACHMENT14 */
+ 168, /* GL_COLOR_ATTACHMENT15 */
+ 348, /* GL_DEPTH_ATTACHMENT */
+ 1482, /* GL_STENCIL_ATTACHMENT */
+ 536, /* GL_FRAMEBUFFER */
+ 1303, /* GL_RENDERBUFFER */
+ 1317, /* GL_RENDERBUFFER_WIDTH */
+ 1310, /* GL_RENDERBUFFER_HEIGHT */
+ 1312, /* GL_RENDERBUFFER_INTERNAL_FORMAT */
+ 1505, /* GL_STENCIL_INDEX_EXT */
+ 1502, /* GL_STENCIL_INDEX1_EXT */
+ 1503, /* GL_STENCIL_INDEX4_EXT */
+ 1504, /* GL_STENCIL_INDEX8_EXT */
+ 1501, /* GL_STENCIL_INDEX16_EXT */
+ 1314, /* GL_RENDERBUFFER_RED_SIZE */
+ 1309, /* GL_RENDERBUFFER_GREEN_SIZE */
+ 1306, /* GL_RENDERBUFFER_BLUE_SIZE */
+ 1304, /* GL_RENDERBUFFER_ALPHA_SIZE */
+ 1307, /* GL_RENDERBUFFER_DEPTH_SIZE */
+ 1316, /* GL_RENDERBUFFER_STENCIL_SIZE */
+ 569, /* GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE */
+ 910, /* GL_MAX_SAMPLES */
+ 1273, /* GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT */
+ 483, /* GL_FIRST_VERTEX_CONVENTION_EXT */
+ 666, /* GL_LAST_VERTEX_CONVENTION_EXT */
+ 1252, /* GL_PROVOKING_VERTEX_EXT */
+ 302, /* GL_COPY_READ_BUFFER */
+ 303, /* GL_COPY_WRITE_BUFFER */
+ 1364, /* GL_RGBA_SNORM */
+ 1360, /* GL_RGBA8_SNORM */
+ 1422, /* GL_SIGNED_NORMALIZED */
+ 911, /* GL_MAX_SERVER_WAIT_TIMEOUT */
+ 1040, /* GL_OBJECT_TYPE */
+ 1526, /* GL_SYNC_CONDITION */
+ 1531, /* GL_SYNC_STATUS */
+ 1528, /* GL_SYNC_FLAGS */
+ 1527, /* GL_SYNC_FENCE */
+ 1530, /* GL_SYNC_GPU_COMMANDS_COMPLETE */
+ 1757, /* GL_UNSIGNALED */
+ 1421, /* GL_SIGNALED */
+ 46, /* GL_ALREADY_SIGNALED */
+ 1728, /* GL_TIMEOUT_EXPIRED */
+ 270, /* GL_CONDITION_SATISFIED */
+ 1840, /* GL_WAIT_FAILED */
+ 468, /* GL_EVAL_BIT */
+ 1284, /* GL_RASTER_POSITION_UNCLIPPED_IBM */
+ 708, /* GL_LIST_BIT */
+ 1623, /* GL_TEXTURE_BIT */
+ 1395, /* GL_SCISSOR_BIT */
29, /* GL_ALL_ATTRIB_BITS */
- 939, /* GL_MULTISAMPLE_BIT */
+ 996, /* GL_MULTISAMPLE_BIT */
30, /* GL_ALL_CLIENT_ATTRIB_BITS */
+ 1729, /* GL_TIMEOUT_IGNORED */
};
-#define Elements(x) sizeof(x)/sizeof(*x)
-
typedef int (*cfunc)(const void *, const void *);
/**
@@ -4881,6 +5163,29 @@ const char *_mesa_lookup_enum_by_nr( int nr )
}
}
+/* Get the name of an enum given that it is a primitive type. Avoids
+ * GL_FALSE/GL_POINTS ambiguity and others.
+ */
+const char *_mesa_lookup_prim_by_nr( int nr )
+{
+ switch (nr) {
+ case GL_POINTS: return "GL_POINTS";
+ case GL_LINES: return "GL_LINES";
+ case GL_LINE_STRIP: return "GL_LINE_STRIP";
+ case GL_LINE_LOOP: return "GL_LINE_LOOP";
+ case GL_TRIANGLES: return "GL_TRIANGLES";
+ case GL_TRIANGLE_STRIP: return "GL_TRIANGLE_STRIP";
+ case GL_TRIANGLE_FAN: return "GL_TRIANGLE_FAN";
+ case GL_QUADS: return "GL_QUADS";
+ case GL_QUAD_STRIP: return "GL_QUAD_STRIP";
+ case GL_POLYGON: return "GL_POLYGON";
+ case GL_POLYGON+1: return "OUTSIDE_BEGIN_END";
+ default: return "<invalid>";
+ }
+}
+
+
+
int _mesa_lookup_enum_by_name( const char *symbol )
{
enum_elt * f = NULL;
diff --git a/src/mesa/main/enums.h b/src/mesa/main/enums.h
index 23a4767f35..b5f69001b8 100644
--- a/src/mesa/main/enums.h
+++ b/src/mesa/main/enums.h
@@ -40,6 +40,12 @@
#if defined(_HAVE_FULL_GL) && _HAVE_FULL_GL
extern const char *_mesa_lookup_enum_by_nr( int nr );
+
+/* Get the name of an enum given that it is a primitive type. Avoids
+ * GL_FALSE/GL_POINTS ambiguity and others.
+ */
+const char *_mesa_lookup_prim_by_nr( int nr );
+
extern int _mesa_lookup_enum_by_name( const char *symbol );
#else
diff --git a/src/mesa/main/eval.c b/src/mesa/main/eval.c
index 3f89f9c1ea..47f99270ce 100644
--- a/src/mesa/main/eval.c
+++ b/src/mesa/main/eval.c
@@ -44,6 +44,10 @@
#include "eval.h"
#include "macros.h"
#include "mtypes.h"
+#include "glapi/dispatch.h"
+
+
+#if FEATURE_eval
/*
@@ -797,6 +801,41 @@ _mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
}
+void
+_mesa_install_eval_vtxfmt(struct _glapi_table *disp,
+ const GLvertexformat *vfmt)
+{
+ SET_EvalCoord1f(disp, vfmt->EvalCoord1f);
+ SET_EvalCoord1fv(disp, vfmt->EvalCoord1fv);
+ SET_EvalCoord2f(disp, vfmt->EvalCoord2f);
+ SET_EvalCoord2fv(disp, vfmt->EvalCoord2fv);
+ SET_EvalPoint1(disp, vfmt->EvalPoint1);
+ SET_EvalPoint2(disp, vfmt->EvalPoint2);
+
+ SET_EvalMesh1(disp, vfmt->EvalMesh1);
+ SET_EvalMesh2(disp, vfmt->EvalMesh2);
+}
+
+
+void
+_mesa_init_eval_dispatch(struct _glapi_table *disp)
+{
+ SET_GetMapdv(disp, _mesa_GetMapdv);
+ SET_GetMapfv(disp, _mesa_GetMapfv);
+ SET_GetMapiv(disp, _mesa_GetMapiv);
+ SET_Map1d(disp, _mesa_Map1d);
+ SET_Map1f(disp, _mesa_Map1f);
+ SET_Map2d(disp, _mesa_Map2d);
+ SET_Map2f(disp, _mesa_Map2f);
+ SET_MapGrid1d(disp, _mesa_MapGrid1d);
+ SET_MapGrid1f(disp, _mesa_MapGrid1f);
+ SET_MapGrid2d(disp, _mesa_MapGrid2d);
+ SET_MapGrid2f(disp, _mesa_MapGrid2f);
+}
+
+
+#endif /* FEATURE_eval */
+
/**********************************************************************/
/***** Initialization *****/
diff --git a/src/mesa/main/eval.h b/src/mesa/main/eval.h
index b3ff0a96f8..49fd37a057 100644
--- a/src/mesa/main/eval.h
+++ b/src/mesa/main/eval.h
@@ -37,13 +37,22 @@
#define EVAL_H
-#include "mtypes.h"
+#include "main/mtypes.h"
-#if _HAVE_FULL_GL
-extern void _mesa_init_eval( GLcontext *ctx );
-extern void _mesa_free_eval_data( GLcontext *ctx );
+#if FEATURE_eval
+#define _MESA_INIT_EVAL_VTXFMT(vfmt, impl) \
+ do { \
+ (vfmt)->EvalCoord1f = impl ## EvalCoord1f; \
+ (vfmt)->EvalCoord1fv = impl ## EvalCoord1fv; \
+ (vfmt)->EvalCoord2f = impl ## EvalCoord2f; \
+ (vfmt)->EvalCoord2fv = impl ## EvalCoord2fv; \
+ (vfmt)->EvalPoint1 = impl ## EvalPoint1; \
+ (vfmt)->EvalPoint2 = impl ## EvalPoint2; \
+ (vfmt)->EvalMesh1 = impl ## EvalMesh1; \
+ (vfmt)->EvalMesh2 = impl ## EvalMesh2; \
+ } while (0)
extern GLuint _mesa_evaluator_components( GLenum target );
@@ -115,14 +124,32 @@ _mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v );
extern void GLAPIENTRY
_mesa_GetMapiv( GLenum target, GLenum query, GLint *v );
-#else
+extern void
+_mesa_install_eval_vtxfmt(struct _glapi_table *disp,
+ const GLvertexformat *vfmt);
+
+extern void
+_mesa_init_eval_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_eval */
+
+#define _MESA_INIT_EVAL_VTXFMT(vfmt, impl) do { } while (0)
-/** No-op */
-#define _mesa_init_eval( c ) ((void)0)
+static INLINE void
+_mesa_install_eval_vtxfmt(struct _glapi_table *disp,
+ const GLvertexformat *vfmt)
+{
+}
-/** No-op */
-#define _mesa_free_eval_data( c ) ((void)0)
+static INLINE void
+_mesa_init_eval_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_eval */
+
+extern void _mesa_init_eval( GLcontext *ctx );
+extern void _mesa_free_eval_data( GLcontext *ctx );
-#endif
-#endif
+#endif /* EVAL_H */
diff --git a/src/mesa/main/execmem.c b/src/mesa/main/execmem.c
index f95c31862a..57c1e117c8 100644
--- a/src/mesa/main/execmem.c
+++ b/src/mesa/main/execmem.c
@@ -24,7 +24,7 @@
/**
- * \file exemem.c
+ * \file execmem.c
* Functions for allocating executable memory.
*
* \author Keith Whitwell
@@ -36,7 +36,7 @@
-#if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__)
+#if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun)
/*
* Allocate a large block of memory which can hold code then dole it out
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index 9522f04ae5..5b54c1cf8c 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.3
+ * Version: 7.6
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -31,7 +32,7 @@
#include "mtypes.h"
-#define F(x) (int)(uintptr_t)&(((struct gl_extensions *)0)->x)
+#define F(x) offsetof(struct gl_extensions, x)
#define ON GL_TRUE
#define OFF GL_FALSE
@@ -44,26 +45,33 @@ static const struct {
const char *name;
int flag_offset;
} default_extensions[] = {
+ { OFF, "GL_ARB_copy_buffer", F(ARB_copy_buffer) },
{ OFF, "GL_ARB_depth_texture", F(ARB_depth_texture) },
- { OFF, "GL_ARB_draw_buffers", F(ARB_draw_buffers) },
+ { OFF, "GL_ARB_depth_clamp", F(ARB_depth_clamp) },
+ { ON, "GL_ARB_draw_buffers", F(ARB_draw_buffers) },
+ { OFF, "GL_ARB_draw_elements_base_vertex", F(ARB_draw_elements_base_vertex) },
{ OFF, "GL_ARB_fragment_program", F(ARB_fragment_program) },
{ OFF, "GL_ARB_fragment_program_shadow", F(ARB_fragment_program_shadow) },
{ OFF, "GL_ARB_fragment_shader", F(ARB_fragment_shader) },
+ { OFF, "GL_ARB_framebuffer_object", F(ARB_framebuffer_object) },
{ OFF, "GL_ARB_half_float_pixel", F(ARB_half_float_pixel) },
{ OFF, "GL_ARB_imaging", F(ARB_imaging) },
- { OFF, "GL_ARB_multisample", F(ARB_multisample) },
+ { OFF, "GL_ARB_map_buffer_range", F(ARB_map_buffer_range) },
+ { ON, "GL_ARB_multisample", F(ARB_multisample) },
{ OFF, "GL_ARB_multitexture", F(ARB_multitexture) },
{ OFF, "GL_ARB_occlusion_query", F(ARB_occlusion_query) },
{ OFF, "GL_ARB_pixel_buffer_object", F(EXT_pixel_buffer_object) },
{ OFF, "GL_ARB_point_parameters", F(EXT_point_parameters) },
{ OFF, "GL_ARB_point_sprite", F(ARB_point_sprite) },
+ { OFF, "GL_ARB_seamless_cube_map", F(ARB_seamless_cube_map) },
{ OFF, "GL_ARB_shader_objects", F(ARB_shader_objects) },
{ OFF, "GL_ARB_shading_language_100", F(ARB_shading_language_100) },
{ OFF, "GL_ARB_shading_language_120", F(ARB_shading_language_120) },
{ OFF, "GL_ARB_shadow", F(ARB_shadow) },
- { OFF, "GL_ARB_shadow_ambient", F(SGIX_shadow_ambient) },
+ { OFF, "GL_ARB_shadow_ambient", F(ARB_shadow_ambient) },
+ { OFF, "GL_ARB_sync", F(ARB_sync) },
{ OFF, "GL_ARB_texture_border_clamp", F(ARB_texture_border_clamp) },
- { OFF, "GL_ARB_texture_compression", F(ARB_texture_compression) },
+ { ON, "GL_ARB_texture_compression", F(ARB_texture_compression) },
{ OFF, "GL_ARB_texture_cube_map", F(ARB_texture_cube_map) },
{ OFF, "GL_ARB_texture_env_add", F(EXT_texture_env_add) },
{ OFF, "GL_ARB_texture_env_combine", F(ARB_texture_env_combine) },
@@ -74,7 +82,9 @@ static const struct {
{ OFF, "GL_ARB_texture_non_power_of_two", F(ARB_texture_non_power_of_two)},
{ OFF, "GL_ARB_texture_rectangle", F(NV_texture_rectangle) },
{ ON, "GL_ARB_transpose_matrix", F(ARB_transpose_matrix) },
- { OFF, "GL_ARB_vertex_buffer_object", F(ARB_vertex_buffer_object) },
+ { OFF, "GL_ARB_vertex_array_bgra", F(EXT_vertex_array_bgra) },
+ { OFF, "GL_ARB_vertex_array_object", F(ARB_vertex_array_object) },
+ { ON, "GL_ARB_vertex_buffer_object", F(ARB_vertex_buffer_object) },
{ OFF, "GL_ARB_vertex_program", F(ARB_vertex_program) },
{ OFF, "GL_ARB_vertex_shader", F(ARB_vertex_shader) },
{ ON, "GL_ARB_window_pos", F(ARB_window_pos) },
@@ -86,7 +96,7 @@ static const struct {
{ OFF, "GL_EXT_blend_logic_op", F(EXT_blend_logic_op) },
{ OFF, "GL_EXT_blend_minmax", F(EXT_blend_minmax) },
{ OFF, "GL_EXT_blend_subtract", F(EXT_blend_subtract) },
- { ON, "GL_EXT_clip_volume_hint", F(EXT_clip_volume_hint) },
+ { OFF, "GL_EXT_clip_volume_hint", F(EXT_clip_volume_hint) },
{ OFF, "GL_EXT_cull_vertex", F(EXT_cull_vertex) },
{ ON, "GL_EXT_compiled_vertex_array", F(EXT_compiled_vertex_array) },
{ OFF, "GL_EXT_convolution", F(EXT_convolution) },
@@ -98,13 +108,14 @@ static const struct {
{ OFF, "GL_EXT_fog_coord", F(EXT_fog_coord) },
{ OFF, "GL_EXT_gpu_program_parameters", F(EXT_gpu_program_parameters) },
{ OFF, "GL_EXT_histogram", F(EXT_histogram) },
- { OFF, "GL_EXT_multi_draw_arrays", F(EXT_multi_draw_arrays) },
+ { ON, "GL_EXT_multi_draw_arrays", F(EXT_multi_draw_arrays) },
{ OFF, "GL_EXT_packed_depth_stencil", F(EXT_packed_depth_stencil) },
{ ON, "GL_EXT_packed_pixels", F(EXT_packed_pixels) },
{ OFF, "GL_EXT_paletted_texture", F(EXT_paletted_texture) },
{ OFF, "GL_EXT_pixel_buffer_object", F(EXT_pixel_buffer_object) },
{ OFF, "GL_EXT_point_parameters", F(EXT_point_parameters) },
{ ON, "GL_EXT_polygon_offset", F(EXT_polygon_offset) },
+ { OFF, "GL_EXT_provoking_vertex", F(EXT_provoking_vertex) },
{ ON, "GL_EXT_rescale_normal", F(EXT_rescale_normal) },
{ OFF, "GL_EXT_secondary_color", F(EXT_secondary_color) },
{ ON, "GL_EXT_separate_specular_color", F(EXT_separate_specular_color) },
@@ -126,33 +137,38 @@ static const struct {
{ ON, "GL_EXT_texture_object", F(EXT_texture_object) },
{ OFF, "GL_EXT_texture_rectangle", F(NV_texture_rectangle) },
{ OFF, "GL_EXT_texture_sRGB", F(EXT_texture_sRGB) },
+ { OFF, "GL_EXT_texture_swizzle", F(EXT_texture_swizzle) },
{ OFF, "GL_EXT_timer_query", F(EXT_timer_query) },
{ ON, "GL_EXT_vertex_array", F(EXT_vertex_array) },
+ { OFF, "GL_EXT_vertex_array_bgra", F(EXT_vertex_array_bgra) },
{ OFF, "GL_EXT_vertex_array_set", F(EXT_vertex_array_set) },
{ OFF, "GL_3DFX_texture_compression_FXT1", F(TDFX_texture_compression_FXT1) },
{ OFF, "GL_APPLE_client_storage", F(APPLE_client_storage) },
{ ON, "GL_APPLE_packed_pixels", F(APPLE_packed_pixels) },
{ OFF, "GL_APPLE_vertex_array_object", F(APPLE_vertex_array_object) },
{ OFF, "GL_ATI_blend_equation_separate", F(EXT_blend_equation_separate) },
+ { OFF, "GL_ATI_envmap_bumpmap", F(ATI_envmap_bumpmap) },
{ OFF, "GL_ATI_texture_env_combine3", F(ATI_texture_env_combine3)},
{ OFF, "GL_ATI_texture_mirror_once", F(ATI_texture_mirror_once)},
{ OFF, "GL_ATI_fragment_shader", F(ATI_fragment_shader)},
{ OFF, "GL_ATI_separate_stencil", F(ATI_separate_stencil)},
- { OFF, "GL_IBM_multimode_draw_arrays", F(IBM_multimode_draw_arrays) },
+ { ON, "GL_IBM_multimode_draw_arrays", F(IBM_multimode_draw_arrays) },
{ ON, "GL_IBM_rasterpos_clip", F(IBM_rasterpos_clip) },
{ OFF, "GL_IBM_texture_mirrored_repeat", F(ARB_texture_mirrored_repeat)},
{ OFF, "GL_INGR_blend_func_separate", F(EXT_blend_func_separate) },
{ OFF, "GL_MESA_pack_invert", F(MESA_pack_invert) },
{ OFF, "GL_MESA_packed_depth_stencil", F(MESA_packed_depth_stencil) },
- { OFF, "GL_MESA_program_debug", F(MESA_program_debug) },
{ OFF, "GL_MESA_resize_buffers", F(MESA_resize_buffers) },
{ OFF, "GL_MESA_texture_array", F(MESA_texture_array) },
+ { OFF, "GL_MESA_texture_signed_rgba", F(MESA_texture_signed_rgba) },
{ OFF, "GL_MESA_ycbcr_texture", F(MESA_ycbcr_texture) },
{ ON, "GL_MESA_window_pos", F(ARB_window_pos) },
{ OFF, "GL_NV_blend_square", F(NV_blend_square) },
+ { OFF, "GL_NV_depth_clamp", F(ARB_depth_clamp) },
{ OFF, "GL_NV_fragment_program", F(NV_fragment_program) },
{ ON, "GL_NV_light_max_exponent", F(NV_light_max_exponent) },
{ OFF, "GL_NV_point_sprite", F(NV_point_sprite) },
+ { OFF, "GL_NV_texture_env_combine4", F(NV_texture_env_combine4) },
{ OFF, "GL_NV_texture_rectangle", F(NV_texture_rectangle) },
{ ON, "GL_NV_texgen_reflection", F(NV_texgen_reflection) },
{ OFF, "GL_NV_vertex_program", F(NV_vertex_program) },
@@ -165,11 +181,14 @@ static const struct {
{ OFF, "GL_SGIS_texture_border_clamp", F(ARB_texture_border_clamp) },
{ ON, "GL_SGIS_texture_edge_clamp", F(SGIS_texture_edge_clamp) },
{ ON, "GL_SGIS_texture_lod", F(SGIS_texture_lod) },
- { OFF, "GL_SGIX_depth_texture", F(ARB_depth_texture) },
- { OFF, "GL_SGIX_shadow", F(SGIX_shadow) },
- { OFF, "GL_SGIX_shadow_ambient", F(SGIX_shadow_ambient) },
- { OFF, "GL_SUN_multi_draw_arrays", F(EXT_multi_draw_arrays) },
+ { ON, "GL_SUN_multi_draw_arrays", F(EXT_multi_draw_arrays) },
{ OFF, "GL_S3_s3tc", F(S3_s3tc) },
+#if FEATURE_OES_draw_texture
+ { OFF, "GL_OES_draw_texture", F(OES_draw_texture) },
+#endif /* FEATURE_OES_draw_texture */
+#if FEATURE_OES_EGL_image
+ { OFF, "GL_OES_EGL_image", F(OES_EGL_image) },
+#endif
};
@@ -181,8 +200,11 @@ static const struct {
void
_mesa_enable_sw_extensions(GLcontext *ctx)
{
+ ctx->Extensions.ARB_copy_buffer = GL_TRUE;
+ ctx->Extensions.ARB_depth_clamp = GL_TRUE;
ctx->Extensions.ARB_depth_texture = GL_TRUE;
- ctx->Extensions.ARB_draw_buffers = GL_TRUE;
+ /*ctx->Extensions.ARB_draw_buffers = GL_TRUE;*/
+ ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE;
#if FEATURE_ARB_fragment_program
ctx->Extensions.ARB_fragment_program = GL_TRUE;
ctx->Extensions.ARB_fragment_program_shadow = GL_TRUE;
@@ -190,10 +212,14 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
#if FEATURE_ARB_fragment_shader
ctx->Extensions.ARB_fragment_shader = GL_TRUE;
#endif
+#if FEATURE_ARB_framebuffer_object
+ ctx->Extensions.ARB_framebuffer_object = GL_TRUE;
+#endif
ctx->Extensions.ARB_half_float_pixel = GL_TRUE;
ctx->Extensions.ARB_imaging = GL_TRUE;
+ ctx->Extensions.ARB_map_buffer_range = GL_TRUE;
ctx->Extensions.ARB_multitexture = GL_TRUE;
-#if FEATURE_ARB_occlusion_query
+#if FEATURE_queryobj
ctx->Extensions.ARB_occlusion_query = GL_TRUE;
#endif
ctx->Extensions.ARB_point_sprite = GL_TRUE;
@@ -204,9 +230,10 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
ctx->Extensions.ARB_shading_language_100 = GL_TRUE;
#endif
#if FEATURE_ARB_shading_language_120
- ctx->Extensions.ARB_shading_language_120 = GL_FALSE; /* not quite done */
+ ctx->Extensions.ARB_shading_language_120 = GL_TRUE;
#endif
ctx->Extensions.ARB_shadow = GL_TRUE;
+ ctx->Extensions.ARB_shadow_ambient = GL_TRUE;
ctx->Extensions.ARB_texture_border_clamp = GL_TRUE;
ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
@@ -215,6 +242,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
/*ctx->Extensions.ARB_texture_float = GL_TRUE;*/
ctx->Extensions.ARB_texture_mirrored_repeat = GL_TRUE;
ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE;
+ ctx->Extensions.ARB_vertex_array_object = GL_TRUE;
#if FEATURE_ARB_vertex_program
ctx->Extensions.ARB_vertex_program = GL_TRUE;
#endif
@@ -222,9 +250,13 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
ctx->Extensions.ARB_vertex_shader = GL_TRUE;
#endif
#if FEATURE_ARB_vertex_buffer_object
- ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;
+ /*ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;*/
+#endif
+#if FEATURE_ARB_sync
+ ctx->Extensions.ARB_sync = GL_TRUE;
#endif
ctx->Extensions.APPLE_vertex_array_object = GL_TRUE;
+ ctx->Extensions.ATI_envmap_bumpmap = GL_TRUE;
#if FEATURE_ATI_fragment_shader
ctx->Extensions.ATI_fragment_shader = GL_TRUE;
#endif
@@ -247,18 +279,19 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
ctx->Extensions.EXT_framebuffer_blit = GL_TRUE;
#endif
ctx->Extensions.EXT_histogram = GL_TRUE;
- ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;
+ /*ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;*/
ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE;
ctx->Extensions.EXT_paletted_texture = GL_TRUE;
#if FEATURE_EXT_pixel_buffer_object
ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
#endif
ctx->Extensions.EXT_point_parameters = GL_TRUE;
+ ctx->Extensions.EXT_provoking_vertex = GL_TRUE;
ctx->Extensions.EXT_shadow_funcs = GL_TRUE;
ctx->Extensions.EXT_secondary_color = GL_TRUE;
ctx->Extensions.EXT_shared_texture_palette = GL_TRUE;
ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
- ctx->Extensions.EXT_stencil_two_side = GL_FALSE; /* obsolete */
+ ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
ctx->Extensions.EXT_texture_env_add = GL_TRUE;
ctx->Extensions.EXT_texture_env_combine = GL_TRUE;
ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
@@ -267,17 +300,17 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
#if FEATURE_EXT_texture_sRGB
ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
#endif
- ctx->Extensions.IBM_multimode_draw_arrays = GL_TRUE;
+ ctx->Extensions.EXT_texture_swizzle = GL_TRUE;
+ ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE;
+ /*ctx->Extensions.IBM_multimode_draw_arrays = GL_TRUE;*/
ctx->Extensions.MESA_pack_invert = GL_TRUE;
-#if FEATURE_MESA_program_debug
- ctx->Extensions.MESA_program_debug = GL_TRUE;
-#endif
ctx->Extensions.MESA_resize_buffers = GL_TRUE;
ctx->Extensions.MESA_texture_array = GL_TRUE;
ctx->Extensions.MESA_ycbcr_texture = GL_TRUE;
ctx->Extensions.NV_blend_square = GL_TRUE;
/*ctx->Extensions.NV_light_max_exponent = GL_TRUE;*/
ctx->Extensions.NV_point_sprite = GL_TRUE;
+ ctx->Extensions.NV_texture_env_combine4 = GL_TRUE;
ctx->Extensions.NV_texture_rectangle = GL_TRUE;
/*ctx->Extensions.NV_texgen_reflection = GL_TRUE;*/
#if FEATURE_NV_vertex_program
@@ -292,8 +325,6 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
ctx->Extensions.SGI_texture_color_table = GL_TRUE;
ctx->Extensions.SGIS_generate_mipmap = GL_TRUE;
ctx->Extensions.SGIS_texture_edge_clamp = GL_TRUE;
- ctx->Extensions.SGIX_shadow = GL_TRUE;
- ctx->Extensions.SGIX_shadow_ambient = GL_TRUE;
#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE;
#endif
@@ -335,10 +366,10 @@ _mesa_enable_imaging_extensions(GLcontext *ctx)
void
_mesa_enable_1_3_extensions(GLcontext *ctx)
{
- ctx->Extensions.ARB_multisample = GL_TRUE;
+ /*ctx->Extensions.ARB_multisample = GL_TRUE;*/
ctx->Extensions.ARB_multitexture = GL_TRUE;
ctx->Extensions.ARB_texture_border_clamp = GL_TRUE;
- ctx->Extensions.ARB_texture_compression = GL_TRUE;
+ /*ctx->Extensions.ARB_texture_compression = GL_TRUE;*/
ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE;
@@ -365,7 +396,7 @@ _mesa_enable_1_4_extensions(GLcontext *ctx)
ctx->Extensions.EXT_blend_minmax = GL_TRUE;
ctx->Extensions.EXT_blend_subtract = GL_TRUE;
ctx->Extensions.EXT_fog_coord = GL_TRUE;
- ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;
+ /*ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;*/
ctx->Extensions.EXT_point_parameters = GL_TRUE;
ctx->Extensions.EXT_secondary_color = GL_TRUE;
ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
@@ -382,7 +413,7 @@ void
_mesa_enable_1_5_extensions(GLcontext *ctx)
{
ctx->Extensions.ARB_occlusion_query = GL_TRUE;
- ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;
+ /*ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;*/
ctx->Extensions.EXT_shadow_funcs = GL_TRUE;
}
@@ -394,11 +425,12 @@ _mesa_enable_1_5_extensions(GLcontext *ctx)
void
_mesa_enable_2_0_extensions(GLcontext *ctx)
{
- ctx->Extensions.ARB_draw_buffers = GL_TRUE;
+ /*ctx->Extensions.ARB_draw_buffers = GL_TRUE;*/
#if FEATURE_ARB_fragment_shader
ctx->Extensions.ARB_fragment_shader = GL_TRUE;
#endif
ctx->Extensions.ARB_point_sprite = GL_TRUE;
+ ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE;
#if FEATURE_ARB_shader_objects
ctx->Extensions.ARB_shader_objects = GL_TRUE;
@@ -406,7 +438,7 @@ _mesa_enable_2_0_extensions(GLcontext *ctx)
#if FEATURE_ARB_shading_language_100
ctx->Extensions.ARB_shading_language_100 = GL_TRUE;
#endif
- ctx->Extensions.EXT_stencil_two_side = GL_FALSE; /* obsolete */
+ ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
#if FEATURE_ARB_vertex_shader
ctx->Extensions.ARB_vertex_shader = GL_TRUE;
#endif
@@ -427,7 +459,7 @@ _mesa_enable_2_1_extensions(GLcontext *ctx)
ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
#endif
#ifdef FEATURE_ARB_shading_language_120
- ctx->Extensions.ARB_shading_language_120 = GL_FALSE; /* not quite done */
+ ctx->Extensions.ARB_shading_language_120 = GL_TRUE;
#endif
}
@@ -435,8 +467,9 @@ _mesa_enable_2_1_extensions(GLcontext *ctx)
/**
* Either enable or disable the named extension.
+ * \return GL_TRUE for success, GL_FALSE if invalid extension name
*/
-static void
+static GLboolean
set_extension( GLcontext *ctx, const char *name, GLboolean state )
{
GLboolean *base = (GLboolean *) &ctx->Extensions;
@@ -445,7 +478,7 @@ set_extension( GLcontext *ctx, const char *name, GLboolean state )
if (ctx->Extensions.String) {
/* The string was already queried - can't change it now! */
_mesa_problem(ctx, "Trying to enable/disable extension after glGetString(GL_EXTENSIONS): %s", name);
- return;
+ return GL_FALSE;
}
for (i = 0 ; i < Elements(default_extensions) ; i++) {
@@ -454,10 +487,10 @@ set_extension( GLcontext *ctx, const char *name, GLboolean state )
GLboolean *enabled = base + default_extensions[i].flag_offset;
*enabled = state;
}
- return;
+ return GL_TRUE;
}
}
- _mesa_problem(ctx, "Trying to enable unknown extension: %s", name);
+ return GL_FALSE;
}
@@ -468,7 +501,8 @@ set_extension( GLcontext *ctx, const char *name, GLboolean state )
void
_mesa_enable_extension( GLcontext *ctx, const char *name )
{
- set_extension(ctx, name, GL_TRUE);
+ if (!set_extension(ctx, name, GL_TRUE))
+ _mesa_problem(ctx, "Trying to enable unknown extension: %s", name);
}
@@ -479,7 +513,8 @@ _mesa_enable_extension( GLcontext *ctx, const char *name )
void
_mesa_disable_extension( GLcontext *ctx, const char *name )
{
- set_extension(ctx, name, GL_FALSE);
+ if (!set_extension(ctx, name, GL_FALSE))
+ _mesa_problem(ctx, "Trying to disable unknown extension: %s", name);
}
@@ -504,6 +539,80 @@ _mesa_extension_is_enabled( GLcontext *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 ? _mesa_strlen(a) : 0;
+ const GLuint bLen = b ? _mesa_strlen(b) : 0;
+ char *s = _mesa_calloc(aLen + bLen + 1);
+ if (s) {
+ if (a)
+ _mesa_memcpy(s, a, aLen);
+ if (b)
+ _mesa_memcpy(s + aLen, b, bLen);
+ s[aLen + bLen] = '\0';
+ }
+ if (a)
+ _mesa_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.
+ */
+static const char *
+get_extension_override( GLcontext *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;
+
+ 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;
+ }
+ else {
+ /* accumulate this non-space character */
+ ext[extLen++] = envExt[i];
+ }
+ }
+
+ return extraExt;
+}
+
+
+/**
* Run through the default_extensions array above and set the
* ctx->Extensions.ARB/EXT_* flags accordingly.
* To be called during context initialization.
@@ -531,8 +640,9 @@ GLubyte *
_mesa_make_extension_string( GLcontext *ctx )
{
const GLboolean *base = (const GLboolean *) &ctx->Extensions;
+ const char *extraExt = get_extension_override(ctx);
GLuint extStrLen = 0;
- GLubyte *s;
+ char *s;
GLuint i;
/* first, compute length of the extension string */
@@ -542,7 +652,14 @@ _mesa_make_extension_string( GLcontext *ctx )
extStrLen += (GLuint)_mesa_strlen(default_extensions[i].name) + 1;
}
}
- s = (GLubyte *) _mesa_malloc(extStrLen);
+
+ if (extraExt)
+ extStrLen += _mesa_strlen(extraExt) + 1; /* +1 for space */
+
+ /* allocate the extension string */
+ s = (char *) _mesa_malloc(extStrLen);
+ if (!s)
+ return NULL;
/* second, build the extension string */
extStrLen = 0;
@@ -552,13 +669,18 @@ _mesa_make_extension_string( GLcontext *ctx )
GLuint len = (GLuint)_mesa_strlen(default_extensions[i].name);
_mesa_memcpy(s + extStrLen, default_extensions[i].name, len);
extStrLen += len;
- s[extStrLen] = (GLubyte) ' ';
+ s[extStrLen] = ' ';
extStrLen++;
}
}
ASSERT(extStrLen > 0);
- s[extStrLen - 1] = 0;
+ s[extStrLen - 1] = 0; /* -1 to overwrite trailing the ' ' */
- return s;
+ if (extraExt) {
+ s = append(s, " ");
+ s = append(s, extraExt);
+ }
+
+ return (GLubyte *) s;
}
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index 876d691c65..877ec00ae4 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -3,6 +3,7 @@
* Version: 7.1
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -24,6 +25,8 @@
/*
+ * GL_EXT/ARB_framebuffer_object extensions
+ *
* Authors:
* Brian Paul
*/
@@ -34,6 +37,7 @@
#include "fbobject.h"
#include "framebuffer.h"
#include "hash.h"
+#include "macros.h"
#include "mipmap.h"
#include "renderbuffer.h"
#include "state.h"
@@ -122,8 +126,22 @@ _mesa_lookup_framebuffer(GLcontext *ctx, GLuint id)
/**
+ * Mark the given framebuffer as invalid. This will force the
+ * test for framebuffer completeness to be done before the framebuffer
+ * is used.
+ */
+static void
+invalidate_framebuffer(struct gl_framebuffer *fb)
+{
+ fb->_Status = 0; /* "indeterminate" */
+}
+
+
+/**
* Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
* gl_renderbuffer_attachment object.
+ * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
+ * the depth buffer attachment point.
*/
struct gl_renderbuffer_attachment *
_mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
@@ -153,6 +171,8 @@ _mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
return NULL;
}
return &fb->Attachment[BUFFER_COLOR0 + i];
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ /* fall-through */
case GL_DEPTH_ATTACHMENT_EXT:
return &fb->Attachment[BUFFER_DEPTH];
case GL_STENCIL_ATTACHMENT_EXT:
@@ -173,7 +193,7 @@ _mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
if (att->Type == GL_TEXTURE) {
ASSERT(att->Texture);
if (ctx->Driver.FinishRenderTexture) {
- /* tell driver we're done rendering to this texobj */
+ /* tell driver that we're done rendering to this texture. */
ctx->Driver.FinishRenderTexture(ctx, att);
}
_mesa_reference_texobj(&att->Texture, NULL); /* unbind */
@@ -226,6 +246,8 @@ _mesa_set_texture_attachment(GLcontext *ctx,
if (att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
ctx->Driver.RenderTexture(ctx, fb, att);
}
+
+ invalidate_framebuffer(fb);
}
@@ -263,16 +285,38 @@ _mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
ASSERT(att);
if (rb) {
_mesa_set_renderbuffer_attachment(ctx, att, rb);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* do stencil attachment here (depth already done above) */
+ att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
+ assert(att);
+ _mesa_set_renderbuffer_attachment(ctx, att, rb);
+ }
}
else {
_mesa_remove_attachment(ctx, att);
}
+ invalidate_framebuffer(fb);
+
_glthread_UNLOCK_MUTEX(fb->Mutex);
}
/**
+ * For debug only.
+ */
+static void
+att_incomplete(const char *msg)
+{
+#if 0
+ _mesa_printf("attachment incomplete: %s\n", msg);
+#else
+ (void) msg;
+#endif
+}
+
+
+/**
* Test if an attachment point is complete and update its Complete field.
* \param format if GL_COLOR, this is a color attachment point,
* if GL_DEPTH, this is a depth component attachment point,
@@ -293,20 +337,26 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
struct gl_texture_image *texImage;
if (!texObj) {
+ att_incomplete("no texobj");
att->Complete = GL_FALSE;
return;
}
texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
if (!texImage) {
+ att_incomplete("no teximage");
att->Complete = GL_FALSE;
return;
}
if (texImage->Width < 1 || texImage->Height < 1) {
+ att_incomplete("teximage width/height=0");
+ _mesa_printf("texobj = %u\n", texObj->Name);
+ _mesa_printf("level = %d\n", att->TextureLevel);
att->Complete = GL_FALSE;
return;
}
if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) {
+ att_incomplete("bad z offset");
att->Complete = GL_FALSE;
return;
}
@@ -314,6 +364,12 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
if (format == GL_COLOR) {
if (texImage->TexFormat->BaseFormat != GL_RGB &&
texImage->TexFormat->BaseFormat != GL_RGBA) {
+ att_incomplete("bad format");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ if (texImage->TexFormat->TexelBytes == 0) {
+ att_incomplete("compressed internalformat");
att->Complete = GL_FALSE;
return;
}
@@ -323,18 +379,30 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
/* OK */
}
else if (ctx->Extensions.EXT_packed_depth_stencil &&
+ ctx->Extensions.ARB_depth_texture &&
texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
/* OK */
}
else {
att->Complete = GL_FALSE;
+ att_incomplete("bad depth format");
return;
}
}
else {
- /* no such thing as stencil textures */
- att->Complete = GL_FALSE;
- return;
+ ASSERT(format == GL_STENCIL);
+ ASSERT(att->Renderbuffer->StencilBits);
+ if (ctx->Extensions.EXT_packed_depth_stencil &&
+ ctx->Extensions.ARB_depth_texture &&
+ att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* OK */
+ }
+ else {
+ /* no such thing as stencil-only textures */
+ att_incomplete("illegal stencil texture");
+ att->Complete = GL_FALSE;
+ return;
+ }
}
}
else if (att->Type == GL_RENDERBUFFER_EXT) {
@@ -342,45 +410,51 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
if (!att->Renderbuffer->InternalFormat ||
att->Renderbuffer->Width < 1 ||
att->Renderbuffer->Height < 1) {
+ att_incomplete("0x0 renderbuffer");
att->Complete = GL_FALSE;
return;
}
if (format == GL_COLOR) {
if (att->Renderbuffer->_BaseFormat != GL_RGB &&
att->Renderbuffer->_BaseFormat != GL_RGBA) {
- ASSERT(att->Renderbuffer->RedBits);
- ASSERT(att->Renderbuffer->GreenBits);
- ASSERT(att->Renderbuffer->BlueBits);
+ att_incomplete("bad renderbuffer color format");
att->Complete = GL_FALSE;
return;
}
+ ASSERT(att->Renderbuffer->RedBits);
+ ASSERT(att->Renderbuffer->GreenBits);
+ ASSERT(att->Renderbuffer->BlueBits);
}
else if (format == GL_DEPTH) {
- ASSERT(att->Renderbuffer->DepthBits);
if (att->Renderbuffer->_BaseFormat == GL_DEPTH_COMPONENT) {
+ ASSERT(att->Renderbuffer->DepthBits);
/* OK */
}
else if (ctx->Extensions.EXT_packed_depth_stencil &&
att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ ASSERT(att->Renderbuffer->DepthBits);
/* OK */
}
else {
+ att_incomplete("bad renderbuffer depth format");
att->Complete = GL_FALSE;
return;
}
}
else {
assert(format == GL_STENCIL);
- ASSERT(att->Renderbuffer->StencilBits);
if (att->Renderbuffer->_BaseFormat == GL_STENCIL_INDEX) {
+ ASSERT(att->Renderbuffer->StencilBits);
/* OK */
}
else if (ctx->Extensions.EXT_packed_depth_stencil &&
att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ ASSERT(att->Renderbuffer->StencilBits);
/* OK */
}
else {
att->Complete = GL_FALSE;
+ att_incomplete("bad renderbuffer stencil format");
return;
}
}
@@ -410,15 +484,18 @@ fbo_incomplete(const char *msg, int index)
/**
* Test if the given framebuffer object is complete and update its
* Status field with the results.
+ * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
+ * driver to make hardware-specific validation/completeness checks.
* Also update the framebuffer's Width and Height fields if the
* framebuffer is complete.
*/
void
_mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
{
- GLuint numImages, width = 0, height = 0;
- GLenum intFormat = GL_NONE;
- GLuint w = 0, h = 0;
+ GLuint numImages;
+ GLenum intFormat = GL_NONE; /* color buffers' internal format */
+ GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
+ GLint numSamples = -1;
GLint i;
GLuint j;
@@ -428,11 +505,22 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
fb->Width = 0;
fb->Height = 0;
- /* Start at -2 to more easily loop over all attachment points */
+ /* Start at -2 to more easily loop over all attachment points.
+ * -2: depth buffer
+ * -1: stencil buffer
+ * >=0: color buffer
+ */
for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
struct gl_renderbuffer_attachment *att;
GLenum f;
+ /*
+ * XXX for ARB_fbo, only check color buffers that are named by
+ * GL_READ_BUFFER and GL_DRAW_BUFFERi.
+ */
+
+ /* check for attachment completeness
+ */
if (i == -2) {
att = &fb->Attachment[BUFFER_DEPTH];
test_attachment_completeness(ctx, GL_DEPTH, att);
@@ -461,11 +549,15 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
}
}
+ /* get width, height, format of the renderbuffer/texture
+ */
if (att->Type == GL_TEXTURE) {
const struct gl_texture_image *texImg
= att->Texture->Image[att->CubeMapFace][att->TextureLevel];
- w = texImg->Width;
- h = texImg->Height;
+ minWidth = MIN2(minWidth, texImg->Width);
+ maxWidth = MAX2(maxWidth, texImg->Width);
+ minHeight = MIN2(minHeight, texImg->Height);
+ maxHeight = MAX2(maxHeight, texImg->Height);
f = texImg->_BaseFormat;
numImages++;
if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT
@@ -476,8 +568,10 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
}
}
else if (att->Type == GL_RENDERBUFFER_EXT) {
- w = att->Renderbuffer->Width;
- h = att->Renderbuffer->Height;
+ minWidth = MIN2(minWidth, att->Renderbuffer->Width);
+ maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
+ minHeight = MIN2(minHeight, att->Renderbuffer->Height);
+ maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
f = att->Renderbuffer->InternalFormat;
numImages++;
}
@@ -486,25 +580,41 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
continue;
}
+ if (numSamples < 0) {
+ /* first buffer */
+ numSamples = att->Renderbuffer->NumSamples;
+ }
+
+ /* Error-check width, height, format, samples
+ */
if (numImages == 1) {
- /* set required width, height and format */
- width = w;
- height = h;
- if (i >= 0)
+ /* save format, num samples */
+ if (i >= 0) {
intFormat = f;
+ }
}
else {
- /* check that width, height, format are same */
- if (w != width || h != height) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
- fbo_incomplete("width or height mismatch", -1);
- return;
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ /* check that width, height, format are same */
+ if (minWidth != maxWidth || minHeight != maxHeight) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
+ fbo_incomplete("width or height mismatch", -1);
+ return;
+ }
+ /* check that all color buffer have same format */
+ if (intFormat != GL_NONE && f != intFormat) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
+ fbo_incomplete("format mismatch", -1);
+ return;
+ }
}
- if (intFormat != GL_NONE && f != intFormat) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
- fbo_incomplete("format mismatch", -1);
+ if (att->Renderbuffer &&
+ att->Renderbuffer->NumSamples != numSamples) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete("inconsistant number of samples", i);
return;
- }
+ }
+
}
}
@@ -534,6 +644,8 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
return;
}
}
+#else
+ (void) j;
#endif
if (numImages == 0) {
@@ -542,12 +654,32 @@ _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
return;
}
- /*
- * If we get here, the framebuffer is complete!
- */
+ /* Provisionally set status = COMPLETE ... */
fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
- fb->Width = w;
- fb->Height = h;
+
+ /* ... but the driver may say the FB is incomplete.
+ * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
+ * if anything.
+ */
+ if (ctx->Driver.ValidateFramebuffer) {
+ ctx->Driver.ValidateFramebuffer(ctx, fb);
+ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ fbo_incomplete("driver marked FBO as incomplete", -1);
+ }
+ }
+
+ if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
+ /*
+ * Note that if ARB_framebuffer_object is supported and the attached
+ * renderbuffers/textures are different sizes, the framebuffer
+ * width/height will be set to the smallest width/height.
+ */
+ fb->Width = minWidth;
+ fb->Height = minHeight;
+
+ /* finally, update the visual info for the framebuffer */
+ _mesa_update_framebuffer_visual(fb);
+ }
}
@@ -579,7 +711,7 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
return;
}
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
/* The above doesn't fully flush the drivers in the way that a
* glFlush does, but that is required here:
*/
@@ -593,6 +725,12 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
/* ID was reserved, but no real renderbuffer object made yet */
newRb = NULL;
}
+ else if (!newRb && ctx->Extensions.ARB_framebuffer_object) {
+ /* All RB IDs must be Gen'd */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
+ return;
+ }
+
if (!newRb) {
/* create new renderbuffer object */
newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
@@ -615,6 +753,27 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
}
+/**
+ * If the given renderbuffer is anywhere attached to the framebuffer, detach
+ * the renderbuffer.
+ * This is used when a renderbuffer object is deleted.
+ * The spec calls for unbinding.
+ */
+static void
+detach_renderbuffer(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer *rb)
+{
+ GLuint i;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (fb->Attachment[i].Renderbuffer == rb) {
+ _mesa_remove_attachment(ctx, &fb->Attachment[i]);
+ }
+ }
+ invalidate_framebuffer(fb);
+}
+
+
void GLAPIENTRY
_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
{
@@ -636,6 +795,13 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
_mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
}
+ if (ctx->DrawBuffer->Name) {
+ detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
+ }
+ if (ctx->ReadBuffer->Name && ctx->ReadBuffer != ctx->DrawBuffer) {
+ detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
+ }
+
/* Remove from hash table immediately, to free the ID.
* But the object will not be freed until it's no longer
* referenced anywhere else.
@@ -737,10 +903,21 @@ _mesa_base_fbo_format(GLcontext *ctx, GLenum internalFormat)
}
-void GLAPIENTRY
-_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
- GLsizei width, GLsizei height)
+/** sentinal value, see below */
+#define NO_SAMPLES 1000
+
+
+/**
+ * Helper function used by _mesa_RenderbufferStorageEXT() and
+ * _mesa_RenderbufferStorageMultisample().
+ * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT().
+ */
+static void
+renderbuffer_storage(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei samples)
{
+ const char *func = samples == NO_SAMPLES ?
+ "glRenderbufferStorage" : "RenderbufferStorageMultisample";
struct gl_renderbuffer *rb;
GLenum baseFormat;
GET_CURRENT_CONTEXT(ctx);
@@ -748,31 +925,39 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (target != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glRenderbufferStorageEXT(target)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
return;
}
baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
if (baseFormat == 0) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glRenderbufferStorageEXT(internalFormat)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func);
return;
}
if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glRenderbufferStorageEXT(width)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
return;
}
if (height < 1 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glRenderbufferStorageEXT(height)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
return;
}
- rb = ctx->CurrentRenderbuffer;
+ if (samples == NO_SAMPLES) {
+ /* NumSamples == 0 indicates non-multisampling */
+ samples = 0;
+ }
+ else if (samples > ctx->Const.MaxSamples) {
+ /* note: driver may choose to use more samples than what's requested */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func);
+ return;
+ }
+ rb = ctx->CurrentRenderbuffer;
if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferStorageEXT");
+ _mesa_error(ctx, GL_INVALID_OPERATION, func);
return;
}
@@ -794,6 +979,7 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
rb->IndexBits =
rb->DepthBits =
rb->StencilBits = 0;
+ rb->NumSamples = samples;
/* Now allocate the storage */
ASSERT(rb->AllocStorage);
@@ -820,7 +1006,8 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
rb->AlphaBits =
rb->IndexBits =
rb->DepthBits =
- rb->StencilBits = 0;
+ rb->StencilBits =
+ rb->NumSamples = 0;
}
/*
@@ -833,8 +1020,31 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
void GLAPIENTRY
+_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ /* GL_ARB_fbo says calling this function is equivalent to calling
+ * glRenderbufferStorageMultisample() with samples=0. We pass in
+ * a token value here just for error reporting purposes.
+ */
+ renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
+}
+
+
+void GLAPIENTRY
+_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ renderbuffer_storage(target, internalFormat, width, height, samples);
+}
+
+
+
+void GLAPIENTRY
_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
{
+ struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -845,7 +1055,8 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
return;
}
- if (!ctx->CurrentRenderbuffer) {
+ rb = ctx->CurrentRenderbuffer;
+ if (!rb) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetRenderbufferParameterivEXT");
return;
@@ -855,32 +1066,38 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
switch (pname) {
case GL_RENDERBUFFER_WIDTH_EXT:
- *params = ctx->CurrentRenderbuffer->Width;
+ *params = rb->Width;
return;
case GL_RENDERBUFFER_HEIGHT_EXT:
- *params = ctx->CurrentRenderbuffer->Height;
+ *params = rb->Height;
return;
case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
- *params = ctx->CurrentRenderbuffer->InternalFormat;
+ *params = rb->InternalFormat;
return;
case GL_RENDERBUFFER_RED_SIZE_EXT:
- *params = ctx->CurrentRenderbuffer->RedBits;
+ *params = rb->RedBits;
break;
case GL_RENDERBUFFER_GREEN_SIZE_EXT:
- *params = ctx->CurrentRenderbuffer->GreenBits;
+ *params = rb->GreenBits;
break;
case GL_RENDERBUFFER_BLUE_SIZE_EXT:
- *params = ctx->CurrentRenderbuffer->BlueBits;
+ *params = rb->BlueBits;
break;
case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
- *params = ctx->CurrentRenderbuffer->AlphaBits;
+ *params = rb->AlphaBits;
break;
case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
- *params = ctx->CurrentRenderbuffer->DepthBits;
+ *params = rb->DepthBits;
break;
case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
- *params = ctx->CurrentRenderbuffer->StencilBits;
+ *params = rb->StencilBits;
break;
+ case GL_RENDERBUFFER_SAMPLES:
+ if (ctx->Extensions.ARB_framebuffer_object) {
+ *params = rb->NumSamples;
+ break;
+ }
+ /* fallthrough */
default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetRenderbufferParameterivEXT(target)");
@@ -946,6 +1163,13 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
GLboolean bindReadBuf, bindDrawBuf;
GET_CURRENT_CONTEXT(ctx);
+#ifdef DEBUG
+ if (ctx->Extensions.ARB_framebuffer_object) {
+ ASSERT(ctx->Extensions.EXT_framebuffer_object);
+ ASSERT(ctx->Extensions.EXT_framebuffer_blit);
+ }
+#endif
+
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (!ctx->Extensions.EXT_framebuffer_object) {
@@ -982,8 +1206,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
return;
}
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
if (ctx->Driver.Flush) {
ctx->Driver.Flush(ctx);
}
@@ -995,6 +1218,12 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
/* ID was reserved, but no real framebuffer object made yet */
newFb = NULL;
}
+ else if (!newFb && ctx->Extensions.ARB_framebuffer_object) {
+ /* All FBO IDs must be Gen'd */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
+ return;
+ }
+
if (!newFb) {
/* create new framebuffer object */
newFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
@@ -1018,19 +1247,26 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
ASSERT(newFb != &DummyFramebuffer);
/*
- * XXX check if re-binding same buffer and skip some of this code.
+ * OK, now bind the new Draw/Read framebuffers, if they're changing.
*/
if (bindReadBuf) {
- _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread);
+ if (ctx->ReadBuffer == newFbread)
+ bindReadBuf = GL_FALSE; /* no change */
+ else
+ _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread);
}
if (bindDrawBuf) {
/* check if old FB had any texture attachments */
- check_end_texture_render(ctx, ctx->DrawBuffer);
+ if (ctx->DrawBuffer->Name != 0) {
+ check_end_texture_render(ctx, ctx->DrawBuffer);
+ }
- /* check if time to delete this framebuffer */
- _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb);
+ if (ctx->DrawBuffer == newFb)
+ bindDrawBuf = GL_FALSE; /* no change */
+ else
+ _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb);
if (newFb->Name != 0) {
/* check if newly bound framebuffer has any texture attachments */
@@ -1038,7 +1274,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
}
}
- if (ctx->Driver.BindFramebuffer) {
+ if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
ctx->Driver.BindFramebuffer(ctx, target, newFb, newFbread);
}
}
@@ -1051,7 +1287,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
/* The above doesn't fully flush the drivers in the way that a
* glFlush does, but that is required here:
*/
@@ -1069,7 +1305,12 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
if (fb == ctx->DrawBuffer) {
/* bind default */
ASSERT(fb->RefCount >= 2);
- _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+ }
+ if (fb == ctx->ReadBuffer) {
+ /* bind default */
+ ASSERT(fb->RefCount >= 2);
+ _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
}
/* remove from hash table immediately, to free the ID */
@@ -1079,7 +1320,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
/* But the object will not be freed until it's no longer
* bound in any context.
*/
- _mesa_unreference_framebuffer(&fb);
+ _mesa_reference_framebuffer(&fb, NULL);
}
}
}
@@ -1158,7 +1399,10 @@ _mesa_CheckFramebufferStatusEXT(GLenum target)
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
- _mesa_test_framebuffer_completeness(ctx, buffer);
+ if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
+ _mesa_test_framebuffer_completeness(ctx, buffer);
+ }
+
return buffer->_Status;
}
@@ -1175,16 +1419,31 @@ framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target,
struct gl_renderbuffer_attachment *att;
struct gl_texture_object *texObj = NULL;
struct gl_framebuffer *fb;
+ GLboolean error = GL_FALSE;
ASSERT_OUTSIDE_BEGIN_END(ctx);
- if (target != GL_FRAMEBUFFER_EXT) {
+ switch (target) {
+ case GL_READ_FRAMEBUFFER_EXT:
+ error = !ctx->Extensions.EXT_framebuffer_blit;
+ fb = ctx->ReadBuffer;
+ break;
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ error = !ctx->Extensions.EXT_framebuffer_blit;
+ /* fall-through */
+ case GL_FRAMEBUFFER_EXT:
+ fb = ctx->DrawBuffer;
+ break;
+ default:
+ error = GL_TRUE;
+ }
+
+ if (error) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferTexture%sEXT(target)", caller);
+ "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
return;
}
- fb = ctx->DrawBuffer;
ASSERT(fb);
/* check framebuffer binding */
@@ -1239,7 +1498,6 @@ framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target,
}
}
-
if ((level < 0) ||
(level >= _mesa_max_texture_levels(ctx, texObj->Target))) {
_mesa_error(ctx, GL_INVALID_VALUE,
@@ -1255,7 +1513,19 @@ framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target,
return;
}
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+ if (texObj && attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* the texture format must be depth+stencil */
+ const struct gl_texture_image *texImg;
+ texImg = texObj->Image[0][texObj->BaseLevel];
+ if (!texImg || texImg->_BaseFormat != GL_DEPTH_STENCIL) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTexture%sEXT(texture is not"
+ " DEPTH_STENCIL format)", caller);
+ return;
+ }
+ }
+
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
/* The above doesn't fully flush the drivers in the way that a
* glFlush does, but that is required here:
*/
@@ -1266,10 +1536,22 @@ framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target,
if (texObj) {
_mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
level, zoffset);
+ /* Set the render-to-texture flag. We'll check this flag in
+ * glTexImage() and friends to determine if we need to revalidate
+ * any FBOs that might be rendering into this texture.
+ * This flag never gets cleared since it's non-trivial to determine
+ * when all FBOs might be done rendering to this texture. That's OK
+ * though since it's uncommon to render to a texture then repeatedly
+ * call glTexImage() to change images in the texture.
+ */
+ texObj->_RenderToTexture = GL_TRUE;
}
else {
_mesa_remove_attachment(ctx, att);
}
+
+ invalidate_framebuffer(fb);
+
_glthread_UNLOCK_MUTEX(fb->Mutex);
}
@@ -1303,7 +1585,7 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
(textarget != GL_TEXTURE_RECTANGLE_ARB) &&
(!IS_CUBE_FACE(textarget))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferTexture2DEXT(textarget)");
+ "glFramebufferTexture2DEXT(textarget=0x%x)", textarget);
return;
}
@@ -1413,7 +1695,18 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
rb = NULL;
}
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* make sure the renderbuffer is a depth/stencil format */
+ if (rb->_BaseFormat != GL_DEPTH_STENCIL) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbufferEXT(renderbuffer"
+ " is not DEPTH_STENCIL format)");
+ return;
+ }
+ }
+
+
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
/* The above doesn't fully flush the drivers in the way that a
* glFlush does, but that is required here:
*/
@@ -1481,7 +1774,20 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
return;
}
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* the depth and stencil attachments must point to the same buffer */
+ const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
+ depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
+ stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
+ if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
+ " attachments differ)");
+ return;
+ }
+ }
+
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
/* The above doesn't fully flush the drivers in the way that a
* glFlush does, but that is required here:
*/
@@ -1541,6 +1847,79 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
"glGetFramebufferAttachmentParameterivEXT(pname)");
}
return;
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->ColorEncoding;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ return;
+ }
+ else {
+ *params = att->Renderbuffer->ComponentType;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->RedBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->GreenBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->BlueBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->AlphaBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->DepthBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->StencilBits;
+ }
+ return;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(pname)");
@@ -1590,11 +1969,22 @@ _mesa_GenerateMipmapEXT(GLenum target)
#if FEATURE_EXT_framebuffer_blit
+/**
+ * Blit rectangular region, optionally from one framebuffer to another.
+ *
+ * Note, if the src buffer is multisampled and the dest is not, this is
+ * when the samples must be resolved to a single color.
+ */
void GLAPIENTRY
_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
+ const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
+ GL_DEPTH_BUFFER_BIT |
+ GL_STENCIL_BUFFER_BIT);
+ const struct gl_framebuffer *readFb, *drawFb;
+ const struct gl_renderbuffer *colorReadRb, *colorDrawRb;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -1604,13 +1994,19 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
_mesa_update_state(ctx);
}
- if (!ctx->ReadBuffer) {
- /* XXX */
+ readFb = ctx->ReadBuffer;
+ drawFb = ctx->DrawBuffer;
+
+ if (!readFb || !drawFb) {
+ /* This will normally never happen but someday we may want to
+ * support MakeCurrent() with no drawables.
+ */
+ return;
}
/* check for complete framebuffers */
- if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
- ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
+ readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
"glBlitFramebufferEXT(incomplete draw/read buffers)");
return;
@@ -1621,9 +2017,7 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
return;
}
- if (mask & ~(GL_COLOR_BUFFER_BIT |
- GL_DEPTH_BUFFER_BIT |
- GL_STENCIL_BUFFER_BIT)) {
+ if (mask & ~legalMaskBits) {
_mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
return;
}
@@ -1636,10 +2030,21 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
return;
}
+ /* get color read/draw renderbuffers */
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ colorReadRb = readFb->_ColorReadBuffer;
+ colorDrawRb = drawFb->_ColorDrawBuffers[0];
+ }
+ else {
+ colorReadRb = colorDrawRb = NULL;
+ }
+
if (mask & GL_STENCIL_BUFFER_BIT) {
- struct gl_renderbuffer *readRb = ctx->ReadBuffer->_StencilBuffer;
- struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_StencilBuffer;
- if (readRb->StencilBits != drawRb->StencilBits) {
+ struct gl_renderbuffer *readRb = readFb->_StencilBuffer;
+ struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer;
+ if (!readRb ||
+ !drawRb ||
+ readRb->StencilBits != drawRb->StencilBits) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBlitFramebufferEXT(stencil buffer size mismatch");
return;
@@ -1647,15 +2052,45 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
}
if (mask & GL_DEPTH_BUFFER_BIT) {
- struct gl_renderbuffer *readRb = ctx->ReadBuffer->_DepthBuffer;
- struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_DepthBuffer;
- if (readRb->DepthBits != drawRb->DepthBits) {
+ struct gl_renderbuffer *readRb = readFb->_DepthBuffer;
+ struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer;
+ if (!readRb ||
+ !drawRb ||
+ readRb->DepthBits != drawRb->DepthBits) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBlitFramebufferEXT(depth buffer size mismatch");
return;
}
}
+ if (readFb->Visual.samples > 0 &&
+ drawFb->Visual.samples > 0 &&
+ readFb->Visual.samples != drawFb->Visual.samples) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(mismatched samples");
+ return;
+ }
+
+ /* extra checks for multisample copies... */
+ if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
+ /* src and dest region sizes must be the same */
+ if (srcX1 - srcX0 != dstX1 - dstX0 ||
+ srcY1 - srcY0 != dstY1 - dstY0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(bad src/dst multisample region sizes");
+ return;
+ }
+
+ /* color formats must match */
+ if (colorReadRb &&
+ colorDrawRb &&
+ colorReadRb->_ActualFormat != colorDrawRb->_ActualFormat) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(bad src/dst multisample pixel formats");
+ return;
+ }
+ }
+
if (!ctx->Extensions.EXT_framebuffer_blit) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
return;
diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h
index b6154719ab..5409394073 100644
--- a/src/mesa/main/fbobject.h
+++ b/src/mesa/main/fbobject.h
@@ -84,6 +84,11 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalformat,
GLsizei width, GLsizei height);
extern void GLAPIENTRY
+_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalformat,
+ GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname,
GLint *params);
diff --git a/src/mesa/main/feedback.c b/src/mesa/main/feedback.c
index 48c2ccbff3..46759dc99e 100644
--- a/src/mesa/main/feedback.c
+++ b/src/mesa/main/feedback.c
@@ -1,13 +1,9 @@
-/**
- * \file feedback.c
- * Selection and feedback modes functions.
- */
-
/*
* Mesa 3-D graphics library
- * Version: 5.1
+ * Version: 7.5
*
- * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -27,6 +23,11 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+/**
+ * \file feedback.c
+ * Selection and feedback modes functions.
+ */
+
#include "glheader.h"
#include "colormac.h"
@@ -35,9 +36,10 @@
#include "feedback.h"
#include "macros.h"
#include "mtypes.h"
+#include "glapi/dispatch.h"
-#if _HAVE_FULL_GL
+#if FEATURE_feedback
#define FB_3D 0x01
@@ -110,61 +112,47 @@ _mesa_PassThrough( GLfloat token )
if (ctx->RenderMode==GL_FEEDBACK) {
FLUSH_VERTICES(ctx, 0);
- FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
- FEEDBACK_TOKEN( ctx, token );
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
+ _mesa_feedback_token( ctx, token );
}
}
-
-/*
+/**
* Put a vertex into the feedback buffer.
*/
-void _mesa_feedback_vertex( GLcontext *ctx,
- const GLfloat win[4],
- const GLfloat color[4],
- GLfloat index,
- const GLfloat texcoord[4] )
+void
+_mesa_feedback_vertex(GLcontext *ctx,
+ const GLfloat win[4],
+ const GLfloat color[4],
+ GLfloat index,
+ const GLfloat texcoord[4])
{
-#if 0
- {
- /* snap window x, y to fractional pixel position */
- const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1);
- GLfixed x, y;
- x = FloatToFixed(win[0]) & snapMask;
- y = FloatToFixed(win[1]) & snapMask;
- FEEDBACK_TOKEN(ctx, FixedToFloat(x));
- FEEDBACK_TOKEN(ctx, FixedToFloat(y) );
- }
-#else
- FEEDBACK_TOKEN( ctx, win[0] );
- FEEDBACK_TOKEN( ctx, win[1] );
-#endif
+ _mesa_feedback_token( ctx, win[0] );
+ _mesa_feedback_token( ctx, win[1] );
if (ctx->Feedback._Mask & FB_3D) {
- FEEDBACK_TOKEN( ctx, win[2] );
+ _mesa_feedback_token( ctx, win[2] );
}
if (ctx->Feedback._Mask & FB_4D) {
- FEEDBACK_TOKEN( ctx, win[3] );
+ _mesa_feedback_token( ctx, win[3] );
}
if (ctx->Feedback._Mask & FB_INDEX) {
- FEEDBACK_TOKEN( ctx, (GLfloat) index );
+ _mesa_feedback_token( ctx, (GLfloat) index );
}
if (ctx->Feedback._Mask & FB_COLOR) {
- FEEDBACK_TOKEN( ctx, color[0] );
- FEEDBACK_TOKEN( ctx, color[1] );
- FEEDBACK_TOKEN( ctx, color[2] );
- FEEDBACK_TOKEN( ctx, color[3] );
+ _mesa_feedback_token( ctx, color[0] );
+ _mesa_feedback_token( ctx, color[1] );
+ _mesa_feedback_token( ctx, color[2] );
+ _mesa_feedback_token( ctx, color[3] );
}
if (ctx->Feedback._Mask & FB_TEXTURE) {
- FEEDBACK_TOKEN( ctx, texcoord[0] );
- FEEDBACK_TOKEN( ctx, texcoord[1] );
- FEEDBACK_TOKEN( ctx, texcoord[2] );
- FEEDBACK_TOKEN( ctx, texcoord[3] );
+ _mesa_feedback_token( ctx, texcoord[0] );
+ _mesa_feedback_token( ctx, texcoord[1] );
+ _mesa_feedback_token( ctx, texcoord[2] );
+ _mesa_feedback_token( ctx, texcoord[3] );
}
}
-#endif
-
/**********************************************************************/
/** \name Selection */
@@ -207,17 +195,20 @@ _mesa_SelectBuffer( GLsizei size, GLuint *buffer )
/**
* Write a value of a record into the selection buffer.
*
- * \param CTX GL context.
- * \param V value.
+ * \param ctx GL context.
+ * \param value value.
*
* Verifies there is free space in the buffer to write the value and
* increments the pointer.
*/
-#define WRITE_RECORD( CTX, V ) \
- if (CTX->Select.BufferCount < CTX->Select.BufferSize) { \
- CTX->Select.Buffer[CTX->Select.BufferCount] = (V); \
- } \
- CTX->Select.BufferCount++;
+static INLINE void
+write_record(GLcontext *ctx, GLuint value)
+{
+ if (ctx->Select.BufferCount < ctx->Select.BufferSize) {
+ ctx->Select.Buffer[ctx->Select.BufferCount] = value;
+ }
+ ctx->Select.BufferCount++;
+}
/**
@@ -229,7 +220,8 @@ _mesa_SelectBuffer( GLsizei size, GLuint *buffer )
* Sets gl_selection::HitFlag and updates gl_selection::HitMinZ and
* gl_selection::HitMaxZ.
*/
-void _mesa_update_hitflag( GLcontext *ctx, GLfloat z )
+void
+_mesa_update_hitflag(GLcontext *ctx, GLfloat z)
{
ctx->Select.HitFlag = GL_TRUE;
if (z < ctx->Select.HitMinZ) {
@@ -252,7 +244,8 @@ void _mesa_update_hitflag( GLcontext *ctx, GLfloat z )
*
* \sa gl_selection.
*/
-static void write_hit_record( GLcontext *ctx )
+static void
+write_hit_record(GLcontext *ctx)
{
GLuint i;
GLuint zmin, zmax, zscale = (~0u);
@@ -264,11 +257,11 @@ static void write_hit_record( GLcontext *ctx )
zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
- WRITE_RECORD( ctx, ctx->Select.NameStackDepth );
- WRITE_RECORD( ctx, zmin );
- WRITE_RECORD( ctx, zmax );
+ write_record( ctx, ctx->Select.NameStackDepth );
+ write_record( ctx, zmin );
+ write_record( ctx, zmax );
for (i = 0; i < ctx->Select.NameStackDepth; i++) {
- WRITE_RECORD( ctx, ctx->Select.NameStack[i] );
+ write_record( ctx, ctx->Select.NameStack[i] );
}
ctx->Select.Hits++;
@@ -512,6 +505,23 @@ _mesa_RenderMode( GLenum mode )
/*@}*/
+void
+_mesa_init_feedback_dispatch(struct _glapi_table *disp)
+{
+ SET_InitNames(disp, _mesa_InitNames);
+ SET_FeedbackBuffer(disp, _mesa_FeedbackBuffer);
+ SET_LoadName(disp, _mesa_LoadName);
+ SET_PassThrough(disp, _mesa_PassThrough);
+ SET_PopName(disp, _mesa_PopName);
+ SET_PushName(disp, _mesa_PushName);
+ SET_SelectBuffer(disp, _mesa_SelectBuffer);
+ SET_RenderMode(disp, _mesa_RenderMode);
+}
+
+
+#endif /* FEATURE_feedback */
+
+
/**********************************************************************/
/** \name Initialization */
/*@{*/
diff --git a/src/mesa/main/feedback.h b/src/mesa/main/feedback.h
index 6c448ad631..6ed1a12525 100644
--- a/src/mesa/main/feedback.h
+++ b/src/mesa/main/feedback.h
@@ -1,13 +1,9 @@
-/**
- * \file feedback.h
- * Selection and feedback modes functions.
- */
-
/*
* Mesa 3-D graphics library
- * Version: 3.5
+ * Version: 7.5
*
- * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -27,31 +23,40 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-
#ifndef FEEDBACK_H
#define FEEDBACK_H
-#include "mtypes.h"
+#include "main/mtypes.h"
+
+#if FEATURE_feedback
-#define FEEDBACK_TOKEN( CTX, T ) \
- if (CTX->Feedback.Count < CTX->Feedback.BufferSize) { \
- CTX->Feedback.Buffer[CTX->Feedback.Count] = (GLfloat) (T); \
- } \
- CTX->Feedback.Count++;
+#define _MESA_INIT_FEEDBACK_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->RenderMode = impl ## RenderMode; \
+ } while (0)
+extern void
+_mesa_feedback_vertex( GLcontext *ctx,
+ const GLfloat win[4],
+ const GLfloat color[4],
+ GLfloat index,
+ const GLfloat texcoord[4] );
-extern void _mesa_init_feedback( GLcontext * ctx );
-extern void _mesa_feedback_vertex( GLcontext *ctx,
- const GLfloat win[4],
- const GLfloat color[4],
- GLfloat index,
- const GLfloat texcoord[4] );
+static INLINE void
+_mesa_feedback_token( GLcontext *ctx, GLfloat token )
+{
+ if (ctx->Feedback.Count < ctx->Feedback.BufferSize) {
+ ctx->Feedback.Buffer[ctx->Feedback.Count] = token;
+ }
+ ctx->Feedback.Count++;
+}
-extern void _mesa_update_hitflag( GLcontext *ctx, GLfloat z );
+extern void
+_mesa_update_hitflag( GLcontext *ctx, GLfloat z );
extern void GLAPIENTRY
@@ -78,5 +83,47 @@ _mesa_PopName( void );
extern GLint GLAPIENTRY
_mesa_RenderMode( GLenum mode );
+extern void
+_mesa_init_feedback_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_feedback */
+
+#define _MESA_INIT_FEEDBACK_FUNCTIONS(driver, impl) do { } while (0)
+
+static INLINE void
+_mesa_feedback_vertex( GLcontext *ctx,
+ const GLfloat win[4],
+ const GLfloat color[4],
+ GLfloat index,
+ const GLfloat texcoord[4] )
+{
+ /* render mode is always GL_RENDER */
+ ASSERT_NO_FEATURE();
+}
+
+
+static INLINE void
+_mesa_feedback_token( GLcontext *ctx, GLfloat token )
+{
+ /* render mode is always GL_RENDER */
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_mesa_update_hitflag( GLcontext *ctx, GLfloat z )
+{
+ /* render mode is always GL_RENDER */
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_mesa_init_feedback_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_feedback */
+
+extern void
+_mesa_init_feedback( GLcontext *ctx );
-#endif
+#endif /* FEEDBACK_H */
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index cc1b44de64..356476e35a 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -1,8 +1,8 @@
/**************************************************************************
- *
+ *
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -10,11 +10,11 @@
* 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.
@@ -22,7 +22,7 @@
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
+ *
**************************************************************************/
/**
@@ -46,32 +46,33 @@
#include "shader/prog_statevars.h"
+/** Max of number of lights and texture coord units */
+#define NUM_UNITS MAX2(MAX_TEXTURE_COORD_UNITS, MAX_LIGHTS)
+
struct state_key {
+ unsigned light_color_material_mask:12;
unsigned light_global_enabled:1;
unsigned light_local_viewer:1;
unsigned light_twoside:1;
- unsigned light_color_material:1;
- unsigned light_color_material_mask:12;
- unsigned light_material_mask:12;
unsigned material_shininess_is_zero:1;
-
unsigned need_eye_coords:1;
unsigned normalize:1;
unsigned rescale_normals:1;
+
unsigned fog_source_is_depth:1;
- unsigned tnl_do_vertex_fog:1;
unsigned separate_specular:1;
- unsigned fog_mode:2;
unsigned point_attenuated:1;
unsigned point_array:1;
unsigned texture_enabled_global:1;
unsigned fragprog_inputs_read:12;
+ unsigned varying_vp_inputs;
+
struct {
unsigned light_enabled:1;
unsigned light_eyepos3_is_zero:1;
unsigned light_spotcutoff_is_180:1;
- unsigned light_attenuated:1;
+ unsigned light_attenuated:1;
unsigned texunit_really_enabled:1;
unsigned texmat_enabled:1;
unsigned texgen_enabled:4;
@@ -79,27 +80,10 @@ struct state_key {
unsigned texgen_mode1:4;
unsigned texgen_mode2:4;
unsigned texgen_mode3:4;
- } unit[8];
+ } unit[NUM_UNITS];
};
-
-#define FOG_NONE 0
-#define FOG_LINEAR 1
-#define FOG_EXP 2
-#define FOG_EXP2 3
-
-static GLuint translate_fog_mode( GLenum mode )
-{
- switch (mode) {
- case GL_LINEAR: return FOG_LINEAR;
- case GL_EXP: return FOG_EXP;
- case GL_EXP2: return FOG_EXP2;
- default: return FOG_NONE;
- }
-}
-
-
#define TXG_NONE 0
#define TXG_OBJ_LINEAR 1
#define TXG_EYE_LINEAR 2
@@ -123,42 +107,6 @@ static GLuint translate_texgen( GLboolean enabled, GLenum mode )
}
-/**
- * Returns bitmask of flags indicating which materials are set per-vertex
- * in the current VB.
- * XXX get these from the VBO...
- */
-static GLbitfield
-tnl_get_per_vertex_materials(GLcontext *ctx)
-{
- GLbitfield mask = 0x0;
-#if 0
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
-
- for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++)
- if (VB->AttribPtr[i] && VB->AttribPtr[i]->stride)
- mask |= 1 << (i - _TNL_FIRST_MAT);
-#endif
- return mask;
-}
-
-
-/**
- * Should fog be computed per-vertex?
- */
-static GLboolean
-tnl_get_per_vertex_fog(GLcontext *ctx)
-{
-#if 0
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- return tnl->_DoVertexFog;
-#else
- return GL_FALSE;
-#endif
-}
-
static GLboolean check_active_shininess( GLcontext *ctx,
const struct state_key *key,
@@ -166,10 +114,11 @@ static GLboolean check_active_shininess( GLcontext *ctx,
{
GLuint bit = 1 << (MAT_ATTRIB_FRONT_SHININESS + side);
- if (key->light_color_material_mask & bit)
+ if ((key->varying_vp_inputs & VERT_BIT_COLOR0) &&
+ (key->light_color_material_mask & bit))
return GL_TRUE;
- if (key->light_material_mask & bit)
+ if (key->varying_vp_inputs & (bit << 16))
return GL_TRUE;
if (ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS + side][0] != 0.0F)
@@ -194,6 +143,7 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
key->need_eye_coords = ctx->_NeedEyeCoords;
key->fragprog_inputs_read = fp->Base.InputsRead;
+ key->varying_vp_inputs = ctx->varying_vp_inputs;
if (ctx->RenderMode == GL_FEEDBACK) {
/* make sure the vertprog emits color and tex0 */
@@ -213,12 +163,9 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
key->light_twoside = 1;
if (ctx->Light.ColorMaterialEnabled) {
- key->light_color_material = 1;
key->light_color_material_mask = ctx->Light.ColorMaterialBitmask;
}
- key->light_material_mask = tnl_get_per_vertex_materials(ctx);
-
for (i = 0; i < MAX_LIGHTS; i++) {
struct gl_light *light = &ctx->Light.Light[i];
@@ -227,7 +174,7 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
if (light->EyePosition[3] == 0.0)
key->unit[i].light_eyepos3_is_zero = 1;
-
+
if (light->SpotCutoff == 180.0)
key->unit[i].light_spotcutoff_is_180 = 1;
@@ -256,12 +203,8 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
if (ctx->Transform.RescaleNormals)
key->rescale_normals = 1;
- key->fog_mode = translate_fog_mode(fp->FogOption);
-
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
key->fog_source_is_depth = 1;
-
- key->tnl_do_vertex_fog = tnl_get_per_vertex_fog(ctx);
if (ctx->Point._Attenuated)
key->point_attenuated = 1;
@@ -275,52 +218,46 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
ctx->Texture._TexMatEnabled ||
ctx->Texture._EnabledUnits)
key->texture_enabled_global = 1;
-
+
for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
if (texUnit->_ReallyEnabled)
key->unit[i].texunit_really_enabled = 1;
- if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
+ if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
key->unit[i].texmat_enabled = 1;
-
+
if (texUnit->TexGenEnabled) {
key->unit[i].texgen_enabled = 1;
-
- key->unit[i].texgen_mode0 =
+
+ key->unit[i].texgen_mode0 =
translate_texgen( texUnit->TexGenEnabled & (1<<0),
- texUnit->GenModeS );
- key->unit[i].texgen_mode1 =
+ texUnit->GenS.Mode );
+ key->unit[i].texgen_mode1 =
translate_texgen( texUnit->TexGenEnabled & (1<<1),
- texUnit->GenModeT );
- key->unit[i].texgen_mode2 =
+ texUnit->GenT.Mode );
+ key->unit[i].texgen_mode2 =
translate_texgen( texUnit->TexGenEnabled & (1<<2),
- texUnit->GenModeR );
- key->unit[i].texgen_mode3 =
+ texUnit->GenR.Mode );
+ key->unit[i].texgen_mode3 =
translate_texgen( texUnit->TexGenEnabled & (1<<3),
- texUnit->GenModeQ );
+ texUnit->GenQ.Mode );
}
}
}
-
+
/* Very useful debugging tool - produces annotated listing of
* generated program with line/function references for each
* instruction back into this file:
*/
#define DISASSEM 0
-/* Should be tunable by the driver - do we want to do matrix
- * multiplications with DP4's or with MUL/MAD's? SSE works better
- * with the latter, drivers may differ.
- */
-#define PREFER_DP4 0
-
/* Use uregs to represent registers internally, translate to Mesa's
- * expected formats on emit.
+ * expected formats on emit.
*
* NOTE: These are passed by value extensively in this file rather
* than as usual by pointer reference. If this disturbs you, try
@@ -345,10 +282,11 @@ struct tnl_program {
const struct state_key *state;
struct gl_vertex_program *program;
GLint max_inst; /** number of instructions allocated for program */
-
+ GLboolean mvp_with_dp4;
+
GLuint temp_in_use;
GLuint temp_reserved;
-
+
struct ureg eye_position;
struct ureg eye_position_z;
struct ureg eye_position_normalized;
@@ -360,7 +298,7 @@ struct tnl_program {
};
-static const struct ureg undef = {
+static const struct ureg undef = {
PROGRAM_UNDEFINED,
0,
0,
@@ -395,7 +333,7 @@ static struct ureg negate( struct ureg reg )
{
reg.negate ^= 1;
return reg;
-}
+}
static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
@@ -404,7 +342,6 @@ static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
GET_SWZ(reg.swz, y),
GET_SWZ(reg.swz, z),
GET_SWZ(reg.swz, w));
-
return reg;
}
@@ -447,20 +384,52 @@ static void release_temp( struct tnl_program *p, struct ureg reg )
}
}
-
static void release_temps( struct tnl_program *p )
{
p->temp_in_use = p->temp_reserved;
}
+static struct ureg register_param5(struct tnl_program *p,
+ GLint s0,
+ GLint s1,
+ GLint s2,
+ GLint s3,
+ GLint s4)
+{
+ gl_state_index tokens[STATE_LENGTH];
+ GLint idx;
+ tokens[0] = s0;
+ tokens[1] = s1;
+ tokens[2] = s2;
+ tokens[3] = s3;
+ tokens[4] = s4;
+ idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
+ return make_ureg(PROGRAM_STATE_VAR, idx);
+}
+
+
+#define register_param1(p,s0) register_param5(p,s0,0,0,0,0)
+#define register_param2(p,s0,s1) register_param5(p,s0,s1,0,0,0)
+#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0)
+#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
+
+
+
/**
* \param input one of VERT_ATTRIB_x tokens.
*/
static struct ureg register_input( struct tnl_program *p, GLuint input )
{
- p->program->Base.InputsRead |= (1<<input);
- return make_ureg(PROGRAM_INPUT, input);
+ assert(input < 32);
+
+ if (p->state->varying_vp_inputs & (1<<input)) {
+ p->program->Base.InputsRead |= (1<<input);
+ return make_ureg(PROGRAM_INPUT, input);
+ }
+ else {
+ return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, input );
+ }
}
@@ -474,7 +443,7 @@ static struct ureg register_output( struct tnl_program *p, GLuint output )
}
-static struct ureg register_const4f( struct tnl_program *p,
+static struct ureg register_const4f( struct tnl_program *p,
GLfloat s0,
GLfloat s1,
GLfloat s2,
@@ -493,7 +462,6 @@ static struct ureg register_const4f( struct tnl_program *p,
return make_ureg(PROGRAM_CONSTANT, idx);
}
-
#define register_const1f(p, s0) register_const4f(p, s0, 0, 0, 1)
#define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0)
#define register_const2f(p, s0, s1) register_const4f(p, s0, s1, 0, 1)
@@ -507,38 +475,12 @@ static GLboolean is_undef( struct ureg reg )
static struct ureg get_identity_param( struct tnl_program *p )
{
- if (is_undef(p->identity))
+ if (is_undef(p->identity))
p->identity = register_const4f(p, 0,0,0,1);
return p->identity;
}
-
-static struct ureg register_param5(struct tnl_program *p,
- GLint s0,
- GLint s1,
- GLint s2,
- GLint s3,
- GLint s4)
-{
- gl_state_index tokens[STATE_LENGTH];
- GLint idx;
- tokens[0] = s0;
- tokens[1] = s1;
- tokens[2] = s2;
- tokens[3] = s3;
- tokens[4] = s4;
- idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
- return make_ureg(PROGRAM_STATE_VAR, idx);
-}
-
-
-#define register_param1(p,s0) register_param5(p,s0,0,0,0,0)
-#define register_param2(p,s0,s1) register_param5(p,s0,s1,0,0,0)
-#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0)
-#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
-
-
static void register_matrix_param5( struct tnl_program *p,
GLint s0, /* modelview, projection, etc */
GLint s1, /* texture matrix number */
@@ -552,7 +494,7 @@ static void register_matrix_param5( struct tnl_program *p,
/* This is a bit sad as the support is there to pull the whole
* matrix out in one go:
*/
- for (i = 0; i <= s3 - s2; i++)
+ for (i = 0; i <= s3 - s2; i++)
matrix[i] = register_param5( p, s0, s1, i, i, s4 );
}
@@ -563,9 +505,8 @@ static void emit_arg( struct prog_src_register *src,
src->File = reg.file;
src->Index = reg.idx;
src->Swizzle = reg.swz;
- src->NegateBase = reg.negate ? NEGATE_XYZW : 0;
+ src->Negate = reg.negate ? NEGATE_XYZW : NEGATE_NONE;
src->Abs = 0;
- src->NegateAbs = 0;
src->RelAddr = 0;
/* Check that bitfield sizes aren't exceeded */
ASSERT(src->Index == reg.idx);
@@ -578,7 +519,7 @@ static void emit_dst( struct prog_dst_register *dst,
dst->File = reg.file;
dst->Index = reg.idx;
/* allow zero as a shorthand for xyzw */
- dst->WriteMask = mask ? mask : WRITEMASK_XYZW;
+ dst->WriteMask = mask ? mask : WRITEMASK_XYZW;
dst->CondMask = COND_TR; /* always pass cond test */
dst->CondSwizzle = SWIZZLE_NOOP;
dst->CondSrc = 0;
@@ -593,12 +534,12 @@ static void debug_insn( struct prog_instruction *inst, const char *fn,
{
if (DISASSEM) {
static const char *last_fn;
-
+
if (fn != last_fn) {
last_fn = fn;
_mesa_printf("%s:\n", fn);
}
-
+
_mesa_printf("%d:\t", line);
_mesa_print_instruction(inst);
}
@@ -617,7 +558,7 @@ static void emit_op3fn(struct tnl_program *p,
{
GLuint nr;
struct prog_instruction *inst;
-
+
assert((GLint) p->program->Base.NumInstructions <= p->max_inst);
if (p->program->Base.NumInstructions == p->max_inst) {
@@ -642,17 +583,16 @@ static void emit_op3fn(struct tnl_program *p,
p->program->Base.Instructions = newInst;
}
-
+
nr = p->program->Base.NumInstructions++;
inst = &p->program->Base.Instructions[nr];
- inst->Opcode = (enum prog_opcode) op;
- inst->StringPos = 0;
+ inst->Opcode = (enum prog_opcode) op;
inst->Data = 0;
-
+
emit_arg( &inst->SrcReg[0], src0 );
emit_arg( &inst->SrcReg[1], src1 );
- emit_arg( &inst->SrcReg[2], src2 );
+ emit_arg( &inst->SrcReg[2], src2 );
emit_dst( &inst->DstReg, dest, mask );
@@ -672,7 +612,7 @@ static void emit_op3fn(struct tnl_program *p,
static struct ureg make_temp( struct tnl_program *p, struct ureg reg )
{
- if (reg.file == PROGRAM_TEMPORARY &&
+ if (reg.file == PROGRAM_TEMPORARY &&
!(p->temp_reserved & (1<<reg.idx)))
return reg;
else {
@@ -753,24 +693,24 @@ static void emit_normalize_vec3( struct tnl_program *p,
}
-static void emit_passthrough( struct tnl_program *p,
+static void emit_passthrough( struct tnl_program *p,
GLuint input,
GLuint output )
{
struct ureg out = register_output(p, output);
- emit_op1(p, OPCODE_MOV, out, 0, register_input(p, input));
+ emit_op1(p, OPCODE_MOV, out, 0, register_input(p, input));
}
static struct ureg get_eye_position( struct tnl_program *p )
{
if (is_undef(p->eye_position)) {
- struct ureg pos = register_input( p, VERT_ATTRIB_POS );
+ struct ureg pos = register_input( p, VERT_ATTRIB_POS );
struct ureg modelview[4];
p->eye_position = reserve_temp(p);
- if (PREFER_DP4) {
+ if (p->mvp_with_dp4) {
register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
0, modelview );
@@ -783,18 +723,18 @@ static struct ureg get_eye_position( struct tnl_program *p )
emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos);
}
}
-
+
return p->eye_position;
}
static struct ureg get_eye_position_z( struct tnl_program *p )
{
- if (!is_undef(p->eye_position))
+ if (!is_undef(p->eye_position))
return swizzle1(p->eye_position, Z);
if (is_undef(p->eye_position_z)) {
- struct ureg pos = register_input( p, VERT_ATTRIB_POS );
+ struct ureg pos = register_input( p, VERT_ATTRIB_POS );
struct ureg modelview[4];
p->eye_position_z = reserve_temp(p);
@@ -804,10 +744,10 @@ static struct ureg get_eye_position_z( struct tnl_program *p )
emit_op2(p, OPCODE_DP4, p->eye_position_z, 0, pos, modelview[2]);
}
-
+
return p->eye_position_z;
}
-
+
static struct ureg get_eye_position_normalized( struct tnl_program *p )
{
@@ -816,7 +756,7 @@ static struct ureg get_eye_position_normalized( struct tnl_program *p )
p->eye_position_normalized = reserve_temp(p);
emit_normalize_vec3(p, p->eye_position_normalized, eye);
}
-
+
return p->eye_position_normalized;
}
@@ -830,7 +770,7 @@ static struct ureg get_transformed_normal( struct tnl_program *p )
{
p->transformed_normal = register_input(p, VERT_ATTRIB_NORMAL );
}
- else if (is_undef(p->transformed_normal))
+ else if (is_undef(p->transformed_normal))
{
struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
struct ureg mvinv[3];
@@ -861,7 +801,7 @@ static struct ureg get_transformed_normal( struct tnl_program *p )
emit_op2( p, OPCODE_MUL, transformed_normal, 0, normal, rescale );
normal = transformed_normal;
}
-
+
assert(normal.file == PROGRAM_TEMPORARY);
p->transformed_normal = normal;
}
@@ -872,17 +812,17 @@ static struct ureg get_transformed_normal( struct tnl_program *p )
static void build_hpos( struct tnl_program *p )
{
- struct ureg pos = register_input( p, VERT_ATTRIB_POS );
+ struct ureg pos = register_input( p, VERT_ATTRIB_POS );
struct ureg hpos = register_output( p, VERT_RESULT_HPOS );
struct ureg mvp[4];
- if (PREFER_DP4) {
- register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
+ if (p->mvp_with_dp4) {
+ register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
0, mvp );
emit_matrix_transform_vec4( p, hpos, mvp, pos );
}
else {
- register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
+ register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
STATE_MATRIX_TRANSPOSE, mvp );
emit_transpose_matrix_transform_vec4( p, hpos, mvp, pos );
}
@@ -891,8 +831,7 @@ static void build_hpos( struct tnl_program *p )
static GLuint material_attrib( GLuint side, GLuint property )
{
- return ((property - STATE_AMBIENT) * 2 +
- side);
+ return (property - STATE_AMBIENT) * 2 + side;
}
@@ -904,27 +843,28 @@ static void set_material_flags( struct tnl_program *p )
p->color_materials = 0;
p->materials = 0;
- if (p->state->light_color_material) {
- p->materials =
+ if (p->state->varying_vp_inputs & VERT_BIT_COLOR0) {
+ p->materials =
p->color_materials = p->state->light_color_material_mask;
}
- p->materials |= p->state->light_material_mask;
+ p->materials |= (p->state->varying_vp_inputs >> 16);
}
-/* XXX temporary!!! */
-#define _TNL_ATTRIB_MAT_FRONT_AMBIENT 32
-
-static struct ureg get_material( struct tnl_program *p, GLuint side,
+static struct ureg get_material( struct tnl_program *p, GLuint side,
GLuint property )
{
GLuint attrib = material_attrib(side, property);
if (p->color_materials & (1<<attrib))
return register_input(p, VERT_ATTRIB_COLOR0);
- else if (p->materials & (1<<attrib))
- return register_input( p, attrib + _TNL_ATTRIB_MAT_FRONT_AMBIENT );
+ else if (p->materials & (1<<attrib)) {
+ /* Put material values in the GENERIC slots -- they are not used
+ * for anything in fixed function mode.
+ */
+ return register_input( p, attrib + VERT_ATTRIB_GENERIC0 );
+ }
else
return register_param3( p, STATE_MATERIAL, side, property );
}
@@ -953,7 +893,7 @@ static struct ureg get_scenecolor( struct tnl_program *p, GLuint side )
struct ureg material_ambient = get_material(p, side, STATE_AMBIENT);
struct ureg material_diffuse = get_material(p, side, STATE_DIFFUSE);
struct ureg tmp = make_temp(p, material_diffuse);
- emit_op3(p, OPCODE_MAD, tmp, WRITEMASK_XYZ, lm_ambient,
+ emit_op3(p, OPCODE_MAD, tmp, WRITEMASK_XYZ, lm_ambient,
material_ambient, material_emission);
return tmp;
}
@@ -962,16 +902,16 @@ static struct ureg get_scenecolor( struct tnl_program *p, GLuint side )
}
-static struct ureg get_lightprod( struct tnl_program *p, GLuint light,
+static struct ureg get_lightprod( struct tnl_program *p, GLuint light,
GLuint side, GLuint property )
{
GLuint attrib = material_attrib(side, property);
if (p->materials & (1<<attrib)) {
- struct ureg light_value =
+ struct ureg light_value =
register_param3(p, STATE_LIGHT, light, property);
struct ureg material_value = get_material(p, side, property);
struct ureg tmp = get_temp(p);
- emit_op2(p, OPCODE_MUL, tmp, 0, light_value, material_value);
+ emit_op2(p, OPCODE_MUL, tmp, 0, light_value, material_value);
return tmp;
}
else
@@ -980,7 +920,7 @@ static struct ureg get_lightprod( struct tnl_program *p, GLuint light,
static struct ureg calculate_light_attenuation( struct tnl_program *p,
- GLuint i,
+ GLuint i,
struct ureg VPpli,
struct ureg dist )
{
@@ -1008,28 +948,28 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p,
/* Calculate distance attenuation:
*/
if (p->state->unit[i].light_attenuated) {
-
/* 1/d,d,d,1/d */
- emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist);
+ emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist);
/* 1,d,d*d,1/d */
- emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y));
+ emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y));
/* 1/dist-atten */
- emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist);
+ emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist);
if (!p->state->unit[i].light_spotcutoff_is_180) {
/* dist-atten */
- emit_op1(p, OPCODE_RCP, dist, 0, dist);
+ emit_op1(p, OPCODE_RCP, dist, 0, dist);
/* spot-atten * dist-atten */
- emit_op2(p, OPCODE_MUL, att, 0, dist, att);
- } else {
+ emit_op2(p, OPCODE_MUL, att, 0, dist, att);
+ }
+ else {
/* dist-atten */
- emit_op1(p, OPCODE_RCP, att, 0, dist);
+ emit_op1(p, OPCODE_RCP, att, 0, dist);
}
}
return att;
}
-
+
/**
* Compute:
@@ -1048,7 +988,7 @@ static void emit_degenerate_lit( struct tnl_program *p,
/* MAX lit, id, dots;
*/
- emit_op2(p, OPCODE_MAX, lit, WRITEMASK_XYZW, id, dots);
+ emit_op2(p, OPCODE_MAX, lit, WRITEMASK_XYZW, id, dots);
/* result[2] = (in > 0 ? 1 : 0)
* SLT lit.z, id.z, dots; # lit.z = (0 < dots.z) ? 1 : 0
@@ -1075,22 +1015,22 @@ static void build_lighting( struct tnl_program *p )
/*
* NOTE:
- * dot.x = dot(normal, VPpli)
- * dot.y = dot(normal, halfAngle)
- * dot.z = back.shininess
- * dot.w = front.shininess
+ * dots.x = dot(normal, VPpli)
+ * dots.y = dot(normal, halfAngle)
+ * dots.z = back.shininess
+ * dots.w = front.shininess
*/
- for (i = 0; i < MAX_LIGHTS; i++)
+ for (i = 0; i < MAX_LIGHTS; i++)
if (p->state->unit[i].light_enabled)
nr_lights++;
-
+
set_material_flags(p);
{
if (!p->state->material_shininess_is_zero) {
struct ureg shininess = get_material(p, 0, STATE_SHININESS);
- emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X));
+ emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X));
release_temp(p, shininess);
}
@@ -1099,13 +1039,15 @@ static void build_lighting( struct tnl_program *p )
_col1 = make_temp(p, get_identity_param(p));
else
_col1 = _col0;
-
}
if (twoside) {
if (!p->state->material_shininess_is_zero) {
+ /* Note that we negate the back-face specular exponent here.
+ * The negation will be un-done later in the back-face code below.
+ */
struct ureg shininess = get_material(p, 1, STATE_SHININESS);
- emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z,
+ emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z,
negate(swizzle1(shininess,X)));
release_temp(p, shininess);
}
@@ -1133,12 +1075,12 @@ static void build_lighting( struct tnl_program *p )
struct ureg res0 = register_output( p, VERT_RESULT_BFC0 );
emit_op1(p, OPCODE_MOV, res0, 0, _bfc0);
}
-
+
if (twoside && separate) {
struct ureg res1 = register_output( p, VERT_RESULT_BFC1 );
emit_op1(p, OPCODE_MOV, res1, 0, _bfc1);
}
-
+
if (nr_lights == 0) {
release_temps(p);
return;
@@ -1148,39 +1090,40 @@ static void build_lighting( struct tnl_program *p )
if (p->state->unit[i].light_enabled) {
struct ureg half = undef;
struct ureg att = undef, VPpli = undef;
-
+
count++;
if (p->state->unit[i].light_eyepos3_is_zero) {
/* Can used precomputed constants in this case.
* Attenuation never applies to infinite lights.
*/
- VPpli = register_param3(p, STATE_INTERNAL,
- STATE_LIGHT_POSITION_NORMALIZED, i);
-
+ VPpli = register_param3(p, STATE_INTERNAL,
+ STATE_LIGHT_POSITION_NORMALIZED, i);
+
if (!p->state->material_shininess_is_zero) {
if (p->state->light_local_viewer) {
struct ureg eye_hat = get_eye_position_normalized(p);
half = get_temp(p);
emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
emit_normalize_vec3(p, half, half);
- } else {
- half = register_param3(p, STATE_INTERNAL,
+ }
+ else {
+ half = register_param3(p, STATE_INTERNAL,
STATE_LIGHT_HALF_VECTOR, i);
}
}
- }
+ }
else {
- struct ureg Ppli = register_param3(p, STATE_INTERNAL,
- STATE_LIGHT_POSITION, i);
+ struct ureg Ppli = register_param3(p, STATE_INTERNAL,
+ STATE_LIGHT_POSITION, i);
struct ureg V = get_eye_position(p);
struct ureg dist = get_temp(p);
- VPpli = get_temp(p);
-
+ VPpli = get_temp(p);
+
/* Calculate VPpli vector
*/
- emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V);
+ emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V);
/* Normalize VPpli. The dist value also used in
* attenuation below.
@@ -1190,7 +1133,7 @@ static void build_lighting( struct tnl_program *p )
emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist);
/* Calculate attenuation:
- */
+ */
if (!p->state->unit[i].light_spotcutoff_is_180 ||
p->state->unit[i].light_attenuated) {
att = calculate_light_attenuation(p, i, VPpli, dist);
@@ -1206,7 +1149,7 @@ static void build_lighting( struct tnl_program *p )
emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
}
else {
- struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z);
+ struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z);
emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir);
}
@@ -1248,7 +1191,8 @@ static void build_lighting( struct tnl_program *p )
res0 = _col0;
res1 = register_output( p, VERT_RESULT_COL0 );
}
- } else {
+ }
+ else {
mask0 = 0;
mask1 = 0;
res0 = _col0;
@@ -1260,12 +1204,12 @@ static void build_lighting( struct tnl_program *p )
emit_op1(p, OPCODE_LIT, lit, 0, dots);
emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0);
- }
+ }
else if (!p->state->material_shininess_is_zero) {
/* there's a non-zero specular term */
emit_op1(p, OPCODE_LIT, lit, 0, dots);
emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0);
- }
+ }
else {
/* no attenutation, no specular */
emit_degenerate_lit(p, lit, dots);
@@ -1274,7 +1218,7 @@ static void build_lighting( struct tnl_program *p )
emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0);
emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1);
-
+
release_temp(p, ambient);
release_temp(p, diffuse);
release_temp(p, specular);
@@ -1288,7 +1232,7 @@ static void build_lighting( struct tnl_program *p )
struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR);
struct ureg res0, res1;
GLuint mask0, mask1;
-
+
if (count == nr_lights) {
if (separate) {
mask0 = WRITEMASK_XYZ;
@@ -1302,13 +1246,19 @@ static void build_lighting( struct tnl_program *p )
res0 = _bfc0;
res1 = register_output( p, VERT_RESULT_BFC0 );
}
- } else {
+ }
+ else {
res0 = _bfc0;
res1 = _bfc1;
mask0 = 0;
mask1 = 0;
}
+ /* For the back face we need to negate the X and Y component
+ * dot products. dots.Z has the negated back-face specular
+ * exponent. We swizzle that into the W position. This
+ * negation makes the back-face specular term positive again.
+ */
dots = negate(swizzle(dots,X,Y,W,Z));
if (!is_undef(att)) {
@@ -1318,8 +1268,8 @@ static void build_lighting( struct tnl_program *p )
}
else if (!p->state->material_shininess_is_zero) {
emit_op1(p, OPCODE_LIT, lit, 0, dots);
- emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0);
- }
+ emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); /**/
+ }
else {
emit_degenerate_lit(p, lit, dots);
emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0);
@@ -1327,8 +1277,10 @@ static void build_lighting( struct tnl_program *p )
emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0);
emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1);
- /* restore negate flag for next lighting */
- dots = negate(dots);
+ /* restore dots to its original state for subsequent lights
+ * by negating and swizzling again.
+ */
+ dots = negate(swizzle(dots,X,Y,W,Z));
release_temp(p, ambient);
release_temp(p, diffuse);
@@ -1357,52 +1309,12 @@ static void build_fog( struct tnl_program *p )
input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X);
}
- if (p->state->fog_mode && p->state->tnl_do_vertex_fog) {
- struct ureg params = register_param2(p, STATE_INTERNAL,
- STATE_FOG_PARAMS_OPTIMIZED);
- struct ureg tmp = get_temp(p);
- GLboolean useabs = (p->state->fog_mode != FOG_EXP2);
-
- if (useabs) {
- emit_op1(p, OPCODE_ABS, tmp, 0, input);
- }
-
- switch (p->state->fog_mode) {
- case FOG_LINEAR: {
- struct ureg id = get_identity_param(p);
- emit_op3(p, OPCODE_MAD, tmp, 0, useabs ? tmp : input,
- swizzle1(params,X), swizzle1(params,Y));
- emit_op2(p, OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */
- emit_op2(p, OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W));
- break;
- }
- case FOG_EXP:
- emit_op2(p, OPCODE_MUL, tmp, 0, useabs ? tmp : input,
- swizzle1(params,Z));
- emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));
- break;
- case FOG_EXP2:
- emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,W));
- emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp);
- emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp));
- break;
- }
-
- release_temp(p, tmp);
- }
- else {
- /* results = incoming fog coords (compute fog per-fragment later)
- *
- * KW: Is it really necessary to do anything in this case?
- * BP: Yes, we always need to compute the absolute value, unless
- * we want to push that down into the fragment program...
- */
- GLboolean useabs = GL_TRUE;
- emit_op1(p, useabs ? OPCODE_ABS : OPCODE_MOV, fog, WRITEMASK_X, input);
- }
+ /* result.fog = {abs(f),0,0,1}; */
+ emit_op1(p, OPCODE_ABS, fog, WRITEMASK_X, input);
+ emit_op1(p, OPCODE_MOV, fog, WRITEMASK_YZW, get_identity_param(p));
}
-
+
static void build_reflect_texgen( struct tnl_program *p,
struct ureg dest,
GLuint writemask )
@@ -1412,9 +1324,9 @@ static void build_reflect_texgen( struct tnl_program *p,
struct ureg tmp = get_temp(p);
/* n.u */
- emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
+ emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
/* 2n.u */
- emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
+ emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
/* (-2n.u)n + u */
emit_op3(p, OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat);
@@ -1443,22 +1355,22 @@ static void build_sphere_texgen( struct tnl_program *p,
*/
/* n.u */
- emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
+ emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
/* 2n.u */
- emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
+ emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
/* (-2n.u)n + u */
- emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat);
+ emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat);
/* r + 0,0,1 */
- emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z));
+ emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z));
/* rx^2 + ry^2 + (rz+1)^2 */
- emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp);
+ emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp);
/* 2/m */
- emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
+ emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
/* 1/m */
- emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half);
+ emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half);
/* r/m + 1/2 */
- emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half);
-
+ emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half);
+
release_temp(p, tmp);
release_temp(p, r);
release_temp(p, inv_m);
@@ -1473,10 +1385,10 @@ static void build_texture_transform( struct tnl_program *p )
if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i)))
continue;
-
- if (p->state->unit[i].texgen_enabled ||
+
+ if (p->state->unit[i].texgen_enabled ||
p->state->unit[i].texmat_enabled) {
-
+
GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
struct ureg out = register_output(p, VERT_RESULT_TEX0 + i);
struct ureg out_texgen = undef;
@@ -1487,8 +1399,8 @@ static void build_texture_transform( struct tnl_program *p )
GLuint reflect_mask = 0;
GLuint normal_mask = 0;
GLuint modes[4];
-
- if (texmat_enabled)
+
+ if (texmat_enabled)
out_texgen = get_temp(p);
else
out_texgen = out;
@@ -1502,31 +1414,31 @@ static void build_texture_transform( struct tnl_program *p )
switch (modes[j]) {
case TXG_OBJ_LINEAR: {
struct ureg obj = register_input(p, VERT_ATTRIB_POS);
- struct ureg plane =
+ struct ureg plane =
register_param3(p, STATE_TEXGEN, i,
STATE_TEXGEN_OBJECT_S + j);
- emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
+ emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
obj, plane );
break;
}
case TXG_EYE_LINEAR: {
struct ureg eye = get_eye_position(p);
- struct ureg plane =
- register_param3(p, STATE_TEXGEN, i,
+ struct ureg plane =
+ register_param3(p, STATE_TEXGEN, i,
STATE_TEXGEN_EYE_S + j);
- emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
+ emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
eye, plane );
break;
}
- case TXG_SPHERE_MAP:
+ case TXG_SPHERE_MAP:
sphere_mask |= WRITEMASK_X << j;
break;
case TXG_REFLECTION_MAP:
reflect_mask |= WRITEMASK_X << j;
break;
- case TXG_NORMAL_MAP:
+ case TXG_NORMAL_MAP:
normal_mask |= WRITEMASK_X << j;
break;
case TXG_NONE:
@@ -1555,10 +1467,10 @@ static void build_texture_transform( struct tnl_program *p )
if (texmat_enabled) {
struct ureg texmat[4];
- struct ureg in = (!is_undef(out_texgen) ?
- out_texgen :
+ struct ureg in = (!is_undef(out_texgen) ?
+ out_texgen :
register_input(p, VERT_ATTRIB_TEX0+i));
- if (PREFER_DP4) {
+ if (p->mvp_with_dp4) {
register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
0, texmat );
emit_matrix_transform_vec4( p, out, texmat, in );
@@ -1571,7 +1483,7 @@ static void build_texture_transform( struct tnl_program *p )
}
release_temps(p);
- }
+ }
else {
emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i);
}
@@ -1618,17 +1530,6 @@ static void build_atten_pointsize( struct tnl_program *p )
/**
- * Emit constant point size.
- */
-static void build_constant_pointsize( struct tnl_program *p )
-{
- struct ureg state_size = register_param1(p, STATE_POINT_SIZE);
- struct ureg out = register_output(p, VERT_RESULT_PSIZ);
- emit_op1(p, OPCODE_MOV, out, WRITEMASK_X, state_size);
-}
-
-
-/**
* Pass-though per-vertex point size, from user's point size array.
*/
static void build_array_pointsize( struct tnl_program *p )
@@ -1640,7 +1541,8 @@ static void build_array_pointsize( struct tnl_program *p )
static void build_tnl_program( struct tnl_program *p )
-{ /* Emit the program, starting with modelviewproject:
+{
+ /* Emit the program, starting with modelviewproject:
*/
build_hpos(p);
@@ -1658,8 +1560,7 @@ static void build_tnl_program( struct tnl_program *p )
}
}
- if ((p->state->fragprog_inputs_read & FRAG_BIT_FOGC) ||
- p->state->fog_mode != FOG_NONE)
+ if (p->state->fragprog_inputs_read & FRAG_BIT_FOGC)
build_fog(p);
if (p->state->fragprog_inputs_read & FRAG_BITS_TEX_ANY)
@@ -1669,12 +1570,6 @@ static void build_tnl_program( struct tnl_program *p )
build_atten_pointsize(p);
else if (p->state->point_array)
build_array_pointsize(p);
-#if 0
- else
- build_constant_pointsize(p);
-#else
- (void) build_constant_pointsize;
-#endif
/* Finish up:
*/
@@ -1691,6 +1586,7 @@ static void build_tnl_program( struct tnl_program *p )
static void
create_new_program( const struct state_key *key,
struct gl_vertex_program *program,
+ GLboolean mvp_with_dp4,
GLuint max_temps)
{
struct tnl_program p;
@@ -1704,7 +1600,8 @@ create_new_program( const struct state_key *key,
p.transformed_normal = undef;
p.identity = undef;
p.temp_in_use = 0;
-
+ p.mvp_with_dp4 = mvp_with_dp4;
+
if (max_temps >= sizeof(int) * 8)
p.temp_reserved = 0;
else
@@ -1747,23 +1644,24 @@ _mesa_get_fixed_func_vertex_program(GLcontext *ctx)
*/
prog = (struct gl_vertex_program *)
_mesa_search_program_cache(ctx->VertexProgram.Cache, &key, sizeof(key));
-
+
if (!prog) {
/* OK, we'll have to build a new one */
if (0)
_mesa_printf("Build new TNL program\n");
-
+
prog = (struct gl_vertex_program *)
- ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+ ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
if (!prog)
return NULL;
create_new_program( &key, prog,
+ ctx->mvp_with_dp4,
ctx->Const.VertexProgram.MaxTemps );
#if 0
if (ctx->Driver.ProgramStringNotify)
- ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB,
+ ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB,
&prog->Base );
#endif
_mesa_program_cache_insert(ctx, ctx->VertexProgram.Cache,
diff --git a/src/mesa/main/fog.c b/src/mesa/main/fog.c
index 50a61bd84b..4323d3db82 100644
--- a/src/mesa/main/fog.c
+++ b/src/mesa/main/fog.c
@@ -67,7 +67,7 @@ _mesa_Fogiv(GLenum pname, const GLint *params )
break;
default:
/* Error will be caught later in _mesa_Fogfv */
- ;
+ ASSIGN_4V(p, 0.0F, 0.0F, 0.0F, 0.0F);
}
_mesa_Fogfv(pname, p);
}
diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c
index af78363ad3..dc79b8ca61 100644
--- a/src/mesa/main/framebuffer.c
+++ b/src/mesa/main/framebuffer.c
@@ -35,6 +35,7 @@
#include "buffers.h"
#include "context.h"
#include "depthstencil.h"
+#include "macros.h"
#include "mtypes.h"
#include "fbobject.h"
#include "framebuffer.h"
@@ -115,6 +116,7 @@ _mesa_new_framebuffer(GLcontext *ctx, GLuint name)
fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;
fb->_ColorReadBufferIndex = BUFFER_COLOR0;
fb->Delete = _mesa_destroy_framebuffer;
+ _glthread_INIT_MUTEX(fb->Mutex);
}
return fb;
}
@@ -222,45 +224,32 @@ _mesa_reference_framebuffer(struct gl_framebuffer **ptr,
/* no change */
return;
}
- if (*ptr) {
- _mesa_unreference_framebuffer(ptr);
- }
- assert(!*ptr);
- assert(fb);
- _glthread_LOCK_MUTEX(fb->Mutex);
- fb->RefCount++;
- _glthread_UNLOCK_MUTEX(fb->Mutex);
- *ptr = fb;
-}
-
-/**
- * Undo/remove a reference to a framebuffer object.
- * Decrement the framebuffer object's reference count and delete it when
- * the refcount hits zero.
- * Note: we pass the address of a pointer and set it to NULL.
- */
-void
-_mesa_unreference_framebuffer(struct gl_framebuffer **fb)
-{
- assert(fb);
- if (*fb) {
+ if (*ptr) {
+ /* unreference old renderbuffer */
GLboolean deleteFlag = GL_FALSE;
+ struct gl_framebuffer *oldFb = *ptr;
- _glthread_LOCK_MUTEX((*fb)->Mutex);
- ASSERT((*fb)->RefCount > 0);
- (*fb)->RefCount--;
- deleteFlag = ((*fb)->RefCount == 0);
- _glthread_UNLOCK_MUTEX((*fb)->Mutex);
+ _glthread_LOCK_MUTEX(oldFb->Mutex);
+ ASSERT(oldFb->RefCount > 0);
+ oldFb->RefCount--;
+ deleteFlag = (oldFb->RefCount == 0);
+ _glthread_UNLOCK_MUTEX(oldFb->Mutex);
if (deleteFlag)
- (*fb)->Delete(*fb);
+ oldFb->Delete(oldFb);
- *fb = NULL;
+ *ptr = NULL;
}
-}
-
+ assert(!*ptr);
+ if (fb) {
+ _glthread_LOCK_MUTEX(fb->Mutex);
+ fb->RefCount++;
+ _glthread_UNLOCK_MUTEX(fb->Mutex);
+ *ptr = fb;
+ }
+}
/**
@@ -418,14 +407,14 @@ _mesa_ResizeBuffersMESA( void )
/**
* Examine all the framebuffer's renderbuffers to update the Width/Height
* fields of the framebuffer. If we have renderbuffers with different
- * sizes, set the framebuffer's width and height to zero.
+ * sizes, set the framebuffer's width and height to the min size.
* Note: this is only intended for user-created framebuffers, not
* window-system framebuffes.
*/
static void
-update_framebuffer_size(struct gl_framebuffer *fb)
+update_framebuffer_size(GLcontext *ctx, struct gl_framebuffer *fb)
{
- GLboolean haveSize = GL_FALSE;
+ GLuint minWidth = ~0, minHeight = ~0;
GLuint i;
/* user-created framebuffers only */
@@ -435,21 +424,19 @@ update_framebuffer_size(struct gl_framebuffer *fb)
struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
const struct gl_renderbuffer *rb = att->Renderbuffer;
if (rb) {
- if (haveSize) {
- if (rb->Width != fb->Width && rb->Height != fb->Height) {
- /* size mismatch! */
- fb->Width = 0;
- fb->Height = 0;
- return;
- }
- }
- else {
- fb->Width = rb->Width;
- fb->Height = rb->Height;
- haveSize = GL_TRUE;
- }
+ minWidth = MIN2(minWidth, rb->Width);
+ minHeight = MIN2(minHeight, rb->Height);
}
}
+
+ if (minWidth != ~0) {
+ fb->Width = minWidth;
+ fb->Height = minHeight;
+ }
+ else {
+ fb->Width = 0;
+ fb->Height = 0;
+ }
}
@@ -469,7 +456,7 @@ _mesa_update_draw_buffer_bounds(GLcontext *ctx)
if (buffer->Name) {
/* user-created framebuffer size depends on the renderbuffers */
- update_framebuffer_size(buffer);
+ update_framebuffer_size(ctx, buffer);
}
buffer->_Xmin = 0;
@@ -544,6 +531,7 @@ _mesa_update_framebuffer_visual(struct gl_framebuffer *fb)
fb->Visual.rgbBits = fb->Visual.redBits
+ fb->Visual.greenBits + fb->Visual.blueBits;
fb->Visual.floatMode = GL_FALSE;
+ fb->Visual.samples = rb->NumSamples;
break;
}
else if (rb->_BaseFormat == GL_COLOR_INDEX) {
@@ -793,8 +781,9 @@ update_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
/* This is a user-created framebuffer.
* Completeness only matters for user-created framebuffers.
*/
- _mesa_test_framebuffer_completeness(ctx, fb);
- _mesa_update_framebuffer_visual(fb);
+ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) {
+ _mesa_test_framebuffer_completeness(ctx, fb);
+ }
}
/* Strictly speaking, we don't need to update the draw-state
@@ -828,7 +817,7 @@ _mesa_update_framebuffer(GLcontext *ctx)
/**
* Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels,
- * glCopyTex[Sub]Image, etc. exists.
+ * glCopyTex[Sub]Image, etc) exists.
* \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
* GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
* \return GL_TRUE if buffer exists, GL_FALSE otherwise
@@ -836,8 +825,12 @@ _mesa_update_framebuffer(GLcontext *ctx)
GLboolean
_mesa_source_buffer_exists(GLcontext *ctx, GLenum format)
{
- const struct gl_renderbuffer_attachment *att
- = ctx->ReadBuffer->Attachment;
+ const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment;
+
+ /* If we don't know the framebuffer status, update it now */
+ if (ctx->ReadBuffer->_Status == 0) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
+ }
if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
return GL_FALSE;
@@ -861,10 +854,8 @@ _mesa_source_buffer_exists(GLcontext *ctx, GLenum format)
if (ctx->ReadBuffer->_ColorReadBuffer == NULL) {
return GL_FALSE;
}
- /* XXX enable this post 6.5 release:
ASSERT(ctx->ReadBuffer->_ColorReadBuffer->RedBits > 0 ||
ctx->ReadBuffer->_ColorReadBuffer->IndexBits > 0);
- */
break;
case GL_DEPTH:
case GL_DEPTH_COMPONENT:
@@ -902,13 +893,17 @@ _mesa_source_buffer_exists(GLcontext *ctx, GLenum format)
/**
* As above, but for drawing operations.
- * XXX code do some code merging w/ above function.
+ * XXX could do some code merging w/ above function.
*/
GLboolean
_mesa_dest_buffer_exists(GLcontext *ctx, GLenum format)
{
- const struct gl_renderbuffer_attachment *att
- = ctx->ReadBuffer->Attachment;
+ const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
+
+ /* If we don't know the framebuffer status, update it now */
+ if (ctx->DrawBuffer->_Status == 0) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer);
+ }
if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
return GL_FALSE;
@@ -929,7 +924,7 @@ _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format)
case GL_BGRA:
case GL_ABGR_EXT:
case GL_COLOR_INDEX:
- /* nothing special */
+ /* Nothing special since GL_DRAW_BUFFER could be GL_NONE. */
/* Could assert that colorbuffer has RedBits > 0 */
break;
case GL_DEPTH:
@@ -956,7 +951,7 @@ _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format)
break;
default:
_mesa_problem(ctx,
- "Unexpected format 0x%x in _mesa_source_buffer_exists",
+ "Unexpected format 0x%x in _mesa_dest_buffer_exists",
format);
return GL_FALSE;
}
diff --git a/src/mesa/main/framebuffer.h b/src/mesa/main/framebuffer.h
index e9eeed28cb..45a4703ba9 100644
--- a/src/mesa/main/framebuffer.h
+++ b/src/mesa/main/framebuffer.h
@@ -47,9 +47,6 @@ _mesa_reference_framebuffer(struct gl_framebuffer **ptr,
struct gl_framebuffer *fb);
extern void
-_mesa_unreference_framebuffer(struct gl_framebuffer **fb);
-
-extern void
_mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint width, GLuint height);
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 8ce9b0ae69..a6e004a816 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -19,9 +19,15 @@
#define INT_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
+#define INT64_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
+#define INT64_TO_INT(I) ( (GLint)((I > INT_MAX) ? INT_MAX : ((I < INT_MIN) ? INT_MIN : (I))) )
+
#define BOOLEAN_TO_INT(B) ( (GLint) (B) )
+#define BOOLEAN_TO_INT64(B) ( (GLint64) (B) )
#define BOOLEAN_TO_FLOAT(B) ( (B) ? 1.0F : 0.0F )
+#define ENUM_TO_INT64(E) ( (GLint64) (E) )
+
/*
* Check if named extension is enabled, if not generate error and return.
@@ -276,6 +282,7 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
case GL_CURRENT_TEXTURE_COORDS:
{
const GLuint texUnit = ctx->Texture.CurrentUnit;
+ FLUSH_CURRENT(ctx, 0);
params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]);
params[1] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]);
params[2] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]);
@@ -460,7 +467,7 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
params[0] = INT_TO_BOOLEAN(ctx->List.ListBase);
break;
case GL_LIST_INDEX:
- params[0] = INT_TO_BOOLEAN(ctx->ListState.CurrentListNum);
+ params[0] = INT_TO_BOOLEAN((ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0));
break;
case GL_LIST_MODE:
{
@@ -884,21 +891,21 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
params[0] = _mesa_IsEnabled(GL_TEXTURE_2D_ARRAY_EXT);
break;
case GL_TEXTURE_BINDING_1D:
- params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1D->Name);
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_INDEX]->Name);
break;
case GL_TEXTURE_BINDING_2D:
- params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2D->Name);
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name);
break;
case GL_TEXTURE_BINDING_3D:
- params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current3D->Name);
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name);
break;
case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
CHECK_EXT1(MESA_texture_array, "GetBooleanv");
- params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1DArray->Name);
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name);
break;
case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
CHECK_EXT1(MESA_texture_array, "GetBooleanv");
- params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2DArray->Name);
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name);
break;
case GL_TEXTURE_GEN_S:
params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0);
@@ -1071,22 +1078,19 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
break;
case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
CHECK_EXT1(ARB_texture_cube_map, "GetBooleanv");
- params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap->Name);
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name);
break;
case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
CHECK_EXT1(ARB_texture_cube_map, "GetBooleanv");
params[0] = INT_TO_BOOLEAN((1 << (ctx->Const.MaxCubeTextureLevels - 1)));
break;
case GL_TEXTURE_COMPRESSION_HINT_ARB:
- CHECK_EXT1(ARB_texture_compression, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Hint.TextureCompression);
break;
case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
- CHECK_EXT1(ARB_texture_compression, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(_mesa_get_compressed_formats(ctx, NULL, GL_FALSE));
break;
case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
- CHECK_EXT1(ARB_texture_compression, "GetBooleanv");
{
GLint formats[100];
GLuint i, n = _mesa_get_compressed_formats(ctx, formats, GL_FALSE);
@@ -1368,35 +1372,27 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxTextureMaxAnisotropy);
break;
case GL_MULTISAMPLE_ARB:
- CHECK_EXT1(ARB_multisample, "GetBooleanv");
params[0] = ctx->Multisample.Enabled;
break;
case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
- CHECK_EXT1(ARB_multisample, "GetBooleanv");
params[0] = ctx->Multisample.SampleAlphaToCoverage;
break;
case GL_SAMPLE_ALPHA_TO_ONE_ARB:
- CHECK_EXT1(ARB_multisample, "GetBooleanv");
params[0] = ctx->Multisample.SampleAlphaToOne;
break;
case GL_SAMPLE_COVERAGE_ARB:
- CHECK_EXT1(ARB_multisample, "GetBooleanv");
params[0] = ctx->Multisample.SampleCoverage;
break;
case GL_SAMPLE_COVERAGE_VALUE_ARB:
- CHECK_EXT1(ARB_multisample, "GetBooleanv");
params[0] = FLOAT_TO_BOOLEAN(ctx->Multisample.SampleCoverageValue);
break;
case GL_SAMPLE_COVERAGE_INVERT_ARB:
- CHECK_EXT1(ARB_multisample, "GetBooleanv");
params[0] = ctx->Multisample.SampleCoverageInvert;
break;
case GL_SAMPLE_BUFFERS_ARB:
- CHECK_EXT1(ARB_multisample, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.sampleBuffers);
break;
case GL_SAMPLES_ARB:
- CHECK_EXT1(ARB_multisample, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.samples);
break;
case GL_RASTER_POSITION_UNCLIPPED_IBM:
@@ -1569,7 +1565,7 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
break;
case GL_TEXTURE_BINDING_RECTANGLE_NV:
CHECK_EXT1(NV_texture_rectangle, "GetBooleanv");
- params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentRect->Name);
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_RECT_INDEX]->Name);
break;
case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV:
CHECK_EXT1(NV_texture_rectangle, "GetBooleanv");
@@ -1592,43 +1588,33 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxSpotExponent);
break;
case GL_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayBufferObj->Name);
break;
case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Vertex.BufferObj->Name);
break;
case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Normal.BufferObj->Name);
break;
case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Color.BufferObj->Name);
break;
case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Index.BufferObj->Name);
break;
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name);
break;
case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name);
break;
case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->SecondaryColor.BufferObj->Name);
break;
case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->FogCoord.BufferObj->Name);
break;
case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Array.ElementArrayBufferObj->Name);
break;
case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
@@ -1736,32 +1722,17 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
params[0] = FLOAT_TO_BOOLEAN(ctx->Depth.BoundsMin);
params[1] = FLOAT_TO_BOOLEAN(ctx->Depth.BoundsMax);
break;
- case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
- CHECK_EXT1(MESA_program_debug, "GetBooleanv");
- params[0] = ctx->FragmentProgram.CallbackEnabled;
- break;
- case GL_VERTEX_PROGRAM_CALLBACK_MESA:
- CHECK_EXT1(MESA_program_debug, "GetBooleanv");
- params[0] = ctx->VertexProgram.CallbackEnabled;
- break;
- case GL_FRAGMENT_PROGRAM_POSITION_MESA:
- CHECK_EXT1(MESA_program_debug, "GetBooleanv");
- params[0] = INT_TO_BOOLEAN(ctx->FragmentProgram.CurrentPosition);
- break;
- case GL_VERTEX_PROGRAM_POSITION_MESA:
- CHECK_EXT1(MESA_program_debug, "GetBooleanv");
- params[0] = INT_TO_BOOLEAN(ctx->VertexProgram.CurrentPosition);
+ case GL_DEPTH_CLAMP:
+ CHECK_EXT1(ARB_depth_clamp, "GetBooleanv");
+ params[0] = ctx->Transform.DepthClamp;
break;
case GL_MAX_DRAW_BUFFERS_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Const.MaxDrawBuffers);
break;
case GL_DRAW_BUFFER0_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetBooleanv");
params[0] = ENUM_TO_BOOLEAN(ctx->DrawBuffer->ColorDrawBuffer[0]);
break;
case GL_DRAW_BUFFER1_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetBooleanv");
{
GLenum buffer;
if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
@@ -1773,7 +1744,6 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
}
break;
case GL_DRAW_BUFFER2_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetBooleanv");
{
GLenum buffer;
if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
@@ -1785,7 +1755,6 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
}
break;
case GL_DRAW_BUFFER3_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetBooleanv");
{
GLenum buffer;
if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
@@ -1877,6 +1846,14 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
CHECK_EXT1(EXT_framebuffer_blit, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->ReadBuffer->Name);
break;
+ case GL_PROVOKING_VERTEX_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetBooleanv");
+ params[0] = ctx->Light.ProvokingVertex;
+ break;
+ case GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetBooleanv");
+ params[0] = ctx->Const.QuadsFollowProvokingVertexConvention;
+ break;
case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
CHECK_EXT1(ARB_fragment_shader, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Const.FragmentProgram.MaxUniformComponents);
@@ -1905,6 +1882,22 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
CHECK_EXT1(ARB_shader_objects, "GetBooleanv");
params[0] = INT_TO_BOOLEAN(ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0);
break;
+ case GL_MAX_SAMPLES:
+ CHECK_EXT1(ARB_framebuffer_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxSamples);
+ break;
+ case GL_VERTEX_ARRAY_BINDING_APPLE:
+ CHECK_EXT1(APPLE_vertex_array_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Name);
+ break;
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXT1(ARB_seamless_cube_map, "GetBooleanv");
+ params[0] = ctx->Texture.CubeMapSeamless;
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ CHECK_EXT1(ARB_sync, "GetBooleanv");
+ params[0] = INT64_TO_BOOLEAN(ctx->Const.MaxServerWaitTimeout);
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetBooleanv(pname=0x%x)", pname);
}
@@ -2124,6 +2117,7 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
case GL_CURRENT_TEXTURE_COORDS:
{
const GLuint texUnit = ctx->Texture.CurrentUnit;
+ FLUSH_CURRENT(ctx, 0);
params[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0];
params[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1];
params[2] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2];
@@ -2308,7 +2302,7 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
params[0] = (GLfloat)(ctx->List.ListBase);
break;
case GL_LIST_INDEX:
- params[0] = (GLfloat)(ctx->ListState.CurrentListNum);
+ params[0] = (GLfloat)((ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0));
break;
case GL_LIST_MODE:
{
@@ -2732,21 +2726,21 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_2D_ARRAY_EXT));
break;
case GL_TEXTURE_BINDING_1D:
- params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1D->Name);
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_INDEX]->Name);
break;
case GL_TEXTURE_BINDING_2D:
- params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2D->Name);
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name);
break;
case GL_TEXTURE_BINDING_3D:
- params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current3D->Name);
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name);
break;
case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
CHECK_EXT1(MESA_texture_array, "GetFloatv");
- params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1DArray->Name);
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name);
break;
case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
CHECK_EXT1(MESA_texture_array, "GetFloatv");
- params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2DArray->Name);
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name);
break;
case GL_TEXTURE_GEN_S:
params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0));
@@ -2919,22 +2913,19 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
break;
case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
CHECK_EXT1(ARB_texture_cube_map, "GetFloatv");
- params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap->Name);
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name);
break;
case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
CHECK_EXT1(ARB_texture_cube_map, "GetFloatv");
params[0] = (GLfloat)((1 << (ctx->Const.MaxCubeTextureLevels - 1)));
break;
case GL_TEXTURE_COMPRESSION_HINT_ARB:
- CHECK_EXT1(ARB_texture_compression, "GetFloatv");
params[0] = (GLfloat)(ctx->Hint.TextureCompression);
break;
case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
- CHECK_EXT1(ARB_texture_compression, "GetFloatv");
params[0] = (GLfloat)(_mesa_get_compressed_formats(ctx, NULL, GL_FALSE));
break;
case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
- CHECK_EXT1(ARB_texture_compression, "GetFloatv");
{
GLint formats[100];
GLuint i, n = _mesa_get_compressed_formats(ctx, formats, GL_FALSE);
@@ -3216,35 +3207,27 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
params[0] = ctx->Const.MaxTextureMaxAnisotropy;
break;
case GL_MULTISAMPLE_ARB:
- CHECK_EXT1(ARB_multisample, "GetFloatv");
params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.Enabled);
break;
case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
- CHECK_EXT1(ARB_multisample, "GetFloatv");
params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleAlphaToCoverage);
break;
case GL_SAMPLE_ALPHA_TO_ONE_ARB:
- CHECK_EXT1(ARB_multisample, "GetFloatv");
params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleAlphaToOne);
break;
case GL_SAMPLE_COVERAGE_ARB:
- CHECK_EXT1(ARB_multisample, "GetFloatv");
params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleCoverage);
break;
case GL_SAMPLE_COVERAGE_VALUE_ARB:
- CHECK_EXT1(ARB_multisample, "GetFloatv");
params[0] = ctx->Multisample.SampleCoverageValue;
break;
case GL_SAMPLE_COVERAGE_INVERT_ARB:
- CHECK_EXT1(ARB_multisample, "GetFloatv");
params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleCoverageInvert);
break;
case GL_SAMPLE_BUFFERS_ARB:
- CHECK_EXT1(ARB_multisample, "GetFloatv");
params[0] = (GLfloat)(ctx->DrawBuffer->Visual.sampleBuffers);
break;
case GL_SAMPLES_ARB:
- CHECK_EXT1(ARB_multisample, "GetFloatv");
params[0] = (GLfloat)(ctx->DrawBuffer->Visual.samples);
break;
case GL_RASTER_POSITION_UNCLIPPED_IBM:
@@ -3417,7 +3400,7 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
break;
case GL_TEXTURE_BINDING_RECTANGLE_NV:
CHECK_EXT1(NV_texture_rectangle, "GetFloatv");
- params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentRect->Name);
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_RECT_INDEX]->Name);
break;
case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV:
CHECK_EXT1(NV_texture_rectangle, "GetFloatv");
@@ -3440,43 +3423,33 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
params[0] = ctx->Const.MaxSpotExponent;
break;
case GL_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ArrayBufferObj->Name);
break;
case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ArrayObj->Vertex.BufferObj->Name);
break;
case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ArrayObj->Normal.BufferObj->Name);
break;
case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ArrayObj->Color.BufferObj->Name);
break;
case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ArrayObj->Index.BufferObj->Name);
break;
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name);
break;
case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name);
break;
case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ArrayObj->SecondaryColor.BufferObj->Name);
break;
case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ArrayObj->FogCoord.BufferObj->Name);
break;
case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetFloatv");
params[0] = (GLfloat)(ctx->Array.ElementArrayBufferObj->Name);
break;
case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
@@ -3584,32 +3557,17 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
params[0] = ctx->Depth.BoundsMin;
params[1] = ctx->Depth.BoundsMax;
break;
- case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
- CHECK_EXT1(MESA_program_debug, "GetFloatv");
- params[0] = BOOLEAN_TO_FLOAT(ctx->FragmentProgram.CallbackEnabled);
- break;
- case GL_VERTEX_PROGRAM_CALLBACK_MESA:
- CHECK_EXT1(MESA_program_debug, "GetFloatv");
- params[0] = BOOLEAN_TO_FLOAT(ctx->VertexProgram.CallbackEnabled);
- break;
- case GL_FRAGMENT_PROGRAM_POSITION_MESA:
- CHECK_EXT1(MESA_program_debug, "GetFloatv");
- params[0] = (GLfloat)(ctx->FragmentProgram.CurrentPosition);
- break;
- case GL_VERTEX_PROGRAM_POSITION_MESA:
- CHECK_EXT1(MESA_program_debug, "GetFloatv");
- params[0] = (GLfloat)(ctx->VertexProgram.CurrentPosition);
+ case GL_DEPTH_CLAMP:
+ CHECK_EXT1(ARB_depth_clamp, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Transform.DepthClamp);
break;
case GL_MAX_DRAW_BUFFERS_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetFloatv");
params[0] = (GLfloat)(ctx->Const.MaxDrawBuffers);
break;
case GL_DRAW_BUFFER0_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetFloatv");
params[0] = ENUM_TO_FLOAT(ctx->DrawBuffer->ColorDrawBuffer[0]);
break;
case GL_DRAW_BUFFER1_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetFloatv");
{
GLenum buffer;
if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
@@ -3621,7 +3579,6 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
}
break;
case GL_DRAW_BUFFER2_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetFloatv");
{
GLenum buffer;
if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
@@ -3633,7 +3590,6 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
}
break;
case GL_DRAW_BUFFER3_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetFloatv");
{
GLenum buffer;
if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
@@ -3725,6 +3681,14 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
CHECK_EXT1(EXT_framebuffer_blit, "GetFloatv");
params[0] = (GLfloat)(ctx->ReadBuffer->Name);
break;
+ case GL_PROVOKING_VERTEX_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.ProvokingVertex);
+ break;
+ case GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Const.QuadsFollowProvokingVertexConvention);
+ break;
case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
CHECK_EXT1(ARB_fragment_shader, "GetFloatv");
params[0] = (GLfloat)(ctx->Const.FragmentProgram.MaxUniformComponents);
@@ -3753,6 +3717,22 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
CHECK_EXT1(ARB_shader_objects, "GetFloatv");
params[0] = (GLfloat)(ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0);
break;
+ case GL_MAX_SAMPLES:
+ CHECK_EXT1(ARB_framebuffer_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxSamples);
+ break;
+ case GL_VERTEX_ARRAY_BINDING_APPLE:
+ CHECK_EXT1(APPLE_vertex_array_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Name);
+ break;
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXT1(ARB_seamless_cube_map, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Texture.CubeMapSeamless);
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ CHECK_EXT1(ARB_sync, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxServerWaitTimeout);
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetFloatv(pname=0x%x)", pname);
}
@@ -3972,6 +3952,7 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
case GL_CURRENT_TEXTURE_COORDS:
{
const GLuint texUnit = ctx->Texture.CurrentUnit;
+ FLUSH_CURRENT(ctx, 0);
params[0] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]);
params[1] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]);
params[2] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]);
@@ -4156,7 +4137,7 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
params[0] = ctx->List.ListBase;
break;
case GL_LIST_INDEX:
- params[0] = ctx->ListState.CurrentListNum;
+ params[0] = (ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0);
break;
case GL_LIST_MODE:
{
@@ -4580,21 +4561,21 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_2D_ARRAY_EXT));
break;
case GL_TEXTURE_BINDING_1D:
- params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1D->Name;
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_INDEX]->Name;
break;
case GL_TEXTURE_BINDING_2D:
- params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2D->Name;
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name;
break;
case GL_TEXTURE_BINDING_3D:
- params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current3D->Name;
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name;
break;
case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
CHECK_EXT1(MESA_texture_array, "GetIntegerv");
- params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1DArray->Name;
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name;
break;
case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
CHECK_EXT1(MESA_texture_array, "GetIntegerv");
- params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2DArray->Name;
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name;
break;
case GL_TEXTURE_GEN_S:
params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0));
@@ -4767,22 +4748,19 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
break;
case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
CHECK_EXT1(ARB_texture_cube_map, "GetIntegerv");
- params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap->Name;
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name;
break;
case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
CHECK_EXT1(ARB_texture_cube_map, "GetIntegerv");
params[0] = (1 << (ctx->Const.MaxCubeTextureLevels - 1));
break;
case GL_TEXTURE_COMPRESSION_HINT_ARB:
- CHECK_EXT1(ARB_texture_compression, "GetIntegerv");
params[0] = ctx->Hint.TextureCompression;
break;
case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
- CHECK_EXT1(ARB_texture_compression, "GetIntegerv");
params[0] = _mesa_get_compressed_formats(ctx, NULL, GL_FALSE);
break;
case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
- CHECK_EXT1(ARB_texture_compression, "GetIntegerv");
{
GLint formats[100];
GLuint i, n = _mesa_get_compressed_formats(ctx, formats, GL_FALSE);
@@ -5064,35 +5042,27 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
params[0] = IROUND(ctx->Const.MaxTextureMaxAnisotropy);
break;
case GL_MULTISAMPLE_ARB:
- CHECK_EXT1(ARB_multisample, "GetIntegerv");
params[0] = BOOLEAN_TO_INT(ctx->Multisample.Enabled);
break;
case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
- CHECK_EXT1(ARB_multisample, "GetIntegerv");
params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleAlphaToCoverage);
break;
case GL_SAMPLE_ALPHA_TO_ONE_ARB:
- CHECK_EXT1(ARB_multisample, "GetIntegerv");
params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleAlphaToOne);
break;
case GL_SAMPLE_COVERAGE_ARB:
- CHECK_EXT1(ARB_multisample, "GetIntegerv");
params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleCoverage);
break;
case GL_SAMPLE_COVERAGE_VALUE_ARB:
- CHECK_EXT1(ARB_multisample, "GetIntegerv");
params[0] = IROUND(ctx->Multisample.SampleCoverageValue);
break;
case GL_SAMPLE_COVERAGE_INVERT_ARB:
- CHECK_EXT1(ARB_multisample, "GetIntegerv");
params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleCoverageInvert);
break;
case GL_SAMPLE_BUFFERS_ARB:
- CHECK_EXT1(ARB_multisample, "GetIntegerv");
params[0] = ctx->DrawBuffer->Visual.sampleBuffers;
break;
case GL_SAMPLES_ARB:
- CHECK_EXT1(ARB_multisample, "GetIntegerv");
params[0] = ctx->DrawBuffer->Visual.samples;
break;
case GL_RASTER_POSITION_UNCLIPPED_IBM:
@@ -5265,7 +5235,7 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
break;
case GL_TEXTURE_BINDING_RECTANGLE_NV:
CHECK_EXT1(NV_texture_rectangle, "GetIntegerv");
- params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentRect->Name;
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_RECT_INDEX]->Name;
break;
case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV:
CHECK_EXT1(NV_texture_rectangle, "GetIntegerv");
@@ -5288,43 +5258,33 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
params[0] = IROUND(ctx->Const.MaxSpotExponent);
break;
case GL_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ArrayBufferObj->Name;
break;
case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ArrayObj->Vertex.BufferObj->Name;
break;
case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ArrayObj->Normal.BufferObj->Name;
break;
case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ArrayObj->Color.BufferObj->Name;
break;
case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ArrayObj->Index.BufferObj->Name;
break;
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name;
break;
case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name;
break;
case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ArrayObj->SecondaryColor.BufferObj->Name;
break;
case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ArrayObj->FogCoord.BufferObj->Name;
break;
case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
- CHECK_EXT1(ARB_vertex_buffer_object, "GetIntegerv");
params[0] = ctx->Array.ElementArrayBufferObj->Name;
break;
case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
@@ -5432,32 +5392,17 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
params[0] = IROUND(ctx->Depth.BoundsMin);
params[1] = IROUND(ctx->Depth.BoundsMax);
break;
- case GL_FRAGMENT_PROGRAM_CALLBACK_MESA:
- CHECK_EXT1(MESA_program_debug, "GetIntegerv");
- params[0] = BOOLEAN_TO_INT(ctx->FragmentProgram.CallbackEnabled);
- break;
- case GL_VERTEX_PROGRAM_CALLBACK_MESA:
- CHECK_EXT1(MESA_program_debug, "GetIntegerv");
- params[0] = BOOLEAN_TO_INT(ctx->VertexProgram.CallbackEnabled);
- break;
- case GL_FRAGMENT_PROGRAM_POSITION_MESA:
- CHECK_EXT1(MESA_program_debug, "GetIntegerv");
- params[0] = ctx->FragmentProgram.CurrentPosition;
- break;
- case GL_VERTEX_PROGRAM_POSITION_MESA:
- CHECK_EXT1(MESA_program_debug, "GetIntegerv");
- params[0] = ctx->VertexProgram.CurrentPosition;
+ case GL_DEPTH_CLAMP:
+ CHECK_EXT1(ARB_depth_clamp, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Transform.DepthClamp);
break;
case GL_MAX_DRAW_BUFFERS_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetIntegerv");
params[0] = ctx->Const.MaxDrawBuffers;
break;
case GL_DRAW_BUFFER0_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetIntegerv");
params[0] = ENUM_TO_INT(ctx->DrawBuffer->ColorDrawBuffer[0]);
break;
case GL_DRAW_BUFFER1_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetIntegerv");
{
GLenum buffer;
if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
@@ -5469,7 +5414,6 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
}
break;
case GL_DRAW_BUFFER2_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetIntegerv");
{
GLenum buffer;
if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
@@ -5481,7 +5425,6 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
}
break;
case GL_DRAW_BUFFER3_ARB:
- CHECK_EXT1(ARB_draw_buffers, "GetIntegerv");
{
GLenum buffer;
if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
@@ -5573,6 +5516,14 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
CHECK_EXT1(EXT_framebuffer_blit, "GetIntegerv");
params[0] = ctx->ReadBuffer->Name;
break;
+ case GL_PROVOKING_VERTEX_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Light.ProvokingVertex);
+ break;
+ case GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Const.QuadsFollowProvokingVertexConvention);
+ break;
case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
CHECK_EXT1(ARB_fragment_shader, "GetIntegerv");
params[0] = ctx->Const.FragmentProgram.MaxUniformComponents;
@@ -5601,11 +5552,1864 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
CHECK_EXT1(ARB_shader_objects, "GetIntegerv");
params[0] = ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0;
break;
+ case GL_MAX_SAMPLES:
+ CHECK_EXT1(ARB_framebuffer_object, "GetIntegerv");
+ params[0] = ctx->Const.MaxSamples;
+ break;
+ case GL_VERTEX_ARRAY_BINDING_APPLE:
+ CHECK_EXT1(APPLE_vertex_array_object, "GetIntegerv");
+ params[0] = ctx->Array.ArrayObj->Name;
+ break;
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXT1(ARB_seamless_cube_map, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Texture.CubeMapSeamless);
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ CHECK_EXT1(ARB_sync, "GetIntegerv");
+ params[0] = INT64_TO_INT(ctx->Const.MaxServerWaitTimeout);
+ break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetIntegerv(pname=0x%x)", pname);
}
}
+#if FEATURE_ARB_sync
+void GLAPIENTRY
+_mesa_GetInteger64v( GLenum pname, GLint64 *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!params)
+ return;
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (ctx->Driver.GetInteger64v &&
+ ctx->Driver.GetInteger64v(ctx, pname, params))
+ return;
+
+ switch (pname) {
+ case GL_ACCUM_RED_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumRedBits;
+ break;
+ case GL_ACCUM_GREEN_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumGreenBits;
+ break;
+ case GL_ACCUM_BLUE_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumBlueBits;
+ break;
+ case GL_ACCUM_ALPHA_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumAlphaBits;
+ break;
+ case GL_ACCUM_CLEAR_VALUE:
+ params[0] = FLOAT_TO_INT64(ctx->Accum.ClearColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Accum.ClearColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Accum.ClearColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Accum.ClearColor[3]);
+ break;
+ case GL_ALPHA_BIAS:
+ params[0] = IROUND64(ctx->Pixel.AlphaBias);
+ break;
+ case GL_ALPHA_BITS:
+ params[0] = ctx->DrawBuffer->Visual.alphaBits;
+ break;
+ case GL_ALPHA_SCALE:
+ params[0] = IROUND64(ctx->Pixel.AlphaScale);
+ break;
+ case GL_ALPHA_TEST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.AlphaEnabled);
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ params[0] = ENUM_TO_INT64(ctx->Color.AlphaFunc);
+ break;
+ case GL_ALPHA_TEST_REF:
+ params[0] = FLOAT_TO_INT64(ctx->Color.AlphaRef);
+ break;
+ case GL_ATTRIB_STACK_DEPTH:
+ params[0] = ctx->AttribStackDepth;
+ break;
+ case GL_AUTO_NORMAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.AutoNormal);
+ break;
+ case GL_AUX_BUFFERS:
+ params[0] = ctx->DrawBuffer->Visual.numAuxBuffers;
+ break;
+ case GL_BLEND:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.BlendEnabled);
+ break;
+ case GL_BLEND_DST:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_SRC_RGB_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_DST_RGB_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC_ALPHA_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendSrcA);
+ break;
+ case GL_BLEND_DST_ALPHA_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendDstA);
+ break;
+ case GL_BLEND_EQUATION:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendEquationRGB );
+ break;
+ case GL_BLEND_EQUATION_ALPHA_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendEquationA );
+ break;
+ case GL_BLEND_COLOR_EXT:
+ params[0] = FLOAT_TO_INT64(ctx->Color.BlendColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Color.BlendColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Color.BlendColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Color.BlendColor[3]);
+ break;
+ case GL_BLUE_BIAS:
+ params[0] = IROUND64(ctx->Pixel.BlueBias);
+ break;
+ case GL_BLUE_BITS:
+ params[0] = ctx->DrawBuffer->Visual.blueBits;
+ break;
+ case GL_BLUE_SCALE:
+ params[0] = IROUND64(ctx->Pixel.BlueScale);
+ break;
+ case GL_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = ctx->ClientAttribStackDepth;
+ break;
+ case GL_CLIP_PLANE0:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 0) & 1);
+ break;
+ case GL_CLIP_PLANE1:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 1) & 1);
+ break;
+ case GL_CLIP_PLANE2:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 2) & 1);
+ break;
+ case GL_CLIP_PLANE3:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 3) & 1);
+ break;
+ case GL_CLIP_PLANE4:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 4) & 1);
+ break;
+ case GL_CLIP_PLANE5:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 5) & 1);
+ break;
+ case GL_COLOR_CLEAR_VALUE:
+ params[0] = FLOAT_TO_INT64(ctx->Color.ClearColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Color.ClearColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Color.ClearColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Color.ClearColor[3]);
+ break;
+ case GL_COLOR_MATERIAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.ColorMaterialEnabled);
+ break;
+ case GL_COLOR_MATERIAL_FACE:
+ params[0] = ENUM_TO_INT64(ctx->Light.ColorMaterialFace);
+ break;
+ case GL_COLOR_MATERIAL_PARAMETER:
+ params[0] = ENUM_TO_INT64(ctx->Light.ColorMaterialMode);
+ break;
+ case GL_COLOR_WRITEMASK:
+ params[0] = ctx->Color.ColorMask[RCOMP] ? 1 : 0;
+ params[1] = ctx->Color.ColorMask[GCOMP] ? 1 : 0;
+ params[2] = ctx->Color.ColorMask[BCOMP] ? 1 : 0;
+ params[3] = ctx->Color.ColorMask[ACOMP] ? 1 : 0;
+ break;
+ case GL_CULL_FACE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.CullFlag);
+ break;
+ case GL_CULL_FACE_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Polygon.CullFaceMode);
+ break;
+ case GL_CURRENT_COLOR:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2]);
+ params[3] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3]);
+ }
+ break;
+ case GL_CURRENT_INDEX:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0]);
+ }
+ break;
+ case GL_CURRENT_NORMAL:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2]);
+ }
+ break;
+ case GL_CURRENT_RASTER_COLOR:
+ params[0] = FLOAT_TO_INT64(ctx->Current.RasterColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.RasterColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.RasterColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Current.RasterColor[3]);
+ break;
+ case GL_CURRENT_RASTER_DISTANCE:
+ params[0] = IROUND64(ctx->Current.RasterDistance);
+ break;
+ case GL_CURRENT_RASTER_INDEX:
+ params[0] = IROUND64(ctx->Current.RasterIndex);
+ break;
+ case GL_CURRENT_RASTER_POSITION:
+ params[0] = IROUND64(ctx->Current.RasterPos[0]);
+ params[1] = IROUND64(ctx->Current.RasterPos[1]);
+ params[2] = IROUND64(ctx->Current.RasterPos[2]);
+ params[3] = IROUND64(ctx->Current.RasterPos[3]);
+ break;
+ case GL_CURRENT_RASTER_SECONDARY_COLOR:
+ params[0] = FLOAT_TO_INT64(ctx->Current.RasterSecondaryColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.RasterSecondaryColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.RasterSecondaryColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Current.RasterSecondaryColor[3]);
+ break;
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ params[0] = IROUND64(ctx->Current.RasterTexCoords[texUnit][0]);
+ params[1] = IROUND64(ctx->Current.RasterTexCoords[texUnit][1]);
+ params[2] = IROUND64(ctx->Current.RasterTexCoords[texUnit][2]);
+ params[3] = IROUND64(ctx->Current.RasterTexCoords[texUnit][3]);
+ }
+ break;
+ case GL_CURRENT_RASTER_POSITION_VALID:
+ params[0] = BOOLEAN_TO_INT64(ctx->Current.RasterPosValid);
+ break;
+ case GL_CURRENT_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]);
+ params[1] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]);
+ params[2] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]);
+ params[3] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3]);
+ }
+ break;
+ case GL_DEPTH_BIAS:
+ params[0] = IROUND64(ctx->Pixel.DepthBias);
+ break;
+ case GL_DEPTH_BITS:
+ params[0] = ctx->DrawBuffer->Visual.depthBits;
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ params[0] = FLOAT_TO_INT64(((GLfloat) ctx->Depth.Clear));
+ break;
+ case GL_DEPTH_FUNC:
+ params[0] = ENUM_TO_INT64(ctx->Depth.Func);
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = FLOAT_TO_INT64(ctx->Viewport.Near);
+ params[1] = FLOAT_TO_INT64(ctx->Viewport.Far);
+ break;
+ case GL_DEPTH_SCALE:
+ params[0] = IROUND64(ctx->Pixel.DepthScale);
+ break;
+ case GL_DEPTH_TEST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Depth.Test);
+ break;
+ case GL_DEPTH_WRITEMASK:
+ params[0] = BOOLEAN_TO_INT64(ctx->Depth.Mask);
+ break;
+ case GL_DITHER:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.DitherFlag);
+ break;
+ case GL_DOUBLEBUFFER:
+ params[0] = BOOLEAN_TO_INT64(ctx->DrawBuffer->Visual.doubleBufferMode);
+ break;
+ case GL_DRAW_BUFFER:
+ params[0] = ENUM_TO_INT64(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_EDGE_FLAG:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = BOOLEAN_TO_INT64((ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0));
+ }
+ break;
+ case GL_FEEDBACK_BUFFER_SIZE:
+ params[0] = ctx->Feedback.BufferSize;
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Feedback.Type);
+ break;
+ case GL_FOG:
+ params[0] = BOOLEAN_TO_INT64(ctx->Fog.Enabled);
+ break;
+ case GL_FOG_COLOR:
+ params[0] = FLOAT_TO_INT64(ctx->Fog.Color[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Fog.Color[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Fog.Color[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Fog.Color[3]);
+ break;
+ case GL_FOG_DENSITY:
+ params[0] = IROUND64(ctx->Fog.Density);
+ break;
+ case GL_FOG_END:
+ params[0] = IROUND64(ctx->Fog.End);
+ break;
+ case GL_FOG_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.Fog);
+ break;
+ case GL_FOG_INDEX:
+ params[0] = IROUND64(ctx->Fog.Index);
+ break;
+ case GL_FOG_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Fog.Mode);
+ break;
+ case GL_FOG_START:
+ params[0] = IROUND64(ctx->Fog.Start);
+ break;
+ case GL_FRONT_FACE:
+ params[0] = ENUM_TO_INT64(ctx->Polygon.FrontFace);
+ break;
+ case GL_GREEN_BIAS:
+ params[0] = IROUND64(ctx->Pixel.GreenBias);
+ break;
+ case GL_GREEN_BITS:
+ params[0] = ctx->DrawBuffer->Visual.greenBits;
+ break;
+ case GL_GREEN_SCALE:
+ params[0] = IROUND64(ctx->Pixel.GreenScale);
+ break;
+ case GL_INDEX_BITS:
+ params[0] = ctx->DrawBuffer->Visual.indexBits;
+ break;
+ case GL_INDEX_CLEAR_VALUE:
+ params[0] = ctx->Color.ClearIndex;
+ break;
+ case GL_INDEX_MODE:
+ params[0] = BOOLEAN_TO_INT64(!ctx->DrawBuffer->Visual.rgbMode);
+ break;
+ case GL_INDEX_OFFSET:
+ params[0] = ctx->Pixel.IndexOffset;
+ break;
+ case GL_INDEX_SHIFT:
+ params[0] = ctx->Pixel.IndexShift;
+ break;
+ case GL_INDEX_WRITEMASK:
+ params[0] = ctx->Color.IndexMask;
+ break;
+ case GL_LIGHT0:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[0].Enabled);
+ break;
+ case GL_LIGHT1:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[1].Enabled);
+ break;
+ case GL_LIGHT2:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[2].Enabled);
+ break;
+ case GL_LIGHT3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[3].Enabled);
+ break;
+ case GL_LIGHT4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[4].Enabled);
+ break;
+ case GL_LIGHT5:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[5].Enabled);
+ break;
+ case GL_LIGHT6:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[6].Enabled);
+ break;
+ case GL_LIGHT7:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[7].Enabled);
+ break;
+ case GL_LIGHTING:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Enabled);
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ params[0] = FLOAT_TO_INT64(ctx->Light.Model.Ambient[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Light.Model.Ambient[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Light.Model.Ambient[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Light.Model.Ambient[3]);
+ break;
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ params[0] = ENUM_TO_INT64(ctx->Light.Model.ColorControl);
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Model.LocalViewer);
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Model.TwoSide);
+ break;
+ case GL_LINE_SMOOTH:
+ params[0] = BOOLEAN_TO_INT64(ctx->Line.SmoothFlag);
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.LineSmooth);
+ break;
+ case GL_LINE_STIPPLE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Line.StippleFlag);
+ break;
+ case GL_LINE_STIPPLE_PATTERN:
+ params[0] = ctx->Line.StipplePattern;
+ break;
+ case GL_LINE_STIPPLE_REPEAT:
+ params[0] = ctx->Line.StippleFactor;
+ break;
+ case GL_LINE_WIDTH:
+ params[0] = IROUND64(ctx->Line.Width);
+ break;
+ case GL_LINE_WIDTH_GRANULARITY:
+ params[0] = IROUND64(ctx->Const.LineWidthGranularity);
+ break;
+ case GL_LINE_WIDTH_RANGE:
+ params[0] = IROUND64(ctx->Const.MinLineWidthAA);
+ params[1] = IROUND64(ctx->Const.MaxLineWidthAA);
+ break;
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ params[0] = IROUND64(ctx->Const.MinLineWidth);
+ params[1] = IROUND64(ctx->Const.MaxLineWidth);
+ break;
+ case GL_LIST_BASE:
+ params[0] = ctx->List.ListBase;
+ break;
+ case GL_LIST_INDEX:
+ params[0] = (ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0);
+ break;
+ case GL_LIST_MODE:
+ {
+ GLenum mode;
+ if (!ctx->CompileFlag)
+ mode = 0;
+ else if (ctx->ExecuteFlag)
+ mode = GL_COMPILE_AND_EXECUTE;
+ else
+ mode = GL_COMPILE;
+ params[0] = ENUM_TO_INT64(mode);
+ }
+ break;
+ case GL_INDEX_LOGIC_OP:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.IndexLogicOpEnabled);
+ break;
+ case GL_COLOR_LOGIC_OP:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.ColorLogicOpEnabled);
+ break;
+ case GL_LOGIC_OP_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Color.LogicOp);
+ break;
+ case GL_MAP1_COLOR_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Color4);
+ break;
+ case GL_MAP1_GRID_DOMAIN:
+ params[0] = IROUND64(ctx->Eval.MapGrid1u1);
+ params[1] = IROUND64(ctx->Eval.MapGrid1u2);
+ break;
+ case GL_MAP1_GRID_SEGMENTS:
+ params[0] = ctx->Eval.MapGrid1un;
+ break;
+ case GL_MAP1_INDEX:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Index);
+ break;
+ case GL_MAP1_NORMAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Normal);
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1TextureCoord1);
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1TextureCoord2);
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1TextureCoord3);
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1TextureCoord4);
+ break;
+ case GL_MAP1_VERTEX_3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Vertex3);
+ break;
+ case GL_MAP1_VERTEX_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Vertex4);
+ break;
+ case GL_MAP2_COLOR_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Color4);
+ break;
+ case GL_MAP2_GRID_DOMAIN:
+ params[0] = IROUND64(ctx->Eval.MapGrid2u1);
+ params[1] = IROUND64(ctx->Eval.MapGrid2u2);
+ params[2] = IROUND64(ctx->Eval.MapGrid2v1);
+ params[3] = IROUND64(ctx->Eval.MapGrid2v2);
+ break;
+ case GL_MAP2_GRID_SEGMENTS:
+ params[0] = ctx->Eval.MapGrid2un;
+ params[1] = ctx->Eval.MapGrid2vn;
+ break;
+ case GL_MAP2_INDEX:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Index);
+ break;
+ case GL_MAP2_NORMAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Normal);
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2TextureCoord1);
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2TextureCoord2);
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2TextureCoord3);
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2TextureCoord4);
+ break;
+ case GL_MAP2_VERTEX_3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Vertex3);
+ break;
+ case GL_MAP2_VERTEX_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Vertex4);
+ break;
+ case GL_MAP_COLOR:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.MapColorFlag);
+ break;
+ case GL_MAP_STENCIL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.MapStencilFlag);
+ break;
+ case GL_MATRIX_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Transform.MatrixMode);
+ break;
+ case GL_MAX_ATTRIB_STACK_DEPTH:
+ params[0] = MAX_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = MAX_CLIENT_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIP_PLANES:
+ params[0] = ctx->Const.MaxClipPlanes;
+ break;
+ case GL_MAX_ELEMENTS_VERTICES:
+ params[0] = ctx->Const.MaxArrayLockSize;
+ break;
+ case GL_MAX_ELEMENTS_INDICES:
+ params[0] = ctx->Const.MaxArrayLockSize;
+ break;
+ case GL_MAX_EVAL_ORDER:
+ params[0] = MAX_EVAL_ORDER;
+ break;
+ case GL_MAX_LIGHTS:
+ params[0] = ctx->Const.MaxLights;
+ break;
+ case GL_MAX_LIST_NESTING:
+ params[0] = MAX_LIST_NESTING;
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ params[0] = MAX_MODELVIEW_STACK_DEPTH;
+ break;
+ case GL_MAX_NAME_STACK_DEPTH:
+ params[0] = MAX_NAME_STACK_DEPTH;
+ break;
+ case GL_MAX_PIXEL_MAP_TABLE:
+ params[0] = MAX_PIXEL_MAP_TABLE;
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ params[0] = MAX_PROJECTION_STACK_DEPTH;
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ params[0] = 1 << (ctx->Const.MaxTextureLevels - 1);
+ break;
+ case GL_MAX_3D_TEXTURE_SIZE:
+ params[0] = 1 << (ctx->Const.Max3DTextureLevels - 1);
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ params[0] = MAX_TEXTURE_STACK_DEPTH;
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ params[0] = ctx->Const.MaxViewportWidth;
+ params[1] = ctx->Const.MaxViewportHeight;
+ break;
+ case GL_MODELVIEW_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ params[0] = ctx->ModelviewMatrixStack.Depth + 1;
+ break;
+ case GL_NAME_STACK_DEPTH:
+ params[0] = ctx->Select.NameStackDepth;
+ break;
+ case GL_NORMALIZE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Transform.Normalize);
+ break;
+ case GL_PACK_ALIGNMENT:
+ params[0] = ctx->Pack.Alignment;
+ break;
+ case GL_PACK_LSB_FIRST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pack.LsbFirst);
+ break;
+ case GL_PACK_ROW_LENGTH:
+ params[0] = ctx->Pack.RowLength;
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ params[0] = ctx->Pack.SkipPixels;
+ break;
+ case GL_PACK_SKIP_ROWS:
+ params[0] = ctx->Pack.SkipRows;
+ break;
+ case GL_PACK_SWAP_BYTES:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pack.SwapBytes);
+ break;
+ case GL_PACK_SKIP_IMAGES_EXT:
+ params[0] = ctx->Pack.SkipImages;
+ break;
+ case GL_PACK_IMAGE_HEIGHT_EXT:
+ params[0] = ctx->Pack.ImageHeight;
+ break;
+ case GL_PACK_INVERT_MESA:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pack.Invert);
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.PerspectiveCorrection);
+ break;
+ case GL_PIXEL_MAP_A_TO_A_SIZE:
+ params[0] = ctx->PixelMaps.AtoA.Size;
+ break;
+ case GL_PIXEL_MAP_B_TO_B_SIZE:
+ params[0] = ctx->PixelMaps.BtoB.Size;
+ break;
+ case GL_PIXEL_MAP_G_TO_G_SIZE:
+ params[0] = ctx->PixelMaps.GtoG.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_A_SIZE:
+ params[0] = ctx->PixelMaps.ItoA.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_B_SIZE:
+ params[0] = ctx->PixelMaps.ItoB.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_G_SIZE:
+ params[0] = ctx->PixelMaps.ItoG.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_I_SIZE:
+ params[0] = ctx->PixelMaps.ItoI.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_R_SIZE:
+ params[0] = ctx->PixelMaps.ItoR.Size;
+ break;
+ case GL_PIXEL_MAP_R_TO_R_SIZE:
+ params[0] = ctx->PixelMaps.RtoR.Size;
+ break;
+ case GL_PIXEL_MAP_S_TO_S_SIZE:
+ params[0] = ctx->PixelMaps.StoS.Size;
+ break;
+ case GL_POINT_SIZE:
+ params[0] = IROUND64(ctx->Point.Size);
+ break;
+ case GL_POINT_SIZE_GRANULARITY:
+ params[0] = IROUND64(ctx->Const.PointSizeGranularity);
+ break;
+ case GL_POINT_SIZE_RANGE:
+ params[0] = IROUND64(ctx->Const.MinPointSizeAA);
+ params[1] = IROUND64(ctx->Const.MaxPointSizeAA);
+ break;
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ params[0] = IROUND64(ctx->Const.MinPointSize);
+ params[1] = IROUND64(ctx->Const.MaxPointSize);
+ break;
+ case GL_POINT_SMOOTH:
+ params[0] = BOOLEAN_TO_INT64(ctx->Point.SmoothFlag);
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.PointSmooth);
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ params[0] = IROUND64(ctx->Point.MinSize);
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ params[0] = IROUND64(ctx->Point.MaxSize);
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ params[0] = IROUND64(ctx->Point.Threshold);
+ break;
+ case GL_DISTANCE_ATTENUATION_EXT:
+ params[0] = IROUND64(ctx->Point.Params[0]);
+ params[1] = IROUND64(ctx->Point.Params[1]);
+ params[2] = IROUND64(ctx->Point.Params[2]);
+ break;
+ case GL_POLYGON_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Polygon.FrontMode);
+ params[1] = ENUM_TO_INT64(ctx->Polygon.BackMode);
+ break;
+ case GL_POLYGON_OFFSET_BIAS_EXT:
+ params[0] = IROUND64(ctx->Polygon.OffsetUnits);
+ break;
+ case GL_POLYGON_OFFSET_FACTOR:
+ params[0] = IROUND64(ctx->Polygon.OffsetFactor );
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ params[0] = IROUND64(ctx->Polygon.OffsetUnits );
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.OffsetPoint);
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.OffsetLine);
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.OffsetFill);
+ break;
+ case GL_POLYGON_SMOOTH:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.SmoothFlag);
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.PolygonSmooth);
+ break;
+ case GL_POLYGON_STIPPLE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.StippleFlag);
+ break;
+ case GL_PROJECTION_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_PROJECTION_STACK_DEPTH:
+ params[0] = ctx->ProjectionMatrixStack.Depth + 1;
+ break;
+ case GL_READ_BUFFER:
+ params[0] = ENUM_TO_INT64(ctx->ReadBuffer->ColorReadBuffer);
+ break;
+ case GL_RED_BIAS:
+ params[0] = IROUND64(ctx->Pixel.RedBias);
+ break;
+ case GL_RED_BITS:
+ params[0] = ctx->DrawBuffer->Visual.redBits;
+ break;
+ case GL_RED_SCALE:
+ params[0] = IROUND64(ctx->Pixel.RedScale);
+ break;
+ case GL_RENDER_MODE:
+ params[0] = ENUM_TO_INT64(ctx->RenderMode);
+ break;
+ case GL_RESCALE_NORMAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Transform.RescaleNormals);
+ break;
+ case GL_RGBA_MODE:
+ params[0] = BOOLEAN_TO_INT64(ctx->DrawBuffer->Visual.rgbMode);
+ break;
+ case GL_SCISSOR_BOX:
+ params[0] = ctx->Scissor.X;
+ params[1] = ctx->Scissor.Y;
+ params[2] = ctx->Scissor.Width;
+ params[3] = ctx->Scissor.Height;
+ break;
+ case GL_SCISSOR_TEST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Scissor.Enabled);
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ params[0] = ctx->Select.BufferSize;
+ break;
+ case GL_SHADE_MODEL:
+ params[0] = ENUM_TO_INT64(ctx->Light.ShadeModel);
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ params[0] = BOOLEAN_TO_INT64(ctx->Texture.SharedPalette);
+ break;
+ case GL_STENCIL_BITS:
+ params[0] = ctx->DrawBuffer->Visual.stencilBits;
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ params[0] = ctx->Stencil.Clear;
+ break;
+ case GL_STENCIL_FAIL:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_FUNC:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.Function[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_REF:
+ params[0] = ctx->Stencil.Ref[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_TEST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Stencil.Enabled);
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ params[0] = ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_WRITEMASK:
+ params[0] = ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STEREO:
+ params[0] = BOOLEAN_TO_INT64(ctx->DrawBuffer->Visual.stereoMode);
+ break;
+ case GL_SUBPIXEL_BITS:
+ params[0] = ctx->Const.SubPixelBits;
+ break;
+ case GL_TEXTURE_1D:
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_1D));
+ break;
+ case GL_TEXTURE_2D:
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_2D));
+ break;
+ case GL_TEXTURE_3D:
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_3D));
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_1D_ARRAY_EXT));
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_2D_ARRAY_EXT));
+ break;
+ case GL_TEXTURE_BINDING_1D:
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetInteger64v");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetInteger64v");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name;
+ break;
+ case GL_TEXTURE_GEN_S:
+ params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_T:
+ params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & T_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_R:
+ params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & R_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_Q:
+ params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & Q_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_MATRIX:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TEXTURE_STACK_DEPTH:
+ params[0] = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Depth + 1;
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ params[0] = ctx->Unpack.Alignment;
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Unpack.LsbFirst);
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ params[0] = ctx->Unpack.RowLength;
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ params[0] = ctx->Unpack.SkipPixels;
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ params[0] = ctx->Unpack.SkipRows;
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ params[0] = BOOLEAN_TO_INT64(ctx->Unpack.SwapBytes);
+ break;
+ case GL_UNPACK_SKIP_IMAGES_EXT:
+ params[0] = ctx->Unpack.SkipImages;
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT_EXT:
+ params[0] = ctx->Unpack.ImageHeight;
+ break;
+ case GL_UNPACK_CLIENT_STORAGE_APPLE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Unpack.ClientStorage);
+ break;
+ case GL_VIEWPORT:
+ params[0] = ctx->Viewport.X;
+ params[1] = ctx->Viewport.Y;
+ params[2] = ctx->Viewport.Width;
+ params[3] = ctx->Viewport.Height;
+ break;
+ case GL_ZOOM_X:
+ params[0] = IROUND64(ctx->Pixel.ZoomX);
+ break;
+ case GL_ZOOM_Y:
+ params[0] = IROUND64(ctx->Pixel.ZoomY);
+ break;
+ case GL_VERTEX_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->Vertex.Enabled);
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ params[0] = ctx->Array.ArrayObj->Vertex.Size;
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Vertex.Type);
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Vertex.Stride;
+ break;
+ case GL_VERTEX_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_NORMAL_ARRAY:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Normal.Enabled);
+ break;
+ case GL_NORMAL_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Normal.Type);
+ break;
+ case GL_NORMAL_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Normal.Stride;
+ break;
+ case GL_NORMAL_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_COLOR_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->Color.Enabled);
+ break;
+ case GL_COLOR_ARRAY_SIZE:
+ params[0] = ctx->Array.ArrayObj->Color.Size;
+ break;
+ case GL_COLOR_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Color.Type);
+ break;
+ case GL_COLOR_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Color.Stride;
+ break;
+ case GL_COLOR_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_INDEX_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->Index.Enabled);
+ break;
+ case GL_INDEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Index.Type);
+ break;
+ case GL_INDEX_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Index.Stride;
+ break;
+ case GL_INDEX_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Size;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Type);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Stride;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->EdgeFlag.Enabled);
+ break;
+ case GL_EDGE_FLAG_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->EdgeFlag.Stride;
+ break;
+ case GL_EDGE_FLAG_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_MAX_TEXTURE_UNITS_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetInteger64v");
+ params[0] = ctx->Const.MaxTextureUnits;
+ break;
+ case GL_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetInteger64v");
+ params[0] = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit;
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetInteger64v");
+ params[0] = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture;
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB));
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetInteger64v");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name;
+ break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetInteger64v");
+ params[0] = (1 << (ctx->Const.MaxCubeTextureLevels - 1));
+ break;
+ case GL_TEXTURE_COMPRESSION_HINT_ARB:
+ params[0] = ctx->Hint.TextureCompression;
+ break;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
+ params[0] = _mesa_get_compressed_formats(ctx, NULL, GL_FALSE);
+ break;
+ case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
+ {
+ GLint formats[100];
+ GLuint i, n = _mesa_get_compressed_formats(ctx, formats, GL_FALSE);
+ ASSERT(n <= 100);
+ for (i = 0; i < n; i++)
+ params[i] = ENUM_TO_INT64(formats[i]);
+ }
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_FIRST_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetInteger64v");
+ params[0] = ctx->Array.LockFirst;
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_COUNT_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetInteger64v");
+ params[0] = ctx->Array.LockCount;
+ break;
+ case GL_TRANSPOSE_COLOR_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_MODELVIEW_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_PROJECTION_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_TEXTURE_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_COLOR_MATRIX_SGI:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = ctx->ColorMatrixStack.Depth + 1;
+ break;
+ case GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = MAX_COLOR_STACK_DEPTH;
+ break;
+ case GL_POST_COLOR_MATRIX_RED_SCALE_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixScale[0]);
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixScale[1]);
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixScale[2]);
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixScale[3]);
+ break;
+ case GL_POST_COLOR_MATRIX_RED_BIAS_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixBias[0]);
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixBias[1]);
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixBias[2]);
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixBias[3]);
+ break;
+ case GL_CONVOLUTION_1D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.Convolution1DEnabled);
+ break;
+ case GL_CONVOLUTION_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.Convolution2DEnabled);
+ break;
+ case GL_SEPARABLE_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.Separable2DEnabled);
+ break;
+ case GL_POST_CONVOLUTION_RED_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionScale[0]);
+ break;
+ case GL_POST_CONVOLUTION_GREEN_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionScale[1]);
+ break;
+ case GL_POST_CONVOLUTION_BLUE_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionScale[2]);
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionScale[3]);
+ break;
+ case GL_POST_CONVOLUTION_RED_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionBias[0]);
+ break;
+ case GL_POST_CONVOLUTION_GREEN_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionBias[1]);
+ break;
+ case GL_POST_CONVOLUTION_BLUE_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionBias[2]);
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionBias[3]);
+ break;
+ case GL_HISTOGRAM:
+ CHECK_EXT1(EXT_histogram, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.HistogramEnabled);
+ break;
+ case GL_MINMAX:
+ CHECK_EXT1(EXT_histogram, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.MinMaxEnabled);
+ break;
+ case GL_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION]);
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION]);
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX]);
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_texture_color_table, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled);
+ break;
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXT2(EXT_secondary_color, ARB_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Fog.ColorSumEnabled);
+ break;
+ case GL_CURRENT_SECONDARY_COLOR_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2]);
+ params[3] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3]);
+ }
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->SecondaryColor.Enabled);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->SecondaryColor.Type);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.Stride;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_SIZE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.Size;
+ break;
+ case GL_CURRENT_FOG_COORDINATE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_FOG][0]);
+ }
+ break;
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->FogCoord.Enabled);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->FogCoord.Type);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ params[0] = ctx->Array.ArrayObj->FogCoord.Stride;
+ break;
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Fog.FogCoordinateSource);
+ break;
+ case GL_MAX_TEXTURE_LOD_BIAS_EXT:
+ CHECK_EXT1(EXT_texture_lod_bias, "GetInteger64v");
+ params[0] = IROUND64(ctx->Const.MaxTextureLodBias);
+ break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ CHECK_EXT1(EXT_texture_filter_anisotropic, "GetInteger64v");
+ params[0] = IROUND64(ctx->Const.MaxTextureMaxAnisotropy);
+ break;
+ case GL_MULTISAMPLE_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.Enabled);
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.SampleAlphaToCoverage);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.SampleAlphaToOne);
+ break;
+ case GL_SAMPLE_COVERAGE_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.SampleCoverage);
+ break;
+ case GL_SAMPLE_COVERAGE_VALUE_ARB:
+ params[0] = IROUND64(ctx->Multisample.SampleCoverageValue);
+ break;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.SampleCoverageInvert);
+ break;
+ case GL_SAMPLE_BUFFERS_ARB:
+ params[0] = ctx->DrawBuffer->Visual.sampleBuffers;
+ break;
+ case GL_SAMPLES_ARB:
+ params[0] = ctx->DrawBuffer->Visual.samples;
+ break;
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXT1(IBM_rasterpos_clip, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Transform.RasterPositionUnclipped);
+ break;
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Point.PointSprite);
+ break;
+ case GL_POINT_SPRITE_R_MODE_NV:
+ CHECK_EXT1(NV_point_sprite, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Point.SpriteRMode);
+ break;
+ case GL_POINT_SPRITE_COORD_ORIGIN:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Point.SpriteOrigin);
+ break;
+ case GL_GENERATE_MIPMAP_HINT_SGIS:
+ CHECK_EXT1(SGIS_generate_mipmap, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Hint.GenerateMipmap);
+ break;
+ case GL_VERTEX_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = (ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[0].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[1].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[2].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[3].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[4].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[5].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[6].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[7].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[8].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[9].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[10].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[11].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[12].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[13].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[14].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[15].Enabled);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[0]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[1]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[2]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[3]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[4]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[5]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[6]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[7]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[8]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[9]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[10]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[11]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[12]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[13]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[14]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[15]);
+ break;
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXT1(NV_fragment_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->FragmentProgram.Enabled);
+ break;
+ case GL_FRAGMENT_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_fragment_program, "GetInteger64v");
+ params[0] = ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0;
+ break;
+ case GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV:
+ CHECK_EXT1(NV_fragment_program, "GetInteger64v");
+ params[0] = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_RECTANGLE_NV));
+ break;
+ case GL_TEXTURE_BINDING_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetInteger64v");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_RECT_INDEX]->Name;
+ break;
+ case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetInteger64v");
+ params[0] = ctx->Const.MaxTextureRectSize;
+ break;
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Stencil.TestTwoSide);
+ break;
+ case GL_ACTIVE_STENCIL_FACE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT);
+ break;
+ case GL_MAX_SHININESS_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetInteger64v");
+ params[0] = IROUND64(ctx->Const.MaxShininess);
+ break;
+ case GL_MAX_SPOT_EXPONENT_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetInteger64v");
+ params[0] = IROUND64(ctx->Const.MaxSpotExponent);
+ break;
+ case GL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayBufferObj->Name;
+ break;
+ case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Vertex.BufferObj->Name;
+ break;
+ case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Normal.BufferObj->Name;
+ break;
+ case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Color.BufferObj->Name;
+ break;
+ case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Index.BufferObj->Name;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name;
+ break;
+ case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.BufferObj->Name;
+ break;
+ case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->FogCoord.BufferObj->Name;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ElementArrayBufferObj->Name;
+ break;
+ case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetInteger64v");
+ params[0] = ctx->Pack.BufferObj->Name;
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetInteger64v");
+ params[0] = ctx->Unpack.BufferObj->Name;
+ break;
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->VertexProgram.Enabled);
+ break;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->VertexProgram.PointSizeEnabled);
+ break;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->VertexProgram.TwoSideEnabled);
+ break;
+ case GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetInteger64v");
+ params[0] = ctx->Const.MaxProgramMatrixStackDepth;
+ break;
+ case GL_MAX_PROGRAM_MATRICES_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetInteger64v");
+ params[0] = ctx->Const.MaxProgramMatrices;
+ break;
+ case GL_CURRENT_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->CurrentStack->Depth + 1);
+ break;
+ case GL_CURRENT_MATRIX_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_fragment_program, "GetInteger64v");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_CURRENT_MATRIX_ARB:
+ CHECK_EXT2(ARB_vertex_program, ARB_fragment_program, "GetInteger64v");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_MAX_VERTEX_ATTRIBS_ARB:
+ CHECK_EXT1(ARB_vertex_program, "GetInteger64v");
+ params[0] = ctx->Const.VertexProgram.MaxAttribs;
+ break;
+ case GL_PROGRAM_ERROR_POSITION_ARB:
+ CHECK_EXT4(NV_vertex_program, ARB_vertex_program, NV_fragment_program, ARB_fragment_program, "GetInteger64v");
+ params[0] = ctx->Program.ErrorPos;
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ CHECK_EXT1(ARB_fragment_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->FragmentProgram.Enabled);
+ break;
+ case GL_MAX_TEXTURE_COORDS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetInteger64v");
+ params[0] = ctx->Const.MaxTextureCoordUnits;
+ break;
+ case GL_MAX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetInteger64v");
+ params[0] = ctx->Const.MaxTextureImageUnits;
+ break;
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Depth.BoundsTest);
+ break;
+ case GL_DEPTH_BOUNDS_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetInteger64v");
+ params[0] = IROUND64(ctx->Depth.BoundsMin);
+ params[1] = IROUND64(ctx->Depth.BoundsMax);
+ break;
+ case GL_DEPTH_CLAMP:
+ CHECK_EXT1(ARB_depth_clamp, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Transform.DepthClamp);
+ break;
+ case GL_MAX_DRAW_BUFFERS_ARB:
+ params[0] = ctx->Const.MaxDrawBuffers;
+ break;
+ case GL_DRAW_BUFFER0_ARB:
+ params[0] = ENUM_TO_INT64(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_DRAW_BUFFER1_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[1];
+ params[0] = ENUM_TO_INT64(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER2_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[2];
+ params[0] = ENUM_TO_INT64(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER3_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[3];
+ params[0] = ENUM_TO_INT64(buffer);
+ }
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+ CHECK_EXT1(OES_read_format, "GetInteger64v");
+ params[0] = ctx->Const.ColorReadType;
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+ CHECK_EXT1(OES_read_format, "GetInteger64v");
+ params[0] = ctx->Const.ColorReadFormat;
+ break;
+ case GL_NUM_FRAGMENT_REGISTERS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 6;
+ break;
+ case GL_NUM_FRAGMENT_CONSTANTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 8;
+ break;
+ case GL_NUM_PASSES_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 2;
+ break;
+ case GL_NUM_INSTRUCTIONS_PER_PASS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 8;
+ break;
+ case GL_NUM_INSTRUCTIONS_TOTAL_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 16;
+ break;
+ case GL_COLOR_ALPHA_PAIRING_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(GL_TRUE);
+ break;
+ case GL_NUM_LOOPBACK_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 3;
+ break;
+ case GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 3;
+ break;
+ case GL_STENCIL_BACK_FUNC:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.Function[1]);
+ break;
+ case GL_STENCIL_BACK_VALUE_MASK:
+ params[0] = ctx->Stencil.ValueMask[1];
+ break;
+ case GL_STENCIL_BACK_WRITEMASK:
+ params[0] = ctx->Stencil.WriteMask[1];
+ break;
+ case GL_STENCIL_BACK_REF:
+ params[0] = ctx->Stencil.Ref[1];
+ break;
+ case GL_STENCIL_BACK_FAIL:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.FailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ZFailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ZPassFunc[1]);
+ break;
+ case GL_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->DrawBuffer->Name;
+ break;
+ case GL_RENDERBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0;
+ break;
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->Const.MaxColorAttachments;
+ break;
+ case GL_MAX_RENDERBUFFER_SIZE_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->Const.MaxRenderbufferSize;
+ break;
+ case GL_READ_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_blit, "GetInteger64v");
+ params[0] = ctx->ReadBuffer->Name;
+ break;
+ case GL_PROVOKING_VERTEX_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.ProvokingVertex);
+ break;
+ case GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Const.QuadsFollowProvokingVertexConvention);
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetInteger64v");
+ params[0] = ctx->Const.FragmentProgram.MaxUniformComponents;
+ break;
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Hint.FragmentShaderDerivative);
+ break;
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetInteger64v");
+ params[0] = ctx->Const.VertexProgram.MaxUniformComponents;
+ break;
+ case GL_MAX_VARYING_FLOATS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetInteger64v");
+ params[0] = ctx->Const.MaxVarying * 4;
+ break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetInteger64v");
+ params[0] = ctx->Const.MaxVertexTextureImageUnits;
+ break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetInteger64v");
+ params[0] = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+ break;
+ case GL_CURRENT_PROGRAM:
+ CHECK_EXT1(ARB_shader_objects, "GetInteger64v");
+ params[0] = ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0;
+ break;
+ case GL_MAX_SAMPLES:
+ CHECK_EXT1(ARB_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->Const.MaxSamples;
+ break;
+ case GL_VERTEX_ARRAY_BINDING_APPLE:
+ CHECK_EXT1(APPLE_vertex_array_object, "GetInteger64v");
+ params[0] = ctx->Array.ArrayObj->Name;
+ break;
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXT1(ARB_seamless_cube_map, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Texture.CubeMapSeamless);
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ CHECK_EXT1(ARB_sync, "GetInteger64v");
+ params[0] = ctx->Const.MaxServerWaitTimeout;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetInteger64v(pname=0x%x)", pname);
+ }
+}
+#endif /* FEATURE_ARB_sync */
+
void GLAPIENTRY
_mesa_GetDoublev( GLenum pname, GLdouble *params )
diff --git a/src/mesa/main/get.h b/src/mesa/main/get.h
index 9b47b230a9..77a9a7d04b 100644
--- a/src/mesa/main/get.h
+++ b/src/mesa/main/get.h
@@ -48,6 +48,9 @@ extern void GLAPIENTRY
_mesa_GetIntegerv( GLenum pname, GLint *params );
extern void GLAPIENTRY
+_mesa_GetInteger64v( GLenum pname, GLint64 *params );
+
+extern void GLAPIENTRY
_mesa_GetPointerv( GLenum pname, GLvoid **params );
extern const GLubyte * GLAPIENTRY
diff --git a/src/mesa/main/get_gen.py b/src/mesa/main/get_gen.py
index a191b045d3..364d8c55c4 100644
--- a/src/mesa/main/get_gen.py
+++ b/src/mesa/main/get_gen.py
@@ -35,6 +35,7 @@ GLfloat = 3
GLdouble = 4
GLboolean = 5
GLfloatN = 6 # A normalized value, such as a color or depth range
+GLint64 = 7
TypeStrings = {
@@ -42,7 +43,8 @@ TypeStrings = {
GLenum : "GLenum",
GLfloat : "GLfloat",
GLdouble : "GLdouble",
- GLboolean : "GLboolean"
+ GLboolean : "GLboolean",
+ GLint64 : "GLint64"
}
@@ -176,7 +178,8 @@ StateVars = [
"ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]",
"ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]",
"ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3]"],
- "const GLuint texUnit = ctx->Texture.CurrentUnit;", None ),
+ """const GLuint texUnit = ctx->Texture.CurrentUnit;
+ FLUSH_CURRENT(ctx, 0);""", None ),
( "GL_DEPTH_BIAS", GLfloat, ["ctx->Pixel.DepthBias"], "", None ),
( "GL_DEPTH_BITS", GLint, ["ctx->DrawBuffer->Visual.depthBits"],
"", None ),
@@ -254,7 +257,7 @@ StateVars = [
["ctx->Const.MinLineWidth",
"ctx->Const.MaxLineWidth"], "", None ),
( "GL_LIST_BASE", GLint, ["ctx->List.ListBase"], "", None ),
- ( "GL_LIST_INDEX", GLint, ["ctx->ListState.CurrentListNum"], "", None ),
+ ( "GL_LIST_INDEX", GLint, ["(ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0)"], "", None ),
( "GL_LIST_MODE", GLenum, ["mode"],
"""GLenum mode;
if (!ctx->CompileFlag)
@@ -432,15 +435,15 @@ StateVars = [
( "GL_TEXTURE_1D_ARRAY_EXT", GLboolean, ["_mesa_IsEnabled(GL_TEXTURE_1D_ARRAY_EXT)"], "", ["MESA_texture_array"] ),
( "GL_TEXTURE_2D_ARRAY_EXT", GLboolean, ["_mesa_IsEnabled(GL_TEXTURE_2D_ARRAY_EXT)"], "", ["MESA_texture_array"] ),
( "GL_TEXTURE_BINDING_1D", GLint,
- ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1D->Name"], "", None ),
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_INDEX]->Name"], "", None ),
( "GL_TEXTURE_BINDING_2D", GLint,
- ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2D->Name"], "", None ),
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name"], "", None ),
( "GL_TEXTURE_BINDING_3D", GLint,
- ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current3D->Name"], "", None ),
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name"], "", None ),
( "GL_TEXTURE_BINDING_1D_ARRAY_EXT", GLint,
- ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1DArray->Name"], "", ["MESA_texture_array"] ),
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name"], "", ["MESA_texture_array"] ),
( "GL_TEXTURE_BINDING_2D_ARRAY_EXT", GLint,
- ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2DArray->Name"], "", ["MESA_texture_array"] ),
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name"], "", ["MESA_texture_array"] ),
( "GL_TEXTURE_GEN_S", GLboolean,
["((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0)"], "", None ),
( "GL_TEXTURE_GEN_T", GLboolean,
@@ -515,7 +518,7 @@ StateVars = [
( "GL_TEXTURE_CUBE_MAP_ARB", GLboolean,
["_mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB)"], "", ["ARB_texture_cube_map"] ),
( "GL_TEXTURE_BINDING_CUBE_MAP_ARB", GLint,
- ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap->Name"],
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name"],
"", ["ARB_texture_cube_map"] ),
( "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB", GLint,
["(1 << (ctx->Const.MaxCubeTextureLevels - 1))"],
@@ -523,10 +526,10 @@ StateVars = [
# GL_ARB_texture_compression */
( "GL_TEXTURE_COMPRESSION_HINT_ARB", GLint,
- ["ctx->Hint.TextureCompression"], "", ["ARB_texture_compression"] ),
+ ["ctx->Hint.TextureCompression"], "", None ),
( "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB", GLint,
["_mesa_get_compressed_formats(ctx, NULL, GL_FALSE)"],
- "", ["ARB_texture_compression"] ),
+ "", None ),
( "GL_COMPRESSED_TEXTURE_FORMATS_ARB", GLenum,
[],
"""GLint formats[100];
@@ -534,7 +537,7 @@ StateVars = [
ASSERT(n <= 100);
for (i = 0; i < n; i++)
params[i] = CONVERSION(formats[i]);""",
- ["ARB_texture_compression"] ),
+ None ),
# GL_EXT_compiled_vertex_array
( "GL_ARRAY_ELEMENT_LOCK_FIRST_EXT", GLint, ["ctx->Array.LockFirst"],
@@ -681,21 +684,21 @@ StateVars = [
# GL_ARB_multisample
( "GL_MULTISAMPLE_ARB", GLboolean,
- ["ctx->Multisample.Enabled"], "", ["ARB_multisample"] ),
+ ["ctx->Multisample.Enabled"], "", None ),
( "GL_SAMPLE_ALPHA_TO_COVERAGE_ARB", GLboolean,
- ["ctx->Multisample.SampleAlphaToCoverage"], "", ["ARB_multisample"] ),
+ ["ctx->Multisample.SampleAlphaToCoverage"], "", None ),
( "GL_SAMPLE_ALPHA_TO_ONE_ARB", GLboolean,
- ["ctx->Multisample.SampleAlphaToOne"], "", ["ARB_multisample"] ),
+ ["ctx->Multisample.SampleAlphaToOne"], "", None ),
( "GL_SAMPLE_COVERAGE_ARB", GLboolean,
- ["ctx->Multisample.SampleCoverage"], "", ["ARB_multisample"] ),
+ ["ctx->Multisample.SampleCoverage"], "", None ),
( "GL_SAMPLE_COVERAGE_VALUE_ARB", GLfloat,
- ["ctx->Multisample.SampleCoverageValue"], "", ["ARB_multisample"] ),
+ ["ctx->Multisample.SampleCoverageValue"], "", None ),
( "GL_SAMPLE_COVERAGE_INVERT_ARB", GLboolean,
- ["ctx->Multisample.SampleCoverageInvert"], "", ["ARB_multisample"] ),
+ ["ctx->Multisample.SampleCoverageInvert"], "", None ),
( "GL_SAMPLE_BUFFERS_ARB", GLint,
- ["ctx->DrawBuffer->Visual.sampleBuffers"], "", ["ARB_multisample"] ),
+ ["ctx->DrawBuffer->Visual.sampleBuffers"], "", None ),
( "GL_SAMPLES_ARB", GLint,
- ["ctx->DrawBuffer->Visual.samples"], "", ["ARB_multisample"] ),
+ ["ctx->DrawBuffer->Visual.samples"], "", None ),
# GL_IBM_rasterpos_clip
( "GL_RASTER_POSITION_UNCLIPPED_IBM", GLboolean,
@@ -795,7 +798,7 @@ StateVars = [
( "GL_TEXTURE_RECTANGLE_NV", GLboolean,
["_mesa_IsEnabled(GL_TEXTURE_RECTANGLE_NV)"], "", ["NV_texture_rectangle"] ),
( "GL_TEXTURE_BINDING_RECTANGLE_NV", GLint,
- ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentRect->Name"],
+ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_RECT_INDEX]->Name"],
"", ["NV_texture_rectangle"] ),
( "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV", GLint,
["ctx->Const.MaxTextureRectSize"], "", ["NV_texture_rectangle"] ),
@@ -815,30 +818,30 @@ StateVars = [
# GL_ARB_vertex_buffer_object
( "GL_ARRAY_BUFFER_BINDING_ARB", GLint,
- ["ctx->Array.ArrayBufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ ["ctx->Array.ArrayBufferObj->Name"], "", None ),
( "GL_VERTEX_ARRAY_BUFFER_BINDING_ARB", GLint,
- ["ctx->Array.ArrayObj->Vertex.BufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ ["ctx->Array.ArrayObj->Vertex.BufferObj->Name"], "", None ),
( "GL_NORMAL_ARRAY_BUFFER_BINDING_ARB", GLint,
- ["ctx->Array.ArrayObj->Normal.BufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ ["ctx->Array.ArrayObj->Normal.BufferObj->Name"], "", None ),
( "GL_COLOR_ARRAY_BUFFER_BINDING_ARB", GLint,
- ["ctx->Array.ArrayObj->Color.BufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ ["ctx->Array.ArrayObj->Color.BufferObj->Name"], "", None ),
( "GL_INDEX_ARRAY_BUFFER_BINDING_ARB", GLint,
- ["ctx->Array.ArrayObj->Index.BufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ ["ctx->Array.ArrayObj->Index.BufferObj->Name"], "", None ),
( "GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB", GLint,
["ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name"],
- "", ["ARB_vertex_buffer_object"] ),
+ "", None ),
( "GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB", GLint,
- ["ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name"], "", ["ARB_vertex_buffer_object"] ),
+ ["ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name"], "", None ),
( "GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB", GLint,
["ctx->Array.ArrayObj->SecondaryColor.BufferObj->Name"],
- "", ["ARB_vertex_buffer_object"] ),
+ "", None ),
( "GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB", GLint,
["ctx->Array.ArrayObj->FogCoord.BufferObj->Name"],
- "", ["ARB_vertex_buffer_object"] ),
+ "", None ),
# GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB - not supported
( "GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB", GLint,
["ctx->Array.ElementArrayBufferObj->Name"],
- "", ["ARB_vertex_buffer_object"] ),
+ "", None ),
# GL_EXT_pixel_buffer_object
( "GL_PIXEL_PACK_BUFFER_BINDING_EXT", GLint,
@@ -902,21 +905,15 @@ StateVars = [
["ctx->Depth.BoundsMin", "ctx->Depth.BoundsMax"],
"", ["EXT_depth_bounds_test"] ),
- # GL_MESA_program_debug
- ( "GL_FRAGMENT_PROGRAM_CALLBACK_MESA", GLboolean,
- ["ctx->FragmentProgram.CallbackEnabled"], "", ["MESA_program_debug"] ),
- ( "GL_VERTEX_PROGRAM_CALLBACK_MESA", GLboolean,
- ["ctx->VertexProgram.CallbackEnabled"], "", ["MESA_program_debug"] ),
- ( "GL_FRAGMENT_PROGRAM_POSITION_MESA", GLint,
- ["ctx->FragmentProgram.CurrentPosition"], "", ["MESA_program_debug"] ),
- ( "GL_VERTEX_PROGRAM_POSITION_MESA", GLint,
- ["ctx->VertexProgram.CurrentPosition"], "", ["MESA_program_debug"] ),
+ # GL_ARB_depth_clamp
+ ( "GL_DEPTH_CLAMP", GLboolean, ["ctx->Transform.DepthClamp"], "",
+ ["ARB_depth_clamp"] ),
# GL_ARB_draw_buffers
( "GL_MAX_DRAW_BUFFERS_ARB", GLint,
- ["ctx->Const.MaxDrawBuffers"], "", ["ARB_draw_buffers"] ),
+ ["ctx->Const.MaxDrawBuffers"], "", None ),
( "GL_DRAW_BUFFER0_ARB", GLenum,
- ["ctx->DrawBuffer->ColorDrawBuffer[0]"], "", ["ARB_draw_buffers"] ),
+ ["ctx->DrawBuffer->ColorDrawBuffer[0]"], "", None ),
( "GL_DRAW_BUFFER1_ARB", GLenum,
["buffer"],
"""GLenum buffer;
@@ -924,7 +921,7 @@ StateVars = [
_mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
return;
}
- buffer = ctx->DrawBuffer->ColorDrawBuffer[1];""", ["ARB_draw_buffers"] ),
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[1];""", None ),
( "GL_DRAW_BUFFER2_ARB", GLenum,
["buffer"],
"""GLenum buffer;
@@ -932,7 +929,7 @@ StateVars = [
_mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
return;
}
- buffer = ctx->DrawBuffer->ColorDrawBuffer[2];""", ["ARB_draw_buffers"] ),
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[2];""", None ),
( "GL_DRAW_BUFFER3_ARB", GLenum,
["buffer"],
"""GLenum buffer;
@@ -940,7 +937,7 @@ StateVars = [
_mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
return;
}
- buffer = ctx->DrawBuffer->ColorDrawBuffer[3];""", ["ARB_draw_buffers"] ),
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[3];""", None ),
# XXX Add more GL_DRAW_BUFFERn_ARB entries as needed in the future
# GL_OES_read_format
@@ -986,6 +983,13 @@ StateVars = [
( "GL_READ_FRAMEBUFFER_BINDING_EXT", GLint, ["ctx->ReadBuffer->Name"], "",
["EXT_framebuffer_blit"] ),
+ # GL_EXT_provoking_vertex
+ ( "GL_PROVOKING_VERTEX_EXT", GLboolean,
+ ["ctx->Light.ProvokingVertex"], "", ["EXT_provoking_vertex"] ),
+ ( "GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT", GLboolean,
+ ["ctx->Const.QuadsFollowProvokingVertexConvention"], "",
+ ["EXT_provoking_vertex"] ),
+
# GL_ARB_fragment_shader
( "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB", GLint,
["ctx->Const.FragmentProgram.MaxUniformComponents"], "",
@@ -1009,7 +1013,23 @@ StateVars = [
# close enough for now.
( "GL_CURRENT_PROGRAM", GLint,
["ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0"],
- "", ["ARB_shader_objects"] )
+ "", ["ARB_shader_objects"] ),
+
+ # GL_ARB_framebuffer_object
+ ( "GL_MAX_SAMPLES", GLint, ["ctx->Const.MaxSamples"], "",
+ ["ARB_framebuffer_object"] ),
+
+ # GL_APPLE_vertex_array_object
+ ( "GL_VERTEX_ARRAY_BINDING_APPLE", GLint, ["ctx->Array.ArrayObj->Name"], "",
+ ["APPLE_vertex_array_object"] ),
+
+ # GL_ARB_seamless_cube_map
+ ( "GL_TEXTURE_CUBE_MAP_SEAMLESS", GLboolean, ["ctx->Texture.CubeMapSeamless"], "",
+ ["ARB_seamless_cube_map"] ),
+
+ # GL_ARB_sync
+ ( "GL_MAX_SERVER_WAIT_TIMEOUT", GLint64, ["ctx->Const.MaxServerWaitTimeout"], "",
+ ["ARB_sync"] ),
]
@@ -1019,10 +1039,16 @@ def ConversionFunc(fromType, toType):
return ""
elif fromType == GLfloat and toType == GLint:
return "IROUND"
+ elif fromType == GLfloat and toType == GLint64:
+ return "IROUND64"
elif fromType == GLfloatN and toType == GLfloat:
return ""
elif fromType == GLint and toType == GLfloat: # but not GLfloatN!
return "(GLfloat)"
+ elif fromType == GLint and toType == GLint64:
+ return ""
+ elif fromType == GLint64 and toType == GLfloat: # but not GLfloatN!
+ return "(GLfloat)"
else:
if fromType == GLfloatN:
fromType = GLfloat
@@ -1037,6 +1063,7 @@ def EmitGetFunction(stateVars, returnType):
"""Emit the code to implement glGetBooleanv, glGetIntegerv or glGetFloatv."""
assert (returnType == GLboolean or
returnType == GLint or
+ returnType == GLint64 or
returnType == GLfloat)
strType = TypeStrings[returnType]
@@ -1047,9 +1074,14 @@ def EmitGetFunction(stateVars, returnType):
function = "GetBooleanv"
elif returnType == GLfloat:
function = "GetFloatv"
+ elif returnType == GLint64:
+ function = "GetInteger64v"
else:
abort()
+ if returnType == GLint64:
+ print "#if FEATURE_ARB_sync"
+
print "void GLAPIENTRY"
print "_mesa_%s( GLenum pname, %s *params )" % (function, strType)
print "{"
@@ -1103,6 +1135,8 @@ def EmitGetFunction(stateVars, returnType):
print ' _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(pname=0x%%x)", pname);' % function
print " }"
print "}"
+ if returnType == GLint64:
+ print "#endif /* FEATURE_ARB_sync */"
print ""
return
@@ -1131,9 +1165,15 @@ def EmitHeader():
#define INT_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
+#define INT64_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
+#define INT64_TO_INT(I) ( (GLint)((I > INT_MAX) ? INT_MAX : ((I < INT_MIN) ? INT_MIN : (I))) )
+
#define BOOLEAN_TO_INT(B) ( (GLint) (B) )
+#define BOOLEAN_TO_INT64(B) ( (GLint64) (B) )
#define BOOLEAN_TO_FLOAT(B) ( (B) ? 1.0F : 0.0F )
+#define ENUM_TO_INT64(E) ( (GLint64) (E) )
+
/*
* Check if named extension is enabled, if not generate error and return.
@@ -1211,5 +1251,6 @@ EmitHeader()
EmitGetFunction(StateVars, GLboolean)
EmitGetFunction(StateVars, GLfloat)
EmitGetFunction(StateVars, GLint)
+EmitGetFunction(StateVars, GLint64)
EmitGetDoublev()
diff --git a/src/mesa/main/getstring.c b/src/mesa/main/getstring.c
index 94bf5de1e8..4b1f4b0ea1 100644
--- a/src/mesa/main/getstring.c
+++ b/src/mesa/main/getstring.c
@@ -82,9 +82,18 @@ compute_version(const GLcontext *ctx)
ctx->Extensions.ARB_vertex_shader &&
ctx->Extensions.ARB_fragment_shader &&
ctx->Extensions.ARB_texture_non_power_of_two &&
- ctx->Extensions.EXT_blend_equation_separate);
+ ctx->Extensions.EXT_blend_equation_separate &&
+
+ /* Technically, 2.0 requires the functionality
+ * of the EXT version. Enable 2.0 if either
+ * extension is available, and assume that a
+ * driver that only exposes the ATI extension
+ * will fallback to software when necessary.
+ */
+ (ctx->Extensions.EXT_stencil_two_side
+ || ctx->Extensions.ATI_separate_stencil));
const GLboolean ver_2_1 = (ver_2_0 &&
- /*ctx->Extensions.ARB_shading_language_120 &&*/
+ ctx->Extensions.ARB_shading_language_120 &&
ctx->Extensions.EXT_pixel_buffer_object &&
ctx->Extensions.EXT_texture_sRGB);
if (ver_2_1)
@@ -233,34 +242,9 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params )
case GL_SELECTION_BUFFER_POINTER:
*params = ctx->Select.Buffer;
break;
-#if FEATURE_MESA_program_debug
- case GL_FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA:
- if (!ctx->Extensions.MESA_program_debug) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv");
- return;
- }
- *params = *(GLvoid **) &ctx->FragmentProgram.Callback;
- break;
- case GL_FRAGMENT_PROGRAM_CALLBACK_DATA_MESA:
- if (!ctx->Extensions.MESA_program_debug) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv");
- return;
- }
- *params = ctx->FragmentProgram.CallbackData;
- break;
- case GL_VERTEX_PROGRAM_CALLBACK_FUNC_MESA:
- if (!ctx->Extensions.MESA_program_debug) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv");
- return;
- }
- *params = *(GLvoid **) &ctx->VertexProgram.Callback;
- break;
- case GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA:
- if (!ctx->Extensions.MESA_program_debug) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv");
- return;
- }
- *params = ctx->VertexProgram.CallbackData;
+#if FEATURE_point_size_array
+ case GL_POINT_SIZE_ARRAY_POINTER_OES:
+ *params = (GLvoid *) ctx->Array.ArrayObj->PointSize.Ptr;
break;
#endif
default:
@@ -287,5 +271,6 @@ _mesa_GetError( void )
_mesa_debug(ctx, "glGetError <-- %s\n", _mesa_lookup_enum_by_nr(e));
ctx->ErrorValue = (GLenum) GL_NO_ERROR;
+ ctx->ErrorDebugCount = 0;
return e;
}
diff --git a/src/mesa/main/glheader.h b/src/mesa/main/glheader.h
index 626806d35f..81d4ccf919 100644
--- a/src/mesa/main/glheader.h
+++ b/src/mesa/main/glheader.h
@@ -1,28 +1,8 @@
-/**
- * \file glheader.h
- * Top-most include file.
- *
- * This is the top-most include file of the Mesa sources.
- * It includes gl.h and all system headers which are needed.
- * Other Mesa source files should \e not directly include any system
- * headers. This allows system-dependent hacks/workarounds to be
- * collected in one place.
- *
- * \note Actually, a lot of system-dependent stuff is now in imports.[ch].
- *
- * If you touch this file, everything gets recompiled!
- *
- * This file should be included before any other header in the .c files.
- *
- * Put compiler/OS/assembly pragmas and macros here to avoid
- * cluttering other source files.
- */
-
/*
* Mesa 3-D graphics library
- * Version: 6.5
+ * Version: 7.5
*
- * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -43,88 +23,22 @@
*/
-#ifndef GLHEADER_H
-#define GLHEADER_H
-
-#include <assert.h>
-#include <ctype.h>
-#if defined(__alpha__) && defined(CCPML)
-#include <cpml.h> /* use Compaq's Fast Math Library on Alpha */
-#else
-#include <math.h>
-#endif
-#include <limits.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#if defined(__linux__) && defined(__i386__)
-#include <fpu_control.h>
-#endif
-#include <float.h>
-#include <stdarg.h>
-
-
-/* Get typedefs for uintptr_t and friends */
-#if defined(__MINGW32__) || defined(__NetBSD__)
-# include <stdint.h>
-#elif defined(_WIN32)
-# include <BaseTsd.h>
-# if _MSC_VER == 1200
- typedef UINT_PTR uintptr_t;
-# endif
-#elif defined(__INTERIX)
-/* Interix 3.x has a gcc that shadows this. */
-# ifndef _UINTPTR_T_DEFINED
- typedef unsigned long uintptr_t;
-# define _UINTPTR_T_DEFINED
-# endif
-#else
-# include <inttypes.h>
-#endif
-
+/**
+ * \file glheader.h
+ * Wrapper for GL/gl.h and GL/glext.h
+ */
-/* Sun compilers define __i386 instead of the gcc-style __i386__ */
-#ifdef __SUNPRO_C
-# if !defined(__i386__) && defined(__i386)
-# define __i386__
-# elif !defined(__amd64__) && defined(__amd64)
-# define __amd64__
-# elif !defined(__sparc__) && defined(__sparc)
-# define __sparc__
-# endif
-# if !defined(__volatile)
-# define __volatile volatile
-# endif
-#endif
-#if defined(_WIN32) && !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(BUILD_FOR_SNAP)
-# define __WIN32__
-# define finite _finite
-#endif
+#ifndef GLHEADER_H
+#define GLHEADER_H
-#if defined(__WATCOMC__)
-# define finite _finite
-# pragma disable_message(201) /* Disable unreachable code warnings */
-#endif
#ifdef WGLAPI
-# undef WGLAPI
+#undef WGLAPI
#endif
+
#if !defined(OPENSTEP) && (defined(__WIN32__) && !defined(__CYGWIN__)) && !defined(BUILD_FOR_SNAP)
-# if !defined(__GNUC__) /* mingw environment */
-# pragma warning( disable : 4068 ) /* unknown pragma */
-# pragma warning( disable : 4710 ) /* function 'foo' not inlined */
-# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */
-# pragma warning( disable : 4127 ) /* conditional expression is constant */
-# if defined(MESA_MINWARN)
-# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */
-# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */
-# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */
-# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */
-# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */
-# endif
-# endif
# if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */
# define WGLAPI __declspec(dllexport)
# elif (defined(_MSC_VER) || defined(__MINGW32__)) && defined(_DLL) /* tag specifying we're building for DLL runtime support */
@@ -135,31 +49,10 @@
#endif /* WIN32 / CYGWIN bracket */
-/*
- * Either define MESA_BIG_ENDIAN or MESA_LITTLE_ENDIAN.
- * Do not use them unless absolutely necessary!
- * Try to use a runtime test instead.
- * For now, only used by some DRI hardware drivers for color/texel packing.
- */
-#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
-#if defined(__linux__)
-#include <byteswap.h>
-#define CPU_TO_LE32( x ) bswap_32( x )
-#else /*__linux__*/
-#include <sys/endian.h>
-#define CPU_TO_LE32( x ) bswap32( x )
-#endif /*__linux__*/
-#define MESA_BIG_ENDIAN 1
-#else
-#define CPU_TO_LE32( x ) ( x )
-#define MESA_LITTLE_ENDIAN 1
-#endif
-#define LE32_TO_CPU( x ) CPU_TO_LE32( x )
-
-
#define GL_GLEXT_PROTOTYPES
#include "GL/gl.h"
#include "GL/glext.h"
+#include "GL/internal/glcore.h"
#ifndef GL_FIXED
@@ -181,129 +74,15 @@
#endif
-#if !defined(CAPI) && defined(WIN32) && !defined(BUILD_FOR_SNAP)
-#define CAPI _cdecl
-#endif
-
-
-/* This is a macro on IRIX */
-#ifdef _P
-#undef _P
-#endif
-
-
-/* Turn off macro checking systems used by other libraries */
-#ifdef CHECK
-#undef CHECK
+#ifndef GL_PROGRAM_BINARY_LENGTH_OES
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
#endif
-/* Create a macro so that asm functions can be linked into compilers other
- * than GNU C
- */
-#ifndef _ASMAPI
-#if defined(WIN32) && !defined(BUILD_FOR_SNAP)/* was: !defined( __GNUC__ ) && !defined( VMS ) && !defined( __INTEL_COMPILER )*/
-#define _ASMAPI __cdecl
-#else
-#define _ASMAPI
-#endif
-#ifdef PTR_DECL_IN_FRONT
-#define _ASMAPIP * _ASMAPI
-#else
-#define _ASMAPIP _ASMAPI *
-#endif
-#endif
-
-#ifdef USE_X86_ASM
-#define _NORMAPI _ASMAPI
-#define _NORMAPIP _ASMAPIP
-#else
-#define _NORMAPI
-#define _NORMAPIP *
-#endif
-
-
-/* Function inlining */
-#if defined(__GNUC__)
-# define INLINE __inline__
-#elif defined(__MSC__)
-# define INLINE __inline
-#elif defined(_MSC_VER)
-# define INLINE __inline
-#elif defined(__ICL)
-# define INLINE __inline
-#elif defined(__INTEL_COMPILER)
-# define INLINE inline
-#elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100)
-# define INLINE __inline
-#elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
-# define INLINE inline
-# define __inline inline
-# define __inline__ inline
-#elif (__STDC_VERSION__ >= 199901L) /* C99 */
-# define INLINE inline
-#else
-# define INLINE
-#endif
-
-
-/* If we build the library with gcc's -fvisibility=hidden flag, we'll
- * use the PUBLIC macro to mark functions that are to be exported.
- *
- * We also need to define a USED attribute, so the optimizer doesn't
- * inline a static function that we later use in an alias. - ajax
- */
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
-# define PUBLIC __attribute__((visibility("default")))
-# define USED __attribute__((used))
-#else
-# define PUBLIC
-# define USED
-#endif
-
-
-/* Some compilers don't like some of Mesa's const usage */
-#ifdef NO_CONST
-# define CONST
-#else
-# define CONST const
-#endif
-
-
-#if !defined(_WIN32_WCE)
-#if defined(BUILD_FOR_SNAP) && defined(CHECKED)
-# define ASSERT(X) _CHECK(X)
-#elif defined(DEBUG)
-# define ASSERT(X) assert(X)
-#else
-# define ASSERT(X)
-#endif
-#endif
-
-
-#if (!defined(__GNUC__) || __GNUC__ < 3) && (!defined(__IBMC__) || __IBMC__ < 900)
-# define __builtin_expect(x, y) x
-#endif
-
-/* The __FUNCTION__ gcc variable is generally only used for debugging.
- * If we're not using gcc, define __FUNCTION__ as a cpp symbol here.
- * Don't define it if using a newer Windows compiler.
+/**
+ * Special, internal token
*/
-#ifndef __FUNCTION__
-# if defined(__VMS)
-# define __FUNCTION__ "VMS$NL:"
-# elif ((!defined __GNUC__) || (__GNUC__ < 2)) && (!defined __xlC__) && \
- (!defined(_MSC_VER) || _MSC_VER < 1300)
-# if (__STDC_VERSION__ >= 199901L) /* C99 */ || \
- (defined(__SUNPRO_C) && defined(__C99FEATURES__))
-# define __FUNCTION__ __func__
-# else
-# define __FUNCTION__ "<unknown>"
-# endif
-# endif
-#endif
-
+#define GL_SHADER_PROGRAM_MESA 0x9999
-#include "config.h"
#endif /* GLHEADER_H */
diff --git a/src/mesa/main/hash.c b/src/mesa/main/hash.c
index ffb2c4d946..08c64568c8 100644
--- a/src/mesa/main/hash.c
+++ b/src/mesa/main/hash.c
@@ -63,6 +63,7 @@ struct _mesa_HashTable {
struct HashEntry *Table[TABLE_SIZE]; /**< the lookup table */
GLuint MaxKey; /**< highest key inserted so far */
_glthread_Mutex Mutex; /**< mutual exclusion lock */
+ _glthread_Mutex WalkMutex; /**< for _mesa_HashWalk() */
GLboolean InDeleteAll; /**< Debug check */
};
@@ -79,6 +80,7 @@ _mesa_NewHashTable(void)
struct _mesa_HashTable *table = CALLOC_STRUCT(_mesa_HashTable);
if (table) {
_glthread_INIT_MUTEX(table->Mutex);
+ _glthread_INIT_MUTEX(table->WalkMutex);
}
return table;
}
@@ -111,6 +113,7 @@ _mesa_DeleteHashTable(struct _mesa_HashTable *table)
}
}
_glthread_DESTROY_MUTEX(table->Mutex);
+ _glthread_DESTROY_MUTEX(table->WalkMutex);
_mesa_free(table);
}
@@ -285,6 +288,11 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table,
/**
* Walk over all entries in a hash table, calling callback function for each.
+ * Note: we use a separate mutex in this function to avoid a recursive
+ * locking deadlock (in case the callback calls _mesa_HashRemove()) and to
+ * prevent multiple threads/contexts from getting tangled up.
+ * A lock-less version of this function could be used when the table will
+ * not be modified.
* \param table the hash table to walk
* \param callback the callback function
* \param userData arbitrary pointer to pass along to the callback
@@ -300,14 +308,16 @@ _mesa_HashWalk(const struct _mesa_HashTable *table,
GLuint pos;
ASSERT(table);
ASSERT(callback);
- _glthread_UNLOCK_MUTEX(table2->Mutex);
+ _glthread_LOCK_MUTEX(table2->WalkMutex);
for (pos = 0; pos < TABLE_SIZE; pos++) {
- struct HashEntry *entry;
- for (entry = table->Table[pos]; entry; entry = entry->Next) {
+ struct HashEntry *entry, *next;
+ for (entry = table->Table[pos]; entry; entry = next) {
+ /* save 'next' pointer now in case the callback deletes the entry */
+ next = entry->Next;
callback(entry->Key, entry->Data, userData);
}
}
- _glthread_UNLOCK_MUTEX(table2->Mutex);
+ _glthread_UNLOCK_MUTEX(table2->WalkMutex);
}
diff --git a/src/mesa/main/hint.c b/src/mesa/main/hint.c
index dcfa9c7363..e2d4129a38 100644
--- a/src/mesa/main/hint.c
+++ b/src/mesa/main/hint.c
@@ -89,10 +89,6 @@ _mesa_Hint( GLenum target, GLenum mode )
/* GL_ARB_texture_compression */
case GL_TEXTURE_COMPRESSION_HINT_ARB:
- if (!ctx->Extensions.ARB_texture_compression) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
- return;
- }
if (ctx->Hint.TextureCompression == mode)
return;
FLUSH_VERTICES(ctx, _NEW_HINT);
diff --git a/src/mesa/main/histogram.c b/src/mesa/main/histogram.c
index 905c1ad830..3632adc03e 100644
--- a/src/mesa/main/histogram.c
+++ b/src/mesa/main/histogram.c
@@ -29,8 +29,11 @@
#include "context.h"
#include "image.h"
#include "histogram.h"
+#include "glapi/dispatch.h"
+#if FEATURE_histogram
+
/*
* XXX the packed pixel formats haven't been tested.
@@ -649,29 +652,11 @@ _mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvo
return;
}
- if (ctx->Pack.BufferObj->Name) {
- /* pack min/max values into a PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(1, &ctx->Pack, 2, 1, 1,
- format, type, values)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetMinMax(invalid PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,"glGetMinMax(PBO is mapped)");
- return;
- }
- values = ADD_POINTERS(buf, values);
- }
- else if (!values) {
- /* not an error */
+
+ values = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack, 2, 1, 1,
+ format, type, values, "glGetMinmax");
+ if (!values)
return;
- }
{
GLfloat minmax[2][4];
@@ -687,10 +672,7 @@ _mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvo
format, type, values, &ctx->Pack, 0x0);
}
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
if (reset) {
_mesa_ResetMinmax(GL_MINMAX);
@@ -733,38 +715,18 @@ _mesa_GetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, G
return;
}
- if (ctx->Pack.BufferObj->Name) {
- /* pack min/max values into a PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(1, &ctx->Pack, ctx->Histogram.Width, 1, 1,
- format, type, values)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetHistogram(invalid PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx,GL_INVALID_OPERATION,"glGetHistogram(PBO is mapped)");
- return;
- }
- values = ADD_POINTERS(buf, values);
- }
- else if (!values) {
- /* not an error */
+ values = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack,
+ ctx->Histogram.Width, 1, 1,
+ format, type, values,
+ "glGetHistogram");
+ if (!values)
return;
- }
pack_histogram(ctx, ctx->Histogram.Width,
(CONST GLuint (*)[4]) ctx->Histogram.Count,
format, type, values, &ctx->Pack);
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
if (reset) {
GLuint i;
@@ -975,6 +937,8 @@ _mesa_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean s
}
}
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+
/* reset histograms */
for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
ctx->Histogram.Count[i][0] = 0;
@@ -1002,8 +966,6 @@ _mesa_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean s
ctx->Histogram.AlphaSize = 8 * sizeof(GLuint);
ctx->Histogram.LuminanceSize = 8 * sizeof(GLuint);
}
-
- ctx->NewState |= _NEW_PIXEL;
}
@@ -1058,8 +1020,6 @@ _mesa_ResetHistogram(GLenum target)
ctx->Histogram.Count[i][2] = 0;
ctx->Histogram.Count[i][3] = 0;
}
-
- ctx->NewState |= _NEW_PIXEL;
}
@@ -1083,10 +1043,27 @@ _mesa_ResetMinmax(GLenum target)
ctx->MinMax.Min[GCOMP] = 1000; ctx->MinMax.Max[GCOMP] = -1000;
ctx->MinMax.Min[BCOMP] = 1000; ctx->MinMax.Max[BCOMP] = -1000;
ctx->MinMax.Min[ACOMP] = 1000; ctx->MinMax.Max[ACOMP] = -1000;
- ctx->NewState |= _NEW_PIXEL;
}
+void
+_mesa_init_histogram_dispatch(struct _glapi_table *disp)
+{
+ SET_GetHistogram(disp, _mesa_GetHistogram);
+ SET_GetHistogramParameterfv(disp, _mesa_GetHistogramParameterfv);
+ SET_GetHistogramParameteriv(disp, _mesa_GetHistogramParameteriv);
+ SET_GetMinmax(disp, _mesa_GetMinmax);
+ SET_GetMinmaxParameterfv(disp, _mesa_GetMinmaxParameterfv);
+ SET_GetMinmaxParameteriv(disp, _mesa_GetMinmaxParameteriv);
+ SET_Histogram(disp, _mesa_Histogram);
+ SET_Minmax(disp, _mesa_Minmax);
+ SET_ResetHistogram(disp, _mesa_ResetHistogram);
+ SET_ResetMinmax(disp, _mesa_ResetMinmax);
+}
+
+
+#endif /* FEATURE_histogram */
+
/**********************************************************************/
/***** Initialization *****/
diff --git a/src/mesa/main/histogram.h b/src/mesa/main/histogram.h
index 367e9b11ba..ce3246baf4 100644
--- a/src/mesa/main/histogram.h
+++ b/src/mesa/main/histogram.h
@@ -36,10 +36,9 @@
#ifndef HISTOGRAM_H
#define HISTOGRAM_H
-#include "glheader.h"
-#include "mtypes.h"
+#include "main/mtypes.h"
-#if _HAVE_FULL_GL
+#if FEATURE_histogram
extern void GLAPIENTRY
_mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values);
@@ -71,13 +70,18 @@ _mesa_ResetHistogram(GLenum target);
extern void GLAPIENTRY
_mesa_ResetMinmax(GLenum target);
-extern void _mesa_init_histogram( GLcontext * ctx );
+extern void
+_mesa_init_histogram_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_histogram */
-#else
+static INLINE void
+_mesa_init_histogram_dispatch(struct _glapi_table *disp)
+{
+}
-/** No-op */
-#define _mesa_init_histogram( c ) ((void) 0)
+#endif /* FEATURE_histogram */
-#endif
+extern void _mesa_init_histogram( GLcontext * ctx );
-#endif
+#endif /* HISTOGRAM_H */
diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c
index 4d86c54777..baecbab0a3 100644
--- a/src/mesa/main/image.c
+++ b/src/mesa/main/image.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.5
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -181,6 +182,8 @@ _mesa_sizeof_type( GLenum type )
return sizeof(GLint);
case GL_FLOAT:
return sizeof(GLfloat);
+ case GL_DOUBLE:
+ return sizeof(GLdouble);
case GL_HALF_FLOAT_ARB:
return sizeof(GLhalfARB);
default:
@@ -293,6 +296,9 @@ _mesa_components_in_format( GLenum format )
return 2;
case GL_DEPTH_STENCIL_EXT:
return 2;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return 2;
default:
return -1;
}
@@ -503,6 +509,20 @@ _mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type )
return GL_TRUE;
else
return GL_FALSE;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ switch (type) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
default:
; /* fall-through */
}
@@ -511,6 +531,226 @@ _mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type )
/**
+ * Test if the given image format is a color/RGBA format (i.e., not color
+ * index, depth, stencil, etc).
+ * \param format the image format value (may by an internal texture format)
+ * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
+ */
+GLboolean
+_mesa_is_color_format(GLenum format)
+{
+ switch (format) {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case 2:
+ 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:
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case 3:
+ case GL_RGB:
+ case GL_BGR:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ case 4:
+ case GL_ABGR_EXT:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ /* float texture formats */
+ case GL_ALPHA16F_ARB:
+ case GL_ALPHA32F_ARB:
+ case GL_LUMINANCE16F_ARB:
+ case GL_LUMINANCE32F_ARB:
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ case GL_INTENSITY16F_ARB:
+ case GL_INTENSITY32F_ARB:
+ case GL_RGB16F_ARB:
+ case GL_RGB32F_ARB:
+ case GL_RGBA16F_ARB:
+ case GL_RGBA32F_ARB:
+ /* compressed formats */
+ case GL_COMPRESSED_ALPHA:
+ case GL_COMPRESSED_LUMINANCE:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ case GL_COMPRESSED_INTENSITY:
+ case GL_COMPRESSED_RGB:
+ case GL_COMPRESSED_RGBA:
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+#if FEATURE_EXT_texture_sRGB
+ case GL_SRGB_EXT:
+ case GL_SRGB8_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ case GL_COMPRESSED_SRGB_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SLUMINANCE_EXT:
+ case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
+#endif /* FEATURE_EXT_texture_sRGB */
+ return GL_TRUE;
+ /* signed texture formats */
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ return GL_TRUE;
+ case GL_YCBCR_MESA: /* not considered to be RGB */
+ /* fall-through */
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a color index format.
+ */
+GLboolean
+_mesa_is_index_format(GLenum format)
+{
+ switch (format) {
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a depth component format.
+ */
+GLboolean
+_mesa_is_depth_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a stencil format.
+ */
+GLboolean
+_mesa_is_stencil_format(GLenum format)
+{
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_STENCIL:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a YCbCr format.
+ */
+GLboolean
+_mesa_is_ycbcr_format(GLenum format)
+{
+ switch (format) {
+ case GL_YCBCR_MESA:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a depth+stencil format.
+ */
+GLboolean
+_mesa_is_depthstencil_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH24_STENCIL8_EXT:
+ case GL_DEPTH_STENCIL_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+/**
+ * Test if the given image format is a dudv format.
+ */
+GLboolean
+_mesa_is_dudv_format(GLenum format)
+{
+ switch (format) {
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
* Return the address of a specific pixel in an image (1D, 2D or 3D).
*
* Pixel unpacking/packing parameters are observed according to \p packing.
@@ -738,12 +978,20 @@ _mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
GLint width, GLint height,
GLenum format, GLenum type )
{
+ GLint bytesPerRow, bytesPerImage, remainder;
+
ASSERT(packing);
- ASSERT(type != GL_BITMAP);
- {
+ if (type == GL_BITMAP) {
+ if (packing->RowLength == 0) {
+ bytesPerRow = (width + 7) / 8;
+ }
+ else {
+ bytesPerRow = (packing->RowLength + 7) / 8;
+ }
+ }
+ else {
const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
- GLint bytesPerRow, bytesPerImage, remainder;
if (bytesPerPixel <= 0)
return -1; /* error */
@@ -753,17 +1001,18 @@ _mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
else {
bytesPerRow = bytesPerPixel * packing->RowLength;
}
- remainder = bytesPerRow % packing->Alignment;
- if (remainder > 0)
- bytesPerRow += (packing->Alignment - remainder);
+ }
- if (packing->ImageHeight == 0)
- bytesPerImage = bytesPerRow * height;
- else
- bytesPerImage = bytesPerRow * packing->ImageHeight;
+ remainder = bytesPerRow % packing->Alignment;
+ if (remainder > 0)
+ bytesPerRow += (packing->Alignment - remainder);
- return bytesPerImage;
- }
+ if (packing->ImageHeight == 0)
+ bytesPerImage = bytesPerRow * height;
+ else
+ bytesPerImage = bytesPerRow * packing->ImageHeight;
+
+ return bytesPerImage;
}
@@ -1010,6 +1259,91 @@ _mesa_pack_bitmap( GLint width, GLint height, const GLubyte *source,
}
+/**
+ * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel.
+ * This is typically used to convert a bitmap into a GLubyte/pixel texture.
+ * "On" bits will set texels to \p onValue.
+ * "Off" bits will not modify texels.
+ * \param width src bitmap width in pixels
+ * \param height src bitmap height in pixels
+ * \param unpack bitmap unpacking state
+ * \param bitmap the src bitmap data
+ * \param destBuffer start of dest buffer
+ * \param destStride row stride in dest buffer
+ * \param onValue if bit is 1, set destBuffer pixel to this value
+ */
+void
+_mesa_expand_bitmap(GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap,
+ GLubyte *destBuffer, GLint destStride,
+ GLubyte onValue)
+{
+ const GLubyte *srcRow = (const GLubyte *)
+ _mesa_image_address2d(unpack, bitmap, width, height,
+ GL_COLOR_INDEX, GL_BITMAP, 0, 0);
+ const GLint srcStride = _mesa_image_row_stride(unpack, width,
+ GL_COLOR_INDEX, GL_BITMAP);
+ GLint row, col;
+
+#define SET_PIXEL(COL, ROW) \
+ destBuffer[(ROW) * destStride + (COL)] = onValue;
+
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = srcRow;
+
+ if (unpack->LsbFirst) {
+ /* Lsb first */
+ GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+
+ if (*src & mask) {
+ SET_PIXEL(col, row);
+ }
+
+ if (mask == 128U) {
+ src++;
+ mask = 1U;
+ }
+ else {
+ mask = mask << 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 1)
+ src++;
+ }
+ else {
+ /* Msb first */
+ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+
+ if (*src & mask) {
+ SET_PIXEL(col, row);
+ }
+
+ if (mask == 1U) {
+ src++;
+ mask = 128U;
+ }
+ else {
+ mask = mask >> 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 128)
+ src++;
+ }
+
+ srcRow += srcStride;
+ } /* row */
+
+#undef SET_PIXEL
+}
+
+
/**********************************************************************/
/***** Pixel processing functions ******/
/**********************************************************************/
@@ -1660,7 +1994,6 @@ _mesa_apply_stencil_transfer_ops(const GLcontext *ctx, GLuint n,
* Used to pack an array [][4] of RGBA float colors as specified
* by the dstFormat, dstType and dstPacking. Used by glReadPixels,
* glGetConvolutionFilter(), etc.
- * Incoming colors will be clamped to [0,1] if needed.
* Note: the rgba values will be modified by this function when any pixel
* transfer ops are enabled.
*/
@@ -1675,6 +2008,10 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
const GLint comps = _mesa_components_in_format(dstFormat);
GLuint i;
+ /* XXX
+ * This test should probably go away. Have the caller set/clear the
+ * IMAGE_CLAMP_BIT as needed.
+ */
if (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE) {
/* need to clamp to [0, 1] */
transferOps |= IMAGE_CLAMP_BIT;
@@ -1774,6 +2111,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
}
break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
+ }
+ break;
default:
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
}
@@ -1847,6 +2191,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
}
break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ }
+ break;
default:
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
}
@@ -1920,6 +2271,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
CLAMPED_FLOAT_TO_USHORT(dst[i*4+3], rgba[i][RCOMP]);
}
break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_USHORT(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_USHORT(rgba[i][GCOMP]);
+ }
+ break;
default:
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
}
@@ -1993,6 +2351,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
}
break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
+ }
+ break;
default:
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
}
@@ -2066,6 +2431,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
dst[i*4+3] = FLOAT_TO_UINT(rgba[i][RCOMP]);
}
break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_UINT(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_UINT(rgba[i][GCOMP]);
+ }
+ break;
default:
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
}
@@ -2139,6 +2511,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
dst[i*4+3] = FLOAT_TO_INT(rgba[i][RCOMP]);
}
break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_INT(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_INT(rgba[i][GCOMP]);
+ }
+ break;
default:
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
}
@@ -2212,6 +2591,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
dst[i*4+3] = rgba[i][RCOMP];
}
break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = rgba[i][RCOMP];
+ dst[i*2+1] = rgba[i][GCOMP];
+ }
+ break;
default:
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
}
@@ -2285,6 +2671,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
dst[i*4+3] = _mesa_float_to_half(rgba[i][RCOMP]);
}
break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = _mesa_float_to_half(rgba[i][RCOMP]);
+ dst[i*2+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ }
+ break;
default:
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
}
@@ -2294,9 +2687,9 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGB) {
GLubyte *dst = (GLubyte *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][RCOMP] * 7.0F)) << 5)
- | (((GLint) (rgba[i][GCOMP] * 7.0F)) << 2)
- | (((GLint) (rgba[i][BCOMP] * 3.0F)) );
+ dst[i] = (IROUND(rgba[i][RCOMP] * 7.0F) << 5)
+ | (IROUND(rgba[i][GCOMP] * 7.0F) << 2)
+ | (IROUND(rgba[i][BCOMP] * 3.0F) );
}
}
break;
@@ -2304,9 +2697,9 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGB) {
GLubyte *dst = (GLubyte *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][RCOMP] * 7.0F)) )
- | (((GLint) (rgba[i][GCOMP] * 7.0F)) << 3)
- | (((GLint) (rgba[i][BCOMP] * 3.0F)) << 6);
+ dst[i] = (IROUND(rgba[i][RCOMP] * 7.0F) )
+ | (IROUND(rgba[i][GCOMP] * 7.0F) << 3)
+ | (IROUND(rgba[i][BCOMP] * 3.0F) << 6);
}
}
break;
@@ -2314,9 +2707,9 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGB) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][RCOMP] * 31.0F)) << 11)
- | (((GLint) (rgba[i][GCOMP] * 63.0F)) << 5)
- | (((GLint) (rgba[i][BCOMP] * 31.0F)) );
+ dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) << 11)
+ | (IROUND(rgba[i][GCOMP] * 63.0F) << 5)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) );
}
}
break;
@@ -2324,9 +2717,9 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGB) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][RCOMP] * 31.0F)) )
- | (((GLint) (rgba[i][GCOMP] * 63.0F)) << 5)
- | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 11);
+ dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) )
+ | (IROUND(rgba[i][GCOMP] * 63.0F) << 5)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 11);
}
}
break;
@@ -2334,28 +2727,28 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGBA) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][RCOMP] * 15.0F)) << 12)
- | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 8)
- | (((GLint) (rgba[i][BCOMP] * 15.0F)) << 4)
- | (((GLint) (rgba[i][ACOMP] * 15.0F)) );
+ dst[i] = (IROUND(rgba[i][RCOMP] * 15.0F) << 12)
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][BCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][ACOMP] * 15.0F) );
}
}
else if (dstFormat == GL_BGRA) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][BCOMP] * 15.0F)) << 12)
- | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 8)
- | (((GLint) (rgba[i][RCOMP] * 15.0F)) << 4)
- | (((GLint) (rgba[i][ACOMP] * 15.0F)) );
+ dst[i] = (IROUND(rgba[i][BCOMP] * 15.0F) << 12)
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][RCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][ACOMP] * 15.0F) );
}
}
else if (dstFormat == GL_ABGR_EXT) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][ACOMP] * 15.0F)) << 12)
- | (((GLint) (rgba[i][BCOMP] * 15.0F)) << 8)
- | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 4)
- | (((GLint) (rgba[i][RCOMP] * 15.0F)) );
+ dst[i] = (IROUND(rgba[i][ACOMP] * 15.0F) << 12)
+ | (IROUND(rgba[i][BCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][RCOMP] * 15.0F) );
}
}
break;
@@ -2363,28 +2756,28 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGBA) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][RCOMP] * 15.0F)) )
- | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 4)
- | (((GLint) (rgba[i][BCOMP] * 15.0F)) << 8)
- | (((GLint) (rgba[i][ACOMP] * 15.0F)) << 12);
+ dst[i] = (IROUND(rgba[i][RCOMP] * 15.0F) )
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][BCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][ACOMP] * 15.0F) << 12);
}
}
else if (dstFormat == GL_BGRA) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][BCOMP] * 15.0F)) )
- | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 4)
- | (((GLint) (rgba[i][RCOMP] * 15.0F)) << 8)
- | (((GLint) (rgba[i][ACOMP] * 15.0F)) << 12);
+ dst[i] = (IROUND(rgba[i][BCOMP] * 15.0F) )
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][RCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][ACOMP] * 15.0F) << 12);
}
}
else if (dstFormat == GL_ABGR_EXT) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][ACOMP] * 15.0F)) )
- | (((GLint) (rgba[i][BCOMP] * 15.0F)) << 4)
- | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 8)
- | (((GLint) (rgba[i][RCOMP] * 15.0F)) << 12);
+ dst[i] = (IROUND(rgba[i][ACOMP] * 15.0F) )
+ | (IROUND(rgba[i][BCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][RCOMP] * 15.0F) << 12);
}
}
break;
@@ -2392,28 +2785,28 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGBA) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][RCOMP] * 31.0F)) << 11)
- | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 6)
- | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 1)
- | (((GLint) (rgba[i][ACOMP] * 1.0F)) );
+ dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) << 11)
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 6)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 1)
+ | (IROUND(rgba[i][ACOMP] * 1.0F) );
}
}
else if (dstFormat == GL_BGRA) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][BCOMP] * 31.0F)) << 11)
- | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 6)
- | (((GLint) (rgba[i][RCOMP] * 31.0F)) << 1)
- | (((GLint) (rgba[i][ACOMP] * 1.0F)) );
+ dst[i] = (IROUND(rgba[i][BCOMP] * 31.0F) << 11)
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 6)
+ | (IROUND(rgba[i][RCOMP] * 31.0F) << 1)
+ | (IROUND(rgba[i][ACOMP] * 1.0F) );
}
}
else if (dstFormat == GL_ABGR_EXT) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][ACOMP] * 31.0F)) << 11)
- | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 6)
- | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 1)
- | (((GLint) (rgba[i][RCOMP] * 1.0F)) );
+ dst[i] = (IROUND(rgba[i][ACOMP] * 31.0F) << 11)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 6)
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 1)
+ | (IROUND(rgba[i][RCOMP] * 1.0F) );
}
}
break;
@@ -2421,28 +2814,28 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGBA) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][RCOMP] * 31.0F)) )
- | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 5)
- | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 10)
- | (((GLint) (rgba[i][ACOMP] * 1.0F)) << 15);
+ dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) )
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 5)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 10)
+ | (IROUND(rgba[i][ACOMP] * 1.0F) << 15);
}
}
else if (dstFormat == GL_BGRA) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][BCOMP] * 31.0F)) )
- | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 5)
- | (((GLint) (rgba[i][RCOMP] * 31.0F)) << 10)
- | (((GLint) (rgba[i][ACOMP] * 1.0F)) << 15);
+ dst[i] = (IROUND(rgba[i][BCOMP] * 31.0F) )
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 5)
+ | (IROUND(rgba[i][RCOMP] * 31.0F) << 10)
+ | (IROUND(rgba[i][ACOMP] * 1.0F) << 15);
}
}
else if (dstFormat == GL_ABGR_EXT) {
GLushort *dst = (GLushort *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLint) (rgba[i][ACOMP] * 31.0F)) )
- | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 5)
- | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 10)
- | (((GLint) (rgba[i][RCOMP] * 1.0F)) << 15);
+ dst[i] = (IROUND(rgba[i][ACOMP] * 31.0F) )
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 5)
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 10)
+ | (IROUND(rgba[i][RCOMP] * 1.0F) << 15);
}
}
break;
@@ -2450,28 +2843,28 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGBA) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][RCOMP] * 255.0F)) << 24)
- | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 16)
- | (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 8)
- | (((GLuint) (rgba[i][ACOMP] * 255.0F)) );
+ dst[i] = (IROUND(rgba[i][RCOMP] * 255.F) << 24)
+ | (IROUND(rgba[i][GCOMP] * 255.F) << 16)
+ | (IROUND(rgba[i][BCOMP] * 255.F) << 8)
+ | (IROUND(rgba[i][ACOMP] * 255.F) );
}
}
else if (dstFormat == GL_BGRA) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 24)
- | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 16)
- | (((GLuint) (rgba[i][RCOMP] * 255.0F)) << 8)
- | (((GLuint) (rgba[i][ACOMP] * 255.0F)) );
+ dst[i] = (IROUND(rgba[i][BCOMP] * 255.F) << 24)
+ | (IROUND(rgba[i][GCOMP] * 255.F) << 16)
+ | (IROUND(rgba[i][RCOMP] * 255.F) << 8)
+ | (IROUND(rgba[i][ACOMP] * 255.F) );
}
}
else if (dstFormat == GL_ABGR_EXT) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][ACOMP] * 255.0F)) << 24)
- | (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 16)
- | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 8)
- | (((GLuint) (rgba[i][RCOMP] * 255.0F)) );
+ dst[i] = (IROUND(rgba[i][ACOMP] * 255.F) << 24)
+ | (IROUND(rgba[i][BCOMP] * 255.F) << 16)
+ | (IROUND(rgba[i][GCOMP] * 255.F) << 8)
+ | (IROUND(rgba[i][RCOMP] * 255.F) );
}
}
break;
@@ -2479,28 +2872,28 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGBA) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][RCOMP] * 255.0F)) )
- | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 8)
- | (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 16)
- | (((GLuint) (rgba[i][ACOMP] * 255.0F)) << 24);
+ dst[i] = (IROUND(rgba[i][RCOMP] * 255.0F) )
+ | (IROUND(rgba[i][GCOMP] * 255.0F) << 8)
+ | (IROUND(rgba[i][BCOMP] * 255.0F) << 16)
+ | (IROUND(rgba[i][ACOMP] * 255.0F) << 24);
}
}
else if (dstFormat == GL_BGRA) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][BCOMP] * 255.0F)) )
- | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 8)
- | (((GLuint) (rgba[i][RCOMP] * 255.0F)) << 16)
- | (((GLuint) (rgba[i][ACOMP] * 255.0F)) << 24);
+ dst[i] = (IROUND(rgba[i][BCOMP] * 255.0F) )
+ | (IROUND(rgba[i][GCOMP] * 255.0F) << 8)
+ | (IROUND(rgba[i][RCOMP] * 255.0F) << 16)
+ | (IROUND(rgba[i][ACOMP] * 255.0F) << 24);
}
}
else if (dstFormat == GL_ABGR_EXT) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][ACOMP] * 255.0F)) )
- | (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 8)
- | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 16)
- | (((GLuint) (rgba[i][RCOMP] * 255.0F)) << 24);
+ dst[i] = (IROUND(rgba[i][ACOMP] * 255.0F) )
+ | (IROUND(rgba[i][BCOMP] * 255.0F) << 8)
+ | (IROUND(rgba[i][GCOMP] * 255.0F) << 16)
+ | (IROUND(rgba[i][RCOMP] * 255.0F) << 24);
}
}
break;
@@ -2508,28 +2901,28 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGBA) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][RCOMP] * 1023.0F)) << 22)
- | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 12)
- | (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 2)
- | (((GLuint) (rgba[i][ACOMP] * 3.0F)) );
+ dst[i] = (IROUND(rgba[i][RCOMP] * 1023.0F) << 22)
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 12)
+ | (IROUND(rgba[i][BCOMP] * 1023.0F) << 2)
+ | (IROUND(rgba[i][ACOMP] * 3.0F) );
}
}
else if (dstFormat == GL_BGRA) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 22)
- | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 12)
- | (((GLuint) (rgba[i][RCOMP] * 1023.0F)) << 2)
- | (((GLuint) (rgba[i][ACOMP] * 3.0F)) );
+ dst[i] = (IROUND(rgba[i][BCOMP] * 1023.0F) << 22)
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 12)
+ | (IROUND(rgba[i][RCOMP] * 1023.0F) << 2)
+ | (IROUND(rgba[i][ACOMP] * 3.0F) );
}
}
else if (dstFormat == GL_ABGR_EXT) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][ACOMP] * 1023.0F)) << 22)
- | (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 12)
- | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 2)
- | (((GLuint) (rgba[i][RCOMP] * 3.0F)) );
+ dst[i] = (IROUND(rgba[i][ACOMP] * 1023.0F) << 22)
+ | (IROUND(rgba[i][BCOMP] * 1023.0F) << 12)
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 2)
+ | (IROUND(rgba[i][RCOMP] * 3.0F) );
}
}
break;
@@ -2537,28 +2930,28 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
if (dstFormat == GL_RGBA) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][RCOMP] * 1023.0F)) )
- | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 10)
- | (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 20)
- | (((GLuint) (rgba[i][ACOMP] * 3.0F)) << 30);
+ dst[i] = (IROUND(rgba[i][RCOMP] * 1023.0F) )
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 10)
+ | (IROUND(rgba[i][BCOMP] * 1023.0F) << 20)
+ | (IROUND(rgba[i][ACOMP] * 3.0F) << 30);
}
}
else if (dstFormat == GL_BGRA) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][BCOMP] * 1023.0F)) )
- | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 10)
- | (((GLuint) (rgba[i][RCOMP] * 1023.0F)) << 20)
- | (((GLuint) (rgba[i][ACOMP] * 3.0F)) << 30);
+ dst[i] = (IROUND(rgba[i][BCOMP] * 1023.0F) )
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 10)
+ | (IROUND(rgba[i][RCOMP] * 1023.0F) << 20)
+ | (IROUND(rgba[i][ACOMP] * 3.0F) << 30);
}
}
else if (dstFormat == GL_ABGR_EXT) {
GLuint *dst = (GLuint *) dstAddr;
for (i=0;i<n;i++) {
- dst[i] = (((GLuint) (rgba[i][ACOMP] * 1023.0F)) )
- | (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 10)
- | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 20)
- | (((GLuint) (rgba[i][RCOMP] * 3.0F)) << 30);
+ dst[i] = (IROUND(rgba[i][ACOMP] * 1023.0F) )
+ | (IROUND(rgba[i][BCOMP] * 1023.0F) << 10)
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 20)
+ | (IROUND(rgba[i][RCOMP] * 3.0F) << 30);
}
}
break;
@@ -2786,7 +3179,7 @@ extract_uint_indexes(GLuint n, GLuint indexes[],
}
else {
for (i = 0; i < n; i++)
- indexes[i] = s[i] & 0xfff; /* lower 8 bits */
+ indexes[i] = s[i] & 0xff; /* lower 8 bits */
}
}
break;
@@ -2834,7 +3227,8 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4],
srcFormat == GL_BGR ||
srcFormat == GL_RGBA ||
srcFormat == GL_BGRA ||
- srcFormat == GL_ABGR_EXT);
+ srcFormat == GL_ABGR_EXT ||
+ srcFormat == GL_DUDV_ATI);
ASSERT(srcType == GL_UNSIGNED_BYTE ||
srcType == GL_BYTE ||
@@ -2949,6 +3343,13 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4],
aComp = 0;
stride = 4;
break;
+ case GL_DUDV_ATI:
+ redIndex = 0;
+ greenIndex = 1;
+ blueIndex = -1;
+ alphaIndex = -1;
+ stride = 2;
+ break;
default:
_mesa_problem(NULL, "bad srcFormat in extract float data");
return;
@@ -3877,6 +4278,62 @@ _mesa_unpack_color_span_float( GLcontext *ctx,
}
}
+/**
+ * Similar to _mesa_unpack_color_span_float(), but for dudv data instead of rgba,
+ * directly return GLbyte data, no transfer ops apply.
+ */
+void
+_mesa_unpack_dudv_span_byte( GLcontext *ctx,
+ GLuint n, GLenum dstFormat, GLbyte dest[],
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps )
+{
+ ASSERT(dstFormat == GL_DUDV_ATI);
+ ASSERT(srcFormat == GL_DUDV_ATI);
+
+ ASSERT(srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_BYTE ||
+ srcType == GL_UNSIGNED_SHORT ||
+ srcType == GL_SHORT ||
+ srcType == GL_UNSIGNED_INT ||
+ srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_ARB ||
+ srcType == GL_FLOAT);
+
+ /* general solution */
+ {
+ GLint dstComponents;
+ GLfloat rgba[MAX_WIDTH][4];
+ GLbyte *dst = dest;
+ GLuint i;
+
+ dstComponents = _mesa_components_in_format( dstFormat );
+ /* source & dest image formats should have been error checked by now */
+ assert(dstComponents > 0);
+
+ /*
+ * Extract image data and convert to RGBA floats
+ */
+ assert(n <= MAX_WIDTH);
+ extract_float_rgba(n, rgba, srcFormat, srcType, source,
+ srcPacking->SwapBytes);
+
+
+ /* Now determine which color channels we need to produce.
+ * And determine the dest index (offset) within each color tuple.
+ */
+
+ /* Now pack results in the requested dstFormat */
+ for (i = 0; i < n; i++) {
+ /* not sure - need clamp[-1,1] here? */
+ dst[0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ dst[1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ dst += dstComponents;
+ }
+ }
+}
/*
* Unpack a row of color index data from a client buffer according to
@@ -4406,6 +4863,17 @@ _mesa_unpack_depth_span( const GLcontext *ctx, GLuint n,
}
return;
}
+ if (srcType == GL_UNSIGNED_INT_24_8
+ && dstType == GL_UNSIGNED_INT
+ && depthMax == 0xffffff) {
+ const GLuint *src = (const GLuint *) source;
+ GLuint *dst = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = src[i] >> 8;
+ }
+ return;
+ }
/* XXX may want to add additional cases here someday */
}
@@ -5172,3 +5640,181 @@ _mesa_clip_to_region(GLint xmin, GLint ymin,
return GL_TRUE;
}
+
+
+/**
+ * Clip dst coords against Xmax (or Ymax).
+ */
+static INLINE void
+clip_right_or_top(GLint *srcX0, GLint *srcX1,
+ GLint *dstX0, GLint *dstX1,
+ GLint maxValue)
+{
+ GLfloat t, bias;
+
+ if (*dstX1 > maxValue) {
+ /* X1 outside right edge */
+ ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */
+ t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
+ /* chop off [t, 1] part */
+ ASSERT(t >= 0.0 && t <= 1.0);
+ *dstX1 = maxValue;
+ bias = (*srcX0 < *srcX1) ? 0.5 : -0.5;
+ *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
+ }
+ else if (*dstX0 > maxValue) {
+ /* X0 outside right edge */
+ ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */
+ t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
+ /* chop off [t, 1] part */
+ ASSERT(t >= 0.0 && t <= 1.0);
+ *dstX0 = maxValue;
+ bias = (*srcX0 < *srcX1) ? -0.5 : 0.5;
+ *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
+ }
+}
+
+
+/**
+ * Clip dst coords against Xmin (or Ymin).
+ */
+static INLINE void
+clip_left_or_bottom(GLint *srcX0, GLint *srcX1,
+ GLint *dstX0, GLint *dstX1,
+ GLint minValue)
+{
+ GLfloat t, bias;
+
+ if (*dstX0 < minValue) {
+ /* X0 outside left edge */
+ ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */
+ t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
+ /* chop off [0, t] part */
+ ASSERT(t >= 0.0 && t <= 1.0);
+ *dstX0 = minValue;
+ bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; /* flipped??? */
+ *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
+ }
+ else if (*dstX1 < minValue) {
+ /* X1 outside left edge */
+ ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */
+ t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
+ /* chop off [0, t] part */
+ ASSERT(t >= 0.0 && t <= 1.0);
+ *dstX1 = minValue;
+ bias = (*srcX0 < *srcX1) ? 0.5 : -0.5;
+ *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
+ }
+}
+
+
+/**
+ * Do clipping of blit src/dest rectangles.
+ * The dest rect is clipped against both the buffer bounds and scissor bounds.
+ * The src rect is just clipped against the buffer bounds.
+ *
+ * When either the src or dest rect is clipped, the other is also clipped
+ * proportionately!
+ *
+ * Note that X0 need not be less than X1 (same for Y) for either the source
+ * and dest rects. That makes the clipping a little trickier.
+ *
+ * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
+ */
+GLboolean
+_mesa_clip_blit(GLcontext *ctx,
+ GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
+ GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1)
+{
+ const GLint srcXmin = 0;
+ const GLint srcXmax = ctx->ReadBuffer->Width;
+ const GLint srcYmin = 0;
+ const GLint srcYmax = ctx->ReadBuffer->Height;
+
+ /* these include scissor bounds */
+ const GLint dstXmin = ctx->DrawBuffer->_Xmin;
+ const GLint dstXmax = ctx->DrawBuffer->_Xmax;
+ const GLint dstYmin = ctx->DrawBuffer->_Ymin;
+ const GLint dstYmax = ctx->DrawBuffer->_Ymax;
+
+ /*
+ printf("PreClipX: src: %d .. %d dst: %d .. %d\n",
+ *srcX0, *srcX1, *dstX0, *dstX1);
+ printf("PreClipY: src: %d .. %d dst: %d .. %d\n",
+ *srcY0, *srcY1, *dstY0, *dstY1);
+ */
+
+ /* trivial rejection tests */
+ if (*dstX0 == *dstX1)
+ return GL_FALSE; /* no width */
+ if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)
+ return GL_FALSE; /* totally out (left) of bounds */
+ if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)
+ return GL_FALSE; /* totally out (right) of bounds */
+
+ if (*dstY0 == *dstY1)
+ return GL_FALSE;
+ if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)
+ return GL_FALSE;
+ if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)
+ return GL_FALSE;
+
+ if (*srcX0 == *srcX1)
+ return GL_FALSE;
+ if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)
+ return GL_FALSE;
+ if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)
+ return GL_FALSE;
+
+ if (*srcY0 == *srcY1)
+ return GL_FALSE;
+ if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)
+ return GL_FALSE;
+ if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)
+ return GL_FALSE;
+
+ /*
+ * dest clip
+ */
+ clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);
+ clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);
+ clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);
+ clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);
+
+ /*
+ * src clip (just swap src/dst values from above)
+ */
+ clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);
+ clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);
+ clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);
+ clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);
+
+ /*
+ printf("PostClipX: src: %d .. %d dst: %d .. %d\n",
+ *srcX0, *srcX1, *dstX0, *dstX1);
+ printf("PostClipY: src: %d .. %d dst: %d .. %d\n",
+ *srcY0, *srcY1, *dstY0, *dstY1);
+ */
+
+ ASSERT(*dstX0 >= dstXmin);
+ ASSERT(*dstX0 <= dstXmax);
+ ASSERT(*dstX1 >= dstXmin);
+ ASSERT(*dstX1 <= dstXmax);
+
+ ASSERT(*dstY0 >= dstYmin);
+ ASSERT(*dstY0 <= dstYmax);
+ ASSERT(*dstY1 >= dstYmin);
+ ASSERT(*dstY1 <= dstYmax);
+
+ ASSERT(*srcX0 >= srcXmin);
+ ASSERT(*srcX0 <= srcXmax);
+ ASSERT(*srcX1 >= srcXmin);
+ ASSERT(*srcX1 <= srcXmax);
+
+ ASSERT(*srcY0 >= srcYmin);
+ ASSERT(*srcY0 <= srcYmax);
+ ASSERT(*srcY1 >= srcYmin);
+ ASSERT(*srcY1 <= srcYmax);
+
+ return GL_TRUE;
+}
diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h
index 0e0bbd96d8..72717d6787 100644
--- a/src/mesa/main/image.h
+++ b/src/mesa/main/image.h
@@ -54,6 +54,27 @@ _mesa_bytes_per_pixel( GLenum format, GLenum type );
extern GLboolean
_mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type );
+extern GLboolean
+_mesa_is_color_format(GLenum format);
+
+extern GLboolean
+_mesa_is_index_format(GLenum format);
+
+extern GLboolean
+_mesa_is_depth_format(GLenum format);
+
+extern GLboolean
+_mesa_is_stencil_format(GLenum format);
+
+extern GLboolean
+_mesa_is_ycbcr_format(GLenum format);
+
+extern GLboolean
+_mesa_is_depthstencil_format(GLenum format);
+
+extern GLboolean
+_mesa_is_dudv_format(GLenum format);
+
extern GLvoid *
_mesa_image_address( GLuint dimensions,
@@ -113,6 +134,13 @@ extern void
_mesa_pack_bitmap( GLint width, GLint height, const GLubyte *source,
GLubyte *dest, const struct gl_pixelstore_attrib *packing );
+extern void
+_mesa_expand_bitmap(GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap,
+ GLubyte *destBuffer, GLint destStride,
+ GLubyte onValue);
+
/** \name Pixel processing functions */
/*@{*/
@@ -198,6 +226,13 @@ _mesa_unpack_color_span_float( GLcontext *ctx,
const struct gl_pixelstore_attrib *srcPacking,
GLbitfield transferOps );
+extern void
+_mesa_unpack_dudv_span_byte( GLcontext *ctx,
+ GLuint n, GLenum dstFormat, GLbyte dest[],
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps );
extern void
_mesa_unpack_index_span( const GLcontext *ctx, GLuint n,
@@ -284,4 +319,10 @@ _mesa_clip_to_region(GLint xmin, GLint ymin,
GLint *x, GLint *y,
GLsizei *width, GLsizei *height );
+extern GLboolean
+_mesa_clip_blit(GLcontext *ctx,
+ GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
+ GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1);
+
+
#endif
diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c
index 5cf1a2baa4..6ffaddcde9 100644
--- a/src/mesa/main/imports.c
+++ b/src/mesa/main/imports.c
@@ -557,7 +557,7 @@ _mesa_pow(double x, double y)
* Find the first bit set in a word.
*/
int
-_mesa_ffs(int i)
+_mesa_ffs(int32_t i)
{
#if (defined(_WIN32) ) || defined(__IBMC__) || defined(__IBMCPP__)
register int bit = 0;
@@ -594,11 +594,7 @@ _mesa_ffs(int i)
* if no bits set.
*/
int
-#ifdef __MINGW32__
-_mesa_ffsll(long val)
-#else
-_mesa_ffsll(long long val)
-#endif
+_mesa_ffsll(int64_t val)
{
#ifdef ffsll
return ffsll(val);
@@ -607,11 +603,11 @@ _mesa_ffsll(long long val)
assert(sizeof(val) == 8);
- bit = _mesa_ffs(val);
+ bit = _mesa_ffs((int32_t)val);
if (bit != 0)
return bit;
- bit = _mesa_ffs(val >> 32);
+ bit = _mesa_ffs((int32_t)(val >> 32));
if (bit != 0)
return 32 + bit;
@@ -915,6 +911,20 @@ _mesa_strtod( const char *s, char **end )
return strtod(s, end);
}
+/** Compute simple checksum/hash for a string */
+unsigned int
+_mesa_str_checksum(const char *str)
+{
+ /* This could probably be much better */
+ unsigned int sum, i;
+ const char *c;
+ sum = i = 1;
+ for (c = str; *c; c++)
+ sum += *c * (i % 100);
+ return sum;
+}
+
+
/*@}*/
@@ -950,14 +960,25 @@ _mesa_snprintf( char *str, size_t size, const char *fmt, ... )
void
_mesa_printf( const char *fmtString, ... )
{
+ va_list args;
+ va_start( args, fmtString );
+ vfprintf(stderr, fmtString, args);
+ va_end( args );
+}
+
+/** Wrapper around fprintf(), using vsprintf() for the formatting. */
+void
+_mesa_fprintf( FILE *f, const char *fmtString, ... )
+{
char s[MAXSTRING];
va_list args;
va_start( args, fmtString );
vsnprintf(s, MAXSTRING, fmtString, args);
va_end( args );
- fprintf(stderr,"%s", s);
+ fprintf(f, "%s", s);
}
+
/** Wrapper around vsprintf() */
int
_mesa_vsprintf( char *str, const char *fmt, va_list args )
@@ -972,39 +993,130 @@ _mesa_vsprintf( char *str, const char *fmt, va_list args )
/** \name Diagnostics */
/*@{*/
+static void
+output_if_debug(const char *prefixString, const char *outputString,
+ GLboolean newline)
+{
+ static int debug = -1;
+
+ /* Check the MESA_DEBUG environment variable if it hasn't
+ * been checked yet. We only have to check it once...
+ */
+ if (debug == -1) {
+ char *env = _mesa_getenv("MESA_DEBUG");
+
+ /* In a debug build, we print warning messages *unless*
+ * MESA_DEBUG is 0. In a non-debug build, we don't
+ * print warning messages *unless* MESA_DEBUG is
+ * set *to any value*.
+ */
+#ifdef DEBUG
+ debug = (env != NULL && _mesa_atoi(env) == 0) ? 0 : 1;
+#else
+ debug = (env != NULL) ? 1 : 0;
+#endif
+ }
+
+ /* Now only print the string if we're required to do so. */
+ if (debug) {
+ fprintf(stderr, "%s: %s", prefixString, outputString);
+ if (newline)
+ fprintf(stderr, "\n");
+
+#if defined(_WIN32) && !defined(_WIN32_WCE)
+ /* stderr from windows applications without console is not usually
+ * visible, so communicate with the debugger instead */
+ {
+ char buf[4096];
+ _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
+ OutputDebugStringA(buf);
+ }
+#endif
+ }
+}
+
+
+/**
+ * Return string version of GL error code.
+ */
+static const char *
+error_string( GLenum error )
+{
+ switch (error) {
+ case GL_NO_ERROR:
+ return "GL_NO_ERROR";
+ case GL_INVALID_VALUE:
+ return "GL_INVALID_VALUE";
+ case GL_INVALID_ENUM:
+ return "GL_INVALID_ENUM";
+ case GL_INVALID_OPERATION:
+ return "GL_INVALID_OPERATION";
+ case GL_STACK_OVERFLOW:
+ return "GL_STACK_OVERFLOW";
+ case GL_STACK_UNDERFLOW:
+ return "GL_STACK_UNDERFLOW";
+ case GL_OUT_OF_MEMORY:
+ return "GL_OUT_OF_MEMORY";
+ case GL_TABLE_TOO_LARGE:
+ return "GL_TABLE_TOO_LARGE";
+ case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
+ return "GL_INVALID_FRAMEBUFFER_OPERATION";
+ default:
+ return "unknown";
+ }
+}
+
+
+/**
+ * When a new type of error is recorded, print a message describing
+ * previous errors which were accumulated.
+ */
+static void
+flush_delayed_errors( GLcontext *ctx )
+{
+ char s[MAXSTRING];
+
+ if (ctx->ErrorDebugCount) {
+ _mesa_snprintf(s, MAXSTRING, "%d similar %s errors",
+ ctx->ErrorDebugCount,
+ error_string(ctx->ErrorValue));
+
+ output_if_debug("Mesa", s, GL_TRUE);
+
+ ctx->ErrorDebugCount = 0;
+ }
+}
+
+
/**
* Report a warning (a recoverable error condition) to stderr if
* either DEBUG is defined or the MESA_DEBUG env var is set.
*
* \param ctx GL context.
- * \param fmtString printf() alike format string.
+ * \param fmtString printf()-like format string.
*/
void
_mesa_warning( GLcontext *ctx, const char *fmtString, ... )
{
- GLboolean debug;
char str[MAXSTRING];
va_list args;
- (void) ctx;
va_start( args, fmtString );
(void) vsnprintf( str, MAXSTRING, fmtString, args );
va_end( args );
-#ifdef DEBUG
- debug = GL_TRUE; /* always print warning */
-#else
- debug = _mesa_getenv("MESA_DEBUG") ? GL_TRUE : GL_FALSE;
-#endif
- if (debug) {
- fprintf(stderr, "Mesa warning: %s\n", str);
- }
+
+ if (ctx)
+ flush_delayed_errors( ctx );
+
+ output_if_debug("Mesa warning", str, GL_TRUE);
}
+
/**
- * Report an internla implementation problem.
+ * Report an internal implementation problem.
* Prints the message to stderr via fprintf().
*
* \param ctx GL context.
- * \param s problem description string.
+ * \param fmtString problem description string.
*/
void
_mesa_problem( const GLcontext *ctx, const char *fmtString, ... )
@@ -1021,8 +1133,9 @@ _mesa_problem( const GLcontext *ctx, const char *fmtString, ... )
fprintf(stderr, "Please report at bugzilla.freedesktop.org\n");
}
+
/**
- * Record an OpenGL state error. These usually occur when the users
+ * Record an OpenGL state error. These usually occur when the user
* passes invalid parameters to a GL function.
*
* If debugging is enabled (either at compile-time via the DEBUG macro, or
@@ -1036,69 +1149,52 @@ _mesa_problem( const GLcontext *ctx, const char *fmtString, ... )
void
_mesa_error( GLcontext *ctx, GLenum error, const char *fmtString, ... )
{
- const char *debugEnv;
- GLboolean debug;
+ static GLint debug = -1;
- debugEnv = _mesa_getenv("MESA_DEBUG");
+ /* Check debug environment variable only once:
+ */
+ if (debug == -1) {
+ const char *debugEnv = _mesa_getenv("MESA_DEBUG");
#ifdef DEBUG
- if (debugEnv && _mesa_strstr(debugEnv, "silent"))
- debug = GL_FALSE;
- else
- debug = GL_TRUE;
+ if (debugEnv && _mesa_strstr(debugEnv, "silent"))
+ debug = GL_FALSE;
+ else
+ debug = GL_TRUE;
#else
- if (debugEnv)
- debug = GL_TRUE;
- else
- debug = GL_FALSE;
+ if (debugEnv)
+ debug = GL_TRUE;
+ else
+ debug = GL_FALSE;
#endif
+ }
- if (debug) {
- va_list args;
- char where[MAXSTRING];
- const char *errstr;
-
- va_start( args, fmtString );
- vsnprintf( where, MAXSTRING, fmtString, args );
- va_end( args );
-
- switch (error) {
- case GL_NO_ERROR:
- errstr = "GL_NO_ERROR";
- break;
- case GL_INVALID_VALUE:
- errstr = "GL_INVALID_VALUE";
- break;
- case GL_INVALID_ENUM:
- errstr = "GL_INVALID_ENUM";
- break;
- case GL_INVALID_OPERATION:
- errstr = "GL_INVALID_OPERATION";
- break;
- case GL_STACK_OVERFLOW:
- errstr = "GL_STACK_OVERFLOW";
- break;
- case GL_STACK_UNDERFLOW:
- errstr = "GL_STACK_UNDERFLOW";
- break;
- case GL_OUT_OF_MEMORY:
- errstr = "GL_OUT_OF_MEMORY";
- break;
- case GL_TABLE_TOO_LARGE:
- errstr = "GL_TABLE_TOO_LARGE";
- break;
- case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
- errstr = "GL_INVALID_FRAMEBUFFER_OPERATION";
- break;
- default:
- errstr = "unknown";
- break;
+ if (debug) {
+ if (ctx->ErrorValue == error &&
+ ctx->ErrorDebugFmtString == fmtString) {
+ ctx->ErrorDebugCount++;
+ }
+ else {
+ char s[MAXSTRING], s2[MAXSTRING];
+ va_list args;
+
+ flush_delayed_errors( ctx );
+
+ va_start(args, fmtString);
+ vsnprintf(s, MAXSTRING, fmtString, args);
+ va_end(args);
+
+ _mesa_snprintf(s2, MAXSTRING, "%s in %s", error_string(error), s);
+ output_if_debug("Mesa: User error", s2, GL_TRUE);
+
+ ctx->ErrorDebugFmtString = fmtString;
+ ctx->ErrorDebugCount = 0;
}
- _mesa_debug(ctx, "User error: %s in %s\n", errstr, where);
}
_mesa_record_error(ctx, error);
-}
+}
+
/**
* Report debug information. Print error message to stderr via fprintf().
@@ -1116,7 +1212,7 @@ _mesa_debug( const GLcontext *ctx, const char *fmtString, ... )
va_start(args, fmtString);
vsnprintf(s, MAXSTRING, fmtString, args);
va_end(args);
- fprintf(stderr, "Mesa: %s", s);
+ output_if_debug("Mesa", s, GL_FALSE);
#endif /* DEBUG */
(void) ctx;
(void) fmtString;
diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h
index 13b571d1cb..7d4012a856 100644
--- a/src/mesa/main/imports.h
+++ b/src/mesa/main/imports.h
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.5
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
@@ -36,10 +36,8 @@
#define IMPORTS_H
-/* XXX some of the stuff in glheader.h should be moved into this file.
- */
+#include "compiler.h"
#include "glheader.h"
-#include <GL/internal/glcore.h>
#ifdef __cplusplus
@@ -48,26 +46,6 @@ extern "C" {
/**********************************************************************/
-/** \name General macros */
-/*@{*/
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-
-/** gcc -pedantic warns about long string literals, LONGSTRING silences that */
-#if !defined(__GNUC__) || (__GNUC__ < 2) || \
- ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
-# define LONGSTRING
-#else
-# define LONGSTRING __extension__
-#endif
-
-/*@}*/
-
-
-/**********************************************************************/
/** Memory macros */
/*@{*/
@@ -130,49 +108,11 @@ typedef union { GLfloat f; GLint i; } fi_type;
#define MAX_GLUSHORT 0xffff
#define MAX_GLUINT 0xffffffff
-#ifndef M_PI
-#define M_PI (3.1415926536)
-#endif
-
-#ifndef M_E
-#define M_E (2.7182818284590452354)
-#endif
-
-#ifndef ONE_DIV_LN2
-#define ONE_DIV_LN2 (1.442695040888963456)
-#endif
-
-#ifndef ONE_DIV_SQRT_LN2
-#define ONE_DIV_SQRT_LN2 (1.201122408786449815)
-#endif
-
-#ifndef FLT_MAX_EXP
-#define FLT_MAX_EXP 128
-#endif
-
/* Degrees to radians conversion: */
#define DEG2RAD (M_PI/180.0)
/***
- *** USE_IEEE: Determine if we're using IEEE floating point
- ***/
-#if defined(__i386__) || defined(__386__) || defined(__sparc__) || \
- defined(__s390x__) || defined(__powerpc__) || \
- defined(__x86_64__) || \
- defined(ia64) || defined(__ia64__) || \
- defined(__hppa__) || defined(hpux) || \
- defined(__mips) || defined(_MIPS_ARCH) || \
- defined(__arm__) || \
- defined(__sh__) || defined(__m32r__) || \
- (defined(__sun) && defined(_IEEE_754)) || \
- (defined(__alpha__) && (defined(__IEEE_FLOAT) || !defined(VMS)))
-#define USE_IEEE
-#define IEEE_ONE 0x3f800000
-#endif
-
-
-/***
*** SQRTF: single-precision square root
***/
#if 0 /* _mesa_sqrtf() not accurate enough - temporarily disabled */
@@ -316,16 +256,9 @@ static INLINE int GET_FLOAT_BITS( float x )
/***
*** IROUND: return (as an integer) float rounded to nearest integer
***/
-#if defined(USE_SPARC_ASM) && defined(__GNUC__) && defined(__sparc__)
-static INLINE int iround(float f)
-{
- int r;
- __asm__ ("fstoi %1, %0" : "=f" (r) : "f" (f));
- return r;
-}
-#define IROUND(x) iround(x)
-#elif defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) && \
- (!defined(__BEOS__) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)))
+#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) && \
+ (!(defined(__BEOS__) || defined(__HAIKU__)) || \
+ (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)))
static INLINE int iround(float f)
{
int r;
@@ -358,6 +291,7 @@ long iround(float f);
#define IROUND(f) ((int) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
#endif
+#define IROUND64(f) ((GLint64) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
/***
*** IROUND_POS: return (as an integer) positive float rounded to nearest int
@@ -508,113 +442,6 @@ _mesa_is_pow_two(int x)
#endif
-/***
- *** START_FAST_MATH: Set x86 FPU to faster, 32-bit precision mode (and save
- *** original mode to a temporary).
- *** END_FAST_MATH: Restore x86 FPU to original mode.
- ***/
-#if defined(__GNUC__) && defined(__i386__)
-/*
- * Set the x86 FPU control word to guarentee only 32 bits of precision
- * are stored in registers. Allowing the FPU to store more introduces
- * differences between situations where numbers are pulled out of memory
- * vs. situations where the compiler is able to optimize register usage.
- *
- * In the worst case, we force the compiler to use a memory access to
- * truncate the float, by specifying the 'volatile' keyword.
- */
-/* Hardware default: All exceptions masked, extended double precision,
- * round to nearest (IEEE compliant):
- */
-#define DEFAULT_X86_FPU 0x037f
-/* All exceptions masked, single precision, round to nearest:
- */
-#define FAST_X86_FPU 0x003f
-/* The fldcw instruction will cause any pending FP exceptions to be
- * raised prior to entering the block, and we clear any pending
- * exceptions before exiting the block. Hence, asm code has free
- * reign over the FPU while in the fast math block.
- */
-#if defined(NO_FAST_MATH)
-#define START_FAST_MATH(x) \
-do { \
- static GLuint mask = DEFAULT_X86_FPU; \
- __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
- __asm__ ( "fldcw %0" : : "m" (mask) ); \
-} while (0)
-#else
-#define START_FAST_MATH(x) \
-do { \
- static GLuint mask = FAST_X86_FPU; \
- __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
- __asm__ ( "fldcw %0" : : "m" (mask) ); \
-} while (0)
-#endif
-/* Restore original FPU mode, and clear any exceptions that may have
- * occurred in the FAST_MATH block.
- */
-#define END_FAST_MATH(x) \
-do { \
- __asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \
-} while (0)
-
-#elif defined(__WATCOMC__) && defined(__386__)
-#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */
-#define FAST_X86_FPU 0x003f /* See GCC comments above */
-void _watcom_start_fast_math(unsigned short *x,unsigned short *mask);
-#pragma aux _watcom_start_fast_math = \
- "fnstcw word ptr [eax]" \
- "fldcw word ptr [ecx]" \
- parm [eax] [ecx] \
- modify exact [];
-void _watcom_end_fast_math(unsigned short *x);
-#pragma aux _watcom_end_fast_math = \
- "fnclex" \
- "fldcw word ptr [eax]" \
- parm [eax] \
- modify exact [];
-#if defined(NO_FAST_MATH)
-#define START_FAST_MATH(x) \
-do { \
- static GLushort mask = DEFAULT_X86_FPU; \
- _watcom_start_fast_math(&x,&mask); \
-} while (0)
-#else
-#define START_FAST_MATH(x) \
-do { \
- static GLushort mask = FAST_X86_FPU; \
- _watcom_start_fast_math(&x,&mask); \
-} while (0)
-#endif
-#define END_FAST_MATH(x) _watcom_end_fast_math(&x)
-
-#elif defined(_MSC_VER) && defined(_M_IX86)
-#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */
-#define FAST_X86_FPU 0x003f /* See GCC comments above */
-#if defined(NO_FAST_MATH)
-#define START_FAST_MATH(x) do {\
- static GLuint mask = DEFAULT_X86_FPU;\
- __asm fnstcw word ptr [x]\
- __asm fldcw word ptr [mask]\
-} while(0)
-#else
-#define START_FAST_MATH(x) do {\
- static GLuint mask = FAST_X86_FPU;\
- __asm fnstcw word ptr [x]\
- __asm fldcw word ptr [mask]\
-} while(0)
-#endif
-#define END_FAST_MATH(x) do {\
- __asm fnclex\
- __asm fldcw word ptr [x]\
-} while(0)
-
-#else
-#define START_FAST_MATH(x) x = 0
-#define END_FAST_MATH(x) (void)(x)
-#endif
-
-
/**
* Return 1 if this is a little endian machine, 0 if big endian.
*/
@@ -708,14 +535,10 @@ extern double
_mesa_pow(double x, double y);
extern int
-_mesa_ffs(int i);
+_mesa_ffs(int32_t i);
extern int
-#ifdef __MINGW32__
-_mesa_ffsll(long i);
-#else
-_mesa_ffsll(long long i);
-#endif
+_mesa_ffsll(int64_t i);
extern unsigned int
_mesa_bitcount(unsigned int n);
@@ -764,6 +587,9 @@ _mesa_atoi( const char *s );
extern double
_mesa_strtod( const char *s, char **end );
+extern unsigned int
+_mesa_str_checksum(const char *str);
+
extern int
_mesa_sprintf( char *str, const char *fmt, ... );
@@ -773,6 +599,9 @@ _mesa_snprintf( char *str, size_t size, const char *fmt, ... );
extern void
_mesa_printf( const char *fmtString, ... );
+extern void
+_mesa_fprintf( FILE *f, const char *fmtString, ... );
+
extern int
_mesa_vsprintf( char *str, const char *fmt, va_list args );
diff --git a/src/mesa/main/light.c b/src/mesa/main/light.c
index ce50224d30..10c89f4368 100644
--- a/src/mesa/main/light.c
+++ b/src/mesa/main/light.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.0
+ * Version: 7.5
*
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -64,6 +65,37 @@ _mesa_ShadeModel( GLenum mode )
/**
+ * Set the provoking vertex (the vertex which specifies the prim's
+ * color when flat shading) to either the first or last vertex of the
+ * triangle or line.
+ */
+void GLAPIENTRY
+_mesa_ProvokingVertexEXT(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glProvokingVertexEXT 0x%x\n", mode);
+
+ switch (mode) {
+ case GL_FIRST_VERTEX_CONVENTION_EXT:
+ case GL_LAST_VERTEX_CONVENTION_EXT:
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProvokingVertexEXT(0x%x)", mode);
+ return;
+ }
+
+ if (ctx->Light.ProvokingVertex == mode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.ProvokingVertex = mode;
+}
+
+
+/**
* Helper function called by _mesa_Lightfv and _mesa_PopAttrib to set
* per-light state.
* For GL_POSITION and GL_SPOT_DIRECTION the params position/direction
@@ -110,10 +142,10 @@ _mesa_light(GLcontext *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
break;
case GL_SPOT_DIRECTION:
/* NOTE: Direction already transformed by inverse ModelView! */
- if (TEST_EQ_3V(light->EyeDirection, params))
+ if (TEST_EQ_3V(light->SpotDirection, params))
return;
FLUSH_VERTICES(ctx, _NEW_LIGHT);
- COPY_3V(light->EyeDirection, params);
+ COPY_3V(light->SpotDirection, params);
break;
case GL_SPOT_EXPONENT:
ASSERT(params[0] >= 0.0);
@@ -209,7 +241,6 @@ _mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
_math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
}
TRANSFORM_DIRECTION(temp, params, ctx->ModelviewMatrixStack.Top->m);
- NORMALIZE_3FV(temp);
params = temp;
break;
case GL_SPOT_EXPONENT:
@@ -326,7 +357,7 @@ _mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
COPY_4V( params, ctx->Light.Light[l].EyePosition );
break;
case GL_SPOT_DIRECTION:
- COPY_3V( params, ctx->Light.Light[l].EyeDirection );
+ COPY_3V( params, ctx->Light.Light[l].SpotDirection );
break;
case GL_SPOT_EXPONENT:
params[0] = ctx->Light.Light[l].SpotExponent;
@@ -388,9 +419,9 @@ _mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
params[3] = (GLint) ctx->Light.Light[l].EyePosition[3];
break;
case GL_SPOT_DIRECTION:
- params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0];
- params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1];
- params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2];
+ params[0] = (GLint) ctx->Light.Light[l].SpotDirection[0];
+ params[1] = (GLint) ctx->Light.Light[l].SpotDirection[1];
+ params[2] = (GLint) ctx->Light.Light[l].SpotDirection[2];
break;
case GL_SPOT_EXPONENT:
params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
@@ -497,7 +528,7 @@ _mesa_LightModeliv( GLenum pname, const GLint *params )
break;
default:
/* Error will be caught later in gl_LightModelfv */
- ;
+ ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F);
}
_mesa_LightModelfv( pname, fparam );
}
@@ -1137,20 +1168,26 @@ compute_light_positions( GLcontext *ctx )
}
if (light->_Flags & LIGHT_SPOT) {
+ /* Note: we normalize the spot direction now */
+
if (ctx->_NeedEyeCoords) {
- COPY_3V( light->_NormDirection, light->EyeDirection );
+ COPY_3V( light->_NormSpotDirection, light->SpotDirection );
+ NORMALIZE_3FV( light->_NormSpotDirection );
}
else {
- TRANSFORM_NORMAL( light->_NormDirection,
- light->EyeDirection,
+ GLfloat spotDir[3];
+ COPY_3V(spotDir, light->SpotDirection);
+ NORMALIZE_3FV(spotDir);
+ TRANSFORM_NORMAL( light->_NormSpotDirection,
+ spotDir,
ctx->ModelviewMatrixStack.Top->m);
}
- NORMALIZE_3FV( light->_NormDirection );
+ NORMALIZE_3FV( light->_NormSpotDirection );
if (!(light->_Flags & LIGHT_POSITIONAL)) {
GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm,
- light->_NormDirection);
+ light->_NormSpotDirection);
if (PV_dot_dir > light->_CosCutoff) {
double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
@@ -1219,15 +1256,15 @@ _mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state )
ctx->Driver.LightingSpaceChange( ctx );
}
else {
- GLuint new_state = ctx->NewState;
+ GLuint new_state2 = ctx->NewState;
/* Recalculate that same state only if it has been invalidated
* by other statechanges.
*/
- if (new_state & _NEW_MODELVIEW)
+ if (new_state2 & _NEW_MODELVIEW)
update_modelview_scale(ctx);
- if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW))
+ if (new_state2 & (_NEW_LIGHT|_NEW_MODELVIEW))
compute_light_positions( ctx );
}
}
@@ -1274,7 +1311,7 @@ init_light( struct gl_light *l, GLuint n )
ASSIGN_4V( l->Specular, 0.0, 0.0, 0.0, 1.0 );
}
ASSIGN_4V( l->EyePosition, 0.0, 0.0, 1.0, 0.0 );
- ASSIGN_3V( l->EyeDirection, 0.0, 0.0, -1.0 );
+ ASSIGN_3V( l->SpotDirection, 0.0, 0.0, -1.0 );
l->SpotExponent = 0.0;
_mesa_invalidate_spot_exp_table( l );
l->SpotCutoff = 180.0;
@@ -1343,6 +1380,7 @@ _mesa_init_lighting( GLcontext *ctx )
init_lightmodel( &ctx->Light.Model );
init_material( &ctx->Light.Material );
ctx->Light.ShadeModel = GL_SMOOTH;
+ ctx->Light.ProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
ctx->Light.Enabled = GL_FALSE;
ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK;
ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
@@ -1368,6 +1406,7 @@ _mesa_init_lighting( GLcontext *ctx )
/* Miscellaneous */
ctx->Light._NeedEyeCoords = GL_FALSE;
ctx->_NeedEyeCoords = GL_FALSE;
+ ctx->_ForceEyeCoords = GL_FALSE;
ctx->_ModelViewInvScale = 1.0;
}
diff --git a/src/mesa/main/light.h b/src/mesa/main/light.h
index b97e17b5be..9c1a5eefad 100644
--- a/src/mesa/main/light.h
+++ b/src/mesa/main/light.h
@@ -1,13 +1,9 @@
-/**
- * \file light.h
- * Lighting.
- */
-
/*
* Mesa 3-D graphics library
- * Version: 3.5
+ * Version: 7.5
*
- * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -37,6 +33,10 @@
extern void GLAPIENTRY
_mesa_ShadeModel( GLenum mode );
+extern void GLAPIENTRY
+_mesa_ProvokingVertexEXT(GLenum mode);
+
+
#if _HAVE_FULL_GL
extern void GLAPIENTRY
_mesa_ColorMaterial( GLenum face, GLenum mode );
diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h
index 2630855a0e..3d9a1aba98 100644
--- a/src/mesa/main/macros.h
+++ b/src/mesa/main/macros.h
@@ -54,33 +54,61 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
#define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 )
-/** Convert GLushort in [0,65536] to GLfloat in [0.0,1.0] */
+/** Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0], texture/fb data */
+#define BYTE_TO_FLOAT_TEX(B) ((B) == -128 ? -1.0F : (B) * (1.0F/127.0F))
+
+/** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127], texture/fb data */
+#define FLOAT_TO_BYTE_TEX(X) ( (GLint) (127.0F * (X)) )
+
+
+/** Convert GLushort in [0,65535] to GLfloat in [0.0,1.0] */
#define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F))
+/** Convert GLfloat in [0.0,1.0] to GLushort in [0, 65535] */
+#define FLOAT_TO_USHORT(X) ((GLuint) ((X) * 65535.0F))
+
+
/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */
#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
-/** Convert GLfloat in [0.0,1.0] to GLshort in [-32768,32767] */
+/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767] */
#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 )
+/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0], texture/fb data */
+#define SHORT_TO_FLOAT_TEX(S) ((S) == -32768 ? -1.0F : (S) * (1.0F/32767.0F))
+
+/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767], texture/fb data */
+#define FLOAT_TO_SHORT_TEX(X) ( (GLint) (32767.0F * (X)) )
+
+
/** Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */
-#define UINT_TO_FLOAT(U) ((GLfloat) (U) * (1.0F / 4294967295.0F))
+#define UINT_TO_FLOAT(U) ((GLfloat) (U) * (1.0F / 4294967295.0))
/** Convert GLfloat in [0.0,1.0] to GLuint in [0,4294967295] */
#define FLOAT_TO_UINT(X) ((GLuint) ((X) * 4294967295.0))
/** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0] */
-#define INT_TO_FLOAT(I) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0F))
+#define INT_TO_FLOAT(I) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0))
/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647] */
/* causes overflow:
-#define FLOAT_TO_INT(X) ( (((GLint) (4294967294.0F * (X))) - 1) / 2 )
+#define FLOAT_TO_INT(X) ( (((GLint) (4294967294.0 * (X))) - 1) / 2 )
*/
/* a close approximation: */
#define FLOAT_TO_INT(X) ( (GLint) (2147483647.0 * (X)) )
+/** Convert GLfloat in [-1.0,1.0] to GLint64 in [-(1<<63),(1 << 63) -1] */
+#define FLOAT_TO_INT64(X) ( (GLint64) (9223372036854775807.0 * (double)(X)) )
+
+
+/** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0], texture/fb data */
+#define INT_TO_FLOAT_TEX(I) ((I) == -2147483648 ? -1.0F : (I) * (1.0F/2147483647.0))
+
+/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647], texture/fb data */
+#define FLOAT_TO_INT_TEX(X) ( (GLint) (2147483647.0 * (X)) )
+
#define BYTE_TO_UBYTE(b) ((GLubyte) ((b) < 0 ? 0 : (GLubyte) (b)))
#define SHORT_TO_UBYTE(s) ((GLubyte) ((s) < 0 ? 0 : (GLubyte) ((s) >> 7)))
@@ -95,7 +123,7 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
#define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15)))
#define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16)))
#define UNCLAMPED_FLOAT_TO_USHORT(us, f) \
- us = ( (GLushort) IROUND( CLAMP((f), 0.0, 1.0) * 65535.0F) )
+ us = ( (GLushort) IROUND( CLAMP((f), 0.0F, 1.0F) * 65535.0F) )
#define CLAMPED_FLOAT_TO_USHORT(us, f) \
us = ( (GLushort) IROUND( (f) * 65535.0F) )
diff --git a/src/mesa/main/matrix.c b/src/mesa/main/matrix.c
index 0f96f94909..ebc3cbd59c 100644
--- a/src/mesa/main/matrix.c
+++ b/src/mesa/main/matrix.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 6.5.3
+ * Version: 7.5
*
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -42,7 +43,6 @@
#include "matrix.h"
#include "mtypes.h"
#include "math/m_matrix.h"
-#include "math/m_xform.h"
/**
@@ -160,10 +160,21 @@ _mesa_MatrixMode( GLenum mode )
ctx->CurrentStack = &ctx->ProjectionMatrixStack;
break;
case GL_TEXTURE:
+ /* This error check is disabled because if we're called from
+ * glPopAttrib() when the active texture unit is >= MaxTextureCoordUnits
+ * we'll generate an unexpected error.
+ * From the GL_ARB_vertex_shader spec it sounds like we should instead
+ * do error checking in other places when we actually try to access
+ * texture matrices beyond MaxTextureCoordUnits.
+ */
+#if 0
if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glMatrixMode(texcoord unit)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glMatrixMode(invalid tex unit %d)",
+ ctx->Texture.CurrentUnit);
return;
}
+#endif
+ ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->TextureMatrixStack));
ctx->CurrentStack = &ctx->TextureMatrixStack[ctx->Texture.CurrentUnit];
break;
case GL_COLOR:
@@ -536,120 +547,6 @@ _mesa_MultTransposeMatrixdARB( const GLdouble *m )
}
#endif
-/**
- * Set the viewport.
- *
- * \param x, y coordinates of the lower-left corner of the viewport rectangle.
- * \param width width of the viewport rectangle.
- * \param height height of the viewport rectangle.
- *
- * \sa Called via glViewport() or display list execution.
- *
- * Flushes the vertices and calls _mesa_set_viewport() with the given
- * parameters.
- */
-void GLAPIENTRY
-_mesa_Viewport( GLint x, GLint y, GLsizei width, GLsizei height )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- _mesa_set_viewport(ctx, x, y, width, height);
-}
-
-
-/**
- * Set new viewport parameters and update derived state (the _WindowMap
- * matrix). Usually called from _mesa_Viewport().
- *
- * \param ctx GL context.
- * \param x, y coordinates of the lower left corner of the viewport rectangle.
- * \param width width of the viewport rectangle.
- * \param height height of the viewport rectangle.
- */
-void
-_mesa_set_viewport( GLcontext *ctx, GLint x, GLint y,
- GLsizei width, GLsizei height )
-{
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height);
-
- if (width < 0 || height < 0) {
- _mesa_error( ctx, GL_INVALID_VALUE,
- "glViewport(%d, %d, %d, %d)", x, y, width, height );
- return;
- }
-
- /* clamp width and height to the implementation dependent range */
- width = CLAMP(width, 1, (GLsizei) ctx->Const.MaxViewportWidth);
- height = CLAMP(height, 1, (GLsizei) ctx->Const.MaxViewportHeight);
-
- ctx->Viewport.X = x;
- ctx->Viewport.Width = width;
- ctx->Viewport.Y = y;
- ctx->Viewport.Height = height;
- ctx->NewState |= _NEW_VIEWPORT;
-
-#if 1
- /* XXX remove this someday. Currently the DRI drivers rely on
- * the WindowMap matrix being up to date in the driver's Viewport
- * and DepthRange functions.
- */
- _math_matrix_viewport(&ctx->Viewport._WindowMap,
- ctx->Viewport.X, ctx->Viewport.Y,
- ctx->Viewport.Width, ctx->Viewport.Height,
- ctx->Viewport.Near, ctx->Viewport.Far,
- ctx->DrawBuffer->_DepthMaxF);
-#endif
-
- if (ctx->Driver.Viewport) {
- /* Many drivers will use this call to check for window size changes
- * and reallocate the z/stencil/accum/etc buffers if needed.
- */
- (*ctx->Driver.Viewport)( ctx, x, y, width, height );
- }
-}
-
-
-#if _HAVE_FULL_GL
-/**
- * Called by glDepthRange
- *
- * \param nearval specifies the Z buffer value which should correspond to
- * the near clip plane
- * \param farval specifies the Z buffer value which should correspond to
- * the far clip plane
- */
-void GLAPIENTRY
-_mesa_DepthRange( GLclampd nearval, GLclampd farval )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- if (MESA_VERBOSE&VERBOSE_API)
- _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval);
-
- ctx->Viewport.Near = (GLfloat) CLAMP( nearval, 0.0, 1.0 );
- ctx->Viewport.Far = (GLfloat) CLAMP( farval, 0.0, 1.0 );
- ctx->NewState |= _NEW_VIEWPORT;
-
-#if 1
- /* XXX remove this someday. Currently the DRI drivers rely on
- * the WindowMap matrix being up to date in the driver's Viewport
- * and DepthRange functions.
- */
- _math_matrix_viewport(&ctx->Viewport._WindowMap,
- ctx->Viewport.X, ctx->Viewport.Y,
- ctx->Viewport.Width, ctx->Viewport.Height,
- ctx->Viewport.Near, ctx->Viewport.Far,
- ctx->DrawBuffer->_DepthMaxF);
-#endif
-
- if (ctx->Driver.DepthRange) {
- (*ctx->Driver.DepthRange)( ctx, nearval, farval );
- }
-}
-#endif
-
/**********************************************************************/
@@ -893,41 +790,4 @@ void _mesa_init_transform( GLcontext *ctx )
}
-/**
- * Initialize the context viewport attribute group.
- *
- * \param ctx GL context.
- *
- * \todo Move this to a new file with other 'viewport' routines.
- */
-void _mesa_init_viewport( GLcontext *ctx )
-{
- GLfloat depthMax = 65535.0F; /* sorf of arbitrary */
-
- /* Viewport group */
- ctx->Viewport.X = 0;
- ctx->Viewport.Y = 0;
- ctx->Viewport.Width = 0;
- ctx->Viewport.Height = 0;
- ctx->Viewport.Near = 0.0;
- ctx->Viewport.Far = 1.0;
- _math_matrix_ctr(&ctx->Viewport._WindowMap);
-
- _math_matrix_viewport(&ctx->Viewport._WindowMap, 0, 0, 0, 0,
- 0.0F, 1.0F, depthMax);
-}
-
-
-/**
- * Free the context viewport attribute group data.
- *
- * \param ctx GL context.
- *
- * \todo Move this to a new file with other 'viewport' routines.
- */
-void _mesa_free_viewport_data( GLcontext *ctx )
-{
- _math_matrix_dtr(&ctx->Viewport._WindowMap);
-}
-
/*@}*/
diff --git a/src/mesa/main/matrix.h b/src/mesa/main/matrix.h
index 38769867a7..a53d1045c7 100644
--- a/src/mesa/main/matrix.h
+++ b/src/mesa/main/matrix.h
@@ -1,13 +1,9 @@
-/**
- * \file matrix.h
- * Matrix operations.
- */
-
/*
* Mesa 3-D graphics library
- * Version: 3.5
+ * Version: 7.5
*
- * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -99,15 +95,6 @@ _mesa_MultTransposeMatrixfARB( const GLfloat *m );
extern void GLAPIENTRY
_mesa_MultTransposeMatrixdARB( const GLdouble *m );
-extern void GLAPIENTRY
-_mesa_Viewport( GLint x, GLint y, GLsizei width, GLsizei height );
-
-extern void
-_mesa_set_viewport( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height );
-
-extern void GLAPIENTRY
-_mesa_DepthRange( GLclampd nearval, GLclampd farval );
-
extern void
_mesa_init_matrix( GLcontext * ctx );
@@ -115,16 +102,10 @@ _mesa_init_matrix( GLcontext * ctx );
extern void
_mesa_init_transform( GLcontext *ctx );
-extern void
-_mesa_init_viewport( GLcontext *ctx );
-
extern void
_mesa_free_matrix_data( GLcontext *ctx );
extern void
-_mesa_free_viewport_data( GLcontext *ctx );
-
-extern void
_mesa_update_modelview_project( GLcontext *ctx, GLuint newstate );
diff --git a/src/mesa/main/mfeatures.h b/src/mesa/main/mfeatures.h
index 3819da3d68..02083ecc3b 100644
--- a/src/mesa/main/mfeatures.h
+++ b/src/mesa/main/mfeatures.h
@@ -31,35 +31,73 @@
#ifndef FEATURES_H
#define FEATURES_H
+#include "compiler.h"
#ifndef _HAVE_FULL_GL
#define _HAVE_FULL_GL 1
#endif
+/* assert that a feature is disabled and should never be used */
+#define ASSERT_NO_FEATURE() ASSERT(0)
+
+/**
+ * A feature can be anything. But most of them share certain characteristics.
+ *
+ * When a feature defines driver entries, they can be initialized by
+ * _MESA_INIT_<FEATURE>_FUNCTIONS
+ *
+ * When a feature defines vtxfmt entries, they can be initialized and
+ * installed by
+ * _MESA_INIT_<FEATURE>_VTXFMT
+ * _mesa_install_<feature>_vtxfmt
+ *
+ * When a feature defines dispatch entries, they are initialized by
+ * _mesa_init_<feature>_dispatch
+ *
+ * When a feature has states, they are initialized and freed by
+ * _mesa_init_<feature>
+ * _mesa_free_<feature>_data
+ *
+ * Except for states, the others compile to no-op when a feature is disabled.
+ *
+ * The GLAPIENTRYs and helper functions defined by a feature should also
+ * compile to no-op when it is disabled. But to save typings and to catch
+ * bugs, some of them may be unavailable, or compile to ASSERT_NO_FEATURE()
+ * when the feature is disabled.
+ *
+ * A feature following the convensions may be used without knowing if it is
+ * enabled or not.
+ */
+
#define FEATURE_accum _HAVE_FULL_GL
+#define FEATURE_arrayelt _HAVE_FULL_GL
#define FEATURE_attrib_stack _HAVE_FULL_GL
#define FEATURE_colortable _HAVE_FULL_GL
#define FEATURE_convolve _HAVE_FULL_GL
#define FEATURE_dispatch _HAVE_FULL_GL
-#define FEATURE_dlist _HAVE_FULL_GL
+#define FEATURE_dlist (_HAVE_FULL_GL && FEATURE_arrayelt && FEATURE_beginend)
#define FEATURE_draw_read_buffer _HAVE_FULL_GL
#define FEATURE_drawpix _HAVE_FULL_GL
-#define FEATURE_evaluators _HAVE_FULL_GL
+#define FEATURE_eval _HAVE_FULL_GL
#define FEATURE_feedback _HAVE_FULL_GL
#define FEATURE_fixedpt 0
#define FEATURE_histogram _HAVE_FULL_GL
#define FEATURE_pixel_transfer _HAVE_FULL_GL
#define FEATURE_point_size_array 0
+#define FEATURE_queryobj _HAVE_FULL_GL
+#define FEATURE_rastpos _HAVE_FULL_GL
#define FEATURE_texgen _HAVE_FULL_GL
#define FEATURE_texture_fxt1 _HAVE_FULL_GL
#define FEATURE_texture_s3tc _HAVE_FULL_GL
#define FEATURE_userclip _HAVE_FULL_GL
+#define FEATURE_beginend _HAVE_FULL_GL
#define FEATURE_vertex_array_byte 0
-#define FEATURE_windowpos _HAVE_FULL_GL
#define FEATURE_es2_glsl 0
-#define FEATURE_ARB_occlusion_query _HAVE_FULL_GL
#define FEATURE_ARB_fragment_program _HAVE_FULL_GL
+#define FEATURE_ARB_framebuffer_object _HAVE_FULL_GL
+#define FEATURE_ARB_map_buffer_range _HAVE_FULL_GL
+#define FEATURE_ARB_pixel_buffer_object _HAVE_FULL_GL
#define FEATURE_ARB_vertex_buffer_object _HAVE_FULL_GL
#define FEATURE_ARB_vertex_program _HAVE_FULL_GL
#define FEATURE_ARB_vertex_shader _HAVE_FULL_GL
@@ -67,14 +105,13 @@
#define FEATURE_ARB_shader_objects (FEATURE_ARB_vertex_shader || FEATURE_ARB_fragment_shader)
#define FEATURE_ARB_shading_language_100 FEATURE_ARB_shader_objects
#define FEATURE_ARB_shading_language_120 FEATURE_ARB_shader_objects
+#define FEATURE_ARB_sync _HAVE_FULL_GL
#define FEATURE_EXT_framebuffer_blit _HAVE_FULL_GL
#define FEATURE_EXT_framebuffer_object _HAVE_FULL_GL
#define FEATURE_EXT_pixel_buffer_object _HAVE_FULL_GL
#define FEATURE_EXT_texture_sRGB _HAVE_FULL_GL
-#define FEATURE_EXT_timer_query _HAVE_FULL_GL
#define FEATURE_ATI_fragment_shader _HAVE_FULL_GL
-#define FEATURE_MESA_program_debug _HAVE_FULL_GL
#define FEATURE_NV_fence _HAVE_FULL_GL
#define FEATURE_NV_fragment_program _HAVE_FULL_GL
#define FEATURE_NV_vertex_program _HAVE_FULL_GL
diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
index 3dd4b3391b..3dca09d9f2 100644
--- a/src/mesa/main/mipmap.c
+++ b/src/mesa/main/mipmap.c
@@ -85,7 +85,22 @@ bytes_per_pixel(GLenum datatype, GLuint comps)
rowC[j][e], rowC[k][e], \
rowD[j][e], rowD[k][e]); \
} while(0)
-
+
+#define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
+ (Aj + Ak \
+ + Bj + Bk \
+ + Cj + Ck \
+ + Dj + Dk \
+ + 4) / 8
+
+#define FILTER_3D_SIGNED(e) \
+ do { \
+ dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \
+ rowB[j][e], rowB[k][e], \
+ rowC[j][e], rowC[k][e], \
+ rowD[j][e], rowD[k][e]); \
+ } while(0)
+
#define FILTER_F_3D(e) \
do { \
dst[i][e] = (rowA[j][e] + rowA[k][e] \
@@ -180,6 +195,53 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
}
}
+ else if (datatype == GL_BYTE && comps == 4) {
+ GLuint i, j, k;
+ const GLbyte(*rowA)[4] = (const GLbyte(*)[4]) srcRowA;
+ const GLbyte(*rowB)[4] = (const GLbyte(*)[4]) srcRowB;
+ GLbyte(*dst)[4] = (GLbyte(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
+ }
+ }
+ else if (datatype == GL_BYTE && comps == 3) {
+ GLuint i, j, k;
+ const GLbyte(*rowA)[3] = (const GLbyte(*)[3]) srcRowA;
+ const GLbyte(*rowB)[3] = (const GLbyte(*)[3]) srcRowB;
+ GLbyte(*dst)[3] = (GLbyte(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ }
+ }
+ else if (datatype == GL_BYTE && comps == 2) {
+ GLuint i, j, k;
+ const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA;
+ const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB;
+ GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ }
+ }
+ else if (datatype == GL_BYTE && comps == 1) {
+ GLuint i, j, k;
+ const GLbyte *rowA = (const GLbyte *) srcRowA;
+ const GLbyte *rowB = (const GLbyte *) srcRowB;
+ GLbyte *dst = (GLbyte *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
+ }
+ }
+
else if (datatype == GL_UNSIGNED_SHORT && comps == 4) {
GLuint i, j, k;
const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA;
@@ -226,7 +288,6 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
}
}
-
else if (datatype == GL_FLOAT && comps == 4) {
GLuint i, j, k;
const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA;
@@ -545,6 +606,44 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
FILTER_3D(0);
}
}
+ if ((datatype == GL_BYTE) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(GLbyte, 4);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D_SIGNED(0);
+ FILTER_3D_SIGNED(1);
+ FILTER_3D_SIGNED(2);
+ FILTER_3D_SIGNED(3);
+ }
+ }
+ else if ((datatype == GL_BYTE) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(GLbyte, 3);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D_SIGNED(0);
+ FILTER_3D_SIGNED(1);
+ FILTER_3D_SIGNED(2);
+ }
+ }
+ else if ((datatype == GL_BYTE) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(GLbyte, 2);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D_SIGNED(0);
+ FILTER_3D_SIGNED(1);
+ }
+ }
+ else if ((datatype == GL_BYTE) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(GLbyte, 1);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D_SIGNED(0);
+ }
+ }
else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) {
DECLARE_ROW_POINTERS(GLushort, 4);
@@ -1176,7 +1275,7 @@ make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
/**
- * \bugs
+ * \bug
* There is quite a bit of refactoring that could be done with this function
* and \c make_2d_mipmap.
*/
@@ -1271,6 +1370,9 @@ make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
/**
* Down-sample a texture image to produce the next lower mipmap level.
+ * \param comps components per texel (1, 2, 3 or 4)
+ * \param srcRowStride stride between source rows, in texels
+ * \param dstRowStride stride between destination rows, in texels
*/
void
_mesa_generate_mipmap_level(GLenum target,
@@ -1379,9 +1481,12 @@ next_mipmap_level_size(GLenum target, GLint border,
/**
- * For GL_SGIX_generate_mipmap:
- * Generate a complete set of mipmaps from texObj's base-level image.
+ * Automatic mipmap generation.
+ * This is the fallback/default function for ctx->Driver.GenerateMipmap().
+ * Generate a complete set of mipmaps from texObj's BaseLevel image.
* Stop at texObj's MaxLevel or when we get to the 1x1 texture.
+ * For cube maps, target will be one of
+ * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
*/
void
_mesa_generate_mipmap(GLcontext *ctx, GLenum target,
@@ -1496,9 +1601,6 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
return;
}
- if (dstImage->ImageOffsets)
- _mesa_free(dstImage->ImageOffsets);
-
/* Free old image data */
if (dstImage->Data)
ctx->Driver.FreeTexImageData(ctx, dstImage);
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 2014745a7a..6ce9ae1d6a 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1,9 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.3
+ * Version: 7.5
*
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
- * Copyright (C) 1999-2008 VMware, Inc. All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -30,22 +30,17 @@
* Please try to mark derived values with a leading underscore ('_').
*/
-#ifndef TYPES_H
-#define TYPES_H
+#ifndef MTYPES_H
+#define MTYPES_H
-#include "glheader.h"
-#include <GL/internal/glcore.h> /* __GLcontextModes (GLvisual) */
-#include "config.h" /* Hardwired parameters */
+#include "main/glheader.h"
+#include "main/config.h"
+#include "main/compiler.h"
+#include "main/mfeatures.h"
#include "glapi/glapi.h"
#include "math/m_matrix.h" /* GLmatrix */
-#include "bitset.h"
-
-
-/**
- * Special, internal token
- */
-#define GL_SHADER_PROGRAM_MESA 0x9999
+#include "main/simple_list.h" /* struct simple_node */
/**
@@ -84,47 +79,18 @@
/**
- * Fixed point data type.
- */
-typedef int GLfixed;
-/*
- * Fixed point arithmetic macros
- */
-#ifndef FIXED_FRAC_BITS
-#define FIXED_FRAC_BITS 11
-#endif
-
-#define FIXED_SHIFT FIXED_FRAC_BITS
-#define FIXED_ONE (1 << FIXED_SHIFT)
-#define FIXED_HALF (1 << (FIXED_SHIFT-1))
-#define FIXED_FRAC_MASK (FIXED_ONE - 1)
-#define FIXED_INT_MASK (~FIXED_FRAC_MASK)
-#define FIXED_EPSILON 1
-#define FIXED_SCALE ((float) FIXED_ONE)
-#define FIXED_DBL_SCALE ((double) FIXED_ONE)
-#define FloatToFixed(X) (IROUND((X) * FIXED_SCALE))
-#define FixedToDouble(X) ((X) * (1.0 / FIXED_DBL_SCALE))
-#define IntToFixed(I) ((I) << FIXED_SHIFT)
-#define FixedToInt(X) ((X) >> FIXED_SHIFT)
-#define FixedToUns(X) (((unsigned int)(X)) >> FIXED_SHIFT)
-#define FixedCeil(X) (((X) + FIXED_ONE - FIXED_EPSILON) & FIXED_INT_MASK)
-#define FixedFloor(X) ((X) & FIXED_INT_MASK)
-#define FixedToFloat(X) ((X) * (1.0F / FIXED_SCALE))
-#define PosFloatToFixed(X) FloatToFixed(X)
-#define SignedFloatToFixed(X) FloatToFixed(X)
-
-
-
-/**
* \name Some forward type declarations
*/
/*@{*/
struct _mesa_HashTable;
+struct gl_attrib_node;
+struct gl_meta_state;
struct gl_pixelstore_attrib;
struct gl_program_cache;
struct gl_texture_format;
struct gl_texture_image;
struct gl_texture_object;
+struct st_context;
typedef struct __GLcontextRec GLcontext;
typedef struct __GLcontextModesRec GLvisual;
typedef struct gl_framebuffer GLframebuffer;
@@ -139,7 +105,7 @@ typedef struct gl_framebuffer GLframebuffer;
* In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
* generic attributes are distinct/separate).
*/
-enum
+typedef enum
{
VERT_ATTRIB_POS = 0,
VERT_ATTRIB_WEIGHT = 1,
@@ -175,7 +141,7 @@ enum
VERT_ATTRIB_GENERIC14 = 30,
VERT_ATTRIB_GENERIC15 = 31,
VERT_ATTRIB_MAX = 32
-};
+} gl_vert_attrib;
/**
* Bitflags for vertex attributes.
@@ -223,32 +189,33 @@ enum
/**
* Indexes for vertex program result attributes
*/
-/*@{*/
-#define VERT_RESULT_HPOS 0
-#define VERT_RESULT_COL0 1
-#define VERT_RESULT_COL1 2
-#define VERT_RESULT_FOGC 3
-#define VERT_RESULT_TEX0 4
-#define VERT_RESULT_TEX1 5
-#define VERT_RESULT_TEX2 6
-#define VERT_RESULT_TEX3 7
-#define VERT_RESULT_TEX4 8
-#define VERT_RESULT_TEX5 9
-#define VERT_RESULT_TEX6 10
-#define VERT_RESULT_TEX7 11
-#define VERT_RESULT_PSIZ 12
-#define VERT_RESULT_BFC0 13
-#define VERT_RESULT_BFC1 14
-#define VERT_RESULT_EDGE 15
-#define VERT_RESULT_VAR0 16 /**< shader varying */
-#define VERT_RESULT_MAX (VERT_RESULT_VAR0 + MAX_VARYING)
-/*@}*/
+typedef enum
+{
+ VERT_RESULT_HPOS = 0,
+ VERT_RESULT_COL0 = 1,
+ VERT_RESULT_COL1 = 2,
+ VERT_RESULT_FOGC = 3,
+ VERT_RESULT_TEX0 = 4,
+ VERT_RESULT_TEX1 = 5,
+ VERT_RESULT_TEX2 = 6,
+ VERT_RESULT_TEX3 = 7,
+ VERT_RESULT_TEX4 = 8,
+ VERT_RESULT_TEX5 = 9,
+ VERT_RESULT_TEX6 = 10,
+ VERT_RESULT_TEX7 = 11,
+ VERT_RESULT_PSIZ = 12,
+ VERT_RESULT_BFC0 = 13,
+ VERT_RESULT_BFC1 = 14,
+ VERT_RESULT_EDGE = 15,
+ VERT_RESULT_VAR0 = 16 /**< shader varying */,
+ VERT_RESULT_MAX = (VERT_RESULT_VAR0 + MAX_VARYING)
+} gl_vert_result;
/**
* Indexes for fragment program input attributes.
*/
-enum
+typedef enum
{
FRAG_ATTRIB_WPOS = 0,
FRAG_ATTRIB_COL0 = 1,
@@ -262,9 +229,11 @@ enum
FRAG_ATTRIB_TEX5 = 9,
FRAG_ATTRIB_TEX6 = 10,
FRAG_ATTRIB_TEX7 = 11,
- FRAG_ATTRIB_VAR0 = 12, /**< shader varying */
+ FRAG_ATTRIB_FACE = 12, /**< front/back face */
+ FRAG_ATTRIB_PNTC = 13, /**< sprite/point coord */
+ FRAG_ATTRIB_VAR0 = 14, /**< shader varying */
FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING)
-};
+} gl_frag_attrib;
/**
* Bitflags for fragment program input attributes.
@@ -274,6 +243,8 @@ enum
#define FRAG_BIT_COL0 (1 << FRAG_ATTRIB_COL0)
#define FRAG_BIT_COL1 (1 << FRAG_ATTRIB_COL1)
#define FRAG_BIT_FOGC (1 << FRAG_ATTRIB_FOGC)
+#define FRAG_BIT_FACE (1 << FRAG_ATTRIB_FACE)
+#define FRAG_BIT_PNTC (1 << FRAG_ATTRIB_PNTC)
#define FRAG_BIT_TEX0 (1 << FRAG_ATTRIB_TEX0)
#define FRAG_BIT_TEX1 (1 << FRAG_ATTRIB_TEX1)
#define FRAG_BIT_TEX2 (1 << FRAG_ATTRIB_TEX2)
@@ -301,41 +272,41 @@ enum
/**
* Fragment program results
*/
-enum
+typedef enum
{
- FRAG_RESULT_COLR = 0,
- FRAG_RESULT_COLH = 1,
- FRAG_RESULT_DEPR = 2,
- FRAG_RESULT_DATA0 = 3,
+ FRAG_RESULT_DEPTH = 0,
+ FRAG_RESULT_COLOR = 1,
+ FRAG_RESULT_DATA0 = 2,
FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
-};
+} gl_frag_result;
/**
* Indexes for all renderbuffers
*/
-enum {
- BUFFER_FRONT_LEFT = 0, /* the four standard color buffers */
- BUFFER_BACK_LEFT = 1,
- BUFFER_FRONT_RIGHT = 2,
- BUFFER_BACK_RIGHT = 3,
- BUFFER_AUX0 = 4, /* optional aux buffer */
- BUFFER_AUX1 = 5,
- BUFFER_AUX2 = 6,
- BUFFER_AUX3 = 7,
- BUFFER_DEPTH = 8,
- BUFFER_STENCIL = 9,
- BUFFER_ACCUM = 10,
- BUFFER_COLOR0 = 11, /* generic renderbuffers */
- BUFFER_COLOR1 = 12,
- BUFFER_COLOR2 = 13,
- BUFFER_COLOR3 = 14,
- BUFFER_COLOR4 = 15,
- BUFFER_COLOR5 = 16,
- BUFFER_COLOR6 = 17,
- BUFFER_COLOR7 = 18,
- BUFFER_COUNT = 19
-};
+typedef enum
+{
+ /* the four standard color buffers */
+ BUFFER_FRONT_LEFT,
+ BUFFER_BACK_LEFT,
+ BUFFER_FRONT_RIGHT,
+ BUFFER_BACK_RIGHT,
+ BUFFER_DEPTH,
+ BUFFER_STENCIL,
+ BUFFER_ACCUM,
+ /* optional aux buffer */
+ BUFFER_AUX0,
+ /* generic renderbuffers */
+ BUFFER_COLOR0,
+ BUFFER_COLOR1,
+ BUFFER_COLOR2,
+ BUFFER_COLOR3,
+ BUFFER_COLOR4,
+ BUFFER_COLOR5,
+ BUFFER_COLOR6,
+ BUFFER_COLOR7,
+ BUFFER_COUNT
+} gl_buffer_index;
/**
* Bit flags for all renderbuffers
@@ -368,9 +339,6 @@ enum {
BUFFER_BIT_FRONT_RIGHT | \
BUFFER_BIT_BACK_RIGHT | \
BUFFER_BIT_AUX0 | \
- BUFFER_BIT_AUX1 | \
- BUFFER_BIT_AUX2 | \
- BUFFER_BIT_AUX3 | \
BUFFER_BIT_COLOR0 | \
BUFFER_BIT_COLOR1 | \
BUFFER_BIT_COLOR2 | \
@@ -382,12 +350,13 @@ enum {
/** The pixel transfer path has three color tables: */
-/*@{*/
-#define COLORTABLE_PRECONVOLUTION 0
-#define COLORTABLE_POSTCONVOLUTION 1
-#define COLORTABLE_POSTCOLORMATRIX 2
-#define COLORTABLE_MAX 3
-/*@}*/
+typedef enum
+{
+ COLORTABLE_PRECONVOLUTION,
+ COLORTABLE_POSTCONVOLUTION,
+ COLORTABLE_POSTCOLORMATRIX,
+ COLORTABLE_MAX
+} gl_colortable_index;
/**
@@ -497,7 +466,7 @@ struct gl_light
GLfloat Diffuse[4]; /**< diffuse color */
GLfloat Specular[4]; /**< specular color */
GLfloat EyePosition[4]; /**< position in eye coordinates */
- GLfloat EyeDirection[4]; /**< spotlight dir in eye coordinates */
+ GLfloat SpotDirection[4]; /**< spotlight direction in eye coordinates */
GLfloat SpotExponent;
GLfloat SpotCutoff; /**< in degrees */
GLfloat _CosCutoffNeg; /**< = cos(SpotCutoff) */
@@ -516,7 +485,7 @@ struct gl_light
GLfloat _Position[4]; /**< position in eye/obj coordinates */
GLfloat _VP_inf_norm[3]; /**< Norm direction to infinite light */
GLfloat _h_inf_norm[3]; /**< Norm( _VP_inf_norm + <0,0,1> ) */
- GLfloat _NormDirection[4]; /**< normalized spotlight direction */
+ GLfloat _NormSpotDirection[4]; /**< normalized spotlight direction */
GLfloat _VP_inf_spot_attenuation;
GLfloat _SpotExpTable[EXP_TABLE_SIZE][2]; /**< to replace a pow() call */
@@ -624,9 +593,7 @@ struct gl_current_attrib
* \note Index and Edgeflag current values are stored as floats in the
* SIX and SEVEN attribute slots.
*/
- /*@{*/
GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */
- /*@}*/
/**
* \name Current raster position attributes (always valid).
@@ -659,84 +626,6 @@ struct gl_depthbuffer_attrib
/**
- * glEnable()/glDisable() attribute group (GL_ENABLE_BIT).
- */
-struct gl_enable_attrib
-{
- GLboolean AlphaTest;
- GLboolean AutoNormal;
- GLboolean Blend;
- GLbitfield ClipPlanes;
- GLboolean ColorMaterial;
- GLboolean ColorTable[COLORTABLE_MAX];
- GLboolean Convolution1D;
- GLboolean Convolution2D;
- GLboolean Separable2D;
- GLboolean CullFace;
- GLboolean DepthTest;
- GLboolean Dither;
- GLboolean Fog;
- GLboolean Histogram;
- GLboolean Light[MAX_LIGHTS];
- GLboolean Lighting;
- GLboolean LineSmooth;
- GLboolean LineStipple;
- GLboolean IndexLogicOp;
- GLboolean ColorLogicOp;
- GLboolean Map1Color4;
- GLboolean Map1Index;
- GLboolean Map1Normal;
- GLboolean Map1TextureCoord1;
- GLboolean Map1TextureCoord2;
- GLboolean Map1TextureCoord3;
- GLboolean Map1TextureCoord4;
- GLboolean Map1Vertex3;
- GLboolean Map1Vertex4;
- GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
- GLboolean Map2Color4;
- GLboolean Map2Index;
- GLboolean Map2Normal;
- GLboolean Map2TextureCoord1;
- GLboolean Map2TextureCoord2;
- GLboolean Map2TextureCoord3;
- GLboolean Map2TextureCoord4;
- GLboolean Map2Vertex3;
- GLboolean Map2Vertex4;
- GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
- GLboolean MinMax;
- GLboolean Normalize;
- GLboolean PixelTexture;
- GLboolean PointSmooth;
- GLboolean PolygonOffsetPoint;
- GLboolean PolygonOffsetLine;
- GLboolean PolygonOffsetFill;
- GLboolean PolygonSmooth;
- GLboolean PolygonStipple;
- GLboolean RescaleNormals;
- GLboolean Scissor;
- GLboolean Stencil;
- GLboolean StencilTwoSide; /* GL_EXT_stencil_two_side */
- GLboolean MultisampleEnabled; /* GL_ARB_multisample */
- GLboolean SampleAlphaToCoverage; /* GL_ARB_multisample */
- GLboolean SampleAlphaToOne; /* GL_ARB_multisample */
- GLboolean SampleCoverage; /* GL_ARB_multisample */
- GLboolean SampleCoverageInvert; /* GL_ARB_multisample */
- GLboolean RasterPositionUnclipped; /* GL_IBM_rasterpos_clip */
- GLuint Texture[MAX_TEXTURE_UNITS];
- GLuint TexGen[MAX_TEXTURE_UNITS];
- /* SGI_texture_color_table */
- GLboolean TextureColorTable[MAX_TEXTURE_UNITS];
- /* GL_ARB_vertex_program / GL_NV_vertex_program */
- GLboolean VertexProgram;
- GLboolean VertexProgramPointSize;
- GLboolean VertexProgramTwoSide;
- /* GL_ARB_point_sprite / GL_NV_point_sprite */
- GLboolean PointSprite;
- GLboolean FragmentShaderATI;
-};
-
-
-/**
* Evaluator attribute group (GL_EVAL_BIT).
*/
struct gl_eval_attrib
@@ -823,11 +712,11 @@ struct gl_hint_attrib
*/
struct gl_histogram_attrib
{
- GLuint Width; /**< number of table entries */
- GLint Format; /**< GL_ALPHA, GL_RGB, etc */
- GLuint Count[HISTOGRAM_TABLE_SIZE][4]; /**< the histogram */
- GLboolean Sink; /**< terminate image transfer? */
- GLubyte RedSize; /**< Bits per counter */
+ GLuint Width; /**< number of table entries */
+ GLint Format; /**< GL_ALPHA, GL_RGB, etc */
+ GLuint Count[HISTOGRAM_TABLE_SIZE][4]; /**< the histogram */
+ GLboolean Sink; /**< terminate image transfer? */
+ GLubyte RedSize; /**< Bits per counter */
GLubyte GreenSize;
GLubyte BlueSize;
GLubyte AlphaSize;
@@ -887,6 +776,7 @@ struct gl_light_attrib
GLboolean Enabled; /**< Lighting enabled flag */
GLenum ShadeModel; /**< GL_FLAT or GL_SMOOTH */
+ GLenum ProvokingVertex; /**< GL_EXT_provoking_vertex */
GLenum ColorMaterialFace; /**< GL_FRONT, BACK or FRONT_AND_BACK */
GLenum ColorMaterialMode; /**< GL_AMBIENT, GL_DIFFUSE, etc */
GLbitfield ColorMaterialBitmask; /**< bitmask formed from Face and Mode */
@@ -901,7 +791,7 @@ struct gl_light_attrib
/*@{*/
GLboolean _NeedEyeCoords;
GLboolean _NeedVertices; /**< Use fast shader? */
- GLbitfield _Flags; /**< LIGHT_* flags, see above */
+ GLbitfield _Flags; /**< LIGHT_* flags, see above */
GLfloat _BaseColor[2][3];
/*@}*/
};
@@ -1006,13 +896,15 @@ struct gl_pixel_attrib
/*--- Begin Pixel Transfer State ---*/
/* Fields are in the order in which they're applied... */
- /* Scale & Bias (index shift, offset) */
+ /** Scale & Bias (index shift, offset) */
+ /*@{*/
GLfloat RedBias, RedScale;
GLfloat GreenBias, GreenScale;
GLfloat BlueBias, BlueScale;
GLfloat AlphaBias, AlphaScale;
GLfloat DepthBias, DepthScale;
GLint IndexShift, IndexOffset;
+ /*@}*/
/* Pixel Maps */
/* Note: actual pixel maps are not part of this attrib group */
@@ -1028,7 +920,7 @@ struct gl_pixel_attrib
GLboolean Convolution1DEnabled;
GLboolean Convolution2DEnabled;
GLboolean Separable2DEnabled;
- GLfloat ConvolutionBorderColor[3][4];
+ GLfloat ConvolutionBorderColor[3][4]; /**< RGBA */
GLenum ConvolutionBorderMode[3];
GLfloat ConvolutionFilterScale[3][4]; /**< RGBA */
GLfloat ConvolutionFilterBias[3][4]; /**< RGBA */
@@ -1047,12 +939,12 @@ struct gl_pixel_attrib
/*--- End Pixel Transfer State ---*/
- /* Pixel Zoom */
+ /** glPixelZoom */
GLfloat ZoomX, ZoomY;
/** GL_SGI_texture_color_table */
- GLfloat TextureColorTableScale[4];
- GLfloat TextureColorTableBias[4];
+ GLfloat TextureColorTableScale[4]; /**< RGBA */
+ GLfloat TextureColorTableBias[4]; /**< RGBA */
};
@@ -1108,51 +1000,69 @@ struct gl_scissor_attrib
/**
* Stencil attribute group (GL_STENCIL_BUFFER_BIT).
+ *
+ * Three sets of stencil data are tracked so that OpenGL 2.0,
+ * GL_EXT_stencil_two_side, and GL_ATI_separate_stencil can all be supported
+ * simultaneously. In each of the stencil state arrays, element 0 corresponds
+ * to GL_FRONT. Element 1 corresponds to the OpenGL 2.0 /
+ * GL_ATI_separate_stencil GL_BACK state. Element 2 corresponds to the
+ * GL_EXT_stencil_two_side GL_BACK state.
+ *
+ * The derived value \c _BackFace is either 1 or 2 depending on whether or
+ * not GL_STENCIL_TEST_TWO_SIDE_EXT is enabled.
+ *
+ * The derived value \c _TestTwoSide is set when the front-face and back-face
+ * stencil state are different.
*/
struct gl_stencil_attrib
{
GLboolean Enabled; /**< Enabled flag */
GLboolean TestTwoSide; /**< GL_EXT_stencil_two_side */
- GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 1) */
+ GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 2) */
+ GLboolean _Enabled; /**< Enabled and stencil buffer present */
GLboolean _TestTwoSide;
- GLenum Function[2]; /**< Stencil function */
- GLenum FailFunc[2]; /**< Fail function */
- GLenum ZPassFunc[2]; /**< Depth buffer pass function */
- GLenum ZFailFunc[2]; /**< Depth buffer fail function */
- GLint Ref[2]; /**< Reference value */
- GLuint ValueMask[2]; /**< Value mask */
- GLuint WriteMask[2]; /**< Write mask */
+ GLubyte _BackFace; /**< Current back stencil state (1 or 2) */
+ GLenum Function[3]; /**< Stencil function */
+ GLenum FailFunc[3]; /**< Fail function */
+ GLenum ZPassFunc[3]; /**< Depth buffer pass function */
+ GLenum ZFailFunc[3]; /**< Depth buffer fail function */
+ GLint Ref[3]; /**< Reference value */
+ GLuint ValueMask[3]; /**< Value mask */
+ GLuint WriteMask[3]; /**< Write mask */
GLuint Clear; /**< Clear value */
};
-#define NUM_TEXTURE_TARGETS 7 /* 1D, 2D, 3D, CUBE, RECT, 1D_STACK, and 2D_STACK */
-
/**
- * An index for each type of texture object
+ * An index for each type of texture object. These correspond to the GL
+ * texture target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc.
+ * Note: the order is from highest priority to lowest priority.
*/
-/*@{*/
-#define TEXTURE_1D_INDEX 0
-#define TEXTURE_2D_INDEX 1
-#define TEXTURE_3D_INDEX 2
-#define TEXTURE_CUBE_INDEX 3
-#define TEXTURE_RECT_INDEX 4
-#define TEXTURE_1D_ARRAY_INDEX 5
-#define TEXTURE_2D_ARRAY_INDEX 6
-/*@}*/
+typedef enum
+{
+ TEXTURE_2D_ARRAY_INDEX,
+ TEXTURE_1D_ARRAY_INDEX,
+ TEXTURE_CUBE_INDEX,
+ TEXTURE_3D_INDEX,
+ TEXTURE_RECT_INDEX,
+ TEXTURE_2D_INDEX,
+ TEXTURE_1D_INDEX,
+ NUM_TEXTURE_TARGETS
+} gl_texture_index;
+
/**
* Bit flags for each type of texture object
* Used for Texture.Unit[]._ReallyEnabled flags.
*/
/*@{*/
-#define TEXTURE_1D_BIT (1 << TEXTURE_1D_INDEX)
-#define TEXTURE_2D_BIT (1 << TEXTURE_2D_INDEX)
-#define TEXTURE_3D_BIT (1 << TEXTURE_3D_INDEX)
+#define TEXTURE_2D_ARRAY_BIT (1 << TEXTURE_2D_ARRAY_INDEX)
+#define TEXTURE_1D_ARRAY_BIT (1 << TEXTURE_1D_ARRAY_INDEX)
#define TEXTURE_CUBE_BIT (1 << TEXTURE_CUBE_INDEX)
+#define TEXTURE_3D_BIT (1 << TEXTURE_3D_INDEX)
#define TEXTURE_RECT_BIT (1 << TEXTURE_RECT_INDEX)
-#define TEXTURE_1D_ARRAY_BIT (1 << TEXTURE_1D_ARRAY_INDEX)
-#define TEXTURE_2D_ARRAY_BIT (1 << TEXTURE_2D_ARRAY_INDEX)
+#define TEXTURE_2D_BIT (1 << TEXTURE_2D_INDEX)
+#define TEXTURE_1D_BIT (1 << TEXTURE_1D_INDEX)
/*@}*/
@@ -1187,27 +1097,12 @@ struct gl_stencil_attrib
/*@}*/
-/* A selection of state flags to make driver and module's lives easier. */
-#define ENABLE_TEXGEN0 0x1
-#define ENABLE_TEXGEN1 0x2
-#define ENABLE_TEXGEN2 0x4
-#define ENABLE_TEXGEN3 0x8
-#define ENABLE_TEXGEN4 0x10
-#define ENABLE_TEXGEN5 0x20
-#define ENABLE_TEXGEN6 0x40
-#define ENABLE_TEXGEN7 0x80
-#define ENABLE_TEXMAT0 0x1 /* Ie. not the identity matrix */
-#define ENABLE_TEXMAT1 0x2
-#define ENABLE_TEXMAT2 0x4
-#define ENABLE_TEXMAT3 0x8
-#define ENABLE_TEXMAT4 0x10
-#define ENABLE_TEXMAT5 0x20
-#define ENABLE_TEXMAT6 0x40
-#define ENABLE_TEXMAT7 0x80
+/** Tex-gen enabled for texture unit? */
+#define ENABLE_TEXGEN(unit) (1 << (unit))
-#define ENABLE_TEXGEN(i) (ENABLE_TEXGEN0 << (i))
-#define ENABLE_TEXMAT(i) (ENABLE_TEXMAT0 << (i))
+/** Non-identity texture matrix for texture unit? */
+#define ENABLE_TEXMAT(unit) (1 << (unit))
/**
@@ -1383,15 +1278,16 @@ struct gl_texture_image
/**
* Indexes for cube map faces.
*/
-/*@{*/
-#define FACE_POS_X 0
-#define FACE_NEG_X 1
-#define FACE_POS_Y 2
-#define FACE_NEG_Y 3
-#define FACE_POS_Z 4
-#define FACE_NEG_Z 5
-#define MAX_FACES 6
-/*@}*/
+typedef enum
+{
+ FACE_POS_X = 0,
+ FACE_NEG_X = 1,
+ FACE_POS_Y = 2,
+ FACE_NEG_Y = 3,
+ FACE_POS_Z = 4,
+ FACE_NEG_Z = 5,
+ MAX_FACES = 6
+} gl_face_index;
/**
@@ -1407,7 +1303,6 @@ struct gl_texture_object
GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
GLfloat Priority; /**< in [0,1] */
GLfloat BorderColor[4]; /**< unclamped */
- GLchan _BorderChan[4]; /**< clamped, as GLchan */
GLenum WrapS; /**< S-axis texture image wrap mode */
GLenum WrapT; /**< T-axis texture image wrap mode */
GLenum WrapR; /**< R-axis texture image wrap mode */
@@ -1419,21 +1314,18 @@ struct gl_texture_object
GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */
GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */
GLfloat MaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
- GLboolean CompareFlag; /**< GL_SGIX_shadow */
- GLenum CompareOperator; /**< GL_SGIX_shadow */
- GLfloat ShadowAmbient; /**< GL_ARB_shadow_ambient */
GLenum CompareMode; /**< GL_ARB_shadow */
GLenum CompareFunc; /**< GL_ARB_shadow */
- GLenum _Function; /**< Comparison function derived from
- * \c CompareOperator, \c CompareMode, and
- * \c CompareFunc.
- */
+ GLfloat CompareFailValue; /**< GL_ARB_shadow_ambient */
GLenum DepthMode; /**< GL_ARB_depth_texture */
GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */
GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - b in spec) */
GLint CropRect[4]; /**< GL_OES_draw_texture */
+ GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */
+ GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */
GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */
GLboolean _Complete; /**< Is texture object complete? */
+ GLboolean _RenderToTexture; /**< Any rendering to this texture? */
/** Actual texture images, indexed by [cube face] and [mipmap level] */
struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
@@ -1452,25 +1344,39 @@ struct gl_texture_object
};
+/** Up to four combiner sources are possible with GL_NV_texture_env_combine4 */
+#define MAX_COMBINER_TERMS 4
+
+
/**
* Texture combine environment state.
- *
- * \todo
- * If GL_NV_texture_env_combine4 is ever supported, the arrays in this
- * structure will need to be expanded for 4 elements.
*/
struct gl_tex_env_combine_state
{
GLenum ModeRGB; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
GLenum ModeA; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
- GLenum SourceRGB[3]; /**< GL_PRIMARY_COLOR, GL_TEXTURE, etc. */
- GLenum SourceA[3]; /**< GL_PRIMARY_COLOR, GL_TEXTURE, etc. */
- GLenum OperandRGB[3]; /**< SRC_COLOR, ONE_MINUS_SRC_COLOR, etc */
- GLenum OperandA[3]; /**< SRC_ALPHA, ONE_MINUS_SRC_ALPHA, etc */
+ /** Source terms: GL_PRIMARY_COLOR, GL_TEXTURE, etc */
+ GLenum SourceRGB[MAX_COMBINER_TERMS];
+ GLenum SourceA[MAX_COMBINER_TERMS];
+ /** Source operands: GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, etc */
+ GLenum OperandRGB[MAX_COMBINER_TERMS];
+ GLenum OperandA[MAX_COMBINER_TERMS];
GLuint ScaleShiftRGB; /**< 0, 1 or 2 */
GLuint ScaleShiftA; /**< 0, 1 or 2 */
- GLuint _NumArgsRGB; /**< Number of inputs used for the combine mode. */
- GLuint _NumArgsA; /**< Number of inputs used for the combine mode. */
+ GLuint _NumArgsRGB; /**< Number of inputs used for the RGB combiner */
+ GLuint _NumArgsA; /**< Number of inputs used for the A combiner */
+};
+
+
+/**
+ * Texture coord generation state.
+ */
+struct gl_texgen
+{
+ GLenum Mode; /**< GL_EYE_LINEAR, GL_SPHERE_MAP, etc */
+ GLbitfield _ModeBit; /**< TEXGEN_x bit corresponding to Mode */
+ GLfloat ObjectPlane[4];
+ GLfloat EyePlane[4];
};
@@ -1486,29 +1392,17 @@ struct gl_texture_unit
GLenum EnvMode; /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */
GLfloat EnvColor[4];
+
+ struct gl_texgen GenS;
+ struct gl_texgen GenT;
+ struct gl_texgen GenR;
+ struct gl_texgen GenQ;
GLbitfield TexGenEnabled; /**< Bitwise-OR of [STRQ]_BIT values */
- /** \name Tex coord generation mode
- * Either GL_OBJECT_LINEAR, GL_EYE_LINEAR or GL_SPHERE_MAP. */
- /*@{*/
- GLenum GenModeS;
- GLenum GenModeT;
- GLenum GenModeR;
- GLenum GenModeQ;
- /*@}*/
- GLbitfield _GenBitS;
- GLbitfield _GenBitT;
- GLbitfield _GenBitR;
- GLbitfield _GenBitQ;
- GLbitfield _GenFlags; /**< bitwise or of _GenBit[STRQ] */
- GLfloat ObjectPlaneS[4];
- GLfloat ObjectPlaneT[4];
- GLfloat ObjectPlaneR[4];
- GLfloat ObjectPlaneQ[4];
- GLfloat EyePlaneS[4];
- GLfloat EyePlaneT[4];
- GLfloat EyePlaneR[4];
- GLfloat EyePlaneQ[4];
+ GLbitfield _GenFlags; /**< Bitwise-OR of Gen[STRQ]._ModeBit */
+
GLfloat LodBias; /**< for biasing mipmap levels */
+ GLenum BumpTarget;
+ GLfloat RotMatrix[4]; /* 2x2 matrix */
/**
* \name GL_EXT_texture_env_combine
@@ -1527,15 +1421,11 @@ struct gl_texture_unit
*/
struct gl_tex_env_combine_state *_CurrentCombine;
- struct gl_texture_object *Current1D;
- struct gl_texture_object *Current2D;
- struct gl_texture_object *Current3D;
- struct gl_texture_object *CurrentCubeMap; /**< GL_ARB_texture_cube_map */
- struct gl_texture_object *CurrentRect; /**< GL_NV_texture_rectangle */
- struct gl_texture_object *Current1DArray; /**< GL_MESA_texture_array */
- struct gl_texture_object *Current2DArray; /**< GL_MESA_texture_array */
+ /** Current texture object pointers */
+ struct gl_texture_object *CurrentTex[NUM_TEXTURE_TARGETS];
- struct gl_texture_object *_Current; /**< Points to really enabled tex obj */
+ /** Points to highest priority, complete and enabled texture object */
+ struct gl_texture_object *_Current;
/** GL_SGI_texture_color_table */
/*@{*/
@@ -1546,32 +1436,37 @@ struct gl_texture_unit
};
-
/**
* Texture attribute group (GL_TEXTURE_BIT).
*/
struct gl_texture_attrib
{
- /**
- * name multitexture
- */
- /**@{*/
- GLuint CurrentUnit; /**< Active texture unit [0, MaxTextureImageUnits-1] */
- GLbitfield _EnabledUnits; /**< one bit set for each really-enabled unit */
- GLbitfield _EnabledCoordUnits; /**< one bit per enabled coordinate unit */
- GLbitfield _GenFlags; /**< for texgen */
- GLbitfield _TexGenEnabled;
- GLbitfield _TexMatEnabled;
- /**@}*/
-
+ GLuint CurrentUnit; /**< GL_ACTIVE_TEXTURE */
struct gl_texture_unit Unit[MAX_TEXTURE_UNITS];
- /** Proxy texture objects */
struct gl_texture_object *ProxyTex[NUM_TEXTURE_TARGETS];
+ /** GL_ARB_seamless_cubemap */
+ GLboolean CubeMapSeamless;
+
/** GL_EXT_shared_texture_palette */
GLboolean SharedPalette;
struct gl_color_table Palette;
+
+ /** Texture units/samplers used by vertex or fragment texturing */
+ GLbitfield _EnabledUnits;
+
+ /** Texture coord units/sets used for fragment texturing */
+ GLbitfield _EnabledCoordUnits;
+
+ /** Texture coord units that have texgen enabled */
+ GLbitfield _TexGenEnabled;
+
+ /** Texture coord units that have non-identity matrices */
+ GLbitfield _TexMatEnabled;
+
+ /** Bitwise-OR of all Texture.Unit[i]._GenFlags */
+ GLbitfield _GenFlags;
};
@@ -1587,6 +1482,7 @@ struct gl_transform_attrib
GLboolean Normalize; /**< Normalize all normals? */
GLboolean RescaleNormals; /**< GL_EXT_rescale_normal */
GLboolean RasterPositionUnclipped; /**< GL_IBM_rasterpos_clip */
+ GLboolean DepthClamp; /**< GL_ARB_depth_clamp */
GLboolean CullVertexFlag; /**< True if GL_CULL_VERTEX_EXT is enabled */
GLfloat CullEyePos[4];
@@ -1607,33 +1503,26 @@ struct gl_viewport_attrib
/**
- * Node for the attribute stack.
- */
-struct gl_attrib_node
-{
- GLbitfield kind;
- void *data;
- struct gl_attrib_node *next;
-};
-
-
-/**
* GL_ARB_vertex/pixel_buffer_object buffer object
*/
struct gl_buffer_object
{
GLint RefCount;
GLuint Name;
- GLenum Usage;
- GLenum Access;
- GLvoid *Pointer; /**< Only valid while buffer is mapped */
- GLsizeiptrARB Size; /**< Size of storage in bytes */
- GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
- GLboolean OnCard; /**< Is buffer in VRAM? (hardware drivers) */
+ GLenum Usage; /**< GL_STREAM_DRAW_ARB, GL_STREAM_READ_ARB, etc. */
+ GLsizeiptrARB Size; /**< Size of buffer storage in bytes */
+ GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
+ /** Fields describing a mapped buffer */
+ /*@{*/
+ GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */
+ GLvoid *Pointer; /**< User-space address of mapping */
+ GLintptr Offset; /**< Mapped offset */
+ GLsizeiptr Length; /**< Mapped length */
+ /*@}*/
+ GLboolean Written; /**< Ever written to? (for debugging) */
};
-
/**
* Client pixel packing/unpacking attributes
*/
@@ -1643,8 +1532,8 @@ struct gl_pixelstore_attrib
GLint RowLength;
GLint SkipPixels;
GLint SkipRows;
- GLint ImageHeight; /**< for GL_EXT_texture3D */
- GLint SkipImages; /**< for GL_EXT_texture3D */
+ GLint ImageHeight;
+ GLint SkipImages;
GLboolean SwapBytes;
GLboolean LsbFirst;
GLboolean ClientStorage; /**< GL_APPLE_client_storage */
@@ -1653,7 +1542,6 @@ struct gl_pixelstore_attrib
};
-
/**
* Client vertex array attributes
*/
@@ -1661,15 +1549,16 @@ struct gl_client_array
{
GLint Size; /**< components per element (1,2,3,4) */
GLenum Type; /**< datatype: GL_FLOAT, GL_INT, etc */
+ GLenum Format; /**< default: GL_RGBA, but may be GL_BGRA */
GLsizei Stride; /**< user-specified stride */
GLsizei StrideB; /**< actual stride in bytes */
const GLubyte *Ptr; /**< Points to array data */
GLboolean Enabled; /**< Enabled flag is a boolean */
GLboolean Normalized; /**< GL_ARB_vertex_program */
+ GLuint _ElementSize; /**< size of each element in bytes */
- /**< GL_ARB_vertex_buffer_object */
- struct gl_buffer_object *BufferObj;
- GLuint _MaxElement;
+ struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
+ GLuint _MaxElement; /**< max element index into array buffer + 1 */
};
@@ -1682,9 +1571,14 @@ struct gl_array_object
/** Name of the array object as received from glGenVertexArrayAPPLE. */
GLuint Name;
+ GLint RefCount;
+ _glthread_Mutex Mutex;
+ GLboolean VBOonly; /**< require all arrays to live in VBOs? */
+
/** Conventional vertex arrays */
/*@{*/
struct gl_client_array Vertex;
+ struct gl_client_array Weight;
struct gl_client_array Normal;
struct gl_client_array Color;
struct gl_client_array SecondaryColor;
@@ -1695,11 +1589,22 @@ struct gl_array_object
struct gl_client_array PointSize;
/*@}*/
- /** Generic arrays for vertex programs/shaders */
- struct gl_client_array VertexAttrib[VERT_ATTRIB_MAX];
+ /**
+ * Generic arrays for vertex programs/shaders.
+ * For NV vertex programs, these attributes alias and take priority
+ * over the conventional attribs above. For ARB vertex programs and
+ * GLSL vertex shaders, these attributes are separate.
+ */
+ struct gl_client_array VertexAttrib[MAX_VERTEX_GENERIC_ATTRIBS];
/** Mask of _NEW_ARRAY_* values indicating which arrays are enabled */
GLbitfield _Enabled;
+
+ /**
+ * Min of all enabled arrays' _MaxElement. When arrays reside inside VBOs
+ * we can determine the max legal (in bounds) glDrawElements array index.
+ */
+ GLuint _MaxElement;
};
@@ -1708,9 +1613,15 @@ struct gl_array_object
*/
struct gl_array_attrib
{
+ /** Currently bound array object. See _mesa_BindVertexArrayAPPLE() */
struct gl_array_object *ArrayObj;
+
+ /** The default vertex array object */
struct gl_array_object *DefaultArrayObj;
+ /** Array objects (GL_ARB/APPLE_vertex_array_object) */
+ struct _mesa_HashTable *Objects;
+
GLint ActiveTexture; /**< Client Active Texture */
GLuint LockFirst; /**< GL_EXT_compiled_vertex_array */
GLuint LockCount; /**< GL_EXT_compiled_vertex_array */
@@ -1718,11 +1629,9 @@ struct gl_array_attrib
GLbitfield NewState; /**< mask of _NEW_ARRAY_* values */
#if FEATURE_ARB_vertex_buffer_object
- struct gl_buffer_object *NullBufferObj;
struct gl_buffer_object *ArrayBufferObj;
struct gl_buffer_object *ElementArrayBufferObj;
#endif
- GLuint _MaxElement; /* Min of all enabled array's maxes */
};
@@ -1732,7 +1641,7 @@ struct gl_array_attrib
struct gl_feedback
{
GLenum Type;
- GLbitfield _Mask; /* FB_* bits */
+ GLbitfield _Mask; /**< FB_* bits */
GLfloat *Buffer;
GLuint BufferSize;
GLuint Count;
@@ -1830,24 +1739,24 @@ struct gl_evaluators
* be "uniform" variables since they can only be set outside glBegin/End.
* They're also all stored in the same Parameters array.
*/
-enum register_file
-{
- PROGRAM_TEMPORARY = 0, /**< machine->Temporary[] */
- PROGRAM_LOCAL_PARAM = 1, /**< gl_program->LocalParams[] */
- PROGRAM_ENV_PARAM = 2, /**< gl_program->Parameters[] */
- PROGRAM_STATE_VAR = 3, /**< gl_program->Parameters[] */
- PROGRAM_INPUT = 4, /**< machine->Inputs[] */
- PROGRAM_OUTPUT = 5, /**< machine->Outputs[] */
- PROGRAM_NAMED_PARAM = 6, /**< gl_program->Parameters[] */
- PROGRAM_CONSTANT = 7, /**< gl_program->Parameters[] */
- PROGRAM_UNIFORM = 8, /**< gl_program->Parameters[] */
- PROGRAM_VARYING = 9, /**< machine->Inputs[]/Outputs[] */
- PROGRAM_WRITE_ONLY = 10, /**< A dummy, write-only register */
- PROGRAM_ADDRESS = 11, /**< machine->AddressReg */
- PROGRAM_SAMPLER = 12, /**< for shader samplers, compile-time only */
- PROGRAM_UNDEFINED = 13, /**< Invalid value */
+typedef enum
+{
+ PROGRAM_TEMPORARY, /**< machine->Temporary[] */
+ PROGRAM_INPUT, /**< machine->Inputs[] */
+ PROGRAM_OUTPUT, /**< machine->Outputs[] */
+ PROGRAM_VARYING, /**< machine->Inputs[]/Outputs[] */
+ PROGRAM_LOCAL_PARAM, /**< gl_program->LocalParams[] */
+ PROGRAM_ENV_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_STATE_VAR, /**< gl_program->Parameters[] */
+ PROGRAM_NAMED_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_CONSTANT, /**< gl_program->Parameters[] */
+ PROGRAM_UNIFORM, /**< gl_program->Parameters[] */
+ PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
+ PROGRAM_ADDRESS, /**< machine->AddressReg */
+ PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
+ PROGRAM_UNDEFINED, /**< Invalid/TBD value */
PROGRAM_FILE_MAX
-};
+} gl_register_file;
/** Vertex and fragment instructions */
@@ -1892,7 +1801,7 @@ struct gl_program
/** Map from sampler unit to texture unit (set by glUniform1i()) */
GLubyte SamplerUnits[MAX_SAMPLERS];
/** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */
- GLubyte SamplerTargets[MAX_SAMPLERS];
+ gl_texture_index SamplerTargets[MAX_SAMPLERS];
/** Logical counts */
/*@{*/
@@ -1935,9 +1844,6 @@ struct gl_fragment_program
struct gl_program Base; /**< base class */
GLenum FogOption;
GLboolean UsesKill; /**< shader uses KIL instruction */
- GLboolean UsesPointCoord; /**< shader uses gl_PointCoord */
- GLboolean UsesFrontFacing; /**< shader used gl_FrontFacing */
- GLboolean UsesFogFragCoord; /**< shader used gl_FogFragCoord */
};
@@ -1956,14 +1862,14 @@ struct gl_program_state
*/
struct gl_vertex_program_state
{
- GLboolean Enabled; /**< User-set GL_VERTEX_PROGRAM_ARB/NV flag */
- GLboolean _Enabled; /**< Enabled and _valid_ user program? */
- GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_ARB/NV */
- GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_ARB/NV */
+ GLboolean Enabled; /**< User-set GL_VERTEX_PROGRAM_ARB/NV flag */
+ GLboolean _Enabled; /**< Enabled and _valid_ user program? */
+ GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_ARB/NV */
+ GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_ARB/NV */
struct gl_vertex_program *Current; /**< User-bound vertex program */
- /** Currently enabled and valid vertex program (including internal programs,
- * user-defined vertex programs and GLSL vertex shaders).
+ /** Currently enabled and valid vertex program (including internal
+ * programs, user-defined vertex programs and GLSL vertex shaders).
* This is the program we must use when rendering.
*/
struct gl_vertex_program *_Current;
@@ -1983,12 +1889,7 @@ struct gl_vertex_program_state
/** Cache of fixed-function programs */
struct gl_program_cache *Cache;
-#if FEATURE_MESA_program_debug
- GLprogramcallbackMESA Callback;
- GLvoid *CallbackData;
- GLboolean CallbackEnabled;
- GLuint CurrentPosition;
-#endif
+ GLboolean _Overriden;
};
@@ -2001,8 +1902,8 @@ struct gl_fragment_program_state
GLboolean _Enabled; /**< Enabled and _valid_ user program? */
struct gl_fragment_program *Current; /**< User-bound fragment program */
- /** Currently enabled and valid fragment program (including internal programs,
- * user-defined fragment programs and GLSL fragment shaders).
+ /** Currently enabled and valid fragment program (including internal
+ * programs, user-defined fragment programs and GLSL fragment shaders).
* This is the program we must use when rendering.
*/
struct gl_fragment_program *_Current;
@@ -2017,13 +1918,6 @@ struct gl_fragment_program_state
/** Cache of fixed-function programs */
struct gl_program_cache *Cache;
-
-#if FEATURE_MESA_program_debug
- GLprogramcallbackMESA Callback;
- GLvoid *CallbackData;
- GLboolean CallbackEnabled;
- GLuint CurrentPosition;
-#endif
};
@@ -2094,9 +1988,26 @@ struct gl_query_state
};
+/** Sync object state */
+struct gl_sync_object {
+ struct simple_node link;
+ GLenum Type; /**< GL_SYNC_FENCE */
+ GLuint Name; /**< Fence name */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending; /**< Object was deleted while there were still
+ * live references (e.g., sync not yet finished)
+ */
+ GLenum SyncCondition;
+ GLbitfield Flags; /**< Flags passed to glFenceSync */
+ GLuint StatusFlag:1; /**< Has the sync object been signaled? */
+};
+
+
/** Set by #pragma directives */
struct gl_sl_pragmas
{
+ GLboolean IgnoreOptimize; /**< ignore #pragma optimize(on/off) ? */
+ GLboolean IgnoreDebug; /**< ignore #pragma debug(on/off) ? */
GLboolean Optimize; /**< defaults on */
GLboolean Debug; /**< defaults off */
};
@@ -2113,7 +2024,9 @@ struct gl_shader
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 */
GLchar *InfoLog;
struct gl_sl_pragmas Pragmas;
@@ -2144,10 +2057,18 @@ struct gl_shader_program
struct gl_program_parameter_list *Varying;
GLboolean LinkStatus; /**< GL_LINK_STATUS */
GLboolean Validated;
+ GLboolean _Used; /**< Ever used for drawing? */
GLchar *InfoLog;
};
+#define GLSL_DUMP 0x1 /**< Dump shaders to stdout */
+#define GLSL_LOG 0x2 /**< Write shaders to files */
+#define GLSL_OPT 0x4 /**< Force optimizations (override pragmas) */
+#define GLSL_NO_OPT 0x8 /**< Force no optimizations (override pragmas) */
+#define GLSL_UNIFORMS 0x10 /**< Print glUniform calls */
+
+
/**
* Context state for GLSL vertex/fragment shaders.
*/
@@ -2156,9 +2077,12 @@ struct gl_shader_state
struct gl_shader_program *CurrentProgram; /**< The user-bound program */
/** Driver-selectable options: */
GLboolean EmitHighLevelInstructions; /**< IF/ELSE/ENDIF vs. BRA, etc. */
+ GLboolean EmitContReturn; /**< Emit CONT/RET opcodes? */
GLboolean EmitCondCodes; /**< Use condition codes? */
GLboolean EmitComments; /**< Annotated instructions */
void *MemPool;
+ GLbitfield Flags; /**< Mask of GLSL_x flags */
+ struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
};
@@ -2172,18 +2096,11 @@ struct gl_shared_state
struct _mesa_HashTable *DisplayList; /**< Display lists hash table */
struct _mesa_HashTable *TexObjects; /**< Texture objects hash table */
- /**
- * \name Default texture objects (shared by all multi-texture units)
- */
- /*@{*/
- struct gl_texture_object *Default1D;
- struct gl_texture_object *Default2D;
- struct gl_texture_object *Default3D;
- struct gl_texture_object *DefaultCubeMap;
- struct gl_texture_object *DefaultRect;
- struct gl_texture_object *Default1DArray;
- struct gl_texture_object *Default2DArray;
- /*@}*/
+ /** Default texture objects (shared by all texture units) */
+ struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
+
+ /** Fallback texture used when a bound texture is incomplete */
+ struct gl_texture_object *FallbackTex;
/**
* \name Thread safety and statechange notification for texture
@@ -2196,6 +2113,8 @@ struct gl_shared_state
GLuint TextureStateStamp; /**< state notification for shared tex */
/*@}*/
+ /** Default buffer object for vertex arrays that aren't in VBOs */
+ struct gl_buffer_object *NullBufferObj;
/**
* \name Vertex/fragment programs
@@ -2229,8 +2148,9 @@ struct gl_shared_state
struct _mesa_HashTable *FrameBuffers;
#endif
- /** Objects associated with the GL_APPLE_vertex_array_object extension. */
- struct _mesa_HashTable *ArrayObjects;
+#if FEATURE_ARB_sync
+ struct simple_node SyncObjects;
+#endif
void *DriverData; /**< Device driver shared state */
};
@@ -2260,7 +2180,9 @@ struct gl_renderbuffer
GLenum _ActualFormat; /**< The driver-chosen format */
GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or
GL_STENCIL_INDEX. */
- GLenum DataType; /**< Type of values passed to the Get/Put functions */
+ GLenum ColorEncoding; /**< GL_LINEAR or GL_SRGB */
+ GLenum ComponentType; /**< GL_FLOAT, GL_INT, GL_UNSIGNED_INT,
+ GL_UNSIGNED_NORMALIZED or GL_INDEX */
GLubyte RedBits; /**< Bits of red per pixel */
GLubyte GreenBits;
GLubyte BlueBits;
@@ -2268,6 +2190,9 @@ struct gl_renderbuffer
GLubyte IndexBits;
GLubyte DepthBits;
GLubyte StencilBits;
+ GLubyte NumSamples;
+
+ GLenum DataType; /**< Type of values passed to the Get/Put functions */
GLvoid *Data; /**< This may not be used by some kinds of RBs */
/* Used to wrap one renderbuffer around another: */
@@ -2342,9 +2267,8 @@ struct gl_renderbuffer
/**
- * A renderbuffer attachment point points to either a texture object
- * (and specifies a mipmap level, cube face or 3D texture slice) or
- * points to a renderbuffer.
+ * A renderbuffer attachment points to either a texture object (and specifies
+ * a mipmap level, cube face or 3D texture slice) or points to a renderbuffer.
*/
struct gl_renderbuffer_attachment
{
@@ -2376,14 +2300,24 @@ struct gl_renderbuffer_attachment
*/
struct gl_framebuffer
{
- _glthread_Mutex Mutex; /**< for thread safety */
- GLuint Name; /* if zero, this is a window system framebuffer */
+ _glthread_Mutex Mutex; /**< for thread safety */
+ /**
+ * If zero, this is a window system framebuffer. If non-zero, this
+ * is a FBO framebuffer; note that for some devices (i.e. those with
+ * a natural pixel coordinate system for FBOs that differs from the
+ * OpenGL/Mesa coordinate system), this means that the viewport,
+ * polygon face orientation, and polygon stipple will have to be inverted.
+ */
+ GLuint Name;
+
GLint RefCount;
GLboolean DeletePending;
- GLvisual Visual; /**< The framebuffer's visual.
- Immutable if this is a window system buffer.
- Computed from attachments if user-made FBO. */
+ /**
+ * The framebuffer's visual. Immutable if this is a window system buffer.
+ * Computed from attachments if user-made FBO.
+ */
+ GLvisual Visual;
GLboolean Initialized;
@@ -2402,9 +2336,10 @@ struct gl_framebuffer
GLfloat _MRD; /**< minimum resolvable difference in Z values */
/*@}*/
- GLenum _Status; /* One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */
+ /** One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */
+ GLenum _Status;
- /* Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */
+ /** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */
struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT];
/* In unextended OpenGL these vars are part of the GL_COLOR_BUFFER
@@ -2466,50 +2401,69 @@ struct gl_program_constants
*/
struct gl_constants
{
- GLint MaxTextureLevels; /**< Maximum number of allowed mipmap levels. */
- GLint Max3DTextureLevels; /**< Maximum number of allowed mipmap levels for 3D texture targets. */
- GLint MaxCubeTextureLevels; /**< Maximum number of allowed mipmap levels for GL_ARB_texture_cube_map */
- GLint MaxArrayTextureLayers; /**< Maximum number of layers in an array texture. */
- GLint MaxTextureRectSize; /* GL_NV_texture_rectangle */
+ GLint MaxTextureLevels; /**< Max mipmap levels. */
+ GLint Max3DTextureLevels; /**< Max mipmap levels for 3D textures */
+ GLint MaxCubeTextureLevels; /**< Max mipmap levels for cube textures */
+ GLint MaxArrayTextureLayers; /**< Max layers in array textures */
+ GLint MaxTextureRectSize; /**< Max rectangle texture size, in pixes */
GLuint MaxTextureCoordUnits;
GLuint MaxTextureImageUnits;
- GLuint MaxTextureUnits; /**< = MIN(CoordUnits, ImageUnits) */
- GLfloat MaxTextureMaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
- GLfloat MaxTextureLodBias; /**< GL_EXT_texture_lod_bias */
+ GLuint MaxVertexTextureImageUnits;
+ GLuint MaxTextureUnits; /**< = MIN(CoordUnits, ImageUnits) */
+ GLfloat MaxTextureMaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
+ GLfloat MaxTextureLodBias; /**< GL_EXT_texture_lod_bias */
+
GLuint MaxArrayLockSize;
+
GLint SubPixelBits;
- GLfloat MinPointSize, MaxPointSize; /* aliased */
- GLfloat MinPointSizeAA, MaxPointSizeAA; /* antialiased */
+
+ GLfloat MinPointSize, MaxPointSize; /**< aliased */
+ GLfloat MinPointSizeAA, MaxPointSizeAA; /**< antialiased */
GLfloat PointSizeGranularity;
- GLfloat MinLineWidth, MaxLineWidth; /* aliased */
- GLfloat MinLineWidthAA, MaxLineWidthAA; /* antialiased */
+ GLfloat MinLineWidth, MaxLineWidth; /**< aliased */
+ GLfloat MinLineWidthAA, MaxLineWidthAA; /**< antialiased */
GLfloat LineWidthGranularity;
+
GLuint MaxColorTableSize;
GLuint MaxConvolutionWidth;
GLuint MaxConvolutionHeight;
+
GLuint MaxClipPlanes;
GLuint MaxLights;
- GLfloat MaxShininess; /* GL_NV_light_max_exponent */
- GLfloat MaxSpotExponent; /* GL_NV_light_max_exponent */
+ GLfloat MaxShininess; /**< GL_NV_light_max_exponent */
+ GLfloat MaxSpotExponent; /**< GL_NV_light_max_exponent */
+
GLuint MaxViewportWidth, MaxViewportHeight;
- struct gl_program_constants VertexProgram; /* GL_ARB_vertex_program */
- struct gl_program_constants FragmentProgram; /* GL_ARB_fragment_program */
- /* shared by vertex and fragment program: */
+
+ struct gl_program_constants VertexProgram; /**< GL_ARB_vertex_program */
+ struct gl_program_constants FragmentProgram; /**< GL_ARB_fragment_program */
GLuint MaxProgramMatrices;
GLuint MaxProgramMatrixStackDepth;
- /* vertex array / buffer object bounds checking */
+
+ /** vertex array / buffer object bounds checking */
GLboolean CheckArrayBounds;
- /* GL_ARB_draw_buffers */
- GLuint MaxDrawBuffers;
- /* GL_OES_read_format */
- GLenum ColorReadFormat;
- GLenum ColorReadType;
- /* GL_EXT_framebuffer_object */
- GLuint MaxColorAttachments;
- GLuint MaxRenderbufferSize;
- /* GL_ARB_vertex_shader */
- GLuint MaxVertexTextureImageUnits;
- GLuint MaxVarying; /**< Number of float[4] vectors */
+
+ GLuint MaxDrawBuffers; /**< GL_ARB_draw_buffers */
+
+ GLenum ColorReadFormat; /**< GL_OES_read_format */
+ GLenum ColorReadType; /**< GL_OES_read_format */
+
+ GLuint MaxColorAttachments; /**< GL_EXT_framebuffer_object */
+ GLuint MaxRenderbufferSize; /**< GL_EXT_framebuffer_object */
+ GLuint MaxSamples; /**< GL_ARB_framebuffer_object */
+
+ GLuint MaxVarying; /**< Number of float[4] varying parameters */
+
+ GLbitfield SupportedBumpUnits; /**> units supporting GL_ATI_envmap_bumpmap as targets */
+
+ /**
+ * Maximum amount of time, measured in nanseconds, that the server can wait.
+ */
+ GLuint64 MaxServerWaitTimeout;
+
+
+ /**< GL_EXT_provoking_vertex */
+ GLboolean QuadsFollowProvokingVertexConvention;
};
@@ -2519,28 +2473,30 @@ struct gl_constants
*/
struct gl_extensions
{
- /**
- * \name Flags to quickly test if certain extensions are available.
- *
- * Not every extension needs to have such a flag, but it's encouraged.
- */
- /*@{*/
GLboolean dummy; /* don't remove this! */
+ GLboolean ARB_copy_buffer;
GLboolean ARB_depth_texture;
+ GLboolean ARB_depth_clamp;
GLboolean ARB_draw_buffers;
+ GLboolean ARB_draw_elements_base_vertex;
GLboolean ARB_fragment_program;
GLboolean ARB_fragment_program_shadow;
GLboolean ARB_fragment_shader;
+ GLboolean ARB_framebuffer_object;
GLboolean ARB_half_float_pixel;
GLboolean ARB_imaging;
+ GLboolean ARB_map_buffer_range;
GLboolean ARB_multisample;
GLboolean ARB_multitexture;
GLboolean ARB_occlusion_query;
GLboolean ARB_point_sprite;
+ GLboolean ARB_seamless_cube_map;
GLboolean ARB_shader_objects;
GLboolean ARB_shading_language_100;
GLboolean ARB_shading_language_120;
GLboolean ARB_shadow;
+ GLboolean ARB_shadow_ambient; /* or GL_ARB_shadow_ambient */
+ GLboolean ARB_sync;
GLboolean ARB_texture_border_clamp;
GLboolean ARB_texture_compression;
GLboolean ARB_texture_cube_map;
@@ -2551,6 +2507,7 @@ struct gl_extensions
GLboolean ARB_texture_mirrored_repeat;
GLboolean ARB_texture_non_power_of_two;
GLboolean ARB_transpose_matrix;
+ GLboolean ARB_vertex_array_object;
GLboolean ARB_vertex_buffer_object;
GLboolean ARB_vertex_program;
GLboolean ARB_vertex_shader;
@@ -2582,6 +2539,7 @@ struct gl_extensions
GLboolean EXT_pixel_buffer_object;
GLboolean EXT_point_parameters;
GLboolean EXT_polygon_offset;
+ GLboolean EXT_provoking_vertex;
GLboolean EXT_rescale_normal;
GLboolean EXT_shadow_funcs;
GLboolean EXT_secondary_color;
@@ -2601,13 +2559,16 @@ struct gl_extensions
GLboolean EXT_texture_lod_bias;
GLboolean EXT_texture_mirror_clamp;
GLboolean EXT_texture_sRGB;
+ GLboolean EXT_texture_swizzle;
GLboolean EXT_timer_query;
GLboolean EXT_vertex_array;
+ GLboolean EXT_vertex_array_bgra;
GLboolean EXT_vertex_array_set;
/* vendor extensions */
GLboolean APPLE_client_storage;
GLboolean APPLE_packed_pixels;
GLboolean APPLE_vertex_array_object;
+ GLboolean ATI_envmap_bumpmap;
GLboolean ATI_texture_mirror_once;
GLboolean ATI_texture_env_combine3;
GLboolean ATI_fragment_shader;
@@ -2616,15 +2577,16 @@ struct gl_extensions
GLboolean IBM_multimode_draw_arrays;
GLboolean MESA_pack_invert;
GLboolean MESA_packed_depth_stencil;
- GLboolean MESA_program_debug;
GLboolean MESA_resize_buffers;
GLboolean MESA_ycbcr_texture;
GLboolean MESA_texture_array;
+ GLboolean MESA_texture_signed_rgba;
GLboolean NV_blend_square;
GLboolean NV_fragment_program;
GLboolean NV_light_max_exponent;
GLboolean NV_point_sprite;
GLboolean NV_texgen_reflection;
+ GLboolean NV_texture_env_combine4;
GLboolean NV_texture_rectangle;
GLboolean NV_vertex_program;
GLboolean NV_vertex_program1_1;
@@ -2635,12 +2597,15 @@ struct gl_extensions
GLboolean SGIS_generate_mipmap;
GLboolean SGIS_texture_edge_clamp;
GLboolean SGIS_texture_lod;
- GLboolean SGIX_shadow;
- GLboolean SGIX_shadow_ambient; /* or GL_ARB_shadow_ambient */
GLboolean TDFX_texture_compression_FXT1;
GLboolean S3_s3tc;
- /*@}*/
- /* The extension string */
+#if FEATURE_OES_draw_texture
+ GLboolean OES_draw_texture;
+#endif /* FEATURE_OES_draw_texture */
+#if FEATURE_OES_EGL_image
+ GLboolean OES_EGL_image;
+#endif
+ /** The extension string */
const GLubyte *String;
};
@@ -2660,7 +2625,6 @@ struct gl_matrix_stack
/**
* \name Bits for image transfer operations
- *
* \sa __GLcontextRec::ImageTransferState.
*/
/*@{*/
@@ -2675,7 +2639,7 @@ struct gl_matrix_stack
#define IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT 0x100
#define IMAGE_HISTOGRAM_BIT 0x200
#define IMAGE_MIN_MAX_BIT 0x400
-#define IMAGE_CLAMP_BIT 0x800 /* extra */
+#define IMAGE_CLAMP_BIT 0x800
/** Pixel Transfer ops up to convolution */
@@ -2728,6 +2692,9 @@ struct gl_matrix_stack
#define _NEW_MULTISAMPLE 0x2000000 /**< __GLcontextRec::Multisample */
#define _NEW_TRACK_MATRIX 0x4000000 /**< __GLcontextRec::VertexProgram */
#define _NEW_PROGRAM 0x8000000 /**< __GLcontextRec::VertexProgram */
+#define _NEW_CURRENT_ATTRIB 0x10000000 /**< __GLcontextRec::Current */
+#define _NEW_PROGRAM_CONSTANTS 0x20000000
+#define _NEW_BUFFER_OBJECT 0x40000000
#define _NEW_ALL ~0
/*@}*/
@@ -2810,6 +2777,10 @@ struct gl_matrix_stack
/*@}*/
+/**
+ * Composite state flags
+ */
+/*@{*/
#define _MESA_NEW_NEED_EYE_COORDS (_NEW_LIGHT | \
_NEW_TEXTURE | \
_NEW_POINT | \
@@ -2819,17 +2790,12 @@ struct gl_matrix_stack
#define _MESA_NEW_NEED_NORMALS (_NEW_LIGHT | \
_NEW_TEXTURE)
-#define _IMAGE_NEW_TRANSFER_STATE (_NEW_PIXEL | _NEW_COLOR_MATRIX)
-
+#define _MESA_NEW_TRANSFER_STATE (_NEW_PIXEL | \
+ _NEW_COLOR_MATRIX)
+/*@}*/
-/*
- * Forward declaration of display list data types:
- */
-union node;
-typedef union node Node;
-
/* This has to be included here. */
#include "dd.h"
@@ -2860,21 +2826,31 @@ struct gl_tnl_module
/*@}*/
};
-/* Strictly this is a tnl/ private concept, but it doesn't seem
+
+/**
+ * Display list flags.
+ * Strictly this is a tnl-private concept, but it doesn't seem
* worthwhile adding a tnl private structure just to hold this one bit
* of information:
*/
-#define MESA_DLIST_DANGLING_REFS 0x1
+#define DLIST_DANGLING_REFS 0x1
+
-/* Provide a location where information about a display list can be
+/** Opaque declaration of display list payload data type */
+union gl_dlist_node;
+
+
+/**
+ * Provide a location where information about a display list can be
* collected. Could be extended with driverPrivate structures,
* etc. in the future.
*/
-struct mesa_display_list
+struct gl_display_list
{
- Node *node;
- GLuint id;
- GLbitfield flags;
+ GLuint Name;
+ GLbitfield Flags; /**< DLIST_x flags */
+ /** The dlist commands are in a linked list of nodes */
+ union gl_dlist_node *Head;
};
@@ -2885,10 +2861,8 @@ struct gl_dlist_state
{
GLuint CallDepth; /**< Current recursion calling depth */
- struct mesa_display_list *CurrentList;
- Node *CurrentListPtr; /**< Head of list being compiled */
- GLuint CurrentListNum; /**< Number of the list being compiled */
- Node *CurrentBlock; /**< Pointer to current block of nodes */
+ struct gl_display_list *CurrentList; /**< List currently being compiled */
+ union gl_dlist_node *CurrentBlock; /**< Pointer to current block of nodes */
GLuint CurrentPos; /**< Index into current block of nodes */
GLvertexformat ListVtxfmt;
@@ -2904,6 +2878,13 @@ struct gl_dlist_state
GLubyte ActiveEdgeFlag;
GLboolean CurrentEdgeFlag;
+
+ struct {
+ /* State known to have been set by the currently-compiling display
+ * list. Used to eliminate some redundant state changes.
+ */
+ GLenum ShadeModel;
+ } Current;
};
@@ -3030,31 +3011,41 @@ struct __GLcontextRec
struct gl_color_table ColorTable[COLORTABLE_MAX];
struct gl_color_table ProxyColorTable[COLORTABLE_MAX];
-#if 0
- struct gl_color_table PostConvolutionColorTable;
- struct gl_color_table ProxyPostConvolutionColorTable;
- struct gl_color_table PostColorMatrixColorTable;
- struct gl_color_table ProxyPostColorMatrixColorTable;
-#endif
-
- struct gl_program_state Program; /**< for vertex or fragment progs */
- struct gl_vertex_program_state VertexProgram; /**< GL_ARB/NV_vertex_program */
- struct gl_fragment_program_state FragmentProgram; /**< GL_ARB/NV_vertex_program */
- struct gl_ati_fragment_shader_state ATIFragmentShader; /**< GL_ATI_fragment_shader */
- struct gl_query_state Query; /**< GL_ARB_occlusion_query */
+ struct gl_program_state Program; /**< general program state */
+ struct gl_vertex_program_state VertexProgram;
+ struct gl_fragment_program_state FragmentProgram;
+ struct gl_ati_fragment_shader_state ATIFragmentShader;
struct gl_shader_state Shader; /**< GLSL shader object state */
+
+ struct gl_query_state Query; /**< occlusion, timer queries */
+
+ struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */
+ struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */
/*@}*/
+ struct gl_meta_state *Meta; /**< for "meta" operations */
+
#if FEATURE_EXT_framebuffer_object
struct gl_renderbuffer *CurrentRenderbuffer;
#endif
GLenum ErrorValue; /**< Last error code */
+
+ /**
+ * Recognize and silence repeated error debug messages in buggy apps.
+ */
+ const char *ErrorDebugFmtString;
+ GLuint ErrorDebugCount;
+
GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */
GLbitfield NewState; /**< bitwise-or of _NEW_* flags */
+ GLboolean ViewportInitialized; /**< has viewport size been initialized? */
+
+ GLbitfield varying_vp_inputs; /**< mask of VERT_BIT_* flags */
+
/** \name Derived state */
/*@{*/
/** Bitwise-or of DD_* flags. Note that this bitfield may be used before
@@ -3066,9 +3057,8 @@ struct __GLcontextRec
GLfloat _ModelViewInvScale;
GLboolean _NeedEyeCoords;
GLboolean _ForceEyeCoords;
- GLenum _CurrentProgram; /* currently executing program */
- GLuint TextureStateTimestamp; /* detect changes to shared state */
+ GLuint TextureStateTimestamp; /**< detect changes to shared state */
struct gl_shine_tab *_ShineTable[2]; /**< Active shine tables */
struct gl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */
@@ -3087,6 +3077,12 @@ struct __GLcontextRec
/** software compression/decompression supported or not */
GLboolean Mesa_DXTn;
+ /**
+ * Use dp4 (rather than mul/mad) instructions for position
+ * transformation?
+ */
+ GLboolean mvp_with_dp4;
+
/** Core tnl module support */
struct gl_tnl_module TnlModule;
@@ -3100,7 +3096,7 @@ struct __GLcontextRec
void *swsetup_context;
void *swtnl_context;
void *swtnl_im;
- void *acache_context;
+ struct st_context *st;
void *aelt_context;
/*@}*/
};
@@ -3138,8 +3134,6 @@ enum _verbose
VERBOSE_PRIMS = 0x0400,
VERBOSE_VERTS = 0x0800,
VERBOSE_DISASSEM = 0x1000,
- VERBOSE_GLSL = 0x2000,
- VERBOSE_GLSL_DUMP = 0x4000
};
@@ -3150,7 +3144,4 @@ enum _debug
-#define Elements(x) sizeof(x)/sizeof(*(x))
-
-
-#endif /* TYPES_H */
+#endif /* MTYPES_H */
diff --git a/src/mesa/main/multisample.c b/src/mesa/main/multisample.c
index b9cfad9216..01b68df7af 100644
--- a/src/mesa/main/multisample.c
+++ b/src/mesa/main/multisample.c
@@ -37,11 +37,6 @@ _mesa_SampleCoverageARB(GLclampf value, GLboolean invert)
{
GET_CURRENT_CONTEXT(ctx);
- if (!ctx->Extensions.ARB_multisample) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB");
- return;
- }
-
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0);
diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c
index 8d24a201f0..23a5c9b9f7 100644
--- a/src/mesa/main/pixel.c
+++ b/src/mesa/main/pixel.c
@@ -36,6 +36,10 @@
#include "macros.h"
#include "pixel.h"
#include "mtypes.h"
+#include "glapi/dispatch.h"
+
+
+#if FEATURE_pixel_transfer
/**********************************************************************/
@@ -136,6 +140,33 @@ store_pixelmap(GLcontext *ctx, GLenum map, GLsizei mapsize,
}
+/**
+ * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
+ */
+static GLboolean
+validate_pbo_access(GLcontext *ctx, struct gl_pixelstore_attrib *pack,
+ GLsizei mapsize, GLenum format, GLenum type,
+ const GLvoid *ptr)
+{
+ GLboolean ok;
+
+ /* Note, need to use DefaultPacking and Unpack's buffer object */
+ ctx->DefaultPacking.BufferObj = pack->BufferObj;
+
+ ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
+ format, type, ptr);
+
+ /* restore */
+ ctx->DefaultPacking.BufferObj = ctx->Shared->NullBufferObj;
+
+ if (!ok) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glPixelMap(invalid PBO access)");
+ }
+ return ok;
+}
+
+
void GLAPIENTRY
_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
{
@@ -158,40 +189,23 @@ _mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
FLUSH_VERTICES(ctx, _NEW_PIXEL);
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack pixelmap from PBO */
- GLubyte *buf;
- /* Note, need to use DefaultPacking and Unpack's buffer object */
- ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
- if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
- GL_INTENSITY, GL_FLOAT, values)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glPixelMapfv(invalid PBO access)");
- return;
- }
- /* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- ctx->Unpack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
+ if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
+ GL_INTENSITY, GL_FLOAT, values)) {
+ return;
+ }
+
+ values = (const GLfloat *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glPixelMapfv(PBO is mapped)");
- return;
}
- values = (const GLfloat *) ADD_POINTERS(buf, values);
- }
- else if (!values) {
return;
}
store_pixelmap(ctx, map, mapsize, values);
- if (ctx->Unpack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- ctx->Unpack.BufferObj);
- }
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
}
@@ -217,31 +231,17 @@ _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
FLUSH_VERTICES(ctx, _NEW_PIXEL);
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack pixelmap from PBO */
- GLubyte *buf;
- /* Note, need to use DefaultPacking and Unpack's buffer object */
- ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
- if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
- GL_INTENSITY, GL_UNSIGNED_INT, values)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glPixelMapuiv(invalid PBO access)");
- return;
- }
- /* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- ctx->Unpack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
+ if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_INT, values)) {
+ return;
+ }
+
+ values = (const GLuint *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glPixelMapuiv(PBO is mapped)");
- return;
}
- values = (const GLuint *) ADD_POINTERS(buf, values);
- }
- else if (!values) {
return;
}
@@ -259,10 +259,7 @@ _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
}
}
- if (ctx->Unpack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- ctx->Unpack.BufferObj);
- }
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
store_pixelmap(ctx, map, mapsize, fvalues);
}
@@ -290,32 +287,17 @@ _mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
FLUSH_VERTICES(ctx, _NEW_PIXEL);
- if (ctx->Unpack.BufferObj->Name) {
- /* unpack pixelmap from PBO */
- GLubyte *buf;
- /* Note, need to use DefaultPacking and Unpack's buffer object */
- ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
- if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
- GL_INTENSITY, GL_UNSIGNED_SHORT,
- values)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glPixelMapusv(invalid PBO access)");
- return;
- }
- /* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- ctx->Unpack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
+ if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
+ return;
+ }
+
+ values = (const GLushort *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glPixelMapusv(PBO is mapped)");
- return;
}
- values = (const GLushort *) ADD_POINTERS(buf, values);
- }
- else if (!values) {
return;
}
@@ -333,10 +315,7 @@ _mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
}
}
- if (ctx->Unpack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- ctx->Unpack.BufferObj);
- }
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
store_pixelmap(ctx, map, mapsize, fvalues);
}
@@ -359,31 +338,17 @@ _mesa_GetPixelMapfv( GLenum map, GLfloat *values )
mapsize = pm->Size;
- if (ctx->Pack.BufferObj->Name) {
- /* pack pixelmap into PBO */
- GLubyte *buf;
- /* Note, need to use DefaultPacking and Pack's buffer object */
- ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
- if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
- GL_INTENSITY, GL_FLOAT, values)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetPixelMapfv(invalid PBO access)");
- return;
- }
- /* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
+ if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
+ GL_INTENSITY, GL_FLOAT, values)) {
+ return;
+ }
+
+ values = (GLfloat *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetPixelMapfv(PBO is mapped)");
- return;
}
- values = (GLfloat *) ADD_POINTERS(buf, values);
- }
- else if (!values) {
return;
}
@@ -397,10 +362,7 @@ _mesa_GetPixelMapfv( GLenum map, GLfloat *values )
MEMCPY(values, pm->Map, mapsize * sizeof(GLfloat));
}
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
@@ -420,31 +382,17 @@ _mesa_GetPixelMapuiv( GLenum map, GLuint *values )
}
mapsize = pm->Size;
- if (ctx->Pack.BufferObj->Name) {
- /* pack pixelmap into PBO */
- GLubyte *buf;
- /* Note, need to use DefaultPacking and Pack's buffer object */
- ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
- if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
- GL_INTENSITY, GL_UNSIGNED_INT, values)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetPixelMapuiv(invalid PBO access)");
- return;
- }
- /* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
+ if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_INT, values)) {
+ return;
+ }
+
+ values = (GLuint *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetPixelMapuiv(PBO is mapped)");
- return;
}
- values = (GLuint *) ADD_POINTERS(buf, values);
- }
- else if (!values) {
return;
}
@@ -458,10 +406,7 @@ _mesa_GetPixelMapuiv( GLenum map, GLuint *values )
}
}
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
@@ -481,32 +426,17 @@ _mesa_GetPixelMapusv( GLenum map, GLushort *values )
}
mapsize = pm ? pm->Size : 0;
- if (ctx->Pack.BufferObj->Name) {
- /* pack pixelmap into PBO */
- GLubyte *buf;
- /* Note, need to use DefaultPacking and Pack's buffer object */
- ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
- if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
- GL_INTENSITY, GL_UNSIGNED_SHORT,
- values)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetPixelMapusv(invalid PBO access)");
- return;
- }
- /* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
+ if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
+ return;
+ }
+
+ values = (GLushort *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetPixelMapusv(PBO is mapped)");
- return;
}
- values = (GLushort *) ADD_POINTERS(buf, values);
- }
- else if (!values) {
return;
}
@@ -528,10 +458,7 @@ _mesa_GetPixelMapusv( GLenum map, GLushort *values )
}
}
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
@@ -819,7 +746,7 @@ update_image_transfer_state(GLcontext *ctx)
/**
- * Update meas pixel transfer derived state.
+ * Update mesa pixel transfer derived state.
*/
void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
{
@@ -828,11 +755,29 @@ void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
/* References ColorMatrix.type (derived above).
*/
- if (new_state & _IMAGE_NEW_TRANSFER_STATE)
+ if (new_state & _MESA_NEW_TRANSFER_STATE)
update_image_transfer_state(ctx);
}
+void
+_mesa_init_pixel_dispatch(struct _glapi_table *disp)
+{
+ SET_GetPixelMapfv(disp, _mesa_GetPixelMapfv);
+ SET_GetPixelMapuiv(disp, _mesa_GetPixelMapuiv);
+ SET_GetPixelMapusv(disp, _mesa_GetPixelMapusv);
+ SET_PixelMapfv(disp, _mesa_PixelMapfv);
+ SET_PixelMapuiv(disp, _mesa_PixelMapuiv);
+ SET_PixelMapusv(disp, _mesa_PixelMapusv);
+ SET_PixelTransferf(disp, _mesa_PixelTransferf);
+ SET_PixelTransferi(disp, _mesa_PixelTransferi);
+ SET_PixelZoom(disp, _mesa_PixelZoom);
+}
+
+
+#endif /* FEATURE_pixel_transfer */
+
+
/**********************************************************************/
/***** Initialization *****/
/**********************************************************************/
diff --git a/src/mesa/main/pixel.h b/src/mesa/main/pixel.h
index cb6c5262a3..7a901aec10 100644
--- a/src/mesa/main/pixel.h
+++ b/src/mesa/main/pixel.h
@@ -33,9 +33,11 @@
#define PIXEL_H
-#include "mtypes.h"
+#include "main/mtypes.h"
+#if FEATURE_pixel_transfer
+
/** \name API functions */
/*@{*/
@@ -68,13 +70,30 @@ _mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor );
/*@}*/
-
extern void
_mesa_update_pixel( GLcontext *ctx, GLuint newstate );
extern void
+_mesa_init_pixel_dispatch( struct _glapi_table * disp );
+
+#else /* FEATURE_pixel_transfer */
+
+static INLINE void
+_mesa_update_pixel(GLcontext *ctx, GLuint newstate)
+{
+}
+
+static INLINE void
+_mesa_init_pixel_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_pixel_transfer */
+
+
+extern void
_mesa_init_pixel( GLcontext * ctx );
/*@}*/
-#endif
+#endif /* PIXEL_H */
diff --git a/src/mesa/main/pixelstore.c b/src/mesa/main/pixelstore.c
index ff1a6344cc..6a641f83f2 100644
--- a/src/mesa/main/pixelstore.c
+++ b/src/mesa/main/pixelstore.c
@@ -245,7 +245,8 @@ _mesa_init_pixelstore( GLcontext *ctx )
ctx->Pack.ClientStorage = GL_FALSE;
ctx->Pack.Invert = GL_FALSE;
#if FEATURE_EXT_pixel_buffer_object
- ctx->Pack.BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj,
+ ctx->Shared->NullBufferObj);
#endif
ctx->Unpack.Alignment = 4;
ctx->Unpack.RowLength = 0;
@@ -258,7 +259,8 @@ _mesa_init_pixelstore( GLcontext *ctx )
ctx->Unpack.ClientStorage = GL_FALSE;
ctx->Unpack.Invert = GL_FALSE;
#if FEATURE_EXT_pixel_buffer_object
- ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj,
+ ctx->Shared->NullBufferObj);
#endif
/*
@@ -278,6 +280,7 @@ _mesa_init_pixelstore( GLcontext *ctx )
ctx->DefaultPacking.ClientStorage = GL_FALSE;
ctx->DefaultPacking.Invert = GL_FALSE;
#if FEATURE_EXT_pixel_buffer_object
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj,
+ ctx->Shared->NullBufferObj);
#endif
}
diff --git a/src/mesa/main/polygon.c b/src/mesa/main/polygon.c
index 564250b881..376a87a396 100644
--- a/src/mesa/main/polygon.c
+++ b/src/mesa/main/polygon.c
@@ -193,32 +193,16 @@ _mesa_PolygonMode( GLenum face, GLenum mode )
void
_mesa_polygon_stipple(GLcontext *ctx, const GLubyte *pattern)
{
- if (ctx->Unpack.BufferObj->Name) {
- /* Get/unpack the stipple pattern from a PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(2, &ctx->Unpack, 32, 32, 1,
- GL_COLOR_INDEX, GL_BITMAP, pattern)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glPolygonStipple(bad PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- GL_READ_ONLY_ARB,
- ctx->Unpack.BufferObj);
- if (!buf) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glPolygonStipple(PBO mapped)");
- return;
- }
- buf = ADD_POINTERS(buf, pattern);
- _mesa_unpack_polygon_stipple(buf, ctx->PolygonStipple, &ctx->Unpack);
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
- ctx->Unpack.BufferObj);
- }
- else {
- /* Get/unpack the stipple pattern from user memory */
- _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack);
- }
+ pattern = _mesa_map_validate_pbo_source(ctx, 2,
+ &ctx->Unpack, 32, 32, 1,
+ GL_COLOR_INDEX, GL_BITMAP, pattern,
+ "glPolygonStipple");
+ if (!pattern)
+ return;
+
+ _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack);
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
}
@@ -255,35 +239,16 @@ _mesa_GetPolygonStipple( GLubyte *dest )
if (MESA_VERBOSE&VERBOSE_API)
_mesa_debug(ctx, "glGetPolygonStipple\n");
- /* XXX someday we may put this code into a separate function and call
- * it with ctx->Driver.GetPolygonStipple().
- */
- if (ctx->Pack.BufferObj->Name) {
- /* Put/pack the stipple pattern into a PBO */
- GLubyte *buf;
- if (!_mesa_validate_pbo_access(2, &ctx->Pack, 32, 32, 1,
- GL_COLOR_INDEX, GL_BITMAP, dest)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetPolygonStipple(bad PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetPolygonStipple(PBO mapped)");
- return;
- }
- buf = ADD_POINTERS(buf, dest);
- _mesa_pack_polygon_stipple(ctx->PolygonStipple, buf, &ctx->Pack);
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
- else {
- /* Put/pack the stipple pattern into user memory */
- _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack);
- }
+ dest = _mesa_map_validate_pbo_dest(ctx, 2,
+ &ctx->Pack, 32, 32, 1,
+ GL_COLOR_INDEX, GL_BITMAP, dest,
+ "glGetPolygonStipple");
+ if (!dest)
+ return;
+
+ _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack);
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c
index 554e0b0d18..3cadaba9f3 100644
--- a/src/mesa/main/queryobj.c
+++ b/src/mesa/main/queryobj.c
@@ -29,6 +29,10 @@
#include "imports.h"
#include "queryobj.h"
#include "mtypes.h"
+#include "glapi/dispatch.h"
+
+
+#if FEATURE_queryobj
/**
@@ -38,7 +42,7 @@
* \param id - the new object's ID
* \return pointer to new query_object object or NULL if out of memory.
*/
-struct gl_query_object *
+static struct gl_query_object *
_mesa_new_query_object(GLcontext *ctx, GLuint id)
{
struct gl_query_object *q = MALLOC_STRUCT(gl_query_object);
@@ -57,7 +61,7 @@ _mesa_new_query_object(GLcontext *ctx, GLuint id)
* Begin a query. Software driver fallback.
* Called via ctx->Driver.BeginQuery().
*/
-void
+static void
_mesa_begin_query(GLcontext *ctx, struct gl_query_object *q)
{
/* no-op */
@@ -68,7 +72,7 @@ _mesa_begin_query(GLcontext *ctx, struct gl_query_object *q)
* End a query. Software driver fallback.
* Called via ctx->Driver.EndQuery().
*/
-void
+static void
_mesa_end_query(GLcontext *ctx, struct gl_query_object *q)
{
q->Ready = GL_TRUE;
@@ -79,21 +83,35 @@ _mesa_end_query(GLcontext *ctx, struct gl_query_object *q)
* Wait for query to complete. Software driver fallback.
* Called via ctx->Driver.WaitQuery().
*/
-void
+static void
_mesa_wait_query(GLcontext *ctx, struct gl_query_object *q)
{
/* For software drivers, _mesa_end_query() should have completed the query.
- * For real hardware, implement a proper WaitQuery() driver function.
+ * For real hardware, implement a proper WaitQuery() driver function,
+ * which may require issuing a flush.
*/
assert(q->Ready);
}
/**
+ * Check if a query results are ready. Software driver fallback.
+ * Called via ctx->Driver.CheckQuery().
+ */
+static void
+_mesa_check_query(GLcontext *ctx, struct gl_query_object *q)
+{
+ /* No-op for sw rendering.
+ * HW drivers may need to flush at this time.
+ */
+}
+
+
+/**
* Delete a query object. Called via ctx->Driver.DeleteQuery().
* Not removed from hash table here.
*/
-void
+static void
_mesa_delete_query(GLcontext *ctx, struct gl_query_object *q)
{
_mesa_free(q);
@@ -109,6 +127,18 @@ lookup_query_object(GLcontext *ctx, GLuint id)
+void
+_mesa_init_query_object_functions(struct dd_function_table *driver)
+{
+ driver->NewQueryObject = _mesa_new_query_object;
+ driver->DeleteQuery = _mesa_delete_query;
+ driver->BeginQuery = _mesa_begin_query;
+ driver->EndQuery = _mesa_end_query;
+ driver->WaitQuery = _mesa_wait_query;
+ driver->CheckQuery = _mesa_check_query;
+}
+
+
void GLAPIENTRY
_mesa_GenQueriesARB(GLsizei n, GLuint *ids)
{
@@ -210,7 +240,6 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
return;
}
break;
-#if FEATURE_EXT_timer_query
case GL_TIME_ELAPSED_EXT:
if (!ctx->Extensions.EXT_timer_query) {
_mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
@@ -221,7 +250,6 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
return;
}
break;
-#endif
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
return;
@@ -259,11 +287,9 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
if (target == GL_SAMPLES_PASSED_ARB) {
ctx->Query.CurrentOcclusionObject = q;
}
-#if FEATURE_EXT_timer_query
else if (target == GL_TIME_ELAPSED_EXT) {
ctx->Query.CurrentTimerObject = q;
}
-#endif
ctx->Driver.BeginQuery(ctx, q);
}
@@ -287,7 +313,6 @@ _mesa_EndQueryARB(GLenum target)
q = ctx->Query.CurrentOcclusionObject;
ctx->Query.CurrentOcclusionObject = NULL;
break;
-#if FEATURE_EXT_timer_query
case GL_TIME_ELAPSED_EXT:
if (!ctx->Extensions.EXT_timer_query) {
_mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
@@ -296,7 +321,6 @@ _mesa_EndQueryARB(GLenum target)
q = ctx->Query.CurrentTimerObject;
ctx->Query.CurrentTimerObject = NULL;
break;
-#endif
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
return;
@@ -328,7 +352,6 @@ _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
}
q = ctx->Query.CurrentOcclusionObject;
break;
-#if FEATURE_EXT_timer_query
case GL_TIME_ELAPSED_EXT:
if (!ctx->Extensions.EXT_timer_query) {
_mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
@@ -336,7 +359,6 @@ _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
}
q = ctx->Query.CurrentTimerObject;
break;
-#endif
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)");
return;
@@ -436,8 +458,6 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
}
-#if FEATURE_EXT_timer_query
-
/**
* New with GL_EXT_timer_query
*/
@@ -511,19 +531,35 @@ _mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)
}
}
-#endif /* FEATURE_EXT_timer_query */
+
+void
+_mesa_init_queryobj_dispatch(struct _glapi_table *disp)
+{
+ SET_GenQueriesARB(disp, _mesa_GenQueriesARB);
+ SET_DeleteQueriesARB(disp, _mesa_DeleteQueriesARB);
+ SET_IsQueryARB(disp, _mesa_IsQueryARB);
+ SET_BeginQueryARB(disp, _mesa_BeginQueryARB);
+ SET_EndQueryARB(disp, _mesa_EndQueryARB);
+ SET_GetQueryivARB(disp, _mesa_GetQueryivARB);
+ SET_GetQueryObjectivARB(disp, _mesa_GetQueryObjectivARB);
+ SET_GetQueryObjectuivARB(disp, _mesa_GetQueryObjectuivARB);
+
+ SET_GetQueryObjecti64vEXT(disp, _mesa_GetQueryObjecti64vEXT);
+ SET_GetQueryObjectui64vEXT(disp, _mesa_GetQueryObjectui64vEXT);
+}
+
+
+#endif /* FEATURE_queryobj */
/**
* Allocate/init the context state related to query objects.
*/
void
-_mesa_init_query(GLcontext *ctx)
+_mesa_init_queryobj(GLcontext *ctx)
{
-#if FEATURE_ARB_occlusion_query
ctx->Query.QueryObjects = _mesa_NewHashTable();
ctx->Query.CurrentOcclusionObject = NULL;
-#endif
}
@@ -543,7 +579,7 @@ delete_queryobj_cb(GLuint id, void *data, void *userData)
* Free the context state related to query objects.
*/
void
-_mesa_free_query_data(GLcontext *ctx)
+_mesa_free_queryobj_data(GLcontext *ctx)
{
_mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx);
_mesa_DeleteHashTable(ctx->Query.QueryObjects);
diff --git a/src/mesa/main/queryobj.h b/src/mesa/main/queryobj.h
index 9a9774641b..861e6ba566 100644
--- a/src/mesa/main/queryobj.h
+++ b/src/mesa/main/queryobj.h
@@ -23,31 +23,24 @@
*/
-#ifndef OCCLUDE_H
-#define OCCLUDE_H
+#ifndef QUERYOBJ_H
+#define QUERYOBJ_H
-extern struct gl_query_object *
-_mesa_new_query_object(GLcontext *ctx, GLuint id);
+#include "main/mtypes.h"
-extern void
-_mesa_init_query(GLcontext *ctx);
-
-extern void
-_mesa_free_query_data(GLcontext *ctx);
-
-extern void
-_mesa_delete_query(GLcontext *ctx, struct gl_query_object *q);
-
-extern void
-_mesa_begin_query(GLcontext *ctx, struct gl_query_object *q);
-
-extern void
-_mesa_end_query(GLcontext *ctx, struct gl_query_object *q);
-extern void
-_mesa_wait_query(GLcontext *ctx, struct gl_query_object *q);
+#if FEATURE_queryobj
+#define _MESA_INIT_QUERYOBJ_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->NewQueryObject = impl ## NewQueryObject; \
+ (driver)->DeleteQuery = impl ## DeleteQuery; \
+ (driver)->BeginQuery = impl ## BeginQuery; \
+ (driver)->EndQuery = impl ## EndQuery; \
+ (driver)->WaitQuery = impl ## WaitQuery; \
+ (driver)->CheckQuery = impl ## CheckQuery; \
+ } while (0)
extern void GLAPIENTRY
_mesa_GenQueriesARB(GLsizei n, GLuint *ids);
@@ -79,5 +72,33 @@ _mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params);
extern void GLAPIENTRY
_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params);
+extern void
+_mesa_init_query_object_functions(struct dd_function_table *driver);
+
+extern void
+_mesa_init_queryobj_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_queryobj */
+
+#define _MESA_INIT_QUERYOBJ_FUNCTIONS(driver, impl) do { } while (0)
+
+static INLINE void
+_mesa_init_query_object_functions(struct dd_function_table *driver)
+{
+}
+
+static INLINE void
+_mesa_init_queryobj_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_queryobj */
+
+extern void
+_mesa_init_queryobj(GLcontext *ctx);
+
+extern void
+_mesa_free_queryobj_data(GLcontext *ctx);
+
-#endif /* OCCLUDE_H */
+#endif /* QUERYOBJ_H */
diff --git a/src/mesa/main/rastpos.c b/src/mesa/main/rastpos.c
index 9f309d6ab8..77eb84103f 100644
--- a/src/mesa/main/rastpos.c
+++ b/src/mesa/main/rastpos.c
@@ -34,6 +34,10 @@
#include "macros.h"
#include "rastpos.h"
#include "state.h"
+#include "glapi/dispatch.h"
+
+
+#if FEATURE_rastpos
/**
@@ -211,7 +215,7 @@ _mesa_RasterPos4sv(const GLshort *v)
/*** GL_ARB_window_pos / GL_MESA_window_pos ***/
/**********************************************************************/
-#if FEATURE_drawpix
+
/**
* All glWindowPosMESA and glWindowPosARB commands call this function to
* update the current raster position.
@@ -436,7 +440,6 @@ _mesa_WindowPos4svMESA(const GLshort *v)
window_pos4f(v[0], v[1], v[2], v[3]);
}
-#endif
#if 0
@@ -477,6 +480,65 @@ void glWindowPos4fMESA( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
#endif
+void
+_mesa_init_rastpos_dispatch(struct _glapi_table *disp)
+{
+ SET_RasterPos2f(disp, _mesa_RasterPos2f);
+ SET_RasterPos2fv(disp, _mesa_RasterPos2fv);
+ SET_RasterPos2i(disp, _mesa_RasterPos2i);
+ SET_RasterPos2iv(disp, _mesa_RasterPos2iv);
+ SET_RasterPos2d(disp, _mesa_RasterPos2d);
+ SET_RasterPos2dv(disp, _mesa_RasterPos2dv);
+ SET_RasterPos2s(disp, _mesa_RasterPos2s);
+ SET_RasterPos2sv(disp, _mesa_RasterPos2sv);
+ SET_RasterPos3d(disp, _mesa_RasterPos3d);
+ SET_RasterPos3dv(disp, _mesa_RasterPos3dv);
+ SET_RasterPos3f(disp, _mesa_RasterPos3f);
+ SET_RasterPos3fv(disp, _mesa_RasterPos3fv);
+ SET_RasterPos3i(disp, _mesa_RasterPos3i);
+ SET_RasterPos3iv(disp, _mesa_RasterPos3iv);
+ SET_RasterPos3s(disp, _mesa_RasterPos3s);
+ SET_RasterPos3sv(disp, _mesa_RasterPos3sv);
+ SET_RasterPos4d(disp, _mesa_RasterPos4d);
+ SET_RasterPos4dv(disp, _mesa_RasterPos4dv);
+ SET_RasterPos4f(disp, _mesa_RasterPos4f);
+ SET_RasterPos4fv(disp, _mesa_RasterPos4fv);
+ SET_RasterPos4i(disp, _mesa_RasterPos4i);
+ SET_RasterPos4iv(disp, _mesa_RasterPos4iv);
+ SET_RasterPos4s(disp, _mesa_RasterPos4s);
+ SET_RasterPos4sv(disp, _mesa_RasterPos4sv);
+
+ /* 197. GL_MESA_window_pos */
+ SET_WindowPos2dMESA(disp, _mesa_WindowPos2dMESA);
+ SET_WindowPos2dvMESA(disp, _mesa_WindowPos2dvMESA);
+ SET_WindowPos2fMESA(disp, _mesa_WindowPos2fMESA);
+ SET_WindowPos2fvMESA(disp, _mesa_WindowPos2fvMESA);
+ SET_WindowPos2iMESA(disp, _mesa_WindowPos2iMESA);
+ SET_WindowPos2ivMESA(disp, _mesa_WindowPos2ivMESA);
+ SET_WindowPos2sMESA(disp, _mesa_WindowPos2sMESA);
+ SET_WindowPos2svMESA(disp, _mesa_WindowPos2svMESA);
+ SET_WindowPos3dMESA(disp, _mesa_WindowPos3dMESA);
+ SET_WindowPos3dvMESA(disp, _mesa_WindowPos3dvMESA);
+ SET_WindowPos3fMESA(disp, _mesa_WindowPos3fMESA);
+ SET_WindowPos3fvMESA(disp, _mesa_WindowPos3fvMESA);
+ SET_WindowPos3iMESA(disp, _mesa_WindowPos3iMESA);
+ SET_WindowPos3ivMESA(disp, _mesa_WindowPos3ivMESA);
+ SET_WindowPos3sMESA(disp, _mesa_WindowPos3sMESA);
+ SET_WindowPos3svMESA(disp, _mesa_WindowPos3svMESA);
+ SET_WindowPos4dMESA(disp, _mesa_WindowPos4dMESA);
+ SET_WindowPos4dvMESA(disp, _mesa_WindowPos4dvMESA);
+ SET_WindowPos4fMESA(disp, _mesa_WindowPos4fMESA);
+ SET_WindowPos4fvMESA(disp, _mesa_WindowPos4fvMESA);
+ SET_WindowPos4iMESA(disp, _mesa_WindowPos4iMESA);
+ SET_WindowPos4ivMESA(disp, _mesa_WindowPos4ivMESA);
+ SET_WindowPos4sMESA(disp, _mesa_WindowPos4sMESA);
+ SET_WindowPos4svMESA(disp, _mesa_WindowPos4svMESA);
+}
+
+
+#endif /* FEATURE_rastpos */
+
+
/**********************************************************************/
/** \name Initialization */
/**********************************************************************/
diff --git a/src/mesa/main/rastpos.h b/src/mesa/main/rastpos.h
index 363f86ad87..767d6f2677 100644
--- a/src/mesa/main/rastpos.h
+++ b/src/mesa/main/rastpos.h
@@ -32,9 +32,16 @@
#define RASTPOS_H
-#include "glheader.h"
+#include "main/mtypes.h"
+#if FEATURE_rastpos
+
+#define _MESA_INIT_RASTPOS_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->RasterPos = impl ## RasterPos; \
+ } while (0)
+
extern void GLAPIENTRY
_mesa_RasterPos2d(GLdouble x, GLdouble y);
@@ -186,8 +193,22 @@ extern void GLAPIENTRY
_mesa_WindowPos4svMESA(const GLshort *v);
extern void
-_mesa_init_rastpos( GLcontext * ctx );
+_mesa_init_rastpos_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_rastpos */
+
+#define _MESA_INIT_RASTPOS_FUNCTIONS(driver, impl) do { } while (0)
+
+static INLINE void
+_mesa_init_rastpos_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_rastpos */
+
+extern void
+_mesa_init_rastpos(GLcontext *ctx);
/*@}*/
-#endif
+#endif /* RASTPOS_H */
diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c
index dfdd297b6e..feea1d375f 100644
--- a/src/mesa/main/readpix.c
+++ b/src/mesa/main/readpix.c
@@ -44,6 +44,10 @@ _mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
GLboolean drawing)
{
const char *readDraw = drawing ? "Draw" : "Read";
+ const GLboolean reading = !drawing;
+
+ /* state validation should have already been done */
+ ASSERT(ctx->NewState == 0x0);
if (ctx->Extensions.EXT_packed_depth_stencil
&& type == GL_UNSIGNED_INT_24_8_EXT
@@ -73,32 +77,45 @@ _mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
case GL_RGBA:
case GL_BGRA:
case GL_ABGR_EXT:
- if (drawing && !ctx->Visual.rgbMode) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
+ if (drawing) {
+ if (!ctx->DrawBuffer->Visual.rgbMode) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
"glDrawPixels(drawing RGB pixels into color index buffer)");
- return GL_TRUE;
+ return GL_TRUE;
+ }
}
- if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadPixels(no color buffer)");
- return GL_TRUE;
+ else {
+ /* reading */
+ if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(no color buffer)");
+ return GL_TRUE;
+ }
}
break;
case GL_COLOR_INDEX:
- if (!drawing && ctx->Visual.rgbMode) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadPixels(reading color index format from RGB buffer)");
- return GL_TRUE;
+ if (drawing) {
+ if (ctx->DrawBuffer->Visual.rgbMode &&
+ (ctx->PixelMaps.ItoR.Size == 0 ||
+ ctx->PixelMaps.ItoG.Size == 0 ||
+ ctx->PixelMaps.ItoB.Size == 0)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(drawing color index pixels into RGB buffer)");
+ return GL_TRUE;
+ }
}
- if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glReadPixels(no color buffer)");
- return GL_TRUE;
+ else {
+ /* reading */
+ if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(no color buffer)");
+ return GL_TRUE;
+ }
}
break;
case GL_STENCIL_INDEX:
if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
- (!drawing && !_mesa_source_buffer_exists(ctx, format))) {
+ (reading && !_mesa_source_buffer_exists(ctx, format))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"gl%sPixels(no stencil buffer)", readDraw);
return GL_TRUE;
@@ -118,7 +135,7 @@ _mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
return GL_TRUE;
}
if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
- (!drawing && !_mesa_source_buffer_exists(ctx, format))) {
+ (reading && !_mesa_source_buffer_exists(ctx, format))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"gl%sPixels(no depth or stencil buffer)", readDraw);
return GL_TRUE;
@@ -170,7 +187,10 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
return;
}
- if (ctx->Pack.BufferObj->Name) {
+ if (width == 0 || height == 0)
+ return; /* nothing to do */
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
format, type, pixels)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
@@ -178,7 +198,7 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
return;
}
- if (ctx->Pack.BufferObj->Pointer) {
+ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
/* buffer is mapped - that's an error */
_mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
return;
diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c
index 6f1d7c3960..38be8266e0 100644
--- a/src/mesa/main/renderbuffer.c
+++ b/src/mesa/main/renderbuffer.c
@@ -1199,7 +1199,8 @@ _mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
if (width > 0 && height > 0) {
/* allocate new buffer storage */
- rb->Data = _mesa_malloc(width * height * pixelSize);
+ rb->Data = malloc(width * height * pixelSize);
+
if (rb->Data == NULL) {
rb->Width = 0;
rb->Height = 0;
@@ -1487,11 +1488,16 @@ _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
rb->InternalFormat = GL_NONE;
rb->_ActualFormat = GL_NONE;
rb->_BaseFormat = GL_NONE;
- rb->DataType = GL_NONE;
+
+ rb->ComponentType = GL_UNSIGNED_NORMALIZED; /* ARB_fbo */
+ rb->ColorEncoding = GL_LINEAR; /* ARB_fbo */
+
rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0;
rb->IndexBits = 0;
rb->DepthBits = 0;
rb->StencilBits = 0;
+
+ rb->DataType = GL_NONE;
rb->Data = NULL;
/* Point back to ourself so that we don't have to check for Wrapped==NULL
diff --git a/src/mesa/main/shaders.c b/src/mesa/main/shaders.c
index 7491d00c35..bc76b91291 100644
--- a/src/mesa/main/shaders.c
+++ b/src/mesa/main/shaders.c
@@ -374,6 +374,43 @@ _mesa_LinkProgramARB(GLhandleARB programObj)
}
+
+/**
+ * Read shader source code from a file.
+ * Useful for debugging to override an app's shader.
+ */
+static GLcharARB *
+_mesa_read_shader(const char *fname)
+{
+ const int max = 50*1000;
+ FILE *f = fopen(fname, "r");
+ GLcharARB *buffer, *shader;
+ int len;
+
+ if (!f) {
+ _mesa_fprintf(stderr, "Unable to open shader file %s\n", fname);
+ return NULL;
+ }
+
+ buffer = (char *) malloc(max);
+ len = fread(buffer, 1, max, f);
+ buffer[len] = 0;
+
+ fclose(f);
+
+ shader = _mesa_strdup(buffer);
+ free(buffer);
+
+ if (0) {
+ _mesa_fprintf(stderr, "Read shader %s:\n", fname);
+ _mesa_fprintf(stderr, "%s\n", shader);
+ }
+
+ return shader;
+}
+
+
+
/**
* Called via glShaderSource() and glShaderSourceARB() API functions.
* Basically, concatenate the source code strings into one long string
@@ -438,6 +475,20 @@ _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count,
source[totalLength - 1] = '\0';
source[totalLength - 2] = '\0';
+#if 0
+ if (0) {
+ GLcharARB *newSource;
+
+ newSource = _mesa_read_shader("newshader.frag");
+ if (newSource) {
+ _mesa_free(source);
+ source = newSource;
+ }
+ }
+#else
+ (void) _mesa_read_shader;
+#endif
+
ctx->Driver.ShaderSource(ctx, shaderObj, source);
_mesa_free(offsets);
@@ -587,8 +638,7 @@ _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
const GLfloat * value)
{
GET_CURRENT_CONTEXT(ctx);
- ctx->Driver.UniformMatrix(ctx, 2, 2, GL_FLOAT_MAT2,
- location, count, transpose, value);
+ ctx->Driver.UniformMatrix(ctx, 2, 2, location, count, transpose, value);
}
void GLAPIENTRY
@@ -596,8 +646,7 @@ _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
const GLfloat * value)
{
GET_CURRENT_CONTEXT(ctx);
- ctx->Driver.UniformMatrix(ctx, 3, 3, GL_FLOAT_MAT3,
- location, count, transpose, value);
+ ctx->Driver.UniformMatrix(ctx, 3, 3, location, count, transpose, value);
}
void GLAPIENTRY
@@ -605,8 +654,7 @@ _mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
const GLfloat * value)
{
GET_CURRENT_CONTEXT(ctx);
- ctx->Driver.UniformMatrix(ctx, 4, 4, GL_FLOAT_MAT4,
- location, count, transpose, value);
+ ctx->Driver.UniformMatrix(ctx, 4, 4, location, count, transpose, value);
}
@@ -618,8 +666,7 @@ _mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat *value)
{
GET_CURRENT_CONTEXT(ctx);
- ctx->Driver.UniformMatrix(ctx, 2, 3, GL_FLOAT_MAT2x3,
- location, count, transpose, value);
+ ctx->Driver.UniformMatrix(ctx, 2, 3, location, count, transpose, value);
}
void GLAPIENTRY
@@ -627,8 +674,7 @@ _mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat *value)
{
GET_CURRENT_CONTEXT(ctx);
- ctx->Driver.UniformMatrix(ctx, 3, 2, GL_FLOAT_MAT3x2,
- location, count, transpose, value);
+ ctx->Driver.UniformMatrix(ctx, 3, 2, location, count, transpose, value);
}
void GLAPIENTRY
@@ -636,8 +682,7 @@ _mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat *value)
{
GET_CURRENT_CONTEXT(ctx);
- ctx->Driver.UniformMatrix(ctx, 2, 4, GL_FLOAT_MAT2x4,
- location, count, transpose, value);
+ ctx->Driver.UniformMatrix(ctx, 2, 4, location, count, transpose, value);
}
void GLAPIENTRY
@@ -645,8 +690,7 @@ _mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat *value)
{
GET_CURRENT_CONTEXT(ctx);
- ctx->Driver.UniformMatrix(ctx, 4, 2, GL_FLOAT_MAT4x2,
- location, count, transpose, value);
+ ctx->Driver.UniformMatrix(ctx, 4, 2, location, count, transpose, value);
}
void GLAPIENTRY
@@ -654,8 +698,7 @@ _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat *value)
{
GET_CURRENT_CONTEXT(ctx);
- ctx->Driver.UniformMatrix(ctx, 3, 4, GL_FLOAT_MAT3x4,
- location, count, transpose, value);
+ ctx->Driver.UniformMatrix(ctx, 3, 4, location, count, transpose, value);
}
void GLAPIENTRY
@@ -663,8 +706,7 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat *value)
{
GET_CURRENT_CONTEXT(ctx);
- ctx->Driver.UniformMatrix(ctx, 4, 3, GL_FLOAT_MAT4x3,
- location, count, transpose, value);
+ ctx->Driver.UniformMatrix(ctx, 4, 3, location, count, transpose, value);
}
diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
new file mode 100644
index 0000000000..4d01e8abc6
--- /dev/null
+++ b/src/mesa/main/shared.c
@@ -0,0 +1,370 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file shared.c
+ * Shared-context state
+ */
+
+
+
+#include "imports.h"
+#include "mtypes.h"
+#include "hash.h"
+#include "arrayobj.h"
+#include "bufferobj.h"
+#include "shared.h"
+#include "shader/program.h"
+#include "shader/shader_api.h"
+#include "dlist.h"
+#if FEATURE_ATI_fragment_shader
+#include "shader/atifragshader.h"
+#endif
+#if FEATURE_ARB_sync
+#include "syncobj.h"
+#endif
+
+/**
+ * Allocate and initialize a shared context state structure.
+ * Initializes the display list, texture objects and vertex programs hash
+ * tables, allocates the texture objects. If it runs out of memory, frees
+ * everything already allocated before returning NULL.
+ *
+ * \return pointer to a gl_shared_state structure on success, or NULL on
+ * failure.
+ */
+struct gl_shared_state *
+_mesa_alloc_shared_state(GLcontext *ctx)
+{
+ struct gl_shared_state *shared;
+ GLuint i;
+
+ shared = CALLOC_STRUCT(gl_shared_state);
+ if (!shared)
+ return NULL;
+
+ _glthread_INIT_MUTEX(shared->Mutex);
+
+ shared->DisplayList = _mesa_NewHashTable();
+ shared->TexObjects = _mesa_NewHashTable();
+ shared->Programs = _mesa_NewHashTable();
+
+#if FEATURE_ARB_vertex_program
+ shared->DefaultVertexProgram = (struct gl_vertex_program *)
+ ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+#endif
+
+#if FEATURE_ARB_fragment_program
+ shared->DefaultFragmentProgram = (struct gl_fragment_program *)
+ ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+#endif
+
+#if FEATURE_ATI_fragment_shader
+ shared->ATIShaders = _mesa_NewHashTable();
+ shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0);
+#endif
+
+#if FEATURE_ARB_shader_objects
+ shared->ShaderObjects = _mesa_NewHashTable();
+#endif
+
+#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
+ shared->BufferObjects = _mesa_NewHashTable();
+#endif
+
+ /* Allocate the default buffer object and set refcount so high that
+ * it never gets deleted.
+ * XXX with recent/improved refcounting this may not longer be needed.
+ */
+ shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0);
+ shared->NullBufferObj->RefCount = 1000 * 1000 * 1000;
+
+ /* Create default texture objects */
+ for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
+ /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */
+ static const GLenum targets[NUM_TEXTURE_TARGETS] = {
+ GL_TEXTURE_2D_ARRAY_EXT,
+ GL_TEXTURE_1D_ARRAY_EXT,
+ GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_3D,
+ GL_TEXTURE_RECTANGLE_NV,
+ GL_TEXTURE_2D,
+ GL_TEXTURE_1D
+ };
+ shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]);
+ }
+
+ /* sanity check */
+ assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1);
+
+ /* Mutex and timestamp for texobj state validation */
+ _glthread_INIT_MUTEX(shared->TexMutex);
+ shared->TextureStateStamp = 0;
+
+#if FEATURE_EXT_framebuffer_object
+ shared->FrameBuffers = _mesa_NewHashTable();
+ shared->RenderBuffers = _mesa_NewHashTable();
+#endif
+
+#if FEATURE_ARB_sync
+ make_empty_list(& shared->SyncObjects);
+#endif
+
+ return shared;
+}
+
+
+/**
+ * Callback for deleting a display list. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_displaylist_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_display_list *list = (struct gl_display_list *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ _mesa_delete_list(ctx, list);
+}
+
+
+/**
+ * Callback for deleting a texture object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_texture_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_texture_object *texObj = (struct gl_texture_object *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ ctx->Driver.DeleteTexture(ctx, texObj);
+}
+
+
+/**
+ * Callback for deleting a program object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_program_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_program *prog = (struct gl_program *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ if(prog != &_mesa_DummyProgram) {
+ ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */
+ prog->RefCount = 0; /* now going away */
+ ctx->Driver.DeleteProgram(ctx, prog);
+ }
+}
+
+
+#if FEATURE_ATI_fragment_shader
+/**
+ * Callback for deleting an ATI fragment shader object.
+ * Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_fragshader_cb(GLuint id, void *data, void *userData)
+{
+ struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ _mesa_delete_ati_fragment_shader(ctx, shader);
+}
+#endif
+
+
+/**
+ * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_bufferobj_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
+ bufObj->Pointer = NULL;
+ }
+ ctx->Driver.DeleteBuffer(ctx, bufObj);
+}
+
+
+/**
+ * Callback for freeing shader program data. Call it before delete_shader_cb
+ * to avoid memory access error.
+ */
+static void
+free_shader_program_data_cb(GLuint id, void *data, void *userData)
+{
+ GLcontext *ctx = (GLcontext *) userData;
+ struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+
+ if (shProg->Type == GL_SHADER_PROGRAM_MESA) {
+ _mesa_free_shader_program_data(ctx, shProg);
+ }
+}
+
+
+/**
+ * Callback for deleting shader and shader programs objects.
+ * Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_shader_cb(GLuint id, void *data, void *userData)
+{
+ GLcontext *ctx = (GLcontext *) userData;
+ struct gl_shader *sh = (struct gl_shader *) data;
+ if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) {
+ _mesa_free_shader(ctx, sh);
+ }
+ else {
+ struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+ ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA);
+ _mesa_free_shader_program(ctx, shProg);
+ }
+}
+
+
+/**
+ * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll()
+ */
+static void
+delete_framebuffer_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
+ /* The fact that the framebuffer is in the hashtable means its refcount
+ * is one, but we're removing from the hashtable now. So clear refcount.
+ */
+ /*assert(fb->RefCount == 1);*/
+ fb->RefCount = 0;
+
+ /* NOTE: Delete should always be defined but there are two reports
+ * of it being NULL (bugs 13507, 14293). Work-around for now.
+ */
+ if (fb->Delete)
+ fb->Delete(fb);
+}
+
+
+/**
+ * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll()
+ */
+static void
+delete_renderbuffer_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data;
+ rb->RefCount = 0; /* see comment for FBOs above */
+ if (rb->Delete)
+ rb->Delete(rb);
+}
+
+
+/**
+ * Deallocate a shared state object and all children structures.
+ *
+ * \param ctx GL context.
+ * \param shared shared state pointer.
+ *
+ * Frees the display lists, the texture objects (calling the driver texture
+ * deletion callback to free its private data) and the vertex programs, as well
+ * as their hash tables.
+ *
+ * \sa alloc_shared_state().
+ */
+void
+_mesa_free_shared_state(GLcontext *ctx, struct gl_shared_state *shared)
+{
+ GLuint i;
+
+ /*
+ * Free display lists
+ */
+ _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx);
+ _mesa_DeleteHashTable(shared->DisplayList);
+
+#if FEATURE_ARB_shader_objects
+ _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx);
+ _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx);
+ _mesa_DeleteHashTable(shared->ShaderObjects);
+#endif
+
+ _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx);
+ _mesa_DeleteHashTable(shared->Programs);
+
+#if FEATURE_ARB_vertex_program
+ _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL);
+#endif
+
+#if FEATURE_ARB_fragment_program
+ _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL);
+#endif
+
+#if FEATURE_ATI_fragment_shader
+ _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx);
+ _mesa_DeleteHashTable(shared->ATIShaders);
+ _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader);
+#endif
+
+#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
+ _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx);
+ _mesa_DeleteHashTable(shared->BufferObjects);
+#endif
+
+#if FEATURE_EXT_framebuffer_object
+ _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx);
+ _mesa_DeleteHashTable(shared->FrameBuffers);
+ _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx);
+ _mesa_DeleteHashTable(shared->RenderBuffers);
+#endif
+
+#if FEATURE_ARB_vertex_buffer_object
+ ctx->Driver.DeleteBuffer(ctx, shared->NullBufferObj);
+#endif
+
+#if FEATURE_ARB_sync
+ {
+ struct simple_node *node;
+ struct simple_node *temp;
+
+ foreach_s(node, temp, & shared->SyncObjects) {
+ _mesa_unref_sync_object(ctx, (struct gl_sync_object *) node);
+ }
+ }
+#endif
+
+ /*
+ * Free texture objects (after FBOs since some textures might have
+ * been bound to FBOs).
+ */
+ ASSERT(ctx->Driver.DeleteTexture);
+ /* the default textures */
+ for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
+ ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]);
+ }
+
+ /* all other textures */
+ _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
+ _mesa_DeleteHashTable(shared->TexObjects);
+
+ _glthread_DESTROY_MUTEX(shared->Mutex);
+ _glthread_DESTROY_MUTEX(shared->TexMutex);
+
+ _mesa_free(shared);
+}
diff --git a/src/mesa/x86/x86.h b/src/mesa/main/shared.h
index 97651ec6ee..e59177e968 100644
--- a/src/mesa/x86/x86.h
+++ b/src/mesa/main/shared.h
@@ -1,9 +1,8 @@
-
/*
* Mesa 3-D graphics library
- * Version: 3.5
+ * Version: 7.5
*
- * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -23,13 +22,16 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-/*
- * Intel x86 assembly code by Josh Vanderhoof
- */
+#ifndef SHARED_H
+#define SHARED_H
+
+
+struct gl_shared_state *
+_mesa_alloc_shared_state(GLcontext *ctx);
+
-#ifndef __X86_H__
-#define __X86_H__
+void
+_mesa_free_shared_state(GLcontext *ctx, struct gl_shared_state *shared);
-extern void _mesa_init_x86_transform_asm( void );
#endif
diff --git a/src/mesa/main/simple_list.h b/src/mesa/main/simple_list.h
index 63475f6f74..ff7f888238 100644
--- a/src/mesa/main/simple_list.h
+++ b/src/mesa/main/simple_list.h
@@ -37,6 +37,11 @@
#ifndef _SIMPLE_LIST_H
#define _SIMPLE_LIST_H
+struct simple_node {
+ struct simple_node *next;
+ struct simple_node *prev;
+};
+
/**
* Remove an element from list.
*
diff --git a/src/mesa/main/sources b/src/mesa/main/sources
index 1b43e7e00f..5d9d99040e 100644
--- a/src/mesa/main/sources
+++ b/src/mesa/main/sources
@@ -63,6 +63,7 @@ texenv.c \
texenvprogram.c \
texformat.c \
texgen.c \
+texgetimage.c \
teximage.c \
texobj.c \
texparam.c \
@@ -79,7 +80,6 @@ vsnprintf.c
MESA_MAIN_HEADERS = \
accum.h \
api_arrayelt.h \
-api_eval.h \
api_exec.h \
api_loopback.h \
api_noop.h \
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index 6fe54c753f..f10e6b04b7 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.3
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
@@ -40,15 +40,15 @@
#include "framebuffer.h"
#include "light.h"
#include "matrix.h"
-#if FEATURE_pixel_transfer
#include "pixel.h"
-#endif
#include "shader/program.h"
+#include "shader/prog_parameter.h"
#include "state.h"
#include "stencil.h"
#include "texenvprogram.h"
#include "texobj.h"
#include "texstate.h"
+#include "viewport.h"
static void
@@ -62,124 +62,172 @@ update_separate_specular(GLcontext *ctx)
/**
- * Update state dependent on vertex arrays.
+ * Compute the index of the last array element that can be safely accessed
+ * in a vertex array. We can really only do this when the array lives in
+ * a VBO.
+ * The array->_MaxElement field will be updated.
+ * Later in glDrawArrays/Elements/etc we can do some bounds checking.
+ */
+static void
+compute_max_element(struct gl_client_array *array)
+{
+ assert(array->Enabled);
+ if (array->BufferObj->Name) {
+ GLsizeiptrARB offset = (GLsizeiptrARB) array->Ptr;
+ GLsizeiptrARB obj_size = (GLsizeiptrARB) array->BufferObj->Size;
+
+ if (offset < obj_size) {
+ array->_MaxElement = (obj_size - offset +
+ array->StrideB -
+ array->_ElementSize) / array->StrideB;
+ } else {
+ array->_MaxElement = 0;
+ }
+ /* Compute the max element we can access in the VBO without going
+ * out of bounds.
+ */
+ array->_MaxElement = ((GLsizeiptrARB) array->BufferObj->Size
+ - (GLsizeiptrARB) array->Ptr + array->StrideB
+ - array->_ElementSize) / array->StrideB;
+ }
+ else {
+ /* user-space array, no idea how big it is */
+ array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */
+ }
+}
+
+
+/**
+ * Helper for update_arrays().
+ * \return min(current min, array->_MaxElement).
+ */
+static GLuint
+update_min(GLuint min, struct gl_client_array *array)
+{
+ compute_max_element(array);
+ return MIN2(min, array->_MaxElement);
+}
+
+
+/**
+ * Update ctx->Array._MaxElement (the max legal index into all enabled arrays).
+ * Need to do this upon new array state or new buffer object state.
*/
static void
update_arrays( GLcontext *ctx )
{
- GLuint i, min;
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint i, min = ~0;
/* find min of _MaxElement values for all enabled arrays */
/* 0 */
if (ctx->VertexProgram._Current
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) {
- min = ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS]._MaxElement;
- }
- else if (ctx->Array.ArrayObj->Vertex.Enabled) {
- min = ctx->Array.ArrayObj->Vertex._MaxElement;
+ && arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]);
}
- else {
- /* can't draw anything without vertex positions! */
- min = 0;
+ else if (arrayObj->Vertex.Enabled) {
+ min = update_min(min, &arrayObj->Vertex);
}
/* 1 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]);
}
/* no conventional vertex weight array */
/* 2 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]);
}
- else if (ctx->Array.ArrayObj->Normal.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->Normal._MaxElement);
+ else if (arrayObj->Normal.Enabled) {
+ min = update_min(min, &arrayObj->Normal);
}
/* 3 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]);
}
- else if (ctx->Array.ArrayObj->Color.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->Color._MaxElement);
+ else if (arrayObj->Color.Enabled) {
+ min = update_min(min, &arrayObj->Color);
}
/* 4 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]);
}
- else if (ctx->Array.ArrayObj->SecondaryColor.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->SecondaryColor._MaxElement);
+ else if (arrayObj->SecondaryColor.Enabled) {
+ min = update_min(min, &arrayObj->SecondaryColor);
}
/* 5 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]);
}
- else if (ctx->Array.ArrayObj->FogCoord.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->FogCoord._MaxElement);
+ else if (arrayObj->FogCoord.Enabled) {
+ min = update_min(min, &arrayObj->FogCoord);
}
/* 6 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]);
}
- else if (ctx->Array.ArrayObj->Index.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->Index._MaxElement);
+ else if (arrayObj->Index.Enabled) {
+ min = update_min(min, &arrayObj->Index);
}
-
/* 7 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]);
}
/* 8..15 */
for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) {
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[i].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[i]._MaxElement);
+ && arrayObj->VertexAttrib[i].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[i]);
}
else if (i - VERT_ATTRIB_TEX0 < ctx->Const.MaxTextureCoordUnits
- && ctx->Array.ArrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->TexCoord[i - VERT_ATTRIB_TEX0]._MaxElement);
+ && arrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) {
+ min = update_min(min, &arrayObj->TexCoord[i - VERT_ATTRIB_TEX0]);
}
}
/* 16..31 */
if (ctx->VertexProgram._Current) {
- for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
- if (ctx->Array.ArrayObj->VertexAttrib[i].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[i]._MaxElement);
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
+ if (arrayObj->VertexAttrib[i].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[i]);
}
}
}
- if (ctx->Array.ArrayObj->EdgeFlag.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->EdgeFlag._MaxElement);
+ if (arrayObj->EdgeFlag.Enabled) {
+ min = update_min(min, &arrayObj->EdgeFlag);
}
/* _MaxElement is one past the last legal array element */
- ctx->Array._MaxElement = min;
+ arrayObj->_MaxElement = min;
}
+/**
+ * Update the following fields:
+ * ctx->VertexProgram._Enabled
+ * ctx->FragmentProgram._Enabled
+ * ctx->ATIFragmentShader._Enabled
+ * This needs to be done before texture state validation.
+ */
static void
-update_program(GLcontext *ctx)
+update_program_enables(GLcontext *ctx)
{
- const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
- const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
- const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
-
/* These _Enabled flags indicate if the program is enabled AND valid. */
ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled
&& ctx->VertexProgram.Current->Base.Instructions;
@@ -187,6 +235,29 @@ update_program(GLcontext *ctx)
&& ctx->FragmentProgram.Current->Base.Instructions;
ctx->ATIFragmentShader._Enabled = ctx->ATIFragmentShader.Enabled
&& ctx->ATIFragmentShader.Current->Instructions[0];
+}
+
+
+/**
+ * Update vertex/fragment program state. In particular, update these fields:
+ * ctx->VertexProgram._Current
+ * ctx->VertexProgram._TnlProgram,
+ * These point to the highest priority enabled vertex/fragment program or are
+ * NULL if fixed-function processing is to be done.
+ *
+ * This function needs to be called after texture state validation in case
+ * we're generating a fragment program from fixed-function texture state.
+ *
+ * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex
+ * or fragment program is being used.
+ */
+static GLbitfield
+update_program(GLcontext *ctx)
+{
+ const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
+ const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
+ GLbitfield new_state = 0x0;
/*
* Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current
@@ -256,18 +327,56 @@ update_program(GLcontext *ctx)
/* Let the driver know what's happening:
*/
- if (ctx->FragmentProgram._Current != prevFP && ctx->Driver.BindProgram) {
- ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
- (struct gl_program *) ctx->FragmentProgram._Current);
+ if (ctx->FragmentProgram._Current != prevFP) {
+ new_state |= _NEW_PROGRAM;
+ if (ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ (struct gl_program *) ctx->FragmentProgram._Current);
+ }
}
- if (ctx->VertexProgram._Current != prevVP && ctx->Driver.BindProgram) {
- ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
- (struct gl_program *) ctx->VertexProgram._Current);
+ if (ctx->VertexProgram._Current != prevVP) {
+ new_state |= _NEW_PROGRAM;
+ if (ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
+ (struct gl_program *) ctx->VertexProgram._Current);
+ }
}
+
+ return new_state;
}
+/**
+ * Examine shader constants and return either _NEW_PROGRAM_CONSTANTS or 0.
+ */
+static GLbitfield
+update_program_constants(GLcontext *ctx)
+{
+ GLbitfield new_state = 0x0;
+
+ if (ctx->FragmentProgram._Current) {
+ const struct gl_program_parameter_list *params =
+ ctx->FragmentProgram._Current->Base.Parameters;
+ if (params && params->StateFlags & ctx->NewState) {
+ new_state |= _NEW_PROGRAM_CONSTANTS;
+ }
+ }
+
+ if (ctx->VertexProgram._Current) {
+ const struct gl_program_parameter_list *params =
+ ctx->VertexProgram._Current->Base.Parameters;
+ if (params && params->StateFlags & ctx->NewState) {
+ new_state |= _NEW_PROGRAM_CONSTANTS;
+ }
+ }
+
+ return new_state;
+}
+
+
+
+
static void
update_viewport_matrix(GLcontext *ctx)
{
@@ -425,17 +534,41 @@ _mesa_update_state_locked( GLcontext *ctx )
{
GLbitfield new_state = ctx->NewState;
GLbitfield prog_flags = _NEW_PROGRAM;
+ GLbitfield new_prog_state = 0x0;
+
+ if (new_state == _NEW_CURRENT_ATTRIB)
+ goto out;
if (MESA_VERBOSE & VERBOSE_STATE)
_mesa_print_state("_mesa_update_state", new_state);
+ /* Determine which state flags effect vertex/fragment program state */
+ if (ctx->FragmentProgram._MaintainTexEnvProgram) {
+ prog_flags |= (_NEW_TEXTURE | _NEW_FOG |
+ _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE |
+ _NEW_PROGRAM);
+ }
+ if (ctx->VertexProgram._MaintainTnlProgram) {
+ prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX |
+ _NEW_TRANSFORM | _NEW_POINT |
+ _NEW_FOG | _NEW_LIGHT |
+ _MESA_NEW_NEED_EYE_COORDS);
+ }
+
+ /*
+ * Now update derived state info
+ */
+
+ if (new_state & prog_flags)
+ update_program_enables( ctx );
+
if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
_mesa_update_modelview_project( ctx, new_state );
if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX))
_mesa_update_texture( ctx, new_state );
- if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL))
+ if (new_state & _NEW_BUFFERS)
_mesa_update_framebuffer(ctx);
if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
@@ -447,18 +580,16 @@ _mesa_update_state_locked( GLcontext *ctx )
if (new_state & _NEW_LIGHT)
_mesa_update_lighting( ctx );
- if (new_state & _NEW_STENCIL)
+ if (new_state & (_NEW_STENCIL | _NEW_BUFFERS))
_mesa_update_stencil( ctx );
-#if FEATURE_pixel_transfer
- if (new_state & _IMAGE_NEW_TRANSFER_STATE)
+ if (new_state & _MESA_NEW_TRANSFER_STATE)
_mesa_update_pixel( ctx, new_state );
-#endif
if (new_state & _DD_NEW_SEPARATE_SPECULAR)
update_separate_specular( ctx );
- if (new_state & (_NEW_ARRAY | _NEW_PROGRAM))
+ if (new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT))
update_arrays( ctx );
if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT))
@@ -488,19 +619,17 @@ _mesa_update_state_locked( GLcontext *ctx )
if (new_state & _MESA_NEW_NEED_EYE_COORDS)
_mesa_update_tnl_spaces( ctx, new_state );
- if (ctx->FragmentProgram._MaintainTexEnvProgram) {
- prog_flags |= (_NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR);
- }
- if (ctx->VertexProgram._MaintainTnlProgram) {
- prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX |
- _NEW_TRANSFORM | _NEW_POINT |
- _NEW_FOG | _NEW_LIGHT |
- _MESA_NEW_NEED_EYE_COORDS);
+ if (new_state & prog_flags) {
+ /* When we generate programs from fixed-function vertex/fragment state
+ * this call may generate/bind a new program. If so, we need to
+ * propogate the _NEW_PROGRAM flag to the driver.
+ */
+ new_prog_state |= update_program( ctx );
}
- if (new_state & prog_flags)
- update_program( ctx );
+ out:
+ new_prog_state |= update_program_constants(ctx);
/*
* Give the driver a chance to act upon the new_state flags.
@@ -511,7 +640,7 @@ _mesa_update_state_locked( GLcontext *ctx )
* Set ctx->NewState to zero to avoid recursion if
* Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?)
*/
- new_state = ctx->NewState;
+ new_state = ctx->NewState | new_prog_state;
ctx->NewState = 0;
ctx->Driver.UpdateState(ctx, new_state);
ctx->Array.NewState = 0;
@@ -527,3 +656,59 @@ _mesa_update_state( GLcontext *ctx )
_mesa_update_state_locked(ctx);
_mesa_unlock_context_textures(ctx);
}
+
+
+
+
+/**
+ * Want to figure out which fragment program inputs are actually
+ * constant/current values from ctx->Current. These should be
+ * referenced as a tracked state variable rather than a fragment
+ * program input, to save the overhead of putting a constant value in
+ * every submitted vertex, transferring it to hardware, interpolating
+ * it across the triangle, etc...
+ *
+ * When there is a VP bound, just use vp->outputs. But when we're
+ * generating vp from fixed function state, basically want to
+ * calculate:
+ *
+ * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) |
+ * potential_vp_outputs )
+ *
+ * Where potential_vp_outputs is calculated by looking at enabled
+ * texgen, etc.
+ *
+ * The generated fragment program should then only declare inputs that
+ * may vary or otherwise differ from the ctx->Current values.
+ * Otherwise, the fp should track them as state values instead.
+ */
+void
+_mesa_set_varying_vp_inputs( GLcontext *ctx,
+ GLbitfield varying_inputs )
+{
+ if (ctx->varying_vp_inputs != varying_inputs) {
+ ctx->varying_vp_inputs = varying_inputs;
+ ctx->NewState |= _NEW_ARRAY;
+ /*_mesa_printf("%s %x\n", __FUNCTION__, varying_inputs);*/
+ }
+}
+
+
+/**
+ * Used by drivers to tell core Mesa that the driver is going to
+ * install/ use its own vertex program. In particular, this will
+ * prevent generated fragment programs from using state vars instead
+ * of ordinary varyings/inputs.
+ */
+void
+_mesa_set_vp_override(GLcontext *ctx, GLboolean flag)
+{
+ if (ctx->VertexProgram._Overriden != flag) {
+ ctx->VertexProgram._Overriden = flag;
+
+ /* Set one of the bits which will trigger fragment program
+ * regeneration:
+ */
+ ctx->NewState |= _NEW_PROGRAM;
+ }
+}
diff --git a/src/mesa/main/state.h b/src/mesa/main/state.h
index bb7cb8f32a..29db08a0b9 100644
--- a/src/mesa/main/state.h
+++ b/src/mesa/main/state.h
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.3
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
@@ -29,13 +29,21 @@
#include "mtypes.h"
extern void
-_mesa_update_state( GLcontext *ctx );
+_mesa_update_state(GLcontext *ctx);
/* As above but can only be called between _mesa_lock_context_textures() and
* _mesa_unlock_context_textures().
*/
extern void
-_mesa_update_state_locked( GLcontext *ctx );
+_mesa_update_state_locked(GLcontext *ctx);
+
+
+extern void
+_mesa_set_varying_vp_inputs(GLcontext *ctx, GLbitfield varying_inputs);
+
+
+extern void
+_mesa_set_vp_override(GLcontext *ctx, GLboolean flag);
#endif
diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c
index 2a4c38b1f2..15c98e2015 100644
--- a/src/mesa/main/stencil.c
+++ b/src/mesa/main/stencil.c
@@ -27,7 +27,7 @@
* \file stencil.c
* Stencil operations.
*
- * Note: There's an incompatibility between GL_EXT_stencil_two_side and
+ * Note: There's some conflict between GL_EXT_stencil_two_side and
* OpenGL 2.0's two-sided stencil feature.
*
* With GL_EXT_stencil_two_side, calling glStencilOp/Func/Mask() only the
@@ -36,12 +36,14 @@
* But with OpenGL 2.0, calling glStencilOp/Func/Mask() sets BOTH the
* front AND back state.
*
- * So either we advertise the GL_EXT_stencil_two_side extension, or OpenGL
- * 2.0, but not both.
- *
* Also, note that GL_ATI_separate_stencil is different as well:
* glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, ...) vs.
* glStencilFuncSeparate(GLenum face, GLenum func, ...).
+ *
+ * This problem is solved by keeping three sets of stencil state:
+ * state[0] = GL_FRONT state.
+ * state[1] = OpenGL 2.0 / GL_ATI_separate_stencil GL_BACK state.
+ * state[2] = GL_EXT_stencil_two_side GL_BACK state.
*/
@@ -198,6 +200,7 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
{
GET_CURRENT_CONTEXT(ctx);
const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+ const GLint face = ctx->Stencil.ActiveFace;
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (!validate_stencil_func(ctx, func)) {
@@ -207,9 +210,7 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
ref = CLAMP( ref, 0, stencilMax );
- if (ctx->Extensions.EXT_stencil_two_side) {
- /* only set active face state */
- const GLint face = ctx->Stencil.ActiveFace;
+ if (face != 0) {
if (ctx->Stencil.Function[face] == func &&
ctx->Stencil.ValueMask[face] == mask &&
ctx->Stencil.Ref[face] == ref)
@@ -218,9 +219,12 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
ctx->Stencil.Function[face] = func;
ctx->Stencil.Ref[face] = ref;
ctx->Stencil.ValueMask[face] = mask;
- if (ctx->Driver.StencilFuncSeparate) {
- ctx->Driver.StencilFuncSeparate(ctx, face ? GL_BACK : GL_FRONT,
- func, ref, mask);
+
+ /* Only propagate the change to the driver if EXT_stencil_two_side
+ * is enabled.
+ */
+ if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
+ ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
}
}
else {
@@ -237,7 +241,9 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
ctx->Stencil.Ref[0] = ctx->Stencil.Ref[1] = ref;
ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
if (ctx->Driver.StencilFuncSeparate) {
- ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT_AND_BACK,
+ ctx->Driver.StencilFuncSeparate(ctx,
+ ((ctx->Stencil.TestTwoSide)
+ ? GL_FRONT : GL_FRONT_AND_BACK),
func, ref, mask);
}
}
@@ -259,17 +265,23 @@ void GLAPIENTRY
_mesa_StencilMask( GLuint mask )
{
GET_CURRENT_CONTEXT(ctx);
+ const GLint face = ctx->Stencil.ActiveFace;
+
ASSERT_OUTSIDE_BEGIN_END(ctx);
- if (ctx->Extensions.EXT_stencil_two_side) {
- /* only set active face state */
- const GLint face = ctx->Stencil.ActiveFace;
+ if (face != 0) {
+ /* Only modify the EXT_stencil_two_side back-face state.
+ */
if (ctx->Stencil.WriteMask[face] == mask)
return;
FLUSH_VERTICES(ctx, _NEW_STENCIL);
ctx->Stencil.WriteMask[face] = mask;
- if (ctx->Driver.StencilMaskSeparate) {
- ctx->Driver.StencilMaskSeparate(ctx, face ? GL_BACK : GL_FRONT, mask);
+
+ /* Only propagate the change to the driver if EXT_stencil_two_side
+ * is enabled.
+ */
+ if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
+ ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
}
}
else {
@@ -280,7 +292,10 @@ _mesa_StencilMask( GLuint mask )
FLUSH_VERTICES(ctx, _NEW_STENCIL);
ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
if (ctx->Driver.StencilMaskSeparate) {
- ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT_AND_BACK, mask);
+ ctx->Driver.StencilMaskSeparate(ctx,
+ ((ctx->Stencil.TestTwoSide)
+ ? GL_FRONT : GL_FRONT_AND_BACK),
+ mask);
}
}
}
@@ -304,6 +319,8 @@ void GLAPIENTRY
_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
{
GET_CURRENT_CONTEXT(ctx);
+ const GLint face = ctx->Stencil.ActiveFace;
+
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (!validate_stencil_op(ctx, fail)) {
@@ -319,9 +336,8 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
return;
}
- if (ctx->Extensions.EXT_stencil_two_side) {
+ if (face != 0) {
/* only set active face state */
- const GLint face = ctx->Stencil.ActiveFace;
if (ctx->Stencil.ZFailFunc[face] == zfail &&
ctx->Stencil.ZPassFunc[face] == zpass &&
ctx->Stencil.FailFunc[face] == fail)
@@ -330,9 +346,12 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
ctx->Stencil.ZFailFunc[face] = zfail;
ctx->Stencil.ZPassFunc[face] = zpass;
ctx->Stencil.FailFunc[face] = fail;
- if (ctx->Driver.StencilOpSeparate) {
- ctx->Driver.StencilOpSeparate(ctx, face ? GL_BACK : GL_FRONT,
- fail, zfail, zpass);
+
+ /* Only propagate the change to the driver if EXT_stencil_two_side
+ * is enabled.
+ */
+ if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
+ ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
}
}
else {
@@ -349,7 +368,9 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
ctx->Stencil.FailFunc[0] = ctx->Stencil.FailFunc[1] = fail;
if (ctx->Driver.StencilOpSeparate) {
- ctx->Driver.StencilOpSeparate(ctx, GL_FRONT_AND_BACK,
+ ctx->Driver.StencilOpSeparate(ctx,
+ ((ctx->Stencil.TestTwoSide)
+ ? GL_FRONT : GL_FRONT_AND_BACK),
fail, zfail, zpass);
}
}
@@ -372,7 +393,7 @@ _mesa_ActiveStencilFaceEXT(GLenum face)
if (face == GL_FRONT || face == GL_BACK) {
FLUSH_VERTICES(ctx, _NEW_STENCIL);
- ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 1;
+ ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
}
else {
_mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
@@ -513,19 +534,20 @@ _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
void
_mesa_update_stencil(GLcontext *ctx)
{
- if (ctx->Extensions.EXT_stencil_two_side) {
- ctx->Stencil._TestTwoSide = ctx->Stencil.TestTwoSide;
- }
- else {
- ctx->Stencil._TestTwoSide =
- (ctx->Stencil.Function[0] != ctx->Stencil.Function[1] ||
- ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[1] ||
- ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[1] ||
- ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[1] ||
- ctx->Stencil.Ref[0] != ctx->Stencil.Ref[1] ||
- ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[1] ||
- ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[1]);
- }
+ const GLint face = ctx->Stencil._BackFace;
+
+ ctx->Stencil._Enabled = (ctx->Stencil.Enabled &&
+ ctx->DrawBuffer->Visual.stencilBits > 0);
+
+ ctx->Stencil._TestTwoSide =
+ ctx->Stencil._Enabled &&
+ (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] ||
+ ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] ||
+ ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] ||
+ ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] ||
+ ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] ||
+ ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] ||
+ ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]);
}
@@ -541,20 +563,28 @@ _mesa_init_stencil(GLcontext *ctx)
{
ctx->Stencil.Enabled = GL_FALSE;
ctx->Stencil.TestTwoSide = GL_FALSE;
- ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 1 = GL_BACK */
+ ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 2 = GL_BACK */
ctx->Stencil.Function[0] = GL_ALWAYS;
ctx->Stencil.Function[1] = GL_ALWAYS;
+ ctx->Stencil.Function[2] = GL_ALWAYS;
ctx->Stencil.FailFunc[0] = GL_KEEP;
ctx->Stencil.FailFunc[1] = GL_KEEP;
+ ctx->Stencil.FailFunc[2] = GL_KEEP;
ctx->Stencil.ZPassFunc[0] = GL_KEEP;
ctx->Stencil.ZPassFunc[1] = GL_KEEP;
+ ctx->Stencil.ZPassFunc[2] = GL_KEEP;
ctx->Stencil.ZFailFunc[0] = GL_KEEP;
ctx->Stencil.ZFailFunc[1] = GL_KEEP;
+ ctx->Stencil.ZFailFunc[2] = GL_KEEP;
ctx->Stencil.Ref[0] = 0;
ctx->Stencil.Ref[1] = 0;
+ ctx->Stencil.Ref[2] = 0;
ctx->Stencil.ValueMask[0] = ~0U;
ctx->Stencil.ValueMask[1] = ~0U;
+ ctx->Stencil.ValueMask[2] = ~0U;
ctx->Stencil.WriteMask[0] = ~0U;
ctx->Stencil.WriteMask[1] = ~0U;
+ ctx->Stencil.WriteMask[2] = ~0U;
ctx->Stencil.Clear = 0;
+ ctx->Stencil._BackFace = 1;
}
diff --git a/src/mesa/main/syncobj.c b/src/mesa/main/syncobj.c
new file mode 100644
index 0000000000..ac3f9eb175
--- /dev/null
+++ b/src/mesa/main/syncobj.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file syncobj.c
+ * Sync object management.
+ *
+ * Unlike textures and other objects that are shared between contexts, sync
+ * objects are not bound to the context. As a result, the reference counting
+ * and delete behavior of sync objects is slightly different. References to
+ * sync objects are added:
+ *
+ * - By \c glFencSynce. This sets the initial reference count to 1.
+ * - At the start of \c glClientWaitSync. The reference is held for the
+ * duration of the wait call.
+ *
+ * References are removed:
+ *
+ * - By \c glDeleteSync.
+ * - At the end of \c glClientWaitSync.
+ *
+ * Additionally, drivers may call \c _mesa_ref_sync_object and
+ * \c _mesa_unref_sync_object as needed to implement \c ServerWaitSync.
+ *
+ * As with shader objects, sync object names become invalid as soon as
+ * \c glDeleteSync is called. For this reason \c glDeleteSync sets the
+ * \c DeletePending flag. All functions validate object handles by testing
+ * this flag.
+ *
+ * \note
+ * Only \c GL_ARB_sync objects are shared between contexts. If support is ever
+ * added for either \c GL_NV_fence or \c GL_APPLE_fence different semantics
+ * will need to be implemented.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "macros.h"
+
+#if FEATURE_ARB_sync
+#include "syncobj.h"
+
+static struct gl_sync_object *
+_mesa_new_sync_object(GLcontext *ctx, GLenum type)
+{
+ struct gl_sync_object *s = MALLOC_STRUCT(gl_sync_object);
+ (void) ctx;
+ (void) type;
+
+ return s;
+}
+
+
+static void
+_mesa_delete_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj)
+{
+ (void) ctx;
+ _mesa_free(syncObj);
+}
+
+
+static void
+_mesa_fence_sync(GLcontext *ctx, struct gl_sync_object *syncObj,
+ GLenum condition, GLbitfield flags)
+{
+ (void) ctx;
+ (void) condition;
+ (void) flags;
+
+ syncObj->StatusFlag = 1;
+}
+
+
+static void
+_mesa_check_sync(GLcontext *ctx, struct gl_sync_object *syncObj)
+{
+ (void) ctx;
+ (void) syncObj;
+
+ /* No-op for software rendering. Hardware drivers will need to determine
+ * whether the state of the sync object has changed.
+ */
+}
+
+
+static void
+_mesa_wait_sync(GLcontext *ctx, struct gl_sync_object *syncObj,
+ GLbitfield flags, GLuint64 timeout)
+{
+ (void) ctx;
+ (void) syncObj;
+ (void) flags;
+ (void) timeout;
+
+ /* No-op for software rendering. Hardware drivers will need to wait until
+ * the state of the sync object changes or the timeout expires.
+ */
+}
+
+
+void
+_mesa_init_sync_object_functions(struct dd_function_table *driver)
+{
+ driver->NewSyncObject = _mesa_new_sync_object;
+ driver->FenceSync = _mesa_fence_sync;
+ driver->DeleteSyncObject = _mesa_delete_sync_object;
+ driver->CheckSync = _mesa_check_sync;
+
+ /* Use the same no-op wait function for both.
+ */
+ driver->ClientWaitSync = _mesa_wait_sync;
+ driver->ServerWaitSync = _mesa_wait_sync;
+}
+
+
+/**
+ * Allocate/init the context state related to sync objects.
+ */
+void
+_mesa_init_sync(GLcontext *ctx)
+{
+ (void) ctx;
+}
+
+
+/**
+ * Free the context state related to sync objects.
+ */
+void
+_mesa_free_sync_data(GLcontext *ctx)
+{
+ (void) ctx;
+}
+
+
+static int
+_mesa_validate_sync(struct gl_sync_object *syncObj)
+{
+ return (syncObj != NULL)
+ && (syncObj->Type == GL_SYNC_FENCE)
+ && !syncObj->DeletePending;
+}
+
+
+void
+_mesa_ref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj)
+{
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ syncObj->RefCount++;
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+}
+
+
+void
+_mesa_unref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj)
+{
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ syncObj->RefCount--;
+ if (syncObj->RefCount == 0) {
+ remove_from_list(& syncObj->link);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ ctx->Driver.DeleteSyncObject(ctx, syncObj);
+ } else {
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ }
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsSync(GLsync sync)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ return _mesa_validate_sync(syncObj) ? GL_TRUE : GL_FALSE;
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteSync(GLsync sync)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ /* From the GL_ARB_sync spec:
+ *
+ * DeleteSync will silently ignore a <sync> value of zero. An
+ * INVALID_VALUE error is generated if <sync> is neither zero nor the
+ * name of a sync object.
+ */
+ if (sync == 0) {
+ return;
+ }
+
+ if (!_mesa_validate_sync(syncObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteSync");
+ return;
+ }
+
+ /* If there are no client-waits or server-waits pending on this sync, delete
+ * the underlying object.
+ */
+ syncObj->DeletePending = GL_TRUE;
+ _mesa_unref_sync_object(ctx, syncObj);
+}
+
+
+GLsync GLAPIENTRY
+_mesa_FenceSync(GLenum condition, GLbitfield flags)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *syncObj;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
+
+ if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glFenceSync(condition=0x%x)",
+ condition);
+ return 0;
+ }
+
+ if (flags != 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glFenceSync(flags=0x%x)",
+ condition);
+ return 0;
+ }
+
+ syncObj = ctx->Driver.NewSyncObject(ctx, GL_SYNC_FENCE);
+ if (syncObj != NULL) {
+ syncObj->Type = GL_SYNC_FENCE;
+ /* The name is not currently used, and it is never visible to
+ * applications. If sync support is extended to provide support for
+ * NV_fence, this field will be used. We'll also need to add an object
+ * ID hashtable.
+ */
+ syncObj->Name = 1;
+ syncObj->RefCount = 1;
+ syncObj->DeletePending = GL_FALSE;
+ syncObj->SyncCondition = condition;
+ syncObj->Flags = flags;
+ syncObj->StatusFlag = 0;
+
+ ctx->Driver.FenceSync(ctx, syncObj, condition, flags);
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ insert_at_tail(& ctx->Shared->SyncObjects, & syncObj->link);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ return (GLsync) syncObj;
+ }
+
+ return NULL;
+}
+
+
+GLenum GLAPIENTRY
+_mesa_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ GLenum ret;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_WAIT_FAILED);
+
+ if (!_mesa_validate_sync(syncObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glClientWaitSync");
+ return GL_WAIT_FAILED;
+ }
+
+ if ((flags & ~GL_SYNC_FLUSH_COMMANDS_BIT) != 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glClientWaitSync(flags=0x%x)", flags);
+ return GL_WAIT_FAILED;
+ }
+
+ _mesa_ref_sync_object(ctx, syncObj);
+
+ /* From the GL_ARB_sync spec:
+ *
+ * ClientWaitSync returns one of four status values. A return value of
+ * ALREADY_SIGNALED indicates that <sync> was signaled at the time
+ * ClientWaitSync was called. ALREADY_SIGNALED will always be returned
+ * if <sync> was signaled, even if the value of <timeout> is zero.
+ */
+ ctx->Driver.CheckSync(ctx, syncObj);
+ if (syncObj->StatusFlag) {
+ ret = GL_ALREADY_SIGNALED;
+ } else {
+ ctx->Driver.ClientWaitSync(ctx, syncObj, flags, timeout);
+
+ ret = syncObj->StatusFlag ? GL_CONDITION_SATISFIED : GL_TIMEOUT_EXPIRED;
+ }
+
+ _mesa_unref_sync_object(ctx, syncObj);
+ return ret;
+}
+
+
+void GLAPIENTRY
+_mesa_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!_mesa_validate_sync(syncObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glWaitSync");
+ return;
+ }
+
+ if (flags != 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glWaitSync(flags=0x%x)", flags);
+ return;
+ }
+
+ /* From the GL_ARB_sync spec:
+ *
+ * If the value of <timeout> is zero, then WaitSync does nothing.
+ */
+ if (timeout == 0) {
+ return;
+ }
+
+ ctx->Driver.ServerWaitSync(ctx, syncObj, flags, timeout);
+}
+
+
+void GLAPIENTRY
+_mesa_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length,
+ GLint *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ GLsizei size = 0;
+ GLint v[1];
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!_mesa_validate_sync(syncObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetSynciv");
+ return;
+ }
+
+ switch (pname) {
+ case GL_OBJECT_TYPE:
+ v[0] = syncObj->Type;
+ size = 1;
+ break;
+
+ case GL_SYNC_CONDITION:
+ v[0] = syncObj->SyncCondition;
+ size = 1;
+ break;
+
+ case GL_SYNC_STATUS:
+ /* Update the state of the sync by dipping into the driver. Note that
+ * this call won't block. It just updates state in the common object
+ * data from the current driver state.
+ */
+ ctx->Driver.CheckSync(ctx, syncObj);
+
+ v[0] = (syncObj->StatusFlag) ? GL_SIGNALED : GL_UNSIGNALED;
+ size = 1;
+ break;
+
+ case GL_SYNC_FLAGS:
+ v[0] = syncObj->Flags;
+ size = 1;
+ break;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetSynciv(pname=0x%x)\n", pname);
+ return;
+ }
+
+ if (size > 0) {
+ const GLsizei copy_count = MIN2(size, bufSize);
+
+ _mesa_memcpy(values, v, sizeof(GLint) * copy_count);
+ }
+
+ if (length != NULL) {
+ *length = size;
+ }
+}
+
+#endif /* FEATURE_ARB_sync */
diff --git a/src/mesa/main/syncobj.h b/src/mesa/main/syncobj.h
new file mode 100644
index 0000000000..f23fa281e2
--- /dev/null
+++ b/src/mesa/main/syncobj.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file syncobj.h
+ * Sync object management.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#ifndef SYNCOBJ_H
+#define SYNCOBJ_H
+
+#include "context.h"
+
+extern void
+_mesa_init_sync_object_functions(struct dd_function_table *driver);
+
+extern void
+_mesa_init_sync(GLcontext *);
+
+extern void
+_mesa_free_sync_data(GLcontext *);
+
+extern void
+_mesa_ref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj);
+
+extern void
+_mesa_unref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj);
+
+extern GLboolean GLAPIENTRY
+_mesa_IsSync(GLsync sync);
+
+extern void GLAPIENTRY
+_mesa_DeleteSync(GLsync sync);
+
+extern GLsync GLAPIENTRY
+_mesa_FenceSync(GLenum condition, GLbitfield flags);
+
+extern GLenum GLAPIENTRY
+_mesa_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+extern void GLAPIENTRY
+_mesa_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+extern void GLAPIENTRY
+_mesa_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length,
+ GLint *values);
+
+#endif /* SYNCOBJ_H */
diff --git a/src/mesa/main/texcompress.c b/src/mesa/main/texcompress.c
index 3ff633acd2..c1b8c7675a 100644
--- a/src/mesa/main/texcompress.c
+++ b/src/mesa/main/texcompress.c
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -56,60 +57,58 @@ GLuint
_mesa_get_compressed_formats(GLcontext *ctx, GLint *formats, GLboolean all)
{
GLuint n = 0;
- if (ctx->Extensions.ARB_texture_compression) {
- if (ctx->Extensions.TDFX_texture_compression_FXT1) {
- if (formats) {
- formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX;
- formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX;
- }
- else {
- n += 2;
- }
+ if (ctx->Extensions.TDFX_texture_compression_FXT1) {
+ if (formats) {
+ formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX;
+ formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX;
}
- if (ctx->Extensions.EXT_texture_compression_s3tc) {
- if (formats) {
- formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
- /* This format has some restrictions/limitations and so should
- * not be returned via the GL_COMPRESSED_TEXTURE_FORMATS query.
- * Specifically, all transparent pixels become black. NVIDIA
- * omits this format too.
- */
- if (all)
- formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
- formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
- }
- else {
- n += 3;
- if (all)
- n += 1;
- }
+ else {
+ n += 2;
}
- if (ctx->Extensions.S3_s3tc) {
- if (formats) {
- formats[n++] = GL_RGB_S3TC;
- formats[n++] = GL_RGB4_S3TC;
- formats[n++] = GL_RGBA_S3TC;
- formats[n++] = GL_RGBA4_S3TC;
- }
- else {
- n += 4;
- }
+ }
+ if (ctx->Extensions.EXT_texture_compression_s3tc) {
+ if (formats) {
+ formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ /* This format has some restrictions/limitations and so should
+ * not be returned via the GL_COMPRESSED_TEXTURE_FORMATS query.
+ * Specifically, all transparent pixels become black. NVIDIA
+ * omits this format too.
+ */
+ if (all)
+ formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ }
+ else {
+ n += 3;
+ if (all)
+ n += 1;
+ }
+ }
+ if (ctx->Extensions.S3_s3tc) {
+ if (formats) {
+ formats[n++] = GL_RGB_S3TC;
+ formats[n++] = GL_RGB4_S3TC;
+ formats[n++] = GL_RGBA_S3TC;
+ formats[n++] = GL_RGBA4_S3TC;
+ }
+ else {
+ n += 4;
}
+ }
#if FEATURE_EXT_texture_sRGB
- if (ctx->Extensions.EXT_texture_sRGB) {
- if (formats) {
- formats[n++] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
- formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
- formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
- formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
- }
- else {
- n += 4;
- }
+ if (ctx->Extensions.EXT_texture_sRGB) {
+ if (formats) {
+ formats[n++] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+ formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ }
+ else {
+ n += 4;
}
-#endif /* FEATURE_EXT_texture_sRGB */
}
+#endif /* FEATURE_EXT_texture_sRGB */
return n;
}
@@ -137,8 +136,10 @@ _mesa_compressed_texture_size( GLcontext *ctx,
ASSERT(depth == 1);
(void) depth;
+ (void) size;
switch (mesaFormat) {
+#if FEATURE_texture_fxt1
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
/* round up width to next multiple of 8, height to next multiple of 4 */
@@ -150,8 +151,14 @@ _mesa_compressed_texture_size( GLcontext *ctx,
* take 16 bytes.
*/
return size;
+#endif
+#if FEATURE_texture_s3tc
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+#endif
/* round up width, height to next multiple of 4 */
width = (width + 3) & ~3;
height = (height + 3) & ~3;
@@ -163,6 +170,10 @@ _mesa_compressed_texture_size( GLcontext *ctx,
return size;
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
/* round up width, height to next multiple of 4 */
width = (width + 3) & ~3;
height = (height + 3) & ~3;
@@ -172,6 +183,7 @@ _mesa_compressed_texture_size( GLcontext *ctx,
* take 16 bytes.
*/
return size;
+#endif
default:
_mesa_problem(ctx, "bad mesaFormat in _mesa_compressed_texture_size");
return 0;
@@ -196,12 +208,15 @@ _mesa_compressed_texture_size_glenum(GLcontext *ctx,
GLuint mesaFormat;
switch (glformat) {
+#if FEATURE_texture_fxt1
case GL_COMPRESSED_RGB_FXT1_3DFX:
mesaFormat = MESA_FORMAT_RGB_FXT1;
break;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
mesaFormat = MESA_FORMAT_RGBA_FXT1;
break;
+#endif
+#if FEATURE_texture_s3tc
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_RGB_S3TC:
mesaFormat = MESA_FORMAT_RGB_DXT1;
@@ -218,6 +233,21 @@ _mesa_compressed_texture_size_glenum(GLcontext *ctx,
case GL_RGBA4_S3TC:
mesaFormat = MESA_FORMAT_RGBA_DXT5;
break;
+#if FEATURE_EXT_texture_sRGB
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ mesaFormat = MESA_FORMAT_SRGB_DXT1;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ mesaFormat = MESA_FORMAT_SRGBA_DXT1;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ mesaFormat = MESA_FORMAT_SRGBA_DXT3;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ mesaFormat = MESA_FORMAT_SRGBA_DXT5;
+ break;
+#endif
+#endif
default:
return 0;
}
@@ -239,18 +269,30 @@ _mesa_compressed_row_stride(GLuint mesaFormat, GLsizei width)
GLint stride;
switch (mesaFormat) {
+#if FEATURE_texture_fxt1
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */
break;
+#endif
+#if FEATURE_texture_s3tc
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+#endif
stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */
break;
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */
break;
+#endif
default:
_mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_row_stride");
return 0;
@@ -287,18 +329,30 @@ _mesa_compressed_image_address(GLint col, GLint row, GLint img,
*/
switch (mesaFormat) {
+#if FEATURE_texture_fxt1
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8);
break;
+#endif
+#if FEATURE_texture_s3tc
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+#endif
addr = (GLubyte *) image + 8 * (((width + 3) / 4) * (row / 4) + col / 4);
break;
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
addr = (GLubyte *) image + 16 * (((width + 3) / 4) * (row / 4) + col / 4);
break;
+#endif
default:
_mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_image_address");
addr = NULL;
diff --git a/src/mesa/main/texcompress_fxt1.c b/src/mesa/main/texcompress_fxt1.c
index 45f344b0c5..14de935e71 100644
--- a/src/mesa/main/texcompress_fxt1.c
+++ b/src/mesa/main/texcompress_fxt1.c
@@ -41,6 +41,9 @@
#include "texstore.h"
+#if FEATURE_texture_fxt1
+
+
static void
fxt1_encode (GLuint width, GLuint height, GLint comps,
const void *source, GLint srcRowStride,
@@ -52,16 +55,6 @@ fxt1_decode_1 (const void *texture, GLint stride,
/**
- * Called during context initialization.
- */
-void
-_mesa_init_texture_fxt1( GLcontext *ctx )
-{
- (void) ctx;
-}
-
-
-/**
* Called via TexFormat->StoreImage to store an RGB_FXT1 texture.
*/
static GLboolean
@@ -224,6 +217,8 @@ fetch_texel_2d_f_rgb_fxt1( const struct gl_texture_image *texImage,
}
+#endif /* FEATURE_texture_fxt1 */
+
const struct gl_texture_format _mesa_texformat_rgb_fxt1 = {
MESA_FORMAT_RGB_FXT1, /* MesaFormat */
@@ -239,6 +234,7 @@ const struct gl_texture_format _mesa_texformat_rgb_fxt1 = {
0, /* DepthBits */
0, /* StencilBits */
0, /* TexelBytes */
+#if FEATURE_texture_fxt1
texstore_rgb_fxt1, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
fetch_texel_2d_rgb_fxt1, /* FetchTexel2D */
@@ -247,6 +243,10 @@ const struct gl_texture_format _mesa_texformat_rgb_fxt1 = {
fetch_texel_2d_f_rgb_fxt1, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
+#else
+ _mesa_texstore_null,
+ _MESA_TEXFORMAT_NULL_OPS
+#endif
};
const struct gl_texture_format _mesa_texformat_rgba_fxt1 = {
@@ -263,6 +263,7 @@ const struct gl_texture_format _mesa_texformat_rgba_fxt1 = {
0, /* DepthBits */
0, /* StencilBits */
0, /* TexelBytes */
+#if FEATURE_texture_fxt1
texstore_rgba_fxt1, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
fetch_texel_2d_rgba_fxt1, /* FetchTexel2D */
@@ -271,9 +272,16 @@ const struct gl_texture_format _mesa_texformat_rgba_fxt1 = {
fetch_texel_2d_f_rgba_fxt1, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
+#else
+ _mesa_texstore_null,
+ _MESA_TEXFORMAT_NULL_OPS
+#endif
};
+#if FEATURE_texture_fxt1
+
+
/***************************************************************************\
* FXT1 encoder
*
@@ -298,17 +306,17 @@ const struct gl_texture_format _mesa_texformat_rgba_fxt1 = {
/*
* Define a 64-bit unsigned integer type and macros
*/
-#ifdef GL_EXT_timer_query /* this extensions defines the GLuint64EXT type */
+#if 1
#define FX64_NATIVE 1
-typedef GLuint64EXT Fx64;
+typedef uint64_t Fx64;
#define FX64_MOV32(a, b) a = b
#define FX64_OR32(a, b) a |= b
#define FX64_SHL(a, c) a <<= c
-#else /* !GL_EXT_timer_query */
+#else
#define FX64_NATIVE 0
@@ -330,7 +338,7 @@ typedef struct {
} \
} while (0)
-#endif /* !GL_EXT_timer_query */
+#endif
#define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
@@ -1722,3 +1730,16 @@ fxt1_decode_1 (const void *texture, GLint stride, /* in pixels */
decode_1[mode](code, t, rgba);
}
+
+
+#endif /* FEATURE_texture_fxt1 */
+
+
+/**
+ * Called during context initialization.
+ */
+void
+_mesa_init_texture_fxt1( GLcontext *ctx )
+{
+ (void) ctx;
+}
diff --git a/src/mesa/main/texcompress_s3tc.c b/src/mesa/main/texcompress_s3tc.c
index a19c161b2c..754cb33cc0 100644
--- a/src/mesa/main/texcompress_s3tc.c
+++ b/src/mesa/main/texcompress_s3tc.c
@@ -3,6 +3,7 @@
* Version: 6.5.3
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -54,6 +55,38 @@
#endif
+#if FEATURE_texture_s3tc
+
+
+#if FEATURE_EXT_texture_sRGB
+/**
+ * Convert an 8-bit sRGB value from non-linear space to a
+ * linear RGB value in [0, 1].
+ * Implemented with a 256-entry lookup table.
+ */
+static INLINE GLfloat
+nonlinear_to_linear(GLubyte cs8)
+{
+ static GLfloat table[256];
+ static GLboolean tableReady = GL_FALSE;
+ if (!tableReady) {
+ /* compute lookup table now */
+ GLuint i;
+ for (i = 0; i < 256; i++) {
+ const GLfloat cs = UBYTE_TO_FLOAT(i);
+ if (cs <= 0.04045) {
+ table[i] = cs / 12.92f;
+ }
+ else {
+ table[i] = (GLfloat) _mesa_pow((cs + 0.055) / 1.055, 2.4);
+ }
+ }
+ tableReady = GL_TRUE;
+ }
+ return table[cs8];
+}
+#endif /* FEATURE_EXT_texture_sRGB */
+
typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut );
dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL;
@@ -176,7 +209,7 @@ texstore_rgb_dxt1(TEXSTORE_PARAMS)
dst, dstRowStride);
}
else {
- _mesa_warning(ctx, "external dxt library not available");
+ _mesa_warning(ctx, "external dxt library not available: texstore_rgb_dxt1");
}
if (tempImage)
@@ -238,7 +271,7 @@ texstore_rgba_dxt1(TEXSTORE_PARAMS)
dst, dstRowStride);
}
else {
- _mesa_warning(ctx, "external dxt library not available");
+ _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt1");
}
if (tempImage)
@@ -299,7 +332,7 @@ texstore_rgba_dxt3(TEXSTORE_PARAMS)
dst, dstRowStride);
}
else {
- _mesa_warning(ctx, "external dxt library not available");
+ _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt3");
}
if (tempImage)
@@ -360,7 +393,7 @@ texstore_rgba_dxt5(TEXSTORE_PARAMS)
dst, dstRowStride);
}
else {
- _mesa_warning(ctx, "external dxt library not available");
+ _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt5");
}
if (tempImage)
@@ -381,7 +414,7 @@ fetch_texel_2d_rgb_dxt1( const struct gl_texture_image *texImage,
(GLubyte *)(texImage)->Data, i, j, texel);
}
else
- _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
+ _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgb_dxt1");
}
@@ -409,7 +442,7 @@ fetch_texel_2d_rgba_dxt1( const struct gl_texture_image *texImage,
(GLubyte *)(texImage)->Data, i, j, texel);
}
else
- _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
+ _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt1\n");
}
@@ -438,7 +471,7 @@ fetch_texel_2d_rgba_dxt3( const struct gl_texture_image *texImage,
i, j, texel);
}
else
- _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
+ _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt3\n");
}
@@ -466,7 +499,7 @@ fetch_texel_2d_rgba_dxt5( const struct gl_texture_image *texImage,
i, j, texel);
}
else
- _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
+ _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt5\n");
}
@@ -483,6 +516,73 @@ fetch_texel_2d_f_rgba_dxt5( const struct gl_texture_image *texImage,
texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
}
+#if FEATURE_EXT_texture_sRGB
+static void
+fetch_texel_2d_f_srgb_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+static void
+fetch_texel_2d_f_srgba_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+static void
+fetch_texel_2d_f_srgba_dxt3( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+static void
+fetch_texel_2d_f_srgba_dxt5( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+#endif /* FEATURE_EXT_texture_sRGB */
+
+
+#else /* FEATURE_texture_s3tc */
+
+
+void
+_mesa_init_texture_s3tc( GLcontext *ctx )
+{
+ (void) ctx;
+}
+
+
+#endif /* FEATURE_texture_s3tc */
+
const struct gl_texture_format _mesa_texformat_rgb_dxt1 = {
MESA_FORMAT_RGB_DXT1, /* MesaFormat */
@@ -498,6 +598,7 @@ const struct gl_texture_format _mesa_texformat_rgb_dxt1 = {
0, /* DepthBits */
0, /* StencilBits */
0, /* TexelBytes */
+#if FEATURE_texture_s3tc
texstore_rgb_dxt1, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
fetch_texel_2d_rgb_dxt1, /* FetchTexel2D */
@@ -506,6 +607,97 @@ const struct gl_texture_format _mesa_texformat_rgb_dxt1 = {
fetch_texel_2d_f_rgb_dxt1, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
+#else
+ _mesa_texstore_null,
+ _MESA_TEXFORMAT_NULL_OPS
+#endif
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_dxt1 = {
+ MESA_FORMAT_RGBA_DXT1, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 1, /*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+#if FEATURE_texture_s3tc
+ texstore_rgba_dxt1, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_dxt1, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_dxt1, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+#else
+ _mesa_texstore_null,
+ _MESA_TEXFORMAT_NULL_OPS
+#endif
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_dxt3 = {
+ MESA_FORMAT_RGBA_DXT3, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 4, /*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+#if FEATURE_texture_s3tc
+ texstore_rgba_dxt3, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_dxt3, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_dxt3, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+#else
+ _mesa_texstore_null,
+ _MESA_TEXFORMAT_NULL_OPS
+#endif
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_dxt5 = {
+ MESA_FORMAT_RGBA_DXT5, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4,/*approx*/ /* RedBits */
+ 4,/*approx*/ /* GreenBits */
+ 4,/*approx*/ /* BlueBits */
+ 4,/*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+#if FEATURE_texture_s3tc
+ texstore_rgba_dxt5, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_dxt5, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_dxt5, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+#else
+ _mesa_texstore_null,
+ _MESA_TEXFORMAT_NULL_OPS
+#endif
};
#if FEATURE_EXT_texture_sRGB
@@ -525,17 +717,16 @@ const struct gl_texture_format _mesa_texformat_srgb_dxt1 = {
0, /* TexelBytes */
texstore_rgb_dxt1, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
- fetch_texel_2d_rgb_dxt1, /* FetchTexel2D */
+ NULL, /* FetchTexel2D */
NULL, /*impossible*/ /* FetchTexel3D */
NULL, /*impossible*/ /* FetchTexel1Df */
- fetch_texel_2d_f_rgb_dxt1, /* FetchTexel2Df */
+ fetch_texel_2d_f_srgb_dxt1, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
};
-#endif
-const struct gl_texture_format _mesa_texformat_rgba_dxt1 = {
- MESA_FORMAT_RGBA_DXT1, /* MesaFormat */
+const struct gl_texture_format _mesa_texformat_srgba_dxt1 = {
+ MESA_FORMAT_SRGBA_DXT1, /* MesaFormat */
GL_RGBA, /* BaseFormat */
GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
4, /*approx*/ /* RedBits */
@@ -550,16 +741,16 @@ const struct gl_texture_format _mesa_texformat_rgba_dxt1 = {
0, /* TexelBytes */
texstore_rgba_dxt1, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
- fetch_texel_2d_rgba_dxt1, /* FetchTexel2D */
+ NULL, /* FetchTexel2D */
NULL, /*impossible*/ /* FetchTexel3D */
NULL, /*impossible*/ /* FetchTexel1Df */
- fetch_texel_2d_f_rgba_dxt1, /* FetchTexel2Df */
+ fetch_texel_2d_f_srgba_dxt1, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
};
-const struct gl_texture_format _mesa_texformat_rgba_dxt3 = {
- MESA_FORMAT_RGBA_DXT3, /* MesaFormat */
+const struct gl_texture_format _mesa_texformat_srgba_dxt3 = {
+ MESA_FORMAT_SRGBA_DXT3, /* MesaFormat */
GL_RGBA, /* BaseFormat */
GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
4, /*approx*/ /* RedBits */
@@ -574,16 +765,16 @@ const struct gl_texture_format _mesa_texformat_rgba_dxt3 = {
0, /* TexelBytes */
texstore_rgba_dxt3, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
- fetch_texel_2d_rgba_dxt3, /* FetchTexel2D */
+ NULL, /* FetchTexel2D */
NULL, /*impossible*/ /* FetchTexel3D */
NULL, /*impossible*/ /* FetchTexel1Df */
- fetch_texel_2d_f_rgba_dxt3, /* FetchTexel2Df */
+ fetch_texel_2d_f_srgba_dxt3, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
};
-const struct gl_texture_format _mesa_texformat_rgba_dxt5 = {
- MESA_FORMAT_RGBA_DXT5, /* MesaFormat */
+const struct gl_texture_format _mesa_texformat_srgba_dxt5 = {
+ MESA_FORMAT_SRGBA_DXT5, /* MesaFormat */
GL_RGBA, /* BaseFormat */
GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
4,/*approx*/ /* RedBits */
@@ -598,10 +789,11 @@ const struct gl_texture_format _mesa_texformat_rgba_dxt5 = {
0, /* TexelBytes */
texstore_rgba_dxt5, /* StoreTexImageFunc */
NULL, /*impossible*/ /* FetchTexel1D */
- fetch_texel_2d_rgba_dxt5, /* FetchTexel2D */
+ NULL, /* FetchTexel2D */
NULL, /*impossible*/ /* FetchTexel3D */
NULL, /*impossible*/ /* FetchTexel1Df */
- fetch_texel_2d_f_rgba_dxt5, /* FetchTexel2Df */
+ fetch_texel_2d_f_srgba_dxt5, /* FetchTexel2Df */
NULL, /*impossible*/ /* FetchTexel3Df */
NULL /* StoreTexel */
};
+#endif
diff --git a/src/mesa/main/texenv.c b/src/mesa/main/texenv.c
index e072cea136..6d86a4275c 100644
--- a/src/mesa/main/texenv.c
+++ b/src/mesa/main/texenv.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.5
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -34,7 +35,420 @@
#include "main/enums.h"
#include "main/macros.h"
#include "main/texenv.h"
-#include "math/m_xform.h"
+#include "main/texstate.h"
+
+
+#define TE_ERROR(errCode, msg, value) \
+ _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
+
+
+/** Set texture env mode */
+static void
+set_env_mode(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum mode)
+{
+ GLboolean legal;
+
+ if (texUnit->EnvMode == mode)
+ return;
+
+ switch (mode) {
+ case GL_MODULATE:
+ case GL_BLEND:
+ case GL_DECAL:
+ case GL_REPLACE:
+ legal = GL_TRUE;
+ break;
+ case GL_REPLACE_EXT:
+ mode = GL_REPLACE; /* GL_REPLACE_EXT != GL_REPLACE */
+ legal = GL_TRUE;
+ break;
+ case GL_ADD:
+ legal = ctx->Extensions.EXT_texture_env_add;
+ break;
+ case GL_COMBINE:
+ legal = (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine);
+ break;
+ case GL_COMBINE4_NV:
+ legal = ctx->Extensions.NV_texture_env_combine4;
+ break;
+ default:
+ legal = GL_FALSE;
+ }
+
+ if (legal) {
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->EnvMode = mode;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
+ }
+}
+
+
+static void
+set_env_color(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ const GLfloat *color)
+{
+ GLfloat tmp[4];
+ tmp[0] = CLAMP(color[0], 0.0F, 1.0F);
+ tmp[1] = CLAMP(color[1], 0.0F, 1.0F);
+ tmp[2] = CLAMP(color[2], 0.0F, 1.0F);
+ tmp[3] = CLAMP(color[3], 0.0F, 1.0F);
+ if (TEST_EQ_4V(tmp, texUnit->EnvColor))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ COPY_4FV(texUnit->EnvColor, tmp);
+}
+
+
+/** Set an RGB or A combiner mode/function */
+static void
+set_combiner_mode(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum pname, GLenum mode)
+{
+ GLboolean legal;
+
+ if (!ctx->Extensions.EXT_texture_env_combine &&
+ !ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
+ return;
+ }
+
+ switch (mode) {
+ case GL_REPLACE:
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ case GL_INTERPOLATE:
+ legal = GL_TRUE;
+ break;
+ case GL_SUBTRACT:
+ legal = ctx->Extensions.ARB_texture_env_combine;
+ break;
+ case GL_DOT3_RGB_EXT:
+ case GL_DOT3_RGBA_EXT:
+ legal = (ctx->Extensions.EXT_texture_env_dot3 &&
+ pname == GL_COMBINE_RGB);
+ break;
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
+ legal = (ctx->Extensions.ARB_texture_env_dot3 &&
+ pname == GL_COMBINE_RGB);
+ break;
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ legal = ctx->Extensions.ATI_texture_env_combine3;
+ break;
+ case GL_BUMP_ENVMAP_ATI:
+ legal = (ctx->Extensions.ATI_envmap_bumpmap &&
+ pname == GL_COMBINE_RGB);
+ break;
+ default:
+ legal = GL_FALSE;
+ }
+
+ if (!legal) {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
+ return;
+ }
+
+ switch (pname) {
+ case GL_COMBINE_RGB:
+ if (texUnit->Combine.ModeRGB == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Combine.ModeRGB = mode;
+ break;
+
+ case GL_COMBINE_ALPHA:
+ if (texUnit->Combine.ModeA == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Combine.ModeA = mode;
+ break;
+ default:
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ }
+}
+
+
+
+/** Set an RGB or A combiner source term */
+static void
+set_combiner_source(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum pname, GLenum param)
+{
+ GLuint term;
+ GLboolean alpha, legal;
+
+ if (!ctx->Extensions.EXT_texture_env_combine &&
+ !ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
+ return;
+ }
+
+ /*
+ * Translate pname to (term, alpha).
+ */
+ switch (pname) {
+ case GL_SOURCE0_RGB:
+ term = 0;
+ alpha = GL_FALSE;
+ break;
+ case GL_SOURCE1_RGB:
+ term = 1;
+ alpha = GL_FALSE;
+ break;
+ case GL_SOURCE2_RGB:
+ term = 2;
+ alpha = GL_FALSE;
+ break;
+ case GL_SOURCE3_RGB_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ term = 3;
+ alpha = GL_FALSE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ case GL_SOURCE0_ALPHA:
+ term = 0;
+ alpha = GL_TRUE;
+ break;
+ case GL_SOURCE1_ALPHA:
+ term = 1;
+ alpha = GL_TRUE;
+ break;
+ case GL_SOURCE2_ALPHA:
+ term = 2;
+ alpha = GL_TRUE;
+ break;
+ case GL_SOURCE3_ALPHA_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ term = 3;
+ alpha = GL_TRUE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ default:
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+
+ assert(term < MAX_COMBINER_TERMS);
+
+ /*
+ * Error-check param (the source term)
+ */
+ switch (param) {
+ case GL_TEXTURE:
+ case GL_CONSTANT:
+ case GL_PRIMARY_COLOR:
+ case GL_PREVIOUS:
+ legal = GL_TRUE;
+ break;
+ case GL_TEXTURE0:
+ case GL_TEXTURE1:
+ case GL_TEXTURE2:
+ case GL_TEXTURE3:
+ case GL_TEXTURE4:
+ case GL_TEXTURE5:
+ case GL_TEXTURE6:
+ case GL_TEXTURE7:
+ legal = (ctx->Extensions.ARB_texture_env_crossbar &&
+ param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits);
+ break;
+ case GL_ZERO:
+ legal = (ctx->Extensions.ATI_texture_env_combine3 ||
+ ctx->Extensions.NV_texture_env_combine4);
+ break;
+ case GL_ONE:
+ legal = ctx->Extensions.ATI_texture_env_combine3;
+ break;
+ default:
+ legal = GL_FALSE;
+ }
+
+ if (!legal) {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+
+ if (alpha)
+ texUnit->Combine.SourceA[term] = param;
+ else
+ texUnit->Combine.SourceRGB[term] = param;
+}
+
+
+/** Set an RGB or A combiner operand term */
+static void
+set_combiner_operand(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum pname, GLenum param)
+{
+ GLuint term;
+ GLboolean alpha, legal;
+
+ if (!ctx->Extensions.EXT_texture_env_combine &&
+ !ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_OPERAND0_RGB:
+ term = 0;
+ alpha = GL_FALSE;
+ break;
+ case GL_OPERAND1_RGB:
+ term = 1;
+ alpha = GL_FALSE;
+ break;
+ case GL_OPERAND2_RGB:
+ if (ctx->Extensions.ARB_texture_env_combine) {
+ term = 2;
+ alpha = GL_FALSE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ case GL_OPERAND3_RGB_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ term = 3;
+ alpha = GL_FALSE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ case GL_OPERAND0_ALPHA:
+ term = 0;
+ alpha = GL_TRUE;
+ break;
+ case GL_OPERAND1_ALPHA:
+ term = 1;
+ alpha = GL_TRUE;
+ break;
+ case GL_OPERAND2_ALPHA:
+ if (ctx->Extensions.ARB_texture_env_combine) {
+ term = 2;
+ alpha = GL_TRUE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ case GL_OPERAND3_ALPHA_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ term = 3;
+ alpha = GL_TRUE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ default:
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+
+ assert(term < MAX_COMBINER_TERMS);
+
+ /*
+ * Error-check param (the source operand)
+ */
+ switch (param) {
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ legal = !alpha;
+ break;
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ legal = GL_TRUE;
+ break;
+ default:
+ legal = GL_FALSE;
+ }
+
+ if (!legal) {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+
+ if (alpha)
+ texUnit->Combine.OperandA[term] = param;
+ else
+ texUnit->Combine.OperandRGB[term] = param;
+}
+
+
+static void
+set_combiner_scale(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum pname, GLfloat scale)
+{
+ GLuint shift;
+
+ if (!ctx->Extensions.EXT_texture_env_combine &&
+ !ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
+ return;
+ }
+
+ if (scale == 1.0F) {
+ shift = 0;
+ }
+ else if (scale == 2.0F) {
+ shift = 1;
+ }
+ else if (scale == 4.0F) {
+ shift = 2;
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
+ return;
+ }
+
+ switch (pname) {
+ case GL_RGB_SCALE:
+ if (texUnit->Combine.ScaleShiftRGB == shift)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Combine.ScaleShiftRGB = shift;
+ break;
+ case GL_ALPHA_SCALE:
+ if (texUnit->Combine.ScaleShiftA == shift)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Combine.ScaleShiftA = shift;
+ break;
+ default:
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ }
+}
@@ -53,378 +467,62 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-
-#define TE_ERROR(errCode, msg, value) \
- _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
+ texUnit = _mesa_get_current_tex_unit(ctx);
if (target == GL_TEXTURE_ENV) {
switch (pname) {
case GL_TEXTURE_ENV_MODE:
- {
- GLenum mode = (GLenum) (GLint) *param;
- if (mode == GL_REPLACE_EXT)
- mode = GL_REPLACE;
- if (texUnit->EnvMode == mode)
- return;
- if (mode == GL_MODULATE ||
- mode == GL_BLEND ||
- mode == GL_DECAL ||
- mode == GL_REPLACE ||
- (mode == GL_ADD && ctx->Extensions.EXT_texture_env_add) ||
- (mode == GL_COMBINE &&
- (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine))) {
- /* legal */
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->EnvMode = mode;
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
- return;
- }
- }
+ set_env_mode(ctx, texUnit, (GLenum) (GLint) param[0]);
break;
case GL_TEXTURE_ENV_COLOR:
- {
- GLfloat tmp[4];
- tmp[0] = CLAMP( param[0], 0.0F, 1.0F );
- tmp[1] = CLAMP( param[1], 0.0F, 1.0F );
- tmp[2] = CLAMP( param[2], 0.0F, 1.0F );
- tmp[3] = CLAMP( param[3], 0.0F, 1.0F );
- if (TEST_EQ_4V(tmp, texUnit->EnvColor))
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- COPY_4FV(texUnit->EnvColor, tmp);
- }
+ set_env_color(ctx, texUnit, param);
break;
case GL_COMBINE_RGB:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const GLenum mode = (GLenum) (GLint) *param;
- if (texUnit->Combine.ModeRGB == mode)
- return;
- switch (mode) {
- case GL_REPLACE:
- case GL_MODULATE:
- case GL_ADD:
- case GL_ADD_SIGNED:
- case GL_INTERPOLATE:
- /* OK */
- break;
- case GL_SUBTRACT:
- if (!ctx->Extensions.ARB_texture_env_combine) {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
- return;
- }
- break;
- case GL_DOT3_RGB_EXT:
- case GL_DOT3_RGBA_EXT:
- if (!ctx->Extensions.EXT_texture_env_dot3) {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
- return;
- }
- break;
- case GL_DOT3_RGB:
- case GL_DOT3_RGBA:
- if (!ctx->Extensions.ARB_texture_env_dot3) {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
- return;
- }
- break;
- case GL_MODULATE_ADD_ATI:
- case GL_MODULATE_SIGNED_ADD_ATI:
- case GL_MODULATE_SUBTRACT_ATI:
- if (!ctx->Extensions.ATI_texture_env_combine3) {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
- return;
- }
- break;
- default:
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
- return;
- }
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.ModeRGB = mode;
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
- return;
- }
- break;
case GL_COMBINE_ALPHA:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const GLenum mode = (GLenum) (GLint) *param;
- if (texUnit->Combine.ModeA == mode)
- return;
- switch (mode) {
- case GL_REPLACE:
- case GL_MODULATE:
- case GL_ADD:
- case GL_ADD_SIGNED:
- case GL_INTERPOLATE:
- /* OK */
- break;
- case GL_SUBTRACT:
- if (!ctx->Extensions.ARB_texture_env_combine) {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
- return;
- }
- break;
- case GL_MODULATE_ADD_ATI:
- case GL_MODULATE_SIGNED_ADD_ATI:
- case GL_MODULATE_SUBTRACT_ATI:
- if (!ctx->Extensions.ATI_texture_env_combine3) {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
- return;
- }
- break;
- default:
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
- return;
- }
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.ModeA = mode;
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
- return;
- }
+ set_combiner_mode(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
break;
case GL_SOURCE0_RGB:
case GL_SOURCE1_RGB:
case GL_SOURCE2_RGB:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const GLenum source = (GLenum) (GLint) *param;
- const GLuint s = pname - GL_SOURCE0_RGB;
- if (texUnit->Combine.SourceRGB[s] == source)
- return;
- if (source == GL_TEXTURE ||
- source == GL_CONSTANT ||
- source == GL_PRIMARY_COLOR ||
- source == GL_PREVIOUS ||
- (ctx->Extensions.ARB_texture_env_crossbar &&
- source >= GL_TEXTURE0 &&
- source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) ||
- (ctx->Extensions.ATI_texture_env_combine3 &&
- (source == GL_ZERO || source == GL_ONE))) {
- /* legal */
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.SourceRGB[s] = source;
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
- return;
- }
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
- return;
- }
- break;
+ case GL_SOURCE3_RGB_NV:
case GL_SOURCE0_ALPHA:
case GL_SOURCE1_ALPHA:
case GL_SOURCE2_ALPHA:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const GLenum source = (GLenum) (GLint) *param;
- const GLuint s = pname - GL_SOURCE0_ALPHA;
- if (texUnit->Combine.SourceA[s] == source)
- return;
- if (source == GL_TEXTURE ||
- source == GL_CONSTANT ||
- source == GL_PRIMARY_COLOR ||
- source == GL_PREVIOUS ||
- (ctx->Extensions.ARB_texture_env_crossbar &&
- source >= GL_TEXTURE0 &&
- source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) ||
- (ctx->Extensions.ATI_texture_env_combine3 &&
- (source == GL_ZERO || source == GL_ONE))) {
- /* legal */
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.SourceA[s] = source;
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
- return;
- }
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
- return;
- }
+ case GL_SOURCE3_ALPHA_NV:
+ set_combiner_source(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
break;
case GL_OPERAND0_RGB:
case GL_OPERAND1_RGB:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const GLenum operand = (GLenum) (GLint) *param;
- const GLuint s = pname - GL_OPERAND0_RGB;
- if (texUnit->Combine.OperandRGB[s] == operand)
- return;
- switch (operand) {
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.OperandRGB[s] = operand;
- break;
- default:
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
- return;
- }
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
- return;
- }
- break;
+ case GL_OPERAND2_RGB:
+ case GL_OPERAND3_RGB_NV:
case GL_OPERAND0_ALPHA:
case GL_OPERAND1_ALPHA:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const GLenum operand = (GLenum) (GLint) *param;
- if (texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] == operand)
- return;
- switch (operand) {
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] = operand;
- break;
- default:
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
- return;
- }
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
- return;
- }
- break;
- case GL_OPERAND2_RGB:
- if (ctx->Extensions.ARB_texture_env_combine) {
- const GLenum operand = (GLenum) (GLint) *param;
- if (texUnit->Combine.OperandRGB[2] == operand)
- return;
- switch (operand) {
- case GL_SRC_COLOR: /* ARB combine only */
- case GL_ONE_MINUS_SRC_COLOR: /* ARB combine only */
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.OperandRGB[2] = operand;
- break;
- default:
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
- return;
- }
- }
- else if (ctx->Extensions.EXT_texture_env_combine) {
- const GLenum operand = (GLenum) (GLint) *param;
- if (texUnit->Combine.OperandRGB[2] == operand)
- return;
- /* operand must be GL_SRC_ALPHA which is the initial value - thus
- don't need to actually compare the operand to the possible value */
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
- return;
- }
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
- return;
- }
- break;
case GL_OPERAND2_ALPHA:
- if (ctx->Extensions.ARB_texture_env_combine) {
- const GLenum operand = (GLenum) (GLint) *param;
- if (texUnit->Combine.OperandA[2] == operand)
- return;
- switch (operand) {
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.OperandA[2] = operand;
- break;
- default:
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
- return;
- }
- }
- else if (ctx->Extensions.EXT_texture_env_combine) {
- const GLenum operand = (GLenum) (GLint) *param;
- if (texUnit->Combine.OperandA[2] == operand)
- return;
- /* operand must be GL_SRC_ALPHA which is the initial value - thus
- don't need to actually compare the operand to the possible value */
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
- return;
- }
- }
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
- return;
- }
+ case GL_OPERAND3_ALPHA_NV:
+ set_combiner_operand(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
break;
case GL_RGB_SCALE:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- GLuint newshift;
- if (*param == 1.0) {
- newshift = 0;
- }
- else if (*param == 2.0) {
- newshift = 1;
- }
- else if (*param == 4.0) {
- newshift = 2;
- }
- else {
- _mesa_error( ctx, GL_INVALID_VALUE,
- "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
- return;
- }
- if (texUnit->Combine.ScaleShiftRGB == newshift)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.ScaleShiftRGB = newshift;
+ case GL_ALPHA_SCALE:
+ set_combiner_scale(ctx, texUnit, pname, param[0]);
+ break;
+ case GL_BUMP_TARGET_ATI:
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
+ return;
}
- else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ if (((GLenum) (GLint) param[0] < GL_TEXTURE0) ||
+ ((GLenum) (GLint) param[0] > GL_TEXTURE31)) {
+ /* spec doesn't say this but it seems logical */
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
return;
}
- break;
- case GL_ALPHA_SCALE:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- GLuint newshift;
- if (*param == 1.0) {
- newshift = 0;
- }
- else if (*param == 2.0) {
- newshift = 1;
- }
- else if (*param == 4.0) {
- newshift = 2;
- }
- else {
- _mesa_error( ctx, GL_INVALID_VALUE,
- "glTexEnv(GL_ALPHA_SCALE not 1, 2 or 4)" );
- return;
- }
- if (texUnit->Combine.ScaleShiftA == newshift)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->Combine.ScaleShiftA = newshift;
+ if (!((1 << ((GLenum) (GLint) param[0] - GL_TEXTURE0)) & ctx->Const.SupportedBumpUnits)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
+ return;
}
else {
- TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
- return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->BumpTarget = (GLenum) (GLint) param[0];
}
break;
default:
@@ -533,6 +631,154 @@ _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
}
+
+/**
+ * Helper for glGetTexEnvi/f()
+ * \return value of queried pname or -1 if error.
+ */
+static GLint
+get_texenvi(GLcontext *ctx, const struct gl_texture_unit *texUnit,
+ GLenum pname)
+{
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ return texUnit->EnvMode;
+ break;
+ case GL_COMBINE_RGB:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ return texUnit->Combine.ModeRGB;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_COMBINE_ALPHA:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ return texUnit->Combine.ModeA;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_SOURCE0_RGB:
+ case GL_SOURCE1_RGB:
+ case GL_SOURCE2_RGB:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
+ return texUnit->Combine.SourceRGB[rgb_idx];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_SOURCE3_RGB_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ return texUnit->Combine.SourceRGB[3];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_SOURCE0_ALPHA:
+ case GL_SOURCE1_ALPHA:
+ case GL_SOURCE2_ALPHA:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
+ return texUnit->Combine.SourceA[alpha_idx];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_SOURCE3_ALPHA_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ return texUnit->Combine.SourceA[3];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_OPERAND0_RGB:
+ case GL_OPERAND1_RGB:
+ case GL_OPERAND2_RGB:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ const unsigned op_rgb = pname - GL_OPERAND0_RGB;
+ return texUnit->Combine.OperandRGB[op_rgb];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_OPERAND3_RGB_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ return texUnit->Combine.OperandRGB[3];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_OPERAND0_ALPHA:
+ case GL_OPERAND1_ALPHA:
+ case GL_OPERAND2_ALPHA:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
+ return texUnit->Combine.OperandA[op_alpha];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_OPERAND3_ALPHA_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ return texUnit->Combine.OperandA[3];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_RGB_SCALE:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ return 1 << texUnit->Combine.ScaleShiftRGB;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_ALPHA_SCALE:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ return 1 << texUnit->Combine.ScaleShiftA;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_BUMP_TARGET_ATI:
+ /* spec doesn't say so, but I think this should be queryable */
+ if (ctx->Extensions.ATI_envmap_bumpmap) {
+ return texUnit->BumpTarget;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ return -1; /* error */
+}
+
+
+
void GLAPIENTRY
_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
{
@@ -548,114 +794,17 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
if (target == GL_TEXTURE_ENV) {
- switch (pname) {
- case GL_TEXTURE_ENV_MODE:
- *params = ENUM_TO_FLOAT(texUnit->EnvMode);
- break;
- case GL_TEXTURE_ENV_COLOR:
- COPY_4FV( params, texUnit->EnvColor );
- break;
- case GL_COMBINE_RGB:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->Combine.ModeRGB;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
- }
- break;
- case GL_COMBINE_ALPHA:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLfloat) texUnit->Combine.ModeA;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
- }
- break;
- case GL_SOURCE0_RGB:
- case GL_SOURCE1_RGB:
- case GL_SOURCE2_RGB:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
- *params = (GLfloat) texUnit->Combine.SourceRGB[rgb_idx];
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
- }
- break;
- case GL_SOURCE0_ALPHA:
- case GL_SOURCE1_ALPHA:
- case GL_SOURCE2_ALPHA:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
- *params = (GLfloat) texUnit->Combine.SourceA[alpha_idx];
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
- }
- break;
- case GL_OPERAND0_RGB:
- case GL_OPERAND1_RGB:
- case GL_OPERAND2_RGB:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const unsigned op_rgb = pname - GL_OPERAND0_RGB;
- *params = (GLfloat) texUnit->Combine.OperandRGB[op_rgb];
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
- }
- break;
- case GL_OPERAND0_ALPHA:
- case GL_OPERAND1_ALPHA:
- case GL_OPERAND2_ALPHA:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
- *params = (GLfloat) texUnit->Combine.OperandA[op_alpha];
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
- }
- break;
- case GL_RGB_SCALE:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- if (texUnit->Combine.ScaleShiftRGB == 0)
- *params = 1.0;
- else if (texUnit->Combine.ScaleShiftRGB == 1)
- *params = 2.0;
- else
- *params = 4.0;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
- return;
- }
- break;
- case GL_ALPHA_SCALE:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- if (texUnit->Combine.ScaleShiftA == 0)
- *params = 1.0;
- else if (texUnit->Combine.ScaleShiftA == 1)
- *params = 2.0;
- else
- *params = 4.0;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
- return;
- }
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname=0x%x)", pname);
+ if (pname == GL_TEXTURE_ENV_COLOR) {
+ COPY_4FV( params, texUnit->EnvColor );
+ }
+ else {
+ GLint val = get_texenvi(ctx, texUnit, pname);
+ if (val >= 0) {
+ *params = (GLfloat) val;
+ }
}
}
else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
@@ -709,118 +858,20 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
if (target == GL_TEXTURE_ENV) {
- switch (pname) {
- case GL_TEXTURE_ENV_MODE:
- *params = (GLint) texUnit->EnvMode;
- break;
- case GL_TEXTURE_ENV_COLOR:
- params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
- params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
- params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
- params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
- break;
- case GL_COMBINE_RGB:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->Combine.ModeRGB;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
- }
- break;
- case GL_COMBINE_ALPHA:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- *params = (GLint) texUnit->Combine.ModeA;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
- }
- break;
- case GL_SOURCE0_RGB:
- case GL_SOURCE1_RGB:
- case GL_SOURCE2_RGB:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
- *params = (GLint) texUnit->Combine.SourceRGB[rgb_idx];
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
- }
- break;
- case GL_SOURCE0_ALPHA:
- case GL_SOURCE1_ALPHA:
- case GL_SOURCE2_ALPHA:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
- *params = (GLint) texUnit->Combine.SourceA[alpha_idx];
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
- }
- break;
- case GL_OPERAND0_RGB:
- case GL_OPERAND1_RGB:
- case GL_OPERAND2_RGB:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const unsigned op_rgb = pname - GL_OPERAND0_RGB;
- *params = (GLint) texUnit->Combine.OperandRGB[op_rgb];
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
- }
- break;
- case GL_OPERAND0_ALPHA:
- case GL_OPERAND1_ALPHA:
- case GL_OPERAND2_ALPHA:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
- *params = (GLint) texUnit->Combine.OperandA[op_alpha];
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
- }
- break;
- case GL_RGB_SCALE:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- if (texUnit->Combine.ScaleShiftRGB == 0)
- *params = 1;
- else if (texUnit->Combine.ScaleShiftRGB == 1)
- *params = 2;
- else
- *params = 4;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
- return;
- }
- break;
- case GL_ALPHA_SCALE:
- if (ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine) {
- if (texUnit->Combine.ScaleShiftA == 0)
- *params = 1;
- else if (texUnit->Combine.ScaleShiftA == 1)
- *params = 2;
- else
- *params = 4;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
- return;
- }
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname=0x%x)",
- pname);
+ if (pname == GL_TEXTURE_ENV_COLOR) {
+ params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
+ params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
+ params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
+ params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
+ }
+ else {
+ GLint val = get_texenvi(ctx, texUnit, pname);
+ if (val >= 0) {
+ *params = val;
+ }
}
}
else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
@@ -859,3 +910,169 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
}
+/**
+ * Why does ATI_envmap_bumpmap require new entrypoints? Should just
+ * reuse TexEnv ones...
+ */
+void GLAPIENTRY
+_mesa_TexBumpParameterivATI( GLenum pname, const GLint *param )
+{
+ GLfloat p[4];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ /* This isn't an "official" error case, but let's tell the user
+ * that something's wrong.
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterivATI");
+ return;
+ }
+
+ if (pname == GL_BUMP_ROT_MATRIX_ATI) {
+ /* hope that conversion is correct here */
+ p[0] = INT_TO_FLOAT( param[0] );
+ p[1] = INT_TO_FLOAT( param[1] );
+ p[2] = INT_TO_FLOAT( param[2] );
+ p[3] = INT_TO_FLOAT( param[3] );
+ }
+ else {
+ p[0] = (GLfloat) param[0];
+ p[1] = p[2] = p[3] = 0.0F; /* init to zero, just to be safe */
+ }
+ _mesa_TexBumpParameterfvATI( pname, p );
+}
+
+
+void GLAPIENTRY
+_mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param )
+{
+ struct gl_texture_unit *texUnit;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterfvATI");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ if (pname == GL_BUMP_ROT_MATRIX_ATI) {
+ if (TEST_EQ_4V(param, texUnit->RotMatrix))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ COPY_4FV(texUnit->RotMatrix, param);
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexBumpParameter(pname)" );
+ return;
+ }
+ /* Drivers might want to know about this, instead of dedicated function
+ just shove it into TexEnv where it really belongs anyway */
+ if (ctx->Driver.TexEnv) {
+ (*ctx->Driver.TexEnv)( ctx, 0, pname, param );
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param )
+{
+ const struct gl_texture_unit *texUnit;
+ GLuint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterivATI");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
+ /* spec leaves open to support larger matrices.
+ Don't think anyone would ever want to use it
+ (and apps almost certainly would not understand it and
+ thus fail to submit matrices correctly) so hardcode this. */
+ *param = 4;
+ }
+ else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
+ /* hope that conversion is correct here */
+ param[0] = FLOAT_TO_INT(texUnit->RotMatrix[0]);
+ param[1] = FLOAT_TO_INT(texUnit->RotMatrix[1]);
+ param[2] = FLOAT_TO_INT(texUnit->RotMatrix[2]);
+ param[3] = FLOAT_TO_INT(texUnit->RotMatrix[3]);
+ }
+ else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
+ GLint count = 0;
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Const.SupportedBumpUnits & (1 << i)) {
+ count++;
+ }
+ }
+ *param = count;
+ }
+ else if (pname == GL_BUMP_TEX_UNITS_ATI) {
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Const.SupportedBumpUnits & (1 << i)) {
+ *param++ = i + GL_TEXTURE0;
+ }
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param )
+{
+ const struct gl_texture_unit *texUnit;
+ GLuint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterfvATI");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
+ /* spec leaves open to support larger matrices.
+ Don't think anyone would ever want to use it
+ (and apps might not understand it) so hardcode this. */
+ *param = 4.0F;
+ }
+ else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
+ param[0] = texUnit->RotMatrix[0];
+ param[1] = texUnit->RotMatrix[1];
+ param[2] = texUnit->RotMatrix[2];
+ param[3] = texUnit->RotMatrix[3];
+ }
+ else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
+ GLint count = 0;
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Const.SupportedBumpUnits & (1 << i)) {
+ count++;
+ }
+ }
+ *param = (GLfloat) count;
+ }
+ else if (pname == GL_BUMP_TEX_UNITS_ATI) {
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Const.SupportedBumpUnits & (1 << i)) {
+ *param++ = (GLfloat) (i + GL_TEXTURE0);
+ }
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
+ return;
+ }
+}
diff --git a/src/mesa/main/texenv.h b/src/mesa/main/texenv.h
index bdff7fdb82..1e9c5faed7 100644
--- a/src/mesa/main/texenv.h
+++ b/src/mesa/main/texenv.h
@@ -48,5 +48,16 @@ _mesa_TexEnvi( GLenum target, GLenum pname, GLint param );
extern void GLAPIENTRY
_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param );
+extern void GLAPIENTRY
+_mesa_TexBumpParameterivATI( GLenum pname, const GLint *param );
+
+extern void GLAPIENTRY
+_mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param );
+
+extern void GLAPIENTRY
+_mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param );
+
+extern void GLAPIENTRY
+_mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param );
#endif /* TEXENV_H */
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c
index 6a57d50193..2f3e47e69e 100644
--- a/src/mesa/main/texenvprogram.c
+++ b/src/mesa/main/texenvprogram.c
@@ -2,6 +2,7 @@
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -26,8 +27,7 @@
**************************************************************************/
#include "glheader.h"
-#include "macros.h"
-#include "enums.h"
+#include "imports.h"
#include "shader/program.h"
#include "shader/prog_parameter.h"
#include "shader/prog_cache.h"
@@ -61,42 +61,61 @@ struct texenvprog_cache_item
struct texenvprog_cache_item *next;
};
+static GLboolean
+texenv_doing_secondary_color(GLcontext *ctx)
+{
+ if (ctx->Light.Enabled &&
+ (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR))
+ return GL_TRUE;
+
+ if (ctx->Fog.ColorSumEnabled)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
/**
- * This MAX is probably a bit generous, but that's OK. There can be
- * up to four instructions per texture unit (TEX + 3 for combine),
- * then there's fog and specular add.
+ * Up to nine instructions per tex unit, plus fog, specular color.
*/
-#define MAX_INSTRUCTIONS ((MAX_TEXTURE_COORD_UNITS * 4) + 12)
+#define MAX_INSTRUCTIONS ((MAX_TEXTURE_COORD_UNITS * 9) + 12)
#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
struct mode_opt {
- GLuint Source:4;
- GLuint Operand:3;
+#ifdef __GNUC__
+ __extension__ GLubyte Source:4; /**< SRC_x */
+ __extension__ GLubyte Operand:3; /**< OPR_x */
+#else
+ GLubyte Source; /**< SRC_x */
+ GLubyte Operand; /**< OPR_x */
+#endif
};
struct state_key {
- GLbitfield enabled_units;
+ GLuint nr_enabled_units:8;
+ GLuint enabled_units:8;
GLuint separate_specular:1;
GLuint fog_enabled:1;
- GLuint fog_mode:2;
+ GLuint fog_mode:2; /**< FOG_x */
+ GLuint inputs_available:12;
+ /* NOTE: This array of structs must be last! (see "keySize" below) */
struct {
GLuint enabled:1;
- GLuint source_index:3; /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */
+ GLuint source_index:3; /**< TEXTURE_x_INDEX */
GLuint shadow:1;
GLuint ScaleShiftRGB:2;
GLuint ScaleShiftA:2;
- GLuint NumArgsRGB:2;
- GLuint ModeRGB:4;
- struct mode_opt OptRGB[3];
+ GLuint NumArgsRGB:3; /**< up to MAX_COMBINER_TERMS */
+ GLuint ModeRGB:5; /**< MODE_x */
+
+ GLuint NumArgsA:3; /**< up to MAX_COMBINER_TERMS */
+ GLuint ModeA:5; /**< MODE_x */
- GLuint NumArgsA:2;
- GLuint ModeA:4;
- struct mode_opt OptA[3];
- } unit[8];
+ struct mode_opt OptRGB[MAX_COMBINER_TERMS];
+ struct mode_opt OptA[MAX_COMBINER_TERMS];
+ } unit[MAX_TEXTURE_UNITS];
};
#define FOG_LINEAR 0
@@ -131,7 +150,9 @@ static GLuint translate_operand( GLenum operand )
case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
case GL_ZERO: return OPR_ZERO;
case GL_ONE: return OPR_ONE;
- default: return OPR_UNKNOWN;
+ default:
+ assert(0);
+ return OPR_UNKNOWN;
}
}
@@ -147,6 +168,7 @@ static GLuint translate_operand( GLenum operand )
#define SRC_CONSTANT 9
#define SRC_PRIMARY_COLOR 10
#define SRC_PREVIOUS 11
+#define SRC_ZERO 12
#define SRC_UNKNOWN 15
static GLuint translate_source( GLenum src )
@@ -164,32 +186,50 @@ static GLuint translate_source( GLenum src )
case GL_CONSTANT: return SRC_CONSTANT;
case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
case GL_PREVIOUS: return SRC_PREVIOUS;
- default: return SRC_UNKNOWN;
+ case GL_ZERO:
+ return SRC_ZERO;
+ default:
+ assert(0);
+ return SRC_UNKNOWN;
}
}
-#define MODE_REPLACE 0
-#define MODE_MODULATE 1
-#define MODE_ADD 2
-#define MODE_ADD_SIGNED 3
-#define MODE_INTERPOLATE 4
-#define MODE_SUBTRACT 5
-#define MODE_DOT3_RGB 6
-#define MODE_DOT3_RGB_EXT 7
-#define MODE_DOT3_RGBA 8
-#define MODE_DOT3_RGBA_EXT 9
-#define MODE_MODULATE_ADD_ATI 10
-#define MODE_MODULATE_SIGNED_ADD_ATI 11
-#define MODE_MODULATE_SUBTRACT_ATI 12
-#define MODE_UNKNOWN 15
-
-static GLuint translate_mode( GLenum mode )
+#define MODE_REPLACE 0 /* r = a0 */
+#define MODE_MODULATE 1 /* r = a0 * a1 */
+#define MODE_ADD 2 /* r = a0 + a1 */
+#define MODE_ADD_SIGNED 3 /* r = a0 + a1 - 0.5 */
+#define MODE_INTERPOLATE 4 /* r = a0 * a2 + a1 * (1 - a2) */
+#define MODE_SUBTRACT 5 /* r = a0 - a1 */
+#define MODE_DOT3_RGB 6 /* r = a0 . a1 */
+#define MODE_DOT3_RGB_EXT 7 /* r = a0 . a1 */
+#define MODE_DOT3_RGBA 8 /* r = a0 . a1 */
+#define MODE_DOT3_RGBA_EXT 9 /* r = a0 . a1 */
+#define MODE_MODULATE_ADD_ATI 10 /* r = a0 * a2 + a1 */
+#define MODE_MODULATE_SIGNED_ADD_ATI 11 /* r = a0 * a2 + a1 - 0.5 */
+#define MODE_MODULATE_SUBTRACT_ATI 12 /* r = a0 * a2 - a1 */
+#define MODE_ADD_PRODUCTS 13 /* r = a0 * a1 + a2 * a3 */
+#define MODE_ADD_PRODUCTS_SIGNED 14 /* r = a0 * a1 + a2 * a3 - 0.5 */
+#define MODE_BUMP_ENVMAP_ATI 15 /* special */
+#define MODE_UNKNOWN 16
+
+/**
+ * Translate GL combiner state into a MODE_x value
+ */
+static GLuint translate_mode( GLenum envMode, GLenum mode )
{
switch (mode) {
case GL_REPLACE: return MODE_REPLACE;
case GL_MODULATE: return MODE_MODULATE;
- case GL_ADD: return MODE_ADD;
- case GL_ADD_SIGNED: return MODE_ADD_SIGNED;
+ case GL_ADD:
+ if (envMode == GL_COMBINE4_NV)
+ return MODE_ADD_PRODUCTS;
+ else
+ return MODE_ADD;
+ case GL_ADD_SIGNED:
+ if (envMode == GL_COMBINE4_NV)
+ return MODE_ADD_PRODUCTS_SIGNED;
+ else
+ return MODE_ADD_SIGNED;
case GL_INTERPOLATE: return MODE_INTERPOLATE;
case GL_SUBTRACT: return MODE_SUBTRACT;
case GL_DOT3_RGB: return MODE_DOT3_RGB;
@@ -199,84 +239,257 @@ static GLuint translate_mode( GLenum mode )
case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
- default: return MODE_UNKNOWN;
+ case GL_BUMP_ENVMAP_ATI: return MODE_BUMP_ENVMAP_ATI;
+ default:
+ assert(0);
+ return MODE_UNKNOWN;
+ }
+}
+
+
+/**
+ * Do we need to clamp the results of the given texture env/combine mode?
+ * If the inputs to the mode are in [0,1] we don't always have to clamp
+ * the results.
+ */
+static GLboolean
+need_saturate( GLuint mode )
+{
+ switch (mode) {
+ case MODE_REPLACE:
+ case MODE_MODULATE:
+ case MODE_INTERPOLATE:
+ return GL_FALSE;
+ case MODE_ADD:
+ case MODE_ADD_SIGNED:
+ case MODE_SUBTRACT:
+ case MODE_DOT3_RGB:
+ case MODE_DOT3_RGB_EXT:
+ case MODE_DOT3_RGBA:
+ case MODE_DOT3_RGBA_EXT:
+ case MODE_MODULATE_ADD_ATI:
+ case MODE_MODULATE_SIGNED_ADD_ATI:
+ case MODE_MODULATE_SUBTRACT_ATI:
+ case MODE_ADD_PRODUCTS:
+ case MODE_ADD_PRODUCTS_SIGNED:
+ case MODE_BUMP_ENVMAP_ATI:
+ return GL_TRUE;
+ default:
+ assert(0);
}
}
-#define TEXTURE_UNKNOWN_INDEX 7
+
+
+/**
+ * Translate TEXTURE_x_BIT to TEXTURE_x_INDEX.
+ */
static GLuint translate_tex_src_bit( GLbitfield bit )
{
- switch (bit) {
- case TEXTURE_1D_BIT: return TEXTURE_1D_INDEX;
- case TEXTURE_2D_BIT: return TEXTURE_2D_INDEX;
- case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX;
- case TEXTURE_3D_BIT: return TEXTURE_3D_INDEX;
- case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX;
- default: return TEXTURE_UNKNOWN_INDEX;
+ ASSERT(bit);
+ return _mesa_ffs(bit) - 1;
+}
+
+
+#define VERT_BIT_TEX_ANY (0xff << VERT_ATTRIB_TEX0)
+#define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0)
+
+/**
+ * Identify all possible varying inputs. The fragment program will
+ * never reference non-varying inputs, but will track them via state
+ * constants instead.
+ *
+ * This function figures out all the inputs that the fragment program
+ * has access to. The bitmask is later reduced to just those which
+ * are actually referenced.
+ */
+static GLbitfield get_fp_input_mask( GLcontext *ctx )
+{
+ /* _NEW_PROGRAM */
+ const GLboolean vertexShader = (ctx->Shader.CurrentProgram &&
+ ctx->Shader.CurrentProgram->LinkStatus &&
+ ctx->Shader.CurrentProgram->VertexProgram);
+ const GLboolean vertexProgram = ctx->VertexProgram._Enabled;
+ GLbitfield fp_inputs = 0x0;
+
+ if (ctx->VertexProgram._Overriden) {
+ /* Somebody's messing with the vertex program and we don't have
+ * a clue what's happening. Assume that it could be producing
+ * all possible outputs.
+ */
+ fp_inputs = ~0;
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ /* _NEW_RENDERMODE */
+ fp_inputs = (FRAG_BIT_COL0 | FRAG_BIT_TEX0);
}
+ else if (!(vertexProgram || vertexShader) ||
+ !ctx->VertexProgram._Current) {
+ /* Fixed function vertex logic */
+ /* _NEW_ARRAY */
+ GLbitfield varying_inputs = ctx->varying_vp_inputs;
+
+ /* These get generated in the setup routine regardless of the
+ * vertex program:
+ */
+ /* _NEW_POINT */
+ if (ctx->Point.PointSprite)
+ varying_inputs |= FRAG_BITS_TEX_ANY;
+
+ /* First look at what values may be computed by the generated
+ * vertex program:
+ */
+ /* _NEW_LIGHT */
+ if (ctx->Light.Enabled) {
+ fp_inputs |= FRAG_BIT_COL0;
+
+ if (texenv_doing_secondary_color(ctx))
+ fp_inputs |= FRAG_BIT_COL1;
+ }
+
+ /* _NEW_TEXTURE */
+ fp_inputs |= (ctx->Texture._TexGenEnabled |
+ ctx->Texture._TexMatEnabled) << FRAG_ATTRIB_TEX0;
+
+ /* Then look at what might be varying as a result of enabled
+ * arrays, etc:
+ */
+ if (varying_inputs & VERT_BIT_COLOR0)
+ fp_inputs |= FRAG_BIT_COL0;
+ if (varying_inputs & VERT_BIT_COLOR1)
+ fp_inputs |= FRAG_BIT_COL1;
+
+ fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0)
+ << FRAG_ATTRIB_TEX0);
+
+ }
+ else {
+ /* calculate from vp->outputs */
+ struct gl_vertex_program *vprog;
+ GLbitfield vp_outputs;
+
+ /* Choose GLSL vertex shader over ARB vertex program. Need this
+ * since vertex shader state validation comes after fragment state
+ * validation (see additional comments in state.c).
+ */
+ if (vertexShader)
+ vprog = ctx->Shader.CurrentProgram->VertexProgram;
+ else
+ vprog = ctx->VertexProgram.Current;
+
+ vp_outputs = vprog->Base.OutputsWritten;
+
+ /* These get generated in the setup routine regardless of the
+ * vertex program:
+ */
+ /* _NEW_POINT */
+ if (ctx->Point.PointSprite)
+ vp_outputs |= FRAG_BITS_TEX_ANY;
+
+ if (vp_outputs & (1 << VERT_RESULT_COL0))
+ fp_inputs |= FRAG_BIT_COL0;
+ if (vp_outputs & (1 << VERT_RESULT_COL1))
+ fp_inputs |= FRAG_BIT_COL1;
+
+ fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) >> VERT_RESULT_TEX0)
+ << FRAG_ATTRIB_TEX0);
+ }
+
+ return fp_inputs;
}
+
/**
* Examine current texture environment state and generate a unique
* key to identify it.
*/
-static void make_state_key( GLcontext *ctx, struct state_key *key )
+static GLuint make_state_key( GLcontext *ctx, struct state_key *key )
{
GLuint i, j;
-
+ GLbitfield inputs_referenced = FRAG_BIT_COL0;
+ const GLbitfield inputs_available = get_fp_input_mask( ctx );
+ GLuint keySize;
+
memset(key, 0, sizeof(*key));
+ /* _NEW_TEXTURE */
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+ const struct gl_texture_object *texObj = texUnit->_Current;
+ const struct gl_tex_env_combine_state *comb = texUnit->_CurrentCombine;
GLenum format;
if (!texUnit->_ReallyEnabled || !texUnit->Enabled)
continue;
- format = texUnit->_Current->Image[0][texUnit->_Current->BaseLevel]->_BaseFormat;
+ format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
key->unit[i].enabled = 1;
key->enabled_units |= (1<<i);
+ key->nr_enabled_units = i + 1;
+ inputs_referenced |= FRAG_BIT_TEX(i);
+
+ key->unit[i].source_index =
+ translate_tex_src_bit(texUnit->_ReallyEnabled);
- key->unit[i].source_index =
- translate_tex_src_bit(texUnit->_ReallyEnabled);
- key->unit[i].shadow = ((texUnit->_Current->CompareMode == GL_COMPARE_R_TO_TEXTURE) &&
+ key->unit[i].shadow = ((texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE) &&
((format == GL_DEPTH_COMPONENT) ||
(format == GL_DEPTH_STENCIL_EXT)));
- key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB;
- key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA;
+ key->unit[i].NumArgsRGB = comb->_NumArgsRGB;
+ key->unit[i].NumArgsA = comb->_NumArgsA;
key->unit[i].ModeRGB =
- translate_mode(texUnit->_CurrentCombine->ModeRGB);
+ translate_mode(texUnit->EnvMode, comb->ModeRGB);
key->unit[i].ModeA =
- translate_mode(texUnit->_CurrentCombine->ModeA);
-
- key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB;
- key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftA;
-
- for (j=0;j<3;j++) {
- key->unit[i].OptRGB[j].Operand =
- translate_operand(texUnit->_CurrentCombine->OperandRGB[j]);
- key->unit[i].OptA[j].Operand =
- translate_operand(texUnit->_CurrentCombine->OperandA[j]);
- key->unit[i].OptRGB[j].Source =
- translate_source(texUnit->_CurrentCombine->SourceRGB[j]);
- key->unit[i].OptA[j].Source =
- translate_source(texUnit->_CurrentCombine->SourceA[j]);
+ translate_mode(texUnit->EnvMode, comb->ModeA);
+
+ key->unit[i].ScaleShiftRGB = comb->ScaleShiftRGB;
+ key->unit[i].ScaleShiftA = comb->ScaleShiftA;
+
+ for (j = 0; j < MAX_COMBINER_TERMS; j++) {
+ key->unit[i].OptRGB[j].Operand = translate_operand(comb->OperandRGB[j]);
+ key->unit[i].OptA[j].Operand = translate_operand(comb->OperandA[j]);
+ key->unit[i].OptRGB[j].Source = translate_source(comb->SourceRGB[j]);
+ key->unit[i].OptA[j].Source = translate_source(comb->SourceA[j]);
}
+
+ if (key->unit[i].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
+ /* requires some special translation */
+ key->unit[i].NumArgsRGB = 2;
+ key->unit[i].ScaleShiftRGB = 0;
+ key->unit[i].OptRGB[0].Operand = OPR_SRC_COLOR;
+ key->unit[i].OptRGB[0].Source = SRC_TEXTURE;
+ key->unit[i].OptRGB[1].Operand = OPR_SRC_COLOR;
+ key->unit[i].OptRGB[1].Source = texUnit->BumpTarget - GL_TEXTURE0 + SRC_TEXTURE0;
+ }
}
-
- if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+
+ /* _NEW_LIGHT | _NEW_FOG */
+ if (texenv_doing_secondary_color(ctx)) {
key->separate_specular = 1;
+ inputs_referenced |= FRAG_BIT_COL1;
+ }
+ /* _NEW_FOG */
if (ctx->Fog.Enabled) {
key->fog_enabled = 1;
key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
+ inputs_referenced |= FRAG_BIT_FOGC; /* maybe */
}
+
+ key->inputs_available = (inputs_available & inputs_referenced);
+
+ /* compute size of state key, ignoring unused texture units */
+ keySize = sizeof(*key) - sizeof(key->unit)
+ + key->nr_enabled_units * sizeof(key->unit[0]);
+
+ return keySize;
}
-/* Use uregs to represent registers internally, translate to Mesa's
+
+/**
+ * Use uregs to represent registers internally, translate to Mesa's
* expected formats on emit.
*
* NOTE: These are passed by value extensively in this file rather
@@ -292,10 +505,8 @@ struct ureg {
GLuint file:4;
GLuint idx:8;
GLuint negatebase:1;
- GLuint abs:1;
- GLuint negateabs:1;
GLuint swz:12;
- GLuint pad:5;
+ GLuint pad:7;
};
static const struct ureg undef = {
@@ -303,22 +514,19 @@ static const struct ureg undef = {
~0,
0,
0,
- 0,
- 0,
0
};
-/* State used to build the fragment program:
+/** State used to build the fragment program:
*/
struct texenv_fragment_program {
struct gl_fragment_program *program;
- GLcontext *ctx;
struct state_key *state;
- GLbitfield alu_temps; /* Track texture indirections, see spec. */
- GLbitfield temps_output; /* Track texture indirections, see spec. */
- GLbitfield temp_in_use; /* Tracks temporary regs which are in use. */
+ GLbitfield alu_temps; /**< Track texture indirections, see spec. */
+ GLbitfield temps_output; /**< Track texture indirections, see spec. */
+ GLbitfield temp_in_use; /**< Tracks temporary regs which are in use. */
GLboolean error;
struct ureg src_texture[MAX_TEXTURE_COORD_UNITS];
@@ -326,11 +534,16 @@ struct texenv_fragment_program {
* else undef.
*/
- struct ureg src_previous; /* Reg containing color from previous
+ struct ureg texcoord_tex[MAX_TEXTURE_COORD_UNITS];
+ /* Reg containing texcoord for a texture unit,
+ * needed for bump mapping, else undef.
+ */
+
+ struct ureg src_previous; /**< Reg containing color from previous
* stage. May need to be decl'd.
*/
- GLuint last_tex_stage; /* Number of last enabled texture unit */
+ GLuint last_tex_stage; /**< Number of last enabled texture unit */
struct ureg half;
struct ureg one;
@@ -345,8 +558,6 @@ static struct ureg make_ureg(GLuint file, GLuint idx)
reg.file = file;
reg.idx = idx;
reg.negatebase = 0;
- reg.abs = 0;
- reg.negateabs = 0;
reg.swz = SWIZZLE_NOOP;
reg.pad = 0;
return reg;
@@ -408,7 +619,7 @@ static struct ureg get_tex_temp( struct texenv_fragment_program *p )
{
int bit;
- /* First try to find availble temp not previously used (to avoid
+ /* First try to find available temp not previously used (to avoid
* starting a new texture indirection). According to the spec, the
* ~p->temps_output isn't necessary, but will keep it there for
* now:
@@ -433,6 +644,14 @@ static struct ureg get_tex_temp( struct texenv_fragment_program *p )
}
+/** Mark a temp reg as being no longer allocatable. */
+static void reserve_temp( struct texenv_fragment_program *p, struct ureg r )
+{
+ if (r.file == PROGRAM_TEMPORARY)
+ p->temps_output |= (1 << r.idx);
+}
+
+
static void release_temps(GLcontext *ctx, struct texenv_fragment_program *p )
{
GLuint max_temp = ctx->Const.FragmentProgram.MaxTemps;
@@ -471,11 +690,29 @@ static struct ureg register_param5( struct texenv_fragment_program *p,
#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0)
#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
+static GLuint frag_to_vert_attrib( GLuint attrib )
+{
+ switch (attrib) {
+ case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0;
+ case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1;
+ default:
+ assert(attrib >= FRAG_ATTRIB_TEX0);
+ assert(attrib <= FRAG_ATTRIB_TEX7);
+ return attrib - FRAG_ATTRIB_TEX0 + VERT_ATTRIB_TEX0;
+ }
+}
+
static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
{
- p->program->Base.InputsRead |= (1 << input);
- return make_ureg(PROGRAM_INPUT, input);
+ if (p->state->inputs_available & (1<<input)) {
+ p->program->Base.InputsRead |= (1 << input);
+ return make_ureg(PROGRAM_INPUT, input);
+ }
+ else {
+ GLuint idx = frag_to_vert_attrib( input );
+ return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx );
+ }
}
@@ -485,9 +722,8 @@ static void emit_arg( struct prog_src_register *reg,
reg->File = ureg.file;
reg->Index = ureg.idx;
reg->Swizzle = ureg.swz;
- reg->NegateBase = ureg.negatebase ? 0xf : 0x0;
- reg->Abs = ureg.abs;
- reg->NegateAbs = ureg.negateabs;
+ reg->Negate = ureg.negatebase ? NEGATE_XYZW : NEGATE_NONE;
+ reg->Abs = GL_FALSE;
}
static void emit_dst( struct prog_dst_register *dst,
@@ -510,7 +746,7 @@ emit_op(struct texenv_fragment_program *p,
struct ureg src1,
struct ureg src2 )
{
- GLuint nr = p->program->Base.NumInstructions++;
+ const GLuint nr = p->program->Base.NumInstructions++;
struct prog_instruction *inst = &p->program->Base.Instructions[nr];
assert(nr < MAX_INSTRUCTIONS);
@@ -526,10 +762,12 @@ emit_op(struct texenv_fragment_program *p,
emit_dst( &inst->DstReg, dest, mask );
+#if 0
/* Accounting for indirection tracking:
*/
if (dest.file == PROGRAM_TEMPORARY)
p->temps_output |= 1 << dest.idx;
+#endif
return inst;
}
@@ -570,6 +808,7 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
GLuint destmask,
GLuint tex_unit,
GLuint tex_idx,
+ GLuint tex_shadow,
struct ureg coord )
{
struct prog_instruction *inst = emit_op( p, op,
@@ -581,9 +820,15 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
inst->TexSrcTarget = tex_idx;
inst->TexSrcUnit = tex_unit;
+ inst->TexShadow = tex_shadow;
p->program->Base.NumTexInstructions++;
+ /* Accounting for indirection tracking:
+ */
+ reserve_temp(p, dest);
+
+#if 0
/* Is this a texture indirection?
*/
if ((coord.file == PROGRAM_TEMPORARY &&
@@ -595,6 +840,7 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
p->alu_temps = 0;
assert(0); /* KW: texture env crossbar */
}
+#endif
return dest;
}
@@ -608,14 +854,16 @@ static struct ureg register_const4f( struct texenv_fragment_program *p,
{
GLfloat values[4];
GLuint idx, swizzle;
+ struct ureg r;
values[0] = s0;
values[1] = s1;
values[2] = s2;
values[3] = s3;
idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
&swizzle );
- ASSERT(swizzle == SWIZZLE_NOOP);
- return make_ureg(PROGRAM_CONSTANT, idx);
+ r = make_ureg(PROGRAM_CONSTANT, idx);
+ r.swz = swizzle;
+ return r;
}
#define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0)
@@ -677,12 +925,18 @@ static struct ureg get_source( struct texenv_fragment_program *p,
case SRC_PRIMARY_COLOR:
return register_input(p, FRAG_ATTRIB_COL0);
+ case SRC_ZERO:
+ return get_zero(p);
+
case SRC_PREVIOUS:
- default:
if (is_undef(p->src_previous))
return register_input(p, FRAG_ATTRIB_COL0);
else
return p->src_previous;
+
+ default:
+ assert(0);
+ return undef;
}
}
@@ -723,22 +977,29 @@ static struct ureg emit_combine_source( struct texenv_fragment_program *p,
case OPR_ONE:
return get_one(p);
case OPR_SRC_COLOR:
+ return src;
default:
+ assert(0);
return src;
}
}
-static GLboolean args_match( struct state_key *key, GLuint unit )
+/**
+ * Check if the RGB and Alpha sources and operands match for the given
+ * texture unit's combinder state. When the RGB and A sources and
+ * operands match, we can emit fewer instructions.
+ */
+static GLboolean args_match( const struct state_key *key, GLuint unit )
{
- GLuint i, nr = key->unit[unit].NumArgsRGB;
+ GLuint i, numArgs = key->unit[unit].NumArgsRGB;
- for (i = 0 ; i < nr ; i++) {
+ for (i = 0; i < numArgs; i++) {
if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
return GL_FALSE;
- switch(key->unit[unit].OptA[i].Operand) {
+ switch (key->unit[unit].OptA[i].Operand) {
case OPR_SRC_ALPHA:
- switch(key->unit[unit].OptRGB[i].Operand) {
+ switch (key->unit[unit].OptRGB[i].Operand) {
case OPR_SRC_COLOR:
case OPR_SRC_ALPHA:
break;
@@ -747,7 +1008,7 @@ static GLboolean args_match( struct state_key *key, GLuint unit )
}
break;
case OPR_ONE_MINUS_SRC_ALPHA:
- switch(key->unit[unit].OptRGB[i].Operand) {
+ switch (key->unit[unit].OptRGB[i].Operand) {
case OPR_ONE_MINUS_SRC_COLOR:
case OPR_ONE_MINUS_SRC_ALPHA:
break;
@@ -772,10 +1033,12 @@ static struct ureg emit_combine( struct texenv_fragment_program *p,
GLuint mode,
const struct mode_opt *opt)
{
- struct ureg src[3];
+ struct ureg src[MAX_COMBINER_TERMS];
struct ureg tmp, half;
GLuint i;
+ assert(nr <= MAX_COMBINER_TERMS);
+
tmp = undef; /* silence warning (bug 5318) */
for (i = 0; i < nr; i++)
@@ -851,7 +1114,30 @@ static struct ureg emit_combine( struct texenv_fragment_program *p,
/* Arg0 * Arg2 - Arg1 */
emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
return dest;
+ case MODE_ADD_PRODUCTS:
+ /* Arg0 * Arg1 + Arg2 * Arg3 */
+ {
+ struct ureg tmp0 = get_temp(p);
+ emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
+ emit_arith( p, OPCODE_MAD, dest, mask, saturate, src[2], src[3], tmp0 );
+ }
+ return dest;
+ case MODE_ADD_PRODUCTS_SIGNED:
+ /* Arg0 * Arg1 + Arg2 * Arg3 - 0.5 */
+ {
+ struct ureg tmp0 = get_temp(p);
+ half = get_half(p);
+ emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
+ emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[2], src[3], tmp0 );
+ emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
+ }
+ return dest;
+ case MODE_BUMP_ENVMAP_ATI:
+ /* special - not handled here */
+ assert(0);
+ return src[0];
default:
+ assert(0);
return src[0];
}
}
@@ -863,15 +1149,18 @@ static struct ureg emit_combine( struct texenv_fragment_program *p,
static struct ureg
emit_texenv(struct texenv_fragment_program *p, GLuint unit)
{
- struct state_key *key = p->state;
- GLboolean saturate = (unit < p->last_tex_stage);
+ const struct state_key *key = p->state;
+ GLboolean rgb_saturate, alpha_saturate;
GLuint rgb_shift, alpha_shift;
- struct ureg out, shift;
- struct ureg dest;
+ struct ureg out, dest;
if (!key->unit[unit].enabled) {
return get_source(p, SRC_PREVIOUS, 0);
}
+ if (key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
+ /* this isn't really a env stage delivering a color and handled elsewhere */
+ return get_source(p, SRC_PREVIOUS, 0);
+ }
switch (key->unit[unit].ModeRGB) {
case MODE_DOT3_RGB_EXT:
@@ -888,6 +1177,23 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
break;
}
+ /* If we'll do rgb/alpha shifting don't saturate in emit_combine().
+ * We don't want to clamp twice.
+ */
+ if (rgb_shift)
+ rgb_saturate = GL_FALSE; /* saturate after rgb shift */
+ else if (need_saturate(key->unit[unit].ModeRGB))
+ rgb_saturate = GL_TRUE;
+ else
+ rgb_saturate = GL_FALSE;
+
+ if (alpha_shift)
+ alpha_saturate = GL_FALSE; /* saturate after alpha shift */
+ else if (need_saturate(key->unit[unit].ModeA))
+ alpha_saturate = GL_TRUE;
+ else
+ alpha_saturate = GL_FALSE;
+
/* If this is the very last calculation, emit direct to output reg:
*/
if (key->separate_specular ||
@@ -896,13 +1202,13 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
rgb_shift)
dest = get_temp( p );
else
- dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
+ dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
/* Emit the RGB and A combine ops
*/
if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
args_match(key, unit)) {
- out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
+ out = emit_combine( p, dest, WRITEMASK_XYZW, rgb_saturate,
unit,
key->unit[unit].NumArgsRGB,
key->unit[unit].ModeRGB,
@@ -910,8 +1216,7 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
}
else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
key->unit[unit].ModeRGB == MODE_DOT3_RGBA) {
-
- out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
+ out = emit_combine( p, dest, WRITEMASK_XYZW, rgb_saturate,
unit,
key->unit[unit].NumArgsRGB,
key->unit[unit].ModeRGB,
@@ -921,12 +1226,12 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
/* Need to do something to stop from re-emitting identical
* argument calculations here:
*/
- out = emit_combine( p, dest, WRITEMASK_XYZ, saturate,
+ out = emit_combine( p, dest, WRITEMASK_XYZ, rgb_saturate,
unit,
key->unit[unit].NumArgsRGB,
key->unit[unit].ModeRGB,
key->unit[unit].OptRGB);
- out = emit_combine( p, dest, WRITEMASK_W, saturate,
+ out = emit_combine( p, dest, WRITEMASK_W, alpha_saturate,
unit,
key->unit[unit].NumArgsA,
key->unit[unit].ModeA,
@@ -936,6 +1241,9 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
/* Deal with the final shift:
*/
if (alpha_shift || rgb_shift) {
+ struct ureg shift;
+ GLboolean saturate = GL_TRUE; /* always saturate at this point */
+
if (rgb_shift == alpha_shift) {
shift = register_scalar_const(p, (GLfloat)(1<<rgb_shift));
}
@@ -960,21 +1268,32 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
static void load_texture( struct texenv_fragment_program *p, GLuint unit )
{
if (is_undef(p->src_texture[unit])) {
- GLuint dim = p->state->unit[unit].source_index;
- struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
+ const GLuint texTarget = p->state->unit[unit].source_index;
+ struct ureg texcoord;
struct ureg tmp = get_tex_temp( p );
- if (dim == TEXTURE_UNKNOWN_INDEX)
- program_error(p, "TexSrcBit");
-
+ if (is_undef(p->texcoord_tex[unit])) {
+ texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
+ }
+ else {
+ /* might want to reuse this reg for tex output actually */
+ texcoord = p->texcoord_tex[unit];
+ }
+
/* TODO: Use D0_MASK_XY where possible.
*/
if (p->state->unit[unit].enabled) {
+ GLboolean shadow = GL_FALSE;
+
+ if (p->state->unit[unit].shadow) {
+ p->program->Base.ShadowSamplers |= 1 << unit;
+ shadow = GL_TRUE;
+ }
+
p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
tmp, WRITEMASK_XYZW,
- unit, dim, texcoord );
- if (p->state->unit[unit].shadow)
- p->program->Base.ShadowSamplers |= 1 << unit;
+ unit, texTarget, shadow,
+ texcoord );
p->program->Base.SamplersUsed |= (1 << unit);
/* This identity mapping should already be in place
@@ -1007,6 +1326,7 @@ static GLboolean load_texenv_source( struct texenv_fragment_program *p,
break;
default:
+ /* not a texture src - do nothing */
break;
}
@@ -1018,13 +1338,13 @@ static GLboolean load_texenv_source( struct texenv_fragment_program *p,
* Generate instructions for loading all texture source terms.
*/
static GLboolean
-load_texunit_sources( struct texenv_fragment_program *p, int unit )
+load_texunit_sources( struct texenv_fragment_program *p, GLuint unit )
{
- struct state_key *key = p->state;
+ const struct state_key *key = p->state;
GLuint i;
for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
- load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit);
+ load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit );
}
for (i = 0; i < key->unit[unit].NumArgsA; i++) {
@@ -1034,6 +1354,43 @@ load_texunit_sources( struct texenv_fragment_program *p, int unit )
return GL_TRUE;
}
+/**
+ * Generate instructions for loading bump map textures.
+ */
+static GLboolean
+load_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit )
+{
+ const struct state_key *key = p->state;
+ GLuint bumpedUnitNr = key->unit[unit].OptRGB[1].Source - SRC_TEXTURE0;
+ struct ureg texcDst, bumpMapRes;
+ struct ureg constdudvcolor = register_const4f(p, 0.0, 0.0, 0.0, 1.0);
+ struct ureg texcSrc = register_input(p, FRAG_ATTRIB_TEX0 + bumpedUnitNr);
+ struct ureg rotMat0 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_0, unit );
+ struct ureg rotMat1 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_1, unit );
+
+ load_texenv_source( p, unit + SRC_TEXTURE0, unit );
+
+ bumpMapRes = get_source(p, key->unit[unit].OptRGB[0].Source, unit);
+ texcDst = get_tex_temp( p );
+ p->texcoord_tex[bumpedUnitNr] = texcDst;
+
+ /* Apply rot matrix and add coords to be available in next phase.
+ * dest = (Arg0.xxxx * rotMat0 + Arg1) + (Arg0.yyyy * rotMat1)
+ * note only 2 coords are affected the rest are left unchanged (mul by 0)
+ */
+ emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
+ swizzle1(bumpMapRes, SWIZZLE_X), rotMat0, texcSrc );
+ emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
+ swizzle1(bumpMapRes, SWIZZLE_Y), rotMat1, texcDst );
+
+ /* Move 0,0,0,1 into bumpmap src if someone (crossbar) is foolish
+ * enough to access this later, should optimize away.
+ */
+ emit_arith( p, OPCODE_MOV, bumpMapRes, WRITEMASK_XYZW, 0,
+ constdudvcolor, undef, undef );
+
+ return GL_TRUE;
+}
/**
* Generate a new fragment program which implements the context's
@@ -1049,7 +1406,6 @@ create_new_program(GLcontext *ctx, struct state_key *key,
struct ureg cf, out;
_mesa_memset(&p, 0, sizeof(p));
- p.ctx = ctx;
p.state = key;
p.program = program;
@@ -1058,21 +1414,23 @@ create_new_program(GLcontext *ctx, struct state_key *key,
*/
p.program->Base.Instructions = instBuffer;
p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
- p.program->Base.NumTexIndirections = 1; /* correct? */
+ p.program->Base.String = NULL;
+ p.program->Base.NumTexIndirections = 1; /* is this right? */
p.program->Base.NumTexInstructions = 0;
p.program->Base.NumAluInstructions = 0;
- p.program->Base.String = NULL;
- p.program->Base.NumInstructions =
- p.program->Base.NumTemporaries =
- p.program->Base.NumParameters =
- p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
+ p.program->Base.NumInstructions = 0;
+ p.program->Base.NumTemporaries = 0;
+ p.program->Base.NumParameters = 0;
+ p.program->Base.NumAttributes = 0;
+ p.program->Base.NumAddressRegs = 0;
p.program->Base.Parameters = _mesa_new_parameter_list();
+ p.program->Base.InputsRead = 0x0;
+ p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLOR;
- p.program->Base.InputsRead = 0;
- p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLR;
-
- for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
+ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
p.src_texture[unit] = undef;
+ p.texcoord_tex[unit] = undef;
+ }
p.src_previous = undef;
p.half = undef;
@@ -1083,11 +1441,23 @@ create_new_program(GLcontext *ctx, struct state_key *key,
release_temps(ctx, &p);
if (key->enabled_units) {
+ GLboolean needbumpstage = GL_FALSE;
+
+ /* Zeroth pass - bump map textures first */
+ for (unit = 0; unit < key->nr_enabled_units; unit++)
+ if (key->unit[unit].enabled &&
+ key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
+ needbumpstage = GL_TRUE;
+ load_texunit_bumpmap( &p, unit );
+ }
+ if (needbumpstage)
+ p.program->Base.NumTexIndirections++;
+
/* First pass - to support texture_env_crossbar, first identify
* all referenced texture sources and emit texld instructions
* for each:
*/
- for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
+ for (unit = 0; unit < key->nr_enabled_units; unit++)
if (key->unit[unit].enabled) {
load_texunit_sources( &p, unit );
p.last_tex_stage = unit;
@@ -1095,15 +1465,16 @@ create_new_program(GLcontext *ctx, struct state_key *key,
/* Second pass - emit combine instructions to build final color:
*/
- for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
- if (key->enabled_units & (1<<unit)) {
+ for (unit = 0; unit < key->nr_enabled_units; unit++)
+ if (key->unit[unit].enabled) {
p.src_previous = emit_texenv( &p, unit );
+ reserve_temp(&p, p.src_previous); /* don't re-use this temp reg */
release_temps(ctx, &p); /* release all temps */
}
}
cf = get_source( &p, SRC_PREVIOUS, 0 );
- out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLR );
+ out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLOR );
if (key->separate_specular) {
/* Emit specular add.
@@ -1128,9 +1499,11 @@ create_new_program(GLcontext *ctx, struct state_key *key,
* a reduced value and not what is expected in FogOption
*/
p.program->FogOption = ctx->Fog.Mode;
- p.program->Base.InputsRead |= FRAG_BIT_FOGC; /* XXX new */
- } else
+ p.program->Base.InputsRead |= FRAG_BIT_FOGC;
+ }
+ else {
p.program->FogOption = GL_NONE;
+ }
if (p.program->Base.NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
program_error(&p, "Exceeded max nr indirect texture lookups");
@@ -1183,12 +1556,13 @@ _mesa_get_fixed_func_fragment_program(GLcontext *ctx)
{
struct gl_fragment_program *prog;
struct state_key key;
+ GLuint keySize;
- make_state_key(ctx, &key);
+ keySize = make_state_key(ctx, &key);
prog = (struct gl_fragment_program *)
_mesa_search_program_cache(ctx->FragmentProgram.Cache,
- &key, sizeof(key));
+ &key, keySize);
if (!prog) {
prog = (struct gl_fragment_program *)
@@ -1197,44 +1571,8 @@ _mesa_get_fixed_func_fragment_program(GLcontext *ctx)
create_new_program(ctx, &key, prog);
_mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
- &key, sizeof(key), &prog->Base);
+ &key, keySize, &prog->Base);
}
return prog;
}
-
-
-
-/**
- * If _MaintainTexEnvProgram is set we'll generate a fragment program that
- * implements the current texture env/combine mode.
- * This function generates that program and puts it into effect.
- */
-void
-_mesa_UpdateTexEnvProgram( GLcontext *ctx )
-{
- const struct gl_fragment_program *prev = ctx->FragmentProgram._Current;
-
- ASSERT(ctx->FragmentProgram._MaintainTexEnvProgram);
-
- /* If a conventional fragment program/shader isn't in effect... */
- if (!ctx->FragmentProgram._Enabled &&
- (!ctx->Shader.CurrentProgram ||
- !ctx->Shader.CurrentProgram->FragmentProgram) )
- {
- struct gl_fragment_program *newProg;
-
- newProg = _mesa_get_fixed_func_fragment_program(ctx);
-
- _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, newProg);
- _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, newProg);
- }
-
- /* Tell the driver about the change. Could define a new target for
- * this?
- */
- if (ctx->FragmentProgram._Current != prev && ctx->Driver.BindProgram) {
- ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
- (struct gl_program *) ctx->FragmentProgram._Current);
- }
-}
diff --git a/src/mesa/main/texenvprogram.h b/src/mesa/main/texenvprogram.h
index a7aa60cf37..0a162d2e7a 100644
--- a/src/mesa/main/texenvprogram.h
+++ b/src/mesa/main/texenvprogram.h
@@ -32,6 +32,4 @@
extern struct gl_fragment_program *
_mesa_get_fixed_func_fragment_program(GLcontext *ctx);
-extern void _mesa_UpdateTexEnvProgram( GLcontext *ctx );
-
#endif
diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c
index 08725846c6..19c92838e0 100644
--- a/src/mesa/main/texformat.c
+++ b/src/mesa/main/texformat.c
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -86,30 +87,33 @@ nonlinear_to_linear(GLubyte cs8)
*
* Have to have this so the FetchTexel function pointer is never NULL.
*/
-static void fetch_null_texel( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+void
+_mesa_texformat_fetch_texel_null(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel)
{
(void) texImage; (void) i; (void) j; (void) k;
texel[RCOMP] = 0;
texel[GCOMP] = 0;
texel[BCOMP] = 0;
texel[ACOMP] = 0;
- _mesa_warning(NULL, "fetch_null_texel() called!");
+ _mesa_warning(NULL, "_mesa_texformat_fetch_texel_null() called!");
}
-static void fetch_null_texelf( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLfloat *texel )
+void
+_mesa_texformat_fetch_texel_f_null(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel)
{
(void) texImage; (void) i; (void) j; (void) k;
texel[RCOMP] = 0.0;
texel[GCOMP] = 0.0;
texel[BCOMP] = 0.0;
texel[ACOMP] = 0.0;
- _mesa_warning(NULL, "fetch_null_texelf() called!");
+ _mesa_warning(NULL, "_mesa_texformat_fetch_texel_f_null() called!");
}
-static void store_null_texel(struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, const void *texel)
+void
+_mesa_texformat_store_texel_null(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
{
(void) texImage;
(void) i;
@@ -153,9 +157,9 @@ const struct gl_texture_format _mesa_texformat_rgba = {
0, /* StencilBits */
4 * sizeof(GLchan), /* TexelBytes */
_mesa_texstore_rgba, /* StoreTexImageFunc */
- fetch_texel_1d_rgba, /* FetchTexel1D */
- fetch_texel_2d_rgba, /* FetchTexel2D */
- fetch_texel_3d_rgba, /* FetchTexel3D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
fetch_texel_1d_f_rgba, /* FetchTexel1Df */
fetch_texel_2d_f_rgba, /* FetchTexel2Df */
fetch_texel_3d_f_rgba, /* FetchTexel3Df */
@@ -177,9 +181,9 @@ const struct gl_texture_format _mesa_texformat_rgb = {
0, /* StencilBits */
3 * sizeof(GLchan), /* TexelBytes */
_mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
- fetch_texel_1d_rgb, /* FetchTexel1D */
- fetch_texel_2d_rgb, /* FetchTexel2D */
- fetch_texel_3d_rgb, /* FetchTexel3D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
fetch_texel_1d_f_rgb, /* FetchTexel1Df */
fetch_texel_2d_f_rgb, /* FetchTexel2Df */
fetch_texel_3d_f_rgb, /* FetchTexel3Df */
@@ -201,12 +205,12 @@ const struct gl_texture_format _mesa_texformat_alpha = {
0, /* StencilBits */
sizeof(GLchan), /* TexelBytes */
_mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
- fetch_texel_1d_alpha, /* FetchTexel1D */
- fetch_texel_2d_alpha, /* FetchTexel2D */
- fetch_texel_3d_alpha, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_alpha, /* FetchTexel1Df */
+ fetch_texel_2d_f_alpha, /* FetchTexel2Df */
+ fetch_texel_3d_f_alpha, /* FetchTexel3Df */
store_texel_alpha /* StoreTexel */
};
@@ -225,12 +229,12 @@ const struct gl_texture_format _mesa_texformat_luminance = {
0, /* StencilBits */
sizeof(GLchan), /* TexelBytes */
_mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
- fetch_texel_1d_luminance, /* FetchTexel1D */
- fetch_texel_2d_luminance, /* FetchTexel2D */
- fetch_texel_3d_luminance, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_luminance, /* FetchTexel1Df */
+ fetch_texel_2d_f_luminance, /* FetchTexel2Df */
+ fetch_texel_3d_f_luminance, /* FetchTexel3Df */
store_texel_luminance /* StoreTexel */
};
@@ -249,12 +253,12 @@ const struct gl_texture_format _mesa_texformat_luminance_alpha = {
0, /* StencilBits */
2 * sizeof(GLchan), /* TexelBytes */
_mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
- fetch_texel_1d_luminance_alpha, /* FetchTexel1D */
- fetch_texel_2d_luminance_alpha, /* FetchTexel2D */
- fetch_texel_3d_luminance_alpha, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_luminance_alpha, /* FetchTexel1Df */
+ fetch_texel_2d_f_luminance_alpha, /* FetchTexel2Df */
+ fetch_texel_3d_f_luminance_alpha, /* FetchTexel3Df */
store_texel_luminance_alpha /* StoreTexel */
};
@@ -273,12 +277,12 @@ const struct gl_texture_format _mesa_texformat_intensity = {
0, /* StencilBits */
sizeof(GLchan), /* TexelBytes */
_mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
- fetch_texel_1d_intensity, /* FetchTexel1D */
- fetch_texel_2d_intensity, /* FetchTexel2D */
- fetch_texel_3d_intensity, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_intensity, /* FetchTexel1Df */
+ fetch_texel_2d_f_intensity, /* FetchTexel2Df */
+ fetch_texel_3d_f_intensity, /* FetchTexel3Df */
store_texel_intensity /* StoreTexel */
};
@@ -333,6 +337,30 @@ const struct gl_texture_format _mesa_texformat_srgba8 = {
store_texel_srgba8 /* StoreTexel */
};
+const struct gl_texture_format _mesa_texformat_sargb8 = {
+ MESA_FORMAT_SARGB8, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_sargb8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_sargb8, /* FetchTexel1Df */
+ fetch_texel_2d_sargb8, /* FetchTexel2Df */
+ fetch_texel_3d_sargb8, /* FetchTexel3Df */
+ store_texel_sargb8 /* StoreTexel */
+};
+
const struct gl_texture_format _mesa_texformat_sl8 = {
MESA_FORMAT_SL8, /* MesaFormat */
GL_LUMINANCE, /* BaseFormat */
@@ -357,6 +385,7 @@ const struct gl_texture_format _mesa_texformat_sl8 = {
store_texel_sl8 /* StoreTexel */
};
+/* Note: this format name looks like a misnomer, make it sal8? */
const struct gl_texture_format _mesa_texformat_sla8 = {
MESA_FORMAT_SLA8, /* MesaFormat */
GL_LUMINANCE_ALPHA, /* BaseFormat */
@@ -671,6 +700,79 @@ const struct gl_texture_format _mesa_texformat_intensity_float16 = {
store_texel_intensity_f16 /* StoreTexel */
};
+const struct gl_texture_format _mesa_texformat_dudv8 = {
+ MESA_FORMAT_DUDV8, /* MesaFormat */
+ GL_DUDV_ATI, /* BaseFormat */
+ GL_SIGNED_NORMALIZED, /* DataType */
+ /* maybe should add dudvBits field, but spec seems to be
+ lacking the ability to query with GetTexLevelParameter anyway */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_dudv8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_dudv8, /* FetchTexel1Df */
+ fetch_texel_2d_dudv8, /* FetchTexel2Df */
+ fetch_texel_3d_dudv8, /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_signed_rgba8888 = {
+ MESA_FORMAT_SIGNED_RGBA8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_SIGNED_NORMALIZED, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_signed_rgba8888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_signed_rgba8888, /* FetchTexel1Df */
+ fetch_texel_2d_signed_rgba8888, /* FetchTexel2Df */
+ fetch_texel_3d_signed_rgba8888, /* FetchTexel3Df */
+ store_texel_signed_rgba8888 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_signed_rgba8888_rev = {
+ MESA_FORMAT_SIGNED_RGBA8888_REV, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_SIGNED_NORMALIZED, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_signed_rgba8888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_signed_rgba8888_rev, /* FetchTexel1Df */
+ fetch_texel_2d_signed_rgba8888_rev, /* FetchTexel2Df */
+ fetch_texel_3d_signed_rgba8888_rev, /* FetchTexel3Df */
+ store_texel_signed_rgba8888_rev /* StoreTexel */
+};
/*@}*/
@@ -694,12 +796,12 @@ const struct gl_texture_format _mesa_texformat_rgba8888 = {
0, /* StencilBits */
4, /* TexelBytes */
_mesa_texstore_rgba8888, /* StoreTexImageFunc */
- fetch_texel_1d_rgba8888, /* FetchTexel1D */
- fetch_texel_2d_rgba8888, /* FetchTexel2D */
- fetch_texel_3d_rgba8888, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgba8888, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba8888, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba8888, /* FetchTexel3Df */
store_texel_rgba8888 /* StoreTexel */
};
@@ -718,12 +820,12 @@ const struct gl_texture_format _mesa_texformat_rgba8888_rev = {
0, /* StencilBits */
4, /* TexelBytes */
_mesa_texstore_rgba8888, /* StoreTexImageFunc */
- fetch_texel_1d_rgba8888_rev, /* FetchTexel1D */
- fetch_texel_2d_rgba8888_rev, /* FetchTexel2D */
- fetch_texel_3d_rgba8888_rev, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgba8888_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba8888_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba8888_rev, /* FetchTexel3Df */
store_texel_rgba8888_rev /* StoreTexel */
};
@@ -742,12 +844,12 @@ const struct gl_texture_format _mesa_texformat_argb8888 = {
0, /* StencilBits */
4, /* TexelBytes */
_mesa_texstore_argb8888, /* StoreTexImageFunc */
- fetch_texel_1d_argb8888, /* FetchTexel1D */
- fetch_texel_2d_argb8888, /* FetchTexel2D */
- fetch_texel_3d_argb8888, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb8888, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb8888, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb8888, /* FetchTexel3Df */
store_texel_argb8888 /* StoreTexel */
};
@@ -766,12 +868,12 @@ const struct gl_texture_format _mesa_texformat_argb8888_rev = {
0, /* StencilBits */
4, /* TexelBytes */
_mesa_texstore_argb8888, /* StoreTexImageFunc */
- fetch_texel_1d_argb8888_rev, /* FetchTexel1D */
- fetch_texel_2d_argb8888_rev, /* FetchTexel2D */
- fetch_texel_3d_argb8888_rev, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb8888_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb8888_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb8888_rev, /* FetchTexel3Df */
store_texel_argb8888_rev /* StoreTexel */
};
@@ -790,12 +892,12 @@ const struct gl_texture_format _mesa_texformat_rgb888 = {
0, /* StencilBits */
3, /* TexelBytes */
_mesa_texstore_rgb888, /* StoreTexImageFunc */
- fetch_texel_1d_rgb888, /* FetchTexel1D */
- fetch_texel_2d_rgb888, /* FetchTexel2D */
- fetch_texel_3d_rgb888, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgb888, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb888, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb888, /* FetchTexel3Df */
store_texel_rgb888 /* StoreTexel */
};
@@ -814,12 +916,12 @@ const struct gl_texture_format _mesa_texformat_bgr888 = {
0, /* StencilBits */
3, /* TexelBytes */
_mesa_texstore_bgr888, /* StoreTexImageFunc */
- fetch_texel_1d_bgr888, /* FetchTexel1D */
- fetch_texel_2d_bgr888, /* FetchTexel2D */
- fetch_texel_3d_bgr888, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_bgr888, /* FetchTexel1Df */
+ fetch_texel_2d_f_bgr888, /* FetchTexel2Df */
+ fetch_texel_3d_f_bgr888, /* FetchTexel3Df */
store_texel_bgr888 /* StoreTexel */
};
@@ -838,12 +940,12 @@ const struct gl_texture_format _mesa_texformat_rgb565 = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_rgb565, /* StoreTexImageFunc */
- fetch_texel_1d_rgb565, /* FetchTexel1D */
- fetch_texel_2d_rgb565, /* FetchTexel2D */
- fetch_texel_3d_rgb565, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgb565, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb565, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb565, /* FetchTexel3Df */
store_texel_rgb565 /* StoreTexel */
};
@@ -862,12 +964,12 @@ const struct gl_texture_format _mesa_texformat_rgb565_rev = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_rgb565, /* StoreTexImageFunc */
- fetch_texel_1d_rgb565_rev, /* FetchTexel1D */
- fetch_texel_2d_rgb565_rev, /* FetchTexel2D */
- fetch_texel_3d_rgb565_rev, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgb565_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb565_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb565_rev, /* FetchTexel3Df */
store_texel_rgb565_rev /* StoreTexel */
};
@@ -886,12 +988,12 @@ const struct gl_texture_format _mesa_texformat_rgba4444 = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_rgba4444, /* StoreTexImageFunc */
- fetch_texel_1d_rgba4444, /* FetchTexel1D */
- fetch_texel_2d_rgba4444, /* FetchTexel2D */
- fetch_texel_3d_rgba4444, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgba4444, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba4444, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba4444, /* FetchTexel3Df */
store_texel_rgba4444 /* StoreTexel */
};
@@ -910,12 +1012,12 @@ const struct gl_texture_format _mesa_texformat_argb4444 = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_argb4444, /* StoreTexImageFunc */
- fetch_texel_1d_argb4444, /* FetchTexel1D */
- fetch_texel_2d_argb4444, /* FetchTexel2D */
- fetch_texel_3d_argb4444, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb4444, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb4444, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb4444, /* FetchTexel3Df */
store_texel_argb4444 /* StoreTexel */
};
@@ -934,12 +1036,12 @@ const struct gl_texture_format _mesa_texformat_argb4444_rev = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_argb4444, /* StoreTexImageFunc */
- fetch_texel_1d_argb4444_rev, /* FetchTexel1D */
- fetch_texel_2d_argb4444_rev, /* FetchTexel2D */
- fetch_texel_3d_argb4444_rev, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb4444_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb4444_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb4444_rev, /* FetchTexel3Df */
store_texel_argb4444_rev /* StoreTexel */
};
@@ -958,12 +1060,12 @@ const struct gl_texture_format _mesa_texformat_rgba5551 = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_rgba5551, /* StoreTexImageFunc */
- fetch_texel_1d_rgba5551, /* FetchTexel1D */
- fetch_texel_2d_rgba5551, /* FetchTexel2D */
- fetch_texel_3d_rgba5551, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgba5551, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba5551, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba5551, /* FetchTexel3Df */
store_texel_rgba5551 /* StoreTexel */
};
@@ -982,12 +1084,12 @@ const struct gl_texture_format _mesa_texformat_argb1555 = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_argb1555, /* StoreTexImageFunc */
- fetch_texel_1d_argb1555, /* FetchTexel1D */
- fetch_texel_2d_argb1555, /* FetchTexel2D */
- fetch_texel_3d_argb1555, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb1555, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb1555, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb1555, /* FetchTexel3Df */
store_texel_argb1555 /* StoreTexel */
};
@@ -1006,12 +1108,12 @@ const struct gl_texture_format _mesa_texformat_argb1555_rev = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_argb1555, /* StoreTexImageFunc */
- fetch_texel_1d_argb1555_rev, /* FetchTexel1D */
- fetch_texel_2d_argb1555_rev, /* FetchTexel2D */
- fetch_texel_3d_argb1555_rev, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb1555_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb1555_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb1555_rev, /* FetchTexel3Df */
store_texel_argb1555_rev /* StoreTexel */
};
@@ -1030,12 +1132,12 @@ const struct gl_texture_format _mesa_texformat_al88 = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_al88, /* StoreTexImageFunc */
- fetch_texel_1d_al88, /* FetchTexel1D */
- fetch_texel_2d_al88, /* FetchTexel2D */
- fetch_texel_3d_al88, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_al88, /* FetchTexel1Df */
+ fetch_texel_2d_f_al88, /* FetchTexel2Df */
+ fetch_texel_3d_f_al88, /* FetchTexel3Df */
store_texel_al88 /* StoreTexel */
};
@@ -1054,12 +1156,12 @@ const struct gl_texture_format _mesa_texformat_al88_rev = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_al88, /* StoreTexImageFunc */
- fetch_texel_1d_al88_rev, /* FetchTexel1D */
- fetch_texel_2d_al88_rev, /* FetchTexel2D */
- fetch_texel_3d_al88_rev, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_al88_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_al88_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_al88_rev, /* FetchTexel3Df */
store_texel_al88_rev /* StoreTexel */
};
@@ -1078,12 +1180,12 @@ const struct gl_texture_format _mesa_texformat_rgb332 = {
0, /* StencilBits */
1, /* TexelBytes */
_mesa_texstore_rgb332, /* StoreTexImageFunc */
- fetch_texel_1d_rgb332, /* FetchTexel1D */
- fetch_texel_2d_rgb332, /* FetchTexel2D */
- fetch_texel_3d_rgb332, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgb332, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb332, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb332, /* FetchTexel3Df */
store_texel_rgb332 /* StoreTexel */
};
@@ -1102,12 +1204,12 @@ const struct gl_texture_format _mesa_texformat_a8 = {
0, /* StencilBits */
1, /* TexelBytes */
_mesa_texstore_a8, /* StoreTexImageFunc */
- fetch_texel_1d_a8, /* FetchTexel1D */
- fetch_texel_2d_a8, /* FetchTexel2D */
- fetch_texel_3d_a8, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_a8, /* FetchTexel1Df */
+ fetch_texel_2d_f_a8, /* FetchTexel2Df */
+ fetch_texel_3d_f_a8, /* FetchTexel3Df */
store_texel_a8 /* StoreTexel */
};
@@ -1126,12 +1228,12 @@ const struct gl_texture_format _mesa_texformat_l8 = {
0, /* StencilBits */
1, /* TexelBytes */
_mesa_texstore_a8,/*yes*/ /* StoreTexImageFunc */
- fetch_texel_1d_l8, /* FetchTexel1D */
- fetch_texel_2d_l8, /* FetchTexel2D */
- fetch_texel_3d_l8, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_l8, /* FetchTexel1Df */
+ fetch_texel_2d_f_l8, /* FetchTexel2Df */
+ fetch_texel_3d_f_l8, /* FetchTexel3Df */
store_texel_l8 /* StoreTexel */
};
@@ -1150,12 +1252,12 @@ const struct gl_texture_format _mesa_texformat_i8 = {
0, /* StencilBits */
1, /* TexelBytes */
_mesa_texstore_a8,/*yes*/ /* StoreTexImageFunc */
- fetch_texel_1d_i8, /* FetchTexel1D */
- fetch_texel_2d_i8, /* FetchTexel2D */
- fetch_texel_3d_i8, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_i8, /* FetchTexel1Df */
+ fetch_texel_2d_f_i8, /* FetchTexel2Df */
+ fetch_texel_3d_f_i8, /* FetchTexel3Df */
store_texel_i8 /* StoreTexel */
};
@@ -1174,12 +1276,12 @@ const struct gl_texture_format _mesa_texformat_ci8 = {
0, /* StencilBits */
1, /* TexelBytes */
_mesa_texstore_ci8, /* StoreTexImageFunc */
- fetch_texel_1d_ci8, /* FetchTexel1D */
- fetch_texel_2d_ci8, /* FetchTexel2D */
- fetch_texel_3d_ci8, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_ci8, /* FetchTexel1Df */
+ fetch_texel_2d_f_ci8, /* FetchTexel2Df */
+ fetch_texel_3d_f_ci8, /* FetchTexel3Df */
store_texel_ci8 /* StoreTexel */
};
@@ -1198,12 +1300,12 @@ const struct gl_texture_format _mesa_texformat_ycbcr = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_ycbcr, /* StoreTexImageFunc */
- fetch_texel_1d_ycbcr, /* FetchTexel1D */
- fetch_texel_2d_ycbcr, /* FetchTexel2D */
- fetch_texel_3d_ycbcr, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_ycbcr, /* FetchTexel1Df */
+ fetch_texel_2d_f_ycbcr, /* FetchTexel2Df */
+ fetch_texel_3d_f_ycbcr, /* FetchTexel3Df */
store_texel_ycbcr /* StoreTexel */
};
@@ -1222,12 +1324,12 @@ const struct gl_texture_format _mesa_texformat_ycbcr_rev = {
0, /* StencilBits */
2, /* TexelBytes */
_mesa_texstore_ycbcr, /* StoreTexImageFunc */
- fetch_texel_1d_ycbcr_rev, /* FetchTexel1D */
- fetch_texel_2d_ycbcr_rev, /* FetchTexel2D */
- fetch_texel_3d_ycbcr_rev, /* FetchTexel3D */
- NULL, /* FetchTexel1Df */
- NULL, /* FetchTexel2Df */
- NULL, /* FetchTexel3Df */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_ycbcr_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_ycbcr_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_ycbcr_rev, /* FetchTexel3Df */
store_texel_ycbcr_rev /* StoreTexel */
};
@@ -1349,13 +1451,7 @@ const struct gl_texture_format _mesa_null_texformat = {
0, /* StencilBits */
0, /* TexelBytes */
NULL, /* StoreTexImageFunc */
- fetch_null_texel, /* FetchTexel1D */
- fetch_null_texel, /* FetchTexel2D */
- fetch_null_texel, /* FetchTexel3D */
- fetch_null_texelf, /* FetchTexel1Df */
- fetch_null_texelf, /* FetchTexel2Df */
- fetch_null_texelf, /* FetchTexel3Df */
- store_null_texel /* StoreTexel */
+ _MESA_TEXFORMAT_NULL_OPS
};
/*@}*/
@@ -1481,41 +1577,39 @@ _mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
}
}
- if (ctx->Extensions.ARB_texture_compression) {
- switch (internalFormat) {
- case GL_COMPRESSED_ALPHA_ARB:
- return &_mesa_texformat_alpha;
- case GL_COMPRESSED_LUMINANCE_ARB:
- return &_mesa_texformat_luminance;
- case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
- return &_mesa_texformat_luminance_alpha;
- case GL_COMPRESSED_INTENSITY_ARB:
- return &_mesa_texformat_intensity;
- case GL_COMPRESSED_RGB_ARB:
+ switch (internalFormat) {
+ case GL_COMPRESSED_ALPHA_ARB:
+ return &_mesa_texformat_alpha;
+ case GL_COMPRESSED_LUMINANCE_ARB:
+ return &_mesa_texformat_luminance;
+ case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
+ return &_mesa_texformat_luminance_alpha;
+ case GL_COMPRESSED_INTENSITY_ARB:
+ return &_mesa_texformat_intensity;
+ case GL_COMPRESSED_RGB_ARB:
#if FEATURE_texture_fxt1
- if (ctx->Extensions.TDFX_texture_compression_FXT1)
- return &_mesa_texformat_rgb_fxt1;
+ if (ctx->Extensions.TDFX_texture_compression_FXT1)
+ return &_mesa_texformat_rgb_fxt1;
#endif
#if FEATURE_texture_s3tc
- if (ctx->Extensions.EXT_texture_compression_s3tc ||
- ctx->Extensions.S3_s3tc)
- return &_mesa_texformat_rgb_dxt1;
+ if (ctx->Extensions.EXT_texture_compression_s3tc ||
+ ctx->Extensions.S3_s3tc)
+ return &_mesa_texformat_rgb_dxt1;
#endif
- return &_mesa_texformat_rgb;
- case GL_COMPRESSED_RGBA_ARB:
+ return &_mesa_texformat_rgb;
+ case GL_COMPRESSED_RGBA_ARB:
#if FEATURE_texture_fxt1
- if (ctx->Extensions.TDFX_texture_compression_FXT1)
- return &_mesa_texformat_rgba_fxt1;
+ if (ctx->Extensions.TDFX_texture_compression_FXT1)
+ return &_mesa_texformat_rgba_fxt1;
#endif
#if FEATURE_texture_s3tc
- if (ctx->Extensions.EXT_texture_compression_s3tc ||
- ctx->Extensions.S3_s3tc)
- return &_mesa_texformat_rgba_dxt3; /* Not rgba_dxt1, see spec */
+ if (ctx->Extensions.EXT_texture_compression_s3tc ||
+ ctx->Extensions.S3_s3tc)
+ return &_mesa_texformat_rgba_dxt3; /* Not rgba_dxt1, see spec */
#endif
- return &_mesa_texformat_rgba;
- default:
- ; /* fallthrough */
- }
+ return &_mesa_texformat_rgba;
+ default:
+ ; /* fallthrough */
}
if (ctx->Extensions.MESA_ycbcr_texture) {
@@ -1611,6 +1705,27 @@ _mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
}
}
+ if (ctx->Extensions.ATI_envmap_bumpmap) {
+ switch (internalFormat) {
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return &_mesa_texformat_dudv8;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.MESA_texture_signed_rgba) {
+ switch (internalFormat) {
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ return &_mesa_texformat_signed_rgba8888;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+
#if FEATURE_EXT_texture_sRGB
if (ctx->Extensions.EXT_texture_sRGB) {
switch (internalFormat) {
@@ -1626,21 +1741,40 @@ _mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
case GL_SLUMINANCE_ALPHA_EXT:
case GL_SLUMINANCE8_ALPHA8_EXT:
return &_mesa_texformat_sla8;
- /* NOTE: not supporting any compression of sRGB at this time */
- case GL_COMPRESSED_SRGB_EXT:
- return &_mesa_texformat_srgb8;
- case GL_COMPRESSED_SRGB_ALPHA_EXT:
- return &_mesa_texformat_srgba8;
case GL_COMPRESSED_SLUMINANCE_EXT:
return &_mesa_texformat_sl8;
case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
return &_mesa_texformat_sla8;
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_EXT:
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgb_dxt1;
+#endif
return &_mesa_texformat_srgb8;
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt3; /* Not srgba_dxt1, see spec */
+#endif
+ return &_mesa_texformat_srgba8;
+#if FEATURE_texture_s3tc
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgb_dxt1;
+ break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt1;
+ break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt3;
+ break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- return &_mesa_texformat_srgba8;
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt5;
+ break;
+#endif
default:
; /* fallthrough */
}
@@ -1721,6 +1855,11 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
*comps = 1; /* XXX OK? */
return;
+ case MESA_FORMAT_S8_Z24:
+ *datatype = GL_UNSIGNED_INT;
+ *comps = 1; /* XXX OK? */
+ return;
+
case MESA_FORMAT_Z16:
*datatype = GL_UNSIGNED_SHORT;
*comps = 1;
@@ -1731,11 +1870,24 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
*comps = 1;
return;
+ case MESA_FORMAT_DUDV8:
+ *datatype = GL_BYTE;
+ *comps = 2;
+ return;
+
+ case MESA_FORMAT_SIGNED_RGBA8888:
+ case MESA_FORMAT_SIGNED_RGBA8888_REV:
+ *datatype = GL_BYTE;
+ *comps = 4;
+ return;
+
+#if FEATURE_EXT_texture_sRGB
case MESA_FORMAT_SRGB8:
*datatype = GL_UNSIGNED_BYTE;
*comps = 3;
return;
case MESA_FORMAT_SRGBA8:
+ case MESA_FORMAT_SARGB8:
*datatype = GL_UNSIGNED_BYTE;
*comps = 4;
return;
@@ -1747,17 +1899,28 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
*datatype = GL_UNSIGNED_BYTE;
*comps = 2;
return;
+#endif
+#if FEATURE_texture_fxt1
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
+#endif
+#if FEATURE_texture_s3tc
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
/* XXX generate error instead? */
*datatype = GL_UNSIGNED_BYTE;
*comps = 0;
return;
+#endif
case MESA_FORMAT_RGBA:
*datatype = CHAN_TYPE;
diff --git a/src/mesa/main/texformat.h b/src/mesa/main/texformat.h
index b1604d4a49..a4d8bbf831 100644
--- a/src/mesa/main/texformat.h
+++ b/src/mesa/main/texformat.h
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -38,6 +39,16 @@
#include "mtypes.h"
+#define _MESA_TEXFORMAT_NULL_OPS \
+ _mesa_texformat_fetch_texel_null, /* FetchTexel1D */ \
+ _mesa_texformat_fetch_texel_null, /* FetchTexel2D */ \
+ _mesa_texformat_fetch_texel_null, /* FetchTexel3D */ \
+ _mesa_texformat_fetch_texel_f_null, /* FetchTexel1Df */ \
+ _mesa_texformat_fetch_texel_f_null, /* FetchTexel2Df */ \
+ _mesa_texformat_fetch_texel_f_null, /* FetchTexel3Df */ \
+ _mesa_texformat_store_texel_null /* StoreTexel */
+
+
/**
* Mesa internal texture image formats.
* All texture images are stored in one of these formats.
@@ -98,9 +109,13 @@ enum _format {
/*@{*/
MESA_FORMAT_SRGB8,
MESA_FORMAT_SRGBA8,
+ MESA_FORMAT_SARGB8,
MESA_FORMAT_SL8,
MESA_FORMAT_SLA8,
MESA_FORMAT_SRGB_DXT1,
+ MESA_FORMAT_SRGBA_DXT1,
+ MESA_FORMAT_SRGBA_DXT3,
+ MESA_FORMAT_SRGBA_DXT5,
/*@}*/
#endif
@@ -150,7 +165,16 @@ enum _format {
MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32,
MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16,
MESA_FORMAT_INTENSITY_FLOAT32,
- MESA_FORMAT_INTENSITY_FLOAT16
+ MESA_FORMAT_INTENSITY_FLOAT16,
+ /*@}*/
+
+ /**
+ * \name Signed fixed point texture formats.
+ */
+ /*@{*/
+ MESA_FORMAT_DUDV8,
+ MESA_FORMAT_SIGNED_RGBA8888,
+ MESA_FORMAT_SIGNED_RGBA8888_REV
/*@}*/
};
@@ -170,9 +194,13 @@ extern const struct gl_texture_format _mesa_texformat_intensity;
/*@{*/
extern const struct gl_texture_format _mesa_texformat_srgb8;
extern const struct gl_texture_format _mesa_texformat_srgba8;
+extern const struct gl_texture_format _mesa_texformat_sargb8;
extern const struct gl_texture_format _mesa_texformat_sl8;
extern const struct gl_texture_format _mesa_texformat_sla8;
extern const struct gl_texture_format _mesa_texformat_srgb_dxt1;
+extern const struct gl_texture_format _mesa_texformat_srgba_dxt1;
+extern const struct gl_texture_format _mesa_texformat_srgba_dxt3;
+extern const struct gl_texture_format _mesa_texformat_srgba_dxt5;
/*@}*/
#endif
@@ -192,6 +220,13 @@ extern const struct gl_texture_format _mesa_texformat_intensity_float32;
extern const struct gl_texture_format _mesa_texformat_intensity_float16;
/*@}*/
+/** Signed fixed point texture formats */
+/*@{*/
+extern const struct gl_texture_format _mesa_texformat_dudv8;
+extern const struct gl_texture_format _mesa_texformat_signed_rgba8888;
+extern const struct gl_texture_format _mesa_texformat_signed_rgba8888_rev;
+/*@}*/
+
/** \name Assorted hardware-friendly formats */
/*@{*/
extern const struct gl_texture_format _mesa_texformat_rgba8888;
@@ -253,4 +288,19 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
GLenum *datatype, GLuint *comps);
+extern void
+_mesa_texformat_fetch_texel_null(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel);
+
+
+extern void
+_mesa_texformat_fetch_texel_f_null(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel);
+
+
+extern void
+_mesa_texformat_store_texel_null(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel);
+
+
#endif
diff --git a/src/mesa/main/texformat_tmp.h b/src/mesa/main/texformat_tmp.h
index 5f0c674d4f..eb160deff9 100644
--- a/src/mesa/main/texformat_tmp.h
+++ b/src/mesa/main/texformat_tmp.h
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -71,14 +72,6 @@
/* MESA_FORMAT_RGBA **********************************************************/
-/* Fetch texel from 1D, 2D or 3D RGBA texture, returning 4 GLchans */
-static void FETCH(rgba)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
-{
- const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 4);
- COPY_CHAN4( texel, src );
-}
-
/* Fetch texel from 1D, 2D or 3D RGBA texture, returning 4 GLfloats */
static void FETCH(f_rgba)( const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel )
@@ -106,17 +99,6 @@ static void store_texel_rgba(struct gl_texture_image *texImage,
/* MESA_FORMAT_RGB ***********************************************************/
-/* Fetch texel from 1D, 2D or 3D RGB texture, returning 4 GLchans */
-static void FETCH(rgb)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
-{
- const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 3);
- texel[RCOMP] = src[0];
- texel[GCOMP] = src[1];
- texel[BCOMP] = src[2];
- texel[ACOMP] = CHAN_MAX;
-}
-
/* Fetch texel from 1D, 2D or 3D RGB texture, returning 4 GLfloats */
static void FETCH(f_rgb)( const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel )
@@ -143,14 +125,14 @@ static void store_texel_rgb(struct gl_texture_image *texImage,
/* MESA_FORMAT_ALPHA *********************************************************/
/* Fetch texel from 1D, 2D or 3D ALPHA texture, returning 4 GLchans */
-static void FETCH(alpha)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_alpha)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 1);
texel[RCOMP] =
texel[GCOMP] =
- texel[BCOMP] = 0;
- texel[ACOMP] = src[0];
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = CHAN_TO_FLOAT(src[0]);
}
#if DIM == 3
@@ -166,14 +148,14 @@ static void store_texel_alpha(struct gl_texture_image *texImage,
/* MESA_FORMAT_LUMINANCE *****************************************************/
/* Fetch texel from 1D, 2D or 3D LUMIN texture, returning 4 GLchans */
-static void FETCH(luminance)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_luminance)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 1);
texel[RCOMP] =
texel[GCOMP] =
- texel[BCOMP] = src[0];
- texel[ACOMP] = CHAN_MAX;
+ texel[BCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -189,14 +171,14 @@ static void store_texel_luminance(struct gl_texture_image *texImage,
/* MESA_FORMAT_LUMINANCE_ALPHA ***********************************************/
/* Fetch texel from 1D, 2D or 3D L_A texture, returning 4 GLchans */
-static void FETCH(luminance_alpha)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_luminance_alpha)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel)
{
const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 2);
- texel[RCOMP] = src[0];
- texel[GCOMP] = src[0];
- texel[BCOMP] = src[0];
- texel[ACOMP] = src[1];
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[ACOMP] = CHAN_TO_FLOAT(src[1]);
}
#if DIM == 3
@@ -213,14 +195,14 @@ static void store_texel_luminance_alpha(struct gl_texture_image *texImage,
/* MESA_FORMAT_INTENSITY *****************************************************/
/* Fetch texel from 1D, 2D or 3D INT. texture, returning 4 GLchans */
-static void FETCH(intensity)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_intensity)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 1);
- texel[RCOMP] = src[0];
- texel[GCOMP] = src[0];
- texel[BCOMP] = src[0];
- texel[ACOMP] = src[0];
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] =
+ texel[ACOMP] = CHAN_TO_FLOAT(src[0]);
}
#if DIM == 3
@@ -605,17 +587,19 @@ static void store_texel_intensity_f16(struct gl_texture_image *texImage,
/* MESA_FORMAT_RGBA8888 ******************************************************/
-/* Fetch texel from 1D, 2D or 3D rgba8888 texture, return 4 GLchans */
-static void FETCH(rgba8888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+/* Fetch texel from 1D, 2D or 3D rgba8888 texture, return 4 GLfloats */
+static void FETCH(f_rgba8888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_CHAN( (s >> 24) );
- texel[GCOMP] = UBYTE_TO_CHAN( (s >> 16) & 0xff );
- texel[BCOMP] = UBYTE_TO_CHAN( (s >> 8) & 0xff );
- texel[ACOMP] = UBYTE_TO_CHAN( (s ) & 0xff );
+ texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 24) );
+ texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
+ texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
}
+
+
#if DIM == 3
static void store_texel_rgba8888(struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, const void *texel)
@@ -630,14 +614,14 @@ static void store_texel_rgba8888(struct gl_texture_image *texImage,
/* MESA_FORMAT_RGBA888_REV ***************************************************/
/* Fetch texel from 1D, 2D or 3D abgr8888 texture, return 4 GLchans */
-static void FETCH(rgba8888_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_rgba8888_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_CHAN( (s ) & 0xff );
- texel[GCOMP] = UBYTE_TO_CHAN( (s >> 8) & 0xff );
- texel[BCOMP] = UBYTE_TO_CHAN( (s >> 16) & 0xff );
- texel[ACOMP] = UBYTE_TO_CHAN( (s >> 24) );
+ texel[RCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
+ texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
+ texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) );
}
#if DIM == 3
@@ -654,14 +638,14 @@ static void store_texel_rgba8888_rev(struct gl_texture_image *texImage,
/* MESA_FORMAT_ARGB8888 ******************************************************/
/* Fetch texel from 1D, 2D or 3D argb8888 texture, return 4 GLchans */
-static void FETCH(argb8888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_argb8888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_CHAN( (s >> 16) & 0xff );
- texel[GCOMP] = UBYTE_TO_CHAN( (s >> 8) & 0xff );
- texel[BCOMP] = UBYTE_TO_CHAN( (s ) & 0xff );
- texel[ACOMP] = UBYTE_TO_CHAN( (s >> 24) );
+ texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
+ texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
+ texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) );
}
#if DIM == 3
@@ -677,15 +661,15 @@ static void store_texel_argb8888(struct gl_texture_image *texImage,
/* MESA_FORMAT_ARGB8888_REV **************************************************/
-/* Fetch texel from 1D, 2D or 3D argb8888_rev texture, return 4 GLchans */
-static void FETCH(argb8888_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+/* Fetch texel from 1D, 2D or 3D argb8888_rev texture, return 4 GLfloats */
+static void FETCH(f_argb8888_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_CHAN( (s >> 8) & 0xff );
- texel[GCOMP] = UBYTE_TO_CHAN( (s >> 16) & 0xff );
- texel[BCOMP] = UBYTE_TO_CHAN( (s >> 24) );
- texel[ACOMP] = UBYTE_TO_CHAN( (s ) & 0xff );
+ texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
+ texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
+ texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
}
#if DIM == 3
@@ -702,14 +686,14 @@ static void store_texel_argb8888_rev(struct gl_texture_image *texImage,
/* MESA_FORMAT_RGB888 ********************************************************/
/* Fetch texel from 1D, 2D or 3D rgb888 texture, return 4 GLchans */
-static void FETCH(rgb888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_rgb888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- texel[RCOMP] = UBYTE_TO_CHAN( src[2] );
- texel[GCOMP] = UBYTE_TO_CHAN( src[1] );
- texel[BCOMP] = UBYTE_TO_CHAN( src[0] );
- texel[ACOMP] = CHAN_MAX;
+ texel[RCOMP] = UBYTE_TO_FLOAT( src[2] );
+ texel[GCOMP] = UBYTE_TO_FLOAT( src[1] );
+ texel[BCOMP] = UBYTE_TO_FLOAT( src[0] );
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -718,9 +702,9 @@ static void store_texel_rgb888(struct gl_texture_image *texImage,
{
const GLubyte *rgba = (const GLubyte *) texel;
GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- dst[0] = rgba[RCOMP];
+ dst[0] = rgba[BCOMP];
dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
+ dst[2] = rgba[RCOMP];
}
#endif
@@ -728,14 +712,14 @@ static void store_texel_rgb888(struct gl_texture_image *texImage,
/* MESA_FORMAT_BGR888 ********************************************************/
/* Fetch texel from 1D, 2D or 3D bgr888 texture, return 4 GLchans */
-static void FETCH(bgr888)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_bgr888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- texel[RCOMP] = UBYTE_TO_CHAN( src[0] );
- texel[GCOMP] = UBYTE_TO_CHAN( src[1] );
- texel[BCOMP] = UBYTE_TO_CHAN( src[2] );
- texel[ACOMP] = CHAN_MAX;
+ texel[RCOMP] = UBYTE_TO_FLOAT( src[0] );
+ texel[GCOMP] = UBYTE_TO_FLOAT( src[1] );
+ texel[BCOMP] = UBYTE_TO_FLOAT( src[2] );
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -744,9 +728,9 @@ static void store_texel_bgr888(struct gl_texture_image *texImage,
{
const GLubyte *rgba = (const GLubyte *) texel;
GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- dst[0] = rgba[BCOMP];
+ dst[0] = rgba[RCOMP];
dst[1] = rgba[GCOMP];
- dst[2] = rgba[RCOMP];
+ dst[2] = rgba[BCOMP];
}
#endif
@@ -757,15 +741,15 @@ static void store_texel_bgr888(struct gl_texture_image *texImage,
/* MESA_FORMAT_RGB565 ********************************************************/
/* Fetch texel from 1D, 2D or 3D rgb565 texture, return 4 GLchans */
-static void FETCH(rgb565)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_rgb565)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
const GLushort s = *src;
- texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) );
- texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) );
- texel[BCOMP] = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
- texel[ACOMP] = CHAN_MAX;
+ texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F);
+ texel[GCOMP] = ((s >> 5 ) & 0x3f) * (1.0F / 63.0F);
+ texel[BCOMP] = ((s ) & 0x1f) * (1.0F / 31.0F);
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -782,15 +766,15 @@ static void store_texel_rgb565(struct gl_texture_image *texImage,
/* MESA_FORMAT_RGB565_REV ****************************************************/
/* Fetch texel from 1D, 2D or 3D rgb565_rev texture, return 4 GLchans */
-static void FETCH(rgb565_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_rgb565_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
const GLushort s = (*src >> 8) | (*src << 8); /* byte swap */
- texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) );
- texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) );
- texel[BCOMP] = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
- texel[ACOMP] = CHAN_MAX;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -806,15 +790,15 @@ static void store_texel_rgb565_rev(struct gl_texture_image *texImage,
/* MESA_FORMAT_RGBA4444 ******************************************************/
/* Fetch texel from 1D, 2D or 3D argb444 texture, return 4 GLchans */
-static void FETCH(rgba4444)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_rgba4444)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
const GLushort s = *src;
- texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 12) & 0xf) | ((s >> 8) & 0xf0) );
- texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) | ((s >> 4) & 0xf0) );
- texel[BCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) | ((s ) & 0xf0) );
- texel[ACOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) | ((s << 4) & 0xf0) );
+ texel[RCOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F);
+ texel[GCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F);
+ texel[BCOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F);
+ texel[ACOMP] = ((s ) & 0xf) * (1.0F / 15.0F);
}
#if DIM == 3
@@ -831,15 +815,15 @@ static void store_texel_rgba4444(struct gl_texture_image *texImage,
/* MESA_FORMAT_ARGB4444 ******************************************************/
/* Fetch texel from 1D, 2D or 3D argb444 texture, return 4 GLchans */
-static void FETCH(argb4444)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_argb4444)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
const GLushort s = *src;
- texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) | ((s >> 4) & 0xf0) );
- texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) | ((s ) & 0xf0) );
- texel[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) | ((s << 4) & 0xf0) );
- texel[ACOMP] = UBYTE_TO_CHAN( ((s >> 12) & 0xf) | ((s >> 8) & 0xf0) );
+ texel[RCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F);
+ texel[GCOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F);
+ texel[BCOMP] = ((s ) & 0xf) * (1.0F / 15.0F);
+ texel[ACOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F);
}
#if DIM == 3
@@ -856,14 +840,14 @@ static void store_texel_argb4444(struct gl_texture_image *texImage,
/* MESA_FORMAT_ARGB4444_REV **************************************************/
/* Fetch texel from 1D, 2D or 3D argb4444_rev texture, return 4 GLchans */
-static void FETCH(argb4444_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_argb4444_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
- texel[RCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) | ((s << 4) & 0xf0) );
- texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 12) & 0xf) | ((s >> 8) & 0xf0) );
- texel[BCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) | ((s >> 4) & 0xf0) );
- texel[ACOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) | ((s ) & 0xf0) );
+ texel[RCOMP] = ((s ) & 0xf) * (1.0F / 15.0F);
+ texel[GCOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F);
+ texel[BCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F);
+ texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F);
}
#if DIM == 3
@@ -879,15 +863,15 @@ static void store_texel_argb4444_rev(struct gl_texture_image *texImage,
/* MESA_FORMAT_RGBA5551 ******************************************************/
/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */
-static void FETCH(rgba5551)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_rgba5551)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
const GLushort s = *src;
- texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) );
- texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 3) & 0xf8) | ((s >> 8) & 0x7) );
- texel[BCOMP] = UBYTE_TO_CHAN( ((s << 2) & 0xf8) | ((s >> 3) & 0x7) );
- texel[ACOMP] = UBYTE_TO_CHAN( ((s) & 0x01) ? 255 : 0);
+ texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F);
+ texel[GCOMP] = ((s >> 6) & 0x1f) * (1.0F / 31.0F);
+ texel[BCOMP] = ((s >> 1) & 0x1f) * (1.0F / 31.0F);
+ texel[ACOMP] = ((s ) & 0x01) * 1.0F;
}
#if DIM == 3
@@ -903,15 +887,15 @@ static void store_texel_rgba5551(struct gl_texture_image *texImage,
/* MESA_FORMAT_ARGB1555 ******************************************************/
/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */
-static void FETCH(argb1555)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_argb1555)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
const GLushort s = *src;
- texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) );
- texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) );
- texel[BCOMP] = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
- texel[ACOMP] = UBYTE_TO_CHAN( ((s >> 15) & 0x01) * 255 );
+ texel[RCOMP] = ((s >> 10) & 0x1f) * (1.0F / 31.0F);
+ texel[GCOMP] = ((s >> 5) & 0x1f) * (1.0F / 31.0F);
+ texel[BCOMP] = ((s >> 0) & 0x1f) * (1.0F / 31.0F);
+ texel[ACOMP] = ((s >> 15) & 0x01) * 1.0F;
}
#if DIM == 3
@@ -928,15 +912,15 @@ static void store_texel_argb1555(struct gl_texture_image *texImage,
/* MESA_FORMAT_ARGB1555_REV **************************************************/
/* Fetch texel from 1D, 2D or 3D argb1555_rev texture, return 4 GLchans */
-static void FETCH(argb1555_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_argb1555_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
const GLushort s = (*src << 8) | (*src >> 8); /* byteswap */
- texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) );
- texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) );
- texel[BCOMP] = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
- texel[ACOMP] = UBYTE_TO_CHAN( ((s >> 15) & 0x01) * 255 );
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
+ texel[ACOMP] = UBYTE_TO_FLOAT( ((s >> 15) & 0x01) * 255 );
}
#if DIM == 3
@@ -953,14 +937,14 @@ static void store_texel_argb1555_rev(struct gl_texture_image *texImage,
/* MESA_FORMAT_AL88 **********************************************************/
/* Fetch texel from 1D, 2D or 3D al88 texture, return 4 GLchans */
-static void FETCH(al88)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_al88)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
texel[RCOMP] =
texel[GCOMP] =
- texel[BCOMP] = UBYTE_TO_CHAN( s & 0xff );
- texel[ACOMP] = UBYTE_TO_CHAN( s >> 8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( s & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( s >> 8 );
}
#if DIM == 3
@@ -977,14 +961,14 @@ static void store_texel_al88(struct gl_texture_image *texImage,
/* MESA_FORMAT_AL88_REV ******************************************************/
/* Fetch texel from 1D, 2D or 3D al88_rev texture, return 4 GLchans */
-static void FETCH(al88_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_al88_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
texel[RCOMP] =
texel[GCOMP] =
- texel[BCOMP] = UBYTE_TO_CHAN( s >> 8 );
- texel[ACOMP] = UBYTE_TO_CHAN( s & 0xff );
+ texel[BCOMP] = UBYTE_TO_FLOAT( s >> 8 );
+ texel[ACOMP] = UBYTE_TO_FLOAT( s & 0xff );
}
#if DIM == 3
@@ -1001,17 +985,15 @@ static void store_texel_al88_rev(struct gl_texture_image *texImage,
/* MESA_FORMAT_RGB332 ********************************************************/
/* Fetch texel from 1D, 2D or 3D rgb332 texture, return 4 GLchans */
-static void FETCH(rgb332)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_rgb332)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
- static const GLubyte lut2to8[4] = {0, 85, 170, 255};
- static const GLubyte lut3to8[8] = {0, 36, 73, 109, 146, 182, 219, 255};
const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
const GLubyte s = *src;
- texel[RCOMP] = UBYTE_TO_CHAN( lut3to8[(s >> 5) & 0x7] );
- texel[GCOMP] = UBYTE_TO_CHAN( lut3to8[(s >> 2) & 0x7] );
- texel[BCOMP] = UBYTE_TO_CHAN( lut2to8[(s ) & 0x3] );
- texel[ACOMP] = CHAN_MAX;
+ texel[RCOMP] = ((s >> 5) & 0x7) * (1.0F / 7.0F);
+ texel[GCOMP] = ((s >> 2) & 0x7) * (1.0F / 7.0F);
+ texel[BCOMP] = ((s ) & 0x3) * (1.0F / 3.0F);
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -1028,14 +1010,14 @@ static void store_texel_rgb332(struct gl_texture_image *texImage,
/* MESA_FORMAT_A8 ************************************************************/
/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */
-static void FETCH(a8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_a8)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
texel[RCOMP] =
texel[GCOMP] =
- texel[BCOMP] = 0;
- texel[ACOMP] = UBYTE_TO_CHAN( src[0] );
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = UBYTE_TO_FLOAT( src[0] );
}
#if DIM == 3
@@ -1052,14 +1034,14 @@ static void store_texel_a8(struct gl_texture_image *texImage,
/* MESA_FORMAT_L8 ************************************************************/
/* Fetch texel from 1D, 2D or 3D l8 texture, return 4 GLchans */
-static void FETCH(l8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_l8)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
texel[RCOMP] =
texel[GCOMP] =
- texel[BCOMP] = UBYTE_TO_CHAN( src[0] );
- texel[ACOMP] = CHAN_MAX;
+ texel[BCOMP] = UBYTE_TO_FLOAT( src[0] );
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -1076,14 +1058,14 @@ static void store_texel_l8(struct gl_texture_image *texImage,
/* MESA_FORMAT_I8 ************************************************************/
/* Fetch texel from 1D, 2D or 3D i8 texture, return 4 GLchans */
-static void FETCH(i8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_i8)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
texel[RCOMP] =
texel[GCOMP] =
texel[BCOMP] =
- texel[ACOMP] = UBYTE_TO_CHAN( src[0] );
+ texel[ACOMP] = UBYTE_TO_FLOAT( src[0] );
}
#if DIM == 3
@@ -1102,12 +1084,11 @@ static void store_texel_i8(struct gl_texture_image *texImage,
/* Fetch CI texel from 1D, 2D or 3D ci8 texture, lookup the index in a
* color table, and return 4 GLchans.
*/
-static void FETCH(ci8)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+static void FETCH(f_ci8)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
const struct gl_color_table *palette;
- GLubyte texelUB[4];
GLuint index;
GET_CURRENT_CONTEXT(ctx);
@@ -1124,61 +1105,48 @@ static void FETCH(ci8)( const struct gl_texture_image *texImage,
index = (*src) & (palette->Size - 1);
{
- const GLubyte *table = palette->TableUB;
+ const GLfloat *table = palette->TableF;
switch (palette->_BaseFormat) {
case GL_ALPHA:
- texelUB[RCOMP] =
- texelUB[GCOMP] =
- texelUB[BCOMP] = 0;
- texelUB[ACOMP] = table[index];
- break;;
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = table[index];
+ break;
case GL_LUMINANCE:
- texelUB[RCOMP] =
- texelUB[GCOMP] =
- texelUB[BCOMP] = table[index];
- texelUB[ACOMP] = 255;
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = table[index];
+ texel[ACOMP] = 1.0F;
break;
case GL_INTENSITY:
- texelUB[RCOMP] =
- texelUB[GCOMP] =
- texelUB[BCOMP] =
- texelUB[ACOMP] = table[index];
- break;;
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] =
+ texel[ACOMP] = table[index];
+ break;
case GL_LUMINANCE_ALPHA:
- texelUB[RCOMP] =
- texelUB[GCOMP] =
- texelUB[BCOMP] = table[index * 2 + 0];
- texelUB[ACOMP] = table[index * 2 + 1];
- break;;
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = table[index * 2 + 0];
+ texel[ACOMP] = table[index * 2 + 1];
+ break;
case GL_RGB:
- texelUB[RCOMP] = table[index * 3 + 0];
- texelUB[GCOMP] = table[index * 3 + 1];
- texelUB[BCOMP] = table[index * 3 + 2];
- texelUB[ACOMP] = 255;
- break;;
+ texel[RCOMP] = table[index * 3 + 0];
+ texel[GCOMP] = table[index * 3 + 1];
+ texel[BCOMP] = table[index * 3 + 2];
+ texel[ACOMP] = 1.0F;
+ break;
case GL_RGBA:
- texelUB[RCOMP] = table[index * 4 + 0];
- texelUB[GCOMP] = table[index * 4 + 1];
- texelUB[BCOMP] = table[index * 4 + 2];
- texelUB[ACOMP] = table[index * 4 + 3];
- break;;
+ texel[RCOMP] = table[index * 4 + 0];
+ texel[GCOMP] = table[index * 4 + 1];
+ texel[BCOMP] = table[index * 4 + 2];
+ texel[ACOMP] = table[index * 4 + 3];
+ break;
default:
_mesa_problem(ctx, "Bad palette format in fetch_texel_ci8");
return;
}
-#if CHAN_TYPE == GL_UNSIGNED_BYTE
- COPY_4UBV(texel, texelUB);
-#elif CHAN_TYPE == GL_UNSIGNED_SHORT
- texel[0] = UBYTE_TO_USHORT(texelUB[0]);
- texel[1] = UBYTE_TO_USHORT(texelUB[1]);
- texel[2] = UBYTE_TO_USHORT(texelUB[2]);
- texel[3] = UBYTE_TO_USHORT(texelUB[3]);
-#else
- texel[0] = UBYTE_TO_FLOAT(texelUB[0]);
- texel[1] = UBYTE_TO_FLOAT(texelUB[1]);
- texel[2] = UBYTE_TO_FLOAT(texelUB[2]);
- texel[3] = UBYTE_TO_FLOAT(texelUB[3]);
-#endif
}
}
@@ -1196,14 +1164,15 @@ static void store_texel_ci8(struct gl_texture_image *texImage,
#if FEATURE_EXT_texture_sRGB
/* Fetch texel from 1D, 2D or 3D srgb8 texture, return 4 GLfloats */
+/* Note: component order is same as for MESA_FORMAT_RGB888 */
static void FETCH(srgb8)(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- texel[RCOMP] = nonlinear_to_linear(src[0]);
+ texel[RCOMP] = nonlinear_to_linear(src[2]);
texel[GCOMP] = nonlinear_to_linear(src[1]);
- texel[BCOMP] = nonlinear_to_linear(src[2]);
- texel[ACOMP] = CHAN_MAX;
+ texel[BCOMP] = nonlinear_to_linear(src[0]);
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -1212,9 +1181,9 @@ static void store_texel_srgb8(struct gl_texture_image *texImage,
{
const GLubyte *rgba = (const GLubyte *) texel;
GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
- dst[0] = rgba[RCOMP]; /* no conversion */
+ dst[0] = rgba[BCOMP]; /* no conversion */
dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
+ dst[2] = rgba[RCOMP];
}
#endif
@@ -1222,11 +1191,11 @@ static void store_texel_srgb8(struct gl_texture_image *texImage,
static void FETCH(srgba8)(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel )
{
- const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4);
- texel[RCOMP] = nonlinear_to_linear(src[0]);
- texel[GCOMP] = nonlinear_to_linear(src[1]);
- texel[BCOMP] = nonlinear_to_linear(src[2]);
- texel[ACOMP] = UBYTE_TO_FLOAT(src[3]); /* linear! */
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = nonlinear_to_linear( (s >> 24) );
+ texel[GCOMP] = nonlinear_to_linear( (s >> 16) & 0xff );
+ texel[BCOMP] = nonlinear_to_linear( (s >> 8) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); /* linear! */
}
#if DIM == 3
@@ -1234,10 +1203,29 @@ static void store_texel_srgba8(struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, const void *texel)
{
const GLubyte *rgba = (const GLubyte *) texel;
- GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4);
- dst[0] = rgba[RCOMP];
- dst[1] = rgba[GCOMP];
- dst[2] = rgba[BCOMP];
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
+/* Fetch texel from 1D, 2D or 3D sargb8 texture, return 4 GLfloats */
+static void FETCH(sargb8)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = nonlinear_to_linear( (s >> 16) & 0xff );
+ texel[GCOMP] = nonlinear_to_linear( (s >> 8) & 0xff );
+ texel[BCOMP] = nonlinear_to_linear( (s ) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); /* linear! */
+}
+
+#if DIM == 3
+static void store_texel_sargb8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
}
#endif
@@ -1249,7 +1237,7 @@ static void FETCH(sl8)(const struct gl_texture_image *texImage,
texel[RCOMP] =
texel[GCOMP] =
texel[BCOMP] = nonlinear_to_linear(src[0]);
- texel[ACOMP] = CHAN_MAX;
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -1284,19 +1272,74 @@ static void store_texel_sla8(struct gl_texture_image *texImage,
}
#endif
+#endif /* FEATURE_EXT_texture_sRGB */
-#endif /* FEATURE_EXT_texture_sRGB */
+/* MESA_FORMAT_DUDV8 ********************************************************/
+
+/* this format by definition produces 0,0,0,1 as rgba values,
+ however we'll return the dudv values as rg and fix up elsewhere */
+static void FETCH(dudv8)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 2);
+ texel[RCOMP] = BYTE_TO_FLOAT(src[0]);
+ texel[GCOMP] = BYTE_TO_FLOAT(src[1]);
+ texel[BCOMP] = 0;
+ texel[ACOMP] = 0;
+}
+
+/* MESA_FORMAT_SIGNED_RGBA8888 ***********************************************/
+
+static void FETCH(signed_rgba8888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = BYTE_TO_FLOAT_TEX( (s >> 24) );
+ texel[GCOMP] = BYTE_TO_FLOAT_TEX( (s >> 16) & 0xff );
+ texel[BCOMP] = BYTE_TO_FLOAT_TEX( (s >> 8) & 0xff );
+ texel[ACOMP] = BYTE_TO_FLOAT_TEX( (s ) & 0xff );
+}
+
+#if DIM == 3
+static void store_texel_signed_rgba8888(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLbyte *rgba = (const GLbyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
+static void FETCH(signed_rgba8888_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = BYTE_TO_FLOAT_TEX( (s ) & 0xff );
+ texel[GCOMP] = BYTE_TO_FLOAT_TEX( (s >> 8) & 0xff );
+ texel[BCOMP] = BYTE_TO_FLOAT_TEX( (s >> 16) & 0xff );
+ texel[ACOMP] = BYTE_TO_FLOAT_TEX( (s >> 24) );
+}
+
+#if DIM == 3
+static void store_texel_signed_rgba8888_rev(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
/* MESA_FORMAT_YCBCR *********************************************************/
-/* Fetch texel from 1D, 2D or 3D ycbcr texture, return 4 GLchans */
-/* We convert YCbCr to RGB here */
-/* XXX this may break if GLchan != GLubyte */
-static void FETCH(ycbcr)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+/* Fetch texel from 1D, 2D or 3D ycbcr texture, return 4 GLfloats.
+ * We convert YCbCr to RGB here.
+ */
+static void FETCH(f_ycbcr)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */
const GLushort *src1 = src0 + 1; /* odd */
@@ -1304,23 +1347,17 @@ static void FETCH(ycbcr)( const struct gl_texture_image *texImage,
const GLubyte cb = *src0 & 0xff; /* chroma U */
const GLubyte y1 = (*src1 >> 8) & 0xff; /* luminance */
const GLubyte cr = *src1 & 0xff; /* chroma V */
- GLint r, g, b;
- if (i & 1) {
- /* odd pixel: use y1,cr,cb */
- r = (GLint) (1.164 * (y1-16) + 1.596 * (cr-128));
- g = (GLint) (1.164 * (y1-16) - 0.813 * (cr-128) - 0.391 * (cb-128));
- b = (GLint) (1.164 * (y1-16) + 2.018 * (cb-128));
- }
- else {
- /* even pixel: use y0,cr,cb */
- r = (GLint) (1.164 * (y0-16) + 1.596 * (cr-128));
- g = (GLint) (1.164 * (y0-16) - 0.813 * (cr-128) - 0.391 * (cb-128));
- b = (GLint) (1.164 * (y0-16) + 2.018 * (cb-128));
- }
- texel[RCOMP] = CLAMP(r, 0, CHAN_MAX);
- texel[GCOMP] = CLAMP(g, 0, CHAN_MAX);
- texel[BCOMP] = CLAMP(b, 0, CHAN_MAX);
- texel[ACOMP] = CHAN_MAX;
+ const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */
+ GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128);
+ GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128);
+ GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128);
+ r *= (1.0F / 255.0F);
+ g *= (1.0F / 255.0F);
+ b *= (1.0F / 255.0F);
+ texel[RCOMP] = CLAMP(r, 0.0F, 1.0F);
+ texel[GCOMP] = CLAMP(g, 0.0F, 1.0F);
+ texel[BCOMP] = CLAMP(b, 0.0F, 1.0F);
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
@@ -1339,11 +1376,11 @@ static void store_texel_ycbcr(struct gl_texture_image *texImage,
/* MESA_FORMAT_YCBCR_REV *****************************************************/
-/* Fetch texel from 1D, 2D or 3D ycbcr_rev texture, return 4 GLchans */
-/* We convert YCbCr to RGB here */
-/* XXX this may break if GLchan != GLubyte */
-static void FETCH(ycbcr_rev)( const struct gl_texture_image *texImage,
- GLint i, GLint j, GLint k, GLchan *texel )
+/* Fetch texel from 1D, 2D or 3D ycbcr_rev texture, return 4 GLfloats.
+ * We convert YCbCr to RGB here.
+ */
+static void FETCH(f_ycbcr_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
{
const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */
const GLushort *src1 = src0 + 1; /* odd */
@@ -1351,23 +1388,17 @@ static void FETCH(ycbcr_rev)( const struct gl_texture_image *texImage,
const GLubyte cr = (*src0 >> 8) & 0xff; /* chroma V */
const GLubyte y1 = *src1 & 0xff; /* luminance */
const GLubyte cb = (*src1 >> 8) & 0xff; /* chroma U */
- GLint r, g, b;
- if (i & 1) {
- /* odd pixel: use y1,cr,cb */
- r = (GLint) (1.164 * (y1-16) + 1.596 * (cr-128));
- g = (GLint) (1.164 * (y1-16) - 0.813 * (cr-128) - 0.391 * (cb-128));
- b = (GLint) (1.164 * (y1-16) + 2.018 * (cb-128));
- }
- else {
- /* even pixel: use y0,cr,cb */
- r = (GLint) (1.164 * (y0-16) + 1.596 * (cr-128));
- g = (GLint) (1.164 * (y0-16) - 0.813 * (cr-128) - 0.391 * (cb-128));
- b = (GLint) (1.164 * (y0-16) + 2.018 * (cb-128));
- }
- texel[RCOMP] = CLAMP(r, 0, CHAN_MAX);
- texel[GCOMP] = CLAMP(g, 0, CHAN_MAX);
- texel[BCOMP] = CLAMP(b, 0, CHAN_MAX);
- texel[ACOMP] = CHAN_MAX;
+ const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */
+ GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128);
+ GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128);
+ GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128);
+ r *= (1.0F / 255.0F);
+ g *= (1.0F / 255.0F);
+ b *= (1.0F / 255.0F);
+ texel[RCOMP] = CLAMP(r, 0.0F, 1.0F);
+ texel[GCOMP] = CLAMP(g, 0.0F, 1.0F);
+ texel[BCOMP] = CLAMP(b, 0.0F, 1.0F);
+ texel[ACOMP] = 1.0F;
}
#if DIM == 3
diff --git a/src/mesa/main/texgen.c b/src/mesa/main/texgen.c
index 244c7aaafc..8c98ee3602 100644
--- a/src/mesa/main/texgen.c
+++ b/src/mesa/main/texgen.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.5
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -34,15 +35,40 @@
#include "main/enums.h"
#include "main/macros.h"
#include "main/texgen.h"
-#include "math/m_xform.h"
+#include "math/m_matrix.h"
+#include "glapi/dispatch.h"
+#if FEATURE_texgen
+
+
+/**
+ * Return texgen state for given coordinate
+ */
+static struct gl_texgen *
+get_texgen(struct gl_texture_unit *texUnit, GLenum coord)
+{
+ switch (coord) {
+ case GL_S:
+ return &texUnit->GenS;
+ case GL_T:
+ return &texUnit->GenT;
+ case GL_R:
+ return &texUnit->GenR;
+ case GL_Q:
+ return &texUnit->GenQ;
+ default:
+ return NULL;
+ }
+}
+
void GLAPIENTRY
_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
{
- GET_CURRENT_CONTEXT(ctx);
struct gl_texture_unit *texUnit;
+ struct gl_texgen *texgen;
+ GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
@@ -59,210 +85,79 @@ _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- switch (coord) {
- case GL_S:
- if (pname==GL_TEXTURE_GEN_MODE) {
- GLenum mode = (GLenum) (GLint) *params;
- GLbitfield bits;
- switch (mode) {
- case GL_OBJECT_LINEAR:
- bits = TEXGEN_OBJ_LINEAR;
- break;
- case GL_EYE_LINEAR:
- bits = TEXGEN_EYE_LINEAR;
- break;
- case GL_REFLECTION_MAP_NV:
- bits = TEXGEN_REFLECTION_MAP_NV;
- break;
- case GL_NORMAL_MAP_NV:
- bits = TEXGEN_NORMAL_MAP_NV;
- break;
- case GL_SPHERE_MAP:
- bits = TEXGEN_SPHERE_MAP;
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
- return;
- }
- if (texUnit->GenModeS == mode)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->GenModeS = mode;
- texUnit->_GenBitS = bits;
- }
- else if (pname==GL_OBJECT_PLANE) {
- if (TEST_EQ_4V(texUnit->ObjectPlaneS, params))
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- COPY_4FV(texUnit->ObjectPlaneS, params);
- }
- else if (pname==GL_EYE_PLANE) {
- GLfloat tmp[4];
- /* Transform plane equation by the inverse modelview matrix */
- if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
- _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
- }
- _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
- if (TEST_EQ_4V(texUnit->EyePlaneS, tmp))
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- COPY_4FV(texUnit->EyePlaneS, tmp);
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
- return;
- }
- break;
- case GL_T:
- if (pname==GL_TEXTURE_GEN_MODE) {
- GLenum mode = (GLenum) (GLint) *params;
- GLbitfield bitt;
- switch (mode) {
- case GL_OBJECT_LINEAR:
- bitt = TEXGEN_OBJ_LINEAR;
- break;
- case GL_EYE_LINEAR:
- bitt = TEXGEN_EYE_LINEAR;
- break;
- case GL_REFLECTION_MAP_NV:
- bitt = TEXGEN_REFLECTION_MAP_NV;
- break;
- case GL_NORMAL_MAP_NV:
- bitt = TEXGEN_NORMAL_MAP_NV;
- break;
- case GL_SPHERE_MAP:
- bitt = TEXGEN_SPHERE_MAP;
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
- return;
- }
- if (texUnit->GenModeT == mode)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->GenModeT = mode;
- texUnit->_GenBitT = bitt;
- }
- else if (pname==GL_OBJECT_PLANE) {
- if (TEST_EQ_4V(texUnit->ObjectPlaneT, params))
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- COPY_4FV(texUnit->ObjectPlaneT, params);
- }
- else if (pname==GL_EYE_PLANE) {
- GLfloat tmp[4];
- /* Transform plane equation by the inverse modelview matrix */
- if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
- _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
- }
- _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
- if (TEST_EQ_4V(texUnit->EyePlaneT, tmp))
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- COPY_4FV(texUnit->EyePlaneT, tmp);
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
- return;
- }
- break;
- case GL_R:
- if (pname==GL_TEXTURE_GEN_MODE) {
- GLenum mode = (GLenum) (GLint) *params;
- GLbitfield bitr;
- switch (mode) {
- case GL_OBJECT_LINEAR:
- bitr = TEXGEN_OBJ_LINEAR;
- break;
- case GL_REFLECTION_MAP_NV:
- bitr = TEXGEN_REFLECTION_MAP_NV;
- break;
- case GL_NORMAL_MAP_NV:
- bitr = TEXGEN_NORMAL_MAP_NV;
- break;
- case GL_EYE_LINEAR:
- bitr = TEXGEN_EYE_LINEAR;
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
- return;
- }
- if (texUnit->GenModeR == mode)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->GenModeR = mode;
- texUnit->_GenBitR = bitr;
- }
- else if (pname==GL_OBJECT_PLANE) {
- if (TEST_EQ_4V(texUnit->ObjectPlaneR, params))
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- COPY_4FV(texUnit->ObjectPlaneR, params);
- }
- else if (pname==GL_EYE_PLANE) {
- GLfloat tmp[4];
- /* Transform plane equation by the inverse modelview matrix */
- if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
- _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
- }
- _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
- if (TEST_EQ_4V(texUnit->EyePlaneR, tmp))
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- COPY_4FV(texUnit->EyePlaneR, tmp);
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
- return;
- }
- break;
- case GL_Q:
- if (pname==GL_TEXTURE_GEN_MODE) {
- GLenum mode = (GLenum) (GLint) *params;
- GLbitfield bitq;
- switch (mode) {
- case GL_OBJECT_LINEAR:
- bitq = TEXGEN_OBJ_LINEAR;
- break;
- case GL_EYE_LINEAR:
- bitq = TEXGEN_EYE_LINEAR;
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
- return;
- }
- if (texUnit->GenModeQ == mode)
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->GenModeQ = mode;
- texUnit->_GenBitQ = bitq;
- }
- else if (pname==GL_OBJECT_PLANE) {
- if (TEST_EQ_4V(texUnit->ObjectPlaneQ, params))
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- COPY_4FV(texUnit->ObjectPlaneQ, params);
- }
- else if (pname==GL_EYE_PLANE) {
- GLfloat tmp[4];
- /* Transform plane equation by the inverse modelview matrix */
- if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
- _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
- }
- _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
- if (TEST_EQ_4V(texUnit->EyePlaneQ, tmp))
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- COPY_4FV(texUnit->EyePlaneQ, tmp);
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
- return;
- }
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(coord)" );
- return;
+ texgen = get_texgen(texUnit, coord);
+ if (!texgen) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexGen(coord)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ {
+ GLenum mode = (GLenum) (GLint) params[0];
+ GLbitfield bit = 0x0;
+ if (texgen->Mode == mode)
+ return;
+ switch (mode) {
+ case GL_OBJECT_LINEAR:
+ bit = TEXGEN_OBJ_LINEAR;
+ break;
+ case GL_EYE_LINEAR:
+ bit = TEXGEN_EYE_LINEAR;
+ break;
+ case GL_SPHERE_MAP:
+ if (coord == GL_S || coord == GL_T)
+ bit = TEXGEN_SPHERE_MAP;
+ break;
+ case GL_REFLECTION_MAP_NV:
+ if (coord != GL_Q)
+ bit = TEXGEN_REFLECTION_MAP_NV;
+ break;
+ case GL_NORMAL_MAP_NV:
+ if (coord != GL_Q)
+ bit = TEXGEN_NORMAL_MAP_NV;
+ break;
+ default:
+ ; /* nop */
+ }
+ if (!bit) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
+ return;
+ }
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texgen->Mode = mode;
+ texgen->_ModeBit = bit;
+ }
+ break;
+
+ case GL_OBJECT_PLANE:
+ {
+ if (TEST_EQ_4V(texgen->ObjectPlane, params))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ COPY_4FV(texgen->ObjectPlane, params);
+ }
+ break;
+
+ case GL_EYE_PLANE:
+ {
+ GLfloat tmp[4];
+ /* Transform plane equation by the inverse modelview matrix */
+ if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
+ _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
+ }
+ _mesa_transform_vector(tmp, params,
+ ctx->ModelviewMatrixStack.Top->inv);
+ if (TEST_EQ_4V(texgen->EyePlane, tmp))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ COPY_4FV(texgen->EyePlane, tmp);
+ }
+ break;
+
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
+ return;
}
if (ctx->Driver.TexGen)
@@ -330,7 +225,8 @@ _mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
void GLAPIENTRY
_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
{
- const struct gl_texture_unit *texUnit;
+ struct gl_texture_unit *texUnit;
+ struct gl_texgen *texgen;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -341,70 +237,24 @@ _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- switch (coord) {
- case GL_S:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = ENUM_TO_DOUBLE(texUnit->GenModeS);
- }
- else if (pname==GL_OBJECT_PLANE) {
- COPY_4V( params, texUnit->ObjectPlaneS );
- }
- else if (pname==GL_EYE_PLANE) {
- COPY_4V( params, texUnit->EyePlaneS );
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
- return;
- }
- break;
- case GL_T:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = ENUM_TO_DOUBLE(texUnit->GenModeT);
- }
- else if (pname==GL_OBJECT_PLANE) {
- COPY_4V( params, texUnit->ObjectPlaneT );
- }
- else if (pname==GL_EYE_PLANE) {
- COPY_4V( params, texUnit->EyePlaneT );
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
- return;
- }
- break;
- case GL_R:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = ENUM_TO_DOUBLE(texUnit->GenModeR);
- }
- else if (pname==GL_OBJECT_PLANE) {
- COPY_4V( params, texUnit->ObjectPlaneR );
- }
- else if (pname==GL_EYE_PLANE) {
- COPY_4V( params, texUnit->EyePlaneR );
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
- return;
- }
- break;
- case GL_Q:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = ENUM_TO_DOUBLE(texUnit->GenModeQ);
- }
- else if (pname==GL_OBJECT_PLANE) {
- COPY_4V( params, texUnit->ObjectPlaneQ );
- }
- else if (pname==GL_EYE_PLANE) {
- COPY_4V( params, texUnit->EyePlaneQ );
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
- return;
- }
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)" );
- return;
+ texgen = get_texgen(texUnit, coord);
+ if (!texgen) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ params[0] = ENUM_TO_DOUBLE(texgen->Mode);
+ break;
+ case GL_OBJECT_PLANE:
+ COPY_4V(params, texgen->ObjectPlane);
+ break;
+ case GL_EYE_PLANE:
+ COPY_4V(params, texgen->EyePlane);
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
}
}
@@ -413,7 +263,8 @@ _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
void GLAPIENTRY
_mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
{
- const struct gl_texture_unit *texUnit;
+ struct gl_texture_unit *texUnit;
+ struct gl_texgen *texgen;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -424,70 +275,24 @@ _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- switch (coord) {
- case GL_S:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = ENUM_TO_FLOAT(texUnit->GenModeS);
- }
- else if (pname==GL_OBJECT_PLANE) {
- COPY_4V( params, texUnit->ObjectPlaneS );
- }
- else if (pname==GL_EYE_PLANE) {
- COPY_4V( params, texUnit->EyePlaneS );
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
- return;
- }
- break;
- case GL_T:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = ENUM_TO_FLOAT(texUnit->GenModeT);
- }
- else if (pname==GL_OBJECT_PLANE) {
- COPY_4V( params, texUnit->ObjectPlaneT );
- }
- else if (pname==GL_EYE_PLANE) {
- COPY_4V( params, texUnit->EyePlaneT );
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
- return;
- }
- break;
- case GL_R:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = ENUM_TO_FLOAT(texUnit->GenModeR);
- }
- else if (pname==GL_OBJECT_PLANE) {
- COPY_4V( params, texUnit->ObjectPlaneR );
- }
- else if (pname==GL_EYE_PLANE) {
- COPY_4V( params, texUnit->EyePlaneR );
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
- return;
- }
- break;
- case GL_Q:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = ENUM_TO_FLOAT(texUnit->GenModeQ);
- }
- else if (pname==GL_OBJECT_PLANE) {
- COPY_4V( params, texUnit->ObjectPlaneQ );
- }
- else if (pname==GL_EYE_PLANE) {
- COPY_4V( params, texUnit->EyePlaneQ );
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
- return;
- }
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)" );
- return;
+ texgen = get_texgen(texUnit, coord);
+ if (!texgen) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ params[0] = ENUM_TO_FLOAT(texgen->Mode);
+ break;
+ case GL_OBJECT_PLANE:
+ COPY_4V(params, texgen->ObjectPlane);
+ break;
+ case GL_EYE_PLANE:
+ COPY_4V(params, texgen->EyePlane);
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
}
}
@@ -496,7 +301,8 @@ _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
void GLAPIENTRY
_mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
{
- const struct gl_texture_unit *texUnit;
+ struct gl_texture_unit *texUnit;
+ struct gl_texgen *texgen;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -507,95 +313,47 @@ _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- switch (coord) {
- case GL_S:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = texUnit->GenModeS;
- }
- else if (pname==GL_OBJECT_PLANE) {
- params[0] = (GLint) texUnit->ObjectPlaneS[0];
- params[1] = (GLint) texUnit->ObjectPlaneS[1];
- params[2] = (GLint) texUnit->ObjectPlaneS[2];
- params[3] = (GLint) texUnit->ObjectPlaneS[3];
- }
- else if (pname==GL_EYE_PLANE) {
- params[0] = (GLint) texUnit->EyePlaneS[0];
- params[1] = (GLint) texUnit->EyePlaneS[1];
- params[2] = (GLint) texUnit->EyePlaneS[2];
- params[3] = (GLint) texUnit->EyePlaneS[3];
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
- return;
- }
- break;
- case GL_T:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = texUnit->GenModeT;
- }
- else if (pname==GL_OBJECT_PLANE) {
- params[0] = (GLint) texUnit->ObjectPlaneT[0];
- params[1] = (GLint) texUnit->ObjectPlaneT[1];
- params[2] = (GLint) texUnit->ObjectPlaneT[2];
- params[3] = (GLint) texUnit->ObjectPlaneT[3];
- }
- else if (pname==GL_EYE_PLANE) {
- params[0] = (GLint) texUnit->EyePlaneT[0];
- params[1] = (GLint) texUnit->EyePlaneT[1];
- params[2] = (GLint) texUnit->EyePlaneT[2];
- params[3] = (GLint) texUnit->EyePlaneT[3];
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
- return;
- }
- break;
- case GL_R:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = texUnit->GenModeR;
- }
- else if (pname==GL_OBJECT_PLANE) {
- params[0] = (GLint) texUnit->ObjectPlaneR[0];
- params[1] = (GLint) texUnit->ObjectPlaneR[1];
- params[2] = (GLint) texUnit->ObjectPlaneR[2];
- params[3] = (GLint) texUnit->ObjectPlaneR[3];
- }
- else if (pname==GL_EYE_PLANE) {
- params[0] = (GLint) texUnit->EyePlaneR[0];
- params[1] = (GLint) texUnit->EyePlaneR[1];
- params[2] = (GLint) texUnit->EyePlaneR[2];
- params[3] = (GLint) texUnit->EyePlaneR[3];
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
- return;
- }
- break;
- case GL_Q:
- if (pname==GL_TEXTURE_GEN_MODE) {
- params[0] = texUnit->GenModeQ;
- }
- else if (pname==GL_OBJECT_PLANE) {
- params[0] = (GLint) texUnit->ObjectPlaneQ[0];
- params[1] = (GLint) texUnit->ObjectPlaneQ[1];
- params[2] = (GLint) texUnit->ObjectPlaneQ[2];
- params[3] = (GLint) texUnit->ObjectPlaneQ[3];
- }
- else if (pname==GL_EYE_PLANE) {
- params[0] = (GLint) texUnit->EyePlaneQ[0];
- params[1] = (GLint) texUnit->EyePlaneQ[1];
- params[2] = (GLint) texUnit->EyePlaneQ[2];
- params[3] = (GLint) texUnit->EyePlaneQ[3];
- }
- else {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
- return;
- }
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)" );
- return;
+ texgen = get_texgen(texUnit, coord);
+ if (!texgen) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ params[0] = texgen->Mode;
+ break;
+ case GL_OBJECT_PLANE:
+ params[0] = (GLint) texgen->ObjectPlane[0];
+ params[1] = (GLint) texgen->ObjectPlane[1];
+ params[2] = (GLint) texgen->ObjectPlane[2];
+ params[3] = (GLint) texgen->ObjectPlane[3];
+ break;
+ case GL_EYE_PLANE:
+ params[0] = (GLint) texgen->EyePlane[0];
+ params[1] = (GLint) texgen->EyePlane[1];
+ params[2] = (GLint) texgen->EyePlane[2];
+ params[3] = (GLint) texgen->EyePlane[3];
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
}
}
+void
+_mesa_init_texgen_dispatch(struct _glapi_table *disp)
+{
+ SET_GetTexGendv(disp, _mesa_GetTexGendv);
+ SET_GetTexGenfv(disp, _mesa_GetTexGenfv);
+ SET_GetTexGeniv(disp, _mesa_GetTexGeniv);
+ SET_TexGend(disp, _mesa_TexGend);
+ SET_TexGendv(disp, _mesa_TexGendv);
+ SET_TexGenf(disp, _mesa_TexGenf);
+ SET_TexGenfv(disp, _mesa_TexGenfv);
+ SET_TexGeni(disp, _mesa_TexGeni);
+ SET_TexGeniv(disp, _mesa_TexGeniv);
+}
+
+
+#endif /* FEATURE_texgen */
diff --git a/src/mesa/main/texgen.h b/src/mesa/main/texgen.h
index 073588efcd..2ca026de3d 100644
--- a/src/mesa/main/texgen.h
+++ b/src/mesa/main/texgen.h
@@ -27,9 +27,16 @@
#define TEXGEN_H
-#include "main/glheader.h"
+#include "main/mtypes.h"
+#if FEATURE_texgen
+
+#define _MESA_INIT_TEXGEN_FUNCTIONS(driver, impl) \
+ do { \
+ (driver)->TexGen = impl ## TexGen; \
+ } while (0)
+
extern void GLAPIENTRY
_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params );
@@ -57,6 +64,19 @@ _mesa_TexGeni( GLenum coord, GLenum pname, GLint param );
extern void GLAPIENTRY
_mesa_TexGeniv( GLenum coord, GLenum pname, const GLint *params );
+extern void
+_mesa_init_texgen_dispatch(struct _glapi_table *disp);
+
+#else /* FEATURE_texgen */
+
+#define _MESA_INIT_TEXGEN_FUNCTIONS(driver, impl) do { } while (0)
+
+static INLINE void
+_mesa_init_texgen_dispatch(struct _glapi_table *disp)
+{
+}
+
+#endif /* FEATURE_texgen */
#endif /* TEXGEN_H */
diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c
new file mode 100644
index 0000000000..14d6fc7659
--- /dev/null
+++ b/src/mesa/main/texgetimage.c
@@ -0,0 +1,581 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * 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.
+ */
+
+
+/**
+ * Code for glGetTexImage() and glGetCompressedTexImage().
+ */
+
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "image.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "texgetimage.h"
+#include "teximage.h"
+#include "texstate.h"
+
+
+
+#if FEATURE_EXT_texture_sRGB
+
+/**
+ * Test if given texture image is an sRGB format.
+ */
+static GLboolean
+is_srgb_teximage(const struct gl_texture_image *texImage)
+{
+ switch (texImage->TexFormat->MesaFormat) {
+ case MESA_FORMAT_SRGB8:
+ case MESA_FORMAT_SRGBA8:
+ case MESA_FORMAT_SARGB8:
+ case MESA_FORMAT_SL8:
+ case MESA_FORMAT_SLA8:
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Convert a float value from linear space to a
+ * non-linear sRGB value in [0, 255].
+ * Not terribly efficient.
+ */
+static INLINE GLfloat
+linear_to_nonlinear(GLfloat cl)
+{
+ /* can't have values outside [0, 1] */
+ GLfloat cs;
+ if (cl < 0.0031308f) {
+ cs = 12.92f * cl;
+ }
+ else {
+ cs = (GLfloat)(1.055 * _mesa_pow(cl, 0.41666) - 0.055);
+ }
+ return cs;
+}
+
+#endif /* FEATURE_EXT_texture_sRGB */
+
+
+/**
+ * Can the given type represent negative values?
+ */
+static INLINE GLboolean
+type_with_negative_values(GLenum type)
+{
+ switch (type) {
+ case GL_BYTE:
+ case GL_SHORT:
+ case GL_INT:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_ARB:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * This is the software fallback for Driver.GetTexImage().
+ * All error checking will have been done before this routine is called.
+ */
+void
+_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* Packing texture image into a PBO.
+ * Map the (potentially) VRAM-based buffer into our process space so
+ * we can write into it with the code below.
+ * A hardware driver might use a sophisticated blit to move the
+ * texture data to the PBO if the PBO is in VRAM along with the texture.
+ */
+ GLubyte *buf = (GLubyte *)
+ ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
+ if (!buf) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
+ return;
+ }
+ /* <pixels> was an offset into the PBO.
+ * Now make it a real, client-side pointer inside the mapped region.
+ */
+ pixels = ADD_POINTERS(buf, pixels);
+ }
+ else if (!pixels) {
+ /* not an error */
+ return;
+ }
+
+ {
+ const GLint width = texImage->Width;
+ const GLint height = texImage->Height;
+ const GLint depth = texImage->Depth;
+ GLint img, row;
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ /* compute destination address in client memory */
+ GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+ assert(dest);
+
+ if (format == GL_COLOR_INDEX) {
+ GLuint indexRow[MAX_WIDTH];
+ GLint col;
+ /* Can't use FetchTexel here because that returns RGBA */
+ if (texImage->TexFormat->IndexBits == 8) {
+ const GLubyte *src = (const GLubyte *) texImage->Data;
+ src += width * (img * texImage->Height + row);
+ for (col = 0; col < width; col++) {
+ indexRow[col] = src[col];
+ }
+ }
+ else if (texImage->TexFormat->IndexBits == 16) {
+ const GLushort *src = (const GLushort *) texImage->Data;
+ src += width * (img * texImage->Height + row);
+ for (col = 0; col < width; col++) {
+ indexRow[col] = src[col];
+ }
+ }
+ else {
+ _mesa_problem(ctx,
+ "Color index problem in _mesa_GetTexImage");
+ }
+ _mesa_pack_index_span(ctx, width, type, dest,
+ indexRow, &ctx->Pack,
+ 0 /* no image transfer */);
+ }
+ else if (format == GL_DEPTH_COMPONENT) {
+ GLfloat depthRow[MAX_WIDTH];
+ GLint col;
+ for (col = 0; col < width; col++) {
+ (*texImage->FetchTexelf)(texImage, col, row, img,
+ depthRow + col);
+ }
+ _mesa_pack_depth_span(ctx, width, dest, type,
+ depthRow, &ctx->Pack);
+ }
+ else if (format == GL_DEPTH_STENCIL_EXT) {
+ /* XXX Note: we're bypassing texImage->FetchTexel()! */
+ const GLuint *src = (const GLuint *) texImage->Data;
+ src += width * row + width * height * img;
+ _mesa_memcpy(dest, src, width * sizeof(GLuint));
+ if (ctx->Pack.SwapBytes) {
+ _mesa_swap4((GLuint *) dest, width);
+ }
+ }
+ else if (format == GL_YCBCR_MESA) {
+ /* No pixel transfer */
+ const GLint rowstride = texImage->RowStride;
+ MEMCPY(dest,
+ (const GLushort *) texImage->Data + row * rowstride,
+ width * sizeof(GLushort));
+ /* check for byte swapping */
+ if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
+ && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
+ (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
+ && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
+ if (!ctx->Pack.SwapBytes)
+ _mesa_swap2((GLushort *) dest, width);
+ }
+ else if (ctx->Pack.SwapBytes) {
+ _mesa_swap2((GLushort *) dest, width);
+ }
+ }
+#if FEATURE_EXT_texture_sRGB
+ else if (is_srgb_teximage(texImage)) {
+ /* special case this since need to backconvert values */
+ /* convert row to RGBA format */
+ GLfloat rgba[MAX_WIDTH][4];
+ GLint col;
+ GLbitfield transferOps = 0x0;
+
+ for (col = 0; col < width; col++) {
+ (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
+ if (texImage->_BaseFormat == GL_LUMINANCE) {
+ rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
+ rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_RGB ||
+ texImage->_BaseFormat == GL_RGBA) {
+ rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+ rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
+ rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
+ }
+ }
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
+ format, type, dest,
+ &ctx->Pack, transferOps);
+ }
+#endif /* FEATURE_EXT_texture_sRGB */
+ else {
+ /* general case: convert row to RGBA format */
+ GLfloat rgba[MAX_WIDTH][4];
+ GLint col;
+ GLbitfield transferOps = 0x0;
+
+ /* clamp does not apply to GetTexImage (final conversion)?
+ * Looks like we need clamp though when going from format
+ * containing negative values to unsigned format.
+ */
+ if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA)
+ transferOps |= IMAGE_CLAMP_BIT;
+ else if (!type_with_negative_values(type) &&
+ (texImage->TexFormat->DataType == GL_FLOAT ||
+ texImage->TexFormat->DataType == GL_SIGNED_NORMALIZED))
+ transferOps |= IMAGE_CLAMP_BIT;
+
+ for (col = 0; col < width; col++) {
+ (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
+ if (texImage->_BaseFormat == GL_ALPHA) {
+ rgba[col][RCOMP] = 0.0;
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE) {
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ rgba[col][ACOMP] = 1.0;
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_INTENSITY) {
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ rgba[col][ACOMP] = 1.0;
+ }
+ }
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
+ format, type, dest,
+ &ctx->Pack, transferOps);
+ } /* format */
+ } /* row */
+ } /* img */
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+}
+
+
+
+/**
+ * This is the software fallback for Driver.GetCompressedTexImage().
+ * All error checking will have been done before this routine is called.
+ */
+void
+_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *img,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ GLuint size;
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* pack texture image into a PBO */
+ GLubyte *buf;
+ if ((const GLubyte *) img + texImage->CompressedSize >
+ (const GLubyte *) ctx->Pack.BufferObj->Size) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(invalid PBO access)");
+ return;
+ }
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB,
+ ctx->Pack.BufferObj);
+ if (!buf) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(PBO is mapped)");
+ return;
+ }
+ img = ADD_POINTERS(buf, img);
+ }
+ else if (!img) {
+ /* not an error */
+ return;
+ }
+
+ /* don't use texImage->CompressedSize since that may be padded out */
+ size = _mesa_compressed_texture_size(ctx, texImage->Width, texImage->Height,
+ texImage->Depth,
+ texImage->TexFormat->MesaFormat);
+
+ /* just memcpy, no pixelstore or pixel transfer */
+ _mesa_memcpy(img, texImage->Data, size);
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+}
+
+
+
+/**
+ * Do error checking for a glGetTexImage() call.
+ * \return GL_TRUE if any error, GL_FALSE if no errors.
+ */
+static GLboolean
+getteximage_error_check(GLcontext *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels )
+{
+ const struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ const GLuint maxLevels = _mesa_max_texture_levels(ctx, target);
+
+ if (maxLevels == 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
+ return GL_TRUE;
+ }
+
+ if (level < 0 || level >= maxLevels) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
+ return GL_TRUE;
+ }
+
+ if (_mesa_sizeof_packed_type(type) <= 0) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
+ return GL_TRUE;
+ }
+
+ if (_mesa_components_in_format(format) <= 0 ||
+ format == GL_STENCIL_INDEX) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.EXT_packed_depth_stencil
+ && _mesa_is_depthstencil_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap
+ && _mesa_is_dudv_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ if (!texObj || _mesa_is_proxy_texture(target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
+ return GL_TRUE;
+ }
+
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ /* out of memory */
+ return GL_TRUE;
+ }
+
+ /* Make sure the requested image format is compatible with the
+ * texture's format. Note that a color index texture can be converted
+ * to RGBA so that combo is allowed.
+ */
+ if (_mesa_is_color_format(format)
+ && !_mesa_is_color_format(texImage->TexFormat->BaseFormat)
+ && !_mesa_is_index_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_index_format(format)
+ && !_mesa_is_index_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_depth_format(format)
+ && !_mesa_is_depth_format(texImage->TexFormat->BaseFormat)
+ && !_mesa_is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_ycbcr_format(format)
+ && !_mesa_is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_depthstencil_format(format)
+ && !_mesa_is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_dudv_format(format)
+ && !_mesa_is_dudv_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* packing texture image into a PBO */
+ const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
+ if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
+ texImage->Height, texImage->Depth,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexImage(invalid PBO access)");
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+
+
+/**
+ * Get texture image. Called by glGetTexImage.
+ *
+ * \param target texture target.
+ * \param level image level.
+ * \param format pixel data format for returned image.
+ * \param type pixel data type for returned image.
+ * \param pixels returned pixel data.
+ */
+void GLAPIENTRY
+_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
+ GLenum type, GLvoid *pixels )
+{
+ const struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (getteximage_error_check(ctx, target, level, format, type, pixels)) {
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, texObj, target, level);
+
+ /* typically, this will call _mesa_get_teximage() */
+ ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
+ texObj, texImage);
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void GLAPIENTRY
+_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
+{
+ const struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLint maxLevels;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
+ return;
+ }
+
+ maxLevels = _mesa_max_texture_levels(ctx, target);
+ ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
+
+ if (level < 0 || level >= maxLevels) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
+ return;
+ }
+
+ if (_mesa_is_proxy_texture(target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
+ return;
+ }
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (texImage) {
+ if (texImage->IsCompressed) {
+ /* this typically calls _mesa_get_compressed_teximage() */
+ ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
+ texObj, texImage);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImageARB");
+ }
+ }
+ else {
+ /* probably invalid mipmap level */
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetCompressedTexImageARB(level)");
+ }
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
diff --git a/src/mesa/main/texgetimage.h b/src/mesa/main/texgetimage.h
new file mode 100644
index 0000000000..088d27c7e1
--- /dev/null
+++ b/src/mesa/main/texgetimage.h
@@ -0,0 +1,55 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * 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 TEXGETIMAGE_H
+#define TEXGETIMAGE_H
+
+
+extern void
+_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *img,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+
+extern void GLAPIENTRY
+_mesa_GetTexImage( GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img);
+
+
+#endif /* TEXGETIMAGE_H */
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 9e968ba743..a0304c02d4 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -1,8 +1,9 @@
/*
* mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.6
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -32,11 +33,10 @@
#include "glheader.h"
#include "bufferobj.h"
#include "context.h"
-#if FEATURE_convolve
#include "convolve.h"
-#endif
#include "fbobject.h"
#include "framebuffer.h"
+#include "hash.h"
#include "image.h"
#include "imports.h"
#include "macros.h"
@@ -50,6 +50,17 @@
/**
+ * State changes which we care about for glCopyTex[Sub]Image() calls.
+ * In particular, we care about pixel transfer state and buffer state
+ * (such as glReadBuffer to make sure we read from the right renderbuffer).
+ */
+#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
+ _NEW_BUFFERS | \
+ _NEW_PIXEL)
+
+
+
+/**
* We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
* elsewhere.
*/
@@ -169,6 +180,8 @@ logbase2( int n )
*
* This is the format which is used during texture application (i.e. the
* texture format and env mode determine the arithmetic used.
+ *
+ * XXX this could be static
*/
GLint
_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
@@ -253,23 +266,21 @@ _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
}
}
- if (ctx->Extensions.ARB_texture_compression) {
- switch (internalFormat) {
- case GL_COMPRESSED_ALPHA:
- return GL_ALPHA;
- case GL_COMPRESSED_LUMINANCE:
- return GL_LUMINANCE;
- case GL_COMPRESSED_LUMINANCE_ALPHA:
- return GL_LUMINANCE_ALPHA;
- case GL_COMPRESSED_INTENSITY:
- return GL_INTENSITY;
- case GL_COMPRESSED_RGB:
- return GL_RGB;
- case GL_COMPRESSED_RGBA:
- return GL_RGBA;
- default:
- ; /* fallthrough */
- }
+ switch (internalFormat) {
+ case GL_COMPRESSED_ALPHA:
+ return GL_ALPHA;
+ case GL_COMPRESSED_LUMINANCE:
+ return GL_LUMINANCE;
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ return GL_LUMINANCE_ALPHA;
+ case GL_COMPRESSED_INTENSITY:
+ return GL_INTENSITY;
+ case GL_COMPRESSED_RGB:
+ return GL_RGB;
+ case GL_COMPRESSED_RGBA:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
}
if (ctx->Extensions.TDFX_texture_compression_FXT1) {
@@ -339,6 +350,26 @@ _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
}
}
+ if (ctx->Extensions.ATI_envmap_bumpmap) {
+ switch (internalFormat) {
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return GL_DUDV_ATI;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.MESA_texture_signed_rgba) {
+ switch (internalFormat) {
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
if (ctx->Extensions.EXT_packed_depth_stencil) {
switch (internalFormat) {
case GL_DEPTH_STENCIL_EXT:
@@ -384,193 +415,6 @@ _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
/**
- * Test if the given image format is a color/RGBA format (i.e., not color
- * index, depth, stencil, etc).
- * \param format the image format value (may by an internal texture format)
- * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
- * XXX maybe move this func to image.c
- */
-GLboolean
-_mesa_is_color_format(GLenum format)
-{
- switch (format) {
- case GL_RED:
- case GL_GREEN:
- case GL_BLUE:
- case GL_ALPHA:
- case GL_ALPHA4:
- case GL_ALPHA8:
- case GL_ALPHA12:
- case GL_ALPHA16:
- case 1:
- case GL_LUMINANCE:
- case GL_LUMINANCE4:
- case GL_LUMINANCE8:
- case GL_LUMINANCE12:
- case GL_LUMINANCE16:
- case 2:
- 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:
- case GL_INTENSITY:
- case GL_INTENSITY4:
- case GL_INTENSITY8:
- case GL_INTENSITY12:
- case GL_INTENSITY16:
- case 3:
- case GL_RGB:
- case GL_BGR:
- case GL_R3_G3_B2:
- case GL_RGB4:
- case GL_RGB5:
- case GL_RGB8:
- case GL_RGB10:
- case GL_RGB12:
- case GL_RGB16:
- case 4:
- case GL_ABGR_EXT:
- case GL_RGBA:
- case GL_BGRA:
- case GL_RGBA2:
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGBA8:
- case GL_RGB10_A2:
- case GL_RGBA12:
- case GL_RGBA16:
- /* float texture formats */
- case GL_ALPHA16F_ARB:
- case GL_ALPHA32F_ARB:
- case GL_LUMINANCE16F_ARB:
- case GL_LUMINANCE32F_ARB:
- case GL_LUMINANCE_ALPHA16F_ARB:
- case GL_LUMINANCE_ALPHA32F_ARB:
- case GL_INTENSITY16F_ARB:
- case GL_INTENSITY32F_ARB:
- case GL_RGB16F_ARB:
- case GL_RGB32F_ARB:
- case GL_RGBA16F_ARB:
- case GL_RGBA32F_ARB:
- /* compressed formats */
- case GL_COMPRESSED_ALPHA:
- case GL_COMPRESSED_LUMINANCE:
- case GL_COMPRESSED_LUMINANCE_ALPHA:
- case GL_COMPRESSED_INTENSITY:
- case GL_COMPRESSED_RGB:
- case GL_COMPRESSED_RGBA:
- case GL_RGB_S3TC:
- case GL_RGB4_S3TC:
- case GL_RGBA_S3TC:
- case GL_RGBA4_S3TC:
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- case GL_COMPRESSED_RGB_FXT1_3DFX:
- case GL_COMPRESSED_RGBA_FXT1_3DFX:
-#if FEATURE_EXT_texture_sRGB
- case GL_SRGB_EXT:
- case GL_SRGB8_EXT:
- case GL_SRGB_ALPHA_EXT:
- case GL_SRGB8_ALPHA8_EXT:
- case GL_SLUMINANCE_ALPHA_EXT:
- case GL_SLUMINANCE8_ALPHA8_EXT:
- case GL_SLUMINANCE_EXT:
- case GL_SLUMINANCE8_EXT:
- case GL_COMPRESSED_SRGB_EXT:
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- case GL_COMPRESSED_SLUMINANCE_EXT:
- case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
-#endif /* FEATURE_EXT_texture_sRGB */
- return GL_TRUE;
- case GL_YCBCR_MESA: /* not considered to be RGB */
- /* fall-through */
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a color index format.
- */
-static GLboolean
-is_index_format(GLenum format)
-{
- switch (format) {
- case GL_COLOR_INDEX:
- case GL_COLOR_INDEX1_EXT:
- case GL_COLOR_INDEX2_EXT:
- case GL_COLOR_INDEX4_EXT:
- case GL_COLOR_INDEX8_EXT:
- case GL_COLOR_INDEX12_EXT:
- case GL_COLOR_INDEX16_EXT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a depth component format.
- */
-static GLboolean
-is_depth_format(GLenum format)
-{
- switch (format) {
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
- case GL_DEPTH_COMPONENT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a YCbCr format.
- */
-static GLboolean
-is_ycbcr_format(GLenum format)
-{
- switch (format) {
- case GL_YCBCR_MESA:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Test if the given image format is a Depth/Stencil format.
- */
-static GLboolean
-is_depthstencil_format(GLenum format)
-{
- switch (format) {
- case GL_DEPTH24_STENCIL8_EXT:
- case GL_DEPTH_STENCIL_EXT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-
-/**
* Test if it is a supported compressed format.
*
* \param internalFormat the internal format token provided by the user.
@@ -630,37 +474,14 @@ _mesa_set_tex_image(struct gl_texture_object *tObj,
GLenum target, GLint level,
struct gl_texture_image *texImage)
{
+ const GLuint face = _mesa_tex_target_to_face(target);
+
ASSERT(tObj);
ASSERT(texImage);
- /* XXX simplify this with _mesa_tex_target_to_face() */
- switch (target) {
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- case GL_TEXTURE_1D_ARRAY_EXT:
- case GL_TEXTURE_2D_ARRAY_EXT:
- tObj->Image[0][level] = texImage;
- break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
- {
- GLuint face = ((GLuint) target -
- (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
- tObj->Image[face][level] = texImage;
- }
- break;
- case GL_TEXTURE_RECTANGLE_NV:
- ASSERT(level == 0);
- tObj->Image[0][level] = texImage;
- break;
- default:
- _mesa_problem(NULL, "bad target in _mesa_set_tex_image()");
- return;
- }
+ ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0);
+
+ tObj->Image[face][level] = texImage;
+
/* Set the 'back' pointer */
texImage->TexObject = tObj;
}
@@ -687,7 +508,7 @@ _mesa_new_texture_image( GLcontext *ctx )
* Free texture image data.
* This function is a fallback called via ctx->Driver.FreeTexImageData().
*
- * \param teximage texture image.
+ * \param texImage texture image.
*
* Free the texture image data if it's not marked as client data.
*/
@@ -709,7 +530,7 @@ _mesa_free_texture_image_data(GLcontext *ctx,
/**
* Free texture image.
*
- * \param teximage texture image.
+ * \param texImage texture image.
*
* Free the texture image structure and the associated image data.
*/
@@ -739,6 +560,9 @@ _mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
GLboolean
_mesa_is_proxy_texture(GLenum target)
{
+ /* NUM_TEXTURE_TARGETS should match number of terms below */
+ assert(NUM_TEXTURE_TARGETS == 7);
+
return (target == GL_PROXY_TEXTURE_1D ||
target == GL_PROXY_TEXTURE_2D ||
target == GL_PROXY_TEXTURE_3D ||
@@ -766,15 +590,15 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
{
switch (target) {
case GL_TEXTURE_1D:
- return texUnit->Current1D;
+ return texUnit->CurrentTex[TEXTURE_1D_INDEX];
case GL_PROXY_TEXTURE_1D:
return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
case GL_TEXTURE_2D:
- return texUnit->Current2D;
+ return texUnit->CurrentTex[TEXTURE_2D_INDEX];
case GL_PROXY_TEXTURE_2D:
return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
case GL_TEXTURE_3D:
- return texUnit->Current3D;
+ return texUnit->CurrentTex[TEXTURE_3D_INDEX];
case GL_PROXY_TEXTURE_3D:
return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
@@ -785,25 +609,25 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_ARB:
return ctx->Extensions.ARB_texture_cube_map
- ? texUnit->CurrentCubeMap : NULL;
+ ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
return ctx->Extensions.ARB_texture_cube_map
? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
case GL_TEXTURE_RECTANGLE_NV:
return ctx->Extensions.NV_texture_rectangle
- ? texUnit->CurrentRect : NULL;
+ ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
case GL_PROXY_TEXTURE_RECTANGLE_NV:
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->Current1DArray : NULL;
+ ? 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;
case GL_TEXTURE_2D_ARRAY_EXT:
return ctx->Extensions.MESA_texture_array
- ? texUnit->Current2DArray : NULL;
+ ? 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;
@@ -815,74 +639,28 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
/**
- * Get the texture image struct which corresponds to target and level
- * of the given texture unit.
+ * Get a texture image pointer from a texture object, given a texture
+ * target and mipmap level. The target and level parameters should
+ * have already been error-checked.
*
* \param ctx GL context.
- * \param texUnit texture unit.
+ * \param texObj texture unit.
* \param target texture target.
* \param level image level.
*
- * \return pointer to the texture image structure on success, or NULL on failure.
- *
- * \sa gl_texture_unit.
+ * \return pointer to the texture image structure, or NULL on failure.
*/
struct gl_texture_image *
_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
GLenum target, GLint level)
{
- ASSERT(texObj);
-
- if (level < 0 || level >= MAX_TEXTURE_LEVELS)
- return NULL;
-
- /* XXX simplify this with _mesa_tex_target_to_face() */
- switch (target) {
- case GL_TEXTURE_1D:
- case GL_PROXY_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_PROXY_TEXTURE_2D:
- case GL_TEXTURE_3D:
- case GL_PROXY_TEXTURE_3D:
- return texObj->Image[0][level];
-
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
- if (ctx->Extensions.ARB_texture_cube_map) {
- GLuint face = ((GLuint) target -
- (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
- return texObj->Image[face][level];
- }
- else
- return NULL;
-
- case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
- if (ctx->Extensions.ARB_texture_cube_map)
- return texObj->Image[0][level];
- else
- return NULL;
-
- case GL_TEXTURE_RECTANGLE_NV:
- case GL_PROXY_TEXTURE_RECTANGLE_NV:
- if (ctx->Extensions.NV_texture_rectangle && level == 0)
- return texObj->Image[0][level];
- else
- return NULL;
+ const GLuint face = _mesa_tex_target_to_face(target);
- case GL_TEXTURE_1D_ARRAY_EXT:
- 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)
- ? texObj->Image[0][level] : NULL;
+ ASSERT(texObj);
+ ASSERT(level >= 0);
+ ASSERT(level < MAX_TEXTURE_LEVELS);
- default:
- return NULL;
- }
+ return texObj->Image[face][level];
}
@@ -925,6 +703,7 @@ struct gl_texture_image *
_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
{
struct gl_texture_image *texImage;
+ GLuint texIndex;
if (level < 0 )
return NULL;
@@ -933,111 +712,54 @@ _mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
case GL_PROXY_TEXTURE_1D:
if (level >= ctx->Const.MaxTextureLevels)
return NULL;
- texImage = ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]->Image[0][level];
- if (!texImage) {
- texImage = ctx->Driver.NewTextureImage(ctx);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
- return NULL;
- }
- ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]->Image[0][level] = texImage;
- /* Set the 'back' pointer */
- texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
- }
- return texImage;
+ texIndex = TEXTURE_1D_INDEX;
+ break;
case GL_PROXY_TEXTURE_2D:
if (level >= ctx->Const.MaxTextureLevels)
return NULL;
- texImage = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]->Image[0][level];
- if (!texImage) {
- texImage = ctx->Driver.NewTextureImage(ctx);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
- return NULL;
- }
- ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]->Image[0][level] = texImage;
- /* Set the 'back' pointer */
- texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
- }
- return texImage;
+ texIndex = TEXTURE_2D_INDEX;
+ break;
case GL_PROXY_TEXTURE_3D:
if (level >= ctx->Const.Max3DTextureLevels)
return NULL;
- texImage = ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]->Image[0][level];
- if (!texImage) {
- texImage = ctx->Driver.NewTextureImage(ctx);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
- return NULL;
- }
- ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]->Image[0][level] = texImage;
- /* Set the 'back' pointer */
- texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
- }
- return texImage;
+ texIndex = TEXTURE_3D_INDEX;
+ break;
case GL_PROXY_TEXTURE_CUBE_MAP:
if (level >= ctx->Const.MaxCubeTextureLevels)
return NULL;
- texImage = ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]->Image[0][level];
- if (!texImage) {
- texImage = ctx->Driver.NewTextureImage(ctx);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
- return NULL;
- }
- ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]->Image[0][level] = texImage;
- /* Set the 'back' pointer */
- texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX];
- }
- return texImage;
+ texIndex = TEXTURE_CUBE_INDEX;
+ break;
case GL_PROXY_TEXTURE_RECTANGLE_NV:
if (level > 0)
return NULL;
- texImage = ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]->Image[0][level];
- if (!texImage) {
- texImage = ctx->Driver.NewTextureImage(ctx);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
- return NULL;
- }
- ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]->Image[0][level] = texImage;
- /* Set the 'back' pointer */
- texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX];
- }
- return texImage;
+ texIndex = TEXTURE_RECT_INDEX;
+ break;
case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
if (level >= ctx->Const.MaxTextureLevels)
return NULL;
- texImage = ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]->Image[0][level];
- if (!texImage) {
- texImage = ctx->Driver.NewTextureImage(ctx);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
- return NULL;
- }
- ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]->Image[0][level] = texImage;
- /* Set the 'back' pointer */
- texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX];
- }
- return texImage;
+ texIndex = TEXTURE_1D_ARRAY_INDEX;
+ break;
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
if (level >= ctx->Const.MaxTextureLevels)
return NULL;
- texImage = ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]->Image[0][level];
- if (!texImage) {
- texImage = ctx->Driver.NewTextureImage(ctx);
- if (!texImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
- return NULL;
- }
- ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]->Image[0][level] = texImage;
- /* Set the 'back' pointer */
- texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX];
- }
- return texImage;
+ texIndex = TEXTURE_2D_ARRAY_INDEX;
+ break;
default:
return NULL;
}
+
+ texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
+ if (!texImage) {
+ texImage = ctx->Driver.NewTextureImage(ctx);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
+ return NULL;
+ }
+ ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
+ /* Set the 'back' pointer */
+ texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
+ }
+ return texImage;
}
@@ -1060,10 +782,6 @@ _mesa_max_texture_levels(GLcontext *ctx, GLenum target)
case GL_PROXY_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
- case GL_TEXTURE_1D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- case GL_TEXTURE_2D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
return ctx->Const.MaxTextureLevels;
case GL_TEXTURE_3D:
case GL_PROXY_TEXTURE_3D:
@@ -1076,10 +794,17 @@ _mesa_max_texture_levels(GLcontext *ctx, GLenum target)
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_ARB:
case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
- return ctx->Const.MaxCubeTextureLevels;
+ return ctx->Extensions.ARB_texture_cube_map
+ ? ctx->Const.MaxCubeTextureLevels : 0;
case GL_TEXTURE_RECTANGLE_NV:
case GL_PROXY_TEXTURE_RECTANGLE_NV:
- return 1;
+ return ctx->Extensions.NV_texture_rectangle ? 1 : 0;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ 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
+ ? ctx->Const.MaxTextureLevels : 0;
default:
return 0; /* bad target */
}
@@ -1217,19 +942,30 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
img->Width = width;
img->Height = height;
img->Depth = depth;
+
img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */
- img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
- img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
img->WidthLog2 = logbase2(img->Width2);
- if (height == 1) /* 1-D texture */
+
+ if (height == 1) { /* 1-D texture */
+ img->Height2 = 1;
img->HeightLog2 = 0;
- else
+ }
+ else {
+ img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
img->HeightLog2 = logbase2(img->Height2);
- if (depth == 1) /* 2-D texture */
+ }
+
+ if (depth == 1) { /* 2-D texture */
+ img->Depth2 = 1;
img->DepthLog2 = 0;
- else
+ }
+ else {
+ img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
img->DepthLog2 = logbase2(img->Depth2);
+ }
+
img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
+
img->IsCompressed = GL_FALSE;
img->CompressedSize = 0;
@@ -1246,6 +982,8 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
* We allocate the array for 1D/2D textures too in order to avoid special-
* case code in the texstore routines.
*/
+ if (img->ImageOffsets)
+ _mesa_free(img->ImageOffsets);
img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint));
for (i = 0; i < depth; i++) {
img->ImageOffsets[i] = i * width * height;
@@ -1267,6 +1005,23 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
/**
+ * Free and clear fields of the gl_texture_image struct.
+ *
+ * \param ctx GL context.
+ * \param texImage texture image structure to be cleared.
+ *
+ * After the call, \p texImage will have no data associated with it. Its
+ * fields are cleared so that its parent object will test incomplete.
+ */
+void
+_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage)
+{
+ ctx->Driver.FreeTexImageData(ctx, texImage);
+ clear_teximage_fields(texImage);
+}
+
+
+/**
* This is the fallback for Driver.TestProxyTexImage(). Test the texture
* level, width, height and depth against the ctx->Const limits for textures.
*
@@ -1572,22 +1327,25 @@ texture_error_check( GLcontext *ctx, GLenum target,
*/
if (!isProxy) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glTexImage%dD(format or type)", dimensions);
+ "glTexImage%dD(incompatible format 0x%x, type 0x%x)",
+ dimensions, format, type);
}
return GL_TRUE;
}
/* make sure internal format and format basically agree */
colorFormat = _mesa_is_color_format(format);
- indexFormat = is_index_format(format);
+ indexFormat = _mesa_is_index_format(format);
if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
- (is_index_format(internalFormat) && !indexFormat) ||
- (is_depth_format(internalFormat) != is_depth_format(format)) ||
- (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
- (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) {
+ (_mesa_is_index_format(internalFormat) && !indexFormat) ||
+ (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) ||
+ (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) ||
+ (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) ||
+ (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) {
if (!isProxy)
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glTexImage(internalFormat/format)");
+ "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)",
+ dimensions, internalFormat, format);
return GL_TRUE;
}
@@ -1761,7 +1519,8 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glTexSubImage%dD(format or type)", dimensions);
+ "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)",
+ dimensions, format, type);
return GL_TRUE;
}
@@ -1868,7 +1627,6 @@ subtexture_error_check2( GLcontext *ctx, GLuint dimensions,
* \param internalFormat internal format given by the user.
* \param width image width given by the user.
* \param height image height given by the user.
- * \param depth image depth given by the user.
* \param border texture border.
*
* \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
@@ -1917,14 +1675,14 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
return GL_TRUE;
}
- /* NOTE: the format and type aren't really significant for
- * TestProxyTexImage(). Only the internalformat really matters.
if (!_mesa_source_buffer_exists(ctx, format)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyTexImage%dD(missing readbuffer)", dimensions);
return GL_TRUE;
}
+ /* NOTE: the format and type aren't really significant for
+ * TestProxyTexImage(). Only the internalformat really matters.
*/
type = GL_FLOAT;
@@ -2018,7 +1776,7 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
return GL_TRUE;
}
}
- else if (is_depth_format(internalFormat)) {
+ else if (_mesa_is_depth_format(internalFormat)) {
/* make sure we have depth/stencil buffers */
if (!ctx->ReadBuffer->_DepthBuffer) {
_mesa_error(ctx, GL_INVALID_OPERATION,
@@ -2026,7 +1784,7 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
return GL_TRUE;
}
}
- else if (is_depthstencil_format(internalFormat)) {
+ else if (_mesa_is_depthstencil_format(internalFormat)) {
/* make sure we have depth/stencil buffers */
if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
_mesa_error(ctx, GL_INVALID_OPERATION,
@@ -2224,7 +1982,8 @@ copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyTexSubImage%dD(missing readbuffer)", dimensions);
+ "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)",
+ dimensions, teximage->_BaseFormat);
return GL_TRUE;
}
@@ -2250,153 +2009,33 @@ copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
}
-/**
- * Get texture image. Called by glGetTexImage.
- *
- * \param target texture target.
- * \param level image level.
- * \param format pixel data format for returned image.
- * \param type pixel data type for returned image.
- * \param pixels returned pixel data.
- */
-void GLAPIENTRY
-_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
- GLenum type, GLvoid *pixels )
+/** Callback info for walking over FBO hash table */
+struct cb_info
{
- const struct gl_texture_unit *texUnit;
+ GLcontext *ctx;
struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GLint maxLevels = 0;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
- texObj = _mesa_select_tex_object(ctx, texUnit, target);
- if (!texObj || _mesa_is_proxy_texture(target)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
- return;
- }
-
- maxLevels = _mesa_max_texture_levels(ctx, target);
- ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
-
- if (level < 0 || level >= maxLevels) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
- return;
- }
-
- if (_mesa_sizeof_packed_type(type) <= 0) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
- return;
- }
-
- if (_mesa_components_in_format(format) <= 0 ||
- format == GL_STENCIL_INDEX) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
- return;
- }
-
- if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return;
- }
-
- if (!ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return;
- }
-
- if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return;
- }
-
- if (!ctx->Extensions.EXT_packed_depth_stencil
- && is_depthstencil_format(format)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
- return;
- }
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- if (!texImage) {
- /* invalid mipmap level, not an error */
- goto out;
- }
-
-
- /* Make sure the requested image format is compatible with the
- * texture's format. Note that a color index texture can be converted
- * to RGBA so that combo is allowed.
- */
- if (_mesa_is_color_format(format)
- && !_mesa_is_color_format(texImage->TexFormat->BaseFormat)
- && !is_index_format(texImage->TexFormat->BaseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- goto out;
- }
- else if (is_index_format(format)
- && !is_index_format(texImage->TexFormat->BaseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- goto out;
- }
- else if (is_depth_format(format)
- && !is_depth_format(texImage->TexFormat->BaseFormat)
- && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- goto out;
- }
- else if (is_ycbcr_format(format)
- && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- goto out;
- }
- else if (is_depthstencil_format(format)
- && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
- goto out;
- }
-
- if (ctx->Pack.BufferObj->Name) {
- /* packing texture image into a PBO */
- const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
- if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
- texImage->Height, texImage->Depth,
- format, type, pixels)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetTexImage(invalid PBO access)");
- goto out;
- }
- }
-
- /* typically, this will call _mesa_get_teximage() */
- ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
- texObj, texImage);
-
- }
- out:
- _mesa_unlock_texture(ctx, texObj);
-}
-
+ GLuint level, face;
+};
/**
- * Check if the given texture image is bound to any framebuffer objects
- * and update/invalidate them.
- * XXX We're only checking the currently bound framebuffer object for now.
- * In the future, perhaps struct gl_texture_image should have a pointer (or
- * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
+ * Check render to texture callback. Called from _mesa_HashWalk().
*/
static void
-update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
- GLuint face, GLuint level)
+check_rtt_cb(GLuint key, void *data, void *userData)
{
- if (ctx->DrawBuffer->Name) {
+ struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
+ const struct cb_info *info = (struct cb_info *) userData;
+ GLcontext *ctx = info->ctx;
+ const struct gl_texture_object *texObj = info->texObj;
+ const GLuint level = info->level, face = info->face;
+
+ /* If this is a user-created FBO */
+ if (fb->Name) {
GLuint i;
+ /* check if any of the FBO's attachments point to 'texObj' */
for (i = 0; i < BUFFER_COUNT; i++) {
- struct gl_renderbuffer_attachment *att =
- ctx->DrawBuffer->Attachment + i;
+ struct gl_renderbuffer_attachment *att = fb->Attachment + i;
if (att->Type == GL_TEXTURE &&
att->Texture == texObj &&
att->TextureLevel == level &&
@@ -2404,12 +2043,79 @@ update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
/* Tell driver about the new renderbuffer texture */
ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
+ /* Mark fb status as indeterminate to force re-validation */
+ fb->_Status = 0;
}
}
}
}
+/**
+ * When a texture image is specified we have to check if it's bound to
+ * any framebuffer objects (render to texture) in order to detect changes
+ * in size or format since that effects FBO completeness.
+ * Any FBOs rendering into the texture must be re-validated.
+ */
+static void
+update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
+ GLuint face, GLuint level)
+{
+ /* Only check this texture if it's been marked as RenderToTexture */
+ if (texObj->_RenderToTexture) {
+ struct cb_info info;
+ info.ctx = ctx;
+ info.texObj = texObj;
+ info.level = level;
+ info.face = face;
+ _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info);
+ }
+}
+
+
+/** Debug helper: override the user-requested internal format */
+static GLenum
+override_internal_format(GLenum internalFormat, GLint width, GLint height)
+{
+#if 0
+ if (internalFormat == GL_RGBA16F_ARB ||
+ internalFormat == GL_RGBA32F_ARB) {
+ printf("Convert rgba float tex to int %d x %d\n", width, height);
+ return GL_RGBA;
+ }
+ else if (internalFormat == GL_RGB16F_ARB ||
+ internalFormat == GL_RGB32F_ARB) {
+ printf("Convert rgb float tex to int %d x %d\n", width, height);
+ return GL_RGB;
+ }
+ else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
+ internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
+ printf("Convert luminance float tex to int %d x %d\n", width, height);
+ return GL_LUMINANCE_ALPHA;
+ }
+ else if (internalFormat == GL_LUMINANCE16F_ARB ||
+ internalFormat == GL_LUMINANCE32F_ARB) {
+ printf("Convert luminance float tex to int %d x %d\n", width, height);
+ return GL_LUMINANCE;
+ }
+ else if (internalFormat == GL_ALPHA16F_ARB ||
+ internalFormat == GL_ALPHA32F_ARB) {
+ printf("Convert luminance float tex to int %d x %d\n", width, height);
+ return GL_ALPHA;
+ }
+ /*
+ else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
+ internalFormat = GL_RGBA;
+ }
+ */
+ else {
+ return internalFormat;
+ }
+#else
+ return internalFormat;
+#endif
+}
+
/*
* Called from the API. Note that width includes the border.
@@ -2423,11 +2129,11 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-#if FEATURE_convolve
+ internalFormat = override_internal_format(internalFormat, width, 1);
+
if (_mesa_is_color_format(internalFormat)) {
_mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
}
-#endif
if (target == GL_TEXTURE_1D) {
/* non-proxy target */
@@ -2441,10 +2147,10 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
return; /* error was recorded */
}
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
_mesa_update_state(ctx);
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -2520,12 +2226,12 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-#if FEATURE_convolve
+ internalFormat = override_internal_format(internalFormat, width, height);
+
if (_mesa_is_color_format(internalFormat)) {
_mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
&postConvHeight);
}
-#endif
if (target == GL_TEXTURE_2D ||
(ctx->Extensions.ARB_texture_cube_map &&
@@ -2547,10 +2253,10 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
return; /* error was recorded */
}
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
_mesa_update_state(ctx);
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -2603,7 +2309,7 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1, border)) {
/* when error, clear all proxy texture image parameters */
if (texImage)
- clear_teximage_fields(ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]->Image[0][level]);
+ clear_teximage_fields(texImage);
}
else {
/* no error, set the tex image parameters */
@@ -2634,6 +2340,8 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ internalFormat = override_internal_format(internalFormat, width, height);
+
if (target == GL_TEXTURE_3D ||
(ctx->Extensions.MESA_texture_array &&
target == GL_TEXTURE_2D_ARRAY_EXT)) {
@@ -2648,10 +2356,10 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
return; /* error was recorded */
}
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
_mesa_update_state(ctx);
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -2741,15 +2449,13 @@ _mesa_TexSubImage1D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
_mesa_update_state(ctx);
-#if FEATURE_convolve
/* XXX should test internal format */
if (_mesa_is_color_format(format)) {
_mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
}
-#endif
if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
postConvWidth, 1, 1, format, type)) {
@@ -2757,7 +2463,7 @@ _mesa_TexSubImage1D( GLenum target, GLint level,
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
assert(texObj);
@@ -2801,23 +2507,21 @@ _mesa_TexSubImage2D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
_mesa_update_state(ctx);
-#if FEATURE_convolve
/* XXX should test internal format */
if (_mesa_is_color_format(format)) {
_mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
&postConvHeight);
}
-#endif
if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
postConvWidth, postConvHeight, 1, format, type)) {
return; /* error was detected */
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -2861,7 +2565,7 @@ _mesa_TexSubImage3D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
_mesa_update_state(ctx);
if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
@@ -2869,7 +2573,7 @@ _mesa_TexSubImage3D( GLenum target, GLint level,
return; /* error was detected */
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
@@ -2917,20 +2621,18 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
-#if FEATURE_convolve
if (_mesa_is_color_format(internalFormat)) {
_mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
}
-#endif
if (copytexture_error_check(ctx, 1, target, level, internalFormat,
postConvWidth, 1, border))
return;
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -2982,21 +2684,19 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
-#if FEATURE_convolve
if (_mesa_is_color_format(internalFormat)) {
_mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
&postConvHeight);
}
-#endif
if (copytexture_error_check(ctx, 2, target, level, internalFormat,
postConvWidth, postConvHeight, border))
return;
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
@@ -3050,24 +2750,22 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
if (copytexsubimage_error_check1(ctx, 1, target, level))
return;
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-#if FEATURE_convolve
if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
_mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
}
-#endif
if (copytexsubimage_error_check2(ctx, 1, target, level,
xoffset, 0, 0, postConvWidth, 1,
@@ -3105,25 +2803,23 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
if (copytexsubimage_error_check1(ctx, 2, target, level))
return;
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-#if FEATURE_convolve
if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
_mesa_adjust_image_for_convolution(ctx, 2,
&postConvWidth, &postConvHeight);
}
-#endif
if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
postConvWidth, postConvHeight, texImage))
@@ -3160,25 +2856,23 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
if (copytexsubimage_error_check1(ctx, 3, target, level))
return;
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-#if FEATURE_convolve
if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
_mesa_adjust_image_for_convolution(ctx, 2,
&postConvWidth, &postConvHeight);
}
-#endif
if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
zoffset, postConvWidth, postConvHeight,
@@ -3420,7 +3114,7 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
@@ -3474,7 +3168,7 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
@@ -3517,7 +3211,7 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
@@ -3573,7 +3267,7 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
@@ -3613,7 +3307,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -3667,7 +3361,7 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -3706,7 +3400,7 @@ _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -3763,7 +3457,7 @@ _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -3820,7 +3514,7 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
{
@@ -3857,55 +3551,3 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
}
-void GLAPIENTRY
-_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
-{
- const struct gl_texture_unit *texUnit;
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GLint maxLevels;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- texObj = _mesa_select_tex_object(ctx, texUnit, target);
- if (!texObj) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
- return;
- }
-
- maxLevels = _mesa_max_texture_levels(ctx, target);
- ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
-
- if (level < 0 || level >= maxLevels) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
- return;
- }
-
- if (_mesa_is_proxy_texture(target)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
- return;
- }
-
- _mesa_lock_texture(ctx, texObj);
- {
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- if (texImage) {
- if (texImage->IsCompressed) {
- /* this typically calls _mesa_get_compressed_teximage() */
- ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
- texObj, texImage);
- }
- else {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImageARB");
- }
- }
- else {
- /* probably invalid mipmap level */
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetCompressedTexImageARB(level)");
- }
- }
- _mesa_unlock_texture(ctx, texObj);
-}
diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h
index eb60a1fa8f..094177da79 100644
--- a/src/mesa/main/teximage.h
+++ b/src/mesa/main/teximage.h
@@ -73,6 +73,10 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
extern void
+_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage);
+
+
+extern void
_mesa_set_tex_image(struct gl_texture_object *tObj,
GLenum target, GLint level,
struct gl_texture_image *texImage);
@@ -111,10 +115,6 @@ extern GLuint
_mesa_tex_target_to_face(GLenum target);
-extern GLboolean
-_mesa_is_color_format(GLenum format);
-
-
/**
* Lock a texture for updating. See also _mesa_lock_context_textures().
*/
@@ -164,11 +164,6 @@ _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalformat,
extern void GLAPIENTRY
-_mesa_GetTexImage( GLenum target, GLint level,
- GLenum format, GLenum type, GLvoid *pixels );
-
-
-extern void GLAPIENTRY
_mesa_TexSubImage1D( GLenum target, GLint level, GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
@@ -260,9 +255,6 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
GLsizei height, GLsizei depth, GLenum format,
GLsizei imageSize, const GLvoid *data);
-extern void GLAPIENTRY
-_mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img);
-
/*@}*/
#endif
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index 7848f0be35..678845ece0 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -28,10 +28,8 @@
*/
-#include "glheader.h"
-#if FEATURE_colortable
+#include "mfeatures.h"
#include "colortab.h"
-#endif
#include "context.h"
#include "enums.h"
#include "fbobject.h"
@@ -42,6 +40,8 @@
#include "texstate.h"
#include "texobj.h"
#include "mtypes.h"
+#include "shader/prog_instruction.h"
+
/**********************************************************************/
@@ -132,12 +132,15 @@ _mesa_initialize_texture_object( struct gl_texture_object *obj,
obj->BaseLevel = 0;
obj->MaxLevel = 1000;
obj->MaxAnisotropy = 1.0;
- obj->CompareFlag = GL_FALSE; /* SGIX_shadow */
- obj->CompareOperator = GL_TEXTURE_LEQUAL_R_SGIX; /* SGIX_shadow */
obj->CompareMode = GL_NONE; /* ARB_shadow */
obj->CompareFunc = GL_LEQUAL; /* ARB_shadow */
+ obj->CompareFailValue = 0.0F; /* ARB_shadow_ambient */
obj->DepthMode = GL_LUMINANCE; /* ARB_depth_texture */
- obj->ShadowAmbient = 0.0F; /* ARB/SGIX_shadow_ambient */
+ obj->Swizzle[0] = GL_RED;
+ obj->Swizzle[1] = GL_GREEN;
+ obj->Swizzle[2] = GL_BLUE;
+ obj->Swizzle[3] = GL_ALPHA;
+ obj->_Swizzle = SWIZZLE_NOOP;
}
@@ -175,7 +178,7 @@ finish_texture_init(GLcontext *ctx, GLenum target,
* Called via ctx->Driver.DeleteTexture() if not overriden by a driver.
*
* \param shared the shared GL state to which the object belongs.
- * \param texOjb the texture object to delete.
+ * \param texObj the texture object to delete.
*/
void
_mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
@@ -189,9 +192,7 @@ _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
*/
texObj->Target = 0x99;
-#if FEATURE_colortable
_mesa_free_colortable_data(&texObj->Palette);
-#endif
/* free the texture images */
for (face = 0; face < 6; face++) {
@@ -241,17 +242,43 @@ _mesa_copy_texture_object( struct gl_texture_object *dest,
dest->BaseLevel = src->BaseLevel;
dest->MaxLevel = src->MaxLevel;
dest->MaxAnisotropy = src->MaxAnisotropy;
- dest->CompareFlag = src->CompareFlag;
- dest->CompareOperator = src->CompareOperator;
- dest->ShadowAmbient = src->ShadowAmbient;
dest->CompareMode = src->CompareMode;
dest->CompareFunc = src->CompareFunc;
+ dest->CompareFailValue = src->CompareFailValue;
dest->DepthMode = src->DepthMode;
dest->_MaxLevel = src->_MaxLevel;
dest->_MaxLambda = src->_MaxLambda;
dest->GenerateMipmap = src->GenerateMipmap;
dest->Palette = src->Palette;
dest->_Complete = src->_Complete;
+ COPY_4V(dest->Swizzle, src->Swizzle);
+ dest->_Swizzle = src->_Swizzle;
+}
+
+
+/**
+ * Clear all texture images of the given texture object.
+ *
+ * \param ctx GL context.
+ * \param t texture object.
+ *
+ * \sa _mesa_clear_texture_image().
+ */
+void
+_mesa_clear_texture_object(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ GLuint i, j;
+
+ if (texObj->Target == 0)
+ return;
+
+ for (i = 0; i < MAX_FACES; i++) {
+ for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
+ struct gl_texture_image *texImage = texObj->Image[i][j];
+ if (texImage)
+ _mesa_clear_texture_image(ctx, texImage);
+ }
+ }
}
@@ -276,7 +303,8 @@ valid_texture_object(const struct gl_texture_object *tex)
_mesa_problem(NULL, "invalid reference to a deleted texture object");
return GL_FALSE;
default:
- _mesa_problem(NULL, "invalid texture object Target value");
+ _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u",
+ tex->Target, tex->Name);
return GL_FALSE;
}
}
@@ -302,7 +330,7 @@ _mesa_reference_texobj(struct gl_texture_object **ptr,
GLboolean deleteFlag = GL_FALSE;
struct gl_texture_object *oldTex = *ptr;
- assert(valid_texture_object(oldTex));
+ ASSERT(valid_texture_object(oldTex));
_glthread_LOCK_MUTEX(oldTex->Mutex);
ASSERT(oldTex->RefCount > 0);
@@ -325,7 +353,7 @@ _mesa_reference_texobj(struct gl_texture_object **ptr,
if (tex) {
/* reference new texture */
- assert(valid_texture_object(tex));
+ ASSERT(valid_texture_object(tex));
_glthread_LOCK_MUTEX(tex->Mutex);
if (tex->RefCount == 0) {
/* this texture's being deleted (look just above) */
@@ -388,8 +416,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
*/
if ((baseLevel < 0) || (baseLevel > MAX_TEXTURE_LEVELS)) {
char s[100];
- _mesa_sprintf(s, "obj %p (%d) base level = %d is invalid",
- (void *) t, t->Name, baseLevel);
+ _mesa_sprintf(s, "base level = %d is invalid", baseLevel);
incomplete(t, s);
t->_Complete = GL_FALSE;
return;
@@ -398,8 +425,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
/* Always need the base level image */
if (!t->Image[0][baseLevel]) {
char s[100];
- _mesa_sprintf(s, "obj %p (%d) Image[baseLevel=%d] == NULL",
- (void *) t, t->Name, baseLevel);
+ _mesa_sprintf(s, "Image[baseLevel=%d] == NULL", baseLevel);
incomplete(t, s);
t->_Complete = GL_FALSE;
return;
@@ -659,6 +685,76 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
}
}
+
+/**
+ * Mark a texture object dirty. It forces the object to be incomplete
+ * and optionally forces the context to re-validate its state.
+ *
+ * \param ctx GL context.
+ * \param texObj texture object.
+ * \param invalidate_state also invalidate context state.
+ */
+void
+_mesa_dirty_texobj(GLcontext *ctx, struct gl_texture_object *texObj,
+ GLboolean invalidate_state)
+{
+ texObj->_Complete = GL_FALSE;
+ if (invalidate_state)
+ ctx->NewState |= _NEW_TEXTURE;
+}
+
+
+/**
+ * Return pointer to a default/fallback texture.
+ * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1).
+ * That's the value a sampler should get when sampling from an
+ * incomplete texture.
+ */
+struct gl_texture_object *
+_mesa_get_fallback_texture(GLcontext *ctx)
+{
+ if (!ctx->Shared->FallbackTex) {
+ /* create fallback texture now */
+ static GLubyte texels[8 * 8][4];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLuint i;
+
+ for (i = 0; i < 8 * 8; i++) {
+ texels[i][0] =
+ texels[i][1] =
+ texels[i][2] = 0x0;
+ texels[i][3] = 0xff;
+ }
+
+ /* create texture object */
+ texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
+ assert(texObj->RefCount == 1);
+ texObj->MinFilter = GL_NEAREST;
+ texObj->MagFilter = GL_NEAREST;
+
+ /* create level[0] texture image */
+ texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);
+
+ /* init the image fields */
+ _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage,
+ 8, 8, 1, 0, GL_RGBA);
+
+ /* set image data */
+ ctx->Driver.TexImage2D(ctx, GL_TEXTURE_2D, 0, GL_RGBA,
+ 8, 8, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texels,
+ &ctx->DefaultPacking, texObj, texImage);
+
+ _mesa_test_texobj_completeness(ctx, texObj);
+ assert(texObj->_Complete);
+
+ ctx->Shared->FallbackTex = texObj;
+ }
+ return ctx->Shared->FallbackTex;
+}
+
+
/*@}*/
@@ -756,37 +852,17 @@ unbind_texobj_from_fbo(GLcontext *ctx, struct gl_texture_object *texObj)
static void
unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj)
{
- GLuint u;
+ GLuint u, tex;
for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
- if (texObj == unit->Current1D) {
- _mesa_reference_texobj(&unit->Current1D, ctx->Shared->Default1D);
- ASSERT(unit->Current1D);
- }
- else if (texObj == unit->Current2D) {
- _mesa_reference_texobj(&unit->Current2D, ctx->Shared->Default2D);
- ASSERT(unit->Current2D);
- }
- else if (texObj == unit->Current3D) {
- _mesa_reference_texobj(&unit->Current3D, ctx->Shared->Default3D);
- ASSERT(unit->Current3D);
- }
- else if (texObj == unit->CurrentCubeMap) {
- _mesa_reference_texobj(&unit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
- ASSERT(unit->CurrentCubeMap);
- }
- else if (texObj == unit->CurrentRect) {
- _mesa_reference_texobj(&unit->CurrentRect, ctx->Shared->DefaultRect);
- ASSERT(unit->CurrentRect);
- }
- else if (texObj == unit->Current1DArray) {
- _mesa_reference_texobj(&unit->Current1DArray, ctx->Shared->Default1DArray);
- ASSERT(unit->Current1DArray);
- }
- else if (texObj == unit->Current2DArray) {
- _mesa_reference_texobj(&unit->Current2DArray, ctx->Shared->Default2DArray);
- ASSERT(unit->Current2DArray);
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ if (texObj == unit->CurrentTex[tex]) {
+ _mesa_reference_texobj(&unit->CurrentTex[tex],
+ ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]);
+ ASSERT(unit->CurrentTex[tex]);
+ break;
+ }
}
}
}
@@ -857,6 +933,35 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
/**
+ * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
+ * into the corresponding Mesa texture target index.
+ * Return -1 if target is invalid.
+ */
+static GLint
+target_enum_to_index(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ return TEXTURE_1D_INDEX;
+ case GL_TEXTURE_2D:
+ return TEXTURE_2D_INDEX;
+ case GL_TEXTURE_3D:
+ return TEXTURE_3D_INDEX;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ return TEXTURE_CUBE_INDEX;
+ case GL_TEXTURE_RECTANGLE_NV:
+ return TEXTURE_RECT_INDEX;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ return TEXTURE_1D_ARRAY_INDEX;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return TEXTURE_2D_ARRAY_INDEX;
+ default:
+ return -1;
+ }
+}
+
+
+/**
* Bind a named texture to a texturing target.
*
* \param target texture target.
@@ -878,38 +983,21 @@ _mesa_BindTexture( GLenum target, GLuint texName )
const GLuint unit = ctx->Texture.CurrentUnit;
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
struct gl_texture_object *newTexObj = NULL, *defaultTexObj = NULL;
+ GLint targetIndex;
+ GLboolean early_out = GL_FALSE;
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
_mesa_debug(ctx, "glBindTexture %s %d\n",
_mesa_lookup_enum_by_nr(target), (GLint) texName);
- switch (target) {
- case GL_TEXTURE_1D:
- defaultTexObj = ctx->Shared->Default1D;
- break;
- case GL_TEXTURE_2D:
- defaultTexObj = ctx->Shared->Default2D;
- break;
- case GL_TEXTURE_3D:
- defaultTexObj = ctx->Shared->Default3D;
- break;
- case GL_TEXTURE_CUBE_MAP_ARB:
- defaultTexObj = ctx->Shared->DefaultCubeMap;
- break;
- case GL_TEXTURE_RECTANGLE_NV:
- defaultTexObj = ctx->Shared->DefaultRect;
- break;
- case GL_TEXTURE_1D_ARRAY_EXT:
- defaultTexObj = ctx->Shared->Default1DArray;
- break;
- case GL_TEXTURE_2D_ARRAY_EXT:
- defaultTexObj = ctx->Shared->Default2DArray;
- break;
- default:
+ targetIndex = target_enum_to_index(target);
+ if (targetIndex < 0) {
_mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
return;
}
+ assert(targetIndex < NUM_TEXTURE_TARGETS);
+ defaultTexObj = ctx->Shared->DefaultTex[targetIndex];
/*
* Get pointer to new texture object (newTexObj)
@@ -950,6 +1038,17 @@ _mesa_BindTexture( GLenum target, GLuint texName )
assert(valid_texture_object(newTexObj));
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ if ((ctx->Shared->RefCount == 1)
+ && (newTexObj == texUnit->CurrentTex[targetIndex])) {
+ early_out = GL_TRUE;
+ }
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ if (early_out) {
+ return;
+ }
+
/* flush before changing binding */
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
@@ -957,40 +1056,8 @@ _mesa_BindTexture( GLenum target, GLuint texName )
* texture object will be decremented. It'll be deleted if the
* count hits zero.
*/
- switch (target) {
- case GL_TEXTURE_1D:
- _mesa_reference_texobj(&texUnit->Current1D, newTexObj);
- ASSERT(texUnit->Current1D);
- break;
- case GL_TEXTURE_2D:
- _mesa_reference_texobj(&texUnit->Current2D, newTexObj);
- ASSERT(texUnit->Current2D);
- break;
- case GL_TEXTURE_3D:
- _mesa_reference_texobj(&texUnit->Current3D, newTexObj);
- ASSERT(texUnit->Current3D);
- break;
- case GL_TEXTURE_CUBE_MAP_ARB:
- _mesa_reference_texobj(&texUnit->CurrentCubeMap, newTexObj);
- ASSERT(texUnit->CurrentCubeMap);
- break;
- case GL_TEXTURE_RECTANGLE_NV:
- _mesa_reference_texobj(&texUnit->CurrentRect, newTexObj);
- ASSERT(texUnit->CurrentRect);
- break;
- case GL_TEXTURE_1D_ARRAY_EXT:
- texUnit->Current1DArray = newTexObj;
- ASSERT(texUnit->Current1DArray);
- break;
- case GL_TEXTURE_2D_ARRAY_EXT:
- texUnit->Current2DArray = newTexObj;
- ASSERT(texUnit->Current2DArray);
- break;
- default:
- /* Bad target should be caught above */
- _mesa_problem(ctx, "bad target in BindTexture");
- return;
- }
+ _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
+ ASSERT(texUnit->CurrentTex[targetIndex]);
/* Pass BindTexture call to device driver */
if (ctx->Driver.BindTexture)
@@ -1132,10 +1199,9 @@ _mesa_IsTexture( GLuint texture )
/**
- * Simplest implementation of texture locking: Grab the a new mutex in
- * the shared context. Examine the shared context state timestamp and
- * if there has been a change, set the appropriate bits in
- * ctx->NewState.
+ * Simplest implementation of texture locking: grab the shared tex
+ * mutex. Examine the shared context state timestamp and if there has
+ * been a change, set the appropriate bits in ctx->NewState.
*
* This is used to deal with synchronizing things when a texture object
* is used/modified by different contexts (or threads) which are sharing
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index d5374c5d6c..9bfebd45c8 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -58,6 +58,9 @@ _mesa_copy_texture_object( struct gl_texture_object *dest,
const struct gl_texture_object *src );
extern void
+_mesa_clear_texture_object(GLcontext *ctx, struct gl_texture_object *obj);
+
+extern void
_mesa_reference_texobj(struct gl_texture_object **ptr,
struct gl_texture_object *tex);
@@ -66,6 +69,13 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
struct gl_texture_object *obj );
extern void
+_mesa_dirty_texobj(GLcontext *ctx, struct gl_texture_object *texObj,
+ GLboolean invalidate_state);
+
+extern struct gl_texture_object *
+_mesa_get_fallback_texture(GLcontext *ctx);
+
+extern void
_mesa_unlock_context_textures( GLcontext *ctx );
extern void
@@ -73,7 +83,6 @@ _mesa_lock_context_textures( GLcontext *ctx );
/*@}*/
-
/**
* \name API functions
*/
diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c
index a9e752a637..6cbb9999b1 100644
--- a/src/mesa/main/texparam.c
+++ b/src/mesa/main/texparam.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.5
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -37,6 +38,8 @@
#include "main/texcompress.h"
#include "main/texparam.h"
#include "main/teximage.h"
+#include "main/texstate.h"
+#include "shader/prog_instruction.h"
/**
@@ -67,409 +70,640 @@ validate_texture_wrap_mode(GLcontext * ctx, GLenum target, GLenum wrap)
return GL_TRUE;
}
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param=0x%x)", wrap );
return GL_FALSE;
}
-void GLAPIENTRY
-_mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param )
+/**
+ * Get current texture object for given target.
+ * Return NULL if any error.
+ */
+static struct gl_texture_object *
+get_texobj(GLcontext *ctx, GLenum target)
{
- _mesa_TexParameterfv(target, pname, &param);
+ struct gl_texture_unit *texUnit;
+
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(current unit)");
+ return NULL;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ return texUnit->CurrentTex[TEXTURE_1D_INDEX];
+ case GL_TEXTURE_2D:
+ return texUnit->CurrentTex[TEXTURE_2D_INDEX];
+ case GL_TEXTURE_3D:
+ return texUnit->CurrentTex[TEXTURE_3D_INDEX];
+ case GL_TEXTURE_CUBE_MAP:
+ if (ctx->Extensions.ARB_texture_cube_map) {
+ return texUnit->CurrentTex[TEXTURE_CUBE_INDEX];
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ if (ctx->Extensions.NV_texture_rectangle) {
+ return texUnit->CurrentTex[TEXTURE_RECT_INDEX];
+ }
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ if (ctx->Extensions.MESA_texture_array) {
+ return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX];
+ }
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ if (ctx->Extensions.MESA_texture_array) {
+ return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX];
+ }
+ break;
+ default:
+ ;
+ }
+
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(target)");
+ return NULL;
}
-void GLAPIENTRY
-_mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
+/**
+ * Convert GL_RED/GREEN/BLUE/ALPHA/ZERO/ONE to SWIZZLE_X/Y/Z/W/ZERO/ONE.
+ * \return -1 if error.
+ */
+static GLint
+comp_to_swizzle(GLenum comp)
{
- const GLenum eparam = (GLenum) (GLint) params[0];
- struct gl_texture_unit *texUnit;
- struct gl_texture_object *texObj;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ switch (comp) {
+ case GL_RED:
+ return SWIZZLE_X;
+ case GL_GREEN:
+ return SWIZZLE_Y;
+ case GL_BLUE:
+ return SWIZZLE_Z;
+ case GL_ALPHA:
+ return SWIZZLE_W;
+ case GL_ZERO:
+ return SWIZZLE_ZERO;
+ case GL_ONE:
+ return SWIZZLE_ONE;
+ default:
+ return -1;
+ }
+}
- if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glTexParameter %s %s %.1f(%s)...\n",
- _mesa_lookup_enum_by_nr(target),
- _mesa_lookup_enum_by_nr(pname),
- *params,
- _mesa_lookup_enum_by_nr(eparam));
- if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameterfv(current unit)");
- return;
+static void
+set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz)
+{
+ ASSERT(comp < 4);
+ ASSERT(swz <= SWIZZLE_NIL);
+ {
+ GLuint mask = 0x7 << (3 * comp);
+ GLuint s = (*swizzle & ~mask) | (swz << (3 * comp));
+ *swizzle = s;
}
+}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
- switch (target) {
- case GL_TEXTURE_1D:
- texObj = texUnit->Current1D;
- break;
- case GL_TEXTURE_2D:
- texObj = texUnit->Current2D;
- break;
- case GL_TEXTURE_3D:
- texObj = texUnit->Current3D;
- break;
- case GL_TEXTURE_CUBE_MAP:
- if (!ctx->Extensions.ARB_texture_cube_map) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
- return;
- }
- texObj = texUnit->CurrentCubeMap;
- break;
- case GL_TEXTURE_RECTANGLE_NV:
- if (!ctx->Extensions.NV_texture_rectangle) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
- return;
- }
- texObj = texUnit->CurrentRect;
- break;
- case GL_TEXTURE_1D_ARRAY_EXT:
- if (!ctx->Extensions.MESA_texture_array) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
- return;
- }
- texObj = texUnit->Current1DArray;
- break;
- case GL_TEXTURE_2D_ARRAY_EXT:
- if (!ctx->Extensions.MESA_texture_array) {
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
- return;
- }
- texObj = texUnit->Current2DArray;
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
- return;
- }
+/**
+ * This is called just prior to changing any texture object state.
+ * 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(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texObj->_Complete = GL_FALSE;
+}
+
+/**
+ * Set an integer-valued texture parameter
+ * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
+ */
+static GLboolean
+set_tex_parameteri(GLcontext *ctx,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLint *params)
+{
switch (pname) {
- case GL_TEXTURE_MIN_FILTER:
- /* A small optimization */
- if (texObj->MinFilter == eparam)
- return;
- if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->MinFilter = eparam;
- }
- else if ((eparam==GL_NEAREST_MIPMAP_NEAREST ||
- eparam==GL_LINEAR_MIPMAP_NEAREST ||
- eparam==GL_NEAREST_MIPMAP_LINEAR ||
- eparam==GL_LINEAR_MIPMAP_LINEAR) &&
- texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->MinFilter = eparam;
- }
- else {
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
- return;
- }
- break;
- case GL_TEXTURE_MAG_FILTER:
- /* A small optimization */
- if (texObj->MagFilter == eparam)
- return;
+ case GL_TEXTURE_MIN_FILTER:
+ if (texObj->MinFilter == params[0])
+ return GL_FALSE;
+ switch (params[0]) {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ flush(ctx, texObj);
+ texObj->MinFilter = params[0];
+ return GL_TRUE;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ if (texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
+ flush(ctx, texObj);
+ texObj->MinFilter = params[0];
+ return GL_TRUE;
+ }
+ /* fall-through */
+ default:
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param=0x%x)",
+ params[0] );
+ }
+ return GL_FALSE;
- if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->MagFilter = eparam;
- }
- else {
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
- return;
- }
- break;
- case GL_TEXTURE_WRAP_S:
- if (texObj->WrapS == eparam)
- return;
- if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->WrapS = eparam;
- }
- else {
- return;
- }
- break;
- case GL_TEXTURE_WRAP_T:
- if (texObj->WrapT == eparam)
- return;
- if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->WrapT = eparam;
- }
- else {
- return;
- }
- break;
- case GL_TEXTURE_WRAP_R:
- if (texObj->WrapR == eparam)
- return;
- if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->WrapR = eparam;
- }
- else {
- return;
- }
- break;
- case GL_TEXTURE_BORDER_COLOR:
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->BorderColor[RCOMP] = params[0];
- texObj->BorderColor[GCOMP] = params[1];
- texObj->BorderColor[BCOMP] = params[2];
- texObj->BorderColor[ACOMP] = params[3];
- UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[RCOMP], params[0]);
- UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[GCOMP], params[1]);
- UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[BCOMP], params[2]);
- UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[ACOMP], params[3]);
- break;
- case GL_TEXTURE_MIN_LOD:
- if (texObj->MinLod == params[0])
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->MinLod = params[0];
- break;
- case GL_TEXTURE_MAX_LOD:
- if (texObj->MaxLod == params[0])
- return;
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->MaxLod = params[0];
- break;
- case GL_TEXTURE_BASE_LEVEL:
- if (params[0] < 0.0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
- return;
- }
- if (target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0.0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
- return;
- }
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->BaseLevel = (GLint) params[0];
- break;
- case GL_TEXTURE_MAX_LEVEL:
- if (params[0] < 0.0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
- return;
- }
- if (target == GL_TEXTURE_RECTANGLE_ARB) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(param)");
- return;
- }
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->MaxLevel = (GLint) params[0];
- break;
- case GL_TEXTURE_PRIORITY:
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->Priority = CLAMP( params[0], 0.0F, 1.0F );
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (ctx->Extensions.EXT_texture_filter_anisotropic) {
- if (params[0] < 1.0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
- return;
- }
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- /* clamp to max, that's what NVIDIA does */
- texObj->MaxAnisotropy = MIN2(params[0],
- ctx->Const.MaxTextureMaxAnisotropy);
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
- return;
- }
- break;
- case GL_TEXTURE_COMPARE_SGIX:
- if (ctx->Extensions.SGIX_shadow) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->CompareFlag = params[0] ? GL_TRUE : GL_FALSE;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=GL_TEXTURE_COMPARE_SGIX)");
- return;
- }
- break;
- case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
- if (ctx->Extensions.SGIX_shadow) {
- GLenum op = (GLenum) params[0];
- if (op == GL_TEXTURE_LEQUAL_R_SGIX ||
- op == GL_TEXTURE_GEQUAL_R_SGIX) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->CompareOperator = op;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param)");
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=GL_TEXTURE_COMPARE_OPERATOR_SGIX)");
- return;
- }
- break;
- case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
- if (ctx->Extensions.SGIX_shadow_ambient) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->ShadowAmbient = CLAMP(params[0], 0.0F, 1.0F);
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=GL_SHADOW_AMBIENT_SGIX)");
- return;
- }
- break;
- case GL_GENERATE_MIPMAP_SGIS:
- if (ctx->Extensions.SGIS_generate_mipmap) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ case GL_TEXTURE_MAG_FILTER:
+ if (texObj->MagFilter == params[0])
+ return GL_FALSE;
+ switch (params[0]) {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ flush(ctx, texObj);
+ texObj->MagFilter = params[0];
+ return GL_TRUE;
+ default:
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param=0x%x)",
+ params[0]);
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_WRAP_S:
+ if (texObj->WrapS == params[0])
+ return GL_FALSE;
+ if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
+ flush(ctx, texObj);
+ texObj->WrapS = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_WRAP_T:
+ if (texObj->WrapT == params[0])
+ return GL_FALSE;
+ if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
+ flush(ctx, texObj);
+ texObj->WrapT = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_WRAP_R:
+ if (texObj->WrapR == params[0])
+ return GL_FALSE;
+ if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
+ flush(ctx, texObj);
+ texObj->WrapR = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_BASE_LEVEL:
+ if (texObj->BaseLevel == params[0])
+ return GL_FALSE;
+ if (params[0] < 0 ||
+ (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexParameter(param=%d)", params[0]);
+ return GL_FALSE;
+ }
+ flush(ctx, texObj);
+ texObj->BaseLevel = params[0];
+ return GL_TRUE;
+
+ case GL_TEXTURE_MAX_LEVEL:
+ if (texObj->MaxLevel == params[0])
+ return GL_FALSE;
+ if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexParameter(param=%d)", params[0]);
+ return GL_FALSE;
+ }
+ flush(ctx, texObj);
+ texObj->MaxLevel = params[0];
+ return GL_TRUE;
+
+ case GL_GENERATE_MIPMAP_SGIS:
+ if (ctx->Extensions.SGIS_generate_mipmap) {
+ if (texObj->GenerateMipmap != params[0]) {
+ flush(ctx, texObj);
texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
+ return GL_TRUE;
}
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)");
- return;
- }
- break;
- case GL_TEXTURE_COMPARE_MODE_ARB:
- if (ctx->Extensions.ARB_shadow) {
- const GLenum mode = (GLenum) params[0];
- if (mode == GL_NONE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->CompareMode = mode;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(bad GL_TEXTURE_COMPARE_MODE_ARB: 0x%x)", mode);
- return;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=GL_TEXTURE_COMPARE_MODE_ARB)");
- return;
- }
- break;
- case GL_TEXTURE_COMPARE_FUNC_ARB:
- if (ctx->Extensions.ARB_shadow) {
- const GLenum func = (GLenum) params[0];
- if (func == GL_LEQUAL || func == GL_GEQUAL) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->CompareFunc = func;
- }
- else if (ctx->Extensions.EXT_shadow_funcs &&
- (func == GL_EQUAL ||
- func == GL_NOTEQUAL ||
- func == GL_LESS ||
- func == GL_GREATER ||
- func == GL_ALWAYS ||
- func == GL_NEVER)) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->CompareFunc = func;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(bad GL_TEXTURE_COMPARE_FUNC_ARB)");
- return;
+ return GL_FALSE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)");
+ }
+ 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);
+ texObj->CompareMode = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(GL_TEXTURE_COMPARE_MODE_ARB)");
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ if (ctx->Extensions.ARB_shadow) {
+ if (texObj->CompareFunc == params[0])
+ return GL_FALSE;
+ switch (params[0]) {
+ case GL_LEQUAL:
+ case GL_GEQUAL:
+ flush(ctx, texObj);
+ texObj->CompareFunc = params[0];
+ return GL_TRUE;
+ case GL_EQUAL:
+ case GL_NOTEQUAL:
+ case GL_LESS:
+ case GL_GREATER:
+ case GL_ALWAYS:
+ case GL_NEVER:
+ if (ctx->Extensions.EXT_shadow_funcs) {
+ flush(ctx, texObj);
+ texObj->CompareFunc = params[0];
+ return GL_TRUE;
}
- }
- else {
+ /* fall-through */
+ default:
_mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=GL_TEXTURE_COMPARE_FUNC_ARB)");
- return;
+ "glTexParameter(GL_TEXTURE_COMPARE_FUNC_ARB)");
}
- break;
- case GL_DEPTH_TEXTURE_MODE_ARB:
- if (ctx->Extensions.ARB_depth_texture) {
- const GLenum result = (GLenum) params[0];
- if (result == GL_LUMINANCE || result == GL_INTENSITY
- || result == GL_ALPHA) {
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texObj->DepthMode = result;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
+ }
+ return GL_FALSE;
+
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ if (ctx->Extensions.ARB_depth_texture &&
+ (params[0] == GL_LUMINANCE ||
+ params[0] == GL_INTENSITY ||
+ params[0] == GL_ALPHA)) {
+ if (texObj->DepthMode != params[0]) {
+ flush(ctx, texObj);
+ texObj->DepthMode = params[0];
+ return GL_TRUE;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(GL_DEPTH_TEXTURE_MODE_ARB)");
+ }
+ return GL_FALSE;
+
+#ifdef FEATURE_OES_draw_texture
+ case GL_TEXTURE_CROP_RECT_OES:
+ texObj->CropRect[0] = params[0];
+ texObj->CropRect[1] = params[1];
+ texObj->CropRect[2] = params[2];
+ texObj->CropRect[3] = params[3];
+ return GL_TRUE;
+#endif
+
+ case GL_TEXTURE_SWIZZLE_R_EXT:
+ case GL_TEXTURE_SWIZZLE_G_EXT:
+ case GL_TEXTURE_SWIZZLE_B_EXT:
+ case GL_TEXTURE_SWIZZLE_A_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
+ const GLint swz = comp_to_swizzle(params[0]);
+ if (swz < 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexParameter(swizzle 0x%x)", params[0]);
+ return GL_FALSE;
+ }
+ ASSERT(comp < 4);
+ if (swz >= 0) {
+ flush(ctx, texObj);
+ 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;
+
+ case GL_TEXTURE_SWIZZLE_RGBA_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ GLuint comp;
+ flush(ctx, texObj);
+ for (comp = 0; comp < 4; comp++) {
+ const GLint swz = comp_to_swizzle(params[comp]);
+ if (swz >= 0) {
+ texObj->Swizzle[comp] = params[comp];
+ set_swizzle_component(&texObj->_Swizzle, comp, swz);
}
else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(bad GL_DEPTH_TEXTURE_MODE_ARB)");
- return;
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexParameter(swizzle 0x%x)", params[comp]);
+ return GL_FALSE;
}
}
- else {
+ return GL_TRUE;
+ }
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
+ return GL_FALSE;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Set a float-valued texture parameter
+ * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
+ */
+static GLboolean
+set_tex_parameterf(GLcontext *ctx,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat *params)
+{
+ switch (pname) {
+ case GL_TEXTURE_MIN_LOD:
+ if (texObj->MinLod == params[0])
+ return GL_FALSE;
+ flush(ctx, texObj);
+ texObj->MinLod = params[0];
+ return GL_TRUE;
+
+ case GL_TEXTURE_MAX_LOD:
+ if (texObj->MaxLod == params[0])
+ return GL_FALSE;
+ flush(ctx, texObj);
+ texObj->MaxLod = params[0];
+ return GL_TRUE;
+
+ case GL_TEXTURE_PRIORITY:
+ flush(ctx, texObj);
+ texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
+ return GL_TRUE;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (ctx->Extensions.EXT_texture_filter_anisotropic) {
+ if (texObj->MaxAnisotropy == params[0])
+ return GL_FALSE;
+ if (params[0] < 1.0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return GL_FALSE;
+ }
+ flush(ctx, texObj);
+ /* clamp to max, that's what NVIDIA does */
+ texObj->MaxAnisotropy = MIN2(params[0],
+ ctx->Const.MaxTextureMaxAnisotropy);
+ return GL_TRUE;
+ }
+ else {
+ static GLuint count = 0;
+ if (count++ < 10)
_mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=GL_DEPTH_TEXTURE_MODE_ARB)");
- return;
- }
- break;
- case GL_TEXTURE_LOD_BIAS:
- /* 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_VERTICES(ctx, _NEW_TEXTURE);
- texObj->LodBias = params[0];
- }
- }
- break;
-#ifdef FEATURE_OES_draw_texture
- case GL_TEXTURE_CROP_RECT_OES:
- texObj->CropRect[0] = (GLint) params[0];
- texObj->CropRect[1] = (GLint) params[1];
- texObj->CropRect[2] = (GLint) params[2];
- texObj->CropRect[3] = (GLint) params[3];
- break;
-#endif
+ "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
+ }
+ return GL_FALSE;
- default:
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ if (ctx->Extensions.ARB_shadow_ambient) {
+ if (texObj->CompareFailValue != params[0]) {
+ flush(ctx, texObj);
+ texObj->CompareFailValue = CLAMP(params[0], 0.0F, 1.0F);
+ return GL_TRUE;
+ }
+ }
+ else {
_mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=0x%x)", pname);
- return;
+ "glTexParameter(pname=GL_TEXTURE_COMPARE_FAIL_VALUE_ARB)");
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_LOD_BIAS:
+ /* 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);
+ texObj->LodBias = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ flush(ctx, texObj);
+ texObj->BorderColor[RCOMP] = params[0];
+ texObj->BorderColor[GCOMP] = params[1];
+ texObj->BorderColor[BCOMP] = params[2];
+ texObj->BorderColor[ACOMP] = params[3];
+ return GL_TRUE;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
}
+ return GL_FALSE;
+}
- texObj->_Complete = GL_FALSE;
- if (ctx->Driver.TexParameter) {
- (*ctx->Driver.TexParameter)( ctx, target, texObj, pname, params );
+void GLAPIENTRY
+_mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ GLboolean need_update;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ texObj = get_texobj(ctx, target);
+ if (!texObj)
+ return;
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_GENERATE_MIPMAP_SGIS:
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ {
+ /* convert float param to int */
+ GLint p = (GLint) param;
+ need_update = set_tex_parameteri(ctx, texObj, pname, &p);
+ }
+ break;
+ default:
+ /* this will generate an error if pname is illegal */
+ need_update = set_tex_parameterf(ctx, texObj, pname, &param);
+ }
+
+ if (ctx->Driver.TexParameter && need_update) {
+ ctx->Driver.TexParameter(ctx, target, texObj, pname, &param);
}
}
void GLAPIENTRY
-_mesa_TexParameteri( GLenum target, GLenum pname, GLint param )
+_mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
{
- GLfloat fparam[4];
- if (pname == GL_TEXTURE_PRIORITY)
- fparam[0] = INT_TO_FLOAT(param);
- else
- fparam[0] = (GLfloat) param;
- fparam[1] = fparam[2] = fparam[3] = 0.0;
- _mesa_TexParameterfv(target, pname, fparam);
+ GLboolean need_update;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ texObj = get_texobj(ctx, target);
+ if (!texObj)
+ return;
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_GENERATE_MIPMAP_SGIS:
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ {
+ /* convert float param to int */
+ GLint p = (GLint) params[0];
+ need_update = set_tex_parameteri(ctx, texObj, pname, &p);
+ }
+ break;
+
+#ifdef FEATURE_OES_draw_texture
+ case GL_TEXTURE_CROP_RECT_OES:
+ {
+ /* convert float params to int */
+ GLint iparams[4];
+ iparams[0] = (GLint) params[0];
+ iparams[1] = (GLint) params[1];
+ iparams[2] = (GLint) params[2];
+ iparams[3] = (GLint) params[3];
+ need_update = set_tex_parameteri(ctx, texObj, pname, iparams);
+ }
+ break;
+#endif
+
+ default:
+ /* this will generate an error if pname is illegal */
+ need_update = set_tex_parameterf(ctx, texObj, pname, params);
+ }
+
+ if (ctx->Driver.TexParameter && need_update) {
+ ctx->Driver.TexParameter(ctx, target, texObj, pname, params);
+ }
}
void GLAPIENTRY
-_mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
+_mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
{
- GLfloat fparam[4];
- if (pname == GL_TEXTURE_BORDER_COLOR) {
- fparam[0] = INT_TO_FLOAT(params[0]);
- fparam[1] = INT_TO_FLOAT(params[1]);
- fparam[2] = INT_TO_FLOAT(params[2]);
- fparam[3] = INT_TO_FLOAT(params[3]);
+ GLboolean need_update;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ texObj = get_texobj(ctx, target);
+ if (!texObj)
+ return;
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_PRIORITY:
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ case GL_TEXTURE_LOD_BIAS:
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ {
+ GLfloat fparam = (GLfloat) param;
+ /* convert int param to float */
+ need_update = set_tex_parameterf(ctx, texObj, pname, &fparam);
+ }
+ break;
+ default:
+ /* this will generate an error if pname is illegal */
+ need_update = set_tex_parameteri(ctx, texObj, pname, &param);
}
- else if (pname == GL_TEXTURE_CROP_RECT_OES) {
- fparam[0] = (GLfloat) params[0];
- fparam[1] = (GLfloat) params[1];
- fparam[2] = (GLfloat) params[2];
- fparam[3] = (GLfloat) params[3];
+
+ if (ctx->Driver.TexParameter && need_update) {
+ GLfloat fparam = (GLfloat) param;
+ ctx->Driver.TexParameter(ctx, target, texObj, pname, &fparam);
}
- else {
- if (pname == GL_TEXTURE_PRIORITY)
- fparam[0] = INT_TO_FLOAT(params[0]);
- else
- fparam[0] = (GLfloat) params[0];
- fparam[1] = fparam[2] = fparam[3] = 0.0F;
+}
+
+
+void GLAPIENTRY
+_mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ GLboolean need_update;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ texObj = get_texobj(ctx, target);
+ if (!texObj)
+ return;
+
+ switch (pname) {
+ case GL_TEXTURE_BORDER_COLOR:
+ {
+ /* convert int params to float */
+ GLfloat fparams[4];
+ fparams[0] = INT_TO_FLOAT(params[0]);
+ fparams[1] = INT_TO_FLOAT(params[1]);
+ fparams[2] = INT_TO_FLOAT(params[2]);
+ fparams[3] = INT_TO_FLOAT(params[3]);
+ need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
+ }
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_PRIORITY:
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ case GL_TEXTURE_LOD_BIAS:
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ {
+ /* convert int param to float */
+ GLfloat fparam = (GLfloat) params[0];
+ need_update = set_tex_parameterf(ctx, texObj, pname, &fparam);
+ }
+ break;
+ default:
+ /* this will generate an error if pname is illegal */
+ need_update = set_tex_parameteri(ctx, texObj, pname, params);
+ }
+
+ if (ctx->Driver.TexParameter && need_update) {
+ GLfloat fparams[4];
+ fparams[0] = INT_TO_FLOAT(params[0]);
+ if (pname == GL_TEXTURE_BORDER_COLOR ||
+ pname == GL_TEXTURE_CROP_RECT_OES) {
+ fparams[1] = INT_TO_FLOAT(params[1]);
+ fparams[2] = INT_TO_FLOAT(params[2]);
+ fparams[3] = INT_TO_FLOAT(params[3]);
+ }
+ ctx->Driver.TexParameter(ctx, target, texObj, pname, fparams);
}
- _mesa_TexParameterfv(target, pname, fparam);
}
@@ -483,44 +717,6 @@ _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
}
-static GLuint
-tex_image_dimensions(GLcontext *ctx, GLenum target)
-{
- switch (target) {
- case GL_TEXTURE_1D:
- case GL_PROXY_TEXTURE_1D:
- return 1;
- case GL_TEXTURE_2D:
- case GL_PROXY_TEXTURE_2D:
- return 2;
- case GL_TEXTURE_3D:
- case GL_PROXY_TEXTURE_3D:
- return 3;
- case GL_TEXTURE_CUBE_MAP:
- case GL_PROXY_TEXTURE_CUBE_MAP:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- return ctx->Extensions.ARB_texture_cube_map ? 2 : 0;
- case GL_TEXTURE_RECTANGLE_NV:
- case GL_PROXY_TEXTURE_RECTANGLE_NV:
- return ctx->Extensions.NV_texture_rectangle ? 2 : 0;
- case GL_TEXTURE_1D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
- return ctx->Extensions.MESA_texture_array ? 2 : 0;
- case GL_TEXTURE_2D_ARRAY_EXT:
- case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
- return ctx->Extensions.MESA_texture_array ? 3 : 0;
- default:
- _mesa_problem(ctx, "bad target in _mesa_tex_target_dimensions()");
- return 0;
- }
-}
-
-
void GLAPIENTRY
_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
GLenum pname, GLint *params )
@@ -528,7 +724,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;
- GLuint dimensions;
GLboolean isProxy;
GLint maxLevels;
GET_CURRENT_CONTEXT(ctx);
@@ -540,19 +735,13 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
/* this will catch bad target values */
- dimensions = tex_image_dimensions(ctx, target); /* 1, 2 or 3 */
- if (dimensions == 0) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)");
- return;
- }
-
maxLevels = _mesa_max_texture_levels(ctx, target);
if (maxLevels == 0) {
- /* should not happen since <target> was just checked above */
- _mesa_problem(ctx, "maxLevels=0 in _mesa_GetTexLevelParameter");
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(target=0x%x)", target);
return;
}
@@ -649,7 +838,8 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
"glGetTexLevelParameter[if]v(pname)");
break;
case GL_TEXTURE_STENCIL_SIZE_EXT:
- if (ctx->Extensions.EXT_packed_depth_stencil) {
+ if (ctx->Extensions.EXT_packed_depth_stencil ||
+ ctx->Extensions.ARB_framebuffer_object) {
*params = img->TexFormat->StencilBits;
}
else {
@@ -660,33 +850,21 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
/* GL_ARB_texture_compression */
case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
- if (ctx->Extensions.ARB_texture_compression) {
- if (img->IsCompressed && !isProxy) {
- /* Don't use ctx->Driver.CompressedTextureSize() since that
- * may returned a padded hardware size.
- */
- *params = _mesa_compressed_texture_size(ctx, img->Width,
- img->Height, img->Depth,
- img->TexFormat->MesaFormat);
- }
- else {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetTexLevelParameter[if]v(pname)");
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetTexLevelParameter[if]v(pname)");
- }
+ if (img->IsCompressed && !isProxy) {
+ /* Don't use ctx->Driver.CompressedTextureSize() since that
+ * may returned a padded hardware size.
+ */
+ *params = _mesa_compressed_texture_size(ctx, img->Width,
+ img->Height, img->Depth,
+ img->TexFormat->MesaFormat);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
break;
case GL_TEXTURE_COMPRESSED:
- if (ctx->Extensions.ARB_texture_compression) {
- *params = (GLint) img->IsCompressed;
- }
- else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetTexLevelParameter[if]v(pname)");
- }
+ *params = (GLint) img->IsCompressed;
break;
/* GL_ARB_texture_float */
@@ -780,7 +958,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
obj = _mesa_select_tex_object(ctx, texUnit, target);
if (!obj) {
@@ -841,63 +1019,49 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
*params = obj->MaxAnisotropy;
}
else
- error = 1;
- break;
- case GL_TEXTURE_COMPARE_SGIX:
- if (ctx->Extensions.SGIX_shadow) {
- *params = (GLfloat) obj->CompareFlag;
- }
- else
- error = 1;
- break;
- case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
- if (ctx->Extensions.SGIX_shadow) {
- *params = (GLfloat) obj->CompareOperator;
- }
- else
- error = 1;
+ error = GL_TRUE;
break;
- case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
- if (ctx->Extensions.SGIX_shadow_ambient) {
- *params = obj->ShadowAmbient;
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ if (ctx->Extensions.ARB_shadow_ambient) {
+ *params = obj->CompareFailValue;
}
else
- error = 1;
+ error = GL_TRUE;
break;
case GL_GENERATE_MIPMAP_SGIS:
if (ctx->Extensions.SGIS_generate_mipmap) {
*params = (GLfloat) obj->GenerateMipmap;
}
else
- error = 1;
+ error = GL_TRUE;
break;
case GL_TEXTURE_COMPARE_MODE_ARB:
if (ctx->Extensions.ARB_shadow) {
*params = (GLfloat) obj->CompareMode;
}
else
- error = 1;
+ error = GL_TRUE;
break;
case GL_TEXTURE_COMPARE_FUNC_ARB:
if (ctx->Extensions.ARB_shadow) {
*params = (GLfloat) obj->CompareFunc;
}
else
- error = 1;
+ error = GL_TRUE;
break;
case GL_DEPTH_TEXTURE_MODE_ARB:
if (ctx->Extensions.ARB_depth_texture) {
*params = (GLfloat) obj->DepthMode;
}
else
- error = 1;
+ error = GL_TRUE;
break;
case GL_TEXTURE_LOD_BIAS:
if (ctx->Extensions.EXT_texture_lod_bias) {
*params = obj->LodBias;
}
else
- error = 1;
+ error = GL_TRUE;
break;
#ifdef FEATURE_OES_draw_texture
case GL_TEXTURE_CROP_RECT_OES:
@@ -907,10 +1071,37 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
params[3] = obj->CropRect[3];
break;
#endif
+
+ case GL_TEXTURE_SWIZZLE_R_EXT:
+ case GL_TEXTURE_SWIZZLE_G_EXT:
+ case GL_TEXTURE_SWIZZLE_B_EXT:
+ case GL_TEXTURE_SWIZZLE_A_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
+ *params = (GLfloat) obj->Swizzle[comp];
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+
+ case GL_TEXTURE_SWIZZLE_RGBA_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ GLuint comp;
+ for (comp = 0; comp < 4; comp++) {
+ params[comp] = (GLfloat) obj->Swizzle[comp];
+ }
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+
default:
- error = 1;
+ error = GL_TRUE;
break;
}
+
if (error)
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
pname);
@@ -924,6 +1115,7 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
{
struct gl_texture_unit *texUnit;
struct gl_texture_object *obj;
+ GLboolean error = GL_FALSE;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -933,7 +1125,7 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
return;
}
- texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texUnit = _mesa_get_current_tex_unit(ctx);
obj = _mesa_select_tex_object(ctx, texUnit, target);
if (!obj) {
@@ -944,19 +1136,19 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
switch (pname) {
case GL_TEXTURE_MAG_FILTER:
*params = (GLint) obj->MagFilter;
- return;
+ break;;
case GL_TEXTURE_MIN_FILTER:
*params = (GLint) obj->MinFilter;
- return;
+ break;;
case GL_TEXTURE_WRAP_S:
*params = (GLint) obj->WrapS;
- return;
+ break;;
case GL_TEXTURE_WRAP_T:
*params = (GLint) obj->WrapT;
- return;
+ break;;
case GL_TEXTURE_WRAP_R:
*params = (GLint) obj->WrapR;
- return;
+ break;;
case GL_TEXTURE_BORDER_COLOR:
{
GLfloat b[4];
@@ -969,7 +1161,7 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
params[2] = FLOAT_TO_INT(b[2]);
params[3] = FLOAT_TO_INT(b[3]);
}
- return;
+ break;;
case GL_TEXTURE_RESIDENT:
{
GLboolean resident;
@@ -979,74 +1171,76 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
resident = GL_TRUE;
*params = (GLint) resident;
}
- return;
+ break;;
case GL_TEXTURE_PRIORITY:
*params = FLOAT_TO_INT(obj->Priority);
- return;
+ break;;
case GL_TEXTURE_MIN_LOD:
*params = (GLint) obj->MinLod;
- return;
+ break;;
case GL_TEXTURE_MAX_LOD:
*params = (GLint) obj->MaxLod;
- return;
+ break;;
case GL_TEXTURE_BASE_LEVEL:
*params = obj->BaseLevel;
- return;
+ break;;
case GL_TEXTURE_MAX_LEVEL:
*params = obj->MaxLevel;
- return;
+ break;;
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
if (ctx->Extensions.EXT_texture_filter_anisotropic) {
*params = (GLint) obj->MaxAnisotropy;
- return;
}
- break;
- case GL_TEXTURE_COMPARE_SGIX:
- if (ctx->Extensions.SGIX_shadow) {
- *params = (GLint) obj->CompareFlag;
- return;
+ else {
+ error = GL_TRUE;
}
break;
- case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
- if (ctx->Extensions.SGIX_shadow) {
- *params = (GLint) obj->CompareOperator;
- return;
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ if (ctx->Extensions.ARB_shadow_ambient) {
+ *params = (GLint) FLOAT_TO_INT(obj->CompareFailValue);
}
- break;
- case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
- if (ctx->Extensions.SGIX_shadow_ambient) {
- *params = (GLint) FLOAT_TO_INT(obj->ShadowAmbient);
- return;
+ else {
+ error = GL_TRUE;
}
break;
case GL_GENERATE_MIPMAP_SGIS:
if (ctx->Extensions.SGIS_generate_mipmap) {
*params = (GLint) obj->GenerateMipmap;
- return;
+ }
+ else {
+ error = GL_TRUE;
}
break;
case GL_TEXTURE_COMPARE_MODE_ARB:
if (ctx->Extensions.ARB_shadow) {
*params = (GLint) obj->CompareMode;
- return;
+ }
+ else {
+ error = GL_TRUE;
}
break;
case GL_TEXTURE_COMPARE_FUNC_ARB:
if (ctx->Extensions.ARB_shadow) {
*params = (GLint) obj->CompareFunc;
- return;
+ }
+ else {
+ error = GL_TRUE;
}
break;
case GL_DEPTH_TEXTURE_MODE_ARB:
if (ctx->Extensions.ARB_depth_texture) {
*params = (GLint) obj->DepthMode;
- return;
+ }
+ else {
+ error = GL_TRUE;
}
break;
case GL_TEXTURE_LOD_BIAS:
if (ctx->Extensions.EXT_texture_lod_bias) {
*params = (GLint) obj->LodBias;
- return;
+ }
+ else {
+ error = GL_TRUE;
}
break;
#ifdef FEATURE_OES_draw_texture
@@ -1057,9 +1251,35 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
params[3] = obj->CropRect[3];
break;
#endif
+ case GL_TEXTURE_SWIZZLE_R_EXT:
+ case GL_TEXTURE_SWIZZLE_G_EXT:
+ case GL_TEXTURE_SWIZZLE_B_EXT:
+ case GL_TEXTURE_SWIZZLE_A_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
+ *params = obj->Swizzle[comp];
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+
+ case GL_TEXTURE_SWIZZLE_RGBA_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ COPY_4V(params, obj->Swizzle);
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+
default:
; /* silence warnings */
}
- /* If we get here, pname was an unrecognized enum */
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
+
+ if (error)
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)",
+ pname);
+
+ _mesa_unlock_texture(ctx, obj);
}
diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c
index 4ae13a7b9b..cc74d58fbd 100644
--- a/src/mesa/main/texrender.c
+++ b/src/mesa/main/texrender.c
@@ -194,6 +194,59 @@ texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
}
}
+/**
+ * Put row of RGB values into a renderbuffer that wraps a texture image.
+ */
+static void
+texture_put_row_rgb(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ const struct texture_renderbuffer *trb
+ = (const struct texture_renderbuffer *) rb;
+ const GLint z = trb->Zoffset;
+ GLuint i;
+
+ y += trb->Yoffset;
+
+ if (rb->DataType == CHAN_TYPE) {
+ const GLchan *rgb = (const GLchan *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, rgb);
+ }
+ rgb += 3;
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLushort *zValues = (const GLushort *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ const GLuint *zValues = (const GLuint *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+ const GLuint *zValues = (const GLuint *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
+ trb->Store(trb->TexImage, x + i, y, z, &flt);
+ }
+ }
+ }
+ else {
+ _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
+ }
+}
+
static void
texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
@@ -380,6 +433,7 @@ wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
trb->Base.GetRow = texture_get_row;
trb->Base.GetValues = texture_get_values;
trb->Base.PutRow = texture_put_row;
+ trb->Base.PutRowRGB = texture_put_row_rgb;
trb->Base.PutMonoRow = texture_put_mono_row;
trb->Base.PutValues = texture_put_values;
trb->Base.PutMonoValues = texture_put_mono_values;
@@ -453,6 +507,7 @@ update_wrapper(GLcontext *ctx, const struct gl_renderbuffer_attachment *att)
trb->Base.BlueBits = trb->TexImage->TexFormat->BlueBits;
trb->Base.AlphaBits = trb->TexImage->TexFormat->AlphaBits;
trb->Base.DepthBits = trb->TexImage->TexFormat->DepthBits;
+ trb->Base.StencilBits = trb->TexImage->TexFormat->StencilBits;
}
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 9bfb7e0ec2..b9311d0ffc 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.5
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
@@ -29,10 +29,9 @@
*/
#include "glheader.h"
+#include "mfeatures.h"
#include "colormac.h"
-#if FEATURE_colortable
#include "colortab.h"
-#endif
#include "context.h"
#include "enums.h"
#include "macros.h"
@@ -42,7 +41,6 @@
#include "texstate.h"
#include "texenvprogram.h"
#include "mtypes.h"
-#include "math/m_xform.h"
@@ -53,10 +51,10 @@
*/
static const struct gl_tex_env_combine_state default_combine_state = {
GL_MODULATE, GL_MODULATE,
- { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
- { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
- { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA },
- { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
+ { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
+ { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
+ { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_ALPHA },
+ { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
0, 0,
2, 2
};
@@ -69,7 +67,7 @@ static const struct gl_tex_env_combine_state default_combine_state = {
void
_mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
{
- GLuint i;
+ GLuint u, tex;
ASSERT(src);
ASSERT(dst);
@@ -81,57 +79,32 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
dst->Texture.SharedPalette = src->Texture.SharedPalette;
/* per-unit state */
- for (i = 0; i < src->Const.MaxTextureImageUnits; i++) {
- dst->Texture.Unit[i].Enabled = src->Texture.Unit[i].Enabled;
- dst->Texture.Unit[i].EnvMode = src->Texture.Unit[i].EnvMode;
- COPY_4V(dst->Texture.Unit[i].EnvColor, src->Texture.Unit[i].EnvColor);
- dst->Texture.Unit[i].TexGenEnabled = src->Texture.Unit[i].TexGenEnabled;
- dst->Texture.Unit[i].GenModeS = src->Texture.Unit[i].GenModeS;
- dst->Texture.Unit[i].GenModeT = src->Texture.Unit[i].GenModeT;
- dst->Texture.Unit[i].GenModeR = src->Texture.Unit[i].GenModeR;
- dst->Texture.Unit[i].GenModeQ = src->Texture.Unit[i].GenModeQ;
- dst->Texture.Unit[i]._GenBitS = src->Texture.Unit[i]._GenBitS;
- dst->Texture.Unit[i]._GenBitT = src->Texture.Unit[i]._GenBitT;
- dst->Texture.Unit[i]._GenBitR = src->Texture.Unit[i]._GenBitR;
- dst->Texture.Unit[i]._GenBitQ = src->Texture.Unit[i]._GenBitQ;
- dst->Texture.Unit[i]._GenFlags = src->Texture.Unit[i]._GenFlags;
- COPY_4V(dst->Texture.Unit[i].ObjectPlaneS, src->Texture.Unit[i].ObjectPlaneS);
- COPY_4V(dst->Texture.Unit[i].ObjectPlaneT, src->Texture.Unit[i].ObjectPlaneT);
- COPY_4V(dst->Texture.Unit[i].ObjectPlaneR, src->Texture.Unit[i].ObjectPlaneR);
- COPY_4V(dst->Texture.Unit[i].ObjectPlaneQ, src->Texture.Unit[i].ObjectPlaneQ);
- COPY_4V(dst->Texture.Unit[i].EyePlaneS, src->Texture.Unit[i].EyePlaneS);
- COPY_4V(dst->Texture.Unit[i].EyePlaneT, src->Texture.Unit[i].EyePlaneT);
- COPY_4V(dst->Texture.Unit[i].EyePlaneR, src->Texture.Unit[i].EyePlaneR);
- COPY_4V(dst->Texture.Unit[i].EyePlaneQ, src->Texture.Unit[i].EyePlaneQ);
- dst->Texture.Unit[i].LodBias = src->Texture.Unit[i].LodBias;
+ for (u = 0; u < src->Const.MaxTextureImageUnits; u++) {
+ dst->Texture.Unit[u].Enabled = src->Texture.Unit[u].Enabled;
+ dst->Texture.Unit[u].EnvMode = src->Texture.Unit[u].EnvMode;
+ COPY_4V(dst->Texture.Unit[u].EnvColor, src->Texture.Unit[u].EnvColor);
+ dst->Texture.Unit[u].TexGenEnabled = src->Texture.Unit[u].TexGenEnabled;
+ dst->Texture.Unit[u].GenS = src->Texture.Unit[u].GenS;
+ dst->Texture.Unit[u].GenT = src->Texture.Unit[u].GenT;
+ dst->Texture.Unit[u].GenR = src->Texture.Unit[u].GenR;
+ dst->Texture.Unit[u].GenQ = src->Texture.Unit[u].GenQ;
+ dst->Texture.Unit[u].LodBias = src->Texture.Unit[u].LodBias;
/* GL_EXT_texture_env_combine */
- dst->Texture.Unit[i].Combine.ModeRGB = src->Texture.Unit[i].Combine.ModeRGB;
- dst->Texture.Unit[i].Combine.ModeA = src->Texture.Unit[i].Combine.ModeA;
- COPY_3V(dst->Texture.Unit[i].Combine.SourceRGB, src->Texture.Unit[i].Combine.SourceRGB);
- COPY_3V(dst->Texture.Unit[i].Combine.SourceA, src->Texture.Unit[i].Combine.SourceA);
- COPY_3V(dst->Texture.Unit[i].Combine.OperandRGB, src->Texture.Unit[i].Combine.OperandRGB);
- COPY_3V(dst->Texture.Unit[i].Combine.OperandA, src->Texture.Unit[i].Combine.OperandA);
- dst->Texture.Unit[i].Combine.ScaleShiftRGB = src->Texture.Unit[i].Combine.ScaleShiftRGB;
- dst->Texture.Unit[i].Combine.ScaleShiftA = src->Texture.Unit[i].Combine.ScaleShiftA;
+ dst->Texture.Unit[u].Combine = src->Texture.Unit[u].Combine;
+
+ /* GL_ATI_envmap_bumpmap - need this? */
+ dst->Texture.Unit[u].BumpTarget = src->Texture.Unit[u].BumpTarget;
+ COPY_4V(dst->Texture.Unit[u].RotMatrix, src->Texture.Unit[u].RotMatrix);
+
/* copy texture object bindings, not contents of texture objects */
_mesa_lock_context_textures(dst);
- _mesa_reference_texobj(&dst->Texture.Unit[i].Current1D,
- src->Texture.Unit[i].Current1D);
- _mesa_reference_texobj(&dst->Texture.Unit[i].Current2D,
- src->Texture.Unit[i].Current2D);
- _mesa_reference_texobj(&dst->Texture.Unit[i].Current3D,
- src->Texture.Unit[i].Current3D);
- _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentCubeMap,
- src->Texture.Unit[i].CurrentCubeMap);
- _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentRect,
- src->Texture.Unit[i].CurrentRect);
- _mesa_reference_texobj(&dst->Texture.Unit[i].Current1DArray,
- src->Texture.Unit[i].Current1DArray);
- _mesa_reference_texobj(&dst->Texture.Unit[i].Current2DArray,
- src->Texture.Unit[i].Current2DArray);
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&dst->Texture.Unit[u].CurrentTex[tex],
+ src->Texture.Unit[u].CurrentTex[tex]);
+ }
_mesa_unlock_context_textures(dst);
}
@@ -204,11 +177,14 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
case GL_LUMINANCE:
case GL_RGB:
case GL_YCBCR_MESA:
+ case GL_DUDV_ATI:
state->SourceA[0] = GL_PREVIOUS;
break;
default:
- _mesa_problem(NULL, "Invalid texBaseFormat in calculate_derived_texenv");
+ _mesa_problem(NULL,
+ "Invalid texBaseFormat 0x%x in calculate_derived_texenv",
+ texBaseFormat);
return;
}
@@ -241,6 +217,7 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
break;
case GL_RGB:
case GL_YCBCR_MESA:
+ case GL_DUDV_ATI:
mode_rgb = GL_REPLACE;
break;
case GL_RGBA:
@@ -267,6 +244,7 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
case GL_LUMINANCE_ALPHA:
case GL_RGBA:
case GL_YCBCR_MESA:
+ case GL_DUDV_ATI:
state->SourceRGB[2] = GL_TEXTURE;
state->SourceA[2] = GL_TEXTURE;
state->SourceRGB[0] = GL_CONSTANT;
@@ -282,7 +260,8 @@ calculate_derived_texenv( struct gl_tex_env_combine_state *state,
default:
_mesa_problem(NULL,
- "Invalid texture env mode in calculate_derived_texenv");
+ "Invalid texture env mode 0x%x in calculate_derived_texenv",
+ mode);
return;
}
@@ -364,84 +343,119 @@ _mesa_ClientActiveTextureARB(GLenum texture)
static void
update_texture_matrices( GLcontext *ctx )
{
- GLuint i;
+ GLuint u;
- ctx->Texture._TexMatEnabled = 0;
+ ctx->Texture._TexMatEnabled = 0x0;
- for (i=0; i < ctx->Const.MaxTextureCoordUnits; i++) {
- if (_math_matrix_is_dirty(ctx->TextureMatrixStack[i].Top)) {
- _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
+ for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
+ if (_math_matrix_is_dirty(ctx->TextureMatrixStack[u].Top)) {
+ _math_matrix_analyse( ctx->TextureMatrixStack[u].Top );
- if (ctx->Texture.Unit[i]._ReallyEnabled &&
- ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
- ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
+ if (ctx->Texture.Unit[u]._ReallyEnabled &&
+ ctx->TextureMatrixStack[u].Top->type != MATRIX_IDENTITY)
+ ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(u);
if (ctx->Driver.TextureMatrix)
- ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
+ ctx->Driver.TextureMatrix( ctx, u, ctx->TextureMatrixStack[u].Top);
}
}
}
/**
- * Update texture object's _Function field. We need to do this
- * whenever any of the texture object's shadow-related fields change
- * or when we start/stop using a fragment program.
- *
- * This function could be expanded someday to update additional per-object
- * fields that depend on assorted state changes.
+ * Examine texture unit's combine/env state to update derived state.
*/
static void
-update_texture_compare_function(GLcontext *ctx,
- struct gl_texture_object *tObj)
+update_tex_combine(GLcontext *ctx, struct gl_texture_unit *texUnit)
{
- /* XXX temporarily disable this test since it breaks the GLSL
- * shadow2D(), etc. functions.
+ struct gl_tex_env_combine_state *combine;
+
+ /* Set the texUnit->_CurrentCombine field to point to the user's combiner
+ * state, or the combiner state which is derived from traditional texenv
+ * mode.
*/
- if (0 /*ctx->FragmentProgram._Current*/) {
- /* Texel/coordinate comparison is ignored for programs.
- * See GL_ARB_fragment_program/shader spec for details.
- */
- tObj->_Function = GL_NONE;
+ if (texUnit->EnvMode == GL_COMBINE ||
+ texUnit->EnvMode == GL_COMBINE4_NV) {
+ texUnit->_CurrentCombine = & texUnit->Combine;
}
- else if (tObj->CompareFlag) {
- /* GL_SGIX_shadow */
- if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
- tObj->_Function = GL_LEQUAL;
+ else {
+ const struct gl_texture_object *texObj = texUnit->_Current;
+ GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
+ if (format == GL_COLOR_INDEX) {
+ format = GL_RGBA; /* a bit of a hack */
}
- else {
- ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX);
- tObj->_Function = GL_GEQUAL;
+ else if (format == GL_DEPTH_COMPONENT ||
+ format == GL_DEPTH_STENCIL_EXT) {
+ format = texObj->DepthMode;
}
+ calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
+ texUnit->_CurrentCombine = & texUnit->_EnvMode;
}
- else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
- /* GL_ARB_shadow */
- tObj->_Function = tObj->CompareFunc;
- }
- else {
- tObj->_Function = GL_NONE; /* pass depth through as grayscale */
- }
-}
+ combine = texUnit->_CurrentCombine;
-/**
- * Helper function for determining which texture object (1D, 2D, cube, etc)
- * should actually be used.
- */
-static void
-texture_override(GLcontext *ctx,
- struct gl_texture_unit *texUnit, GLbitfield enableBits,
- struct gl_texture_object *texObj, GLuint textureBit)
-{
- if (!texUnit->_ReallyEnabled && (enableBits & textureBit)) {
- if (!texObj->_Complete) {
- _mesa_test_texobj_completeness(ctx, texObj);
- }
- if (texObj->_Complete) {
- texUnit->_ReallyEnabled = textureBit;
- texUnit->_Current = texObj;
- update_texture_compare_function(ctx, texObj);
- }
+ /* Determine number of source RGB terms in the combiner function */
+ switch (combine->ModeRGB) {
+ case GL_REPLACE:
+ combine->_NumArgsRGB = 1;
+ break;
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ if (texUnit->EnvMode == GL_COMBINE4_NV)
+ combine->_NumArgsRGB = 4;
+ else
+ combine->_NumArgsRGB = 2;
+ break;
+ case GL_MODULATE:
+ case GL_SUBTRACT:
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
+ case GL_DOT3_RGB_EXT:
+ case GL_DOT3_RGBA_EXT:
+ combine->_NumArgsRGB = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ combine->_NumArgsRGB = 3;
+ break;
+ case GL_BUMP_ENVMAP_ATI:
+ /* no real arguments for this case */
+ combine->_NumArgsRGB = 0;
+ break;
+ default:
+ combine->_NumArgsRGB = 0;
+ _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
+ return;
+ }
+
+ /* Determine number of source Alpha terms in the combiner function */
+ switch (combine->ModeA) {
+ case GL_REPLACE:
+ combine->_NumArgsA = 1;
+ break;
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ if (texUnit->EnvMode == GL_COMBINE4_NV)
+ combine->_NumArgsA = 4;
+ else
+ combine->_NumArgsA = 2;
+ break;
+ case GL_MODULATE:
+ case GL_SUBTRACT:
+ combine->_NumArgsA = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ combine->_NumArgsA = 3;
+ break;
+ default:
+ combine->_NumArgsA = 0;
+ _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
+ break;
}
}
@@ -460,6 +474,7 @@ update_texture_state( GLcontext *ctx )
GLuint unit;
struct gl_fragment_program *fprog = NULL;
struct gl_vertex_program *vprog = NULL;
+ GLbitfield enabledFragUnits = 0x0;
if (ctx->Shader.CurrentProgram &&
ctx->Shader.CurrentProgram->LinkStatus) {
@@ -478,145 +493,98 @@ update_texture_state( GLcontext *ctx )
}
}
- ctx->NewState |= _NEW_TEXTURE; /* TODO: only set this if there are
- * actual changes.
- */
+ /* TODO: only set this if there are actual changes */
+ ctx->NewState |= _NEW_TEXTURE;
- ctx->Texture._EnabledUnits = 0;
- ctx->Texture._GenFlags = 0;
- ctx->Texture._TexMatEnabled = 0;
- ctx->Texture._TexGenEnabled = 0;
+ ctx->Texture._EnabledUnits = 0x0;
+ ctx->Texture._GenFlags = 0x0;
+ ctx->Texture._TexMatEnabled = 0x0;
+ ctx->Texture._TexGenEnabled = 0x0;
/*
* Update texture unit state.
*/
for (unit = 0; unit < ctx->Const.MaxTextureImageUnits; unit++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- GLbitfield enableBits;
+ GLbitfield enabledVertTargets = 0x0;
+ GLbitfield enabledFragTargets = 0x0;
+ GLbitfield enabledTargets = 0x0;
+ GLuint texIndex;
- texUnit->_Current = NULL;
- texUnit->_ReallyEnabled = 0;
- texUnit->_GenFlags = 0;
-
- /* Get the bitmask of texture enables.
+ /* Get the bitmask of texture target enables.
* enableBits will be a mask of the TEXTURE_*_BIT flags indicating
* which texture targets are enabled (fixed function) or referenced
* by a fragment shader/program. When multiple flags are set, we'll
- * settle on the one with highest priority (see texture_override below).
+ * settle on the one with highest priority (see below).
*/
- if (fprog || vprog) {
- enableBits = 0x0;
- if (fprog)
- enableBits |= fprog->Base.TexturesUsed[unit];
- if (vprog)
- enableBits |= vprog->Base.TexturesUsed[unit];
+ if (vprog) {
+ enabledVertTargets |= vprog->Base.TexturesUsed[unit];
+ }
+
+ if (fprog) {
+ enabledFragTargets |= fprog->Base.TexturesUsed[unit];
}
else {
- if (!texUnit->Enabled)
- continue;
- enableBits = texUnit->Enabled;
+ /* fixed-function fragment program */
+ enabledFragTargets |= texUnit->Enabled;
}
- ASSERT(texUnit->Current1D);
- ASSERT(texUnit->Current2D);
- ASSERT(texUnit->Current3D);
- ASSERT(texUnit->CurrentCubeMap);
- ASSERT(texUnit->CurrentRect);
- ASSERT(texUnit->Current1DArray);
- ASSERT(texUnit->Current2DArray);
-
- /* Look for the highest-priority texture target that's enabled and
- * complete. That's the one we'll use for texturing. If we're using
- * a fragment program we're guaranteed that bitcount(enabledBits) <= 1.
- */
- texture_override(ctx, texUnit, enableBits,
- texUnit->Current2DArray, TEXTURE_2D_ARRAY_BIT);
- texture_override(ctx, texUnit, enableBits,
- texUnit->Current1DArray, TEXTURE_1D_ARRAY_BIT);
- texture_override(ctx, texUnit, enableBits,
- texUnit->CurrentCubeMap, TEXTURE_CUBE_BIT);
- texture_override(ctx, texUnit, enableBits,
- texUnit->Current3D, TEXTURE_3D_BIT);
- texture_override(ctx, texUnit, enableBits,
- texUnit->CurrentRect, TEXTURE_RECT_BIT);
- texture_override(ctx, texUnit, enableBits,
- texUnit->Current2D, TEXTURE_2D_BIT);
- texture_override(ctx, texUnit, enableBits,
- texUnit->Current1D, TEXTURE_1D_BIT);
+ enabledTargets = enabledVertTargets | enabledFragTargets;
- if (!texUnit->_ReallyEnabled) {
+ texUnit->_ReallyEnabled = 0x0;
+
+ if (enabledTargets == 0x0) {
+ /* neither vertex nor fragment processing uses this unit */
continue;
}
- if (texUnit->_ReallyEnabled)
- ctx->Texture._EnabledUnits |= (1 << unit);
-
- if (texUnit->EnvMode == GL_COMBINE) {
- texUnit->_CurrentCombine = & texUnit->Combine;
+ /* Look for the highest priority texture target that's enabled (or used
+ * by the vert/frag shaders) and "complete". That's the one we'll use
+ * for texturing. If we're using vert/frag program we're guaranteed
+ * that bitcount(enabledBits) <= 1.
+ * Note that the TEXTURE_x_INDEX values are in high to low priority.
+ */
+ for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
+ if (enabledTargets & (1 << texIndex)) {
+ struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
+ if (!texObj->_Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->_Complete) {
+ texUnit->_ReallyEnabled = 1 << texIndex;
+ _mesa_reference_texobj(&texUnit->_Current, texObj);
+ break;
+ }
+ }
}
- else {
- const struct gl_texture_object *texObj = texUnit->_Current;
- GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
- if (format == GL_COLOR_INDEX) {
- format = GL_RGBA; /* a bit of a hack */
+
+ if (!texUnit->_ReallyEnabled) {
+ if (fprog) {
+ /* If we get here it means the shader is expecting a texture
+ * object, but there isn't one (or it's incomplete). Use the
+ * fallback texture.
+ */
+ struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
+ texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
+ _mesa_reference_texobj(&texUnit->_Current, texObj);
}
- else if (format == GL_DEPTH_COMPONENT
- || format == GL_DEPTH_STENCIL_EXT) {
- format = texObj->DepthMode;
+ else {
+ /* fixed-function: texture unit is really disabled */
+ continue;
}
- calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
- texUnit->_CurrentCombine = & texUnit->_EnvMode;
}
- switch (texUnit->_CurrentCombine->ModeRGB) {
- case GL_REPLACE:
- texUnit->_CurrentCombine->_NumArgsRGB = 1;
- break;
- case GL_MODULATE:
- case GL_ADD:
- case GL_ADD_SIGNED:
- case GL_SUBTRACT:
- case GL_DOT3_RGB:
- case GL_DOT3_RGBA:
- case GL_DOT3_RGB_EXT:
- case GL_DOT3_RGBA_EXT:
- texUnit->_CurrentCombine->_NumArgsRGB = 2;
- break;
- case GL_INTERPOLATE:
- case GL_MODULATE_ADD_ATI:
- case GL_MODULATE_SIGNED_ADD_ATI:
- case GL_MODULATE_SUBTRACT_ATI:
- texUnit->_CurrentCombine->_NumArgsRGB = 3;
- break;
- default:
- texUnit->_CurrentCombine->_NumArgsRGB = 0;
- _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
- return;
- }
+ /* if we get here, we know this texture unit is enabled */
- switch (texUnit->_CurrentCombine->ModeA) {
- case GL_REPLACE:
- texUnit->_CurrentCombine->_NumArgsA = 1;
- break;
- case GL_MODULATE:
- case GL_ADD:
- case GL_ADD_SIGNED:
- case GL_SUBTRACT:
- texUnit->_CurrentCombine->_NumArgsA = 2;
- break;
- case GL_INTERPOLATE:
- case GL_MODULATE_ADD_ATI:
- case GL_MODULATE_SIGNED_ADD_ATI:
- case GL_MODULATE_SUBTRACT_ATI:
- texUnit->_CurrentCombine->_NumArgsA = 3;
- break;
- default:
- texUnit->_CurrentCombine->_NumArgsA = 0;
- _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
- break;
- }
+ ctx->Texture._EnabledUnits |= (1 << unit);
+
+ if (enabledFragTargets)
+ enabledFragUnits |= (1 << unit);
+
+ update_tex_combine(ctx, texUnit);
}
+
/* Determine which texture coordinate sets are actually needed */
if (fprog) {
const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
@@ -624,28 +592,30 @@ update_texture_state( GLcontext *ctx )
= (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
}
else {
- ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
+ ctx->Texture._EnabledCoordUnits = enabledFragUnits;
}
/* Setup texgen for those texture coordinate sets that are in use */
for (unit = 0; unit < ctx->Const.MaxTextureCoordUnits; unit++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ texUnit->_GenFlags = 0x0;
+
if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
continue;
if (texUnit->TexGenEnabled) {
if (texUnit->TexGenEnabled & S_BIT) {
- texUnit->_GenFlags |= texUnit->_GenBitS;
+ texUnit->_GenFlags |= texUnit->GenS._ModeBit;
}
if (texUnit->TexGenEnabled & T_BIT) {
- texUnit->_GenFlags |= texUnit->_GenBitT;
- }
- if (texUnit->TexGenEnabled & Q_BIT) {
- texUnit->_GenFlags |= texUnit->_GenBitQ;
+ texUnit->_GenFlags |= texUnit->GenT._ModeBit;
}
if (texUnit->TexGenEnabled & R_BIT) {
- texUnit->_GenFlags |= texUnit->_GenBitR;
+ texUnit->_GenFlags |= texUnit->GenR._ModeBit;
+ }
+ if (texUnit->TexGenEnabled & Q_BIT) {
+ texUnit->_GenFlags |= texUnit->GenQ._ModeBit;
}
ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
@@ -728,6 +698,7 @@ static void
init_texture_unit( GLcontext *ctx, GLuint unit )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLuint tex;
texUnit->EnvMode = GL_MODULATE;
ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
@@ -735,35 +706,36 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
texUnit->Combine = default_combine_state;
texUnit->_EnvMode = default_combine_state;
texUnit->_CurrentCombine = & texUnit->_EnvMode;
-
- texUnit->TexGenEnabled = 0;
- texUnit->GenModeS = GL_EYE_LINEAR;
- texUnit->GenModeT = GL_EYE_LINEAR;
- texUnit->GenModeR = GL_EYE_LINEAR;
- texUnit->GenModeQ = GL_EYE_LINEAR;
- texUnit->_GenBitS = TEXGEN_EYE_LINEAR;
- texUnit->_GenBitT = TEXGEN_EYE_LINEAR;
- texUnit->_GenBitR = TEXGEN_EYE_LINEAR;
- texUnit->_GenBitQ = TEXGEN_EYE_LINEAR;
+ texUnit->BumpTarget = GL_TEXTURE0;
+
+ texUnit->TexGenEnabled = 0x0;
+ texUnit->GenS.Mode = GL_EYE_LINEAR;
+ texUnit->GenT.Mode = GL_EYE_LINEAR;
+ texUnit->GenR.Mode = GL_EYE_LINEAR;
+ texUnit->GenQ.Mode = GL_EYE_LINEAR;
+ texUnit->GenS._ModeBit = TEXGEN_EYE_LINEAR;
+ texUnit->GenT._ModeBit = TEXGEN_EYE_LINEAR;
+ texUnit->GenR._ModeBit = TEXGEN_EYE_LINEAR;
+ texUnit->GenQ._ModeBit = TEXGEN_EYE_LINEAR;
/* Yes, these plane coefficients are correct! */
- ASSIGN_4V( texUnit->ObjectPlaneS, 1.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->ObjectPlaneT, 0.0, 1.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->ObjectPlaneR, 0.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->ObjectPlaneQ, 0.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->EyePlaneS, 1.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->EyePlaneT, 0.0, 1.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
+
+ /* no mention of this in spec, but maybe id matrix expected? */
+ ASSIGN_4V( texUnit->RotMatrix, 1.0, 0.0, 0.0, 1.0 );
/* initialize current texture object ptrs to the shared default objects */
- _mesa_reference_texobj(&texUnit->Current1D, ctx->Shared->Default1D);
- _mesa_reference_texobj(&texUnit->Current2D, ctx->Shared->Default2D);
- _mesa_reference_texobj(&texUnit->Current3D, ctx->Shared->Default3D);
- _mesa_reference_texobj(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
- _mesa_reference_texobj(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
- _mesa_reference_texobj(&texUnit->Current1DArray, ctx->Shared->Default1DArray);
- _mesa_reference_texobj(&texUnit->Current2DArray, ctx->Shared->Default2DArray);
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&texUnit->CurrentTex[tex],
+ ctx->Shared->DefaultTex[tex]);
+ }
}
@@ -773,26 +745,22 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
GLboolean
_mesa_init_texture(GLcontext *ctx)
{
- GLuint i;
-
- assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
- assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
+ GLuint u;
/* Texture group */
ctx->Texture.CurrentUnit = 0; /* multitexture */
- ctx->Texture._EnabledUnits = 0;
+ ctx->Texture._EnabledUnits = 0x0;
ctx->Texture.SharedPalette = GL_FALSE;
-#if FEATURE_colortable
_mesa_init_colortable(&ctx->Texture.Palette);
-#endif
- for (i = 0; i < MAX_TEXTURE_UNITS; i++)
- init_texture_unit( ctx, i );
+ for (u = 0; u < MAX_TEXTURE_UNITS; u++)
+ init_texture_unit(ctx, u);
/* After we're done initializing the context's texture state the default
* texture objects' refcounts should be at least MAX_TEXTURE_UNITS + 1.
*/
- assert(ctx->Shared->Default1D->RefCount >= MAX_TEXTURE_UNITS + 1);
+ assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount
+ >= MAX_TEXTURE_UNITS + 1);
/* Allocate proxy textures */
if (!alloc_proxy_textures( ctx ))
@@ -812,27 +780,20 @@ _mesa_free_texture_data(GLcontext *ctx)
/* unreference current textures */
for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
- struct gl_texture_unit *unit = ctx->Texture.Unit + u;
- _mesa_reference_texobj(&unit->Current1D, NULL);
- _mesa_reference_texobj(&unit->Current2D, NULL);
- _mesa_reference_texobj(&unit->Current3D, NULL);
- _mesa_reference_texobj(&unit->CurrentCubeMap, NULL);
- _mesa_reference_texobj(&unit->CurrentRect, NULL);
- _mesa_reference_texobj(&unit->Current1DArray, NULL);
- _mesa_reference_texobj(&unit->Current2DArray, NULL);
+ /* The _Current texture could account for another reference */
+ _mesa_reference_texobj(&ctx->Texture.Unit[u]._Current, NULL);
+
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&ctx->Texture.Unit[u].CurrentTex[tgt], NULL);
+ }
}
/* Free proxy texture objects */
for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
-#if FEATURE_colortable
- {
- GLuint i;
- for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
- _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
- }
-#endif
+ for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++)
+ _mesa_free_colortable_data(&ctx->Texture.Unit[u].ColorTable);
}
@@ -844,17 +805,13 @@ _mesa_free_texture_data(GLcontext *ctx)
void
_mesa_update_default_objects_texture(GLcontext *ctx)
{
- GLuint i;
-
- for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
- struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
-
- _mesa_reference_texobj(&texUnit->Current1D, ctx->Shared->Default1D);
- _mesa_reference_texobj(&texUnit->Current2D, ctx->Shared->Default2D);
- _mesa_reference_texobj(&texUnit->Current3D, ctx->Shared->Default3D);
- _mesa_reference_texobj(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
- _mesa_reference_texobj(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
- _mesa_reference_texobj(&texUnit->Current1DArray, ctx->Shared->Default1DArray);
- _mesa_reference_texobj(&texUnit->Current2DArray, ctx->Shared->Default2DArray);
+ GLuint u, tex;
+
+ for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&texUnit->CurrentTex[tex],
+ ctx->Shared->DefaultTex[tex]);
+ }
}
}
diff --git a/src/mesa/main/texstate.h b/src/mesa/main/texstate.h
index a7d7088c62..17ac68000c 100644
--- a/src/mesa/main/texstate.h
+++ b/src/mesa/main/texstate.h
@@ -35,6 +35,18 @@
#include "mtypes.h"
+/**
+ * Return pointer to current texture unit.
+ * This the texture unit set by glActiveTexture(), not glClientActiveTexture().
+ */
+static INLINE struct gl_texture_unit *
+_mesa_get_current_tex_unit(GLcontext *ctx)
+{
+ ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->Texture.Unit));
+ return &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
+}
+
+
extern void
_mesa_copy_texture_state( const GLcontext *src, GLcontext *dst );
@@ -48,16 +60,14 @@ _mesa_print_texunit_state( GLcontext *ctx, GLuint unit );
*/
/*@{*/
-
-/*
- * GL_ARB_multitexture
- */
extern void GLAPIENTRY
_mesa_ActiveTextureARB( GLenum target );
extern void GLAPIENTRY
_mesa_ClientActiveTextureARB( GLenum target );
+/*@}*/
+
/**
* \name Initialization, state maintenance
diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c
index 67cfca2565..352c88e673 100644
--- a/src/mesa/main/texstore.c
+++ b/src/mesa/main/texstore.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.3
+ * Version: 7.5
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008-2009 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -55,9 +56,7 @@
#include "bufferobj.h"
#include "colormac.h"
#include "context.h"
-#if FEATURE_convolve
#include "convolve.h"
-#endif
#include "image.h"
#include "macros.h"
#include "mipmap.h"
@@ -271,16 +270,6 @@ compute_component_mapping(GLenum inFormat, GLenum outFormat,
}
-#if !FEATURE_convolve
-static void
-_mesa_adjust_image_for_convolution(GLcontext *ctx, GLuint dims,
- GLsizei *srcWidth, GLsizei *srcHeight)
-{
- /* no-op */
-}
-#endif
-
-
/**
* Make a temporary (color) texture image with GLfloat components.
* Apply all needed pixel unpacking and pixel transfer operations.
@@ -384,7 +373,6 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
convWidth = srcWidth;
convHeight = srcHeight;
-#if FEATURE_convolve
/* do convolution */
{
GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4);
@@ -404,7 +392,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
}
}
}
-#endif
+
/* do post-convolution transfer and pack into tempImage */
{
const GLint logComponents
@@ -561,7 +549,6 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
textureBaseFormat == GL_ALPHA ||
textureBaseFormat == GL_INTENSITY);
-#if FEATURE_convolve
if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
(dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
(dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
@@ -583,7 +570,6 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
transferOps = 0;
freeSrcImage = GL_TRUE;
}
-#endif
/* unpack and transfer the source image */
tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
@@ -797,6 +783,7 @@ static const GLubyte *
type_mapping( GLenum srcType )
{
switch (srcType) {
+ case GL_BYTE:
case GL_UNSIGNED_BYTE:
return map_identity;
case GL_UNSIGNED_INT_8_8_8_8:
@@ -818,6 +805,7 @@ byteswap_mapping( GLboolean swapBytes,
return map_identity;
switch (srcType) {
+ case GL_BYTE:
case GL_UNSIGNED_BYTE:
return map_identity;
case GL_UNSIGNED_INT_8_8_8_8:
@@ -885,8 +873,8 @@ _mesa_swizzle_ubyte_image(GLcontext *ctx,
/* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
- if (srcRowStride == dstRowStride &&
- srcComponents == dstComponents &&
+ if (srcComponents == dstComponents &&
+ srcRowStride == dstRowStride &&
srcRowStride == srcWidth * srcComponents &&
dimensions < 3) {
/* 1 and 2D images only */
@@ -992,6 +980,32 @@ memcpy_texture(GLcontext *ctx,
}
+/**
+ * no-op store
+ */
+GLboolean
+_mesa_texstore_null(TEXSTORE_PARAMS)
+{
+ (void) ctx;
+ (void) dims;
+ (void) baseInternalFormat;
+ (void) dstFormat;
+ (void) dstAddr;
+ (void) dstXoffset;
+ (void) dstYoffset;
+ (void) dstZoffset;
+ (void) dstRowStride;
+ (void) dstImageOffsets;
+ (void) srcWidth;
+ (void) srcHeight;
+ (void) srcDepth;
+ (void) srcFormat;
+ (void) srcType;
+ (void) srcAddr;
+ (void) srcPacking;
+ return GL_TRUE;
+}
+
/**
* Store an image in any of the formats:
@@ -2470,7 +2484,214 @@ _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
return GL_TRUE;
}
+GLboolean
+_mesa_texstore_dudv8(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_dudv8);
+ ASSERT(dstFormat->TexelBytes == 2);
+ ASSERT(ctx->Extensions.ATI_envmap_bumpmap);
+ ASSERT((srcFormat == GL_DU8DV8_ATI) ||
+ (srcFormat == GL_DUDV_ATI));
+ ASSERT(baseInternalFormat == GL_DUDV_ATI);
+ if (!srcPacking->SwapBytes && srcType == GL_BYTE &&
+ littleEndian) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (srcType == GL_BYTE) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if (littleEndian) {
+ dstmap[0] = 0;
+ dstmap[1] = 3;
+ }
+ else {
+ dstmap[0] = 3;
+ dstmap[1] = 0;
+ }
+ dstmap[2] = ZERO; /* ? */
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ GL_LUMINANCE_ALPHA, /* hack */
+ GL_UNSIGNED_BYTE, /* hack */
+ GL_LUMINANCE_ALPHA, /* hack */
+ dstmap, 2,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path - note this is defined for 2d textures only */
+ const GLint components = _mesa_components_in_format(baseInternalFormat);
+ const GLint srcStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLbyte *tempImage, *dst, *src;
+ GLint row;
+
+ tempImage = (GLbyte *) _mesa_malloc(srcWidth * srcHeight * srcDepth
+ * components * sizeof(GLbyte));
+ if (!tempImage)
+ return GL_FALSE;
+
+ src = (GLbyte *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ 0, 0, 0);
+
+ dst = tempImage;
+ for (row = 0; row < srcHeight; row++) {
+ _mesa_unpack_dudv_span_byte(ctx, srcWidth, baseInternalFormat,
+ dst, srcFormat, srcType, src,
+ srcPacking, 0);
+ dst += srcWidth * components;
+ src += srcStride;
+ }
+
+ src = tempImage;
+ dst = (GLbyte *) dstAddr
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ memcpy(dst, src, srcWidth * dstFormat->TexelBytes);
+ dst += dstRowStride;
+ src += srcWidth * dstFormat->TexelBytes;
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+/**
+ * Store a texture in MESA_FORMAT_SIGNED_RGBA8888 or MESA_FORMAT_SIGNED_RGBA8888_REV
+ */
+GLboolean
+_mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_signed_rgba8888 ||
+ dstFormat == &_mesa_texformat_signed_rgba8888_rev);
+ ASSERT(dstFormat->TexelBytes == 4);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_signed_rgba8888 &&
+ baseInternalFormat == GL_RGBA &&
+ ((srcFormat == GL_RGBA && srcType == GL_BYTE && !littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && littleEndian))) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_signed_rgba8888_rev &&
+ baseInternalFormat == GL_RGBA &&
+ ((srcFormat == GL_RGBA && srcType == GL_BYTE && littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && !littleEndian))) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ (srcType == GL_BYTE) &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if ((littleEndian && dstFormat == &_mesa_texformat_signed_rgba8888) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_signed_rgba8888_rev)) {
+ dstmap[3] = 0;
+ dstmap[2] = 1;
+ dstmap[1] = 2;
+ dstmap[0] = 3;
+ }
+ else {
+ dstmap[3] = 3;
+ dstmap[2] = 2;
+ dstmap[1] = 1;
+ dstmap[0] = 0;
+ }
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 4,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLfloat *srcRow = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLuint *dstUI = (GLuint *) dstRow;
+ if (dstFormat == &_mesa_texformat_signed_rgba8888) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
+ srcRow += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888_REV( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
+ srcRow += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
/**
* Store a combined depth/stencil texture image.
@@ -2479,12 +2700,45 @@ GLboolean
_mesa_texstore_z24_s8(TEXSTORE_PARAMS)
{
const GLfloat depthScale = (GLfloat) 0xffffff;
+ const GLint srcRowStride
+ = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
+ / sizeof(GLuint);
+ GLint img, row;
ASSERT(dstFormat == &_mesa_texformat_z24_s8);
- ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT);
- ASSERT(srcType == GL_UNSIGNED_INT_24_8_EXT);
+ ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT);
+ ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT);
- if (ctx->Pixel.DepthScale == 1.0f &&
+ /* In case we only upload depth we need to preserve the stencil */
+ if (srcFormat == GL_DEPTH_COMPONENT) {
+ for (img = 0; img < srcDepth; img++) {
+ GLuint *dstRow = (GLuint *) dstAddr
+ + dstImageOffsets[dstZoffset + img]
+ + dstYoffset * dstRowStride / sizeof(GLuint)
+ + dstXoffset;
+ const GLuint *src
+ = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ img, 0, 0);
+ for (row = 0; row < srcHeight; row++) {
+ GLuint depth[MAX_WIDTH];
+ GLint i;
+ _mesa_unpack_depth_span(ctx, srcWidth,
+ GL_UNSIGNED_INT, /* dst type */
+ depth, /* dst addr */
+ depthScale,
+ srcType, src, srcPacking);
+
+ for (i = 0; i < srcWidth; i++)
+ dstRow[i] = depth[i] << 8 | (dstRow[i] & 0x000000FF);
+
+ src += srcRowStride;
+ dstRow += dstRowStride / sizeof(GLuint);
+ }
+ }
+ }
+ else if (ctx->Pixel.DepthScale == 1.0f &&
ctx->Pixel.DepthBias == 0.0f &&
!srcPacking->SwapBytes) {
/* simple path */
@@ -2769,7 +3023,6 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
GLboolean
_mesa_texstore_srgb8(TEXSTORE_PARAMS)
{
- const GLboolean littleEndian = _mesa_little_endian();
const struct gl_texture_format *newDstFormat;
StoreTexImageFunc store;
GLboolean k;
@@ -2777,14 +3030,8 @@ _mesa_texstore_srgb8(TEXSTORE_PARAMS)
ASSERT(dstFormat == &_mesa_texformat_srgb8);
/* reuse normal rgb texstore code */
- if (littleEndian) {
- newDstFormat = &_mesa_texformat_bgr888;
- store = _mesa_texstore_bgr888;
- }
- else {
- newDstFormat = &_mesa_texformat_rgb888;
- store = _mesa_texstore_rgb888;
- }
+ newDstFormat = &_mesa_texformat_rgb888;
+ store = _mesa_texstore_rgb888;
k = store(ctx, dims, baseInternalFormat,
newDstFormat, dstAddr,
@@ -2800,17 +3047,13 @@ _mesa_texstore_srgb8(TEXSTORE_PARAMS)
GLboolean
_mesa_texstore_srgba8(TEXSTORE_PARAMS)
{
- const GLboolean littleEndian = _mesa_little_endian();
const struct gl_texture_format *newDstFormat;
GLboolean k;
ASSERT(dstFormat == &_mesa_texformat_srgba8);
/* reuse normal rgba texstore code */
- if (littleEndian)
- newDstFormat = &_mesa_texformat_rgba8888_rev;
- else
- newDstFormat = &_mesa_texformat_rgba8888;
+ newDstFormat = &_mesa_texformat_rgba8888;
k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
newDstFormat, dstAddr,
@@ -2824,6 +3067,28 @@ _mesa_texstore_srgba8(TEXSTORE_PARAMS)
GLboolean
+_mesa_texstore_sargb8(TEXSTORE_PARAMS)
+{
+ const struct gl_texture_format *newDstFormat;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_sargb8);
+
+ /* reuse normal rgba texstore code */
+ newDstFormat = &_mesa_texformat_argb8888;
+
+ k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+
+GLboolean
_mesa_texstore_sl8(TEXSTORE_PARAMS)
{
const struct gl_texture_format *newDstFormat;
@@ -2848,17 +3113,13 @@ _mesa_texstore_sl8(TEXSTORE_PARAMS)
GLboolean
_mesa_texstore_sla8(TEXSTORE_PARAMS)
{
- const GLboolean littleEndian = _mesa_little_endian();
const struct gl_texture_format *newDstFormat;
GLboolean k;
ASSERT(dstFormat == &_mesa_texformat_sla8);
/* reuse normal luminance/alpha texstore code */
- if (littleEndian)
- newDstFormat = &_mesa_texformat_al88;
- else
- newDstFormat = &_mesa_texformat_al88_rev;
+ newDstFormat = &_mesa_texformat_al88;
k = _mesa_texstore_al88(ctx, dims, baseInternalFormat,
newDstFormat, dstAddr,
@@ -2888,7 +3149,7 @@ _mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
{
GLubyte *buf;
- if (unpack->BufferObj->Name == 0) {
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
/* no PBO */
return pixels;
}
@@ -2924,7 +3185,7 @@ _mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
{
GLubyte *buf;
- if (packing->BufferObj->Name == 0) {
+ if (!_mesa_is_bufferobj(packing->BufferObj)) {
/* not using a PBO - return pointer unchanged */
return pixels;
}
@@ -2954,7 +3215,7 @@ void
_mesa_unmap_teximage_pbo(GLcontext *ctx,
const struct gl_pixelstore_attrib *unpack)
{
- if (unpack->BufferObj->Name) {
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
unpack->BufferObj);
}
@@ -3673,252 +3934,3 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
(void) texObj;
(void) texImage;
}
-
-
-
-
-#if FEATURE_EXT_texture_sRGB
-
-/**
- * Test if given texture image is an sRGB format.
- */
-static GLboolean
-is_srgb_teximage(const struct gl_texture_image *texImage)
-{
- switch (texImage->TexFormat->MesaFormat) {
- case MESA_FORMAT_SRGB8:
- case MESA_FORMAT_SRGBA8:
- case MESA_FORMAT_SL8:
- case MESA_FORMAT_SLA8:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-#endif /* FEATURE_EXT_texture_sRGB */
-
-
-/**
- * This is the software fallback for Driver.GetTexImage().
- * All error checking will have been done before this routine is called.
- */
-void
-_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
- GLenum format, GLenum type, GLvoid *pixels,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
-
- if (ctx->Pack.BufferObj->Name) {
- /* Packing texture image into a PBO.
- * Map the (potentially) VRAM-based buffer into our process space so
- * we can write into it with the code below.
- * A hardware driver might use a sophisticated blit to move the
- * texture data to the PBO if the PBO is in VRAM along with the texture.
- */
- GLubyte *buf = (GLubyte *)
- ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
- return;
- }
- /* <pixels> was an offset into the PBO.
- * Now make it a real, client-side pointer inside the mapped region.
- */
- pixels = ADD_POINTERS(buf, pixels);
- }
- else if (!pixels) {
- /* not an error */
- return;
- }
-
- {
- const GLint width = texImage->Width;
- const GLint height = texImage->Height;
- const GLint depth = texImage->Depth;
- GLint img, row;
- for (img = 0; img < depth; img++) {
- for (row = 0; row < height; row++) {
- /* compute destination address in client memory */
- GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- img, row, 0);
- assert(dest);
-
- if (format == GL_COLOR_INDEX) {
- GLuint indexRow[MAX_WIDTH];
- GLint col;
- /* Can't use FetchTexel here because that returns RGBA */
- if (texImage->TexFormat->IndexBits == 8) {
- const GLubyte *src = (const GLubyte *) texImage->Data;
- src += width * (img * texImage->Height + row);
- for (col = 0; col < width; col++) {
- indexRow[col] = src[col];
- }
- }
- else if (texImage->TexFormat->IndexBits == 16) {
- const GLushort *src = (const GLushort *) texImage->Data;
- src += width * (img * texImage->Height + row);
- for (col = 0; col < width; col++) {
- indexRow[col] = src[col];
- }
- }
- else {
- _mesa_problem(ctx,
- "Color index problem in _mesa_GetTexImage");
- }
- _mesa_pack_index_span(ctx, width, type, dest,
- indexRow, &ctx->Pack,
- 0 /* no image transfer */);
- }
- else if (format == GL_DEPTH_COMPONENT) {
- GLfloat depthRow[MAX_WIDTH];
- GLint col;
- for (col = 0; col < width; col++) {
- (*texImage->FetchTexelf)(texImage, col, row, img,
- depthRow + col);
- }
- _mesa_pack_depth_span(ctx, width, dest, type,
- depthRow, &ctx->Pack);
- }
- else if (format == GL_DEPTH_STENCIL_EXT) {
- /* XXX Note: we're bypassing texImage->FetchTexel()! */
- const GLuint *src = (const GLuint *) texImage->Data;
- src += width * row + width * height * img;
- _mesa_memcpy(dest, src, width * sizeof(GLuint));
- if (ctx->Pack.SwapBytes) {
- _mesa_swap4((GLuint *) dest, width);
- }
- }
- else if (format == GL_YCBCR_MESA) {
- /* No pixel transfer */
- const GLint rowstride = texImage->RowStride;
- MEMCPY(dest,
- (const GLushort *) texImage->Data + row * rowstride,
- width * sizeof(GLushort));
- /* check for byte swapping */
- if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
- && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
- (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
- && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
- if (!ctx->Pack.SwapBytes)
- _mesa_swap2((GLushort *) dest, width);
- }
- else if (ctx->Pack.SwapBytes) {
- _mesa_swap2((GLushort *) dest, width);
- }
- }
-#if FEATURE_EXT_texture_sRGB
- else if (is_srgb_teximage(texImage)) {
- /* no pixel transfer and no non-linear to linear conversion */
- const GLint comps = texImage->TexFormat->TexelBytes;
- const GLint rowstride = comps * texImage->RowStride;
- MEMCPY(dest,
- (const GLubyte *) texImage->Data + row * rowstride,
- comps * width * sizeof(GLubyte));
- }
-#endif /* FEATURE_EXT_texture_sRGB */
- else {
- /* general case: convert row to RGBA format */
- GLfloat rgba[MAX_WIDTH][4];
- GLint col;
- GLbitfield transferOps = 0x0;
-
- if (type == GL_FLOAT &&
- ((ctx->Color.ClampReadColor == GL_TRUE) ||
- (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB &&
- texImage->TexFormat->DataType != GL_FLOAT)))
- transferOps |= IMAGE_CLAMP_BIT;
-
- for (col = 0; col < width; col++) {
- (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
- if (texImage->TexFormat->BaseFormat == GL_ALPHA) {
- rgba[col][RCOMP] = 0.0;
- rgba[col][GCOMP] = 0.0;
- rgba[col][BCOMP] = 0.0;
- }
- else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE) {
- rgba[col][GCOMP] = 0.0;
- rgba[col][BCOMP] = 0.0;
- rgba[col][ACOMP] = 1.0;
- }
- else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE_ALPHA) {
- rgba[col][GCOMP] = 0.0;
- rgba[col][BCOMP] = 0.0;
- }
- else if (texImage->TexFormat->BaseFormat == GL_INTENSITY) {
- rgba[col][GCOMP] = 0.0;
- rgba[col][BCOMP] = 0.0;
- rgba[col][ACOMP] = 1.0;
- }
- }
- _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
- format, type, dest,
- &ctx->Pack, transferOps /*image xfer ops*/);
- } /* format */
- } /* row */
- } /* img */
- }
-
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
-}
-
-
-
-/**
- * This is the software fallback for Driver.GetCompressedTexImage().
- * All error checking will have been done before this routine is called.
- */
-void
-_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
- GLvoid *img,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- GLuint size;
-
- if (ctx->Pack.BufferObj->Name) {
- /* pack texture image into a PBO */
- GLubyte *buf;
- if ((const GLubyte *) img + texImage->CompressedSize >
- (const GLubyte *) ctx->Pack.BufferObj->Size) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImage(invalid PBO access)");
- return;
- }
- buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- GL_WRITE_ONLY_ARB,
- ctx->Pack.BufferObj);
- if (!buf) {
- /* buffer is already mapped - that's an error */
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetCompressedTexImage(PBO is mapped)");
- return;
- }
- img = ADD_POINTERS(buf, img);
- }
- else if (!img) {
- /* not an error */
- return;
- }
-
- /* don't use texImage->CompressedSize since that may be padded out */
- size = _mesa_compressed_texture_size(ctx, texImage->Width, texImage->Height,
- texImage->Depth,
- texImage->TexFormat->MesaFormat);
-
- /* just memcpy, no pixelstore or pixel transfer */
- _mesa_memcpy(img, texImage->Data, size);
-
- if (ctx->Pack.BufferObj->Name) {
- ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
- ctx->Pack.BufferObj);
- }
-}
diff --git a/src/mesa/main/texstore.h b/src/mesa/main/texstore.h
index 951d0a112b..e1b12dfa95 100644
--- a/src/mesa/main/texstore.h
+++ b/src/mesa/main/texstore.h
@@ -3,6 +3,7 @@
* Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -38,6 +39,7 @@
#include "mtypes.h"
+extern GLboolean _mesa_texstore_null(TEXSTORE_PARAMS);
extern GLboolean _mesa_texstore_rgba(TEXSTORE_PARAMS);
extern GLboolean _mesa_texstore_color_index(TEXSTORE_PARAMS);
extern GLboolean _mesa_texstore_rgba8888(TEXSTORE_PARAMS);
@@ -73,10 +75,12 @@ extern GLboolean _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS);
#if FEATURE_EXT_texture_sRGB
extern GLboolean _mesa_texstore_srgb8(TEXSTORE_PARAMS);
extern GLboolean _mesa_texstore_srgba8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_sargb8(TEXSTORE_PARAMS);
extern GLboolean _mesa_texstore_sl8(TEXSTORE_PARAMS);
extern GLboolean _mesa_texstore_sla8(TEXSTORE_PARAMS);
#endif
-
+extern GLboolean _mesa_texstore_dudv8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS);
extern GLchan *
_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
@@ -207,19 +211,6 @@ _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
struct gl_texture_image *texImage);
-extern void
-_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
- GLenum format, GLenum type, GLvoid *pixels,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
-
-extern void
-_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
- GLvoid *img,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage);
-
extern const GLvoid *
_mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
GLsizei width, GLsizei height, GLsizei depth,
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index 9d9b28b518..6cd2a2f4f6 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.2
+ * Version: 7.6
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -29,6 +30,7 @@
#include "context.h"
#include "enable.h"
#include "enums.h"
+#include "hash.h"
#include "mtypes.h"
#include "varray.h"
#include "arrayobj.h"
@@ -36,49 +38,55 @@
/**
- * Update the fields of a vertex array object.
- * We need to do a few special things for arrays that live in
- * vertex buffer objects.
+ * Set the fields of a vertex array.
+ * Also do an error check for GL_ARB_vertex_array_object: check that
+ * all arrays reside in VBOs when using a vertex array object.
*
* \param array the array to update
* \param dirtyBit which bit to set in ctx->Array.NewState for this array
* \param elementSize size of each array element, in bytes
* \param size components per element (1, 2, 3 or 4)
* \param type datatype of each component (GL_FLOAT, GL_INT, etc)
+ * \param format either GL_RGBA or GL_BGRA
* \param stride stride between elements, in elements
* \param normalized are integer types converted to floats in [-1, 1]?
* \param ptr the address (or offset inside VBO) of the array data
+ * \return GL_TRUE if no error, GL_FALSE if error
*/
-static void
+static GLboolean
update_array(GLcontext *ctx, struct gl_client_array *array,
GLbitfield dirtyBit, GLsizei elementSize,
- GLint size, GLenum type,
+ GLint size, GLenum type, GLenum format,
GLsizei stride, GLboolean normalized, const GLvoid *ptr)
{
+ ASSERT(format == GL_RGBA || format == GL_BGRA);
+
+ if (ctx->Array.ArrayObj->VBOonly &&
+ ctx->Array.ArrayBufferObj->Name == 0) {
+ /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
+ * Generate GL_INVALID_OPERATION if that's not true.
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertex/Normal/EtcPointer(non-VBO array)");
+ return GL_FALSE;
+ }
+
array->Size = size;
array->Type = type;
+ array->Format = format;
array->Stride = stride;
array->StrideB = stride ? stride : elementSize;
array->Normalized = normalized;
array->Ptr = (const GLubyte *) ptr;
-#if FEATURE_ARB_vertex_buffer_object
+ array->_ElementSize = elementSize;
+
_mesa_reference_buffer_object(ctx, &array->BufferObj,
ctx->Array.ArrayBufferObj);
- /* Compute the index of the last array element that's inside the buffer.
- * Later in glDrawArrays we'll check if start + count > _MaxElement to
- * be sure we won't go out of bounds.
- */
- if (ctx->Array.ArrayBufferObj->Name)
- array->_MaxElement = ((GLsizeiptrARB) ctx->Array.ArrayBufferObj->Size
- - (GLsizeiptrARB) array->Ptr + array->StrideB
- - elementSize) / array->StrideB;
- else
-#endif
- array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */
-
ctx->NewState |= _NEW_ARRAY;
ctx->Array.NewState |= dirtyBit;
+
+ return GL_TRUE;
}
@@ -127,12 +135,14 @@ _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
break;
#endif
default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
+ _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
- elementSize, size, type, stride, GL_FALSE, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
+ elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr))
+ return;
if (ctx->Driver.VertexPointer)
ctx->Driver.VertexPointer( ctx, size, type, stride, ptr );
@@ -177,12 +187,14 @@ _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
break;
#endif
default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
+ _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
- elementSize, 3, type, stride, GL_TRUE, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
+ elementSize, 3, type, GL_RGBA, stride, GL_TRUE, ptr))
+ return;
if (ctx->Driver.NormalPointer)
ctx->Driver.NormalPointer( ctx, type, stride, ptr );
@@ -193,12 +205,15 @@ void GLAPIENTRY
_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
{
GLsizei elementSize;
+ GLenum format;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (size < 3 || size > 4) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
- return;
+ if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(size)");
+ return;
+ }
}
if (stride < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
@@ -209,6 +224,18 @@ _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
_mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
_mesa_lookup_enum_by_nr( type ), stride);
+ if (size == GL_BGRA) {
+ if (type != GL_UNSIGNED_BYTE) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
+ return;
+ }
+ format = GL_BGRA;
+ size = 4;
+ }
+ else {
+ format = GL_RGBA;
+ }
+
switch (type) {
case GL_BYTE:
elementSize = size * sizeof(GLbyte);
@@ -240,12 +267,14 @@ _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
break;
#endif
default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
+ _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
- elementSize, size, type, stride, GL_TRUE, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
+ elementSize, size, type, format, stride, GL_TRUE, ptr))
+ return;
if (ctx->Driver.ColorPointer)
ctx->Driver.ColorPointer( ctx, size, type, stride, ptr );
@@ -276,8 +305,9 @@ _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
- elementSize, 1, type, stride, GL_FALSE, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
+ elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr))
+ return;
if (ctx->Driver.FogCoordPointer)
ctx->Driver.FogCoordPointer( ctx, type, stride, ptr );
@@ -317,8 +347,9 @@ _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
- elementSize, 1, type, stride, GL_FALSE, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
+ elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr))
+ return;
if (ctx->Driver.IndexPointer)
ctx->Driver.IndexPointer( ctx, type, stride, ptr );
@@ -330,12 +361,15 @@ _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
GLsizei stride, const GLvoid *ptr)
{
GLsizei elementSize;
+ GLenum format;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
if (size != 3 && size != 4) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)" );
- return;
+ if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)");
+ return;
+ }
}
if (stride < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
@@ -346,6 +380,18 @@ _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
_mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
size, _mesa_lookup_enum_by_nr( type ), stride);
+ if (size == GL_BGRA) {
+ if (type != GL_UNSIGNED_BYTE) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
+ return;
+ }
+ format = GL_BGRA;
+ size = 4;
+ }
+ else {
+ format = GL_RGBA;
+ }
+
switch (type) {
case GL_BYTE:
elementSize = size * sizeof(GLbyte);
@@ -372,12 +418,15 @@ _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
elementSize = size * sizeof(GLdouble);
break;
default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type)" );
+ _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor, _NEW_ARRAY_COLOR1,
- elementSize, size, type, stride, GL_TRUE, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor,
+ _NEW_ARRAY_COLOR1, elementSize, size, type,
+ format, stride, GL_TRUE, ptr))
+ return;
if (ctx->Driver.SecondaryColorPointer)
ctx->Driver.SecondaryColorPointer( ctx, size, type, stride, ptr );
@@ -431,13 +480,15 @@ _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
break;
#endif
default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
- _NEW_ARRAY_TEXCOORD(unit),
- elementSize, size, type, stride, GL_FALSE, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
+ _NEW_ARRAY_TEXCOORD(unit),
+ elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr))
+ return;
if (ctx->Driver.TexCoordPointer)
ctx->Driver.TexCoordPointer( ctx, size, type, stride, ptr );
@@ -455,8 +506,10 @@ _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
- sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
+ sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
+ stride, GL_FALSE, ptr))
+ return;
if (ctx->Driver.EdgeFlagPointer)
ctx->Driver.EdgeFlagPointer( ctx, stride, ptr );
@@ -490,21 +543,28 @@ _mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
}
update_array(ctx, &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
- elementSize, 1, type, stride, GL_FALSE, ptr);
+ elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
}
#if FEATURE_NV_vertex_program
+/**
+ * Set a vertex attribute array.
+ * Note that these arrays DO alias the conventional GL vertex arrays
+ * (position, normal, color, fog, texcoord, etc).
+ * The generic attribute slots at #16 and above are not touched.
+ */
void GLAPIENTRY
_mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
GLsizei stride, const GLvoid *ptr)
{
GLboolean normalized = GL_FALSE;
GLsizei elementSize;
+ GLenum format;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
+ if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
_mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
return;
}
@@ -524,6 +584,21 @@ _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
return;
}
+ if (size == GL_BGRA) {
+ if (type != GL_UNSIGNED_BYTE) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glVertexAttribPointerNV(GL_BGRA/type)");
+ return;
+ }
+
+ format = GL_BGRA;
+ size = 4;
+ normalized = GL_TRUE;
+ }
+ else {
+ format = GL_RGBA;
+ }
+
/* check for valid 'type' and compute StrideB right away */
switch (type) {
case GL_UNSIGNED_BYTE:
@@ -540,13 +615,15 @@ _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
elementSize = size * sizeof(GLdouble);
break;
default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type)" );
+ _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
- _NEW_ARRAY_ATTRIB(index),
- elementSize, size, type, stride, normalized, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
+ _NEW_ARRAY_ATTRIB(index),
+ elementSize, size, type, format, stride, normalized, ptr))
+ return;
if (ctx->Driver.VertexAttribPointer)
ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
@@ -555,12 +632,18 @@ _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
#if FEATURE_ARB_vertex_program
+/**
+ * Set a generic vertex attribute array.
+ * Note that these arrays DO NOT alias the conventional GL vertex arrays
+ * (position, normal, color, fog, texcoord, etc).
+ */
void GLAPIENTRY
_mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
GLboolean normalized,
GLsizei stride, const GLvoid *ptr)
{
GLsizei elementSize;
+ GLenum format;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -570,8 +653,10 @@ _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
}
if (size < 1 || size > 4) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
- return;
+ if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
+ return;
+ }
}
if (stride < 0) {
@@ -579,6 +664,25 @@ _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
return;
}
+ if (size == GL_BGRA) {
+ if (type != GL_UNSIGNED_BYTE) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glVertexAttribPointerARB(GL_BGRA/type)");
+ return;
+ }
+ if (normalized != GL_TRUE) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glVertexAttribPointerARB(GL_BGRA/normalized)");
+ return;
+ }
+
+ format = GL_BGRA;
+ size = 4;
+ }
+ else {
+ format = GL_RGBA;
+ }
+
/* check for valid 'type' and compute StrideB right away */
/* NOTE: more types are supported here than in the NV extension */
switch (type) {
@@ -616,9 +720,10 @@ _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
return;
}
- update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
- _NEW_ARRAY_ATTRIB(index),
- elementSize, size, type, stride, normalized, ptr);
+ if (!update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
+ _NEW_ARRAY_ATTRIB(index),
+ elementSize, size, type, format, stride, normalized, ptr))
+ return;
if (ctx->Driver.VertexAttribPointer)
ctx->Driver.VertexAttribPointer(ctx, index, size, type, stride, ptr);
@@ -933,24 +1038,6 @@ _mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
}
-/* GL_EXT_multi_draw_arrays */
-void GLAPIENTRY
-_mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type,
- const GLvoid **indices, GLsizei primcount )
-{
- GET_CURRENT_CONTEXT(ctx);
- GLint i;
-
- ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
-
- for (i = 0; i < primcount; i++) {
- if (count[i] > 0) {
- CALL_DrawElements(ctx->Exec, (mode, count[i], type, indices[i]));
- }
- }
-}
-
-
/* GL_IBM_multimode_draw_arrays */
void GLAPIENTRY
_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
@@ -994,13 +1081,107 @@ _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
/**
+ * Copy one client vertex array to another.
+ */
+void
+_mesa_copy_client_array(GLcontext *ctx,
+ struct gl_client_array *dst,
+ struct gl_client_array *src)
+{
+ dst->Size = src->Size;
+ dst->Type = src->Type;
+ dst->Format = src->Format;
+ dst->Stride = src->Stride;
+ dst->StrideB = src->StrideB;
+ dst->Ptr = src->Ptr;
+ dst->Enabled = src->Enabled;
+ dst->Normalized = src->Normalized;
+ dst->_ElementSize = src->_ElementSize;
+ _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
+ dst->_MaxElement = src->_MaxElement;
+}
+
+
+
+/**
+ * Print vertex array's fields.
+ */
+static void
+print_array(const char *name, GLint index, const struct gl_client_array *array)
+{
+ if (index >= 0)
+ _mesa_printf(" %s[%d]: ", name, index);
+ else
+ _mesa_printf(" %s: ", name);
+ _mesa_printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %u), MaxElem=%u\n",
+ array->Ptr, array->Type, array->Size,
+ array->_ElementSize, array->StrideB,
+ array->BufferObj->Name, array->BufferObj->Size,
+ array->_MaxElement);
+}
+
+
+/**
+ * Print current vertex object/array info. For debug.
+ */
+void
+_mesa_print_arrays(GLcontext *ctx)
+{
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint i;
+
+ _mesa_update_array_object_max_element(ctx, arrayObj);
+
+ _mesa_printf("Array Object %u\n", arrayObj->Name);
+ if (arrayObj->Vertex.Enabled)
+ print_array("Vertex", -1, &arrayObj->Vertex);
+ if (arrayObj->Normal.Enabled)
+ print_array("Normal", -1, &arrayObj->Normal);
+ if (arrayObj->Color.Enabled)
+ print_array("Color", -1, &arrayObj->Color);
+ for (i = 0; i < Elements(arrayObj->TexCoord); i++)
+ if (arrayObj->TexCoord[i].Enabled)
+ print_array("TexCoord", i, &arrayObj->TexCoord[i]);
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
+ if (arrayObj->VertexAttrib[i].Enabled)
+ print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
+ _mesa_printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
+}
+
+
+/**
* Initialize vertex array state for given context.
*/
void
_mesa_init_varray(GLcontext *ctx)
{
ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
- ctx->Array.ArrayObj = ctx->Array.DefaultArrayObj;
-
+ _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
+ ctx->Array.DefaultArrayObj);
ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
+
+ ctx->Array.Objects = _mesa_NewHashTable();
+}
+
+
+/**
+ * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_arrayobj_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_array_object *arrayObj = (struct gl_array_object *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ _mesa_delete_array_object(ctx, arrayObj);
+}
+
+
+/**
+ * Free vertex array state for given context.
+ */
+void
+_mesa_free_varray_data(GLcontext *ctx)
+{
+ _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
+ _mesa_DeleteHashTable(ctx->Array.Objects);
}
diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h
index 6385689fcc..ef790c504e 100644
--- a/src/mesa/main/varray.h
+++ b/src/mesa/main/varray.h
@@ -1,18 +1,9 @@
-/**
- * \file varray.h
- * Vertex arrays.
- *
- * \if subset
- * (No-op)
- *
- * \endif
- */
-
/*
* Mesa 3-D graphics library
- * Version: 4.1
+ * Version: 7.6
*
- * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -138,6 +129,11 @@ extern void GLAPIENTRY
_mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type,
const GLvoid **indices, GLsizei primcount );
+extern void GLAPIENTRY
+_mesa_MultiDrawElementsBaseVertex( GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount,
+ const GLint *basevertex);
extern void GLAPIENTRY
_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
@@ -156,13 +152,49 @@ _mesa_LockArraysEXT(GLint first, GLsizei count);
extern void GLAPIENTRY
_mesa_UnlockArraysEXT( void );
+
+extern void GLAPIENTRY
+_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count);
+
+extern void GLAPIENTRY
+_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices);
+
+extern void GLAPIENTRY
+_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices);
+
+extern void GLAPIENTRY
+_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex);
+
+extern void GLAPIENTRY
+_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices,
+ GLint basevertex);
+
+
+extern void
+_mesa_copy_client_array(GLcontext *ctx,
+ struct gl_client_array *dst,
+ struct gl_client_array *src);
+
+
+extern void
+_mesa_print_arrays(GLcontext *ctx);
+
extern void
_mesa_init_varray( GLcontext * ctx );
+extern void
+_mesa_free_varray_data(GLcontext *ctx);
+
#else
/** No-op */
#define _mesa_init_varray( c ) ((void)0)
+#define _mesa_free_varray_data( c ) ((void)0)
#endif
diff --git a/src/mesa/main/version.h b/src/mesa/main/version.h
index 3d874c8ba8..0cae1860a3 100644
--- a/src/mesa/main/version.h
+++ b/src/mesa/main/version.h
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.3
+ * Version: 7.7
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -29,9 +30,9 @@
/* Mesa version */
#define MESA_MAJOR 7
-#define MESA_MINOR 3
+#define MESA_MINOR 7
#define MESA_PATCH 0
-#define MESA_VERSION_STRING "7.3-rc3"
+#define MESA_VERSION_STRING "7.7-devel"
/* To make version comparison easy */
#define MESA_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
diff --git a/src/mesa/main/viewport.c b/src/mesa/main/viewport.c
new file mode 100644
index 0000000000..309308c983
--- /dev/null
+++ b/src/mesa/main/viewport.c
@@ -0,0 +1,180 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * \file viewport.c
+ * glViewport and glDepthRange functions.
+ */
+
+
+#include "context.h"
+#include "macros.h"
+#include "viewport.h"
+
+
+/**
+ * Set the viewport.
+ * \sa Called via glViewport() or display list execution.
+ *
+ * Flushes the vertices and calls _mesa_set_viewport() with the given
+ * parameters.
+ */
+void GLAPIENTRY
+_mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ _mesa_set_viewport(ctx, x, y, width, height);
+}
+
+
+/**
+ * Set new viewport parameters and update derived state (the _WindowMap
+ * matrix). Usually called from _mesa_Viewport().
+ *
+ * \param ctx GL context.
+ * \param x, y coordinates of the lower left corner of the viewport rectangle.
+ * \param width width of the viewport rectangle.
+ * \param height height of the viewport rectangle.
+ */
+void
+_mesa_set_viewport(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height);
+
+ if (width < 0 || height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glViewport(%d, %d, %d, %d)", x, y, width, height);
+ return;
+ }
+
+ /* clamp width and height to the implementation dependent range */
+ width = MIN2(width, (GLsizei) ctx->Const.MaxViewportWidth);
+ height = MIN2(height, (GLsizei) ctx->Const.MaxViewportHeight);
+
+ ctx->Viewport.X = x;
+ ctx->Viewport.Width = width;
+ ctx->Viewport.Y = y;
+ ctx->Viewport.Height = height;
+ ctx->NewState |= _NEW_VIEWPORT;
+
+#if 1
+ /* XXX remove this someday. Currently the DRI drivers rely on
+ * the WindowMap matrix being up to date in the driver's Viewport
+ * and DepthRange functions.
+ */
+ _math_matrix_viewport(&ctx->Viewport._WindowMap,
+ ctx->Viewport.X, ctx->Viewport.Y,
+ ctx->Viewport.Width, ctx->Viewport.Height,
+ ctx->Viewport.Near, ctx->Viewport.Far,
+ ctx->DrawBuffer->_DepthMaxF);
+#endif
+
+ if (ctx->Driver.Viewport) {
+ /* Many drivers will use this call to check for window size changes
+ * and reallocate the z/stencil/accum/etc buffers if needed.
+ */
+ ctx->Driver.Viewport(ctx, x, y, width, height);
+ }
+}
+
+
+/**
+ * Called by glDepthRange
+ *
+ * \param nearval specifies the Z buffer value which should correspond to
+ * the near clip plane
+ * \param farval specifies the Z buffer value which should correspond to
+ * the far clip plane
+ */
+void GLAPIENTRY
+_mesa_DepthRange(GLclampd nearval, GLclampd farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval);
+
+ if (ctx->Viewport.Near == nearval &&
+ ctx->Viewport.Far == farval)
+ return;
+
+ ctx->Viewport.Near = (GLfloat) CLAMP(nearval, 0.0, 1.0);
+ ctx->Viewport.Far = (GLfloat) CLAMP(farval, 0.0, 1.0);
+ ctx->NewState |= _NEW_VIEWPORT;
+
+#if 1
+ /* XXX remove this someday. Currently the DRI drivers rely on
+ * the WindowMap matrix being up to date in the driver's Viewport
+ * and DepthRange functions.
+ */
+ _math_matrix_viewport(&ctx->Viewport._WindowMap,
+ ctx->Viewport.X, ctx->Viewport.Y,
+ ctx->Viewport.Width, ctx->Viewport.Height,
+ ctx->Viewport.Near, ctx->Viewport.Far,
+ ctx->DrawBuffer->_DepthMaxF);
+#endif
+
+ if (ctx->Driver.DepthRange) {
+ ctx->Driver.DepthRange(ctx, nearval, farval);
+ }
+}
+
+
+
+/**
+ * Initialize the context viewport attribute group.
+ * \param ctx the GL context.
+ */
+void _mesa_init_viewport(GLcontext *ctx)
+{
+ GLfloat depthMax = 65535.0F; /* sorf of arbitrary */
+
+ /* Viewport group */
+ ctx->Viewport.X = 0;
+ ctx->Viewport.Y = 0;
+ ctx->Viewport.Width = 0;
+ ctx->Viewport.Height = 0;
+ ctx->Viewport.Near = 0.0;
+ ctx->Viewport.Far = 1.0;
+ _math_matrix_ctr(&ctx->Viewport._WindowMap);
+
+ _math_matrix_viewport(&ctx->Viewport._WindowMap, 0, 0, 0, 0,
+ 0.0F, 1.0F, depthMax);
+}
+
+
+/**
+ * Free the context viewport attribute group data.
+ * \param ctx the GL context.
+ */
+void _mesa_free_viewport_data(GLcontext *ctx)
+{
+ _math_matrix_dtr(&ctx->Viewport._WindowMap);
+}
+
diff --git a/src/mesa/main/viewport.h b/src/mesa/main/viewport.h
new file mode 100644
index 0000000000..f08fef2797
--- /dev/null
+++ b/src/mesa/main/viewport.h
@@ -0,0 +1,52 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef VIEWPORT_H
+#define VIEWPORT_H
+
+
+extern void GLAPIENTRY
+_mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+
+
+extern void
+_mesa_set_viewport(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height);
+
+
+extern void GLAPIENTRY
+_mesa_DepthRange(GLclampd nearval, GLclampd farval);
+
+
+extern void
+_mesa_init_viewport(GLcontext *ctx);
+
+
+extern void
+_mesa_free_viewport_data(GLcontext *ctx);
+
+
+#endif
diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c
index 0204979003..6e0581f62d 100644
--- a/src/mesa/main/vtxfmt.c
+++ b/src/mesa/main/vtxfmt.c
@@ -27,12 +27,18 @@
*/
#include "glheader.h"
+#include "api_arrayelt.h"
#include "api_loopback.h"
#include "context.h"
#include "imports.h"
#include "mtypes.h"
#include "state.h"
#include "vtxfmt.h"
+#include "eval.h"
+#include "dlist.h"
+
+
+#if FEATURE_beginend
/* The neutral vertex format. This wraps all tnl module functions,
@@ -54,9 +60,12 @@
ASSERT( tnl->Current ); \
ASSERT( tnl->SwapCount < NUM_VERTEX_FORMAT_ENTRIES ); \
ASSERT( tmp_offset >= 0 ); \
- \
- /* Save the swapped function's dispatch entry so it can be */ \
- /* restored later. */ \
+ \
+ if (tnl->SwapCount == 0) \
+ ctx->Driver.BeginVertices( ctx ); \
+ \
+ /* Save the swapped function's dispatch entry so it can be */ \
+ /* restored later. */ \
tnl->Swapped[tnl->SwapCount].location = & (((_glapi_proc *)ctx->Exec)[tmp_offset]); \
tnl->Swapped[tnl->SwapCount].function = (_glapi_proc)TAG(FUNC); \
tnl->SwapCount++; \
@@ -79,18 +88,16 @@
static void
install_vtxfmt( struct _glapi_table *tab, const GLvertexformat *vfmt )
{
- SET_ArrayElement(tab, vfmt->ArrayElement);
+ _mesa_install_arrayelt_vtxfmt(tab, vfmt);
+
SET_Color3f(tab, vfmt->Color3f);
SET_Color3fv(tab, vfmt->Color3fv);
SET_Color4f(tab, vfmt->Color4f);
SET_Color4fv(tab, vfmt->Color4fv);
SET_EdgeFlag(tab, vfmt->EdgeFlag);
- SET_EvalCoord1f(tab, vfmt->EvalCoord1f);
- SET_EvalCoord1fv(tab, vfmt->EvalCoord1fv);
- SET_EvalCoord2f(tab, vfmt->EvalCoord2f);
- SET_EvalCoord2fv(tab, vfmt->EvalCoord2fv);
- SET_EvalPoint1(tab, vfmt->EvalPoint1);
- SET_EvalPoint2(tab, vfmt->EvalPoint2);
+
+ _mesa_install_eval_vtxfmt(tab, vfmt);
+
SET_FogCoordfEXT(tab, vfmt->FogCoordfEXT);
SET_FogCoordfvEXT(tab, vfmt->FogCoordfvEXT);
SET_Indexf(tab, vfmt->Indexf);
@@ -122,17 +129,19 @@ install_vtxfmt( struct _glapi_table *tab, const GLvertexformat *vfmt )
SET_Vertex3fv(tab, vfmt->Vertex3fv);
SET_Vertex4f(tab, vfmt->Vertex4f);
SET_Vertex4fv(tab, vfmt->Vertex4fv);
- SET_CallList(tab, vfmt->CallList);
- SET_CallLists(tab, vfmt->CallLists);
+
+ _mesa_install_dlist_vtxfmt(tab, vfmt);
+
SET_Begin(tab, vfmt->Begin);
SET_End(tab, vfmt->End);
SET_Rectf(tab, vfmt->Rectf);
SET_DrawArrays(tab, vfmt->DrawArrays);
SET_DrawElements(tab, vfmt->DrawElements);
SET_DrawRangeElements(tab, vfmt->DrawRangeElements);
- SET_EvalMesh1(tab, vfmt->EvalMesh1);
- SET_EvalMesh2(tab, vfmt->EvalMesh2);
- ASSERT(tab->EvalMesh2);
+ SET_MultiDrawElementsEXT(tab, vfmt->MultiDrawElementsEXT);
+ SET_DrawElementsBaseVertex(tab, vfmt->DrawElementsBaseVertex);
+ SET_DrawRangeElementsBaseVertex(tab, vfmt->DrawRangeElementsBaseVertex);
+ SET_MultiDrawElementsBaseVertex(tab, vfmt->MultiDrawElementsBaseVertex);
/* GL_NV_vertex_program */
SET_VertexAttrib1fNV(tab, vfmt->VertexAttrib1fNV);
@@ -172,7 +181,10 @@ void _mesa_install_exec_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt )
void _mesa_install_save_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt )
{
+ /* vfmt is empty when dlist is disabled */
+#if FEATURE_dlist
install_vtxfmt( ctx->Save, vfmt );
+#endif
}
@@ -189,3 +201,6 @@ void _mesa_restore_exec_vtxfmt( GLcontext *ctx )
tnl->SwapCount = 0;
}
+
+
+#endif /* FEATURE_beginend */
diff --git a/src/mesa/main/vtxfmt.h b/src/mesa/main/vtxfmt.h
index 76f108e023..819a6ec218 100644
--- a/src/mesa/main/vtxfmt.h
+++ b/src/mesa/main/vtxfmt.h
@@ -33,6 +33,8 @@
#ifndef _VTXFMT_H_
#define _VTXFMT_H_
+#if FEATURE_beginend
+
extern void _mesa_init_exec_vtxfmt( GLcontext *ctx );
extern void _mesa_install_exec_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt );
@@ -40,4 +42,29 @@ extern void _mesa_install_save_vtxfmt( GLcontext *ctx, const GLvertexformat *vfm
extern void _mesa_restore_exec_vtxfmt( GLcontext *ctx );
-#endif
+#else /* FEATURE_beginend */
+
+static INLINE void
+_mesa_init_exec_vtxfmt( GLcontext *ctx )
+{
+}
+
+static INLINE void
+_mesa_install_exec_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt )
+{
+}
+
+static INLINE void
+_mesa_install_save_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt )
+{
+}
+
+
+static INLINE void
+_mesa_restore_exec_vtxfmt( GLcontext *ctx )
+{
+}
+
+#endif /* FEATURE_beginend */
+
+#endif /* _VTXFMT_H_ */
diff --git a/src/mesa/main/vtxfmt_tmp.h b/src/mesa/main/vtxfmt_tmp.h
index 6f5d01e40f..d56a2bb95e 100644
--- a/src/mesa/main/vtxfmt_tmp.h
+++ b/src/mesa/main/vtxfmt_tmp.h
@@ -335,6 +335,17 @@ static void GLAPIENTRY TAG(DrawElements)( GLenum mode, GLsizei count, GLenum typ
CALL_DrawElements(GET_DISPATCH(), ( mode, count, type, indices ));
}
+static void GLAPIENTRY TAG(MultiDrawElementsEXT)( GLenum mode,
+ const GLsizei *count,
+ GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount)
+{
+ PRE_LOOPBACK( MultiDrawElementsEXT );
+ CALL_MultiDrawElementsEXT(GET_DISPATCH(), ( mode, count, type, indices,
+ primcount ));
+}
+
static void GLAPIENTRY TAG(DrawRangeElements)( GLenum mode, GLuint start,
GLuint end, GLsizei count,
GLenum type, const GLvoid *indices )
@@ -343,6 +354,44 @@ static void GLAPIENTRY TAG(DrawRangeElements)( GLenum mode, GLuint start,
CALL_DrawRangeElements(GET_DISPATCH(), ( mode, start, end, count, type, indices ));
}
+static void GLAPIENTRY TAG(DrawElementsBaseVertex)( GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
+{
+ PRE_LOOPBACK( DrawElementsBaseVertex );
+ CALL_DrawElementsBaseVertex(GET_DISPATCH(), ( mode, count, type,
+ indices, basevertex ));
+}
+
+static void GLAPIENTRY TAG(DrawRangeElementsBaseVertex)( GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
+{
+ PRE_LOOPBACK( DrawRangeElementsBaseVertex );
+ CALL_DrawRangeElementsBaseVertex(GET_DISPATCH(), ( mode, start, end,
+ count, type, indices,
+ basevertex ));
+}
+
+static void GLAPIENTRY TAG(MultiDrawElementsBaseVertex)( GLenum mode,
+ const GLsizei *count,
+ GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount,
+ const GLint *basevertex)
+{
+ PRE_LOOPBACK( MultiDrawElementsBaseVertex );
+ CALL_MultiDrawElementsBaseVertex(GET_DISPATCH(), ( mode, count, type,
+ indices,
+ primcount, basevertex ));
+}
+
static void GLAPIENTRY TAG(EvalMesh1)( GLenum mode, GLint i1, GLint i2 )
{
PRE_LOOPBACK( EvalMesh1 );
@@ -522,6 +571,10 @@ static GLvertexformat TAG(vtxfmt) = {
TAG(DrawArrays),
TAG(DrawElements),
TAG(DrawRangeElements),
+ TAG(MultiDrawElementsEXT),
+ TAG(DrawElementsBaseVertex),
+ TAG(DrawRangeElementsBaseVertex),
+ TAG(MultiDrawElementsBaseVertex),
TAG(EvalMesh1),
TAG(EvalMesh2)
};
diff --git a/src/mesa/math/m_clip_tmp.h b/src/mesa/math/m_clip_tmp.h
index f3a589be05..2e30964057 100644
--- a/src/mesa/math/m_clip_tmp.h
+++ b/src/mesa/math/m_clip_tmp.h
@@ -44,7 +44,8 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points4)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask )
+ GLubyte *andMask,
+ GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLfloat *from = (GLfloat *)clip_vec->start;
@@ -66,16 +67,20 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points4)( GLvector4f *clip_vec,
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
mask |= (((cw < cy) << CLIP_TOP_SHIFT));
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
- mask |= (((cw < cz) << CLIP_FAR_SHIFT));
- mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
+ if (viewport_z_clip) {
+ mask |= (((cw < cz) << CLIP_FAR_SHIFT));
+ mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
+ }
#else /* !defined(macintosh)) */
GLubyte mask = 0;
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
- if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
- if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
+ if (viewport_z_clip) {
+ if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
+ if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
+ }
#endif /* defined(macintosh) */
clipMask[i] = mask;
@@ -119,7 +124,8 @@ static GLvector4f * _XFORMAPI TAG(cliptest_np_points4)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask )
+ GLubyte *andMask,
+ GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
@@ -141,16 +147,20 @@ static GLvector4f * _XFORMAPI TAG(cliptest_np_points4)( GLvector4f *clip_vec,
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
mask |= (((cw < cy) << CLIP_TOP_SHIFT));
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
- mask |= (((cw < cz) << CLIP_FAR_SHIFT));
- mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
+ if (viewport_z_clip) {
+ mask |= (((cw < cz) << CLIP_FAR_SHIFT));
+ mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
+ }
#else /* !defined(macintosh)) */
GLubyte mask = 0;
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
- if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
- if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
+ if (viewport_z_clip) {
+ if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
+ if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
+ }
#endif /* defined(macintosh) */
clipMask[i] = mask;
@@ -171,7 +181,8 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask )
+ GLubyte *andMask,
+ GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
@@ -187,8 +198,10 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec,
else if (cx < -1.0) mask |= CLIP_LEFT_BIT;
if (cy > 1.0) mask |= CLIP_TOP_BIT;
else if (cy < -1.0) mask |= CLIP_BOTTOM_BIT;
- if (cz > 1.0) mask |= CLIP_FAR_BIT;
- else if (cz < -1.0) mask |= CLIP_NEAR_BIT;
+ if (viewport_z_clip) {
+ if (cz > 1.0) mask |= CLIP_FAR_BIT;
+ else if (cz < -1.0) mask |= CLIP_NEAR_BIT;
+ }
clipMask[i] = mask;
tmpOrMask |= mask;
tmpAndMask &= mask;
@@ -204,7 +217,8 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points2)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask )
+ GLubyte *andMask,
+ GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
@@ -231,7 +245,7 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points2)( GLvector4f *clip_vec,
}
-static void TAG(init_c_cliptest)( void )
+void TAG(init_c_cliptest)( void )
{
_mesa_clip_tab[4] = TAG(cliptest_points4);
_mesa_clip_tab[3] = TAG(cliptest_points3);
diff --git a/src/mesa/math/m_debug_clip.c b/src/mesa/math/m_debug_clip.c
index 460fed4a75..95ae5a347d 100644
--- a/src/mesa/math/m_debug_clip.c
+++ b/src/mesa/math/m_debug_clip.c
@@ -67,7 +67,8 @@ static GLvector4f *ref_cliptest_points4( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask )
+ GLubyte *andMask,
+ GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
@@ -87,8 +88,10 @@ static GLvector4f *ref_cliptest_points4( GLvector4f *clip_vec,
if ( cx + cw < 0 ) mask |= CLIP_LEFT_BIT;
if ( -cy + cw < 0 ) mask |= CLIP_TOP_BIT;
if ( cy + cw < 0 ) mask |= CLIP_BOTTOM_BIT;
- if ( -cz + cw < 0 ) mask |= CLIP_FAR_BIT;
- if ( cz + cw < 0 ) mask |= CLIP_NEAR_BIT;
+ if (viewport_z_clip) {
+ if ( -cz + cw < 0 ) mask |= CLIP_FAR_BIT;
+ if ( cz + cw < 0 ) mask |= CLIP_NEAR_BIT;
+ }
clipMask[i] = mask;
if ( mask ) {
c++;
@@ -122,7 +125,8 @@ static GLvector4f *ref_cliptest_points3( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask )
+ GLubyte *andMask,
+ GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
@@ -138,8 +142,10 @@ static GLvector4f *ref_cliptest_points3( GLvector4f *clip_vec,
else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT;
if ( cy > 1.0 ) mask |= CLIP_TOP_BIT;
else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT;
- if ( cz > 1.0 ) mask |= CLIP_FAR_BIT;
- else if ( cz < -1.0 ) mask |= CLIP_NEAR_BIT;
+ if (viewport_z_clip) {
+ if ( cz > 1.0 ) mask |= CLIP_FAR_BIT;
+ else if ( cz < -1.0 ) mask |= CLIP_NEAR_BIT;
+ }
clipMask[i] = mask;
tmpOrMask |= mask;
tmpAndMask &= mask;
@@ -154,7 +160,8 @@ static GLvector4f * ref_cliptest_points2( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask )
+ GLubyte *andMask,
+ GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
@@ -163,6 +170,9 @@ static GLvector4f * ref_cliptest_points2( GLvector4f *clip_vec,
GLubyte tmpOrMask = *orMask;
GLubyte tmpAndMask = *andMask;
GLuint i;
+
+ (void) viewport_z_clip;
+
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
const GLfloat cx = from[0], cy = from[1];
GLubyte mask = 0;
@@ -208,6 +218,7 @@ static int test_cliptest_function( clip_func func, int np,
#ifdef RUN_DEBUG_BENCHMARK
int cycle_i; /* the counter for the benchmarks we run */
#endif
+ GLboolean viewport_z_clip = GL_TRUE;
(void) cycles;
@@ -247,15 +258,15 @@ static int test_cliptest_function( clip_func func, int np,
dco = rco = 0;
dca = rca = CLIP_FRUSTUM_BITS;
- ref_cliptest[psize]( source, ref, rm, &rco, &rca );
+ ref_cliptest[psize]( source, ref, rm, &rco, &rca, viewport_z_clip );
if ( mesa_profile ) {
BEGIN_RACE( *cycles );
- func( source, dest, dm, &dco, &dca );
+ func( source, dest, dm, &dco, &dca, viewport_z_clip );
END_RACE( *cycles );
}
else {
- func( source, dest, dm, &dco, &dca );
+ func( source, dest, dm, &dco, &dca, viewport_z_clip );
}
if ( dco != rco ) {
diff --git a/src/mesa/math/m_debug_util.h b/src/mesa/math/m_debug_util.h
index 7abe6f2565..2e67db8e55 100644
--- a/src/mesa/math/m_debug_util.h
+++ b/src/mesa/math/m_debug_util.h
@@ -231,8 +231,8 @@ extern char *mesa_profile;
#define BEGIN_RACE(x) \
x = LONG_MAX; \
for (cycle_i = 0; cycle_i <10; cycle_i++) { \
- register long cycle_tmp1 asm("l0"); \
- register long cycle_tmp2 asm("l1"); \
+ register long cycle_tmp1 __asm__("l0"); \
+ register long cycle_tmp2 __asm__("l1"); \
/* rd %tick, %l0 */ \
__asm__ __volatile__ (".word 0xa1410000" : "=r" (cycle_tmp1)); /* save timestamp */
diff --git a/src/mesa/math/m_debug_xform.c b/src/mesa/math/m_debug_xform.c
index ec22c7052d..df8cc066b6 100644
--- a/src/mesa/math/m_debug_xform.c
+++ b/src/mesa/math/m_debug_xform.c
@@ -206,7 +206,8 @@ static int test_transform_function( transform_func func, int psize,
case VAR:
break;
default:
- abort();
+ ASSERT(0);
+ return 0;
}
}
}
diff --git a/src/mesa/math/m_matrix.c b/src/mesa/math/m_matrix.c
index 84b4cae4ad..da6956efed 100644
--- a/src/mesa/math/m_matrix.c
+++ b/src/mesa/math/m_matrix.c
@@ -1379,11 +1379,10 @@ _math_matrix_analyse( GLmatrix *mat )
if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) {
matrix_invert( mat );
+ mat->flags &= ~MAT_DIRTY_INVERSE;
}
- mat->flags &= ~(MAT_DIRTY_FLAGS|
- MAT_DIRTY_TYPE|
- MAT_DIRTY_INVERSE);
+ mat->flags &= ~(MAT_DIRTY_FLAGS | MAT_DIRTY_TYPE);
}
/*@}*/
@@ -1620,3 +1619,24 @@ _math_transposefd( GLfloat to[16], const GLdouble from[16] )
/*@}*/
+
+/**
+ * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix. This
+ * function is used for transforming clipping plane equations and spotlight
+ * directions.
+ * Mathematically, u = v * m.
+ * Input: v - input vector
+ * m - transformation matrix
+ * Output: u - transformed vector
+ */
+void
+_mesa_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
+{
+ const GLfloat v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+#define M(row,col) m[row + col*4]
+ u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
+ u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
+ u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
+ u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
+#undef M
+}
diff --git a/src/mesa/math/m_matrix.h b/src/mesa/math/m_matrix.h
index a8d9000e89..3bc5de6cd4 100644
--- a/src/mesa/math/m_matrix.h
+++ b/src/mesa/math/m_matrix.h
@@ -200,6 +200,9 @@ do { \
} while (0)
+extern void
+_mesa_transform_vector(GLfloat u[4], const GLfloat v[4], const GLfloat m[16]);
+
/*@}*/
diff --git a/src/mesa/math/m_vector.c b/src/mesa/math/m_vector.c
index c5e2fd1de1..4cbab11a35 100644
--- a/src/mesa/math/m_vector.c
+++ b/src/mesa/math/m_vector.c
@@ -1,4 +1,3 @@
-
/*
* Mesa 3-D graphics library
* Version: 3.5
@@ -37,11 +36,12 @@
-/*
+/**
* Given a vector [count][4] of floats, set all the [][elt] values
* to 0 (if elt = 0, 1, 2) or 1.0 (if elt = 3).
*/
-void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint count, GLuint elt )
+void
+_mesa_vector4f_clean_elem( GLvector4f *vec, GLuint count, GLuint elt )
{
static const GLubyte elem_bits[4] = {
VEC_DIRTY_0,
@@ -54,12 +54,13 @@ void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint count, GLuint elt )
GLfloat (*data)[4] = (GLfloat (*)[4])vec->start;
GLuint i;
- for (i = 0 ; i < count ; i++)
+ for (i = 0; i < count; i++)
data[i][elt] = v;
vec->flags &= ~elem_bits[elt];
}
+
static const GLubyte size_bits[5] = {
0,
VEC_SIZE_1,
@@ -69,61 +70,53 @@ static const GLubyte size_bits[5] = {
};
-
-/*
+/**
* Initialize GLvector objects.
- * Input: v - the vector object to initialize.
- * flags - bitwise-OR of VEC_* flags
- * storage - pointer to storage for the vector's data
+ * \param v the vector object to initialize.
+ * \param flags bitwise-OR of VEC_* flags
+ * \param storage pointer to storage for the vector's data
*/
-
-
-void _mesa_vector4f_init( GLvector4f *v, GLuint flags, GLfloat (*storage)[4] )
+void
+_mesa_vector4f_init( GLvector4f *v, GLbitfield flags, GLfloat (*storage)[4] )
{
v->stride = 4 * sizeof(GLfloat);
v->size = 2; /* may change: 2-4 for vertices and 1-4 for texcoords */
v->data = storage;
v->start = (GLfloat *) storage;
v->count = 0;
- v->flags = size_bits[4] | flags ;
+ v->flags = size_bits[4] | flags;
}
-
-
-/*
+/**
* Initialize GLvector objects and allocate storage.
- * Input: v - the vector object
- * sz - unused????
- * flags - bitwise-OR of VEC_* flags
- * count - number of elements to allocate in vector
- * alignment - desired memory alignment for the data (in bytes)
+ * \param v the vector object
+ * \param flags bitwise-OR of VEC_* flags
+ * \param count number of elements to allocate in vector
+ * \param alignment desired memory alignment for the data (in bytes)
*/
-
-
-void _mesa_vector4f_alloc( GLvector4f *v, GLuint flags, GLuint count,
- GLuint alignment )
+void
+_mesa_vector4f_alloc( GLvector4f *v, GLbitfield flags, GLuint count,
+ GLuint alignment )
{
v->stride = 4 * sizeof(GLfloat);
v->size = 2;
v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLfloat), alignment );
+ v->storage_count = count;
v->start = (GLfloat *) v->storage;
v->data = (GLfloat (*)[4]) v->storage;
v->count = 0;
- v->flags = size_bits[4] | flags | VEC_MALLOC ;
+ v->flags = size_bits[4] | flags | VEC_MALLOC;
}
-
-
-/*
+/**
* Vector deallocation. Free whatever memory is pointed to by the
* vector's storage field if the VEC_MALLOC flag is set.
* DO NOT free the GLvector object itself, though.
*/
-
-
-void _mesa_vector4f_free( GLvector4f *v )
+void
+_mesa_vector4f_free( GLvector4f *v )
{
if (v->flags & VEC_MALLOC) {
ALIGN_FREE( v->storage );
@@ -135,13 +128,15 @@ void _mesa_vector4f_free( GLvector4f *v )
}
-/*
+/**
* For debugging
*/
-void _mesa_vector4f_print( GLvector4f *v, GLubyte *cullmask, GLboolean culling )
+void
+_mesa_vector4f_print( const GLvector4f *v, const GLubyte *cullmask,
+ GLboolean culling )
{
- GLfloat c[4] = { 0, 0, 0, 1 };
- const char *templates[5] = {
+ static const GLfloat c[4] = { 0, 0, 0, 1 };
+ static const char *templates[5] = {
"%d:\t0, 0, 0, 1\n",
"%d:\t%f, 0, 0, 1\n",
"%d:\t%f, %f, 0, 1\n",
@@ -154,30 +149,32 @@ void _mesa_vector4f_print( GLvector4f *v, GLubyte *cullmask, GLboolean culling )
GLuint j, i = 0, count;
_mesa_printf("data-start\n");
- for ( ; d != v->start ; STRIDE_F(d, v->stride), i++)
+ for (; d != v->start; STRIDE_F(d, v->stride), i++)
_mesa_printf(t, i, d[0], d[1], d[2], d[3]);
_mesa_printf("start-count(%u)\n", v->count);
count = i + v->count;
if (culling) {
- for ( ; i < count ; STRIDE_F(d, v->stride), i++)
+ for (; i < count; STRIDE_F(d, v->stride), i++)
if (cullmask[i])
_mesa_printf(t, i, d[0], d[1], d[2], d[3]);
}
else {
- for ( ; i < count ; STRIDE_F(d, v->stride), i++)
+ for (; i < count; STRIDE_F(d, v->stride), i++)
_mesa_printf(t, i, d[0], d[1], d[2], d[3]);
}
- for (j = v->size ; j < 4; j++) {
+ for (j = v->size; j < 4; j++) {
if ((v->flags & (1<<j)) == 0) {
_mesa_printf("checking col %u is clean as advertised ", j);
- for (i = 0, d = (GLfloat *) v->data ;
- i < count && d[j] == c[j] ;
- i++, STRIDE_F(d, v->stride)) {};
+ for (i = 0, d = (GLfloat *) v->data;
+ i < count && d[j] == c[j];
+ i++, STRIDE_F(d, v->stride)) {
+ /* no-op */
+ }
if (i == count)
_mesa_printf(" --> ok\n");
@@ -186,5 +183,3 @@ void _mesa_vector4f_print( GLvector4f *v, GLubyte *cullmask, GLboolean culling )
}
}
}
-
-
diff --git a/src/mesa/math/m_vector.h b/src/mesa/math/m_vector.h
index 647388ac7d..71281d5758 100644
--- a/src/mesa/math/m_vector.h
+++ b/src/mesa/math/m_vector.h
@@ -31,7 +31,6 @@
#define _M_VECTOR_H_
#include "main/glheader.h"
-#include "main/mtypes.h" /* hack for GLchan */
#define VEC_DIRTY_0 0x1
@@ -50,7 +49,8 @@
-/* Wrap all the information about vectors up in a struct. Has
+/**
+ * Wrap all the information about vectors up in a struct. Has
* additional fields compared to the other vectors to help us track of
* different vertex sizes, and whether we need to clean columns out
* because they contain non-(0,0,0,1) values.
@@ -60,29 +60,27 @@
* the transformation routines.
*/
typedef struct {
- GLfloat (*data)[4]; /* may be malloc'd or point to client data */
- GLfloat *start; /* points somewhere inside of <data> */
- GLuint count; /* size of the vector (in elements) */
- GLuint stride; /* stride from one element to the next (in bytes) */
- GLuint size; /* 2-4 for vertices and 1-4 for texcoords */
- GLuint flags; /* which columns are dirty */
- void *storage; /* self-allocated storage */
+ GLfloat (*data)[4]; /**< may be malloc'd or point to client data */
+ GLfloat *start; /**< points somewhere inside of <data> */
+ GLuint count; /**< size of the vector (in elements) */
+ GLuint stride; /**< stride from one element to the next (in bytes) */
+ GLuint size; /**< 2-4 for vertices and 1-4 for texcoords */
+ GLbitfield flags; /**< bitmask of VEC_x flags */
+ void *storage; /**< self-allocated storage */
+ GLuint storage_count; /**< storage size in elements */
} GLvector4f;
-extern void _mesa_vector4f_init( GLvector4f *v, GLuint flags,
+extern void _mesa_vector4f_init( GLvector4f *v, GLbitfield flags,
GLfloat (*storage)[4] );
-extern void _mesa_vector4f_alloc( GLvector4f *v, GLuint flags,
+extern void _mesa_vector4f_alloc( GLvector4f *v, GLbitfield flags,
GLuint count, GLuint alignment );
extern void _mesa_vector4f_free( GLvector4f *v );
-extern void _mesa_vector4f_print( GLvector4f *v, GLubyte *, GLboolean );
+extern void _mesa_vector4f_print( const GLvector4f *v, const GLubyte *, GLboolean );
extern void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint nr, GLuint elt );
-
-
-
-/*
+/**
* Given vector <v>, return a pointer (cast to <type *> to the <i>-th element.
*
* End up doing a lot of slow imuls if not careful.
diff --git a/src/mesa/math/m_xform.c b/src/mesa/math/m_xform.c
index 901ae5b416..369f2c6e95 100644
--- a/src/mesa/math/m_xform.c
+++ b/src/mesa/math/m_xform.c
@@ -40,7 +40,6 @@
#include "m_matrix.h"
#include "m_translate.h"
#include "m_xform.h"
-#include "mathmod.h"
#ifdef DEBUG_MATH
@@ -97,99 +96,6 @@ transform_func *_mesa_transform_tab[5];
#undef ARGS
-
-
-GLvector4f *_mesa_project_points( GLvector4f *proj_vec,
- const GLvector4f *clip_vec )
-{
- const GLuint stride = clip_vec->stride;
- const GLfloat *from = (GLfloat *)clip_vec->start;
- const GLuint count = clip_vec->count;
- GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
- GLuint i;
-
- for (i = 0 ; i < count ; i++, STRIDE_F(from, stride))
- {
- GLfloat oow = 1.0F / from[3];
- vProj[i][3] = oow;
- vProj[i][0] = from[0] * oow;
- vProj[i][1] = from[1] * oow;
- vProj[i][2] = from[2] * oow;
- }
-
- proj_vec->flags |= VEC_SIZE_4;
- proj_vec->size = 3;
- proj_vec->count = clip_vec->count;
- return proj_vec;
-}
-
-
-
-
-
-
-/*
- * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix. This
- * function is used for transforming clipping plane equations and spotlight
- * directions.
- * Mathematically, u = v * m.
- * Input: v - input vector
- * m - transformation matrix
- * Output: u - transformed vector
- */
-void _mesa_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
-{
- GLfloat v0=v[0], v1=v[1], v2=v[2], v3=v[3];
-#define M(row,col) m[row + col*4]
- u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
- u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
- u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
- u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
-#undef M
-}
-
-
-/* Useful for one-off point transformations, as in clipping.
- * Note that because the matrix isn't analysed we do too many
- * multiplies, and that the result is always 4-clean.
- */
-void _mesa_transform_point_sz( GLfloat Q[4], const GLfloat M[16],
- const GLfloat P[4], GLuint sz )
-{
- if (Q == P)
- return;
-
- if (sz == 4)
- {
- Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12] * P[3];
- Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13] * P[3];
- Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14] * P[3];
- Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15] * P[3];
- }
- else if (sz == 3)
- {
- Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12];
- Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13];
- Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14];
- Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15];
- }
- else if (sz == 2)
- {
- Q[0] = M[0] * P[0] + M[4] * P[1] + M[12];
- Q[1] = M[1] * P[0] + M[5] * P[1] + M[13];
- Q[2] = M[2] * P[0] + M[6] * P[1] + M[14];
- Q[3] = M[3] * P[0] + M[7] * P[1] + M[15];
- }
- else if (sz == 1)
- {
- Q[0] = M[0] * P[0] + M[12];
- Q[1] = M[1] * P[0] + M[13];
- Q[2] = M[2] * P[0] + M[14];
- Q[3] = M[3] * P[0] + M[15];
- }
-}
-
-
/*
* This is called only once. It initializes several tables with pointers
* to optimized transformation functions. This is where we can test for
@@ -220,11 +126,3 @@ _math_init_transformation( void )
_mesa_init_all_x86_64_transform_asm();
#endif
}
-
-void
-_math_init( void )
-{
- _math_init_transformation();
- _math_init_translate();
- _math_init_eval();
-}
diff --git a/src/mesa/math/m_xform.h b/src/mesa/math/m_xform.h
index 24e8ddbd57..33421ad1c0 100644
--- a/src/mesa/math/m_xform.h
+++ b/src/mesa/math/m_xform.h
@@ -42,12 +42,9 @@
extern void
-_mesa_transform_vector(GLfloat u[4], CONST GLfloat v[4], CONST GLfloat m[16]);
-
-
-extern void
_math_init_transformation(void);
-
+extern void
+init_c_cliptest(void);
/* KW: Clip functions now do projective divide as well. The projected
* coordinates are very useful to us because they let us cull
@@ -106,7 +103,8 @@ typedef GLvector4f * (_XFORMAPIP clip_func)( GLvector4f *vClip,
GLvector4f *vProj,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask );
+ GLubyte *andMask,
+ GLboolean viewport_z_clip );
typedef void (*dotprod_func)( GLfloat *out,
GLuint out_stride,
@@ -148,18 +146,6 @@ typedef void (_XFORMAPIP transform_func)( GLvector4f *to_vec,
CONST GLvector4f *from_vec );
-extern GLvector4f *_mesa_project_points( GLvector4f *to,
- CONST GLvector4f *from );
-
-extern void _mesa_transform_bounds3( GLubyte *orMask, GLubyte *andMask,
- CONST GLfloat m[16],
- CONST GLfloat src[][3] );
-
-extern void _mesa_transform_bounds2( GLubyte *orMask, GLubyte *andMask,
- CONST GLfloat m[16],
- CONST GLfloat src[][3] );
-
-
extern dotprod_func _mesa_dotprod_tab[5];
extern vec_copy_func _mesa_copy_tab[0x10];
extern vec_copy_func _mesa_copy_clean_tab[5];
@@ -173,9 +159,6 @@ extern normal_func _mesa_normal_tab[0xf];
extern transform_func *_mesa_transform_tab[5];
-extern void _mesa_transform_point_sz( GLfloat Q[4], CONST GLfloat M[16],
- CONST GLfloat P[4], GLuint sz );
-
#define TransformRaw( to, mat, from ) \
( _mesa_transform_tab[(from)->size][(mat)->type]( to, (mat)->m, from ), \
diff --git a/src/mesa/ppc/common_ppc.c b/src/mesa/ppc/common_ppc.c
index 786e1817ac..c7cec96e5d 100644
--- a/src/mesa/ppc/common_ppc.c
+++ b/src/mesa/ppc/common_ppc.c
@@ -85,7 +85,7 @@ void _mesa_init_all_ppc_transform_asm( void )
}
# ifndef USE_VMX_ASM
- _mesa_ppc_cpu_features &= ~PPC_FEATURES_HAS_ALTIVEC;
+ _mesa_ppc_cpu_features &= ~PPC_FEATURE_HAS_ALTIVEC;
# endif
#endif
}
diff --git a/src/mesa/shader/.gitignore b/src/mesa/shader/.gitignore
new file mode 100644
index 0000000000..086fd9a705
--- /dev/null
+++ b/src/mesa/shader/.gitignore
@@ -0,0 +1 @@
+program_parse.output
diff --git a/src/mesa/shader/Makefile b/src/mesa/shader/Makefile
new file mode 100644
index 0000000000..400a543bda
--- /dev/null
+++ b/src/mesa/shader/Makefile
@@ -0,0 +1,7 @@
+all: program_parse.tab.c lex.yy.c
+
+program_parse.tab.c program_parse.tab.h: program_parse.y
+ bison -v -d $<
+
+lex.yy.c: program_lexer.l
+ flex --never-interactive $<
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c
index a3a75c3b0a..05ee4f563e 100644
--- a/src/mesa/shader/arbprogparse.c
+++ b/src/mesa/shader/arbprogparse.c
@@ -30,6 +30,27 @@
* \author Karl Rasche
*/
+/**
+Notes on program parameters, etc.
+
+The instructions we emit will use six kinds of source registers:
+
+ PROGRAM_INPUT - input registers
+ PROGRAM_TEMPORARY - temp registers
+ PROGRAM_ADDRESS - address/indirect register
+ PROGRAM_SAMPLER - texture sampler
+ PROGRAM_CONSTANT - indexes into program->Parameters, a known constant/literal
+ PROGRAM_STATE_VAR - indexes into program->Parameters, and may actually be:
+ + a state variable, like "state.fog.color", or
+ + a pointer to a "program.local[k]" parameter, or
+ + a pointer to a "program.env[k]" parameter
+
+Basically, all the program.local[] and program.env[] values will get mapped
+into the unified gl_program->Parameters array. This solves the problem of
+having three separate program parameter arrays.
+*/
+
+
#include "main/glheader.h"
#include "main/imports.h"
#include "main/context.h"
@@ -38,3809 +59,11 @@
#include "shader/grammar/grammar_mesa.h"
#include "arbprogparse.h"
#include "program.h"
+#include "programopt.h"
#include "prog_parameter.h"
#include "prog_statevars.h"
#include "prog_instruction.h"
-
-
-/* For ARB programs, use the NV instruction limits */
-#define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \
- MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
-
-
-/**
- * This is basically a union of the vertex_program and fragment_program
- * structs that we can use to parse the program into
- *
- * XXX we can probably get rid of this entirely someday.
- */
-struct arb_program
-{
- struct gl_program Base;
-
- GLuint Position; /* Just used for error reporting while parsing */
- GLuint MajorVersion;
- GLuint MinorVersion;
-
- /* ARB_vertex_progmra options */
- GLboolean HintPositionInvariant;
-
- /* ARB_fragment_progmra options */
- GLenum PrecisionOption; /* GL_DONT_CARE, GL_NICEST or GL_FASTEST */
- GLenum FogOption; /* GL_NONE, GL_LINEAR, GL_EXP or GL_EXP2 */
-
- /* ARB_fragment_program specifics */
- GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS];
- GLbitfield ShadowSamplers;
- GLuint NumAluInstructions;
- GLuint NumTexInstructions;
- GLuint NumTexIndirections;
-
- GLboolean UsesKill;
-};
-
-
-
-/* TODO:
- * Fragment Program Stuff:
- * -----------------------------------------------------
- *
- * - things from Michal's email
- * + overflow on atoi
- * + not-overflowing floats (don't use parse_integer..)
- * + can remove range checking in arbparse.c
- *
- * - check all limits of number of various variables
- * + parameters
- *
- * - test! test! test!
- *
- * Vertex Program Stuff:
- * -----------------------------------------------------
- * - Optimize param array usage and count limits correctly, see spec,
- * section 2.14.3.7
- * + Record if an array is reference absolutly or relatively (or both)
- * + For absolute arrays, store a bitmap of accesses
- * + For single parameters, store an access flag
- * + After parsing, make a parameter cleanup and merging pass, where
- * relative arrays are layed out first, followed by abs arrays, and
- * finally single state.
- * + Remap offsets for param src and dst registers
- * + Now we can properly count parameter usage
- *
- * - Multiple state binding errors in param arrays (see spec, just before
- * section 2.14.3.3)
- * - grep for XXX
- *
- * Mesa Stuff
- * -----------------------------------------------------
- * - User clipping planes vs. PositionInvariant
- * - Is it sufficient to just multiply by the mvp to transform in the
- * PositionInvariant case? Or do we need something more involved?
- *
- * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
- * - fetch state listed in program_parameters list
- * + WTF should this go???
- * + currently in nvvertexec.c and s_nvfragprog.c
- *
- * - allow for multiple address registers (and fetch address regs properly)
- *
- * Cosmetic Stuff
- * -----------------------------------------------------
- * - remove any leftover unused grammer.c stuff (dict_ ?)
- * - fix grammer.c error handling so its not static
- * - #ifdef around stuff pertaining to extentions
- *
- * Outstanding Questions:
- * -----------------------------------------------------
- * - ARB_matrix_palette / ARB_vertex_blend -- not supported
- * what gets hacked off because of this:
- * + VERTEX_ATTRIB_MATRIXINDEX
- * + VERTEX_ATTRIB_WEIGHT
- * + MATRIX_MODELVIEW
- * + MATRIX_PALETTE
- *
- * - When can we fetch env/local params from their own register files, and
- * when to we have to fetch them into the main state register file?
- * (think arrays)
- *
- * Grammar Changes:
- * -----------------------------------------------------
- */
-
-/* Changes since moving the file to shader directory
-
-2004-III-4 ------------------------------------------------------------
-- added #include "grammar_mesa.h"
-- removed grammar specific code part (it resides now in grammar.c)
-- added GL_ARB_fragment_program_shadow tokens
-- modified #include "arbparse_syn.h"
-- major changes inside _mesa_parse_arb_program()
-- check the program string for '\0' characters
-- copy the program string to a one-byte-longer location to have
- it null-terminated
-- position invariance test (not writing to result.position) moved
- to syntax part
-*/
-
-typedef GLubyte *production;
-
-
-/**
- * This is the text describing the rules to parse the grammar
- */
-LONGSTRING static char arb_grammar_text[] =
-#include "arbprogram_syn.h"
-;
-
-/**
- * These should match up with the values defined in arbprogram.syn
- */
-
-/*
- Changes:
- - changed and merged V_* and F_* opcode values to OP_*.
- - added GL_ARB_fragment_program_shadow specific tokens (michal)
-*/
-#define REVISION 0x0a
-
-/* program type */
-#define FRAGMENT_PROGRAM 0x01
-#define VERTEX_PROGRAM 0x02
-
-/* program section */
-#define OPTION 0x01
-#define INSTRUCTION 0x02
-#define DECLARATION 0x03
-#define END 0x04
-
-/* GL_ARB_fragment_program option */
-#define ARB_PRECISION_HINT_FASTEST 0x00
-#define ARB_PRECISION_HINT_NICEST 0x01
-#define ARB_FOG_EXP 0x02
-#define ARB_FOG_EXP2 0x03
-#define ARB_FOG_LINEAR 0x04
-
-/* GL_ARB_vertex_program option */
-#define ARB_POSITION_INVARIANT 0x05
-
-/* GL_ARB_fragment_program_shadow option */
-#define ARB_FRAGMENT_PROGRAM_SHADOW 0x06
-
-/* GL_ARB_draw_buffers option */
-#define ARB_DRAW_BUFFERS 0x07
-
-/* GL_MESA_texture_array option */
-#define MESA_TEXTURE_ARRAY 0x08
-
-/* GL_ARB_fragment_program instruction class */
-#define OP_ALU_INST 0x00
-#define OP_TEX_INST 0x01
-
-/* GL_ARB_vertex_program instruction class */
-/* OP_ALU_INST */
-
-/* GL_ARB_fragment_program instruction type */
-#define OP_ALU_VECTOR 0x00
-#define OP_ALU_SCALAR 0x01
-#define OP_ALU_BINSC 0x02
-#define OP_ALU_BIN 0x03
-#define OP_ALU_TRI 0x04
-#define OP_ALU_SWZ 0x05
-#define OP_TEX_SAMPLE 0x06
-#define OP_TEX_KIL 0x07
-
-/* GL_ARB_vertex_program instruction type */
-#define OP_ALU_ARL 0x08
-/* OP_ALU_VECTOR */
-/* OP_ALU_SCALAR */
-/* OP_ALU_BINSC */
-/* OP_ALU_BIN */
-/* OP_ALU_TRI */
-/* OP_ALU_SWZ */
-
-/* GL_ARB_fragment_program instruction code */
-#define OP_ABS 0x00
-#define OP_ABS_SAT 0x1B
-#define OP_FLR 0x09
-#define OP_FLR_SAT 0x26
-#define OP_FRC 0x0A
-#define OP_FRC_SAT 0x27
-#define OP_LIT 0x0C
-#define OP_LIT_SAT 0x2A
-#define OP_MOV 0x11
-#define OP_MOV_SAT 0x30
-#define OP_COS 0x1F
-#define OP_COS_SAT 0x20
-#define OP_EX2 0x07
-#define OP_EX2_SAT 0x25
-#define OP_LG2 0x0B
-#define OP_LG2_SAT 0x29
-#define OP_RCP 0x14
-#define OP_RCP_SAT 0x33
-#define OP_RSQ 0x15
-#define OP_RSQ_SAT 0x34
-#define OP_SIN 0x38
-#define OP_SIN_SAT 0x39
-#define OP_SCS 0x35
-#define OP_SCS_SAT 0x36
-#define OP_POW 0x13
-#define OP_POW_SAT 0x32
-#define OP_ADD 0x01
-#define OP_ADD_SAT 0x1C
-#define OP_DP3 0x03
-#define OP_DP3_SAT 0x21
-#define OP_DP4 0x04
-#define OP_DP4_SAT 0x22
-#define OP_DPH 0x05
-#define OP_DPH_SAT 0x23
-#define OP_DST 0x06
-#define OP_DST_SAT 0x24
-#define OP_MAX 0x0F
-#define OP_MAX_SAT 0x2E
-#define OP_MIN 0x10
-#define OP_MIN_SAT 0x2F
-#define OP_MUL 0x12
-#define OP_MUL_SAT 0x31
-#define OP_SGE 0x16
-#define OP_SGE_SAT 0x37
-#define OP_SLT 0x17
-#define OP_SLT_SAT 0x3A
-#define OP_SUB 0x18
-#define OP_SUB_SAT 0x3B
-#define OP_XPD 0x1A
-#define OP_XPD_SAT 0x43
-#define OP_CMP 0x1D
-#define OP_CMP_SAT 0x1E
-#define OP_LRP 0x2B
-#define OP_LRP_SAT 0x2C
-#define OP_MAD 0x0E
-#define OP_MAD_SAT 0x2D
-#define OP_SWZ 0x19
-#define OP_SWZ_SAT 0x3C
-#define OP_TEX 0x3D
-#define OP_TEX_SAT 0x3E
-#define OP_TXB 0x3F
-#define OP_TXB_SAT 0x40
-#define OP_TXP 0x41
-#define OP_TXP_SAT 0x42
-#define OP_KIL 0x28
-
-/* GL_ARB_vertex_program instruction code */
-#define OP_ARL 0x02
-/* OP_ABS */
-/* OP_FLR */
-/* OP_FRC */
-/* OP_LIT */
-/* OP_MOV */
-/* OP_EX2 */
-#define OP_EXP 0x08
-/* OP_LG2 */
-#define OP_LOG 0x0D
-/* OP_RCP */
-/* OP_RSQ */
-/* OP_POW */
-/* OP_ADD */
-/* OP_DP3 */
-/* OP_DP4 */
-/* OP_DPH */
-/* OP_DST */
-/* OP_MAX */
-/* OP_MIN */
-/* OP_MUL */
-/* OP_SGE */
-/* OP_SLT */
-/* OP_SUB */
-/* OP_XPD */
-/* OP_MAD */
-/* OP_SWZ */
-
-/* fragment attribute binding */
-#define FRAGMENT_ATTRIB_COLOR 0x01
-#define FRAGMENT_ATTRIB_TEXCOORD 0x02
-#define FRAGMENT_ATTRIB_FOGCOORD 0x03
-#define FRAGMENT_ATTRIB_POSITION 0x04
-
-/* vertex attribute binding */
-#define VERTEX_ATTRIB_POSITION 0x01
-#define VERTEX_ATTRIB_WEIGHT 0x02
-#define VERTEX_ATTRIB_NORMAL 0x03
-#define VERTEX_ATTRIB_COLOR 0x04
-#define VERTEX_ATTRIB_FOGCOORD 0x05
-#define VERTEX_ATTRIB_TEXCOORD 0x06
-#define VERTEX_ATTRIB_MATRIXINDEX 0x07
-#define VERTEX_ATTRIB_GENERIC 0x08
-
-/* fragment result binding */
-#define FRAGMENT_RESULT_COLOR 0x01
-#define FRAGMENT_RESULT_DEPTH 0x02
-
-/* vertex result binding */
-#define VERTEX_RESULT_POSITION 0x01
-#define VERTEX_RESULT_COLOR 0x02
-#define VERTEX_RESULT_FOGCOORD 0x03
-#define VERTEX_RESULT_POINTSIZE 0x04
-#define VERTEX_RESULT_TEXCOORD 0x05
-
-/* texture target */
-#define TEXTARGET_1D 0x01
-#define TEXTARGET_2D 0x02
-#define TEXTARGET_3D 0x03
-#define TEXTARGET_RECT 0x04
-#define TEXTARGET_CUBE 0x05
-/* GL_ARB_fragment_program_shadow */
-#define TEXTARGET_SHADOW1D 0x06
-#define TEXTARGET_SHADOW2D 0x07
-#define TEXTARGET_SHADOWRECT 0x08
-/* GL_MESA_texture_array */
-#define TEXTARGET_1D_ARRAY 0x09
-#define TEXTARGET_2D_ARRAY 0x0a
-#define TEXTARGET_SHADOW1D_ARRAY 0x0b
-#define TEXTARGET_SHADOW2D_ARRAY 0x0c
-
-/* face type */
-#define FACE_FRONT 0x00
-#define FACE_BACK 0x01
-
-/* color type */
-#define COLOR_PRIMARY 0x00
-#define COLOR_SECONDARY 0x01
-
-/* component */
-#define COMPONENT_X 0x00
-#define COMPONENT_Y 0x01
-#define COMPONENT_Z 0x02
-#define COMPONENT_W 0x03
-#define COMPONENT_0 0x04
-#define COMPONENT_1 0x05
-
-/* array index type */
-#define ARRAY_INDEX_ABSOLUTE 0x00
-#define ARRAY_INDEX_RELATIVE 0x01
-
-/* matrix name */
-#define MATRIX_MODELVIEW 0x01
-#define MATRIX_PROJECTION 0x02
-#define MATRIX_MVP 0x03
-#define MATRIX_TEXTURE 0x04
-#define MATRIX_PALETTE 0x05
-#define MATRIX_PROGRAM 0x06
-
-/* matrix modifier */
-#define MATRIX_MODIFIER_IDENTITY 0x00
-#define MATRIX_MODIFIER_INVERSE 0x01
-#define MATRIX_MODIFIER_TRANSPOSE 0x02
-#define MATRIX_MODIFIER_INVTRANS 0x03
-
-/* constant type */
-#define CONSTANT_SCALAR 0x01
-#define CONSTANT_VECTOR 0x02
-
-/* program param type */
-#define PROGRAM_PARAM_ENV 0x01
-#define PROGRAM_PARAM_LOCAL 0x02
-
-/* register type */
-#define REGISTER_ATTRIB 0x01
-#define REGISTER_PARAM 0x02
-#define REGISTER_RESULT 0x03
-#define REGISTER_ESTABLISHED_NAME 0x04
-
-/* param binding */
-#define PARAM_NULL 0x00
-#define PARAM_ARRAY_ELEMENT 0x01
-#define PARAM_STATE_ELEMENT 0x02
-#define PARAM_PROGRAM_ELEMENT 0x03
-#define PARAM_PROGRAM_ELEMENTS 0x04
-#define PARAM_CONSTANT 0x05
-
-/* param state property */
-#define STATE_MATERIAL_PARSER 0x01
-#define STATE_LIGHT_PARSER 0x02
-#define STATE_LIGHT_MODEL 0x03
-#define STATE_LIGHT_PROD 0x04
-#define STATE_FOG 0x05
-#define STATE_MATRIX_ROWS 0x06
-/* GL_ARB_fragment_program */
-#define STATE_TEX_ENV 0x07
-#define STATE_DEPTH 0x08
-/* GL_ARB_vertex_program */
-#define STATE_TEX_GEN 0x09
-#define STATE_CLIP_PLANE 0x0A
-#define STATE_POINT 0x0B
-
-/* state material property */
-#define MATERIAL_AMBIENT 0x01
-#define MATERIAL_DIFFUSE 0x02
-#define MATERIAL_SPECULAR 0x03
-#define MATERIAL_EMISSION 0x04
-#define MATERIAL_SHININESS 0x05
-
-/* state light property */
-#define LIGHT_AMBIENT 0x01
-#define LIGHT_DIFFUSE 0x02
-#define LIGHT_SPECULAR 0x03
-#define LIGHT_POSITION 0x04
-#define LIGHT_ATTENUATION 0x05
-#define LIGHT_HALF 0x06
-#define LIGHT_SPOT_DIRECTION 0x07
-
-/* state light model property */
-#define LIGHT_MODEL_AMBIENT 0x01
-#define LIGHT_MODEL_SCENECOLOR 0x02
-
-/* state light product property */
-#define LIGHT_PROD_AMBIENT 0x01
-#define LIGHT_PROD_DIFFUSE 0x02
-#define LIGHT_PROD_SPECULAR 0x03
-
-/* state texture environment property */
-#define TEX_ENV_COLOR 0x01
-
-/* state texture generation coord property */
-#define TEX_GEN_EYE 0x01
-#define TEX_GEN_OBJECT 0x02
-
-/* state fog property */
-#define FOG_COLOR 0x01
-#define FOG_PARAMS 0x02
-
-/* state depth property */
-#define DEPTH_RANGE 0x01
-
-/* state point parameters property */
-#define POINT_SIZE 0x01
-#define POINT_ATTENUATION 0x02
-
-/* declaration */
-#define ATTRIB 0x01
-#define PARAM 0x02
-#define TEMP 0x03
-#define OUTPUT 0x04
-#define ALIAS 0x05
-/* GL_ARB_vertex_program */
-#define ADDRESS 0x06
-
-/*-----------------------------------------------------------------------
- * From here on down is the semantic checking portion
- *
- */
-
-/**
- * Variable Table Handling functions
- */
-typedef enum
-{
- vt_none,
- vt_address,
- vt_attrib,
- vt_param,
- vt_temp,
- vt_output,
- vt_alias
-} var_type;
-
-
-/**
- * Setting an explicit field for each of the binding properties is a bit
- * wasteful of space, but it should be much more clear when reading later on..
- */
-struct var_cache
-{
- const GLubyte *name; /* don't free() - no need */
- var_type type;
- GLuint address_binding; /* The index of the address register we should
- * be using */
- GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
- GLuint attrib_is_generic; /* If the attrib was specified through a generic
- * vertex attrib */
- GLuint temp_binding; /* The index of the temp register we are to use */
- GLuint output_binding; /* Output/result register number */
- struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
- * that this is aliased to */
- GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
- * PROGRAM_ENV_PARAM} */
- GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
- * the tokens representing our bound state (or constants)
- * start */
- GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
- * we take up with our state tokens or constants. Note that
- * this is _not_ the same as the number of param registers
- * we eventually use */
- struct var_cache *next;
-};
-
-static GLvoid
-var_cache_create (struct var_cache **va)
-{
- *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
- if (*va) {
- (**va).name = NULL;
- (**va).type = vt_none;
- (**va).attrib_binding = ~0;
- (**va).attrib_is_generic = 0;
- (**va).temp_binding = ~0;
- (**va).output_binding = ~0;
- (**va).param_binding_type = ~0;
- (**va).param_binding_begin = ~0;
- (**va).param_binding_length = ~0;
- (**va).alias_binding = NULL;
- (**va).next = NULL;
- }
-}
-
-static GLvoid
-var_cache_destroy (struct var_cache **va)
-{
- if (*va) {
- var_cache_destroy (&(**va).next);
- _mesa_free (*va);
- *va = NULL;
- }
-}
-
-static GLvoid
-var_cache_append (struct var_cache **va, struct var_cache *nv)
-{
- if (*va)
- var_cache_append (&(**va).next, nv);
- else
- *va = nv;
-}
-
-static struct var_cache *
-var_cache_find (struct var_cache *va, const GLubyte * name)
-{
- /*struct var_cache *first = va;*/
-
- while (va) {
- if (!_mesa_strcmp ( (const char*) name, (const char*) va->name)) {
- if (va->type == vt_alias)
- return va->alias_binding;
- return va;
- }
-
- va = va->next;
- }
-
- return NULL;
-}
-
-
-
-/**
- * Called when an error is detected while parsing/compiling a program.
- * Sets the ctx->Program.ErrorString field to descript and records a
- * GL_INVALID_OPERATION error.
- * \param position position of error in program string
- * \param descrip verbose error description
- */
-static void
-program_error(GLcontext *ctx, GLint position, const char *descrip)
-{
- if (descrip) {
- const char *prefix = "glProgramString(", *suffix = ")";
- char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
- _mesa_strlen(prefix) +
- _mesa_strlen(suffix) + 1);
- if (str) {
- _mesa_sprintf(str, "%s%s%s", prefix, descrip, suffix);
- _mesa_error(ctx, GL_INVALID_OPERATION, str);
- _mesa_free(str);
- }
- }
- _mesa_set_program_error(ctx, position, descrip);
-}
-
-
-/**
- * As above, but with an extra string parameter for more info.
- */
-static void
-program_error2(GLcontext *ctx, GLint position, const char *descrip,
- const char *var)
-{
- if (descrip) {
- const char *prefix = "glProgramString(", *suffix = ")";
- char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
- _mesa_strlen(": ") +
- _mesa_strlen(var) +
- _mesa_strlen(prefix) +
- _mesa_strlen(suffix) + 1);
- if (str) {
- _mesa_sprintf(str, "%s%s: %s%s", prefix, descrip, var, suffix);
- _mesa_error(ctx, GL_INVALID_OPERATION, str);
- _mesa_free(str);
- }
- }
- {
- char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
- _mesa_strlen(": ") +
- _mesa_strlen(var) + 1);
- if (str) {
- _mesa_sprintf(str, "%s: %s", descrip, var);
- }
- _mesa_set_program_error(ctx, position, str);
- if (str) {
- _mesa_free(str);
- }
- }
-}
-
-
-
-/**
- * constructs an integer from 4 GLubytes in LE format
- */
-static GLuint
-parse_position (const GLubyte ** inst)
-{
- GLuint value;
-
- value = (GLuint) (*(*inst)++);
- value += (GLuint) (*(*inst)++) * 0x100;
- value += (GLuint) (*(*inst)++) * 0x10000;
- value += (GLuint) (*(*inst)++) * 0x1000000;
-
- return value;
-}
-
-/**
- * This will, given a string, lookup the string as a variable name in the
- * var cache. If the name is found, the var cache node corresponding to the
- * var name is returned. If it is not found, a new entry is allocated
- *
- * \param I Points into the binary array where the string identifier begins
- * \param found 1 if the string was found in the var_cache, 0 if it was allocated
- * \return The location on the var_cache corresponding the the string starting at I
- */
-static struct var_cache *
-parse_string (const GLubyte ** inst, struct var_cache **vc_head,
- struct arb_program *Program, GLuint * found)
-{
- const GLubyte *i = *inst;
- struct var_cache *va = NULL;
- (void) Program;
-
- *inst += _mesa_strlen ((char *) i) + 1;
-
- va = var_cache_find (*vc_head, i);
-
- if (va) {
- *found = 1;
- return va;
- }
-
- *found = 0;
- var_cache_create (&va);
- va->name = (const GLubyte *) i;
-
- var_cache_append (vc_head, va);
-
- return va;
-}
-
-static char *
-parse_string_without_adding (const GLubyte ** inst, struct arb_program *Program)
-{
- const GLubyte *i = *inst;
- (void) Program;
-
- *inst += _mesa_strlen ((char *) i) + 1;
-
- return (char *) i;
-}
-
-/**
- * \return -1 if we parse '-', return 1 otherwise
- */
-static GLint
-parse_sign (const GLubyte ** inst)
-{
- /*return *(*inst)++ != '+'; */
-
- if (**inst == '-') {
- (*inst)++;
- return -1;
- }
- else if (**inst == '+') {
- (*inst)++;
- return 1;
- }
-
- return 1;
-}
-
-/**
- * parses and returns signed integer
- */
-static GLint
-parse_integer (const GLubyte ** inst, struct arb_program *Program)
-{
- GLint sign;
- GLint value;
-
- /* check if *inst points to '+' or '-'
- * if yes, grab the sign and increment *inst
- */
- sign = parse_sign (inst);
-
- /* now check if *inst points to 0
- * if yes, increment the *inst and return the default value
- */
- if (**inst == 0) {
- (*inst)++;
- return 0;
- }
-
- /* parse the integer as you normally would do it */
- value = _mesa_atoi (parse_string_without_adding (inst, Program));
-
- /* now, after terminating 0 there is a position
- * to parse it - parse_position()
- */
- Program->Position = parse_position (inst);
-
- return value * sign;
-}
-
-/**
- Accumulate this string of digits, and return them as
- a large integer represented in floating point (for range).
- If scale is not NULL, also accumulates a power-of-ten
- integer scale factor that represents the number of digits
- in the string.
-*/
-static GLdouble
-parse_float_string(const GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
-{
- GLdouble value = 0.0;
- GLdouble oscale = 1.0;
-
- if (**inst == 0) { /* this string of digits is empty-- do nothing */
- (*inst)++;
- }
- else { /* nonempty string-- parse out the digits */
- while (**inst >= '0' && **inst <= '9') {
- GLubyte digit = *((*inst)++);
- value = value * 10.0 + (GLint) (digit - '0');
- oscale *= 10.0;
- }
- assert(**inst == 0); /* integer string should end with 0 */
- (*inst)++; /* skip over terminating 0 */
- Program->Position = parse_position(inst); /* skip position (from integer) */
- }
- if (scale)
- *scale = oscale;
- return value;
-}
-
-/**
- Parse an unsigned floating-point number from this stream of tokenized
- characters. Example floating-point formats supported:
- 12.34
- 12
- 0.34
- .34
- 12.34e-4
- */
-static GLfloat
-parse_float (const GLubyte ** inst, struct arb_program *Program)
-{
- GLint exponent;
- GLdouble whole, fraction, fracScale = 1.0;
-
- whole = parse_float_string(inst, Program, 0);
- fraction = parse_float_string(inst, Program, &fracScale);
-
- /* Parse signed exponent */
- exponent = parse_integer(inst, Program); /* This is the exponent */
-
- /* Assemble parts of floating-point number: */
- return (GLfloat) ((whole + fraction / fracScale) *
- _mesa_pow(10.0, (GLfloat) exponent));
-}
-
-
-/**
- */
-static GLfloat
-parse_signed_float (const GLubyte ** inst, struct arb_program *Program)
-{
- GLint sign = parse_sign (inst);
- GLfloat value = parse_float (inst, Program);
- return value * sign;
-}
-
-/**
- * This picks out a constant value from the parsed array. The constant vector is r
- * returned in the *values array, which should be of length 4.
- *
- * \param values - The 4 component vector with the constant value in it
- */
-static GLvoid
-parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Program,
- GLboolean use)
-{
- GLuint components, i;
-
-
- switch (*(*inst)++) {
- case CONSTANT_SCALAR:
- if (use == GL_TRUE) {
- values[0] =
- values[1] =
- values[2] = values[3] = parse_float (inst, Program);
- }
- else {
- values[0] =
- values[1] =
- values[2] = values[3] = parse_signed_float (inst, Program);
- }
-
- break;
- case CONSTANT_VECTOR:
- values[0] = values[1] = values[2] = 0;
- values[3] = 1;
- components = *(*inst)++;
- for (i = 0; i < components; i++) {
- values[i] = parse_signed_float (inst, Program);
- }
- break;
- }
-}
-
-/**
- * \param offset The offset from the address register that we should
- * address
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_relative_offset(GLcontext *ctx, const GLubyte **inst,
- struct arb_program *Program, GLint *offset)
-{
- (void) ctx;
- *offset = parse_integer(inst, Program);
- return 0;
-}
-
-/**
- * \param color 0 if color type is primary, 1 if color type is secondary
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_color_type (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
- GLint * color)
-{
- (void) ctx; (void) Program;
- *color = *(*inst)++ != COLOR_PRIMARY;
- return 0;
-}
-
-/**
- * Get an integer corresponding to a generic vertex attribute.
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_generic_attrib_num(GLcontext *ctx, const GLubyte ** inst,
- struct arb_program *Program, GLuint *attrib)
-{
- GLint i = parse_integer(inst, Program);
-
- if ((i < 0) || (i >= MAX_VERTEX_PROGRAM_ATTRIBS))
- {
- program_error(ctx, Program->Position,
- "Invalid generic vertex attribute index");
- return 1;
- }
-
- *attrib = (GLuint) i;
-
- return 0;
-}
-
-
-/**
- * \param color The index of the color buffer to write into
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_output_color_num (GLcontext * ctx, const GLubyte ** inst,
- struct arb_program *Program, GLuint * color)
-{
- GLint i = parse_integer (inst, Program);
-
- if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
- program_error(ctx, Program->Position, "Invalid draw buffer index");
- return 1;
- }
-
- *color = (GLuint) i;
- return 0;
-}
-
-
-/**
- * Validate the index of a texture coordinate
- *
- * \param coord The texture unit index
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_texcoord_num (GLcontext * ctx, const GLubyte ** inst,
- struct arb_program *Program, GLuint * coord)
-{
- GLint i = parse_integer (inst, Program);
-
- if ((i < 0) || (i >= (int)ctx->Const.MaxTextureCoordUnits)) {
- program_error(ctx, Program->Position, "Invalid texture coordinate index");
- return 1;
- }
-
- *coord = (GLuint) i;
- return 0;
-}
-
-
-/**
- * Validate the index of a texture image unit
- *
- * \param coord The texture unit index
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_teximage_num (GLcontext * ctx, const GLubyte ** inst,
- struct arb_program *Program, GLuint * coord)
-{
- GLint i = parse_integer (inst, Program);
-
- if ((i < 0) || (i >= (int)ctx->Const.MaxTextureImageUnits)) {
- program_error(ctx, Program->Position, "Invalid texture image index");
- return 1;
- }
-
- *coord = (GLuint) i;
- return 0;
-}
-
-
-/**
- * \param coord The weight index
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_weight_num (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
- GLint * coord)
-{
- *coord = parse_integer (inst, Program);
-
- if ((*coord < 0) || (*coord >= 1)) {
- program_error(ctx, Program->Position, "Invalid weight index");
- return 1;
- }
-
- return 0;
-}
-
-/**
- * \param coord The clip plane index
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_clipplane_num (GLcontext * ctx, const GLubyte ** inst,
- struct arb_program *Program, GLint * coord)
-{
- *coord = parse_integer (inst, Program);
-
- if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
- program_error(ctx, Program->Position, "Invalid clip plane index");
- return 1;
- }
-
- return 0;
-}
-
-
-/**
- * \return 0 on front face, 1 on back face
- */
-static GLuint
-parse_face_type (const GLubyte ** inst)
-{
- switch (*(*inst)++) {
- case FACE_FRONT:
- return 0;
-
- case FACE_BACK:
- return 1;
- }
- return 0;
-}
-
-
-/**
- * Given a matrix and a modifier token on the binary array, return tokens
- * that _mesa_fetch_state() [program.c] can understand.
- *
- * \param matrix - the matrix we are talking about
- * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
- * \param matrix_modifier - the matrix modifier (trans, inv, etc)
- * \return 0 on sucess, 1 on failure
- */
-static GLuint
-parse_matrix (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
- GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
-{
- GLubyte mat = *(*inst)++;
-
- *matrix_idx = 0;
-
- switch (mat) {
- case MATRIX_MODELVIEW:
- *matrix = STATE_MODELVIEW_MATRIX;
- *matrix_idx = parse_integer (inst, Program);
- if (*matrix_idx > 0) {
- program_error(ctx, Program->Position,
- "ARB_vertex_blend not supported");
- return 1;
- }
- break;
-
- case MATRIX_PROJECTION:
- *matrix = STATE_PROJECTION_MATRIX;
- break;
-
- case MATRIX_MVP:
- *matrix = STATE_MVP_MATRIX;
- break;
-
- case MATRIX_TEXTURE:
- *matrix = STATE_TEXTURE_MATRIX;
- *matrix_idx = parse_integer (inst, Program);
- if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
- program_error(ctx, Program->Position, "Invalid Texture Unit");
- /* bad *matrix_id */
- return 1;
- }
- break;
-
- /* This is not currently supported (ARB_matrix_palette) */
- case MATRIX_PALETTE:
- *matrix_idx = parse_integer (inst, Program);
- program_error(ctx, Program->Position,
- "ARB_matrix_palette not supported");
- return 1;
- break;
-
- case MATRIX_PROGRAM:
- *matrix = STATE_PROGRAM_MATRIX;
- *matrix_idx = parse_integer (inst, Program);
- if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
- program_error(ctx, Program->Position, "Invalid Program Matrix");
- /* bad *matrix_idx */
- return 1;
- }
- break;
- }
-
- switch (*(*inst)++) {
- case MATRIX_MODIFIER_IDENTITY:
- *matrix_modifier = 0;
- break;
- case MATRIX_MODIFIER_INVERSE:
- *matrix_modifier = STATE_MATRIX_INVERSE;
- break;
- case MATRIX_MODIFIER_TRANSPOSE:
- *matrix_modifier = STATE_MATRIX_TRANSPOSE;
- break;
- case MATRIX_MODIFIER_INVTRANS:
- *matrix_modifier = STATE_MATRIX_INVTRANS;
- break;
- }
-
- return 0;
-}
-
-
-/**
- * This parses a state string (rather, the binary version of it) into
- * a 6-token sequence as described in _mesa_fetch_state() [program.c]
- *
- * \param inst - the start in the binary arry to start working from
- * \param state_tokens - the storage for the 6-token state description
- * \return - 0 on sucess, 1 on error
- */
-static GLuint
-parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
- struct arb_program *Program,
- gl_state_index state_tokens[STATE_LENGTH])
-{
- GLubyte token = *(*inst)++;
-
- switch (token) {
- case STATE_MATERIAL_PARSER:
- state_tokens[0] = STATE_MATERIAL;
- state_tokens[1] = parse_face_type (inst);
- switch (*(*inst)++) {
- case MATERIAL_AMBIENT:
- state_tokens[2] = STATE_AMBIENT;
- break;
- case MATERIAL_DIFFUSE:
- state_tokens[2] = STATE_DIFFUSE;
- break;
- case MATERIAL_SPECULAR:
- state_tokens[2] = STATE_SPECULAR;
- break;
- case MATERIAL_EMISSION:
- state_tokens[2] = STATE_EMISSION;
- break;
- case MATERIAL_SHININESS:
- state_tokens[2] = STATE_SHININESS;
- break;
- }
- break;
-
- case STATE_LIGHT_PARSER:
- state_tokens[0] = STATE_LIGHT;
- state_tokens[1] = parse_integer (inst, Program);
-
- /* Check the value of state_tokens[1] against the # of lights */
- if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
- program_error(ctx, Program->Position, "Invalid Light Number");
- /* bad state_tokens[1] */
- return 1;
- }
-
- switch (*(*inst)++) {
- case LIGHT_AMBIENT:
- state_tokens[2] = STATE_AMBIENT;
- break;
- case LIGHT_DIFFUSE:
- state_tokens[2] = STATE_DIFFUSE;
- break;
- case LIGHT_SPECULAR:
- state_tokens[2] = STATE_SPECULAR;
- break;
- case LIGHT_POSITION:
- state_tokens[2] = STATE_POSITION;
- break;
- case LIGHT_ATTENUATION:
- state_tokens[2] = STATE_ATTENUATION;
- break;
- case LIGHT_HALF:
- state_tokens[2] = STATE_HALF_VECTOR;
- break;
- case LIGHT_SPOT_DIRECTION:
- state_tokens[2] = STATE_SPOT_DIRECTION;
- break;
- }
- break;
-
- case STATE_LIGHT_MODEL:
- switch (*(*inst)++) {
- case LIGHT_MODEL_AMBIENT:
- state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
- break;
- case LIGHT_MODEL_SCENECOLOR:
- state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
- state_tokens[1] = parse_face_type (inst);
- break;
- }
- break;
-
- case STATE_LIGHT_PROD:
- state_tokens[0] = STATE_LIGHTPROD;
- state_tokens[1] = parse_integer (inst, Program);
-
- /* Check the value of state_tokens[1] against the # of lights */
- if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
- program_error(ctx, Program->Position, "Invalid Light Number");
- /* bad state_tokens[1] */
- return 1;
- }
-
- state_tokens[2] = parse_face_type (inst);
- switch (*(*inst)++) {
- case LIGHT_PROD_AMBIENT:
- state_tokens[3] = STATE_AMBIENT;
- break;
- case LIGHT_PROD_DIFFUSE:
- state_tokens[3] = STATE_DIFFUSE;
- break;
- case LIGHT_PROD_SPECULAR:
- state_tokens[3] = STATE_SPECULAR;
- break;
- }
- break;
-
-
- case STATE_FOG:
- switch (*(*inst)++) {
- case FOG_COLOR:
- state_tokens[0] = STATE_FOG_COLOR;
- break;
- case FOG_PARAMS:
- state_tokens[0] = STATE_FOG_PARAMS;
- break;
- }
- break;
-
- case STATE_TEX_ENV:
- state_tokens[1] = parse_integer (inst, Program);
- switch (*(*inst)++) {
- case TEX_ENV_COLOR:
- state_tokens[0] = STATE_TEXENV_COLOR;
- break;
- }
- break;
-
- case STATE_TEX_GEN:
- {
- GLuint type, coord;
-
- state_tokens[0] = STATE_TEXGEN;
- /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
-
- if (parse_texcoord_num (ctx, inst, Program, &coord))
- return 1;
- state_tokens[1] = coord;
-
- /* EYE or OBJECT */
- type = *(*inst)++;
-
- /* 0 - s, 1 - t, 2 - r, 3 - q */
- coord = *(*inst)++;
-
- if (type == TEX_GEN_EYE) {
- switch (coord) {
- case COMPONENT_X:
- state_tokens[2] = STATE_TEXGEN_EYE_S;
- break;
- case COMPONENT_Y:
- state_tokens[2] = STATE_TEXGEN_EYE_T;
- break;
- case COMPONENT_Z:
- state_tokens[2] = STATE_TEXGEN_EYE_R;
- break;
- case COMPONENT_W:
- state_tokens[2] = STATE_TEXGEN_EYE_Q;
- break;
- default:
- _mesa_problem(ctx, "bad texgen component in "
- "parse_state_single_item()");
- }
- }
- else {
- switch (coord) {
- case COMPONENT_X:
- state_tokens[2] = STATE_TEXGEN_OBJECT_S;
- break;
- case COMPONENT_Y:
- state_tokens[2] = STATE_TEXGEN_OBJECT_T;
- break;
- case COMPONENT_Z:
- state_tokens[2] = STATE_TEXGEN_OBJECT_R;
- break;
- case COMPONENT_W:
- state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
- break;
- default:
- _mesa_problem(ctx, "bad texgen component in "
- "parse_state_single_item()");
- }
- }
- }
- break;
-
- case STATE_DEPTH:
- switch (*(*inst)++) {
- case DEPTH_RANGE:
- state_tokens[0] = STATE_DEPTH_RANGE;
- break;
- }
- break;
-
- case STATE_CLIP_PLANE:
- state_tokens[0] = STATE_CLIPPLANE;
- if (parse_clipplane_num (ctx, inst, Program,
- (GLint *) &state_tokens[1]))
- return 1;
- break;
-
- case STATE_POINT:
- switch (*(*inst)++) {
- case POINT_SIZE:
- state_tokens[0] = STATE_POINT_SIZE;
- break;
-
- case POINT_ATTENUATION:
- state_tokens[0] = STATE_POINT_ATTENUATION;
- break;
- }
- break;
-
- /* XXX: I think this is the correct format for a matrix row */
- case STATE_MATRIX_ROWS:
- if (parse_matrix(ctx, inst, Program,
- (GLint *) &state_tokens[0],
- (GLint *) &state_tokens[1],
- (GLint *) &state_tokens[4]))
- return 1;
-
- state_tokens[2] = parse_integer (inst, Program); /* The first row to grab */
-
- if ((**inst) != 0) { /* Either the last row, 0 */
- state_tokens[3] = parse_integer (inst, Program);
- if (state_tokens[3] < state_tokens[2]) {
- program_error(ctx, Program->Position,
- "Second matrix index less than the first");
- /* state_tokens[4] vs. state_tokens[3] */
- return 1;
- }
- }
- else {
- state_tokens[3] = state_tokens[2];
- (*inst)++;
- }
- break;
- }
-
- return 0;
-}
-
-/**
- * This parses a state string (rather, the binary version of it) into
- * a 6-token similar for the state fetching code in program.c
- *
- * One might ask, why fetch these parameters into just like you fetch
- * state when they are already stored in other places?
- *
- * Because of array offsets -> We can stick env/local parameters in the
- * middle of a parameter array and then index someplace into the array
- * when we execute.
- *
- * One optimization might be to only do this for the cases where the
- * env/local parameters end up inside of an array, and leave the
- * single parameters (or arrays of pure env/local pareameters) in their
- * respective register files.
- *
- * For ENV parameters, the format is:
- * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
- * state_tokens[1] = STATE_ENV
- * state_tokens[2] = the parameter index
- *
- * for LOCAL parameters, the format is:
- * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
- * state_tokens[1] = STATE_LOCAL
- * state_tokens[2] = the parameter index
- *
- * \param inst - the start in the binary arry to start working from
- * \param state_tokens - the storage for the 6-token state description
- * \return - 0 on sucess, 1 on failure
- */
-static GLuint
-parse_program_single_item (GLcontext * ctx, const GLubyte ** inst,
- struct arb_program *Program,
- gl_state_index state_tokens[STATE_LENGTH])
-{
- if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
- state_tokens[0] = STATE_FRAGMENT_PROGRAM;
- else
- state_tokens[0] = STATE_VERTEX_PROGRAM;
-
-
- switch (*(*inst)++) {
- case PROGRAM_PARAM_ENV:
- state_tokens[1] = STATE_ENV;
- state_tokens[2] = parse_integer (inst, Program);
-
- /* Check state_tokens[2] against the number of ENV parameters available */
- if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
- (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxEnvParams))
- ||
- ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
- (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) {
- program_error(ctx, Program->Position,
- "Invalid Program Env Parameter");
- /* bad state_tokens[2] */
- return 1;
- }
-
- break;
-
- case PROGRAM_PARAM_LOCAL:
- state_tokens[1] = STATE_LOCAL;
- state_tokens[2] = parse_integer (inst, Program);
-
- /* Check state_tokens[2] against the number of LOCAL parameters available */
- if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
- (state_tokens[2] >= (GLint) ctx->Const.FragmentProgram.MaxLocalParams))
- ||
- ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
- (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) {
- program_error(ctx, Program->Position,
- "Invalid Program Local Parameter");
- /* bad state_tokens[2] */
- return 1;
- }
- break;
- }
-
- return 0;
-}
-
-/**
- * For ARB_vertex_program, programs are not allowed to use both an explicit
- * vertex attribute and a generic vertex attribute corresponding to the same
- * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
- *
- * This will walk our var_cache and make sure that nobody does anything fishy.
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-generic_attrib_check(struct var_cache *vc_head)
-{
- int a;
- struct var_cache *curr;
- GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
- genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
-
- for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
- explicitAttrib[a] = GL_FALSE;
- genericAttrib[a] = GL_FALSE;
- }
-
- curr = vc_head;
- while (curr) {
- if (curr->type == vt_attrib) {
- if (curr->attrib_is_generic)
- genericAttrib[ curr->attrib_binding ] = GL_TRUE;
- else
- explicitAttrib[ curr->attrib_binding ] = GL_TRUE;
- }
-
- curr = curr->next;
- }
-
- for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
- if ((explicitAttrib[a]) && (genericAttrib[a]))
- return 1;
- }
-
- return 0;
-}
-
-/**
- * This will handle the binding side of an ATTRIB var declaration
- *
- * \param inputReg returns the input register index, one of the
- * VERT_ATTRIB_* or FRAG_ATTRIB_* values.
- * \return returns 0 on success, 1 on error
- */
-static GLuint
-parse_attrib_binding(GLcontext * ctx, const GLubyte ** inst,
- struct arb_program *Program,
- GLuint *inputReg, GLuint *is_generic)
-{
- GLint err = 0;
-
- *is_generic = 0;
-
- if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
- switch (*(*inst)++) {
- case FRAGMENT_ATTRIB_COLOR:
- {
- GLint coord;
- err = parse_color_type (ctx, inst, Program, &coord);
- *inputReg = FRAG_ATTRIB_COL0 + coord;
- }
- break;
- case FRAGMENT_ATTRIB_TEXCOORD:
- {
- GLuint texcoord = 0;
- err = parse_texcoord_num (ctx, inst, Program, &texcoord);
- *inputReg = FRAG_ATTRIB_TEX0 + texcoord;
- }
- break;
- case FRAGMENT_ATTRIB_FOGCOORD:
- *inputReg = FRAG_ATTRIB_FOGC;
- break;
- case FRAGMENT_ATTRIB_POSITION:
- *inputReg = FRAG_ATTRIB_WPOS;
- break;
- default:
- err = 1;
- break;
- }
- }
- else {
- switch (*(*inst)++) {
- case VERTEX_ATTRIB_POSITION:
- *inputReg = VERT_ATTRIB_POS;
- break;
-
- case VERTEX_ATTRIB_WEIGHT:
- {
- GLint weight;
- err = parse_weight_num (ctx, inst, Program, &weight);
- *inputReg = VERT_ATTRIB_WEIGHT;
-#if 1
- /* hack for Warcraft (see bug 8060) */
- _mesa_warning(ctx, "Application error: vertex program uses 'vertex.weight' but GL_ARB_vertex_blend not supported.");
- break;
-#else
- program_error(ctx, Program->Position,
- "ARB_vertex_blend not supported");
- return 1;
-#endif
- }
-
- case VERTEX_ATTRIB_NORMAL:
- *inputReg = VERT_ATTRIB_NORMAL;
- break;
-
- case VERTEX_ATTRIB_COLOR:
- {
- GLint color;
- err = parse_color_type (ctx, inst, Program, &color);
- if (color) {
- *inputReg = VERT_ATTRIB_COLOR1;
- }
- else {
- *inputReg = VERT_ATTRIB_COLOR0;
- }
- }
- break;
-
- case VERTEX_ATTRIB_FOGCOORD:
- *inputReg = VERT_ATTRIB_FOG;
- break;
-
- case VERTEX_ATTRIB_TEXCOORD:
- {
- GLuint unit = 0;
- err = parse_texcoord_num (ctx, inst, Program, &unit);
- *inputReg = VERT_ATTRIB_TEX0 + unit;
- }
- break;
-
- case VERTEX_ATTRIB_MATRIXINDEX:
- /* Not supported at this time */
- {
- const char *msg = "ARB_palette_matrix not supported";
- parse_integer (inst, Program);
- program_error(ctx, Program->Position, msg);
- }
- return 1;
-
- case VERTEX_ATTRIB_GENERIC:
- {
- GLuint attrib;
- err = parse_generic_attrib_num(ctx, inst, Program, &attrib);
- if (!err) {
- *is_generic = 1;
- /* Add VERT_ATTRIB_GENERIC0 here because ARB_vertex_program's
- * attributes do not alias the conventional vertex
- * attributes.
- */
- if (attrib > 0)
- *inputReg = attrib + VERT_ATTRIB_GENERIC0;
- else
- *inputReg = 0;
- }
- }
- break;
-
- default:
- err = 1;
- break;
- }
- }
-
- if (err) {
- program_error(ctx, Program->Position, "Bad attribute binding");
- }
-
- return err;
-}
-
-
-/**
- * This translates between a binary token for an output variable type
- * and the mesa token for the same thing.
- *
- * \param inst The parsed tokens
- * \param outputReg Returned index/number of the output register,
- * one of the VERT_RESULT_* or FRAG_RESULT_* values.
- */
-static GLuint
-parse_result_binding(GLcontext *ctx, const GLubyte **inst,
- GLuint *outputReg, struct arb_program *Program)
-{
- const GLubyte token = *(*inst)++;
-
- switch (token) {
- case FRAGMENT_RESULT_COLOR:
- if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
- GLuint out_color;
-
- /* This gets result of the color buffer we're supposed to
- * draw into. This pertains to GL_ARB_draw_buffers.
- */
- parse_output_color_num(ctx, inst, Program, &out_color);
- ASSERT(out_color < MAX_DRAW_BUFFERS);
- *outputReg = FRAG_RESULT_COLR;
- }
- else {
- /* for vtx programs, this is VERTEX_RESULT_POSITION */
- *outputReg = VERT_RESULT_HPOS;
- }
- break;
-
- case FRAGMENT_RESULT_DEPTH:
- if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
- /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
- *outputReg = FRAG_RESULT_DEPR;
- }
- else {
- /* for vtx programs, this is VERTEX_RESULT_COLOR */
- GLint color_type;
- GLuint face_type = parse_face_type(inst);
- GLint err = parse_color_type(ctx, inst, Program, &color_type);
- if (err)
- return 1;
-
- if (face_type) {
- /* back face */
- if (color_type) {
- *outputReg = VERT_RESULT_BFC1; /* secondary color */
- }
- else {
- *outputReg = VERT_RESULT_BFC0; /* primary color */
- }
- }
- else {
- /* front face */
- if (color_type) {
- *outputReg = VERT_RESULT_COL1; /* secondary color */
- }
- /* primary color */
- else {
- *outputReg = VERT_RESULT_COL0; /* primary color */
- }
- }
- }
- break;
-
- case VERTEX_RESULT_FOGCOORD:
- *outputReg = VERT_RESULT_FOGC;
- break;
-
- case VERTEX_RESULT_POINTSIZE:
- *outputReg = VERT_RESULT_PSIZ;
- break;
-
- case VERTEX_RESULT_TEXCOORD:
- {
- GLuint unit;
- if (parse_texcoord_num (ctx, inst, Program, &unit))
- return 1;
- *outputReg = VERT_RESULT_TEX0 + unit;
- }
- break;
- }
-
- Program->Base.OutputsWritten |= (1 << *outputReg);
-
- return 0;
-}
-
-
-/**
- * This handles the declaration of ATTRIB variables
- *
- * XXX: Still needs
- * parse_vert_attrib_binding(), or something like that
- *
- * \return 0 on sucess, 1 on error
- */
-static GLint
-parse_attrib (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
- struct arb_program *Program)
-{
- GLuint found;
- struct var_cache *attrib_var;
-
- attrib_var = parse_string (inst, vc_head, Program, &found);
- Program->Position = parse_position (inst);
- if (found) {
- program_error2(ctx, Program->Position,
- "Duplicate variable declaration",
- (char *) attrib_var->name);
- return 1;
- }
-
- attrib_var->type = vt_attrib;
-
- if (parse_attrib_binding(ctx, inst, Program, &attrib_var->attrib_binding,
- &attrib_var->attrib_is_generic))
- return 1;
-
- if (generic_attrib_check(*vc_head)) {
- program_error(ctx, Program->Position,
- "Cannot use both a generic vertex attribute "
- "and a specific attribute of the same type");
- return 1;
- }
-
- Program->Base.NumAttributes++;
- return 0;
-}
-
-/**
- * \param use -- TRUE if we're called when declaring implicit parameters,
- * FALSE if we're declaraing variables. This has to do with
- * if we get a signed or unsigned float for scalar constants
- */
-static GLuint
-parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
- struct var_cache *param_var,
- struct arb_program *Program, GLboolean use)
-{
- GLint idx;
- GLuint err = 0;
- gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0};
- GLfloat const_values[4];
-
- GLubyte token = *(*inst)++;
-
- switch (token) {
- case PARAM_STATE_ELEMENT:
- if (parse_state_single_item (ctx, inst, Program, state_tokens))
- return 1;
-
- /* If we adding STATE_MATRIX that has multiple rows, we need to
- * unroll it and call _mesa_add_state_reference() for each row
- */
- if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
- state_tokens[0] == STATE_PROJECTION_MATRIX ||
- state_tokens[0] == STATE_MVP_MATRIX ||
- state_tokens[0] == STATE_TEXTURE_MATRIX ||
- state_tokens[0] == STATE_PROGRAM_MATRIX)
- && (state_tokens[2] != state_tokens[3])) {
- GLint row;
- const GLint first_row = state_tokens[2];
- const GLint last_row = state_tokens[3];
-
- for (row = first_row; row <= last_row; row++) {
- state_tokens[2] = state_tokens[3] = row;
-
- idx = _mesa_add_state_reference(Program->Base.Parameters,
- state_tokens);
- if (param_var->param_binding_begin == ~0U)
- param_var->param_binding_begin = idx;
- param_var->param_binding_length++;
- Program->Base.NumParameters++;
- }
- }
- else {
- idx = _mesa_add_state_reference(Program->Base.Parameters,
- state_tokens);
- if (param_var->param_binding_begin == ~0U)
- param_var->param_binding_begin = idx;
- param_var->param_binding_length++;
- Program->Base.NumParameters++;
- }
- break;
-
- case PARAM_PROGRAM_ELEMENT:
- if (parse_program_single_item (ctx, inst, Program, state_tokens))
- return 1;
- idx = _mesa_add_state_reference (Program->Base.Parameters, state_tokens);
- if (param_var->param_binding_begin == ~0U)
- param_var->param_binding_begin = idx;
- param_var->param_binding_length++;
- Program->Base.NumParameters++;
-
- /* Check if there is more: 0 -> we're done, else its an integer */
- if (**inst) {
- GLuint out_of_range, new_idx;
- GLuint start_idx = state_tokens[2] + 1;
- GLuint end_idx = parse_integer (inst, Program);
-
- out_of_range = 0;
- if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
- if (((state_tokens[1] == STATE_ENV)
- && (end_idx >= ctx->Const.FragmentProgram.MaxEnvParams))
- || ((state_tokens[1] == STATE_LOCAL)
- && (end_idx >=
- ctx->Const.FragmentProgram.MaxLocalParams)))
- out_of_range = 1;
- }
- else {
- if (((state_tokens[1] == STATE_ENV)
- && (end_idx >= ctx->Const.VertexProgram.MaxEnvParams))
- || ((state_tokens[1] == STATE_LOCAL)
- && (end_idx >=
- ctx->Const.VertexProgram.MaxLocalParams)))
- out_of_range = 1;
- }
- if (out_of_range) {
- program_error(ctx, Program->Position,
- "Invalid Program Parameter"); /*end_idx*/
- return 1;
- }
-
- for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
- state_tokens[2] = new_idx;
- idx = _mesa_add_state_reference(Program->Base.Parameters,
- state_tokens);
- param_var->param_binding_length++;
- Program->Base.NumParameters++;
- }
- }
- else {
- (*inst)++;
- }
- break;
-
- case PARAM_CONSTANT:
- /* parsing something like {1.0, 2.0, 3.0, 4.0} */
- parse_constant (inst, const_values, Program, use);
- idx = _mesa_add_named_constant(Program->Base.Parameters,
- (char *) param_var->name,
- const_values, 4);
- if (param_var->param_binding_begin == ~0U)
- param_var->param_binding_begin = idx;
- param_var->param_binding_type = PROGRAM_CONSTANT;
- param_var->param_binding_length++;
- Program->Base.NumParameters++;
- break;
-
- default:
- program_error(ctx, Program->Position,
- "Unexpected token (in parse_param_elements())");
- return 1;
- }
-
- /* Make sure we haven't blown past our parameter limits */
- if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
- (Program->Base.NumParameters >=
- ctx->Const.VertexProgram.MaxLocalParams))
- || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
- && (Program->Base.NumParameters >=
- ctx->Const.FragmentProgram.MaxLocalParams))) {
- program_error(ctx, Program->Position, "Too many parameter variables");
- return 1;
- }
-
- return err;
-}
-
-
-/**
- * This picks out PARAM program parameter bindings.
- *
- * XXX: This needs to be stressed & tested
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
- struct arb_program *Program)
-{
- GLuint found, err;
- GLint specified_length;
- struct var_cache *param_var;
-
- err = 0;
- param_var = parse_string (inst, vc_head, Program, &found);
- Program->Position = parse_position (inst);
-
- if (found) {
- program_error2(ctx, Program->Position,
- "Duplicate variable declaration",
- (char *) param_var->name);
- return 1;
- }
-
- specified_length = parse_integer (inst, Program);
-
- if (specified_length < 0) {
- program_error(ctx, Program->Position, "Negative parameter array length");
- return 1;
- }
-
- param_var->type = vt_param;
- param_var->param_binding_length = 0;
-
- /* Right now, everything is shoved into the main state register file.
- *
- * In the future, it would be nice to leave things ENV/LOCAL params
- * in their respective register files, if possible
- */
- param_var->param_binding_type = PROGRAM_STATE_VAR;
-
- /* Remember to:
- * * - add each guy to the parameter list
- * * - increment the param_var->param_binding_len
- * * - store the param_var->param_binding_begin for the first one
- * * - compare the actual len to the specified len at the end
- */
- while (**inst != PARAM_NULL) {
- if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
- return 1;
- }
-
- /* Test array length here! */
- if (specified_length) {
- if (specified_length != (int)param_var->param_binding_length) {
- program_error(ctx, Program->Position,
- "Declared parameter array length does not match parameter list");
- }
- }
-
- (*inst)++;
-
- return 0;
-}
-
-/**
- *
- */
-static GLuint
-parse_param_use (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
- struct arb_program *Program, struct var_cache **new_var)
-{
- struct var_cache *param_var;
-
- /* First, insert a dummy entry into the var_cache */
- var_cache_create (&param_var);
- param_var->name = (const GLubyte *) " ";
- param_var->type = vt_param;
-
- param_var->param_binding_length = 0;
- /* Don't fill in binding_begin; We use the default value of -1
- * to tell if its already initialized, elsewhere.
- *
- * param_var->param_binding_begin = 0;
- */
- param_var->param_binding_type = PROGRAM_STATE_VAR;
-
- var_cache_append (vc_head, param_var);
-
- /* Then fill it with juicy parameter goodness */
- if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
- return 1;
-
- *new_var = param_var;
-
- return 0;
-}
-
-
-/**
- * This handles the declaration of TEMP variables
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_temp (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
- struct arb_program *Program)
-{
- GLuint found;
- struct var_cache *temp_var;
-
- while (**inst != 0) {
- temp_var = parse_string (inst, vc_head, Program, &found);
- Program->Position = parse_position (inst);
- if (found) {
- program_error2(ctx, Program->Position,
- "Duplicate variable declaration",
- (char *) temp_var->name);
- return 1;
- }
-
- temp_var->type = vt_temp;
-
- if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
- (Program->Base.NumTemporaries >=
- ctx->Const.FragmentProgram.MaxTemps))
- || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
- && (Program->Base.NumTemporaries >=
- ctx->Const.VertexProgram.MaxTemps))) {
- program_error(ctx, Program->Position,
- "Too many TEMP variables declared");
- return 1;
- }
-
- temp_var->temp_binding = Program->Base.NumTemporaries;
- Program->Base.NumTemporaries++;
- }
- (*inst)++;
-
- return 0;
-}
-
-/**
- * This handles variables of the OUTPUT variety
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_output (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
- struct arb_program *Program)
-{
- GLuint found;
- struct var_cache *output_var;
- GLuint err;
-
- output_var = parse_string (inst, vc_head, Program, &found);
- Program->Position = parse_position (inst);
- if (found) {
- program_error2(ctx, Program->Position,
- "Duplicate variable declaration",
- (char *) output_var->name);
- return 1;
- }
-
- output_var->type = vt_output;
-
- err = parse_result_binding(ctx, inst, &output_var->output_binding, Program);
- return err;
-}
-
-/**
- * This handles variables of the ALIAS kind
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_alias (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
- struct arb_program *Program)
-{
- GLuint found;
- struct var_cache *temp_var;
-
- temp_var = parse_string (inst, vc_head, Program, &found);
- Program->Position = parse_position (inst);
-
- if (found) {
- program_error2(ctx, Program->Position,
- "Duplicate variable declaration",
- (char *) temp_var->name);
- return 1;
- }
-
- temp_var->type = vt_alias;
- temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
- Program->Position = parse_position (inst);
-
- if (!found)
- {
- program_error2(ctx, Program->Position,
- "Undefined alias value",
- (char *) temp_var->alias_binding->name);
- return 1;
- }
-
- return 0;
-}
-
-/**
- * This handles variables of the ADDRESS kind
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_address (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
- struct arb_program *Program)
-{
- GLuint found;
- struct var_cache *temp_var;
-
- while (**inst != 0) {
- temp_var = parse_string (inst, vc_head, Program, &found);
- Program->Position = parse_position (inst);
- if (found) {
- program_error2(ctx, Program->Position,
- "Duplicate variable declaration",
- (char *) temp_var->name);
- return 1;
- }
-
- temp_var->type = vt_address;
-
- if (Program->Base.NumAddressRegs >=
- ctx->Const.VertexProgram.MaxAddressRegs) {
- const char *msg = "Too many ADDRESS variables declared";
- program_error(ctx, Program->Position, msg);
- return 1;
- }
-
- temp_var->address_binding = Program->Base.NumAddressRegs;
- Program->Base.NumAddressRegs++;
- }
- (*inst)++;
-
- return 0;
-}
-
-/**
- * Parse a program declaration
- *
- * \return 0 on sucess, 1 on error
- */
-static GLint
-parse_declaration (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
- struct arb_program *Program)
-{
- GLint err = 0;
-
- switch (*(*inst)++) {
- case ADDRESS:
- err = parse_address (ctx, inst, vc_head, Program);
- break;
-
- case ALIAS:
- err = parse_alias (ctx, inst, vc_head, Program);
- break;
-
- case ATTRIB:
- err = parse_attrib (ctx, inst, vc_head, Program);
- break;
-
- case OUTPUT:
- err = parse_output (ctx, inst, vc_head, Program);
- break;
-
- case PARAM:
- err = parse_param (ctx, inst, vc_head, Program);
- break;
-
- case TEMP:
- err = parse_temp (ctx, inst, vc_head, Program);
- break;
- }
-
- return err;
-}
-
-/**
- * Handle the parsing out of a masked destination register, either for a
- * vertex or fragment program.
- *
- * If we are a vertex program, make sure we don't write to
- * result.position if we have specified that the program is
- * position invariant
- *
- * \param File - The register file we write to
- * \param Index - The register index we write to
- * \param WriteMask - The mask controlling which components we write (1->write)
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_masked_dst_reg (GLcontext * ctx, const GLubyte ** inst,
- struct var_cache **vc_head, struct arb_program *Program,
- enum register_file *File, GLuint *Index, GLint *WriteMask)
-{
- GLuint tmp, result;
- struct var_cache *dst;
-
- /* We either have a result register specified, or a
- * variable that may or may not be writable
- */
- switch (*(*inst)++) {
- case REGISTER_RESULT:
- if (parse_result_binding(ctx, inst, Index, Program))
- return 1;
- *File = PROGRAM_OUTPUT;
- break;
-
- case REGISTER_ESTABLISHED_NAME:
- dst = parse_string (inst, vc_head, Program, &result);
- Program->Position = parse_position (inst);
-
- /* If the name has never been added to our symbol table, we're hosed */
- if (!result) {
- program_error(ctx, Program->Position, "0: Undefined variable");
- return 1;
- }
-
- switch (dst->type) {
- case vt_output:
- *File = PROGRAM_OUTPUT;
- *Index = dst->output_binding;
- break;
-
- case vt_temp:
- *File = PROGRAM_TEMPORARY;
- *Index = dst->temp_binding;
- break;
-
- /* If the var type is not vt_output or vt_temp, no go */
- default:
- program_error(ctx, Program->Position,
- "Destination register is read only");
- return 1;
- }
- break;
-
- default:
- program_error(ctx, Program->Position,
- "Unexpected opcode in parse_masked_dst_reg()");
- return 1;
- }
-
-
- /* Position invariance test */
- /* This test is done now in syntax portion - when position invariance OPTION
- is specified, "result.position" rule is disabled so there is no way
- to write the position
- */
- /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
- (*Index == 0)) {
- program_error(ctx, Program->Position,
- "Vertex program specified position invariance and wrote vertex position");
- }*/
-
- /* And then the mask.
- * w,a -> bit 0
- * z,b -> bit 1
- * y,g -> bit 2
- * x,r -> bit 3
- *
- * ==> Need to reverse the order of bits for this!
- */
- tmp = (GLint) *(*inst)++;
- *WriteMask = (((tmp>>3) & 0x1) |
- ((tmp>>1) & 0x2) |
- ((tmp<<1) & 0x4) |
- ((tmp<<3) & 0x8));
-
- return 0;
-}
-
-
-/**
- * Handle the parsing of a address register
- *
- * \param Index - The register index we write to
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_address_reg (GLcontext * ctx, const GLubyte ** inst,
- struct var_cache **vc_head,
- struct arb_program *Program, GLint * Index)
-{
- struct var_cache *dst;
- GLuint result;
-
- *Index = 0; /* XXX */
-
- dst = parse_string (inst, vc_head, Program, &result);
- Program->Position = parse_position (inst);
-
- /* If the name has never been added to our symbol table, we're hosed */
- if (!result) {
- program_error(ctx, Program->Position, "Undefined variable");
- return 1;
- }
-
- if (dst->type != vt_address) {
- program_error(ctx, Program->Position, "Variable is not of type ADDRESS");
- return 1;
- }
-
- return 0;
-}
-
-#if 0 /* unused */
-/**
- * Handle the parsing out of a masked address register
- *
- * \param Index - The register index we write to
- * \param WriteMask - The mask controlling which components we write (1->write)
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_masked_address_reg (GLcontext * ctx, const GLubyte ** inst,
- struct var_cache **vc_head,
- struct arb_program *Program, GLint * Index,
- GLboolean * WriteMask)
-{
- if (parse_address_reg (ctx, inst, vc_head, Program, Index))
- return 1;
-
- /* This should be 0x8 */
- (*inst)++;
-
- /* Writemask of .x is implied */
- WriteMask[0] = 1;
- WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
-
- return 0;
-}
-#endif
-
-/**
- * Parse out a swizzle mask.
- *
- * Basically convert COMPONENT_X/Y/Z/W to SWIZZLE_X/Y/Z/W
- *
- * The len parameter allows us to grab 4 components for a vector
- * swizzle, or just 1 component for a scalar src register selection
- */
-static void
-parse_swizzle_mask(const GLubyte ** inst, GLubyte *swizzle, GLint len)
-{
- GLint i;
-
- for (i = 0; i < 4; i++)
- swizzle[i] = i;
-
- for (i = 0; i < len; i++) {
- switch (*(*inst)++) {
- case COMPONENT_X:
- swizzle[i] = SWIZZLE_X;
- break;
- case COMPONENT_Y:
- swizzle[i] = SWIZZLE_Y;
- break;
- case COMPONENT_Z:
- swizzle[i] = SWIZZLE_Z;
- break;
- case COMPONENT_W:
- swizzle[i] = SWIZZLE_W;
- break;
- default:
- _mesa_problem(NULL, "bad component in parse_swizzle_mask()");
- return;
- }
- }
-}
-
-
-/**
- * Parse an extended swizzle mask which is a sequence of
- * four x/y/z/w/0/1 tokens.
- * \return swizzle four swizzle values
- * \return negateMask four element bitfield
- */
-static void
-parse_extended_swizzle_mask(const GLubyte **inst, GLubyte swizzle[4],
- GLubyte *negateMask)
-{
- GLint i;
-
- *negateMask = 0x0;
- for (i = 0; i < 4; i++) {
- GLubyte swz;
- if (parse_sign(inst) == -1)
- *negateMask |= (1 << i);
-
- swz = *(*inst)++;
-
- switch (swz) {
- case COMPONENT_0:
- swizzle[i] = SWIZZLE_ZERO;
- break;
- case COMPONENT_1:
- swizzle[i] = SWIZZLE_ONE;
- break;
- case COMPONENT_X:
- swizzle[i] = SWIZZLE_X;
- break;
- case COMPONENT_Y:
- swizzle[i] = SWIZZLE_Y;
- break;
- case COMPONENT_Z:
- swizzle[i] = SWIZZLE_Z;
- break;
- case COMPONENT_W:
- swizzle[i] = SWIZZLE_W;
- break;
- default:
- _mesa_problem(NULL, "bad case in parse_extended_swizzle_mask()");
- return;
- }
- }
-}
-
-
-static GLuint
-parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
- struct var_cache **vc_head,
- struct arb_program *Program,
- enum register_file * File, GLint * Index,
- GLboolean *IsRelOffset )
-{
- struct var_cache *src;
- GLuint binding, is_generic, found;
- GLint offset;
-
- *IsRelOffset = 0;
-
- /* And the binding for the src */
- switch (*(*inst)++) {
- case REGISTER_ATTRIB:
- if (parse_attrib_binding
- (ctx, inst, Program, &binding, &is_generic))
- return 1;
- *File = PROGRAM_INPUT;
- *Index = binding;
-
- /* We need to insert a dummy variable into the var_cache so we can
- * catch generic vertex attrib aliasing errors
- */
- var_cache_create(&src);
- src->type = vt_attrib;
- src->name = (const GLubyte *) "Dummy Attrib Variable";
- src->attrib_binding = binding;
- src->attrib_is_generic = is_generic;
- var_cache_append(vc_head, src);
- if (generic_attrib_check(*vc_head)) {
- program_error(ctx, Program->Position,
- "Cannot use both a generic vertex attribute "
- "and a specific attribute of the same type");
- return 1;
- }
- break;
-
- case REGISTER_PARAM:
- switch (**inst) {
- case PARAM_ARRAY_ELEMENT:
- (*inst)++;
- src = parse_string (inst, vc_head, Program, &found);
- Program->Position = parse_position (inst);
-
- if (!found) {
- program_error2(ctx, Program->Position,
- "Undefined variable",
- (char *) src->name);
- return 1;
- }
-
- *File = (enum register_file) src->param_binding_type;
-
- switch (*(*inst)++) {
- case ARRAY_INDEX_ABSOLUTE:
- offset = parse_integer (inst, Program);
-
- if ((offset < 0)
- || (offset >= (int)src->param_binding_length)) {
- program_error(ctx, Program->Position,
- "Index out of range");
- /* offset, src->name */
- return 1;
- }
-
- *Index = src->param_binding_begin + offset;
- break;
-
- case ARRAY_INDEX_RELATIVE:
- {
- GLint addr_reg_idx, rel_off;
-
- /* First, grab the address regiseter */
- if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
- return 1;
-
- /* And the .x */
- ((*inst)++);
- ((*inst)++);
- ((*inst)++);
- ((*inst)++);
-
- /* Then the relative offset */
- if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
-
- /* And store it properly */
- *Index = src->param_binding_begin + rel_off;
- *IsRelOffset = 1;
- }
- break;
- }
- break;
-
- default:
- if (parse_param_use (ctx, inst, vc_head, Program, &src))
- return 1;
-
- *File = (enum register_file) src->param_binding_type;
- *Index = src->param_binding_begin;
- break;
- }
- break;
-
- case REGISTER_ESTABLISHED_NAME:
- src = parse_string (inst, vc_head, Program, &found);
- Program->Position = parse_position (inst);
-
- /* If the name has never been added to our symbol table, we're hosed */
- if (!found) {
- program_error(ctx, Program->Position,
- "3: Undefined variable"); /* src->name */
- return 1;
- }
-
- switch (src->type) {
- case vt_attrib:
- *File = PROGRAM_INPUT;
- *Index = src->attrib_binding;
- break;
-
- /* XXX: We have to handle offsets someplace in here! -- or are those above? */
- case vt_param:
- *File = (enum register_file) src->param_binding_type;
- *Index = src->param_binding_begin;
- break;
-
- case vt_temp:
- *File = PROGRAM_TEMPORARY;
- *Index = src->temp_binding;
- break;
-
- /* If the var type is vt_output no go */
- default:
- program_error(ctx, Program->Position,
- "destination register is read only");
- /* bad src->name */
- return 1;
- }
- break;
-
- default:
- program_error(ctx, Program->Position,
- "Unknown token in parse_src_reg");
- return 1;
- }
-
- /* Add attributes to InputsRead only if they are used the program.
- * This avoids the handling of unused ATTRIB declarations in the drivers. */
- if (*File == PROGRAM_INPUT)
- Program->Base.InputsRead |= (1 << *Index);
-
- return 0;
-}
-
-
-/**
- * Parse vertex/fragment program vector source register.
- */
-static GLuint
-parse_vector_src_reg(GLcontext *ctx, const GLubyte **inst,
- struct var_cache **vc_head,
- struct arb_program *program,
- struct prog_src_register *reg)
-{
- enum register_file file;
- GLint index;
- GLubyte negateMask;
- GLubyte swizzle[4];
- GLboolean isRelOffset;
-
- /* Grab the sign */
- negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
-
- /* And the src reg */
- if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
- return 1;
-
- /* finally, the swizzle */
- parse_swizzle_mask(inst, swizzle, 4);
-
- reg->File = file;
- reg->Index = index;
- reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
- reg->NegateBase = negateMask;
- reg->RelAddr = isRelOffset;
- return 0;
-}
-
-
-/**
- * Parse vertex/fragment program scalar source register.
- */
-static GLuint
-parse_scalar_src_reg(GLcontext *ctx, const GLubyte **inst,
- struct var_cache **vc_head,
- struct arb_program *program,
- struct prog_src_register *reg)
-{
- enum register_file file;
- GLint index;
- GLubyte negateMask;
- GLubyte swizzle[4];
- GLboolean isRelOffset;
-
- /* Grab the sign */
- negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
-
- /* And the src reg */
- if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
- return 1;
-
- /* finally, the swizzle */
- parse_swizzle_mask(inst, swizzle, 1);
-
- reg->File = file;
- reg->Index = index;
- reg->Swizzle = (swizzle[0] << 0);
- reg->NegateBase = negateMask;
- reg->RelAddr = isRelOffset;
- return 0;
-}
-
-
-/**
- * Parse vertex/fragment program destination register.
- * \return 1 if error, 0 if no error.
- */
-static GLuint
-parse_dst_reg(GLcontext * ctx, const GLubyte ** inst,
- struct var_cache **vc_head, struct arb_program *program,
- struct prog_dst_register *reg )
-{
- GLint mask;
- GLuint idx;
- enum register_file file;
-
- if (parse_masked_dst_reg (ctx, inst, vc_head, program, &file, &idx, &mask))
- return 1;
-
- reg->File = file;
- reg->Index = idx;
- reg->WriteMask = mask;
- return 0;
-}
-
-
-/**
- * This is a big mother that handles getting opcodes into the instruction
- * and handling the src & dst registers for fragment program instructions
- * \return 1 if error, 0 if no error
- */
-static GLuint
-parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
- struct var_cache **vc_head, struct arb_program *Program,
- struct prog_instruction *fp)
-{
- GLint a;
- GLuint texcoord;
- GLubyte instClass, type, code;
- GLboolean rel;
- GLuint shadow_tex = 0;
-
- _mesa_init_instructions(fp, 1);
-
- /* Record the position in the program string for debugging */
- fp->StringPos = Program->Position;
-
- /* OP_ALU_INST or OP_TEX_INST */
- instClass = *(*inst)++;
-
- /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
- * OP_TEX_{SAMPLE, KIL}
- */
- type = *(*inst)++;
-
- /* The actual opcode name */
- code = *(*inst)++;
-
- /* Increment the correct count */
- switch (instClass) {
- case OP_ALU_INST:
- Program->NumAluInstructions++;
- break;
- case OP_TEX_INST:
- Program->NumTexInstructions++;
- break;
- }
-
- switch (type) {
- case OP_ALU_VECTOR:
- switch (code) {
- case OP_ABS_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_ABS:
- fp->Opcode = OPCODE_ABS;
- break;
-
- case OP_FLR_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_FLR:
- fp->Opcode = OPCODE_FLR;
- break;
-
- case OP_FRC_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_FRC:
- fp->Opcode = OPCODE_FRC;
- break;
-
- case OP_LIT_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_LIT:
- fp->Opcode = OPCODE_LIT;
- break;
-
- case OP_MOV_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_MOV:
- fp->Opcode = OPCODE_MOV;
- break;
- }
-
- if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
- return 1;
-
- if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
- return 1;
- break;
-
- case OP_ALU_SCALAR:
- switch (code) {
- case OP_COS_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_COS:
- fp->Opcode = OPCODE_COS;
- break;
-
- case OP_EX2_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_EX2:
- fp->Opcode = OPCODE_EX2;
- break;
-
- case OP_LG2_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_LG2:
- fp->Opcode = OPCODE_LG2;
- break;
-
- case OP_RCP_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_RCP:
- fp->Opcode = OPCODE_RCP;
- break;
-
- case OP_RSQ_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_RSQ:
- fp->Opcode = OPCODE_RSQ;
- break;
-
- case OP_SIN_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_SIN:
- fp->Opcode = OPCODE_SIN;
- break;
-
- case OP_SCS_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_SCS:
-
- fp->Opcode = OPCODE_SCS;
- break;
- }
-
- if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
- return 1;
-
- if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
- return 1;
- break;
-
- case OP_ALU_BINSC:
- switch (code) {
- case OP_POW_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_POW:
- fp->Opcode = OPCODE_POW;
- break;
- }
-
- if (parse_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
- return 1;
-
- for (a = 0; a < 2; a++) {
- if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
- return 1;
- }
- break;
-
-
- case OP_ALU_BIN:
- switch (code) {
- case OP_ADD_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_ADD:
- fp->Opcode = OPCODE_ADD;
- break;
-
- case OP_DP3_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_DP3:
- fp->Opcode = OPCODE_DP3;
- break;
-
- case OP_DP4_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_DP4:
- fp->Opcode = OPCODE_DP4;
- break;
-
- case OP_DPH_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_DPH:
- fp->Opcode = OPCODE_DPH;
- break;
-
- case OP_DST_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_DST:
- fp->Opcode = OPCODE_DST;
- break;
-
- case OP_MAX_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_MAX:
- fp->Opcode = OPCODE_MAX;
- break;
-
- case OP_MIN_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_MIN:
- fp->Opcode = OPCODE_MIN;
- break;
-
- case OP_MUL_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_MUL:
- fp->Opcode = OPCODE_MUL;
- break;
-
- case OP_SGE_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_SGE:
- fp->Opcode = OPCODE_SGE;
- break;
-
- case OP_SLT_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_SLT:
- fp->Opcode = OPCODE_SLT;
- break;
-
- case OP_SUB_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_SUB:
- fp->Opcode = OPCODE_SUB;
- break;
-
- case OP_XPD_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_XPD:
- fp->Opcode = OPCODE_XPD;
- break;
- }
-
- if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
- return 1;
- for (a = 0; a < 2; a++) {
- if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
- return 1;
- }
- break;
-
- case OP_ALU_TRI:
- switch (code) {
- case OP_CMP_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_CMP:
- fp->Opcode = OPCODE_CMP;
- break;
-
- case OP_LRP_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_LRP:
- fp->Opcode = OPCODE_LRP;
- break;
-
- case OP_MAD_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_MAD:
- fp->Opcode = OPCODE_MAD;
- break;
- }
-
- if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
- return 1;
-
- for (a = 0; a < 3; a++) {
- if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
- return 1;
- }
- break;
-
- case OP_ALU_SWZ:
- switch (code) {
- case OP_SWZ_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_SWZ:
- fp->Opcode = OPCODE_SWZ;
- break;
- }
- if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
- return 1;
-
- {
- GLubyte swizzle[4];
- GLubyte negateMask;
- enum register_file file;
- GLint index;
-
- if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &rel))
- return 1;
- parse_extended_swizzle_mask(inst, swizzle, &negateMask);
- fp->SrcReg[0].File = file;
- fp->SrcReg[0].Index = index;
- fp->SrcReg[0].NegateBase = negateMask;
- fp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
- swizzle[1],
- swizzle[2],
- swizzle[3]);
- }
- break;
-
- case OP_TEX_SAMPLE:
- switch (code) {
- case OP_TEX_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_TEX:
- fp->Opcode = OPCODE_TEX;
- break;
-
- case OP_TXP_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_TXP:
- fp->Opcode = OPCODE_TXP;
- break;
-
- case OP_TXB_SAT:
- fp->SaturateMode = SATURATE_ZERO_ONE;
- case OP_TXB:
- fp->Opcode = OPCODE_TXB;
- break;
- }
-
- if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
- return 1;
-
- if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
- return 1;
-
- /* texImageUnit */
- if (parse_teximage_num (ctx, inst, Program, &texcoord))
- return 1;
- fp->TexSrcUnit = texcoord;
-
- /* texTarget */
- switch (*(*inst)++) {
- case TEXTARGET_SHADOW1D:
- shadow_tex = 1 << texcoord;
- /* FALLTHROUGH */
- case TEXTARGET_1D:
- fp->TexSrcTarget = TEXTURE_1D_INDEX;
- break;
- case TEXTARGET_SHADOW2D:
- shadow_tex = 1 << texcoord;
- /* FALLTHROUGH */
- case TEXTARGET_2D:
- fp->TexSrcTarget = TEXTURE_2D_INDEX;
- break;
- case TEXTARGET_3D:
- fp->TexSrcTarget = TEXTURE_3D_INDEX;
- break;
- case TEXTARGET_SHADOWRECT:
- shadow_tex = 1 << texcoord;
- /* FALLTHROUGH */
- case TEXTARGET_RECT:
- fp->TexSrcTarget = TEXTURE_RECT_INDEX;
- break;
- case TEXTARGET_CUBE:
- fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
- break;
- case TEXTARGET_SHADOW1D_ARRAY:
- shadow_tex = 1 << texcoord;
- /* FALLTHROUGH */
- case TEXTARGET_1D_ARRAY:
- fp->TexSrcTarget = TEXTURE_1D_ARRAY_INDEX;
- break;
- case TEXTARGET_SHADOW2D_ARRAY:
- shadow_tex = 1 << texcoord;
- /* FALLTHROUGH */
- case TEXTARGET_2D_ARRAY:
- fp->TexSrcTarget = TEXTURE_2D_ARRAY_INDEX;
- break;
- }
-
- /* Don't test the first time a particular sampler is seen. Each time
- * after that, make sure the shadow state is the same.
- */
- if ((_mesa_bitcount(Program->TexturesUsed[texcoord]) > 0)
- && ((Program->ShadowSamplers & (1 << texcoord)) != shadow_tex)) {
- program_error(ctx, Program->Position,
- "texture image unit used for shadow sampling and non-shadow sampling");
- return 1;
- }
-
- Program->TexturesUsed[texcoord] |= (1 << fp->TexSrcTarget);
- /* Check that both "2D" and "CUBE" (for example) aren't both used */
- if (_mesa_bitcount(Program->TexturesUsed[texcoord]) > 1) {
- program_error(ctx, Program->Position,
- "multiple targets used on one texture image unit");
- return 1;
- }
-
-
- Program->ShadowSamplers |= shadow_tex;
- break;
-
- case OP_TEX_KIL:
- Program->UsesKill = 1;
- if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
- return 1;
- fp->Opcode = OPCODE_KIL;
- break;
- default:
- _mesa_problem(ctx, "bad type 0x%x in parse_fp_instruction()", type);
- return 1;
- }
-
- return 0;
-}
-
-
-/**
- * Handle the parsing out of a masked address register
- *
- * \param Index - The register index we write to
- * \param WriteMask - The mask controlling which components we write (1->write)
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_vp_address_reg (GLcontext * ctx, const GLubyte ** inst,
- struct var_cache **vc_head,
- struct arb_program *Program,
- struct prog_dst_register *reg)
-{
- GLint idx;
-
- if (parse_address_reg (ctx, inst, vc_head, Program, &idx))
- return 1;
-
- /* This should be 0x8 */
- (*inst)++;
-
- reg->File = PROGRAM_ADDRESS;
- reg->Index = idx;
-
- /* Writemask of .x is implied */
- reg->WriteMask = 0x1;
- return 0;
-}
-
-
-/**
- * This is a big mother that handles getting opcodes into the instruction
- * and handling the src & dst registers for vertex program instructions
- */
-static GLuint
-parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst,
- struct var_cache **vc_head, struct arb_program *Program,
- struct prog_instruction *vp)
-{
- GLint a;
- GLubyte type, code;
-
- /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
- type = *(*inst)++;
-
- /* The actual opcode name */
- code = *(*inst)++;
-
- _mesa_init_instructions(vp, 1);
- /* Record the position in the program string for debugging */
- vp->StringPos = Program->Position;
-
- switch (type) {
- /* XXX: */
- case OP_ALU_ARL:
- vp->Opcode = OPCODE_ARL;
-
- /* Remember to set SrcReg.RelAddr; */
-
- /* Get the masked address register [dst] */
- if (parse_vp_address_reg(ctx, inst, vc_head, Program, &vp->DstReg))
- return 1;
-
- vp->DstReg.File = PROGRAM_ADDRESS;
-
- /* Get a scalar src register */
- if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
- return 1;
-
- break;
-
- case OP_ALU_VECTOR:
- switch (code) {
- case OP_ABS:
- vp->Opcode = OPCODE_ABS;
- break;
- case OP_FLR:
- vp->Opcode = OPCODE_FLR;
- break;
- case OP_FRC:
- vp->Opcode = OPCODE_FRC;
- break;
- case OP_LIT:
- vp->Opcode = OPCODE_LIT;
- break;
- case OP_MOV:
- vp->Opcode = OPCODE_MOV;
- break;
- }
-
- if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
- return 1;
-
- if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
- return 1;
- break;
-
- case OP_ALU_SCALAR:
- switch (code) {
- case OP_EX2:
- vp->Opcode = OPCODE_EX2;
- break;
- case OP_EXP:
- vp->Opcode = OPCODE_EXP;
- break;
- case OP_LG2:
- vp->Opcode = OPCODE_LG2;
- break;
- case OP_LOG:
- vp->Opcode = OPCODE_LOG;
- break;
- case OP_RCP:
- vp->Opcode = OPCODE_RCP;
- break;
- case OP_RSQ:
- vp->Opcode = OPCODE_RSQ;
- break;
- }
- if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
- return 1;
-
- if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
- return 1;
- break;
-
- case OP_ALU_BINSC:
- switch (code) {
- case OP_POW:
- vp->Opcode = OPCODE_POW;
- break;
- }
- if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
- return 1;
-
- for (a = 0; a < 2; a++) {
- if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
- return 1;
- }
- break;
-
- case OP_ALU_BIN:
- switch (code) {
- case OP_ADD:
- vp->Opcode = OPCODE_ADD;
- break;
- case OP_DP3:
- vp->Opcode = OPCODE_DP3;
- break;
- case OP_DP4:
- vp->Opcode = OPCODE_DP4;
- break;
- case OP_DPH:
- vp->Opcode = OPCODE_DPH;
- break;
- case OP_DST:
- vp->Opcode = OPCODE_DST;
- break;
- case OP_MAX:
- vp->Opcode = OPCODE_MAX;
- break;
- case OP_MIN:
- vp->Opcode = OPCODE_MIN;
- break;
- case OP_MUL:
- vp->Opcode = OPCODE_MUL;
- break;
- case OP_SGE:
- vp->Opcode = OPCODE_SGE;
- break;
- case OP_SLT:
- vp->Opcode = OPCODE_SLT;
- break;
- case OP_SUB:
- vp->Opcode = OPCODE_SUB;
- break;
- case OP_XPD:
- vp->Opcode = OPCODE_XPD;
- break;
- }
- if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
- return 1;
-
- for (a = 0; a < 2; a++) {
- if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
- return 1;
- }
- break;
-
- case OP_ALU_TRI:
- switch (code) {
- case OP_MAD:
- vp->Opcode = OPCODE_MAD;
- break;
- }
-
- if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
- return 1;
-
- for (a = 0; a < 3; a++) {
- if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
- return 1;
- }
- break;
-
- case OP_ALU_SWZ:
- switch (code) {
- case OP_SWZ:
- vp->Opcode = OPCODE_SWZ;
- break;
- }
- {
- GLubyte swizzle[4];
- GLubyte negateMask;
- GLboolean relAddr;
- enum register_file file;
- GLint index;
-
- if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
- return 1;
-
- if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
- return 1;
- parse_extended_swizzle_mask (inst, swizzle, &negateMask);
- vp->SrcReg[0].File = file;
- vp->SrcReg[0].Index = index;
- vp->SrcReg[0].NegateBase = negateMask;
- vp->SrcReg[0].Swizzle = MAKE_SWIZZLE4(swizzle[0],
- swizzle[1],
- swizzle[2],
- swizzle[3]);
- vp->SrcReg[0].RelAddr = relAddr;
- }
- break;
- }
- return 0;
-}
-
-#if DEBUG_PARSING
-
-static GLvoid
-debug_variables (GLcontext * ctx, struct var_cache *vc_head,
- struct arb_program *Program)
-{
- struct var_cache *vc;
- GLint a, b;
-
- fprintf (stderr, "debug_variables, vc_head: %p\n", (void*) vc_head);
-
- /* First of all, print out the contents of the var_cache */
- vc = vc_head;
- while (vc) {
- fprintf (stderr, "[%p]\n", (void*) vc);
- switch (vc->type) {
- case vt_none:
- fprintf (stderr, "UNDEFINED %s\n", vc->name);
- break;
- case vt_attrib:
- fprintf (stderr, "ATTRIB %s\n", vc->name);
- fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
- break;
- case vt_param:
- fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
- vc->param_binding_begin, vc->param_binding_length);
- b = vc->param_binding_begin;
- for (a = 0; a < vc->param_binding_length; a++) {
- fprintf (stderr, "%s\n",
- Program->Base.Parameters->Parameters[a + b].Name);
- if (Program->Base.Parameters->Parameters[a + b].Type == PROGRAM_STATE_VAR) {
- const char *s;
- s = _mesa_program_state_string(Program->Base.Parameters->Parameters
- [a + b].StateIndexes);
- fprintf(stderr, "%s\n", s);
- _mesa_free((char *) s);
- }
- else
- fprintf (stderr, "%f %f %f %f\n",
- Program->Base.Parameters->ParameterValues[a + b][0],
- Program->Base.Parameters->ParameterValues[a + b][1],
- Program->Base.Parameters->ParameterValues[a + b][2],
- Program->Base.Parameters->ParameterValues[a + b][3]);
- }
- break;
- case vt_temp:
- fprintf (stderr, "TEMP %s\n", vc->name);
- fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
- break;
- case vt_output:
- fprintf (stderr, "OUTPUT %s\n", vc->name);
- fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
- break;
- case vt_alias:
- fprintf (stderr, "ALIAS %s\n", vc->name);
- fprintf (stderr, " binding: 0x%p (%s)\n",
- (void*) vc->alias_binding, vc->alias_binding->name);
- break;
- default:
- /* nothing */
- ;
- }
- vc = vc->next;
- }
-}
-
-#endif /* DEBUG_PARSING */
-
-
-/**
- * The main loop for parsing a fragment or vertex program
- *
- * \return 1 on error, 0 on success
- */
-static GLint
-parse_instructions(GLcontext * ctx, const GLubyte * inst,
- struct var_cache **vc_head, struct arb_program *Program)
-{
- const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
- ? ctx->Const.FragmentProgram.MaxInstructions
- : ctx->Const.VertexProgram.MaxInstructions;
- GLint err = 0;
-
- ASSERT(MAX_INSTRUCTIONS >= maxInst);
-
- Program->MajorVersion = (GLuint) * inst++;
- Program->MinorVersion = (GLuint) * inst++;
-
- while (*inst != END) {
- switch (*inst++) {
-
- case OPTION:
- switch (*inst++) {
- case ARB_PRECISION_HINT_FASTEST:
- Program->PrecisionOption = GL_FASTEST;
- break;
-
- case ARB_PRECISION_HINT_NICEST:
- Program->PrecisionOption = GL_NICEST;
- break;
-
- case ARB_FOG_EXP:
- Program->FogOption = GL_EXP;
- break;
-
- case ARB_FOG_EXP2:
- Program->FogOption = GL_EXP2;
- break;
-
- case ARB_FOG_LINEAR:
- Program->FogOption = GL_LINEAR;
- break;
-
- case ARB_POSITION_INVARIANT:
- if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
- Program->HintPositionInvariant = GL_TRUE;
- break;
-
- case ARB_FRAGMENT_PROGRAM_SHADOW:
- if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
- /* TODO ARB_fragment_program_shadow code */
- }
- break;
-
- case ARB_DRAW_BUFFERS:
- if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
- /* do nothing for now */
- }
- break;
-
- case MESA_TEXTURE_ARRAY:
- /* do nothing for now */
- break;
- }
- break;
-
- case INSTRUCTION:
- /* check length */
- if (Program->Base.NumInstructions + 1 >= maxInst) {
- program_error(ctx, Program->Position,
- "Max instruction count exceeded");
- return 1;
- }
- Program->Position = parse_position (&inst);
- /* parse the current instruction */
- if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
- err = parse_fp_instruction (ctx, &inst, vc_head, Program,
- &Program->Base.Instructions[Program->Base.NumInstructions]);
- }
- else {
- err = parse_vp_instruction (ctx, &inst, vc_head, Program,
- &Program->Base.Instructions[Program->Base.NumInstructions]);
- }
-
- /* increment instuction count */
- Program->Base.NumInstructions++;
- break;
-
- case DECLARATION:
- err = parse_declaration (ctx, &inst, vc_head, Program);
- break;
-
- default:
- break;
- }
-
- if (err)
- break;
- }
-
- /* Finally, tag on an OPCODE_END instruction */
- {
- const GLuint numInst = Program->Base.NumInstructions;
- _mesa_init_instructions(Program->Base.Instructions + numInst, 1);
- Program->Base.Instructions[numInst].Opcode = OPCODE_END;
- /* YYY Wrong Position in program, whatever, at least not random -> crash
- Program->Position = parse_position (&inst);
- */
- Program->Base.Instructions[numInst].StringPos = Program->Position;
- }
- Program->Base.NumInstructions++;
-
- /*
- * Initialize native counts to logical counts. The device driver may
- * change them if program is translated into a hardware program.
- */
- Program->Base.NumNativeInstructions = Program->Base.NumInstructions;
- Program->Base.NumNativeTemporaries = Program->Base.NumTemporaries;
- Program->Base.NumNativeParameters = Program->Base.NumParameters;
- Program->Base.NumNativeAttributes = Program->Base.NumAttributes;
- Program->Base.NumNativeAddressRegs = Program->Base.NumAddressRegs;
-
- return err;
-}
-
-
-/* XXX temporary */
-LONGSTRING static char core_grammar_text[] =
-#include "shader/grammar/grammar_syn.h"
-;
-
-
-/**
- * Set a grammar parameter.
- * \param name the grammar parameter
- * \param value the new parameter value
- * \return 0 if OK, 1 if error
- */
-static int
-set_reg8 (GLcontext *ctx, grammar id, const char *name, GLubyte value)
-{
- char error_msg[300];
- GLint error_pos;
-
- if (grammar_set_reg8 (id, (const byte *) name, value))
- return 0;
-
- grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
- _mesa_set_program_error (ctx, error_pos, error_msg);
- _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
- return 1;
-}
-
-
-/**
- * Enable support for the given language option in the parser.
- * \return 1 if OK, 0 if error
- */
-static int
-enable_ext(GLcontext *ctx, grammar id, const char *name)
-{
- return !set_reg8(ctx, id, name, 1);
-}
-
-
-/**
- * Enable parser extensions based on which OpenGL extensions are supported
- * by this rendering context.
- *
- * \return GL_TRUE if OK, GL_FALSE if error.
- */
-static GLboolean
-enable_parser_extensions(GLcontext *ctx, grammar id)
-{
-#if 0
- /* These are not supported at this time */
- if ((ctx->Extensions.ARB_vertex_blend ||
- ctx->Extensions.EXT_vertex_weighting)
- && !enable_ext(ctx, id, "vertex_blend"))
- return GL_FALSE;
- if (ctx->Extensions.ARB_matrix_palette
- && !enable_ext(ctx, id, "matrix_palette"))
- return GL_FALSE;
-#endif
- if (ctx->Extensions.ARB_fragment_program_shadow
- && !enable_ext(ctx, id, "fragment_program_shadow"))
- return GL_FALSE;
- if (ctx->Extensions.EXT_point_parameters
- && !enable_ext(ctx, id, "point_parameters"))
- return GL_FALSE;
- if (ctx->Extensions.EXT_secondary_color
- && !enable_ext(ctx, id, "secondary_color"))
- return GL_FALSE;
- if (ctx->Extensions.EXT_fog_coord
- && !enable_ext(ctx, id, "fog_coord"))
- return GL_FALSE;
- if (ctx->Extensions.NV_texture_rectangle
- && !enable_ext(ctx, id, "texture_rectangle"))
- return GL_FALSE;
- if (ctx->Extensions.ARB_draw_buffers
- && !enable_ext(ctx, id, "draw_buffers"))
- return GL_FALSE;
- if (ctx->Extensions.MESA_texture_array
- && !enable_ext(ctx, id, "texture_array"))
- return GL_FALSE;
-#if 1
- /* hack for Warcraft (see bug 8060) */
- enable_ext(ctx, id, "vertex_blend");
-#endif
-
- return GL_TRUE;
-}
-
-
-/**
- * This kicks everything off.
- *
- * \param ctx - The GL Context
- * \param str - The program string
- * \param len - The program string length
- * \param program - The arb_program struct to return all the parsed info in
- * \return GL_TRUE on sucess, GL_FALSE on error
- */
-static GLboolean
-_mesa_parse_arb_program(GLcontext *ctx, GLenum target,
- const GLubyte *str, GLsizei len,
- struct arb_program *program)
-{
- GLint a, err, error_pos;
- char error_msg[300];
- GLuint parsed_len;
- struct var_cache *vc_head;
- grammar arbprogram_syn_id;
- GLubyte *parsed, *inst;
- GLubyte *strz = NULL;
- static int arbprogram_syn_is_ok = 0; /* XXX temporary */
-
- /* set the program target before parsing */
- program->Base.Target = target;
-
- /* Reset error state */
- _mesa_set_program_error(ctx, -1, NULL);
-
- /* check if arb_grammar_text (arbprogram.syn) is syntactically correct */
- if (!arbprogram_syn_is_ok) {
- /* One-time initialization of parsing system */
- grammar grammar_syn_id;
- GLuint parsed_len;
-
- grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
- if (grammar_syn_id == 0) {
- grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
- /* XXX this is not a GL error - it's an implementation bug! - FIX */
- _mesa_set_program_error (ctx, error_pos, error_msg);
- _mesa_error (ctx, GL_INVALID_OPERATION,
- "glProgramStringARB(Error loading grammar rule set)");
- return GL_FALSE;
- }
-
- err = !grammar_check(grammar_syn_id, (byte *) arb_grammar_text,
- &parsed, &parsed_len);
-
- /* 'parsed' is unused here */
- _mesa_free (parsed);
- parsed = NULL;
-
- /* NOTE: we can't destroy grammar_syn_id right here because
- * grammar_destroy() can reset the last error
- */
- if (err) {
- /* XXX this is not a GL error - it's an implementation bug! - FIX */
- grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
- _mesa_set_program_error (ctx, error_pos, error_msg);
- _mesa_error (ctx, GL_INVALID_OPERATION,
- "glProgramString(Error loading grammar rule set");
- grammar_destroy (grammar_syn_id);
- return GL_FALSE;
- }
-
- grammar_destroy (grammar_syn_id);
-
- arbprogram_syn_is_ok = 1;
- }
-
- /* create the grammar object */
- arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
- if (arbprogram_syn_id == 0) {
- /* XXX this is not a GL error - it's an implementation bug! - FIX */
- grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
- _mesa_set_program_error (ctx, error_pos, error_msg);
- _mesa_error (ctx, GL_INVALID_OPERATION,
- "glProgramString(Error loading grammer rule set)");
- return GL_FALSE;
- }
-
- /* Set program_target register value */
- if (set_reg8 (ctx, arbprogram_syn_id, "program_target",
- program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
- grammar_destroy (arbprogram_syn_id);
- return GL_FALSE;
- }
-
- if (!enable_parser_extensions(ctx, arbprogram_syn_id)) {
- grammar_destroy(arbprogram_syn_id);
- return GL_FALSE;
- }
-
- /* check for NULL character occurences */
- {
- GLint i;
- for (i = 0; i < len; i++) {
- if (str[i] == '\0') {
- program_error(ctx, i, "illegal character");
- grammar_destroy (arbprogram_syn_id);
- return GL_FALSE;
- }
- }
- }
-
- /* copy the program string to a null-terminated string */
- strz = (GLubyte *) _mesa_malloc (len + 1);
- if (!strz) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
- grammar_destroy (arbprogram_syn_id);
- return GL_FALSE;
- }
- _mesa_memcpy (strz, str, len);
- strz[len] = '\0';
-
- /* do a fast check on program string - initial production buffer is 4K */
- err = !grammar_fast_check(arbprogram_syn_id, strz,
- &parsed, &parsed_len, 0x1000);
-
- /* Syntax parse error */
- if (err) {
- grammar_get_last_error((GLubyte *) error_msg, 300, &error_pos);
- program_error(ctx, error_pos, error_msg);
-
-#if DEBUG_PARSING
- /* useful for debugging */
- do {
- int line, col;
- char *s;
- fprintf(stderr, "program: %s\n", (char *) strz);
- fprintf(stderr, "Error Pos: %d\n", ctx->Program.ErrorPos);
- s = (char *) _mesa_find_line_column(strz, strz+ctx->Program.ErrorPos,
- &line, &col);
- fprintf(stderr, "line %d col %d: %s\n", line, col, s);
- } while (0);
-#endif
-
- _mesa_free(strz);
- _mesa_free(parsed);
-
- grammar_destroy (arbprogram_syn_id);
- return GL_FALSE;
- }
-
- grammar_destroy (arbprogram_syn_id);
-
- /*
- * Program string is syntactically correct at this point
- * Parse the tokenized version of the program now, generating
- * vertex/fragment program instructions.
- */
-
- /* Initialize the arb_program struct */
- program->Base.String = strz;
- program->Base.Instructions = _mesa_alloc_instructions(MAX_INSTRUCTIONS);
- program->Base.NumInstructions =
- program->Base.NumTemporaries =
- program->Base.NumParameters =
- program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
- program->Base.Parameters = _mesa_new_parameter_list ();
- program->Base.InputsRead = 0x0;
- program->Base.OutputsWritten = 0x0;
- program->Position = 0;
- program->MajorVersion = program->MinorVersion = 0;
- program->PrecisionOption = GL_DONT_CARE;
- program->FogOption = GL_NONE;
- program->HintPositionInvariant = GL_FALSE;
- for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
- program->TexturesUsed[a] = 0x0;
- program->ShadowSamplers = 0x0;
- program->NumAluInstructions =
- program->NumTexInstructions =
- program->NumTexIndirections = 0;
- program->UsesKill = 0;
-
- vc_head = NULL;
- err = GL_FALSE;
-
- /* Start examining the tokens in the array */
- inst = parsed;
-
- /* Check the grammer rev */
- if (*inst++ != REVISION) {
- program_error (ctx, 0, "Grammar version mismatch");
- err = GL_TRUE;
- }
- else {
- /* ignore program target */
- inst++;
- err = parse_instructions(ctx, inst, &vc_head, program);
- }
-
- /*debug_variables(ctx, vc_head, program); */
-
- /* We're done with the parsed binary array */
- var_cache_destroy (&vc_head);
-
- _mesa_free (parsed);
-
- /* Reallocate the instruction array from size [MAX_INSTRUCTIONS]
- * to size [ap.Base.NumInstructions].
- */
- program->Base.Instructions
- = _mesa_realloc_instructions(program->Base.Instructions,
- MAX_INSTRUCTIONS,
- program->Base.NumInstructions);
-
- return !err;
-}
-
+#include "program_parser.h"
void
@@ -3848,11 +71,18 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
const GLvoid *str, GLsizei len,
struct gl_fragment_program *program)
{
- struct arb_program ap;
+ struct gl_program prog;
+ struct asm_parser_state state;
GLuint i;
ASSERT(target == GL_FRAGMENT_PROGRAM_ARB);
- if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
+
+ memset(&prog, 0, sizeof(prog));
+ memset(&state, 0, sizeof(state));
+ state.prog = &prog;
+
+ if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len,
+ &state)) {
/* Error in the program. Just return. */
return;
}
@@ -3860,44 +90,60 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
/* Copy the relevant contents of the arb_program struct into the
* fragment_program struct.
*/
- program->Base.String = ap.Base.String;
- program->Base.NumInstructions = ap.Base.NumInstructions;
- program->Base.NumTemporaries = ap.Base.NumTemporaries;
- program->Base.NumParameters = ap.Base.NumParameters;
- program->Base.NumAttributes = ap.Base.NumAttributes;
- program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
- program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
- program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
- program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
- program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
- program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
- program->Base.NumAluInstructions = ap.Base.NumAluInstructions;
- program->Base.NumTexInstructions = ap.Base.NumTexInstructions;
- program->Base.NumTexIndirections = ap.Base.NumTexIndirections;
- program->Base.NumNativeAluInstructions = ap.Base.NumAluInstructions;
- program->Base.NumNativeTexInstructions = ap.Base.NumTexInstructions;
- program->Base.NumNativeTexIndirections = ap.Base.NumTexIndirections;
- program->Base.InputsRead = ap.Base.InputsRead;
- program->Base.OutputsWritten = ap.Base.OutputsWritten;
+ program->Base.String = prog.String;
+ program->Base.NumInstructions = prog.NumInstructions;
+ program->Base.NumTemporaries = prog.NumTemporaries;
+ program->Base.NumParameters = prog.NumParameters;
+ program->Base.NumAttributes = prog.NumAttributes;
+ program->Base.NumAddressRegs = prog.NumAddressRegs;
+ program->Base.NumNativeInstructions = prog.NumNativeInstructions;
+ program->Base.NumNativeTemporaries = prog.NumNativeTemporaries;
+ program->Base.NumNativeParameters = prog.NumNativeParameters;
+ program->Base.NumNativeAttributes = prog.NumNativeAttributes;
+ program->Base.NumNativeAddressRegs = prog.NumNativeAddressRegs;
+ program->Base.NumAluInstructions = prog.NumAluInstructions;
+ program->Base.NumTexInstructions = prog.NumTexInstructions;
+ program->Base.NumTexIndirections = prog.NumTexIndirections;
+ program->Base.NumNativeAluInstructions = prog.NumAluInstructions;
+ program->Base.NumNativeTexInstructions = prog.NumTexInstructions;
+ program->Base.NumNativeTexIndirections = prog.NumTexIndirections;
+ program->Base.InputsRead = prog.InputsRead;
+ program->Base.OutputsWritten = prog.OutputsWritten;
for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) {
- program->Base.TexturesUsed[i] = ap.TexturesUsed[i];
- if (ap.TexturesUsed[i])
+ program->Base.TexturesUsed[i] = prog.TexturesUsed[i];
+ if (prog.TexturesUsed[i])
program->Base.SamplersUsed |= (1 << i);
}
- program->Base.ShadowSamplers = ap.ShadowSamplers;
- program->FogOption = ap.FogOption;
- program->UsesKill = ap.UsesKill;
+ program->Base.ShadowSamplers = prog.ShadowSamplers;
+ switch (state.option.Fog) {
+ case OPTION_FOG_EXP: program->FogOption = GL_EXP; break;
+ case OPTION_FOG_EXP2: program->FogOption = GL_EXP2; break;
+ case OPTION_FOG_LINEAR: program->FogOption = GL_LINEAR; break;
+ default: program->FogOption = GL_NONE; break;
+ }
+
+ program->UsesKill = state.fragment.UsesKill;
if (program->FogOption)
program->Base.InputsRead |= FRAG_BIT_FOGC;
-
+
if (program->Base.Instructions)
_mesa_free(program->Base.Instructions);
- program->Base.Instructions = ap.Base.Instructions;
+ program->Base.Instructions = prog.Instructions;
if (program->Base.Parameters)
_mesa_free_parameter_list(program->Base.Parameters);
- program->Base.Parameters = ap.Base.Parameters;
+ program->Base.Parameters = prog.Parameters;
+
+ /* Append fog instructions now if the program has "OPTION ARB_fog_exp"
+ * or similar. We used to leave this up to drivers, but it appears
+ * there's no hardware that wants to do fog in a discrete stage separate
+ * from the fragment shader.
+ */
+ if (program->FogOption != GL_NONE) {
+ _mesa_append_fog_code(ctx, program);
+ program->FogOption = GL_NONE;
+ }
#if DEBUG_FP
_mesa_printf("____________Fragment program %u ________\n", program->Base.Id);
@@ -3917,11 +163,17 @@ _mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
const GLvoid *str, GLsizei len,
struct gl_vertex_program *program)
{
- struct arb_program ap;
+ struct gl_program prog;
+ struct asm_parser_state state;
ASSERT(target == GL_VERTEX_PROGRAM_ARB);
- if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
+ memset(&prog, 0, sizeof(prog));
+ memset(&state, 0, sizeof(state));
+ state.prog = &prog;
+
+ if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len,
+ &state)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glProgramString(bad program)");
return;
}
@@ -3929,28 +181,29 @@ _mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
/* Copy the relevant contents of the arb_program struct into the
* vertex_program struct.
*/
- program->Base.String = ap.Base.String;
- program->Base.NumInstructions = ap.Base.NumInstructions;
- program->Base.NumTemporaries = ap.Base.NumTemporaries;
- program->Base.NumParameters = ap.Base.NumParameters;
- program->Base.NumAttributes = ap.Base.NumAttributes;
- program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
- program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
- program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
- program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
- program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
- program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
- program->Base.InputsRead = ap.Base.InputsRead;
- program->Base.OutputsWritten = ap.Base.OutputsWritten;
- program->IsPositionInvariant = ap.HintPositionInvariant;
+ program->Base.String = prog.String;
+ program->Base.NumInstructions = prog.NumInstructions;
+ program->Base.NumTemporaries = prog.NumTemporaries;
+ program->Base.NumParameters = prog.NumParameters;
+ program->Base.NumAttributes = prog.NumAttributes;
+ program->Base.NumAddressRegs = prog.NumAddressRegs;
+ program->Base.NumNativeInstructions = prog.NumNativeInstructions;
+ program->Base.NumNativeTemporaries = prog.NumNativeTemporaries;
+ program->Base.NumNativeParameters = prog.NumNativeParameters;
+ program->Base.NumNativeAttributes = prog.NumNativeAttributes;
+ program->Base.NumNativeAddressRegs = prog.NumNativeAddressRegs;
+ program->Base.InputsRead = prog.InputsRead;
+ program->Base.OutputsWritten = prog.OutputsWritten;
+ program->IsPositionInvariant = (state.option.PositionInvariant)
+ ? GL_TRUE : GL_FALSE;
if (program->Base.Instructions)
_mesa_free(program->Base.Instructions);
- program->Base.Instructions = ap.Base.Instructions;
+ program->Base.Instructions = prog.Instructions;
if (program->Base.Parameters)
_mesa_free_parameter_list(program->Base.Parameters);
- program->Base.Parameters = ap.Base.Parameters;
+ program->Base.Parameters = prog.Parameters;
#if DEBUG_VP
_mesa_printf("____________Vertex program %u __________\n", program->Base.Id);
diff --git a/src/mesa/shader/arbprogram.c b/src/mesa/shader/arbprogram.c
index 7c2b747c43..4d8cff0700 100644
--- a/src/mesa/shader/arbprogram.c
+++ b/src/mesa/shader/arbprogram.c
@@ -74,8 +74,6 @@ _mesa_BindProgram(GLenum target, GLuint id)
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-
/* Error-check target and get curProg */
if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */
(ctx->Extensions.NV_vertex_program ||
@@ -132,6 +130,9 @@ _mesa_BindProgram(GLenum target, GLuint id)
return;
}
+ /* signal new program (and its new constants) */
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+
/* bind newProg */
if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
_mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
@@ -253,6 +254,8 @@ _mesa_EnableVertexAttribArrayARB(GLuint index)
return;
}
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
FLUSH_VERTICES(ctx, _NEW_ARRAY);
ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
@@ -272,6 +275,8 @@ _mesa_DisableVertexAttribArrayARB(GLuint index)
return;
}
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
FLUSH_VERTICES(ctx, _NEW_ARRAY);
ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
@@ -298,32 +303,41 @@ _mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
}
+/**
+ * Return info for a generic vertex attribute array (no alias with
+ * legacy vertex attributes (pos, normal, color, etc)).
+ */
void GLAPIENTRY
_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
{
+ const struct gl_client_array *array;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
+ if (index >= MAX_VERTEX_GENERIC_ATTRIBS) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)");
return;
}
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
switch (pname) {
case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Enabled;
+ params[0] = (GLfloat) array->Enabled;
break;
case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size;
+ params[0] = (GLfloat) array->Size;
break;
case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
+ params[0] = (GLfloat) array->Stride;
break;
case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type;
+ params[0] = (GLfloat) array->Type;
break;
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Normalized;
+ params[0] = array->Normalized;
break;
case GL_CURRENT_VERTEX_ATTRIB_ARB:
if (index == 0) {
@@ -335,11 +349,7 @@ _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
COPY_4V(params, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]);
break;
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
- if (!ctx->Extensions.ARB_vertex_buffer_object) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
- return;
- }
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name;
+ params[0] = (GLfloat) array->BufferObj->Name;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
@@ -383,6 +393,8 @@ _mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
return;
}
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
*pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
}
@@ -493,7 +505,7 @@ _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
if (target == GL_FRAGMENT_PROGRAM_ARB
&& ctx->Extensions.ARB_fragment_program) {
@@ -541,7 +553,7 @@ _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
GLfloat * dest;
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
if (count <= 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
@@ -599,10 +611,7 @@ _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-
- if (!ctx->_CurrentProgram)
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
if (target == GL_FRAGMENT_PROGRAM_ARB
&& ctx->Extensions.ARB_fragment_program) {
@@ -638,7 +647,7 @@ _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
struct gl_program *prog;
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
if ((target == GL_FRAGMENT_PROGRAM_NV
&& ctx->Extensions.NV_fragment_program) ||
@@ -692,7 +701,7 @@ _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
GLint i;
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
if (count <= 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
@@ -822,8 +831,7 @@ _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
struct gl_program *prog;
GET_CURRENT_CONTEXT(ctx);
- if (!ctx->_CurrentProgram)
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
if (target == GL_VERTEX_PROGRAM_ARB
&& ctx->Extensions.ARB_vertex_program) {
@@ -993,6 +1001,9 @@ _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
return;
}
+ } else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
+ return;
}
}
@@ -1004,8 +1015,7 @@ _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
char *dst = (char *) string;
GET_CURRENT_CONTEXT(ctx);
- if (!ctx->_CurrentProgram)
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
if (target == GL_VERTEX_PROGRAM_ARB) {
prog = &(ctx->VertexProgram.Current->Base);
diff --git a/src/mesa/shader/arbprogram.syn b/src/mesa/shader/arbprogram.syn
deleted file mode 100644
index b12c6a0eda..0000000000
--- a/src/mesa/shader/arbprogram.syn
+++ /dev/null
@@ -1,2824 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version: 6.2
- *
- * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
- /**
- * \file arbprogram.syn
- * ARB_fragment/vertex_program syntax
- * \author Michal Krol
- */
-
-.syntax program;
-
-/*
- This value must be incremented every time emit code values or structure of the production
- array changes. This value is placed at the beginning of the production array. The loader
- compares the value with its REVISION value. If they do not match, the loader is not up
- to date.
-*/
-.emtcode REVISION 0x0a
-
-/* program type */
-.emtcode FRAGMENT_PROGRAM 0x01
-.emtcode VERTEX_PROGRAM 0x02
-
-/* program section */
-.emtcode OPTION 0x01
-.emtcode INSTRUCTION 0x02
-.emtcode DECLARATION 0x03
-.emtcode END 0x04
-
-/* GL_ARB_fragment_program option */
-.emtcode ARB_PRECISION_HINT_FASTEST 0x00
-.emtcode ARB_PRECISION_HINT_NICEST 0x01
-.emtcode ARB_FOG_EXP 0x02
-.emtcode ARB_FOG_EXP2 0x03
-.emtcode ARB_FOG_LINEAR 0x04
-
-/* GL_ARB_vertex_program option */
-.emtcode ARB_POSITION_INVARIANT 0x05
-
-/* GL_ARB_fragment_program_shadow option */
-.emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x06
-
-/* GL_ARB_draw_buffers option */
-.emtcode ARB_DRAW_BUFFERS 0x07
-
-/* GL_MESA_texture_array option */
-.emtcode MESA_TEXTURE_ARRAY 0x08
-
-/* GL_ARB_fragment_program instruction class */
-.emtcode OP_ALU_INST 0x00
-.emtcode OP_TEX_INST 0x01
-
-/* GL_ARB_vertex_program instruction class */
-/* OP_ALU_INST */
-
-/* GL_ARB_fragment_program instruction type */
-.emtcode OP_ALU_VECTOR 0x00
-.emtcode OP_ALU_SCALAR 0x01
-.emtcode OP_ALU_BINSC 0x02
-.emtcode OP_ALU_BIN 0x03
-.emtcode OP_ALU_TRI 0x04
-.emtcode OP_ALU_SWZ 0x05
-.emtcode OP_TEX_SAMPLE 0x06
-.emtcode OP_TEX_KIL 0x07
-
-/* GL_ARB_vertex_program instruction type */
-.emtcode OP_ALU_ARL 0x08
-/* OP_ALU_VECTOR */
-/* OP_ALU_SCALAR */
-/* OP_ALU_BINSC */
-/* OP_ALU_BIN */
-/* OP_ALU_TRI */
-/* OP_ALU_SWZ */
-
-/* GL_ARB_fragment_program instruction code */
-.emtcode OP_ABS 0x00
-.emtcode OP_ABS_SAT 0x1B
-.emtcode OP_FLR 0x09
-.emtcode OP_FLR_SAT 0x26
-.emtcode OP_FRC 0x0A
-.emtcode OP_FRC_SAT 0x27
-.emtcode OP_LIT 0x0C
-.emtcode OP_LIT_SAT 0x2A
-.emtcode OP_MOV 0x11
-.emtcode OP_MOV_SAT 0x30
-.emtcode OP_COS 0x1F
-.emtcode OP_COS_SAT 0x20
-.emtcode OP_EX2 0x07
-.emtcode OP_EX2_SAT 0x25
-.emtcode OP_LG2 0x0B
-.emtcode OP_LG2_SAT 0x29
-.emtcode OP_RCP 0x14
-.emtcode OP_RCP_SAT 0x33
-.emtcode OP_RSQ 0x15
-.emtcode OP_RSQ_SAT 0x34
-.emtcode OP_SIN 0x38
-.emtcode OP_SIN_SAT 0x39
-.emtcode OP_SCS 0x35
-.emtcode OP_SCS_SAT 0x36
-.emtcode OP_POW 0x13
-.emtcode OP_POW_SAT 0x32
-.emtcode OP_ADD 0x01
-.emtcode OP_ADD_SAT 0x1C
-.emtcode OP_DP3 0x03
-.emtcode OP_DP3_SAT 0x21
-.emtcode OP_DP4 0x04
-.emtcode OP_DP4_SAT 0x22
-.emtcode OP_DPH 0x05
-.emtcode OP_DPH_SAT 0x23
-.emtcode OP_DST 0x06
-.emtcode OP_DST_SAT 0x24
-.emtcode OP_MAX 0x0F
-.emtcode OP_MAX_SAT 0x2E
-.emtcode OP_MIN 0x10
-.emtcode OP_MIN_SAT 0x2F
-.emtcode OP_MUL 0x12
-.emtcode OP_MUL_SAT 0x31
-.emtcode OP_SGE 0x16
-.emtcode OP_SGE_SAT 0x37
-.emtcode OP_SLT 0x17
-.emtcode OP_SLT_SAT 0x3A
-.emtcode OP_SUB 0x18
-.emtcode OP_SUB_SAT 0x3B
-.emtcode OP_XPD 0x1A
-.emtcode OP_XPD_SAT 0x43
-.emtcode OP_CMP 0x1D
-.emtcode OP_CMP_SAT 0x1E
-.emtcode OP_LRP 0x2B
-.emtcode OP_LRP_SAT 0x2C
-.emtcode OP_MAD 0x0E
-.emtcode OP_MAD_SAT 0x2D
-.emtcode OP_SWZ 0x19
-.emtcode OP_SWZ_SAT 0x3C
-.emtcode OP_TEX 0x3D
-.emtcode OP_TEX_SAT 0x3E
-.emtcode OP_TXB 0x3F
-.emtcode OP_TXB_SAT 0x40
-.emtcode OP_TXP 0x41
-.emtcode OP_TXP_SAT 0x42
-.emtcode OP_KIL 0x28
-
-/* GL_ARB_vertex_program instruction code */
-.emtcode OP_ARL 0x02
-/* OP_ABS */
-/* OP_FLR */
-/* OP_FRC */
-/* OP_LIT */
-/* OP_MOV */
-/* OP_EX2 */
-.emtcode OP_EXP 0x08
-/* OP_LG2 */
-.emtcode OP_LOG 0x0D
-/* OP_RCP */
-/* OP_RSQ */
-/* OP_POW */
-/* OP_ADD */
-/* OP_DP3 */
-/* OP_DP4 */
-/* OP_DPH */
-/* OP_DST */
-/* OP_MAX */
-/* OP_MIN */
-/* OP_MUL */
-/* OP_SGE */
-/* OP_SLT */
-/* OP_SUB */
-/* OP_XPD */
-/* OP_MAD */
-/* OP_SWZ */
-
-/* fragment attribute binding */
-.emtcode FRAGMENT_ATTRIB_COLOR 0x01
-.emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02
-.emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03
-.emtcode FRAGMENT_ATTRIB_POSITION 0x04
-
-/* vertex attribute binding */
-.emtcode VERTEX_ATTRIB_POSITION 0x01
-.emtcode VERTEX_ATTRIB_WEIGHT 0x02
-.emtcode VERTEX_ATTRIB_NORMAL 0x03
-.emtcode VERTEX_ATTRIB_COLOR 0x04
-.emtcode VERTEX_ATTRIB_FOGCOORD 0x05
-.emtcode VERTEX_ATTRIB_TEXCOORD 0x06
-.emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07
-.emtcode VERTEX_ATTRIB_GENERIC 0x08
-
-/* fragment result binding */
-.emtcode FRAGMENT_RESULT_COLOR 0x01
-.emtcode FRAGMENT_RESULT_DEPTH 0x02
-
-/* vertex result binding */
-.emtcode VERTEX_RESULT_POSITION 0x01
-.emtcode VERTEX_RESULT_COLOR 0x02
-.emtcode VERTEX_RESULT_FOGCOORD 0x03
-.emtcode VERTEX_RESULT_POINTSIZE 0x04
-.emtcode VERTEX_RESULT_TEXCOORD 0x05
-
-/* texture target */
-.emtcode TEXTARGET_1D 0x01
-.emtcode TEXTARGET_2D 0x02
-.emtcode TEXTARGET_3D 0x03
-.emtcode TEXTARGET_RECT 0x04
-.emtcode TEXTARGET_CUBE 0x05
-/* GL_ARB_fragment_program_shadow */
-.emtcode TEXTARGET_SHADOW1D 0x06
-.emtcode TEXTARGET_SHADOW2D 0x07
-.emtcode TEXTARGET_SHADOWRECT 0x08
-/* GL_MESA_texture_array */
-.emtcode TEXTARGET_1D_ARRAY 0x09
-.emtcode TEXTARGET_2D_ARRAY 0x0a
-.emtcode TEXTARGET_SHADOW1D_ARRAY 0x0b
-.emtcode TEXTARGET_SHADOW2D_ARRAY 0x0c
-
-/* face type */
-.emtcode FACE_FRONT 0x00
-.emtcode FACE_BACK 0x01
-
-/* color type */
-.emtcode COLOR_PRIMARY 0x00
-.emtcode COLOR_SECONDARY 0x01
-
-/* component */
-.emtcode COMPONENT_X 0x00
-.emtcode COMPONENT_Y 0x01
-.emtcode COMPONENT_Z 0x02
-.emtcode COMPONENT_W 0x03
-.emtcode COMPONENT_0 0x04
-.emtcode COMPONENT_1 0x05
-
-/* array index type */
-.emtcode ARRAY_INDEX_ABSOLUTE 0x00
-.emtcode ARRAY_INDEX_RELATIVE 0x01
-
-/* matrix name */
-.emtcode MATRIX_MODELVIEW 0x01
-.emtcode MATRIX_PROJECTION 0x02
-.emtcode MATRIX_MVP 0x03
-.emtcode MATRIX_TEXTURE 0x04
-.emtcode MATRIX_PALETTE 0x05
-.emtcode MATRIX_PROGRAM 0x06
-
-/* matrix modifier */
-.emtcode MATRIX_MODIFIER_IDENTITY 0x00
-.emtcode MATRIX_MODIFIER_INVERSE 0x01
-.emtcode MATRIX_MODIFIER_TRANSPOSE 0x02
-.emtcode MATRIX_MODIFIER_INVTRANS 0x03
-
-/* constant type */
-.emtcode CONSTANT_SCALAR 0x01
-.emtcode CONSTANT_VECTOR 0x02
-
-/* program param type */
-.emtcode PROGRAM_PARAM_ENV 0x01
-.emtcode PROGRAM_PARAM_LOCAL 0x02
-
-/* register type */
-.emtcode REGISTER_ATTRIB 0x01
-.emtcode REGISTER_PARAM 0x02
-.emtcode REGISTER_RESULT 0x03
-.emtcode REGISTER_ESTABLISHED_NAME 0x04
-
-/* param binding */
-.emtcode PARAM_NULL 0x00
-.emtcode PARAM_ARRAY_ELEMENT 0x01
-.emtcode PARAM_STATE_ELEMENT 0x02
-.emtcode PARAM_PROGRAM_ELEMENT 0x03
-.emtcode PARAM_PROGRAM_ELEMENTS 0x04
-.emtcode PARAM_CONSTANT 0x05
-
-/* param state property */
-.emtcode STATE_MATERIAL 0x01
-.emtcode STATE_LIGHT 0x02
-.emtcode STATE_LIGHT_MODEL 0x03
-.emtcode STATE_LIGHT_PROD 0x04
-.emtcode STATE_FOG 0x05
-.emtcode STATE_MATRIX_ROWS 0x06
-/* GL_ARB_fragment_program */
-.emtcode STATE_TEX_ENV 0x07
-.emtcode STATE_DEPTH 0x08
-/* GL_ARB_vertex_program */
-.emtcode STATE_TEX_GEN 0x09
-.emtcode STATE_CLIP_PLANE 0x0A
-.emtcode STATE_POINT 0x0B
-
-/* state material property */
-.emtcode MATERIAL_AMBIENT 0x01
-.emtcode MATERIAL_DIFFUSE 0x02
-.emtcode MATERIAL_SPECULAR 0x03
-.emtcode MATERIAL_EMISSION 0x04
-.emtcode MATERIAL_SHININESS 0x05
-
-/* state light property */
-.emtcode LIGHT_AMBIENT 0x01
-.emtcode LIGHT_DIFFUSE 0x02
-.emtcode LIGHT_SPECULAR 0x03
-.emtcode LIGHT_POSITION 0x04
-.emtcode LIGHT_ATTENUATION 0x05
-.emtcode LIGHT_HALF 0x06
-.emtcode LIGHT_SPOT_DIRECTION 0x07
-
-/* state light model property */
-.emtcode LIGHT_MODEL_AMBIENT 0x01
-.emtcode LIGHT_MODEL_SCENECOLOR 0x02
-
-/* state light product property */
-.emtcode LIGHT_PROD_AMBIENT 0x01
-.emtcode LIGHT_PROD_DIFFUSE 0x02
-.emtcode LIGHT_PROD_SPECULAR 0x03
-
-/* state texture environment property */
-.emtcode TEX_ENV_COLOR 0x01
-
-/* state texture generation coord property */
-.emtcode TEX_GEN_EYE 0x01
-.emtcode TEX_GEN_OBJECT 0x02
-
-/* state fog property */
-.emtcode FOG_COLOR 0x01
-.emtcode FOG_PARAMS 0x02
-
-/* state depth property */
-.emtcode DEPTH_RANGE 0x01
-
-/* state point parameters property */
-.emtcode POINT_SIZE 0x01
-.emtcode POINT_ATTENUATION 0x02
-
-/* declaration */
-.emtcode ATTRIB 0x01
-.emtcode PARAM 0x02
-.emtcode TEMP 0x03
-.emtcode OUTPUT 0x04
-.emtcode ALIAS 0x05
-/* GL_ARB_vertex_program */
-.emtcode ADDRESS 0x06
-
-/* error messages */
-.errtext UNKNOWN_PROGRAM_SIGNATURE "1001: '$e_signature$': unknown program signature"
-.errtext MISSING_END_OR_INVALID_STATEMENT "1002: '$e_statement$': invalid statement"
-.errtext CODE_AFTER_END "1003: '$e_statement$': code after 'END' keyword"
-.errtext INVALID_PROGRAM_OPTION "1004: '$e_identifier$': invalid program option"
-.errtext EXT_SWIZ_COMP_EXPECTED "1005: extended swizzle component expected but '$e_token$' found"
-.errtext TEX_TARGET_EXPECTED "1006: texture target expected but '$e_token$' found"
-.errtext TEXTURE_EXPECTED "1007: 'texture' expected but '$e_identifier$' found"
-.errtext SOURCE_REGISTER_EXPECTED "1008: source register expected but '$e_token$' found"
-.errtext DESTINATION_REGISTER_EXPECTED "1009: destination register expected but '$e_token$' found"
-.errtext INVALID_ADDRESS_COMPONENT "1010: '$e_identifier$': invalid address component"
-.errtext INVALID_ADDRESS_WRITEMASK "1011: '$e_identifier$': invalid address writemask"
-.errtext INVALID_COMPONENT "1012: '$e_charordigit$': invalid component"
-.errtext INVALID_SUFFIX "1013: '$e_identifier$': invalid suffix"
-.errtext INVALID_WRITEMASK "1014: '$e_identifier$': invalid writemask"
-.errtext FRAGMENT_EXPECTED "1015: 'fragment' expected but '$e_identifier$' found"
-.errtext VERTEX_EXPECTED "1016: 'vertex' expected but '$e_identifier$' found"
-.errtext INVALID_FRAGMENT_PROPERTY "1017: '$e_identifier$': invalid fragment property"
-.errtext INVALID_VERTEX_PROPERTY "1018: '$e_identifier$': invalid vertex property"
-.errtext INVALID_STATE_PROPERTY "1019: '$e_identifier$': invalid state property"
-.errtext INVALID_MATERIAL_PROPERTY "1020: '$e_identifier$': invalid material property"
-.errtext INVALID_LIGHT_PROPERTY "1021: '$e_identifier$': invalid light property"
-.errtext INVALID_SPOT_PROPERTY "1022: '$e_identifier$': invalid spot property"
-.errtext INVALID_LIGHTMODEL_PROPERTY "1023: '$e_identifier$': invalid light model property"
-.errtext INVALID_LIGHTPROD_PROPERTY "1024: '$e_identifier$': invalid light product property"
-.errtext INVALID_TEXENV_PROPERTY "1025: '$e_identifier$': invalid texture environment property"
-.errtext INVALID_TEXGEN_PROPERTY "1026: '$e_identifier$': invalid texture generating property"
-.errtext INVALID_TEXGEN_COORD "1027: '$e_identifier$': invalid texture generating coord"
-.errtext INVALID_FOG_PROPERTY "1028: '$e_identifier$': invalid fog property"
-.errtext INVALID_DEPTH_PROPERTY "1029: '$e_identifier$': invalid depth property"
-.errtext INVALID_CLIPPLANE_PROPERTY "1030: '$e_identifier$': invalid clip plane property"
-.errtext INVALID_POINT_PROPERTY "1031: '$e_identifier$': invalid point property"
-.errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED "1032: matrix row selector or modifier expected but '$e_token$' found"
-.errtext INVALID_MATRIX_NAME "1033: '$e_identifier$': invalid matrix name"
-.errtext INVALID_PROGRAM_PROPERTY "1034: '$e_identifier$': invalid program property"
-.errtext RESULT_EXPECTED "1035: 'result' expected but '$e_token$' found"
-.errtext INVALID_RESULT_PROPERTY "1036: '$e_identifier$': invalid result property"
-.errtext INVALID_FACE_PROPERTY "1037: '$e_identifier$': invalid face property"
-.errtext INVALID_COLOR_PROPERTY "1038: '$e_identifier$': invalid color property"
-.errtext IDENTIFIER_EXPECTED "1039: identifier expected but '$e_token$' found"
-.errtext RESERVED_KEYWORD "1040: use of reserved keyword as an identifier"
-.errtext INTEGER_EXPECTED "1041: integer value expected but '$e_token$' found"
-.errtext MISSING_SEMICOLON "1042: ';' expected but '$e_token$' found"
-.errtext MISSING_COMMA "1043: ',' expected but '$e_token$' found"
-.errtext MISSING_LBRACKET "1044: '[' expected but '$e_token$' found"
-.errtext MISSING_RBRACKET "1045: ']' expected but '$e_token$' found"
-.errtext MISSING_DOT "1046: '.' expected but '$e_token$' found"
-.errtext MISSING_EQUAL "1047: '=' expected but '$e_token$' found"
-.errtext MISSING_LBRACE "1048: '{' expected but '$e_token$' found"
-.errtext MISSING_RBRACE "1049: '}' expected but '$e_token$' found"
-.errtext MISSING_DOTDOT "1050: '..' expected but '$e_token$' found"
-.errtext MISSING_FRACTION_OR_EXPONENT "1051: missing fraction part or exponent"
-.errtext MISSING_DOT_OR_EXPONENT "1052: missing '.' or exponent"
-.errtext EXPONENT_VALUE_EXPECTED "1053: exponent value expected"
-.errtext INTEGER_OUT_OF_RANGE "1054: integer value out of range"
-.errtext OPERATION_NEEDS_DESTINATION_VARIABLE "1055: operation needs destination variable"
-.errtext OPERATION_NEEDS_SOURCE_VARIABLE "1056: operation needs source variable"
-.errtext ADDRESS_REGISTER_EXPECTED "1057: address register expected but '$e_token$' found"
-.errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED "1058: address register or integer literal expected but '$e_token$' found"
-
-/* extension presence condition registers */
-
-/* GL_ARB_vertex_blend */
-/* GL_EXT_vertex_weighting */
-.regbyte vertex_blend 0x00
-
-/* GL_ARB_matrix_palette */
-.regbyte matrix_palette 0x00
-
-/* GL_ARB_point_parameters */
-/* GL_EXT_point_parameters */
-.regbyte point_parameters 0x00
-
-/* GL_EXT_secondary_color */
-.regbyte secondary_color 0x00
-
-/* GL_EXT_fog_coord */
-.regbyte fog_coord 0x00
-
-/* GL_EXT_texture_rectangle */
-/* GL_NV_texture_rectangle */
-.regbyte texture_rectangle 0x00
-
-/* GL_ARB_fragment_program_shadow */
-.regbyte fragment_program_shadow 0x00
-
-/* GL_ARB_draw_buffers */
-.regbyte draw_buffers 0x00
-
-/* GL_MESA_texture_array */
-.regbyte texture_array 0x00
-
-/* option presence condition registers */
-/* they are all initially set to zero - when a particular OPTION is encountered, the appropriate */
-/* register is set to 1 to indicate that the OPTION was specified. */
-
-/* GL_ARB_fragment_program */
-.regbyte ARB_precision_hint_fastest 0x00
-.regbyte ARB_precision_hint_nicest 0x00
-.regbyte ARB_fog_exp 0x00
-.regbyte ARB_fog_exp2 0x00
-.regbyte ARB_fog_linear 0x00
-
-/* GL_ARB_vertex_program */
-.regbyte ARB_position_invariant 0x00
-
-/* GL_ARB_fragment_program_shadow */
-.regbyte ARB_fragment_program_shadow 0x00
-
-/* GL_ARB_draw_buffers */
-.regbyte ARB_draw_buffers 0x00
-
-/* GL_MESA_texture_array */
-.regbyte MESA_texture_array 0x00
-
-/* program target condition register */
-/* this syntax script deals with two program targets - VERTEX_PROGRAM and FRAGMENT_PROGRAM. */
-/* to distinguish between them we need a register that will store for us the current target. */
-/* the client will typically set the register to apropriate value before parsing a particular */
-/* program. the mapping between program targets and their values is listed below. */
-/* */
-/* program target register value */
-/* ---------------------------------------------- */
-/* FRAGMENT_PROGRAM 0x10 */
-/* VERTEX_PROGRAM 0x20 */
-/* */
-/* the initial value of the register is 0 to catch potential errors with not setting the register */
-/* with the proper value. */
-.regbyte program_target 0x00
-
-/*
- <program> ::= <optionSequence> <statementSequence> "END"
-*/
-program
- programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;
-programs
- .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or
- .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;
-frag_program_1_0
- '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and
- optional_space .and fp_optionSequence .and fp_statementSequence .and
- "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and
- '\0' .error CODE_AFTER_END;
-vert_program_1_0
- '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and
- optional_space .and vp_optionSequence .and vp_statementSequence .and
- "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and
- '\0' .error CODE_AFTER_END;
-
-/*
- <optionSequence> ::= <optionSequence> <option>
- | ""
-*/
-fp_optionSequence
- .loop fp_option;
-vp_optionSequence
- .loop vp_option;
-
-/*
- <option> ::= "OPTION" <identifier> ";"
-
-NOTE: options ARB_precision_hint_nicest and ARB_precision_hint_fastest are exclusive. When one of
- these options is encountered, the other one is automatically disabled.
- the same applies to options ARB_fog_exp, ARB_fog_exp2 and ARB_fog_linear.
-*/
-fp_option
- "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and
- fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;
-vp_option
- "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and
- vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;
-fp_optionString
- .if (ARB_precision_hint_nicest == 0x00) "ARB_precision_hint_fastest"
- .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or
- .if (ARB_precision_hint_fastest == 0x00) "ARB_precision_hint_nicest"
- .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or
- fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or
- fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or
- fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or
- .if (fragment_program_shadow != 0x00) "ARB_fragment_program_shadow"
- .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01 .or
- .if (draw_buffers != 0x00) "ARB_draw_buffers" .emit ARB_DRAW_BUFFERS
- .load ARB_draw_buffers 0x01 .or
- .if (texture_array != 0x00) "MESA_texture_array" .emit MESA_TEXTURE_ARRAY
- .load MESA_texture_array 0x01;
-vp_optionString
- "ARB_position_invariant" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;
-fp_ARB_fog_exp
- .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp";
-fp_ARB_fog_exp2
- .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp2";
-fp_ARB_fog_linear
- .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) "ARB_fog_linear";
-
-/*
- <statementSequence> ::= <statementSequence> <statement>
- | ""
-*/
-fp_statementSequence
- .loop fp_statement;
-vp_statementSequence
- .loop vp_statement;
-
-/*
- <statement> ::= <instruction> ";"
- | <namingStatement> ";"
-
-NOTE: ".emit $" in the definitions below means that we output instruction position (offset of
- the first character of instruction) for program debugging purposes.
-*/
-fp_statement
- fp_statement_1 .or fp_statement_2;
-vp_statement
- vp_statement_1 .or vp_statement_2;
-fp_statement_1
- fp_instruction .emit INSTRUCTION .emit $ .and semicolon;
-fp_statement_2
- fp_namingStatement .emit DECLARATION .and semicolon;
-vp_statement_1
- vp_instruction .emit INSTRUCTION .emit $ .and semicolon;
-vp_statement_2
- vp_namingStatement .emit DECLARATION .and semicolon;
-
-/*
-fragment program
- <instruction> ::= <ALUInstruction>
- | <TexInstruction>
-
-vertex program
- <instruction> ::= <ARL_instruction>
- | <VECTORop_instruction>
- | <SCALARop_instruction>
- | <BINSCop_instruction>
- | <BINop_instruction>
- | <TRIop_instruction>
- | <SWZ_instruction>
-*/
-fp_instruction
- ALUInstruction .emit OP_ALU_INST .or
- TexInstruction .emit OP_TEX_INST;
-vp_instruction
- ARL_instruction .emit OP_ALU_ARL .or
- vp_VECTORop_instruction .emit OP_ALU_VECTOR .or
- vp_SCALARop_instruction .emit OP_ALU_SCALAR .or
- vp_BINSCop_instruction .emit OP_ALU_BINSC .or
- vp_BINop_instruction .emit OP_ALU_BIN .or
- vp_TRIop_instruction .emit OP_ALU_TRI .or
- vp_SWZ_instruction .emit OP_ALU_SWZ;
-
-/*
-fragment program
- <ALUInstruction> ::= <VECTORop_instruction>
- | <SCALARop_instruction>
- | <BINSCop_instruction>
- | <BINop_instruction>
- | <TRIop_instruction>
- | <SWZ_instruction>
-*/
-ALUInstruction
- fp_VECTORop_instruction .emit OP_ALU_VECTOR .or
- fp_SCALARop_instruction .emit OP_ALU_SCALAR .or
- fp_BINSCop_instruction .emit OP_ALU_BINSC .or
- fp_BINop_instruction .emit OP_ALU_BIN .or
- fp_TRIop_instruction .emit OP_ALU_TRI .or
- fp_SWZ_instruction .emit OP_ALU_SWZ;
-
-/*
-fragment program
- <TexInstruction> ::= <SAMPLE_instruction>
- | <KIL_instruction>
-*/
-TexInstruction
- SAMPLE_instruction .emit OP_TEX_SAMPLE .or
- KIL_instruction .emit OP_TEX_KIL;
-
-/*
-vertex program
- <ARL_instruction> ::= "ARL" <maskedAddrReg> "," <scalarSrcReg>
-*/
-ARL_instruction
- "ARL" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;
-
-/*
-fragment program
- <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> ","
- <vectorSrcReg>
-
-vertex program
- <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," <swizzleSrcReg>
-*/
-fp_VECTORop_instruction
- fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;
-vp_VECTORop_instruction
- vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;
-
-/*
-fragment program
- <VECTORop> ::= "ABS" | "ABS_SAT"
- | "FLR" | "FLR_SAT"
- | "FRC" | "FRC_SAT"
- | "LIT" | "LIT_SAT"
- | "MOV" | "MOV_SAT"
-
-vertex program
- <VECTORop> ::= "ABS"
- | "FLR"
- | "FRC"
- | "LIT"
- | "MOV"
-*/
-fp_VECTORop
- "ABS" .emit OP_ABS .or "ABS_SAT" .emit OP_ABS_SAT .or
- "FLR" .emit OP_FLR .or "FLR_SAT" .emit OP_FLR_SAT .or
- "FRC" .emit OP_FRC .or "FRC_SAT" .emit OP_FRC_SAT .or
- "LIT" .emit OP_LIT .or "LIT_SAT" .emit OP_LIT_SAT .or
- "MOV" .emit OP_MOV .or "MOV_SAT" .emit OP_MOV_SAT;
-vp_VECTORop
- "ABS" .emit OP_ABS .or
- "FLR" .emit OP_FLR .or
- "FRC" .emit OP_FRC .or
- "LIT" .emit OP_LIT .or
- "MOV" .emit OP_MOV;
-
-/*
- <SCALARop_instruction> ::= <SCALARop> <maskedDstReg> "," <scalarSrcReg>
-*/
-fp_SCALARop_instruction
- fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;
-vp_SCALARop_instruction
- vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;
-
-/*
-fragment program
- <SCALARop> ::= "COS" | "COS_SAT"
- | "EX2" | "EX2_SAT"
- | "LG2" | "LG2_SAT"
- | "RCP" | "RCP_SAT"
- | "RSQ" | "RSQ_SAT"
- | "SIN" | "SIN_SAT"
- | "SCS" | "SCS_SAT"
-
-vertex program
- <SCALARop> ::= "EX2"
- | "EXP"
- | "LG2"
- | "LOG"
- | "RCP"
- | "RSQ"
-*/
-fp_SCALARop
- "COS" .emit OP_COS .or "COS_SAT" .emit OP_COS_SAT .or
- "EX2" .emit OP_EX2 .or "EX2_SAT" .emit OP_EX2_SAT .or
- "LG2" .emit OP_LG2 .or "LG2_SAT" .emit OP_LG2_SAT .or
- "RCP" .emit OP_RCP .or "RCP_SAT" .emit OP_RCP_SAT .or
- "RSQ" .emit OP_RSQ .or "RSQ_SAT" .emit OP_RSQ_SAT .or
- "SIN" .emit OP_SIN .or "SIN_SAT" .emit OP_SIN_SAT .or
- "SCS" .emit OP_SCS .or "SCS_SAT" .emit OP_SCS_SAT;
-vp_SCALARop
- "EX2" .emit OP_EX2 .or
- "EXP" .emit OP_EXP .or
- "LG2" .emit OP_LG2 .or
- "LOG" .emit OP_LOG .or
- "RCP" .emit OP_RCP .or
- "RSQ" .emit OP_RSQ;
-
-/*
- <BINSCop_instruction> ::= <BINSCop> <maskedDstReg> "," <scalarSrcReg> ","
- <scalarSrcReg>
-*/
-fp_BINSCop_instruction
- fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and
- fp_scalarSrcReg;
-vp_BINSCop_instruction
- vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and
- vp_scalarSrcReg;
-
-/*
-fragment program
- <BINSCop> ::= "POW" | "POW_SAT"
-
-vertex program
- <BINSCop> ::= "POW"
-*/
-fp_BINSCop
- "POW" .emit OP_POW .or "POW_SAT" .emit OP_POW_SAT;
-vp_BINSCop
- "POW" .emit OP_POW;
-
-/*
-fragment program
- <BINop_instruction> ::= <BINop> <maskedDstReg> ","
- <vectorSrcReg> "," <vectorSrcReg>
-
-vertex program
- <BINop_instruction> ::= <BINop> <maskedDstReg> ","
- <swizzleSrcReg> "," <swizzleSrcReg>
-*/
-fp_BINop_instruction
- fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
- vectorSrcReg;
-vp_BINop_instruction
- vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and
- swizzleSrcReg;
-
-/*
-fragment program
- <BINop> ::= "ADD" | "ADD_SAT"
- | "DP3" | "DP3_SAT"
- | "DP4" | "DP4_SAT"
- | "DPH" | "DPH_SAT"
- | "DST" | "DST_SAT"
- | "MAX" | "MAX_SAT"
- | "MIN" | "MIN_SAT"
- | "MUL" | "MUL_SAT"
- | "SGE" | "SGE_SAT"
- | "SLT" | "SLT_SAT"
- | "SUB" | "SUB_SAT"
- | "XPD" | "XPD_SAT"
-
-vertex program
- <BINop> ::= "ADD"
- | "DP3"
- | "DP4"
- | "DPH"
- | "DST"
- | "MAX"
- | "MIN"
- | "MUL"
- | "SGE"
- | "SLT"
- | "SUB"
- | "XPD"
-*/
-fp_BINop
- "ADD" .emit OP_ADD .or "ADD_SAT" .emit OP_ADD_SAT .or
- "DP3" .emit OP_DP3 .or "DP3_SAT" .emit OP_DP3_SAT .or
- "DP4" .emit OP_DP4 .or "DP4_SAT" .emit OP_DP4_SAT .or
- "DPH" .emit OP_DPH .or "DPH_SAT" .emit OP_DPH_SAT .or
- "DST" .emit OP_DST .or "DST_SAT" .emit OP_DST_SAT .or
- "MAX" .emit OP_MAX .or "MAX_SAT" .emit OP_MAX_SAT .or
- "MIN" .emit OP_MIN .or "MIN_SAT" .emit OP_MIN_SAT .or
- "MUL" .emit OP_MUL .or "MUL_SAT" .emit OP_MUL_SAT .or
- "SGE" .emit OP_SGE .or "SGE_SAT" .emit OP_SGE_SAT .or
- "SLT" .emit OP_SLT .or "SLT_SAT" .emit OP_SLT_SAT .or
- "SUB" .emit OP_SUB .or "SUB_SAT" .emit OP_SUB_SAT .or
- "XPD" .emit OP_XPD .or "XPD_SAT" .emit OP_XPD_SAT;
-vp_BINop
- "ADD" .emit OP_ADD .or
- "DP3" .emit OP_DP3 .or
- "DP4" .emit OP_DP4 .or
- "DPH" .emit OP_DPH .or
- "DST" .emit OP_DST .or
- "MAX" .emit OP_MAX .or
- "MIN" .emit OP_MIN .or
- "MUL" .emit OP_MUL .or
- "SGE" .emit OP_SGE .or
- "SLT" .emit OP_SLT .or
- "SUB" .emit OP_SUB .or
- "XPD" .emit OP_XPD;
-
-/*
-fragment program
- <TRIop_instruction> ::= <TRIop> <maskedDstReg> ","
- <vectorSrcReg> "," <vectorSrcReg> ","
- <vectorSrcReg>
-
-vertex program
- <TRIop_instruction> ::= <TRIop> <maskedDstReg> ","
- <swizzleSrcReg> "," <swizzleSrcReg> ","
- <swizzleSrcReg>
-*/
-fp_TRIop_instruction
- fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
- vectorSrcReg .and comma .and vectorSrcReg;
-vp_TRIop_instruction
- vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and
- swizzleSrcReg .and comma .and swizzleSrcReg;
-
-/*
-fragment program
- <TRIop> ::= "CMP" | "CMP_SAT"
- | "LRP" | "LRP_SAT"
- | "MAD" | "MAD_SAT"
-
-vertex program
- <TRIop> ::= "MAD"
-*/
-fp_TRIop
- "CMP" .emit OP_CMP .or "CMP_SAT" .emit OP_CMP_SAT .or
- "LRP" .emit OP_LRP .or "LRP_SAT" .emit OP_LRP_SAT .or
- "MAD" .emit OP_MAD .or "MAD_SAT" .emit OP_MAD_SAT;
-vp_TRIop
- "MAD" .emit OP_MAD;
-
-/*
-fragment program
- <SWZ_instruction> ::= <SWZop> <maskedDstReg> ","
- <srcReg> "," <extendedSwizzle>
-
-vertex program
- <SWZ_instruction> ::= "SWZ" <maskedDstReg> "," <srcReg> ","
- <extendedSwizzle>
-*/
-fp_SWZ_instruction
- SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and
- fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;
-vp_SWZ_instruction
- "SWZ" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and
- vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;
-
-/*
-fragment program
- <SWZop> ::= "SWZ" | "SWZ_SAT"
-*/
-SWZop
- "SWZ" .emit OP_SWZ .or "SWZ_SAT" .emit OP_SWZ_SAT;
-
-/*
-fragment program
- <SAMPLE_instruction> ::= <SAMPLEop> <maskedDstReg> ","
- <vectorSrcReg> "," <texImageUnit> ","
- <texTarget>
-*/
-SAMPLE_instruction
- SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
- texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;
-
-/*
-fragment program
- <SAMPLEop> ::= "TEX" | "TEX_SAT"
- | "TXP" | "TXP_SAT"
- | "TXB" | "TXB_SAT"
-*/
-SAMPLEop
- "TEX" .emit OP_TEX .or "TEX_SAT" .emit OP_TEX_SAT .or
- "TXB" .emit OP_TXB .or "TXB_SAT" .emit OP_TXB_SAT .or
- "TXP" .emit OP_TXP .or "TXP_SAT" .emit OP_TXP_SAT;
-
-/*
-fragment program
- <KIL_instruction> ::= "KIL" <vectorSrcReg>
-*/
-KIL_instruction
- "KIL" .emit OP_KIL .and space_src .and vectorSrcReg;
-
-/*
-fragment program
- <texImageUnit> ::= "texture" <optTexImageUnitNum>
-*/
-texImageUnit
- "texture" .error TEXTURE_EXPECTED .and optTexImageUnitNum;
-
-/*
-fragment program
- <texTarget> ::= "1D"
- | "2D"
- | "3D"
- | "CUBE"
- | "RECT"
- | <shadowTarget> (if option ARB_fragment_program_shadow present)
- | <arrayTarget> (if option MESA_texture_array present)
-*/
-texTarget
- "1D" .emit TEXTARGET_1D .or
- "2D" .emit TEXTARGET_2D .or
- "3D" .emit TEXTARGET_3D .or
- .if (texture_rectangle != 0x00) "RECT" .emit TEXTARGET_RECT .or
- "CUBE" .emit TEXTARGET_CUBE .or
- .if (ARB_fragment_program_shadow != 0x00) shadowTarget .or
- .if (MESA_texture_array != 0x00) arrayTarget;
-
-/*
-GL_ARB_fragment_program_shadow
- <shadowTarget> ::= "SHADOW1D"
- | "SHADOW2D"
- | "SHADOWRECT"
- | <shadowArrayTarget> (if option MESA_texture_array present)
-*/
-shadowTarget
- "SHADOW1D" .emit TEXTARGET_SHADOW1D .or
- "SHADOW2D" .emit TEXTARGET_SHADOW2D .or
- .if (texture_rectangle != 0x00) "SHADOWRECT" .emit TEXTARGET_SHADOWRECT .or
- .if (MESA_texture_array != 0x00) shadowArrayTarget;
-
-/*
-GL_MESA_texture_array
-
- <arrayTarget> ::= "ARRAY1D"
- | "ARRAY2D"
-
- <shadowArrayTarget> ::= "SHADOWARRAY1D"
- | "SHADOWARRAY2D"
-*/
-
-arrayTarget
- "ARRAY1D" .emit TEXTARGET_1D_ARRAY .or
- "ARRAY2D" .emit TEXTARGET_2D_ARRAY;
-
-shadowArrayTarget
- "SHADOWARRAY1D" .emit TEXTARGET_SHADOW1D_ARRAY .or
- "SHADOWARRAY2D" .emit TEXTARGET_SHADOW2D_ARRAY;
-
-/*
-fragment program
- <optTexImageUnitNum> ::= ""
- | "[" <texImageUnitNum> "]"
-*/
-optTexImageUnitNum
- optTexImageUnitNum_1 .or .true .emit 0x00;
-optTexImageUnitNum_1
- lbracket_ne .and texImageUnitNum .and rbracket;
-
-/*
-fragment program
- <texImageUnitNum> ::= <integer> from 0 to
- MAX_TEXTURE_IMAGE_UNITS_ARB-1
-*/
-texImageUnitNum
- integer;
-
-/*
- <scalarSrcReg> ::= <optionalSign> <srcReg> <scalarSuffix>
-*/
-fp_scalarSrcReg
- optionalSign .and fp_srcReg .and fp_scalarSuffix;
-vp_scalarSrcReg
- optionalSign .and vp_srcReg .and vp_scalarSuffix;
-
-/*
-vertex program
- <swizzleSrcReg> ::= <optionalSign> <srcReg> <swizzleSuffix>
-*/
-swizzleSrcReg
- optionalSign .and vp_srcReg .and swizzleSuffix;
-
-/*
-fragment program
- <vectorSrcReg> ::= <optionalSign> <srcReg> <optionalSuffix>
-*/
-vectorSrcReg
- optionalSign .and fp_srcReg .and optionalSuffix;
-
-/*
- <maskedDstReg> ::= <dstReg> <optionalMask>
-*/
-fp_maskedDstReg
- fp_dstReg .and fp_optionalMask;
-vp_maskedDstReg
- vp_dstReg .and vp_optionalMask;
-
-/*
-vertex program
- <maskedAddrReg> ::= <addrReg> <addrWriteMask>
-*/
-maskedAddrReg
- addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;
-
-/*
-fragment program
- <extendedSwizzle> ::= <xyzwExtendedSwizzle>
- | <rgbaExtendedSwizzle>
-
-vertex program
- <extendedSwizzle> ::= <extSwizComp> "," <extSwizComp> ","
- <extSwizComp> "," <extSwizComp>
-
-NOTE: do NOT change the order of <rgbaExtendedSwizzle> and <xyzwExtendedSwizzle> rulez
-*/
-fp_extendedSwizzle
- rgbaExtendedSwizzle .or xyzwExtendedSwizzle;
-vp_extendedSwizzle
- extSwizComp .and comma .and
- extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- extSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-
-/*
-fragment program
- <xyzwExtendedSwizzle> ::= <xyzwExtSwizComp> "," <xyzwExtSwizComp> ","
- <xyzwExtSwizComp> "," <xyzwExtSwizComp>
-*/
-xyzwExtendedSwizzle
- xyzwExtSwizComp .and comma .and
- xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-
-/*
-fragment program
- <rgbaExtendedSwizzle> ::= <rgbaExtSwizComp> "," <rgbaExtSwizComp> ","
- <rgbaExtSwizComp> "," <rgbaExtSwizComp>
-*/
-rgbaExtendedSwizzle
- rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or
- rgbaExtendedSwizzle_4;
-rgbaExtendedSwizzle_1
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;
-rgbaExtendedSwizzle_2
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and
- rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-rgbaExtendedSwizzle_3
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-rgbaExtendedSwizzle_4
- rgbaExtSwizComp_alpha .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-
-/*
-fragment program
- <xyzwExtSwizComp> ::= <optionalSign> <xyzwExtSwizSel>
-*/
-xyzwExtSwizComp
- optionalSign .and xyzwExtSwizSel;
-
-/*
-fragment program
- <rgbaExtSwizComp> ::= <optionalSign> <rgbaExtSwizSel>
-*/
-rgbaExtSwizComp
- optionalSign .and rgbaExtSwizSel;
-rgbaExtSwizComp_digit
- optionalSign .and rgbaExtSwizSel_digit;
-rgbaExtSwizComp_alpha
- optionalSign .and rgbaExtSwizSel_alpha;
-
-/*
-vertex program
- <extSwizComp> ::= <optionalSign> <extSwizSel>
-*/
-extSwizComp
- optionalSign .and extSwizSel;
-
-/*
-fragment program
- <xyzwExtSwizSel> ::= "0"
- | "1"
- | <xyzwComponent>
-*/
-xyzwExtSwizSel
- "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or xyzwComponent_single;
-
-/*
-fragment program
- <rgbaExtSwizSel> ::= "0"
- | "1"
- | <rgbaComponent>
-*/
-rgbaExtSwizSel
- rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;
-rgbaExtSwizSel_digit
- "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1;
-rgbaExtSwizSel_alpha
- rgbaComponent_single;
-
-/*
-vertex program
- <extSwizSel> ::= "0"
- | "1"
- | <component>
-*/
-extSwizSel
- "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or vp_component_single;
-
-/*
-fragment program
- <srcReg> ::= <fragmentAttribReg>
- | <temporaryReg>
- | <progParamReg>
-
-vertex program
- <srcReg> ::= <vertexAttribReg>
- | <temporaryReg>
- | <progParamReg>
-*/
-fp_srcReg
- fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;
-vp_srcReg
- vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;
-fp_srcReg_1
- fragmentAttribReg .emit REGISTER_ATTRIB .or
- fp_progParamReg .emit REGISTER_PARAM .or
- fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
-vp_srcReg_1
- vertexAttribReg .emit REGISTER_ATTRIB .or
- vp_progParamReg .emit REGISTER_PARAM .or
- vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
-
-/*
-fragment program
- <dstReg> ::= <temporaryReg>
- | <fragmentResultReg>
-
-vertex program
- <dstReg> ::= <temporaryReg>
- | <vertexResultReg>
-*/
-fp_dstReg
- fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;
-vp_dstReg
- vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;
-fp_dstReg_1
- fragmentResultReg .emit REGISTER_RESULT .or
- fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
-vp_dstReg_1
- vertexResultReg .emit REGISTER_RESULT .or
- vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
-
-/*
-fragment program
- <fragmentAttribReg> ::= <establishedName>
- | <fragAttribBinding>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
-*/
-fragmentAttribReg
- /*fp_establishedName .or */fragAttribBinding;
-
-/*
-vertex program
- <vertexAttribReg> ::= <establishedName>
- | <vtxAttribBinding>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
-*/
-vertexAttribReg
- vtxAttribBinding;
-
-/*
- <temporaryReg> ::= <establishedName>
-*/
-fp_temporaryReg
- fp_establishedName_no_error_on_identifier;
-vp_temporaryReg
- vp_establishedName_no_error_on_identifier;
-
-/*
-fragment program
- <progParamReg> ::= <progParamSingle>
- | <progParamArray> "[" <progParamArrayAbs> "]"
- | <paramSingleItemUse>
-
-vertex program
- <progParamReg> ::= <progParamSingle>
- | <progParamArray> "[" <progParamArrayMem> "]"
- | <paramSingleItemUse>
-*/
-fp_progParamReg
- fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;
-vp_progParamReg
- vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;
-fp_progParamReg_1
- fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and
- rbracket;
-vp_progParamReg_1
- vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and
- rbracket;
-
-/*
- <progParamSingle> ::= <establishedName>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
-*/
-fp_progParamSingle
- .false;
-vp_progParamSingle
- .false;
-
-/*
- <progParamArray> ::= <establishedName>
-*/
-fp_progParamArray
- fp_establishedName_no_error_on_identifier;
-vp_progParamArray
- vp_establishedName_no_error_on_identifier;
-
-/*
-vertex program
- <progParamArrayMem> ::= <progParamArrayAbs>
- | <progParamArrayRel>
-*/
-progParamArrayMem
- progParamArrayAbs .or progParamArrayRel;
-
-/*
- <progParamArrayAbs> ::= <integer>
-*/
-progParamArrayAbs
- integer_ne .emit ARRAY_INDEX_ABSOLUTE;
-
-/*
-vertex program
- <progParamArrayRel> ::= <addrReg> <addrComponent> <addrRegRelOffset>
-*/
-progParamArrayRel
- addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and
- addrComponent .and addrRegRelOffset;
-
-/*
-vertex program
- <addrRegRelOffset> ::= ""
- | "+" <addrRegPosOffset>
- | "-" <addrRegNegOffset>
-*/
-addrRegRelOffset
- addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;
-addrRegRelOffset_1
- plus_ne .and addrRegPosOffset;
-addrRegRelOffset_2
- minus_ne .and addrRegNegOffset;
-
-/*
-vertex program
- <addrRegPosOffset> ::= <integer> from 0 to 63
-*/
-addrRegPosOffset
- integer_0_63;
-
-/*
-vertex program
- <addrRegNegOffset> ::= <integer> from 0 to 64
-*/
-addrRegNegOffset
- integer_0_64;
-
-/*
-fragment program
- <fragmentResultReg> ::= <establishedName>
- | <resultBinding>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>
-*/
-fragmentResultReg
- fp_resultBinding;
-
-/*
-vertex program
- <vertexResultReg> ::= <establishedName>
- | <resultBinding>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>
-*/
-vertexResultReg
- vp_resultBinding;
-
-/*
-vertex program
- <addrReg> ::= <establishedName>
-*/
-addrReg
- vp_establishedName_no_error_on_identifier;
-
-/*
-vertex program
- <addrComponent> ::= "." "x"
-*/
-addrComponent
- dot .and "x" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X
- .emit COMPONENT_X .emit COMPONENT_X;
-
-/*
-vertex program
- <addrWriteMask> ::= "." "x"
-*/
-addrWriteMask
- dot .and "x" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;
-
-/*
- <scalarSuffix> ::= "." <component>
-*/
-fp_scalarSuffix
- dot .and fp_component_single .error INVALID_COMPONENT;
-vp_scalarSuffix
- dot .and vp_component_single .error INVALID_COMPONENT;
-
-/*
-vertex program
- <swizzleSuffix> ::= ""
- | "." <component>
- | "." <component> <component>
- <component> <component>
-*/
-swizzleSuffix
- swizzleSuffix_1 .or
- .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;
-swizzleSuffix_1
- dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;
-swizzleSuffix_2
- swizzleSuffix_3 .or swizzleSuffix_4;
-swizzleSuffix_3
- vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and
- vp_component_multi .error INVALID_COMPONENT;
-swizzleSuffix_4
- "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
- "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
- "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
- "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;
-
-/*
-fragment program
- <optionalSuffix> ::= ""
- | "." <component>
- | "." <xyzwComponent> <xyzwComponent>
- <xyzwComponent> <xyzwComponent>
- | "." <rgbaComponent> <rgbaComponent>
- <rgbaComponent> <rgbaComponent>
-*/
-optionalSuffix
- optionalSuffix_1 .or
- .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;
-optionalSuffix_1
- dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;
-optionalSuffix_2
- optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;
-optionalSuffix_3
- xyzwComponent_multi .and xyzwComponent_multi .and
- xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;
-optionalSuffix_4
- rgbaComponent_multi .and rgbaComponent_multi .and
- rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;
-optionalSuffix_5
- "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
- "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
- "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
- "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or
- "r" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
- "g" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
- "b" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
- "a" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;
-
-/*
-fragment program
- <component> ::= <xyzwComponent>
- | <rgbaComponent>
-
-vertex program
- <component> ::= "x"
- | "y"
- | "z"
- | "w"
-*/
-fp_component_single
- xyzwComponent_single .or rgbaComponent_single;
-vp_component_multi
- 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or
- 'w' .emit COMPONENT_W;
-vp_component_single
- "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or
- "w" .emit COMPONENT_W;
-
-/*
-fragment program
- <xyzwComponent> ::= "x" | "y" | "z" | "w"
-*/
-xyzwComponent_multi
- 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or
- 'w' .emit COMPONENT_W;
-xyzwComponent_single
- "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or
- "w" .emit COMPONENT_W;
-
-/*
-fragment program
- <rgbaComponent> ::= "r" | "g" | "b" | "a"
-*/
-rgbaComponent_multi
- 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or
- 'a' .emit COMPONENT_W;
-rgbaComponent_single
- "r" .emit COMPONENT_X .or "g" .emit COMPONENT_Y .or "b" .emit COMPONENT_Z .or
- "a" .emit COMPONENT_W;
-
-/*
-fragment program
- <optionalMask> ::= ""
- | <xyzwMask>
- | <rgbaMask>
-
-vertex program
- <optionalMask> ::= ""
- | "." "x"
- | "." "y"
- | "." "xy"
- | "." "z"
- | "." "xz"
- | "." "yz"
- | "." "xyz"
- | "." "w"
- | "." "xw"
- | "." "yw"
- | "." "xyw"
- | "." "zw"
- | "." "xzw"
- | "." "yzw"
- | "." "xyzw"
-
-NOTE: do NOT change the order of <rgbaMask> and <xyzwMask> rulez
-*/
-fp_optionalMask
- rgbaMask .or xyzwMask .or .true .emit 0x0F;
-vp_optionalMask
- xyzwMask .or .true .emit 0x0F;
-
-/*
-fragment program
- <xyzwMask> ::= "." "x"
- | "." "y"
- | "." "xy"
- | "." "z"
- | "." "xz"
- | "." "yz"
- | "." "xyz"
- | "." "w"
- | "." "xw"
- | "." "yw"
- | "." "xyw"
- | "." "zw"
- | "." "xzw"
- | "." "yzw"
- | "." "xyzw"
-
-NOTE: <xyzwMask> is also referenced by the vertex program symbol <optionalMask>.
-*/
-xyzwMask
- dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;
-xyzwMask_1
- "xyzw" .emit 0x0F .or "xyz" .emit 0x0E .or "xyw" .emit 0x0D .or "xy" .emit 0x0C .or
- "xzw" .emit 0x0B .or "xz" .emit 0x0A .or "xw" .emit 0x09 .or "x" .emit 0x08 .or
- "yzw" .emit 0x07 .or "yz" .emit 0x06 .or "yw" .emit 0x05 .or "y" .emit 0x04 .or
- "zw" .emit 0x03 .or "z" .emit 0x02 .or "w" .emit 0x01;
-
-/*
-fragment program
- <rgbaMask> ::= "." "r"
- | "." "g"
- | "." "rg"
- | "." "b"
- | "." "rb"
- | "." "gb"
- | "." "rgb"
- | "." "a"
- | "." "ra"
- | "." "ga"
- | "." "rga"
- | "." "ba"
- | "." "rba"
- | "." "gba"
- | "." "rgba"
-*/
-rgbaMask
- dot_ne .and rgbaMask_1;
-rgbaMask_1
- "rgba" .emit 0x0F .or "rgb" .emit 0x0E .or "rga" .emit 0x0D .or "rg" .emit 0x0C .or
- "rba" .emit 0x0B .or "rb" .emit 0x0A .or "ra" .emit 0x09 .or "r" .emit 0x08 .or
- "gba" .emit 0x07 .or "gb" .emit 0x06 .or "ga" .emit 0x05 .or "g" .emit 0x04 .or
- "ba" .emit 0x03 .or "b" .emit 0x02 .or "a" .emit 0x01;
-
-/*
-fragment program
- <namingStatement> ::= <ATTRIB_statement>
- | <PARAM_statement>
- | <TEMP_statement>
- | <OUTPUT_statement>
- | <ALIAS_statement>
-
-vertex program
- <namingStatement> ::= <ATTRIB_statement>
- | <PARAM_statement>
- | <TEMP_statement>
- | <ADDRESS_statement>
- | <OUTPUT_statement>
- | <ALIAS_statement>
-*/
-fp_namingStatement
- fp_ATTRIB_statement .emit ATTRIB .or
- fp_PARAM_statement .emit PARAM .or
- fp_TEMP_statement .emit TEMP .or
- fp_OUTPUT_statement .emit OUTPUT .or
- fp_ALIAS_statement .emit ALIAS;
-vp_namingStatement
- vp_ATTRIB_statement .emit ATTRIB .or
- vp_PARAM_statement .emit PARAM .or
- vp_TEMP_statement .emit TEMP .or
- ADDRESS_statement .emit ADDRESS .or
- vp_OUTPUT_statement .emit OUTPUT .or
- vp_ALIAS_statement .emit ALIAS;
-
-/*
-fragment program
- <ATTRIB_statement> ::= "ATTRIB" <establishName> "="
- <fragAttribBinding>
-
-vertex program
- <ATTRIB_statement> ::= "ATTRIB" <establishName> "="
- <vtxAttribBinding>
-*/
-fp_ATTRIB_statement
- "ATTRIB" .and space .and fp_establishName .and equal .and
- fragAttribBinding .error FRAGMENT_EXPECTED;
-vp_ATTRIB_statement
- "ATTRIB" .and space .and vp_establishName .and equal .and
- vtxAttribBinding .error VERTEX_EXPECTED;
-
-/*
-fragment program
- <fragAttribBinding> ::= "fragment" "." <fragAttribItem>
-*/
-fragAttribBinding
- "fragment" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;
-
-/*
-vertex program
- <vtxAttribBinding> ::= "vertex" "." <vtxAttribItem>
-*/
-vtxAttribBinding
- "vertex" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;
-
-/*
-fragment program
- <fragAttribItem> ::= "color" <optColorType>
- | "texcoord" <optTexCoordNum>
- | "fogcoord"
- | "position"
-*/
-fragAttribItem
- fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or
- fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or
- .if (fog_coord != 0x00) "fogcoord" .emit FRAGMENT_ATTRIB_FOGCOORD .or
- "position" .emit FRAGMENT_ATTRIB_POSITION;
-fragAttribItem_1
- "color" .and optColorType;
-fragAttribItem_2
- "texcoord" .and optTexCoordNum;
-
-/*
-vertex program
- <vtxAttribItem> ::= "position"
- | "weight" <vtxOptWeightNum>
- | "normal"
- | "color" <optColorType>
- | "fogcoord"
- | "texcoord" <optTexCoordNum>
- | "matrixindex" "[" <vtxWeightNum> "]"
- | "attrib" "[" <vtxAttribNum> "]"
-*/
-vtxAttribItem
- "position" .emit VERTEX_ATTRIB_POSITION .or
- .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or
- "normal" .emit VERTEX_ATTRIB_NORMAL .or
- vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or
- "fogcoord" .emit VERTEX_ATTRIB_FOGCOORD .or
- vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or
- .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or
- vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;
-vtxAttribItem_1
- "weight" .and vtxOptWeightNum;
-vtxAttribItem_2
- "color" .and optColorType;
-vtxAttribItem_3
- "texcoord" .and optTexCoordNum;
-vtxAttribItem_4
- "matrixindex" .and lbracket .and vtxWeightNum .and rbracket;
-vtxAttribItem_5
- "attrib" .and lbracket .and vtxAttribNum .and rbracket;
-
-/*
-vertex program
- <vtxAttribNum> ::= <integer> from 0 to MAX_VERTEX_ATTRIBS_ARB-1
-*/
-vtxAttribNum
- integer;
-
-/*
-vertex program
- <vtxOptWeightNum> ::= ""
- | "[" <vtxWeightNum> "]"
-*/
-vtxOptWeightNum
- vtxOptWeightNum_1 .or .true .emit 0x00;
-vtxOptWeightNum_1
- lbracket_ne .and vtxWeightNum .and rbracket;
-
-/*
-vertex program
- <vtxWeightNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1,
- must be divisible by four
-*/
-vtxWeightNum
- integer;
-
-/*
- <PARAM_statement> ::= <PARAM_singleStmt>
- | <PARAM_multipleStmt>
-*/
-fp_PARAM_statement
- fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;
-vp_PARAM_statement
- vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;
-
-/*
- <PARAM_singleStmt> ::= "PARAM" <establishName> <paramSingleInit>
-*/
-fp_PARAM_singleStmt
- "PARAM" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and
- .true .emit PARAM_NULL;
-vp_PARAM_singleStmt
- "PARAM" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and
- .true .emit PARAM_NULL;
-
-/*
- <PARAM_multipleStmt> ::= "PARAM" <establishName> "[" <optArraySize> "]"
- <paramMultipleInit>
-*/
-fp_PARAM_multipleStmt
- "PARAM" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and
- fp_paramMultipleInit .and .true .emit PARAM_NULL;
-vp_PARAM_multipleStmt
- "PARAM" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and
- vp_paramMultipleInit .and .true .emit PARAM_NULL;
-
-/*
- <optArraySize> ::= ""
- | <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB
- (maximum number of allowed program
- parameter bindings)
-*/
-optArraySize
- optional_integer;
-
-/*
- <paramSingleInit> ::= "=" <paramSingleItemDecl>
-*/
-fp_paramSingleInit
- equal .and fp_paramSingleItemDecl;
-vp_paramSingleInit
- equal .and vp_paramSingleItemDecl;
-
-/*
- <paramMultipleInit> ::= "=" "{" <paramMultInitList> "}"
-*/
-fp_paramMultipleInit
- equal .and lbrace .and fp_paramMultInitList .and rbrace;
-vp_paramMultipleInit
- equal .and lbrace .and vp_paramMultInitList .and rbrace;
-
-/*
- <paramMultInitList> ::= <paramMultipleItem>
- | <paramMultipleItem> "," <paramMultiInitList>
-*/
-fp_paramMultInitList
- fp_paramMultInitList_1 .or fp_paramMultipleItem;
-vp_paramMultInitList
- vp_paramMultInitList_1 .or vp_paramMultipleItem;
-fp_paramMultInitList_1
- fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;
-vp_paramMultInitList_1
- vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;
-
-/*
- <paramSingleItemDecl> ::= <stateSingleItem>
- | <programSingleItem>
- | <paramConstDecl>
-*/
-fp_paramSingleItemDecl
- fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstDecl .emit PARAM_CONSTANT;
-vp_paramSingleItemDecl
- vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstDecl .emit PARAM_CONSTANT;
-
-/*
- <paramSingleItemUse> ::= <stateSingleItem>
- | <programSingleItem>
- | <paramConstUse>
-*/
-fp_paramSingleItemUse
- fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstUse .emit PARAM_CONSTANT;
-vp_paramSingleItemUse
- vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstUse .emit PARAM_CONSTANT;
-
-/*
- <paramMultipleItem> ::= <stateMultipleItem>
- | <programMultipleItem>
- | <paramConstDecl>
-*/
-fp_paramMultipleItem
- fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or
- programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstDecl .emit PARAM_CONSTANT;
-vp_paramMultipleItem
- vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or
- programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstDecl .emit PARAM_CONSTANT;
-
-/*
- <stateMultipleItem> ::= <stateSingleItem>
- | "state" "." <stateMatrixRows>
-*/
-fp_stateMultipleItem
- stateMultipleItem_1 .or fp_stateSingleItem;
-vp_stateMultipleItem
- stateMultipleItem_1 .or vp_stateSingleItem;
-stateMultipleItem_1
- "state" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;
-
-/*
-fragment program
- <stateSingleItem> ::= "state" "." <stateMaterialItem>
- | "state" "." <stateLightItem>
- | "state" "." <stateLightModelItem>
- | "state" "." <stateLightProdItem>
- | "state" "." <stateTexEnvItem>
- | "state" "." <stateFogItem>
- | "state" "." <stateDepthItem>
- | "state" "." <stateMatrixRow>
-
-vertex program
- <stateSingleItem> ::= "state" "." <stateMaterialItem>
- | "state" "." <stateLightItem>
- | "state" "." <stateLightModelItem>
- | "state" "." <stateLightProdItem>
- | "state" "." <stateTexGenItem>
- | "state" "." <stateFogItem>
- | "state" "." <stateClipPlaneItem>
- | "state" "." <statePointItem>
- | "state" "." <stateMatrixRow>
-*/
-fp_stateSingleItem
- "state" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;
-vp_stateSingleItem
- "state" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;
-fp_stateSingleItem_1
- stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or
- stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;
-vp_stateSingleItem_1
- stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or
- stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or
- stateSingleItem_11;
-stateSingleItem_1
- stateMaterialItem .emit STATE_MATERIAL;
-stateSingleItem_2
- stateLightItem .emit STATE_LIGHT;
-stateSingleItem_3
- stateLightModelItem .emit STATE_LIGHT_MODEL;
-stateSingleItem_4
- stateLightProdItem .emit STATE_LIGHT_PROD;
-stateSingleItem_5
- stateTexEnvItem .emit STATE_TEX_ENV;
-stateSingleItem_6
- stateTexGenItem .emit STATE_TEX_GEN;
-stateSingleItem_7
- stateFogItem .emit STATE_FOG;
-stateSingleItem_8
- stateDepthItem .emit STATE_DEPTH;
-stateSingleItem_9
- stateClipPlaneItem .emit STATE_CLIP_PLANE;
-stateSingleItem_10
- statePointItem .emit STATE_POINT;
-stateSingleItem_11
- stateMatrixRow .emit STATE_MATRIX_ROWS;
-
-/*
- <stateMaterialItem> ::= "material" <optFaceType> "." <stateMatProperty>
-*/
-stateMaterialItem
- "material" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;
-
-/*
- <stateMatProperty> ::= "ambient"
- | "diffuse"
- | "specular"
- | "emission"
- | "shininess"
-*/
-stateMatProperty
- "ambient" .emit MATERIAL_AMBIENT .or
- "diffuse" .emit MATERIAL_DIFFUSE .or
- "specular" .emit MATERIAL_SPECULAR .or
- "emission" .emit MATERIAL_EMISSION .or
- "shininess" .emit MATERIAL_SHININESS;
-
-/*
- <stateLightItem> ::= "light" "[" <stateLightNumber> "]" "."
- <stateLightProperty>
-*/
-stateLightItem
- "light" .and lbracket .and stateLightNumber .and rbracket .and dot .and
- stateLightProperty .error INVALID_LIGHT_PROPERTY;
-
-/*
- <stateLightProperty> ::= "ambient"
- | "diffuse"
- | "specular"
- | "position"
- | "attenuation"
- | "spot" "." <stateSpotProperty>
- | "half"
-*/
-stateLightProperty
- "ambient" .emit LIGHT_AMBIENT .or
- "diffuse" .emit LIGHT_DIFFUSE .or
- "specular" .emit LIGHT_SPECULAR .or
- "position" .emit LIGHT_POSITION .or
- "attenuation" .emit LIGHT_ATTENUATION .or
- stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or
- "half" .emit LIGHT_HALF;
-stateLightProperty_1
- "spot" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;
-
-/*
- <stateSpotProperty> ::= "direction"
-*/
-stateSpotProperty
- "direction";
-
-/*
- <stateLightModelItem> ::= "lightmodel" <stateLModProperty>
-*/
-stateLightModelItem
- "lightmodel" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;
-
-/*
- <stateLModProperty> ::= "." "ambient"
- | <optFaceType> "." "scenecolor"
-*/
-stateLModProperty
- stateLModProperty_1 .or stateLModProperty_2;
-stateLModProperty_1
- dot .and "ambient" .emit LIGHT_MODEL_AMBIENT;
-stateLModProperty_2
- stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;
-stateLModProperty_3
- optFaceType .and dot .and "scenecolor";
-
-/*
- <stateLightProdItem> ::= "lightprod" "[" <stateLightNumber> "]"
- <optFaceType> "." <stateLProdProperty>
-*/
-stateLightProdItem
- "lightprod" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and
- stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;
-
-/*
- <stateLProdProperty> ::= "ambient"
- | "diffuse"
- | "specular"
-*/
-stateLProdProperty
- "ambient" .emit LIGHT_PROD_AMBIENT .or
- "diffuse" .emit LIGHT_PROD_DIFFUSE .or
- "specular" .emit LIGHT_PROD_SPECULAR;
-
-/*
- <stateLightNumber> ::= <integer> from 0 to MAX_LIGHTS-1
-*/
-stateLightNumber
- integer;
-
-/*
-fragment program
- <stateTexEnvItem> ::= "texenv" <optLegacyTexUnitNum> "."
- <stateTexEnvProperty>
-*/
-stateTexEnvItem
- "texenv" .and optLegacyTexUnitNum .and dot .and
- stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;
-
-/*
-fragment program
- <stateTexEnvProperty> ::= "color"
-*/
-stateTexEnvProperty
- "color" .emit TEX_ENV_COLOR;
-
-/*
-fragment program
- <optLegacyTexUnitNum> ::= ""
- | "[" <legacyTexUnitNum> "]"
-*/
-optLegacyTexUnitNum
- optLegacyTexUnitNum_1 .or .true .emit 0x00;
-optLegacyTexUnitNum_1
- lbracket_ne .and legacyTexUnitNum .and rbracket;
-
-/*
-fragment program
- <legacyTexUnitNum> ::= <integer> from 0 to MAX_TEXTURE_UNITS-1
-*/
-legacyTexUnitNum
- integer;
-
-/*
-vertex program
- <stateTexGenItem> ::= "texgen" <optTexCoordNum> "."
- <stateTexGenType> "." <stateTexGenCoord>
-*/
-stateTexGenItem
- "texgen" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and
- dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;
-
-/*
-vertex program
- <stateTexGenType> ::= "eye"
- | "object"
-*/
-stateTexGenType
- "eye" .emit TEX_GEN_EYE .or
- "object" .emit TEX_GEN_OBJECT;
-
-/*
-vertex program
- <stateTexGenCoord> ::= "s"
- | "t"
- | "r"
- | "q"
-*/
-stateTexGenCoord
- "s" .emit COMPONENT_X .or
- "t" .emit COMPONENT_Y .or
- "r" .emit COMPONENT_Z .or
- "q" .emit COMPONENT_W;
-
-/*
- <stateFogItem> ::= "fog" "." <stateFogProperty>
-*/
-stateFogItem
- "fog" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;
-
-/*
- <stateFogProperty> ::= "color"
- | "params"
-*/
-stateFogProperty
- "color" .emit FOG_COLOR .or
- "params" .emit FOG_PARAMS;
-
-/*
-fragment program
- <stateDepthItem> ::= "depth" "." <stateDepthProperty>
-*/
-stateDepthItem
- "depth" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;
-
-/*
-fragment program
- <stateDepthProperty> ::= "range"
-*/
-stateDepthProperty
- "range" .emit DEPTH_RANGE;
-
-/*
-vertex program
- <stateClipPlaneItem> ::= "clip" "[" <stateClipPlaneNum> "]" "." "plane"
-*/
-stateClipPlaneItem
- "clip" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and
- "plane" .error INVALID_CLIPPLANE_PROPERTY;
-
-/*
-vertex program
- <stateClipPlaneNum> ::= <integer> from 0 to MAX_CLIP_PLANES-1
-*/
-stateClipPlaneNum
- integer;
-
-/*
-vertex program
- <statePointItem> ::= "point" "." <statePointProperty>
-*/
-statePointItem
- "point" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;
-
-/*
-vertex program
- <statePointProperty> ::= "size"
- | "attenuation"
-*/
-statePointProperty
- "size" .emit POINT_SIZE .or
- .if (point_parameters != 0x00) "attenuation" .emit POINT_ATTENUATION;
-
-/*
- <stateMatrixRow> ::= <stateMatrixItem> "." "row" "["
- <stateMatrixRowNum> "]"
-*/
-stateMatrixRow
- stateMatrixItem .and dot .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and
- lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;
-
-/*
- <stateMatrixRows> ::= <stateMatrixItem> <optMatrixRows>
-*/
-stateMatrixRows
- stateMatrixItem .and optMatrixRows;
-
-/*
- <optMatrixRows> ::= ""
- | "." "row" "[" <stateMatrixRowNum> ".."
- <stateMatrixRowNum> "]"
-*/
-optMatrixRows
- optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;
-optMatrixRows_1
- dot_ne .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and
- stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;
-
-/*
- <stateMatrixItem> ::= "matrix" "." <stateMatrixName>
- <stateOptMatModifier>
-*/
-stateMatrixItem
- "matrix" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;
-
-/*
- <stateOptMatModifier> ::= ""
- | "." <stateMatModifier>
-*/
-stateOptMatModifier
- stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;
-stateOptMatModifier_1
- dot_ne .and stateMatModifier;
-
-/*
- <stateMatModifier> ::= "inverse"
- | "transpose"
- | "invtrans"
-*/
-stateMatModifier
- "inverse" .emit MATRIX_MODIFIER_INVERSE .or
- "transpose" .emit MATRIX_MODIFIER_TRANSPOSE .or
- "invtrans" .emit MATRIX_MODIFIER_INVTRANS;
-
-/*
- <stateMatrixRowNum> ::= <integer> from 0 to 3
-*/
-stateMatrixRowNum
- integer_0_3;
-
-/*
- <stateMatrixName> ::= "modelview" <stateOptModMatNum>
- | "projection"
- | "mvp"
- | "texture" <optTexCoordNum>
- | "palette" "[" <statePaletteMatNum> "]"
- | "program" "[" <stateProgramMatNum> "]"
-*/
-stateMatrixName
- stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or
- "projection" .emit MATRIX_PROJECTION .or
- "mvp" .emit MATRIX_MVP .or
- stateMatrixName_1_2 .emit MATRIX_TEXTURE .or
- .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or
- stateMatrixName_1_4 .emit MATRIX_PROGRAM;
-stateMatrixName_1_1
- "modelview" .and stateOptModMatNum;
-stateMatrixName_1_2
- "texture" .and optTexCoordNum;
-stateMatrixName_1_3
- "palette" .and lbracket .and statePaletteMatNum .and rbracket;
-stateMatrixName_1_4
- "program" .and lbracket .and stateProgramMatNum .and rbracket;
-
-/*
- <stateOptModMatNum> ::= ""
- | "[" <stateModMatNum> "]"
-*/
-stateOptModMatNum
- .if (vertex_blend != 0x00) stateOptModMatNum_1 .or
- .true .emit 0x00;
-stateOptModMatNum_1
- lbracket_ne .and stateModMatNum .and rbracket;
-
-/*
- <stateModMatNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1
-*/
-stateModMatNum
- integer;
-
-/*
- <optTexCoordNum> ::= ""
- | "[" <texCoordNum> "]"
-*/
-optTexCoordNum
- optTexCoordNum_1 .or .true .emit 0x00;
-optTexCoordNum_1
- lbracket_ne .and texCoordNum .and rbracket;
-
-/*
- <texCoordNum> ::= <integer> from 0 to MAX_TEXTURE_COORDS_ARB-1
-*/
-texCoordNum
- integer;
-
-/*
- <statePaletteMatNum> ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1
-*/
-statePaletteMatNum
- integer;
-
-/*
- <stateProgramMatNum> ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1
-*/
-stateProgramMatNum
- integer;
-
-/*
- <programSingleItem> ::= <progEnvParam>
- | <progLocalParam>
-
-NOTE: <programSingleItem> has been modified for correct error handling. If program property
- is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.
-*/
-programSingleItem
- "program" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;
-programSingleItem_1
- progEnvParam .or progLocalParam;
-
-/*
- <programMultipleItem> ::= <progEnvParams>
- | <progLocalParams>
-
-NOTE: <programMultipleItem> has been modified for correct error handling. If program property
- is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.
-*/
-programMultipleItem
- "program" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;
-programMultipleItem_1
- progEnvParams .or progLocalParams;
-
-/*
- <progEnvParams> ::= "program" "." "env"
- "[" <progEnvParamNums> "]"
-
-NOTE: "program" "." has been moved to <programMultipleItem>.
-*/
-progEnvParams
- "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;
-
-/*
- <progEnvParamNums> ::= <progEnvParamNum>
- | <progEnvParamNum> ".." <progEnvParamNum>
-*/
-progEnvParamNums
- progEnvParamNums_1 .or progEnvParamNums_2;
-progEnvParamNums_1
- progEnvParamNum .and dotdot_ne .and progEnvParamNum;
-progEnvParamNums_2
- progEnvParamNum .and .true .emit 0x00;
-
-/*
- <progEnvParam> ::= "program" "." "env"
- "[" <progEnvParamNum> "]"
-
-NOTE: "program" "." has been moved to <programSingleItem>.
-*/
-progEnvParam
- "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;
-
-/*
- <progLocalParams> ::= "program" "." "local"
- "[" <progLocalParamNums> "]"
-
-NOTE: "program" "." has been moved to <programMultipleItem>.
-*/
-progLocalParams
- "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;
-
-/*
- <progLocalParamNums> ::= <progLocalParamNum>
- | <progLocalParamNum> ".." <progLocalParamNum>
-*/
-progLocalParamNums
- progLocalParamNums_1 .or progLocalParamNums_2;
-progLocalParamNums_1
- progLocalParamNum .and dotdot_ne .and progLocalParamNum;
-progLocalParamNums_2
- progLocalParamNum .and .true .emit 0x00;
-
-/*
- <progLocalParam> ::= "program" "." "local"
- "[" <progLocalParamNum> "]"
-
-NOTE: "program" "." has been moved to <programSingleItem>.
-*/
-progLocalParam
- "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;
-
-/*
- <progEnvParamNum> ::= <integer> from 0 to
- MAX_PROGRAM_ENV_PARAMETERS_ARB - 1
-*/
-progEnvParamNum
- integer;
-
-/*
- <progLocalParamNum> ::= <integer> from 0 to
- MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1
-*/
-progLocalParamNum
- integer;
-
-/*
- <paramConstDecl> ::= <paramConstScalarDecl>
- | <paramConstVector>
-*/
-paramConstDecl
- paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;
-
-/*
- <paramConstUse> ::= <paramConstScalarUse>
- | <paramConstVector>
-*/
-paramConstUse
- paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;
-
-/*
- <paramConstScalarDecl> ::= <signedFloatConstant>
-*/
-paramConstScalarDecl
- signedFloatConstant;
-
-/*
- <paramConstScalarUse> ::= <floatConstant>
-*/
-paramConstScalarUse
- floatConstant;
-
-/*
- <paramConstVector> ::= "{" <signedFloatConstant> "}"
- | "{" <signedFloatConstant> ","
- <signedFloatConstant> "}"
- | "{" <signedFloatConstant> ","
- <signedFloatConstant> ","
- <signedFloatConstant> "}"
- | "{" <signedFloatConstant> ","
- <signedFloatConstant> ","
- <signedFloatConstant> ","
- <signedFloatConstant> "}"
-*/
-paramConstVector
- paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or
- paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;
-paramConstVector_1
- lbrace_ne .and signedFloatConstant .and rbrace;
-paramConstVector_2
- lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;
-paramConstVector_3
- lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and
- signedFloatConstant .and rbrace;
-paramConstVector_4
- lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and
- signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;
-
-/*
- <signedFloatConstant> ::= <optionalSign> <floatConstant>
-*/
-signedFloatConstant
- optionalSign .and floatConstant;
-
-/*
- <floatConstant> ::= see text
- The <floatConstant> rule matches a floating-point constant consisting
- of an integer part, a decimal point, a fraction part, an "e" or
- "E", and an optionally signed integer exponent. The integer and
- fraction parts both consist of a sequence of one or more digits ("0"
- through "9"). Either the integer part or the fraction parts (not
- both) may be missing; either the decimal point or the "e" (or "E")
- and the exponent (not both) may be missing.
-*/
-floatConstant
- float;
-
-/*
- <optionalSign> ::= ""
- | "-"
- | "+"
-*/
-optionalSign
- optional_sign_ne;
-
-/*
- <TEMP_statement> ::= "TEMP" <varNameList>
-*/
-fp_TEMP_statement
- "TEMP" .and space .and fp_varNameList .and .true .emit 0x00;
-vp_TEMP_statement
- "TEMP" .and space .and vp_varNameList .and .true .emit 0x00;
-
-/*
-vertex program
- <ADDRESS_statement> ::= "ADDRESS" <varNameList>
-*/
-ADDRESS_statement
- "ADDRESS" .and space .and vp_varNameList .and .true .emit 0x00;
-
-/*
- <varNameList> ::= <establishName>
- | <establishName> "," <varNameList>
-*/
-fp_varNameList
- fp_varNameList_1 .or fp_establishName;
-vp_varNameList
- vp_varNameList_1 .or vp_establishName;
-fp_varNameList_1
- fp_establishName .and comma_ne .and fp_varNameList;
-vp_varNameList_1
- vp_establishName .and comma_ne .and vp_varNameList;
-
-/*
- <OUTPUT_statement> ::= "OUTPUT" <establishName> "="
- <resultBinding>
-*/
-fp_OUTPUT_statement
- "OUTPUT" .and space .and fp_establishName .and equal .and
- fp_resultBinding .error RESULT_EXPECTED;
-vp_OUTPUT_statement
- "OUTPUT" .and space .and vp_establishName .and equal .and
- vp_resultBinding .error RESULT_EXPECTED;
-
-/*
-fragment program
- <resultBinding> ::= "result" "." "color"
- | "result" "." "color" <optOutputColorNum> (if option ARB_draw_buffers present)
- | "result" "." "depth"
-
-vertex program
- <resultBinding> ::= "result" "." "position"
- | "result" "." <resultColBinding>
- | "result" "." "fogcoord"
- | "result" "." "pointsize"
- | "result" "." "texcoord" <optTexCoordNum>
-*/
-fp_resultBinding
- "result" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;
-vp_resultBinding
- "result" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;
-fp_resultBinding_1
- fp_resultBinding_2 .emit FRAGMENT_RESULT_COLOR .or
- "depth" .emit FRAGMENT_RESULT_DEPTH;
-fp_resultBinding_2
- "color" .and optOutputColorNum;
-vp_resultBinding_1
- .if (ARB_position_invariant == 0x00) "position" .emit VERTEX_RESULT_POSITION .or
- resultColBinding .emit VERTEX_RESULT_COLOR .or
- "fogcoord" .emit VERTEX_RESULT_FOGCOORD .or
- "pointsize" .emit VERTEX_RESULT_POINTSIZE .or
- vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;
-vp_resultBinding_2
- "texcoord" .and optTexCoordNum;
-
-/*
-GL_ARB_draw_buffers
- <optOutputColorNum> ::= ""
- | "[" <outputColorNum> "]"
-*/
-optOutputColorNum
- .if (ARB_draw_buffers != 0x00) optOutputColorNum_1 .or .true .emit 0x00;
-optOutputColorNum_1
- lbracket_ne .and outputColorNum .and rbracket;
-
-/*
-GL_ARB_draw_buffers
- <outputColorNum> ::= <integer> from 0 to MAX_DRAW_BUFFERS_ARB-1
-*/
-outputColorNum
- integer;
-
-/*
-vertex program
- <resultColBinding> ::= "color" <optFaceType> <optColorType>
-*/
-resultColBinding
- "color" .and optFaceType .and optColorType;
-
-/*
- <optFaceType> ::= ""
- | "." "front"
- | "." "back"
-*/
-optFaceType
- FaceType .or .true .emit FACE_FRONT;
-FaceType
- dot_ne .and FaceProperty;
-FaceProperty
- "front" .emit FACE_FRONT .or "back" .emit FACE_BACK;
-
-/*
- <optColorType> ::= ""
- | "." "primary"
- | "." "secondary"
-*/
-optColorType
- ColorType .or .true .emit COLOR_PRIMARY;
-ColorType
- dot_ne .and ColorProperty;
-ColorProperty
- "primary" .emit COLOR_PRIMARY .or
- .if (secondary_color != 0x00) "secondary" .emit COLOR_SECONDARY;
-
-/*
- <ALIAS_statement> ::= "ALIAS" <establishName> "="
- <establishedName>
-*/
-fp_ALIAS_statement
- "ALIAS" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;
-vp_ALIAS_statement
- "ALIAS" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;
-fp_ALIAS_statement_1
- space .and fp_establishName;
-vp_ALIAS_statement_1
- space .and vp_establishName;
-
-/*
- <establishName> ::= <identifier>
-*/
-fp_establishName
- fp_identifier;
-vp_establishName
- vp_identifier;
-
-/*
- <establishedName> ::= <identifier>
-*/
-fp_establishedName
- fp_identifier;
-vp_establishedName
- vp_identifier;
-fp_establishedName_no_error_on_identifier
- fp_identifier_ne;
-vp_establishedName_no_error_on_identifier
- vp_identifier_ne;
-
-/*
-fragment program
- <identifier> ::= see text
- The <identifier> rule matches a sequence of one or more letters ("A"
- through "Z", "a" through "z"), digits ("0" through "9), underscores
- ("_"), or dollar signs ("$"); the first character must not be a
- number. Upper and lower case letters are considered different
- (names are case-sensitive). The following strings are reserved
- keywords and may not be used as identifiers:
-
- ABS, ABS_SAT, ADD, ADD_SAT, ALIAS, ATTRIB, CMP, CMP_SAT, COS,
- COS_SAT, DP3, DP3_SAT, DP4, DP4_SAT, DPH, DPH_SAT, DST, DST_SAT,
- END, EX2, EX2_SAT, FLR, FLR_SAT, FRC, FRC_SAT, KIL, LG2,
- LG2_SAT, LIT, LIT_SAT, LRP, LRP_SAT, MAD, MAD_SAT, MAX, MAX_SAT,
- MIN, MIN_SAT, MOV, MOV_SAT, MUL, MUL_SAT, OPTION, OUTPUT, PARAM,
- POW, POW_SAT, RCP, RCP_SAT, RSQ, RSQ_SAT, SIN, SIN_SAT, SCS,
- SCS_SAT, SGE, SGE_SAT, SLT, SLT_SAT, SUB, SUB_SAT, SWZ, SWZ_SAT,
- TEMP, TEX, TEX_SAT, TXB, TXB_SAT, TXP, TXP_SAT, XPD, XPD_SAT,
- fragment, program, result, state, and texture.
-
-vertex program
- <identifier> ::= see text
- The <identifier> rule matches a sequence of one or more letters ("A"
- through "Z", "a" through "z"), digits ("0" through "9), underscores ("_"),
- or dollar signs ("$"); the first character must not be a number. Upper
- and lower case letters are considered different (names are
- case-sensitive). The following strings are reserved keywords and may not
- be used as identifiers:
-
- ABS, ADD, ADDRESS, ALIAS, ARL, ATTRIB, DP3, DP4, DPH, DST, END, EX2,
- EXP, FLR, FRC, LG2, LIT, LOG, MAD, MAX, MIN, MOV, MUL, OPTION, OUTPUT,
- PARAM, POW, RCP, RSQ, SGE, SLT, SUB, SWZ, TEMP, XPD, program, result,
- state, and vertex.
-*/
-fp_identifier
- fp_identifier_ne .error IDENTIFIER_EXPECTED;
-vp_identifier
- vp_identifier_ne .error IDENTIFIER_EXPECTED;
-fp_identifier_ne
- fp_not_reserved_identifier .and identifier_ne;
-vp_identifier_ne
- vp_not_reserved_identifier .and identifier_ne;
-
-fp_not_reserved_identifier
- fp_not_reserved_identifier_1 .or .true;
-fp_not_reserved_identifier_1
- fp_reserved_identifier .and .false .error RESERVED_KEYWORD;
-vp_not_reserved_identifier
- vp_not_reserved_identifier_1 .or .true;
-vp_not_reserved_identifier_1
- vp_reserved_identifier .and .false .error RESERVED_KEYWORD;
-
-fp_reserved_identifier
- "ABS" .or "ABS_SAT" .or "ADD" .or "ADD_SAT" .or "ALIAS" .or "ATTRIB" .or "CMP" .or "CMP_SAT" .or
- "COS" .or "COS_SAT" .or "DP3" .or "DP3_SAT" .or "DP4" .or "DP4_SAT" .or "DPH" .or "DPH_SAT" .or
- "DST" .or "DST_SAT" .or "END" .or "EX2" .or "EX2_SAT" .or "FLR" .or "FLR_SAT" .or "FRC" .or
- "FRC_SAT" .or "KIL" .or "LG2" .or "LG2_SAT" .or "LIT" .or "LIT_SAT" .or "LRP" .or "LRP_SAT" .or
- "MAD" .or "MAD_SAT" .or "MAX" .or "MAX_SAT" .or "MIN" .or "MIN_SAT" .or "MOV" .or "MOV_SAT" .or
- "MUL" .or "MUL_SAT" .or "OPTION" .or "OUTPUT" .or "PARAM" .or "POW" .or "POW_SAT" .or "RCP" .or
- "RCP_SAT" .or "RSQ" .or "RSQ_SAT" .or "SIN" .or "SIN_SAT" .or "SCS" .or "SCS_SAT" .or "SGE" .or
- "SGE_SAT" .or "SLT" .or "SLT_SAT" .or "SUB" .or "SUB_SAT" .or "SWZ" .or "SWZ_SAT" .or "TEMP" .or
- "TEX" .or "TEX_SAT" .or "TXB" .or "TXB_SAT" .or "TXP" .or "TXP_SAT" .or "XPD" .or "XPD_SAT" .or
- "fragment" .or "program" .or "result" .or "state" .or "texture";
-vp_reserved_identifier
- "ABS" .or "ADD" .or "ADDRESS" .or "ALIAS" .or "ARL" .or "ATTRIB" .or "DP3" .or "DP4" .or
- "DPH" .or "DST" .or "END" .or "EX2" .or "EXP" .or "FLR" .or "FRC" .or "LG2" .or "LIT" .or
- "LOG" .or "MAD" .or "MAX" .or "MIN" .or "MOV" .or "MUL" .or "OPTION" .or "OUTPUT" .or
- "PARAM" .or "POW" .or "RCP" .or "RSQ" .or "SGE" .or "SLT" .or "SUB" .or "SWZ" .or "TEMP" .or
- "XPD" .or "program" .or "result" .or "state" .or "vertex";
-
-/*
- The <integer> rule matches an integer constant. The integer consists
- of a sequence of one or more digits ("0" through "9").
-*/
-integer
- integer_ne .error INTEGER_EXPECTED;
-
-zero
- '0';
-
-leading_zeroes
- .loop zero;
-
-no_digit
- no_digit_1 .or .true;
-no_digit_1
- digit10 .and .false .error INTEGER_OUT_OF_RANGE;
-
-all_zeroes
- all_zeroes_1 .or no_digit_1;
-all_zeroes_1
- '0' .and .loop zero .and no_digit;
-
-integer_0_3
- integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
-integer_0_3_1
- integer_0_3_2 .or all_zeroes .emit '0';
-integer_0_3_2 /* [1, 3] */
- leading_zeroes .and '1'-'3' .emit * .and no_digit;
-
-integer_0_63
- integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
-integer_0_63_1
- integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or
- all_zeroes .emit '0';
-integer_0_63_2 /* [7, 9] */
- leading_zeroes .and '7'-'9' .emit * .and no_digit;
-integer_0_63_3 /* [10, 59] */
- leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;
-integer_0_63_4 /* [60, 63] */
- leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;
-integer_0_63_5 /* [1, 6] */
- leading_zeroes .and '1'-'6' .emit * .and no_digit;
-
-integer_0_64
- integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
-integer_0_64_1
- integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or
- all_zeroes .emit '0';
-integer_0_64_2 /* [7, 9] */
- leading_zeroes .and '7'-'9' .emit * .and no_digit;
-integer_0_64_3 /* [10, 59] */
- leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;
-integer_0_64_4 /* [60, 64] */
- leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;
-integer_0_64_5 /* [1, 6] */
- leading_zeroes .and '1'-'6' .emit * .and no_digit;
-
-optional_space
- space .or .true;
-
-space_dst
- space .error OPERATION_NEEDS_DESTINATION_VARIABLE;
-
-space_src
- space .error OPERATION_NEEDS_SOURCE_VARIABLE;
-
-space
- single_space .and .loop single_space;
-
-single_space
- white_char .or comment_block;
-
-white_char
- ' ' .or '\t' .or '\n' .or '\r';
-
-comment_block
- '#' .and .loop comment_char .and optional_new_line;
-
-/* All ASCII characters except '\r', '\n' and '\0' */
-comment_char
- '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
-
-optional_new_line
- '\n' .or crlf .or .true;
-
-crlf
- '\r' .and '\n';
-
-semicolon
- optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;
-
-comma
- optional_space .and ',' .error MISSING_COMMA .and optional_space;
-
-comma_ne
- optional_space .and ',' .and optional_space;
-
-lbracket
- optional_space .and '[' .error MISSING_LBRACKET .and optional_space;
-
-lbracket_ne
- optional_space .and '[' .and optional_space;
-
-rbracket
- optional_space .and ']' .error MISSING_RBRACKET .and optional_space;
-
-dot
- optional_space .and '.' .error MISSING_DOT .and optional_space;
-
-dot_ne
- optional_space .and '.' .and optional_space;
-
-equal
- optional_space .and '=' .error MISSING_EQUAL .and optional_space;
-
-lbrace
- optional_space .and '{' .error MISSING_LBRACE .and optional_space;
-
-lbrace_ne
- optional_space .and '{' .and optional_space;
-
-rbrace
- optional_space .and '}' .error MISSING_RBRACE .and optional_space;
-
-dotdot
- optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;
-
-dotdot_ne
- optional_space .and '.' .and '.' .and optional_space;
-
-/*
- The definition below accepts the following floating point number formats:
- .99 .99e99 99. 99.99 99.99e99 99.e99 99e99
- Also 99 format was considered and accepted because of a large number of existing program
- strings with such a format.
-*/
-float
- float_1 .or float_2 .or float_legacy;
-float_1
- '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;
-float_2
- integer_ne .and float_3;
-float_3
- float_4 .or float_5;
-float_4
- '.' .and optional_integer .and optional_exponent;
-float_5
- exponent .emit 0x00;
-float_legacy
- integer_ne .and .true .emit 0x00 .emit 0x00;
-
-/*
- Below is a correct version of <float> definiton.
-*/
-/*
-float
- float_1 .or float_2;
-float_1
- '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;
-float_2
- integer_ne .and float_3 .error MISSING_DOT_OR_EXPONENT;
-float_3
- float_4 .or float_5;
-float_4
- '.' .and optional_integer .and optional_exponent;
-float_5
- exponent .emit 0x00;
-*/
-
-integer_ne
- integer_ne_1 .and .true .emit 0x00 .emit $;
-integer_ne_1
- digit10 .emit * .and .loop digit10 .emit *;
-
-optional_integer
- integer_ne .or .true .emit 0x00;
-
-/*
-NOTE: If exponent part is omited we treat it as if it was "E+1".
-*/
-optional_exponent
- exponent .or .true .emit 0x00;
-
-exponent
- exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;
-exponent_1
- 'e' .or 'E';
-
-optional_sign_ne
- minus_ne .or plus_ne .or .true;
-
-plus_ne
- optional_space .and '+' .and optional_space;
-
-minus_ne
- optional_space .and '-' .emit '-' .and optional_space;
-
-identifier_ne
- first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;
-
-follow_idchar
- first_idchar .or digit10;
-
-first_idchar
- 'a'-'z' .or 'A'-'Z' .or '_' .or '$';
-
-digit10
- '0'-'9';
-
-/*
- string filtering - if a string is encountered in grammar ("blabla"), the symbol below is
- executed to create the string. The symbol must not throw any errors and emit bytes - it should
- stop if it encounters invalid character. After this the resulting string (from starting
- position up to the invalid character (but without it) is compared with the grammar string.
-*/
-.string __string_filter;
-
-__string_filter
- .loop __identifier_char;
-
-__identifier_char
- 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';
-
-/*
- error token filtering
-*/
-e_signature
- e_signature_char .and .loop e_signature_char;
-e_signature_char
- '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';
-
-e_statement
- .loop e_statement_not_term;
-/* All ASCII characters to one of '\r', '\n', '\0' and ';' */
-e_statement_not_term
- '\x3C'-'\xFF' .or '\x0E'-'\x3A' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
-
-e_identifier
- e_identifier_first .and .loop e_identifier_next;
-e_identifier_first
- 'a'-'z' .or 'A'-'Z' .or '_' .or '$';
-e_identifier_next
- e_identifier_first .or '0'-'9';
-
-e_token
- e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or
- '-' .or ',' .or ';';
-e_token_number
- e_token_digit .and .loop e_token_digit;
-e_token_digit
- '0'-'9';
-
-e_charordigit
- 'A'-'Z' .or 'a'-'z' .or '0'-'9';
-
diff --git a/src/mesa/shader/arbprogram_syn.h b/src/mesa/shader/arbprogram_syn.h
deleted file mode 100644
index d95a5dede4..0000000000
--- a/src/mesa/shader/arbprogram_syn.h
+++ /dev/null
@@ -1,1350 +0,0 @@
-
-/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */
-
-" \n"
-".syntax program;\n"
-".emtcode REVISION 0x0a\n"
-".emtcode FRAGMENT_PROGRAM 0x01\n"
-".emtcode VERTEX_PROGRAM 0x02\n"
-".emtcode OPTION 0x01\n"
-".emtcode INSTRUCTION 0x02\n"
-".emtcode DECLARATION 0x03\n"
-".emtcode END 0x04\n"
-".emtcode ARB_PRECISION_HINT_FASTEST 0x00\n"
-".emtcode ARB_PRECISION_HINT_NICEST 0x01\n"
-".emtcode ARB_FOG_EXP 0x02\n"
-".emtcode ARB_FOG_EXP2 0x03\n"
-".emtcode ARB_FOG_LINEAR 0x04\n"
-".emtcode ARB_POSITION_INVARIANT 0x05\n"
-".emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x06\n"
-".emtcode ARB_DRAW_BUFFERS 0x07\n"
-".emtcode MESA_TEXTURE_ARRAY 0x08\n"
-".emtcode OP_ALU_INST 0x00\n"
-".emtcode OP_TEX_INST 0x01\n"
-".emtcode OP_ALU_VECTOR 0x00\n"
-".emtcode OP_ALU_SCALAR 0x01\n"
-".emtcode OP_ALU_BINSC 0x02\n"
-".emtcode OP_ALU_BIN 0x03\n"
-".emtcode OP_ALU_TRI 0x04\n"
-".emtcode OP_ALU_SWZ 0x05\n"
-".emtcode OP_TEX_SAMPLE 0x06\n"
-".emtcode OP_TEX_KIL 0x07\n"
-".emtcode OP_ALU_ARL 0x08\n"
-".emtcode OP_ABS 0x00\n"
-".emtcode OP_ABS_SAT 0x1B\n"
-".emtcode OP_FLR 0x09\n"
-".emtcode OP_FLR_SAT 0x26\n"
-".emtcode OP_FRC 0x0A\n"
-".emtcode OP_FRC_SAT 0x27\n"
-".emtcode OP_LIT 0x0C\n"
-".emtcode OP_LIT_SAT 0x2A\n"
-".emtcode OP_MOV 0x11\n"
-".emtcode OP_MOV_SAT 0x30\n"
-".emtcode OP_COS 0x1F\n"
-".emtcode OP_COS_SAT 0x20\n"
-".emtcode OP_EX2 0x07\n"
-".emtcode OP_EX2_SAT 0x25\n"
-".emtcode OP_LG2 0x0B\n"
-".emtcode OP_LG2_SAT 0x29\n"
-".emtcode OP_RCP 0x14\n"
-".emtcode OP_RCP_SAT 0x33\n"
-".emtcode OP_RSQ 0x15\n"
-".emtcode OP_RSQ_SAT 0x34\n"
-".emtcode OP_SIN 0x38\n"
-".emtcode OP_SIN_SAT 0x39\n"
-".emtcode OP_SCS 0x35\n"
-".emtcode OP_SCS_SAT 0x36\n"
-".emtcode OP_POW 0x13\n"
-".emtcode OP_POW_SAT 0x32\n"
-".emtcode OP_ADD 0x01\n"
-".emtcode OP_ADD_SAT 0x1C\n"
-".emtcode OP_DP3 0x03\n"
-".emtcode OP_DP3_SAT 0x21\n"
-".emtcode OP_DP4 0x04\n"
-".emtcode OP_DP4_SAT 0x22\n"
-".emtcode OP_DPH 0x05\n"
-".emtcode OP_DPH_SAT 0x23\n"
-".emtcode OP_DST 0x06\n"
-".emtcode OP_DST_SAT 0x24\n"
-".emtcode OP_MAX 0x0F\n"
-".emtcode OP_MAX_SAT 0x2E\n"
-".emtcode OP_MIN 0x10\n"
-".emtcode OP_MIN_SAT 0x2F\n"
-".emtcode OP_MUL 0x12\n"
-".emtcode OP_MUL_SAT 0x31\n"
-".emtcode OP_SGE 0x16\n"
-".emtcode OP_SGE_SAT 0x37\n"
-".emtcode OP_SLT 0x17\n"
-".emtcode OP_SLT_SAT 0x3A\n"
-".emtcode OP_SUB 0x18\n"
-".emtcode OP_SUB_SAT 0x3B\n"
-".emtcode OP_XPD 0x1A\n"
-".emtcode OP_XPD_SAT 0x43\n"
-".emtcode OP_CMP 0x1D\n"
-".emtcode OP_CMP_SAT 0x1E\n"
-".emtcode OP_LRP 0x2B\n"
-".emtcode OP_LRP_SAT 0x2C\n"
-".emtcode OP_MAD 0x0E\n"
-".emtcode OP_MAD_SAT 0x2D\n"
-".emtcode OP_SWZ 0x19\n"
-".emtcode OP_SWZ_SAT 0x3C\n"
-".emtcode OP_TEX 0x3D\n"
-".emtcode OP_TEX_SAT 0x3E\n"
-".emtcode OP_TXB 0x3F\n"
-".emtcode OP_TXB_SAT 0x40\n"
-".emtcode OP_TXP 0x41\n"
-".emtcode OP_TXP_SAT 0x42\n"
-".emtcode OP_KIL 0x28\n"
-".emtcode OP_ARL 0x02\n"
-".emtcode OP_EXP 0x08\n"
-".emtcode OP_LOG 0x0D\n"
-".emtcode FRAGMENT_ATTRIB_COLOR 0x01\n"
-".emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02\n"
-".emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03\n"
-".emtcode FRAGMENT_ATTRIB_POSITION 0x04\n"
-".emtcode VERTEX_ATTRIB_POSITION 0x01\n"
-".emtcode VERTEX_ATTRIB_WEIGHT 0x02\n"
-".emtcode VERTEX_ATTRIB_NORMAL 0x03\n"
-".emtcode VERTEX_ATTRIB_COLOR 0x04\n"
-".emtcode VERTEX_ATTRIB_FOGCOORD 0x05\n"
-".emtcode VERTEX_ATTRIB_TEXCOORD 0x06\n"
-".emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07\n"
-".emtcode VERTEX_ATTRIB_GENERIC 0x08\n"
-".emtcode FRAGMENT_RESULT_COLOR 0x01\n"
-".emtcode FRAGMENT_RESULT_DEPTH 0x02\n"
-".emtcode VERTEX_RESULT_POSITION 0x01\n"
-".emtcode VERTEX_RESULT_COLOR 0x02\n"
-".emtcode VERTEX_RESULT_FOGCOORD 0x03\n"
-".emtcode VERTEX_RESULT_POINTSIZE 0x04\n"
-".emtcode VERTEX_RESULT_TEXCOORD 0x05\n"
-".emtcode TEXTARGET_1D 0x01\n"
-".emtcode TEXTARGET_2D 0x02\n"
-".emtcode TEXTARGET_3D 0x03\n"
-".emtcode TEXTARGET_RECT 0x04\n"
-".emtcode TEXTARGET_CUBE 0x05\n"
-".emtcode TEXTARGET_SHADOW1D 0x06\n"
-".emtcode TEXTARGET_SHADOW2D 0x07\n"
-".emtcode TEXTARGET_SHADOWRECT 0x08\n"
-".emtcode TEXTARGET_1D_ARRAY 0x09\n"
-".emtcode TEXTARGET_2D_ARRAY 0x0a\n"
-".emtcode TEXTARGET_SHADOW1D_ARRAY 0x0b\n"
-".emtcode TEXTARGET_SHADOW2D_ARRAY 0x0c\n"
-".emtcode FACE_FRONT 0x00\n"
-".emtcode FACE_BACK 0x01\n"
-".emtcode COLOR_PRIMARY 0x00\n"
-".emtcode COLOR_SECONDARY 0x01\n"
-".emtcode COMPONENT_X 0x00\n"
-".emtcode COMPONENT_Y 0x01\n"
-".emtcode COMPONENT_Z 0x02\n"
-".emtcode COMPONENT_W 0x03\n"
-".emtcode COMPONENT_0 0x04\n"
-".emtcode COMPONENT_1 0x05\n"
-".emtcode ARRAY_INDEX_ABSOLUTE 0x00\n"
-".emtcode ARRAY_INDEX_RELATIVE 0x01\n"
-".emtcode MATRIX_MODELVIEW 0x01\n"
-".emtcode MATRIX_PROJECTION 0x02\n"
-".emtcode MATRIX_MVP 0x03\n"
-".emtcode MATRIX_TEXTURE 0x04\n"
-".emtcode MATRIX_PALETTE 0x05\n"
-".emtcode MATRIX_PROGRAM 0x06\n"
-".emtcode MATRIX_MODIFIER_IDENTITY 0x00\n"
-".emtcode MATRIX_MODIFIER_INVERSE 0x01\n"
-".emtcode MATRIX_MODIFIER_TRANSPOSE 0x02\n"
-".emtcode MATRIX_MODIFIER_INVTRANS 0x03\n"
-".emtcode CONSTANT_SCALAR 0x01\n"
-".emtcode CONSTANT_VECTOR 0x02\n"
-".emtcode PROGRAM_PARAM_ENV 0x01\n"
-".emtcode PROGRAM_PARAM_LOCAL 0x02\n"
-".emtcode REGISTER_ATTRIB 0x01\n"
-".emtcode REGISTER_PARAM 0x02\n"
-".emtcode REGISTER_RESULT 0x03\n"
-".emtcode REGISTER_ESTABLISHED_NAME 0x04\n"
-".emtcode PARAM_NULL 0x00\n"
-".emtcode PARAM_ARRAY_ELEMENT 0x01\n"
-".emtcode PARAM_STATE_ELEMENT 0x02\n"
-".emtcode PARAM_PROGRAM_ELEMENT 0x03\n"
-".emtcode PARAM_PROGRAM_ELEMENTS 0x04\n"
-".emtcode PARAM_CONSTANT 0x05\n"
-".emtcode STATE_MATERIAL 0x01\n"
-".emtcode STATE_LIGHT 0x02\n"
-".emtcode STATE_LIGHT_MODEL 0x03\n"
-".emtcode STATE_LIGHT_PROD 0x04\n"
-".emtcode STATE_FOG 0x05\n"
-".emtcode STATE_MATRIX_ROWS 0x06\n"
-".emtcode STATE_TEX_ENV 0x07\n"
-".emtcode STATE_DEPTH 0x08\n"
-".emtcode STATE_TEX_GEN 0x09\n"
-".emtcode STATE_CLIP_PLANE 0x0A\n"
-".emtcode STATE_POINT 0x0B\n"
-".emtcode MATERIAL_AMBIENT 0x01\n"
-".emtcode MATERIAL_DIFFUSE 0x02\n"
-".emtcode MATERIAL_SPECULAR 0x03\n"
-".emtcode MATERIAL_EMISSION 0x04\n"
-".emtcode MATERIAL_SHININESS 0x05\n"
-".emtcode LIGHT_AMBIENT 0x01\n"
-".emtcode LIGHT_DIFFUSE 0x02\n"
-".emtcode LIGHT_SPECULAR 0x03\n"
-".emtcode LIGHT_POSITION 0x04\n"
-".emtcode LIGHT_ATTENUATION 0x05\n"
-".emtcode LIGHT_HALF 0x06\n"
-".emtcode LIGHT_SPOT_DIRECTION 0x07\n"
-".emtcode LIGHT_MODEL_AMBIENT 0x01\n"
-".emtcode LIGHT_MODEL_SCENECOLOR 0x02\n"
-".emtcode LIGHT_PROD_AMBIENT 0x01\n"
-".emtcode LIGHT_PROD_DIFFUSE 0x02\n"
-".emtcode LIGHT_PROD_SPECULAR 0x03\n"
-".emtcode TEX_ENV_COLOR 0x01\n"
-".emtcode TEX_GEN_EYE 0x01\n"
-".emtcode TEX_GEN_OBJECT 0x02\n"
-".emtcode FOG_COLOR 0x01\n"
-".emtcode FOG_PARAMS 0x02\n"
-".emtcode DEPTH_RANGE 0x01\n"
-".emtcode POINT_SIZE 0x01\n"
-".emtcode POINT_ATTENUATION 0x02\n"
-".emtcode ATTRIB 0x01\n"
-".emtcode PARAM 0x02\n"
-".emtcode TEMP 0x03\n"
-".emtcode OUTPUT 0x04\n"
-".emtcode ALIAS 0x05\n"
-".emtcode ADDRESS 0x06\n"
-".errtext UNKNOWN_PROGRAM_SIGNATURE \"1001: '$e_signature$': unknown program signature\"\n"
-".errtext MISSING_END_OR_INVALID_STATEMENT \"1002: '$e_statement$': invalid statement\"\n"
-".errtext CODE_AFTER_END \"1003: '$e_statement$': code after 'END' keyword\"\n"
-".errtext INVALID_PROGRAM_OPTION \"1004: '$e_identifier$': invalid program option\"\n"
-".errtext EXT_SWIZ_COMP_EXPECTED \"1005: extended swizzle component expected but '$e_token$' found\"\n"
-".errtext TEX_TARGET_EXPECTED \"1006: texture target expected but '$e_token$' found\"\n"
-".errtext TEXTURE_EXPECTED \"1007: 'texture' expected but '$e_identifier$' found\"\n"
-".errtext SOURCE_REGISTER_EXPECTED \"1008: source register expected but '$e_token$' found\"\n"
-".errtext DESTINATION_REGISTER_EXPECTED \"1009: destination register expected but '$e_token$' found\"\n"
-".errtext INVALID_ADDRESS_COMPONENT \"1010: '$e_identifier$': invalid address component\"\n"
-".errtext INVALID_ADDRESS_WRITEMASK \"1011: '$e_identifier$': invalid address writemask\"\n"
-".errtext INVALID_COMPONENT \"1012: '$e_charordigit$': invalid component\"\n"
-".errtext INVALID_SUFFIX \"1013: '$e_identifier$': invalid suffix\"\n"
-".errtext INVALID_WRITEMASK \"1014: '$e_identifier$': invalid writemask\"\n"
-".errtext FRAGMENT_EXPECTED \"1015: 'fragment' expected but '$e_identifier$' found\"\n"
-".errtext VERTEX_EXPECTED \"1016: 'vertex' expected but '$e_identifier$' found\"\n"
-".errtext INVALID_FRAGMENT_PROPERTY \"1017: '$e_identifier$': invalid fragment property\"\n"
-".errtext INVALID_VERTEX_PROPERTY \"1018: '$e_identifier$': invalid vertex property\"\n"
-".errtext INVALID_STATE_PROPERTY \"1019: '$e_identifier$': invalid state property\"\n"
-".errtext INVALID_MATERIAL_PROPERTY \"1020: '$e_identifier$': invalid material property\"\n"
-".errtext INVALID_LIGHT_PROPERTY \"1021: '$e_identifier$': invalid light property\"\n"
-".errtext INVALID_SPOT_PROPERTY \"1022: '$e_identifier$': invalid spot property\"\n"
-".errtext INVALID_LIGHTMODEL_PROPERTY \"1023: '$e_identifier$': invalid light model property\"\n"
-".errtext INVALID_LIGHTPROD_PROPERTY \"1024: '$e_identifier$': invalid light product property\"\n"
-".errtext INVALID_TEXENV_PROPERTY \"1025: '$e_identifier$': invalid texture environment property\"\n"
-".errtext INVALID_TEXGEN_PROPERTY \"1026: '$e_identifier$': invalid texture generating property\"\n"
-".errtext INVALID_TEXGEN_COORD \"1027: '$e_identifier$': invalid texture generating coord\"\n"
-".errtext INVALID_FOG_PROPERTY \"1028: '$e_identifier$': invalid fog property\"\n"
-".errtext INVALID_DEPTH_PROPERTY \"1029: '$e_identifier$': invalid depth property\"\n"
-".errtext INVALID_CLIPPLANE_PROPERTY \"1030: '$e_identifier$': invalid clip plane property\"\n"
-".errtext INVALID_POINT_PROPERTY \"1031: '$e_identifier$': invalid point property\"\n"
-".errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED \"1032: matrix row selector or modifier expected but '$e_token$' found\"\n"
-".errtext INVALID_MATRIX_NAME \"1033: '$e_identifier$': invalid matrix name\"\n"
-".errtext INVALID_PROGRAM_PROPERTY \"1034: '$e_identifier$': invalid program property\"\n"
-".errtext RESULT_EXPECTED \"1035: 'result' expected but '$e_token$' found\"\n"
-".errtext INVALID_RESULT_PROPERTY \"1036: '$e_identifier$': invalid result property\"\n"
-".errtext INVALID_FACE_PROPERTY \"1037: '$e_identifier$': invalid face property\"\n"
-".errtext INVALID_COLOR_PROPERTY \"1038: '$e_identifier$': invalid color property\"\n"
-".errtext IDENTIFIER_EXPECTED \"1039: identifier expected but '$e_token$' found\"\n"
-".errtext RESERVED_KEYWORD \"1040: use of reserved keyword as an identifier\"\n"
-".errtext INTEGER_EXPECTED \"1041: integer value expected but '$e_token$' found\"\n"
-".errtext MISSING_SEMICOLON \"1042: ';' expected but '$e_token$' found\"\n"
-".errtext MISSING_COMMA \"1043: ',' expected but '$e_token$' found\"\n"
-".errtext MISSING_LBRACKET \"1044: '[' expected but '$e_token$' found\"\n"
-".errtext MISSING_RBRACKET \"1045: ']' expected but '$e_token$' found\"\n"
-".errtext MISSING_DOT \"1046: '.' expected but '$e_token$' found\"\n"
-".errtext MISSING_EQUAL \"1047: '=' expected but '$e_token$' found\"\n"
-".errtext MISSING_LBRACE \"1048: '{' expected but '$e_token$' found\"\n"
-".errtext MISSING_RBRACE \"1049: '}' expected but '$e_token$' found\"\n"
-".errtext MISSING_DOTDOT \"1050: '..' expected but '$e_token$' found\"\n"
-".errtext MISSING_FRACTION_OR_EXPONENT \"1051: missing fraction part or exponent\"\n"
-".errtext MISSING_DOT_OR_EXPONENT \"1052: missing '.' or exponent\"\n"
-".errtext EXPONENT_VALUE_EXPECTED \"1053: exponent value expected\"\n"
-".errtext INTEGER_OUT_OF_RANGE \"1054: integer value out of range\"\n"
-".errtext OPERATION_NEEDS_DESTINATION_VARIABLE \"1055: operation needs destination variable\"\n"
-".errtext OPERATION_NEEDS_SOURCE_VARIABLE \"1056: operation needs source variable\"\n"
-".errtext ADDRESS_REGISTER_EXPECTED \"1057: address register expected but '$e_token$' found\"\n"
-".errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED \"1058: address register or integer literal expected but '$e_token$' found\"\n"
-".regbyte vertex_blend 0x00\n"
-".regbyte matrix_palette 0x00\n"
-".regbyte point_parameters 0x00\n"
-".regbyte secondary_color 0x00\n"
-".regbyte fog_coord 0x00\n"
-".regbyte texture_rectangle 0x00\n"
-".regbyte fragment_program_shadow 0x00\n"
-".regbyte draw_buffers 0x00\n"
-".regbyte texture_array 0x00\n"
-".regbyte ARB_precision_hint_fastest 0x00\n"
-".regbyte ARB_precision_hint_nicest 0x00\n"
-".regbyte ARB_fog_exp 0x00\n"
-".regbyte ARB_fog_exp2 0x00\n"
-".regbyte ARB_fog_linear 0x00\n"
-".regbyte ARB_position_invariant 0x00\n"
-".regbyte ARB_fragment_program_shadow 0x00\n"
-".regbyte ARB_draw_buffers 0x00\n"
-".regbyte MESA_texture_array 0x00\n"
-".regbyte program_target 0x00\n"
-"program\n"
-" programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;\n"
-"programs\n"
-" .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or\n"
-" .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;\n"
-"frag_program_1_0\n"
-" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and\n"
-" optional_space .and fp_optionSequence .and fp_statementSequence .and\n"
-" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"
-" '\\0' .error CODE_AFTER_END;\n"
-"vert_program_1_0\n"
-" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and\n"
-" optional_space .and vp_optionSequence .and vp_statementSequence .and\n"
-" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"
-" '\\0' .error CODE_AFTER_END;\n"
-"fp_optionSequence\n"
-" .loop fp_option;\n"
-"vp_optionSequence\n"
-" .loop vp_option;\n"
-"fp_option\n"
-" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"
-" fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"
-"vp_option\n"
-" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"
-" vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"
-"fp_optionString\n"
-" .if (ARB_precision_hint_nicest == 0x00) \"ARB_precision_hint_fastest\"\n"
-" .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or\n"
-" .if (ARB_precision_hint_fastest == 0x00) \"ARB_precision_hint_nicest\"\n"
-" .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or\n"
-" fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or\n"
-" fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or\n"
-" fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or\n"
-" .if (fragment_program_shadow != 0x00) \"ARB_fragment_program_shadow\"\n"
-" .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01 .or\n"
-" .if (draw_buffers != 0x00) \"ARB_draw_buffers\" .emit ARB_DRAW_BUFFERS\n"
-" .load ARB_draw_buffers 0x01 .or\n"
-" .if (texture_array != 0x00) \"MESA_texture_array\" .emit MESA_TEXTURE_ARRAY\n"
-" .load MESA_texture_array 0x01;\n"
-"vp_optionString\n"
-" \"ARB_position_invariant\" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;\n"
-"fp_ARB_fog_exp\n"
-" .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp\";\n"
-"fp_ARB_fog_exp2\n"
-" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp2\";\n"
-"fp_ARB_fog_linear\n"
-" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) \"ARB_fog_linear\";\n"
-"fp_statementSequence\n"
-" .loop fp_statement;\n"
-"vp_statementSequence\n"
-" .loop vp_statement;\n"
-"fp_statement\n"
-" fp_statement_1 .or fp_statement_2;\n"
-"vp_statement\n"
-" vp_statement_1 .or vp_statement_2;\n"
-"fp_statement_1\n"
-" fp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"
-"fp_statement_2\n"
-" fp_namingStatement .emit DECLARATION .and semicolon;\n"
-"vp_statement_1\n"
-" vp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"
-"vp_statement_2\n"
-" vp_namingStatement .emit DECLARATION .and semicolon;\n"
-"fp_instruction\n"
-" ALUInstruction .emit OP_ALU_INST .or\n"
-" TexInstruction .emit OP_TEX_INST;\n"
-"vp_instruction\n"
-" ARL_instruction .emit OP_ALU_ARL .or\n"
-" vp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"
-" vp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"
-" vp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"
-" vp_BINop_instruction .emit OP_ALU_BIN .or\n"
-" vp_TRIop_instruction .emit OP_ALU_TRI .or\n"
-" vp_SWZ_instruction .emit OP_ALU_SWZ;\n"
-"ALUInstruction\n"
-" fp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"
-" fp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"
-" fp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"
-" fp_BINop_instruction .emit OP_ALU_BIN .or\n"
-" fp_TRIop_instruction .emit OP_ALU_TRI .or\n"
-" fp_SWZ_instruction .emit OP_ALU_SWZ;\n"
-"TexInstruction\n"
-" SAMPLE_instruction .emit OP_TEX_SAMPLE .or\n"
-" KIL_instruction .emit OP_TEX_KIL;\n"
-"ARL_instruction\n"
-" \"ARL\" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;\n"
-"fp_VECTORop_instruction\n"
-" fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;\n"
-"vp_VECTORop_instruction\n"
-" vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;\n"
-"fp_VECTORop\n"
-" \"ABS\" .emit OP_ABS .or \"ABS_SAT\" .emit OP_ABS_SAT .or\n"
-" \"FLR\" .emit OP_FLR .or \"FLR_SAT\" .emit OP_FLR_SAT .or\n"
-" \"FRC\" .emit OP_FRC .or \"FRC_SAT\" .emit OP_FRC_SAT .or\n"
-" \"LIT\" .emit OP_LIT .or \"LIT_SAT\" .emit OP_LIT_SAT .or\n"
-" \"MOV\" .emit OP_MOV .or \"MOV_SAT\" .emit OP_MOV_SAT;\n"
-"vp_VECTORop\n"
-" \"ABS\" .emit OP_ABS .or\n"
-" \"FLR\" .emit OP_FLR .or\n"
-" \"FRC\" .emit OP_FRC .or\n"
-" \"LIT\" .emit OP_LIT .or\n"
-" \"MOV\" .emit OP_MOV;\n"
-"fp_SCALARop_instruction\n"
-" fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;\n"
-"vp_SCALARop_instruction\n"
-" vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;\n"
-"fp_SCALARop\n"
-" \"COS\" .emit OP_COS .or \"COS_SAT\" .emit OP_COS_SAT .or\n"
-" \"EX2\" .emit OP_EX2 .or \"EX2_SAT\" .emit OP_EX2_SAT .or\n"
-" \"LG2\" .emit OP_LG2 .or \"LG2_SAT\" .emit OP_LG2_SAT .or\n"
-" \"RCP\" .emit OP_RCP .or \"RCP_SAT\" .emit OP_RCP_SAT .or\n"
-" \"RSQ\" .emit OP_RSQ .or \"RSQ_SAT\" .emit OP_RSQ_SAT .or\n"
-" \"SIN\" .emit OP_SIN .or \"SIN_SAT\" .emit OP_SIN_SAT .or\n"
-" \"SCS\" .emit OP_SCS .or \"SCS_SAT\" .emit OP_SCS_SAT;\n"
-"vp_SCALARop\n"
-" \"EX2\" .emit OP_EX2 .or\n"
-" \"EXP\" .emit OP_EXP .or\n"
-" \"LG2\" .emit OP_LG2 .or\n"
-" \"LOG\" .emit OP_LOG .or\n"
-" \"RCP\" .emit OP_RCP .or\n"
-" \"RSQ\" .emit OP_RSQ;\n"
-"fp_BINSCop_instruction\n"
-" fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and\n"
-" fp_scalarSrcReg;\n"
-"vp_BINSCop_instruction\n"
-" vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and\n"
-" vp_scalarSrcReg;\n"
-"fp_BINSCop\n"
-" \"POW\" .emit OP_POW .or \"POW_SAT\" .emit OP_POW_SAT;\n"
-"vp_BINSCop\n"
-" \"POW\" .emit OP_POW;\n"
-"fp_BINop_instruction\n"
-" fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
-" vectorSrcReg;\n"
-"vp_BINop_instruction\n"
-" vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"
-" swizzleSrcReg;\n"
-"fp_BINop\n"
-" \"ADD\" .emit OP_ADD .or \"ADD_SAT\" .emit OP_ADD_SAT .or\n"
-" \"DP3\" .emit OP_DP3 .or \"DP3_SAT\" .emit OP_DP3_SAT .or\n"
-" \"DP4\" .emit OP_DP4 .or \"DP4_SAT\" .emit OP_DP4_SAT .or\n"
-" \"DPH\" .emit OP_DPH .or \"DPH_SAT\" .emit OP_DPH_SAT .or\n"
-" \"DST\" .emit OP_DST .or \"DST_SAT\" .emit OP_DST_SAT .or\n"
-" \"MAX\" .emit OP_MAX .or \"MAX_SAT\" .emit OP_MAX_SAT .or\n"
-" \"MIN\" .emit OP_MIN .or \"MIN_SAT\" .emit OP_MIN_SAT .or\n"
-" \"MUL\" .emit OP_MUL .or \"MUL_SAT\" .emit OP_MUL_SAT .or\n"
-" \"SGE\" .emit OP_SGE .or \"SGE_SAT\" .emit OP_SGE_SAT .or\n"
-" \"SLT\" .emit OP_SLT .or \"SLT_SAT\" .emit OP_SLT_SAT .or\n"
-" \"SUB\" .emit OP_SUB .or \"SUB_SAT\" .emit OP_SUB_SAT .or\n"
-" \"XPD\" .emit OP_XPD .or \"XPD_SAT\" .emit OP_XPD_SAT;\n"
-"vp_BINop\n"
-" \"ADD\" .emit OP_ADD .or\n"
-" \"DP3\" .emit OP_DP3 .or\n"
-" \"DP4\" .emit OP_DP4 .or\n"
-" \"DPH\" .emit OP_DPH .or\n"
-" \"DST\" .emit OP_DST .or\n"
-" \"MAX\" .emit OP_MAX .or\n"
-" \"MIN\" .emit OP_MIN .or\n"
-" \"MUL\" .emit OP_MUL .or\n"
-" \"SGE\" .emit OP_SGE .or\n"
-" \"SLT\" .emit OP_SLT .or\n"
-" \"SUB\" .emit OP_SUB .or\n"
-" \"XPD\" .emit OP_XPD;\n"
-"fp_TRIop_instruction\n"
-" fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
-" vectorSrcReg .and comma .and vectorSrcReg;\n"
-"vp_TRIop_instruction\n"
-" vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"
-" swizzleSrcReg .and comma .and swizzleSrcReg;\n"
-"fp_TRIop\n"
-" \"CMP\" .emit OP_CMP .or \"CMP_SAT\" .emit OP_CMP_SAT .or\n"
-" \"LRP\" .emit OP_LRP .or \"LRP_SAT\" .emit OP_LRP_SAT .or\n"
-" \"MAD\" .emit OP_MAD .or \"MAD_SAT\" .emit OP_MAD_SAT;\n"
-"vp_TRIop\n"
-" \"MAD\" .emit OP_MAD;\n"
-"fp_SWZ_instruction\n"
-" SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and\n"
-" fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"
-"vp_SWZ_instruction\n"
-" \"SWZ\" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and\n"
-" vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"
-"SWZop\n"
-" \"SWZ\" .emit OP_SWZ .or \"SWZ_SAT\" .emit OP_SWZ_SAT;\n"
-"SAMPLE_instruction\n"
-" SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
-" texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;\n"
-"SAMPLEop\n"
-" \"TEX\" .emit OP_TEX .or \"TEX_SAT\" .emit OP_TEX_SAT .or\n"
-" \"TXB\" .emit OP_TXB .or \"TXB_SAT\" .emit OP_TXB_SAT .or\n"
-" \"TXP\" .emit OP_TXP .or \"TXP_SAT\" .emit OP_TXP_SAT;\n"
-"KIL_instruction\n"
-" \"KIL\" .emit OP_KIL .and space_src .and vectorSrcReg;\n"
-"texImageUnit\n"
-" \"texture\" .error TEXTURE_EXPECTED .and optTexImageUnitNum;\n"
-"texTarget\n"
-" \"1D\" .emit TEXTARGET_1D .or\n"
-" \"2D\" .emit TEXTARGET_2D .or\n"
-" \"3D\" .emit TEXTARGET_3D .or\n"
-" .if (texture_rectangle != 0x00) \"RECT\" .emit TEXTARGET_RECT .or\n"
-" \"CUBE\" .emit TEXTARGET_CUBE .or\n"
-" .if (ARB_fragment_program_shadow != 0x00) shadowTarget .or\n"
-" .if (MESA_texture_array != 0x00) arrayTarget;\n"
-"shadowTarget\n"
-" \"SHADOW1D\" .emit TEXTARGET_SHADOW1D .or\n"
-" \"SHADOW2D\" .emit TEXTARGET_SHADOW2D .or\n"
-" .if (texture_rectangle != 0x00) \"SHADOWRECT\" .emit TEXTARGET_SHADOWRECT .or\n"
-" .if (MESA_texture_array != 0x00) shadowArrayTarget;\n"
-"arrayTarget\n"
-" \"ARRAY1D\" .emit TEXTARGET_1D_ARRAY .or\n"
-" \"ARRAY2D\" .emit TEXTARGET_2D_ARRAY;\n"
-"shadowArrayTarget\n"
-" \"SHADOWARRAY1D\" .emit TEXTARGET_SHADOW1D_ARRAY .or\n"
-" \"SHADOWARRAY2D\" .emit TEXTARGET_SHADOW2D_ARRAY;\n"
-"optTexImageUnitNum\n"
-" optTexImageUnitNum_1 .or .true .emit 0x00;\n"
-"optTexImageUnitNum_1\n"
-" lbracket_ne .and texImageUnitNum .and rbracket;\n"
-"texImageUnitNum\n"
-" integer;\n"
-"fp_scalarSrcReg\n"
-" optionalSign .and fp_srcReg .and fp_scalarSuffix;\n"
-"vp_scalarSrcReg\n"
-" optionalSign .and vp_srcReg .and vp_scalarSuffix;\n"
-"swizzleSrcReg\n"
-" optionalSign .and vp_srcReg .and swizzleSuffix;\n"
-"vectorSrcReg\n"
-" optionalSign .and fp_srcReg .and optionalSuffix;\n"
-"fp_maskedDstReg\n"
-" fp_dstReg .and fp_optionalMask;\n"
-"vp_maskedDstReg\n"
-" vp_dstReg .and vp_optionalMask;\n"
-"maskedAddrReg\n"
-" addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;\n"
-"fp_extendedSwizzle\n"
-" rgbaExtendedSwizzle .or xyzwExtendedSwizzle;\n"
-"vp_extendedSwizzle\n"
-" extSwizComp .and comma .and\n"
-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"xyzwExtendedSwizzle\n"
-" xyzwExtSwizComp .and comma .and\n"
-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"rgbaExtendedSwizzle\n"
-" rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or\n"
-" rgbaExtendedSwizzle_4;\n"
-"rgbaExtendedSwizzle_1\n"
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;\n"
-"rgbaExtendedSwizzle_2\n"
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"
-" rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"rgbaExtendedSwizzle_3\n"
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and\n"
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"rgbaExtendedSwizzle_4\n"
-" rgbaExtSwizComp_alpha .and comma .and \n"
-"rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"xyzwExtSwizComp\n"
-" optionalSign .and xyzwExtSwizSel;\n"
-"rgbaExtSwizComp\n"
-" optionalSign .and rgbaExtSwizSel;\n"
-"rgbaExtSwizComp_digit\n"
-" optionalSign .and rgbaExtSwizSel_digit;\n"
-"rgbaExtSwizComp_alpha\n"
-" optionalSign .and rgbaExtSwizSel_alpha;\n"
-"extSwizComp\n"
-" optionalSign .and extSwizSel;\n"
-"xyzwExtSwizSel\n"
-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or xyzwComponent_single;\n"
-"rgbaExtSwizSel\n"
-" rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;\n"
-"rgbaExtSwizSel_digit\n"
-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1;\n"
-"rgbaExtSwizSel_alpha\n"
-" rgbaComponent_single;\n"
-"extSwizSel\n"
-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or vp_component_single;\n"
-"fp_srcReg\n"
-" fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"
-"vp_srcReg\n"
-" vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"
-"fp_srcReg_1\n"
-" fragmentAttribReg .emit REGISTER_ATTRIB .or\n"
-" fp_progParamReg .emit REGISTER_PARAM .or\n"
-" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
-"vp_srcReg_1\n"
-" vertexAttribReg .emit REGISTER_ATTRIB .or\n"
-" vp_progParamReg .emit REGISTER_PARAM .or\n"
-" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
-"fp_dstReg\n"
-" fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"
-"vp_dstReg\n"
-" vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"
-"fp_dstReg_1\n"
-" fragmentResultReg .emit REGISTER_RESULT .or\n"
-" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
-"vp_dstReg_1\n"
-" vertexResultReg .emit REGISTER_RESULT .or\n"
-" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
-"fragmentAttribReg\n"
-" fragAttribBinding;\n"
-"vertexAttribReg\n"
-" vtxAttribBinding;\n"
-"fp_temporaryReg\n"
-" fp_establishedName_no_error_on_identifier;\n"
-"vp_temporaryReg\n"
-" vp_establishedName_no_error_on_identifier;\n"
-"fp_progParamReg\n"
-" fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;\n"
-"vp_progParamReg\n"
-" vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;\n"
-"fp_progParamReg_1\n"
-" fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and\n"
-" rbracket;\n"
-"vp_progParamReg_1\n"
-" vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and\n"
-" rbracket;\n"
-"fp_progParamSingle\n"
-" .false;\n"
-"vp_progParamSingle\n"
-" .false;\n"
-"fp_progParamArray\n"
-" fp_establishedName_no_error_on_identifier;\n"
-"vp_progParamArray\n"
-" vp_establishedName_no_error_on_identifier;\n"
-"progParamArrayMem\n"
-" progParamArrayAbs .or progParamArrayRel;\n"
-"progParamArrayAbs\n"
-" integer_ne .emit ARRAY_INDEX_ABSOLUTE;\n"
-"progParamArrayRel\n"
-" addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and\n"
-" addrComponent .and addrRegRelOffset;\n"
-"addrRegRelOffset\n"
-" addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;\n"
-"addrRegRelOffset_1\n"
-" plus_ne .and addrRegPosOffset;\n"
-"addrRegRelOffset_2\n"
-" minus_ne .and addrRegNegOffset;\n"
-"addrRegPosOffset\n"
-" integer_0_63;\n"
-"addrRegNegOffset\n"
-" integer_0_64;\n"
-"fragmentResultReg\n"
-" fp_resultBinding;\n"
-"vertexResultReg\n"
-" vp_resultBinding;\n"
-"addrReg\n"
-" vp_establishedName_no_error_on_identifier;\n"
-"addrComponent\n"
-" dot .and \"x\" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X\n"
-" .emit COMPONENT_X .emit COMPONENT_X;\n"
-"addrWriteMask\n"
-" dot .and \"x\" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;\n"
-"fp_scalarSuffix\n"
-" dot .and fp_component_single .error INVALID_COMPONENT;\n"
-"vp_scalarSuffix\n"
-" dot .and vp_component_single .error INVALID_COMPONENT;\n"
-"swizzleSuffix\n"
-" swizzleSuffix_1 .or\n"
-" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"
-"swizzleSuffix_1\n"
-" dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;\n"
-"swizzleSuffix_2\n"
-" swizzleSuffix_3 .or swizzleSuffix_4;\n"
-"swizzleSuffix_3\n"
-" vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and\n"
-" vp_component_multi .error INVALID_COMPONENT;\n"
-"swizzleSuffix_4\n"
-" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
-" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
-" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
-" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"
-"optionalSuffix\n"
-" optionalSuffix_1 .or\n"
-" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"
-"optionalSuffix_1\n"
-" dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;\n"
-"optionalSuffix_2\n"
-" optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;\n"
-"optionalSuffix_3\n"
-" xyzwComponent_multi .and xyzwComponent_multi .and\n"
-" xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;\n"
-"optionalSuffix_4\n"
-" rgbaComponent_multi .and rgbaComponent_multi .and\n"
-" rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;\n"
-"optionalSuffix_5\n"
-" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
-" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
-" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
-" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or\n"
-" \"r\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
-" \"g\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
-" \"b\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
-" \"a\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"
-"fp_component_single\n"
-" xyzwComponent_single .or rgbaComponent_single;\n"
-"vp_component_multi\n"
-" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"
-" 'w' .emit COMPONENT_W;\n"
-"vp_component_single\n"
-" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"
-" \"w\" .emit COMPONENT_W;\n"
-"xyzwComponent_multi\n"
-" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"
-" 'w' .emit COMPONENT_W;\n"
-"xyzwComponent_single\n"
-" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"
-" \"w\" .emit COMPONENT_W;\n"
-"rgbaComponent_multi\n"
-" 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or\n"
-" 'a' .emit COMPONENT_W;\n"
-"rgbaComponent_single\n"
-" \"r\" .emit COMPONENT_X .or \"g\" .emit COMPONENT_Y .or \"b\" .emit COMPONENT_Z .or\n"
-" \"a\" .emit COMPONENT_W;\n"
-"fp_optionalMask\n"
-" rgbaMask .or xyzwMask .or .true .emit 0x0F;\n"
-"vp_optionalMask\n"
-" xyzwMask .or .true .emit 0x0F;\n"
-"xyzwMask\n"
-" dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;\n"
-"xyzwMask_1\n"
-" \"xyzw\" .emit 0x0F .or \"xyz\" .emit 0x0E .or \"xyw\" .emit 0x0D .or \"xy\" .emit 0x0C .or\n"
-" \"xzw\" .emit 0x0B .or \"xz\" .emit 0x0A .or \"xw\" .emit 0x09 .or \"x\" .emit 0x08 .or\n"
-" \"yzw\" .emit 0x07 .or \"yz\" .emit 0x06 .or \"yw\" .emit 0x05 .or \"y\" .emit 0x04 .or\n"
-" \"zw\" .emit 0x03 .or \"z\" .emit 0x02 .or \"w\" .emit 0x01;\n"
-"rgbaMask\n"
-" dot_ne .and rgbaMask_1;\n"
-"rgbaMask_1\n"
-" \"rgba\" .emit 0x0F .or \"rgb\" .emit 0x0E .or \"rga\" .emit 0x0D .or \"rg\" .emit 0x0C .or\n"
-" \"rba\" .emit 0x0B .or \"rb\" .emit 0x0A .or \"ra\" .emit 0x09 .or \"r\" .emit 0x08 .or\n"
-" \"gba\" .emit 0x07 .or \"gb\" .emit 0x06 .or \"ga\" .emit 0x05 .or \"g\" .emit 0x04 .or\n"
-" \"ba\" .emit 0x03 .or \"b\" .emit 0x02 .or \"a\" .emit 0x01;\n"
-"fp_namingStatement\n"
-" fp_ATTRIB_statement .emit ATTRIB .or\n"
-" fp_PARAM_statement .emit PARAM .or\n"
-" fp_TEMP_statement .emit TEMP .or\n"
-" fp_OUTPUT_statement .emit OUTPUT .or\n"
-" fp_ALIAS_statement .emit ALIAS;\n"
-"vp_namingStatement\n"
-" vp_ATTRIB_statement .emit ATTRIB .or\n"
-" vp_PARAM_statement .emit PARAM .or\n"
-" vp_TEMP_statement .emit TEMP .or\n"
-" ADDRESS_statement .emit ADDRESS .or\n"
-" vp_OUTPUT_statement .emit OUTPUT .or\n"
-" vp_ALIAS_statement .emit ALIAS;\n"
-"fp_ATTRIB_statement\n"
-" \"ATTRIB\" .and space .and fp_establishName .and equal .and\n"
-" fragAttribBinding .error FRAGMENT_EXPECTED;\n"
-"vp_ATTRIB_statement\n"
-" \"ATTRIB\" .and space .and vp_establishName .and equal .and\n"
-" vtxAttribBinding .error VERTEX_EXPECTED;\n"
-"fragAttribBinding\n"
-" \"fragment\" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;\n"
-"vtxAttribBinding\n"
-" \"vertex\" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;\n"
-"fragAttribItem\n"
-" fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or\n"
-" fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or\n"
-" .if (fog_coord != 0x00) \"fogcoord\" .emit FRAGMENT_ATTRIB_FOGCOORD .or\n"
-" \"position\" .emit FRAGMENT_ATTRIB_POSITION;\n"
-"fragAttribItem_1\n"
-" \"color\" .and optColorType;\n"
-"fragAttribItem_2\n"
-" \"texcoord\" .and optTexCoordNum;\n"
-"vtxAttribItem\n"
-" \"position\" .emit VERTEX_ATTRIB_POSITION .or\n"
-" .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or\n"
-" \"normal\" .emit VERTEX_ATTRIB_NORMAL .or\n"
-" vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or\n"
-" \"fogcoord\" .emit VERTEX_ATTRIB_FOGCOORD .or\n"
-" vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or\n"
-" .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or\n"
-" vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;\n"
-"vtxAttribItem_1\n"
-" \"weight\" .and vtxOptWeightNum;\n"
-"vtxAttribItem_2\n"
-" \"color\" .and optColorType;\n"
-"vtxAttribItem_3\n"
-" \"texcoord\" .and optTexCoordNum;\n"
-"vtxAttribItem_4\n"
-" \"matrixindex\" .and lbracket .and vtxWeightNum .and rbracket;\n"
-"vtxAttribItem_5\n"
-" \"attrib\" .and lbracket .and vtxAttribNum .and rbracket;\n"
-"vtxAttribNum\n"
-" integer;\n"
-"vtxOptWeightNum\n"
-" vtxOptWeightNum_1 .or .true .emit 0x00;\n"
-"vtxOptWeightNum_1\n"
-" lbracket_ne .and vtxWeightNum .and rbracket;\n"
-"vtxWeightNum\n"
-" integer;\n"
-"fp_PARAM_statement\n"
-" fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;\n"
-"vp_PARAM_statement\n"
-" vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;\n"
-"fp_PARAM_singleStmt\n"
-" \"PARAM\" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and\n"
-" .true .emit PARAM_NULL;\n"
-"vp_PARAM_singleStmt\n"
-" \"PARAM\" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and\n"
-" .true .emit PARAM_NULL;\n"
-"fp_PARAM_multipleStmt\n"
-" \"PARAM\" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"
-" fp_paramMultipleInit .and .true .emit PARAM_NULL;\n"
-"vp_PARAM_multipleStmt\n"
-" \"PARAM\" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"
-" vp_paramMultipleInit .and .true .emit PARAM_NULL;\n"
-"optArraySize\n"
-" optional_integer;\n"
-"fp_paramSingleInit\n"
-" equal .and fp_paramSingleItemDecl;\n"
-"vp_paramSingleInit\n"
-" equal .and vp_paramSingleItemDecl;\n"
-"fp_paramMultipleInit\n"
-" equal .and lbrace .and fp_paramMultInitList .and rbrace;\n"
-"vp_paramMultipleInit\n"
-" equal .and lbrace .and vp_paramMultInitList .and rbrace;\n"
-"fp_paramMultInitList\n"
-" fp_paramMultInitList_1 .or fp_paramMultipleItem;\n"
-"vp_paramMultInitList\n"
-" vp_paramMultInitList_1 .or vp_paramMultipleItem;\n"
-"fp_paramMultInitList_1\n"
-" fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;\n"
-"vp_paramMultInitList_1\n"
-" vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;\n"
-"fp_paramSingleItemDecl\n"
-" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstDecl .emit PARAM_CONSTANT;\n"
-"vp_paramSingleItemDecl\n"
-" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstDecl .emit PARAM_CONSTANT;\n"
-"fp_paramSingleItemUse\n"
-" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstUse .emit PARAM_CONSTANT;\n"
-"vp_paramSingleItemUse\n"
-" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstUse .emit PARAM_CONSTANT;\n"
-"fp_paramMultipleItem\n"
-" fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstDecl .emit PARAM_CONSTANT;\n"
-"vp_paramMultipleItem\n"
-" vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstDecl .emit PARAM_CONSTANT;\n"
-"fp_stateMultipleItem\n"
-" stateMultipleItem_1 .or fp_stateSingleItem;\n"
-"vp_stateMultipleItem\n"
-" stateMultipleItem_1 .or vp_stateSingleItem;\n"
-"stateMultipleItem_1\n"
-" \"state\" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;\n"
-"fp_stateSingleItem\n"
-" \"state\" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"
-"vp_stateSingleItem\n"
-" \"state\" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"
-"fp_stateSingleItem_1\n"
-" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"
-" stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;\n"
-"vp_stateSingleItem_1\n"
-" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"
-" stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or\n"
-" stateSingleItem_11;\n"
-"stateSingleItem_1\n"
-" stateMaterialItem .emit STATE_MATERIAL;\n"
-"stateSingleItem_2\n"
-" stateLightItem .emit STATE_LIGHT;\n"
-"stateSingleItem_3\n"
-" stateLightModelItem .emit STATE_LIGHT_MODEL;\n"
-"stateSingleItem_4\n"
-" stateLightProdItem .emit STATE_LIGHT_PROD;\n"
-"stateSingleItem_5\n"
-" stateTexEnvItem .emit STATE_TEX_ENV;\n"
-"stateSingleItem_6\n"
-" stateTexGenItem .emit STATE_TEX_GEN;\n"
-"stateSingleItem_7\n"
-" stateFogItem .emit STATE_FOG;\n"
-"stateSingleItem_8\n"
-" stateDepthItem .emit STATE_DEPTH;\n"
-"stateSingleItem_9\n"
-" stateClipPlaneItem .emit STATE_CLIP_PLANE;\n"
-"stateSingleItem_10\n"
-" statePointItem .emit STATE_POINT;\n"
-"stateSingleItem_11\n"
-" stateMatrixRow .emit STATE_MATRIX_ROWS;\n"
-"stateMaterialItem\n"
-" \"material\" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;\n"
-"stateMatProperty\n"
-" \"ambient\" .emit MATERIAL_AMBIENT .or\n"
-" \"diffuse\" .emit MATERIAL_DIFFUSE .or\n"
-" \"specular\" .emit MATERIAL_SPECULAR .or\n"
-" \"emission\" .emit MATERIAL_EMISSION .or\n"
-" \"shininess\" .emit MATERIAL_SHININESS;\n"
-"stateLightItem\n"
-" \"light\" .and lbracket .and stateLightNumber .and rbracket .and dot .and\n"
-" stateLightProperty .error INVALID_LIGHT_PROPERTY;\n"
-"stateLightProperty\n"
-" \"ambient\" .emit LIGHT_AMBIENT .or\n"
-" \"diffuse\" .emit LIGHT_DIFFUSE .or\n"
-" \"specular\" .emit LIGHT_SPECULAR .or\n"
-" \"position\" .emit LIGHT_POSITION .or\n"
-" \"attenuation\" .emit LIGHT_ATTENUATION .or\n"
-" stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or\n"
-" \"half\" .emit LIGHT_HALF;\n"
-"stateLightProperty_1\n"
-" \"spot\" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;\n"
-"stateSpotProperty\n"
-" \"direction\";\n"
-"stateLightModelItem\n"
-" \"lightmodel\" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;\n"
-"stateLModProperty\n"
-" stateLModProperty_1 .or stateLModProperty_2;\n"
-"stateLModProperty_1\n"
-" dot .and \"ambient\" .emit LIGHT_MODEL_AMBIENT;\n"
-"stateLModProperty_2\n"
-" stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;\n"
-"stateLModProperty_3\n"
-" optFaceType .and dot .and \"scenecolor\";\n"
-"stateLightProdItem\n"
-" \"lightprod\" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and\n"
-" stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;\n"
-"stateLProdProperty\n"
-" \"ambient\" .emit LIGHT_PROD_AMBIENT .or\n"
-" \"diffuse\" .emit LIGHT_PROD_DIFFUSE .or\n"
-" \"specular\" .emit LIGHT_PROD_SPECULAR;\n"
-"stateLightNumber\n"
-" integer;\n"
-"stateTexEnvItem\n"
-" \"texenv\" .and optLegacyTexUnitNum .and dot .and\n"
-" stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;\n"
-"stateTexEnvProperty\n"
-" \"color\" .emit TEX_ENV_COLOR;\n"
-"optLegacyTexUnitNum\n"
-" optLegacyTexUnitNum_1 .or .true .emit 0x00;\n"
-"optLegacyTexUnitNum_1\n"
-" lbracket_ne .and legacyTexUnitNum .and rbracket;\n"
-"legacyTexUnitNum\n"
-" integer;\n"
-"stateTexGenItem\n"
-" \"texgen\" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and\n"
-" dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;\n"
-"stateTexGenType\n"
-" \"eye\" .emit TEX_GEN_EYE .or\n"
-" \"object\" .emit TEX_GEN_OBJECT;\n"
-"stateTexGenCoord\n"
-" \"s\" .emit COMPONENT_X .or\n"
-" \"t\" .emit COMPONENT_Y .or\n"
-" \"r\" .emit COMPONENT_Z .or\n"
-" \"q\" .emit COMPONENT_W;\n"
-"stateFogItem\n"
-" \"fog\" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;\n"
-"stateFogProperty\n"
-" \"color\" .emit FOG_COLOR .or\n"
-" \"params\" .emit FOG_PARAMS;\n"
-"stateDepthItem\n"
-" \"depth\" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;\n"
-"stateDepthProperty\n"
-" \"range\" .emit DEPTH_RANGE;\n"
-"stateClipPlaneItem\n"
-" \"clip\" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and\n"
-" \"plane\" .error INVALID_CLIPPLANE_PROPERTY;\n"
-"stateClipPlaneNum\n"
-" integer;\n"
-"statePointItem\n"
-" \"point\" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;\n"
-"statePointProperty\n"
-" \"size\" .emit POINT_SIZE .or\n"
-" .if (point_parameters != 0x00) \"attenuation\" .emit POINT_ATTENUATION;\n"
-"stateMatrixRow\n"
-" stateMatrixItem .and dot .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and\n"
-" lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;\n"
-"stateMatrixRows\n"
-" stateMatrixItem .and optMatrixRows;\n"
-"optMatrixRows\n"
-" optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;\n"
-"optMatrixRows_1\n"
-" dot_ne .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and\n"
-" stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;\n"
-"stateMatrixItem\n"
-" \"matrix\" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;\n"
-"stateOptMatModifier\n"
-" stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;\n"
-"stateOptMatModifier_1\n"
-" dot_ne .and stateMatModifier;\n"
-"stateMatModifier\n"
-" \"inverse\" .emit MATRIX_MODIFIER_INVERSE .or\n"
-" \"transpose\" .emit MATRIX_MODIFIER_TRANSPOSE .or\n"
-" \"invtrans\" .emit MATRIX_MODIFIER_INVTRANS;\n"
-"stateMatrixRowNum\n"
-" integer_0_3;\n"
-"stateMatrixName\n"
-" stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or\n"
-" \"projection\" .emit MATRIX_PROJECTION .or\n"
-" \"mvp\" .emit MATRIX_MVP .or\n"
-" stateMatrixName_1_2 .emit MATRIX_TEXTURE .or\n"
-" .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or\n"
-" stateMatrixName_1_4 .emit MATRIX_PROGRAM;\n"
-"stateMatrixName_1_1\n"
-" \"modelview\" .and stateOptModMatNum;\n"
-"stateMatrixName_1_2\n"
-" \"texture\" .and optTexCoordNum;\n"
-"stateMatrixName_1_3\n"
-" \"palette\" .and lbracket .and statePaletteMatNum .and rbracket;\n"
-"stateMatrixName_1_4\n"
-" \"program\" .and lbracket .and stateProgramMatNum .and rbracket;\n"
-"stateOptModMatNum\n"
-" .if (vertex_blend != 0x00) stateOptModMatNum_1 .or\n"
-" .true .emit 0x00;\n"
-"stateOptModMatNum_1\n"
-" lbracket_ne .and stateModMatNum .and rbracket;\n"
-"stateModMatNum\n"
-" integer;\n"
-"optTexCoordNum\n"
-" optTexCoordNum_1 .or .true .emit 0x00;\n"
-"optTexCoordNum_1\n"
-" lbracket_ne .and texCoordNum .and rbracket;\n"
-"texCoordNum\n"
-" integer;\n"
-"statePaletteMatNum\n"
-" integer;\n"
-"stateProgramMatNum\n"
-" integer;\n"
-"programSingleItem\n"
-" \"program\" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"
-"programSingleItem_1\n"
-" progEnvParam .or progLocalParam;\n"
-"programMultipleItem\n"
-" \"program\" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"
-"programMultipleItem_1\n"
-" progEnvParams .or progLocalParams;\n"
-"progEnvParams\n"
-" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;\n"
-"progEnvParamNums\n"
-" progEnvParamNums_1 .or progEnvParamNums_2;\n"
-"progEnvParamNums_1\n"
-" progEnvParamNum .and dotdot_ne .and progEnvParamNum;\n"
-"progEnvParamNums_2\n"
-" progEnvParamNum .and .true .emit 0x00;\n"
-"progEnvParam\n"
-" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;\n"
-"progLocalParams\n"
-" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;\n"
-"progLocalParamNums\n"
-" progLocalParamNums_1 .or progLocalParamNums_2;\n"
-"progLocalParamNums_1\n"
-" progLocalParamNum .and dotdot_ne .and progLocalParamNum;\n"
-"progLocalParamNums_2\n"
-" progLocalParamNum .and .true .emit 0x00;\n"
-"progLocalParam\n"
-" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;\n"
-"progEnvParamNum\n"
-" integer;\n"
-"progLocalParamNum\n"
-" integer;\n"
-"paramConstDecl\n"
-" paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"
-"paramConstUse\n"
-" paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"
-"paramConstScalarDecl\n"
-" signedFloatConstant;\n"
-"paramConstScalarUse\n"
-" floatConstant;\n"
-"paramConstVector\n"
-" paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or\n"
-" paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;\n"
-"paramConstVector_1\n"
-" lbrace_ne .and signedFloatConstant .and rbrace;\n"
-"paramConstVector_2\n"
-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"
-"paramConstVector_3\n"
-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"
-" signedFloatConstant .and rbrace;\n"
-"paramConstVector_4\n"
-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"
-" signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"
-"signedFloatConstant\n"
-" optionalSign .and floatConstant;\n"
-"floatConstant\n"
-" float;\n"
-"optionalSign\n"
-" optional_sign_ne;\n"
-"fp_TEMP_statement\n"
-" \"TEMP\" .and space .and fp_varNameList .and .true .emit 0x00;\n"
-"vp_TEMP_statement\n"
-" \"TEMP\" .and space .and vp_varNameList .and .true .emit 0x00;\n"
-"ADDRESS_statement\n"
-" \"ADDRESS\" .and space .and vp_varNameList .and .true .emit 0x00;\n"
-"fp_varNameList\n"
-" fp_varNameList_1 .or fp_establishName;\n"
-"vp_varNameList\n"
-" vp_varNameList_1 .or vp_establishName;\n"
-"fp_varNameList_1\n"
-" fp_establishName .and comma_ne .and fp_varNameList;\n"
-"vp_varNameList_1\n"
-" vp_establishName .and comma_ne .and vp_varNameList;\n"
-"fp_OUTPUT_statement\n"
-" \"OUTPUT\" .and space .and fp_establishName .and equal .and\n"
-" fp_resultBinding .error RESULT_EXPECTED;\n"
-"vp_OUTPUT_statement\n"
-" \"OUTPUT\" .and space .and vp_establishName .and equal .and\n"
-" vp_resultBinding .error RESULT_EXPECTED;\n"
-"fp_resultBinding\n"
-" \"result\" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"
-"vp_resultBinding\n"
-" \"result\" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"
-"fp_resultBinding_1\n"
-" fp_resultBinding_2 .emit FRAGMENT_RESULT_COLOR .or\n"
-" \"depth\" .emit FRAGMENT_RESULT_DEPTH;\n"
-"fp_resultBinding_2\n"
-" \"color\" .and optOutputColorNum;\n"
-"vp_resultBinding_1\n"
-" .if (ARB_position_invariant == 0x00) \"position\" .emit VERTEX_RESULT_POSITION .or\n"
-" resultColBinding .emit VERTEX_RESULT_COLOR .or\n"
-" \"fogcoord\" .emit VERTEX_RESULT_FOGCOORD .or\n"
-" \"pointsize\" .emit VERTEX_RESULT_POINTSIZE .or\n"
-" vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;\n"
-"vp_resultBinding_2\n"
-" \"texcoord\" .and optTexCoordNum;\n"
-"optOutputColorNum\n"
-" .if (ARB_draw_buffers != 0x00) optOutputColorNum_1 .or .true .emit 0x00;\n"
-"optOutputColorNum_1\n"
-" lbracket_ne .and outputColorNum .and rbracket;\n"
-"outputColorNum\n"
-" integer;\n"
-"resultColBinding\n"
-" \"color\" .and optFaceType .and optColorType;\n"
-"optFaceType\n"
-" FaceType .or .true .emit FACE_FRONT;\n"
-"FaceType\n"
-" dot_ne .and FaceProperty;\n"
-"FaceProperty\n"
-" \"front\" .emit FACE_FRONT .or \"back\" .emit FACE_BACK;\n"
-"optColorType\n"
-" ColorType .or .true .emit COLOR_PRIMARY;\n"
-"ColorType\n"
-" dot_ne .and ColorProperty;\n"
-"ColorProperty\n"
-" \"primary\" .emit COLOR_PRIMARY .or\n"
-" .if (secondary_color != 0x00) \"secondary\" .emit COLOR_SECONDARY;\n"
-"fp_ALIAS_statement\n"
-" \"ALIAS\" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;\n"
-"vp_ALIAS_statement\n"
-" \"ALIAS\" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;\n"
-"fp_ALIAS_statement_1\n"
-" space .and fp_establishName;\n"
-"vp_ALIAS_statement_1\n"
-" space .and vp_establishName;\n"
-"fp_establishName\n"
-" fp_identifier;\n"
-"vp_establishName\n"
-" vp_identifier;\n"
-"fp_establishedName\n"
-" fp_identifier;\n"
-"vp_establishedName\n"
-" vp_identifier;\n"
-"fp_establishedName_no_error_on_identifier\n"
-" fp_identifier_ne;\n"
-"vp_establishedName_no_error_on_identifier\n"
-" vp_identifier_ne;\n"
-"fp_identifier\n"
-" fp_identifier_ne .error IDENTIFIER_EXPECTED;\n"
-"vp_identifier\n"
-" vp_identifier_ne .error IDENTIFIER_EXPECTED;\n"
-"fp_identifier_ne\n"
-" fp_not_reserved_identifier .and identifier_ne;\n"
-"vp_identifier_ne\n"
-" vp_not_reserved_identifier .and identifier_ne;\n"
-"fp_not_reserved_identifier\n"
-" fp_not_reserved_identifier_1 .or .true;\n"
-"fp_not_reserved_identifier_1\n"
-" fp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"
-"vp_not_reserved_identifier\n"
-" vp_not_reserved_identifier_1 .or .true;\n"
-"vp_not_reserved_identifier_1\n"
-" vp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"
-"fp_reserved_identifier\n"
-" \"ABS\" .or \"ABS_SAT\" .or \"ADD\" .or \"ADD_SAT\" .or \"ALIAS\" .or \"ATTRIB\" .or \"CMP\" .or \"CMP_SAT\" .or\n"
-" \"COS\" .or \"COS_SAT\" .or \"DP3\" .or \"DP3_SAT\" .or \"DP4\" .or \"DP4_SAT\" .or \"DPH\" .or \"DPH_SAT\" .or\n"
-" \"DST\" .or \"DST_SAT\" .or \"END\" .or \"EX2\" .or \"EX2_SAT\" .or \"FLR\" .or \"FLR_SAT\" .or \"FRC\" .or\n"
-" \"FRC_SAT\" .or \"KIL\" .or \"LG2\" .or \"LG2_SAT\" .or \"LIT\" .or \"LIT_SAT\" .or \"LRP\" .or \"LRP_SAT\" .or\n"
-" \"MAD\" .or \"MAD_SAT\" .or \"MAX\" .or \"MAX_SAT\" .or \"MIN\" .or \"MIN_SAT\" .or \"MOV\" .or \"MOV_SAT\" .or\n"
-" \"MUL\" .or \"MUL_SAT\" .or \"OPTION\" .or \"OUTPUT\" .or \"PARAM\" .or \"POW\" .or \"POW_SAT\" .or \"RCP\" .or\n"
-" \"RCP_SAT\" .or \"RSQ\" .or \"RSQ_SAT\" .or \"SIN\" .or \"SIN_SAT\" .or \"SCS\" .or \"SCS_SAT\" .or \"SGE\" .or\n"
-" \"SGE_SAT\" .or \"SLT\" .or \"SLT_SAT\" .or \"SUB\" .or \"SUB_SAT\" .or \"SWZ\" .or \"SWZ_SAT\" .or \"TEMP\" .or\n"
-" \"TEX\" .or \"TEX_SAT\" .or \"TXB\" .or \"TXB_SAT\" .or \"TXP\" .or \"TXP_SAT\" .or \"XPD\" .or \"XPD_SAT\" .or\n"
-" \"fragment\" .or \"program\" .or \"result\" .or \"state\" .or \"texture\";\n"
-"vp_reserved_identifier\n"
-" \"ABS\" .or \"ADD\" .or \"ADDRESS\" .or \"ALIAS\" .or \"ARL\" .or \"ATTRIB\" .or \"DP3\" .or \"DP4\" .or\n"
-" \"DPH\" .or \"DST\" .or \"END\" .or \"EX2\" .or \"EXP\" .or \"FLR\" .or \"FRC\" .or \"LG2\" .or \"LIT\" .or\n"
-" \"LOG\" .or \"MAD\" .or \"MAX\" .or \"MIN\" .or \"MOV\" .or \"MUL\" .or \"OPTION\" .or \"OUTPUT\" .or\n"
-" \"PARAM\" .or \"POW\" .or \"RCP\" .or \"RSQ\" .or \"SGE\" .or \"SLT\" .or \"SUB\" .or \"SWZ\" .or \"TEMP\" .or\n"
-" \"XPD\" .or \"program\" .or \"result\" .or \"state\" .or \"vertex\";\n"
-"integer\n"
-" integer_ne .error INTEGER_EXPECTED;\n"
-"zero\n"
-" '0';\n"
-"leading_zeroes\n"
-" .loop zero;\n"
-"no_digit\n"
-" no_digit_1 .or .true;\n"
-"no_digit_1\n"
-" digit10 .and .false .error INTEGER_OUT_OF_RANGE;\n"
-"all_zeroes\n"
-" all_zeroes_1 .or no_digit_1;\n"
-"all_zeroes_1\n"
-" '0' .and .loop zero .and no_digit;\n"
-"integer_0_3\n"
-" integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
-"integer_0_3_1\n"
-" integer_0_3_2 .or all_zeroes .emit '0';\n"
-"integer_0_3_2 \n"
-" leading_zeroes .and '1'-'3' .emit * .and no_digit;\n"
-"integer_0_63\n"
-" integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
-"integer_0_63_1\n"
-" integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or\n"
-" all_zeroes .emit '0';\n"
-"integer_0_63_2 \n"
-" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"
-"integer_0_63_3 \n"
-" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"
-"integer_0_63_4 \n"
-" leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;\n"
-"integer_0_63_5 \n"
-" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"
-"integer_0_64\n"
-" integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
-"integer_0_64_1\n"
-" integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or\n"
-" all_zeroes .emit '0';\n"
-"integer_0_64_2 \n"
-" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"
-"integer_0_64_3 \n"
-" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"
-"integer_0_64_4 \n"
-" leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;\n"
-"integer_0_64_5 \n"
-" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"
-"optional_space\n"
-" space .or .true;\n"
-"space_dst\n"
-" space .error OPERATION_NEEDS_DESTINATION_VARIABLE;\n"
-"space_src\n"
-" space .error OPERATION_NEEDS_SOURCE_VARIABLE;\n"
-"space\n"
-" single_space .and .loop single_space;\n"
-"single_space\n"
-" white_char .or comment_block;\n"
-"white_char\n"
-" ' ' .or '\\t' .or '\\n' .or '\\r';\n"
-"comment_block\n"
-" '#' .and .loop comment_char .and optional_new_line;\n"
-"comment_char\n"
-" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
-"optional_new_line\n"
-" '\\n' .or crlf .or .true;\n"
-"crlf\n"
-" '\\r' .and '\\n';\n"
-"semicolon\n"
-" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"
-"comma\n"
-" optional_space .and ',' .error MISSING_COMMA .and optional_space;\n"
-"comma_ne\n"
-" optional_space .and ',' .and optional_space;\n"
-"lbracket\n"
-" optional_space .and '[' .error MISSING_LBRACKET .and optional_space;\n"
-"lbracket_ne\n"
-" optional_space .and '[' .and optional_space;\n"
-"rbracket\n"
-" optional_space .and ']' .error MISSING_RBRACKET .and optional_space;\n"
-"dot\n"
-" optional_space .and '.' .error MISSING_DOT .and optional_space;\n"
-"dot_ne\n"
-" optional_space .and '.' .and optional_space;\n"
-"equal\n"
-" optional_space .and '=' .error MISSING_EQUAL .and optional_space;\n"
-"lbrace\n"
-" optional_space .and '{' .error MISSING_LBRACE .and optional_space;\n"
-"lbrace_ne\n"
-" optional_space .and '{' .and optional_space;\n"
-"rbrace\n"
-" optional_space .and '}' .error MISSING_RBRACE .and optional_space;\n"
-"dotdot\n"
-" optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;\n"
-"dotdot_ne\n"
-" optional_space .and '.' .and '.' .and optional_space;\n"
-"float\n"
-" float_1 .or float_2 .or float_legacy;\n"
-"float_1\n"
-" '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;\n"
-"float_2\n"
-" integer_ne .and float_3;\n"
-"float_3\n"
-" float_4 .or float_5;\n"
-"float_4\n"
-" '.' .and optional_integer .and optional_exponent;\n"
-"float_5\n"
-" exponent .emit 0x00;\n"
-"float_legacy\n"
-" integer_ne .and .true .emit 0x00 .emit 0x00;\n"
-"integer_ne\n"
-" integer_ne_1 .and .true .emit 0x00 .emit $;\n"
-"integer_ne_1\n"
-" digit10 .emit * .and .loop digit10 .emit *;\n"
-"optional_integer\n"
-" integer_ne .or .true .emit 0x00;\n"
-"optional_exponent\n"
-" exponent .or .true .emit 0x00;\n"
-"exponent\n"
-" exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;\n"
-"exponent_1\n"
-" 'e' .or 'E';\n"
-"optional_sign_ne\n"
-" minus_ne .or plus_ne .or .true;\n"
-"plus_ne\n"
-" optional_space .and '+' .and optional_space;\n"
-"minus_ne\n"
-" optional_space .and '-' .emit '-' .and optional_space;\n"
-"identifier_ne\n"
-" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;\n"
-"follow_idchar\n"
-" first_idchar .or digit10;\n"
-"first_idchar\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"
-"digit10\n"
-" '0'-'9';\n"
-".string __string_filter;\n"
-"__string_filter\n"
-" .loop __identifier_char;\n"
-"__identifier_char\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';\n"
-"e_signature\n"
-" e_signature_char .and .loop e_signature_char;\n"
-"e_signature_char\n"
-" '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"
-"e_statement\n"
-" .loop e_statement_not_term;\n"
-"e_statement_not_term\n"
-" '\\x3C'-'\\xFF' .or '\\x0E'-'\\x3A' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
-"e_identifier\n"
-" e_identifier_first .and .loop e_identifier_next;\n"
-"e_identifier_first\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"
-"e_identifier_next\n"
-" e_identifier_first .or '0'-'9';\n"
-"e_token\n"
-" e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or\n"
-" '-' .or ',' .or ';';\n"
-"e_token_number\n"
-" e_token_digit .and .loop e_token_digit;\n"
-"e_token_digit\n"
-" '0'-'9';\n"
-"e_charordigit\n"
-" 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"
-""
diff --git a/src/mesa/shader/atifragshader.h b/src/mesa/shader/atifragshader.h
index 32fb3a8019..e1dc20e606 100644
--- a/src/mesa/shader/atifragshader.h
+++ b/src/mesa/shader/atifragshader.h
@@ -8,6 +8,8 @@
#ifndef ATIFRAGSHADER_H
#define ATIFRAGSHADER_H
+#include "main/mtypes.h"
+
#define MAX_NUM_INSTRUCTIONS_PER_PASS_ATI 8
#define MAX_NUM_PASSES_ATI 2
#define MAX_NUM_FRAGMENT_REGISTERS_ATI 6
diff --git a/src/mesa/shader/grammar/descrip.mms b/src/mesa/shader/grammar/descrip.mms
deleted file mode 100644
index 6976b70d6a..0000000000
--- a/src/mesa/shader/grammar/descrip.mms
+++ /dev/null
@@ -1,42 +0,0 @@
-# Makefile for core library for VMS
-# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
-# Last revision : 29 September 2008
-
-.first
- define gl [----.include.gl]
- define math [--.math]
- define swrast [--.swrast]
- define array_cache [--.array_cache]
- define main [--.main]
-
-.include [----]mms-config.
-
-##### MACROS #####
-
-VPATH = RCS
-
-INCDIR = [----.include],[],[--.main],[--.glapi],[-.slang]
-LIBDIR = [----.lib]
-CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
-
-SOURCES = grammar_mesa.c
-
-OBJECTS = grammar_mesa.obj
-
-##### RULES #####
-
-VERSION=Mesa V3.4
-
-##### TARGETS #####
-all :
- $(MMS)$(MMSQUALIFIERS) $(LIBDIR)$(GL_LIB)
-
-# Make the library
-$(LIBDIR)$(GL_LIB) : $(OBJECTS)
- @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
-
-clean :
- purge
- delete *.obj;*
-
-grammar_mesa.obj : grammar_mesa.c grammar.c
diff --git a/src/mesa/shader/hash_table.c b/src/mesa/shader/hash_table.c
new file mode 100644
index 0000000000..881179f9d8
--- /dev/null
+++ b/src/mesa/shader/hash_table.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2008 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 hash_table.c
+ * \brief Implementation of a generic, opaque hash table data type.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include <assert.h>
+
+#include "main/imports.h"
+#include "main/simple_list.h"
+#include "hash_table.h"
+
+struct node {
+ struct node *next;
+ struct node *prev;
+};
+
+struct hash_table {
+ hash_func_t hash;
+ hash_compare_func_t compare;
+
+ unsigned num_buckets;
+ struct node buckets[1];
+};
+
+
+struct hash_node {
+ struct node link;
+ const void *key;
+ void *data;
+};
+
+
+struct hash_table *
+hash_table_ctor(unsigned num_buckets, hash_func_t hash,
+ hash_compare_func_t compare)
+{
+ struct hash_table *ht;
+ unsigned i;
+
+
+ if (num_buckets < 16) {
+ num_buckets = 16;
+ }
+
+ ht = _mesa_malloc(sizeof(*ht) + ((num_buckets - 1)
+ * sizeof(ht->buckets[0])));
+ if (ht != NULL) {
+ ht->hash = hash;
+ ht->compare = compare;
+ ht->num_buckets = num_buckets;
+
+ for (i = 0; i < num_buckets; i++) {
+ make_empty_list(& ht->buckets[i]);
+ }
+ }
+
+ return ht;
+}
+
+
+void
+hash_table_dtor(struct hash_table *ht)
+{
+ hash_table_clear(ht);
+ _mesa_free(ht);
+}
+
+
+void
+hash_table_clear(struct hash_table *ht)
+{
+ struct node *node;
+ struct node *temp;
+ unsigned i;
+
+
+ for (i = 0; i < ht->num_buckets; i++) {
+ foreach_s(node, temp, & ht->buckets[i]) {
+ remove_from_list(node);
+ _mesa_free(node);
+ }
+
+ assert(is_empty_list(& ht->buckets[i]));
+ }
+}
+
+
+void *
+hash_table_find(struct hash_table *ht, const void *key)
+{
+ const unsigned hash_value = (*ht->hash)(key);
+ const unsigned bucket = hash_value % ht->num_buckets;
+ struct node *node;
+
+ foreach(node, & ht->buckets[bucket]) {
+ struct hash_node *hn = (struct hash_node *) node;
+
+ if ((*ht->compare)(hn->key, key) == 0) {
+ return hn->data;
+ }
+ }
+
+ return NULL;
+}
+
+
+void
+hash_table_insert(struct hash_table *ht, void *data, const void *key)
+{
+ const unsigned hash_value = (*ht->hash)(key);
+ const unsigned bucket = hash_value % ht->num_buckets;
+ struct hash_node *node;
+
+ node = _mesa_calloc(sizeof(*node));
+
+ node->data = data;
+ node->key = key;
+
+ insert_at_head(& ht->buckets[bucket], & node->link);
+}
+
+
+unsigned
+hash_table_string_hash(const void *key)
+{
+ const char *str = (const char *) key;
+ unsigned hash = 5381;
+
+
+ while (*str != '\0') {
+ hash = (hash * 33) + *str;
+ str++;
+ }
+
+ return hash;
+}
diff --git a/src/mesa/shader/hash_table.h b/src/mesa/shader/hash_table.h
new file mode 100644
index 0000000000..7b302f5dbe
--- /dev/null
+++ b/src/mesa/shader/hash_table.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2008 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 hash_table.h
+ * \brief Implementation of a generic, opaque hash table data type.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#ifndef HASH_TABLE_H
+#define HASH_TABLE_H
+
+#include <string.h>
+
+struct hash_table;
+
+typedef unsigned (*hash_func_t)(const void *key);
+typedef int (*hash_compare_func_t)(const void *key1, const void *key2);
+
+/**
+ * Hash table constructor
+ *
+ * Creates a hash table with the specified number of buckets. The supplied
+ * \c hash and \c compare routines are used when adding elements to the table
+ * and when searching for elements in the table.
+ *
+ * \param num_buckets Number of buckets (bins) in the hash table.
+ * \param hash Function used to compute hash value of input keys.
+ * \param compare Function used to compare keys.
+ */
+extern struct hash_table *hash_table_ctor(unsigned num_buckets,
+ hash_func_t hash, hash_compare_func_t compare);
+
+
+/**
+ * Release all memory associated with a hash table
+ *
+ * \warning
+ * This function cannot release memory occupied either by keys or data.
+ */
+extern void hash_table_dtor(struct hash_table *ht);
+
+
+/**
+ * Flush all entries from a hash table
+ *
+ * \param ht Table to be cleared of its entries.
+ */
+extern void hash_table_clear(struct hash_table *ht);
+
+
+/**
+ * Search a hash table for a specific element
+ *
+ * \param ht Table to be searched
+ * \param key Key of the desired element
+ *
+ * \return
+ * The \c data value supplied to \c hash_table_insert when the element with
+ * the matching key was added. If no matching key exists in the table,
+ * \c NULL is returned.
+ */
+extern void *hash_table_find(struct hash_table *ht, const void *key);
+
+
+/**
+ * Add an element to a hash table
+ */
+extern void hash_table_insert(struct hash_table *ht, void *data,
+ const void *key);
+
+
+/**
+ * Compute hash value of a string
+ *
+ * Computes the hash value of a string using the DJB2 algorithm developed by
+ * Professor Daniel J. Bernstein. It was published on comp.lang.c once upon
+ * a time. I was unable to find the original posting in the archives.
+ *
+ * \param key Pointer to a NUL terminated string to be hashed.
+ *
+ * \sa hash_table_string_compare
+ */
+extern unsigned hash_table_string_hash(const void *key);
+
+
+/**
+ * Compare two strings used as keys
+ *
+ * This is just a macro wrapper around \c strcmp.
+ *
+ * \sa hash_table_string_hash
+ */
+#define hash_table_string_compare ((hash_compare_func_t) strcmp)
+
+#endif /* HASH_TABLE_H */
diff --git a/src/mesa/shader/lex.yy.c b/src/mesa/shader/lex.yy.c
new file mode 100644
index 0000000000..283ba8d26e
--- /dev/null
+++ b/src/mesa/shader/lex.yy.c
@@ -0,0 +1,3578 @@
+
+#line 3 "lex.yy.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+static void yyensure_buffer_stack (yyscan_t yyscanner );
+static void yy_load_buffer_state (yyscan_t yyscanner );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 183
+#define YY_END_OF_BUFFER 184
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[675] =
+ { 0,
+ 0, 0, 184, 182, 180, 179, 182, 182, 152, 178,
+ 154, 154, 154, 154, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 180, 0, 0, 181, 152, 0,
+ 153, 155, 175, 175, 0, 0, 0, 0, 175, 0,
+ 0, 0, 0, 0, 0, 0, 132, 176, 133, 134,
+ 166, 166, 166, 166, 0, 154, 0, 140, 141, 142,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 174, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 173, 173, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 172, 172, 172, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 163, 163, 163, 164, 164, 165, 156,
+ 155, 156, 0, 157, 11, 13, 152, 15, 152, 152,
+ 16, 18, 152, 20, 22, 24, 26, 6, 28, 30,
+ 31, 33, 35, 38, 36, 40, 41, 43, 45, 47,
+
+ 49, 51, 152, 152, 152, 53, 55, 152, 57, 59,
+ 61, 152, 63, 65, 67, 69, 152, 71, 73, 75,
+ 77, 152, 152, 152, 152, 152, 152, 0, 0, 0,
+ 0, 155, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 93, 94, 96, 0, 171, 0, 0, 0,
+ 0, 0, 0, 110, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 170, 169, 169, 122, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 160, 160,
+ 161, 162, 0, 158, 152, 152, 152, 152, 152, 152,
+ 152, 152, 143, 152, 152, 152, 152, 152, 152, 152,
+
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 144, 152, 152, 152, 152, 152, 152,
+ 152, 152, 10, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 0, 177, 0, 0, 0, 86, 87,
+ 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 168, 0, 0, 0,
+ 126, 0, 128, 0, 0, 0, 0, 0, 0, 167,
+ 159, 152, 152, 152, 4, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+
+ 152, 152, 152, 152, 152, 152, 9, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 82, 152, 152, 0, 0, 0,
+ 0, 0, 88, 89, 0, 0, 0, 0, 97, 0,
+ 0, 101, 104, 0, 0, 0, 0, 0, 0, 0,
+ 115, 116, 0, 0, 0, 0, 121, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 152, 152, 152,
+ 152, 152, 152, 5, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 7, 8, 152, 152, 152, 152, 152, 152, 152,
+
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 83,
+ 152, 79, 0, 0, 0, 0, 137, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 107, 0, 111, 112,
+ 0, 114, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 130, 131, 0, 0, 138, 12, 3, 14,
+ 148, 149, 152, 17, 19, 21, 23, 25, 27, 29,
+ 32, 34, 39, 37, 42, 44, 46, 48, 50, 52,
+ 54, 56, 58, 60, 62, 152, 152, 152, 64, 66,
+ 68, 70, 72, 74, 76, 78, 152, 81, 139, 0,
+ 0, 84, 0, 90, 0, 0, 0, 99, 0, 0,
+
+ 0, 0, 0, 0, 113, 0, 0, 119, 106, 0,
+ 0, 0, 0, 0, 0, 135, 0, 152, 145, 146,
+ 152, 80, 0, 0, 0, 0, 92, 95, 100, 0,
+ 0, 105, 0, 0, 0, 118, 0, 0, 0, 0,
+ 127, 129, 0, 152, 152, 2, 1, 0, 91, 0,
+ 103, 0, 109, 117, 0, 0, 124, 125, 136, 152,
+ 147, 0, 102, 0, 120, 123, 152, 85, 108, 152,
+ 152, 150, 151, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 5, 1, 6, 7, 1, 1, 1, 1,
+ 1, 1, 8, 1, 8, 9, 1, 10, 11, 12,
+ 13, 14, 15, 15, 15, 15, 15, 1, 1, 1,
+ 1, 1, 1, 1, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 7, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 1, 1, 1, 1, 41, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[68] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 2, 1, 3, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2
+ } ;
+
+static yyconst flex_int16_t yy_base[678] =
+ { 0,
+ 0, 0, 954, 955, 66, 955, 948, 949, 0, 69,
+ 85, 128, 140, 152, 151, 58, 39, 48, 75, 927,
+ 158, 160, 73, 59, 71, 170, 54, 920, 890, 889,
+ 901, 885, 899, 898, 142, 927, 939, 955, 0, 206,
+ 955, 189, 168, 171, 53, 27, 66, 119, 175, 899,
+ 885, 123, 170, 883, 895, 183, 955, 198, 225, 99,
+ 212, 219, 223, 227, 285, 297, 308, 955, 955, 955,
+ 904, 917, 911, 165, 900, 903, 899, 914, 224, 896,
+ 910, 194, 896, 909, 900, 913, 890, 901, 892, 294,
+ 893, 884, 893, 884, 883, 884, 878, 884, 895, 881,
+
+ 878, 890, 893, 880, 873, 889, 865, 193, 139, 885,
+ 861, 846, 841, 858, 834, 839, 865, 167, 854, 259,
+ 849, 325, 282, 851, 832, 302, 842, 838, 833, 43,
+ 839, 825, 841, 838, 829, 305, 309, 831, 820, 834,
+ 837, 819, 834, 821, 818, 825, 275, 833, 254, 299,
+ 317, 327, 331, 810, 827, 828, 821, 803, 310, 804,
+ 826, 817, 316, 327, 331, 335, 339, 343, 347, 955,
+ 405, 416, 422, 428, 825, 240, 849, 0, 848, 831,
+ 821, 820, 840, 818, 817, 816, 815, 0, 814, 0,
+ 813, 812, 0, 811, 810, 0, 809, 808, 807, 806,
+
+ 805, 804, 820, 813, 826, 800, 799, 805, 797, 796,
+ 795, 816, 793, 792, 791, 790, 800, 788, 787, 786,
+ 785, 777, 776, 761, 761, 760, 759, 802, 774, 762,
+ 434, 442, 416, 766, 186, 763, 757, 757, 751, 764,
+ 764, 749, 955, 955, 764, 752, 418, 759, 281, 756,
+ 762, 308, 757, 955, 748, 755, 754, 757, 743, 742,
+ 746, 741, 278, 746, 420, 428, 430, 955, 738, 736,
+ 736, 744, 745, 727, 421, 732, 738, 419, 426, 430,
+ 434, 438, 496, 502, 752, 764, 750, 749, 742, 756,
+ 746, 745, 0, 744, 743, 742, 741, 740, 739, 738,
+
+ 737, 736, 735, 734, 733, 732, 731, 730, 733, 726,
+ 733, 726, 725, 0, 724, 723, 722, 725, 720, 719,
+ 718, 717, 0, 716, 715, 714, 713, 691, 685, 690,
+ 696, 679, 694, 315, 955, 693, 683, 687, 955, 955,
+ 677, 686, 672, 689, 672, 675, 669, 955, 670, 669,
+ 666, 673, 666, 674, 670, 680, 677, 659, 665, 672,
+ 656, 655, 673, 655, 667, 666, 955, 665, 655, 659,
+ 955, 646, 955, 651, 651, 659, 642, 643, 653, 955,
+ 955, 685, 667, 683, 0, 507, 681, 681, 680, 679,
+ 678, 677, 676, 675, 674, 673, 672, 671, 670, 669,
+
+ 668, 667, 666, 665, 652, 645, 0, 662, 661, 660,
+ 659, 658, 636, 656, 655, 654, 653, 652, 651, 650,
+ 649, 618, 621, 601, 0, 602, 595, 602, 601, 602,
+ 594, 612, 955, 955, 594, 592, 602, 595, 955, 590,
+ 607, 330, 955, 598, 582, 583, 592, 583, 582, 582,
+ 955, 581, 590, 580, 596, 593, 955, 592, 590, 579,
+ 580, 576, 568, 575, 570, 571, 566, 592, 592, 590,
+ 604, 603, 598, 0, 586, 585, 584, 583, 582, 581,
+ 580, 579, 578, 577, 576, 575, 574, 573, 572, 571,
+ 570, 0, 0, 569, 568, 567, 566, 565, 509, 564,
+
+ 563, 562, 561, 560, 559, 558, 557, 535, 535, 0,
+ 542, 0, 576, 575, 524, 542, 955, 537, 532, 525,
+ 521, 533, 523, 521, 517, 533, 524, 523, 955, 955,
+ 526, 955, 521, 514, 503, 514, 506, 510, 523, 518,
+ 521, 503, 955, 955, 515, 504, 955, 0, 0, 0,
+ 0, 0, 543, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 539, 538, 536, 0, 0,
+ 0, 0, 0, 0, 0, 0, 494, 0, 0, 545,
+ 544, 955, 491, 955, 495, 495, 504, 955, 488, 502,
+
+ 483, 485, 482, 490, 955, 468, 479, 955, 955, 483,
+ 479, 472, 470, 470, 483, 955, 467, 507, 0, 0,
+ 507, 0, 514, 513, 472, 433, 955, 955, 955, 435,
+ 435, 955, 429, 386, 377, 955, 366, 365, 323, 328,
+ 955, 955, 339, 348, 337, 955, 955, 307, 955, 305,
+ 955, 257, 955, 955, 247, 221, 955, 955, 955, 236,
+ 0, 213, 955, 150, 955, 955, 232, 955, 955, 162,
+ 138, 0, 0, 955, 541, 108, 544
+ } ;
+
+static yyconst flex_int16_t yy_def[678] =
+ { 0,
+ 674, 1, 674, 674, 674, 674, 674, 675, 676, 674,
+ 674, 674, 674, 674, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 674, 674, 675, 674, 676, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 677, 674, 674, 674, 674, 674,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 676, 676, 676,
+ 676, 676, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 676, 676, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 676,
+ 676, 674, 674, 674, 674, 674, 676, 674, 674, 676,
+ 676, 676, 676, 0, 674, 674, 674
+ } ;
+
+static yyconst flex_int16_t yy_nxt[1023] =
+ { 0,
+ 4, 5, 6, 5, 7, 8, 9, 4, 10, 11,
+ 12, 13, 14, 11, 11, 15, 9, 16, 17, 18,
+ 19, 9, 9, 9, 20, 21, 22, 9, 23, 24,
+ 9, 25, 26, 27, 9, 9, 9, 28, 9, 9,
+ 9, 9, 9, 9, 9, 9, 29, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 30, 9, 31, 32,
+ 33, 9, 34, 9, 9, 9, 9, 35, 79, 35,
+ 40, 80, 129, 108, 96, 81, 130, 41, 42, 42,
+ 42, 42, 42, 42, 76, 82, 77, 97, 98, 240,
+ 99, 109, 78, 65, 66, 66, 66, 66, 66, 66,
+
+ 83, 241, 94, 100, 67, 127, 84, 95, 128, 39,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 131,
+ 132, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 67, 133, 61, 62, 63, 64, 65, 66, 66, 66,
+ 66, 66, 66, 35, 160, 35, 68, 67, 65, 66,
+ 66, 66, 66, 66, 66, 219, 673, 161, 69, 67,
+ 65, 66, 66, 66, 66, 66, 66, 71, 220, 72,
+ 70, 67, 140, 67, 134, 90, 73, 135, 141, 86,
+ 672, 87, 74, 91, 75, 67, 88, 101, 92, 89,
+ 178, 102, 103, 104, 93, 105, 179, 67, 42, 42,
+
+ 42, 42, 42, 42, 106, 189, 107, 40, 122, 123,
+ 123, 142, 126, 123, 669, 123, 136, 137, 123, 217,
+ 124, 124, 123, 190, 147, 143, 123, 125, 125, 123,
+ 218, 337, 144, 123, 122, 148, 184, 185, 149, 151,
+ 152, 150, 670, 671, 338, 153, 186, 118, 119, 45,
+ 46, 47, 48, 154, 50, 51, 123, 162, 52, 53,
+ 54, 55, 56, 57, 120, 59, 60, 668, 155, 121,
+ 156, 286, 667, 157, 158, 163, 163, 163, 163, 666,
+ 287, 159, 164, 163, 165, 166, 167, 163, 163, 168,
+ 169, 163, 163, 163, 171, 171, 171, 171, 171, 171,
+
+ 230, 665, 664, 260, 172, 65, 66, 66, 66, 66,
+ 66, 66, 198, 261, 154, 173, 67, 174, 174, 174,
+ 174, 174, 174, 233, 233, 364, 349, 257, 365, 233,
+ 172, 199, 231, 258, 232, 232, 232, 232, 232, 232,
+ 233, 350, 67, 233, 233, 236, 233, 233, 262, 233,
+ 247, 233, 233, 353, 263, 273, 233, 663, 233, 233,
+ 233, 428, 662, 233, 233, 274, 354, 233, 265, 233,
+ 661, 264, 266, 267, 233, 233, 660, 429, 233, 278,
+ 278, 278, 278, 524, 659, 233, 525, 658, 657, 233,
+ 278, 278, 278, 278, 279, 278, 278, 280, 281, 278,
+
+ 278, 278, 278, 278, 278, 278, 282, 278, 278, 278,
+ 278, 278, 278, 278, 42, 42, 42, 42, 42, 42,
+ 656, 655, 654, 283, 122, 284, 284, 284, 284, 284,
+ 284, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 232, 232, 232, 232, 232, 232, 653,
+ 122, 232, 232, 232, 232, 232, 232, 335, 335, 335,
+ 335, 335, 335, 335, 374, 335, 375, 335, 376, 335,
+ 335, 367, 335, 652, 335, 335, 335, 335, 335, 651,
+ 650, 377, 380, 380, 380, 380, 335, 649, 335, 380,
+ 380, 380, 380, 381, 380, 380, 380, 380, 380, 380,
+
+ 380, 380, 380, 380, 380, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 471, 472, 576,
+ 577, 648, 647, 646, 645, 644, 643, 642, 641, 640,
+ 639, 638, 637, 636, 635, 634, 633, 632, 631, 473,
+ 578, 37, 37, 37, 170, 170, 630, 629, 628, 627,
+ 626, 625, 624, 623, 622, 621, 620, 619, 618, 617,
+ 616, 615, 614, 613, 612, 611, 610, 609, 608, 607,
+ 606, 605, 604, 603, 602, 601, 600, 599, 598, 597,
+ 596, 595, 594, 593, 592, 591, 590, 589, 588, 587,
+ 586, 585, 584, 583, 582, 581, 580, 579, 575, 574,
+
+ 573, 572, 571, 570, 569, 568, 567, 566, 565, 564,
+ 563, 562, 561, 560, 559, 558, 557, 556, 555, 554,
+ 553, 552, 551, 550, 549, 548, 547, 546, 545, 544,
+ 543, 542, 541, 540, 539, 538, 537, 536, 535, 534,
+ 533, 532, 531, 530, 529, 528, 527, 526, 523, 522,
+ 521, 520, 519, 518, 517, 516, 515, 514, 513, 512,
+ 511, 510, 509, 508, 507, 506, 505, 504, 503, 502,
+ 501, 500, 499, 498, 497, 496, 495, 494, 493, 492,
+ 491, 490, 489, 488, 487, 486, 485, 484, 483, 482,
+ 481, 480, 479, 478, 477, 476, 475, 474, 470, 469,
+
+ 468, 467, 466, 465, 464, 463, 462, 461, 460, 459,
+ 458, 457, 456, 455, 454, 453, 452, 451, 450, 449,
+ 448, 447, 446, 445, 444, 443, 442, 441, 440, 439,
+ 438, 437, 436, 435, 434, 433, 432, 431, 430, 427,
+ 426, 425, 424, 423, 422, 421, 420, 419, 418, 417,
+ 416, 415, 414, 413, 412, 411, 410, 409, 408, 407,
+ 406, 405, 404, 403, 402, 401, 400, 399, 398, 397,
+ 396, 395, 394, 393, 392, 391, 390, 389, 388, 387,
+ 386, 385, 384, 383, 382, 379, 378, 373, 372, 371,
+ 370, 369, 368, 366, 363, 362, 361, 360, 359, 358,
+
+ 357, 356, 355, 352, 351, 348, 347, 346, 345, 344,
+ 343, 342, 341, 340, 339, 336, 264, 236, 334, 333,
+ 332, 331, 330, 329, 328, 327, 326, 325, 324, 323,
+ 322, 321, 320, 319, 318, 317, 316, 315, 314, 313,
+ 312, 311, 310, 309, 308, 307, 306, 305, 304, 303,
+ 302, 301, 300, 299, 298, 297, 296, 295, 294, 293,
+ 292, 291, 290, 289, 288, 285, 277, 276, 275, 272,
+ 271, 270, 269, 268, 259, 256, 255, 254, 253, 252,
+ 251, 250, 249, 248, 246, 245, 244, 243, 242, 239,
+ 238, 237, 235, 234, 162, 229, 228, 227, 226, 225,
+
+ 224, 223, 222, 221, 216, 215, 214, 213, 212, 211,
+ 210, 209, 208, 207, 206, 205, 204, 203, 202, 201,
+ 200, 197, 196, 195, 194, 193, 192, 191, 188, 187,
+ 183, 182, 181, 180, 177, 176, 175, 146, 145, 139,
+ 138, 38, 117, 116, 115, 114, 113, 112, 111, 110,
+ 85, 38, 36, 674, 3, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674
+ } ;
+
+static yyconst flex_int16_t yy_chk[1023] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 5, 17, 5,
+ 10, 17, 46, 27, 24, 18, 46, 10, 10, 10,
+ 10, 10, 10, 10, 16, 18, 16, 24, 25, 130,
+ 25, 27, 16, 11, 11, 11, 11, 11, 11, 11,
+
+ 19, 130, 23, 25, 11, 45, 19, 23, 45, 676,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 47,
+ 47, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 47, 10, 10, 10, 10, 12, 12, 12, 12,
+ 12, 12, 12, 35, 60, 35, 12, 12, 13, 13,
+ 13, 13, 13, 13, 13, 109, 671, 60, 13, 13,
+ 14, 14, 14, 14, 14, 14, 14, 15, 109, 15,
+ 14, 14, 52, 12, 48, 22, 15, 48, 52, 21,
+ 670, 21, 15, 22, 15, 13, 21, 26, 22, 21,
+ 74, 26, 26, 26, 22, 26, 74, 14, 42, 42,
+
+ 42, 42, 42, 42, 26, 82, 26, 40, 42, 43,
+ 43, 53, 44, 44, 664, 43, 49, 49, 44, 108,
+ 118, 43, 49, 82, 56, 53, 43, 118, 43, 44,
+ 108, 235, 53, 49, 42, 56, 79, 79, 56, 58,
+ 58, 56, 667, 667, 235, 58, 79, 40, 40, 40,
+ 40, 40, 40, 58, 40, 40, 58, 61, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 662, 59, 40,
+ 59, 176, 660, 59, 59, 61, 61, 61, 61, 656,
+ 176, 59, 62, 62, 62, 62, 63, 63, 63, 63,
+ 64, 64, 64, 64, 65, 65, 65, 65, 65, 65,
+
+ 120, 655, 652, 149, 65, 66, 66, 66, 66, 66,
+ 66, 66, 90, 149, 120, 67, 66, 67, 67, 67,
+ 67, 67, 67, 123, 123, 263, 249, 147, 263, 123,
+ 65, 90, 122, 147, 122, 122, 122, 122, 122, 122,
+ 123, 249, 66, 126, 126, 126, 136, 136, 150, 126,
+ 137, 137, 136, 252, 150, 159, 137, 650, 151, 151,
+ 126, 334, 648, 136, 151, 159, 252, 137, 152, 152,
+ 645, 151, 153, 153, 152, 151, 644, 334, 153, 163,
+ 163, 163, 163, 442, 643, 152, 442, 640, 639, 153,
+ 164, 164, 164, 164, 165, 165, 165, 165, 166, 166,
+
+ 166, 166, 167, 167, 167, 167, 168, 168, 168, 168,
+ 169, 169, 169, 169, 171, 171, 171, 171, 171, 171,
+ 638, 637, 635, 172, 171, 172, 172, 172, 172, 172,
+ 172, 173, 173, 173, 173, 173, 173, 174, 174, 174,
+ 174, 174, 174, 231, 231, 231, 231, 231, 231, 634,
+ 171, 232, 232, 232, 232, 232, 232, 233, 233, 247,
+ 247, 265, 265, 233, 275, 247, 275, 265, 275, 266,
+ 266, 267, 267, 633, 233, 266, 247, 267, 265, 631,
+ 630, 275, 278, 278, 278, 278, 266, 626, 267, 279,
+ 279, 279, 279, 280, 280, 280, 280, 281, 281, 281,
+
+ 281, 282, 282, 282, 282, 283, 283, 283, 283, 283,
+ 283, 284, 284, 284, 284, 284, 284, 386, 386, 499,
+ 499, 625, 624, 623, 621, 618, 617, 615, 614, 613,
+ 612, 611, 610, 607, 606, 604, 603, 602, 601, 386,
+ 499, 675, 675, 675, 677, 677, 600, 599, 597, 596,
+ 595, 593, 591, 590, 587, 578, 577, 576, 553, 546,
+ 545, 542, 541, 540, 539, 538, 537, 536, 535, 534,
+ 533, 531, 528, 527, 526, 525, 524, 523, 522, 521,
+ 520, 519, 518, 516, 515, 514, 513, 511, 509, 508,
+ 507, 506, 505, 504, 503, 502, 501, 500, 498, 497,
+
+ 496, 495, 494, 491, 490, 489, 488, 487, 486, 485,
+ 484, 483, 482, 481, 480, 479, 478, 477, 476, 475,
+ 473, 472, 471, 470, 469, 468, 467, 466, 465, 464,
+ 463, 462, 461, 460, 459, 458, 456, 455, 454, 453,
+ 452, 450, 449, 448, 447, 446, 445, 444, 441, 440,
+ 438, 437, 436, 435, 432, 431, 430, 429, 428, 427,
+ 426, 424, 423, 422, 421, 420, 419, 418, 417, 416,
+ 415, 414, 413, 412, 411, 410, 409, 408, 406, 405,
+ 404, 403, 402, 401, 400, 399, 398, 397, 396, 395,
+ 394, 393, 392, 391, 390, 389, 388, 387, 384, 383,
+
+ 382, 379, 378, 377, 376, 375, 374, 372, 370, 369,
+ 368, 366, 365, 364, 363, 362, 361, 360, 359, 358,
+ 357, 356, 355, 354, 353, 352, 351, 350, 349, 347,
+ 346, 345, 344, 343, 342, 341, 338, 337, 336, 333,
+ 332, 331, 330, 329, 328, 327, 326, 325, 324, 322,
+ 321, 320, 319, 318, 317, 316, 315, 313, 312, 311,
+ 310, 309, 308, 307, 306, 305, 304, 303, 302, 301,
+ 300, 299, 298, 297, 296, 295, 294, 292, 291, 290,
+ 289, 288, 287, 286, 285, 277, 276, 274, 273, 272,
+ 271, 270, 269, 264, 262, 261, 260, 259, 258, 257,
+
+ 256, 255, 253, 251, 250, 248, 246, 245, 242, 241,
+ 240, 239, 238, 237, 236, 234, 230, 229, 228, 227,
+ 226, 225, 224, 223, 222, 221, 220, 219, 218, 217,
+ 216, 215, 214, 213, 212, 211, 210, 209, 208, 207,
+ 206, 205, 204, 203, 202, 201, 200, 199, 198, 197,
+ 195, 194, 192, 191, 189, 187, 186, 185, 184, 183,
+ 182, 181, 180, 179, 177, 175, 162, 161, 160, 158,
+ 157, 156, 155, 154, 148, 146, 145, 144, 143, 142,
+ 141, 140, 139, 138, 135, 134, 133, 132, 131, 129,
+ 128, 127, 125, 124, 121, 119, 117, 116, 115, 114,
+
+ 113, 112, 111, 110, 107, 106, 105, 104, 103, 102,
+ 101, 100, 99, 98, 97, 96, 95, 94, 93, 92,
+ 91, 89, 88, 87, 86, 85, 84, 83, 81, 80,
+ 78, 77, 76, 75, 73, 72, 71, 55, 54, 51,
+ 50, 37, 36, 34, 33, 32, 31, 30, 29, 28,
+ 20, 8, 7, 3, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674
+ } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "program_lexer.l"
+#line 2 "program_lexer.l"
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include "main/glheader.h"
+#include "prog_instruction.h"
+#include "prog_statevars.h"
+
+#include "program_parser.h"
+#include "program_parse.tab.h"
+
+#define require_ARB_vp (yyextra->mode == ARB_vertex)
+#define require_ARB_fp (yyextra->mode == ARB_fragment)
+#define require_shadow (yyextra->option.Shadow)
+#define require_rect (yyextra->option.TexRect)
+#define require_texarray (yyextra->option.TexArray)
+
+#ifndef HAVE_UNISTD_H
+#define YY_NO_UNISTD_H
+#endif
+
+#define return_token_or_IDENTIFIER(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define return_token_or_DOT(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yyless(1); \
+ return DOT; \
+ } \
+ } while (0)
+
+
+#define return_opcode(condition, token, opcode, sat) \
+ do { \
+ if (condition) { \
+ yylval->temp_inst.Opcode = OPCODE_ ## opcode; \
+ yylval->temp_inst.SaturateMode = SATURATE_ ## sat; \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define SWIZZLE_INVAL MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \
+ SWIZZLE_NIL, SWIZZLE_NIL)
+
+static unsigned
+mask_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return WRITEMASK_X;
+ case 'y':
+ case 'g':
+ return WRITEMASK_Y;
+ case 'z':
+ case 'b':
+ return WRITEMASK_Z;
+ case 'w':
+ case 'a':
+ return WRITEMASK_W;
+ }
+
+ return 0;
+}
+
+static unsigned
+swiz_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return SWIZZLE_X;
+ case 'y':
+ case 'g':
+ return SWIZZLE_Y;
+ case 'z':
+ case 'b':
+ return SWIZZLE_Z;
+ case 'w':
+ case 'a':
+ return SWIZZLE_W;
+ }
+
+ return 0;
+}
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->first_column = yylloc->last_column; \
+ yylloc->last_column += yyleng; \
+ if ((yylloc->first_line == 1) \
+ && (yylloc->first_column == 1)) { \
+ yylloc->position = 1; \
+ } else { \
+ yylloc->position += yylloc->last_column - yylloc->first_column; \
+ } \
+ } while(0);
+
+#define YY_EXTRA_TYPE struct asm_parser_state *
+#line 1007 "lex.yy.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ int yy_n_chars;
+ int yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ YYSTYPE * yylval_r;
+
+ YYLTYPE * yylloc_r;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+ /* This must go here because YYSTYPE and YYLTYPE are included
+ * from bison output in section 1.*/
+ # define yylval yyg->yylval_r
+
+ # define yylloc yyg->yylloc_r
+
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out (FILE * out_str ,yyscan_t yyscanner );
+
+int yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner );
+
+void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+ YYLTYPE *yyget_lloc (yyscan_t yyscanner );
+
+ void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ unsigned n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex \
+ (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int yylex \
+ (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 136 "program_lexer.l"
+
+
+#line 1251 "lex.yy.c"
+
+ yylval = yylval_param;
+
+ yylloc = yylloc_param;
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ yy_load_buffer_state(yyscanner );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 675 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 955 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yyg->yy_hold_char;
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 138 "program_lexer.l"
+{ return ARBvp_10; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 139 "program_lexer.l"
+{ return ARBfp_10; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 140 "program_lexer.l"
+{
+ yylval->integer = at_address;
+ return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
+}
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 144 "program_lexer.l"
+{ return ALIAS; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 145 "program_lexer.l"
+{ return ATTRIB; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 146 "program_lexer.l"
+{ return END; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 147 "program_lexer.l"
+{ return OPTION; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 148 "program_lexer.l"
+{ return OUTPUT; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 149 "program_lexer.l"
+{ return PARAM; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 150 "program_lexer.l"
+{ yylval->integer = at_temp; return TEMP; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 152 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, ABS, OFF); }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 153 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, ABS, ZERO_ONE); }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 154 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, ADD, OFF); }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 155 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, ADD, ZERO_ONE); }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 156 "program_lexer.l"
+{ return_opcode(require_ARB_vp, ARL, ARL, OFF); }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 158 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, CMP, OFF); }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 159 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, CMP, ZERO_ONE); }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 160 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, COS, OFF); }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 161 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, COS, ZERO_ONE); }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 163 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, DP3, OFF); }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 164 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, DP3, ZERO_ONE); }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 165 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, DP4, OFF); }
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 166 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, DP4, ZERO_ONE); }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 167 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, DPH, OFF); }
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 168 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, DPH, ZERO_ONE); }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 169 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, DST, OFF); }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 170 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, DST, ZERO_ONE); }
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 172 "program_lexer.l"
+{ return_opcode( 1, SCALAR_OP, EX2, OFF); }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 173 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, EX2, ZERO_ONE); }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 174 "program_lexer.l"
+{ return_opcode(require_ARB_vp, SCALAR_OP, EXP, OFF); }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 176 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, FLR, OFF); }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 177 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, FLR, ZERO_ONE); }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 178 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, FRC, OFF); }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 179 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, FRC, ZERO_ONE); }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 181 "program_lexer.l"
+{ return_opcode(require_ARB_fp, KIL, KIL, OFF); }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 183 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, LIT, OFF); }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 184 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, LIT, ZERO_ONE); }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 185 "program_lexer.l"
+{ return_opcode( 1, SCALAR_OP, LG2, OFF); }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 186 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, LG2, ZERO_ONE); }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 187 "program_lexer.l"
+{ return_opcode(require_ARB_vp, SCALAR_OP, LOG, OFF); }
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 188 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, LRP, OFF); }
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 189 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, LRP, ZERO_ONE); }
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 191 "program_lexer.l"
+{ return_opcode( 1, TRI_OP, MAD, OFF); }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 192 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, MAD, ZERO_ONE); }
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 193 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, MAX, OFF); }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 194 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, MAX, ZERO_ONE); }
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 195 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, MIN, OFF); }
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 196 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, MIN, ZERO_ONE); }
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 197 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, MOV, OFF); }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 198 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, MOV, ZERO_ONE); }
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 199 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, MUL, OFF); }
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 200 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, MUL, ZERO_ONE); }
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 202 "program_lexer.l"
+{ return_opcode( 1, BINSC_OP, POW, OFF); }
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 203 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BINSC_OP, POW, ZERO_ONE); }
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 205 "program_lexer.l"
+{ return_opcode( 1, SCALAR_OP, RCP, OFF); }
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 206 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, RCP, ZERO_ONE); }
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 207 "program_lexer.l"
+{ return_opcode( 1, SCALAR_OP, RSQ, OFF); }
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 208 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, RSQ, ZERO_ONE); }
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 210 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, SCS, OFF); }
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 211 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, SCS, ZERO_ONE); }
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 212 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, SGE, OFF); }
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 213 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, SGE, ZERO_ONE); }
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 214 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, SIN, OFF); }
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 215 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, SIN, ZERO_ONE); }
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 216 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, SLT, OFF); }
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 217 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, SLT, ZERO_ONE); }
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 218 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, SUB, OFF); }
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 219 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, SUB, ZERO_ONE); }
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 220 "program_lexer.l"
+{ return_opcode( 1, SWZ, SWZ, OFF); }
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 221 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SWZ, SWZ, ZERO_ONE); }
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 223 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TEX, OFF); }
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 224 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TEX, ZERO_ONE); }
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 225 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TXB, OFF); }
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 226 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TXB, ZERO_ONE); }
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 227 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TXP, OFF); }
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 228 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TXP, ZERO_ONE); }
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 230 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, XPD, OFF); }
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 231 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, XPD, ZERO_ONE); }
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 233 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 234 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 235 "program_lexer.l"
+{ return PROGRAM; }
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 236 "program_lexer.l"
+{ return STATE; }
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 237 "program_lexer.l"
+{ return RESULT; }
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 239 "program_lexer.l"
+{ return AMBIENT; }
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 240 "program_lexer.l"
+{ return ATTENUATION; }
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 241 "program_lexer.l"
+{ return BACK; }
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 242 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, CLIP); }
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 243 "program_lexer.l"
+{ return COLOR; }
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 244 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_fp, DEPTH); }
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 245 "program_lexer.l"
+{ return DIFFUSE; }
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 246 "program_lexer.l"
+{ return DIRECTION; }
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 247 "program_lexer.l"
+{ return EMISSION; }
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 248 "program_lexer.l"
+{ return ENV; }
+ YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 249 "program_lexer.l"
+{ return EYE; }
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 250 "program_lexer.l"
+{ return FOGCOORD; }
+ YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 251 "program_lexer.l"
+{ return FOG; }
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 252 "program_lexer.l"
+{ return FRONT; }
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 253 "program_lexer.l"
+{ return HALF; }
+ YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 254 "program_lexer.l"
+{ return INVERSE; }
+ YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 255 "program_lexer.l"
+{ return INVTRANS; }
+ YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 256 "program_lexer.l"
+{ return LIGHT; }
+ YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 257 "program_lexer.l"
+{ return LIGHTMODEL; }
+ YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 258 "program_lexer.l"
+{ return LIGHTPROD; }
+ YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 259 "program_lexer.l"
+{ return LOCAL; }
+ YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 260 "program_lexer.l"
+{ return MATERIAL; }
+ YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 261 "program_lexer.l"
+{ return MAT_PROGRAM; }
+ YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 262 "program_lexer.l"
+{ return MATRIX; }
+ YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 263 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, MATRIXINDEX); }
+ YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 264 "program_lexer.l"
+{ return MODELVIEW; }
+ YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 265 "program_lexer.l"
+{ return MVP; }
+ YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 266 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, NORMAL); }
+ YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 267 "program_lexer.l"
+{ return OBJECT; }
+ YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 268 "program_lexer.l"
+{ return PALETTE; }
+ YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 269 "program_lexer.l"
+{ return PARAMS; }
+ YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 270 "program_lexer.l"
+{ return PLANE; }
+ YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 271 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, POINT_TOK); }
+ YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 272 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, POINTSIZE); }
+ YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 273 "program_lexer.l"
+{ return POSITION; }
+ YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 274 "program_lexer.l"
+{ return PRIMARY; }
+ YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 275 "program_lexer.l"
+{ return PROJECTION; }
+ YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 276 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_fp, RANGE); }
+ YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 277 "program_lexer.l"
+{ return ROW; }
+ YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 278 "program_lexer.l"
+{ return SCENECOLOR; }
+ YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 279 "program_lexer.l"
+{ return SECONDARY; }
+ YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 280 "program_lexer.l"
+{ return SHININESS; }
+ YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 281 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, SIZE_TOK); }
+ YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 282 "program_lexer.l"
+{ return SPECULAR; }
+ YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 283 "program_lexer.l"
+{ return SPOT; }
+ YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 284 "program_lexer.l"
+{ return TEXCOORD; }
+ YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 285 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_fp, TEXENV); }
+ YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 286 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, TEXGEN); }
+ YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 287 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, TEXGEN_Q); }
+ YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 288 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, TEXGEN_S); }
+ YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 289 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, TEXGEN_T); }
+ YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 290 "program_lexer.l"
+{ return TEXTURE; }
+ YY_BREAK
+case 136:
+YY_RULE_SETUP
+#line 291 "program_lexer.l"
+{ return TRANSPOSE; }
+ YY_BREAK
+case 137:
+YY_RULE_SETUP
+#line 292 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, VTXATTRIB); }
+ YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 293 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, WEIGHT); }
+ YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 295 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
+ YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 296 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
+ YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 297 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
+ YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 298 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
+ YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 299 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
+ YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 300 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); }
+ YY_BREAK
+case 145:
+YY_RULE_SETUP
+#line 301 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); }
+ YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 302 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); }
+ YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 303 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); }
+ YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 304 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); }
+ YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 305 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); }
+ YY_BREAK
+case 150:
+YY_RULE_SETUP
+#line 306 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); }
+ YY_BREAK
+case 151:
+YY_RULE_SETUP
+#line 307 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); }
+ YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 309 "program_lexer.l"
+{
+ yylval->string = strdup(yytext);
+ return IDENTIFIER;
+}
+ YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 314 "program_lexer.l"
+{ return DOT_DOT; }
+ YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 316 "program_lexer.l"
+{
+ yylval->integer = strtol(yytext, NULL, 10);
+ return INTEGER;
+}
+ YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 320 "program_lexer.l"
+{
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+ YY_BREAK
+case 156:
+/* rule 156 can match eol */
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 324 "program_lexer.l"
+{
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+ YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 328 "program_lexer.l"
+{
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+ YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 332 "program_lexer.l"
+{
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+ YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 337 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return MASK4;
+}
+ YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 343 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return MASK3;
+}
+ YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 349 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return MASK3;
+}
+ YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 354 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return MASK3;
+}
+ YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 360 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+ YY_BREAK
+case 164:
+YY_RULE_SETUP
+#line 366 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+ YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 372 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return MASK2;
+}
+ YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 378 "program_lexer.l"
+{
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return MASK1;
+}
+ YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 385 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return SWIZZLE;
+}
+ YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 394 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return_token_or_DOT(require_ARB_fp, MASK4);
+}
+ YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 400 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+ YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 406 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+ YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 411 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+ YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 417 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+ YY_BREAK
+case 173:
+YY_RULE_SETUP
+#line 423 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+ YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 429 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+ YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 435 "program_lexer.l"
+{
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return_token_or_DOT(require_ARB_fp, MASK1);
+}
+ YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 443 "program_lexer.l"
+{
+ if (require_ARB_vp) {
+ return TEXGEN_R;
+ } else {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
+ SWIZZLE_X, SWIZZLE_X);
+ yylval->swiz_mask.mask = WRITEMASK_X;
+ return MASK1;
+ }
+}
+ YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 454 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return_token_or_DOT(require_ARB_fp, SWIZZLE);
+}
+ YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 463 "program_lexer.l"
+{ return DOT; }
+ YY_BREAK
+case 179:
+/* rule 179 can match eol */
+YY_RULE_SETUP
+#line 465 "program_lexer.l"
+{
+ yylloc->first_line++;
+ yylloc->first_column = 1;
+ yylloc->last_line++;
+ yylloc->last_column = 1;
+ yylloc->position++;
+}
+ YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 472 "program_lexer.l"
+/* eat whitespace */ ;
+ YY_BREAK
+case 181:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 473 "program_lexer.l"
+/* eat comments */ ;
+ YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 474 "program_lexer.l"
+{ return yytext[0]; }
+ YY_BREAK
+case 183:
+YY_RULE_SETUP
+#line 475 "program_lexer.l"
+ECHO;
+ YY_BREAK
+#line 2383 "lex.yy.c"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap(yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin ,yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 675 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ register int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+ register char *yy_cp = yyg->yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 675 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 674);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+{
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yyg->yy_hold_char;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yyg->yy_n_chars + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ yyg->yytext_ptr = yy_bp;
+ yyg->yy_hold_char = *yy_cp;
+ yyg->yy_c_buf_p = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap(yyscanner ) )
+ return EOF;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state(yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void yy_load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+ yyfree((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_flush_buffer(b ,yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack(yyscanner);
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void yypop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ int num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @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.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int yyget_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *yyget_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_lineno (int line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "yyset_lineno called with no buffer" , yyscanner);
+
+ yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_column (int column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "yyset_column called with no buffer" , yyscanner);
+
+ yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = in_str ;
+}
+
+void yyset_out (FILE * out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = out_str ;
+}
+
+int yyget_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void yyset_debug (int bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylval;
+}
+
+void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylval = yylval_param;
+}
+
+YYLTYPE *yyget_lloc (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylloc;
+}
+
+void yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylloc = yylloc_param;
+}
+
+/* User-visible API */
+
+/* yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to yyalloc in
+ * the yyextra field.
+ */
+
+int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ yyset_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ yyfree(yyg->yy_start_stack ,yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
+{
+ return (void *) malloc( size );
+}
+
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr , yyscan_t yyscanner)
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 475 "program_lexer.l"
+
+
+
+void
+_mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state,
+ const char *string, size_t len)
+{
+ yylex_init_extra(state,scanner);
+ yy_scan_bytes(string,len,*scanner);
+}
+
+void
+_mesa_program_lexer_dtor(void *scanner)
+{
+ yylex_destroy(scanner);
+}
+
diff --git a/src/mesa/shader/nvfragparse.c b/src/mesa/shader/nvfragparse.c
index 20e4781372..0fd55524ab 100644
--- a/src/mesa/shader/nvfragparse.c
+++ b/src/mesa/shader/nvfragparse.c
@@ -43,6 +43,7 @@
#include "main/macros.h"
#include "program.h"
#include "prog_parameter.h"
+#include "prog_print.h"
#include "prog_instruction.h"
#include "nvfragparse.h"
@@ -384,16 +385,6 @@ static const char *InputRegisters[MAX_NV_FRAGMENT_PROGRAM_INPUTS + 1] = {
"TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
};
-static const char *OutputRegisters[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS + 1] = {
- "COLR", "COLH",
- /* These are only allows for register combiners */
- /*
- "TEX0", "TEX1", "TEX2", "TEX3",
- */
- "DEPR", NULL
-};
-
-
/**********************************************************************/
@@ -828,7 +819,6 @@ static GLboolean
Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
{
GLubyte token[100];
- GLint j;
/* Match "o[" */
if (!Parse_String(parseState, "o["))
@@ -839,19 +829,19 @@ Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
RETURN_ERROR;
/* try to match an output register name */
- for (j = 0; OutputRegisters[j]; j++) {
- if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) {
- static GLuint bothColors = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_COLH);
- *outputRegNum = j;
- parseState->outputsWritten |= (1 << j);
- if ((parseState->outputsWritten & bothColors) == bothColors) {
- RETURN_ERROR1("Illegal to write to both o[COLR] and o[COLH]");
- }
- break;
- }
+ if (_mesa_strcmp((char *) token, "COLR") == 0 ||
+ _mesa_strcmp((char *) token, "COLH") == 0) {
+ /* note that we don't distinguish between COLR and COLH */
+ *outputRegNum = FRAG_RESULT_COLOR;
+ parseState->outputsWritten |= (1 << FRAG_RESULT_COLOR);
+ }
+ else if (_mesa_strcmp((char *) token, "DEPR") == 0) {
+ *outputRegNum = FRAG_RESULT_DEPTH;
+ parseState->outputsWritten |= (1 << FRAG_RESULT_DEPTH);
}
- if (!OutputRegisters[j])
+ else {
RETURN_ERROR1("Invalid output register name");
+ }
/* Match ']' */
if (!Parse_String(parseState, "]"))
@@ -967,6 +957,7 @@ Parse_VectorSrc(struct parse_state *parseState,
GLfloat sign = 1.0F;
GLubyte token[100];
GLint idx;
+ GLuint negateBase, negateAbs;
/*
* First, take care of +/- and absolute value stuff.
@@ -978,21 +969,23 @@ Parse_VectorSrc(struct parse_state *parseState,
if (Parse_String(parseState, "|")) {
srcReg->Abs = GL_TRUE;
- srcReg->NegateAbs = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
+ negateAbs = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
if (Parse_String(parseState, "-"))
- srcReg->NegateBase = NEGATE_XYZW;
+ negateBase = NEGATE_XYZW;
else if (Parse_String(parseState, "+"))
- srcReg->NegateBase = NEGATE_NONE;
+ negateBase = NEGATE_NONE;
else
- srcReg->NegateBase = NEGATE_NONE;
+ negateBase = NEGATE_NONE;
}
else {
srcReg->Abs = GL_FALSE;
- srcReg->NegateAbs = GL_FALSE;
- srcReg->NegateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
+ negateAbs = NEGATE_NONE;
+ negateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
}
+ srcReg->Negate = srcReg->Abs ? negateAbs : negateBase;
+
/* This should be the real src vector/register name */
if (!Peek_Token(parseState, token))
RETURN_ERROR;
@@ -1093,6 +1086,7 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
GLfloat sign = 1.0F;
GLboolean needSuffix = GL_TRUE;
GLint idx;
+ GLuint negateBase, negateAbs;
/*
* First, take care of +/- and absolute value stuff.
@@ -1104,21 +1098,23 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
if (Parse_String(parseState, "|")) {
srcReg->Abs = GL_TRUE;
- srcReg->NegateAbs = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
+ negateAbs = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
if (Parse_String(parseState, "-"))
- srcReg->NegateBase = NEGATE_XYZW;
+ negateBase = NEGATE_XYZW;
else if (Parse_String(parseState, "+"))
- srcReg->NegateBase = NEGATE_NONE;
+ negateBase = NEGATE_NONE;
else
- srcReg->NegateBase = NEGATE_NONE;
+ negateBase = NEGATE_NONE;
}
else {
srcReg->Abs = GL_FALSE;
- srcReg->NegateAbs = GL_FALSE;
- srcReg->NegateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
+ negateAbs = NEGATE_NONE;
+ negateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
}
+ srcReg->Negate = srcReg->Abs ? negateAbs : negateBase;
+
if (!Peek_Token(parseState, token))
RETURN_ERROR;
@@ -1257,9 +1253,8 @@ Parse_PrintInstruction(struct parse_state *parseState,
}
inst->SrcReg[0].Swizzle = SWIZZLE_NOOP;
- inst->SrcReg[0].NegateBase = NEGATE_NONE;
inst->SrcReg[0].Abs = GL_FALSE;
- inst->SrcReg[0].NegateAbs = GL_FALSE;
+ inst->SrcReg[0].Negate = NEGATE_NONE;
return GL_TRUE;
}
@@ -1318,8 +1313,6 @@ Parse_InstructionSequence(struct parse_state *parseState,
}
else if (Parse_String(parseState, "END")) {
inst->Opcode = OPCODE_END;
- inst->StringPos = parseState->curLine - parseState->start;
- assert(inst->StringPos >= 0);
parseState->numInst++;
if (Parse_Token(parseState, token)) {
RETURN_ERROR1("Code after END opcode.");
@@ -1346,8 +1339,6 @@ Parse_InstructionSequence(struct parse_state *parseState,
inst->SaturateMode = (instMatch.suffixes & (_S))
? SATURATE_ZERO_ONE : SATURATE_OFF;
inst->CondUpdate = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE;
- inst->StringPos = parseState->curLine - parseState->start;
- assert(inst->StringPos >= 0);
/*
* parse the input and output operands
@@ -1570,7 +1561,7 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
#ifdef DEBUG_foo
_mesa_printf("--- glLoadProgramNV(%d) result ---\n", program->Base.Id);
- _mesa_print_nv_fragment_program(program);
+ _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0);
_mesa_printf("----------------------------------\n");
#endif
}
@@ -1582,243 +1573,6 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
}
-static void
-PrintSrcReg(const struct gl_fragment_program *program,
- const struct prog_src_register *src)
-{
- static const char comps[5] = "xyzw";
-
- if (src->NegateAbs) {
- _mesa_printf("-");
- }
- if (src->Abs) {
- _mesa_printf("|");
- }
- if (src->NegateBase) {
- _mesa_printf("-");
- }
- if (src->File == PROGRAM_NAMED_PARAM) {
- if (program->Base.Parameters->Parameters[src->Index].Type
- == PROGRAM_CONSTANT) {
- const GLfloat *v;
- v = program->Base.Parameters->ParameterValues[src->Index];
- _mesa_printf("{%g, %g, %g, %g}", v[0], v[1], v[2], v[3]);
- }
- else {
- ASSERT(program->Base.Parameters->Parameters[src->Index].Type
- == PROGRAM_NAMED_PARAM);
- _mesa_printf("%s", program->Base.Parameters->Parameters[src->Index].Name);
- }
- }
- else if (src->File == PROGRAM_OUTPUT) {
- _mesa_printf("o[%s]", OutputRegisters[src->Index]);
- }
- else if (src->File == PROGRAM_INPUT) {
- _mesa_printf("f[%s]", InputRegisters[src->Index]);
- }
- else if (src->File == PROGRAM_LOCAL_PARAM) {
- _mesa_printf("p[%d]", src->Index);
- }
- else if (src->File == PROGRAM_TEMPORARY) {
- if (src->Index >= 32)
- _mesa_printf("H%d", src->Index);
- else
- _mesa_printf("R%d", src->Index);
- }
- else if (src->File == PROGRAM_WRITE_ONLY) {
- _mesa_printf("%cC", "HR"[src->Index]);
- }
- else {
- _mesa_problem(NULL, "Invalid fragment register %d", src->Index);
- return;
- }
- if (GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 1) &&
- GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 2) &&
- GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 3)) {
- _mesa_printf(".%c", comps[GET_SWZ(src->Swizzle, 0)]);
- }
- else if (src->Swizzle != SWIZZLE_NOOP) {
- _mesa_printf(".%c%c%c%c",
- comps[GET_SWZ(src->Swizzle, 0)],
- comps[GET_SWZ(src->Swizzle, 1)],
- comps[GET_SWZ(src->Swizzle, 2)],
- comps[GET_SWZ(src->Swizzle, 3)]);
- }
- if (src->Abs) {
- _mesa_printf("|");
- }
-}
-
-static void
-PrintTextureSrc(const struct prog_instruction *inst)
-{
- _mesa_printf("TEX%d, ", inst->TexSrcUnit);
- switch (inst->TexSrcTarget) {
- case TEXTURE_1D_INDEX:
- _mesa_printf("1D");
- break;
- case TEXTURE_2D_INDEX:
- _mesa_printf("2D");
- break;
- case TEXTURE_3D_INDEX:
- _mesa_printf("3D");
- break;
- case TEXTURE_RECT_INDEX:
- _mesa_printf("RECT");
- break;
- case TEXTURE_CUBE_INDEX:
- _mesa_printf("CUBE");
- break;
- default:
- _mesa_problem(NULL, "Invalid textue target in PrintTextureSrc");
- }
-}
-
-static void
-PrintCondCode(const struct prog_dst_register *dst)
-{
- static const char *comps = "xyzw";
- static const char *ccString[] = {
- "??", "GT", "EQ", "LT", "UN", "GE", "LE", "NE", "TR", "FL", "??"
- };
-
- _mesa_printf("%s", ccString[dst->CondMask]);
- if (GET_SWZ(dst->CondSwizzle, 0) == GET_SWZ(dst->CondSwizzle, 1) &&
- GET_SWZ(dst->CondSwizzle, 0) == GET_SWZ(dst->CondSwizzle, 2) &&
- GET_SWZ(dst->CondSwizzle, 0) == GET_SWZ(dst->CondSwizzle, 3)) {
- _mesa_printf(".%c", comps[GET_SWZ(dst->CondSwizzle, 0)]);
- }
- else if (dst->CondSwizzle != SWIZZLE_NOOP) {
- _mesa_printf(".%c%c%c%c",
- comps[GET_SWZ(dst->CondSwizzle, 0)],
- comps[GET_SWZ(dst->CondSwizzle, 1)],
- comps[GET_SWZ(dst->CondSwizzle, 2)],
- comps[GET_SWZ(dst->CondSwizzle, 3)]);
- }
-}
-
-
-static void
-PrintDstReg(const struct prog_dst_register *dst)
-{
- if (dst->File == PROGRAM_OUTPUT) {
- _mesa_printf("o[%s]", OutputRegisters[dst->Index]);
- }
- else if (dst->File == PROGRAM_TEMPORARY) {
- if (dst->Index >= 32)
- _mesa_printf("H%d", dst->Index);
- else
- _mesa_printf("R%d", dst->Index);
- }
- else if (dst->File == PROGRAM_LOCAL_PARAM) {
- _mesa_printf("p[%d]", dst->Index);
- }
- else if (dst->File == PROGRAM_WRITE_ONLY) {
- _mesa_printf("%cC", "HR"[dst->Index]);
- }
- else {
- _mesa_printf("???");
- }
-
- if (dst->WriteMask != 0 && dst->WriteMask != WRITEMASK_XYZW) {
- _mesa_printf(".");
- if (dst->WriteMask & WRITEMASK_X)
- _mesa_printf("x");
- if (dst->WriteMask & WRITEMASK_Y)
- _mesa_printf("y");
- if (dst->WriteMask & WRITEMASK_Z)
- _mesa_printf("z");
- if (dst->WriteMask & WRITEMASK_W)
- _mesa_printf("w");
- }
-
- if (dst->CondMask != COND_TR ||
- dst->CondSwizzle != SWIZZLE_NOOP) {
- _mesa_printf(" (");
- PrintCondCode(dst);
- _mesa_printf(")");
- }
-}
-
-
-/**
- * Print (unparse) the given vertex program. Just for debugging.
- */
-void
-_mesa_print_nv_fragment_program(const struct gl_fragment_program *program)
-{
- const struct prog_instruction *inst;
-
- for (inst = program->Base.Instructions; inst->Opcode != OPCODE_END; inst++) {
- int i;
- for (i = 0; Instructions[i].name; i++) {
- if (inst->Opcode == Instructions[i].opcode) {
- /* print instruction name */
- _mesa_printf("%s", Instructions[i].name);
- if (inst->Precision == FLOAT16)
- _mesa_printf("H");
- else if (inst->Precision == FIXED12)
- _mesa_printf("X");
- if (inst->CondUpdate)
- _mesa_printf("C");
- if (inst->SaturateMode == SATURATE_ZERO_ONE)
- _mesa_printf("_SAT");
- _mesa_printf(" ");
-
- if (Instructions[i].inputs == INPUT_CC) {
- PrintCondCode(&inst->DstReg);
- }
- else if (Instructions[i].outputs == OUTPUT_V ||
- Instructions[i].outputs == OUTPUT_S) {
- /* print dest register */
- PrintDstReg(&inst->DstReg);
- _mesa_printf(", ");
- }
-
- /* print source register(s) */
- if (Instructions[i].inputs == INPUT_1V ||
- Instructions[i].inputs == INPUT_1S) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- }
- else if (Instructions[i].inputs == INPUT_2V ||
- Instructions[i].inputs == INPUT_2S) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[1]);
- }
- else if (Instructions[i].inputs == INPUT_3V) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[1]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[2]);
- }
- else if (Instructions[i].inputs == INPUT_1V_T) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintTextureSrc(inst);
- }
- else if (Instructions[i].inputs == INPUT_3V_T) {
- PrintSrcReg(program, &inst->SrcReg[0]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[1]);
- _mesa_printf(", ");
- PrintSrcReg(program, &inst->SrcReg[2]);
- _mesa_printf(", ");
- PrintTextureSrc(inst);
- }
- _mesa_printf(";\n");
- break;
- }
- }
- if (!Instructions[i].name) {
- _mesa_printf("Invalid opcode %d\n", inst->Opcode);
- }
- }
- _mesa_printf("END\n");
-}
-
-
const char *
_mesa_nv_fragment_input_register_name(GLuint i)
{
@@ -1826,10 +1580,3 @@ _mesa_nv_fragment_input_register_name(GLuint i)
return InputRegisters[i];
}
-
-const char *
-_mesa_nv_fragment_output_register_name(GLuint i)
-{
- ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_OUTPUTS);
- return OutputRegisters[i];
-}
diff --git a/src/mesa/shader/nvfragparse.h b/src/mesa/shader/nvfragparse.h
index de45cf543d..544ab80c56 100644
--- a/src/mesa/shader/nvfragparse.h
+++ b/src/mesa/shader/nvfragparse.h
@@ -37,16 +37,7 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum target,
struct gl_fragment_program *program);
-extern void
-_mesa_print_nv_fragment_program(const struct gl_fragment_program *program);
-
-
extern const char *
_mesa_nv_fragment_input_register_name(GLuint i);
-
-extern const char *
-_mesa_nv_fragment_output_register_name(GLuint i);
-
-
#endif
diff --git a/src/mesa/shader/nvprogram.c b/src/mesa/shader/nvprogram.c
index 88272fff3f..d6469b17be 100644
--- a/src/mesa/shader/nvprogram.c
+++ b/src/mesa/shader/nvprogram.c
@@ -246,8 +246,7 @@ _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
struct gl_program *prog;
GET_CURRENT_CONTEXT(ctx);
- if (!ctx->_CurrentProgram)
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
prog = _mesa_lookup_program(ctx, id);
if (!prog) {
@@ -283,8 +282,7 @@ _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
struct gl_program *prog;
GET_CURRENT_CONTEXT(ctx);
- if (!ctx->_CurrentProgram)
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
if (pname != GL_PROGRAM_STRING_NV) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)");
@@ -356,6 +354,7 @@ _mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
void GLAPIENTRY
_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
{
+ const struct gl_client_array *array;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -364,15 +363,17 @@ _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
return;
}
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
switch (pname) {
case GL_ATTRIB_ARRAY_SIZE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size;
+ params[0] = array->Size;
break;
case GL_ATTRIB_ARRAY_STRIDE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
+ params[0] = array->Stride;
break;
case GL_ATTRIB_ARRAY_TYPE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type;
+ params[0] = array->Type;
break;
case GL_CURRENT_ATTRIB_NV:
if (index == 0) {
@@ -397,6 +398,7 @@ _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
void GLAPIENTRY
_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
{
+ const struct gl_client_array *array;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -405,15 +407,17 @@ _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
return;
}
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
switch (pname) {
case GL_ATTRIB_ARRAY_SIZE_NV:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size;
+ params[0] = (GLfloat) array->Size;
break;
case GL_ATTRIB_ARRAY_STRIDE_NV:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
+ params[0] = (GLfloat) array->Stride;
break;
case GL_ATTRIB_ARRAY_TYPE_NV:
- params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type;
+ params[0] = (GLfloat) array->Type;
break;
case GL_CURRENT_ATTRIB_NV:
if (index == 0) {
@@ -438,6 +442,7 @@ _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
void GLAPIENTRY
_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
{
+ const struct gl_client_array *array;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -446,15 +451,17 @@ _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
return;
}
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
switch (pname) {
case GL_ATTRIB_ARRAY_SIZE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Size;
+ params[0] = array->Size;
break;
case GL_ATTRIB_ARRAY_STRIDE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Stride;
+ params[0] = array->Stride;
break;
case GL_ATTRIB_ARRAY_TYPE_NV:
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Type;
+ params[0] = array->Type;
break;
case GL_CURRENT_ATTRIB_NV:
if (index == 0) {
@@ -469,11 +476,7 @@ _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
params[3] = (GLint) ctx->Current.Attrib[index][3];
break;
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
- if (!ctx->Extensions.ARB_vertex_buffer_object) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
- return;
- }
- params[0] = ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name;
+ params[0] = array->BufferObj->Name;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
@@ -712,7 +715,7 @@ _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
prog = _mesa_lookup_program(ctx, id);
if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
@@ -777,8 +780,7 @@ _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
GET_CURRENT_CONTEXT(ctx);
- if (!ctx->_CurrentProgram)
- ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
prog = _mesa_lookup_program(ctx, id);
if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
diff --git a/src/mesa/shader/nvvertparse.c b/src/mesa/shader/nvvertparse.c
index 08538c0ee4..f5e2df2670 100644
--- a/src/mesa/shader/nvvertparse.c
+++ b/src/mesa/shader/nvvertparse.c
@@ -44,6 +44,7 @@
#include "nvprogram.h"
#include "nvvertparse.h"
#include "prog_instruction.h"
+#include "prog_print.h"
#include "program.h"
@@ -640,12 +641,12 @@ Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *sr
RETURN_ERROR;
if (token[0] == '-') {
(void) Parse_String(parseState, "-");
- srcReg->NegateBase = NEGATE_XYZW;
+ srcReg->Negate = NEGATE_XYZW;
if (!Peek_Token(parseState, token))
RETURN_ERROR;
}
else {
- srcReg->NegateBase = NEGATE_NONE;
+ srcReg->Negate = NEGATE_NONE;
}
/* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
@@ -733,13 +734,13 @@ Parse_ScalarSrcReg(struct parse_state *parseState, struct prog_src_register *src
if (!Peek_Token(parseState, token))
RETURN_ERROR;
if (token[0] == '-') {
- srcReg->NegateBase = NEGATE_XYZW;
+ srcReg->Negate = NEGATE_XYZW;
(void) Parse_String(parseState, "-"); /* consume '-' */
if (!Peek_Token(parseState, token))
RETURN_ERROR;
}
else {
- srcReg->NegateBase = NEGATE_NONE;
+ srcReg->Negate = NEGATE_NONE;
}
/* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
@@ -799,7 +800,6 @@ Parse_UnaryOpInstruction(struct parse_state *parseState,
RETURN_ERROR1("ABS illegal for vertex program 1.0");
inst->Opcode = opcode;
- inst->StringPos = parseState->curLine - parseState->start;
/* dest reg */
if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
@@ -832,7 +832,6 @@ Parse_BiOpInstruction(struct parse_state *parseState,
RETURN_ERROR1("SUB illegal for vertex program 1.0");
inst->Opcode = opcode;
- inst->StringPos = parseState->curLine - parseState->start;
/* dest reg */
if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
@@ -880,7 +879,6 @@ Parse_TriOpInstruction(struct parse_state *parseState,
enum prog_opcode opcode)
{
inst->Opcode = opcode;
- inst->StringPos = parseState->curLine - parseState->start;
/* dest reg */
if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
@@ -951,7 +949,6 @@ Parse_ScalarInstruction(struct parse_state *parseState,
RETURN_ERROR1("RCC illegal for vertex program 1.0");
inst->Opcode = opcode;
- inst->StringPos = parseState->curLine - parseState->start;
/* dest reg */
if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
@@ -977,7 +974,6 @@ static GLboolean
Parse_AddressInstruction(struct parse_state *parseState, struct prog_instruction *inst)
{
inst->Opcode = OPCODE_ARL;
- inst->StringPos = parseState->curLine - parseState->start;
/* Make ARB_vp backends happy */
inst->DstReg.File = PROGRAM_ADDRESS;
@@ -1010,7 +1006,6 @@ Parse_EndInstruction(struct parse_state *parseState, struct prog_instruction *in
GLubyte token[100];
inst->Opcode = OPCODE_END;
- inst->StringPos = parseState->curLine - parseState->start;
/* this should fail! */
if (Parse_Token(parseState, token))
@@ -1044,7 +1039,6 @@ Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *
GLint idx;
inst->Opcode = OPCODE_PRINT;
- inst->StringPos = parseState->curLine - parseState->start;
/* The first argument is a literal string 'just like this' */
if (!Parse_String(parseState, "'"))
@@ -1068,7 +1062,7 @@ Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *
RETURN_ERROR;
srcReg->RelAddr = GL_FALSE;
- srcReg->NegateBase = NEGATE_NONE;
+ srcReg->Negate = NEGATE_NONE;
srcReg->Swizzle = SWIZZLE_NOOP;
/* Register can be R<n>, c[n], c[n +/- offset], a named vertex attrib,
@@ -1401,7 +1395,7 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
#ifdef DEBUG_foo
_mesa_printf("--- glLoadProgramNV result ---\n");
- _mesa_print_nv_vertex_program(program);
+ _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0);
_mesa_printf("------------------------------\n");
#endif
}
@@ -1417,161 +1411,6 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
}
-static void
-PrintSrcReg(const struct prog_src_register *src)
-{
- static const char comps[5] = "xyzw";
- if (src->NegateBase)
- _mesa_printf("-");
- if (src->RelAddr) {
- if (src->Index > 0)
- _mesa_printf("c[A0.x + %d]", src->Index);
- else if (src->Index < 0)
- _mesa_printf("c[A0.x - %d]", -src->Index);
- else
- _mesa_printf("c[A0.x]");
- }
- else if (src->File == PROGRAM_OUTPUT) {
- _mesa_printf("o[%s]", OutputRegisters[src->Index]);
- }
- else if (src->File == PROGRAM_INPUT) {
- _mesa_printf("v[%s]", InputRegisters[src->Index]);
- }
- else if (src->File == PROGRAM_ENV_PARAM) {
- _mesa_printf("c[%d]", src->Index);
- }
- else {
- ASSERT(src->File == PROGRAM_TEMPORARY);
- _mesa_printf("R%d", src->Index);
- }
-
- if (GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 1) &&
- GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 2) &&
- GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 3)) {
- _mesa_printf(".%c", comps[GET_SWZ(src->Swizzle, 0)]);
- }
- else if (src->Swizzle != SWIZZLE_NOOP) {
- _mesa_printf(".%c%c%c%c",
- comps[GET_SWZ(src->Swizzle, 0)],
- comps[GET_SWZ(src->Swizzle, 1)],
- comps[GET_SWZ(src->Swizzle, 2)],
- comps[GET_SWZ(src->Swizzle, 3)]);
- }
-}
-
-
-static void
-PrintDstReg(const struct prog_dst_register *dst)
-{
- if (dst->File == PROGRAM_OUTPUT) {
- _mesa_printf("o[%s]", OutputRegisters[dst->Index]);
- }
- else if (dst->File == PROGRAM_INPUT) {
- _mesa_printf("v[%s]", InputRegisters[dst->Index]);
- }
- else if (dst->File == PROGRAM_ENV_PARAM) {
- _mesa_printf("c[%d]", dst->Index);
- }
- else {
- ASSERT(dst->File == PROGRAM_TEMPORARY);
- _mesa_printf("R%d", dst->Index);
- }
-
- if (dst->WriteMask != 0 && dst->WriteMask != WRITEMASK_XYZW) {
- _mesa_printf(".");
- if (dst->WriteMask & WRITEMASK_X)
- _mesa_printf("x");
- if (dst->WriteMask & WRITEMASK_Y)
- _mesa_printf("y");
- if (dst->WriteMask & WRITEMASK_Z)
- _mesa_printf("z");
- if (dst->WriteMask & WRITEMASK_W)
- _mesa_printf("w");
- }
-}
-
-
-/**
- * Print a single NVIDIA vertex program instruction.
- */
-void
-_mesa_print_nv_vertex_instruction(const struct prog_instruction *inst)
-{
- GLuint i, n;
-
- switch (inst->Opcode) {
- case OPCODE_MOV:
- case OPCODE_LIT:
- case OPCODE_RCP:
- case OPCODE_RSQ:
- case OPCODE_EXP:
- case OPCODE_LOG:
- case OPCODE_RCC:
- case OPCODE_ABS:
- case OPCODE_MUL:
- case OPCODE_ADD:
- case OPCODE_DP3:
- case OPCODE_DP4:
- case OPCODE_DST:
- case OPCODE_MIN:
- case OPCODE_MAX:
- case OPCODE_SLT:
- case OPCODE_SGE:
- case OPCODE_DPH:
- case OPCODE_SUB:
- case OPCODE_MAD:
- _mesa_printf("%s ", _mesa_opcode_string(inst->Opcode));
- PrintDstReg(&inst->DstReg);
- _mesa_printf(", ");
- n = _mesa_num_inst_src_regs(inst->Opcode);
- for (i = 0; i < n; i++) {
- PrintSrcReg(&inst->SrcReg[i]);
- if (i + 1 < n)
- _mesa_printf(", ");
- }
- _mesa_printf(";\n");
- break;
- case OPCODE_ARL:
- _mesa_printf("ARL A0.x, ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(";\n");
- break;
- case OPCODE_PRINT:
- _mesa_printf("PRINT '%s'", inst->Data);
- if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
- _mesa_printf(", ");
- PrintSrcReg(&inst->SrcReg[0]);
- _mesa_printf(";\n");
- }
- else {
- _mesa_printf("\n");
- }
- break;
- case OPCODE_END:
- _mesa_printf("END\n");
- break;
- default:
- _mesa_printf("BAD INSTRUCTION\n");
- }
-}
-
-
-/**
- * Print (unparse) the given vertex program. Just for debugging.
- */
-void
-_mesa_print_nv_vertex_program(const struct gl_vertex_program *program)
-{
- const struct prog_instruction *inst;
-
- for (inst = program->Base.Instructions; ; inst++) {
- _mesa_print_nv_vertex_instruction(inst);
- if (inst->Opcode == OPCODE_END)
- return;
- }
-}
-
-
const char *
_mesa_nv_vertex_input_register_name(GLuint i)
{
diff --git a/src/mesa/shader/nvvertparse.h b/src/mesa/shader/nvvertparse.h
index 15fb03cd4e..9919e22388 100644
--- a/src/mesa/shader/nvvertparse.h
+++ b/src/mesa/shader/nvvertparse.h
@@ -35,11 +35,6 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum target,
const GLubyte *str, GLsizei len,
struct gl_vertex_program *program);
-extern void
-_mesa_print_nv_vertex_instruction(const struct prog_instruction *inst);
-
-extern void
-_mesa_print_nv_vertex_program(const struct gl_vertex_program *program);
extern const char *
_mesa_nv_vertex_input_register_name(GLuint i);
diff --git a/src/mesa/shader/prog_cache.c b/src/mesa/shader/prog_cache.c
index 36a25377c5..9437e59613 100644
--- a/src/mesa/shader/prog_cache.c
+++ b/src/mesa/shader/prog_cache.c
@@ -44,6 +44,7 @@ struct cache_item
struct gl_program_cache
{
struct cache_item **items;
+ struct cache_item *last;
GLuint size, n_items;
};
@@ -83,6 +84,8 @@ rehash(struct gl_program_cache *cache)
struct cache_item *c, *next;
GLuint size, i;
+ cache->last = NULL;
+
size = cache->size * 3;
items = (struct cache_item**) _mesa_malloc(size * sizeof(*items));
_mesa_memset(items, 0, size * sizeof(*items));
@@ -105,6 +108,8 @@ clear_cache(GLcontext *ctx, struct gl_program_cache *cache)
{
struct cache_item *c, *next;
GLuint i;
+
+ cache->last = NULL;
for (i = 0; i < cache->size; i++) {
for (c = cache->items[i]; c; c = next) {
@@ -149,18 +154,26 @@ _mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *cache)
struct gl_program *
-_mesa_search_program_cache(const struct gl_program_cache *cache,
+_mesa_search_program_cache(struct gl_program_cache *cache,
const void *key, GLuint keysize)
{
- const GLuint hash = hash_key(key, keysize);
- struct cache_item *c;
-
- for (c = cache->items[hash % cache->size]; c; c = c->next) {
- if (c->hash == hash && memcmp(c->key, key, keysize) == 0)
- return c->program;
+ if (cache->last &&
+ memcmp(cache->last->key, key, keysize) == 0) {
+ return cache->last->program;
}
+ else {
+ const GLuint hash = hash_key(key, keysize);
+ struct cache_item *c;
+
+ for (c = cache->items[hash % cache->size]; c; c = c->next) {
+ if (c->hash == hash && memcmp(c->key, key, keysize) == 0) {
+ cache->last = c;
+ return c->program;
+ }
+ }
- return NULL;
+ return NULL;
+ }
}
diff --git a/src/mesa/shader/prog_cache.h b/src/mesa/shader/prog_cache.h
index a8c91fba01..4e1ccac03f 100644
--- a/src/mesa/shader/prog_cache.h
+++ b/src/mesa/shader/prog_cache.h
@@ -42,7 +42,7 @@ _mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *pc);
extern struct gl_program *
-_mesa_search_program_cache(const struct gl_program_cache *cache,
+_mesa_search_program_cache(struct gl_program_cache *cache,
const void *key, GLuint keysize);
extern void
diff --git a/src/mesa/shader/prog_debug.c b/src/mesa/shader/prog_debug.c
deleted file mode 100644
index 7bcb2ef734..0000000000
--- a/src/mesa/shader/prog_debug.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "nvfragparse.h"
-#include "nvvertparse.h"
-#include "program.h"
-#include "prog_debug.h"
-#include "prog_parameter.h"
-#include "prog_instruction.h"
-
-
-
-/**
- * Functions for the experimental GL_MESA_program_debug extension.
- */
-
-
-/* XXX temporary */
-GLAPI void GLAPIENTRY
-glProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
- GLvoid *data)
-{
- _mesa_ProgramCallbackMESA(target, callback, data);
-}
-
-
-void
-_mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback,
- GLvoid *data)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- switch (target) {
- case GL_FRAGMENT_PROGRAM_ARB:
- if (!ctx->Extensions.ARB_fragment_program) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
- return;
- }
- ctx->FragmentProgram.Callback = callback;
- ctx->FragmentProgram.CallbackData = data;
- break;
- case GL_FRAGMENT_PROGRAM_NV:
- if (!ctx->Extensions.NV_fragment_program) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
- return;
- }
- ctx->FragmentProgram.Callback = callback;
- ctx->FragmentProgram.CallbackData = data;
- break;
- case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
- if (!ctx->Extensions.ARB_vertex_program &&
- !ctx->Extensions.NV_vertex_program) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
- return;
- }
- ctx->VertexProgram.Callback = callback;
- ctx->VertexProgram.CallbackData = data;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)");
- return;
- }
-}
-
-
-/* XXX temporary */
-GLAPI void GLAPIENTRY
-glGetProgramRegisterfvMESA(GLenum target,
- GLsizei len, const GLubyte *registerName,
- GLfloat *v)
-{
- _mesa_GetProgramRegisterfvMESA(target, len, registerName, v);
-}
-
-
-void
-_mesa_GetProgramRegisterfvMESA(GLenum target,
- GLsizei len, const GLubyte *registerName,
- GLfloat *v)
-{
- char reg[1000];
- GET_CURRENT_CONTEXT(ctx);
-
- /* We _should_ be inside glBegin/glEnd */
-#if 0
- if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA");
- return;
- }
-#endif
-
- /* make null-terminated copy of registerName */
- len = MIN2((unsigned int) len, sizeof(reg) - 1);
- _mesa_memcpy(reg, registerName, len);
- reg[len] = 0;
-
- switch (target) {
- case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
- if (!ctx->Extensions.ARB_vertex_program &&
- !ctx->Extensions.NV_vertex_program) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetProgramRegisterfvMESA(target)");
- return;
- }
- if (!ctx->VertexProgram._Enabled) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetProgramRegisterfvMESA");
- return;
- }
- /* GL_NV_vertex_program */
- if (reg[0] == 'R') {
- /* Temp register */
- GLint i = _mesa_atoi(reg + 1);
- if (i >= (GLint)ctx->Const.VertexProgram.MaxTemps) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetProgramRegisterfvMESA(registerName)");
- return;
- }
- ctx->Driver.GetProgramRegister(ctx, PROGRAM_TEMPORARY, i, v);
- }
- else if (reg[0] == 'v' && reg[1] == '[') {
- /* Vertex Input attribute */
- GLuint i;
- for (i = 0; i < ctx->Const.VertexProgram.MaxAttribs; i++) {
- const char *name = _mesa_nv_vertex_input_register_name(i);
- char number[10];
- _mesa_sprintf(number, "%d", i);
- if (_mesa_strncmp(reg + 2, name, 4) == 0 ||
- _mesa_strncmp(reg + 2, number, _mesa_strlen(number)) == 0) {
- ctx->Driver.GetProgramRegister(ctx, PROGRAM_INPUT, i, v);
- return;
- }
- }
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetProgramRegisterfvMESA(registerName)");
- return;
- }
- else if (reg[0] == 'o' && reg[1] == '[') {
- /* Vertex output attribute */
- }
- /* GL_ARB_vertex_program */
- else if (_mesa_strncmp(reg, "vertex.", 7) == 0) {
-
- }
- else {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetProgramRegisterfvMESA(registerName)");
- return;
- }
- break;
- case GL_FRAGMENT_PROGRAM_ARB:
- if (!ctx->Extensions.ARB_fragment_program) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetProgramRegisterfvMESA(target)");
- return;
- }
- if (!ctx->FragmentProgram._Enabled) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetProgramRegisterfvMESA");
- return;
- }
- /* XXX to do */
- break;
- case GL_FRAGMENT_PROGRAM_NV:
- if (!ctx->Extensions.NV_fragment_program) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetProgramRegisterfvMESA(target)");
- return;
- }
- if (!ctx->FragmentProgram._Enabled) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetProgramRegisterfvMESA");
- return;
- }
- if (reg[0] == 'R') {
- /* Temp register */
- GLint i = _mesa_atoi(reg + 1);
- if (i >= (GLint)ctx->Const.FragmentProgram.MaxTemps) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetProgramRegisterfvMESA(registerName)");
- return;
- }
- ctx->Driver.GetProgramRegister(ctx, PROGRAM_TEMPORARY,
- i, v);
- }
- else if (reg[0] == 'f' && reg[1] == '[') {
- /* Fragment input attribute */
- GLuint i;
- for (i = 0; i < ctx->Const.FragmentProgram.MaxAttribs; i++) {
- const char *name = _mesa_nv_fragment_input_register_name(i);
- if (_mesa_strncmp(reg + 2, name, 4) == 0) {
- ctx->Driver.GetProgramRegister(ctx, PROGRAM_INPUT, i, v);
- return;
- }
- }
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetProgramRegisterfvMESA(registerName)");
- return;
- }
- else if (_mesa_strcmp(reg, "o[COLR]") == 0) {
- /* Fragment output color */
- ctx->Driver.GetProgramRegister(ctx, PROGRAM_OUTPUT,
- FRAG_RESULT_COLR, v);
- }
- else if (_mesa_strcmp(reg, "o[COLH]") == 0) {
- /* Fragment output color */
- ctx->Driver.GetProgramRegister(ctx, PROGRAM_OUTPUT,
- FRAG_RESULT_COLH, v);
- }
- else if (_mesa_strcmp(reg, "o[DEPR]") == 0) {
- /* Fragment output depth */
- ctx->Driver.GetProgramRegister(ctx, PROGRAM_OUTPUT,
- FRAG_RESULT_DEPR, v);
- }
- else {
- /* try user-defined identifiers */
- const GLfloat *value = _mesa_lookup_parameter_value(
- ctx->FragmentProgram.Current->Base.Parameters, -1, reg);
- if (value) {
- COPY_4V(v, value);
- }
- else {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetProgramRegisterfvMESA(registerName)");
- return;
- }
- }
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetProgramRegisterfvMESA(target)");
- return;
- }
-}
diff --git a/src/mesa/shader/prog_execute.c b/src/mesa/shader/prog_execute.c
index a93733c085..c8a762f8ff 100644
--- a/src/mesa/shader/prog_execute.c
+++ b/src/mesa/shader/prog_execute.c
@@ -186,30 +186,6 @@ get_dst_register_pointer(const struct prog_dst_register *dest,
-#if FEATURE_MESA_program_debug
-static struct gl_program_machine *CurrentMachine = NULL;
-
-/**
- * For GL_MESA_program_debug.
- * Return current value (4*GLfloat) of a program register.
- * Called via ctx->Driver.GetProgramRegister().
- */
-void
-_mesa_get_program_register(GLcontext *ctx, enum register_file file,
- GLuint index, GLfloat val[4])
-{
- if (CurrentMachine) {
- struct prog_src_register srcReg;
- const GLfloat *src;
- srcReg.File = file;
- srcReg.Index = index;
- src = get_src_register_pointer(&srcReg, CurrentMachine);
- COPY_4V(val, src);
- }
-}
-#endif /* FEATURE_MESA_program_debug */
-
-
/**
* Fetch a 4-element float vector from the given source register.
* Apply swizzling and negating as needed.
@@ -236,24 +212,26 @@ fetch_vector4(const struct prog_src_register *source,
result[3] = src[GET_SWZ(source->Swizzle, 3)];
}
- if (source->NegateBase) {
- result[0] = -result[0];
- result[1] = -result[1];
- result[2] = -result[2];
- result[3] = -result[3];
- }
if (source->Abs) {
result[0] = FABSF(result[0]);
result[1] = FABSF(result[1]);
result[2] = FABSF(result[2]);
result[3] = FABSF(result[3]);
}
- if (source->NegateAbs) {
+ if (source->Negate) {
+ ASSERT(source->Negate == NEGATE_XYZW);
result[0] = -result[0];
result[1] = -result[1];
result[2] = -result[2];
result[3] = -result[3];
}
+
+#ifdef NAN_CHECK
+ assert(!IS_INF_OR_NAN(result[0]));
+ assert(!IS_INF_OR_NAN(result[0]));
+ assert(!IS_INF_OR_NAN(result[0]));
+ assert(!IS_INF_OR_NAN(result[0]));
+#endif
}
@@ -283,7 +261,7 @@ fetch_vector4ui(const struct prog_src_register *source,
result[3] = src[GET_SWZ(source->Swizzle, 3)];
}
- /* Note: no NegateBase, Abs, NegateAbs here */
+ /* Note: no Negate or Abs here */
}
@@ -323,19 +301,14 @@ fetch_vector4_deriv(GLcontext * ctx,
result[2] = deriv[GET_SWZ(source->Swizzle, 2)];
result[3] = deriv[GET_SWZ(source->Swizzle, 3)];
- if (source->NegateBase) {
- result[0] = -result[0];
- result[1] = -result[1];
- result[2] = -result[2];
- result[3] = -result[3];
- }
if (source->Abs) {
result[0] = FABSF(result[0]);
result[1] = FABSF(result[1]);
result[2] = FABSF(result[2]);
result[3] = FABSF(result[3]);
}
- if (source->NegateAbs) {
+ if (source->Negate) {
+ ASSERT(source->Negate == NEGATE_XYZW);
result[0] = -result[0];
result[1] = -result[1];
result[2] = -result[2];
@@ -360,13 +333,10 @@ fetch_vector1(const struct prog_src_register *source,
result[0] = src[GET_SWZ(source->Swizzle, 0)];
- if (source->NegateBase) {
- result[0] = -result[0];
- }
if (source->Abs) {
result[0] = FABSF(result[0]);
}
- if (source->NegateAbs) {
+ if (source->Negate) {
result[0] = -result[0];
}
}
@@ -516,6 +486,13 @@ store_vector4(const struct prog_instruction *inst,
}
}
+#ifdef NAN_CHECK
+ assert(!IS_INF_OR_NAN(value[0]));
+ assert(!IS_INF_OR_NAN(value[0]));
+ assert(!IS_INF_OR_NAN(value[0]));
+ assert(!IS_INF_OR_NAN(value[0]));
+#endif
+
if (writeMask & WRITEMASK_X)
dst[0] = value[0];
if (writeMask & WRITEMASK_Y)
@@ -633,10 +610,6 @@ _mesa_execute_program(GLcontext * ctx,
printf("execute program %u --------------------\n", program->Id);
}
-#if FEATURE_MESA_program_debug
- CurrentMachine = machine;
-#endif
-
if (program->Target == GL_VERTEX_PROGRAM_ARB) {
machine->EnvParams = ctx->VertexProgram.Parameters;
}
@@ -647,15 +620,6 @@ _mesa_execute_program(GLcontext * ctx,
for (pc = 0; pc < numInst; pc++) {
const struct prog_instruction *inst = program->Instructions + pc;
-#if FEATURE_MESA_program_debug
- if (ctx->FragmentProgram.CallbackEnabled &&
- ctx->FragmentProgram.Callback) {
- ctx->FragmentProgram.CurrentPosition = inst->StringPos;
- ctx->FragmentProgram.Callback(program->Target,
- ctx->FragmentProgram.CallbackData);
- }
-#endif
-
if (DEBUG_PROG) {
_mesa_print_instruction(inst);
}
@@ -873,7 +837,7 @@ _mesa_execute_program(GLcontext * ctx,
* result.z = result.x * APPX(result.y)
* We do what the ARB extension says.
*/
- q[2] = (GLfloat) pow(2.0, t[0]);
+ q[2] = (GLfloat) _mesa_pow(2.0, t[0]);
}
q[1] = t[0] - floor_t0;
q[3] = 1.0F;
@@ -882,10 +846,14 @@ _mesa_execute_program(GLcontext * ctx,
break;
case OPCODE_EX2: /* Exponential base 2 */
{
- GLfloat a[4], result[4];
+ GLfloat a[4], result[4], val;
fetch_vector1(&inst->SrcReg[0], machine, a);
- result[0] = result[1] = result[2] = result[3] =
- (GLfloat) _mesa_pow(2.0, a[0]);
+ val = (GLfloat) _mesa_pow(2.0, a[0]);
+ /*
+ if (IS_INF_OR_NAN(val))
+ val = 1.0e10;
+ */
+ result[0] = result[1] = result[2] = result[3] = val;
store_vector4(inst, machine, result);
}
break;
@@ -954,6 +922,11 @@ _mesa_execute_program(GLcontext * ctx,
{
GLfloat a[4];
fetch_vector4(&inst->SrcReg[0], machine, a);
+ if (DEBUG_PROG) {
+ printf("KIL if (%g %g %g %g) <= 0.0\n",
+ a[0], a[1], a[2], a[3]);
+ }
+
if (a[0] < 0.0F || a[1] < 0.0F || a[2] < 0.0F || a[3] < 0.0F) {
return GL_FALSE;
}
@@ -961,12 +934,17 @@ _mesa_execute_program(GLcontext * ctx,
break;
case OPCODE_LG2: /* log base 2 */
{
- GLfloat a[4], result[4];
+ GLfloat a[4], result[4], val;
fetch_vector1(&inst->SrcReg[0], machine, a);
/* The fast LOG2 macro doesn't meet the precision requirements.
*/
- result[0] = result[1] = result[2] = result[3] =
- (log(a[0]) * 1.442695F);
+ if (a[0] == 0.0F) {
+ val = 0.0F;
+ }
+ else {
+ val = log(a[0]) * 1.442695F;
+ }
+ result[0] = result[1] = result[2] = result[3] = val;
store_vector4(inst, machine, result);
}
break;
@@ -986,7 +964,7 @@ _mesa_execute_program(GLcontext * ctx,
if (a[1] == 0.0 && a[3] == 0.0)
result[2] = 1.0;
else
- result[2] = EXPF(a[3] * LOGF(a[1]));
+ result[2] = (GLfloat) _mesa_pow(a[1], a[3]);
}
else {
result[2] = 0.0;
@@ -1551,7 +1529,7 @@ _mesa_execute_program(GLcontext * ctx,
ASSERT(swz <= 3);
result[i] = src[swz];
}
- if (source->NegateBase & (1 << i))
+ if (source->Negate & (1 << i))
result[i] = -result[i];
}
store_vector4(inst, machine, result);
@@ -1577,8 +1555,8 @@ _mesa_execute_program(GLcontext * ctx,
case OPCODE_TXB: /* GL_ARB_fragment_program only */
/* Texel lookup with LOD bias */
{
- const struct gl_texture_unit *texUnit
- = &ctx->Texture.Unit[inst->TexSrcUnit];
+ const GLuint unit = machine->Samplers[inst->TexSrcUnit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
GLfloat texcoord[4], color[4], lodBias;
fetch_vector4(&inst->SrcReg[0], machine, texcoord);
@@ -1780,9 +1758,5 @@ _mesa_execute_program(GLcontext * ctx,
} /* for pc */
-#if FEATURE_MESA_program_debug
- CurrentMachine = NULL;
-#endif
-
return GL_TRUE;
}
diff --git a/src/mesa/shader/prog_execute.h b/src/mesa/shader/prog_execute.h
index 8ceb7b092e..adefc5439d 100644
--- a/src/mesa/shader/prog_execute.h
+++ b/src/mesa/shader/prog_execute.h
@@ -73,7 +73,7 @@ struct gl_program_machine
extern void
-_mesa_get_program_register(GLcontext *ctx, enum register_file file,
+_mesa_get_program_register(GLcontext *ctx, gl_register_file file,
GLuint index, GLfloat val[4]);
extern GLboolean
diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c
index 4a6d0d670a..44c961927a 100644
--- a/src/mesa/shader/prog_instruction.c
+++ b/src/mesa/shader/prog_instruction.c
@@ -254,6 +254,7 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = {
GLuint
_mesa_num_inst_src_regs(gl_inst_opcode opcode)
{
+ ASSERT(opcode < MAX_OPCODE);
ASSERT(opcode == InstInfo[opcode].Opcode);
ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode);
return InstInfo[opcode].NumSrcRegs;
@@ -266,6 +267,7 @@ _mesa_num_inst_src_regs(gl_inst_opcode opcode)
GLuint
_mesa_num_inst_dst_regs(gl_inst_opcode opcode)
{
+ ASSERT(opcode < MAX_OPCODE);
ASSERT(opcode == InstInfo[opcode].Opcode);
ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode);
return InstInfo[opcode].NumDstRegs;
@@ -284,12 +286,67 @@ _mesa_is_tex_instruction(gl_inst_opcode opcode)
/**
+ * Check if there's a potential src/dst register data dependency when
+ * using SOA execution.
+ * Example:
+ * MOV T, T.yxwz;
+ * This would expand into:
+ * MOV t0, t1;
+ * MOV t1, t0;
+ * MOV t2, t3;
+ * MOV t3, t2;
+ * The second instruction will have the wrong value for t0 if executed as-is.
+ */
+GLboolean
+_mesa_check_soa_dependencies(const struct prog_instruction *inst)
+{
+ GLuint i, chan;
+
+ if (inst->DstReg.WriteMask == WRITEMASK_X ||
+ inst->DstReg.WriteMask == WRITEMASK_Y ||
+ inst->DstReg.WriteMask == WRITEMASK_Z ||
+ inst->DstReg.WriteMask == WRITEMASK_W ||
+ inst->DstReg.WriteMask == 0x0) {
+ /* no chance of data dependency */
+ return GL_FALSE;
+ }
+
+ /* loop over src regs */
+ for (i = 0; i < 3; i++) {
+ if (inst->SrcReg[i].File == inst->DstReg.File &&
+ inst->SrcReg[i].Index == inst->DstReg.Index) {
+ /* loop over dest channels */
+ GLuint channelsWritten = 0x0;
+ for (chan = 0; chan < 4; chan++) {
+ if (inst->DstReg.WriteMask & (1 << chan)) {
+ /* check if we're reading a channel that's been written */
+ GLuint swizzle = GET_SWZ(inst->SrcReg[i].Swizzle, chan);
+ if (swizzle <= SWIZZLE_W &&
+ (channelsWritten & (1 << swizzle))) {
+ return GL_TRUE;
+ }
+
+ channelsWritten |= (1 << chan);
+ }
+ }
+ }
+ }
+ return GL_FALSE;
+}
+
+
+/**
* Return string name for given program opcode.
*/
const char *
_mesa_opcode_string(gl_inst_opcode opcode)
{
- ASSERT(opcode < MAX_OPCODE);
- return InstInfo[opcode].Name;
+ if (opcode < MAX_OPCODE)
+ return InstInfo[opcode].Name;
+ else {
+ static char s[20];
+ _mesa_snprintf(s, sizeof(s), "OP%u", opcode);
+ return s;
+ }
}
diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h
index 268afc528c..39a221eeab 100644
--- a/src/mesa/shader/prog_instruction.h
+++ b/src/mesa/shader/prog_instruction.h
@@ -38,6 +38,9 @@
#define PROG_INSTRUCTION_H
+#include "main/mfeatures.h"
+
+
/**
* Swizzle indexes.
* Do not change!
@@ -130,6 +133,7 @@
#define NEGATE_Y 0x2
#define NEGATE_Z 0x4
#define NEGATE_W 0x8
+#define NEGATE_XYZ 0x7
#define NEGATE_XYZW 0xf
#define NEGATE_NONE 0x0
/*@}*/
@@ -240,46 +244,33 @@ typedef enum prog_opcode {
/**
+ * Number of bits for the src/dst register Index field.
+ * This limits the size of temp/uniform register files.
+ */
+#define INST_INDEX_BITS 10
+
+
+/**
* Instruction source register.
*/
struct prog_src_register
{
GLuint File:4; /**< One of the PROGRAM_* register file values. */
- GLint Index:9; /**< May be negative for relative addressing. */
+ GLint Index:(INST_INDEX_BITS+1); /**< Extra bit here for sign bit.
+ * May be negative for relative addressing.
+ */
GLuint Swizzle:12;
GLuint RelAddr:1;
- /**
- * \name Source register "sign" control.
- *
- * The ARB and NV extensions allow varrying degrees of control over the
- * sign of the source vector components. These values allow enough control
- * for all flavors of the extensions.
- */
- /*@{*/
- /**
- * Per-component negation for the SWZ instruction. For non-SWZ
- * instructions the only possible values are NEGATE_XYZW and NEGATE_NONE.
- *
- * \since
- * ARB_vertex_program, ARB_fragment_program
- */
- GLuint NegateBase:4;
-
- /**
- * Take the component-wise absolute value.
- *
- * \since
- * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
- * NV_vertex_program2_option.
- */
+ /** Take the component-wise absolute value */
GLuint Abs:1;
/**
- * Post-absolute value negation (all components).
+ * Post-Abs negation.
+ * This will either be NEGATE_NONE or NEGATE_XYZW, except for the SWZ
+ * instruction which allows per-component negation.
*/
- GLuint NegateAbs:1;
- /*@}*/
+ GLuint Negate:4;
};
@@ -289,7 +280,7 @@ struct prog_src_register
struct prog_dst_register
{
GLuint File:4; /**< One of the PROGRAM_* register file values */
- GLuint Index:8;
+ GLuint Index:INST_INDEX_BITS; /**< Unsigned, never negative */
GLuint WriteMask:4;
GLuint RelAddr:1;
@@ -313,17 +304,16 @@ struct prog_dst_register
* Condition code swizzle value.
*/
GLuint CondSwizzle:12;
-
+
/**
* Selects the condition code register to use for conditional destination
* update masking. In NV_fragmnet_program or NV_vertex_program2 mode, only
- * condition code register 0 is available. In NV_vertex_program3 mode,
+ * condition code register 0 is available. In NV_vertex_program3 mode,
* condition code registers 0 and 1 are available.
*/
GLuint CondSrc:1;
/*@}*/
-
- GLuint pad:30;
+ GLuint pad:28;
};
@@ -333,14 +323,6 @@ struct prog_dst_register
struct prog_instruction
{
gl_inst_opcode Opcode;
-#if FEATURE_MESA_program_debug
- GLshort StringPos;
-#endif
- /**
- * Arbitrary data. Used for the PRINT, CAL, and BRA instructions.
- */
- void *Data;
-
struct prog_src_register SrcReg[3];
struct prog_dst_register DstReg;
@@ -378,9 +360,9 @@ struct prog_instruction
* NV_fragment_program, NV_fragment_program_option, NV_vertex_program3.
*/
GLuint SaturateMode:2;
-
+
/**
- * Per-instruction selectable precision.
+ * Per-instruction selectable precision: FLOAT32, FLOAT16, FIXED12.
*
* \since
* NV_fragment_program, NV_fragment_program_option.
@@ -388,43 +370,36 @@ struct prog_instruction
GLuint Precision:3;
/**
- * \name Texture source controls.
- *
- * The texture source controls are only used with the \c TEX, \c TXD,
- * \c TXL, and \c TXP instructions.
- *
- * \since
- * ARB_fragment_program, NV_fragment_program, NV_vertex_program3.
+ * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions.
*/
/*@{*/
- /**
- * Source texture unit. OpenGL supports a maximum of 32 texture
- * units.
- */
+ /** Source texture unit. */
GLuint TexSrcUnit:5;
-
- /**
- * Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX.
- */
+
+ /** Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX */
GLuint TexSrcTarget:3;
+
+ /** True if tex instruction should do shadow comparison */
+ GLuint TexShadow:1;
/*@}*/
/**
* For BRA and CAL instructions, the location to jump to.
* For BGNLOOP, points to ENDLOOP (and vice-versa).
* For BRK, points to BGNLOOP (which points to ENDLOOP).
- * For IF, points to else or endif.
- * For ELSE, points to endif.
+ * For IF, points to ELSE or ENDIF.
+ * For ELSE, points to ENDIF.
*/
GLint BranchTarget;
- /**
- * For TEX instructions in shaders, the sampler to use for the
- * texture lookup.
- */
- GLint Sampler;
-
+ /** for debugging purposes */
const char *Comment;
+
+ /** Arbitrary data. Used for OPCODE_PRINT and some drivers */
+ void *Data;
+
+ /** for driver use (try to remove someday) */
+ GLint Aux;
};
@@ -454,6 +429,9 @@ _mesa_num_inst_dst_regs(gl_inst_opcode opcode);
extern GLboolean
_mesa_is_tex_instruction(gl_inst_opcode opcode);
+extern GLboolean
+_mesa_check_soa_dependencies(const struct prog_instruction *inst);
+
extern const char *
_mesa_opcode_string(gl_inst_opcode opcode);
diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c
new file mode 100644
index 0000000000..be903106a0
--- /dev/null
+++ b/src/mesa/shader/prog_optimize.c
@@ -0,0 +1,832 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION 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/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "program.h"
+#include "prog_instruction.h"
+#include "prog_optimize.h"
+#include "prog_print.h"
+
+
+#define MAX_LOOP_NESTING 50
+
+
+static GLboolean dbg = GL_FALSE;
+
+
+/**
+ * In 'prog' remove instruction[i] if removeFlags[i] == TRUE.
+ * \return number of instructions removed
+ */
+static GLuint
+remove_instructions(struct gl_program *prog, const GLboolean *removeFlags)
+{
+ GLint i, removeEnd = 0, removeCount = 0;
+ GLuint totalRemoved = 0;
+
+ /* go backward */
+ for (i = prog->NumInstructions - 1; i >= 0; i--) {
+ if (removeFlags[i]) {
+ totalRemoved++;
+ if (removeCount == 0) {
+ /* begin a run of instructions to remove */
+ removeEnd = i;
+ removeCount = 1;
+ }
+ else {
+ /* extend the run of instructions to remove */
+ removeCount++;
+ }
+ }
+ else {
+ /* don't remove this instruction, but check if the preceeding
+ * instructions are to be removed.
+ */
+ if (removeCount > 0) {
+ GLint removeStart = removeEnd - removeCount + 1;
+ _mesa_delete_instructions(prog, removeStart, removeCount);
+ removeStart = removeCount = 0; /* reset removal info */
+ }
+ }
+ }
+ return totalRemoved;
+}
+
+
+/**
+ * Remap register indexes according to map.
+ * \param prog the program to search/replace
+ * \param file the type of register file to search/replace
+ * \param map maps old register indexes to new indexes
+ */
+static void
+replace_regs(struct gl_program *prog, gl_register_file file, const GLint map[])
+{
+ GLuint i;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == file) {
+ GLuint index = inst->SrcReg[j].Index;
+ ASSERT(map[index] >= 0);
+ inst->SrcReg[j].Index = map[index];
+ }
+ }
+ if (inst->DstReg.File == file) {
+ const GLuint index = inst->DstReg.Index;
+ ASSERT(map[index] >= 0);
+ inst->DstReg.Index = map[index];
+ }
+ }
+}
+
+
+/**
+ * Consolidate temporary registers to use low numbers. For example, if the
+ * shader only uses temps 4, 5, 8, replace them with 0, 1, 2.
+ */
+static void
+_mesa_consolidate_registers(struct gl_program *prog)
+{
+ GLboolean tempUsed[MAX_PROGRAM_TEMPS];
+ GLint tempMap[MAX_PROGRAM_TEMPS];
+ GLuint tempMax = 0, i;
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin register consolidation\n");
+ }
+
+ memset(tempUsed, 0, sizeof(tempUsed));
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ tempMap[i] = -1;
+ }
+
+ /* set tempUsed[i] if temporary [i] is referenced */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->SrcReg[j].Index;
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+ tempUsed[index] = GL_TRUE;
+ tempMax = MAX2(tempMax, index);
+ break;
+ }
+ }
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->DstReg.Index;
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+ tempUsed[index] = GL_TRUE;
+ tempMax = MAX2(tempMax, index);
+ }
+ }
+
+ /* allocate a new index for each temp that's used */
+ {
+ GLuint freeTemp = 0;
+ for (i = 0; i <= tempMax; i++) {
+ if (tempUsed[i]) {
+ tempMap[i] = freeTemp++;
+ /*_mesa_printf("replace %u with %u\n", i, tempMap[i]);*/
+ }
+ }
+ if (freeTemp == tempMax + 1) {
+ /* no consolidation possible */
+ return;
+ }
+ if (dbg) {
+ _mesa_printf("Replace regs 0..%u with 0..%u\n", tempMax, freeTemp-1);
+ }
+ }
+
+ replace_regs(prog, PROGRAM_TEMPORARY, tempMap);
+
+ if (dbg) {
+ _mesa_printf("Optimize: End register consolidation\n");
+ }
+}
+
+
+/**
+ * Remove dead instructions from the given program.
+ * This is very primitive for now. Basically look for temp registers
+ * that are written to but never read. Remove any instructions that
+ * write to such registers. Be careful with condition code setters.
+ */
+static void
+_mesa_remove_dead_code(struct gl_program *prog)
+{
+ GLboolean tempWritten[MAX_PROGRAM_TEMPS], tempRead[MAX_PROGRAM_TEMPS];
+ GLboolean *removeInst; /* per-instruction removal flag */
+ GLuint i, rem;
+
+ memset(tempWritten, 0, sizeof(tempWritten));
+ memset(tempRead, 0, sizeof(tempRead));
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin dead code removal\n");
+ /*_mesa_print_program(prog);*/
+ }
+
+ removeInst = (GLboolean *)
+ _mesa_calloc(prog->NumInstructions * sizeof(GLboolean));
+
+ /* Determine which temps are read and written */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+
+ /* check src regs */
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->SrcReg[j].Index;
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+
+ if (inst->SrcReg[j].RelAddr) {
+ if (dbg)
+ _mesa_printf("abort remove dead code (indirect temp)\n");
+ return;
+ }
+
+ tempRead[index] = GL_TRUE;
+ }
+ }
+
+ /* check dst reg */
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->DstReg.Index;
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+
+ if (inst->DstReg.RelAddr) {
+ if (dbg)
+ _mesa_printf("abort remove dead code (indirect temp)\n");
+ return;
+ }
+
+ tempWritten[index] = GL_TRUE;
+ if (inst->CondUpdate) {
+ /* If we're writing to this register and setting condition
+ * codes we cannot remove the instruction. Prevent removal
+ * by setting the 'read' flag.
+ */
+ tempRead[index] = GL_TRUE;
+ }
+ }
+ }
+
+ if (dbg) {
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (tempWritten[i] && !tempRead[i])
+ _mesa_printf("Remove writes to tmp %u\n", i);
+ }
+ }
+
+ /* find instructions that write to dead registers, flag for removal */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ GLint index = inst->DstReg.Index;
+ removeInst[i] = (tempWritten[index] && !tempRead[index]);
+ if (dbg && removeInst[i]) {
+ _mesa_printf("Remove inst %u: ", i);
+ _mesa_print_instruction(inst);
+ }
+ }
+ }
+
+ /* now remove the instructions which aren't needed */
+ rem = remove_instructions(prog, removeInst);
+
+ _mesa_free(removeInst);
+
+ if (dbg) {
+ _mesa_printf("Optimize: End dead code removal. %u instructions removed\n", rem);
+ /*_mesa_print_program(prog);*/
+ }
+}
+
+
+enum temp_use
+{
+ READ,
+ WRITE,
+ FLOW,
+ END
+};
+
+/**
+ * Scan forward in program from 'start' for the next occurance of TEMP[index].
+ * Return READ, WRITE, FLOW or END to indicate the next usage or an indicator
+ * that we can't look further.
+ */
+static enum temp_use
+find_next_temp_use(const struct gl_program *prog, GLuint start, GLuint index)
+{
+ GLuint i;
+
+ for (i = start; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ switch (inst->Opcode) {
+ case OPCODE_BGNLOOP:
+ case OPCODE_ENDLOOP:
+ case OPCODE_BGNSUB:
+ case OPCODE_ENDSUB:
+ return FLOW;
+ default:
+ {
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY &&
+ inst->SrcReg[j].Index == index)
+ return READ;
+ }
+ if (inst->DstReg.File == PROGRAM_TEMPORARY &&
+ inst->DstReg.Index == index)
+ return WRITE;
+ }
+ }
+ }
+
+ return END;
+}
+
+
+/**
+ * Try to remove extraneous MOV instructions from the given program.
+ */
+static void
+_mesa_remove_extra_moves(struct gl_program *prog)
+{
+ GLboolean *removeInst; /* per-instruction removal flag */
+ GLuint i, rem, loopNesting = 0, subroutineNesting = 0;
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin remove extra moves\n");
+ _mesa_print_program(prog);
+ }
+
+ removeInst = (GLboolean *)
+ _mesa_calloc(prog->NumInstructions * sizeof(GLboolean));
+
+ /*
+ * Look for sequences such as this:
+ * FOO tmpX, arg0, arg1;
+ * MOV tmpY, tmpX;
+ * and convert into:
+ * FOO tmpY, arg0, arg1;
+ */
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+
+ switch (inst->Opcode) {
+ case OPCODE_BGNLOOP:
+ loopNesting++;
+ break;
+ case OPCODE_ENDLOOP:
+ loopNesting--;
+ break;
+ case OPCODE_BGNSUB:
+ subroutineNesting++;
+ break;
+ case OPCODE_ENDSUB:
+ subroutineNesting--;
+ break;
+ case OPCODE_MOV:
+ if (i > 0 &&
+ loopNesting == 0 &&
+ subroutineNesting == 0 &&
+ inst->SrcReg[0].File == PROGRAM_TEMPORARY &&
+ inst->SrcReg[0].Swizzle == SWIZZLE_XYZW) {
+ /* see if this MOV can be removed */
+ const GLuint tempIndex = inst->SrcReg[0].Index;
+ struct prog_instruction *prevInst;
+ GLuint prevI;
+
+ /* get pointer to previous instruction */
+ prevI = i - 1;
+ while (removeInst[prevI] && prevI > 0)
+ prevI--;
+ prevInst = prog->Instructions + prevI;
+
+ if (prevInst->DstReg.File == PROGRAM_TEMPORARY &&
+ prevInst->DstReg.Index == tempIndex &&
+ prevInst->DstReg.WriteMask == WRITEMASK_XYZW) {
+
+ enum temp_use next_use =
+ find_next_temp_use(prog, i + 1, tempIndex);
+
+ if (next_use == WRITE || next_use == END) {
+ /* OK, we can safely remove this MOV instruction.
+ * Transform:
+ * prevI: FOO tempIndex, x, y;
+ * i: MOV z, tempIndex;
+ * Into:
+ * prevI: FOO z, x, y;
+ */
+
+ /* patch up prev inst */
+ prevInst->DstReg.File = inst->DstReg.File;
+ prevInst->DstReg.Index = inst->DstReg.Index;
+
+ /* flag this instruction for removal */
+ removeInst[i] = GL_TRUE;
+
+ if (dbg) {
+ _mesa_printf("Remove MOV at %u\n", i);
+ _mesa_printf("new prev inst %u: ", prevI);
+ _mesa_print_instruction(prevInst);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ ; /* nothing */
+ }
+ }
+
+ /* now remove the instructions which aren't needed */
+ rem = remove_instructions(prog, removeInst);
+
+ if (dbg) {
+ _mesa_printf("Optimize: End remove extra moves. %u instructions removed\n", rem);
+ /*_mesa_print_program(prog);*/
+ }
+}
+
+
+/** A live register interval */
+struct interval
+{
+ GLuint Reg; /** The temporary register index */
+ GLuint Start, End; /** Start/end instruction numbers */
+};
+
+
+/** A list of register intervals */
+struct interval_list
+{
+ GLuint Num;
+ struct interval Intervals[MAX_PROGRAM_TEMPS];
+};
+
+
+static void
+append_interval(struct interval_list *list, const struct interval *inv)
+{
+ list->Intervals[list->Num++] = *inv;
+}
+
+
+/** Insert interval inv into list, sorted by interval end */
+static void
+insert_interval_by_end(struct interval_list *list, const struct interval *inv)
+{
+ /* XXX we could do a binary search insertion here since list is sorted */
+ GLint i = list->Num - 1;
+ while (i >= 0 && list->Intervals[i].End > inv->End) {
+ list->Intervals[i + 1] = list->Intervals[i];
+ i--;
+ }
+ list->Intervals[i + 1] = *inv;
+ list->Num++;
+
+#ifdef DEBUG
+ {
+ GLuint i;
+ for (i = 0; i + 1 < list->Num; i++) {
+ ASSERT(list->Intervals[i].End <= list->Intervals[i + 1].End);
+ }
+ }
+#endif
+}
+
+
+/** Remove the given interval from the interval list */
+static void
+remove_interval(struct interval_list *list, const struct interval *inv)
+{
+ /* XXX we could binary search since list is sorted */
+ GLuint k;
+ for (k = 0; k < list->Num; k++) {
+ if (list->Intervals[k].Reg == inv->Reg) {
+ /* found, remove it */
+ ASSERT(list->Intervals[k].Start == inv->Start);
+ ASSERT(list->Intervals[k].End == inv->End);
+ while (k < list->Num - 1) {
+ list->Intervals[k] = list->Intervals[k + 1];
+ k++;
+ }
+ list->Num--;
+ return;
+ }
+ }
+}
+
+
+/** called by qsort() */
+static int
+compare_start(const void *a, const void *b)
+{
+ const struct interval *ia = (const struct interval *) a;
+ const struct interval *ib = (const struct interval *) b;
+ if (ia->Start < ib->Start)
+ return -1;
+ else if (ia->Start > ib->Start)
+ return +1;
+ else
+ return 0;
+}
+
+/** sort the interval list according to interval starts */
+static void
+sort_interval_list_by_start(struct interval_list *list)
+{
+ qsort(list->Intervals, list->Num, sizeof(struct interval), compare_start);
+#ifdef DEBUG
+ {
+ GLuint i;
+ for (i = 0; i + 1 < list->Num; i++) {
+ ASSERT(list->Intervals[i].Start <= list->Intervals[i + 1].Start);
+ }
+ }
+#endif
+}
+
+
+/**
+ * Update the intermediate interval info for register 'index' and
+ * instruction 'ic'.
+ */
+static void
+update_interval(GLint intBegin[], GLint intEnd[], GLuint index, GLuint ic)
+{
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+ if (intBegin[index] == -1) {
+ ASSERT(intEnd[index] == -1);
+ intBegin[index] = intEnd[index] = ic;
+ }
+ else {
+ intEnd[index] = ic;
+ }
+}
+
+
+/**
+ * Find first/last instruction that references each temporary register.
+ */
+GLboolean
+_mesa_find_temp_intervals(const struct prog_instruction *instructions,
+ GLuint numInstructions,
+ GLint intBegin[MAX_PROGRAM_TEMPS],
+ GLint intEnd[MAX_PROGRAM_TEMPS])
+{
+ struct loop_info
+ {
+ GLuint Start, End; /**< Start, end instructions of loop */
+ };
+ struct loop_info loopStack[MAX_LOOP_NESTING];
+ GLuint loopStackDepth = 0;
+ GLuint i;
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++){
+ intBegin[i] = intEnd[i] = -1;
+ }
+
+ /* Scan instructions looking for temporary registers */
+ for (i = 0; i < numInstructions; i++) {
+ const struct prog_instruction *inst = instructions + i;
+ if (inst->Opcode == OPCODE_BGNLOOP) {
+ loopStack[loopStackDepth].Start = i;
+ loopStack[loopStackDepth].End = inst->BranchTarget;
+ loopStackDepth++;
+ }
+ else if (inst->Opcode == OPCODE_ENDLOOP) {
+ loopStackDepth--;
+ }
+ else if (inst->Opcode == OPCODE_CAL) {
+ return GL_FALSE;
+ }
+ else {
+ const GLuint numSrc = 3;/*_mesa_num_inst_src_regs(inst->Opcode);*/
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->SrcReg[j].Index;
+ if (inst->SrcReg[j].RelAddr)
+ return GL_FALSE;
+ update_interval(intBegin, intEnd, index, i);
+ if (loopStackDepth > 0) {
+ /* extend temp register's interval to end of loop */
+ GLuint loopEnd = loopStack[loopStackDepth - 1].End;
+ update_interval(intBegin, intEnd, index, loopEnd);
+ }
+ }
+ }
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->DstReg.Index;
+ if (inst->DstReg.RelAddr)
+ return GL_FALSE;
+ update_interval(intBegin, intEnd, index, i);
+ if (loopStackDepth > 0) {
+ /* extend temp register's interval to end of loop */
+ GLuint loopEnd = loopStack[loopStackDepth - 1].End;
+ update_interval(intBegin, intEnd, index, loopEnd);
+ }
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Find the live intervals for each temporary register in the program.
+ * For register R, the interval [A,B] indicates that R is referenced
+ * from instruction A through instruction B.
+ * Special consideration is needed for loops and subroutines.
+ * \return GL_TRUE if success, GL_FALSE if we cannot proceed for some reason
+ */
+static GLboolean
+find_live_intervals(struct gl_program *prog,
+ struct interval_list *liveIntervals)
+{
+ GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS];
+ GLuint i;
+
+ /*
+ * Note: we'll return GL_FALSE below if we find relative indexing
+ * into the TEMP register file. We can't handle that yet.
+ * We also give up on subroutines for now.
+ */
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin find intervals\n");
+ }
+
+ /* build intermediate arrays */
+ if (!_mesa_find_temp_intervals(prog->Instructions, prog->NumInstructions,
+ intBegin, intEnd))
+ return GL_FALSE;
+
+ /* Build live intervals list from intermediate arrays */
+ liveIntervals->Num = 0;
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (intBegin[i] >= 0) {
+ struct interval inv;
+ inv.Reg = i;
+ inv.Start = intBegin[i];
+ inv.End = intEnd[i];
+ append_interval(liveIntervals, &inv);
+ }
+ }
+
+ /* Sort the list according to interval starts */
+ sort_interval_list_by_start(liveIntervals);
+
+ if (dbg) {
+ /* print interval info */
+ for (i = 0; i < liveIntervals->Num; i++) {
+ const struct interval *inv = liveIntervals->Intervals + i;
+ _mesa_printf("Reg[%d] live [%d, %d]:",
+ inv->Reg, inv->Start, inv->End);
+ if (1) {
+ int j;
+ for (j = 0; j < inv->Start; j++)
+ _mesa_printf(" ");
+ for (j = inv->Start; j <= inv->End; j++)
+ _mesa_printf("x");
+ }
+ _mesa_printf("\n");
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/** Scan the array of used register flags to find free entry */
+static GLint
+alloc_register(GLboolean usedRegs[MAX_PROGRAM_TEMPS])
+{
+ GLuint k;
+ for (k = 0; k < MAX_PROGRAM_TEMPS; k++) {
+ if (!usedRegs[k]) {
+ usedRegs[k] = GL_TRUE;
+ return k;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * This function implements "Linear Scan Register Allocation" to reduce
+ * the number of temporary registers used by the program.
+ *
+ * We compute the "live interval" for all temporary registers then
+ * examine the overlap of the intervals to allocate new registers.
+ * Basically, if two intervals do not overlap, they can use the same register.
+ */
+static void
+_mesa_reallocate_registers(struct gl_program *prog)
+{
+ struct interval_list liveIntervals;
+ GLint registerMap[MAX_PROGRAM_TEMPS];
+ GLboolean usedRegs[MAX_PROGRAM_TEMPS];
+ GLuint i;
+ GLint maxTemp = -1;
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin live-interval register reallocation\n");
+ _mesa_print_program(prog);
+ }
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++){
+ registerMap[i] = -1;
+ usedRegs[i] = GL_FALSE;
+ }
+
+ if (!find_live_intervals(prog, &liveIntervals)) {
+ if (dbg)
+ _mesa_printf("Aborting register reallocation\n");
+ return;
+ }
+
+ {
+ struct interval_list activeIntervals;
+ activeIntervals.Num = 0;
+
+ /* loop over live intervals, allocating a new register for each */
+ for (i = 0; i < liveIntervals.Num; i++) {
+ const struct interval *live = liveIntervals.Intervals + i;
+
+ if (dbg)
+ _mesa_printf("Consider register %u\n", live->Reg);
+
+ /* Expire old intervals. Intervals which have ended with respect
+ * to the live interval can have their remapped registers freed.
+ */
+ {
+ GLint j;
+ for (j = 0; j < activeIntervals.Num; j++) {
+ const struct interval *inv = activeIntervals.Intervals + j;
+ if (inv->End >= live->Start) {
+ /* Stop now. Since the activeInterval list is sorted
+ * we know we don't have to go further.
+ */
+ break;
+ }
+ else {
+ /* Interval 'inv' has expired */
+ const GLint regNew = registerMap[inv->Reg];
+ ASSERT(regNew >= 0);
+
+ if (dbg)
+ _mesa_printf(" expire interval for reg %u\n", inv->Reg);
+
+ /* remove interval j from active list */
+ remove_interval(&activeIntervals, inv);
+ j--; /* counter-act j++ in for-loop above */
+
+ /* return register regNew to the free pool */
+ if (dbg)
+ _mesa_printf(" free reg %d\n", regNew);
+ ASSERT(usedRegs[regNew] == GL_TRUE);
+ usedRegs[regNew] = GL_FALSE;
+ }
+ }
+ }
+
+ /* find a free register for this live interval */
+ {
+ const GLint k = alloc_register(usedRegs);
+ if (k < 0) {
+ /* out of registers, give up */
+ return;
+ }
+ registerMap[live->Reg] = k;
+ maxTemp = MAX2(maxTemp, k);
+ if (dbg)
+ _mesa_printf(" remap register %u -> %d\n", live->Reg, k);
+ }
+
+ /* Insert this live interval into the active list which is sorted
+ * by increasing end points.
+ */
+ insert_interval_by_end(&activeIntervals, live);
+ }
+ }
+
+ if (maxTemp + 1 < liveIntervals.Num) {
+ /* OK, we've reduced the number of registers needed.
+ * Scan the program and replace all the old temporary register
+ * indexes with the new indexes.
+ */
+ replace_regs(prog, PROGRAM_TEMPORARY, registerMap);
+
+ prog->NumTemporaries = maxTemp + 1;
+ }
+
+ if (dbg) {
+ _mesa_printf("Optimize: End live-interval register reallocation\n");
+ _mesa_printf("Num temp regs before: %u after: %u\n",
+ liveIntervals.Num, maxTemp + 1);
+ _mesa_print_program(prog);
+ }
+}
+
+
+/**
+ * Apply optimizations to the given program to eliminate unnecessary
+ * instructions, temp regs, etc.
+ */
+void
+_mesa_optimize_program(GLcontext *ctx, struct gl_program *program)
+{
+ if (1)
+ _mesa_remove_dead_code(program);
+
+ if (0) /* not tested much yet */
+ _mesa_remove_extra_moves(program);
+
+ if (0)
+ _mesa_consolidate_registers(program);
+ else
+ _mesa_reallocate_registers(program);
+}
diff --git a/src/mesa/shader/prog_optimize.h b/src/mesa/shader/prog_optimize.h
new file mode 100644
index 0000000000..43894a2723
--- /dev/null
+++ b/src/mesa/shader/prog_optimize.h
@@ -0,0 +1,45 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION 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 PROG_OPT_H
+#define PROG_OPT_H
+
+
+#include "main/config.h"
+
+
+struct gl_program;
+struct prog_instruction;
+
+
+extern GLboolean
+_mesa_find_temp_intervals(const struct prog_instruction *instructions,
+ GLuint numInstructions,
+ GLint intBegin[MAX_PROGRAM_TEMPS],
+ GLint intEnd[MAX_PROGRAM_TEMPS]);
+
+extern void
+_mesa_optimize_program(GLcontext *ctx, struct gl_program *program);
+
+#endif
diff --git a/src/mesa/shader/prog_parameter.c b/src/mesa/shader/prog_parameter.c
index dc48e84ab2..6b9e73b2cb 100644
--- a/src/mesa/shader/prog_parameter.c
+++ b/src/mesa/shader/prog_parameter.c
@@ -44,6 +44,34 @@ _mesa_new_parameter_list(void)
}
+struct gl_program_parameter_list *
+_mesa_new_parameter_list_sized(unsigned size)
+{
+ struct gl_program_parameter_list *p = _mesa_new_parameter_list();
+
+ if ((p != NULL) && (size != 0)) {
+ p->Size = size;
+
+ /* alloc arrays */
+ p->Parameters = (struct gl_program_parameter *)
+ _mesa_calloc(size * sizeof(struct gl_program_parameter));
+
+ p->ParameterValues = (GLfloat (*)[4])
+ _mesa_align_malloc(size * 4 *sizeof(GLfloat), 16);
+
+
+ if ((p->Parameters == NULL) || (p->ParameterValues == NULL)) {
+ _mesa_free(p->Parameters);
+ _mesa_align_free(p->ParameterValues);
+ _mesa_free(p);
+ p = NULL;
+ }
+ }
+
+ return p;
+}
+
+
/**
* Free a parameter list and all its parameters
*/
@@ -78,7 +106,7 @@ _mesa_free_parameter_list(struct gl_program_parameter_list *paramList)
*/
GLint
_mesa_add_parameter(struct gl_program_parameter_list *paramList,
- enum register_file type, const char *name,
+ gl_register_file type, const char *name,
GLuint size, GLenum datatype, const GLfloat *values,
const gl_state_index state[STATE_LENGTH],
GLbitfield flags)
@@ -178,15 +206,20 @@ _mesa_add_named_constant(struct gl_program_parameter_list *paramList,
const char *name, const GLfloat values[4],
GLuint size)
{
-#if 0 /* disable this for now -- we need to save the name! */
+ /* first check if this is a duplicate constant */
GLint pos;
- GLuint swizzle;
- ASSERT(size == 4); /* XXX future feature */
- /* check if we already have this constant */
- if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) {
- return pos;
+ for (pos = 0; pos < paramList->NumParameters; pos++) {
+ const GLfloat *pvals = paramList->ParameterValues[pos];
+ if (pvals[0] == values[0] &&
+ pvals[1] == values[1] &&
+ pvals[2] == values[2] &&
+ pvals[3] == values[3] &&
+ _mesa_strcmp(paramList->Parameters[pos].Name, name) == 0) {
+ /* Same name and value is already in the param list - reuse it */
+ return pos;
+ }
}
-#endif
+ /* not found, add new parameter */
return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name,
size, GL_NONE, values, NULL, 0x0);
}
@@ -322,15 +355,16 @@ _mesa_add_sampler(struct gl_program_parameter_list *paramList,
else {
GLuint i;
const GLint size = 1; /* a sampler is basically a texture unit number */
- GLfloat value;
+ GLfloat value[4];
GLint numSamplers = 0;
for (i = 0; i < paramList->NumParameters; i++) {
if (paramList->Parameters[i].Type == PROGRAM_SAMPLER)
numSamplers++;
}
- value = (GLfloat) numSamplers;
+ value[0] = (GLfloat) numSamplers;
+ value[1] = value[2] = value[3] = 0.0F;
(void) _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name,
- size, datatype, &value, NULL, 0x0);
+ size, datatype, value, NULL, 0x0);
return numSamplers;
}
}
@@ -424,7 +458,7 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList,
const gl_state_index stateTokens[STATE_LENGTH])
{
const GLuint size = 4; /* XXX fix */
- const char *name;
+ char *name;
GLint index;
/* Check if the state reference is already in the list */
@@ -451,7 +485,7 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList,
paramList->StateFlags |= _mesa_program_state_flags(stateTokens);
/* free name string here since we duplicated it in add_parameter() */
- _mesa_free((void *) name);
+ _mesa_free(name);
return index;
}
@@ -517,7 +551,7 @@ _mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList,
* swizzling to find a match.
* \param list the parameter list to search
* \param v the float vector to search for
- * \param size number of element in v
+ * \param vSize number of element in v
* \param posOut returns the position of the constant, if found
* \param swizzleOut returns a swizzle mask describing location of the
* vector elements if found.
@@ -681,7 +715,7 @@ _mesa_combine_parameter_lists(const struct gl_program_parameter_list *listA,
*/
GLuint
_mesa_longest_parameter_name(const struct gl_program_parameter_list *list,
- enum register_file type)
+ gl_register_file type)
{
GLuint i, maxLen = 0;
if (!list)
@@ -702,7 +736,7 @@ _mesa_longest_parameter_name(const struct gl_program_parameter_list *list,
*/
GLuint
_mesa_num_parameters_of_type(const struct gl_program_parameter_list *list,
- enum register_file type)
+ gl_register_file type)
{
GLuint i, count = 0;
if (list) {
diff --git a/src/mesa/shader/prog_parameter.h b/src/mesa/shader/prog_parameter.h
index 200f2c0045..d1fcf47e61 100644
--- a/src/mesa/shader/prog_parameter.h
+++ b/src/mesa/shader/prog_parameter.h
@@ -54,7 +54,7 @@
struct gl_program_parameter
{
const char *Name; /**< Null-terminated string */
- enum register_file Type; /**< PROGRAM_NAMED_PARAM, CONSTANT or STATE_VAR */
+ gl_register_file Type; /**< PROGRAM_NAMED_PARAM, CONSTANT or STATE_VAR */
GLenum DataType; /**< GL_FLOAT, GL_FLOAT_VEC2, etc */
GLuint Size; /**< Number of components (1..4) */
GLboolean Used; /**< Helper flag for GLSL uniform tracking */
@@ -84,6 +84,9 @@ struct gl_program_parameter_list
extern struct gl_program_parameter_list *
_mesa_new_parameter_list(void);
+extern struct gl_program_parameter_list *
+_mesa_new_parameter_list_sized(unsigned size);
+
extern void
_mesa_free_parameter_list(struct gl_program_parameter_list *paramList);
@@ -102,7 +105,7 @@ _mesa_num_parameters(const struct gl_program_parameter_list *list)
extern GLint
_mesa_add_parameter(struct gl_program_parameter_list *paramList,
- enum register_file type, const char *name,
+ gl_register_file type, const char *name,
GLuint size, GLenum datatype, const GLfloat *values,
const gl_state_index state[STATE_LENGTH],
GLbitfield flags);
@@ -161,11 +164,11 @@ _mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list,
extern GLuint
_mesa_longest_parameter_name(const struct gl_program_parameter_list *list,
- enum register_file type);
+ gl_register_file type);
extern GLuint
_mesa_num_parameters_of_type(const struct gl_program_parameter_list *list,
- enum register_file type);
+ gl_register_file type);
#endif /* PROG_PARAMETER_H */
diff --git a/src/mesa/shader/prog_parameter_layout.c b/src/mesa/shader/prog_parameter_layout.c
new file mode 100644
index 0000000000..1c37b3a7a5
--- /dev/null
+++ b/src/mesa/shader/prog_parameter_layout.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file prog_parameter_layout.c
+ * \brief Helper functions to layout storage for program parameters
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#include "main/mtypes.h"
+#include "prog_parameter.h"
+#include "prog_parameter_layout.h"
+#include "prog_instruction.h"
+#include "program_parser.h"
+
+unsigned
+_mesa_combine_swizzles(unsigned base, unsigned applied)
+{
+ unsigned swiz = 0;
+ unsigned i;
+
+ for (i = 0; i < 4; i++) {
+ const unsigned s = GET_SWZ(applied, i);
+
+ swiz |= ((s <= SWIZZLE_W) ? GET_SWZ(base, s) : s) << (i * 3);
+ }
+
+ return swiz;
+}
+
+
+/**
+ * Copy indirect access array from one parameter list to another
+ *
+ * \param src Parameter array copied from
+ * \param dst Parameter array copied to
+ * \param first Index of first element in \c src to copy
+ * \param count Number of elements to copy
+ *
+ * \return
+ * The location in \c dst of the first element copied from \c src on
+ * success. -1 on failure.
+ *
+ * \warning
+ * This function assumes that there is already enough space available in
+ * \c dst to hold all of the elements that will be copied over.
+ */
+static int
+copy_indirect_accessed_array(struct gl_program_parameter_list *src,
+ struct gl_program_parameter_list *dst,
+ unsigned first, unsigned count)
+{
+ const int base = dst->NumParameters;
+ unsigned i;
+ unsigned j;
+
+
+ for (i = first; i < (first + count); i++) {
+ struct gl_program_parameter *curr = & src->Parameters[i];
+
+
+ if (curr->Type == PROGRAM_CONSTANT) {
+ j = dst->NumParameters;
+ } else {
+ for (j = 0; j < dst->NumParameters; j++) {
+ if (memcmp(dst->Parameters[j].StateIndexes, curr->StateIndexes,
+ sizeof(curr->StateIndexes)) == 0) {
+ return -1;
+ }
+ }
+ }
+
+ assert(j == dst->NumParameters);
+
+ memcpy(& dst->Parameters[j], curr,
+ sizeof(dst->Parameters[j]));
+ memcpy(dst->ParameterValues[j], src->ParameterValues[i],
+ sizeof(GLfloat) * 4);
+ curr->Name = NULL;
+
+ dst->NumParameters++;
+ }
+
+ return base;
+}
+
+
+/**
+ * XXX description???
+ * \return GL_TRUE for success, GL_FALSE for failure
+ */
+GLboolean
+_mesa_layout_parameters(struct asm_parser_state *state)
+{
+ struct gl_program_parameter_list *layout;
+ struct asm_instruction *inst;
+ unsigned i;
+
+
+ layout =
+ _mesa_new_parameter_list_sized(state->prog->Parameters->NumParameters);
+
+
+ /* PASS 1: Move any parameters that are accessed indirectly from the
+ * original parameter list to the new parameter list.
+ */
+ for (inst = state->inst_head; inst != NULL; inst = inst->next) {
+ for (i = 0; i < 3; i++) {
+ if (inst->SrcReg[i].Base.RelAddr) {
+ /* Only attempt to add the to the new parameter list once.
+ */
+ if (!inst->SrcReg[i].Symbol->pass1_done) {
+ const int new_begin =
+ copy_indirect_accessed_array(state->prog->Parameters, layout,
+ inst->SrcReg[i].Symbol->param_binding_begin,
+ inst->SrcReg[i].Symbol->param_binding_length);
+
+ if (new_begin < 0) {
+ return GL_FALSE;
+ }
+
+ inst->SrcReg[i].Symbol->param_binding_begin = new_begin;
+ inst->SrcReg[i].Symbol->pass1_done = 1;
+ }
+
+ /* Previously the Index was just the offset from the parameter
+ * array. Now that the base of the parameter array is known, the
+ * index can be updated to its actual value.
+ */
+ inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
+ inst->Base.SrcReg[i].Index +=
+ inst->SrcReg[i].Symbol->param_binding_begin;
+ }
+ }
+ }
+
+
+ /* PASS 2: Move any parameters that are not accessed indirectly from the
+ * original parameter list to the new parameter list.
+ */
+ for (inst = state->inst_head; inst != NULL; inst = inst->next) {
+ for (i = 0; i < 3; i++) {
+ const struct gl_program_parameter *p;
+ const int idx = inst->SrcReg[i].Base.Index;
+ unsigned swizzle = SWIZZLE_NOOP;
+
+
+ /* All relative addressed operands were processed on the first
+ * pass. Just skip them here.
+ */
+ if (inst->SrcReg[i].Base.RelAddr) {
+ continue;
+ }
+
+
+ if ((inst->SrcReg[i].Base.File <= PROGRAM_VARYING )
+ || (inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY)) {
+ continue;
+ }
+
+ inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
+ p = & state->prog->Parameters->Parameters[idx];
+
+ switch (p->Type) {
+ case PROGRAM_CONSTANT: {
+ const float *const v =
+ state->prog->Parameters->ParameterValues[idx];
+
+ inst->Base.SrcReg[i].Index =
+ _mesa_add_unnamed_constant(layout, v, p->Size, & swizzle);
+
+ inst->Base.SrcReg[i].Swizzle =
+ _mesa_combine_swizzles(swizzle, inst->Base.SrcReg[i].Swizzle);
+ break;
+ }
+
+ case PROGRAM_STATE_VAR:
+ inst->Base.SrcReg[i].Index =
+ _mesa_add_state_reference(layout, p->StateIndexes);
+ break;
+
+ default:
+ break;
+ }
+
+ inst->SrcReg[i].Base.File = p->Type;
+ inst->Base.SrcReg[i].File = p->Type;
+ }
+ }
+
+
+ _mesa_free_parameter_list(state->prog->Parameters);
+ state->prog->Parameters = layout;
+
+ return GL_TRUE;
+}
diff --git a/src/mesa/shader/prog_parameter_layout.h b/src/mesa/shader/prog_parameter_layout.h
new file mode 100644
index 0000000000..99a7b6c726
--- /dev/null
+++ b/src/mesa/shader/prog_parameter_layout.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file prog_parameter_layout.h
+ * \brief Helper functions to layout storage for program parameters
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#pragma once
+
+#ifndef PROG_PARAMETER_LAYOUT_H
+#define PROG_PARAMETER_LAYOUT_H
+
+extern unsigned _mesa_combine_swizzles(unsigned base, unsigned applied);
+
+struct asm_parser_state;
+
+extern GLboolean _mesa_layout_parameters(struct asm_parser_state *state);
+
+#endif /* PROG_PARAMETER_LAYOUT_H */
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index 0ec13a415c..b71735aa80 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -3,6 +3,7 @@
* Version: 7.3
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -42,7 +43,7 @@
* Return string name for given program/register file.
*/
static const char *
-file_string(enum register_file f, gl_prog_print_mode mode)
+file_string(gl_register_file f, gl_prog_print_mode mode)
{
switch (f) {
case PROGRAM_TEMPORARY:
@@ -74,7 +75,11 @@ file_string(enum register_file f, gl_prog_print_mode mode)
case PROGRAM_UNDEFINED:
return "UNDEFINED";
default:
- return "Unknown program file!";
+ {
+ static char s[20];
+ _mesa_snprintf(s, sizeof(s), "FILE%u", f);
+ return s;
+ }
}
}
@@ -85,6 +90,9 @@ file_string(enum register_file f, gl_prog_print_mode mode)
static const char *
arb_input_attrib_string(GLint index, GLenum progType)
{
+ /*
+ * These strings should match the VERT_ATTRIB_x and FRAG_ATTRIB_x tokens.
+ */
const char *vertAttribs[] = {
"vertex.position",
"vertex.weight",
@@ -159,6 +167,9 @@ arb_input_attrib_string(GLint index, GLenum progType)
static const char *
arb_output_attrib_string(GLint index, GLenum progType)
{
+ /*
+ * These strings should match the VERT_RESULT_x and FRAG_RESULT_x tokens.
+ */
const char *vertResults[] = {
"result.position",
"result.color.primary",
@@ -183,7 +194,12 @@ arb_output_attrib_string(GLint index, GLenum progType)
};
const char *fragResults[] = {
"result.color",
- "result.depth"
+ "result.color(half)",
+ "result.depth",
+ "result.color[0]",
+ "result.color[1]",
+ "result.color[2]",
+ "result.color[3]"
};
if (progType == GL_VERTEX_PROGRAM_ARB) {
@@ -201,62 +217,62 @@ arb_output_attrib_string(GLint index, GLenum progType)
* Return string representation of the given register.
* Note that some types of registers (like PROGRAM_UNIFORM) aren't defined
* by the ARB/NV program languages so we've taken some liberties here.
- * \param file the register file (PROGRAM_INPUT, PROGRAM_TEMPORARY, etc)
+ * \param f the register file (PROGRAM_INPUT, PROGRAM_TEMPORARY, etc)
* \param index number of the register in the register file
* \param mode the output format/mode/style
* \param prog pointer to containing program
*/
static const char *
-reg_string(enum register_file f, GLint index, gl_prog_print_mode mode,
+reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode,
GLboolean relAddr, const struct gl_program *prog)
{
static char str[100];
+ const char *addr = relAddr ? "ADDR+" : "";
str[0] = 0;
switch (mode) {
case PROG_PRINT_DEBUG:
- if (relAddr)
- sprintf(str, "%s[ADDR+%d]", file_string(f, mode), index);
- else
- sprintf(str, "%s[%d]", file_string(f, mode), index);
+ _mesa_sprintf(str, "%s[%s%d]", file_string(f, mode), addr, index);
break;
case PROG_PRINT_ARB:
switch (f) {
case PROGRAM_INPUT:
- sprintf(str, "%s", arb_input_attrib_string(index, prog->Target));
+ _mesa_sprintf(str, "%s", arb_input_attrib_string(index, prog->Target));
break;
case PROGRAM_OUTPUT:
- sprintf(str, "%s", arb_output_attrib_string(index, prog->Target));
+ _mesa_sprintf(str, "%s", arb_output_attrib_string(index, prog->Target));
break;
case PROGRAM_TEMPORARY:
- sprintf(str, "temp%d", index);
+ _mesa_sprintf(str, "temp%d", index);
break;
case PROGRAM_ENV_PARAM:
- sprintf(str, "program.env[%d]", index);
+ _mesa_sprintf(str, "program.env[%s%d]", addr, index);
break;
case PROGRAM_LOCAL_PARAM:
- sprintf(str, "program.local[%d]", index);
+ _mesa_sprintf(str, "program.local[%s%d]", addr, index);
break;
case PROGRAM_VARYING: /* extension */
- sprintf(str, "varying[%d]", index);
+ _mesa_sprintf(str, "varying[%s%d]", addr, index);
break;
case PROGRAM_CONSTANT: /* extension */
- sprintf(str, "constant[%d]", index);
+ _mesa_sprintf(str, "constant[%s%d]", addr, index);
break;
case PROGRAM_UNIFORM: /* extension */
- sprintf(str, "uniform[%d]", index);
+ _mesa_sprintf(str, "uniform[%s%d]", addr, index);
break;
case PROGRAM_STATE_VAR:
{
struct gl_program_parameter *param
= prog->Parameters->Parameters + index;
- sprintf(str, _mesa_program_state_string(param->StateIndexes));
+ char *state = _mesa_program_state_string(param->StateIndexes);
+ _mesa_sprintf(str, state);
+ _mesa_free(state);
}
break;
case PROGRAM_ADDRESS:
- sprintf(str, "A%d", index);
+ _mesa_sprintf(str, "A%d", index);
break;
default:
_mesa_problem(NULL, "bad file in reg_string()");
@@ -267,30 +283,30 @@ reg_string(enum register_file f, GLint index, gl_prog_print_mode mode,
switch (f) {
case PROGRAM_INPUT:
if (prog->Target == GL_VERTEX_PROGRAM_ARB)
- sprintf(str, "v[%d]", index);
+ _mesa_sprintf(str, "v[%d]", index);
else
- sprintf(str, "f[%d]", index);
+ _mesa_sprintf(str, "f[%d]", index);
break;
case PROGRAM_OUTPUT:
- sprintf(str, "o[%d]", index);
+ _mesa_sprintf(str, "o[%d]", index);
break;
case PROGRAM_TEMPORARY:
- sprintf(str, "R%d", index);
+ _mesa_sprintf(str, "R%d", index);
break;
case PROGRAM_ENV_PARAM:
- sprintf(str, "c[%d]", index);
+ _mesa_sprintf(str, "c[%d]", index);
break;
case PROGRAM_VARYING: /* extension */
- sprintf(str, "varying[%d]", index);
+ _mesa_sprintf(str, "varying[%s%d]", addr, index);
break;
case PROGRAM_UNIFORM: /* extension */
- sprintf(str, "uniform[%d]", index);
+ _mesa_sprintf(str, "uniform[%s%d]", addr, index);
break;
case PROGRAM_CONSTANT: /* extension */
- sprintf(str, "constant[%d]", index);
+ _mesa_sprintf(str, "constant[%s%d]", addr, index);
break;
case PROGRAM_STATE_VAR: /* extension */
- sprintf(str, "state[%d]", index);
+ _mesa_sprintf(str, "state[%s%d]", addr, index);
break;
default:
_mesa_problem(NULL, "bad file in reg_string()");
@@ -313,19 +329,19 @@ reg_string(enum register_file f, GLint index, gl_prog_print_mode mode,
* \param extended if true, also allow 0, 1 values
*/
const char *
-_mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)
+_mesa_swizzle_string(GLuint swizzle, GLuint negateMask, GLboolean extended)
{
static const char swz[] = "xyzw01!?"; /* See SWIZZLE_x definitions */
static char s[20];
GLuint i = 0;
- if (!extended && swizzle == SWIZZLE_NOOP && negateBase == 0)
+ if (!extended && swizzle == SWIZZLE_NOOP && negateMask == 0)
return ""; /* no swizzle/negation */
if (!extended)
s[i++] = '.';
- if (negateBase & NEGATE_X)
+ if (negateMask & NEGATE_X)
s[i++] = '-';
s[i++] = swz[GET_SWZ(swizzle, 0)];
@@ -333,7 +349,7 @@ _mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)
s[i++] = ',';
}
- if (negateBase & NEGATE_Y)
+ if (negateMask & NEGATE_Y)
s[i++] = '-';
s[i++] = swz[GET_SWZ(swizzle, 1)];
@@ -341,7 +357,7 @@ _mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)
s[i++] = ',';
}
- if (negateBase & NEGATE_Z)
+ if (negateMask & NEGATE_Z)
s[i++] = '-';
s[i++] = swz[GET_SWZ(swizzle, 2)];
@@ -349,7 +365,7 @@ _mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)
s[i++] = ',';
}
- if (negateBase & NEGATE_W)
+ if (negateMask & NEGATE_W)
s[i++] = '-';
s[i++] = swz[GET_SWZ(swizzle, 3)];
@@ -358,6 +374,19 @@ _mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended)
}
+void
+_mesa_print_swizzle(GLuint swizzle)
+{
+ if (swizzle == SWIZZLE_XYZW) {
+ _mesa_printf(".xyzw\n");
+ }
+ else {
+ const char *s = _mesa_swizzle_string(swizzle, 0, 0);
+ _mesa_printf("%s\n", s);
+ }
+}
+
+
const char *
_mesa_writemask_string(GLuint writeMask)
{
@@ -401,90 +430,102 @@ _mesa_condcode_string(GLuint condcode)
static void
-print_dst_reg(const struct prog_dst_register *dstReg, gl_prog_print_mode mode,
- const struct gl_program *prog)
+fprint_dst_reg(FILE * f,
+ const struct prog_dst_register *dstReg,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
{
- _mesa_printf("%s%s",
- reg_string((enum register_file) dstReg->File,
- dstReg->Index, mode, dstReg->RelAddr, prog),
- _mesa_writemask_string(dstReg->WriteMask));
+ _mesa_fprintf(f, "%s%s",
+ reg_string((gl_register_file) dstReg->File,
+ dstReg->Index, mode, dstReg->RelAddr, prog),
+ _mesa_writemask_string(dstReg->WriteMask));
if (dstReg->CondMask != COND_TR) {
- _mesa_printf(" (%s.%s)",
- _mesa_condcode_string(dstReg->CondMask),
- _mesa_swizzle_string(dstReg->CondSwizzle, GL_FALSE, GL_FALSE));
+ _mesa_fprintf(f, " (%s.%s)",
+ _mesa_condcode_string(dstReg->CondMask),
+ _mesa_swizzle_string(dstReg->CondSwizzle,
+ GL_FALSE, GL_FALSE));
}
#if 0
- _mesa_printf("%s[%d]%s",
- file_string((enum register_file) dstReg->File, mode),
+ _mesa_fprintf(f, "%s[%d]%s",
+ file_string((gl_register_file) dstReg->File, mode),
dstReg->Index,
_mesa_writemask_string(dstReg->WriteMask));
#endif
}
+
static void
-print_src_reg(const struct prog_src_register *srcReg, gl_prog_print_mode mode,
- const struct gl_program *prog)
+fprint_src_reg(FILE *f,
+ const struct prog_src_register *srcReg,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
{
- _mesa_printf("%s%s",
- reg_string((enum register_file) srcReg->File,
- srcReg->Index, mode, srcReg->RelAddr, prog),
- _mesa_swizzle_string(srcReg->Swizzle,
- srcReg->NegateBase, GL_FALSE));
+ const char *abs = srcReg->Abs ? "|" : "";
+
+ _mesa_fprintf(f, "%s%s%s%s",
+ abs,
+ reg_string((gl_register_file) srcReg->File,
+ srcReg->Index, mode, srcReg->RelAddr, prog),
+ _mesa_swizzle_string(srcReg->Swizzle,
+ srcReg->Negate, GL_FALSE),
+ abs);
#if 0
- _mesa_printf("%s[%d]%s",
- file_string((enum register_file) srcReg->File, mode),
- srcReg->Index,
- _mesa_swizzle_string(srcReg->Swizzle,
- srcReg->NegateBase, GL_FALSE));
+ _mesa_fprintf(f, "%s[%d]%s",
+ file_string((gl_register_file) srcReg->File, mode),
+ srcReg->Index,
+ _mesa_swizzle_string(srcReg->Swizzle,
+ srcReg->Negate, GL_FALSE));
#endif
}
+
static void
-print_comment(const struct prog_instruction *inst)
+fprint_comment(FILE *f, const struct prog_instruction *inst)
{
if (inst->Comment)
- _mesa_printf("; # %s\n", inst->Comment);
+ _mesa_fprintf(f, "; # %s\n", inst->Comment);
else
- _mesa_printf(";\n");
+ _mesa_fprintf(f, ";\n");
}
static void
-print_alu_instruction(const struct prog_instruction *inst,
- const char *opcode_string, GLuint numRegs,
- gl_prog_print_mode mode,
- const struct gl_program *prog)
+fprint_alu_instruction(FILE *f,
+ const struct prog_instruction *inst,
+ const char *opcode_string, GLuint numRegs,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
{
GLuint j;
- _mesa_printf("%s", opcode_string);
+ _mesa_fprintf(f, "%s", opcode_string);
if (inst->CondUpdate)
- _mesa_printf(".C");
+ _mesa_fprintf(f, ".C");
/* frag prog only */
if (inst->SaturateMode == SATURATE_ZERO_ONE)
- _mesa_printf("_SAT");
+ _mesa_fprintf(f, "_SAT");
- _mesa_printf(" ");
+ _mesa_fprintf(f, " ");
if (inst->DstReg.File != PROGRAM_UNDEFINED) {
- print_dst_reg(&inst->DstReg, mode, prog);
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
}
else {
- _mesa_printf(" ???");
+ _mesa_fprintf(f, " ???");
}
if (numRegs > 0)
- _mesa_printf(", ");
+ _mesa_fprintf(f, ", ");
for (j = 0; j < numRegs; j++) {
- print_src_reg(inst->SrcReg + j, mode, prog);
+ fprint_src_reg(f, inst->SrcReg + j, mode, prog);
if (j + 1 < numRegs)
- _mesa_printf(", ");
+ _mesa_fprintf(f, ", ");
}
- print_comment(inst);
+ fprint_comment(f, inst);
}
@@ -492,15 +533,8 @@ void
_mesa_print_alu_instruction(const struct prog_instruction *inst,
const char *opcode_string, GLuint numRegs)
{
- print_alu_instruction(inst, opcode_string, numRegs, PROG_PRINT_DEBUG, NULL);
-}
-
-
-void
-_mesa_print_instruction(const struct prog_instruction *inst)
-{
- /* note: 4th param should be ignored for PROG_PRINT_DEBUG */
- _mesa_print_instruction_opt(inst, 0, PROG_PRINT_DEBUG, NULL);
+ fprint_alu_instruction(stderr, inst, opcode_string,
+ numRegs, PROG_PRINT_DEBUG, NULL);
}
@@ -508,7 +542,9 @@ _mesa_print_instruction(const struct prog_instruction *inst)
* Print a single vertex/fragment program instruction.
*/
GLint
-_mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
+_mesa_fprint_instruction_opt(FILE *f,
+ const struct prog_instruction *inst,
+ GLint indent,
gl_prog_print_mode mode,
const struct gl_program *prog)
{
@@ -521,275 +557,348 @@ _mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
indent -= 3;
}
for (i = 0; i < indent; i++) {
- _mesa_printf(" ");
+ _mesa_fprintf(f, " ");
}
switch (inst->Opcode) {
case OPCODE_PRINT:
- _mesa_printf("PRINT '%s'", inst->Data);
+ _mesa_fprintf(f, "PRINT '%s'", inst->Data);
if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
- _mesa_printf(", ");
- _mesa_printf("%s[%d]%s",
- file_string((enum register_file) inst->SrcReg[0].File,
+ _mesa_fprintf(f, ", ");
+ _mesa_fprintf(f, "%s[%d]%s",
+ file_string((gl_register_file) inst->SrcReg[0].File,
mode),
inst->SrcReg[0].Index,
_mesa_swizzle_string(inst->SrcReg[0].Swizzle,
- inst->SrcReg[0].NegateBase, GL_FALSE));
+ inst->SrcReg[0].Negate, GL_FALSE));
}
if (inst->Comment)
- _mesa_printf(" # %s", inst->Comment);
- print_comment(inst);
+ _mesa_fprintf(f, " # %s", inst->Comment);
+ fprint_comment(f, inst);
break;
case OPCODE_SWZ:
- _mesa_printf("SWZ");
+ _mesa_fprintf(f, "SWZ");
if (inst->SaturateMode == SATURATE_ZERO_ONE)
- _mesa_printf("_SAT");
- _mesa_printf(" ");
- print_dst_reg(&inst->DstReg, mode, prog);
- _mesa_printf(", %s[%d], %s",
- file_string((enum register_file) inst->SrcReg[0].File,
+ _mesa_fprintf(f, "_SAT");
+ _mesa_fprintf(f, " ");
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ _mesa_fprintf(f, ", %s[%d], %s",
+ file_string((gl_register_file) inst->SrcReg[0].File,
mode),
inst->SrcReg[0].Index,
_mesa_swizzle_string(inst->SrcReg[0].Swizzle,
- inst->SrcReg[0].NegateBase, GL_TRUE));
- print_comment(inst);
+ inst->SrcReg[0].Negate, GL_TRUE));
+ fprint_comment(f, inst);
break;
case OPCODE_TEX:
case OPCODE_TXP:
case OPCODE_TXL:
case OPCODE_TXB:
- _mesa_printf("%s", _mesa_opcode_string(inst->Opcode));
+ _mesa_fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
if (inst->SaturateMode == SATURATE_ZERO_ONE)
- _mesa_printf("_SAT");
- _mesa_printf(" ");
- print_dst_reg(&inst->DstReg, mode, prog);
- _mesa_printf(", ");
- print_src_reg(&inst->SrcReg[0], mode, prog);
- _mesa_printf(", texture[%d], ", inst->TexSrcUnit);
+ _mesa_fprintf(f, "_SAT");
+ _mesa_fprintf(f, " ");
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ _mesa_fprintf(f, ", ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ _mesa_fprintf(f, ", texture[%d], ", inst->TexSrcUnit);
switch (inst->TexSrcTarget) {
- case TEXTURE_1D_INDEX: _mesa_printf("1D"); break;
- case TEXTURE_2D_INDEX: _mesa_printf("2D"); break;
- case TEXTURE_3D_INDEX: _mesa_printf("3D"); break;
- case TEXTURE_CUBE_INDEX: _mesa_printf("CUBE"); break;
- case TEXTURE_RECT_INDEX: _mesa_printf("RECT"); break;
+ case TEXTURE_1D_INDEX: _mesa_fprintf(f, "1D"); break;
+ case TEXTURE_2D_INDEX: _mesa_fprintf(f, "2D"); break;
+ case TEXTURE_3D_INDEX: _mesa_fprintf(f, "3D"); break;
+ case TEXTURE_CUBE_INDEX: _mesa_fprintf(f, "CUBE"); break;
+ case TEXTURE_RECT_INDEX: _mesa_fprintf(f, "RECT"); break;
default:
;
}
- print_comment(inst);
+ if (inst->TexShadow)
+ _mesa_fprintf(f, " SHADOW");
+ fprint_comment(f, inst);
break;
case OPCODE_KIL:
- _mesa_printf("%s", _mesa_opcode_string(inst->Opcode));
- _mesa_printf(" ");
- print_src_reg(&inst->SrcReg[0], mode, prog);
- print_comment(inst);
+ _mesa_fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
+ _mesa_fprintf(f, " ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ fprint_comment(f, inst);
break;
case OPCODE_KIL_NV:
- _mesa_printf("%s", _mesa_opcode_string(inst->Opcode));
- _mesa_printf(" ");
- _mesa_printf("%s.%s",
+ _mesa_fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
+ _mesa_fprintf(f, " ");
+ _mesa_fprintf(f, "%s.%s",
_mesa_condcode_string(inst->DstReg.CondMask),
_mesa_swizzle_string(inst->DstReg.CondSwizzle,
GL_FALSE, GL_FALSE));
- print_comment(inst);
+ fprint_comment(f, inst);
break;
case OPCODE_ARL:
- _mesa_printf("ARL ");
- print_dst_reg(&inst->DstReg, mode, prog);
- _mesa_printf(", ");
- print_src_reg(&inst->SrcReg[0], mode, prog);
- print_comment(inst);
+ _mesa_fprintf(f, "ARL ");
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ _mesa_fprintf(f, ", ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ fprint_comment(f, inst);
break;
case OPCODE_BRA:
- _mesa_printf("BRA %d (%s%s)",
+ _mesa_fprintf(f, "BRA %d (%s%s)",
inst->BranchTarget,
_mesa_condcode_string(inst->DstReg.CondMask),
_mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
- print_comment(inst);
+ fprint_comment(f, inst);
break;
case OPCODE_IF:
if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
/* Use ordinary register */
- _mesa_printf("IF ");
- print_src_reg(&inst->SrcReg[0], mode, prog);
- _mesa_printf("; ");
+ _mesa_fprintf(f, "IF ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ _mesa_fprintf(f, "; ");
}
else {
/* Use cond codes */
- _mesa_printf("IF (%s%s);",
+ _mesa_fprintf(f, "IF (%s%s);",
_mesa_condcode_string(inst->DstReg.CondMask),
_mesa_swizzle_string(inst->DstReg.CondSwizzle,
0, GL_FALSE));
}
- _mesa_printf(" # (if false, goto %d)", inst->BranchTarget);
- print_comment(inst);
+ _mesa_fprintf(f, " # (if false, goto %d)", inst->BranchTarget);
+ fprint_comment(f, inst);
return indent + 3;
case OPCODE_ELSE:
- _mesa_printf("ELSE; # (goto %d)\n", inst->BranchTarget);
+ _mesa_fprintf(f, "ELSE; # (goto %d)\n", inst->BranchTarget);
return indent + 3;
case OPCODE_ENDIF:
- _mesa_printf("ENDIF;\n");
+ _mesa_fprintf(f, "ENDIF;\n");
break;
case OPCODE_BGNLOOP:
- _mesa_printf("BGNLOOP; # (end at %d)\n", inst->BranchTarget);
+ _mesa_fprintf(f, "BGNLOOP; # (end at %d)\n", inst->BranchTarget);
return indent + 3;
case OPCODE_ENDLOOP:
- _mesa_printf("ENDLOOP; # (goto %d)\n", inst->BranchTarget);
+ _mesa_fprintf(f, "ENDLOOP; # (goto %d)\n", inst->BranchTarget);
break;
case OPCODE_BRK:
case OPCODE_CONT:
- _mesa_printf("%s (%s%s); # (goto %d)",
+ _mesa_fprintf(f, "%s (%s%s); # (goto %d)",
_mesa_opcode_string(inst->Opcode),
_mesa_condcode_string(inst->DstReg.CondMask),
_mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
inst->BranchTarget);
- print_comment(inst);
+ fprint_comment(f, inst);
break;
case OPCODE_BGNSUB:
if (mode == PROG_PRINT_NV) {
- _mesa_printf("%s:\n", inst->Comment); /* comment is label */
+ _mesa_fprintf(f, "%s:\n", inst->Comment); /* comment is label */
return indent;
}
else {
- _mesa_printf("BGNSUB");
- print_comment(inst);
+ _mesa_fprintf(f, "BGNSUB");
+ fprint_comment(f, inst);
return indent + 3;
}
case OPCODE_ENDSUB:
if (mode == PROG_PRINT_DEBUG) {
- _mesa_printf("ENDSUB");
- print_comment(inst);
+ _mesa_fprintf(f, "ENDSUB");
+ fprint_comment(f, inst);
}
break;
case OPCODE_CAL:
if (mode == PROG_PRINT_NV) {
- _mesa_printf("CAL %s; # (goto %d)\n", inst->Comment, inst->BranchTarget);
+ _mesa_fprintf(f, "CAL %s; # (goto %d)\n", inst->Comment, inst->BranchTarget);
}
else {
- _mesa_printf("CAL %u", inst->BranchTarget);
- print_comment(inst);
+ _mesa_fprintf(f, "CAL %u", inst->BranchTarget);
+ fprint_comment(f, inst);
}
break;
case OPCODE_RET:
- _mesa_printf("RET (%s%s)",
+ _mesa_fprintf(f, "RET (%s%s)",
_mesa_condcode_string(inst->DstReg.CondMask),
_mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
- print_comment(inst);
+ fprint_comment(f, inst);
break;
case OPCODE_END:
- _mesa_printf("END\n");
+ _mesa_fprintf(f, "END\n");
break;
case OPCODE_NOP:
if (mode == PROG_PRINT_DEBUG) {
- _mesa_printf("NOP");
- print_comment(inst);
+ _mesa_fprintf(f, "NOP");
+ fprint_comment(f, inst);
}
else if (inst->Comment) {
/* ARB/NV extensions don't have NOP instruction */
- _mesa_printf("# %s\n", inst->Comment);
+ _mesa_fprintf(f, "# %s\n", inst->Comment);
}
break;
/* XXX may need other special-case instructions */
default:
- /* typical alu instruction */
- print_alu_instruction(inst,
- _mesa_opcode_string(inst->Opcode),
- _mesa_num_inst_src_regs(inst->Opcode),
- mode, prog);
+ if (inst->Opcode < MAX_OPCODE) {
+ /* typical alu instruction */
+ fprint_alu_instruction(f, inst,
+ _mesa_opcode_string(inst->Opcode),
+ _mesa_num_inst_src_regs(inst->Opcode),
+ mode, prog);
+ }
+ else {
+ fprint_alu_instruction(f, inst,
+ _mesa_opcode_string(inst->Opcode),
+ 3/*_mesa_num_inst_src_regs(inst->Opcode)*/,
+ mode, prog);
+ }
break;
}
return indent;
}
-/**
- * Print program to stdout, default options.
- */
+GLint
+_mesa_print_instruction_opt(const struct prog_instruction *inst,
+ GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ return _mesa_fprint_instruction_opt(stderr, inst, indent, mode, prog);
+}
+
+
void
-_mesa_print_program(const struct gl_program *prog)
+_mesa_print_instruction(const struct prog_instruction *inst)
{
- _mesa_print_program_opt(prog, PROG_PRINT_DEBUG, GL_TRUE);
+ /* note: 4th param should be ignored for PROG_PRINT_DEBUG */
+ _mesa_fprint_instruction_opt(stderr, inst, 0, PROG_PRINT_DEBUG, NULL);
}
+
/**
* Print program, with options.
*/
void
-_mesa_print_program_opt(const struct gl_program *prog,
- gl_prog_print_mode mode,
- GLboolean lineNumbers)
+_mesa_fprint_program_opt(FILE *f,
+ const struct gl_program *prog,
+ gl_prog_print_mode mode,
+ GLboolean lineNumbers)
{
GLuint i, indent = 0;
switch (prog->Target) {
case GL_VERTEX_PROGRAM_ARB:
if (mode == PROG_PRINT_ARB)
- _mesa_printf("!!ARBvp1.0\n");
+ _mesa_fprintf(f, "!!ARBvp1.0\n");
else if (mode == PROG_PRINT_NV)
- _mesa_printf("!!VP1.0\n");
+ _mesa_fprintf(f, "!!VP1.0\n");
else
- _mesa_printf("# Vertex Program/Shader\n");
+ _mesa_fprintf(f, "# Vertex Program/Shader\n");
break;
case GL_FRAGMENT_PROGRAM_ARB:
case GL_FRAGMENT_PROGRAM_NV:
if (mode == PROG_PRINT_ARB)
- _mesa_printf("!!ARBfp1.0\n");
+ _mesa_fprintf(f, "!!ARBfp1.0\n");
else if (mode == PROG_PRINT_NV)
- _mesa_printf("!!FP1.0\n");
+ _mesa_fprintf(f, "!!FP1.0\n");
else
- _mesa_printf("# Fragment Program/Shader\n");
+ _mesa_fprintf(f, "# Fragment Program/Shader\n");
break;
}
for (i = 0; i < prog->NumInstructions; i++) {
if (lineNumbers)
- _mesa_printf("%3d: ", i);
- indent = _mesa_print_instruction_opt(prog->Instructions + i,
+ _mesa_fprintf(f, "%3d: ", i);
+ indent = _mesa_fprint_instruction_opt(f, prog->Instructions + i,
indent, mode, prog);
}
}
/**
- * Print all of a program's parameters.
+ * Print program to stderr, default options.
*/
void
-_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog)
+_mesa_print_program(const struct gl_program *prog)
+{
+ _mesa_fprint_program_opt(stderr, prog, PROG_PRINT_DEBUG, GL_TRUE);
+}
+
+
+/**
+ * Return binary representation of value (as a string).
+ * Insert a comma to separate each group of 8 bits.
+ * XXX move to imports.[ch] if useful elsewhere.
+ */
+static const char *
+binary(GLbitfield val)
+{
+ static char buf[50];
+ GLint i, len = 0;
+ for (i = 31; i >= 0; --i) {
+ if (val & (1 << i))
+ buf[len++] = '1';
+ else if (len > 0 || i == 0)
+ buf[len++] = '0';
+ if (len > 0 && ((i-1) % 8) == 7)
+ buf[len++] = ',';
+ }
+ buf[len] = '\0';
+ return buf;
+}
+
+
+/**
+ * Print all of a program's parameters/fields to given file.
+ */
+static void
+_mesa_fprint_program_parameters(FILE *f,
+ GLcontext *ctx,
+ const struct gl_program *prog)
{
GLuint i;
- _mesa_printf("InputsRead: 0x%x\n", prog->InputsRead);
- _mesa_printf("OutputsWritten: 0x%x\n", prog->OutputsWritten);
- _mesa_printf("NumInstructions=%d\n", prog->NumInstructions);
- _mesa_printf("NumTemporaries=%d\n", prog->NumTemporaries);
- _mesa_printf("NumParameters=%d\n", prog->NumParameters);
- _mesa_printf("NumAttributes=%d\n", prog->NumAttributes);
- _mesa_printf("NumAddressRegs=%d\n", prog->NumAddressRegs);
- _mesa_printf("Samplers=[ ");
+ _mesa_fprintf(f, "InputsRead: 0x%x (0b%s)\n",
+ prog->InputsRead, binary(prog->InputsRead));
+ _mesa_fprintf(f, "OutputsWritten: 0x%x (0b%s)\n",
+ prog->OutputsWritten, binary(prog->OutputsWritten));
+ _mesa_fprintf(f, "NumInstructions=%d\n", prog->NumInstructions);
+ _mesa_fprintf(f, "NumTemporaries=%d\n", prog->NumTemporaries);
+ _mesa_fprintf(f, "NumParameters=%d\n", prog->NumParameters);
+ _mesa_fprintf(f, "NumAttributes=%d\n", prog->NumAttributes);
+ _mesa_fprintf(f, "NumAddressRegs=%d\n", prog->NumAddressRegs);
+ _mesa_fprintf(f, "SamplersUsed: 0x%x (0b%s)\n",
+ prog->SamplersUsed, binary(prog->SamplersUsed));
+ _mesa_fprintf(f, "Samplers=[ ");
for (i = 0; i < MAX_SAMPLERS; i++) {
- _mesa_printf("%d ", prog->SamplerUnits[i]);
+ _mesa_fprintf(f, "%d ", prog->SamplerUnits[i]);
}
- _mesa_printf("]\n");
+ _mesa_fprintf(f, "]\n");
_mesa_load_state_parameters(ctx, prog->Parameters);
#if 0
- _mesa_printf("Local Params:\n");
+ _mesa_fprintf(f, "Local Params:\n");
for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){
const GLfloat *p = prog->LocalParams[i];
- _mesa_printf("%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]);
+ _mesa_fprintf(f, "%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]);
}
#endif
_mesa_print_parameter_list(prog->Parameters);
}
+/**
+ * Print all of a program's parameters/fields to stderr.
+ */
void
-_mesa_print_parameter_list(const struct gl_program_parameter_list *list)
+_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog)
+{
+ _mesa_fprint_program_parameters(stderr, ctx, prog);
+}
+
+
+/**
+ * Print a program parameter list to given file.
+ */
+static void
+_mesa_fprint_parameter_list(FILE *f,
+ const struct gl_program_parameter_list *list)
{
const gl_prog_print_mode mode = PROG_PRINT_DEBUG;
GLuint i;
@@ -797,22 +906,114 @@ _mesa_print_parameter_list(const struct gl_program_parameter_list *list)
if (!list)
return;
- _mesa_printf("param list %p\n", (void *) list);
+ _mesa_fprintf(f, "param list %p\n", (void *) list);
+ _mesa_fprintf(f, "dirty state flags: 0x%x\n", list->StateFlags);
for (i = 0; i < list->NumParameters; i++){
struct gl_program_parameter *param = list->Parameters + i;
const GLfloat *v = list->ParameterValues[i];
- _mesa_printf("param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}",
+ _mesa_fprintf(f, "param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}",
i, param->Size,
file_string(list->Parameters[i].Type, mode),
param->Name, v[0], v[1], v[2], v[3]);
if (param->Flags & PROG_PARAM_BIT_CENTROID)
- _mesa_printf(" Centroid");
+ _mesa_fprintf(f, " Centroid");
if (param->Flags & PROG_PARAM_BIT_INVARIANT)
- _mesa_printf(" Invariant");
+ _mesa_fprintf(f, " Invariant");
if (param->Flags & PROG_PARAM_BIT_FLAT)
- _mesa_printf(" Flat");
+ _mesa_fprintf(f, " Flat");
if (param->Flags & PROG_PARAM_BIT_LINEAR)
- _mesa_printf(" Linear");
- _mesa_printf("\n");
+ _mesa_fprintf(f, " Linear");
+ _mesa_fprintf(f, "\n");
+ }
+}
+
+
+/**
+ * Print a program parameter list to stderr.
+ */
+void
+_mesa_print_parameter_list(const struct gl_program_parameter_list *list)
+{
+ _mesa_fprint_parameter_list(stderr, list);
+}
+
+
+/**
+ * Write shader and associated info to a file.
+ */
+void
+_mesa_write_shader_to_file(const struct gl_shader *shader)
+{
+ const char *type;
+ char filename[100];
+ FILE *f;
+
+ if (shader->Type == GL_FRAGMENT_SHADER)
+ type = "frag";
+ else
+ type = "vert";
+
+ _mesa_snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type);
+ f = fopen(filename, "w");
+ if (!f) {
+ fprintf(stderr, "Unable to open %s for writing\n", filename);
+ return;
+ }
+
+ fprintf(f, "/* Shader %u source, checksum %u */\n", shader->Name, shader->SourceChecksum);
+ fputs(shader->Source, f);
+ fprintf(f, "\n");
+
+ fprintf(f, "/* Compile status: %s */\n",
+ shader->CompileStatus ? "ok" : "fail");
+ if (!shader->CompileStatus) {
+ fprintf(f, "/* Log Info: */\n");
+ fputs(shader->InfoLog, f);
+ }
+ else {
+ fprintf(f, "/* GPU code */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE);
+ fprintf(f, "*/\n");
+ fprintf(f, "/* Parameters / constants */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_parameter_list(f, shader->Program->Parameters);
+ fprintf(f, "*/\n");
+ }
+
+ fclose(f);
+}
+
+
+/**
+ * Append the shader's uniform info/values to the shader log file.
+ * The log file will typically have been created by the
+ * _mesa_write_shader_to_file function.
+ */
+void
+_mesa_append_uniforms_to_file(const struct gl_shader *shader,
+ const struct gl_program *prog)
+{
+ const char *type;
+ char filename[100];
+ FILE *f;
+
+ if (shader->Type == GL_FRAGMENT_SHADER)
+ type = "frag";
+ else
+ type = "vert";
+
+ _mesa_snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type);
+ f = fopen(filename, "a"); /* append */
+ if (!f) {
+ fprintf(stderr, "Unable to open %s for appending\n", filename);
+ return;
}
+
+ fprintf(f, "/* First-draw parameters / constants */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_parameter_list(f, prog->Parameters);
+ fprintf(f, "*/\n");
+
+ fclose(f);
}
diff --git a/src/mesa/shader/prog_print.h b/src/mesa/shader/prog_print.h
index cd9e388e82..fc286ded54 100644
--- a/src/mesa/shader/prog_print.h
+++ b/src/mesa/shader/prog_print.h
@@ -47,6 +47,9 @@ const char *
_mesa_writemask_string(GLuint writeMask);
extern void
+_mesa_print_swizzle(GLuint swizzle);
+
+extern void
_mesa_print_alu_instruction(const struct prog_instruction *inst,
const char *opcode_string, GLuint numRegs);
@@ -54,6 +57,13 @@ extern void
_mesa_print_instruction(const struct prog_instruction *inst);
extern GLint
+_mesa_fprint_instruction_opt(FILE *f,
+ const struct prog_instruction *inst,
+ GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog);
+
+extern GLint
_mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
gl_prog_print_mode mode,
const struct gl_program *prog);
@@ -62,8 +72,9 @@ extern void
_mesa_print_program(const struct gl_program *prog);
extern void
-_mesa_print_program_opt(const struct gl_program *prog, gl_prog_print_mode mode,
- GLboolean lineNumbers);
+_mesa_fprint_program_opt(FILE *f,
+ const struct gl_program *prog, gl_prog_print_mode mode,
+ GLboolean lineNumbers);
extern void
_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog);
@@ -72,4 +83,12 @@ extern void
_mesa_print_parameter_list(const struct gl_program_parameter_list *list);
+extern void
+_mesa_write_shader_to_file(const struct gl_shader *shader);
+
+extern void
+_mesa_append_uniforms_to_file(const struct gl_shader *shader,
+ const struct gl_program *prog);
+
+
#endif /* PROG_PRINT_H */
diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c
index 615826b210..058d4bbafb 100644
--- a/src/mesa/shader/prog_statevars.c
+++ b/src/mesa/shader/prog_statevars.c
@@ -112,7 +112,7 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
value[3] = ctx->Light.Light[ln].SpotExponent;
return;
case STATE_SPOT_DIRECTION:
- COPY_3V(value, ctx->Light.Light[ln].EyeDirection);
+ COPY_3V(value, ctx->Light.Light[ln].SpotDirection);
value[3] = ctx->Light.Light[ln]._CosCutoff;
return;
case STATE_SPOT_CUTOFF:
@@ -206,28 +206,28 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
/* state[2] is the texgen attribute */
switch (state[2]) {
case STATE_TEXGEN_EYE_S:
- COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneS);
+ COPY_4V(value, ctx->Texture.Unit[unit].GenS.EyePlane);
return;
case STATE_TEXGEN_EYE_T:
- COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneT);
+ COPY_4V(value, ctx->Texture.Unit[unit].GenT.EyePlane);
return;
case STATE_TEXGEN_EYE_R:
- COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneR);
+ COPY_4V(value, ctx->Texture.Unit[unit].GenR.EyePlane);
return;
case STATE_TEXGEN_EYE_Q:
- COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneQ);
+ COPY_4V(value, ctx->Texture.Unit[unit].GenQ.EyePlane);
return;
case STATE_TEXGEN_OBJECT_S:
- COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneS);
+ COPY_4V(value, ctx->Texture.Unit[unit].GenS.ObjectPlane);
return;
case STATE_TEXGEN_OBJECT_T:
- COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneT);
+ COPY_4V(value, ctx->Texture.Unit[unit].GenT.ObjectPlane);
return;
case STATE_TEXGEN_OBJECT_R:
- COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneR);
+ COPY_4V(value, ctx->Texture.Unit[unit].GenR.ObjectPlane);
return;
case STATE_TEXGEN_OBJECT_Q:
- COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneQ);
+ COPY_4V(value, ctx->Texture.Unit[unit].GenQ.ObjectPlane);
return;
default:
_mesa_problem(ctx, "Invalid texgen state in fetch_state");
@@ -359,10 +359,10 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
switch (state[1]) {
case STATE_ENV:
COPY_4V(value, ctx->FragmentProgram.Parameters[idx]);
- break;
+ return;
case STATE_LOCAL:
COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]);
- break;
+ return;
default:
_mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
return;
@@ -378,10 +378,10 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
switch (state[1]) {
case STATE_ENV:
COPY_4V(value, ctx->VertexProgram.Parameters[idx]);
- break;
+ return;
case STATE_LOCAL:
COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]);
- break;
+ return;
default:
_mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
return;
@@ -395,6 +395,13 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
case STATE_INTERNAL:
switch (state[1]) {
+ case STATE_CURRENT_ATTRIB:
+ {
+ const GLuint idx = (GLuint) state[2];
+ COPY_4V(value, ctx->Current.Attrib[idx]);
+ }
+ return;
+
case STATE_NORMAL_SCALE:
ASSIGN_4V(value,
ctx->_ModelViewInvScale,
@@ -402,19 +409,25 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
ctx->_ModelViewInvScale,
1);
return;
+
case STATE_TEXRECT_SCALE:
+ /* Value = { 1/texWidth, 1/texHeight, 0, 1 }.
+ * Used to convert unnormalized texcoords to normalized texcoords.
+ */
{
const int unit = (int) state[2];
const struct gl_texture_object *texObj
= ctx->Texture.Unit[unit]._Current;
if (texObj) {
struct gl_texture_image *texImage = texObj->Image[0][0];
- ASSIGN_4V(value, (GLfloat) (1.0 / texImage->Width),
- (GLfloat)(1.0 / texImage->Height),
+ ASSIGN_4V(value,
+ (GLfloat) (1.0 / texImage->Width),
+ (GLfloat) (1.0 / texImage->Height),
0.0f, 1.0f);
}
}
return;
+
case STATE_FOG_PARAMS_OPTIMIZED:
/* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog)
* might be more expensive than EX2 on some hw, plus it needs
@@ -431,79 +444,118 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2);
return;
- case STATE_LIGHT_SPOT_DIR_NORMALIZED: {
- /* here, state[2] is the light number */
- /* pre-normalize spot dir */
- const GLuint ln = (GLuint) state[2];
- COPY_3V(value, ctx->Light.Light[ln]._NormDirection);
- value[3] = ctx->Light.Light[ln]._CosCutoff;
+ case STATE_LIGHT_SPOT_DIR_NORMALIZED:
+ {
+ /* here, state[2] is the light number */
+ /* pre-normalize spot dir */
+ const GLuint ln = (GLuint) state[2];
+ COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection);
+ value[3] = ctx->Light.Light[ln]._CosCutoff;
+ }
return;
- }
- case STATE_LIGHT_POSITION: {
- const GLuint ln = (GLuint) state[2];
- COPY_4V(value, ctx->Light.Light[ln]._Position);
+ case STATE_LIGHT_POSITION:
+ {
+ const GLuint ln = (GLuint) state[2];
+ COPY_4V(value, ctx->Light.Light[ln]._Position);
+ }
return;
- }
- case STATE_LIGHT_POSITION_NORMALIZED: {
- const GLuint ln = (GLuint) state[2];
- COPY_4V(value, ctx->Light.Light[ln]._Position);
- NORMALIZE_3FV( value );
+ case STATE_LIGHT_POSITION_NORMALIZED:
+ {
+ const GLuint ln = (GLuint) state[2];
+ COPY_4V(value, ctx->Light.Light[ln]._Position);
+ NORMALIZE_3FV( value );
+ }
return;
- }
- case STATE_LIGHT_HALF_VECTOR: {
- const GLuint ln = (GLuint) state[2];
- GLfloat p[3];
- /* Compute infinite half angle vector:
- * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
- * light.EyePosition.w should be 0 for infinite lights.
- */
- COPY_3V(p, ctx->Light.Light[ln]._Position);
- NORMALIZE_3FV(p);
- ADD_3V(value, p, ctx->_EyeZDir);
- NORMALIZE_3FV(value);
- value[3] = 1.0;
+ case STATE_LIGHT_HALF_VECTOR:
+ {
+ const GLuint ln = (GLuint) state[2];
+ GLfloat p[3];
+ /* Compute infinite half angle vector:
+ * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
+ * light.EyePosition.w should be 0 for infinite lights.
+ */
+ COPY_3V(p, ctx->Light.Light[ln]._Position);
+ NORMALIZE_3FV(p);
+ ADD_3V(value, p, ctx->_EyeZDir);
+ NORMALIZE_3FV(value);
+ value[3] = 1.0;
+ }
return;
- }
-
case STATE_PT_SCALE:
value[0] = ctx->Pixel.RedScale;
value[1] = ctx->Pixel.GreenScale;
value[2] = ctx->Pixel.BlueScale;
value[3] = ctx->Pixel.AlphaScale;
- break;
+ return;
+
case STATE_PT_BIAS:
value[0] = ctx->Pixel.RedBias;
value[1] = ctx->Pixel.GreenBias;
value[2] = ctx->Pixel.BlueBias;
value[3] = ctx->Pixel.AlphaBias;
- break;
+ return;
+
case STATE_PCM_SCALE:
COPY_4V(value, ctx->Pixel.PostColorMatrixScale);
- break;
+ return;
+
case STATE_PCM_BIAS:
COPY_4V(value, ctx->Pixel.PostColorMatrixBias);
- break;
+ return;
+
case STATE_SHADOW_AMBIENT:
{
const int unit = (int) state[2];
const struct gl_texture_object *texObj
= ctx->Texture.Unit[unit]._Current;
if (texObj) {
- value[0] = texObj->ShadowAmbient;
- value[1] = texObj->ShadowAmbient;
- value[2] = texObj->ShadowAmbient;
- value[3] = texObj->ShadowAmbient;
+ value[0] =
+ value[1] =
+ value[2] =
+ value[3] = texObj->CompareFailValue;
}
}
return;
+ case STATE_FB_SIZE:
+ value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1);
+ value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1);
+ value[2] = 0.0F;
+ value[3] = 0.0F;
+ return;
+
+ case STATE_ROT_MATRIX_0:
+ {
+ const int unit = (int) state[2];
+ GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
+ value[0] = rotMat22[0];
+ value[1] = rotMat22[2];
+ value[2] = 0.0;
+ value[3] = 0.0;
+ }
+ return;
+
+ case STATE_ROT_MATRIX_1:
+ {
+ const int unit = (int) state[2];
+ GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
+ value[0] = rotMat22[1];
+ value[1] = rotMat22[3];
+ value[2] = 0.0;
+ value[3] = 0.0;
+ }
+ return;
+
+ /* XXX: make sure new tokens added here are also handled in the
+ * _mesa_program_state_flags() switch, below.
+ */
default:
- /* unknown state indexes are silently ignored
- * should be handled by the driver.
+ /* Unknown state indexes are silently ignored here.
+ * Drivers may do something special.
*/
return;
}
@@ -574,11 +626,34 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
case STATE_INTERNAL:
switch (state[1]) {
+ case STATE_CURRENT_ATTRIB:
+ return _NEW_CURRENT_ATTRIB;
+
+ case STATE_NORMAL_SCALE:
+ return _NEW_MODELVIEW;
+
case STATE_TEXRECT_SCALE:
case STATE_SHADOW_AMBIENT:
+ case STATE_ROT_MATRIX_0:
+ case STATE_ROT_MATRIX_1:
return _NEW_TEXTURE;
case STATE_FOG_PARAMS_OPTIMIZED:
return _NEW_FOG;
+ case STATE_LIGHT_SPOT_DIR_NORMALIZED:
+ case STATE_LIGHT_POSITION:
+ case STATE_LIGHT_POSITION_NORMALIZED:
+ case STATE_LIGHT_HALF_VECTOR:
+ return _NEW_LIGHT;
+
+ case STATE_PT_SCALE:
+ case STATE_PT_BIAS:
+ case STATE_PCM_SCALE:
+ case STATE_PCM_BIAS:
+ return _NEW_PIXEL;
+
+ case STATE_FB_SIZE:
+ return _NEW_BUFFERS;
+
default:
/* unknown state indexes are silently ignored and
* no flag set, since it is handled by the driver.
@@ -701,28 +776,28 @@ append_token(char *dst, gl_state_index k)
append(dst, ".spot.cutoff");
break;
case STATE_TEXGEN_EYE_S:
- append(dst, "eye.s");
+ append(dst, ".eye.s");
break;
case STATE_TEXGEN_EYE_T:
- append(dst, "eye.t");
+ append(dst, ".eye.t");
break;
case STATE_TEXGEN_EYE_R:
- append(dst, "eye.r");
+ append(dst, ".eye.r");
break;
case STATE_TEXGEN_EYE_Q:
- append(dst, "eye.q");
+ append(dst, ".eye.q");
break;
case STATE_TEXGEN_OBJECT_S:
- append(dst, "object.s");
+ append(dst, ".object.s");
break;
case STATE_TEXGEN_OBJECT_T:
- append(dst, "object.t");
+ append(dst, ".object.t");
break;
case STATE_TEXGEN_OBJECT_R:
- append(dst, "object.r");
+ append(dst, ".object.r");
break;
case STATE_TEXGEN_OBJECT_Q:
- append(dst, "object.q");
+ append(dst, ".object.q");
break;
case STATE_TEXENV_COLOR:
append(dst, "texenv");
@@ -741,7 +816,10 @@ append_token(char *dst, gl_state_index k)
break;
/* BEGIN internal state vars */
case STATE_INTERNAL:
- append(dst, "(internal)");
+ append(dst, ".internal.");
+ break;
+ case STATE_CURRENT_ATTRIB:
+ append(dst, "current");
break;
case STATE_NORMAL_SCALE:
append(dst, "normalScale");
@@ -777,7 +855,16 @@ append_token(char *dst, gl_state_index k)
append(dst, "PCMbias");
break;
case STATE_SHADOW_AMBIENT:
- append(dst, "ShadowAmbient");
+ append(dst, "CompareFailValue");
+ break;
+ case STATE_FB_SIZE:
+ append(dst, "FbSize");
+ break;
+ case STATE_ROT_MATRIX_0:
+ append(dst, "rotMatrixRow0");
+ break;
+ case STATE_ROT_MATRIX_1:
+ append(dst, "rotMatrixRow1");
break;
default:
/* probably STATE_INTERNAL_DRIVER+i (driver private state) */
@@ -807,7 +894,7 @@ append_index(char *dst, GLint index)
* For example, return "state.matrix.texture[2].inverse".
* Use _mesa_free() to deallocate the string.
*/
-const char *
+char *
_mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
{
char str[1000] = "";
@@ -902,7 +989,9 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
break;
case STATE_INTERNAL:
append_token(str, state[1]);
- break;
+ if (state[1] == STATE_CURRENT_ATTRIB)
+ append_index(str, state[2]);
+ break;
default:
_mesa_problem(NULL, "Invalid state in _mesa_program_state_string");
break;
diff --git a/src/mesa/shader/prog_statevars.h b/src/mesa/shader/prog_statevars.h
index 909bce0a4f..1180d9eaa4 100644
--- a/src/mesa/shader/prog_statevars.h
+++ b/src/mesa/shader/prog_statevars.h
@@ -104,6 +104,7 @@ typedef enum gl_state_index_ {
STATE_LOCAL,
STATE_INTERNAL, /* Mesa additions */
+ STATE_CURRENT_ATTRIB, /* ctx->Current vertex attrib value */
STATE_NORMAL_SCALE,
STATE_TEXRECT_SCALE,
STATE_FOG_PARAMS_OPTIMIZED, /* for faster fog calc */
@@ -116,6 +117,9 @@ typedef enum gl_state_index_ {
STATE_PCM_SCALE, /**< Post color matrix RGBA scale */
STATE_PCM_BIAS, /**< Post color matrix RGBA bias */
STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */
+ STATE_FB_SIZE, /**< (width-1, height-1, 0, 0) */
+ STATE_ROT_MATRIX_0, /**< ATI_envmap_bumpmap, rot matrix row 0 */
+ STATE_ROT_MATRIX_1, /**< ATI_envmap_bumpmap, rot matrix row 1 */
STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */
} gl_state_index;
@@ -130,7 +134,7 @@ extern GLbitfield
_mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]);
-extern const char *
+extern char *
_mesa_program_state_string(const gl_state_index state[STATE_LENGTH]);
diff --git a/src/mesa/shader/prog_uniform.c b/src/mesa/shader/prog_uniform.c
index dc76be8e46..0642713148 100644
--- a/src/mesa/shader/prog_uniform.c
+++ b/src/mesa/shader/prog_uniform.c
@@ -142,8 +142,8 @@ _mesa_longest_uniform_name(const struct gl_uniform_list *list)
GLint max = 0;
GLuint i;
for (i = 0; list && i < list->NumUniforms; i++) {
- GLuint len = _mesa_strlen(list->Uniforms[i].Name);
- if (len > (GLuint)max)
+ GLint len = (GLint)_mesa_strlen(list->Uniforms[i].Name);
+ if (len > max)
max = len;
}
return max;
diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c
index d114828ec6..963478fccd 100644
--- a/src/mesa/shader/program.c
+++ b/src/mesa/shader/program.c
@@ -53,6 +53,21 @@ _mesa_init_program(GLcontext *ctx)
{
GLuint i;
+ /*
+ * If this assertion fails, we need to increase the field
+ * size for register indexes.
+ */
+ ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4
+ <= (1 << INST_INDEX_BITS));
+ ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4
+ <= (1 << INST_INDEX_BITS));
+
+ /* If this fails, increase prog_instruction::TexSrcUnit size */
+ ASSERT(MAX_TEXTURE_UNITS < (1 << 5));
+
+ /* If this fails, increase prog_instruction::TexSrcTarget size */
+ ASSERT(NUM_TEXTURE_TARGETS < (1 << 3));
+
ctx->Program.ErrorPos = -1;
ctx->Program.ErrorString = _mesa_strdup("");
@@ -287,6 +302,7 @@ _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
struct gl_program *prog;
switch (target) {
case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
+ case GL_VERTEX_STATE_PROGRAM_NV:
prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
target, id );
break;
@@ -554,7 +570,6 @@ _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count)
return GL_TRUE;
}
-
/**
* Delete 'count' instructions at 'start' in the given program.
* Adjust branch targets accordingly.
@@ -691,17 +706,47 @@ _mesa_combine_programs(GLcontext *ctx,
if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
struct gl_fragment_program *fprogA, *fprogB, *newFprog;
+ GLbitfield progB_inputsRead = progB->InputsRead;
+ GLint progB_colorFile, progB_colorIndex;
+
fprogA = (struct gl_fragment_program *) progA;
fprogB = (struct gl_fragment_program *) progB;
newFprog = (struct gl_fragment_program *) newProg;
newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;
+ /* We'll do a search and replace for instances
+ * of progB_colorFile/progB_colorIndex below...
+ */
+ progB_colorFile = PROGRAM_INPUT;
+ progB_colorIndex = FRAG_ATTRIB_COL0;
+
+ /*
+ * The fragment program may get color from a state var rather than
+ * a fragment input (vertex output) if it's constant.
+ * See the texenvprogram.c code.
+ * So, search the program's parameter list now to see if the program
+ * gets color from a state var instead of a conventional fragment
+ * input register.
+ */
+ for (i = 0; i < progB->Parameters->NumParameters; i++) {
+ struct gl_program_parameter *p = &progB->Parameters->Parameters[i];
+ if (p->Type == PROGRAM_STATE_VAR &&
+ p->StateIndexes[0] == STATE_INTERNAL &&
+ p->StateIndexes[1] == STATE_CURRENT_ATTRIB &&
+ p->StateIndexes[2] == VERT_ATTRIB_COLOR0) {
+ progB_inputsRead |= FRAG_BIT_COL0;
+ progB_colorFile = PROGRAM_STATE_VAR;
+ progB_colorIndex = i;
+ break;
+ }
+ }
+
/* Connect color outputs of fprogA to color inputs of fprogB, via a
* new temporary register.
*/
- if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) &&
- (progB->InputsRead & (1 << FRAG_ATTRIB_COL0))) {
+ if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) &&
+ (progB_inputsRead & FRAG_BIT_COL0)) {
GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY);
if (tempReg < 0) {
_mesa_problem(ctx, "No free temp regs found in "
@@ -710,16 +755,17 @@ _mesa_combine_programs(GLcontext *ctx,
}
/* replace writes to result.color[0] with tempReg */
replace_registers(newInst, lenA,
- PROGRAM_OUTPUT, FRAG_RESULT_COLR,
+ PROGRAM_OUTPUT, FRAG_RESULT_COLOR,
PROGRAM_TEMPORARY, tempReg);
- /* replace reads from input.color[0] with tempReg */
+ /* replace reads from the input color with tempReg */
replace_registers(newInst + lenA, lenB,
- PROGRAM_INPUT, FRAG_ATTRIB_COL0,
- PROGRAM_TEMPORARY, tempReg);
+ progB_colorFile, progB_colorIndex, /* search for */
+ PROGRAM_TEMPORARY, tempReg /* replace with */ );
}
- inputsB = progB->InputsRead;
- if (progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) {
+ /* compute combined program's InputsRead */
+ inputsB = progB_inputsRead;
+ if (progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) {
inputsB &= ~(1 << FRAG_ATTRIB_COL0);
}
newProg->InputsRead = progA->InputsRead | inputsB;
@@ -780,3 +826,63 @@ _mesa_find_free_register(const struct gl_program *prog, GLuint regFile)
return -1;
}
+
+
+
+/**
+ * "Post-process" a GPU program. This is intended to be used for debugging.
+ * Example actions include no-op'ing instructions or changing instruction
+ * behaviour.
+ */
+void
+_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog)
+{
+ static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 };
+ GLuint i;
+ GLuint whiteSwizzle;
+ GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters,
+ white, 4, &whiteSwizzle);
+
+ (void) whiteIndex;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
+
+ (void) n;
+
+ if (_mesa_is_tex_instruction(inst->Opcode)) {
+#if 0
+ /* replace TEX/TXP/TXB with MOV */
+ inst->Opcode = OPCODE_MOV;
+ inst->DstReg.WriteMask = WRITEMASK_XYZW;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
+ inst->SrcReg[0].Negate = NEGATE_NONE;
+#endif
+
+#if 0
+ /* disable shadow texture mode */
+ inst->TexShadow = 0;
+#endif
+ }
+
+ if (inst->Opcode == OPCODE_TXP) {
+#if 0
+ inst->Opcode = OPCODE_MOV;
+ inst->DstReg.WriteMask = WRITEMASK_XYZW;
+ inst->SrcReg[0].File = PROGRAM_CONSTANT;
+ inst->SrcReg[0].Index = whiteIndex;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
+ inst->SrcReg[0].Negate = NEGATE_NONE;
+#endif
+#if 0
+ inst->TexShadow = 0;
+#endif
+#if 0
+ inst->Opcode = OPCODE_TEX;
+ inst->TexShadow = 0;
+#endif
+ }
+
+ }
+}
diff --git a/src/mesa/shader/program.h b/src/mesa/shader/program.h
index 48176162c3..56a4191f57 100644
--- a/src/mesa/shader/program.h
+++ b/src/mesa/shader/program.h
@@ -122,6 +122,8 @@ _mesa_combine_programs(GLcontext *ctx,
extern GLint
_mesa_find_free_register(const struct gl_program *prog, GLuint regFile);
+extern void
+_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog);
#endif /* PROGRAM_H */
diff --git a/src/mesa/shader/program_lexer.l b/src/mesa/shader/program_lexer.l
new file mode 100644
index 0000000000..612f99a42d
--- /dev/null
+++ b/src/mesa/shader/program_lexer.l
@@ -0,0 +1,493 @@
+%{
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include "main/glheader.h"
+#include "prog_instruction.h"
+#include "prog_statevars.h"
+
+#include "program_parser.h"
+#include "program_parse.tab.h"
+
+#define require_ARB_vp (yyextra->mode == ARB_vertex)
+#define require_ARB_fp (yyextra->mode == ARB_fragment)
+#define require_shadow (yyextra->option.Shadow)
+#define require_rect (yyextra->option.TexRect)
+#define require_texarray (yyextra->option.TexArray)
+
+#ifndef HAVE_UNISTD_H
+#define YY_NO_UNISTD_H
+#endif
+
+#define return_token_or_IDENTIFIER(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define return_token_or_DOT(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yyless(1); \
+ return DOT; \
+ } \
+ } while (0)
+
+
+#define return_opcode(condition, token, opcode, sat) \
+ do { \
+ if (condition) { \
+ yylval->temp_inst.Opcode = OPCODE_ ## opcode; \
+ yylval->temp_inst.SaturateMode = SATURATE_ ## sat; \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define SWIZZLE_INVAL MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \
+ SWIZZLE_NIL, SWIZZLE_NIL)
+
+static unsigned
+mask_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return WRITEMASK_X;
+ case 'y':
+ case 'g':
+ return WRITEMASK_Y;
+ case 'z':
+ case 'b':
+ return WRITEMASK_Z;
+ case 'w':
+ case 'a':
+ return WRITEMASK_W;
+ }
+
+ return 0;
+}
+
+static unsigned
+swiz_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return SWIZZLE_X;
+ case 'y':
+ case 'g':
+ return SWIZZLE_Y;
+ case 'z':
+ case 'b':
+ return SWIZZLE_Z;
+ case 'w':
+ case 'a':
+ return SWIZZLE_W;
+ }
+
+ return 0;
+}
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->first_column = yylloc->last_column; \
+ yylloc->last_column += yyleng; \
+ if ((yylloc->first_line == 1) \
+ && (yylloc->first_column == 1)) { \
+ yylloc->position = 1; \
+ } else { \
+ yylloc->position += yylloc->last_column - yylloc->first_column; \
+ } \
+ } while(0);
+
+#define YY_EXTRA_TYPE struct asm_parser_state *
+%}
+
+num [0-9]+
+exp [Ee][-+]?[0-9]+
+frac "."[0-9]+
+dot "."[ \t]*
+
+%option bison-bridge bison-locations reentrant noyywrap
+%%
+
+"!!ARBvp1.0" { return ARBvp_10; }
+"!!ARBfp1.0" { return ARBfp_10; }
+ADDRESS {
+ yylval->integer = at_address;
+ return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
+}
+ALIAS { return ALIAS; }
+ATTRIB { return ATTRIB; }
+END { return END; }
+OPTION { return OPTION; }
+OUTPUT { return OUTPUT; }
+PARAM { return PARAM; }
+TEMP { yylval->integer = at_temp; return TEMP; }
+
+ABS { return_opcode( 1, VECTOR_OP, ABS, OFF); }
+ABS_SAT { return_opcode(require_ARB_fp, VECTOR_OP, ABS, ZERO_ONE); }
+ADD { return_opcode( 1, BIN_OP, ADD, OFF); }
+ADD_SAT { return_opcode(require_ARB_fp, BIN_OP, ADD, ZERO_ONE); }
+ARL { return_opcode(require_ARB_vp, ARL, ARL, OFF); }
+
+CMP { return_opcode(require_ARB_fp, TRI_OP, CMP, OFF); }
+CMP_SAT { return_opcode(require_ARB_fp, TRI_OP, CMP, ZERO_ONE); }
+COS { return_opcode(require_ARB_fp, SCALAR_OP, COS, OFF); }
+COS_SAT { return_opcode(require_ARB_fp, SCALAR_OP, COS, ZERO_ONE); }
+
+DP3 { return_opcode( 1, BIN_OP, DP3, OFF); }
+DP3_SAT { return_opcode(require_ARB_fp, BIN_OP, DP3, ZERO_ONE); }
+DP4 { return_opcode( 1, BIN_OP, DP4, OFF); }
+DP4_SAT { return_opcode(require_ARB_fp, BIN_OP, DP4, ZERO_ONE); }
+DPH { return_opcode( 1, BIN_OP, DPH, OFF); }
+DPH_SAT { return_opcode(require_ARB_fp, BIN_OP, DPH, ZERO_ONE); }
+DST { return_opcode( 1, BIN_OP, DST, OFF); }
+DST_SAT { return_opcode(require_ARB_fp, BIN_OP, DST, ZERO_ONE); }
+
+EX2 { return_opcode( 1, SCALAR_OP, EX2, OFF); }
+EX2_SAT { return_opcode(require_ARB_fp, SCALAR_OP, EX2, ZERO_ONE); }
+EXP { return_opcode(require_ARB_vp, SCALAR_OP, EXP, OFF); }
+
+FLR { return_opcode( 1, VECTOR_OP, FLR, OFF); }
+FLR_SAT { return_opcode(require_ARB_fp, VECTOR_OP, FLR, ZERO_ONE); }
+FRC { return_opcode( 1, VECTOR_OP, FRC, OFF); }
+FRC_SAT { return_opcode(require_ARB_fp, VECTOR_OP, FRC, ZERO_ONE); }
+
+KIL { return_opcode(require_ARB_fp, KIL, KIL, OFF); }
+
+LIT { return_opcode( 1, VECTOR_OP, LIT, OFF); }
+LIT_SAT { return_opcode(require_ARB_fp, VECTOR_OP, LIT, ZERO_ONE); }
+LG2 { return_opcode( 1, SCALAR_OP, LG2, OFF); }
+LG2_SAT { return_opcode(require_ARB_fp, SCALAR_OP, LG2, ZERO_ONE); }
+LOG { return_opcode(require_ARB_vp, SCALAR_OP, LOG, OFF); }
+LRP { return_opcode(require_ARB_fp, TRI_OP, LRP, OFF); }
+LRP_SAT { return_opcode(require_ARB_fp, TRI_OP, LRP, ZERO_ONE); }
+
+MAD { return_opcode( 1, TRI_OP, MAD, OFF); }
+MAD_SAT { return_opcode(require_ARB_fp, TRI_OP, MAD, ZERO_ONE); }
+MAX { return_opcode( 1, BIN_OP, MAX, OFF); }
+MAX_SAT { return_opcode(require_ARB_fp, BIN_OP, MAX, ZERO_ONE); }
+MIN { return_opcode( 1, BIN_OP, MIN, OFF); }
+MIN_SAT { return_opcode(require_ARB_fp, BIN_OP, MIN, ZERO_ONE); }
+MOV { return_opcode( 1, VECTOR_OP, MOV, OFF); }
+MOV_SAT { return_opcode(require_ARB_fp, VECTOR_OP, MOV, ZERO_ONE); }
+MUL { return_opcode( 1, BIN_OP, MUL, OFF); }
+MUL_SAT { return_opcode(require_ARB_fp, BIN_OP, MUL, ZERO_ONE); }
+
+POW { return_opcode( 1, BINSC_OP, POW, OFF); }
+POW_SAT { return_opcode(require_ARB_fp, BINSC_OP, POW, ZERO_ONE); }
+
+RCP { return_opcode( 1, SCALAR_OP, RCP, OFF); }
+RCP_SAT { return_opcode(require_ARB_fp, SCALAR_OP, RCP, ZERO_ONE); }
+RSQ { return_opcode( 1, SCALAR_OP, RSQ, OFF); }
+RSQ_SAT { return_opcode(require_ARB_fp, SCALAR_OP, RSQ, ZERO_ONE); }
+
+SCS { return_opcode(require_ARB_fp, SCALAR_OP, SCS, OFF); }
+SCS_SAT { return_opcode(require_ARB_fp, SCALAR_OP, SCS, ZERO_ONE); }
+SGE { return_opcode( 1, BIN_OP, SGE, OFF); }
+SGE_SAT { return_opcode(require_ARB_fp, BIN_OP, SGE, ZERO_ONE); }
+SIN { return_opcode(require_ARB_fp, SCALAR_OP, SIN, OFF); }
+SIN_SAT { return_opcode(require_ARB_fp, SCALAR_OP, SIN, ZERO_ONE); }
+SLT { return_opcode( 1, BIN_OP, SLT, OFF); }
+SLT_SAT { return_opcode(require_ARB_fp, BIN_OP, SLT, ZERO_ONE); }
+SUB { return_opcode( 1, BIN_OP, SUB, OFF); }
+SUB_SAT { return_opcode(require_ARB_fp, BIN_OP, SUB, ZERO_ONE); }
+SWZ { return_opcode( 1, SWZ, SWZ, OFF); }
+SWZ_SAT { return_opcode(require_ARB_fp, SWZ, SWZ, ZERO_ONE); }
+
+TEX { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, OFF); }
+TEX_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, ZERO_ONE); }
+TXB { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, OFF); }
+TXB_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, ZERO_ONE); }
+TXP { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, OFF); }
+TXP_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, ZERO_ONE); }
+
+XPD { return_opcode( 1, BIN_OP, XPD, OFF); }
+XPD_SAT { return_opcode(require_ARB_fp, BIN_OP, XPD, ZERO_ONE); }
+
+vertex { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
+fragment { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
+program { return PROGRAM; }
+state { return STATE; }
+result { return RESULT; }
+
+{dot}ambient { return AMBIENT; }
+{dot}attenuation { return ATTENUATION; }
+{dot}back { return BACK; }
+{dot}clip { return_token_or_DOT(require_ARB_vp, CLIP); }
+{dot}color { return COLOR; }
+{dot}depth { return_token_or_DOT(require_ARB_fp, DEPTH); }
+{dot}diffuse { return DIFFUSE; }
+{dot}direction { return DIRECTION; }
+{dot}emission { return EMISSION; }
+{dot}env { return ENV; }
+{dot}eye { return EYE; }
+{dot}fogcoord { return FOGCOORD; }
+{dot}fog { return FOG; }
+{dot}front { return FRONT; }
+{dot}half { return HALF; }
+{dot}inverse { return INVERSE; }
+{dot}invtrans { return INVTRANS; }
+{dot}light { return LIGHT; }
+{dot}lightmodel { return LIGHTMODEL; }
+{dot}lightprod { return LIGHTPROD; }
+{dot}local { return LOCAL; }
+{dot}material { return MATERIAL; }
+{dot}program { return MAT_PROGRAM; }
+{dot}matrix { return MATRIX; }
+{dot}matrixindex { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); }
+{dot}modelview { return MODELVIEW; }
+{dot}mvp { return MVP; }
+{dot}normal { return_token_or_DOT(require_ARB_vp, NORMAL); }
+{dot}object { return OBJECT; }
+{dot}palette { return PALETTE; }
+{dot}params { return PARAMS; }
+{dot}plane { return PLANE; }
+{dot}point { return_token_or_DOT(require_ARB_vp, POINT_TOK); }
+{dot}pointsize { return_token_or_DOT(require_ARB_vp, POINTSIZE); }
+{dot}position { return POSITION; }
+{dot}primary { return PRIMARY; }
+{dot}projection { return PROJECTION; }
+{dot}range { return_token_or_DOT(require_ARB_fp, RANGE); }
+{dot}row { return ROW; }
+{dot}scenecolor { return SCENECOLOR; }
+{dot}secondary { return SECONDARY; }
+{dot}shininess { return SHININESS; }
+{dot}size { return_token_or_DOT(require_ARB_vp, SIZE_TOK); }
+{dot}specular { return SPECULAR; }
+{dot}spot { return SPOT; }
+{dot}texcoord { return TEXCOORD; }
+{dot}texenv { return_token_or_DOT(require_ARB_fp, TEXENV); }
+{dot}texgen { return_token_or_DOT(require_ARB_vp, TEXGEN); }
+{dot}q { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); }
+{dot}s { return_token_or_DOT(require_ARB_vp, TEXGEN_S); }
+{dot}t { return_token_or_DOT(require_ARB_vp, TEXGEN_T); }
+{dot}texture { return TEXTURE; }
+{dot}transpose { return TRANSPOSE; }
+{dot}attrib { return_token_or_DOT(require_ARB_vp, VTXATTRIB); }
+{dot}weight { return_token_or_DOT(require_ARB_vp, WEIGHT); }
+
+texture { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
+1D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
+2D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
+3D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
+CUBE { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
+RECT { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); }
+SHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); }
+SHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); }
+SHADOWRECT { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); }
+ARRAY1D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); }
+ARRAY2D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); }
+ARRAYSHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); }
+ARRAYSHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); }
+
+[_a-zA-Z$][_a-zA-Z0-9$]* {
+ yylval->string = strdup(yytext);
+ return IDENTIFIER;
+}
+
+".." { return DOT_DOT; }
+
+{num} {
+ yylval->integer = strtol(yytext, NULL, 10);
+ return INTEGER;
+}
+{num}?{frac}{exp}? {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+{num}"."/[^.] {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+{num}{exp} {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+{num}"."{exp} {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+
+".xyzw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return MASK4;
+}
+
+".xy"[zw] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return MASK3;
+}
+".xzw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return MASK3;
+}
+".yzw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return MASK3;
+}
+
+".x"[yzw] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+".y"[zw] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+".zw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return MASK2;
+}
+
+"."[xyzw] {
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return MASK1;
+}
+
+"."[xyzw]{4} {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return SWIZZLE;
+}
+
+".rgba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return_token_or_DOT(require_ARB_fp, MASK4);
+}
+
+".rg"[ba] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+".rba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+".gba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+
+".r"[gba] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+".g"[ba] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+".ba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+
+"."[gba] {
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return_token_or_DOT(require_ARB_fp, MASK1);
+}
+
+
+".r" {
+ if (require_ARB_vp) {
+ return TEXGEN_R;
+ } else {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
+ SWIZZLE_X, SWIZZLE_X);
+ yylval->swiz_mask.mask = WRITEMASK_X;
+ return MASK1;
+ }
+}
+
+"."[rgba]{4} {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return_token_or_DOT(require_ARB_fp, SWIZZLE);
+}
+
+"." { return DOT; }
+
+\n {
+ yylloc->first_line++;
+ yylloc->first_column = 1;
+ yylloc->last_line++;
+ yylloc->last_column = 1;
+ yylloc->position++;
+}
+[ \t\r]+ /* eat whitespace */ ;
+#.*$ /* eat comments */ ;
+. { return yytext[0]; }
+%%
+
+void
+_mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state,
+ const char *string, size_t len)
+{
+ yylex_init_extra(state, scanner);
+ yy_scan_bytes(string, len, *scanner);
+}
+
+void
+_mesa_program_lexer_dtor(void *scanner)
+{
+ yylex_destroy(scanner);
+}
diff --git a/src/mesa/shader/program_parse.tab.c b/src/mesa/shader/program_parse.tab.c
new file mode 100644
index 0000000000..9f2d4de90f
--- /dev/null
+++ b/src/mesa/shader/program_parse.tab.c
@@ -0,0 +1,5249 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.1"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 1
+
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 1 "program_parse.y"
+
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "program.h"
+#include "prog_parameter.h"
+#include "prog_parameter_layout.h"
+#include "prog_statevars.h"
+#include "prog_instruction.h"
+
+#include "symbol_table.h"
+#include "program_parser.h"
+
+extern void *yy_scan_string(char *);
+extern void yy_delete_buffer(void *);
+
+static struct asm_symbol *declare_variable(struct asm_parser_state *state,
+ char *name, enum asm_type t, struct YYLTYPE *locp);
+
+static int add_state_reference(struct gl_program_parameter_list *param_list,
+ const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_state(struct gl_program *prog,
+ struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_param(struct gl_program *prog,
+ struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_const(struct gl_program *prog,
+ struct asm_symbol *param_var, const struct asm_vector *vec);
+
+static int yyparse(struct asm_parser_state *state);
+
+static char *make_error_string(const char *fmt, ...);
+
+static void yyerror(struct YYLTYPE *locp, struct asm_parser_state *state,
+ const char *s);
+
+static int validate_inputs(struct YYLTYPE *locp,
+ struct asm_parser_state *state);
+
+static void init_dst_reg(struct prog_dst_register *r);
+
+static void init_src_reg(struct asm_src_register *r);
+
+static struct asm_instruction *asm_instruction_ctor(gl_inst_opcode op,
+ const struct prog_dst_register *dst, const struct asm_src_register *src0,
+ const struct asm_src_register *src1, const struct asm_src_register *src2);
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do { \
+ if (YYID(N)) { \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
+ (Current).position = YYRHSLOC(Rhs, 1).position; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC(Rhs, N).last_column; \
+ } else { \
+ (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \
+ (Current).last_line = (Current).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 0).last_column; \
+ (Current).last_column = (Current).first_column; \
+ (Current).position = YYRHSLOC(Rhs, 0).position \
+ + (Current).first_column; \
+ } \
+ } while(YYID(0))
+
+#define YYLEX_PARAM state->scanner
+
+
+/* Line 189 of yacc.c */
+#line 174 "program_parse.tab.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ARBvp_10 = 258,
+ ARBfp_10 = 259,
+ ADDRESS = 260,
+ ALIAS = 261,
+ ATTRIB = 262,
+ OPTION = 263,
+ OUTPUT = 264,
+ PARAM = 265,
+ TEMP = 266,
+ END = 267,
+ BIN_OP = 268,
+ BINSC_OP = 269,
+ SAMPLE_OP = 270,
+ SCALAR_OP = 271,
+ TRI_OP = 272,
+ VECTOR_OP = 273,
+ ARL = 274,
+ KIL = 275,
+ SWZ = 276,
+ INTEGER = 277,
+ REAL = 278,
+ AMBIENT = 279,
+ ATTENUATION = 280,
+ BACK = 281,
+ CLIP = 282,
+ COLOR = 283,
+ DEPTH = 284,
+ DIFFUSE = 285,
+ DIRECTION = 286,
+ EMISSION = 287,
+ ENV = 288,
+ EYE = 289,
+ FOG = 290,
+ FOGCOORD = 291,
+ FRAGMENT = 292,
+ FRONT = 293,
+ HALF = 294,
+ INVERSE = 295,
+ INVTRANS = 296,
+ LIGHT = 297,
+ LIGHTMODEL = 298,
+ LIGHTPROD = 299,
+ LOCAL = 300,
+ MATERIAL = 301,
+ MAT_PROGRAM = 302,
+ MATRIX = 303,
+ MATRIXINDEX = 304,
+ MODELVIEW = 305,
+ MVP = 306,
+ NORMAL = 307,
+ OBJECT = 308,
+ PALETTE = 309,
+ PARAMS = 310,
+ PLANE = 311,
+ POINT_TOK = 312,
+ POINTSIZE = 313,
+ POSITION = 314,
+ PRIMARY = 315,
+ PROGRAM = 316,
+ PROJECTION = 317,
+ RANGE = 318,
+ RESULT = 319,
+ ROW = 320,
+ SCENECOLOR = 321,
+ SECONDARY = 322,
+ SHININESS = 323,
+ SIZE_TOK = 324,
+ SPECULAR = 325,
+ SPOT = 326,
+ STATE = 327,
+ TEXCOORD = 328,
+ TEXENV = 329,
+ TEXGEN = 330,
+ TEXGEN_Q = 331,
+ TEXGEN_R = 332,
+ TEXGEN_S = 333,
+ TEXGEN_T = 334,
+ TEXTURE = 335,
+ TRANSPOSE = 336,
+ TEXTURE_UNIT = 337,
+ TEX_1D = 338,
+ TEX_2D = 339,
+ TEX_3D = 340,
+ TEX_CUBE = 341,
+ TEX_RECT = 342,
+ TEX_SHADOW1D = 343,
+ TEX_SHADOW2D = 344,
+ TEX_SHADOWRECT = 345,
+ TEX_ARRAY1D = 346,
+ TEX_ARRAY2D = 347,
+ TEX_ARRAYSHADOW1D = 348,
+ TEX_ARRAYSHADOW2D = 349,
+ VERTEX = 350,
+ VTXATTRIB = 351,
+ WEIGHT = 352,
+ IDENTIFIER = 353,
+ MASK4 = 354,
+ MASK3 = 355,
+ MASK2 = 356,
+ MASK1 = 357,
+ SWIZZLE = 358,
+ DOT_DOT = 359,
+ DOT = 360
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 214 of yacc.c */
+#line 107 "program_parse.y"
+
+ struct asm_instruction *inst;
+ struct asm_symbol *sym;
+ struct asm_symbol temp_sym;
+ struct asm_swizzle_mask swiz_mask;
+ struct asm_src_register src_reg;
+ struct prog_dst_register dst_reg;
+ struct prog_instruction temp_inst;
+ char *string;
+ unsigned result;
+ unsigned attrib;
+ int integer;
+ float real;
+ gl_state_index state[STATE_LENGTH];
+ int negate;
+ struct asm_vector vector;
+ gl_inst_opcode opcode;
+
+ struct {
+ unsigned swz;
+ unsigned rgba_valid:1;
+ unsigned xyzw_valid:1;
+ unsigned negate:1;
+ } ext_swizzle;
+
+
+
+/* Line 214 of yacc.c */
+#line 343 "program_parse.tab.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+/* Line 264 of yacc.c */
+#line 249 "program_parse.y"
+
+extern int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param,
+ void *yyscanner);
+
+
+/* Line 264 of yacc.c */
+#line 374 "program_parse.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+ YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 5
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 342
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 115
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 134
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 264
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 436
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 360
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 110, 107, 111, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 106,
+ 2, 112, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 108, 2, 109, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 113, 2, 114, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 8, 10, 12, 15, 16, 20, 23,
+ 24, 27, 30, 32, 34, 36, 38, 40, 42, 44,
+ 46, 48, 50, 52, 57, 62, 67, 74, 81, 90,
+ 99, 102, 105, 107, 109, 111, 113, 115, 117, 119,
+ 121, 123, 125, 127, 129, 136, 140, 144, 147, 150,
+ 158, 161, 163, 165, 167, 169, 174, 176, 178, 180,
+ 182, 184, 186, 188, 192, 193, 196, 199, 201, 203,
+ 205, 207, 209, 211, 213, 215, 217, 218, 220, 222,
+ 224, 226, 227, 229, 231, 233, 235, 237, 239, 244,
+ 247, 250, 252, 255, 257, 260, 262, 265, 270, 275,
+ 277, 278, 282, 284, 286, 289, 291, 294, 296, 298,
+ 302, 309, 310, 312, 315, 320, 322, 326, 328, 330,
+ 332, 334, 336, 338, 340, 342, 344, 346, 349, 352,
+ 355, 358, 361, 364, 367, 370, 373, 376, 379, 382,
+ 386, 388, 390, 392, 398, 400, 402, 404, 407, 409,
+ 411, 414, 416, 419, 426, 428, 432, 434, 436, 438,
+ 440, 442, 447, 449, 451, 453, 455, 457, 459, 462,
+ 464, 466, 472, 474, 477, 479, 481, 487, 490, 491,
+ 498, 502, 503, 505, 507, 509, 511, 513, 516, 518,
+ 520, 523, 528, 533, 534, 538, 540, 542, 544, 547,
+ 549, 551, 553, 555, 561, 563, 567, 573, 579, 581,
+ 585, 591, 593, 595, 597, 599, 601, 603, 605, 607,
+ 609, 613, 619, 627, 637, 640, 643, 645, 647, 648,
+ 649, 653, 654, 658, 662, 664, 669, 672, 675, 678,
+ 681, 685, 688, 692, 693, 695, 697, 698, 700, 702,
+ 703, 705, 707, 708, 710, 712, 713, 717, 718, 722,
+ 723, 727, 729, 731, 733
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int16 yyrhs[] =
+{
+ 116, 0, -1, 117, 118, 120, 12, -1, 3, -1,
+ 4, -1, 118, 119, -1, -1, 8, 98, 106, -1,
+ 120, 121, -1, -1, 122, 106, -1, 158, 106, -1,
+ 123, -1, 124, -1, 125, -1, 126, -1, 127, -1,
+ 128, -1, 129, -1, 130, -1, 135, -1, 131, -1,
+ 132, -1, 19, 139, 107, 136, -1, 18, 138, 107,
+ 137, -1, 16, 138, 107, 136, -1, 14, 138, 107,
+ 136, 107, 136, -1, 13, 138, 107, 137, 107, 137,
+ -1, 17, 138, 107, 137, 107, 137, 107, 137, -1,
+ 15, 138, 107, 137, 107, 133, 107, 134, -1, 20,
+ 137, -1, 82, 243, -1, 83, -1, 84, -1, 85,
+ -1, 86, -1, 87, -1, 88, -1, 89, -1, 90,
+ -1, 91, -1, 92, -1, 93, -1, 94, -1, 21,
+ 138, 107, 143, 107, 140, -1, 229, 143, 155, -1,
+ 229, 143, 156, -1, 144, 157, -1, 152, 154, -1,
+ 141, 107, 141, 107, 141, 107, 141, -1, 229, 142,
+ -1, 22, -1, 98, -1, 98, -1, 160, -1, 145,
+ 108, 146, 109, -1, 174, -1, 236, -1, 98, -1,
+ 98, -1, 147, -1, 148, -1, 22, -1, 152, 153,
+ 149, -1, -1, 110, 150, -1, 111, 151, -1, 22,
+ -1, 22, -1, 98, -1, 102, -1, 102, -1, 102,
+ -1, 102, -1, 99, -1, 103, -1, -1, 99, -1,
+ 100, -1, 101, -1, 102, -1, -1, 159, -1, 166,
+ -1, 230, -1, 232, -1, 235, -1, 248, -1, 7,
+ 98, 112, 160, -1, 95, 161, -1, 37, 165, -1,
+ 59, -1, 97, 163, -1, 52, -1, 28, 241, -1,
+ 36, -1, 73, 242, -1, 49, 108, 164, 109, -1,
+ 96, 108, 162, 109, -1, 22, -1, -1, 108, 164,
+ 109, -1, 22, -1, 59, -1, 28, 241, -1, 36,
+ -1, 73, 242, -1, 167, -1, 168, -1, 10, 98,
+ 170, -1, 10, 98, 108, 169, 109, 171, -1, -1,
+ 22, -1, 112, 173, -1, 112, 113, 172, 114, -1,
+ 175, -1, 172, 107, 175, -1, 177, -1, 213, -1,
+ 223, -1, 177, -1, 213, -1, 224, -1, 176, -1,
+ 214, -1, 223, -1, 177, -1, 72, 201, -1, 72,
+ 178, -1, 72, 180, -1, 72, 183, -1, 72, 185,
+ -1, 72, 191, -1, 72, 187, -1, 72, 194, -1,
+ 72, 196, -1, 72, 198, -1, 72, 200, -1, 72,
+ 212, -1, 46, 240, 179, -1, 189, -1, 32, -1,
+ 68, -1, 42, 108, 190, 109, 181, -1, 189, -1,
+ 59, -1, 25, -1, 71, 182, -1, 39, -1, 31,
+ -1, 43, 184, -1, 24, -1, 240, 66, -1, 44,
+ 108, 190, 109, 240, 186, -1, 189, -1, 74, 244,
+ 188, -1, 28, -1, 24, -1, 30, -1, 70, -1,
+ 22, -1, 75, 242, 192, 193, -1, 34, -1, 53,
+ -1, 78, -1, 79, -1, 77, -1, 76, -1, 35,
+ 195, -1, 28, -1, 55, -1, 27, 108, 197, 109,
+ 56, -1, 22, -1, 57, 199, -1, 69, -1, 25,
+ -1, 203, 65, 108, 206, 109, -1, 203, 202, -1,
+ -1, 65, 108, 206, 104, 206, 109, -1, 48, 207,
+ 204, -1, -1, 205, -1, 40, -1, 81, -1, 41,
+ -1, 22, -1, 50, 208, -1, 62, -1, 51, -1,
+ 80, 242, -1, 54, 108, 210, 109, -1, 47, 108,
+ 211, 109, -1, -1, 108, 209, 109, -1, 22, -1,
+ 22, -1, 22, -1, 29, 63, -1, 217, -1, 220,
+ -1, 215, -1, 218, -1, 61, 33, 108, 216, 109,
+ -1, 221, -1, 221, 104, 221, -1, 61, 33, 108,
+ 221, 109, -1, 61, 45, 108, 219, 109, -1, 222,
+ -1, 222, 104, 222, -1, 61, 45, 108, 222, 109,
+ -1, 22, -1, 22, -1, 225, -1, 227, -1, 226,
+ -1, 227, -1, 228, -1, 23, -1, 22, -1, 113,
+ 228, 114, -1, 113, 228, 107, 228, 114, -1, 113,
+ 228, 107, 228, 107, 228, 114, -1, 113, 228, 107,
+ 228, 107, 228, 107, 228, 114, -1, 229, 23, -1,
+ 229, 22, -1, 110, -1, 111, -1, -1, -1, 11,
+ 231, 234, -1, -1, 5, 233, 234, -1, 234, 107,
+ 98, -1, 98, -1, 9, 98, 112, 236, -1, 64,
+ 59, -1, 64, 36, -1, 64, 237, -1, 64, 58,
+ -1, 64, 73, 242, -1, 64, 29, -1, 28, 238,
+ 239, -1, -1, 38, -1, 26, -1, -1, 60, -1,
+ 67, -1, -1, 38, -1, 26, -1, -1, 60, -1,
+ 67, -1, -1, 108, 245, 109, -1, -1, 108, 246,
+ 109, -1, -1, 108, 247, 109, -1, 22, -1, 22,
+ -1, 22, -1, 6, 98, 112, 98, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 256, 256, 259, 267, 279, 280, 283, 305, 306,
+ 309, 324, 327, 332, 339, 340, 341, 342, 343, 344,
+ 345, 348, 349, 352, 358, 365, 372, 380, 387, 395,
+ 440, 447, 453, 454, 455, 456, 457, 458, 459, 460,
+ 461, 462, 463, 464, 467, 480, 493, 506, 528, 537,
+ 570, 577, 592, 642, 684, 695, 716, 726, 732, 763,
+ 780, 780, 782, 789, 801, 802, 803, 806, 818, 830,
+ 848, 859, 871, 873, 874, 875, 876, 879, 879, 879,
+ 879, 880, 883, 884, 885, 886, 887, 888, 891, 909,
+ 913, 919, 923, 927, 931, 940, 949, 953, 958, 964,
+ 975, 975, 976, 978, 982, 986, 990, 996, 996, 998,
+ 1014, 1037, 1040, 1051, 1057, 1063, 1064, 1071, 1077, 1083,
+ 1091, 1097, 1103, 1111, 1117, 1123, 1131, 1132, 1135, 1136,
+ 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1148,
+ 1157, 1161, 1165, 1171, 1180, 1184, 1188, 1197, 1201, 1207,
+ 1213, 1220, 1225, 1233, 1243, 1245, 1253, 1259, 1263, 1267,
+ 1273, 1284, 1293, 1297, 1302, 1306, 1310, 1314, 1320, 1327,
+ 1331, 1337, 1345, 1356, 1363, 1367, 1373, 1383, 1394, 1398,
+ 1416, 1425, 1428, 1434, 1438, 1442, 1448, 1459, 1464, 1469,
+ 1474, 1479, 1484, 1492, 1495, 1500, 1513, 1521, 1532, 1540,
+ 1540, 1542, 1542, 1544, 1554, 1559, 1566, 1576, 1585, 1590,
+ 1597, 1607, 1617, 1629, 1629, 1630, 1630, 1632, 1642, 1650,
+ 1660, 1668, 1676, 1685, 1696, 1700, 1706, 1707, 1708, 1711,
+ 1711, 1714, 1714, 1717, 1723, 1731, 1744, 1753, 1762, 1766,
+ 1775, 1784, 1795, 1802, 1807, 1816, 1828, 1831, 1840, 1851,
+ 1852, 1853, 1856, 1857, 1858, 1861, 1862, 1865, 1866, 1869,
+ 1870, 1873, 1884, 1895, 1906
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "ARBvp_10", "ARBfp_10", "ADDRESS",
+ "ALIAS", "ATTRIB", "OPTION", "OUTPUT", "PARAM", "TEMP", "END", "BIN_OP",
+ "BINSC_OP", "SAMPLE_OP", "SCALAR_OP", "TRI_OP", "VECTOR_OP", "ARL",
+ "KIL", "SWZ", "INTEGER", "REAL", "AMBIENT", "ATTENUATION", "BACK",
+ "CLIP", "COLOR", "DEPTH", "DIFFUSE", "DIRECTION", "EMISSION", "ENV",
+ "EYE", "FOG", "FOGCOORD", "FRAGMENT", "FRONT", "HALF", "INVERSE",
+ "INVTRANS", "LIGHT", "LIGHTMODEL", "LIGHTPROD", "LOCAL", "MATERIAL",
+ "MAT_PROGRAM", "MATRIX", "MATRIXINDEX", "MODELVIEW", "MVP", "NORMAL",
+ "OBJECT", "PALETTE", "PARAMS", "PLANE", "POINT_TOK", "POINTSIZE",
+ "POSITION", "PRIMARY", "PROGRAM", "PROJECTION", "RANGE", "RESULT", "ROW",
+ "SCENECOLOR", "SECONDARY", "SHININESS", "SIZE_TOK", "SPECULAR", "SPOT",
+ "STATE", "TEXCOORD", "TEXENV", "TEXGEN", "TEXGEN_Q", "TEXGEN_R",
+ "TEXGEN_S", "TEXGEN_T", "TEXTURE", "TRANSPOSE", "TEXTURE_UNIT", "TEX_1D",
+ "TEX_2D", "TEX_3D", "TEX_CUBE", "TEX_RECT", "TEX_SHADOW1D",
+ "TEX_SHADOW2D", "TEX_SHADOWRECT", "TEX_ARRAY1D", "TEX_ARRAY2D",
+ "TEX_ARRAYSHADOW1D", "TEX_ARRAYSHADOW2D", "VERTEX", "VTXATTRIB",
+ "WEIGHT", "IDENTIFIER", "MASK4", "MASK3", "MASK2", "MASK1", "SWIZZLE",
+ "DOT_DOT", "DOT", "';'", "','", "'['", "']'", "'+'", "'-'", "'='", "'{'",
+ "'}'", "$accept", "program", "language", "optionSequence", "option",
+ "statementSequence", "statement", "instruction", "ALU_instruction",
+ "TexInstruction", "ARL_instruction", "VECTORop_instruction",
+ "SCALARop_instruction", "BINSCop_instruction", "BINop_instruction",
+ "TRIop_instruction", "SAMPLE_instruction", "KIL_instruction",
+ "texImageUnit", "texTarget", "SWZ_instruction", "scalarSrcReg",
+ "swizzleSrcReg", "maskedDstReg", "maskedAddrReg", "extendedSwizzle",
+ "extSwizComp", "extSwizSel", "srcReg", "dstReg", "progParamArray",
+ "progParamArrayMem", "progParamArrayAbs", "progParamArrayRel",
+ "addrRegRelOffset", "addrRegPosOffset", "addrRegNegOffset", "addrReg",
+ "addrComponent", "addrWriteMask", "scalarSuffix", "swizzleSuffix",
+ "optionalMask", "namingStatement", "ATTRIB_statement", "attribBinding",
+ "vtxAttribItem", "vtxAttribNum", "vtxOptWeightNum", "vtxWeightNum",
+ "fragAttribItem", "PARAM_statement", "PARAM_singleStmt",
+ "PARAM_multipleStmt", "optArraySize", "paramSingleInit",
+ "paramMultipleInit", "paramMultInitList", "paramSingleItemDecl",
+ "paramSingleItemUse", "paramMultipleItem", "stateMultipleItem",
+ "stateSingleItem", "stateMaterialItem", "stateMatProperty",
+ "stateLightItem", "stateLightProperty", "stateSpotProperty",
+ "stateLightModelItem", "stateLModProperty", "stateLightProdItem",
+ "stateLProdProperty", "stateTexEnvItem", "stateTexEnvProperty",
+ "ambDiffSpecProperty", "stateLightNumber", "stateTexGenItem",
+ "stateTexGenType", "stateTexGenCoord", "stateFogItem",
+ "stateFogProperty", "stateClipPlaneItem", "stateClipPlaneNum",
+ "statePointItem", "statePointProperty", "stateMatrixRow",
+ "stateMatrixRows", "optMatrixRows", "stateMatrixItem",
+ "stateOptMatModifier", "stateMatModifier", "stateMatrixRowNum",
+ "stateMatrixName", "stateOptModMatNum", "stateModMatNum",
+ "statePaletteMatNum", "stateProgramMatNum", "stateDepthItem",
+ "programSingleItem", "programMultipleItem", "progEnvParams",
+ "progEnvParamNums", "progEnvParam", "progLocalParams",
+ "progLocalParamNums", "progLocalParam", "progEnvParamNum",
+ "progLocalParamNum", "paramConstDecl", "paramConstUse",
+ "paramConstScalarDecl", "paramConstScalarUse", "paramConstVector",
+ "signedFloatConstant", "optionalSign", "TEMP_statement", "@1",
+ "ADDRESS_statement", "@2", "varNameList", "OUTPUT_statement",
+ "resultBinding", "resultColBinding", "optResultFaceType",
+ "optResultColorType", "optFaceType", "optColorType",
+ "optTexCoordUnitNum", "optTexImageUnitNum", "optLegacyTexUnitNum",
+ "texCoordUnitNum", "texImageUnitNum", "legacyTexUnitNum",
+ "ALIAS_statement", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 360, 59, 44, 91, 93,
+ 43, 45, 61, 123, 125
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 115, 116, 117, 117, 118, 118, 119, 120, 120,
+ 121, 121, 122, 122, 123, 123, 123, 123, 123, 123,
+ 123, 124, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 135, 136, 137, 138, 139, 140,
+ 141, 142, 142, 143, 143, 143, 143, 144, 144, 145,
+ 146, 146, 147, 148, 149, 149, 149, 150, 151, 152,
+ 153, 154, 155, 156, 156, 156, 156, 157, 157, 157,
+ 157, 157, 158, 158, 158, 158, 158, 158, 159, 160,
+ 160, 161, 161, 161, 161, 161, 161, 161, 161, 162,
+ 163, 163, 164, 165, 165, 165, 165, 166, 166, 167,
+ 168, 169, 169, 170, 171, 172, 172, 173, 173, 173,
+ 174, 174, 174, 175, 175, 175, 176, 176, 177, 177,
+ 177, 177, 177, 177, 177, 177, 177, 177, 177, 178,
+ 179, 179, 179, 180, 181, 181, 181, 181, 181, 182,
+ 183, 184, 184, 185, 186, 187, 188, 189, 189, 189,
+ 190, 191, 192, 192, 193, 193, 193, 193, 194, 195,
+ 195, 196, 197, 198, 199, 199, 200, 201, 202, 202,
+ 203, 204, 204, 205, 205, 205, 206, 207, 207, 207,
+ 207, 207, 207, 208, 208, 209, 210, 211, 212, 213,
+ 213, 214, 214, 215, 216, 216, 217, 218, 219, 219,
+ 220, 221, 222, 223, 223, 224, 224, 225, 226, 226,
+ 227, 227, 227, 227, 228, 228, 229, 229, 229, 231,
+ 230, 233, 232, 234, 234, 235, 236, 236, 236, 236,
+ 236, 236, 237, 238, 238, 238, 239, 239, 239, 240,
+ 240, 240, 241, 241, 241, 242, 242, 243, 243, 244,
+ 244, 245, 246, 247, 248
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 4, 1, 1, 2, 0, 3, 2, 0,
+ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 4, 4, 4, 6, 6, 8, 8,
+ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 6, 3, 3, 2, 2, 7,
+ 2, 1, 1, 1, 1, 4, 1, 1, 1, 1,
+ 1, 1, 1, 3, 0, 2, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 4, 2,
+ 2, 1, 2, 1, 2, 1, 2, 4, 4, 1,
+ 0, 3, 1, 1, 2, 1, 2, 1, 1, 3,
+ 6, 0, 1, 2, 4, 1, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+ 1, 1, 1, 5, 1, 1, 1, 2, 1, 1,
+ 2, 1, 2, 6, 1, 3, 1, 1, 1, 1,
+ 1, 4, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 5, 1, 2, 1, 1, 5, 2, 0, 6,
+ 3, 0, 1, 1, 1, 1, 1, 2, 1, 1,
+ 2, 4, 4, 0, 3, 1, 1, 1, 2, 1,
+ 1, 1, 1, 5, 1, 3, 5, 5, 1, 3,
+ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 5, 7, 9, 2, 2, 1, 1, 0, 0,
+ 3, 0, 3, 3, 1, 4, 2, 2, 2, 2,
+ 3, 2, 3, 0, 1, 1, 0, 1, 1, 0,
+ 1, 1, 0, 1, 1, 0, 3, 0, 3, 0,
+ 3, 1, 1, 1, 4
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint16 yydefact[] =
+{
+ 0, 3, 4, 0, 6, 1, 9, 0, 5, 0,
+ 0, 231, 0, 0, 0, 0, 229, 2, 0, 0,
+ 0, 0, 0, 0, 0, 228, 0, 8, 0, 12,
+ 13, 14, 15, 16, 17, 18, 19, 21, 22, 20,
+ 0, 82, 83, 107, 108, 84, 85, 86, 87, 7,
+ 0, 0, 0, 0, 0, 0, 0, 58, 0, 81,
+ 57, 0, 0, 0, 0, 0, 69, 0, 0, 226,
+ 227, 30, 0, 0, 10, 11, 234, 232, 0, 0,
+ 0, 111, 228, 109, 230, 243, 241, 237, 239, 236,
+ 255, 238, 228, 77, 78, 79, 80, 47, 228, 228,
+ 228, 228, 228, 228, 71, 48, 219, 218, 0, 0,
+ 0, 0, 53, 228, 76, 0, 54, 56, 120, 121,
+ 199, 200, 122, 215, 216, 0, 0, 264, 88, 235,
+ 112, 0, 113, 117, 118, 119, 213, 214, 217, 0,
+ 245, 244, 246, 0, 240, 0, 0, 0, 0, 25,
+ 0, 24, 23, 252, 105, 103, 255, 90, 0, 0,
+ 0, 0, 0, 0, 249, 0, 249, 0, 0, 259,
+ 255, 128, 129, 130, 131, 133, 132, 134, 135, 136,
+ 137, 0, 138, 252, 95, 0, 93, 91, 255, 0,
+ 100, 89, 0, 74, 73, 75, 46, 0, 0, 233,
+ 0, 225, 224, 247, 248, 242, 261, 0, 228, 228,
+ 0, 0, 228, 253, 254, 104, 106, 0, 0, 0,
+ 198, 169, 170, 168, 0, 151, 251, 250, 150, 0,
+ 0, 0, 0, 193, 189, 0, 188, 255, 181, 175,
+ 174, 173, 0, 0, 0, 0, 94, 0, 96, 0,
+ 0, 92, 228, 220, 62, 0, 60, 61, 0, 228,
+ 0, 110, 256, 27, 26, 72, 45, 257, 0, 0,
+ 211, 0, 212, 0, 172, 0, 160, 0, 152, 0,
+ 157, 158, 141, 142, 159, 139, 140, 0, 0, 187,
+ 0, 190, 183, 185, 184, 180, 182, 263, 0, 156,
+ 155, 162, 163, 0, 0, 102, 0, 99, 0, 0,
+ 0, 55, 70, 64, 44, 0, 0, 228, 0, 31,
+ 0, 228, 206, 210, 0, 0, 249, 197, 0, 195,
+ 0, 196, 0, 260, 167, 166, 164, 165, 161, 186,
+ 0, 97, 98, 101, 228, 221, 0, 0, 63, 228,
+ 51, 52, 50, 0, 0, 0, 115, 123, 126, 124,
+ 201, 202, 125, 262, 0, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 29, 28, 171,
+ 146, 148, 145, 0, 143, 144, 0, 192, 194, 191,
+ 176, 0, 67, 65, 68, 66, 0, 0, 0, 127,
+ 178, 228, 114, 258, 149, 147, 153, 154, 228, 222,
+ 228, 0, 0, 0, 177, 116, 0, 0, 0, 204,
+ 0, 208, 0, 223, 228, 203, 0, 207, 0, 0,
+ 49, 205, 209, 0, 0, 179
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 3, 4, 6, 8, 9, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 268, 377,
+ 39, 146, 71, 58, 67, 314, 315, 352, 114, 59,
+ 115, 255, 256, 257, 348, 393, 395, 68, 313, 105,
+ 266, 196, 97, 40, 41, 116, 191, 308, 251, 306,
+ 157, 42, 43, 44, 131, 83, 261, 355, 132, 117,
+ 356, 357, 118, 171, 285, 172, 384, 405, 173, 228,
+ 174, 406, 175, 300, 286, 277, 176, 303, 338, 177,
+ 223, 178, 275, 179, 241, 180, 399, 414, 181, 295,
+ 296, 340, 238, 289, 330, 332, 328, 182, 119, 359,
+ 360, 418, 120, 361, 420, 121, 271, 273, 362, 122,
+ 136, 123, 124, 138, 72, 45, 55, 46, 50, 77,
+ 47, 60, 91, 142, 205, 229, 215, 144, 319, 243,
+ 207, 364, 298, 48
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -369
+static const yytype_int16 yypact[] =
+{
+ 143, -369, -369, 36, -369, -369, 45, -39, -369, 169,
+ -33, -369, -19, -6, -4, 12, -369, -369, -34, -34,
+ -34, -34, -34, -34, 15, 62, -34, -369, 26, -369,
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ 60, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ 20, 56, 107, 110, 37, 20, -3, -369, 111, 109,
+ -369, 113, 114, 116, 117, 118, -369, 119, 125, -369,
+ -369, -369, -15, 121, -369, -369, -369, 122, 132, -18,
+ 167, 210, -11, -369, 122, 63, -369, -369, -369, -369,
+ 130, -369, 62, -369, -369, -369, -369, -369, 62, 62,
+ 62, 62, 62, 62, -369, -369, -369, -369, 9, 72,
+ 87, -1, 131, 62, 104, 134, -369, -369, -369, -369,
+ -369, -369, -369, -369, -369, -15, 142, -369, -369, -369,
+ -369, 135, -369, -369, -369, -369, -369, -369, -369, 182,
+ -369, -369, 52, 219, -369, 138, 139, -15, 140, -369,
+ 141, -369, -369, 61, -369, -369, 130, -369, 144, 145,
+ 146, 180, 11, 147, 85, 148, 99, 89, -2, 149,
+ 130, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -369, 184, -369, 61, -369, 150, -369, -369, 130, 151,
+ 152, -369, 27, -369, -369, -369, -369, -10, 154, -369,
+ 153, -369, -369, -369, -369, -369, -369, 155, 62, 62,
+ 161, 168, 62, -369, -369, -369, -369, 229, 244, 246,
+ -369, -369, -369, -369, 247, -369, -369, -369, -369, 204,
+ 247, 17, 163, 164, -369, 165, -369, 130, 67, -369,
+ -369, -369, 252, 248, 18, 170, -369, 253, -369, 255,
+ 253, -369, 62, -369, -369, 171, -369, -369, 177, 62,
+ 172, -369, -369, -369, -369, -369, -369, 173, 175, 176,
+ -369, 178, -369, 179, -369, 181, -369, 183, -369, 185,
+ -369, -369, -369, -369, -369, -369, -369, 262, 264, -369,
+ 267, -369, -369, -369, -369, -369, -369, -369, 186, -369,
+ -369, -369, -369, 136, 269, -369, 187, -369, 188, 190,
+ 43, -369, -369, 106, -369, 193, -5, -7, 271, -369,
+ 108, 62, -369, -369, 245, 4, 99, -369, 194, -369,
+ 195, -369, 196, -369, -369, -369, -369, -369, -369, -369,
+ 197, -369, -369, -369, 62, -369, 280, 285, -369, 62,
+ -369, -369, -369, 93, 87, 53, -369, -369, -369, -369,
+ -369, -369, -369, -369, 199, -369, -369, -369, -369, -369,
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -369, -369, -369, 278, -369, -369, 8, -369, -369, -369,
+ -369, 57, -369, -369, -369, -369, 203, 205, 206, -369,
+ 250, -7, -369, -369, -369, -369, -369, -369, 62, -369,
+ 62, 229, 244, 208, -369, -369, 198, 211, 202, 213,
+ 214, 218, 269, -369, 62, -369, 229, -369, 244, 54,
+ -369, -369, -369, 269, 215, -369
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -369, -94, -88, 133, -369, -369, -334, -369, -85, -369,
+ -369, -369, -369, -369, -369, -369, -369, 128, -369, -369,
+ -369, -369, -369, -369, -369, 251, -369, -369, -369, 77,
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -72, -369, -81, -369, -369, -369, -369, -369, -369, -369,
+ -369, -369, -369, -369, -305, 101, -369, -369, -369, -369,
+ -369, -369, -369, -369, -369, -369, -369, -369, -22, -369,
+ -369, -336, -369, -369, -369, -369, -369, -369, 254, -369,
+ -369, -369, -369, -369, -369, -369, -342, -368, 256, -369,
+ -369, -369, -80, -110, -82, -369, -369, -369, -369, 279,
+ -369, 257, -369, -369, -369, -161, 156, -146, -369, -369,
+ -369, -369, -369, -369
+};
+
+/* 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 -60
+static const yytype_int16 yytable[] =
+{
+ 139, 133, 137, 192, 145, 231, 149, 106, 107, 152,
+ 216, 148, 254, 150, 151, 396, 147, 350, 147, 108,
+ 385, 147, 108, 239, 244, 85, 86, 183, 280, 380,
+ 56, 139, 280, 87, 281, 184, 5, 153, 281, 221,
+ 198, 280, 248, 381, 421, 154, 109, 281, 185, 282,
+ 109, 186, 301, 7, 353, 88, 89, 110, 187, 10,
+ 432, 110, 210, 382, 57, 354, 222, 240, 155, 419,
+ 90, 302, 188, 49, 284, 383, 417, 111, 284, 51,
+ 111, 407, 156, 112, 431, 283, 429, 284, 66, 140,
+ 430, 291, 52, 351, 53, 189, 190, 434, 113, 69,
+ 70, 141, 113, 69, 70, 158, 113, 292, 293, 225,
+ 54, 226, 203, 66, 160, 264, 161, 159, 76, 204,
+ 263, 213, 162, 227, 269, 226, 397, 147, 214, 163,
+ 164, 165, 74, 166, 252, 167, 232, 227, 398, 233,
+ 234, 253, 310, 235, 168, 81, 1, 2, 294, 82,
+ 344, 236, 61, 62, 63, 64, 65, 345, 433, 73,
+ 401, 169, 170, 390, 408, 386, 75, 402, 78, 237,
+ 139, 409, 69, 70, 11, 12, 13, 316, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 365, 366, 367, 368, 369, 370, 371, 372, 373,
+ 374, 375, 376, 193, 201, 202, 194, 195, 93, 94,
+ 95, 96, 334, 335, 336, 337, 346, 347, 92, 79,
+ 98, 99, 80, 100, 101, 102, 103, 104, 125, 126,
+ 127, 56, 130, 378, 391, 139, 358, 137, 143, -59,
+ 199, 206, 197, 220, 200, 208, 209, 211, 212, 245,
+ 267, 270, 217, 218, 219, 224, 230, 242, 247, 249,
+ 250, 259, 139, 265, 262, 260, 272, 316, 274, 276,
+ 278, 287, 288, 290, 297, 305, 299, 307, 304, 312,
+ 311, 318, 320, 321, 327, 317, 329, 322, 323, 331,
+ 324, 339, 325, 363, 326, 333, 341, 342, 416, 343,
+ 349, 379, 392, 387, 388, 389, 390, 394, 403, 404,
+ 410, 425, 423, 411, 412, 413, 422, 426, 424, 139,
+ 358, 137, 428, 427, 435, 258, 139, 309, 316, 415,
+ 128, 279, 400, 0, 84, 0, 134, 129, 135, 246,
+ 0, 0, 316
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 82, 82, 82, 113, 92, 166, 100, 22, 23, 103,
+ 156, 99, 22, 101, 102, 349, 98, 22, 100, 37,
+ 325, 103, 37, 25, 170, 28, 29, 28, 24, 25,
+ 64, 113, 24, 36, 30, 36, 0, 28, 30, 28,
+ 125, 24, 188, 39, 412, 36, 61, 30, 49, 32,
+ 61, 52, 34, 8, 61, 58, 59, 72, 59, 98,
+ 428, 72, 147, 59, 98, 72, 55, 69, 59, 411,
+ 73, 53, 73, 106, 70, 71, 410, 95, 70, 98,
+ 95, 386, 73, 98, 426, 68, 422, 70, 98, 26,
+ 424, 237, 98, 98, 98, 96, 97, 433, 113, 110,
+ 111, 38, 113, 110, 111, 33, 113, 40, 41, 24,
+ 98, 26, 60, 98, 27, 209, 29, 45, 98, 67,
+ 208, 60, 35, 38, 212, 26, 33, 209, 67, 42,
+ 43, 44, 106, 46, 107, 48, 47, 38, 45, 50,
+ 51, 114, 252, 54, 57, 108, 3, 4, 81, 112,
+ 107, 62, 19, 20, 21, 22, 23, 114, 104, 26,
+ 107, 74, 75, 109, 107, 326, 106, 114, 112, 80,
+ 252, 114, 110, 111, 5, 6, 7, 259, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 99, 22, 23, 102, 103, 99, 100,
+ 101, 102, 76, 77, 78, 79, 110, 111, 107, 112,
+ 107, 107, 112, 107, 107, 107, 107, 102, 107, 107,
+ 98, 64, 22, 321, 344, 317, 317, 317, 108, 108,
+ 98, 22, 108, 63, 109, 107, 107, 107, 107, 65,
+ 82, 22, 108, 108, 108, 108, 108, 108, 108, 108,
+ 108, 107, 344, 102, 109, 112, 22, 349, 22, 22,
+ 66, 108, 108, 108, 22, 22, 28, 22, 108, 102,
+ 109, 108, 107, 107, 22, 113, 22, 109, 109, 22,
+ 109, 22, 109, 22, 109, 109, 109, 109, 408, 109,
+ 107, 56, 22, 109, 109, 109, 109, 22, 109, 31,
+ 107, 109, 114, 108, 108, 65, 108, 104, 107, 401,
+ 401, 401, 104, 109, 109, 197, 408, 250, 410, 401,
+ 79, 230, 354, -1, 55, -1, 82, 80, 82, 183,
+ -1, -1, 424
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 4, 116, 117, 0, 118, 8, 119, 120,
+ 98, 5, 6, 7, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 135,
+ 158, 159, 166, 167, 168, 230, 232, 235, 248, 106,
+ 233, 98, 98, 98, 98, 231, 64, 98, 138, 144,
+ 236, 138, 138, 138, 138, 138, 98, 139, 152, 110,
+ 111, 137, 229, 138, 106, 106, 98, 234, 112, 112,
+ 112, 108, 112, 170, 234, 28, 29, 36, 58, 59,
+ 73, 237, 107, 99, 100, 101, 102, 157, 107, 107,
+ 107, 107, 107, 107, 102, 154, 22, 23, 37, 61,
+ 72, 95, 98, 113, 143, 145, 160, 174, 177, 213,
+ 217, 220, 224, 226, 227, 107, 107, 98, 160, 236,
+ 22, 169, 173, 177, 213, 223, 225, 227, 228, 229,
+ 26, 38, 238, 108, 242, 137, 136, 229, 137, 136,
+ 137, 137, 136, 28, 36, 59, 73, 165, 33, 45,
+ 27, 29, 35, 42, 43, 44, 46, 48, 57, 74,
+ 75, 178, 180, 183, 185, 187, 191, 194, 196, 198,
+ 200, 203, 212, 28, 36, 49, 52, 59, 73, 96,
+ 97, 161, 228, 99, 102, 103, 156, 108, 143, 98,
+ 109, 22, 23, 60, 67, 239, 22, 245, 107, 107,
+ 143, 107, 107, 60, 67, 241, 242, 108, 108, 108,
+ 63, 28, 55, 195, 108, 24, 26, 38, 184, 240,
+ 108, 240, 47, 50, 51, 54, 62, 80, 207, 25,
+ 69, 199, 108, 244, 242, 65, 241, 108, 242, 108,
+ 108, 163, 107, 114, 22, 146, 147, 148, 152, 107,
+ 112, 171, 109, 137, 136, 102, 155, 82, 133, 137,
+ 22, 221, 22, 222, 22, 197, 22, 190, 66, 190,
+ 24, 30, 32, 68, 70, 179, 189, 108, 108, 208,
+ 108, 242, 40, 41, 81, 204, 205, 22, 247, 28,
+ 188, 34, 53, 192, 108, 22, 164, 22, 162, 164,
+ 228, 109, 102, 153, 140, 141, 229, 113, 108, 243,
+ 107, 107, 109, 109, 109, 109, 109, 22, 211, 22,
+ 209, 22, 210, 109, 76, 77, 78, 79, 193, 22,
+ 206, 109, 109, 109, 107, 114, 110, 111, 149, 107,
+ 22, 98, 142, 61, 72, 172, 175, 176, 177, 214,
+ 215, 218, 223, 22, 246, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 134, 137, 56,
+ 25, 39, 59, 71, 181, 189, 240, 109, 109, 109,
+ 109, 228, 22, 150, 22, 151, 141, 33, 45, 201,
+ 203, 107, 114, 109, 31, 182, 186, 189, 107, 114,
+ 107, 108, 108, 65, 202, 175, 228, 141, 216, 221,
+ 219, 222, 108, 114, 107, 109, 104, 109, 104, 206,
+ 141, 221, 222, 104, 206, 109
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (&yylloc, state, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, &yylloc, scanner)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, Location, state); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct asm_parser_state *state)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, state)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ struct asm_parser_state *state;
+#endif
+{
+ if (!yyvaluep)
+ return;
+ YYUSE (yylocationp);
+ YYUSE (state);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct asm_parser_state *state)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, state)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ struct asm_parser_state *state;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+ YYFPRINTF (yyoutput, ": ");
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, state);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct asm_parser_state *state)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule, state)
+ YYSTYPE *yyvsp;
+ YYLTYPE *yylsp;
+ int yyrule;
+ struct asm_parser_state *state;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , &(yylsp[(yyi + 1) - (yynrhs)]) , state);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, yylsp, Rule, state); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, struct asm_parser_state *state)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp, state)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ YYLTYPE *yylocationp;
+ struct asm_parser_state *state;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (yylocationp);
+ YYUSE (state);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (struct asm_parser_state *state);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (struct asm_parser_state *state)
+#else
+int
+yyparse (state)
+ struct asm_parser_state *state;
+#endif
+#endif
+{
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Location data for the lookahead symbol. */
+YYLTYPE yylloc;
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls;
+ YYLTYPE *yylsp;
+
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[2];
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+ YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yyls = yylsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+ yylsp = yyls;
+
+#if YYLTYPE_IS_TRIVIAL
+ /* Initialize the default location before parsing starts. */
+ yylloc.first_line = yylloc.last_line = 1;
+ yylloc.first_column = yylloc.last_column = 1;
+#endif
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+ YYLTYPE *yyls1 = yyls;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yyls1, yysize * sizeof (*yylsp),
+ &yystacksize);
+
+ yyls = yyls1;
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ YYSTACK_RELOCATE (yyls_alloc, yyls);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+ yylsp = yyls + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+ *++yylsp = yylloc;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+ /* Default location. */
+ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 3:
+
+/* Line 1455 of yacc.c */
+#line 260 "program_parse.y"
+ {
+ if (state->prog->Target != GL_VERTEX_PROGRAM_ARB) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid fragment program header");
+
+ }
+ state->mode = ARB_vertex;
+ ;}
+ break;
+
+ case 4:
+
+/* Line 1455 of yacc.c */
+#line 268 "program_parse.y"
+ {
+ if (state->prog->Target != GL_FRAGMENT_PROGRAM_ARB) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid vertex program header");
+ }
+ state->mode = ARB_fragment;
+
+ state->option.TexRect =
+ (state->ctx->Extensions.NV_texture_rectangle != GL_FALSE);
+ ;}
+ break;
+
+ case 7:
+
+/* Line 1455 of yacc.c */
+#line 284 "program_parse.y"
+ {
+ int valid = 0;
+
+ if (state->mode == ARB_vertex) {
+ valid = _mesa_ARBvp_parse_option(state, (yyvsp[(2) - (3)].string));
+ } else if (state->mode == ARB_fragment) {
+ valid = _mesa_ARBfp_parse_option(state, (yyvsp[(2) - (3)].string));
+ }
+
+
+ if (!valid) {
+ const char *const err_str = (state->mode == ARB_vertex)
+ ? "invalid ARB vertex program option"
+ : "invalid ARB fragment program option";
+
+ yyerror(& (yylsp[(2) - (3)]), state, err_str);
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 10:
+
+/* Line 1455 of yacc.c */
+#line 310 "program_parse.y"
+ {
+ if ((yyvsp[(1) - (2)].inst) != NULL) {
+ if (state->inst_tail == NULL) {
+ state->inst_head = (yyvsp[(1) - (2)].inst);
+ } else {
+ state->inst_tail->next = (yyvsp[(1) - (2)].inst);
+ }
+
+ state->inst_tail = (yyvsp[(1) - (2)].inst);
+ (yyvsp[(1) - (2)].inst)->next = NULL;
+
+ state->prog->NumInstructions++;
+ }
+ ;}
+ break;
+
+ case 12:
+
+/* Line 1455 of yacc.c */
+#line 328 "program_parse.y"
+ {
+ (yyval.inst) = (yyvsp[(1) - (1)].inst);
+ state->prog->NumAluInstructions++;
+ ;}
+ break;
+
+ case 13:
+
+/* Line 1455 of yacc.c */
+#line 333 "program_parse.y"
+ {
+ (yyval.inst) = (yyvsp[(1) - (1)].inst);
+ state->prog->NumTexInstructions++;
+ ;}
+ break;
+
+ case 23:
+
+/* Line 1455 of yacc.c */
+#line 353 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor(OPCODE_ARL, & (yyvsp[(2) - (4)].dst_reg), & (yyvsp[(4) - (4)].src_reg), NULL, NULL);
+ ;}
+ break;
+
+ case 24:
+
+/* Line 1455 of yacc.c */
+#line 359 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (4)].temp_inst).Opcode, & (yyvsp[(2) - (4)].dst_reg), & (yyvsp[(4) - (4)].src_reg), NULL, NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (4)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 25:
+
+/* Line 1455 of yacc.c */
+#line 366 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (4)].temp_inst).Opcode, & (yyvsp[(2) - (4)].dst_reg), & (yyvsp[(4) - (4)].src_reg), NULL, NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (4)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 26:
+
+/* Line 1455 of yacc.c */
+#line 373 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (6)].temp_inst).Opcode, & (yyvsp[(2) - (6)].dst_reg), & (yyvsp[(4) - (6)].src_reg), & (yyvsp[(6) - (6)].src_reg), NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (6)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 27:
+
+/* Line 1455 of yacc.c */
+#line 381 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (6)].temp_inst).Opcode, & (yyvsp[(2) - (6)].dst_reg), & (yyvsp[(4) - (6)].src_reg), & (yyvsp[(6) - (6)].src_reg), NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (6)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 28:
+
+/* Line 1455 of yacc.c */
+#line 389 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (8)].temp_inst).Opcode, & (yyvsp[(2) - (8)].dst_reg), & (yyvsp[(4) - (8)].src_reg), & (yyvsp[(6) - (8)].src_reg), & (yyvsp[(8) - (8)].src_reg));
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (8)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 29:
+
+/* Line 1455 of yacc.c */
+#line 396 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (8)].temp_inst).Opcode, & (yyvsp[(2) - (8)].dst_reg), & (yyvsp[(4) - (8)].src_reg), NULL, NULL);
+ if ((yyval.inst) != NULL) {
+ const GLbitfield tex_mask = (1U << (yyvsp[(6) - (8)].integer));
+ GLbitfield shadow_tex = 0;
+ GLbitfield target_mask = 0;
+
+
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (8)].temp_inst).SaturateMode;
+ (yyval.inst)->Base.TexSrcUnit = (yyvsp[(6) - (8)].integer);
+
+ if ((yyvsp[(8) - (8)].integer) < 0) {
+ shadow_tex = tex_mask;
+
+ (yyval.inst)->Base.TexSrcTarget = -(yyvsp[(8) - (8)].integer);
+ (yyval.inst)->Base.TexShadow = 1;
+ } else {
+ (yyval.inst)->Base.TexSrcTarget = (yyvsp[(8) - (8)].integer);
+ }
+
+ target_mask = (1U << (yyval.inst)->Base.TexSrcTarget);
+
+ /* If this texture unit was previously accessed and that access
+ * had a different texture target, generate an error.
+ *
+ * If this texture unit was previously accessed and that access
+ * had a different shadow mode, generate an error.
+ */
+ if ((state->prog->TexturesUsed[(yyvsp[(6) - (8)].integer)] != 0)
+ && ((state->prog->TexturesUsed[(yyvsp[(6) - (8)].integer)] != target_mask)
+ || ((state->prog->ShadowSamplers & tex_mask)
+ != shadow_tex))) {
+ yyerror(& (yylsp[(8) - (8)]), state,
+ "multiple targets used on one texture image unit");
+ YYERROR;
+ }
+
+
+ state->prog->TexturesUsed[(yyvsp[(6) - (8)].integer)] |= target_mask;
+ state->prog->ShadowSamplers |= shadow_tex;
+ }
+ ;}
+ break;
+
+ case 30:
+
+/* Line 1455 of yacc.c */
+#line 441 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor(OPCODE_KIL, NULL, & (yyvsp[(2) - (2)].src_reg), NULL, NULL);
+ state->fragment.UsesKill = 1;
+ ;}
+ break;
+
+ case 31:
+
+/* Line 1455 of yacc.c */
+#line 448 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 32:
+
+/* Line 1455 of yacc.c */
+#line 453 "program_parse.y"
+ { (yyval.integer) = TEXTURE_1D_INDEX; ;}
+ break;
+
+ case 33:
+
+/* Line 1455 of yacc.c */
+#line 454 "program_parse.y"
+ { (yyval.integer) = TEXTURE_2D_INDEX; ;}
+ break;
+
+ case 34:
+
+/* Line 1455 of yacc.c */
+#line 455 "program_parse.y"
+ { (yyval.integer) = TEXTURE_3D_INDEX; ;}
+ break;
+
+ case 35:
+
+/* Line 1455 of yacc.c */
+#line 456 "program_parse.y"
+ { (yyval.integer) = TEXTURE_CUBE_INDEX; ;}
+ break;
+
+ case 36:
+
+/* Line 1455 of yacc.c */
+#line 457 "program_parse.y"
+ { (yyval.integer) = TEXTURE_RECT_INDEX; ;}
+ break;
+
+ case 37:
+
+/* Line 1455 of yacc.c */
+#line 458 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_1D_INDEX; ;}
+ break;
+
+ case 38:
+
+/* Line 1455 of yacc.c */
+#line 459 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_2D_INDEX; ;}
+ break;
+
+ case 39:
+
+/* Line 1455 of yacc.c */
+#line 460 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_RECT_INDEX; ;}
+ break;
+
+ case 40:
+
+/* Line 1455 of yacc.c */
+#line 461 "program_parse.y"
+ { (yyval.integer) = TEXTURE_1D_ARRAY_INDEX; ;}
+ break;
+
+ case 41:
+
+/* Line 1455 of yacc.c */
+#line 462 "program_parse.y"
+ { (yyval.integer) = TEXTURE_2D_ARRAY_INDEX; ;}
+ break;
+
+ case 42:
+
+/* Line 1455 of yacc.c */
+#line 463 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_1D_ARRAY_INDEX; ;}
+ break;
+
+ case 43:
+
+/* Line 1455 of yacc.c */
+#line 464 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_2D_ARRAY_INDEX; ;}
+ break;
+
+ case 44:
+
+/* Line 1455 of yacc.c */
+#line 468 "program_parse.y"
+ {
+ /* FIXME: Is this correct? Should the extenedSwizzle be applied
+ * FIXME: to the existing swizzle?
+ */
+ (yyvsp[(4) - (6)].src_reg).Base.Swizzle = (yyvsp[(6) - (6)].swiz_mask).swizzle;
+ (yyvsp[(4) - (6)].src_reg).Base.Negate = (yyvsp[(6) - (6)].swiz_mask).mask;
+
+ (yyval.inst) = asm_instruction_ctor(OPCODE_SWZ, & (yyvsp[(2) - (6)].dst_reg), & (yyvsp[(4) - (6)].src_reg), NULL, NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (6)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 45:
+
+/* Line 1455 of yacc.c */
+#line 481 "program_parse.y"
+ {
+ (yyval.src_reg) = (yyvsp[(2) - (3)].src_reg);
+
+ if ((yyvsp[(1) - (3)].negate)) {
+ (yyval.src_reg).Base.Negate = ~(yyval.src_reg).Base.Negate;
+ }
+
+ (yyval.src_reg).Base.Swizzle = _mesa_combine_swizzles((yyval.src_reg).Base.Swizzle,
+ (yyvsp[(3) - (3)].swiz_mask).swizzle);
+ ;}
+ break;
+
+ case 46:
+
+/* Line 1455 of yacc.c */
+#line 494 "program_parse.y"
+ {
+ (yyval.src_reg) = (yyvsp[(2) - (3)].src_reg);
+
+ if ((yyvsp[(1) - (3)].negate)) {
+ (yyval.src_reg).Base.Negate = ~(yyval.src_reg).Base.Negate;
+ }
+
+ (yyval.src_reg).Base.Swizzle = _mesa_combine_swizzles((yyval.src_reg).Base.Swizzle,
+ (yyvsp[(3) - (3)].swiz_mask).swizzle);
+ ;}
+ break;
+
+ case 47:
+
+/* Line 1455 of yacc.c */
+#line 507 "program_parse.y"
+ {
+ (yyval.dst_reg) = (yyvsp[(1) - (2)].dst_reg);
+ (yyval.dst_reg).WriteMask = (yyvsp[(2) - (2)].swiz_mask).mask;
+
+ if ((yyval.dst_reg).File == PROGRAM_OUTPUT) {
+ /* Technically speaking, this should check that it is in
+ * vertex program mode. However, PositionInvariant can never be
+ * set in fragment program mode, so it is somewhat irrelevant.
+ */
+ if (state->option.PositionInvariant
+ && ((yyval.dst_reg).Index == VERT_RESULT_HPOS)) {
+ yyerror(& (yylsp[(1) - (2)]), state, "position-invariant programs cannot "
+ "write position");
+ YYERROR;
+ }
+
+ state->prog->OutputsWritten |= (1U << (yyval.dst_reg).Index);
+ }
+ ;}
+ break;
+
+ case 48:
+
+/* Line 1455 of yacc.c */
+#line 529 "program_parse.y"
+ {
+ init_dst_reg(& (yyval.dst_reg));
+ (yyval.dst_reg).File = PROGRAM_ADDRESS;
+ (yyval.dst_reg).Index = 0;
+ (yyval.dst_reg).WriteMask = (yyvsp[(2) - (2)].swiz_mask).mask;
+ ;}
+ break;
+
+ case 49:
+
+/* Line 1455 of yacc.c */
+#line 538 "program_parse.y"
+ {
+ const unsigned xyzw_valid =
+ ((yyvsp[(1) - (7)].ext_swizzle).xyzw_valid << 0)
+ | ((yyvsp[(3) - (7)].ext_swizzle).xyzw_valid << 1)
+ | ((yyvsp[(5) - (7)].ext_swizzle).xyzw_valid << 2)
+ | ((yyvsp[(7) - (7)].ext_swizzle).xyzw_valid << 3);
+ const unsigned rgba_valid =
+ ((yyvsp[(1) - (7)].ext_swizzle).rgba_valid << 0)
+ | ((yyvsp[(3) - (7)].ext_swizzle).rgba_valid << 1)
+ | ((yyvsp[(5) - (7)].ext_swizzle).rgba_valid << 2)
+ | ((yyvsp[(7) - (7)].ext_swizzle).rgba_valid << 3);
+
+ /* All of the swizzle components have to be valid in either RGBA
+ * or XYZW. Note that 0 and 1 are valid in both, so both masks
+ * can have some bits set.
+ *
+ * We somewhat deviate from the spec here. It would be really hard
+ * to figure out which component is the error, and there probably
+ * isn't a lot of benefit.
+ */
+ if ((rgba_valid != 0x0f) && (xyzw_valid != 0x0f)) {
+ yyerror(& (yylsp[(1) - (7)]), state, "cannot combine RGBA and XYZW swizzle "
+ "components");
+ YYERROR;
+ }
+
+ (yyval.swiz_mask).swizzle = MAKE_SWIZZLE4((yyvsp[(1) - (7)].ext_swizzle).swz, (yyvsp[(3) - (7)].ext_swizzle).swz, (yyvsp[(5) - (7)].ext_swizzle).swz, (yyvsp[(7) - (7)].ext_swizzle).swz);
+ (yyval.swiz_mask).mask = ((yyvsp[(1) - (7)].ext_swizzle).negate) | ((yyvsp[(3) - (7)].ext_swizzle).negate << 1) | ((yyvsp[(5) - (7)].ext_swizzle).negate << 2)
+ | ((yyvsp[(7) - (7)].ext_swizzle).negate << 3);
+ ;}
+ break;
+
+ case 50:
+
+/* Line 1455 of yacc.c */
+#line 571 "program_parse.y"
+ {
+ (yyval.ext_swizzle) = (yyvsp[(2) - (2)].ext_swizzle);
+ (yyval.ext_swizzle).negate = ((yyvsp[(1) - (2)].negate)) ? 1 : 0;
+ ;}
+ break;
+
+ case 51:
+
+/* Line 1455 of yacc.c */
+#line 578 "program_parse.y"
+ {
+ if (((yyvsp[(1) - (1)].integer) != 0) && ((yyvsp[(1) - (1)].integer) != 1)) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid extended swizzle selector");
+ YYERROR;
+ }
+
+ (yyval.ext_swizzle).swz = ((yyvsp[(1) - (1)].integer) == 0) ? SWIZZLE_ZERO : SWIZZLE_ONE;
+
+ /* 0 and 1 are valid for both RGBA swizzle names and XYZW
+ * swizzle names.
+ */
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ ;}
+ break;
+
+ case 52:
+
+/* Line 1455 of yacc.c */
+#line 593 "program_parse.y"
+ {
+ if (strlen((yyvsp[(1) - (1)].string)) > 1) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid extended swizzle selector");
+ YYERROR;
+ }
+
+ switch ((yyvsp[(1) - (1)].string)[0]) {
+ case 'x':
+ (yyval.ext_swizzle).swz = SWIZZLE_X;
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ break;
+ case 'y':
+ (yyval.ext_swizzle).swz = SWIZZLE_Y;
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ break;
+ case 'z':
+ (yyval.ext_swizzle).swz = SWIZZLE_Z;
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ break;
+ case 'w':
+ (yyval.ext_swizzle).swz = SWIZZLE_W;
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ break;
+
+ case 'r':
+ (yyval.ext_swizzle).swz = SWIZZLE_X;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ break;
+ case 'g':
+ (yyval.ext_swizzle).swz = SWIZZLE_Y;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ break;
+ case 'b':
+ (yyval.ext_swizzle).swz = SWIZZLE_Z;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ break;
+ case 'a':
+ (yyval.ext_swizzle).swz = SWIZZLE_W;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ break;
+
+ default:
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid extended swizzle selector");
+ YYERROR;
+ break;
+ }
+ ;}
+ break;
+
+ case 53:
+
+/* Line 1455 of yacc.c */
+#line 643 "program_parse.y"
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(1) - (1)].string));
+
+ if (s == NULL) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_param) && (s->type != at_temp)
+ && (s->type != at_attrib)) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type == at_param) && s->param_is_array) {
+ yyerror(& (yylsp[(1) - (1)]), state, "non-array access to array PARAM");
+ YYERROR;
+ }
+
+ init_src_reg(& (yyval.src_reg));
+ switch (s->type) {
+ case at_temp:
+ (yyval.src_reg).Base.File = PROGRAM_TEMPORARY;
+ (yyval.src_reg).Base.Index = s->temp_binding;
+ break;
+ case at_param:
+ (yyval.src_reg).Base.File = s->param_binding_type;
+ (yyval.src_reg).Base.Index = s->param_binding_begin;
+ break;
+ case at_attrib:
+ (yyval.src_reg).Base.File = PROGRAM_INPUT;
+ (yyval.src_reg).Base.Index = s->attrib_binding;
+ state->prog->InputsRead |= (1U << (yyval.src_reg).Base.Index);
+
+ if (!validate_inputs(& (yylsp[(1) - (1)]), state)) {
+ YYERROR;
+ }
+ break;
+
+ default:
+ YYERROR;
+ break;
+ }
+ ;}
+ break;
+
+ case 54:
+
+/* Line 1455 of yacc.c */
+#line 685 "program_parse.y"
+ {
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.File = PROGRAM_INPUT;
+ (yyval.src_reg).Base.Index = (yyvsp[(1) - (1)].attrib);
+ state->prog->InputsRead |= (1U << (yyval.src_reg).Base.Index);
+
+ if (!validate_inputs(& (yylsp[(1) - (1)]), state)) {
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 55:
+
+/* Line 1455 of yacc.c */
+#line 696 "program_parse.y"
+ {
+ if (! (yyvsp[(3) - (4)].src_reg).Base.RelAddr
+ && ((unsigned) (yyvsp[(3) - (4)].src_reg).Base.Index >= (yyvsp[(1) - (4)].sym)->param_binding_length)) {
+ yyerror(& (yylsp[(3) - (4)]), state, "out of bounds array access");
+ YYERROR;
+ }
+
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.File = (yyvsp[(1) - (4)].sym)->param_binding_type;
+
+ if ((yyvsp[(3) - (4)].src_reg).Base.RelAddr) {
+ (yyvsp[(1) - (4)].sym)->param_accessed_indirectly = 1;
+
+ (yyval.src_reg).Base.RelAddr = 1;
+ (yyval.src_reg).Base.Index = (yyvsp[(3) - (4)].src_reg).Base.Index;
+ (yyval.src_reg).Symbol = (yyvsp[(1) - (4)].sym);
+ } else {
+ (yyval.src_reg).Base.Index = (yyvsp[(1) - (4)].sym)->param_binding_begin + (yyvsp[(3) - (4)].src_reg).Base.Index;
+ }
+ ;}
+ break;
+
+ case 56:
+
+/* Line 1455 of yacc.c */
+#line 717 "program_parse.y"
+ {
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.File = ((yyvsp[(1) - (1)].temp_sym).name != NULL)
+ ? (yyvsp[(1) - (1)].temp_sym).param_binding_type
+ : PROGRAM_CONSTANT;
+ (yyval.src_reg).Base.Index = (yyvsp[(1) - (1)].temp_sym).param_binding_begin;
+ ;}
+ break;
+
+ case 57:
+
+/* Line 1455 of yacc.c */
+#line 727 "program_parse.y"
+ {
+ init_dst_reg(& (yyval.dst_reg));
+ (yyval.dst_reg).File = PROGRAM_OUTPUT;
+ (yyval.dst_reg).Index = (yyvsp[(1) - (1)].result);
+ ;}
+ break;
+
+ case 58:
+
+/* Line 1455 of yacc.c */
+#line 733 "program_parse.y"
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(1) - (1)].string));
+
+ if (s == NULL) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_output) && (s->type != at_temp)) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ }
+
+ init_dst_reg(& (yyval.dst_reg));
+ switch (s->type) {
+ case at_temp:
+ (yyval.dst_reg).File = PROGRAM_TEMPORARY;
+ (yyval.dst_reg).Index = s->temp_binding;
+ break;
+ case at_output:
+ (yyval.dst_reg).File = PROGRAM_OUTPUT;
+ (yyval.dst_reg).Index = s->output_binding;
+ break;
+ default:
+ (yyval.dst_reg).File = s->param_binding_type;
+ (yyval.dst_reg).Index = s->param_binding_begin;
+ break;
+ }
+ ;}
+ break;
+
+ case 59:
+
+/* Line 1455 of yacc.c */
+#line 764 "program_parse.y"
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(1) - (1)].string));
+
+ if (s == NULL) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_param) || !s->param_is_array) {
+ yyerror(& (yylsp[(1) - (1)]), state, "array access to non-PARAM variable");
+ YYERROR;
+ } else {
+ (yyval.sym) = s;
+ }
+ ;}
+ break;
+
+ case 62:
+
+/* Line 1455 of yacc.c */
+#line 783 "program_parse.y"
+ {
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.Index = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 63:
+
+/* Line 1455 of yacc.c */
+#line 790 "program_parse.y"
+ {
+ /* FINISHME: Add support for multiple address registers.
+ */
+ /* FINISHME: Add support for 4-component address registers.
+ */
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.RelAddr = 1;
+ (yyval.src_reg).Base.Index = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 64:
+
+/* Line 1455 of yacc.c */
+#line 801 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 65:
+
+/* Line 1455 of yacc.c */
+#line 802 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 66:
+
+/* Line 1455 of yacc.c */
+#line 803 "program_parse.y"
+ { (yyval.integer) = -(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 67:
+
+/* Line 1455 of yacc.c */
+#line 807 "program_parse.y"
+ {
+ if (((yyvsp[(1) - (1)].integer) < 0) || ((yyvsp[(1) - (1)].integer) > 63)) {
+ yyerror(& (yylsp[(1) - (1)]), state,
+ "relative address offset too large (positive)");
+ YYERROR;
+ } else {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ }
+ ;}
+ break;
+
+ case 68:
+
+/* Line 1455 of yacc.c */
+#line 819 "program_parse.y"
+ {
+ if (((yyvsp[(1) - (1)].integer) < 0) || ((yyvsp[(1) - (1)].integer) > 64)) {
+ yyerror(& (yylsp[(1) - (1)]), state,
+ "relative address offset too large (negative)");
+ YYERROR;
+ } else {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ }
+ ;}
+ break;
+
+ case 69:
+
+/* Line 1455 of yacc.c */
+#line 831 "program_parse.y"
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(1) - (1)].string));
+
+ if (s == NULL) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid array member");
+ YYERROR;
+ } else if (s->type != at_address) {
+ yyerror(& (yylsp[(1) - (1)]), state,
+ "invalid variable for indexed array access");
+ YYERROR;
+ } else {
+ (yyval.sym) = s;
+ }
+ ;}
+ break;
+
+ case 70:
+
+/* Line 1455 of yacc.c */
+#line 849 "program_parse.y"
+ {
+ if ((yyvsp[(1) - (1)].swiz_mask).mask != WRITEMASK_X) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid address component selector");
+ YYERROR;
+ } else {
+ (yyval.swiz_mask) = (yyvsp[(1) - (1)].swiz_mask);
+ }
+ ;}
+ break;
+
+ case 71:
+
+/* Line 1455 of yacc.c */
+#line 860 "program_parse.y"
+ {
+ if ((yyvsp[(1) - (1)].swiz_mask).mask != WRITEMASK_X) {
+ yyerror(& (yylsp[(1) - (1)]), state,
+ "address register write mask must be \".x\"");
+ YYERROR;
+ } else {
+ (yyval.swiz_mask) = (yyvsp[(1) - (1)].swiz_mask);
+ }
+ ;}
+ break;
+
+ case 76:
+
+/* Line 1455 of yacc.c */
+#line 876 "program_parse.y"
+ { (yyval.swiz_mask).swizzle = SWIZZLE_NOOP; (yyval.swiz_mask).mask = WRITEMASK_XYZW; ;}
+ break;
+
+ case 81:
+
+/* Line 1455 of yacc.c */
+#line 880 "program_parse.y"
+ { (yyval.swiz_mask).swizzle = SWIZZLE_NOOP; (yyval.swiz_mask).mask = WRITEMASK_XYZW; ;}
+ break;
+
+ case 88:
+
+/* Line 1455 of yacc.c */
+#line 892 "program_parse.y"
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, (yyvsp[(2) - (4)].string), at_attrib, & (yylsp[(2) - (4)]));
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->attrib_binding = (yyvsp[(4) - (4)].attrib);
+ state->InputsBound |= (1U << s->attrib_binding);
+
+ if (!validate_inputs(& (yylsp[(4) - (4)]), state)) {
+ YYERROR;
+ }
+ }
+ ;}
+ break;
+
+ case 89:
+
+/* Line 1455 of yacc.c */
+#line 910 "program_parse.y"
+ {
+ (yyval.attrib) = (yyvsp[(2) - (2)].attrib);
+ ;}
+ break;
+
+ case 90:
+
+/* Line 1455 of yacc.c */
+#line 914 "program_parse.y"
+ {
+ (yyval.attrib) = (yyvsp[(2) - (2)].attrib);
+ ;}
+ break;
+
+ case 91:
+
+/* Line 1455 of yacc.c */
+#line 920 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_POS;
+ ;}
+ break;
+
+ case 92:
+
+/* Line 1455 of yacc.c */
+#line 924 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_WEIGHT;
+ ;}
+ break;
+
+ case 93:
+
+/* Line 1455 of yacc.c */
+#line 928 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_NORMAL;
+ ;}
+ break;
+
+ case 94:
+
+/* Line 1455 of yacc.c */
+#line 932 "program_parse.y"
+ {
+ if (!state->ctx->Extensions.EXT_secondary_color) {
+ yyerror(& (yylsp[(2) - (2)]), state, "GL_EXT_secondary_color not supported");
+ YYERROR;
+ }
+
+ (yyval.attrib) = VERT_ATTRIB_COLOR0 + (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 95:
+
+/* Line 1455 of yacc.c */
+#line 941 "program_parse.y"
+ {
+ if (!state->ctx->Extensions.EXT_fog_coord) {
+ yyerror(& (yylsp[(1) - (1)]), state, "GL_EXT_fog_coord not supported");
+ YYERROR;
+ }
+
+ (yyval.attrib) = VERT_ATTRIB_FOG;
+ ;}
+ break;
+
+ case 96:
+
+/* Line 1455 of yacc.c */
+#line 950 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_TEX0 + (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 97:
+
+/* Line 1455 of yacc.c */
+#line 954 "program_parse.y"
+ {
+ yyerror(& (yylsp[(1) - (4)]), state, "GL_ARB_matrix_palette not supported");
+ YYERROR;
+ ;}
+ break;
+
+ case 98:
+
+/* Line 1455 of yacc.c */
+#line 959 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_GENERIC0 + (yyvsp[(3) - (4)].integer);
+ ;}
+ break;
+
+ case 99:
+
+/* Line 1455 of yacc.c */
+#line 965 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->limits->MaxAttribs) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid vertex attribute reference");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 103:
+
+/* Line 1455 of yacc.c */
+#line 979 "program_parse.y"
+ {
+ (yyval.attrib) = FRAG_ATTRIB_WPOS;
+ ;}
+ break;
+
+ case 104:
+
+/* Line 1455 of yacc.c */
+#line 983 "program_parse.y"
+ {
+ (yyval.attrib) = FRAG_ATTRIB_COL0 + (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 105:
+
+/* Line 1455 of yacc.c */
+#line 987 "program_parse.y"
+ {
+ (yyval.attrib) = FRAG_ATTRIB_FOGC;
+ ;}
+ break;
+
+ case 106:
+
+/* Line 1455 of yacc.c */
+#line 991 "program_parse.y"
+ {
+ (yyval.attrib) = FRAG_ATTRIB_TEX0 + (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 109:
+
+/* Line 1455 of yacc.c */
+#line 999 "program_parse.y"
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, (yyvsp[(2) - (3)].string), at_param, & (yylsp[(2) - (3)]));
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->param_binding_type = (yyvsp[(3) - (3)].temp_sym).param_binding_type;
+ s->param_binding_begin = (yyvsp[(3) - (3)].temp_sym).param_binding_begin;
+ s->param_binding_length = (yyvsp[(3) - (3)].temp_sym).param_binding_length;
+ s->param_is_array = 0;
+ }
+ ;}
+ break;
+
+ case 110:
+
+/* Line 1455 of yacc.c */
+#line 1015 "program_parse.y"
+ {
+ if (((yyvsp[(4) - (6)].integer) != 0) && ((unsigned) (yyvsp[(4) - (6)].integer) != (yyvsp[(6) - (6)].temp_sym).param_binding_length)) {
+ yyerror(& (yylsp[(4) - (6)]), state,
+ "parameter array size and number of bindings must match");
+ YYERROR;
+ } else {
+ struct asm_symbol *const s =
+ declare_variable(state, (yyvsp[(2) - (6)].string), (yyvsp[(6) - (6)].temp_sym).type, & (yylsp[(2) - (6)]));
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->param_binding_type = (yyvsp[(6) - (6)].temp_sym).param_binding_type;
+ s->param_binding_begin = (yyvsp[(6) - (6)].temp_sym).param_binding_begin;
+ s->param_binding_length = (yyvsp[(6) - (6)].temp_sym).param_binding_length;
+ s->param_is_array = 1;
+ }
+ }
+ ;}
+ break;
+
+ case 111:
+
+/* Line 1455 of yacc.c */
+#line 1037 "program_parse.y"
+ {
+ (yyval.integer) = 0;
+ ;}
+ break;
+
+ case 112:
+
+/* Line 1455 of yacc.c */
+#line 1041 "program_parse.y"
+ {
+ if (((yyvsp[(1) - (1)].integer) < 1) || ((unsigned) (yyvsp[(1) - (1)].integer) >= state->limits->MaxParameters)) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid parameter array size");
+ YYERROR;
+ } else {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ }
+ ;}
+ break;
+
+ case 113:
+
+/* Line 1455 of yacc.c */
+#line 1052 "program_parse.y"
+ {
+ (yyval.temp_sym) = (yyvsp[(2) - (2)].temp_sym);
+ ;}
+ break;
+
+ case 114:
+
+/* Line 1455 of yacc.c */
+#line 1058 "program_parse.y"
+ {
+ (yyval.temp_sym) = (yyvsp[(3) - (4)].temp_sym);
+ ;}
+ break;
+
+ case 116:
+
+/* Line 1455 of yacc.c */
+#line 1065 "program_parse.y"
+ {
+ (yyvsp[(1) - (3)].temp_sym).param_binding_length += (yyvsp[(3) - (3)].temp_sym).param_binding_length;
+ (yyval.temp_sym) = (yyvsp[(1) - (3)].temp_sym);
+ ;}
+ break;
+
+ case 117:
+
+/* Line 1455 of yacc.c */
+#line 1072 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 118:
+
+/* Line 1455 of yacc.c */
+#line 1078 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 119:
+
+/* Line 1455 of yacc.c */
+#line 1084 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & (yyval.temp_sym), & (yyvsp[(1) - (1)].vector));
+ ;}
+ break;
+
+ case 120:
+
+/* Line 1455 of yacc.c */
+#line 1092 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 121:
+
+/* Line 1455 of yacc.c */
+#line 1098 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 122:
+
+/* Line 1455 of yacc.c */
+#line 1104 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & (yyval.temp_sym), & (yyvsp[(1) - (1)].vector));
+ ;}
+ break;
+
+ case 123:
+
+/* Line 1455 of yacc.c */
+#line 1112 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 124:
+
+/* Line 1455 of yacc.c */
+#line 1118 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 125:
+
+/* Line 1455 of yacc.c */
+#line 1124 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & (yyval.temp_sym), & (yyvsp[(1) - (1)].vector));
+ ;}
+ break;
+
+ case 126:
+
+/* Line 1455 of yacc.c */
+#line 1131 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(1) - (1)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 127:
+
+/* Line 1455 of yacc.c */
+#line 1132 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 128:
+
+/* Line 1455 of yacc.c */
+#line 1135 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 129:
+
+/* Line 1455 of yacc.c */
+#line 1136 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 130:
+
+/* Line 1455 of yacc.c */
+#line 1137 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 131:
+
+/* Line 1455 of yacc.c */
+#line 1138 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 132:
+
+/* Line 1455 of yacc.c */
+#line 1139 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 133:
+
+/* Line 1455 of yacc.c */
+#line 1140 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 134:
+
+/* Line 1455 of yacc.c */
+#line 1141 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 135:
+
+/* Line 1455 of yacc.c */
+#line 1142 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 136:
+
+/* Line 1455 of yacc.c */
+#line 1143 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 137:
+
+/* Line 1455 of yacc.c */
+#line 1144 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 138:
+
+/* Line 1455 of yacc.c */
+#line 1145 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 139:
+
+/* Line 1455 of yacc.c */
+#line 1149 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_MATERIAL;
+ (yyval.state)[1] = (yyvsp[(2) - (3)].integer);
+ (yyval.state)[2] = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 140:
+
+/* Line 1455 of yacc.c */
+#line 1158 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 141:
+
+/* Line 1455 of yacc.c */
+#line 1162 "program_parse.y"
+ {
+ (yyval.integer) = STATE_EMISSION;
+ ;}
+ break;
+
+ case 142:
+
+/* Line 1455 of yacc.c */
+#line 1166 "program_parse.y"
+ {
+ (yyval.integer) = STATE_SHININESS;
+ ;}
+ break;
+
+ case 143:
+
+/* Line 1455 of yacc.c */
+#line 1172 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_LIGHT;
+ (yyval.state)[1] = (yyvsp[(3) - (5)].integer);
+ (yyval.state)[2] = (yyvsp[(5) - (5)].integer);
+ ;}
+ break;
+
+ case 144:
+
+/* Line 1455 of yacc.c */
+#line 1181 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 145:
+
+/* Line 1455 of yacc.c */
+#line 1185 "program_parse.y"
+ {
+ (yyval.integer) = STATE_POSITION;
+ ;}
+ break;
+
+ case 146:
+
+/* Line 1455 of yacc.c */
+#line 1189 "program_parse.y"
+ {
+ if (!state->ctx->Extensions.EXT_point_parameters) {
+ yyerror(& (yylsp[(1) - (1)]), state, "GL_ARB_point_parameters not supported");
+ YYERROR;
+ }
+
+ (yyval.integer) = STATE_ATTENUATION;
+ ;}
+ break;
+
+ case 147:
+
+/* Line 1455 of yacc.c */
+#line 1198 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 148:
+
+/* Line 1455 of yacc.c */
+#line 1202 "program_parse.y"
+ {
+ (yyval.integer) = STATE_HALF_VECTOR;
+ ;}
+ break;
+
+ case 149:
+
+/* Line 1455 of yacc.c */
+#line 1208 "program_parse.y"
+ {
+ (yyval.integer) = STATE_SPOT_DIRECTION;
+ ;}
+ break;
+
+ case 150:
+
+/* Line 1455 of yacc.c */
+#line 1214 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(2) - (2)].state)[0];
+ (yyval.state)[1] = (yyvsp[(2) - (2)].state)[1];
+ ;}
+ break;
+
+ case 151:
+
+/* Line 1455 of yacc.c */
+#line 1221 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_LIGHTMODEL_AMBIENT;
+ ;}
+ break;
+
+ case 152:
+
+/* Line 1455 of yacc.c */
+#line 1226 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_LIGHTMODEL_SCENECOLOR;
+ (yyval.state)[1] = (yyvsp[(1) - (2)].integer);
+ ;}
+ break;
+
+ case 153:
+
+/* Line 1455 of yacc.c */
+#line 1234 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_LIGHTPROD;
+ (yyval.state)[1] = (yyvsp[(3) - (6)].integer);
+ (yyval.state)[2] = (yyvsp[(5) - (6)].integer);
+ (yyval.state)[3] = (yyvsp[(6) - (6)].integer);
+ ;}
+ break;
+
+ case 155:
+
+/* Line 1455 of yacc.c */
+#line 1246 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = (yyvsp[(3) - (3)].integer);
+ (yyval.state)[1] = (yyvsp[(2) - (3)].integer);
+ ;}
+ break;
+
+ case 156:
+
+/* Line 1455 of yacc.c */
+#line 1254 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXENV_COLOR;
+ ;}
+ break;
+
+ case 157:
+
+/* Line 1455 of yacc.c */
+#line 1260 "program_parse.y"
+ {
+ (yyval.integer) = STATE_AMBIENT;
+ ;}
+ break;
+
+ case 158:
+
+/* Line 1455 of yacc.c */
+#line 1264 "program_parse.y"
+ {
+ (yyval.integer) = STATE_DIFFUSE;
+ ;}
+ break;
+
+ case 159:
+
+/* Line 1455 of yacc.c */
+#line 1268 "program_parse.y"
+ {
+ (yyval.integer) = STATE_SPECULAR;
+ ;}
+ break;
+
+ case 160:
+
+/* Line 1455 of yacc.c */
+#line 1274 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxLights) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid light selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 161:
+
+/* Line 1455 of yacc.c */
+#line 1285 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_TEXGEN;
+ (yyval.state)[1] = (yyvsp[(2) - (4)].integer);
+ (yyval.state)[2] = (yyvsp[(3) - (4)].integer) + (yyvsp[(4) - (4)].integer);
+ ;}
+ break;
+
+ case 162:
+
+/* Line 1455 of yacc.c */
+#line 1294 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 163:
+
+/* Line 1455 of yacc.c */
+#line 1298 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_OBJECT_S;
+ ;}
+ break;
+
+ case 164:
+
+/* Line 1455 of yacc.c */
+#line 1303 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_S - STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 165:
+
+/* Line 1455 of yacc.c */
+#line 1307 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_T - STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 166:
+
+/* Line 1455 of yacc.c */
+#line 1311 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_R - STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 167:
+
+/* Line 1455 of yacc.c */
+#line 1315 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_Q - STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 168:
+
+/* Line 1455 of yacc.c */
+#line 1321 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 169:
+
+/* Line 1455 of yacc.c */
+#line 1328 "program_parse.y"
+ {
+ (yyval.integer) = STATE_FOG_COLOR;
+ ;}
+ break;
+
+ case 170:
+
+/* Line 1455 of yacc.c */
+#line 1332 "program_parse.y"
+ {
+ (yyval.integer) = STATE_FOG_PARAMS;
+ ;}
+ break;
+
+ case 171:
+
+/* Line 1455 of yacc.c */
+#line 1338 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_CLIPPLANE;
+ (yyval.state)[1] = (yyvsp[(3) - (5)].integer);
+ ;}
+ break;
+
+ case 172:
+
+/* Line 1455 of yacc.c */
+#line 1346 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxClipPlanes) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid clip plane selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 173:
+
+/* Line 1455 of yacc.c */
+#line 1357 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 174:
+
+/* Line 1455 of yacc.c */
+#line 1364 "program_parse.y"
+ {
+ (yyval.integer) = STATE_POINT_SIZE;
+ ;}
+ break;
+
+ case 175:
+
+/* Line 1455 of yacc.c */
+#line 1368 "program_parse.y"
+ {
+ (yyval.integer) = STATE_POINT_ATTENUATION;
+ ;}
+ break;
+
+ case 176:
+
+/* Line 1455 of yacc.c */
+#line 1374 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (5)].state)[0];
+ (yyval.state)[1] = (yyvsp[(1) - (5)].state)[1];
+ (yyval.state)[2] = (yyvsp[(4) - (5)].integer);
+ (yyval.state)[3] = (yyvsp[(4) - (5)].integer);
+ (yyval.state)[4] = (yyvsp[(1) - (5)].state)[2];
+ ;}
+ break;
+
+ case 177:
+
+/* Line 1455 of yacc.c */
+#line 1384 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (2)].state)[0];
+ (yyval.state)[1] = (yyvsp[(1) - (2)].state)[1];
+ (yyval.state)[2] = (yyvsp[(2) - (2)].state)[2];
+ (yyval.state)[3] = (yyvsp[(2) - (2)].state)[3];
+ (yyval.state)[4] = (yyvsp[(1) - (2)].state)[2];
+ ;}
+ break;
+
+ case 178:
+
+/* Line 1455 of yacc.c */
+#line 1394 "program_parse.y"
+ {
+ (yyval.state)[2] = 0;
+ (yyval.state)[3] = 3;
+ ;}
+ break;
+
+ case 179:
+
+/* Line 1455 of yacc.c */
+#line 1399 "program_parse.y"
+ {
+ /* It seems logical that the matrix row range specifier would have
+ * to specify a range or more than one row (i.e., $5 > $3).
+ * However, the ARB_vertex_program spec says "a program will fail
+ * to load if <a> is greater than <b>." This means that $3 == $5
+ * is valid.
+ */
+ if ((yyvsp[(3) - (6)].integer) > (yyvsp[(5) - (6)].integer)) {
+ yyerror(& (yylsp[(3) - (6)]), state, "invalid matrix row range");
+ YYERROR;
+ }
+
+ (yyval.state)[2] = (yyvsp[(3) - (6)].integer);
+ (yyval.state)[3] = (yyvsp[(5) - (6)].integer);
+ ;}
+ break;
+
+ case 180:
+
+/* Line 1455 of yacc.c */
+#line 1417 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(2) - (3)].state)[0];
+ (yyval.state)[1] = (yyvsp[(2) - (3)].state)[1];
+ (yyval.state)[2] = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 181:
+
+/* Line 1455 of yacc.c */
+#line 1425 "program_parse.y"
+ {
+ (yyval.integer) = 0;
+ ;}
+ break;
+
+ case 182:
+
+/* Line 1455 of yacc.c */
+#line 1429 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 183:
+
+/* Line 1455 of yacc.c */
+#line 1435 "program_parse.y"
+ {
+ (yyval.integer) = STATE_MATRIX_INVERSE;
+ ;}
+ break;
+
+ case 184:
+
+/* Line 1455 of yacc.c */
+#line 1439 "program_parse.y"
+ {
+ (yyval.integer) = STATE_MATRIX_TRANSPOSE;
+ ;}
+ break;
+
+ case 185:
+
+/* Line 1455 of yacc.c */
+#line 1443 "program_parse.y"
+ {
+ (yyval.integer) = STATE_MATRIX_INVTRANS;
+ ;}
+ break;
+
+ case 186:
+
+/* Line 1455 of yacc.c */
+#line 1449 "program_parse.y"
+ {
+ if ((yyvsp[(1) - (1)].integer) > 3) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid matrix row reference");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 187:
+
+/* Line 1455 of yacc.c */
+#line 1460 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_MODELVIEW_MATRIX;
+ (yyval.state)[1] = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 188:
+
+/* Line 1455 of yacc.c */
+#line 1465 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_PROJECTION_MATRIX;
+ (yyval.state)[1] = 0;
+ ;}
+ break;
+
+ case 189:
+
+/* Line 1455 of yacc.c */
+#line 1470 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_MVP_MATRIX;
+ (yyval.state)[1] = 0;
+ ;}
+ break;
+
+ case 190:
+
+/* Line 1455 of yacc.c */
+#line 1475 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_TEXTURE_MATRIX;
+ (yyval.state)[1] = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 191:
+
+/* Line 1455 of yacc.c */
+#line 1480 "program_parse.y"
+ {
+ yyerror(& (yylsp[(1) - (4)]), state, "GL_ARB_matrix_palette not supported");
+ YYERROR;
+ ;}
+ break;
+
+ case 192:
+
+/* Line 1455 of yacc.c */
+#line 1485 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_PROGRAM_MATRIX;
+ (yyval.state)[1] = (yyvsp[(3) - (4)].integer);
+ ;}
+ break;
+
+ case 193:
+
+/* Line 1455 of yacc.c */
+#line 1492 "program_parse.y"
+ {
+ (yyval.integer) = 0;
+ ;}
+ break;
+
+ case 194:
+
+/* Line 1455 of yacc.c */
+#line 1496 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(2) - (3)].integer);
+ ;}
+ break;
+
+ case 195:
+
+/* Line 1455 of yacc.c */
+#line 1501 "program_parse.y"
+ {
+ /* Since GL_ARB_vertex_blend isn't supported, only modelview matrix
+ * zero is valid.
+ */
+ if ((yyvsp[(1) - (1)].integer) != 0) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid modelview matrix index");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 196:
+
+/* Line 1455 of yacc.c */
+#line 1514 "program_parse.y"
+ {
+ /* Since GL_ARB_matrix_palette isn't supported, just let any value
+ * through here. The error will be generated later.
+ */
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 197:
+
+/* Line 1455 of yacc.c */
+#line 1522 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxProgramMatrices) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program matrix selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 198:
+
+/* Line 1455 of yacc.c */
+#line 1533 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_DEPTH_RANGE;
+ ;}
+ break;
+
+ case 203:
+
+/* Line 1455 of yacc.c */
+#line 1545 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = state->state_param_enum;
+ (yyval.state)[1] = STATE_ENV;
+ (yyval.state)[2] = (yyvsp[(4) - (5)].state)[0];
+ (yyval.state)[3] = (yyvsp[(4) - (5)].state)[1];
+ ;}
+ break;
+
+ case 204:
+
+/* Line 1455 of yacc.c */
+#line 1555 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (1)].integer);
+ (yyval.state)[1] = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 205:
+
+/* Line 1455 of yacc.c */
+#line 1560 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (3)].integer);
+ (yyval.state)[1] = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 206:
+
+/* Line 1455 of yacc.c */
+#line 1567 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = state->state_param_enum;
+ (yyval.state)[1] = STATE_ENV;
+ (yyval.state)[2] = (yyvsp[(4) - (5)].integer);
+ (yyval.state)[3] = (yyvsp[(4) - (5)].integer);
+ ;}
+ break;
+
+ case 207:
+
+/* Line 1455 of yacc.c */
+#line 1577 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = state->state_param_enum;
+ (yyval.state)[1] = STATE_LOCAL;
+ (yyval.state)[2] = (yyvsp[(4) - (5)].state)[0];
+ (yyval.state)[3] = (yyvsp[(4) - (5)].state)[1];
+ ;}
+ break;
+
+ case 208:
+
+/* Line 1455 of yacc.c */
+#line 1586 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (1)].integer);
+ (yyval.state)[1] = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 209:
+
+/* Line 1455 of yacc.c */
+#line 1591 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (3)].integer);
+ (yyval.state)[1] = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 210:
+
+/* Line 1455 of yacc.c */
+#line 1598 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = state->state_param_enum;
+ (yyval.state)[1] = STATE_LOCAL;
+ (yyval.state)[2] = (yyvsp[(4) - (5)].integer);
+ (yyval.state)[3] = (yyvsp[(4) - (5)].integer);
+ ;}
+ break;
+
+ case 211:
+
+/* Line 1455 of yacc.c */
+#line 1608 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->limits->MaxEnvParams) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid environment parameter reference");
+ YYERROR;
+ }
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 212:
+
+/* Line 1455 of yacc.c */
+#line 1618 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->limits->MaxLocalParams) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid local parameter reference");
+ YYERROR;
+ }
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 217:
+
+/* Line 1455 of yacc.c */
+#line 1633 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[1] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[2] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[3] = (yyvsp[(1) - (1)].real);
+ ;}
+ break;
+
+ case 218:
+
+/* Line 1455 of yacc.c */
+#line 1643 "program_parse.y"
+ {
+ (yyval.vector).count = 1;
+ (yyval.vector).data[0] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[1] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[2] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[3] = (yyvsp[(1) - (1)].real);
+ ;}
+ break;
+
+ case 219:
+
+/* Line 1455 of yacc.c */
+#line 1651 "program_parse.y"
+ {
+ (yyval.vector).count = 1;
+ (yyval.vector).data[0] = (float) (yyvsp[(1) - (1)].integer);
+ (yyval.vector).data[1] = (float) (yyvsp[(1) - (1)].integer);
+ (yyval.vector).data[2] = (float) (yyvsp[(1) - (1)].integer);
+ (yyval.vector).data[3] = (float) (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 220:
+
+/* Line 1455 of yacc.c */
+#line 1661 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(2) - (3)].real);
+ (yyval.vector).data[1] = 0.0f;
+ (yyval.vector).data[2] = 0.0f;
+ (yyval.vector).data[3] = 1.0f;
+ ;}
+ break;
+
+ case 221:
+
+/* Line 1455 of yacc.c */
+#line 1669 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(2) - (5)].real);
+ (yyval.vector).data[1] = (yyvsp[(4) - (5)].real);
+ (yyval.vector).data[2] = 0.0f;
+ (yyval.vector).data[3] = 1.0f;
+ ;}
+ break;
+
+ case 222:
+
+/* Line 1455 of yacc.c */
+#line 1678 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(2) - (7)].real);
+ (yyval.vector).data[1] = (yyvsp[(4) - (7)].real);
+ (yyval.vector).data[2] = (yyvsp[(6) - (7)].real);
+ (yyval.vector).data[3] = 1.0f;
+ ;}
+ break;
+
+ case 223:
+
+/* Line 1455 of yacc.c */
+#line 1687 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(2) - (9)].real);
+ (yyval.vector).data[1] = (yyvsp[(4) - (9)].real);
+ (yyval.vector).data[2] = (yyvsp[(6) - (9)].real);
+ (yyval.vector).data[3] = (yyvsp[(8) - (9)].real);
+ ;}
+ break;
+
+ case 224:
+
+/* Line 1455 of yacc.c */
+#line 1697 "program_parse.y"
+ {
+ (yyval.real) = ((yyvsp[(1) - (2)].negate)) ? -(yyvsp[(2) - (2)].real) : (yyvsp[(2) - (2)].real);
+ ;}
+ break;
+
+ case 225:
+
+/* Line 1455 of yacc.c */
+#line 1701 "program_parse.y"
+ {
+ (yyval.real) = (float)(((yyvsp[(1) - (2)].negate)) ? -(yyvsp[(2) - (2)].integer) : (yyvsp[(2) - (2)].integer));
+ ;}
+ break;
+
+ case 226:
+
+/* Line 1455 of yacc.c */
+#line 1706 "program_parse.y"
+ { (yyval.negate) = FALSE; ;}
+ break;
+
+ case 227:
+
+/* Line 1455 of yacc.c */
+#line 1707 "program_parse.y"
+ { (yyval.negate) = TRUE; ;}
+ break;
+
+ case 228:
+
+/* Line 1455 of yacc.c */
+#line 1708 "program_parse.y"
+ { (yyval.negate) = FALSE; ;}
+ break;
+
+ case 229:
+
+/* Line 1455 of yacc.c */
+#line 1711 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(1) - (1)].integer); ;}
+ break;
+
+ case 231:
+
+/* Line 1455 of yacc.c */
+#line 1714 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(1) - (1)].integer); ;}
+ break;
+
+ case 233:
+
+/* Line 1455 of yacc.c */
+#line 1718 "program_parse.y"
+ {
+ if (!declare_variable(state, (yyvsp[(3) - (3)].string), (yyvsp[(0) - (3)].integer), & (yylsp[(3) - (3)]))) {
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 234:
+
+/* Line 1455 of yacc.c */
+#line 1724 "program_parse.y"
+ {
+ if (!declare_variable(state, (yyvsp[(1) - (1)].string), (yyvsp[(0) - (1)].integer), & (yylsp[(1) - (1)]))) {
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 235:
+
+/* Line 1455 of yacc.c */
+#line 1732 "program_parse.y"
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, (yyvsp[(2) - (4)].string), at_output, & (yylsp[(2) - (4)]));
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->output_binding = (yyvsp[(4) - (4)].result);
+ }
+ ;}
+ break;
+
+ case 236:
+
+/* Line 1455 of yacc.c */
+#line 1745 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.result) = VERT_RESULT_HPOS;
+ } else {
+ yyerror(& (yylsp[(2) - (2)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 237:
+
+/* Line 1455 of yacc.c */
+#line 1754 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.result) = VERT_RESULT_FOGC;
+ } else {
+ yyerror(& (yylsp[(2) - (2)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 238:
+
+/* Line 1455 of yacc.c */
+#line 1763 "program_parse.y"
+ {
+ (yyval.result) = (yyvsp[(2) - (2)].result);
+ ;}
+ break;
+
+ case 239:
+
+/* Line 1455 of yacc.c */
+#line 1767 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.result) = VERT_RESULT_PSIZ;
+ } else {
+ yyerror(& (yylsp[(2) - (2)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 240:
+
+/* Line 1455 of yacc.c */
+#line 1776 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.result) = VERT_RESULT_TEX0 + (yyvsp[(3) - (3)].integer);
+ } else {
+ yyerror(& (yylsp[(2) - (3)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 241:
+
+/* Line 1455 of yacc.c */
+#line 1785 "program_parse.y"
+ {
+ if (state->mode == ARB_fragment) {
+ (yyval.result) = FRAG_RESULT_DEPTH;
+ } else {
+ yyerror(& (yylsp[(2) - (2)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 242:
+
+/* Line 1455 of yacc.c */
+#line 1796 "program_parse.y"
+ {
+ (yyval.result) = (yyvsp[(2) - (3)].integer) + (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 243:
+
+/* Line 1455 of yacc.c */
+#line 1802 "program_parse.y"
+ {
+ (yyval.integer) = (state->mode == ARB_vertex)
+ ? VERT_RESULT_COL0
+ : FRAG_RESULT_COLOR;
+ ;}
+ break;
+
+ case 244:
+
+/* Line 1455 of yacc.c */
+#line 1808 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.integer) = VERT_RESULT_COL0;
+ } else {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 245:
+
+/* Line 1455 of yacc.c */
+#line 1817 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.integer) = VERT_RESULT_BFC0;
+ } else {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 246:
+
+/* Line 1455 of yacc.c */
+#line 1828 "program_parse.y"
+ {
+ (yyval.integer) = 0;
+ ;}
+ break;
+
+ case 247:
+
+/* Line 1455 of yacc.c */
+#line 1832 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.integer) = 0;
+ } else {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 248:
+
+/* Line 1455 of yacc.c */
+#line 1841 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.integer) = 1;
+ } else {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 249:
+
+/* Line 1455 of yacc.c */
+#line 1851 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 250:
+
+/* Line 1455 of yacc.c */
+#line 1852 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 251:
+
+/* Line 1455 of yacc.c */
+#line 1853 "program_parse.y"
+ { (yyval.integer) = 1; ;}
+ break;
+
+ case 252:
+
+/* Line 1455 of yacc.c */
+#line 1856 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 253:
+
+/* Line 1455 of yacc.c */
+#line 1857 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 254:
+
+/* Line 1455 of yacc.c */
+#line 1858 "program_parse.y"
+ { (yyval.integer) = 1; ;}
+ break;
+
+ case 255:
+
+/* Line 1455 of yacc.c */
+#line 1861 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 256:
+
+/* Line 1455 of yacc.c */
+#line 1862 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(2) - (3)].integer); ;}
+ break;
+
+ case 257:
+
+/* Line 1455 of yacc.c */
+#line 1865 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 258:
+
+/* Line 1455 of yacc.c */
+#line 1866 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(2) - (3)].integer); ;}
+ break;
+
+ case 259:
+
+/* Line 1455 of yacc.c */
+#line 1869 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 260:
+
+/* Line 1455 of yacc.c */
+#line 1870 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(2) - (3)].integer); ;}
+ break;
+
+ case 261:
+
+/* Line 1455 of yacc.c */
+#line 1874 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxTextureCoordUnits) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid texture coordinate unit selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 262:
+
+/* Line 1455 of yacc.c */
+#line 1885 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxTextureImageUnits) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid texture image unit selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 263:
+
+/* Line 1455 of yacc.c */
+#line 1896 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxTextureUnits) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid texture unit selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 264:
+
+/* Line 1455 of yacc.c */
+#line 1907 "program_parse.y"
+ {
+ struct asm_symbol *exist = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(2) - (4)].string));
+ struct asm_symbol *target = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(4) - (4)].string));
+
+
+ if (exist != NULL) {
+ yyerror(& (yylsp[(2) - (4)]), state, "redeclared identifier");
+ YYERROR;
+ } else if (target == NULL) {
+ yyerror(& (yylsp[(4) - (4)]), state,
+ "undefined variable binding in ALIAS statement");
+ YYERROR;
+ } else {
+ _mesa_symbol_table_add_symbol(state->st, 0, (yyvsp[(2) - (4)].string), target);
+ }
+ ;}
+ break;
+
+
+
+/* Line 1455 of yacc.c */
+#line 4577 "program_parse.tab.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+ *++yylsp = yyloc;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (&yylloc, state, YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (&yylloc, state, yymsg);
+ }
+ else
+ {
+ yyerror (&yylloc, state, YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+ yyerror_range[0] = yylloc;
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, &yylloc, state);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ yyerror_range[0] = yylsp[1-yylen];
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ yyerror_range[0] = *yylsp;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yylsp, state);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+ yyerror_range[1] = yylloc;
+ /* Using YYLLOC is tempting, but would change the location of
+ the lookahead. YYLOC is available though. */
+ YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+ *++yylsp = yyloc;
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (&yylloc, state, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc, state);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yylsp, state);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+/* Line 1675 of yacc.c */
+#line 1927 "program_parse.y"
+
+
+struct asm_instruction *
+asm_instruction_ctor(gl_inst_opcode op,
+ const struct prog_dst_register *dst,
+ const struct asm_src_register *src0,
+ const struct asm_src_register *src1,
+ const struct asm_src_register *src2)
+{
+ struct asm_instruction *inst = calloc(1, sizeof(struct asm_instruction));
+
+ if (inst) {
+ _mesa_init_instructions(& inst->Base, 1);
+ inst->Base.Opcode = op;
+
+ /* In the core ARB extensions only the KIL instruction doesn't have a
+ * destination register.
+ */
+ if (dst == NULL) {
+ init_dst_reg(& inst->Base.DstReg);
+ } else {
+ inst->Base.DstReg = *dst;
+ }
+
+ inst->Base.SrcReg[0] = src0->Base;
+ inst->SrcReg[0] = *src0;
+
+ if (src1 != NULL) {
+ inst->Base.SrcReg[1] = src1->Base;
+ inst->SrcReg[1] = *src1;
+ } else {
+ init_src_reg(& inst->SrcReg[1]);
+ }
+
+ if (src2 != NULL) {
+ inst->Base.SrcReg[2] = src2->Base;
+ inst->SrcReg[2] = *src2;
+ } else {
+ init_src_reg(& inst->SrcReg[2]);
+ }
+ }
+
+ return inst;
+}
+
+
+void
+init_dst_reg(struct prog_dst_register *r)
+{
+ memset(r, 0, sizeof(*r));
+ r->File = PROGRAM_UNDEFINED;
+ r->WriteMask = WRITEMASK_XYZW;
+ r->CondMask = COND_TR;
+ r->CondSwizzle = SWIZZLE_NOOP;
+}
+
+
+void
+init_src_reg(struct asm_src_register *r)
+{
+ memset(r, 0, sizeof(*r));
+ r->Base.File = PROGRAM_UNDEFINED;
+ r->Base.Swizzle = SWIZZLE_NOOP;
+ r->Symbol = NULL;
+}
+
+
+/**
+ * Validate the set of inputs used by a program
+ *
+ * Validates that legal sets of inputs are used by the program. In this case
+ * "used" included both reading the input or binding the input to a name using
+ * the \c ATTRIB command.
+ *
+ * \return
+ * \c TRUE if the combination of inputs used is valid, \c FALSE otherwise.
+ */
+int
+validate_inputs(struct YYLTYPE *locp, struct asm_parser_state *state)
+{
+ const int inputs = state->prog->InputsRead | state->InputsBound;
+
+ if (((inputs & 0x0ffff) & (inputs >> 16)) != 0) {
+ yyerror(locp, state, "illegal use of generic attribute and name attribute");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+struct asm_symbol *
+declare_variable(struct asm_parser_state *state, char *name, enum asm_type t,
+ struct YYLTYPE *locp)
+{
+ struct asm_symbol *s = NULL;
+ struct asm_symbol *exist = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, name);
+
+
+ if (exist != NULL) {
+ yyerror(locp, state, "redeclared identifier");
+ } else {
+ s = calloc(1, sizeof(struct asm_symbol));
+ s->name = name;
+ s->type = t;
+
+ switch (t) {
+ case at_temp:
+ if (state->prog->NumTemporaries >= state->limits->MaxTemps) {
+ yyerror(locp, state, "too many temporaries declared");
+ free(s);
+ return NULL;
+ }
+
+ s->temp_binding = state->prog->NumTemporaries;
+ state->prog->NumTemporaries++;
+ break;
+
+ case at_address:
+ if (state->prog->NumAddressRegs >= state->limits->MaxAddressRegs) {
+ yyerror(locp, state, "too many address registers declared");
+ free(s);
+ return NULL;
+ }
+
+ /* FINISHME: Add support for multiple address registers.
+ */
+ state->prog->NumAddressRegs++;
+ break;
+
+ default:
+ break;
+ }
+
+ _mesa_symbol_table_add_symbol(state->st, 0, s->name, s);
+ s->next = state->sym;
+ state->sym = s;
+ }
+
+ return s;
+}
+
+
+int add_state_reference(struct gl_program_parameter_list *param_list,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ const GLuint size = 4; /* XXX fix */
+ char *name;
+ GLint index;
+
+ name = _mesa_program_state_string(tokens);
+ index = _mesa_add_parameter(param_list, PROGRAM_STATE_VAR, name,
+ size, GL_NONE, NULL, tokens, 0x0);
+ param_list->StateFlags |= _mesa_program_state_flags(tokens);
+
+ /* free name string here since we duplicated it in add_parameter() */
+ _mesa_free(name);
+
+ return index;
+}
+
+
+int
+initialize_symbol_from_state(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ int idx = -1;
+ gl_state_index state_tokens[STATE_LENGTH];
+
+
+ memcpy(state_tokens, tokens, sizeof(state_tokens));
+
+ param_var->type = at_param;
+ param_var->param_binding_type = PROGRAM_STATE_VAR;
+
+ /* If we are adding a STATE_MATRIX that has multiple rows, we need to
+ * unroll it and call add_state_reference() for each row
+ */
+ if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
+ state_tokens[0] == STATE_PROJECTION_MATRIX ||
+ state_tokens[0] == STATE_MVP_MATRIX ||
+ state_tokens[0] == STATE_TEXTURE_MATRIX ||
+ state_tokens[0] == STATE_PROGRAM_MATRIX)
+ && (state_tokens[2] != state_tokens[3])) {
+ int row;
+ const int first_row = state_tokens[2];
+ const int last_row = state_tokens[3];
+
+ for (row = first_row; row <= last_row; row++) {
+ state_tokens[2] = state_tokens[3] = row;
+
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+ }
+ else {
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+
+ return idx;
+}
+
+
+int
+initialize_symbol_from_param(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ int idx = -1;
+ gl_state_index state_tokens[STATE_LENGTH];
+
+
+ memcpy(state_tokens, tokens, sizeof(state_tokens));
+
+ assert((state_tokens[0] == STATE_VERTEX_PROGRAM)
+ || (state_tokens[0] == STATE_FRAGMENT_PROGRAM));
+ assert((state_tokens[1] == STATE_ENV)
+ || (state_tokens[1] == STATE_LOCAL));
+
+ param_var->type = at_param;
+ param_var->param_binding_type = (state_tokens[1] == STATE_ENV)
+ ? PROGRAM_ENV_PARAM : PROGRAM_LOCAL_PARAM;
+
+ /* If we are adding a STATE_ENV or STATE_LOCAL that has multiple elements,
+ * we need to unroll it and call add_state_reference() for each row
+ */
+ if (state_tokens[2] != state_tokens[3]) {
+ int row;
+ const int first_row = state_tokens[2];
+ const int last_row = state_tokens[3];
+
+ for (row = first_row; row <= last_row; row++) {
+ state_tokens[2] = state_tokens[3] = row;
+
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+ }
+ else {
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+
+ return idx;
+}
+
+
+int
+initialize_symbol_from_const(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const struct asm_vector *vec)
+{
+ const int idx = _mesa_add_parameter(prog->Parameters, PROGRAM_CONSTANT,
+ NULL, vec->count, GL_NONE, vec->data,
+ NULL, 0x0);
+
+ param_var->type = at_param;
+ param_var->param_binding_type = PROGRAM_CONSTANT;
+
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+
+ return idx;
+}
+
+
+char *
+make_error_string(const char *fmt, ...)
+{
+ int length;
+ char *str;
+ va_list args;
+
+ va_start(args, fmt);
+
+ /* Call vsnprintf once to determine how large the final string is. Call it
+ * again to do the actual formatting. from the vsnprintf manual page:
+ *
+ * Upon successful return, these functions return the number of
+ * characters printed (not including the trailing '\0' used to end
+ * output to strings).
+ */
+ length = 1 + vsnprintf(NULL, 0, fmt, args);
+
+ str = _mesa_malloc(length);
+ if (str) {
+ vsnprintf(str, length, fmt, args);
+ }
+
+ va_end(args);
+
+ return str;
+}
+
+
+void
+yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
+{
+ char *err_str;
+
+
+ err_str = make_error_string("glProgramStringARB(%s)\n", s);
+ if (err_str) {
+ _mesa_error(state->ctx, GL_INVALID_OPERATION, err_str);
+ _mesa_free(err_str);
+ }
+
+ err_str = make_error_string("line %u, char %u: error: %s\n",
+ locp->first_line, locp->first_column, s);
+ _mesa_set_program_error(state->ctx, locp->position, err_str);
+
+ if (err_str) {
+ _mesa_free(err_str);
+ }
+}
+
+
+GLboolean
+_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str,
+ GLsizei len, struct asm_parser_state *state)
+{
+ struct asm_instruction *inst;
+ unsigned i;
+ GLubyte *strz;
+ GLboolean result = GL_FALSE;
+ void *temp;
+ struct asm_symbol *sym;
+
+ state->ctx = ctx;
+ state->prog->Target = target;
+ state->prog->Parameters = _mesa_new_parameter_list();
+
+ /* Make a copy of the program string and force it to be NUL-terminated.
+ */
+ strz = (GLubyte *) _mesa_malloc(len + 1);
+ if (strz == NULL) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
+ return GL_FALSE;
+ }
+ _mesa_memcpy (strz, str, len);
+ strz[len] = '\0';
+
+ state->prog->String = strz;
+
+ state->st = _mesa_symbol_table_ctor();
+
+ state->limits = (target == GL_VERTEX_PROGRAM_ARB)
+ ? & ctx->Const.VertexProgram
+ : & ctx->Const.FragmentProgram;
+
+ state->MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
+ state->MaxTextureCoordUnits = ctx->Const.MaxTextureCoordUnits;
+ state->MaxTextureUnits = ctx->Const.MaxTextureUnits;
+ state->MaxClipPlanes = ctx->Const.MaxClipPlanes;
+ state->MaxLights = ctx->Const.MaxLights;
+ state->MaxProgramMatrices = ctx->Const.MaxProgramMatrices;
+
+ state->state_param_enum = (target == GL_VERTEX_PROGRAM_ARB)
+ ? STATE_VERTEX_PROGRAM : STATE_FRAGMENT_PROGRAM;
+
+ _mesa_set_program_error(ctx, -1, NULL);
+
+ _mesa_program_lexer_ctor(& state->scanner, state, (const char *) str, len);
+ yyparse(state);
+ _mesa_program_lexer_dtor(state->scanner);
+
+
+ if (ctx->Program.ErrorPos != -1) {
+ goto error;
+ }
+
+ if (! _mesa_layout_parameters(state)) {
+ struct YYLTYPE loc;
+
+ loc.first_line = 0;
+ loc.first_column = 0;
+ loc.position = len;
+
+ yyerror(& loc, state, "invalid PARAM usage");
+ goto error;
+ }
+
+
+
+ /* Add one instruction to store the "END" instruction.
+ */
+ state->prog->Instructions =
+ _mesa_alloc_instructions(state->prog->NumInstructions + 1);
+ inst = state->inst_head;
+ for (i = 0; i < state->prog->NumInstructions; i++) {
+ struct asm_instruction *const temp = inst->next;
+
+ state->prog->Instructions[i] = inst->Base;
+ inst = temp;
+ }
+
+ /* Finally, tag on an OPCODE_END instruction */
+ {
+ const GLuint numInst = state->prog->NumInstructions;
+ _mesa_init_instructions(state->prog->Instructions + numInst, 1);
+ state->prog->Instructions[numInst].Opcode = OPCODE_END;
+ }
+ state->prog->NumInstructions++;
+
+ state->prog->NumParameters = state->prog->Parameters->NumParameters;
+ state->prog->NumAttributes = _mesa_bitcount(state->prog->InputsRead);
+
+ /*
+ * Initialize native counts to logical counts. The device driver may
+ * change them if program is translated into a hardware program.
+ */
+ state->prog->NumNativeInstructions = state->prog->NumInstructions;
+ state->prog->NumNativeTemporaries = state->prog->NumTemporaries;
+ state->prog->NumNativeParameters = state->prog->NumParameters;
+ state->prog->NumNativeAttributes = state->prog->NumAttributes;
+ state->prog->NumNativeAddressRegs = state->prog->NumAddressRegs;
+
+ result = GL_TRUE;
+
+error:
+ for (inst = state->inst_head; inst != NULL; inst = temp) {
+ temp = inst->next;
+ _mesa_free(inst);
+ }
+
+ state->inst_head = NULL;
+ state->inst_tail = NULL;
+
+ for (sym = state->sym; sym != NULL; sym = temp) {
+ temp = sym->next;
+
+ _mesa_free((void *) sym->name);
+ _mesa_free(sym);
+ }
+ state->sym = NULL;
+
+ _mesa_symbol_table_dtor(state->st);
+ state->st = NULL;
+
+ return result;
+}
+
diff --git a/src/mesa/shader/program_parse.tab.h b/src/mesa/shader/program_parse.tab.h
new file mode 100644
index 0000000000..dabb3bf1a3
--- /dev/null
+++ b/src/mesa/shader/program_parse.tab.h
@@ -0,0 +1,207 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ARBvp_10 = 258,
+ ARBfp_10 = 259,
+ ADDRESS = 260,
+ ALIAS = 261,
+ ATTRIB = 262,
+ OPTION = 263,
+ OUTPUT = 264,
+ PARAM = 265,
+ TEMP = 266,
+ END = 267,
+ BIN_OP = 268,
+ BINSC_OP = 269,
+ SAMPLE_OP = 270,
+ SCALAR_OP = 271,
+ TRI_OP = 272,
+ VECTOR_OP = 273,
+ ARL = 274,
+ KIL = 275,
+ SWZ = 276,
+ INTEGER = 277,
+ REAL = 278,
+ AMBIENT = 279,
+ ATTENUATION = 280,
+ BACK = 281,
+ CLIP = 282,
+ COLOR = 283,
+ DEPTH = 284,
+ DIFFUSE = 285,
+ DIRECTION = 286,
+ EMISSION = 287,
+ ENV = 288,
+ EYE = 289,
+ FOG = 290,
+ FOGCOORD = 291,
+ FRAGMENT = 292,
+ FRONT = 293,
+ HALF = 294,
+ INVERSE = 295,
+ INVTRANS = 296,
+ LIGHT = 297,
+ LIGHTMODEL = 298,
+ LIGHTPROD = 299,
+ LOCAL = 300,
+ MATERIAL = 301,
+ MAT_PROGRAM = 302,
+ MATRIX = 303,
+ MATRIXINDEX = 304,
+ MODELVIEW = 305,
+ MVP = 306,
+ NORMAL = 307,
+ OBJECT = 308,
+ PALETTE = 309,
+ PARAMS = 310,
+ PLANE = 311,
+ POINT_TOK = 312,
+ POINTSIZE = 313,
+ POSITION = 314,
+ PRIMARY = 315,
+ PROGRAM = 316,
+ PROJECTION = 317,
+ RANGE = 318,
+ RESULT = 319,
+ ROW = 320,
+ SCENECOLOR = 321,
+ SECONDARY = 322,
+ SHININESS = 323,
+ SIZE_TOK = 324,
+ SPECULAR = 325,
+ SPOT = 326,
+ STATE = 327,
+ TEXCOORD = 328,
+ TEXENV = 329,
+ TEXGEN = 330,
+ TEXGEN_Q = 331,
+ TEXGEN_R = 332,
+ TEXGEN_S = 333,
+ TEXGEN_T = 334,
+ TEXTURE = 335,
+ TRANSPOSE = 336,
+ TEXTURE_UNIT = 337,
+ TEX_1D = 338,
+ TEX_2D = 339,
+ TEX_3D = 340,
+ TEX_CUBE = 341,
+ TEX_RECT = 342,
+ TEX_SHADOW1D = 343,
+ TEX_SHADOW2D = 344,
+ TEX_SHADOWRECT = 345,
+ TEX_ARRAY1D = 346,
+ TEX_ARRAY2D = 347,
+ TEX_ARRAYSHADOW1D = 348,
+ TEX_ARRAYSHADOW2D = 349,
+ VERTEX = 350,
+ VTXATTRIB = 351,
+ WEIGHT = 352,
+ IDENTIFIER = 353,
+ MASK4 = 354,
+ MASK3 = 355,
+ MASK2 = 356,
+ MASK1 = 357,
+ SWIZZLE = 358,
+ DOT_DOT = 359,
+ DOT = 360
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 1676 of yacc.c */
+#line 107 "program_parse.y"
+
+ struct asm_instruction *inst;
+ struct asm_symbol *sym;
+ struct asm_symbol temp_sym;
+ struct asm_swizzle_mask swiz_mask;
+ struct asm_src_register src_reg;
+ struct prog_dst_register dst_reg;
+ struct prog_instruction temp_inst;
+ char *string;
+ unsigned result;
+ unsigned attrib;
+ int integer;
+ float real;
+ gl_state_index state[STATE_LENGTH];
+ int negate;
+ struct asm_vector vector;
+ gl_inst_opcode opcode;
+
+ struct {
+ unsigned swz;
+ unsigned rgba_valid:1;
+ unsigned xyzw_valid:1;
+ unsigned negate:1;
+ } ext_swizzle;
+
+
+
+/* Line 1676 of yacc.c */
+#line 185 "program_parse.tab.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/src/mesa/shader/program_parse.y b/src/mesa/shader/program_parse.y
new file mode 100644
index 0000000000..06c1915fbe
--- /dev/null
+++ b/src/mesa/shader/program_parse.y
@@ -0,0 +1,2379 @@
+%{
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "program.h"
+#include "prog_parameter.h"
+#include "prog_parameter_layout.h"
+#include "prog_statevars.h"
+#include "prog_instruction.h"
+
+#include "symbol_table.h"
+#include "program_parser.h"
+
+extern void *yy_scan_string(char *);
+extern void yy_delete_buffer(void *);
+
+static struct asm_symbol *declare_variable(struct asm_parser_state *state,
+ char *name, enum asm_type t, struct YYLTYPE *locp);
+
+static int add_state_reference(struct gl_program_parameter_list *param_list,
+ const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_state(struct gl_program *prog,
+ struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_param(struct gl_program *prog,
+ struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_const(struct gl_program *prog,
+ struct asm_symbol *param_var, const struct asm_vector *vec);
+
+static int yyparse(struct asm_parser_state *state);
+
+static char *make_error_string(const char *fmt, ...);
+
+static void yyerror(struct YYLTYPE *locp, struct asm_parser_state *state,
+ const char *s);
+
+static int validate_inputs(struct YYLTYPE *locp,
+ struct asm_parser_state *state);
+
+static void init_dst_reg(struct prog_dst_register *r);
+
+static void init_src_reg(struct asm_src_register *r);
+
+static struct asm_instruction *asm_instruction_ctor(gl_inst_opcode op,
+ const struct prog_dst_register *dst, const struct asm_src_register *src0,
+ const struct asm_src_register *src1, const struct asm_src_register *src2);
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do { \
+ if (YYID(N)) { \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
+ (Current).position = YYRHSLOC(Rhs, 1).position; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC(Rhs, N).last_column; \
+ } else { \
+ (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \
+ (Current).last_line = (Current).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 0).last_column; \
+ (Current).last_column = (Current).first_column; \
+ (Current).position = YYRHSLOC(Rhs, 0).position \
+ + (Current).first_column; \
+ } \
+ } while(YYID(0))
+
+#define YYLEX_PARAM state->scanner
+%}
+
+%pure-parser
+%locations
+%parse-param { struct asm_parser_state *state }
+%error-verbose
+%lex-param { void *scanner }
+
+%union {
+ struct asm_instruction *inst;
+ struct asm_symbol *sym;
+ struct asm_symbol temp_sym;
+ struct asm_swizzle_mask swiz_mask;
+ struct asm_src_register src_reg;
+ struct prog_dst_register dst_reg;
+ struct prog_instruction temp_inst;
+ char *string;
+ unsigned result;
+ unsigned attrib;
+ int integer;
+ float real;
+ gl_state_index state[STATE_LENGTH];
+ int negate;
+ struct asm_vector vector;
+ gl_inst_opcode opcode;
+
+ struct {
+ unsigned swz;
+ unsigned rgba_valid:1;
+ unsigned xyzw_valid:1;
+ unsigned negate:1;
+ } ext_swizzle;
+}
+
+%token ARBvp_10 ARBfp_10
+
+/* Tokens for assembler pseudo-ops */
+%token <integer> ADDRESS
+%token ALIAS ATTRIB
+%token OPTION OUTPUT
+%token PARAM
+%token <integer> TEMP
+%token END
+
+ /* Tokens for instructions */
+%token <temp_inst> BIN_OP BINSC_OP SAMPLE_OP SCALAR_OP TRI_OP VECTOR_OP
+%token <temp_inst> ARL KIL SWZ
+
+%token <integer> INTEGER
+%token <real> REAL
+
+%token AMBIENT ATTENUATION
+%token BACK
+%token CLIP COLOR
+%token DEPTH DIFFUSE DIRECTION
+%token EMISSION ENV EYE
+%token FOG FOGCOORD FRAGMENT FRONT
+%token HALF
+%token INVERSE INVTRANS
+%token LIGHT LIGHTMODEL LIGHTPROD LOCAL
+%token MATERIAL MAT_PROGRAM MATRIX MATRIXINDEX MODELVIEW MVP
+%token NORMAL
+%token OBJECT
+%token PALETTE PARAMS PLANE POINT_TOK POINTSIZE POSITION PRIMARY PROGRAM PROJECTION
+%token RANGE RESULT ROW
+%token SCENECOLOR SECONDARY SHININESS SIZE_TOK SPECULAR SPOT STATE
+%token TEXCOORD TEXENV TEXGEN TEXGEN_Q TEXGEN_R TEXGEN_S TEXGEN_T TEXTURE TRANSPOSE
+%token TEXTURE_UNIT TEX_1D TEX_2D TEX_3D TEX_CUBE TEX_RECT
+%token TEX_SHADOW1D TEX_SHADOW2D TEX_SHADOWRECT
+%token TEX_ARRAY1D TEX_ARRAY2D TEX_ARRAYSHADOW1D TEX_ARRAYSHADOW2D
+%token VERTEX VTXATTRIB
+%token WEIGHT
+
+%token <string> IDENTIFIER
+%token <swiz_mask> MASK4 MASK3 MASK2 MASK1 SWIZZLE
+%token DOT_DOT
+%token DOT
+
+%type <inst> instruction ALU_instruction TexInstruction
+%type <inst> ARL_instruction VECTORop_instruction
+%type <inst> SCALARop_instruction BINSCop_instruction BINop_instruction
+%type <inst> TRIop_instruction SWZ_instruction SAMPLE_instruction
+%type <inst> KIL_instruction
+
+%type <dst_reg> dstReg maskedDstReg maskedAddrReg
+%type <src_reg> srcReg scalarSrcReg swizzleSrcReg
+%type <swiz_mask> scalarSuffix swizzleSuffix extendedSwizzle
+%type <ext_swizzle> extSwizComp extSwizSel
+%type <swiz_mask> optionalMask
+
+%type <sym> progParamArray
+%type <integer> addrRegRelOffset addrRegPosOffset addrRegNegOffset
+%type <src_reg> progParamArrayMem progParamArrayAbs progParamArrayRel
+%type <sym> addrReg
+%type <swiz_mask> addrComponent addrWriteMask
+
+%type <result> resultBinding resultColBinding
+%type <integer> optFaceType optColorType
+%type <integer> optResultFaceType optResultColorType
+
+%type <integer> optTexImageUnitNum texImageUnitNum
+%type <integer> optTexCoordUnitNum texCoordUnitNum
+%type <integer> optLegacyTexUnitNum legacyTexUnitNum
+%type <integer> texImageUnit texTarget
+%type <integer> vtxAttribNum
+
+%type <attrib> attribBinding vtxAttribItem fragAttribItem
+
+%type <temp_sym> paramSingleInit paramSingleItemDecl
+%type <integer> optArraySize
+
+%type <state> stateSingleItem stateMultipleItem
+%type <state> stateMaterialItem
+%type <state> stateLightItem stateLightModelItem stateLightProdItem
+%type <state> stateTexGenItem stateFogItem stateClipPlaneItem statePointItem
+%type <state> stateMatrixItem stateMatrixRow stateMatrixRows
+%type <state> stateTexEnvItem stateDepthItem
+
+%type <state> stateLModProperty
+%type <state> stateMatrixName optMatrixRows
+
+%type <integer> stateMatProperty
+%type <integer> stateLightProperty stateSpotProperty
+%type <integer> stateLightNumber stateLProdProperty
+%type <integer> stateTexGenType stateTexGenCoord
+%type <integer> stateTexEnvProperty
+%type <integer> stateFogProperty
+%type <integer> stateClipPlaneNum
+%type <integer> statePointProperty
+
+%type <integer> stateOptMatModifier stateMatModifier stateMatrixRowNum
+%type <integer> stateOptModMatNum stateModMatNum statePaletteMatNum
+%type <integer> stateProgramMatNum
+
+%type <integer> ambDiffSpecProperty
+
+%type <state> programSingleItem progEnvParam progLocalParam
+%type <state> programMultipleItem progEnvParams progLocalParams
+
+%type <temp_sym> paramMultipleInit paramMultInitList paramMultipleItem
+%type <temp_sym> paramSingleItemUse
+
+%type <integer> progEnvParamNum progLocalParamNum
+%type <state> progEnvParamNums progLocalParamNums
+
+%type <vector> paramConstDecl paramConstUse
+%type <vector> paramConstScalarDecl paramConstScalarUse paramConstVector
+%type <real> signedFloatConstant
+%type <negate> optionalSign
+
+%{
+extern int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param,
+ void *yyscanner);
+%}
+
+%%
+
+program: language optionSequence statementSequence END
+ ;
+
+language: ARBvp_10
+ {
+ if (state->prog->Target != GL_VERTEX_PROGRAM_ARB) {
+ yyerror(& @1, state, "invalid fragment program header");
+
+ }
+ state->mode = ARB_vertex;
+ }
+ | ARBfp_10
+ {
+ if (state->prog->Target != GL_FRAGMENT_PROGRAM_ARB) {
+ yyerror(& @1, state, "invalid vertex program header");
+ }
+ state->mode = ARB_fragment;
+
+ state->option.TexRect =
+ (state->ctx->Extensions.NV_texture_rectangle != GL_FALSE);
+ }
+ ;
+
+optionSequence: optionSequence option
+ |
+ ;
+
+option: OPTION IDENTIFIER ';'
+ {
+ int valid = 0;
+
+ if (state->mode == ARB_vertex) {
+ valid = _mesa_ARBvp_parse_option(state, $2);
+ } else if (state->mode == ARB_fragment) {
+ valid = _mesa_ARBfp_parse_option(state, $2);
+ }
+
+
+ if (!valid) {
+ const char *const err_str = (state->mode == ARB_vertex)
+ ? "invalid ARB vertex program option"
+ : "invalid ARB fragment program option";
+
+ yyerror(& @2, state, err_str);
+ YYERROR;
+ }
+ }
+ ;
+
+statementSequence: statementSequence statement
+ |
+ ;
+
+statement: instruction ';'
+ {
+ if ($1 != NULL) {
+ if (state->inst_tail == NULL) {
+ state->inst_head = $1;
+ } else {
+ state->inst_tail->next = $1;
+ }
+
+ state->inst_tail = $1;
+ $1->next = NULL;
+
+ state->prog->NumInstructions++;
+ }
+ }
+ | namingStatement ';'
+ ;
+
+instruction: ALU_instruction
+ {
+ $$ = $1;
+ state->prog->NumAluInstructions++;
+ }
+ | TexInstruction
+ {
+ $$ = $1;
+ state->prog->NumTexInstructions++;
+ }
+ ;
+
+ALU_instruction: ARL_instruction
+ | VECTORop_instruction
+ | SCALARop_instruction
+ | BINSCop_instruction
+ | BINop_instruction
+ | TRIop_instruction
+ | SWZ_instruction
+ ;
+
+TexInstruction: SAMPLE_instruction
+ | KIL_instruction
+ ;
+
+ARL_instruction: ARL maskedAddrReg ',' scalarSrcReg
+ {
+ $$ = asm_instruction_ctor(OPCODE_ARL, & $2, & $4, NULL, NULL);
+ }
+ ;
+
+VECTORop_instruction: VECTOR_OP maskedDstReg ',' swizzleSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+SCALARop_instruction: SCALAR_OP maskedDstReg ',' scalarSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+BINSCop_instruction: BINSC_OP maskedDstReg ',' scalarSrcReg ',' scalarSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+
+BINop_instruction: BIN_OP maskedDstReg ',' swizzleSrcReg ',' swizzleSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+TRIop_instruction: TRI_OP maskedDstReg ','
+ swizzleSrcReg ',' swizzleSrcReg ',' swizzleSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, & $8);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+SAMPLE_instruction: SAMPLE_OP maskedDstReg ',' swizzleSrcReg ',' texImageUnit ',' texTarget
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
+ if ($$ != NULL) {
+ const GLbitfield tex_mask = (1U << $6);
+ GLbitfield shadow_tex = 0;
+ GLbitfield target_mask = 0;
+
+
+ $$->Base.SaturateMode = $1.SaturateMode;
+ $$->Base.TexSrcUnit = $6;
+
+ if ($8 < 0) {
+ shadow_tex = tex_mask;
+
+ $$->Base.TexSrcTarget = -$8;
+ $$->Base.TexShadow = 1;
+ } else {
+ $$->Base.TexSrcTarget = $8;
+ }
+
+ target_mask = (1U << $$->Base.TexSrcTarget);
+
+ /* If this texture unit was previously accessed and that access
+ * had a different texture target, generate an error.
+ *
+ * If this texture unit was previously accessed and that access
+ * had a different shadow mode, generate an error.
+ */
+ if ((state->prog->TexturesUsed[$6] != 0)
+ && ((state->prog->TexturesUsed[$6] != target_mask)
+ || ((state->prog->ShadowSamplers & tex_mask)
+ != shadow_tex))) {
+ yyerror(& @8, state,
+ "multiple targets used on one texture image unit");
+ YYERROR;
+ }
+
+
+ state->prog->TexturesUsed[$6] |= target_mask;
+ state->prog->ShadowSamplers |= shadow_tex;
+ }
+ }
+ ;
+
+KIL_instruction: KIL swizzleSrcReg
+ {
+ $$ = asm_instruction_ctor(OPCODE_KIL, NULL, & $2, NULL, NULL);
+ state->fragment.UsesKill = 1;
+ }
+ ;
+
+texImageUnit: TEXTURE_UNIT optTexImageUnitNum
+ {
+ $$ = $2;
+ }
+ ;
+
+texTarget: TEX_1D { $$ = TEXTURE_1D_INDEX; }
+ | TEX_2D { $$ = TEXTURE_2D_INDEX; }
+ | TEX_3D { $$ = TEXTURE_3D_INDEX; }
+ | TEX_CUBE { $$ = TEXTURE_CUBE_INDEX; }
+ | TEX_RECT { $$ = TEXTURE_RECT_INDEX; }
+ | TEX_SHADOW1D { $$ = -TEXTURE_1D_INDEX; }
+ | TEX_SHADOW2D { $$ = -TEXTURE_2D_INDEX; }
+ | TEX_SHADOWRECT { $$ = -TEXTURE_RECT_INDEX; }
+ | TEX_ARRAY1D { $$ = TEXTURE_1D_ARRAY_INDEX; }
+ | TEX_ARRAY2D { $$ = TEXTURE_2D_ARRAY_INDEX; }
+ | TEX_ARRAYSHADOW1D { $$ = -TEXTURE_1D_ARRAY_INDEX; }
+ | TEX_ARRAYSHADOW2D { $$ = -TEXTURE_2D_ARRAY_INDEX; }
+ ;
+
+SWZ_instruction: SWZ maskedDstReg ',' srcReg ',' extendedSwizzle
+ {
+ /* FIXME: Is this correct? Should the extenedSwizzle be applied
+ * FIXME: to the existing swizzle?
+ */
+ $4.Base.Swizzle = $6.swizzle;
+ $4.Base.Negate = $6.mask;
+
+ $$ = asm_instruction_ctor(OPCODE_SWZ, & $2, & $4, NULL, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+scalarSrcReg: optionalSign srcReg scalarSuffix
+ {
+ $$ = $2;
+
+ if ($1) {
+ $$.Base.Negate = ~$$.Base.Negate;
+ }
+
+ $$.Base.Swizzle = _mesa_combine_swizzles($$.Base.Swizzle,
+ $3.swizzle);
+ }
+ ;
+
+swizzleSrcReg: optionalSign srcReg swizzleSuffix
+ {
+ $$ = $2;
+
+ if ($1) {
+ $$.Base.Negate = ~$$.Base.Negate;
+ }
+
+ $$.Base.Swizzle = _mesa_combine_swizzles($$.Base.Swizzle,
+ $3.swizzle);
+ }
+ ;
+
+maskedDstReg: dstReg optionalMask
+ {
+ $$ = $1;
+ $$.WriteMask = $2.mask;
+
+ if ($$.File == PROGRAM_OUTPUT) {
+ /* Technically speaking, this should check that it is in
+ * vertex program mode. However, PositionInvariant can never be
+ * set in fragment program mode, so it is somewhat irrelevant.
+ */
+ if (state->option.PositionInvariant
+ && ($$.Index == VERT_RESULT_HPOS)) {
+ yyerror(& @1, state, "position-invariant programs cannot "
+ "write position");
+ YYERROR;
+ }
+
+ state->prog->OutputsWritten |= (1U << $$.Index);
+ }
+ }
+ ;
+
+maskedAddrReg: addrReg addrWriteMask
+ {
+ init_dst_reg(& $$);
+ $$.File = PROGRAM_ADDRESS;
+ $$.Index = 0;
+ $$.WriteMask = $2.mask;
+ }
+ ;
+
+extendedSwizzle: extSwizComp ',' extSwizComp ',' extSwizComp ',' extSwizComp
+ {
+ const unsigned xyzw_valid =
+ ($1.xyzw_valid << 0)
+ | ($3.xyzw_valid << 1)
+ | ($5.xyzw_valid << 2)
+ | ($7.xyzw_valid << 3);
+ const unsigned rgba_valid =
+ ($1.rgba_valid << 0)
+ | ($3.rgba_valid << 1)
+ | ($5.rgba_valid << 2)
+ | ($7.rgba_valid << 3);
+
+ /* All of the swizzle components have to be valid in either RGBA
+ * or XYZW. Note that 0 and 1 are valid in both, so both masks
+ * can have some bits set.
+ *
+ * We somewhat deviate from the spec here. It would be really hard
+ * to figure out which component is the error, and there probably
+ * isn't a lot of benefit.
+ */
+ if ((rgba_valid != 0x0f) && (xyzw_valid != 0x0f)) {
+ yyerror(& @1, state, "cannot combine RGBA and XYZW swizzle "
+ "components");
+ YYERROR;
+ }
+
+ $$.swizzle = MAKE_SWIZZLE4($1.swz, $3.swz, $5.swz, $7.swz);
+ $$.mask = ($1.negate) | ($3.negate << 1) | ($5.negate << 2)
+ | ($7.negate << 3);
+ }
+ ;
+
+extSwizComp: optionalSign extSwizSel
+ {
+ $$ = $2;
+ $$.negate = ($1) ? 1 : 0;
+ }
+ ;
+
+extSwizSel: INTEGER
+ {
+ if (($1 != 0) && ($1 != 1)) {
+ yyerror(& @1, state, "invalid extended swizzle selector");
+ YYERROR;
+ }
+
+ $$.swz = ($1 == 0) ? SWIZZLE_ZERO : SWIZZLE_ONE;
+
+ /* 0 and 1 are valid for both RGBA swizzle names and XYZW
+ * swizzle names.
+ */
+ $$.xyzw_valid = 1;
+ $$.rgba_valid = 1;
+ }
+ | IDENTIFIER
+ {
+ if (strlen($1) > 1) {
+ yyerror(& @1, state, "invalid extended swizzle selector");
+ YYERROR;
+ }
+
+ switch ($1[0]) {
+ case 'x':
+ $$.swz = SWIZZLE_X;
+ $$.xyzw_valid = 1;
+ break;
+ case 'y':
+ $$.swz = SWIZZLE_Y;
+ $$.xyzw_valid = 1;
+ break;
+ case 'z':
+ $$.swz = SWIZZLE_Z;
+ $$.xyzw_valid = 1;
+ break;
+ case 'w':
+ $$.swz = SWIZZLE_W;
+ $$.xyzw_valid = 1;
+ break;
+
+ case 'r':
+ $$.swz = SWIZZLE_X;
+ $$.rgba_valid = 1;
+ break;
+ case 'g':
+ $$.swz = SWIZZLE_Y;
+ $$.rgba_valid = 1;
+ break;
+ case 'b':
+ $$.swz = SWIZZLE_Z;
+ $$.rgba_valid = 1;
+ break;
+ case 'a':
+ $$.swz = SWIZZLE_W;
+ $$.rgba_valid = 1;
+ break;
+
+ default:
+ yyerror(& @1, state, "invalid extended swizzle selector");
+ YYERROR;
+ break;
+ }
+ }
+ ;
+
+srcReg: IDENTIFIER /* temporaryReg | progParamSingle */
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $1);
+
+ if (s == NULL) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_param) && (s->type != at_temp)
+ && (s->type != at_attrib)) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type == at_param) && s->param_is_array) {
+ yyerror(& @1, state, "non-array access to array PARAM");
+ YYERROR;
+ }
+
+ init_src_reg(& $$);
+ switch (s->type) {
+ case at_temp:
+ $$.Base.File = PROGRAM_TEMPORARY;
+ $$.Base.Index = s->temp_binding;
+ break;
+ case at_param:
+ $$.Base.File = s->param_binding_type;
+ $$.Base.Index = s->param_binding_begin;
+ break;
+ case at_attrib:
+ $$.Base.File = PROGRAM_INPUT;
+ $$.Base.Index = s->attrib_binding;
+ state->prog->InputsRead |= (1U << $$.Base.Index);
+
+ if (!validate_inputs(& @1, state)) {
+ YYERROR;
+ }
+ break;
+
+ default:
+ YYERROR;
+ break;
+ }
+ }
+ | attribBinding
+ {
+ init_src_reg(& $$);
+ $$.Base.File = PROGRAM_INPUT;
+ $$.Base.Index = $1;
+ state->prog->InputsRead |= (1U << $$.Base.Index);
+
+ if (!validate_inputs(& @1, state)) {
+ YYERROR;
+ }
+ }
+ | progParamArray '[' progParamArrayMem ']'
+ {
+ if (! $3.Base.RelAddr
+ && ((unsigned) $3.Base.Index >= $1->param_binding_length)) {
+ yyerror(& @3, state, "out of bounds array access");
+ YYERROR;
+ }
+
+ init_src_reg(& $$);
+ $$.Base.File = $1->param_binding_type;
+
+ if ($3.Base.RelAddr) {
+ $1->param_accessed_indirectly = 1;
+
+ $$.Base.RelAddr = 1;
+ $$.Base.Index = $3.Base.Index;
+ $$.Symbol = $1;
+ } else {
+ $$.Base.Index = $1->param_binding_begin + $3.Base.Index;
+ }
+ }
+ | paramSingleItemUse
+ {
+ init_src_reg(& $$);
+ $$.Base.File = ($1.name != NULL)
+ ? $1.param_binding_type
+ : PROGRAM_CONSTANT;
+ $$.Base.Index = $1.param_binding_begin;
+ }
+ ;
+
+dstReg: resultBinding
+ {
+ init_dst_reg(& $$);
+ $$.File = PROGRAM_OUTPUT;
+ $$.Index = $1;
+ }
+ | IDENTIFIER /* temporaryReg | vertexResultReg */
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $1);
+
+ if (s == NULL) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_output) && (s->type != at_temp)) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ }
+
+ init_dst_reg(& $$);
+ switch (s->type) {
+ case at_temp:
+ $$.File = PROGRAM_TEMPORARY;
+ $$.Index = s->temp_binding;
+ break;
+ case at_output:
+ $$.File = PROGRAM_OUTPUT;
+ $$.Index = s->output_binding;
+ break;
+ default:
+ $$.File = s->param_binding_type;
+ $$.Index = s->param_binding_begin;
+ break;
+ }
+ }
+ ;
+
+progParamArray: IDENTIFIER
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $1);
+
+ if (s == NULL) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_param) || !s->param_is_array) {
+ yyerror(& @1, state, "array access to non-PARAM variable");
+ YYERROR;
+ } else {
+ $$ = s;
+ }
+ }
+ ;
+
+progParamArrayMem: progParamArrayAbs | progParamArrayRel;
+
+progParamArrayAbs: INTEGER
+ {
+ init_src_reg(& $$);
+ $$.Base.Index = $1;
+ }
+ ;
+
+progParamArrayRel: addrReg addrComponent addrRegRelOffset
+ {
+ /* FINISHME: Add support for multiple address registers.
+ */
+ /* FINISHME: Add support for 4-component address registers.
+ */
+ init_src_reg(& $$);
+ $$.Base.RelAddr = 1;
+ $$.Base.Index = $3;
+ }
+ ;
+
+addrRegRelOffset: { $$ = 0; }
+ | '+' addrRegPosOffset { $$ = $2; }
+ | '-' addrRegNegOffset { $$ = -$2; }
+ ;
+
+addrRegPosOffset: INTEGER
+ {
+ if (($1 < 0) || ($1 > 63)) {
+ yyerror(& @1, state,
+ "relative address offset too large (positive)");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+addrRegNegOffset: INTEGER
+ {
+ if (($1 < 0) || ($1 > 64)) {
+ yyerror(& @1, state,
+ "relative address offset too large (negative)");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+addrReg: IDENTIFIER
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $1);
+
+ if (s == NULL) {
+ yyerror(& @1, state, "invalid array member");
+ YYERROR;
+ } else if (s->type != at_address) {
+ yyerror(& @1, state,
+ "invalid variable for indexed array access");
+ YYERROR;
+ } else {
+ $$ = s;
+ }
+ }
+ ;
+
+addrComponent: MASK1
+ {
+ if ($1.mask != WRITEMASK_X) {
+ yyerror(& @1, state, "invalid address component selector");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+addrWriteMask: MASK1
+ {
+ if ($1.mask != WRITEMASK_X) {
+ yyerror(& @1, state,
+ "address register write mask must be \".x\"");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+scalarSuffix: MASK1;
+
+swizzleSuffix: MASK1
+ | MASK4
+ | SWIZZLE
+ | { $$.swizzle = SWIZZLE_NOOP; $$.mask = WRITEMASK_XYZW; }
+ ;
+
+optionalMask: MASK4 | MASK3 | MASK2 | MASK1
+ | { $$.swizzle = SWIZZLE_NOOP; $$.mask = WRITEMASK_XYZW; }
+ ;
+
+namingStatement: ATTRIB_statement
+ | PARAM_statement
+ | TEMP_statement
+ | ADDRESS_statement
+ | OUTPUT_statement
+ | ALIAS_statement
+ ;
+
+ATTRIB_statement: ATTRIB IDENTIFIER '=' attribBinding
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, $2, at_attrib, & @2);
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->attrib_binding = $4;
+ state->InputsBound |= (1U << s->attrib_binding);
+
+ if (!validate_inputs(& @4, state)) {
+ YYERROR;
+ }
+ }
+ }
+ ;
+
+attribBinding: VERTEX vtxAttribItem
+ {
+ $$ = $2;
+ }
+ | FRAGMENT fragAttribItem
+ {
+ $$ = $2;
+ }
+ ;
+
+vtxAttribItem: POSITION
+ {
+ $$ = VERT_ATTRIB_POS;
+ }
+ | WEIGHT vtxOptWeightNum
+ {
+ $$ = VERT_ATTRIB_WEIGHT;
+ }
+ | NORMAL
+ {
+ $$ = VERT_ATTRIB_NORMAL;
+ }
+ | COLOR optColorType
+ {
+ if (!state->ctx->Extensions.EXT_secondary_color) {
+ yyerror(& @2, state, "GL_EXT_secondary_color not supported");
+ YYERROR;
+ }
+
+ $$ = VERT_ATTRIB_COLOR0 + $2;
+ }
+ | FOGCOORD
+ {
+ if (!state->ctx->Extensions.EXT_fog_coord) {
+ yyerror(& @1, state, "GL_EXT_fog_coord not supported");
+ YYERROR;
+ }
+
+ $$ = VERT_ATTRIB_FOG;
+ }
+ | TEXCOORD optTexCoordUnitNum
+ {
+ $$ = VERT_ATTRIB_TEX0 + $2;
+ }
+ | MATRIXINDEX '[' vtxWeightNum ']'
+ {
+ yyerror(& @1, state, "GL_ARB_matrix_palette not supported");
+ YYERROR;
+ }
+ | VTXATTRIB '[' vtxAttribNum ']'
+ {
+ $$ = VERT_ATTRIB_GENERIC0 + $3;
+ }
+ ;
+
+vtxAttribNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->limits->MaxAttribs) {
+ yyerror(& @1, state, "invalid vertex attribute reference");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+vtxOptWeightNum: | '[' vtxWeightNum ']';
+vtxWeightNum: INTEGER;
+
+fragAttribItem: POSITION
+ {
+ $$ = FRAG_ATTRIB_WPOS;
+ }
+ | COLOR optColorType
+ {
+ $$ = FRAG_ATTRIB_COL0 + $2;
+ }
+ | FOGCOORD
+ {
+ $$ = FRAG_ATTRIB_FOGC;
+ }
+ | TEXCOORD optTexCoordUnitNum
+ {
+ $$ = FRAG_ATTRIB_TEX0 + $2;
+ }
+ ;
+
+PARAM_statement: PARAM_singleStmt | PARAM_multipleStmt;
+
+PARAM_singleStmt: PARAM IDENTIFIER paramSingleInit
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, $2, at_param, & @2);
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->param_binding_type = $3.param_binding_type;
+ s->param_binding_begin = $3.param_binding_begin;
+ s->param_binding_length = $3.param_binding_length;
+ s->param_is_array = 0;
+ }
+ }
+ ;
+
+PARAM_multipleStmt: PARAM IDENTIFIER '[' optArraySize ']' paramMultipleInit
+ {
+ if (($4 != 0) && ((unsigned) $4 != $6.param_binding_length)) {
+ yyerror(& @4, state,
+ "parameter array size and number of bindings must match");
+ YYERROR;
+ } else {
+ struct asm_symbol *const s =
+ declare_variable(state, $2, $6.type, & @2);
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->param_binding_type = $6.param_binding_type;
+ s->param_binding_begin = $6.param_binding_begin;
+ s->param_binding_length = $6.param_binding_length;
+ s->param_is_array = 1;
+ }
+ }
+ }
+ ;
+
+optArraySize:
+ {
+ $$ = 0;
+ }
+ | INTEGER
+ {
+ if (($1 < 1) || ((unsigned) $1 >= state->limits->MaxParameters)) {
+ yyerror(& @1, state, "invalid parameter array size");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+paramSingleInit: '=' paramSingleItemDecl
+ {
+ $$ = $2;
+ }
+ ;
+
+paramMultipleInit: '=' '{' paramMultInitList '}'
+ {
+ $$ = $3;
+ }
+ ;
+
+paramMultInitList: paramMultipleItem
+ | paramMultInitList ',' paramMultipleItem
+ {
+ $1.param_binding_length += $3.param_binding_length;
+ $$ = $1;
+ }
+ ;
+
+paramSingleItemDecl: stateSingleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & $$, $1);
+ }
+ | programSingleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & $$, $1);
+ }
+ | paramConstDecl
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & $$, & $1);
+ }
+ ;
+
+paramSingleItemUse: stateSingleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & $$, $1);
+ }
+ | programSingleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & $$, $1);
+ }
+ | paramConstUse
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & $$, & $1);
+ }
+ ;
+
+paramMultipleItem: stateMultipleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & $$, $1);
+ }
+ | programMultipleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & $$, $1);
+ }
+ | paramConstDecl
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & $$, & $1);
+ }
+ ;
+
+stateMultipleItem: stateSingleItem { memcpy($$, $1, sizeof($$)); }
+ | STATE stateMatrixRows { memcpy($$, $2, sizeof($$)); }
+ ;
+
+stateSingleItem: STATE stateMaterialItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateLightItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateLightModelItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateLightProdItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateTexGenItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateTexEnvItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateFogItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateClipPlaneItem { memcpy($$, $2, sizeof($$)); }
+ | STATE statePointItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateMatrixRow { memcpy($$, $2, sizeof($$)); }
+ | STATE stateDepthItem { memcpy($$, $2, sizeof($$)); }
+ ;
+
+stateMaterialItem: MATERIAL optFaceType stateMatProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_MATERIAL;
+ $$[1] = $2;
+ $$[2] = $3;
+ }
+ ;
+
+stateMatProperty: ambDiffSpecProperty
+ {
+ $$ = $1;
+ }
+ | EMISSION
+ {
+ $$ = STATE_EMISSION;
+ }
+ | SHININESS
+ {
+ $$ = STATE_SHININESS;
+ }
+ ;
+
+stateLightItem: LIGHT '[' stateLightNumber ']' stateLightProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_LIGHT;
+ $$[1] = $3;
+ $$[2] = $5;
+ }
+ ;
+
+stateLightProperty: ambDiffSpecProperty
+ {
+ $$ = $1;
+ }
+ | POSITION
+ {
+ $$ = STATE_POSITION;
+ }
+ | ATTENUATION
+ {
+ if (!state->ctx->Extensions.EXT_point_parameters) {
+ yyerror(& @1, state, "GL_ARB_point_parameters not supported");
+ YYERROR;
+ }
+
+ $$ = STATE_ATTENUATION;
+ }
+ | SPOT stateSpotProperty
+ {
+ $$ = $2;
+ }
+ | HALF
+ {
+ $$ = STATE_HALF_VECTOR;
+ }
+ ;
+
+stateSpotProperty: DIRECTION
+ {
+ $$ = STATE_SPOT_DIRECTION;
+ }
+ ;
+
+stateLightModelItem: LIGHTMODEL stateLModProperty
+ {
+ $$[0] = $2[0];
+ $$[1] = $2[1];
+ }
+ ;
+
+stateLModProperty: AMBIENT
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_LIGHTMODEL_AMBIENT;
+ }
+ | optFaceType SCENECOLOR
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_LIGHTMODEL_SCENECOLOR;
+ $$[1] = $1;
+ }
+ ;
+
+stateLightProdItem: LIGHTPROD '[' stateLightNumber ']' optFaceType stateLProdProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_LIGHTPROD;
+ $$[1] = $3;
+ $$[2] = $5;
+ $$[3] = $6;
+ }
+ ;
+
+stateLProdProperty: ambDiffSpecProperty;
+
+stateTexEnvItem: TEXENV optLegacyTexUnitNum stateTexEnvProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = $3;
+ $$[1] = $2;
+ }
+ ;
+
+stateTexEnvProperty: COLOR
+ {
+ $$ = STATE_TEXENV_COLOR;
+ }
+ ;
+
+ambDiffSpecProperty: AMBIENT
+ {
+ $$ = STATE_AMBIENT;
+ }
+ | DIFFUSE
+ {
+ $$ = STATE_DIFFUSE;
+ }
+ | SPECULAR
+ {
+ $$ = STATE_SPECULAR;
+ }
+ ;
+
+stateLightNumber: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxLights) {
+ yyerror(& @1, state, "invalid light selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+stateTexGenItem: TEXGEN optTexCoordUnitNum stateTexGenType stateTexGenCoord
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_TEXGEN;
+ $$[1] = $2;
+ $$[2] = $3 + $4;
+ }
+ ;
+
+stateTexGenType: EYE
+ {
+ $$ = STATE_TEXGEN_EYE_S;
+ }
+ | OBJECT
+ {
+ $$ = STATE_TEXGEN_OBJECT_S;
+ }
+ ;
+stateTexGenCoord: TEXGEN_S
+ {
+ $$ = STATE_TEXGEN_EYE_S - STATE_TEXGEN_EYE_S;
+ }
+ | TEXGEN_T
+ {
+ $$ = STATE_TEXGEN_EYE_T - STATE_TEXGEN_EYE_S;
+ }
+ | TEXGEN_R
+ {
+ $$ = STATE_TEXGEN_EYE_R - STATE_TEXGEN_EYE_S;
+ }
+ | TEXGEN_Q
+ {
+ $$ = STATE_TEXGEN_EYE_Q - STATE_TEXGEN_EYE_S;
+ }
+ ;
+
+stateFogItem: FOG stateFogProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = $2;
+ }
+ ;
+
+stateFogProperty: COLOR
+ {
+ $$ = STATE_FOG_COLOR;
+ }
+ | PARAMS
+ {
+ $$ = STATE_FOG_PARAMS;
+ }
+ ;
+
+stateClipPlaneItem: CLIP '[' stateClipPlaneNum ']' PLANE
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_CLIPPLANE;
+ $$[1] = $3;
+ }
+ ;
+
+stateClipPlaneNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxClipPlanes) {
+ yyerror(& @1, state, "invalid clip plane selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+statePointItem: POINT_TOK statePointProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = $2;
+ }
+ ;
+
+statePointProperty: SIZE_TOK
+ {
+ $$ = STATE_POINT_SIZE;
+ }
+ | ATTENUATION
+ {
+ $$ = STATE_POINT_ATTENUATION;
+ }
+ ;
+
+stateMatrixRow: stateMatrixItem ROW '[' stateMatrixRowNum ']'
+ {
+ $$[0] = $1[0];
+ $$[1] = $1[1];
+ $$[2] = $4;
+ $$[3] = $4;
+ $$[4] = $1[2];
+ }
+ ;
+
+stateMatrixRows: stateMatrixItem optMatrixRows
+ {
+ $$[0] = $1[0];
+ $$[1] = $1[1];
+ $$[2] = $2[2];
+ $$[3] = $2[3];
+ $$[4] = $1[2];
+ }
+ ;
+
+optMatrixRows:
+ {
+ $$[2] = 0;
+ $$[3] = 3;
+ }
+ | ROW '[' stateMatrixRowNum DOT_DOT stateMatrixRowNum ']'
+ {
+ /* It seems logical that the matrix row range specifier would have
+ * to specify a range or more than one row (i.e., $5 > $3).
+ * However, the ARB_vertex_program spec says "a program will fail
+ * to load if <a> is greater than <b>." This means that $3 == $5
+ * is valid.
+ */
+ if ($3 > $5) {
+ yyerror(& @3, state, "invalid matrix row range");
+ YYERROR;
+ }
+
+ $$[2] = $3;
+ $$[3] = $5;
+ }
+ ;
+
+stateMatrixItem: MATRIX stateMatrixName stateOptMatModifier
+ {
+ $$[0] = $2[0];
+ $$[1] = $2[1];
+ $$[2] = $3;
+ }
+ ;
+
+stateOptMatModifier:
+ {
+ $$ = 0;
+ }
+ | stateMatModifier
+ {
+ $$ = $1;
+ }
+ ;
+
+stateMatModifier: INVERSE
+ {
+ $$ = STATE_MATRIX_INVERSE;
+ }
+ | TRANSPOSE
+ {
+ $$ = STATE_MATRIX_TRANSPOSE;
+ }
+ | INVTRANS
+ {
+ $$ = STATE_MATRIX_INVTRANS;
+ }
+ ;
+
+stateMatrixRowNum: INTEGER
+ {
+ if ($1 > 3) {
+ yyerror(& @1, state, "invalid matrix row reference");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+stateMatrixName: MODELVIEW stateOptModMatNum
+ {
+ $$[0] = STATE_MODELVIEW_MATRIX;
+ $$[1] = $2;
+ }
+ | PROJECTION
+ {
+ $$[0] = STATE_PROJECTION_MATRIX;
+ $$[1] = 0;
+ }
+ | MVP
+ {
+ $$[0] = STATE_MVP_MATRIX;
+ $$[1] = 0;
+ }
+ | TEXTURE optTexCoordUnitNum
+ {
+ $$[0] = STATE_TEXTURE_MATRIX;
+ $$[1] = $2;
+ }
+ | PALETTE '[' statePaletteMatNum ']'
+ {
+ yyerror(& @1, state, "GL_ARB_matrix_palette not supported");
+ YYERROR;
+ }
+ | MAT_PROGRAM '[' stateProgramMatNum ']'
+ {
+ $$[0] = STATE_PROGRAM_MATRIX;
+ $$[1] = $3;
+ }
+ ;
+
+stateOptModMatNum:
+ {
+ $$ = 0;
+ }
+ | '[' stateModMatNum ']'
+ {
+ $$ = $2;
+ }
+ ;
+stateModMatNum: INTEGER
+ {
+ /* Since GL_ARB_vertex_blend isn't supported, only modelview matrix
+ * zero is valid.
+ */
+ if ($1 != 0) {
+ yyerror(& @1, state, "invalid modelview matrix index");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+statePaletteMatNum: INTEGER
+ {
+ /* Since GL_ARB_matrix_palette isn't supported, just let any value
+ * through here. The error will be generated later.
+ */
+ $$ = $1;
+ }
+ ;
+stateProgramMatNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxProgramMatrices) {
+ yyerror(& @1, state, "invalid program matrix selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+stateDepthItem: DEPTH RANGE
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_DEPTH_RANGE;
+ }
+ ;
+
+
+programSingleItem: progEnvParam | progLocalParam;
+
+programMultipleItem: progEnvParams | progLocalParams;
+
+progEnvParams: PROGRAM ENV '[' progEnvParamNums ']'
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = state->state_param_enum;
+ $$[1] = STATE_ENV;
+ $$[2] = $4[0];
+ $$[3] = $4[1];
+ }
+ ;
+
+progEnvParamNums: progEnvParamNum
+ {
+ $$[0] = $1;
+ $$[1] = $1;
+ }
+ | progEnvParamNum DOT_DOT progEnvParamNum
+ {
+ $$[0] = $1;
+ $$[1] = $3;
+ }
+ ;
+
+progEnvParam: PROGRAM ENV '[' progEnvParamNum ']'
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = state->state_param_enum;
+ $$[1] = STATE_ENV;
+ $$[2] = $4;
+ $$[3] = $4;
+ }
+ ;
+
+progLocalParams: PROGRAM LOCAL '[' progLocalParamNums ']'
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = state->state_param_enum;
+ $$[1] = STATE_LOCAL;
+ $$[2] = $4[0];
+ $$[3] = $4[1];
+ }
+
+progLocalParamNums: progLocalParamNum
+ {
+ $$[0] = $1;
+ $$[1] = $1;
+ }
+ | progLocalParamNum DOT_DOT progLocalParamNum
+ {
+ $$[0] = $1;
+ $$[1] = $3;
+ }
+ ;
+
+progLocalParam: PROGRAM LOCAL '[' progLocalParamNum ']'
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = state->state_param_enum;
+ $$[1] = STATE_LOCAL;
+ $$[2] = $4;
+ $$[3] = $4;
+ }
+ ;
+
+progEnvParamNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->limits->MaxEnvParams) {
+ yyerror(& @1, state, "invalid environment parameter reference");
+ YYERROR;
+ }
+ $$ = $1;
+ }
+ ;
+
+progLocalParamNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->limits->MaxLocalParams) {
+ yyerror(& @1, state, "invalid local parameter reference");
+ YYERROR;
+ }
+ $$ = $1;
+ }
+ ;
+
+
+
+paramConstDecl: paramConstScalarDecl | paramConstVector;
+paramConstUse: paramConstScalarUse | paramConstVector;
+
+paramConstScalarDecl: signedFloatConstant
+ {
+ $$.count = 4;
+ $$.data[0] = $1;
+ $$.data[1] = $1;
+ $$.data[2] = $1;
+ $$.data[3] = $1;
+ }
+ ;
+
+paramConstScalarUse: REAL
+ {
+ $$.count = 1;
+ $$.data[0] = $1;
+ $$.data[1] = $1;
+ $$.data[2] = $1;
+ $$.data[3] = $1;
+ }
+ | INTEGER
+ {
+ $$.count = 1;
+ $$.data[0] = (float) $1;
+ $$.data[1] = (float) $1;
+ $$.data[2] = (float) $1;
+ $$.data[3] = (float) $1;
+ }
+ ;
+
+paramConstVector: '{' signedFloatConstant '}'
+ {
+ $$.count = 4;
+ $$.data[0] = $2;
+ $$.data[1] = 0.0f;
+ $$.data[2] = 0.0f;
+ $$.data[3] = 1.0f;
+ }
+ | '{' signedFloatConstant ',' signedFloatConstant '}'
+ {
+ $$.count = 4;
+ $$.data[0] = $2;
+ $$.data[1] = $4;
+ $$.data[2] = 0.0f;
+ $$.data[3] = 1.0f;
+ }
+ | '{' signedFloatConstant ',' signedFloatConstant ','
+ signedFloatConstant '}'
+ {
+ $$.count = 4;
+ $$.data[0] = $2;
+ $$.data[1] = $4;
+ $$.data[2] = $6;
+ $$.data[3] = 1.0f;
+ }
+ | '{' signedFloatConstant ',' signedFloatConstant ','
+ signedFloatConstant ',' signedFloatConstant '}'
+ {
+ $$.count = 4;
+ $$.data[0] = $2;
+ $$.data[1] = $4;
+ $$.data[2] = $6;
+ $$.data[3] = $8;
+ }
+ ;
+
+signedFloatConstant: optionalSign REAL
+ {
+ $$ = ($1) ? -$2 : $2;
+ }
+ | optionalSign INTEGER
+ {
+ $$ = (float)(($1) ? -$2 : $2);
+ }
+ ;
+
+optionalSign: '+' { $$ = FALSE; }
+ | '-' { $$ = TRUE; }
+ | { $$ = FALSE; }
+ ;
+
+TEMP_statement: TEMP { $<integer>$ = $1; } varNameList
+ ;
+
+ADDRESS_statement: ADDRESS { $<integer>$ = $1; } varNameList
+ ;
+
+varNameList: varNameList ',' IDENTIFIER
+ {
+ if (!declare_variable(state, $3, $<integer>0, & @3)) {
+ YYERROR;
+ }
+ }
+ | IDENTIFIER
+ {
+ if (!declare_variable(state, $1, $<integer>0, & @1)) {
+ YYERROR;
+ }
+ }
+ ;
+
+OUTPUT_statement: OUTPUT IDENTIFIER '=' resultBinding
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, $2, at_output, & @2);
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->output_binding = $4;
+ }
+ }
+ ;
+
+resultBinding: RESULT POSITION
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_HPOS;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | RESULT FOGCOORD
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_FOGC;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | RESULT resultColBinding
+ {
+ $$ = $2;
+ }
+ | RESULT POINTSIZE
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_PSIZ;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | RESULT TEXCOORD optTexCoordUnitNum
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_TEX0 + $3;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | RESULT DEPTH
+ {
+ if (state->mode == ARB_fragment) {
+ $$ = FRAG_RESULT_DEPTH;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ ;
+
+resultColBinding: COLOR optResultFaceType optResultColorType
+ {
+ $$ = $2 + $3;
+ }
+ ;
+
+optResultFaceType:
+ {
+ $$ = (state->mode == ARB_vertex)
+ ? VERT_RESULT_COL0
+ : FRAG_RESULT_COLOR;
+ }
+ | FRONT
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_COL0;
+ } else {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | BACK
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_BFC0;
+ } else {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ ;
+
+optResultColorType:
+ {
+ $$ = 0;
+ }
+ | PRIMARY
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = 0;
+ } else {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | SECONDARY
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = 1;
+ } else {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ ;
+
+optFaceType: { $$ = 0; }
+ | FRONT { $$ = 0; }
+ | BACK { $$ = 1; }
+ ;
+
+optColorType: { $$ = 0; }
+ | PRIMARY { $$ = 0; }
+ | SECONDARY { $$ = 1; }
+ ;
+
+optTexCoordUnitNum: { $$ = 0; }
+ | '[' texCoordUnitNum ']' { $$ = $2; }
+ ;
+
+optTexImageUnitNum: { $$ = 0; }
+ | '[' texImageUnitNum ']' { $$ = $2; }
+ ;
+
+optLegacyTexUnitNum: { $$ = 0; }
+ | '[' legacyTexUnitNum ']' { $$ = $2; }
+ ;
+
+texCoordUnitNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxTextureCoordUnits) {
+ yyerror(& @1, state, "invalid texture coordinate unit selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+texImageUnitNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxTextureImageUnits) {
+ yyerror(& @1, state, "invalid texture image unit selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+legacyTexUnitNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxTextureUnits) {
+ yyerror(& @1, state, "invalid texture unit selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+ALIAS_statement: ALIAS IDENTIFIER '=' IDENTIFIER
+ {
+ struct asm_symbol *exist = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $2);
+ struct asm_symbol *target = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $4);
+
+
+ if (exist != NULL) {
+ yyerror(& @2, state, "redeclared identifier");
+ YYERROR;
+ } else if (target == NULL) {
+ yyerror(& @4, state,
+ "undefined variable binding in ALIAS statement");
+ YYERROR;
+ } else {
+ _mesa_symbol_table_add_symbol(state->st, 0, $2, target);
+ }
+ }
+ ;
+
+%%
+
+struct asm_instruction *
+asm_instruction_ctor(gl_inst_opcode op,
+ const struct prog_dst_register *dst,
+ const struct asm_src_register *src0,
+ const struct asm_src_register *src1,
+ const struct asm_src_register *src2)
+{
+ struct asm_instruction *inst = calloc(1, sizeof(struct asm_instruction));
+
+ if (inst) {
+ _mesa_init_instructions(& inst->Base, 1);
+ inst->Base.Opcode = op;
+
+ /* In the core ARB extensions only the KIL instruction doesn't have a
+ * destination register.
+ */
+ if (dst == NULL) {
+ init_dst_reg(& inst->Base.DstReg);
+ } else {
+ inst->Base.DstReg = *dst;
+ }
+
+ inst->Base.SrcReg[0] = src0->Base;
+ inst->SrcReg[0] = *src0;
+
+ if (src1 != NULL) {
+ inst->Base.SrcReg[1] = src1->Base;
+ inst->SrcReg[1] = *src1;
+ } else {
+ init_src_reg(& inst->SrcReg[1]);
+ }
+
+ if (src2 != NULL) {
+ inst->Base.SrcReg[2] = src2->Base;
+ inst->SrcReg[2] = *src2;
+ } else {
+ init_src_reg(& inst->SrcReg[2]);
+ }
+ }
+
+ return inst;
+}
+
+
+void
+init_dst_reg(struct prog_dst_register *r)
+{
+ memset(r, 0, sizeof(*r));
+ r->File = PROGRAM_UNDEFINED;
+ r->WriteMask = WRITEMASK_XYZW;
+ r->CondMask = COND_TR;
+ r->CondSwizzle = SWIZZLE_NOOP;
+}
+
+
+void
+init_src_reg(struct asm_src_register *r)
+{
+ memset(r, 0, sizeof(*r));
+ r->Base.File = PROGRAM_UNDEFINED;
+ r->Base.Swizzle = SWIZZLE_NOOP;
+ r->Symbol = NULL;
+}
+
+
+/**
+ * Validate the set of inputs used by a program
+ *
+ * Validates that legal sets of inputs are used by the program. In this case
+ * "used" included both reading the input or binding the input to a name using
+ * the \c ATTRIB command.
+ *
+ * \return
+ * \c TRUE if the combination of inputs used is valid, \c FALSE otherwise.
+ */
+int
+validate_inputs(struct YYLTYPE *locp, struct asm_parser_state *state)
+{
+ const int inputs = state->prog->InputsRead | state->InputsBound;
+
+ if (((inputs & 0x0ffff) & (inputs >> 16)) != 0) {
+ yyerror(locp, state, "illegal use of generic attribute and name attribute");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+struct asm_symbol *
+declare_variable(struct asm_parser_state *state, char *name, enum asm_type t,
+ struct YYLTYPE *locp)
+{
+ struct asm_symbol *s = NULL;
+ struct asm_symbol *exist = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, name);
+
+
+ if (exist != NULL) {
+ yyerror(locp, state, "redeclared identifier");
+ } else {
+ s = calloc(1, sizeof(struct asm_symbol));
+ s->name = name;
+ s->type = t;
+
+ switch (t) {
+ case at_temp:
+ if (state->prog->NumTemporaries >= state->limits->MaxTemps) {
+ yyerror(locp, state, "too many temporaries declared");
+ free(s);
+ return NULL;
+ }
+
+ s->temp_binding = state->prog->NumTemporaries;
+ state->prog->NumTemporaries++;
+ break;
+
+ case at_address:
+ if (state->prog->NumAddressRegs >= state->limits->MaxAddressRegs) {
+ yyerror(locp, state, "too many address registers declared");
+ free(s);
+ return NULL;
+ }
+
+ /* FINISHME: Add support for multiple address registers.
+ */
+ state->prog->NumAddressRegs++;
+ break;
+
+ default:
+ break;
+ }
+
+ _mesa_symbol_table_add_symbol(state->st, 0, s->name, s);
+ s->next = state->sym;
+ state->sym = s;
+ }
+
+ return s;
+}
+
+
+int add_state_reference(struct gl_program_parameter_list *param_list,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ const GLuint size = 4; /* XXX fix */
+ char *name;
+ GLint index;
+
+ name = _mesa_program_state_string(tokens);
+ index = _mesa_add_parameter(param_list, PROGRAM_STATE_VAR, name,
+ size, GL_NONE, NULL, tokens, 0x0);
+ param_list->StateFlags |= _mesa_program_state_flags(tokens);
+
+ /* free name string here since we duplicated it in add_parameter() */
+ _mesa_free(name);
+
+ return index;
+}
+
+
+int
+initialize_symbol_from_state(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ int idx = -1;
+ gl_state_index state_tokens[STATE_LENGTH];
+
+
+ memcpy(state_tokens, tokens, sizeof(state_tokens));
+
+ param_var->type = at_param;
+ param_var->param_binding_type = PROGRAM_STATE_VAR;
+
+ /* If we are adding a STATE_MATRIX that has multiple rows, we need to
+ * unroll it and call add_state_reference() for each row
+ */
+ if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
+ state_tokens[0] == STATE_PROJECTION_MATRIX ||
+ state_tokens[0] == STATE_MVP_MATRIX ||
+ state_tokens[0] == STATE_TEXTURE_MATRIX ||
+ state_tokens[0] == STATE_PROGRAM_MATRIX)
+ && (state_tokens[2] != state_tokens[3])) {
+ int row;
+ const int first_row = state_tokens[2];
+ const int last_row = state_tokens[3];
+
+ for (row = first_row; row <= last_row; row++) {
+ state_tokens[2] = state_tokens[3] = row;
+
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+ }
+ else {
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+
+ return idx;
+}
+
+
+int
+initialize_symbol_from_param(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ int idx = -1;
+ gl_state_index state_tokens[STATE_LENGTH];
+
+
+ memcpy(state_tokens, tokens, sizeof(state_tokens));
+
+ assert((state_tokens[0] == STATE_VERTEX_PROGRAM)
+ || (state_tokens[0] == STATE_FRAGMENT_PROGRAM));
+ assert((state_tokens[1] == STATE_ENV)
+ || (state_tokens[1] == STATE_LOCAL));
+
+ param_var->type = at_param;
+ param_var->param_binding_type = (state_tokens[1] == STATE_ENV)
+ ? PROGRAM_ENV_PARAM : PROGRAM_LOCAL_PARAM;
+
+ /* If we are adding a STATE_ENV or STATE_LOCAL that has multiple elements,
+ * we need to unroll it and call add_state_reference() for each row
+ */
+ if (state_tokens[2] != state_tokens[3]) {
+ int row;
+ const int first_row = state_tokens[2];
+ const int last_row = state_tokens[3];
+
+ for (row = first_row; row <= last_row; row++) {
+ state_tokens[2] = state_tokens[3] = row;
+
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+ }
+ else {
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+
+ return idx;
+}
+
+
+int
+initialize_symbol_from_const(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const struct asm_vector *vec)
+{
+ const int idx = _mesa_add_parameter(prog->Parameters, PROGRAM_CONSTANT,
+ NULL, vec->count, GL_NONE, vec->data,
+ NULL, 0x0);
+
+ param_var->type = at_param;
+ param_var->param_binding_type = PROGRAM_CONSTANT;
+
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+
+ return idx;
+}
+
+
+char *
+make_error_string(const char *fmt, ...)
+{
+ int length;
+ char *str;
+ va_list args;
+
+ va_start(args, fmt);
+
+ /* Call vsnprintf once to determine how large the final string is. Call it
+ * again to do the actual formatting. from the vsnprintf manual page:
+ *
+ * Upon successful return, these functions return the number of
+ * characters printed (not including the trailing '\0' used to end
+ * output to strings).
+ */
+ length = 1 + vsnprintf(NULL, 0, fmt, args);
+
+ str = _mesa_malloc(length);
+ if (str) {
+ vsnprintf(str, length, fmt, args);
+ }
+
+ va_end(args);
+
+ return str;
+}
+
+
+void
+yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
+{
+ char *err_str;
+
+
+ err_str = make_error_string("glProgramStringARB(%s)\n", s);
+ if (err_str) {
+ _mesa_error(state->ctx, GL_INVALID_OPERATION, err_str);
+ _mesa_free(err_str);
+ }
+
+ err_str = make_error_string("line %u, char %u: error: %s\n",
+ locp->first_line, locp->first_column, s);
+ _mesa_set_program_error(state->ctx, locp->position, err_str);
+
+ if (err_str) {
+ _mesa_free(err_str);
+ }
+}
+
+
+GLboolean
+_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str,
+ GLsizei len, struct asm_parser_state *state)
+{
+ struct asm_instruction *inst;
+ unsigned i;
+ GLubyte *strz;
+ GLboolean result = GL_FALSE;
+ void *temp;
+ struct asm_symbol *sym;
+
+ state->ctx = ctx;
+ state->prog->Target = target;
+ state->prog->Parameters = _mesa_new_parameter_list();
+
+ /* Make a copy of the program string and force it to be NUL-terminated.
+ */
+ strz = (GLubyte *) _mesa_malloc(len + 1);
+ if (strz == NULL) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
+ return GL_FALSE;
+ }
+ _mesa_memcpy (strz, str, len);
+ strz[len] = '\0';
+
+ state->prog->String = strz;
+
+ state->st = _mesa_symbol_table_ctor();
+
+ state->limits = (target == GL_VERTEX_PROGRAM_ARB)
+ ? & ctx->Const.VertexProgram
+ : & ctx->Const.FragmentProgram;
+
+ state->MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
+ state->MaxTextureCoordUnits = ctx->Const.MaxTextureCoordUnits;
+ state->MaxTextureUnits = ctx->Const.MaxTextureUnits;
+ state->MaxClipPlanes = ctx->Const.MaxClipPlanes;
+ state->MaxLights = ctx->Const.MaxLights;
+ state->MaxProgramMatrices = ctx->Const.MaxProgramMatrices;
+
+ state->state_param_enum = (target == GL_VERTEX_PROGRAM_ARB)
+ ? STATE_VERTEX_PROGRAM : STATE_FRAGMENT_PROGRAM;
+
+ _mesa_set_program_error(ctx, -1, NULL);
+
+ _mesa_program_lexer_ctor(& state->scanner, state, (const char *) str, len);
+ yyparse(state);
+ _mesa_program_lexer_dtor(state->scanner);
+
+
+ if (ctx->Program.ErrorPos != -1) {
+ goto error;
+ }
+
+ if (! _mesa_layout_parameters(state)) {
+ struct YYLTYPE loc;
+
+ loc.first_line = 0;
+ loc.first_column = 0;
+ loc.position = len;
+
+ yyerror(& loc, state, "invalid PARAM usage");
+ goto error;
+ }
+
+
+
+ /* Add one instruction to store the "END" instruction.
+ */
+ state->prog->Instructions =
+ _mesa_alloc_instructions(state->prog->NumInstructions + 1);
+ inst = state->inst_head;
+ for (i = 0; i < state->prog->NumInstructions; i++) {
+ struct asm_instruction *const temp = inst->next;
+
+ state->prog->Instructions[i] = inst->Base;
+ inst = temp;
+ }
+
+ /* Finally, tag on an OPCODE_END instruction */
+ {
+ const GLuint numInst = state->prog->NumInstructions;
+ _mesa_init_instructions(state->prog->Instructions + numInst, 1);
+ state->prog->Instructions[numInst].Opcode = OPCODE_END;
+ }
+ state->prog->NumInstructions++;
+
+ state->prog->NumParameters = state->prog->Parameters->NumParameters;
+ state->prog->NumAttributes = _mesa_bitcount(state->prog->InputsRead);
+
+ /*
+ * Initialize native counts to logical counts. The device driver may
+ * change them if program is translated into a hardware program.
+ */
+ state->prog->NumNativeInstructions = state->prog->NumInstructions;
+ state->prog->NumNativeTemporaries = state->prog->NumTemporaries;
+ state->prog->NumNativeParameters = state->prog->NumParameters;
+ state->prog->NumNativeAttributes = state->prog->NumAttributes;
+ state->prog->NumNativeAddressRegs = state->prog->NumAddressRegs;
+
+ result = GL_TRUE;
+
+error:
+ for (inst = state->inst_head; inst != NULL; inst = temp) {
+ temp = inst->next;
+ _mesa_free(inst);
+ }
+
+ state->inst_head = NULL;
+ state->inst_tail = NULL;
+
+ for (sym = state->sym; sym != NULL; sym = temp) {
+ temp = sym->next;
+
+ _mesa_free((void *) sym->name);
+ _mesa_free(sym);
+ }
+ state->sym = NULL;
+
+ _mesa_symbol_table_dtor(state->st);
+ state->st = NULL;
+
+ return result;
+}
diff --git a/src/mesa/shader/program_parse_extra.c b/src/mesa/shader/program_parse_extra.c
new file mode 100644
index 0000000000..8e4be606f1
--- /dev/null
+++ b/src/mesa/shader/program_parse_extra.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <string.h>
+#include "main/mtypes.h"
+#include "prog_instruction.h"
+#include "program_parser.h"
+
+
+/**
+ * Extra assembly-level parser routines
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+int
+_mesa_ARBvp_parse_option(struct asm_parser_state *state, const char *option)
+{
+ if (strcmp(option, "ARB_position_invariant") == 0) {
+ state->option.PositionInvariant = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int
+_mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option)
+{
+ /* All of the options currently supported start with "ARB_". The code is
+ * currently structured with nested if-statements because eventually options
+ * that start with "NV_" will be supported. This structure will result in
+ * less churn when those options are added.
+ */
+ if (strncmp(option, "ARB_", 4) == 0) {
+ /* Advance the pointer past the "ARB_" prefix.
+ */
+ option += 4;
+
+
+ if (strncmp(option, "fog_", 4) == 0) {
+ option += 4;
+
+ if (state->option.Fog == OPTION_NONE) {
+ if (strcmp(option, "exp") == 0) {
+ state->option.Fog = OPTION_FOG_EXP;
+ return 1;
+ } else if (strcmp(option, "exp2") == 0) {
+ state->option.Fog = OPTION_FOG_EXP2;
+ return 1;
+ } else if (strcmp(option, "linear") == 0) {
+ state->option.Fog = OPTION_FOG_LINEAR;
+ return 1;
+ }
+ }
+
+ return 0;
+ } else if (strncmp(option, "precision_hint_", 15) == 0) {
+ option += 15;
+
+ if (state->option.PrecisionHint == OPTION_NONE) {
+ if (strcmp(option, "nicest") == 0) {
+ state->option.PrecisionHint = OPTION_NICEST;
+ return 1;
+ } else if (strcmp(option, "fastest") == 0) {
+ state->option.PrecisionHint = OPTION_FASTEST;
+ return 1;
+ }
+ }
+
+ return 0;
+ } else if (strcmp(option, "draw_buffers") == 0) {
+ /* Don't need to check extension availability because all Mesa-based
+ * drivers support GL_ARB_draw_buffers.
+ */
+ state->option.DrawBuffers = 1;
+ return 1;
+ } else if (strcmp(option, "fragment_program_shadow") == 0) {
+ if (state->ctx->Extensions.ARB_fragment_program_shadow) {
+ state->option.Shadow = 1;
+ return 1;
+ }
+ }
+ } else if (strncmp(option, "MESA_", 5) == 0) {
+ option += 5;
+
+ if (strcmp(option, "texture_array") == 0) {
+ if (state->ctx->Extensions.MESA_texture_array) {
+ state->option.TexArray = 1;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/src/mesa/shader/program_parser.h b/src/mesa/shader/program_parser.h
new file mode 100644
index 0000000000..fa47d84565
--- /dev/null
+++ b/src/mesa/shader/program_parser.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include "main/config.h"
+
+#ifndef MTYPES_H
+struct __GLcontextRec;
+typedef struct __GLcontextRec GLcontext;
+#endif
+
+enum asm_type {
+ at_none,
+ at_address,
+ at_attrib,
+ at_param,
+ at_temp,
+ at_output,
+};
+
+struct asm_symbol {
+ struct asm_symbol *next; /**< List linkage for freeing. */
+ const char *name;
+ enum asm_type type;
+ unsigned attrib_binding;
+ unsigned output_binding; /**< Output / result register number. */
+
+ /**
+ * One of PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM, or PROGRAM_ENV_PARAM.
+ */
+ unsigned param_binding_type;
+
+ /**
+ * Offset into the program_parameter_list where the tokens representing our
+ * bound state (or constants) start.
+ */
+ unsigned param_binding_begin;
+
+ /* This is how many entries in the the program_parameter_list we take up
+ * with our state tokens or constants. Note that this is _not_ the same as
+ * the number of param registers we eventually use.
+ */
+ unsigned param_binding_length;
+
+ /**
+ * Index of the temp register assigned to this variable.
+ */
+ unsigned temp_binding;
+
+ /**
+ * Flag whether or not a PARAM is an array
+ */
+ unsigned param_is_array:1;
+
+
+ /**
+ * Flag whether or not a PARAM array is accessed indirectly
+ */
+ unsigned param_accessed_indirectly:1;
+
+
+ /**
+ * \brief Is first pass of parameter layout done with this variable?
+ *
+ * The parameter layout routine operates in two passes. This flag tracks
+ * whether or not the first pass has handled this variable.
+ *
+ * \sa _mesa_layout_parameters
+ */
+ unsigned pass1_done:1;
+};
+
+
+struct asm_vector {
+ unsigned count;
+ float data[4];
+};
+
+
+struct asm_swizzle_mask {
+ unsigned swizzle:12;
+ unsigned mask:4;
+};
+
+
+struct asm_src_register {
+ struct prog_src_register Base;
+
+ /**
+ * Symbol associated with indirect access to parameter arrays.
+ *
+ * If \c Base::RelAddr is 1, this will point to the symbol for the parameter
+ * that is being dereferenced. Further, \c Base::Index will be the offset
+ * from the address register being used.
+ */
+ struct asm_symbol *Symbol;
+};
+
+
+struct asm_instruction {
+ struct prog_instruction Base;
+ struct asm_instruction *next;
+ struct asm_src_register SrcReg[3];
+};
+
+
+struct asm_parser_state {
+ GLcontext *ctx;
+ struct gl_program *prog;
+
+ /**
+ * Per-program target limits
+ */
+ struct gl_program_constants *limits;
+
+ struct _mesa_symbol_table *st;
+
+ /**
+ * Linked list of symbols
+ *
+ * This list is \b only used when cleaning up compiler state and freeing
+ * memory.
+ */
+ struct asm_symbol *sym;
+
+ /**
+ * State for the lexer.
+ */
+ void *scanner;
+
+ /**
+ * Linked list of instructions generated during parsing.
+ */
+ /*@{*/
+ struct asm_instruction *inst_head;
+ struct asm_instruction *inst_tail;
+ /*@}*/
+
+
+ /**
+ * Selected limits copied from gl_constants
+ *
+ * These are limits from the GL context, but various bits in the program
+ * must be validated against these values.
+ */
+ /*@{*/
+ unsigned MaxTextureCoordUnits;
+ unsigned MaxTextureImageUnits;
+ unsigned MaxTextureUnits;
+ unsigned MaxClipPlanes;
+ unsigned MaxLights;
+ unsigned MaxProgramMatrices;
+ /*@}*/
+
+ /**
+ * Value to use in state vector accessors for environment and local
+ * parameters
+ */
+ unsigned state_param_enum;
+
+
+ /**
+ * Input attributes bound to specific names
+ *
+ * This is only needed so that errors can be properly produced when
+ * multiple ATTRIB statements bind illegal combinations of vertex
+ * attributes.
+ */
+ unsigned InputsBound;
+
+ enum {
+ invalid_mode = 0,
+ ARB_vertex,
+ ARB_fragment
+ } mode;
+
+ struct {
+ unsigned PositionInvariant:1;
+ unsigned Fog:2;
+ unsigned PrecisionHint:2;
+ unsigned DrawBuffers:1;
+ unsigned Shadow:1;
+ unsigned TexRect:1;
+ unsigned TexArray:1;
+ } option;
+
+ struct {
+ unsigned UsesKill:1;
+ } fragment;
+};
+
+#define OPTION_NONE 0
+#define OPTION_FOG_EXP 1
+#define OPTION_FOG_EXP2 2
+#define OPTION_FOG_LINEAR 3
+#define OPTION_NICEST 1
+#define OPTION_FASTEST 2
+
+typedef struct YYLTYPE {
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ int position;
+} YYLTYPE;
+
+#define YYLTYPE_IS_DECLARED 1
+#define YYLTYPE_IS_TRIVIAL 1
+
+
+extern GLboolean _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
+ const GLubyte *str, GLsizei len, struct asm_parser_state *state);
+
+
+
+/* From program_lexer.l. */
+extern void _mesa_program_lexer_dtor(void *scanner);
+
+extern void _mesa_program_lexer_ctor(void **scanner,
+ struct asm_parser_state *state, const char *string, size_t len);
+
+
+/**
+ *\name From program_parse_extra.c
+ */
+/*@{*/
+
+/**
+ * Parses and processes an option string to an ARB vertex program
+ *
+ * \return
+ * Non-zero on success, zero on failure.
+ */
+extern int _mesa_ARBvp_parse_option(struct asm_parser_state *state,
+ const char *option);
+
+/**
+ * Parses and processes an option string to an ARB fragment program
+ *
+ * \return
+ * Non-zero on success, zero on failure.
+ */
+extern int _mesa_ARBfp_parse_option(struct asm_parser_state *state,
+ const char *option);
+
+/*@}*/
diff --git a/src/mesa/shader/programopt.c b/src/mesa/shader/programopt.c
index 56f1eb832e..f70c75cec8 100644
--- a/src/mesa/shader/programopt.c
+++ b/src/mesa/shader/programopt.c
@@ -45,8 +45,8 @@
* into a vertex program.
* May be used to implement the position_invariant option.
*/
-void
-_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog)
+static void
+_mesa_insert_mvp_dp4_code(GLcontext *ctx, struct gl_vertex_program *vprog)
{
struct prog_instruction *newInst;
const GLuint origLen = vprog->Base.NumInstructions;
@@ -113,6 +113,121 @@ _mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog)
}
+static void
+_mesa_insert_mvp_mad_code(GLcontext *ctx, struct gl_vertex_program *vprog)
+{
+ struct prog_instruction *newInst;
+ const GLuint origLen = vprog->Base.NumInstructions;
+ const GLuint newLen = origLen + 4;
+ GLuint hposTemp;
+ GLuint i;
+
+ /*
+ * Setup state references for the modelview/projection matrix.
+ * XXX we should check if these state vars are already declared.
+ */
+ static const gl_state_index mvpState[4][STATE_LENGTH] = {
+ { STATE_MVP_MATRIX, 0, 0, 0, STATE_MATRIX_TRANSPOSE },
+ { STATE_MVP_MATRIX, 0, 1, 1, STATE_MATRIX_TRANSPOSE },
+ { STATE_MVP_MATRIX, 0, 2, 2, STATE_MATRIX_TRANSPOSE },
+ { STATE_MVP_MATRIX, 0, 3, 3, STATE_MATRIX_TRANSPOSE },
+ };
+ GLint mvpRef[4];
+
+ for (i = 0; i < 4; i++) {
+ mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters,
+ mvpState[i]);
+ }
+
+ /* Alloc storage for new instructions */
+ newInst = _mesa_alloc_instructions(newLen);
+ if (!newInst) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glProgramString(inserting position_invariant code)");
+ return;
+ }
+
+ /* TEMP hposTemp; */
+ hposTemp = vprog->Base.NumTemporaries++;
+
+ /*
+ * Generated instructions:
+ * emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]);
+ * emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp);
+ * emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp);
+ * emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp);
+ */
+ _mesa_init_instructions(newInst, 4);
+
+ newInst[0].Opcode = OPCODE_MUL;
+ newInst[0].DstReg.File = PROGRAM_TEMPORARY;
+ newInst[0].DstReg.Index = hposTemp;
+ newInst[0].DstReg.WriteMask = WRITEMASK_XYZW;
+ newInst[0].SrcReg[0].File = PROGRAM_INPUT;
+ newInst[0].SrcReg[0].Index = VERT_ATTRIB_POS;
+ newInst[0].SrcReg[0].Swizzle = SWIZZLE_XXXX;
+ newInst[0].SrcReg[1].File = PROGRAM_STATE_VAR;
+ newInst[0].SrcReg[1].Index = mvpRef[0];
+ newInst[0].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+
+ for (i = 1; i <= 2; i++) {
+ newInst[i].Opcode = OPCODE_MAD;
+ newInst[i].DstReg.File = PROGRAM_TEMPORARY;
+ newInst[i].DstReg.Index = hposTemp;
+ newInst[i].DstReg.WriteMask = WRITEMASK_XYZW;
+ newInst[i].SrcReg[0].File = PROGRAM_INPUT;
+ newInst[i].SrcReg[0].Index = VERT_ATTRIB_POS;
+ newInst[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(i,i,i,i);
+ newInst[i].SrcReg[1].File = PROGRAM_STATE_VAR;
+ newInst[i].SrcReg[1].Index = mvpRef[i];
+ newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+ newInst[i].SrcReg[2].File = PROGRAM_TEMPORARY;
+ newInst[i].SrcReg[2].Index = hposTemp;
+ newInst[1].SrcReg[2].Swizzle = SWIZZLE_NOOP;
+ }
+
+ newInst[3].Opcode = OPCODE_MAD;
+ newInst[3].DstReg.File = PROGRAM_OUTPUT;
+ newInst[3].DstReg.Index = VERT_RESULT_HPOS;
+ newInst[3].DstReg.WriteMask = WRITEMASK_XYZW;
+ newInst[3].SrcReg[0].File = PROGRAM_INPUT;
+ newInst[3].SrcReg[0].Index = VERT_ATTRIB_POS;
+ newInst[3].SrcReg[0].Swizzle = SWIZZLE_WWWW;
+ newInst[3].SrcReg[1].File = PROGRAM_STATE_VAR;
+ newInst[3].SrcReg[1].Index = mvpRef[3];
+ newInst[3].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+ newInst[3].SrcReg[2].File = PROGRAM_TEMPORARY;
+ newInst[3].SrcReg[2].Index = hposTemp;
+ newInst[3].SrcReg[2].Swizzle = SWIZZLE_NOOP;
+
+
+ /* Append original instructions after new instructions */
+ _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen);
+
+ /* free old instructions */
+ _mesa_free_instructions(vprog->Base.Instructions, origLen);
+
+ /* install new instructions */
+ vprog->Base.Instructions = newInst;
+ vprog->Base.NumInstructions = newLen;
+ vprog->Base.InputsRead |= VERT_BIT_POS;
+ vprog->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS);
+}
+
+
+void
+_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog)
+{
+ if (ctx->mvp_with_dp4)
+ _mesa_insert_mvp_dp4_code( ctx, vprog );
+ else
+ _mesa_insert_mvp_mad_code( ctx, vprog );
+}
+
+
+
+
+
/**
* Append extra instructions onto the given fragment program to implement
@@ -171,7 +286,7 @@ _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
if (inst->Opcode == OPCODE_END)
break;
if (inst->DstReg.File == PROGRAM_OUTPUT &&
- inst->DstReg.Index == FRAG_RESULT_COLR) {
+ inst->DstReg.Index == FRAG_RESULT_COLOR) {
/* change the instruction to write to colorTemp w/ clamping */
inst->DstReg.File = PROGRAM_TEMPORARY;
inst->DstReg.Index = colorTemp;
@@ -241,7 +356,7 @@ _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
inst->DstReg.WriteMask = WRITEMASK_X;
inst->SrcReg[0].File = PROGRAM_TEMPORARY;
inst->SrcReg[0].Index = fogFactorTemp;
- inst->SrcReg[0].NegateBase = NEGATE_XYZW;
+ inst->SrcReg[0].Negate = NEGATE_XYZW;
inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
inst->SaturateMode = SATURATE_ZERO_ONE;
inst++;
@@ -249,7 +364,7 @@ _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
/* LRP result.color.xyz, fogFactorTemp.xxxx, colorTemp, fogColorRef; */
inst->Opcode = OPCODE_LRP;
inst->DstReg.File = PROGRAM_OUTPUT;
- inst->DstReg.Index = FRAG_RESULT_COLR;
+ inst->DstReg.Index = FRAG_RESULT_COLOR;
inst->DstReg.WriteMask = WRITEMASK_XYZ;
inst->SrcReg[0].File = PROGRAM_TEMPORARY;
inst->SrcReg[0].Index = fogFactorTemp;
@@ -264,7 +379,7 @@ _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
/* MOV result.color.w, colorTemp.x; # copy alpha */
inst->Opcode = OPCODE_MOV;
inst->DstReg.File = PROGRAM_OUTPUT;
- inst->DstReg.Index = FRAG_RESULT_COLR;
+ inst->DstReg.Index = FRAG_RESULT_COLOR;
inst->DstReg.WriteMask = WRITEMASK_W;
inst->SrcReg[0].File = PROGRAM_TEMPORARY;
inst->SrcReg[0].Index = colorTemp;
@@ -375,7 +490,7 @@ _mesa_count_texture_instructions(struct gl_program *prog)
* So, rewrite the program to use a temporary register in this case.
*/
void
-_mesa_remove_output_reads(struct gl_program *prog, enum register_file type)
+_mesa_remove_output_reads(struct gl_program *prog, gl_register_file type)
{
GLuint i;
GLint outputMap[VERT_RESULT_MAX];
diff --git a/src/mesa/shader/programopt.h b/src/mesa/shader/programopt.h
index 11572e64f5..96acaf9566 100644
--- a/src/mesa/shader/programopt.h
+++ b/src/mesa/shader/programopt.h
@@ -40,6 +40,6 @@ extern void
_mesa_count_texture_instructions(struct gl_program *prog);
extern void
-_mesa_remove_output_reads(struct gl_program *prog, enum register_file type);
+_mesa_remove_output_reads(struct gl_program *prog, gl_register_file type);
#endif /* PROGRAMOPT_H */
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index b3d66c5bab..54a25dfaf0 100644
--- a/src/mesa/shader/shader_api.c
+++ b/src/mesa/shader/shader_api.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.2
+ * Version: 7.6
*
* Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -50,11 +51,6 @@
#include "glapi/dispatch.h"
-#ifndef GL_PROGRAM_BINARY_LENGTH_OES
-#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
-#endif
-
-
/**
* Allocate a new gl_shader_program object, initialize it.
*/
@@ -370,6 +366,31 @@ _mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
}
+/**
+ * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
+ */
+static GLbitfield
+get_shader_flags(void)
+{
+ GLbitfield flags = 0x0;
+ const char *env = _mesa_getenv("MESA_GLSL");
+
+ if (env) {
+ if (_mesa_strstr(env, "dump"))
+ flags |= GLSL_DUMP;
+ if (_mesa_strstr(env, "log"))
+ flags |= GLSL_LOG;
+ if (_mesa_strstr(env, "nopt"))
+ flags |= GLSL_NO_OPT;
+ else if (_mesa_strstr(env, "opt"))
+ flags |= GLSL_OPT;
+ if (_mesa_strstr(env, "uniform"))
+ flags |= GLSL_UNIFORMS;
+ }
+
+ return flags;
+}
+
/**
* Initialize context's shader state.
@@ -381,8 +402,16 @@ _mesa_init_shader_state(GLcontext * ctx)
* are generated by the GLSL compiler.
*/
ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
- ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
+ ctx->Shader.EmitContReturn = GL_TRUE;
+ ctx->Shader.EmitCondCodes = GL_FALSE;
ctx->Shader.EmitComments = GL_FALSE;
+ ctx->Shader.Flags = get_shader_flags();
+
+ /* Default pragma settings */
+ ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
+ ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
+ ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
+ ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
}
@@ -801,6 +830,27 @@ is_integer_type(GLenum type)
}
+static GLboolean
+is_sampler_type(GLenum type)
+{
+ switch (type) {
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_2D_RECT_ARB:
+ case GL_SAMPLER_2D_RECT_SHADOW_ARB:
+ case GL_SAMPLER_1D_ARRAY_EXT:
+ case GL_SAMPLER_2D_ARRAY_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
static void
_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
GLsizei maxLength, GLsizei *length, GLint *size,
@@ -835,7 +885,7 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
static struct gl_program_parameter *
get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
{
- const struct gl_program *prog;
+ const struct gl_program *prog = NULL;
GLint progPos;
progPos = shProg->Uniforms->Uniforms[index].VertPos;
@@ -865,7 +915,8 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
GLenum *type, GLchar *nameOut)
{
const struct gl_shader_program *shProg;
- const struct gl_program *prog;
+ const struct gl_program *prog = NULL;
+ const struct gl_program_parameter *param;
GLint progPos;
shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
@@ -891,14 +942,30 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
if (!prog || progPos < 0)
return; /* should never happen */
- if (nameOut)
- copy_string(nameOut, maxLength, length,
- prog->Parameters->Parameters[progPos].Name);
- if (size)
- *size = prog->Parameters->Parameters[progPos].Size
- / sizeof_glsl_type(prog->Parameters->Parameters[progPos].DataType);
- if (type)
- *type = prog->Parameters->Parameters[progPos].DataType;
+ ASSERT(progPos < prog->Parameters->NumParameters);
+ param = &prog->Parameters->Parameters[progPos];
+
+ if (nameOut) {
+ copy_string(nameOut, maxLength, length, param->Name);
+ }
+
+ if (size) {
+ GLint typeSize = sizeof_glsl_type(param->DataType);
+ if (param->Size > typeSize) {
+ /* This is an array.
+ * Array elements are placed on vector[4] boundaries so they're
+ * a multiple of four floats. We round typeSize up to next multiple
+ * of four to get the right size below.
+ */
+ typeSize = (typeSize + 3) & ~3;
+ }
+ /* Note that the returned size is in units of the <type>, not bytes */
+ *size = param->Size / typeSize;
+ }
+
+ if (type) {
+ *type = param->DataType;
+ }
}
@@ -1117,7 +1184,8 @@ get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
/**
* Determine the number of rows and columns occupied by a uniform
- * according to its datatype.
+ * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
+ * the number of rows = 1 and cols = number of elements in the vector.
*/
static void
get_uniform_rows_cols(const struct gl_program_parameter *p,
@@ -1126,33 +1194,45 @@ 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 */
- *rows = p->Size / 4 + 1;
- if (p->Size % 4 == 0)
- *cols = 4;
- else
- *cols = p->Size % 4;
+ if (p->Size <= 4) {
+ *rows = 1;
+ *cols = p->Size;
+ }
+ else {
+ *rows = p->Size / 4 + 1;
+ if (p->Size % 4 == 0)
+ *cols = 4;
+ else
+ *cols = p->Size % 4;
+ }
}
}
-#define MAX_UNIFORM_ELEMENTS 16
-
/**
- * Helper for GetUniformfv(), GetUniformiv()
- * Returns number of elements written to 'params' output.
+ * Helper for get_uniform[fi]v() functions.
+ * Given a shader program name and uniform location, return a pointer
+ * to the shader program and return the program parameter position.
*/
-static GLuint
-get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
- GLfloat *params)
+static void
+lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location,
+ struct gl_program **progOut, GLint *paramPosOut)
{
struct gl_shader_program *shProg
= _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
- if (shProg) {
- if (shProg->Uniforms &&
- location >= 0 && location < (GLint) shProg->Uniforms->NumUniforms) {
- GLint progPos;
- const struct gl_program *prog = NULL;
+ struct gl_program *prog = NULL;
+ GLint progPos = -1;
+ /* if shProg is NULL, we'll have already recorded an error */
+
+ if (shProg) {
+ if (!shProg->Uniforms ||
+ location < 0 ||
+ location >= (GLint) shProg->Uniforms->NumUniforms) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
+ }
+ else {
+ /* OK, find the gl_program and program parameter location */
progPos = shProg->Uniforms->Uniforms[location].VertPos;
if (progPos >= 0) {
prog = &shProg->VertexProgram->Base;
@@ -1163,33 +1243,11 @@ get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
prog = &shProg->FragmentProgram->Base;
}
}
-
- ASSERT(prog);
- if (prog) {
- const struct gl_program_parameter *p =
- &prog->Parameters->Parameters[progPos];
- GLint rows, cols, i, j, k;
-
- /* See uniformiv() below */
- assert(p->Size <= MAX_UNIFORM_ELEMENTS);
-
- get_uniform_rows_cols(p, &rows, &cols);
-
- k = 0;
- for (i = 0; i < rows; i++) {
- for (j = 0; j < cols; j++ ) {
- params[k++] = prog->Parameters->ParameterValues[progPos+i][j];
- }
- }
-
- return p->Size;
- }
- }
- else {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
}
}
- return 0;
+
+ *progOut = prog;
+ *paramPosOut = progPos;
}
@@ -1200,23 +1258,54 @@ static void
_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
GLfloat *params)
{
- (void) get_uniformfv(ctx, program, location, params);
+ struct gl_program *prog;
+ GLint paramPos;
+
+ lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
+
+ if (prog) {
+ const struct gl_program_parameter *p =
+ &prog->Parameters->Parameters[paramPos];
+ GLint rows, cols, i, j, k;
+
+ get_uniform_rows_cols(p, &rows, &cols);
+
+ k = 0;
+ for (i = 0; i < rows; i++) {
+ for (j = 0; j < cols; j++ ) {
+ params[k++] = prog->Parameters->ParameterValues[paramPos+i][j];
+ }
+ }
+ }
}
/**
* Called via ctx->Driver.GetUniformiv().
+ * \sa _mesa_get_uniformfv, only difference is a cast.
*/
static void
_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
GLint *params)
{
- GLfloat fparams[MAX_UNIFORM_ELEMENTS];
- GLuint n = get_uniformfv(ctx, program, location, fparams);
- GLuint i;
- assert(n <= MAX_UNIFORM_ELEMENTS);
- for (i = 0; i < n; i++) {
- params[i] = (GLint) fparams[i];
+ struct gl_program *prog;
+ GLint paramPos;
+
+ lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
+
+ if (prog) {
+ const struct gl_program_parameter *p =
+ &prog->Parameters->Parameters[paramPos];
+ GLint rows, cols, i, j, k;
+
+ get_uniform_rows_cols(p, &rows, &cols);
+
+ k = 0;
+ for (i = 0; i < rows; i++) {
+ for (j = 0; j < cols; j++ ) {
+ params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j];
+ }
+ }
}
}
@@ -1342,6 +1431,9 @@ _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
}
sh->Source = source;
sh->CompileStatus = GL_FALSE;
+#ifdef DEBUG
+ sh->SourceChecksum = _mesa_str_checksum(sh->Source);
+#endif
}
@@ -1357,7 +1449,13 @@ _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
if (!sh)
return;
- sh->CompileStatus = _slang_compile(ctx, sh);
+ /* set default pragma state for shader */
+ sh->Pragmas = ctx->Shader.DefaultPragmas;
+
+ /* this call will set the sh->CompileStatus field to indicate if
+ * compilation was successful.
+ */
+ (void) _slang_compile(ctx, sh);
}
@@ -1393,7 +1491,7 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
if (program) {
shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
@@ -1401,9 +1499,26 @@ _mesa_use_program(GLcontext *ctx, GLuint program)
return;
}
if (!shProg->LinkStatus) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUseProgram(program %u not linked)", program);
return;
}
+
+ /* debug code */
+ if (0) {
+ GLuint i;
+ _mesa_printf("Use Shader %u\n", shProg->Name);
+ for (i = 0; i < shProg->NumShaders; i++) {
+ _mesa_printf(" shader %u, type 0x%x, checksum %u\n",
+ shProg->Shaders[i]->Name,
+ shProg->Shaders[i]->Type,
+ shProg->Shaders[i]->SourceChecksum);
+ }
+ if (shProg->VertexProgram)
+ printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
+ if (shProg->FragmentProgram)
+ printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
+ }
}
else {
shProg = NULL;
@@ -1438,36 +1553,16 @@ _mesa_update_shader_textures_used(struct gl_program *prog)
for (s = 0; s < MAX_SAMPLERS; s++) {
if (prog->SamplersUsed & (1 << s)) {
- GLuint u = prog->SamplerUnits[s];
- GLuint t = prog->SamplerTargets[s];
- assert(u < MAX_TEXTURE_IMAGE_UNITS);
- prog->TexturesUsed[u] |= (1 << t);
+ GLuint unit = prog->SamplerUnits[s];
+ GLuint tgt = prog->SamplerTargets[s];
+ assert(unit < MAX_TEXTURE_IMAGE_UNITS);
+ assert(tgt < NUM_TEXTURE_TARGETS);
+ prog->TexturesUsed[unit] |= (1 << tgt);
}
}
}
-static GLboolean
-is_sampler_type(GLenum type)
-{
- switch (type) {
- case GL_SAMPLER_1D:
- case GL_SAMPLER_2D:
- case GL_SAMPLER_3D:
- case GL_SAMPLER_CUBE:
- case GL_SAMPLER_1D_SHADOW:
- case GL_SAMPLER_2D_SHADOW:
- case GL_SAMPLER_2D_RECT_ARB:
- case GL_SAMPLER_2D_RECT_SHADOW_ARB:
- case GL_SAMPLER_1D_ARRAY_EXT:
- case GL_SAMPLER_2D_ARRAY_EXT:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
/**
* Check if the type given by userType is allowed to set a uniform of the
* target type. Generally, equivalence is required, but setting Boolean
@@ -1506,10 +1601,10 @@ compatible_types(GLenum userType, GLenum targetType)
* \param program the program whose uniform to update
* \param index the index of the program parameter for the uniform
* \param offset additional parameter slot offset (for arrays)
- * \param type the datatype of the uniform
+ * \param type the incoming datatype of 'values'
* \param count the number of uniforms to set
- * \param elems number of elements per uniform
- * \param values the new values
+ * \param elems number of elements per uniform (1, 2, 3 or 4)
+ * \param values the new values, of datatype 'type'
*/
static void
set_program_uniform(GLcontext *ctx, struct gl_program *program,
@@ -1517,66 +1612,103 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
GLenum type, GLsizei count, GLint elems,
const void *values)
{
- struct gl_program_parameter *param =
+ const struct gl_program_parameter *param =
&program->Parameters->Parameters[index];
assert(offset >= 0);
+ assert(elems >= 1);
+ assert(elems <= 4);
if (!compatible_types(type, param->DataType)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
return;
}
- if (index + offset > program->Parameters->Size) {
+ if (index + offset > (GLint) program->Parameters->Size) {
/* out of bounds! */
return;
}
if (param->Type == PROGRAM_SAMPLER) {
/* This controls which texture unit which is used by a sampler */
- GLuint texUnit, sampler;
+ GLboolean changed = GL_FALSE;
+ GLint i;
+
+ /* this should have been caught by the compatible_types() check */
+ ASSERT(type == GL_INT);
+
+ /* loop over number of samplers to change */
+ for (i = 0; i < count; i++) {
+ GLuint sampler =
+ (GLuint) program->Parameters->ParameterValues[index + offset + i][0];
+ GLuint texUnit = ((GLuint *) values)[i];
+
+ /* check that the sampler (tex unit index) is legal */
+ if (texUnit >= ctx->Const.MaxTextureImageUnits) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glUniform1(invalid sampler/tex unit index)");
+ return;
+ }
- /* data type for setting samplers must be int */
- if (type != GL_INT || count != 1) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glUniform(only glUniform1i can be used "
- "to set sampler uniforms)");
- return;
+ /* This maps a sampler to a texture unit: */
+ if (sampler < MAX_SAMPLERS) {
+#if 0
+ _mesa_printf("Set program %p sampler %d '%s' to unit %u\n",
+ program, sampler, param->Name, texUnit);
+#endif
+ if (program->SamplerUnits[sampler] != texUnit) {
+ program->SamplerUnits[sampler] = texUnit;
+ changed = GL_TRUE;
+ }
+ }
}
- sampler = (GLuint) program->Parameters->ParameterValues[index][0];
- texUnit = ((GLuint *) values)[0];
-
- /* check that the sampler (tex unit index) is legal */
- if (texUnit >= ctx->Const.MaxTextureImageUnits) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glUniform1(invalid sampler/tex unit index)");
- return;
+ if (changed) {
+ /* When a sampler's value changes it usually requires rewriting
+ * a GPU program's TEX instructions since there may not be a
+ * sampler->texture lookup table. We signal this with the
+ * ProgramStringNotify() callback.
+ */
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
+ _mesa_update_shader_textures_used(program);
+ ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
}
-
- /* This maps a sampler to a texture unit: */
- program->SamplerUnits[sampler] = texUnit;
- _mesa_update_shader_textures_used(program);
-
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
}
else {
/* ordinary uniform variable */
+ const GLboolean isUniformBool = is_boolean_type(param->DataType);
+ const GLboolean areIntValues = is_integer_type(type);
+ const GLint slots = (param->Size + 3) / 4;
+ const GLint typeSize = sizeof_glsl_type(param->DataType);
GLsizei k, i;
- GLint slots = (param->Size + 3) / 4;
- if (count * elems > (GLint) param->Size) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
- return;
+ if (param->Size > typeSize) {
+ /* an array */
+ /* we'll ignore extra data below */
+ }
+ else {
+ /* non-array: count must be one */
+ if (count != 1) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniform(uniform is not an array)");
+ return;
+ }
}
- if (count > slots)
- count = slots;
-
+ /* loop over number of array elements */
for (k = 0; k < count; k++) {
- GLfloat *uniformVal =
- program->Parameters->ParameterValues[index + offset + k];
- if (is_integer_type(type)) {
+ GLfloat *uniformVal;
+
+ if (offset + k >= slots) {
+ /* Extra array data is ignored */
+ break;
+ }
+
+ /* uniformVal (the destination) is always float[4] */
+ uniformVal = program->Parameters->ParameterValues[index + offset + k];
+
+ if (areIntValues) {
+ /* convert user's ints to floats */
const GLint *iValues = ((const GLint *) values) + k * elems;
for (i = 0; i < elems; i++) {
uniformVal[i] = (GLfloat) iValues[i];
@@ -1590,9 +1722,9 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
}
/* if the uniform is bool-valued, convert to 1.0 or 0.0 */
- if (is_boolean_type(param->DataType)) {
+ if (isUniformBool) {
for (i = 0; i < elems; i++) {
- uniformVal[i] = uniformVal[i] ? 1.0 : 0.0;
+ uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
}
}
}
@@ -1610,6 +1742,7 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
struct gl_uniform *uniform;
GLint elems, offset;
+ GLenum basicType;
if (!shProg || !shProg->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
@@ -1619,6 +1752,11 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
if (location == -1)
return; /* The standard specifies this as a no-op */
+ if (location < -1) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
+ return;
+ }
+
split_location_offset(&location, &offset);
if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
@@ -1633,19 +1771,35 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
switch (type) {
case GL_FLOAT:
+ basicType = GL_FLOAT;
+ elems = 1;
+ break;
case GL_INT:
+ basicType = GL_INT;
elems = 1;
break;
case GL_FLOAT_VEC2:
+ basicType = GL_FLOAT;
+ elems = 2;
+ break;
case GL_INT_VEC2:
+ basicType = GL_INT;
elems = 2;
break;
case GL_FLOAT_VEC3:
+ basicType = GL_FLOAT;
+ elems = 3;
+ break;
case GL_INT_VEC3:
+ basicType = GL_INT;
elems = 3;
break;
case GL_FLOAT_VEC4:
+ basicType = GL_FLOAT;
+ elems = 4;
+ break;
case GL_INT_VEC4:
+ basicType = GL_INT;
elems = 4;
break;
default:
@@ -1653,10 +1807,29 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
uniform = &shProg->Uniforms->Uniforms[location];
+ if (ctx->Shader.Flags & GLSL_UNIFORMS) {
+ GLint i;
+ _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ",
+ shProg->Name, uniform->Name, location);
+ if (basicType == GL_INT) {
+ const GLint *v = (const GLint *) values;
+ for (i = 0; i < count * elems; i++) {
+ _mesa_printf("%d ", v[i]);
+ }
+ }
+ else {
+ const GLfloat *v = (const GLfloat *) values;
+ for (i = 0; i < count * elems; i++) {
+ _mesa_printf("%g ", v[i]);
+ }
+ }
+ _mesa_printf("\n");
+ }
+
/* A uniform var may be used by both a vertex shader and a fragment
* shader. We may need to update one or both shader's uniform here:
*/
@@ -1742,7 +1915,7 @@ set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
*/
static void
_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
- GLenum matrixType, GLint location, GLsizei count,
+ GLint location, GLsizei count,
GLboolean transpose, const GLfloat *values)
{
struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
@@ -1758,6 +1931,11 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
if (location == -1)
return; /* The standard specifies this as a no-op */
+ if (location < -1) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
+ return;
+ }
+
split_location_offset(&location, &offset);
if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
@@ -1769,7 +1947,7 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
return;
}
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
uniform = &shProg->Uniforms->Uniforms[location];
@@ -1797,19 +1975,74 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
}
-static void
-_mesa_validate_program(GLcontext *ctx, GLuint program)
+/**
+ * Validate a program's samplers.
+ * Specifically, check that there aren't two samplers of different types
+ * pointing to the same texture unit.
+ * \return GL_TRUE if valid, GL_FALSE if invalid
+ */
+static GLboolean
+validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
{
- struct gl_shader_program *shProg;
+ static const char *targetName[] = {
+ "TEXTURE_2D_ARRAY",
+ "TEXTURE_1D_ARRAY",
+ "TEXTURE_CUBE",
+ "TEXTURE_3D",
+ "TEXTURE_RECT",
+ "TEXTURE_2D",
+ "TEXTURE_1D",
+ };
+ GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS];
+ GLbitfield samplersUsed = prog->SamplersUsed;
+ GLuint i;
- shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
- if (!shProg) {
- return;
+ assert(Elements(targetName) == NUM_TEXTURE_TARGETS);
+
+ if (samplersUsed == 0x0)
+ return GL_TRUE;
+
+ for (i = 0; i < Elements(targetUsed); i++)
+ targetUsed[i] = -1;
+
+ /* walk over bits which are set in 'samplers' */
+ while (samplersUsed) {
+ GLuint unit;
+ gl_texture_index target;
+ GLint sampler = _mesa_ffs(samplersUsed) - 1;
+ assert(sampler >= 0);
+ assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
+ unit = prog->SamplerUnits[sampler];
+ target = prog->SamplerTargets[sampler];
+ if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
+ _mesa_snprintf(errMsg, 100,
+ "Texture unit %d is accessed both as %s and %s",
+ unit, targetName[targetUsed[unit]], targetName[target]);
+ return GL_FALSE;
+ }
+ targetUsed[unit] = target;
+ samplersUsed ^= (1 << sampler);
}
+ return GL_TRUE;
+}
+
+
+/**
+ * Do validation of the given shader program.
+ * \param errMsg returns error message if validation fails.
+ * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
+ */
+GLboolean
+_mesa_validate_shader_program(GLcontext *ctx,
+ const struct gl_shader_program *shProg,
+ char *errMsg)
+{
+ const struct gl_vertex_program *vp = shProg->VertexProgram;
+ const struct gl_fragment_program *fp = shProg->FragmentProgram;
+
if (!shProg->LinkStatus) {
- shProg->Validated = GL_FALSE;
- return;
+ return GL_FALSE;
}
/* From the GL spec, a program is invalid if any of these are true:
@@ -1827,7 +2060,44 @@ _mesa_validate_program(GLcontext *ctx, GLuint program)
image units allowed.
*/
- shProg->Validated = GL_TRUE;
+
+ /*
+ * Check: any two active samplers in the current program object are of
+ * different types, but refer to the same texture image unit,
+ */
+ if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) {
+ return GL_FALSE;
+ }
+ if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via glValidateProgram()
+ */
+static void
+_mesa_validate_program(GLcontext *ctx, GLuint program)
+{
+ struct gl_shader_program *shProg;
+ char errMsg[100];
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
+ if (!shProg) {
+ return;
+ }
+
+ shProg->Validated = _mesa_validate_shader_program(ctx, shProg, errMsg);
+ if (!shProg->Validated) {
+ /* update info log */
+ if (shProg->InfoLog) {
+ _mesa_free(shProg->InfoLog);
+ }
+ shProg->InfoLog = _mesa_strdup(errMsg);
+ }
}
diff --git a/src/mesa/shader/shader_api.h b/src/mesa/shader/shader_api.h
index ec1996ee98..d08d47373e 100644
--- a/src/mesa/shader/shader_api.h
+++ b/src/mesa/shader/shader_api.h
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 6.5
+ * Version: 7.6
*
* Copyright (C) 2004-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -87,6 +88,11 @@ extern void
_mesa_use_program(GLcontext *ctx, GLuint program);
+extern GLboolean
+_mesa_validate_shader_program(GLcontext *ctx,
+ const struct gl_shader_program *shProg,
+ char *errMsg);
+
extern void
_mesa_init_glsl_driver_functions(struct dd_function_table *driver);
diff --git a/src/mesa/shader/slang/library/slang_common_builtin.gc b/src/mesa/shader/slang/library/slang_common_builtin.gc
index 230c57cea8..9764fc25b0 100644
--- a/src/mesa/shader/slang/library/slang_common_builtin.gc
+++ b/src/mesa/shader/slang/library/slang_common_builtin.gc
@@ -1659,76 +1659,76 @@ bvec4 not (const bvec4 v)
vec4 texture1D(const sampler1D sampler, const float coord)
{
- __asm vec4_tex1d __retVal, sampler, coord;
+ __asm vec4_tex_1d __retVal, sampler, coord;
}
vec4 texture1DProj(const sampler1D sampler, const vec2 coord)
{
// need to swizzle .y into .w
- __asm vec4_texp1d __retVal, sampler, coord.xyyy;
+ __asm vec4_tex_1d_proj __retVal, sampler, coord.xyyy;
}
vec4 texture1DProj(const sampler1D sampler, const vec4 coord)
{
- __asm vec4_texp1d __retVal, sampler, coord;
+ __asm vec4_tex_1d_proj __retVal, sampler, coord;
}
vec4 texture2D(const sampler2D sampler, const vec2 coord)
{
- __asm vec4_tex2d __retVal, sampler, coord;
+ __asm vec4_tex_2d __retVal, sampler, coord;
}
vec4 texture2DProj(const sampler2D sampler, const vec3 coord)
{
// need to swizzle 'z' into 'w'.
- __asm vec4_texp2d __retVal, sampler, coord.xyzz;
+ __asm vec4_tex_2d_proj __retVal, sampler, coord.xyzz;
}
vec4 texture2DProj(const sampler2D sampler, const vec4 coord)
{
- __asm vec4_texp2d __retVal, sampler, coord;
+ __asm vec4_tex_2d_proj __retVal, sampler, coord;
}
vec4 texture3D(const sampler3D sampler, const vec3 coord)
{
- __asm vec4_tex3d __retVal, sampler, coord;
+ __asm vec4_tex_3d __retVal, sampler, coord;
}
vec4 texture3DProj(const sampler3D sampler, const vec4 coord)
{
- __asm vec4_texp3d __retVal, sampler, coord;
+ __asm vec4_tex_3d_proj __retVal, sampler, coord;
}
vec4 textureCube(const samplerCube sampler, const vec3 coord)
{
- __asm vec4_texcube __retVal, sampler, coord;
+ __asm vec4_tex_cube __retVal, sampler, coord;
}
vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord)
{
- __asm vec4_tex1d __retVal, sampler, coord;
+ __asm vec4_tex_1d_shadow __retVal, sampler, coord;
}
vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord)
{
// .s and .p will be divided by .q
- __asm vec4_texp1d __retVal, sampler, coord;
+ __asm vec4_tex_1d_proj_shadow __retVal, sampler, coord;
}
vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord)
{
- __asm vec4_tex2d __retVal, sampler, coord;
+ __asm vec4_tex_2d_shadow __retVal, sampler, coord;
}
vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord)
{
// .s, .t and .p will be divided by .q
- __asm vec4_texp2d __retVal, sampler, coord;
+ __asm vec4_tex_2d_proj_shadow __retVal, sampler, coord;
}
@@ -1741,22 +1741,22 @@ vec4 texture2DRect(const sampler2DRect sampler, const vec2 coord)
vec4 texture2DRectProj(const sampler2DRect sampler, const vec3 coord)
{
// need to swizzle .y into .w
- __asm vec4_texp_rect __retVal, sampler, coord.xyzz;
+ __asm vec4_tex_rect_proj __retVal, sampler, coord.xyzz;
}
vec4 texture2DRectProj(const sampler2DRect sampler, const vec4 coord)
{
- __asm vec4_texp_rect __retVal, sampler, ccoord;
+ __asm vec4_tex_rect_proj __retVal, sampler, ccoord;
}
vec4 shadow2DRect(const sampler2DRectShadow sampler, const vec3 coord)
{
- __asm vec4_tex_rect __retVal, sampler, coord;
+ __asm vec4_tex_rect_shadow __retVal, sampler, coord;
}
vec4 shadow2DRectProj(const sampler2DRectShadow sampler, const vec4 coord)
{
- __asm vec4_texp_rect __retVal, sampler, coord;
+ __asm vec4_tex_rect_proj_shadow __retVal, sampler, coord;
}
diff --git a/src/mesa/shader/slang/library/slang_common_builtin_gc.h b/src/mesa/shader/slang/library/slang_common_builtin_gc.h
index 759bf247d8..78a7b83ec1 100644
--- a/src/mesa/shader/slang/library/slang_common_builtin_gc.h
+++ b/src/mesa/shader/slang/library/slang_common_builtin_gc.h
@@ -744,125 +744,129 @@
120,121,122,0,0,18,118,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,4,0,0,110,111,116,0,1,1,0,0,4,0,118,0,
0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,17,48,0,48,0,
0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,0,1,1,0,0,16,0,115,97,109,112,108,101,
-114,0,0,1,1,0,0,9,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,49,100,0,18,95,95,
+114,0,0,1,1,0,0,9,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,49,100,0,18,95,95,
114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,
0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,1,0,0,16,0,115,97,109,112,108,101,
-114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,112,49,100,0,18,95,
-95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,59,120,121,
-121,121,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,1,0,0,16,0,
-115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,
-120,112,49,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,
-111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,0,1,1,0,0,17,0,115,97,109,
-112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,50,100,
-0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,
-0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,114,111,106,0,1,1,0,0,17,0,115,97,109,
-112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,112,50,
+114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,49,100,95,112,
+114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,
+114,100,0,59,120,121,121,121,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,
+111,106,0,1,1,0,0,16,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,
+118,101,99,52,95,116,101,120,95,49,100,95,112,114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,
+115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,
+117,114,101,50,68,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,
+0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,
+112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,
+50,68,80,114,111,106,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,
+0,0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,95,112,114,111,106,0,18,95,95,114,101,116,86,97,
+108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,59,120,121,122,122,0,0,0,0,1,90,
+95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,114,111,106,0,1,1,0,0,17,0,115,97,109,112,108,
+101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,95,
+112,114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,
+111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,0,1,1,0,0,18,0,115,97,109,
+112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,51,
100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,
-59,120,121,122,122,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,114,111,106,0,1,
-1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,
-95,116,101,120,112,50,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,
-18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,0,1,1,0,0,18,0,
-115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,
-120,51,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,
-114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,80,114,111,106,0,1,1,0,0,18,0,
-115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,
-120,112,51,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,
-111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,67,117,98,101,0,1,1,0,0,19,0,
-115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,
-120,99,117,98,101,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,
-111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,0,1,1,0,0,20,0,115,97,109,112,
-108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,49,100,0,18,
-95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,
-90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,80,114,111,106,0,1,1,0,0,20,0,115,97,109,112,108,101,
-114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,112,49,100,0,18,95,
-95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,
-95,0,0,12,0,0,115,104,97,100,111,119,50,68,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,0,1,1,0,0,
-11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,50,100,0,18,95,95,114,101,116,86,97,
-108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,
-97,100,111,119,50,68,80,114,111,106,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,
-111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,112,50,100,0,18,95,95,114,101,116,86,97,108,
-0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,
-116,117,114,101,50,68,82,101,99,116,0,1,1,0,0,22,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,
-111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,114,101,99,116,0,18,95,95,114,101,116,86,
-97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,
-101,120,116,117,114,101,50,68,82,101,99,116,80,114,111,106,0,1,1,0,0,22,0,115,97,109,112,108,101,
-114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,112,95,114,101,99,
-116,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,
-59,120,121,122,122,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,82,101,99,116,80,
-114,111,106,0,1,1,0,0,22,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,
-4,118,101,99,52,95,116,101,120,112,95,114,101,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,115,
-97,109,112,108,101,114,0,0,18,99,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,
-119,50,68,82,101,99,116,0,1,1,0,0,23,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,
-100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,114,101,99,116,0,18,95,95,114,101,116,86,97,108,0,0,
-18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,
-111,119,50,68,82,101,99,116,80,114,111,106,0,1,1,0,0,23,0,115,97,109,112,108,101,114,0,0,1,1,0,0,
-12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,112,95,114,101,99,116,0,18,95,95,
+0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,80,114,111,106,0,1,1,0,0,18,0,115,97,
+109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,
+51,100,95,112,114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,
+18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,67,117,98,101,0,1,1,0,
+0,19,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,
+116,101,120,95,99,117,98,101,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,
+0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,0,1,1,0,0,20,0,115,
+97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,
+95,49,100,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,80,114,111,
+106,0,1,1,0,0,20,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,
+101,99,52,95,116,101,120,95,49,100,95,112,114,111,106,95,115,104,97,100,111,119,0,18,95,95,114,101,
+116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,
+0,115,104,97,100,111,119,50,68,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,
+111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,95,115,104,97,100,111,119,0,18,95,95,
114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,
-0,0,9,0,0,110,111,105,115,101,49,0,1,1,0,0,9,0,120,0,0,0,1,4,102,108,111,97,116,95,110,111,105,115,
-101,49,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,9,0,0,110,111,105,115,101,
-49,0,1,1,0,0,10,0,120,0,0,0,1,4,102,108,111,97,116,95,110,111,105,115,101,50,0,18,95,95,114,101,
-116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,9,0,0,110,111,105,115,101,49,0,1,1,0,0,11,0,120,0,0,0,
-1,4,102,108,111,97,116,95,110,111,105,115,101,51,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,
-0,1,90,95,0,0,9,0,0,110,111,105,115,101,49,0,1,1,0,0,12,0,120,0,0,0,1,4,102,108,111,97,116,95,110,
-111,105,115,101,52,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,10,0,0,110,111,
-105,115,101,50,0,1,1,0,0,9,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,
+0,0,12,0,0,115,104,97,100,111,119,50,68,80,114,111,106,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,
+0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,95,112,114,111,
+106,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,
+0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,82,101,99,116,
+0,1,1,0,0,22,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,0,1,4,118,101,99,
+52,95,116,101,120,95,114,101,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,82,101,
+99,116,80,114,111,106,0,1,1,0,0,22,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,
+100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,114,101,99,116,95,112,114,111,106,0,18,95,95,114,101,
+116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,59,120,121,122,122,0,0,
+0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,82,101,99,116,80,114,111,106,0,1,1,0,0,22,
+0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,
+101,120,95,114,101,99,116,95,112,114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,
+112,108,101,114,0,0,18,99,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,50,
+68,82,101,99,116,0,1,1,0,0,23,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,
+0,1,4,118,101,99,52,95,116,101,120,95,114,101,99,116,95,115,104,97,100,111,119,0,18,95,95,114,101,
+116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,
+0,115,104,97,100,111,119,50,68,82,101,99,116,80,114,111,106,0,1,1,0,0,23,0,115,97,109,112,108,101,
+114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,114,101,99,116,
+95,112,114,111,106,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,
+112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,9,0,0,110,111,105,115,101,49,0,1,1,0,
+0,9,0,120,0,0,0,1,4,102,108,111,97,116,95,110,111,105,115,101,49,0,18,95,95,114,101,116,86,97,108,
+0,0,18,120,0,0,0,0,1,90,95,0,0,9,0,0,110,111,105,115,101,49,0,1,1,0,0,10,0,120,0,0,0,1,4,102,108,
+111,97,116,95,110,111,105,115,101,50,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,
+0,9,0,0,110,111,105,115,101,49,0,1,1,0,0,11,0,120,0,0,0,1,4,102,108,111,97,116,95,110,111,105,115,
+101,51,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,9,0,0,110,111,105,115,101,
+49,0,1,1,0,0,12,0,120,0,0,0,1,4,102,108,111,97,116,95,110,111,105,115,101,52,0,18,95,95,114,101,
+116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,9,0,120,0,0,0,
+1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,
+95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,17,49,57,0,51,52,0,0,
+46,0,0,20,0,0,1,90,95,0,0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,10,0,120,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,49,57,0,51,
+52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,
+11,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,
+0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,
+118,101,99,51,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,0,46,0,0,20,0,0,1,
+90,95,0,0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,12,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,
+59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,49,57,0,51,52,0,0,0,17,55,
+0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,11,0,0,110,111,
+105,115,101,51,0,1,1,0,0,9,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,
105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,
-115,101,49,0,0,18,120,0,17,49,57,0,51,52,0,0,46,0,0,20,0,0,1,90,95,0,0,10,0,0,110,111,105,115,101,
-50,0,1,1,0,0,10,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,
-49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,
-18,120,0,58,118,101,99,50,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,0,20,0,0,1,90,95,0,
-0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,11,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,
-120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,
-58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,
-0,0,17,51,0,50,51,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,12,0,
-120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,
-20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,
-99,52,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,
-0,0,20,0,0,1,90,95,0,0,11,0,0,110,111,105,115,101,51,0,1,1,0,0,9,0,120,0,0,0,1,9,18,95,95,114,101,
-116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,
-97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,17,49,57,0,51,52,0,0,46,0,0,20,0,9,18,95,
-95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,17,53,0,52,55,0,0,46,0,
-0,20,0,0,1,90,95,0,0,11,0,0,110,111,105,115,101,51,0,1,1,0,0,10,0,120,0,0,0,1,9,18,95,95,114,101,
-116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,
-97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,49,57,0,51,52,0,0,
-0,17,55,0,54,54,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,
-101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,0,46,0,0,20,0,
-0,1,90,95,0,0,11,0,0,110,111,105,115,101,51,0,1,1,0,0,11,0,120,0,0,0,1,9,18,95,95,114,101,116,86,
-97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,
-0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,49,57,0,51,52,0,0,0,17,
-55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,
-110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,
-0,17,49,49,0,48,52,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,11,0,0,110,111,105,115,101,51,0,1,1,0,0,12,0,
-120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,
-20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,
-99,52,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,
-0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,
-101,99,52,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,0,17,49,51,0,49,57,0,
-0,0,0,46,0,0,20,0,0,1,90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,9,0,120,0,0,0,1,9,18,95,95,
+115,101,49,0,0,18,120,0,17,49,57,0,51,52,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,
+0,58,110,111,105,115,101,49,0,0,18,120,0,17,53,0,52,55,0,0,46,0,0,20,0,0,1,90,95,0,0,11,0,0,110,
+111,105,115,101,51,0,1,1,0,0,10,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,
+111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,
+105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,
+0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,
+101,99,50,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,11,0,0,110,
+111,105,115,101,51,0,1,1,0,0,11,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,
+111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,
+105,115,101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,
+0,50,51,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,
+0,0,18,120,0,58,118,101,99,51,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,
+0,0,46,0,0,20,0,0,1,90,95,0,0,11,0,0,110,111,105,115,101,51,0,1,1,0,0,12,0,120,0,0,0,1,9,18,95,95,
114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,
-101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,17,49,57,0,51,52,0,0,46,0,0,20,
-0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,17,53,0,52,55,
-0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,0,
-17,50,51,0,53,52,0,0,46,0,0,20,0,0,1,90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,10,0,120,0,
-0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,
-9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,
-50,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,
-59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,53,0,52,55,0,0,0,17,49,55,
-0,56,53,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,
-0,0,18,120,0,58,118,101,99,50,0,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,0,46,0,0,20,0,0,1,
-90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,11,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,
+101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,49,57,
+0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,0,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,53,
+0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,0,17,49,51,0,49,57,0,0,0,0,46,0,0,20,0,0,
+1,90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,9,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,
108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,
-59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,49,57,0,51,52,0,0,0,17,55,
-0,54,54,0,0,0,17,51,0,50,51,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,
-111,105,115,101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,
-49,49,0,48,52,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,
-101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,17,51,49,0,
-57,49,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,12,0,120,0,0,0,1,9,
-18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,
-95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,
-49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,0,0,20,0,9,18,
-95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,
-17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,0,17,49,51,0,49,57,0,0,0,0,46,0,0,
-20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,
-99,52,0,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,17,51,49,0,57,49,0,0,0,17,51,55,0,52,56,0,
-0,0,0,46,0,0,20,0,0,0
+59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,17,49,57,0,51,52,0,0,46,0,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,17,53,0,52,55,0,0,46,0,0,20,0,
+9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,0,17,50,51,0,53,
+52,0,0,46,0,0,20,0,0,1,90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,10,0,120,0,0,0,1,9,18,95,
+95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,49,57,
+0,51,52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,
+111,105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,0,
+46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,0,58,
+118,101,99,50,0,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,12,0,0,
+110,111,105,115,101,52,0,1,1,0,0,11,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,
+110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,
+111,105,115,101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,
+51,0,50,51,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,
+49,0,0,18,120,0,58,118,101,99,51,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,
+0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,
+0,58,118,101,99,51,0,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,17,51,49,0,57,49,0,0,0,0,46,0,
+0,20,0,0,1,90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,12,0,120,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,
+97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,49,57,0,51,52,0,0,
+0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,
+86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,53,0,52,55,0,0,
+0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,0,17,49,51,0,49,57,0,0,0,0,46,0,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,50,
+51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,17,51,49,0,57,49,0,0,0,17,51,55,0,52,56,0,0,0,0,46,0,0,20,
+0,0,0
diff --git a/src/mesa/shader/slang/library/slang_fragment_builtin.gc b/src/mesa/shader/slang/library/slang_fragment_builtin.gc
index 416c6ff313..2e063e6416 100644
--- a/src/mesa/shader/slang/library/slang_fragment_builtin.gc
+++ b/src/mesa/shader/slang/library/slang_fragment_builtin.gc
@@ -46,7 +46,7 @@ vec4 texture1D(const sampler1D sampler, const float coord, const float bias)
vec4 coord4;
coord4.x = coord;
coord4.w = bias;
- __asm vec4_texb1d __retVal, sampler, coord4;
+ __asm vec4_tex_1d_bias __retVal, sampler, coord4;
}
vec4 texture1DProj(const sampler1D sampler, const vec2 coord, const float bias)
@@ -55,7 +55,7 @@ vec4 texture1DProj(const sampler1D sampler, const vec2 coord, const float bias)
vec4 pcoord;
pcoord.x = coord.x / coord.y;
pcoord.w = bias;
- __asm vec4_texb1d __retVal, sampler, pcoord;
+ __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
}
vec4 texture1DProj(const sampler1D sampler, const vec4 coord, const float bias)
@@ -64,7 +64,7 @@ vec4 texture1DProj(const sampler1D sampler, const vec4 coord, const float bias)
vec4 pcoord;
pcoord.x = coord.x / coord.z;
pcoord.w = bias;
- __asm vec4_texb1d __retVal, sampler, pcoord;
+ __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
}
@@ -75,7 +75,7 @@ vec4 texture2D(const sampler2D sampler, const vec2 coord, const float bias)
vec4 coord4;
coord4.xy = coord.xy;
coord4.w = bias;
- __asm vec4_texb2d __retVal, sampler, coord4;
+ __asm vec4_tex_2d_bias __retVal, sampler, coord4;
}
vec4 texture2DProj(const sampler2D sampler, const vec3 coord, const float bias)
@@ -84,7 +84,7 @@ vec4 texture2DProj(const sampler2D sampler, const vec3 coord, const float bias)
vec4 pcoord;
pcoord.xy = coord.xy / coord.z;
pcoord.w = bias;
- __asm vec4_texb2d __retVal, sampler, pcoord;
+ __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
}
vec4 texture2DProj(const sampler2D sampler, const vec4 coord, const float bias)
@@ -93,7 +93,7 @@ vec4 texture2DProj(const sampler2D sampler, const vec4 coord, const float bias)
vec4 pcoord;
pcoord.xy = coord.xy / coord.w;
pcoord.w = bias;
- __asm vec4_texb2d __retVal, sampler, pcoord;
+ __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
}
@@ -104,7 +104,7 @@ vec4 texture3D(const sampler3D sampler, const vec3 coord, const float bias)
vec4 coord4;
coord4.xyz = coord.xyz;
coord4.w = bias;
- __asm vec4_texb3d __retVal, sampler, coord4;
+ __asm vec4_tex_3d_bias __retVal, sampler, coord4;
}
vec4 texture3DProj(const sampler3D sampler, const vec4 coord, const float bias)
@@ -113,7 +113,7 @@ vec4 texture3DProj(const sampler3D sampler, const vec4 coord, const float bias)
vec4 pcoord;
pcoord.xyz = coord.xyz / coord.w;
pcoord.w = bias;
- __asm vec4_texb3d __retVal, sampler, pcoord;
+ __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
}
@@ -124,21 +124,17 @@ vec4 textureCube(const samplerCube sampler, const vec3 coord, const float bias)
vec4 coord4;
coord4.xyz = coord;
coord4.w = bias;
- __asm vec4_texcube __retVal, sampler, coord4;
+ __asm vec4_tex_cube __retVal, sampler, coord4;
}
-
-// For shadow textures, we use the regular tex instructions since they should
-// do the depth comparison step.
-
vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord, const float bias)
{
vec4 coord4;
coord4.xyz = coord;
coord4.w = bias;
- __asm vec4_texb1d __retVal, sampler, coord4;
+ __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
}
vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord, const float bias)
@@ -147,7 +143,7 @@ vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord, const float b
pcoord.x = coord.x / coord.w;
pcoord.z = coord.z;
pcoord.w = bias;
- __asm vec4_texb1d __retVal, sampler, pcoord;
+ __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
}
vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord, const float bias)
@@ -155,7 +151,7 @@ vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord, const float bias)
vec4 coord4;
coord4.xyz = coord;
coord4.w = bias;
- __asm vec4_texb2d __retVal, sampler, coord4;
+ __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
}
vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord, const float bias)
@@ -164,7 +160,7 @@ vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord, const float b
pcoord.xy = coord.xy / coord.w;
pcoord.z = coord.z;
pcoord.w = bias;
- __asm vec4_texb2d __retVal, sampler, pcoord;
+ __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
}
diff --git a/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h b/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h
index 738a0f9295..c5a1cce2a4 100644
--- a/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h
+++ b/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h
@@ -14,94 +14,97 @@
108,101,114,0,0,1,1,0,0,9,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,
12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,0,18,99,111,111,114,100,0,
20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,
-98,49,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,
-100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,1,0,0,16,0,
-115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,
-1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,18,99,
-111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,121,0,49,20,0,9,18,112,99,111,111,114,100,0,
-59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,98,49,100,0,18,95,95,114,101,116,
-86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,
-0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,1,0,0,16,0,115,97,109,112,108,101,114,0,0,1,
-1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,
-111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,120,0,18,
-99,111,111,114,100,0,59,122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,
-0,4,118,101,99,52,95,116,101,120,98,49,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,
-108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,
-50,68,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,
-0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,
-52,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,
-18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,98,50,100,0,18,95,95,114,101,116,86,97,108,
-0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,
-120,116,117,114,101,50,68,80,114,111,106,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,
-0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,
-100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,
-111,111,114,100,0,59,122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,
-4,118,101,99,52,95,116,101,120,98,50,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,
-108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,
-50,68,80,114,111,106,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,
-0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,
-99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
-119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,
-116,101,120,98,50,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,
+95,49,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,
+18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,
+106,0,1,1,0,0,16,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,
+98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,
+100,0,59,120,0,18,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,121,0,49,20,0,9,18,112,
+99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,
+98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,
+111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,1,0,0,
+16,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,
+0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,
+18,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,122,0,49,20,0,9,18,112,99,111,111,114,
+100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,0,
+18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,
+0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,0,1,1,0,0,17,0,115,97,109,112,108,101,114,
+0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,
+111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,0,18,99,111,111,114,100,0,59,120,
+121,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,
+101,120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,
+114,111,106,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,
+0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,
+111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,122,0,
+49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,
+120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,
+0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,114,
+111,106,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,
+9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,
+114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,119,0,49,20,
+0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,
+50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,
112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,0,1,1,0,0,18,0,
115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,
1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,
18,99,111,111,114,100,0,59,120,121,122,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,
-115,0,20,0,4,118,101,99,52,95,116,101,120,98,51,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,
-109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,
-114,101,51,68,80,114,111,106,0,1,1,0,0,18,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,
-114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,
-18,112,99,111,111,114,100,0,59,120,121,122,0,18,99,111,111,114,100,0,59,120,121,122,0,18,99,111,
-111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,
-118,101,99,52,95,116,101,120,98,51,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,
-101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,67,
-117,98,101,0,1,1,0,0,19,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,
-0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,
-100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,
-105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,99,117,98,101,0,18,95,95,114,101,116,86,97,108,0,
-0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,
-100,111,119,49,68,0,1,1,0,0,20,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,
-0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,
-111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,20,0,9,18,99,111,111,114,100,52,0,59,119,
-0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,98,49,100,0,18,95,95,114,101,116,86,97,
-108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,
-104,97,100,111,119,49,68,80,114,111,106,0,1,1,0,0,20,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,
-99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,
-100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,120,0,18,99,111,111,
-114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,122,0,18,99,111,111,114,100,0,59,122,0,
-20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,
-98,49,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,
-114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,50,68,0,1,1,0,0,21,0,115,97,109,112,108,
-101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,
-0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,
-100,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,
-101,120,98,50,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,
-111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,50,68,80,114,111,106,0,1,1,0,0,21,
-0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,
-0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,0,
-18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,
-114,100,0,59,122,0,18,99,111,111,114,100,0,59,122,0,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,
-98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,98,50,100,0,18,95,95,114,101,116,86,97,108,0,0,
-18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,9,0,0,100,70,100,
-120,0,1,1,0,0,9,0,112,0,0,0,1,4,118,101,99,52,95,100,100,120,0,18,95,95,114,101,116,86,97,108,0,59,
-120,0,0,18,112,0,59,120,120,120,120,0,0,0,0,1,90,95,0,0,10,0,0,100,70,100,120,0,1,1,0,0,10,0,112,0,
-0,0,1,4,118,101,99,52,95,100,100,120,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,112,0,59,
-120,121,121,121,0,0,0,0,1,90,95,0,0,11,0,0,100,70,100,120,0,1,1,0,0,11,0,112,0,0,0,1,4,118,101,99,
-52,95,100,100,120,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,112,0,59,120,121,122,
-122,0,0,0,0,1,90,95,0,0,12,0,0,100,70,100,120,0,1,1,0,0,12,0,112,0,0,0,1,4,118,101,99,52,95,100,
-100,120,0,18,95,95,114,101,116,86,97,108,0,0,18,112,0,0,0,0,1,90,95,0,0,9,0,0,100,70,100,121,0,1,1,
-0,0,9,0,112,0,0,0,1,4,118,101,99,52,95,100,100,121,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,
-18,112,0,59,120,120,120,120,0,0,0,0,1,90,95,0,0,10,0,0,100,70,100,121,0,1,1,0,0,10,0,112,0,0,0,1,4,
-118,101,99,52,95,100,100,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,112,0,59,120,121,
-121,121,0,0,0,0,1,90,95,0,0,11,0,0,100,70,100,121,0,1,1,0,0,11,0,112,0,0,0,1,4,118,101,99,52,95,
-100,100,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,112,0,59,120,121,122,122,0,0,
-0,0,1,90,95,0,0,12,0,0,100,70,100,121,0,1,1,0,0,12,0,112,0,0,0,1,4,118,101,99,52,95,100,100,121,0,
-18,95,95,114,101,116,86,97,108,0,0,18,112,0,0,0,0,1,90,95,0,0,9,0,0,102,119,105,100,116,104,0,1,1,
-0,0,9,0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,58,97,98,115,0,0,58,
-100,70,100,121,0,0,18,112,0,0,0,0,0,46,0,0,1,90,95,0,0,10,0,0,102,119,105,100,116,104,0,1,1,0,0,10,
-0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,58,97,98,115,0,0,58,100,70,
-100,121,0,0,18,112,0,0,0,0,0,46,0,0,1,90,95,0,0,11,0,0,102,119,105,100,116,104,0,1,1,0,0,11,0,112,
-0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,58,97,98,115,0,0,58,100,70,100,
-121,0,0,18,112,0,0,0,0,0,46,0,0,1,90,95,0,0,12,0,0,102,119,105,100,116,104,0,1,1,0,0,12,0,112,0,0,
-0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,58,97,98,115,0,0,58,100,70,100,121,0,
-0,18,112,0,0,0,0,0,46,0,0,0
+115,0,20,0,4,118,101,99,52,95,116,101,120,95,51,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,
+108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,
+101,120,116,117,114,101,51,68,80,114,111,106,0,1,1,0,0,18,0,115,97,109,112,108,101,114,0,0,1,1,0,0,
+12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,
+114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,122,0,18,99,111,111,114,100,0,59,120,121,
+122,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,
+115,0,20,0,4,118,101,99,52,95,116,101,120,95,51,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,
+108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,
+101,120,116,117,114,101,67,117,98,101,0,1,1,0,0,19,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,
+99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,
+52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,20,0,9,18,99,111,
+111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,99,117,98,101,
+0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,
+0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,0,1,1,0,0,20,0,115,97,109,112,108,101,114,0,
+0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,
+111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,20,
+0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,
+49,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,
+109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,
+49,68,80,114,111,106,0,1,1,0,0,20,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,
+0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,
+99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,119,0,49,
+20,0,9,18,112,99,111,111,114,100,0,59,122,0,18,99,111,111,114,100,0,59,122,0,20,0,9,18,112,99,111,
+111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,
+97,115,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,50,68,0,1,1,0,
+0,21,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,
+115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,
+121,122,0,18,99,111,111,114,100,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,
+0,4,118,101,99,52,95,116,101,120,95,50,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,
+114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,
+95,0,0,12,0,0,115,104,97,100,111,119,50,68,80,114,111,106,0,1,1,0,0,21,0,115,97,109,112,108,101,
+114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,
+112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
+120,121,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,122,0,18,99,
+111,111,114,100,0,59,122,0,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,
+118,101,99,52,95,116,101,120,95,50,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,
+101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,
+0,0,9,0,0,100,70,100,120,0,1,1,0,0,9,0,112,0,0,0,1,4,118,101,99,52,95,100,100,120,0,18,95,95,114,
+101,116,86,97,108,0,59,120,0,0,18,112,0,59,120,120,120,120,0,0,0,0,1,90,95,0,0,10,0,0,100,70,100,
+120,0,1,1,0,0,10,0,112,0,0,0,1,4,118,101,99,52,95,100,100,120,0,18,95,95,114,101,116,86,97,108,0,
+59,120,121,0,0,18,112,0,59,120,121,121,121,0,0,0,0,1,90,95,0,0,11,0,0,100,70,100,120,0,1,1,0,0,11,
+0,112,0,0,0,1,4,118,101,99,52,95,100,100,120,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,
+18,112,0,59,120,121,122,122,0,0,0,0,1,90,95,0,0,12,0,0,100,70,100,120,0,1,1,0,0,12,0,112,0,0,0,1,4,
+118,101,99,52,95,100,100,120,0,18,95,95,114,101,116,86,97,108,0,0,18,112,0,0,0,0,1,90,95,0,0,9,0,0,
+100,70,100,121,0,1,1,0,0,9,0,112,0,0,0,1,4,118,101,99,52,95,100,100,121,0,18,95,95,114,101,116,86,
+97,108,0,59,120,0,0,18,112,0,59,120,120,120,120,0,0,0,0,1,90,95,0,0,10,0,0,100,70,100,121,0,1,1,0,
+0,10,0,112,0,0,0,1,4,118,101,99,52,95,100,100,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,
+0,18,112,0,59,120,121,121,121,0,0,0,0,1,90,95,0,0,11,0,0,100,70,100,121,0,1,1,0,0,11,0,112,0,0,0,1,
+4,118,101,99,52,95,100,100,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,112,0,59,
+120,121,122,122,0,0,0,0,1,90,95,0,0,12,0,0,100,70,100,121,0,1,1,0,0,12,0,112,0,0,0,1,4,118,101,99,
+52,95,100,100,121,0,18,95,95,114,101,116,86,97,108,0,0,18,112,0,0,0,0,1,90,95,0,0,9,0,0,102,119,
+105,100,116,104,0,1,1,0,0,9,0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,
+0,58,97,98,115,0,0,58,100,70,100,121,0,0,18,112,0,0,0,0,0,46,0,0,1,90,95,0,0,10,0,0,102,119,105,
+100,116,104,0,1,1,0,0,10,0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,
+58,97,98,115,0,0,58,100,70,100,121,0,0,18,112,0,0,0,0,0,46,0,0,1,90,95,0,0,11,0,0,102,119,105,100,
+116,104,0,1,1,0,0,11,0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,58,97,
+98,115,0,0,58,100,70,100,121,0,0,18,112,0,0,0,0,0,46,0,0,1,90,95,0,0,12,0,0,102,119,105,100,116,
+104,0,1,1,0,0,12,0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,58,97,98,
+115,0,0,58,100,70,100,121,0,0,18,112,0,0,0,0,0,46,0,0,0
diff --git a/src/mesa/shader/slang/library/slang_version_syn.h b/src/mesa/shader/slang/library/slang_version_syn.h
deleted file mode 100644
index 3b94d85927..0000000000
--- a/src/mesa/shader/slang/library/slang_version_syn.h
+++ /dev/null
@@ -1,64 +0,0 @@
-".syntax version_directive;\n"
-"version_directive\n"
-" version_directive_1 .and .loop version_directive_2;\n"
-"version_directive_1\n"
-" prior_optional_spaces .and optional_version_directive .and .true .emit $;\n"
-"version_directive_2\n"
-" prior_optional_spaces .and version_directive_body .and .true .emit $;\n"
-"optional_version_directive\n"
-" version_directive_body .or .true .emit 10 .emit 1;\n"
-"version_directive_body\n"
-" '#' .and optional_space .and \"version\" .and space .and version_number .and optional_space .and\n"
-" new_line;\n"
-"version_number\n"
-" version_number_110;\n"
-"version_number_110\n"
-" leading_zeroes .and \"110\" .emit 10 .emit 1;\n"
-"leading_zeroes\n"
-" .loop zero;\n"
-"zero\n"
-" '0';\n"
-"space\n"
-" single_space .and .loop single_space;\n"
-"optional_space\n"
-" .loop single_space;\n"
-"single_space\n"
-" ' ' .or '\\t';\n"
-"prior_optional_spaces\n"
-" .loop prior_space;\n"
-"prior_space\n"
-" c_style_comment_block .or cpp_style_comment_block .or space .or new_line;\n"
-"c_style_comment_block\n"
-" '/' .and '*' .and c_style_comment_rest;\n"
-"c_style_comment_rest\n"
-" .loop c_style_comment_char_no_star .and c_style_comment_rest_1;\n"
-"c_style_comment_rest_1\n"
-" c_style_comment_end .or c_style_comment_rest_2;\n"
-"c_style_comment_rest_2\n"
-" '*' .and c_style_comment_rest;\n"
-"c_style_comment_char_no_star\n"
-" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"
-"c_style_comment_end\n"
-" '*' .and '/';\n"
-"cpp_style_comment_block\n"
-" '/' .and '/' .and cpp_style_comment_block_1;\n"
-"cpp_style_comment_block_1\n"
-" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n"
-"cpp_style_comment_block_2\n"
-" .loop cpp_style_comment_char .and new_line;\n"
-"cpp_style_comment_block_3\n"
-" .loop cpp_style_comment_char;\n"
-"cpp_style_comment_char\n"
-" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
-"new_line\n"
-" cr_lf .or lf_cr .or '\\n' .or '\\r';\n"
-"cr_lf\n"
-" '\\r' .and '\\n';\n"
-"lf_cr\n"
-" '\\n' .and '\\r';\n"
-".string __string_filter;\n"
-"__string_filter\n"
-" .loop __identifier_char;\n"
-"__identifier_char\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n"
-""
diff --git a/src/mesa/shader/slang/library/slang_vertex_builtin.gc b/src/mesa/shader/slang/library/slang_vertex_builtin.gc
index 17e86d9a0e..9ad5f35425 100644
--- a/src/mesa/shader/slang/library/slang_vertex_builtin.gc
+++ b/src/mesa/shader/slang/library/slang_vertex_builtin.gc
@@ -78,7 +78,7 @@ vec4 texture1DLod(const sampler1D sampler, const float coord, const float lod)
vec4 coord4;
coord4.x = coord;
coord4.w = lod;
- __asm vec4_texb1d __retVal, sampler, coord4;
+ __asm vec4_tex_1d_bias __retVal, sampler, coord4;
}
vec4 texture1DProjLod(const sampler1D sampler, const vec2 coord, const float lod)
@@ -86,7 +86,7 @@ vec4 texture1DProjLod(const sampler1D sampler, const vec2 coord, const float lod
vec4 pcoord;
pcoord.x = coord.x / coord.y;
pcoord.w = lod;
- __asm vec4_texb1d __retVal, sampler, pcoord;
+ __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
}
vec4 texture1DProjLod(const sampler1D sampler, const vec4 coord, const float lod)
@@ -94,7 +94,7 @@ vec4 texture1DProjLod(const sampler1D sampler, const vec4 coord, const float lod
vec4 pcoord;
pcoord.x = coord.x / coord.z;
pcoord.w = lod;
- __asm vec4_texb1d __retVal, sampler, pcoord;
+ __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
}
@@ -104,7 +104,7 @@ vec4 texture2DLod(const sampler2D sampler, const vec2 coord, const float lod)
vec4 coord4;
coord4.xy = coord.xy;
coord4.w = lod;
- __asm vec4_texb2d __retVal, sampler, coord4;
+ __asm vec4_tex_2d_bias __retVal, sampler, coord4;
}
vec4 texture2DProjLod(const sampler2D sampler, const vec3 coord, const float lod)
@@ -112,7 +112,7 @@ vec4 texture2DProjLod(const sampler2D sampler, const vec3 coord, const float lod
vec4 pcoord;
pcoord.xy = coord.xy / coord.z;
pcoord.w = lod;
- __asm vec4_texb2d __retVal, sampler, pcoord;
+ __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
}
vec4 texture2DProjLod(const sampler2D sampler, const vec4 coord, const float lod)
@@ -120,7 +120,7 @@ vec4 texture2DProjLod(const sampler2D sampler, const vec4 coord, const float lod
vec4 pcoord;
pcoord.xy = coord.xy / coord.z;
pcoord.w = lod;
- __asm vec4_texb2d __retVal, sampler, pcoord;
+ __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
}
@@ -129,16 +129,16 @@ vec4 texture3DLod(const sampler3D sampler, const vec3 coord, const float lod)
vec4 coord4;
coord4.xyz = coord.xyz;
coord4.w = lod;
- __asm vec4_texb3d __retVal, sampler, coord4;
+ __asm vec4_tex_3d_bias __retVal, sampler, coord4;
}
vec4 texture3DProjLod(const sampler3D sampler, const vec4 coord, const float lod)
{
- // do projection here (there's no vec4_texbp3d instruction)
+ // do projection here (there's no vec4_tex_3d_bias_proj instruction)
vec4 pcoord;
pcoord.xyz = coord.xyz / coord.w;
pcoord.w = lod;
- __asm vec4_texb3d __retVal, sampler, pcoord;
+ __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
}
@@ -147,7 +147,7 @@ vec4 textureCubeLod(const samplerCube sampler, const vec3 coord, const float lod
vec4 coord4;
coord4.xyz = coord;
coord4.w = lod;
- __asm vec4_texcube __retVal, sampler, coord4;
+ __asm vec4_tex_cube __retVal, sampler, coord4;
}
@@ -156,7 +156,7 @@ vec4 shadow1DLod(const sampler1DShadow sampler, const vec3 coord, const float lo
vec4 coord4;
coord4.xyz = coord;
coord4.w = lod;
- __asm vec4_texb1d __retVal, sampler, coord4;
+ __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
}
vec4 shadow1DProjLod(const sampler1DShadow sampler, const vec4 coord,
@@ -166,7 +166,7 @@ vec4 shadow1DProjLod(const sampler1DShadow sampler, const vec4 coord,
pcoord.x = coord.x / coord.w;
pcoord.z = coord.z;
pcoord.w = lod;
- __asm vec4_texb1d __retVal, sampler, pcoord;
+ __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
}
@@ -175,7 +175,7 @@ vec4 shadow2DLod(const sampler2DShadow sampler, const vec3 coord, const float lo
vec4 coord4;
coord4.xyz = coord;
coord4.w = lod;
- __asm vec4_texb2d __retVal, sampler, coord4;
+ __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
}
vec4 shadow2DProjLod(const sampler2DShadow sampler, const vec4 coord,
@@ -185,6 +185,6 @@ vec4 shadow2DProjLod(const sampler2DShadow sampler, const vec4 coord,
pcoord.xy = coord.xy / coord.w;
pcoord.z = coord.z;
pcoord.w = lod;
- __asm vec4_texb2d __retVal, sampler, pcoord;
+ __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
}
diff --git a/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h b/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h
index 2cb91bf268..e5a252b019 100644
--- a/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h
+++ b/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h
@@ -33,74 +33,77 @@
0,116,101,120,116,117,114,101,49,68,76,111,100,0,1,1,0,0,16,0,115,97,109,112,108,101,114,0,0,1,1,0,
0,9,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,
100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,0,18,99,111,111,114,100,0,20,0,9,18,99,111,111,
-114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,98,49,100,0,18,95,95,
-114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,
-95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,76,111,100,0,1,1,0,0,16,0,115,97,
-109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,
-95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,18,99,111,111,
-114,100,0,59,120,0,18,99,111,111,114,100,0,59,121,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,
-18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,98,49,100,0,18,95,95,114,101,116,86,97,108,0,
-0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,
-120,116,117,114,101,49,68,80,114,111,106,76,111,100,0,1,1,0,0,16,0,115,97,109,112,108,101,114,0,0,
-1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,
-111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,120,0,18,
-99,111,111,114,100,0,59,122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,
-4,118,101,99,52,95,116,101,120,98,49,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,
-108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,
-50,68,76,111,100,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,
-1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,
-114,100,52,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,20,0,9,18,99,111,111,114,100,52,0,
-59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,98,50,100,0,18,95,95,114,101,116,86,
-97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,
-116,101,120,116,117,114,101,50,68,80,114,111,106,76,111,100,0,1,1,0,0,17,0,115,97,109,112,108,101,
-114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,
-112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
-120,121,0,18,99,111,111,114,100,0,59,122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,
-111,100,0,20,0,4,118,101,99,52,95,116,101,120,98,50,100,0,18,95,95,114,101,116,86,97,108,0,0,18,
-115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,
-116,117,114,101,50,68,80,114,111,106,76,111,100,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,
-0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,
-111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,
-18,99,111,111,114,100,0,59,122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,
-20,0,4,118,101,99,52,95,116,101,120,98,50,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,
-112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,
-101,51,68,76,111,100,0,1,1,0,0,18,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,
-0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,
-111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,59,120,121,122,0,20,0,9,18,99,111,111,
-114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,98,51,100,0,18,95,95,
-114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,
-95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,80,114,111,106,76,111,100,0,1,1,0,0,18,0,115,97,
+114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,
+115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,
+52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,76,111,100,0,1,1,0,
+0,16,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,
+0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,
+18,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,121,0,49,20,0,9,18,112,99,111,111,114,
+100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,0,
+18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,
+0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,76,111,100,0,1,1,0,0,16,0,
+115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,
+3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,18,99,111,
+111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,
+119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,0,18,95,95,
+114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,
+95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,76,111,100,0,1,1,0,0,17,0,115,97,109,112,108,101,
+114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,
+99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,0,18,99,111,111,114,100,0,59,
+120,121,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,
+101,120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,
+114,111,106,76,111,100,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,
+100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,
+99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
+122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,
+101,120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,
+114,111,106,76,111,100,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,
+100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,
+99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
+122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,
+101,120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,76,
+111,100,0,1,1,0,0,18,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,
+9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,
+52,0,59,120,121,122,0,18,99,111,111,114,100,0,59,120,121,122,0,20,0,9,18,99,111,111,114,100,52,0,
+59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,51,100,95,98,105,97,115,0,18,95,
+95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,
+90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,80,114,111,106,76,111,100,0,1,1,0,0,18,0,115,97,
109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,
95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,122,0,18,99,
111,111,114,100,0,59,120,121,122,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,
-114,100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,98,51,100,0,18,95,95,114,
-101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,
-0,0,12,0,0,116,101,120,116,117,114,101,67,117,98,101,76,111,100,0,1,1,0,0,19,0,115,97,109,112,108,
-101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,
-1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,
-0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,
-99,117,98,101,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,
-114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,76,111,100,0,1,1,0,0,20,0,115,
+114,100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,51,100,95,98,105,97,115,
+0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,
+0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,67,117,98,101,76,111,100,0,1,1,0,0,19,0,115,
97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,
90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,
111,111,114,100,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,
-95,116,101,120,98,49,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,
-99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,80,114,111,106,76,
-111,100,0,1,1,0,0,20,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,
-9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,
-100,0,59,120,0,18,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,
-99,111,111,114,100,0,59,122,0,18,99,111,111,114,100,0,59,122,0,20,0,9,18,112,99,111,111,114,100,0,
-59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,98,49,100,0,18,95,95,114,101,116,86,
-97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,
-115,104,97,100,111,119,50,68,76,111,100,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,
-99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,
-0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,20,0,9,18,99,111,111,
-114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,98,50,100,0,18,95,95,
-114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,
-95,0,0,12,0,0,115,104,97,100,111,119,50,68,80,114,111,106,76,111,100,0,1,1,0,0,21,0,115,97,109,112,
-108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,
-12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,
-100,0,59,120,121,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,122,0,
-18,99,111,111,114,100,0,59,122,0,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,
-4,118,101,99,52,95,116,101,120,98,50,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,
+95,116,101,120,95,99,117,98,101,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,
+0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,76,111,100,0,
+1,1,0,0,20,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,
+111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,
+120,121,122,0,18,99,111,111,114,100,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,108,111,100,0,
+20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,
+95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,
+90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,80,114,111,106,76,111,100,0,1,1,0,0,20,0,115,97,109,
+112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,
+0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,18,99,111,111,114,
+100,0,59,120,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,122,0,18,
+99,111,111,114,100,0,59,122,0,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,4,
+118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,
+101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,
+0,0,12,0,0,115,104,97,100,111,119,50,68,76,111,100,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,0,1,
+1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,
+114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,20,0,9,18,
+99,111,111,114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,50,100,95,
+98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,
+101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,50,68,80,
+114,111,106,76,111,100,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,
+100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,
+99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
+119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,122,0,18,99,111,111,114,100,0,59,122,0,20,0,9,18,
+112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,50,100,
+95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,
108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,0
diff --git a/src/mesa/shader/slang/slang_builtin.c b/src/mesa/shader/slang/slang_builtin.c
index c0f4c79e13..bef0f85653 100644
--- a/src/mesa/shader/slang/slang_builtin.c
+++ b/src/mesa/shader/slang/slang_builtin.c
@@ -85,7 +85,7 @@ lookup_statevar(const char *var, GLint index1, GLint index2, const char *field,
{ "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
{ "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
- { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
{ NULL, 0, 0 }
};
@@ -111,10 +111,9 @@ lookup_statevar(const char *var, GLint index1, GLint index2, const char *field,
if (isMatrix) {
if (tokens[0] == STATE_TEXTURE_MATRIX) {
- if (index1 >= 0) {
- tokens[1] = index1; /* which texture matrix */
- index1 = 0; /* prevent extra addition at end of function */
- }
+ /* texture_matrix[index1][index2] */
+ tokens[1] = index1 >= 0 ? index1 : 0; /* which texture matrix */
+ index1 = index2; /* move matrix row value to index1 */
}
if (index1 < 0) {
/* index1 is unused: prevent extra addition at end of function */
@@ -437,7 +436,7 @@ emit_statevars(const char *name, int array_len,
struct gl_program_parameter_list *paramList)
{
if (type->type == SLANG_SPEC_ARRAY) {
- GLint i, pos;
+ GLint i, pos = -1;
assert(array_len > 0);
if (strcmp(name, "gl_ClipPlane") == 0) {
tokens[0] = STATE_CLIPPLANE;
@@ -457,28 +456,36 @@ emit_statevars(const char *name, int array_len,
tokens[0] = STATE_TEXENV_COLOR;
}
else if (strcmp(name, "gl_EyePlaneS") == 0) {
- tokens[0] = STATE_TEXGEN_EYE_S;
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_EYE_S;
}
else if (strcmp(name, "gl_EyePlaneT") == 0) {
- tokens[0] = STATE_TEXGEN_EYE_T;
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_EYE_T;
}
else if (strcmp(name, "gl_EyePlaneR") == 0) {
- tokens[0] = STATE_TEXGEN_EYE_R;
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_EYE_R;
}
else if (strcmp(name, "gl_EyePlaneQ") == 0) {
- tokens[0] = STATE_TEXGEN_EYE_Q;
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_EYE_Q;
}
else if (strcmp(name, "gl_ObjectPlaneS") == 0) {
- tokens[0] = STATE_TEXGEN_OBJECT_S;
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_OBJECT_S;
}
else if (strcmp(name, "gl_ObjectPlaneT") == 0) {
- tokens[0] = STATE_TEXGEN_OBJECT_T;
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_OBJECT_T;
}
else if (strcmp(name, "gl_ObjectPlaneR") == 0) {
- tokens[0] = STATE_TEXGEN_OBJECT_R;
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_OBJECT_R;
}
else if (strcmp(name, "gl_ObjectPlaneQ") == 0) {
- tokens[0] = STATE_TEXGEN_OBJECT_Q;
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_OBJECT_Q;
}
else {
return -1; /* invalid array name */
@@ -494,7 +501,7 @@ emit_statevars(const char *name, int array_len,
}
else if (type->type == SLANG_SPEC_STRUCT) {
const slang_variable_scope *fields = type->_struct->fields;
- GLuint i, pos;
+ GLuint i, pos = 0;
for (i = 0; i < fields->num_variables; i++) {
const slang_variable *var = fields->variables[i];
GLint p = emit_statevars(var->a_name, 0, &var->type.specifier,
@@ -674,7 +681,9 @@ _slang_alloc_statevar(slang_ir_node *n,
if (n->Opcode == IR_ELEMENT) {
/* XXX can only handle constant indexes for now */
if (n->Children[1]->Opcode == IR_FLOAT) {
- index2 = (GLint) n->Children[1]->Value[0];
+ /* two-dimensional array index: mat[i][j] */
+ index2 = index1;
+ index1 = (GLint) n->Children[1]->Value[0];
}
else {
*direct = GL_FALSE;
@@ -701,3 +710,186 @@ _slang_alloc_statevar(slang_ir_node *n,
*direct = GL_FALSE;
return alloc_state_var_array(n->Var, paramList);
}
+
+
+
+
+#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
+
+
+/** Predefined shader inputs */
+struct input_info
+{
+ const char *Name;
+ GLuint Attrib;
+ GLenum Type;
+ GLuint Swizzle;
+};
+
+/** Predefined vertex shader inputs/attributes */
+static const struct input_info vertInputs[] = {
+ { "gl_Vertex", VERT_ATTRIB_POS, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_Normal", VERT_ATTRIB_NORMAL, GL_FLOAT_VEC3, SWIZZLE_NOOP },
+ { "gl_Color", VERT_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_FogCoord", VERT_ATTRIB_FOG, GL_FLOAT, SWIZZLE_XXXX },
+ { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { NULL, 0, SWIZZLE_NOOP }
+};
+
+/** Predefined fragment shader inputs */
+static const struct input_info fragInputs[] = {
+ { "gl_FragCoord", FRAG_ATTRIB_WPOS, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_Color", FRAG_ATTRIB_COL0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_SecondaryColor", FRAG_ATTRIB_COL1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_TexCoord", FRAG_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ /* note: we're packing several quantities into the fogcoord vector */
+ { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, GL_FLOAT, SWIZZLE_XXXX },
+ { "gl_FrontFacing", FRAG_ATTRIB_FACE, GL_FLOAT, SWIZZLE_XXXX },
+ { "gl_PointCoord", FRAG_ATTRIB_PNTC, GL_FLOAT_VEC2, SWIZZLE_XYZW },
+ { NULL, 0, SWIZZLE_NOOP }
+};
+
+
+/**
+ * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to
+ * a vertex or fragment program input variable. Return -1 if the input
+ * name is invalid.
+ * XXX return size too
+ */
+GLint
+_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut)
+{
+ const struct input_info *inputs;
+ GLuint i;
+
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ inputs = vertInputs;
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ inputs = fragInputs;
+ break;
+ /* XXX geom program */
+ default:
+ _mesa_problem(NULL, "bad target in _slang_input_index");
+ return -1;
+ }
+
+ ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */
+
+ for (i = 0; inputs[i].Name; i++) {
+ if (strcmp(inputs[i].Name, name) == 0) {
+ /* found */
+ *swizzleOut = inputs[i].Swizzle;
+ return inputs[i].Attrib;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Return name of the given vertex attribute (VERT_ATTRIB_x).
+ */
+const char *
+_slang_vert_attrib_name(GLuint attrib)
+{
+ GLuint i;
+ assert(attrib < VERT_ATTRIB_GENERIC0);
+ for (i = 0; vertInputs[i].Name; i++) {
+ if (vertInputs[i].Attrib == attrib)
+ return vertInputs[i].Name;
+ }
+ return NULL;
+}
+
+
+/**
+ * Return type (GL_FLOAT, GL_FLOAT_VEC2, etc) of the given vertex
+ * attribute (VERT_ATTRIB_x).
+ */
+GLenum
+_slang_vert_attrib_type(GLuint attrib)
+{
+ GLuint i;
+ assert(attrib < VERT_ATTRIB_GENERIC0);
+ for (i = 0; vertInputs[i].Name; i++) {
+ if (vertInputs[i].Attrib == attrib)
+ return vertInputs[i].Type;
+ }
+ return GL_NONE;
+}
+
+
+
+
+
+/** Predefined shader output info */
+struct output_info
+{
+ const char *Name;
+ GLuint Attrib;
+};
+
+/** Predefined vertex shader outputs */
+static const struct output_info vertOutputs[] = {
+ { "gl_Position", VERT_RESULT_HPOS },
+ { "gl_FrontColor", VERT_RESULT_COL0 },
+ { "gl_BackColor", VERT_RESULT_BFC0 },
+ { "gl_FrontSecondaryColor", VERT_RESULT_COL1 },
+ { "gl_BackSecondaryColor", VERT_RESULT_BFC1 },
+ { "gl_TexCoord", VERT_RESULT_TEX0 },
+ { "gl_FogFragCoord", VERT_RESULT_FOGC },
+ { "gl_PointSize", VERT_RESULT_PSIZ },
+ { NULL, 0 }
+};
+
+/** Predefined fragment shader outputs */
+static const struct output_info fragOutputs[] = {
+ { "gl_FragColor", FRAG_RESULT_COLOR },
+ { "gl_FragDepth", FRAG_RESULT_DEPTH },
+ { "gl_FragData", FRAG_RESULT_DATA0 },
+ { NULL, 0 }
+};
+
+
+/**
+ * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to
+ * a vertex or fragment program output variable. Return -1 for an invalid
+ * output name.
+ */
+GLint
+_slang_output_index(const char *name, GLenum target)
+{
+ const struct output_info *outputs;
+ GLuint i;
+
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ outputs = vertOutputs;
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ outputs = fragOutputs;
+ break;
+ /* XXX geom program */
+ default:
+ _mesa_problem(NULL, "bad target in _slang_output_index");
+ return -1;
+ }
+
+ for (i = 0; outputs[i].Name; i++) {
+ if (strcmp(outputs[i].Name, name) == 0) {
+ /* found */
+ return outputs[i].Attrib;
+ }
+ }
+ return -1;
+}
diff --git a/src/mesa/shader/slang/slang_builtin.h b/src/mesa/shader/slang/slang_builtin.h
index 7f6fe80fcc..f814d11ac7 100644
--- a/src/mesa/shader/slang/slang_builtin.h
+++ b/src/mesa/shader/slang/slang_builtin.h
@@ -37,4 +37,18 @@ _slang_alloc_statevar(slang_ir_node *n,
GLboolean *direct);
+extern GLint
+_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut);
+
+extern GLint
+_slang_output_index(const char *name, GLenum target);
+
+
+extern const char *
+_slang_vert_attrib_name(GLuint attrib);
+
+extern GLenum
+_slang_vert_attrib_type(GLuint attrib);
+
+
#endif /* SLANG_BUILTIN_H */
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 11340d26e2..349f432dec 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -46,6 +46,7 @@
#include "shader/prog_print.h"
#include "shader/prog_statevars.h"
#include "slang_typeinfo.h"
+#include "slang_builtin.h"
#include "slang_codegen.h"
#include "slang_compile.h"
#include "slang_label.h"
@@ -75,6 +76,11 @@ const GLuint MAX_FOR_LOOP_UNROLL_COMPLEXITY = 256;
static slang_ir_node *
_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
+static void
+slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
+ GLuint substCount, slang_variable **substOld,
+ slang_operation **substNew, GLboolean isLHS);
+
/**
* Retrieves type information about an operation.
@@ -296,46 +302,6 @@ _slang_array_size(GLint elemSize, GLint arrayLen)
}
-
-/**
- * Establish the binding between a slang_ir_node and a slang_variable.
- * Then, allocate/attach a slang_ir_storage object to the IR node if needed.
- * The IR node must be a IR_VAR or IR_VAR_DECL node.
- * \param n the IR node
- * \param var the variable to associate with the IR node
- */
-static void
-_slang_attach_storage(slang_ir_node *n, slang_variable *var)
-{
- assert(n);
- assert(var);
- assert(n->Opcode == IR_VAR || n->Opcode == IR_VAR_DECL);
- assert(!n->Var || n->Var == var);
-
- n->Var = var;
-
- if (!n->Store) {
- /* need to setup storage */
- if (n->Var && n->Var->store) {
- /* node storage info = var storage info */
- n->Store = n->Var->store;
- }
- else {
- /* alloc new storage info */
- n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -7, -5);
-#if 0
- printf("%s var=%s Store=%p Size=%d\n", __FUNCTION__,
- (char*) var->a_name,
- (void*) n->Store, n->Store->Size);
-#endif
- if (n->Var)
- n->Var->store = n->Store;
- assert(n->Var->store);
- }
- }
-}
-
-
/**
* Return the TEXTURE_*_INDEX value that corresponds to a sampler type,
* or -1 if the type is not a sampler.
@@ -366,109 +332,67 @@ sampler_to_texture_index(const slang_type_specifier_type type)
}
-#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
+/** helper to build a SLANG_OPER_IDENTIFIER node */
+static void
+slang_operation_identifier(slang_operation *oper,
+ slang_assemble_ctx *A,
+ const char *name)
+{
+ oper->type = SLANG_OPER_IDENTIFIER;
+ oper->a_id = slang_atom_pool_atom(A->atoms, name);
+}
+
/**
- * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to
- * a vertex or fragment program input variable. Return -1 if the input
- * name is invalid.
- * XXX return size too
+ * Called when we begin code/IR generation for a new while/do/for loop.
*/
-static GLint
-_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut)
+static void
+push_loop(slang_assemble_ctx *A, slang_operation *loopOper, slang_ir_node *loopIR)
{
- struct input_info {
- const char *Name;
- GLuint Attrib;
- GLuint Swizzle;
- };
- static const struct input_info vertInputs[] = {
- { "gl_Vertex", VERT_ATTRIB_POS, SWIZZLE_NOOP },
- { "gl_Normal", VERT_ATTRIB_NORMAL, SWIZZLE_NOOP },
- { "gl_Color", VERT_ATTRIB_COLOR0, SWIZZLE_NOOP },
- { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, SWIZZLE_NOOP },
- { "gl_FogCoord", VERT_ATTRIB_FOG, SWIZZLE_XXXX },
- { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, SWIZZLE_NOOP },
- { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, SWIZZLE_NOOP },
- { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, SWIZZLE_NOOP },
- { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, SWIZZLE_NOOP },
- { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, SWIZZLE_NOOP },
- { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, SWIZZLE_NOOP },
- { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, SWIZZLE_NOOP },
- { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, SWIZZLE_NOOP },
- { NULL, 0, SWIZZLE_NOOP }
- };
- static const struct input_info fragInputs[] = {
- { "gl_FragCoord", FRAG_ATTRIB_WPOS, SWIZZLE_NOOP },
- { "gl_Color", FRAG_ATTRIB_COL0, SWIZZLE_NOOP },
- { "gl_SecondaryColor", FRAG_ATTRIB_COL1, SWIZZLE_NOOP },
- { "gl_TexCoord", FRAG_ATTRIB_TEX0, SWIZZLE_NOOP },
- /* note: we're packing several quantities into the fogcoord vector */
- { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, SWIZZLE_XXXX },
- { "gl_FrontFacing", FRAG_ATTRIB_FOGC, SWIZZLE_YYYY }, /*XXX*/
- { "gl_PointCoord", FRAG_ATTRIB_FOGC, SWIZZLE_ZWWW },
- { NULL, 0, SWIZZLE_NOOP }
- };
- GLuint i;
- const struct input_info *inputs
- = (target == GL_VERTEX_PROGRAM_ARB) ? vertInputs : fragInputs;
+ A->LoopOperStack[A->LoopDepth] = loopOper;
+ A->LoopIRStack[A->LoopDepth] = loopIR;
+ A->LoopDepth++;
+}
- ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */
- for (i = 0; inputs[i].Name; i++) {
- if (strcmp(inputs[i].Name, name) == 0) {
- /* found */
- *swizzleOut = inputs[i].Swizzle;
- return inputs[i].Attrib;
- }
- }
- return -1;
+/**
+ * Called when we end code/IR generation for a new while/do/for loop.
+ */
+static void
+pop_loop(slang_assemble_ctx *A)
+{
+ assert(A->LoopDepth > 0);
+ A->LoopDepth--;
}
/**
- * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to
- * a vertex or fragment program output variable. Return -1 for an invalid
- * output name.
+ * Return pointer to slang_operation for the loop we're currently inside,
+ * or NULL if not in a loop.
*/
-static GLint
-_slang_output_index(const char *name, GLenum target)
+static const slang_operation *
+current_loop_oper(const slang_assemble_ctx *A)
{
- struct output_info {
- const char *Name;
- GLuint Attrib;
- };
- static const struct output_info vertOutputs[] = {
- { "gl_Position", VERT_RESULT_HPOS },
- { "gl_FrontColor", VERT_RESULT_COL0 },
- { "gl_BackColor", VERT_RESULT_BFC0 },
- { "gl_FrontSecondaryColor", VERT_RESULT_COL1 },
- { "gl_BackSecondaryColor", VERT_RESULT_BFC1 },
- { "gl_TexCoord", VERT_RESULT_TEX0 },
- { "gl_FogFragCoord", VERT_RESULT_FOGC },
- { "gl_PointSize", VERT_RESULT_PSIZ },
- { NULL, 0 }
- };
- static const struct output_info fragOutputs[] = {
- { "gl_FragColor", FRAG_RESULT_COLR },
- { "gl_FragDepth", FRAG_RESULT_DEPR },
- { "gl_FragData", FRAG_RESULT_DATA0 },
- { NULL, 0 }
- };
- GLuint i;
- const struct output_info *outputs
- = (target == GL_VERTEX_PROGRAM_ARB) ? vertOutputs : fragOutputs;
-
- for (i = 0; outputs[i].Name; i++) {
- if (strcmp(outputs[i].Name, name) == 0) {
- /* found */
- return outputs[i].Attrib;
- }
- }
- return -1;
+ if (A->LoopDepth > 0)
+ return A->LoopOperStack[A->LoopDepth - 1];
+ else
+ return NULL;
}
+/**
+ * Return pointer to slang_ir_node for the loop we're currently inside,
+ * or NULL if not in a loop.
+ */
+static slang_ir_node *
+current_loop_ir(const slang_assemble_ctx *A)
+{
+ if (A->LoopDepth > 0)
+ return A->LoopIRStack[A->LoopDepth - 1];
+ else
+ return NULL;
+}
+
/**********************************************************************/
@@ -516,18 +440,28 @@ static slang_asm_info AsmInfo[] = {
/* float binary op */
{ "float_power", IR_POW, 1, 2 },
/* texture / sampler */
- { "vec4_tex1d", IR_TEX, 1, 2 },
- { "vec4_texb1d", IR_TEXB, 1, 2 }, /* 1d w/ bias */
- { "vec4_texp1d", IR_TEXP, 1, 2 }, /* 1d w/ projection */
- { "vec4_tex2d", IR_TEX, 1, 2 },
- { "vec4_texb2d", IR_TEXB, 1, 2 }, /* 2d w/ bias */
- { "vec4_texp2d", IR_TEXP, 1, 2 }, /* 2d w/ projection */
- { "vec4_tex3d", IR_TEX, 1, 2 },
- { "vec4_texb3d", IR_TEXB, 1, 2 }, /* 3d w/ bias */
- { "vec4_texp3d", IR_TEXP, 1, 2 }, /* 3d w/ projection */
- { "vec4_texcube", IR_TEX, 1, 2 }, /* cubemap */
- { "vec4_tex_rect", IR_TEX, 1, 2 }, /* rectangle */
- { "vec4_texp_rect", IR_TEX, 1, 2 },/* rectangle w/ projection */
+ { "vec4_tex_1d", IR_TEX, 1, 2 },
+ { "vec4_tex_1d_bias", IR_TEXB, 1, 2 }, /* 1d w/ bias */
+ { "vec4_tex_1d_proj", IR_TEXP, 1, 2 }, /* 1d w/ projection */
+ { "vec4_tex_2d", IR_TEX, 1, 2 },
+ { "vec4_tex_2d_bias", IR_TEXB, 1, 2 }, /* 2d w/ bias */
+ { "vec4_tex_2d_proj", IR_TEXP, 1, 2 }, /* 2d w/ projection */
+ { "vec4_tex_3d", IR_TEX, 1, 2 },
+ { "vec4_tex_3d_bias", IR_TEXB, 1, 2 }, /* 3d w/ bias */
+ { "vec4_tex_3d_proj", IR_TEXP, 1, 2 }, /* 3d w/ projection */
+ { "vec4_tex_cube", IR_TEX, 1, 2 }, /* cubemap */
+ { "vec4_tex_rect", IR_TEX, 1, 2 }, /* rectangle */
+ { "vec4_tex_rect_bias", IR_TEX, 1, 2 }, /* rectangle w/ projection */
+
+ /* texture / sampler but with shadow comparison */
+ { "vec4_tex_1d_shadow", IR_TEX_SH, 1, 2 },
+ { "vec4_tex_1d_bias_shadow", IR_TEXB_SH, 1, 2 },
+ { "vec4_tex_1d_proj_shadow", IR_TEXP_SH, 1, 2 },
+ { "vec4_tex_2d_shadow", IR_TEX_SH, 1, 2 },
+ { "vec4_tex_2d_bias_shadow", IR_TEXB_SH, 1, 2 },
+ { "vec4_tex_2d_proj_shadow", IR_TEXP_SH, 1, 2 },
+ { "vec4_tex_rect_shadow", IR_TEX_SH, 1, 2 },
+ { "vec4_tex_rect_proj_shadow", IR_TEXP_SH, 1, 2 },
/* unary op */
{ "ivec4_to_vec4", IR_I_TO_F, 1, 1 }, /* int[4] to float[4] */
@@ -666,7 +600,7 @@ new_break(slang_ir_node *loopNode)
assert(loopNode);
assert(loopNode->Opcode == IR_LOOP);
if (n) {
- /* insert this node at head of linked list */
+ /* insert this node at head of linked list of cont/break instructions */
n->List = loopNode->List;
loopNode->List = n;
}
@@ -678,14 +612,15 @@ new_break(slang_ir_node *loopNode)
* Make new IR_BREAK_IF_TRUE.
*/
static slang_ir_node *
-new_break_if_true(slang_ir_node *loopNode, slang_ir_node *cond)
+new_break_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
{
+ slang_ir_node *loopNode = current_loop_ir(A);
slang_ir_node *n;
assert(loopNode);
assert(loopNode->Opcode == IR_LOOP);
n = new_node1(IR_BREAK_IF_TRUE, cond);
if (n) {
- /* insert this node at head of linked list */
+ /* insert this node at head of linked list of cont/break instructions */
n->List = loopNode->List;
loopNode->List = n;
}
@@ -697,14 +632,16 @@ new_break_if_true(slang_ir_node *loopNode, slang_ir_node *cond)
* Make new IR_CONT_IF_TRUE node.
*/
static slang_ir_node *
-new_cont_if_true(slang_ir_node *loopNode, slang_ir_node *cond)
+new_cont_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
{
+ slang_ir_node *loopNode = current_loop_ir(A);
slang_ir_node *n;
assert(loopNode);
assert(loopNode->Opcode == IR_LOOP);
n = new_node1(IR_CONT_IF_TRUE, cond);
if (n) {
- /* insert this node at head of linked list */
+ n->Parent = loopNode; /* pointer to containing loop */
+ /* insert this node at head of linked list of cont/break instructions */
n->List = loopNode->List;
loopNode->List = n;
}
@@ -735,7 +672,14 @@ new_var(slang_assemble_ctx *A, slang_variable *var)
{
slang_ir_node *n = new_node0(IR_VAR);
if (n) {
- _slang_attach_storage(n, var);
+ ASSERT(var);
+ ASSERT(var->store);
+ ASSERT(!n->Store);
+ ASSERT(!n->Var);
+
+ /* Set IR node's Var and Store pointers */
+ n->Var = var;
+ n->Store = var->store;
}
return n;
}
@@ -772,6 +716,7 @@ _slang_is_noop(const slang_operation *oper)
/**
* Recursively search tree for a node of the given type.
*/
+#if 0
static slang_operation *
_slang_find_node_type(slang_operation *oper, slang_operation_type type)
{
@@ -785,13 +730,14 @@ _slang_find_node_type(slang_operation *oper, slang_operation_type type)
}
return NULL;
}
+#endif
/**
* Count the number of operations of the given time rooted at 'oper'.
*/
static GLuint
-_slang_count_node_type(slang_operation *oper, slang_operation_type type)
+_slang_count_node_type(const slang_operation *oper, slang_operation_type type)
{
GLuint i, count = 0;
if (oper->type == type) {
@@ -845,6 +791,37 @@ _slang_is_tail_return(const slang_operation *oper)
}
+/**
+ * Generate a variable declaration opeartion.
+ * I.e.: generate AST code for "bool flag = false;"
+ */
+static void
+slang_generate_declaration(slang_assemble_ctx *A,
+ slang_variable_scope *scope,
+ slang_operation *decl,
+ slang_type_specifier_type type,
+ const char *name,
+ GLint initValue)
+{
+ slang_variable *var;
+
+ assert(type == SLANG_SPEC_BOOL ||
+ type == SLANG_SPEC_INT);
+
+ decl->type = SLANG_OPER_VARIABLE_DECL;
+
+ var = slang_variable_scope_grow(scope);
+
+ slang_fully_specified_type_construct(&var->type);
+
+ var->type.specifier.type = type;
+ var->a_name = slang_atom_pool_atom(A->atoms, name);
+ decl->a_id = var->a_name;
+ var->initializer = slang_operation_new(1);
+ slang_operation_literal_bool(var->initializer, initValue);
+}
+
+
static void
slang_resolve_variable(slang_operation *oper)
{
@@ -855,6 +832,159 @@ slang_resolve_variable(slang_operation *oper)
/**
+ * Rewrite AST code for "return expression;".
+ *
+ * We return values from functions by assinging the returned value to
+ * the hidden __retVal variable which is an extra 'out' parameter we add
+ * to the function signature.
+ * This code basically converts "return expr;" into "__retVal = expr; return;"
+ *
+ * \return the new AST code.
+ */
+static slang_operation *
+gen_return_with_expression(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *blockOper, *assignOper;
+
+ assert(oper->type == SLANG_OPER_RETURN);
+
+ if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
+ slang_info_log_error(A->log, "illegal return expression");
+ return NULL;
+ }
+
+ blockOper = slang_operation_new(1);
+ blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+ blockOper->locals->outer_scope = oper->locals->outer_scope;
+ slang_operation_add_children(blockOper, 2);
+
+ if (A->UseReturnFlag) {
+ /* Emit:
+ * {
+ * if (__notRetFlag)
+ * __retVal = expr;
+ * __notRetFlag = 0;
+ * }
+ */
+ {
+ slang_operation *ifOper = slang_oper_child(blockOper, 0);
+ ifOper->type = SLANG_OPER_IF;
+ slang_operation_add_children(ifOper, 3);
+ {
+ slang_operation *cond = slang_oper_child(ifOper, 0);
+ cond->type = SLANG_OPER_IDENTIFIER;
+ cond->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+ }
+ {
+ slang_operation *elseOper = slang_oper_child(ifOper, 2);
+ elseOper->type = SLANG_OPER_VOID;
+ }
+ assignOper = slang_oper_child(ifOper, 1);
+ }
+ {
+ slang_operation *setOper = slang_oper_child(blockOper, 1);
+ setOper->type = SLANG_OPER_ASSIGN;
+ slang_operation_add_children(setOper, 2);
+ {
+ slang_operation *lhs = slang_oper_child(setOper, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+ }
+ {
+ slang_operation *rhs = slang_oper_child(setOper, 1);
+ slang_operation_literal_bool(rhs, GL_FALSE);
+ }
+ }
+ }
+ else {
+ /* Emit:
+ * {
+ * __retVal = expr;
+ * return_inlined;
+ * }
+ */
+ assignOper = slang_oper_child(blockOper, 0);
+ {
+ slang_operation *returnOper = slang_oper_child(blockOper, 1);
+ returnOper->type = SLANG_OPER_RETURN_INLINED;
+ assert(returnOper->num_children == 0);
+ }
+ }
+
+ /* __retVal = expression; */
+ assignOper->type = SLANG_OPER_ASSIGN;
+ slang_operation_add_children(assignOper, 2);
+ {
+ slang_operation *lhs = slang_oper_child(assignOper, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = slang_atom_pool_atom(A->atoms, "__retVal");
+ }
+ {
+ slang_operation *rhs = slang_oper_child(assignOper, 1);
+ slang_operation_copy(rhs, &oper->children[0]);
+ }
+
+ ///blockOper->locals->outer_scope = oper->locals->outer_scope;
+
+ /*slang_print_tree(blockOper, 0);*/
+
+ return blockOper;
+}
+
+
+/**
+ * Rewrite AST code for "return;" (no expression).
+ */
+static slang_operation *
+gen_return_without_expression(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *newRet;
+
+ assert(oper->type == SLANG_OPER_RETURN);
+
+ if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
+ slang_info_log_error(A->log, "return statement requires an expression");
+ return NULL;
+ }
+
+ if (A->UseReturnFlag) {
+ /* Emit:
+ * __notRetFlag = 0;
+ */
+ {
+ newRet = slang_operation_new(1);
+ newRet->locals->outer_scope = oper->locals->outer_scope;
+ newRet->type = SLANG_OPER_ASSIGN;
+ slang_operation_add_children(newRet, 2);
+ {
+ slang_operation *lhs = slang_oper_child(newRet, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+ }
+ {
+ slang_operation *rhs = slang_oper_child(newRet, 1);
+ slang_operation_literal_bool(rhs, GL_FALSE);
+ }
+ }
+ }
+ else {
+ /* Emit:
+ * return_inlined;
+ */
+ newRet = slang_operation_new(1);
+ newRet->locals->outer_scope = oper->locals->outer_scope;
+ newRet->type = SLANG_OPER_RETURN_INLINED;
+ }
+
+ /*slang_print_tree(newRet, 0);*/
+
+ return newRet;
+}
+
+
+
+
+/**
* Replace particular variables (SLANG_OPER_IDENTIFIER) with new expressions.
*/
static void
@@ -889,7 +1019,8 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
GLuint i;
v = _slang_variable_locate(oper->locals, id, GL_TRUE);
if (!v) {
- _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id);
+ if (_mesa_strcmp((char *) oper->a_id, "__notRetFlag"))
+ _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id);
return;
}
@@ -919,62 +1050,24 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
break;
case SLANG_OPER_RETURN:
- /* do return replacement here too */
- assert(oper->num_children == 0 || oper->num_children == 1);
- if (oper->num_children == 1 && !_slang_is_noop(&oper->children[0])) {
- /* replace:
- * return expr;
- * with:
- * __retVal = expr;
- * return;
- * then do substitutions on the assignment.
- */
- slang_operation *blockOper, *assignOper, *returnOper;
+ {
+ slang_operation *newReturn;
+ /* generate new 'return' code' */
+ if (slang_oper_child(oper, 0)->type == SLANG_OPER_VOID)
+ newReturn = gen_return_without_expression(A, oper);
+ else
+ newReturn = gen_return_with_expression(A, oper);
- /* check if function actually has a return type */
- assert(A->CurFunction);
- if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
- slang_info_log_error(A->log, "illegal return expression");
+ if (!newReturn)
return;
- }
-
- blockOper = slang_operation_new(1);
- blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
- blockOper->num_children = 2;
- blockOper->locals->outer_scope = oper->locals->outer_scope;
- blockOper->children = slang_operation_new(2);
- assignOper = blockOper->children + 0;
- returnOper = blockOper->children + 1;
-
- assignOper->type = SLANG_OPER_ASSIGN;
- assignOper->num_children = 2;
- assignOper->locals->outer_scope = blockOper->locals;
- assignOper->children = slang_operation_new(2);
- assignOper->children[0].type = SLANG_OPER_IDENTIFIER;
- assignOper->children[0].a_id = slang_atom_pool_atom(A->atoms, "__retVal");
- assignOper->children[0].locals->outer_scope = assignOper->locals;
-
- slang_operation_copy(&assignOper->children[1],
- &oper->children[0]);
-
- returnOper->type = SLANG_OPER_RETURN; /* return w/ no value */
- assert(returnOper->num_children == 0);
- /* do substitutions on the "__retVal = expr" sub-tree */
- slang_substitute(A, assignOper,
+ /* do substitutions on the new 'return' code */
+ slang_substitute(A, newReturn,
substCount, substOld, substNew, GL_FALSE);
- /* install new code */
- slang_operation_copy(oper, blockOper);
- slang_operation_destruct(blockOper);
- }
- else {
- /* check if return value was expected */
- assert(A->CurFunction);
- if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
- slang_info_log_error(A->log, "return statement requires an expression");
- return;
- }
+ /* install new 'return' code */
+ slang_operation_copy(oper, newReturn);
+ slang_operation_destruct(newReturn);
}
break;
@@ -1222,8 +1315,9 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
}
else if (p->type.qualifier == SLANG_QUAL_CONST) {
/* a constant input param */
- if (args[i].type == SLANG_OPER_IDENTIFIER ||
- args[i].type == SLANG_OPER_LITERAL_FLOAT) {
+ if (args[i].type == SLANG_OPER_IDENTIFIER ||
+ args[i].type == SLANG_OPER_LITERAL_FLOAT ||
+ args[i].type == SLANG_OPER_SUBSCRIPT) {
/* replace all occurances of this parameter variable with the
* actual argument variable or a literal.
*/
@@ -1369,12 +1463,74 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
}
+/**
+ * Insert declaration for "bool __notRetFlag" in given block operation.
+ * This is used when we can't emit "early" return statements in subroutines.
+ */
+static void
+declare_return_flag(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *decl;
+
+ assert(oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+ oper->type == SLANG_OPER_SEQUENCE);
+
+ decl = slang_operation_insert_child(oper, 1);
+
+ slang_generate_declaration(A, oper->locals, decl,
+ SLANG_SPEC_BOOL, "__notRetFlag", GL_TRUE);
+
+ /*slang_print_tree(oper, 0);*/
+}
+
+
+/**
+ * Recursively replace instances of the old node type with the new type.
+ */
+static void
+replace_node_type(slang_operation *oper, slang_operation_type oldType,
+ slang_operation_type newType)
+{
+ GLuint i;
+
+ if (oper->type == oldType)
+ oper->type = newType;
+
+ for (i = 0; i < slang_oper_num_children(oper); i++) {
+ replace_node_type(slang_oper_child(oper, i), oldType, newType);
+ }
+}
+
+
+
+/**
+ * Test if the given function body has an "early return". That is, there's
+ * a 'return' statement that's not the very last instruction in the body.
+ */
+static GLboolean
+has_early_return(const slang_operation *funcBody)
+{
+ GLuint retCount = _slang_count_node_type(funcBody, SLANG_OPER_RETURN);
+ if (retCount == 0)
+ return GL_FALSE;
+ else if (retCount == 1 && _slang_is_tail_return(funcBody))
+ return GL_FALSE;
+ else
+ return GL_TRUE;
+}
+
+
+/**
+ * Emit IR code for a function call. This does one of two things:
+ * 1. Inline the function's code
+ * 2. Create an IR for the function's body and create a real call to it.
+ */
static slang_ir_node *
_slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
slang_operation *oper, slang_operation *dest)
{
slang_ir_node *n;
- slang_operation *inlined;
+ slang_operation *instance;
slang_label *prevFuncEndLabel;
char name[200];
@@ -1383,9 +1539,14 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
A->curFuncEndLabel = _slang_label_new(name);
assert(A->curFuncEndLabel);
+ /*
+ * 'instance' is basically a copy of the function's body with various
+ * transformations.
+ */
+
if (slang_is_asm_function(fun) && !dest) {
/* assemble assembly function - tree style */
- inlined = slang_inline_asm_function(A, fun, oper);
+ instance = slang_inline_asm_function(A, fun, oper);
}
else {
/* non-assembly function */
@@ -1394,65 +1555,82 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
* 1. insert the inline code
* 2. Generate a call to the "inline" code as a subroutine
*/
+ const GLboolean earlyReturn = has_early_return(fun->body);
+ if (earlyReturn && !A->EmitContReturn) {
+ A->UseReturnFlag = GL_TRUE;
+ }
- slang_operation *ret = NULL;
-
- inlined = slang_inline_function_call(A, fun, oper, dest);
- if (!inlined)
+ instance = slang_inline_function_call(A, fun, oper, dest);
+ if (!instance)
return NULL;
- ret = _slang_find_node_type(inlined, SLANG_OPER_RETURN);
- if (ret) {
- /* check if this is a "tail" return */
- if (_slang_count_node_type(inlined, SLANG_OPER_RETURN) == 1 &&
- _slang_is_tail_return(inlined)) {
- /* The only RETURN is the last stmt in the function, no-op it
- * and inline the function body.
+ if (earlyReturn) {
+ /* The function we're calling has one or more 'return' statements
+ * that prevent us from inlining the function's code.
+ *
+ * In this case, change the function's body type from
+ * SLANG_OPER_BLOCK_NEW_SCOPE to SLANG_OPER_NON_INLINED_CALL.
+ * During code emit this will result in a true subroutine call.
+ *
+ * Also, convert SLANG_OPER_RETURN_INLINED nodes to SLANG_OPER_RETURN.
+ */
+ slang_operation *callOper;
+
+ assert(instance->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+ instance->type == SLANG_OPER_SEQUENCE);
+
+ if (_slang_function_has_return_value(fun) && !dest) {
+ assert(instance->children[0].type == SLANG_OPER_VARIABLE_DECL);
+ assert(instance->children[2].type == SLANG_OPER_IDENTIFIER);
+ callOper = &instance->children[1];
+ }
+ else {
+ callOper = instance;
+ }
+
+ if (A->UseReturnFlag) {
+ /* Early returns not supported. Create a _returnFlag variable
+ * that's set upon 'return' and tested elsewhere to no-op any
+ * remaining instructions in the subroutine.
*/
- ret->type = SLANG_OPER_NONE;
+ assert(callOper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+ callOper->type == SLANG_OPER_SEQUENCE);
+ declare_return_flag(A, callOper);
}
else {
- slang_operation *callOper;
- /* The function we're calling has one or more 'return' statements.
- * So, we can't truly inline this function because we need to
- * implement 'return' with RET (and CAL).
- * Nevertheless, we performed "inlining" to make a new instance
- * of the function body to deal with static register allocation.
- *
- * XXX check if there's one 'return' and if it's the very last
- * statement in the function - we can optimize that case.
+ /* We can emit real 'return' statements. If we generated any
+ * 'inline return' statements during function instantiation,
+ * change them back to regular 'return' statements.
*/
- assert(inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
- inlined->type == SLANG_OPER_SEQUENCE);
-
- if (_slang_function_has_return_value(fun) && !dest) {
- assert(inlined->children[0].type == SLANG_OPER_VARIABLE_DECL);
- assert(inlined->children[2].type == SLANG_OPER_IDENTIFIER);
- callOper = &inlined->children[1];
- }
- else {
- callOper = inlined;
- }
- callOper->type = SLANG_OPER_NON_INLINED_CALL;
- callOper->fun = fun;
- callOper->label = _slang_label_new_unique((char*) fun->header.a_name);
+ replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
+ SLANG_OPER_RETURN);
}
+
+ callOper->type = SLANG_OPER_NON_INLINED_CALL;
+ callOper->fun = fun;
+ callOper->label = _slang_label_new_unique((char*) fun->header.a_name);
+ }
+ else {
+ /* If there are any 'return' statements remaining, they're at the
+ * very end of the function and can effectively become no-ops.
+ */
+ replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
+ SLANG_OPER_VOID);
}
}
- if (!inlined)
+ if (!instance)
return NULL;
- /* Replace the function call with the inlined block (or new CALL stmt) */
+ /* Replace the function call with the instance block (or new CALL stmt) */
slang_operation_destruct(oper);
- *oper = *inlined;
- _slang_free(inlined);
+ *oper = *instance;
+ _slang_free(instance);
#if 0
- assert(inlined->locals);
- printf("*** Inlined code for call to %s:\n",
- (char*) fun->header.a_name);
+ assert(instance->locals);
+ printf("*** Inlined code for call to %s:\n", (char*) fun->header.a_name);
slang_print_tree(oper, 10);
printf("\n");
#endif
@@ -1462,6 +1640,14 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
/*_slang_label_delete(A->curFuncEndLabel);*/
A->curFuncEndLabel = prevFuncEndLabel;
+ if (A->pragmas->Debug) {
+ char s[1000];
+ _mesa_snprintf(s, sizeof(s), "Call/inline %s()", (char *) fun->header.a_name);
+ n->Comment = _slang_strdup(s);
+ }
+
+ A->UseReturnFlag = GL_FALSE;
+
return n;
}
@@ -2216,12 +2402,13 @@ _slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
name);
return NULL;
}
+
if (!fun->body) {
- slang_info_log_error(A->log,
- "Function '%s' prototyped but not defined. "
- "Separate compilation units not supported.",
- name);
- return NULL;
+ /* The function body may be in another compilation unit.
+ * We'll try concatenating the shaders and recompile at link time.
+ */
+ A->UnresolvedRefs = GL_TRUE;
+ return new_node1(IR_NOP, NULL);
}
/* type checking to be sure function's return type matches 'dest' type */
@@ -2353,19 +2540,252 @@ _slang_is_boolean(slang_assemble_ctx *A, slang_operation *oper)
/**
+ * Check if a loop contains a 'continue' statement.
+ * Stop looking if we find a nested loop.
+ */
+static GLboolean
+_slang_loop_contains_continue(const slang_operation *oper)
+{
+ switch (oper->type) {
+ case SLANG_OPER_CONTINUE:
+ return GL_TRUE;
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_WHILE:
+ /* stop upon finding a nested loop */
+ return GL_FALSE;
+ default:
+ /* recurse */
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ const slang_operation *child = slang_oper_child_const(oper, i);
+ if (_slang_loop_contains_continue(child))
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Check if a loop contains a 'continue' or 'break' statement.
+ * Stop looking if we find a nested loop.
+ */
+static GLboolean
+_slang_loop_contains_continue_or_break(const slang_operation *oper)
+{
+ switch (oper->type) {
+ case SLANG_OPER_CONTINUE:
+ case SLANG_OPER_BREAK:
+ return GL_TRUE;
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_WHILE:
+ /* stop upon finding a nested loop */
+ return GL_FALSE;
+ default:
+ /* recurse */
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ const slang_operation *child = slang_oper_child_const(oper, i);
+ if (_slang_loop_contains_continue_or_break(child))
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Replace 'break' and 'continue' statements inside a do and while loops.
+ * This is a recursive helper function used by
+ * _slang_gen_do/while_without_continue().
+ */
+static void
+replace_break_and_cont(slang_assemble_ctx *A, slang_operation *oper)
+{
+ switch (oper->type) {
+ case SLANG_OPER_BREAK:
+ /* replace 'break' with "_notBreakFlag = false; break" */
+ {
+ slang_operation *block = oper;
+ block->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ slang_operation_add_children(block, 2);
+ {
+ slang_operation *assign = slang_oper_child(block, 0);
+ assign->type = SLANG_OPER_ASSIGN;
+ slang_operation_add_children(assign, 2);
+ {
+ slang_operation *lhs = slang_oper_child(assign, 0);
+ slang_operation_identifier(lhs, A, "_notBreakFlag");
+ }
+ {
+ slang_operation *rhs = slang_oper_child(assign, 1);
+ slang_operation_literal_bool(rhs, GL_FALSE);
+ }
+ }
+ {
+ slang_operation *brk = slang_oper_child(block, 1);
+ brk->type = SLANG_OPER_BREAK;
+ assert(!brk->children);
+ }
+ }
+ break;
+ case SLANG_OPER_CONTINUE:
+ /* convert continue into a break */
+ oper->type = SLANG_OPER_BREAK;
+ break;
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_WHILE:
+ /* stop upon finding a nested loop */
+ break;
+ default:
+ /* recurse */
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ replace_break_and_cont(A, slang_oper_child(oper, i));
+ }
+ }
+ }
+}
+
+
+/**
+ * Transform a while-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ *
+ * while (LOOPCOND) {
+ * A;
+ * if (IFCOND)
+ * continue;
+ * B;
+ * break;
+ * C;
+ * }
+ *
+ * After:
+ *
+ * {
+ * bool _notBreakFlag = 1;
+ * while (_notBreakFlag && LOOPCOND) {
+ * do {
+ * A;
+ * if (IFCOND) {
+ * break; // was continue
+ * }
+ * B;
+ * _notBreakFlag = 0; // was
+ * break; // break
+ * C;
+ * } while (0)
+ * }
+ * }
+ */
+static slang_ir_node *
+_slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *top;
+ slang_operation *innerBody;
+
+ assert(oper->type == SLANG_OPER_WHILE);
+
+ top = slang_operation_new(1);
+ top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ top->locals->outer_scope = oper->locals->outer_scope;
+ slang_operation_add_children(top, 2);
+
+ /* declare: bool _notBreakFlag = true */
+ {
+ slang_operation *condDecl = slang_oper_child(top, 0);
+ slang_generate_declaration(A, top->locals, condDecl,
+ SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
+ }
+
+ /* build outer while-loop: while (_notBreakFlag && LOOPCOND) { ... } */
+ {
+ slang_operation *outerWhile = slang_oper_child(top, 1);
+ outerWhile->type = SLANG_OPER_WHILE;
+ slang_operation_add_children(outerWhile, 2);
+
+ /* _notBreakFlag && LOOPCOND */
+ {
+ slang_operation *cond = slang_oper_child(outerWhile, 0);
+ cond->type = SLANG_OPER_LOGICALAND;
+ slang_operation_add_children(cond, 2);
+ {
+ slang_operation *notBreak = slang_oper_child(cond, 0);
+ slang_operation_identifier(notBreak, A, "_notBreakFlag");
+ }
+ {
+ slang_operation *origCond = slang_oper_child(cond, 1);
+ slang_operation_copy(origCond, slang_oper_child(oper, 0));
+ }
+ }
+
+ /* inner loop */
+ {
+ slang_operation *innerDo = slang_oper_child(outerWhile, 1);
+ innerDo->type = SLANG_OPER_DO;
+ slang_operation_add_children(innerDo, 2);
+
+ /* copy original do-loop body into inner do-loop's body */
+ innerBody = slang_oper_child(innerDo, 0);
+ slang_operation_copy(innerBody, slang_oper_child(oper, 1));
+ innerBody->locals->outer_scope = innerDo->locals;
+
+ /* inner do-loop's condition is constant/false */
+ {
+ slang_operation *constFalse = slang_oper_child(innerDo, 1);
+ slang_operation_literal_bool(constFalse, GL_FALSE);
+ }
+ }
+ }
+
+ /* Finally, in innerBody,
+ * replace "break" with "_notBreakFlag = 0; break"
+ * replace "continue" with "break"
+ */
+ replace_break_and_cont(A, innerBody);
+
+ /*slang_print_tree(top, 0);*/
+
+ return _slang_gen_operation(A, top);
+
+ return NULL;
+}
+
+
+/**
* Generate loop code using high-level IR_LOOP instruction
*/
static slang_ir_node *
-_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
{
/*
* LOOP:
* BREAK if !expr (child[0])
* body code (child[1])
*/
- slang_ir_node *prevLoop, *loop, *breakIf, *body;
+ slang_ir_node *loop, *breakIf, *body;
GLboolean isConst, constTrue;
+ if (!A->EmitContReturn) {
+ /* We don't want to emit CONT instructions. If this while-loop has
+ * a continue, translate it away.
+ */
+ if (_slang_loop_contains_continue(slang_oper_child(oper, 1))) {
+ return _slang_gen_while_without_continue(A, oper);
+ }
+ }
+
/* type-check expression */
if (!_slang_is_boolean(A, &oper->children[0])) {
slang_info_log_error(A->log, "scalar/boolean expression expected for 'while'");
@@ -2380,11 +2800,11 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
return new_node0(IR_NOP);
}
+ /* Begin new loop */
loop = new_loop(NULL);
- /* save old, push new loop */
- prevLoop = A->CurLoop;
- A->CurLoop = loop;
+ /* save loop state */
+ push_loop(A, oper, loop);
if (isConst && constTrue) {
/* while(nonzero constant), no conditional break */
@@ -2393,7 +2813,7 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
else {
slang_ir_node *cond
= new_cond(new_not(_slang_gen_operation(A, &oper->children[0])));
- breakIf = new_break_if_true(A->CurLoop, cond);
+ breakIf = new_break_if_true(A, cond);
}
body = _slang_gen_operation(A, &oper->children[1]);
loop->Children[0] = new_seq(breakIf, body);
@@ -2402,23 +2822,128 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
/* loop->List is head of linked list of break/continue nodes */
if (!loop->List && isConst && constTrue) {
/* infinite loop detected */
- A->CurLoop = prevLoop; /* clean-up */
+ pop_loop(A);
slang_info_log_error(A->log, "Infinite loop detected!");
return NULL;
}
- /* pop loop, restore prev */
- A->CurLoop = prevLoop;
+ /* restore loop state */
+ pop_loop(A);
return loop;
}
/**
+ * Transform a do-while-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ *
+ * do {
+ * A;
+ * if (IFCOND)
+ * continue;
+ * B;
+ * break;
+ * C;
+ * } while (LOOPCOND);
+ *
+ * After:
+ *
+ * {
+ * bool _notBreakFlag = 1;
+ * do {
+ * do {
+ * A;
+ * if (IFCOND) {
+ * break; // was continue
+ * }
+ * B;
+ * _notBreakFlag = 0; // was
+ * break; // break
+ * C;
+ * } while (0)
+ * } while (_notBreakFlag && LOOPCOND);
+ * }
+ */
+static slang_ir_node *
+_slang_gen_do_without_continue(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *top;
+ slang_operation *innerBody;
+
+ assert(oper->type == SLANG_OPER_DO);
+
+ top = slang_operation_new(1);
+ top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ top->locals->outer_scope = oper->locals->outer_scope;
+ slang_operation_add_children(top, 2);
+
+ /* declare: bool _notBreakFlag = true */
+ {
+ slang_operation *condDecl = slang_oper_child(top, 0);
+ slang_generate_declaration(A, top->locals, condDecl,
+ SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
+ }
+
+ /* build outer do-loop: do { ... } while (_notBreakFlag && LOOPCOND) */
+ {
+ slang_operation *outerDo = slang_oper_child(top, 1);
+ outerDo->type = SLANG_OPER_DO;
+ slang_operation_add_children(outerDo, 2);
+
+ /* inner do-loop */
+ {
+ slang_operation *innerDo = slang_oper_child(outerDo, 0);
+ innerDo->type = SLANG_OPER_DO;
+ slang_operation_add_children(innerDo, 2);
+
+ /* copy original do-loop body into inner do-loop's body */
+ innerBody = slang_oper_child(innerDo, 0);
+ slang_operation_copy(innerBody, slang_oper_child(oper, 0));
+ innerBody->locals->outer_scope = innerDo->locals;
+
+ /* inner do-loop's condition is constant/false */
+ {
+ slang_operation *constFalse = slang_oper_child(innerDo, 1);
+ slang_operation_literal_bool(constFalse, GL_FALSE);
+ }
+ }
+
+ /* _notBreakFlag && LOOPCOND */
+ {
+ slang_operation *cond = slang_oper_child(outerDo, 1);
+ cond->type = SLANG_OPER_LOGICALAND;
+ slang_operation_add_children(cond, 2);
+ {
+ slang_operation *notBreak = slang_oper_child(cond, 0);
+ slang_operation_identifier(notBreak, A, "_notBreakFlag");
+ }
+ {
+ slang_operation *origCond = slang_oper_child(cond, 1);
+ slang_operation_copy(origCond, slang_oper_child(oper, 1));
+ }
+ }
+ }
+
+ /* Finally, in innerBody,
+ * replace "break" with "_notBreakFlag = 0; break"
+ * replace "continue" with "break"
+ */
+ replace_break_and_cont(A, innerBody);
+
+ /*slang_print_tree(top, 0);*/
+
+ return _slang_gen_operation(A, top);
+}
+
+
+/**
* Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
*/
static slang_ir_node *
-_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
{
/*
* LOOP:
@@ -2426,9 +2951,18 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
* tail code:
* BREAK if !expr (child[1])
*/
- slang_ir_node *prevLoop, *loop;
+ slang_ir_node *loop;
GLboolean isConst, constTrue;
+ if (!A->EmitContReturn) {
+ /* We don't want to emit CONT instructions. If this do-loop has
+ * a continue, translate it away.
+ */
+ if (_slang_loop_contains_continue(slang_oper_child(oper, 0))) {
+ return _slang_gen_do_without_continue(A, oper);
+ }
+ }
+
/* type-check expression */
if (!_slang_is_boolean(A, &oper->children[1])) {
slang_info_log_error(A->log, "scalar/boolean expression expected for 'do/while'");
@@ -2437,9 +2971,8 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
loop = new_loop(NULL);
- /* save old, push new loop */
- prevLoop = A->CurLoop;
- A->CurLoop = loop;
+ /* save loop state */
+ push_loop(A, oper, loop);
/* loop body: */
loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
@@ -2453,13 +2986,13 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
else {
slang_ir_node *cond
= new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
- loop->Children[1] = new_break_if_true(A->CurLoop, cond);
+ loop->Children[1] = new_break_if_true(A, cond);
}
/* XXX we should do infinite loop detection, as above */
- /* pop loop, restore prev */
- A->CurLoop = prevLoop;
+ /* restore loop state */
+ pop_loop(A);
return loop;
}
@@ -2501,9 +3034,14 @@ _slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
const char *varName;
slang_atom varId;
- assert(oper->type == SLANG_OPER_FOR);
+ if (oper->type != SLANG_OPER_FOR)
+ return GL_FALSE;
+
assert(oper->num_children == 4);
+ if (_slang_loop_contains_continue_or_break(slang_oper_child_const(oper, 3)))
+ return GL_FALSE;
+
/* children[0] must be either "int i=constant" or "i=constant" */
if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
slang_variable *var;
@@ -2665,6 +3203,9 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
/* do IR codegen for body */
n = _slang_gen_operation(A, body);
+ if (!n)
+ return NULL;
+
root = new_seq(root, n);
slang_operation_delete(body);
@@ -2675,19 +3216,182 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
/**
+ * Replace 'continue' statement with 'break' inside a for-loop.
+ * This is a recursive helper function used by _slang_gen_for_without_continue().
+ */
+static void
+replace_continue_with_break(slang_assemble_ctx *A, slang_operation *oper)
+{
+ switch (oper->type) {
+ case SLANG_OPER_CONTINUE:
+ oper->type = SLANG_OPER_BREAK;
+ break;
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_WHILE:
+ /* stop upon finding a nested loop */
+ break;
+ default:
+ /* recurse */
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ replace_continue_with_break(A, slang_oper_child(oper, i));
+ }
+ }
+ }
+}
+
+
+/**
+ * Transform a for-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ *
+ * for (INIT; LOOPCOND; INCR) {
+ * A;
+ * if (IFCOND) {
+ * continue;
+ * }
+ * B;
+ * }
+ *
+ * After:
+ *
+ * {
+ * bool _condFlag = 1;
+ * for (INIT; _condFlag; ) {
+ * for ( ; _condFlag = LOOPCOND; INCR) {
+ * A;
+ * if (IFCOND) {
+ * break;
+ * }
+ * B;
+ * }
+ * if (_condFlag)
+ * INCR;
+ * }
+ * }
+ */
+static slang_ir_node *
+_slang_gen_for_without_continue(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *top;
+ slang_operation *outerFor, *innerFor, *init, *cond, *incr;
+ slang_operation *lhs, *rhs;
+
+ assert(oper->type == SLANG_OPER_FOR);
+
+ top = slang_operation_new(1);
+ top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ top->locals->outer_scope = oper->locals->outer_scope;
+ slang_operation_add_children(top, 2);
+
+ /* declare: bool _condFlag = true */
+ {
+ slang_operation *condDecl = slang_oper_child(top, 0);
+ slang_generate_declaration(A, top->locals, condDecl,
+ SLANG_SPEC_BOOL, "_condFlag", GL_TRUE);
+ }
+
+ /* build outer loop: for (INIT; _condFlag; ) { */
+ outerFor = slang_oper_child(top, 1);
+ outerFor->type = SLANG_OPER_FOR;
+ slang_operation_add_children(outerFor, 4);
+
+ init = slang_oper_child(outerFor, 0);
+ slang_operation_copy(init, slang_oper_child(oper, 0));
+
+ cond = slang_oper_child(outerFor, 1);
+ cond->type = SLANG_OPER_IDENTIFIER;
+ cond->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
+
+ incr = slang_oper_child(outerFor, 2);
+ incr->type = SLANG_OPER_VOID;
+
+ /* body of the outer loop */
+ {
+ slang_operation *block = slang_oper_child(outerFor, 3);
+
+ slang_operation_add_children(block, 2);
+ block->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+
+ /* build inner loop: for ( ; _condFlag = LOOPCOND; INCR) { */
+ {
+ innerFor = slang_oper_child(block, 0);
+
+ /* make copy of orig loop */
+ slang_operation_copy(innerFor, oper);
+ assert(innerFor->type == SLANG_OPER_FOR);
+ innerFor->locals->outer_scope = block->locals;
+
+ init = slang_oper_child(innerFor, 0);
+ init->type = SLANG_OPER_VOID; /* leak? */
+
+ cond = slang_oper_child(innerFor, 1);
+ slang_operation_destruct(cond);
+ cond->type = SLANG_OPER_ASSIGN;
+ cond->locals = _slang_variable_scope_new(innerFor->locals);
+ slang_operation_add_children(cond, 2);
+
+ lhs = slang_oper_child(cond, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
+
+ rhs = slang_oper_child(cond, 1);
+ slang_operation_copy(rhs, slang_oper_child(oper, 1));
+ }
+
+ /* if (_condFlag) INCR; */
+ {
+ slang_operation *ifop = slang_oper_child(block, 1);
+ ifop->type = SLANG_OPER_IF;
+ slang_operation_add_children(ifop, 2);
+
+ /* re-use cond node build above */
+ slang_operation_copy(slang_oper_child(ifop, 0), cond);
+
+ /* incr node from original for-loop operation */
+ slang_operation_copy(slang_oper_child(ifop, 1),
+ slang_oper_child(oper, 2));
+ }
+
+ /* finally, replace "continue" with "break" in the inner for-loop */
+ replace_continue_with_break(A, slang_oper_child(innerFor, 3));
+ }
+
+ return _slang_gen_operation(A, top);
+}
+
+
+
+/**
* Generate IR for a for-loop. Unrolling will be done when possible.
*/
static slang_ir_node *
-_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_for(slang_assemble_ctx * A, slang_operation *oper)
{
- GLboolean unroll = _slang_can_unroll_for_loop(A, oper);
+ GLboolean unroll;
+ if (!A->EmitContReturn) {
+ /* We don't want to emit CONT instructions. If this for-loop has
+ * a continue, translate it away.
+ */
+ if (_slang_loop_contains_continue(slang_oper_child(oper, 3))) {
+ return _slang_gen_for_without_continue(A, oper);
+ }
+ }
+
+ unroll = _slang_can_unroll_for_loop(A, oper);
if (unroll) {
slang_ir_node *code = _slang_unroll_for_loop(A, oper);
if (code)
return code;
}
+ assert(oper->type == SLANG_OPER_FOR);
+
/* conventional for-loop code generation */
{
/*
@@ -2698,24 +3402,23 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
* tail code:
* incr code (child[2]) // XXX continue here
*/
- slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr;
+ slang_ir_node *loop, *cond, *breakIf, *body, *init, *incr;
init = _slang_gen_operation(A, &oper->children[0]);
loop = new_loop(NULL);
- /* save old, push new loop */
- prevLoop = A->CurLoop;
- A->CurLoop = loop;
+ /* save loop state */
+ push_loop(A, oper, loop);
cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
- breakIf = new_break_if_true(A->CurLoop, cond);
+ breakIf = new_break_if_true(A, cond);
body = _slang_gen_operation(A, &oper->children[3]);
incr = _slang_gen_operation(A, &oper->children[2]);
loop->Children[0] = new_seq(breakIf, body);
loop->Children[1] = incr; /* tail code */
- /* pop loop, restore prev */
- A->CurLoop = prevLoop;
+ /* restore loop state */
+ pop_loop(A);
return new_seq(init, loop);
}
@@ -2725,18 +3428,22 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
static slang_ir_node *
_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper)
{
- slang_ir_node *n, *loopNode;
+ slang_ir_node *n, *cont, *incr = NULL, *loopNode;
+
assert(oper->type == SLANG_OPER_CONTINUE);
- loopNode = A->CurLoop;
+ loopNode = current_loop_ir(A);
assert(loopNode);
assert(loopNode->Opcode == IR_LOOP);
- n = new_node0(IR_CONT);
- if (n) {
- n->Parent = loopNode;
- /* insert this node at head of linked list */
- n->List = loopNode->List;
- loopNode->List = n;
+
+ cont = new_node0(IR_CONT);
+ if (cont) {
+ cont->Parent = loopNode;
+ /* insert this node at head of linked list of cont/break instructions */
+ cont->List = loopNode->List;
+ loopNode->List = cont;
}
+
+ n = new_seq(incr, cont);
return n;
}
@@ -2806,13 +3513,15 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)
&& !haveElseClause) {
/* Special case: generate a conditional break */
- ifBody = new_break_if_true(A->CurLoop, cond);
+ ifBody = new_break_if_true(A, cond);
return ifBody;
}
else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
- && !haveElseClause) {
- /* Special case: generate a conditional break */
- ifBody = new_cont_if_true(A->CurLoop, cond);
+ && !haveElseClause
+ && current_loop_oper(A)
+ && current_loop_oper(A)->type != SLANG_OPER_FOR) {
+ /* Special case: generate a conditional continue */
+ ifBody = new_cont_if_true(A, cond);
return ifBody;
}
else {
@@ -2988,7 +3697,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
slang_ir_node *varDecl, *n;
slang_ir_storage *store;
GLint arrayLen, size, totalSize; /* if array then totalSize > size */
- enum register_file file;
+ gl_register_file file;
/*assert(!var->declared);*/
var->declared = GL_TRUE;
@@ -3004,7 +3713,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
file = PROGRAM_TEMPORARY;
}
- totalSize = size = _slang_sizeof_type_specifier(&var->type.specifier);
+ size = _slang_sizeof_type_specifier(&var->type.specifier);
if (size <= 0) {
slang_info_log_error(A->log, "invalid declaration for '%s'", varName);
return NULL;
@@ -3018,22 +3727,23 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
if (!varDecl)
return NULL;
- _slang_attach_storage(varDecl, var); /* undefined storage at first */
- assert(var->store);
- assert(varDecl->Store == var->store);
- assert(varDecl->Store);
- assert(varDecl->Store->Index < 0);
- store = var->store;
+ /* Allocate slang_ir_storage for this variable if needed.
+ * Note that we may not actually allocate a constant or temporary register
+ * until later.
+ */
+ if (!var->store) {
+ GLint index = -7; /* TBD / unknown */
+ var->store = _slang_new_ir_storage(file, index, totalSize);
+ if (!var->store)
+ return NULL; /* out of memory */
+ }
- assert(store == varDecl->Store);
+ /* set the IR node's Var and Store pointers */
+ varDecl->Var = var;
+ varDecl->Store = var->store;
- /* Fill in storage fields which we now know. store->Index/Swizzle may be
- * set for some cases below. Otherwise, store->Index/Swizzle will be set
- * during code emit.
- */
- store->File = file;
- store->Size = totalSize;
+ store = var->store;
/* if there's an initializer, generate IR for the expression */
if (initializer) {
@@ -3222,14 +3932,11 @@ _slang_gen_logical_and(slang_assemble_ctx *A, slang_operation *oper)
select = slang_operation_new(1);
select->type = SLANG_OPER_SELECT;
- select->num_children = 3;
- select->children = slang_operation_new(3);
+ slang_operation_add_children(select, 3);
- slang_operation_copy(&select->children[0], &oper->children[0]);
- slang_operation_copy(&select->children[1], &oper->children[1]);
- select->children[2].type = SLANG_OPER_LITERAL_BOOL;
- ASSIGN_4V(select->children[2].literal, 0, 0, 0, 0); /* false */
- select->children[2].literal_size = 1;
+ slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
+ slang_operation_copy(slang_oper_child(select, 1), &oper->children[1]);
+ slang_operation_literal_bool(slang_oper_child(select, 2), GL_FALSE);
n = _slang_gen_select(A, select);
return n;
@@ -3248,14 +3955,11 @@ _slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper)
select = slang_operation_new(1);
select->type = SLANG_OPER_SELECT;
- select->num_children = 3;
- select->children = slang_operation_new(3);
+ slang_operation_add_children(select, 3);
- slang_operation_copy(&select->children[0], &oper->children[0]);
- select->children[1].type = SLANG_OPER_LITERAL_BOOL;
- ASSIGN_4V(select->children[1].literal, 1, 1, 1, 1); /* true */
- select->children[1].literal_size = 1;
- slang_operation_copy(&select->children[2], &oper->children[1]);
+ slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
+ slang_operation_literal_bool(slang_oper_child(select, 1), GL_TRUE);
+ slang_operation_copy(slang_oper_child(select, 2), &oper->children[1]);
n = _slang_gen_select(A, select);
return n;
@@ -3268,70 +3972,8 @@ _slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper)
static slang_ir_node *
_slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
{
- const GLboolean haveReturnValue
- = (oper->num_children == 1 && oper->children[0].type != SLANG_OPER_VOID);
-
- /* error checking */
- assert(A->CurFunction);
- if (haveReturnValue &&
- A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
- slang_info_log_error(A->log, "illegal return expression");
- return NULL;
- }
- else if (!haveReturnValue &&
- A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
- slang_info_log_error(A->log, "return statement requires an expression");
- return NULL;
- }
-
- if (!haveReturnValue) {
- return new_return(A->curFuncEndLabel);
- }
- else {
- /*
- * Convert from:
- * return expr;
- * To:
- * __retVal = expr;
- * return; // goto __endOfFunction
- */
- slang_operation *assign;
- slang_atom a_retVal;
- slang_ir_node *n;
-
- a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
- assert(a_retVal);
-
-#if 1 /* DEBUG */
- {
- slang_variable *v =
- _slang_variable_locate(oper->locals, a_retVal, GL_TRUE);
- if (!v) {
- /* trying to return a value in a void-valued function */
- return NULL;
- }
- }
-#endif
-
- assign = slang_operation_new(1);
- assign->type = SLANG_OPER_ASSIGN;
- assign->num_children = 2;
- assign->children = slang_operation_new(2);
- /* lhs (__retVal) */
- assign->children[0].type = SLANG_OPER_IDENTIFIER;
- assign->children[0].a_id = a_retVal;
- assign->children[0].locals->outer_scope = assign->locals;
- /* rhs (expr) */
- /* XXX we might be able to avoid this copy someday */
- slang_operation_copy(&assign->children[1], &oper->children[0]);
-
- /* assemble the new code */
- n = new_seq(_slang_gen_operation(A, assign),
- new_return(A->curFuncEndLabel));
-
- slang_operation_delete(assign);
- return n;
- }
+ assert(oper->type == SLANG_OPER_RETURN);
+ return new_return(A->curFuncEndLabel);
}
@@ -3437,6 +4079,7 @@ _slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
assert(oper->type == SLANG_OPER_VARIABLE_DECL);
assert(oper->num_children <= 1);
+
/* lookup the variable by name */
var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
if (!var)
@@ -3592,6 +4235,9 @@ root_swizzle(const slang_ir_storage *st)
static slang_ir_node *
_slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
{
+ slang_operation *pred = NULL;
+ slang_ir_node *n = NULL;
+
if (oper->children[0].type == SLANG_OPER_IDENTIFIER) {
/* Check that var is writeable */
slang_variable *var
@@ -3612,6 +4258,17 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
(char *) oper->children[0].a_id);
return NULL;
}
+
+ /* check if we need to predicate this assignment based on __notRetFlag */
+ if ((var->is_global ||
+ var->type.qualifier == SLANG_QUAL_OUT ||
+ var->type.qualifier == SLANG_QUAL_INOUT) && A->UseReturnFlag) {
+ /* create predicate, used below */
+ pred = slang_operation_new(1);
+ pred->type = SLANG_OPER_IDENTIFIER;
+ pred->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+ pred->locals->outer_scope = oper->locals->outer_scope;
+ }
}
if (oper->children[0].type == SLANG_OPER_IDENTIFIER &&
@@ -3623,14 +4280,12 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
* cases such as "v.x = f();" - would help with typical vertex
* transformation.
*/
- slang_ir_node *n;
n = _slang_gen_function_call_name(A,
(const char *) oper->children[1].a_id,
&oper->children[1], &oper->children[0]);
- return n;
}
else {
- slang_ir_node *n, *lhs, *rhs;
+ slang_ir_node *lhs, *rhs;
/* lhs and rhs type checking */
if (!_slang_assignment_compatible(A,
@@ -3662,7 +4317,7 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
if (lhs && rhs) {
/* convert lhs swizzle into writemask */
const GLuint swizzle = root_swizzle(lhs->Store);
- GLuint writemask, newSwizzle;
+ GLuint writemask, newSwizzle = 0x0;
if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) {
/* Non-simple writemask, need to swizzle right hand side in
* order to put components into the right place.
@@ -3670,12 +4325,21 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
rhs = _slang_gen_swizzle(rhs, newSwizzle);
}
n = new_node2(IR_COPY, lhs, rhs);
- return n;
}
else {
return NULL;
}
}
+
+ if (n && pred) {
+ /* predicate the assignment code on __notRetFlag */
+ slang_ir_node *top, *cond;
+
+ cond = _slang_gen_operation(A, pred);
+ top = new_if(cond, n, NULL);
+ return top;
+ }
+ return n;
}
@@ -4028,13 +4692,13 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
case SLANG_OPER_WHILE:
return _slang_gen_while(A, oper);
case SLANG_OPER_BREAK:
- if (!A->CurLoop) {
+ if (!current_loop_oper(A)) {
slang_info_log_error(A->log, "'break' not in loop");
return NULL;
}
- return new_break(A->CurLoop);
+ return new_break(current_loop_ir(A));
case SLANG_OPER_CONTINUE:
- if (!A->CurLoop) {
+ if (!current_loop_oper(A)) {
slang_info_log_error(A->log, "'continue' not in loop");
return NULL;
}
@@ -4160,6 +4824,8 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
return _slang_gen_method_call(A, oper);
case SLANG_OPER_RETURN:
return _slang_gen_return(A, oper);
+ case SLANG_OPER_RETURN_INLINED:
+ return _slang_gen_return(A, oper);
case SLANG_OPER_LABEL:
return new_label(oper->label);
case SLANG_OPER_IDENTIFIER:
@@ -4281,6 +4947,8 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
const GLint totalSize = _slang_array_size(size, arrayLen);
GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
+ var->is_global = GL_TRUE;
+
/* check for sampler2D arrays */
if (texIndex == -1 && var->type.specifier._array)
texIndex = sampler_to_texture_index(var->type.specifier._array->type);
@@ -4333,13 +5001,25 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
if (prog) {
/* user-defined uniform */
if (datatype == GL_NONE) {
- if (var->type.specifier.type == SLANG_SPEC_STRUCT) {
+ if ((var->type.specifier.type == SLANG_SPEC_ARRAY &&
+ var->type.specifier._array->type == SLANG_SPEC_STRUCT) ||
+ (var->type.specifier.type == SLANG_SPEC_STRUCT)) {
/* temporary work-around */
GLenum datatype = GL_FLOAT;
GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
totalSize, datatype, NULL);
store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
totalSize, swizzle);
+
+ if (arrayLen > 0) {
+ GLint a = arrayLen - 1;
+ GLint i;
+ for (i = 0; i < a; i++) {
+ GLfloat value = (GLfloat)(i + uniformLoc + 1);
+ (void) _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM,
+ varName, 1, datatype, &value, NULL, 0x0);
+ }
+ }
/* XXX what we need to do is unroll the struct into its
* basic types, creating a uniform variable for each.
@@ -4567,7 +5247,9 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
assert(A->program->Parameters );
assert(A->program->Varying);
assert(A->vartable);
- A->CurLoop = NULL;
+
+ A->LoopDepth = 0;
+ A->UseReturnFlag = GL_FALSE;
A->CurFunction = fun;
/* fold constant expressions, etc. */
@@ -4615,6 +5297,14 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
printf("************* End codegen function ************\n\n");
#endif
+ if (A->UnresolvedRefs) {
+ /* Can't codegen at this time.
+ * At link time we'll concatenate all the vertex shaders and/or all
+ * the fragment shaders and try recompiling.
+ */
+ return GL_TRUE;
+ }
+
/* Emit program instructions */
success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_TRUE, A->log);
_slang_free_ir_tree(n);
diff --git a/src/mesa/shader/slang/slang_codegen.h b/src/mesa/shader/slang/slang_codegen.h
index f2daa034e4..ee3be55a45 100644
--- a/src/mesa/shader/slang/slang_codegen.h
+++ b/src/mesa/shader/slang/slang_codegen.h
@@ -31,6 +31,9 @@
#include "slang_compile.h"
+#define MAX_LOOP_DEPTH 30
+
+
typedef struct slang_assemble_ctx_
{
slang_atom_pool *atoms;
@@ -39,9 +42,19 @@ typedef struct slang_assemble_ctx_
struct gl_sl_pragmas *pragmas;
slang_var_table *vartable;
slang_info_log *log;
- struct slang_label_ *curFuncEndLabel;
- struct slang_ir_node_ *CurLoop;
+
+ /* current loop stack */
+ const slang_operation *LoopOperStack[MAX_LOOP_DEPTH];
+ struct slang_ir_node_ *LoopIRStack[MAX_LOOP_DEPTH];
+ GLuint LoopDepth;
+
+ /* current function */
struct slang_function_ *CurFunction;
+ struct slang_label_ *curFuncEndLabel;
+ GLboolean UseReturnFlag;
+
+ GLboolean UnresolvedRefs;
+ GLboolean EmitContReturn;
} slang_assemble_ctx;
diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c
index 818b90b7a8..c1b97c7cb7 100644
--- a/src/mesa/shader/slang/slang_compile.c
+++ b/src/mesa/shader/slang/slang_compile.c
@@ -32,6 +32,7 @@
#include "main/context.h"
#include "shader/program.h"
#include "shader/programopt.h"
+#include "shader/prog_optimize.h"
#include "shader/prog_print.h"
#include "shader/prog_parameter.h"
#include "shader/grammar/grammar_mesa.h"
@@ -1450,7 +1451,7 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
case OP_CALL:
{
GLboolean array_constructor = GL_FALSE;
- GLint array_constructor_size;
+ GLint array_constructor_size = 0;
op->type = SLANG_OPER_CALL;
op->a_id = parse_identifier(C);
@@ -1952,6 +1953,7 @@ static int
parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
const slang_fully_specified_type * type)
{
+ GET_CURRENT_CONTEXT(ctx); /* a hack */
slang_variable *var;
slang_atom a_name;
@@ -2055,6 +2057,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
/* emit code for global var decl */
if (C->global_scope) {
slang_assemble_ctx A;
+ memset(&A, 0, sizeof(slang_assemble_ctx));
A.atoms = C->atoms;
A.space.funcs = O->funs;
A.space.structs = O->structs;
@@ -2064,6 +2067,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
A.vartable = O->vartable;
A.log = C->L;
A.curFuncEndLabel = NULL;
+ A.EmitContReturn = ctx->Shader.EmitContReturn;
if (!_slang_codegen_global_variable(&A, var, C->type))
RETURN0;
}
@@ -2072,7 +2076,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
if (C->global_scope) {
if (var->initializer != NULL) {
slang_assemble_ctx A;
-
+ memset(&A, 0, sizeof(slang_assemble_ctx));
A.atoms = C->atoms;
A.space.funcs = O->funs;
A.space.structs = O->structs;
@@ -2159,6 +2163,12 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
(O->funs->num_functions + 1)
* sizeof(slang_function));
if (O->funs->functions == NULL) {
+ /* Make sure that there are no functions marked, as the
+ * allocation is currently NULL, in order to avoid
+ * a potental segfault as we clean up later.
+ */
+ O->funs->num_functions = 0;
+
slang_info_log_memory(C->L);
slang_function_destruct(&parsed_func);
return GL_FALSE;
@@ -2414,7 +2424,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
if (mainFunc) {
/* assemble (generate code) for main() */
slang_assemble_ctx A;
-
+ memset(&A, 0, sizeof(slang_assemble_ctx));
A.atoms = C->atoms;
A.space.funcs = o.funs;
A.space.structs = o.structs;
@@ -2422,6 +2432,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
A.program = o.program;
A.pragmas = &shader->Pragmas;
A.vartable = o.vartable;
+ A.EmitContReturn = ctx->Shader.EmitContReturn;
A.log = C->L;
/* main() takes no parameters */
@@ -2433,6 +2444,8 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
_slang_codegen_function(&A, mainFunc);
shader->Main = GL_TRUE; /* this shader defines main() */
+
+ shader->UnresolvedRefs = A.UnresolvedRefs;
}
_slang_pop_var_table(o.vartable);
@@ -2794,6 +2807,19 @@ _slang_compile(GLcontext *ctx, struct gl_shader *shader)
_mesa_print_program(shader->Program);
#endif
+ shader->CompileStatus = success;
+
+ if (success) {
+ if (shader->Pragmas.Optimize &&
+ (ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
+ _mesa_optimize_program(ctx, shader->Program);
+ }
+ }
+
+ if (ctx->Shader.Flags & GLSL_LOG) {
+ _mesa_write_shader_to_file(shader);
+ }
+
return success;
}
diff --git a/src/mesa/shader/slang/slang_compile_operation.c b/src/mesa/shader/slang/slang_compile_operation.c
index e650616880..3e2bdbc91f 100644
--- a/src/mesa/shader/slang/slang_compile_operation.c
+++ b/src/mesa/shader/slang/slang_compile_operation.c
@@ -119,11 +119,13 @@ slang_operation_copy(slang_operation * x, const slang_operation * y)
if (!slang_operation_construct(&z))
return GL_FALSE;
z.type = y->type;
- z.children = (slang_operation *)
- _slang_alloc(y->num_children * sizeof(slang_operation));
- if (z.children == NULL) {
- slang_operation_destruct(&z);
- return GL_FALSE;
+ if (y->num_children > 0) {
+ z.children = (slang_operation *)
+ _slang_alloc(y->num_children * sizeof(slang_operation));
+ if (z.children == NULL) {
+ slang_operation_destruct(&z);
+ return GL_FALSE;
+ }
}
for (z.num_children = 0; z.num_children < y->num_children;
z.num_children++) {
@@ -152,6 +154,15 @@ slang_operation_copy(slang_operation * x, const slang_operation * y)
return GL_FALSE;
}
}
+
+ /* update scoping for children */
+ for (i = 0; i < y->num_children; i++) {
+ if (y->children[i].locals &&
+ y->children[i].locals->outer_scope == y->locals) {
+ z.children[i].locals->outer_scope = z.locals;
+ }
+ }
+
#if 0
z.var = y->var;
z.fun = y->fun;
@@ -198,6 +209,20 @@ slang_operation_delete(slang_operation *oper)
}
+void
+slang_operation_free_children(slang_operation *oper)
+{
+ GLuint i;
+ for (i = 0; i < slang_oper_num_children(oper); i++) {
+ slang_operation *child = slang_oper_child(oper, i);
+ slang_operation_destruct(child);
+ }
+ _slang_free(oper->children);
+ oper->children = NULL;
+ oper->num_children = 0;
+}
+
+
slang_operation *
slang_operation_grow(GLuint *numChildren, slang_operation **children)
{
@@ -263,6 +288,26 @@ slang_operation_insert(GLuint *numElements, slang_operation **array,
}
+/**
+ * Add/insert new child into given node at given position.
+ * \return pointer to the new child node
+ */
+slang_operation *
+slang_operation_insert_child(slang_operation *oper, GLuint pos)
+{
+ slang_operation *newOp;
+
+ newOp = slang_operation_insert(&oper->num_children,
+ &oper->children,
+ pos);
+ if (newOp) {
+ newOp->locals->outer_scope = oper->locals;
+ }
+
+ return newOp;
+}
+
+
void
_slang_operation_swap(slang_operation *oper0, slang_operation *oper1)
{
@@ -272,3 +317,16 @@ _slang_operation_swap(slang_operation *oper0, slang_operation *oper1)
}
+void
+slang_operation_add_children(slang_operation *oper, GLuint num_children)
+{
+ GLuint i;
+ assert(oper->num_children == 0);
+ assert(oper->children == NULL);
+ oper->num_children = num_children;
+ oper->children = slang_operation_new(num_children);
+ for (i = 0; i < num_children; i++) {
+ oper->children[i].locals = _slang_variable_scope_new(oper->locals);
+ }
+}
+
diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h
index 37af5d617c..58f1edeed8 100644
--- a/src/mesa/shader/slang/slang_compile_operation.h
+++ b/src/mesa/shader/slang/slang_compile_operation.h
@@ -42,6 +42,7 @@ typedef enum slang_operation_type_
SLANG_OPER_CONTINUE, /* "continue" statement */
SLANG_OPER_DISCARD, /* "discard" (kill fragment) statement */
SLANG_OPER_RETURN, /* "return" [expr] */
+ SLANG_OPER_RETURN_INLINED, /* "return" [expr] from inlined function */
SLANG_OPER_LABEL, /* a jump target */
SLANG_OPER_EXPRESSION, /* [expr] */
SLANG_OPER_IF, /* "if" [0] then [1] else [2] */
@@ -150,6 +151,9 @@ slang_operation_new(GLuint count);
extern void
slang_operation_delete(slang_operation *oper);
+extern void
+slang_operation_free_children(slang_operation *oper);
+
extern slang_operation *
slang_operation_grow(GLuint *numChildren, slang_operation **children);
@@ -157,8 +161,66 @@ extern slang_operation *
slang_operation_insert(GLuint *numChildren, slang_operation **children,
GLuint pos);
+extern slang_operation *
+slang_operation_insert_child(slang_operation *oper, GLuint pos);
+
extern void
_slang_operation_swap(slang_operation *oper0, slang_operation *oper1);
+extern void
+slang_operation_add_children(slang_operation *oper, GLuint num_children);
+
+
+/** Return number of children of given node */
+static INLINE GLuint
+slang_oper_num_children(const slang_operation *oper)
+{
+ return oper->num_children;
+}
+
+/** Return child of given operation node */
+static INLINE slang_operation *
+slang_oper_child(slang_operation *oper, GLuint child)
+{
+ assert(child < oper->num_children);
+ return &oper->children[child];
+}
+
+
+/** Return child of given operation node, const version */
+static INLINE const slang_operation *
+slang_oper_child_const(const slang_operation *oper, GLuint child)
+{
+ assert(child < oper->num_children);
+ return &oper->children[child];
+}
+
+
+/** Init oper to a boolean literal. */
+static INLINE void
+slang_operation_literal_bool(slang_operation *oper, GLboolean value)
+{
+ oper->type = SLANG_OPER_LITERAL_BOOL;
+ oper->literal[0] =
+ oper->literal[1] =
+ oper->literal[2] =
+ oper->literal[3] = (float) value;
+ oper->literal_size = 1;
+}
+
+
+/** Init oper to an int literal. */
+static INLINE void
+slang_operation_literal_int(slang_operation *oper, GLint value)
+{
+ oper->type = SLANG_OPER_LITERAL_INT;
+ oper->literal[0] =
+ oper->literal[1] =
+ oper->literal[2] =
+ oper->literal[3] = (float) value;
+ oper->literal_size = 1;
+}
+
+
#endif /* SLANG_COMPILE_OPERATION_H */
diff --git a/src/mesa/shader/slang/slang_compile_variable.h b/src/mesa/shader/slang/slang_compile_variable.h
index a667d91b47..b4585599f2 100644
--- a/src/mesa/shader/slang/slang_compile_variable.h
+++ b/src/mesa/shader/slang/slang_compile_variable.h
@@ -39,6 +39,7 @@ typedef struct slang_variable_
GLuint array_len; /**< only if type == SLANG_SPEC_ARRAy */
struct slang_operation_ *initializer; /**< Optional initializer code */
GLuint size; /**< Variable's size in bytes */
+ GLboolean is_global;
GLboolean isTemp; /**< a named temporary (__resultTmp) */
GLboolean declared; /**< for debug */
struct slang_ir_storage_ *store; /**< Storage for this var */
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index ea446fa5d4..3f455e0640 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -62,6 +62,8 @@ typedef struct
GLuint MaxInstructions; /**< size of prog->Instructions[] buffer */
+ GLboolean UnresolvedFunctions;
+
/* code-gen options */
GLboolean EmitHighLevelInstructions;
GLboolean EmitCondCodes;
@@ -164,7 +166,7 @@ _slang_var_swizzle(GLint size, GLint comp)
{
switch (size) {
case 1:
- return MAKE_SWIZZLE4(comp, comp, comp, comp);
+ return MAKE_SWIZZLE4(comp, SWIZZLE_NIL, SWIZZLE_NIL, SWIZZLE_NIL);
case 2:
return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
case 3:
@@ -446,12 +448,12 @@ new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode)
static struct prog_instruction *
emit_arl_load(slang_emit_info *emitInfo,
- enum register_file file, GLint index, GLuint swizzle)
+ gl_register_file file, GLint index, GLuint swizzle)
{
struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL);
inst->SrcReg[0].File = file;
inst->SrcReg[0].Index = index;
- inst->SrcReg[0].Swizzle = swizzle;
+ inst->SrcReg[0].Swizzle = fix_swizzle(swizzle);
inst->DstReg.File = PROGRAM_ADDRESS;
inst->DstReg.Index = 0;
inst->DstReg.WriteMask = WRITEMASK_X;
@@ -872,7 +874,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
emit(emitInfo, n->Children[1]);
if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) {
+ /* XXX this error should have been caught in slang_codegen.c */
slang_info_log_error(emitInfo->log, "invalid operands to == or !=");
+ n->Store = NULL;
return NULL;
}
@@ -902,6 +906,7 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
slang_ir_storage tempStore;
if (!alloc_local_temp(emitInfo, &tempStore, 4)) {
+ n->Store = NULL;
return NULL;
/* out of temps */
}
@@ -1130,7 +1135,7 @@ emit_negation(slang_emit_info *emitInfo, slang_ir_node *n)
n->Children[0]->Store,
NULL,
NULL);
- inst->SrcReg[0].NegateBase = NEGATE_XYZW;
+ inst->SrcReg[0].Negate = NEGATE_XYZW;
return inst;
}
@@ -1259,16 +1264,33 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
{
struct prog_instruction *inst;
gl_inst_opcode opcode;
+ GLboolean shadow = GL_FALSE;
- if (n->Opcode == IR_TEX) {
+ switch (n->Opcode) {
+ case IR_TEX:
opcode = OPCODE_TEX;
- }
- else if (n->Opcode == IR_TEXB) {
+ break;
+ case IR_TEX_SH:
+ opcode = OPCODE_TEX;
+ shadow = GL_TRUE;
+ break;
+ case IR_TEXB:
opcode = OPCODE_TXB;
- }
- else {
- assert(n->Opcode == IR_TEXP);
+ break;
+ case IR_TEXB_SH:
+ opcode = OPCODE_TXB;
+ shadow = GL_TRUE;
+ break;
+ case IR_TEXP:
opcode = OPCODE_TXP;
+ break;
+ case IR_TEXP_SH:
+ opcode = OPCODE_TXP;
+ shadow = GL_TRUE;
+ break;
+ default:
+ _mesa_problem(NULL, "Bad IR TEX code");
+ return NULL;
}
if (n->Children[0]->Opcode == IR_ELEMENT) {
@@ -1300,6 +1322,8 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
NULL,
NULL);
+ inst->TexShadow = shadow;
+
/* Store->Index is the uniform/sampler index */
assert(n->Children[0]->Store->Index >= 0);
inst->TexSrcUnit = n->Children[0]->Store->Index;
@@ -1335,7 +1359,8 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)
inst = emit(emitInfo, n->Children[1]);
if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) {
- if (!emitInfo->log->text) {
+ if (!emitInfo->log->text && !emitInfo->UnresolvedFunctions) {
+ /* XXX this error should have been caught in slang_codegen.c */
slang_info_log_error(emitInfo->log, "invalid assignment");
}
return NULL;
@@ -1358,6 +1383,7 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)
#if PEEPHOLE_OPTIMIZATIONS
if (inst &&
+ (n->Children[1]->Opcode != IR_SWIZZLE) &&
_slang_is_temp(emitInfo->vt, n->Children[1]->Store) &&
(inst->DstReg.File == n->Children[1]->Store->File) &&
(inst->DstReg.Index == n->Children[1]->Store->Index) &&
@@ -1374,13 +1400,9 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)
* becomes:
* MUL a, x, y;
*/
- if (n->Children[1]->Opcode != IR_SWIZZLE)
- _slang_free_temp(emitInfo->vt, n->Children[1]->Store);
- *n->Children[1]->Store = *n->Children[0]->Store;
/* fixup the previous instruction (which stored the RHS result) */
assert(n->Children[0]->Store->Index >= 0);
-
storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store);
return inst;
}
@@ -1813,6 +1835,25 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n)
}
+/**
+ * Return the size of a swizzle mask given that some swizzle components
+ * may be NIL/undefined. For example:
+ * swizzle_size(".zzxx") = 4
+ * swizzle_size(".xy??") = 2
+ * swizzle_size(".w???") = 1
+ */
+static GLuint
+swizzle_size(GLuint swizzle)
+{
+ GLuint i;
+ for (i = 0; i < 4; i++) {
+ if (GET_SWZ(swizzle, i) == SWIZZLE_NIL)
+ return i;
+ }
+ return 4;
+}
+
+
static struct prog_instruction *
emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
{
@@ -1820,14 +1861,25 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
inst = emit(emitInfo, n->Children[0]);
-#if 0
- assert(n->Store->Parent);
- /* Apply this node's swizzle to parent's storage */
- GLuint swizzle = n->Store->Swizzle;
- _slang_copy_ir_storage(n->Store, n->Store->Parent);
- n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle);
+ if (!n->Store->Parent) {
+ /* this covers a case such as "(b ? p : q).x" */
+ n->Store->Parent = n->Children[0]->Store;
+ assert(n->Store->Parent);
+ }
+
+ {
+ const GLuint swizzle = n->Store->Swizzle;
+ /* new storage is parent storage with updated Swizzle + Size fields */
+ _slang_copy_ir_storage(n->Store, n->Store->Parent);
+ /* Apply this node's swizzle to parent's storage */
+ n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle);
+ /* Update size */
+ n->Store->Size = swizzle_size(n->Store->Swizzle);
+ }
+
assert(!n->Store->Parent);
-#endif
+ assert(n->Store->Index >= 0);
+
return inst;
}
@@ -2107,6 +2159,7 @@ emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n)
if (index < 0) {
/* error */
char s[100];
+ /* XXX isn't this really an out of memory/resources error? */
_mesa_snprintf(s, sizeof(s), "Undefined variable '%s'",
(char *) n->Var->a_name);
slang_info_log_error(emitInfo->log, s);
@@ -2120,6 +2173,10 @@ emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n)
/* mark var as used */
_mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name);
}
+ else if (n->Store->File == PROGRAM_INPUT) {
+ assert(n->Store->Index >= 0);
+ emitInfo->prog->InputsRead |= (1 << n->Store->Index);
+ }
if (n->Store->Index < 0) {
/* probably ran out of registers */
@@ -2142,6 +2199,12 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
return NULL;
}
+ if (n->Comment) {
+ inst = new_instruction(emitInfo, OPCODE_NOP);
+ inst->Comment = _mesa_strdup(n->Comment);
+ inst = NULL;
+ }
+
switch (n->Opcode) {
case IR_SEQ:
/* sequence of two sub-trees */
@@ -2235,6 +2298,9 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
case IR_TEX:
case IR_TEXB:
case IR_TEXP:
+ case IR_TEX_SH:
+ case IR_TEXB_SH:
+ case IR_TEXP_SH:
return emit_tex(emitInfo, n);
case IR_NEG:
return emit_negation(emitInfo, n);
@@ -2424,7 +2490,9 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4;
}
if (prog->Parameters->NumParameters > maxUniforms) {
- slang_info_log_error(log, "Constant/uniform register limit exceeded");
+ slang_info_log_error(log, "Constant/uniform register limit exceeded "
+ "(max=%u vec4)", maxUniforms);
+
return GL_FALSE;
}
diff --git a/src/mesa/shader/slang/slang_emit.h b/src/mesa/shader/slang/slang_emit.h
index 8ff52bf605..ab4c202d67 100644
--- a/src/mesa/shader/slang/slang_emit.h
+++ b/src/mesa/shader/slang/slang_emit.h
@@ -32,10 +32,6 @@
#include "main/mtypes.h"
-extern void
-slang_print_ir(const slang_ir_node *n, int indent);
-
-
extern GLuint
_slang_swizzle_swizzle(GLuint swz1, GLuint swz2);
diff --git a/src/mesa/shader/slang/slang_ir.c b/src/mesa/shader/slang/slang_ir.c
index e4c6e0ea51..1c7f7474e7 100644
--- a/src/mesa/shader/slang/slang_ir.c
+++ b/src/mesa/shader/slang/slang_ir.c
@@ -94,6 +94,9 @@ static const slang_ir_info IrInfo[] = {
{ IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
{ IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 1 },
{ IR_TEXP, "IR_TEXP", OPCODE_TXP, 4, 1 },
+ { IR_TEX_SH, "IR_TEX_SH", OPCODE_TEX, 4, 1 },
+ { IR_TEXB_SH, "IR_TEXB_SH", OPCODE_TXB, 4, 1 },
+ { IR_TEXP_SH, "IR_TEXP_SH", OPCODE_TXP, 4, 1 },
{ IR_FLOAT, "IR_FLOAT", OPCODE_NOP, 0, 0 }, /* float literal */
{ IR_FIELD, "IR_FIELD", OPCODE_NOP, 0, 0 },
{ IR_ELEMENT, "IR_ELEMENT", OPCODE_NOP, 0, 0 },
@@ -118,7 +121,7 @@ _slang_ir_info(slang_ir_opcode opcode)
void
_slang_init_ir_storage(slang_ir_storage *st,
- enum register_file file, GLint index, GLint size,
+ gl_register_file file, GLint index, GLint size,
GLuint swizzle)
{
st->File = file;
@@ -134,7 +137,7 @@ _slang_init_ir_storage(slang_ir_storage *st,
* Return a new slang_ir_storage object.
*/
slang_ir_storage *
-_slang_new_ir_storage(enum register_file file, GLint index, GLint size)
+_slang_new_ir_storage(gl_register_file file, GLint index, GLint size)
{
slang_ir_storage *st;
st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
@@ -154,7 +157,7 @@ _slang_new_ir_storage(enum register_file file, GLint index, GLint size)
* Return a new slang_ir_storage object.
*/
slang_ir_storage *
-_slang_new_ir_storage_swz(enum register_file file, GLint index, GLint size,
+_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
GLuint swizzle)
{
slang_ir_storage *st;
@@ -193,10 +196,10 @@ _slang_new_ir_storage_relative(GLint index, GLint size,
slang_ir_storage *
-_slang_new_ir_storage_indirect(enum register_file file,
+_slang_new_ir_storage_indirect(gl_register_file file,
GLint index,
GLint size,
- enum register_file indirectFile,
+ gl_register_file indirectFile,
GLint indirectIndex,
GLuint indirectSwizzle)
{
diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h
index 644269d491..e796693ed5 100644
--- a/src/mesa/shader/slang/slang_ir.h
+++ b/src/mesa/shader/slang/slang_ir.h
@@ -131,6 +131,10 @@ typedef enum
IR_TEXB, /* texture lookup with LOD bias */
IR_TEXP, /* texture lookup with projection */
+ IR_TEX_SH, /* texture lookup, shadow compare */
+ IR_TEXB_SH, /* texture lookup with LOD bias, shadow compare */
+ IR_TEXP_SH, /* texture lookup with projection, shadow compare */
+
IR_FLOAT,
IR_I_TO_F, /* int[4] to float[4] conversion */
IR_F_TO_I, /* float[4] to int[4] conversion */
@@ -167,7 +171,7 @@ typedef enum
*/
struct slang_ir_storage_
{
- enum register_file File; /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
+ gl_register_file File; /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
GLint Index; /**< -1 means unallocated */
GLint Size; /**< number of floats or ints */
GLuint Swizzle; /**< Swizzle AND writemask info */
@@ -176,7 +180,7 @@ struct slang_ir_storage_
GLboolean RelAddr; /* we'll remove this eventually */
GLboolean IsIndirect;
- enum register_file IndirectFile;
+ gl_register_file IndirectFile;
GLint IndirectIndex;
GLuint IndirectSwizzle;
GLuint TexTarget; /**< If File==PROGRAM_SAMPLER, one of TEXTURE_x_INDEX */
@@ -208,6 +212,7 @@ typedef struct slang_ir_node_
struct slang_ir_node_ *List; /**< For various linked lists */
struct slang_ir_node_ *Parent; /**< Pointer to logical parent (ie. loop) */
slang_label *Label; /**< Used for branches */
+ const char *Comment; /**< If Opcode == IR_COMMENT */
} slang_ir_node;
@@ -231,15 +236,15 @@ _slang_ir_info(slang_ir_opcode opcode);
extern void
_slang_init_ir_storage(slang_ir_storage *st,
- enum register_file file, GLint index, GLint size,
+ gl_register_file file, GLint index, GLint size,
GLuint swizzle);
extern slang_ir_storage *
-_slang_new_ir_storage(enum register_file file, GLint index, GLint size);
+_slang_new_ir_storage(gl_register_file file, GLint index, GLint size);
extern slang_ir_storage *
-_slang_new_ir_storage_swz(enum register_file file, GLint index, GLint size,
+_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
GLuint swizzle);
extern slang_ir_storage *
@@ -248,10 +253,10 @@ _slang_new_ir_storage_relative(GLint index, GLint size,
extern slang_ir_storage *
-_slang_new_ir_storage_indirect(enum register_file file,
+_slang_new_ir_storage_indirect(gl_register_file file,
GLint index,
GLint size,
- enum register_file indirectFile,
+ gl_register_file indirectFile,
GLint indirectIndex,
GLuint indirectSwizzle);
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index c6d5cc0566..169c07f8ce 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -40,6 +40,7 @@
#include "shader/prog_statevars.h"
#include "shader/prog_uniform.h"
#include "shader/shader_api.h"
+#include "slang_builtin.h"
#include "slang_link.h"
@@ -97,7 +98,8 @@ bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit)
* which inputs are centroid-sampled, invariant, etc.
*/
static GLboolean
-link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
+link_varying_vars(GLcontext *ctx,
+ struct gl_shader_program *shProg, struct gl_program *prog)
{
GLuint *map, i, firstVarying, newFile;
GLbitfield *inOutFlags;
@@ -156,8 +158,12 @@ link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
var->Flags);
}
+ if (shProg->Varying->NumParameters > ctx->Const.MaxVarying) {
+ link_error(shProg, "Too many varying variables");
+ return GL_FALSE;
+ }
+
/* Map varying[i] to varying[j].
- * Plus, set prog->Input/OutputFlags[] as described above.
* Note: the loop here takes care of arrays or large (sz>4) vars.
*/
{
@@ -282,6 +288,7 @@ link_uniform_vars(GLcontext *ctx,
for (i = 0; i < prog->NumInstructions; i++) {
struct prog_instruction *inst = prog->Instructions + i;
if (_mesa_is_tex_instruction(inst->Opcode)) {
+ /* here, inst->TexSrcUnit is really the sampler unit */
const GLint oldSampNum = inst->TexSrcUnit;
#if 0
@@ -289,12 +296,14 @@ link_uniform_vars(GLcontext *ctx,
inst->TexSrcUnit, samplerMap[ inst->TexSrcUnit ]);
#endif
- /* here, texUnit is really samplerUnit */
if (oldSampNum < Elements(samplerMap)) {
const GLuint newSampNum = samplerMap[oldSampNum];
inst->TexSrcUnit = newSampNum;
prog->SamplerTargets[newSampNum] = inst->TexSrcTarget;
prog->SamplersUsed |= (1 << newSampNum);
+ if (inst->TexShadow) {
+ prog->ShadowSamplers |= (1 << newSampNum);
+ }
}
}
}
@@ -316,9 +325,10 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
const struct gl_program *origProg,
struct gl_program *linkedProg)
{
- GLint attribMap[MAX_VERTEX_ATTRIBS];
+ GLint attribMap[MAX_VERTEX_GENERIC_ATTRIBS];
GLuint i, j;
- GLbitfield usedAttributes;
+ GLbitfield usedAttributes; /* generics only, not legacy attributes */
+ GLbitfield inputsRead = 0x0;
assert(origProg != linkedProg);
assert(origProg->Target == GL_VERTEX_PROGRAM_ARB);
@@ -342,8 +352,17 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
usedAttributes |= (1 << attr);
}
+ /* If gl_Vertex is used, that actually counts against the limit
+ * on generic vertex attributes. This avoids the ambiguity of
+ * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos)
+ * or generic attribute[0]. If gl_Vertex is used, we want the former.
+ */
+ if (origProg->InputsRead & VERT_BIT_POS) {
+ usedAttributes |= 0x1;
+ }
+
/* initialize the generic attribute map entries to -1 */
- for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) {
+ for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
attribMap[i] = -1;
}
@@ -353,6 +372,10 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
for (i = 0; i < linkedProg->NumInstructions; i++) {
struct prog_instruction *inst = linkedProg->Instructions + i;
for (j = 0; j < 3; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_INPUT) {
+ inputsRead |= (1 << inst->SrcReg[j].Index);
+ }
+
if (inst->SrcReg[j].File == PROGRAM_INPUT &&
inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) {
/*
@@ -384,11 +407,11 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
* Start at 1 since generic attribute 0 always aliases
* glVertex/position.
*/
- for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) {
+ for (attr = 0; attr < MAX_VERTEX_GENERIC_ATTRIBS; attr++) {
if (((1 << attr) & usedAttributes) == 0)
break;
}
- if (attr == MAX_VERTEX_ATTRIBS) {
+ if (attr == MAX_VERTEX_GENERIC_ATTRIBS) {
link_error(shProg, "Too many vertex attributes");
return GL_FALSE;
}
@@ -414,6 +437,20 @@ _slang_resolve_attributes(struct gl_shader_program *shProg,
}
}
+ /* Handle pre-defined attributes here (gl_Vertex, gl_Normal, etc).
+ * When the user queries the active attributes we need to include both
+ * the user-defined attributes and the built-in ones.
+ */
+ for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_GENERIC0; i++) {
+ if (inputsRead & (1 << i)) {
+ _mesa_add_attribute(linkedProg->Attributes,
+ _slang_vert_attrib_name(i),
+ 4, /* size in floats */
+ _slang_vert_attrib_type(i),
+ -1 /* attrib/input */);
+ }
+ }
+
return GL_TRUE;
}
@@ -467,37 +504,152 @@ _slang_update_inputs_outputs(struct gl_program *prog)
for (j = 0; j < numSrc; j++) {
if (inst->SrcReg[j].File == PROGRAM_INPUT) {
prog->InputsRead |= 1 << inst->SrcReg[j].Index;
- if (prog->Target == GL_FRAGMENT_PROGRAM_ARB &&
- inst->SrcReg[j].Index == FRAG_ATTRIB_FOGC) {
- /* The fragment shader FOGC input is used for fog,
- * front-facing and sprite/point coord.
- */
- struct gl_fragment_program *fp = fragment_program(prog);
- const GLint swz = GET_SWZ(inst->SrcReg[j].Swizzle, 0);
- if (swz == SWIZZLE_X)
- fp->UsesFogFragCoord = GL_TRUE;
- else if (swz == SWIZZLE_Y)
- fp->UsesFrontFacing = GL_TRUE;
- else if (swz == SWIZZLE_Z || swz == SWIZZLE_W)
- fp->UsesPointCoord = GL_TRUE;
- }
}
else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) {
maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1));
}
}
+
if (inst->DstReg.File == PROGRAM_OUTPUT) {
prog->OutputsWritten |= 1 << inst->DstReg.Index;
+ if (inst->DstReg.RelAddr) {
+ /* If the output attribute is indexed with relative addressing
+ * we know that it must be a varying or texcoord such as
+ * gl_TexCoord[i] = v; In this case, mark all the texcoords
+ * or varying outputs as being written. It's not an error if
+ * a vertex shader writes varying vars that aren't used by the
+ * fragment shader. But it is an error for a fragment shader
+ * to use varyings that are not written by the vertex shader.
+ */
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
+ if (inst->DstReg.Index == VERT_RESULT_TEX0) {
+ /* mark all texcoord outputs as written */
+ const GLbitfield mask =
+ ((1 << MAX_TEXTURE_COORD_UNITS) - 1) << VERT_RESULT_TEX0;
+ prog->OutputsWritten |= mask;
+ }
+ else if (inst->DstReg.Index == VERT_RESULT_VAR0) {
+ /* mark all generic varying outputs as written */
+ const GLbitfield mask =
+ ((1 << MAX_VARYING) - 1) << VERT_RESULT_VAR0;
+ prog->OutputsWritten |= mask;
+ }
+ }
+ }
}
else if (inst->DstReg.File == PROGRAM_ADDRESS) {
maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
}
}
-
prog->NumAddressRegs = maxAddrReg;
}
+
+
+
+/**
+ * Return a new shader whose source code is the concatenation of
+ * all the shader sources of the given type.
+ */
+static struct gl_shader *
+concat_shaders(struct gl_shader_program *shProg, GLenum shaderType)
+{
+ struct gl_shader *newShader;
+ const struct gl_shader *firstShader = NULL;
+ GLuint shaderLengths[100];
+ GLchar *source;
+ GLuint totalLen = 0, len = 0;
+ GLuint i;
+
+ /* compute total size of new shader source code */
+ for (i = 0; i < shProg->NumShaders; i++) {
+ const struct gl_shader *shader = shProg->Shaders[i];
+ if (shader->Type == shaderType) {
+ shaderLengths[i] = _mesa_strlen(shader->Source);
+ totalLen += shaderLengths[i];
+ if (!firstShader)
+ firstShader = shader;
+ }
+ }
+
+ if (totalLen == 0)
+ return NULL;
+
+ source = (GLchar *) _mesa_malloc(totalLen + 1);
+ if (!source)
+ return NULL;
+
+ /* concatenate shaders */
+ for (i = 0; i < shProg->NumShaders; i++) {
+ const struct gl_shader *shader = shProg->Shaders[i];
+ if (shader->Type == shaderType) {
+ _mesa_memcpy(source + len, shader->Source, shaderLengths[i]);
+ len += shaderLengths[i];
+ }
+ }
+ source[len] = '\0';
+ /*
+ _mesa_printf("---NEW CONCATENATED SHADER---:\n%s\n------------\n", source);
+ */
+
+ newShader = CALLOC_STRUCT(gl_shader);
+ newShader->Type = shaderType;
+ newShader->Source = source;
+ newShader->Pragmas = firstShader->Pragmas;
+
+ return newShader;
+}
+
+
+/**
+ * Search the shader program's list of shaders to find the one that
+ * defines main().
+ * This will involve shader concatenation and recompilation if needed.
+ */
+static struct gl_shader *
+get_main_shader(GLcontext *ctx,
+ struct gl_shader_program *shProg, GLenum type)
+{
+ struct gl_shader *shader = NULL;
+ GLuint i;
+
+ /*
+ * Look for a shader that defines main() and has no unresolved references.
+ */
+ for (i = 0; i < shProg->NumShaders; i++) {
+ shader = shProg->Shaders[i];
+ if (shader->Type == type &&
+ shader->Main &&
+ !shader->UnresolvedRefs) {
+ /* All set! */
+ return shader;
+ }
+ }
+
+ /*
+ * There must have been unresolved references during the original
+ * compilation. Try concatenating all the shaders of the given type
+ * and recompile that.
+ */
+ shader = concat_shaders(shProg, type);
+
+ if (shader) {
+ _slang_compile(ctx, shader);
+
+ /* Finally, check if recompiling failed */
+ if (!shader->CompileStatus ||
+ !shader->Main ||
+ shader->UnresolvedRefs) {
+ link_error(shProg, "Unresolved symbols");
+ return NULL;
+ }
+ }
+
+ return shader;
+}
+
+
/**
* Shader linker. Currently:
*
@@ -514,13 +666,16 @@ _slang_link(GLcontext *ctx,
GLhandleARB programObj,
struct gl_shader_program *shProg)
{
- const struct gl_vertex_program *vertProg;
- const struct gl_fragment_program *fragProg;
+ const struct gl_vertex_program *vertProg = NULL;
+ const struct gl_fragment_program *fragProg = NULL;
GLuint numSamplers = 0;
GLuint i;
_mesa_clear_shader_program_data(ctx, shProg);
+ /* Initialize LinkStatus to "success". Will be cleared if error. */
+ shProg->LinkStatus = GL_TRUE;
+
/* check that all programs compiled successfully */
for (i = 0; i < shProg->NumShaders; i++) {
if (!shProg->Shaders[i]->CompileStatus) {
@@ -532,24 +687,19 @@ _slang_link(GLcontext *ctx,
shProg->Uniforms = _mesa_new_uniform_list();
shProg->Varying = _mesa_new_parameter_list();
- /**
- * Find attached vertex, fragment shaders defining main()
+ /*
+ * Find the vertex and fragment shaders which define main()
*/
- vertProg = NULL;
- fragProg = NULL;
- for (i = 0; i < shProg->NumShaders; i++) {
- struct gl_shader *shader = shProg->Shaders[i];
- if (shader->Type == GL_VERTEX_SHADER) {
- if (shader->Main)
- vertProg = vertex_program(shader->Program);
- }
- else if (shader->Type == GL_FRAGMENT_SHADER) {
- if (shader->Main)
- fragProg = fragment_program(shader->Program);
- }
- else {
- _mesa_problem(ctx, "unexpected shader target in slang_link()");
- }
+ {
+ struct gl_shader *vertShader, *fragShader;
+ vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER);
+ fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER);
+ if (vertShader)
+ vertProg = vertex_program(vertShader->Program);
+ if (fragShader)
+ fragProg = fragment_program(fragShader->Program);
+ if (!shProg->LinkStatus)
+ return;
}
#if FEATURE_es2_glsl
@@ -573,6 +723,8 @@ _slang_link(GLcontext *ctx,
struct gl_vertex_program *linked_vprog =
vertex_program(_mesa_clone_program(ctx, &vertProg->Base));
shProg->VertexProgram = linked_vprog; /* refcount OK */
+ /* vertex program ID not significant; just set Id for debugging purposes */
+ shProg->VertexProgram->Base.Id = shProg->Name;
ASSERT(shProg->VertexProgram->Base.RefCount == 1);
}
@@ -581,16 +733,18 @@ _slang_link(GLcontext *ctx,
struct gl_fragment_program *linked_fprog =
fragment_program(_mesa_clone_program(ctx, &fragProg->Base));
shProg->FragmentProgram = linked_fprog; /* refcount OK */
+ /* vertex program ID not significant; just set Id for debugging purposes */
+ shProg->FragmentProgram->Base.Id = shProg->Name;
ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
}
/* link varying vars */
if (shProg->VertexProgram) {
- if (!link_varying_vars(shProg, &shProg->VertexProgram->Base))
+ if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base))
return;
}
if (shProg->FragmentProgram) {
- if (!link_varying_vars(shProg, &shProg->FragmentProgram->Base))
+ if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base))
return;
}
@@ -650,7 +804,7 @@ _slang_link(GLcontext *ctx,
/* check that gl_FragColor and gl_FragData are not both written to */
if (shProg->FragmentProgram) {
GLbitfield outputsWritten = shProg->FragmentProgram->Base.OutputsWritten;
- if ((outputsWritten & ((1 << FRAG_RESULT_COLR))) &&
+ if ((outputsWritten & ((1 << FRAG_RESULT_COLOR))) &&
(outputsWritten >= (1 << FRAG_RESULT_DATA0))) {
link_error(shProg, "Fragment program cannot write both gl_FragColor"
" and gl_FragData[].\n");
@@ -666,12 +820,12 @@ _slang_link(GLcontext *ctx,
/* notify driver that a new fragment program has been compiled/linked */
ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
&shProg->FragmentProgram->Base);
- if (MESA_VERBOSE & VERBOSE_GLSL_DUMP) {
- printf("Mesa original fragment program:\n");
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ _mesa_printf("Mesa pre-link fragment program:\n");
_mesa_print_program(&fragProg->Base);
_mesa_print_program_parameters(ctx, &fragProg->Base);
- printf("Mesa post-link fragment program:\n");
+ _mesa_printf("Mesa post-link fragment program:\n");
_mesa_print_program(&shProg->FragmentProgram->Base);
_mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
}
@@ -684,20 +838,31 @@ _slang_link(GLcontext *ctx,
/* notify driver that a new vertex program has been compiled/linked */
ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
&shProg->VertexProgram->Base);
- if (MESA_VERBOSE & VERBOSE_GLSL_DUMP) {
- printf("Mesa original vertex program:\n");
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ _mesa_printf("Mesa pre-link vertex program:\n");
_mesa_print_program(&vertProg->Base);
_mesa_print_program_parameters(ctx, &vertProg->Base);
- printf("Mesa post-link vertex program:\n");
+ _mesa_printf("Mesa post-link vertex program:\n");
_mesa_print_program(&shProg->VertexProgram->Base);
_mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);
}
}
- if (MESA_VERBOSE & VERBOSE_GLSL_DUMP) {
- printf("Varying vars:\n");
+ /* Debug: */
+ if (0) {
+ if (shProg->VertexProgram)
+ _mesa_postprocess_program(ctx, &shProg->VertexProgram->Base);
+ if (shProg->FragmentProgram)
+ _mesa_postprocess_program(ctx, &shProg->FragmentProgram->Base);
+ }
+
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ _mesa_printf("Varying vars:\n");
_mesa_print_parameter_list(shProg->Varying);
+ if (shProg->InfoLog) {
+ _mesa_printf("Info Log: %s\n", shProg->InfoLog);
+ }
}
shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);
diff --git a/src/mesa/shader/slang/slang_log.c b/src/mesa/shader/slang/slang_log.c
index d5576d7ee2..d7d2b4fbfd 100644
--- a/src/mesa/shader/slang/slang_log.c
+++ b/src/mesa/shader/slang/slang_log.c
@@ -77,10 +77,6 @@ slang_info_log_message(slang_info_log * log, const char *prefix,
slang_string_concat(log->text, msg);
slang_string_concat(log->text, "\n");
- if (MESA_VERBOSE & VERBOSE_GLSL) {
- _mesa_printf("Mesa: GLSL %s", log->text);
- }
-
return 1;
}
diff --git a/src/mesa/shader/slang/slang_preprocess.c b/src/mesa/shader/slang/slang_preprocess.c
index cd79c8b94a..e9a24cc009 100644
--- a/src/mesa/shader/slang/slang_preprocess.c
+++ b/src/mesa/shader/slang/slang_preprocess.c
@@ -508,8 +508,7 @@ static GLvoid
pp_ext_init(pp_ext *self, const struct gl_extensions *extensions)
{
pp_ext_disable_all (self);
- if (extensions->ARB_draw_buffers)
- self->ARB_draw_buffers = GL_TRUE;
+ self->ARB_draw_buffers = GL_TRUE;
if (extensions->NV_texture_rectangle)
self->ARB_texture_rectangle = GL_TRUE;
}
@@ -531,14 +530,6 @@ pp_ext_set(pp_ext *self, const char *name, GLboolean enable)
}
-static void
-pp_pragmas_init(struct gl_sl_pragmas *pragmas)
-{
- pragmas->Optimize = GL_TRUE;
- pragmas->Debug = GL_FALSE;
-}
-
-
/**
* Called in response to #pragma. For example, "#pragma debug(on)" would
* call this function as pp_pragma("debug", "on").
@@ -554,10 +545,12 @@ pp_pragma(struct gl_sl_pragmas *pragmas, const char *pragma, const char *param)
if (!param)
return GL_FALSE; /* missing required param */
if (_mesa_strcmp(param, "on") == 0) {
- pragmas->Optimize = GL_TRUE;
+ if (!pragmas->IgnoreOptimize)
+ pragmas->Optimize = GL_TRUE;
}
else if (_mesa_strcmp(param, "off") == 0) {
- pragmas->Optimize = GL_FALSE;
+ if (!pragmas->IgnoreOptimize)
+ pragmas->Optimize = GL_FALSE;
}
else {
return GL_FALSE; /* invalid param */
@@ -567,10 +560,12 @@ pp_pragma(struct gl_sl_pragmas *pragmas, const char *pragma, const char *param)
if (!param)
return GL_FALSE; /* missing required param */
if (_mesa_strcmp(param, "on") == 0) {
- pragmas->Debug = GL_TRUE;
+ if (!pragmas->IgnoreDebug)
+ pragmas->Debug = GL_TRUE;
}
else if (_mesa_strcmp(param, "off") == 0) {
- pragmas->Debug = GL_FALSE;
+ if (!pragmas->IgnoreDebug)
+ pragmas->Debug = GL_FALSE;
}
else {
return GL_FALSE; /* invalid param */
@@ -946,7 +941,6 @@ preprocess_source (slang_string *output, const char *source,
}
pp_state_init (&state, elog, extensions);
- pp_pragmas_init (pragmas);
/* add the predefined symbols to the symbol table */
for (i = 0; predefined[i]; i++) {
@@ -1041,11 +1035,11 @@ preprocess_source (slang_string *output, const char *source,
/* Parse optional macro parameters. */
while (prod[i++] != PARAM_END) {
- if (state.cond.top->effective) {
- pp_symbol *param;
+ pp_symbol *param;
- id = (const char *) (&prod[i]);
- idlen = _mesa_strlen (id);
+ id = (const char *) (&prod[i]);
+ idlen = _mesa_strlen (id);
+ if (state.cond.top->effective) {
pp_annotate (output, "%s, ", id);
param = pp_symbols_push (&symbol->parameters);
if (param == NULL)
@@ -1059,8 +1053,23 @@ preprocess_source (slang_string *output, const char *source,
id = (const char *) (&prod[i]);
idlen = _mesa_strlen (id);
if (state.cond.top->effective) {
+ slang_string replacement;
+ expand_state es;
+
pp_annotate (output, ") %s", id);
- slang_string_pushs (&symbol->replacement, id, idlen);
+
+ slang_string_init(&replacement);
+ slang_string_pushs(&replacement, id, idlen);
+
+ /* Expand macro replacement. */
+ es.output = &symbol->replacement;
+ es.input = slang_string_cstr(&replacement);
+ es.state = &state;
+ if (!expand(&es, &state.symbols)) {
+ slang_string_free(&replacement);
+ goto error;
+ }
+ slang_string_free(&replacement);
}
i += idlen + 1;
}
@@ -1292,11 +1301,52 @@ error:
/**
+ * Remove the continuation characters from the input string.
+ * This is the very first step in preprocessing and is effective
+ * even inside comment blocks.
+ * If there is a whitespace between a backslash and a newline,
+ * this is not considered as a line continuation.
+ * \return GL_TRUE for success, GL_FALSE otherwise.
+ */
+static GLboolean
+_slang_preprocess_backslashes(slang_string *output,
+ const char *input)
+{
+ while (*input) {
+ if (input[0] == '\\') {
+ /* If a newline follows, eat the backslash and the newline. */
+ if (input[1] == '\r') {
+ if (input[2] == '\n') {
+ input += 3;
+ } else {
+ input += 2;
+ }
+ } else if (input[1] == '\n') {
+ if (input[2] == '\r') {
+ input += 3;
+ } else {
+ input += 2;
+ }
+ } else {
+ /* Leave the backslash alone. */
+ slang_string_pushc(output, *input++);
+ }
+ } else {
+ slang_string_pushc(output, *input++);
+ }
+ }
+ return GL_TRUE;
+}
+
+
+/**
* Run preprocessor on source code.
* \param extensions indicates which GL extensions are enabled
* \param output the post-process results
* \param input the input text
* \param elog log to record warnings, errors
+ * \param extensions out extension settings
+ * \param pragmas in/out #pragma settings
* \return GL_TRUE for success, GL_FALSE for error
*/
GLboolean
@@ -1308,6 +1358,7 @@ _slang_preprocess_directives(slang_string *output,
{
grammar pid, eid;
GLboolean success;
+ slang_string without_backslashes;
pid = grammar_load_from_text ((const byte *) (slang_pp_directives_syn));
if (pid == 0) {
@@ -1320,9 +1371,36 @@ _slang_preprocess_directives(slang_string *output,
grammar_destroy (pid);
return GL_FALSE;
}
- success = preprocess_source (output, input, pid, eid, elog, extensions, pragmas);
+
+ slang_string_init(&without_backslashes);
+ success = _slang_preprocess_backslashes(&without_backslashes, input);
+
+ if (0) {
+ _mesa_printf("Pre-processed shader:\n");
+ _mesa_printf("%s", slang_string_cstr(&without_backslashes));
+ _mesa_printf("----------------------\n");
+ }
+
+ if (success) {
+ success = preprocess_source(output,
+ slang_string_cstr(&without_backslashes),
+ pid,
+ eid,
+ elog,
+ extensions,
+ pragmas);
+ }
+
+ slang_string_free(&without_backslashes);
grammar_destroy (eid);
grammar_destroy (pid);
+
+ if (0) {
+ _mesa_printf("Post-processed shader:\n");
+ _mesa_printf("%s", slang_string_cstr(output));
+ _mesa_printf("----------------------\n");
+ }
+
return success;
}
diff --git a/src/mesa/shader/slang/slang_print.c b/src/mesa/shader/slang/slang_print.c
index bf1475f91d..98c7877534 100644
--- a/src/mesa/shader/slang/slang_print.c
+++ b/src/mesa/shader/slang/slang_print.c
@@ -261,6 +261,7 @@ slang_print_tree(const slang_operation *op, int indent)
break;
case SLANG_OPER_BLOCK_NEW_SCOPE:
+ case SLANG_OPER_NON_INLINED_CALL:
spaces(indent);
printf("{{ // new scope locals=%p outer=%p: ",
(void *) op->locals,
@@ -348,6 +349,13 @@ slang_print_tree(const slang_operation *op, int indent)
slang_print_tree(&op->children[0], indent + 3);
break;
+ case SLANG_OPER_RETURN_INLINED:
+ spaces(indent);
+ printf("RETURN_INLINED\n");
+ if (op->num_children > 0)
+ slang_print_tree(&op->children[0], indent + 3);
+ break;
+
case SLANG_OPER_LABEL:
spaces(indent);
printf("LABEL %s\n", (char *) op->a_id);
@@ -478,7 +486,7 @@ slang_print_tree(const slang_operation *op, int indent)
(void *) scope,
(void *) op->locals,
(void *) op->locals->outer_scope);
- assert(scope);
+ /*assert(scope);*/
}
}
break;
diff --git a/src/mesa/shader/slang/slang_typeinfo.c b/src/mesa/shader/slang/slang_typeinfo.c
index 1ef43f58c0..4a48bc8b8e 100644
--- a/src/mesa/shader/slang/slang_typeinfo.c
+++ b/src/mesa/shader/slang/slang_typeinfo.c
@@ -790,6 +790,7 @@ _slang_typeof_operation(slang_operation * op,
return GL_FALSE;
}
ti->can_be_referenced = _ti.can_be_referenced;
+ ti->array_len = field->array_len;
}
else {
GLuint rows;
diff --git a/src/mesa/shader/slang/slang_vartable.c b/src/mesa/shader/slang/slang_vartable.c
index de0c93957b..a4ebacc093 100644
--- a/src/mesa/shader/slang/slang_vartable.c
+++ b/src/mesa/shader/slang/slang_vartable.c
@@ -4,6 +4,7 @@
#include "shader/prog_print.h"
#include "slang_compile.h"
#include "slang_compile_variable.h"
+#include "slang_emit.h"
#include "slang_mem.h"
#include "slang_vartable.h"
#include "slang_ir.h"
@@ -72,9 +73,8 @@ _slang_delete_var_table(slang_var_table *vt)
/**
- * Create new table, put at head, return ptr to it.
- * XXX we should take a maxTemps parameter to indicate how many temporaries
- * are available for the current shader/program target.
+ * Create new table on top of vartable stack.
+ * Used when we enter a {} block.
*/
void
_slang_push_var_table(slang_var_table *vt)
@@ -95,7 +95,8 @@ _slang_push_var_table(slang_var_table *vt)
/**
- * Destroy given table, return ptr to Parent
+ * Pop top entry from variable table.
+ * Used when we leave a {} block.
*/
void
_slang_pop_var_table(slang_var_table *vt)
@@ -125,10 +126,12 @@ _slang_pop_var_table(slang_var_table *vt)
else
comp = 0;
- assert(store->Index >= 0);
- for (j = 0; j < store->Size; j++) {
- assert(t->Temps[store->Index * 4 + j + comp] == VAR);
- t->Temps[store->Index * 4 + j + comp] = FREE;
+ /* store->Index may be -1 if we run out of registers */
+ if (store->Index >= 0) {
+ for (j = 0; j < store->Size; j++) {
+ assert(t->Temps[store->Index * 4 + j + comp] == VAR);
+ t->Temps[store->Index * 4 + j + comp] = FREE;
+ }
}
store->Index = -1;
}
@@ -156,7 +159,7 @@ _slang_pop_var_table(slang_var_table *vt)
/**
- * Add a new variable to the given symbol table.
+ * Add a new variable to the given var/symbol table.
*/
void
_slang_add_variable(slang_var_table *vt, slang_variable *v)
@@ -214,6 +217,7 @@ alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
GLuint found = 0;
for (j = 0; j < (GLuint) size; j++) {
+ assert(i + j < 4 * MAX_PROGRAM_TEMPS);
if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
found++;
}
@@ -225,13 +229,17 @@ alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
/* found block of size free regs */
if (size > 1)
assert(i % 4 == 0);
- for (j = 0; j < (GLuint) size; j++)
+ for (j = 0; j < (GLuint) size; j++) {
+ assert(i + j < 4 * MAX_PROGRAM_TEMPS);
t->Temps[i + j] = isTemp ? TEMP : VAR;
+ }
assert(i < MAX_PROGRAM_TEMPS * 4);
t->ValSize[i] = size;
return i;
}
}
+
+ /* if we get here, we ran out of registers */
return -1;
}
@@ -259,21 +267,7 @@ _slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
return GL_FALSE;
store->Index = i / 4;
- if (store->Size == 1) {
- const GLuint comp = i % 4;
- store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
- }
- else if (store->Size == 2) {
- store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
- SWIZZLE_NIL, SWIZZLE_NIL);
- }
- else if (store->Size == 3) {
- store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
- SWIZZLE_Z, SWIZZLE_NIL);
- }
- else {
- store->Swizzle = SWIZZLE_NOOP;
- }
+ store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
if (dbg)
printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
@@ -301,20 +295,7 @@ _slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
assert(store->Index < 0);
store->Index = i / 4;
- if (store->Size == 1) {
- const GLuint comp = i % 4;
- store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
- }
- else {
- /* XXX improve swizzled for size=2/3, use for writemask... */
-#if 1
- if (store->Size == 2) {
- store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
- SWIZZLE_NIL, SWIZZLE_NIL);
- }
-#endif
- store->Swizzle = SWIZZLE_NOOP;
- }
+ store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
if (dbg) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
store->Size, store->Index,
diff --git a/src/mesa/shader/symbol_table.c b/src/mesa/shader/symbol_table.c
new file mode 100644
index 0000000000..7a9aa7b8f6
--- /dev/null
+++ b/src/mesa/shader/symbol_table.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright © 2008 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "symbol_table.h"
+#include "hash_table.h"
+
+struct symbol {
+ /**
+ * Link to the next symbol in the table with the same name
+ *
+ * The linked list of symbols with the same name is ordered by scope
+ * from inner-most to outer-most.
+ */
+ struct symbol *next_with_same_name;
+
+
+ /**
+ * Link to the next symbol in the table with the same scope
+ *
+ * The linked list of symbols with the same scope is unordered. Symbols
+ * in this list my have unique names.
+ */
+ struct symbol *next_with_same_scope;
+
+
+ /**
+ * Header information for the list of symbols with the same name.
+ */
+ struct symbol_header *hdr;
+
+
+ /**
+ * Name space of the symbol
+ *
+ * Name space are arbitrary user assigned integers. No two symbols can
+ * exist in the same name space at the same scope level.
+ */
+ int name_space;
+
+
+ /**
+ * Arbitrary user supplied data.
+ */
+ void *data;
+};
+
+
+/**
+ */
+struct symbol_header {
+ /** Symbol name. */
+ const char *name;
+
+ /** Linked list of symbols with the same name. */
+ struct symbol *symbols;
+};
+
+
+/**
+ * Element of the scope stack.
+ */
+struct scope_level {
+ /** Link to next (inner) scope level. */
+ struct scope_level *next;
+
+ /** Linked list of symbols with the same scope. */
+ struct symbol *symbols;
+};
+
+
+/**
+ *
+ */
+struct _mesa_symbol_table {
+ /** Hash table containing all symbols in the symbol table. */
+ struct hash_table *ht;
+
+ /** Top of scope stack. */
+ struct scope_level *current_scope;
+};
+
+
+struct _mesa_symbol_table_iterator {
+ /**
+ * Name space of symbols returned by this iterator.
+ */
+ int name_space;
+
+
+ /**
+ * Currently iterated symbol
+ *
+ * The next call to \c _mesa_symbol_table_iterator_get will return this
+ * value. It will also update this value to the value that should be
+ * returned by the next call.
+ */
+ struct symbol *curr;
+};
+
+
+static void
+check_symbol_table(struct _mesa_symbol_table *table)
+{
+#if 1
+ struct scope_level *scope;
+
+ for (scope = table->current_scope; scope != NULL; scope = scope->next) {
+ struct symbol *sym;
+
+ for (sym = scope->symbols
+ ; sym != NULL
+ ; sym = sym->next_with_same_name) {
+ const struct symbol_header *const hdr = sym->hdr;
+ struct symbol *sym2;
+
+ for (sym2 = hdr->symbols
+ ; sym2 != NULL
+ ; sym2 = sym2->next_with_same_name) {
+ assert(sym2->hdr == hdr);
+ }
+ }
+ }
+#endif
+}
+
+void
+_mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table)
+{
+ struct scope_level *const scope = table->current_scope;
+ struct symbol *sym = scope->symbols;
+
+ table->current_scope = scope->next;
+
+ free(scope);
+
+ while (sym != NULL) {
+ struct symbol *const next = sym->next_with_same_scope;
+ struct symbol_header *const hdr = sym->hdr;
+
+ assert(hdr->symbols == sym);
+
+ hdr->symbols = sym->next_with_same_name;
+
+ free(sym);
+
+ sym = next;
+ }
+
+ check_symbol_table(table);
+}
+
+
+void
+_mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
+{
+ struct scope_level *const scope = calloc(1, sizeof(*scope));
+
+ scope->next = table->current_scope;
+ table->current_scope = scope;
+}
+
+
+static struct symbol_header *
+find_symbol(struct _mesa_symbol_table *table, const char *name)
+{
+ return (struct symbol_header *) hash_table_find(table->ht, name);
+}
+
+
+struct _mesa_symbol_table_iterator *
+_mesa_symbol_table_iterator_ctor(struct _mesa_symbol_table *table,
+ int name_space, const char *name)
+{
+ struct _mesa_symbol_table_iterator *iter = calloc(1, sizeof(*iter));
+ struct symbol_header *const hdr = find_symbol(table, name);
+
+ iter->name_space = name_space;
+
+ if (hdr != NULL) {
+ struct symbol *sym;
+
+ for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
+ assert(sym->hdr == hdr);
+
+ if ((name_space == -1) || (sym->name_space == name_space)) {
+ iter->curr = sym;
+ break;
+ }
+ }
+ }
+
+ return iter;
+}
+
+
+void
+_mesa_symbol_table_iterator_dtor(struct _mesa_symbol_table_iterator *iter)
+{
+ free(iter);
+}
+
+
+void *
+_mesa_symbol_table_iterator_get(struct _mesa_symbol_table_iterator *iter)
+{
+ return (iter->curr == NULL) ? NULL : iter->curr->data;
+}
+
+
+int
+_mesa_symbol_table_iterator_next(struct _mesa_symbol_table_iterator *iter)
+{
+ struct symbol_header *hdr;
+
+ if (iter->curr == NULL) {
+ return 0;
+ }
+
+ hdr = iter->curr->hdr;
+ iter->curr = iter->curr->next_with_same_name;
+
+ while (iter->curr != NULL) {
+ assert(iter->curr->hdr == hdr);
+
+ if ((iter->name_space == -1)
+ || (iter->curr->name_space == iter->name_space)) {
+ return 1;
+ }
+
+ iter->curr = iter->curr->next_with_same_name;
+ }
+
+ return 0;
+}
+
+
+void *
+_mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table,
+ int name_space, const char *name)
+{
+ struct symbol_header *const hdr = find_symbol(table, name);
+
+ if (hdr != NULL) {
+ struct symbol *sym;
+
+
+ for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
+ assert(sym->hdr == hdr);
+
+ if ((name_space == -1) || (sym->name_space == name_space)) {
+ return sym->data;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+int
+_mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
+ int name_space, const char *name,
+ void *declaration)
+{
+ struct symbol_header *hdr;
+ struct symbol *sym;
+
+ check_symbol_table(table);
+
+ hdr = find_symbol(table, name);
+
+ check_symbol_table(table);
+
+ if (hdr == NULL) {
+ hdr = calloc(1, sizeof(*hdr));
+ hdr->name = name;
+
+ hash_table_insert(table->ht, hdr, name);
+ }
+
+ check_symbol_table(table);
+
+ sym = calloc(1, sizeof(*sym));
+ sym->next_with_same_name = hdr->symbols;
+ sym->next_with_same_scope = table->current_scope->symbols;
+ sym->hdr = hdr;
+ sym->name_space = name_space;
+ sym->data = declaration;
+
+ assert(sym->hdr == hdr);
+
+ hdr->symbols = sym;
+ table->current_scope->symbols = sym;
+
+ check_symbol_table(table);
+ return 0;
+}
+
+
+struct _mesa_symbol_table *
+_mesa_symbol_table_ctor(void)
+{
+ struct _mesa_symbol_table *table = calloc(1, sizeof(*table));
+
+ if (table != NULL) {
+ table->ht = hash_table_ctor(32, hash_table_string_hash,
+ hash_table_string_compare);
+
+ _mesa_symbol_table_push_scope(table);
+ }
+
+ return table;
+}
+
+
+void
+_mesa_symbol_table_dtor(struct _mesa_symbol_table *table)
+{
+ while (table->current_scope != NULL) {
+ _mesa_symbol_table_pop_scope(table);
+ }
+
+ hash_table_dtor(table->ht);
+ free(table);
+}
diff --git a/src/mesa/shader/symbol_table.h b/src/mesa/shader/symbol_table.h
new file mode 100644
index 0000000000..0c054ef139
--- /dev/null
+++ b/src/mesa/shader/symbol_table.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifndef MESA_SYMBOL_TABLE_H
+#define MESA_SYMBOL_TABLE_H
+
+struct _mesa_symbol_table;
+struct _mesa_symbol_table_iterator;
+
+extern void _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table);
+
+extern void _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table);
+
+extern int _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *symtab,
+ int name_space, const char *name, void *declaration);
+
+extern void *_mesa_symbol_table_find_symbol(
+ struct _mesa_symbol_table *symtab, int name_space, const char *name);
+
+extern struct _mesa_symbol_table *_mesa_symbol_table_ctor(void);
+
+extern void _mesa_symbol_table_dtor(struct _mesa_symbol_table *);
+
+extern struct _mesa_symbol_table_iterator *_mesa_symbol_table_iterator_ctor(
+ struct _mesa_symbol_table *table, int name_space, const char *name);
+
+extern void _mesa_symbol_table_iterator_dtor(
+ struct _mesa_symbol_table_iterator *);
+
+extern void *_mesa_symbol_table_iterator_get(
+ struct _mesa_symbol_table_iterator *iter);
+
+extern int _mesa_symbol_table_iterator_next(
+ struct _mesa_symbol_table_iterator *iter);
+
+#endif /* MESA_SYMBOL_TABLE_H */
diff --git a/src/mesa/sources b/src/mesa/sources.mak
index 01a3fb89e6..fa2a6307a4 100644
--- a/src/mesa/sources
+++ b/src/mesa/sources.mak
@@ -17,6 +17,7 @@ MAIN_SOURCES = \
main/colortab.c \
main/context.c \
main/convolve.c \
+ main/cpuinfo.c \
main/debug.c \
main/depth.c \
main/depthstencil.c \
@@ -57,8 +58,10 @@ MAIN_SOURCES = \
main/renderbuffer.c \
main/scissor.c \
main/shaders.c \
+ main/shared.c \
main/state.c \
main/stencil.c \
+ main/syncobj.c \
main/texcompress.c \
main/texcompress_s3tc.c \
main/texcompress_fxt1.c \
@@ -66,6 +69,7 @@ MAIN_SOURCES = \
main/texenvprogram.c \
main/texformat.c \
main/texgen.c \
+ main/texgetimage.c \
main/teximage.c \
main/texobj.c \
main/texparam.c \
@@ -73,6 +77,7 @@ MAIN_SOURCES = \
main/texstate.c \
main/texstore.c \
main/varray.c \
+ main/viewport.c \
main/vtxfmt.c
GLAPI_SOURCES = \
@@ -88,7 +93,9 @@ MATH_SOURCES = \
math/m_eval.c \
math/m_matrix.c \
math/m_translate.c \
- math/m_vector.c \
+ math/m_vector.c
+
+MATH_XFORM_SOURCES = \
math/m_xform.c
SWRAST_SOURCES = \
@@ -100,7 +107,7 @@ SWRAST_SOURCES = \
swrast/s_bitmap.c \
swrast/s_blend.c \
swrast/s_blit.c \
- swrast/s_buffers.c \
+ swrast/s_clear.c \
swrast/s_copypix.c \
swrast/s_context.c \
swrast/s_depth.c \
@@ -162,27 +169,77 @@ VBO_SOURCES = \
vbo/vbo_save_draw.c \
vbo/vbo_save_loopback.c
+STATETRACKER_SOURCES = \
+ state_tracker/st_atom.c \
+ state_tracker/st_atom_blend.c \
+ state_tracker/st_atom_clip.c \
+ state_tracker/st_atom_constbuf.c \
+ state_tracker/st_atom_depth.c \
+ state_tracker/st_atom_framebuffer.c \
+ state_tracker/st_atom_pixeltransfer.c \
+ state_tracker/st_atom_sampler.c \
+ state_tracker/st_atom_scissor.c \
+ state_tracker/st_atom_shader.c \
+ state_tracker/st_atom_rasterizer.c \
+ state_tracker/st_atom_stipple.c \
+ state_tracker/st_atom_texture.c \
+ state_tracker/st_atom_viewport.c \
+ state_tracker/st_cb_accum.c \
+ state_tracker/st_cb_bitmap.c \
+ state_tracker/st_cb_blit.c \
+ state_tracker/st_cb_bufferobjects.c \
+ state_tracker/st_cb_clear.c \
+ state_tracker/st_cb_flush.c \
+ state_tracker/st_cb_get.c \
+ state_tracker/st_cb_drawpixels.c \
+ state_tracker/st_cb_fbo.c \
+ state_tracker/st_cb_feedback.c \
+ state_tracker/st_cb_program.c \
+ state_tracker/st_cb_queryobj.c \
+ state_tracker/st_cb_rasterpos.c \
+ state_tracker/st_cb_readpixels.c \
+ state_tracker/st_cb_strings.c \
+ state_tracker/st_cb_texture.c \
+ state_tracker/st_cb_viewport.c \
+ state_tracker/st_api.c \
+ state_tracker/st_context.c \
+ state_tracker/st_debug.c \
+ state_tracker/st_draw.c \
+ state_tracker/st_draw_feedback.c \
+ state_tracker/st_extensions.c \
+ state_tracker/st_format.c \
+ state_tracker/st_framebuffer.c \
+ state_tracker/st_gen_mipmap.c \
+ state_tracker/st_mesa_to_tgsi.c \
+ state_tracker/st_program.c \
+ state_tracker/st_texture.c
SHADER_SOURCES = \
shader/arbprogparse.c \
shader/arbprogram.c \
shader/atifragshader.c \
shader/grammar/grammar_mesa.c \
+ shader/hash_table.c \
+ shader/lex.yy.c \
shader/nvfragparse.c \
shader/nvprogram.c \
shader/nvvertparse.c \
shader/program.c \
+ shader/program_parse.tab.c \
+ shader/program_parse_extra.c \
shader/prog_cache.c \
- shader/prog_debug.c \
shader/prog_execute.c \
shader/prog_instruction.c \
shader/prog_noise.c \
+ shader/prog_optimize.c \
shader/prog_parameter.c \
+ shader/prog_parameter_layout.c \
shader/prog_print.c \
shader/prog_statevars.c \
shader/prog_uniform.c \
shader/programopt.c \
- shader/shader_api.c \
+ shader/symbol_table.c \
+ shader/shader_api.c
SLANG_SOURCES = \
shader/slang/slang_builtin.c \
@@ -208,7 +265,7 @@ SLANG_SOURCES = \
ASM_C_SOURCES = \
x86/common_x86.c \
- x86/x86.c \
+ x86/x86_xform.c \
x86/3dnow.c \
x86/sse.c \
x86/rtasm/x86sse.c \
@@ -253,41 +310,56 @@ SPARC_API = \
sparc/glapi_sparc.S
COMMON_DRIVER_SOURCES = \
- drivers/common/driverfuncs.c
-
-
+ drivers/common/driverfuncs.c \
+ drivers/common/meta.c
-### All the core C sources
+# Sources for building non-Gallium drivers
MESA_SOURCES = \
$(MAIN_SOURCES) \
$(MATH_SOURCES) \
+ $(MATH_XFORM_SOURCES) \
$(VBO_SOURCES) \
$(TNL_SOURCES) \
$(SHADER_SOURCES) \
$(SWRAST_SOURCES) \
$(SWRAST_SETUP_SOURCES) \
- $(COMMON_DRIVER_SOURCES) \
+ $(COMMON_DRIVER_SOURCES)\
$(ASM_C_SOURCES) \
$(SLANG_SOURCES)
+# Sources for building Gallium drivers
+MESA_GALLIUM_SOURCES = \
+ $(MAIN_SOURCES) \
+ $(MATH_SOURCES) \
+ $(VBO_SOURCES) \
+ $(STATETRACKER_SOURCES) \
+ $(SHADER_SOURCES) \
+ ppc/common_ppc.c \
+ x86/common_x86.c \
+ $(SLANG_SOURCES)
+
+# All the core C sources, for dependency checking
ALL_SOURCES = \
$(MESA_SOURCES) \
$(GLAPI_SOURCES) \
- $(ASM_SOURCES) \
- $(COMMON_DRIVER_SOURCES)
-
+ $(MESA_ASM_SOURCES) \
+ $(STATETRACKER_SOURCES)
### Object files
MESA_OBJECTS = \
$(MESA_SOURCES:.c=.o) \
- $(ASM_SOURCES:.S=.o)
+ $(MESA_ASM_SOURCES:.S=.o)
+
+MESA_GALLIUM_OBJECTS = \
+ $(MESA_GALLIUM_SOURCES:.c=.o) \
+ $(MESA_ASM_SOURCES:.S=.o)
GLAPI_OBJECTS = \
$(GLAPI_SOURCES:.c=.o) \
- $(ASM_API:.S=.o)
+ $(GLAPI_ASM_SOURCES:.S=.o)
COMMON_DRIVER_OBJECTS = $(COMMON_DRIVER_SOURCES:.c=.o)
@@ -295,11 +367,9 @@ COMMON_DRIVER_OBJECTS = $(COMMON_DRIVER_SOURCES:.c=.o)
### Include directories
-### XXX we should be able to trim this down to just -Iinclude/ and -Isrc/mesa/
-### since most #includes have been changed from #include "mtypes.h" to
-### #include "main/mtypes.h", etc.
INCLUDE_DIRS = \
-I$(TOP)/include \
-I$(TOP)/src/mesa \
- -I$(TOP)/src/mesa/main
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary
diff --git a/src/mesa/sparc/clip.S b/src/mesa/sparc/clip.S
index 58c228ed15..dc239171ff 100644
--- a/src/mesa/sparc/clip.S
+++ b/src/mesa/sparc/clip.S
@@ -25,12 +25,8 @@
#define VEC_SIZE_3 7
#define VEC_SIZE_4 15
-#if defined(SVR4) || defined(__SVR4) || defined(__svr4__)
- /* Solaris requires this for 64-bit. */
.register %g2, #scratch
.register %g3, #scratch
- .register %g7, #scratch
-#endif
.text
.align 64
@@ -62,7 +58,8 @@ clip_table:
.byte 31, 29, 31, 30, 27, 25, 27, 26
/* GLvector4f *clip_vec, GLvector4f *proj_vec,
- GLubyte clipMask[], GLubyte *orMask, GLubyte *andMask */
+ GLubyte clipMask[], GLubyte *orMask, GLubyte *andMask,
+ GLboolean viewport_z_enable */
.align 64
__pc_tramp:
@@ -78,7 +75,7 @@ _mesa_sparc_cliptest_points4:
add %g1, 0x4, %g1
ld [%i0 + V4F_STRIDE], %l1
- ld [%i0 + V4F_COUNT], %g7
+ ld [%i0 + V4F_COUNT], %l3
LDPTR [%i0 + V4F_START], %i0
LDPTR [%i1 + V4F_START], %i5
ldub [%i3], %g2
@@ -91,12 +88,12 @@ _mesa_sparc_cliptest_points4:
st %g3, [%i1 + V4F_FLAGS]
mov 3, %g3
st %g3, [%i1 + V4F_SIZE]
- st %g7, [%i1 + V4F_COUNT]
+ st %l3, [%i1 + V4F_COUNT]
clr %l2
clr %l0
/* l0: i
- * g7: count
+ * l3: count
* l1: stride
* l2: c
* g2: (tmpAndMask << 8) | tmpOrMask
@@ -153,12 +150,12 @@ _mesa_sparc_cliptest_points4:
3: add %i5, 0x10, %i5 ! IEU1
add %l0, 1, %l0 ! IEU0 Group
add %i2, 1, %i2 ! IEU0 Group
- cmp %l0, %g7 ! IEU1 Group
+ cmp %l0, %l3 ! IEU1 Group
bne 1b ! CTI
add %i0, %l1, %i0 ! IEU0 Group
stb %g2, [%i3] ! LSU
srl %g2, 8, %g3 ! IEU0 Group
- cmp %l2, %g7 ! IEU1 Group
+ cmp %l2, %l3 ! IEU1 Group
bl,a 1f ! CTI
clr %g3 ! IEU0
1: stb %g3, [%i4] ! LSU Group
@@ -174,25 +171,18 @@ _mesa_sparc_cliptest_points4_np:
add %g1, 0x4, %g1
ld [%i0 + V4F_STRIDE], %l1
- ld [%i0 + V4F_COUNT], %g7
+ ld [%i0 + V4F_COUNT], %l3
LDPTR [%i0 + V4F_START], %i0
- LDPTR [%i1 + V4F_START], %i5
ldub [%i3], %g2
ldub [%i4], %g3
sll %g3, 8, %g3
or %g2, %g3, %g2
- ld [%i1 + V4F_FLAGS], %g3
- or %g3, VEC_SIZE_4, %g3
- st %g3, [%i1 + V4F_FLAGS]
- mov 3, %g3
- st %g3, [%i1 + V4F_SIZE]
- st %g7, [%i1 + V4F_COUNT]
clr %l2
clr %l0
/* l0: i
- * g7: count
+ * l3: count
* l1: stride
* l2: c
* g2: (tmpAndMask << 8) | tmpOrMask
@@ -230,12 +220,12 @@ _mesa_sparc_cliptest_points4_np:
and %g2, %g4, %g2 ! IEU0 Group
2: add %l0, 1, %l0 ! IEU0 Group
add %i2, 1, %i2 ! IEU0 Group
- cmp %l0, %g7 ! IEU1 Group
+ cmp %l0, %l3 ! IEU1 Group
bne 1b ! CTI
add %i0, %l1, %i0 ! IEU0 Group
stb %g2, [%i3] ! LSU
srl %g2, 8, %g3 ! IEU0 Group
- cmp %l2, %g7 ! IEU1 Group
+ cmp %l2, %l3 ! IEU1 Group
bl,a 1f ! CTI
clr %g3 ! IEU0
1: stb %g3, [%i4] ! LSU Group
diff --git a/src/mesa/sparc/glapi_sparc.S b/src/mesa/sparc/glapi_sparc.S
index 3d1d55fd76..50a2037034 100644
--- a/src/mesa/sparc/glapi_sparc.S
+++ b/src/mesa/sparc/glapi_sparc.S
@@ -26,817 +26,176 @@
* SOFTWARE.
*/
-#include "glapioffsets.h"
+#include "glapi/glapioffsets.h"
#ifdef __arch64__
-# define GL_STUB(fn,off) \
-fn: \
- sethi %hi(0xDEADBEEF), %g4 ; \
- sethi %hi(0xDEADBEEF), %g1 ; \
- or %g4, %lo(0xDEADBEEF), %g4 ; \
- or %g1, %lo(0xDEADBEEF), %g1 ; \
- sllx %g4, 32, %g4 ; \
- ldx [%g1 + %g4], %g1 ; \
- sethi %hi(8 * off), %g4 ; \
- or %g4, %lo(8 * off), %g4 ; \
- ldx [%g1 + %g4], %g5 ; \
- jmpl %g5, %g0 ; \
- nop
+#define GL_OFF(N) ((N) * 8)
+#define GL_LL ldx
+#define GL_TIE_LD(SYM) %tie_ldx(SYM)
+#define GL_STACK_SIZE 128
#else
-# define GL_STUB(fn,off) \
-fn: \
- sethi %hi(0xDEADBEEF), %g1 ; \
- ld [%g1 + %lo(0xDEADBEEF)], %g1 ; \
- ld [%g1 + (4 * off)], %g5 ; \
- jmpl %g5, %g0 ; \
- nop
+#define GL_OFF(N) ((N) * 4)
+#define GL_LL ld
+#define GL_TIE_LD(SYM) %tie_ld(SYM)
+#define GL_STACK_SIZE 64
#endif
-#define GL_STUB_ALIAS(fn,alias) fn = alias
+#define GLOBL_FN(x) .globl x ; .type x, @function
+#define HIDDEN(x) .hidden x
-.text
-.align 32
- .globl __glapi_sparc_icache_flush ; .type __glapi_sparc_icache_flush,#function
+ .register %g2, #scratch
+ .register %g3, #scratch
+
+ .text
+
+ GLOBL_FN(__glapi_sparc_icache_flush)
+ HIDDEN(__glapi_sparc_icache_flush)
+ .type __glapi_sparc_icache_flush, @function
__glapi_sparc_icache_flush: /* %o0 = insn_addr */
flush %o0
retl
- nop
+ nop
+
+ .align 32
+
+ .type __glapi_sparc_get_pc, @function
+__glapi_sparc_get_pc:
+ retl
+ add %o7, %g2, %g2
+ .size __glapi_sparc_get_pc, .-__glapi_sparc_get_pc
+
+#ifdef GLX_USE_TLS
+
+ GLOBL_FN(__glapi_sparc_get_dispatch)
+ HIDDEN(__glapi_sparc_get_dispatch)
+__glapi_sparc_get_dispatch:
+ mov %o7, %g1
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %g2
+ call __glapi_sparc_get_pc
+ add %g2, %lo(_GLOBAL_OFFSET_TABLE_+4), %g2
+ mov %g1, %o7
+ sethi %tie_hi22(_glapi_tls_Dispatch), %g1
+ add %g1, %tie_lo10(_glapi_tls_Dispatch), %g1
+ GL_LL [%g2 + %g1], %g2, GL_TIE_LD(_glapi_tls_Dispatch)
+ retl
+ mov %g2, %o0
+
+ .data
+ .align 32
+
+ /* --> sethi %hi(_glapi_tls_Dispatch), %g1 */
+ /* --> or %g1, %lo(_glapi_tls_Dispatch), %g1 */
+ GLOBL_FN(__glapi_sparc_tls_stub)
+ HIDDEN(__glapi_sparc_tls_stub)
+__glapi_sparc_tls_stub: /* Call offset in %g3 */
+ mov %o7, %g1
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %g2
+ call __glapi_sparc_get_pc
+ add %g2, %lo(_GLOBAL_OFFSET_TABLE_+4), %g2
+ mov %g1, %o7
+ srl %g3, 10, %g3
+ sethi %tie_hi22(_glapi_tls_Dispatch), %g1
+ add %g1, %tie_lo10(_glapi_tls_Dispatch), %g1
+ GL_LL [%g2 + %g1], %g2, GL_TIE_LD(_glapi_tls_Dispatch)
+ GL_LL [%g7+%g2], %g1
+ GL_LL [%g1 + %g3], %g1
+ jmp %g1
+ nop
+ .size __glapi_sparc_tls_stub, .-__glapi_sparc_tls_stub
+
+#define GL_STUB(fn, off) \
+ GLOBL_FN(fn); \
+fn: ba __glapi_sparc_tls_stub; \
+ sethi GL_OFF(off), %g3; \
+ .size fn,.-fn;
+
+#elif defined(PTHREADS)
+
+ /* 64-bit 0x00 --> sethi %hh(_glapi_Dispatch), %g1 */
+ /* 64-bit 0x04 --> sethi %lm(_glapi_Dispatch), %g2 */
+ /* 64-bit 0x08 --> or %g1, %hm(_glapi_Dispatch), %g1 */
+ /* 64-bit 0x0c --> sllx %g1, 32, %g1 */
+ /* 64-bit 0x10 --> add %g1, %g2, %g1 */
+ /* 64-bit 0x14 --> ldx [%g1 + %lo(_glapi_Dispatch)], %g1 */
-.data
-.align 64
+ /* 32-bit 0x00 --> sethi %hi(_glapi_Dispatch), %g1 */
+ /* 32-bit 0x04 --> ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
- .globl glNewList ; .type glNewList,#function
- .globl glEndList ; .type glEndList,#function
- .globl glCallList ; .type glCallList,#function
- .globl glCallLists ; .type glCallLists,#function
- .globl glDeleteLists ; .type glDeleteLists,#function
- .globl glGenLists ; .type glGenLists,#function
- .globl glListBase ; .type glListBase,#function
- .globl glBegin ; .type glBegin,#function
- .globl glBitmap ; .type glBitmap,#function
- .globl glColor3b ; .type glColor3b,#function
- .globl glColor3bv ; .type glColor3bv,#function
- .globl glColor3d ; .type glColor3d,#function
- .globl glColor3dv ; .type glColor3dv,#function
- .globl glColor3f ; .type glColor3f,#function
- .globl glColor3fv ; .type glColor3fv,#function
- .globl glColor3i ; .type glColor3i,#function
- .globl glColor3iv ; .type glColor3iv,#function
- .globl glColor3s ; .type glColor3s,#function
- .globl glColor3sv ; .type glColor3sv,#function
- .globl glColor3ub ; .type glColor3ub,#function
- .globl glColor3ubv ; .type glColor3ubv,#function
- .globl glColor3ui ; .type glColor3ui,#function
- .globl glColor3uiv ; .type glColor3uiv,#function
- .globl glColor3us ; .type glColor3us,#function
- .globl glColor3usv ; .type glColor3usv,#function
- .globl glColor4b ; .type glColor4b,#function
- .globl glColor4bv ; .type glColor4bv,#function
- .globl glColor4d ; .type glColor4d,#function
- .globl glColor4dv ; .type glColor4dv,#function
- .globl glColor4f ; .type glColor4f,#function
- .globl glColor4fv ; .type glColor4fv,#function
- .globl glColor4i ; .type glColor4i,#function
- .globl glColor4iv ; .type glColor4iv,#function
- .globl glColor4s ; .type glColor4s,#function
- .globl glColor4sv ; .type glColor4sv,#function
- .globl glColor4ub ; .type glColor4ub,#function
- .globl glColor4ubv ; .type glColor4ubv,#function
- .globl glColor4ui ; .type glColor4ui,#function
- .globl glColor4uiv ; .type glColor4uiv,#function
- .globl glColor4us ; .type glColor4us,#function
- .globl glColor4usv ; .type glColor4usv,#function
- .globl glEdgeFlag ; .type glEdgeFlag,#function
- .globl glEdgeFlagv ; .type glEdgeFlagv,#function
- .globl glEnd ; .type glEnd,#function
- .globl glIndexd ; .type glIndexd,#function
- .globl glIndexdv ; .type glIndexdv,#function
- .globl glIndexf ; .type glIndexf,#function
- .globl glIndexfv ; .type glIndexfv,#function
- .globl glIndexi ; .type glIndexi,#function
- .globl glIndexiv ; .type glIndexiv,#function
- .globl glIndexs ; .type glIndexs,#function
- .globl glIndexsv ; .type glIndexsv,#function
- .globl glNormal3b ; .type glNormal3b,#function
- .globl glNormal3bv ; .type glNormal3bv,#function
- .globl glNormal3d ; .type glNormal3d,#function
- .globl glNormal3dv ; .type glNormal3dv,#function
- .globl glNormal3f ; .type glNormal3f,#function
- .globl glNormal3fv ; .type glNormal3fv,#function
- .globl glNormal3i ; .type glNormal3i,#function
- .globl glNormal3iv ; .type glNormal3iv,#function
- .globl glNormal3s ; .type glNormal3s,#function
- .globl glNormal3sv ; .type glNormal3sv,#function
- .globl glRasterPos2d ; .type glRasterPos2d,#function
- .globl glRasterPos2dv ; .type glRasterPos2dv,#function
- .globl glRasterPos2f ; .type glRasterPos2f,#function
- .globl glRasterPos2fv ; .type glRasterPos2fv,#function
- .globl glRasterPos2i ; .type glRasterPos2i,#function
- .globl glRasterPos2iv ; .type glRasterPos2iv,#function
- .globl glRasterPos2s ; .type glRasterPos2s,#function
- .globl glRasterPos2sv ; .type glRasterPos2sv,#function
- .globl glRasterPos3d ; .type glRasterPos3d,#function
- .globl glRasterPos3dv ; .type glRasterPos3dv,#function
- .globl glRasterPos3f ; .type glRasterPos3f,#function
- .globl glRasterPos3fv ; .type glRasterPos3fv,#function
- .globl glRasterPos3i ; .type glRasterPos3i,#function
- .globl glRasterPos3iv ; .type glRasterPos3iv,#function
- .globl glRasterPos3s ; .type glRasterPos3s,#function
- .globl glRasterPos3sv ; .type glRasterPos3sv,#function
- .globl glRasterPos4d ; .type glRasterPos4d,#function
- .globl glRasterPos4dv ; .type glRasterPos4dv,#function
- .globl glRasterPos4f ; .type glRasterPos4f,#function
- .globl glRasterPos4fv ; .type glRasterPos4fv,#function
- .globl glRasterPos4i ; .type glRasterPos4i,#function
- .globl glRasterPos4iv ; .type glRasterPos4iv,#function
- .globl glRasterPos4s ; .type glRasterPos4s,#function
- .globl glRasterPos4sv ; .type glRasterPos4sv,#function
- .globl glRectd ; .type glRectd,#function
- .globl glRectdv ; .type glRectdv,#function
- .globl glRectf ; .type glRectf,#function
- .globl glRectfv ; .type glRectfv,#function
- .globl glRecti ; .type glRecti,#function
- .globl glRectiv ; .type glRectiv,#function
- .globl glRects ; .type glRects,#function
- .globl glRectsv ; .type glRectsv,#function
- .globl glTexCoord1d ; .type glTexCoord1d,#function
- .globl glTexCoord1dv ; .type glTexCoord1dv,#function
- .globl glTexCoord1f ; .type glTexCoord1f,#function
- .globl glTexCoord1fv ; .type glTexCoord1fv,#function
- .globl glTexCoord1i ; .type glTexCoord1i,#function
- .globl glTexCoord1iv ; .type glTexCoord1iv,#function
- .globl glTexCoord1s ; .type glTexCoord1s,#function
- .globl glTexCoord1sv ; .type glTexCoord1sv,#function
- .globl glTexCoord2d ; .type glTexCoord2d,#function
- .globl glTexCoord2dv ; .type glTexCoord2dv,#function
- .globl glTexCoord2f ; .type glTexCoord2f,#function
- .globl glTexCoord2fv ; .type glTexCoord2fv,#function
- .globl glTexCoord2i ; .type glTexCoord2i,#function
- .globl glTexCoord2iv ; .type glTexCoord2iv,#function
- .globl glTexCoord2s ; .type glTexCoord2s,#function
- .globl glTexCoord2sv ; .type glTexCoord2sv,#function
- .globl glTexCoord3d ; .type glTexCoord3d,#function
- .globl glTexCoord3dv ; .type glTexCoord3dv,#function
- .globl glTexCoord3f ; .type glTexCoord3f,#function
- .globl glTexCoord3fv ; .type glTexCoord3fv,#function
- .globl glTexCoord3i ; .type glTexCoord3i,#function
- .globl glTexCoord3iv ; .type glTexCoord3iv,#function
- .globl glTexCoord3s ; .type glTexCoord3s,#function
- .globl glTexCoord3sv ; .type glTexCoord3sv,#function
- .globl glTexCoord4d ; .type glTexCoord4d,#function
- .globl glTexCoord4dv ; .type glTexCoord4dv,#function
- .globl glTexCoord4f ; .type glTexCoord4f,#function
- .globl glTexCoord4fv ; .type glTexCoord4fv,#function
- .globl glTexCoord4i ; .type glTexCoord4i,#function
- .globl glTexCoord4iv ; .type glTexCoord4iv,#function
- .globl glTexCoord4s ; .type glTexCoord4s,#function
- .globl glTexCoord4sv ; .type glTexCoord4sv,#function
- .globl glVertex2d ; .type glVertex2d,#function
- .globl glVertex2dv ; .type glVertex2dv,#function
- .globl glVertex2f ; .type glVertex2f,#function
- .globl glVertex2fv ; .type glVertex2fv,#function
- .globl glVertex2i ; .type glVertex2i,#function
- .globl glVertex2iv ; .type glVertex2iv,#function
- .globl glVertex2s ; .type glVertex2s,#function
- .globl glVertex2sv ; .type glVertex2sv,#function
- .globl glVertex3d ; .type glVertex3d,#function
- .globl glVertex3dv ; .type glVertex3dv,#function
- .globl glVertex3f ; .type glVertex3f,#function
- .globl glVertex3fv ; .type glVertex3fv,#function
- .globl glVertex3i ; .type glVertex3i,#function
- .globl glVertex3iv ; .type glVertex3iv,#function
- .globl glVertex3s ; .type glVertex3s,#function
- .globl glVertex3sv ; .type glVertex3sv,#function
- .globl glVertex4d ; .type glVertex4d,#function
- .globl glVertex4dv ; .type glVertex4dv,#function
- .globl glVertex4f ; .type glVertex4f,#function
- .globl glVertex4fv ; .type glVertex4fv,#function
- .globl glVertex4i ; .type glVertex4i,#function
- .globl glVertex4iv ; .type glVertex4iv,#function
- .globl glVertex4s ; .type glVertex4s,#function
- .globl glVertex4sv ; .type glVertex4sv,#function
- .globl glClipPlane ; .type glClipPlane,#function
- .globl glColorMaterial ; .type glColorMaterial,#function
- .globl glCullFace ; .type glCullFace,#function
- .globl glFogf ; .type glFogf,#function
- .globl glFogfv ; .type glFogfv,#function
- .globl glFogi ; .type glFogi,#function
- .globl glFogiv ; .type glFogiv,#function
- .globl glFrontFace ; .type glFrontFace,#function
- .globl glHint ; .type glHint,#function
- .globl glLightf ; .type glLightf,#function
- .globl glLightfv ; .type glLightfv,#function
- .globl glLighti ; .type glLighti,#function
- .globl glLightiv ; .type glLightiv,#function
- .globl glLightModelf ; .type glLightModelf,#function
- .globl glLightModelfv ; .type glLightModelfv,#function
- .globl glLightModeli ; .type glLightModeli,#function
- .globl glLightModeliv ; .type glLightModeliv,#function
- .globl glLineStipple ; .type glLineStipple,#function
- .globl glLineWidth ; .type glLineWidth,#function
- .globl glMaterialf ; .type glMaterialf,#function
- .globl glMaterialfv ; .type glMaterialfv,#function
- .globl glMateriali ; .type glMateriali,#function
- .globl glMaterialiv ; .type glMaterialiv,#function
- .globl glPointSize ; .type glPointSize,#function
- .globl glPolygonMode ; .type glPolygonMode,#function
- .globl glPolygonStipple ; .type glPolygonStipple,#function
- .globl glScissor ; .type glScissor,#function
- .globl glShadeModel ; .type glShadeModel,#function
- .globl glTexParameterf ; .type glTexParameterf,#function
- .globl glTexParameterfv ; .type glTexParameterfv,#function
- .globl glTexParameteri ; .type glTexParameteri,#function
- .globl glTexParameteriv ; .type glTexParameteriv,#function
- .globl glTexImage1D ; .type glTexImage1D,#function
- .globl glTexImage2D ; .type glTexImage2D,#function
- .globl glTexEnvf ; .type glTexEnvf,#function
- .globl glTexEnvfv ; .type glTexEnvfv,#function
- .globl glTexEnvi ; .type glTexEnvi,#function
- .globl glTexEnviv ; .type glTexEnviv,#function
- .globl glTexGend ; .type glTexGend,#function
- .globl glTexGendv ; .type glTexGendv,#function
- .globl glTexGenf ; .type glTexGenf,#function
- .globl glTexGenfv ; .type glTexGenfv,#function
- .globl glTexGeni ; .type glTexGeni,#function
- .globl glTexGeniv ; .type glTexGeniv,#function
- .globl glFeedbackBuffer ; .type glFeedbackBuffer,#function
- .globl glSelectBuffer ; .type glSelectBuffer,#function
- .globl glRenderMode ; .type glRenderMode,#function
- .globl glInitNames ; .type glInitNames,#function
- .globl glLoadName ; .type glLoadName,#function
- .globl glPassThrough ; .type glPassThrough,#function
- .globl glPopName ; .type glPopName,#function
- .globl glPushName ; .type glPushName,#function
- .globl glDrawBuffer ; .type glDrawBuffer,#function
- .globl glClear ; .type glClear,#function
- .globl glClearAccum ; .type glClearAccum,#function
- .globl glClearIndex ; .type glClearIndex,#function
- .globl glClearColor ; .type glClearColor,#function
- .globl glClearStencil ; .type glClearStencil,#function
- .globl glClearDepth ; .type glClearDepth,#function
- .globl glStencilMask ; .type glStencilMask,#function
- .globl glColorMask ; .type glColorMask,#function
- .globl glDepthMask ; .type glDepthMask,#function
- .globl glIndexMask ; .type glIndexMask,#function
- .globl glAccum ; .type glAccum,#function
- .globl glDisable ; .type glDisable,#function
- .globl glEnable ; .type glEnable,#function
- .globl glFinish ; .type glFinish,#function
- .globl glFlush ; .type glFlush,#function
- .globl glPopAttrib ; .type glPopAttrib,#function
- .globl glPushAttrib ; .type glPushAttrib,#function
- .globl glMap1d ; .type glMap1d,#function
- .globl glMap1f ; .type glMap1f,#function
- .globl glMap2d ; .type glMap2d,#function
- .globl glMap2f ; .type glMap2f,#function
- .globl glMapGrid1d ; .type glMapGrid1d,#function
- .globl glMapGrid1f ; .type glMapGrid1f,#function
- .globl glMapGrid2d ; .type glMapGrid2d,#function
- .globl glMapGrid2f ; .type glMapGrid2f,#function
- .globl glEvalCoord1d ; .type glEvalCoord1d,#function
- .globl glEvalCoord1dv ; .type glEvalCoord1dv,#function
- .globl glEvalCoord1f ; .type glEvalCoord1f,#function
- .globl glEvalCoord1fv ; .type glEvalCoord1fv,#function
- .globl glEvalCoord2d ; .type glEvalCoord2d,#function
- .globl glEvalCoord2dv ; .type glEvalCoord2dv,#function
- .globl glEvalCoord2f ; .type glEvalCoord2f,#function
- .globl glEvalCoord2fv ; .type glEvalCoord2fv,#function
- .globl glEvalMesh1 ; .type glEvalMesh1,#function
- .globl glEvalPoint1 ; .type glEvalPoint1,#function
- .globl glEvalMesh2 ; .type glEvalMesh2,#function
- .globl glEvalPoint2 ; .type glEvalPoint2,#function
- .globl glAlphaFunc ; .type glAlphaFunc,#function
- .globl glBlendFunc ; .type glBlendFunc,#function
- .globl glLogicOp ; .type glLogicOp,#function
- .globl glStencilFunc ; .type glStencilFunc,#function
- .globl glStencilOp ; .type glStencilOp,#function
- .globl glDepthFunc ; .type glDepthFunc,#function
- .globl glPixelZoom ; .type glPixelZoom,#function
- .globl glPixelTransferf ; .type glPixelTransferf,#function
- .globl glPixelTransferi ; .type glPixelTransferi,#function
- .globl glPixelStoref ; .type glPixelStoref,#function
- .globl glPixelStorei ; .type glPixelStorei,#function
- .globl glPixelMapfv ; .type glPixelMapfv,#function
- .globl glPixelMapuiv ; .type glPixelMapuiv,#function
- .globl glPixelMapusv ; .type glPixelMapusv,#function
- .globl glReadBuffer ; .type glReadBuffer,#function
- .globl glCopyPixels ; .type glCopyPixels,#function
- .globl glReadPixels ; .type glReadPixels,#function
- .globl glDrawPixels ; .type glDrawPixels,#function
- .globl glGetBooleanv ; .type glGetBooleanv,#function
- .globl glGetClipPlane ; .type glGetClipPlane,#function
- .globl glGetDoublev ; .type glGetDoublev,#function
- .globl glGetError ; .type glGetError,#function
- .globl glGetFloatv ; .type glGetFloatv,#function
- .globl glGetIntegerv ; .type glGetIntegerv,#function
- .globl glGetLightfv ; .type glGetLightfv,#function
- .globl glGetLightiv ; .type glGetLightiv,#function
- .globl glGetMapdv ; .type glGetMapdv,#function
- .globl glGetMapfv ; .type glGetMapfv,#function
- .globl glGetMapiv ; .type glGetMapiv,#function
- .globl glGetMaterialfv ; .type glGetMaterialfv,#function
- .globl glGetMaterialiv ; .type glGetMaterialiv,#function
- .globl glGetPixelMapfv ; .type glGetPixelMapfv,#function
- .globl glGetPixelMapuiv ; .type glGetPixelMapuiv,#function
- .globl glGetPixelMapusv ; .type glGetPixelMapusv,#function
- .globl glGetPolygonStipple ; .type glGetPolygonStipple,#function
- .globl glGetString ; .type glGetString,#function
- .globl glGetTexEnvfv ; .type glGetTexEnvfv,#function
- .globl glGetTexEnviv ; .type glGetTexEnviv,#function
- .globl glGetTexGendv ; .type glGetTexGendv,#function
- .globl glGetTexGenfv ; .type glGetTexGenfv,#function
- .globl glGetTexGeniv ; .type glGetTexGeniv,#function
- .globl glGetTexImage ; .type glGetTexImage,#function
- .globl glGetTexParameterfv ; .type glGetTexParameterfv,#function
- .globl glGetTexParameteriv ; .type glGetTexParameteriv,#function
- .globl glGetTexLevelParameterfv ; .type glGetTexLevelParameterfv,#function
- .globl glGetTexLevelParameteriv ; .type glGetTexLevelParameteriv,#function
- .globl glIsEnabled ; .type glIsEnabled,#function
- .globl glIsList ; .type glIsList,#function
- .globl glDepthRange ; .type glDepthRange,#function
- .globl glFrustum ; .type glFrustum,#function
- .globl glLoadIdentity ; .type glLoadIdentity,#function
- .globl glLoadMatrixf ; .type glLoadMatrixf,#function
- .globl glLoadMatrixd ; .type glLoadMatrixd,#function
- .globl glMatrixMode ; .type glMatrixMode,#function
- .globl glMultMatrixf ; .type glMultMatrixf,#function
- .globl glMultMatrixd ; .type glMultMatrixd,#function
- .globl glOrtho ; .type glOrtho,#function
- .globl glPopMatrix ; .type glPopMatrix,#function
- .globl glPushMatrix ; .type glPushMatrix,#function
- .globl glRotated ; .type glRotated,#function
- .globl glRotatef ; .type glRotatef,#function
- .globl glScaled ; .type glScaled,#function
- .globl glScalef ; .type glScalef,#function
- .globl glTranslated ; .type glTranslated,#function
- .globl glTranslatef ; .type glTranslatef,#function
- .globl glViewport ; .type glViewport,#function
- .globl glArrayElement ; .type glArrayElement,#function
- .globl glBindTexture ; .type glBindTexture,#function
- .globl glColorPointer ; .type glColorPointer,#function
- .globl glDisableClientState ; .type glDisableClientState,#function
- .globl glDrawArrays ; .type glDrawArrays,#function
- .globl glDrawElements ; .type glDrawElements,#function
- .globl glEdgeFlagPointer ; .type glEdgeFlagPointer,#function
- .globl glEnableClientState ; .type glEnableClientState,#function
- .globl glIndexPointer ; .type glIndexPointer,#function
- .globl glIndexub ; .type glIndexub,#function
- .globl glIndexubv ; .type glIndexubv,#function
- .globl glInterleavedArrays ; .type glInterleavedArrays,#function
- .globl glNormalPointer ; .type glNormalPointer,#function
- .globl glPolygonOffset ; .type glPolygonOffset,#function
- .globl glTexCoordPointer ; .type glTexCoordPointer,#function
- .globl glVertexPointer ; .type glVertexPointer,#function
- .globl glAreTexturesResident ; .type glAreTexturesResident,#function
- .globl glCopyTexImage1D ; .type glCopyTexImage1D,#function
- .globl glCopyTexImage2D ; .type glCopyTexImage2D,#function
- .globl glCopyTexSubImage1D ; .type glCopyTexSubImage1D,#function
- .globl glCopyTexSubImage2D ; .type glCopyTexSubImage2D,#function
- .globl glDeleteTextures ; .type glDeleteTextures,#function
- .globl glGenTextures ; .type glGenTextures,#function
- .globl glGetPointerv ; .type glGetPointerv,#function
- .globl glIsTexture ; .type glIsTexture,#function
- .globl glPrioritizeTextures ; .type glPrioritizeTextures,#function
- .globl glTexSubImage1D ; .type glTexSubImage1D,#function
- .globl glTexSubImage2D ; .type glTexSubImage2D,#function
- .globl glPopClientAttrib ; .type glPopClientAttrib,#function
- .globl glPushClientAttrib ; .type glPushClientAttrib,#function
- .globl glBlendColor ; .type glBlendColor,#function
- .globl glBlendEquation ; .type glBlendEquation,#function
- .globl glDrawRangeElements ; .type glDrawRangeElements,#function
- .globl glColorTable ; .type glColorTable,#function
- .globl glColorTableParameterfv ; .type glColorTableParameterfv,#function
- .globl glColorTableParameteriv ; .type glColorTableParameteriv,#function
- .globl glCopyColorTable ; .type glCopyColorTable,#function
- .globl glGetColorTable ; .type glGetColorTable,#function
- .globl glGetColorTableParameterfv ; .type glGetColorTableParameterfv,#function
- .globl glGetColorTableParameteriv ; .type glGetColorTableParameteriv,#function
- .globl glColorSubTable ; .type glColorSubTable,#function
- .globl glCopyColorSubTable ; .type glCopyColorSubTable,#function
- .globl glConvolutionFilter1D ; .type glConvolutionFilter1D,#function
- .globl glConvolutionFilter2D ; .type glConvolutionFilter2D,#function
- .globl glConvolutionParameterf ; .type glConvolutionParameterf,#function
- .globl glConvolutionParameterfv ; .type glConvolutionParameterfv,#function
- .globl glConvolutionParameteri ; .type glConvolutionParameteri,#function
- .globl glConvolutionParameteriv ; .type glConvolutionParameteriv,#function
- .globl glCopyConvolutionFilter1D ; .type glCopyConvolutionFilter1D,#function
- .globl glCopyConvolutionFilter2D ; .type glCopyConvolutionFilter2D,#function
- .globl glGetConvolutionFilter ; .type glGetConvolutionFilter,#function
- .globl glGetConvolutionParameterfv ; .type glGetConvolutionParameterfv,#function
- .globl glGetConvolutionParameteriv ; .type glGetConvolutionParameteriv,#function
- .globl glGetSeparableFilter ; .type glGetSeparableFilter,#function
- .globl glSeparableFilter2D ; .type glSeparableFilter2D,#function
- .globl glGetHistogram ; .type glGetHistogram,#function
- .globl glGetHistogramParameterfv ; .type glGetHistogramParameterfv,#function
- .globl glGetHistogramParameteriv ; .type glGetHistogramParameteriv,#function
- .globl glGetMinmax ; .type glGetMinmax,#function
- .globl glGetMinmaxParameterfv ; .type glGetMinmaxParameterfv,#function
- .globl glGetMinmaxParameteriv ; .type glGetMinmaxParameteriv,#function
- .globl glHistogram ; .type glHistogram,#function
- .globl glMinmax ; .type glMinmax,#function
- .globl glResetHistogram ; .type glResetHistogram,#function
- .globl glResetMinmax ; .type glResetMinmax,#function
- .globl glTexImage3D ; .type glTexImage3D,#function
- .globl glTexSubImage3D ; .type glTexSubImage3D,#function
- .globl glCopyTexSubImage3D ; .type glCopyTexSubImage3D,#function
- .globl glActiveTextureARB ; .type glActiveTextureARB,#function
- .globl glClientActiveTextureARB ; .type glClientActiveTextureARB,#function
- .globl glMultiTexCoord1dARB ; .type glMultiTexCoord1dARB,#function
- .globl glMultiTexCoord1dvARB ; .type glMultiTexCoord1dvARB,#function
- .globl glMultiTexCoord1fARB ; .type glMultiTexCoord1fARB,#function
- .globl glMultiTexCoord1fvARB ; .type glMultiTexCoord1fvARB,#function
- .globl glMultiTexCoord1iARB ; .type glMultiTexCoord1iARB,#function
- .globl glMultiTexCoord1ivARB ; .type glMultiTexCoord1ivARB,#function
- .globl glMultiTexCoord1sARB ; .type glMultiTexCoord1sARB,#function
- .globl glMultiTexCoord1svARB ; .type glMultiTexCoord1svARB,#function
- .globl glMultiTexCoord2dARB ; .type glMultiTexCoord2dARB,#function
- .globl glMultiTexCoord2dvARB ; .type glMultiTexCoord2dvARB,#function
- .globl glMultiTexCoord2fARB ; .type glMultiTexCoord2fARB,#function
- .globl glMultiTexCoord2fvARB ; .type glMultiTexCoord2fvARB,#function
- .globl glMultiTexCoord2iARB ; .type glMultiTexCoord2iARB,#function
- .globl glMultiTexCoord2ivARB ; .type glMultiTexCoord2ivARB,#function
- .globl glMultiTexCoord2sARB ; .type glMultiTexCoord2sARB,#function
- .globl glMultiTexCoord2svARB ; .type glMultiTexCoord2svARB,#function
- .globl glMultiTexCoord3dARB ; .type glMultiTexCoord3dARB,#function
- .globl glMultiTexCoord3dvARB ; .type glMultiTexCoord3dvARB,#function
- .globl glMultiTexCoord3fARB ; .type glMultiTexCoord3fARB,#function
- .globl glMultiTexCoord3fvARB ; .type glMultiTexCoord3fvARB,#function
- .globl glMultiTexCoord3iARB ; .type glMultiTexCoord3iARB,#function
- .globl glMultiTexCoord3ivARB ; .type glMultiTexCoord3ivARB,#function
- .globl glMultiTexCoord3sARB ; .type glMultiTexCoord3sARB,#function
- .globl glMultiTexCoord3svARB ; .type glMultiTexCoord3svARB,#function
- .globl glMultiTexCoord4dARB ; .type glMultiTexCoord4dARB,#function
- .globl glMultiTexCoord4dvARB ; .type glMultiTexCoord4dvARB,#function
- .globl glMultiTexCoord4fARB ; .type glMultiTexCoord4fARB,#function
- .globl glMultiTexCoord4fvARB ; .type glMultiTexCoord4fvARB,#function
- .globl glMultiTexCoord4iARB ; .type glMultiTexCoord4iARB,#function
- .globl glMultiTexCoord4ivARB ; .type glMultiTexCoord4ivARB,#function
- .globl glMultiTexCoord4sARB ; .type glMultiTexCoord4sARB,#function
- .globl glMultiTexCoord4svARB ; .type glMultiTexCoord4svARB,#function
- .globl glAttachShader ; .type glAttachShader,#function
- .globl glCreateProgram ; .type glCreateProgram,#function
- .globl glCreateShader ; .type glCreateShader,#function
- .globl glDeleteProgram ; .type glDeleteProgram,#function
- .globl glDeleteShader ; .type glDeleteShader,#function
- .globl glDetachShader ; .type glDetachShader,#function
- .globl glGetAttachedShaders ; .type glGetAttachedShaders,#function
- .globl glGetProgramInfoLog ; .type glGetProgramInfoLog,#function
- .globl glGetProgramiv ; .type glGetProgramiv,#function
- .globl glGetShaderInfoLog ; .type glGetShaderInfoLog,#function
- .globl glGetShaderiv ; .type glGetShaderiv,#function
- .globl glIsProgram ; .type glIsProgram,#function
- .globl glIsShader ; .type glIsShader,#function
- .globl glStencilFuncSeparate ; .type glStencilFuncSeparate,#function
- .globl glStencilMaskSeparate ; .type glStencilMaskSeparate,#function
- .globl glStencilOpSeparate ; .type glStencilOpSeparate,#function
- .globl glUniformMatrix2x3fv ; .type glUniformMatrix2x3fv,#function
- .globl glUniformMatrix2x4fv ; .type glUniformMatrix2x4fv,#function
- .globl glUniformMatrix3x2fv ; .type glUniformMatrix3x2fv,#function
- .globl glUniformMatrix3x4fv ; .type glUniformMatrix3x4fv,#function
- .globl glUniformMatrix4x2fv ; .type glUniformMatrix4x2fv,#function
- .globl glUniformMatrix4x3fv ; .type glUniformMatrix4x3fv,#function
- .globl glLoadTransposeMatrixdARB ; .type glLoadTransposeMatrixdARB,#function
- .globl glLoadTransposeMatrixfARB ; .type glLoadTransposeMatrixfARB,#function
- .globl glMultTransposeMatrixdARB ; .type glMultTransposeMatrixdARB,#function
- .globl glMultTransposeMatrixfARB ; .type glMultTransposeMatrixfARB,#function
- .globl glSampleCoverageARB ; .type glSampleCoverageARB,#function
- .globl glCompressedTexImage1DARB ; .type glCompressedTexImage1DARB,#function
- .globl glCompressedTexImage2DARB ; .type glCompressedTexImage2DARB,#function
- .globl glCompressedTexImage3DARB ; .type glCompressedTexImage3DARB,#function
- .globl glCompressedTexSubImage1DARB ; .type glCompressedTexSubImage1DARB,#function
- .globl glCompressedTexSubImage2DARB ; .type glCompressedTexSubImage2DARB,#function
- .globl glCompressedTexSubImage3DARB ; .type glCompressedTexSubImage3DARB,#function
- .globl glGetCompressedTexImageARB ; .type glGetCompressedTexImageARB,#function
- .globl glDisableVertexAttribArrayARB ; .type glDisableVertexAttribArrayARB,#function
- .globl glEnableVertexAttribArrayARB ; .type glEnableVertexAttribArrayARB,#function
- .globl glGetProgramEnvParameterdvARB ; .type glGetProgramEnvParameterdvARB,#function
- .globl glGetProgramEnvParameterfvARB ; .type glGetProgramEnvParameterfvARB,#function
- .globl glGetProgramLocalParameterdvARB ; .type glGetProgramLocalParameterdvARB,#function
- .globl glGetProgramLocalParameterfvARB ; .type glGetProgramLocalParameterfvARB,#function
- .globl glGetProgramStringARB ; .type glGetProgramStringARB,#function
- .globl glGetProgramivARB ; .type glGetProgramivARB,#function
- .globl glGetVertexAttribdvARB ; .type glGetVertexAttribdvARB,#function
- .globl glGetVertexAttribfvARB ; .type glGetVertexAttribfvARB,#function
- .globl glGetVertexAttribivARB ; .type glGetVertexAttribivARB,#function
- .globl glProgramEnvParameter4dARB ; .type glProgramEnvParameter4dARB,#function
- .globl glProgramEnvParameter4dvARB ; .type glProgramEnvParameter4dvARB,#function
- .globl glProgramEnvParameter4fARB ; .type glProgramEnvParameter4fARB,#function
- .globl glProgramEnvParameter4fvARB ; .type glProgramEnvParameter4fvARB,#function
- .globl glProgramLocalParameter4dARB ; .type glProgramLocalParameter4dARB,#function
- .globl glProgramLocalParameter4dvARB ; .type glProgramLocalParameter4dvARB,#function
- .globl glProgramLocalParameter4fARB ; .type glProgramLocalParameter4fARB,#function
- .globl glProgramLocalParameter4fvARB ; .type glProgramLocalParameter4fvARB,#function
- .globl glProgramStringARB ; .type glProgramStringARB,#function
- .globl glVertexAttrib1dARB ; .type glVertexAttrib1dARB,#function
- .globl glVertexAttrib1dvARB ; .type glVertexAttrib1dvARB,#function
- .globl glVertexAttrib1fARB ; .type glVertexAttrib1fARB,#function
- .globl glVertexAttrib1fvARB ; .type glVertexAttrib1fvARB,#function
- .globl glVertexAttrib1sARB ; .type glVertexAttrib1sARB,#function
- .globl glVertexAttrib1svARB ; .type glVertexAttrib1svARB,#function
- .globl glVertexAttrib2dARB ; .type glVertexAttrib2dARB,#function
- .globl glVertexAttrib2dvARB ; .type glVertexAttrib2dvARB,#function
- .globl glVertexAttrib2fARB ; .type glVertexAttrib2fARB,#function
- .globl glVertexAttrib2fvARB ; .type glVertexAttrib2fvARB,#function
- .globl glVertexAttrib2sARB ; .type glVertexAttrib2sARB,#function
- .globl glVertexAttrib2svARB ; .type glVertexAttrib2svARB,#function
- .globl glVertexAttrib3dARB ; .type glVertexAttrib3dARB,#function
- .globl glVertexAttrib3dvARB ; .type glVertexAttrib3dvARB,#function
- .globl glVertexAttrib3fARB ; .type glVertexAttrib3fARB,#function
- .globl glVertexAttrib3fvARB ; .type glVertexAttrib3fvARB,#function
- .globl glVertexAttrib3sARB ; .type glVertexAttrib3sARB,#function
- .globl glVertexAttrib3svARB ; .type glVertexAttrib3svARB,#function
- .globl glVertexAttrib4NbvARB ; .type glVertexAttrib4NbvARB,#function
- .globl glVertexAttrib4NivARB ; .type glVertexAttrib4NivARB,#function
- .globl glVertexAttrib4NsvARB ; .type glVertexAttrib4NsvARB,#function
- .globl glVertexAttrib4NubARB ; .type glVertexAttrib4NubARB,#function
- .globl glVertexAttrib4NubvARB ; .type glVertexAttrib4NubvARB,#function
- .globl glVertexAttrib4NuivARB ; .type glVertexAttrib4NuivARB,#function
- .globl glVertexAttrib4NusvARB ; .type glVertexAttrib4NusvARB,#function
- .globl glVertexAttrib4bvARB ; .type glVertexAttrib4bvARB,#function
- .globl glVertexAttrib4dARB ; .type glVertexAttrib4dARB,#function
- .globl glVertexAttrib4dvARB ; .type glVertexAttrib4dvARB,#function
- .globl glVertexAttrib4fARB ; .type glVertexAttrib4fARB,#function
- .globl glVertexAttrib4fvARB ; .type glVertexAttrib4fvARB,#function
- .globl glVertexAttrib4ivARB ; .type glVertexAttrib4ivARB,#function
- .globl glVertexAttrib4sARB ; .type glVertexAttrib4sARB,#function
- .globl glVertexAttrib4svARB ; .type glVertexAttrib4svARB,#function
- .globl glVertexAttrib4ubvARB ; .type glVertexAttrib4ubvARB,#function
- .globl glVertexAttrib4uivARB ; .type glVertexAttrib4uivARB,#function
- .globl glVertexAttrib4usvARB ; .type glVertexAttrib4usvARB,#function
- .globl glVertexAttribPointerARB ; .type glVertexAttribPointerARB,#function
- .globl glBindBufferARB ; .type glBindBufferARB,#function
- .globl glBufferDataARB ; .type glBufferDataARB,#function
- .globl glBufferSubDataARB ; .type glBufferSubDataARB,#function
- .globl glDeleteBuffersARB ; .type glDeleteBuffersARB,#function
- .globl glGenBuffersARB ; .type glGenBuffersARB,#function
- .globl glGetBufferParameterivARB ; .type glGetBufferParameterivARB,#function
- .globl glGetBufferPointervARB ; .type glGetBufferPointervARB,#function
- .globl glGetBufferSubDataARB ; .type glGetBufferSubDataARB,#function
- .globl glIsBufferARB ; .type glIsBufferARB,#function
- .globl glMapBufferARB ; .type glMapBufferARB,#function
- .globl glUnmapBufferARB ; .type glUnmapBufferARB,#function
- .globl glBeginQueryARB ; .type glBeginQueryARB,#function
- .globl glDeleteQueriesARB ; .type glDeleteQueriesARB,#function
- .globl glEndQueryARB ; .type glEndQueryARB,#function
- .globl glGenQueriesARB ; .type glGenQueriesARB,#function
- .globl glGetQueryObjectivARB ; .type glGetQueryObjectivARB,#function
- .globl glGetQueryObjectuivARB ; .type glGetQueryObjectuivARB,#function
- .globl glGetQueryivARB ; .type glGetQueryivARB,#function
- .globl glIsQueryARB ; .type glIsQueryARB,#function
- .globl glAttachObjectARB ; .type glAttachObjectARB,#function
- .globl glCompileShaderARB ; .type glCompileShaderARB,#function
- .globl glCreateProgramObjectARB ; .type glCreateProgramObjectARB,#function
- .globl glCreateShaderObjectARB ; .type glCreateShaderObjectARB,#function
- .globl glDeleteObjectARB ; .type glDeleteObjectARB,#function
- .globl glDetachObjectARB ; .type glDetachObjectARB,#function
- .globl glGetActiveUniformARB ; .type glGetActiveUniformARB,#function
- .globl glGetAttachedObjectsARB ; .type glGetAttachedObjectsARB,#function
- .globl glGetHandleARB ; .type glGetHandleARB,#function
- .globl glGetInfoLogARB ; .type glGetInfoLogARB,#function
- .globl glGetObjectParameterfvARB ; .type glGetObjectParameterfvARB,#function
- .globl glGetObjectParameterivARB ; .type glGetObjectParameterivARB,#function
- .globl glGetShaderSourceARB ; .type glGetShaderSourceARB,#function
- .globl glGetUniformLocationARB ; .type glGetUniformLocationARB,#function
- .globl glGetUniformfvARB ; .type glGetUniformfvARB,#function
- .globl glGetUniformivARB ; .type glGetUniformivARB,#function
- .globl glLinkProgramARB ; .type glLinkProgramARB,#function
- .globl glShaderSourceARB ; .type glShaderSourceARB,#function
- .globl glUniform1fARB ; .type glUniform1fARB,#function
- .globl glUniform1fvARB ; .type glUniform1fvARB,#function
- .globl glUniform1iARB ; .type glUniform1iARB,#function
- .globl glUniform1ivARB ; .type glUniform1ivARB,#function
- .globl glUniform2fARB ; .type glUniform2fARB,#function
- .globl glUniform2fvARB ; .type glUniform2fvARB,#function
- .globl glUniform2iARB ; .type glUniform2iARB,#function
- .globl glUniform2ivARB ; .type glUniform2ivARB,#function
- .globl glUniform3fARB ; .type glUniform3fARB,#function
- .globl glUniform3fvARB ; .type glUniform3fvARB,#function
- .globl glUniform3iARB ; .type glUniform3iARB,#function
- .globl glUniform3ivARB ; .type glUniform3ivARB,#function
- .globl glUniform4fARB ; .type glUniform4fARB,#function
- .globl glUniform4fvARB ; .type glUniform4fvARB,#function
- .globl glUniform4iARB ; .type glUniform4iARB,#function
- .globl glUniform4ivARB ; .type glUniform4ivARB,#function
- .globl glUniformMatrix2fvARB ; .type glUniformMatrix2fvARB,#function
- .globl glUniformMatrix3fvARB ; .type glUniformMatrix3fvARB,#function
- .globl glUniformMatrix4fvARB ; .type glUniformMatrix4fvARB,#function
- .globl glUseProgramObjectARB ; .type glUseProgramObjectARB,#function
- .globl glValidateProgramARB ; .type glValidateProgramARB,#function
- .globl glBindAttribLocationARB ; .type glBindAttribLocationARB,#function
- .globl glGetActiveAttribARB ; .type glGetActiveAttribARB,#function
- .globl glGetAttribLocationARB ; .type glGetAttribLocationARB,#function
- .globl glDrawBuffersARB ; .type glDrawBuffersARB,#function
- .globl glPolygonOffsetEXT ; .type glPolygonOffsetEXT,#function
- .globl gl_dispatch_stub_562 ; .type gl_dispatch_stub_562,#function
- .globl gl_dispatch_stub_563 ; .type gl_dispatch_stub_563,#function
- .globl gl_dispatch_stub_564 ; .type gl_dispatch_stub_564,#function
- .globl gl_dispatch_stub_565 ; .type gl_dispatch_stub_565,#function
- .globl gl_dispatch_stub_566 ; .type gl_dispatch_stub_566,#function
- .globl gl_dispatch_stub_567 ; .type gl_dispatch_stub_567,#function
- .globl gl_dispatch_stub_568 ; .type gl_dispatch_stub_568,#function
- .globl gl_dispatch_stub_569 ; .type gl_dispatch_stub_569,#function
- .globl glColorPointerEXT ; .type glColorPointerEXT,#function
- .globl glEdgeFlagPointerEXT ; .type glEdgeFlagPointerEXT,#function
- .globl glIndexPointerEXT ; .type glIndexPointerEXT,#function
- .globl glNormalPointerEXT ; .type glNormalPointerEXT,#function
- .globl glTexCoordPointerEXT ; .type glTexCoordPointerEXT,#function
- .globl glVertexPointerEXT ; .type glVertexPointerEXT,#function
- .globl glPointParameterfEXT ; .type glPointParameterfEXT,#function
- .globl glPointParameterfvEXT ; .type glPointParameterfvEXT,#function
- .globl glLockArraysEXT ; .type glLockArraysEXT,#function
- .globl glUnlockArraysEXT ; .type glUnlockArraysEXT,#function
- .globl gl_dispatch_stub_580 ; .type gl_dispatch_stub_580,#function
- .globl gl_dispatch_stub_581 ; .type gl_dispatch_stub_581,#function
- .globl glSecondaryColor3bEXT ; .type glSecondaryColor3bEXT,#function
- .globl glSecondaryColor3bvEXT ; .type glSecondaryColor3bvEXT,#function
- .globl glSecondaryColor3dEXT ; .type glSecondaryColor3dEXT,#function
- .globl glSecondaryColor3dvEXT ; .type glSecondaryColor3dvEXT,#function
- .globl glSecondaryColor3fEXT ; .type glSecondaryColor3fEXT,#function
- .globl glSecondaryColor3fvEXT ; .type glSecondaryColor3fvEXT,#function
- .globl glSecondaryColor3iEXT ; .type glSecondaryColor3iEXT,#function
- .globl glSecondaryColor3ivEXT ; .type glSecondaryColor3ivEXT,#function
- .globl glSecondaryColor3sEXT ; .type glSecondaryColor3sEXT,#function
- .globl glSecondaryColor3svEXT ; .type glSecondaryColor3svEXT,#function
- .globl glSecondaryColor3ubEXT ; .type glSecondaryColor3ubEXT,#function
- .globl glSecondaryColor3ubvEXT ; .type glSecondaryColor3ubvEXT,#function
- .globl glSecondaryColor3uiEXT ; .type glSecondaryColor3uiEXT,#function
- .globl glSecondaryColor3uivEXT ; .type glSecondaryColor3uivEXT,#function
- .globl glSecondaryColor3usEXT ; .type glSecondaryColor3usEXT,#function
- .globl glSecondaryColor3usvEXT ; .type glSecondaryColor3usvEXT,#function
- .globl glSecondaryColorPointerEXT ; .type glSecondaryColorPointerEXT,#function
- .globl glMultiDrawArraysEXT ; .type glMultiDrawArraysEXT,#function
- .globl glMultiDrawElementsEXT ; .type glMultiDrawElementsEXT,#function
- .globl glFogCoordPointerEXT ; .type glFogCoordPointerEXT,#function
- .globl glFogCoorddEXT ; .type glFogCoorddEXT,#function
- .globl glFogCoorddvEXT ; .type glFogCoorddvEXT,#function
- .globl glFogCoordfEXT ; .type glFogCoordfEXT,#function
- .globl glFogCoordfvEXT ; .type glFogCoordfvEXT,#function
- .globl gl_dispatch_stub_606 ; .type gl_dispatch_stub_606,#function
- .globl glBlendFuncSeparateEXT ; .type glBlendFuncSeparateEXT,#function
- .globl glFlushVertexArrayRangeNV ; .type glFlushVertexArrayRangeNV,#function
- .globl glVertexArrayRangeNV ; .type glVertexArrayRangeNV,#function
- .globl glCombinerInputNV ; .type glCombinerInputNV,#function
- .globl glCombinerOutputNV ; .type glCombinerOutputNV,#function
- .globl glCombinerParameterfNV ; .type glCombinerParameterfNV,#function
- .globl glCombinerParameterfvNV ; .type glCombinerParameterfvNV,#function
- .globl glCombinerParameteriNV ; .type glCombinerParameteriNV,#function
- .globl glCombinerParameterivNV ; .type glCombinerParameterivNV,#function
- .globl glFinalCombinerInputNV ; .type glFinalCombinerInputNV,#function
- .globl glGetCombinerInputParameterfvNV ; .type glGetCombinerInputParameterfvNV,#function
- .globl glGetCombinerInputParameterivNV ; .type glGetCombinerInputParameterivNV,#function
- .globl glGetCombinerOutputParameterfvNV ; .type glGetCombinerOutputParameterfvNV,#function
- .globl glGetCombinerOutputParameterivNV ; .type glGetCombinerOutputParameterivNV,#function
- .globl glGetFinalCombinerInputParameterfvNV ; .type glGetFinalCombinerInputParameterfvNV,#function
- .globl glGetFinalCombinerInputParameterivNV ; .type glGetFinalCombinerInputParameterivNV,#function
- .globl glResizeBuffersMESA ; .type glResizeBuffersMESA,#function
- .globl glWindowPos2dMESA ; .type glWindowPos2dMESA,#function
- .globl glWindowPos2dvMESA ; .type glWindowPos2dvMESA,#function
- .globl glWindowPos2fMESA ; .type glWindowPos2fMESA,#function
- .globl glWindowPos2fvMESA ; .type glWindowPos2fvMESA,#function
- .globl glWindowPos2iMESA ; .type glWindowPos2iMESA,#function
- .globl glWindowPos2ivMESA ; .type glWindowPos2ivMESA,#function
- .globl glWindowPos2sMESA ; .type glWindowPos2sMESA,#function
- .globl glWindowPos2svMESA ; .type glWindowPos2svMESA,#function
- .globl glWindowPos3dMESA ; .type glWindowPos3dMESA,#function
- .globl glWindowPos3dvMESA ; .type glWindowPos3dvMESA,#function
- .globl glWindowPos3fMESA ; .type glWindowPos3fMESA,#function
- .globl glWindowPos3fvMESA ; .type glWindowPos3fvMESA,#function
- .globl glWindowPos3iMESA ; .type glWindowPos3iMESA,#function
- .globl glWindowPos3ivMESA ; .type glWindowPos3ivMESA,#function
- .globl glWindowPos3sMESA ; .type glWindowPos3sMESA,#function
- .globl glWindowPos3svMESA ; .type glWindowPos3svMESA,#function
- .globl glWindowPos4dMESA ; .type glWindowPos4dMESA,#function
- .globl glWindowPos4dvMESA ; .type glWindowPos4dvMESA,#function
- .globl glWindowPos4fMESA ; .type glWindowPos4fMESA,#function
- .globl glWindowPos4fvMESA ; .type glWindowPos4fvMESA,#function
- .globl glWindowPos4iMESA ; .type glWindowPos4iMESA,#function
- .globl glWindowPos4ivMESA ; .type glWindowPos4ivMESA,#function
- .globl glWindowPos4sMESA ; .type glWindowPos4sMESA,#function
- .globl glWindowPos4svMESA ; .type glWindowPos4svMESA,#function
- .globl gl_dispatch_stub_648 ; .type gl_dispatch_stub_648,#function
- .globl gl_dispatch_stub_649 ; .type gl_dispatch_stub_649,#function
- .globl gl_dispatch_stub_650 ; .type gl_dispatch_stub_650,#function
- .globl gl_dispatch_stub_651 ; .type gl_dispatch_stub_651,#function
- .globl gl_dispatch_stub_652 ; .type gl_dispatch_stub_652,#function
- .globl gl_dispatch_stub_653 ; .type gl_dispatch_stub_653,#function
- .globl gl_dispatch_stub_654 ; .type gl_dispatch_stub_654,#function
- .globl gl_dispatch_stub_655 ; .type gl_dispatch_stub_655,#function
- .globl gl_dispatch_stub_656 ; .type gl_dispatch_stub_656,#function
- .globl glAreProgramsResidentNV ; .type glAreProgramsResidentNV,#function
- .globl glBindProgramNV ; .type glBindProgramNV,#function
- .globl glDeleteProgramsNV ; .type glDeleteProgramsNV,#function
- .globl glExecuteProgramNV ; .type glExecuteProgramNV,#function
- .globl glGenProgramsNV ; .type glGenProgramsNV,#function
- .globl glGetProgramParameterdvNV ; .type glGetProgramParameterdvNV,#function
- .globl glGetProgramParameterfvNV ; .type glGetProgramParameterfvNV,#function
- .globl glGetProgramStringNV ; .type glGetProgramStringNV,#function
- .globl glGetProgramivNV ; .type glGetProgramivNV,#function
- .globl glGetTrackMatrixivNV ; .type glGetTrackMatrixivNV,#function
- .globl glGetVertexAttribPointervNV ; .type glGetVertexAttribPointervNV,#function
- .globl glGetVertexAttribdvNV ; .type glGetVertexAttribdvNV,#function
- .globl glGetVertexAttribfvNV ; .type glGetVertexAttribfvNV,#function
- .globl glGetVertexAttribivNV ; .type glGetVertexAttribivNV,#function
- .globl glIsProgramNV ; .type glIsProgramNV,#function
- .globl glLoadProgramNV ; .type glLoadProgramNV,#function
- .globl glProgramParameters4dvNV ; .type glProgramParameters4dvNV,#function
- .globl glProgramParameters4fvNV ; .type glProgramParameters4fvNV,#function
- .globl glRequestResidentProgramsNV ; .type glRequestResidentProgramsNV,#function
- .globl glTrackMatrixNV ; .type glTrackMatrixNV,#function
- .globl glVertexAttrib1dNV ; .type glVertexAttrib1dNV,#function
- .globl glVertexAttrib1dvNV ; .type glVertexAttrib1dvNV,#function
- .globl glVertexAttrib1fNV ; .type glVertexAttrib1fNV,#function
- .globl glVertexAttrib1fvNV ; .type glVertexAttrib1fvNV,#function
- .globl glVertexAttrib1sNV ; .type glVertexAttrib1sNV,#function
- .globl glVertexAttrib1svNV ; .type glVertexAttrib1svNV,#function
- .globl glVertexAttrib2dNV ; .type glVertexAttrib2dNV,#function
- .globl glVertexAttrib2dvNV ; .type glVertexAttrib2dvNV,#function
- .globl glVertexAttrib2fNV ; .type glVertexAttrib2fNV,#function
- .globl glVertexAttrib2fvNV ; .type glVertexAttrib2fvNV,#function
- .globl glVertexAttrib2sNV ; .type glVertexAttrib2sNV,#function
- .globl glVertexAttrib2svNV ; .type glVertexAttrib2svNV,#function
- .globl glVertexAttrib3dNV ; .type glVertexAttrib3dNV,#function
- .globl glVertexAttrib3dvNV ; .type glVertexAttrib3dvNV,#function
- .globl glVertexAttrib3fNV ; .type glVertexAttrib3fNV,#function
- .globl glVertexAttrib3fvNV ; .type glVertexAttrib3fvNV,#function
- .globl glVertexAttrib3sNV ; .type glVertexAttrib3sNV,#function
- .globl glVertexAttrib3svNV ; .type glVertexAttrib3svNV,#function
- .globl glVertexAttrib4dNV ; .type glVertexAttrib4dNV,#function
- .globl glVertexAttrib4dvNV ; .type glVertexAttrib4dvNV,#function
- .globl glVertexAttrib4fNV ; .type glVertexAttrib4fNV,#function
- .globl glVertexAttrib4fvNV ; .type glVertexAttrib4fvNV,#function
- .globl glVertexAttrib4sNV ; .type glVertexAttrib4sNV,#function
- .globl glVertexAttrib4svNV ; .type glVertexAttrib4svNV,#function
- .globl glVertexAttrib4ubNV ; .type glVertexAttrib4ubNV,#function
- .globl glVertexAttrib4ubvNV ; .type glVertexAttrib4ubvNV,#function
- .globl glVertexAttribPointerNV ; .type glVertexAttribPointerNV,#function
- .globl glVertexAttribs1dvNV ; .type glVertexAttribs1dvNV,#function
- .globl glVertexAttribs1fvNV ; .type glVertexAttribs1fvNV,#function
- .globl glVertexAttribs1svNV ; .type glVertexAttribs1svNV,#function
- .globl glVertexAttribs2dvNV ; .type glVertexAttribs2dvNV,#function
- .globl glVertexAttribs2fvNV ; .type glVertexAttribs2fvNV,#function
- .globl glVertexAttribs2svNV ; .type glVertexAttribs2svNV,#function
- .globl glVertexAttribs3dvNV ; .type glVertexAttribs3dvNV,#function
- .globl glVertexAttribs3fvNV ; .type glVertexAttribs3fvNV,#function
- .globl glVertexAttribs3svNV ; .type glVertexAttribs3svNV,#function
- .globl glVertexAttribs4dvNV ; .type glVertexAttribs4dvNV,#function
- .globl glVertexAttribs4fvNV ; .type glVertexAttribs4fvNV,#function
- .globl glVertexAttribs4svNV ; .type glVertexAttribs4svNV,#function
- .globl glVertexAttribs4ubvNV ; .type glVertexAttribs4ubvNV,#function
- .globl glAlphaFragmentOp1ATI ; .type glAlphaFragmentOp1ATI,#function
- .globl glAlphaFragmentOp2ATI ; .type glAlphaFragmentOp2ATI,#function
- .globl glAlphaFragmentOp3ATI ; .type glAlphaFragmentOp3ATI,#function
- .globl glBeginFragmentShaderATI ; .type glBeginFragmentShaderATI,#function
- .globl glBindFragmentShaderATI ; .type glBindFragmentShaderATI,#function
- .globl glColorFragmentOp1ATI ; .type glColorFragmentOp1ATI,#function
- .globl glColorFragmentOp2ATI ; .type glColorFragmentOp2ATI,#function
- .globl glColorFragmentOp3ATI ; .type glColorFragmentOp3ATI,#function
- .globl glDeleteFragmentShaderATI ; .type glDeleteFragmentShaderATI,#function
- .globl glEndFragmentShaderATI ; .type glEndFragmentShaderATI,#function
- .globl glGenFragmentShadersATI ; .type glGenFragmentShadersATI,#function
- .globl glPassTexCoordATI ; .type glPassTexCoordATI,#function
- .globl glSampleMapATI ; .type glSampleMapATI,#function
- .globl glSetFragmentShaderConstantATI ; .type glSetFragmentShaderConstantATI,#function
- .globl glPointParameteriNV ; .type glPointParameteriNV,#function
- .globl glPointParameterivNV ; .type glPointParameterivNV,#function
- .globl gl_dispatch_stub_733 ; .type gl_dispatch_stub_733,#function
- .globl gl_dispatch_stub_734 ; .type gl_dispatch_stub_734,#function
- .globl gl_dispatch_stub_735 ; .type gl_dispatch_stub_735,#function
- .globl gl_dispatch_stub_736 ; .type gl_dispatch_stub_736,#function
- .globl gl_dispatch_stub_737 ; .type gl_dispatch_stub_737,#function
- .globl glGetProgramNamedParameterdvNV ; .type glGetProgramNamedParameterdvNV,#function
- .globl glGetProgramNamedParameterfvNV ; .type glGetProgramNamedParameterfvNV,#function
- .globl glProgramNamedParameter4dNV ; .type glProgramNamedParameter4dNV,#function
- .globl glProgramNamedParameter4dvNV ; .type glProgramNamedParameter4dvNV,#function
- .globl glProgramNamedParameter4fNV ; .type glProgramNamedParameter4fNV,#function
- .globl glProgramNamedParameter4fvNV ; .type glProgramNamedParameter4fvNV,#function
- .globl gl_dispatch_stub_744 ; .type gl_dispatch_stub_744,#function
- .globl gl_dispatch_stub_745 ; .type gl_dispatch_stub_745,#function
- .globl glBindFramebufferEXT ; .type glBindFramebufferEXT,#function
- .globl glBindRenderbufferEXT ; .type glBindRenderbufferEXT,#function
- .globl glCheckFramebufferStatusEXT ; .type glCheckFramebufferStatusEXT,#function
- .globl glDeleteFramebuffersEXT ; .type glDeleteFramebuffersEXT,#function
- .globl glDeleteRenderbuffersEXT ; .type glDeleteRenderbuffersEXT,#function
- .globl glFramebufferRenderbufferEXT ; .type glFramebufferRenderbufferEXT,#function
- .globl glFramebufferTexture1DEXT ; .type glFramebufferTexture1DEXT,#function
- .globl glFramebufferTexture2DEXT ; .type glFramebufferTexture2DEXT,#function
- .globl glFramebufferTexture3DEXT ; .type glFramebufferTexture3DEXT,#function
- .globl glGenFramebuffersEXT ; .type glGenFramebuffersEXT,#function
- .globl glGenRenderbuffersEXT ; .type glGenRenderbuffersEXT,#function
- .globl glGenerateMipmapEXT ; .type glGenerateMipmapEXT,#function
- .globl glGetFramebufferAttachmentParameterivEXT ; .type glGetFramebufferAttachmentParameterivEXT,#function
- .globl glGetRenderbufferParameterivEXT ; .type glGetRenderbufferParameterivEXT,#function
- .globl glIsFramebufferEXT ; .type glIsFramebufferEXT,#function
- .globl glIsRenderbufferEXT ; .type glIsRenderbufferEXT,#function
- .globl glRenderbufferStorageEXT ; .type glRenderbufferStorageEXT,#function
- .globl gl_dispatch_stub_763 ; .type gl_dispatch_stub_763,#function
- .globl glFramebufferTextureLayerEXT ; .type glFramebufferTextureLayerEXT,#function
- .globl gl_dispatch_stub_765 ; .type gl_dispatch_stub_765,#function
- .globl gl_dispatch_stub_766 ; .type gl_dispatch_stub_766,#function
- .globl gl_dispatch_stub_767 ; .type gl_dispatch_stub_767,#function
- .globl gl_dispatch_stub_768 ; .type gl_dispatch_stub_768,#function
- .globl gl_dispatch_stub_769 ; .type gl_dispatch_stub_769,#function
- .globl _mesa_sparc_glapi_begin ; .type _mesa_sparc_glapi_begin,#function
-_mesa_sparc_glapi_begin:
+ .data
+ .align 32
+
+ GLOBL_FN(__glapi_sparc_pthread_stub)
+ HIDDEN(__glapi_sparc_pthread_stub)
+__glapi_sparc_pthread_stub: /* Call offset in %g3 */
+ mov %o7, %g1
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %g2
+ call __glapi_sparc_get_pc
+ add %g2, %lo(_GLOBAL_OFFSET_TABLE_+4), %g2
+ mov %g1, %o7
+ sethi %hi(_glapi_Dispatch), %g1
+ or %g1, %lo(_glapi_Dispatch), %g1
+ srl %g3, 10, %g3
+ GL_LL [%g2+%g1], %g2
+ GL_LL [%g2], %g1
+ cmp %g1, 0
+ be 2f
+ nop
+1: GL_LL [%g1 + %g3], %g1
+ jmp %g1
+ nop
+2: save %sp, GL_STACK_SIZE, %sp
+ mov %g3, %l0
+ call _glapi_get_dispatch
+ nop
+ mov %o0, %g1
+ mov %l0, %g3
+ ba 1b
+ restore %g0, %g0, %g0
+ .size __glapi_sparc_pthread_stub, .-__glapi_sparc_pthread_stub
+
+#define GL_STUB(fn, off) \
+ GLOBL_FN(fn); \
+fn: ba __glapi_sparc_pthread_stub; \
+ sethi GL_OFF(off), %g3; \
+ .size fn,.-fn;
+
+#else /* Non-threaded version. */
+
+ .type __glapi_sparc_nothread_stub, @function
+__glapi_sparc_nothread_stub: /* Call offset in %g3 */
+ mov %o7, %g1
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %g2
+ call __glapi_sparc_get_pc
+ add %g2, %lo(_GLOBAL_OFFSET_TABLE_+4), %g2
+ mov %g1, %o7
+ srl %g3, 10, %g3
+ sethi %hi(_glapi_Dispatch), %g1
+ or %g1, %lo(_glapi_Dispatch), %g1
+ GL_LL [%g2+%g1], %g2
+ GL_LL [%g2], %g1
+ GL_LL [%g1 + %g3], %g1
+ jmp %g1
+ nop
+ .size __glapi_sparc_nothread_stub, .-__glapi_sparc_nothread_stub
+
+#define GL_STUB(fn, off) \
+ GLOBL_FN(fn); \
+fn: ba __glapi_sparc_nothread_stub; \
+ sethi GL_OFF(off), %g3; \
+ .size fn,.-fn;
+
+#endif
+
+#define GL_STUB_ALIAS(fn, alias) \
+ .globl fn; \
+ .set fn, alias
+
+ .text
+ .align 32
+
+ .globl gl_dispatch_functions_start
+ HIDDEN(gl_dispatch_functions_start)
+gl_dispatch_functions_start:
GL_STUB(glNewList, _gloffset_NewList)
GL_STUB(glEndList, _gloffset_EndList)
@@ -1399,15 +758,39 @@ _mesa_sparc_glapi_begin:
GL_STUB(glGetActiveAttribARB, _gloffset_GetActiveAttribARB)
GL_STUB(glGetAttribLocationARB, _gloffset_GetAttribLocationARB)
GL_STUB(glDrawBuffersARB, _gloffset_DrawBuffersARB)
+ GL_STUB(glRenderbufferStorageMultisample, _gloffset_RenderbufferStorageMultisample)
+ GL_STUB(glFlushMappedBufferRange, _gloffset_FlushMappedBufferRange)
+ GL_STUB(glMapBufferRange, _gloffset_MapBufferRange)
+ GL_STUB(glBindVertexArray, _gloffset_BindVertexArray)
+ GL_STUB(glGenVertexArrays, _gloffset_GenVertexArrays)
+ GL_STUB(glCopyBufferSubData, _gloffset_CopyBufferSubData)
+ GL_STUB(glClientWaitSync, _gloffset_ClientWaitSync)
+ GL_STUB(glDeleteSync, _gloffset_DeleteSync)
+ GL_STUB(glFenceSync, _gloffset_FenceSync)
+ GL_STUB(glGetInteger64v, _gloffset_GetInteger64v)
+ GL_STUB(glGetSynciv, _gloffset_GetSynciv)
+ GL_STUB(glIsSync, _gloffset_IsSync)
+ GL_STUB(glWaitSync, _gloffset_WaitSync)
+ GL_STUB(glDrawElementsBaseVertex, _gloffset_DrawElementsBaseVertex)
+ GL_STUB(glDrawRangeElementsBaseVertex, _gloffset_DrawRangeElementsBaseVertex)
+ GL_STUB(glMultiDrawElementsBaseVertex, _gloffset_MultiDrawElementsBaseVertex)
GL_STUB(glPolygonOffsetEXT, _gloffset_PolygonOffsetEXT)
- GL_STUB(gl_dispatch_stub_562, _gloffset__dispatch_stub_562)
- GL_STUB(gl_dispatch_stub_563, _gloffset__dispatch_stub_563)
- GL_STUB(gl_dispatch_stub_564, _gloffset__dispatch_stub_564)
- GL_STUB(gl_dispatch_stub_565, _gloffset__dispatch_stub_565)
- GL_STUB(gl_dispatch_stub_566, _gloffset__dispatch_stub_566)
- GL_STUB(gl_dispatch_stub_567, _gloffset__dispatch_stub_567)
- GL_STUB(gl_dispatch_stub_568, _gloffset__dispatch_stub_568)
- GL_STUB(gl_dispatch_stub_569, _gloffset__dispatch_stub_569)
+ GL_STUB(gl_dispatch_stub_578, _gloffset_GetPixelTexGenParameterfvSGIS)
+ HIDDEN(gl_dispatch_stub_578)
+ GL_STUB(gl_dispatch_stub_579, _gloffset_GetPixelTexGenParameterivSGIS)
+ HIDDEN(gl_dispatch_stub_579)
+ GL_STUB(gl_dispatch_stub_580, _gloffset_PixelTexGenParameterfSGIS)
+ HIDDEN(gl_dispatch_stub_580)
+ GL_STUB(gl_dispatch_stub_581, _gloffset_PixelTexGenParameterfvSGIS)
+ HIDDEN(gl_dispatch_stub_581)
+ GL_STUB(gl_dispatch_stub_582, _gloffset_PixelTexGenParameteriSGIS)
+ HIDDEN(gl_dispatch_stub_582)
+ GL_STUB(gl_dispatch_stub_583, _gloffset_PixelTexGenParameterivSGIS)
+ HIDDEN(gl_dispatch_stub_583)
+ GL_STUB(gl_dispatch_stub_584, _gloffset_SampleMaskSGIS)
+ HIDDEN(gl_dispatch_stub_584)
+ GL_STUB(gl_dispatch_stub_585, _gloffset_SamplePatternSGIS)
+ HIDDEN(gl_dispatch_stub_585)
GL_STUB(glColorPointerEXT, _gloffset_ColorPointerEXT)
GL_STUB(glEdgeFlagPointerEXT, _gloffset_EdgeFlagPointerEXT)
GL_STUB(glIndexPointerEXT, _gloffset_IndexPointerEXT)
@@ -1418,8 +801,10 @@ _mesa_sparc_glapi_begin:
GL_STUB(glPointParameterfvEXT, _gloffset_PointParameterfvEXT)
GL_STUB(glLockArraysEXT, _gloffset_LockArraysEXT)
GL_STUB(glUnlockArraysEXT, _gloffset_UnlockArraysEXT)
- GL_STUB(gl_dispatch_stub_580, _gloffset__dispatch_stub_580)
- GL_STUB(gl_dispatch_stub_581, _gloffset__dispatch_stub_581)
+ GL_STUB(gl_dispatch_stub_596, _gloffset_CullParameterdvEXT)
+ HIDDEN(gl_dispatch_stub_596)
+ GL_STUB(gl_dispatch_stub_597, _gloffset_CullParameterfvEXT)
+ HIDDEN(gl_dispatch_stub_597)
GL_STUB(glSecondaryColor3bEXT, _gloffset_SecondaryColor3bEXT)
GL_STUB(glSecondaryColor3bvEXT, _gloffset_SecondaryColor3bvEXT)
GL_STUB(glSecondaryColor3dEXT, _gloffset_SecondaryColor3dEXT)
@@ -1444,7 +829,8 @@ _mesa_sparc_glapi_begin:
GL_STUB(glFogCoorddvEXT, _gloffset_FogCoorddvEXT)
GL_STUB(glFogCoordfEXT, _gloffset_FogCoordfEXT)
GL_STUB(glFogCoordfvEXT, _gloffset_FogCoordfvEXT)
- GL_STUB(gl_dispatch_stub_606, _gloffset__dispatch_stub_606)
+ GL_STUB(gl_dispatch_stub_622, _gloffset_PixelTexGenSGIX)
+ HIDDEN(gl_dispatch_stub_622)
GL_STUB(glBlendFuncSeparateEXT, _gloffset_BlendFuncSeparateEXT)
GL_STUB(glFlushVertexArrayRangeNV, _gloffset_FlushVertexArrayRangeNV)
GL_STUB(glVertexArrayRangeNV, _gloffset_VertexArrayRangeNV)
@@ -1486,15 +872,24 @@ _mesa_sparc_glapi_begin:
GL_STUB(glWindowPos4ivMESA, _gloffset_WindowPos4ivMESA)
GL_STUB(glWindowPos4sMESA, _gloffset_WindowPos4sMESA)
GL_STUB(glWindowPos4svMESA, _gloffset_WindowPos4svMESA)
- GL_STUB(gl_dispatch_stub_648, _gloffset__dispatch_stub_648)
- GL_STUB(gl_dispatch_stub_649, _gloffset__dispatch_stub_649)
- GL_STUB(gl_dispatch_stub_650, _gloffset__dispatch_stub_650)
- GL_STUB(gl_dispatch_stub_651, _gloffset__dispatch_stub_651)
- GL_STUB(gl_dispatch_stub_652, _gloffset__dispatch_stub_652)
- GL_STUB(gl_dispatch_stub_653, _gloffset__dispatch_stub_653)
- GL_STUB(gl_dispatch_stub_654, _gloffset__dispatch_stub_654)
- GL_STUB(gl_dispatch_stub_655, _gloffset__dispatch_stub_655)
- GL_STUB(gl_dispatch_stub_656, _gloffset__dispatch_stub_656)
+ GL_STUB(gl_dispatch_stub_664, _gloffset_MultiModeDrawArraysIBM)
+ HIDDEN(gl_dispatch_stub_664)
+ GL_STUB(gl_dispatch_stub_665, _gloffset_MultiModeDrawElementsIBM)
+ HIDDEN(gl_dispatch_stub_665)
+ GL_STUB(gl_dispatch_stub_666, _gloffset_DeleteFencesNV)
+ HIDDEN(gl_dispatch_stub_666)
+ GL_STUB(gl_dispatch_stub_667, _gloffset_FinishFenceNV)
+ HIDDEN(gl_dispatch_stub_667)
+ GL_STUB(gl_dispatch_stub_668, _gloffset_GenFencesNV)
+ HIDDEN(gl_dispatch_stub_668)
+ GL_STUB(gl_dispatch_stub_669, _gloffset_GetFenceivNV)
+ HIDDEN(gl_dispatch_stub_669)
+ GL_STUB(gl_dispatch_stub_670, _gloffset_IsFenceNV)
+ HIDDEN(gl_dispatch_stub_670)
+ GL_STUB(gl_dispatch_stub_671, _gloffset_SetFenceNV)
+ HIDDEN(gl_dispatch_stub_671)
+ GL_STUB(gl_dispatch_stub_672, _gloffset_TestFenceNV)
+ HIDDEN(gl_dispatch_stub_672)
GL_STUB(glAreProgramsResidentNV, _gloffset_AreProgramsResidentNV)
GL_STUB(glBindProgramNV, _gloffset_BindProgramNV)
GL_STUB(glDeleteProgramsNV, _gloffset_DeleteProgramsNV)
@@ -1555,6 +950,10 @@ _mesa_sparc_glapi_begin:
GL_STUB(glVertexAttribs4fvNV, _gloffset_VertexAttribs4fvNV)
GL_STUB(glVertexAttribs4svNV, _gloffset_VertexAttribs4svNV)
GL_STUB(glVertexAttribs4ubvNV, _gloffset_VertexAttribs4ubvNV)
+ GL_STUB(glGetTexBumpParameterfvATI, _gloffset_GetTexBumpParameterfvATI)
+ GL_STUB(glGetTexBumpParameterivATI, _gloffset_GetTexBumpParameterivATI)
+ GL_STUB(glTexBumpParameterfvATI, _gloffset_TexBumpParameterfvATI)
+ GL_STUB(glTexBumpParameterivATI, _gloffset_TexBumpParameterivATI)
GL_STUB(glAlphaFragmentOp1ATI, _gloffset_AlphaFragmentOp1ATI)
GL_STUB(glAlphaFragmentOp2ATI, _gloffset_AlphaFragmentOp2ATI)
GL_STUB(glAlphaFragmentOp3ATI, _gloffset_AlphaFragmentOp3ATI)
@@ -1571,19 +970,26 @@ _mesa_sparc_glapi_begin:
GL_STUB(glSetFragmentShaderConstantATI, _gloffset_SetFragmentShaderConstantATI)
GL_STUB(glPointParameteriNV, _gloffset_PointParameteriNV)
GL_STUB(glPointParameterivNV, _gloffset_PointParameterivNV)
- GL_STUB(gl_dispatch_stub_733, _gloffset__dispatch_stub_733)
- GL_STUB(gl_dispatch_stub_734, _gloffset__dispatch_stub_734)
- GL_STUB(gl_dispatch_stub_735, _gloffset__dispatch_stub_735)
- GL_STUB(gl_dispatch_stub_736, _gloffset__dispatch_stub_736)
- GL_STUB(gl_dispatch_stub_737, _gloffset__dispatch_stub_737)
+ GL_STUB(gl_dispatch_stub_753, _gloffset_ActiveStencilFaceEXT)
+ HIDDEN(gl_dispatch_stub_753)
+ GL_STUB(gl_dispatch_stub_754, _gloffset_BindVertexArrayAPPLE)
+ HIDDEN(gl_dispatch_stub_754)
+ GL_STUB(gl_dispatch_stub_755, _gloffset_DeleteVertexArraysAPPLE)
+ HIDDEN(gl_dispatch_stub_755)
+ GL_STUB(gl_dispatch_stub_756, _gloffset_GenVertexArraysAPPLE)
+ HIDDEN(gl_dispatch_stub_756)
+ GL_STUB(gl_dispatch_stub_757, _gloffset_IsVertexArrayAPPLE)
+ HIDDEN(gl_dispatch_stub_757)
GL_STUB(glGetProgramNamedParameterdvNV, _gloffset_GetProgramNamedParameterdvNV)
GL_STUB(glGetProgramNamedParameterfvNV, _gloffset_GetProgramNamedParameterfvNV)
GL_STUB(glProgramNamedParameter4dNV, _gloffset_ProgramNamedParameter4dNV)
GL_STUB(glProgramNamedParameter4dvNV, _gloffset_ProgramNamedParameter4dvNV)
GL_STUB(glProgramNamedParameter4fNV, _gloffset_ProgramNamedParameter4fNV)
GL_STUB(glProgramNamedParameter4fvNV, _gloffset_ProgramNamedParameter4fvNV)
- GL_STUB(gl_dispatch_stub_744, _gloffset__dispatch_stub_744)
- GL_STUB(gl_dispatch_stub_745, _gloffset__dispatch_stub_745)
+ GL_STUB(gl_dispatch_stub_764, _gloffset_DepthBoundsEXT)
+ HIDDEN(gl_dispatch_stub_764)
+ GL_STUB(gl_dispatch_stub_765, _gloffset_BlendEquationSeparateEXT)
+ HIDDEN(gl_dispatch_stub_765)
GL_STUB(glBindFramebufferEXT, _gloffset_BindFramebufferEXT)
GL_STUB(glBindRenderbufferEXT, _gloffset_BindRenderbufferEXT)
GL_STUB(glCheckFramebufferStatusEXT, _gloffset_CheckFramebufferStatusEXT)
@@ -1601,268 +1007,362 @@ _mesa_sparc_glapi_begin:
GL_STUB(glIsFramebufferEXT, _gloffset_IsFramebufferEXT)
GL_STUB(glIsRenderbufferEXT, _gloffset_IsRenderbufferEXT)
GL_STUB(glRenderbufferStorageEXT, _gloffset_RenderbufferStorageEXT)
- GL_STUB(gl_dispatch_stub_763, _gloffset__dispatch_stub_763)
+ GL_STUB(gl_dispatch_stub_783, _gloffset_BlitFramebufferEXT)
+ HIDDEN(gl_dispatch_stub_783)
+ GL_STUB(gl_dispatch_stub_784, _gloffset_BufferParameteriAPPLE)
+ HIDDEN(gl_dispatch_stub_784)
+ GL_STUB(gl_dispatch_stub_785, _gloffset_FlushMappedBufferRangeAPPLE)
+ HIDDEN(gl_dispatch_stub_785)
GL_STUB(glFramebufferTextureLayerEXT, _gloffset_FramebufferTextureLayerEXT)
- GL_STUB(gl_dispatch_stub_765, _gloffset__dispatch_stub_765)
- GL_STUB(gl_dispatch_stub_766, _gloffset__dispatch_stub_766)
- GL_STUB(gl_dispatch_stub_767, _gloffset__dispatch_stub_767)
- GL_STUB(gl_dispatch_stub_768, _gloffset__dispatch_stub_768)
- GL_STUB(gl_dispatch_stub_769, _gloffset__dispatch_stub_769)
-
- .globl _mesa_sparc_glapi_end ; .type _mesa_sparc_glapi_end,#function
-_mesa_sparc_glapi_end:
-
- .globl glArrayElementEXT ; .type glArrayElementEXT,#function ; glArrayElementEXT = glArrayElement
- .globl glBindTextureEXT ; .type glBindTextureEXT,#function ; glBindTextureEXT = glBindTexture
- .globl glDrawArraysEXT ; .type glDrawArraysEXT,#function ; glDrawArraysEXT = glDrawArrays
+ GL_STUB(glProvokingVertexEXT, _gloffset_ProvokingVertexEXT)
+ GL_STUB(gl_dispatch_stub_788, _gloffset_GetTexParameterPointervAPPLE)
+ HIDDEN(gl_dispatch_stub_788)
+ GL_STUB(gl_dispatch_stub_789, _gloffset_TextureRangeAPPLE)
+ HIDDEN(gl_dispatch_stub_789)
+ GL_STUB(gl_dispatch_stub_790, _gloffset_StencilFuncSeparateATI)
+ HIDDEN(gl_dispatch_stub_790)
+ GL_STUB(gl_dispatch_stub_791, _gloffset_ProgramEnvParameters4fvEXT)
+ HIDDEN(gl_dispatch_stub_791)
+ GL_STUB(gl_dispatch_stub_792, _gloffset_ProgramLocalParameters4fvEXT)
+ HIDDEN(gl_dispatch_stub_792)
+ GL_STUB(gl_dispatch_stub_793, _gloffset_GetQueryObjecti64vEXT)
+ HIDDEN(gl_dispatch_stub_793)
+ GL_STUB(gl_dispatch_stub_794, _gloffset_GetQueryObjectui64vEXT)
+ HIDDEN(gl_dispatch_stub_794)
+ GL_STUB_ALIAS(glArrayElementEXT, glArrayElement)
+ GL_STUB_ALIAS(glBindTextureEXT, glBindTexture)
+ GL_STUB_ALIAS(glDrawArraysEXT, glDrawArrays)
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glAreTexturesResidentEXT, glAreTexturesResident)
+#endif
+ GL_STUB_ALIAS(glCopyTexImage1DEXT, glCopyTexImage1D)
+ GL_STUB_ALIAS(glCopyTexImage2DEXT, glCopyTexImage2D)
+ GL_STUB_ALIAS(glCopyTexSubImage1DEXT, glCopyTexSubImage1D)
+ GL_STUB_ALIAS(glCopyTexSubImage2DEXT, glCopyTexSubImage2D)
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glDeleteTexturesEXT, glDeleteTextures)
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGenTexturesEXT, glGenTextures)
+#endif
+ GL_STUB_ALIAS(glGetPointervEXT, glGetPointerv)
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glIsTextureEXT, glIsTexture)
+#endif
+ GL_STUB_ALIAS(glPrioritizeTexturesEXT, glPrioritizeTextures)
+ GL_STUB_ALIAS(glTexSubImage1DEXT, glTexSubImage1D)
+ GL_STUB_ALIAS(glTexSubImage2DEXT, glTexSubImage2D)
+ GL_STUB_ALIAS(glBlendColorEXT, glBlendColor)
+ GL_STUB_ALIAS(glBlendEquationEXT, glBlendEquation)
+ GL_STUB_ALIAS(glDrawRangeElementsEXT, glDrawRangeElements)
+ GL_STUB_ALIAS(glColorTableSGI, glColorTable)
+ GL_STUB_ALIAS(glColorTableEXT, glColorTable)
+ GL_STUB_ALIAS(glColorTableParameterfvSGI, glColorTableParameterfv)
+ GL_STUB_ALIAS(glColorTableParameterivSGI, glColorTableParameteriv)
+ GL_STUB_ALIAS(glCopyColorTableSGI, glCopyColorTable)
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGetColorTableSGI, glGetColorTable)
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGetColorTableEXT, glGetColorTable)
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGetColorTableParameterfvSGI, glGetColorTableParameterfv)
+#endif
#ifndef GLX_INDIRECT_RENDERING
- .globl glAreTexturesResidentEXT ; .type glAreTexturesResidentEXT,#function ; glAreTexturesResidentEXT = glAreTexturesResident
+ GL_STUB_ALIAS(glGetColorTableParameterfvEXT, glGetColorTableParameterfv)
#endif
- .globl glCopyTexImage1DEXT ; .type glCopyTexImage1DEXT,#function ; glCopyTexImage1DEXT = glCopyTexImage1D
- .globl glCopyTexImage2DEXT ; .type glCopyTexImage2DEXT,#function ; glCopyTexImage2DEXT = glCopyTexImage2D
- .globl glCopyTexSubImage1DEXT ; .type glCopyTexSubImage1DEXT,#function ; glCopyTexSubImage1DEXT = glCopyTexSubImage1D
- .globl glCopyTexSubImage2DEXT ; .type glCopyTexSubImage2DEXT,#function ; glCopyTexSubImage2DEXT = glCopyTexSubImage2D
#ifndef GLX_INDIRECT_RENDERING
- .globl glDeleteTexturesEXT ; .type glDeleteTexturesEXT,#function ; glDeleteTexturesEXT = glDeleteTextures
+ GL_STUB_ALIAS(glGetColorTableParameterivSGI, glGetColorTableParameteriv)
#endif
#ifndef GLX_INDIRECT_RENDERING
- .globl glGenTexturesEXT ; .type glGenTexturesEXT,#function ; glGenTexturesEXT = glGenTextures
+ GL_STUB_ALIAS(glGetColorTableParameterivEXT, glGetColorTableParameteriv)
#endif
- .globl glGetPointervEXT ; .type glGetPointervEXT,#function ; glGetPointervEXT = glGetPointerv
+ GL_STUB_ALIAS(glColorSubTableEXT, glColorSubTable)
+ GL_STUB_ALIAS(glCopyColorSubTableEXT, glCopyColorSubTable)
+ GL_STUB_ALIAS(glConvolutionFilter1DEXT, glConvolutionFilter1D)
+ GL_STUB_ALIAS(glConvolutionFilter2DEXT, glConvolutionFilter2D)
+ GL_STUB_ALIAS(glConvolutionParameterfEXT, glConvolutionParameterf)
+ GL_STUB_ALIAS(glConvolutionParameterfvEXT, glConvolutionParameterfv)
+ GL_STUB_ALIAS(glConvolutionParameteriEXT, glConvolutionParameteri)
+ GL_STUB_ALIAS(glConvolutionParameterivEXT, glConvolutionParameteriv)
+ GL_STUB_ALIAS(glCopyConvolutionFilter1DEXT, glCopyConvolutionFilter1D)
+ GL_STUB_ALIAS(glCopyConvolutionFilter2DEXT, glCopyConvolutionFilter2D)
#ifndef GLX_INDIRECT_RENDERING
- .globl glIsTextureEXT ; .type glIsTextureEXT,#function ; glIsTextureEXT = glIsTexture
+ GL_STUB_ALIAS(glGetConvolutionFilterEXT, glGetConvolutionFilter)
#endif
- .globl glPrioritizeTexturesEXT ; .type glPrioritizeTexturesEXT,#function ; glPrioritizeTexturesEXT = glPrioritizeTextures
- .globl glTexSubImage1DEXT ; .type glTexSubImage1DEXT,#function ; glTexSubImage1DEXT = glTexSubImage1D
- .globl glTexSubImage2DEXT ; .type glTexSubImage2DEXT,#function ; glTexSubImage2DEXT = glTexSubImage2D
- .globl glBlendColorEXT ; .type glBlendColorEXT,#function ; glBlendColorEXT = glBlendColor
- .globl glBlendEquationEXT ; .type glBlendEquationEXT,#function ; glBlendEquationEXT = glBlendEquation
- .globl glDrawRangeElementsEXT ; .type glDrawRangeElementsEXT,#function ; glDrawRangeElementsEXT = glDrawRangeElements
- .globl glColorTableEXT ; .type glColorTableEXT,#function ; glColorTableEXT = glColorTable
#ifndef GLX_INDIRECT_RENDERING
- .globl glGetColorTableEXT ; .type glGetColorTableEXT,#function ; glGetColorTableEXT = glGetColorTable
+ GL_STUB_ALIAS(glGetConvolutionParameterfvEXT, glGetConvolutionParameterfv)
#endif
#ifndef GLX_INDIRECT_RENDERING
- .globl glGetColorTableParameterfvEXT ; .type glGetColorTableParameterfvEXT,#function ; glGetColorTableParameterfvEXT = glGetColorTableParameterfv
+ GL_STUB_ALIAS(glGetConvolutionParameterivEXT, glGetConvolutionParameteriv)
#endif
#ifndef GLX_INDIRECT_RENDERING
- .globl glGetColorTableParameterivEXT ; .type glGetColorTableParameterivEXT,#function ; glGetColorTableParameterivEXT = glGetColorTableParameteriv
+ GL_STUB_ALIAS(glGetSeparableFilterEXT, glGetSeparableFilter)
#endif
- .globl glTexImage3DEXT ; .type glTexImage3DEXT,#function ; glTexImage3DEXT = glTexImage3D
- .globl glTexSubImage3DEXT ; .type glTexSubImage3DEXT,#function ; glTexSubImage3DEXT = glTexSubImage3D
- .globl glCopyTexSubImage3DEXT ; .type glCopyTexSubImage3DEXT,#function ; glCopyTexSubImage3DEXT = glCopyTexSubImage3D
- .globl glActiveTexture ; .type glActiveTexture,#function ; glActiveTexture = glActiveTextureARB
- .globl glClientActiveTexture ; .type glClientActiveTexture,#function ; glClientActiveTexture = glClientActiveTextureARB
- .globl glMultiTexCoord1d ; .type glMultiTexCoord1d,#function ; glMultiTexCoord1d = glMultiTexCoord1dARB
- .globl glMultiTexCoord1dv ; .type glMultiTexCoord1dv,#function ; glMultiTexCoord1dv = glMultiTexCoord1dvARB
- .globl glMultiTexCoord1f ; .type glMultiTexCoord1f,#function ; glMultiTexCoord1f = glMultiTexCoord1fARB
- .globl glMultiTexCoord1fv ; .type glMultiTexCoord1fv,#function ; glMultiTexCoord1fv = glMultiTexCoord1fvARB
- .globl glMultiTexCoord1i ; .type glMultiTexCoord1i,#function ; glMultiTexCoord1i = glMultiTexCoord1iARB
- .globl glMultiTexCoord1iv ; .type glMultiTexCoord1iv,#function ; glMultiTexCoord1iv = glMultiTexCoord1ivARB
- .globl glMultiTexCoord1s ; .type glMultiTexCoord1s,#function ; glMultiTexCoord1s = glMultiTexCoord1sARB
- .globl glMultiTexCoord1sv ; .type glMultiTexCoord1sv,#function ; glMultiTexCoord1sv = glMultiTexCoord1svARB
- .globl glMultiTexCoord2d ; .type glMultiTexCoord2d,#function ; glMultiTexCoord2d = glMultiTexCoord2dARB
- .globl glMultiTexCoord2dv ; .type glMultiTexCoord2dv,#function ; glMultiTexCoord2dv = glMultiTexCoord2dvARB
- .globl glMultiTexCoord2f ; .type glMultiTexCoord2f,#function ; glMultiTexCoord2f = glMultiTexCoord2fARB
- .globl glMultiTexCoord2fv ; .type glMultiTexCoord2fv,#function ; glMultiTexCoord2fv = glMultiTexCoord2fvARB
- .globl glMultiTexCoord2i ; .type glMultiTexCoord2i,#function ; glMultiTexCoord2i = glMultiTexCoord2iARB
- .globl glMultiTexCoord2iv ; .type glMultiTexCoord2iv,#function ; glMultiTexCoord2iv = glMultiTexCoord2ivARB
- .globl glMultiTexCoord2s ; .type glMultiTexCoord2s,#function ; glMultiTexCoord2s = glMultiTexCoord2sARB
- .globl glMultiTexCoord2sv ; .type glMultiTexCoord2sv,#function ; glMultiTexCoord2sv = glMultiTexCoord2svARB
- .globl glMultiTexCoord3d ; .type glMultiTexCoord3d,#function ; glMultiTexCoord3d = glMultiTexCoord3dARB
- .globl glMultiTexCoord3dv ; .type glMultiTexCoord3dv,#function ; glMultiTexCoord3dv = glMultiTexCoord3dvARB
- .globl glMultiTexCoord3f ; .type glMultiTexCoord3f,#function ; glMultiTexCoord3f = glMultiTexCoord3fARB
- .globl glMultiTexCoord3fv ; .type glMultiTexCoord3fv,#function ; glMultiTexCoord3fv = glMultiTexCoord3fvARB
- .globl glMultiTexCoord3i ; .type glMultiTexCoord3i,#function ; glMultiTexCoord3i = glMultiTexCoord3iARB
- .globl glMultiTexCoord3iv ; .type glMultiTexCoord3iv,#function ; glMultiTexCoord3iv = glMultiTexCoord3ivARB
- .globl glMultiTexCoord3s ; .type glMultiTexCoord3s,#function ; glMultiTexCoord3s = glMultiTexCoord3sARB
- .globl glMultiTexCoord3sv ; .type glMultiTexCoord3sv,#function ; glMultiTexCoord3sv = glMultiTexCoord3svARB
- .globl glMultiTexCoord4d ; .type glMultiTexCoord4d,#function ; glMultiTexCoord4d = glMultiTexCoord4dARB
- .globl glMultiTexCoord4dv ; .type glMultiTexCoord4dv,#function ; glMultiTexCoord4dv = glMultiTexCoord4dvARB
- .globl glMultiTexCoord4f ; .type glMultiTexCoord4f,#function ; glMultiTexCoord4f = glMultiTexCoord4fARB
- .globl glMultiTexCoord4fv ; .type glMultiTexCoord4fv,#function ; glMultiTexCoord4fv = glMultiTexCoord4fvARB
- .globl glMultiTexCoord4i ; .type glMultiTexCoord4i,#function ; glMultiTexCoord4i = glMultiTexCoord4iARB
- .globl glMultiTexCoord4iv ; .type glMultiTexCoord4iv,#function ; glMultiTexCoord4iv = glMultiTexCoord4ivARB
- .globl glMultiTexCoord4s ; .type glMultiTexCoord4s,#function ; glMultiTexCoord4s = glMultiTexCoord4sARB
- .globl glMultiTexCoord4sv ; .type glMultiTexCoord4sv,#function ; glMultiTexCoord4sv = glMultiTexCoord4svARB
- .globl glLoadTransposeMatrixd ; .type glLoadTransposeMatrixd,#function ; glLoadTransposeMatrixd = glLoadTransposeMatrixdARB
- .globl glLoadTransposeMatrixf ; .type glLoadTransposeMatrixf,#function ; glLoadTransposeMatrixf = glLoadTransposeMatrixfARB
- .globl glMultTransposeMatrixd ; .type glMultTransposeMatrixd,#function ; glMultTransposeMatrixd = glMultTransposeMatrixdARB
- .globl glMultTransposeMatrixf ; .type glMultTransposeMatrixf,#function ; glMultTransposeMatrixf = glMultTransposeMatrixfARB
- .globl glSampleCoverage ; .type glSampleCoverage,#function ; glSampleCoverage = glSampleCoverageARB
- .globl glCompressedTexImage1D ; .type glCompressedTexImage1D,#function ; glCompressedTexImage1D = glCompressedTexImage1DARB
- .globl glCompressedTexImage2D ; .type glCompressedTexImage2D,#function ; glCompressedTexImage2D = glCompressedTexImage2DARB
- .globl glCompressedTexImage3D ; .type glCompressedTexImage3D,#function ; glCompressedTexImage3D = glCompressedTexImage3DARB
- .globl glCompressedTexSubImage1D ; .type glCompressedTexSubImage1D,#function ; glCompressedTexSubImage1D = glCompressedTexSubImage1DARB
- .globl glCompressedTexSubImage2D ; .type glCompressedTexSubImage2D,#function ; glCompressedTexSubImage2D = glCompressedTexSubImage2DARB
- .globl glCompressedTexSubImage3D ; .type glCompressedTexSubImage3D,#function ; glCompressedTexSubImage3D = glCompressedTexSubImage3DARB
- .globl glGetCompressedTexImage ; .type glGetCompressedTexImage,#function ; glGetCompressedTexImage = glGetCompressedTexImageARB
- .globl glDisableVertexAttribArray ; .type glDisableVertexAttribArray,#function ; glDisableVertexAttribArray = glDisableVertexAttribArrayARB
- .globl glEnableVertexAttribArray ; .type glEnableVertexAttribArray,#function ; glEnableVertexAttribArray = glEnableVertexAttribArrayARB
- .globl glGetVertexAttribdv ; .type glGetVertexAttribdv,#function ; glGetVertexAttribdv = glGetVertexAttribdvARB
- .globl glGetVertexAttribfv ; .type glGetVertexAttribfv,#function ; glGetVertexAttribfv = glGetVertexAttribfvARB
- .globl glGetVertexAttribiv ; .type glGetVertexAttribiv,#function ; glGetVertexAttribiv = glGetVertexAttribivARB
- .globl glProgramParameter4dNV ; .type glProgramParameter4dNV,#function ; glProgramParameter4dNV = glProgramEnvParameter4dARB
- .globl glProgramParameter4dvNV ; .type glProgramParameter4dvNV,#function ; glProgramParameter4dvNV = glProgramEnvParameter4dvARB
- .globl glProgramParameter4fNV ; .type glProgramParameter4fNV,#function ; glProgramParameter4fNV = glProgramEnvParameter4fARB
- .globl glProgramParameter4fvNV ; .type glProgramParameter4fvNV,#function ; glProgramParameter4fvNV = glProgramEnvParameter4fvARB
- .globl glVertexAttrib1d ; .type glVertexAttrib1d,#function ; glVertexAttrib1d = glVertexAttrib1dARB
- .globl glVertexAttrib1dv ; .type glVertexAttrib1dv,#function ; glVertexAttrib1dv = glVertexAttrib1dvARB
- .globl glVertexAttrib1f ; .type glVertexAttrib1f,#function ; glVertexAttrib1f = glVertexAttrib1fARB
- .globl glVertexAttrib1fv ; .type glVertexAttrib1fv,#function ; glVertexAttrib1fv = glVertexAttrib1fvARB
- .globl glVertexAttrib1s ; .type glVertexAttrib1s,#function ; glVertexAttrib1s = glVertexAttrib1sARB
- .globl glVertexAttrib1sv ; .type glVertexAttrib1sv,#function ; glVertexAttrib1sv = glVertexAttrib1svARB
- .globl glVertexAttrib2d ; .type glVertexAttrib2d,#function ; glVertexAttrib2d = glVertexAttrib2dARB
- .globl glVertexAttrib2dv ; .type glVertexAttrib2dv,#function ; glVertexAttrib2dv = glVertexAttrib2dvARB
- .globl glVertexAttrib2f ; .type glVertexAttrib2f,#function ; glVertexAttrib2f = glVertexAttrib2fARB
- .globl glVertexAttrib2fv ; .type glVertexAttrib2fv,#function ; glVertexAttrib2fv = glVertexAttrib2fvARB
- .globl glVertexAttrib2s ; .type glVertexAttrib2s,#function ; glVertexAttrib2s = glVertexAttrib2sARB
- .globl glVertexAttrib2sv ; .type glVertexAttrib2sv,#function ; glVertexAttrib2sv = glVertexAttrib2svARB
- .globl glVertexAttrib3d ; .type glVertexAttrib3d,#function ; glVertexAttrib3d = glVertexAttrib3dARB
- .globl glVertexAttrib3dv ; .type glVertexAttrib3dv,#function ; glVertexAttrib3dv = glVertexAttrib3dvARB
- .globl glVertexAttrib3f ; .type glVertexAttrib3f,#function ; glVertexAttrib3f = glVertexAttrib3fARB
- .globl glVertexAttrib3fv ; .type glVertexAttrib3fv,#function ; glVertexAttrib3fv = glVertexAttrib3fvARB
- .globl glVertexAttrib3s ; .type glVertexAttrib3s,#function ; glVertexAttrib3s = glVertexAttrib3sARB
- .globl glVertexAttrib3sv ; .type glVertexAttrib3sv,#function ; glVertexAttrib3sv = glVertexAttrib3svARB
- .globl glVertexAttrib4Nbv ; .type glVertexAttrib4Nbv,#function ; glVertexAttrib4Nbv = glVertexAttrib4NbvARB
- .globl glVertexAttrib4Niv ; .type glVertexAttrib4Niv,#function ; glVertexAttrib4Niv = glVertexAttrib4NivARB
- .globl glVertexAttrib4Nsv ; .type glVertexAttrib4Nsv,#function ; glVertexAttrib4Nsv = glVertexAttrib4NsvARB
- .globl glVertexAttrib4Nub ; .type glVertexAttrib4Nub,#function ; glVertexAttrib4Nub = glVertexAttrib4NubARB
- .globl glVertexAttrib4Nubv ; .type glVertexAttrib4Nubv,#function ; glVertexAttrib4Nubv = glVertexAttrib4NubvARB
- .globl glVertexAttrib4Nuiv ; .type glVertexAttrib4Nuiv,#function ; glVertexAttrib4Nuiv = glVertexAttrib4NuivARB
- .globl glVertexAttrib4Nusv ; .type glVertexAttrib4Nusv,#function ; glVertexAttrib4Nusv = glVertexAttrib4NusvARB
- .globl glVertexAttrib4bv ; .type glVertexAttrib4bv,#function ; glVertexAttrib4bv = glVertexAttrib4bvARB
- .globl glVertexAttrib4d ; .type glVertexAttrib4d,#function ; glVertexAttrib4d = glVertexAttrib4dARB
- .globl glVertexAttrib4dv ; .type glVertexAttrib4dv,#function ; glVertexAttrib4dv = glVertexAttrib4dvARB
- .globl glVertexAttrib4f ; .type glVertexAttrib4f,#function ; glVertexAttrib4f = glVertexAttrib4fARB
- .globl glVertexAttrib4fv ; .type glVertexAttrib4fv,#function ; glVertexAttrib4fv = glVertexAttrib4fvARB
- .globl glVertexAttrib4iv ; .type glVertexAttrib4iv,#function ; glVertexAttrib4iv = glVertexAttrib4ivARB
- .globl glVertexAttrib4s ; .type glVertexAttrib4s,#function ; glVertexAttrib4s = glVertexAttrib4sARB
- .globl glVertexAttrib4sv ; .type glVertexAttrib4sv,#function ; glVertexAttrib4sv = glVertexAttrib4svARB
- .globl glVertexAttrib4ubv ; .type glVertexAttrib4ubv,#function ; glVertexAttrib4ubv = glVertexAttrib4ubvARB
- .globl glVertexAttrib4uiv ; .type glVertexAttrib4uiv,#function ; glVertexAttrib4uiv = glVertexAttrib4uivARB
- .globl glVertexAttrib4usv ; .type glVertexAttrib4usv,#function ; glVertexAttrib4usv = glVertexAttrib4usvARB
- .globl glVertexAttribPointer ; .type glVertexAttribPointer,#function ; glVertexAttribPointer = glVertexAttribPointerARB
- .globl glBindBuffer ; .type glBindBuffer,#function ; glBindBuffer = glBindBufferARB
- .globl glBufferData ; .type glBufferData,#function ; glBufferData = glBufferDataARB
- .globl glBufferSubData ; .type glBufferSubData,#function ; glBufferSubData = glBufferSubDataARB
- .globl glDeleteBuffers ; .type glDeleteBuffers,#function ; glDeleteBuffers = glDeleteBuffersARB
- .globl glGenBuffers ; .type glGenBuffers,#function ; glGenBuffers = glGenBuffersARB
- .globl glGetBufferParameteriv ; .type glGetBufferParameteriv,#function ; glGetBufferParameteriv = glGetBufferParameterivARB
- .globl glGetBufferPointerv ; .type glGetBufferPointerv,#function ; glGetBufferPointerv = glGetBufferPointervARB
- .globl glGetBufferSubData ; .type glGetBufferSubData,#function ; glGetBufferSubData = glGetBufferSubDataARB
- .globl glIsBuffer ; .type glIsBuffer,#function ; glIsBuffer = glIsBufferARB
- .globl glMapBuffer ; .type glMapBuffer,#function ; glMapBuffer = glMapBufferARB
- .globl glUnmapBuffer ; .type glUnmapBuffer,#function ; glUnmapBuffer = glUnmapBufferARB
- .globl glBeginQuery ; .type glBeginQuery,#function ; glBeginQuery = glBeginQueryARB
- .globl glDeleteQueries ; .type glDeleteQueries,#function ; glDeleteQueries = glDeleteQueriesARB
- .globl glEndQuery ; .type glEndQuery,#function ; glEndQuery = glEndQueryARB
- .globl glGenQueries ; .type glGenQueries,#function ; glGenQueries = glGenQueriesARB
- .globl glGetQueryObjectiv ; .type glGetQueryObjectiv,#function ; glGetQueryObjectiv = glGetQueryObjectivARB
- .globl glGetQueryObjectuiv ; .type glGetQueryObjectuiv,#function ; glGetQueryObjectuiv = glGetQueryObjectuivARB
- .globl glGetQueryiv ; .type glGetQueryiv,#function ; glGetQueryiv = glGetQueryivARB
- .globl glIsQuery ; .type glIsQuery,#function ; glIsQuery = glIsQueryARB
- .globl glCompileShader ; .type glCompileShader,#function ; glCompileShader = glCompileShaderARB
- .globl glGetActiveUniform ; .type glGetActiveUniform,#function ; glGetActiveUniform = glGetActiveUniformARB
- .globl glGetShaderSource ; .type glGetShaderSource,#function ; glGetShaderSource = glGetShaderSourceARB
- .globl glGetUniformLocation ; .type glGetUniformLocation,#function ; glGetUniformLocation = glGetUniformLocationARB
- .globl glGetUniformfv ; .type glGetUniformfv,#function ; glGetUniformfv = glGetUniformfvARB
- .globl glGetUniformiv ; .type glGetUniformiv,#function ; glGetUniformiv = glGetUniformivARB
- .globl glLinkProgram ; .type glLinkProgram,#function ; glLinkProgram = glLinkProgramARB
- .globl glShaderSource ; .type glShaderSource,#function ; glShaderSource = glShaderSourceARB
- .globl glUniform1f ; .type glUniform1f,#function ; glUniform1f = glUniform1fARB
- .globl glUniform1fv ; .type glUniform1fv,#function ; glUniform1fv = glUniform1fvARB
- .globl glUniform1i ; .type glUniform1i,#function ; glUniform1i = glUniform1iARB
- .globl glUniform1iv ; .type glUniform1iv,#function ; glUniform1iv = glUniform1ivARB
- .globl glUniform2f ; .type glUniform2f,#function ; glUniform2f = glUniform2fARB
- .globl glUniform2fv ; .type glUniform2fv,#function ; glUniform2fv = glUniform2fvARB
- .globl glUniform2i ; .type glUniform2i,#function ; glUniform2i = glUniform2iARB
- .globl glUniform2iv ; .type glUniform2iv,#function ; glUniform2iv = glUniform2ivARB
- .globl glUniform3f ; .type glUniform3f,#function ; glUniform3f = glUniform3fARB
- .globl glUniform3fv ; .type glUniform3fv,#function ; glUniform3fv = glUniform3fvARB
- .globl glUniform3i ; .type glUniform3i,#function ; glUniform3i = glUniform3iARB
- .globl glUniform3iv ; .type glUniform3iv,#function ; glUniform3iv = glUniform3ivARB
- .globl glUniform4f ; .type glUniform4f,#function ; glUniform4f = glUniform4fARB
- .globl glUniform4fv ; .type glUniform4fv,#function ; glUniform4fv = glUniform4fvARB
- .globl glUniform4i ; .type glUniform4i,#function ; glUniform4i = glUniform4iARB
- .globl glUniform4iv ; .type glUniform4iv,#function ; glUniform4iv = glUniform4ivARB
- .globl glUniformMatrix2fv ; .type glUniformMatrix2fv,#function ; glUniformMatrix2fv = glUniformMatrix2fvARB
- .globl glUniformMatrix3fv ; .type glUniformMatrix3fv,#function ; glUniformMatrix3fv = glUniformMatrix3fvARB
- .globl glUniformMatrix4fv ; .type glUniformMatrix4fv,#function ; glUniformMatrix4fv = glUniformMatrix4fvARB
- .globl glUseProgram ; .type glUseProgram,#function ; glUseProgram = glUseProgramObjectARB
- .globl glValidateProgram ; .type glValidateProgram,#function ; glValidateProgram = glValidateProgramARB
- .globl glBindAttribLocation ; .type glBindAttribLocation,#function ; glBindAttribLocation = glBindAttribLocationARB
- .globl glGetActiveAttrib ; .type glGetActiveAttrib,#function ; glGetActiveAttrib = glGetActiveAttribARB
- .globl glGetAttribLocation ; .type glGetAttribLocation,#function ; glGetAttribLocation = glGetAttribLocationARB
- .globl glDrawBuffers ; .type glDrawBuffers,#function ; glDrawBuffers = glDrawBuffersARB
- .globl glDrawBuffersATI ; .type glDrawBuffersATI,#function ; glDrawBuffersATI = glDrawBuffersARB
- .globl glPointParameterf ; .type glPointParameterf,#function ; glPointParameterf = glPointParameterfEXT
- .globl glPointParameterfARB ; .type glPointParameterfARB,#function ; glPointParameterfARB = glPointParameterfEXT
- .globl glPointParameterfv ; .type glPointParameterfv,#function ; glPointParameterfv = glPointParameterfvEXT
- .globl glPointParameterfvARB ; .type glPointParameterfvARB,#function ; glPointParameterfvARB = glPointParameterfvEXT
- .globl glSecondaryColor3b ; .type glSecondaryColor3b,#function ; glSecondaryColor3b = glSecondaryColor3bEXT
- .globl glSecondaryColor3bv ; .type glSecondaryColor3bv,#function ; glSecondaryColor3bv = glSecondaryColor3bvEXT
- .globl glSecondaryColor3d ; .type glSecondaryColor3d,#function ; glSecondaryColor3d = glSecondaryColor3dEXT
- .globl glSecondaryColor3dv ; .type glSecondaryColor3dv,#function ; glSecondaryColor3dv = glSecondaryColor3dvEXT
- .globl glSecondaryColor3f ; .type glSecondaryColor3f,#function ; glSecondaryColor3f = glSecondaryColor3fEXT
- .globl glSecondaryColor3fv ; .type glSecondaryColor3fv,#function ; glSecondaryColor3fv = glSecondaryColor3fvEXT
- .globl glSecondaryColor3i ; .type glSecondaryColor3i,#function ; glSecondaryColor3i = glSecondaryColor3iEXT
- .globl glSecondaryColor3iv ; .type glSecondaryColor3iv,#function ; glSecondaryColor3iv = glSecondaryColor3ivEXT
- .globl glSecondaryColor3s ; .type glSecondaryColor3s,#function ; glSecondaryColor3s = glSecondaryColor3sEXT
- .globl glSecondaryColor3sv ; .type glSecondaryColor3sv,#function ; glSecondaryColor3sv = glSecondaryColor3svEXT
- .globl glSecondaryColor3ub ; .type glSecondaryColor3ub,#function ; glSecondaryColor3ub = glSecondaryColor3ubEXT
- .globl glSecondaryColor3ubv ; .type glSecondaryColor3ubv,#function ; glSecondaryColor3ubv = glSecondaryColor3ubvEXT
- .globl glSecondaryColor3ui ; .type glSecondaryColor3ui,#function ; glSecondaryColor3ui = glSecondaryColor3uiEXT
- .globl glSecondaryColor3uiv ; .type glSecondaryColor3uiv,#function ; glSecondaryColor3uiv = glSecondaryColor3uivEXT
- .globl glSecondaryColor3us ; .type glSecondaryColor3us,#function ; glSecondaryColor3us = glSecondaryColor3usEXT
- .globl glSecondaryColor3usv ; .type glSecondaryColor3usv,#function ; glSecondaryColor3usv = glSecondaryColor3usvEXT
- .globl glSecondaryColorPointer ; .type glSecondaryColorPointer,#function ; glSecondaryColorPointer = glSecondaryColorPointerEXT
- .globl glMultiDrawArrays ; .type glMultiDrawArrays,#function ; glMultiDrawArrays = glMultiDrawArraysEXT
- .globl glMultiDrawElements ; .type glMultiDrawElements,#function ; glMultiDrawElements = glMultiDrawElementsEXT
- .globl glFogCoordPointer ; .type glFogCoordPointer,#function ; glFogCoordPointer = glFogCoordPointerEXT
- .globl glFogCoordd ; .type glFogCoordd,#function ; glFogCoordd = glFogCoorddEXT
- .globl glFogCoorddv ; .type glFogCoorddv,#function ; glFogCoorddv = glFogCoorddvEXT
- .globl glFogCoordf ; .type glFogCoordf,#function ; glFogCoordf = glFogCoordfEXT
- .globl glFogCoordfv ; .type glFogCoordfv,#function ; glFogCoordfv = glFogCoordfvEXT
- .globl glBlendFuncSeparate ; .type glBlendFuncSeparate,#function ; glBlendFuncSeparate = glBlendFuncSeparateEXT
- .globl glWindowPos2d ; .type glWindowPos2d,#function ; glWindowPos2d = glWindowPos2dMESA
- .globl glWindowPos2dARB ; .type glWindowPos2dARB,#function ; glWindowPos2dARB = glWindowPos2dMESA
- .globl glWindowPos2dv ; .type glWindowPos2dv,#function ; glWindowPos2dv = glWindowPos2dvMESA
- .globl glWindowPos2dvARB ; .type glWindowPos2dvARB,#function ; glWindowPos2dvARB = glWindowPos2dvMESA
- .globl glWindowPos2f ; .type glWindowPos2f,#function ; glWindowPos2f = glWindowPos2fMESA
- .globl glWindowPos2fARB ; .type glWindowPos2fARB,#function ; glWindowPos2fARB = glWindowPos2fMESA
- .globl glWindowPos2fv ; .type glWindowPos2fv,#function ; glWindowPos2fv = glWindowPos2fvMESA
- .globl glWindowPos2fvARB ; .type glWindowPos2fvARB,#function ; glWindowPos2fvARB = glWindowPos2fvMESA
- .globl glWindowPos2i ; .type glWindowPos2i,#function ; glWindowPos2i = glWindowPos2iMESA
- .globl glWindowPos2iARB ; .type glWindowPos2iARB,#function ; glWindowPos2iARB = glWindowPos2iMESA
- .globl glWindowPos2iv ; .type glWindowPos2iv,#function ; glWindowPos2iv = glWindowPos2ivMESA
- .globl glWindowPos2ivARB ; .type glWindowPos2ivARB,#function ; glWindowPos2ivARB = glWindowPos2ivMESA
- .globl glWindowPos2s ; .type glWindowPos2s,#function ; glWindowPos2s = glWindowPos2sMESA
- .globl glWindowPos2sARB ; .type glWindowPos2sARB,#function ; glWindowPos2sARB = glWindowPos2sMESA
- .globl glWindowPos2sv ; .type glWindowPos2sv,#function ; glWindowPos2sv = glWindowPos2svMESA
- .globl glWindowPos2svARB ; .type glWindowPos2svARB,#function ; glWindowPos2svARB = glWindowPos2svMESA
- .globl glWindowPos3d ; .type glWindowPos3d,#function ; glWindowPos3d = glWindowPos3dMESA
- .globl glWindowPos3dARB ; .type glWindowPos3dARB,#function ; glWindowPos3dARB = glWindowPos3dMESA
- .globl glWindowPos3dv ; .type glWindowPos3dv,#function ; glWindowPos3dv = glWindowPos3dvMESA
- .globl glWindowPos3dvARB ; .type glWindowPos3dvARB,#function ; glWindowPos3dvARB = glWindowPos3dvMESA
- .globl glWindowPos3f ; .type glWindowPos3f,#function ; glWindowPos3f = glWindowPos3fMESA
- .globl glWindowPos3fARB ; .type glWindowPos3fARB,#function ; glWindowPos3fARB = glWindowPos3fMESA
- .globl glWindowPos3fv ; .type glWindowPos3fv,#function ; glWindowPos3fv = glWindowPos3fvMESA
- .globl glWindowPos3fvARB ; .type glWindowPos3fvARB,#function ; glWindowPos3fvARB = glWindowPos3fvMESA
- .globl glWindowPos3i ; .type glWindowPos3i,#function ; glWindowPos3i = glWindowPos3iMESA
- .globl glWindowPos3iARB ; .type glWindowPos3iARB,#function ; glWindowPos3iARB = glWindowPos3iMESA
- .globl glWindowPos3iv ; .type glWindowPos3iv,#function ; glWindowPos3iv = glWindowPos3ivMESA
- .globl glWindowPos3ivARB ; .type glWindowPos3ivARB,#function ; glWindowPos3ivARB = glWindowPos3ivMESA
- .globl glWindowPos3s ; .type glWindowPos3s,#function ; glWindowPos3s = glWindowPos3sMESA
- .globl glWindowPos3sARB ; .type glWindowPos3sARB,#function ; glWindowPos3sARB = glWindowPos3sMESA
- .globl glWindowPos3sv ; .type glWindowPos3sv,#function ; glWindowPos3sv = glWindowPos3svMESA
- .globl glWindowPos3svARB ; .type glWindowPos3svARB,#function ; glWindowPos3svARB = glWindowPos3svMESA
- .globl glBindProgramARB ; .type glBindProgramARB,#function ; glBindProgramARB = glBindProgramNV
- .globl glDeleteProgramsARB ; .type glDeleteProgramsARB,#function ; glDeleteProgramsARB = glDeleteProgramsNV
- .globl glGenProgramsARB ; .type glGenProgramsARB,#function ; glGenProgramsARB = glGenProgramsNV
- .globl glGetVertexAttribPointerv ; .type glGetVertexAttribPointerv,#function ; glGetVertexAttribPointerv = glGetVertexAttribPointervNV
- .globl glGetVertexAttribPointervARB ; .type glGetVertexAttribPointervARB,#function ; glGetVertexAttribPointervARB = glGetVertexAttribPointervNV
- .globl glIsProgramARB ; .type glIsProgramARB,#function ; glIsProgramARB = glIsProgramNV
- .globl glPointParameteri ; .type glPointParameteri,#function ; glPointParameteri = glPointParameteriNV
- .globl glPointParameteriv ; .type glPointParameteriv,#function ; glPointParameteriv = glPointParameterivNV
- .globl glBlendEquationSeparate ; .type glBlendEquationSeparate,#function ; glBlendEquationSeparate = glBlendEquationSeparateEXT
+ GL_STUB_ALIAS(glSeparableFilter2DEXT, glSeparableFilter2D)
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGetHistogramEXT, glGetHistogram)
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGetHistogramParameterfvEXT, glGetHistogramParameterfv)
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGetHistogramParameterivEXT, glGetHistogramParameteriv)
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGetMinmaxEXT, glGetMinmax)
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGetMinmaxParameterfvEXT, glGetMinmaxParameterfv)
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ GL_STUB_ALIAS(glGetMinmaxParameterivEXT, glGetMinmaxParameteriv)
+#endif
+ GL_STUB_ALIAS(glHistogramEXT, glHistogram)
+ GL_STUB_ALIAS(glMinmaxEXT, glMinmax)
+ GL_STUB_ALIAS(glResetHistogramEXT, glResetHistogram)
+ GL_STUB_ALIAS(glResetMinmaxEXT, glResetMinmax)
+ GL_STUB_ALIAS(glTexImage3DEXT, glTexImage3D)
+ GL_STUB_ALIAS(glTexSubImage3DEXT, glTexSubImage3D)
+ GL_STUB_ALIAS(glCopyTexSubImage3DEXT, glCopyTexSubImage3D)
+ GL_STUB_ALIAS(glActiveTexture, glActiveTextureARB)
+ GL_STUB_ALIAS(glClientActiveTexture, glClientActiveTextureARB)
+ GL_STUB_ALIAS(glMultiTexCoord1d, glMultiTexCoord1dARB)
+ GL_STUB_ALIAS(glMultiTexCoord1dv, glMultiTexCoord1dvARB)
+ GL_STUB_ALIAS(glMultiTexCoord1f, glMultiTexCoord1fARB)
+ GL_STUB_ALIAS(glMultiTexCoord1fv, glMultiTexCoord1fvARB)
+ GL_STUB_ALIAS(glMultiTexCoord1i, glMultiTexCoord1iARB)
+ GL_STUB_ALIAS(glMultiTexCoord1iv, glMultiTexCoord1ivARB)
+ GL_STUB_ALIAS(glMultiTexCoord1s, glMultiTexCoord1sARB)
+ GL_STUB_ALIAS(glMultiTexCoord1sv, glMultiTexCoord1svARB)
+ GL_STUB_ALIAS(glMultiTexCoord2d, glMultiTexCoord2dARB)
+ GL_STUB_ALIAS(glMultiTexCoord2dv, glMultiTexCoord2dvARB)
+ GL_STUB_ALIAS(glMultiTexCoord2f, glMultiTexCoord2fARB)
+ GL_STUB_ALIAS(glMultiTexCoord2fv, glMultiTexCoord2fvARB)
+ GL_STUB_ALIAS(glMultiTexCoord2i, glMultiTexCoord2iARB)
+ GL_STUB_ALIAS(glMultiTexCoord2iv, glMultiTexCoord2ivARB)
+ GL_STUB_ALIAS(glMultiTexCoord2s, glMultiTexCoord2sARB)
+ GL_STUB_ALIAS(glMultiTexCoord2sv, glMultiTexCoord2svARB)
+ GL_STUB_ALIAS(glMultiTexCoord3d, glMultiTexCoord3dARB)
+ GL_STUB_ALIAS(glMultiTexCoord3dv, glMultiTexCoord3dvARB)
+ GL_STUB_ALIAS(glMultiTexCoord3f, glMultiTexCoord3fARB)
+ GL_STUB_ALIAS(glMultiTexCoord3fv, glMultiTexCoord3fvARB)
+ GL_STUB_ALIAS(glMultiTexCoord3i, glMultiTexCoord3iARB)
+ GL_STUB_ALIAS(glMultiTexCoord3iv, glMultiTexCoord3ivARB)
+ GL_STUB_ALIAS(glMultiTexCoord3s, glMultiTexCoord3sARB)
+ GL_STUB_ALIAS(glMultiTexCoord3sv, glMultiTexCoord3svARB)
+ GL_STUB_ALIAS(glMultiTexCoord4d, glMultiTexCoord4dARB)
+ GL_STUB_ALIAS(glMultiTexCoord4dv, glMultiTexCoord4dvARB)
+ GL_STUB_ALIAS(glMultiTexCoord4f, glMultiTexCoord4fARB)
+ GL_STUB_ALIAS(glMultiTexCoord4fv, glMultiTexCoord4fvARB)
+ GL_STUB_ALIAS(glMultiTexCoord4i, glMultiTexCoord4iARB)
+ GL_STUB_ALIAS(glMultiTexCoord4iv, glMultiTexCoord4ivARB)
+ GL_STUB_ALIAS(glMultiTexCoord4s, glMultiTexCoord4sARB)
+ GL_STUB_ALIAS(glMultiTexCoord4sv, glMultiTexCoord4svARB)
+ GL_STUB_ALIAS(glStencilOpSeparateATI, glStencilOpSeparate)
+ GL_STUB_ALIAS(glLoadTransposeMatrixd, glLoadTransposeMatrixdARB)
+ GL_STUB_ALIAS(glLoadTransposeMatrixf, glLoadTransposeMatrixfARB)
+ GL_STUB_ALIAS(glMultTransposeMatrixd, glMultTransposeMatrixdARB)
+ GL_STUB_ALIAS(glMultTransposeMatrixf, glMultTransposeMatrixfARB)
+ GL_STUB_ALIAS(glSampleCoverage, glSampleCoverageARB)
+ GL_STUB_ALIAS(glCompressedTexImage1D, glCompressedTexImage1DARB)
+ GL_STUB_ALIAS(glCompressedTexImage2D, glCompressedTexImage2DARB)
+ GL_STUB_ALIAS(glCompressedTexImage3D, glCompressedTexImage3DARB)
+ GL_STUB_ALIAS(glCompressedTexSubImage1D, glCompressedTexSubImage1DARB)
+ GL_STUB_ALIAS(glCompressedTexSubImage2D, glCompressedTexSubImage2DARB)
+ GL_STUB_ALIAS(glCompressedTexSubImage3D, glCompressedTexSubImage3DARB)
+ GL_STUB_ALIAS(glGetCompressedTexImage, glGetCompressedTexImageARB)
+ GL_STUB_ALIAS(glDisableVertexAttribArray, glDisableVertexAttribArrayARB)
+ GL_STUB_ALIAS(glEnableVertexAttribArray, glEnableVertexAttribArrayARB)
+ GL_STUB_ALIAS(glGetVertexAttribdv, glGetVertexAttribdvARB)
+ GL_STUB_ALIAS(glGetVertexAttribfv, glGetVertexAttribfvARB)
+ GL_STUB_ALIAS(glGetVertexAttribiv, glGetVertexAttribivARB)
+ GL_STUB_ALIAS(glProgramParameter4dNV, glProgramEnvParameter4dARB)
+ GL_STUB_ALIAS(glProgramParameter4dvNV, glProgramEnvParameter4dvARB)
+ GL_STUB_ALIAS(glProgramParameter4fNV, glProgramEnvParameter4fARB)
+ GL_STUB_ALIAS(glProgramParameter4fvNV, glProgramEnvParameter4fvARB)
+ GL_STUB_ALIAS(glVertexAttrib1d, glVertexAttrib1dARB)
+ GL_STUB_ALIAS(glVertexAttrib1dv, glVertexAttrib1dvARB)
+ GL_STUB_ALIAS(glVertexAttrib1f, glVertexAttrib1fARB)
+ GL_STUB_ALIAS(glVertexAttrib1fv, glVertexAttrib1fvARB)
+ GL_STUB_ALIAS(glVertexAttrib1s, glVertexAttrib1sARB)
+ GL_STUB_ALIAS(glVertexAttrib1sv, glVertexAttrib1svARB)
+ GL_STUB_ALIAS(glVertexAttrib2d, glVertexAttrib2dARB)
+ GL_STUB_ALIAS(glVertexAttrib2dv, glVertexAttrib2dvARB)
+ GL_STUB_ALIAS(glVertexAttrib2f, glVertexAttrib2fARB)
+ GL_STUB_ALIAS(glVertexAttrib2fv, glVertexAttrib2fvARB)
+ GL_STUB_ALIAS(glVertexAttrib2s, glVertexAttrib2sARB)
+ GL_STUB_ALIAS(glVertexAttrib2sv, glVertexAttrib2svARB)
+ GL_STUB_ALIAS(glVertexAttrib3d, glVertexAttrib3dARB)
+ GL_STUB_ALIAS(glVertexAttrib3dv, glVertexAttrib3dvARB)
+ GL_STUB_ALIAS(glVertexAttrib3f, glVertexAttrib3fARB)
+ GL_STUB_ALIAS(glVertexAttrib3fv, glVertexAttrib3fvARB)
+ GL_STUB_ALIAS(glVertexAttrib3s, glVertexAttrib3sARB)
+ GL_STUB_ALIAS(glVertexAttrib3sv, glVertexAttrib3svARB)
+ GL_STUB_ALIAS(glVertexAttrib4Nbv, glVertexAttrib4NbvARB)
+ GL_STUB_ALIAS(glVertexAttrib4Niv, glVertexAttrib4NivARB)
+ GL_STUB_ALIAS(glVertexAttrib4Nsv, glVertexAttrib4NsvARB)
+ GL_STUB_ALIAS(glVertexAttrib4Nub, glVertexAttrib4NubARB)
+ GL_STUB_ALIAS(glVertexAttrib4Nubv, glVertexAttrib4NubvARB)
+ GL_STUB_ALIAS(glVertexAttrib4Nuiv, glVertexAttrib4NuivARB)
+ GL_STUB_ALIAS(glVertexAttrib4Nusv, glVertexAttrib4NusvARB)
+ GL_STUB_ALIAS(glVertexAttrib4bv, glVertexAttrib4bvARB)
+ GL_STUB_ALIAS(glVertexAttrib4d, glVertexAttrib4dARB)
+ GL_STUB_ALIAS(glVertexAttrib4dv, glVertexAttrib4dvARB)
+ GL_STUB_ALIAS(glVertexAttrib4f, glVertexAttrib4fARB)
+ GL_STUB_ALIAS(glVertexAttrib4fv, glVertexAttrib4fvARB)
+ GL_STUB_ALIAS(glVertexAttrib4iv, glVertexAttrib4ivARB)
+ GL_STUB_ALIAS(glVertexAttrib4s, glVertexAttrib4sARB)
+ GL_STUB_ALIAS(glVertexAttrib4sv, glVertexAttrib4svARB)
+ GL_STUB_ALIAS(glVertexAttrib4ubv, glVertexAttrib4ubvARB)
+ GL_STUB_ALIAS(glVertexAttrib4uiv, glVertexAttrib4uivARB)
+ GL_STUB_ALIAS(glVertexAttrib4usv, glVertexAttrib4usvARB)
+ GL_STUB_ALIAS(glVertexAttribPointer, glVertexAttribPointerARB)
+ GL_STUB_ALIAS(glBindBuffer, glBindBufferARB)
+ GL_STUB_ALIAS(glBufferData, glBufferDataARB)
+ GL_STUB_ALIAS(glBufferSubData, glBufferSubDataARB)
+ GL_STUB_ALIAS(glDeleteBuffers, glDeleteBuffersARB)
+ GL_STUB_ALIAS(glGenBuffers, glGenBuffersARB)
+ GL_STUB_ALIAS(glGetBufferParameteriv, glGetBufferParameterivARB)
+ GL_STUB_ALIAS(glGetBufferPointerv, glGetBufferPointervARB)
+ GL_STUB_ALIAS(glGetBufferSubData, glGetBufferSubDataARB)
+ GL_STUB_ALIAS(glIsBuffer, glIsBufferARB)
+ GL_STUB_ALIAS(glMapBuffer, glMapBufferARB)
+ GL_STUB_ALIAS(glUnmapBuffer, glUnmapBufferARB)
+ GL_STUB_ALIAS(glBeginQuery, glBeginQueryARB)
+ GL_STUB_ALIAS(glDeleteQueries, glDeleteQueriesARB)
+ GL_STUB_ALIAS(glEndQuery, glEndQueryARB)
+ GL_STUB_ALIAS(glGenQueries, glGenQueriesARB)
+ GL_STUB_ALIAS(glGetQueryObjectiv, glGetQueryObjectivARB)
+ GL_STUB_ALIAS(glGetQueryObjectuiv, glGetQueryObjectuivARB)
+ GL_STUB_ALIAS(glGetQueryiv, glGetQueryivARB)
+ GL_STUB_ALIAS(glIsQuery, glIsQueryARB)
+ GL_STUB_ALIAS(glCompileShader, glCompileShaderARB)
+ GL_STUB_ALIAS(glGetActiveUniform, glGetActiveUniformARB)
+ GL_STUB_ALIAS(glGetShaderSource, glGetShaderSourceARB)
+ GL_STUB_ALIAS(glGetUniformLocation, glGetUniformLocationARB)
+ GL_STUB_ALIAS(glGetUniformfv, glGetUniformfvARB)
+ GL_STUB_ALIAS(glGetUniformiv, glGetUniformivARB)
+ GL_STUB_ALIAS(glLinkProgram, glLinkProgramARB)
+ GL_STUB_ALIAS(glShaderSource, glShaderSourceARB)
+ GL_STUB_ALIAS(glUniform1f, glUniform1fARB)
+ GL_STUB_ALIAS(glUniform1fv, glUniform1fvARB)
+ GL_STUB_ALIAS(glUniform1i, glUniform1iARB)
+ GL_STUB_ALIAS(glUniform1iv, glUniform1ivARB)
+ GL_STUB_ALIAS(glUniform2f, glUniform2fARB)
+ GL_STUB_ALIAS(glUniform2fv, glUniform2fvARB)
+ GL_STUB_ALIAS(glUniform2i, glUniform2iARB)
+ GL_STUB_ALIAS(glUniform2iv, glUniform2ivARB)
+ GL_STUB_ALIAS(glUniform3f, glUniform3fARB)
+ GL_STUB_ALIAS(glUniform3fv, glUniform3fvARB)
+ GL_STUB_ALIAS(glUniform3i, glUniform3iARB)
+ GL_STUB_ALIAS(glUniform3iv, glUniform3ivARB)
+ GL_STUB_ALIAS(glUniform4f, glUniform4fARB)
+ GL_STUB_ALIAS(glUniform4fv, glUniform4fvARB)
+ GL_STUB_ALIAS(glUniform4i, glUniform4iARB)
+ GL_STUB_ALIAS(glUniform4iv, glUniform4ivARB)
+ GL_STUB_ALIAS(glUniformMatrix2fv, glUniformMatrix2fvARB)
+ GL_STUB_ALIAS(glUniformMatrix3fv, glUniformMatrix3fvARB)
+ GL_STUB_ALIAS(glUniformMatrix4fv, glUniformMatrix4fvARB)
+ GL_STUB_ALIAS(glUseProgram, glUseProgramObjectARB)
+ GL_STUB_ALIAS(glValidateProgram, glValidateProgramARB)
+ GL_STUB_ALIAS(glBindAttribLocation, glBindAttribLocationARB)
+ GL_STUB_ALIAS(glGetActiveAttrib, glGetActiveAttribARB)
+ GL_STUB_ALIAS(glGetAttribLocation, glGetAttribLocationARB)
+ GL_STUB_ALIAS(glDrawBuffers, glDrawBuffersARB)
+ GL_STUB_ALIAS(glDrawBuffersATI, glDrawBuffersARB)
+ GL_STUB_ALIAS(glPointParameterf, glPointParameterfEXT)
+ GL_STUB_ALIAS(glPointParameterfARB, glPointParameterfEXT)
+ GL_STUB_ALIAS(glPointParameterfSGIS, glPointParameterfEXT)
+ GL_STUB_ALIAS(glPointParameterfv, glPointParameterfvEXT)
+ GL_STUB_ALIAS(glPointParameterfvARB, glPointParameterfvEXT)
+ GL_STUB_ALIAS(glPointParameterfvSGIS, glPointParameterfvEXT)
+ GL_STUB_ALIAS(glSecondaryColor3b, glSecondaryColor3bEXT)
+ GL_STUB_ALIAS(glSecondaryColor3bv, glSecondaryColor3bvEXT)
+ GL_STUB_ALIAS(glSecondaryColor3d, glSecondaryColor3dEXT)
+ GL_STUB_ALIAS(glSecondaryColor3dv, glSecondaryColor3dvEXT)
+ GL_STUB_ALIAS(glSecondaryColor3f, glSecondaryColor3fEXT)
+ GL_STUB_ALIAS(glSecondaryColor3fv, glSecondaryColor3fvEXT)
+ GL_STUB_ALIAS(glSecondaryColor3i, glSecondaryColor3iEXT)
+ GL_STUB_ALIAS(glSecondaryColor3iv, glSecondaryColor3ivEXT)
+ GL_STUB_ALIAS(glSecondaryColor3s, glSecondaryColor3sEXT)
+ GL_STUB_ALIAS(glSecondaryColor3sv, glSecondaryColor3svEXT)
+ GL_STUB_ALIAS(glSecondaryColor3ub, glSecondaryColor3ubEXT)
+ GL_STUB_ALIAS(glSecondaryColor3ubv, glSecondaryColor3ubvEXT)
+ GL_STUB_ALIAS(glSecondaryColor3ui, glSecondaryColor3uiEXT)
+ GL_STUB_ALIAS(glSecondaryColor3uiv, glSecondaryColor3uivEXT)
+ GL_STUB_ALIAS(glSecondaryColor3us, glSecondaryColor3usEXT)
+ GL_STUB_ALIAS(glSecondaryColor3usv, glSecondaryColor3usvEXT)
+ GL_STUB_ALIAS(glSecondaryColorPointer, glSecondaryColorPointerEXT)
+ GL_STUB_ALIAS(glMultiDrawArrays, glMultiDrawArraysEXT)
+ GL_STUB_ALIAS(glMultiDrawElements, glMultiDrawElementsEXT)
+ GL_STUB_ALIAS(glFogCoordPointer, glFogCoordPointerEXT)
+ GL_STUB_ALIAS(glFogCoordd, glFogCoorddEXT)
+ GL_STUB_ALIAS(glFogCoorddv, glFogCoorddvEXT)
+ GL_STUB_ALIAS(glFogCoordf, glFogCoordfEXT)
+ GL_STUB_ALIAS(glFogCoordfv, glFogCoordfvEXT)
+ GL_STUB_ALIAS(glBlendFuncSeparate, glBlendFuncSeparateEXT)
+ GL_STUB_ALIAS(glBlendFuncSeparateINGR, glBlendFuncSeparateEXT)
+ GL_STUB_ALIAS(glWindowPos2d, glWindowPos2dMESA)
+ GL_STUB_ALIAS(glWindowPos2dARB, glWindowPos2dMESA)
+ GL_STUB_ALIAS(glWindowPos2dv, glWindowPos2dvMESA)
+ GL_STUB_ALIAS(glWindowPos2dvARB, glWindowPos2dvMESA)
+ GL_STUB_ALIAS(glWindowPos2f, glWindowPos2fMESA)
+ GL_STUB_ALIAS(glWindowPos2fARB, glWindowPos2fMESA)
+ GL_STUB_ALIAS(glWindowPos2fv, glWindowPos2fvMESA)
+ GL_STUB_ALIAS(glWindowPos2fvARB, glWindowPos2fvMESA)
+ GL_STUB_ALIAS(glWindowPos2i, glWindowPos2iMESA)
+ GL_STUB_ALIAS(glWindowPos2iARB, glWindowPos2iMESA)
+ GL_STUB_ALIAS(glWindowPos2iv, glWindowPos2ivMESA)
+ GL_STUB_ALIAS(glWindowPos2ivARB, glWindowPos2ivMESA)
+ GL_STUB_ALIAS(glWindowPos2s, glWindowPos2sMESA)
+ GL_STUB_ALIAS(glWindowPos2sARB, glWindowPos2sMESA)
+ GL_STUB_ALIAS(glWindowPos2sv, glWindowPos2svMESA)
+ GL_STUB_ALIAS(glWindowPos2svARB, glWindowPos2svMESA)
+ GL_STUB_ALIAS(glWindowPos3d, glWindowPos3dMESA)
+ GL_STUB_ALIAS(glWindowPos3dARB, glWindowPos3dMESA)
+ GL_STUB_ALIAS(glWindowPos3dv, glWindowPos3dvMESA)
+ GL_STUB_ALIAS(glWindowPos3dvARB, glWindowPos3dvMESA)
+ GL_STUB_ALIAS(glWindowPos3f, glWindowPos3fMESA)
+ GL_STUB_ALIAS(glWindowPos3fARB, glWindowPos3fMESA)
+ GL_STUB_ALIAS(glWindowPos3fv, glWindowPos3fvMESA)
+ GL_STUB_ALIAS(glWindowPos3fvARB, glWindowPos3fvMESA)
+ GL_STUB_ALIAS(glWindowPos3i, glWindowPos3iMESA)
+ GL_STUB_ALIAS(glWindowPos3iARB, glWindowPos3iMESA)
+ GL_STUB_ALIAS(glWindowPos3iv, glWindowPos3ivMESA)
+ GL_STUB_ALIAS(glWindowPos3ivARB, glWindowPos3ivMESA)
+ GL_STUB_ALIAS(glWindowPos3s, glWindowPos3sMESA)
+ GL_STUB_ALIAS(glWindowPos3sARB, glWindowPos3sMESA)
+ GL_STUB_ALIAS(glWindowPos3sv, glWindowPos3svMESA)
+ GL_STUB_ALIAS(glWindowPos3svARB, glWindowPos3svMESA)
+ GL_STUB_ALIAS(glBindProgramARB, glBindProgramNV)
+ GL_STUB_ALIAS(glDeleteProgramsARB, glDeleteProgramsNV)
+ GL_STUB_ALIAS(glGenProgramsARB, glGenProgramsNV)
+ GL_STUB_ALIAS(glGetVertexAttribPointerv, glGetVertexAttribPointervNV)
+ GL_STUB_ALIAS(glGetVertexAttribPointervARB, glGetVertexAttribPointervNV)
+ GL_STUB_ALIAS(glIsProgramARB, glIsProgramNV)
+ GL_STUB_ALIAS(glPointParameteri, glPointParameteriNV)
+ GL_STUB_ALIAS(glPointParameteriv, glPointParameterivNV)
+ GL_STUB_ALIAS(glBindFramebuffer, glBindFramebufferEXT)
+ GL_STUB_ALIAS(glBindRenderbuffer, glBindRenderbufferEXT)
+ GL_STUB_ALIAS(glCheckFramebufferStatus, glCheckFramebufferStatusEXT)
+ GL_STUB_ALIAS(glDeleteFramebuffers, glDeleteFramebuffersEXT)
+ GL_STUB_ALIAS(glDeleteRenderbuffers, glDeleteRenderbuffersEXT)
+ GL_STUB_ALIAS(glFramebufferRenderbuffer, glFramebufferRenderbufferEXT)
+ GL_STUB_ALIAS(glFramebufferTexture1D, glFramebufferTexture1DEXT)
+ GL_STUB_ALIAS(glFramebufferTexture2D, glFramebufferTexture2DEXT)
+ GL_STUB_ALIAS(glFramebufferTexture3D, glFramebufferTexture3DEXT)
+ GL_STUB_ALIAS(glGenFramebuffers, glGenFramebuffersEXT)
+ GL_STUB_ALIAS(glGenRenderbuffers, glGenRenderbuffersEXT)
+ GL_STUB_ALIAS(glGenerateMipmap, glGenerateMipmapEXT)
+ GL_STUB_ALIAS(glGetFramebufferAttachmentParameteriv, glGetFramebufferAttachmentParameterivEXT)
+ GL_STUB_ALIAS(glGetRenderbufferParameteriv, glGetRenderbufferParameterivEXT)
+ GL_STUB_ALIAS(glIsFramebuffer, glIsFramebufferEXT)
+ GL_STUB_ALIAS(glIsRenderbuffer, glIsRenderbufferEXT)
+ GL_STUB_ALIAS(glRenderbufferStorage, glRenderbufferStorageEXT)
+ GL_STUB_ALIAS(glFramebufferTextureLayer, glFramebufferTextureLayerEXT)
+
+ .globl gl_dispatch_functions_end
+ HIDDEN(gl_dispatch_functions_end)
+gl_dispatch_functions_end:
diff --git a/src/mesa/sparc/norm.S b/src/mesa/sparc/norm.S
index 44950a10a5..117d36fa22 100644
--- a/src/mesa/sparc/norm.S
+++ b/src/mesa/sparc/norm.S
@@ -1,11 +1,8 @@
#include "sparc_matrix.h"
-#if defined(SVR4) || defined(__SVR4) || defined(__svr4__)
- /* Solaris requires this for 64-bit. */
.register %g2, #scratch
.register %g3, #scratch
-#endif
.text
@@ -98,7 +95,7 @@ _mesa_sparc_transform_normalize_normals:
cmp %o4, %g1 ! continue if (i < count)
bl 1b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
ba 7f
nop
@@ -154,7 +151,7 @@ _mesa_sparc_transform_normalize_normals:
cmp %o4, %g1 ! continue if (i < count)
bl 5b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
@@ -225,7 +222,7 @@ _mesa_sparc_transform_normalize_normals_no_rot:
cmp %o4, %g1 ! continue if (i < count)
bl 1b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
ba 7f
nop
@@ -263,7 +260,7 @@ _mesa_sparc_transform_normalize_normals_no_rot:
cmp %o4, %g1 ! continue if (i < count)
bl 5b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
@@ -314,7 +311,7 @@ _mesa_sparc_transform_rescale_normals_no_rot:
cmp %o4, %g1 ! continue if (i < count)
bl 1b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
@@ -379,7 +376,7 @@ _mesa_sparc_transform_rescale_normals:
cmp %o4, %g1 ! continue if (i < count)
bl 1b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
@@ -421,7 +418,7 @@ _mesa_sparc_transform_normals_no_rot:
cmp %o4, %g1 ! continue if (i < count)
bl 1b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
@@ -471,7 +468,7 @@ _mesa_sparc_transform_normals:
cmp %o4, %g1 ! continue if (i < count)
bl 1b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
@@ -529,7 +526,7 @@ _mesa_sparc_normalize_normals:
cmp %o4, %g1 ! continue if (i < count)
bl 1b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
ba 7f
nop
@@ -557,7 +554,7 @@ _mesa_sparc_normalize_normals:
cmp %o4, %g1 ! continue if (i < count)
bl 5b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
@@ -602,7 +599,7 @@ _mesa_sparc_rescale_normals:
cmp %o4, %g1 ! continue if (i < count)
bl 1b
- add %g3, 0x0c, %g3 ! advance out vector pointer
+ add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
diff --git a/src/mesa/sparc/sparc.c b/src/mesa/sparc/sparc.c
index 84e8ac6723..cea0c7cecf 100644
--- a/src/mesa/sparc/sparc.c
+++ b/src/mesa/sparc/sparc.c
@@ -78,13 +78,15 @@ extern GLvector4f *_mesa_sparc_cliptest_points4(GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask);
+ GLubyte *andMask,
+ GLboolean viewport_z_clip);
extern GLvector4f *_mesa_sparc_cliptest_points4_np(GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask);
+ GLubyte *andMask,
+ GLboolean viewport_z_clip);
#define NORM_ARGS const GLmatrix *mat, \
GLfloat scale, \
@@ -113,8 +115,6 @@ void _mesa_init_all_sparc_transform_asm(void)
_mesa_clip_tab[4] = _mesa_sparc_cliptest_points4;
_mesa_clip_np_tab[4] = _mesa_sparc_cliptest_points4_np;
-#if 0
- /* disable these too. See bug 673938 */
_mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
_mesa_sparc_transform_normalize_normals;
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
@@ -131,7 +131,6 @@ void _mesa_init_all_sparc_transform_asm(void)
_mesa_sparc_normalize_normals;
_mesa_normal_tab[NORM_RESCALE] =
_mesa_sparc_rescale_normals;
-#endif
#ifdef DEBUG_MATH
_math_test_all_transform_functions("sparc");
@@ -140,38 +139,4 @@ void _mesa_init_all_sparc_transform_asm(void)
#endif
}
-extern unsigned int _mesa_sparc_glapi_begin;
-extern unsigned int _mesa_sparc_glapi_end;
-extern void __glapi_sparc_icache_flush(unsigned int *);
-
#endif /* USE_SPARC_ASM */
-
-
-void _mesa_init_sparc_glapi_relocs(void)
-{
-#ifdef USE_SPARC_ASM
- unsigned int *insn_ptr, *end_ptr;
- unsigned long disp_addr;
-
- insn_ptr = &_mesa_sparc_glapi_begin;
- end_ptr = &_mesa_sparc_glapi_end;
- disp_addr = (unsigned long) &_glapi_Dispatch;
-
- while (insn_ptr < end_ptr) {
-#ifdef __arch64__
- insn_ptr[0] |= (disp_addr >> (32 + 10));
- insn_ptr[1] |= ((disp_addr & 0xffffffff) >> 10);
- __glapi_sparc_icache_flush(&insn_ptr[0]);
- insn_ptr[2] |= ((disp_addr >> 32) & ((1 << 10) - 1));
- insn_ptr[3] |= (disp_addr & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&insn_ptr[2]);
- insn_ptr += 11;
-#else
- insn_ptr[0] |= (disp_addr >> 10);
- insn_ptr[1] |= (disp_addr & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&insn_ptr[0]);
- insn_ptr += 5;
-#endif
- }
-#endif /* USE_SPARC_ASM */
-}
diff --git a/src/mesa/sparc/sparc.h b/src/mesa/sparc/sparc.h
index a98e4d0e40..b9ea336856 100644
--- a/src/mesa/sparc/sparc.h
+++ b/src/mesa/sparc/sparc.h
@@ -32,6 +32,5 @@
#define SPARC_H
extern void _mesa_init_all_sparc_transform_asm(void);
-extern void _mesa_init_sparc_glapi_relocs(void);
#endif /* !(SPARC_H) */
diff --git a/src/mesa/state_tracker/Makefile b/src/mesa/state_tracker/Makefile
new file mode 100644
index 0000000000..0ab1dc6e6b
--- /dev/null
+++ b/src/mesa/state_tracker/Makefile
@@ -0,0 +1,2 @@
+default:
+ cd ../.. ; make \ No newline at end of file
diff --git a/src/mesa/state_tracker/st_api.c b/src/mesa/state_tracker/st_api.c
new file mode 100644
index 0000000000..fc0e9a2316
--- /dev/null
+++ b/src/mesa/state_tracker/st_api.c
@@ -0,0 +1,33 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Just a global symbol for EGL to look for to identify the supported
+ * graphics API.
+ */
+int st_api_OpenGL = 1;
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c
new file mode 100644
index 0000000000..ca15ce1b47
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom.c
@@ -0,0 +1,192 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+
+#include "pipe/p_defines.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_bitmap.h"
+#include "st_program.h"
+
+
+
+/**
+ * This is used to initialize st->atoms[].
+ */
+static const struct st_tracked_state *atoms[] =
+{
+ &st_update_depth_stencil_alpha,
+ &st_update_clip,
+
+ &st_finalize_textures,
+ &st_update_shader,
+
+ &st_update_rasterizer,
+ &st_update_polygon_stipple,
+ &st_update_viewport,
+ &st_update_scissor,
+ &st_update_blend,
+ &st_update_sampler,
+ &st_update_texture,
+ &st_update_framebuffer,
+ &st_update_vs_constants,
+ &st_update_fs_constants,
+ &st_update_pixel_transfer
+};
+
+
+void st_init_atoms( struct st_context *st )
+{
+ /* no-op */
+}
+
+
+void st_destroy_atoms( struct st_context *st )
+{
+ /* no-op */
+}
+
+
+/***********************************************************************
+ */
+
+static GLboolean check_state( const struct st_state_flags *a,
+ const struct st_state_flags *b )
+{
+ return ((a->mesa & b->mesa) ||
+ (a->st & b->st));
+}
+
+static void accumulate_state( struct st_state_flags *a,
+ const struct st_state_flags *b )
+{
+ a->mesa |= b->mesa;
+ a->st |= b->st;
+}
+
+
+static void xor_states( struct st_state_flags *result,
+ const struct st_state_flags *a,
+ const struct st_state_flags *b )
+{
+ result->mesa = a->mesa ^ b->mesa;
+ result->st = a->st ^ b->st;
+}
+
+
+/* Too complex to figure out, just check every time:
+ */
+static void check_program_state( struct st_context *st )
+{
+ GLcontext *ctx = st->ctx;
+
+ if (ctx->VertexProgram._Current != &st->vp->Base)
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+
+ if (ctx->FragmentProgram._Current != &st->fp->Base)
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+
+}
+
+
+/***********************************************************************
+ * Update all derived state:
+ */
+
+void st_validate_state( struct st_context *st )
+{
+ struct st_state_flags *state = &st->dirty;
+ GLuint i;
+
+ /* The bitmap cache is immune to pixel unpack changes.
+ * Note that GLUT makes several calls to glPixelStore for each
+ * bitmap char it draws so this is an important check.
+ */
+ if (state->mesa & ~_NEW_PACKUNPACK)
+ st_flush_bitmap_cache(st);
+
+ check_program_state( st );
+
+ if (state->st == 0)
+ return;
+
+// _mesa_printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);
+
+ if (1) {
+ /* Debug version which enforces various sanity checks on the
+ * state flags which are generated and checked to help ensure
+ * state atoms are ordered correctly in the list.
+ */
+ struct st_state_flags examined, prev;
+ memset(&examined, 0, sizeof(examined));
+ prev = *state;
+
+ for (i = 0; i < Elements(atoms); i++) {
+ const struct st_tracked_state *atom = atoms[i];
+ struct st_state_flags generated;
+
+// _mesa_printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st);
+
+ if (!(atom->dirty.mesa || atom->dirty.st) ||
+ !atom->update) {
+ _mesa_printf("malformed atom %s\n", atom->name);
+ assert(0);
+ }
+
+ if (check_state(state, &atom->dirty)) {
+ atoms[i]->update( st );
+// _mesa_printf("after: %x\n", atom->dirty.mesa);
+ }
+
+ accumulate_state(&examined, &atom->dirty);
+
+ /* generated = (prev ^ state)
+ * if (examined & generated)
+ * fail;
+ */
+ xor_states(&generated, &prev, state);
+ assert(!check_state(&examined, &generated));
+ prev = *state;
+ }
+// _mesa_printf("\n");
+
+ }
+ else {
+ for (i = 0; i < Elements(atoms); i++) {
+ if (check_state(state, &atoms[i]->dirty))
+ atoms[i]->update( st );
+ }
+ }
+
+ memset(state, 0, sizeof(*state));
+}
+
+
+
diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h
new file mode 100644
index 0000000000..c7cffd85c8
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef ST_ATOM_H
+#define ST_ATOM_H
+
+struct st_context;
+struct st_tracked_state;
+
+void st_init_atoms( struct st_context *st );
+void st_destroy_atoms( struct st_context *st );
+
+
+void st_validate_state( struct st_context *st );
+
+
+extern const struct st_tracked_state st_update_framebuffer;
+extern const struct st_tracked_state st_update_clip;
+extern const struct st_tracked_state st_update_depth_stencil_alpha;
+extern const struct st_tracked_state st_update_shader;
+extern const struct st_tracked_state st_update_rasterizer;
+extern const struct st_tracked_state st_update_polygon_stipple;
+extern const struct st_tracked_state st_update_viewport;
+extern const struct st_tracked_state st_update_scissor;
+extern const struct st_tracked_state st_update_blend;
+extern const struct st_tracked_state st_update_sampler;
+extern const struct st_tracked_state st_update_texture;
+extern const struct st_tracked_state st_finalize_textures;
+extern const struct st_tracked_state st_update_fs_constants;
+extern const struct st_tracked_state st_update_vs_constants;
+extern const struct st_tracked_state st_update_pixel_transfer;
+
+
+uint st_compare_func_to_pipe(GLenum func);
+
+#endif
diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c
new file mode 100644
index 0000000000..35c09c3e08
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_blend.c
@@ -0,0 +1,232 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+
+#include "st_context.h"
+#include "st_atom.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "cso_cache/cso_context.h"
+
+#include "main/macros.h"
+
+/**
+ * Convert GLenum blend tokens to pipe tokens.
+ * Both blend factors and blend funcs are accepted.
+ */
+static GLuint
+translate_blend(GLenum blend)
+{
+ switch (blend) {
+ /* blend functions */
+ case GL_FUNC_ADD:
+ return PIPE_BLEND_ADD;
+ case GL_FUNC_SUBTRACT:
+ return PIPE_BLEND_SUBTRACT;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ return PIPE_BLEND_REVERSE_SUBTRACT;
+ case GL_MIN:
+ return PIPE_BLEND_MIN;
+ case GL_MAX:
+ return PIPE_BLEND_MAX;
+
+ /* blend factors */
+ case GL_ONE:
+ return PIPE_BLENDFACTOR_ONE;
+ case GL_SRC_COLOR:
+ return PIPE_BLENDFACTOR_SRC_COLOR;
+ case GL_SRC_ALPHA:
+ return PIPE_BLENDFACTOR_SRC_ALPHA;
+ case GL_DST_ALPHA:
+ return PIPE_BLENDFACTOR_DST_ALPHA;
+ case GL_DST_COLOR:
+ return PIPE_BLENDFACTOR_DST_COLOR;
+ case GL_SRC_ALPHA_SATURATE:
+ return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
+ case GL_CONSTANT_COLOR:
+ return PIPE_BLENDFACTOR_CONST_COLOR;
+ case GL_CONSTANT_ALPHA:
+ return PIPE_BLENDFACTOR_CONST_ALPHA;
+ /*
+ return PIPE_BLENDFACTOR_SRC1_COLOR;
+ return PIPE_BLENDFACTOR_SRC1_ALPHA;
+ */
+ case GL_ZERO:
+ return PIPE_BLENDFACTOR_ZERO;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return PIPE_BLENDFACTOR_INV_SRC_COLOR;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ case GL_ONE_MINUS_DST_COLOR:
+ return PIPE_BLENDFACTOR_INV_DST_COLOR;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return PIPE_BLENDFACTOR_INV_DST_ALPHA;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ return PIPE_BLENDFACTOR_INV_CONST_COLOR;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
+ /*
+ return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
+ return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
+ */
+ default:
+ assert("invalid GL token in translate_blend()" == NULL);
+ return 0;
+ }
+}
+
+
+/**
+ * Convert GLenum logicop tokens to pipe tokens.
+ */
+static GLuint
+translate_logicop(GLenum logicop)
+{
+ switch (logicop) {
+ case GL_CLEAR:
+ return PIPE_LOGICOP_CLEAR;
+ case GL_NOR:
+ return PIPE_LOGICOP_NOR;
+ case GL_AND_INVERTED:
+ return PIPE_LOGICOP_AND_INVERTED;
+ case GL_COPY_INVERTED:
+ return PIPE_LOGICOP_COPY_INVERTED;
+ case GL_AND_REVERSE:
+ return PIPE_LOGICOP_AND_REVERSE;
+ case GL_INVERT:
+ return PIPE_LOGICOP_INVERT;
+ case GL_XOR:
+ return PIPE_LOGICOP_XOR;
+ case GL_NAND:
+ return PIPE_LOGICOP_NAND;
+ case GL_AND:
+ return PIPE_LOGICOP_AND;
+ case GL_EQUIV:
+ return PIPE_LOGICOP_EQUIV;
+ case GL_NOOP:
+ return PIPE_LOGICOP_NOOP;
+ case GL_OR_INVERTED:
+ return PIPE_LOGICOP_OR_INVERTED;
+ case GL_COPY:
+ return PIPE_LOGICOP_COPY;
+ case GL_OR_REVERSE:
+ return PIPE_LOGICOP_OR_REVERSE;
+ case GL_OR:
+ return PIPE_LOGICOP_OR;
+ case GL_SET:
+ return PIPE_LOGICOP_SET;
+ default:
+ assert("invalid GL token in translate_logicop()" == NULL);
+ return 0;
+ }
+}
+
+
+static void
+update_blend( struct st_context *st )
+{
+ struct pipe_blend_state *blend = &st->state.blend;
+
+ memset(blend, 0, sizeof(*blend));
+
+ if (st->ctx->Color.ColorLogicOpEnabled ||
+ (st->ctx->Color.BlendEnabled &&
+ st->ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) {
+ /* logicop enabled */
+ blend->logicop_enable = 1;
+ blend->logicop_func = translate_logicop(st->ctx->Color.LogicOp);
+ }
+ else if (st->ctx->Color.BlendEnabled) {
+ /* blending enabled */
+ blend->blend_enable = 1;
+
+ blend->rgb_func = translate_blend(st->ctx->Color.BlendEquationRGB);
+ if (st->ctx->Color.BlendEquationRGB == GL_MIN ||
+ st->ctx->Color.BlendEquationRGB == GL_MAX) {
+ /* Min/max are special */
+ blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+ }
+ else {
+ blend->rgb_src_factor = translate_blend(st->ctx->Color.BlendSrcRGB);
+ blend->rgb_dst_factor = translate_blend(st->ctx->Color.BlendDstRGB);
+ }
+
+ blend->alpha_func = translate_blend(st->ctx->Color.BlendEquationA);
+ if (st->ctx->Color.BlendEquationA == GL_MIN ||
+ st->ctx->Color.BlendEquationA == GL_MAX) {
+ /* Min/max are special */
+ blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend->alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+ }
+ else {
+ blend->alpha_src_factor = translate_blend(st->ctx->Color.BlendSrcA);
+ blend->alpha_dst_factor = translate_blend(st->ctx->Color.BlendDstA);
+ }
+ }
+ else {
+ /* no blending / logicop */
+ }
+
+ /* Colormask - maybe reverse these bits? */
+ if (st->ctx->Color.ColorMask[0])
+ blend->colormask |= PIPE_MASK_R;
+ if (st->ctx->Color.ColorMask[1])
+ blend->colormask |= PIPE_MASK_G;
+ if (st->ctx->Color.ColorMask[2])
+ blend->colormask |= PIPE_MASK_B;
+ if (st->ctx->Color.ColorMask[3])
+ blend->colormask |= PIPE_MASK_A;
+
+ if (st->ctx->Color.DitherFlag)
+ blend->dither = 1;
+
+ cso_set_blend(st->cso_context, blend);
+
+ {
+ struct pipe_blend_color bc;
+ COPY_4FV(bc.color, st->ctx->Color.BlendColor);
+ cso_set_blend_color(st->cso_context, &bc);
+ }
+}
+
+
+const struct st_tracked_state st_update_blend = {
+ "st_update_blend", /* name */
+ { /* dirty */
+ (_NEW_COLOR), /* XXX _NEW_BLEND someday? */ /* mesa */
+ 0, /* st */
+ },
+ update_blend, /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_clip.c b/src/mesa/state_tracker/st_atom_clip.c
new file mode 100644
index 0000000000..23d709b814
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_clip.c
@@ -0,0 +1,71 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+
+
+/* Second state atom for user clip planes:
+ */
+static void update_clip( struct st_context *st )
+{
+ struct pipe_clip_state clip;
+ GLuint i;
+
+ memset(&clip, 0, sizeof(clip));
+
+ for (i = 0; i < PIPE_MAX_CLIP_PLANES; i++) {
+ if (st->ctx->Transform.ClipPlanesEnabled & (1 << i)) {
+ memcpy(clip.ucp[clip.nr],
+ st->ctx->Transform._ClipUserPlane[i],
+ sizeof(clip.ucp[0]));
+ clip.nr++;
+ }
+ }
+
+ if (memcmp(&clip, &st->state.clip, sizeof(clip)) != 0) {
+ st->state.clip = clip;
+ st->pipe->set_clip_state(st->pipe, &clip);
+ }
+}
+
+
+const struct st_tracked_state st_update_clip = {
+ "st_update_clip", /* name */
+ { /* dirty */
+ (_NEW_TRANSFORM), /* mesa */
+ 0, /* st */
+ },
+ update_clip /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
new file mode 100644
index 0000000000..5d4d8eee02
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_constbuf.c
@@ -0,0 +1,142 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_atom_constbuf.h"
+#include "st_program.h"
+#include "st_inlines.h"
+
+
+/**
+ * Pass the given program parameters to the graphics pipe as a
+ * constant buffer.
+ * \param shader_type either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT
+ */
+void st_upload_constants( struct st_context *st,
+ struct gl_program_parameter_list *params,
+ unsigned shader_type)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_constant_buffer *cbuf = &st->state.constants[shader_type];
+
+ assert(shader_type == PIPE_SHADER_VERTEX ||
+ shader_type == PIPE_SHADER_FRAGMENT);
+
+ /* update constants */
+ if (params && params->NumParameters) {
+ const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4;
+
+ _mesa_load_state_parameters(st->ctx, params);
+
+ /* We always need to get a new buffer, to keep the drivers simple and
+ * avoid gratuitous rendering synchronization.
+ */
+ pipe_buffer_reference(&cbuf->buffer, NULL );
+ cbuf->buffer = pipe_buffer_create(pipe->screen, 16,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ paramBytes );
+
+ if (0) {
+ debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n",
+ __FUNCTION__, shader_type, params->NumParameters,
+ params->StateFlags);
+ _mesa_print_parameter_list(params);
+ }
+
+ /* load Mesa constants into the constant buffer */
+ if (cbuf->buffer)
+ st_no_flush_pipe_buffer_write(st, cbuf->buffer,
+ 0, paramBytes,
+ params->ParameterValues);
+
+ st->pipe->set_constant_buffer(st->pipe, shader_type, 0, cbuf);
+ }
+ else {
+ st->constants.tracked_state[shader_type].dirty.mesa = 0x0;
+ }
+}
+
+
+/**
+ * Vertex shader:
+ */
+static void update_vs_constants(struct st_context *st )
+{
+ struct st_vertex_program *vp = st->vp;
+ struct gl_program_parameter_list *params = vp->Base.Base.Parameters;
+
+ st_upload_constants( st, params, PIPE_SHADER_VERTEX );
+}
+
+
+const struct st_tracked_state st_update_vs_constants = {
+ "st_update_vs_constants", /* name */
+ { /* dirty */
+ (_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS), /* mesa */
+ ST_NEW_VERTEX_PROGRAM, /* st */
+ },
+ update_vs_constants /* update */
+};
+
+
+
+/**
+ * Fragment shader:
+ */
+static void update_fs_constants(struct st_context *st )
+{
+ struct st_fragment_program *fp = st->fp;
+ struct gl_program_parameter_list *params = fp->Base.Base.Parameters;
+
+ st_upload_constants( st, params, PIPE_SHADER_FRAGMENT );
+}
+
+
+const struct st_tracked_state st_update_fs_constants = {
+ "st_update_fs_constants", /* name */
+ { /* dirty */
+ (_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS), /* mesa */
+ ST_NEW_FRAGMENT_PROGRAM, /* st */
+ },
+ update_fs_constants /* update */
+};
+
diff --git a/src/mesa/state_tracker/st_atom_constbuf.h b/src/mesa/state_tracker/st_atom_constbuf.h
new file mode 100644
index 0000000000..f707534e2c
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_constbuf.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_ATOM_CONSTBUF_H
+#define ST_ATOM_CONSTBUF_H
+
+
+void st_upload_constants( struct st_context *st,
+ struct gl_program_parameter_list *params,
+ unsigned id);
+
+
+#endif /* ST_ATOM_CONSTBUF_H */
diff --git a/src/mesa/state_tracker/st_atom_depth.c b/src/mesa/state_tracker/st_atom_depth.c
new file mode 100644
index 0000000000..0aa128f947
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_depth.c
@@ -0,0 +1,155 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ * Zack Rusin
+ */
+
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Convert an OpenGL compare mode to a pipe tokens.
+ */
+GLuint
+st_compare_func_to_pipe(GLenum func)
+{
+ /* Same values, just biased */
+ assert(PIPE_FUNC_NEVER == GL_NEVER - GL_NEVER);
+ assert(PIPE_FUNC_LESS == GL_LESS - GL_NEVER);
+ assert(PIPE_FUNC_EQUAL == GL_EQUAL - GL_NEVER);
+ assert(PIPE_FUNC_LEQUAL == GL_LEQUAL - GL_NEVER);
+ assert(PIPE_FUNC_GREATER == GL_GREATER - GL_NEVER);
+ assert(PIPE_FUNC_NOTEQUAL == GL_NOTEQUAL - GL_NEVER);
+ assert(PIPE_FUNC_GEQUAL == GL_GEQUAL - GL_NEVER);
+ assert(PIPE_FUNC_ALWAYS == GL_ALWAYS - GL_NEVER);
+ assert(func >= GL_NEVER);
+ assert(func <= GL_ALWAYS);
+ return func - GL_NEVER;
+}
+
+
+/**
+ * Convert GLenum stencil op tokens to pipe tokens.
+ */
+static GLuint
+gl_stencil_op_to_pipe(GLenum func)
+{
+ switch (func) {
+ case GL_KEEP:
+ return PIPE_STENCIL_OP_KEEP;
+ case GL_ZERO:
+ return PIPE_STENCIL_OP_ZERO;
+ case GL_REPLACE:
+ return PIPE_STENCIL_OP_REPLACE;
+ case GL_INCR:
+ return PIPE_STENCIL_OP_INCR;
+ case GL_DECR:
+ return PIPE_STENCIL_OP_DECR;
+ case GL_INCR_WRAP:
+ return PIPE_STENCIL_OP_INCR_WRAP;
+ case GL_DECR_WRAP:
+ return PIPE_STENCIL_OP_DECR_WRAP;
+ case GL_INVERT:
+ return PIPE_STENCIL_OP_INVERT;
+ default:
+ assert("invalid GL token in gl_stencil_op_to_pipe()" == NULL);
+ return 0;
+ }
+}
+
+static void
+update_depth_stencil_alpha(struct st_context *st)
+{
+ struct pipe_depth_stencil_alpha_state *dsa = &st->state.depth_stencil;
+ GLcontext *ctx = st->ctx;
+
+ memset(dsa, 0, sizeof(*dsa));
+
+ if (ctx->Depth.Test && ctx->DrawBuffer->Visual.depthBits > 0) {
+ dsa->depth.enabled = 1;
+ dsa->depth.writemask = ctx->Depth.Mask;
+ dsa->depth.func = st_compare_func_to_pipe(ctx->Depth.Func);
+ }
+
+ if (ctx->Query.CurrentOcclusionObject &&
+ ctx->Query.CurrentOcclusionObject->Active)
+ dsa->depth.occlusion_count = 1;
+
+ if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
+ dsa->stencil[0].enabled = 1;
+ dsa->stencil[0].func = st_compare_func_to_pipe(ctx->Stencil.Function[0]);
+ dsa->stencil[0].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[0]);
+ dsa->stencil[0].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[0]);
+ dsa->stencil[0].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[0]);
+ dsa->stencil[0].ref_value = ctx->Stencil.Ref[0] & 0xff;
+ dsa->stencil[0].valuemask = ctx->Stencil.ValueMask[0] & 0xff;
+ dsa->stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
+
+ if (ctx->Stencil._TestTwoSide) {
+ const GLuint back = ctx->Stencil._BackFace;
+ dsa->stencil[1].enabled = 1;
+ dsa->stencil[1].func = st_compare_func_to_pipe(ctx->Stencil.Function[back]);
+ dsa->stencil[1].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[back]);
+ dsa->stencil[1].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[back]);
+ dsa->stencil[1].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[back]);
+ dsa->stencil[1].ref_value = ctx->Stencil.Ref[back] & 0xff;
+ dsa->stencil[1].valuemask = ctx->Stencil.ValueMask[back] & 0xff;
+ dsa->stencil[1].writemask = ctx->Stencil.WriteMask[back] & 0xff;
+ }
+ else {
+ dsa->stencil[1] = dsa->stencil[0];
+ dsa->stencil[1].enabled = 0;
+ }
+ }
+
+ if (ctx->Color.AlphaEnabled) {
+ dsa->alpha.enabled = 1;
+ dsa->alpha.func = st_compare_func_to_pipe(ctx->Color.AlphaFunc);
+ dsa->alpha.ref_value = ctx->Color.AlphaRef;
+ }
+
+ cso_set_depth_stencil_alpha(st->cso_context, dsa);
+}
+
+
+const struct st_tracked_state st_update_depth_stencil_alpha = {
+ "st_update_depth_stencil", /* name */
+ { /* dirty */
+ (_NEW_DEPTH|_NEW_STENCIL|_NEW_COLOR), /* mesa */
+ 0, /* st */
+ },
+ update_depth_stencil_alpha /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c
new file mode 100644
index 0000000000..5209a6a0c9
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -0,0 +1,184 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_fbo.h"
+#include "st_public.h"
+#include "st_texture.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "cso_cache/cso_context.h"
+
+
+
+/**
+ * When doing GL render to texture, we have to be sure that finalize_texture()
+ * didn't yank out the pipe_texture that we earlier created a surface for.
+ * Check for that here and create a new surface if needed.
+ */
+static void
+update_renderbuffer_surface(struct st_context *st,
+ struct st_renderbuffer *strb)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+ struct pipe_texture *texture = strb->rtt->pt;
+ int rtt_width = strb->Base.Width;
+ int rtt_height = strb->Base.Height;
+
+ if (!strb->surface ||
+ strb->surface->texture != texture ||
+ strb->surface->width != rtt_width ||
+ strb->surface->height != rtt_height) {
+ GLuint level;
+ /* find matching mipmap level size */
+ for (level = 0; level <= texture->last_level; level++) {
+ if (texture->width[level] == rtt_width &&
+ texture->height[level] == rtt_height) {
+
+ pipe_surface_reference(&strb->surface, NULL);
+
+ strb->surface = screen->get_tex_surface(screen,
+ texture,
+ strb->rtt_face,
+ level,
+ strb->rtt_slice,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+#if 0
+ printf("-- alloc new surface %d x %d into tex %p\n",
+ strb->surface->width, strb->surface->height,
+ texture);
+#endif
+ break;
+ }
+ }
+ }
+}
+
+
+/**
+ * Update framebuffer state (color, depth, stencil, etc. buffers)
+ */
+static void
+update_framebuffer_state( struct st_context *st )
+{
+ struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer;
+ struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ struct st_renderbuffer *strb;
+ GLuint i;
+
+ framebuffer->width = fb->Width;
+ framebuffer->height = fb->Height;
+
+ /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/
+
+ /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
+ * to determine which surfaces to draw to
+ */
+ framebuffer->nr_cbufs = 0;
+ for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);
+
+ if (strb) {
+ /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/
+ if (strb->rtt) {
+ /* rendering to a GL texture, may have to update surface */
+ update_renderbuffer_surface(st, strb);
+ }
+
+ if (strb->surface) {
+ pipe_surface_reference(&framebuffer->cbufs[framebuffer->nr_cbufs],
+ strb->surface);
+ framebuffer->nr_cbufs++;
+ }
+ strb->defined = GL_TRUE; /* we'll be drawing something */
+ }
+ }
+ for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&framebuffer->cbufs[i], NULL);
+ }
+
+ /*
+ * Depth/Stencil renderbuffer/surface.
+ */
+ strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
+ if (strb) {
+ strb = st_renderbuffer(strb->Base.Wrapped);
+ if (strb->rtt) {
+ /* rendering to a GL texture, may have to update surface */
+ update_renderbuffer_surface(st, strb);
+ }
+ pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
+ }
+ else {
+ strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
+ if (strb) {
+ strb = st_renderbuffer(strb->Base.Wrapped);
+ assert(strb->surface);
+ pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
+ }
+ else
+ pipe_surface_reference(&framebuffer->zsbuf, NULL);
+ }
+
+ cso_set_framebuffer(st->cso_context, framebuffer);
+
+ if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
+ if (st->frontbuffer_status == FRONT_STATUS_COPY_OF_BACK) {
+ /* copy back color buffer to front color buffer */
+ struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
+ struct pipe_surface *surf_front, *surf_back;
+ (void) st_get_framebuffer_surface(stfb, ST_SURFACE_FRONT_LEFT, &surf_front);
+ (void) st_get_framebuffer_surface(stfb, ST_SURFACE_BACK_LEFT, &surf_back);
+
+ st->pipe->surface_copy(st->pipe,
+ surf_front, 0, 0, /* dest */
+ surf_back, 0, 0, /* src */
+ fb->Width, fb->Height);
+ }
+ /* we're assuming we'll really draw to the front buffer */
+ st->frontbuffer_status = FRONT_STATUS_DIRTY;
+ }
+}
+
+
+const struct st_tracked_state st_update_framebuffer = {
+ "st_update_framebuffer", /* name */
+ { /* dirty */
+ _NEW_BUFFERS, /* mesa */
+ ST_NEW_FRAMEBUFFER, /* st */
+ },
+ update_framebuffer_state /* update */
+};
+
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
new file mode 100644
index 0000000000..eff3666ca8
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -0,0 +1,473 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Generate fragment programs to implement pixel transfer ops, such as
+ * scale/bias, colormatrix, colortable, convolution...
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_format.h"
+#include "st_program.h"
+#include "st_texture.h"
+#include "st_inlines.h"
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "util/u_pack_color.h"
+
+
+struct state_key
+{
+ GLuint scaleAndBias:1;
+ GLuint colorMatrix:1;
+ GLuint colorMatrixPostScaleBias:1;
+ GLuint pixelMaps:1;
+
+#if 0
+ GLfloat Maps[3][256][4];
+ int NumMaps;
+ GLint NumStages;
+ pipeline_stage Stages[STAGE_MAX];
+ GLboolean StagesUsed[STAGE_MAX];
+ GLfloat Scale1[4], Bias1[4];
+ GLfloat Scale2[4], Bias2[4];
+#endif
+};
+
+
+static GLboolean
+is_identity(const GLfloat m[16])
+{
+ GLuint i;
+ for (i = 0; i < 16; i++) {
+ const int row = i % 4, col = i / 4;
+ const float val = (GLfloat)(row == col);
+ if (m[i] != val)
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+
+static void
+make_state_key(GLcontext *ctx, struct state_key *key)
+{
+ static const GLfloat zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ static const GLfloat one[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+
+ memset(key, 0, sizeof(*key));
+
+ if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
+ ctx->Pixel.GreenBias != 0.0 || ctx->Pixel.GreenScale != 1.0 ||
+ ctx->Pixel.BlueBias != 0.0 || ctx->Pixel.BlueScale != 1.0 ||
+ ctx->Pixel.AlphaBias != 0.0 || ctx->Pixel.AlphaScale != 1.0) {
+ key->scaleAndBias = 1;
+ }
+
+ if (!is_identity(ctx->ColorMatrixStack.Top->m)) {
+ key->colorMatrix = 1;
+ }
+
+ if (!TEST_EQ_4V(ctx->Pixel.PostColorMatrixScale, one) ||
+ !TEST_EQ_4V(ctx->Pixel.PostColorMatrixBias, zero)) {
+ key->colorMatrixPostScaleBias = 1;
+ }
+
+ key->pixelMaps = ctx->Pixel.MapColorFlag;
+}
+
+
+static struct pipe_texture *
+create_color_map_texture(GLcontext *ctx)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_texture *pt;
+ enum pipe_format format;
+ const uint texSize = 256; /* simple, and usually perfect */
+
+ /* find an RGBA texture format */
+ format = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER);
+
+ /* create texture for color map/table */
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0,
+ texSize, texSize, 1, PIPE_TEXTURE_USAGE_SAMPLER);
+ return pt;
+}
+
+
+/**
+ * Update the pixelmap texture with the contents of the R/G/B/A pixel maps.
+ */
+static void
+load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_transfer *transfer;
+ const GLuint rSize = ctx->PixelMaps.RtoR.Size;
+ const GLuint gSize = ctx->PixelMaps.GtoG.Size;
+ const GLuint bSize = ctx->PixelMaps.BtoB.Size;
+ const GLuint aSize = ctx->PixelMaps.AtoA.Size;
+ const uint texSize = pt->width[0];
+ uint *dest;
+ uint i, j;
+
+ transfer = st_cond_flush_get_tex_transfer(st_context(ctx),
+ pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
+ 0, 0, texSize, texSize);
+ dest = (uint *) screen->transfer_map(screen, transfer);
+
+ /* Pack four 1D maps into a 2D texture:
+ * R map is placed horizontally, indexed by S, in channel 0
+ * G map is placed vertically, indexed by T, in channel 1
+ * B map is placed horizontally, indexed by S, in channel 2
+ * A map is placed vertically, indexed by T, in channel 3
+ */
+ for (i = 0; i < texSize; i++) {
+ for (j = 0; j < texSize; j++) {
+ int k = (i * texSize + j);
+ ubyte r = ctx->PixelMaps.RtoR.Map8[j * rSize / texSize];
+ ubyte g = ctx->PixelMaps.GtoG.Map8[i * gSize / texSize];
+ ubyte b = ctx->PixelMaps.BtoB.Map8[j * bSize / texSize];
+ ubyte a = ctx->PixelMaps.AtoA.Map8[i * aSize / texSize];
+ util_pack_color_ub(r, g, b, a, pt->format, dest + k);
+ }
+ }
+
+ screen->transfer_unmap(screen, transfer);
+ screen->tex_transfer_destroy(transfer);
+}
+
+
+
+#define MAX_INST 100
+
+/**
+ * Returns a fragment program which implements the current pixel transfer ops.
+ */
+static struct gl_fragment_program *
+get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
+{
+ struct st_context *st = ctx->st;
+ struct prog_instruction inst[MAX_INST];
+ struct gl_program_parameter_list *params;
+ struct gl_fragment_program *fp;
+ GLuint ic = 0;
+ const GLuint colorTemp = 0;
+
+ fp = (struct gl_fragment_program *)
+ ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ if (!fp)
+ return NULL;
+
+ params = _mesa_new_parameter_list();
+
+ /*
+ * Get initial pixel color from the texture.
+ * TEX colorTemp, fragment.texcoord[0], texture[0], 2D;
+ */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_TEX;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_INPUT;
+ inst[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
+ inst[ic].TexSrcUnit = 0;
+ inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+ fp->Base.InputsRead = (1 << FRAG_ATTRIB_TEX0);
+ fp->Base.OutputsWritten = (1 << FRAG_RESULT_COLOR);
+ fp->Base.SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
+
+ if (key->scaleAndBias) {
+ static const gl_state_index scale_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
+ static const gl_state_index bias_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
+ GLfloat scale[4], bias[4];
+ GLint scale_p, bias_p;
+
+ scale[0] = ctx->Pixel.RedScale;
+ scale[1] = ctx->Pixel.GreenScale;
+ scale[2] = ctx->Pixel.BlueScale;
+ scale[3] = ctx->Pixel.AlphaScale;
+ bias[0] = ctx->Pixel.RedBias;
+ bias[1] = ctx->Pixel.GreenBias;
+ bias[2] = ctx->Pixel.BlueBias;
+ bias[3] = ctx->Pixel.AlphaBias;
+
+ scale_p = _mesa_add_state_reference(params, scale_state);
+ bias_p = _mesa_add_state_reference(params, bias_state);
+
+ /* MAD colorTemp, colorTemp, scale, bias; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MAD;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = scale_p;
+ inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[2].Index = bias_p;
+ ic++;
+ }
+
+ if (key->pixelMaps) {
+ const GLuint temp = 1;
+
+ /* create the colormap/texture now if not already done */
+ if (!st->pixel_xfer.pixelmap_texture) {
+ st->pixel_xfer.pixelmap_texture = create_color_map_texture(ctx);
+ }
+
+ /* with a little effort, we can do four pixel map look-ups with
+ * two TEX instructions:
+ */
+
+ /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_TEX;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_XY; /* write R,G */
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].TexSrcUnit = 1;
+ inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_TEX;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_ZW; /* write B,A */
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W,
+ SWIZZLE_Z, SWIZZLE_W);
+ inst[ic].TexSrcUnit = 1;
+ inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* MOV colorTemp, temp; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MOV;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = temp;
+ ic++;
+
+ fp->Base.SamplersUsed |= (1 << 1); /* sampler 1 is used */
+ }
+
+ if (key->colorMatrix) {
+ static const gl_state_index row0_state[STATE_LENGTH] =
+ { STATE_COLOR_MATRIX, 0, 0, 0, 0 };
+ static const gl_state_index row1_state[STATE_LENGTH] =
+ { STATE_COLOR_MATRIX, 0, 1, 1, 0 };
+ static const gl_state_index row2_state[STATE_LENGTH] =
+ { STATE_COLOR_MATRIX, 0, 2, 2, 0 };
+ static const gl_state_index row3_state[STATE_LENGTH] =
+ { STATE_COLOR_MATRIX, 0, 3, 3, 0 };
+
+ GLint row0_p = _mesa_add_state_reference(params, row0_state);
+ GLint row1_p = _mesa_add_state_reference(params, row1_state);
+ GLint row2_p = _mesa_add_state_reference(params, row2_state);
+ GLint row3_p = _mesa_add_state_reference(params, row3_state);
+ const GLuint temp = 1;
+
+ /* DP4 temp.x, colorTemp, matrow0; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_DP4;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_X;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = row0_p;
+ ic++;
+
+ /* DP4 temp.y, colorTemp, matrow1; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_DP4;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_Y;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = row1_p;
+ ic++;
+
+ /* DP4 temp.z, colorTemp, matrow2; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_DP4;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_Z;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = row2_p;
+ ic++;
+
+ /* DP4 temp.w, colorTemp, matrow3; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_DP4;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_W;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = row3_p;
+ ic++;
+
+ /* MOV colorTemp, temp; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MOV;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = temp;
+ ic++;
+ }
+
+ if (key->colorMatrixPostScaleBias) {
+ static const gl_state_index scale_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
+ static const gl_state_index bias_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
+ GLint scale_param, bias_param;
+
+ scale_param = _mesa_add_state_reference(params, scale_state);
+ bias_param = _mesa_add_state_reference(params, bias_state);
+
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MAD;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = scale_param;
+ inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[2].Index = bias_param;
+ ic++;
+ }
+
+ /* Modify last instruction's dst reg to write to result.color */
+ {
+ struct prog_instruction *last = &inst[ic - 1];
+ last->DstReg.File = PROGRAM_OUTPUT;
+ last->DstReg.Index = FRAG_RESULT_COLOR;
+ }
+
+ /* END; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_END;
+ ic++;
+
+ assert(ic <= MAX_INST);
+
+
+ fp->Base.Instructions = _mesa_alloc_instructions(ic);
+ if (!fp->Base.Instructions) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "generating pixel transfer program");
+ return NULL;
+ }
+
+ _mesa_copy_instructions(fp->Base.Instructions, inst, ic);
+ fp->Base.NumInstructions = ic;
+ fp->Base.Parameters = params;
+
+#if 0
+ printf("========= pixel transfer prog\n");
+ _mesa_print_program(&fp->Base);
+ _mesa_print_parameter_list(fp->Base.Parameters);
+#endif
+
+ return fp;
+}
+
+
+
+/**
+ * Update st->pixel_xfer.program in response to new pixel-transfer state.
+ */
+static void
+update_pixel_transfer(struct st_context *st)
+{
+ GLcontext *ctx = st->ctx;
+ struct state_key key;
+ struct gl_fragment_program *fp;
+
+ make_state_key(st->ctx, &key);
+
+ fp = (struct gl_fragment_program *)
+ _mesa_search_program_cache(st->pixel_xfer.cache, &key, sizeof(key));
+ if (!fp) {
+ fp = get_pixel_transfer_program(st->ctx, &key);
+ _mesa_program_cache_insert(st->ctx, st->pixel_xfer.cache,
+ &key, sizeof(key), &fp->Base);
+ }
+
+ if (ctx->Pixel.MapColorFlag) {
+ load_color_map_texture(ctx, st->pixel_xfer.pixelmap_texture);
+ }
+ st->pixel_xfer.pixelmap_enabled = ctx->Pixel.MapColorFlag;
+
+ st->pixel_xfer.program = (struct st_fragment_program *) fp;
+}
+
+
+
+const struct st_tracked_state st_update_pixel_transfer = {
+ "st_update_pixel_transfer", /* name */
+ { /* dirty */
+ _NEW_PIXEL | _NEW_COLOR_MATRIX, /* mesa */
+ 0, /* st */
+ },
+ update_pixel_transfer /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c
new file mode 100644
index 0000000000..36b28cb4df
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_rasterizer.c
@@ -0,0 +1,276 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/macros.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "cso_cache/cso_context.h"
+
+
+static GLuint translate_fill( GLenum mode )
+{
+ switch (mode) {
+ case GL_POINT:
+ return PIPE_POLYGON_MODE_POINT;
+ case GL_LINE:
+ return PIPE_POLYGON_MODE_LINE;
+ case GL_FILL:
+ return PIPE_POLYGON_MODE_FILL;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static GLboolean get_offset_flag( GLuint fill_mode,
+ const struct gl_polygon_attrib *p )
+{
+ switch (fill_mode) {
+ case PIPE_POLYGON_MODE_POINT:
+ return p->OffsetPoint;
+ case PIPE_POLYGON_MODE_LINE:
+ return p->OffsetLine;
+ case PIPE_POLYGON_MODE_FILL:
+ return p->OffsetFill;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+static void update_raster_state( struct st_context *st )
+{
+ GLcontext *ctx = st->ctx;
+ struct pipe_rasterizer_state *raster = &st->state.rasterizer;
+ const struct gl_vertex_program *vertProg = ctx->VertexProgram._Current;
+ uint i;
+
+ memset(raster, 0, sizeof(*raster));
+
+ /* _NEW_POLYGON, _NEW_BUFFERS
+ */
+ {
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ raster->front_winding = PIPE_WINDING_CCW;
+ else
+ raster->front_winding = PIPE_WINDING_CW;
+
+ /* 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...
+ */
+ if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0)
+ raster->front_winding ^= PIPE_WINDING_BOTH;
+ }
+
+ /* _NEW_LIGHT
+ */
+ if (ctx->Light.ShadeModel == GL_FLAT)
+ raster->flatshade = 1;
+
+ if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION_EXT)
+ raster->flatshade_first = 1;
+
+ /* _NEW_LIGHT | _NEW_PROGRAM
+ *
+ * Back-face colors can come from traditional lighting (when
+ * GL_LIGHT_MODEL_TWO_SIDE is set) or from vertex programs/shaders (when
+ * GL_VERTEX_PROGRAM_TWO_SIDE is set). Note the logic here.
+ */
+ if (ctx->VertexProgram._Current) {
+ if (ctx->VertexProgram._Enabled ||
+ (ctx->Shader.CurrentProgram &&
+ ctx->Shader.CurrentProgram->VertexProgram &&
+ ctx->Shader.CurrentProgram->LinkStatus)) {
+ /* user-defined vertex program or shader */
+ raster->light_twoside = ctx->VertexProgram.TwoSideEnabled;
+ }
+ else {
+ /* TNL-generated program */
+ raster->light_twoside = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
+ }
+ }
+ else if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
+ raster->light_twoside = 1;
+ }
+
+ /* _NEW_POLYGON
+ */
+ if (ctx->Polygon.CullFlag) {
+ if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
+ raster->cull_mode = PIPE_WINDING_BOTH;
+ }
+ else if (ctx->Polygon.CullFaceMode == GL_FRONT) {
+ raster->cull_mode = raster->front_winding;
+ }
+ else {
+ raster->cull_mode = raster->front_winding ^ PIPE_WINDING_BOTH;
+ }
+ }
+
+ /* _NEW_POLYGON
+ */
+ {
+ GLuint fill_front = translate_fill( ctx->Polygon.FrontMode );
+ GLuint fill_back = translate_fill( ctx->Polygon.BackMode );
+
+ if (raster->front_winding == PIPE_WINDING_CW) {
+ raster->fill_cw = fill_front;
+ raster->fill_ccw = fill_back;
+ }
+ else {
+ raster->fill_cw = fill_back;
+ raster->fill_ccw = fill_front;
+ }
+
+ /* Simplify when culling is active:
+ */
+ if (raster->cull_mode & PIPE_WINDING_CW) {
+ raster->fill_cw = raster->fill_ccw;
+ }
+
+ if (raster->cull_mode & PIPE_WINDING_CCW) {
+ raster->fill_ccw = raster->fill_cw;
+ }
+ }
+
+ /* _NEW_POLYGON
+ */
+ if (ctx->Polygon.OffsetUnits != 0.0 ||
+ ctx->Polygon.OffsetFactor != 0.0) {
+ raster->offset_cw = get_offset_flag( raster->fill_cw, &ctx->Polygon );
+ raster->offset_ccw = get_offset_flag( raster->fill_ccw, &ctx->Polygon );
+ raster->offset_units = ctx->Polygon.OffsetUnits;
+ raster->offset_scale = ctx->Polygon.OffsetFactor;
+ }
+
+ if (ctx->Polygon.SmoothFlag)
+ raster->poly_smooth = 1;
+
+ if (ctx->Polygon.StippleFlag)
+ raster->poly_stipple_enable = 1;
+
+ /* _NEW_POINT
+ */
+ raster->point_size = ctx->Point.Size;
+
+ raster->point_size_min = 0; /* temporary, will go away */
+ raster->point_size_max = 1000; /* temporary, will go away */
+
+ raster->point_smooth = ctx->Point.SmoothFlag;
+ raster->point_sprite = ctx->Point.PointSprite;
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
+ if (ctx->Point.CoordReplace[i]) {
+ if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^
+ (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM))
+ raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_UPPER_LEFT;
+ else
+ raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_LOWER_LEFT;
+ }
+ else {
+ raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_NONE;
+ }
+ }
+
+ /* ST_NEW_VERTEX_PROGRAM
+ */
+ if (vertProg) {
+ if (vertProg->Base.Id == 0) {
+ if (vertProg->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ)) {
+ /* generated program which emits point size */
+ raster->point_size_per_vertex = TRUE;
+ }
+ }
+ else if (ctx->VertexProgram.PointSizeEnabled) {
+ /* user-defined program and GL_VERTEX_PROGRAM_POINT_SIZE set */
+ raster->point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled;
+ }
+ }
+ if (!raster->point_size_per_vertex) {
+ /* clamp size now */
+ raster->point_size = CLAMP(ctx->Point.Size,
+ ctx->Point.MinSize,
+ ctx->Point.MaxSize);
+ }
+
+ /* _NEW_LINE
+ */
+ raster->line_smooth = ctx->Line.SmoothFlag;
+ if (ctx->Line.SmoothFlag) {
+ raster->line_width = CLAMP(ctx->Line.Width,
+ ctx->Const.MinLineWidthAA,
+ ctx->Const.MaxLineWidthAA);
+ }
+ else {
+ raster->line_width = CLAMP(ctx->Line.Width,
+ ctx->Const.MinLineWidth,
+ ctx->Const.MaxLineWidth);
+ }
+
+ raster->line_stipple_enable = ctx->Line.StippleFlag;
+ raster->line_stipple_pattern = ctx->Line.StipplePattern;
+ /* GL stipple factor is in [1,256], remap to [0, 255] here */
+ raster->line_stipple_factor = ctx->Line.StippleFactor - 1;
+
+ /* _NEW_MULTISAMPLE */
+ if (ctx->Multisample._Enabled || st->force_msaa)
+ raster->multisample = 1;
+
+ /* _NEW_SCISSOR */
+ if (ctx->Scissor.Enabled)
+ raster->scissor = 1;
+
+ raster->gl_rasterization_rules = 1;
+
+ cso_set_rasterizer(st->cso_context, raster);
+}
+
+const struct st_tracked_state st_update_rasterizer = {
+ "st_update_rasterizer", /* name */
+ {
+ (_NEW_BUFFERS |
+ _NEW_LIGHT |
+ _NEW_LINE |
+ _NEW_MULTISAMPLE |
+ _NEW_POINT |
+ _NEW_POLYGON |
+ _NEW_PROGRAM |
+ _NEW_SCISSOR), /* mesa state dependencies*/
+ ST_NEW_VERTEX_PROGRAM, /* state tracker dependencies */
+ },
+ update_raster_state /* update function */
+};
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
new file mode 100644
index 0000000000..50ce82811c
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -0,0 +1,250 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+
+#include "main/macros.h"
+
+#include "st_context.h"
+#include "st_cb_texture.h"
+#include "st_atom.h"
+#include "st_program.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Convert GLenum texcoord wrap tokens to pipe tokens.
+ */
+static GLuint
+gl_wrap_xlate(GLenum wrap)
+{
+ switch (wrap) {
+ case GL_REPEAT:
+ return PIPE_TEX_WRAP_REPEAT;
+ case GL_CLAMP:
+ return PIPE_TEX_WRAP_CLAMP;
+ case GL_CLAMP_TO_EDGE:
+ return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ case GL_CLAMP_TO_BORDER:
+ return PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ case GL_MIRRORED_REPEAT:
+ return PIPE_TEX_WRAP_MIRROR_REPEAT;
+ case GL_MIRROR_CLAMP_EXT:
+ return PIPE_TEX_WRAP_MIRROR_CLAMP;
+ case GL_MIRROR_CLAMP_TO_EDGE_EXT:
+ return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
+ case GL_MIRROR_CLAMP_TO_BORDER_EXT:
+ return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+static GLuint
+gl_filter_to_mip_filter(GLenum filter)
+{
+ switch (filter) {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ return PIPE_TEX_MIPFILTER_NONE;
+
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ return PIPE_TEX_MIPFILTER_NEAREST;
+
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return PIPE_TEX_MIPFILTER_LINEAR;
+
+ default:
+ assert(0);
+ return PIPE_TEX_MIPFILTER_NONE;
+ }
+}
+
+
+static GLuint
+gl_filter_to_img_filter(GLenum filter)
+{
+ switch (filter) {
+ case GL_NEAREST:
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ return PIPE_TEX_FILTER_NEAREST;
+
+ case GL_LINEAR:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return PIPE_TEX_FILTER_LINEAR;
+
+ default:
+ assert(0);
+ return PIPE_TEX_FILTER_NEAREST;
+ }
+}
+
+
+static void
+xlate_border_color(const GLfloat *colorIn, GLenum baseFormat, GLfloat *colorOut)
+{
+ switch (baseFormat) {
+ 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)
+{
+ struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
+ struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
+ fprog->Base.SamplersUsed);
+ GLuint su;
+
+ st->state.num_samplers = 0;
+
+ /* loop over sampler units (aka tex image units) */
+ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
+ struct pipe_sampler_state *sampler = st->state.samplers + su;
+
+ memset(sampler, 0, sizeof(*sampler));
+
+ if (samplersUsed & (1 << su)) {
+ struct gl_texture_object *texobj;
+ struct gl_texture_image *teximg;
+ GLuint texUnit;
+
+ if (fprog->Base.SamplersUsed & (1 << su))
+ texUnit = fprog->Base.SamplerUnits[su];
+ else
+ texUnit = vprog->Base.SamplerUnits[su];
+
+ texobj = st->ctx->Texture.Unit[texUnit]._Current;
+ if (!texobj) {
+ texobj = st_get_default_texture(st);
+ }
+
+ teximg = texobj->Image[0][texobj->BaseLevel];
+
+ sampler->wrap_s = gl_wrap_xlate(texobj->WrapS);
+ sampler->wrap_t = gl_wrap_xlate(texobj->WrapT);
+ sampler->wrap_r = gl_wrap_xlate(texobj->WrapR);
+
+ sampler->min_img_filter = gl_filter_to_img_filter(texobj->MinFilter);
+ sampler->min_mip_filter = gl_filter_to_mip_filter(texobj->MinFilter);
+ sampler->mag_img_filter = gl_filter_to_img_filter(texobj->MagFilter);
+
+ if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
+ sampler->normalized_coords = 1;
+
+ sampler->lod_bias = st->ctx->Texture.Unit[su].LodBias;
+ sampler->min_lod = MAX2(0.0f, texobj->MinLod);
+ sampler->max_lod = MIN2(texobj->MaxLevel - texobj->BaseLevel,
+ texobj->MaxLod);
+ if (sampler->max_lod < sampler->min_lod) {
+ /* The GL spec doesn't seem to specify what to do in this case.
+ * Swap the values.
+ */
+ float tmp = sampler->max_lod;
+ sampler->max_lod = sampler->min_lod;
+ sampler->min_lod = tmp;
+ assert(sampler->min_lod <= sampler->max_lod);
+ }
+
+ xlate_border_color(texobj->BorderColor,
+ teximg ? teximg->TexFormat->BaseFormat : GL_RGBA,
+ sampler->border_color);
+
+ sampler->max_anisotropy = texobj->MaxAnisotropy;
+ if (sampler->max_anisotropy > 1.0) {
+ sampler->min_img_filter = PIPE_TEX_FILTER_ANISO;
+ sampler->mag_img_filter = PIPE_TEX_FILTER_ANISO;
+ }
+
+ /* only care about ARB_shadow, not SGI shadow */
+ if (texobj->CompareMode == GL_COMPARE_R_TO_TEXTURE) {
+ sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
+ sampler->compare_func
+ = st_compare_func_to_pipe(texobj->CompareFunc);
+ }
+
+ st->state.num_samplers = su + 1;
+
+ /*printf("%s su=%u non-null\n", __FUNCTION__, su);*/
+ cso_single_sampler(st->cso_context, su, sampler);
+ }
+ else {
+ /*printf("%s su=%u null\n", __FUNCTION__, su);*/
+ cso_single_sampler(st->cso_context, su, NULL);
+ }
+ }
+
+ cso_single_sampler_done(st->cso_context);
+}
+
+
+const struct st_tracked_state st_update_sampler = {
+ "st_update_sampler", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ 0, /* st */
+ },
+ update_samplers /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_scissor.c b/src/mesa/state_tracker/st_atom_scissor.c
new file mode 100644
index 0000000000..3fd59e1945
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_scissor.c
@@ -0,0 +1,92 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+
+
+/**
+ * Scissor depends on the scissor box, and the framebuffer dimensions.
+ */
+static void
+update_scissor( struct st_context *st )
+{
+ struct pipe_scissor_state scissor;
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ GLint miny, maxy;
+
+ scissor.minx = 0;
+ scissor.miny = 0;
+ scissor.maxx = fb->Width;
+ scissor.maxy = fb->Height;
+
+ if (st->ctx->Scissor.Enabled) {
+ if ((GLuint)st->ctx->Scissor.X > scissor.minx)
+ scissor.minx = st->ctx->Scissor.X;
+ if ((GLuint)st->ctx->Scissor.Y > scissor.miny)
+ scissor.miny = st->ctx->Scissor.Y;
+
+ if ((GLuint)st->ctx->Scissor.X + st->ctx->Scissor.Width < scissor.maxx)
+ scissor.maxx = st->ctx->Scissor.X + st->ctx->Scissor.Width;
+ if ((GLuint)st->ctx->Scissor.Y + st->ctx->Scissor.Height < scissor.maxy)
+ scissor.maxy = st->ctx->Scissor.Y + st->ctx->Scissor.Height;
+
+ /* check for null space */
+ if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy)
+ scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0;
+ }
+
+ /* Now invert Y. Pipe drivers use the convention Y=0=top for surfaces
+ */
+ miny = fb->Height - scissor.maxy;
+ maxy = fb->Height - scissor.miny;
+ scissor.miny = miny;
+ scissor.maxy = maxy;
+
+ if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) {
+ /* state has changed */
+ st->state.scissor = scissor; /* struct copy */
+ st->pipe->set_scissor_state(st->pipe, &scissor); /* activate */
+ }
+}
+
+
+const struct st_tracked_state st_update_scissor = {
+ "st_update_scissor", /* name */
+ { /* dirty */
+ (_NEW_SCISSOR | _NEW_BUFFERS), /* mesa */
+ 0, /* st */
+ },
+ update_scissor /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
new file mode 100644
index 0000000000..ee649be885
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -0,0 +1,377 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * State validation for vertex/fragment shaders.
+ * Note that we have to delay most vertex/fragment shader translation
+ * until rendering time since the linkage between the vertex outputs and
+ * fragment inputs can vary depending on the pairing of shaders.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "shader/program.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_simple_shaders.h"
+
+#include "cso_cache/cso_context.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_program.h"
+#include "st_atom_shader.h"
+#include "st_mesa_to_tgsi.h"
+
+
+/**
+ * This represents a vertex program, especially translated to match
+ * the inputs of a particular fragment shader.
+ */
+struct translated_vertex_program
+{
+ struct st_vertex_program *master;
+
+ /** The fragment shader "signature" this vertex shader is meant for: */
+ GLbitfield frag_inputs;
+
+ /** Compared against master vertex program's serialNo: */
+ GLuint serialNo;
+
+ /** Maps VERT_RESULT_x to slot */
+ GLuint output_to_slot[VERT_RESULT_MAX];
+ ubyte output_to_semantic_name[VERT_RESULT_MAX];
+ ubyte output_to_semantic_index[VERT_RESULT_MAX];
+
+ /** Pointer to the translated vertex program */
+ struct st_vertex_program *vp;
+
+ struct translated_vertex_program *next; /**< next in linked list */
+};
+
+
+
+/**
+ * Given a vertex program output attribute, return the corresponding
+ * fragment program input attribute.
+ * \return -1 for vertex outputs that have no corresponding fragment input
+ */
+static GLint
+vp_out_to_fp_in(GLuint vertResult)
+{
+ if (vertResult >= VERT_RESULT_TEX0 &&
+ vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS)
+ return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0);
+
+ if (vertResult >= VERT_RESULT_VAR0 &&
+ vertResult < VERT_RESULT_VAR0 + MAX_VARYING)
+ return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0);
+
+ switch (vertResult) {
+ case VERT_RESULT_HPOS:
+ return FRAG_ATTRIB_WPOS;
+ case VERT_RESULT_COL0:
+ return FRAG_ATTRIB_COL0;
+ case VERT_RESULT_COL1:
+ return FRAG_ATTRIB_COL1;
+ case VERT_RESULT_FOGC:
+ return FRAG_ATTRIB_FOGC;
+ default:
+ /* Back-face colors, edge flags, etc */
+ return -1;
+ }
+}
+
+
+/**
+ * Find a translated vertex program that corresponds to stvp and
+ * has outputs matched to stfp's inputs.
+ * This performs vertex and fragment translation (to TGSI) when needed.
+ */
+static struct translated_vertex_program *
+find_translated_vp(struct st_context *st,
+ struct st_vertex_program *stvp,
+ struct st_fragment_program *stfp)
+{
+ static const GLuint UNUSED = ~0;
+ struct translated_vertex_program *xvp;
+ const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
+
+ /*
+ * Translate fragment program if needed.
+ */
+ if (!stfp->state.tokens) {
+ GLuint inAttr, numIn = 0;
+
+ for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
+ if (fragInputsRead & (1 << inAttr)) {
+ stfp->input_to_slot[inAttr] = numIn;
+ numIn++;
+ }
+ else {
+ stfp->input_to_slot[inAttr] = UNUSED;
+ }
+ }
+
+ stfp->num_input_slots = numIn;
+
+ assert(stfp->Base.Base.NumInstructions > 1);
+
+ st_translate_fragment_program(st, stfp, stfp->input_to_slot);
+ }
+
+
+ /* See if we've got a translated vertex program whose outputs match
+ * the fragment program's inputs.
+ * XXX This could be a hash lookup, using InputsRead as the key.
+ */
+ for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) {
+ if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
+ break;
+ }
+ }
+
+ /* No? Allocate translated vp object now */
+ if (!xvp) {
+ xvp = ST_CALLOC_STRUCT(translated_vertex_program);
+ xvp->frag_inputs = fragInputsRead;
+ xvp->master = stvp;
+
+ xvp->next = stfp->vertex_programs;
+ stfp->vertex_programs = xvp;
+ }
+
+ /* See if we need to translate vertex program to TGSI form */
+ if (xvp->serialNo != stvp->serialNo) {
+ GLuint outAttr;
+ const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
+ GLuint numVpOuts = 0;
+ GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
+ GLbitfield usedGenerics = 0x0;
+ GLbitfield usedOutputSlots = 0x0;
+
+ /* Compute mapping of vertex program outputs to slots, which depends
+ * on the fragment program's input->slot mapping.
+ */
+ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
+ /* set defaults: */
+ xvp->output_to_slot[outAttr] = UNUSED;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
+ xvp->output_to_semantic_index[outAttr] = 99;
+
+ if (outAttr == VERT_RESULT_HPOS) {
+ /* always put xformed position into slot zero */
+ GLuint slot = 0;
+ xvp->output_to_slot[VERT_RESULT_HPOS] = slot;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
+ xvp->output_to_semantic_index[outAttr] = 0;
+ numVpOuts++;
+ usedOutputSlots |= (1 << slot);
+ }
+ else if (outputsWritten & (1 << outAttr)) {
+ /* see if the frag prog wants this vert output */
+ GLint fpInAttrib = vp_out_to_fp_in(outAttr);
+ if (fpInAttrib >= 0) {
+ GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
+ if (fpInSlot != ~0) {
+ /* match this vp output to the fp input */
+ GLuint vpOutSlot = stfp->input_map[fpInSlot];
+ xvp->output_to_slot[outAttr] = vpOutSlot;
+ xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
+ xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
+ numVpOuts++;
+ usedOutputSlots |= (1 << vpOutSlot);
+ }
+ else {
+#if 0 /*debug*/
+ printf("VP output %d not used by FP\n", outAttr);
+#endif
+ }
+ }
+ else if (outAttr == VERT_RESULT_PSIZ)
+ emitPntSize = GL_TRUE;
+ else if (outAttr == VERT_RESULT_BFC0)
+ emitBFC0 = GL_TRUE;
+ else if (outAttr == VERT_RESULT_BFC1)
+ emitBFC1 = GL_TRUE;
+ }
+#if 0 /*debug*/
+ printf("assign vp output_to_slot[%d] = %d\n", outAttr,
+ xvp->output_to_slot[outAttr]);
+#endif
+ }
+
+ /* must do these last */
+ if (emitPntSize) {
+ GLuint slot = numVpOuts++;
+ xvp->output_to_slot[VERT_RESULT_PSIZ] = slot;
+ xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
+ xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
+ usedOutputSlots |= (1 << slot);
+ }
+ if (emitBFC0) {
+ GLuint slot = numVpOuts++;
+ xvp->output_to_slot[VERT_RESULT_BFC0] = slot;
+ xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
+ xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
+ usedOutputSlots |= (1 << slot);
+ }
+ if (emitBFC1) {
+ GLuint slot = numVpOuts++;
+ xvp->output_to_slot[VERT_RESULT_BFC1] = slot;
+ xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR;
+ xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1;
+ usedOutputSlots |= (1 << slot);
+ }
+
+ /* build usedGenerics mask */
+ usedGenerics = 0x0;
+ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
+ if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
+ usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]);
+ }
+ }
+
+ /* For each vertex program output that doesn't match up to a fragment
+ * program input, map the vertex program output to a free slot and
+ * free generic attribute.
+ */
+ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
+ if (outputsWritten & (1 << outAttr)) {
+ if (xvp->output_to_slot[outAttr] == UNUSED) {
+ GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1;
+ GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1;
+ usedGenerics |= (1 << freeGeneric);
+ usedOutputSlots |= (1 << freeSlot);
+ xvp->output_to_slot[outAttr] = freeSlot;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
+ xvp->output_to_semantic_index[outAttr] = freeGeneric;
+ }
+ }
+
+#if 0 /*debug*/
+ printf("vp output_to_slot[%d] = %d\n", outAttr,
+ xvp->output_to_slot[outAttr]);
+#endif
+ }
+
+ assert(stvp->Base.Base.NumInstructions > 1);
+
+ st_translate_vertex_program(st, stvp, xvp->output_to_slot,
+ xvp->output_to_semantic_name,
+ xvp->output_to_semantic_index);
+
+ xvp->vp = stvp;
+
+ /* translated VP is up to date now */
+ xvp->serialNo = stvp->serialNo;
+ }
+
+ return xvp;
+}
+
+
+void
+st_free_translated_vertex_programs(struct st_context *st,
+ struct translated_vertex_program *xvp)
+{
+ struct translated_vertex_program *next;
+
+ while (xvp) {
+ next = xvp->next;
+ _mesa_free(xvp);
+ xvp = next;
+ }
+}
+
+
+static void *
+get_passthrough_fs(struct st_context *st)
+{
+ if (!st->passthrough_fs) {
+ st->passthrough_fs =
+ util_make_fragment_passthrough_shader(st->pipe);
+ }
+
+ return st->passthrough_fs;
+}
+
+
+static void
+update_linkage( struct st_context *st )
+{
+ struct st_vertex_program *stvp;
+ struct st_fragment_program *stfp;
+ struct translated_vertex_program *xvp;
+
+ /* find active shader and params -- Should be covered by
+ * ST_NEW_VERTEX_PROGRAM
+ */
+ assert(st->ctx->VertexProgram._Current);
+ stvp = st_vertex_program(st->ctx->VertexProgram._Current);
+ assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
+
+ assert(st->ctx->FragmentProgram._Current);
+ stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
+ assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
+
+ xvp = find_translated_vp(st, stvp, stfp);
+
+ st_reference_vertprog(st, &st->vp, stvp);
+ st_reference_fragprog(st, &st->fp, stfp);
+
+ cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
+
+ if (st->missing_textures) {
+ /* use a pass-through frag shader that uses no textures */
+ void *fs = get_passthrough_fs(st);
+ cso_set_fragment_shader_handle(st->cso_context, fs);
+ }
+ else {
+ cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
+ }
+
+ st->vertex_result_to_slot = xvp->output_to_slot;
+}
+
+
+const struct st_tracked_state st_update_shader = {
+ "st_update_shader", /* name */
+ { /* dirty */
+ 0, /* mesa */
+ ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM /* st */
+ },
+ update_linkage /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_shader.h b/src/mesa/state_tracker/st_atom_shader.h
new file mode 100644
index 0000000000..8403bc66c9
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_shader.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_ATOM_SHADER_H
+#define ST_ATOM_SHADER_H
+
+
+extern void
+st_free_translated_vertex_programs(struct st_context *st,
+ struct translated_vertex_program *xvp);
+
+
+#endif /* ST_ATOM_SHADER_H */
diff --git a/src/mesa/state_tracker/st_atom_stipple.c b/src/mesa/state_tracker/st_atom_stipple.c
new file mode 100644
index 0000000000..31e124b329
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_stipple.c
@@ -0,0 +1,91 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * \brief polygon stipple state
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+
+/**
+ * OpenGL's polygon stipple is indexed with window coordinates in which
+ * the origin (0,0) is the lower-left corner of the window.
+ * With Gallium, the origin is the upper-left corner of the window.
+ * To convert GL's polygon stipple to what gallium expects we need to
+ * invert the pattern vertically and rotate the stipple rows according
+ * to the window height.
+ */
+static void
+invert_stipple(GLuint dest[32], const GLuint src[32], GLuint winHeight)
+{
+ GLuint i;
+
+ for (i = 0; i < 32; i++) {
+ dest[i] = src[(winHeight - 1 - i) & 0x1f];
+ }
+}
+
+
+
+static void
+update_stipple( struct st_context *st )
+{
+ const GLuint sz = sizeof(st->state.poly_stipple);
+ assert(sz == sizeof(st->ctx->PolygonStipple));
+
+ if (memcmp(st->state.poly_stipple, st->ctx->PolygonStipple, sz)) {
+ /* state has changed */
+ struct pipe_poly_stipple newStipple;
+
+ memcpy(st->state.poly_stipple, st->ctx->PolygonStipple, sz);
+
+ invert_stipple(newStipple.stipple, st->ctx->PolygonStipple,
+ st->ctx->DrawBuffer->Height);
+
+ st->pipe->set_polygon_stipple(st->pipe, &newStipple);
+ }
+}
+
+
+/** Update the stipple when the pattern or window height changes */
+const struct st_tracked_state st_update_polygon_stipple = {
+ "st_update_polygon_stipple", /* name */
+ { /* dirty */
+ (_NEW_POLYGONSTIPPLE |
+ _NEW_BUFFERS), /* mesa */
+ 0, /* st */
+ },
+ update_stipple /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
new file mode 100644
index 0000000000..4d4f97da7e
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -0,0 +1,161 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_texture.h"
+#include "st_cb_texture.h"
+#include "pipe/p_context.h"
+#include "cso_cache/cso_context.h"
+
+
+static void
+update_textures(struct st_context *st)
+{
+ struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
+ struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
+ fprog->Base.SamplersUsed);
+ GLuint su;
+
+ st->state.num_textures = 0;
+
+ /* loop over sampler units (aka tex image units) */
+ for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
+ struct pipe_texture *pt = NULL;
+
+ if (samplersUsed & (1 << su)) {
+ struct gl_texture_object *texObj;
+ struct st_texture_object *stObj;
+ GLboolean flush, retval;
+ GLuint texUnit;
+
+ if (fprog->Base.SamplersUsed & (1 << su))
+ texUnit = fprog->Base.SamplerUnits[su];
+ else
+ texUnit = vprog->Base.SamplerUnits[su];
+
+ texObj = st->ctx->Texture.Unit[texUnit]._Current;
+
+ if (!texObj) {
+ texObj = st_get_default_texture(st);
+ }
+ stObj = st_texture_object(texObj);
+
+ retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
+ if (!retval) {
+ /* out of mem */
+ continue;
+ }
+
+ st->state.num_textures = su + 1;
+
+ pt = st_get_stobj_texture(stObj);
+ }
+
+ /*
+ if (pt) {
+ printf("%s su=%u non-null\n", __FUNCTION__, su);
+ }
+ else {
+ printf("%s su=%u null\n", __FUNCTION__, su);
+ }
+ */
+
+ pipe_texture_reference(&st->state.sampler_texture[su], pt);
+ }
+
+ cso_set_sampler_textures(st->cso_context,
+ st->state.num_textures,
+ st->state.sampler_texture);
+}
+
+
+const struct st_tracked_state st_update_texture = {
+ "st_update_texture", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ ST_NEW_FRAGMENT_PROGRAM, /* st */
+ },
+ update_textures /* update */
+};
+
+
+
+
+static void
+finalize_textures(struct st_context *st)
+{
+ struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
+ const GLboolean prev_missing_textures = st->missing_textures;
+ GLuint su;
+
+ st->missing_textures = GL_FALSE;
+
+ for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) {
+ if (fprog->Base.SamplersUsed & (1 << su)) {
+ const GLuint texUnit = fprog->Base.SamplerUnits[su];
+ struct gl_texture_object *texObj
+ = st->ctx->Texture.Unit[texUnit]._Current;
+ struct st_texture_object *stObj = st_texture_object(texObj);
+
+ if (texObj) {
+ GLboolean flush, retval;
+
+ retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
+ if (!retval) {
+ /* out of mem */
+ st->missing_textures = GL_TRUE;
+ continue;
+ }
+
+ stObj->teximage_realloc = TRUE;
+ }
+ }
+ }
+
+ if (prev_missing_textures != st->missing_textures)
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+}
+
+
+
+const struct st_tracked_state st_finalize_textures = {
+ "st_finalize_textures", /* name */
+ { /* dirty */
+ _NEW_TEXTURE, /* mesa */
+ 0, /* st */
+ },
+ finalize_textures /* update */
+};
diff --git a/src/mesa/state_tracker/st_atom_viewport.c b/src/mesa/state_tracker/st_atom_viewport.c
new file mode 100644
index 0000000000..27ec2eb033
--- /dev/null
+++ b/src/mesa/state_tracker/st_atom_viewport.c
@@ -0,0 +1,91 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "main/context.h"
+#include "main/colormac.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "cso_cache/cso_context.h"
+
+/**
+ * Update the viewport transformation matrix. Depends on:
+ * - viewport pos/size
+ * - depthrange
+ * - window pos/size or FBO size
+ */
+static void
+update_viewport( struct st_context *st )
+{
+ GLcontext *ctx = st->ctx;
+ GLfloat yScale, yBias;
+
+ /* _NEW_BUFFERS
+ */
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ yScale = -1;
+ yBias = (GLfloat)ctx->DrawBuffer->Height;
+ }
+ else {
+ yScale = 1.0;
+ yBias = 0.0;
+ }
+
+ /* _NEW_VIEWPORT
+ */
+ {
+ GLfloat x = (GLfloat)ctx->Viewport.X;
+ GLfloat y = (GLfloat)ctx->Viewport.Y;
+ GLfloat z = ctx->Viewport.Near;
+ GLfloat half_width = (GLfloat)ctx->Viewport.Width / 2.0f;
+ GLfloat half_height = (GLfloat)ctx->Viewport.Height / 2.0f;
+ GLfloat half_depth = (GLfloat)(ctx->Viewport.Far - ctx->Viewport.Near) / 2.0f;
+
+ st->state.viewport.scale[0] = half_width;
+ st->state.viewport.scale[1] = half_height * yScale;
+ st->state.viewport.scale[2] = half_depth;
+ st->state.viewport.scale[3] = 1.0;
+
+ st->state.viewport.translate[0] = half_width + x;
+ st->state.viewport.translate[1] = (half_height + y) * yScale + yBias;
+ st->state.viewport.translate[2] = half_depth + z;
+ st->state.viewport.translate[3] = 0.0;
+
+ cso_set_viewport(st->cso_context, &st->state.viewport);
+ }
+}
+
+
+const struct st_tracked_state st_update_viewport = {
+ "st_update_viewport", /* name */
+ { /* dirty */
+ _NEW_BUFFERS | _NEW_VIEWPORT, /* mesa */
+ 0, /* st */
+ },
+ update_viewport /* update */
+};
diff --git a/src/mesa/state_tracker/st_cache.h b/src/mesa/state_tracker/st_cache.h
new file mode 100644
index 0000000000..b81de316ec
--- /dev/null
+++ b/src/mesa/state_tracker/st_cache.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Zack Rusin <zack@tungstengraphics.com>
+ */
+
+#ifndef ST_CACHE_H
+#define ST_CACHE_H
+
+#include "cso_cache/cso_cache.h"
+
+struct pipe_blend_state;
+struct pipe_sampler_state;
+struct st_context;
+
+
+const struct cso_blend *
+st_cached_blend_state(struct st_context *st,
+ const struct pipe_blend_state *blend);
+
+const struct cso_sampler *
+st_cached_sampler_state(struct st_context *st,
+ const struct pipe_sampler_state *sampler);
+
+const struct cso_depth_stencil_alpha *
+st_cached_depth_stencil_alpha_state(struct st_context *st,
+ const struct pipe_depth_stencil_alpha_state *depth_stencil);
+
+const struct cso_rasterizer *
+st_cached_rasterizer_state(struct st_context *st,
+ const struct pipe_rasterizer_state *raster);
+
+const struct cso_fragment_shader *
+st_cached_fs_state(struct st_context *st,
+ const struct pipe_shader_state *templ);
+
+
+const struct cso_vertex_shader *
+st_cached_vs_state(struct st_context *st,
+ const struct pipe_shader_state *templ);
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c
new file mode 100644
index 0000000000..95181578f6
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_accum.c
@@ -0,0 +1,333 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+
+#include "st_context.h"
+#include "st_cb_accum.h"
+#include "st_cb_fbo.h"
+#include "st_draw.h"
+#include "st_public.h"
+#include "st_format.h"
+#include "st_texture.h"
+#include "st_inlines.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+
+
+/**
+ * For hardware that supports deep color buffers, we could accelerate
+ * most/all the accum operations with blending/texturing.
+ * For now, just use the get/put_tile() functions and do things in software.
+ */
+
+
+void
+st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ struct st_renderbuffer *acc_strb = st_renderbuffer(rb);
+ const GLint xpos = ctx->DrawBuffer->_Xmin;
+ const GLint ypos = ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - xpos;
+ const GLint height = ctx->DrawBuffer->_Ymax - ypos;
+ size_t stride = acc_strb->stride;
+ GLubyte *data = acc_strb->data;
+
+ if(!data)
+ return;
+
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ GLshort r = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]);
+ GLshort g = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]);
+ GLshort b = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]);
+ GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]);
+ int i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *dst = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
+ for (j = 0; j < width; j++) {
+ dst[0] = r;
+ dst[1] = g;
+ dst[2] = b;
+ dst[3] = a;
+ dst += 4;
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()");
+ }
+}
+
+
+/** For ADD/MULT */
+static void
+accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias,
+ GLint xpos, GLint ypos, GLint width, GLint height,
+ struct st_renderbuffer *acc_strb)
+{
+ size_t stride = acc_strb->stride;
+ GLubyte *data = acc_strb->data;
+
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ int i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
+ for (j = 0; j < width * 4; j++) {
+ float val = SHORT_TO_FLOAT(*acc) * scale + bias;
+ *acc++ = FLOAT_TO_SHORT(val);
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
+ }
+}
+
+
+static void
+accum_accum(struct st_context *st, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height,
+ struct st_renderbuffer *acc_strb,
+ struct st_renderbuffer *color_strb)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_transfer *color_trans;
+ size_t stride = acc_strb->stride;
+ GLubyte *data = acc_strb->data;
+ GLfloat *buf;
+
+ color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, xpos, ypos,
+ width, height);
+
+ buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+
+ pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf);
+
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ const GLfloat *color = buf;
+ int i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
+ for (j = 0; j < width * 4; j++) {
+ float val = *color++ * value;
+ *acc++ += FLOAT_TO_SHORT(val);
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
+ }
+
+ _mesa_free(buf);
+ screen->tex_transfer_destroy(color_trans);
+}
+
+
+static void
+accum_load(struct st_context *st, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height,
+ struct st_renderbuffer *acc_strb,
+ struct st_renderbuffer *color_strb)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_transfer *color_trans;
+ size_t stride = acc_strb->stride;
+ GLubyte *data = acc_strb->data;
+ GLfloat *buf;
+
+ color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, xpos, ypos,
+ width, height);
+
+ buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+
+ pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf);
+
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ const GLfloat *color = buf;
+ int i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
+ for (j = 0; j < width * 4; j++) {
+ float val = *color++ * value;
+ *acc++ = FLOAT_TO_SHORT(val);
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
+ }
+
+ _mesa_free(buf);
+ screen->tex_transfer_destroy(color_trans);
+}
+
+
+static void
+accum_return(GLcontext *ctx, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height,
+ struct st_renderbuffer *acc_strb,
+ struct st_renderbuffer *color_strb)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const GLubyte *colormask = ctx->Color.ColorMask;
+ enum pipe_transfer_usage usage;
+ struct pipe_transfer *color_trans;
+ size_t stride = acc_strb->stride;
+ const GLubyte *data = acc_strb->data;
+ GLfloat *buf;
+
+ buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+
+ if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3])
+ usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ usage = PIPE_TRANSFER_WRITE;
+
+ color_trans = st_cond_flush_get_tex_transfer(st_context(ctx),
+ color_strb->texture, 0, 0, 0,
+ usage,
+ xpos, ypos,
+ width, height);
+
+ if (usage != PIPE_TRANSFER_WRITE)
+ pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf);
+
+ switch (acc_strb->format) {
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ {
+ GLfloat *color = buf;
+ int i, j, ch;
+ for (i = 0; i < height; i++) {
+ const GLshort *acc = (const GLshort *) (data + (ypos + i) * stride + xpos * 8);
+ for (j = 0; j < width; j++) {
+ for (ch = 0; ch < 4; ch++) {
+ if (colormask[ch]) {
+ GLfloat val = SHORT_TO_FLOAT(*acc * value);
+ *color = CLAMP(val, 0.0f, 1.0f);
+ }
+ else {
+ /* No change */
+ }
+ ++acc;
+ ++color;
+ }
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
+ }
+
+ pipe_put_tile_rgba(color_trans, 0, 0, width, height, buf);
+
+ _mesa_free(buf);
+ screen->tex_transfer_destroy(color_trans);
+}
+
+
+static void
+st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
+{
+ struct st_context *st = ctx->st;
+ struct st_renderbuffer *acc_strb
+ = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
+ struct st_renderbuffer *color_strb
+ = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
+
+ const GLint xpos = ctx->DrawBuffer->_Xmin;
+ const GLint ypos = ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - xpos;
+ const GLint height = ctx->DrawBuffer->_Ymax - ypos;
+
+ if(!acc_strb->data)
+ return;
+
+ /* make sure color bufs aren't cached */
+ st_flush( st, PIPE_FLUSH_RENDER_CACHE, NULL );
+
+ switch (op) {
+ case GL_ADD:
+ if (value != 0.0F) {
+ accum_mad(ctx, 1.0, value, xpos, ypos, width, height, acc_strb);
+ }
+ break;
+ case GL_MULT:
+ if (value != 1.0F) {
+ accum_mad(ctx, value, 0.0, xpos, ypos, width, height, acc_strb);
+ }
+ break;
+ case GL_ACCUM:
+ if (value != 0.0F) {
+ accum_accum(st, value, xpos, ypos, width, height, acc_strb, color_strb);
+ }
+ break;
+ case GL_LOAD:
+ accum_load(st, value, xpos, ypos, width, height, acc_strb, color_strb);
+ break;
+ case GL_RETURN:
+ accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+
+void st_init_accum_functions(struct dd_function_table *functions)
+{
+ functions->Accum = st_Accum;
+}
diff --git a/src/mesa/state_tracker/st_cb_accum.h b/src/mesa/state_tracker/st_cb_accum.h
new file mode 100644
index 0000000000..ed9b7dab94
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_accum.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_ACCUM_H
+#define ST_CB_ACCUM_H
+
+
+extern void
+st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb);
+
+extern void st_init_accum_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_ACCUM_H */
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
new file mode 100644
index 0000000000..902fb38d1a
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -0,0 +1,819 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/bufferobj.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_atom_constbuf.h"
+#include "st_program.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_program.h"
+#include "st_mesa_to_tgsi.h"
+#include "st_texture.h"
+#include "st_inlines.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+#include "util/u_draw_quad.h"
+#include "util/u_simple_shaders.h"
+#include "shader/prog_instruction.h"
+#include "cso_cache/cso_context.h"
+
+
+
+/**
+ * glBitmaps are drawn as textured quads. The user's bitmap pattern
+ * is stored in a texture image. An alpha8 texture format is used.
+ * The fragment shader samples a bit (texel) from the texture, then
+ * discards the fragment if the bit is off.
+ *
+ * Note that we actually store the inverse image of the bitmap to
+ * simplify the fragment program. An "on" bit gets stored as texel=0x0
+ * and an "off" bit is stored as texel=0xff. Then we kill the
+ * fragment if the negated texel value is less than zero.
+ */
+
+
+/**
+ * The bitmap cache attempts to accumulate multiple glBitmap calls in a
+ * buffer which is then rendered en mass upon a flush, state change, etc.
+ * A wide, short buffer is used to target the common case of a series
+ * of glBitmap calls being used to draw text.
+ */
+static GLboolean UseBitmapCache = GL_TRUE;
+
+
+#define BITMAP_CACHE_WIDTH 512
+#define BITMAP_CACHE_HEIGHT 32
+
+struct bitmap_cache
+{
+ /** Window pos to render the cached image */
+ GLint xpos, ypos;
+ /** Bounds of region used in window coords */
+ GLint xmin, ymin, xmax, ymax;
+
+ GLfloat color[4];
+
+ /** Bitmap's Z position */
+ GLfloat zpos;
+
+ struct pipe_texture *texture;
+ struct pipe_transfer *trans;
+
+ GLboolean empty;
+
+ /** An I8 texture image: */
+ ubyte *buffer;
+};
+
+
+/** Epsilon for Z comparisons */
+#define Z_EPSILON 1e-06
+
+
+/**
+ * Make fragment program for glBitmap:
+ * Sample the texture and kill the fragment if the bit is 0.
+ * This program will be combined with the user's fragment program.
+ */
+static struct st_fragment_program *
+make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
+{
+ struct st_fragment_program *stfp;
+ struct gl_program *p;
+ GLuint ic = 0;
+
+ p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ if (!p)
+ return NULL;
+
+ p->NumInstructions = 3;
+
+ p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
+ if (!p->Instructions) {
+ ctx->Driver.DeleteProgram(ctx, p);
+ return NULL;
+ }
+ _mesa_init_instructions(p->Instructions, p->NumInstructions);
+
+ /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
+ p->Instructions[ic].Opcode = OPCODE_TEX;
+ p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].DstReg.Index = 0;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
+ p->Instructions[ic].TexSrcUnit = samplerIndex;
+ p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
+ p->Instructions[ic].Opcode = OPCODE_KIL;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+
+ if (ctx->st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM)
+ p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX;
+
+ p->Instructions[ic].SrcReg[0].Index = 0;
+ p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW;
+ ic++;
+
+ /* END; */
+ p->Instructions[ic++].Opcode = OPCODE_END;
+
+ assert(ic == p->NumInstructions);
+
+ p->InputsRead = FRAG_BIT_TEX0;
+ p->OutputsWritten = 0x0;
+ p->SamplersUsed = (1 << samplerIndex);
+
+ stfp = (struct st_fragment_program *) p;
+ stfp->Base.UsesKill = GL_TRUE;
+
+ /* No need to send this incomplete program down to hardware:
+ *
+ * st_translate_fragment_program(ctx->st, stfp, NULL);
+ */
+
+ return stfp;
+}
+
+
+static int
+find_free_bit(uint bitfield)
+{
+ int i;
+ for (i = 0; i < 32; i++) {
+ if ((bitfield & (1 << i)) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Combine basic bitmap fragment program with the user-defined program.
+ */
+static struct st_fragment_program *
+combined_bitmap_fragment_program(GLcontext *ctx)
+{
+ struct st_context *st = ctx->st;
+ struct st_fragment_program *stfp = st->fp;
+
+ if (!stfp->bitmap_program) {
+ /*
+ * Generate new program which is the user-defined program prefixed
+ * with the bitmap sampler/kill instructions.
+ */
+ struct st_fragment_program *bitmap_prog;
+ uint sampler;
+
+ sampler = find_free_bit(st->fp->Base.Base.SamplersUsed);
+ bitmap_prog = make_bitmap_fragment_program(ctx, sampler);
+
+ stfp->bitmap_program = (struct st_fragment_program *)
+ _mesa_combine_programs(ctx,
+ &bitmap_prog->Base.Base, &stfp->Base.Base);
+ stfp->bitmap_program->bitmap_sampler = sampler;
+
+ /* done with this after combining */
+ st_reference_fragprog(st, &bitmap_prog, NULL);
+
+#if 0
+ {
+ struct gl_program *p = &stfp->bitmap_program->Base.Base;
+ printf("Combined bitmap program:\n");
+ _mesa_print_program(p);
+ printf("InputsRead: 0x%x\n", p->InputsRead);
+ printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
+ _mesa_print_parameter_list(p->Parameters);
+ }
+#endif
+
+ /* translate to TGSI tokens */
+ st_translate_fragment_program(st, stfp->bitmap_program, NULL);
+ }
+
+ return stfp->bitmap_program;
+}
+
+
+/**
+ * Copy user-provide bitmap bits into texture buffer, expanding
+ * bits into texels.
+ * "On" bits will set texels to 0x0.
+ * "Off" bits will not modify texels.
+ * Note that the image is actually going to be upside down in
+ * the texture. We deal with that with texcoords.
+ */
+static void
+unpack_bitmap(struct st_context *st,
+ GLint px, GLint py, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap,
+ ubyte *destBuffer, uint destStride)
+{
+ destBuffer += py * destStride + px;
+
+ _mesa_expand_bitmap(width, height, unpack, bitmap,
+ destBuffer, destStride, 0x0);
+}
+
+
+/**
+ * Create a texture which represents a bitmap image.
+ */
+static struct pipe_texture *
+make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_transfer *transfer;
+ ubyte *dest;
+ struct pipe_texture *pt;
+
+ /* PBO source... */
+ bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
+ if (!bitmap) {
+ return NULL;
+ }
+
+ /**
+ * Create texture to hold bitmap pattern.
+ */
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, ctx->st->bitmap.tex_format,
+ 0, width, height, 1,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ if (!pt) {
+ _mesa_unmap_pbo_source(ctx, unpack);
+ return NULL;
+ }
+
+ transfer = st_no_flush_get_tex_transfer(st_context(ctx), pt, 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ 0, 0, width, height);
+
+ dest = screen->transfer_map(screen, transfer);
+
+ /* Put image into texture transfer */
+ memset(dest, 0xff, height * transfer->stride);
+ unpack_bitmap(ctx->st, 0, 0, width, height, unpack, bitmap,
+ dest, transfer->stride);
+
+ _mesa_unmap_pbo_source(ctx, unpack);
+
+ /* Release transfer */
+ screen->transfer_unmap(screen, transfer);
+ screen->tex_transfer_destroy(transfer);
+
+ return pt;
+}
+
+static GLuint
+setup_bitmap_vertex_data(struct st_context *st,
+ int x, int y, int width, int height,
+ float z, const float color[4])
+{
+ struct pipe_context *pipe = st->pipe;
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLfloat fb_width = (GLfloat)fb->Width;
+ const GLfloat fb_height = (GLfloat)fb->Height;
+ const GLfloat x0 = (GLfloat)x;
+ const GLfloat x1 = (GLfloat)(x + width);
+ const GLfloat y0 = (GLfloat)y;
+ const GLfloat y1 = (GLfloat)(y + height);
+ const GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
+ const GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
+ const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
+ const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
+ const GLuint max_slots = 4096 / sizeof(st->bitmap.vertices);
+ GLuint i;
+
+ if (st->bitmap.vbuf_slot >= max_slots) {
+ pipe_buffer_reference(&st->bitmap.vbuf, NULL);
+ st->bitmap.vbuf_slot = 0;
+ }
+
+ if (!st->bitmap.vbuf) {
+ st->bitmap.vbuf = pipe_buffer_create(pipe->screen, 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ max_slots * sizeof(st->bitmap.vertices));
+ }
+
+ /* Positions are in clip coords since we need to do clipping in case
+ * the bitmap quad goes beyond the window bounds.
+ */
+ st->bitmap.vertices[0][0][0] = clip_x0;
+ st->bitmap.vertices[0][0][1] = clip_y0;
+ st->bitmap.vertices[0][2][0] = sLeft;
+ st->bitmap.vertices[0][2][1] = tTop;
+
+ st->bitmap.vertices[1][0][0] = clip_x1;
+ st->bitmap.vertices[1][0][1] = clip_y0;
+ st->bitmap.vertices[1][2][0] = sRight;
+ st->bitmap.vertices[1][2][1] = tTop;
+
+ st->bitmap.vertices[2][0][0] = clip_x1;
+ st->bitmap.vertices[2][0][1] = clip_y1;
+ st->bitmap.vertices[2][2][0] = sRight;
+ st->bitmap.vertices[2][2][1] = tBot;
+
+ st->bitmap.vertices[3][0][0] = clip_x0;
+ st->bitmap.vertices[3][0][1] = clip_y1;
+ st->bitmap.vertices[3][2][0] = sLeft;
+ st->bitmap.vertices[3][2][1] = tBot;
+
+ /* same for all verts: */
+ for (i = 0; i < 4; i++) {
+ st->bitmap.vertices[i][0][2] = z;
+ st->bitmap.vertices[i][0][3] = 1.0;
+ st->bitmap.vertices[i][1][0] = color[0];
+ st->bitmap.vertices[i][1][1] = color[1];
+ st->bitmap.vertices[i][1][2] = color[2];
+ st->bitmap.vertices[i][1][3] = color[3];
+ st->bitmap.vertices[i][2][2] = 0.0; /*R*/
+ st->bitmap.vertices[i][2][3] = 1.0; /*Q*/
+ }
+
+ /* put vertex data into vbuf */
+ st_no_flush_pipe_buffer_write(st,
+ st->bitmap.vbuf,
+ st->bitmap.vbuf_slot * sizeof st->bitmap.vertices,
+ sizeof st->bitmap.vertices,
+ st->bitmap.vertices);
+
+ return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
+}
+
+
+
+/**
+ * Render a glBitmap by drawing a textured quad
+ */
+static void
+draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
+ GLsizei width, GLsizei height,
+ struct pipe_texture *pt,
+ const GLfloat *color)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct cso_context *cso = ctx->st->cso_context;
+ struct st_fragment_program *stfp;
+ GLuint maxSize;
+ GLuint offset;
+
+ stfp = combined_bitmap_fragment_program(ctx);
+
+ /* As an optimization, Mesa's fragment programs will sometimes get the
+ * primary color from a statevar/constant rather than a varying variable.
+ * when that's the case, we need to ensure that we use the 'color'
+ * parameter and not the current attribute color (which may have changed
+ * through glRasterPos and state validation.
+ * So, we force the proper color here. Not elegant, but it works.
+ */
+ {
+ GLfloat colorSave[4];
+ COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
+ COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
+ st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
+ COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
+ }
+
+
+ /* limit checks */
+ /* XXX if the bitmap is larger than the max texture size, break
+ * it up into chunks.
+ */
+ maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+ assert(width <= (GLsizei)maxSize);
+ assert(height <= (GLsizei)maxSize);
+
+ cso_save_rasterizer(cso);
+ cso_save_samplers(cso);
+ cso_save_sampler_textures(cso);
+ cso_save_viewport(cso);
+ cso_save_fragment_shader(cso);
+ cso_save_vertex_shader(cso);
+
+ /* rasterizer state: just scissor */
+ st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
+ cso_set_rasterizer(cso, &st->bitmap.rasterizer);
+
+ /* fragment shader state: TEX lookup program */
+ cso_set_fragment_shader_handle(cso, stfp->driver_shader);
+
+ /* vertex shader state: position + texcoord pass-through */
+ cso_set_vertex_shader_handle(cso, st->bitmap.vs);
+
+ /* user samplers, plus our bitmap sampler */
+ {
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers);
+ uint i;
+ for (i = 0; i < st->state.num_samplers; i++) {
+ samplers[i] = &st->state.samplers[i];
+ }
+ samplers[stfp->bitmap_sampler] = &st->bitmap.sampler;
+ cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
+ }
+
+ /* user textures, plus the bitmap texture */
+ {
+ struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+ uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures);
+ memcpy(textures, st->state.sampler_texture, sizeof(textures));
+ textures[stfp->bitmap_sampler] = pt;
+ cso_set_sampler_textures(cso, num, textures);
+ }
+
+ /* viewport state: viewport matching window dims */
+ {
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
+ const GLfloat width = (GLfloat)fb->Width;
+ const GLfloat height = (GLfloat)fb->Height;
+ struct pipe_viewport_state vp;
+ vp.scale[0] = 0.5f * width;
+ vp.scale[1] = height * (invert ? -0.5f : 0.5f);
+ vp.scale[2] = 1.0f;
+ vp.scale[3] = 1.0f;
+ vp.translate[0] = 0.5f * width;
+ vp.translate[1] = 0.5f * height;
+ vp.translate[2] = 0.0f;
+ vp.translate[3] = 0.0f;
+ cso_set_viewport(cso, &vp);
+ }
+
+ /* draw textured quad */
+ offset = setup_bitmap_vertex_data(st, x, y, width, height, z, color);
+
+ util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 3); /* attribs/vert */
+
+
+ /* restore state */
+ cso_restore_rasterizer(cso);
+ cso_restore_samplers(cso);
+ cso_restore_sampler_textures(cso);
+ cso_restore_viewport(cso);
+ cso_restore_fragment_shader(cso);
+ cso_restore_vertex_shader(cso);
+}
+
+
+static void
+reset_cache(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ //memset(cache->buffer, 0xff, sizeof(cache->buffer));
+ cache->empty = GL_TRUE;
+
+ cache->xmin = 1000000;
+ cache->xmax = -1000000;
+ cache->ymin = 1000000;
+ cache->ymax = -1000000;
+
+ if (cache->trans) {
+ screen->tex_transfer_destroy(cache->trans);
+ cache->trans = NULL;
+ }
+
+ assert(!cache->texture);
+
+ /* allocate a new texture */
+ cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
+ st->bitmap.tex_format, 0,
+ BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
+ 1, PIPE_TEXTURE_USAGE_SAMPLER);
+
+}
+
+static void
+create_cache_trans(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ if (cache->trans)
+ return;
+
+ /* Map the texture transfer.
+ * Subsequent glBitmap calls will write into the texture image.
+ */
+ cache->trans = st_no_flush_get_tex_transfer(st, cache->texture, 0, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ BITMAP_CACHE_WIDTH,
+ BITMAP_CACHE_HEIGHT);
+ cache->buffer = screen->transfer_map(screen, cache->trans);
+
+ /* init image to all 0xff */
+ memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT);
+}
+
+
+/**
+ * If there's anything in the bitmap cache, draw/flush it now.
+ */
+void
+st_flush_bitmap_cache(struct st_context *st)
+{
+ if (!st->bitmap.cache->empty) {
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+ if (st->ctx->DrawBuffer) {
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+
+ assert(cache->xmin <= cache->xmax);
+
+/* printf("flush size %d x %d at %d, %d\n",
+ cache->xmax - cache->xmin,
+ cache->ymax - cache->ymin,
+ cache->xpos, cache->ypos);
+*/
+
+ /* The texture transfer has been mapped until now.
+ * So unmap and release the texture transfer before drawing.
+ */
+ if (cache->trans) {
+ screen->transfer_unmap(screen, cache->trans);
+ cache->buffer = NULL;
+
+ screen->tex_transfer_destroy(cache->trans);
+ cache->trans = NULL;
+ }
+
+ draw_bitmap_quad(st->ctx,
+ cache->xpos,
+ cache->ypos,
+ cache->zpos,
+ BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
+ cache->texture,
+ cache->color);
+ }
+
+ /* release/free the texture */
+ pipe_texture_reference(&cache->texture, NULL);
+
+ reset_cache(st);
+ }
+}
+
+/* Flush bitmap cache and release vertex buffer.
+ */
+void
+st_flush_bitmap( struct st_context *st )
+{
+ st_flush_bitmap_cache(st);
+
+ /* Release vertex buffer to avoid synchronous rendering if we were
+ * to map it in the next frame.
+ */
+ pipe_buffer_reference(&st->bitmap.vbuf, NULL);
+ st->bitmap.vbuf_slot = 0;
+}
+
+
+/**
+ * Try to accumulate this glBitmap call in the bitmap cache.
+ * \return GL_TRUE for success, GL_FALSE if bitmap is too large, etc.
+ */
+static GLboolean
+accum_bitmap(struct st_context *st,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap )
+{
+ struct bitmap_cache *cache = st->bitmap.cache;
+ int px = -999, py;
+ const GLfloat z = st->ctx->Current.RasterPos[2];
+
+ if (width > BITMAP_CACHE_WIDTH ||
+ height > BITMAP_CACHE_HEIGHT)
+ return GL_FALSE; /* too big to cache */
+
+ if (!cache->empty) {
+ px = x - cache->xpos; /* pos in buffer */
+ py = y - cache->ypos;
+ if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
+ py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
+ !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) ||
+ ((fabs(z - cache->zpos) > Z_EPSILON))) {
+ /* This bitmap would extend beyond cache bounds, or the bitmap
+ * color is changing
+ * so flush and continue.
+ */
+ st_flush_bitmap_cache(st);
+ }
+ }
+
+ if (cache->empty) {
+ /* Initialize. Center bitmap vertically in the buffer. */
+ px = 0;
+ py = (BITMAP_CACHE_HEIGHT - height) / 2;
+ cache->xpos = x;
+ cache->ypos = y - py;
+ cache->zpos = z;
+ cache->empty = GL_FALSE;
+ COPY_4FV(cache->color, st->ctx->Current.RasterColor);
+ }
+
+ assert(px != -999);
+
+ if (x < cache->xmin)
+ cache->xmin = x;
+ if (y < cache->ymin)
+ cache->ymin = y;
+ if (x + width > cache->xmax)
+ cache->xmax = x + width;
+ if (y + height > cache->ymax)
+ cache->ymax = y + height;
+
+ /* create the transfer if needed */
+ create_cache_trans(st);
+
+ unpack_bitmap(st, px, py, width, height, unpack, bitmap,
+ cache->buffer, BITMAP_CACHE_WIDTH);
+
+ return GL_TRUE; /* accumulated */
+}
+
+
+
+/**
+ * Called via ctx->Driver.Bitmap()
+ */
+static void
+st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
+{
+ struct st_context *st = ctx->st;
+ struct pipe_texture *pt;
+
+ if (width == 0 || height == 0)
+ return;
+
+ st_validate_state(st);
+
+ if (!st->bitmap.vs) {
+ /* create pass-through vertex shader now */
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_COLOR,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0, 0 };
+ st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
+ semantic_names,
+ semantic_indexes);
+ }
+
+ if (UseBitmapCache && accum_bitmap(st, x, y, width, height, unpack, bitmap))
+ return;
+
+ pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
+ if (pt) {
+ assert(pt->target == PIPE_TEXTURE_2D);
+ draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
+ width, height, pt,
+ st->ctx->Current.RasterColor);
+ /* release/free the texture */
+ pipe_texture_reference(&pt, NULL);
+ }
+}
+
+
+/** Per-context init */
+void
+st_init_bitmap_functions(struct dd_function_table *functions)
+{
+ functions->Bitmap = st_Bitmap;
+}
+
+
+/** Per-context init */
+void
+st_init_bitmap(struct st_context *st)
+{
+ struct pipe_sampler_state *sampler = &st->bitmap.sampler;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+
+ /* init sampler state once */
+ memset(sampler, 0, sizeof(*sampler));
+ sampler->wrap_s = PIPE_TEX_WRAP_CLAMP;
+ sampler->wrap_t = PIPE_TEX_WRAP_CLAMP;
+ sampler->wrap_r = PIPE_TEX_WRAP_CLAMP;
+ sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler->normalized_coords = 1;
+
+ /* init baseline rasterizer state once */
+ memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
+ st->bitmap.rasterizer.gl_rasterization_rules = 1;
+
+ /* find a usable texture format */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
+ }
+ else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM;
+ }
+ else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM;
+ }
+ else {
+ /* XXX support more formats */
+ assert(0);
+ }
+
+ /* alloc bitmap cache object */
+ st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache);
+
+ reset_cache(st);
+}
+
+
+/** Per-context tear-down */
+void
+st_destroy_bitmap(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct bitmap_cache *cache = st->bitmap.cache;
+
+
+
+ if (st->bitmap.vs) {
+ cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
+ st->bitmap.vs = NULL;
+ }
+
+ if (st->bitmap.vbuf) {
+ pipe_buffer_reference(&st->bitmap.vbuf, NULL);
+ st->bitmap.vbuf = NULL;
+ }
+
+ if (cache) {
+ if (cache->trans) {
+ screen->transfer_unmap(screen, cache->trans);
+ screen->tex_transfer_destroy(cache->trans);
+ }
+ pipe_texture_reference(&st->bitmap.cache->texture, NULL);
+ _mesa_free(st->bitmap.cache);
+ st->bitmap.cache = NULL;
+ }
+}
diff --git a/src/mesa/state_tracker/st_cb_bitmap.h b/src/mesa/state_tracker/st_cb_bitmap.h
new file mode 100644
index 0000000000..81cf61981d
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bitmap.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_BITMAP_H
+#define ST_CB_BITMAP_H
+
+
+extern void
+st_init_bitmap_functions(struct dd_function_table *functions);
+
+extern void
+st_init_bitmap(struct st_context *st);
+
+extern void
+st_destroy_bitmap(struct st_context *st);
+
+extern void
+st_flush_bitmap_cache(struct st_context *st);
+
+/* Flush bitmap cache and release vertex buffer. Needed at end of
+ * frame to avoid synchronous rendering.
+ */
+extern void
+st_flush_bitmap(struct st_context *st);
+
+
+#endif /* ST_CB_BITMAP_H */
diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c
new file mode 100644
index 0000000000..c741940bcf
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_blit.c
@@ -0,0 +1,184 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_program.h"
+#include "st_cb_blit.h"
+#include "st_cb_fbo.h"
+
+#include "util/u_blit.h"
+
+#include "cso_cache/cso_context.h"
+
+
+void
+st_init_blit(struct st_context *st)
+{
+ st->blit = util_create_blit(st->pipe, st->cso_context);
+}
+
+
+void
+st_destroy_blit(struct st_context *st)
+{
+ util_destroy_blit(st->blit);
+ st->blit = NULL;
+}
+
+
+static void
+st_BlitFramebuffer(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT |
+ GL_STENCIL_BUFFER_BIT);
+ struct st_context *st = ctx->st;
+ const uint pFilter = ((filter == GL_NEAREST)
+ ? PIPE_TEX_MIPFILTER_NEAREST
+ : PIPE_TEX_MIPFILTER_LINEAR);
+ struct gl_framebuffer *readFB = ctx->ReadBuffer;
+ struct gl_framebuffer *drawFB = ctx->DrawBuffer;
+
+ if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
+ &dstX0, &dstY0, &dstX1, &dstY1)) {
+ return; /* nothing to draw/blit */
+ }
+
+ if (st_fb_orientation(drawFB) == Y_0_TOP) {
+ /* invert Y for dest */
+ dstY0 = drawFB->Height - dstY0;
+ dstY1 = drawFB->Height - dstY1;
+ }
+
+ if (st_fb_orientation(readFB) == Y_0_TOP) {
+ /* invert Y for src */
+ srcY0 = readFB->Height - srcY0;
+ srcY1 = readFB->Height - srcY1;
+ }
+
+ if (srcY0 > srcY1 && dstY0 > dstY1) {
+ /* Both src and dst are upside down. Swap Y to make it
+ * right-side up to increase odds of using a fast path.
+ * Recall that all Gallium raster coords have Y=0=top.
+ */
+ GLint tmp;
+ tmp = srcY0;
+ srcY0 = srcY1;
+ srcY1 = tmp;
+ tmp = dstY0;
+ dstY0 = dstY1;
+ dstY1 = tmp;
+ }
+
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ struct st_renderbuffer *srcRb =
+ st_renderbuffer(readFB->_ColorReadBuffer);
+ struct st_renderbuffer *dstRb =
+ st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
+ struct pipe_surface *srcSurf = srcRb->surface;
+ struct pipe_surface *dstSurf = dstRb->surface;
+
+ util_blit_pixels(st->blit,
+ srcSurf, srcX0, srcY0, srcX1, srcY1,
+ dstSurf, dstX0, dstY0, dstX1, dstY1,
+ 0.0, pFilter);
+ }
+
+ if (mask & depthStencil) {
+ /* depth and/or stencil blit */
+
+ /* get src/dst depth surfaces */
+ struct st_renderbuffer *srcDepthRb =
+ st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);
+ struct st_renderbuffer *dstDepthRb =
+ st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);
+ struct pipe_surface *srcDepthSurf =
+ srcDepthRb ? srcDepthRb->surface : NULL;
+ struct pipe_surface *dstDepthSurf =
+ dstDepthRb ? dstDepthRb->surface : NULL;
+
+ /* get src/dst stencil surfaces */
+ struct st_renderbuffer *srcStencilRb =
+ st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);
+ struct st_renderbuffer *dstStencilRb =
+ st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer);
+ struct pipe_surface *srcStencilSurf =
+ srcStencilRb ? srcStencilRb->surface : NULL;
+ struct pipe_surface *dstStencilSurf =
+ dstStencilRb ? dstStencilRb->surface : NULL;
+
+ if ((mask & depthStencil) == depthStencil &&
+ srcDepthSurf == srcStencilSurf &&
+ dstDepthSurf == dstStencilSurf) {
+ /* Blitting depth and stencil values between combined
+ * depth/stencil buffers. This is the ideal case for such buffers.
+ */
+ util_blit_pixels(st->blit,
+ srcDepthSurf, srcX0, srcY0, srcX1, srcY1,
+ dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
+ 0.0, pFilter);
+ }
+ else {
+ /* blitting depth and stencil separately */
+
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ /* blit Z only */
+ _mesa_problem(ctx, "st_BlitFramebuffer(DEPTH) not completed");
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ /* blit stencil only */
+ _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) not completed");
+ }
+ }
+ }
+}
+
+
+
+void
+st_init_blit_functions(struct dd_function_table *functions)
+{
+#if FEATURE_EXT_framebuffer_blit
+ functions->BlitFramebuffer = st_BlitFramebuffer;
+#endif
+}
diff --git a/src/mesa/state_tracker/st_cb_blit.h b/src/mesa/state_tracker/st_cb_blit.h
new file mode 100644
index 0000000000..ed22986b53
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_blit.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_BLIT_H
+#define ST_CB_BLIT_H
+
+
+#include "st_context.h"
+
+
+
+extern void
+st_init_blit(struct st_context *st);
+
+extern void
+st_destroy_blit(struct st_context *st);
+
+extern void
+st_init_blit_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_BLIT_H */
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c
new file mode 100644
index 0000000000..8e09d0b932
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bufferobjects.c
@@ -0,0 +1,354 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Functions for pixel buffer objects and vertex/element buffer objects.
+ */
+
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/arrayobj.h"
+#include "main/bufferobj.h"
+
+#include "st_inlines.h"
+#include "st_context.h"
+#include "st_cb_bufferobjects.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+
+/**
+ * There is some duplication between mesa's bufferobjects and our
+ * bufmgr buffers. Both have an integer handle and a hashtable to
+ * lookup an opaque structure. It would be nice if the handles and
+ * internal structure where somehow shared.
+ */
+static struct gl_buffer_object *
+st_bufferobj_alloc(GLcontext *ctx, GLuint name, GLenum target)
+{
+ struct st_buffer_object *st_obj = ST_CALLOC_STRUCT(st_buffer_object);
+
+ if (!st_obj)
+ return NULL;
+
+ _mesa_initialize_buffer_object(&st_obj->Base, name, target);
+
+ return &st_obj->Base;
+}
+
+
+
+/**
+ * Deallocate/free a vertex/pixel buffer object.
+ * Called via glDeleteBuffersARB().
+ */
+static void
+st_bufferobj_free(GLcontext *ctx, struct gl_buffer_object *obj)
+{
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ if (st_obj->buffer)
+ pipe_buffer_reference(&st_obj->buffer, NULL);
+
+ _mesa_free(st_obj);
+}
+
+
+
+/**
+ * Replace data in a subrange of buffer object. If the data range
+ * specified by size + offset extends beyond the end of the buffer or
+ * if data is NULL, no copy is performed.
+ * Called via glBufferSubDataARB().
+ */
+static void
+st_bufferobj_subdata(GLcontext *ctx,
+ GLenum target,
+ GLintptrARB offset,
+ GLsizeiptrARB size,
+ const GLvoid * data, struct gl_buffer_object *obj)
+{
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ /* we may be called from VBO code, so double-check params here */
+ ASSERT(offset >= 0);
+ ASSERT(size >= 0);
+ ASSERT(offset + size <= obj->Size);
+
+ st_cond_flush_pipe_buffer_write(st_context(ctx), st_obj->buffer,
+ offset, size, data);
+}
+
+
+/**
+ * Called via glGetBufferSubDataARB().
+ */
+static void
+st_bufferobj_get_subdata(GLcontext *ctx,
+ GLenum target,
+ GLintptrARB offset,
+ GLsizeiptrARB size,
+ GLvoid * data, struct gl_buffer_object *obj)
+{
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ /* we may be called from VBO code, so double-check params here */
+ ASSERT(offset >= 0);
+ ASSERT(size >= 0);
+ ASSERT(offset + size <= obj->Size);
+
+ st_cond_flush_pipe_buffer_read(st_context(ctx), st_obj->buffer,
+ offset, size, data);
+}
+
+
+/**
+ * Allocate space for and store data in a buffer object. Any data that was
+ * previously stored in the buffer object is lost. If data is NULL,
+ * memory will be allocated, but no copy will occur.
+ * Called via ctx->Driver.BufferData().
+ * \return GL_TRUE for success, GL_FALSE if out of memory
+ */
+static GLboolean
+st_bufferobj_data(GLcontext *ctx,
+ GLenum target,
+ GLsizeiptrARB size,
+ const GLvoid * data,
+ GLenum usage,
+ struct gl_buffer_object *obj)
+{
+ 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;
+
+ st_obj->Base.Size = size;
+ st_obj->Base.Usage = usage;
+
+ switch(target) {
+ case GL_PIXEL_PACK_BUFFER_ARB:
+ case GL_PIXEL_UNPACK_BUFFER_ARB:
+ buffer_usage = PIPE_BUFFER_USAGE_PIXEL;
+ break;
+ case GL_ARRAY_BUFFER_ARB:
+ buffer_usage = PIPE_BUFFER_USAGE_VERTEX;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_ARB:
+ buffer_usage = PIPE_BUFFER_USAGE_INDEX;
+ break;
+ default:
+ buffer_usage = 0;
+ }
+
+ pipe_buffer_reference( &st_obj->buffer, NULL );
+
+ st_obj->buffer = pipe_buffer_create( pipe->screen, 32, buffer_usage, size );
+
+ if (!st_obj->buffer) {
+ return GL_FALSE;
+ }
+
+ if (data)
+ st_no_flush_pipe_buffer_write(st_context(ctx), st_obj->buffer, 0,
+ size, data);
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via glMapBufferARB().
+ */
+static void *
+st_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access,
+ struct gl_buffer_object *obj)
+{
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ uint flags;
+
+ switch (access) {
+ case GL_WRITE_ONLY:
+ flags = PIPE_BUFFER_USAGE_CPU_WRITE;
+ break;
+ case GL_READ_ONLY:
+ flags = PIPE_BUFFER_USAGE_CPU_READ;
+ break;
+ case GL_READ_WRITE:
+ /* fall-through */
+ default:
+ flags = PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE;
+ break;
+ }
+
+ obj->Pointer = st_cond_flush_pipe_buffer_map(st_context(ctx),
+ st_obj->buffer,
+ flags);
+ if (obj->Pointer) {
+ obj->Offset = 0;
+ obj->Length = obj->Size;
+ }
+ return obj->Pointer;
+}
+
+
+/**
+ * Called via glMapBufferRange().
+ */
+static void *
+st_bufferobj_map_range(GLcontext *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length, GLbitfield access,
+ struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ uint flags = 0x0;
+
+ if (access & GL_MAP_WRITE_BIT)
+ flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
+
+ if (access & GL_MAP_READ_BIT)
+ flags |= PIPE_BUFFER_USAGE_CPU_READ;
+
+ if (access & GL_MAP_FLUSH_EXPLICIT_BIT)
+ flags |= PIPE_BUFFER_USAGE_FLUSH_EXPLICIT;
+
+ /* ... other flags ...
+ */
+
+ if (access & MESA_MAP_NOWAIT_BIT)
+ flags |= PIPE_BUFFER_USAGE_DONTBLOCK;
+
+ assert(offset >= 0);
+ assert(length >= 0);
+ assert(offset < obj->Size);
+ assert(offset + length <= obj->Size);
+
+ obj->Pointer = pipe_buffer_map_range(pipe->screen, st_obj->buffer, offset, length, flags);
+ if (obj->Pointer) {
+ obj->Pointer = (ubyte *) obj->Pointer + offset;
+ obj->Offset = offset;
+ obj->Length = length;
+ obj->AccessFlags = access;
+ }
+
+ return obj->Pointer;
+}
+
+
+static void
+st_bufferobj_flush_mapped_range(GLcontext *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length,
+ struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ /* Subrange is relative to mapped range */
+ assert(offset >= 0);
+ assert(length >= 0);
+ assert(offset + length <= obj->Length);
+
+ pipe_buffer_flush_mapped_range(pipe->screen, st_obj->buffer,
+ obj->Offset + offset, length);
+}
+
+
+/**
+ * Called via glUnmapBufferARB().
+ */
+static GLboolean
+st_bufferobj_unmap(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ pipe_buffer_unmap(pipe->screen, st_obj->buffer);
+ obj->Pointer = NULL;
+ obj->Offset = 0;
+ obj->Length = 0;
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via glCopyBufferSubData().
+ */
+static void
+st_copy_buffer_subdata(GLcontext *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_buffer_object *srcObj = st_buffer_object(src);
+ struct st_buffer_object *dstObj = st_buffer_object(dst);
+ ubyte *srcPtr, *dstPtr;
+
+ /* buffer should not already be mapped */
+ assert(!src->Pointer);
+ assert(!dst->Pointer);
+
+ srcPtr = (ubyte *) pipe_buffer_map_range(pipe->screen,
+ srcObj->buffer,
+ readOffset, size,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ dstPtr = (ubyte *) pipe_buffer_map_range(pipe->screen,
+ dstObj->buffer,
+ writeOffset, size,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ if (srcPtr && dstPtr)
+ _mesa_memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
+
+ pipe_buffer_unmap(pipe->screen, srcObj->buffer);
+ pipe_buffer_unmap(pipe->screen, dstObj->buffer);
+}
+
+
+void
+st_init_bufferobject_functions(struct dd_function_table *functions)
+{
+ functions->NewBufferObject = st_bufferobj_alloc;
+ functions->DeleteBuffer = st_bufferobj_free;
+ functions->BufferData = st_bufferobj_data;
+ functions->BufferSubData = st_bufferobj_subdata;
+ functions->GetBufferSubData = st_bufferobj_get_subdata;
+ functions->MapBuffer = st_bufferobj_map;
+ functions->MapBufferRange = st_bufferobj_map_range;
+ functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range;
+ functions->UnmapBuffer = st_bufferobj_unmap;
+ functions->CopyBufferSubData = st_copy_buffer_subdata;
+
+ /* For GL_APPLE_vertex_array_object */
+ functions->NewArrayObject = _mesa_new_array_object;
+ functions->DeleteArrayObject = _mesa_delete_array_object;
+}
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.h b/src/mesa/state_tracker/st_cb_bufferobjects.h
new file mode 100644
index 0000000000..fda6d05dd3
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bufferobjects.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+ *
+ * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_BUFFEROBJECTS_H
+#define ST_CB_BUFFEROBJECTS_H
+
+struct st_context;
+struct gl_buffer_object;
+struct pipe_buffer;
+
+/**
+ * State_tracker vertex/pixel buffer object, derived from Mesa's
+ * gl_buffer_object.
+ */
+struct st_buffer_object
+{
+ struct gl_buffer_object Base;
+ struct pipe_buffer *buffer;
+};
+
+
+/** cast wrapper */
+static INLINE struct st_buffer_object *
+st_buffer_object(struct gl_buffer_object *obj)
+{
+ return (struct st_buffer_object *) obj;
+}
+
+
+extern void
+st_init_bufferobject_functions(struct dd_function_table *functions);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
new file mode 100644
index 0000000000..8a8c99f7e1
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -0,0 +1,495 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ * Michel Dänzer
+ */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "shader/prog_instruction.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_accum.h"
+#include "st_cb_clear.h"
+#include "st_cb_fbo.h"
+#include "st_draw.h"
+#include "st_program.h"
+#include "st_public.h"
+#include "st_mesa_to_tgsi.h"
+#include "st_inlines.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "util/u_pack_color.h"
+#include "util/u_simple_shaders.h"
+#include "util/u_draw_quad.h"
+
+#include "cso_cache/cso_context.h"
+
+
+void
+st_init_clear(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ memset(&st->clear.raster, 0, sizeof(st->clear.raster));
+ st->clear.raster.gl_rasterization_rules = 1;
+
+ /* rasterizer state: bypass vertex shader, clipping and viewport */
+ st->clear.raster.bypass_vs_clip_and_viewport = 1;
+
+ /* fragment shader state: color pass-through program */
+ st->clear.fs =
+ util_make_fragment_passthrough_shader(pipe);
+
+ /* vertex shader state: color/position pass-through */
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_COLOR };
+ const uint semantic_indexes[] = { 0, 0 };
+ st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2,
+ semantic_names,
+ semantic_indexes);
+ }
+}
+
+
+void
+st_destroy_clear(struct st_context *st)
+{
+ if (st->clear.fs) {
+ cso_delete_fragment_shader(st->cso_context, st->clear.fs);
+ st->clear.fs = NULL;
+ }
+ if (st->clear.vs) {
+ cso_delete_vertex_shader(st->cso_context, st->clear.vs);
+ st->clear.vs = NULL;
+ }
+ if (st->clear.vbuf) {
+ pipe_buffer_reference(&st->clear.vbuf, NULL);
+ st->clear.vbuf = NULL;
+ }
+}
+
+
+/**
+ * Draw a screen-aligned quadrilateral.
+ * Coords are window coords with y=0=bottom. These will be passed
+ * through unmodified to the rasterizer as we have set
+ * rasterizer->bypass_vs_clip_and_viewport.
+ */
+static void
+draw_quad(GLcontext *ctx,
+ float x0, float y0, float x1, float y1, GLfloat z,
+ const GLfloat color[4])
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ const GLuint max_slots = 1024 / sizeof(st->clear.vertices);
+ GLuint i;
+
+ if (st->clear.vbuf_slot >= max_slots) {
+ pipe_buffer_reference(&st->clear.vbuf, NULL);
+ st->clear.vbuf_slot = 0;
+ }
+
+ if (!st->clear.vbuf) {
+ st->clear.vbuf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
+ max_slots * sizeof(st->clear.vertices));
+ }
+
+ /* positions */
+ st->clear.vertices[0][0][0] = x0;
+ st->clear.vertices[0][0][1] = y0;
+
+ st->clear.vertices[1][0][0] = x1;
+ st->clear.vertices[1][0][1] = y0;
+
+ st->clear.vertices[2][0][0] = x1;
+ st->clear.vertices[2][0][1] = y1;
+
+ st->clear.vertices[3][0][0] = x0;
+ st->clear.vertices[3][0][1] = y1;
+
+ /* same for all verts: */
+ for (i = 0; i < 4; i++) {
+ st->clear.vertices[i][0][2] = z;
+ st->clear.vertices[i][0][3] = 1.0;
+ st->clear.vertices[i][1][0] = color[0];
+ st->clear.vertices[i][1][1] = color[1];
+ st->clear.vertices[i][1][2] = color[2];
+ st->clear.vertices[i][1][3] = color[3];
+ }
+
+ /* put vertex data into vbuf */
+ st_no_flush_pipe_buffer_write(st, st->clear.vbuf,
+ st->clear.vbuf_slot * sizeof(st->clear.vertices),
+ sizeof(st->clear.vertices),
+ st->clear.vertices);
+
+ /* draw */
+ util_draw_vertex_buffer(pipe,
+ st->clear.vbuf,
+ st->clear.vbuf_slot * sizeof(st->clear.vertices),
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
+
+ /* Increment slot */
+ st->clear.vbuf_slot++;
+}
+
+
+
+/**
+ * Do glClear by drawing a quadrilateral.
+ * The vertices of the quad will be computed from the
+ * ctx->DrawBuffer->_X/Ymin/max fields.
+ */
+static void
+clear_with_quad(GLcontext *ctx,
+ GLboolean color, GLboolean depth, GLboolean stencil)
+{
+ struct st_context *st = ctx->st;
+ const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
+ const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
+ GLfloat y0, y1;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ y0 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax);
+ y1 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin);
+ }
+ else {
+ y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
+ y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
+ }
+
+ /*
+ printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__,
+ color ? "color, " : "",
+ depth ? "depth, " : "",
+ stencil ? "stencil" : "",
+ x0, y0,
+ x1, y1);
+ */
+
+ cso_save_blend(st->cso_context);
+ cso_save_depth_stencil_alpha(st->cso_context);
+ cso_save_rasterizer(st->cso_context);
+ cso_save_fragment_shader(st->cso_context);
+ cso_save_vertex_shader(st->cso_context);
+
+ /* blend state: RGBA masking */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ if (color) {
+ if (ctx->Color.ColorMask[0])
+ blend.colormask |= PIPE_MASK_R;
+ if (ctx->Color.ColorMask[1])
+ blend.colormask |= PIPE_MASK_G;
+ if (ctx->Color.ColorMask[2])
+ blend.colormask |= PIPE_MASK_B;
+ if (ctx->Color.ColorMask[3])
+ blend.colormask |= PIPE_MASK_A;
+ if (st->ctx->Color.DitherFlag)
+ blend.dither = 1;
+ }
+ cso_set_blend(st->cso_context, &blend);
+ }
+
+ /* depth_stencil state: always pass/set to ref value */
+ {
+ struct pipe_depth_stencil_alpha_state depth_stencil;
+ memset(&depth_stencil, 0, sizeof(depth_stencil));
+ if (depth) {
+ depth_stencil.depth.enabled = 1;
+ depth_stencil.depth.writemask = 1;
+ depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
+ }
+
+ if (stencil) {
+ depth_stencil.stencil[0].enabled = 1;
+ depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
+ depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
+ depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+ depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
+ depth_stencil.stencil[0].ref_value = ctx->Stencil.Clear;
+ depth_stencil.stencil[0].valuemask = 0xff;
+ depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
+ }
+
+ cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
+ }
+
+ cso_set_rasterizer(st->cso_context, &st->clear.raster);
+
+ 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(ctx, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor);
+
+ /* Restore pipe state */
+ cso_restore_blend(st->cso_context);
+ cso_restore_depth_stencil_alpha(st->cso_context);
+ cso_restore_rasterizer(st->cso_context);
+ cso_restore_fragment_shader(st->cso_context);
+ cso_restore_vertex_shader(st->cso_context);
+}
+
+
+/**
+ * Determine if we need to clear the depth buffer by drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
+ return TRUE;
+
+ if (!ctx->Color.ColorMask[0] ||
+ !ctx->Color.ColorMask[1] ||
+ !ctx->Color.ColorMask[2] ||
+ !ctx->Color.ColorMask[3])
+ return TRUE;
+
+ return FALSE;
+}
+
+
+static INLINE GLboolean
+check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const GLuint stencilMax = (1 << rb->StencilBits) - 1;
+ GLboolean maskStencil
+ = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
+
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
+ return TRUE;
+
+ if (maskStencil)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/**
+ * Determine if we need to clear the depth buffer by drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const struct st_renderbuffer *strb = st_renderbuffer(rb);
+ const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);
+
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
+ return TRUE;
+
+ if (isDS &&
+ ctx->DrawBuffer->Visual.stencilBits > 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/**
+ * Determine if we need to clear the stencil buffer by drawing a quad.
+ */
+static INLINE GLboolean
+check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const struct st_renderbuffer *strb = st_renderbuffer(rb);
+ const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);
+ const GLuint stencilMax = (1 << rb->StencilBits) - 1;
+ const GLboolean maskStencil
+ = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
+
+ if (maskStencil)
+ return TRUE;
+
+ if (ctx->Scissor.Enabled &&
+ (ctx->Scissor.X != 0 ||
+ ctx->Scissor.Y != 0 ||
+ ctx->Scissor.Width < rb->Width ||
+ ctx->Scissor.Height < rb->Height))
+ return TRUE;
+
+ /* This is correct, but it is necessary to look at the depth clear
+ * value held in the surface when it comes time to issue the clear,
+ * rather than taking depth and stencil clear values from the
+ * current state.
+ */
+ if (isDS &&
+ ctx->DrawBuffer->Visual.depthBits > 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+
+void st_flush_clear( struct st_context *st )
+{
+ /* Release vertex buffer to avoid synchronous rendering if we were
+ * to map it in the next frame.
+ */
+ pipe_buffer_reference(&st->clear.vbuf, NULL);
+ st->clear.vbuf_slot = 0;
+}
+
+
+
+/**
+ * Called via ctx->Driver.Clear()
+ * XXX: doesn't pick up the differences between front/back/left/right
+ * clears. Need to sort that out...
+ */
+static void st_clear(GLcontext *ctx, GLbitfield mask)
+{
+ static const GLbitfield BUFFER_BITS_DS
+ = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
+ struct st_context *st = ctx->st;
+ struct gl_renderbuffer *depthRb
+ = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+ struct gl_renderbuffer *stencilRb
+ = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+ GLbitfield quad_buffers = 0;
+ GLbitfield clear_buffers = 0;
+ GLuint i;
+
+ /* This makes sure the pipe has the latest scissor, etc values */
+ st_validate_state( st );
+
+ if (mask & BUFFER_BITS_COLOR) {
+ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+ GLuint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
+
+ if (mask & (1 << b)) {
+ struct gl_renderbuffer *rb
+ = ctx->DrawBuffer->Attachment[b].Renderbuffer;
+ struct st_renderbuffer *strb;
+
+ assert(rb);
+
+ strb = st_renderbuffer(rb);
+
+ if (!strb->surface)
+ continue;
+
+ if (check_clear_color_with_quad( ctx, rb ))
+ quad_buffers |= PIPE_CLEAR_COLOR;
+ else
+ clear_buffers |= PIPE_CLEAR_COLOR;
+ }
+ }
+ }
+
+ if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) {
+ /* clearing combined depth + stencil */
+ struct st_renderbuffer *strb = st_renderbuffer(depthRb);
+
+ if (strb->surface) {
+ if (check_clear_depth_stencil_with_quad(ctx, depthRb))
+ quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ else
+ clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ }
+ }
+ else {
+ /* separate depth/stencil clears */
+ if (mask & BUFFER_BIT_DEPTH) {
+ struct st_renderbuffer *strb = st_renderbuffer(depthRb);
+
+ if (strb->surface) {
+ if (check_clear_depth_with_quad(ctx, depthRb))
+ quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ else
+ clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ }
+ }
+ if (mask & BUFFER_BIT_STENCIL) {
+ struct st_renderbuffer *strb = st_renderbuffer(stencilRb);
+
+ if (strb->surface) {
+ if (check_clear_stencil_with_quad(ctx, stencilRb))
+ quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ else
+ clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+ }
+ }
+ }
+
+ /*
+ * If we're going to use clear_with_quad() for any reason, use it for
+ * everything possible.
+ */
+ if (quad_buffers) {
+ quad_buffers |= clear_buffers;
+ clear_with_quad(ctx,
+ quad_buffers & PIPE_CLEAR_COLOR,
+ mask & BUFFER_BIT_DEPTH,
+ mask & BUFFER_BIT_STENCIL);
+ } else if (clear_buffers)
+ ctx->st->pipe->clear(ctx->st->pipe, clear_buffers, ctx->Color.ClearColor,
+ ctx->Depth.Clear, ctx->Stencil.Clear);
+
+ if (mask & BUFFER_BIT_ACCUM)
+ st_clear_accum_buffer(ctx,
+ ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
+}
+
+
+void st_init_clear_functions(struct dd_function_table *functions)
+{
+ functions->Clear = st_clear;
+}
diff --git a/src/mesa/state_tracker/st_cb_clear.h b/src/mesa/state_tracker/st_cb_clear.h
new file mode 100644
index 0000000000..bc035ac25c
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_clear.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_CLEAR_H
+#define ST_CB_CLEAR_H
+
+
+extern void
+st_init_clear(struct st_context *st);
+
+
+extern void
+st_destroy_clear(struct st_context *st);
+
+extern void
+st_flush_clear(struct st_context *st);
+
+
+extern void
+st_init_clear_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_CLEAR_H */
+
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
new file mode 100644
index 0000000000..99f3ba678b
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -0,0 +1,1146 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/bufferobj.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "main/state.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_atom_constbuf.h"
+#include "st_draw.h"
+#include "st_program.h"
+#include "st_cb_drawpixels.h"
+#include "st_cb_readpixels.h"
+#include "st_cb_fbo.h"
+#include "st_cb_texture.h"
+#include "st_draw.h"
+#include "st_format.h"
+#include "st_mesa_to_tgsi.h"
+#include "st_texture.h"
+#include "st_inlines.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+#include "util/u_draw_quad.h"
+#include "util/u_math.h"
+#include "shader/prog_instruction.h"
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Check if the given program is:
+ * 0: MOVE result.color, fragment.color;
+ * 1: END;
+ */
+static GLboolean
+is_passthrough_program(const struct gl_fragment_program *prog)
+{
+ if (prog->Base.NumInstructions == 2) {
+ const struct prog_instruction *inst = prog->Base.Instructions;
+ if (inst[0].Opcode == OPCODE_MOV &&
+ inst[1].Opcode == OPCODE_END &&
+ inst[0].DstReg.File == PROGRAM_OUTPUT &&
+ inst[0].DstReg.Index == FRAG_RESULT_COLOR &&
+ inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
+ inst[0].SrcReg[0].File == PROGRAM_INPUT &&
+ inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
+ inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+
+
+/**
+ * Make fragment shader for glDraw/CopyPixels. This shader is made
+ * by combining the pixel transfer shader with the user-defined shader.
+ */
+static struct st_fragment_program *
+combined_drawpix_fragment_program(GLcontext *ctx)
+{
+ struct st_context *st = st_context(ctx);
+ struct st_fragment_program *stfp;
+
+ if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
+ && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
+ /* the pixel tranfer program has not changed and the user-defined
+ * program has not changed, so re-use the combined program.
+ */
+ stfp = st->pixel_xfer.combined_prog;
+ }
+ else {
+ /* Concatenate the pixel transfer program with the current user-
+ * defined program.
+ */
+ if (is_passthrough_program(&st->fp->Base)) {
+ stfp = (struct st_fragment_program *)
+ _mesa_clone_program(ctx, &st->pixel_xfer.program->Base.Base);
+ }
+ else {
+#if 0
+ printf("Base program:\n");
+ _mesa_print_program(&st->fp->Base.Base);
+ printf("DrawPix program:\n");
+ _mesa_print_program(&st->pixel_xfer.program->Base.Base);
+#endif
+ stfp = (struct st_fragment_program *)
+ _mesa_combine_programs(ctx,
+ &st->pixel_xfer.program->Base.Base,
+ &st->fp->Base.Base);
+ }
+
+#if 0
+ {
+ struct gl_program *p = &stfp->Base.Base;
+ printf("Combined DrawPixels program:\n");
+ _mesa_print_program(p);
+ printf("InputsRead: 0x%x\n", p->InputsRead);
+ printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
+ _mesa_print_parameter_list(p->Parameters);
+ }
+#endif
+
+ /* translate to TGSI tokens */
+ st_translate_fragment_program(st, stfp, NULL);
+
+ /* save new program, update serial numbers */
+ st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
+ st->pixel_xfer.user_prog_sn = st->fp->serialNo;
+ st->pixel_xfer.combined_prog_sn = stfp->serialNo;
+ /* can't reference new program directly, already have a reference on it */
+ st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
+ st->pixel_xfer.combined_prog = stfp;
+ }
+
+ /* Ideally we'd have updated the pipe constants during the normal
+ * st/atom mechanism. But we can't since this is specific to glDrawPixels.
+ */
+ st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
+
+ return stfp;
+}
+
+
+/**
+ * Create fragment shader that does a TEX() instruction to get a Z
+ * value, then writes to FRAG_RESULT_DEPTH.
+ * Pass fragment color through as-is.
+ */
+static struct st_fragment_program *
+make_fragment_shader_z(struct st_context *st)
+{
+ GLcontext *ctx = st->ctx;
+ struct gl_program *p;
+ GLuint ic = 0;
+
+ if (st->drawpix.z_shader) {
+ return st->drawpix.z_shader;
+ }
+
+ /*
+ * Create shader now
+ */
+ p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ if (!p)
+ return NULL;
+
+ p->NumInstructions = 3;
+
+ p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
+ if (!p->Instructions) {
+ ctx->Driver.DeleteProgram(ctx, p);
+ return NULL;
+ }
+ _mesa_init_instructions(p->Instructions, p->NumInstructions);
+
+ /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
+ p->Instructions[ic].Opcode = OPCODE_TEX;
+ p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH;
+ p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
+ p->Instructions[ic].TexSrcUnit = 0;
+ p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* MOV result.color, fragment.color */
+ p->Instructions[ic].Opcode = OPCODE_MOV;
+ p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLOR;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
+ ic++;
+
+ /* END; */
+ p->Instructions[ic++].Opcode = OPCODE_END;
+
+ assert(ic == p->NumInstructions);
+
+ p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
+ p->OutputsWritten = (1 << FRAG_RESULT_COLOR) | (1 << FRAG_RESULT_DEPTH);
+ p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
+
+ st->drawpix.z_shader = (struct st_fragment_program *) p;
+ st_translate_fragment_program(st, st->drawpix.z_shader, NULL);
+
+ return st->drawpix.z_shader;
+}
+
+
+
+/**
+ * Create a simple vertex shader that just passes through the
+ * vertex position and texcoord (and optionally, color).
+ */
+static struct st_vertex_program *
+st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
+{
+ GLcontext *ctx = st->ctx;
+ struct st_vertex_program *stvp;
+ struct gl_program *p;
+ GLuint ic = 0;
+
+ if (st->drawpix.vert_shaders[passColor])
+ return st->drawpix.vert_shaders[passColor];
+
+ /*
+ * Create shader now
+ */
+ p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+ if (!p)
+ return NULL;
+
+ if (passColor)
+ p->NumInstructions = 4;
+ else
+ p->NumInstructions = 3;
+
+ p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
+ if (!p->Instructions) {
+ ctx->Driver.DeleteProgram(ctx, p);
+ return NULL;
+ }
+ _mesa_init_instructions(p->Instructions, p->NumInstructions);
+ /* MOV result.pos, vertex.pos; */
+ p->Instructions[0].Opcode = OPCODE_MOV;
+ p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
+ p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
+ /* MOV result.texcoord0, vertex.texcoord0; */
+ p->Instructions[1].Opcode = OPCODE_MOV;
+ p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
+ p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
+ ic = 2;
+ if (passColor) {
+ /* MOV result.color0, vertex.color0; */
+ p->Instructions[ic].Opcode = OPCODE_MOV;
+ p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
+ p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
+ ic++;
+ }
+
+ /* END; */
+ p->Instructions[ic].Opcode = OPCODE_END;
+ ic++;
+
+ assert(ic == p->NumInstructions);
+
+ p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
+ p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
+ (1 << VERT_RESULT_HPOS));
+ if (passColor) {
+ p->InputsRead |= VERT_BIT_COLOR0;
+ p->OutputsWritten |= (1 << VERT_RESULT_COL0);
+ }
+
+ stvp = (struct st_vertex_program *) p;
+ st_translate_vertex_program(st, stvp, NULL, NULL, NULL);
+
+ st->drawpix.vert_shaders[passColor] = stvp;
+
+ return stvp;
+}
+
+
+static GLenum
+_mesa_base_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH_COMPONENT:
+ return GL_DEPTH_COMPONENT;
+ case GL_DEPTH_STENCIL:
+ return GL_DEPTH_STENCIL;
+ case GL_STENCIL_INDEX:
+ return GL_STENCIL_INDEX;
+ default:
+ return GL_RGBA;
+ }
+}
+
+
+/**
+ * Make texture containing an image for glDrawPixels image.
+ * If 'pixels' is NULL, leave the texture image data undefined.
+ */
+static struct pipe_texture *
+make_texture(struct st_context *st,
+ GLsizei width, GLsizei height, GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ GLcontext *ctx = st->ctx;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const struct gl_texture_format *mformat;
+ struct pipe_texture *pt;
+ enum pipe_format pipeFormat;
+ GLuint cpp;
+ GLenum baseFormat;
+ int ptw, pth;
+
+ baseFormat = _mesa_base_format(format);
+
+ mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type);
+ assert(mformat);
+
+ pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat);
+ assert(pipeFormat);
+ cpp = st_sizeof_format(pipeFormat);
+
+ pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
+ if (!pixels)
+ return NULL;
+
+ /* Need to use POT texture? */
+ ptw = width;
+ pth = height;
+ if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) {
+ int l2pt, maxSize;
+
+ l2pt = util_logbase2(width);
+ if (1<<l2pt != width) {
+ ptw = 1<<(l2pt+1);
+ }
+ l2pt = util_logbase2(height);
+ if (1<<l2pt != height) {
+ pth = 1<<(l2pt+1);
+ }
+
+ /* Check against maximum texture size */
+ maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+ assert(ptw <= maxSize);
+ assert(pth <= maxSize);
+ }
+
+ pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, ptw, pth, 1,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ if (!pt) {
+ _mesa_unmap_pbo_source(ctx, unpack);
+ return NULL;
+ }
+
+ {
+ struct pipe_transfer *transfer;
+ static const GLuint dstImageOffsets = 0;
+ GLboolean success;
+ GLubyte *dest;
+ const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
+
+ /* we'll do pixel transfer in a fragment shader */
+ ctx->_ImageTransferState = 0x0;
+
+ transfer = st_no_flush_get_tex_transfer(st, pt, 0, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ width, height);
+
+ /* map texture transfer */
+ dest = screen->transfer_map(screen, transfer);
+
+ /* Put image into texture transfer.
+ * Note that the image is actually going to be upside down in
+ * the texture. We deal with that with texcoords.
+ */
+ success = mformat->StoreImage(ctx, 2, /* dims */
+ baseFormat, /* baseInternalFormat */
+ mformat, /* gl_texture_format */
+ dest, /* dest */
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ transfer->stride, /* dstRowStride, bytes */
+ &dstImageOffsets, /* dstImageOffsets */
+ width, height, 1, /* size */
+ format, type, /* src format/type */
+ pixels, /* data source */
+ unpack);
+
+ /* unmap */
+ screen->transfer_unmap(screen, transfer);
+ screen->tex_transfer_destroy(transfer);
+
+ assert(success);
+
+ /* restore */
+ ctx->_ImageTransferState = imageTransferStateSave;
+ }
+
+ _mesa_unmap_pbo_source(ctx, unpack);
+
+ return pt;
+}
+
+
+/**
+ * Draw quad with texcoords and optional color.
+ * Coords are window coords with y=0=bottom.
+ * \param color may be null
+ * \param invertTex if true, flip texcoords vertically
+ */
+static void
+draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
+ GLfloat x1, GLfloat y1, const GLfloat *color,
+ GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
+
+ /* setup vertex data */
+ {
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLfloat fb_width = (GLfloat) fb->Width;
+ const GLfloat fb_height = (GLfloat) fb->Height;
+ const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
+ const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
+ const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
+ const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
+ const GLfloat sLeft = 0.0f, sRight = maxXcoord;
+ const GLfloat tTop = invertTex ? maxYcoord : 0.0f;
+ const GLfloat tBot = invertTex ? 0.0f : maxYcoord;
+ GLuint tex, i;
+
+ /* upper-left */
+ verts[0][0][0] = clip_x0; /* v[0].attr[0].x */
+ verts[0][0][1] = clip_y0; /* v[0].attr[0].y */
+
+ /* upper-right */
+ verts[1][0][0] = clip_x1;
+ verts[1][0][1] = clip_y0;
+
+ /* lower-right */
+ verts[2][0][0] = clip_x1;
+ verts[2][0][1] = clip_y1;
+
+ /* lower-left */
+ verts[3][0][0] = clip_x0;
+ verts[3][0][1] = clip_y1;
+
+ tex = color ? 2 : 1;
+ verts[0][tex][0] = sLeft; /* v[0].attr[tex].s */
+ verts[0][tex][1] = tTop; /* v[0].attr[tex].t */
+ verts[1][tex][0] = sRight;
+ verts[1][tex][1] = tTop;
+ verts[2][tex][0] = sRight;
+ verts[2][tex][1] = tBot;
+ verts[3][tex][0] = sLeft;
+ verts[3][tex][1] = tBot;
+
+ /* same for all verts: */
+ if (color) {
+ for (i = 0; i < 4; i++) {
+ verts[i][0][2] = z; /*Z*/
+ verts[i][0][3] = 1.0f; /*W*/
+ verts[i][1][0] = color[0];
+ verts[i][1][1] = color[1];
+ verts[i][1][2] = color[2];
+ verts[i][1][3] = color[3];
+ verts[i][2][2] = 0.0f; /*R*/
+ verts[i][2][3] = 1.0f; /*Q*/
+ }
+ }
+ else {
+ for (i = 0; i < 4; i++) {
+ verts[i][0][2] = z; /*Z*/
+ verts[i][0][3] = 1.0f; /*W*/
+ verts[i][1][2] = 0.0f; /*R*/
+ verts[i][1][3] = 1.0f; /*Q*/
+ }
+ }
+ }
+
+ {
+ struct pipe_buffer *buf;
+
+ /* allocate/load buffer object with vertex data */
+ buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(verts));
+ st_no_flush_pipe_buffer_write(st, buf, 0, sizeof(verts), verts);
+
+ util_draw_vertex_buffer(pipe, buf, 0,
+ PIPE_PRIM_QUADS,
+ 4, /* verts */
+ 3); /* attribs/vert */
+ pipe_buffer_reference(&buf, NULL);
+ }
+}
+
+
+
+static void
+draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
+ GLsizei width, GLsizei height,
+ GLfloat zoomX, GLfloat zoomY,
+ struct pipe_texture *pt,
+ struct st_vertex_program *stvp,
+ struct st_fragment_program *stfp,
+ const GLfloat *color,
+ GLboolean invertTex)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct cso_context *cso = st->cso_context;
+ GLfloat x0, y0, x1, y1;
+ GLsizei maxSize;
+
+ /* limit checks */
+ /* XXX if DrawPixels image is larger than max texture size, break
+ * it up into chunks.
+ */
+ maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+ assert(width <= maxSize);
+ assert(height <= maxSize);
+
+ cso_save_rasterizer(cso);
+ cso_save_viewport(cso);
+ cso_save_samplers(cso);
+ cso_save_sampler_textures(cso);
+ cso_save_fragment_shader(cso);
+ cso_save_vertex_shader(cso);
+
+ /* rasterizer state: just scissor */
+ {
+ struct pipe_rasterizer_state rasterizer;
+ memset(&rasterizer, 0, sizeof(rasterizer));
+ rasterizer.gl_rasterization_rules = 1;
+ rasterizer.scissor = ctx->Scissor.Enabled;
+ cso_set_rasterizer(cso, &rasterizer);
+ }
+
+ /* fragment shader state: TEX lookup program */
+ cso_set_fragment_shader_handle(cso, stfp->driver_shader);
+
+ /* vertex shader state: position + texcoord pass-through */
+ cso_set_vertex_shader_handle(cso, stvp->driver_shader);
+
+
+ /* texture sampling state: */
+ {
+ struct pipe_sampler_state sampler;
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
+ sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.normalized_coords = 1;
+
+ cso_single_sampler(cso, 0, &sampler);
+ if (st->pixel_xfer.pixelmap_enabled) {
+ cso_single_sampler(cso, 1, &sampler);
+ }
+ cso_single_sampler_done(cso);
+ }
+
+ /* viewport state: viewport matching window dims */
+ {
+ const float width = (float) ctx->DrawBuffer->Width;
+ const float height = (float) ctx->DrawBuffer->Height;
+ struct pipe_viewport_state vp;
+ vp.scale[0] = 0.5f * width;
+ vp.scale[1] = -0.5f * height;
+ vp.scale[2] = 1.0f;
+ vp.scale[3] = 1.0f;
+ vp.translate[0] = 0.5f * width;
+ vp.translate[1] = 0.5f * height;
+ vp.translate[2] = 0.0f;
+ vp.translate[3] = 0.0f;
+ cso_set_viewport(cso, &vp);
+ }
+
+ /* texture state: */
+ if (st->pixel_xfer.pixelmap_enabled) {
+ struct pipe_texture *textures[2];
+ textures[0] = pt;
+ textures[1] = st->pixel_xfer.pixelmap_texture;
+ pipe->set_sampler_textures(pipe, 2, textures);
+ }
+ else {
+ pipe->set_sampler_textures(pipe, 1, &pt);
+ }
+
+ /* Compute window coords (y=0=bottom) with pixel zoom.
+ * Recall that these coords are transformed by the current
+ * vertex shader and viewport transformation.
+ */
+ x0 = (GLfloat) x;
+ x1 = x + width * ctx->Pixel.ZoomX;
+ y0 = (GLfloat) y;
+ y1 = y + height * ctx->Pixel.ZoomY;
+
+ draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex,
+ (GLfloat) width / pt->width[0],
+ (GLfloat) height / pt->height[0]);
+
+ /* restore state */
+ cso_restore_rasterizer(cso);
+ cso_restore_viewport(cso);
+ cso_restore_samplers(cso);
+ cso_restore_sampler_textures(cso);
+ cso_restore_fragment_shader(cso);
+ cso_restore_vertex_shader(cso);
+}
+
+
+static void
+draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct st_renderbuffer *strb;
+ enum pipe_transfer_usage usage;
+ struct pipe_transfer *pt;
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
+ GLint skipPixels;
+ ubyte *stmap;
+
+ strb = st_renderbuffer(ctx->DrawBuffer->
+ Attachment[BUFFER_STENCIL].Renderbuffer);
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ y = ctx->DrawBuffer->Height - y - height;
+ }
+
+ if(format != GL_DEPTH_STENCIL &&
+ pf_get_component_bits( strb->format, PIPE_FORMAT_COMP_Z ) != 0)
+ usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ usage = PIPE_TRANSFER_WRITE;
+
+ pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, 0, 0, 0,
+ usage, x, y,
+ width, height);
+
+ stmap = screen->transfer_map(screen, pt);
+
+ pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
+ assert(pixels);
+
+ /* if width > MAX_WIDTH, have to process image in chunks */
+ skipPixels = 0;
+ while (skipPixels < width) {
+ const GLint spanX = skipPixels;
+ const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLubyte sValues[MAX_WIDTH];
+ GLuint zValues[MAX_WIDTH];
+ GLenum destType = GL_UNSIGNED_BYTE;
+ const GLvoid *source = _mesa_image_address2d(unpack, pixels,
+ width, height,
+ format, type,
+ row, skipPixels);
+ _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues,
+ type, source, unpack,
+ ctx->_ImageTransferState);
+
+ if (format == GL_DEPTH_STENCIL) {
+ _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues,
+ (1 << 24) - 1, type, source, unpack);
+ }
+
+ if (zoom) {
+ _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
+ "zoom not complete");
+ }
+
+ {
+ GLint spanY;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ spanY = height - row - 1;
+ }
+ else {
+ spanY = row;
+ }
+
+ /* now pack the stencil (and Z) values in the dest format */
+ switch (pt->format) {
+ case PIPE_FORMAT_S8_UNORM:
+ {
+ ubyte *dest = stmap + spanY * pt->stride + spanX;
+ assert(usage == PIPE_TRANSFER_WRITE);
+ memcpy(dest, sValues, spanWidth);
+ }
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ if (format == GL_DEPTH_STENCIL) {
+ uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
+ GLint k;
+ assert(usage == PIPE_TRANSFER_WRITE);
+ for (k = 0; k < spanWidth; k++) {
+ dest[k] = zValues[k] | (sValues[k] << 24);
+ }
+ }
+ else {
+ uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
+ GLint k;
+ assert(usage == PIPE_TRANSFER_READ_WRITE);
+ for (k = 0; k < spanWidth; k++) {
+ dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ if (format == GL_DEPTH_STENCIL) {
+ uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
+ GLint k;
+ assert(usage == PIPE_TRANSFER_WRITE);
+ for (k = 0; k < spanWidth; k++) {
+ dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
+ }
+ }
+ else {
+ uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
+ GLint k;
+ assert(usage == PIPE_TRANSFER_READ_WRITE);
+ for (k = 0; k < spanWidth; k++) {
+ dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+ skipPixels += spanWidth;
+ }
+
+ _mesa_unmap_pbo_source(ctx, unpack);
+
+ /* unmap the stencil buffer */
+ screen->transfer_unmap(screen, pt);
+ screen->tex_transfer_destroy(pt);
+}
+
+
+/**
+ * Called via ctx->Driver.DrawPixels()
+ */
+static void
+st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
+{
+ struct st_fragment_program *stfp;
+ struct st_vertex_program *stvp;
+ struct st_context *st = st_context(ctx);
+ struct pipe_surface *ps;
+ const GLfloat *color;
+
+ if (format == GL_STENCIL_INDEX ||
+ format == GL_DEPTH_STENCIL) {
+ draw_stencil_pixels(ctx, x, y, width, height, format, type,
+ unpack, pixels);
+ return;
+ }
+
+ /* Mesa state should be up to date by now */
+ assert(ctx->NewState == 0x0);
+
+ st_validate_state(st);
+
+ if (format == GL_DEPTH_COMPONENT) {
+ ps = st->state.framebuffer.zsbuf;
+ stfp = make_fragment_shader_z(st);
+ stvp = st_make_passthrough_vertex_shader(st, GL_TRUE);
+ color = ctx->Current.RasterColor;
+ }
+ else {
+ ps = st->state.framebuffer.cbufs[0];
+ stfp = combined_drawpix_fragment_program(ctx);
+ stvp = st_make_passthrough_vertex_shader(st, GL_FALSE);
+ color = NULL;
+ }
+
+ /* draw with textured quad */
+ {
+ struct pipe_texture *pt
+ = make_texture(st, width, height, format, type, unpack, pixels);
+ if (pt) {
+ draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
+ width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
+ pt, stvp, stfp, color, GL_FALSE);
+ pipe_texture_reference(&pt, NULL);
+ }
+ }
+}
+
+
+
+static void
+copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty)
+{
+ struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ enum pipe_transfer_usage usage;
+ struct pipe_transfer *ptDraw;
+ ubyte *drawMap;
+ ubyte *buffer;
+ int i;
+
+ buffer = _mesa_malloc(width * height * sizeof(ubyte));
+ if (!buffer) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
+ return;
+ }
+
+ /* this will do stencil pixel transfer ops */
+ st_read_stencil_pixels(ctx, srcx, srcy, width, height,
+ GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
+ &ctx->DefaultPacking, buffer);
+
+ if(pf_get_component_bits( rbDraw->format, PIPE_FORMAT_COMP_Z ) != 0)
+ usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ usage = PIPE_TRANSFER_WRITE;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ dsty = rbDraw->Base.Height - dsty - height;
+ }
+
+ ptDraw = st_cond_flush_get_tex_transfer(st_context(ctx),
+ rbDraw->texture, 0, 0, 0,
+ usage, dstx, dsty,
+ width, height);
+
+ assert(ptDraw->block.width == 1);
+ assert(ptDraw->block.height == 1);
+
+ /* map the stencil buffer */
+ drawMap = screen->transfer_map(screen, ptDraw);
+
+ /* draw */
+ /* XXX PixelZoom not handled yet */
+ for (i = 0; i < height; i++) {
+ ubyte *dst;
+ const ubyte *src;
+ int y;
+
+ y = i;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ y = height - y - 1;
+ }
+
+ dst = drawMap + y * ptDraw->stride;
+ src = buffer + i * width;
+
+ switch (ptDraw->format) {
+ case PIPE_FORMAT_S8Z24_UNORM:
+ {
+ uint *dst4 = (uint *) dst;
+ int j;
+ assert(usage == PIPE_TRANSFER_READ_WRITE);
+ for (j = 0; j < width; j++) {
+ *dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
+ dst4++;
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ {
+ uint *dst4 = (uint *) dst;
+ int j;
+ assert(usage == PIPE_TRANSFER_READ_WRITE);
+ for (j = 0; j < width; j++) {
+ *dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff);
+ dst4++;
+ }
+ }
+ break;
+ case PIPE_FORMAT_S8_UNORM:
+ assert(usage == PIPE_TRANSFER_WRITE);
+ memcpy(dst, src, width);
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ _mesa_free(buffer);
+
+ /* unmap the stencil buffer */
+ screen->transfer_unmap(screen, ptDraw);
+ screen->tex_transfer_destroy(ptDraw);
+}
+
+
+static void
+st_CopyPixels(GLcontext *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 pipe_screen *screen = pipe->screen;
+ struct st_renderbuffer *rbRead;
+ struct st_vertex_program *stvp;
+ struct st_fragment_program *stfp;
+ struct pipe_texture *pt;
+ GLfloat *color;
+ enum pipe_format srcFormat, texFormat;
+ int ptw, pth;
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ st_validate_state(st);
+
+ if (srcx < 0) {
+ width -= -srcx;
+ dstx += -srcx;
+ srcx = 0;
+ }
+
+ if (srcy < 0) {
+ height -= -srcy;
+ dsty += -srcy;
+ srcy = 0;
+ }
+
+ if (dstx < 0) {
+ width -= -dstx;
+ srcx += -dstx;
+ dstx = 0;
+ }
+
+ if (dsty < 0) {
+ height -= -dsty;
+ srcy += -dsty;
+ dsty = 0;
+ }
+
+ if (width < 0 || height < 0)
+ return;
+
+
+ if (type == GL_STENCIL) {
+ /* can't use texturing to do stencil */
+ copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
+ return;
+ }
+
+ if (type == GL_COLOR) {
+ rbRead = st_get_color_read_renderbuffer(ctx);
+ color = NULL;
+ stfp = combined_drawpix_fragment_program(ctx);
+ stvp = st_make_passthrough_vertex_shader(st, GL_FALSE);
+ }
+ else {
+ assert(type == GL_DEPTH);
+ rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
+ color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ stfp = make_fragment_shader_z(st);
+ stvp = st_make_passthrough_vertex_shader(st, GL_TRUE);
+ }
+
+ srcFormat = rbRead->texture->format;
+
+ if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ texFormat = srcFormat;
+ }
+ else {
+ /* srcFormat can't be used as a texture format */
+ if (type == GL_DEPTH) {
+ texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL);
+ assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */
+ }
+ else {
+ /* default color format */
+ texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ assert(texFormat != PIPE_FORMAT_NONE);
+ }
+ }
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ srcy = ctx->DrawBuffer->Height - srcy - height;
+
+ if (srcy < 0) {
+ height -= -srcy;
+ srcy = 0;
+ }
+
+ if (height < 0)
+ return;
+ }
+
+ /* Need to use POT texture? */
+ ptw = width;
+ pth = height;
+ if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) {
+ int l2pt, maxSize;
+
+ l2pt = util_logbase2(width);
+ if (1<<l2pt != width) {
+ ptw = 1<<(l2pt+1);
+ }
+ l2pt = util_logbase2(height);
+ if (1<<l2pt != height) {
+ pth = 1<<(l2pt+1);
+ }
+
+ /* Check against maximum texture size */
+ maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+ assert(ptw <= maxSize);
+ assert(pth <= maxSize);
+ }
+
+ pt = st_texture_create(st, PIPE_TEXTURE_2D, texFormat, 0,
+ ptw, pth, 1,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ if (!pt)
+ return;
+
+
+ if (srcFormat == texFormat) {
+ /* copy source framebuffer surface into mipmap/texture */
+ struct pipe_surface *psRead = screen->get_tex_surface(screen,
+ rbRead->texture, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ);
+ struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE );
+ pipe->surface_copy(pipe,
+ psTex, /* dest */
+ 0, 0, /* destx/y */
+ psRead,
+ srcx, srcy, width, height);
+ pipe_surface_reference(&psRead, NULL);
+ pipe_surface_reference(&psTex, NULL);
+ }
+ else {
+ /* CPU-based fallback/conversion */
+ struct pipe_transfer *ptRead =
+ st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0,
+ PIPE_TRANSFER_READ, srcx, srcy, width,
+ height);
+ struct pipe_transfer *ptTex;
+ enum pipe_transfer_usage transfer_usage;
+
+ if (type == GL_DEPTH && pf_is_depth_and_stencil(pt->format))
+ transfer_usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ transfer_usage = PIPE_TRANSFER_WRITE;
+
+ ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage,
+ 0, 0, width, height);
+
+ if (type == GL_COLOR) {
+ /* alternate path using get/put_tile() */
+ GLfloat *buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+
+ pipe_get_tile_rgba(ptRead, 0, 0, width, height, buf);
+ pipe_put_tile_rgba(ptTex, 0, 0, width, height, buf);
+
+ _mesa_free(buf);
+ }
+ else {
+ /* GL_DEPTH */
+ GLuint *buf = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
+ pipe_get_tile_z(ptRead, 0, 0, width, height, buf);
+ pipe_put_tile_z(ptTex, 0, 0, width, height, buf);
+ _mesa_free(buf);
+ }
+
+ screen->tex_transfer_destroy(ptRead);
+ screen->tex_transfer_destroy(ptTex);
+ }
+
+ /* draw textured quad */
+ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
+ width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
+ pt, stvp, stfp, color, GL_TRUE);
+
+ pipe_texture_reference(&pt, NULL);
+}
+
+
+
+void st_init_drawpixels_functions(struct dd_function_table *functions)
+{
+ functions->DrawPixels = st_DrawPixels;
+ functions->CopyPixels = st_CopyPixels;
+}
+
+
+void
+st_destroy_drawpix(struct st_context *st)
+{
+ st_reference_fragprog(st, &st->drawpix.z_shader, NULL);
+ st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
+ st_reference_vertprog(st, &st->drawpix.vert_shaders[0], NULL);
+ st_reference_vertprog(st, &st->drawpix.vert_shaders[1], NULL);
+}
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h
new file mode 100644
index 0000000000..26fe864d18
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_drawpixels.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_DRAWPIXELS_H
+#define ST_CB_DRAWPIXELS_H
+
+
+extern void st_init_drawpixels_functions(struct dd_function_table *functions);
+
+extern void
+st_destroy_drawpix(struct st_context *st);
+
+
+#endif /* ST_CB_DRAWPIXELS_H */
diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c
new file mode 100644
index 0000000000..3b98b9c40b
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_drawtex.c
@@ -0,0 +1,297 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+
+/**
+ * Implementation of glDrawTex() for GL_OES_draw_tex
+ */
+
+
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/bufferobj.h"
+#include "main/drawtex.h"
+#include "main/macros.h"
+#include "main/state.h"
+#include "main/texformat.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_atom_constbuf.h"
+#include "st_draw.h"
+#include "st_cb_drawtex.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_tile.h"
+#include "util/u_draw_quad.h"
+#include "util/u_simple_shaders.h"
+
+#include "cso_cache/cso_context.h"
+
+
+struct cached_shader
+{
+ //struct pipe_shader_state shader;
+ void *handle;
+
+ uint num_attribs;
+ uint semantic_names[2 + MAX_TEXTURE_UNITS];
+ uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
+};
+
+#define MAX_SHADERS (2 * MAX_TEXTURE_UNITS)
+
+/**
+ * Simple linear list cache.
+ * Most of the time there'll only be one cached shader.
+ */
+static struct cached_shader CachedShaders[MAX_SHADERS];
+static GLuint NumCachedShaders = 0;
+
+
+#if FEATURE_OES_draw_texture
+
+
+static void *
+lookup_shader(struct pipe_context *pipe,
+ uint num_attribs,
+ const uint *semantic_names,
+ const uint *semantic_indexes)
+{
+ GLuint i, j;
+
+ /* look for existing shader with same attributes */
+ for (i = 0; i < NumCachedShaders; i++) {
+ if (CachedShaders[i].num_attribs == num_attribs) {
+ GLboolean match = GL_TRUE;
+ for (j = 0; j < num_attribs; j++) {
+ if (semantic_names[j] != CachedShaders[i].semantic_names[j] ||
+ semantic_indexes[j] != CachedShaders[i].semantic_indexes[j]) {
+ match = GL_FALSE;
+ break;
+ }
+ }
+ if (match)
+ return CachedShaders[i].handle;
+ }
+ }
+
+ /* not found - create new one now */
+ if (NumCachedShaders >= MAX_SHADERS) {
+ return NULL;
+ }
+
+ CachedShaders[i].num_attribs = num_attribs;
+ for (j = 0; j < num_attribs; j++) {
+ CachedShaders[i].semantic_names[j] = semantic_names[j];
+ CachedShaders[i].semantic_indexes[j] = semantic_indexes[j];
+ }
+
+ CachedShaders[i].handle =
+ util_make_vertex_passthrough_shader(pipe,
+ num_attribs,
+ semantic_names,
+ semantic_indexes);
+ NumCachedShaders++;
+
+ return CachedShaders[i].handle;
+}
+
+static void
+st_DrawTex(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat width, GLfloat height)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct cso_context *cso = ctx->st->cso_context;
+ struct pipe_buffer *vbuffer;
+ GLuint i, numTexCoords, numAttribs;
+ GLboolean emitColor;
+ uint semantic_names[2 + MAX_TEXTURE_UNITS];
+ uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
+ GLbitfield inputs = VERT_BIT_POS;
+
+ /* determine if we need vertex color */
+ if (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_COL0)
+ emitColor = GL_TRUE;
+ else
+ emitColor = GL_FALSE;
+
+ /* determine how many enabled sets of texcoords */
+ numTexCoords = 0;
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
+ inputs |= VERT_BIT_TEX(i);
+ numTexCoords++;
+ }
+ }
+
+ /* total number of attributes per vertex */
+ numAttribs = 1 + emitColor + numTexCoords;
+
+
+ /* create the vertex buffer */
+ vbuffer = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
+ numAttribs * 4 * 4 * sizeof(GLfloat));
+
+ /* load vertex buffer */
+ {
+#define SET_ATTRIB(VERT, ATTR, X, Y, Z, W) \
+ do { \
+ GLuint k = (((VERT) * numAttribs + (ATTR)) * 4); \
+ assert(k < 4 * 4 * numAttribs); \
+ vbuf[k + 0] = X; \
+ vbuf[k + 1] = Y; \
+ vbuf[k + 2] = Z; \
+ vbuf[k + 3] = W; \
+ } while (0)
+
+ const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height;
+ GLfloat *vbuf = (GLfloat *) pipe_buffer_map(pipe->screen, vbuffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ GLuint attr;
+
+ z = CLAMP(z, 0.0f, 1.0f);
+
+ /* positions (in clip coords) */
+ {
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLfloat fb_width = (GLfloat)fb->Width;
+ const GLfloat fb_height = (GLfloat)fb->Height;
+
+ const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
+ const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
+ const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
+
+ SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f); /* lower left */
+ SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f); /* lower right */
+ SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f); /* upper right */
+ SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f); /* upper left */
+
+ semantic_names[0] = TGSI_SEMANTIC_POSITION;
+ semantic_indexes[0] = 0;
+ }
+
+ /* colors */
+ if (emitColor) {
+ const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]);
+ SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]);
+ SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]);
+ SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]);
+ semantic_names[1] = TGSI_SEMANTIC_COLOR;
+ semantic_indexes[1] = 0;
+ attr = 2;
+ }
+ else {
+ attr = 1;
+ }
+
+ /* texcoords */
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
+ struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current;
+ struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
+ const GLfloat wt = (GLfloat) img->Width;
+ const GLfloat ht = (GLfloat) img->Height;
+ const GLfloat s0 = obj->CropRect[0] / wt;
+ const GLfloat t0 = obj->CropRect[1] / ht;
+ const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt;
+ const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht;
+
+ /*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/
+ SET_ATTRIB(0, attr, s0, t0, 0.0f, 1.0f); /* lower left */
+ SET_ATTRIB(1, attr, s1, t0, 0.0f, 1.0f); /* lower right */
+ SET_ATTRIB(2, attr, s1, t1, 0.0f, 1.0f); /* upper right */
+ SET_ATTRIB(3, attr, s0, t1, 0.0f, 1.0f); /* upper left */
+
+ semantic_names[attr] = TGSI_SEMANTIC_GENERIC;
+ semantic_indexes[attr] = 0;
+
+ attr++;
+ }
+ }
+
+ pipe_buffer_unmap(pipe->screen, vbuffer);
+
+#undef SET_ATTRIB
+ }
+
+
+ cso_save_viewport(cso);
+ cso_save_vertex_shader(cso);
+
+ {
+ void *vs = lookup_shader(pipe, numAttribs,
+ semantic_names, semantic_indexes);
+ cso_set_vertex_shader_handle(cso, vs);
+ }
+
+ /* viewport state: viewport matching window dims */
+ {
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
+ const GLfloat width = (GLfloat)fb->Width;
+ const GLfloat height = (GLfloat)fb->Height;
+ struct pipe_viewport_state vp;
+ vp.scale[0] = 0.5f * width;
+ vp.scale[1] = height * (invert ? -0.5f : 0.5f);
+ vp.scale[2] = 1.0f;
+ vp.scale[3] = 1.0f;
+ vp.translate[0] = 0.5f * width;
+ vp.translate[1] = 0.5f * height;
+ vp.translate[2] = 0.0f;
+ vp.translate[3] = 0.0f;
+ cso_set_viewport(cso, &vp);
+ }
+
+
+ util_draw_vertex_buffer(pipe, vbuffer,
+ 0, /* offset */
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ numAttribs); /* attribs/vert */
+
+
+ pipe_buffer_reference(&vbuffer, NULL);
+
+ /* restore state */
+ cso_restore_viewport(cso);
+ cso_restore_vertex_shader(cso);
+}
+
+
+#endif /* FEATURE_OES_draw_texture */
+
+
+void
+st_init_drawtex_functions(struct dd_function_table *functions)
+{
+ _MESA_INIT_DRAWTEX_FUNCTIONS(functions, st_);
+}
+
+
+/**
+ * Free any cached shaders
+ */
+void
+st_destroy_drawtex(struct st_context *st)
+{
+ GLuint i;
+ for (i = 0; i < NumCachedShaders; i++) {
+ cso_delete_vertex_shader(st->cso_context, CachedShaders[i].handle);
+ }
+ NumCachedShaders = 0;
+}
diff --git a/src/mesa/state_tracker/st_cb_drawtex.h b/src/mesa/state_tracker/st_cb_drawtex.h
new file mode 100644
index 0000000000..7b0da70279
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_drawtex.h
@@ -0,0 +1,18 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_DRAWTEX_H
+#define ST_CB_DRAWTEX_H
+
+extern void
+st_init_drawtex_functions(struct dd_function_table *functions);
+
+extern void
+st_destroy_drawtex(struct st_context *st);
+
+#endif /* ST_CB_DRAWTEX_H */
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
new file mode 100644
index 0000000000..a96602878e
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -0,0 +1,664 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Framebuffer/renderbuffer functions.
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/fbobject.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "st_context.h"
+#include "st_cb_fbo.h"
+#include "st_cb_texture.h"
+#include "st_format.h"
+#include "st_public.h"
+#include "st_texture.h"
+
+
+
+/**
+ * Compute the renderbuffer's Red/Green/EtcBit fields from the pipe format.
+ */
+static int
+init_renderbuffer_bits(struct st_renderbuffer *strb,
+ enum pipe_format pipeFormat)
+{
+ struct pipe_format_info info;
+
+ if (!st_get_format_info( pipeFormat, &info )) {
+ assert( 0 );
+ }
+
+ strb->Base._ActualFormat = info.base_format;
+ strb->Base.RedBits = info.red_bits;
+ strb->Base.GreenBits = info.green_bits;
+ strb->Base.BlueBits = info.blue_bits;
+ strb->Base.AlphaBits = info.alpha_bits;
+ strb->Base.DepthBits = info.depth_bits;
+ strb->Base.StencilBits = info.stencil_bits;
+ strb->Base.DataType = st_format_datatype(pipeFormat);
+
+ return info.size;
+}
+
+/**
+ * gl_renderbuffer::AllocStorage()
+ * This is called to allocate the original drawing surface, and
+ * during window resize.
+ */
+static GLboolean
+st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+ enum pipe_format format;
+
+ if (strb->format != PIPE_FORMAT_NONE)
+ format = strb->format;
+ else
+ format = st_choose_renderbuffer_format(pipe, internalFormat);
+
+ /* init renderbuffer fields */
+ strb->Base.Width = width;
+ strb->Base.Height = height;
+ init_renderbuffer_bits(strb, format);
+
+ strb->defined = GL_FALSE; /* undefined contents now */
+
+ if(strb->software) {
+ struct pipe_format_block block;
+ size_t size;
+
+ _mesa_free(strb->data);
+
+ assert(strb->format != PIPE_FORMAT_NONE);
+ pf_get_block(strb->format, &block);
+
+ strb->stride = pf_get_stride(&block, width);
+ size = pf_get_2d_size(&block, strb->stride, height);
+
+ strb->data = _mesa_malloc(size);
+
+ return strb->data != NULL;
+ }
+ else {
+ struct pipe_texture template;
+ unsigned surface_usage;
+
+ /* Free the old surface and texture
+ */
+ pipe_surface_reference( &strb->surface, NULL );
+ pipe_texture_reference( &strb->texture, NULL );
+
+ /* Setup new texture template.
+ */
+ memset(&template, 0, sizeof(template));
+ template.target = PIPE_TEXTURE_2D;
+ template.format = format;
+ pf_get_block(format, &template.block);
+ template.width[0] = width;
+ template.height[0] = height;
+ template.depth[0] = 1;
+ template.last_level = 0;
+ template.nr_samples = rb->NumSamples;
+ if (pf_is_depth_stencil(format)) {
+ template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ }
+ else {
+ template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+ PIPE_TEXTURE_USAGE_RENDER_TARGET);
+ }
+
+ /* Probably need dedicated flags for surface usage too:
+ */
+ surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+#if 0
+ PIPE_BUFFER_USAGE_CPU_READ |
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+#endif
+
+ strb->texture = pipe->screen->texture_create( pipe->screen,
+ &template );
+
+ if (!strb->texture)
+ return FALSE;
+
+ strb->surface = pipe->screen->get_tex_surface( pipe->screen,
+ strb->texture,
+ 0, 0, 0,
+ surface_usage );
+
+ assert(strb->surface->texture);
+ assert(strb->surface->format);
+ assert(strb->surface->width == width);
+ assert(strb->surface->height == height);
+
+
+ return strb->surface != NULL;
+ }
+}
+
+
+/**
+ * gl_renderbuffer::Delete()
+ */
+static void
+st_renderbuffer_delete(struct gl_renderbuffer *rb)
+{
+ struct st_renderbuffer *strb = st_renderbuffer(rb);
+ ASSERT(strb);
+ pipe_surface_reference(&strb->surface, NULL);
+ pipe_texture_reference(&strb->texture, NULL);
+ _mesa_free(strb->data);
+ _mesa_free(strb);
+}
+
+
+/**
+ * gl_renderbuffer::GetPointer()
+ */
+static void *
+null_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ /* By returning NULL we force all software rendering to go through
+ * the span routines.
+ */
+#if 0
+ assert(0); /* Should never get called with softpipe */
+#endif
+ return NULL;
+}
+
+
+/**
+ * Called via ctx->Driver.NewFramebuffer()
+ */
+static struct gl_framebuffer *
+st_new_framebuffer(GLcontext *ctx, GLuint name)
+{
+ /* XXX not sure we need to subclass gl_framebuffer for pipe */
+ return _mesa_new_framebuffer(ctx, name);
+}
+
+
+/**
+ * Called via ctx->Driver.NewRenderbuffer()
+ */
+static struct gl_renderbuffer *
+st_new_renderbuffer(GLcontext *ctx, GLuint name)
+{
+ struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
+ if (strb) {
+ _mesa_init_renderbuffer(&strb->Base, name);
+ strb->Base.Delete = st_renderbuffer_delete;
+ strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+ strb->Base.GetPointer = null_get_pointer;
+ strb->format = PIPE_FORMAT_NONE;
+ return &strb->Base;
+ }
+ return NULL;
+}
+
+
+/**
+ * Allocate a renderbuffer for a an on-screen window (not a user-created
+ * renderbuffer). The window system code determines the format.
+ */
+struct gl_renderbuffer *
+st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
+{
+ struct st_renderbuffer *strb;
+
+ strb = ST_CALLOC_STRUCT(st_renderbuffer);
+ if (!strb) {
+ _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
+ return NULL;
+ }
+
+ _mesa_init_renderbuffer(&strb->Base, 0);
+ strb->Base.ClassID = 0x4242; /* just a unique value */
+ strb->Base.NumSamples = samples;
+ strb->format = format;
+ strb->software = sw;
+
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ strb->Base.InternalFormat = GL_RGBA;
+ strb->Base._BaseFormat = GL_RGBA;
+ break;
+ case PIPE_FORMAT_Z16_UNORM:
+ strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
+ strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+ break;
+ case PIPE_FORMAT_Z32_UNORM:
+ strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
+ strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_Z24S8_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
+ case PIPE_FORMAT_Z24X8_UNORM:
+ strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
+ strb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+ break;
+ case PIPE_FORMAT_S8_UNORM:
+ strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
+ strb->Base._BaseFormat = GL_STENCIL_INDEX;
+ break;
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ strb->Base.InternalFormat = GL_RGBA16;
+ strb->Base._BaseFormat = GL_RGBA;
+ break;
+ default:
+ _mesa_problem(NULL,
+ "Unexpected format in st_new_renderbuffer_fb");
+ return NULL;
+ }
+
+ /* st-specific methods */
+ strb->Base.Delete = st_renderbuffer_delete;
+ strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+ strb->Base.GetPointer = null_get_pointer;
+
+ /* surface is allocated in st_renderbuffer_alloc_storage() */
+ strb->surface = NULL;
+
+ return &strb->Base;
+}
+
+
+
+
+/**
+ * Called via ctx->Driver.BindFramebufferEXT().
+ */
+static void
+st_bind_framebuffer(GLcontext *ctx, GLenum target,
+ struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
+{
+
+}
+
+/**
+ * Called by ctx->Driver.FramebufferRenderbuffer
+ */
+static void
+st_framebuffer_renderbuffer(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb)
+{
+ /* XXX no need for derivation? */
+ _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+}
+
+
+/**
+ * Called by ctx->Driver.RenderTexture
+ */
+static void
+st_render_texture(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att)
+{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct st_renderbuffer *strb;
+ struct gl_renderbuffer *rb;
+ struct pipe_texture *pt = st_get_texobj_texture(att->Texture);
+ struct st_texture_object *stObj;
+ const struct gl_texture_image *texImage =
+ att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+
+ if (!pt)
+ return;
+
+ /* create new renderbuffer which wraps the texture image */
+ rb = st_new_renderbuffer(ctx, 0);
+ if (!rb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
+ return;
+ }
+
+ _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+ assert(rb->RefCount == 1);
+ rb->AllocStorage = NULL; /* should not get called */
+ strb = st_renderbuffer(rb);
+
+ assert(strb->Base.RefCount > 0);
+
+ /* get the texture for the texture object */
+ stObj = st_texture_object(att->Texture);
+
+ /* point renderbuffer at texobject */
+ strb->rtt = stObj;
+ strb->rtt_level = att->TextureLevel;
+ strb->rtt_face = att->CubeMapFace;
+ strb->rtt_slice = att->Zoffset;
+
+ rb->Width = texImage->Width2;
+ rb->Height = texImage->Height2;
+ /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
+
+ /*printf("***** pipe texture %d x %d\n", pt->width[0], pt->height[0]);*/
+
+ pipe_texture_reference( &strb->texture, pt );
+
+ pipe_surface_reference(&strb->surface, NULL);
+
+ /* new surface for rendering into the texture */
+ strb->surface = screen->get_tex_surface(screen,
+ strb->texture,
+ strb->rtt_face,
+ strb->rtt_level,
+ strb->rtt_slice,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ init_renderbuffer_bits(strb, pt->format);
+
+ /*
+ printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p %d x %d\n",
+ att->Texture, pt, strb->surface, rb->Width, rb->Height);
+ */
+
+ /* Invalidate buffer state so that the pipe's framebuffer state
+ * gets updated.
+ * That's where the new renderbuffer (which we just created) gets
+ * passed to the pipe as a (color/depth) render target.
+ */
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+/**
+ * Called via ctx->Driver.FinishRenderTexture.
+ */
+static void
+st_finish_render_texture(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att)
+{
+ struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
+
+ if (!strb)
+ return;
+
+ st_flush( ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL );
+
+ if (strb->surface)
+ pipe_surface_reference( &strb->surface, NULL );
+
+ strb->rtt = NULL;
+
+ /*
+ printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
+ */
+
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+
+ /* restore previous framebuffer state */
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+/**
+ * Validate a renderbuffer attachment for a particular usage.
+ */
+
+static GLboolean
+st_validate_attachment(struct pipe_screen *screen,
+ const struct gl_renderbuffer_attachment *att,
+ GLuint usage)
+{
+ const struct st_texture_object *stObj =
+ st_texture_object(att->Texture);
+
+ /**
+ * Only validate texture attachments for now, since
+ * st_renderbuffer_alloc_storage makes sure that
+ * the format is supported.
+ */
+
+ if (att->Type != GL_TEXTURE)
+ return GL_TRUE;
+
+ if (!stObj)
+ return GL_FALSE;
+
+ return screen->is_format_supported(screen, stObj->pt->format,
+ PIPE_TEXTURE_2D,
+ usage, 0);
+}
+
+/**
+ * Check that the framebuffer configuration is valid in terms of what
+ * the driver can support.
+ *
+ * For Gallium we only supports combined Z+stencil, not separate buffers.
+ */
+static void
+st_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ const struct gl_renderbuffer *depthRb =
+ fb->Attachment[BUFFER_DEPTH].Renderbuffer;
+ const struct gl_renderbuffer *stencilRb =
+ fb->Attachment[BUFFER_STENCIL].Renderbuffer;
+ GLuint i;
+
+ if (stencilRb && depthRb && stencilRb != depthRb) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+
+ if (!st_validate_attachment(screen,
+ &fb->Attachment[BUFFER_DEPTH],
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+ if (!st_validate_attachment(screen,
+ &fb->Attachment[BUFFER_STENCIL],
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+ for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
+ if (!st_validate_attachment(screen,
+ &fb->Attachment[BUFFER_COLOR0 + i],
+ PIPE_TEXTURE_USAGE_RENDER_TARGET)) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ return;
+ }
+ }
+}
+
+
+/**
+ * Copy back color buffer to front color buffer.
+ */
+static void
+copy_back_to_front(struct st_context *st,
+ struct gl_framebuffer *fb,
+ gl_buffer_index frontIndex,
+ gl_buffer_index backIndex)
+
+{
+ struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
+ struct pipe_surface *surf_front, *surf_back;
+
+ (void) st_get_framebuffer_surface(stfb, frontIndex, &surf_front);
+ (void) st_get_framebuffer_surface(stfb, backIndex, &surf_back);
+
+ if (surf_front && surf_back) {
+ st->pipe->surface_copy(st->pipe,
+ surf_front, 0, 0, /* dest */
+ surf_back, 0, 0, /* src */
+ fb->Width, fb->Height);
+ }
+}
+
+
+/**
+ * Check if we're drawing into, or read from, a front color buffer. If the
+ * front buffer is missing, create it now.
+ *
+ * The back color buffer must exist since we'll use its format/samples info
+ * for creating the front buffer.
+ *
+ * \param frontIndex either BUFFER_FRONT_LEFT or BUFFER_FRONT_RIGHT
+ * \param backIndex either BUFFER_BACK_LEFT or BUFFER_BACK_RIGHT
+ */
+static void
+check_create_front_buffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ gl_buffer_index frontIndex,
+ gl_buffer_index backIndex)
+{
+ if (fb->Attachment[frontIndex].Renderbuffer == NULL) {
+ GLboolean create = GL_FALSE;
+
+ /* check if drawing to or reading from front buffer */
+ if (fb->_ColorReadBufferIndex == frontIndex) {
+ create = GL_TRUE;
+ }
+ else {
+ GLuint b;
+ for (b = 0; b < fb->_NumColorDrawBuffers; b++) {
+ if (fb->_ColorDrawBufferIndexes[b] == frontIndex) {
+ create = GL_TRUE;
+ break;
+ }
+ }
+ }
+
+ if (create) {
+ struct st_renderbuffer *back;
+ struct gl_renderbuffer *front;
+ enum pipe_format colorFormat;
+ uint samples;
+
+ if (0)
+ _mesa_debug(ctx, "Allocate new front buffer\n");
+
+ /* get back renderbuffer info */
+ back = st_renderbuffer(fb->Attachment[backIndex].Renderbuffer);
+ colorFormat = back->format;
+ samples = back->Base.NumSamples;
+
+ /* create front renderbuffer */
+ front = st_new_renderbuffer_fb(colorFormat, samples, FALSE);
+ _mesa_add_renderbuffer(fb, frontIndex, front);
+
+ /* alloc texture/surface for new front buffer */
+ front->AllocStorage(ctx, front, front->InternalFormat,
+ fb->Width, fb->Height);
+
+ /* initialize the front color buffer contents by copying
+ * the back buffer.
+ */
+ copy_back_to_front(ctx->st, fb, frontIndex, backIndex);
+ }
+ }
+}
+
+
+/**
+ * If front left/right color buffers are missing, create them now.
+ */
+static void
+check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ /* check if we need to create the front left buffer now */
+ check_create_front_buffer(ctx, fb, BUFFER_FRONT_LEFT, BUFFER_BACK_LEFT);
+
+ if (fb->Visual.stereoMode) {
+ check_create_front_buffer(ctx, fb, BUFFER_FRONT_RIGHT, BUFFER_BACK_RIGHT);
+ }
+
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+/**
+ * Called via glDrawBuffer.
+ */
+static void
+st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
+{
+ (void) count;
+ (void) buffers;
+ check_create_front_buffers(ctx, ctx->DrawBuffer);
+}
+
+
+/**
+ * Called via glReadBuffer.
+ */
+static void
+st_ReadBuffer(GLcontext *ctx, GLenum buffer)
+{
+ (void) buffer;
+ check_create_front_buffers(ctx, ctx->ReadBuffer);
+}
+
+
+void st_init_fbo_functions(struct dd_function_table *functions)
+{
+ functions->NewFramebuffer = st_new_framebuffer;
+ functions->NewRenderbuffer = st_new_renderbuffer;
+ functions->BindFramebuffer = st_bind_framebuffer;
+ functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
+ functions->RenderTexture = st_render_texture;
+ functions->FinishRenderTexture = st_finish_render_texture;
+ functions->ValidateFramebuffer = st_validate_framebuffer;
+ /* no longer needed by core Mesa, drivers handle resizes...
+ functions->ResizeBuffers = st_resize_buffers;
+ */
+
+ functions->DrawBuffers = st_DrawBuffers;
+ functions->ReadBuffer = st_ReadBuffer;
+}
diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h
new file mode 100644
index 0000000000..bea6eb89c3
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_fbo.h
@@ -0,0 +1,75 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_FBO_H
+#define ST_CB_FBO_H
+
+
+/**
+ * Derived renderbuffer class. Just need to add a pointer to the
+ * pipe surface.
+ */
+struct st_renderbuffer
+{
+ struct gl_renderbuffer Base;
+ struct pipe_texture *texture;
+ struct pipe_surface *surface; /* temporary view into texture */
+ enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */
+ GLboolean defined; /**< defined contents? */
+
+ /**
+ * Used only when hardware accumulation buffers are not supported.
+ */
+ boolean software;
+ size_t stride;
+ void *data;
+
+ struct st_texture_object *rtt; /**< GL render to texture's texture */
+ int rtt_level, rtt_face, rtt_slice;
+
+ /** Render to texture state */
+ struct pipe_texture *texture_save;
+ struct pipe_surface *surface_save;
+};
+
+
+static INLINE struct st_renderbuffer *
+st_renderbuffer(struct gl_renderbuffer *rb)
+{
+ return (struct st_renderbuffer *) rb;
+}
+
+
+extern struct gl_renderbuffer *
+st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw);
+
+extern void
+st_init_fbo_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_FBO_H */
diff --git a/src/mesa/state_tracker/st_cb_feedback.c b/src/mesa/state_tracker/st_cb_feedback.c
new file mode 100644
index 0000000000..93f7145219
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_feedback.c
@@ -0,0 +1,309 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * GL_SELECT and GL_FEEDBACK render modes.
+ * Basically, we use a private instance of the 'draw' module for doing
+ * selection/feedback. It would be nice to use the transform_feedback
+ * hardware feature, but it's defined as happening pre-clip and we want
+ * post-clipped primitives. Also, there's concerns about the efficiency
+ * of using the hardware for this anyway.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/feedback.h"
+#include "main/macros.h"
+
+#include "vbo/vbo.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "st_cb_feedback.h"
+#include "st_cb_bufferobjects.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "cso_cache/cso_cache.h"
+
+#include "draw/draw_context.h"
+#include "draw/draw_pipe.h"
+
+
+/**
+ * This is actually used for both feedback and selection.
+ */
+struct feedback_stage
+{
+ struct draw_stage stage; /**< Base class */
+ GLcontext *ctx; /**< Rendering context */
+ GLboolean reset_stipple_counter;
+};
+
+
+/**********************************************************************
+ * GL Feedback functions
+ **********************************************************************/
+
+static INLINE struct feedback_stage *
+feedback_stage( struct draw_stage *stage )
+{
+ return (struct feedback_stage *)stage;
+}
+
+
+static void
+feedback_vertex(GLcontext *ctx, const struct draw_context *draw,
+ const struct vertex_header *v)
+{
+ const struct st_context *st = ctx->st;
+ GLfloat win[4];
+ const GLfloat *color, *texcoord;
+ const GLfloat ci = 0;
+ GLuint slot;
+
+ /* Recall that Y=0=Top of window for Gallium wincoords */
+ win[0] = v->data[0][0];
+ win[1] = ctx->DrawBuffer->Height - v->data[0][1];
+ win[2] = v->data[0][2];
+ win[3] = 1.0F / v->data[0][3];
+
+ /* XXX
+ * When we compute vertex layout, save info about position of the
+ * color and texcoord attribs to use here.
+ */
+
+ slot = st->vertex_result_to_slot[VERT_RESULT_COL0];
+ if (slot != ~0U)
+ color = v->data[slot];
+ else
+ color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+
+ slot = st->vertex_result_to_slot[VERT_RESULT_TEX0];
+ if (slot != ~0U)
+ texcoord = v->data[slot];
+ else
+ texcoord = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+
+ _mesa_feedback_vertex(ctx, win, color, ci, texcoord);
+}
+
+
+static void
+feedback_tri( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ struct draw_context *draw = stage->draw;
+ _mesa_feedback_token(fs->ctx, (GLfloat) GL_POLYGON_TOKEN);
+ _mesa_feedback_token(fs->ctx, (GLfloat) 3); /* three vertices */
+ feedback_vertex(fs->ctx, draw, prim->v[0]);
+ feedback_vertex(fs->ctx, draw, prim->v[1]);
+ feedback_vertex(fs->ctx, draw, prim->v[2]);
+}
+
+
+static void
+feedback_line( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ struct draw_context *draw = stage->draw;
+ if (fs->reset_stipple_counter) {
+ _mesa_feedback_token(fs->ctx, (GLfloat) GL_LINE_RESET_TOKEN);
+ fs->reset_stipple_counter = GL_FALSE;
+ }
+ else {
+ _mesa_feedback_token(fs->ctx, (GLfloat) GL_LINE_TOKEN);
+ }
+ feedback_vertex(fs->ctx, draw, prim->v[0]);
+ feedback_vertex(fs->ctx, draw, prim->v[1]);
+}
+
+
+static void
+feedback_point( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ struct draw_context *draw = stage->draw;
+ _mesa_feedback_token(fs->ctx, (GLfloat) GL_POINT_TOKEN);
+ feedback_vertex(fs->ctx, draw, prim->v[0]);
+}
+
+
+static void
+feedback_flush( struct draw_stage *stage, unsigned flags )
+{
+ /* no-op */
+}
+
+
+static void
+feedback_reset_stipple_counter( struct draw_stage *stage )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ fs->reset_stipple_counter = GL_TRUE;
+}
+
+
+static void
+feedback_destroy( struct draw_stage *stage )
+{
+ /* no-op */
+}
+
+/**
+ * Create GL feedback drawing stage.
+ */
+static struct draw_stage *
+draw_glfeedback_stage(GLcontext *ctx, struct draw_context *draw)
+{
+ struct feedback_stage *fs = ST_CALLOC_STRUCT(feedback_stage);
+
+ fs->stage.draw = draw;
+ fs->stage.next = NULL;
+ fs->stage.point = feedback_point;
+ fs->stage.line = feedback_line;
+ fs->stage.tri = feedback_tri;
+ fs->stage.flush = feedback_flush;
+ fs->stage.reset_stipple_counter = feedback_reset_stipple_counter;
+ fs->stage.destroy = feedback_destroy;
+ fs->ctx = ctx;
+
+ return &fs->stage;
+}
+
+
+
+/**********************************************************************
+ * GL Selection functions
+ **********************************************************************/
+
+static void
+select_tri( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] );
+ _mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] );
+ _mesa_update_hitflag( fs->ctx, prim->v[2]->data[0][2] );
+}
+
+static void
+select_line( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] );
+ _mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] );
+}
+
+
+static void
+select_point( struct draw_stage *stage, struct prim_header *prim )
+{
+ struct feedback_stage *fs = feedback_stage(stage);
+ _mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] );
+}
+
+
+static void
+select_flush( struct draw_stage *stage, unsigned flags )
+{
+ /* no-op */
+}
+
+
+static void
+select_reset_stipple_counter( struct draw_stage *stage )
+{
+ /* no-op */
+}
+
+static void
+select_destroy( struct draw_stage *stage )
+{
+ /* no-op */
+}
+
+
+/**
+ * Create GL selection mode drawing stage.
+ */
+static struct draw_stage *
+draw_glselect_stage(GLcontext *ctx, struct draw_context *draw)
+{
+ struct feedback_stage *fs = ST_CALLOC_STRUCT(feedback_stage);
+
+ fs->stage.draw = draw;
+ fs->stage.next = NULL;
+ fs->stage.point = select_point;
+ fs->stage.line = select_line;
+ fs->stage.tri = select_tri;
+ fs->stage.flush = select_flush;
+ fs->stage.reset_stipple_counter = select_reset_stipple_counter;
+ fs->stage.destroy = select_destroy;
+ fs->ctx = ctx;
+
+ return &fs->stage;
+}
+
+
+static void
+st_RenderMode(GLcontext *ctx, GLenum newMode )
+{
+ struct st_context *st = ctx->st;
+ struct draw_context *draw = st->draw;
+
+ if (newMode == GL_RENDER) {
+ /* restore normal VBO draw function */
+ vbo_set_draw_func(ctx, st_draw_vbo);
+ }
+ else if (newMode == GL_SELECT) {
+ if (!st->selection_stage)
+ st->selection_stage = draw_glselect_stage(ctx, draw);
+ draw_set_rasterize_stage(draw, st->selection_stage);
+ /* Plug in new vbo draw function */
+ vbo_set_draw_func(ctx, st_feedback_draw_vbo);
+ }
+ else {
+ if (!st->feedback_stage)
+ st->feedback_stage = draw_glfeedback_stage(ctx, draw);
+ draw_set_rasterize_stage(draw, st->feedback_stage);
+ /* Plug in new vbo draw function */
+ vbo_set_draw_func(ctx, st_feedback_draw_vbo);
+ /* need to generate/use a vertex program that emits pos/color/tex */
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+ }
+}
+
+
+
+void st_init_feedback_functions(struct dd_function_table *functions)
+{
+ functions->RenderMode = st_RenderMode;
+}
diff --git a/src/mesa/state_tracker/st_cb_feedback.h b/src/mesa/state_tracker/st_cb_feedback.h
new file mode 100644
index 0000000000..2559ba3817
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_feedback.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_FEEDBACK_H
+#define ST_CB_FEEDBACK_H
+
+
+extern void
+st_init_feedback_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_FEEDBACK_H */
diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c
new file mode 100644
index 0000000000..1329f807bc
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_flush.c
@@ -0,0 +1,176 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "st_context.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_flush.h"
+#include "st_cb_clear.h"
+#include "st_cb_fbo.h"
+#include "st_public.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "util/u_gen_mipmap.h"
+#include "util/u_blit.h"
+
+
+/** Check if we have a front color buffer and if it's been drawn to. */
+static INLINE GLboolean
+is_front_buffer_dirty(struct st_context *st)
+{
+ if (st->frontbuffer_status == FRONT_STATUS_DIRTY) {
+ return GL_TRUE;
+ }
+ else {
+ GLframebuffer *fb = st->ctx->DrawBuffer;
+ struct st_renderbuffer *strb
+ = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ return strb && strb->defined;
+ }
+}
+
+
+/**
+ * Tell the screen to display the front color buffer on-screen.
+ */
+static void
+display_front_buffer(struct st_context *st)
+{
+ GLframebuffer *fb = st->ctx->DrawBuffer;
+ struct st_renderbuffer *strb
+ = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+
+ if (strb) {
+ struct pipe_surface *front_surf = strb->surface;
+
+ /* Hook for copying "fake" frontbuffer if necessary:
+ */
+ st->pipe->screen->flush_frontbuffer( st->pipe->screen, front_surf,
+ st->pipe->priv );
+
+ /*
+ st->frontbuffer_status = FRONT_STATUS_UNDEFINED;
+ */
+ }
+}
+
+
+void st_flush( struct st_context *st, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence )
+{
+ FLUSH_CURRENT(st->ctx, 0);
+
+ /* Release any vertex buffers that might potentially be accessed in
+ * successive frames:
+ */
+ st_flush_bitmap(st);
+ st_flush_clear(st);
+ util_blit_flush(st->blit);
+ util_gen_mipmap_flush(st->gen_mipmap);
+
+ st->pipe->flush( st->pipe, pipeFlushFlags, fence );
+}
+
+
+/**
+ * Flush, and wait for completion.
+ */
+void st_finish( struct st_context *st )
+{
+ struct pipe_fence_handle *fence = NULL;
+
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
+
+ if(fence) {
+ st->pipe->screen->fence_finish(st->pipe->screen, fence, 0);
+ st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
+ }
+}
+
+
+
+/**
+ * Called via ctx->Driver.Flush()
+ */
+static void st_glFlush(GLcontext *ctx)
+{
+ struct st_context *st = ctx->st;
+
+ /* Don't call st_finish() here. It is not the state tracker's
+ * responsibilty to inject sleeps in the hope of avoiding buffer
+ * synchronization issues. Calling finish() here will just hide
+ * problems that need to be fixed elsewhere.
+ */
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
+
+ if (is_front_buffer_dirty(st)) {
+ display_front_buffer(st);
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.Finish()
+ */
+static void st_glFinish(GLcontext *ctx)
+{
+ struct st_context *st = ctx->st;
+
+ st_finish(st);
+
+ if (is_front_buffer_dirty(st)) {
+ display_front_buffer(st);
+ }
+}
+
+
+void st_init_flush_functions(struct dd_function_table *functions)
+{
+ functions->Flush = st_glFlush;
+ functions->Finish = st_glFinish;
+
+ /* Windows opengl32.dll calls glFinish prior to every swapbuffers.
+ * This is unnecessary and degrades performance. Luckily we have some
+ * scope to work around this, as the externally-visible behaviour of
+ * Finish() is identical to Flush() in all cases - no differences in
+ * rendering or ReadPixels are visible if we opt not to wait here.
+ *
+ * Only set this up on windows to avoid suprise elsewhere.
+ */
+#ifdef PIPE_OS_WINDOWS
+ functions->Finish = st_glFlush;
+#endif
+}
diff --git a/src/mesa/state_tracker/st_cb_flush.h b/src/mesa/state_tracker/st_cb_flush.h
new file mode 100644
index 0000000000..c26f779225
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_flush.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_FLUSH_H
+#define ST_CB_FLUSH_H
+
+
+extern void
+st_init_flush_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_FLUSH_H */
+
diff --git a/src/mesa/state_tracker/st_cb_get.c b/src/mesa/state_tracker/st_cb_get.c
new file mode 100644
index 0000000000..e7d7f03bc9
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_get.c
@@ -0,0 +1,97 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * glGet functions
+ *
+ * \author Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+
+#include "pipe/p_defines.h"
+
+#include "st_cb_fbo.h"
+#include "st_cb_get.h"
+
+
+
+/**
+ * Examine the current color read buffer format to determine
+ * which GL pixel format/type combo is the best match.
+ */
+static void
+get_preferred_read_format_type(GLcontext *ctx, GLint *format, GLint *type)
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct st_renderbuffer *strb = st_renderbuffer(fb->_ColorReadBuffer);
+
+ /* defaults */
+ *format = ctx->Const.ColorReadFormat;
+ *type = ctx->Const.ColorReadType;
+
+ if (strb) {
+ /* XXX could add more cases here... */
+ if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM) {
+ *format = GL_BGRA;
+ if (_mesa_little_endian())
+ *type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ else
+ *type = GL_UNSIGNED_INT_8_8_8_8;
+ }
+ }
+}
+
+
+/**
+ * We only intercept the OES preferred ReadPixels format/type.
+ * Everything else goes to the default _mesa_GetIntegerv.
+ */
+static GLboolean
+st_GetIntegerv(GLcontext *ctx, GLenum pname, GLint *params)
+{
+ GLint dummy;
+
+ switch (pname) {
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+ get_preferred_read_format_type(ctx, &dummy, params);
+ return GL_TRUE;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+ get_preferred_read_format_type(ctx, params, &dummy);
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+void st_init_get_functions(struct dd_function_table *functions)
+{
+ functions->GetIntegerv = st_GetIntegerv;
+}
diff --git a/src/mesa/state_tracker/st_cb_get.h b/src/mesa/state_tracker/st_cb_get.h
new file mode 100644
index 0000000000..8e9f3e9306
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_get.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_GET_H
+#define ST_CB_GET_H
+
+
+extern void
+st_init_get_functions(struct dd_function_table *functions);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
new file mode 100644
index 0000000000..4398ab2839
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_program.c
@@ -0,0 +1,266 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/program.h"
+#include "shader/programopt.h"
+#include "shader/shader_api.h"
+
+#include "cso_cache/cso_context.h"
+#include "draw/draw_context.h"
+
+#include "st_context.h"
+#include "st_program.h"
+#include "st_atom_shader.h"
+#include "st_cb_program.h"
+
+
+static GLuint SerialNo = 1;
+
+
+/**
+ * Called via ctx->Driver.BindProgram() to bind an ARB vertex or
+ * fragment program.
+ */
+static void st_bind_program( GLcontext *ctx,
+ GLenum target,
+ struct gl_program *prog )
+{
+ struct st_context *st = st_context(ctx);
+
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+ break;
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.UseProgram() to bind a linked GLSL program
+ * (vertex shader + fragment shader).
+ */
+static void st_use_program( GLcontext *ctx,
+ GLuint program )
+{
+ struct st_context *st = st_context(ctx);
+
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+
+ _mesa_use_program(ctx, program);
+}
+
+
+
+/**
+ * Called via ctx->Driver.NewProgram() to allocate a new vertex or
+ * fragment program.
+ */
+static struct gl_program *st_new_program( GLcontext *ctx,
+ GLenum target,
+ GLuint id )
+{
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB: {
+ struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program);
+
+ prog->serialNo = SerialNo++;
+
+ return _mesa_init_vertex_program( ctx,
+ &prog->Base,
+ target,
+ id );
+ }
+
+ case GL_FRAGMENT_PROGRAM_ARB:
+ case GL_FRAGMENT_PROGRAM_NV: {
+ struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program);
+
+ prog->serialNo = SerialNo++;
+
+ return _mesa_init_fragment_program( ctx,
+ &prog->Base,
+ target,
+ id );
+ }
+
+ default:
+ assert(0);
+ return NULL;
+ }
+}
+
+
+void
+st_delete_program(GLcontext *ctx, struct gl_program *prog)
+{
+ struct st_context *st = st_context(ctx);
+
+ switch( prog->Target ) {
+ case GL_VERTEX_PROGRAM_ARB:
+ {
+ struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
+
+ if (stvp->driver_shader) {
+ cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
+ stvp->driver_shader = NULL;
+ }
+
+ if (stvp->draw_shader) {
+#if FEATURE_feedback || FEATURE_drawpix
+ /* this would only have been allocated for the RasterPos path */
+ draw_delete_vertex_shader(st->draw, stvp->draw_shader);
+ stvp->draw_shader = NULL;
+#endif
+ }
+
+ if (stvp->state.tokens) {
+ _mesa_free((void *) stvp->state.tokens);
+ stvp->state.tokens = NULL;
+ }
+ }
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ {
+ struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
+
+ if (stfp->driver_shader) {
+ cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
+ stfp->driver_shader = NULL;
+ }
+
+ if (stfp->state.tokens) {
+ _mesa_free((void *) stfp->state.tokens);
+ stfp->state.tokens = NULL;
+ }
+
+ if (stfp->bitmap_program) {
+ struct gl_program *prg = &stfp->bitmap_program->Base.Base;
+ _mesa_reference_program(ctx, &prg, NULL);
+ stfp->bitmap_program = NULL;
+ }
+
+ st_free_translated_vertex_programs(st, stfp->vertex_programs);
+ }
+ break;
+ default:
+ assert(0); /* problem */
+ }
+
+ /* delete base class */
+ _mesa_delete_program( ctx, prog );
+}
+
+
+static GLboolean st_is_program_native( GLcontext *ctx,
+ GLenum target,
+ struct gl_program *prog )
+{
+ return GL_TRUE;
+}
+
+
+static void st_program_string_notify( GLcontext *ctx,
+ GLenum target,
+ struct gl_program *prog )
+{
+ struct st_context *st = st_context(ctx);
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
+
+ stfp->serialNo++;
+
+ if (stfp->driver_shader) {
+ cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
+ stfp->driver_shader = NULL;
+ }
+
+ if (stfp->state.tokens) {
+ _mesa_free((void *) stfp->state.tokens);
+ stfp->state.tokens = NULL;
+ }
+
+ stfp->param_state = stfp->Base.Base.Parameters->StateFlags;
+
+ if (st->fp == stfp)
+ st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB) {
+ struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
+
+ stvp->serialNo++;
+
+ if (stvp->driver_shader) {
+ cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
+ stvp->driver_shader = NULL;
+ }
+
+ if (stvp->draw_shader) {
+#if FEATURE_feedback || FEATURE_drawpix
+ /* this would only have been allocated for the RasterPos path */
+ draw_delete_vertex_shader(st->draw, stvp->draw_shader);
+ stvp->draw_shader = NULL;
+#endif
+ }
+
+ if (stvp->state.tokens) {
+ _mesa_free((void *) stvp->state.tokens);
+ stvp->state.tokens = NULL;
+ }
+
+ stvp->param_state = stvp->Base.Base.Parameters->StateFlags;
+
+ if (st->vp == stvp)
+ st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+ }
+}
+
+
+
+void st_init_program_functions(struct dd_function_table *functions)
+{
+ functions->BindProgram = st_bind_program;
+ functions->UseProgram = st_use_program;
+ functions->NewProgram = st_new_program;
+ functions->DeleteProgram = st_delete_program;
+ functions->IsProgramNative = st_is_program_native;
+ functions->ProgramStringNotify = st_program_string_notify;
+}
diff --git a/src/mesa/state_tracker/st_cb_program.h b/src/mesa/state_tracker/st_cb_program.h
new file mode 100644
index 0000000000..0de96f2fd2
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_program.h
@@ -0,0 +1,39 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_PROGRAM_H
+#define ST_CB_PROGRAM_H
+
+
+extern void
+st_init_program_functions(struct dd_function_table *functions);
+
+extern void
+st_delete_program(GLcontext *ctx, struct gl_program *prog);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_queryobj.c b/src/mesa/state_tracker/st_cb_queryobj.c
new file mode 100644
index 0000000000..dcf4c38eb6
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_queryobj.c
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * glBegin/EndQuery interface to pipe
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/image.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "st_context.h"
+#include "st_cb_queryobj.h"
+#include "st_public.h"
+
+
+struct st_query_object
+{
+ struct gl_query_object base;
+ struct pipe_query *pq;
+};
+
+
+/**
+ * Cast wrapper
+ */
+static struct st_query_object *
+st_query_object(struct gl_query_object *q)
+{
+ return (struct st_query_object *) q;
+}
+
+
+static struct gl_query_object *
+st_NewQueryObject(GLcontext *ctx, GLuint id)
+{
+ struct st_query_object *stq = ST_CALLOC_STRUCT(st_query_object);
+ if (stq) {
+ stq->base.Id = id;
+ stq->base.Ready = GL_TRUE;
+ stq->pq = NULL;
+ return &stq->base;
+ }
+ return NULL;
+}
+
+
+
+static void
+st_DeleteQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ if (stq->pq) {
+ pipe->destroy_query(pipe, stq->pq);
+ stq->pq = NULL;
+ }
+
+ _mesa_free(stq);
+}
+
+
+static void
+st_BeginQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ switch (q->Target) {
+ case GL_SAMPLES_PASSED_ARB:
+ if (!stq->pq)
+ stq->pq = pipe->create_query( pipe, PIPE_QUERY_OCCLUSION_COUNTER );
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ pipe->begin_query(pipe, stq->pq);
+}
+
+
+static void
+st_EndQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ pipe->end_query(pipe, stq->pq);
+}
+
+
+static void
+st_WaitQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ /* this function should only be called if we don't have a ready result */
+ assert(!stq->base.Ready);
+
+ while (!stq->base.Ready &&
+ !pipe->get_query_result(pipe,
+ stq->pq,
+ TRUE,
+ &q->Result))
+ {
+ /* nothing */
+ }
+
+ q->Ready = GL_TRUE;
+}
+
+
+static void
+st_CheckQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct st_query_object *stq = st_query_object(q);
+
+ if (!q->Ready) {
+ q->Ready = pipe->get_query_result(pipe,
+ stq->pq,
+ FALSE,
+ &q->Result);
+ }
+}
+
+
+
+
+void st_init_query_functions(struct dd_function_table *functions)
+{
+ functions->NewQueryObject = st_NewQueryObject;
+ functions->DeleteQuery = st_DeleteQuery;
+ functions->BeginQuery = st_BeginQuery;
+ functions->EndQuery = st_EndQuery;
+ functions->WaitQuery = st_WaitQuery;
+ functions->CheckQuery = st_CheckQuery;
+}
diff --git a/src/mesa/state_tracker/st_cb_queryobj.h b/src/mesa/state_tracker/st_cb_queryobj.h
new file mode 100644
index 0000000000..9220a212b6
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_queryobj.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_QUERYOBJ_H
+#define ST_CB_QUERYOBJ_H
+
+
+extern void
+st_init_query_functions(struct dd_function_table *functions);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c
new file mode 100644
index 0000000000..d82b2a2035
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_rasterpos.c
@@ -0,0 +1,262 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * glRasterPos implementation. Basically render a GL_POINT with our
+ * private draw module. Plug in a special "rasterpos" stage at the end
+ * of the 'draw' pipeline to capture the results and update the current
+ * raster pos attributes.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/feedback.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "st_cb_rasterpos.h"
+#include "st_draw.h"
+#include "draw/draw_context.h"
+#include "draw/draw_pipe.h"
+#include "shader/prog_instruction.h"
+#include "vbo/vbo.h"
+
+
+
+/**
+ * Our special drawing pipeline stage (replaces rasterization).
+ */
+struct rastpos_stage
+{
+ struct draw_stage stage; /**< Base class */
+ GLcontext *ctx; /**< Rendering context */
+
+ /* vertex attrib info we can setup once and re-use */
+ struct gl_client_array array[VERT_ATTRIB_MAX];
+ const struct gl_client_array *arrays[VERT_ATTRIB_MAX];
+ struct _mesa_prim prim;
+};
+
+
+static INLINE struct rastpos_stage *
+rastpos_stage( struct draw_stage *stage )
+{
+ return (struct rastpos_stage *) stage;
+}
+
+static void
+rastpos_flush( struct draw_stage *stage, unsigned flags )
+{
+ /* no-op */
+}
+
+static void
+rastpos_reset_stipple_counter( struct draw_stage *stage )
+{
+ /* no-op */
+}
+
+static void
+rastpos_tri( struct draw_stage *stage, struct prim_header *prim )
+{
+ /* should never get here */
+ assert(0);
+}
+
+static void
+rastpos_line( struct draw_stage *stage, struct prim_header *prim )
+{
+ /* should never get here */
+ assert(0);
+}
+
+static void
+rastpos_destroy(struct draw_stage *stage)
+{
+ _mesa_free(stage);
+}
+
+
+/**
+ * Update a raster pos attribute from the vertex result if it's present,
+ * else copy the current attrib.
+ */
+static void
+update_attrib(GLcontext *ctx, const GLuint *outputMapping,
+ const struct vertex_header *vert,
+ GLfloat *dest,
+ GLuint result, GLuint defaultAttrib)
+{
+ const GLfloat *src;
+ const GLuint k = outputMapping[result];
+ if (k != ~0U)
+ src = vert->data[k];
+ else
+ src = ctx->Current.Attrib[defaultAttrib];
+ COPY_4V(dest, src);
+}
+
+
+/**
+ * Normally, this function would render a GL_POINT.
+ */
+static void
+rastpos_point(struct draw_stage *stage, struct prim_header *prim)
+{
+ struct rastpos_stage *rs = rastpos_stage(stage);
+ GLcontext *ctx = rs->ctx;
+ struct st_context *st = ctx->st;
+ const GLfloat height = (GLfloat) ctx->DrawBuffer->Height;
+ const GLuint *outputMapping = st->vertex_result_to_slot;
+ const GLfloat *pos;
+ GLuint i;
+
+ /* if we get here, we didn't get clipped */
+ ctx->Current.RasterPosValid = GL_TRUE;
+
+ /* update raster pos */
+ pos = prim->v[0]->data[0];
+ ctx->Current.RasterPos[0] = pos[0];
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP)
+ ctx->Current.RasterPos[1] = height - pos[1]; /* invert Y */
+ else
+ ctx->Current.RasterPos[1] = pos[1];
+ ctx->Current.RasterPos[2] = pos[2];
+ ctx->Current.RasterPos[3] = pos[3];
+
+ /* update other raster attribs */
+ update_attrib(ctx, outputMapping, prim->v[0],
+ ctx->Current.RasterColor,
+ VERT_RESULT_COL0, VERT_ATTRIB_COLOR0);
+
+ update_attrib(ctx, outputMapping, prim->v[0],
+ ctx->Current.RasterSecondaryColor,
+ VERT_RESULT_COL1, VERT_ATTRIB_COLOR1);
+
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+ update_attrib(ctx, outputMapping, prim->v[0],
+ ctx->Current.RasterTexCoords[i],
+ VERT_RESULT_TEX0 + i, VERT_ATTRIB_TEX0 + i);
+ }
+
+ if (ctx->RenderMode == GL_SELECT) {
+ _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
+ }
+}
+
+
+/**
+ * Create rasterpos "drawing" stage.
+ */
+static struct rastpos_stage *
+new_draw_rastpos_stage(GLcontext *ctx, struct draw_context *draw)
+{
+ struct rastpos_stage *rs = ST_CALLOC_STRUCT(rastpos_stage);
+ GLuint i;
+
+ rs->stage.draw = draw;
+ rs->stage.next = NULL;
+ rs->stage.point = rastpos_point;
+ rs->stage.line = rastpos_line;
+ rs->stage.tri = rastpos_tri;
+ rs->stage.flush = rastpos_flush;
+ rs->stage.destroy = rastpos_destroy;
+ rs->stage.reset_stipple_counter = rastpos_reset_stipple_counter;
+ rs->stage.destroy = rastpos_destroy;
+ rs->ctx = ctx;
+
+ for (i = 0; i < Elements(rs->array); i++) {
+ rs->array[i].Size = 4;
+ rs->array[i].Type = GL_FLOAT;
+ rs->array[i].Format = GL_RGBA;
+ rs->array[i].Stride = 0;
+ rs->array[i].StrideB = 0;
+ rs->array[i].Ptr = (GLubyte *) ctx->Current.Attrib[i];
+ rs->array[i].Enabled = GL_TRUE;
+ rs->array[i].Normalized = GL_TRUE;
+ rs->array[i].BufferObj = NULL;
+ rs->arrays[i] = &rs->array[i];
+ }
+
+ rs->prim.mode = GL_POINTS;
+ rs->prim.indexed = 0;
+ rs->prim.begin = 1;
+ rs->prim.end = 1;
+ rs->prim.weak = 0;
+ rs->prim.start = 0;
+ rs->prim.count = 1;
+
+ return rs;
+}
+
+
+static void
+st_RasterPos(GLcontext *ctx, const GLfloat v[4])
+{
+ struct st_context *st = ctx->st;
+ struct draw_context *draw = st->draw;
+ struct rastpos_stage *rs;
+
+ if (st->rastpos_stage) {
+ /* get rastpos stage info */
+ rs = rastpos_stage(st->rastpos_stage);
+ }
+ else {
+ /* create rastpos draw stage */
+ rs = new_draw_rastpos_stage(ctx, draw);
+ st->rastpos_stage = &rs->stage;
+ }
+
+ /* plug our rastpos stage into the draw module */
+ draw_set_rasterize_stage(st->draw, st->rastpos_stage);
+
+ /* make sure everything's up to date */
+ st_validate_state(ctx->st);
+
+ /* This will get set only if rastpos_point(), above, gets called */
+ ctx->Current.RasterPosValid = GL_FALSE;
+
+ /* All vertex attribs but position were previously initialized above.
+ * Just plug in position pointer now.
+ */
+ rs->array[0].Ptr = (GLubyte *) v;
+
+ /* draw the point */
+ st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, GL_TRUE, 0, 1);
+}
+
+
+
+void st_init_rasterpos_functions(struct dd_function_table *functions)
+{
+ functions->RasterPos = st_RasterPos;
+}
diff --git a/src/mesa/state_tracker/st_cb_rasterpos.h b/src/mesa/state_tracker/st_cb_rasterpos.h
new file mode 100644
index 0000000000..2b992e1405
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_rasterpos.h
@@ -0,0 +1,33 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ST_CB_RASTERPOS_H
+#define ST_CB_RASTERPOS_H
+
+extern void st_init_rasterpos_functions(struct dd_function_table *functions);
+
+#endif
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
new file mode 100644
index 0000000000..75424aa2e7
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -0,0 +1,544 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * glReadPixels interface to pipe
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/image.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+
+#include "st_context.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_readpixels.h"
+#include "st_cb_fbo.h"
+#include "st_format.h"
+#include "st_public.h"
+#include "st_texture.h"
+#include "st_inlines.h"
+
+/**
+ * Special case for reading stencil buffer.
+ * For color/depth we use get_tile(). For stencil, map the stencil buffer.
+ */
+void
+st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ GLvoid *pixels)
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer);
+ struct pipe_transfer *pt;
+ ubyte *stmap;
+ GLint j;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ y = ctx->DrawBuffer->Height - y - height;
+ }
+
+ /* Create a read transfer from the renderbuffer's texture */
+
+ pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, x, y,
+ width, height);
+
+ /* map the stencil buffer */
+ stmap = screen->transfer_map(screen, pt);
+
+ /* width should never be > MAX_WIDTH since we did clipping earlier */
+ ASSERT(width <= MAX_WIDTH);
+
+ /* process image row by row */
+ for (j = 0; j < height; j++) {
+ GLvoid *dest;
+ GLstencil sValues[MAX_WIDTH];
+ GLfloat zValues[MAX_WIDTH];
+ GLint srcY;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ srcY = height - j - 1;
+ }
+ else {
+ srcY = j;
+ }
+
+ /* get stencil (and Z) values */
+ switch (pt->format) {
+ case PIPE_FORMAT_S8_UNORM:
+ {
+ const ubyte *src = stmap + srcY * pt->stride;
+ memcpy(sValues, src, width);
+ }
+ break;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ if (format == GL_DEPTH_STENCIL) {
+ const uint *src = (uint *) (stmap + srcY * pt->stride);
+ const GLfloat scale = 1.0f / (0xffffff);
+ GLint k;
+ for (k = 0; k < width; k++) {
+ sValues[k] = src[k] >> 24;
+ zValues[k] = (src[k] & 0xffffff) * scale;
+ }
+ }
+ else {
+ const uint *src = (uint *) (stmap + srcY * pt->stride);
+ GLint k;
+ for (k = 0; k < width; k++) {
+ sValues[k] = src[k] >> 24;
+ }
+ }
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ if (format == GL_DEPTH_STENCIL) {
+ const uint *src = (uint *) (stmap + srcY * pt->stride);
+ const GLfloat scale = 1.0f / (0xffffff);
+ GLint k;
+ for (k = 0; k < width; k++) {
+ sValues[k] = src[k] & 0xff;
+ zValues[k] = (src[k] >> 8) * scale;
+ }
+ }
+ else {
+ const uint *src = (uint *) (stmap + srcY * pt->stride);
+ GLint k;
+ for (k = 0; k < width; k++) {
+ sValues[k] = src[k] & 0xff;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ /* store */
+ dest = _mesa_image_address2d(packing, pixels, width, height,
+ format, type, j, 0);
+ if (format == GL_DEPTH_STENCIL) {
+ _mesa_pack_depth_stencil_span(ctx, width, dest,
+ zValues, sValues, packing);
+ }
+ else {
+ _mesa_pack_stencil_span(ctx, width, type, dest, sValues, packing);
+ }
+ }
+
+ /* unmap the stencil buffer */
+ screen->transfer_unmap(screen, pt);
+ screen->tex_transfer_destroy(pt);
+}
+
+
+/**
+ * Return renderbuffer to use for reading color pixels for glRead/CopyPixel
+ * commands.
+ * Special care is needed for the front buffer.
+ */
+struct st_renderbuffer *
+st_get_color_read_renderbuffer(GLcontext *ctx)
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->_ColorReadBuffer);
+ struct st_renderbuffer *front =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+
+ if (strb == front
+ && ctx->st->frontbuffer_status == FRONT_STATUS_COPY_OF_BACK) {
+ /* reading from front color buffer, which is a logical copy of the
+ * back color buffer.
+ */
+ struct st_renderbuffer *back =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ strb = back;
+ }
+
+ return strb;
+}
+
+
+/**
+ * Try to do glReadPixels in a fast manner for common cases.
+ * \return GL_TRUE for success, GL_FALSE for failure
+ */
+static GLboolean
+st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+ enum combination {
+ A8R8G8B8_UNORM_TO_RGBA_UBYTE,
+ A8R8G8B8_UNORM_TO_RGB_UBYTE,
+ A8R8G8B8_UNORM_TO_BGRA_UINT
+ } combo;
+
+ if (ctx->_ImageTransferState)
+ return GL_FALSE;
+
+ if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM &&
+ format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ combo = A8R8G8B8_UNORM_TO_RGBA_UBYTE;
+ }
+ else if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM &&
+ format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ combo = A8R8G8B8_UNORM_TO_RGB_UBYTE;
+ }
+ else if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM &&
+ format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
+ combo = A8R8G8B8_UNORM_TO_BGRA_UINT;
+ }
+ else {
+ return GL_FALSE;
+ }
+
+ /*printf("st_fast_readpixels combo %d\n", (GLint) combo);*/
+
+ {
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_transfer *trans;
+ const GLubyte *map;
+ GLubyte *dst;
+ GLint row, col, dy, dstStride;
+
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ y = strb->texture->height[0] - y - height;
+ }
+
+ trans = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, x, y,
+ width, height);
+ if (!trans) {
+ return GL_FALSE;
+ }
+
+ map = screen->transfer_map(screen, trans);
+ if (!map) {
+ screen->tex_transfer_destroy(trans);
+ return GL_FALSE;
+ }
+
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ y = height - 1;
+ dy = -1;
+ }
+ else {
+ y = 0;
+ dy = 1;
+ }
+
+ dst = _mesa_image_address2d(pack, dest, width, height,
+ format, type, 0, 0);
+ dstStride = _mesa_image_row_stride(pack, width, format, type);
+
+ switch (combo) {
+ case A8R8G8B8_UNORM_TO_RGBA_UBYTE:
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = map + y * trans->stride;
+ for (col = 0; col < width; col++) {
+ GLuint pixel = ((GLuint *) src)[col];
+ dst[col*4+0] = (pixel >> 16) & 0xff;
+ dst[col*4+1] = (pixel >> 8) & 0xff;
+ dst[col*4+2] = (pixel >> 0) & 0xff;
+ dst[col*4+3] = (pixel >> 24) & 0xff;
+ }
+ dst += dstStride;
+ y += dy;
+ }
+ break;
+ case A8R8G8B8_UNORM_TO_RGB_UBYTE:
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = map + y * trans->stride;
+ for (col = 0; col < width; col++) {
+ GLuint pixel = ((GLuint *) src)[col];
+ dst[col*3+0] = (pixel >> 16) & 0xff;
+ dst[col*3+1] = (pixel >> 8) & 0xff;
+ dst[col*3+2] = (pixel >> 0) & 0xff;
+ }
+ dst += dstStride;
+ y += dy;
+ }
+ break;
+ case A8R8G8B8_UNORM_TO_BGRA_UINT:
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = map + y * trans->stride;
+ memcpy(dst, src, 4 * width);
+ dst += dstStride;
+ y += dy;
+ }
+ break;
+ default:
+ ; /* nothing */
+ }
+
+ screen->transfer_unmap(screen, trans);
+ screen->tex_transfer_destroy(trans);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Do glReadPixels by getting rows from the framebuffer transfer with
+ * get_tile(). Convert to requested format/type with Mesa image routines.
+ * Image transfer ops are done in software too.
+ */
+static void
+st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ GLfloat temp[MAX_WIDTH][4];
+ const GLbitfield transferOps = ctx->_ImageTransferState;
+ GLsizei i, j;
+ GLint yStep, dfStride;
+ GLfloat *df;
+ struct st_renderbuffer *strb;
+ struct gl_pixelstore_attrib clippedPacking = *pack;
+ struct pipe_transfer *trans;
+
+ assert(ctx->ReadBuffer->Width > 0);
+
+ /* XXX convolution not done yet */
+ assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0);
+
+ /* Do all needed clipping here, so that we can forget about it later */
+ if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
+ /* The ReadPixels transfer is totally outside the window bounds */
+ return;
+ }
+
+ dest = _mesa_map_pbo_dest(ctx, &clippedPacking, dest);
+ if (!dest)
+ return;
+
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ if (format == GL_STENCIL_INDEX ||
+ format == GL_DEPTH_STENCIL) {
+ st_read_stencil_pixels(ctx, x, y, width, height,
+ format, type, pack, dest);
+ return;
+ }
+ else if (format == GL_DEPTH_COMPONENT) {
+ strb = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
+ }
+ else {
+ /* Read color buffer */
+ strb = st_get_color_read_renderbuffer(ctx);
+ }
+
+ if (!strb)
+ return;
+
+ /* try a fast-path readpixels before anything else */
+ if (st_fast_readpixels(ctx, strb, x, y, width, height,
+ format, type, pack, dest)) {
+ /* success! */
+ _mesa_unmap_pbo_dest(ctx, &clippedPacking);
+ return;
+ }
+
+ if (format == GL_RGBA && type == GL_FLOAT) {
+ /* write tile(row) directly into user's buffer */
+ df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width,
+ height, format, type, 0, 0);
+ dfStride = width * 4;
+ }
+ else {
+ /* write tile(row) into temp row buffer */
+ df = (GLfloat *) temp;
+ dfStride = 0;
+ }
+
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ y = strb->Base.Height - y - height;
+ }
+
+ /* Create a read transfer from the renderbuffer's texture */
+ trans = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ, x, y,
+ width, height);
+
+ /* determine bottom-to-top vs. top-to-bottom order */
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ y = height - 1;
+ yStep = -1;
+ }
+ else {
+ y = 0;
+ yStep = 1;
+ }
+
+ /*
+ * Copy pixels from pipe_transfer to user memory
+ */
+ {
+ /* dest of first pixel in client memory */
+ GLubyte *dst = _mesa_image_address2d(&clippedPacking, dest, width,
+ height, format, type, 0, 0);
+ /* dest row stride */
+ const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width,
+ format, type);
+
+ if (trans->format == PIPE_FORMAT_S8Z24_UNORM ||
+ trans->format == PIPE_FORMAT_X8Z24_UNORM) {
+ if (format == GL_DEPTH_COMPONENT) {
+ for (i = 0; i < height; i++) {
+ GLuint ztemp[MAX_WIDTH];
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / ((1 << 24) - 1);
+ pipe_get_tile_raw(trans, 0, y, width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff));
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
+ }
+ else {
+ /* XXX: unreachable code -- should be before st_read_stencil_pixels */
+ assert(format == GL_DEPTH_STENCIL_EXT);
+ for (i = 0; i < height; i++) {
+ GLuint *zshort = (GLuint *)dst;
+ pipe_get_tile_raw(trans, 0, y, width, 1, dst, 0);
+ y += yStep;
+ /* Reverse into 24/8 */
+ for (j = 0; j < width; j++) {
+ zshort[j] = (zshort[j] << 8) | (zshort[j] >> 24);
+ }
+ dst += dstStride;
+ }
+ }
+ }
+ else if (trans->format == PIPE_FORMAT_Z24S8_UNORM ||
+ trans->format == PIPE_FORMAT_Z24X8_UNORM) {
+ if (format == GL_DEPTH_COMPONENT) {
+ for (i = 0; i < height; i++) {
+ GLuint ztemp[MAX_WIDTH];
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / ((1 << 24) - 1);
+ pipe_get_tile_raw(trans, 0, y, width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * ((ztemp[j] >> 8) & 0xffffff));
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
+ }
+ else {
+ /* XXX: unreachable code -- should be before st_read_stencil_pixels */
+ assert(format == GL_DEPTH_STENCIL_EXT);
+ for (i = 0; i < height; i++) {
+ pipe_get_tile_raw(trans, 0, y, width, 1, dst, 0);
+ y += yStep;
+ dst += dstStride;
+ }
+ }
+ }
+ else if (trans->format == PIPE_FORMAT_Z16_UNORM) {
+ for (i = 0; i < height; i++) {
+ GLushort ztemp[MAX_WIDTH];
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / 0xffff;
+ pipe_get_tile_raw(trans, 0, y, width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * ztemp[j]);
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
+ }
+ else if (trans->format == PIPE_FORMAT_Z32_UNORM) {
+ for (i = 0; i < height; i++) {
+ GLuint ztemp[MAX_WIDTH];
+ GLfloat zfloat[MAX_WIDTH];
+ const double scale = 1.0 / 0xffffffff;
+ pipe_get_tile_raw(trans, 0, y, width, 1, ztemp, 0);
+ y += yStep;
+ for (j = 0; j < width; j++) {
+ zfloat[j] = (float) (scale * ztemp[j]);
+ }
+ _mesa_pack_depth_span(ctx, width, dst, type,
+ zfloat, &clippedPacking);
+ dst += dstStride;
+ }
+ }
+ else {
+ /* RGBA format */
+ /* Do a row at a time to flip image data vertically */
+ for (i = 0; i < height; i++) {
+ pipe_get_tile_rgba(trans, 0, y, width, 1, df);
+ y += yStep;
+ df += dfStride;
+ if (!dfStride) {
+ _mesa_pack_rgba_span_float(ctx, width, temp, format, type, dst,
+ &clippedPacking, transferOps);
+ dst += dstStride;
+ }
+ }
+ }
+ }
+
+ screen->tex_transfer_destroy(trans);
+
+ _mesa_unmap_pbo_dest(ctx, &clippedPacking);
+}
+
+
+void st_init_readpixels_functions(struct dd_function_table *functions)
+{
+ functions->ReadPixels = st_readpixels;
+}
diff --git a/src/mesa/state_tracker/st_cb_readpixels.h b/src/mesa/state_tracker/st_cb_readpixels.h
new file mode 100644
index 0000000000..c90ef02906
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_readpixels.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_READPIXELS_H
+#define ST_CB_READPIXELS_H
+
+extern struct st_renderbuffer *
+st_get_color_read_renderbuffer(GLcontext *ctx);
+
+extern void
+st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ GLvoid *pixels);
+
+extern void
+st_init_readpixels_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_READPIXELS_H */
diff --git a/src/mesa/state_tracker/st_cb_strings.c b/src/mesa/state_tracker/st_cb_strings.c
new file mode 100644
index 0000000000..bb931f17c4
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_strings.c
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/version.h"
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "st_context.h"
+#include "st_cb_strings.h"
+
+#define ST_VERSION_STRING "0.3"
+
+static const GLubyte *
+st_get_string(GLcontext * ctx, GLenum name)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_screen *screen = st->pipe->screen;
+
+ switch (name) {
+ case GL_VENDOR: {
+ const char *vendor = screen->get_vendor( screen );
+ util_snprintf(st->vendor, sizeof(st->vendor), "%s", vendor);
+ return (GLubyte *) st->vendor;
+ }
+
+ case GL_RENDERER:
+ util_snprintf(st->renderer, sizeof(st->renderer), "Gallium %s on %s",
+ ST_VERSION_STRING,
+ screen->get_name( screen ));
+
+ return (GLubyte *) st->renderer;
+
+ default:
+ return NULL;
+ }
+}
+
+
+void st_init_string_functions(struct dd_function_table *functions)
+{
+ functions->GetString = st_get_string;
+}
diff --git a/src/mesa/state_tracker/st_cb_strings.h b/src/mesa/state_tracker/st_cb_strings.h
new file mode 100644
index 0000000000..3b765aaa59
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_strings.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_STRINGS_H
+#define ST_CB_STRINGS_H
+
+
+extern void
+st_init_string_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_CLEAR_H */
+
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
new file mode 100644
index 0000000000..462f105e75
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -0,0 +1,1993 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/mfeatures.h"
+#include "main/bufferobj.h"
+#if FEATURE_convolve
+#include "main/convolve.h"
+#endif
+#include "main/enums.h"
+#include "main/image.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mipmap.h"
+#include "main/pixel.h"
+#include "main/texcompress.h"
+#include "main/texformat.h"
+#include "main/texgetimage.h"
+#include "main/teximage.h"
+#include "main/texobj.h"
+#include "main/texstore.h"
+
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_cb_fbo.h"
+#include "state_tracker/st_cb_texture.h"
+#include "state_tracker/st_format.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_texture.h"
+#include "state_tracker/st_gen_mipmap.h"
+#include "state_tracker/st_inlines.h"
+#include "state_tracker/st_atom.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_tile.h"
+#include "util/u_blit.h"
+#include "util/u_surface.h"
+#include "util/u_math.h"
+
+
+#define DBG if (0) printf
+
+
+static enum pipe_texture_target
+gl_target_to_pipe(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ return PIPE_TEXTURE_1D;
+
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE_NV:
+ return PIPE_TEXTURE_2D;
+
+ case GL_TEXTURE_3D:
+ return PIPE_TEXTURE_3D;
+
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ return PIPE_TEXTURE_CUBE;
+
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+/**
+ * Return nominal bytes per texel for a compressed format, 0 for non-compressed
+ * format.
+ */
+static GLuint
+compressed_num_bytes(GLuint mesaFormat)
+{
+ switch(mesaFormat) {
+#if FEATURE_texture_fxt1
+ case MESA_FORMAT_RGB_FXT1:
+ case MESA_FORMAT_RGBA_FXT1:
+#endif
+#if FEATURE_texture_s3tc
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+ return 2;
+ case MESA_FORMAT_RGBA_DXT3:
+ case MESA_FORMAT_RGBA_DXT5:
+ return 4;
+#endif
+ default:
+ return 0;
+ }
+}
+
+
+static GLboolean
+is_compressed_mesa_format(const struct gl_texture_format *format)
+{
+ switch (format->MesaFormat) {
+#if FEATURE_texture_s3tc
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+ case MESA_FORMAT_RGBA_DXT3:
+ case MESA_FORMAT_RGBA_DXT5:
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+ return GL_TRUE;
+#endif
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/** called via ctx->Driver.NewTextureImage() */
+static struct gl_texture_image *
+st_NewTextureImage(GLcontext * ctx)
+{
+ DBG("%s\n", __FUNCTION__);
+ (void) ctx;
+ return (struct gl_texture_image *) ST_CALLOC_STRUCT(st_texture_image);
+}
+
+
+/** called via ctx->Driver.NewTextureObject() */
+static struct gl_texture_object *
+st_NewTextureObject(GLcontext * ctx, GLuint name, GLenum target)
+{
+ struct st_texture_object *obj = ST_CALLOC_STRUCT(st_texture_object);
+
+ DBG("%s\n", __FUNCTION__);
+ _mesa_initialize_texture_object(&obj->base, name, target);
+
+ return &obj->base;
+}
+
+/** called via ctx->Driver.DeleteTextureImage() */
+static void
+st_DeleteTextureObject(GLcontext *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ if (stObj->pt)
+ pipe_texture_reference(&stObj->pt, NULL);
+
+ _mesa_delete_texture_object(ctx, texObj);
+}
+
+
+/** called via ctx->Driver.FreeTexImageData() */
+static void
+st_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
+{
+ struct st_texture_image *stImage = st_texture_image(texImage);
+
+ DBG("%s\n", __FUNCTION__);
+
+ if (stImage->pt) {
+ pipe_texture_reference(&stImage->pt, NULL);
+ }
+
+ if (texImage->Data) {
+ _mesa_align_free(texImage->Data);
+ texImage->Data = NULL;
+ }
+}
+
+
+/**
+ * From linux kernel i386 header files, copes with odd sizes better
+ * than COPY_DWORDS would:
+ * XXX Put this in src/mesa/main/imports.h ???
+ */
+#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86)
+static INLINE void *
+__memcpy(void *to, const void *from, size_t n)
+{
+ int d0, d1, d2;
+ __asm__ __volatile__("rep ; movsl\n\t"
+ "testb $2,%b4\n\t"
+ "je 1f\n\t"
+ "movsw\n"
+ "1:\ttestb $1,%b4\n\t"
+ "je 2f\n\t"
+ "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
+ :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
+ :"memory");
+ return (to);
+}
+#else
+#define __memcpy(a,b,c) memcpy(a,b,c)
+#endif
+
+
+/**
+ * The system memcpy (at least on ubuntu 5.10) has problems copying
+ * to agp (writecombined) memory from a source which isn't 64-byte
+ * aligned - there is a 4x performance falloff.
+ *
+ * The x86 __memcpy is immune to this but is slightly slower
+ * (10%-ish) than the system memcpy.
+ *
+ * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
+ * isn't much faster than x86_memcpy for agp copies.
+ *
+ * TODO: switch dynamically.
+ */
+static void *
+do_memcpy(void *dest, const void *src, size_t n)
+{
+ if ((((unsigned long) src) & 63) || (((unsigned long) dest) & 63)) {
+ return __memcpy(dest, src, n);
+ }
+ else
+ return memcpy(dest, src, n);
+}
+
+
+/**
+ * Return default texture usage bitmask for the given texture format.
+ */
+static GLuint
+default_usage(enum pipe_format fmt)
+{
+ GLuint usage = PIPE_TEXTURE_USAGE_SAMPLER;
+ if (pf_is_depth_stencil(fmt))
+ usage |= PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ else
+ usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ return usage;
+}
+
+
+/**
+ * Allocate a pipe_texture object for the given st_texture_object using
+ * the given st_texture_image to guess the mipmap size/levels.
+ *
+ * [comments...]
+ * Otherwise, store it in memory if (Border != 0) or (any dimension ==
+ * 1).
+ *
+ * Otherwise, if max_level >= level >= min_level, create texture with
+ * space for images from min_level down to max_level.
+ *
+ * Otherwise, create texture with space for images from (level 0)..(1x1).
+ * Consider pruning this texture at a validation if the saving is worth it.
+ */
+static void
+guess_and_alloc_texture(struct st_context *st,
+ struct st_texture_object *stObj,
+ const struct st_texture_image *stImage)
+{
+ GLuint firstLevel;
+ GLuint lastLevel;
+ GLuint width = stImage->base.Width2; /* size w/out border */
+ GLuint height = stImage->base.Height2;
+ GLuint depth = stImage->base.Depth2;
+ GLuint i, usage;
+ enum pipe_format fmt;
+
+ DBG("%s\n", __FUNCTION__);
+
+ assert(!stObj->pt);
+
+ if (stObj->pt &&
+ (GLint) stImage->level > stObj->base.BaseLevel &&
+ (stImage->base.Width == 1 ||
+ (stObj->base.Target != GL_TEXTURE_1D &&
+ stImage->base.Height == 1) ||
+ (stObj->base.Target == GL_TEXTURE_3D &&
+ stImage->base.Depth == 1)))
+ return;
+
+ /* If this image disrespects BaseLevel, allocate from level zero.
+ * Usually BaseLevel == 0, so it's unlikely to happen.
+ */
+ if ((GLint) stImage->level < stObj->base.BaseLevel)
+ firstLevel = 0;
+ else
+ firstLevel = stObj->base.BaseLevel;
+
+
+ /* Figure out image dimensions at start level.
+ */
+ for (i = stImage->level; i > firstLevel; i--) {
+ if (width != 1)
+ width <<= 1;
+ if (height != 1)
+ height <<= 1;
+ if (depth != 1)
+ depth <<= 1;
+ }
+
+ if (width == 0 || height == 0 || depth == 0) {
+ /* no texture needed */
+ return;
+ }
+
+ /* Guess a reasonable value for lastLevel. This is probably going
+ * to be wrong fairly often and might mean that we have to look at
+ * resizable buffers, or require that buffers implement lazy
+ * pagetable arrangements.
+ */
+ if ((stObj->base.MinFilter == GL_NEAREST ||
+ stObj->base.MinFilter == GL_LINEAR ||
+ stImage->base._BaseFormat == GL_DEPTH_COMPONENT ||
+ stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) &&
+ stImage->level == firstLevel) {
+ lastLevel = firstLevel;
+ }
+ else {
+ GLuint l2width = util_logbase2(width);
+ GLuint l2height = util_logbase2(height);
+ GLuint l2depth = util_logbase2(depth);
+ lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
+ }
+
+ fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat);
+
+ usage = default_usage(fmt);
+
+ stObj->pt = st_texture_create(st,
+ gl_target_to_pipe(stObj->base.Target),
+ fmt,
+ lastLevel,
+ width,
+ height,
+ depth,
+ usage);
+
+ DBG("%s - success\n", __FUNCTION__);
+}
+
+
+/**
+ * Adjust pixel unpack params and image dimensions to strip off the
+ * texture border.
+ * Gallium doesn't support texture borders. They've seldem been used
+ * and seldom been implemented correctly anyway.
+ * \param unpackNew returns the new pixel unpack parameters
+ */
+static void
+strip_texture_border(GLint border,
+ GLint *width, GLint *height, GLint *depth,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_pixelstore_attrib *unpackNew)
+{
+ assert(border > 0); /* sanity check */
+
+ *unpackNew = *unpack;
+
+ if (unpackNew->RowLength == 0)
+ unpackNew->RowLength = *width;
+
+ if (depth && unpackNew->ImageHeight == 0)
+ unpackNew->ImageHeight = *height;
+
+ unpackNew->SkipPixels += border;
+ if (height)
+ unpackNew->SkipRows += border;
+ if (depth)
+ unpackNew->SkipImages += border;
+
+ assert(*width >= 3);
+ *width = *width - 2 * border;
+ if (height && *height >= 3)
+ *height = *height - 2 * border;
+ if (depth && *depth >= 3)
+ *depth = *depth - 2 * 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(GLcontext * 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 pipe_screen *screen = ctx->st->pipe->screen;
+ const struct gl_texture_format *mesa_format;
+ struct pipe_texture templ;
+ struct pipe_texture *src_tex;
+ struct pipe_surface *dst_surface;
+ 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) */
+ dst_surface = screen->get_tex_surface(screen, stImage->pt,
+ stImage->face, stImage->level, 0,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+ 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 = PIPE_TEXTURE_2D;
+ templ.format = st_mesa_format_to_pipe_format(mesa_format->MesaFormat);
+ pf_get_block(templ.format, &templ.block);
+ templ.width[0] = width;
+ templ.height[0] = height;
+ templ.depth[0] = 1;
+ templ.last_level = 0;
+ templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+ src_tex = screen->texture_create(screen, &templ);
+
+ if (!src_tex)
+ return GL_FALSE;
+
+ /* Put user's tex data into the temporary texture
+ */
+ tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx), src_tex,
+ 0, 0, 0, /* face, level are zero */
+ PIPE_TRANSFER_WRITE,
+ 0, 0, width, height); /* x, y, w, h */
+ map = screen->transfer_map(screen, tex_xfer);
+
+ mesa_format->StoreImage(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 */
+
+ screen->transfer_unmap(screen, tex_xfer);
+ screen->tex_transfer_destroy(tex_xfer);
+
+ /* copy / compress image */
+ util_blit_pixels_tex(ctx->st->blit,
+ src_tex, /* pipe_texture (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_texture_reference(&src_tex, NULL);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Do glTexImage1/2/3D().
+ */
+static void
+st_TexImage(GLcontext * ctx,
+ GLint dims,
+ GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth,
+ GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ GLsizei imageSize, GLboolean compressed_src)
+{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ GLint postConvWidth, postConvHeight;
+ GLint texelBytes, sizeInBytes;
+ GLuint dstRowStride = 0;
+ struct gl_pixelstore_attrib unpackNB;
+ enum pipe_transfer_usage transfer_usage = 0;
+
+ DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
+
+ /* switch to "normal" */
+ if (stObj->surface_based) {
+ _mesa_clear_texture_object(ctx, texObj);
+ stObj->surface_based = GL_FALSE;
+ }
+
+ /* gallium does not support texture borders, strip it off */
+ if (border) {
+ strip_texture_border(border, &width, &height, &depth, unpack, &unpackNB);
+ unpack = &unpackNB;
+ texImage->Width = width;
+ texImage->Height = height;
+ texImage->Depth = depth;
+ texImage->Border = 0;
+ border = 0;
+ }
+
+ postConvWidth = width;
+ postConvHeight = height;
+
+ stImage->face = _mesa_tex_target_to_face(target);
+ stImage->level = level;
+
+#if FEATURE_convolve
+ if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
+ _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
+ &postConvHeight);
+ }
+#endif
+
+ /* choose the texture format */
+ texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
+ format, type);
+
+ _mesa_set_fetch_functions(texImage, dims);
+
+ if (texImage->TexFormat->TexelBytes == 0) {
+ /* must be a compressed format */
+ texelBytes = 0;
+ texImage->IsCompressed = GL_TRUE;
+ texImage->CompressedSize =
+ ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
+ texImage->Height, texImage->Depth,
+ texImage->TexFormat->MesaFormat);
+ }
+ else {
+ texelBytes = texImage->TexFormat->TexelBytes;
+
+ /* Minimum pitch of 32 bytes */
+ if (postConvWidth * texelBytes < 32) {
+ postConvWidth = 32 / texelBytes;
+ texImage->RowStride = postConvWidth;
+ }
+
+ /* we'll set RowStride elsewhere when the texture is a "mapped" state */
+ /*assert(texImage->RowStride == postConvWidth);*/
+ }
+
+ /* Release the reference to a potentially orphaned buffer.
+ * Release any old malloced memory.
+ */
+ if (stImage->pt) {
+ pipe_texture_reference(&stImage->pt, NULL);
+ assert(!texImage->Data);
+ }
+ else if (texImage->Data) {
+ _mesa_align_free(texImage->Data);
+ }
+
+ if (width == 0 || height == 0 || depth == 0) {
+ /* stop after freeing old image */
+ return;
+ }
+
+ /* If this is the only mipmap level in the texture, could call
+ * bmBufferData with NULL data to free the old block and avoid
+ * waiting on any outstanding fences.
+ */
+ if (stObj->pt) {
+ if (stObj->teximage_realloc ||
+ level > (GLint) stObj->pt->last_level ||
+ (stObj->pt->last_level == level &&
+ stObj->pt->target != PIPE_TEXTURE_CUBE &&
+ !st_texture_match_image(stObj->pt, &stImage->base,
+ stImage->face, stImage->level))) {
+ DBG("release it\n");
+ pipe_texture_reference(&stObj->pt, NULL);
+ assert(!stObj->pt);
+ stObj->teximage_realloc = FALSE;
+ }
+ }
+
+ if (!stObj->pt) {
+ guess_and_alloc_texture(ctx->st, stObj, stImage);
+ if (!stObj->pt) {
+ /* Probably out of memory.
+ * Try flushing any pending rendering, then retry.
+ */
+ st_finish(ctx->st);
+ guess_and_alloc_texture(ctx->st, stObj, stImage);
+ if (!stObj->pt) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ return;
+ }
+ }
+ }
+
+ assert(!stImage->pt);
+
+ if (stObj->pt &&
+ st_texture_match_image(stObj->pt, &stImage->base,
+ stImage->face, stImage->level)) {
+
+ pipe_texture_reference(&stImage->pt, stObj->pt);
+ assert(stImage->pt);
+ }
+
+ if (!stImage->pt)
+ DBG("XXX: Image did not fit into texture - storing in local memory!\n");
+
+ /* st_CopyTexImage calls this function with pixels == NULL, with
+ * the expectation that the texture will be set up but nothing
+ * more will be done. This is where those calls return:
+ */
+ if (compressed_src) {
+ pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
+ unpack,
+ "glCompressedTexImage");
+ }
+ else {
+ pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
+ format, type,
+ pixels, unpack, "glTexImage");
+ }
+ if (!pixels)
+ return;
+
+ /* See if we can do texture compression with a blit/render.
+ */
+ if (!compressed_src &&
+ !ctx->Mesa_DXTn &&
+ is_compressed_mesa_format(texImage->TexFormat) &&
+ screen->is_format_supported(screen,
+ stImage->pt->format,
+ stImage->pt->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth,
+ format, type, pixels, unpack, texImage)) {
+ goto done;
+ }
+ }
+
+ if (stImage->pt) {
+ if (format == GL_DEPTH_COMPONENT &&
+ pf_is_depth_and_stencil(stImage->pt->format))
+ transfer_usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ transfer_usage = PIPE_TRANSFER_WRITE;
+
+ texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
+ transfer_usage, 0, 0,
+ stImage->base.Width,
+ stImage->base.Height);
+ if(stImage->transfer)
+ dstRowStride = stImage->transfer->stride;
+ }
+ else {
+ /* Allocate regular memory and store the image there temporarily. */
+ if (texImage->IsCompressed) {
+ sizeInBytes = texImage->CompressedSize;
+ dstRowStride =
+ _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
+ assert(dims != 3);
+ }
+ else {
+ dstRowStride = postConvWidth * texelBytes;
+ sizeInBytes = depth * dstRowStride * postConvHeight;
+ }
+
+ texImage->Data = _mesa_align_malloc(sizeInBytes, 16);
+ }
+
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ return;
+ }
+
+ DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
+ width, height, depth, width * texelBytes, dstRowStride);
+
+ /* Copy data. Would like to know when it's ok for us to eg. use
+ * the blitter to copy. Or, use the hardware to do the format
+ * conversion and copy:
+ */
+ if (compressed_src) {
+ memcpy(texImage->Data, pixels, imageSize);
+ }
+ else {
+ const GLuint srcImageStride =
+ _mesa_image_image_stride(unpack, width, height, format, type);
+ GLint i;
+ const GLubyte *src = (const GLubyte *) pixels;
+
+ for (i = 0; i < depth; i++) {
+ if (!texImage->TexFormat->StoreImage(ctx, dims,
+ texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ format, type, src, unpack)) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ }
+
+ if (stImage->pt && i + 1 < depth) {
+ /* unmap this slice */
+ st_texture_image_unmap(ctx->st, stImage);
+ /* map next slice of 3D texture */
+ texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1,
+ transfer_usage, 0, 0,
+ stImage->base.Width,
+ stImage->base.Height);
+ src += srcImageStride;
+ }
+ }
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, unpack);
+
+done:
+ if (stImage->pt && texImage->Data) {
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = NULL;
+ }
+
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+static void
+st_TexImage3D(GLcontext * ctx,
+ GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth,
+ GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexImage(ctx, 3, target, level, internalFormat, width, height, depth,
+ border, format, type, pixels, unpack, texObj, texImage,
+ 0, GL_FALSE);
+}
+
+
+static void
+st_TexImage2D(GLcontext * ctx,
+ GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border,
+ format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
+}
+
+
+static void
+st_TexImage1D(GLcontext * ctx,
+ GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexImage(ctx, 1, target, level, internalFormat, width, 1, 1, border,
+ format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
+}
+
+
+static void
+st_CompressedTexImage2D(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border,
+ 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, GL_TRUE);
+}
+
+
+
+/**
+ * glGetTexImage() helper: decompress a compressed texture by rendering
+ * a textured quad. Store the results in the user's buffer.
+ */
+static void
+decompress_with_blit(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ const GLuint width = texImage->Width;
+ const GLuint height = texImage->Height;
+ struct pipe_surface *dst_surface;
+ struct pipe_texture *dst_texture;
+ struct pipe_transfer *tex_xfer;
+
+ /* create temp / dest surface */
+ if (!util_create_rgba_surface(screen, width, height,
+ &dst_texture, &dst_surface)) {
+ _mesa_problem(ctx, "util_create_rgba_surface() failed "
+ "in decompress_with_blit()");
+ return;
+ }
+
+ /* blit/render/decompress */
+ util_blit_pixels_tex(ctx->st->blit,
+ stImage->pt, /* pipe_texture (src) */
+ 0, 0, /* src x0, y0 */
+ width, height, /* src x1, y1 */
+ dst_surface, /* pipe_surface (dst) */
+ 0, 0, /* dst x0, y0 */
+ width, height, /* dst x1, y1 */
+ 0.0, /* z */
+ PIPE_TEX_MIPFILTER_NEAREST);
+
+ /* map the dst_surface so we can read from it */
+ tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx),
+ dst_texture, 0, 0, 0,
+ PIPE_TRANSFER_READ,
+ 0, 0, width, height);
+
+ pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels);
+
+ /* copy/pack data into user buffer */
+ if (st_equal_formats(stImage->pt->format, format, type)) {
+ /* memcpy */
+ const uint bytesPerRow = width * pf_get_size(stImage->pt->format);
+ ubyte *map = screen->transfer_map(screen, tex_xfer);
+ GLuint row;
+ for (row = 0; row < height; row++) {
+ GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
+ height, format, type, row, 0);
+ memcpy(dest, map, bytesPerRow);
+ map += tex_xfer->stride;
+ }
+ screen->transfer_unmap(screen, tex_xfer);
+ }
+ else {
+ /* format translation via floats */
+ GLuint row;
+ for (row = 0; row < height; row++) {
+ const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
+ GLfloat rgba[4 * MAX_WIDTH];
+ GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
+ height, format, type, row, 0);
+
+ /* get float[4] rgba row from surface */
+ pipe_get_tile_rgba(tex_xfer, 0, row, width, 1, rgba);
+
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
+ type, dest, &ctx->Pack, transferOps);
+ }
+ }
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+
+ /* destroy the temp / dest surface */
+ util_destroy_rgba_surface(dst_texture, dst_surface);
+}
+
+
+
+/**
+ * Need to map texture image into memory before copying image data,
+ * then unmap it.
+ */
+static void
+st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid * pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage, GLboolean compressed_dst)
+{
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ const GLuint dstImageStride =
+ _mesa_image_image_stride(&ctx->Pack, texImage->Width, texImage->Height,
+ format, type);
+ GLuint depth, i;
+ GLubyte *dest;
+
+ if (stImage->pt &&
+ pf_is_compressed(stImage->pt->format) &&
+ !compressed_dst) {
+ /* Need to decompress the texture.
+ * We'll do this by rendering a textured quad.
+ * Note that we only expect RGBA formats (no Z/depth formats).
+ */
+ decompress_with_blit(ctx, target, level, format, type, pixels,
+ texObj, texImage);
+ return;
+ }
+
+ /* Map */
+ if (stImage->pt) {
+ /* Image is stored in hardware format in a buffer managed by the
+ * kernel. Need to explicitly map and unmap it.
+ */
+ unsigned face = _mesa_tex_target_to_face(target);
+
+ st_teximage_flush_before_map(ctx->st, stImage->pt, face, level,
+ PIPE_TRANSFER_READ);
+
+ texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
+ PIPE_TRANSFER_READ, 0, 0,
+ stImage->base.Width,
+ stImage->base.Height);
+ texImage->RowStride = stImage->transfer->stride / stImage->pt->block.size;
+ }
+ else {
+ /* Otherwise, the image should actually be stored in
+ * texImage->Data. This is pretty confusing for
+ * everybody, I'd much prefer to separate the two functions of
+ * texImage->Data - storage for texture images in main memory
+ * and access (ie mappings) of images. In other words, we'd
+ * create a new texImage->Map field and leave Data simply for
+ * storage.
+ */
+ assert(texImage->Data);
+ }
+
+ depth = texImage->Depth;
+ texImage->Depth = 1;
+
+ dest = (GLubyte *) pixels;
+
+ for (i = 0; i < depth; i++) {
+ if (compressed_dst) {
+ _mesa_get_compressed_teximage(ctx, target, level, dest,
+ texObj, texImage);
+ }
+ else {
+ _mesa_get_teximage(ctx, target, level, format, type, dest,
+ texObj, texImage);
+ }
+
+ if (stImage->pt && i + 1 < depth) {
+ /* unmap this slice */
+ st_texture_image_unmap(ctx->st, stImage);
+ /* map next slice of 3D texture */
+ texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1,
+ PIPE_TRANSFER_READ, 0, 0,
+ stImage->base.Width,
+ stImage->base.Height);
+ dest += dstImageStride;
+ }
+ }
+
+ texImage->Depth = depth;
+
+ /* Unmap */
+ if (stImage->pt) {
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = NULL;
+ }
+}
+
+
+static void
+st_GetTexImage(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid * pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_get_tex_image(ctx, target, level, format, type, pixels, texObj, texImage,
+ GL_FALSE);
+}
+
+
+static void
+st_GetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_get_tex_image(ctx, target, level, 0, 0, pixels, texObj, texImage,
+ GL_TRUE);
+}
+
+
+
+static void
+st_TexSubimage(GLcontext *ctx, GLint dims, 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 *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ struct pipe_screen *screen = ctx->st->pipe->screen;
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ GLuint dstRowStride;
+ const GLuint srcImageStride =
+ _mesa_image_image_stride(packing, width, height, format, type);
+ GLint i;
+ const GLubyte *src;
+ /* init to silence warning only: */
+ enum pipe_transfer_usage transfer_usage = PIPE_TRANSFER_WRITE;
+
+ DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(target),
+ level, xoffset, yoffset, width, height);
+
+ pixels =
+ _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
+ type, pixels, packing, "glTexSubImage2D");
+ if (!pixels)
+ return;
+
+ /* See if we can do texture compression with a blit/render.
+ */
+ if (!ctx->Mesa_DXTn &&
+ is_compressed_mesa_format(texImage->TexFormat) &&
+ screen->is_format_supported(screen,
+ stImage->pt->format,
+ stImage->pt->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ if (compress_with_blit(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, pixels, packing, texImage)) {
+ goto done;
+ }
+ }
+
+ /* Map buffer if necessary. Need to lock to prevent other contexts
+ * from uploading the buffer under us.
+ */
+ if (stImage->pt) {
+ unsigned face = _mesa_tex_target_to_face(target);
+
+ if (format == GL_DEPTH_COMPONENT &&
+ pf_is_depth_and_stencil(stImage->pt->format))
+ transfer_usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ transfer_usage = PIPE_TRANSFER_WRITE;
+
+ st_teximage_flush_before_map(ctx->st, stImage->pt, face, level,
+ transfer_usage);
+ texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset,
+ transfer_usage,
+ xoffset, yoffset,
+ width, height);
+ }
+
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
+ return;
+ }
+
+ src = (const GLubyte *) pixels;
+ dstRowStride = stImage->transfer->stride;
+
+ for (i = 0; i < depth; i++) {
+ if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ 0, 0, 0,
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ format, type, src, packing)) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
+ }
+
+ if (stImage->pt && i + 1 < depth) {
+ /* unmap this slice */
+ st_texture_image_unmap(ctx->st, stImage);
+ /* map next slice of 3D texture */
+ texImage->Data = st_texture_image_map(ctx->st, stImage,
+ zoffset + i + 1,
+ transfer_usage,
+ xoffset, yoffset,
+ width, height);
+ src += srcImageStride;
+ }
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+
+done:
+ if (stImage->pt) {
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = NULL;
+ }
+
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+
+static void
+st_TexSubImage3D(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexSubimage(ctx, 3, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type,
+ pixels, packing, texObj, texImage);
+}
+
+
+static void
+st_TexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexSubimage(ctx, 2, target, level, xoffset, yoffset, 0,
+ width, height, 1, format, type,
+ pixels, packing, texObj, texImage);
+}
+
+
+static void
+st_TexSubImage1D(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width, GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ st_TexSubimage(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1,
+ format, type, pixels, packing, texObj, texImage);
+}
+
+
+static void
+st_CompressedTexSubImage1D(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ assert(0);
+}
+
+
+static void
+st_CompressedTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLint height,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ struct pipe_format_block block;
+ int srcBlockStride;
+ int dstBlockStride;
+ int y;
+
+ if (stImage->pt) {
+ unsigned face = _mesa_tex_target_to_face(target);
+
+ st_teximage_flush_before_map(ctx->st, stImage->pt, face, level,
+ PIPE_TRANSFER_WRITE);
+ texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
+ PIPE_TRANSFER_WRITE,
+ xoffset, yoffset,
+ width, height);
+
+ block = stImage->pt->block;
+ srcBlockStride = pf_get_stride(&block, width);
+ dstBlockStride = stImage->transfer->stride;
+ } else {
+ assert(stImage->pt);
+ /* TODO find good values for block and strides */
+ /* TODO also adjust texImage->data for yoffset/xoffset */
+ return;
+ }
+
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage");
+ return;
+ }
+
+ assert(xoffset % block.width == 0);
+ assert(yoffset % block.height == 0);
+ assert(width % block.width == 0);
+ assert(height % block.height == 0);
+
+ for (y = 0; y < height; y += block.height) {
+ /* don't need to adjust for xoffset and yoffset as st_texture_image_map does that */
+ const char *src = (const char*)data + srcBlockStride * pf_get_nblocksy(&block, y);
+ char *dst = (char*)texImage->Data + dstBlockStride * pf_get_nblocksy(&block, y);
+ memcpy(dst, src, pf_get_stride(&block, width));
+ }
+
+ if (stImage->pt) {
+ st_texture_image_unmap(ctx->st, stImage);
+ texImage->Data = NULL;
+ }
+}
+
+
+static void
+st_CompressedTexSubImage3D(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLint height, GLint depth,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ assert(0);
+}
+
+
+
+/**
+ * Do a CopyTexSubImage operation using a read transfer from the source,
+ * a write transfer to the destination and get_tile()/put_tile() to access
+ * the pixels/texels.
+ *
+ * Note: srcY=0=TOP of renderbuffer
+ */
+static void
+fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
+ struct st_renderbuffer *strb,
+ struct st_texture_image *stImage,
+ GLenum baseFormat,
+ GLint destX, GLint destY, GLint destZ,
+ GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_transfer *src_trans;
+ GLvoid *texDest;
+ enum pipe_transfer_usage transfer_usage;
+
+ assert(width <= MAX_WIDTH);
+
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ srcY = strb->Base.Height - srcY - height;
+ }
+
+ src_trans = st_cond_flush_get_tex_transfer( st_context(ctx),
+ strb->texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_READ,
+ srcX, srcY,
+ width, height);
+
+ if (baseFormat == GL_DEPTH_COMPONENT &&
+ pf_is_depth_and_stencil(stImage->pt->format))
+ transfer_usage = PIPE_TRANSFER_READ_WRITE;
+ else
+ transfer_usage = PIPE_TRANSFER_WRITE;
+
+ st_teximage_flush_before_map(ctx->st, stImage->pt, 0, 0,
+ transfer_usage);
+
+ texDest = st_texture_image_map(ctx->st, stImage, 0, transfer_usage,
+ destX, destY, width, height);
+
+ if (baseFormat == GL_DEPTH_COMPONENT ||
+ baseFormat == GL_DEPTH24_STENCIL8) {
+ const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F ||
+ ctx->Pixel.DepthBias != 0.0F);
+ GLint row, yStep;
+
+ /* determine bottom-to-top vs. top-to-bottom order for src buffer */
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ srcY = height - 1;
+ yStep = -1;
+ }
+ else {
+ srcY = 0;
+ yStep = 1;
+ }
+
+ /* To avoid a large temp memory allocation, do copy row by row */
+ for (row = 0; row < height; row++, srcY += yStep) {
+ uint data[MAX_WIDTH];
+ pipe_get_tile_z(src_trans, 0, srcY, width, 1, data);
+ if (scaleOrBias) {
+ _mesa_scale_and_bias_depth_uint(ctx, width, data);
+ }
+ pipe_put_tile_z(stImage->transfer, 0, row, width, 1, data);
+ }
+ }
+ else {
+ /* RGBA format */
+ GLfloat *tempSrc =
+ (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+
+ if (tempSrc && texDest) {
+ const GLint dims = 2;
+ const GLint dstRowStride = stImage->transfer->stride;
+ struct gl_texture_image *texImage = &stImage->base;
+ struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;
+
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ unpack.Invert = GL_TRUE;
+ }
+
+ /* get float/RGBA image from framebuffer */
+ /* XXX this usually involves a lot of int/float conversion.
+ * try to avoid that someday.
+ */
+ pipe_get_tile_rgba(src_trans, 0, 0, width, height, tempSrc);
+
+ /* Store into texture memory.
+ * Note that this does some special things such as pixel transfer
+ * ops and format conversion. In particular, if the dest tex format
+ * is actually RGBA but the user created the texture as GL_RGB we
+ * need to fill-in/override the alpha channel with 1.0.
+ */
+ texImage->TexFormat->StoreImage(ctx, dims,
+ texImage->_BaseFormat,
+ texImage->TexFormat,
+ texDest,
+ 0, 0, 0,
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ GL_RGBA, GL_FLOAT, tempSrc, /* src */
+ &unpack);
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
+ }
+
+ if (tempSrc)
+ _mesa_free(tempSrc);
+ }
+
+ st_texture_image_unmap(ctx->st, stImage);
+ screen->tex_transfer_destroy(src_trans);
+}
+
+
+static unsigned
+compatible_src_dst_formats(const struct gl_renderbuffer *src,
+ const struct gl_texture_image *dst)
+{
+ const GLenum srcFormat = src->_BaseFormat;
+ const GLenum dstLogicalFormat = dst->_BaseFormat;
+
+ if (srcFormat == dstLogicalFormat) {
+ /* This is the same as matching_base_formats, which should
+ * always pass, as it did previously.
+ */
+ return TGSI_WRITEMASK_XYZW;
+ }
+ else if (srcFormat == GL_RGBA &&
+ dstLogicalFormat == GL_RGB) {
+ /* Add a single special case to cope with RGBA->RGB transfers,
+ * setting A to 1.0 to cope with situations where the RGB
+ * destination is actually stored as RGBA.
+ */
+ return TGSI_WRITEMASK_XYZ; /* A ==> 1.0 */
+ }
+ else {
+ /* Otherwise fail.
+ */
+ return 0;
+ }
+}
+
+
+
+/**
+ * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
+ * Note that the region to copy has already been clipped so we know we
+ * won't read from outside the source renderbuffer's bounds.
+ *
+ * Note: srcY=0=Bottom of renderbuffer (GL convention)
+ */
+static void
+st_copy_texsubimage(GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint destX, GLint destY, GLint destZ,
+ GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height)
+{
+ struct gl_texture_unit *texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj =
+ _mesa_select_tex_object(ctx, texUnit, target);
+ struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, texObj, target, level);
+ struct st_texture_image *stImage = st_texture_image(texImage);
+ const GLenum texBaseFormat = texImage->InternalFormat;
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct st_renderbuffer *strb;
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ enum pipe_format dest_format, src_format;
+ GLboolean use_fallback = GL_TRUE;
+ GLboolean matching_base_formats;
+ GLuint format_writemask;
+ struct pipe_surface *dest_surface = NULL;
+ GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
+
+ /* any rendering in progress must flushed before we grab the fb image */
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* make sure finalize_textures has been called?
+ */
+ if (0) st_validate_state(ctx->st);
+
+ /* determine if copying depth or color data */
+ if (texBaseFormat == GL_DEPTH_COMPONENT ||
+ texBaseFormat == GL_DEPTH24_STENCIL8) {
+ strb = st_renderbuffer(fb->_DepthBuffer);
+ }
+ else if (texBaseFormat == GL_DEPTH_STENCIL_EXT) {
+ strb = st_renderbuffer(fb->_StencilBuffer);
+ }
+ else {
+ /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */
+ strb = st_renderbuffer(fb->_ColorReadBuffer);
+ }
+
+ if (!strb || !strb->surface || !stImage->pt) {
+ debug_printf("%s: null strb or stImage\n", __FUNCTION__);
+ return;
+ }
+
+ if (srcX < 0) {
+ width -= -srcX;
+ destX += -srcX;
+ srcX = 0;
+ }
+
+ if (srcY < 0) {
+ height -= -srcY;
+ destY += -srcY;
+ srcY = 0;
+ }
+
+ if (destX < 0) {
+ width -= -destX;
+ srcX += -destX;
+ destX = 0;
+ }
+
+ if (destY < 0) {
+ height -= -destY;
+ srcY += -destY;
+ destY = 0;
+ }
+
+ if (width < 0 || height < 0)
+ return;
+
+
+ assert(strb);
+ assert(strb->surface);
+ assert(stImage->pt);
+
+ src_format = strb->surface->format;
+ dest_format = stImage->pt->format;
+
+ /*
+ * Determine if the src framebuffer and dest texture have the same
+ * base format. We need this to detect a case such as the framebuffer
+ * being GL_RGBA but the texture being GL_RGB. If the actual hardware
+ * texture format stores RGBA we need to set A=1 (overriding the
+ * framebuffer's alpha values). We can't do that with the blit or
+ * textured-quad paths.
+ */
+ matching_base_formats = (strb->Base._BaseFormat == texImage->_BaseFormat);
+ format_writemask = compatible_src_dst_formats(&strb->Base, texImage);
+
+ if (ctx->_ImageTransferState == 0x0) {
+
+ if (matching_base_formats &&
+ src_format == dest_format &&
+ !do_flip)
+ {
+ /* use surface_copy() / blit */
+
+ dest_surface = screen->get_tex_surface(screen, stImage->pt,
+ stImage->face, stImage->level,
+ destZ,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* for surface_copy(), y=0=top, always */
+ pipe->surface_copy(pipe,
+ /* dest */
+ dest_surface,
+ destX, destY,
+ /* src */
+ strb->surface,
+ srcX, srcY,
+ /* size */
+ width, height);
+ use_fallback = GL_FALSE;
+ }
+ else if (format_writemask &&
+ screen->is_format_supported(screen, src_format,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER,
+ 0) &&
+ screen->is_format_supported(screen, dest_format,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ 0)) {
+ /* draw textured quad to do the copy */
+ GLint srcY0, srcY1;
+
+ dest_surface = screen->get_tex_surface(screen, stImage->pt,
+ stImage->face, stImage->level,
+ destZ,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ if (do_flip) {
+ srcY1 = strb->Base.Height - srcY - height;
+ srcY0 = srcY1 + height;
+ }
+ else {
+ srcY0 = srcY;
+ srcY1 = srcY0 + height;
+ }
+ util_blit_pixels_writemask(ctx->st->blit,
+ strb->surface,
+ srcX, srcY0,
+ srcX + width, srcY1,
+ dest_surface,
+ destX, destY,
+ destX + width, destY + height,
+ 0.0, PIPE_TEX_MIPFILTER_NEAREST,
+ format_writemask);
+ use_fallback = GL_FALSE;
+ }
+
+ if (dest_surface)
+ pipe_surface_reference(&dest_surface, NULL);
+ }
+
+ if (use_fallback) {
+ /* software fallback */
+ fallback_copy_texsubimage(ctx, target, level,
+ strb, stImage, texBaseFormat,
+ destX, destY, destZ,
+ srcX, srcY, width, height);
+ }
+
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+
+static void
+st_CopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLint border)
+{
+ struct gl_texture_unit *texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj =
+ _mesa_select_tex_object(ctx, texUnit, target);
+ struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, texObj, target, level);
+
+ /* Setup or redefine the texture object, texture and texture
+ * image. Don't populate yet.
+ */
+ ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ width, border,
+ GL_RGBA, CHAN_TYPE, NULL,
+ &ctx->DefaultPacking, texObj, texImage);
+
+ st_copy_texsubimage(ctx, target, level,
+ 0, 0, 0, /* destX,Y,Z */
+ x, y, width, 1); /* src X, Y, size */
+}
+
+
+static void
+st_CopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border)
+{
+ struct gl_texture_unit *texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj =
+ _mesa_select_tex_object(ctx, texUnit, target);
+ struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, texObj, target, level);
+
+ /* Setup or redefine the texture object, texture and texture
+ * image. Don't populate yet.
+ */
+ ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ width, height, border,
+ GL_RGBA, CHAN_TYPE, NULL,
+ &ctx->DefaultPacking, texObj, texImage);
+
+ st_copy_texsubimage(ctx, target, level,
+ 0, 0, 0, /* destX,Y,Z */
+ x, y, width, height); /* src X, Y, size */
+}
+
+
+static void
+st_CopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width)
+{
+ const GLint yoffset = 0, zoffset = 0;
+ const GLsizei height = 1;
+ st_copy_texsubimage(ctx, target, level,
+ xoffset, yoffset, zoffset, /* destX,Y,Z */
+ x, y, width, height); /* src X, Y, size */
+}
+
+
+static void
+st_CopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ const GLint zoffset = 0;
+ st_copy_texsubimage(ctx, target, level,
+ xoffset, yoffset, zoffset, /* destX,Y,Z */
+ x, y, width, height); /* src X, Y, size */
+}
+
+
+static void
+st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ st_copy_texsubimage(ctx, target, level,
+ xoffset, yoffset, zoffset, /* destX,Y,Z */
+ x, y, width, height); /* src X, Y, size */
+}
+
+
+/**
+ * Compute which mipmap levels that really need to be sent to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ */
+static void
+calculate_first_last_level(struct st_texture_object *stObj)
+{
+ struct gl_texture_object *tObj = &stObj->base;
+
+ /* These must be signed values. MinLod and MaxLod can be negative numbers,
+ * and having firstLevel and lastLevel as signed prevents the need for
+ * extra sign checks.
+ */
+ GLint firstLevel;
+ GLint lastLevel;
+
+ /* Yes, this looks overly complicated, but it's all needed.
+ */
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+ firstLevel = lastLevel = tObj->BaseLevel;
+ }
+ else {
+ firstLevel = 0;
+ lastLevel = MIN2(tObj->MaxLevel,
+ (int) tObj->Image[0][tObj->BaseLevel]->WidthLog2);
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_4D_SGIS:
+ firstLevel = lastLevel = 0;
+ break;
+ default:
+ return;
+ }
+
+ stObj->lastLevel = lastLevel;
+}
+
+
+static void
+copy_image_data_to_texture(struct st_context *st,
+ struct st_texture_object *stObj,
+ GLuint dstLevel,
+ struct st_texture_image *stImage)
+{
+ if (stImage->pt) {
+ /* Copy potentially with the blitter:
+ */
+ st_texture_image_copy(st->pipe,
+ stObj->pt, dstLevel, /* dest texture, level */
+ stImage->pt, /* src texture */
+ stImage->face
+ );
+
+ pipe_texture_reference(&stImage->pt, NULL);
+ }
+ else if (stImage->base.Data) {
+ assert(stImage->base.Data != NULL);
+
+ /* More straightforward upload.
+ */
+
+ st_teximage_flush_before_map(st, stObj->pt, stImage->face, dstLevel,
+ PIPE_TRANSFER_WRITE);
+
+
+ st_texture_image_data(st,
+ stObj->pt,
+ stImage->face,
+ dstLevel,
+ stImage->base.Data,
+ stImage->base.RowStride *
+ stObj->pt->block.size,
+ stImage->base.RowStride *
+ stImage->base.Height *
+ stObj->pt->block.size);
+ _mesa_align_free(stImage->base.Data);
+ stImage->base.Data = NULL;
+ }
+
+ pipe_texture_reference(&stImage->pt, stObj->pt);
+}
+
+
+/**
+ * Called during state validation. When this function is finished,
+ * the texture object should be ready for rendering.
+ * \return GL_TRUE for success, GL_FALSE for failure (out of mem)
+ */
+GLboolean
+st_finalize_texture(GLcontext *ctx,
+ struct pipe_context *pipe,
+ struct gl_texture_object *tObj,
+ GLboolean *needFlush)
+{
+ struct st_texture_object *stObj = st_texture_object(tObj);
+ const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ GLuint cpp, face;
+ struct st_texture_image *firstImage;
+
+ *needFlush = GL_FALSE;
+
+ /* We know/require this is true by now:
+ */
+ assert(stObj->base._Complete);
+
+ /* What levels must the texture include at a minimum?
+ */
+ calculate_first_last_level(stObj);
+ firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
+
+ /* If both firstImage and stObj point to a texture which can contain
+ * all active images, favour firstImage. Note that because of the
+ * completeness requirement, we know that the image dimensions
+ * will match.
+ */
+ if (firstImage->pt &&
+ firstImage->pt != stObj->pt &&
+ firstImage->pt->last_level >= stObj->lastLevel) {
+ pipe_texture_reference(&stObj->pt, firstImage->pt);
+ }
+
+ /* FIXME: determine format block instead of cpp */
+ if (firstImage->base.IsCompressed) {
+ cpp = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat);
+ }
+ else {
+ cpp = firstImage->base.TexFormat->TexelBytes;
+ }
+
+ /* If we already have a gallium texture, check that it matches the texture
+ * object's format, target, size, num_levels, etc.
+ */
+ if (stObj->pt) {
+ const enum pipe_format fmt =
+ st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
+ if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
+ stObj->pt->format != fmt ||
+ stObj->pt->last_level < stObj->lastLevel ||
+ stObj->pt->width[0] != firstImage->base.Width2 ||
+ stObj->pt->height[0] != firstImage->base.Height2 ||
+ stObj->pt->depth[0] != firstImage->base.Depth2 ||
+ /* Nominal bytes per pixel: */
+ stObj->pt->block.size / stObj->pt->block.width != cpp)
+ {
+ pipe_texture_reference(&stObj->pt, NULL);
+ ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
+ }
+ }
+
+ /* May need to create a new gallium texture:
+ */
+ if (!stObj->pt) {
+ const enum pipe_format fmt =
+ st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
+ GLuint usage = default_usage(fmt);
+
+ stObj->pt = st_texture_create(ctx->st,
+ gl_target_to_pipe(stObj->base.Target),
+ fmt,
+ stObj->lastLevel,
+ firstImage->base.Width2,
+ firstImage->base.Height2,
+ firstImage->base.Depth2,
+ usage);
+
+ if (!stObj->pt) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ return GL_FALSE;
+ }
+ }
+
+ /* Pull in any images not in the object's texture:
+ */
+ for (face = 0; face < nr_faces; face++) {
+ GLuint level;
+ for (level = 0; level <= stObj->lastLevel; level++) {
+ struct st_texture_image *stImage =
+ st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]);
+
+ /* Need to import images in main memory or held in other textures.
+ */
+ if (stImage && stObj->pt != stImage->pt) {
+ copy_image_data_to_texture(ctx->st, stObj, level, stImage);
+ *needFlush = GL_TRUE;
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Returns pointer to a default/dummy texture.
+ * This is typically used when the current shader has tex/sample instructions
+ * but the user has not provided a (any) texture(s).
+ */
+struct gl_texture_object *
+st_get_default_texture(struct st_context *st)
+{
+ if (!st->default_texture) {
+ static const GLenum target = GL_TEXTURE_2D;
+ GLubyte pixels[16][16][4];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImg;
+ GLuint i, j;
+
+ /* The ARB_fragment_program spec says (0,0,0,1) should be returned
+ * when attempting to sample incomplete textures.
+ */
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 16; j++) {
+ pixels[i][j][0] = 0;
+ pixels[i][j][1] = 0;
+ pixels[i][j][2] = 0;
+ pixels[i][j][3] = 255;
+ }
+ }
+
+ texObj = st->ctx->Driver.NewTextureObject(st->ctx, 0, target);
+
+ texImg = _mesa_get_tex_image(st->ctx, texObj, target, 0);
+
+ _mesa_init_teximage_fields(st->ctx, target, texImg,
+ 16, 16, 1, 0, /* w, h, d, border */
+ GL_RGBA);
+
+ st_TexImage(st->ctx, 2, target,
+ 0, GL_RGBA, /* level, intformat */
+ 16, 16, 1, 0, /* w, h, d, border */
+ GL_RGBA, GL_UNSIGNED_BYTE, pixels,
+ &st->ctx->DefaultPacking,
+ texObj, texImg,
+ 0, 0);
+
+ texObj->MinFilter = GL_NEAREST;
+ texObj->MagFilter = GL_NEAREST;
+ texObj->_Complete = GL_TRUE;
+
+ st->default_texture = texObj;
+ }
+ return st->default_texture;
+}
+
+
+void
+st_init_texture_functions(struct dd_function_table *functions)
+{
+ functions->ChooseTextureFormat = st_ChooseTextureFormat;
+ functions->TexImage1D = st_TexImage1D;
+ functions->TexImage2D = st_TexImage2D;
+ functions->TexImage3D = st_TexImage3D;
+ functions->TexSubImage1D = st_TexSubImage1D;
+ functions->TexSubImage2D = st_TexSubImage2D;
+ functions->TexSubImage3D = st_TexSubImage3D;
+ functions->CompressedTexSubImage1D = st_CompressedTexSubImage1D;
+ functions->CompressedTexSubImage2D = st_CompressedTexSubImage2D;
+ functions->CompressedTexSubImage3D = st_CompressedTexSubImage3D;
+ functions->CopyTexImage1D = st_CopyTexImage1D;
+ functions->CopyTexImage2D = st_CopyTexImage2D;
+ functions->CopyTexSubImage1D = st_CopyTexSubImage1D;
+ functions->CopyTexSubImage2D = st_CopyTexSubImage2D;
+ functions->CopyTexSubImage3D = st_CopyTexSubImage3D;
+ functions->GenerateMipmap = st_generate_mipmap;
+
+ functions->GetTexImage = st_GetTexImage;
+
+ /* compressed texture functions */
+ functions->CompressedTexImage2D = st_CompressedTexImage2D;
+ functions->GetCompressedTexImage = st_GetCompressedTexImage;
+ functions->CompressedTextureSize = _mesa_compressed_texture_size;
+
+ functions->NewTextureObject = st_NewTextureObject;
+ functions->NewTextureImage = st_NewTextureImage;
+ functions->DeleteTexture = st_DeleteTextureObject;
+ functions->FreeTexImageData = st_FreeTextureImageData;
+ functions->UpdateTexturePalette = 0;
+
+ functions->TextureMemCpy = do_memcpy;
+
+ /* XXX Temporary until we can query pipe's texture sizes */
+ functions->TestProxyTexImage = _mesa_test_proxy_teximage;
+}
diff --git a/src/mesa/state_tracker/st_cb_texture.h b/src/mesa/state_tracker/st_cb_texture.h
new file mode 100644
index 0000000000..f1fe0339cd
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_texture.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_CB_TEXTURE_H
+#define ST_CB_TEXTURE_H
+
+
+extern GLboolean
+st_finalize_texture(GLcontext *ctx,
+ struct pipe_context *pipe,
+ struct gl_texture_object *tObj,
+ GLboolean *needFlush);
+
+
+extern struct gl_texture_object *
+st_get_default_texture(struct st_context *st);
+
+
+extern void
+st_init_texture_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_TEXTURE_H */
diff --git a/src/mesa/state_tracker/st_cb_viewport.c b/src/mesa/state_tracker/st_cb_viewport.c
new file mode 100644
index 0000000000..75b0a219ce
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_viewport.c
@@ -0,0 +1,53 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/glheader.h"
+#include "st_context.h"
+#include "st_public.h"
+#include "st_cb_viewport.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/internal/p_winsys_screen.h"
+
+
+static void st_viewport(GLcontext * ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ struct st_context *st = ctx->st;
+
+ if (st->pipe->winsys && st->pipe->winsys->update_buffer)
+ st->pipe->winsys->update_buffer( st->pipe->winsys,
+ st->pipe->priv );
+}
+
+void st_init_viewport_functions(struct dd_function_table *functions)
+{
+ functions->Viewport = st_viewport;
+}
diff --git a/src/mesa/state_tracker/st_cb_viewport.h b/src/mesa/state_tracker/st_cb_viewport.h
new file mode 100644
index 0000000000..44948e5316
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_viewport.h
@@ -0,0 +1,29 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+extern void
+st_init_viewport_functions(struct dd_function_table *functions);
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
new file mode 100644
index 0000000000..508d522f9a
--- /dev/null
+++ b/src/mesa/state_tracker/st_context.c
@@ -0,0 +1,350 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/extensions.h"
+#include "main/matrix.h"
+#include "main/buffers.h"
+#include "main/scissor.h"
+#include "main/viewport.h"
+#include "vbo/vbo.h"
+#include "shader/shader_api.h"
+#include "glapi/glapi.h"
+#include "st_public.h"
+#include "st_context.h"
+#include "st_cb_accum.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_blit.h"
+#include "st_cb_bufferobjects.h"
+#include "st_cb_clear.h"
+#if FEATURE_drawpix
+#include "st_cb_drawpixels.h"
+#include "st_cb_rasterpos.h"
+#endif
+#ifdef FEATURE_OES_draw_texture
+#include "st_cb_drawtex.h"
+#endif
+#include "st_cb_fbo.h"
+#include "st_cb_get.h"
+#if FEATURE_feedback
+#include "st_cb_feedback.h"
+#endif
+#include "st_cb_program.h"
+#include "st_cb_queryobj.h"
+#include "st_cb_readpixels.h"
+#include "st_cb_texture.h"
+#include "st_cb_flush.h"
+#include "st_cb_strings.h"
+#include "st_cb_viewport.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "st_extensions.h"
+#include "st_gen_mipmap.h"
+#include "st_program.h"
+#include "pipe/p_context.h"
+#include "draw/draw_context.h"
+#include "cso_cache/cso_cache.h"
+#include "cso_cache/cso_context.h"
+
+
+/**
+ * Called via ctx->Driver.UpdateState()
+ */
+void st_invalidate_state(GLcontext * ctx, GLuint new_state)
+{
+ struct st_context *st = st_context(ctx);
+
+ st->dirty.mesa |= new_state;
+ st->dirty.st |= ST_NEW_MESA;
+
+ /* This is the only core Mesa module we depend upon.
+ * No longer use swrast, swsetup, tnl.
+ */
+ _vbo_InvalidateState(ctx, new_state);
+}
+
+
+/**
+ * Check for multisample env var override.
+ */
+int
+st_get_msaa(void)
+{
+ const char *msaa = _mesa_getenv("__GL_FSAA_MODE");
+ if (msaa)
+ return atoi(msaa);
+ return 0;
+}
+
+
+static struct st_context *
+st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe )
+{
+ uint i;
+ struct st_context *st = ST_CALLOC_STRUCT( st_context );
+
+ ctx->st = st;
+
+ st->ctx = ctx;
+ st->pipe = pipe;
+
+ /* state tracker needs the VBO module */
+ _vbo_CreateContext(ctx);
+
+#if FEATURE_feedback || FEATURE_drawpix
+ st->draw = draw_create(); /* for selection/feedback */
+
+ /* Disable draw options that might convert points/lines to tris, etc.
+ * as that would foul-up feedback/selection mode.
+ */
+ draw_wide_line_threshold(st->draw, 1000.0f);
+ draw_wide_point_threshold(st->draw, 1000.0f);
+ draw_enable_line_stipple(st->draw, FALSE);
+ draw_enable_point_sprites(st->draw, FALSE);
+#endif
+
+ st->dirty.mesa = ~0;
+ st->dirty.st = ~0;
+
+ st->cso_context = cso_create_context(pipe);
+
+ st_init_atoms( st );
+ st_init_bitmap(st);
+ st_init_clear(st);
+ st_init_draw( st );
+ st_init_generate_mipmap(st);
+ st_init_blit(st);
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ st->state.sampler_list[i] = &st->state.samplers[i];
+
+ /* we want all vertex data to be placed in buffer objects */
+ vbo_use_buffer_objects(ctx);
+
+ /* Need these flags:
+ */
+ st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+
+ st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
+
+ st->pixel_xfer.cache = _mesa_new_program_cache();
+
+ st->force_msaa = st_get_msaa();
+
+ /* GL limits and extensions */
+ st_init_limits(st);
+ st_init_extensions(st);
+
+ return st;
+}
+
+
+struct st_context *st_create_context(struct pipe_context *pipe,
+ const __GLcontextModes *visual,
+ struct st_context *share)
+{
+ GLcontext *ctx;
+ GLcontext *shareCtx = share ? share->ctx : NULL;
+ struct dd_function_table funcs;
+
+ memset(&funcs, 0, sizeof(funcs));
+ st_init_driver_functions(&funcs);
+
+ ctx = _mesa_create_context(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.
+ */
+ if (debug_get_bool_option("MESA_MVP_DP4", FALSE))
+ _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
+
+ return st_create_context_priv(ctx, pipe);
+}
+
+
+static void st_destroy_context_priv( struct st_context *st )
+{
+ uint i;
+
+#if FEATURE_feedback || FEATURE_drawpix
+ draw_destroy(st->draw);
+#endif
+ st_destroy_atoms( st );
+ st_destroy_draw( st );
+ st_destroy_generate_mipmap(st);
+#if FEATURE_EXT_framebuffer_blit
+ st_destroy_blit(st);
+#endif
+ st_destroy_clear(st);
+#if FEATURE_drawpix
+ st_destroy_bitmap(st);
+ st_destroy_drawpix(st);
+#endif
+#ifdef FEATURE_OES_draw_texture
+ st_destroy_drawtex(st);
+#endif
+
+ for (i = 0; i < Elements(st->state.sampler_texture); i++) {
+ pipe_texture_reference(&st->state.sampler_texture[i], NULL);
+ }
+
+ for (i = 0; i < Elements(st->state.constants); i++) {
+ if (st->state.constants[i].buffer) {
+ pipe_buffer_reference(&st->state.constants[i].buffer, NULL);
+ }
+ }
+
+ if (st->default_texture) {
+ st->ctx->Driver.DeleteTexture(st->ctx, st->default_texture);
+ st->default_texture = NULL;
+ }
+
+ _mesa_free( st );
+}
+
+
+void st_destroy_context( struct st_context *st )
+{
+ struct pipe_context *pipe = st->pipe;
+ struct cso_context *cso = st->cso_context;
+ GLcontext *ctx = st->ctx;
+ GLuint i;
+
+ /* need to unbind and destroy CSO objects before anything else */
+ cso_release_all(st->cso_context);
+
+ st_reference_fragprog(st, &st->fp, NULL);
+ st_reference_vertprog(st, &st->vp, NULL);
+
+ /* release framebuffer surfaces */
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL);
+ }
+ pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL);
+
+ _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
+
+ _vbo_DestroyContext(st->ctx);
+
+ _mesa_free_context_data(ctx);
+
+ st_destroy_context_priv(st);
+
+ cso_destroy_context(cso);
+
+ pipe->destroy( pipe );
+
+ _mesa_free(ctx);
+}
+
+
+GLboolean
+st_make_current(struct st_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read)
+{
+ /* Call this periodically to detect when the user has begun using
+ * GL rendering from multiple threads.
+ */
+ _glapi_check_multithread();
+
+ if (st) {
+ if (!_mesa_make_current(st->ctx, &draw->Base, &read->Base))
+ return GL_FALSE;
+
+ _mesa_check_init_viewport(st->ctx, draw->InitWidth, draw->InitHeight);
+
+ return GL_TRUE;
+ }
+ else {
+ return _mesa_make_current(NULL, NULL, NULL);
+ }
+}
+
+struct st_context *st_get_current(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ return (ctx == NULL) ? NULL : ctx->st;
+}
+
+void st_copy_context_state(struct st_context *dst,
+ struct st_context *src,
+ uint mask)
+{
+ _mesa_copy_context(dst->ctx, src->ctx, mask);
+}
+
+
+
+st_proc st_get_proc_address(const char *procname)
+{
+ return (st_proc) _glapi_get_proc_address(procname);
+}
+
+
+
+void st_init_driver_functions(struct dd_function_table *functions)
+{
+ _mesa_init_glsl_driver_functions(functions);
+
+#if FEATURE_accum
+ st_init_accum_functions(functions);
+#endif
+#if FEATURE_EXT_framebuffer_blit
+ st_init_blit_functions(functions);
+#endif
+ st_init_bufferobject_functions(functions);
+ st_init_clear_functions(functions);
+#if FEATURE_drawpix
+ st_init_bitmap_functions(functions);
+ st_init_drawpixels_functions(functions);
+ st_init_rasterpos_functions(functions);
+#endif
+
+#if FEATURE_OES_draw_texture
+ st_init_drawtex_functions(functions);
+#endif
+
+ st_init_fbo_functions(functions);
+ st_init_get_functions(functions);
+#if FEATURE_feedback
+ st_init_feedback_functions(functions);
+#endif
+ st_init_program_functions(functions);
+#if FEATURE_queryobj
+ st_init_query_functions(functions);
+#endif
+ st_init_readpixels_functions(functions);
+ st_init_texture_functions(functions);
+ st_init_flush_functions(functions);
+ st_init_string_functions(functions);
+ st_init_viewport_functions(functions);
+
+ functions->UpdateState = st_invalidate_state;
+}
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
new file mode 100644
index 0000000000..18adb35e87
--- /dev/null
+++ b/src/mesa/state_tracker/st_context.h
@@ -0,0 +1,245 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ST_CONTEXT_H
+#define ST_CONTEXT_H
+
+#include "main/mtypes.h"
+#include "shader/prog_cache.h"
+#include "pipe/p_state.h"
+
+
+struct st_context;
+struct st_texture_object;
+struct st_fragment_program;
+struct draw_context;
+struct draw_stage;
+struct cso_cache;
+struct cso_blend;
+struct gen_mipmap_state;
+struct blit_state;
+struct bitmap_cache;
+
+
+/** XXX we'd like to get rid of these */
+#define FRONT_STATUS_UNDEFINED 0
+#define FRONT_STATUS_DIRTY 1
+#define FRONT_STATUS_COPY_OF_BACK 2
+
+
+#define ST_NEW_MESA 0x1 /* Mesa state has changed */
+#define ST_NEW_FRAGMENT_PROGRAM 0x2
+#define ST_NEW_VERTEX_PROGRAM 0x4
+#define ST_NEW_FRAMEBUFFER 0x8
+
+
+struct st_state_flags {
+ GLuint mesa;
+ GLuint st;
+};
+
+struct st_tracked_state {
+ const char *name;
+ struct st_state_flags dirty;
+ void (*update)( struct st_context *st );
+};
+
+
+
+struct st_context
+{
+ GLcontext *ctx;
+
+ struct pipe_context *pipe;
+
+ struct draw_context *draw; /**< For selection/feedback/rastpos only */
+ struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */
+ struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */
+ struct draw_stage *rastpos_stage; /**< For glRasterPos */
+
+ /* Some state is contained in constant objects.
+ * Other state is just parameter values.
+ */
+ struct {
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depth_stencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_state *sampler_list[PIPE_MAX_SAMPLERS];
+ struct pipe_clip_state clip;
+ struct pipe_constant_buffer constants[2];
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_texture *sampler_texture[PIPE_MAX_SAMPLERS];
+ struct pipe_scissor_state scissor;
+ struct pipe_viewport_state viewport;
+
+ GLuint num_samplers;
+ GLuint num_textures;
+
+ GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */
+ } state;
+
+ struct {
+ struct st_tracked_state tracked_state[PIPE_SHADER_TYPES];
+ } constants;
+
+ /* XXX unused: */
+ struct {
+ struct gl_fragment_program *fragment_program;
+ } cb;
+
+ GLuint frontbuffer_status; /**< one of FRONT_STATUS_ (XXX to be removed) */
+
+ char vendor[100];
+ char renderer[100];
+
+ struct st_state_flags dirty;
+
+ GLboolean missing_textures;
+
+ /** Mapping from VERT_RESULT_x to post-transformed vertex slot */
+ const GLuint *vertex_result_to_slot;
+
+ struct st_vertex_program *vp; /**< Currently bound vertex program */
+ struct st_fragment_program *fp; /**< Currently bound fragment program */
+
+ struct gl_texture_object *default_texture;
+
+ struct {
+ struct gl_program_cache *cache;
+ struct st_fragment_program *program; /**< cur pixel transfer prog */
+ GLuint xfer_prog_sn; /**< pixel xfer program serial no. */
+ GLuint user_prog_sn; /**< user fragment program serial no. */
+ struct st_fragment_program *combined_prog;
+ GLuint combined_prog_sn;
+ struct pipe_texture *pixelmap_texture;
+ boolean pixelmap_enabled; /**< use the pixelmap texture? */
+ } pixel_xfer;
+
+ /** for glBitmap */
+ struct {
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state sampler;
+ enum pipe_format tex_format;
+ void *vs;
+ float vertices[4][3][4]; /**< vertex pos + color + texcoord */
+ struct pipe_buffer *vbuf;
+ unsigned vbuf_slot; /* next free slot in vbuf */
+ struct bitmap_cache *cache;
+ } bitmap;
+
+ /** for glDraw/CopyPixels */
+ struct {
+ struct st_fragment_program *z_shader;
+ struct st_vertex_program *vert_shaders[2];
+ } drawpix;
+
+ /** for glClear */
+ struct {
+ struct pipe_rasterizer_state raster;
+ struct pipe_viewport_state viewport;
+ void *vs;
+ void *fs;
+ float vertices[4][2][4]; /**< vertex pos + color */
+ struct pipe_buffer *vbuf;
+ unsigned vbuf_slot;
+ } clear;
+
+ void *passthrough_fs; /**< simple pass-through frag shader */
+
+ struct gen_mipmap_state *gen_mipmap;
+ struct blit_state *blit;
+
+ struct cso_context *cso_context;
+
+ int force_msaa;
+};
+
+
+/* Need this so that we can implement Mesa callbacks in this module.
+ */
+static INLINE struct st_context *st_context(GLcontext *ctx)
+{
+ return ctx->st;
+}
+
+
+/**
+ * Wrapper for GLframebuffer.
+ * This is an opaque type to the outside world.
+ */
+struct st_framebuffer
+{
+ GLframebuffer Base;
+ void *Private;
+ GLuint InitWidth, InitHeight;
+};
+
+
+extern void st_init_driver_functions(struct dd_function_table *functions);
+
+void st_invalidate_state(GLcontext * ctx, GLuint new_state);
+
+
+
+#define Y_0_TOP 1
+#define Y_0_BOTTOM 2
+
+static INLINE GLuint
+st_fb_orientation(const struct gl_framebuffer *fb)
+{
+ if (fb && fb->Name == 0) {
+ /* Drawing into a window (on-screen buffer).
+ *
+ * Negate Y scale to flip image vertically.
+ * The NDC Y coords prior to viewport transformation are in the range
+ * [y=-1=bottom, y=1=top]
+ * Hardware window coords are in the range [y=0=top, y=H-1=bottom] where
+ * H is the window height.
+ * Use the viewport transformation to invert Y.
+ */
+ return Y_0_TOP;
+ }
+ else {
+ /* Drawing into user-created FBO (very likely a texture).
+ *
+ * For textures, T=0=Bottom, so by extension Y=0=Bottom for rendering.
+ */
+ return Y_0_BOTTOM;
+ }
+}
+
+
+/** clear-alloc a struct-sized object, with casting */
+#define ST_CALLOC_STRUCT(T) (struct T *) _mesa_calloc(sizeof(struct T))
+
+
+extern int
+st_get_msaa(void);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c
new file mode 100644
index 0000000000..c7d26ce33c
--- /dev/null
+++ b/src/mesa/state_tracker/st_debug.c
@@ -0,0 +1,70 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "main/context.h"
+#include "shader/prog_print.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "cso_cache/cso_cache.h"
+
+#include "st_context.h"
+#include "st_debug.h"
+#include "st_program.h"
+
+
+
+/**
+ * Print current state. May be called from inside gdb to see currently
+ * bound vertex/fragment shaders and associated constants.
+ */
+void
+st_print_current(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct st_context *st = ctx->st;
+
+#if 0
+ int i;
+
+ printf("Vertex Transform Inputs:\n");
+ for (i = 0; i < st->vp->state.num_inputs; i++) {
+ printf(" Slot %d: VERT_ATTRIB_%d\n", i, st->vp->index_to_input[i]);
+ }
+#endif
+
+ tgsi_dump( st->vp->state.tokens, 0 );
+ if (st->vp->Base.Base.Parameters)
+ _mesa_print_parameter_list(st->vp->Base.Base.Parameters);
+
+ tgsi_dump( st->fp->state.tokens, 0 );
+ if (st->fp->Base.Base.Parameters)
+ _mesa_print_parameter_list(st->fp->Base.Base.Parameters);
+}
diff --git a/src/mesa/state_tracker/st_debug.h b/src/mesa/state_tracker/st_debug.h
new file mode 100644
index 0000000000..49d752e1b2
--- /dev/null
+++ b/src/mesa/state_tracker/st_debug.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_DEBUG_H
+#define ST_DEBUG_H
+
+extern void
+st_print_current(void);
+
+
+#endif /* ST_DEBUG_H */
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
new file mode 100644
index 0000000000..503a5f34a3
--- /dev/null
+++ b/src/mesa/state_tracker/st_draw.c
@@ -0,0 +1,719 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "shader/prog_uniform.h"
+
+#include "vbo/vbo.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_bufferobjects.h"
+#include "st_draw.h"
+#include "st_program.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+
+static GLuint double_types[4] = {
+ PIPE_FORMAT_R64_FLOAT,
+ PIPE_FORMAT_R64G64_FLOAT,
+ PIPE_FORMAT_R64G64B64_FLOAT,
+ PIPE_FORMAT_R64G64B64A64_FLOAT
+};
+
+static GLuint float_types[4] = {
+ PIPE_FORMAT_R32_FLOAT,
+ PIPE_FORMAT_R32G32_FLOAT,
+ PIPE_FORMAT_R32G32B32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT
+};
+
+static GLuint uint_types_norm[4] = {
+ PIPE_FORMAT_R32_UNORM,
+ PIPE_FORMAT_R32G32_UNORM,
+ PIPE_FORMAT_R32G32B32_UNORM,
+ PIPE_FORMAT_R32G32B32A32_UNORM
+};
+
+static GLuint uint_types_scale[4] = {
+ PIPE_FORMAT_R32_USCALED,
+ PIPE_FORMAT_R32G32_USCALED,
+ PIPE_FORMAT_R32G32B32_USCALED,
+ PIPE_FORMAT_R32G32B32A32_USCALED
+};
+
+static GLuint int_types_norm[4] = {
+ PIPE_FORMAT_R32_SNORM,
+ PIPE_FORMAT_R32G32_SNORM,
+ PIPE_FORMAT_R32G32B32_SNORM,
+ PIPE_FORMAT_R32G32B32A32_SNORM
+};
+
+static GLuint int_types_scale[4] = {
+ PIPE_FORMAT_R32_SSCALED,
+ PIPE_FORMAT_R32G32_SSCALED,
+ PIPE_FORMAT_R32G32B32_SSCALED,
+ PIPE_FORMAT_R32G32B32A32_SSCALED
+};
+
+static GLuint ushort_types_norm[4] = {
+ PIPE_FORMAT_R16_UNORM,
+ PIPE_FORMAT_R16G16_UNORM,
+ PIPE_FORMAT_R16G16B16_UNORM,
+ PIPE_FORMAT_R16G16B16A16_UNORM
+};
+
+static GLuint ushort_types_scale[4] = {
+ PIPE_FORMAT_R16_USCALED,
+ PIPE_FORMAT_R16G16_USCALED,
+ PIPE_FORMAT_R16G16B16_USCALED,
+ PIPE_FORMAT_R16G16B16A16_USCALED
+};
+
+static GLuint short_types_norm[4] = {
+ PIPE_FORMAT_R16_SNORM,
+ PIPE_FORMAT_R16G16_SNORM,
+ PIPE_FORMAT_R16G16B16_SNORM,
+ PIPE_FORMAT_R16G16B16A16_SNORM
+};
+
+static GLuint short_types_scale[4] = {
+ PIPE_FORMAT_R16_SSCALED,
+ PIPE_FORMAT_R16G16_SSCALED,
+ PIPE_FORMAT_R16G16B16_SSCALED,
+ PIPE_FORMAT_R16G16B16A16_SSCALED
+};
+
+static GLuint ubyte_types_norm[4] = {
+ PIPE_FORMAT_R8_UNORM,
+ PIPE_FORMAT_R8G8_UNORM,
+ PIPE_FORMAT_R8G8B8_UNORM,
+ PIPE_FORMAT_R8G8B8A8_UNORM
+};
+
+static GLuint ubyte_types_scale[4] = {
+ PIPE_FORMAT_R8_USCALED,
+ PIPE_FORMAT_R8G8_USCALED,
+ PIPE_FORMAT_R8G8B8_USCALED,
+ PIPE_FORMAT_R8G8B8A8_USCALED
+};
+
+static GLuint byte_types_norm[4] = {
+ PIPE_FORMAT_R8_SNORM,
+ PIPE_FORMAT_R8G8_SNORM,
+ PIPE_FORMAT_R8G8B8_SNORM,
+ PIPE_FORMAT_R8G8B8A8_SNORM
+};
+
+static GLuint byte_types_scale[4] = {
+ PIPE_FORMAT_R8_SSCALED,
+ PIPE_FORMAT_R8G8_SSCALED,
+ PIPE_FORMAT_R8G8B8_SSCALED,
+ PIPE_FORMAT_R8G8B8A8_SSCALED
+};
+
+static GLuint fixed_types[4] = {
+ PIPE_FORMAT_R32_FIXED,
+ PIPE_FORMAT_R32G32_FIXED,
+ PIPE_FORMAT_R32G32B32_FIXED,
+ PIPE_FORMAT_R32G32B32A32_FIXED
+};
+
+
+
+/**
+ * Return a PIPE_FORMAT_x for the given GL datatype and size.
+ */
+GLuint
+st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
+ GLboolean normalized)
+{
+ assert((type >= GL_BYTE && type <= GL_DOUBLE) ||
+ type == GL_FIXED);
+ assert(size >= 1);
+ assert(size <= 4);
+ assert(format == GL_RGBA || format == GL_BGRA);
+
+ if (format == GL_BGRA) {
+ /* this is an odd-ball case */
+ assert(type == GL_UNSIGNED_BYTE);
+ assert(normalized);
+ return PIPE_FORMAT_B8G8R8A8_UNORM;
+ }
+
+ if (normalized) {
+ switch (type) {
+ case GL_DOUBLE: return double_types[size-1];
+ case GL_FLOAT: return float_types[size-1];
+ case GL_INT: return int_types_norm[size-1];
+ case GL_SHORT: return short_types_norm[size-1];
+ case GL_BYTE: return byte_types_norm[size-1];
+ case GL_UNSIGNED_INT: return uint_types_norm[size-1];
+ case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1];
+ case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1];
+ case GL_FIXED: return fixed_types[size-1];
+ default: assert(0); return 0;
+ }
+ }
+ else {
+ switch (type) {
+ case GL_DOUBLE: return double_types[size-1];
+ case GL_FLOAT: return float_types[size-1];
+ case GL_INT: return int_types_scale[size-1];
+ case GL_SHORT: return short_types_scale[size-1];
+ case GL_BYTE: return byte_types_scale[size-1];
+ case GL_UNSIGNED_INT: return uint_types_scale[size-1];
+ case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1];
+ case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1];
+ case GL_FIXED: return fixed_types[size-1];
+ default: assert(0); return 0;
+ }
+ }
+ return 0; /* silence compiler warning */
+}
+
+
+/*
+ * If edge flags are needed, setup an bitvector of flags and call
+ * pipe->set_edgeflags().
+ * XXX memleak: need to free the returned pointer at some point
+ */
+static void *
+setup_edgeflags(GLcontext *ctx, GLenum primMode, GLint start, GLint count,
+ const struct gl_client_array *array)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+
+ if ((primMode == GL_TRIANGLES ||
+ primMode == GL_QUADS ||
+ primMode == GL_POLYGON) &&
+ (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL)) {
+ /* need edge flags */
+ GLint i;
+ unsigned *vec;
+ struct st_buffer_object *stobj = st_buffer_object(array->BufferObj);
+ ubyte *map;
+
+ if (!stobj || stobj->Base.Name == 0) {
+ /* edge flags are not in a VBO */
+ return NULL;
+ }
+
+ vec = (unsigned *) _mesa_calloc(sizeof(unsigned) * ((count + 31) / 32));
+ if (!vec)
+ return NULL;
+
+ map = pipe_buffer_map(pipe->screen, stobj->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+ map = ADD_POINTERS(map, array->Ptr);
+
+ for (i = 0; i < count; i++) {
+ if (*((float *) map))
+ vec[i/32] |= 1 << (i % 32);
+
+ map += array->StrideB;
+ }
+
+ pipe_buffer_unmap(pipe->screen, stobj->buffer);
+
+ pipe->set_edgeflags(pipe, vec);
+
+ return vec;
+ }
+ else {
+ /* edge flags not needed */
+ pipe->set_edgeflags(pipe, NULL);
+ return NULL;
+ }
+}
+
+
+/**
+ * Examine the active arrays to determine if we have interleaved
+ * vertex arrays all living in one VBO, or all living in user space.
+ * \param userSpace returns whether the arrays are in user space.
+ */
+static GLboolean
+is_interleaved_arrays(const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ GLboolean *userSpace)
+{
+ GLuint attr;
+ const struct gl_buffer_object *firstBufObj = NULL;
+ GLint firstStride = -1;
+ GLuint num_client_arrays = 0;
+ const GLubyte *client_addr = NULL;
+
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj;
+ const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */
+
+ if (firstStride < 0) {
+ firstStride = stride;
+ }
+ 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 (!client_addr) {
+ client_addr = arrays[mesaAttr]->Ptr;
+ }
+ else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) {
+ /* arrays start too far apart */
+ return GL_FALSE;
+ }
+ }
+ else if (!firstBufObj) {
+ firstBufObj = bufObj;
+ }
+ else if (bufObj != firstBufObj) {
+ return GL_FALSE;
+ }
+ }
+
+ *userSpace = (num_client_arrays == vp->num_inputs);
+ /* printf("user space: %d (%d %d)\n", (int) *userSpace,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 gl_client_array **arrays,
+ GLuint max_index,
+ const GLubyte **low, const GLubyte **high)
+{
+ const GLubyte *low_addr = NULL;
+ GLuint attr;
+ GLint stride;
+
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ const GLubyte *start = arrays[mesaAttr]->Ptr;
+ stride = arrays[mesaAttr]->StrideB;
+ if (attr == 0) {
+ low_addr = start;
+ }
+ else {
+ low_addr = MIN2(low_addr, start);
+ }
+ }
+
+ *low = low_addr;
+ *high = low_addr + (max_index + 1) * stride;
+}
+
+
+/**
+ * Set up for drawing interleaved arrays that all live in one VBO
+ * or all live in user space.
+ * \param vbuffer returns vertex buffer info
+ * \param velements returns vertex element info
+ */
+static void
+setup_interleaved_attribs(GLcontext *ctx,
+ const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ GLuint max_index,
+ GLboolean userSpace,
+ struct pipe_vertex_buffer *vbuffer,
+ struct pipe_vertex_element velements[])
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ GLuint attr;
+ const GLubyte *offset0;
+
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
+ 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, arrays, max_index, &low, &high);
+ /*printf("buffer range: %p %p %d\n", low, high, high-low);*/
+
+ offset0 = low;
+ if (userSpace) {
+ vbuffer->buffer =
+ pipe_user_buffer_create(pipe->screen, (void *) low, high - low);
+ vbuffer->buffer_offset = 0;
+ }
+ else {
+ vbuffer->buffer = NULL;
+ pipe_buffer_reference(&vbuffer->buffer, stobj->buffer);
+ vbuffer->buffer_offset = pointer_to_offset(low);
+ }
+ vbuffer->stride = stride; /* in bytes */
+ vbuffer->max_index = max_index;
+ }
+
+ velements[attr].src_offset =
+ (unsigned) (arrays[mesaAttr]->Ptr - offset0);
+ velements[attr].vertex_buffer_index = 0;
+ velements[attr].nr_components = arrays[mesaAttr]->Size;
+ velements[attr].src_format =
+ st_pipe_vertex_format(arrays[mesaAttr]->Type,
+ arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Format,
+ arrays[mesaAttr]->Normalized);
+ assert(velements[attr].src_format);
+ }
+}
+
+
+/**
+ * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
+ * vertex attribute.
+ * \param vbuffer returns vertex buffer info
+ * \param velements returns vertex element info
+ */
+static void
+setup_non_interleaved_attribs(GLcontext *ctx,
+ const struct st_vertex_program *vp,
+ const struct gl_client_array **arrays,
+ GLuint max_index,
+ GLboolean *userSpace,
+ struct pipe_vertex_buffer vbuffer[],
+ struct pipe_vertex_element velements[])
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ GLuint attr;
+
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ 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
+ * really an offset from the start of the VBO, not a pointer.
+ */
+ 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_buffer_reference(&vbuffer[attr].buffer, stobj->buffer);
+ vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr);
+ velements[attr].src_offset = 0;
+ }
+ 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);
+ }
+ else {
+ /* no array, use ctx->Current.Attrib[] value */
+ bytes = sizeof(ctx->Current.Attrib[0]);
+ vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen,
+ (void *) ctx->Current.Attrib[mesaAttr], bytes);
+ stride = 0;
+ }
+
+ vbuffer[attr].buffer_offset = 0;
+ velements[attr].src_offset = 0;
+ }
+
+ assert(velements[attr].src_offset <= 2048); /* 11-bit field */
+
+ /* common-case setup */
+ vbuffer[attr].stride = stride; /* in bytes */
+ vbuffer[attr].max_index = max_index;
+ velements[attr].vertex_buffer_index = attr;
+ velements[attr].nr_components = arrays[mesaAttr]->Size;
+ velements[attr].src_format
+ = st_pipe_vertex_format(arrays[mesaAttr]->Type,
+ arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Format,
+ arrays[mesaAttr]->Normalized);
+ assert(velements[attr].src_format);
+ }
+}
+
+
+
+/**
+ * Prior to drawing, check that any uniforms referenced by the
+ * current shader have been set. If a uniform has not been set,
+ * issue a warning.
+ */
+static void
+check_uniforms(GLcontext *ctx)
+{
+ const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ if (shProg && shProg->LinkStatus) {
+ GLuint i;
+ for (i = 0; i < shProg->Uniforms->NumUniforms; i++) {
+ const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i];
+ if (!u->Initialized) {
+ _mesa_warning(ctx,
+ "Using shader with uninitialized uniform: %s",
+ u->Name);
+ }
+ }
+ }
+}
+
+
+/**
+ * This function gets plugged into the VBO module and is called when
+ * we have something to render.
+ * Basically, translate the information into the format expected by gallium.
+ */
+void
+st_draw_vbo(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ const struct st_vertex_program *vp;
+ const struct pipe_shader_state *vs;
+ struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
+ GLuint attr;
+ struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+ unsigned num_vbuffers, num_velements;
+ GLboolean userSpace;
+
+ /* Gallium probably doesn't want this in some cases. */
+ if (!index_bounds_valid)
+ vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+
+ /* sanity check for pointer arithmetic below */
+ assert(sizeof(arrays[0]->Ptr[0]) == 1);
+
+ st_validate_state(ctx->st);
+
+ /* must get these after state validation! */
+ vp = ctx->st->vp;
+ vs = &ctx->st->vp->state;
+
+#if 0
+ if (MESA_VERBOSE & VERBOSE_GLSL) {
+ check_uniforms(ctx);
+ }
+#else
+ (void) check_uniforms;
+#endif
+
+ /*
+ * Setup the vbuffer[] and velements[] arrays.
+ */
+ if (is_interleaved_arrays(vp, arrays, &userSpace)) {
+ /*printf("Draw interleaved\n");*/
+ setup_interleaved_attribs(ctx, vp, arrays, max_index, userSpace,
+ vbuffer, velements);
+ num_vbuffers = 1;
+ num_velements = vp->num_inputs;
+ if (num_velements == 0)
+ num_vbuffers = 0;
+ }
+ else {
+ /*printf("Draw non-interleaved\n");*/
+ setup_non_interleaved_attribs(ctx, vp, arrays, max_index,
+ &userSpace, vbuffer, velements);
+ num_vbuffers = vp->num_inputs;
+ num_velements = vp->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].nr_comps = %u\n", i, velements[i].nr_components);
+ printf("vlements[%d].format = %s\n", i, pf_name(velements[i].src_format));
+ }
+ }
+#endif
+
+ pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer);
+ pipe->set_vertex_elements(pipe, num_velements, velements);
+
+ if (num_vbuffers == 0 || num_velements == 0)
+ return;
+
+ /* do actual drawing */
+ if (ib) {
+ /* indexed primitive */
+ struct gl_buffer_object *bufobj = ib->obj;
+ struct pipe_buffer *indexBuf = NULL;
+ unsigned indexSize, indexOffset, i;
+
+ switch (ib->type) {
+ case GL_UNSIGNED_INT:
+ indexSize = 4;
+ break;
+ case GL_UNSIGNED_SHORT:
+ indexSize = 2;
+ break;
+ case GL_UNSIGNED_BYTE:
+ indexSize = 1;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ /* get/create the index buffer object */
+ if (bufobj && bufobj->Name) {
+ /* elements/indexes are in a real VBO */
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ pipe_buffer_reference(&indexBuf, stobj->buffer);
+ indexOffset = pointer_to_offset(ib->ptr) / indexSize;
+ }
+ else {
+ /* element/indicies are in user space memory */
+ indexBuf = pipe_user_buffer_create(pipe->screen, (void *) ib->ptr,
+ ib->count * indexSize);
+ indexOffset = 0;
+ }
+
+ /* draw */
+ if (nr_prims == 1 && pipe->draw_range_elements != NULL) {
+ i = 0;
+
+ /* XXX: exercise temporary path to pass min/max directly
+ * through to driver & draw module. These interfaces still
+ * need a bit of work...
+ */
+ setup_edgeflags(ctx, prims[i].mode,
+ prims[i].start + indexOffset, prims[i].count,
+ arrays[VERT_ATTRIB_EDGEFLAG]);
+
+ pipe->draw_range_elements(pipe, indexBuf, indexSize,
+ min_index,
+ max_index,
+ prims[i].mode,
+ prims[i].start + indexOffset, prims[i].count);
+ }
+ else {
+ for (i = 0; i < nr_prims; i++) {
+ setup_edgeflags(ctx, prims[i].mode,
+ prims[i].start + indexOffset, prims[i].count,
+ arrays[VERT_ATTRIB_EDGEFLAG]);
+
+ pipe->draw_elements(pipe, indexBuf, indexSize,
+ prims[i].mode,
+ prims[i].start + indexOffset, prims[i].count);
+ }
+ }
+
+ pipe_buffer_reference(&indexBuf, NULL);
+ }
+ else {
+ /* non-indexed */
+ GLuint i;
+ for (i = 0; i < nr_prims; i++) {
+ setup_edgeflags(ctx, prims[i].mode,
+ prims[i].start, prims[i].count,
+ arrays[VERT_ATTRIB_EDGEFLAG]);
+
+ pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count);
+ }
+ }
+
+ /* unreference buffers (frees wrapped user-space buffer objects) */
+ for (attr = 0; attr < num_vbuffers; attr++) {
+ pipe_buffer_reference(&vbuffer[attr].buffer, NULL);
+ assert(!vbuffer[attr].buffer);
+ }
+
+ if (userSpace)
+ {
+ pipe->set_vertex_buffers(pipe, 0, NULL);
+ }
+}
+
+
+void st_init_draw( struct st_context *st )
+{
+ GLcontext *ctx = st->ctx;
+
+ vbo_set_draw_func(ctx, st_draw_vbo);
+}
+
+
+void st_destroy_draw( struct st_context *st )
+{
+}
+
+
diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h
new file mode 100644
index 0000000000..3e0face656
--- /dev/null
+++ b/src/mesa/state_tracker/st_draw.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * Copyright 2004 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef ST_DRAW_H
+#define ST_DRAW_H
+
+struct _mesa_prim;
+struct _mesa_index_buffer;
+
+void st_init_draw( struct st_context *st );
+
+void st_destroy_draw( struct st_context *st );
+
+extern void
+st_draw_vbo(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index);
+
+extern void
+st_feedback_draw_vbo(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index);
+
+/* Internal function:
+ */
+extern GLuint
+st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
+ GLboolean normalized);
+
+
+/**
+ * When drawing with VBOs, the addresses specified with
+ * glVertex/Color/TexCoordPointer() are really offsets into the VBO, not real
+ * addresses. At some point we need to convert those pointers to offsets.
+ * This function is basically a cast wrapper to avoid warnings when building
+ * in 64-bit mode.
+ */
+static INLINE unsigned
+pointer_to_offset(const void *ptr)
+{
+ return (unsigned) (((unsigned long) ptr) & 0xffffffffUL);
+}
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
new file mode 100644
index 0000000000..b2d682ef64
--- /dev/null
+++ b/src/mesa/state_tracker/st_draw_feedback.c
@@ -0,0 +1,274 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "shader/prog_uniform.h"
+
+#include "vbo/vbo.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_cb_bufferobjects.h"
+#include "st_draw.h"
+#include "st_program.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "draw/draw_private.h"
+#include "draw/draw_context.h"
+
+
+#if FEATURE_feedback || FEATURE_drawpix
+
+/**
+ * Set the (private) draw module's post-transformed vertex format when in
+ * GL_SELECT or GL_FEEDBACK mode or for glRasterPos.
+ */
+static void
+set_feedback_vertex_format(GLcontext *ctx)
+{
+#if 0
+ struct st_context *st = ctx->st;
+ struct vertex_info vinfo;
+ GLuint i;
+
+ memset(&vinfo, 0, sizeof(vinfo));
+
+ if (ctx->RenderMode == GL_SELECT) {
+ assert(ctx->RenderMode == GL_SELECT);
+ vinfo.num_attribs = 1;
+ vinfo.format[0] = FORMAT_4F;
+ vinfo.interp_mode[0] = INTERP_LINEAR;
+ }
+ else {
+ /* GL_FEEDBACK, or glRasterPos */
+ /* emit all attribs (pos, color, texcoord) as GLfloat[4] */
+ vinfo.num_attribs = st->state.vs->cso->state.num_outputs;
+ for (i = 0; i < vinfo.num_attribs; i++) {
+ vinfo.format[i] = FORMAT_4F;
+ vinfo.interp_mode[i] = INTERP_LINEAR;
+ }
+ }
+
+ draw_set_vertex_info(st->draw, &vinfo);
+#endif
+}
+
+
+/**
+ * Called by VBO to draw arrays when in selection or feedback mode and
+ * to implement glRasterPos.
+ * This is very much like the normal draw_vbo() function above.
+ * Look at code refactoring some day.
+ * Might move this into the failover module some day.
+ */
+void
+st_feedback_draw_vbo(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct draw_context *draw = st->draw;
+ const struct st_vertex_program *vp;
+ const struct pipe_shader_state *vs;
+ struct pipe_buffer *index_buffer_handle = 0;
+ struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
+ struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+ GLuint attr, i;
+ ubyte *mapped_constants;
+
+ assert(draw);
+
+ st_validate_state(ctx->st);
+
+ if (!index_bounds_valid)
+ vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+
+ /* must get these after state validation! */
+ vp = ctx->st->vp;
+ vs = &st->vp->state;
+
+ if (!st->vp->draw_shader) {
+ st->vp->draw_shader = draw_create_vertex_shader(draw, vs);
+ }
+
+ /*
+ * Set up the draw module's state.
+ *
+ * We'd like to do this less frequently, but the normal state-update
+ * code sends state updates to the pipe, not to our private draw module.
+ */
+ assert(draw);
+ draw_set_viewport_state(draw, &st->state.viewport);
+ draw_set_clip_state(draw, &st->state.clip);
+ draw_set_rasterizer_state(draw, &st->state.rasterizer);
+ draw_bind_vertex_shader(draw, st->vp->draw_shader);
+ set_feedback_vertex_format(ctx);
+
+ /* loop over TGSI shader inputs to determine vertex buffer
+ * and attribute info
+ */
+ for (attr = 0; attr < vp->num_inputs; attr++) {
+ const GLuint mesaAttr = vp->index_to_input[attr];
+ struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
+ void *map;
+
+ if (bufobj && bufobj->Name) {
+ /* Attribute data is in a VBO.
+ * Recall that for VBOs, the gl_client_array->Ptr field is
+ * really an offset from the start of the VBO, not a pointer.
+ */
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+ assert(stobj->buffer);
+
+ vbuffers[attr].buffer = NULL;
+ pipe_buffer_reference(&vbuffers[attr].buffer, stobj->buffer);
+ vbuffers[attr].buffer_offset = pointer_to_offset(arrays[0]->Ptr);
+ velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr;
+ }
+ else {
+ /* attribute data is in user-space memory, not a VBO */
+ uint bytes = (arrays[mesaAttr]->Size
+ * _mesa_sizeof_type(arrays[mesaAttr]->Type)
+ * (max_index + 1));
+
+ /* wrap user data */
+ vbuffers[attr].buffer
+ = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
+ bytes);
+ vbuffers[attr].buffer_offset = 0;
+ velements[attr].src_offset = 0;
+ }
+
+ /* common-case setup */
+ vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
+ vbuffers[attr].max_index = max_index;
+ velements[attr].vertex_buffer_index = attr;
+ velements[attr].nr_components = arrays[mesaAttr]->Size;
+ velements[attr].src_format =
+ st_pipe_vertex_format(arrays[mesaAttr]->Type,
+ arrays[mesaAttr]->Size,
+ arrays[mesaAttr]->Format,
+ arrays[mesaAttr]->Normalized);
+ assert(velements[attr].src_format);
+
+ /* tell draw about this attribute */
+#if 0
+ draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
+#endif
+
+ /* map the attrib buffer */
+ map = pipe_buffer_map(pipe->screen, vbuffers[attr].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_vertex_buffer(draw, attr, map);
+ }
+
+ draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
+ draw_set_vertex_elements(draw, vp->num_inputs, velements);
+
+ if (ib) {
+ struct gl_buffer_object *bufobj = ib->obj;
+ unsigned indexSize;
+ void *map;
+
+ switch (ib->type) {
+ case GL_UNSIGNED_INT:
+ indexSize = 4;
+ break;
+ case GL_UNSIGNED_SHORT:
+ indexSize = 2;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ if (bufobj && bufobj->Name) {
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+
+ index_buffer_handle = stobj->buffer;
+
+ map = pipe_buffer_map(pipe->screen, index_buffer_handle,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ draw_set_mapped_element_buffer(draw, indexSize, map);
+ }
+ else {
+ draw_set_mapped_element_buffer(draw, indexSize, (void *) ib->ptr);
+ }
+ }
+ else {
+ /* no index/element buffer */
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+
+
+ /* map constant buffers */
+ mapped_constants = pipe_buffer_map(pipe->screen,
+ st->state.constants[PIPE_SHADER_VERTEX].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_constant_buffer(st->draw, mapped_constants,
+ st->state.constants[PIPE_SHADER_VERTEX].buffer->size);
+
+
+ /* draw here */
+ for (i = 0; i < nr_prims; i++) {
+ draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
+ }
+
+
+ /* unmap constant buffers */
+ pipe_buffer_unmap(pipe->screen, st->state.constants[PIPE_SHADER_VERTEX].buffer);
+
+ /*
+ * unmap vertex/index buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (draw->pt.vertex_buffer[i].buffer) {
+ pipe_buffer_unmap(pipe->screen, draw->pt.vertex_buffer[i].buffer);
+ pipe_buffer_reference(&draw->pt.vertex_buffer[i].buffer, NULL);
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ }
+ }
+ if (index_buffer_handle) {
+ pipe_buffer_unmap(pipe->screen, index_buffer_handle);
+ draw_set_mapped_element_buffer(draw, 0, NULL);
+ }
+}
+
+#endif /* FEATURE_feedback || FEATURE_drawpix */
+
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
new file mode 100644
index 0000000000..ce3c302e48
--- /dev/null
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -0,0 +1,308 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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/imports.h"
+#include "main/context.h"
+#include "main/extensions.h"
+#include "main/macros.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+
+#include "st_context.h"
+#include "st_extensions.h"
+
+
+static int _min(int a, int b)
+{
+ return (a < b) ? a : b;
+}
+
+static float _maxf(float a, float b)
+{
+ return (a > b) ? a : b;
+}
+
+static int _clamp(int a, int min, int max)
+{
+ if (a < min)
+ return min;
+ else if (a > max)
+ return max;
+ else
+ return a;
+}
+
+
+/**
+ * Query driver to get implementation limits.
+ * Note that we have to limit/clamp against Mesa's internal limits too.
+ */
+void st_init_limits(struct st_context *st)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+ struct gl_constants *c = &st->ctx->Const;
+
+ c->MaxTextureLevels
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS),
+ MAX_TEXTURE_LEVELS);
+
+ c->Max3DTextureLevels
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS),
+ MAX_3D_TEXTURE_LEVELS);
+
+ c->MaxCubeTextureLevels
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS),
+ MAX_CUBE_TEXTURE_LEVELS);
+
+ c->MaxTextureRectSize
+ = _min(1 << (c->MaxTextureLevels - 1), MAX_TEXTURE_RECT_SIZE);
+
+ c->MaxTextureImageUnits
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS),
+ MAX_TEXTURE_IMAGE_UNITS);
+
+ c->MaxVertexTextureImageUnits
+ = _min(screen->get_param(screen, PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS),
+ MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+
+ c->MaxTextureCoordUnits
+ = _min(c->MaxTextureImageUnits, MAX_TEXTURE_COORD_UNITS);
+
+ c->MaxTextureUnits = _min(c->MaxTextureImageUnits, c->MaxTextureCoordUnits);
+
+ c->MaxDrawBuffers
+ = _clamp(screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS),
+ 1, MAX_DRAW_BUFFERS);
+
+ c->MaxLineWidth
+ = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_LINE_WIDTH));
+ c->MaxLineWidthAA
+ = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_LINE_WIDTH_AA));
+
+ c->MaxPointSize
+ = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_POINT_WIDTH));
+ c->MaxPointSizeAA
+ = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_POINT_WIDTH_AA));
+
+ c->MaxTextureMaxAnisotropy
+ = _maxf(2.0f, screen->get_paramf(screen, PIPE_CAP_MAX_TEXTURE_ANISOTROPY));
+
+ c->MaxTextureLodBias
+ = screen->get_paramf(screen, PIPE_CAP_MAX_TEXTURE_LOD_BIAS);
+
+ c->MaxDrawBuffers
+ = CLAMP(screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS),
+ 1, MAX_DRAW_BUFFERS);
+
+ /* Is TGSI_OPCODE_CONT supported? */
+ /* XXX separate query for early function return? */
+ st->ctx->Shader.EmitContReturn =
+ screen->get_param(screen, PIPE_CAP_TGSI_CONT_SUPPORTED);
+}
+
+
+/**
+ * Use pipe_screen::get_param() to query PIPE_CAP_ values to determine
+ * which GL extensions are supported.
+ * Quite a few extensions are always supported because they are standard
+ * features or can be built on top of other gallium features.
+ * Some fine tuning may still be needed.
+ */
+void st_init_extensions(struct st_context *st)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+ GLcontext *ctx = st->ctx;
+
+ /*
+ * Extensions that are supported by all Gallium drivers:
+ */
+ ctx->Extensions.ARB_copy_buffer = GL_TRUE;
+ ctx->Extensions.ARB_fragment_program = GL_TRUE;
+ ctx->Extensions.ARB_map_buffer_range = GL_TRUE;
+ ctx->Extensions.ARB_multisample = GL_TRUE;
+ ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; /* XXX temp */
+ ctx->Extensions.ARB_texture_compression = GL_TRUE;
+ ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE;
+ ctx->Extensions.ARB_vertex_array_object = GL_TRUE;
+ ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;
+ ctx->Extensions.ARB_vertex_program = GL_TRUE;
+
+ ctx->Extensions.EXT_blend_color = GL_TRUE;
+ ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
+ ctx->Extensions.EXT_blend_logic_op = GL_TRUE;
+ ctx->Extensions.EXT_blend_minmax = GL_TRUE;
+ ctx->Extensions.EXT_blend_subtract = GL_TRUE;
+ ctx->Extensions.EXT_framebuffer_blit = GL_TRUE;
+ ctx->Extensions.EXT_framebuffer_object = GL_TRUE;
+ ctx->Extensions.EXT_fog_coord = GL_TRUE;
+ ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;
+ ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
+ ctx->Extensions.EXT_point_parameters = GL_TRUE;
+ ctx->Extensions.EXT_provoking_vertex = GL_TRUE;
+ ctx->Extensions.EXT_secondary_color = GL_TRUE;
+ ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_add = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_combine = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
+ ctx->Extensions.EXT_texture_lod_bias = GL_TRUE;
+ ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE;
+
+ ctx->Extensions.APPLE_vertex_array_object = GL_TRUE;
+
+ ctx->Extensions.NV_blend_square = GL_TRUE;
+ ctx->Extensions.NV_texgen_reflection = GL_TRUE;
+ ctx->Extensions.NV_texture_env_combine4 = GL_TRUE;
+
+#if FEATURE_OES_draw_texture
+ ctx->Extensions.OES_draw_texture = GL_TRUE;
+#endif
+
+ ctx->Extensions.SGI_color_matrix = GL_TRUE;
+ ctx->Extensions.SGIS_generate_mipmap = GL_TRUE;
+
+ /*
+ * Extensions that depend on the driver/hardware:
+ */
+ if (screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS) > 0) {
+ ctx->Extensions.ARB_draw_buffers = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_GLSL)) {
+ ctx->Extensions.ARB_fragment_shader = GL_TRUE;
+ ctx->Extensions.ARB_vertex_shader = GL_TRUE;
+ ctx->Extensions.ARB_shader_objects = GL_TRUE;
+ ctx->Extensions.ARB_shading_language_100 = GL_TRUE;
+ ctx->Extensions.ARB_shading_language_120 = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_TEXTURE_MIRROR_REPEAT) > 0) {
+ ctx->Extensions.ARB_texture_mirrored_repeat = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_BLEND_EQUATION_SEPARATE)) {
+ ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_TEXTURE_MIRROR_CLAMP) > 0) {
+ ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) {
+ ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE;
+ ctx->Extensions.NV_texture_rectangle = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS) > 1) {
+ ctx->Extensions.ARB_multitexture = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
+ ctx->Extensions.ATI_separate_stencil = GL_TRUE;
+ ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_ANISOTROPIC_FILTER)) {
+ ctx->Extensions.EXT_texture_filter_anisotropic = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_POINT_SPRITE)) {
+ ctx->Extensions.ARB_point_sprite = GL_TRUE;
+ /* GL_NV_point_sprite is not supported by gallium because we don't
+ * support the GL_POINT_SPRITE_R_MODE_NV option.
+ */
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY)) {
+ ctx->Extensions.ARB_occlusion_query = GL_TRUE;
+ }
+
+ if (screen->get_param(screen, PIPE_CAP_TEXTURE_SHADOW_MAP)) {
+ ctx->Extensions.ARB_depth_texture = GL_TRUE;
+ ctx->Extensions.ARB_shadow = GL_TRUE;
+ ctx->Extensions.EXT_shadow_funcs = GL_TRUE;
+ /*ctx->Extensions.ARB_shadow_ambient = GL_TRUE;*/
+ }
+
+ /* GL_EXT_packed_depth_stencil requires both the ability to render to
+ * a depth/stencil buffer and texture from depth/stencil source.
+ */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0) &&
+ screen->is_format_supported(screen, PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE;
+ }
+ else if (screen->is_format_supported(screen, PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0) &&
+ screen->is_format_supported(screen, PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE;
+ }
+
+ /* sRGB support */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8B8A8_SRGB,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0) ||
+ screen->is_format_supported(screen, PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
+ }
+
+ /* s3tc support */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE;
+ }
+
+ /* ycbcr support */
+ if (screen->is_format_supported(screen, PIPE_FORMAT_YCBCR,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0) ||
+ screen->is_format_supported(screen, PIPE_FORMAT_YCBCR_REV,
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+ ctx->Extensions.MESA_ycbcr_texture = GL_TRUE;
+ }
+
+ /* GL_ARB_framebuffer_object */
+ if (ctx->Extensions.EXT_packed_depth_stencil) {
+ /* we support always support GL_EXT_framebuffer_blit */
+ ctx->Extensions.ARB_framebuffer_object = GL_TRUE;
+ }
+}
diff --git a/src/mesa/state_tracker/st_extensions.h b/src/mesa/state_tracker/st_extensions.h
new file mode 100644
index 0000000000..2994f16dd3
--- /dev/null
+++ b/src/mesa/state_tracker/st_extensions.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_EXTENSIONS_H
+#define ST_EXTENSIONS_H
+
+
+extern void st_init_limits(struct st_context *st);
+
+extern void st_init_extensions(struct st_context *st);
+
+
+#endif /* ST_EXTENSIONS_H */
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
new file mode 100644
index 0000000000..dcb90a3107
--- /dev/null
+++ b/src/mesa/state_tracker/st_format.c
@@ -0,0 +1,742 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2008 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * Texture Image-related functions.
+ * \author Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/texstore.h"
+#include "main/texformat.h"
+#include "main/enums.h"
+#include "main/macros.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "st_context.h"
+#include "st_format.h"
+
+static GLuint
+format_bits(
+ pipe_format_rgbazs_t info,
+ GLuint comp )
+{
+ return pf_get_component_bits( (enum pipe_format) info, comp );
+}
+
+static GLuint
+format_max_bits(
+ pipe_format_rgbazs_t info )
+{
+ GLuint size = format_bits( info, PIPE_FORMAT_COMP_R );
+
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_G ) );
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_B ) );
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_A ) );
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_Z ) );
+ size = MAX2( size, format_bits( info, PIPE_FORMAT_COMP_S ) );
+ return size;
+}
+
+static GLuint
+format_size(
+ pipe_format_rgbazs_t info )
+{
+ return
+ format_bits( info, PIPE_FORMAT_COMP_R ) +
+ format_bits( info, PIPE_FORMAT_COMP_G ) +
+ format_bits( info, PIPE_FORMAT_COMP_B ) +
+ format_bits( info, PIPE_FORMAT_COMP_A ) +
+ format_bits( info, PIPE_FORMAT_COMP_Z ) +
+ format_bits( info, PIPE_FORMAT_COMP_S );
+}
+
+/*
+ * XXX temporary here
+ */
+GLboolean
+st_get_format_info(enum pipe_format format, struct pipe_format_info *pinfo)
+{
+ if (pf_layout(format) == PIPE_FORMAT_LAYOUT_RGBAZS) {
+ pipe_format_rgbazs_t info;
+
+ info = format;
+
+#if 0
+ printf("%s\n", pf_name( format ) );
+#endif
+
+ /* Data type */
+ if (format == PIPE_FORMAT_A1R5G5B5_UNORM || format == PIPE_FORMAT_R5G6B5_UNORM) {
+ pinfo->datatype = GL_UNSIGNED_SHORT;
+ }
+ else {
+ GLuint size;
+
+ size = format_max_bits( info );
+ if (size == 8) {
+ if (pf_type(info) == PIPE_FORMAT_TYPE_UNORM)
+ pinfo->datatype = GL_UNSIGNED_BYTE;
+ else
+ pinfo->datatype = GL_BYTE;
+ }
+ else if (size == 16) {
+ if (pf_type(info) == PIPE_FORMAT_TYPE_UNORM)
+ pinfo->datatype = GL_UNSIGNED_SHORT;
+ else
+ pinfo->datatype = GL_SHORT;
+ }
+ else {
+ assert( size <= 32 );
+ if (pf_type(info) == PIPE_FORMAT_TYPE_UNORM)
+ pinfo->datatype = GL_UNSIGNED_INT;
+ else
+ pinfo->datatype = GL_INT;
+ }
+ }
+
+ /* Component bits */
+ pinfo->red_bits = format_bits( info, PIPE_FORMAT_COMP_R );
+ pinfo->green_bits = format_bits( info, PIPE_FORMAT_COMP_G );
+ pinfo->blue_bits = format_bits( info, PIPE_FORMAT_COMP_B );
+ pinfo->alpha_bits = format_bits( info, PIPE_FORMAT_COMP_A );
+ pinfo->depth_bits = format_bits( info, PIPE_FORMAT_COMP_Z );
+ pinfo->stencil_bits = format_bits( info, PIPE_FORMAT_COMP_S );
+ pinfo->luminance_bits = 0;
+ pinfo->intensity_bits = 0;
+
+ /* Format size */
+ pinfo->size = format_size( info ) / 8;
+
+ /* Luminance & Intensity bits */
+ if( pf_swizzle_x(info) == PIPE_FORMAT_COMP_R &&
+ pf_swizzle_y(info) == PIPE_FORMAT_COMP_R &&
+ pf_swizzle_z(info) == PIPE_FORMAT_COMP_R ) {
+ if( pf_swizzle_w(info) == PIPE_FORMAT_COMP_R ) {
+ pinfo->intensity_bits = pinfo->red_bits;
+ }
+ else {
+ pinfo->luminance_bits = pinfo->red_bits;
+ }
+ pinfo->red_bits = 0;
+ }
+
+ /* Base format */
+ if (pinfo->depth_bits) {
+ if (pinfo->stencil_bits) {
+ pinfo->base_format = GL_DEPTH_STENCIL_EXT;
+ }
+ else {
+ pinfo->base_format = GL_DEPTH_COMPONENT;
+ }
+ }
+ else if (pinfo->stencil_bits) {
+ pinfo->base_format = GL_STENCIL_INDEX;
+ }
+ else {
+ pinfo->base_format = GL_RGBA;
+ }
+ }
+ else if (pf_layout(format) == PIPE_FORMAT_LAYOUT_YCBCR) {
+ pinfo->base_format = GL_YCBCR_MESA;
+ pinfo->datatype = GL_UNSIGNED_SHORT;
+ pinfo->size = 2; /* two bytes per "texel" */
+ }
+ else {
+ /* compressed format? */
+ assert(0);
+ }
+
+#if 0
+ printf(
+ "ST_FORMAT: R(%u), G(%u), B(%u), A(%u), Z(%u), S(%u)\n",
+ pinfo->red_bits,
+ pinfo->green_bits,
+ pinfo->blue_bits,
+ pinfo->alpha_bits,
+ pinfo->depth_bits,
+ pinfo->stencil_bits );
+#endif
+
+ pinfo->format = format;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Return bytes per pixel for the given format.
+ */
+GLuint
+st_sizeof_format(enum pipe_format format)
+{
+ struct pipe_format_info info;
+ if (!st_get_format_info( format, &info )) {
+ assert( 0 );
+ return 0;
+ }
+ return info.size;
+}
+
+
+/**
+ * Return bytes per pixel for the given format.
+ */
+GLenum
+st_format_datatype(enum pipe_format format)
+{
+ struct pipe_format_info info;
+ if (!st_get_format_info( format, &info )) {
+ assert( 0 );
+ return 0;
+ }
+ return info.datatype;
+}
+
+
+enum pipe_format
+st_mesa_format_to_pipe_format(GLuint mesaFormat)
+{
+ switch (mesaFormat) {
+ /* fix this */
+ case MESA_FORMAT_ARGB8888_REV:
+ case MESA_FORMAT_ARGB8888:
+ return PIPE_FORMAT_A8R8G8B8_UNORM;
+ case MESA_FORMAT_ARGB1555:
+ return PIPE_FORMAT_A1R5G5B5_UNORM;
+ case MESA_FORMAT_ARGB4444:
+ return PIPE_FORMAT_A4R4G4B4_UNORM;
+ case MESA_FORMAT_RGB565:
+ return PIPE_FORMAT_R5G6B5_UNORM;
+ case MESA_FORMAT_AL88:
+ return PIPE_FORMAT_A8L8_UNORM;
+ case MESA_FORMAT_A8:
+ return PIPE_FORMAT_A8_UNORM;
+ case MESA_FORMAT_L8:
+ return PIPE_FORMAT_L8_UNORM;
+ case MESA_FORMAT_I8:
+ return PIPE_FORMAT_I8_UNORM;
+ case MESA_FORMAT_Z16:
+ return PIPE_FORMAT_Z16_UNORM;
+ case MESA_FORMAT_Z32:
+ return PIPE_FORMAT_Z32_UNORM;
+ case MESA_FORMAT_Z24_S8:
+ return PIPE_FORMAT_Z24S8_UNORM;
+ case MESA_FORMAT_S8_Z24:
+ return PIPE_FORMAT_S8Z24_UNORM;
+ case MESA_FORMAT_YCBCR:
+ return PIPE_FORMAT_YCBCR;
+#if FEATURE_texture_s3tc
+ case MESA_FORMAT_RGB_DXT1:
+ return PIPE_FORMAT_DXT1_RGB;
+ case MESA_FORMAT_RGBA_DXT1:
+ return PIPE_FORMAT_DXT1_RGBA;
+ case MESA_FORMAT_RGBA_DXT3:
+ return PIPE_FORMAT_DXT3_RGBA;
+ case MESA_FORMAT_RGBA_DXT5:
+ return PIPE_FORMAT_DXT5_RGBA;
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ return PIPE_FORMAT_DXT1_SRGB;
+ case MESA_FORMAT_SRGBA_DXT1:
+ return PIPE_FORMAT_DXT1_SRGBA;
+ case MESA_FORMAT_SRGBA_DXT3:
+ return PIPE_FORMAT_DXT3_SRGBA;
+ case MESA_FORMAT_SRGBA_DXT5:
+ return PIPE_FORMAT_DXT5_SRGBA;
+#endif
+#endif
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SLA8:
+ return PIPE_FORMAT_A8L8_SRGB;
+ case MESA_FORMAT_SL8:
+ return PIPE_FORMAT_L8_SRGB;
+ case MESA_FORMAT_SRGB8:
+ return PIPE_FORMAT_R8G8B8_SRGB;
+ case MESA_FORMAT_SRGBA8:
+ return PIPE_FORMAT_R8G8B8A8_SRGB;
+ case MESA_FORMAT_SARGB8:
+ return PIPE_FORMAT_A8R8G8B8_SRGB;
+#endif
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+/**
+ * Find an RGBA format supported by the context/winsys.
+ */
+static enum pipe_format
+default_rgba_format(struct pipe_screen *screen,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ static const enum pipe_format colorFormats[] = {
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_R5G6B5_UNORM
+ };
+ uint i;
+ for (i = 0; i < Elements(colorFormats); i++) {
+ if (screen->is_format_supported( screen, colorFormats[i], target, tex_usage, geom_flags )) {
+ return colorFormats[i];
+ }
+ }
+ return PIPE_FORMAT_NONE;
+}
+
+/**
+ * Find an sRGBA format supported by the context/winsys.
+ */
+static enum pipe_format
+default_srgba_format(struct pipe_screen *screen,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ static const enum pipe_format colorFormats[] = {
+ PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_B8G8R8A8_SRGB,
+ PIPE_FORMAT_R8G8B8A8_SRGB,
+ };
+ uint i;
+ for (i = 0; i < Elements(colorFormats); i++) {
+ if (screen->is_format_supported( screen, colorFormats[i], target, tex_usage, geom_flags )) {
+ return colorFormats[i];
+ }
+ }
+ return PIPE_FORMAT_NONE;
+}
+
+/**
+ * Search list of formats for first RGBA format with >8 bits/channel.
+ */
+static enum pipe_format
+default_deep_rgba_format(struct pipe_screen *screen,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_SNORM, target, tex_usage, geom_flags)) {
+ return PIPE_FORMAT_R16G16B16A16_SNORM;
+ }
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET)
+ return default_rgba_format(screen, target, tex_usage, geom_flags);
+ else
+ return PIPE_FORMAT_NONE;
+}
+
+
+/**
+ * Find an Z format supported by the context/winsys.
+ */
+static enum pipe_format
+default_depth_format(struct pipe_screen *screen,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ static const enum pipe_format zFormats[] = {
+ PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM
+ };
+ uint i;
+ for (i = 0; i < Elements(zFormats); i++) {
+ if (screen->is_format_supported( screen, zFormats[i], target, tex_usage, geom_flags )) {
+ return zFormats[i];
+ }
+ }
+ return PIPE_FORMAT_NONE;
+}
+
+
+/**
+ * Given an OpenGL internalFormat value for a texture or surface, return
+ * the best matching PIPE_FORMAT_x, or PIPE_FORMAT_NONE if there's no match.
+ * \param target one of PIPE_TEXTURE_x
+ * \param tex_usage either PIPE_TEXTURE_USAGE_RENDER_TARGET
+ * or PIPE_TEXTURE_USAGE_SAMPLER
+ */
+enum pipe_format
+st_choose_format(struct pipe_context *pipe, GLenum internalFormat,
+ enum pipe_texture_target target, unsigned tex_usage)
+{
+ struct pipe_screen *screen = pipe->screen;
+ unsigned geom_flags = 0;
+
+ switch (internalFormat) {
+ case 4:
+ case GL_RGBA:
+ case GL_COMPRESSED_RGBA:
+ case 3:
+ case GL_RGB:
+ case GL_COMPRESSED_RGB:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+ case GL_RGBA16:
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET)
+ return default_deep_rgba_format( screen, target, tex_usage, geom_flags );
+ else
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_RGBA4:
+ case GL_RGBA2:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A4R4G4B4_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A4R4G4B4_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_RGB5_A1:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A1R5G5B5_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A1R5G5B5_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_RGB5:
+ case GL_RGB4:
+ case GL_R3_G3_B2:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_R5G6B5_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_R5G6B5_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A1R5G5B5_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A1R5G5B5_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case GL_COMPRESSED_ALPHA:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A8_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_COMPRESSED_LUMINANCE:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_L8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_L8_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case 2:
+ 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:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A8L8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A8L8_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case GL_COMPRESSED_INTENSITY:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_I8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_I8_UNORM;
+ return default_rgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_YCBCR_MESA:
+ if (screen->is_format_supported(screen, PIPE_FORMAT_YCBCR,
+ target, tex_usage, geom_flags)) {
+ return PIPE_FORMAT_YCBCR;
+ }
+ if (screen->is_format_supported(screen, PIPE_FORMAT_YCBCR_REV,
+ target, tex_usage, geom_flags)) {
+ return PIPE_FORMAT_YCBCR_REV;
+ }
+ return PIPE_FORMAT_NONE;
+
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return PIPE_FORMAT_DXT1_RGB;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return PIPE_FORMAT_DXT1_RGBA;
+
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ return PIPE_FORMAT_DXT3_RGBA;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return PIPE_FORMAT_DXT5_RGBA;
+
+#if 0
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ return PIPE_FORMAT_RGB_FXT1;
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ return PIPE_FORMAT_RGB_FXT1;
+#endif
+
+ case GL_DEPTH_COMPONENT16:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z16_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z16_UNORM;
+ /* fall-through */
+ case GL_DEPTH_COMPONENT24:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_S8Z24_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_S8Z24_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z24S8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z24S8_UNORM;
+ /* fall-through */
+ case GL_DEPTH_COMPONENT32:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z32_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z32_UNORM;
+ /* fall-through */
+ case GL_DEPTH_COMPONENT:
+ return default_depth_format( screen, target, tex_usage, geom_flags );
+
+ case GL_STENCIL_INDEX:
+ case GL_STENCIL_INDEX1_EXT:
+ case GL_STENCIL_INDEX4_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ case GL_STENCIL_INDEX16_EXT:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_S8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_S8_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_S8Z24_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_S8Z24_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z24S8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z24S8_UNORM;
+ return PIPE_FORMAT_NONE;
+
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_S8Z24_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_S8Z24_UNORM;
+ if (screen->is_format_supported( screen, PIPE_FORMAT_Z24S8_UNORM, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_Z24S8_UNORM;
+ return PIPE_FORMAT_NONE;
+
+ case GL_SRGB_EXT:
+ case GL_SRGB8_EXT:
+ case GL_COMPRESSED_SRGB_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ return default_srgba_format( screen, target, tex_usage, geom_flags );
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return PIPE_FORMAT_DXT1_SRGB;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ return PIPE_FORMAT_DXT1_SRGBA;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ return PIPE_FORMAT_DXT3_SRGBA;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return PIPE_FORMAT_DXT5_SRGBA;
+
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ case GL_COMPRESSED_SLUMINANCE_EXT:
+ case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_A8L8_SRGB, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_A8L8_SRGB;
+ return default_srgba_format( screen, target, tex_usage, geom_flags );
+
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ if (screen->is_format_supported( screen, PIPE_FORMAT_L8_SRGB, target, tex_usage, geom_flags ))
+ return PIPE_FORMAT_L8_SRGB;
+ return default_srgba_format( screen, target, tex_usage, geom_flags );
+
+ default:
+ return PIPE_FORMAT_NONE;
+ }
+}
+
+
+static GLboolean
+is_depth_or_stencil_format(GLenum internalFormat)
+{
+ switch (internalFormat) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ case GL_STENCIL_INDEX:
+ case GL_STENCIL_INDEX1_EXT:
+ case GL_STENCIL_INDEX4_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ case GL_STENCIL_INDEX16_EXT:
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+/**
+ * Called by FBO code to choose a PIPE_FORMAT_ for drawing surfaces.
+ */
+enum pipe_format
+st_choose_renderbuffer_format(struct pipe_context *pipe, GLenum internalFormat)
+{
+ uint usage;
+ if (is_depth_or_stencil_format(internalFormat))
+ usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+ else
+ usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+ return st_choose_format(pipe, internalFormat, PIPE_TEXTURE_2D, usage);
+}
+
+
+static const struct gl_texture_format *
+translate_gallium_format_to_mesa_format(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return &_mesa_texformat_argb8888;
+ case PIPE_FORMAT_A1R5G5B5_UNORM:
+ return &_mesa_texformat_argb1555;
+ case PIPE_FORMAT_A4R4G4B4_UNORM:
+ return &_mesa_texformat_argb4444;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return &_mesa_texformat_rgb565;
+ case PIPE_FORMAT_A8L8_UNORM:
+ return &_mesa_texformat_al88;
+ case PIPE_FORMAT_A8_UNORM:
+ return &_mesa_texformat_a8;
+ case PIPE_FORMAT_L8_UNORM:
+ return &_mesa_texformat_l8;
+ case PIPE_FORMAT_I8_UNORM:
+ return &_mesa_texformat_i8;
+ case PIPE_FORMAT_Z16_UNORM:
+ return &_mesa_texformat_z16;
+ case PIPE_FORMAT_Z32_UNORM:
+ return &_mesa_texformat_z32;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ return &_mesa_texformat_z24_s8;
+ case PIPE_FORMAT_S8Z24_UNORM:
+ return &_mesa_texformat_s8_z24;
+ case PIPE_FORMAT_YCBCR:
+ return &_mesa_texformat_ycbcr;
+ case PIPE_FORMAT_YCBCR_REV:
+ return &_mesa_texformat_ycbcr_rev;
+#if FEATURE_texture_s3tc
+ case PIPE_FORMAT_DXT1_RGB:
+ return &_mesa_texformat_rgb_dxt1;
+ case PIPE_FORMAT_DXT1_RGBA:
+ return &_mesa_texformat_rgba_dxt1;
+ case PIPE_FORMAT_DXT3_RGBA:
+ return &_mesa_texformat_rgba_dxt3;
+ case PIPE_FORMAT_DXT5_RGBA:
+ return &_mesa_texformat_rgba_dxt5;
+#if FEATURE_EXT_texture_sRGB
+ case PIPE_FORMAT_DXT1_SRGB:
+ return &_mesa_texformat_srgb_dxt1;
+ case PIPE_FORMAT_DXT1_SRGBA:
+ return &_mesa_texformat_srgba_dxt1;
+ case PIPE_FORMAT_DXT3_SRGBA:
+ return &_mesa_texformat_srgba_dxt3;
+ case PIPE_FORMAT_DXT5_SRGBA:
+ return &_mesa_texformat_srgba_dxt5;
+#endif
+#endif
+#if FEATURE_EXT_texture_sRGB
+ case PIPE_FORMAT_A8L8_SRGB:
+ return &_mesa_texformat_sla8;
+ case PIPE_FORMAT_L8_SRGB:
+ return &_mesa_texformat_sl8;
+ case PIPE_FORMAT_R8G8B8_SRGB:
+ return &_mesa_texformat_srgb8;
+ case PIPE_FORMAT_R8G8B8A8_SRGB:
+ return &_mesa_texformat_srgba8;
+ case PIPE_FORMAT_A8R8G8B8_SRGB:
+ return &_mesa_texformat_sargb8;
+#endif
+ /* XXX add additional cases */
+ default:
+ assert(0);
+ return NULL;
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.chooseTextureFormat().
+ */
+const struct gl_texture_format *
+st_ChooseTextureFormat(GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type)
+{
+ enum pipe_format pFormat;
+
+ (void) format;
+ (void) type;
+
+ pFormat = st_choose_format(ctx->st->pipe, internalFormat, PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_USAGE_SAMPLER);
+ if (pFormat == PIPE_FORMAT_NONE)
+ return NULL;
+
+ return translate_gallium_format_to_mesa_format(pFormat);
+}
+
+
+/**
+ * Test if a gallium format is equivalent to a GL format/type.
+ */
+GLboolean
+st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type)
+{
+ switch (pFormat) {
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ return format == GL_RGBA && type == GL_UNSIGNED_BYTE;
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ return format == GL_BGRA && type == GL_UNSIGNED_BYTE;
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ return format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5;
+ /* XXX more combos... */
+ default:
+ return GL_FALSE;
+ }
+}
diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h
new file mode 100644
index 0000000000..9d9e02fe9b
--- /dev/null
+++ b/src/mesa/state_tracker/st_format.h
@@ -0,0 +1,83 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_FORMAT_H
+#define ST_FORMAT_H
+
+
+struct pipe_format_info
+{
+ enum pipe_format format;
+ GLenum base_format;
+ GLenum datatype;
+ GLubyte red_bits;
+ GLubyte green_bits;
+ GLubyte blue_bits;
+ GLubyte alpha_bits;
+ GLubyte luminance_bits;
+ GLubyte intensity_bits;
+ GLubyte depth_bits;
+ GLubyte stencil_bits;
+ GLubyte size; /**< in bytes */
+};
+
+
+GLboolean
+st_get_format_info(enum pipe_format format, struct pipe_format_info *pinfo);
+
+
+extern GLuint
+st_sizeof_format(enum pipe_format format);
+
+
+extern GLenum
+st_format_datatype(enum pipe_format format);
+
+
+extern enum pipe_format
+st_mesa_format_to_pipe_format(GLuint mesaFormat);
+
+
+extern enum pipe_format
+st_choose_format(struct pipe_context *pipe, GLenum internalFormat,
+ enum pipe_texture_target target, unsigned tex_usage);
+
+extern enum pipe_format
+st_choose_renderbuffer_format(struct pipe_context *pipe, GLenum internalFormat);
+
+
+extern const struct gl_texture_format *
+st_ChooseTextureFormat(GLcontext * ctx, GLint internalFormat,
+ GLenum format, GLenum type);
+
+
+extern GLboolean
+st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type);
+
+
+#endif /* ST_CB_TEXIMAGE_H */
diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c
new file mode 100644
index 0000000000..ca32b2e573
--- /dev/null
+++ b/src/mesa/state_tracker/st_framebuffer.c
@@ -0,0 +1,409 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "main/imports.h"
+#include "main/buffers.h"
+#include "main/context.h"
+#include "main/framebuffer.h"
+#include "main/matrix.h"
+#include "main/renderbuffer.h"
+#include "main/scissor.h"
+#include "main/viewport.h"
+#include "st_context.h"
+#include "st_cb_fbo.h"
+#include "st_public.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+
+
+struct st_framebuffer *
+st_create_framebuffer( const __GLcontextModes *visual,
+ enum pipe_format colorFormat,
+ enum pipe_format depthFormat,
+ enum pipe_format stencilFormat,
+ uint width, uint height,
+ void *private)
+{
+ struct st_framebuffer *stfb = ST_CALLOC_STRUCT(st_framebuffer);
+ if (stfb) {
+ int samples = st_get_msaa();
+
+ if (visual->sampleBuffers)
+ samples = visual->samples;
+
+ _mesa_initialize_framebuffer(&stfb->Base, visual);
+
+ if (visual->doubleBufferMode) {
+ struct gl_renderbuffer *rb
+ = st_new_renderbuffer_fb(colorFormat, samples, FALSE);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb);
+ }
+ else {
+ /* Only allocate front buffer right now if we're single buffered.
+ * If double-buffered, allocate front buffer on demand later.
+ * See check_create_front_buffers().
+ */
+ struct gl_renderbuffer *rb
+ = st_new_renderbuffer_fb(colorFormat, samples, FALSE);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb);
+ }
+
+ if (depthFormat == stencilFormat && depthFormat != PIPE_FORMAT_NONE) {
+ /* combined depth/stencil buffer */
+ struct gl_renderbuffer *depthStencilRb
+ = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
+ /* note: bind RB to two attachment points */
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthStencilRb);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, depthStencilRb);
+ }
+ else {
+ /* separate depth and/or stencil */
+
+ if (visual->depthBits == 32) {
+ /* 32-bit depth buffer */
+ struct gl_renderbuffer *depthRb
+ = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
+ }
+ else if (visual->depthBits == 24) {
+ /* 24-bit depth buffer, ignore stencil bits */
+ struct gl_renderbuffer *depthRb
+ = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
+ }
+ else if (visual->depthBits > 0) {
+ /* 16-bit depth buffer */
+ struct gl_renderbuffer *depthRb
+ = st_new_renderbuffer_fb(depthFormat, samples, FALSE);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
+ }
+
+ if (visual->stencilBits > 0) {
+ /* 8-bit stencil */
+ struct gl_renderbuffer *stencilRb
+ = st_new_renderbuffer_fb(stencilFormat, samples, FALSE);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, stencilRb);
+ }
+ }
+
+ if (visual->accumRedBits > 0) {
+ /* 16-bit/channel accum */
+ /* TODO: query the pipe screen for accumulation buffer format support */
+ struct gl_renderbuffer *accumRb
+ = st_new_renderbuffer_fb(PIPE_FORMAT_R16G16B16A16_SNORM, 0, TRUE);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_ACCUM, accumRb);
+ }
+
+ stfb->Base.Initialized = GL_TRUE;
+ stfb->InitWidth = width;
+ stfb->InitHeight = height;
+ stfb->Private = private;
+ }
+ return stfb;
+}
+
+
+void st_resize_framebuffer( struct st_framebuffer *stfb,
+ uint width, uint height )
+{
+ if (stfb->Base.Width != width || stfb->Base.Height != height) {
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx) {
+ _mesa_check_init_viewport(ctx, width, height);
+
+ _mesa_resize_framebuffer(ctx, &stfb->Base, width, height);
+
+ assert(stfb->Base.Width == width);
+ assert(stfb->Base.Height == height);
+ }
+ }
+}
+
+
+void st_unreference_framebuffer( struct st_framebuffer *stfb )
+{
+ _mesa_reference_framebuffer((struct gl_framebuffer **) &stfb, NULL);
+}
+
+
+
+/**
+ * Set/replace a framebuffer surface.
+ * The user of the state tracker can use this instead of
+ * st_resize_framebuffer() to provide new surfaces when a window is resized.
+ */
+void
+st_set_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface *surf)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ static const GLuint invalid_size = 9999999;
+ struct st_renderbuffer *strb;
+ GLuint width, height, i;
+
+ assert(surfIndex < BUFFER_COUNT);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+
+ /* fail */
+ if (!strb) return;
+
+ /* replace the renderbuffer's surface/texture pointers */
+ pipe_surface_reference( &strb->surface, surf );
+ pipe_texture_reference( &strb->texture, surf->texture );
+
+ if (ctx) {
+ /* If ctx isn't set, we've likely not made current yet.
+ * But when we do, we need to start setting this dirty bit
+ * to ensure the renderbuffer attachements are up-to-date
+ * via update_framebuffer.
+ */
+ ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
+ }
+
+ /* update renderbuffer's width/height */
+ strb->Base.Width = surf->width;
+ strb->Base.Height = surf->height;
+
+ /* Try to update the framebuffer's width/height from the renderbuffer
+ * sizes. Before we start drawing, all the rbs _should_ be the same size.
+ */
+ width = height = invalid_size;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (stfb->Base.Attachment[i].Renderbuffer) {
+ if (width == invalid_size) {
+ width = stfb->Base.Attachment[i].Renderbuffer->Width;
+ height = stfb->Base.Attachment[i].Renderbuffer->Height;
+ }
+ else if (width != stfb->Base.Attachment[i].Renderbuffer->Width ||
+ height != stfb->Base.Attachment[i].Renderbuffer->Height) {
+ /* inconsistant renderbuffer sizes, bail out */
+ return;
+ }
+ }
+ }
+
+ if (width != invalid_size) {
+ /* OK, the renderbuffers are of a consistant size, so update the
+ * parent framebuffer's size.
+ */
+ stfb->Base.Width = width;
+ stfb->Base.Height = height;
+ }
+}
+
+
+
+/**
+ * Return the pipe_surface for the given renderbuffer.
+ */
+int
+st_get_framebuffer_surface(struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface)
+{
+ struct st_renderbuffer *strb;
+
+ assert(surfIndex <= ST_SURFACE_DEPTH);
+
+ /* sanity checks, ST tokens should match Mesa tokens */
+ assert(ST_SURFACE_FRONT_LEFT == BUFFER_FRONT_LEFT);
+ assert(ST_SURFACE_BACK_RIGHT == BUFFER_BACK_RIGHT);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+ if (strb) {
+ *surface = strb->surface;
+ return GL_TRUE;
+ }
+
+ *surface = NULL;
+ return GL_FALSE;
+}
+
+int
+st_get_framebuffer_texture(struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture)
+{
+ struct st_renderbuffer *strb;
+
+ assert(surfIndex <= ST_SURFACE_DEPTH);
+
+ /* sanity checks, ST tokens should match Mesa tokens */
+ assert(ST_SURFACE_FRONT_LEFT == BUFFER_FRONT_LEFT);
+ assert(ST_SURFACE_BACK_RIGHT == BUFFER_BACK_RIGHT);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+ if (strb) {
+ *texture = strb->texture;
+ return GL_TRUE;
+ }
+
+ *texture = NULL;
+ return GL_FALSE;
+}
+
+/**
+ * This function is to be called prior to SwapBuffers on the given
+ * framebuffer. It checks if the current context is bound to the framebuffer
+ * and flushes rendering if needed.
+ */
+void
+st_notify_swapbuffers(struct st_framebuffer *stfb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx && ctx->DrawBuffer == &stfb->Base) {
+ st_flush( ctx->st,
+ PIPE_FLUSH_RENDER_CACHE |
+ PIPE_FLUSH_SWAPBUFFERS |
+ PIPE_FLUSH_FRAME,
+ NULL );
+ if (st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer))
+ ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK;
+ }
+}
+
+
+/**
+ * Swap the front/back color buffers. Exchange the front/back pointers
+ * and update some derived state.
+ * No need to call st_notify_swapbuffers() first.
+ *
+ * For a single-buffered framebuffer, no swap occurs, but we still return
+ * the pointer(s) to the front color buffer(s).
+ *
+ * \param front_left returns pointer to front-left renderbuffer after swap
+ * \param front_right returns pointer to front-right renderbuffer after swap
+ */
+void
+st_swapbuffers(struct st_framebuffer *stfb,
+ struct pipe_surface **front_left,
+ struct pipe_surface **front_right)
+{
+ struct gl_framebuffer *fb = &stfb->Base;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx && ctx->DrawBuffer == &stfb->Base) {
+ st_flush( ctx->st,
+ PIPE_FLUSH_RENDER_CACHE |
+ PIPE_FLUSH_SWAPBUFFERS |
+ PIPE_FLUSH_FRAME,
+ NULL );
+ }
+
+ if (!fb->Visual.doubleBufferMode) {
+ /* single buffer mode - return pointers to front surfaces */
+ if (front_left) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ *front_left = strb->surface;
+ }
+ if (front_right) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer);
+ *front_right = strb ? strb->surface : NULL;
+ }
+ return;
+ }
+
+ /* swap left buffers */
+ if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) {
+ struct gl_renderbuffer *rbTemp;
+ rbTemp = fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer =
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer = rbTemp;
+ if (front_left) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ *front_left = strb->surface;
+ }
+ /* mark back buffer contents as undefined */
+ {
+ struct st_renderbuffer *back =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ back->defined = GL_FALSE;
+ }
+ }
+ else {
+ /* no front buffer, display the back buffer */
+ if (front_left) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ *front_left = strb->surface;
+ }
+ }
+
+ /* swap right buffers (for stereo) */
+ if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) {
+ struct gl_renderbuffer *rbTemp;
+ rbTemp = fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer;
+ fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer =
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer;
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer = rbTemp;
+ if (front_right) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer);
+ *front_right = strb->surface;
+ }
+ /* mark back buffer contents as undefined */
+ {
+ struct st_renderbuffer *back =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
+ back->defined = GL_FALSE;
+ }
+ }
+ else {
+ /* no front right buffer, display back right buffer (if exists) */
+ if (front_right) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
+ *front_right = strb ? strb->surface : NULL;
+ }
+ }
+
+ /* Update the _ColorDrawBuffers[] array and _ColorReadBuffer pointer */
+ _mesa_update_framebuffer(ctx);
+
+ /* Make sure we draw into the new back surface */
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
+void *st_framebuffer_private( struct st_framebuffer *stfb )
+{
+ return stfb->Private;
+}
+
+void st_get_framebuffer_dimensions( struct st_framebuffer *stfb,
+ uint *width,
+ uint *height)
+{
+ *width = stfb->Base.Width;
+ *height = stfb->Base.Height;
+}
diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c
new file mode 100644
index 0000000000..58f6933652
--- /dev/null
+++ b/src/mesa/state_tracker/st_gen_mipmap.c
@@ -0,0 +1,214 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "main/imports.h"
+#include "main/mipmap.h"
+#include "main/teximage.h"
+#include "main/texformat.h"
+
+#include "shader/prog_instruction.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_gen_mipmap.h"
+
+#include "cso_cache/cso_cache.h"
+#include "cso_cache/cso_context.h"
+
+#include "st_context.h"
+#include "st_draw.h"
+#include "st_gen_mipmap.h"
+#include "st_program.h"
+#include "st_texture.h"
+#include "st_cb_texture.h"
+#include "st_inlines.h"
+
+
+/**
+ * one-time init for generate mipmap
+ * XXX Note: there may be other times we need no-op/simple state like this.
+ * In that case, some code refactoring would be good.
+ */
+void
+st_init_generate_mipmap(struct st_context *st)
+{
+ st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context);
+}
+
+
+void
+st_destroy_generate_mipmap(struct st_context *st)
+{
+ util_destroy_gen_mipmap(st->gen_mipmap);
+ st->gen_mipmap = NULL;
+}
+
+
+/**
+ * Generate mipmap levels using hardware rendering.
+ * \return TRUE if successful, FALSE if not possible
+ */
+static boolean
+st_render_mipmap(struct st_context *st,
+ GLenum target,
+ struct pipe_texture *pt,
+ uint baseLevel, uint lastLevel)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const uint face = _mesa_tex_target_to_face(target);
+
+ assert(target != GL_TEXTURE_3D); /* not done yet */
+
+ /* check if we can render in the texture's format */
+ if (!screen->is_format_supported(screen, pt->format, pt->target,
+ PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+ return FALSE;
+ }
+
+ util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel,
+ PIPE_TEX_FILTER_LINEAR);
+
+ return TRUE;
+}
+
+
+static void
+fallback_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture *pt = st_get_texobj_texture(texObj);
+ const uint baseLevel = texObj->BaseLevel;
+ const uint lastLevel = pt->last_level;
+ const uint face = _mesa_tex_target_to_face(target), zslice = 0;
+ uint dstLevel;
+ GLenum datatype;
+ GLuint comps;
+
+ assert(target != GL_TEXTURE_3D); /* not done yet */
+
+ _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
+ &datatype, &comps);
+
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ struct pipe_transfer *srcTrans, *dstTrans;
+ const ubyte *srcData;
+ ubyte *dstData;
+ int srcStride, dstStride;
+
+ srcTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face,
+ srcLevel, zslice,
+ PIPE_TRANSFER_READ, 0, 0,
+ pt->width[srcLevel],
+ pt->height[srcLevel]);
+
+ dstTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face,
+ dstLevel, zslice,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ pt->width[dstLevel],
+ pt->height[dstLevel]);
+
+ srcData = (ubyte *) screen->transfer_map(screen, srcTrans);
+ dstData = (ubyte *) screen->transfer_map(screen, dstTrans);
+
+ srcStride = srcTrans->stride / srcTrans->block.size;
+ dstStride = dstTrans->stride / dstTrans->block.size;
+
+ _mesa_generate_mipmap_level(target, datatype, comps,
+ 0 /*border*/,
+ pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel],
+ srcData,
+ srcStride, /* stride in texels */
+ pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel],
+ dstData,
+ dstStride); /* stride in texels */
+
+ screen->transfer_unmap(screen, srcTrans);
+ screen->transfer_unmap(screen, dstTrans);
+
+ screen->tex_transfer_destroy(srcTrans);
+ screen->tex_transfer_destroy(dstTrans);
+ }
+}
+
+
+void
+st_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_texture *pt = st_get_texobj_texture(texObj);
+ const uint baseLevel = texObj->BaseLevel;
+ uint lastLevel;
+ uint dstLevel;
+
+ if (!pt)
+ return;
+
+ lastLevel = pt->last_level;
+
+ if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) {
+ fallback_generate_mipmap(ctx, target, texObj);
+ }
+
+ /* Fill in the Mesa gl_texture_image fields */
+ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
+ const uint srcLevel = dstLevel - 1;
+ const struct gl_texture_image *srcImage
+ = _mesa_get_tex_image(ctx, texObj, target, srcLevel);
+ struct gl_texture_image *dstImage;
+ struct st_texture_image *stImage;
+ uint dstWidth = pt->width[dstLevel];
+ uint dstHeight = pt->height[dstLevel];
+ uint dstDepth = pt->depth[dstLevel];
+ uint border = srcImage->Border;
+
+ dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
+ if (!dstImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
+ return;
+ }
+
+ /* Free old image data */
+ if (dstImage->Data)
+ ctx->Driver.FreeTexImageData(ctx, dstImage);
+
+ /* initialize new image */
+ _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
+ dstDepth, border, srcImage->InternalFormat);
+
+ dstImage->TexFormat = srcImage->TexFormat;
+
+ stImage = (struct st_texture_image *) dstImage;
+ pipe_texture_reference(&stImage->pt, pt);
+ }
+}
diff --git a/src/mesa/state_tracker/st_gen_mipmap.h b/src/mesa/state_tracker/st_gen_mipmap.h
new file mode 100644
index 0000000000..00fbae9302
--- /dev/null
+++ b/src/mesa/state_tracker/st_gen_mipmap.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_GEN_MIPMAP_H
+#define ST_GEN_MIPMAP_H
+
+
+extern void
+st_init_generate_mipmap(struct st_context *st);
+
+
+extern void
+st_destroy_generate_mipmap(struct st_context *st);
+
+
+extern void
+st_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj);
+
+
+#endif /* ST_GEN_MIPMAP_H */
diff --git a/src/mesa/state_tracker/st_inlines.h b/src/mesa/state_tracker/st_inlines.h
new file mode 100644
index 0000000000..a41cfeb96f
--- /dev/null
+++ b/src/mesa/state_tracker/st_inlines.h
@@ -0,0 +1,154 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Functions for checking if buffers/textures are referenced when we need
+ * to read/write from/to them. Flush when needed.
+ */
+
+#ifndef ST_INLINES_H
+#define ST_INLINES_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_state.h"
+
+#include "st_context.h"
+#include "st_texture.h"
+#include "st_public.h"
+
+static INLINE struct pipe_transfer *
+st_cond_flush_get_tex_transfer(struct st_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ unsigned int zslice,
+ enum pipe_transfer_usage usage,
+ unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+
+ st_teximage_flush_before_map(st, pt, face, level, usage);
+ return screen->get_tex_transfer(screen, pt, face, level, zslice, usage,
+ x, y, w, h);
+}
+
+static INLINE struct pipe_transfer *
+st_no_flush_get_tex_transfer(struct st_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ unsigned int zslice,
+ enum pipe_transfer_usage usage,
+ unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+
+ return screen->get_tex_transfer(screen, pt, face, level,
+ zslice, usage, x, y, w, h);
+}
+
+static INLINE void *
+st_cond_flush_pipe_buffer_map(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int map_flags)
+{
+ struct pipe_context *pipe = st->pipe;
+ unsigned int referenced = pipe->is_buffer_referenced(pipe, buf);
+
+ if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
+ (map_flags & PIPE_BUFFER_USAGE_CPU_WRITE)))
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ return pipe_buffer_map(pipe->screen, buf, map_flags);
+}
+
+static INLINE void *
+st_no_flush_pipe_buffer_map(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int map_flags)
+{
+ return pipe_buffer_map(st->pipe->screen, buf, map_flags);
+}
+
+
+static INLINE void
+st_cond_flush_pipe_buffer_write(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ const void * data)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ if (pipe->is_buffer_referenced(pipe, buf))
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ pipe_buffer_write(pipe->screen, buf, offset, size, data);
+}
+
+static INLINE void
+st_no_flush_pipe_buffer_write(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ const void * data)
+{
+ pipe_buffer_write(st->pipe->screen, buf, offset, size, data);
+}
+
+static INLINE void
+st_cond_flush_pipe_buffer_read(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ void * data)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ if (pipe->is_buffer_referenced(pipe, buf) & PIPE_REFERENCED_FOR_WRITE)
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ pipe_buffer_read(pipe->screen, buf, offset, size, data);
+}
+
+static INLINE void
+st_no_flush_pipe_buffer_read(struct st_context *st,
+ struct pipe_buffer *buf,
+ unsigned int offset,
+ unsigned int size,
+ void * data)
+{
+ pipe_buffer_read(st->pipe->screen, buf, offset, size, data);
+}
+
+#endif
+
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
new file mode 100644
index 0000000000..2ab12d3cf3
--- /dev/null
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -0,0 +1,1202 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * \author
+ * Michal Krol
+ */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_build.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_sanity.h"
+#include "st_mesa_to_tgsi.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "util/u_debug.h"
+
+/*
+ * Map mesa register file to TGSI register file.
+ */
+static GLuint
+map_register_file(
+ gl_register_file file,
+ GLuint index,
+ const GLuint immediateMapping[],
+ GLboolean indirectAccess )
+{
+ switch( file ) {
+ case PROGRAM_UNDEFINED:
+ return TGSI_FILE_NULL;
+ case PROGRAM_TEMPORARY:
+ return TGSI_FILE_TEMPORARY;
+ /*case PROGRAM_LOCAL_PARAM:*/
+ /*case PROGRAM_ENV_PARAM:*/
+
+ /* Because of the longstanding problem with mesa arb shaders
+ * where constants, immediates and state variables are all
+ * bundled together as PROGRAM_STATE_VAR, we can't tell from the
+ * mesa register file whether this is a CONSTANT or an
+ * IMMEDIATE, hence we need all the other information.
+ */
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_NAMED_PARAM:
+ case PROGRAM_UNIFORM:
+ if (!indirectAccess && immediateMapping && immediateMapping[index] != ~0)
+ return TGSI_FILE_IMMEDIATE;
+ else
+ return TGSI_FILE_CONSTANT;
+ case PROGRAM_CONSTANT:
+ if (indirectAccess)
+ return TGSI_FILE_CONSTANT;
+ assert(immediateMapping[index] != ~0);
+ return TGSI_FILE_IMMEDIATE;
+ case PROGRAM_INPUT:
+ return TGSI_FILE_INPUT;
+ case PROGRAM_OUTPUT:
+ return TGSI_FILE_OUTPUT;
+ case PROGRAM_ADDRESS:
+ return TGSI_FILE_ADDRESS;
+ default:
+ assert( 0 );
+ return TGSI_FILE_NULL;
+ }
+}
+
+/**
+ * Map mesa register file index to TGSI index.
+ * Take special care when processing input and output indices.
+ * \param file one of TGSI_FILE_x
+ * \param index the mesa register file index
+ * \param inputMapping maps Mesa input indexes to TGSI input indexes
+ * \param outputMapping maps Mesa output indexes to TGSI output indexes
+ */
+static GLuint
+map_register_file_index(
+ GLuint procType,
+ GLuint file,
+ GLuint index,
+ GLuint *swizzle,
+ const GLuint inputMapping[],
+ const GLuint outputMapping[],
+ const GLuint immediateMapping[],
+ GLboolean indirectAccess )
+{
+ switch( file ) {
+ case TGSI_FILE_INPUT:
+ /* inputs are mapped according to the user-defined map */
+ return inputMapping[index];
+
+ case TGSI_FILE_OUTPUT:
+ return outputMapping[index];
+
+ case TGSI_FILE_IMMEDIATE:
+ if (indirectAccess)
+ return index;
+ assert(immediateMapping[index] != ~0);
+ return immediateMapping[index];
+
+ default:
+ return index;
+ }
+}
+
+/*
+ * Map mesa texture target to TGSI texture target.
+ */
+static GLuint
+map_texture_target(
+ GLuint textarget,
+ GLboolean shadow )
+{
+ switch( textarget ) {
+ case TEXTURE_1D_INDEX:
+ if (shadow)
+ return TGSI_TEXTURE_SHADOW1D;
+ else
+ return TGSI_TEXTURE_1D;
+ case TEXTURE_2D_INDEX:
+ if (shadow)
+ return TGSI_TEXTURE_SHADOW2D;
+ else
+ return TGSI_TEXTURE_2D;
+ case TEXTURE_3D_INDEX:
+ return TGSI_TEXTURE_3D;
+ case TEXTURE_CUBE_INDEX:
+ return TGSI_TEXTURE_CUBE;
+ case TEXTURE_RECT_INDEX:
+ if (shadow)
+ return TGSI_TEXTURE_SHADOWRECT;
+ else
+ return TGSI_TEXTURE_RECT;
+ default:
+ assert( 0 );
+ }
+
+ return TGSI_TEXTURE_1D;
+}
+
+static GLuint
+convert_sat(
+ GLuint sat )
+{
+ switch( sat ) {
+ case SATURATE_OFF:
+ return TGSI_SAT_NONE;
+ case SATURATE_ZERO_ONE:
+ return TGSI_SAT_ZERO_ONE;
+ case SATURATE_PLUS_MINUS_ONE:
+ return TGSI_SAT_MINUS_PLUS_ONE;
+ default:
+ assert( 0 );
+ return TGSI_SAT_NONE;
+ }
+}
+
+static GLuint
+convert_writemask(
+ GLuint writemask )
+{
+ assert( WRITEMASK_X == TGSI_WRITEMASK_X );
+ assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );
+ assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );
+ assert( WRITEMASK_W == TGSI_WRITEMASK_W );
+ assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );
+
+ return writemask;
+}
+
+static struct tgsi_full_immediate
+make_immediate(const float *value, uint size)
+{
+ struct tgsi_full_immediate imm;
+ unsigned i;
+
+ imm = tgsi_default_full_immediate();
+ imm.Immediate.NrTokens += size;
+ imm.Immediate.DataType = TGSI_IMM_FLOAT32;
+
+ for (i = 0; i < size; i++)
+ imm.u[i].Float = value[i];
+
+ return imm;
+}
+
+static void
+compile_instruction(
+ const struct prog_instruction *inst,
+ struct tgsi_full_instruction *fullinst,
+ const GLuint inputMapping[],
+ const GLuint outputMapping[],
+ const GLuint immediateMapping[],
+ GLboolean indirectAccess,
+ GLuint preamble_size,
+ GLuint procType,
+ GLboolean *insideSubroutine,
+ GLint wposTemp)
+{
+ GLuint i;
+ struct tgsi_full_dst_register *fulldst;
+ struct tgsi_full_src_register *fullsrc;
+
+ *fullinst = tgsi_default_full_instruction();
+
+ fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );
+ fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode );
+ fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
+
+ fulldst = &fullinst->FullDstRegisters[0];
+ fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL, GL_FALSE );
+ fulldst->DstRegister.Index = map_register_file_index(
+ procType,
+ fulldst->DstRegister.File,
+ inst->DstReg.Index,
+ NULL,
+ inputMapping,
+ outputMapping,
+ NULL,
+ GL_FALSE );
+ fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
+ if (inst->DstReg.RelAddr) {
+ fulldst->DstRegister.Indirect = 1;
+ fulldst->DstRegisterInd.File = TGSI_FILE_ADDRESS;
+ fulldst->DstRegisterInd.Index = 0;
+ }
+
+ for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
+ GLuint j;
+ GLuint swizzle = inst->SrcReg[i].Swizzle;
+
+ fullsrc = &fullinst->FullSrcRegisters[i];
+
+ if (procType == TGSI_PROCESSOR_FRAGMENT &&
+ inst->SrcReg[i].File == PROGRAM_INPUT &&
+ inst->SrcReg[i].Index == FRAG_ATTRIB_WPOS) {
+ /* special case of INPUT[WPOS] */
+ fullsrc->SrcRegister.File = TGSI_FILE_TEMPORARY;
+ fullsrc->SrcRegister.Index = wposTemp;
+ }
+ else {
+ /* any other src register */
+ fullsrc->SrcRegister.File = map_register_file(
+ inst->SrcReg[i].File,
+ inst->SrcReg[i].Index,
+ immediateMapping,
+ indirectAccess );
+ fullsrc->SrcRegister.Index = map_register_file_index(
+ procType,
+ fullsrc->SrcRegister.File,
+ inst->SrcReg[i].Index,
+ &swizzle,
+ inputMapping,
+ outputMapping,
+ immediateMapping,
+ indirectAccess );
+ }
+
+ /* swizzle (ext swizzle also depends on negation) */
+ {
+ GLuint swz[4];
+ GLboolean extended = (inst->SrcReg[i].Negate != NEGATE_NONE &&
+ inst->SrcReg[i].Negate != NEGATE_XYZW);
+ for( j = 0; j < 4; j++ ) {
+ swz[j] = GET_SWZ( swizzle, j );
+ if (swz[j] > SWIZZLE_W)
+ extended = GL_TRUE;
+ }
+ if (extended) {
+ for (j = 0; j < 4; j++) {
+ tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz,
+ swz[j], j);
+ }
+ }
+ else {
+ for (j = 0; j < 4; j++) {
+ tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister,
+ swz[j], j);
+ }
+ }
+ }
+
+ if( inst->SrcReg[i].Negate == NEGATE_XYZW ) {
+ fullsrc->SrcRegister.Negate = 1;
+ }
+ else if( inst->SrcReg[i].Negate != NEGATE_NONE ) {
+ if( inst->SrcReg[i].Negate & NEGATE_X ) {
+ fullsrc->SrcRegisterExtSwz.NegateX = 1;
+ }
+ if( inst->SrcReg[i].Negate & NEGATE_Y ) {
+ fullsrc->SrcRegisterExtSwz.NegateY = 1;
+ }
+ if( inst->SrcReg[i].Negate & NEGATE_Z ) {
+ fullsrc->SrcRegisterExtSwz.NegateZ = 1;
+ }
+ if( inst->SrcReg[i].Negate & NEGATE_W ) {
+ fullsrc->SrcRegisterExtSwz.NegateW = 1;
+ }
+ }
+
+ if( inst->SrcReg[i].Abs ) {
+ fullsrc->SrcRegisterExtMod.Absolute = 1;
+ }
+
+ if( inst->SrcReg[i].RelAddr ) {
+ fullsrc->SrcRegister.Indirect = 1;
+
+ fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;
+ fullsrc->SrcRegisterInd.Index = 0;
+ }
+ }
+
+ switch( inst->Opcode ) {
+ case OPCODE_ARL:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;
+ break;
+ case OPCODE_ABS:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;
+ break;
+ case OPCODE_ADD:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;
+ break;
+ case OPCODE_BGNLOOP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_BGNSUB:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
+ *insideSubroutine = GL_TRUE;
+ break;
+ case OPCODE_BRA:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_BRA;
+ break;
+ case OPCODE_BRK:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_BRK;
+ break;
+ case OPCODE_CAL:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_CAL;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_CMP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;
+ break;
+ case OPCODE_CONT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_CONT;
+ break;
+ case OPCODE_COS:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_COS;
+ break;
+ case OPCODE_DDX:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;
+ break;
+ case OPCODE_DDY:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;
+ break;
+ case OPCODE_DP2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP2;
+ break;
+ case OPCODE_DP2A:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP2A;
+ break;
+ case OPCODE_DP3:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
+ break;
+ case OPCODE_DP4:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
+ break;
+ case OPCODE_DPH:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
+ break;
+ case OPCODE_DST:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
+ break;
+ case OPCODE_ELSE:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_ENDIF:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF;
+ break;
+ case OPCODE_ENDLOOP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_ENDSUB:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
+ *insideSubroutine = GL_FALSE;
+ break;
+ case OPCODE_EX2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
+ break;
+ case OPCODE_EXP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_EXP;
+ break;
+ case OPCODE_FLR:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
+ break;
+ case OPCODE_FRC:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
+ break;
+ case OPCODE_IF:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_IF;
+ fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
+ break;
+ case OPCODE_TRUNC:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TRUNC;
+ break;
+ case OPCODE_KIL:
+ /* conditional */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
+ break;
+ case OPCODE_KIL_NV:
+ /* predicated */
+ assert(inst->DstReg.CondMask == COND_TR);
+ fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
+ break;
+ case OPCODE_LG2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
+ break;
+ case OPCODE_LOG:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LOG;
+ break;
+ case OPCODE_LIT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
+ break;
+ case OPCODE_LRP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
+ break;
+ case OPCODE_MAD:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
+ break;
+ case OPCODE_MAX:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
+ break;
+ case OPCODE_MIN:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
+ break;
+ case OPCODE_MOV:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
+ break;
+ case OPCODE_MUL:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
+ break;
+ case OPCODE_NOISE1:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1;
+ break;
+ case OPCODE_NOISE2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2;
+ break;
+ case OPCODE_NOISE3:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3;
+ break;
+ case OPCODE_NOISE4:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4;
+ break;
+ case OPCODE_NOP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NOP;
+ break;
+ case OPCODE_NRM3:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NRM;
+ break;
+ case OPCODE_NRM4:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_NRM4;
+ break;
+ case OPCODE_POW:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
+ break;
+ case OPCODE_RCP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
+ break;
+ case OPCODE_RET:
+ /* If RET is used inside main (not a real subroutine) we may want
+ * to execute END instead of RET. TBD...
+ */
+ if (1 /* *insideSubroutine */) {
+ fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
+ }
+ else {
+ /* inside main() pseudo-function */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_END;
+ }
+ break;
+ case OPCODE_RSQ:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
+ break;
+ case OPCODE_SCS:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
+ fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
+ break;
+ case OPCODE_SEQ:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ;
+ break;
+ case OPCODE_SGE:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
+ break;
+ case OPCODE_SGT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SGT;
+ break;
+ case OPCODE_SIN:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
+ break;
+ case OPCODE_SLE:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SLE;
+ break;
+ case OPCODE_SLT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
+ break;
+ case OPCODE_SNE:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SNE;
+ break;
+ case OPCODE_SSG:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SSG;
+ break;
+ case OPCODE_SUB:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
+ break;
+ case OPCODE_SWZ:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
+ break;
+ case OPCODE_TEX:
+ /* ordinary texture lookup */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture =
+ map_texture_target( inst->TexSrcTarget, inst->TexShadow );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXB:
+ /* texture lookup with LOD bias */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture =
+ map_texture_target( inst->TexSrcTarget, inst->TexShadow );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXD:
+ /* texture lookup with explicit partial derivatives */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXD;
+ fullinst->Instruction.NumSrcRegs = 4;
+ fullinst->InstructionExtTexture.Texture =
+ map_texture_target( inst->TexSrcTarget, inst->TexShadow );
+ /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */
+ fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXL:
+ /* texture lookup with explicit LOD */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXL;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture =
+ map_texture_target( inst->TexSrcTarget, inst->TexShadow );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXP:
+ /* texture lookup with divide by Q component */
+ /* convert to TEX w/ special flag for division */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture =
+ map_texture_target( inst->TexSrcTarget, inst->TexShadow );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_XPD:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
+ fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
+ break;
+ case OPCODE_END:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_END;
+ break;
+ default:
+ assert( 0 );
+ }
+}
+
+/**
+ * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
+ */
+static struct tgsi_full_declaration
+make_input_decl(
+ GLuint index,
+ GLboolean interpolate_info,
+ GLuint interpolate,
+ GLuint usage_mask,
+ GLboolean semantic_info,
+ GLuint semantic_name,
+ GLbitfield semantic_index,
+ GLbitfield input_flags)
+{
+ struct tgsi_full_declaration decl;
+
+ assert(semantic_name < TGSI_SEMANTIC_COUNT);
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ decl.Declaration.UsageMask = usage_mask;
+ decl.Declaration.Semantic = semantic_info;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
+ if (semantic_info) {
+ decl.Semantic.SemanticName = semantic_name;
+ decl.Semantic.SemanticIndex = semantic_index;
+ }
+ if (interpolate_info) {
+ decl.Declaration.Interpolate = interpolate;
+ }
+ if (input_flags & PROG_PARAM_BIT_CENTROID)
+ decl.Declaration.Centroid = 1;
+ if (input_flags & PROG_PARAM_BIT_INVARIANT)
+ decl.Declaration.Invariant = 1;
+
+ return decl;
+}
+
+/**
+ * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
+ */
+static struct tgsi_full_declaration
+make_output_decl(
+ GLuint index,
+ GLuint semantic_name,
+ GLuint semantic_index,
+ GLuint usage_mask,
+ GLbitfield output_flags)
+{
+ struct tgsi_full_declaration decl;
+
+ assert(semantic_name < TGSI_SEMANTIC_COUNT);
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_OUTPUT;
+ decl.Declaration.UsageMask = usage_mask;
+ decl.Declaration.Semantic = 1;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
+ decl.Semantic.SemanticName = semantic_name;
+ decl.Semantic.SemanticIndex = semantic_index;
+ if (output_flags & PROG_PARAM_BIT_CENTROID)
+ decl.Declaration.Centroid = 1;
+ if (output_flags & PROG_PARAM_BIT_INVARIANT)
+ decl.Declaration.Invariant = 1;
+
+ return decl;
+}
+
+
+static struct tgsi_full_declaration
+make_temp_decl(
+ GLuint start_index,
+ GLuint end_index )
+{
+ struct tgsi_full_declaration decl;
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ decl.DeclarationRange.First = start_index;
+ decl.DeclarationRange.Last = end_index;
+ return decl;
+}
+
+static struct tgsi_full_declaration
+make_addr_decl(
+ GLuint start_index,
+ GLuint end_index )
+{
+ struct tgsi_full_declaration decl;
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_ADDRESS;
+ decl.DeclarationRange.First = start_index;
+ decl.DeclarationRange.Last = end_index;
+ return decl;
+}
+
+static struct tgsi_full_declaration
+make_sampler_decl(GLuint index)
+{
+ struct tgsi_full_declaration decl;
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
+ return decl;
+}
+
+/** Reference into a constant buffer */
+static struct tgsi_full_declaration
+make_constant_decl(GLuint first, GLuint last)
+{
+ struct tgsi_full_declaration decl;
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_CONSTANT;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
+ return decl;
+}
+
+
+
+/**
+ * Find the temporaries which are used in the given program.
+ */
+static void
+find_temporaries(const struct gl_program *program,
+ GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
+{
+ GLuint i, j;
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++)
+ tempsUsed[i] = GL_FALSE;
+
+ for (i = 0; i < program->NumInstructions; i++) {
+ const struct prog_instruction *inst = program->Instructions + i;
+ const GLuint n = _mesa_num_inst_src_regs( inst->Opcode );
+ for (j = 0; j < n; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
+ tempsUsed[inst->SrcReg[j].Index] = GL_TRUE;
+ if (inst->DstReg.File == PROGRAM_TEMPORARY)
+ tempsUsed[inst->DstReg.Index] = GL_TRUE;
+ }
+ }
+}
+
+
+/**
+ * Find an unused temporary in the tempsUsed array.
+ */
+static int
+find_free_temporary(GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
+{
+ int i;
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (!tempsUsed[i]) {
+ tempsUsed[i] = GL_TRUE;
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/** helper for building simple TGSI instruction, one src register */
+static void
+build_tgsi_instruction1(struct tgsi_full_instruction *inst,
+ int opcode,
+ int dstFile, int dstIndex, int writemask,
+ int srcFile1, int srcIndex1)
+{
+ *inst = tgsi_default_full_instruction();
+
+ inst->Instruction.Opcode = opcode;
+
+ inst->Instruction.NumDstRegs = 1;
+ inst->FullDstRegisters[0].DstRegister.File = dstFile;
+ inst->FullDstRegisters[0].DstRegister.Index = dstIndex;
+ inst->FullDstRegisters[0].DstRegister.WriteMask = writemask;
+
+ inst->Instruction.NumSrcRegs = 1;
+ inst->FullSrcRegisters[0].SrcRegister.File = srcFile1;
+ inst->FullSrcRegisters[0].SrcRegister.Index = srcIndex1;
+}
+
+
+/** helper for building simple TGSI instruction, two src registers */
+static void
+build_tgsi_instruction2(struct tgsi_full_instruction *inst,
+ int opcode,
+ int dstFile, int dstIndex, int writemask,
+ int srcFile1, int srcIndex1,
+ int srcFile2, int srcIndex2)
+{
+ *inst = tgsi_default_full_instruction();
+
+ inst->Instruction.Opcode = opcode;
+
+ inst->Instruction.NumDstRegs = 1;
+ inst->FullDstRegisters[0].DstRegister.File = dstFile;
+ inst->FullDstRegisters[0].DstRegister.Index = dstIndex;
+ inst->FullDstRegisters[0].DstRegister.WriteMask = writemask;
+
+ inst->Instruction.NumSrcRegs = 2;
+ inst->FullSrcRegisters[0].SrcRegister.File = srcFile1;
+ inst->FullSrcRegisters[0].SrcRegister.Index = srcIndex1;
+ inst->FullSrcRegisters[1].SrcRegister.File = srcFile2;
+ inst->FullSrcRegisters[1].SrcRegister.Index = srcIndex2;
+}
+
+
+
+/**
+ * Emit the TGSI instructions for inverting the WPOS y coordinate.
+ */
+static int
+emit_inverted_wpos(struct tgsi_token *tokens,
+ int wpos_temp,
+ int winsize_const,
+ int wpos_input,
+ struct tgsi_header *header, int maxTokens)
+{
+ struct tgsi_full_instruction fullinst;
+ int ti = 0;
+
+ /* MOV wpos_temp.xzw, input[wpos]; */
+ build_tgsi_instruction1(&fullinst,
+ TGSI_OPCODE_MOV,
+ TGSI_FILE_TEMPORARY, wpos_temp, WRITEMASK_XZW,
+ TGSI_FILE_INPUT, 0);
+
+ ti += tgsi_build_full_instruction(&fullinst,
+ &tokens[ti],
+ header,
+ maxTokens - ti);
+
+ /* SUB wpos_temp.y, const[winsize_const] - input[wpos_input]; */
+ build_tgsi_instruction2(&fullinst,
+ TGSI_OPCODE_SUB,
+ TGSI_FILE_TEMPORARY, wpos_temp, WRITEMASK_Y,
+ TGSI_FILE_CONSTANT, winsize_const,
+ TGSI_FILE_INPUT, wpos_input);
+
+ ti += tgsi_build_full_instruction(&fullinst,
+ &tokens[ti],
+ header,
+ maxTokens - ti);
+
+ return ti;
+}
+
+
+
+
+/**
+ * Translate Mesa program to TGSI format.
+ * \param program the program to translate
+ * \param numInputs number of input registers used
+ * \param inputMapping maps Mesa fragment program inputs to TGSI generic
+ * input indexes
+ * \param inputSemanticName the TGSI_SEMANTIC flag for each input
+ * \param inputSemanticIndex the semantic index (ex: which texcoord) for each input
+ * \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
+
+ * \param numOutputs number of output registers used
+ * \param outputMapping maps Mesa fragment program outputs to TGSI
+ * generic outputs
+ * \param outputSemanticName the TGSI_SEMANTIC flag for each output
+ * \param outputSemanticIndex the semantic index (ex: which texcoord) for each output
+ * \param tokens array to store translated tokens in
+ * \param maxTokens size of the tokens array
+ *
+ * \return number of tokens placed in 'tokens' buffer, or zero if error
+ */
+GLuint
+st_translate_mesa_program(
+ GLcontext *ctx,
+ uint procType,
+ const struct gl_program *program,
+ GLuint numInputs,
+ const GLuint inputMapping[],
+ const ubyte inputSemanticName[],
+ const ubyte inputSemanticIndex[],
+ const GLuint interpMode[],
+ const GLbitfield inputFlags[],
+ GLuint numOutputs,
+ const GLuint outputMapping[],
+ const ubyte outputSemanticName[],
+ const ubyte outputSemanticIndex[],
+ const GLbitfield outputFlags[],
+ struct tgsi_token *tokens,
+ GLuint maxTokens )
+{
+ GLuint i;
+ GLuint ti; /* token index */
+ struct tgsi_header *header;
+ struct tgsi_processor *processor;
+ GLuint preamble_size = 0;
+ GLuint immediates[1000];
+ GLuint numImmediates = 0;
+ GLboolean insideSubroutine = GL_FALSE;
+ GLboolean indirectAccess = GL_FALSE;
+ GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
+ GLint wposTemp = -1, winHeightConst = -1;
+
+ assert(procType == TGSI_PROCESSOR_FRAGMENT ||
+ procType == TGSI_PROCESSOR_VERTEX);
+
+ find_temporaries(program, tempsUsed);
+
+ if (procType == TGSI_PROCESSOR_FRAGMENT) {
+ if (program->InputsRead & FRAG_BIT_WPOS) {
+ /* Fragment program uses fragment position input.
+ * Need to replace instances of INPUT[WPOS] with temp T
+ * where T = INPUT[WPOS] by y is inverted.
+ */
+ static const gl_state_index winSizeState[STATE_LENGTH]
+ = { STATE_INTERNAL, STATE_FB_SIZE, 0, 0, 0 };
+ winHeightConst = _mesa_add_state_reference(program->Parameters,
+ winSizeState);
+ wposTemp = find_free_temporary(tempsUsed);
+ }
+ }
+
+
+ *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
+
+ header = (struct tgsi_header *) &tokens[1];
+ *header = tgsi_build_header();
+
+ processor = (struct tgsi_processor *) &tokens[2];
+ *processor = tgsi_build_processor( procType, header );
+
+ ti = 3;
+
+ /*
+ * Declare input attributes.
+ */
+ if (procType == TGSI_PROCESSOR_FRAGMENT) {
+ for (i = 0; i < numInputs; i++) {
+ struct tgsi_full_declaration fulldecl;
+ fulldecl = make_input_decl(i,
+ GL_TRUE, interpMode[i],
+ TGSI_WRITEMASK_XYZW,
+ GL_TRUE, inputSemanticName[i],
+ inputSemanticIndex[i],
+ inputFlags[i]);
+ ti += tgsi_build_full_declaration(&fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+ else {
+ /* vertex prog */
+ /* XXX: this could probaby be merged with the clause above.
+ * the only difference is the semantic tags.
+ */
+ for (i = 0; i < numInputs; i++) {
+ struct tgsi_full_declaration fulldecl;
+ fulldecl = make_input_decl(i,
+ GL_FALSE, 0,
+ TGSI_WRITEMASK_XYZW,
+ GL_FALSE, 0, 0,
+ inputFlags[i]);
+ ti += tgsi_build_full_declaration(&fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+
+ /*
+ * Declare output attributes.
+ */
+ if (procType == TGSI_PROCESSOR_FRAGMENT) {
+ for (i = 0; i < numOutputs; i++) {
+ struct tgsi_full_declaration fulldecl;
+ switch (outputSemanticName[i]) {
+ case TGSI_SEMANTIC_POSITION:
+ fulldecl = make_output_decl(i,
+ TGSI_SEMANTIC_POSITION, /* Z / Depth */
+ outputSemanticIndex[i],
+ TGSI_WRITEMASK_Z,
+ outputFlags[i]);
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ fulldecl = make_output_decl(i,
+ TGSI_SEMANTIC_COLOR,
+ outputSemanticIndex[i],
+ TGSI_WRITEMASK_XYZW,
+ outputFlags[i]);
+ break;
+ default:
+ assert(0);
+ return 0;
+ }
+ ti += tgsi_build_full_declaration(&fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+ else {
+ /* vertex prog */
+ for (i = 0; i < numOutputs; i++) {
+ struct tgsi_full_declaration fulldecl;
+ fulldecl = make_output_decl(i,
+ outputSemanticName[i],
+ outputSemanticIndex[i],
+ TGSI_WRITEMASK_XYZW,
+ outputFlags[i]);
+ ti += tgsi_build_full_declaration(&fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+
+ /* temporary decls */
+ {
+ GLboolean inside_range = GL_FALSE;
+ GLuint start_range = 0;
+
+ tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
+ for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
+ if (tempsUsed[i] && !inside_range) {
+ inside_range = GL_TRUE;
+ start_range = i;
+ }
+ else if (!tempsUsed[i] && inside_range) {
+ struct tgsi_full_declaration fulldecl;
+
+ inside_range = GL_FALSE;
+ fulldecl = make_temp_decl( start_range, i - 1 );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+ }
+
+ /* Declare address register.
+ */
+ if (program->NumAddressRegs > 0) {
+ struct tgsi_full_declaration fulldecl;
+
+ assert( program->NumAddressRegs == 1 );
+
+ fulldecl = make_addr_decl( 0, 0 );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+ indirectAccess = GL_TRUE;
+ }
+
+ /* immediates/literals */
+ memset(immediates, ~0, sizeof(immediates));
+
+ /* Emit immediates only when there is no address register in use.
+ * FIXME: Be smarter and recognize param arrays -- indirect addressing is
+ * only valid within the referenced array.
+ */
+ if (program->Parameters && !indirectAccess) {
+ for (i = 0; i < program->Parameters->NumParameters; i++) {
+ if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
+ struct tgsi_full_immediate fullimm;
+
+ fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 );
+ ti += tgsi_build_full_immediate(
+ &fullimm,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ immediates[i] = numImmediates;
+ numImmediates++;
+ }
+ }
+ }
+
+ /* constant buffer refs */
+ if (program->Parameters) {
+ GLint start = -1, end = -1;
+
+ for (i = 0; i < program->Parameters->NumParameters; i++) {
+ GLboolean emit = (i == program->Parameters->NumParameters - 1);
+ GLboolean matches;
+
+ switch (program->Parameters->Parameters[i].Type) {
+ case PROGRAM_ENV_PARAM:
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_NAMED_PARAM:
+ case PROGRAM_UNIFORM:
+ matches = GL_TRUE;
+ break;
+ case PROGRAM_CONSTANT:
+ matches = indirectAccess;
+ break;
+ default:
+ matches = GL_FALSE;
+ }
+
+ if (matches) {
+ if (start == -1) {
+ /* begin a sequence */
+ start = i;
+ end = i;
+ }
+ else {
+ /* continue sequence */
+ end = i;
+ }
+ }
+ else {
+ if (start != -1) {
+ /* end of sequence */
+ emit = GL_TRUE;
+ }
+ }
+
+ if (emit && start >= 0) {
+ struct tgsi_full_declaration fulldecl;
+
+ fulldecl = make_constant_decl( start, end );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ start = end = -1;
+ }
+ }
+ }
+
+ /* texture samplers */
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (program->SamplersUsed & (1 << i)) {
+ struct tgsi_full_declaration fulldecl;
+
+ fulldecl = make_sampler_decl( i );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+ }
+
+ /* invert WPOS fragment input */
+ if (wposTemp >= 0) {
+ ti += emit_inverted_wpos(&tokens[ti], wposTemp, winHeightConst,
+ inputMapping[FRAG_ATTRIB_WPOS],
+ header, maxTokens - ti);
+ preamble_size = 2; /* two instructions added */
+ }
+
+ for (i = 0; i < program->NumInstructions; i++) {
+ struct tgsi_full_instruction fullinst;
+
+ compile_instruction(
+ &program->Instructions[i],
+ &fullinst,
+ inputMapping,
+ outputMapping,
+ immediates,
+ indirectAccess,
+ preamble_size,
+ procType,
+ &insideSubroutine,
+ wposTemp);
+
+ ti += tgsi_build_full_instruction(
+ &fullinst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+
+#if DEBUG
+ if(!tgsi_sanity_check(tokens)) {
+ debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
+ debug_printf("\nOriginal program:\n%s", program->String);
+ debug_printf("\nMesa program:\n");
+ _mesa_print_program(program);
+ debug_printf("\nTGSI program:\n");
+ tgsi_dump(tokens, 0);
+ assert(0);
+ }
+#endif
+
+ return ti;
+}
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.h b/src/mesa/state_tracker/st_mesa_to_tgsi.h
new file mode 100644
index 0000000000..b465b3bddc
--- /dev/null
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_MESA_TO_TGSI_H
+#define ST_MESA_TO_TGSI_H
+
+#include "main/mtypes.h"
+
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct tgsi_token;
+struct gl_program;
+
+GLuint
+st_translate_mesa_program(
+ GLcontext *ctx,
+ uint procType,
+ const struct gl_program *program,
+ GLuint numInputs,
+ const GLuint inputMapping[],
+ const ubyte inputSemanticName[],
+ const ubyte inputSemanticIndex[],
+ const GLuint interpMode[],
+ const GLbitfield inputFlags[],
+ GLuint numOutputs,
+ const GLuint outputMapping[],
+ const ubyte outputSemanticName[],
+ const ubyte outputSemanticIndex[],
+ const GLbitfield outputFlags[],
+ struct tgsi_token *tokens,
+ GLuint maxTokens );
+
+
+#if defined __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ST_MESA_TO_TGSI_H */
+
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
new file mode 100644
index 0000000000..d2da20ae42
--- /dev/null
+++ b/src/mesa/state_tracker/st_program.c
@@ -0,0 +1,597 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "shader/prog_print.h"
+#include "shader/programopt.h"
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw/draw_context.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_program.h"
+#include "st_mesa_to_tgsi.h"
+#include "cso_cache/cso_context.h"
+
+
+#define ST_MAX_SHADER_TOKENS (8 * 1024)
+
+
+#define TGSI_DEBUG 0
+
+
+/**
+ * Translate a Mesa vertex shader into a TGSI shader.
+ * \param outputMapping to map vertex program output registers (VERT_RESULT_x)
+ * to TGSI output slots
+ * \param tokensOut destination for TGSI tokens
+ * \return pointer to cached pipe_shader object.
+ */
+void
+st_translate_vertex_program(struct st_context *st,
+ struct st_vertex_program *stvp,
+ const GLuint outputMapping[],
+ const ubyte *outputSemanticName,
+ const ubyte *outputSemanticIndex)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct tgsi_token *tokens;
+ GLuint defaultOutputMapping[VERT_RESULT_MAX];
+ struct pipe_shader_state vs;
+ GLuint attr, i;
+ GLuint num_generic = 0;
+ GLuint num_tokens;
+
+ ubyte vs_input_semantic_name[PIPE_MAX_SHADER_INPUTS];
+ ubyte vs_input_semantic_index[PIPE_MAX_SHADER_INPUTS];
+ uint vs_num_inputs = 0;
+
+ ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
+ ubyte vs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
+ uint vs_num_outputs = 0;
+
+ GLbitfield input_flags[MAX_PROGRAM_INPUTS];
+ GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
+
+ tokens = (struct tgsi_token *)MALLOC(ST_MAX_SHADER_TOKENS * sizeof *tokens);
+ if(!tokens) {
+ /* FIXME: propagate error to the caller */
+ assert(0);
+ return;
+ }
+
+ memset(&vs, 0, sizeof(vs));
+ memset(input_flags, 0, sizeof(input_flags));
+ memset(output_flags, 0, sizeof(output_flags));
+
+ if (stvp->Base.IsPositionInvariant)
+ _mesa_insert_mvp_code(st->ctx, &stvp->Base);
+
+ /*
+ * Determine number of inputs, the mappings between VERT_ATTRIB_x
+ * and TGSI generic input indexes, plus input attrib semantic info.
+ */
+ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+ if (stvp->Base.Base.InputsRead & (1 << attr)) {
+ const GLuint slot = vs_num_inputs;
+
+ vs_num_inputs++;
+
+ stvp->input_to_index[attr] = slot;
+ stvp->index_to_input[slot] = attr;
+
+ switch (attr) {
+ case VERT_ATTRIB_POS:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_WEIGHT:
+ /* fall-through */
+ case VERT_ATTRIB_NORMAL:
+ /* just label as a generic */
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_COLOR0:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_COLOR1:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs_input_semantic_index[slot] = 1;
+ break;
+ case VERT_ATTRIB_FOG:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_POINT_SIZE:
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+ vs_input_semantic_index[slot] = 0;
+ break;
+ case VERT_ATTRIB_TEX0:
+ case VERT_ATTRIB_TEX1:
+ case VERT_ATTRIB_TEX2:
+ case VERT_ATTRIB_TEX3:
+ case VERT_ATTRIB_TEX4:
+ case VERT_ATTRIB_TEX5:
+ case VERT_ATTRIB_TEX6:
+ case VERT_ATTRIB_TEX7:
+ assert(slot < Elements(vs_input_semantic_name));
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs_input_semantic_index[slot] = num_generic++;
+ break;
+ case VERT_ATTRIB_GENERIC0:
+ case VERT_ATTRIB_GENERIC1:
+ case VERT_ATTRIB_GENERIC2:
+ case VERT_ATTRIB_GENERIC3:
+ case VERT_ATTRIB_GENERIC4:
+ case VERT_ATTRIB_GENERIC5:
+ case VERT_ATTRIB_GENERIC6:
+ case VERT_ATTRIB_GENERIC7:
+ case VERT_ATTRIB_GENERIC8:
+ case VERT_ATTRIB_GENERIC9:
+ case VERT_ATTRIB_GENERIC10:
+ case VERT_ATTRIB_GENERIC11:
+ case VERT_ATTRIB_GENERIC12:
+ case VERT_ATTRIB_GENERIC13:
+ case VERT_ATTRIB_GENERIC14:
+ case VERT_ATTRIB_GENERIC15:
+ assert(attr < VERT_ATTRIB_MAX);
+ assert(slot < Elements(vs_input_semantic_name));
+ vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs_input_semantic_index[slot] = num_generic++;
+ break;
+ default:
+ assert(0);
+ }
+
+ input_flags[slot] = stvp->Base.Base.InputFlags[attr];
+ }
+ }
+
+#if 0
+ if (outputMapping && outputSemanticName) {
+ printf("VERT_RESULT written out_slot semantic_name semantic_index\n");
+ for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+ printf(" %-2d %c %3d %2d %2d\n",
+ attr,
+ ((stvp->Base.Base.OutputsWritten & (1 << attr)) ? 'Y' : ' '),
+ outputMapping[attr],
+ outputSemanticName[attr],
+ outputSemanticIndex[attr]);
+ }
+ }
+#endif
+
+ /* initialize output semantics to defaults */
+ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
+ assert(i < Elements(vs_output_semantic_name));
+ vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
+ vs_output_semantic_index[i] = 0;
+ output_flags[i] = 0x0;
+ }
+
+ num_generic = 0;
+ /*
+ * Determine number of outputs, the (default) output register
+ * mapping and the semantic information for each output.
+ */
+ for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+ if (stvp->Base.Base.OutputsWritten & (1 << attr)) {
+ GLuint slot;
+
+ /* XXX
+ * Pass in the fragment program's input's semantic info.
+ * Use the generic semantic indexes from there, instead of
+ * guessing below.
+ */
+
+ if (outputMapping) {
+ slot = outputMapping[attr];
+ assert(slot != ~0);
+ }
+ else {
+ slot = vs_num_outputs;
+ vs_num_outputs++;
+ defaultOutputMapping[attr] = slot;
+ }
+
+ switch (attr) {
+ case VERT_RESULT_HPOS:
+ assert(slot == 0);
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_COL0:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_COL1:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ vs_output_semantic_index[slot] = 1;
+ break;
+ case VERT_RESULT_BFC0:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_BFC1:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+ vs_output_semantic_index[slot] = 1;
+ break;
+ case VERT_RESULT_FOGC:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_PSIZ:
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+ vs_output_semantic_index[slot] = 0;
+ break;
+ case VERT_RESULT_EDGE:
+ assert(0);
+ break;
+ case VERT_RESULT_TEX0:
+ case VERT_RESULT_TEX1:
+ case VERT_RESULT_TEX2:
+ case VERT_RESULT_TEX3:
+ case VERT_RESULT_TEX4:
+ case VERT_RESULT_TEX5:
+ case VERT_RESULT_TEX6:
+ case VERT_RESULT_TEX7:
+ /* fall-through */
+ case VERT_RESULT_VAR0:
+ /* fall-through */
+ default:
+ assert(slot < Elements(vs_output_semantic_name));
+ if (outputSemanticName) {
+ /* use provided semantic into */
+ assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT);
+ vs_output_semantic_name[slot] = outputSemanticName[attr];
+ vs_output_semantic_index[slot] = outputSemanticIndex[attr];
+ }
+ else {
+ /* use default semantic info */
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs_output_semantic_index[slot] = num_generic++;
+ }
+ }
+
+ assert(slot < Elements(output_flags));
+ output_flags[slot] = stvp->Base.Base.OutputFlags[attr];
+ }
+ }
+
+ if (outputMapping) {
+ /* find max output slot referenced to compute vs_num_outputs */
+ GLuint maxSlot = 0;
+ for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+ if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
+ maxSlot = outputMapping[attr];
+ }
+ vs_num_outputs = maxSlot + 1;
+ }
+ else {
+ outputMapping = defaultOutputMapping;
+ }
+
+#if 0 /* debug */
+ {
+ GLuint i;
+ printf("outputMapping? %d\n", outputMapping ? 1 : 0);
+ if (outputMapping) {
+ printf("attr -> slot\n");
+ for (i = 0; i < 16; i++) {
+ printf(" %2d %3d\n", i, outputMapping[i]);
+ }
+ }
+ printf("slot sem_name sem_index\n");
+ for (i = 0; i < vs_num_outputs; i++) {
+ printf(" %2d %d %d\n",
+ i,
+ vs_output_semantic_name[i],
+ vs_output_semantic_index[i]);
+ }
+ }
+#endif
+
+ /* free old shader state, if any */
+ if (stvp->state.tokens) {
+ _mesa_free((void *) stvp->state.tokens);
+ stvp->state.tokens = NULL;
+ }
+ if (stvp->driver_shader) {
+ cso_delete_vertex_shader(st->cso_context, stvp->driver_shader);
+ stvp->driver_shader = NULL;
+ }
+
+ /* XXX: fix static allocation of tokens:
+ */
+ num_tokens = st_translate_mesa_program(st->ctx,
+ TGSI_PROCESSOR_VERTEX,
+ &stvp->Base.Base,
+ /* inputs */
+ vs_num_inputs,
+ stvp->input_to_index,
+ vs_input_semantic_name,
+ vs_input_semantic_index,
+ NULL,
+ input_flags,
+ /* outputs */
+ vs_num_outputs,
+ outputMapping,
+ vs_output_semantic_name,
+ vs_output_semantic_index,
+ output_flags,
+ /* tokenized result */
+ tokens, ST_MAX_SHADER_TOKENS);
+
+ assert(num_tokens < ST_MAX_SHADER_TOKENS);
+
+ vs.tokens = (struct tgsi_token *)
+ _mesa_realloc(tokens,
+ ST_MAX_SHADER_TOKENS * sizeof *tokens,
+ num_tokens * sizeof *tokens);
+
+ stvp->num_inputs = vs_num_inputs;
+ stvp->state = vs; /* struct copy */
+ stvp->driver_shader = pipe->create_vs_state(pipe, &vs);
+
+ if (0)
+ _mesa_print_program(&stvp->Base.Base);
+
+ if (TGSI_DEBUG)
+ tgsi_dump( vs.tokens, 0 );
+}
+
+
+
+/**
+ * Translate a Mesa fragment shader into a TGSI shader.
+ * \param inputMapping to map fragment program input registers to TGSI
+ * input slots
+ * \param tokensOut destination for TGSI tokens
+ * \return pointer to cached pipe_shader object.
+ */
+void
+st_translate_fragment_program(struct st_context *st,
+ struct st_fragment_program *stfp,
+ const GLuint inputMapping[])
+{
+ struct pipe_context *pipe = st->pipe;
+ struct tgsi_token *tokens;
+ GLuint outputMapping[FRAG_RESULT_MAX];
+ GLuint defaultInputMapping[FRAG_ATTRIB_MAX];
+ struct pipe_shader_state fs;
+ GLuint interpMode[16]; /* XXX size? */
+ GLuint attr;
+ const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
+ GLuint vslot = 0;
+ GLuint num_generic = 0;
+ GLuint num_tokens;
+
+ uint fs_num_inputs = 0;
+
+ ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
+ ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
+ uint fs_num_outputs = 0;
+
+ GLbitfield input_flags[MAX_PROGRAM_INPUTS];
+ GLbitfield output_flags[MAX_PROGRAM_OUTPUTS];
+
+ tokens = (struct tgsi_token *)MALLOC(ST_MAX_SHADER_TOKENS * sizeof *tokens);
+ if(!tokens) {
+ /* FIXME: propagate error to the caller */
+ assert(0);
+ return;
+ }
+
+ memset(&fs, 0, sizeof(fs));
+ memset(input_flags, 0, sizeof(input_flags));
+ memset(output_flags, 0, sizeof(output_flags));
+
+ /* which vertex output goes to the first fragment input: */
+ if (inputsRead & FRAG_BIT_WPOS)
+ vslot = 0;
+ else
+ vslot = 1;
+
+ /*
+ * Convert Mesa program inputs to TGSI input register semantics.
+ */
+ for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
+ if (inputsRead & (1 << attr)) {
+ const GLuint slot = fs_num_inputs;
+
+ defaultInputMapping[attr] = slot;
+
+ stfp->input_map[slot] = vslot++;
+
+ fs_num_inputs++;
+
+ switch (attr) {
+ case FRAG_ATTRIB_WPOS:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ stfp->input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ case FRAG_ATTRIB_COL0:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stfp->input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ case FRAG_ATTRIB_COL1:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stfp->input_semantic_index[slot] = 1;
+ interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
+ break;
+ case FRAG_ATTRIB_FOGC:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ stfp->input_semantic_index[slot] = 0;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+ break;
+ case FRAG_ATTRIB_FACE:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
+ stfp->input_semantic_index[slot] = num_generic++;
+ interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
+ break;
+ case FRAG_ATTRIB_PNTC:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stfp->input_semantic_index[slot] = num_generic++;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+ break;
+ case FRAG_ATTRIB_TEX0:
+ case FRAG_ATTRIB_TEX1:
+ case FRAG_ATTRIB_TEX2:
+ case FRAG_ATTRIB_TEX3:
+ case FRAG_ATTRIB_TEX4:
+ case FRAG_ATTRIB_TEX5:
+ case FRAG_ATTRIB_TEX6:
+ case FRAG_ATTRIB_TEX7:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stfp->input_semantic_index[slot] = num_generic++;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+ break;
+ case FRAG_ATTRIB_VAR0:
+ /* fall-through */
+ default:
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stfp->input_semantic_index[slot] = num_generic++;
+ interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
+ }
+
+ input_flags[slot] = stfp->Base.Base.InputFlags[attr];
+ }
+ }
+
+ /*
+ * Semantics and mapping for outputs
+ */
+ {
+ uint numColors = 0;
+ GLbitfield outputsWritten = stfp->Base.Base.OutputsWritten;
+
+ /* if z is written, emit that first */
+ if (outputsWritten & (1 << FRAG_RESULT_DEPTH)) {
+ fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
+ fs_output_semantic_index[fs_num_outputs] = 0;
+ outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
+ fs_num_outputs++;
+ outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
+ }
+
+ /* handle remaning outputs (color) */
+ for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
+ if (outputsWritten & (1 << attr)) {
+ switch (attr) {
+ case FRAG_RESULT_DEPTH:
+ /* handled above */
+ assert(0);
+ break;
+ default:
+ assert(attr == FRAG_RESULT_COLOR ||
+ (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
+ fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
+ fs_output_semantic_index[fs_num_outputs] = numColors;
+ outputMapping[attr] = fs_num_outputs;
+ numColors++;
+ break;
+ }
+
+ output_flags[fs_num_outputs] = stfp->Base.Base.OutputFlags[attr];
+
+ fs_num_outputs++;
+ }
+ }
+ }
+
+ if (!inputMapping)
+ inputMapping = defaultInputMapping;
+
+ /* XXX: fix static allocation of tokens:
+ */
+ num_tokens = st_translate_mesa_program(st->ctx,
+ TGSI_PROCESSOR_FRAGMENT,
+ &stfp->Base.Base,
+ /* inputs */
+ fs_num_inputs,
+ inputMapping,
+ stfp->input_semantic_name,
+ stfp->input_semantic_index,
+ interpMode,
+ input_flags,
+ /* outputs */
+ fs_num_outputs,
+ outputMapping,
+ fs_output_semantic_name,
+ fs_output_semantic_index,
+ output_flags,
+ /* tokenized result */
+ tokens, ST_MAX_SHADER_TOKENS);
+
+ assert(num_tokens < ST_MAX_SHADER_TOKENS);
+
+ fs.tokens = (struct tgsi_token *)
+ _mesa_realloc(tokens,
+ ST_MAX_SHADER_TOKENS * sizeof *tokens,
+ num_tokens * sizeof *tokens);
+
+ stfp->state = fs; /* struct copy */
+ stfp->driver_shader = pipe->create_fs_state(pipe, &fs);
+
+ if (0)
+ _mesa_print_program(&stfp->Base.Base);
+
+ if (TGSI_DEBUG)
+ tgsi_dump( fs.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
+}
+
+
+/**
+ * Debug- print current shader text
+ */
+void
+st_print_shaders(GLcontext *ctx)
+{
+ struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ if (shProg) {
+ GLuint i;
+ for (i = 0; i < shProg->NumShaders; i++) {
+ printf("GLSL shader %u of %u:\n", i, shProg->NumShaders);
+ printf("%s\n", shProg->Shaders[i]->Source);
+ }
+ }
+}
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
new file mode 100644
index 0000000000..e2e5eddef2
--- /dev/null
+++ b/src/mesa/state_tracker/st_program.h
@@ -0,0 +1,158 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef ST_PROGRAM_H
+#define ST_PROGRAM_H
+
+#include "main/mtypes.h"
+#include "shader/program.h"
+#include "pipe/p_shader_tokens.h"
+
+
+struct cso_fragment_shader;
+struct cso_vertex_shader;
+struct translated_vertex_program;
+
+
+/**
+ * Derived from Mesa gl_fragment_program:
+ */
+struct st_fragment_program
+{
+ struct gl_fragment_program Base;
+ GLuint serialNo;
+
+ GLuint input_to_slot[FRAG_ATTRIB_MAX]; /**< Maps FRAG_ATTRIB_x to slot */
+ GLuint num_input_slots;
+
+ /** map FP input back to VP output */
+ GLuint input_map[PIPE_MAX_SHADER_INPUTS];
+
+ ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
+ ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
+
+ struct pipe_shader_state state;
+ void *driver_shader;
+
+ GLuint param_state;
+
+ /** List of vertex programs which have been translated such that their
+ * outputs match this fragment program's inputs.
+ */
+ struct translated_vertex_program *vertex_programs;
+
+ /** Program prefixed with glBitmap prologue */
+ struct st_fragment_program *bitmap_program;
+ uint bitmap_sampler;
+};
+
+
+/**
+ * Derived from Mesa gl_fragment_program:
+ */
+struct st_vertex_program
+{
+ struct gl_vertex_program Base; /**< The Mesa vertex program */
+ GLuint serialNo;
+
+ /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */
+ GLuint input_to_index[VERT_ATTRIB_MAX];
+ /** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */
+ GLuint index_to_input[PIPE_MAX_SHADER_INPUTS];
+
+ GLuint num_inputs;
+
+ struct pipe_shader_state state;
+ void *driver_shader;
+
+ /** For using our private draw module (glRasterPos) */
+ struct draw_vertex_shader *draw_shader;
+
+ GLuint param_state;
+};
+
+
+static INLINE struct st_fragment_program *
+st_fragment_program( struct gl_fragment_program *fp )
+{
+ return (struct st_fragment_program *)fp;
+}
+
+
+static INLINE struct st_vertex_program *
+st_vertex_program( struct gl_vertex_program *vp )
+{
+ return (struct st_vertex_program *)vp;
+}
+
+
+static INLINE void
+st_reference_vertprog(struct st_context *st,
+ struct st_vertex_program **ptr,
+ struct st_vertex_program *prog)
+{
+ _mesa_reference_program(st->ctx,
+ (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+static INLINE void
+st_reference_fragprog(struct st_context *st,
+ struct st_fragment_program **ptr,
+ struct st_fragment_program *prog)
+{
+ _mesa_reference_program(st->ctx,
+ (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+
+extern void
+st_translate_fragment_program(struct st_context *st,
+ struct st_fragment_program *fp,
+ const GLuint inputMapping[]);
+
+
+extern void
+st_translate_vertex_program(struct st_context *st,
+ struct st_vertex_program *vp,
+ const GLuint vert_output_to_slot[],
+ const ubyte *fs_input_semantic_name,
+ const ubyte *fs_input_semantic_index);
+
+
+extern void
+st_print_shaders(GLcontext *ctx);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h
new file mode 100644
index 0000000000..a5fdac32d1
--- /dev/null
+++ b/src/mesa/state_tracker/st_public.h
@@ -0,0 +1,129 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ST_PUBLIC_H
+#define ST_PUBLIC_H
+
+#include "GL/gl.h"
+#include "GL/internal/glcore.h" /* for __GLcontextModes */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+
+
+#define ST_SURFACE_FRONT_LEFT 0
+#define ST_SURFACE_BACK_LEFT 1
+#define ST_SURFACE_FRONT_RIGHT 2
+#define ST_SURFACE_BACK_RIGHT 3
+#define ST_SURFACE_DEPTH 8
+
+#define ST_TEXTURE_2D 0x2
+#define ST_TEXTURE_RECT 0x4
+
+#define ST_TEXTURE_RGB 0x1
+#define ST_TEXTURE_RGBA 0x2
+
+
+struct st_context;
+struct st_framebuffer;
+struct pipe_context;
+struct pipe_fence_handle;
+struct pipe_surface;
+struct pipe_texture;
+
+
+struct st_context *st_create_context(struct pipe_context *pipe,
+ const __GLcontextModes *visual,
+ struct st_context *share);
+
+void st_destroy_context( struct st_context *st );
+
+void st_copy_context_state(struct st_context *dst, struct st_context *src,
+ uint mask);
+
+struct st_framebuffer *st_create_framebuffer( const __GLcontextModes *visual,
+ enum pipe_format colorFormat,
+ enum pipe_format depthFormat,
+ enum pipe_format stencilFormat,
+ uint width, uint height,
+ void *privateData);
+
+void st_resize_framebuffer( struct st_framebuffer *stfb,
+ uint width, uint height );
+
+void st_set_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface *surf);
+
+void st_get_framebuffer_dimensions( struct st_framebuffer *stfb,
+ uint *width, uint *height);
+
+int st_get_framebuffer_surface(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_surface **surface);
+
+int st_get_framebuffer_texture(struct st_framebuffer *stfb,
+ uint surfIndex, struct pipe_texture **texture);
+
+void *st_framebuffer_private( struct st_framebuffer *stfb );
+
+void st_unreference_framebuffer( struct st_framebuffer *stfb );
+
+GLboolean st_make_current(struct st_context *st,
+ struct st_framebuffer *draw,
+ struct st_framebuffer *read);
+
+struct st_context *st_get_current(void);
+
+void st_flush( struct st_context *st, uint pipeFlushFlags,
+ struct pipe_fence_handle **fence );
+void st_finish( struct st_context *st );
+
+void st_notify_swapbuffers(struct st_framebuffer *stfb);
+
+void st_swapbuffers(struct st_framebuffer *stfb,
+ struct pipe_surface **front_left,
+ struct pipe_surface **front_right);
+
+int st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
+ enum pipe_format format);
+int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level);
+
+/** Redirect rendering into stfb's surface to a texture image */
+int st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
+ int target, int format, int level);
+
+/** Undo surface-to-texture binding */
+int st_release_teximage(struct st_framebuffer *stfb, uint surfIndex,
+ int target, int format, int level);
+
+
+/** Generic function type */
+typedef void (*st_proc)();
+
+st_proc st_get_proc_address(const char *procname);
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
new file mode 100644
index 0000000000..bbc2830e69
--- /dev/null
+++ b/src/mesa/state_tracker/st_texture.c
@@ -0,0 +1,583 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "st_context.h"
+#include "st_format.h"
+#include "st_public.h"
+#include "st_texture.h"
+#include "st_cb_fbo.h"
+#include "st_inlines.h"
+#include "main/enums.h"
+#include "main/texobj.h"
+#include "main/teximage.h"
+#include "main/texstore.h"
+
+#undef Elements /* fix re-defined macro warning */
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_rect.h"
+
+
+#define DBG if(0) printf
+
+#if 0
+static GLenum
+target_to_target(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ return GL_TEXTURE_CUBE_MAP_ARB;
+ default:
+ return target;
+ }
+}
+#endif
+
+
+/**
+ * Allocate a new pipe_texture object
+ * width0, height0, depth0 are the dimensions of the level 0 image
+ * (the highest resolution). last_level indicates how many mipmap levels
+ * to allocate storage for. For non-mipmapped textures, this will be zero.
+ */
+struct pipe_texture *
+st_texture_create(struct st_context *st,
+ enum pipe_texture_target target,
+ enum pipe_format format,
+ GLuint last_level,
+ GLuint width0,
+ GLuint height0,
+ GLuint depth0,
+ GLuint usage )
+{
+ struct pipe_texture pt, *newtex;
+ struct pipe_screen *screen = st->pipe->screen;
+
+ assert(target <= PIPE_TEXTURE_CUBE);
+
+ DBG("%s target %s format %s last_level %d\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(format), last_level);
+
+ assert(format);
+ assert(screen->is_format_supported(screen, format, target,
+ PIPE_TEXTURE_USAGE_SAMPLER, 0));
+
+ memset(&pt, 0, sizeof(pt));
+ pt.target = target;
+ pt.format = format;
+ pt.last_level = last_level;
+ pt.width[0] = width0;
+ pt.height[0] = height0;
+ pt.depth[0] = depth0;
+ pf_get_block(format, &pt.block);
+ pt.tex_usage = usage;
+
+ newtex = screen->texture_create(screen, &pt);
+
+ assert(!newtex || pipe_is_referenced(&newtex->reference));
+
+ return newtex;
+}
+
+
+/**
+ * Check if a texture image can be pulled into a unified mipmap texture.
+ */
+GLboolean
+st_texture_match_image(const struct pipe_texture *pt,
+ const struct gl_texture_image *image,
+ GLuint face, GLuint level)
+{
+ /* Images with borders are never pulled into mipmap textures.
+ */
+ if (image->Border)
+ return GL_FALSE;
+
+ /* Check if this image's format matches the established texture's format.
+ */
+ if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format)
+ return GL_FALSE;
+
+ /* Test if this image's size matches what's expected in the
+ * established texture.
+ */
+ if (image->Width != pt->width[level] ||
+ image->Height != pt->height[level] ||
+ image->Depth != pt->depth[level])
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+#if 000
+/* Although we use the image_offset[] array to store relative offsets
+ * to cube faces, Mesa doesn't know anything about this and expects
+ * each cube face to be treated as a separate image.
+ *
+ * These functions present that view to mesa:
+ */
+const GLuint *
+st_texture_depth_offsets(struct pipe_texture *pt, GLuint level)
+{
+ static const GLuint zero = 0;
+
+ if (pt->target != PIPE_TEXTURE_3D || pt->level[level].nr_images == 1)
+ return &zero;
+ else
+ return pt->level[level].image_offset;
+}
+
+
+/**
+ * Return the offset to the given mipmap texture image within the
+ * texture memory buffer, in bytes.
+ */
+GLuint
+st_texture_image_offset(const struct pipe_texture * pt,
+ GLuint face, GLuint level)
+{
+ if (pt->target == PIPE_TEXTURE_CUBE)
+ return (pt->level[level].level_offset +
+ pt->level[level].image_offset[face] * pt->cpp);
+ else
+ return pt->level[level].level_offset;
+}
+#endif
+
+
+/**
+ * Map a teximage in a mipmap texture.
+ * \param row_stride returns row stride in bytes
+ * \param image_stride returns image stride in bytes (for 3D textures).
+ * \return address of mapping
+ */
+GLubyte *
+st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
+ GLuint zoffset, enum pipe_transfer_usage usage,
+ GLuint x, GLuint y, GLuint w, GLuint h)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_texture *pt = stImage->pt;
+
+ DBG("%s \n", __FUNCTION__);
+
+ stImage->transfer = st_no_flush_get_tex_transfer(st, pt, stImage->face,
+ stImage->level, zoffset,
+ usage, x, y, w, h);
+
+ if (stImage->transfer)
+ return screen->transfer_map(screen, stImage->transfer);
+ else
+ return NULL;
+}
+
+
+void
+st_texture_image_unmap(struct st_context *st,
+ struct st_texture_image *stImage)
+{
+ struct pipe_screen *screen = st->pipe->screen;
+
+ DBG("%s\n", __FUNCTION__);
+
+ screen->transfer_unmap(screen, stImage->transfer);
+
+ screen->tex_transfer_destroy(stImage->transfer);
+}
+
+
+
+/**
+ * Upload data to a rectangular sub-region. Lots of choices how to do this:
+ *
+ * - memcpy by span to current destination
+ * - upload data as new buffer and blit
+ *
+ * Currently always memcpy.
+ */
+static void
+st_surface_data(struct pipe_context *pipe,
+ struct pipe_transfer *dst,
+ unsigned dstx, unsigned dsty,
+ const void *src, unsigned src_stride,
+ unsigned srcx, unsigned srcy, unsigned width, unsigned height)
+{
+ struct pipe_screen *screen = pipe->screen;
+ void *map = screen->transfer_map(screen, dst);
+
+ util_copy_rect(map,
+ &dst->block,
+ dst->stride,
+ dstx, dsty,
+ width, height,
+ src, src_stride,
+ srcx, srcy);
+
+ screen->transfer_unmap(screen, dst);
+}
+
+
+/* Upload data for a particular image.
+ */
+void
+st_texture_image_data(struct st_context *st,
+ struct pipe_texture *dst,
+ GLuint face,
+ GLuint level,
+ void *src,
+ GLuint src_row_stride, GLuint src_image_stride)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ GLuint depth = dst->depth[level];
+ GLuint i;
+ const GLubyte *srcUB = src;
+ struct pipe_transfer *dst_transfer;
+
+ DBG("%s\n", __FUNCTION__);
+
+ for (i = 0; i < depth; i++) {
+ dst_transfer = st_no_flush_get_tex_transfer(st, dst, face, level, i,
+ PIPE_TRANSFER_WRITE, 0, 0,
+ dst->width[level],
+ dst->height[level]);
+
+ st_surface_data(pipe, dst_transfer,
+ 0, 0, /* dstx, dsty */
+ srcUB,
+ src_row_stride,
+ 0, 0, /* source x, y */
+ dst->width[level], dst->height[level]); /* width, height */
+
+ screen->tex_transfer_destroy(dst_transfer);
+
+ srcUB += src_image_stride;
+ }
+}
+
+
+/* Copy mipmap image between textures
+ */
+void
+st_texture_image_copy(struct pipe_context *pipe,
+ struct pipe_texture *dst, GLuint dstLevel,
+ struct pipe_texture *src,
+ GLuint face)
+{
+ struct pipe_screen *screen = pipe->screen;
+ GLuint width = dst->width[dstLevel];
+ GLuint height = dst->height[dstLevel];
+ GLuint depth = dst->depth[dstLevel];
+ struct pipe_surface *src_surface;
+ struct pipe_surface *dst_surface;
+ GLuint i;
+
+ for (i = 0; i < depth; i++) {
+ GLuint srcLevel;
+
+ /* find src texture level of needed size */
+ for (srcLevel = 0; srcLevel <= src->last_level; srcLevel++) {
+ if (src->width[srcLevel] == width &&
+ src->height[srcLevel] == height) {
+ break;
+ }
+ }
+ assert(src->width[srcLevel] == width);
+ assert(src->height[srcLevel] == height);
+
+#if 0
+ {
+ src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ ubyte *map = screen->surface_map(screen, src_surface, PIPE_BUFFER_USAGE_CPU_READ);
+ map += src_surface->width * src_surface->height * 4 / 2;
+ printf("%s center pixel: %d %d %d %d (pt %p[%d] -> %p[%d])\n",
+ __FUNCTION__,
+ map[0], map[1], map[2], map[3],
+ src, srcLevel, dst, dstLevel);
+
+ screen->surface_unmap(screen, src_surface);
+ pipe_surface_reference(&src_surface, NULL);
+ }
+#endif
+
+ dst_surface = screen->get_tex_surface(screen, dst, face, dstLevel, i,
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i,
+ PIPE_BUFFER_USAGE_GPU_READ);
+
+ pipe->surface_copy(pipe,
+ dst_surface,
+ 0, 0, /* destX, Y */
+ src_surface,
+ 0, 0, /* srcX, Y */
+ width, height);
+
+ pipe_surface_reference(&src_surface, NULL);
+ pipe_surface_reference(&dst_surface, NULL);
+ }
+}
+
+
+/**
+ * Bind a pipe surface to a texture object. After the call,
+ * the texture object is marked dirty and will be (re-)validated.
+ *
+ * If this is the first surface bound, the texture object is said to
+ * switch from normal to surface based. It will be cleared first in
+ * this case.
+ *
+ * \param ps pipe surface to be unbound
+ * \param target texture target
+ * \param level image level
+ * \param format internal format of the texture
+ */
+int
+st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
+ enum pipe_format format)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ struct st_texture_object *stObj;
+ struct st_texture_image *stImage;
+ GLenum internalFormat;
+
+ switch (target) {
+ case ST_TEXTURE_2D:
+ target = GL_TEXTURE_2D;
+ break;
+ case ST_TEXTURE_RECT:
+ target = GL_TEXTURE_RECTANGLE_ARB;
+ break;
+ default:
+ return 0;
+ }
+
+ /* map pipe format to base format for now */
+ if (pf_get_component_bits(format, PIPE_FORMAT_COMP_A) > 0)
+ internalFormat = GL_RGBA;
+ else
+ internalFormat = GL_RGB;
+
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+
+ stObj = st_texture_object(texObj);
+ /* switch to surface based */
+ if (!stObj->surface_based) {
+ _mesa_clear_texture_object(ctx, texObj);
+ stObj->surface_based = GL_TRUE;
+ }
+
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ stImage = st_texture_image(texImage);
+
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ ps->width, ps->height, 1, 0, internalFormat);
+ texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
+ GL_RGBA, GL_UNSIGNED_BYTE);
+ _mesa_set_fetch_functions(texImage, 2);
+ pipe_texture_reference(&stImage->pt, ps->texture);
+
+ _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+ _mesa_unlock_texture(ctx, texObj);
+
+ return 1;
+}
+
+
+/**
+ * Unbind a pipe surface from a texture object. After the call,
+ * the texture object is marked dirty and will be (re-)validated.
+ *
+ * \param ps pipe surface to be unbound
+ * \param target texture target
+ * \param level image level
+ */
+int
+st_unbind_texture_surface(struct pipe_surface *ps, int target, int level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ struct st_texture_object *stObj;
+ struct st_texture_image *stImage;
+
+ switch (target) {
+ case ST_TEXTURE_2D:
+ target = GL_TEXTURE_2D;
+ break;
+ case ST_TEXTURE_RECT:
+ target = GL_TEXTURE_RECTANGLE_ARB;
+ break;
+ default:
+ return 0;
+ }
+
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ stObj = st_texture_object(texObj);
+ stImage = st_texture_image(texImage);
+
+ /* Make sure the pipe surface is still bound. The texture object is still
+ * considered surface based even if this is the last bound surface. */
+ if (stImage->pt == ps->texture) {
+ pipe_texture_reference(&stImage->pt, NULL);
+ _mesa_clear_texture_image(ctx, texImage);
+
+ _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+ }
+
+ _mesa_unlock_texture(ctx, texObj);
+
+ return 1;
+}
+
+
+/** Redirect rendering into stfb's surface to a texture image */
+int
+st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
+ int target, int format, int level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ const GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ struct st_texture_image *stImage;
+ struct st_renderbuffer *strb;
+ GLint face = 0, slice = 0;
+
+ assert(surfIndex <= ST_SURFACE_DEPTH);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+
+ if (strb->texture_save || strb->surface_save) {
+ /* Error! */
+ return 0;
+ }
+
+ if (target == ST_TEXTURE_2D) {
+ texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX];
+ texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, level);
+ stImage = st_texture_image(texImage);
+ }
+ else {
+ /* unsupported target */
+ return 0;
+ }
+
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* save the renderbuffer's surface/texture info */
+ pipe_texture_reference(&strb->texture_save, strb->texture);
+ pipe_surface_reference(&strb->surface_save, strb->surface);
+
+ /* plug in new surface/texture info */
+ pipe_texture_reference(&strb->texture, stImage->pt);
+ strb->surface = screen->get_tex_surface(screen, strb->texture,
+ face, level, slice,
+ (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE));
+
+ st->dirty.st |= ST_NEW_FRAMEBUFFER;
+
+ return 1;
+}
+
+
+/** Undo surface-to-texture binding */
+int
+st_release_teximage(struct st_framebuffer *stfb, uint surfIndex,
+ int target, int format, int level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct st_context *st = ctx->st;
+ struct st_renderbuffer *strb;
+
+ assert(surfIndex <= ST_SURFACE_DEPTH);
+
+ strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
+
+ if (!strb->texture_save || !strb->surface_save) {
+ /* Error! */
+ return 0;
+ }
+
+ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ /* free tex surface, restore original */
+ pipe_surface_reference(&strb->surface, strb->surface_save);
+ pipe_texture_reference(&strb->texture, strb->texture_save);
+
+ pipe_surface_reference(&strb->surface_save, NULL);
+ pipe_texture_reference(&strb->texture_save, NULL);
+
+ st->dirty.st |= ST_NEW_FRAMEBUFFER;
+
+ return 1;
+}
+
+void
+st_teximage_flush_before_map(struct st_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ enum pipe_transfer_usage usage)
+{
+ struct pipe_context *pipe = st->pipe;
+ unsigned referenced =
+ pipe->is_texture_referenced(pipe, pt, face, level);
+
+ if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
+ usage == PIPE_TRANSFER_WRITE ||
+ usage == PIPE_TRANSFER_READ_WRITE))
+ st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
+}
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
new file mode 100644
index 0000000000..60868ce067
--- /dev/null
+++ b/src/mesa/state_tracker/st_texture.h
@@ -0,0 +1,184 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef ST_TEXTURE_H
+#define ST_TEXTURE_H
+
+
+#include "main/mtypes.h"
+
+struct pipe_context;
+struct pipe_texture;
+
+
+struct st_texture_image
+{
+ struct gl_texture_image base;
+
+ /* These aren't stored in gl_texture_image
+ */
+ GLuint level;
+ GLuint face;
+
+ /* If stImage->pt != NULL, image data is stored here.
+ * Else if stImage->base.Data != NULL, image is stored there.
+ * Else there is no image data.
+ */
+ struct pipe_texture *pt;
+
+ struct pipe_transfer *transfer;
+};
+
+
+
+struct st_texture_object
+{
+ struct gl_texture_object base; /* The "parent" object */
+
+ /* The texture must include at levels [0..lastLevel] once validated:
+ */
+ GLuint lastLevel;
+
+ /* On validation any active images held in main memory or in other
+ * textures will be copied to this texture and the old storage freed.
+ */
+ struct pipe_texture *pt;
+
+ GLboolean teximage_realloc;
+
+ /* True if there is/was a surface bound to this texture object. It helps
+ * track whether the texture object is surface based or not.
+ */
+ GLboolean surface_based;
+};
+
+
+static INLINE struct st_texture_image *
+st_texture_image(struct gl_texture_image *img)
+{
+ return (struct st_texture_image *) img;
+}
+
+static INLINE struct st_texture_object *
+st_texture_object(struct gl_texture_object *obj)
+{
+ return (struct st_texture_object *) obj;
+}
+
+
+static INLINE struct pipe_texture *
+st_get_texobj_texture(struct gl_texture_object *texObj)
+{
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ return stObj ? stObj->pt : NULL;
+}
+
+
+static INLINE struct pipe_texture *
+st_get_stobj_texture(struct st_texture_object *stObj)
+{
+ return stObj ? stObj->pt : NULL;
+}
+
+
+extern struct pipe_texture *
+st_texture_create(struct st_context *st,
+ enum pipe_texture_target target,
+ enum pipe_format format,
+ GLuint last_level,
+ GLuint width0,
+ GLuint height0,
+ GLuint depth0,
+ GLuint tex_usage );
+
+
+/* Check if an image fits into an existing texture object.
+ */
+extern GLboolean
+st_texture_match_image(const struct pipe_texture *pt,
+ const struct gl_texture_image *image,
+ GLuint face, GLuint level);
+
+/* Return a pointer to an image within a texture. Return image stride as
+ * well.
+ */
+extern GLubyte *
+st_texture_image_map(struct st_context *st,
+ struct st_texture_image *stImage,
+ GLuint zoffset,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y,
+ unsigned w, unsigned h);
+
+extern void
+st_texture_image_unmap(struct st_context *st,
+ struct st_texture_image *stImage);
+
+
+/* Return pointers to each 2d slice within an image. Indexed by depth
+ * value.
+ */
+extern const GLuint *
+st_texture_depth_offsets(struct pipe_texture *pt, GLuint level);
+
+
+/* Return the linear offset of an image relative to the start of its region.
+ */
+extern GLuint
+st_texture_image_offset(const struct pipe_texture *pt,
+ GLuint face, GLuint level);
+
+extern GLuint
+st_texture_texel_offset(const struct pipe_texture * pt,
+ GLuint face, GLuint level,
+ GLuint col, GLuint row, GLuint img);
+
+
+/* Upload an image into a texture
+ */
+extern void
+st_texture_image_data(struct st_context *st,
+ struct pipe_texture *dst,
+ GLuint face, GLuint level, void *src,
+ GLuint src_row_pitch, GLuint src_image_pitch);
+
+
+/* Copy an image between two textures
+ */
+extern void
+st_texture_image_copy(struct pipe_context *pipe,
+ struct pipe_texture *dst, GLuint dstLevel,
+ struct pipe_texture *src,
+ GLuint face);
+
+extern void
+st_teximage_flush_before_map(struct st_context *st,
+ struct pipe_texture *pt,
+ unsigned int face,
+ unsigned int level,
+ enum pipe_transfer_usage usage);
+#endif
diff --git a/src/mesa/swrast/s_accum.c b/src/mesa/swrast/s_accum.c
index ff741777e7..c29ccf2d9b 100644
--- a/src/mesa/swrast/s_accum.c
+++ b/src/mesa/swrast/s_accum.c
@@ -73,6 +73,9 @@
#endif
+#if FEATURE_accum
+
+
/**
* This is called when we fall out of optimized/unscaled accum buffer mode.
* That is, we convert each unscaled accum buffer value into a scaled value
@@ -550,7 +553,7 @@ _swrast_Accum(GLcontext *ctx, GLenum op, GLfloat value)
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLint xpos, ypos, width, height;
- if (SWRAST_CONTEXT(ctx)->NewState)
+ if (swrast->NewState)
_swrast_validate_derived( ctx );
if (!ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer) {
@@ -558,9 +561,9 @@ _swrast_Accum(GLcontext *ctx, GLenum op, GLfloat value)
return;
}
- RENDER_START(swrast, ctx);
+ swrast_render_start(ctx);
- /* Compute region after calling RENDER_START so that we know the
+ /* Compute region after calling swrast_render_start() so that we know the
* drawbuffer's size/bounds are up to date.
*/
xpos = ctx->DrawBuffer->_Xmin;
@@ -595,5 +598,8 @@ _swrast_Accum(GLcontext *ctx, GLenum op, GLfloat value)
break;
}
- RENDER_FINISH(swrast, ctx);
+ swrast_render_finish(ctx);
}
+
+
+#endif /* FEATURE_accum */
diff --git a/src/mesa/swrast/s_accum.h b/src/mesa/swrast/s_accum.h
index 42e38cf02b..730c0254b2 100644
--- a/src/mesa/swrast/s_accum.h
+++ b/src/mesa/swrast/s_accum.h
@@ -30,8 +30,19 @@
#include "main/mtypes.h"
+#if FEATURE_accum
+
extern void
_swrast_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb);
+#else /* FEATURE_accum */
+
+static INLINE void
+_swrast_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ ASSERT_NO_FEATURE();
+}
#endif
+
+#endif /* S_ACCUM_H */
diff --git a/src/mesa/swrast/s_atifragshader.c b/src/mesa/swrast/s_atifragshader.c
index 21cbd3cf37..5fefae6c42 100644
--- a/src/mesa/swrast/s_atifragshader.c
+++ b/src/mesa/swrast/s_atifragshader.c
@@ -47,17 +47,12 @@ static void
fetch_texel(GLcontext * ctx, const GLfloat texcoord[4], GLfloat lambda,
GLuint unit, GLfloat color[4])
{
- GLchan rgba[4];
SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* XXX use a float-valued TextureSample routine here!!! */
swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
1, (const GLfloat(*)[4]) texcoord,
- &lambda, &rgba);
- color[0] = CHAN_TO_FLOAT(rgba[0]);
- color[1] = CHAN_TO_FLOAT(rgba[1]);
- color[2] = CHAN_TO_FLOAT(rgba[2]);
- color[3] = CHAN_TO_FLOAT(rgba[3]);
+ &lambda, (GLfloat (*)[4]) color);
}
static void
@@ -591,8 +586,6 @@ _swrast_exec_fragment_shader(GLcontext * ctx, SWspan *span)
/* incoming colors should be floats */
ASSERT(span->array->ChanType == GL_FLOAT);
- ctx->_CurrentProgram = GL_FRAGMENT_SHADER_ATI;
-
for (i = 0; i < span->end; i++) {
if (span->array->mask[i]) {
init_machine(ctx, &machine, shader, span, i);
@@ -608,6 +601,4 @@ _swrast_exec_fragment_shader(GLcontext * ctx, SWspan *span)
}
}
}
-
- ctx->_CurrentProgram = 0;
}
diff --git a/src/mesa/swrast/s_bitmap.c b/src/mesa/swrast/s_bitmap.c
index 35b34e654f..b7a28a46e9 100644
--- a/src/mesa/swrast/s_bitmap.c
+++ b/src/mesa/swrast/s_bitmap.c
@@ -38,6 +38,8 @@
#include "s_span.h"
+#if FEATURE_drawpix
+
/**
* Render a bitmap.
@@ -50,18 +52,17 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLint row, col;
GLuint count = 0;
SWspan span;
ASSERT(ctx->RenderMode == GL_RENDER);
- bitmap = _mesa_map_bitmap_pbo(ctx, unpack, bitmap);
+ bitmap = (const GLubyte *) _mesa_map_pbo_source(ctx, unpack, bitmap);
if (!bitmap)
return;
- RENDER_START(swrast,ctx);
+ swrast_render_start(ctx);
if (SWRAST_CONTEXT(ctx)->NewState)
_swrast_validate_derived( ctx );
@@ -132,9 +133,9 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
}
}
- RENDER_FINISH(swrast,ctx);
+ swrast_render_finish(ctx);
- _mesa_unmap_bitmap_pbo(ctx, unpack);
+ _mesa_unmap_pbo_source(ctx, unpack);
}
@@ -157,7 +158,7 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
ASSERT(ctx->RenderMode == GL_RENDER);
ASSERT(bitmap);
- RENDER_START(swrast,ctx);
+ swrast_render_start(ctx);
if (SWRAST_CONTEXT(ctx)->NewState)
_swrast_validate_derived( ctx );
@@ -224,6 +225,9 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
}
}
- RENDER_FINISH(swrast,ctx);
+ swrast_render_finish(ctx);
}
#endif
+
+
+#endif /* FEATURE_drawpix */
diff --git a/src/mesa/swrast/s_blit.c b/src/mesa/swrast/s_blit.c
index bc4b2ac625..8303e4debc 100644
--- a/src/mesa/swrast/s_blit.c
+++ b/src/mesa/swrast/s_blit.c
@@ -24,6 +24,7 @@
#include "main/glheader.h"
+#include "main/image.h"
#include "main/macros.h"
#include "s_context.h"
@@ -104,7 +105,7 @@ static void
blit_nearest(GLcontext *ctx,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLenum buffer)
+ GLbitfield buffer)
{
struct gl_renderbuffer *readRb, *drawRb;
@@ -456,7 +457,7 @@ static void
simple_blit(GLcontext *ctx,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLenum buffer)
+ GLbitfield buffer)
{
struct gl_renderbuffer *readRb, *drawRb;
const GLint width = srcX1 - srcX0;
@@ -551,184 +552,6 @@ simple_blit(GLcontext *ctx,
/**
- * Clip dst coords against Xmax (or Ymax).
- */
-static INLINE void
-clip_right_or_top(GLint *srcX0, GLint *srcX1,
- GLint *dstX0, GLint *dstX1,
- GLint maxValue)
-{
- GLfloat t, bias;
-
- if (*dstX1 > maxValue) {
- /* X1 outside right edge */
- ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */
- t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
- /* chop off [t, 1] part */
- ASSERT(t >= 0.0 && t <= 1.0);
- *dstX1 = maxValue;
- bias = (*srcX0 < *srcX1) ? 0.5 : -0.5;
- *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
- }
- else if (*dstX0 > maxValue) {
- /* X0 outside right edge */
- ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */
- t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
- /* chop off [t, 1] part */
- ASSERT(t >= 0.0 && t <= 1.0);
- *dstX0 = maxValue;
- bias = (*srcX0 < *srcX1) ? -0.5 : 0.5;
- *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
- }
-}
-
-
-/**
- * Clip dst coords against Xmin (or Ymin).
- */
-static INLINE void
-clip_left_or_bottom(GLint *srcX0, GLint *srcX1,
- GLint *dstX0, GLint *dstX1,
- GLint minValue)
-{
- GLfloat t, bias;
-
- if (*dstX0 < minValue) {
- /* X0 outside left edge */
- ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */
- t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
- /* chop off [0, t] part */
- ASSERT(t >= 0.0 && t <= 1.0);
- *dstX0 = minValue;
- bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; /* flipped??? */
- *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
- }
- else if (*dstX1 < minValue) {
- /* X1 outside left edge */
- ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */
- t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
- /* chop off [0, t] part */
- ASSERT(t >= 0.0 && t <= 1.0);
- *dstX1 = minValue;
- bias = (*srcX0 < *srcX1) ? 0.5 : -0.5;
- *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
- }
-}
-
-
-/**
- * Do clipping of blit src/dest rectangles.
- * The dest rect is clipped against both the buffer bounds and scissor bounds.
- * The src rect is just clipped against the buffer bounds.
- *
- * When either the src or dest rect is clipped, the other is also clipped
- * proportionately!
- *
- * Note that X0 need not be less than X1 (same for Y) for either the source
- * and dest rects. That makes the clipping a little trickier.
- *
- * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
- */
-static GLboolean
-clip_blit(GLcontext *ctx,
- GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
- GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1)
-{
- const GLint srcXmin = 0;
- const GLint srcXmax = ctx->ReadBuffer->Width;
- const GLint srcYmin = 0;
- const GLint srcYmax = ctx->ReadBuffer->Height;
-
- /* these include scissor bounds */
- const GLint dstXmin = ctx->DrawBuffer->_Xmin;
- const GLint dstXmax = ctx->DrawBuffer->_Xmax;
- const GLint dstYmin = ctx->DrawBuffer->_Ymin;
- const GLint dstYmax = ctx->DrawBuffer->_Ymax;
-
- /*
- printf("PreClipX: src: %d .. %d dst: %d .. %d\n",
- *srcX0, *srcX1, *dstX0, *dstX1);
- printf("PreClipY: src: %d .. %d dst: %d .. %d\n",
- *srcY0, *srcY1, *dstY0, *dstY1);
- */
-
- /* trivial rejection tests */
- if (*dstX0 == *dstX1)
- return GL_FALSE; /* no width */
- if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)
- return GL_FALSE; /* totally out (left) of bounds */
- if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)
- return GL_FALSE; /* totally out (right) of bounds */
-
- if (*dstY0 == *dstY1)
- return GL_FALSE;
- if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)
- return GL_FALSE;
- if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)
- return GL_FALSE;
-
- if (*srcX0 == *srcX1)
- return GL_FALSE;
- if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)
- return GL_FALSE;
- if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)
- return GL_FALSE;
-
- if (*srcY0 == *srcY1)
- return GL_FALSE;
- if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)
- return GL_FALSE;
- if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)
- return GL_FALSE;
-
- /*
- * dest clip
- */
- clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);
- clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);
- clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);
- clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);
-
- /*
- * src clip (just swap src/dst values from above)
- */
- clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);
- clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);
- clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);
- clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);
-
- /*
- printf("PostClipX: src: %d .. %d dst: %d .. %d\n",
- *srcX0, *srcX1, *dstX0, *dstX1);
- printf("PostClipY: src: %d .. %d dst: %d .. %d\n",
- *srcY0, *srcY1, *dstY0, *dstY1);
- */
-
- ASSERT(*dstX0 >= dstXmin);
- ASSERT(*dstX0 <= dstXmax);
- ASSERT(*dstX1 >= dstXmin);
- ASSERT(*dstX1 <= dstXmax);
-
- ASSERT(*dstY0 >= dstYmin);
- ASSERT(*dstY0 <= dstYmax);
- ASSERT(*dstY1 >= dstYmin);
- ASSERT(*dstY1 <= dstYmax);
-
- ASSERT(*srcX0 >= srcXmin);
- ASSERT(*srcX0 <= srcXmax);
- ASSERT(*srcX1 >= srcXmin);
- ASSERT(*srcX1 <= srcXmax);
-
- ASSERT(*srcY0 >= srcYmin);
- ASSERT(*srcY0 <= srcYmax);
- ASSERT(*srcY1 >= srcYmin);
- ASSERT(*srcY1 <= srcYmax);
-
- return GL_TRUE;
-}
-
-
-/**
* Software fallback for glBlitFramebufferEXT().
*/
void
@@ -737,8 +560,7 @@ _swrast_BlitFramebuffer(GLcontext *ctx,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
- static const GLint buffers[3] = {
+ static const GLbitfield buffers[3] = {
GL_COLOR_BUFFER_BIT,
GL_DEPTH_BUFFER_BIT,
GL_STENCIL_BUFFER_BIT
@@ -748,12 +570,12 @@ _swrast_BlitFramebuffer(GLcontext *ctx,
if (!ctx->DrawBuffer->_NumColorDrawBuffers)
return;
- if (!clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
- &dstX0, &dstY0, &dstX1, &dstY1)) {
+ if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
+ &dstX0, &dstY0, &dstX1, &dstY1)) {
return;
}
- RENDER_START(swrast, ctx);
+ swrast_render_start(ctx);
if (srcX1 - srcX0 == dstX1 - dstX0 &&
srcY1 - srcY0 == dstY1 - dstY0 &&
@@ -789,5 +611,5 @@ _swrast_BlitFramebuffer(GLcontext *ctx,
}
}
- RENDER_FINISH(swrast, ctx);
+ swrast_render_finish(ctx);
}
diff --git a/src/mesa/swrast/s_buffers.c b/src/mesa/swrast/s_clear.c
index 9e87d6d485..35080fd394 100644
--- a/src/mesa/swrast/s_buffers.c
+++ b/src/mesa/swrast/s_clear.c
@@ -22,8 +22,6 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-/** XXX This file should be named s_clear.c */
-
#include "main/glheader.h"
#include "main/colormac.h"
#include "main/macros.h"
@@ -307,8 +305,6 @@ clear_color_buffers(GLcontext *ctx)
void
_swrast_Clear(GLcontext *ctx, GLbitfield buffers)
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
-
#ifdef DEBUG_FOO
{
const GLbitfield legalBits =
@@ -319,15 +315,12 @@ _swrast_Clear(GLcontext *ctx, GLbitfield buffers)
BUFFER_BIT_DEPTH |
BUFFER_BIT_STENCIL |
BUFFER_BIT_ACCUM |
- BUFFER_BIT_AUX0 |
- BUFFER_BIT_AUX1 |
- BUFFER_BIT_AUX2 |
- BUFFER_BIT_AUX3;
+ BUFFER_BIT_AUX0;
assert((buffers & (~legalBits)) == 0);
}
#endif
- RENDER_START(swrast,ctx);
+ swrast_render_start(ctx);
/* do software clearing here */
if (buffers) {
@@ -347,5 +340,5 @@ _swrast_Clear(GLcontext *ctx, GLbitfield buffers)
}
}
- RENDER_FINISH(swrast,ctx);
+ swrast_render_finish(ctx);
}
diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c
index 62857ddeb0..abf0008565 100644
--- a/src/mesa/swrast/s_context.c
+++ b/src/mesa/swrast/s_context.c
@@ -61,7 +61,7 @@ _swrast_update_rasterflags( GLcontext *ctx )
if (ctx->Depth.Test) rasterMask |= DEPTH_BIT;
if (swrast->_FogEnabled) rasterMask |= FOG_BIT;
if (ctx->Scissor.Enabled) rasterMask |= CLIP_BIT;
- if (ctx->Stencil.Enabled) rasterMask |= STENCIL_BIT;
+ if (ctx->Stencil._Enabled) rasterMask |= STENCIL_BIT;
if (ctx->Visual.rgbMode) {
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
if (colorMask != 0xffffffff) rasterMask |= MASKING_BIT;
@@ -172,19 +172,29 @@ _swrast_update_fog_hint( GLcontext *ctx )
/**
- * Update the swrast->_AnyTextureCombine flag.
+ * Update the swrast->_TextureCombinePrimary flag.
*/
static void
_swrast_update_texture_env( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint i;
- swrast->_AnyTextureCombine = GL_FALSE;
+
+ swrast->_TextureCombinePrimary = GL_FALSE;
+
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (ctx->Texture.Unit[i].EnvMode == GL_COMBINE_EXT ||
- ctx->Texture.Unit[i].EnvMode == GL_COMBINE4_NV) {
- swrast->_AnyTextureCombine = GL_TRUE;
- return;
+ const struct gl_tex_env_combine_state *combine =
+ ctx->Texture.Unit[i]._CurrentCombine;
+ GLuint term;
+ for (term = 0; term < combine->_NumArgsRGB; term++) {
+ if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) {
+ swrast->_TextureCombinePrimary = GL_TRUE;
+ return;
+ }
+ if (combine->SourceA[term] == GL_PRIMARY_COLOR) {
+ swrast->_TextureCombinePrimary = GL_TRUE;
+ return;
+ }
}
}
}
@@ -206,10 +216,13 @@ _swrast_update_deferred_texture(GLcontext *ctx)
else {
const struct gl_fragment_program *fprog
= ctx->FragmentProgram._Current;
- if (fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR))) {
+ if (fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) {
/* Z comes from fragment program/shader */
swrast->_DeferredTexture = GL_FALSE;
}
+ else if (fprog && fprog->UsesKill) {
+ swrast->_DeferredTexture = GL_FALSE;
+ }
else if (ctx->Query.CurrentOcclusionObject) {
/* occlusion query depends on shader discard/kill results */
swrast->_DeferredTexture = GL_FALSE;
@@ -254,19 +267,32 @@ _swrast_update_fragment_program(GLcontext *ctx, GLbitfield newState)
{
const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
if (fp) {
-#if 0
- /* XXX Need a way to trigger the initial loading of parameters
- * even when there's no recent state changes.
- */
- if (fp->Base.Parameters->StateFlags & newState)
-#endif
- _mesa_load_state_parameters(ctx, fp->Base.Parameters);
+ _mesa_load_state_parameters(ctx, fp->Base.Parameters);
}
}
+/**
+ * See if we can do early diffuse+specular (primary+secondary) color
+ * add per vertex instead of per-fragment.
+ */
+static void
+_swrast_update_specular_vertex_add(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLboolean separateSpecular = ctx->Fog.ColorSumEnabled ||
+ (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR);
+
+ swrast->SpecularVertexAdd = (separateSpecular
+ && ctx->Texture._EnabledUnits == 0x0
+ && !ctx->FragmentProgram._Current
+ && !ctx->ATIFragmentShader._Enabled);
+}
+
#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \
+ _NEW_PROGRAM_CONSTANTS | \
_NEW_TEXTURE | \
_NEW_HINT | \
_NEW_POLYGON )
@@ -326,9 +352,7 @@ _swrast_validate_triangle( GLcontext *ctx,
swrast->choose_triangle( ctx );
ASSERT(swrast->Triangle);
- if (ctx->Texture._EnabledUnits == 0
- && NEED_SECONDARY_COLOR(ctx)
- && !ctx->FragmentProgram._Current) {
+ if (swrast->SpecularVertexAdd) {
/* separate specular color, but no texture */
swrast->SpecTriangle = swrast->Triangle;
swrast->Triangle = _swrast_add_spec_terms_triangle;
@@ -350,9 +374,7 @@ _swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
swrast->choose_line( ctx );
ASSERT(swrast->Line);
- if (ctx->Texture._EnabledUnits == 0
- && NEED_SECONDARY_COLOR(ctx)
- && !ctx->FragmentProgram._Current) {
+ if (swrast->SpecularVertexAdd) {
swrast->SpecLine = swrast->Line;
swrast->Line = _swrast_add_spec_terms_line;
}
@@ -372,9 +394,7 @@ _swrast_validate_point( GLcontext *ctx, const SWvertex *v0 )
_swrast_validate_derived( ctx );
swrast->choose_point( ctx );
- if (ctx->Texture._EnabledUnits == 0
- && NEED_SECONDARY_COLOR(ctx)
- && !ctx->FragmentProgram._Current) {
+ if (swrast->SpecularVertexAdd) {
swrast->SpecPoint = swrast->Point;
swrast->Point = _swrast_add_spec_terms_point;
}
@@ -502,13 +522,6 @@ _swrast_invalidate_state( GLcontext *ctx, GLbitfield new_state )
new_state = ~0;
}
- {
- const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
- if (fp && (fp->Base.Parameters->StateFlags & new_state)) {
- _mesa_load_state_parameters(ctx, fp->Base.Parameters);
- }
- }
-
if (new_state & swrast->InvalidateTriangleMask)
swrast->Triangle = _swrast_validate_triangle;
@@ -533,6 +546,9 @@ _swrast_update_texture_samplers(GLcontext *ctx)
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint u;
+ if (!swrast)
+ return; /* pipe hack */
+
for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
const struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
/* Note: If tObj is NULL, the sample function will be a simple
@@ -622,17 +638,7 @@ _swrast_validate_derived( GLcontext *ctx )
if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
_swrast_update_fog_state( ctx );
- if (swrast->NewState & (_NEW_MODELVIEW |
- _NEW_PROJECTION |
- _NEW_TEXTURE_MATRIX |
- _NEW_FOG |
- _NEW_LIGHT |
- _NEW_LINE |
- _NEW_TEXTURE |
- _NEW_TRANSFORM |
- _NEW_POINT |
- _NEW_VIEWPORT |
- _NEW_PROGRAM))
+ if (swrast->NewState & (_NEW_PROGRAM_CONSTANTS | _NEW_PROGRAM))
_swrast_update_fragment_program( ctx, swrast->NewState );
if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) {
@@ -653,6 +659,12 @@ _swrast_validate_derived( GLcontext *ctx )
_NEW_TEXTURE))
_swrast_update_active_attribs(ctx);
+ if (swrast->NewState & (_NEW_FOG |
+ _NEW_PROGRAM |
+ _NEW_LIGHT |
+ _NEW_TEXTURE))
+ _swrast_update_specular_vertex_add(ctx);
+
swrast->NewState = 0;
swrast->StateChanges = 0;
swrast->InvalidateState = _swrast_invalidate_state;
@@ -817,8 +829,8 @@ _swrast_CreateContext( GLcontext *ctx )
swrast->PointSpan.facing = 0;
swrast->PointSpan.array = swrast->SpanArrays;
- swrast->TexelBuffer = (GLchan *) MALLOC(ctx->Const.MaxTextureImageUnits *
- MAX_WIDTH * 4 * sizeof(GLchan));
+ swrast->TexelBuffer = (GLfloat *) MALLOC(ctx->Const.MaxTextureImageUnits *
+ MAX_WIDTH * 4 * sizeof(GLfloat));
if (!swrast->TexelBuffer) {
FREE(swrast->SpanArrays);
FREE(swrast);
diff --git a/src/mesa/swrast/s_context.h b/src/mesa/swrast/s_context.h
index a511d1c9a1..9059f9b5ec 100644
--- a/src/mesa/swrast/s_context.h
+++ b/src/mesa/swrast/s_context.h
@@ -52,7 +52,7 @@
typedef void (*texture_sample_func)(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4]);
+ const GLfloat lambda[], GLfloat rgba[][4]);
typedef void (_ASMAPIP blend_func)( GLcontext *ctx, GLuint n,
const GLubyte mask[],
@@ -131,7 +131,7 @@ typedef struct
GLfloat _BackfaceSign; /** +1 or -1 */
GLfloat _BackfaceCullSign; /** +1, 0, or -1 */
GLboolean _PreferPixelFog; /* Compute fog blend factor per fragment? */
- GLboolean _AnyTextureCombine;
+ GLboolean _TextureCombinePrimary;
GLboolean _FogEnabled;
GLboolean _DeferredTexture;
GLenum _FogMode; /* either GL_FOG_MODE or fragment program's fog mode */
@@ -157,6 +157,7 @@ typedef struct
GLbitfield NewState;
GLuint StateChanges;
GLenum Primitive; /* current primitive being drawn (ala glBegin) */
+ GLboolean SpecularVertexAdd; /**< Add specular/secondary color per vertex */
void (*InvalidateState)( GLcontext *ctx, GLbitfield new_state );
@@ -221,7 +222,7 @@ typedef struct
/** Buffer for saving the sampled texture colors.
* Needed for GL_ARB_texture_env_crossbar implementation.
*/
- GLchan *TexelBuffer;
+ GLfloat *TexelBuffer;
validate_texture_image_func ValidateTextureImage;
@@ -238,21 +239,43 @@ extern void
_swrast_update_texture_samplers(GLcontext *ctx);
-#define SWRAST_CONTEXT(ctx) ((SWcontext *)ctx->swrast_context)
+/** Return SWcontext for the given GLcontext */
+static INLINE SWcontext *
+SWRAST_CONTEXT(GLcontext *ctx)
+{
+ return (SWcontext *) ctx->swrast_context;
+}
+
+/** const version of above */
+static INLINE const SWcontext *
+CONST_SWRAST_CONTEXT(const GLcontext *ctx)
+{
+ return (const SWcontext *) ctx->swrast_context;
+}
+
+
+/**
+ * Called prior to framebuffer reading/writing.
+ * For drivers that rely on swrast for fallback rendering, this is the
+ * driver's opportunity to map renderbuffers and textures.
+ */
+static INLINE void
+swrast_render_start(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (swrast->Driver.SpanRenderStart)
+ swrast->Driver.SpanRenderStart(ctx);
+}
-#define RENDER_START(SWctx, GLctx) \
- do { \
- if ((SWctx)->Driver.SpanRenderStart) { \
- (*(SWctx)->Driver.SpanRenderStart)(GLctx); \
- } \
- } while (0)
-#define RENDER_FINISH(SWctx, GLctx) \
- do { \
- if ((SWctx)->Driver.SpanRenderFinish) { \
- (*(SWctx)->Driver.SpanRenderFinish)(GLctx); \
- } \
- } while (0)
+/** Called after framebuffer reading/writing */
+static INLINE void
+swrast_render_finish(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (swrast->Driver.SpanRenderFinish)
+ swrast->Driver.SpanRenderFinish(ctx);
+}
@@ -267,6 +290,34 @@ _swrast_update_texture_samplers(GLcontext *ctx);
/*
+ * Fixed point arithmetic macros
+ */
+#ifndef FIXED_FRAC_BITS
+#define FIXED_FRAC_BITS 11
+#endif
+
+#define FIXED_SHIFT FIXED_FRAC_BITS
+#define FIXED_ONE (1 << FIXED_SHIFT)
+#define FIXED_HALF (1 << (FIXED_SHIFT-1))
+#define FIXED_FRAC_MASK (FIXED_ONE - 1)
+#define FIXED_INT_MASK (~FIXED_FRAC_MASK)
+#define FIXED_EPSILON 1
+#define FIXED_SCALE ((float) FIXED_ONE)
+#define FIXED_DBL_SCALE ((double) FIXED_ONE)
+#define FloatToFixed(X) (IROUND((X) * FIXED_SCALE))
+#define FixedToDouble(X) ((X) * (1.0 / FIXED_DBL_SCALE))
+#define IntToFixed(I) ((I) << FIXED_SHIFT)
+#define FixedToInt(X) ((X) >> FIXED_SHIFT)
+#define FixedToUns(X) (((unsigned int)(X)) >> FIXED_SHIFT)
+#define FixedCeil(X) (((X) + FIXED_ONE - FIXED_EPSILON) & FIXED_INT_MASK)
+#define FixedFloor(X) ((X) & FIXED_INT_MASK)
+#define FixedToFloat(X) ((X) * (1.0F / FIXED_SCALE))
+#define PosFloatToFixed(X) FloatToFixed(X)
+#define SignedFloatToFixed(X) FloatToFixed(X)
+
+
+
+/*
* XXX these macros are just bandages for now in order to make
* CHAN_BITS==32 compile cleanly.
* These should probably go elsewhere at some point.
diff --git a/src/mesa/swrast/s_copypix.c b/src/mesa/swrast/s_copypix.c
index fc5990b261..8f2db3afbb 100644
--- a/src/mesa/swrast/s_copypix.c
+++ b/src/mesa/swrast/s_copypix.c
@@ -40,6 +40,8 @@
#include "s_zoom.h"
+#if FEATURE_drawpix
+
/**
* Determine if there's overlap in an image copy.
@@ -899,7 +901,7 @@ _swrast_CopyPixels( GLcontext *ctx,
GLint destx, GLint desty, GLenum type )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
- RENDER_START(swrast,ctx);
+ swrast_render_start(ctx);
if (swrast->NewState)
_swrast_validate_derived( ctx );
@@ -928,5 +930,8 @@ _swrast_CopyPixels( GLcontext *ctx,
}
}
- RENDER_FINISH(swrast,ctx);
+ swrast_render_finish(ctx);
}
+
+
+#endif /* FEATURE_drawpix */
diff --git a/src/mesa/swrast/s_depth.c b/src/mesa/swrast/s_depth.c
index 26e23f02d5..1a428fb1a2 100644
--- a/src/mesa/swrast/s_depth.c
+++ b/src/mesa/swrast/s_depth.c
@@ -497,6 +497,33 @@ depth_test_span32( GLcontext *ctx, GLuint n,
return passed;
}
+/* Apply ARB_depth_clamp to span of fragments. */
+void
+_swrast_depth_clamp_span( GLcontext *ctx, SWspan *span )
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_DepthBuffer;
+ const GLuint count = span->end;
+ GLuint *zValues = span->array->z;
+ GLuint near, far;
+ int i;
+
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ near = FLOAT_TO_UINT(ctx->Viewport.Near);
+ far = FLOAT_TO_UINT(ctx->Viewport.Far);
+ } else {
+ assert(rb->DataType == GL_UNSIGNED_INT);
+ CLAMPED_FLOAT_TO_USHORT(near, ctx->Viewport.Near);
+ CLAMPED_FLOAT_TO_USHORT(far, ctx->Viewport.Far);
+ }
+ for (i = 0; i < count; i++) {
+ if (zValues[i] < near)
+ zValues[i] = near;
+ if (zValues[i] > far)
+ zValues[i] = far;
+ }
+}
+
/*
diff --git a/src/mesa/swrast/s_depth.h b/src/mesa/swrast/s_depth.h
index 3688625683..7eae366742 100644
--- a/src/mesa/swrast/s_depth.h
+++ b/src/mesa/swrast/s_depth.h
@@ -33,6 +33,8 @@
extern GLuint
_swrast_depth_test_span( GLcontext *ctx, SWspan *span);
+extern void
+_swrast_depth_clamp_span( GLcontext *ctx, SWspan *span );
extern GLboolean
_swrast_depth_bounds_test( GLcontext *ctx, SWspan *span );
diff --git a/src/mesa/swrast/s_drawpix.c b/src/mesa/swrast/s_drawpix.c
index 7af3e3dad1..6ce449b2a8 100644
--- a/src/mesa/swrast/s_drawpix.c
+++ b/src/mesa/swrast/s_drawpix.c
@@ -39,6 +39,8 @@
#include "s_zoom.h"
+#if FEATURE_drawpix
+
/**
* Try to do a fast and simple RGB(a) glDrawPixels.
@@ -829,8 +831,19 @@ _swrast_DrawPixels( GLcontext *ctx,
const GLvoid *pixels )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLboolean save_vp_override = ctx->VertexProgram._Overriden;
+
+ /* We are creating fragments directly, without going through vertex
+ * programs.
+ *
+ * This override flag tells the fragment processing code that its input
+ * comes from a non-standard source, and it may therefore not rely on
+ * optimizations that assume e.g. constant color if there is no color
+ * vertex array.
+ */
+ _mesa_set_vp_override(ctx, GL_TRUE);
- RENDER_START(swrast,ctx);
+ swrast_render_start(ctx);
if (ctx->NewState)
_mesa_update_state(ctx);
@@ -838,9 +851,10 @@ _swrast_DrawPixels( GLcontext *ctx,
if (swrast->NewState)
_swrast_validate_derived( ctx );
- pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels);
+ pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
if (!pixels) {
- RENDER_FINISH(swrast,ctx);
+ swrast_render_finish(ctx);
+ _mesa_set_vp_override(ctx, save_vp_override);
return;
}
@@ -879,60 +893,11 @@ _swrast_DrawPixels( GLcontext *ctx,
/* don't return yet, clean-up */
}
- RENDER_FINISH(swrast,ctx);
+ swrast_render_finish(ctx);
+ _mesa_set_vp_override(ctx, save_vp_override);
- _mesa_unmap_drapix_pbo(ctx, unpack);
+ _mesa_unmap_pbo_source(ctx, unpack);
}
-
-#if 0 /* experimental */
-/*
- * Execute glDrawDepthPixelsMESA().
- */
-void
-_swrast_DrawDepthPixelsMESA( GLcontext *ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height,
- GLenum colorFormat, GLenum colorType,
- const GLvoid *colors,
- GLenum depthType, const GLvoid *depths,
- const struct gl_pixelstore_attrib *unpack )
-{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
-
- if (swrast->NewState)
- _swrast_validate_derived( ctx );
-
- RENDER_START(swrast,ctx);
-
- switch (colorFormat) {
- case GL_COLOR_INDEX:
- if (ctx->Visual.rgbMode)
- draw_rgba_pixels(ctx, x,y, width, height, colorFormat, colorType,
- unpack, colors);
- else
- draw_index_pixels(ctx, x, y, width, height, colorType,
- unpack, colors);
- break;
- case GL_RED:
- case GL_GREEN:
- case GL_BLUE:
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_RGB:
- case GL_BGR:
- case GL_RGBA:
- case GL_BGRA:
- case GL_ABGR_EXT:
- draw_rgba_pixels(ctx, x, y, width, height, colorFormat, colorType,
- unpack, colors);
- break;
- default:
- _mesa_problem(ctx, "unexpected format in glDrawDepthPixelsMESA");
- }
-
- RENDER_FINISH(swrast,ctx);
-}
-#endif
+#endif /* FEATURE_drawpix */
diff --git a/src/mesa/swrast/s_feedback.c b/src/mesa/swrast/s_feedback.c
index aa79531277..0eea1d0c3b 100644
--- a/src/mesa/swrast/s_feedback.c
+++ b/src/mesa/swrast/s_feedback.c
@@ -34,6 +34,8 @@
#include "s_triangle.h"
+#if FEATURE_feedback
+
static void
feedback_vertex(GLcontext * ctx, const SWvertex * v, const SWvertex * pv)
@@ -58,9 +60,9 @@ void
_swrast_feedback_triangle(GLcontext *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2)
{
- if (_swrast_culltriangle(ctx, v0, v1, v2)) {
- FEEDBACK_TOKEN(ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN);
- FEEDBACK_TOKEN(ctx, (GLfloat) 3); /* three vertices */
+ if (!_swrast_culltriangle(ctx, v0, v1, v2)) {
+ _mesa_feedback_token(ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN);
+ _mesa_feedback_token(ctx, (GLfloat) 3); /* three vertices */
if (ctx->Light.ShadeModel == GL_SMOOTH) {
feedback_vertex(ctx, v0, v0);
@@ -86,7 +88,7 @@ _swrast_feedback_line(GLcontext *ctx, const SWvertex *v0,
if (swrast->StippleCounter == 0)
token = GL_LINE_RESET_TOKEN;
- FEEDBACK_TOKEN(ctx, (GLfloat) (GLint) token);
+ _mesa_feedback_token(ctx, (GLfloat) (GLint) token);
if (ctx->Light.ShadeModel == GL_SMOOTH) {
feedback_vertex(ctx, v0, v0);
@@ -104,7 +106,7 @@ _swrast_feedback_line(GLcontext *ctx, const SWvertex *v0,
void
_swrast_feedback_point(GLcontext *ctx, const SWvertex *v)
{
- FEEDBACK_TOKEN(ctx, (GLfloat) (GLint) GL_POINT_TOKEN);
+ _mesa_feedback_token(ctx, (GLfloat) (GLint) GL_POINT_TOKEN);
feedback_vertex(ctx, v, v);
}
@@ -113,7 +115,7 @@ void
_swrast_select_triangle(GLcontext *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2)
{
- if (_swrast_culltriangle(ctx, v0, v1, v2)) {
+ if (!_swrast_culltriangle(ctx, v0, v1, v2)) {
const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
_mesa_update_hitflag( ctx, v0->attrib[FRAG_ATTRIB_WPOS][2] * zs );
@@ -138,3 +140,6 @@ _swrast_select_point(GLcontext *ctx, const SWvertex *v)
const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
_mesa_update_hitflag( ctx, v->attrib[FRAG_ATTRIB_WPOS][2] * zs );
}
+
+
+#endif /* FEATURE_feedback */
diff --git a/src/mesa/swrast/s_feedback.h b/src/mesa/swrast/s_feedback.h
index 9feab75dbb..994984f6f7 100644
--- a/src/mesa/swrast/s_feedback.h
+++ b/src/mesa/swrast/s_feedback.h
@@ -31,6 +31,8 @@
#include "swrast.h"
+#if FEATURE_feedback
+
extern void _swrast_feedback_point( GLcontext *ctx, const SWvertex *v );
extern void _swrast_feedback_line( GLcontext *ctx,
@@ -46,5 +48,48 @@ extern void _swrast_select_line( GLcontext *ctx,
extern void _swrast_select_triangle( GLcontext *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2 );
+#else /* FEATURE_feedback */
+
+static INLINE void
+_swrast_feedback_point( GLcontext *ctx, const SWvertex *v )
+{
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_swrast_feedback_line( GLcontext *ctx,
+ const SWvertex *v1, const SWvertex *v2 )
+{
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_swrast_feedback_triangle( GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1, const SWvertex *v2 )
+{
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_swrast_select_point( GLcontext *ctx, const SWvertex *v )
+{
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_swrast_select_line( GLcontext *ctx,
+ const SWvertex *v1, const SWvertex *v2 )
+{
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_swrast_select_triangle( GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1, const SWvertex *v2 )
+{
+ ASSERT_NO_FEATURE();
+}
#endif
+
+#endif /* S_FEEDBACK_H */
diff --git a/src/mesa/swrast/s_fog.c b/src/mesa/swrast/s_fog.c
index b9ba265db6..77ed0cfef9 100644
--- a/src/mesa/swrast/s_fog.c
+++ b/src/mesa/swrast/s_fog.c
@@ -164,7 +164,7 @@ else { \
void
_swrast_fog_rgba_span( const GLcontext *ctx, SWspan *span )
{
- const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const SWcontext *swrast = CONST_SWRAST_CONTEXT(ctx);
GLfloat rFog, gFog, bFog;
ASSERT(swrast->_FogEnabled);
@@ -283,7 +283,7 @@ _swrast_fog_rgba_span( const GLcontext *ctx, SWspan *span )
void
_swrast_fog_ci_span( const GLcontext *ctx, SWspan *span )
{
- const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const SWcontext *swrast = CONST_SWRAST_CONTEXT(ctx);
const GLuint fogIndex = (GLuint) ctx->Fog.Index;
GLuint *index = span->array->index;
diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c
index 525cf9d724..613a91b0ec 100644
--- a/src/mesa/swrast/s_fragprog.c
+++ b/src/mesa/swrast/s_fragprog.c
@@ -33,6 +33,32 @@
/**
+ * Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel'
+ * and return results in 'colorOut'.
+ */
+static INLINE void
+swizzle_texel(const GLfloat texel[4], GLfloat colorOut[4], GLuint swizzle)
+{
+ if (swizzle == SWIZZLE_NOOP) {
+ COPY_4V(colorOut, texel);
+ }
+ else {
+ GLfloat vector[6];
+ vector[SWIZZLE_X] = texel[0];
+ vector[SWIZZLE_Y] = texel[1];
+ vector[SWIZZLE_Z] = texel[2];
+ vector[SWIZZLE_W] = texel[3];
+ vector[SWIZZLE_ZERO] = 0.0F;
+ vector[SWIZZLE_ONE] = 1.0F;
+ colorOut[0] = vector[GET_SWZ(swizzle, 0)];
+ colorOut[1] = vector[GET_SWZ(swizzle, 1)];
+ colorOut[2] = vector[GET_SWZ(swizzle, 2)];
+ colorOut[3] = vector[GET_SWZ(swizzle, 3)];
+ }
+}
+
+
+/**
* Fetch a texel with given lod.
* Called via machine->FetchTexelLod()
*/
@@ -40,20 +66,22 @@ static void
fetch_texel_lod( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
GLuint unit, GLfloat color[4] )
{
- GLchan rgba[4];
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
- if (texObj)
+ if (texObj) {
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLfloat rgba[4];
+
lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod);
- /* XXX use a float-valued TextureSample routine here!!! */
- swrast->TextureSample[unit](ctx, texObj, 1, (const GLfloat (*)[4]) texcoord,
- &lambda, &rgba);
- color[0] = CHAN_TO_FLOAT(rgba[0]);
- color[1] = CHAN_TO_FLOAT(rgba[1]);
- color[2] = CHAN_TO_FLOAT(rgba[2]);
- color[3] = CHAN_TO_FLOAT(rgba[3]);
+ swrast->TextureSample[unit](ctx, texObj, 1,
+ (const GLfloat (*)[4]) texcoord,
+ &lambda, &rgba);
+ swizzle_texel(rgba, color, texObj->_Swizzle);
+ }
+ else {
+ ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
+ }
}
@@ -69,13 +97,14 @@ fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4],
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
- GLfloat lambda;
- GLchan rgba[4];
if (texObj) {
- const struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
+ const struct gl_texture_image *texImg =
+ texObj->Image[0][texObj->BaseLevel];
const GLfloat texW = (GLfloat) texImg->WidthScale;
const GLfloat texH = (GLfloat) texImg->HeightScale;
+ GLfloat lambda;
+ GLfloat rgba[4];
lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
texdx[1], texdy[1], /* dt/dx, dt/dy */
@@ -85,14 +114,15 @@ fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4],
1.0F / texcoord[3]) + lodBias;
lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod);
- }
- swrast->TextureSample[unit](ctx, texObj, 1, (const GLfloat (*)[4]) texcoord,
- &lambda, &rgba);
- color[0] = CHAN_TO_FLOAT(rgba[0]);
- color[1] = CHAN_TO_FLOAT(rgba[1]);
- color[2] = CHAN_TO_FLOAT(rgba[2]);
- color[3] = CHAN_TO_FLOAT(rgba[3]);
+ swrast->TextureSample[unit](ctx, texObj, 1,
+ (const GLfloat (*)[4]) texcoord,
+ &lambda, &rgba);
+ swizzle_texel(rgba, color, texObj->_Swizzle);
+ }
+ else {
+ ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
+ }
}
@@ -127,9 +157,8 @@ init_machine(GLcontext *ctx, struct gl_program_machine *machine,
/* if running a GLSL program (not ARB_fragment_program) */
if (ctx->Shader.CurrentProgram) {
- /* Store front/back facing value in register FOGC.Y */
- machine->Attribs[FRAG_ATTRIB_FOGC][col][1] = 1.0 - span->facing;
- /* Note FOGC.ZW is gl_PointCoord if drawing a sprite */
+ /* Store front/back facing value */
+ machine->Attribs[FRAG_ATTRIB_FACE][col][0] = 1.0 - span->facing;
}
machine->CurElement = col;
@@ -167,9 +196,9 @@ run_program(GLcontext *ctx, SWspan *span, GLuint start, GLuint end)
if (_mesa_execute_program(ctx, &program->Base, machine)) {
/* Store result color */
- if (outputsWritten & (1 << FRAG_RESULT_COLR)) {
+ if (outputsWritten & (1 << FRAG_RESULT_COLOR)) {
COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i],
- machine->Outputs[FRAG_RESULT_COLR]);
+ machine->Outputs[FRAG_RESULT_COLOR]);
}
else {
/* Multiple drawbuffers / render targets
@@ -186,8 +215,8 @@ run_program(GLcontext *ctx, SWspan *span, GLuint start, GLuint end)
}
/* Store result depth/z */
- if (outputsWritten & (1 << FRAG_RESULT_DEPR)) {
- const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPR][2];
+ if (outputsWritten & (1 << FRAG_RESULT_DEPTH)) {
+ const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPTH][2];
if (depth <= 0.0)
span->array->z[i] = 0;
else if (depth >= 1.0)
@@ -220,20 +249,16 @@ _swrast_exec_fragment_program( GLcontext *ctx, SWspan *span )
ASSERT(span->array->ChanType == GL_FLOAT);
}
- ctx->_CurrentProgram = GL_FRAGMENT_PROGRAM_ARB; /* or NV, doesn't matter */
-
run_program(ctx, span, 0, span->end);
- if (program->Base.OutputsWritten & (1 << FRAG_RESULT_COLR)) {
+ if (program->Base.OutputsWritten & (1 << FRAG_RESULT_COLOR)) {
span->interpMask &= ~SPAN_RGBA;
span->arrayMask |= SPAN_RGBA;
}
- if (program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR)) {
+ if (program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH)) {
span->interpMask &= ~SPAN_Z;
span->arrayMask |= SPAN_Z;
}
-
- ctx->_CurrentProgram = 0;
}
diff --git a/src/mesa/swrast/s_imaging.c b/src/mesa/swrast/s_imaging.c
index 591857c342..7cc97b7f03 100644
--- a/src/mesa/swrast/s_imaging.c
+++ b/src/mesa/swrast/s_imaging.c
@@ -34,12 +34,14 @@
#include "s_span.h"
+#if FEATURE_colortable
+
+
void
_swrast_CopyColorTable( GLcontext *ctx,
GLenum target, GLenum internalformat,
GLint x, GLint y, GLsizei width)
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLchan data[MAX_WIDTH][4];
struct gl_buffer_object *bufferSave;
@@ -51,17 +53,17 @@ _swrast_CopyColorTable( GLcontext *ctx,
if (width > MAX_WIDTH)
width = MAX_WIDTH;
- RENDER_START( swrast, ctx );
+ swrast_render_start(ctx);
/* read the data from framebuffer */
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, x, y, CHAN_TYPE, data );
- RENDER_FINISH(swrast,ctx);
+ swrast_render_finish(ctx);
/* save PBO binding */
bufferSave = ctx->Unpack.BufferObj;
- ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
_mesa_ColorTable(target, internalformat, width, GL_RGBA, CHAN_TYPE, data);
@@ -74,7 +76,6 @@ void
_swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
GLint x, GLint y, GLsizei width)
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLchan data[MAX_WIDTH][4];
struct gl_buffer_object *bufferSave;
@@ -86,17 +87,17 @@ _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
if (width > MAX_WIDTH)
width = MAX_WIDTH;
- RENDER_START( swrast, ctx );
+ swrast_render_start(ctx);
/* read the data from framebuffer */
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, x, y, CHAN_TYPE, data );
- RENDER_FINISH(swrast,ctx);
+ swrast_render_finish(ctx);
/* save PBO binding */
bufferSave = ctx->Unpack.BufferObj;
- ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
_mesa_ColorSubTable(target, start, width, GL_RGBA, CHAN_TYPE, data);
@@ -105,12 +106,17 @@ _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
}
+#endif /* FEATURE_colortable */
+
+
+#if FEATURE_convolve
+
+
void
_swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
GLenum internalFormat,
GLint x, GLint y, GLsizei width)
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLchan rgba[MAX_CONVOLUTION_WIDTH][4];
struct gl_buffer_object *bufferSave;
@@ -119,17 +125,17 @@ _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
return;
}
- RENDER_START( swrast, ctx );
+ swrast_render_start(ctx);
/* read the data from framebuffer */
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, x, y, CHAN_TYPE, rgba );
- RENDER_FINISH( swrast, ctx );
+ swrast_render_finish(ctx);
/* save PBO binding */
bufferSave = ctx->Unpack.BufferObj;
- ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
/* store as convolution filter */
_mesa_ConvolutionFilter1D(target, internalFormat, width,
@@ -145,7 +151,6 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height)
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_pixelstore_attrib packSave;
GLchan rgba[MAX_CONVOLUTION_HEIGHT][MAX_CONVOLUTION_WIDTH][4];
GLint i;
@@ -156,7 +161,7 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
return;
}
- RENDER_START(swrast,ctx);
+ swrast_render_start(ctx);
/* read pixels from framebuffer */
for (i = 0; i < height; i++) {
@@ -164,7 +169,7 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
width, x, y + i, CHAN_TYPE, rgba[i] );
}
- RENDER_FINISH(swrast,ctx);
+ swrast_render_finish(ctx);
/*
* HACK: save & restore context state so we can store this as a
@@ -182,12 +187,12 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
ctx->Unpack.SkipImages = 0;
ctx->Unpack.SwapBytes = GL_FALSE;
ctx->Unpack.LsbFirst = GL_FALSE;
- ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
ctx->NewState |= _NEW_PACKUNPACK;
/* save PBO binding */
bufferSave = ctx->Unpack.BufferObj;
- ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
_mesa_ConvolutionFilter2D(target, internalFormat, width, height,
GL_RGBA, CHAN_TYPE, rgba);
@@ -198,3 +203,6 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
ctx->Unpack = packSave; /* restore pixel packing params */
ctx->NewState |= _NEW_PACKUNPACK;
}
+
+
+#endif /* FEATURE_convolve */
diff --git a/src/mesa/swrast/s_points.c b/src/mesa/swrast/s_points.c
index 61ff4d0b84..50ec2063a5 100644
--- a/src/mesa/swrast/s_points.c
+++ b/src/mesa/swrast/s_points.c
@@ -139,9 +139,10 @@ sprite_point(GLcontext *ctx, const SWvertex *vert)
}
ATTRIB_LOOP_BEGIN
- if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0) {
+ if (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) {
+ /* a texcoord attribute */
const GLuint u = attr - FRAG_ATTRIB_TEX0;
- /* a texcoord */
+ ASSERT(u < Elements(ctx->Point.CoordReplace));
if (ctx->Point.CoordReplace[u]) {
tCoords[numTcoords++] = attr;
@@ -170,15 +171,15 @@ sprite_point(GLcontext *ctx, const SWvertex *vert)
continue;
}
}
- else if (attr == FRAG_ATTRIB_FOGC) {
- /* GLSL gl_PointCoord is stored in fog.zw */
- span.attrStart[FRAG_ATTRIB_FOGC][2] = 0.0;
- span.attrStart[FRAG_ATTRIB_FOGC][3] = 0.0; /* t0 set below */
- span.attrStepX[FRAG_ATTRIB_FOGC][2] = dsdx;
- span.attrStepX[FRAG_ATTRIB_FOGC][3] = 0.0;
- span.attrStepY[FRAG_ATTRIB_FOGC][2] = 0.0;
- span.attrStepY[FRAG_ATTRIB_FOGC][3] = dtdy;
- tCoords[numTcoords++] = FRAG_ATTRIB_FOGC;
+ else if (attr == FRAG_ATTRIB_PNTC) {
+ /* GLSL gl_PointCoord.xy (.zw undefined) */
+ span.attrStart[FRAG_ATTRIB_PNTC][0] = 0.0;
+ span.attrStart[FRAG_ATTRIB_PNTC][1] = 0.0; /* t0 set below */
+ span.attrStepX[FRAG_ATTRIB_PNTC][0] = dsdx;
+ span.attrStepX[FRAG_ATTRIB_PNTC][1] = 0.0;
+ span.attrStepY[FRAG_ATTRIB_PNTC][0] = 0.0;
+ span.attrStepY[FRAG_ATTRIB_PNTC][1] = dtdy;
+ tCoords[numTcoords++] = FRAG_ATTRIB_PNTC;
continue;
}
/* use vertex's texcoord/attrib */
@@ -221,10 +222,7 @@ sprite_point(GLcontext *ctx, const SWvertex *vert)
GLuint i;
/* setup texcoord T for this row */
for (i = 0; i < numTcoords; i++) {
- if (tCoords[i] == FRAG_ATTRIB_FOGC)
- span.attrStart[FRAG_ATTRIB_FOGC][3] = tcoord;
- else
- span.attrStart[tCoords[i]][1] = tcoord;
+ span.attrStart[tCoords[i]][1] = tcoord;
}
/* these might get changed by span clipping */
@@ -570,6 +568,9 @@ void
_swrast_choose_point(GLcontext *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLfloat size = CLAMP(ctx->Point.Size,
+ ctx->Point.MinSize,
+ ctx->Point.MaxSize);
if (ctx->RenderMode == GL_RENDER) {
if (ctx->Point.PointSprite) {
@@ -578,7 +579,7 @@ _swrast_choose_point(GLcontext *ctx)
else if (ctx->Point.SmoothFlag) {
swrast->Point = smooth_point;
}
- else if (ctx->Point.Size > 1.0 ||
+ else if (size > 1.0 ||
ctx->Point._Attenuated ||
ctx->VertexProgram.PointSizeEnabled) {
swrast->Point = large_point;
diff --git a/src/mesa/swrast/s_readpix.c b/src/mesa/swrast/s_readpix.c
index f263045170..48b9408d24 100644
--- a/src/mesa/swrast/s_readpix.c
+++ b/src/mesa/swrast/s_readpix.c
@@ -555,11 +555,11 @@ _swrast_ReadPixels( GLcontext *ctx,
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_pixelstore_attrib clippedPacking = *packing;
- /* Need to do RENDER_START before clipping or anything else since this
- * is where a driver may grab the hw lock and get an updated window
- * size.
+ /* Need to do swrast_render_start() before clipping or anything else
+ * since this is where a driver may grab the hw lock and get an updated
+ * window size.
*/
- RENDER_START(swrast, ctx);
+ swrast_render_start(ctx);
if (ctx->NewState)
_mesa_update_state(ctx);
@@ -570,11 +570,11 @@ _swrast_ReadPixels( GLcontext *ctx,
/* Do all needed clipping here, so that we can forget about it later */
if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
/* The ReadPixels region is totally outside the window bounds */
- RENDER_FINISH(swrast, ctx);
+ swrast_render_finish(ctx);
return;
}
- pixels = _mesa_map_readpix_pbo(ctx, &clippedPacking, pixels);
+ pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels);
if (!pixels)
return;
@@ -614,7 +614,7 @@ _swrast_ReadPixels( GLcontext *ctx,
/* don't return yet, clean-up */
}
- RENDER_FINISH(swrast, ctx);
+ swrast_render_finish(ctx);
- _mesa_unmap_readpix_pbo(ctx, &clippedPacking);
+ _mesa_unmap_pbo_dest(ctx, &clippedPacking);
}
diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c
index 7f9cc64bb2..704230d1d7 100644
--- a/src/mesa/swrast/s_span.c
+++ b/src/mesa/swrast/s_span.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.5
*
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -188,10 +189,10 @@ interpolate_active_attribs(GLcontext *ctx, SWspan *span, GLbitfield attrMask)
const GLfloat dv1dx = span->attrStepX[attr][1];
const GLfloat dv2dx = span->attrStepX[attr][2];
const GLfloat dv3dx = span->attrStepX[attr][3];
- GLfloat v0 = span->attrStart[attr][0];
- GLfloat v1 = span->attrStart[attr][1];
- GLfloat v2 = span->attrStart[attr][2];
- GLfloat v3 = span->attrStart[attr][3];
+ GLfloat v0 = span->attrStart[attr][0] + span->leftClip * dv0dx;
+ GLfloat v1 = span->attrStart[attr][1] + span->leftClip * dv1dx;
+ GLfloat v2 = span->attrStart[attr][2] + span->leftClip * dv2dx;
+ GLfloat v3 = span->attrStart[attr][3] + span->leftClip * dv3dx;
GLuint k;
for (k = 0; k < span->end; k++) {
const GLfloat invW = 1.0f / w;
@@ -442,11 +443,10 @@ _swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
* Compute mipmap LOD from partial derivatives.
* This the ideal solution, as given in the OpenGL spec.
*/
-#if 0
-static GLfloat
-compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
- GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
- GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
+GLfloat
+_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
+ GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
+ GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
{
GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
@@ -458,13 +458,13 @@ compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
GLfloat lambda = LOG2(rho);
return lambda;
}
-#endif
/**
* Compute mipmap LOD from partial derivatives.
* This is a faster approximation than above function.
*/
+#if 0
GLfloat
_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
@@ -485,6 +485,7 @@ _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
lambda = LOG2(rho);
return lambda;
}
+#endif
/**
@@ -521,10 +522,10 @@ interpolate_texcoords(GLcontext *ctx, SWspan *span)
const GLfloat drdx = span->attrStepX[attr][2];
const GLfloat dqdx = span->attrStepX[attr][3];
const GLfloat dqdy = span->attrStepY[attr][3];
- GLfloat s = span->attrStart[attr][0];
- GLfloat t = span->attrStart[attr][1];
- GLfloat r = span->attrStart[attr][2];
- GLfloat q = span->attrStart[attr][3];
+ GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx;
+ GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx;
+ GLfloat r = span->attrStart[attr][2] + span->leftClip * drdx;
+ GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx;
if (obj) {
const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
@@ -546,7 +547,7 @@ interpolate_texcoords(GLcontext *ctx, SWspan *span)
|| ctx->ATIFragmentShader._Enabled) {
/* do perspective correction but don't divide s, t, r by q */
const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
- GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
+ GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
for (i = 0; i < span->end; i++) {
const GLfloat invW = 1.0F / w;
texcoord[i][0] = s * invW;
@@ -587,7 +588,7 @@ interpolate_texcoords(GLcontext *ctx, SWspan *span)
ctx->ATIFragmentShader._Enabled) {
/* do perspective correction but don't divide s, t, r by q */
const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
- GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
+ GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
for (i = 0; i < span->end; i++) {
const GLfloat invW = 1.0F / w;
texcoord[i][0] = s * invW;
@@ -660,8 +661,8 @@ interpolate_wpos(GLcontext *ctx, SWspan *span)
}
}
- w = span->attrStart[FRAG_ATTRIB_WPOS][3];
dw = span->attrStepX[FRAG_ATTRIB_WPOS][3];
+ w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dw;
for (i = 0; i < span->end; i++) {
wpos[i][2] = (GLfloat) span->array->z[i] * zScale;
wpos[i][3] = w;
@@ -726,6 +727,8 @@ clip_span( GLcontext *ctx, SWspan *span )
const GLint ymin = ctx->DrawBuffer->_Ymin;
const GLint ymax = ctx->DrawBuffer->_Ymax;
+ span->leftClip = 0;
+
if (span->arrayMask & SPAN_XY) {
/* arrays of x/y pixel coords */
const GLint *x = span->array->x;
@@ -753,7 +756,7 @@ clip_span( GLcontext *ctx, SWspan *span )
/* horizontal span of pixels */
const GLint x = span->x;
const GLint y = span->y;
- const GLint n = span->end;
+ GLint n = span->end;
/* Trivial rejection tests */
if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
@@ -761,18 +764,44 @@ clip_span( GLcontext *ctx, SWspan *span )
return GL_FALSE; /* all pixels clipped */
}
+ /* Clip to right */
+ if (x + n > xmax) {
+ ASSERT(x < xmax);
+ n = span->end = xmax - x;
+ }
+
/* Clip to the left */
if (x < xmin) {
+ const GLint leftClip = xmin - x;
+ GLuint i;
+
+ ASSERT(leftClip > 0);
ASSERT(x + n > xmin);
+
+ /* Clip 'leftClip' pixels from the left side.
+ * The span->leftClip field will be applied when we interpolate
+ * fragment attributes.
+ * For arrays of values, shift them left.
+ */
+ for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
+ if (span->arrayAttribs & (1 << i)) {
+ /* shift array elements left by 'leftClip' */
+ _mesa_memcpy(span->array->attribs[i],
+ span->array->attribs[i] + leftClip,
+ (n - leftClip) * 4 * sizeof(GLfloat));
+ }
+ }
+
+ span->leftClip = leftClip;
+ span->x = xmin;
+ span->end -= leftClip;
span->writeAll = GL_FALSE;
- _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
}
- /* Clip to right */
- if (x + n > xmax) {
- ASSERT(x < xmax);
- span->end = xmax - x;
- }
+ ASSERT(span->x >= xmin);
+ ASSERT(span->x + span->end <= xmax);
+ ASSERT(span->y >= ymin);
+ ASSERT(span->y < ymax);
return GL_TRUE; /* some pixels visible */
}
@@ -818,6 +847,12 @@ _swrast_write_index_span( GLcontext *ctx, SWspan *span)
}
}
+ if (!(span->arrayMask & SPAN_MASK)) {
+ /* post-clip sanity check */
+ assert(span->x >= 0);
+ assert(span->y >= 0);
+ }
+
/* Depth bounds test */
if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
if (!_swrast_depth_bounds_test(ctx, span)) {
@@ -845,12 +880,15 @@ _swrast_write_index_span( GLcontext *ctx, SWspan *span)
stipple_polygon_span(ctx, span);
}
+ if (ctx->Transform.DepthClamp)
+ _swrast_depth_clamp_span(ctx, span);
+
/* Stencil and Z testing */
- if (ctx->Depth.Test || ctx->Stencil.Enabled) {
+ if (ctx->Stencil._Enabled || ctx->Depth.Test) {
if (!(span->arrayMask & SPAN_Z))
_swrast_span_interpolate_z(ctx, span);
- if (ctx->Stencil.Enabled) {
+ if (ctx->Stencil._Enabled) {
if (!_swrast_stencil_and_ztest_span(ctx, span)) {
span->arrayMask = origArrayMask;
return;
@@ -866,7 +904,6 @@ _swrast_write_index_span( GLcontext *ctx, SWspan *span)
}
}
-#if FEATURE_ARB_occlusion_query
if (ctx->Query.CurrentOcclusionObject) {
/* update count of 'passed' fragments */
struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
@@ -874,7 +911,6 @@ _swrast_write_index_span( GLcontext *ctx, SWspan *span)
for (i = 0; i < span->end; i++)
q->Result += span->array->mask[i];
}
-#endif
/* we have to wait until after occlusion to do this test */
if (ctx->Color.IndexMask == 0) {
@@ -1211,7 +1247,7 @@ shade_texture_span(GLcontext *ctx, SWspan *span)
_swrast_exec_fragment_shader(ctx, span);
}
}
- else if (ctx->Texture._EnabledUnits) {
+ else if (ctx->Texture._EnabledCoordUnits) {
/* conventional texturing */
#if CHAN_BITS == 32
@@ -1250,7 +1286,7 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
void * const origRgba = span->array->rgba;
const GLboolean shader = (ctx->FragmentProgram._Current
|| ctx->ATIFragmentShader._Enabled);
- const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits;
+ const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits;
struct gl_framebuffer *fb = ctx->DrawBuffer;
/*
@@ -1262,7 +1298,6 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
span->primitive == GL_LINE ||
span->primitive == GL_POLYGON ||
span->primitive == GL_BITMAP);
- ASSERT(span->end <= MAX_WIDTH);
/* Fragment write masks */
if (span->arrayMask & SPAN_MASK) {
@@ -1275,15 +1310,16 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
}
/* Clip to window/scissor box */
- if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
- if (!clip_span(ctx, span)) {
- return;
- }
+ if (!clip_span(ctx, span)) {
+ return;
}
+ ASSERT(span->end <= MAX_WIDTH);
+
#ifdef DEBUG
/* Make sure all fragments are within window bounds */
if (span->arrayMask & SPAN_XY) {
+ /* array of pixel locations */
GLuint i;
for (i = 0; i < span->end; i++) {
if (span->array->mask[i]) {
@@ -1311,18 +1347,19 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
/* Do the alpha test */
if (ctx->Color.AlphaEnabled) {
if (!_swrast_alpha_test(ctx, span)) {
+ /* all fragments failed test */
goto end;
}
}
/* Stencil and Z testing */
- if (ctx->Stencil.Enabled || ctx->Depth.Test) {
+ if (ctx->Stencil._Enabled || ctx->Depth.Test) {
if (!(span->arrayMask & SPAN_Z))
_swrast_span_interpolate_z(ctx, span);
-
- if (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0) {
+ if (ctx->Stencil._Enabled) {
/* Combined Z/stencil tests */
if (!_swrast_stencil_and_ztest_span(ctx, span)) {
+ /* all fragments failed test */
goto end;
}
}
@@ -1331,12 +1368,12 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
ASSERT(ctx->Depth.Test);
ASSERT(span->arrayMask & SPAN_Z);
if (!_swrast_depth_test_span(ctx, span)) {
+ /* all fragments failed test */
goto end;
}
}
}
-#if FEATURE_ARB_occlusion_query
if (ctx->Query.CurrentOcclusionObject) {
/* update count of 'passed' fragments */
struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
@@ -1344,12 +1381,12 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
for (i = 0; i < span->end; i++)
q->Result += span->array->mask[i];
}
-#endif
/* We had to wait until now to check for glColorMask(0,0,0,0) because of
* the occlusion test.
*/
if (colorMask == 0x0) {
+ /* no colors to write */
goto end;
}
@@ -1373,12 +1410,14 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
ASSERT(span->arrayMask & SPAN_RGBA);
- if (!shader) {
- /* Add base and specular colors */
- if (ctx->Fog.ColorSumEnabled ||
- (ctx->Light.Enabled &&
- ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
- add_specular(ctx, span);
+ if (span->primitive == GL_BITMAP || !swrast->SpecularVertexAdd) {
+ /* Add primary and specular (diffuse + specular) colors */
+ if (!shader) {
+ if (ctx->Fog.ColorSumEnabled ||
+ (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
+ add_specular(ctx, span);
+ }
}
}
@@ -1399,11 +1438,17 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
}
/*
- * Write to renderbuffers
+ * Write to renderbuffers.
+ * Depending on glDrawBuffer() state and the which color outputs are
+ * written by the fragment shader, we may either replicate one color to
+ * all renderbuffers or write a different color to each renderbuffer.
+ * multiFragOutputs=TRUE for the later case.
*/
{
const GLuint numBuffers = fb->_NumColorDrawBuffers;
- const GLboolean multiFragOutputs = numBuffers > 1;
+ const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
+ const GLboolean multiFragOutputs =
+ (fp && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0));
GLuint buf;
for (buf = 0; buf < numBuffers; buf++) {
diff --git a/src/mesa/swrast/s_span.h b/src/mesa/swrast/s_span.h
index c4b47df58f..0eabae20e0 100644
--- a/src/mesa/swrast/s_span.h
+++ b/src/mesa/swrast/s_span.h
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 6.5
+ * Version: 7.5
*
- * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -106,6 +107,9 @@ typedef struct sw_span
/** Number of fragments in the span */
GLuint end;
+ /** for clipping left edge of spans */
+ GLuint leftClip;
+
/** This flag indicates that mask[] array is effectively filled with ones */
GLboolean writeAll;
@@ -165,6 +169,7 @@ do { \
(S).arrayMask = 0x0; \
(S).arrayAttribs = 0x0; \
(S).end = 0; \
+ (S).leftClip = 0; \
(S).facing = 0; \
(S).array = SWRAST_CONTEXT(ctx)->SpanArrays; \
} while (0)
diff --git a/src/mesa/swrast/s_stencil.c b/src/mesa/swrast/s_stencil.c
index c925922463..e9e9d3a4f1 100644
--- a/src/mesa/swrast/s_stencil.c
+++ b/src/mesa/swrast/s_stencil.c
@@ -231,8 +231,9 @@ do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
GLubyte fail[MAX_WIDTH];
GLboolean allfail = GL_FALSE;
GLuint i;
- GLstencil r, s;
const GLuint valueMask = ctx->Stencil.ValueMask[face];
+ const GLstencil r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
+ GLstencil s;
ASSERT(n <= MAX_WIDTH);
@@ -260,7 +261,6 @@ do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
allfail = GL_TRUE;
break;
case GL_LESS:
- r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
@@ -279,7 +279,6 @@ do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
}
break;
case GL_LEQUAL:
- r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
@@ -298,7 +297,6 @@ do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
}
break;
case GL_GREATER:
- r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
@@ -317,7 +315,6 @@ do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
}
break;
case GL_GEQUAL:
- r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
@@ -336,7 +333,6 @@ do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
}
break;
case GL_EQUAL:
- r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
@@ -355,7 +351,6 @@ do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
}
break;
case GL_NOTEQUAL:
- r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
for (i=0;i<n;i++) {
if (mask[i]) {
s = (GLstencil) (stencil[i] & valueMask);
@@ -997,10 +992,12 @@ stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face )
GLboolean
_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span)
{
+ const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
+
if (span->arrayMask & SPAN_XY)
- return stencil_and_ztest_pixels(ctx, span, span->facing);
+ return stencil_and_ztest_pixels(ctx, span, face);
else
- return stencil_and_ztest_span(ctx, span, span->facing);
+ return stencil_and_ztest_span(ctx, span, face);
}
diff --git a/src/mesa/swrast/s_texcombine.c b/src/mesa/swrast/s_texcombine.c
index 632d650007..889164b986 100644
--- a/src/mesa/swrast/s_texcombine.c
+++ b/src/mesa/swrast/s_texcombine.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 6.5.1
+ * Version: 7.5
*
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -28,116 +29,134 @@
#include "main/colormac.h"
#include "main/image.h"
#include "main/imports.h"
-#include "main/macros.h"
#include "main/pixel.h"
+#include "shader/prog_instruction.h"
#include "s_context.h"
#include "s_texcombine.h"
-#define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
-#define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
-#if CHAN_BITS == 32
-typedef GLfloat ChanTemp;
-#else
-typedef GLuint ChanTemp;
-#endif
+/**
+ * Pointer to array of float[4]
+ * This type makes the code below more concise and avoids a lot of casting.
+ */
+typedef float (*float4_array)[4];
+
+
+/**
+ * Return array of texels for given unit.
+ */
+static INLINE float4_array
+get_texel_array(SWcontext *swrast, GLuint unit)
+{
+ return (float4_array) (swrast->TexelBuffer + unit * MAX_WIDTH * 4);
+}
+
/**
- * Do texture application for GL_ARB/EXT_texture_env_combine.
- * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
- * GL_ATI_texture_env_combine3. Since "classic" texture environments are
- * implemented using GL_ARB_texture_env_combine-like state, this same function
- * is used for classic texture environment application as well.
+ * Do texture application for:
+ * GL_EXT_texture_env_combine
+ * GL_ARB_texture_env_combine
+ * GL_EXT_texture_env_dot3
+ * GL_ARB_texture_env_dot3
+ * GL_ATI_texture_env_combine3
+ * GL_NV_texture_env_combine4
+ * conventional GL texture env modes
*
* \param ctx rendering context
- * \param textureUnit the texture unit to apply
+ * \param unit the texture combiner unit
* \param n number of fragments to process (span width)
* \param primary_rgba incoming fragment color array
* \param texelBuffer pointer to texel colors for all texture units
*
- * \param rgba incoming colors, which get modified here
+ * \param rgba incoming/result fragment colors
*/
static void
-texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
- CONST GLchan (*primary_rgba)[4],
- CONST GLchan *texelBuffer,
- GLchan (*rgba)[4] )
+texture_combine( GLcontext *ctx, GLuint unit, GLuint n,
+ const float4_array primary_rgba,
+ const GLfloat *texelBuffer,
+ GLchan (*rgbaChan)[4] )
{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
- const GLchan (*argRGB [3])[4];
- const GLchan (*argA [3])[4];
- const GLuint RGBshift = textureUnit->_CurrentCombine->ScaleShiftRGB;
- const GLuint Ashift = textureUnit->_CurrentCombine->ScaleShiftA;
-#if CHAN_TYPE == GL_FLOAT
- const GLchan RGBmult = (GLfloat) (1 << RGBshift);
- const GLchan Amult = (GLfloat) (1 << Ashift);
-#else
- const GLint half = (CHAN_MAX + 1) / 2;
-#endif
- static const GLchan one[4] = { CHAN_MAX, CHAN_MAX, CHAN_MAX, CHAN_MAX };
- static const GLchan zero[4] = { 0, 0, 0, 0 };
- const GLuint numColorArgs = textureUnit->_CurrentCombine->_NumArgsRGB;
- const GLuint numAlphaArgs = textureUnit->_CurrentCombine->_NumArgsA;
- GLchan ccolor[3][MAX_WIDTH][4];
- GLuint i, j;
-
- ASSERT(ctx->Extensions.EXT_texture_env_combine ||
- ctx->Extensions.ARB_texture_env_combine);
- ASSERT(SWRAST_CONTEXT(ctx)->_AnyTextureCombine);
+ const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
+ float4_array argRGB[MAX_COMBINER_TERMS];
+ float4_array argA[MAX_COMBINER_TERMS];
+ const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
+ const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
+ const GLuint numArgsRGB = combine->_NumArgsRGB;
+ const GLuint numArgsA = combine->_NumArgsA;
+ GLfloat ccolor[MAX_COMBINER_TERMS][MAX_WIDTH][4]; /* temp color buffers */
+ GLfloat rgba[MAX_WIDTH][4];
+ GLuint i, term;
+
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
+ rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
+ rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
+ rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
+ }
/*
printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
- textureUnit->_CurrentCombine->ModeRGB,
- textureUnit->_CurrentCombine->ModeA,
- textureUnit->_CurrentCombine->SourceRGB[0],
- textureUnit->_CurrentCombine->SourceA[0],
- textureUnit->_CurrentCombine->SourceRGB[1],
- textureUnit->_CurrentCombine->SourceA[1]);
+ combine->ModeRGB,
+ combine->ModeA,
+ combine->SourceRGB[0],
+ combine->SourceA[0],
+ combine->SourceRGB[1],
+ combine->SourceA[1]);
*/
/*
- * Do operand setup for up to 3 operands. Loop over the terms.
+ * Do operand setup for up to 4 operands. Loop over the terms.
*/
- for (j = 0; j < numColorArgs; j++) {
- const GLenum srcRGB = textureUnit->_CurrentCombine->SourceRGB[j];
+ for (term = 0; term < numArgsRGB; term++) {
+ const GLenum srcRGB = combine->SourceRGB[term];
+ const GLenum operandRGB = combine->OperandRGB[term];
switch (srcRGB) {
case GL_TEXTURE:
- argRGB[j] = (const GLchan (*)[4])
- (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
+ argRGB[term] = get_texel_array(swrast, unit);
break;
case GL_PRIMARY_COLOR:
- argRGB[j] = primary_rgba;
+ argRGB[term] = primary_rgba;
break;
case GL_PREVIOUS:
- argRGB[j] = (const GLchan (*)[4]) rgba;
+ argRGB[term] = rgba;
break;
case GL_CONSTANT:
{
- GLchan (*c)[4] = ccolor[j];
- GLchan red, green, blue, alpha;
- UNCLAMPED_FLOAT_TO_CHAN(red, textureUnit->EnvColor[0]);
- UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
- UNCLAMPED_FLOAT_TO_CHAN(blue, textureUnit->EnvColor[2]);
- UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
+ float4_array c = ccolor[term];
+ GLfloat red = textureUnit->EnvColor[0];
+ GLfloat green = textureUnit->EnvColor[1];
+ GLfloat blue = textureUnit->EnvColor[2];
+ GLfloat alpha = textureUnit->EnvColor[3];
for (i = 0; i < n; i++) {
- c[i][RCOMP] = red;
- c[i][GCOMP] = green;
- c[i][BCOMP] = blue;
- c[i][ACOMP] = alpha;
+ ASSIGN_4V(c[i], red, green, blue, alpha);
}
- argRGB[j] = (const GLchan (*)[4]) ccolor[j];
+ argRGB[term] = ccolor[term];
}
break;
/* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
*/
case GL_ZERO:
- argRGB[j] = & zero;
+ {
+ float4_array c = ccolor[term];
+ for (i = 0; i < n; i++) {
+ ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ argRGB[term] = ccolor[term];
+ }
break;
case GL_ONE:
- argRGB[j] = & one;
+ {
+ float4_array c = ccolor[term];
+ for (i = 0; i < n; i++) {
+ ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
+ }
+ argRGB[term] = ccolor[term];
+ }
break;
default:
/* ARB_texture_env_crossbar source */
@@ -146,76 +165,88 @@ texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
return;
- argRGB[j] = (const GLchan (*)[4])
- (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
+ argRGB[term] = get_texel_array(swrast, srcUnit);
}
}
- if (textureUnit->_CurrentCombine->OperandRGB[j] != GL_SRC_COLOR) {
- const GLchan (*src)[4] = argRGB[j];
- GLchan (*dst)[4] = ccolor[j];
+ if (operandRGB != GL_SRC_COLOR) {
+ float4_array src = argRGB[term];
+ float4_array dst = ccolor[term];
- /* point to new arg[j] storage */
- argRGB[j] = (const GLchan (*)[4]) ccolor[j];
+ /* point to new arg[term] storage */
+ argRGB[term] = ccolor[term];
- if (textureUnit->_CurrentCombine->OperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
+ switch (operandRGB) {
+ case GL_ONE_MINUS_SRC_COLOR:
for (i = 0; i < n; i++) {
- dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP];
- dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP];
- dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP];
+ dst[i][RCOMP] = 1.0F - src[i][RCOMP];
+ dst[i][GCOMP] = 1.0F - src[i][GCOMP];
+ dst[i][BCOMP] = 1.0F - src[i][BCOMP];
}
- }
- else if (textureUnit->_CurrentCombine->OperandRGB[j] == GL_SRC_ALPHA) {
+ break;
+ case GL_SRC_ALPHA:
for (i = 0; i < n; i++) {
- dst[i][RCOMP] = src[i][ACOMP];
- dst[i][GCOMP] = src[i][ACOMP];
+ dst[i][RCOMP] =
+ dst[i][GCOMP] =
dst[i][BCOMP] = src[i][ACOMP];
}
- }
- else {
- ASSERT(textureUnit->_CurrentCombine->OperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
for (i = 0; i < n; i++) {
- dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
- dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
- dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP];
+ dst[i][RCOMP] =
+ dst[i][GCOMP] =
+ dst[i][BCOMP] = 1.0F - src[i][ACOMP];
}
+ break;
+ default:
+ _mesa_problem(ctx, "Bad operandRGB");
}
}
}
/*
- * Set up the argA[i] pointers
+ * Set up the argA[term] pointers
*/
- for (j = 0; j < numAlphaArgs; j++) {
- const GLenum srcA = textureUnit->_CurrentCombine->SourceA[j];
+ for (term = 0; term < numArgsA; term++) {
+ const GLenum srcA = combine->SourceA[term];
+ const GLenum operandA = combine->OperandA[term];
switch (srcA) {
case GL_TEXTURE:
- argA[j] = (const GLchan (*)[4])
- (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
+ argA[term] = get_texel_array(swrast, unit);
break;
case GL_PRIMARY_COLOR:
- argA[j] = primary_rgba;
+ argA[term] = primary_rgba;
break;
case GL_PREVIOUS:
- argA[j] = (const GLchan (*)[4]) rgba;
+ argA[term] = rgba;
break;
case GL_CONSTANT:
{
- GLchan alpha, (*c)[4] = ccolor[j];
- UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
+ float4_array c = ccolor[term];
+ GLfloat alpha = textureUnit->EnvColor[3];
for (i = 0; i < n; i++)
c[i][ACOMP] = alpha;
- argA[j] = (const GLchan (*)[4]) ccolor[j];
+ argA[term] = ccolor[term];
}
break;
/* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
*/
case GL_ZERO:
- argA[j] = & zero;
+ {
+ float4_array c = ccolor[term];
+ for (i = 0; i < n; i++)
+ c[i][ACOMP] = 0.0F;
+ argA[term] = ccolor[term];
+ }
break;
case GL_ONE:
- argA[j] = & one;
+ {
+ float4_array c = ccolor[term];
+ for (i = 0; i < n; i++)
+ c[i][ACOMP] = 1.0F;
+ argA[term] = ccolor[term];
+ }
break;
default:
/* ARB_texture_env_crossbar source */
@@ -224,481 +255,251 @@ texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
return;
- argA[j] = (const GLchan (*)[4])
- (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
+ argA[term] = get_texel_array(swrast, srcUnit);
}
}
- if (textureUnit->_CurrentCombine->OperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
- const GLchan (*src)[4] = argA[j];
- GLchan (*dst)[4] = ccolor[j];
- argA[j] = (const GLchan (*)[4]) ccolor[j];
+ if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
+ float4_array src = argA[term];
+ float4_array dst = ccolor[term];
+ argA[term] = ccolor[term];
for (i = 0; i < n; i++) {
- dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
+ dst[i][ACOMP] = 1.0F - src[i][ACOMP];
}
}
}
- /*
- * Do the texture combine.
- */
- switch (textureUnit->_CurrentCombine->ModeRGB) {
+ /* RGB channel combine */
+ {
+ float4_array arg0 = argRGB[0];
+ float4_array arg1 = argRGB[1];
+ float4_array arg2 = argRGB[2];
+ float4_array arg3 = argRGB[3];
+
+ switch (combine->ModeRGB) {
case GL_REPLACE:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- if (RGBshift) {
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][RCOMP] = arg0[i][RCOMP] * RGBmult;
- rgba[i][GCOMP] = arg0[i][GCOMP] * RGBmult;
- rgba[i][BCOMP] = arg0[i][BCOMP] * RGBmult;
-#else
- GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift;
- GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift;
- GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift;
- rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
-#endif
- }
- }
- else {
- for (i = 0; i < n; i++) {
- rgba[i][RCOMP] = arg0[i][RCOMP];
- rgba[i][GCOMP] = arg0[i][GCOMP];
- rgba[i][BCOMP] = arg0[i][BCOMP];
- }
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
+ rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
+ rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
}
break;
case GL_MODULATE:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - RGBshift;
-#endif
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * RGBmult;
- rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * RGBmult;
- rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * RGBmult;
-#else
- GLuint r = PROD(arg0[i][RCOMP], arg1[i][RCOMP]) >> shift;
- GLuint g = PROD(arg0[i][GCOMP], arg1[i][GCOMP]) >> shift;
- GLuint b = PROD(arg0[i][BCOMP], arg1[i][BCOMP]) >> shift;
- rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
+ rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
+ rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
}
break;
case GL_ADD:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
+ if (textureUnit->EnvMode == GL_COMBINE4_NV) {
+ /* (a * b) + (c * d) */
for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * RGBmult;
- rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * RGBmult;
- rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * RGBmult;
-#else
- GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift;
- GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift;
- GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift;
- rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
-#endif
+ rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
+ arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
+ arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
+ arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
+ }
+ }
+ else {
+ /* 2-term addition */
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
}
}
break;
case GL_ADD_SIGNED:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
+ if (textureUnit->EnvMode == GL_COMBINE4_NV) {
+ /* (a * b) + (c * d) - 0.5 */
for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * RGBmult;
- rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * RGBmult;
- rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * RGBmult;
-#else
- GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] -half;
- GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] -half;
- GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] -half;
- r = (r < 0) ? 0 : r << RGBshift;
- g = (g < 0) ? 0 : g << RGBshift;
- b = (b < 0) ? 0 : b << RGBshift;
- rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
-#endif
+ rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
+ arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
+ arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
+ arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5) * scaleRGB;
}
}
- break;
- case GL_INTERPOLATE:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
- const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - RGBshift;
-#endif
+ else {
for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
- arg1[i][RCOMP] * (CHAN_MAXF - arg2[i][RCOMP])) * RGBmult;
- rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
- arg1[i][GCOMP] * (CHAN_MAXF - arg2[i][GCOMP])) * RGBmult;
- rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
- arg1[i][BCOMP] * (CHAN_MAXF - arg2[i][BCOMP])) * RGBmult;
-#else
- GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
- + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP]))
- >> shift;
- GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
- + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP]))
- >> shift;
- GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
- + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP]))
- >> shift;
- rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
-#endif
+ rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * scaleRGB;
}
}
break;
+ case GL_INTERPOLATE:
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
+ arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
+ arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
+ arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
+ }
+ break;
case GL_SUBTRACT:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * RGBmult;
- rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * RGBmult;
- rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * RGBmult;
-#else
- GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift;
- GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift;
- GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift;
- rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
- rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
- rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
}
break;
case GL_DOT3_RGB_EXT:
case GL_DOT3_RGBA_EXT:
- {
- /* Do not scale the result by 1 2 or 4 */
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
- (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
- (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
- * 4.0F;
- dot = CLAMP(dot, 0.0F, CHAN_MAXF);
-#else
- GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
- (GLint)arg1[i][RCOMP] - half) +
- S_PROD((GLint)arg0[i][GCOMP] - half,
- (GLint)arg1[i][GCOMP] - half) +
- S_PROD((GLint)arg0[i][BCOMP] - half,
- (GLint)arg1[i][BCOMP] - half)) >> 6;
- dot = CLAMP(dot, 0, CHAN_MAX);
-#endif
- rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
- }
+ /* Do not scale the result by 1 2 or 4 */
+ for (i = 0; i < n; i++) {
+ GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
+ (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
+ (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
+ * 4.0F;
+ dot = CLAMP(dot, 0.0F, 1.0F);
+ rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
}
break;
case GL_DOT3_RGB:
case GL_DOT3_RGBA:
- {
- /* DO scale the result by 1 2 or 4 */
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
- (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
- (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
- * 4.0F * RGBmult;
- dot = CLAMP(dot, 0.0, CHAN_MAXF);
-#else
- GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
- (GLint)arg1[i][RCOMP] - half) +
- S_PROD((GLint)arg0[i][GCOMP] - half,
- (GLint)arg1[i][GCOMP] - half) +
- S_PROD((GLint)arg0[i][BCOMP] - half,
- (GLint)arg1[i][BCOMP] - half)) >> 6;
- dot <<= RGBshift;
- dot = CLAMP(dot, 0, CHAN_MAX);
-#endif
- rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
- }
+ /* DO scale the result by 1 2 or 4 */
+ for (i = 0; i < n; i++) {
+ GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
+ (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
+ (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
+ * 4.0F * scaleRGB;
+ dot = CLAMP(dot, 0.0, 1.0F);
+ rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
}
break;
case GL_MODULATE_ADD_ATI:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
- const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - RGBshift;
-#endif
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP]) * RGBmult;
- rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP]) * RGBmult;
- rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP]) * RGBmult;
-#else
- GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
- + ((GLuint) arg1[i][RCOMP] << CHAN_BITS)) >> shift;
- GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
- + ((GLuint) arg1[i][GCOMP] << CHAN_BITS)) >> shift;
- GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
- + ((GLuint) arg1[i][BCOMP] << CHAN_BITS)) >> shift;
- rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
+ arg1[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
+ arg1[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
+ arg1[i][BCOMP]) * scaleRGB;
}
break;
case GL_MODULATE_SIGNED_ADD_ATI:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
- const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - RGBshift;
-#endif
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP] - 0.5) * RGBmult;
- rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP] - 0.5) * RGBmult;
- rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP] - 0.5) * RGBmult;
-#else
- GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP])
- + (((GLint) arg1[i][RCOMP] - half) << CHAN_BITS))
- >> shift;
- GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP])
- + (((GLint) arg1[i][GCOMP] - half) << CHAN_BITS))
- >> shift;
- GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP])
- + (((GLint) arg1[i][BCOMP] - half) << CHAN_BITS))
- >> shift;
- rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
- rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
- rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
+ arg1[i][RCOMP] - 0.5) * scaleRGB;
+ rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
+ arg1[i][GCOMP] - 0.5) * scaleRGB;
+ rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
+ arg1[i][BCOMP] - 0.5) * scaleRGB;
}
break;
case GL_MODULATE_SUBTRACT_ATI:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
- const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - RGBshift;
-#endif
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) - arg1[i][RCOMP]) * RGBmult;
- rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) - arg1[i][GCOMP]) * RGBmult;
- rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) - arg1[i][BCOMP]) * RGBmult;
-#else
- GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP])
- - ((GLint) arg1[i][RCOMP] << CHAN_BITS))
- >> shift;
- GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP])
- - ((GLint) arg1[i][GCOMP] << CHAN_BITS))
- >> shift;
- GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP])
- - ((GLint) arg1[i][BCOMP] << CHAN_BITS))
- >> shift;
- rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
- rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
- rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
+ arg1[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
+ arg1[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
+ arg1[i][BCOMP]) * scaleRGB;
}
break;
+ case GL_BUMP_ENVMAP_ATI:
+ /* this produces a fixed rgba color, and the coord calc is done elsewhere */
+ for (i = 0; i < n; i++) {
+ /* rgba result is 0,0,0,1 */
+ rgba[i][RCOMP] = 0.0;
+ rgba[i][GCOMP] = 0.0;
+ rgba[i][BCOMP] = 0.0;
+ rgba[i][ACOMP] = 1.0;
+ }
+ return; /* no alpha processing */
default:
_mesa_problem(ctx, "invalid combine mode");
+ }
}
- switch (textureUnit->_CurrentCombine->ModeA) {
+ /* Alpha channel combine */
+ {
+ float4_array arg0 = argA[0];
+ float4_array arg1 = argA[1];
+ float4_array arg2 = argA[2];
+ float4_array arg3 = argA[3];
+
+ switch (combine->ModeA) {
case GL_REPLACE:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
- if (Ashift) {
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- GLchan a = arg0[i][ACOMP] * Amult;
-#else
- GLuint a = (GLuint) arg0[i][ACOMP] << Ashift;
-#endif
- rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
- }
- }
- else {
- for (i = 0; i < n; i++) {
- rgba[i][ACOMP] = arg0[i][ACOMP];
- }
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
}
break;
case GL_MODULATE:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - Ashift;
-#endif
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * Amult;
-#else
- GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift);
- rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
}
break;
case GL_ADD:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
+ if (textureUnit->EnvMode == GL_COMBINE4_NV) {
+ /* (a * b) + (c * d) */
for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * Amult;
-#else
- GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift;
- rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
-#endif
+ rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
+ arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
+ }
+ }
+ else {
+ /* two-term add */
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
}
}
break;
case GL_ADD_SIGNED:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
+ if (textureUnit->EnvMode == GL_COMBINE4_NV) {
+ /* (a * b) + (c * d) - 0.5 */
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
+ arg2[i][ACOMP] * arg3[i][ACOMP] -
+ 0.5) * scaleA;
+ }
+ }
+ else {
+ /* a + b - 0.5 */
for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * Amult;
-#else
- GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] -half;
- a = (a < 0) ? 0 : a << Ashift;
- rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
-#endif
+ rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
}
}
break;
case GL_INTERPOLATE:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
- const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - Ashift;
-#endif
- for (i=0; i<n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
- arg1[i][ACOMP] * (CHAN_MAXF - arg2[i][ACOMP]))
- * Amult;
-#else
- GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
- + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP]))
- >> shift;
- rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
+ arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
+ * scaleA;
}
break;
case GL_SUBTRACT:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * Amult;
-#else
- GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << Ashift;
- rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
}
break;
case GL_MODULATE_ADD_ATI:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
- const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - Ashift;
-#endif
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP]) * Amult;
-#else
- GLint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
- + ((GLuint) arg1[i][ACOMP] << CHAN_BITS))
- >> shift;
- rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
+ + arg1[i][ACOMP]) * scaleA;
}
break;
case GL_MODULATE_SIGNED_ADD_ATI:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
- const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - Ashift;
-#endif
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP] - 0.5F) * Amult;
-#else
- GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP])
- + (((GLint) arg1[i][ACOMP] - half) << CHAN_BITS))
- >> shift;
- rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
+ arg1[i][ACOMP] - 0.5F) * scaleA;
}
break;
case GL_MODULATE_SUBTRACT_ATI:
- {
- const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
- const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
- const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
-#if CHAN_TYPE != GL_FLOAT
- const GLint shift = CHAN_BITS - Ashift;
-#endif
- for (i = 0; i < n; i++) {
-#if CHAN_TYPE == GL_FLOAT
- rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) - arg1[i][ACOMP]) * Amult;
-#else
- GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP])
- - ((GLint) arg1[i][ACOMP] << CHAN_BITS))
- >> shift;
- rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
-#endif
- }
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
+ - arg1[i][ACOMP]) * scaleA;
}
break;
default:
_mesa_problem(ctx, "invalid combine mode");
+ }
}
/* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
@@ -706,370 +507,52 @@ texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
* were written such that the GL_COMBINE_ALPHA value could be set to
* GL_DOT3.
*/
- if (textureUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT ||
- textureUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) {
+ if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
+ combine->ModeRGB == GL_DOT3_RGBA) {
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = rgba[i][RCOMP];
}
}
+
+ for (i = 0; i < n; i++) {
+ UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
+ }
}
-#undef PROD
/**
- * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
- * MODULATE, or DECAL) to an array of fragments.
- * Input: textureUnit - pointer to texture unit to apply
- * format - base internal texture format
- * n - number of fragments
- * primary_rgba - primary colors (may alias rgba for single texture)
- * texels - array of texel colors
- * InOut: rgba - incoming fragment colors modified by texel colors
- * according to the texture environment mode.
+ * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
+ * See GL_EXT_texture_swizzle.
*/
static void
-texture_apply( const GLcontext *ctx,
- const struct gl_texture_unit *texUnit,
- GLuint n,
- CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
- GLchan rgba[][4] )
+swizzle_texels(GLuint swizzle, GLuint count, float4_array texels)
{
- GLint baseLevel;
+ const GLuint swzR = GET_SWZ(swizzle, 0);
+ const GLuint swzG = GET_SWZ(swizzle, 1);
+ const GLuint swzB = GET_SWZ(swizzle, 2);
+ const GLuint swzA = GET_SWZ(swizzle, 3);
+ GLfloat vector[6];
GLuint i;
- GLchan Rc, Gc, Bc, Ac;
- GLenum format;
- (void) primary_rgba;
-
- ASSERT(texUnit);
- ASSERT(texUnit->_Current);
-
- baseLevel = texUnit->_Current->BaseLevel;
- ASSERT(texUnit->_Current->Image[0][baseLevel]);
-
- format = texUnit->_Current->Image[0][baseLevel]->_BaseFormat;
-
- if (format == GL_COLOR_INDEX || format == GL_YCBCR_MESA) {
- format = GL_RGBA; /* a bit of a hack */
- }
- else if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
- format = texUnit->_Current->DepthMode;
- }
-
- switch (texUnit->EnvMode) {
- case GL_REPLACE:
- switch (format) {
- case GL_ALPHA:
- for (i=0;i<n;i++) {
- /* Cv = Cf */
- /* Av = At */
- rgba[i][ACOMP] = texel[i][ACOMP];
- }
- break;
- case GL_LUMINANCE:
- for (i=0;i<n;i++) {
- /* Cv = Lt */
- GLchan Lt = texel[i][RCOMP];
- rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
- /* Av = Af */
- }
- break;
- case GL_LUMINANCE_ALPHA:
- for (i=0;i<n;i++) {
- GLchan Lt = texel[i][RCOMP];
- /* Cv = Lt */
- rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
- /* Av = At */
- rgba[i][ACOMP] = texel[i][ACOMP];
- }
- break;
- case GL_INTENSITY:
- for (i=0;i<n;i++) {
- /* Cv = It */
- GLchan It = texel[i][RCOMP];
- rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
- /* Av = It */
- rgba[i][ACOMP] = It;
- }
- break;
- case GL_RGB:
- for (i=0;i<n;i++) {
- /* Cv = Ct */
- rgba[i][RCOMP] = texel[i][RCOMP];
- rgba[i][GCOMP] = texel[i][GCOMP];
- rgba[i][BCOMP] = texel[i][BCOMP];
- /* Av = Af */
- }
- break;
- case GL_RGBA:
- for (i=0;i<n;i++) {
- /* Cv = Ct */
- rgba[i][RCOMP] = texel[i][RCOMP];
- rgba[i][GCOMP] = texel[i][GCOMP];
- rgba[i][BCOMP] = texel[i][BCOMP];
- /* Av = At */
- rgba[i][ACOMP] = texel[i][ACOMP];
- }
- break;
- default:
- _mesa_problem(ctx, "Bad format (GL_REPLACE) in texture_apply");
- return;
- }
- break;
-
- case GL_MODULATE:
- switch (format) {
- case GL_ALPHA:
- for (i=0;i<n;i++) {
- /* Cv = Cf */
- /* Av = AfAt */
- rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
- }
- break;
- case GL_LUMINANCE:
- for (i=0;i<n;i++) {
- /* Cv = LtCf */
- GLchan Lt = texel[i][RCOMP];
- rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
- rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
- rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
- /* Av = Af */
- }
- break;
- case GL_LUMINANCE_ALPHA:
- for (i=0;i<n;i++) {
- /* Cv = CfLt */
- GLchan Lt = texel[i][RCOMP];
- rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
- rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
- rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
- /* Av = AfAt */
- rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
- }
- break;
- case GL_INTENSITY:
- for (i=0;i<n;i++) {
- /* Cv = CfIt */
- GLchan It = texel[i][RCOMP];
- rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It );
- rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It );
- rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It );
- /* Av = AfIt */
- rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It );
- }
- break;
- case GL_RGB:
- for (i=0;i<n;i++) {
- /* Cv = CfCt */
- rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
- rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
- rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
- /* Av = Af */
- }
- break;
- case GL_RGBA:
- for (i=0;i<n;i++) {
- /* Cv = CfCt */
- rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
- rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
- rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
- /* Av = AfAt */
- rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
- }
- break;
- default:
- _mesa_problem(ctx, "Bad format (GL_MODULATE) in texture_apply");
- return;
- }
- break;
-
- case GL_DECAL:
- switch (format) {
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_INTENSITY:
- /* undefined */
- break;
- case GL_RGB:
- for (i=0;i<n;i++) {
- /* Cv = Ct */
- rgba[i][RCOMP] = texel[i][RCOMP];
- rgba[i][GCOMP] = texel[i][GCOMP];
- rgba[i][BCOMP] = texel[i][BCOMP];
- /* Av = Af */
- }
- break;
- case GL_RGBA:
- for (i=0;i<n;i++) {
- /* Cv = Cf(1-At) + CtAt */
- GLchan t = texel[i][ACOMP], s = CHAN_MAX - t;
- rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t);
- rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t);
- rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t);
- /* Av = Af */
- }
- break;
- default:
- _mesa_problem(ctx, "Bad format (GL_DECAL) in texture_apply");
- return;
- }
- break;
-
- case GL_BLEND:
- UNCLAMPED_FLOAT_TO_CHAN(Rc, texUnit->EnvColor[0]);
- UNCLAMPED_FLOAT_TO_CHAN(Gc, texUnit->EnvColor[1]);
- UNCLAMPED_FLOAT_TO_CHAN(Bc, texUnit->EnvColor[2]);
- UNCLAMPED_FLOAT_TO_CHAN(Ac, texUnit->EnvColor[3]);
- switch (format) {
- case GL_ALPHA:
- for (i=0;i<n;i++) {
- /* Cv = Cf */
- /* Av = AfAt */
- rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
- }
- break;
- case GL_LUMINANCE:
- for (i=0;i<n;i++) {
- /* Cv = Cf(1-Lt) + CcLt */
- GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
- rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
- rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
- rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
- /* Av = Af */
- }
- break;
- case GL_LUMINANCE_ALPHA:
- for (i=0;i<n;i++) {
- /* Cv = Cf(1-Lt) + CcLt */
- GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
- rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
- rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
- rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
- /* Av = AfAt */
- rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
- }
- break;
- case GL_INTENSITY:
- for (i=0;i<n;i++) {
- /* Cv = Cf(1-It) + CcIt */
- GLchan It = texel[i][RCOMP], s = CHAN_MAX - It;
- rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It);
- rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It);
- rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It);
- /* Av = Af(1-It) + Ac*It */
- rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It);
- }
- break;
- case GL_RGB:
- for (i=0;i<n;i++) {
- /* Cv = Cf(1-Ct) + CcCt */
- rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
- rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
- rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
- /* Av = Af */
- }
- break;
- case GL_RGBA:
- for (i=0;i<n;i++) {
- /* Cv = Cf(1-Ct) + CcCt */
- rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
- rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
- rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
- /* Av = AfAt */
- rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
- }
- break;
- default:
- _mesa_problem(ctx, "Bad format (GL_BLEND) in texture_apply");
- return;
- }
- break;
-
- /* XXX don't clamp results if GLchan is float??? */
-
- case GL_ADD: /* GL_EXT_texture_add_env */
- switch (format) {
- case GL_ALPHA:
- for (i=0;i<n;i++) {
- /* Rv = Rf */
- /* Gv = Gf */
- /* Bv = Bf */
- rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
- }
- break;
- case GL_LUMINANCE:
- for (i=0;i<n;i++) {
- ChanTemp Lt = texel[i][RCOMP];
- ChanTemp r = rgba[i][RCOMP] + Lt;
- ChanTemp g = rgba[i][GCOMP] + Lt;
- ChanTemp b = rgba[i][BCOMP] + Lt;
- rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
- /* Av = Af */
- }
- break;
- case GL_LUMINANCE_ALPHA:
- for (i=0;i<n;i++) {
- ChanTemp Lt = texel[i][RCOMP];
- ChanTemp r = rgba[i][RCOMP] + Lt;
- ChanTemp g = rgba[i][GCOMP] + Lt;
- ChanTemp b = rgba[i][BCOMP] + Lt;
- rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
- rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
- }
- break;
- case GL_INTENSITY:
- for (i=0;i<n;i++) {
- GLchan It = texel[i][RCOMP];
- ChanTemp r = rgba[i][RCOMP] + It;
- ChanTemp g = rgba[i][GCOMP] + It;
- ChanTemp b = rgba[i][BCOMP] + It;
- ChanTemp a = rgba[i][ACOMP] + It;
- rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
- rgba[i][ACOMP] = MIN2(a, CHAN_MAX);
- }
- break;
- case GL_RGB:
- for (i=0;i<n;i++) {
- ChanTemp r = rgba[i][RCOMP] + texel[i][RCOMP];
- ChanTemp g = rgba[i][GCOMP] + texel[i][GCOMP];
- ChanTemp b = rgba[i][BCOMP] + texel[i][BCOMP];
- rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
- /* Av = Af */
- }
- break;
- case GL_RGBA:
- for (i=0;i<n;i++) {
- ChanTemp r = rgba[i][RCOMP] + texel[i][RCOMP];
- ChanTemp g = rgba[i][GCOMP] + texel[i][GCOMP];
- ChanTemp b = rgba[i][BCOMP] + texel[i][BCOMP];
- rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
- rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
- rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
- rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
- }
- break;
- default:
- _mesa_problem(ctx, "Bad format (GL_ADD) in texture_apply");
- return;
- }
- break;
- default:
- _mesa_problem(ctx, "Bad env mode in texture_apply");
- return;
+ vector[SWIZZLE_ZERO] = 0;
+ vector[SWIZZLE_ONE] = 1.0F;
+
+ for (i = 0; i < count; i++) {
+ vector[SWIZZLE_X] = texels[i][0];
+ vector[SWIZZLE_Y] = texels[i][1];
+ vector[SWIZZLE_Z] = texels[i][2];
+ vector[SWIZZLE_W] = texels[i][3];
+ texels[i][RCOMP] = vector[swzR];
+ texels[i][GCOMP] = vector[swzG];
+ texels[i][BCOMP] = vector[swzB];
+ texels[i][ACOMP] = vector[swzA];
}
}
-
/**
* Apply texture mapping to a span of fragments.
*/
@@ -1077,31 +560,99 @@ void
_swrast_texture_span( GLcontext *ctx, SWspan *span )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
- GLchan primary_rgba[MAX_WIDTH][4];
+ GLfloat primary_rgba[MAX_WIDTH][4];
GLuint unit;
- ASSERT(span->end < MAX_WIDTH);
+ ASSERT(span->end <= MAX_WIDTH);
/*
* Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
*/
- if (swrast->_AnyTextureCombine)
- MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan));
+ if (swrast->_TextureCombinePrimary) {
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
+ primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
+ primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
+ primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
+ }
+ }
+
+ /* First must sample all bump maps */
+ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ if (texUnit->_ReallyEnabled &&
+ texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
+ const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
+ span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
+ float4_array targetcoords =
+ span->array->attribs[FRAG_ATTRIB_TEX0 +
+ ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];
+
+ const struct gl_texture_object *curObj = texUnit->_Current;
+ GLfloat *lambda = span->array->lambda[unit];
+ float4_array texels = get_texel_array(swrast, unit);
+ GLuint i;
+ GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
+ GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
+ GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
+ GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];
+
+ /* adjust texture lod (lambda) */
+ if (span->arrayMask & SPAN_LAMBDA) {
+ if (texUnit->LodBias + curObj->LodBias != 0.0F) {
+ /* apply LOD bias, but don't clamp yet */
+ const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
+ -ctx->Const.MaxTextureLodBias,
+ ctx->Const.MaxTextureLodBias);
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ lambda[i] += bias;
+ }
+ }
+
+ if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
+ /* apply LOD clamping to lambda */
+ const GLfloat min = curObj->MinLod;
+ const GLfloat max = curObj->MaxLod;
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ GLfloat l = lambda[i];
+ lambda[i] = CLAMP(l, min, max);
+ }
+ }
+ }
+
+ /* Sample the texture (span->end = number of fragments) */
+ swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
+ texcoords, lambda, texels );
+
+ /* manipulate the span values of the bump target
+ not sure this can work correctly even ignoring
+ the problem that channel is unsigned */
+ for (i = 0; i < span->end; i++) {
+ targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
+ rotMatrix01) / targetcoords[i][3];
+ targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
+ rotMatrix11) / targetcoords[i][3];
+ }
+ }
+ }
/*
* Must do all texture sampling before combining in order to
* accomodate GL_ARB_texture_env_crossbar.
*/
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
- if (ctx->Texture.Unit[unit]._ReallyEnabled) {
- const GLfloat (*texcoords)[4]
- = (const GLfloat (*)[4])
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ if (texUnit->_ReallyEnabled &&
+ texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
+ const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
- const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
const struct gl_texture_object *curObj = texUnit->_Current;
GLfloat *lambda = span->array->lambda[unit];
- GLchan (*texels)[4] = (GLchan (*)[4])
- (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan)));
+ float4_array texels = get_texel_array(swrast, unit);
/* adjust texture lod (lambda) */
if (span->arrayMask & SPAN_LAMBDA) {
@@ -1134,13 +685,12 @@ _swrast_texture_span( GLcontext *ctx, SWspan *span )
/* GL_SGI_texture_color_table */
if (texUnit->ColorTableEnabled) {
-#if CHAN_TYPE == GL_UNSIGNED_BYTE
- _mesa_lookup_rgba_ubyte(&texUnit->ColorTable, span->end, texels);
-#elif CHAN_TYPE == GL_UNSIGNED_SHORT
- _mesa_lookup_rgba_ubyte(&texUnit->ColorTable, span->end, texels);
-#else
_mesa_lookup_rgba_float(&texUnit->ColorTable, span->end, texels);
-#endif
+ }
+
+ /* GL_EXT_texture_swizzle */
+ if (curObj->_Swizzle != SWIZZLE_NOOP) {
+ swizzle_texels(curObj->_Swizzle, span->end, texels);
}
}
}
@@ -1151,22 +701,10 @@ _swrast_texture_span( GLcontext *ctx, SWspan *span )
*/
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
- const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
- if (texUnit->_CurrentCombine != &texUnit->_EnvMode ) {
- texture_combine( ctx, unit, span->end,
- (CONST GLchan (*)[4]) primary_rgba,
- swrast->TexelBuffer,
- span->array->rgba );
- }
- else {
- /* conventional texture blend */
- const GLchan (*texels)[4] = (const GLchan (*)[4])
- (swrast->TexelBuffer + unit *
- (span->end * 4 * sizeof(GLchan)));
- texture_apply( ctx, texUnit, span->end,
- (CONST GLchan (*)[4]) primary_rgba, texels,
- span->array->rgba );
- }
+ texture_combine( ctx, unit, span->end,
+ primary_rgba,
+ swrast->TexelBuffer,
+ span->array->rgba );
}
}
}
diff --git a/src/mesa/swrast/s_texfilter.c b/src/mesa/swrast/s_texfilter.c
index a095b255ab..6b1f934647 100644
--- a/src/mesa/swrast/s_texfilter.c
+++ b/src/mesa/swrast/s_texfilter.c
@@ -43,18 +43,11 @@
#define FRAC(f) ((f) - IFLOOR(f))
-/**
- * Constants for integer linear interpolation.
- */
-#define ILERP_SCALE 65536.0F
-#define ILERP_SHIFT 16
-
/**
- * Linear interpolation macros
+ * Linear interpolation macro
*/
#define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
-#define ILERP(IT, A, B) ( (A) + (((IT) * ((B) - (A))) >> ILERP_SHIFT) )
/**
@@ -76,21 +69,6 @@ lerp_2d(GLfloat a, GLfloat b,
/**
- * Do 2D/biliner interpolation of integer values.
- * \sa lerp_2d
- */
-static INLINE GLint
-ilerp_2d(GLint ia, GLint ib,
- GLint v00, GLint v10, GLint v01, GLint v11)
-{
- /* fixed point interpolants in [0, ILERP_SCALE] */
- const GLint temp0 = ILERP(ia, v00, v10);
- const GLint temp1 = ILERP(ia, v01, v11);
- return ILERP(ib, temp0, temp1);
-}
-
-
-/**
* Do 3D/trilinear interpolation of float values.
* \sa lerp_2d
*/
@@ -110,50 +88,15 @@ lerp_3d(GLfloat a, GLfloat b, GLfloat c,
/**
- * Do 3D/trilinear interpolation of integer values.
- * \sa lerp_2d
- */
-static INLINE GLint
-ilerp_3d(GLint ia, GLint ib, GLint ic,
- GLint v000, GLint v100, GLint v010, GLint v110,
- GLint v001, GLint v101, GLint v011, GLint v111)
-{
- /* fixed point interpolants in [0, ILERP_SCALE] */
- const GLint temp00 = ILERP(ia, v000, v100);
- const GLint temp10 = ILERP(ia, v010, v110);
- const GLint temp01 = ILERP(ia, v001, v101);
- const GLint temp11 = ILERP(ia, v011, v111);
- const GLint temp0 = ILERP(ib, temp00, temp10);
- const GLint temp1 = ILERP(ib, temp01, temp11);
- return ILERP(ic, temp0, temp1);
-}
-
-
-/**
* Do linear interpolation of colors.
*/
static INLINE void
-lerp_rgba(GLchan result[4], GLfloat t, const GLchan a[4], const GLchan b[4])
+lerp_rgba(GLfloat result[4], GLfloat t, const GLfloat a[4], const GLfloat b[4])
{
-#if CHAN_TYPE == GL_FLOAT
result[0] = LERP(t, a[0], b[0]);
result[1] = LERP(t, a[1], b[1]);
result[2] = LERP(t, a[2], b[2]);
result[3] = LERP(t, a[3], b[3]);
-#elif CHAN_TYPE == GL_UNSIGNED_SHORT
- result[0] = (GLchan) (LERP(t, a[0], b[0]) + 0.5);
- result[1] = (GLchan) (LERP(t, a[1], b[1]) + 0.5);
- result[2] = (GLchan) (LERP(t, a[2], b[2]) + 0.5);
- result[3] = (GLchan) (LERP(t, a[3], b[3]) + 0.5);
-#else
- /* fixed point interpolants in [0, ILERP_SCALE] */
- const GLint it = IROUND_POS(t * ILERP_SCALE);
- ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE);
- result[0] = ILERP(it, a[0], b[0]);
- result[1] = ILERP(it, a[1], b[1]);
- result[2] = ILERP(it, a[2], b[2]);
- result[3] = ILERP(it, a[3], b[3]);
-#endif
}
@@ -161,29 +104,14 @@ lerp_rgba(GLchan result[4], GLfloat t, const GLchan a[4], const GLchan b[4])
* Do bilinear interpolation of colors.
*/
static INLINE void
-lerp_rgba_2d(GLchan result[4], GLfloat a, GLfloat b,
- const GLchan t00[4], const GLchan t10[4],
- const GLchan t01[4], const GLchan t11[4])
+lerp_rgba_2d(GLfloat result[4], GLfloat a, GLfloat b,
+ const GLfloat t00[4], const GLfloat t10[4],
+ const GLfloat t01[4], const GLfloat t11[4])
{
-#if CHAN_TYPE == GL_FLOAT
result[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]);
result[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]);
result[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]);
result[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]);
-#elif CHAN_TYPE == GL_UNSIGNED_SHORT
- result[0] = (GLchan) (lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]) + 0.5);
- result[1] = (GLchan) (lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]) + 0.5);
- result[2] = (GLchan) (lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]) + 0.5);
- result[3] = (GLchan) (lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]) + 0.5);
-#else
- const GLint ia = IROUND_POS(a * ILERP_SCALE);
- const GLint ib = IROUND_POS(b * ILERP_SCALE);
- ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE);
- result[0] = ilerp_2d(ia, ib, t00[0], t10[0], t01[0], t11[0]);
- result[1] = ilerp_2d(ia, ib, t00[1], t10[1], t01[1], t11[1]);
- result[2] = ilerp_2d(ia, ib, t00[2], t10[2], t01[2], t11[2]);
- result[3] = ilerp_2d(ia, ib, t00[3], t10[3], t01[3], t11[3]);
-#endif
}
@@ -191,34 +119,18 @@ lerp_rgba_2d(GLchan result[4], GLfloat a, GLfloat b,
* Do trilinear interpolation of colors.
*/
static INLINE void
-lerp_rgba_3d(GLchan result[4], GLfloat a, GLfloat b, GLfloat c,
- const GLchan t000[4], const GLchan t100[4],
- const GLchan t010[4], const GLchan t110[4],
- const GLchan t001[4], const GLchan t101[4],
- const GLchan t011[4], const GLchan t111[4])
+lerp_rgba_3d(GLfloat result[4], GLfloat a, GLfloat b, GLfloat c,
+ const GLfloat t000[4], const GLfloat t100[4],
+ const GLfloat t010[4], const GLfloat t110[4],
+ const GLfloat t001[4], const GLfloat t101[4],
+ const GLfloat t011[4], const GLfloat t111[4])
{
GLuint k;
/* compiler should unroll these short loops */
-#if CHAN_TYPE == GL_FLOAT
for (k = 0; k < 4; k++) {
result[k] = lerp_3d(a, b, c, t000[k], t100[k], t010[k], t110[k],
t001[k], t101[k], t011[k], t111[k]);
}
-#elif CHAN_TYPE == GL_UNSIGNED_SHORT
- for (k = 0; k < 4; k++) {
- result[k] = (GLchan)(lerp_3d(a, b, c,
- t000[k], t100[k], t010[k], t110[k],
- t001[k], t101[k], t011[k], t111[k]) + 0.5F);
- }
-#else
- GLint ia = IROUND_POS(a * ILERP_SCALE);
- GLint ib = IROUND_POS(b * ILERP_SCALE);
- GLint ic = IROUND_POS(c * ILERP_SCALE);
- for (k = 0; k < 4; k++) {
- result[k] = ilerp_3d(ia, ib, ic, t000[k], t100[k], t010[k], t110[k],
- t001[k], t101[k], t011[k], t111[k]);
- }
-#endif
}
@@ -226,7 +138,7 @@ lerp_rgba_3d(GLchan result[4], GLfloat a, GLfloat b, GLfloat c,
* If A is a signed integer, A % B doesn't give the right value for A < 0
* (in terms of texture repeat). Just casting to unsigned fixes that.
*/
-#define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))
+#define REMAINDER(A, B) (((A) + (B) * 1024) % (B))
/**
@@ -502,6 +414,169 @@ linear_repeat_texel_location(GLuint size, GLfloat s,
/**
+ * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
+ */
+static INLINE GLint
+clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max)
+{
+ switch (wrapMode) {
+ case GL_CLAMP:
+ return IFLOOR( CLAMP(coord, 0.0F, max - 1) );
+ case GL_CLAMP_TO_EDGE:
+ return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) );
+ case GL_CLAMP_TO_BORDER:
+ return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) );
+ default:
+ _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_nearest");
+ return 0;
+ }
+}
+
+
+/**
+ * As above, but GL_LINEAR filtering.
+ */
+static INLINE void
+clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max,
+ GLint *i0out, GLint *i1out, GLfloat *weight)
+{
+ GLfloat fcol;
+ GLint i0, i1;
+ switch (wrapMode) {
+ case GL_CLAMP:
+ /* Not exactly what the spec says, but it matches NVIDIA output */
+ fcol = CLAMP(coord - 0.5F, 0.0, max-1);
+ i0 = IFLOOR(fcol);
+ i1 = i0 + 1;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ fcol = CLAMP(coord, 0.5F, max - 0.5F);
+ fcol -= 0.5F;
+ i0 = IFLOOR(fcol);
+ i1 = i0 + 1;
+ if (i1 > max - 1)
+ i1 = max - 1;
+ break;
+ case GL_CLAMP_TO_BORDER:
+ fcol = CLAMP(coord, -0.5F, max + 0.5F);
+ fcol -= 0.5F;
+ i0 = IFLOOR(fcol);
+ i1 = i0 + 1;
+ break;
+ default:
+ _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_linear");
+ i0 = i1 = 0;
+ fcol = 0.0F;
+ }
+ *i0out = i0;
+ *i1out = i1;
+ *weight = FRAC(fcol);
+}
+
+
+/**
+ * Compute nearest integer texcoords for given texobj and coordinate.
+ */
+static INLINE void
+nearest_texcoord(const struct gl_texture_object *texObj,
+ const GLfloat texcoord[4],
+ GLint *i, GLint *j, GLint *k)
+{
+ const GLint baseLevel = texObj->BaseLevel;
+ const struct gl_texture_image *img = texObj->Image[0][baseLevel];
+ const GLint width = img->Width;
+ const GLint height = img->Height;
+ const GLint depth = img->Depth;
+
+ switch (texObj->Target) {
+ case GL_TEXTURE_RECTANGLE_ARB:
+ *i = clamp_rect_coord_nearest(texObj->WrapS, texcoord[0], width);
+ *j = clamp_rect_coord_nearest(texObj->WrapT, texcoord[1], height);
+ *k = 0;
+ break;
+ case GL_TEXTURE_1D:
+ *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
+ *j = 0;
+ *k = 0;
+ break;
+ case GL_TEXTURE_2D:
+ *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
+ *j = nearest_texel_location(texObj->WrapT, img, height, texcoord[1]);
+ *k = 0;
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
+ *j = clamp_rect_coord_nearest(texObj->WrapT, texcoord[1], height);
+ *k = 0;
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
+ *j = nearest_texel_location(texObj->WrapT, img, height, texcoord[1]);
+ *k = clamp_rect_coord_nearest(texObj->WrapR, texcoord[2], depth);
+ break;
+ default:
+ *i = *j = *k = 0;
+ }
+}
+
+
+/**
+ * Compute linear integer texcoords for given texobj and coordinate.
+ */
+static INLINE void
+linear_texcoord(const struct gl_texture_object *texObj,
+ const GLfloat texcoord[4],
+ GLint *i0, GLint *i1, GLint *j0, GLint *j1, GLint *slice,
+ GLfloat *wi, GLfloat *wj)
+{
+ const GLint baseLevel = texObj->BaseLevel;
+ const struct gl_texture_image *img = texObj->Image[0][baseLevel];
+ const GLint width = img->Width;
+ const GLint height = img->Height;
+ const GLint depth = img->Depth;
+
+ switch (texObj->Target) {
+ case GL_TEXTURE_RECTANGLE_ARB:
+ clamp_rect_coord_linear(texObj->WrapS, texcoord[0],
+ width, i0, i1, wi);
+ clamp_rect_coord_linear(texObj->WrapT, texcoord[1],
+ height, j0, j1, wj);
+ *slice = 0;
+ break;
+
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ linear_texel_locations(texObj->WrapS, img, width,
+ texcoord[0], i0, i1, wi);
+ linear_texel_locations(texObj->WrapT, img, height,
+ texcoord[1], j0, j1, wj);
+ *slice = 0;
+ break;
+
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ linear_texel_locations(texObj->WrapS, img, width,
+ texcoord[0], i0, i1, wi);
+ *j0 = clamp_rect_coord_nearest(texObj->WrapT, texcoord[1], height);
+ *j1 = *j0;
+ *slice = 0;
+ break;
+
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ linear_texel_locations(texObj->WrapS, img, width,
+ texcoord[0], i0, i1, wi);
+ linear_texel_locations(texObj->WrapT, img, height,
+ texcoord[1], j0, j1, wj);
+ *slice = clamp_rect_coord_nearest(texObj->WrapR, texcoord[2], depth);
+ break;
+
+ default:
+ *slice = 0;
+ }
+}
+
+
+
+/**
* For linear interpolation between mipmap levels N and N+1, this function
* computes N.
*/
@@ -660,6 +735,44 @@ compute_min_mag_ranges(const struct gl_texture_object *tObj,
}
+/**
+ * When we sample the border color, it must be interpreted according to
+ * the base texture format. Ex: if the texture base format it GL_ALPHA,
+ * we return (0,0,0,BorderAlpha).
+ */
+static INLINE void
+get_border_color(const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ GLfloat rgba[4])
+{
+ switch (img->TexFormat->BaseFormat) {
+ case GL_RGB:
+ rgba[0] = tObj->BorderColor[0];
+ rgba[1] = tObj->BorderColor[1];
+ rgba[2] = tObj->BorderColor[2];
+ rgba[3] = 1.0F;
+ break;
+ case GL_ALPHA:
+ rgba[0] = rgba[1] = rgba[2] = 0.0;
+ rgba[3] = tObj->BorderColor[3];
+ break;
+ case GL_LUMINANCE:
+ rgba[0] = rgba[1] = rgba[2] = tObj->BorderColor[0];
+ rgba[3] = 1.0;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ rgba[0] = rgba[1] = rgba[2] = tObj->BorderColor[0];
+ rgba[3] = tObj->BorderColor[3];
+ break;
+ case GL_INTENSITY:
+ rgba[0] = rgba[1] = rgba[2] = rgba[3] = tObj->BorderColor[0];
+ break;
+ default:
+ COPY_4V(rgba, tObj->BorderColor);
+ }
+}
+
+
/**********************************************************************/
/* 1-D Texture Sampling Functions */
/**********************************************************************/
@@ -671,7 +784,7 @@ static INLINE void
sample_1d_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
- const GLfloat texcoord[4], GLchan rgba[4])
+ const GLfloat texcoord[4], GLfloat rgba[4])
{
const GLint width = img->Width2; /* without border, power of two */
GLint i;
@@ -680,10 +793,10 @@ sample_1d_nearest(GLcontext *ctx,
i += img->Border;
if (i < 0 || i >= (GLint) img->Width) {
/* Need this test for GL_CLAMP_TO_BORDER mode */
- COPY_CHAN4(rgba, tObj->_BorderChan);
+ get_border_color(tObj, img, rgba);
}
else {
- img->FetchTexelc(img, i, 0, 0, rgba);
+ img->FetchTexelf(img, i, 0, 0, rgba);
}
}
@@ -695,13 +808,13 @@ static INLINE void
sample_1d_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
- const GLfloat texcoord[4], GLchan rgba[4])
+ const GLfloat texcoord[4], GLfloat rgba[4])
{
const GLint width = img->Width2;
GLint i0, i1;
GLbitfield useBorderColor = 0x0;
GLfloat a;
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
@@ -716,16 +829,16 @@ sample_1d_linear(GLcontext *ctx,
/* fetch texel colors */
if (useBorderColor & I0BIT) {
- COPY_CHAN4(t0, tObj->_BorderChan);
+ get_border_color(tObj, img, t0);
}
else {
- img->FetchTexelc(img, i0, 0, 0, t0);
+ img->FetchTexelf(img, i0, 0, 0, t0);
}
if (useBorderColor & I1BIT) {
- COPY_CHAN4(t1, tObj->_BorderChan);
+ get_border_color(tObj, img, t1);
}
else {
- img->FetchTexelc(img, i1, 0, 0, t1);
+ img->FetchTexelf(img, i1, 0, 0, t1);
}
lerp_rgba(rgba, a, t0, t1);
@@ -736,7 +849,7 @@ static void
sample_1d_nearest_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -751,7 +864,7 @@ static void
sample_1d_linear_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -766,7 +879,7 @@ static void
sample_1d_nearest_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -777,7 +890,7 @@ sample_1d_nearest_mipmap_linear(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4];
+ GLfloat t0[4], t1[4];
const GLfloat f = FRAC(lambda[i]);
sample_1d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
sample_1d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
@@ -791,7 +904,7 @@ static void
sample_1d_linear_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -802,7 +915,7 @@ sample_1d_linear_mipmap_linear(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4];
+ GLfloat t0[4], t1[4];
const GLfloat f = FRAC(lambda[i]);
sample_1d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
sample_1d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
@@ -817,7 +930,7 @@ static void
sample_nearest_1d( GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4] )
+ GLfloat rgba[][4] )
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -833,7 +946,7 @@ static void
sample_linear_1d( GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4] )
+ GLfloat rgba[][4] )
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -849,7 +962,7 @@ static void
sample_lambda_1d( GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4] )
+ const GLfloat lambda[], GLfloat rgba[][4] )
{
GLuint minStart, minEnd; /* texels with minification */
GLuint magStart, magEnd; /* texels with magnification */
@@ -929,7 +1042,7 @@ sample_2d_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
const GLfloat texcoord[4],
- GLchan rgba[])
+ GLfloat rgba[])
{
const GLint width = img->Width2; /* without border, power of two */
const GLint height = img->Height2; /* without border, power of two */
@@ -945,10 +1058,10 @@ sample_2d_nearest(GLcontext *ctx,
if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
/* Need this test for GL_CLAMP_TO_BORDER mode */
- COPY_CHAN4(rgba, tObj->_BorderChan);
+ get_border_color(tObj, img, rgba);
}
else {
- img->FetchTexelc(img, i, j, 0, rgba);
+ img->FetchTexelf(img, i, j, 0, rgba);
}
}
@@ -962,14 +1075,14 @@ sample_2d_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
const GLfloat texcoord[4],
- GLchan rgba[])
+ GLfloat rgba[])
{
const GLint width = img->Width2;
const GLint height = img->Height2;
GLint i0, j0, i1, j1;
GLbitfield useBorderColor = 0x0;
GLfloat a, b;
- GLchan t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
+ GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
@@ -989,28 +1102,28 @@ sample_2d_linear(GLcontext *ctx,
/* fetch four texel colors */
if (useBorderColor & (I0BIT | J0BIT)) {
- COPY_CHAN4(t00, tObj->_BorderChan);
+ get_border_color(tObj, img, t00);
}
else {
- img->FetchTexelc(img, i0, j0, 0, t00);
+ img->FetchTexelf(img, i0, j0, 0, t00);
}
if (useBorderColor & (I1BIT | J0BIT)) {
- COPY_CHAN4(t10, tObj->_BorderChan);
+ get_border_color(tObj, img, t10);
}
else {
- img->FetchTexelc(img, i1, j0, 0, t10);
+ img->FetchTexelf(img, i1, j0, 0, t10);
}
if (useBorderColor & (I0BIT | J1BIT)) {
- COPY_CHAN4(t01, tObj->_BorderChan);
+ get_border_color(tObj, img, t01);
}
else {
- img->FetchTexelc(img, i0, j1, 0, t01);
+ img->FetchTexelf(img, i0, j1, 0, t01);
}
if (useBorderColor & (I1BIT | J1BIT)) {
- COPY_CHAN4(t11, tObj->_BorderChan);
+ get_border_color(tObj, img, t11);
}
else {
- img->FetchTexelc(img, i1, j1, 0, t11);
+ img->FetchTexelf(img, i1, j1, 0, t11);
}
lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11);
@@ -1026,13 +1139,13 @@ sample_2d_linear_repeat(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
const GLfloat texcoord[4],
- GLchan rgba[])
+ GLfloat rgba[])
{
const GLint width = img->Width2;
const GLint height = img->Height2;
GLint i0, j0, i1, j1;
GLfloat wi, wj;
- GLchan t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
+ GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
(void) ctx;
@@ -1045,10 +1158,10 @@ sample_2d_linear_repeat(GLcontext *ctx,
linear_repeat_texel_location(width, texcoord[0], &i0, &i1, &wi);
linear_repeat_texel_location(height, texcoord[1], &j0, &j1, &wj);
- img->FetchTexelc(img, i0, j0, 0, t00);
- img->FetchTexelc(img, i1, j0, 0, t10);
- img->FetchTexelc(img, i0, j1, 0, t01);
- img->FetchTexelc(img, i1, j1, 0, t11);
+ img->FetchTexelf(img, i0, j0, 0, t00);
+ img->FetchTexelf(img, i1, j0, 0, t10);
+ img->FetchTexelf(img, i0, j1, 0, t01);
+ img->FetchTexelf(img, i1, j1, 0, t11);
lerp_rgba_2d(rgba, wi, wj, t00, t10, t01, t11);
}
@@ -1058,7 +1171,7 @@ static void
sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
for (i = 0; i < n; i++) {
@@ -1072,7 +1185,7 @@ static void
sample_2d_linear_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1087,7 +1200,7 @@ static void
sample_2d_nearest_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1098,7 +1211,7 @@ sample_2d_nearest_mipmap_linear(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_2d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
sample_2d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
@@ -1112,7 +1225,7 @@ static void
sample_2d_linear_mipmap_linear( GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4] )
+ const GLfloat lambda[], GLfloat rgba[][4] )
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1123,7 +1236,7 @@ sample_2d_linear_mipmap_linear( GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_2d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
sample_2d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
@@ -1137,7 +1250,7 @@ static void
sample_2d_linear_mipmap_linear_repeat(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1150,7 +1263,7 @@ sample_2d_linear_mipmap_linear_repeat(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level ],
texcoord[i], t0);
@@ -1167,7 +1280,7 @@ static void
sample_nearest_2d(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -1183,7 +1296,7 @@ static void
sample_linear_2d(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -1216,7 +1329,7 @@ static void
opt_sample_rgb_2d(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
const GLfloat width = (GLfloat) img->Width;
@@ -1238,9 +1351,9 @@ opt_sample_rgb_2d(GLcontext *ctx,
GLint j = IFLOOR(texcoords[k][1] * height) & rowMask;
GLint pos = (j << shift) | i;
GLchan *texel = ((GLchan *) img->Data) + 3*pos;
- rgba[k][RCOMP] = texel[0];
- rgba[k][GCOMP] = texel[1];
- rgba[k][BCOMP] = texel[2];
+ rgba[k][RCOMP] = CHAN_TO_FLOAT(texel[0]);
+ rgba[k][GCOMP] = CHAN_TO_FLOAT(texel[1]);
+ rgba[k][BCOMP] = CHAN_TO_FLOAT(texel[2]);
}
}
@@ -1257,7 +1370,7 @@ static void
opt_sample_rgba_2d(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
const GLfloat width = (GLfloat) img->Width;
@@ -1279,7 +1392,10 @@ opt_sample_rgba_2d(GLcontext *ctx,
const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask;
const GLint pos = (row << shift) | col;
const GLchan *texel = ((GLchan *) img->Data) + (pos << 2); /* pos*4 */
- COPY_CHAN4(rgba[i], texel);
+ rgba[i][RCOMP] = CHAN_TO_FLOAT(texel[0]);
+ rgba[i][GCOMP] = CHAN_TO_FLOAT(texel[1]);
+ rgba[i][BCOMP] = CHAN_TO_FLOAT(texel[2]);
+ rgba[i][ACOMP] = CHAN_TO_FLOAT(texel[3]);
}
}
@@ -1289,7 +1405,7 @@ static void
sample_lambda_2d(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel];
GLuint minStart, minEnd; /* texels with minification */
@@ -1411,7 +1527,7 @@ sample_3d_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
const GLfloat texcoord[4],
- GLchan rgba[4])
+ GLfloat rgba[4])
{
const GLint width = img->Width2; /* without border, power of two */
const GLint height = img->Height2; /* without border, power of two */
@@ -1427,10 +1543,10 @@ sample_3d_nearest(GLcontext *ctx,
j < 0 || j >= (GLint) img->Height ||
k < 0 || k >= (GLint) img->Depth) {
/* Need this test for GL_CLAMP_TO_BORDER mode */
- COPY_CHAN4(rgba, tObj->_BorderChan);
+ get_border_color(tObj, img, rgba);
}
else {
- img->FetchTexelc(img, i, j, k, rgba);
+ img->FetchTexelf(img, i, j, k, rgba);
}
}
@@ -1443,7 +1559,7 @@ sample_3d_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
const GLfloat texcoord[4],
- GLchan rgba[4])
+ GLfloat rgba[4])
{
const GLint width = img->Width2;
const GLint height = img->Height2;
@@ -1451,8 +1567,8 @@ sample_3d_linear(GLcontext *ctx,
GLint i0, j0, k0, i1, j1, k1;
GLbitfield useBorderColor = 0x0;
GLfloat a, b, c;
- GLchan t000[4], t010[4], t001[4], t011[4];
- GLchan t100[4], t110[4], t101[4], t111[4];
+ GLfloat t000[4], t010[4], t001[4], t011[4];
+ GLfloat t100[4], t110[4], t101[4], t111[4];
linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
@@ -1478,53 +1594,53 @@ sample_3d_linear(GLcontext *ctx,
/* Fetch texels */
if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
- COPY_CHAN4(t000, tObj->_BorderChan);
+ get_border_color(tObj, img, t000);
}
else {
- img->FetchTexelc(img, i0, j0, k0, t000);
+ img->FetchTexelf(img, i0, j0, k0, t000);
}
if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
- COPY_CHAN4(t100, tObj->_BorderChan);
+ get_border_color(tObj, img, t100);
}
else {
- img->FetchTexelc(img, i1, j0, k0, t100);
+ img->FetchTexelf(img, i1, j0, k0, t100);
}
if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
- COPY_CHAN4(t010, tObj->_BorderChan);
+ get_border_color(tObj, img, t010);
}
else {
- img->FetchTexelc(img, i0, j1, k0, t010);
+ img->FetchTexelf(img, i0, j1, k0, t010);
}
if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
- COPY_CHAN4(t110, tObj->_BorderChan);
+ get_border_color(tObj, img, t110);
}
else {
- img->FetchTexelc(img, i1, j1, k0, t110);
+ img->FetchTexelf(img, i1, j1, k0, t110);
}
if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
- COPY_CHAN4(t001, tObj->_BorderChan);
+ get_border_color(tObj, img, t001);
}
else {
- img->FetchTexelc(img, i0, j0, k1, t001);
+ img->FetchTexelf(img, i0, j0, k1, t001);
}
if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
- COPY_CHAN4(t101, tObj->_BorderChan);
+ get_border_color(tObj, img, t101);
}
else {
- img->FetchTexelc(img, i1, j0, k1, t101);
+ img->FetchTexelf(img, i1, j0, k1, t101);
}
if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
- COPY_CHAN4(t011, tObj->_BorderChan);
+ get_border_color(tObj, img, t011);
}
else {
- img->FetchTexelc(img, i0, j1, k1, t011);
+ img->FetchTexelf(img, i0, j1, k1, t011);
}
if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
- COPY_CHAN4(t111, tObj->_BorderChan);
+ get_border_color(tObj, img, t111);
}
else {
- img->FetchTexelc(img, i1, j1, k1, t111);
+ img->FetchTexelf(img, i1, j1, k1, t111);
}
/* trilinear interpolation of samples */
@@ -1536,7 +1652,7 @@ static void
sample_3d_nearest_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4] )
+ const GLfloat lambda[], GLfloat rgba[][4] )
{
GLuint i;
for (i = 0; i < n; i++) {
@@ -1550,7 +1666,7 @@ static void
sample_3d_linear_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1565,7 +1681,7 @@ static void
sample_3d_nearest_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1576,7 +1692,7 @@ sample_3d_nearest_mipmap_linear(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_3d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
sample_3d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
@@ -1590,7 +1706,7 @@ static void
sample_3d_linear_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1601,7 +1717,7 @@ sample_3d_linear_mipmap_linear(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_3d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
sample_3d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
@@ -1616,7 +1732,7 @@ static void
sample_nearest_3d(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -1632,7 +1748,7 @@ static void
sample_linear_3d(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -1648,7 +1764,7 @@ static void
sample_lambda_3d(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint minStart, minEnd; /* texels with minification */
GLuint magStart, magEnd; /* texels with magnification */
@@ -1799,7 +1915,7 @@ static void
sample_nearest_cube(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint i;
(void) lambda;
@@ -1817,7 +1933,7 @@ static void
sample_linear_cube(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
(void) lambda;
@@ -1835,7 +1951,7 @@ static void
sample_cube_nearest_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1864,7 +1980,7 @@ static void
sample_cube_linear_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1883,7 +1999,7 @@ static void
sample_cube_nearest_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1898,7 +2014,7 @@ sample_cube_nearest_mipmap_linear(GLcontext *ctx,
newCoord, rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_2d_nearest(ctx, tObj, images[level ], newCoord, t0);
sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1);
@@ -1912,7 +2028,7 @@ static void
sample_cube_linear_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -1927,7 +2043,7 @@ sample_cube_linear_mipmap_linear(GLcontext *ctx,
newCoord, rgba[i]);
}
else {
- GLchan t0[4], t1[4];
+ GLfloat t0[4], t1[4];
const GLfloat f = FRAC(lambda[i]);
sample_2d_linear(ctx, tObj, images[level ], newCoord, t0);
sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1);
@@ -1942,7 +2058,7 @@ static void
sample_lambda_cube(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint minStart, minEnd; /* texels with minification */
GLuint magStart, magEnd; /* texels with magnification */
@@ -2012,71 +2128,11 @@ sample_lambda_cube(GLcontext *ctx,
/**********************************************************************/
-/**
- * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
- */
-static INLINE GLint
-clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max)
-{
- switch (wrapMode) {
- case GL_CLAMP:
- return IFLOOR( CLAMP(coord, 0.0F, max - 1) );
- case GL_CLAMP_TO_EDGE:
- return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) );
- case GL_CLAMP_TO_BORDER:
- return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) );
- default:
- _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_nearest");
- return 0;
- }
-}
-
-
-/**
- * As above, but GL_LINEAR filtering.
- */
-static INLINE void
-clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max,
- GLint *i0out, GLint *i1out, GLfloat *weight)
-{
- GLfloat fcol;
- GLint i0, i1;
- switch (wrapMode) {
- case GL_CLAMP:
- /* Not exactly what the spec says, but it matches NVIDIA output */
- fcol = CLAMP(coord - 0.5F, 0.0, max-1);
- i0 = IFLOOR(fcol);
- i1 = i0 + 1;
- break;
- case GL_CLAMP_TO_EDGE:
- fcol = CLAMP(coord, 0.5F, max - 0.5F);
- fcol -= 0.5F;
- i0 = IFLOOR(fcol);
- i1 = i0 + 1;
- if (i1 > max - 1)
- i1 = max - 1;
- break;
- case GL_CLAMP_TO_BORDER:
- fcol = CLAMP(coord, -0.5F, max + 0.5F);
- fcol -= 0.5F;
- i0 = IFLOOR(fcol);
- i1 = i0 + 1;
- default:
- _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_linear");
- i0 = i1 = 0;
- fcol = 0.0F;
- }
- *i0out = i0;
- *i1out = i1;
- *weight = FRAC(fcol);
-}
-
-
static void
sample_nearest_rect(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
const struct gl_texture_image *img = tObj->Image[0][0];
const GLint width = img->Width;
@@ -2099,9 +2155,9 @@ sample_nearest_rect(GLcontext *ctx,
col = clamp_rect_coord_nearest(tObj->WrapS, texcoords[i][0], width);
row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height);
if (col < 0 || col >= width || row < 0 || row >= height)
- COPY_CHAN4(rgba[i], tObj->_BorderChan);
+ get_border_color(tObj, img, rgba[i]);
else
- img->FetchTexelc(img, col, row, 0, rgba[i]);
+ img->FetchTexelf(img, col, row, 0, rgba[i]);
}
}
@@ -2110,7 +2166,7 @@ static void
sample_linear_rect(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
const struct gl_texture_image *img = tObj->Image[0][0];
const GLint width = img->Width;
@@ -2130,7 +2186,7 @@ sample_linear_rect(GLcontext *ctx,
for (i = 0; i < n; i++) {
GLint i0, j0, i1, j1;
- GLchan t00[4], t01[4], t10[4], t11[4];
+ GLfloat t00[4], t01[4], t10[4], t11[4];
GLfloat a, b;
GLbitfield useBorderColor = 0x0;
@@ -2147,24 +2203,24 @@ sample_linear_rect(GLcontext *ctx,
/* get four texel samples */
if (useBorderColor & (I0BIT | J0BIT))
- COPY_CHAN4(t00, tObj->_BorderChan);
+ get_border_color(tObj, img, t00);
else
- img->FetchTexelc(img, i0, j0, 0, t00);
+ img->FetchTexelf(img, i0, j0, 0, t00);
if (useBorderColor & (I1BIT | J0BIT))
- COPY_CHAN4(t10, tObj->_BorderChan);
+ get_border_color(tObj, img, t10);
else
- img->FetchTexelc(img, i1, j0, 0, t10);
+ img->FetchTexelf(img, i1, j0, 0, t10);
if (useBorderColor & (I0BIT | J1BIT))
- COPY_CHAN4(t01, tObj->_BorderChan);
+ get_border_color(tObj, img, t01);
else
- img->FetchTexelc(img, i0, j1, 0, t01);
+ img->FetchTexelf(img, i0, j1, 0, t01);
if (useBorderColor & (I1BIT | J1BIT))
- COPY_CHAN4(t11, tObj->_BorderChan);
+ get_border_color(tObj, img, t11);
else
- img->FetchTexelc(img, i1, j1, 0, t11);
+ img->FetchTexelf(img, i1, j1, 0, t11);
lerp_rgba_2d(rgba[i], a, b, t00, t10, t01, t11);
}
@@ -2176,7 +2232,7 @@ static void
sample_lambda_rect(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint minStart, minEnd, magStart, magEnd;
@@ -2222,7 +2278,7 @@ sample_2d_array_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
const GLfloat texcoord[4],
- GLchan rgba[4])
+ GLfloat rgba[4])
{
const GLint width = img->Width2; /* without border, power of two */
const GLint height = img->Height2; /* without border, power of two */
@@ -2239,10 +2295,10 @@ sample_2d_array_nearest(GLcontext *ctx,
j < 0 || j >= (GLint) img->Height ||
array < 0 || array >= (GLint) img->Depth) {
/* Need this test for GL_CLAMP_TO_BORDER mode */
- COPY_CHAN4(rgba, tObj->_BorderChan);
+ get_border_color(tObj, img, rgba);
}
else {
- img->FetchTexelc(img, i, j, array, rgba);
+ img->FetchTexelf(img, i, j, array, rgba);
}
}
@@ -2255,7 +2311,7 @@ sample_2d_array_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
const GLfloat texcoord[4],
- GLchan rgba[4])
+ GLfloat rgba[4])
{
const GLint width = img->Width2;
const GLint height = img->Height2;
@@ -2264,14 +2320,14 @@ sample_2d_array_linear(GLcontext *ctx,
GLint array;
GLbitfield useBorderColor = 0x0;
GLfloat a, b;
- GLchan t00[4], t01[4], t10[4], t11[4];
+ GLfloat t00[4], t01[4], t10[4], t11[4];
linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
array = clamp_rect_coord_nearest(tObj->WrapR, texcoord[2], depth);
if (array < 0 || array >= depth) {
- COPY_CHAN4(rgba, tObj->_BorderChan);
+ COPY_4V(rgba, tObj->BorderColor);
}
else {
if (img->Border) {
@@ -2290,28 +2346,28 @@ sample_2d_array_linear(GLcontext *ctx,
/* Fetch texels */
if (useBorderColor & (I0BIT | J0BIT)) {
- COPY_CHAN4(t00, tObj->_BorderChan);
+ get_border_color(tObj, img, t00);
}
else {
- img->FetchTexelc(img, i0, j0, array, t00);
+ img->FetchTexelf(img, i0, j0, array, t00);
}
if (useBorderColor & (I1BIT | J0BIT)) {
- COPY_CHAN4(t10, tObj->_BorderChan);
+ get_border_color(tObj, img, t10);
}
else {
- img->FetchTexelc(img, i1, j0, array, t10);
+ img->FetchTexelf(img, i1, j0, array, t10);
}
if (useBorderColor & (I0BIT | J1BIT)) {
- COPY_CHAN4(t01, tObj->_BorderChan);
+ get_border_color(tObj, img, t01);
}
else {
- img->FetchTexelc(img, i0, j1, array, t01);
+ img->FetchTexelf(img, i0, j1, array, t01);
}
if (useBorderColor & (I1BIT | J1BIT)) {
- COPY_CHAN4(t11, tObj->_BorderChan);
+ get_border_color(tObj, img, t11);
}
else {
- img->FetchTexelc(img, i1, j1, array, t11);
+ img->FetchTexelf(img, i1, j1, array, t11);
}
/* trilinear interpolation of samples */
@@ -2324,7 +2380,7 @@ static void
sample_2d_array_nearest_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
for (i = 0; i < n; i++) {
@@ -2339,7 +2395,7 @@ static void
sample_2d_array_linear_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -2355,7 +2411,7 @@ static void
sample_2d_array_nearest_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -2366,7 +2422,7 @@ sample_2d_array_nearest_mipmap_linear(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level ],
texcoord[i], t0);
@@ -2382,7 +2438,7 @@ static void
sample_2d_array_linear_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -2393,7 +2449,7 @@ sample_2d_array_linear_mipmap_linear(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_2d_array_linear(ctx, tObj, tObj->Image[0][level ],
texcoord[i], t0);
@@ -2410,7 +2466,7 @@ static void
sample_nearest_2d_array(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -2427,7 +2483,7 @@ static void
sample_linear_2d_array(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -2443,7 +2499,7 @@ static void
sample_lambda_2d_array(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint minStart, minEnd; /* texels with minification */
GLuint magStart, magEnd; /* texels with magnification */
@@ -2532,7 +2588,7 @@ sample_1d_array_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
const GLfloat texcoord[4],
- GLchan rgba[4])
+ GLfloat rgba[4])
{
const GLint width = img->Width2; /* without border, power of two */
const GLint height = img->Height;
@@ -2546,10 +2602,10 @@ sample_1d_array_nearest(GLcontext *ctx,
if (i < 0 || i >= (GLint) img->Width ||
array < 0 || array >= (GLint) img->Height) {
/* Need this test for GL_CLAMP_TO_BORDER mode */
- COPY_CHAN4(rgba, tObj->_BorderChan);
+ get_border_color(tObj, img, rgba);
}
else {
- img->FetchTexelc(img, i, array, 0, rgba);
+ img->FetchTexelf(img, i, array, 0, rgba);
}
}
@@ -2562,7 +2618,7 @@ sample_1d_array_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
const struct gl_texture_image *img,
const GLfloat texcoord[4],
- GLchan rgba[4])
+ GLfloat rgba[4])
{
const GLint width = img->Width2;
const GLint height = img->Height;
@@ -2570,7 +2626,7 @@ sample_1d_array_linear(GLcontext *ctx,
GLint array;
GLbitfield useBorderColor = 0x0;
GLfloat a;
- GLchan t0[4], t1[4];
+ GLfloat t0[4], t1[4];
linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
array = clamp_rect_coord_nearest(tObj->WrapT, texcoord[1], height);
@@ -2589,16 +2645,16 @@ sample_1d_array_linear(GLcontext *ctx,
/* Fetch texels */
if (useBorderColor & (I0BIT | K0BIT)) {
- COPY_CHAN4(t0, tObj->_BorderChan);
+ get_border_color(tObj, img, t0);
}
else {
- img->FetchTexelc(img, i0, array, 0, t0);
+ img->FetchTexelf(img, i0, array, 0, t0);
}
if (useBorderColor & (I1BIT | K0BIT)) {
- COPY_CHAN4(t1, tObj->_BorderChan);
+ get_border_color(tObj, img, t1);
}
else {
- img->FetchTexelc(img, i1, array, 0, t1);
+ img->FetchTexelf(img, i1, array, 0, t1);
}
/* bilinear interpolation of samples */
@@ -2610,7 +2666,7 @@ static void
sample_1d_array_nearest_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
for (i = 0; i < n; i++) {
@@ -2625,7 +2681,7 @@ static void
sample_1d_array_linear_mipmap_nearest(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -2641,7 +2697,7 @@ static void
sample_1d_array_nearest_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -2652,7 +2708,7 @@ sample_1d_array_nearest_mipmap_linear(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
@@ -2666,7 +2722,7 @@ static void
sample_1d_array_linear_mipmap_linear(GLcontext *ctx,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
ASSERT(lambda != NULL);
@@ -2677,7 +2733,7 @@ sample_1d_array_linear_mipmap_linear(GLcontext *ctx,
texcoord[i], rgba[i]);
}
else {
- GLchan t0[4], t1[4]; /* texels */
+ GLfloat t0[4], t1[4]; /* texels */
const GLfloat f = FRAC(lambda[i]);
sample_1d_array_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
sample_1d_array_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
@@ -2692,7 +2748,7 @@ static void
sample_nearest_1d_array(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -2708,7 +2764,7 @@ static void
sample_linear_1d_array(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4],
- const GLfloat lambda[], GLchan rgba[][4])
+ const GLfloat lambda[], GLfloat rgba[][4])
{
GLuint i;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
@@ -2724,7 +2780,7 @@ static void
sample_lambda_1d_array(GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint minStart, minEnd; /* texels with minification */
GLuint magStart, magEnd; /* texels with magnification */
@@ -2796,13 +2852,109 @@ sample_lambda_1d_array(GLcontext *ctx,
/**
+ * Compare texcoord against depth sample. Return 1.0 or the ambient value.
+ */
+static INLINE GLfloat
+shadow_compare(GLenum function, GLfloat coord, GLfloat depthSample,
+ GLfloat ambient)
+{
+ switch (function) {
+ case GL_LEQUAL:
+ return (coord <= depthSample) ? 1.0F : ambient;
+ case GL_GEQUAL:
+ return (coord >= depthSample) ? 1.0F : ambient;
+ case GL_LESS:
+ return (coord < depthSample) ? 1.0F : ambient;
+ case GL_GREATER:
+ return (coord > depthSample) ? 1.0F : ambient;
+ case GL_EQUAL:
+ return (coord == depthSample) ? 1.0F : ambient;
+ case GL_NOTEQUAL:
+ return (coord != depthSample) ? 1.0F : ambient;
+ case GL_ALWAYS:
+ return 1.0F;
+ case GL_NEVER:
+ return ambient;
+ case GL_NONE:
+ return depthSample;
+ default:
+ _mesa_problem(NULL, "Bad compare func in shadow_compare");
+ return ambient;
+ }
+}
+
+
+/**
+ * Compare texcoord against four depth samples.
+ */
+static INLINE GLfloat
+shadow_compare4(GLenum function, GLfloat coord,
+ GLfloat depth00, GLfloat depth01,
+ GLfloat depth10, GLfloat depth11,
+ GLfloat ambient, GLfloat wi, GLfloat wj)
+{
+ const GLfloat d = (1.0F - (GLfloat) ambient) * 0.25F;
+ GLfloat luminance = 1.0F;
+
+ switch (function) {
+ case GL_LEQUAL:
+ if (depth00 <= coord) luminance -= d;
+ if (depth01 <= coord) luminance -= d;
+ if (depth10 <= coord) luminance -= d;
+ if (depth11 <= coord) luminance -= d;
+ return luminance;
+ case GL_GEQUAL:
+ if (depth00 >= coord) luminance -= d;
+ if (depth01 >= coord) luminance -= d;
+ if (depth10 >= coord) luminance -= d;
+ if (depth11 >= coord) luminance -= d;
+ return luminance;
+ case GL_LESS:
+ if (depth00 < coord) luminance -= d;
+ if (depth01 < coord) luminance -= d;
+ if (depth10 < coord) luminance -= d;
+ if (depth11 < coord) luminance -= d;
+ return luminance;
+ case GL_GREATER:
+ if (depth00 > coord) luminance -= d;
+ if (depth01 > coord) luminance -= d;
+ if (depth10 > coord) luminance -= d;
+ if (depth11 > coord) luminance -= d;
+ return luminance;
+ case GL_EQUAL:
+ if (depth00 == coord) luminance -= d;
+ if (depth01 == coord) luminance -= d;
+ if (depth10 == coord) luminance -= d;
+ if (depth11 == coord) luminance -= d;
+ return luminance;
+ case GL_NOTEQUAL:
+ if (depth00 != coord) luminance -= d;
+ if (depth01 != coord) luminance -= d;
+ if (depth10 != coord) luminance -= d;
+ if (depth11 != coord) luminance -= d;
+ return luminance;
+ case GL_ALWAYS:
+ return 0.0;
+ case GL_NEVER:
+ return ambient;
+ case GL_NONE:
+ /* ordinary bilinear filtering */
+ return lerp_2d(wi, wj, depth00, depth10, depth01, depth11);
+ default:
+ _mesa_problem(NULL, "Bad compare func in sample_depth_texture");
+ return 0.0F;
+ }
+}
+
+
+/**
* Sample a shadow/depth texture.
*/
static void
sample_depth_texture( GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan texel[][4] )
+ GLfloat texel[][4] )
{
const GLint baseLevel = tObj->BaseLevel;
const struct gl_texture_image *img = tObj->Image[0][baseLevel];
@@ -2811,9 +2963,9 @@ sample_depth_texture( GLcontext *ctx,
const GLint depth = img->Depth;
const GLuint compare_coord = (tObj->Target == GL_TEXTURE_2D_ARRAY_EXT)
? 3 : 2;
- GLchan ambient;
+ GLfloat ambient;
GLenum function;
- GLchan result;
+ GLfloat result;
(void) lambda;
@@ -2826,56 +2978,20 @@ sample_depth_texture( GLcontext *ctx,
tObj->Target == GL_TEXTURE_1D_ARRAY_EXT ||
tObj->Target == GL_TEXTURE_2D_ARRAY_EXT);
- UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient);
+ ambient = tObj->CompareFailValue;
/* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
- function = tObj->_Function;
+ function = (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) ?
+ tObj->CompareFunc : GL_NONE;
+
if (tObj->MagFilter == GL_NEAREST) {
GLuint i;
for (i = 0; i < n; i++) {
GLfloat depthSample;
GLint col, row, slice;
- switch (tObj->Target) {
- case GL_TEXTURE_RECTANGLE_ARB:
- col = clamp_rect_coord_nearest(tObj->WrapS, texcoords[i][0], width);
- row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height);
- slice = 0;
- break;
-
- case GL_TEXTURE_1D:
- col = nearest_texel_location(tObj->WrapS, img, width,
- texcoords[i][0]);
- row = 0;
- slice = 0;
- break;
-
- case GL_TEXTURE_2D:
- col = nearest_texel_location(tObj->WrapS, img, width,
- texcoords[i][0]);
- row = nearest_texel_location(tObj->WrapT, img, height,
- texcoords[i][1]);
- slice = 0;
- break;
-
- case GL_TEXTURE_1D_ARRAY_EXT:
- col = nearest_texel_location(tObj->WrapS, img, width,
- texcoords[i][0]);
- row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height);
- slice = 0;
- break;
-
- case GL_TEXTURE_2D_ARRAY_EXT:
- col = nearest_texel_location(tObj->WrapS, img, width,
- texcoords[i][0]);
- row = nearest_texel_location(tObj->WrapT, img, height,
- texcoords[i][1]);
- slice = clamp_rect_coord_nearest(tObj->WrapR, texcoords[i][2], depth);
- break;
- default:
- col = row = slice = 0;
- }
+ nearest_texcoord(tObj, texcoords[i], &col, &row, &slice);
if (col >= 0 && row >= 0 && col < width && row < height &&
slice >= 0 && slice < depth) {
@@ -2885,57 +3001,18 @@ sample_depth_texture( GLcontext *ctx,
depthSample = tObj->BorderColor[0];
}
- switch (function) {
- case GL_LEQUAL:
- result = (texcoords[i][compare_coord] <= depthSample) ? CHAN_MAX : ambient;
- break;
- case GL_GEQUAL:
- result = (texcoords[i][compare_coord] >= depthSample) ? CHAN_MAX : ambient;
- break;
- case GL_LESS:
- result = (texcoords[i][compare_coord] < depthSample) ? CHAN_MAX : ambient;
- break;
- case GL_GREATER:
- result = (texcoords[i][compare_coord] > depthSample) ? CHAN_MAX : ambient;
- break;
- case GL_EQUAL:
- result = (texcoords[i][compare_coord] == depthSample) ? CHAN_MAX : ambient;
- break;
- case GL_NOTEQUAL:
- result = (texcoords[i][compare_coord] != depthSample) ? CHAN_MAX : ambient;
- break;
- case GL_ALWAYS:
- result = CHAN_MAX;
- break;
- case GL_NEVER:
- result = ambient;
- break;
- case GL_NONE:
- CLAMPED_FLOAT_TO_CHAN(result, depthSample);
- break;
- default:
- _mesa_problem(ctx, "Bad compare func in sample_depth_texture");
- return;
- }
+ result = shadow_compare(function, texcoords[i][compare_coord],
+ depthSample, ambient);
switch (tObj->DepthMode) {
case GL_LUMINANCE:
- texel[i][RCOMP] = result;
- texel[i][GCOMP] = result;
- texel[i][BCOMP] = result;
- texel[i][ACOMP] = CHAN_MAX;
+ ASSIGN_4V(texel[i], result, result, result, 1.0F);
break;
case GL_INTENSITY:
- texel[i][RCOMP] = result;
- texel[i][GCOMP] = result;
- texel[i][BCOMP] = result;
- texel[i][ACOMP] = result;
+ ASSIGN_4V(texel[i], result, result, result, result);
break;
case GL_ALPHA:
- texel[i][RCOMP] = 0;
- texel[i][GCOMP] = 0;
- texel[i][BCOMP] = 0;
- texel[i][ACOMP] = result;
+ ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
break;
default:
_mesa_problem(ctx, "Bad depth texture mode");
@@ -2949,45 +3026,11 @@ sample_depth_texture( GLcontext *ctx,
GLfloat depth00, depth01, depth10, depth11;
GLint i0, i1, j0, j1;
GLint slice;
- GLfloat a, b;
+ GLfloat wi, wj;
GLuint useBorderTexel;
- switch (tObj->Target) {
- case GL_TEXTURE_RECTANGLE_ARB:
- clamp_rect_coord_linear(tObj->WrapS, texcoords[i][0],
- width, &i0, &i1, &a);
- clamp_rect_coord_linear(tObj->WrapT, texcoords[i][1],
- height, &j0, &j1, &b);
- slice = 0;
- break;
-
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- linear_texel_locations(tObj->WrapS, img, width,
- texcoords[i][0], &i0, &i1, &a);
- linear_texel_locations(tObj->WrapT, img, height,
- texcoords[i][1], &j0, &j1, &b);
- slice = 0;
- break;
-
- case GL_TEXTURE_1D_ARRAY_EXT:
- linear_texel_locations(tObj->WrapS, img, width,
- texcoords[i][0], &i0, &i1, &a);
- j0 = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height);
- j1 = j0;
- slice = 0;
- break;
-
- case GL_TEXTURE_2D_ARRAY_EXT:
- linear_texel_locations(tObj->WrapS, img, width,
- texcoords[i][0], &i0, &i1, &a);
- linear_texel_locations(tObj->WrapT, img, height,
- texcoords[i][1], &j0, &j1, &b);
- slice = clamp_rect_coord_nearest(tObj->WrapR, texcoords[i][2], depth);
- break;
- default:
- slice = 0;
- }
+ linear_texcoord(tObj, texcoords[i], &i0, &i1, &j0, &j1, &slice,
+ &wi, &wj);
useBorderTexel = 0;
if (img->Border) {
@@ -3046,213 +3089,29 @@ sample_depth_texture( GLcontext *ctx,
}
}
- if (0) {
- /* compute a single weighted depth sample and do one comparison */
- const GLfloat depthSample
- = lerp_2d(a, b, depth00, depth10, depth01, depth11);
- if ((depthSample <= texcoords[i][compare_coord] && function == GL_LEQUAL) ||
- (depthSample >= texcoords[i][compare_coord] && function == GL_GEQUAL)) {
- result = ambient;
- }
- else {
- result = CHAN_MAX;
- }
- }
- else {
- /* Do four depth/R comparisons and compute a weighted result.
- * If this touches on somebody's I.P., I'll remove this code
- * upon request.
- */
- const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F;
- GLfloat luminance = CHAN_MAXF;
-
- switch (function) {
- case GL_LEQUAL:
- if (depth00 <= texcoords[i][compare_coord]) luminance -= d;
- if (depth01 <= texcoords[i][compare_coord]) luminance -= d;
- if (depth10 <= texcoords[i][compare_coord]) luminance -= d;
- if (depth11 <= texcoords[i][compare_coord]) luminance -= d;
- result = (GLchan) luminance;
- break;
- case GL_GEQUAL:
- if (depth00 >= texcoords[i][compare_coord]) luminance -= d;
- if (depth01 >= texcoords[i][compare_coord]) luminance -= d;
- if (depth10 >= texcoords[i][compare_coord]) luminance -= d;
- if (depth11 >= texcoords[i][compare_coord]) luminance -= d;
- result = (GLchan) luminance;
- break;
- case GL_LESS:
- if (depth00 < texcoords[i][compare_coord]) luminance -= d;
- if (depth01 < texcoords[i][compare_coord]) luminance -= d;
- if (depth10 < texcoords[i][compare_coord]) luminance -= d;
- if (depth11 < texcoords[i][compare_coord]) luminance -= d;
- result = (GLchan) luminance;
- break;
- case GL_GREATER:
- if (depth00 > texcoords[i][compare_coord]) luminance -= d;
- if (depth01 > texcoords[i][compare_coord]) luminance -= d;
- if (depth10 > texcoords[i][compare_coord]) luminance -= d;
- if (depth11 > texcoords[i][compare_coord]) luminance -= d;
- result = (GLchan) luminance;
- break;
- case GL_EQUAL:
- if (depth00 == texcoords[i][compare_coord]) luminance -= d;
- if (depth01 == texcoords[i][compare_coord]) luminance -= d;
- if (depth10 == texcoords[i][compare_coord]) luminance -= d;
- if (depth11 == texcoords[i][compare_coord]) luminance -= d;
- result = (GLchan) luminance;
- break;
- case GL_NOTEQUAL:
- if (depth00 != texcoords[i][compare_coord]) luminance -= d;
- if (depth01 != texcoords[i][compare_coord]) luminance -= d;
- if (depth10 != texcoords[i][compare_coord]) luminance -= d;
- if (depth11 != texcoords[i][compare_coord]) luminance -= d;
- result = (GLchan) luminance;
- break;
- case GL_ALWAYS:
- result = 0;
- break;
- case GL_NEVER:
- result = CHAN_MAX;
- break;
- case GL_NONE:
- /* ordinary bilinear filtering */
- {
- const GLfloat depthSample
- = lerp_2d(a, b, depth00, depth10, depth01, depth11);
- CLAMPED_FLOAT_TO_CHAN(result, depthSample);
- }
- break;
- default:
- _mesa_problem(ctx, "Bad compare func in sample_depth_texture");
- return;
- }
- }
+ result = shadow_compare4(function, texcoords[i][compare_coord],
+ depth00, depth01, depth10, depth11,
+ ambient, wi, wj);
switch (tObj->DepthMode) {
case GL_LUMINANCE:
- texel[i][RCOMP] = result;
- texel[i][GCOMP] = result;
- texel[i][BCOMP] = result;
- texel[i][ACOMP] = CHAN_MAX;
+ ASSIGN_4V(texel[i], result, result, result, 1.0F);
break;
case GL_INTENSITY:
- texel[i][RCOMP] = result;
- texel[i][GCOMP] = result;
- texel[i][BCOMP] = result;
- texel[i][ACOMP] = result;
+ ASSIGN_4V(texel[i], result, result, result, result);
break;
case GL_ALPHA:
- texel[i][RCOMP] = 0;
- texel[i][GCOMP] = 0;
- texel[i][BCOMP] = 0;
- texel[i][ACOMP] = result;
+ ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
break;
default:
_mesa_problem(ctx, "Bad depth texture mode");
}
+
} /* for */
} /* if filter */
}
-#if 0
-/*
- * Experimental depth texture sampling function.
- */
-static void
-sample_depth_texture2(const GLcontext *ctx,
- const struct gl_texture_unit *texUnit,
- GLuint n, const GLfloat texcoords[][4],
- GLchan texel[][4])
-{
- const struct gl_texture_object *texObj = texUnit->_Current;
- const GLint baseLevel = texObj->BaseLevel;
- const struct gl_texture_image *texImage = texObj->Image[0][baseLevel];
- const GLuint width = texImage->Width;
- const GLuint height = texImage->Height;
- GLchan ambient;
- GLboolean lequal, gequal;
-
- if (texObj->Target != GL_TEXTURE_2D) {
- _mesa_problem(ctx, "only 2-D depth textures supported at this time");
- return;
- }
-
- if (texObj->MinFilter != texObj->MagFilter) {
- _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
- return;
- }
-
- /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
- * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
- * isn't a depth texture.
- */
- if (texImage->TexFormat->BaseFormat != GL_DEPTH_COMPONENT) {
- _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
- return;
- }
-
- UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient);
-
- if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
- lequal = GL_TRUE;
- gequal = GL_FALSE;
- }
- else {
- lequal = GL_FALSE;
- gequal = GL_TRUE;
- }
-
- {
- GLuint i;
- for (i = 0; i < n; i++) {
- const GLint K = 3;
- GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count;
- GLfloat w;
- GLchan lum;
- col = nearest_texel_location(texObj->WrapS, img, width,
- texcoords[i][0]);
- row = nearest_texel_location(texObj->WrapT, img, height,
- texcoords[i][1]);
-
- imin = col - K;
- imax = col + K;
- jmin = row - K;
- jmax = row + K;
-
- if (imin < 0) imin = 0;
- if (imax >= width) imax = width - 1;
- if (jmin < 0) jmin = 0;
- if (jmax >= height) jmax = height - 1;
-
- samples = (imax - imin + 1) * (jmax - jmin + 1);
- count = 0;
- for (jj = jmin; jj <= jmax; jj++) {
- for (ii = imin; ii <= imax; ii++) {
- GLfloat depthSample;
- texImage->FetchTexelf(texImage, ii, jj, 0, &depthSample);
- if ((depthSample <= r[i] && lequal) ||
- (depthSample >= r[i] && gequal)) {
- count++;
- }
- }
- }
-
- w = (GLfloat) count / (GLfloat) samples;
- w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient);
- lum = (GLint) w;
-
- texel[i][RCOMP] = lum;
- texel[i][GCOMP] = lum;
- texel[i][BCOMP] = lum;
- texel[i][ACOMP] = CHAN_MAX;
- }
- }
-}
-#endif
-
-
/**
* We use this function when a texture object is in an "incomplete" state.
* When a fragment program attempts to sample an incomplete texture we
@@ -3263,7 +3122,7 @@ static void
null_sample_func( GLcontext *ctx,
const struct gl_texture_object *tObj, GLuint n,
const GLfloat texcoords[][4], const GLfloat lambda[],
- GLchan rgba[][4])
+ GLfloat rgba[][4])
{
GLuint i;
(void) ctx;
diff --git a/src/mesa/swrast/s_texstore.c b/src/mesa/swrast/s_texstore.c
index 16b00b9fa1..f9ff9ad6a4 100644
--- a/src/mesa/swrast/s_texstore.c
+++ b/src/mesa/swrast/s_texstore.c
@@ -67,7 +67,6 @@ static GLvoid *
read_color_image( GLcontext *ctx, GLint x, GLint y, GLenum type,
GLsizei width, GLsizei height )
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
const GLint pixelSize = _mesa_bytes_per_pixel(GL_RGBA, type);
const GLint stride = width * pixelSize;
@@ -78,7 +77,7 @@ read_color_image( GLcontext *ctx, GLint x, GLint y, GLenum type,
if (!image)
return NULL;
- RENDER_START(swrast, ctx);
+ swrast_render_start(ctx);
dst = image;
for (row = 0; row < height; row++) {
@@ -86,7 +85,7 @@ read_color_image( GLcontext *ctx, GLint x, GLint y, GLenum type,
dst += stride;
}
- RENDER_FINISH(swrast, ctx);
+ swrast_render_finish(ctx);
return image;
}
@@ -101,7 +100,6 @@ read_depth_image( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height )
{
struct gl_renderbuffer *rb = ctx->ReadBuffer->_DepthBuffer;
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint *image, *dst;
GLint i;
@@ -109,7 +107,7 @@ read_depth_image( GLcontext *ctx, GLint x, GLint y,
if (!image)
return NULL;
- RENDER_START(swrast, ctx);
+ swrast_render_start(ctx);
dst = image;
for (i = 0; i < height; i++) {
@@ -117,7 +115,7 @@ read_depth_image( GLcontext *ctx, GLint x, GLint y,
dst += width;
}
- RENDER_FINISH(swrast, ctx);
+ swrast_render_finish(ctx);
return image;
}
@@ -132,7 +130,6 @@ read_depth_stencil_image(GLcontext *ctx, GLint x, GLint y,
{
struct gl_renderbuffer *depthRb = ctx->ReadBuffer->_DepthBuffer;
struct gl_renderbuffer *stencilRb = ctx->ReadBuffer->_StencilBuffer;
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint *image, *dst;
GLint i;
@@ -143,7 +140,7 @@ read_depth_stencil_image(GLcontext *ctx, GLint x, GLint y,
if (!image)
return NULL;
- RENDER_START(swrast, ctx);
+ swrast_render_start(ctx);
/* read from depth buffer */
dst = image;
@@ -205,7 +202,7 @@ read_depth_stencil_image(GLcontext *ctx, GLint x, GLint y,
dst += width;
}
- RENDER_FINISH(swrast, ctx);
+ swrast_render_finish(ctx);
return image;
}
diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c
index a2e8433e27..1ab0e19f92 100644
--- a/src/mesa/swrast/s_triangle.c
+++ b/src/mesa/swrast/s_triangle.c
@@ -35,6 +35,7 @@
#include "main/imports.h"
#include "main/macros.h"
#include "main/texformat.h"
+#include "shader/prog_instruction.h"
#include "s_aatriangle.h"
#include "s_context.h"
@@ -43,8 +44,9 @@
#include "s_triangle.h"
-/*
- * Just used for feedback mode.
+/**
+ * Test if a triangle should be culled. Used for feedback and selection mode.
+ * \return GL_TRUE if the triangle is to be culled, GL_FALSE otherwise.
*/
GLboolean
_swrast_culltriangle( GLcontext *ctx,
@@ -52,16 +54,17 @@ _swrast_culltriangle( GLcontext *ctx,
const SWvertex *v1,
const SWvertex *v2 )
{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLfloat ex = v1->attrib[FRAG_ATTRIB_WPOS][0] - v0->attrib[FRAG_ATTRIB_WPOS][0];
GLfloat ey = v1->attrib[FRAG_ATTRIB_WPOS][1] - v0->attrib[FRAG_ATTRIB_WPOS][1];
GLfloat fx = v2->attrib[FRAG_ATTRIB_WPOS][0] - v0->attrib[FRAG_ATTRIB_WPOS][0];
GLfloat fy = v2->attrib[FRAG_ATTRIB_WPOS][1] - v0->attrib[FRAG_ATTRIB_WPOS][1];
GLfloat c = ex*fy-ey*fx;
- if (c * SWRAST_CONTEXT(ctx)->_BackfaceCullSign > 0)
- return 0;
+ if (c * swrast->_BackfaceSign * swrast->_BackfaceCullSign <= 0.0F)
+ return GL_FALSE;
- return 1;
+ return GL_TRUE;
}
@@ -131,7 +134,8 @@ _swrast_culltriangle( GLcontext *ctx,
#define SETUP_CODE \
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \
- struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
+ struct gl_texture_object *obj = \
+ ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \
const GLint b = obj->BaseLevel; \
const GLfloat twidth = (GLfloat) obj->Image[0][b]->Width; \
const GLfloat theight = (GLfloat) obj->Image[0][b]->Height; \
@@ -182,7 +186,8 @@ _swrast_culltriangle( GLcontext *ctx,
#define SETUP_CODE \
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \
- struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
+ struct gl_texture_object *obj = \
+ ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \
const GLint b = obj->BaseLevel; \
const GLfloat twidth = (GLfloat) obj->Image[0][b]->Width; \
const GLfloat theight = (GLfloat) obj->Image[0][b]->Height; \
@@ -263,10 +268,7 @@ affine_span(GLcontext *ctx, SWspan *span,
struct affine_info *info)
{
GLchan sample[4]; /* the filtered texture sample */
- const GLuint texEnableSave = ctx->Texture._EnabledUnits;
-
- /* Disable tex units so they're not re-applied in swrast_write_rgba_span */
- ctx->Texture._EnabledUnits = 0x0;
+ const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits;
/* Instead of defining a function for each mode, a test is done
* between the outer and inner loops. This is to reduce code size
@@ -396,6 +398,9 @@ affine_span(GLcontext *ctx, SWspan *span,
GLuint i;
GLchan *dest = span->array->rgba[0];
+ /* Disable tex units so they're not re-applied in swrast_write_rgba_span */
+ ctx->Texture._EnabledCoordUnits = 0x0;
+
span->intTex[0] -= FIXED_HALF;
span->intTex[1] -= FIXED_HALF;
switch (info->filter) {
@@ -501,7 +506,7 @@ affine_span(GLcontext *ctx, SWspan *span,
_swrast_write_rgba_span(ctx, span);
/* re-enable texture units */
- ctx->Texture._EnabledUnits = texEnableSave;
+ ctx->Texture._EnabledCoordUnits = texEnableSave;
#undef SPAN_NEAREST
#undef SPAN_LINEAR
@@ -523,7 +528,8 @@ affine_span(GLcontext *ctx, SWspan *span,
#define SETUP_CODE \
struct affine_info info; \
struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
- struct gl_texture_object *obj = unit->Current2D; \
+ struct gl_texture_object *obj = \
+ ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \
const GLint b = obj->BaseLevel; \
const GLfloat twidth = (GLfloat) obj->Image[0][b]->Width; \
const GLfloat theight = (GLfloat) obj->Image[0][b]->Height; \
@@ -660,8 +666,8 @@ fast_persp_span(GLcontext *ctx, SWspan *span,
GLfloat tex_coord[3], tex_step[3];
GLchan *dest = span->array->rgba[0];
- const GLuint savedTexEnable = ctx->Texture._EnabledUnits;
- ctx->Texture._EnabledUnits = 0;
+ const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits;
+ ctx->Texture._EnabledCoordUnits = 0;
tex_coord[0] = span->attrStart[FRAG_ATTRIB_TEX0][0] * (info->smask + 1);
tex_step[0] = span->attrStepX[FRAG_ATTRIB_TEX0][0] * (info->smask + 1);
@@ -774,7 +780,7 @@ fast_persp_span(GLcontext *ctx, SWspan *span,
#undef SPAN_LINEAR
/* restore state */
- ctx->Texture._EnabledUnits = savedTexEnable;
+ ctx->Texture._EnabledCoordUnits = texEnableSave;
}
@@ -793,7 +799,8 @@ fast_persp_span(GLcontext *ctx, SWspan *span,
#define SETUP_CODE \
struct persp_info info; \
const struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
- const struct gl_texture_object *obj = unit->Current2D; \
+ struct gl_texture_object *obj = \
+ ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \
const GLint b = obj->BaseLevel; \
info.texture = (const GLchan *) obj->Image[0][b]->Data; \
info.twidth_log2 = obj->Image[0][b]->WidthLog2; \
@@ -1017,7 +1024,7 @@ _swrast_choose_triangle( GLcontext *ctx )
ctx->Depth.Test &&
ctx->Depth.Mask == GL_FALSE &&
ctx->Depth.Func == GL_LESS &&
- !ctx->Stencil.Enabled) {
+ !ctx->Stencil._Enabled) {
if ((rgbmode &&
ctx->Color.ColorMask[0] == 0 &&
ctx->Color.ColorMask[1] == 0 &&
@@ -1049,7 +1056,8 @@ _swrast_choose_triangle( GLcontext *ctx )
const struct gl_texture_image *texImg;
GLenum minFilter, magFilter, envMode;
GLint format;
- texObj2D = ctx->Texture.Unit[0].Current2D;
+ texObj2D = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];
+
texImg = texObj2D ? texObj2D->Image[0][texObj2D->BaseLevel] : NULL;
format = texImg ? texImg->TexFormat->MesaFormat : -1;
minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0;
@@ -1063,6 +1071,7 @@ _swrast_choose_triangle( GLcontext *ctx )
&& ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT
&& texObj2D->WrapS == GL_REPEAT
&& texObj2D->WrapT == GL_REPEAT
+ && texObj2D->_Swizzle == SWIZZLE_NOOP
&& texImg->_IsPowerOfTwo
&& texImg->Border == 0
&& texImg->Width == texImg->RowStride
@@ -1070,7 +1079,8 @@ _swrast_choose_triangle( GLcontext *ctx )
&& minFilter == magFilter
&& ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
&& !swrast->_FogEnabled
- && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) {
+ && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT
+ && ctx->Texture.Unit[0].EnvMode != GL_COMBINE4_NV) {
if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
if (minFilter == GL_NEAREST
&& format == MESA_FORMAT_RGB
diff --git a/src/mesa/swrast/swrast.h b/src/mesa/swrast/swrast.h
index 047f7991e6..a85d69bfbf 100644
--- a/src/mesa/swrast/swrast.h
+++ b/src/mesa/swrast/swrast.h
@@ -33,6 +33,7 @@
#define SWRAST_H
#include "main/mtypes.h"
+#include "swrast_features.h"
/**
* \struct SWvertex
@@ -75,6 +76,12 @@ typedef struct {
} SWvertex;
+/**
+ * Fixed point data type.
+ */
+typedef int GLfixed;
+
+
#define FRAG_ATTRIB_CI FRAG_ATTRIB_COL0
@@ -96,28 +103,6 @@ extern struct swrast_device_driver *
_swrast_GetDeviceDriverReference( GLcontext *ctx );
extern void
-_swrast_Bitmap( GLcontext *ctx,
- GLint px, GLint py,
- GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap );
-
-extern void
-_swrast_CopyPixels( GLcontext *ctx,
- GLint srcx, GLint srcy,
- GLint destx, GLint desty,
- GLsizei width, GLsizei height,
- GLenum type );
-
-extern void
-_swrast_DrawPixels( GLcontext *ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *pixels );
-
-extern void
_swrast_ReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
@@ -133,10 +118,6 @@ _swrast_BlitFramebuffer(GLcontext *ctx,
extern void
_swrast_Clear(GLcontext *ctx, GLbitfield buffers);
-extern void
-_swrast_Accum(GLcontext *ctx, GLenum op, GLfloat value);
-
-
/* Reset the stipple counter
*/
@@ -202,28 +183,6 @@ _swrast_print_vertex( GLcontext *ctx, const SWvertex *v );
/*
- * Imaging fallbacks (a better solution should be found, perhaps
- * moving all the imaging fallback code to a new module)
- */
-extern void
-_swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
- GLenum internalFormat,
- GLint x, GLint y, GLsizei width,
- GLsizei height);
-extern void
-_swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
- GLenum internalFormat,
- GLint x, GLint y, GLsizei width);
-extern void
-_swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
- GLint x, GLint y, GLsizei width);
-extern void
-_swrast_CopyColorTable( GLcontext *ctx,
- GLenum target, GLenum internalformat,
- GLint x, GLint y, GLsizei width);
-
-
-/*
* Texture fallbacks. Could also live in a new module
* with the rest of the texture store fallbacks?
*/
@@ -260,12 +219,6 @@ extern void
_swrast_eject_texture_images(GLcontext *ctx);
-#if FEATURE_MESA_program_debug
-extern void
-_swrast_get_program_register(GLcontext *, enum register_file file,
- GLuint index, GLfloat val[4]);
-#endif /* FEATURE_MESA_program_debug */
-
/**
* The driver interface for the software rasterizer.
@@ -287,6 +240,4 @@ struct swrast_device_driver {
void (*SpanRenderFinish)(GLcontext *ctx);
};
-
-
-#endif
+#endif /* SWRAST_H */
diff --git a/src/mesa/swrast/swrast_features.h b/src/mesa/swrast/swrast_features.h
new file mode 100644
index 0000000000..486d607eb9
--- /dev/null
+++ b/src/mesa/swrast/swrast_features.h
@@ -0,0 +1,142 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/**
+ * \file swrast/swrast_features.h
+ * \brief Public interface to the software rasterization functions.
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SWRAST_FEATURES_H
+#define SWRAST_FEATURES_H
+
+#include "main/mtypes.h"
+
+
+#if FEATURE_accum
+
+extern void
+_swrast_Accum(GLcontext *ctx, GLenum op, GLfloat value);
+
+#endif
+
+
+/*
+ * Imaging fallbacks (a better solution should be found, perhaps
+ * moving all the imaging fallback code to a new module)
+ */
+#if FEATURE_convolve
+
+extern void
+_swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width,
+ GLsizei height);
+
+extern void
+_swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width);
+
+#endif
+
+
+#if FEATURE_colortable
+
+extern void
+_swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width);
+
+extern void
+_swrast_CopyColorTable( GLcontext *ctx,
+ GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width);
+
+#define _swrast_UpdateTexturePalette NULL
+
+#endif
+
+
+#if FEATURE_drawpix
+
+extern void
+_swrast_Bitmap( GLcontext *ctx,
+ GLint px, GLint py,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap );
+
+extern void
+_swrast_CopyPixels( GLcontext *ctx,
+ GLint srcx, GLint srcy,
+ GLint destx, GLint desty,
+ GLsizei width, GLsizei height,
+ GLenum type );
+
+extern void
+_swrast_DrawPixels( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels );
+
+#else /* FEATURE_drawpix */
+
+static INLINE void
+_swrast_Bitmap( GLcontext *ctx,
+ GLint px, GLint py,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap )
+{
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_swrast_CopyPixels( GLcontext *ctx,
+ GLint srcx, GLint srcy,
+ GLint destx, GLint desty,
+ GLsizei width, GLsizei height,
+ GLenum type )
+{
+ ASSERT_NO_FEATURE();
+}
+
+static INLINE void
+_swrast_DrawPixels( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ ASSERT_NO_FEATURE();
+}
+
+#endif
+
+
+#endif /* SWRAST_FEATURES_H */
diff --git a/src/mesa/swrast_setup/ss_triangle.c b/src/mesa/swrast_setup/ss_triangle.c
index 54e24c4c44..e15b1348d8 100644
--- a/src/mesa/swrast_setup/ss_triangle.c
+++ b/src/mesa/swrast_setup/ss_triangle.c
@@ -45,46 +45,32 @@ static tnl_triangle_func tri_tab[SS_MAX_TRIFUNC];
static tnl_quad_func quad_tab[SS_MAX_TRIFUNC];
-static void _swsetup_render_line_tri( GLcontext *ctx,
- GLuint e0, GLuint e1, GLuint e2,
- GLuint facing )
+/*
+ * Render a triangle respecting edge flags.
+ */
+typedef void (* swsetup_edge_render_prim_tri)(GLcontext *ctx,
+ const GLubyte *ef,
+ GLuint e0,
+ GLuint e1,
+ GLuint e2,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2);
+
+/*
+ * Render a triangle using lines and respecting edge flags.
+ */
+static void
+_swsetup_edge_render_line_tri(GLcontext *ctx,
+ const GLubyte *ef,
+ GLuint e0,
+ GLuint e1,
+ GLuint e2,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2)
{
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
- struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
- GLubyte *ef = VB->EdgeFlag;
- SWvertex *verts = swsetup->verts;
- SWvertex *v0 = &verts[e0];
- SWvertex *v1 = &verts[e1];
- SWvertex *v2 = &verts[e2];
- GLchan c[2][4];
- GLfloat s[2][4];
- GLfloat i[2];
-
- /* cull testing */
- if (ctx->Polygon.CullFlag) {
- if (facing == 1 && ctx->Polygon.CullFaceMode != GL_FRONT)
- return;
- if (facing == 0 && ctx->Polygon.CullFaceMode != GL_BACK)
- return;
- }
-
- _swrast_SetFacing(ctx, facing);
-
- if (ctx->Light.ShadeModel == GL_FLAT) {
- COPY_CHAN4(c[0], v0->color);
- COPY_CHAN4(c[1], v1->color);
- COPY_4V(s[0], v0->attrib[FRAG_ATTRIB_COL1]);
- COPY_4V(s[1], v1->attrib[FRAG_ATTRIB_COL1]);
- i[0] = v0->attrib[FRAG_ATTRIB_CI][0];
- i[1] = v1->attrib[FRAG_ATTRIB_CI][0];
-
- COPY_CHAN4(v0->color, v2->color);
- COPY_CHAN4(v1->color, v2->color);
- COPY_4V(v0->attrib[FRAG_ATTRIB_COL1], v2->attrib[FRAG_ATTRIB_COL1]);
- COPY_4V(v1->attrib[FRAG_ATTRIB_COL1], v2->attrib[FRAG_ATTRIB_COL1]);
- v0->attrib[FRAG_ATTRIB_CI][0] = v2->attrib[FRAG_ATTRIB_CI][0];
- v1->attrib[FRAG_ATTRIB_CI][0] = v2->attrib[FRAG_ATTRIB_CI][0];
- }
if (swsetup->render_prim == GL_POLYGON) {
if (ef[e2]) _swrast_Line( ctx, v2, v0 );
@@ -95,20 +81,37 @@ static void _swsetup_render_line_tri( GLcontext *ctx,
if (ef[e1]) _swrast_Line( ctx, v1, v2 );
if (ef[e2]) _swrast_Line( ctx, v2, v0 );
}
+}
- if (ctx->Light.ShadeModel == GL_FLAT) {
- COPY_CHAN4(v0->color, c[0]);
- COPY_CHAN4(v1->color, c[1]);
- COPY_4V(v0->attrib[FRAG_ATTRIB_COL1], s[0]);
- COPY_4V(v1->attrib[FRAG_ATTRIB_COL1], s[1]);
- v0->attrib[FRAG_ATTRIB_CI][0] = i[0];
- v1->attrib[FRAG_ATTRIB_CI][0] = i[1];
- }
+/*
+ * Render a triangle using points and respecting edge flags.
+ */
+static void
+_swsetup_edge_render_point_tri(GLcontext *ctx,
+ const GLubyte *ef,
+ GLuint e0,
+ GLuint e1,
+ GLuint e2,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2)
+{
+ if (ef[e0]) _swrast_Point( ctx, v0 );
+ if (ef[e1]) _swrast_Point( ctx, v1 );
+ if (ef[e2]) _swrast_Point( ctx, v2 );
+
+ _swrast_flush(ctx);
}
-static void _swsetup_render_point_tri( GLcontext *ctx,
- GLuint e0, GLuint e1, GLuint e2,
- GLuint facing )
+/*
+ * Render a triangle respecting cull and shade model.
+ */
+static void _swsetup_render_tri(GLcontext *ctx,
+ GLuint e0,
+ GLuint e1,
+ GLuint e2,
+ GLuint facing,
+ swsetup_edge_render_prim_tri render)
{
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
@@ -117,9 +120,6 @@ static void _swsetup_render_point_tri( GLcontext *ctx,
SWvertex *v0 = &verts[e0];
SWvertex *v1 = &verts[e1];
SWvertex *v2 = &verts[e2];
- GLchan c[2][4];
- GLfloat s[2][4];
- GLfloat i[2];
/* cull testing */
if (ctx->Polygon.CullFlag) {
@@ -132,6 +132,10 @@ static void _swsetup_render_point_tri( GLcontext *ctx,
_swrast_SetFacing(ctx, facing);
if (ctx->Light.ShadeModel == GL_FLAT) {
+ GLchan c[2][4];
+ GLfloat s[2][4];
+ GLfloat i[2];
+
/* save colors/indexes for v0, v1 vertices */
COPY_CHAN4(c[0], v0->color);
COPY_CHAN4(c[1], v1->color);
@@ -147,14 +151,9 @@ static void _swsetup_render_point_tri( GLcontext *ctx,
COPY_4V(v1->attrib[FRAG_ATTRIB_COL1], v2->attrib[FRAG_ATTRIB_COL1]);
v0->attrib[FRAG_ATTRIB_CI][0] = v2->attrib[FRAG_ATTRIB_CI][0];
v1->attrib[FRAG_ATTRIB_CI][0] = v2->attrib[FRAG_ATTRIB_CI][0];
- }
- if (ef[e0]) _swrast_Point( ctx, v0 );
- if (ef[e1]) _swrast_Point( ctx, v1 );
- if (ef[e2]) _swrast_Point( ctx, v2 );
+ render(ctx, ef, e0, e1, e2, v0, v1, v2);
- if (ctx->Light.ShadeModel == GL_FLAT) {
- /* restore v0, v1 colores/indexes */
COPY_CHAN4(v0->color, c[0]);
COPY_CHAN4(v1->color, c[1]);
COPY_4V(v0->attrib[FRAG_ATTRIB_COL1], s[0]);
@@ -162,7 +161,9 @@ static void _swsetup_render_point_tri( GLcontext *ctx,
v0->attrib[FRAG_ATTRIB_CI][0] = i[0];
v1->attrib[FRAG_ATTRIB_CI][0] = i[1];
}
- _swrast_flush(ctx);
+ else {
+ render(ctx, ef, e0, e1, e2, v0, v1, v2);
+ }
}
#define SS_COLOR(a,b) UNCLAMPED_FLOAT_TO_RGBA_CHAN(a,b)
diff --git a/src/mesa/swrast_setup/ss_tritmp.h b/src/mesa/swrast_setup/ss_tritmp.h
index 97d2f4a16b..724b5e94fa 100644
--- a/src/mesa/swrast_setup/ss_tritmp.h
+++ b/src/mesa/swrast_setup/ss_tritmp.h
@@ -171,14 +171,14 @@ static void TAG(triangle)(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2 )
v[1]->attrib[FRAG_ATTRIB_WPOS][2] = oz1;
v[2]->attrib[FRAG_ATTRIB_WPOS][2] = oz2;
}
- _swsetup_render_point_tri( ctx, e0, e1, e2, facing );
+ _swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_point_tri);
} else if (mode == GL_LINE) {
if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetLine) {
v[0]->attrib[FRAG_ATTRIB_WPOS][2] = oz0;
v[1]->attrib[FRAG_ATTRIB_WPOS][2] = oz1;
v[2]->attrib[FRAG_ATTRIB_WPOS][2] = oz2;
}
- _swsetup_render_line_tri( ctx, e0, e1, e2, facing );
+ _swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_line_tri);
} else {
if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetFill) {
v[0]->attrib[FRAG_ATTRIB_WPOS][2] = oz0;
diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c
index 5e2a58249e..f2771cde09 100644
--- a/src/mesa/tnl/t_context.c
+++ b/src/mesa/tnl/t_context.c
@@ -32,6 +32,8 @@
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/light.h"
+#include "math/m_translate.h"
+#include "math/m_xform.h"
#include "tnl.h"
#include "t_context.h"
@@ -78,6 +80,12 @@ _tnl_CreateContext( GLcontext *ctx )
tnl->nr_blocks = 0;
+ /* plug in the VBO drawing function */
+ vbo_set_draw_func(ctx, _tnl_vbo_draw_prims);
+
+ _math_init_transformation();
+ _math_init_translate();
+
return GL_TRUE;
}
@@ -109,24 +117,28 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state )
tnl->pipeline.new_state |= new_state;
- /* Calculate tnl->render_inputs:
+ /* Calculate tnl->render_inputs. This bitmask indicates which vertex
+ * attributes need to be emitted to the rasterizer.
*/
if (ctx->Visual.rgbMode) {
GLuint i;
RENDERINPUTS_ZERO( tnl->render_inputs_bitset );
RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POS );
+
if (!fp || (fp->Base.InputsRead & FRAG_BIT_COL0)) {
RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR0 );
}
+
+ if (NEED_SECONDARY_COLOR(ctx))
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 );
+
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
- if (ctx->Texture._EnabledCoordUnits & (1 << i)) {
+ if (ctx->Texture._EnabledCoordUnits & (1 << i) ||
+ (fp && fp->Base.InputsRead & FRAG_BIT_TEX(i))) {
RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX(i) );
}
}
-
- if (NEED_SECONDARY_COLOR(ctx))
- RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 );
}
else {
RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POS );
@@ -137,13 +149,10 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state )
/* fixed-function fog */
RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG );
}
- else if (ctx->FragmentProgram._Current) {
- struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
- if (fp) {
- if (fp->FogOption != GL_NONE || (fp->Base.InputsRead & FRAG_BIT_FOGC)) {
- /* fragment program needs fog coord */
- RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG );
- }
+ else if (fp) {
+ if (fp->FogOption != GL_NONE || (fp->Base.InputsRead & FRAG_BIT_FOGC)) {
+ /* fragment program needs fog coord */
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG );
}
}
diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h
index 0a6ce04614..6137c2d2fe 100644
--- a/src/mesa/tnl/t_context.h
+++ b/src/mesa/tnl/t_context.h
@@ -50,6 +50,7 @@
#define _T_CONTEXT_H
#include "main/glheader.h"
+#include "main/bitset.h"
#include "main/mtypes.h"
#include "math/m_matrix.h"
@@ -547,4 +548,8 @@ typedef struct
#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */
+extern void
+tnl_clip_prepare(GLcontext *ctx);
+
+
#endif
diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c
index fd647c1f4a..04fa106300 100644
--- a/src/mesa/tnl/t_draw.c
+++ b/src/mesa/tnl/t_draw.c
@@ -88,6 +88,29 @@ static void free_space(GLcontext *ctx)
} while (0)
+/**
+ * Convert array of BGRA/GLubyte[4] values to RGBA/float[4]
+ * \param ptr input/ubyte array
+ * \param fptr output/float array
+ */
+static void
+convert_bgra_to_float(const struct gl_client_array *input,
+ const GLubyte *ptr, GLfloat *fptr,
+ GLuint count )
+{
+ GLuint i;
+ assert(input->Normalized);
+ assert(input->Size == 4);
+ for (i = 0; i < count; i++) {
+ const GLubyte *in = (GLubyte *) ptr; /* in is in BGRA order */
+ *fptr++ = UBYTE_TO_FLOAT(in[2]); /* red */
+ *fptr++ = UBYTE_TO_FLOAT(in[1]); /* green */
+ *fptr++ = UBYTE_TO_FLOAT(in[0]); /* blue */
+ *fptr++ = UBYTE_TO_FLOAT(in[3]); /* alpha */
+ ptr += input->StrideB;
+ }
+}
+
/* Adjust pointer to point at first requested element, convert to
* floating point, populate VB->AttribPtr[].
@@ -112,7 +135,13 @@ static void _tnl_import_array( GLcontext *ctx,
CONVERT(GLbyte, BYTE_TO_FLOAT);
break;
case GL_UNSIGNED_BYTE:
- CONVERT(GLubyte, UBYTE_TO_FLOAT);
+ if (input->Format == GL_BGRA) {
+ /* See GL_EXT_vertex_array_bgra */
+ convert_bgra_to_float(input, ptr, fptr, count);
+ }
+ else {
+ CONVERT(GLubyte, UBYTE_TO_FLOAT);
+ }
break;
case GL_SHORT:
CONVERT(GLshort, SHORT_TO_FLOAT);
@@ -287,22 +316,27 @@ static void bind_indices( GLcontext *ctx,
ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
- if (ib->type == GL_UNSIGNED_INT) {
+ if (ib->type == GL_UNSIGNED_INT && VB->Primitive[0].basevertex == 0) {
VB->Elts = (GLuint *) ptr;
}
else {
GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
VB->Elts = elts;
- if (ib->type == GL_UNSIGNED_SHORT) {
+ if (ib->type == GL_UNSIGNED_INT) {
+ const GLuint *in = (GLuint *)ptr;
+ for (i = 0; i < ib->count; i++)
+ *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
+ }
+ else if (ib->type == GL_UNSIGNED_SHORT) {
const GLushort *in = (GLushort *)ptr;
for (i = 0; i < ib->count; i++)
- *elts++ = (GLuint)(*in++);
+ *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
}
else {
const GLubyte *in = (GLubyte *)ptr;
for (i = 0; i < ib->count; i++)
- *elts++ = (GLuint)(*in++);
+ *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
}
}
}
@@ -331,6 +365,20 @@ static void unmap_vbos( GLcontext *ctx,
}
+void _tnl_vbo_draw_prims(GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index)
+{
+ if (!index_bounds_valid)
+ vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+
+ _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
+}
/* This is the main entrypoint into the slimmed-down software tnl
* module. In a regular swtnl driver, this can be plugged straight
@@ -347,10 +395,14 @@ void _tnl_draw_prims( GLcontext *ctx,
TNLcontext *tnl = TNL_CONTEXT(ctx);
const GLuint TEST_SPLIT = 0;
const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
+ GLuint max_basevertex = prim->basevertex;
+ GLuint i;
+
+ for (i = 1; i < nr_prims; i++)
+ max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
if (0)
{
- GLuint i;
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
for (i = 0; i < nr_prims; i++)
_mesa_printf("prim %d: %s start %d count %d\n", i,
@@ -364,10 +416,10 @@ void _tnl_draw_prims( GLcontext *ctx,
*/
vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib,
min_index, max_index,
- _tnl_draw_prims );
+ _tnl_vbo_draw_prims );
return;
}
- else if (max_index > max) {
+ else if (max_index + max_basevertex > max) {
/* The software TNL pipeline has a fixed amount of storage for
* vertices and it is necessary to split incoming drawing commands
* if they exceed that limit.
@@ -381,8 +433,8 @@ void _tnl_draw_prims( GLcontext *ctx,
* recursively call back into this function.
*/
vbo_split_prims( ctx, arrays, prim, nr_prims, ib,
- 0, max_index,
- _tnl_draw_prims,
+ 0, max_index + prim->basevertex,
+ _tnl_vbo_draw_prims,
&limits );
}
else {
@@ -392,17 +444,34 @@ void _tnl_draw_prims( GLcontext *ctx,
struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
GLuint nr_bo = 0;
- /* Binding inputs may imply mapping some vertex buffer objects.
- * They will need to be unmapped below.
- */
- bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo);
- bind_indices(ctx, ib, bo, &nr_bo);
- bind_prims(ctx, prim, nr_prims );
+ for (i = 0; i < nr_prims;) {
+ GLuint this_nr_prims;
+
+ /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
+ * will rebase the elements to the basevertex, and we'll only
+ * emit strings of prims with the same basevertex in one draw call.
+ */
+ for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
+ this_nr_prims++) {
+ if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
+ break;
+ }
+
+ /* Binding inputs may imply mapping some vertex buffer objects.
+ * They will need to be unmapped below.
+ */
+ bind_prims(ctx, &prim[i], this_nr_prims);
+ bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1,
+ bo, &nr_bo);
+ bind_indices(ctx, ib, bo, &nr_bo);
- TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
+ TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
- unmap_vbos(ctx, bo, nr_bo);
- free_space(ctx);
+ unmap_vbos(ctx, bo, nr_bo);
+ free_space(ctx);
+
+ i += this_nr_prims;
+ }
}
}
diff --git a/src/mesa/tnl/t_rasterpos.c b/src/mesa/tnl/t_rasterpos.c
index dfbe0f1806..a8cf86060f 100644
--- a/src/mesa/tnl/t_rasterpos.c
+++ b/src/mesa/tnl/t_rasterpos.c
@@ -26,17 +26,19 @@
#include "main/glheader.h"
#include "main/colormac.h"
#include "main/context.h"
-#include "feedback.h"
-#include "light.h"
+#include "main/feedback.h"
+#include "main/light.h"
#include "main/macros.h"
-#include "rastpos.h"
-#include "simple_list.h"
+#include "main/rastpos.h"
+#include "main/simple_list.h"
#include "main/mtypes.h"
#include "math/m_matrix.h"
#include "tnl/tnl.h"
+#if FEATURE_rastpos
+
/**
* Clip a point against the view volume.
@@ -46,11 +48,10 @@
* \return zero if outside view volume, or one if inside.
*/
static GLuint
-viewclip_point( const GLfloat v[] )
+viewclip_point_xy( const GLfloat v[] )
{
if ( v[0] > v[3] || v[0] < -v[3]
- || v[1] > v[3] || v[1] < -v[3]
- || v[2] > v[3] || v[2] < -v[3] ) {
+ || v[1] > v[3] || v[1] < -v[3] ) {
return 0;
}
else {
@@ -167,7 +168,7 @@ shade_rastpos(GLcontext *ctx,
light->QuadraticAttenuation));
if (light->_Flags & LIGHT_SPOT) {
- GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
if (PV_dot_dir<light->_CosCutoff) {
continue;
@@ -301,12 +302,12 @@ compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4],
mInv = 0.0F;
if (texUnit->TexGenEnabled & S_BIT) {
- switch (texUnit->GenModeS) {
+ switch (texUnit->GenS.Mode) {
case GL_OBJECT_LINEAR:
- texcoord[0] = DOT4(vObj, texUnit->ObjectPlaneS);
+ texcoord[0] = DOT4(vObj, texUnit->GenS.ObjectPlane);
break;
case GL_EYE_LINEAR:
- texcoord[0] = DOT4(vEye, texUnit->EyePlaneS);
+ texcoord[0] = DOT4(vEye, texUnit->GenS.EyePlane);
break;
case GL_SPHERE_MAP:
texcoord[0] = rx * mInv + 0.5F;
@@ -324,12 +325,12 @@ compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4],
}
if (texUnit->TexGenEnabled & T_BIT) {
- switch (texUnit->GenModeT) {
+ switch (texUnit->GenT.Mode) {
case GL_OBJECT_LINEAR:
- texcoord[1] = DOT4(vObj, texUnit->ObjectPlaneT);
+ texcoord[1] = DOT4(vObj, texUnit->GenT.ObjectPlane);
break;
case GL_EYE_LINEAR:
- texcoord[1] = DOT4(vEye, texUnit->EyePlaneT);
+ texcoord[1] = DOT4(vEye, texUnit->GenT.EyePlane);
break;
case GL_SPHERE_MAP:
texcoord[1] = ry * mInv + 0.5F;
@@ -347,12 +348,12 @@ compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4],
}
if (texUnit->TexGenEnabled & R_BIT) {
- switch (texUnit->GenModeR) {
+ switch (texUnit->GenR.Mode) {
case GL_OBJECT_LINEAR:
- texcoord[2] = DOT4(vObj, texUnit->ObjectPlaneR);
+ texcoord[2] = DOT4(vObj, texUnit->GenR.ObjectPlane);
break;
case GL_EYE_LINEAR:
- texcoord[2] = DOT4(vEye, texUnit->EyePlaneR);
+ texcoord[2] = DOT4(vEye, texUnit->GenR.EyePlane);
break;
case GL_REFLECTION_MAP:
texcoord[2] = rz;
@@ -367,12 +368,12 @@ compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4],
}
if (texUnit->TexGenEnabled & Q_BIT) {
- switch (texUnit->GenModeQ) {
+ switch (texUnit->GenQ.Mode) {
case GL_OBJECT_LINEAR:
- texcoord[3] = DOT4(vObj, texUnit->ObjectPlaneQ);
+ texcoord[3] = DOT4(vObj, texUnit->GenQ.ObjectPlane);
break;
case GL_EYE_LINEAR:
- texcoord[3] = DOT4(vEye, texUnit->EyePlaneQ);
+ texcoord[3] = DOT4(vEye, texUnit->GenQ.EyePlane);
break;
default:
_mesa_problem(ctx, "Bad Q texgen in compute_texgen()");
@@ -408,18 +409,18 @@ _tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4])
/* apply projection matrix: clip = Proj * eye */
TRANSFORM_POINT( clip, ctx->ProjectionMatrixStack.Top->m, eye );
- /* clip to view volume */
- if (ctx->Transform.RasterPositionUnclipped) {
- /* GL_IBM_rasterpos_clip: only clip against Z */
+ /* clip to view volume. */
+ if (!ctx->Transform.DepthClamp) {
if (viewclip_point_z(clip) == 0) {
ctx->Current.RasterPosValid = GL_FALSE;
return;
}
}
- else if (viewclip_point(clip) == 0) {
- /* Normal OpenGL behaviour */
- ctx->Current.RasterPosValid = GL_FALSE;
- return;
+ if (!ctx->Transform.RasterPositionUnclipped) {
+ if (viewclip_point_xy(clip) == 0) {
+ ctx->Current.RasterPosValid = GL_FALSE;
+ return;
+ }
}
/* clip to user clipping planes */
@@ -443,6 +444,12 @@ _tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4])
/ ctx->DrawBuffer->_DepthMaxF;
ctx->Current.RasterPos[3] = clip[3];
+ if (ctx->Transform.DepthClamp) {
+ ctx->Current.RasterPos[3] = CLAMP(ctx->Current.RasterPos[3],
+ ctx->Viewport.Near,
+ ctx->Viewport.Far);
+ }
+
/* compute raster distance */
if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
@@ -503,3 +510,6 @@ _tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4])
_mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
}
}
+
+
+#endif /* FEATURE_rastpos */
diff --git a/src/mesa/tnl/t_vb_cliptmp.h b/src/mesa/tnl/t_vb_cliptmp.h
index 788fe329ed..618b8b3130 100644
--- a/src/mesa/tnl/t_vb_cliptmp.h
+++ b/src/mesa/tnl/t_vb_cliptmp.h
@@ -127,7 +127,7 @@ TAG(clip_line)( GLcontext *ctx, GLuint v0, GLuint v1, GLubyte mask )
GLuint p;
const GLuint v0_orig = v0;
- if (mask & 0x3f) {
+ if (mask & CLIP_FRUSTUM_BITS) {
LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
@@ -199,7 +199,24 @@ TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
- if (mask & 0x3f) {
+ if (0) {
+ /* print pre-clip vertex coords */
+ GLuint i, j;
+ _mesa_printf("pre clip:\n");
+ for (i = 0; i < n; i++) {
+ j = inlist[i];
+ _mesa_printf(" %u: %u: %f, %f, %f, %f\n",
+ i, j,
+ coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
+ assert(!IS_INF_OR_NAN(coord[j][0]));
+ assert(!IS_INF_OR_NAN(coord[j][1]));
+ assert(!IS_INF_OR_NAN(coord[j][2]));
+ assert(!IS_INF_OR_NAN(coord[j][3]));
+ }
+ }
+
+
+ if (mask & CLIP_FRUSTUM_BITS) {
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
@@ -227,6 +244,18 @@ TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
}
}
+ if (0) {
+ /* print post-clip vertex coords */
+ GLuint i, j;
+ _mesa_printf("post clip:\n");
+ for (i = 0; i < n; i++) {
+ j = inlist[i];
+ _mesa_printf(" %u: %u: %f, %f, %f, %f\n",
+ i, j,
+ coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
+ }
+ }
+
tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
}
@@ -250,7 +279,7 @@ TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */
- if (mask & 0x3f) {
+ if (mask & CLIP_FRUSTUM_BITS) {
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
diff --git a/src/mesa/tnl/t_vb_lighttmp.h b/src/mesa/tnl/t_vb_lighttmp.h
index a78f27761f..124ca3c74f 100644
--- a/src/mesa/tnl/t_vb_lighttmp.h
+++ b/src/mesa/tnl/t_vb_lighttmp.h
@@ -141,7 +141,7 @@ static void TAG(light_rgba_spec)( GLcontext *ctx,
/* spotlight attenuation */
if (light->_Flags & LIGHT_SPOT) {
- GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
if (PV_dot_dir<light->_CosCutoff) {
continue; /* this light makes no contribution */
@@ -325,7 +325,7 @@ static void TAG(light_rgba)( GLcontext *ctx,
/* spotlight attenuation */
if (light->_Flags & LIGHT_SPOT) {
- GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
if (PV_dot_dir<light->_CosCutoff) {
continue; /* this light makes no contribution */
@@ -721,7 +721,7 @@ static void TAG(light_ci)( GLcontext *ctx,
/* spotlight attenuation */
if (light->_Flags & LIGHT_SPOT) {
- GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
if (PV_dot_dir < light->_CosCutoff) {
continue; /* this light makes no contribution */
}
diff --git a/src/mesa/tnl/t_vb_points.c b/src/mesa/tnl/t_vb_points.c
index 01d055c1dd..a52505b4b8 100644
--- a/src/mesa/tnl/t_vb_points.c
+++ b/src/mesa/tnl/t_vb_points.c
@@ -25,7 +25,9 @@
* Brian Paul
*/
+#include "main/glheader.h"
#include "main/mtypes.h"
+#include "main/dd.h"
#include "main/imports.h"
#include "t_context.h"
#include "t_pipeline.h"
diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c
index f99401ca6d..c10a27614f 100644
--- a/src/mesa/tnl/t_vb_program.c
+++ b/src/mesa/tnl/t_vb_program.c
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.1
+ * Version: 7.6
*
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -46,6 +47,16 @@
#include "tnl/t_pipeline.h"
+#ifdef NAN_CHECK
+/** Check for NaNs and very large values */
+static INLINE void
+check_float(float x)
+{
+ assert(!IS_INF_OR_NAN(x));
+ assert(1.0e-15 <= x && x <= 1.0e15);
+}
+#endif
+
/*!
* Private storage for the vertex program pipeline stage.
@@ -120,13 +131,16 @@ do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store)
store->ormask = 0;
store->andmask = CLIP_FRUSTUM_BITS;
+ tnl_clip_prepare(ctx);
+
if (tnl->NeedNdcCoords) {
VB->NdcPtr =
_mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
&store->ndcCoords,
store->clipmask,
&store->ormask,
- &store->andmask );
+ &store->andmask,
+ !ctx->Transform.DepthClamp );
}
else {
VB->NdcPtr = NULL;
@@ -134,7 +148,8 @@ do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store)
NULL,
store->clipmask,
&store->ormask,
- &store->andmask );
+ &store->andmask,
+ !ctx->Transform.DepthClamp );
}
if (store->andmask) {
@@ -176,17 +191,12 @@ static void
vp_fetch_texel(GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
GLuint unit, GLfloat color[4])
{
- GLchan rgba[4];
SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* XXX use a float-valued TextureSample routine here!!! */
swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
1, (const GLfloat (*)[4]) texcoord,
- &lambda, &rgba);
- color[0] = CHAN_TO_FLOAT(rgba[0]);
- color[1] = CHAN_TO_FLOAT(rgba[1]);
- color[2] = CHAN_TO_FLOAT(rgba[2]);
- color[3] = CHAN_TO_FLOAT(rgba[3]);
+ &lambda, (GLfloat (*)[4]) color);
}
@@ -212,7 +222,7 @@ init_machine(GLcontext *ctx, struct gl_program_machine *machine)
{
/* Input registers get initialized from the current vertex attribs */
MEMCPY(machine->VertAttribs, ctx->Current.Attrib,
- MAX_VERTEX_PROGRAM_ATTRIBS * 4 * sizeof(GLfloat));
+ MAX_VERTEX_GENERIC_ATTRIBS * 4 * sizeof(GLfloat));
if (ctx->VertexProgram._Current->IsNVProgram) {
GLuint i;
@@ -356,6 +366,12 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
const GLuint size = VB->AttribPtr[attr]->size;
const GLuint stride = VB->AttribPtr[attr]->stride;
const GLfloat *data = (GLfloat *) (ptr + stride * i);
+#ifdef NAN_CHECK
+ check_float(data[0]);
+ check_float(data[1]);
+ check_float(data[2]);
+ check_float(data[3]);
+#endif
COPY_CLEAN_4V(machine.VertAttribs[attr], size, data);
}
}
@@ -366,8 +382,17 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
/* copy the output registers into the VB->attribs arrays */
for (j = 0; j < numOutputs; j++) {
const GLuint attr = outputs[j];
+#ifdef NAN_CHECK
+ check_float(machine.Outputs[attr][0]);
+ check_float(machine.Outputs[attr][1]);
+ check_float(machine.Outputs[attr][2]);
+ check_float(machine.Outputs[attr][3]);
+#endif
COPY_4V(store->results[attr].data[i], machine.Outputs[attr]);
}
+#ifdef NAN_CHECK
+ ASSERT(machine.Outputs[0][3] != 0.0F);
+#endif
#if 0
printf("HPOS: %f %f %f %f\n",
machine.Outputs[0][0],
diff --git a/src/mesa/tnl/t_vb_rendertmp.h b/src/mesa/tnl/t_vb_rendertmp.h
index 2b5f4e93b2..75f6f55bdc 100644
--- a/src/mesa/tnl/t_vb_rendertmp.h
+++ b/src/mesa/tnl/t_vb_rendertmp.h
@@ -82,7 +82,10 @@ static void TAG(render_lines)( GLcontext *ctx,
INIT(GL_LINES);
for (j=start+1; j<count; j+=2 ) {
RESET_STIPPLE;
- RENDER_LINE( ELT(j-1), ELT(j) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(j-1), ELT(j) );
+ else
+ RENDER_LINE( ELT(j), ELT(j-1) );
}
POSTFIX;
}
@@ -103,9 +106,12 @@ static void TAG(render_line_strip)( GLcontext *ctx,
RESET_STIPPLE;
}
- for (j=start+1; j<count; j++ )
- RENDER_LINE( ELT(j-1), ELT(j) );
-
+ for (j=start+1; j<count; j++ ) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(j-1), ELT(j) );
+ else
+ RENDER_LINE( ELT(j), ELT(j-1) );
+ }
POSTFIX;
}
@@ -125,15 +131,24 @@ static void TAG(render_line_loop)( GLcontext *ctx,
if (start+1 < count) {
if (TEST_PRIM_BEGIN(flags)) {
RESET_STIPPLE;
- RENDER_LINE( ELT(start), ELT(start+1) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(start), ELT(start+1) );
+ else
+ RENDER_LINE( ELT(start+1), ELT(start) );
}
for ( i = start+2 ; i < count ; i++) {
- RENDER_LINE( ELT(i-1), ELT(i) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(i-1), ELT(i) );
+ else
+ RENDER_LINE( ELT(i), ELT(i-1) );
}
if ( TEST_PRIM_END(flags)) {
- RENDER_LINE( ELT(count-1), ELT(start) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(count-1), ELT(start) );
+ else
+ RENDER_LINE( ELT(start), ELT(count-1) );
}
}
@@ -156,11 +171,17 @@ static void TAG(render_triangles)( GLcontext *ctx,
/* Leave the edgeflags as supplied by the user.
*/
RESET_STIPPLE;
- RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
}
} else {
for (j=start+2; j<count; j+=3) {
- RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
}
}
POSTFIX;
@@ -180,26 +201,38 @@ static void TAG(render_tri_strip)( GLcontext *ctx,
INIT(GL_TRIANGLE_STRIP);
if (NEED_EDGEFLAG_SETUP) {
for (j=start+2;j<count;j++,parity^=1) {
- GLuint ej2 = ELT(j-2+parity);
- GLuint ej1 = ELT(j-1-parity);
- GLuint ej = ELT(j);
- GLboolean ef2 = EDGEFLAG_GET( ej2 );
- GLboolean ef1 = EDGEFLAG_GET( ej1 );
- GLboolean ef = EDGEFLAG_GET( ej );
+ GLuint ej2, ej1, ej;
+ GLboolean ef2, ef1, ef;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) {
+ ej2 = ELT(j-2+parity);
+ ej1 = ELT(j-1-parity);
+ ej = ELT(j);
+ }
+ else {
+ ej2 = ELT(j-1+parity);
+ ej1 = ELT(j-parity);
+ ej = ELT(j-2);
+ }
+ ef2 = EDGEFLAG_GET( ej2 );
+ ef1 = EDGEFLAG_GET( ej1 );
+ ef = EDGEFLAG_GET( ej );
if (TEST_PRIM_BEGIN(flags)) {
RESET_STIPPLE;
}
EDGEFLAG_SET( ej2, GL_TRUE );
EDGEFLAG_SET( ej1, GL_TRUE );
EDGEFLAG_SET( ej, GL_TRUE );
- RENDER_TRI( ej2, ej1, ej );
+ RENDER_TRI( ej2, ej1, ej );
EDGEFLAG_SET( ej2, ef2 );
EDGEFLAG_SET( ej1, ef1 );
EDGEFLAG_SET( ej, ef );
}
} else {
for (j=start+2; j<count ; j++, parity^=1) {
- RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
+ else
+ RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) );
}
}
POSTFIX;
@@ -232,14 +265,20 @@ static void TAG(render_tri_fan)( GLcontext *ctx,
EDGEFLAG_SET( ejs, GL_TRUE );
EDGEFLAG_SET( ej1, GL_TRUE );
EDGEFLAG_SET( ej, GL_TRUE );
- RENDER_TRI( ejs, ej1, ej);
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ejs, ej1, ej);
+ else
+ RENDER_TRI( ej, ejs, ej1);
EDGEFLAG_SET( ejs, efs );
EDGEFLAG_SET( ej1, ef1 );
EDGEFLAG_SET( ej, ef );
}
} else {
for (j=start+2;j<count;j++) {
- RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
+ else
+ RENDER_TRI( ELT(j), ELT(start), ELT(j-1) );
}
}
@@ -331,11 +370,19 @@ static void TAG(render_quads)( GLcontext *ctx,
/* Use user-specified edgeflags for quads.
*/
RESET_STIPPLE;
- RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
}
} else {
for (j=start+3; j<count; j+=4) {
- RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
}
}
POSTFIX;
@@ -367,7 +414,11 @@ static void TAG(render_quad_strip)( GLcontext *ctx,
EDGEFLAG_SET( ELT(j-2), GL_TRUE );
EDGEFLAG_SET( ELT(j-1), GL_TRUE );
EDGEFLAG_SET( ELT(j), GL_TRUE );
- RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
EDGEFLAG_SET( ELT(j-3), ef3 );
EDGEFLAG_SET( ELT(j-2), ef2 );
EDGEFLAG_SET( ELT(j-1), ef1 );
@@ -375,7 +426,11 @@ static void TAG(render_quad_strip)( GLcontext *ctx,
}
} else {
for (j=start+3;j<count;j+=2) {
- RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
}
}
POSTFIX;
diff --git a/src/mesa/tnl/t_vb_texgen.c b/src/mesa/tnl/t_vb_texgen.c
index 14d3876e54..7c1819b223 100644
--- a/src/mesa/tnl/t_vb_texgen.c
+++ b/src/mesa/tnl/t_vb_texgen.c
@@ -367,16 +367,16 @@ static void texgen( GLcontext *ctx,
if (texUnit->TexGenEnabled & S_BIT) {
GLuint i;
- switch (texUnit->GenModeS) {
+ switch (texUnit->GenS.Mode) {
case GL_OBJECT_LINEAR:
_mesa_dotprod_tab[obj->size]( (GLfloat *)out->data,
sizeof(out->data[0]), obj,
- texUnit->ObjectPlaneS );
+ texUnit->GenS.ObjectPlane );
break;
case GL_EYE_LINEAR:
_mesa_dotprod_tab[eye->size]( (GLfloat *)out->data,
sizeof(out->data[0]), eye,
- texUnit->EyePlaneS );
+ texUnit->GenS.EyePlane );
break;
case GL_SPHERE_MAP:
for (i = 0; i < count; i++)
@@ -400,16 +400,16 @@ static void texgen( GLcontext *ctx,
if (texUnit->TexGenEnabled & T_BIT) {
GLuint i;
- switch (texUnit->GenModeT) {
+ switch (texUnit->GenT.Mode) {
case GL_OBJECT_LINEAR:
_mesa_dotprod_tab[obj->size]( &(out->data[0][1]),
sizeof(out->data[0]), obj,
- texUnit->ObjectPlaneT );
+ texUnit->GenT.ObjectPlane );
break;
case GL_EYE_LINEAR:
_mesa_dotprod_tab[eye->size]( &(out->data[0][1]),
sizeof(out->data[0]), eye,
- texUnit->EyePlaneT );
+ texUnit->GenT.EyePlane );
break;
case GL_SPHERE_MAP:
for (i = 0; i < count; i++)
@@ -433,16 +433,16 @@ static void texgen( GLcontext *ctx,
if (texUnit->TexGenEnabled & R_BIT) {
GLuint i;
- switch (texUnit->GenModeR) {
+ switch (texUnit->GenR.Mode) {
case GL_OBJECT_LINEAR:
_mesa_dotprod_tab[obj->size]( &(out->data[0][2]),
sizeof(out->data[0]), obj,
- texUnit->ObjectPlaneR );
+ texUnit->GenR.ObjectPlane );
break;
case GL_EYE_LINEAR:
_mesa_dotprod_tab[eye->size]( &(out->data[0][2]),
sizeof(out->data[0]), eye,
- texUnit->EyePlaneR );
+ texUnit->GenR.EyePlane );
break;
case GL_REFLECTION_MAP_NV:
for (i=0;i<count;i++)
@@ -461,16 +461,16 @@ static void texgen( GLcontext *ctx,
}
if (texUnit->TexGenEnabled & Q_BIT) {
- switch (texUnit->GenModeQ) {
+ switch (texUnit->GenQ.Mode) {
case GL_OBJECT_LINEAR:
_mesa_dotprod_tab[obj->size]( &(out->data[0][3]),
sizeof(out->data[0]), obj,
- texUnit->ObjectPlaneQ );
+ texUnit->GenQ.ObjectPlane );
break;
case GL_EYE_LINEAR:
_mesa_dotprod_tab[eye->size]( &(out->data[0][3]),
sizeof(out->data[0]), eye,
- texUnit->EyePlaneQ );
+ texUnit->GenQ.EyePlane );
break;
default:
_mesa_problem(ctx, "Bad Q texgen");
diff --git a/src/mesa/tnl/t_vb_vertex.c b/src/mesa/tnl/t_vb_vertex.c
index 30aa7c4086..4734754ea4 100644
--- a/src/mesa/tnl/t_vb_vertex.c
+++ b/src/mesa/tnl/t_vb_vertex.c
@@ -118,6 +118,22 @@ static void (*(usercliptab[5]))( GLcontext *,
};
+void
+tnl_clip_prepare(GLcontext *ctx)
+{
+ /* Neither the x86 nor sparc asm cliptest functions have been updated
+ * for ARB_depth_clamp, so force the C paths.
+ */
+ if (ctx->Transform.DepthClamp) {
+ static GLboolean c_funcs_installed = GL_FALSE;
+ if (!c_funcs_installed) {
+ init_c_cliptest();
+ c_funcs_installed = GL_TRUE;
+ }
+ }
+}
+
+
static GLboolean run_vertex_stage( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
@@ -129,6 +145,8 @@ static GLboolean run_vertex_stage( GLcontext *ctx,
if (ctx->VertexProgram._Current)
return GL_TRUE;
+ tnl_clip_prepare(ctx);
+
if (ctx->_NeedEyeCoords) {
/* Separate modelview transformation:
* Use combined ModelProject to avoid some depth artifacts
@@ -173,7 +191,8 @@ static GLboolean run_vertex_stage( GLcontext *ctx,
&store->proj,
store->clipmask,
&store->ormask,
- &store->andmask );
+ &store->andmask,
+ !ctx->Transform.DepthClamp );
}
else {
VB->NdcPtr = NULL;
@@ -181,7 +200,8 @@ static GLboolean run_vertex_stage( GLcontext *ctx,
NULL,
store->clipmask,
&store->ormask,
- &store->andmask );
+ &store->andmask,
+ !ctx->Transform.DepthClamp );
}
if (store->andmask)
diff --git a/src/mesa/tnl/t_vertex.c b/src/mesa/tnl/t_vertex.c
index 10b78f820e..fe4209ae57 100644
--- a/src/mesa/tnl/t_vertex.c
+++ b/src/mesa/tnl/t_vertex.c
@@ -535,27 +535,30 @@ void _tnl_init_vertices( GLcontext *ctx,
void _tnl_free_vertices( GLcontext *ctx )
{
- struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
- struct tnl_clipspace_fastpath *fp, *tmp;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ if (tnl) {
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_fastpath *fp, *tmp;
- if (vtx->vertex_buf) {
- ALIGN_FREE(vtx->vertex_buf);
- vtx->vertex_buf = NULL;
- }
-
- for (fp = vtx->fastpath ; fp ; fp = tmp) {
- tmp = fp->next;
- FREE(fp->attr);
-
- /* KW: At the moment, fp->func is constrained to be allocated by
- * _mesa_exec_alloc(), as the hardwired fastpaths in
- * t_vertex_generic.c are handled specially. It would be nice
- * to unify them, but this probably won't change until this
- * module gets another overhaul.
- */
- _mesa_exec_free((void *) fp->func);
- FREE(fp);
+ if (vtx->vertex_buf) {
+ ALIGN_FREE(vtx->vertex_buf);
+ vtx->vertex_buf = NULL;
+ }
+
+ for (fp = vtx->fastpath ; fp ; fp = tmp) {
+ tmp = fp->next;
+ FREE(fp->attr);
+
+ /* KW: At the moment, fp->func is constrained to be allocated by
+ * _mesa_exec_alloc(), as the hardwired fastpaths in
+ * t_vertex_generic.c are handled specially. It would be nice
+ * to unify them, but this probably won't change until this
+ * module gets another overhaul.
+ */
+ _mesa_exec_free((void *) fp->func);
+ FREE(fp);
+ }
+
+ vtx->fastpath = NULL;
}
-
- vtx->fastpath = NULL;
}
diff --git a/src/mesa/tnl/t_vp_build.c b/src/mesa/tnl/t_vp_build.c
index 7be4d95af6..735937bbe2 100644
--- a/src/mesa/tnl/t_vp_build.c
+++ b/src/mesa/tnl/t_vp_build.c
@@ -32,6 +32,7 @@
#include "main/glheader.h"
#include "main/ffvertex_prog.h"
+#include "main/dd.h"
#include "t_vp_build.h"
diff --git a/src/mesa/tnl/t_vp_build.h b/src/mesa/tnl/t_vp_build.h
index d1c147ff03..d6ebc66c04 100644
--- a/src/mesa/tnl/t_vp_build.h
+++ b/src/mesa/tnl/t_vp_build.h
@@ -29,6 +29,13 @@
#include "main/mtypes.h"
+#define TNL_FIXED_FUNCTION_STATE_FLAGS (_NEW_PROGRAM | \
+ _NEW_LIGHT | \
+ _NEW_TEXTURE | \
+ _NEW_TEXTURE_MATRIX | \
+ _NEW_TRANSFORM | \
+ _NEW_FOG | \
+ _NEW_POINT)
extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx );
diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h
index 9a1717bf89..4736dcff9e 100644
--- a/src/mesa/tnl/tnl.h
+++ b/src/mesa/tnl/tnl.h
@@ -29,7 +29,7 @@
#define _TNL_H
#include "main/mtypes.h"
-
+#include "tnl_features.h"
/* These are the public-access functions exported from tnl. (A few
@@ -81,8 +81,17 @@ _tnl_draw_prims( GLcontext *ctx,
GLuint min_index,
GLuint max_index);
+void
+_tnl_vbo_draw_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index);
extern void
-_tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]);
+_mesa_load_tracked_matrices(GLcontext *ctx);
#endif
diff --git a/src/mesa/tnl/tnl_features.h b/src/mesa/tnl/tnl_features.h
new file mode 100644
index 0000000000..0c86dd09a4
--- /dev/null
+++ b/src/mesa/tnl/tnl_features.h
@@ -0,0 +1,13 @@
+#ifndef _TNL_FEATURES_H
+#define _TNL_FEATURES_H
+
+#include "main/mtypes.h"
+
+#if FEATURE_rastpos
+
+extern void
+_tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]);
+
+#endif
+
+#endif /* _TNL_FEATURES_H */
diff --git a/src/mesa/tnl_dd/t_dd_vb.c b/src/mesa/tnl_dd/t_dd_vb.c
index 3cedd90119..b3937c29a0 100644
--- a/src/mesa/tnl_dd/t_dd_vb.c
+++ b/src/mesa/tnl_dd/t_dd_vb.c
@@ -188,6 +188,9 @@ void TAG(translate_vertex)(GLcontext *ctx,
}
+/* prototype to silence warning */
+void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v );
+
void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v )
{
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index 4c51b44cda..b24ecfd7cd 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -44,6 +44,7 @@ struct _mesa_prim {
GLuint start;
GLuint count;
+ GLint basevertex;
};
/* Would like to call this a "vbo_index_buffer", but this would be
@@ -69,6 +70,7 @@ typedef void (*vbo_draw_func)( GLcontext *ctx,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index );
@@ -112,9 +114,30 @@ void vbo_rebase_prims( GLcontext *ctx,
GLuint min_index,
GLuint max_index,
vbo_draw_func draw );
-
+void
+vbo_get_minmax_index(GLcontext *ctx, const struct _mesa_prim *prim,
+ const struct _mesa_index_buffer *ib,
+ GLuint *min_index, GLuint *max_index);
void vbo_use_buffer_objects(GLcontext *ctx);
+void vbo_set_draw_func(GLcontext *ctx, vbo_draw_func func);
+
+
+void GLAPIENTRY
+_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+
+void GLAPIENTRY
+_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z);
+
+void GLAPIENTRY
+_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+
+void GLAPIENTRY
+_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
+
+void GLAPIENTRY
+_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
#endif
diff --git a/src/mesa/vbo/vbo_attrib_tmp.h b/src/mesa/vbo/vbo_attrib_tmp.h
index ff11c7d59a..7a889b8e2f 100644
--- a/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/src/mesa/vbo/vbo_attrib_tmp.h
@@ -265,7 +265,7 @@ static void GLAPIENTRY TAG(VertexAttrib1fARB)( GLuint index, GLfloat x )
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR1F(0, x);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR1F(VBO_ATTRIB_GENERIC0 + index, x);
else
ERROR();
@@ -277,7 +277,7 @@ static void GLAPIENTRY TAG(VertexAttrib1fvARB)( GLuint index,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR1FV(0, v);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR1FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
@@ -289,7 +289,7 @@ static void GLAPIENTRY TAG(VertexAttrib2fARB)( GLuint index, GLfloat x,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR2F(0, x, y);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2F(VBO_ATTRIB_GENERIC0 + index, x, y);
else
ERROR();
@@ -301,7 +301,7 @@ static void GLAPIENTRY TAG(VertexAttrib2fvARB)( GLuint index,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR2FV(0, v);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
@@ -313,7 +313,7 @@ static void GLAPIENTRY TAG(VertexAttrib3fARB)( GLuint index, GLfloat x,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR3F(0, x, y, z);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3F(VBO_ATTRIB_GENERIC0 + index, x, y, z);
else
ERROR();
@@ -325,7 +325,7 @@ static void GLAPIENTRY TAG(VertexAttrib3fvARB)( GLuint index,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR3FV(0, v);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
@@ -338,7 +338,7 @@ static void GLAPIENTRY TAG(VertexAttrib4fARB)( GLuint index, GLfloat x,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR4F(0, x, y, z, w);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4F(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
else
ERROR();
@@ -350,7 +350,7 @@ static void GLAPIENTRY TAG(VertexAttrib4fvARB)( GLuint index,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR4FV(0, v);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
index a73a46b9c8..75c32e0b9b 100644
--- a/src/mesa/vbo/vbo_context.c
+++ b/src/mesa/vbo/vbo_context.c
@@ -28,9 +28,12 @@
#include "main/imports.h"
#include "main/mtypes.h"
#include "main/api_arrayelt.h"
+#include "main/bufferobj.h"
+#include "math/m_eval.h"
#include "vbo.h"
#include "vbo_context.h"
+#if 0
/* Reach out and grab this to use as the default:
*/
extern void _tnl_draw_prims( GLcontext *ctx,
@@ -40,6 +43,7 @@ extern void _tnl_draw_prims( GLcontext *ctx,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index );
+#endif
@@ -76,8 +80,10 @@ static void init_legacy_currval(GLcontext *ctx)
cl->StrideB = 0;
cl->Enabled = 1;
cl->Type = GL_FLOAT;
+ cl->Format = GL_RGBA;
cl->Ptr = (const void *)ctx->Current.Attrib[i];
- cl->BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
}
}
@@ -97,11 +103,13 @@ static void init_generic_currval(GLcontext *ctx)
*/
cl->Size = 1;
cl->Type = GL_FLOAT;
+ cl->Format = GL_RGBA;
cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i];
cl->Stride = 0;
cl->StrideB = 0;
cl->Enabled = 1;
- cl->BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
}
}
@@ -141,10 +149,12 @@ static void init_mat_currval(GLcontext *ctx)
cl->Ptr = (const void *)ctx->Light.Material.Attrib[i];
cl->Type = GL_FLOAT;
+ cl->Format = GL_RGBA;
cl->Stride = 0;
cl->StrideB = 0;
cl->Enabled = 1;
- cl->BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
}
}
@@ -205,14 +215,16 @@ GLboolean _vbo_CreateContext( GLcontext *ctx )
for (i = 0; i < 4; i++)
vbo->map_vp_none[28+i] = i;
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ for (i = 0; i < Elements(vbo->map_vp_arb); i++)
vbo->map_vp_arb[i] = i;
}
/* By default:
*/
+#if 0 /* dead - see vbo_set_draw_func() */
vbo->draw_prims = _tnl_draw_prims;
+#endif
/* Hook our functions into exec and compile dispatch tables. These
* will pretty much be permanently installed, which means that the
@@ -223,6 +235,8 @@ GLboolean _vbo_CreateContext( GLcontext *ctx )
vbo_save_init( ctx );
#endif
+ _math_init_eval();
+
return GL_TRUE;
}
@@ -240,10 +254,20 @@ void _vbo_DestroyContext( GLcontext *ctx )
ctx->aelt_context = NULL;
}
- vbo_exec_destroy(ctx);
+ if (vbo_context(ctx)) {
+ vbo_exec_destroy(ctx);
#if FEATURE_dlist
- vbo_save_destroy(ctx);
+ vbo_save_destroy(ctx);
#endif
- FREE(vbo_context(ctx));
- ctx->swtnl_im = NULL;
+ FREE(vbo_context(ctx));
+ ctx->swtnl_im = NULL;
+ }
}
+
+
+void vbo_set_draw_func(GLcontext *ctx, vbo_draw_func func)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ vbo->draw_prims = func;
+}
+
diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h
index bf405eb693..8b726dc8ac 100644
--- a/src/mesa/vbo/vbo_context.h
+++ b/src/mesa/vbo/vbo_context.h
@@ -68,8 +68,8 @@ struct vbo_context {
struct gl_client_array *generic_currval;
struct gl_client_array *mat_currval;
- GLuint map_vp_none[32];
- GLuint map_vp_arb[32];
+ GLuint map_vp_none[VERT_ATTRIB_MAX];
+ GLuint map_vp_arb[VERT_ATTRIB_MAX];
GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */
GLfloat CurrentFloatEdgeFlag;
@@ -92,16 +92,18 @@ static INLINE struct vbo_context *vbo_context(GLcontext *ctx)
return (struct vbo_context *)(ctx->swtnl_im);
}
-enum {
- VP_NONE = 1,
- VP_NV,
- VP_ARB
-};
-static INLINE GLuint get_program_mode( GLcontext *ctx )
+/**
+ * Return VP_x token to indicate whether we're running fixed-function
+ * vertex transformation, an NV vertex program or ARB vertex program/shader.
+ */
+static INLINE enum vp_mode
+get_program_mode( GLcontext *ctx )
{
if (!ctx->VertexProgram._Current)
return VP_NONE;
+ else if (ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram)
+ return VP_NONE;
else if (ctx->VertexProgram._Current->IsNVProgram)
return VP_NV;
else
diff --git a/src/mesa/vbo/vbo_exec.c b/src/mesa/vbo/vbo_exec.c
index 635f239acc..e168a89ea5 100644
--- a/src/mesa/vbo/vbo_exec.c
+++ b/src/mesa/vbo/vbo_exec.c
@@ -57,6 +57,7 @@ void vbo_exec_init( GLcontext *ctx )
ctx->Driver.NeedFlush = 0;
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+ ctx->Driver.BeginVertices = vbo_exec_BeginVertices;
ctx->Driver.FlushVertices = vbo_exec_FlushVertices;
vbo_exec_invalidate_state( ctx, ~0 );
diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h
index ddbcbe1181..516be0995b 100644
--- a/src/mesa/vbo/vbo_exec.h
+++ b/src/mesa/vbo/vbo_exec.h
@@ -43,11 +43,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* Wierd implementation stuff:
*/
-#define VBO_VERT_BUFFER_SIZE (1024*16) /* dwords == 64k */
+#define VBO_VERT_BUFFER_SIZE (1024*64) /* bytes */
#define VBO_MAX_ATTR_CODEGEN 16
#define ERROR_ATTRIB 16
+/** Current vertex program mode */
+enum vp_mode {
+ VP_NONE, /**< fixed function */
+ VP_NV, /**< NV vertex program */
+ VP_ARB /**< ARB vertex program or GLSL vertex shader */
+};
struct vbo_exec_eval1_map {
@@ -78,14 +84,15 @@ struct vbo_exec_context
struct {
struct gl_buffer_object *bufferobj;
- GLubyte *buffer_map;
- GLuint vertex_size;
+ GLuint vertex_size; /* in dwords */
struct _mesa_prim prim[VBO_MAX_PRIM];
GLuint prim_count;
- GLfloat *vbptr; /* cursor, points into buffer */
+ GLfloat *buffer_map;
+ GLfloat *buffer_ptr; /* cursor, points into buffer */
+ GLuint buffer_used; /* in bytes */
GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */
GLuint vert_count;
@@ -102,7 +109,7 @@ struct vbo_exec_context
* values are squashed down to the 32 attributes passed to the
* vertex program below:
*/
- GLuint program_mode;
+ enum vp_mode program_mode;
GLuint enabled_flags;
const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
} vtx;
@@ -115,7 +122,7 @@ struct vbo_exec_context
} eval;
struct {
- GLuint program_mode;
+ enum vp_mode program_mode;
GLuint enabled_flags;
GLuint array_obj;
@@ -140,6 +147,9 @@ struct vbo_exec_context
void vbo_exec_init( GLcontext *ctx );
void vbo_exec_destroy( GLcontext *ctx );
void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state );
+void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap );
+
+void vbo_exec_BeginVertices( GLcontext *ctx );
void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags );
@@ -151,7 +161,26 @@ void vbo_exec_array_destroy( struct vbo_exec_context *exec );
void vbo_exec_vtx_init( struct vbo_exec_context *exec );
void vbo_exec_vtx_destroy( struct vbo_exec_context *exec );
-void vbo_exec_vtx_flush( struct vbo_exec_context *exec );
+
+#if FEATURE_beginend
+
+void vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap );
+void vbo_exec_vtx_map( struct vbo_exec_context *exec );
+
+#else /* FEATURE_beginend */
+
+static INLINE void
+vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
+{
+}
+
+static INLINE void
+vbo_exec_vtx_map( struct vbo_exec_context *exec )
+{
+}
+
+#endif /* FEATURE_beginend */
+
void vbo_exec_vtx_wrap( struct vbo_exec_context *exec );
void vbo_exec_eval_update( struct vbo_exec_context *exec );
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index d48f5230cb..d105183bac 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -35,9 +35,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/context.h"
#include "main/macros.h"
#include "main/vtxfmt.h"
-#if FEATURE_dlist
#include "main/dlist.h"
-#endif
+#include "main/eval.h"
#include "main/state.h"
#include "main/light.h"
#include "main/api_arrayelt.h"
@@ -51,6 +50,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
+/** ID/name for immediate-mode VBO */
+#define IMM_BUFFER_NAME 0xaabbccdd
+
+
static void reset_attrfv( struct vbo_exec_context *exec );
@@ -62,7 +65,7 @@ static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
if (exec->vtx.prim_count == 0) {
exec->vtx.copied.nr = 0;
exec->vtx.vert_count = 0;
- exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map;
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
}
else {
GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
@@ -80,7 +83,7 @@ static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
/* Execute the buffer and save copied vertices.
*/
if (exec->vtx.vert_count)
- vbo_exec_vtx_flush( exec );
+ vbo_exec_vtx_flush( exec, GL_FALSE );
else {
exec->vtx.prim_count = 0;
exec->vtx.copied.nr = 0;
@@ -121,9 +124,9 @@ void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
- _mesa_memcpy( exec->vtx.vbptr, data,
+ _mesa_memcpy( exec->vtx.buffer_ptr, data,
exec->vtx.vertex_size * sizeof(GLfloat));
- exec->vtx.vbptr += exec->vtx.vertex_size;
+ exec->vtx.buffer_ptr += exec->vtx.vertex_size;
data += exec->vtx.vertex_size;
exec->vtx.vert_count++;
}
@@ -143,29 +146,36 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
if (exec->vtx.attrsz[i]) {
- GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
-
/* Note: the exec->vtx.current[i] pointers point into the
* ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
*/
- COPY_CLEAN_4V(current,
- exec->vtx.attrsz[i],
- exec->vtx.attrptr[i]);
-
+ GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ GLfloat tmp[4];
+
+ COPY_CLEAN_4V(tmp,
+ exec->vtx.attrsz[i],
+ exec->vtx.attrptr[i]);
+
+ if (memcmp(current, tmp, sizeof(tmp)) != 0)
+ {
+ memcpy(current, tmp, sizeof(tmp));
- /* Given that we explicitly state size here, there is no need
- * for the COPY_CLEAN above, could just copy 16 bytes and be
- * done. The only problem is when Mesa accesses ctx->Current
- * directly.
- */
- vbo->currval[i].Size = exec->vtx.attrsz[i];
-
- /* This triggers rather too much recalculation of Mesa state
- * that doesn't get used (eg light positions).
- */
- if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
- i <= VBO_ATTRIB_MAT_BACK_INDEXES)
- ctx->NewState |= _NEW_LIGHT;
+ /* Given that we explicitly state size here, there is no need
+ * for the COPY_CLEAN above, could just copy 16 bytes and be
+ * done. The only problem is when Mesa accesses ctx->Current
+ * directly.
+ */
+ vbo->currval[i].Size = exec->vtx.attrsz[i];
+
+ /* This triggers rather too much recalculation of Mesa state
+ * that doesn't get used (eg light positions).
+ */
+ if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
+ i <= VBO_ATTRIB_MAT_BACK_INDEXES)
+ ctx->NewState |= _NEW_LIGHT;
+
+ ctx->NewState |= _NEW_CURRENT_ATTRIB;
+ }
}
}
@@ -176,8 +186,6 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
_mesa_update_color_material(ctx,
ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
}
-
- ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
}
@@ -197,8 +205,6 @@ static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
break;
}
}
-
- ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
}
@@ -244,9 +250,10 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
exec->vtx.attrsz[attr] = newsz;
exec->vtx.vertex_size += newsz - oldsz;
- exec->vtx.max_vert = VBO_VERT_BUFFER_SIZE / exec->vtx.vertex_size;
+ 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.vbptr = (GLfloat *)exec->vtx.buffer_map;
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
/* Recalculate all the attrptr[] values
@@ -272,10 +279,10 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
if (exec->vtx.copied.nr)
{
GLfloat *data = exec->vtx.copied.buffer;
- GLfloat *dest = exec->vtx.vbptr;
+ GLfloat *dest = exec->vtx.buffer_ptr;
GLuint j;
- assert(exec->vtx.vbptr == (GLfloat *)exec->vtx.buffer_map);
+ assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
@@ -301,7 +308,7 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
}
}
- exec->vtx.vbptr = dest;
+ exec->vtx.buffer_ptr = dest;
exec->vtx.vert_count += exec->vtx.copied.nr;
exec->vtx.copied.nr = 0;
}
@@ -338,12 +345,10 @@ static void vbo_exec_fixup_vertex( GLcontext *ctx,
*/
if (attr == 0)
exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
- else
- exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
}
-
+#if FEATURE_beginend
/*
*/
@@ -366,9 +371,9 @@ do { \
GLuint i; \
\
for (i = 0; i < exec->vtx.vertex_size; i++) \
- exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \
+ exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \
\
- exec->vtx.vbptr += exec->vtx.vertex_size; \
+ exec->vtx.buffer_ptr += exec->vtx.vertex_size; \
exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
\
if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
@@ -386,6 +391,7 @@ do { \
+#if FEATURE_eval
/* Eval
*/
static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
@@ -478,23 +484,7 @@ static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
vbo_exec_EvalCoord2f( u, v );
}
-
-
-/**
- * Check if programs/shaders are enabled and valid at glBegin time.
- */
-GLboolean
-vbo_validate_shaders(GLcontext *ctx)
-{
- if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
- (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
- return GL_FALSE;
- }
- if (ctx->Shader.CurrentProgram && !ctx->Shader.CurrentProgram->LinkStatus) {
- return GL_FALSE;
- }
- return GL_TRUE;
-}
+#endif /* FEATURE_eval */
/* Build a list of primitives on the fly. Keep
@@ -515,9 +505,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
return;
}
- if (!vbo_validate_shaders(ctx)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBegin (invalid vertex/fragment program)");
+ if (!_mesa_valid_to_render(ctx, "glBegin")) {
return;
}
@@ -525,7 +513,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
* begin/end pairs.
*/
if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
- vbo_exec_FlushVertices( ctx, ~0 );
+ vbo_exec_FlushVertices_internal( ctx, GL_FALSE );
i = exec->vtx.prim_count++;
exec->vtx.prim[i].mode = mode;
@@ -559,7 +547,7 @@ static void GLAPIENTRY vbo_exec_End( void )
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
if (exec->vtx.prim_count == VBO_MAX_PRIM)
- vbo_exec_vtx_flush( exec );
+ vbo_exec_vtx_flush( exec, GL_FALSE );
}
else
_mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
@@ -570,24 +558,19 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
{
GLvertexformat *vfmt = &exec->vtxfmt;
- vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
+ _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
+
vfmt->Begin = vbo_exec_Begin;
-#if FEATURE_dlist
- vfmt->CallList = _mesa_CallList;
- vfmt->CallLists = _mesa_CallLists;
-#endif
vfmt->End = vbo_exec_End;
- vfmt->EvalCoord1f = vbo_exec_EvalCoord1f;
- vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv;
- vfmt->EvalCoord2f = vbo_exec_EvalCoord2f;
- vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv;
- vfmt->EvalPoint1 = vbo_exec_EvalPoint1;
- vfmt->EvalPoint2 = vbo_exec_EvalPoint2;
- vfmt->Rectf = _mesa_noop_Rectf;
- vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
- vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
+ _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_);
+
+ /* use noop eval mesh */
+#define vbo_exec_EvalMesh1 _mesa_noop_EvalMesh1
+#define vbo_exec_EvalMesh2 _mesa_noop_EvalMesh2
+ _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_);
+ vfmt->Rectf = _mesa_noop_Rectf;
/* from attrib_tmp.h:
*/
@@ -651,6 +634,98 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
}
+#else /* FEATURE_beginend */
+
+
+#define ATTR( A, N, V0, V1, V2, V3 ) \
+do { \
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
+ \
+ /* FLUSH_UPDATE_CURRENT needs to be set manually */ \
+ exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
+ \
+ if (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; \
+ } \
+} while (0)
+
+#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
+#define TAG(x) vbo_##x
+
+#include "vbo_attrib_tmp.h"
+
+static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
+{
+ /* silence warnings */
+ (void) vbo_Color3f;
+ (void) vbo_Color3fv;
+ (void) vbo_Color4f;
+ (void) vbo_Color4fv;
+ (void) vbo_FogCoordfEXT;
+ (void) vbo_FogCoordfvEXT;
+ (void) vbo_MultiTexCoord1f;
+ (void) vbo_MultiTexCoord1fv;
+ (void) vbo_MultiTexCoord2f;
+ (void) vbo_MultiTexCoord2fv;
+ (void) vbo_MultiTexCoord3f;
+ (void) vbo_MultiTexCoord3fv;
+ (void) vbo_MultiTexCoord4f;
+ (void) vbo_MultiTexCoord4fv;
+ (void) vbo_Normal3f;
+ (void) vbo_Normal3fv;
+ (void) vbo_SecondaryColor3fEXT;
+ (void) vbo_SecondaryColor3fvEXT;
+ (void) vbo_TexCoord1f;
+ (void) vbo_TexCoord1fv;
+ (void) vbo_TexCoord2f;
+ (void) vbo_TexCoord2fv;
+ (void) vbo_TexCoord3f;
+ (void) vbo_TexCoord3fv;
+ (void) vbo_TexCoord4f;
+ (void) vbo_TexCoord4fv;
+ (void) vbo_Vertex2f;
+ (void) vbo_Vertex2fv;
+ (void) vbo_Vertex3f;
+ (void) vbo_Vertex3fv;
+ (void) vbo_Vertex4f;
+ (void) vbo_Vertex4fv;
+
+ (void) vbo_VertexAttrib1fARB;
+ (void) vbo_VertexAttrib1fvARB;
+ (void) vbo_VertexAttrib2fARB;
+ (void) vbo_VertexAttrib2fvARB;
+ (void) vbo_VertexAttrib3fARB;
+ (void) vbo_VertexAttrib3fvARB;
+ (void) vbo_VertexAttrib4fARB;
+ (void) vbo_VertexAttrib4fvARB;
+
+ (void) vbo_VertexAttrib1fNV;
+ (void) vbo_VertexAttrib1fvNV;
+ (void) vbo_VertexAttrib2fNV;
+ (void) vbo_VertexAttrib2fvNV;
+ (void) vbo_VertexAttrib3fNV;
+ (void) vbo_VertexAttrib3fvNV;
+ (void) vbo_VertexAttrib4fNV;
+ (void) vbo_VertexAttrib4fvNV;
+
+ (void) vbo_Materialfv;
+
+ (void) vbo_EdgeFlag;
+ (void) vbo_Indexf;
+ (void) vbo_Indexfv;
+}
+
+
+#endif /* FEATURE_beginend */
+
+
/**
* Tell the VBO module to use a real OpenGL vertex buffer object to
* store accumulated immediate-mode vertex data.
@@ -663,25 +738,22 @@ void vbo_use_buffer_objects(GLcontext *ctx)
/* Any buffer name but 0 can be used here since this bufferobj won't
* go into the bufferobj hashtable.
*/
- GLuint bufName = 0xaabbccdd;
+ GLuint bufName = IMM_BUFFER_NAME;
GLenum target = GL_ARRAY_BUFFER_ARB;
- GLenum access = GL_READ_WRITE_ARB;
GLenum usage = GL_STREAM_DRAW_ARB;
- GLsizei size = VBO_VERT_BUFFER_SIZE * sizeof(GLfloat);
+ GLsizei size = VBO_VERT_BUFFER_SIZE;
/* Make sure this func is only used once */
- assert(exec->vtx.bufferobj == ctx->Array.NullBufferObj);
+ assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
if (exec->vtx.buffer_map) {
_mesa_align_free(exec->vtx.buffer_map);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
}
/* Allocate a real buffer object now */
exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
-
- /* and map it */
- exec->vtx.buffer_map
- = ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
}
@@ -693,14 +765,17 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
GLuint i;
/* Allocate a buffer object. Will just reuse this object
- * continuously.
+ * continuously, unless vbo_use_buffer_objects() is called to enable
+ * use of real VBOs.
*/
_mesa_reference_buffer_object(ctx,
&exec->vtx.bufferobj,
- ctx->Array.NullBufferObj);
+ ctx->Shared->NullBufferObj);
ASSERT(!exec->vtx.buffer_map);
- exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64);
+ exec->vtx.buffer_map = (GLfloat *)ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE, 64);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+
vbo_exec_vtxfmt_init( exec );
/* Hook our functions into the dispatch table.
@@ -725,38 +800,82 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
{
- if (exec->vtx.bufferobj->Name) {
- /* using a real VBO for vertex data */
- GLcontext *ctx = exec->ctx;
- _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
- }
- else {
- /* just using malloc'd space for vertex data */
- if (exec->vtx.buffer_map) {
+ /* using a real VBO for vertex data */
+ GLcontext *ctx = exec->ctx;
+ unsigned i;
+
+ /* True VBOs should already be unmapped
+ */
+ if (exec->vtx.buffer_map) {
+ ASSERT(exec->vtx.bufferobj->Name == 0 ||
+ exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
+ if (exec->vtx.bufferobj->Name == 0) {
ALIGN_FREE(exec->vtx.buffer_map);
exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
}
}
-}
+ /* Drop any outstanding reference to the vertex buffer
+ */
+ for (i = 0; i < Elements(exec->vtx.arrays); i++) {
+ _mesa_reference_buffer_object(ctx,
+ &exec->vtx.arrays[i].BufferObj,
+ NULL);
+ }
-void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags )
+ /* Free the vertex buffer:
+ */
+ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
+}
+
+void vbo_exec_BeginVertices( GLcontext *ctx )
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ if (0) _mesa_printf("%s\n", __FUNCTION__);
+ vbo_exec_vtx_map( exec );
- if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
- return;
+ assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
+ exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
+}
- if (exec->vtx.vert_count) {
- vbo_exec_vtx_flush( exec );
+void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ 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 );
}
+}
+
+
+
+void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- exec->ctx->Driver.NeedFlush = 0;
+ if (0) _mesa_printf("%s\n", __FUNCTION__);
+
+ if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+ if (0) _mesa_printf("%s - inside begin/end\n", __FUNCTION__);
+ return;
+ }
+
+ vbo_exec_FlushVertices_internal( ctx, GL_TRUE );
+
+ /* Need to do this to ensure BeginVertices gets called again:
+ */
+ if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) {
+ _mesa_restore_exec_vtxfmt( ctx );
+ exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
+ }
+
+ exec->ctx->Driver.NeedFlush &= ~flags;
}
@@ -772,3 +891,36 @@ static void reset_attrfv( struct vbo_exec_context *exec )
exec->vtx.vertex_size = 0;
}
+
+void GLAPIENTRY
+_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
+{
+ vbo_Color4f(r, g, b, a);
+}
+
+
+void GLAPIENTRY
+_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ vbo_Normal3f(x, y, z);
+}
+
+
+void GLAPIENTRY
+_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ vbo_MultiTexCoord4f(target, s, t, r, q);
+}
+
+void GLAPIENTRY
+_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
+{
+ vbo_Materialfv(face, pname, params);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ vbo_VertexAttrib4fARB(index, x, y, z, w);
+}
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 82f4db17d1..b9550d6106 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -30,19 +31,38 @@
#include "main/state.h"
#include "main/api_validate.h"
#include "main/api_noop.h"
+#include "main/varray.h"
+#include "main/bufferobj.h"
+#include "main/macros.h"
+#include "glapi/dispatch.h"
#include "vbo_context.h"
-/* Compute min and max elements for drawelements calls.
+
+/**
+ * Compute min and max elements for glDraw[Range]Elements() calls.
*/
-static void get_minmax_index( GLuint count, GLuint type,
- const GLvoid *indices,
- GLuint *min_index,
- GLuint *max_index)
+void
+vbo_get_minmax_index(GLcontext *ctx,
+ const struct _mesa_prim *prim,
+ const struct _mesa_index_buffer *ib,
+ GLuint *min_index, GLuint *max_index)
{
GLuint i;
+ GLsizei count = prim->count;
+ const void *indices;
+
+ if (_mesa_is_bufferobj(ib->obj)) {
+ const GLvoid *map = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ib->obj);
+ indices = ADD_POINTERS(map, ib->ptr);
+ } else {
+ indices = ib->ptr;
+ }
- switch(type) {
+ switch (ib->type) {
case GL_UNSIGNED_INT: {
const GLuint *ui_indices = (const GLuint *)indices;
GLuint max_ui = ui_indices[count-1];
@@ -83,48 +103,250 @@ static void get_minmax_index( GLuint count, GLuint type,
assert(0);
break;
}
+
+ if (_mesa_is_bufferobj(ib->obj)) {
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ib->obj);
+ }
+}
+
+
+/**
+ * Check that element 'j' of the array has reasonable data.
+ * Map VBO if needed.
+ */
+static void
+check_array_data(GLcontext *ctx, struct gl_client_array *array,
+ GLuint attrib, GLuint j)
+{
+ if (array->Enabled) {
+ const void *data = array->Ptr;
+ if (_mesa_is_bufferobj(array->BufferObj)) {
+ if (!array->BufferObj->Pointer) {
+ /* need to map now */
+ array->BufferObj->Pointer = ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ array->BufferObj);
+ }
+ data = ADD_POINTERS(data, array->BufferObj->Pointer);
+ }
+ switch (array->Type) {
+ case GL_FLOAT:
+ {
+ GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
+ GLuint k;
+ for (k = 0; k < array->Size; k++) {
+ if (IS_INF_OR_NAN(f[k]) ||
+ f[k] >= 1.0e20 || f[k] <= -1.0e10) {
+ _mesa_printf("Bad array data:\n");
+ _mesa_printf(" Element[%u].%u = %f\n", j, k, f[k]);
+ _mesa_printf(" Array %u at %p\n", attrib, (void* ) array);
+ _mesa_printf(" Type 0x%x, Size %d, Stride %d\n",
+ array->Type, array->Size, array->Stride);
+ _mesa_printf(" Address/offset %p in Buffer Object %u\n",
+ array->Ptr, array->BufferObj->Name);
+ f[k] = 1.0; /* XXX replace the bad value! */
+ }
+ //assert(!IS_INF_OR_NAN(f[k]));
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+
+/**
+ * Unmap the buffer object referenced by given array, if mapped.
+ */
+static void
+unmap_array_buffer(GLcontext *ctx, struct gl_client_array *array)
+{
+ if (array->Enabled &&
+ _mesa_is_bufferobj(array->BufferObj) &&
+ _mesa_bufferobj_mapped(array->BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ array->BufferObj);
+ }
}
-/* Just translate the arrayobj into a sane layout.
+/**
+ * Examine the array's data for NaNs, etc.
*/
-static void bind_array_obj( GLcontext *ctx )
+static void
+check_draw_elements_data(GLcontext *ctx, GLsizei count, GLenum elemType,
+ const void *elements, GLint basevertex)
+{
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ const void *elemMap;
+ GLint i, k;
+
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
+ elemMap = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ctx->Array.ElementArrayBufferObj);
+ elements = ADD_POINTERS(elements, elemMap);
+ }
+
+ for (i = 0; i < count; i++) {
+ GLuint j;
+
+ /* j = element[i] */
+ switch (elemType) {
+ case GL_UNSIGNED_BYTE:
+ j = ((const GLubyte *) elements)[i];
+ break;
+ case GL_UNSIGNED_SHORT:
+ j = ((const GLushort *) elements)[i];
+ break;
+ case GL_UNSIGNED_INT:
+ j = ((const GLuint *) elements)[i];
+ break;
+ default:
+ assert(0);
+ }
+
+ /* check element j of each enabled array */
+ check_array_data(ctx, &arrayObj->Vertex, VERT_ATTRIB_POS, j);
+ check_array_data(ctx, &arrayObj->Normal, VERT_ATTRIB_NORMAL, j);
+ check_array_data(ctx, &arrayObj->Color, VERT_ATTRIB_COLOR0, j);
+ check_array_data(ctx, &arrayObj->SecondaryColor, VERT_ATTRIB_COLOR1, j);
+ for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
+ check_array_data(ctx, &arrayObj->TexCoord[k], VERT_ATTRIB_TEX0 + k, j);
+ }
+ for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
+ check_array_data(ctx, &arrayObj->VertexAttrib[k], VERT_ATTRIB_GENERIC0 + k, j);
+ }
+ }
+
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ctx->Array.ElementArrayBufferObj);
+ }
+
+ unmap_array_buffer(ctx, &arrayObj->Vertex);
+ unmap_array_buffer(ctx, &arrayObj->Normal);
+ unmap_array_buffer(ctx, &arrayObj->Color);
+ for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
+ unmap_array_buffer(ctx, &arrayObj->TexCoord[k]);
+ }
+ for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
+ unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
+ }
+}
+
+
+/**
+ * Check array data, looking for NaNs, etc.
+ */
+static void
+check_draw_arrays_data(GLcontext *ctx, GLint start, GLsizei count)
+{
+ /* TO DO */
+}
+
+
+/**
+ * Print info/data for glDrawArrays().
+ */
+static void
+print_draw_arrays(GLcontext *ctx, struct vbo_exec_context *exec,
+ GLenum mode, GLint start, GLsizei count)
+{
+ int i;
+
+ _mesa_printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
+ mode, start, count);
+
+ for (i = 0; i < 32; i++) {
+ GLuint bufName = exec->array.inputs[i]->BufferObj->Name;
+ GLint stride = exec->array.inputs[i]->Stride;
+ _mesa_printf("attr %2d: size %d stride %d enabled %d "
+ "ptr %p Bufobj %u\n",
+ i,
+ exec->array.inputs[i]->Size,
+ stride,
+ /*exec->array.inputs[i]->Enabled,*/
+ exec->array.legacy_array[i]->Enabled,
+ exec->array.inputs[i]->Ptr,
+ bufName);
+
+ if (bufName) {
+ struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName);
+ GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY_ARB, buf);
+ int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
+ float *f = (float *) (p + offset);
+ int *k = (int *) f;
+ int i;
+ int n = (count * stride) / 4;
+ if (n > 32)
+ n = 32;
+ _mesa_printf(" Data at offset %d:\n", offset);
+ for (i = 0; i < n; i++) {
+ _mesa_printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
+ }
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf);
+ }
+ }
+}
+
+
+/**
+ * Just translate the arrayobj into a sane layout.
+ */
+static void
+bind_array_obj(GLcontext *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
GLuint i;
/* TODO: Fix the ArrayObj struct to keep legacy arrays in an array
* rather than as individual named arrays. Then this function can
* go away.
*/
- exec->array.legacy_array[VERT_ATTRIB_POS] = &ctx->Array.ArrayObj->Vertex;
- exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &vbo->legacy_currval[VERT_ATTRIB_WEIGHT];
- exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &ctx->Array.ArrayObj->Normal;
- exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &ctx->Array.ArrayObj->Color;
- exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &ctx->Array.ArrayObj->SecondaryColor;
- exec->array.legacy_array[VERT_ATTRIB_FOG] = &ctx->Array.ArrayObj->FogCoord;
- exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &ctx->Array.ArrayObj->Index;
- if (ctx->Array.ArrayObj->PointSize.Enabled) {
+ exec->array.legacy_array[VERT_ATTRIB_POS] = &arrayObj->Vertex;
+ exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &arrayObj->Weight;
+ exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &arrayObj->Normal;
+ exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &arrayObj->Color;
+ exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &arrayObj->SecondaryColor;
+ exec->array.legacy_array[VERT_ATTRIB_FOG] = &arrayObj->FogCoord;
+ exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &arrayObj->Index;
+ if (arrayObj->PointSize.Enabled) {
/* this aliases COLOR_INDEX */
- exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &ctx->Array.ArrayObj->PointSize;
+ exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &arrayObj->PointSize;
}
- exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &ctx->Array.ArrayObj->EdgeFlag;
+ exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &arrayObj->EdgeFlag;
- for (i = 0; i < 8; i++)
- exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &ctx->Array.ArrayObj->TexCoord[i];
+ for (i = 0; i < Elements(arrayObj->TexCoord); i++)
+ exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &arrayObj->TexCoord[i];
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
- exec->array.generic_array[i] = &ctx->Array.ArrayObj->VertexAttrib[i];
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
+ assert(i < Elements(exec->array.generic_array));
+ exec->array.generic_array[i] = &arrayObj->VertexAttrib[i];
+ }
- exec->array.array_obj = ctx->Array.ArrayObj->Name;
+ exec->array.array_obj = arrayObj->Name;
}
-static void recalculate_input_bindings( GLcontext *ctx )
+
+static void
+recalculate_input_bindings(GLcontext *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
const struct gl_client_array **inputs = &exec->array.inputs[0];
+ GLbitfield const_inputs = 0x0;
GLuint i;
exec->array.program_mode = get_program_mode(ctx);
@@ -132,28 +354,34 @@ static void recalculate_input_bindings( GLcontext *ctx )
switch (exec->array.program_mode) {
case VP_NONE:
- /* When no vertex program is active, we put the material values
- * into the generic slots. This is the only situation where
- * material values are available as per-vertex attributes.
+ /* When no vertex program is active (or the vertex program is generated
+ * from fixed-function state). We put the material values into the
+ * generic slots. This is the only situation where material values
+ * are available as per-vertex attributes.
*/
for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
- else
+ else {
inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
}
for (i = 0; i < MAT_ATTRIB_MAX; i++) {
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
}
/* Could use just about anything, just to fill in the empty
* slots:
*/
- for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++)
+ for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) {
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
-
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
break;
+
case VP_NV:
/* NV_vertex_program - attribute arrays alias and override
* conventional, legacy arrays. No materials, and the generic
@@ -164,20 +392,24 @@ static void recalculate_input_bindings( GLcontext *ctx )
inputs[i] = exec->array.generic_array[i];
else if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
- else
+ else {
inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
}
/* Could use just about anything, just to fill in the empty
* slots:
*/
- for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++)
+ for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
-
+ const_inputs |= 1 << i;
+ }
break;
+
case VP_ARB:
- /* ARB_vertex_program - Only the attribute zero (position) array
- * aliases and overrides the legacy position array.
+ /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
+ * attribute array aliases and overrides the legacy position array.
*
* Otherwise, legacy attributes available in the legacy slots,
* generic attributes in the generic slots and materials are not
@@ -187,28 +419,38 @@ static void recalculate_input_bindings( GLcontext *ctx )
inputs[0] = exec->array.generic_array[0];
else if (exec->array.legacy_array[0]->Enabled)
inputs[0] = exec->array.legacy_array[0];
- else
+ else {
inputs[0] = &vbo->legacy_currval[0];
-
+ const_inputs |= 1 << 0;
+ }
for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
- else
+ else {
inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
}
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
if (exec->array.generic_array[i]->Enabled)
inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
- else
+ else {
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
+
}
break;
}
+
+ _mesa_set_varying_vp_inputs( ctx, ~const_inputs );
}
-static void bind_arrays( GLcontext *ctx )
+
+static void
+bind_arrays(GLcontext *ctx)
{
#if 0
if (ctx->Array.ArrayObj.Name != exec->array.array_obj) {
@@ -248,13 +490,26 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
if (ctx->NewState)
_mesa_update_state( ctx );
- if (!vbo_validate_shaders(ctx)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawArrays(bad shader)");
+ if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
return;
}
+#if 0
+ check_draw_arrays_data(ctx, start, count);
+#else
+ (void) check_draw_arrays_data;
+#endif
+
bind_arrays( ctx );
+ /* Again... because we may have changed the bitmask of per-vertex varying
+ * attributes. If we regenerate the fixed-function vertex program now
+ * we may be able to prune down the number of vertex attributes which we
+ * need in the shader.
+ */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
prim[0].begin = 1;
prim[0].end = 1;
prim[0].weak = 0;
@@ -263,40 +518,105 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
prim[0].start = start;
prim[0].count = count;
prim[0].indexed = 0;
+ prim[0].basevertex = 0;
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count - 1 );
+ vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL,
+ GL_TRUE, start, start + count - 1 );
+
+#if 0
+ print_draw_arrays(ctx, exec, mode, start, count);
+#else
+ (void) print_draw_arrays;
+#endif
}
+/**
+ * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
+ */
+static void
+dump_element_buffer(GLcontext *ctx, GLenum type)
+{
+ const GLvoid *map = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ctx->Array.ElementArrayBufferObj);
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ const GLubyte *us = (const GLubyte *) map;
+ GLuint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) {
+ _mesa_printf("%02x ", us[i]);
+ if (i % 32 == 31)
+ _mesa_printf("\n");
+ }
+ _mesa_printf("\n");
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ const GLushort *us = (const GLushort *) map;
+ GLuint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) {
+ _mesa_printf("%04x ", us[i]);
+ if (i % 16 == 15)
+ _mesa_printf("\n");
+ }
+ _mesa_printf("\n");
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ const GLuint *us = (const GLuint *) map;
+ GLuint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) {
+ _mesa_printf("%08x ", us[i]);
+ if (i % 8 == 7)
+ _mesa_printf("\n");
+ }
+ _mesa_printf("\n");
+ }
+ break;
+ default:
+ ;
+ }
-static void GLAPIENTRY
-vbo_exec_DrawRangeElements(GLenum mode,
- GLuint start, GLuint end,
- GLsizei count, GLenum type, const GLvoid *indices)
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ctx->Array.ElementArrayBufferObj);
+}
+
+/* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements */
+static void
+vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode,
+ GLboolean index_bounds_valid,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
{
- GET_CURRENT_CONTEXT(ctx);
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct _mesa_index_buffer ib;
struct _mesa_prim prim[1];
- if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices ))
- return;
-
FLUSH_CURRENT( ctx, 0 );
if (ctx->NewState)
_mesa_update_state( ctx );
- if (!vbo_validate_shaders(ctx)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawRangeElements(bad shader)");
+ if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
return;
}
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
bind_arrays( ctx );
ib.count = count;
- ib.type = type;
+ ib.type = type;
ib.obj = ctx->Array.ElementArrayBufferObj;
ib.ptr = indices;
@@ -308,6 +628,7 @@ vbo_exec_DrawRangeElements(GLenum mode,
prim[0].start = 0;
prim[0].count = count;
prim[0].indexed = 1;
+ prim[0].basevertex = basevertex;
/* Need to give special consideration to rendering a range of
* indices starting somewhere above zero. Typically the
@@ -340,66 +661,366 @@ vbo_exec_DrawRangeElements(GLenum mode,
* for the latter case elsewhere.
*/
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end );
+ vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
+ index_bounds_valid, start, end );
}
static void GLAPIENTRY
-vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
+vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
{
GET_CURRENT_CONTEXT(ctx);
- GLuint min_index = 0;
- GLuint max_index = 0;
- if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+ if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
+ type, indices, basevertex ))
return;
- if (!vbo_validate_shaders(ctx)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawElements(bad shader)");
+ if (end >= ctx->Array.ArrayObj->_MaxElement) {
+ /* the max element is out of bounds of one or more enabled arrays */
+ _mesa_warning(ctx, "glDraw[Range]Elements{,BaseVertex}(start %u, end %u, "
+ "count %d, type 0x%x, indices=%p, base=%d)\n"
+ "\tindex=%u is out of bounds (max=%u) "
+ "Element Buffer %u (size %d)",
+ start, end, count, type, indices, end, basevertex,
+ ctx->Array.ArrayObj->_MaxElement - 1,
+ ctx->Array.ElementArrayBufferObj->Name,
+ ctx->Array.ElementArrayBufferObj->Size);
+
+ if (0)
+ dump_element_buffer(ctx, type);
+
+ if (0)
+ _mesa_print_arrays(ctx);
return;
}
+ else if (0) {
+ _mesa_printf("glDraw[Range]Elements{,BaseVertex}"
+ "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
+ "base %d\n",
+ start, end, type, count,
+ ctx->Array.ElementArrayBufferObj->Name,
+ basevertex);
+ }
- if (ctx->Array.ElementArrayBufferObj->Name) {
- const GLvoid *map = ctx->Driver.MapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- GL_READ_ONLY,
- ctx->Array.ElementArrayBufferObj);
+#if 0
+ check_draw_elements_data(ctx, count, type, indices);
+#else
+ (void) check_draw_elements_data;
+#endif
- get_minmax_index(count, type, ADD_POINTERS(map, indices), &min_index, &max_index);
+ vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
+ count, type, indices, basevertex);
+}
- ctx->Driver.UnmapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- ctx->Array.ElementArrayBufferObj);
+static void GLAPIENTRY
+vbo_exec_DrawRangeElements(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
+ indices, 0);
+}
+
+
+static void GLAPIENTRY
+vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
+ return;
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
+ count, type, indices, 0);
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
+ basevertex ))
+ return;
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
+ count, type, indices, basevertex);
+}
+
+/* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements */
+static void
+vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount,
+ const GLint *basevertex)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct _mesa_index_buffer ib;
+ struct _mesa_prim *prim;
+ unsigned int index_type_size = 0;
+ uintptr_t min_index_ptr, max_index_ptr;
+ GLboolean fallback = GL_FALSE;
+ int i;
+
+ if (primcount == 0)
+ return;
+
+ FLUSH_CURRENT( ctx, 0 );
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ prim = _mesa_calloc(primcount * sizeof(*prim));
+ if (prim == NULL) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
+ return;
+ }
+
+ /* Decide if we can do this all as one set of primitives sharing the
+ * same index buffer, or if we have to reset the index pointer per primitive.
+ */
+ bind_arrays( ctx );
+
+ switch (type) {
+ case GL_UNSIGNED_INT:
+ index_type_size = 4;
+ break;
+ case GL_UNSIGNED_SHORT:
+ index_type_size = 2;
+ break;
+ case GL_UNSIGNED_BYTE:
+ index_type_size = 1;
+ break;
+ default:
+ assert(0);
+ }
+
+ min_index_ptr = (uintptr_t)indices[0];
+ max_index_ptr = 0;
+ for (i = 0; i < primcount; i++) {
+ min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
+ max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
+ index_type_size * count[i]);
+ }
+
+ /* Check if we can handle this thing as a bunch of index offsets from the
+ * same index pointer. If we can't, then we have to fall back to doing
+ * a draw_prims per primitive.
+ */
+ if (index_type_size != 1) {
+ for (i = 0; i < primcount; i++) {
+ if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
+ fallback = GL_TRUE;
+ break;
+ }
+ }
}
- else {
- get_minmax_index(count, type, indices, &min_index, &max_index);
+
+ /* If the index buffer isn't in a VBO, then treating the application's
+ * subranges of the index buffer as one large index buffer may lead to
+ * us reading unmapped memory.
+ */
+ if (!_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
+ fallback = GL_TRUE;
+
+ if (!fallback) {
+ ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
+ ib.type = type;
+ ib.obj = ctx->Array.ElementArrayBufferObj;
+ ib.ptr = (void *)min_index_ptr;
+
+ for (i = 0; i < primcount; i++) {
+ prim[i].begin = (i == 0);
+ prim[i].end = (i == primcount - 1);
+ prim[i].weak = 0;
+ prim[i].pad = 0;
+ prim[i].mode = mode;
+ prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
+ prim[i].count = count[i];
+ prim[i].indexed = 1;
+ if (basevertex != NULL)
+ prim[i].basevertex = basevertex[i];
+ else
+ prim[i].basevertex = 0;
+ }
+
+ vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
+ GL_FALSE, ~0, ~0);
+ } else {
+ for (i = 0; i < primcount; i++) {
+ ib.count = count[i];
+ ib.type = type;
+ ib.obj = ctx->Array.ElementArrayBufferObj;
+ ib.ptr = indices[i];
+
+
+ prim[0].begin = 1;
+ prim[0].end = 1;
+ prim[0].weak = 0;
+ prim[0].pad = 0;
+ prim[0].mode = mode;
+ prim[0].start = 0;
+ prim[0].count = count[i];
+ prim[0].indexed = 1;
+ if (basevertex != NULL)
+ prim[0].basevertex = basevertex[i];
+ else
+ prim[0].basevertex = 0;
+ }
+
+ vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
+ GL_FALSE, ~0, ~0);
}
+ _mesa_free(prim);
+}
- vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type, indices);
+static void GLAPIENTRY
+vbo_exec_MultiDrawElements(GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ for (i = 0; i < primcount; i++) {
+ if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
+ 0))
+ return;
+ }
+
+ vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
+ NULL);
}
+static void GLAPIENTRY
+vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount,
+ const GLsizei *basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
-/***********************************************************************
- * Initialization
- */
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ for (i = 0; i < primcount; i++) {
+ if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
+ basevertex[i]))
+ return;
+ }
+ vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
+ basevertex);
+}
+/***********************************************************************
+ * Initialization
+ */
-void vbo_exec_array_init( struct vbo_exec_context *exec )
+void
+vbo_exec_array_init( struct vbo_exec_context *exec )
{
#if 1
exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
+ exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
+ exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
+ exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
+ exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
#else
exec->vtxfmt.DrawArrays = _mesa_noop_DrawArrays;
exec->vtxfmt.DrawElements = _mesa_noop_DrawElements;
exec->vtxfmt.DrawRangeElements = _mesa_noop_DrawRangeElements;
+ exec->vtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ exec->vtxfmt.DrawElementsBaseVertex = _mesa_noop_DrawElementsBaseVertex;
+ exec->vtxfmt.DrawRangeElementsBaseVertex = _mesa_noop_DrawRangeElementsBaseVertex;
+ exec->vtxfmt.MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
#endif
}
-void vbo_exec_array_destroy( struct vbo_exec_context *exec )
+void
+vbo_exec_array_destroy( struct vbo_exec_context *exec )
{
/* nothing to do */
}
+
+
+/* This API entrypoint is not ordinarily used */
+void GLAPIENTRY
+_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ vbo_exec_DrawArrays(mode, first, count);
+}
+
+
+/* This API entrypoint is not ordinarily used */
+void GLAPIENTRY
+_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ vbo_exec_DrawElements(mode, count, type, indices);
+}
+
+void GLAPIENTRY
+_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
+}
+
+
+/* This API entrypoint is not ordinarily used */
+void GLAPIENTRY
+_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices)
+{
+ vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
+}
+
+void GLAPIENTRY
+_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices, GLint basevertex)
+{
+ vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
+ indices, basevertex);
+}
+
+/* GL_EXT_multi_draw_arrays */
+void GLAPIENTRY
+_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount)
+{
+ vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
+}
+
+void GLAPIENTRY
+_mesa_MultiDrawElementsBaseVertex(GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount,
+ const GLint *basevertex)
+{
+ vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
+ primcount, basevertex);
+}
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
index 92356ba977..ee148df4a1 100644
--- a/src/mesa/vbo/vbo_exec_draw.c
+++ b/src/mesa/vbo/vbo_exec_draw.c
@@ -35,7 +35,11 @@
#include "vbo_context.h"
-static void vbo_exec_debug_verts( struct vbo_exec_context *exec )
+#if FEATURE_beginend
+
+
+static void
+vbo_exec_debug_verts( struct vbo_exec_context *exec )
{
GLuint count = exec->vtx.vert_count;
GLuint i;
@@ -50,7 +54,7 @@ static void vbo_exec_debug_verts( struct vbo_exec_context *exec )
struct _mesa_prim *prim = &exec->vtx.prim[i];
_mesa_printf(" prim %d: %s%s %d..%d %s %s\n",
i,
- _mesa_lookup_enum_by_nr(prim->mode),
+ _mesa_lookup_prim_by_nr(prim->mode),
prim->weak ? " (weak)" : "",
prim->start,
prim->start + prim->count,
@@ -64,19 +68,19 @@ static void vbo_exec_debug_verts( struct vbo_exec_context *exec )
* NOTE: Need to have calculated primitives by this point -- do it on the fly.
* NOTE: Old 'parity' issue is gone.
*/
-static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
+static GLuint
+vbo_copy_vertices( struct vbo_exec_context *exec )
{
GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count;
GLuint ovf, i;
GLuint sz = exec->vtx.vertex_size;
GLfloat *dst = exec->vtx.copied.buffer;
- GLfloat *src = ((GLfloat *)exec->vtx.buffer_map +
- exec->vtx.prim[exec->vtx.prim_count-1].start *
- exec->vtx.vertex_size);
+ const GLfloat *src = (exec->vtx.buffer_map +
+ exec->vtx.prim[exec->vtx.prim_count-1].start *
+ exec->vtx.vertex_size);
- switch( exec->ctx->Driver.CurrentExecPrimitive )
- {
+ switch (exec->ctx->Driver.CurrentExecPrimitive) {
case GL_POINTS:
return 0;
case GL_LINES:
@@ -95,8 +99,9 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
_mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
return i;
case GL_LINE_STRIP:
- if (nr == 0)
+ if (nr == 0) {
return 0;
+ }
else {
_mesa_memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) );
return 1;
@@ -104,12 +109,14 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
case GL_LINE_LOOP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
- if (nr == 0)
+ if (nr == 0) {
return 0;
+ }
else if (nr == 1) {
_mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) );
return 1;
- } else {
+ }
+ else {
_mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) );
_mesa_memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) );
return 2;
@@ -122,9 +129,15 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
/* fallthrough */
case GL_QUAD_STRIP:
switch (nr) {
- case 0: ovf = 0; break;
- case 1: ovf = 1; break;
- default: ovf = 2 + (nr&1); break;
+ case 0:
+ ovf = 0;
+ break;
+ case 1:
+ ovf = 1;
+ break;
+ default:
+ ovf = 2 + (nr & 1);
+ break;
}
for (i = 0 ; i < ovf ; i++)
_mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
@@ -141,15 +154,17 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
/* TODO: populate these as the vertex is defined:
*/
-static void vbo_exec_bind_arrays( GLcontext *ctx )
+static void
+vbo_exec_bind_arrays( GLcontext *ctx )
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct gl_client_array *arrays = exec->vtx.arrays;
- GLuint count = exec->vtx.vert_count;
- GLubyte *data = exec->vtx.buffer_map;
+ const GLuint count = exec->vtx.vert_count;
+ const GLubyte *data = (GLubyte *) exec->vtx.buffer_map;
const GLuint *map;
GLuint attr;
+ GLbitfield varying_inputs = 0x0;
/* Install the default (ie Current) attributes first, then overlay
* all active ones.
@@ -175,7 +190,21 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
exec->vtx.inputs[attr + 16] = &vbo->generic_currval[attr];
}
map = vbo->map_vp_arb;
+
+ /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
+ * In that case we effectively need to route the data from
+ * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
+ */
+ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
+ (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
+ exec->vtx.inputs[16] = exec->vtx.inputs[0];
+ exec->vtx.attrsz[16] = exec->vtx.attrsz[0];
+ exec->vtx.attrptr[16] = exec->vtx.attrptr[0];
+ exec->vtx.attrsz[0] = 0;
+ }
break;
+ default:
+ assert(0);
}
/* Make all active attributes (including edgeflag) available as
@@ -188,11 +217,13 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
/* override the default array set above */
exec->vtx.inputs[attr] = &arrays[attr];
- if (exec->vtx.bufferobj->Name) {
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
/* a real buffer obj: Ptr is an offset, not a pointer*/
- int offset;
+ GLsizeiptr offset;
assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */
- offset = (GLbyte *) data - (GLbyte *) exec->vtx.bufferobj->Pointer;
+ offset = (GLbyte *) data -
+ (GLbyte *) exec->vtx.bufferobj->Pointer +
+ exec->vtx.bufferobj->Offset;
assert(offset >= 0);
arrays[attr].Ptr = (void *) offset;
}
@@ -204,6 +235,7 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat);
arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat);
arrays[attr].Type = GL_FLOAT;
+ arrays[attr].Format = GL_RGBA;
arrays[attr].Enabled = 1;
_mesa_reference_buffer_object(ctx,
&arrays[attr].BufferObj,
@@ -211,20 +243,117 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
arrays[attr]._MaxElement = count; /* ??? */
data += exec->vtx.attrsz[src] * sizeof(GLfloat);
+ varying_inputs |= 1 << attr;
}
}
+
+ _mesa_set_varying_vp_inputs( ctx, varying_inputs );
+}
+
+
+static void
+vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
+{
+ GLenum target = GL_ARRAY_BUFFER_ARB;
+
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
+ GLcontext *ctx = exec->ctx;
+
+ if (ctx->Driver.FlushMappedBufferRange) {
+ GLintptr offset = exec->vtx.buffer_used - exec->vtx.bufferobj->Offset;
+ GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * sizeof(float);
+
+ if (length)
+ ctx->Driver.FlushMappedBufferRange(ctx, target,
+ offset, length,
+ exec->vtx.bufferobj);
+ }
+
+ exec->vtx.buffer_used += (exec->vtx.buffer_ptr -
+ exec->vtx.buffer_map) * sizeof(float);
+
+ assert(exec->vtx.buffer_used <= VBO_VERT_BUFFER_SIZE);
+ assert(exec->vtx.buffer_ptr != NULL);
+
+ ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
+ exec->vtx.max_vert = 0;
+ }
+}
+
+
+void
+vbo_exec_vtx_map( struct vbo_exec_context *exec )
+{
+ GLcontext *ctx = exec->ctx;
+ const GLenum target = GL_ARRAY_BUFFER_ARB;
+ const GLenum access = GL_READ_WRITE_ARB; /* for MapBuffer */
+ const GLenum accessRange = GL_MAP_WRITE_BIT | /* for MapBufferRange */
+ GL_MAP_INVALIDATE_RANGE_BIT |
+ GL_MAP_UNSYNCHRONIZED_BIT |
+ GL_MAP_FLUSH_EXPLICIT_BIT |
+ MESA_MAP_NOWAIT_BIT;
+ const GLenum usage = GL_STREAM_DRAW_ARB;
+
+ 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;
+ }
+
+ if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 &&
+ ctx->Driver.MapBufferRange) {
+ exec->vtx.buffer_map =
+ (GLfloat *)ctx->Driver.MapBufferRange(ctx,
+ target,
+ exec->vtx.buffer_used,
+ (VBO_VERT_BUFFER_SIZE -
+ exec->vtx.buffer_used),
+ accessRange,
+ exec->vtx.bufferobj);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ }
+
+ if (!exec->vtx.buffer_map) {
+ exec->vtx.buffer_used = 0;
+
+ ctx->Driver.BufferData(ctx, target,
+ VBO_VERT_BUFFER_SIZE,
+ NULL, usage, exec->vtx.bufferobj);
+
+
+ if (ctx->Driver.MapBufferRange)
+ exec->vtx.buffer_map =
+ (GLfloat *)ctx->Driver.MapBufferRange(ctx, target,
+ 0, VBO_VERT_BUFFER_SIZE,
+ accessRange,
+ exec->vtx.bufferobj);
+ if (!exec->vtx.buffer_map)
+ exec->vtx.buffer_map =
+ (GLfloat *)ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
+ assert(exec->vtx.buffer_map);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ }
+
+ if (0)
+ _mesa_printf("map %d..\n", exec->vtx.buffer_used);
}
+
/**
* Execute the buffer and save copied verts.
*/
-void vbo_exec_vtx_flush( struct vbo_exec_context *exec )
+void
+vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
{
if (0)
vbo_exec_debug_verts( exec );
-
if (exec->vtx.prim_count &&
exec->vtx.vert_count) {
@@ -232,40 +361,59 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec )
if (exec->vtx.copied.nr != exec->vtx.vert_count) {
GLcontext *ctx = exec->ctx;
-
- GLenum target = GL_ARRAY_BUFFER_ARB;
- GLenum access = GL_READ_WRITE_ARB;
- GLenum usage = GL_STREAM_DRAW_ARB;
- GLsizei size = VBO_VERT_BUFFER_SIZE * sizeof(GLfloat);
- /* Before the unmap (why?)
+ /* Before the update_state() as this may raise _NEW_ARRAY
+ * from _mesa_set_varying_vp_inputs().
*/
vbo_exec_bind_arrays( ctx );
- /* if using a real VBO, unmap it before drawing */
- if (exec->vtx.bufferobj->Name) {
- ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj);
- exec->vtx.buffer_map = NULL;
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
+ vbo_exec_vtx_unmap( exec );
}
+ if (0)
+ _mesa_printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count,
+ exec->vtx.vert_count);
+
vbo_context(ctx)->draw_prims( ctx,
exec->vtx.inputs,
exec->vtx.prim,
exec->vtx.prim_count,
NULL,
+ GL_TRUE,
0,
exec->vtx.vert_count - 1);
- /* If using a real VBO, get new storage */
- if (exec->vtx.bufferobj->Name) {
- ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
- exec->vtx.buffer_map =
- ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
+ /* If using a real VBO, get new storage -- unless asked not to.
+ */
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !unmap) {
+ vbo_exec_vtx_map( exec );
}
}
}
+ /* May have to unmap explicitly if we didn't draw:
+ */
+ if (unmap &&
+ _mesa_is_bufferobj(exec->vtx.bufferobj) &&
+ exec->vtx.buffer_map) {
+ vbo_exec_vtx_unmap( exec );
+ }
+
+
+ if (unmap || exec->vtx.vertex_size == 0)
+ exec->vtx.max_vert = 0;
+ else
+ exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
+ (exec->vtx.vertex_size * sizeof(GLfloat)));
+
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
exec->vtx.prim_count = 0;
exec->vtx.vert_count = 0;
- exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map;
}
+
+
+#endif /* FEATURE_beginend */
diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c
index dae778e741..799a25fc1c 100644
--- a/src/mesa/vbo/vbo_rebase.c
+++ b/src/mesa/vbo/vbo_rebase.c
@@ -126,7 +126,20 @@ void vbo_rebase_prims( GLcontext *ctx,
if (0)
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
- if (ib) {
+
+ if (ib && ctx->Extensions.ARB_draw_elements_base_vertex) {
+ /* If we can just tell the hardware or the TNL to interpret our
+ * indices with a different base, do so.
+ */
+ tmp_prims = (struct _mesa_prim *)_mesa_malloc(sizeof(*prim) * nr_prims);
+
+ for (i = 0; i < nr_prims; i++) {
+ tmp_prims[i] = prim[i];
+ tmp_prims[i].basevertex -= min_index;
+ }
+
+ prim = tmp_prims;
+ } else if (ib) {
/* Unfortunately need to adjust each index individually.
*/
GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer;
@@ -161,7 +174,7 @@ void vbo_rebase_prims( GLcontext *ctx,
GL_ELEMENT_ARRAY_BUFFER,
ib->obj);
- tmp_ib.obj = ctx->Array.NullBufferObj;
+ tmp_ib.obj = ctx->Shared->NullBufferObj;
tmp_ib.ptr = tmp_indices;
tmp_ib.count = ib->count;
tmp_ib.type = ib->type;
@@ -208,6 +221,7 @@ void vbo_rebase_prims( GLcontext *ctx,
prim,
nr_prims,
ib,
+ GL_TRUE,
0,
max_index - min_index );
diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h
index b7e9baabf8..86bbd24f7b 100644
--- a/src/mesa/vbo/vbo_save.h
+++ b/src/mesa/vbo/vbo_save.h
@@ -64,6 +64,13 @@ struct vbo_save_vertex_list {
GLubyte attrsz[VBO_ATTRIB_MAX];
GLuint vertex_size;
+ /* Copy of the final vertex from node->vertex_store->bufferobj.
+ * Keep this in regular (non-VBO) memory to avoid repeated
+ * map/unmap of the VBO when updating GL current data.
+ */
+ GLfloat *current_data;
+ GLuint current_size;
+
GLuint buffer_offset;
GLuint count;
GLuint wrap_count; /* number of copied vertices at start */
@@ -130,7 +137,7 @@ struct vbo_save_context {
struct vbo_save_vertex_store *vertex_store;
struct vbo_save_primitive_store *prim_store;
- GLfloat *vbptr; /* cursor, points into buffer */
+ GLfloat *buffer_ptr; /* cursor, points into buffer */
GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current values */
GLfloat *attrptr[VBO_ATTRIB_MAX];
GLuint vert_count;
@@ -166,7 +173,7 @@ void vbo_loopback_vertex_list( GLcontext *ctx,
void vbo_save_EndList( GLcontext *ctx );
void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode );
void vbo_save_EndCallList( GLcontext *ctx );
-void vbo_save_BeginCallList( GLcontext *ctx, struct mesa_display_list *list );
+void vbo_save_BeginCallList( GLcontext *ctx, struct gl_display_list *list );
void vbo_save_SaveFlushVertices( GLcontext *ctx );
GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode );
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index f69a33d817..4da248e2b8 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -72,7 +72,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/context.h"
#include "main/dlist.h"
#include "main/enums.h"
+#include "main/eval.h"
#include "main/macros.h"
+#include "main/api_noop.h"
#include "main/api_validate.h"
#include "main/api_arrayelt.h"
#include "main/vtxfmt.h"
@@ -241,7 +243,7 @@ static void _save_reset_counters( GLcontext *ctx )
save->buffer = (save->vertex_store->buffer +
save->vertex_store->used);
- assert(save->buffer == save->vbptr);
+ assert(save->buffer == save->buffer_ptr);
if (save->vertex_size)
save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
@@ -289,11 +291,36 @@ static void _save_compile_vertex_list( GLcontext *ctx )
node->vertex_store->refcount++;
node->prim_store->refcount++;
+
+ node->current_size = node->vertex_size - node->attrsz[0];
+ node->current_data = NULL;
+
+ if (node->current_size) {
+ /* If the malloc fails, we just pull the data out of the VBO
+ * later instead.
+ */
+ node->current_data = MALLOC( node->current_size * sizeof(GLfloat) );
+ if (node->current_data) {
+ const char *buffer = (const char *)save->vertex_store->buffer;
+ unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat);
+ unsigned vertex_offset = 0;
+
+ if (node->count)
+ vertex_offset = (node->count-1) * node->vertex_size * sizeof(GLfloat);
+
+ memcpy( node->current_data,
+ buffer + node->buffer_offset + vertex_offset + attr_offset,
+ node->current_size * sizeof(GLfloat) );
+ }
+ }
+
+
+
assert(node->attrsz[VBO_ATTRIB_POS] != 0 ||
node->count == 0);
if (save->dangling_attr_ref)
- ctx->ListState.CurrentList->flags |= MESA_DLIST_DANGLING_REFS;
+ ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
save->vertex_store->used += save->vertex_size * node->count;
save->prim_store->used += node->prim_count;
@@ -343,7 +370,7 @@ static void _save_compile_vertex_list( GLcontext *ctx )
/* Allocate and map new store:
*/
save->vertex_store = alloc_vertex_store( ctx );
- save->vbptr = map_vertex_store( ctx, save->vertex_store );
+ save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
}
if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
@@ -414,9 +441,9 @@ static void _save_wrap_filled_vertex( GLcontext *ctx )
assert(save->max_vert - save->vert_count > save->copied.nr);
for (i = 0 ; i < save->copied.nr ; i++) {
- _mesa_memcpy( save->vbptr, data, save->vertex_size * sizeof(GLfloat));
+ _mesa_memcpy( save->buffer_ptr, data, save->vertex_size * sizeof(GLfloat));
data += save->vertex_size;
- save->vbptr += save->vertex_size;
+ save->buffer_ptr += save->vertex_size;
save->vert_count++;
}
}
@@ -550,7 +577,7 @@ static void _save_upgrade_vertex( GLcontext *ctx,
}
}
- save->vbptr = dest;
+ save->buffer_ptr = dest;
save->vert_count += save->copied.nr;
}
}
@@ -622,9 +649,9 @@ do { \
GLuint i; \
\
for (i = 0; i < save->vertex_size; i++) \
- save->vbptr[i] = save->vertex[i]; \
+ save->buffer_ptr[i] = save->vertex[i]; \
\
- save->vbptr += save->vertex_size; \
+ save->buffer_ptr += save->vertex_size; \
\
if (++save->vert_count >= save->max_vert) \
_save_wrap_filled_vertex( ctx ); \
@@ -642,19 +669,33 @@ do { \
* -- Flush current buffer
* -- Fallback to opcodes for the rest of the begin/end object.
*/
-#define DO_FALLBACK(ctx) \
-do { \
- struct vbo_save_context *save = &vbo_context(ctx)->save; \
- \
- if (save->vert_count || save->prim_count) \
- _save_compile_vertex_list( ctx ); \
- \
- _save_copy_to_current( ctx ); \
- _save_reset_vertex( ctx ); \
- _save_reset_counters( ctx ); \
- _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); \
- ctx->Driver.SaveNeedFlush = 0; \
-} while (0)
+static void DO_FALLBACK( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (save->vert_count || save->prim_count) {
+ GLint i = save->prim_count - 1;
+
+ /* Close off in-progress primitive.
+ */
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+
+ /* Need to replay this display list with loopback,
+ * unfortunately, otherwise this primitive won't be handled
+ * properly:
+ */
+ save->dangling_attr_ref = 1;
+
+ _save_compile_vertex_list( ctx );
+ }
+
+ _save_copy_to_current( ctx );
+ _save_reset_vertex( ctx );
+ _save_reset_counters( ctx );
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+ ctx->Driver.SaveNeedFlush = 0;
+}
static void GLAPIENTRY _save_EvalCoord1f( GLfloat u )
{
@@ -786,6 +827,33 @@ static void GLAPIENTRY _save_DrawRangeElements(GLenum mode,
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
}
+static void GLAPIENTRY _save_DrawElementsBaseVertex(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) count; (void) type; (void) indices; (void)basevertex;
+
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
+}
+
+static void GLAPIENTRY _save_DrawRangeElementsBaseVertex(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLint basevertex)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) start; (void) end; (void) count; (void) type;
+ (void) indices; (void)basevertex;
+
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
+}
+
static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count)
{
GET_CURRENT_CONTEXT(ctx);
@@ -867,12 +935,12 @@ static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum
GET_CURRENT_CONTEXT(ctx);
GLint i;
- if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
return;
_ae_map_vbos( ctx );
- if (ctx->Array.ElementArrayBufferObj->Name)
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
indices = ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices);
vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
@@ -908,7 +976,7 @@ static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,
GET_CURRENT_CONTEXT(ctx);
if (_mesa_validate_DrawRangeElements( ctx, mode,
start, end,
- count, type, indices ))
+ count, type, indices, 0 ))
_save_OBE_DrawElements( mode, count, type, indices );
}
@@ -921,7 +989,8 @@ static void _save_vtxfmt_init( GLcontext *ctx )
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLvertexformat *vfmt = &save->vtxfmt;
- vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
+ _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
+
vfmt->Begin = _save_Begin;
vfmt->Color3f = _save_Color3f;
vfmt->Color3fv = _save_Color3fv;
@@ -980,26 +1049,23 @@ static void _save_vtxfmt_init( GLcontext *ctx )
/* This will all require us to fallback to saving the list as opcodes:
*/
- vfmt->CallList = _save_CallList; /* inside begin/end */
- vfmt->CallLists = _save_CallLists; /* inside begin/end */
- vfmt->EvalCoord1f = _save_EvalCoord1f;
- vfmt->EvalCoord1fv = _save_EvalCoord1fv;
- vfmt->EvalCoord2f = _save_EvalCoord2f;
- vfmt->EvalCoord2fv = _save_EvalCoord2fv;
- vfmt->EvalPoint1 = _save_EvalPoint1;
- vfmt->EvalPoint2 = _save_EvalPoint2;
+ _MESA_INIT_DLIST_VTXFMT(vfmt, _save_); /* inside begin/end */
+
+ _MESA_INIT_EVAL_VTXFMT(vfmt, _save_);
/* These are all errors as we at least know we are in some sort of
* begin/end pair:
*/
- vfmt->EvalMesh1 = _save_EvalMesh1;
- vfmt->EvalMesh2 = _save_EvalMesh2;
vfmt->Begin = _save_Begin;
vfmt->Rectf = _save_Rectf;
vfmt->DrawArrays = _save_DrawArrays;
vfmt->DrawElements = _save_DrawElements;
vfmt->DrawRangeElements = _save_DrawRangeElements;
-
+ vfmt->DrawElementsBaseVertex = _save_DrawElementsBaseVertex;
+ vfmt->DrawRangeElementsBaseVertex = _save_DrawRangeElementsBaseVertex;
+ /* Loops back into vfmt->DrawElements */
+ vfmt->MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ vfmt->MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
}
@@ -1035,7 +1101,7 @@ void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode )
if (!save->vertex_store)
save->vertex_store = alloc_vertex_store( ctx );
- save->vbptr = map_vertex_store( ctx, save->vertex_store );
+ save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
_save_reset_vertex( ctx );
_save_reset_counters( ctx );
@@ -1076,10 +1142,10 @@ void vbo_save_EndList( GLcontext *ctx )
assert(save->vertex_size == 0);
}
-void vbo_save_BeginCallList( GLcontext *ctx, struct mesa_display_list *dlist )
+void vbo_save_BeginCallList( GLcontext *ctx, struct gl_display_list *dlist )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
- save->replay_flags |= dlist->flags;
+ save->replay_flags |= dlist->Flags;
}
void vbo_save_EndCallList( GLcontext *ctx )
@@ -1105,6 +1171,11 @@ static void vbo_destroy_vertex_list( GLcontext *ctx, void *data )
if ( --node->prim_store->refcount == 0 )
FREE( node->prim_store );
+
+ if (node->current_data) {
+ FREE(node->current_data);
+ node->current_data = NULL;
+ }
}
@@ -1114,16 +1185,16 @@ static void vbo_print_vertex_list( GLcontext *ctx, void *data )
GLuint i;
(void) ctx;
- _mesa_debug(NULL, "VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
- node->count,
- node->prim_count,
- node->vertex_size);
+ _mesa_printf("VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
+ node->count,
+ node->prim_count,
+ node->vertex_size);
for (i = 0 ; i < node->prim_count ; i++) {
struct _mesa_prim *prim = &node->prim[i];
_mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n",
i,
- _mesa_lookup_enum_by_nr(prim->mode),
+ _mesa_lookup_prim_by_nr(prim->mode),
prim->weak ? " (weak)" : "",
prim->start,
prim->start + prim->count,
@@ -1184,6 +1255,9 @@ void vbo_save_api_init( struct vbo_save_context *save )
ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays;
ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements;
ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements;
+ /* loops back into _save_OBE_DrawElements */
+ ctx->ListState.ListVtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ ctx->ListState.ListVtxfmt.MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
_mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
}
diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
index ed82f09958..d834fa1f2e 100644
--- a/src/mesa/vbo/vbo_save_draw.c
+++ b/src/mesa/vbo/vbo_save_draw.c
@@ -46,36 +46,55 @@ static void _playback_copy_to_current( GLcontext *ctx,
const struct vbo_save_vertex_list *node )
{
struct vbo_context *vbo = vbo_context(ctx);
- GLfloat vertex[VBO_ATTRIB_MAX * 4], *data = vertex;
+ GLfloat vertex[VBO_ATTRIB_MAX * 4];
+ GLfloat *data;
GLuint i, offset;
- if (node->count)
- offset = (node->buffer_offset +
- (node->count-1) * node->vertex_size * sizeof(GLfloat));
- else
- offset = node->buffer_offset;
+ if (node->current_size == 0)
+ return;
- ctx->Driver.GetBufferSubData( ctx, 0, offset,
- node->vertex_size * sizeof(GLfloat),
- data, node->vertex_store->bufferobj );
+ if (node->current_data) {
+ data = node->current_data;
+ }
+ else {
+ data = vertex;
+
+ if (node->count)
+ offset = (node->buffer_offset +
+ (node->count-1) * node->vertex_size * sizeof(GLfloat));
+ else
+ offset = node->buffer_offset;
- data += node->attrsz[0]; /* skip vertex position */
+ ctx->Driver.GetBufferSubData( ctx, 0, offset,
+ node->vertex_size * sizeof(GLfloat),
+ data, node->vertex_store->bufferobj );
+
+ data += node->attrsz[0]; /* skip vertex position */
+ }
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
if (node->attrsz[i]) {
GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ GLfloat tmp[4];
- COPY_CLEAN_4V(current,
- node->attrsz[i],
- data);
+ COPY_CLEAN_4V(tmp,
+ node->attrsz[i],
+ data);
+
+ if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0)
+ {
+ memcpy(current, tmp, 4 * sizeof(GLfloat));
- vbo->currval[i].Size = node->attrsz[i];
+ vbo->currval[i].Size = node->attrsz[i];
- data += node->attrsz[i];
+ if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
+ i <= VBO_ATTRIB_LAST_MATERIAL)
+ ctx->NewState |= _NEW_LIGHT;
+
+ ctx->NewState |= _NEW_CURRENT_ATTRIB;
+ }
- if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
- i <= VBO_ATTRIB_LAST_MATERIAL)
- ctx->NewState |= _NEW_LIGHT;
+ data += node->attrsz[i];
}
}
@@ -107,9 +126,13 @@ static void vbo_bind_vertex_list( GLcontext *ctx,
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_save_context *save = &vbo->save;
struct gl_client_array *arrays = save->arrays;
- GLuint data = node->buffer_offset;
+ GLuint buffer_offset = node->buffer_offset;
const GLuint *map;
GLuint attr;
+ GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */
+ GLbitfield varying_inputs = 0x0;
+
+ memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
/* Install the default (ie Current) attributes first, then overlay
* all active ones.
@@ -135,21 +158,35 @@ static void vbo_bind_vertex_list( GLcontext *ctx,
save->inputs[attr + 16] = &vbo->generic_currval[attr];
}
map = vbo->map_vp_arb;
+
+ /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
+ * In that case we effectively need to route the data from
+ * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
+ */
+ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
+ (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
+ save->inputs[16] = save->inputs[0];
+ node_attrsz[16] = node_attrsz[0];
+ node_attrsz[0] = 0;
+ }
break;
+ default:
+ assert(0);
}
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
GLuint src = map[attr];
- if (node->attrsz[src]) {
+ if (node_attrsz[src]) {
/* override the default array set above */
save->inputs[attr] = &arrays[attr];
- arrays[attr].Ptr = (const GLubyte *) data;
+ arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset;
arrays[attr].Size = node->attrsz[src];
arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat);
arrays[attr].Stride = node->vertex_size * sizeof(GLfloat);
arrays[attr].Type = GL_FLOAT;
+ arrays[attr].Format = GL_RGBA;
arrays[attr].Enabled = 1;
_mesa_reference_buffer_object(ctx,
&arrays[attr].BufferObj,
@@ -158,9 +195,12 @@ static void vbo_bind_vertex_list( GLcontext *ctx,
assert(arrays[attr].BufferObj->Name);
- data += node->attrsz[src] * sizeof(GLfloat);
+ buffer_offset += node->attrsz[src] * sizeof(GLfloat);
+ varying_inputs |= 1<<attr;
}
}
+
+ _mesa_set_varying_vp_inputs( ctx, varying_inputs );
}
static void vbo_save_loopback_vertex_list( GLcontext *ctx,
@@ -229,11 +269,17 @@ void vbo_save_playback_vertex_list( GLcontext *ctx, void *data )
vbo_bind_vertex_list( ctx, node );
+ /* Again...
+ */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
vbo_context(ctx)->draw_prims( ctx,
save->inputs,
node->prim,
node->prim_count,
NULL,
+ GL_TRUE,
0, /* Node is a VBO, so this is ok */
node->count - 1);
}
diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c
index 92ca4ea95d..b7a74e4535 100644
--- a/src/mesa/vbo/vbo_save_loopback.c
+++ b/src/mesa/vbo/vbo_save_loopback.c
@@ -97,7 +97,7 @@ static void loopback_prim( GLcontext *ctx,
if (0)
_mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n",
- _mesa_lookup_enum_by_nr(prim->mode),
+ _mesa_lookup_prim_by_nr(prim->mode),
prim->begin ? "begin" : "..",
prim->end ? "end" : "..",
start,
diff --git a/src/mesa/vbo/vbo_split.c b/src/mesa/vbo/vbo_split.c
index 58e879628d..c445acca7d 100644
--- a/src/mesa/vbo/vbo_split.c
+++ b/src/mesa/vbo/vbo_split.c
@@ -50,6 +50,7 @@
#include "main/glheader.h"
#include "main/imports.h"
#include "main/mtypes.h"
+#include "main/macros.h"
#include "vbo_split.h"
#include "vbo.h"
@@ -107,7 +108,12 @@ void vbo_split_prims( GLcontext *ctx,
vbo_draw_func draw,
const struct split_limits *limits )
{
-
+ GLuint max_basevertex = prim->basevertex;
+ GLuint i;
+
+ for (i = 1; i < nr_prims; i++)
+ max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
+
if (ib) {
if (limits->max_indices == 0) {
/* Could traverse the indices, re-emitting vertices in turn.
diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c
index 685cc0fdf6..c45190b9dd 100644
--- a/src/mesa/vbo/vbo_split_copy.c
+++ b/src/mesa/vbo/vbo_split_copy.c
@@ -30,7 +30,9 @@
*/
#include "main/glheader.h"
+#include "main/bufferobj.h"
#include "main/imports.h"
+#include "main/image.h"
#include "main/macros.h"
#include "main/enums.h"
#include "main/mtypes.h"
@@ -41,7 +43,8 @@
#define ELT_TABLE_SIZE 16
-/* Used for vertex-level splitting of indexed buffers. Note that
+/**
+ * Used for vertex-level splitting of indexed buffers. Note that
* non-indexed primitives may be converted to indexed in some cases
* (eg loops, fans) in order to use this splitting path.
*/
@@ -73,23 +76,21 @@ struct copy_context {
GLuint *translated_elt_buf;
const GLuint *srcelt;
- /* A baby hash table to avoid re-emitting (some) duplicate
+ /** A baby hash table to avoid re-emitting (some) duplicate
* vertices when splitting indexed primitives.
*/
struct {
GLuint in;
GLuint out;
} vert_cache[ELT_TABLE_SIZE];
-
GLuint vertex_size;
GLubyte *dstbuf;
- GLubyte *dstptr; /* dstptr == dstbuf + dstelt_max * vertsize */
- GLuint dstbuf_size; /* in vertices */
- GLuint dstbuf_nr; /* count of emitted vertices, also the
- * largest value in dstelt. Our
- * MaxIndex.
- */
+ GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */
+ GLuint dstbuf_size; /**< in vertices */
+ GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value
+ * in dstelt. Our MaxIndex.
+ */
GLuint *dstelt;
GLuint dstelt_nr;
@@ -102,32 +103,19 @@ struct copy_context {
};
-static GLuint type_size( GLenum type )
-{
- switch(type) {
- case GL_BYTE: return sizeof(GLbyte);
- case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
- case GL_SHORT: return sizeof(GLshort);
- case GL_UNSIGNED_SHORT: return sizeof(GLushort);
- case GL_INT: return sizeof(GLint);
- case GL_UNSIGNED_INT: return sizeof(GLuint);
- case GL_FLOAT: return sizeof(GLfloat);
- case GL_DOUBLE: return sizeof(GLdouble);
- default: return 0;
- }
-}
-
static GLuint attr_size( const struct gl_client_array *array )
{
- return array->Size * type_size(array->Type);
+ return array->Size * _mesa_sizeof_type(array->Type);
}
-/* Starts returning true slightly before the buffer fills, to ensure
+/**
+ * Starts returning true slightly before the buffer fills, to ensure
* that there is sufficient room for any remaining vertices to finish
* off the prim:
*/
-static GLboolean check_flush( struct copy_context *copy )
+static GLboolean
+check_flush( struct copy_context *copy )
{
GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
@@ -145,7 +133,44 @@ static GLboolean check_flush( struct copy_context *copy )
return GL_FALSE;
}
-static void flush( struct copy_context *copy )
+
+/**
+ * Dump the parameters/info for a vbo->draw() call.
+ */
+static void
+dump_draw_info(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index)
+{
+ GLuint i, j;
+
+ _mesa_printf("VBO Draw:\n");
+ for (i = 0; i < nr_prims; i++) {
+ _mesa_printf("Prim %u of %u\n", i, nr_prims);
+ _mesa_printf(" Prim mode 0x%x\n", prims[i].mode);
+ _mesa_printf(" IB: %p\n", (void*) ib);
+ for (j = 0; j < VERT_ATTRIB_MAX; j++) {
+ _mesa_printf(" array %d at %p:\n", j, (void*) arrays[j]);
+ _mesa_printf(" enabled %d, ptr %p, size %d, type 0x%x, stride %d\n",
+ arrays[j]->Enabled, arrays[j]->Ptr,
+ arrays[j]->Size, arrays[j]->Type, arrays[j]->StrideB);
+ if (0) {
+ GLint k = prims[i].start + prims[i].count - 1;
+ GLfloat *last = (GLfloat *) (arrays[j]->Ptr + arrays[j]->Stride * k);
+ _mesa_printf(" last: %f %f %f\n",
+ last[0], last[1], last[2]);
+ }
+ }
+ }
+}
+
+
+static void
+flush( struct copy_context *copy )
{
GLuint i;
@@ -153,11 +178,24 @@ static void flush( struct copy_context *copy )
*/
copy->dstib.count = copy->dstelt_nr;
+#if 0
+ dump_draw_info(copy->ctx,
+ copy->dstarray_ptr,
+ copy->dstprim,
+ copy->dstprim_nr,
+ &copy->dstib,
+ 0,
+ copy->dstbuf_nr);
+#else
+ (void) dump_draw_info;
+#endif
+
copy->draw( copy->ctx,
copy->dstarray_ptr,
copy->dstprim,
copy->dstprim_nr,
&copy->dstib,
+ GL_TRUE,
0,
copy->dstbuf_nr );
@@ -175,22 +213,27 @@ static void flush( struct copy_context *copy )
}
-
-static void begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
+/**
+ * Called at begin of each primitive during replay.
+ */
+static void
+begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
{
struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
-/* _mesa_printf("begin %s (%d)\n", _mesa_lookup_enum_by_nr(mode), begin_flag); */
+/* _mesa_printf("begin %s (%d)\n", _mesa_lookup_prim_by_nr(mode), begin_flag); */
prim->mode = mode;
prim->begin = begin_flag;
}
-/* Use a hashtable to attempt to identify recently-emitted vertices
+/**
+ * Use a hashtable to attempt to identify recently-emitted vertices
* and avoid re-emitting them.
*/
-static GLuint elt(struct copy_context *copy, GLuint elt_idx)
+static GLuint
+elt(struct copy_context *copy, GLuint elt_idx)
{
GLuint elt = copy->srcelt[elt_idx];
GLuint slot = elt & (ELT_TABLE_SIZE-1);
@@ -213,6 +256,17 @@ static GLuint elt(struct copy_context *copy, GLuint elt_idx)
memcpy(csr, srcptr, copy->varying[i].size);
csr += copy->varying[i].size;
+#ifdef NAN_CHECK
+ if (srcarray->Type == GL_FLOAT) {
+ GLuint k;
+ GLfloat *f = (GLfloat *) srcptr;
+ for (k = 0; k < srcarray->Size; k++) {
+ assert(!IS_INF_OR_NAN(f[k]));
+ assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
+ }
+ }
+#endif
+
if (0)
{
const GLuint *f = (const GLuint *)srcptr;
@@ -222,7 +276,6 @@ static GLuint elt(struct copy_context *copy, GLuint elt_idx)
_mesa_printf("%x ", f[j]);
_mesa_printf("\n");
}
-
}
copy->vert_cache[slot].in = elt;
@@ -230,9 +283,8 @@ static GLuint elt(struct copy_context *copy, GLuint elt_idx)
copy->dstptr += copy->vertex_size;
assert(csr == copy->dstptr);
- assert(copy->dstptr == (copy->dstbuf +
- copy->dstbuf_nr *
- copy->vertex_size));
+ assert(copy->dstptr == (copy->dstbuf +
+ copy->dstbuf_nr * copy->vertex_size));
}
/* else */
/* _mesa_printf(" --> reuse vertex\n"); */
@@ -242,7 +294,12 @@ static GLuint elt(struct copy_context *copy, GLuint elt_idx)
return check_flush(copy);
}
-static void end( struct copy_context *copy, GLboolean end_flag )
+
+/**
+ * Called at end of each primitive during replay.
+ */
+static void
+end( struct copy_context *copy, GLboolean end_flag )
{
struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
@@ -257,8 +314,8 @@ static void end( struct copy_context *copy, GLboolean end_flag )
}
-
-static void replay_elts( struct copy_context *copy )
+static void
+replay_elts( struct copy_context *copy )
{
GLuint i, j, k;
GLboolean split;
@@ -362,7 +419,8 @@ static void replay_elts( struct copy_context *copy )
}
-static void replay_init( struct copy_context *copy )
+static void
+replay_init( struct copy_context *copy )
{
GLcontext *ctx = copy->ctx;
GLuint i;
@@ -387,11 +445,8 @@ static void replay_init( struct copy_context *copy )
copy->varying[j].size = attr_size(copy->array[i]);
copy->vertex_size += attr_size(copy->array[i]);
- if (vbo->Name && !vbo->Pointer)
- ctx->Driver.MapBuffer(ctx,
- GL_ARRAY_BUFFER_ARB,
- GL_WRITE_ONLY, /* XXX */
- vbo);
+ if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo))
+ ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY, vbo);
copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer,
copy->array[i]->Ptr);
@@ -404,13 +459,13 @@ static void replay_init( struct copy_context *copy )
* caller convert non-indexed prims to indexed. Could alternately
* do it internally.
*/
- if (copy->ib->obj->Name && !copy->ib->obj->Pointer)
- ctx->Driver.MapBuffer(ctx,
- GL_ARRAY_BUFFER_ARB, /* XXX */
- GL_WRITE_ONLY, /* XXX */
+ if (_mesa_is_bufferobj(copy->ib->obj) &&
+ !_mesa_bufferobj_mapped(copy->ib->obj))
+ ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY,
copy->ib->obj);
- srcptr = (const GLubyte *)ADD_POINTERS(copy->ib->obj->Pointer, copy->ib->ptr);
+ srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer,
+ copy->ib->ptr);
switch (copy->ib->type) {
case GL_UNSIGNED_BYTE:
@@ -434,7 +489,6 @@ static void replay_init( struct copy_context *copy )
copy->srcelt = (const GLuint *)srcptr;
break;
}
-
/* Figure out the maximum allowed vertex buffer size:
*/
@@ -449,8 +503,7 @@ static void replay_init( struct copy_context *copy )
*
* XXX: This should be a VBO!
*/
- copy->dstbuf = _mesa_malloc(copy->dstbuf_size *
- copy->vertex_size);
+ copy->dstbuf = _mesa_malloc(copy->dstbuf_size * copy->vertex_size);
copy->dstptr = copy->dstbuf;
/* Setup new vertex arrays to point into the output buffer:
@@ -461,12 +514,13 @@ static void replay_init( struct copy_context *copy )
dst->Size = src->Size;
dst->Type = src->Type;
+ dst->Format = GL_RGBA;
dst->Stride = copy->vertex_size;
dst->StrideB = copy->vertex_size;
dst->Ptr = copy->dstbuf + offset;
dst->Enabled = GL_TRUE;
dst->Normalized = src->Normalized;
- dst->BufferObj = ctx->Array.NullBufferObj;
+ dst->BufferObj = ctx->Shared->NullBufferObj;
dst->_MaxElement = copy->dstbuf_size; /* may be less! */
offset += copy->varying[i].size;
@@ -486,12 +540,16 @@ static void replay_init( struct copy_context *copy )
*/
copy->dstib.count = 0; /* duplicates dstelt_nr */
copy->dstib.type = GL_UNSIGNED_INT;
- copy->dstib.obj = ctx->Array.NullBufferObj;
+ copy->dstib.obj = ctx->Shared->NullBufferObj;
copy->dstib.ptr = copy->dstelt;
}
-static void replay_finish( struct copy_context *copy )
+/**
+ * Free up everything allocated during split/replay.
+ */
+static void
+replay_finish( struct copy_context *copy )
{
GLcontext *ctx = copy->ctx;
GLuint i;
@@ -501,25 +559,27 @@ static void replay_finish( struct copy_context *copy )
_mesa_free(copy->translated_elt_buf);
_mesa_free(copy->dstbuf);
_mesa_free(copy->dstelt);
-
+
/* Unmap VBO's
*/
for (i = 0; i < copy->nr_varying; i++) {
struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj;
-
- if (vbo->Name && vbo->Pointer)
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, vbo);
+ if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo))
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, vbo);
}
/* Unmap index buffer:
*/
- if (copy->ib->obj->Name && copy->ib->obj->Pointer) {
- ctx->Driver.UnmapBuffer(ctx,
- GL_ARRAY_BUFFER_ARB, /* XXX */
- copy->ib->obj);
+ if (_mesa_is_bufferobj(copy->ib->obj) &&
+ _mesa_bufferobj_mapped(copy->ib->obj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, copy->ib->obj);
}
}
+
+/**
+ * Split VBO into smaller pieces, draw the pieces.
+ */
void vbo_split_copy( GLcontext *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
@@ -529,30 +589,40 @@ void vbo_split_copy( GLcontext *ctx,
const struct split_limits *limits )
{
struct copy_context copy;
- GLuint i;
+ GLuint i, this_nr_prims;
+
+ for (i = 0; i < nr_prims;) {
+ /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
+ * will rebase the elements to the basevertex, and we'll only
+ * emit strings of prims with the same basevertex in one draw call.
+ */
+ for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
+ this_nr_prims++) {
+ if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
+ break;
+ }
- memset(&copy, 0, sizeof(copy));
+ memset(&copy, 0, sizeof(copy));
- /* Require indexed primitives:
- */
- assert(ib);
-
- copy.ctx = ctx;
- copy.array = arrays;
- copy.prim = prim;
- copy.nr_prims = nr_prims;
- copy.ib = ib;
- copy.draw = draw;
- copy.limits = limits;
+ /* Require indexed primitives:
+ */
+ assert(ib);
+ copy.ctx = ctx;
+ copy.array = arrays;
+ copy.prim = &prim[i];
+ copy.nr_prims = this_nr_prims;
+ copy.ib = ib;
+ copy.draw = draw;
+ copy.limits = limits;
- /* Clear the vertex cache:
- */
- for (i = 0; i < ELT_TABLE_SIZE; i++)
- copy.vert_cache[i].in = ~0;
+ /* Clear the vertex cache:
+ */
+ for (i = 0; i < ELT_TABLE_SIZE; i++)
+ copy.vert_cache[i].in = ~0;
-
- replay_init(&copy);
- replay_elts(&copy);
- replay_finish(&copy);
+ replay_init(&copy);
+ replay_elts(&copy);
+ replay_finish(&copy);
+ }
}
diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c
index fbc856e93b..da84eaa6ea 100644
--- a/src/mesa/vbo/vbo_split_inplace.c
+++ b/src/mesa/vbo/vbo_split_inplace.c
@@ -59,39 +59,23 @@ struct split_context {
static void flush_vertex( struct split_context *split )
{
GLuint min_index, max_index;
+ GLuint i;
if (!split->dstprim_nr)
return;
- if (split->ib) {
- /* This should basically be multipass rendering over the same
- * unchanging set of VBO's. Would like the driver not to
- * re-upload the data, or swtnl not to re-transform the
- * vertices.
- */
- assert(split->max_index - split->min_index < split->limits->max_verts);
- min_index = split->min_index;
- max_index = split->max_index;
- }
- else {
- /* Non-indexed rendering. Cannot assume that the primitives are
- * ordered by increasing vertex, because of entrypoints like
- * MultiDrawArrays.
- */
- GLuint i;
- min_index = split->dstprim[0].start;
- max_index = min_index + split->dstprim[0].count - 1;
+ min_index = split->dstprim[0].start;
+ max_index = min_index + split->dstprim[0].count - 1;
- for (i = 1; i < split->dstprim_nr; i++) {
- GLuint tmp_min = split->dstprim[i].start;
- GLuint tmp_max = tmp_min + split->dstprim[i].count - 1;
+ for (i = 1; i < split->dstprim_nr; i++) {
+ GLuint tmp_min = split->dstprim[i].start;
+ GLuint tmp_max = tmp_min + split->dstprim[i].count - 1;
- if (tmp_min < min_index)
- min_index = tmp_min;
+ if (tmp_min < min_index)
+ min_index = tmp_min;
- if (tmp_max > max_index)
- max_index = tmp_max;
- }
+ if (tmp_max > max_index)
+ max_index = tmp_max;
}
assert(max_index >= min_index);
@@ -101,6 +85,7 @@ static void flush_vertex( struct split_context *split )
split->dstprim,
split->dstprim_nr,
NULL,
+ GL_TRUE,
min_index,
max_index);
@@ -221,7 +206,7 @@ static void split_prims( struct split_context *split)
ib.count = count;
ib.type = GL_UNSIGNED_INT;
- ib.obj = split->ctx->Array.NullBufferObj;
+ ib.obj = split->ctx->Shared->NullBufferObj;
ib.ptr = elts;
tmpprim = *prim;
diff --git a/src/mesa/vf/vf.c b/src/mesa/vf/vf.c
new file mode 100644
index 0000000000..82f3d2b641
--- /dev/null
+++ b/src/mesa/vf/vf.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * TUNGSTEN GRAPHICS 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:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+
+#include "vf.h"
+
+#define DBG 0
+
+
+
+static GLboolean match_fastpath( struct vertex_fetch *vf,
+ const struct vf_fastpath *fp)
+{
+ GLuint j;
+
+ if (vf->attr_count != fp->attr_count)
+ return GL_FALSE;
+
+ for (j = 0; j < vf->attr_count; j++)
+ if (vf->attr[j].format != fp->attr[j].format ||
+ vf->attr[j].inputsize != fp->attr[j].size ||
+ vf->attr[j].vertoffset != fp->attr[j].offset)
+ return GL_FALSE;
+
+ if (fp->match_strides) {
+ if (vf->vertex_stride != fp->vertex_stride)
+ return GL_FALSE;
+
+ for (j = 0; j < vf->attr_count; j++)
+ if (vf->attr[j].inputstride != fp->attr[j].stride)
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean search_fastpath_emit( struct vertex_fetch *vf )
+{
+ struct vf_fastpath *fp = vf->fastpath;
+
+ for ( ; fp ; fp = fp->next) {
+ if (match_fastpath(vf, fp)) {
+ vf->emit = fp->func;
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+void vf_register_fastpath( struct vertex_fetch *vf,
+ GLboolean match_strides )
+{
+ struct vf_fastpath *fastpath = CALLOC_STRUCT(vf_fastpath);
+ GLuint i;
+
+ fastpath->vertex_stride = vf->vertex_stride;
+ fastpath->attr_count = vf->attr_count;
+ fastpath->match_strides = match_strides;
+ fastpath->func = vf->emit;
+ fastpath->attr = (struct vf_attr_type *)
+ _mesa_malloc(vf->attr_count * sizeof(fastpath->attr[0]));
+
+ for (i = 0; i < vf->attr_count; i++) {
+ fastpath->attr[i].format = vf->attr[i].format;
+ fastpath->attr[i].stride = vf->attr[i].inputstride;
+ fastpath->attr[i].size = vf->attr[i].inputsize;
+ fastpath->attr[i].offset = vf->attr[i].vertoffset;
+ }
+
+ fastpath->next = vf->fastpath;
+ vf->fastpath = fastpath;
+}
+
+
+
+
+/***********************************************************************
+ * Build codegen functions or return generic ones:
+ */
+static void choose_emit_func( struct vertex_fetch *vf,
+ GLuint count,
+ GLubyte *dest)
+{
+ vf->emit = NULL;
+
+ /* Does this match an existing (hardwired, codegen or known-bad)
+ * fastpath?
+ */
+ if (search_fastpath_emit(vf)) {
+ /* Use this result. If it is null, then it is already known
+ * that the current state will fail for codegen and there is no
+ * point trying again.
+ */
+ }
+ else if (vf->codegen_emit) {
+ vf->codegen_emit( vf );
+ }
+
+ if (!vf->emit) {
+ vf_generate_hardwired_emit(vf);
+ }
+
+ /* Otherwise use the generic version:
+ */
+ if (!vf->emit)
+ vf->emit = vf_generic_emit;
+
+ vf->emit( vf, count, dest );
+}
+
+
+
+
+
+/***********************************************************************
+ * Public entrypoints, mostly dispatch to the above:
+ */
+
+
+
+GLuint vf_set_vertex_attributes( struct vertex_fetch *vf,
+ const struct vf_attr_map *map,
+ GLuint nr,
+ GLuint vertex_stride )
+{
+ GLuint offset = 0;
+ GLuint i, j;
+
+ assert(nr < VF_ATTRIB_MAX);
+
+ memset(vf->lookup, 0, sizeof(vf->lookup));
+
+ for (j = 0, i = 0; i < nr; i++) {
+ const GLuint format = map[i].format;
+ if (format == EMIT_PAD) {
+ if (DBG)
+ _mesa_printf("%d: pad %d, offset %d\n", i,
+ map[i].offset, offset);
+
+ offset += map[i].offset;
+
+ }
+ else {
+ assert(vf->lookup[map[i].attrib] == 0);
+ vf->lookup[map[i].attrib] = &vf->attr[j];
+
+ vf->attr[j].attrib = map[i].attrib;
+ vf->attr[j].format = format;
+ vf->attr[j].insert = vf_format_info[format].insert;
+ vf->attr[j].extract = vf_format_info[format].extract;
+ vf->attr[j].vertattrsize = vf_format_info[format].attrsize;
+ vf->attr[j].vertoffset = offset;
+
+ if (DBG)
+ _mesa_printf("%d: %s, offset %d\n", i,
+ vf_format_info[format].name,
+ vf->attr[j].vertoffset);
+
+ offset += vf_format_info[format].attrsize;
+ j++;
+ }
+ }
+
+ vf->attr_count = j;
+ vf->vertex_stride = vertex_stride ? vertex_stride : offset;
+ vf->emit = choose_emit_func;
+
+ assert(vf->vertex_stride >= offset);
+ return vf->vertex_stride;
+}
+
+
+
+void vf_set_vp_matrix( struct vertex_fetch *vf,
+ const GLfloat *viewport )
+{
+ assert(vf->allow_viewport_emits);
+
+ /* scale */
+ vf->vp[0] = viewport[MAT_SX];
+ vf->vp[1] = viewport[MAT_SY];
+ vf->vp[2] = viewport[MAT_SZ];
+ vf->vp[3] = 1.0;
+
+ /* translate */
+ vf->vp[4] = viewport[MAT_TX];
+ vf->vp[5] = viewport[MAT_TY];
+ vf->vp[6] = viewport[MAT_TZ];
+ vf->vp[7] = 0.0;
+}
+
+void vf_set_vp_scale_translate( struct vertex_fetch *vf,
+ const GLfloat *scale,
+ const GLfloat *translate )
+{
+ assert(vf->allow_viewport_emits);
+
+ vf->vp[0] = scale[0];
+ vf->vp[1] = scale[1];
+ vf->vp[2] = scale[2];
+ vf->vp[3] = scale[3];
+
+ vf->vp[4] = translate[0];
+ vf->vp[5] = translate[1];
+ vf->vp[6] = translate[2];
+ vf->vp[7] = translate[3];
+}
+
+
+/* Set attribute pointers, adjusted for start position:
+ */
+void vf_set_sources( struct vertex_fetch *vf,
+ GLvector4f * const sources[],
+ GLuint start )
+{
+ struct vf_attr *a = vf->attr;
+ GLuint j;
+
+ for (j = 0; j < vf->attr_count; j++) {
+ const GLvector4f *vptr = sources[a[j].attrib];
+
+ if ((a[j].inputstride != vptr->stride) ||
+ (a[j].inputsize != vptr->size))
+ vf->emit = choose_emit_func;
+
+ a[j].inputstride = vptr->stride;
+ a[j].inputsize = vptr->size;
+ a[j].do_insert = a[j].insert[vptr->size - 1];
+ a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
+ }
+}
+
+
+
+/* Emit count VB vertices to dest.
+ */
+void vf_emit_vertices( struct vertex_fetch *vf,
+ GLuint count,
+ void *dest )
+{
+ vf->emit( vf, count, (GLubyte*) dest );
+}
+
+
+/* Extract a named attribute from a hardware vertex. Will have to
+ * reverse any viewport transformation, swizzling or other conversions
+ * which may have been applied.
+ *
+ * This is mainly required for on-the-fly vertex translations to
+ * swrast format.
+ */
+void vf_get_attr( struct vertex_fetch *vf,
+ const void *vertex,
+ GLenum attr,
+ const GLfloat *dflt,
+ GLfloat *dest )
+{
+ const struct vf_attr *a = vf->attr;
+ const GLuint attr_count = vf->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ if (a[j].attrib == attr) {
+ a[j].extract( &a[j], dest, (GLubyte *)vertex + a[j].vertoffset );
+ return;
+ }
+ }
+
+ /* Else return the value from ctx->Current.
+ */
+ _mesa_memcpy( dest, dflt, 4*sizeof(GLfloat));
+}
+
+
+
+
+struct vertex_fetch *vf_create( GLboolean allow_viewport_emits )
+{
+ struct vertex_fetch *vf = CALLOC_STRUCT(vertex_fetch);
+ GLuint i;
+
+ for (i = 0; i < VF_ATTRIB_MAX; i++)
+ vf->attr[i].vf = vf;
+
+ vf->allow_viewport_emits = allow_viewport_emits;
+
+ switch(CHAN_TYPE) {
+ case GL_UNSIGNED_BYTE:
+ vf->chan_scale[0] = 255.0;
+ vf->chan_scale[1] = 255.0;
+ vf->chan_scale[2] = 255.0;
+ vf->chan_scale[3] = 255.0;
+ break;
+ case GL_UNSIGNED_SHORT:
+ vf->chan_scale[0] = 65535.0;
+ vf->chan_scale[1] = 65535.0;
+ vf->chan_scale[2] = 65535.0;
+ vf->chan_scale[3] = 65535.0;
+ break;
+ default:
+ vf->chan_scale[0] = 1.0;
+ vf->chan_scale[1] = 1.0;
+ vf->chan_scale[2] = 1.0;
+ vf->chan_scale[3] = 1.0;
+ break;
+ }
+
+ vf->identity[0] = 0.0;
+ vf->identity[1] = 0.0;
+ vf->identity[2] = 0.0;
+ vf->identity[3] = 1.0;
+
+ vf->codegen_emit = NULL;
+
+#ifdef USE_SSE_ASM
+ if (!_mesa_getenv("MESA_NO_CODEGEN"))
+ vf->codegen_emit = vf_generate_sse_emit;
+#endif
+
+ return vf;
+}
+
+
+void vf_destroy( struct vertex_fetch *vf )
+{
+ struct vf_fastpath *fp, *tmp;
+
+ for (fp = vf->fastpath ; fp ; fp = tmp) {
+ tmp = fp->next;
+ FREE(fp->attr);
+
+ /* KW: At the moment, fp->func is constrained to be allocated by
+ * _mesa_exec_alloc(), as the hardwired fastpaths in
+ * t_vertex_generic.c are handled specially. It would be nice
+ * to unify them, but this probably won't change until this
+ * module gets another overhaul.
+ */
+ _mesa_exec_free((void *) fp->func);
+ FREE(fp);
+ }
+
+ vf->fastpath = NULL;
+ FREE(vf);
+}
diff --git a/src/mesa/vf/vf.h b/src/mesa/vf/vf.h
new file mode 100644
index 0000000000..83d7547619
--- /dev/null
+++ b/src/mesa/vf/vf.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * TUNGSTEN GRAPHICS 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:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#ifndef VF_VERTEX_H
+#define VF_VERTEX_H
+
+#include "main/mtypes.h"
+#include "math/m_vector.h"
+
+enum {
+ VF_ATTRIB_POS = 0,
+ VF_ATTRIB_WEIGHT = 1,
+ VF_ATTRIB_NORMAL = 2,
+ VF_ATTRIB_COLOR0 = 3,
+ VF_ATTRIB_COLOR1 = 4,
+ VF_ATTRIB_FOG = 5,
+ VF_ATTRIB_COLOR_INDEX = 6,
+ VF_ATTRIB_EDGEFLAG = 7,
+ VF_ATTRIB_TEX0 = 8,
+ VF_ATTRIB_TEX1 = 9,
+ VF_ATTRIB_TEX2 = 10,
+ VF_ATTRIB_TEX3 = 11,
+ VF_ATTRIB_TEX4 = 12,
+ VF_ATTRIB_TEX5 = 13,
+ VF_ATTRIB_TEX6 = 14,
+ VF_ATTRIB_TEX7 = 15,
+ VF_ATTRIB_VAR0 = 16,
+ VF_ATTRIB_VAR1 = 17,
+ VF_ATTRIB_VAR2 = 18,
+ VF_ATTRIB_VAR3 = 19,
+ VF_ATTRIB_VAR4 = 20,
+ VF_ATTRIB_VAR5 = 21,
+ VF_ATTRIB_VAR6 = 22,
+ VF_ATTRIB_VAR7 = 23,
+ VF_ATTRIB_POINTSIZE = 24,
+ VF_ATTRIB_BFC0 = 25,
+ VF_ATTRIB_BFC1 = 26,
+ VF_ATTRIB_CLIP_POS = 27,
+ VF_ATTRIB_VERTEX_HEADER = 28,
+ VF_ATTRIB_MAX = 29
+};
+
+
+enum vf_attr_format {
+ EMIT_1F,
+ EMIT_2F,
+ EMIT_3F,
+ EMIT_4F,
+ EMIT_2F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_3F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_4F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_3F_XYW, /* for projective texture */
+ EMIT_1UB_1F, /* for fog coordinate */
+ EMIT_3UB_3F_RGB, /* for specular color */
+ EMIT_3UB_3F_BGR, /* for specular color */
+ EMIT_4UB_4F_RGBA, /* for color */
+ EMIT_4UB_4F_BGRA, /* for color */
+ EMIT_4UB_4F_ARGB, /* for color */
+ EMIT_4UB_4F_ABGR, /* for color */
+ EMIT_4CHAN_4F_RGBA, /* for swrast color */
+ EMIT_PAD, /* leave a hole of 'offset' bytes */
+ EMIT_MAX
+};
+
+struct vf_attr_map {
+ GLuint attrib;
+ enum vf_attr_format format;
+ GLuint offset;
+};
+
+struct vertex_fetch;
+
+void vf_set_vp_matrix( struct vertex_fetch *vf,
+ const GLfloat *viewport );
+
+void vf_set_vp_scale_translate( struct vertex_fetch *vf,
+ const GLfloat *scale,
+ const GLfloat *translate );
+
+GLuint vf_set_vertex_attributes( struct vertex_fetch *vf,
+ const struct vf_attr_map *map,
+ GLuint nr,
+ GLuint vertex_stride );
+
+void vf_set_sources( struct vertex_fetch *vf,
+ GLvector4f * const attrib[],
+ GLuint start );
+
+void vf_emit_vertices( struct vertex_fetch *vf,
+ GLuint count,
+ void *dest );
+
+void vf_get_attr( struct vertex_fetch *vf,
+ const void *vertex,
+ GLenum attr,
+ const GLfloat *dflt,
+ GLfloat *dest );
+
+struct vertex_fetch *vf_create( GLboolean allow_viewport_emits );
+
+void vf_destroy( struct vertex_fetch *vf );
+
+
+
+/***********************************************************************
+ * Internal functions and structs:
+ */
+
+struct vf_attr;
+
+typedef void (*vf_extract_func)( const struct vf_attr *a,
+ GLfloat *out,
+ const GLubyte *v );
+
+typedef void (*vf_insert_func)( const struct vf_attr *a,
+ GLubyte *v,
+ const GLfloat *in );
+
+typedef void (*vf_emit_func)( struct vertex_fetch *vf,
+ GLuint count,
+ GLubyte *dest );
+
+
+
+/* Describes how to convert/move a vertex attribute from a vertex
+ * array to a vertex structure.
+ */
+struct vf_attr
+{
+ struct vertex_fetch *vf;
+
+ GLuint format;
+ GLuint inputsize;
+ GLuint inputstride;
+ GLuint vertoffset; /* position of the attrib in the vertex struct */
+
+ GLuint attrib; /* which vertex attrib (0=position, etc) */
+ GLuint vertattrsize; /* size of the attribute in bytes */
+
+ GLubyte *inputptr;
+ const vf_insert_func *insert;
+ vf_insert_func do_insert;
+ vf_extract_func extract;
+};
+
+struct vertex_fetch
+{
+ struct vf_attr attr[VF_ATTRIB_MAX];
+ GLuint attr_count;
+ GLuint vertex_stride;
+
+ struct vf_attr *lookup[VF_ATTRIB_MAX];
+
+ vf_emit_func emit;
+
+ /* Parameters and constants for codegen:
+ */
+ GLboolean allow_viewport_emits;
+ GLfloat vp[8];
+ GLfloat chan_scale[4];
+ GLfloat identity[4];
+
+ struct vf_fastpath *fastpath;
+
+ void (*codegen_emit)( struct vertex_fetch *vf );
+};
+
+
+struct vf_attr_type {
+ GLuint format;
+ GLuint size;
+ GLuint stride;
+ GLuint offset;
+};
+
+struct vf_fastpath {
+ GLuint vertex_stride;
+ GLuint attr_count;
+ GLboolean match_strides;
+
+ struct vf_attr_type *attr;
+
+ vf_emit_func func;
+ struct vf_fastpath *next;
+};
+
+
+void vf_register_fastpath( struct vertex_fetch *vtx,
+ GLboolean match_strides );
+
+void vf_generic_emit( struct vertex_fetch *vf,
+ GLuint count,
+ GLubyte *v );
+
+void vf_generate_hardwired_emit( struct vertex_fetch *vf );
+
+void vf_generate_sse_emit( struct vertex_fetch *vf );
+
+
+struct vf_format_info {
+ const char *name;
+ vf_extract_func extract;
+ vf_insert_func insert[4];
+ const GLuint attrsize;
+};
+
+const struct vf_format_info vf_format_info[EMIT_MAX];
+
+
+#endif
diff --git a/src/mesa/vf/vf_generic.c b/src/mesa/vf/vf_generic.c
new file mode 100644
index 0000000000..baa00af29a
--- /dev/null
+++ b/src/mesa/vf/vf_generic.c
@@ -0,0 +1,981 @@
+
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * TUNGSTEN GRAPHICS 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:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+
+#include "vf/vf.h"
+
+
+/*
+ * These functions take the NDC coordinates pointed to by 'in', apply the
+ * NDC->Viewport mapping and store the results at 'v'.
+ */
+
+static INLINE void insert_4f_viewport_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = scale[2] * in[2] + trans[2];
+ out[3] = in[3];
+}
+
+static INLINE void insert_4f_viewport_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = scale[2] * in[2] + trans[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = trans[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = trans[1];
+ out[2] = trans[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_3f_viewport_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = scale[2] * in[2] + trans[2];
+}
+
+static INLINE void insert_3f_viewport_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+ out[2] = scale[2] * in[2] + trans[2];
+}
+
+static INLINE void insert_3f_viewport_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = trans[1];
+ out[2] = trans[2];
+}
+
+static INLINE void insert_2f_viewport_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = scale[1] * in[1] + trans[1];
+}
+
+static INLINE void insert_2f_viewport_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = scale[0] * in[0] + trans[0];
+ out[1] = trans[1];
+}
+
+
+/*
+ * These functions do the same as above, except for the viewport mapping.
+ */
+
+static INLINE void insert_4f_4( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+static INLINE void insert_4f_3( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static INLINE void insert_3f_xyw_4( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[3];
+}
+
+static INLINE void insert_3f_xyw_err( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ (void) a; (void) v; (void) in;
+ _mesa_exit(1);
+}
+
+static INLINE void insert_3f_3( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+}
+
+static INLINE void insert_3f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+}
+
+static INLINE void insert_3f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+}
+
+
+static INLINE void insert_2f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+}
+
+static INLINE void insert_2f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+}
+
+static INLINE void insert_1f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+
+ out[0] = in[0];
+}
+
+static INLINE void insert_null( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+ (void) a; (void) v; (void) in;
+}
+
+static INLINE void insert_4chan_4f_rgba_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
+}
+
+static INLINE void insert_4chan_4f_rgba_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ c[2] = 0;
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ c[1] = 0;
+ c[2] = 0;
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4ub_4f_rgba_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_rgba_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[2] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ v[1] = 0;
+ v[2] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_bgra_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[0] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ v[1] = 0;
+ v[0] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_argb_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ v[3] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ v[2] = 0x00;
+ v[3] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_4( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_abgr_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ v[1] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ v[2] = 0x00;
+ v[1] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_3ub_3f_rgb_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+}
+
+static INLINE void insert_3ub_3f_rgb_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_rgb_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ v[1] = 0;
+ v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_3( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+}
+
+static INLINE void insert_3ub_3f_bgr_2( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[0] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ v[1] = 0;
+ v[0] = 0;
+}
+
+
+static INLINE void insert_1ub_1f_1( const struct vf_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+}
+
+
+/***********************************************************************
+ * Functions to perform the reverse operations to the above, for
+ * swrast translation and clip-interpolation.
+ *
+ * Currently always extracts a full 4 floats.
+ */
+
+static void extract_4f_viewport( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ /* Although included for completeness, the position coordinate is
+ * usually handled differently during clipping.
+ */
+ out[0] = (in[0] - trans[0]) / scale[0];
+ out[1] = (in[1] - trans[1]) / scale[1];
+ out[2] = (in[2] - trans[2]) / scale[2];
+ out[3] = in[3];
+}
+
+static void extract_3f_viewport( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = (in[0] - trans[0]) / scale[0];
+ out[1] = (in[1] - trans[1]) / scale[1];
+ out[2] = (in[2] - trans[2]) / scale[2];
+ out[3] = 1;
+}
+
+
+static void extract_2f_viewport( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat *scale = a->vf->vp;
+ const GLfloat *trans = a->vf->vp + 4;
+
+ out[0] = (in[0] - trans[0]) / scale[0];
+ out[1] = (in[1] - trans[1]) / scale[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+
+static void extract_4f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+static void extract_3f_xyw( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = in[2];
+}
+
+
+static void extract_3f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = 1;
+}
+
+
+static void extract_2f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static void extract_1f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static void extract_4chan_4f_rgba( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+
+ out[0] = CHAN_TO_FLOAT(c[0]);
+ out[1] = CHAN_TO_FLOAT(c[1]);
+ out[2] = CHAN_TO_FLOAT(c[2]);
+ out[3] = CHAN_TO_FLOAT(c[3]);
+}
+
+static void extract_4ub_4f_rgba( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[2] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_bgra( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[2] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[0] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_argb( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[3] = UBYTE_TO_FLOAT(v[0]);
+ out[0] = UBYTE_TO_FLOAT(v[1]);
+ out[1] = UBYTE_TO_FLOAT(v[2]);
+ out[2] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_abgr( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[3] = UBYTE_TO_FLOAT(v[0]);
+ out[2] = UBYTE_TO_FLOAT(v[1]);
+ out[1] = UBYTE_TO_FLOAT(v[2]);
+ out[0] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_3ub_3f_rgb( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[2] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = 1;
+}
+
+static void extract_3ub_3f_bgr( const struct vf_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[2] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[0] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = 1;
+}
+
+static void extract_1ub_1f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+
+const struct vf_format_info vf_format_info[EMIT_MAX] =
+{
+ { "1f",
+ extract_1f,
+ { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 },
+ sizeof(GLfloat) },
+
+ { "2f",
+ extract_2f,
+ { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 },
+ 2 * sizeof(GLfloat) },
+
+ { "3f",
+ extract_3f,
+ { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 },
+ 3 * sizeof(GLfloat) },
+
+ { "4f",
+ extract_4f,
+ { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 },
+ 4 * sizeof(GLfloat) },
+
+ { "2f_viewport",
+ extract_2f_viewport,
+ { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2,
+ insert_2f_viewport_2 },
+ 2 * sizeof(GLfloat) },
+
+ { "3f_viewport",
+ extract_3f_viewport,
+ { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3,
+ insert_3f_viewport_3 },
+ 3 * sizeof(GLfloat) },
+
+ { "4f_viewport",
+ extract_4f_viewport,
+ { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3,
+ insert_4f_viewport_4 },
+ 4 * sizeof(GLfloat) },
+
+ { "3f_xyw",
+ extract_3f_xyw,
+ { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err,
+ insert_3f_xyw_4 },
+ 3 * sizeof(GLfloat) },
+
+ { "1ub_1f",
+ extract_1ub_1f,
+ { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 },
+ sizeof(GLubyte) },
+
+ { "3ub_3f_rgb",
+ extract_3ub_3f_rgb,
+ { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3,
+ insert_3ub_3f_rgb_3 },
+ 3 * sizeof(GLubyte) },
+
+ { "3ub_3f_bgr",
+ extract_3ub_3f_bgr,
+ { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3,
+ insert_3ub_3f_bgr_3 },
+ 3 * sizeof(GLubyte) },
+
+ { "4ub_4f_rgba",
+ extract_4ub_4f_rgba,
+ { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3,
+ insert_4ub_4f_rgba_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_bgra",
+ extract_4ub_4f_bgra,
+ { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3,
+ insert_4ub_4f_bgra_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_argb",
+ extract_4ub_4f_argb,
+ { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3,
+ insert_4ub_4f_argb_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_abgr",
+ extract_4ub_4f_abgr,
+ { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3,
+ insert_4ub_4f_abgr_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4chan_4f_rgba",
+ extract_4chan_4f_rgba,
+ { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3,
+ insert_4chan_4f_rgba_4 },
+ 4 * sizeof(GLchan) },
+
+ { "pad",
+ NULL,
+ { NULL, NULL, NULL, NULL },
+ 0 }
+
+};
+
+
+
+
+/***********************************************************************
+ * Hardwired fastpaths for emitting whole vertices or groups of
+ * vertices
+ */
+#define EMIT5(NR, F0, F1, F2, F3, F4, NAME) \
+static void NAME( struct vertex_fetch *vf, \
+ GLuint count, \
+ GLubyte *v ) \
+{ \
+ struct vf_attr *a = vf->attr; \
+ GLuint i; \
+ \
+ for (i = 0 ; i < count ; i++, v += vf->vertex_stride) { \
+ if (NR > 0) { \
+ F0( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr ); \
+ a[0].inputptr += a[0].inputstride; \
+ } \
+ \
+ if (NR > 1) { \
+ F1( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr ); \
+ a[1].inputptr += a[1].inputstride; \
+ } \
+ \
+ if (NR > 2) { \
+ F2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr ); \
+ a[2].inputptr += a[2].inputstride; \
+ } \
+ \
+ if (NR > 3) { \
+ F3( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr ); \
+ a[3].inputptr += a[3].inputstride; \
+ } \
+ \
+ if (NR > 4) { \
+ F4( &a[4], v + a[4].vertoffset, (GLfloat *)a[4].inputptr ); \
+ a[4].inputptr += a[4].inputstride; \
+ } \
+ } \
+}
+
+
+#define EMIT2(F0, F1, NAME) EMIT5(2, F0, F1, insert_null, \
+ insert_null, insert_null, NAME)
+
+#define EMIT3(F0, F1, F2, NAME) EMIT5(3, F0, F1, F2, insert_null, \
+ insert_null, NAME)
+
+#define EMIT4(F0, F1, F2, F3, NAME) EMIT5(4, F0, F1, F2, F3, \
+ insert_null, NAME)
+
+
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4)
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4)
+EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4)
+
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2)
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, emit_viewport4_bgra4_st2)
+EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2)
+
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2)
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2, emit_viewport4_bgra4_st2_st2)
+EMIT4(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_xyzw4_rgba4_st2_st2)
+
+
+/* Use the codegen paths to select one of a number of hardwired
+ * fastpaths.
+ */
+void vf_generate_hardwired_emit( struct vertex_fetch *vf )
+{
+ vf_emit_func func = NULL;
+
+ /* Does it fit a hardwired fastpath? Help! this is growing out of
+ * control!
+ */
+ switch (vf->attr_count) {
+ case 2:
+ if (vf->attr[0].do_insert == insert_3f_viewport_3) {
+ if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4)
+ func = emit_viewport3_bgra4;
+ else if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4)
+ func = emit_viewport3_rgba4;
+ }
+ else if (vf->attr[0].do_insert == insert_3f_3 &&
+ vf->attr[1].do_insert == insert_4ub_4f_rgba_4) {
+ func = emit_xyz3_rgba4;
+ }
+ break;
+ case 3:
+ if (vf->attr[2].do_insert == insert_2f_2) {
+ if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) {
+ if (vf->attr[0].do_insert == insert_4f_viewport_4)
+ func = emit_viewport4_rgba4_st2;
+ else if (vf->attr[0].do_insert == insert_4f_4)
+ func = emit_xyzw4_rgba4_st2;
+ }
+ else if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4 &&
+ vf->attr[0].do_insert == insert_4f_viewport_4)
+ func = emit_viewport4_bgra4_st2;
+ }
+ break;
+ case 4:
+ if (vf->attr[2].do_insert == insert_2f_2 &&
+ vf->attr[3].do_insert == insert_2f_2) {
+ if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) {
+ if (vf->attr[0].do_insert == insert_4f_viewport_4)
+ func = emit_viewport4_rgba4_st2_st2;
+ else if (vf->attr[0].do_insert == insert_4f_4)
+ func = emit_xyzw4_rgba4_st2_st2;
+ }
+ else if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4 &&
+ vf->attr[0].do_insert == insert_4f_viewport_4)
+ func = emit_viewport4_bgra4_st2_st2;
+ }
+ break;
+ }
+
+ vf->emit = func;
+}
+
+/***********************************************************************
+ * Generic (non-codegen) functions for whole vertices or groups of
+ * vertices
+ */
+
+void vf_generic_emit( struct vertex_fetch *vf,
+ GLuint count,
+ GLubyte *v )
+{
+ struct vf_attr *a = vf->attr;
+ const GLuint attr_count = vf->attr_count;
+ const GLuint stride = vf->vertex_stride;
+ GLuint i, j;
+
+ for (i = 0 ; i < count ; i++, v += stride) {
+ for (j = 0; j < attr_count; j++) {
+ GLfloat *in = (GLfloat *)a[j].inputptr;
+ a[j].inputptr += a[j].inputstride;
+ a[j].do_insert( &a[j], v + a[j].vertoffset, in );
+ }
+ }
+}
+
+
diff --git a/src/mesa/vf/vf_sse.c b/src/mesa/vf/vf_sse.c
new file mode 100644
index 0000000000..4d70196ffe
--- /dev/null
+++ b/src/mesa/vf/vf_sse.c
@@ -0,0 +1,662 @@
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * 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
+ * TUNGSTEN GRAPHICS 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:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+#include "main/enums.h"
+
+#include "vf/vf.h"
+
+#if defined(USE_SSE_ASM)
+
+#include "x86/rtasm/x86sse.h"
+#include "x86/common_x86_asm.h"
+
+
+#define X 0
+#define Y 1
+#define Z 2
+#define W 3
+
+
+struct x86_program {
+ struct x86_function func;
+
+ struct vertex_fetch *vf;
+ GLboolean inputs_safe;
+ GLboolean outputs_safe;
+ GLboolean have_sse2;
+
+ struct x86_reg identity;
+ struct x86_reg chan0;
+};
+
+
+static struct x86_reg get_identity( struct x86_program *p )
+{
+ return p->identity;
+}
+
+static void emit_load4f_4( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_load4f_3( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Have to jump through some hoops:
+ *
+ * c 0 0 0
+ * c 0 0 1
+ * 0 0 c 1
+ * a b c 1
+ */
+ sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+ sse_shufps(&p->func, dest, dest, SHUF(Y,Z,X,W) );
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Initialize from identity, then pull in low two words:
+ */
+ sse_movups(&p->func, dest, get_identity(p));
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Pull in low word, then swizzle in identity */
+ sse_movss(&p->func, dest, arg0);
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+}
+
+
+
+static void emit_load3f_3( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Over-reads by 1 dword - potential SEGV if input is a vertex
+ * array.
+ */
+ if (p->inputs_safe) {
+ sse_movups(&p->func, dest, arg0);
+ }
+ else {
+ /* c 0 0 0
+ * c c c c
+ * a b c c
+ */
+ sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+ sse_shufps(&p->func, dest, dest, SHUF(X,X,X,X));
+ sse_movlps(&p->func, dest, arg0);
+ }
+}
+
+static void emit_load3f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ emit_load4f_2(p, dest, arg0);
+}
+
+static void emit_load3f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ emit_load4f_1(p, dest, arg0);
+}
+
+static void emit_load2f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load2f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ emit_load4f_1(p, dest, arg0);
+}
+
+static void emit_load1f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movss(&p->func, dest, arg0);
+}
+
+static void (*load[4][4])( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 ) = {
+ { emit_load1f_1,
+ emit_load1f_1,
+ emit_load1f_1,
+ emit_load1f_1 },
+
+ { emit_load2f_1,
+ emit_load2f_2,
+ emit_load2f_2,
+ emit_load2f_2 },
+
+ { emit_load3f_1,
+ emit_load3f_2,
+ emit_load3f_3,
+ emit_load3f_3 },
+
+ { emit_load4f_1,
+ emit_load4f_2,
+ emit_load4f_3,
+ emit_load4f_4 }
+};
+
+static void emit_load( struct x86_program *p,
+ struct x86_reg dest,
+ GLuint sz,
+ struct x86_reg src,
+ GLuint src_sz)
+{
+ load[sz-1][src_sz-1](p, dest, src);
+}
+
+static void emit_store4f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_store3f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ if (p->outputs_safe) {
+ /* Emit the extra dword anyway. This may hurt writecombining,
+ * may cause other problems.
+ */
+ sse_movups(&p->func, dest, arg0);
+ }
+ else {
+ /* Alternate strategy - emit two, shuffle, emit one.
+ */
+ sse_movlps(&p->func, dest, arg0);
+ sse_shufps(&p->func, arg0, arg0, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
+ sse_movss(&p->func, x86_make_disp(dest,8), arg0);
+ }
+}
+
+static void emit_store2f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_store1f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movss(&p->func, dest, arg0);
+}
+
+
+static void (*store[4])( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 ) =
+{
+ emit_store1f,
+ emit_store2f,
+ emit_store3f,
+ emit_store4f
+};
+
+static void emit_store( struct x86_program *p,
+ struct x86_reg dest,
+ GLuint sz,
+ struct x86_reg temp )
+
+{
+ store[sz-1](p, dest, temp);
+}
+
+static void emit_pack_store_4ub( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg temp )
+{
+ /* Scale by 255.0
+ */
+ sse_mulps(&p->func, temp, p->chan0);
+
+ if (p->have_sse2) {
+ sse2_cvtps2dq(&p->func, temp, temp);
+ sse2_packssdw(&p->func, temp, temp);
+ sse2_packuswb(&p->func, temp, temp);
+ sse_movss(&p->func, dest, temp);
+ }
+ else {
+ struct x86_reg mmx0 = x86_make_reg(file_MMX, 0);
+ struct x86_reg mmx1 = x86_make_reg(file_MMX, 1);
+ sse_cvtps2pi(&p->func, mmx0, temp);
+ sse_movhlps(&p->func, temp, temp);
+ sse_cvtps2pi(&p->func, mmx1, temp);
+ mmx_packssdw(&p->func, mmx0, mmx1);
+ mmx_packuswb(&p->func, mmx0, mmx0);
+ mmx_movd(&p->func, dest, mmx0);
+ }
+}
+
+static GLint get_offset( const void *a, const void *b )
+{
+ return (const char *)b - (const char *)a;
+}
+
+/* Not much happens here. Eventually use this function to try and
+ * avoid saving/reloading the source pointers each vertex (if some of
+ * them can fit in registers).
+ */
+static void get_src_ptr( struct x86_program *p,
+ struct x86_reg srcREG,
+ struct x86_reg vfREG,
+ struct vf_attr *a )
+{
+ struct vertex_fetch *vf = p->vf;
+ struct x86_reg ptr_to_src = x86_make_disp(vfREG, get_offset(vf, &a->inputptr));
+
+ /* Load current a[j].inputptr
+ */
+ x86_mov(&p->func, srcREG, ptr_to_src);
+}
+
+static void update_src_ptr( struct x86_program *p,
+ struct x86_reg srcREG,
+ struct x86_reg vfREG,
+ struct vf_attr *a )
+{
+ if (a->inputstride) {
+ struct vertex_fetch *vf = p->vf;
+ struct x86_reg ptr_to_src = x86_make_disp(vfREG, get_offset(vf, &a->inputptr));
+
+ /* add a[j].inputstride (hardcoded value - could just as easily
+ * pull the stride value from memory each time).
+ */
+ x86_lea(&p->func, srcREG, x86_make_disp(srcREG, a->inputstride));
+
+ /* save new value of a[j].inputptr
+ */
+ x86_mov(&p->func, ptr_to_src, srcREG);
+ }
+}
+
+
+/* Lots of hardcoding
+ *
+ * EAX -- pointer to current output vertex
+ * ECX -- pointer to current attribute
+ *
+ */
+static GLboolean build_vertex_emit( struct x86_program *p )
+{
+ struct vertex_fetch *vf = p->vf;
+ GLuint j = 0;
+
+ struct x86_reg vertexEAX = x86_make_reg(file_REG32, reg_AX);
+ struct x86_reg srcECX = x86_make_reg(file_REG32, reg_CX);
+ struct x86_reg countEBP = x86_make_reg(file_REG32, reg_BP);
+ struct x86_reg vfESI = x86_make_reg(file_REG32, reg_SI);
+ struct x86_reg temp = x86_make_reg(file_XMM, 0);
+ struct x86_reg vp0 = x86_make_reg(file_XMM, 1);
+ struct x86_reg vp1 = x86_make_reg(file_XMM, 2);
+ GLubyte *fixup, *label;
+
+ /* Push a few regs?
+ */
+ x86_push(&p->func, countEBP);
+ x86_push(&p->func, vfESI);
+
+
+ /* Get vertex count, compare to zero
+ */
+ x86_xor(&p->func, srcECX, srcECX);
+ x86_mov(&p->func, countEBP, x86_fn_arg(&p->func, 2));
+ x86_cmp(&p->func, countEBP, srcECX);
+ fixup = x86_jcc_forward(&p->func, cc_E);
+
+ /* Initialize destination register.
+ */
+ x86_mov(&p->func, vertexEAX, x86_fn_arg(&p->func, 3));
+
+ /* Move argument 1 (vf) into a reg:
+ */
+ x86_mov(&p->func, vfESI, x86_fn_arg(&p->func, 1));
+
+
+ /* Possibly load vp0, vp1 for viewport calcs:
+ */
+ if (vf->allow_viewport_emits) {
+ sse_movups(&p->func, vp0, x86_make_disp(vfESI, get_offset(vf, &vf->vp[0])));
+ sse_movups(&p->func, vp1, x86_make_disp(vfESI, get_offset(vf, &vf->vp[4])));
+ }
+
+ /* always load, needed or not:
+ */
+ sse_movups(&p->func, p->chan0, x86_make_disp(vfESI, get_offset(vf, &vf->chan_scale[0])));
+ sse_movups(&p->func, p->identity, x86_make_disp(vfESI, get_offset(vf, &vf->identity[0])));
+
+ /* Note address for loop jump */
+ label = x86_get_label(&p->func);
+
+ /* Emit code for each of the attributes. Currently routes
+ * everything through SSE registers, even when it might be more
+ * efficient to stick with regular old x86. No optimization or
+ * other tricks - enough new ground to cover here just getting
+ * things working.
+ */
+ while (j < vf->attr_count) {
+ struct vf_attr *a = &vf->attr[j];
+ struct x86_reg dest = x86_make_disp(vertexEAX, a->vertoffset);
+
+ /* Now, load an XMM reg from src, perhaps transform, then save.
+ * Could be shortcircuited in specific cases:
+ */
+ switch (a->format) {
+ case EMIT_1F:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 1, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_2F:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 2, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_3F:
+ /* Potentially the worst case - hardcode 2+1 copying:
+ */
+ if (0) {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ }
+ else {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 2, temp);
+ if (a->inputsize > 2) {
+ emit_load(p, temp, 1, x86_make_disp(srcECX, 8), 1);
+ emit_store(p, x86_make_disp(dest,8), 1, temp);
+ }
+ else {
+ sse_movss(&p->func, x86_make_disp(dest,8), get_identity(p));
+ }
+ update_src_ptr(p, srcECX, vfESI, a);
+ }
+ break;
+ case EMIT_4F:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_2F_VIEWPORT:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 2, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_3F_VIEWPORT:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4F_VIEWPORT:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_3F_XYW:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(X,Y,W,Z));
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+
+ case EMIT_1UB_1F:
+ /* Test for PAD3 + 1UB:
+ */
+ if (j > 0 &&
+ a[-1].vertoffset + a[-1].vertattrsize <= a->vertoffset - 3)
+ {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(X,X,X,X));
+ emit_pack_store_4ub(p, x86_make_disp(dest, -3), temp); /* overkill! */
+ update_src_ptr(p, srcECX, vfESI, a);
+ }
+ else {
+ _mesa_printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize );
+ return GL_FALSE;
+ }
+ break;
+ case EMIT_3UB_3F_RGB:
+ case EMIT_3UB_3F_BGR:
+ /* Test for 3UB + PAD1:
+ */
+ if (j == vf->attr_count - 1 ||
+ a[1].vertoffset >= a->vertoffset + 4) {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ if (a->format == EMIT_3UB_3F_BGR)
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ }
+ /* Test for 3UB + 1UB:
+ */
+ else if (j < vf->attr_count - 1 &&
+ a[1].format == EMIT_1UB_1F &&
+ a[1].vertoffset == a->vertoffset + 3) {
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ update_src_ptr(p, srcECX, vfESI, a);
+
+ /* Make room for incoming value:
+ */
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+
+ get_src_ptr(p, srcECX, vfESI, &a[1]);
+ emit_load(p, temp, 1, x86_deref(srcECX), a[1].inputsize);
+ update_src_ptr(p, srcECX, vfESI, &a[1]);
+
+ /* Rearrange and possibly do BGR conversion:
+ */
+ if (a->format == EMIT_3UB_3F_BGR)
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+ else
+ sse_shufps(&p->func, temp, temp, SHUF(Y,Z,W,X));
+
+ emit_pack_store_4ub(p, dest, temp);
+ j++; /* NOTE: two attrs consumed */
+ }
+ else {
+ _mesa_printf("Can't emit 3ub\n");
+ }
+ return GL_FALSE; /* add this later */
+ break;
+
+ case EMIT_4UB_4F_RGBA:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4UB_4F_BGRA:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4UB_4F_ARGB:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4UB_4F_ABGR:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case EMIT_4CHAN_4F_RGBA:
+ switch (CHAN_TYPE) {
+ case GL_UNSIGNED_BYTE:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case GL_FLOAT:
+ get_src_ptr(p, srcECX, vfESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vfESI, a);
+ break;
+ case GL_UNSIGNED_SHORT:
+ default:
+ _mesa_printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE));
+ return GL_FALSE;
+ }
+ break;
+ default:
+ _mesa_printf("unknown a[%d].format %d\n", j, a->format);
+ return GL_FALSE; /* catch any new opcodes */
+ }
+
+ /* Increment j by at least 1 - may have been incremented above also:
+ */
+ j++;
+ }
+
+ /* Next vertex:
+ */
+ x86_lea(&p->func, vertexEAX, x86_make_disp(vertexEAX, vf->vertex_stride));
+
+ /* decr count, loop if not zero
+ */
+ x86_dec(&p->func, countEBP);
+ x86_test(&p->func, countEBP, countEBP);
+ x86_jcc(&p->func, cc_NZ, label);
+
+ /* Exit mmx state?
+ */
+ if (p->func.need_emms)
+ mmx_emms(&p->func);
+
+ /* Land forward jump here:
+ */
+ x86_fixup_fwd_jump(&p->func, fixup);
+
+ /* Pop regs and return
+ */
+ x86_pop(&p->func, x86_get_base_reg(vfESI));
+ x86_pop(&p->func, countEBP);
+ x86_ret(&p->func);
+
+ vf->emit = (vf_emit_func)x86_get_func(&p->func);
+ return GL_TRUE;
+}
+
+
+
+void vf_generate_sse_emit( struct vertex_fetch *vf )
+{
+ struct x86_program p;
+
+ if (!cpu_has_xmm) {
+ vf->codegen_emit = NULL;
+ return;
+ }
+
+ _mesa_memset(&p, 0, sizeof(p));
+
+ p.vf = vf;
+ p.inputs_safe = 0; /* for now */
+ p.outputs_safe = 0; /* for now */
+ p.have_sse2 = cpu_has_xmm2;
+ p.identity = x86_make_reg(file_XMM, 6);
+ p.chan0 = x86_make_reg(file_XMM, 7);
+
+ x86_init_func(&p.func);
+
+ if (build_vertex_emit(&p)) {
+ vf_register_fastpath( vf, GL_TRUE );
+ }
+ else {
+ /* Note the failure so that we don't keep trying to codegen an
+ * impossible state:
+ */
+ vf_register_fastpath( vf, GL_FALSE );
+ x86_release_func(&p.func);
+ }
+}
+
+#else
+
+void vf_generate_sse_emit( struct vertex_fetch *vf )
+{
+ /* Dummy version for when USE_SSE_ASM not defined */
+}
+
+#endif
diff --git a/src/mesa/x86-64/glapi_x86-64.S b/src/mesa/x86-64/glapi_x86-64.S
index cb34061b36..907deb4d2f 100644
--- a/src/mesa/x86-64/glapi_x86-64.S
+++ b/src/mesa/x86-64/glapi_x86-64.S
@@ -45,7 +45,7 @@
# define GL_PREFIX(n) GLNAME(CONCAT(gl,n))
# endif
-#if defined(PTHREADS) || defined(USE_XTHREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS)
+#if defined(PTHREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS)
# define THREADS
#endif
@@ -21112,12 +21112,652 @@ GL_PREFIX(DrawBuffersARB):
.size GL_PREFIX(DrawBuffersARB), .-GL_PREFIX(DrawBuffersARB)
.p2align 4,,15
+ .globl GL_PREFIX(RenderbufferStorageMultisample)
+ .type GL_PREFIX(RenderbufferStorageMultisample), @function
+GL_PREFIX(RenderbufferStorageMultisample):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4488(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ call _x86_64_get_dispatch@PLT
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4488(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4488(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ call _glapi_get_dispatch
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4488(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(RenderbufferStorageMultisample), .-GL_PREFIX(RenderbufferStorageMultisample)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(FlushMappedBufferRange)
+ .type GL_PREFIX(FlushMappedBufferRange), @function
+GL_PREFIX(FlushMappedBufferRange):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4496(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _x86_64_get_dispatch@PLT
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4496(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4496(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _glapi_get_dispatch
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4496(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(FlushMappedBufferRange), .-GL_PREFIX(FlushMappedBufferRange)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(MapBufferRange)
+ .type GL_PREFIX(MapBufferRange), @function
+GL_PREFIX(MapBufferRange):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4504(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4504(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4504(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4504(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(MapBufferRange), .-GL_PREFIX(MapBufferRange)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(BindVertexArray)
+ .type GL_PREFIX(BindVertexArray), @function
+GL_PREFIX(BindVertexArray):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4512(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ call _x86_64_get_dispatch@PLT
+ popq %rdi
+ movq 4512(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4512(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ call _glapi_get_dispatch
+ popq %rdi
+ movq 4512(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(BindVertexArray), .-GL_PREFIX(BindVertexArray)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(GenVertexArrays)
+ .type GL_PREFIX(GenVertexArrays), @function
+GL_PREFIX(GenVertexArrays):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4520(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 4520(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4520(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 4520(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(GenVertexArrays), .-GL_PREFIX(GenVertexArrays)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(CopyBufferSubData)
+ .type GL_PREFIX(CopyBufferSubData), @function
+GL_PREFIX(CopyBufferSubData):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4528(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ call _x86_64_get_dispatch@PLT
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4528(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4528(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ call _glapi_get_dispatch
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4528(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(CopyBufferSubData), .-GL_PREFIX(CopyBufferSubData)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(ClientWaitSync)
+ .type GL_PREFIX(ClientWaitSync), @function
+GL_PREFIX(ClientWaitSync):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4536(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _x86_64_get_dispatch@PLT
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4536(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4536(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _glapi_get_dispatch
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4536(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(ClientWaitSync), .-GL_PREFIX(ClientWaitSync)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(DeleteSync)
+ .type GL_PREFIX(DeleteSync), @function
+GL_PREFIX(DeleteSync):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4544(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ call _x86_64_get_dispatch@PLT
+ popq %rdi
+ movq 4544(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4544(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ call _glapi_get_dispatch
+ popq %rdi
+ movq 4544(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(DeleteSync), .-GL_PREFIX(DeleteSync)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(FenceSync)
+ .type GL_PREFIX(FenceSync), @function
+GL_PREFIX(FenceSync):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4552(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 4552(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4552(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 4552(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(FenceSync), .-GL_PREFIX(FenceSync)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(GetInteger64v)
+ .type GL_PREFIX(GetInteger64v), @function
+GL_PREFIX(GetInteger64v):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4560(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 4560(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4560(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 4560(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(GetInteger64v), .-GL_PREFIX(GetInteger64v)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(GetSynciv)
+ .type GL_PREFIX(GetSynciv), @function
+GL_PREFIX(GetSynciv):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4568(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ call _x86_64_get_dispatch@PLT
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4568(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4568(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ call _glapi_get_dispatch
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4568(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(GetSynciv), .-GL_PREFIX(GetSynciv)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(IsSync)
+ .type GL_PREFIX(IsSync), @function
+GL_PREFIX(IsSync):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4576(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ call _x86_64_get_dispatch@PLT
+ popq %rdi
+ movq 4576(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4576(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ call _glapi_get_dispatch
+ popq %rdi
+ movq 4576(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(IsSync), .-GL_PREFIX(IsSync)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(WaitSync)
+ .type GL_PREFIX(WaitSync), @function
+GL_PREFIX(WaitSync):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4584(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _x86_64_get_dispatch@PLT
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4584(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4584(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _glapi_get_dispatch
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4584(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(WaitSync), .-GL_PREFIX(WaitSync)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(DrawElementsBaseVertex)
+ .type GL_PREFIX(DrawElementsBaseVertex), @function
+GL_PREFIX(DrawElementsBaseVertex):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4592(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ call _x86_64_get_dispatch@PLT
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4592(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4592(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ call _glapi_get_dispatch
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4592(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(DrawElementsBaseVertex), .-GL_PREFIX(DrawElementsBaseVertex)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(DrawRangeElementsBaseVertex)
+ .type GL_PREFIX(DrawRangeElementsBaseVertex), @function
+GL_PREFIX(DrawRangeElementsBaseVertex):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4600(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ pushq %r9
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %r9
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4600(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4600(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ pushq %r9
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %r9
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4600(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(DrawRangeElementsBaseVertex), .-GL_PREFIX(DrawRangeElementsBaseVertex)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(MultiDrawElementsBaseVertex)
+ .type GL_PREFIX(MultiDrawElementsBaseVertex), @function
+GL_PREFIX(MultiDrawElementsBaseVertex):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 4608(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ pushq %r9
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %r9
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4608(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 4608(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rcx
+ pushq %r8
+ pushq %r9
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %r9
+ popq %r8
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 4608(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(MultiDrawElementsBaseVertex), .-GL_PREFIX(MultiDrawElementsBaseVertex)
+
+ .p2align 4,,15
.globl GL_PREFIX(PolygonOffsetEXT)
.type GL_PREFIX(PolygonOffsetEXT), @function
GL_PREFIX(PolygonOffsetEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4488(%rax), %r11
+ movq 4616(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -21127,13 +21767,13 @@ GL_PREFIX(PolygonOffsetEXT):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 4488(%rax), %r11
+ movq 4616(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4488(%rax), %r11
+ movq 4616(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -21143,19 +21783,19 @@ GL_PREFIX(PolygonOffsetEXT):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 4488(%rax), %r11
+ movq 4616(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(PolygonOffsetEXT), .-GL_PREFIX(PolygonOffsetEXT)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_562)
- .type GL_PREFIX(_dispatch_stub_562), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_562))
-GL_PREFIX(_dispatch_stub_562):
+ .globl GL_PREFIX(_dispatch_stub_578)
+ .type GL_PREFIX(_dispatch_stub_578), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_578))
+GL_PREFIX(_dispatch_stub_578):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4496(%rax), %r11
+ movq 4624(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21165,13 +21805,13 @@ GL_PREFIX(_dispatch_stub_562):
popq %rbp
popq %rsi
popq %rdi
- movq 4496(%rax), %r11
+ movq 4624(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4496(%rax), %r11
+ movq 4624(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21181,19 +21821,19 @@ GL_PREFIX(_dispatch_stub_562):
popq %rbp
popq %rsi
popq %rdi
- movq 4496(%rax), %r11
+ movq 4624(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_562), .-GL_PREFIX(_dispatch_stub_562)
+ .size GL_PREFIX(_dispatch_stub_578), .-GL_PREFIX(_dispatch_stub_578)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_563)
- .type GL_PREFIX(_dispatch_stub_563), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_563))
-GL_PREFIX(_dispatch_stub_563):
+ .globl GL_PREFIX(_dispatch_stub_579)
+ .type GL_PREFIX(_dispatch_stub_579), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_579))
+GL_PREFIX(_dispatch_stub_579):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4504(%rax), %r11
+ movq 4632(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21203,13 +21843,13 @@ GL_PREFIX(_dispatch_stub_563):
popq %rbp
popq %rsi
popq %rdi
- movq 4504(%rax), %r11
+ movq 4632(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4504(%rax), %r11
+ movq 4632(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21219,19 +21859,19 @@ GL_PREFIX(_dispatch_stub_563):
popq %rbp
popq %rsi
popq %rdi
- movq 4504(%rax), %r11
+ movq 4632(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_563), .-GL_PREFIX(_dispatch_stub_563)
+ .size GL_PREFIX(_dispatch_stub_579), .-GL_PREFIX(_dispatch_stub_579)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_564)
- .type GL_PREFIX(_dispatch_stub_564), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_564))
-GL_PREFIX(_dispatch_stub_564):
+ .globl GL_PREFIX(_dispatch_stub_580)
+ .type GL_PREFIX(_dispatch_stub_580), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_580))
+GL_PREFIX(_dispatch_stub_580):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4512(%rax), %r11
+ movq 4640(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -21241,13 +21881,13 @@ GL_PREFIX(_dispatch_stub_564):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 4512(%rax), %r11
+ movq 4640(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4512(%rax), %r11
+ movq 4640(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -21257,19 +21897,19 @@ GL_PREFIX(_dispatch_stub_564):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 4512(%rax), %r11
+ movq 4640(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_564), .-GL_PREFIX(_dispatch_stub_564)
+ .size GL_PREFIX(_dispatch_stub_580), .-GL_PREFIX(_dispatch_stub_580)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_565)
- .type GL_PREFIX(_dispatch_stub_565), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_565))
-GL_PREFIX(_dispatch_stub_565):
+ .globl GL_PREFIX(_dispatch_stub_581)
+ .type GL_PREFIX(_dispatch_stub_581), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_581))
+GL_PREFIX(_dispatch_stub_581):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4520(%rax), %r11
+ movq 4648(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21279,13 +21919,13 @@ GL_PREFIX(_dispatch_stub_565):
popq %rbp
popq %rsi
popq %rdi
- movq 4520(%rax), %r11
+ movq 4648(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4520(%rax), %r11
+ movq 4648(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21295,19 +21935,19 @@ GL_PREFIX(_dispatch_stub_565):
popq %rbp
popq %rsi
popq %rdi
- movq 4520(%rax), %r11
+ movq 4648(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_565), .-GL_PREFIX(_dispatch_stub_565)
+ .size GL_PREFIX(_dispatch_stub_581), .-GL_PREFIX(_dispatch_stub_581)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_566)
- .type GL_PREFIX(_dispatch_stub_566), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_566))
-GL_PREFIX(_dispatch_stub_566):
+ .globl GL_PREFIX(_dispatch_stub_582)
+ .type GL_PREFIX(_dispatch_stub_582), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_582))
+GL_PREFIX(_dispatch_stub_582):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4528(%rax), %r11
+ movq 4656(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21317,13 +21957,13 @@ GL_PREFIX(_dispatch_stub_566):
popq %rbp
popq %rsi
popq %rdi
- movq 4528(%rax), %r11
+ movq 4656(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4528(%rax), %r11
+ movq 4656(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21333,19 +21973,19 @@ GL_PREFIX(_dispatch_stub_566):
popq %rbp
popq %rsi
popq %rdi
- movq 4528(%rax), %r11
+ movq 4656(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_566), .-GL_PREFIX(_dispatch_stub_566)
+ .size GL_PREFIX(_dispatch_stub_582), .-GL_PREFIX(_dispatch_stub_582)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_567)
- .type GL_PREFIX(_dispatch_stub_567), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_567))
-GL_PREFIX(_dispatch_stub_567):
+ .globl GL_PREFIX(_dispatch_stub_583)
+ .type GL_PREFIX(_dispatch_stub_583), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_583))
+GL_PREFIX(_dispatch_stub_583):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4536(%rax), %r11
+ movq 4664(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21355,13 +21995,13 @@ GL_PREFIX(_dispatch_stub_567):
popq %rbp
popq %rsi
popq %rdi
- movq 4536(%rax), %r11
+ movq 4664(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4536(%rax), %r11
+ movq 4664(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21371,19 +22011,19 @@ GL_PREFIX(_dispatch_stub_567):
popq %rbp
popq %rsi
popq %rdi
- movq 4536(%rax), %r11
+ movq 4664(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_567), .-GL_PREFIX(_dispatch_stub_567)
+ .size GL_PREFIX(_dispatch_stub_583), .-GL_PREFIX(_dispatch_stub_583)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_568)
- .type GL_PREFIX(_dispatch_stub_568), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_568))
-GL_PREFIX(_dispatch_stub_568):
+ .globl GL_PREFIX(_dispatch_stub_584)
+ .type GL_PREFIX(_dispatch_stub_584), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_584))
+GL_PREFIX(_dispatch_stub_584):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4544(%rax), %r11
+ movq 4672(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21393,13 +22033,13 @@ GL_PREFIX(_dispatch_stub_568):
popq %rbp
popq %rsi
popq %rdi
- movq 4544(%rax), %r11
+ movq 4672(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4544(%rax), %r11
+ movq 4672(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21409,40 +22049,40 @@ GL_PREFIX(_dispatch_stub_568):
popq %rbp
popq %rsi
popq %rdi
- movq 4544(%rax), %r11
+ movq 4672(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_568), .-GL_PREFIX(_dispatch_stub_568)
+ .size GL_PREFIX(_dispatch_stub_584), .-GL_PREFIX(_dispatch_stub_584)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_569)
- .type GL_PREFIX(_dispatch_stub_569), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_569))
-GL_PREFIX(_dispatch_stub_569):
+ .globl GL_PREFIX(_dispatch_stub_585)
+ .type GL_PREFIX(_dispatch_stub_585), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_585))
+GL_PREFIX(_dispatch_stub_585):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4552(%rax), %r11
+ movq 4680(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4552(%rax), %r11
+ movq 4680(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4552(%rax), %r11
+ movq 4680(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4552(%rax), %r11
+ movq 4680(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_569), .-GL_PREFIX(_dispatch_stub_569)
+ .size GL_PREFIX(_dispatch_stub_585), .-GL_PREFIX(_dispatch_stub_585)
.p2align 4,,15
.globl GL_PREFIX(ColorPointerEXT)
@@ -21450,7 +22090,7 @@ GL_PREFIX(_dispatch_stub_569):
GL_PREFIX(ColorPointerEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4560(%rax), %r11
+ movq 4688(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21464,13 +22104,13 @@ GL_PREFIX(ColorPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4560(%rax), %r11
+ movq 4688(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4560(%rax), %r11
+ movq 4688(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21484,7 +22124,7 @@ GL_PREFIX(ColorPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4560(%rax), %r11
+ movq 4688(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ColorPointerEXT), .-GL_PREFIX(ColorPointerEXT)
@@ -21495,7 +22135,7 @@ GL_PREFIX(ColorPointerEXT):
GL_PREFIX(EdgeFlagPointerEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4568(%rax), %r11
+ movq 4696(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21505,13 +22145,13 @@ GL_PREFIX(EdgeFlagPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4568(%rax), %r11
+ movq 4696(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4568(%rax), %r11
+ movq 4696(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21521,7 +22161,7 @@ GL_PREFIX(EdgeFlagPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4568(%rax), %r11
+ movq 4696(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(EdgeFlagPointerEXT), .-GL_PREFIX(EdgeFlagPointerEXT)
@@ -21532,7 +22172,7 @@ GL_PREFIX(EdgeFlagPointerEXT):
GL_PREFIX(IndexPointerEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4576(%rax), %r11
+ movq 4704(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21546,13 +22186,13 @@ GL_PREFIX(IndexPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4576(%rax), %r11
+ movq 4704(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4576(%rax), %r11
+ movq 4704(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21566,7 +22206,7 @@ GL_PREFIX(IndexPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4576(%rax), %r11
+ movq 4704(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(IndexPointerEXT), .-GL_PREFIX(IndexPointerEXT)
@@ -21577,7 +22217,7 @@ GL_PREFIX(IndexPointerEXT):
GL_PREFIX(NormalPointerEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4584(%rax), %r11
+ movq 4712(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21591,13 +22231,13 @@ GL_PREFIX(NormalPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4584(%rax), %r11
+ movq 4712(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4584(%rax), %r11
+ movq 4712(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21611,7 +22251,7 @@ GL_PREFIX(NormalPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4584(%rax), %r11
+ movq 4712(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(NormalPointerEXT), .-GL_PREFIX(NormalPointerEXT)
@@ -21622,7 +22262,7 @@ GL_PREFIX(NormalPointerEXT):
GL_PREFIX(TexCoordPointerEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4592(%rax), %r11
+ movq 4720(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21636,13 +22276,13 @@ GL_PREFIX(TexCoordPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4592(%rax), %r11
+ movq 4720(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4592(%rax), %r11
+ movq 4720(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21656,7 +22296,7 @@ GL_PREFIX(TexCoordPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4592(%rax), %r11
+ movq 4720(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(TexCoordPointerEXT), .-GL_PREFIX(TexCoordPointerEXT)
@@ -21667,7 +22307,7 @@ GL_PREFIX(TexCoordPointerEXT):
GL_PREFIX(VertexPointerEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4600(%rax), %r11
+ movq 4728(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21681,13 +22321,13 @@ GL_PREFIX(VertexPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4600(%rax), %r11
+ movq 4728(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4600(%rax), %r11
+ movq 4728(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21701,7 +22341,7 @@ GL_PREFIX(VertexPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4600(%rax), %r11
+ movq 4728(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexPointerEXT), .-GL_PREFIX(VertexPointerEXT)
@@ -21712,7 +22352,7 @@ GL_PREFIX(VertexPointerEXT):
GL_PREFIX(PointParameterfEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4608(%rax), %r11
+ movq 4736(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -21722,13 +22362,13 @@ GL_PREFIX(PointParameterfEXT):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 4608(%rax), %r11
+ movq 4736(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4608(%rax), %r11
+ movq 4736(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -21738,7 +22378,7 @@ GL_PREFIX(PointParameterfEXT):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 4608(%rax), %r11
+ movq 4736(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(PointParameterfEXT), .-GL_PREFIX(PointParameterfEXT)
@@ -21749,7 +22389,7 @@ GL_PREFIX(PointParameterfEXT):
GL_PREFIX(PointParameterfvEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4616(%rax), %r11
+ movq 4744(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21759,13 +22399,13 @@ GL_PREFIX(PointParameterfvEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 4616(%rax), %r11
+ movq 4744(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4616(%rax), %r11
+ movq 4744(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21775,7 +22415,7 @@ GL_PREFIX(PointParameterfvEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 4616(%rax), %r11
+ movq 4744(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(PointParameterfvEXT), .-GL_PREFIX(PointParameterfvEXT)
@@ -21786,7 +22426,7 @@ GL_PREFIX(PointParameterfvEXT):
GL_PREFIX(LockArraysEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4624(%rax), %r11
+ movq 4752(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21796,13 +22436,13 @@ GL_PREFIX(LockArraysEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 4624(%rax), %r11
+ movq 4752(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4624(%rax), %r11
+ movq 4752(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21812,7 +22452,7 @@ GL_PREFIX(LockArraysEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 4624(%rax), %r11
+ movq 4752(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(LockArraysEXT), .-GL_PREFIX(LockArraysEXT)
@@ -21823,37 +22463,37 @@ GL_PREFIX(LockArraysEXT):
GL_PREFIX(UnlockArraysEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4632(%rax), %r11
+ movq 4760(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rbp
call _x86_64_get_dispatch@PLT
popq %rbp
- movq 4632(%rax), %r11
+ movq 4760(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4632(%rax), %r11
+ movq 4760(%rax), %r11
jmp *%r11
1:
pushq %rbp
call _glapi_get_dispatch
popq %rbp
- movq 4632(%rax), %r11
+ movq 4760(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(UnlockArraysEXT), .-GL_PREFIX(UnlockArraysEXT)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_580)
- .type GL_PREFIX(_dispatch_stub_580), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_580))
-GL_PREFIX(_dispatch_stub_580):
+ .globl GL_PREFIX(_dispatch_stub_596)
+ .type GL_PREFIX(_dispatch_stub_596), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_596))
+GL_PREFIX(_dispatch_stub_596):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4640(%rax), %r11
+ movq 4768(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21863,13 +22503,13 @@ GL_PREFIX(_dispatch_stub_580):
popq %rbp
popq %rsi
popq %rdi
- movq 4640(%rax), %r11
+ movq 4768(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4640(%rax), %r11
+ movq 4768(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21879,19 +22519,19 @@ GL_PREFIX(_dispatch_stub_580):
popq %rbp
popq %rsi
popq %rdi
- movq 4640(%rax), %r11
+ movq 4768(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_580), .-GL_PREFIX(_dispatch_stub_580)
+ .size GL_PREFIX(_dispatch_stub_596), .-GL_PREFIX(_dispatch_stub_596)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_581)
- .type GL_PREFIX(_dispatch_stub_581), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_581))
-GL_PREFIX(_dispatch_stub_581):
+ .globl GL_PREFIX(_dispatch_stub_597)
+ .type GL_PREFIX(_dispatch_stub_597), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_597))
+GL_PREFIX(_dispatch_stub_597):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4648(%rax), %r11
+ movq 4776(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21901,13 +22541,13 @@ GL_PREFIX(_dispatch_stub_581):
popq %rbp
popq %rsi
popq %rdi
- movq 4648(%rax), %r11
+ movq 4776(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4648(%rax), %r11
+ movq 4776(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21917,10 +22557,10 @@ GL_PREFIX(_dispatch_stub_581):
popq %rbp
popq %rsi
popq %rdi
- movq 4648(%rax), %r11
+ movq 4776(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_581), .-GL_PREFIX(_dispatch_stub_581)
+ .size GL_PREFIX(_dispatch_stub_597), .-GL_PREFIX(_dispatch_stub_597)
.p2align 4,,15
.globl GL_PREFIX(SecondaryColor3bEXT)
@@ -21928,7 +22568,7 @@ GL_PREFIX(_dispatch_stub_581):
GL_PREFIX(SecondaryColor3bEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4656(%rax), %r11
+ movq 4784(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -21938,13 +22578,13 @@ GL_PREFIX(SecondaryColor3bEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4656(%rax), %r11
+ movq 4784(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4656(%rax), %r11
+ movq 4784(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -21954,7 +22594,7 @@ GL_PREFIX(SecondaryColor3bEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4656(%rax), %r11
+ movq 4784(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3bEXT), .-GL_PREFIX(SecondaryColor3bEXT)
@@ -21965,25 +22605,25 @@ GL_PREFIX(SecondaryColor3bEXT):
GL_PREFIX(SecondaryColor3bvEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4664(%rax), %r11
+ movq 4792(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4664(%rax), %r11
+ movq 4792(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4664(%rax), %r11
+ movq 4792(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4664(%rax), %r11
+ movq 4792(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3bvEXT), .-GL_PREFIX(SecondaryColor3bvEXT)
@@ -21994,7 +22634,7 @@ GL_PREFIX(SecondaryColor3bvEXT):
GL_PREFIX(SecondaryColor3dEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4672(%rax), %r11
+ movq 4800(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -22006,13 +22646,13 @@ GL_PREFIX(SecondaryColor3dEXT):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 4672(%rax), %r11
+ movq 4800(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4672(%rax), %r11
+ movq 4800(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -22024,7 +22664,7 @@ GL_PREFIX(SecondaryColor3dEXT):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 4672(%rax), %r11
+ movq 4800(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3dEXT), .-GL_PREFIX(SecondaryColor3dEXT)
@@ -22035,25 +22675,25 @@ GL_PREFIX(SecondaryColor3dEXT):
GL_PREFIX(SecondaryColor3dvEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4680(%rax), %r11
+ movq 4808(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4680(%rax), %r11
+ movq 4808(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4680(%rax), %r11
+ movq 4808(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4680(%rax), %r11
+ movq 4808(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3dvEXT), .-GL_PREFIX(SecondaryColor3dvEXT)
@@ -22064,7 +22704,7 @@ GL_PREFIX(SecondaryColor3dvEXT):
GL_PREFIX(SecondaryColor3fEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4688(%rax), %r11
+ movq 4816(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -22076,13 +22716,13 @@ GL_PREFIX(SecondaryColor3fEXT):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 4688(%rax), %r11
+ movq 4816(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4688(%rax), %r11
+ movq 4816(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -22094,7 +22734,7 @@ GL_PREFIX(SecondaryColor3fEXT):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 4688(%rax), %r11
+ movq 4816(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3fEXT), .-GL_PREFIX(SecondaryColor3fEXT)
@@ -22105,25 +22745,25 @@ GL_PREFIX(SecondaryColor3fEXT):
GL_PREFIX(SecondaryColor3fvEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4696(%rax), %r11
+ movq 4824(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4696(%rax), %r11
+ movq 4824(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4696(%rax), %r11
+ movq 4824(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4696(%rax), %r11
+ movq 4824(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3fvEXT), .-GL_PREFIX(SecondaryColor3fvEXT)
@@ -22134,7 +22774,7 @@ GL_PREFIX(SecondaryColor3fvEXT):
GL_PREFIX(SecondaryColor3iEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4704(%rax), %r11
+ movq 4832(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22144,13 +22784,13 @@ GL_PREFIX(SecondaryColor3iEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4704(%rax), %r11
+ movq 4832(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4704(%rax), %r11
+ movq 4832(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22160,7 +22800,7 @@ GL_PREFIX(SecondaryColor3iEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4704(%rax), %r11
+ movq 4832(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3iEXT), .-GL_PREFIX(SecondaryColor3iEXT)
@@ -22171,25 +22811,25 @@ GL_PREFIX(SecondaryColor3iEXT):
GL_PREFIX(SecondaryColor3ivEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4712(%rax), %r11
+ movq 4840(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4712(%rax), %r11
+ movq 4840(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4712(%rax), %r11
+ movq 4840(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4712(%rax), %r11
+ movq 4840(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3ivEXT), .-GL_PREFIX(SecondaryColor3ivEXT)
@@ -22200,7 +22840,7 @@ GL_PREFIX(SecondaryColor3ivEXT):
GL_PREFIX(SecondaryColor3sEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4720(%rax), %r11
+ movq 4848(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22210,13 +22850,13 @@ GL_PREFIX(SecondaryColor3sEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4720(%rax), %r11
+ movq 4848(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4720(%rax), %r11
+ movq 4848(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22226,7 +22866,7 @@ GL_PREFIX(SecondaryColor3sEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4720(%rax), %r11
+ movq 4848(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3sEXT), .-GL_PREFIX(SecondaryColor3sEXT)
@@ -22237,25 +22877,25 @@ GL_PREFIX(SecondaryColor3sEXT):
GL_PREFIX(SecondaryColor3svEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4728(%rax), %r11
+ movq 4856(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4728(%rax), %r11
+ movq 4856(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4728(%rax), %r11
+ movq 4856(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4728(%rax), %r11
+ movq 4856(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3svEXT), .-GL_PREFIX(SecondaryColor3svEXT)
@@ -22266,7 +22906,7 @@ GL_PREFIX(SecondaryColor3svEXT):
GL_PREFIX(SecondaryColor3ubEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4736(%rax), %r11
+ movq 4864(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22276,13 +22916,13 @@ GL_PREFIX(SecondaryColor3ubEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4736(%rax), %r11
+ movq 4864(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4736(%rax), %r11
+ movq 4864(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22292,7 +22932,7 @@ GL_PREFIX(SecondaryColor3ubEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4736(%rax), %r11
+ movq 4864(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3ubEXT), .-GL_PREFIX(SecondaryColor3ubEXT)
@@ -22303,25 +22943,25 @@ GL_PREFIX(SecondaryColor3ubEXT):
GL_PREFIX(SecondaryColor3ubvEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4744(%rax), %r11
+ movq 4872(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4744(%rax), %r11
+ movq 4872(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4744(%rax), %r11
+ movq 4872(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4744(%rax), %r11
+ movq 4872(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3ubvEXT), .-GL_PREFIX(SecondaryColor3ubvEXT)
@@ -22332,7 +22972,7 @@ GL_PREFIX(SecondaryColor3ubvEXT):
GL_PREFIX(SecondaryColor3uiEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4752(%rax), %r11
+ movq 4880(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22342,13 +22982,13 @@ GL_PREFIX(SecondaryColor3uiEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4752(%rax), %r11
+ movq 4880(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4752(%rax), %r11
+ movq 4880(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22358,7 +22998,7 @@ GL_PREFIX(SecondaryColor3uiEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4752(%rax), %r11
+ movq 4880(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3uiEXT), .-GL_PREFIX(SecondaryColor3uiEXT)
@@ -22369,25 +23009,25 @@ GL_PREFIX(SecondaryColor3uiEXT):
GL_PREFIX(SecondaryColor3uivEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4760(%rax), %r11
+ movq 4888(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4760(%rax), %r11
+ movq 4888(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4760(%rax), %r11
+ movq 4888(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4760(%rax), %r11
+ movq 4888(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3uivEXT), .-GL_PREFIX(SecondaryColor3uivEXT)
@@ -22398,7 +23038,7 @@ GL_PREFIX(SecondaryColor3uivEXT):
GL_PREFIX(SecondaryColor3usEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4768(%rax), %r11
+ movq 4896(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22408,13 +23048,13 @@ GL_PREFIX(SecondaryColor3usEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4768(%rax), %r11
+ movq 4896(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4768(%rax), %r11
+ movq 4896(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22424,7 +23064,7 @@ GL_PREFIX(SecondaryColor3usEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4768(%rax), %r11
+ movq 4896(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3usEXT), .-GL_PREFIX(SecondaryColor3usEXT)
@@ -22435,25 +23075,25 @@ GL_PREFIX(SecondaryColor3usEXT):
GL_PREFIX(SecondaryColor3usvEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4776(%rax), %r11
+ movq 4904(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4776(%rax), %r11
+ movq 4904(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4776(%rax), %r11
+ movq 4904(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4776(%rax), %r11
+ movq 4904(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColor3usvEXT), .-GL_PREFIX(SecondaryColor3usvEXT)
@@ -22464,7 +23104,7 @@ GL_PREFIX(SecondaryColor3usvEXT):
GL_PREFIX(SecondaryColorPointerEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4784(%rax), %r11
+ movq 4912(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22478,13 +23118,13 @@ GL_PREFIX(SecondaryColorPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4784(%rax), %r11
+ movq 4912(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4784(%rax), %r11
+ movq 4912(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22498,7 +23138,7 @@ GL_PREFIX(SecondaryColorPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4784(%rax), %r11
+ movq 4912(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SecondaryColorPointerEXT), .-GL_PREFIX(SecondaryColorPointerEXT)
@@ -22509,7 +23149,7 @@ GL_PREFIX(SecondaryColorPointerEXT):
GL_PREFIX(MultiDrawArraysEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4792(%rax), %r11
+ movq 4920(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22523,13 +23163,13 @@ GL_PREFIX(MultiDrawArraysEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4792(%rax), %r11
+ movq 4920(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4792(%rax), %r11
+ movq 4920(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22543,7 +23183,7 @@ GL_PREFIX(MultiDrawArraysEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4792(%rax), %r11
+ movq 4920(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(MultiDrawArraysEXT), .-GL_PREFIX(MultiDrawArraysEXT)
@@ -22554,7 +23194,7 @@ GL_PREFIX(MultiDrawArraysEXT):
GL_PREFIX(MultiDrawElementsEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4800(%rax), %r11
+ movq 4928(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22568,13 +23208,13 @@ GL_PREFIX(MultiDrawElementsEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4800(%rax), %r11
+ movq 4928(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4800(%rax), %r11
+ movq 4928(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22588,7 +23228,7 @@ GL_PREFIX(MultiDrawElementsEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4800(%rax), %r11
+ movq 4928(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(MultiDrawElementsEXT), .-GL_PREFIX(MultiDrawElementsEXT)
@@ -22599,7 +23239,7 @@ GL_PREFIX(MultiDrawElementsEXT):
GL_PREFIX(FogCoordPointerEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4808(%rax), %r11
+ movq 4936(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22609,13 +23249,13 @@ GL_PREFIX(FogCoordPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4808(%rax), %r11
+ movq 4936(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4808(%rax), %r11
+ movq 4936(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22625,7 +23265,7 @@ GL_PREFIX(FogCoordPointerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4808(%rax), %r11
+ movq 4936(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FogCoordPointerEXT), .-GL_PREFIX(FogCoordPointerEXT)
@@ -22636,7 +23276,7 @@ GL_PREFIX(FogCoordPointerEXT):
GL_PREFIX(FogCoorddEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4816(%rax), %r11
+ movq 4944(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $8, %rsp
@@ -22644,13 +23284,13 @@ GL_PREFIX(FogCoorddEXT):
call _x86_64_get_dispatch@PLT
movq (%rsp), %xmm0
addq $8, %rsp
- movq 4816(%rax), %r11
+ movq 4944(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4816(%rax), %r11
+ movq 4944(%rax), %r11
jmp *%r11
1:
subq $8, %rsp
@@ -22658,7 +23298,7 @@ GL_PREFIX(FogCoorddEXT):
call _glapi_get_dispatch
movq (%rsp), %xmm0
addq $8, %rsp
- movq 4816(%rax), %r11
+ movq 4944(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FogCoorddEXT), .-GL_PREFIX(FogCoorddEXT)
@@ -22669,25 +23309,25 @@ GL_PREFIX(FogCoorddEXT):
GL_PREFIX(FogCoorddvEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4824(%rax), %r11
+ movq 4952(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4824(%rax), %r11
+ movq 4952(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4824(%rax), %r11
+ movq 4952(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4824(%rax), %r11
+ movq 4952(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FogCoorddvEXT), .-GL_PREFIX(FogCoorddvEXT)
@@ -22698,7 +23338,7 @@ GL_PREFIX(FogCoorddvEXT):
GL_PREFIX(FogCoordfEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4832(%rax), %r11
+ movq 4960(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $8, %rsp
@@ -22706,13 +23346,13 @@ GL_PREFIX(FogCoordfEXT):
call _x86_64_get_dispatch@PLT
movq (%rsp), %xmm0
addq $8, %rsp
- movq 4832(%rax), %r11
+ movq 4960(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4832(%rax), %r11
+ movq 4960(%rax), %r11
jmp *%r11
1:
subq $8, %rsp
@@ -22720,7 +23360,7 @@ GL_PREFIX(FogCoordfEXT):
call _glapi_get_dispatch
movq (%rsp), %xmm0
addq $8, %rsp
- movq 4832(%rax), %r11
+ movq 4960(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FogCoordfEXT), .-GL_PREFIX(FogCoordfEXT)
@@ -22731,58 +23371,58 @@ GL_PREFIX(FogCoordfEXT):
GL_PREFIX(FogCoordfvEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4840(%rax), %r11
+ movq 4968(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4840(%rax), %r11
+ movq 4968(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4840(%rax), %r11
+ movq 4968(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4840(%rax), %r11
+ movq 4968(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FogCoordfvEXT), .-GL_PREFIX(FogCoordfvEXT)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_606)
- .type GL_PREFIX(_dispatch_stub_606), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_606))
-GL_PREFIX(_dispatch_stub_606):
+ .globl GL_PREFIX(_dispatch_stub_622)
+ .type GL_PREFIX(_dispatch_stub_622), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_622))
+GL_PREFIX(_dispatch_stub_622):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4848(%rax), %r11
+ movq 4976(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 4848(%rax), %r11
+ movq 4976(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4848(%rax), %r11
+ movq 4976(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 4848(%rax), %r11
+ movq 4976(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_606), .-GL_PREFIX(_dispatch_stub_606)
+ .size GL_PREFIX(_dispatch_stub_622), .-GL_PREFIX(_dispatch_stub_622)
.p2align 4,,15
.globl GL_PREFIX(BlendFuncSeparateEXT)
@@ -22790,7 +23430,7 @@ GL_PREFIX(_dispatch_stub_606):
GL_PREFIX(BlendFuncSeparateEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4856(%rax), %r11
+ movq 4984(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22804,13 +23444,13 @@ GL_PREFIX(BlendFuncSeparateEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4856(%rax), %r11
+ movq 4984(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4856(%rax), %r11
+ movq 4984(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22824,7 +23464,7 @@ GL_PREFIX(BlendFuncSeparateEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 4856(%rax), %r11
+ movq 4984(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(BlendFuncSeparateEXT), .-GL_PREFIX(BlendFuncSeparateEXT)
@@ -22835,25 +23475,25 @@ GL_PREFIX(BlendFuncSeparateEXT):
GL_PREFIX(FlushVertexArrayRangeNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4864(%rax), %r11
+ movq 4992(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rbp
call _x86_64_get_dispatch@PLT
popq %rbp
- movq 4864(%rax), %r11
+ movq 4992(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4864(%rax), %r11
+ movq 4992(%rax), %r11
jmp *%r11
1:
pushq %rbp
call _glapi_get_dispatch
popq %rbp
- movq 4864(%rax), %r11
+ movq 4992(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FlushVertexArrayRangeNV), .-GL_PREFIX(FlushVertexArrayRangeNV)
@@ -22864,7 +23504,7 @@ GL_PREFIX(FlushVertexArrayRangeNV):
GL_PREFIX(VertexArrayRangeNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4872(%rax), %r11
+ movq 5000(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22874,13 +23514,13 @@ GL_PREFIX(VertexArrayRangeNV):
popq %rbp
popq %rsi
popq %rdi
- movq 4872(%rax), %r11
+ movq 5000(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4872(%rax), %r11
+ movq 5000(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22890,7 +23530,7 @@ GL_PREFIX(VertexArrayRangeNV):
popq %rbp
popq %rsi
popq %rdi
- movq 4872(%rax), %r11
+ movq 5000(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexArrayRangeNV), .-GL_PREFIX(VertexArrayRangeNV)
@@ -22901,7 +23541,7 @@ GL_PREFIX(VertexArrayRangeNV):
GL_PREFIX(CombinerInputNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4880(%rax), %r11
+ movq 5008(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22919,13 +23559,13 @@ GL_PREFIX(CombinerInputNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4880(%rax), %r11
+ movq 5008(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4880(%rax), %r11
+ movq 5008(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22943,7 +23583,7 @@ GL_PREFIX(CombinerInputNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4880(%rax), %r11
+ movq 5008(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(CombinerInputNV), .-GL_PREFIX(CombinerInputNV)
@@ -22954,7 +23594,7 @@ GL_PREFIX(CombinerInputNV):
GL_PREFIX(CombinerOutputNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4888(%rax), %r11
+ movq 5016(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -22972,13 +23612,13 @@ GL_PREFIX(CombinerOutputNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4888(%rax), %r11
+ movq 5016(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4888(%rax), %r11
+ movq 5016(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -22996,7 +23636,7 @@ GL_PREFIX(CombinerOutputNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4888(%rax), %r11
+ movq 5016(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(CombinerOutputNV), .-GL_PREFIX(CombinerOutputNV)
@@ -23007,7 +23647,7 @@ GL_PREFIX(CombinerOutputNV):
GL_PREFIX(CombinerParameterfNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4896(%rax), %r11
+ movq 5024(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -23017,13 +23657,13 @@ GL_PREFIX(CombinerParameterfNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 4896(%rax), %r11
+ movq 5024(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4896(%rax), %r11
+ movq 5024(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -23033,7 +23673,7 @@ GL_PREFIX(CombinerParameterfNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 4896(%rax), %r11
+ movq 5024(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(CombinerParameterfNV), .-GL_PREFIX(CombinerParameterfNV)
@@ -23044,7 +23684,7 @@ GL_PREFIX(CombinerParameterfNV):
GL_PREFIX(CombinerParameterfvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4904(%rax), %r11
+ movq 5032(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23054,13 +23694,13 @@ GL_PREFIX(CombinerParameterfvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 4904(%rax), %r11
+ movq 5032(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4904(%rax), %r11
+ movq 5032(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23070,7 +23710,7 @@ GL_PREFIX(CombinerParameterfvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 4904(%rax), %r11
+ movq 5032(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(CombinerParameterfvNV), .-GL_PREFIX(CombinerParameterfvNV)
@@ -23081,7 +23721,7 @@ GL_PREFIX(CombinerParameterfvNV):
GL_PREFIX(CombinerParameteriNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4912(%rax), %r11
+ movq 5040(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23091,13 +23731,13 @@ GL_PREFIX(CombinerParameteriNV):
popq %rbp
popq %rsi
popq %rdi
- movq 4912(%rax), %r11
+ movq 5040(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4912(%rax), %r11
+ movq 5040(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23107,7 +23747,7 @@ GL_PREFIX(CombinerParameteriNV):
popq %rbp
popq %rsi
popq %rdi
- movq 4912(%rax), %r11
+ movq 5040(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(CombinerParameteriNV), .-GL_PREFIX(CombinerParameteriNV)
@@ -23118,7 +23758,7 @@ GL_PREFIX(CombinerParameteriNV):
GL_PREFIX(CombinerParameterivNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4920(%rax), %r11
+ movq 5048(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23128,13 +23768,13 @@ GL_PREFIX(CombinerParameterivNV):
popq %rbp
popq %rsi
popq %rdi
- movq 4920(%rax), %r11
+ movq 5048(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4920(%rax), %r11
+ movq 5048(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23144,7 +23784,7 @@ GL_PREFIX(CombinerParameterivNV):
popq %rbp
popq %rsi
popq %rdi
- movq 4920(%rax), %r11
+ movq 5048(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(CombinerParameterivNV), .-GL_PREFIX(CombinerParameterivNV)
@@ -23155,7 +23795,7 @@ GL_PREFIX(CombinerParameterivNV):
GL_PREFIX(FinalCombinerInputNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4928(%rax), %r11
+ movq 5056(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23169,13 +23809,13 @@ GL_PREFIX(FinalCombinerInputNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4928(%rax), %r11
+ movq 5056(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4928(%rax), %r11
+ movq 5056(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23189,7 +23829,7 @@ GL_PREFIX(FinalCombinerInputNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4928(%rax), %r11
+ movq 5056(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FinalCombinerInputNV), .-GL_PREFIX(FinalCombinerInputNV)
@@ -23200,7 +23840,7 @@ GL_PREFIX(FinalCombinerInputNV):
GL_PREFIX(GetCombinerInputParameterfvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4936(%rax), %r11
+ movq 5064(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23214,13 +23854,13 @@ GL_PREFIX(GetCombinerInputParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4936(%rax), %r11
+ movq 5064(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4936(%rax), %r11
+ movq 5064(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23234,7 +23874,7 @@ GL_PREFIX(GetCombinerInputParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4936(%rax), %r11
+ movq 5064(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetCombinerInputParameterfvNV), .-GL_PREFIX(GetCombinerInputParameterfvNV)
@@ -23245,7 +23885,7 @@ GL_PREFIX(GetCombinerInputParameterfvNV):
GL_PREFIX(GetCombinerInputParameterivNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4944(%rax), %r11
+ movq 5072(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23259,13 +23899,13 @@ GL_PREFIX(GetCombinerInputParameterivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4944(%rax), %r11
+ movq 5072(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4944(%rax), %r11
+ movq 5072(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23279,7 +23919,7 @@ GL_PREFIX(GetCombinerInputParameterivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4944(%rax), %r11
+ movq 5072(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetCombinerInputParameterivNV), .-GL_PREFIX(GetCombinerInputParameterivNV)
@@ -23290,7 +23930,7 @@ GL_PREFIX(GetCombinerInputParameterivNV):
GL_PREFIX(GetCombinerOutputParameterfvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4952(%rax), %r11
+ movq 5080(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23304,13 +23944,13 @@ GL_PREFIX(GetCombinerOutputParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4952(%rax), %r11
+ movq 5080(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4952(%rax), %r11
+ movq 5080(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23324,7 +23964,7 @@ GL_PREFIX(GetCombinerOutputParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4952(%rax), %r11
+ movq 5080(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetCombinerOutputParameterfvNV), .-GL_PREFIX(GetCombinerOutputParameterfvNV)
@@ -23335,7 +23975,7 @@ GL_PREFIX(GetCombinerOutputParameterfvNV):
GL_PREFIX(GetCombinerOutputParameterivNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4960(%rax), %r11
+ movq 5088(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23349,13 +23989,13 @@ GL_PREFIX(GetCombinerOutputParameterivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4960(%rax), %r11
+ movq 5088(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4960(%rax), %r11
+ movq 5088(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23369,7 +24009,7 @@ GL_PREFIX(GetCombinerOutputParameterivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4960(%rax), %r11
+ movq 5088(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetCombinerOutputParameterivNV), .-GL_PREFIX(GetCombinerOutputParameterivNV)
@@ -23380,7 +24020,7 @@ GL_PREFIX(GetCombinerOutputParameterivNV):
GL_PREFIX(GetFinalCombinerInputParameterfvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4968(%rax), %r11
+ movq 5096(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23390,13 +24030,13 @@ GL_PREFIX(GetFinalCombinerInputParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4968(%rax), %r11
+ movq 5096(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4968(%rax), %r11
+ movq 5096(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23406,7 +24046,7 @@ GL_PREFIX(GetFinalCombinerInputParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4968(%rax), %r11
+ movq 5096(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetFinalCombinerInputParameterfvNV), .-GL_PREFIX(GetFinalCombinerInputParameterfvNV)
@@ -23417,7 +24057,7 @@ GL_PREFIX(GetFinalCombinerInputParameterfvNV):
GL_PREFIX(GetFinalCombinerInputParameterivNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4976(%rax), %r11
+ movq 5104(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23427,13 +24067,13 @@ GL_PREFIX(GetFinalCombinerInputParameterivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4976(%rax), %r11
+ movq 5104(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4976(%rax), %r11
+ movq 5104(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23443,7 +24083,7 @@ GL_PREFIX(GetFinalCombinerInputParameterivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 4976(%rax), %r11
+ movq 5104(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetFinalCombinerInputParameterivNV), .-GL_PREFIX(GetFinalCombinerInputParameterivNV)
@@ -23454,25 +24094,25 @@ GL_PREFIX(GetFinalCombinerInputParameterivNV):
GL_PREFIX(ResizeBuffersMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4984(%rax), %r11
+ movq 5112(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rbp
call _x86_64_get_dispatch@PLT
popq %rbp
- movq 4984(%rax), %r11
+ movq 5112(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4984(%rax), %r11
+ movq 5112(%rax), %r11
jmp *%r11
1:
pushq %rbp
call _glapi_get_dispatch
popq %rbp
- movq 4984(%rax), %r11
+ movq 5112(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ResizeBuffersMESA), .-GL_PREFIX(ResizeBuffersMESA)
@@ -23483,7 +24123,7 @@ GL_PREFIX(ResizeBuffersMESA):
GL_PREFIX(WindowPos2dMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 4992(%rax), %r11
+ movq 5120(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -23493,13 +24133,13 @@ GL_PREFIX(WindowPos2dMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 4992(%rax), %r11
+ movq 5120(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 4992(%rax), %r11
+ movq 5120(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -23509,7 +24149,7 @@ GL_PREFIX(WindowPos2dMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 4992(%rax), %r11
+ movq 5120(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos2dMESA), .-GL_PREFIX(WindowPos2dMESA)
@@ -23520,25 +24160,25 @@ GL_PREFIX(WindowPos2dMESA):
GL_PREFIX(WindowPos2dvMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5000(%rax), %r11
+ movq 5128(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5000(%rax), %r11
+ movq 5128(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5000(%rax), %r11
+ movq 5128(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5000(%rax), %r11
+ movq 5128(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos2dvMESA), .-GL_PREFIX(WindowPos2dvMESA)
@@ -23549,7 +24189,7 @@ GL_PREFIX(WindowPos2dvMESA):
GL_PREFIX(WindowPos2fMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5008(%rax), %r11
+ movq 5136(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -23559,13 +24199,13 @@ GL_PREFIX(WindowPos2fMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 5008(%rax), %r11
+ movq 5136(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5008(%rax), %r11
+ movq 5136(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -23575,7 +24215,7 @@ GL_PREFIX(WindowPos2fMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 5008(%rax), %r11
+ movq 5136(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos2fMESA), .-GL_PREFIX(WindowPos2fMESA)
@@ -23586,25 +24226,25 @@ GL_PREFIX(WindowPos2fMESA):
GL_PREFIX(WindowPos2fvMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5016(%rax), %r11
+ movq 5144(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5016(%rax), %r11
+ movq 5144(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5016(%rax), %r11
+ movq 5144(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5016(%rax), %r11
+ movq 5144(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos2fvMESA), .-GL_PREFIX(WindowPos2fvMESA)
@@ -23615,7 +24255,7 @@ GL_PREFIX(WindowPos2fvMESA):
GL_PREFIX(WindowPos2iMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5024(%rax), %r11
+ movq 5152(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23625,13 +24265,13 @@ GL_PREFIX(WindowPos2iMESA):
popq %rbp
popq %rsi
popq %rdi
- movq 5024(%rax), %r11
+ movq 5152(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5024(%rax), %r11
+ movq 5152(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23641,7 +24281,7 @@ GL_PREFIX(WindowPos2iMESA):
popq %rbp
popq %rsi
popq %rdi
- movq 5024(%rax), %r11
+ movq 5152(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos2iMESA), .-GL_PREFIX(WindowPos2iMESA)
@@ -23652,25 +24292,25 @@ GL_PREFIX(WindowPos2iMESA):
GL_PREFIX(WindowPos2ivMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5032(%rax), %r11
+ movq 5160(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5032(%rax), %r11
+ movq 5160(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5032(%rax), %r11
+ movq 5160(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5032(%rax), %r11
+ movq 5160(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos2ivMESA), .-GL_PREFIX(WindowPos2ivMESA)
@@ -23681,7 +24321,7 @@ GL_PREFIX(WindowPos2ivMESA):
GL_PREFIX(WindowPos2sMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5040(%rax), %r11
+ movq 5168(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23691,13 +24331,13 @@ GL_PREFIX(WindowPos2sMESA):
popq %rbp
popq %rsi
popq %rdi
- movq 5040(%rax), %r11
+ movq 5168(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5040(%rax), %r11
+ movq 5168(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23707,7 +24347,7 @@ GL_PREFIX(WindowPos2sMESA):
popq %rbp
popq %rsi
popq %rdi
- movq 5040(%rax), %r11
+ movq 5168(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos2sMESA), .-GL_PREFIX(WindowPos2sMESA)
@@ -23718,25 +24358,25 @@ GL_PREFIX(WindowPos2sMESA):
GL_PREFIX(WindowPos2svMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5048(%rax), %r11
+ movq 5176(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5048(%rax), %r11
+ movq 5176(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5048(%rax), %r11
+ movq 5176(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5048(%rax), %r11
+ movq 5176(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos2svMESA), .-GL_PREFIX(WindowPos2svMESA)
@@ -23747,7 +24387,7 @@ GL_PREFIX(WindowPos2svMESA):
GL_PREFIX(WindowPos3dMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5056(%rax), %r11
+ movq 5184(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -23759,13 +24399,13 @@ GL_PREFIX(WindowPos3dMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 5056(%rax), %r11
+ movq 5184(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5056(%rax), %r11
+ movq 5184(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -23777,7 +24417,7 @@ GL_PREFIX(WindowPos3dMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 5056(%rax), %r11
+ movq 5184(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos3dMESA), .-GL_PREFIX(WindowPos3dMESA)
@@ -23788,25 +24428,25 @@ GL_PREFIX(WindowPos3dMESA):
GL_PREFIX(WindowPos3dvMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5064(%rax), %r11
+ movq 5192(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5064(%rax), %r11
+ movq 5192(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5064(%rax), %r11
+ movq 5192(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5064(%rax), %r11
+ movq 5192(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos3dvMESA), .-GL_PREFIX(WindowPos3dvMESA)
@@ -23817,7 +24457,7 @@ GL_PREFIX(WindowPos3dvMESA):
GL_PREFIX(WindowPos3fMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5072(%rax), %r11
+ movq 5200(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -23829,13 +24469,13 @@ GL_PREFIX(WindowPos3fMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 5072(%rax), %r11
+ movq 5200(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5072(%rax), %r11
+ movq 5200(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -23847,7 +24487,7 @@ GL_PREFIX(WindowPos3fMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $24, %rsp
- movq 5072(%rax), %r11
+ movq 5200(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos3fMESA), .-GL_PREFIX(WindowPos3fMESA)
@@ -23858,25 +24498,25 @@ GL_PREFIX(WindowPos3fMESA):
GL_PREFIX(WindowPos3fvMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5080(%rax), %r11
+ movq 5208(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5080(%rax), %r11
+ movq 5208(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5080(%rax), %r11
+ movq 5208(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5080(%rax), %r11
+ movq 5208(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos3fvMESA), .-GL_PREFIX(WindowPos3fvMESA)
@@ -23887,7 +24527,7 @@ GL_PREFIX(WindowPos3fvMESA):
GL_PREFIX(WindowPos3iMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5088(%rax), %r11
+ movq 5216(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23897,13 +24537,13 @@ GL_PREFIX(WindowPos3iMESA):
popq %rdx
popq %rsi
popq %rdi
- movq 5088(%rax), %r11
+ movq 5216(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5088(%rax), %r11
+ movq 5216(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23913,7 +24553,7 @@ GL_PREFIX(WindowPos3iMESA):
popq %rdx
popq %rsi
popq %rdi
- movq 5088(%rax), %r11
+ movq 5216(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos3iMESA), .-GL_PREFIX(WindowPos3iMESA)
@@ -23924,25 +24564,25 @@ GL_PREFIX(WindowPos3iMESA):
GL_PREFIX(WindowPos3ivMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5096(%rax), %r11
+ movq 5224(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5096(%rax), %r11
+ movq 5224(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5096(%rax), %r11
+ movq 5224(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5096(%rax), %r11
+ movq 5224(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos3ivMESA), .-GL_PREFIX(WindowPos3ivMESA)
@@ -23953,7 +24593,7 @@ GL_PREFIX(WindowPos3ivMESA):
GL_PREFIX(WindowPos3sMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5104(%rax), %r11
+ movq 5232(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -23963,13 +24603,13 @@ GL_PREFIX(WindowPos3sMESA):
popq %rdx
popq %rsi
popq %rdi
- movq 5104(%rax), %r11
+ movq 5232(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5104(%rax), %r11
+ movq 5232(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -23979,7 +24619,7 @@ GL_PREFIX(WindowPos3sMESA):
popq %rdx
popq %rsi
popq %rdi
- movq 5104(%rax), %r11
+ movq 5232(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos3sMESA), .-GL_PREFIX(WindowPos3sMESA)
@@ -23990,25 +24630,25 @@ GL_PREFIX(WindowPos3sMESA):
GL_PREFIX(WindowPos3svMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5112(%rax), %r11
+ movq 5240(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5112(%rax), %r11
+ movq 5240(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5112(%rax), %r11
+ movq 5240(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5112(%rax), %r11
+ movq 5240(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos3svMESA), .-GL_PREFIX(WindowPos3svMESA)
@@ -24019,7 +24659,7 @@ GL_PREFIX(WindowPos3svMESA):
GL_PREFIX(WindowPos4dMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5120(%rax), %r11
+ movq 5248(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $40, %rsp
@@ -24033,13 +24673,13 @@ GL_PREFIX(WindowPos4dMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $40, %rsp
- movq 5120(%rax), %r11
+ movq 5248(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5120(%rax), %r11
+ movq 5248(%rax), %r11
jmp *%r11
1:
subq $40, %rsp
@@ -24053,7 +24693,7 @@ GL_PREFIX(WindowPos4dMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $40, %rsp
- movq 5120(%rax), %r11
+ movq 5248(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos4dMESA), .-GL_PREFIX(WindowPos4dMESA)
@@ -24064,25 +24704,25 @@ GL_PREFIX(WindowPos4dMESA):
GL_PREFIX(WindowPos4dvMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5128(%rax), %r11
+ movq 5256(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5128(%rax), %r11
+ movq 5256(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5128(%rax), %r11
+ movq 5256(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5128(%rax), %r11
+ movq 5256(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos4dvMESA), .-GL_PREFIX(WindowPos4dvMESA)
@@ -24093,7 +24733,7 @@ GL_PREFIX(WindowPos4dvMESA):
GL_PREFIX(WindowPos4fMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5136(%rax), %r11
+ movq 5264(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $40, %rsp
@@ -24107,13 +24747,13 @@ GL_PREFIX(WindowPos4fMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $40, %rsp
- movq 5136(%rax), %r11
+ movq 5264(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5136(%rax), %r11
+ movq 5264(%rax), %r11
jmp *%r11
1:
subq $40, %rsp
@@ -24127,7 +24767,7 @@ GL_PREFIX(WindowPos4fMESA):
movq 8(%rsp), %xmm1
movq (%rsp), %xmm0
addq $40, %rsp
- movq 5136(%rax), %r11
+ movq 5264(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos4fMESA), .-GL_PREFIX(WindowPos4fMESA)
@@ -24138,25 +24778,25 @@ GL_PREFIX(WindowPos4fMESA):
GL_PREFIX(WindowPos4fvMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5144(%rax), %r11
+ movq 5272(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5144(%rax), %r11
+ movq 5272(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5144(%rax), %r11
+ movq 5272(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5144(%rax), %r11
+ movq 5272(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos4fvMESA), .-GL_PREFIX(WindowPos4fvMESA)
@@ -24167,7 +24807,7 @@ GL_PREFIX(WindowPos4fvMESA):
GL_PREFIX(WindowPos4iMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5152(%rax), %r11
+ movq 5280(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24181,13 +24821,13 @@ GL_PREFIX(WindowPos4iMESA):
popq %rdx
popq %rsi
popq %rdi
- movq 5152(%rax), %r11
+ movq 5280(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5152(%rax), %r11
+ movq 5280(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24201,7 +24841,7 @@ GL_PREFIX(WindowPos4iMESA):
popq %rdx
popq %rsi
popq %rdi
- movq 5152(%rax), %r11
+ movq 5280(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos4iMESA), .-GL_PREFIX(WindowPos4iMESA)
@@ -24212,25 +24852,25 @@ GL_PREFIX(WindowPos4iMESA):
GL_PREFIX(WindowPos4ivMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5160(%rax), %r11
+ movq 5288(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5160(%rax), %r11
+ movq 5288(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5160(%rax), %r11
+ movq 5288(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5160(%rax), %r11
+ movq 5288(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos4ivMESA), .-GL_PREFIX(WindowPos4ivMESA)
@@ -24241,7 +24881,7 @@ GL_PREFIX(WindowPos4ivMESA):
GL_PREFIX(WindowPos4sMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5168(%rax), %r11
+ movq 5296(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24255,13 +24895,13 @@ GL_PREFIX(WindowPos4sMESA):
popq %rdx
popq %rsi
popq %rdi
- movq 5168(%rax), %r11
+ movq 5296(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5168(%rax), %r11
+ movq 5296(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24275,7 +24915,7 @@ GL_PREFIX(WindowPos4sMESA):
popq %rdx
popq %rsi
popq %rdi
- movq 5168(%rax), %r11
+ movq 5296(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos4sMESA), .-GL_PREFIX(WindowPos4sMESA)
@@ -24286,37 +24926,37 @@ GL_PREFIX(WindowPos4sMESA):
GL_PREFIX(WindowPos4svMESA):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5176(%rax), %r11
+ movq 5304(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5176(%rax), %r11
+ movq 5304(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5176(%rax), %r11
+ movq 5304(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5176(%rax), %r11
+ movq 5304(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(WindowPos4svMESA), .-GL_PREFIX(WindowPos4svMESA)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_648)
- .type GL_PREFIX(_dispatch_stub_648), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_648))
-GL_PREFIX(_dispatch_stub_648):
+ .globl GL_PREFIX(_dispatch_stub_664)
+ .type GL_PREFIX(_dispatch_stub_664), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_664))
+GL_PREFIX(_dispatch_stub_664):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5184(%rax), %r11
+ movq 5312(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24330,13 +24970,13 @@ GL_PREFIX(_dispatch_stub_648):
popq %rdx
popq %rsi
popq %rdi
- movq 5184(%rax), %r11
+ movq 5312(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5184(%rax), %r11
+ movq 5312(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24350,19 +24990,19 @@ GL_PREFIX(_dispatch_stub_648):
popq %rdx
popq %rsi
popq %rdi
- movq 5184(%rax), %r11
+ movq 5312(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_648), .-GL_PREFIX(_dispatch_stub_648)
+ .size GL_PREFIX(_dispatch_stub_664), .-GL_PREFIX(_dispatch_stub_664)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_649)
- .type GL_PREFIX(_dispatch_stub_649), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_649))
-GL_PREFIX(_dispatch_stub_649):
+ .globl GL_PREFIX(_dispatch_stub_665)
+ .type GL_PREFIX(_dispatch_stub_665), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_665))
+GL_PREFIX(_dispatch_stub_665):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5192(%rax), %r11
+ movq 5320(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24380,13 +25020,13 @@ GL_PREFIX(_dispatch_stub_649):
popq %rdx
popq %rsi
popq %rdi
- movq 5192(%rax), %r11
+ movq 5320(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5192(%rax), %r11
+ movq 5320(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24404,19 +25044,19 @@ GL_PREFIX(_dispatch_stub_649):
popq %rdx
popq %rsi
popq %rdi
- movq 5192(%rax), %r11
+ movq 5320(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_649), .-GL_PREFIX(_dispatch_stub_649)
+ .size GL_PREFIX(_dispatch_stub_665), .-GL_PREFIX(_dispatch_stub_665)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_650)
- .type GL_PREFIX(_dispatch_stub_650), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_650))
-GL_PREFIX(_dispatch_stub_650):
+ .globl GL_PREFIX(_dispatch_stub_666)
+ .type GL_PREFIX(_dispatch_stub_666), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_666))
+GL_PREFIX(_dispatch_stub_666):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5200(%rax), %r11
+ movq 5328(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24426,13 +25066,13 @@ GL_PREFIX(_dispatch_stub_650):
popq %rbp
popq %rsi
popq %rdi
- movq 5200(%rax), %r11
+ movq 5328(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5200(%rax), %r11
+ movq 5328(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24442,49 +25082,49 @@ GL_PREFIX(_dispatch_stub_650):
popq %rbp
popq %rsi
popq %rdi
- movq 5200(%rax), %r11
+ movq 5328(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_650), .-GL_PREFIX(_dispatch_stub_650)
+ .size GL_PREFIX(_dispatch_stub_666), .-GL_PREFIX(_dispatch_stub_666)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_651)
- .type GL_PREFIX(_dispatch_stub_651), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_651))
-GL_PREFIX(_dispatch_stub_651):
+ .globl GL_PREFIX(_dispatch_stub_667)
+ .type GL_PREFIX(_dispatch_stub_667), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_667))
+GL_PREFIX(_dispatch_stub_667):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5208(%rax), %r11
+ movq 5336(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5208(%rax), %r11
+ movq 5336(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5208(%rax), %r11
+ movq 5336(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5208(%rax), %r11
+ movq 5336(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_651), .-GL_PREFIX(_dispatch_stub_651)
+ .size GL_PREFIX(_dispatch_stub_667), .-GL_PREFIX(_dispatch_stub_667)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_652)
- .type GL_PREFIX(_dispatch_stub_652), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_652))
-GL_PREFIX(_dispatch_stub_652):
+ .globl GL_PREFIX(_dispatch_stub_668)
+ .type GL_PREFIX(_dispatch_stub_668), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_668))
+GL_PREFIX(_dispatch_stub_668):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5216(%rax), %r11
+ movq 5344(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24494,13 +25134,13 @@ GL_PREFIX(_dispatch_stub_652):
popq %rbp
popq %rsi
popq %rdi
- movq 5216(%rax), %r11
+ movq 5344(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5216(%rax), %r11
+ movq 5344(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24510,19 +25150,19 @@ GL_PREFIX(_dispatch_stub_652):
popq %rbp
popq %rsi
popq %rdi
- movq 5216(%rax), %r11
+ movq 5344(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_652), .-GL_PREFIX(_dispatch_stub_652)
+ .size GL_PREFIX(_dispatch_stub_668), .-GL_PREFIX(_dispatch_stub_668)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_653)
- .type GL_PREFIX(_dispatch_stub_653), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_653))
-GL_PREFIX(_dispatch_stub_653):
+ .globl GL_PREFIX(_dispatch_stub_669)
+ .type GL_PREFIX(_dispatch_stub_669), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_669))
+GL_PREFIX(_dispatch_stub_669):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5224(%rax), %r11
+ movq 5352(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24532,13 +25172,13 @@ GL_PREFIX(_dispatch_stub_653):
popq %rdx
popq %rsi
popq %rdi
- movq 5224(%rax), %r11
+ movq 5352(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5224(%rax), %r11
+ movq 5352(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24548,49 +25188,49 @@ GL_PREFIX(_dispatch_stub_653):
popq %rdx
popq %rsi
popq %rdi
- movq 5224(%rax), %r11
+ movq 5352(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_653), .-GL_PREFIX(_dispatch_stub_653)
+ .size GL_PREFIX(_dispatch_stub_669), .-GL_PREFIX(_dispatch_stub_669)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_654)
- .type GL_PREFIX(_dispatch_stub_654), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_654))
-GL_PREFIX(_dispatch_stub_654):
+ .globl GL_PREFIX(_dispatch_stub_670)
+ .type GL_PREFIX(_dispatch_stub_670), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_670))
+GL_PREFIX(_dispatch_stub_670):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5232(%rax), %r11
+ movq 5360(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5232(%rax), %r11
+ movq 5360(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5232(%rax), %r11
+ movq 5360(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5232(%rax), %r11
+ movq 5360(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_654), .-GL_PREFIX(_dispatch_stub_654)
+ .size GL_PREFIX(_dispatch_stub_670), .-GL_PREFIX(_dispatch_stub_670)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_655)
- .type GL_PREFIX(_dispatch_stub_655), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_655))
-GL_PREFIX(_dispatch_stub_655):
+ .globl GL_PREFIX(_dispatch_stub_671)
+ .type GL_PREFIX(_dispatch_stub_671), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_671))
+GL_PREFIX(_dispatch_stub_671):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5240(%rax), %r11
+ movq 5368(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24600,13 +25240,13 @@ GL_PREFIX(_dispatch_stub_655):
popq %rbp
popq %rsi
popq %rdi
- movq 5240(%rax), %r11
+ movq 5368(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5240(%rax), %r11
+ movq 5368(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24616,40 +25256,40 @@ GL_PREFIX(_dispatch_stub_655):
popq %rbp
popq %rsi
popq %rdi
- movq 5240(%rax), %r11
+ movq 5368(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_655), .-GL_PREFIX(_dispatch_stub_655)
+ .size GL_PREFIX(_dispatch_stub_671), .-GL_PREFIX(_dispatch_stub_671)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_656)
- .type GL_PREFIX(_dispatch_stub_656), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_656))
-GL_PREFIX(_dispatch_stub_656):
+ .globl GL_PREFIX(_dispatch_stub_672)
+ .type GL_PREFIX(_dispatch_stub_672), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_672))
+GL_PREFIX(_dispatch_stub_672):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5248(%rax), %r11
+ movq 5376(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5248(%rax), %r11
+ movq 5376(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5248(%rax), %r11
+ movq 5376(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5248(%rax), %r11
+ movq 5376(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_656), .-GL_PREFIX(_dispatch_stub_656)
+ .size GL_PREFIX(_dispatch_stub_672), .-GL_PREFIX(_dispatch_stub_672)
.p2align 4,,15
.globl GL_PREFIX(AreProgramsResidentNV)
@@ -24657,7 +25297,7 @@ GL_PREFIX(_dispatch_stub_656):
GL_PREFIX(AreProgramsResidentNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5256(%rax), %r11
+ movq 5384(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24667,13 +25307,13 @@ GL_PREFIX(AreProgramsResidentNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5256(%rax), %r11
+ movq 5384(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5256(%rax), %r11
+ movq 5384(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24683,7 +25323,7 @@ GL_PREFIX(AreProgramsResidentNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5256(%rax), %r11
+ movq 5384(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(AreProgramsResidentNV), .-GL_PREFIX(AreProgramsResidentNV)
@@ -24694,7 +25334,7 @@ GL_PREFIX(AreProgramsResidentNV):
GL_PREFIX(BindProgramNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5264(%rax), %r11
+ movq 5392(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24704,13 +25344,13 @@ GL_PREFIX(BindProgramNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5264(%rax), %r11
+ movq 5392(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5264(%rax), %r11
+ movq 5392(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24720,7 +25360,7 @@ GL_PREFIX(BindProgramNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5264(%rax), %r11
+ movq 5392(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(BindProgramNV), .-GL_PREFIX(BindProgramNV)
@@ -24731,7 +25371,7 @@ GL_PREFIX(BindProgramNV):
GL_PREFIX(DeleteProgramsNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5272(%rax), %r11
+ movq 5400(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24741,13 +25381,13 @@ GL_PREFIX(DeleteProgramsNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5272(%rax), %r11
+ movq 5400(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5272(%rax), %r11
+ movq 5400(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24757,7 +25397,7 @@ GL_PREFIX(DeleteProgramsNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5272(%rax), %r11
+ movq 5400(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(DeleteProgramsNV), .-GL_PREFIX(DeleteProgramsNV)
@@ -24768,7 +25408,7 @@ GL_PREFIX(DeleteProgramsNV):
GL_PREFIX(ExecuteProgramNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5280(%rax), %r11
+ movq 5408(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24778,13 +25418,13 @@ GL_PREFIX(ExecuteProgramNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5280(%rax), %r11
+ movq 5408(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5280(%rax), %r11
+ movq 5408(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24794,7 +25434,7 @@ GL_PREFIX(ExecuteProgramNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5280(%rax), %r11
+ movq 5408(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ExecuteProgramNV), .-GL_PREFIX(ExecuteProgramNV)
@@ -24805,7 +25445,7 @@ GL_PREFIX(ExecuteProgramNV):
GL_PREFIX(GenProgramsNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5288(%rax), %r11
+ movq 5416(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24815,13 +25455,13 @@ GL_PREFIX(GenProgramsNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5288(%rax), %r11
+ movq 5416(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5288(%rax), %r11
+ movq 5416(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24831,7 +25471,7 @@ GL_PREFIX(GenProgramsNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5288(%rax), %r11
+ movq 5416(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GenProgramsNV), .-GL_PREFIX(GenProgramsNV)
@@ -24842,7 +25482,7 @@ GL_PREFIX(GenProgramsNV):
GL_PREFIX(GetProgramParameterdvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5296(%rax), %r11
+ movq 5424(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24856,13 +25496,13 @@ GL_PREFIX(GetProgramParameterdvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5296(%rax), %r11
+ movq 5424(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5296(%rax), %r11
+ movq 5424(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24876,7 +25516,7 @@ GL_PREFIX(GetProgramParameterdvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5296(%rax), %r11
+ movq 5424(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetProgramParameterdvNV), .-GL_PREFIX(GetProgramParameterdvNV)
@@ -24887,7 +25527,7 @@ GL_PREFIX(GetProgramParameterdvNV):
GL_PREFIX(GetProgramParameterfvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5304(%rax), %r11
+ movq 5432(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24901,13 +25541,13 @@ GL_PREFIX(GetProgramParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5304(%rax), %r11
+ movq 5432(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5304(%rax), %r11
+ movq 5432(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24921,7 +25561,7 @@ GL_PREFIX(GetProgramParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5304(%rax), %r11
+ movq 5432(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetProgramParameterfvNV), .-GL_PREFIX(GetProgramParameterfvNV)
@@ -24932,7 +25572,7 @@ GL_PREFIX(GetProgramParameterfvNV):
GL_PREFIX(GetProgramStringNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5312(%rax), %r11
+ movq 5440(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24942,13 +25582,13 @@ GL_PREFIX(GetProgramStringNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5312(%rax), %r11
+ movq 5440(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5312(%rax), %r11
+ movq 5440(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24958,7 +25598,7 @@ GL_PREFIX(GetProgramStringNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5312(%rax), %r11
+ movq 5440(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetProgramStringNV), .-GL_PREFIX(GetProgramStringNV)
@@ -24969,7 +25609,7 @@ GL_PREFIX(GetProgramStringNV):
GL_PREFIX(GetProgramivNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5320(%rax), %r11
+ movq 5448(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -24979,13 +25619,13 @@ GL_PREFIX(GetProgramivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5320(%rax), %r11
+ movq 5448(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5320(%rax), %r11
+ movq 5448(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -24995,7 +25635,7 @@ GL_PREFIX(GetProgramivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5320(%rax), %r11
+ movq 5448(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetProgramivNV), .-GL_PREFIX(GetProgramivNV)
@@ -25006,7 +25646,7 @@ GL_PREFIX(GetProgramivNV):
GL_PREFIX(GetTrackMatrixivNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5328(%rax), %r11
+ movq 5456(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25020,13 +25660,13 @@ GL_PREFIX(GetTrackMatrixivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5328(%rax), %r11
+ movq 5456(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5328(%rax), %r11
+ movq 5456(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25040,7 +25680,7 @@ GL_PREFIX(GetTrackMatrixivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5328(%rax), %r11
+ movq 5456(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetTrackMatrixivNV), .-GL_PREFIX(GetTrackMatrixivNV)
@@ -25051,7 +25691,7 @@ GL_PREFIX(GetTrackMatrixivNV):
GL_PREFIX(GetVertexAttribPointervNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5336(%rax), %r11
+ movq 5464(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25061,13 +25701,13 @@ GL_PREFIX(GetVertexAttribPointervNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5336(%rax), %r11
+ movq 5464(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5336(%rax), %r11
+ movq 5464(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25077,7 +25717,7 @@ GL_PREFIX(GetVertexAttribPointervNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5336(%rax), %r11
+ movq 5464(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetVertexAttribPointervNV), .-GL_PREFIX(GetVertexAttribPointervNV)
@@ -25088,7 +25728,7 @@ GL_PREFIX(GetVertexAttribPointervNV):
GL_PREFIX(GetVertexAttribdvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5344(%rax), %r11
+ movq 5472(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25098,13 +25738,13 @@ GL_PREFIX(GetVertexAttribdvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5344(%rax), %r11
+ movq 5472(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5344(%rax), %r11
+ movq 5472(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25114,7 +25754,7 @@ GL_PREFIX(GetVertexAttribdvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5344(%rax), %r11
+ movq 5472(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetVertexAttribdvNV), .-GL_PREFIX(GetVertexAttribdvNV)
@@ -25125,7 +25765,7 @@ GL_PREFIX(GetVertexAttribdvNV):
GL_PREFIX(GetVertexAttribfvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5352(%rax), %r11
+ movq 5480(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25135,13 +25775,13 @@ GL_PREFIX(GetVertexAttribfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5352(%rax), %r11
+ movq 5480(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5352(%rax), %r11
+ movq 5480(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25151,7 +25791,7 @@ GL_PREFIX(GetVertexAttribfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5352(%rax), %r11
+ movq 5480(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetVertexAttribfvNV), .-GL_PREFIX(GetVertexAttribfvNV)
@@ -25162,7 +25802,7 @@ GL_PREFIX(GetVertexAttribfvNV):
GL_PREFIX(GetVertexAttribivNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5360(%rax), %r11
+ movq 5488(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25172,13 +25812,13 @@ GL_PREFIX(GetVertexAttribivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5360(%rax), %r11
+ movq 5488(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5360(%rax), %r11
+ movq 5488(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25188,7 +25828,7 @@ GL_PREFIX(GetVertexAttribivNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5360(%rax), %r11
+ movq 5488(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetVertexAttribivNV), .-GL_PREFIX(GetVertexAttribivNV)
@@ -25199,25 +25839,25 @@ GL_PREFIX(GetVertexAttribivNV):
GL_PREFIX(IsProgramNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5368(%rax), %r11
+ movq 5496(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5368(%rax), %r11
+ movq 5496(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5368(%rax), %r11
+ movq 5496(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5368(%rax), %r11
+ movq 5496(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(IsProgramNV), .-GL_PREFIX(IsProgramNV)
@@ -25228,7 +25868,7 @@ GL_PREFIX(IsProgramNV):
GL_PREFIX(LoadProgramNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5376(%rax), %r11
+ movq 5504(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25242,13 +25882,13 @@ GL_PREFIX(LoadProgramNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5376(%rax), %r11
+ movq 5504(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5376(%rax), %r11
+ movq 5504(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25262,7 +25902,7 @@ GL_PREFIX(LoadProgramNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5376(%rax), %r11
+ movq 5504(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(LoadProgramNV), .-GL_PREFIX(LoadProgramNV)
@@ -25273,7 +25913,7 @@ GL_PREFIX(LoadProgramNV):
GL_PREFIX(ProgramParameters4dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5384(%rax), %r11
+ movq 5512(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25287,13 +25927,13 @@ GL_PREFIX(ProgramParameters4dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5384(%rax), %r11
+ movq 5512(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5384(%rax), %r11
+ movq 5512(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25307,7 +25947,7 @@ GL_PREFIX(ProgramParameters4dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5384(%rax), %r11
+ movq 5512(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ProgramParameters4dvNV), .-GL_PREFIX(ProgramParameters4dvNV)
@@ -25318,7 +25958,7 @@ GL_PREFIX(ProgramParameters4dvNV):
GL_PREFIX(ProgramParameters4fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5392(%rax), %r11
+ movq 5520(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25332,13 +25972,13 @@ GL_PREFIX(ProgramParameters4fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5392(%rax), %r11
+ movq 5520(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5392(%rax), %r11
+ movq 5520(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25352,7 +25992,7 @@ GL_PREFIX(ProgramParameters4fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5392(%rax), %r11
+ movq 5520(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ProgramParameters4fvNV), .-GL_PREFIX(ProgramParameters4fvNV)
@@ -25363,7 +26003,7 @@ GL_PREFIX(ProgramParameters4fvNV):
GL_PREFIX(RequestResidentProgramsNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5400(%rax), %r11
+ movq 5528(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25373,13 +26013,13 @@ GL_PREFIX(RequestResidentProgramsNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5400(%rax), %r11
+ movq 5528(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5400(%rax), %r11
+ movq 5528(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25389,7 +26029,7 @@ GL_PREFIX(RequestResidentProgramsNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5400(%rax), %r11
+ movq 5528(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(RequestResidentProgramsNV), .-GL_PREFIX(RequestResidentProgramsNV)
@@ -25400,7 +26040,7 @@ GL_PREFIX(RequestResidentProgramsNV):
GL_PREFIX(TrackMatrixNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5408(%rax), %r11
+ movq 5536(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25414,13 +26054,13 @@ GL_PREFIX(TrackMatrixNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5408(%rax), %r11
+ movq 5536(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5408(%rax), %r11
+ movq 5536(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25434,7 +26074,7 @@ GL_PREFIX(TrackMatrixNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5408(%rax), %r11
+ movq 5536(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(TrackMatrixNV), .-GL_PREFIX(TrackMatrixNV)
@@ -25445,7 +26085,7 @@ GL_PREFIX(TrackMatrixNV):
GL_PREFIX(VertexAttrib1dNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5416(%rax), %r11
+ movq 5544(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -25455,13 +26095,13 @@ GL_PREFIX(VertexAttrib1dNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 5416(%rax), %r11
+ movq 5544(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5416(%rax), %r11
+ movq 5544(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -25471,7 +26111,7 @@ GL_PREFIX(VertexAttrib1dNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 5416(%rax), %r11
+ movq 5544(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib1dNV), .-GL_PREFIX(VertexAttrib1dNV)
@@ -25482,7 +26122,7 @@ GL_PREFIX(VertexAttrib1dNV):
GL_PREFIX(VertexAttrib1dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5424(%rax), %r11
+ movq 5552(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25492,13 +26132,13 @@ GL_PREFIX(VertexAttrib1dvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5424(%rax), %r11
+ movq 5552(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5424(%rax), %r11
+ movq 5552(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25508,7 +26148,7 @@ GL_PREFIX(VertexAttrib1dvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5424(%rax), %r11
+ movq 5552(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib1dvNV), .-GL_PREFIX(VertexAttrib1dvNV)
@@ -25519,7 +26159,7 @@ GL_PREFIX(VertexAttrib1dvNV):
GL_PREFIX(VertexAttrib1fNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5432(%rax), %r11
+ movq 5560(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -25529,13 +26169,13 @@ GL_PREFIX(VertexAttrib1fNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 5432(%rax), %r11
+ movq 5560(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5432(%rax), %r11
+ movq 5560(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -25545,7 +26185,7 @@ GL_PREFIX(VertexAttrib1fNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 5432(%rax), %r11
+ movq 5560(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib1fNV), .-GL_PREFIX(VertexAttrib1fNV)
@@ -25556,7 +26196,7 @@ GL_PREFIX(VertexAttrib1fNV):
GL_PREFIX(VertexAttrib1fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5440(%rax), %r11
+ movq 5568(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25566,13 +26206,13 @@ GL_PREFIX(VertexAttrib1fvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5440(%rax), %r11
+ movq 5568(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5440(%rax), %r11
+ movq 5568(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25582,7 +26222,7 @@ GL_PREFIX(VertexAttrib1fvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5440(%rax), %r11
+ movq 5568(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib1fvNV), .-GL_PREFIX(VertexAttrib1fvNV)
@@ -25593,7 +26233,7 @@ GL_PREFIX(VertexAttrib1fvNV):
GL_PREFIX(VertexAttrib1sNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5448(%rax), %r11
+ movq 5576(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25603,13 +26243,13 @@ GL_PREFIX(VertexAttrib1sNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5448(%rax), %r11
+ movq 5576(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5448(%rax), %r11
+ movq 5576(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25619,7 +26259,7 @@ GL_PREFIX(VertexAttrib1sNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5448(%rax), %r11
+ movq 5576(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib1sNV), .-GL_PREFIX(VertexAttrib1sNV)
@@ -25630,7 +26270,7 @@ GL_PREFIX(VertexAttrib1sNV):
GL_PREFIX(VertexAttrib1svNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5456(%rax), %r11
+ movq 5584(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25640,13 +26280,13 @@ GL_PREFIX(VertexAttrib1svNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5456(%rax), %r11
+ movq 5584(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5456(%rax), %r11
+ movq 5584(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25656,7 +26296,7 @@ GL_PREFIX(VertexAttrib1svNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5456(%rax), %r11
+ movq 5584(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib1svNV), .-GL_PREFIX(VertexAttrib1svNV)
@@ -25667,7 +26307,7 @@ GL_PREFIX(VertexAttrib1svNV):
GL_PREFIX(VertexAttrib2dNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5464(%rax), %r11
+ movq 5592(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -25679,13 +26319,13 @@ GL_PREFIX(VertexAttrib2dNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 5464(%rax), %r11
+ movq 5592(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5464(%rax), %r11
+ movq 5592(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -25697,7 +26337,7 @@ GL_PREFIX(VertexAttrib2dNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 5464(%rax), %r11
+ movq 5592(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib2dNV), .-GL_PREFIX(VertexAttrib2dNV)
@@ -25708,7 +26348,7 @@ GL_PREFIX(VertexAttrib2dNV):
GL_PREFIX(VertexAttrib2dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5472(%rax), %r11
+ movq 5600(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25718,13 +26358,13 @@ GL_PREFIX(VertexAttrib2dvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5472(%rax), %r11
+ movq 5600(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5472(%rax), %r11
+ movq 5600(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25734,7 +26374,7 @@ GL_PREFIX(VertexAttrib2dvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5472(%rax), %r11
+ movq 5600(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib2dvNV), .-GL_PREFIX(VertexAttrib2dvNV)
@@ -25745,7 +26385,7 @@ GL_PREFIX(VertexAttrib2dvNV):
GL_PREFIX(VertexAttrib2fNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5480(%rax), %r11
+ movq 5608(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $24, %rsp
@@ -25757,13 +26397,13 @@ GL_PREFIX(VertexAttrib2fNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 5480(%rax), %r11
+ movq 5608(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5480(%rax), %r11
+ movq 5608(%rax), %r11
jmp *%r11
1:
subq $24, %rsp
@@ -25775,7 +26415,7 @@ GL_PREFIX(VertexAttrib2fNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $24, %rsp
- movq 5480(%rax), %r11
+ movq 5608(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib2fNV), .-GL_PREFIX(VertexAttrib2fNV)
@@ -25786,7 +26426,7 @@ GL_PREFIX(VertexAttrib2fNV):
GL_PREFIX(VertexAttrib2fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5488(%rax), %r11
+ movq 5616(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25796,13 +26436,13 @@ GL_PREFIX(VertexAttrib2fvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5488(%rax), %r11
+ movq 5616(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5488(%rax), %r11
+ movq 5616(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25812,7 +26452,7 @@ GL_PREFIX(VertexAttrib2fvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5488(%rax), %r11
+ movq 5616(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib2fvNV), .-GL_PREFIX(VertexAttrib2fvNV)
@@ -25823,7 +26463,7 @@ GL_PREFIX(VertexAttrib2fvNV):
GL_PREFIX(VertexAttrib2sNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5496(%rax), %r11
+ movq 5624(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25833,13 +26473,13 @@ GL_PREFIX(VertexAttrib2sNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5496(%rax), %r11
+ movq 5624(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5496(%rax), %r11
+ movq 5624(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25849,7 +26489,7 @@ GL_PREFIX(VertexAttrib2sNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5496(%rax), %r11
+ movq 5624(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib2sNV), .-GL_PREFIX(VertexAttrib2sNV)
@@ -25860,7 +26500,7 @@ GL_PREFIX(VertexAttrib2sNV):
GL_PREFIX(VertexAttrib2svNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5504(%rax), %r11
+ movq 5632(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25870,13 +26510,13 @@ GL_PREFIX(VertexAttrib2svNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5504(%rax), %r11
+ movq 5632(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5504(%rax), %r11
+ movq 5632(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25886,7 +26526,7 @@ GL_PREFIX(VertexAttrib2svNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5504(%rax), %r11
+ movq 5632(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib2svNV), .-GL_PREFIX(VertexAttrib2svNV)
@@ -25897,7 +26537,7 @@ GL_PREFIX(VertexAttrib2svNV):
GL_PREFIX(VertexAttrib3dNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5512(%rax), %r11
+ movq 5640(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $40, %rsp
@@ -25911,13 +26551,13 @@ GL_PREFIX(VertexAttrib3dNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $40, %rsp
- movq 5512(%rax), %r11
+ movq 5640(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5512(%rax), %r11
+ movq 5640(%rax), %r11
jmp *%r11
1:
subq $40, %rsp
@@ -25931,7 +26571,7 @@ GL_PREFIX(VertexAttrib3dNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $40, %rsp
- movq 5512(%rax), %r11
+ movq 5640(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib3dNV), .-GL_PREFIX(VertexAttrib3dNV)
@@ -25942,7 +26582,7 @@ GL_PREFIX(VertexAttrib3dNV):
GL_PREFIX(VertexAttrib3dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5520(%rax), %r11
+ movq 5648(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -25952,13 +26592,13 @@ GL_PREFIX(VertexAttrib3dvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5520(%rax), %r11
+ movq 5648(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5520(%rax), %r11
+ movq 5648(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -25968,7 +26608,7 @@ GL_PREFIX(VertexAttrib3dvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5520(%rax), %r11
+ movq 5648(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib3dvNV), .-GL_PREFIX(VertexAttrib3dvNV)
@@ -25979,7 +26619,7 @@ GL_PREFIX(VertexAttrib3dvNV):
GL_PREFIX(VertexAttrib3fNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5528(%rax), %r11
+ movq 5656(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $40, %rsp
@@ -25993,13 +26633,13 @@ GL_PREFIX(VertexAttrib3fNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $40, %rsp
- movq 5528(%rax), %r11
+ movq 5656(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5528(%rax), %r11
+ movq 5656(%rax), %r11
jmp *%r11
1:
subq $40, %rsp
@@ -26013,7 +26653,7 @@ GL_PREFIX(VertexAttrib3fNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $40, %rsp
- movq 5528(%rax), %r11
+ movq 5656(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib3fNV), .-GL_PREFIX(VertexAttrib3fNV)
@@ -26024,7 +26664,7 @@ GL_PREFIX(VertexAttrib3fNV):
GL_PREFIX(VertexAttrib3fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5536(%rax), %r11
+ movq 5664(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26034,13 +26674,13 @@ GL_PREFIX(VertexAttrib3fvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5536(%rax), %r11
+ movq 5664(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5536(%rax), %r11
+ movq 5664(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26050,7 +26690,7 @@ GL_PREFIX(VertexAttrib3fvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5536(%rax), %r11
+ movq 5664(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib3fvNV), .-GL_PREFIX(VertexAttrib3fvNV)
@@ -26061,7 +26701,7 @@ GL_PREFIX(VertexAttrib3fvNV):
GL_PREFIX(VertexAttrib3sNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5544(%rax), %r11
+ movq 5672(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26075,13 +26715,13 @@ GL_PREFIX(VertexAttrib3sNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5544(%rax), %r11
+ movq 5672(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5544(%rax), %r11
+ movq 5672(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26095,7 +26735,7 @@ GL_PREFIX(VertexAttrib3sNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5544(%rax), %r11
+ movq 5672(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib3sNV), .-GL_PREFIX(VertexAttrib3sNV)
@@ -26106,7 +26746,7 @@ GL_PREFIX(VertexAttrib3sNV):
GL_PREFIX(VertexAttrib3svNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5552(%rax), %r11
+ movq 5680(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26116,13 +26756,13 @@ GL_PREFIX(VertexAttrib3svNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5552(%rax), %r11
+ movq 5680(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5552(%rax), %r11
+ movq 5680(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26132,7 +26772,7 @@ GL_PREFIX(VertexAttrib3svNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5552(%rax), %r11
+ movq 5680(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib3svNV), .-GL_PREFIX(VertexAttrib3svNV)
@@ -26143,7 +26783,7 @@ GL_PREFIX(VertexAttrib3svNV):
GL_PREFIX(VertexAttrib4dNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5560(%rax), %r11
+ movq 5688(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $40, %rsp
@@ -26159,13 +26799,13 @@ GL_PREFIX(VertexAttrib4dNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $40, %rsp
- movq 5560(%rax), %r11
+ movq 5688(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5560(%rax), %r11
+ movq 5688(%rax), %r11
jmp *%r11
1:
subq $40, %rsp
@@ -26181,7 +26821,7 @@ GL_PREFIX(VertexAttrib4dNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $40, %rsp
- movq 5560(%rax), %r11
+ movq 5688(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib4dNV), .-GL_PREFIX(VertexAttrib4dNV)
@@ -26192,7 +26832,7 @@ GL_PREFIX(VertexAttrib4dNV):
GL_PREFIX(VertexAttrib4dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5568(%rax), %r11
+ movq 5696(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26202,13 +26842,13 @@ GL_PREFIX(VertexAttrib4dvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5568(%rax), %r11
+ movq 5696(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5568(%rax), %r11
+ movq 5696(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26218,7 +26858,7 @@ GL_PREFIX(VertexAttrib4dvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5568(%rax), %r11
+ movq 5696(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib4dvNV), .-GL_PREFIX(VertexAttrib4dvNV)
@@ -26229,7 +26869,7 @@ GL_PREFIX(VertexAttrib4dvNV):
GL_PREFIX(VertexAttrib4fNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5576(%rax), %r11
+ movq 5704(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $40, %rsp
@@ -26245,13 +26885,13 @@ GL_PREFIX(VertexAttrib4fNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $40, %rsp
- movq 5576(%rax), %r11
+ movq 5704(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5576(%rax), %r11
+ movq 5704(%rax), %r11
jmp *%r11
1:
subq $40, %rsp
@@ -26267,7 +26907,7 @@ GL_PREFIX(VertexAttrib4fNV):
movq 8(%rsp), %xmm0
movq (%rsp), %rdi
addq $40, %rsp
- movq 5576(%rax), %r11
+ movq 5704(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib4fNV), .-GL_PREFIX(VertexAttrib4fNV)
@@ -26278,7 +26918,7 @@ GL_PREFIX(VertexAttrib4fNV):
GL_PREFIX(VertexAttrib4fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5584(%rax), %r11
+ movq 5712(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26288,13 +26928,13 @@ GL_PREFIX(VertexAttrib4fvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5584(%rax), %r11
+ movq 5712(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5584(%rax), %r11
+ movq 5712(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26304,7 +26944,7 @@ GL_PREFIX(VertexAttrib4fvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5584(%rax), %r11
+ movq 5712(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib4fvNV), .-GL_PREFIX(VertexAttrib4fvNV)
@@ -26315,7 +26955,7 @@ GL_PREFIX(VertexAttrib4fvNV):
GL_PREFIX(VertexAttrib4sNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5592(%rax), %r11
+ movq 5720(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26329,13 +26969,13 @@ GL_PREFIX(VertexAttrib4sNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5592(%rax), %r11
+ movq 5720(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5592(%rax), %r11
+ movq 5720(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26349,7 +26989,7 @@ GL_PREFIX(VertexAttrib4sNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5592(%rax), %r11
+ movq 5720(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib4sNV), .-GL_PREFIX(VertexAttrib4sNV)
@@ -26360,7 +27000,7 @@ GL_PREFIX(VertexAttrib4sNV):
GL_PREFIX(VertexAttrib4svNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5600(%rax), %r11
+ movq 5728(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26370,13 +27010,13 @@ GL_PREFIX(VertexAttrib4svNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5600(%rax), %r11
+ movq 5728(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5600(%rax), %r11
+ movq 5728(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26386,7 +27026,7 @@ GL_PREFIX(VertexAttrib4svNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5600(%rax), %r11
+ movq 5728(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib4svNV), .-GL_PREFIX(VertexAttrib4svNV)
@@ -26397,7 +27037,7 @@ GL_PREFIX(VertexAttrib4svNV):
GL_PREFIX(VertexAttrib4ubNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5608(%rax), %r11
+ movq 5736(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26411,13 +27051,13 @@ GL_PREFIX(VertexAttrib4ubNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5608(%rax), %r11
+ movq 5736(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5608(%rax), %r11
+ movq 5736(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26431,7 +27071,7 @@ GL_PREFIX(VertexAttrib4ubNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5608(%rax), %r11
+ movq 5736(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib4ubNV), .-GL_PREFIX(VertexAttrib4ubNV)
@@ -26442,7 +27082,7 @@ GL_PREFIX(VertexAttrib4ubNV):
GL_PREFIX(VertexAttrib4ubvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5616(%rax), %r11
+ movq 5744(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26452,13 +27092,13 @@ GL_PREFIX(VertexAttrib4ubvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5616(%rax), %r11
+ movq 5744(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5616(%rax), %r11
+ movq 5744(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26468,7 +27108,7 @@ GL_PREFIX(VertexAttrib4ubvNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5616(%rax), %r11
+ movq 5744(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttrib4ubvNV), .-GL_PREFIX(VertexAttrib4ubvNV)
@@ -26479,7 +27119,7 @@ GL_PREFIX(VertexAttrib4ubvNV):
GL_PREFIX(VertexAttribPointerNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5624(%rax), %r11
+ movq 5752(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26493,13 +27133,13 @@ GL_PREFIX(VertexAttribPointerNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5624(%rax), %r11
+ movq 5752(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5624(%rax), %r11
+ movq 5752(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26513,7 +27153,7 @@ GL_PREFIX(VertexAttribPointerNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5624(%rax), %r11
+ movq 5752(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribPointerNV), .-GL_PREFIX(VertexAttribPointerNV)
@@ -26524,7 +27164,7 @@ GL_PREFIX(VertexAttribPointerNV):
GL_PREFIX(VertexAttribs1dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5632(%rax), %r11
+ movq 5760(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26534,13 +27174,13 @@ GL_PREFIX(VertexAttribs1dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5632(%rax), %r11
+ movq 5760(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5632(%rax), %r11
+ movq 5760(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26550,7 +27190,7 @@ GL_PREFIX(VertexAttribs1dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5632(%rax), %r11
+ movq 5760(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs1dvNV), .-GL_PREFIX(VertexAttribs1dvNV)
@@ -26561,7 +27201,7 @@ GL_PREFIX(VertexAttribs1dvNV):
GL_PREFIX(VertexAttribs1fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5640(%rax), %r11
+ movq 5768(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26571,13 +27211,13 @@ GL_PREFIX(VertexAttribs1fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5640(%rax), %r11
+ movq 5768(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5640(%rax), %r11
+ movq 5768(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26587,7 +27227,7 @@ GL_PREFIX(VertexAttribs1fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5640(%rax), %r11
+ movq 5768(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs1fvNV), .-GL_PREFIX(VertexAttribs1fvNV)
@@ -26598,7 +27238,7 @@ GL_PREFIX(VertexAttribs1fvNV):
GL_PREFIX(VertexAttribs1svNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5648(%rax), %r11
+ movq 5776(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26608,13 +27248,13 @@ GL_PREFIX(VertexAttribs1svNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5648(%rax), %r11
+ movq 5776(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5648(%rax), %r11
+ movq 5776(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26624,7 +27264,7 @@ GL_PREFIX(VertexAttribs1svNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5648(%rax), %r11
+ movq 5776(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs1svNV), .-GL_PREFIX(VertexAttribs1svNV)
@@ -26635,7 +27275,7 @@ GL_PREFIX(VertexAttribs1svNV):
GL_PREFIX(VertexAttribs2dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5656(%rax), %r11
+ movq 5784(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26645,13 +27285,13 @@ GL_PREFIX(VertexAttribs2dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5656(%rax), %r11
+ movq 5784(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5656(%rax), %r11
+ movq 5784(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26661,7 +27301,7 @@ GL_PREFIX(VertexAttribs2dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5656(%rax), %r11
+ movq 5784(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs2dvNV), .-GL_PREFIX(VertexAttribs2dvNV)
@@ -26672,7 +27312,7 @@ GL_PREFIX(VertexAttribs2dvNV):
GL_PREFIX(VertexAttribs2fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5664(%rax), %r11
+ movq 5792(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26682,13 +27322,13 @@ GL_PREFIX(VertexAttribs2fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5664(%rax), %r11
+ movq 5792(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5664(%rax), %r11
+ movq 5792(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26698,7 +27338,7 @@ GL_PREFIX(VertexAttribs2fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5664(%rax), %r11
+ movq 5792(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs2fvNV), .-GL_PREFIX(VertexAttribs2fvNV)
@@ -26709,7 +27349,7 @@ GL_PREFIX(VertexAttribs2fvNV):
GL_PREFIX(VertexAttribs2svNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5672(%rax), %r11
+ movq 5800(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26719,13 +27359,13 @@ GL_PREFIX(VertexAttribs2svNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5672(%rax), %r11
+ movq 5800(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5672(%rax), %r11
+ movq 5800(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26735,7 +27375,7 @@ GL_PREFIX(VertexAttribs2svNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5672(%rax), %r11
+ movq 5800(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs2svNV), .-GL_PREFIX(VertexAttribs2svNV)
@@ -26746,7 +27386,7 @@ GL_PREFIX(VertexAttribs2svNV):
GL_PREFIX(VertexAttribs3dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5680(%rax), %r11
+ movq 5808(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26756,13 +27396,13 @@ GL_PREFIX(VertexAttribs3dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5680(%rax), %r11
+ movq 5808(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5680(%rax), %r11
+ movq 5808(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26772,7 +27412,7 @@ GL_PREFIX(VertexAttribs3dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5680(%rax), %r11
+ movq 5808(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs3dvNV), .-GL_PREFIX(VertexAttribs3dvNV)
@@ -26783,7 +27423,7 @@ GL_PREFIX(VertexAttribs3dvNV):
GL_PREFIX(VertexAttribs3fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5688(%rax), %r11
+ movq 5816(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26793,13 +27433,13 @@ GL_PREFIX(VertexAttribs3fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5688(%rax), %r11
+ movq 5816(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5688(%rax), %r11
+ movq 5816(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26809,7 +27449,7 @@ GL_PREFIX(VertexAttribs3fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5688(%rax), %r11
+ movq 5816(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs3fvNV), .-GL_PREFIX(VertexAttribs3fvNV)
@@ -26820,7 +27460,7 @@ GL_PREFIX(VertexAttribs3fvNV):
GL_PREFIX(VertexAttribs3svNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5696(%rax), %r11
+ movq 5824(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26830,13 +27470,13 @@ GL_PREFIX(VertexAttribs3svNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5696(%rax), %r11
+ movq 5824(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5696(%rax), %r11
+ movq 5824(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26846,7 +27486,7 @@ GL_PREFIX(VertexAttribs3svNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5696(%rax), %r11
+ movq 5824(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs3svNV), .-GL_PREFIX(VertexAttribs3svNV)
@@ -26857,7 +27497,7 @@ GL_PREFIX(VertexAttribs3svNV):
GL_PREFIX(VertexAttribs4dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5704(%rax), %r11
+ movq 5832(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26867,13 +27507,13 @@ GL_PREFIX(VertexAttribs4dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5704(%rax), %r11
+ movq 5832(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5704(%rax), %r11
+ movq 5832(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26883,7 +27523,7 @@ GL_PREFIX(VertexAttribs4dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5704(%rax), %r11
+ movq 5832(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs4dvNV), .-GL_PREFIX(VertexAttribs4dvNV)
@@ -26894,7 +27534,7 @@ GL_PREFIX(VertexAttribs4dvNV):
GL_PREFIX(VertexAttribs4fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5712(%rax), %r11
+ movq 5840(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26904,13 +27544,13 @@ GL_PREFIX(VertexAttribs4fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5712(%rax), %r11
+ movq 5840(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5712(%rax), %r11
+ movq 5840(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26920,7 +27560,7 @@ GL_PREFIX(VertexAttribs4fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5712(%rax), %r11
+ movq 5840(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs4fvNV), .-GL_PREFIX(VertexAttribs4fvNV)
@@ -26931,7 +27571,7 @@ GL_PREFIX(VertexAttribs4fvNV):
GL_PREFIX(VertexAttribs4svNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5720(%rax), %r11
+ movq 5848(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26941,13 +27581,13 @@ GL_PREFIX(VertexAttribs4svNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5720(%rax), %r11
+ movq 5848(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5720(%rax), %r11
+ movq 5848(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26957,7 +27597,7 @@ GL_PREFIX(VertexAttribs4svNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5720(%rax), %r11
+ movq 5848(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs4svNV), .-GL_PREFIX(VertexAttribs4svNV)
@@ -26968,7 +27608,7 @@ GL_PREFIX(VertexAttribs4svNV):
GL_PREFIX(VertexAttribs4ubvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5728(%rax), %r11
+ movq 5856(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -26978,13 +27618,13 @@ GL_PREFIX(VertexAttribs4ubvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5728(%rax), %r11
+ movq 5856(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5728(%rax), %r11
+ movq 5856(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -26994,18 +27634,166 @@ GL_PREFIX(VertexAttribs4ubvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5728(%rax), %r11
+ movq 5856(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(VertexAttribs4ubvNV), .-GL_PREFIX(VertexAttribs4ubvNV)
.p2align 4,,15
+ .globl GL_PREFIX(GetTexBumpParameterfvATI)
+ .type GL_PREFIX(GetTexBumpParameterfvATI), @function
+GL_PREFIX(GetTexBumpParameterfvATI):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 5864(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 5864(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 5864(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 5864(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(GetTexBumpParameterfvATI), .-GL_PREFIX(GetTexBumpParameterfvATI)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(GetTexBumpParameterivATI)
+ .type GL_PREFIX(GetTexBumpParameterivATI), @function
+GL_PREFIX(GetTexBumpParameterivATI):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 5872(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 5872(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 5872(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 5872(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(GetTexBumpParameterivATI), .-GL_PREFIX(GetTexBumpParameterivATI)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(TexBumpParameterfvATI)
+ .type GL_PREFIX(TexBumpParameterfvATI), @function
+GL_PREFIX(TexBumpParameterfvATI):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 5880(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 5880(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 5880(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 5880(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(TexBumpParameterfvATI), .-GL_PREFIX(TexBumpParameterfvATI)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(TexBumpParameterivATI)
+ .type GL_PREFIX(TexBumpParameterivATI), @function
+GL_PREFIX(TexBumpParameterivATI):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 5888(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _x86_64_get_dispatch@PLT
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 5888(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 5888(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
+ call _glapi_get_dispatch
+ popq %rbp
+ popq %rsi
+ popq %rdi
+ movq 5888(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(TexBumpParameterivATI), .-GL_PREFIX(TexBumpParameterivATI)
+
+ .p2align 4,,15
.globl GL_PREFIX(AlphaFragmentOp1ATI)
.type GL_PREFIX(AlphaFragmentOp1ATI), @function
GL_PREFIX(AlphaFragmentOp1ATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5736(%rax), %r11
+ movq 5896(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27023,13 +27811,13 @@ GL_PREFIX(AlphaFragmentOp1ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5736(%rax), %r11
+ movq 5896(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5736(%rax), %r11
+ movq 5896(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27047,7 +27835,7 @@ GL_PREFIX(AlphaFragmentOp1ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5736(%rax), %r11
+ movq 5896(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(AlphaFragmentOp1ATI), .-GL_PREFIX(AlphaFragmentOp1ATI)
@@ -27058,7 +27846,7 @@ GL_PREFIX(AlphaFragmentOp1ATI):
GL_PREFIX(AlphaFragmentOp2ATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5744(%rax), %r11
+ movq 5904(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27076,13 +27864,13 @@ GL_PREFIX(AlphaFragmentOp2ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5744(%rax), %r11
+ movq 5904(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5744(%rax), %r11
+ movq 5904(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27100,7 +27888,7 @@ GL_PREFIX(AlphaFragmentOp2ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5744(%rax), %r11
+ movq 5904(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(AlphaFragmentOp2ATI), .-GL_PREFIX(AlphaFragmentOp2ATI)
@@ -27111,7 +27899,7 @@ GL_PREFIX(AlphaFragmentOp2ATI):
GL_PREFIX(AlphaFragmentOp3ATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5752(%rax), %r11
+ movq 5912(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27129,13 +27917,13 @@ GL_PREFIX(AlphaFragmentOp3ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5752(%rax), %r11
+ movq 5912(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5752(%rax), %r11
+ movq 5912(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27153,7 +27941,7 @@ GL_PREFIX(AlphaFragmentOp3ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5752(%rax), %r11
+ movq 5912(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(AlphaFragmentOp3ATI), .-GL_PREFIX(AlphaFragmentOp3ATI)
@@ -27164,25 +27952,25 @@ GL_PREFIX(AlphaFragmentOp3ATI):
GL_PREFIX(BeginFragmentShaderATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5760(%rax), %r11
+ movq 5920(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rbp
call _x86_64_get_dispatch@PLT
popq %rbp
- movq 5760(%rax), %r11
+ movq 5920(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5760(%rax), %r11
+ movq 5920(%rax), %r11
jmp *%r11
1:
pushq %rbp
call _glapi_get_dispatch
popq %rbp
- movq 5760(%rax), %r11
+ movq 5920(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(BeginFragmentShaderATI), .-GL_PREFIX(BeginFragmentShaderATI)
@@ -27193,25 +27981,25 @@ GL_PREFIX(BeginFragmentShaderATI):
GL_PREFIX(BindFragmentShaderATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5768(%rax), %r11
+ movq 5928(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5768(%rax), %r11
+ movq 5928(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5768(%rax), %r11
+ movq 5928(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5768(%rax), %r11
+ movq 5928(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(BindFragmentShaderATI), .-GL_PREFIX(BindFragmentShaderATI)
@@ -27222,7 +28010,7 @@ GL_PREFIX(BindFragmentShaderATI):
GL_PREFIX(ColorFragmentOp1ATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5776(%rax), %r11
+ movq 5936(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27240,13 +28028,13 @@ GL_PREFIX(ColorFragmentOp1ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5776(%rax), %r11
+ movq 5936(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5776(%rax), %r11
+ movq 5936(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27264,7 +28052,7 @@ GL_PREFIX(ColorFragmentOp1ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5776(%rax), %r11
+ movq 5936(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ColorFragmentOp1ATI), .-GL_PREFIX(ColorFragmentOp1ATI)
@@ -27275,7 +28063,7 @@ GL_PREFIX(ColorFragmentOp1ATI):
GL_PREFIX(ColorFragmentOp2ATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5784(%rax), %r11
+ movq 5944(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27293,13 +28081,13 @@ GL_PREFIX(ColorFragmentOp2ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5784(%rax), %r11
+ movq 5944(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5784(%rax), %r11
+ movq 5944(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27317,7 +28105,7 @@ GL_PREFIX(ColorFragmentOp2ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5784(%rax), %r11
+ movq 5944(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ColorFragmentOp2ATI), .-GL_PREFIX(ColorFragmentOp2ATI)
@@ -27328,7 +28116,7 @@ GL_PREFIX(ColorFragmentOp2ATI):
GL_PREFIX(ColorFragmentOp3ATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5792(%rax), %r11
+ movq 5952(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27346,13 +28134,13 @@ GL_PREFIX(ColorFragmentOp3ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5792(%rax), %r11
+ movq 5952(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5792(%rax), %r11
+ movq 5952(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27370,7 +28158,7 @@ GL_PREFIX(ColorFragmentOp3ATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5792(%rax), %r11
+ movq 5952(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ColorFragmentOp3ATI), .-GL_PREFIX(ColorFragmentOp3ATI)
@@ -27381,25 +28169,25 @@ GL_PREFIX(ColorFragmentOp3ATI):
GL_PREFIX(DeleteFragmentShaderATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5800(%rax), %r11
+ movq 5960(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5800(%rax), %r11
+ movq 5960(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5800(%rax), %r11
+ movq 5960(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5800(%rax), %r11
+ movq 5960(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(DeleteFragmentShaderATI), .-GL_PREFIX(DeleteFragmentShaderATI)
@@ -27410,25 +28198,25 @@ GL_PREFIX(DeleteFragmentShaderATI):
GL_PREFIX(EndFragmentShaderATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5808(%rax), %r11
+ movq 5968(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rbp
call _x86_64_get_dispatch@PLT
popq %rbp
- movq 5808(%rax), %r11
+ movq 5968(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5808(%rax), %r11
+ movq 5968(%rax), %r11
jmp *%r11
1:
pushq %rbp
call _glapi_get_dispatch
popq %rbp
- movq 5808(%rax), %r11
+ movq 5968(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(EndFragmentShaderATI), .-GL_PREFIX(EndFragmentShaderATI)
@@ -27439,25 +28227,25 @@ GL_PREFIX(EndFragmentShaderATI):
GL_PREFIX(GenFragmentShadersATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5816(%rax), %r11
+ movq 5976(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5816(%rax), %r11
+ movq 5976(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5816(%rax), %r11
+ movq 5976(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5816(%rax), %r11
+ movq 5976(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GenFragmentShadersATI), .-GL_PREFIX(GenFragmentShadersATI)
@@ -27468,7 +28256,7 @@ GL_PREFIX(GenFragmentShadersATI):
GL_PREFIX(PassTexCoordATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5824(%rax), %r11
+ movq 5984(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27478,13 +28266,13 @@ GL_PREFIX(PassTexCoordATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5824(%rax), %r11
+ movq 5984(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5824(%rax), %r11
+ movq 5984(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27494,7 +28282,7 @@ GL_PREFIX(PassTexCoordATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5824(%rax), %r11
+ movq 5984(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(PassTexCoordATI), .-GL_PREFIX(PassTexCoordATI)
@@ -27505,7 +28293,7 @@ GL_PREFIX(PassTexCoordATI):
GL_PREFIX(SampleMapATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5832(%rax), %r11
+ movq 5992(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27515,13 +28303,13 @@ GL_PREFIX(SampleMapATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5832(%rax), %r11
+ movq 5992(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5832(%rax), %r11
+ movq 5992(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27531,7 +28319,7 @@ GL_PREFIX(SampleMapATI):
popq %rdx
popq %rsi
popq %rdi
- movq 5832(%rax), %r11
+ movq 5992(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SampleMapATI), .-GL_PREFIX(SampleMapATI)
@@ -27542,7 +28330,7 @@ GL_PREFIX(SampleMapATI):
GL_PREFIX(SetFragmentShaderConstantATI):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5840(%rax), %r11
+ movq 6000(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27552,13 +28340,13 @@ GL_PREFIX(SetFragmentShaderConstantATI):
popq %rbp
popq %rsi
popq %rdi
- movq 5840(%rax), %r11
+ movq 6000(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5840(%rax), %r11
+ movq 6000(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27568,7 +28356,7 @@ GL_PREFIX(SetFragmentShaderConstantATI):
popq %rbp
popq %rsi
popq %rdi
- movq 5840(%rax), %r11
+ movq 6000(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(SetFragmentShaderConstantATI), .-GL_PREFIX(SetFragmentShaderConstantATI)
@@ -27579,7 +28367,7 @@ GL_PREFIX(SetFragmentShaderConstantATI):
GL_PREFIX(PointParameteriNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5848(%rax), %r11
+ movq 6008(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27589,13 +28377,13 @@ GL_PREFIX(PointParameteriNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5848(%rax), %r11
+ movq 6008(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5848(%rax), %r11
+ movq 6008(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27605,7 +28393,7 @@ GL_PREFIX(PointParameteriNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5848(%rax), %r11
+ movq 6008(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(PointParameteriNV), .-GL_PREFIX(PointParameteriNV)
@@ -27616,7 +28404,7 @@ GL_PREFIX(PointParameteriNV):
GL_PREFIX(PointParameterivNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5856(%rax), %r11
+ movq 6016(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27626,13 +28414,13 @@ GL_PREFIX(PointParameterivNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5856(%rax), %r11
+ movq 6016(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5856(%rax), %r11
+ movq 6016(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27642,79 +28430,79 @@ GL_PREFIX(PointParameterivNV):
popq %rbp
popq %rsi
popq %rdi
- movq 5856(%rax), %r11
+ movq 6016(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(PointParameterivNV), .-GL_PREFIX(PointParameterivNV)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_733)
- .type GL_PREFIX(_dispatch_stub_733), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_733))
-GL_PREFIX(_dispatch_stub_733):
+ .globl GL_PREFIX(_dispatch_stub_753)
+ .type GL_PREFIX(_dispatch_stub_753), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_753))
+GL_PREFIX(_dispatch_stub_753):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5864(%rax), %r11
+ movq 6024(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5864(%rax), %r11
+ movq 6024(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5864(%rax), %r11
+ movq 6024(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5864(%rax), %r11
+ movq 6024(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_733), .-GL_PREFIX(_dispatch_stub_733)
+ .size GL_PREFIX(_dispatch_stub_753), .-GL_PREFIX(_dispatch_stub_753)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_734)
- .type GL_PREFIX(_dispatch_stub_734), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_734))
-GL_PREFIX(_dispatch_stub_734):
+ .globl GL_PREFIX(_dispatch_stub_754)
+ .type GL_PREFIX(_dispatch_stub_754), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_754))
+GL_PREFIX(_dispatch_stub_754):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5872(%rax), %r11
+ movq 6032(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5872(%rax), %r11
+ movq 6032(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5872(%rax), %r11
+ movq 6032(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5872(%rax), %r11
+ movq 6032(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_734), .-GL_PREFIX(_dispatch_stub_734)
+ .size GL_PREFIX(_dispatch_stub_754), .-GL_PREFIX(_dispatch_stub_754)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_735)
- .type GL_PREFIX(_dispatch_stub_735), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_735))
-GL_PREFIX(_dispatch_stub_735):
+ .globl GL_PREFIX(_dispatch_stub_755)
+ .type GL_PREFIX(_dispatch_stub_755), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_755))
+GL_PREFIX(_dispatch_stub_755):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5880(%rax), %r11
+ movq 6040(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27724,13 +28512,13 @@ GL_PREFIX(_dispatch_stub_735):
popq %rbp
popq %rsi
popq %rdi
- movq 5880(%rax), %r11
+ movq 6040(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5880(%rax), %r11
+ movq 6040(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27740,19 +28528,19 @@ GL_PREFIX(_dispatch_stub_735):
popq %rbp
popq %rsi
popq %rdi
- movq 5880(%rax), %r11
+ movq 6040(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_735), .-GL_PREFIX(_dispatch_stub_735)
+ .size GL_PREFIX(_dispatch_stub_755), .-GL_PREFIX(_dispatch_stub_755)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_736)
- .type GL_PREFIX(_dispatch_stub_736), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_736))
-GL_PREFIX(_dispatch_stub_736):
+ .globl GL_PREFIX(_dispatch_stub_756)
+ .type GL_PREFIX(_dispatch_stub_756), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_756))
+GL_PREFIX(_dispatch_stub_756):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5888(%rax), %r11
+ movq 6048(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27762,13 +28550,13 @@ GL_PREFIX(_dispatch_stub_736):
popq %rbp
popq %rsi
popq %rdi
- movq 5888(%rax), %r11
+ movq 6048(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5888(%rax), %r11
+ movq 6048(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27778,40 +28566,40 @@ GL_PREFIX(_dispatch_stub_736):
popq %rbp
popq %rsi
popq %rdi
- movq 5888(%rax), %r11
+ movq 6048(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_736), .-GL_PREFIX(_dispatch_stub_736)
+ .size GL_PREFIX(_dispatch_stub_756), .-GL_PREFIX(_dispatch_stub_756)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_737)
- .type GL_PREFIX(_dispatch_stub_737), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_737))
-GL_PREFIX(_dispatch_stub_737):
+ .globl GL_PREFIX(_dispatch_stub_757)
+ .type GL_PREFIX(_dispatch_stub_757), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_757))
+GL_PREFIX(_dispatch_stub_757):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5896(%rax), %r11
+ movq 6056(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5896(%rax), %r11
+ movq 6056(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5896(%rax), %r11
+ movq 6056(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5896(%rax), %r11
+ movq 6056(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_737), .-GL_PREFIX(_dispatch_stub_737)
+ .size GL_PREFIX(_dispatch_stub_757), .-GL_PREFIX(_dispatch_stub_757)
.p2align 4,,15
.globl GL_PREFIX(GetProgramNamedParameterdvNV)
@@ -27819,7 +28607,7 @@ GL_PREFIX(_dispatch_stub_737):
GL_PREFIX(GetProgramNamedParameterdvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5904(%rax), %r11
+ movq 6064(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27833,13 +28621,13 @@ GL_PREFIX(GetProgramNamedParameterdvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5904(%rax), %r11
+ movq 6064(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5904(%rax), %r11
+ movq 6064(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27853,7 +28641,7 @@ GL_PREFIX(GetProgramNamedParameterdvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5904(%rax), %r11
+ movq 6064(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetProgramNamedParameterdvNV), .-GL_PREFIX(GetProgramNamedParameterdvNV)
@@ -27864,7 +28652,7 @@ GL_PREFIX(GetProgramNamedParameterdvNV):
GL_PREFIX(GetProgramNamedParameterfvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5912(%rax), %r11
+ movq 6072(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27878,13 +28666,13 @@ GL_PREFIX(GetProgramNamedParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5912(%rax), %r11
+ movq 6072(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5912(%rax), %r11
+ movq 6072(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -27898,7 +28686,7 @@ GL_PREFIX(GetProgramNamedParameterfvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5912(%rax), %r11
+ movq 6072(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetProgramNamedParameterfvNV), .-GL_PREFIX(GetProgramNamedParameterfvNV)
@@ -27909,7 +28697,7 @@ GL_PREFIX(GetProgramNamedParameterfvNV):
GL_PREFIX(ProgramNamedParameter4dNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5920(%rax), %r11
+ movq 6080(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $56, %rsp
@@ -27929,13 +28717,13 @@ GL_PREFIX(ProgramNamedParameter4dNV):
movq 8(%rsp), %rsi
movq (%rsp), %rdi
addq $56, %rsp
- movq 5920(%rax), %r11
+ movq 6080(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5920(%rax), %r11
+ movq 6080(%rax), %r11
jmp *%r11
1:
subq $56, %rsp
@@ -27955,7 +28743,7 @@ GL_PREFIX(ProgramNamedParameter4dNV):
movq 8(%rsp), %rsi
movq (%rsp), %rdi
addq $56, %rsp
- movq 5920(%rax), %r11
+ movq 6080(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ProgramNamedParameter4dNV), .-GL_PREFIX(ProgramNamedParameter4dNV)
@@ -27966,7 +28754,7 @@ GL_PREFIX(ProgramNamedParameter4dNV):
GL_PREFIX(ProgramNamedParameter4dvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5928(%rax), %r11
+ movq 6088(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -27980,13 +28768,13 @@ GL_PREFIX(ProgramNamedParameter4dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5928(%rax), %r11
+ movq 6088(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5928(%rax), %r11
+ movq 6088(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28000,7 +28788,7 @@ GL_PREFIX(ProgramNamedParameter4dvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5928(%rax), %r11
+ movq 6088(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ProgramNamedParameter4dvNV), .-GL_PREFIX(ProgramNamedParameter4dvNV)
@@ -28011,7 +28799,7 @@ GL_PREFIX(ProgramNamedParameter4dvNV):
GL_PREFIX(ProgramNamedParameter4fNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5936(%rax), %r11
+ movq 6096(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
subq $56, %rsp
@@ -28031,13 +28819,13 @@ GL_PREFIX(ProgramNamedParameter4fNV):
movq 8(%rsp), %rsi
movq (%rsp), %rdi
addq $56, %rsp
- movq 5936(%rax), %r11
+ movq 6096(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5936(%rax), %r11
+ movq 6096(%rax), %r11
jmp *%r11
1:
subq $56, %rsp
@@ -28057,7 +28845,7 @@ GL_PREFIX(ProgramNamedParameter4fNV):
movq 8(%rsp), %rsi
movq (%rsp), %rdi
addq $56, %rsp
- movq 5936(%rax), %r11
+ movq 6096(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ProgramNamedParameter4fNV), .-GL_PREFIX(ProgramNamedParameter4fNV)
@@ -28068,7 +28856,7 @@ GL_PREFIX(ProgramNamedParameter4fNV):
GL_PREFIX(ProgramNamedParameter4fvNV):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5944(%rax), %r11
+ movq 6104(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28082,13 +28870,13 @@ GL_PREFIX(ProgramNamedParameter4fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5944(%rax), %r11
+ movq 6104(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5944(%rax), %r11
+ movq 6104(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28102,19 +28890,19 @@ GL_PREFIX(ProgramNamedParameter4fvNV):
popq %rdx
popq %rsi
popq %rdi
- movq 5944(%rax), %r11
+ movq 6104(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(ProgramNamedParameter4fvNV), .-GL_PREFIX(ProgramNamedParameter4fvNV)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_744)
- .type GL_PREFIX(_dispatch_stub_744), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_744))
-GL_PREFIX(_dispatch_stub_744):
+ .globl GL_PREFIX(_dispatch_stub_764)
+ .type GL_PREFIX(_dispatch_stub_764), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_764))
+GL_PREFIX(_dispatch_stub_764):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5952(%rax), %r11
+ movq 6112(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28124,13 +28912,13 @@ GL_PREFIX(_dispatch_stub_744):
popq %rbp
popq %rsi
popq %rdi
- movq 5952(%rax), %r11
+ movq 6112(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5952(%rax), %r11
+ movq 6112(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28140,19 +28928,19 @@ GL_PREFIX(_dispatch_stub_744):
popq %rbp
popq %rsi
popq %rdi
- movq 5952(%rax), %r11
+ movq 6112(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_744), .-GL_PREFIX(_dispatch_stub_744)
+ .size GL_PREFIX(_dispatch_stub_764), .-GL_PREFIX(_dispatch_stub_764)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_745)
- .type GL_PREFIX(_dispatch_stub_745), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_745))
-GL_PREFIX(_dispatch_stub_745):
+ .globl GL_PREFIX(_dispatch_stub_765)
+ .type GL_PREFIX(_dispatch_stub_765), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_765))
+GL_PREFIX(_dispatch_stub_765):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5960(%rax), %r11
+ movq 6120(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28162,13 +28950,13 @@ GL_PREFIX(_dispatch_stub_745):
popq %rbp
popq %rsi
popq %rdi
- movq 5960(%rax), %r11
+ movq 6120(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5960(%rax), %r11
+ movq 6120(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28178,10 +28966,10 @@ GL_PREFIX(_dispatch_stub_745):
popq %rbp
popq %rsi
popq %rdi
- movq 5960(%rax), %r11
+ movq 6120(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_745), .-GL_PREFIX(_dispatch_stub_745)
+ .size GL_PREFIX(_dispatch_stub_765), .-GL_PREFIX(_dispatch_stub_765)
.p2align 4,,15
.globl GL_PREFIX(BindFramebufferEXT)
@@ -28189,7 +28977,7 @@ GL_PREFIX(_dispatch_stub_745):
GL_PREFIX(BindFramebufferEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5968(%rax), %r11
+ movq 6128(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28199,13 +28987,13 @@ GL_PREFIX(BindFramebufferEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 5968(%rax), %r11
+ movq 6128(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5968(%rax), %r11
+ movq 6128(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28215,7 +29003,7 @@ GL_PREFIX(BindFramebufferEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 5968(%rax), %r11
+ movq 6128(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(BindFramebufferEXT), .-GL_PREFIX(BindFramebufferEXT)
@@ -28226,7 +29014,7 @@ GL_PREFIX(BindFramebufferEXT):
GL_PREFIX(BindRenderbufferEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5976(%rax), %r11
+ movq 6136(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28236,13 +29024,13 @@ GL_PREFIX(BindRenderbufferEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 5976(%rax), %r11
+ movq 6136(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5976(%rax), %r11
+ movq 6136(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28252,7 +29040,7 @@ GL_PREFIX(BindRenderbufferEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 5976(%rax), %r11
+ movq 6136(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(BindRenderbufferEXT), .-GL_PREFIX(BindRenderbufferEXT)
@@ -28263,25 +29051,25 @@ GL_PREFIX(BindRenderbufferEXT):
GL_PREFIX(CheckFramebufferStatusEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5984(%rax), %r11
+ movq 6144(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 5984(%rax), %r11
+ movq 6144(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5984(%rax), %r11
+ movq 6144(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 5984(%rax), %r11
+ movq 6144(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(CheckFramebufferStatusEXT), .-GL_PREFIX(CheckFramebufferStatusEXT)
@@ -28292,7 +29080,7 @@ GL_PREFIX(CheckFramebufferStatusEXT):
GL_PREFIX(DeleteFramebuffersEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 5992(%rax), %r11
+ movq 6152(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28302,13 +29090,13 @@ GL_PREFIX(DeleteFramebuffersEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 5992(%rax), %r11
+ movq 6152(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 5992(%rax), %r11
+ movq 6152(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28318,7 +29106,7 @@ GL_PREFIX(DeleteFramebuffersEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 5992(%rax), %r11
+ movq 6152(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(DeleteFramebuffersEXT), .-GL_PREFIX(DeleteFramebuffersEXT)
@@ -28329,7 +29117,7 @@ GL_PREFIX(DeleteFramebuffersEXT):
GL_PREFIX(DeleteRenderbuffersEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6000(%rax), %r11
+ movq 6160(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28339,13 +29127,13 @@ GL_PREFIX(DeleteRenderbuffersEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 6000(%rax), %r11
+ movq 6160(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6000(%rax), %r11
+ movq 6160(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28355,7 +29143,7 @@ GL_PREFIX(DeleteRenderbuffersEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 6000(%rax), %r11
+ movq 6160(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(DeleteRenderbuffersEXT), .-GL_PREFIX(DeleteRenderbuffersEXT)
@@ -28366,7 +29154,7 @@ GL_PREFIX(DeleteRenderbuffersEXT):
GL_PREFIX(FramebufferRenderbufferEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6008(%rax), %r11
+ movq 6168(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28380,13 +29168,13 @@ GL_PREFIX(FramebufferRenderbufferEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6008(%rax), %r11
+ movq 6168(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6008(%rax), %r11
+ movq 6168(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28400,7 +29188,7 @@ GL_PREFIX(FramebufferRenderbufferEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6008(%rax), %r11
+ movq 6168(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FramebufferRenderbufferEXT), .-GL_PREFIX(FramebufferRenderbufferEXT)
@@ -28411,7 +29199,7 @@ GL_PREFIX(FramebufferRenderbufferEXT):
GL_PREFIX(FramebufferTexture1DEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6016(%rax), %r11
+ movq 6176(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28425,13 +29213,13 @@ GL_PREFIX(FramebufferTexture1DEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6016(%rax), %r11
+ movq 6176(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6016(%rax), %r11
+ movq 6176(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28445,7 +29233,7 @@ GL_PREFIX(FramebufferTexture1DEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6016(%rax), %r11
+ movq 6176(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FramebufferTexture1DEXT), .-GL_PREFIX(FramebufferTexture1DEXT)
@@ -28456,7 +29244,7 @@ GL_PREFIX(FramebufferTexture1DEXT):
GL_PREFIX(FramebufferTexture2DEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6024(%rax), %r11
+ movq 6184(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28470,13 +29258,13 @@ GL_PREFIX(FramebufferTexture2DEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6024(%rax), %r11
+ movq 6184(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6024(%rax), %r11
+ movq 6184(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28490,7 +29278,7 @@ GL_PREFIX(FramebufferTexture2DEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6024(%rax), %r11
+ movq 6184(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FramebufferTexture2DEXT), .-GL_PREFIX(FramebufferTexture2DEXT)
@@ -28501,7 +29289,7 @@ GL_PREFIX(FramebufferTexture2DEXT):
GL_PREFIX(FramebufferTexture3DEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6032(%rax), %r11
+ movq 6192(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28519,13 +29307,13 @@ GL_PREFIX(FramebufferTexture3DEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6032(%rax), %r11
+ movq 6192(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6032(%rax), %r11
+ movq 6192(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28543,7 +29331,7 @@ GL_PREFIX(FramebufferTexture3DEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6032(%rax), %r11
+ movq 6192(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FramebufferTexture3DEXT), .-GL_PREFIX(FramebufferTexture3DEXT)
@@ -28554,7 +29342,7 @@ GL_PREFIX(FramebufferTexture3DEXT):
GL_PREFIX(GenFramebuffersEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6040(%rax), %r11
+ movq 6200(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28564,13 +29352,13 @@ GL_PREFIX(GenFramebuffersEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 6040(%rax), %r11
+ movq 6200(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6040(%rax), %r11
+ movq 6200(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28580,7 +29368,7 @@ GL_PREFIX(GenFramebuffersEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 6040(%rax), %r11
+ movq 6200(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GenFramebuffersEXT), .-GL_PREFIX(GenFramebuffersEXT)
@@ -28591,7 +29379,7 @@ GL_PREFIX(GenFramebuffersEXT):
GL_PREFIX(GenRenderbuffersEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6048(%rax), %r11
+ movq 6208(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28601,13 +29389,13 @@ GL_PREFIX(GenRenderbuffersEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 6048(%rax), %r11
+ movq 6208(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6048(%rax), %r11
+ movq 6208(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28617,7 +29405,7 @@ GL_PREFIX(GenRenderbuffersEXT):
popq %rbp
popq %rsi
popq %rdi
- movq 6048(%rax), %r11
+ movq 6208(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GenRenderbuffersEXT), .-GL_PREFIX(GenRenderbuffersEXT)
@@ -28628,25 +29416,25 @@ GL_PREFIX(GenRenderbuffersEXT):
GL_PREFIX(GenerateMipmapEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6056(%rax), %r11
+ movq 6216(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 6056(%rax), %r11
+ movq 6216(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6056(%rax), %r11
+ movq 6216(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 6056(%rax), %r11
+ movq 6216(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GenerateMipmapEXT), .-GL_PREFIX(GenerateMipmapEXT)
@@ -28657,7 +29445,7 @@ GL_PREFIX(GenerateMipmapEXT):
GL_PREFIX(GetFramebufferAttachmentParameterivEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6064(%rax), %r11
+ movq 6224(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28671,13 +29459,13 @@ GL_PREFIX(GetFramebufferAttachmentParameterivEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6064(%rax), %r11
+ movq 6224(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6064(%rax), %r11
+ movq 6224(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28691,7 +29479,7 @@ GL_PREFIX(GetFramebufferAttachmentParameterivEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6064(%rax), %r11
+ movq 6224(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetFramebufferAttachmentParameterivEXT), .-GL_PREFIX(GetFramebufferAttachmentParameterivEXT)
@@ -28702,7 +29490,7 @@ GL_PREFIX(GetFramebufferAttachmentParameterivEXT):
GL_PREFIX(GetRenderbufferParameterivEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6072(%rax), %r11
+ movq 6232(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28712,13 +29500,13 @@ GL_PREFIX(GetRenderbufferParameterivEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6072(%rax), %r11
+ movq 6232(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6072(%rax), %r11
+ movq 6232(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28728,7 +29516,7 @@ GL_PREFIX(GetRenderbufferParameterivEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6072(%rax), %r11
+ movq 6232(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(GetRenderbufferParameterivEXT), .-GL_PREFIX(GetRenderbufferParameterivEXT)
@@ -28739,25 +29527,25 @@ GL_PREFIX(GetRenderbufferParameterivEXT):
GL_PREFIX(IsFramebufferEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6080(%rax), %r11
+ movq 6240(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 6080(%rax), %r11
+ movq 6240(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6080(%rax), %r11
+ movq 6240(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 6080(%rax), %r11
+ movq 6240(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(IsFramebufferEXT), .-GL_PREFIX(IsFramebufferEXT)
@@ -28768,25 +29556,25 @@ GL_PREFIX(IsFramebufferEXT):
GL_PREFIX(IsRenderbufferEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6088(%rax), %r11
+ movq 6248(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch@PLT
popq %rdi
- movq 6088(%rax), %r11
+ movq 6248(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6088(%rax), %r11
+ movq 6248(%rax), %r11
jmp *%r11
1:
pushq %rdi
call _glapi_get_dispatch
popq %rdi
- movq 6088(%rax), %r11
+ movq 6248(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(IsRenderbufferEXT), .-GL_PREFIX(IsRenderbufferEXT)
@@ -28797,7 +29585,7 @@ GL_PREFIX(IsRenderbufferEXT):
GL_PREFIX(RenderbufferStorageEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6096(%rax), %r11
+ movq 6256(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28811,13 +29599,13 @@ GL_PREFIX(RenderbufferStorageEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6096(%rax), %r11
+ movq 6256(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6096(%rax), %r11
+ movq 6256(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28831,19 +29619,19 @@ GL_PREFIX(RenderbufferStorageEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6096(%rax), %r11
+ movq 6256(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(RenderbufferStorageEXT), .-GL_PREFIX(RenderbufferStorageEXT)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_763)
- .type GL_PREFIX(_dispatch_stub_763), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_763))
-GL_PREFIX(_dispatch_stub_763):
+ .globl GL_PREFIX(_dispatch_stub_783)
+ .type GL_PREFIX(_dispatch_stub_783), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_783))
+GL_PREFIX(_dispatch_stub_783):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6104(%rax), %r11
+ movq 6264(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28861,13 +29649,13 @@ GL_PREFIX(_dispatch_stub_763):
popq %rdx
popq %rsi
popq %rdi
- movq 6104(%rax), %r11
+ movq 6264(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6104(%rax), %r11
+ movq 6264(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28885,10 +29673,86 @@ GL_PREFIX(_dispatch_stub_763):
popq %rdx
popq %rsi
popq %rdi
- movq 6104(%rax), %r11
+ movq 6264(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(_dispatch_stub_783), .-GL_PREFIX(_dispatch_stub_783)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(_dispatch_stub_784)
+ .type GL_PREFIX(_dispatch_stub_784), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_784))
+GL_PREFIX(_dispatch_stub_784):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 6272(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _x86_64_get_dispatch@PLT
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 6272(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 6272(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _glapi_get_dispatch
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 6272(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_763), .-GL_PREFIX(_dispatch_stub_763)
+ .size GL_PREFIX(_dispatch_stub_784), .-GL_PREFIX(_dispatch_stub_784)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(_dispatch_stub_785)
+ .type GL_PREFIX(_dispatch_stub_785), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_785))
+GL_PREFIX(_dispatch_stub_785):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 6280(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _x86_64_get_dispatch@PLT
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 6280(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 6280(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _glapi_get_dispatch
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 6280(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(_dispatch_stub_785), .-GL_PREFIX(_dispatch_stub_785)
.p2align 4,,15
.globl GL_PREFIX(FramebufferTextureLayerEXT)
@@ -28896,7 +29760,7 @@ GL_PREFIX(_dispatch_stub_763):
GL_PREFIX(FramebufferTextureLayerEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6112(%rax), %r11
+ movq 6288(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28910,13 +29774,13 @@ GL_PREFIX(FramebufferTextureLayerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6112(%rax), %r11
+ movq 6288(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6112(%rax), %r11
+ movq 6288(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28930,19 +29794,124 @@ GL_PREFIX(FramebufferTextureLayerEXT):
popq %rdx
popq %rsi
popq %rdi
- movq 6112(%rax), %r11
+ movq 6288(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
.size GL_PREFIX(FramebufferTextureLayerEXT), .-GL_PREFIX(FramebufferTextureLayerEXT)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_765)
- .type GL_PREFIX(_dispatch_stub_765), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_765))
-GL_PREFIX(_dispatch_stub_765):
+ .globl GL_PREFIX(ProvokingVertexEXT)
+ .type GL_PREFIX(ProvokingVertexEXT), @function
+GL_PREFIX(ProvokingVertexEXT):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6120(%rax), %r11
+ movq 6296(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ call _x86_64_get_dispatch@PLT
+ popq %rdi
+ movq 6296(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 6296(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ call _glapi_get_dispatch
+ popq %rdi
+ movq 6296(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(ProvokingVertexEXT), .-GL_PREFIX(ProvokingVertexEXT)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(_dispatch_stub_788)
+ .type GL_PREFIX(_dispatch_stub_788), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_788))
+GL_PREFIX(_dispatch_stub_788):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 6304(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _x86_64_get_dispatch@PLT
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 6304(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 6304(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _glapi_get_dispatch
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 6304(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(_dispatch_stub_788), .-GL_PREFIX(_dispatch_stub_788)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(_dispatch_stub_789)
+ .type GL_PREFIX(_dispatch_stub_789), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_789))
+GL_PREFIX(_dispatch_stub_789):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 6312(%rax), %r11
+ jmp *%r11
+#elif defined(PTHREADS)
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _x86_64_get_dispatch@PLT
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 6312(%rax), %r11
+ jmp *%r11
+#else
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax, %rax
+ je 1f
+ movq 6312(%rax), %r11
+ jmp *%r11
+1:
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ call _glapi_get_dispatch
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ movq 6312(%rax), %r11
+ jmp *%r11
+#endif /* defined(GLX_USE_TLS) */
+ .size GL_PREFIX(_dispatch_stub_789), .-GL_PREFIX(_dispatch_stub_789)
+
+ .p2align 4,,15
+ .globl GL_PREFIX(_dispatch_stub_790)
+ .type GL_PREFIX(_dispatch_stub_790), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_790))
+GL_PREFIX(_dispatch_stub_790):
+#if defined(GLX_USE_TLS)
+ call _x86_64_get_dispatch@PLT
+ movq 6320(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -28956,13 +29925,13 @@ GL_PREFIX(_dispatch_stub_765):
popq %rdx
popq %rsi
popq %rdi
- movq 6120(%rax), %r11
+ movq 6320(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6120(%rax), %r11
+ movq 6320(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -28976,19 +29945,19 @@ GL_PREFIX(_dispatch_stub_765):
popq %rdx
popq %rsi
popq %rdi
- movq 6120(%rax), %r11
+ movq 6320(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_765), .-GL_PREFIX(_dispatch_stub_765)
+ .size GL_PREFIX(_dispatch_stub_790), .-GL_PREFIX(_dispatch_stub_790)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_766)
- .type GL_PREFIX(_dispatch_stub_766), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_766))
-GL_PREFIX(_dispatch_stub_766):
+ .globl GL_PREFIX(_dispatch_stub_791)
+ .type GL_PREFIX(_dispatch_stub_791), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_791))
+GL_PREFIX(_dispatch_stub_791):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6128(%rax), %r11
+ movq 6328(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -29002,13 +29971,13 @@ GL_PREFIX(_dispatch_stub_766):
popq %rdx
popq %rsi
popq %rdi
- movq 6128(%rax), %r11
+ movq 6328(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6128(%rax), %r11
+ movq 6328(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -29022,19 +29991,19 @@ GL_PREFIX(_dispatch_stub_766):
popq %rdx
popq %rsi
popq %rdi
- movq 6128(%rax), %r11
+ movq 6328(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_766), .-GL_PREFIX(_dispatch_stub_766)
+ .size GL_PREFIX(_dispatch_stub_791), .-GL_PREFIX(_dispatch_stub_791)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_767)
- .type GL_PREFIX(_dispatch_stub_767), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_767))
-GL_PREFIX(_dispatch_stub_767):
+ .globl GL_PREFIX(_dispatch_stub_792)
+ .type GL_PREFIX(_dispatch_stub_792), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_792))
+GL_PREFIX(_dispatch_stub_792):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6136(%rax), %r11
+ movq 6336(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -29048,13 +30017,13 @@ GL_PREFIX(_dispatch_stub_767):
popq %rdx
popq %rsi
popq %rdi
- movq 6136(%rax), %r11
+ movq 6336(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6136(%rax), %r11
+ movq 6336(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -29068,19 +30037,19 @@ GL_PREFIX(_dispatch_stub_767):
popq %rdx
popq %rsi
popq %rdi
- movq 6136(%rax), %r11
+ movq 6336(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_767), .-GL_PREFIX(_dispatch_stub_767)
+ .size GL_PREFIX(_dispatch_stub_792), .-GL_PREFIX(_dispatch_stub_792)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_768)
- .type GL_PREFIX(_dispatch_stub_768), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_768))
-GL_PREFIX(_dispatch_stub_768):
+ .globl GL_PREFIX(_dispatch_stub_793)
+ .type GL_PREFIX(_dispatch_stub_793), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_793))
+GL_PREFIX(_dispatch_stub_793):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6144(%rax), %r11
+ movq 6344(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -29090,13 +30059,13 @@ GL_PREFIX(_dispatch_stub_768):
popq %rdx
popq %rsi
popq %rdi
- movq 6144(%rax), %r11
+ movq 6344(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6144(%rax), %r11
+ movq 6344(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -29106,19 +30075,19 @@ GL_PREFIX(_dispatch_stub_768):
popq %rdx
popq %rsi
popq %rdi
- movq 6144(%rax), %r11
+ movq 6344(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_768), .-GL_PREFIX(_dispatch_stub_768)
+ .size GL_PREFIX(_dispatch_stub_793), .-GL_PREFIX(_dispatch_stub_793)
.p2align 4,,15
- .globl GL_PREFIX(_dispatch_stub_769)
- .type GL_PREFIX(_dispatch_stub_769), @function
- HIDDEN(GL_PREFIX(_dispatch_stub_769))
-GL_PREFIX(_dispatch_stub_769):
+ .globl GL_PREFIX(_dispatch_stub_794)
+ .type GL_PREFIX(_dispatch_stub_794), @function
+ HIDDEN(GL_PREFIX(_dispatch_stub_794))
+GL_PREFIX(_dispatch_stub_794):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch@PLT
- movq 6152(%rax), %r11
+ movq 6352(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
@@ -29128,13 +30097,13 @@ GL_PREFIX(_dispatch_stub_769):
popq %rdx
popq %rsi
popq %rdi
- movq 6152(%rax), %r11
+ movq 6352(%rax), %r11
jmp *%r11
#else
movq _glapi_Dispatch(%rip), %rax
testq %rax, %rax
je 1f
- movq 6152(%rax), %r11
+ movq 6352(%rax), %r11
jmp *%r11
1:
pushq %rdi
@@ -29144,10 +30113,10 @@ GL_PREFIX(_dispatch_stub_769):
popq %rdx
popq %rsi
popq %rdi
- movq 6152(%rax), %r11
+ movq 6352(%rax), %r11
jmp *%r11
#endif /* defined(GLX_USE_TLS) */
- .size GL_PREFIX(_dispatch_stub_769), .-GL_PREFIX(_dispatch_stub_769)
+ .size GL_PREFIX(_dispatch_stub_794), .-GL_PREFIX(_dispatch_stub_794)
.globl GL_PREFIX(ArrayElementEXT) ; .set GL_PREFIX(ArrayElementEXT), GL_PREFIX(ArrayElement)
.globl GL_PREFIX(BindTextureEXT) ; .set GL_PREFIX(BindTextureEXT), GL_PREFIX(BindTexture)
@@ -29402,7 +30371,28 @@ GL_PREFIX(_dispatch_stub_769):
.globl GL_PREFIX(IsProgramARB) ; .set GL_PREFIX(IsProgramARB), GL_PREFIX(IsProgramNV)
.globl GL_PREFIX(PointParameteri) ; .set GL_PREFIX(PointParameteri), GL_PREFIX(PointParameteriNV)
.globl GL_PREFIX(PointParameteriv) ; .set GL_PREFIX(PointParameteriv), GL_PREFIX(PointParameterivNV)
- .globl GL_PREFIX(BlendEquationSeparate) ; .set GL_PREFIX(BlendEquationSeparate), GL_PREFIX(_dispatch_stub_745)
+ .globl GL_PREFIX(DeleteVertexArrays) ; .set GL_PREFIX(DeleteVertexArrays), GL_PREFIX(_dispatch_stub_755)
+ .globl GL_PREFIX(IsVertexArray) ; .set GL_PREFIX(IsVertexArray), GL_PREFIX(_dispatch_stub_757)
+ .globl GL_PREFIX(BlendEquationSeparate) ; .set GL_PREFIX(BlendEquationSeparate), GL_PREFIX(_dispatch_stub_765)
+ .globl GL_PREFIX(BindFramebuffer) ; .set GL_PREFIX(BindFramebuffer), GL_PREFIX(BindFramebufferEXT)
+ .globl GL_PREFIX(BindRenderbuffer) ; .set GL_PREFIX(BindRenderbuffer), GL_PREFIX(BindRenderbufferEXT)
+ .globl GL_PREFIX(CheckFramebufferStatus) ; .set GL_PREFIX(CheckFramebufferStatus), GL_PREFIX(CheckFramebufferStatusEXT)
+ .globl GL_PREFIX(DeleteFramebuffers) ; .set GL_PREFIX(DeleteFramebuffers), GL_PREFIX(DeleteFramebuffersEXT)
+ .globl GL_PREFIX(DeleteRenderbuffers) ; .set GL_PREFIX(DeleteRenderbuffers), GL_PREFIX(DeleteRenderbuffersEXT)
+ .globl GL_PREFIX(FramebufferRenderbuffer) ; .set GL_PREFIX(FramebufferRenderbuffer), GL_PREFIX(FramebufferRenderbufferEXT)
+ .globl GL_PREFIX(FramebufferTexture1D) ; .set GL_PREFIX(FramebufferTexture1D), GL_PREFIX(FramebufferTexture1DEXT)
+ .globl GL_PREFIX(FramebufferTexture2D) ; .set GL_PREFIX(FramebufferTexture2D), GL_PREFIX(FramebufferTexture2DEXT)
+ .globl GL_PREFIX(FramebufferTexture3D) ; .set GL_PREFIX(FramebufferTexture3D), GL_PREFIX(FramebufferTexture3DEXT)
+ .globl GL_PREFIX(GenFramebuffers) ; .set GL_PREFIX(GenFramebuffers), GL_PREFIX(GenFramebuffersEXT)
+ .globl GL_PREFIX(GenRenderbuffers) ; .set GL_PREFIX(GenRenderbuffers), GL_PREFIX(GenRenderbuffersEXT)
+ .globl GL_PREFIX(GenerateMipmap) ; .set GL_PREFIX(GenerateMipmap), GL_PREFIX(GenerateMipmapEXT)
+ .globl GL_PREFIX(GetFramebufferAttachmentParameteriv) ; .set GL_PREFIX(GetFramebufferAttachmentParameteriv), GL_PREFIX(GetFramebufferAttachmentParameterivEXT)
+ .globl GL_PREFIX(GetRenderbufferParameteriv) ; .set GL_PREFIX(GetRenderbufferParameteriv), GL_PREFIX(GetRenderbufferParameterivEXT)
+ .globl GL_PREFIX(IsFramebuffer) ; .set GL_PREFIX(IsFramebuffer), GL_PREFIX(IsFramebufferEXT)
+ .globl GL_PREFIX(IsRenderbuffer) ; .set GL_PREFIX(IsRenderbuffer), GL_PREFIX(IsRenderbufferEXT)
+ .globl GL_PREFIX(RenderbufferStorage) ; .set GL_PREFIX(RenderbufferStorage), GL_PREFIX(RenderbufferStorageEXT)
+ .globl GL_PREFIX(BlitFramebuffer) ; .set GL_PREFIX(BlitFramebuffer), GL_PREFIX(_dispatch_stub_783)
+ .globl GL_PREFIX(FramebufferTextureLayer) ; .set GL_PREFIX(FramebufferTextureLayer), GL_PREFIX(FramebufferTextureLayerEXT)
#if defined(GLX_USE_TLS) && defined(__linux__)
.section ".note.ABI-tag", "a"
diff --git a/src/mesa/x86-64/x86-64.c b/src/mesa/x86-64/x86-64.c
index 96f8da87f0..ac176ef328 100644
--- a/src/mesa/x86-64/x86-64.c
+++ b/src/mesa/x86-64/x86-64.c
@@ -35,7 +35,7 @@
#include "math/m_xform.h"
#include "tnl/t_context.h"
#include "x86-64.h"
-#include "../x86/common_x86_macros.h"
+#include "../x86/x86_xform.h"
#ifdef DEBUG
#include "math/m_debug.h"
diff --git a/src/mesa/x86/3dnow.c b/src/mesa/x86/3dnow.c
index c037a61761..de2fb1e2aa 100644
--- a/src/mesa/x86/3dnow.c
+++ b/src/mesa/x86/3dnow.c
@@ -34,7 +34,7 @@
#include "tnl/t_context.h"
#include "3dnow.h"
-#include "common_x86_macros.h"
+#include "x86_xform.h"
#ifdef DEBUG_MATH
#include "math/m_debug.h"
diff --git a/src/mesa/x86/Makefile b/src/mesa/x86/Makefile
index dc8c7f355e..69122c114b 100644
--- a/src/mesa/x86/Makefile
+++ b/src/mesa/x86/Makefile
@@ -21,7 +21,7 @@ clean:
gen_matypes: gen_matypes.c
- $(CC) $(INCLUDE_DIRS) $(CFLAGS) gen_matypes.c -o gen_matypes
+ $(HOST_CC) $(ARCH_FLAGS) $(INCLUDE_DIRS) $(HOST_CFLAGS) gen_matypes.c -o gen_matypes
# need some special rules here, unfortunately
matypes.h: ../main/mtypes.h ../tnl/t_context.h gen_matypes
diff --git a/src/mesa/x86/common_x86.c b/src/mesa/x86/common_x86.c
index 5321547935..5efdb4f24a 100644
--- a/src/mesa/x86/common_x86.c
+++ b/src/mesa/x86/common_x86.c
@@ -52,7 +52,10 @@
#include "common_x86_asm.h"
-int _mesa_x86_cpu_features = 0;
+/** Bitmask of X86_FEATURE_x bits */
+int _mesa_x86_cpu_features = 0x0;
+
+
/* No reason for this to be public.
*/
@@ -73,9 +76,12 @@ extern GLuint _ASMAPI _mesa_x86_cpuid_edx(GLuint op);
* kernels provide full SSE support on all processors that expose SSE via
* the CPUID mechanism.
*/
+
+/* These are assembly functions: */
extern void _mesa_test_os_sse_support( void );
extern void _mesa_test_os_sse_exception_support( void );
+
#if defined(WIN32)
#ifndef STATUS_FLOAT_MULTIPLE_TRAPS
# define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L)
@@ -107,7 +113,11 @@ static LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS exp)
#endif /* WIN32 */
-static void check_os_sse_support( void )
+/**
+ * Check if SSE is supported.
+ * If not, turn off the X86_FEATURE_XMM flag in _mesa_x86_cpu_features.
+ */
+void _mesa_check_os_sse_support( void )
{
#if defined(__FreeBSD__)
{
@@ -187,10 +197,26 @@ static void check_os_sse_support( void )
#endif /* USE_SSE_ASM */
-void _mesa_init_all_x86_transform_asm( void )
+/**
+ * Initialize the _mesa_x86_cpu_features bitfield.
+ * This is a no-op if called more than once.
+ */
+void
+_mesa_get_x86_features(void)
{
+ static int called = 0;
+
+ if (called)
+ return;
+
+ called = 1;
+
#ifdef USE_X86_ASM
- _mesa_x86_cpu_features = 0;
+ _mesa_x86_cpu_features = 0x0;
+
+ if (_mesa_getenv( "MESA_NO_ASM")) {
+ return;
+ }
if (!_mesa_x86_has_cpuid()) {
_mesa_debug(NULL, "CPUID not detected\n");
@@ -263,52 +289,5 @@ void _mesa_init_all_x86_transform_asm( void )
}
}
-
- if ( _mesa_getenv( "MESA_NO_ASM" ) ) {
- _mesa_x86_cpu_features = 0;
- }
-
- if ( _mesa_x86_cpu_features ) {
- _mesa_init_x86_transform_asm();
- }
-
-#ifdef USE_MMX_ASM
- if ( cpu_has_mmx ) {
- if ( _mesa_getenv( "MESA_NO_MMX" ) == 0 ) {
- _mesa_debug(NULL, "MMX cpu detected.\n");
- } else {
- _mesa_x86_cpu_features &= ~(X86_FEATURE_MMX);
- }
- }
-#endif
-
-#ifdef USE_3DNOW_ASM
- if ( cpu_has_3dnow ) {
- if ( _mesa_getenv( "MESA_NO_3DNOW" ) == 0 ) {
- _mesa_debug(NULL, "3DNow! cpu detected.\n");
- _mesa_init_3dnow_transform_asm();
- } else {
- _mesa_x86_cpu_features &= ~(X86_FEATURE_3DNOW);
- }
- }
-#endif
-
-#ifdef USE_SSE_ASM
- if ( cpu_has_xmm ) {
- if ( _mesa_getenv( "MESA_NO_SSE" ) == 0 ) {
- _mesa_debug(NULL, "SSE cpu detected.\n");
- if ( _mesa_getenv( "MESA_FORCE_SSE" ) == 0 ) {
- check_os_sse_support();
- }
- if ( cpu_has_xmm ) {
- _mesa_init_sse_transform_asm();
- }
- } else {
- _mesa_debug(NULL, "SSE cpu detected, but switched off by user.\n");
- _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
- }
- }
-#endif
-#endif
+#endif /* USE_X86_ASM */
}
-
diff --git a/src/mesa/x86/common_x86_asm.h b/src/mesa/x86/common_x86_asm.h
index 89312b2437..0d39e3d230 100644
--- a/src/mesa/x86/common_x86_asm.h
+++ b/src/mesa/x86/common_x86_asm.h
@@ -42,18 +42,12 @@
*/
#include "common_x86_features.h"
-#ifdef USE_X86_ASM
-#include "x86.h"
-#ifdef USE_3DNOW_ASM
-#include "3dnow.h"
-#endif
-#ifdef USE_SSE_ASM
-#include "sse.h"
-#endif
-#endif
-
extern int _mesa_x86_cpu_features;
+extern void _mesa_get_x86_features(void);
+
+extern void _mesa_check_os_sse_support(void);
+
extern void _mesa_init_all_x86_transform_asm( void );
#endif
diff --git a/src/mesa/x86/gen_matypes.c b/src/mesa/x86/gen_matypes.c
index afb4b11529..d56b701aa8 100644
--- a/src/mesa/x86/gen_matypes.c
+++ b/src/mesa/x86/gen_matypes.c
@@ -61,7 +61,7 @@ do { \
printf( "\n" ); \
} while (0)
-#if defined(__BEOS__) || defined(_LP64)
+#if defined(__BEOS__) || defined(__HAIKU__) || defined(_LP64)
#define OFFSET( s, t, m ) \
printf( "#define %s\t%ld\n", s, offsetof( t, m ) );
#else
@@ -69,7 +69,7 @@ do { \
printf( "#define %s\t%d\n", s, offsetof( t, m ) );
#endif
-#if defined(__BEOS__) || defined(_LP64)
+#if defined(__BEOS__) || defined(__HAIKU__) || defined(_LP64)
#define SIZEOF( s, t ) \
printf( "#define %s\t%ld\n", s, sizeof(t) );
#else
@@ -197,7 +197,7 @@ int main( int argc, char **argv )
OFFSET( "LIGHT_DIFFUSE ", struct gl_light, Diffuse );
OFFSET( "LIGHT_SPECULAR ", struct gl_light, Specular );
OFFSET( "LIGHT_EYE_POSITION ", struct gl_light, EyePosition );
- OFFSET( "LIGHT_EYE_DIRECTION ", struct gl_light, EyeDirection );
+ OFFSET( "LIGHT_SPOT_DIRECTION ", struct gl_light, SpotDirection );
OFFSET( "LIGHT_SPOT_EXPONENT ", struct gl_light, SpotExponent );
OFFSET( "LIGHT_SPOT_CUTOFF ", struct gl_light, SpotCutoff );
OFFSET( "LIGHT_COS_CUTOFF ", struct gl_light, _CosCutoff );
@@ -211,7 +211,7 @@ int main( int argc, char **argv )
OFFSET( "LIGHT_POSITION ", struct gl_light, _Position );
OFFSET( "LIGHT_VP_INF_NORM ", struct gl_light, _VP_inf_norm );
OFFSET( "LIGHT_H_INF_NORM ", struct gl_light, _h_inf_norm );
- OFFSET( "LIGHT_NORM_DIRECTION ", struct gl_light, _NormDirection );
+ OFFSET( "LIGHT_NORM_DIRECTION ", struct gl_light, _NormSpotDirection );
OFFSET( "LIGHT_VP_INF_SPOT_ATTEN ", struct gl_light, _VP_inf_spot_attenuation );
printf( "\n" );
OFFSET( "LIGHT_SPOT_EXP_TABLE ", struct gl_light, _SpotExpTable );
diff --git a/src/mesa/x86/glapi_x86.S b/src/mesa/x86/glapi_x86.S
index b99c2b6520..5f12b4fb6a 100644
--- a/src/mesa/x86/glapi_x86.S
+++ b/src/mesa/x86/glapi_x86.S
@@ -52,7 +52,7 @@
#define GLOBL_FN(x) GLOBL x
#endif
-#if defined(PTHREADS) || defined(USE_XTHREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS)
+#if defined(PTHREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS)
# define THREADS
#endif
@@ -712,23 +712,39 @@ GLNAME(gl_dispatch_functions_start):
GL_STUB(GetActiveAttribARB, _gloffset_GetActiveAttribARB, GetActiveAttribARB@28)
GL_STUB(GetAttribLocationARB, _gloffset_GetAttribLocationARB, GetAttribLocationARB@8)
GL_STUB(DrawBuffersARB, _gloffset_DrawBuffersARB, DrawBuffersARB@8)
+ GL_STUB(RenderbufferStorageMultisample, _gloffset_RenderbufferStorageMultisample, RenderbufferStorageMultisample@20)
+ GL_STUB(FlushMappedBufferRange, _gloffset_FlushMappedBufferRange, FlushMappedBufferRange@12)
+ GL_STUB(MapBufferRange, _gloffset_MapBufferRange, MapBufferRange@16)
+ GL_STUB(BindVertexArray, _gloffset_BindVertexArray, BindVertexArray@4)
+ GL_STUB(GenVertexArrays, _gloffset_GenVertexArrays, GenVertexArrays@8)
+ GL_STUB(CopyBufferSubData, _gloffset_CopyBufferSubData, CopyBufferSubData@20)
+ GL_STUB(ClientWaitSync, _gloffset_ClientWaitSync, ClientWaitSync@12)
+ GL_STUB(DeleteSync, _gloffset_DeleteSync, DeleteSync@4)
+ GL_STUB(FenceSync, _gloffset_FenceSync, FenceSync@8)
+ GL_STUB(GetInteger64v, _gloffset_GetInteger64v, GetInteger64v@8)
+ GL_STUB(GetSynciv, _gloffset_GetSynciv, GetSynciv@20)
+ GL_STUB(IsSync, _gloffset_IsSync, IsSync@4)
+ GL_STUB(WaitSync, _gloffset_WaitSync, WaitSync@12)
+ GL_STUB(DrawElementsBaseVertex, _gloffset_DrawElementsBaseVertex, DrawElementsBaseVertex@20)
+ GL_STUB(DrawRangeElementsBaseVertex, _gloffset_DrawRangeElementsBaseVertex, DrawRangeElementsBaseVertex@28)
+ GL_STUB(MultiDrawElementsBaseVertex, _gloffset_MultiDrawElementsBaseVertex, MultiDrawElementsBaseVertex@24)
GL_STUB(PolygonOffsetEXT, _gloffset_PolygonOffsetEXT, PolygonOffsetEXT@8)
- GL_STUB(_dispatch_stub_562, _gloffset_GetPixelTexGenParameterfvSGIS, _dispatch_stub_562@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_562, _dispatch_stub_562@8))
- GL_STUB(_dispatch_stub_563, _gloffset_GetPixelTexGenParameterivSGIS, _dispatch_stub_563@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_563, _dispatch_stub_563@8))
- GL_STUB(_dispatch_stub_564, _gloffset_PixelTexGenParameterfSGIS, _dispatch_stub_564@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_564, _dispatch_stub_564@8))
- GL_STUB(_dispatch_stub_565, _gloffset_PixelTexGenParameterfvSGIS, _dispatch_stub_565@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_565, _dispatch_stub_565@8))
- GL_STUB(_dispatch_stub_566, _gloffset_PixelTexGenParameteriSGIS, _dispatch_stub_566@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_566, _dispatch_stub_566@8))
- GL_STUB(_dispatch_stub_567, _gloffset_PixelTexGenParameterivSGIS, _dispatch_stub_567@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_567, _dispatch_stub_567@8))
- GL_STUB(_dispatch_stub_568, _gloffset_SampleMaskSGIS, _dispatch_stub_568@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_568, _dispatch_stub_568@8))
- GL_STUB(_dispatch_stub_569, _gloffset_SamplePatternSGIS, _dispatch_stub_569@4)
- HIDDEN(GL_PREFIX(_dispatch_stub_569, _dispatch_stub_569@4))
+ GL_STUB(_dispatch_stub_578, _gloffset_GetPixelTexGenParameterfvSGIS, _dispatch_stub_578@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_578, _dispatch_stub_578@8))
+ GL_STUB(_dispatch_stub_579, _gloffset_GetPixelTexGenParameterivSGIS, _dispatch_stub_579@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_579, _dispatch_stub_579@8))
+ GL_STUB(_dispatch_stub_580, _gloffset_PixelTexGenParameterfSGIS, _dispatch_stub_580@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_580, _dispatch_stub_580@8))
+ GL_STUB(_dispatch_stub_581, _gloffset_PixelTexGenParameterfvSGIS, _dispatch_stub_581@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_581, _dispatch_stub_581@8))
+ GL_STUB(_dispatch_stub_582, _gloffset_PixelTexGenParameteriSGIS, _dispatch_stub_582@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_582, _dispatch_stub_582@8))
+ GL_STUB(_dispatch_stub_583, _gloffset_PixelTexGenParameterivSGIS, _dispatch_stub_583@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_583, _dispatch_stub_583@8))
+ GL_STUB(_dispatch_stub_584, _gloffset_SampleMaskSGIS, _dispatch_stub_584@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_584, _dispatch_stub_584@8))
+ GL_STUB(_dispatch_stub_585, _gloffset_SamplePatternSGIS, _dispatch_stub_585@4)
+ HIDDEN(GL_PREFIX(_dispatch_stub_585, _dispatch_stub_585@4))
GL_STUB(ColorPointerEXT, _gloffset_ColorPointerEXT, ColorPointerEXT@20)
GL_STUB(EdgeFlagPointerEXT, _gloffset_EdgeFlagPointerEXT, EdgeFlagPointerEXT@12)
GL_STUB(IndexPointerEXT, _gloffset_IndexPointerEXT, IndexPointerEXT@16)
@@ -739,10 +755,10 @@ GLNAME(gl_dispatch_functions_start):
GL_STUB(PointParameterfvEXT, _gloffset_PointParameterfvEXT, PointParameterfvEXT@8)
GL_STUB(LockArraysEXT, _gloffset_LockArraysEXT, LockArraysEXT@8)
GL_STUB(UnlockArraysEXT, _gloffset_UnlockArraysEXT, UnlockArraysEXT@0)
- GL_STUB(_dispatch_stub_580, _gloffset_CullParameterdvEXT, _dispatch_stub_580@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_580, _dispatch_stub_580@8))
- GL_STUB(_dispatch_stub_581, _gloffset_CullParameterfvEXT, _dispatch_stub_581@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_581, _dispatch_stub_581@8))
+ GL_STUB(_dispatch_stub_596, _gloffset_CullParameterdvEXT, _dispatch_stub_596@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_596, _dispatch_stub_596@8))
+ GL_STUB(_dispatch_stub_597, _gloffset_CullParameterfvEXT, _dispatch_stub_597@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_597, _dispatch_stub_597@8))
GL_STUB(SecondaryColor3bEXT, _gloffset_SecondaryColor3bEXT, SecondaryColor3bEXT@12)
GL_STUB(SecondaryColor3bvEXT, _gloffset_SecondaryColor3bvEXT, SecondaryColor3bvEXT@4)
GL_STUB(SecondaryColor3dEXT, _gloffset_SecondaryColor3dEXT, SecondaryColor3dEXT@24)
@@ -767,8 +783,8 @@ GLNAME(gl_dispatch_functions_start):
GL_STUB(FogCoorddvEXT, _gloffset_FogCoorddvEXT, FogCoorddvEXT@4)
GL_STUB(FogCoordfEXT, _gloffset_FogCoordfEXT, FogCoordfEXT@4)
GL_STUB(FogCoordfvEXT, _gloffset_FogCoordfvEXT, FogCoordfvEXT@4)
- GL_STUB(_dispatch_stub_606, _gloffset_PixelTexGenSGIX, _dispatch_stub_606@4)
- HIDDEN(GL_PREFIX(_dispatch_stub_606, _dispatch_stub_606@4))
+ GL_STUB(_dispatch_stub_622, _gloffset_PixelTexGenSGIX, _dispatch_stub_622@4)
+ HIDDEN(GL_PREFIX(_dispatch_stub_622, _dispatch_stub_622@4))
GL_STUB(BlendFuncSeparateEXT, _gloffset_BlendFuncSeparateEXT, BlendFuncSeparateEXT@16)
GL_STUB(FlushVertexArrayRangeNV, _gloffset_FlushVertexArrayRangeNV, FlushVertexArrayRangeNV@0)
GL_STUB(VertexArrayRangeNV, _gloffset_VertexArrayRangeNV, VertexArrayRangeNV@8)
@@ -810,24 +826,24 @@ GLNAME(gl_dispatch_functions_start):
GL_STUB(WindowPos4ivMESA, _gloffset_WindowPos4ivMESA, WindowPos4ivMESA@4)
GL_STUB(WindowPos4sMESA, _gloffset_WindowPos4sMESA, WindowPos4sMESA@16)
GL_STUB(WindowPos4svMESA, _gloffset_WindowPos4svMESA, WindowPos4svMESA@4)
- GL_STUB(_dispatch_stub_648, _gloffset_MultiModeDrawArraysIBM, _dispatch_stub_648@20)
- HIDDEN(GL_PREFIX(_dispatch_stub_648, _dispatch_stub_648@20))
- GL_STUB(_dispatch_stub_649, _gloffset_MultiModeDrawElementsIBM, _dispatch_stub_649@24)
- HIDDEN(GL_PREFIX(_dispatch_stub_649, _dispatch_stub_649@24))
- GL_STUB(_dispatch_stub_650, _gloffset_DeleteFencesNV, _dispatch_stub_650@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_650, _dispatch_stub_650@8))
- GL_STUB(_dispatch_stub_651, _gloffset_FinishFenceNV, _dispatch_stub_651@4)
- HIDDEN(GL_PREFIX(_dispatch_stub_651, _dispatch_stub_651@4))
- GL_STUB(_dispatch_stub_652, _gloffset_GenFencesNV, _dispatch_stub_652@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_652, _dispatch_stub_652@8))
- GL_STUB(_dispatch_stub_653, _gloffset_GetFenceivNV, _dispatch_stub_653@12)
- HIDDEN(GL_PREFIX(_dispatch_stub_653, _dispatch_stub_653@12))
- GL_STUB(_dispatch_stub_654, _gloffset_IsFenceNV, _dispatch_stub_654@4)
- HIDDEN(GL_PREFIX(_dispatch_stub_654, _dispatch_stub_654@4))
- GL_STUB(_dispatch_stub_655, _gloffset_SetFenceNV, _dispatch_stub_655@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_655, _dispatch_stub_655@8))
- GL_STUB(_dispatch_stub_656, _gloffset_TestFenceNV, _dispatch_stub_656@4)
- HIDDEN(GL_PREFIX(_dispatch_stub_656, _dispatch_stub_656@4))
+ GL_STUB(_dispatch_stub_664, _gloffset_MultiModeDrawArraysIBM, _dispatch_stub_664@20)
+ HIDDEN(GL_PREFIX(_dispatch_stub_664, _dispatch_stub_664@20))
+ GL_STUB(_dispatch_stub_665, _gloffset_MultiModeDrawElementsIBM, _dispatch_stub_665@24)
+ HIDDEN(GL_PREFIX(_dispatch_stub_665, _dispatch_stub_665@24))
+ GL_STUB(_dispatch_stub_666, _gloffset_DeleteFencesNV, _dispatch_stub_666@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_666, _dispatch_stub_666@8))
+ GL_STUB(_dispatch_stub_667, _gloffset_FinishFenceNV, _dispatch_stub_667@4)
+ HIDDEN(GL_PREFIX(_dispatch_stub_667, _dispatch_stub_667@4))
+ GL_STUB(_dispatch_stub_668, _gloffset_GenFencesNV, _dispatch_stub_668@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_668, _dispatch_stub_668@8))
+ GL_STUB(_dispatch_stub_669, _gloffset_GetFenceivNV, _dispatch_stub_669@12)
+ HIDDEN(GL_PREFIX(_dispatch_stub_669, _dispatch_stub_669@12))
+ GL_STUB(_dispatch_stub_670, _gloffset_IsFenceNV, _dispatch_stub_670@4)
+ HIDDEN(GL_PREFIX(_dispatch_stub_670, _dispatch_stub_670@4))
+ GL_STUB(_dispatch_stub_671, _gloffset_SetFenceNV, _dispatch_stub_671@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_671, _dispatch_stub_671@8))
+ GL_STUB(_dispatch_stub_672, _gloffset_TestFenceNV, _dispatch_stub_672@4)
+ HIDDEN(GL_PREFIX(_dispatch_stub_672, _dispatch_stub_672@4))
GL_STUB(AreProgramsResidentNV, _gloffset_AreProgramsResidentNV, AreProgramsResidentNV@12)
GL_STUB(BindProgramNV, _gloffset_BindProgramNV, BindProgramNV@8)
GL_STUB(DeleteProgramsNV, _gloffset_DeleteProgramsNV, DeleteProgramsNV@8)
@@ -888,6 +904,10 @@ GLNAME(gl_dispatch_functions_start):
GL_STUB(VertexAttribs4fvNV, _gloffset_VertexAttribs4fvNV, VertexAttribs4fvNV@12)
GL_STUB(VertexAttribs4svNV, _gloffset_VertexAttribs4svNV, VertexAttribs4svNV@12)
GL_STUB(VertexAttribs4ubvNV, _gloffset_VertexAttribs4ubvNV, VertexAttribs4ubvNV@12)
+ GL_STUB(GetTexBumpParameterfvATI, _gloffset_GetTexBumpParameterfvATI, GetTexBumpParameterfvATI@8)
+ GL_STUB(GetTexBumpParameterivATI, _gloffset_GetTexBumpParameterivATI, GetTexBumpParameterivATI@8)
+ GL_STUB(TexBumpParameterfvATI, _gloffset_TexBumpParameterfvATI, TexBumpParameterfvATI@8)
+ GL_STUB(TexBumpParameterivATI, _gloffset_TexBumpParameterivATI, TexBumpParameterivATI@8)
GL_STUB(AlphaFragmentOp1ATI, _gloffset_AlphaFragmentOp1ATI, AlphaFragmentOp1ATI@24)
GL_STUB(AlphaFragmentOp2ATI, _gloffset_AlphaFragmentOp2ATI, AlphaFragmentOp2ATI@36)
GL_STUB(AlphaFragmentOp3ATI, _gloffset_AlphaFragmentOp3ATI, AlphaFragmentOp3ATI@48)
@@ -904,26 +924,26 @@ GLNAME(gl_dispatch_functions_start):
GL_STUB(SetFragmentShaderConstantATI, _gloffset_SetFragmentShaderConstantATI, SetFragmentShaderConstantATI@8)
GL_STUB(PointParameteriNV, _gloffset_PointParameteriNV, PointParameteriNV@8)
GL_STUB(PointParameterivNV, _gloffset_PointParameterivNV, PointParameterivNV@8)
- GL_STUB(_dispatch_stub_733, _gloffset_ActiveStencilFaceEXT, _dispatch_stub_733@4)
- HIDDEN(GL_PREFIX(_dispatch_stub_733, _dispatch_stub_733@4))
- GL_STUB(_dispatch_stub_734, _gloffset_BindVertexArrayAPPLE, _dispatch_stub_734@4)
- HIDDEN(GL_PREFIX(_dispatch_stub_734, _dispatch_stub_734@4))
- GL_STUB(_dispatch_stub_735, _gloffset_DeleteVertexArraysAPPLE, _dispatch_stub_735@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_735, _dispatch_stub_735@8))
- GL_STUB(_dispatch_stub_736, _gloffset_GenVertexArraysAPPLE, _dispatch_stub_736@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_736, _dispatch_stub_736@8))
- GL_STUB(_dispatch_stub_737, _gloffset_IsVertexArrayAPPLE, _dispatch_stub_737@4)
- HIDDEN(GL_PREFIX(_dispatch_stub_737, _dispatch_stub_737@4))
+ GL_STUB(_dispatch_stub_753, _gloffset_ActiveStencilFaceEXT, _dispatch_stub_753@4)
+ HIDDEN(GL_PREFIX(_dispatch_stub_753, _dispatch_stub_753@4))
+ GL_STUB(_dispatch_stub_754, _gloffset_BindVertexArrayAPPLE, _dispatch_stub_754@4)
+ HIDDEN(GL_PREFIX(_dispatch_stub_754, _dispatch_stub_754@4))
+ GL_STUB(_dispatch_stub_755, _gloffset_DeleteVertexArraysAPPLE, _dispatch_stub_755@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_755, _dispatch_stub_755@8))
+ GL_STUB(_dispatch_stub_756, _gloffset_GenVertexArraysAPPLE, _dispatch_stub_756@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_756, _dispatch_stub_756@8))
+ GL_STUB(_dispatch_stub_757, _gloffset_IsVertexArrayAPPLE, _dispatch_stub_757@4)
+ HIDDEN(GL_PREFIX(_dispatch_stub_757, _dispatch_stub_757@4))
GL_STUB(GetProgramNamedParameterdvNV, _gloffset_GetProgramNamedParameterdvNV, GetProgramNamedParameterdvNV@16)
GL_STUB(GetProgramNamedParameterfvNV, _gloffset_GetProgramNamedParameterfvNV, GetProgramNamedParameterfvNV@16)
GL_STUB(ProgramNamedParameter4dNV, _gloffset_ProgramNamedParameter4dNV, ProgramNamedParameter4dNV@44)
GL_STUB(ProgramNamedParameter4dvNV, _gloffset_ProgramNamedParameter4dvNV, ProgramNamedParameter4dvNV@16)
GL_STUB(ProgramNamedParameter4fNV, _gloffset_ProgramNamedParameter4fNV, ProgramNamedParameter4fNV@28)
GL_STUB(ProgramNamedParameter4fvNV, _gloffset_ProgramNamedParameter4fvNV, ProgramNamedParameter4fvNV@16)
- GL_STUB(_dispatch_stub_744, _gloffset_DepthBoundsEXT, _dispatch_stub_744@16)
- HIDDEN(GL_PREFIX(_dispatch_stub_744, _dispatch_stub_744@16))
- GL_STUB(_dispatch_stub_745, _gloffset_BlendEquationSeparateEXT, _dispatch_stub_745@8)
- HIDDEN(GL_PREFIX(_dispatch_stub_745, _dispatch_stub_745@8))
+ GL_STUB(_dispatch_stub_764, _gloffset_DepthBoundsEXT, _dispatch_stub_764@16)
+ HIDDEN(GL_PREFIX(_dispatch_stub_764, _dispatch_stub_764@16))
+ GL_STUB(_dispatch_stub_765, _gloffset_BlendEquationSeparateEXT, _dispatch_stub_765@8)
+ HIDDEN(GL_PREFIX(_dispatch_stub_765, _dispatch_stub_765@8))
GL_STUB(BindFramebufferEXT, _gloffset_BindFramebufferEXT, BindFramebufferEXT@8)
GL_STUB(BindRenderbufferEXT, _gloffset_BindRenderbufferEXT, BindRenderbufferEXT@8)
GL_STUB(CheckFramebufferStatusEXT, _gloffset_CheckFramebufferStatusEXT, CheckFramebufferStatusEXT@4)
@@ -941,19 +961,28 @@ GLNAME(gl_dispatch_functions_start):
GL_STUB(IsFramebufferEXT, _gloffset_IsFramebufferEXT, IsFramebufferEXT@4)
GL_STUB(IsRenderbufferEXT, _gloffset_IsRenderbufferEXT, IsRenderbufferEXT@4)
GL_STUB(RenderbufferStorageEXT, _gloffset_RenderbufferStorageEXT, RenderbufferStorageEXT@16)
- GL_STUB(_dispatch_stub_763, _gloffset_BlitFramebufferEXT, _dispatch_stub_763@40)
- HIDDEN(GL_PREFIX(_dispatch_stub_763, _dispatch_stub_763@40))
+ GL_STUB(_dispatch_stub_783, _gloffset_BlitFramebufferEXT, _dispatch_stub_783@40)
+ HIDDEN(GL_PREFIX(_dispatch_stub_783, _dispatch_stub_783@40))
+ GL_STUB(_dispatch_stub_784, _gloffset_BufferParameteriAPPLE, _dispatch_stub_784@12)
+ HIDDEN(GL_PREFIX(_dispatch_stub_784, _dispatch_stub_784@12))
+ GL_STUB(_dispatch_stub_785, _gloffset_FlushMappedBufferRangeAPPLE, _dispatch_stub_785@12)
+ HIDDEN(GL_PREFIX(_dispatch_stub_785, _dispatch_stub_785@12))
GL_STUB(FramebufferTextureLayerEXT, _gloffset_FramebufferTextureLayerEXT, FramebufferTextureLayerEXT@20)
- GL_STUB(_dispatch_stub_765, _gloffset_StencilFuncSeparateATI, _dispatch_stub_765@16)
- HIDDEN(GL_PREFIX(_dispatch_stub_765, _dispatch_stub_765@16))
- GL_STUB(_dispatch_stub_766, _gloffset_ProgramEnvParameters4fvEXT, _dispatch_stub_766@16)
- HIDDEN(GL_PREFIX(_dispatch_stub_766, _dispatch_stub_766@16))
- GL_STUB(_dispatch_stub_767, _gloffset_ProgramLocalParameters4fvEXT, _dispatch_stub_767@16)
- HIDDEN(GL_PREFIX(_dispatch_stub_767, _dispatch_stub_767@16))
- GL_STUB(_dispatch_stub_768, _gloffset_GetQueryObjecti64vEXT, _dispatch_stub_768@12)
- HIDDEN(GL_PREFIX(_dispatch_stub_768, _dispatch_stub_768@12))
- GL_STUB(_dispatch_stub_769, _gloffset_GetQueryObjectui64vEXT, _dispatch_stub_769@12)
- HIDDEN(GL_PREFIX(_dispatch_stub_769, _dispatch_stub_769@12))
+ GL_STUB(ProvokingVertexEXT, _gloffset_ProvokingVertexEXT, ProvokingVertexEXT@4)
+ GL_STUB(_dispatch_stub_788, _gloffset_GetTexParameterPointervAPPLE, _dispatch_stub_788@12)
+ HIDDEN(GL_PREFIX(_dispatch_stub_788, _dispatch_stub_788@12))
+ GL_STUB(_dispatch_stub_789, _gloffset_TextureRangeAPPLE, _dispatch_stub_789@12)
+ HIDDEN(GL_PREFIX(_dispatch_stub_789, _dispatch_stub_789@12))
+ GL_STUB(_dispatch_stub_790, _gloffset_StencilFuncSeparateATI, _dispatch_stub_790@16)
+ HIDDEN(GL_PREFIX(_dispatch_stub_790, _dispatch_stub_790@16))
+ GL_STUB(_dispatch_stub_791, _gloffset_ProgramEnvParameters4fvEXT, _dispatch_stub_791@16)
+ HIDDEN(GL_PREFIX(_dispatch_stub_791, _dispatch_stub_791@16))
+ GL_STUB(_dispatch_stub_792, _gloffset_ProgramLocalParameters4fvEXT, _dispatch_stub_792@16)
+ HIDDEN(GL_PREFIX(_dispatch_stub_792, _dispatch_stub_792@16))
+ GL_STUB(_dispatch_stub_793, _gloffset_GetQueryObjecti64vEXT, _dispatch_stub_793@12)
+ HIDDEN(GL_PREFIX(_dispatch_stub_793, _dispatch_stub_793@12))
+ GL_STUB(_dispatch_stub_794, _gloffset_GetQueryObjectui64vEXT, _dispatch_stub_794@12)
+ HIDDEN(GL_PREFIX(_dispatch_stub_794, _dispatch_stub_794@12))
GL_STUB_ALIAS(ArrayElementEXT, _gloffset_ArrayElement, ArrayElementEXT@4, ArrayElement, ArrayElement@4)
GL_STUB_ALIAS(BindTextureEXT, _gloffset_BindTexture, BindTextureEXT@8, BindTexture, BindTexture@8)
GL_STUB_ALIAS(DrawArraysEXT, _gloffset_DrawArrays, DrawArraysEXT@12, DrawArrays, DrawArrays@12)
@@ -1269,6 +1298,24 @@ GLNAME(gl_dispatch_functions_start):
GL_STUB_ALIAS(IsProgramARB, _gloffset_IsProgramNV, IsProgramARB@4, IsProgramNV, IsProgramNV@4)
GL_STUB_ALIAS(PointParameteri, _gloffset_PointParameteriNV, PointParameteri@8, PointParameteriNV, PointParameteriNV@8)
GL_STUB_ALIAS(PointParameteriv, _gloffset_PointParameterivNV, PointParameteriv@8, PointParameterivNV, PointParameterivNV@8)
+ GL_STUB_ALIAS(BindFramebuffer, _gloffset_BindFramebufferEXT, BindFramebuffer@8, BindFramebufferEXT, BindFramebufferEXT@8)
+ GL_STUB_ALIAS(BindRenderbuffer, _gloffset_BindRenderbufferEXT, BindRenderbuffer@8, BindRenderbufferEXT, BindRenderbufferEXT@8)
+ GL_STUB_ALIAS(CheckFramebufferStatus, _gloffset_CheckFramebufferStatusEXT, CheckFramebufferStatus@4, CheckFramebufferStatusEXT, CheckFramebufferStatusEXT@4)
+ GL_STUB_ALIAS(DeleteFramebuffers, _gloffset_DeleteFramebuffersEXT, DeleteFramebuffers@8, DeleteFramebuffersEXT, DeleteFramebuffersEXT@8)
+ GL_STUB_ALIAS(DeleteRenderbuffers, _gloffset_DeleteRenderbuffersEXT, DeleteRenderbuffers@8, DeleteRenderbuffersEXT, DeleteRenderbuffersEXT@8)
+ GL_STUB_ALIAS(FramebufferRenderbuffer, _gloffset_FramebufferRenderbufferEXT, FramebufferRenderbuffer@16, FramebufferRenderbufferEXT, FramebufferRenderbufferEXT@16)
+ GL_STUB_ALIAS(FramebufferTexture1D, _gloffset_FramebufferTexture1DEXT, FramebufferTexture1D@20, FramebufferTexture1DEXT, FramebufferTexture1DEXT@20)
+ GL_STUB_ALIAS(FramebufferTexture2D, _gloffset_FramebufferTexture2DEXT, FramebufferTexture2D@20, FramebufferTexture2DEXT, FramebufferTexture2DEXT@20)
+ GL_STUB_ALIAS(FramebufferTexture3D, _gloffset_FramebufferTexture3DEXT, FramebufferTexture3D@24, FramebufferTexture3DEXT, FramebufferTexture3DEXT@24)
+ GL_STUB_ALIAS(GenFramebuffers, _gloffset_GenFramebuffersEXT, GenFramebuffers@8, GenFramebuffersEXT, GenFramebuffersEXT@8)
+ GL_STUB_ALIAS(GenRenderbuffers, _gloffset_GenRenderbuffersEXT, GenRenderbuffers@8, GenRenderbuffersEXT, GenRenderbuffersEXT@8)
+ GL_STUB_ALIAS(GenerateMipmap, _gloffset_GenerateMipmapEXT, GenerateMipmap@4, GenerateMipmapEXT, GenerateMipmapEXT@4)
+ GL_STUB_ALIAS(GetFramebufferAttachmentParameteriv, _gloffset_GetFramebufferAttachmentParameterivEXT, GetFramebufferAttachmentParameteriv@16, GetFramebufferAttachmentParameterivEXT, GetFramebufferAttachmentParameterivEXT@16)
+ GL_STUB_ALIAS(GetRenderbufferParameteriv, _gloffset_GetRenderbufferParameterivEXT, GetRenderbufferParameteriv@12, GetRenderbufferParameterivEXT, GetRenderbufferParameterivEXT@12)
+ GL_STUB_ALIAS(IsFramebuffer, _gloffset_IsFramebufferEXT, IsFramebuffer@4, IsFramebufferEXT, IsFramebufferEXT@4)
+ GL_STUB_ALIAS(IsRenderbuffer, _gloffset_IsRenderbufferEXT, IsRenderbuffer@4, IsRenderbufferEXT, IsRenderbufferEXT@4)
+ GL_STUB_ALIAS(RenderbufferStorage, _gloffset_RenderbufferStorageEXT, RenderbufferStorage@16, RenderbufferStorageEXT, RenderbufferStorageEXT@16)
+ GL_STUB_ALIAS(FramebufferTextureLayer, _gloffset_FramebufferTextureLayerEXT, FramebufferTextureLayer@20, FramebufferTextureLayerEXT, FramebufferTextureLayerEXT@20)
GLOBL GLNAME(gl_dispatch_functions_end)
HIDDEN(GLNAME(gl_dispatch_functions_end))
diff --git a/src/mesa/x86/rtasm/x86sse.c b/src/mesa/x86/rtasm/x86sse.c
index e68f8dfec1..5aedf5b04b 100644
--- a/src/mesa/x86/rtasm/x86sse.c
+++ b/src/mesa/x86/rtasm/x86sse.c
@@ -1,3 +1,4 @@
+#ifdef USE_X86_ASM
#if defined(__i386__) || defined(__386__)
#include "main/imports.h"
@@ -290,7 +291,7 @@ void x86_call( struct x86_function *p, void (*label)())
void x86_call( struct x86_function *p, struct x86_reg reg)
{
emit_1ub(p, 0xff);
- emit_modrm(p, reg, reg);
+ emit_modrm_noreg(p, 2, reg);
}
#endif
@@ -1192,3 +1193,9 @@ void x86sse_dummy( void )
}
#endif
+
+#else /* USE_X86_ASM */
+
+int x86sse_c_dummy_var; /* silence warning */
+
+#endif /* USE_X86_ASM */
diff --git a/src/mesa/x86/sse.c b/src/mesa/x86/sse.c
index 1c185387c6..aef15b5315 100644
--- a/src/mesa/x86/sse.c
+++ b/src/mesa/x86/sse.c
@@ -33,7 +33,7 @@
#include "tnl/t_context.h"
#include "sse.h"
-#include "common_x86_macros.h"
+#include "x86_xform.h"
#ifdef DEBUG_MATH
#include "math/m_debug.h"
diff --git a/src/mesa/x86/sse_xform2.S b/src/mesa/x86/sse_xform2.S
index 91b82e7297..b490d4c169 100644
--- a/src/mesa/x86/sse_xform2.S
+++ b/src/mesa/x86/sse_xform2.S
@@ -186,6 +186,7 @@ GLNAME(_mesa_sse_transform_points2_3d_no_rot):
MOV_L( REGOFF(V4F_START, EDI), EDI ) /* ptr to first dest vertex */
ADD_L( EDI, ECX ) /* count += dest ptr */
+ PXOR( XMM0, XMM0 )
ALIGNTEXT32
MOVSS ( M(0), XMM1 ) /* - | - | - | m0 */
diff --git a/src/mesa/x86/sse_xform3.S b/src/mesa/x86/sse_xform3.S
index 1fc79ef21b..8a79eeda18 100644
--- a/src/mesa/x86/sse_xform3.S
+++ b/src/mesa/x86/sse_xform3.S
@@ -198,6 +198,7 @@ GLNAME(_mesa_sse_transform_points3_3d_no_rot):
MOV_L( REGOFF(V4F_START, EDI), EDI ) /* ptr to first dest vertex */
ADD_L( EDI, ECX ) /* count += dest ptr */
+ PXOR( XMM0, XMM0 )
ALIGNTEXT32
MOVSS ( M(0), XMM1 ) /* - | - | - | m0 */
diff --git a/src/mesa/x86/x86.c b/src/mesa/x86/x86_xform.c
index ce649f66b0..52f6b25d81 100644
--- a/src/mesa/x86/x86.c
+++ b/src/mesa/x86/x86_xform.c
@@ -32,8 +32,17 @@
#include "math/m_xform.h"
#include "tnl/t_context.h"
-#include "x86.h"
-#include "common_x86_macros.h"
+#include "x86_xform.h"
+#include "common_x86_asm.h"
+
+#ifdef USE_X86_ASM
+#ifdef USE_3DNOW_ASM
+#include "3dnow.h"
+#endif
+#ifdef USE_SSE_ASM
+#include "sse.h"
+#endif
+#endif
#ifdef DEBUG_MATH
#include "math/m_debug.h"
@@ -51,21 +60,24 @@ _mesa_x86_cliptest_points4( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask );
+ GLubyte *andMask,
+ GLboolean viewport_z_clip );
extern GLvector4f * _ASMAPI
_mesa_x86_cliptest_points4_np( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
- GLubyte *andMask );
+ GLubyte *andMask,
+ GLboolean viewport_z_clip );
extern void _ASMAPI
_mesa_v16_x86_cliptest_points4( GLfloat *first_vert,
GLfloat *last_vert,
GLubyte *or_mask,
GLubyte *and_mask,
- GLubyte *clip_mask );
+ GLubyte *clip_mask,
+ GLboolean viewport_z_clip );
extern void _ASMAPI
_mesa_v16_x86_general_xform( GLfloat *dest,
@@ -76,9 +88,9 @@ _mesa_v16_x86_general_xform( GLfloat *dest,
#endif
-void _mesa_init_x86_transform_asm( void )
-{
#ifdef USE_X86_ASM
+static void _mesa_init_x86_transform_asm( void )
+{
ASSIGN_XFORM_GROUP( x86, 2 );
ASSIGN_XFORM_GROUP( x86, 3 );
ASSIGN_XFORM_GROUP( x86, 4 );
@@ -90,6 +102,55 @@ void _mesa_init_x86_transform_asm( void )
_math_test_all_transform_functions( "x86" );
_math_test_all_cliptest_functions( "x86" );
#endif
-#endif
}
+#endif
+
+void _mesa_init_all_x86_transform_asm( void )
+{
+ _mesa_get_x86_features();
+
+#ifdef USE_X86_ASM
+ if ( _mesa_x86_cpu_features ) {
+ _mesa_init_x86_transform_asm();
+ }
+
+#ifdef USE_MMX_ASM
+ if ( cpu_has_mmx ) {
+ if ( _mesa_getenv( "MESA_NO_MMX" ) == 0 ) {
+ _mesa_debug(NULL, "MMX cpu detected.\n");
+ } else {
+ _mesa_x86_cpu_features &= ~(X86_FEATURE_MMX);
+ }
+ }
+#endif
+
+#ifdef USE_3DNOW_ASM
+ if ( cpu_has_3dnow ) {
+ if ( _mesa_getenv( "MESA_NO_3DNOW" ) == 0 ) {
+ _mesa_debug(NULL, "3DNow! cpu detected.\n");
+ _mesa_init_3dnow_transform_asm();
+ } else {
+ _mesa_x86_cpu_features &= ~(X86_FEATURE_3DNOW);
+ }
+ }
+#endif
+
+#ifdef USE_SSE_ASM
+ if ( cpu_has_xmm ) {
+ if ( _mesa_getenv( "MESA_NO_SSE" ) == 0 ) {
+ _mesa_debug(NULL, "SSE cpu detected.\n");
+ if ( _mesa_getenv( "MESA_FORCE_SSE" ) == 0 ) {
+ _mesa_check_os_sse_support();
+ }
+ if ( cpu_has_xmm ) {
+ _mesa_init_sse_transform_asm();
+ }
+ } else {
+ _mesa_debug(NULL, "SSE cpu detected, but switched off by user.\n");
+ _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
+ }
+ }
+#endif
+#endif
+}
diff --git a/src/mesa/x86/common_x86_macros.h b/src/mesa/x86/x86_xform.h
index 462f32b3f2..e886d9add2 100644
--- a/src/mesa/x86/common_x86_macros.h
+++ b/src/mesa/x86/x86_xform.h
@@ -26,8 +26,8 @@
* Gareth Hughes
*/
-#ifndef __COMMON_X86_MACROS_H__
-#define __COMMON_X86_MACROS_H__
+#ifndef X86_XFORM_H
+#define X86_XFORM_H
/* =============================================================
diff --git a/src/xvmc/Makefile b/src/xvmc/Makefile
new file mode 100644
index 0000000000..7badcfd264
--- /dev/null
+++ b/src/xvmc/Makefile
@@ -0,0 +1,73 @@
+TARGET = libXvMCg3dvl.so
+SONAME = libXvMCg3dvl.so.1
+GALLIUMDIR = ../gallium
+
+OBJECTS = block.o surface.o context.o subpicture.o attributes.o
+
+ifeq (${DRIVER}, softpipe)
+OBJECTS += ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+endif
+
+CFLAGS += -g -fPIC -Wall -Werror=implicit-function-declaration \
+ -I${GALLIUMDIR}/state_trackers/g3dvl \
+ -I${GALLIUMDIR}/winsys/g3dvl \
+ -I${GALLIUMDIR}/include \
+ -I${GALLIUMDIR}/auxiliary \
+ -I${GALLIUMDIR}/drivers
+
+ifeq (${DRIVER}, softpipe)
+LDFLAGS += -L${GALLIUMDIR}/state_trackers/g3dvl \
+ -L${GALLIUMDIR}/drivers/softpipe \
+ -L${GALLIUMDIR}/auxiliary/tgsi \
+ -L${GALLIUMDIR}/auxiliary/draw \
+ -L${GALLIUMDIR}/auxiliary/translate \
+ -L${GALLIUMDIR}/auxiliary/cso_cache \
+ -L${GALLIUMDIR}/auxiliary/util \
+ -L${GALLIUMDIR}/auxiliary/rtasm
+else
+LDFLAGS += -L${GALLIUMDIR}/state_trackers/g3dvl \
+ -L${GALLIUMDIR}/winsys/g3dvl/nouveau \
+ -L${GALLIUMDIR}/auxiliary/util
+endif
+
+ifeq (${DRIVER}, softpipe)
+LIBS += -lg3dvl -lsoftpipe -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lutil -lm
+else
+LIBS += -lg3dvl -lnouveau_dri -lutil
+endif
+
+#############################################
+
+ifeq (${DRIVER}, softpipe)
+.PHONY = all clean g3dvl
+else
+.PHONY = all clean g3dvl nouveau_winsys
+endif
+
+all: ${TARGET}
+
+ifeq (${DRIVER}, softpipe)
+${TARGET}: ${OBJECTS} g3dvl
+ $(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ ${OBJECTS} ${LIBS}
+
+g3dvl:
+ cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE}
+
+clean:
+ cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} clean
+ rm -rf ${OBJECTS} ${TARGET}
+else
+${TARGET}: ${OBJECTS} g3dvl nouveau_winsys
+ $(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ ${OBJECTS} ${LIBS}
+
+g3dvl:
+ cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE}
+
+nouveau_winsys:
+ cd ${GALLIUMDIR}/winsys/g3dvl/nouveau; ${MAKE}
+
+clean:
+ cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} clean
+ cd ${GALLIUMDIR}/winsys/g3dvl/nouveau; ${MAKE} clean
+ rm -rf ${OBJECTS} ${TARGET}
+endif
diff --git a/src/xvmc/attributes.c b/src/xvmc/attributes.c
new file mode 100644
index 0000000000..674524b8b8
--- /dev/null
+++ b/src/xvmc/attributes.c
@@ -0,0 +1,20 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+
+XvAttribute* XvMCQueryAttributes(Display *display, XvMCContext *context, int *number)
+{
+ return NULL;
+}
+
+Status XvMCSetAttribute(Display *display, XvMCContext *context, Atom attribute, int value)
+{
+ return BadImplementation;
+}
+
+Status XvMCGetAttribute(Display *display, XvMCContext *context, Atom attribute, int *value)
+{
+ return BadImplementation;
+}
+
diff --git a/src/xvmc/block.c b/src/xvmc/block.c
new file mode 100644
index 0000000000..b38a89be09
--- /dev/null
+++ b/src/xvmc/block.c
@@ -0,0 +1,79 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMC.h>
+#include <util/u_memory.h>
+#include <vl_display.h>
+#include <vl_screen.h>
+#include <vl_context.h>
+
+#define BLOCK_SIZE (64 * 2)
+
+Status XvMCCreateBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks)
+{
+ struct vlContext *vl_ctx;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+ if (num_blocks == 0)
+ return BadValue;
+
+ assert(blocks);
+
+ vl_ctx = context->privData;
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ blocks->context_id = context->context_id;
+ blocks->num_blocks = num_blocks;
+ blocks->blocks = MALLOC(BLOCK_SIZE * num_blocks);
+ /* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */
+ blocks->privData = display;
+
+ return Success;
+}
+
+Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *blocks)
+{
+ assert(display);
+ assert(blocks);
+ assert(display == blocks->privData);
+ FREE(blocks->blocks);
+
+ return Success;
+}
+
+Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks)
+{
+ struct vlContext *vl_ctx;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+ if (num_blocks == 0)
+ return BadValue;
+
+ assert(blocks);
+
+ vl_ctx = context->privData;
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ blocks->context_id = context->context_id;
+ blocks->num_blocks = num_blocks;
+ blocks->macro_blocks = MALLOC(sizeof(XvMCMacroBlock) * num_blocks);
+ /* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */
+ blocks->privData = display;
+
+ return Success;
+}
+
+Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *blocks)
+{
+ assert(display);
+ assert(blocks);
+ assert(display == blocks->privData);
+ FREE(blocks->macro_blocks);
+
+ return Success;
+}
diff --git a/src/xvmc/context.c b/src/xvmc/context.c
new file mode 100644
index 0000000000..273f658029
--- /dev/null
+++ b/src/xvmc/context.c
@@ -0,0 +1,207 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+#include <pipe/p_context.h>
+#include <vl_display.h>
+#include <vl_screen.h>
+#include <vl_context.h>
+#include <vl_winsys.h>
+
+static Status Validate
+(
+ Display *display,
+ XvPortID port,
+ int surface_type_id,
+ unsigned int width,
+ unsigned int height,
+ int flags,
+ int *found_port,
+ int *chroma_format,
+ int *mc_type
+)
+{
+ unsigned int found_surface = 0;
+ XvAdaptorInfo *adaptor_info;
+ unsigned int num_adaptors;
+ int num_types;
+ unsigned int max_width, max_height;
+ Status ret;
+ unsigned int i, j, k;
+
+ assert(display && chroma_format);
+
+ *found_port = 0;
+
+ ret = XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info);
+ if (ret != Success)
+ return ret;
+
+ /* Scan through all adaptors looking for this port and surface */
+ for (i = 0; i < num_adaptors && !*found_port; ++i)
+ {
+ /* Scan through all ports of this adaptor looking for our port */
+ for (j = 0; j < adaptor_info[i].num_ports && !*found_port; ++j)
+ {
+ /* If this is our port, scan through all its surfaces looking for our surface */
+ if (adaptor_info[i].base_id + j == port)
+ {
+ XvMCSurfaceInfo *surface_info;
+
+ *found_port = 1;
+ surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
+
+ if (surface_info)
+ {
+ for (k = 0; k < num_types && !found_surface; ++k)
+ {
+ if (surface_info[k].surface_type_id == surface_type_id)
+ {
+ found_surface = 1;
+ max_width = surface_info[k].max_width;
+ max_height = surface_info[k].max_height;
+ *chroma_format = surface_info[k].chroma_format;
+ *mc_type = surface_info[k].mc_type;
+ }
+ }
+
+ XFree(surface_info);
+ }
+ else
+ {
+ XvFreeAdaptorInfo(adaptor_info);
+ return BadAlloc;
+ }
+ }
+ }
+ }
+
+ XvFreeAdaptorInfo(adaptor_info);
+
+ if (!*found_port)
+ return XvBadPort;
+ if (!found_surface)
+ return BadMatch;
+ if (width > max_width || height > max_height)
+ return BadValue;
+ if (flags != XVMC_DIRECT && flags != 0)
+ return BadValue;
+
+ return Success;
+}
+
+static enum vlProfile ProfileToVL(int xvmc_profile)
+{
+ if (xvmc_profile & XVMC_MPEG_1)
+ assert(0);
+ else if (xvmc_profile & XVMC_MPEG_2)
+ return vlProfileMpeg2Main;
+ else if (xvmc_profile & XVMC_H263)
+ assert(0);
+ else if (xvmc_profile & XVMC_MPEG_4)
+ assert(0);
+ else
+ assert(0);
+
+ return -1;
+}
+
+static enum vlEntryPoint EntryToVL(int xvmc_entry)
+{
+ return xvmc_entry & XVMC_IDCT ? vlEntryPointIDCT : vlEntryPointMC;
+}
+
+static enum vlFormat FormatToVL(int xvmc_format)
+{
+ switch (xvmc_format)
+ {
+ case XVMC_CHROMA_FORMAT_420:
+ return vlFormatYCbCr420;
+ case XVMC_CHROMA_FORMAT_422:
+ return vlFormatYCbCr422;
+ case XVMC_CHROMA_FORMAT_444:
+ return vlFormatYCbCr444;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context)
+{
+ int found_port;
+ int chroma_format;
+ int mc_type;
+ Status ret;
+ struct vlDisplay *vl_dpy;
+ struct vlScreen *vl_scrn;
+ struct vlContext *vl_ctx;
+ struct pipe_context *pipe;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+
+ ret = Validate(display, port, surface_type_id, width, height, flags, &found_port, &chroma_format, &mc_type);
+
+ /* XXX: Success and XvBadPort have the same value */
+ if (ret != Success || !found_port)
+ return ret;
+
+ /* XXX: Assumes default screen, should check which screen port is on */
+ pipe = create_pipe_context(display, XDefaultScreen(display));
+
+ assert(pipe);
+
+ vlCreateDisplay(display, &vl_dpy);
+ vlCreateScreen(vl_dpy, XDefaultScreen(display), pipe->screen, &vl_scrn);
+ vlCreateContext
+ (
+ vl_scrn,
+ pipe,
+ width,
+ height,
+ FormatToVL(chroma_format),
+ ProfileToVL(mc_type),
+ EntryToVL(mc_type),
+ &vl_ctx
+ );
+
+ context->context_id = XAllocID(display);
+ context->surface_type_id = surface_type_id;
+ context->width = width;
+ context->height = height;
+ context->flags = flags;
+ context->port = port;
+ context->privData = vl_ctx;
+
+ return Success;
+}
+
+Status XvMCDestroyContext(Display *display, XvMCContext *context)
+{
+ struct vlContext *vl_ctx;
+ struct vlScreen *vl_screen;
+ struct vlDisplay *vl_dpy;
+ struct pipe_context *pipe;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+
+ vl_ctx = context->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ pipe = vlGetPipeContext(vl_ctx);
+ vl_screen = vlContextGetScreen(vl_ctx);
+ vl_dpy = vlGetDisplay(vl_screen);
+ vlDestroyContext(vl_ctx);
+ vlDestroyScreen(vl_screen);
+ vlDestroyDisplay(vl_dpy);
+ destroy_pipe_context(pipe);
+
+ return Success;
+}
diff --git a/src/xvmc/subpicture.c b/src/xvmc/subpicture.c
new file mode 100644
index 0000000000..c8f70c90d0
--- /dev/null
+++ b/src/xvmc/subpicture.c
@@ -0,0 +1,215 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+
+Status XvMCCreateSubpicture
+(
+ Display *display,
+ XvMCContext *context,
+ XvMCSubpicture *subpicture,
+ unsigned short width,
+ unsigned short height,
+ int xvimage_id
+)
+{
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+
+ assert(subpicture);
+
+ if (width > 2048 || height > 2048)
+ return BadValue;
+
+ if (xvimage_id != 123)
+ return BadMatch;
+
+ subpicture->subpicture_id = XAllocID(display);
+ subpicture->context_id = context->context_id;
+ subpicture->xvimage_id = xvimage_id;
+ subpicture->width = width;
+ subpicture->height = height;
+ subpicture->num_palette_entries = 0;
+ subpicture->entry_bytes = 0;
+ subpicture->component_order[0] = 0;
+ subpicture->component_order[1] = 0;
+ subpicture->component_order[2] = 0;
+ subpicture->component_order[3] = 0;
+ /* TODO: subpicture->privData = ;*/
+
+ return Success;
+}
+
+Status XvMCClearSubpicture
+(
+ Display *display,
+ XvMCSubpicture *subpicture,
+ short x,
+ short y,
+ unsigned short width,
+ unsigned short height,
+ unsigned int color
+)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ /* TODO: Assert clear rect is within bounds? Or clip? */
+
+ return Success;
+}
+
+Status XvMCCompositeSubpicture
+(
+ Display *display,
+ XvMCSubpicture *subpicture,
+ XvImage *image,
+ short srcx,
+ short srcy,
+ unsigned short width,
+ unsigned short height,
+ short dstx,
+ short dsty
+)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(image);
+
+ if (subpicture->xvimage_id != image->id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+
+ return Success;
+}
+
+Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return BadImplementation;
+}
+
+Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture, unsigned char *palette)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(palette);
+
+ /* We don't support paletted subpictures */
+ return BadMatch;
+}
+
+Status XvMCBlendSubpicture
+(
+ Display *display,
+ XvMCSurface *target_surface,
+ XvMCSubpicture *subpicture,
+ short subx,
+ short suby,
+ unsigned short subw,
+ unsigned short subh,
+ short surfx,
+ short surfy,
+ unsigned short surfw,
+ unsigned short surfh
+)
+{
+ assert(display);
+
+ if (!target_surface)
+ return XvMCBadSurface;
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ if (target_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+ return Success;
+}
+
+Status XvMCBlendSubpicture2
+(
+ Display *display,
+ XvMCSurface *source_surface,
+ XvMCSurface *target_surface,
+ XvMCSubpicture *subpicture,
+ short subx,
+ short suby,
+ unsigned short subw,
+ unsigned short subh,
+ short surfx,
+ short surfy,
+ unsigned short surfw,
+ unsigned short surfh
+)
+{
+ assert(display);
+
+ if (!source_surface || !target_surface)
+ return XvMCBadSurface;
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ if (source_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ if (source_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+ return Success;
+}
+
+Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return Success;
+}
+
+Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return Success;
+}
+
+Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture, int *status)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(status);
+
+ /* TODO */
+ *status = 0;
+
+ return Success;
+}
+
diff --git a/src/xvmc/surface.c b/src/xvmc/surface.c
new file mode 100644
index 0000000000..7c5f45bd34
--- /dev/null
+++ b/src/xvmc/surface.c
@@ -0,0 +1,355 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMC.h>
+#include <vl_display.h>
+#include <vl_screen.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <vl_types.h>
+
+static enum vlMacroBlockType TypeToVL(int xvmc_mb_type)
+{
+ if (xvmc_mb_type & XVMC_MB_TYPE_INTRA)
+ return vlMacroBlockTypeIntra;
+ if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_FORWARD)
+ return vlMacroBlockTypeFwdPredicted;
+ if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_BACKWARD)
+ return vlMacroBlockTypeBkwdPredicted;
+ if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+ return vlMacroBlockTypeBiPredicted;
+
+ assert(0);
+
+ return -1;
+}
+
+static enum vlPictureType PictureToVL(int xvmc_pic)
+{
+ switch (xvmc_pic)
+ {
+ case XVMC_TOP_FIELD:
+ return vlPictureTypeTopField;
+ case XVMC_BOTTOM_FIELD:
+ return vlPictureTypeBottomField;
+ case XVMC_FRAME_PICTURE:
+ return vlPictureTypeFrame;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static enum vlMotionType MotionToVL(int xvmc_motion_type, int xvmc_dct_type)
+{
+ switch (xvmc_motion_type)
+ {
+ case XVMC_PREDICTION_FRAME:
+ return xvmc_dct_type == XVMC_DCT_TYPE_FIELD ? vlMotionType16x8 : vlMotionTypeFrame;
+ case XVMC_PREDICTION_FIELD:
+ return vlMotionTypeField;
+ case XVMC_PREDICTION_DUAL_PRIME:
+ return vlMotionTypeDualPrime;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface)
+{
+ struct vlContext *vl_ctx;
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_ctx = context->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ if (vlCreateSurface(vlContextGetScreen(vl_ctx),
+ context->width, context->height,
+ vlGetPictureFormat(vl_ctx),
+ &vl_sfc))
+ {
+ return BadAlloc;
+ }
+
+ vlBindToContext(vl_sfc, vl_ctx);
+
+ surface->surface_id = XAllocID(display);
+ surface->context_id = context->context_id;
+ surface->surface_type_id = context->surface_type_id;
+ surface->width = context->width;
+ surface->height = context->height;
+ surface->privData = vl_sfc;
+
+ return Success;
+}
+
+Status XvMCRenderSurface
+(
+ Display *display,
+ XvMCContext *context,
+ unsigned int picture_structure,
+ XvMCSurface *target_surface,
+ XvMCSurface *past_surface,
+ XvMCSurface *future_surface,
+ unsigned int flags,
+ unsigned int num_macroblocks,
+ unsigned int first_macroblock,
+ XvMCMacroBlockArray *macroblocks,
+ XvMCBlockArray *blocks
+)
+{
+ struct vlContext *vl_ctx;
+ struct vlSurface *target_vl_surface;
+ struct vlSurface *past_vl_surface;
+ struct vlSurface *future_vl_surface;
+ struct vlMpeg2MacroBlockBatch batch;
+ struct vlMpeg2MacroBlock vl_macroblocks[num_macroblocks];
+ unsigned int i;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+ if (!target_surface)
+ return XvMCBadSurface;
+
+ if
+ (
+ picture_structure != XVMC_TOP_FIELD &&
+ picture_structure != XVMC_BOTTOM_FIELD &&
+ picture_structure != XVMC_FRAME_PICTURE
+ )
+ return BadValue;
+ if (future_surface && !past_surface)
+ return BadMatch;
+
+ vl_ctx = context->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ target_vl_surface = target_surface->privData;
+ past_vl_surface = past_surface ? past_surface->privData : NULL;
+ future_vl_surface = future_surface ? future_surface->privData : NULL;
+
+ assert(context->context_id == target_surface->context_id);
+ assert(!past_surface || context->context_id == past_surface->context_id);
+ assert(!future_surface || context->context_id == future_surface->context_id);
+
+ assert(macroblocks);
+ assert(blocks);
+
+ assert(macroblocks->context_id == context->context_id);
+ assert(blocks->context_id == context->context_id);
+
+ assert(flags == 0 || flags == XVMC_SECOND_FIELD);
+
+ batch.past_surface = past_vl_surface;
+ batch.future_surface = future_vl_surface;
+ batch.picture_type = PictureToVL(picture_structure);
+ batch.field_order = flags & XVMC_SECOND_FIELD ? vlFieldOrderSecond : vlFieldOrderFirst;
+ batch.num_macroblocks = num_macroblocks;
+ batch.macroblocks = vl_macroblocks;
+
+ for (i = 0; i < num_macroblocks; ++i)
+ {
+ unsigned int j = first_macroblock + i;
+
+ unsigned int k, l, m;
+
+ batch.macroblocks[i].mbx = macroblocks->macro_blocks[j].x;
+ batch.macroblocks[i].mby = macroblocks->macro_blocks[j].y;
+ batch.macroblocks[i].mb_type = TypeToVL(macroblocks->macro_blocks[j].macroblock_type);
+ if (batch.macroblocks[i].mb_type != vlMacroBlockTypeIntra)
+ batch.macroblocks[i].mo_type = MotionToVL(macroblocks->macro_blocks[j].motion_type, macroblocks->macro_blocks[j].dct_type);
+ batch.macroblocks[i].dct_type = macroblocks->macro_blocks[j].dct_type == XVMC_DCT_TYPE_FIELD ? vlDCTTypeFieldCoded : vlDCTTypeFrameCoded;
+
+ for (k = 0; k < 2; ++k)
+ for (l = 0; l < 2; ++l)
+ for (m = 0; m < 2; ++m)
+ batch.macroblocks[i].PMV[k][l][m] = macroblocks->macro_blocks[j].PMV[k][l][m];
+
+ batch.macroblocks[i].cbp = macroblocks->macro_blocks[j].coded_block_pattern;
+ batch.macroblocks[i].blocks = blocks->blocks + (macroblocks->macro_blocks[j].index * 64);
+ }
+
+ vlRenderMacroBlocksMpeg2(&batch, target_vl_surface);
+
+ return Success;
+}
+
+Status XvMCFlushSurface(Display *display, XvMCSurface *surface)
+{
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ vlSurfaceFlush(vl_sfc);
+
+ return Success;
+}
+
+Status XvMCSyncSurface(Display *display, XvMCSurface *surface)
+{
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ vlSurfaceSync(vl_sfc);
+
+ return Success;
+}
+
+Status XvMCPutSurface
+(
+ Display *display,
+ XvMCSurface *surface,
+ Drawable drawable,
+ short srcx,
+ short srcy,
+ unsigned short srcw,
+ unsigned short srch,
+ short destx,
+ short desty,
+ unsigned short destw,
+ unsigned short desth,
+ int flags
+)
+{
+ Window root;
+ int x, y;
+ unsigned int width, height;
+ unsigned int border_width;
+ unsigned int depth;
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ if (XGetGeometry(display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
+ return BadDrawable;
+
+ assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
+
+ /* TODO: Correct for negative srcx,srcy & destx,desty by clipping */
+
+ assert(srcx + srcw - 1 < surface->width);
+ assert(srcy + srch - 1 < surface->height);
+ /* XXX: Some apps (mplayer) hit these asserts because they call
+ * this function after the window has been resized by the WM
+ * but before they've handled the corresponding XEvent and
+ * know about the new dimensions. The output will be clipped
+ * for a few frames until the app updates destw and desth.
+ */
+ /*assert(destx + destw - 1 < width);
+ assert(desty + desth - 1 < height);*/
+
+ vl_sfc = surface->privData;
+
+ vlPutPicture(vl_sfc, drawable, srcx, srcy, srcw, srch, destx, desty, destw, desth, width, height, PictureToVL(flags));
+
+ return Success;
+}
+
+Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status)
+{
+ struct vlSurface *vl_sfc;
+ enum vlResourceStatus res_status;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ assert(status);
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ vlSurfaceGetStatus(vl_sfc, &res_status);
+
+ switch (res_status)
+ {
+ case vlResourceStatusFree:
+ {
+ *status = 0;
+ break;
+ }
+ case vlResourceStatusRendering:
+ {
+ *status = XVMC_RENDERING;
+ break;
+ }
+ case vlResourceStatusDisplaying:
+ {
+ *status = XVMC_DISPLAYING;
+ break;
+ }
+ default:
+ assert(0);
+ }
+
+ return Success;
+}
+
+Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
+{
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ vlDestroySurface(vl_sfc);
+
+ return Success;
+}
+
+Status XvMCHideSurface(Display *display, XvMCSurface *surface)
+{
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ /* No op, only for overlaid rendering */
+
+ return Success;
+}
diff --git a/src/xvmc/tests/.gitignore b/src/xvmc/tests/.gitignore
new file mode 100644
index 0000000000..e1d2f9023d
--- /dev/null
+++ b/src/xvmc/tests/.gitignore
@@ -0,0 +1,5 @@
+test_context
+test_surface
+test_blocks
+test_rendering
+xvmc_bench
diff --git a/src/xvmc/tests/Makefile b/src/xvmc/tests/Makefile
new file mode 100644
index 0000000000..de095161d2
--- /dev/null
+++ b/src/xvmc/tests/Makefile
@@ -0,0 +1,27 @@
+CFLAGS += -g -Wall
+LDFLAGS +=
+LIBS += -lXvMCW -lXvMC -lXv
+
+#############################################
+
+.PHONY = all clean
+
+all: test_context test_surface test_blocks test_rendering xvmc_bench
+
+test_context: test_context.o testlib.o
+ $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_surface: test_surface.o testlib.o
+ $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_blocks: test_blocks.o testlib.o
+ $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_rendering: test_rendering.o testlib.o
+ $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+xvmc_bench: xvmc_bench.o testlib.o
+ $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+clean:
+ rm -rf *.o test_context test_surface test_blocks test_rendering xvmc_bench
diff --git a/src/xvmc/tests/test_blocks.c b/src/xvmc/tests/test_blocks.c
new file mode 100644
index 0000000000..dc80adfa65
--- /dev/null
+++ b/src/xvmc/tests/test_blocks.c
@@ -0,0 +1,84 @@
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+ const unsigned int width = 16, height = 16;
+ const unsigned int min_required_blocks = 1, min_required_macroblocks = 1;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+
+ Display *display;
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface;
+ XvMCBlockArray blocks = {0};
+ XvMCMacroBlockArray macroblocks = {0};
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ width,
+ height,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+
+ /* Test NULL context */
+ assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext);
+ /* Test 0 blocks */
+ assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue);
+ /* Test valid params */
+ assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success);
+ /* Test context id assigned and correct */
+ assert(blocks.context_id == context.context_id);
+ /* Test number of blocks assigned and correct */
+ assert(blocks.num_blocks == min_required_blocks);
+ /* Test block pointer valid */
+ assert(blocks.blocks != NULL);
+ /* Test NULL context */
+ assert(XvMCCreateMacroBlocks(display, NULL, 1, &macroblocks) == XvMCBadContext);
+ /* Test 0 macroblocks */
+ assert(XvMCCreateMacroBlocks(display, &context, 0, &macroblocks) == BadValue);
+ /* Test valid params */
+ assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, &macroblocks) == Success);
+ /* Test context id assigned and correct */
+ assert(macroblocks.context_id == context.context_id);
+ /* Test macroblock pointer valid */
+ assert(macroblocks.macro_blocks != NULL);
+ /* Test valid params */
+ assert(XvMCDestroyMacroBlocks(display, &macroblocks) == Success);
+ /* Test valid params */
+ assert(XvMCDestroyBlocks(display, &blocks) == Success);
+
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/xvmc/tests/test_context.c b/src/xvmc/tests/test_context.c
new file mode 100644
index 0000000000..53f7449cd0
--- /dev/null
+++ b/src/xvmc/tests/test_context.c
@@ -0,0 +1,92 @@
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+ const unsigned int width = 16, height = 16;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+
+ Display *display;
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context = {0};
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ width,
+ height,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ /* Test NULL context */
+ /* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext);
+ /* Test invalid port */
+ /* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */
+ assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort);
+ /* Test invalid surface */
+ assert(XvMCCreateContext(display, port_num, -1, width, height, XVMC_DIRECT, &context) == BadMatch);
+ /* Test invalid flags */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue);
+ /* Test huge width */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue);
+ /* Test huge height */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue);
+ /* Test huge width & height */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue);
+ /* Test valid params */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+ /* Test context id assigned */
+ assert(context.context_id != 0);
+ /* Test surface type id assigned and correct */
+ assert(context.surface_type_id == surface_type_id);
+ /* Test width & height assigned and correct */
+ assert(context.width == width && context.height == height);
+ /* Test port assigned and correct */
+ assert(context.port == port_num);
+ /* Test flags assigned and correct */
+ assert(context.flags == XVMC_DIRECT);
+ /* Test NULL context */
+ assert(XvMCDestroyContext(display, NULL) == XvMCBadContext);
+ /* Test valid params */
+ assert(XvMCDestroyContext(display, &context) == Success);
+ /* Test awkward but valid width */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success);
+ assert(context.width >= width + 1);
+ assert(XvMCDestroyContext(display, &context) == Success);
+ /* Test awkward but valid height */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success);
+ assert(context.height >= height + 1);
+ assert(XvMCDestroyContext(display, &context) == Success);
+ /* Test awkward but valid width & height */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success);
+ assert(context.width >= width + 1 && context.height >= height + 1);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/xvmc/tests/test_rendering.c b/src/xvmc/tests/test_rendering.c
new file mode 100644
index 0000000000..1e7467a3aa
--- /dev/null
+++ b/src/xvmc/tests/test_rendering.c
@@ -0,0 +1,287 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include "testlib.h"
+
+#define BLOCK_WIDTH 8
+#define BLOCK_HEIGHT 8
+#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT)
+#define MACROBLOCK_WIDTH 16
+#define MACROBLOCK_HEIGHT 16
+#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH)
+#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT)
+#define BLOCKS_PER_MACROBLOCK 6
+
+#define INPUT_WIDTH 16
+#define INPUT_HEIGHT 16
+#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH)
+#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT)
+#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS)
+
+#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH
+#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT
+#define DEFAULT_ACCEPTABLE_ERR 0.01
+
+void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt)
+{
+ int fail = 0;
+ int i;
+
+ *output_width = DEFAULT_OUTPUT_WIDTH;
+ *output_height = DEFAULT_OUTPUT_WIDTH;
+ *acceptable_error = DEFAULT_ACCEPTABLE_ERR;
+ *prompt = 1;
+
+ for (i = 1; i < argc && !fail; ++i)
+ {
+ if (!strcmp(argv[i], "-w"))
+ {
+ if (sscanf(argv[++i], "%u", output_width) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-h"))
+ {
+ if (sscanf(argv[++i], "%u", output_height) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-e"))
+ {
+ if (sscanf(argv[++i], "%lf", acceptable_error) != 1)
+ fail = 1;
+ }
+ else if (strcmp(argv[i], "-n"))
+ *prompt = 0;
+ else
+ fail = 1;
+ }
+
+ if (fail)
+ error
+ (
+ 1, 0,
+ "Bad argument.\n"
+ "\n"
+ "Usage: %s [options]\n"
+ "\t-w <width>\tOutput width\n"
+ "\t-h <height>\tOutput height\n"
+ "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
+ "\t-n\tDon't prompt for quit\n",
+ argv[0]
+ );
+}
+
+void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal)
+{
+ unsigned int x, y;
+ unsigned int range = stop - start;
+
+ if (horizontal)
+ {
+ for (y = 0; y < BLOCK_HEIGHT; ++y)
+ for (x = 0; x < BLOCK_WIDTH; ++x)
+ block[y * BLOCK_WIDTH + x] = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1)));
+ }
+ else
+ {
+ for (y = 0; y < BLOCK_HEIGHT; ++y)
+ for (x = 0; x < BLOCK_WIDTH; ++x)
+ block[y * BLOCK_WIDTH + x] = (short)(start + range * (y / (float)(BLOCK_HEIGHT - 1)));
+ }
+}
+
+int main(int argc, char **argv)
+{
+ unsigned int output_width;
+ unsigned int output_height;
+ double acceptable_error;
+ int prompt;
+ Display *display;
+ Window root, window;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface;
+ XvMCBlockArray block_array;
+ XvMCMacroBlockArray mb_array;
+ int mbx, mby, bx, by;
+ XvMCMacroBlock *mb;
+ short *blocks;
+ int quit = 0;
+
+ ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt);
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ INPUT_WIDTH,
+ INPUT_HEIGHT,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ root = XDefaultRootWindow(display);
+ window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey);
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success);
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+ assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
+ assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success);
+
+ mb = mb_array.macro_blocks;
+ blocks = block_array.blocks;
+
+ for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby)
+ for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx)
+ {
+ mb->x = mbx;
+ mb->y = mby;
+ mb->macroblock_type = XVMC_MB_TYPE_INTRA;
+ /*mb->motion_type = ;*/
+ /*mb->motion_vertical_field_select = ;*/
+ mb->dct_type = XVMC_DCT_TYPE_FRAME;
+ /*mb->PMV[0][0][0] = ;
+ mb->PMV[0][0][1] = ;
+ mb->PMV[0][1][0] = ;
+ mb->PMV[0][1][1] = ;
+ mb->PMV[1][0][0] = ;
+ mb->PMV[1][0][1] = ;
+ mb->PMV[1][1][0] = ;
+ mb->PMV[1][1][1] = ;*/
+ mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK;
+ mb->coded_block_pattern = 0x3F;
+
+ mb++;
+
+ for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by)
+ for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx)
+ {
+ const int start = 16, stop = 235, range = stop - start;
+
+ Gradient
+ (
+ blocks,
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+ 1
+ );
+
+ blocks += BLOCK_SIZE;
+ }
+
+ for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by)
+ for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx)
+ {
+ const int start = 16, stop = 240, range = stop - start;
+
+ Gradient
+ (
+ blocks,
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+ 1
+ );
+
+ blocks += BLOCK_SIZE;
+
+ Gradient
+ (
+ blocks,
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+ 1
+ );
+
+ blocks += BLOCK_SIZE;
+ }
+ }
+
+ XSelectInput(display, window, ExposureMask | KeyPressMask);
+ XMapWindow(display, window);
+ XSync(display, 0);
+
+ /* Test NULL context */
+ assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext);
+ /* Test NULL surface */
+ assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface);
+ /* Test bad picture structure */
+ assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue);
+ /* Test valid params */
+ assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success);
+
+ /* Test NULL surface */
+ assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
+ /* Test bad window */
+ /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
+ /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
+
+ if (prompt)
+ {
+ puts("Press any button to quit...");
+
+ while (!quit)
+ {
+ if (XPending(display) > 0)
+ {
+ XEvent event;
+
+ XNextEvent(display, &event);
+
+ switch (event.type)
+ {
+ case Expose:
+ {
+ /* Test valid params */
+ assert
+ (
+ XvMCPutSurface
+ (
+ display, &surface, window,
+ 0, 0, INPUT_WIDTH, INPUT_HEIGHT,
+ 0, 0, output_width, output_height,
+ XVMC_FRAME_PICTURE
+ ) == Success
+ );
+ break;
+ }
+ case KeyPress:
+ {
+ quit = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ assert(XvMCDestroyBlocks(display, &block_array) == Success);
+ assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XDestroyWindow(display, window);
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/xvmc/tests/test_surface.c b/src/xvmc/tests/test_surface.c
new file mode 100644
index 0000000000..25ebdcc4fc
--- /dev/null
+++ b/src/xvmc/tests/test_surface.c
@@ -0,0 +1,72 @@
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+ const unsigned int width = 16, height = 16;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+
+ Display *display;
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface = {0};
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ width,
+ height,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+
+ /* Test NULL context */
+ assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext);
+ /* Test NULL surface */
+ assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface);
+ /* Test valid params */
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+ /* Test surface id assigned */
+ assert(surface.surface_id != 0);
+ /* Test context id assigned and correct */
+ assert(surface.context_id == context.context_id);
+ /* Test surface type id assigned and correct */
+ assert(surface.surface_type_id == surface_type_id);
+ /* Test width & height assigned and correct */
+ assert(surface.width == width && surface.height == height);
+ /* Test valid params */
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ /* Test NULL surface */
+ assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface);
+
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XCloseDisplay(display);
+
+ return 0;
+}
+
diff --git a/src/xvmc/tests/testlib.c b/src/xvmc/tests/testlib.c
new file mode 100644
index 0000000000..59a03ca813
--- /dev/null
+++ b/src/xvmc/tests/testlib.c
@@ -0,0 +1,119 @@
+#include "testlib.h"
+#include <stdio.h>
+
+/*
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line)
+{
+ fputs(doc_string, stderr);
+ if (!pred)
+ fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line);
+ else
+ fputs(" PASS!\n", stderr);
+}
+*/
+
+int GetPort
+(
+ Display *display,
+ unsigned int width,
+ unsigned int height,
+ unsigned int chroma_format,
+ const unsigned int *mc_types,
+ unsigned int num_mc_types,
+ XvPortID *port_id,
+ int *surface_type_id,
+ unsigned int *is_overlay,
+ unsigned int *intra_unsigned
+)
+{
+ unsigned int found_port = 0;
+ XvAdaptorInfo *adaptor_info;
+ unsigned int num_adaptors;
+ int num_types;
+ int ev_base, err_base;
+ unsigned int i, j, k, l;
+
+ if (!XvMCQueryExtension(display, &ev_base, &err_base))
+ return 0;
+ if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success)
+ return 0;
+
+ for (i = 0; i < num_adaptors && !found_port; ++i)
+ {
+ if (adaptor_info[i].type & XvImageMask)
+ {
+ XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
+
+ if (surface_info)
+ {
+ for (j = 0; j < num_types && !found_port; ++j)
+ {
+ if
+ (
+ surface_info[j].chroma_format == chroma_format &&
+ surface_info[j].max_width >= width &&
+ surface_info[j].max_height >= height
+ )
+ {
+ for (k = 0; k < num_mc_types && !found_port; ++k)
+ {
+ if (surface_info[j].mc_type == mc_types[k])
+ {
+ for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l)
+ {
+ if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success)
+ {
+ *port_id = adaptor_info[i].base_id + l;
+ *surface_type_id = surface_info[j].surface_type_id;
+ *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE;
+ *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED;
+ found_port = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ XFree(surface_info);
+ }
+ }
+ }
+
+ XvFreeAdaptorInfo(adaptor_info);
+
+ return found_port;
+}
+
+unsigned int align(unsigned int value, unsigned int alignment)
+{
+ return (value + alignment - 1) & ~(alignment - 1);
+}
+
+/* From the glibc manual */
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
+{
+ /* Perform the carry for the later subtraction by updating y. */
+ if (x->tv_usec < y->tv_usec)
+ {
+ int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+ y->tv_usec -= 1000000 * nsec;
+ y->tv_sec += nsec;
+ }
+ if (x->tv_usec - y->tv_usec > 1000000)
+ {
+ int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+ y->tv_usec += 1000000 * nsec;
+ y->tv_sec -= nsec;
+ }
+
+ /*
+ * Compute the time remaining to wait.
+ * tv_usec is certainly positive.
+ */
+ result->tv_sec = x->tv_sec - y->tv_sec;
+ result->tv_usec = x->tv_usec - y->tv_usec;
+
+ /* Return 1 if result is negative. */
+ return x->tv_sec < y->tv_sec;
+}
diff --git a/src/xvmc/tests/testlib.h b/src/xvmc/tests/testlib.h
new file mode 100644
index 0000000000..af71ad74e1
--- /dev/null
+++ b/src/xvmc/tests/testlib.h
@@ -0,0 +1,42 @@
+#ifndef testlib_h
+#define testlib_h
+
+/*
+#define TEST(pred, doc) test(pred, #pred, doc, __FILE__, __LINE__)
+
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line);
+*/
+
+#include <sys/time.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+
+/*
+ * display: IN A valid X display
+ * width, height: IN Surface size that the port must display
+ * chroma_format: IN Chroma format that the port must display
+ * mc_types, num_mc_types: IN List of MC types that the port must support, first port that matches the first mc_type will be returned
+ * port_id: OUT Your port's ID
+ * surface_type_id: OUT Your port's surface ID
+ * is_overlay: OUT If 1, port uses overlay surfaces, you need to set a colorkey
+ * intra_unsigned: OUT If 1, port uses unsigned values for intra-coded blocks
+ */
+int GetPort
+(
+ Display *display,
+ unsigned int width,
+ unsigned int height,
+ unsigned int chroma_format,
+ const unsigned int *mc_types,
+ unsigned int num_mc_types,
+ XvPortID *port_id,
+ int *surface_type_id,
+ unsigned int *is_overlay,
+ unsigned int *intra_unsigned
+);
+
+unsigned int align(unsigned int value, unsigned int alignment);
+
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y);
+
+#endif
diff --git a/src/xvmc/tests/xvmc_bench.c b/src/xvmc/tests/xvmc_bench.c
new file mode 100644
index 0000000000..d5a39ecf17
--- /dev/null
+++ b/src/xvmc/tests/xvmc_bench.c
@@ -0,0 +1,271 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include <sys/time.h>
+#include "testlib.h"
+
+#define MACROBLOCK_WIDTH 16
+#define MACROBLOCK_HEIGHT 16
+#define BLOCKS_PER_MACROBLOCK 6
+
+#define DEFAULT_INPUT_WIDTH 720
+#define DEFAULT_INPUT_HEIGHT 480
+#define DEFAULT_REPS 100
+
+#define PIPELINE_STEP_MC 1
+#define PIPELINE_STEP_CSC 2
+#define PIPELINE_STEP_SWAP 4
+
+#define MB_TYPE_I 1
+#define MB_TYPE_P 2
+#define MB_TYPE_B 4
+
+struct Config
+{
+ unsigned int input_width;
+ unsigned int input_height;
+ unsigned int output_width;
+ unsigned int output_height;
+ unsigned int pipeline;
+ unsigned int mb_types;
+ unsigned int reps;
+};
+
+void ParseArgs(int argc, char **argv, struct Config *config)
+{
+ int fail = 0;
+ int i;
+
+ config->input_width = DEFAULT_INPUT_WIDTH;
+ config->input_height = DEFAULT_INPUT_HEIGHT;
+ config->output_width = 0;
+ config->output_height = 0;
+ config->pipeline = 0;
+ config->mb_types = 0;
+ config->reps = DEFAULT_REPS;
+
+ for (i = 1; i < argc && !fail; ++i)
+ {
+ if (!strcmp(argv[i], "-iw"))
+ {
+ if (sscanf(argv[++i], "%u", &config->input_width) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-ih"))
+ {
+ if (sscanf(argv[++i], "%u", &config->input_height) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-ow"))
+ {
+ if (sscanf(argv[++i], "%u", &config->output_width) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-oh"))
+ {
+ if (sscanf(argv[++i], "%u", &config->output_height) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-p"))
+ {
+ char *token = strtok(argv[++i], ",");
+
+ while (token && !fail)
+ {
+ if (!strcmp(token, "mc"))
+ config->pipeline |= PIPELINE_STEP_MC;
+ else if (!strcmp(token, "csc"))
+ config->pipeline |= PIPELINE_STEP_CSC;
+ else if (!strcmp(token, "swp"))
+ config->pipeline |= PIPELINE_STEP_SWAP;
+ else
+ fail = 1;
+
+ if (!fail)
+ token = strtok(NULL, ",");
+ }
+ }
+ else if (!strcmp(argv[i], "-mb"))
+ {
+ char *token = strtok(argv[++i], ",");
+
+ while (token && !fail)
+ {
+ if (strcmp(token, "i"))
+ config->mb_types |= MB_TYPE_I;
+ else if (strcmp(token, "p"))
+ config->mb_types |= MB_TYPE_P;
+ else if (strcmp(token, "b"))
+ config->mb_types |= MB_TYPE_B;
+ else
+ fail = 1;
+
+ if (!fail)
+ token = strtok(NULL, ",");
+ }
+ }
+ else if (!strcmp(argv[i], "-r"))
+ {
+ if (sscanf(argv[++i], "%u", &config->reps) != 1)
+ fail = 1;
+ }
+ else
+ fail = 1;
+ }
+
+ if (fail)
+ error
+ (
+ 1, 0,
+ "Bad argument.\n"
+ "\n"
+ "Usage: %s [options]\n"
+ "\t-iw <width>\tInput width\n"
+ "\t-ih <height>\tInput height\n"
+ "\t-ow <width>\tOutput width\n"
+ "\t-oh <height>\tOutput height\n"
+ "\t-p <pipeline>\tPipeline to test\n"
+ "\t-mb <mb type>\tMacroBlock types to use\n"
+ "\t-r <reps>\tRepetitions\n\n"
+ "\tPipeline steps: mc,csc,swap\n"
+ "\tMB types: i,p,b\n",
+ argv[0]
+ );
+
+ if (config->output_width == 0)
+ config->output_width = config->input_width;
+ if (config->output_height == 0)
+ config->output_height = config->input_height;
+ if (!config->pipeline)
+ config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP;
+ if (!config->mb_types)
+ config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B;
+}
+
+int main(int argc, char **argv)
+{
+ struct Config config;
+ Display *display;
+ Window root, window;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface;
+ XvMCBlockArray block_array;
+ XvMCMacroBlockArray mb_array;
+ unsigned int mbw, mbh;
+ unsigned int mbx, mby;
+ unsigned int reps;
+ struct timeval start, stop, diff;
+ double diff_secs;
+
+ ParseArgs(argc, argv, &config);
+
+ mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
+ mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ config.input_width,
+ config.input_height,
+ XVMC_CHROMA_FORMAT_420,
+ mc_types,
+ 2,
+ &port_num,
+ &surface_type_id,
+ &is_overlay,
+ &intra_unsigned
+ ))
+ {
+ XCloseDisplay(display);
+ error(1, 0, "Error, unable to find a good port.\n");
+ }
+
+ if (is_overlay)
+ {
+ Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+ XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+ }
+
+ root = XDefaultRootWindow(display);
+ window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey);
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success);
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+ assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
+ assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success);
+
+ for (mby = 0; mby < mbh; ++mby)
+ for (mbx = 0; mbx < mbw; ++mbx)
+ {
+ mb_array.macro_blocks[mby * mbw + mbx].x = mbx;
+ mb_array.macro_blocks[mby * mbw + mbx].y = mby;
+ mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA;
+ /*mb->motion_type = ;*/
+ /*mb->motion_vertical_field_select = ;*/
+ mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME;
+ /*mb->PMV[0][0][0] = ;
+ mb->PMV[0][0][1] = ;
+ mb->PMV[0][1][0] = ;
+ mb->PMV[0][1][1] = ;
+ mb->PMV[1][0][0] = ;
+ mb->PMV[1][0][1] = ;
+ mb->PMV[1][1][0] = ;
+ mb->PMV[1][1][1] = ;*/
+ mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK;
+ mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F;
+ }
+
+ XSelectInput(display, window, ExposureMask | KeyPressMask);
+ XMapWindow(display, window);
+ XSync(display, 0);
+
+ gettimeofday(&start, NULL);
+
+ for (reps = 0; reps < config.reps; ++reps)
+ {
+ if (config.pipeline & PIPELINE_STEP_MC)
+ {
+ assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success);
+ assert(XvMCFlushSurface(display, &surface) == Success);
+ }
+ if (config.pipeline & PIPELINE_STEP_CSC)
+ assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success);
+ }
+
+ gettimeofday(&stop, NULL);
+
+ timeval_subtract(&diff, &stop, &start);
+ diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0;
+
+ printf("XvMC Benchmark\n");
+ printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height);
+ printf("Pipeline: ");
+ if (config.pipeline & PIPELINE_STEP_MC)
+ printf("|mc|");
+ if (config.pipeline & PIPELINE_STEP_CSC)
+ printf("|csc|");
+ if (config.pipeline & PIPELINE_STEP_SWAP)
+ printf("|swap|");
+ printf("\n");
+ printf("Reps: %u\n", config.reps);
+ printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs);
+
+ assert(XvMCDestroyBlocks(display, &block_array) == Success);
+ assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XDestroyWindow(display, window);
+ XCloseDisplay(display);
+
+ return 0;
+}